summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/.prev_CMakeLists.txt1066
-rw-r--r--src/corelib/CMakeLists.txt1335
-rw-r--r--src/corelib/Qt5AndroidSupport.cmake202
-rw-r--r--src/corelib/Qt5CoreMacros.cmake507
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake1513
-rw-r--r--src/corelib/Qt6CTestMacros.cmake763
-rw-r--r--src/corelib/Qt6Config.cmake.in51
-rw-r--r--src/corelib/Qt6CoreConfigExtras.cmake.in84
-rw-r--r--src/corelib/Qt6CoreConfigExtrasMkspecDir.cmake.in6
-rw-r--r--src/corelib/Qt6CoreConfigExtrasMkspecDirForInstall.cmake.in6
-rw-r--r--src/corelib/Qt6CoreConfigureFileTemplate.in1
-rw-r--r--src/corelib/Qt6CoreDeploySupport.cmake680
-rw-r--r--src/corelib/Qt6CoreMacros.cmake3229
-rw-r--r--src/corelib/Qt6CoreResourceInit.in.cpp14
-rw-r--r--src/corelib/Qt6ModuleLocation.cmake.in15
-rw-r--r--src/corelib/Qt6ModuleLocationForInstall.cmake.in6
-rw-r--r--src/corelib/Qt6WasmMacros.cmake140
-rw-r--r--src/corelib/QtCompressMimeDatabase.cmake156
-rw-r--r--src/corelib/QtCore.dynlist2
-rw-r--r--src/corelib/animation/animation.pri25
-rw-r--r--src/corelib/animation/qabstractanimation.cpp293
-rw-r--r--src/corelib/animation/qabstractanimation.h68
-rw-r--r--src/corelib/animation/qabstractanimation_p.h128
-rw-r--r--src/corelib/animation/qanimationgroup.cpp50
-rw-r--r--src/corelib/animation/qanimationgroup.h40
-rw-r--r--src/corelib/animation/qanimationgroup_p.h44
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp42
-rw-r--r--src/corelib/animation/qparallelanimationgroup.h40
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h42
-rw-r--r--src/corelib/animation/qpauseanimation.cpp59
-rw-r--r--src/corelib/animation/qpauseanimation.h43
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp148
-rw-r--r--src/corelib/animation/qpropertyanimation.h48
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h66
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp69
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.h44
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h55
-rw-r--r--src/corelib/animation/qvariantanimation.cpp115
-rw-r--r--src/corelib/animation/qvariantanimation.h49
-rw-r--r--src/corelib/animation/qvariantanimation_p.h51
-rw-r--r--src/corelib/compat/removed_api.cpp1124
-rw-r--r--src/corelib/configure.cmake569
-rw-r--r--src/corelib/configure.json1098
-rw-r--r--src/corelib/corelib.pro164
-rw-r--r--src/corelib/debug_script.py77
-rw-r--r--src/corelib/doc/images/resources.pngbin49998 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-button-history.pngbin8493 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-button-nested.pngbin7051 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-button.pngbin4233 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-customevents.pngbin2544 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-customevents2.pngbin6713 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-examples.pngbin3326 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-finished.pngbin5518 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-nonparallel.pngbin5350 -> 0 bytes
-rw-r--r--src/corelib/doc/images/statemachine-parallel.pngbin8631 -> 0 bytes
-rw-r--r--src/corelib/doc/include/QtCoreDoc4
-rw-r--r--src/corelib/doc/include/jni.h29
-rw-r--r--src/corelib/doc/qtcore.qdocconf32
-rw-r--r--src/corelib/doc/snippets/buffer/buffer.cpp51
-rw-r--r--src/corelib/doc/snippets/cmake-macros/deployment.cmake27
-rw-r--r--src/corelib/doc/snippets/cmake-macros/examples.cmake115
-rw-r--r--src/corelib/doc/snippets/cmake-macros/examples.cpp16
-rw-r--r--src/corelib/doc/snippets/code/doc_src_containers.cpp168
-rw-r--r--src/corelib/doc/snippets/code/doc_src_groups.cpp51
-rw-r--r--src/corelib/doc/snippets/code/doc_src_objecttrees.cpp51
-rw-r--r--src/corelib/doc/snippets/code/doc_src_properties.cpp63
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp359
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qcache.cpp51
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qiterator.cpp160
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qnamespace.cpp51
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qnamespace.qdoc51
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qplugin.cpp57
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qplugin.pro4
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qset.cpp103
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp51
-rw-r--r--src/corelib/doc/snippets/code/doc_src_resources.cpp64
-rw-r--r--src/corelib/doc/snippets/code/doc_src_resources.qdoc55
-rw-r--r--src/corelib/doc/snippets/code/qlogging/qlogging.cpp61
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp144
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp146
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp55
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp98
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdatastream.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdir.cpp68
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdiriterator.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp70
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qfile.cpp61
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qfileinfo.cpp135
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qiodevice.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp91
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qsettings.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qstorageinfo.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qtemporarydir.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp57
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp61
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp106
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter_win.cpp20
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qcoreapplication.cpp61
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp65
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmath.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp84
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp76
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp111
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qproperty.cpp152
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp55
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qtimer.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp72
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp55
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_plugin_qlibrary.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp81
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_statemachine_qstatemachine.cpp65
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qanystringview.cpp12
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp104
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qbytearraymatcher.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp34
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qcollator.cpp11
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp103
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qregexp.cpp243
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qregularexpression.cpp82
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qstaticlatin1stringmatcher.cpp8
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp82
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qstringconverter.cpp77
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qstringiterator.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qstringview.cpp55
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qutf8stringview.cpp7
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qatomic.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp67
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp298
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qfuturesynchronizer.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qfuturewatcher.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qmutex.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qmutexpool.cpp71
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qreadwritelock.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp57
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp87
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qbitarray.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp177
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp90
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp210
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qmultimap.cpp256
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qpoint.cpp55
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qscopedpointer.cpp53
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qsize.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qtimeline.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_xml_qxmlstream.cpp51
-rw-r--r--src/corelib/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp158
-rw-r--r--src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp51
-rw-r--r--src/corelib/doc/snippets/customtype/customtypeexample.cpp90
-rw-r--r--src/corelib/doc/snippets/eventfilters/filterobject.cpp51
-rw-r--r--src/corelib/doc/snippets/eventfilters/filterobject.h53
-rw-r--r--src/corelib/doc/snippets/eventfilters/main.cpp51
-rw-r--r--src/corelib/doc/snippets/events/events.cpp51
-rw-r--r--src/corelib/doc/snippets/file/file.cpp51
-rw-r--r--src/corelib/doc/snippets/fileinfo/main.cpp59
-rw-r--r--src/corelib/doc/snippets/hellotrmain.cpp55
-rw-r--r--src/corelib/doc/snippets/jni/src_qjniobject.cpp63
-rw-r--r--src/corelib/doc/snippets/ntfsp.cpp66
-rw-r--r--src/corelib/doc/snippets/overview/using-qt-core.cmake4
-rw-r--r--src/corelib/doc/snippets/pointer/pointer.cpp51
-rw-r--r--src/corelib/doc/snippets/process/process.cpp51
-rw-r--r--src/corelib/doc/snippets/qbytearraylist/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qbytearraylist/qbytearraylist.pro2
-rw-r--r--src/corelib/doc/snippets/qdebug/qdebugsnippet.cpp51
-rw-r--r--src/corelib/doc/snippets/qdir-listfiles/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qdir-namefilters/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qelapsedtimer/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qloggingcategory/main.cpp80
-rw-r--r--src/corelib/doc/snippets/qmessageauthenticationcode/main.cpp59
-rw-r--r--src/corelib/doc/snippets/qmetaobject-invokable/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qmetaobject-invokable/qmetaobject-invokable.pro3
-rw-r--r--src/corelib/doc/snippets/qmetaobject-invokable/window.cpp51
-rw-r--r--src/corelib/doc/snippets/qmetaobject-invokable/window.h51
-rw-r--r--src/corelib/doc/snippets/qmetaobject-revision/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qmetaobject-revision/qmetaobject-revision.pro4
-rw-r--r--src/corelib/doc/snippets/qmetaobject-revision/window.cpp51
-rw-r--r--src/corelib/doc/snippets/qmetaobject-revision/window.h51
-rw-r--r--src/corelib/doc/snippets/qmetatype/registerConverters.cpp62
-rw-r--r--src/corelib/doc/snippets/qprocess-environment/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qprocess/qprocess-createprocessargumentsmodifier.cpp51
-rw-r--r--src/corelib/doc/snippets/qprocess/qprocess-simpleexecution.cpp51
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp60
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.h52
-rw-r--r--src/corelib/doc/snippets/qsortfilterproxymodel-details/main.cpp55
-rw-r--r--src/corelib/doc/snippets/qstack/main.cpp51
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp121
-rw-r--r--src/corelib/doc/snippets/qstring/stringbuilder.cpp86
-rw-r--r--src/corelib/doc/snippets/qstringlist/main.cpp80
-rw-r--r--src/corelib/doc/snippets/qstringlistmodel/main.cpp53
-rw-r--r--src/corelib/doc/snippets/qtcast/qtcast.cpp51
-rw-r--r--src/corelib/doc/snippets/qversionnumber/main.cpp59
-rw-r--r--src/corelib/doc/snippets/qxmlstreamwriter/main.cpp51
-rw-r--r--src/corelib/doc/snippets/resource-system/CMakeLists.txt41
-rw-r--r--src/corelib/doc/snippets/resource-system/application.pro38
-rw-r--r--src/corelib/doc/snippets/resource-system/application.qrc18
-rw-r--r--src/corelib/doc/snippets/resource-system/images/copy.pngbin0 -> 67 bytes
-rw-r--r--src/corelib/doc/snippets/resource-system/images/cut.pngbin0 -> 67 bytes
-rw-r--r--src/corelib/doc/snippets/resource-system/images/new.pngbin0 -> 67 bytes
-rw-r--r--src/corelib/doc/snippets/resource-system/images/open.pngbin0 -> 67 bytes
-rw-r--r--src/corelib/doc/snippets/resource-system/images/paste.pngbin0 -> 67 bytes
-rw-r--r--src/corelib/doc/snippets/resource-system/images/save.pngbin0 -> 67 bytes
-rw-r--r--src/corelib/doc/snippets/resource-system/main.cpp28
-rw-r--r--src/corelib/doc/snippets/resource-system/mainwindow.cpp125
-rw-r--r--src/corelib/doc/snippets/settings/settings.cpp61
-rw-r--r--src/corelib/doc/snippets/sharedemployee/employee.h51
-rw-r--r--src/corelib/doc/snippets/sharedemployee/main.cpp51
-rw-r--r--src/corelib/doc/snippets/signalsandslots/lcdnumber.h51
-rw-r--r--src/corelib/doc/snippets/signalsandslots/signalsandslots.cpp51
-rw-r--r--src/corelib/doc/snippets/signalsandslots/signalsandslots.h51
-rw-r--r--src/corelib/doc/snippets/statemachine/eventtest.cpp83
-rw-r--r--src/corelib/doc/snippets/statemachine/main.cpp98
-rw-r--r--src/corelib/doc/snippets/statemachine/main2.cpp103
-rw-r--r--src/corelib/doc/snippets/statemachine/main3.cpp70
-rw-r--r--src/corelib/doc/snippets/statemachine/main4.cpp122
-rw-r--r--src/corelib/doc/snippets/statemachine/main5.cpp182
-rw-r--r--src/corelib/doc/snippets/streaming/main.cpp51
-rw-r--r--src/corelib/doc/snippets/streaming/streaming.pro2
-rw-r--r--src/corelib/doc/snippets/threads/threads.cpp57
-rw-r--r--src/corelib/doc/snippets/timers/analogclock.cpp97
-rw-r--r--src/corelib/doc/snippets/timers/timers.cpp95
-rw-r--r--src/corelib/doc/src/animation.qdoc414
-rw-r--r--src/corelib/doc/src/cbor.qdoc79
-rw-r--r--src/corelib/doc/src/cmake-macros.qdoc416
-rw-r--r--src/corelib/doc/src/cmake/cmake-commands.qdoc17
-rw-r--r--src/corelib/doc/src/cmake/cmake-configure-variables.qdoc587
-rw-r--r--src/corelib/doc/src/cmake/cmake-deploy-variables.qdoc307
-rw-r--r--src/corelib/doc/src/cmake/cmake-properties.qdoc637
-rw-r--r--src/corelib/doc/src/cmake/cmake-standard-properties.qdoc24
-rw-r--r--src/corelib/doc/src/cmake/policy/qtp0002.qdoc63
-rw-r--r--src/corelib/doc/src/cmake/policy/qtp0003.qdoc46
-rw-r--r--src/corelib/doc/src/cmake/qt_add_big_resources.qdoc53
-rw-r--r--src/corelib/doc/src/cmake/qt_add_binary_resources.qdoc43
-rw-r--r--src/corelib/doc/src/cmake/qt_add_executable.qdoc114
-rw-r--r--src/corelib/doc/src/cmake/qt_add_library.qdoc80
-rw-r--r--src/corelib/doc/src/cmake/qt_add_plugin.qdoc87
-rw-r--r--src/corelib/doc/src/cmake/qt_add_resources.qdoc110
-rw-r--r--src/corelib/doc/src/cmake/qt_allow_non_utf8_sources.qdoc34
-rw-r--r--src/corelib/doc/src/cmake/qt_android_add_apk_target.qdoc55
-rw-r--r--src/corelib/doc/src/cmake/qt_android_apply_arch_suffix.qdoc36
-rw-r--r--src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc82
-rw-r--r--src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc78
-rw-r--r--src/corelib/doc/src/cmake/qt_deploy_runtime_dependencies.qdoc198
-rw-r--r--src/corelib/doc/src/cmake/qt_deploy_translations.qdoc76
-rw-r--r--src/corelib/doc/src/cmake/qt_disable_unicode_defines.qdoc34
-rw-r--r--src/corelib/doc/src/cmake/qt_extract_metatypes.qdoc69
-rw-r--r--src/corelib/doc/src/cmake/qt_finalize_project.qdoc53
-rw-r--r--src/corelib/doc/src/cmake/qt_finalize_target.qdoc89
-rw-r--r--src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc110
-rw-r--r--src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc65
-rw-r--r--src/corelib/doc/src/cmake/qt_generate_moc.qdoc45
-rw-r--r--src/corelib/doc/src/cmake/qt_import_plugins.qdoc97
-rw-r--r--src/corelib/doc/src/cmake/qt_policy.qdoc65
-rw-r--r--src/corelib/doc/src/cmake/qt_set_finalizer_mode.qdoc90
-rw-r--r--src/corelib/doc/src/cmake/qt_standard_project_setup.qdoc101
-rw-r--r--src/corelib/doc/src/cmake/qt_wrap_cpp.qdoc90
-rw-r--r--src/corelib/doc/src/containers.qdoc406
-rw-r--r--src/corelib/doc/src/custom-types.qdoc59
-rw-r--r--src/corelib/doc/src/datastreamformat.qdoc78
-rw-r--r--src/corelib/doc/src/dontdocument.qdoc28
-rw-r--r--src/corelib/doc/src/eventsandfilters.qdoc28
-rw-r--r--src/corelib/doc/src/external-resources.qdoc172
-rw-r--r--src/corelib/doc/src/filestorage.qdoc28
-rw-r--r--src/corelib/doc/src/foreach-keyword.qdoc90
-rw-r--r--src/corelib/doc/src/implicit-sharing.qdoc28
-rw-r--r--src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc13
-rw-r--r--src/corelib/doc/src/includes/cmake-android-qt-finalize-project-warning.qdocinc8
-rw-r--r--src/corelib/doc/src/includes/cmake-android-supported-abis.qdocinc1
-rw-r--r--src/corelib/doc/src/includes/cmake-deploy-modified-variable-values.qdocinc30
-rw-r--r--src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies-deploy-tool-options.qdocinc20
-rw-r--r--src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc46
-rw-r--r--src/corelib/doc/src/includes/cmake-deploy-var-usage.qdocinc6
-rw-r--r--src/corelib/doc/src/includes/cmake-find-package-core.qdocinc6
-rw-r--r--src/corelib/doc/src/includes/cmake-generate-deploy-app-script-deploy-tool-options.qdocinc16
-rw-r--r--src/corelib/doc/src/includes/cmake-generate-deploy-app-script.qdocinc21
-rw-r--r--src/corelib/doc/src/includes/models.qdocinc14
-rw-r--r--src/corelib/doc/src/includes/permissions.qdocinc51
-rw-r--r--src/corelib/doc/src/includes/qfile-copy.qdocinc11
-rw-r--r--src/corelib/doc/src/includes/qobject.qdocinc10
-rw-r--r--src/corelib/doc/src/includes/qstring.qdocinc36
-rw-r--r--src/corelib/doc/src/includes/qt_add_big_resources.qdocinc44
-rw-r--r--src/corelib/doc/src/includes/qt_add_binary_resources.qdocinc39
-rw-r--r--src/corelib/doc/src/includes/qt_add_resources.qdocinc40
-rw-r--r--src/corelib/doc/src/includes/qt_generate_moc.qdocinc42
-rw-r--r--src/corelib/doc/src/includes/qt_import_plugins.qdocinc58
-rw-r--r--src/corelib/doc/src/includes/qt_wrap_cpp.qdocinc49
-rw-r--r--src/corelib/doc/src/io.qdoc30
-rw-r--r--src/corelib/doc/src/ipc.qdoc492
-rw-r--r--src/corelib/doc/src/java-style-iterators.qdoc174
-rw-r--r--src/corelib/doc/src/json.qdoc40
-rw-r--r--src/corelib/doc/src/objectmodel/bindableproperties.qdoc264
-rw-r--r--src/corelib/doc/src/objectmodel/metaobjects.qdoc32
-rw-r--r--src/corelib/doc/src/objectmodel/object.qdoc28
-rw-r--r--src/corelib/doc/src/objectmodel/objecttrees.qdoc28
-rw-r--r--src/corelib/doc/src/objectmodel/properties.qdoc81
-rw-r--r--src/corelib/doc/src/objectmodel/signalsandslots.qdoc61
-rw-r--r--src/corelib/doc/src/plugin-classes.qdoc28
-rw-r--r--src/corelib/doc/src/qt6-changes.qdoc606
-rw-r--r--src/corelib/doc/src/qtcore-index.qdoc96
-rw-r--r--src/corelib/doc/src/qtcore.qdoc48
-rw-r--r--src/corelib/doc/src/qtserialization.qdoc145
-rw-r--r--src/corelib/doc/src/resource-system.qdoc389
-rw-r--r--src/corelib/doc/src/statemachine.qdoc577
-rw-r--r--src/corelib/doc/src/timers.qdoc140
-rw-r--r--src/corelib/global/archdetect.cpp52
-rw-r--r--src/corelib/global/global.pri133
-rw-r--r--src/corelib/global/minimum-linux.S81
-rw-r--r--src/corelib/global/minimum-linux_p.h76
-rw-r--r--src/corelib/global/q20algorithm.h191
-rw-r--r--src/corelib/global/q20chrono.h62
-rw-r--r--src/corelib/global/q20functional.h46
-rw-r--r--src/corelib/global/q20iterator.h54
-rw-r--r--src/corelib/global/q20map.h72
-rw-r--r--src/corelib/global/q20memory.h93
-rw-r--r--src/corelib/global/q20type_traits.h81
-rw-r--r--src/corelib/global/q20vector.h90
-rw-r--r--src/corelib/global/q23functional.h49
-rw-r--r--src/corelib/global/q23utility.cpp25
-rw-r--r--src/corelib/global/q23utility.h75
-rw-r--r--src/corelib/global/qassert.cpp277
-rw-r--r--src/corelib/global/qassert.h116
-rw-r--r--src/corelib/global/qcompare.cpp1357
-rw-r--r--src/corelib/global/qcompare.h891
-rw-r--r--src/corelib/global/qcompare_impl.h34
-rw-r--r--src/corelib/global/qcomparehelpers.h567
-rw-r--r--src/corelib/global/qcompilerdetection.h789
-rw-r--r--src/corelib/global/qcompilerdetection.qdoc427
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h80
-rw-r--r--src/corelib/global/qconfig.cpp.in49
-rw-r--r--src/corelib/global/qconstructormacros.h38
-rw-r--r--src/corelib/global/qcontainerinfo.h229
-rw-r--r--src/corelib/global/qdarwinhelpers.h37
-rw-r--r--src/corelib/global/qdarwinhelpers.qdoc34
-rw-r--r--src/corelib/global/qendian.cpp76
-rw-r--r--src/corelib/global/qendian.h135
-rw-r--r--src/corelib/global/qendian_p.h273
-rw-r--r--src/corelib/global/qexceptionhandling.cpp20
-rw-r--r--src/corelib/global/qexceptionhandling.h46
-rw-r--r--src/corelib/global/qflags.h284
-rw-r--r--src/corelib/global/qflags.qdoc459
-rw-r--r--src/corelib/global/qfloat16.cpp304
-rw-r--r--src/corelib/global/qfloat16.h518
-rw-r--r--src/corelib/global/qfloat16_f16c.c91
-rw-r--r--src/corelib/global/qfloat16tables.cpp566
-rw-r--r--src/corelib/global/qforeach.h84
-rw-r--r--src/corelib/global/qforeach.qdoc72
-rw-r--r--src/corelib/global/qfunctionpointer.h23
-rw-r--r--src/corelib/global/qfunctionpointer.qdoc9
-rw-r--r--src/corelib/global/qglobal.cpp4789
-rw-r--r--src/corelib/global/qglobal.h1308
-rw-r--r--src/corelib/global/qglobal_p.h77
-rw-r--r--src/corelib/global/qglobalstatic.h219
-rw-r--r--src/corelib/global/qglobalstatic.qdoc149
-rw-r--r--src/corelib/global/qhooks.cpp42
-rw-r--r--src/corelib/global/qhooks_p.h40
-rw-r--r--src/corelib/global/qisenum.h51
-rw-r--r--src/corelib/global/qlibraryinfo.cpp776
-rw-r--r--src/corelib/global/qlibraryinfo.h87
-rw-r--r--src/corelib/global/qlibraryinfo_p.h57
-rw-r--r--src/corelib/global/qlogging.cpp1453
-rw-r--r--src/corelib/global/qlogging.h116
-rw-r--r--src/corelib/global/qlogging_p.h90
-rw-r--r--src/corelib/global/qmalloc.cpp71
-rw-r--r--src/corelib/global/qmalloc.h26
-rw-r--r--src/corelib/global/qmemory_p.h71
-rw-r--r--src/corelib/global/qminmax.h88
-rw-r--r--src/corelib/global/qminmax.qdoc39
-rw-r--r--src/corelib/global/qnamespace.h532
-rw-r--r--src/corelib/global/qnamespace.qdoc772
-rw-r--r--src/corelib/global/qnativeinterface.h148
-rw-r--r--src/corelib/global/qnativeinterface_p.h63
-rw-r--r--src/corelib/global/qnumeric.cpp345
-rw-r--r--src/corelib/global/qnumeric.h415
-rw-r--r--src/corelib/global/qnumeric_p.h474
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp338
-rw-r--r--src/corelib/global/qoperatingsystemversion.h324
-rw-r--r--src/corelib/global/qoperatingsystemversion_darwin.mm91
-rw-r--r--src/corelib/global/qoperatingsystemversion_p.h41
-rw-r--r--src/corelib/global/qoperatingsystemversion_win.cpp72
-rw-r--r--src/corelib/global/qoperatingsystemversion_win_p.h42
-rw-r--r--src/corelib/global/qoverload.h80
-rw-r--r--src/corelib/global/qoverload.qdoc43
-rw-r--r--src/corelib/global/qprocessordetection.h97
-rw-r--r--src/corelib/global/qprocessordetection.qdoc448
-rw-r--r--src/corelib/global/qrandom.cpp379
-rw-r--r--src/corelib/global/qrandom.h134
-rw-r--r--src/corelib/global/qrandom_p.h50
-rw-r--r--src/corelib/global/qsimd.cpp421
-rw-r--r--src/corelib/global/qsimd.h62
-rw-r--r--src/corelib/global/qsimd_p.h410
-rw-r--r--src/corelib/global/qsimd_x86.cpp291
-rw-r--r--src/corelib/global/qsimd_x86_p.h616
-rw-r--r--src/corelib/global/qswap.h38
-rw-r--r--src/corelib/global/qswap.qdoc38
-rw-r--r--src/corelib/global/qsysinfo.cpp1072
-rw-r--r--src/corelib/global/qsysinfo.h214
-rw-r--r--src/corelib/global/qsystemdetection.h215
-rw-r--r--src/corelib/global/qsystemdetection.qdoc219
-rw-r--r--src/corelib/global/qt_pch.h62
-rw-r--r--src/corelib/global/qt_windows.h69
-rw-r--r--src/corelib/global/qtclasshelpermacros.h132
-rw-r--r--src/corelib/global/qtclasshelpermacros.qdoc59
-rw-r--r--src/corelib/global/qtconfiginclude.h22
-rw-r--r--src/corelib/global/qtconfigmacros.h209
-rw-r--r--src/corelib/global/qtdeprecationmarkers.h347
-rw-r--r--src/corelib/global/qtdeprecationmarkers.qdoc64
-rw-r--r--src/corelib/global/qtenvironmentvariables.cpp429
-rw-r--r--src/corelib/global/qtenvironmentvariables.h38
-rw-r--r--src/corelib/global/qtenvironmentvariables_p.h39
-rw-r--r--src/corelib/global/qtnoop.h20
-rw-r--r--src/corelib/global/qtpreprocessorsupport.h26
-rw-r--r--src/corelib/global/qtpreprocessorsupport.qdoc20
-rw-r--r--src/corelib/global/qtrace_p.h173
-rw-r--r--src/corelib/global/qtresource.h21
-rw-r--r--src/corelib/global/qtresource.qdoc54
-rw-r--r--src/corelib/global/qtsymbolmacros.h65
-rw-r--r--src/corelib/global/qttranslation.h44
-rw-r--r--src/corelib/global/qttranslation.qdoc206
-rw-r--r--src/corelib/global/qttypetraits.h65
-rw-r--r--src/corelib/global/qttypetraits.qdoc146
-rw-r--r--src/corelib/global/qtversion.h38
-rw-r--r--src/corelib/global/qtversionchecks.cpp46
-rw-r--r--src/corelib/global/qtversionchecks.h114
-rw-r--r--src/corelib/global/qtypeinfo.h462
-rw-r--r--src/corelib/global/qtypeinfo.qdoc48
-rw-r--r--src/corelib/global/qtypes.cpp528
-rw-r--r--src/corelib/global/qtypes.h283
-rw-r--r--src/corelib/global/qtypetraits.h55
-rw-r--r--src/corelib/global/qversiontagging.cpp78
-rw-r--r--src/corelib/global/qversiontagging.h190
-rw-r--r--src/corelib/global/qvolatile_p.h53
-rw-r--r--src/corelib/global/qxpfunctional.h195
-rw-r--r--src/corelib/global/qxptype_traits.h121
-rw-r--r--src/corelib/io/PSL-LICENSE.txt373
-rw-r--r--src/corelib/io/forkfd_qt.c15
-rw-r--r--src/corelib/io/forkfd_qt.cpp48
-rw-r--r--src/corelib/io/io.pri196
-rw-r--r--src/corelib/io/qabstractfileengine.cpp352
-rw-r--r--src/corelib/io/qabstractfileengine_p.h111
-rw-r--r--src/corelib/io/qbuffer.cpp130
-rw-r--r--src/corelib/io/qbuffer.h57
-rw-r--r--src/corelib/io/qdataurl.cpp70
-rw-r--r--src/corelib/io/qdataurl_p.h41
-rw-r--r--src/corelib/io/qdebug.cpp543
-rw-r--r--src/corelib/io/qdebug.h407
-rw-r--r--src/corelib/io/qdebug_p.h48
-rw-r--r--src/corelib/io/qdir.cpp986
-rw-r--r--src/corelib/io/qdir.h101
-rw-r--r--src/corelib/io/qdir_p.h69
-rw-r--r--src/corelib/io/qdirentryinfo_p.h156
-rw-r--r--src/corelib/io/qdiriterator.cpp431
-rw-r--r--src/corelib/io/qdiriterator.h45
-rw-r--r--src/corelib/io/qdirlisting.cpp673
-rw-r--r--src/corelib/io/qdirlisting.h119
-rw-r--r--src/corelib/io/qfile.cpp465
-rw-r--r--src/corelib/io/qfile.h204
-rw-r--r--src/corelib/io/qfile_p.h44
-rw-r--r--src/corelib/io/qfiledevice.cpp128
-rw-r--r--src/corelib/io/qfiledevice.h62
-rw-r--r--src/corelib/io/qfiledevice_p.h111
-rw-r--r--src/corelib/io/qfileinfo.cpp1017
-rw-r--r--src/corelib/io/qfileinfo.h120
-rw-r--r--src/corelib/io/qfileinfo_p.h62
-rw-r--r--src/corelib/io/qfileselector.cpp72
-rw-r--r--src/corelib/io/qfileselector.h40
-rw-r--r--src/corelib/io/qfileselector_p.h42
-rw-r--r--src/corelib/io/qfilesystemengine.cpp93
-rw-r--r--src/corelib/io/qfilesystemengine_mac.mm40
-rw-r--r--src/corelib/io/qfilesystemengine_p.h65
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp840
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp1280
-rw-r--r--src/corelib/io/qfilesystementry.cpp147
-rw-r--r--src/corelib/io/qfilesystementry_p.h93
-rw-r--r--src/corelib/io/qfilesystemiterator_p.h66
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp115
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp77
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h123
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp105
-rw-r--r--src/corelib/io/qfilesystemwatcher.h44
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.mm66
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents_p.h40
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp51
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify_p.h40
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp46
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue_p.h46
-rw-r--r--src/corelib/io/qfilesystemwatcher_p.h52
-rw-r--r--src/corelib/io/qfilesystemwatcher_polling.cpp76
-rw-r--r--src/corelib/io/qfilesystemwatcher_polling_p.h54
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp95
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h47
-rw-r--r--src/corelib/io/qfsfileengine.cpp163
-rw-r--r--src/corelib/io/qfsfileengine_iterator.cpp81
-rw-r--r--src/corelib/io/qfsfileengine_iterator_p.h52
-rw-r--r--src/corelib/io/qfsfileengine_p.h90
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp118
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp233
-rw-r--r--src/corelib/io/qiodevice.cpp420
-rw-r--r--src/corelib/io/qiodevice.h72
-rw-r--r--src/corelib/io/qiodevice_p.h102
-rw-r--r--src/corelib/io/qiodevicebase.h33
-rw-r--r--src/corelib/io/qipaddress.cpp103
-rw-r--r--src/corelib/io/qipaddress_p.h40
-rw-r--r--src/corelib/io/qlockfile.cpp155
-rw-r--r--src/corelib/io/qlockfile.h51
-rw-r--r--src/corelib/io/qlockfile_p.h62
-rw-r--r--src/corelib/io/qlockfile_unix.cpp77
-rw-r--r--src/corelib/io/qlockfile_win.cpp96
-rw-r--r--src/corelib/io/qloggingcategory.cpp205
-rw-r--r--src/corelib/io/qloggingcategory.h146
-rw-r--r--src/corelib/io/qloggingregistry.cpp174
-rw-r--r--src/corelib/io/qloggingregistry_p.h92
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp146
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h105
-rw-r--r--src/corelib/io/qntdll_p.h62
-rw-r--r--src/corelib/io/qprocess.cpp1151
-rw-r--r--src/corelib/io/qprocess.h133
-rw-r--r--src/corelib/io/qprocess_darwin.mm40
-rw-r--r--src/corelib/io/qprocess_p.h166
-rw-r--r--src/corelib/io/qprocess_unix.cpp1282
-rw-r--r--src/corelib/io/qprocess_win.cpp721
-rw-r--r--src/corelib/io/qresource.cpp869
-rw-r--r--src/corelib/io/qresource.h55
-rw-r--r--src/corelib/io/qresource_iterator.cpp78
-rw-r--r--src/corelib/io/qresource_iterator_p.h47
-rw-r--r--src/corelib/io/qresource_p.h68
-rw-r--r--src/corelib/io/qsavefile.cpp64
-rw-r--r--src/corelib/io/qsavefile.h46
-rw-r--r--src/corelib/io/qsavefile_p.h44
-rw-r--r--src/corelib/io/qsettings.cpp895
-rw-r--r--src/corelib/io/qsettings.h82
-rw-r--r--src/corelib/io/qsettings_mac.cpp214
-rw-r--r--src/corelib/io/qsettings_p.h109
-rw-r--r--src/corelib/io/qsettings_wasm.cpp498
-rw-r--r--src/corelib/io/qsettings_win.cpp185
-rw-r--r--src/corelib/io/qstandardpaths.cpp184
-rw-r--r--src/corelib/io/qstandardpaths.h51
-rw-r--r--src/corelib/io/qstandardpaths_android.cpp252
-rw-r--r--src/corelib/io/qstandardpaths_haiku.cpp52
-rw-r--r--src/corelib/io/qstandardpaths_mac.mm88
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp421
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp124
-rw-r--r--src/corelib/io/qstorageinfo.cpp86
-rw-r--r--src/corelib/io/qstorageinfo.h64
-rw-r--r--src/corelib/io/qstorageinfo_linux.cpp288
-rw-r--r--src/corelib/io/qstorageinfo_linux_p.h244
-rw-r--r--src/corelib/io/qstorageinfo_mac.cpp49
-rw-r--r--src/corelib/io/qstorageinfo_p.h163
-rw-r--r--src/corelib/io/qstorageinfo_stub.cpp25
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp506
-rw-r--r--src/corelib/io/qstorageinfo_win.cpp193
-rw-r--r--src/corelib/io/qt_attribution.json29
-rw-r--r--src/corelib/io/qtemporarydir.cpp118
-rw-r--r--src/corelib/io/qtemporarydir.h61
-rw-r--r--src/corelib/io/qtemporaryfile.cpp191
-rw-r--r--src/corelib/io/qtemporaryfile.h87
-rw-r--r--src/corelib/io/qtemporaryfile_p.h49
-rw-r--r--src/corelib/io/qurl.cpp1264
-rw-r--r--src/corelib/io/qurl.h252
-rw-r--r--src/corelib/io/qurl_p.h48
-rw-r--r--src/corelib/io/qurlidna.cpp2977
-rw-r--r--src/corelib/io/qurlquery.cpp160
-rw-r--r--src/corelib/io/qurlquery.h125
-rw-r--r--src/corelib/io/qurlrecode.cpp171
-rw-r--r--src/corelib/io/qwindowspipereader.cpp580
-rw-r--r--src/corelib/io/qwindowspipereader_p.h101
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp412
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h153
-rw-r--r--src/corelib/io/qzip.cpp1347
-rw-r--r--src/corelib/io/qzipreader_p.h87
-rw-r--r--src/corelib/io/qzipwriter_p.h77
-rw-r--r--src/corelib/ipc/qsharedmemory.cpp689
-rw-r--r--src/corelib/ipc/qsharedmemory.h99
-rw-r--r--src/corelib/ipc/qsharedmemory_p.h215
-rw-r--r--src/corelib/ipc/qsharedmemory_posix.cpp196
-rw-r--r--src/corelib/ipc/qsharedmemory_systemv.cpp212
-rw-r--r--src/corelib/ipc/qsharedmemory_win.cpp148
-rw-r--r--src/corelib/ipc/qsystemsemaphore.cpp (renamed from src/corelib/kernel/qsystemsemaphore.cpp)267
-rw-r--r--src/corelib/ipc/qsystemsemaphore.h75
-rw-r--r--src/corelib/ipc/qsystemsemaphore_p.h152
-rw-r--r--src/corelib/ipc/qsystemsemaphore_posix.cpp171
-rw-r--r--src/corelib/ipc/qsystemsemaphore_systemv.cpp201
-rw-r--r--src/corelib/ipc/qsystemsemaphore_win.cpp98
-rw-r--r--src/corelib/ipc/qtipccommon.cpp610
-rw-r--r--src/corelib/ipc/qtipccommon.h206
-rw-r--r--src/corelib/ipc/qtipccommon_p.h173
-rw-r--r--src/corelib/itemmodels/itemmodels.pri63
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp490
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h240
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel_p.h101
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.cpp208
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h51
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel_p.h80
-rw-r--r--src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp232
-rw-r--r--src/corelib/itemmodels/qconcatenatetablesproxymodel.h55
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.cpp337
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.h65
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel_p.h72
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp500
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.h124
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel_p.h82
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp802
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h115
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp57
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.h40
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.cpp85
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.h40
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel_p.h40
-rw-r--r--src/corelib/kernel/kernel.pri209
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp402
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h131
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher_p.h57
-rw-r--r--src/corelib/kernel/qabstractnativeeventfilter.cpp46
-rw-r--r--src/corelib/kernel/qabstractnativeeventfilter.h44
-rw-r--r--src/corelib/kernel/qapplicationstatic.h86
-rw-r--r--src/corelib/kernel/qapplicationstatic.qdoc109
-rw-r--r--src/corelib/kernel/qassociativeiterable.cpp287
-rw-r--r--src/corelib/kernel/qassociativeiterable.h173
-rw-r--r--src/corelib/kernel/qbasictimer.cpp111
-rw-r--r--src/corelib/kernel/qbasictimer.h80
-rw-r--r--src/corelib/kernel/qbindingstorage.h94
-rw-r--r--src/corelib/kernel/qcfsocketnotifier.cpp58
-rw-r--r--src/corelib/kernel/qcfsocketnotifier_p.h40
-rw-r--r--src/corelib/kernel/qchronotimer.cpp452
-rw-r--r--src/corelib/kernel/qchronotimer.h149
-rw-r--r--src/corelib/kernel/qcore_foundation.mm302
-rw-r--r--src/corelib/kernel/qcore_mac.mm711
-rw-r--r--src/corelib/kernel/qcore_mac_p.h260
-rw-r--r--src/corelib/kernel/qcore_unix.cpp107
-rw-r--r--src/corelib/kernel/qcore_unix_p.h204
-rw-r--r--src/corelib/kernel/qcore_wasm.cpp97
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp1207
-rw-r--r--src/corelib/kernel/qcoreapplication.h154
-rw-r--r--src/corelib/kernel/qcoreapplication_mac.cpp45
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h67
-rw-r--r--src/corelib/kernel/qcoreapplication_platform.h73
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp135
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h40
-rw-r--r--src/corelib/kernel/qcoreevent.cpp223
-rw-r--r--src/corelib/kernel/qcoreevent.h166
-rw-r--r--src/corelib/kernel/qcoreevent_p.h39
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp59
-rw-r--r--src/corelib/kernel/qcoreglobaldata_p.h77
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp572
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h153
-rw-r--r--src/corelib/kernel/qdeadlinetimer_p.h70
-rw-r--r--src/corelib/kernel/qelapsedtimer.cpp347
-rw-r--r--src/corelib/kernel/qelapsedtimer.h72
-rw-r--r--src/corelib/kernel/qelapsedtimer_generic.cpp213
-rw-r--r--src/corelib/kernel/qelapsedtimer_mac.cpp166
-rw-r--r--src/corelib/kernel/qelapsedtimer_unix.cpp265
-rw-r--r--src/corelib/kernel/qelapsedtimer_win.cpp172
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm127
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf_p.h83
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp162
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h56
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp178
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h65
-rw-r--r--src/corelib/kernel/qeventdispatcher_wasm.cpp1000
-rw-r--r--src/corelib/kernel/qeventdispatcher_wasm_p.h139
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp526
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h82
-rw-r--r--src/corelib/kernel/qeventloop.cpp257
-rw-r--r--src/corelib/kernel/qeventloop.h88
-rw-r--r--src/corelib/kernel/qeventloop_p.h40
-rw-r--r--src/corelib/kernel/qfunctions_nacl.cpp154
-rw-r--r--src/corelib/kernel/qfunctions_nacl.h92
-rw-r--r--src/corelib/kernel/qfunctions_p.h46
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.cpp208
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.h195
-rw-r--r--src/corelib/kernel/qfunctions_win.cpp66
-rw-r--r--src/corelib/kernel/qfunctions_win_p.h51
-rw-r--r--src/corelib/kernel/qfunctions_winrt_p.h75
-rw-r--r--src/corelib/kernel/qiterable.cpp612
-rw-r--r--src/corelib/kernel/qiterable.h516
-rw-r--r--src/corelib/kernel/qiterable_p.h42
-rw-r--r--src/corelib/kernel/qjni.cpp2386
-rw-r--r--src/corelib/kernel/qjni_p.h291
-rw-r--r--src/corelib/kernel/qjniarray.h464
-rw-r--r--src/corelib/kernel/qjnienvironment.cpp538
-rw-r--r--src/corelib/kernel/qjnienvironment.h103
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp490
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h139
-rw-r--r--src/corelib/kernel/qjniobject.cpp1432
-rw-r--r--src/corelib/kernel/qjniobject.h871
-rw-r--r--src/corelib/kernel/qjnionload.cpp81
-rw-r--r--src/corelib/kernel/qjnitypes.h223
-rw-r--r--src/corelib/kernel/qjnitypes_impl.h373
-rw-r--r--src/corelib/kernel/qmath.cpp42
-rw-r--r--src/corelib/kernel/qmath.h168
-rw-r--r--src/corelib/kernel/qmath.qdoc133
-rw-r--r--src/corelib/kernel/qmetacontainer.cpp831
-rw-r--r--src/corelib/kernel/qmetacontainer.h1197
-rw-r--r--src/corelib/kernel/qmetaobject.cpp1727
-rw-r--r--src/corelib/kernel/qmetaobject.h197
-rw-r--r--src/corelib/kernel/qmetaobject_moc_p.h41
-rw-r--r--src/corelib/kernel/qmetaobject_p.h152
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp735
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h69
-rw-r--r--src/corelib/kernel/qmetatype.cpp2907
-rw-r--r--src/corelib/kernel/qmetatype.h2739
-rw-r--r--src/corelib/kernel/qmetatype_p.h248
-rw-r--r--src/corelib/kernel/qmetatypeswitcher_p.h89
-rw-r--r--src/corelib/kernel/qmimedata.cpp220
-rw-r--r--src/corelib/kernel/qmimedata.h46
-rw-r--r--src/corelib/kernel/qobject.cpp1793
-rw-r--r--src/corelib/kernel/qobject.h365
-rw-r--r--src/corelib/kernel/qobject_impl.h64
-rw-r--r--src/corelib/kernel/qobject_p.h420
-rw-r--r--src/corelib/kernel/qobject_p_p.h257
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.cpp42
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.h43
-rw-r--r--src/corelib/kernel/qobjectdefs.h467
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h503
-rw-r--r--src/corelib/kernel/qpermissions.cpp693
-rw-r--r--src/corelib/kernel/qpermissions.h219
-rw-r--r--src/corelib/kernel/qpermissions_android.cpp189
-rw-r--r--src/corelib/kernel/qpermissions_darwin.mm88
-rw-r--r--src/corelib/kernel/qpermissions_p.h55
-rw-r--r--src/corelib/kernel/qpermissions_wasm.cpp275
-rw-r--r--src/corelib/kernel/qpointer.h160
-rw-r--r--src/corelib/kernel/qpointer.qdoc (renamed from src/corelib/kernel/qpointer.cpp)135
-rw-r--r--src/corelib/kernel/qpoll.cpp51
-rw-r--r--src/corelib/kernel/qpoll_p.h42
-rw-r--r--src/corelib/kernel/qppsattribute.cpp308
-rw-r--r--src/corelib/kernel/qppsattribute_p.h138
-rw-r--r--src/corelib/kernel/qppsattributeprivate_p.h89
-rw-r--r--src/corelib/kernel/qppsobject.cpp966
-rw-r--r--src/corelib/kernel/qppsobject_p.h127
-rw-r--r--src/corelib/kernel/qppsobjectprivate_p.h128
-rw-r--r--src/corelib/kernel/qproperty.cpp2509
-rw-r--r--src/corelib/kernel/qproperty.h1512
-rw-r--r--src/corelib/kernel/qproperty_p.h1006
-rw-r--r--src/corelib/kernel/qpropertybinding.cpp203
-rw-r--r--src/corelib/kernel/qpropertybinding_p.h186
-rw-r--r--src/corelib/kernel/qpropertyprivate.h420
-rw-r--r--src/corelib/kernel/qsequentialiterable.cpp215
-rw-r--r--src/corelib/kernel/qsequentialiterable.h155
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp624
-rw-r--r--src/corelib/kernel/qsharedmemory.h137
-rw-r--r--src/corelib/kernel/qsharedmemory_android.cpp110
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h180
-rw-r--r--src/corelib/kernel/qsharedmemory_posix.cpp236
-rw-r--r--src/corelib/kernel/qsharedmemory_systemv.cpp260
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp116
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp185
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp54
-rw-r--r--src/corelib/kernel/qsignalmapper.h41
-rw-r--r--src/corelib/kernel/qsingleshottimer_p.h141
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp161
-rw-r--r--src/corelib/kernel/qsocketnotifier.h72
-rw-r--r--src/corelib/kernel/qsystemerror.cpp79
-rw-r--r--src/corelib/kernel/qsystemerror_p.h59
-rw-r--r--src/corelib/kernel/qsystemsemaphore.h96
-rw-r--r--src/corelib/kernel/qsystemsemaphore_android.cpp83
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h119
-rw-r--r--src/corelib/kernel/qsystemsemaphore_posix.cpp186
-rw-r--r--src/corelib/kernel/qsystemsemaphore_systemv.cpp225
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp103
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp136
-rw-r--r--src/corelib/kernel/qt_attribution.json4
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp166
-rw-r--r--src/corelib/kernel/qtestsupport_core.h80
-rw-r--r--src/corelib/kernel/qtimer.cpp500
-rw-r--r--src/corelib/kernel/qtimer.h243
-rw-r--r--src/corelib/kernel/qtimer_p.h73
-rw-r--r--src/corelib/kernel/qtimerinfo_unix.cpp722
-rw-r--r--src/corelib/kernel/qtimerinfo_unix_p.h129
-rw-r--r--src/corelib/kernel/qtmetamacros.h126
-rw-r--r--src/corelib/kernel/qtmochelpers.h86
-rw-r--r--src/corelib/kernel/qtranslator.cpp131
-rw-r--r--src/corelib/kernel/qtranslator.h61
-rw-r--r--src/corelib/kernel/qtranslator_p.h40
-rw-r--r--src/corelib/kernel/qvariant.cpp4155
-rw-r--r--src/corelib/kernel/qvariant.h1104
-rw-r--r--src/corelib/kernel/qvariant_p.h413
-rw-r--r--src/corelib/kernel/qvarianthash.h20
-rw-r--r--src/corelib/kernel/qvariantlist.h19
-rw-r--r--src/corelib/kernel/qvariantmap.h20
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp161
-rw-r--r--src/corelib/kernel/qwineventnotifier.h42
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h59
-rw-r--r--src/corelib/kernel/qwinregistry.cpp172
-rw-r--r--src/corelib/kernel/qwinregistry_p.h72
-rw-r--r--src/corelib/mimetypes/mime/generate.bat73
-rw-r--r--src/corelib/mimetypes/mime/generate.pl113
-rw-r--r--src/corelib/mimetypes/mime/hexdump.ps129
-rw-r--r--src/corelib/mimetypes/mime/packages/freedesktop.org.xml73878
-rw-r--r--src/corelib/mimetypes/mimetypes.pri55
-rw-r--r--src/corelib/mimetypes/mimetypes.qrc5
-rw-r--r--src/corelib/mimetypes/mimetypes_resources.cmake7
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp467
-rw-r--r--src/corelib/mimetypes/qmimedatabase.h42
-rw-r--r--src/corelib/mimetypes/qmimedatabase_p.h63
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern.cpp220
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern_p.h94
-rw-r--r--src/corelib/mimetypes/qmimemagicrule.cpp113
-rw-r--r--src/corelib/mimetypes/qmimemagicrule_p.h44
-rw-r--r--src/corelib/mimetypes/qmimemagicrulematcher.cpp40
-rw-r--r--src/corelib/mimetypes/qmimemagicrulematcher_p.h40
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp505
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h130
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp190
-rw-r--r--src/corelib/mimetypes/qmimetype.h54
-rw-r--r--src/corelib/mimetypes/qmimetype_p.h78
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp161
-rw-r--r--src/corelib/mimetypes/qmimetypeparser_p.h64
-rw-r--r--src/corelib/platform/android/qandroidextras.cpp1228
-rw-r--r--src/corelib/platform/android/qandroidextras_p.h246
-rw-r--r--src/corelib/platform/android/qandroidnativeinterface.cpp243
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin.mm90
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_bluetooth.mm86
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_calendar.mm71
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_camera.mm42
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_contacts.mm58
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_location.mm263
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_microphone.mm42
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_p.h58
-rw-r--r--src/corelib/platform/darwin/qdarwinpermissionplugin_p_p.h104
-rw-r--r--src/corelib/platform/ios/PrivacyInfo.xcprivacy31
-rw-r--r--src/corelib/platform/platform.pri1
-rw-r--r--src/corelib/platform/wasm/qstdweb.cpp819
-rw-r--r--src/corelib/platform/wasm/qstdweb_p.h274
-rw-r--r--src/corelib/platform/wasm/wasm.pri3
-rw-r--r--src/corelib/platform/windows/qcomobject_p.h127
-rw-r--r--src/corelib/platform/windows/qfactorycacheregistration.cpp53
-rw-r--r--src/corelib/platform/windows/qfactorycacheregistration_p.h52
-rw-r--r--src/corelib/platform/windows/qt_winrtbase_p.h34
-rw-r--r--src/corelib/plugin/plugin.pri38
-rw-r--r--src/corelib/plugin/qcoffpeparser.cpp383
-rw-r--r--src/corelib/plugin/qcoffpeparser_p.h34
-rw-r--r--src/corelib/plugin/qelfparser_p.cpp957
-rw-r--r--src/corelib/plugin/qelfparser_p.h84
-rw-r--r--src/corelib/plugin/qfactoryinterface.cpp40
-rw-r--r--src/corelib/plugin/qfactoryinterface.h43
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp699
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h92
-rw-r--r--src/corelib/plugin/qlibrary.cpp609
-rw-r--r--src/corelib/plugin/qlibrary.h58
-rw-r--r--src/corelib/plugin/qlibrary_p.h69
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp158
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp55
-rw-r--r--src/corelib/plugin/qmachparser.cpp141
-rw-r--r--src/corelib/plugin/qmachparser_p.h48
-rw-r--r--src/corelib/plugin/qplugin.h262
-rw-r--r--src/corelib/plugin/qplugin.qdoc46
-rw-r--r--src/corelib/plugin/qplugin_p.h101
-rw-r--r--src/corelib/plugin/qpluginloader.cpp209
-rw-r--r--src/corelib/plugin/qpluginloader.h42
-rw-r--r--src/corelib/plugin/qsystemlibrary.cpp87
-rw-r--r--src/corelib/plugin/qsystemlibrary_p.h61
-rw-r--r--src/corelib/plugin/quuid.cpp421
-rw-r--r--src/corelib/plugin/quuid.h249
-rw-r--r--src/corelib/qt_cmdline.cmake17
-rw-r--r--src/corelib/qtcore.tracepoints41
-rw-r--r--src/corelib/qtzlib.pro7
-rwxr-xr-xsrc/corelib/serialization/make-xml-parser.sh40
-rw-r--r--src/corelib/serialization/qbinaryjson.cpp415
-rw-r--r--src/corelib/serialization/qbinaryjson_p.h615
-rw-r--r--src/corelib/serialization/qbinaryjsonarray.cpp137
-rw-r--r--src/corelib/serialization/qbinaryjsonarray_p.h98
-rw-r--r--src/corelib/serialization/qbinaryjsonobject.cpp149
-rw-r--r--src/corelib/serialization/qbinaryjsonobject_p.h97
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue.cpp147
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue_p.h136
-rw-r--r--src/corelib/serialization/qcborarray.cpp221
-rw-r--r--src/corelib/serialization/qcborarray.h221
-rw-r--r--src/corelib/serialization/qcborcommon.cpp73
-rw-r--r--src/corelib/serialization/qcborcommon.h49
-rw-r--r--src/corelib/serialization/qcborcommon_p.h43
-rw-r--r--src/corelib/serialization/qcbordiagnostic.cpp88
-rw-r--r--src/corelib/serialization/qcbormap.cpp445
-rw-r--r--src/corelib/serialization/qcbormap.h322
-rw-r--r--src/corelib/serialization/qcborstream.h42
-rw-r--r--src/corelib/serialization/qcborstreamreader.cpp617
-rw-r--r--src/corelib/serialization/qcborstreamreader.h79
-rw-r--r--src/corelib/serialization/qcborstreamwriter.cpp100
-rw-r--r--src/corelib/serialization/qcborstreamwriter.h46
-rw-r--r--src/corelib/serialization/qcborvalue.cpp1315
-rw-r--r--src/corelib/serialization/qcborvalue.h358
-rw-r--r--src/corelib/serialization/qcborvalue_p.h164
-rw-r--r--src/corelib/serialization/qdatastream.cpp367
-rw-r--r--src/corelib/serialization/qdatastream.h387
-rw-r--r--src/corelib/serialization/qdatastream_p.h45
-rw-r--r--src/corelib/serialization/qjson_p.h89
-rw-r--r--src/corelib/serialization/qjsonarray.cpp334
-rw-r--r--src/corelib/serialization/qjsonarray.h341
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp187
-rw-r--r--src/corelib/serialization/qjsondocument.cpp296
-rw-r--r--src/corelib/serialization/qjsondocument.h80
-rw-r--r--src/corelib/serialization/qjsonobject.cpp436
-rw-r--r--src/corelib/serialization/qjsonobject.h392
-rw-r--r--src/corelib/serialization/qjsonparser.cpp275
-rw-r--r--src/corelib/serialization/qjsonparser_p.h40
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp548
-rw-r--r--src/corelib/serialization/qjsonvalue.h294
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp65
-rw-r--r--src/corelib/serialization/qjsonwriter_p.h40
-rw-r--r--src/corelib/serialization/qtextstream.cpp478
-rw-r--r--src/corelib/serialization/qtextstream.h126
-rw-r--r--src/corelib/serialization/qtextstream_p.h74
-rw-r--r--src/corelib/serialization/qxmlstream.cpp1546
-rw-r--r--src/corelib/serialization/qxmlstream.g589
-rw-r--r--src/corelib/serialization/qxmlstream.h344
-rw-r--r--src/corelib/serialization/qxmlstream_p.h1846
-rw-r--r--src/corelib/serialization/qxmlstreamgrammar.cpp496
-rw-r--r--src/corelib/serialization/qxmlstreamgrammar_p.h128
-rw-r--r--src/corelib/serialization/qxmlstreamparser_p.h1006
-rw-r--r--src/corelib/serialization/qxmlutils.cpp81
-rw-r--r--src/corelib/serialization/qxmlutils_p.h42
-rw-r--r--src/corelib/serialization/serialization.pri76
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp239
-rw-r--r--src/corelib/statemachine/qabstractstate.h88
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h99
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp435
-rw-r--r--src/corelib/statemachine/qabstracttransition.h117
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h95
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp256
-rw-r--r--src/corelib/statemachine/qeventtransition.h85
-rw-r--r--src/corelib/statemachine/qeventtransition_p.h81
-rw-r--r--src/corelib/statemachine/qfinalstate.cpp141
-rw-r--r--src/corelib/statemachine/qfinalstate.h73
-rw-r--r--src/corelib/statemachine/qfinalstate_p.h72
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp334
-rw-r--r--src/corelib/statemachine/qhistorystate.h95
-rw-r--r--src/corelib/statemachine/qhistorystate_p.h80
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h78
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp287
-rw-r--r--src/corelib/statemachine/qsignaltransition.h99
-rw-r--r--src/corelib/statemachine/qsignaltransition_p.h83
-rw-r--r--src/corelib/statemachine/qstate.cpp603
-rw-r--r--src/corelib/statemachine/qstate.h134
-rw-r--r--src/corelib/statemachine/qstate_p.h127
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp3211
-rw-r--r--src/corelib/statemachine/qstatemachine.h199
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h334
-rw-r--r--src/corelib/statemachine/statemachine.pri33
-rw-r--r--src/corelib/text/UNICODE_LICENSE.txt46
-rw-r--r--src/corelib/text/qanystringview.cpp660
-rw-r--r--src/corelib/text/qanystringview.h351
-rw-r--r--src/corelib/text/qbytearray.cpp2998
-rw-r--r--src/corelib/text/qbytearray.h944
-rw-r--r--src/corelib/text/qbytearray_p.h65
-rw-r--r--src/corelib/text/qbytearrayalgorithms.h148
-rw-r--r--src/corelib/text/qbytearraylist.cpp90
-rw-r--r--src/corelib/text/qbytearraylist.h79
-rw-r--r--src/corelib/text/qbytearraymatcher.cpp124
-rw-r--r--src/corelib/text/qbytearraymatcher.h120
-rw-r--r--src/corelib/text/qbytearrayview.h406
-rw-r--r--src/corelib/text/qbytearrayview.qdoc1056
-rw-r--r--src/corelib/text/qbytedata_p.h145
-rw-r--r--src/corelib/text/qchar.cpp536
-rw-r--r--src/corelib/text/qchar.h382
-rw-r--r--src/corelib/text/qcollator.cpp319
-rw-r--r--src/corelib/text/qcollator.h74
-rw-r--r--src/corelib/text/qcollator_icu.cpp55
-rw-r--r--src/corelib/text/qcollator_macx.cpp64
-rw-r--r--src/corelib/text/qcollator_p.h52
-rw-r--r--src/corelib/text/qcollator_posix.cpp75
-rw-r--r--src/corelib/text/qcollator_win.cpp73
-rw-r--r--src/corelib/text/qdoublescanprint_p.h42
-rw-r--r--src/corelib/text/qlatin1stringmatcher.cpp233
-rw-r--r--src/corelib/text/qlatin1stringmatcher.h181
-rw-r--r--src/corelib/text/qlatin1stringview.h375
-rw-r--r--src/corelib/text/qlatin1stringview.qdoc1295
-rw-r--r--src/corelib/text/qlocale.cpp4076
-rw-r--r--src/corelib/text/qlocale.h1866
-rw-r--r--src/corelib/text/qlocale.qdoc733
-rw-r--r--src/corelib/text/qlocale_data_p.h13730
-rw-r--r--src/corelib/text/qlocale_icu.cpp40
-rw-r--r--src/corelib/text/qlocale_mac.mm632
-rw-r--r--src/corelib/text/qlocale_p.h615
-rw-r--r--src/corelib/text/qlocale_tools.cpp708
-rw-r--r--src/corelib/text/qlocale_tools_p.h125
-rw-r--r--src/corelib/text/qlocale_unix.cpp109
-rw-r--r--src/corelib/text/qlocale_wasm.cpp54
-rw-r--r--src/corelib/text/qlocale_win.cpp606
-rw-r--r--src/corelib/text/qregexp.cpp5039
-rw-r--r--src/corelib/text/qregexp.h151
-rw-r--r--src/corelib/text/qregularexpression.cpp746
-rw-r--r--src/corelib/text/qregularexpression.h258
-rw-r--r--src/corelib/text/qstaticlatin1stringmatcher.h157
-rw-r--r--src/corelib/text/qstaticlatin1stringmatcher.qdoc87
-rw-r--r--src/corelib/text/qstring.cpp9674
-rw-r--r--src/corelib/text/qstring.h2325
-rw-r--r--src/corelib/text/qstring_compat.cpp112
-rw-r--r--src/corelib/text/qstring_mips_dsp_asm.S40
-rw-r--r--src/corelib/text/qstringalgorithms.h276
-rw-r--r--src/corelib/text/qstringalgorithms_p.h64
-rw-r--r--src/corelib/text/qstringbuilder.cpp102
-rw-r--r--src/corelib/text/qstringbuilder.h319
-rw-r--r--src/corelib/text/qstringconverter.cpp1599
-rw-r--r--src/corelib/text/qstringconverter.h380
-rw-r--r--src/corelib/text/qstringconverter_base.h176
-rw-r--r--src/corelib/text/qstringconverter_p.h229
-rw-r--r--src/corelib/text/qstringfwd.h56
-rw-r--r--src/corelib/text/qstringiterator.qdoc28
-rw-r--r--src/corelib/text/qstringiterator_p.h85
-rw-r--r--src/corelib/text/qstringlist.cpp458
-rw-r--r--src/corelib/text/qstringlist.h413
-rw-r--r--src/corelib/text/qstringliteral.h72
-rw-r--r--src/corelib/text/qstringmatcher.cpp139
-rw-r--r--src/corelib/text/qstringmatcher.h73
-rw-r--r--src/corelib/text/qstringtokenizer.cpp132
-rw-r--r--src/corelib/text/qstringtokenizer.h98
-rw-r--r--src/corelib/text/qstringview.cpp638
-rw-r--r--src/corelib/text/qstringview.h464
-rw-r--r--src/corelib/text/qt_attribution.json36
-rw-r--r--src/corelib/text/qtextboundaryfinder.cpp234
-rw-r--r--src/corelib/text/qtextboundaryfinder.h68
-rw-r--r--src/corelib/text/qtliterals.qdoc44
-rw-r--r--src/corelib/text/qunicodetables.cpp28146
-rw-r--r--src/corelib/text/qunicodetables_p.h96
-rw-r--r--src/corelib/text/qunicodetools.cpp830
-rw-r--r--src/corelib/text/qunicodetools_p.h51
-rw-r--r--src/corelib/text/qutf8stringview.h434
-rw-r--r--src/corelib/text/qutf8stringview.qdoc720
-rw-r--r--src/corelib/text/qvsnprintf.cpp42
-rw-r--r--src/corelib/text/text.pri92
-rw-r--r--src/corelib/thread/qatomic.cpp226
-rw-r--r--src/corelib/thread/qatomic.h115
-rw-r--r--src/corelib/thread/qatomic_bootstrap.h97
-rw-r--r--src/corelib/thread/qatomic_cxx11.h111
-rw-r--r--src/corelib/thread/qatomic_msvc.h485
-rw-r--r--src/corelib/thread/qbasicatomic.h122
-rw-r--r--src/corelib/thread/qexception.cpp150
-rw-r--r--src/corelib/thread/qexception.h78
-rw-r--r--src/corelib/thread/qfutex_freebsd_p.h82
-rw-r--r--src/corelib/thread/qfutex_linux_p.h95
-rw-r--r--src/corelib/thread/qfutex_mac_p.h140
-rw-r--r--src/corelib/thread/qfutex_p.h149
-rw-r--r--src/corelib/thread/qfutex_win_p.h58
-rw-r--r--src/corelib/thread/qfuture.h270
-rw-r--r--src/corelib/thread/qfuture.qdoc811
-rw-r--r--src/corelib/thread/qfuture_impl.h842
-rw-r--r--src/corelib/thread/qfutureinterface.cpp471
-rw-r--r--src/corelib/thread/qfutureinterface.h275
-rw-r--r--src/corelib/thread/qfutureinterface_p.h137
-rw-r--r--src/corelib/thread/qfuturesynchronizer.h61
-rw-r--r--src/corelib/thread/qfuturesynchronizer.qdoc34
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp92
-rw-r--r--src/corelib/thread/qfuturewatcher.h48
-rw-r--r--src/corelib/thread/qfuturewatcher_p.h41
-rw-r--r--src/corelib/thread/qgenericatomic.h383
-rw-r--r--src/corelib/thread/qlocking_p.h52
-rw-r--r--src/corelib/thread/qmutex.cpp642
-rw-r--r--src/corelib/thread/qmutex.h355
-rw-r--r--src/corelib/thread/qmutex_linux.cpp182
-rw-r--r--src/corelib/thread/qmutex_mac.cpp51
-rw-r--r--src/corelib/thread/qmutex_p.h101
-rw-r--r--src/corelib/thread/qmutex_unix.cpp120
-rw-r--r--src/corelib/thread/qmutex_win.cpp66
-rw-r--r--src/corelib/thread/qorderedmutexlocker_p.h112
-rw-r--r--src/corelib/thread/qpromise.h141
-rw-r--r--src/corelib/thread/qpromise.qdoc157
-rw-r--r--src/corelib/thread/qreadwritelock.cpp308
-rw-r--r--src/corelib/thread/qreadwritelock.h110
-rw-r--r--src/corelib/thread/qreadwritelock_p.h114
-rw-r--r--src/corelib/thread/qresultstore.cpp119
-rw-r--r--src/corelib/thread/qresultstore.h121
-rw-r--r--src/corelib/thread/qrunnable.cpp88
-rw-r--r--src/corelib/thread/qrunnable.h160
-rw-r--r--src/corelib/thread/qsemaphore.cpp347
-rw-r--r--src/corelib/thread/qsemaphore.h85
-rw-r--r--src/corelib/thread/qthread.cpp419
-rw-r--r--src/corelib/thread/qthread.h190
-rw-r--r--src/corelib/thread/qthread_p.h213
-rw-r--r--src/corelib/thread/qthread_unix.cpp307
-rw-r--r--src/corelib/thread/qthread_win.cpp151
-rw-r--r--src/corelib/thread/qthreadpool.cpp427
-rw-r--r--src/corelib/thread/qthreadpool.h96
-rw-r--r--src/corelib/thread/qthreadpool_p.h89
-rw-r--r--src/corelib/thread/qthreadstorage.cpp60
-rw-r--r--src/corelib/thread/qthreadstorage.h46
-rw-r--r--src/corelib/thread/qtsan_impl.h79
-rw-r--r--src/corelib/thread/qwaitcondition.h42
-rw-r--r--src/corelib/thread/qwaitcondition.qdoc42
-rw-r--r--src/corelib/thread/qwaitcondition_p.h141
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp199
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp113
-rw-r--r--src/corelib/thread/qyieldcpu.h64
-rw-r--r--src/corelib/thread/qyieldcpu.qdoc59
-rw-r--r--src/corelib/thread/thread.pri85
-rw-r--r--src/corelib/time/qcalendar.cpp987
-rw-r--r--src/corelib/time/qcalendar.h67
-rw-r--r--src/corelib/time/qcalendarbackend_p.h77
-rw-r--r--src/corelib/time/qcalendarmath_p.h152
-rw-r--r--src/corelib/time/qdatetime.cpp4449
-rw-r--r--src/corelib/time/qdatetime.h563
-rw-r--r--src/corelib/time/qdatetime_p.h123
-rw-r--r--src/corelib/time/qdatetimeparser.cpp1124
-rw-r--r--src/corelib/time/qdatetimeparser_p.h114
-rw-r--r--src/corelib/time/qgregoriancalendar.cpp259
-rw-r--r--src/corelib/time/qgregoriancalendar_p.h59
-rw-r--r--src/corelib/time/qhijricalendar.cpp44
-rw-r--r--src/corelib/time/qhijricalendar_data_p.h2924
-rw-r--r--src/corelib/time/qhijricalendar_p.h43
-rw-r--r--src/corelib/time/qislamiccivilcalendar.cpp91
-rw-r--r--src/corelib/time/qislamiccivilcalendar_p.h43
-rw-r--r--src/corelib/time/qjalalicalendar.cpp74
-rw-r--r--src/corelib/time/qjalalicalendar_data_p.h1989
-rw-r--r--src/corelib/time/qjalalicalendar_p.h43
-rw-r--r--src/corelib/time/qjuliancalendar.cpp80
-rw-r--r--src/corelib/time/qjuliancalendar_p.h43
-rw-r--r--src/corelib/time/qlocaltime.cpp720
-rw-r--r--src/corelib/time/qlocaltime_p.h46
-rw-r--r--src/corelib/time/qmilankoviccalendar.cpp100
-rw-r--r--src/corelib/time/qmilankoviccalendar_p.h43
-rw-r--r--src/corelib/time/qromancalendar.cpp53
-rw-r--r--src/corelib/time/qromancalendar_data_p.h7666
-rw-r--r--src/corelib/time/qromancalendar_p.h49
-rw-r--r--src/corelib/time/qtimezone.cpp1256
-rw-r--r--src/corelib/time/qtimezone.h252
-rw-r--r--src/corelib/time/qtimezonelocale.cpp29
-rw-r--r--src/corelib/time/qtimezonelocale_data_p.h39
-rw-r--r--src/corelib/time/qtimezonelocale_p.h31
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp834
-rw-r--r--src/corelib/time/qtimezoneprivate_android.cpp180
-rw-r--r--src/corelib/time/qtimezoneprivate_data_p.h2485
-rw-r--r--src/corelib/time/qtimezoneprivate_icu.cpp178
-rw-r--r--src/corelib/time/qtimezoneprivate_mac.mm71
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h182
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp717
-rw-r--r--src/corelib/time/qtimezoneprivate_win.cpp483
-rw-r--r--src/corelib/time/time.pri71
-rw-r--r--src/corelib/tools/qalgorithms.h602
-rw-r--r--src/corelib/tools/qalgorithms.qdoc638
-rw-r--r--src/corelib/tools/qarraydata.cpp298
-rw-r--r--src/corelib/tools/qarraydata.h310
-rw-r--r--src/corelib/tools/qarraydataops.h1200
-rw-r--r--src/corelib/tools/qarraydatapointer.h543
-rw-r--r--src/corelib/tools/qatomicscopedvaluerollback.h127
-rw-r--r--src/corelib/tools/qatomicscopedvaluerollback.qdoc123
-rw-r--r--src/corelib/tools/qbitarray.cpp479
-rw-r--r--src/corelib/tools/qbitarray.h222
-rw-r--r--src/corelib/tools/qcache.h153
-rw-r--r--src/corelib/tools/qcache.qdoc42
-rw-r--r--src/corelib/tools/qcommandlineoption.cpp88
-rw-r--r--src/corelib/tools/qcommandlineoption.h53
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp204
-rw-r--r--src/corelib/tools/qcommandlineparser.h40
-rw-r--r--src/corelib/tools/qcontainerfwd.h100
-rw-r--r--src/corelib/tools/qcontainertools_impl.h470
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp68
-rw-r--r--src/corelib/tools/qcontiguouscache.h105
-rw-r--r--src/corelib/tools/qcryptographichash.cpp1542
-rw-r--r--src/corelib/tools/qcryptographichash.h77
-rw-r--r--src/corelib/tools/qduplicatetracker_p.h134
-rw-r--r--src/corelib/tools/qeasingcurve.cpp144
-rw-r--r--src/corelib/tools/qeasingcurve.h61
-rw-r--r--src/corelib/tools/qflatmap_p.h484
-rw-r--r--src/corelib/tools/qfreelist.cpp58
-rw-r--r--src/corelib/tools/qfreelist_p.h52
-rw-r--r--src/corelib/tools/qfunctionaltools_impl.cpp47
-rw-r--r--src/corelib/tools/qfunctionaltools_impl.h77
-rw-r--r--src/corelib/tools/qhash.cpp1656
-rw-r--r--src/corelib/tools/qhash.h1311
-rw-r--r--src/corelib/tools/qhashfunctions.h266
-rw-r--r--src/corelib/tools/qiterator.h191
-rw-r--r--src/corelib/tools/qiterator.qdoc610
-rw-r--r--src/corelib/tools/qline.cpp218
-rw-r--r--src/corelib/tools/qline.h264
-rw-r--r--src/corelib/tools/qlist.cpp66
-rw-r--r--src/corelib/tools/qlist.h988
-rw-r--r--src/corelib/tools/qlist.qdoc743
-rw-r--r--src/corelib/tools/qmakearray_p.h50
-rw-r--r--src/corelib/tools/qmap.cpp2132
-rw-r--r--src/corelib/tools/qmap.h2432
-rw-r--r--src/corelib/tools/qmap.qdoc1400
-rw-r--r--src/corelib/tools/qmargins.cpp184
-rw-r--r--src/corelib/tools/qmargins.h398
-rw-r--r--src/corelib/tools/qmessageauthenticationcode.cpp305
-rw-r--r--src/corelib/tools/qmessageauthenticationcode.h69
-rw-r--r--src/corelib/tools/qminimalflatset_p.h156
-rw-r--r--src/corelib/tools/qmultimap.qdoc1543
-rw-r--r--src/corelib/tools/qoffsetstringarray_p.h246
-rw-r--r--src/corelib/tools/qpair.h47
-rw-r--r--src/corelib/tools/qpair.qdoc46
-rw-r--r--src/corelib/tools/qpoint.cpp204
-rw-r--r--src/corelib/tools/qpoint.h373
-rw-r--r--src/corelib/tools/qqueue.cpp40
-rw-r--r--src/corelib/tools/qqueue.h45
-rw-r--r--src/corelib/tools/qrect.cpp350
-rw-r--r--src/corelib/tools/qrect.h716
-rw-r--r--src/corelib/tools/qrefcount.cpp40
-rw-r--r--src/corelib/tools/qrefcount.h40
-rw-r--r--src/corelib/tools/qringbuffer.cpp105
-rw-r--r--src/corelib/tools/qringbuffer_p.h109
-rw-r--r--src/corelib/tools/qscopedpointer.cpp93
-rw-r--r--src/corelib/tools/qscopedpointer.h175
-rw-r--r--src/corelib/tools/qscopedpointer_p.h148
-rw-r--r--src/corelib/tools/qscopedvaluerollback.cpp42
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h63
-rw-r--r--src/corelib/tools/qscopeguard.h62
-rw-r--r--src/corelib/tools/qscopeguard.qdoc30
-rw-r--r--src/corelib/tools/qset.h121
-rw-r--r--src/corelib/tools/qset.qdoc375
-rw-r--r--src/corelib/tools/qshareddata.cpp137
-rw-r--r--src/corelib/tools/qshareddata.h384
-rw-r--r--src/corelib/tools/qshareddata_impl.h142
-rw-r--r--src/corelib/tools/qsharedpointer.cpp206
-rw-r--r--src/corelib/tools/qsharedpointer.h88
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h415
-rw-r--r--src/corelib/tools/qsize.cpp130
-rw-r--r--src/corelib/tools/qsize.h413
-rw-r--r--src/corelib/tools/qspan.h452
-rw-r--r--src/corelib/tools/qspan.qdoc651
-rw-r--r--src/corelib/tools/qspan_p.h24
-rw-r--r--src/corelib/tools/qstack.cpp40
-rw-r--r--src/corelib/tools/qstack.h63
-rw-r--r--src/corelib/tools/qtaggedpointer.h92
-rw-r--r--src/corelib/tools/qtaggedpointer.qdoc54
-rw-r--r--src/corelib/tools/qtimeline.cpp293
-rw-r--r--src/corelib/tools/qtimeline.h72
-rw-r--r--src/corelib/tools/qtools_p.h133
-rw-r--r--src/corelib/tools/qtyperevision.cpp217
-rw-r--r--src/corelib/tools/qtyperevision.h167
-rw-r--r--src/corelib/tools/quniquehandle_p.h225
-rw-r--r--src/corelib/tools/qvarlengtharray.h1146
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc220
-rw-r--r--src/corelib/tools/qvector.h46
-rw-r--r--src/corelib/tools/qvector_msvc.cpp51
-rw-r--r--src/corelib/tools/qversionnumber.cpp470
-rw-r--r--src/corelib/tools/qversionnumber.h446
-rw-r--r--src/corelib/tools/tools.pri117
-rw-r--r--src/corelib/tracing/qctf.cpp144
-rw-r--r--src/corelib/tracing/qctf_p.h238
1257 files changed, 236957 insertions, 202460 deletions
diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt
deleted file mode 100644
index f93c934c85..0000000000
--- a/src/corelib/.prev_CMakeLists.txt
+++ /dev/null
@@ -1,1066 +0,0 @@
-# Generated from corelib.pro.
-
-#####################################################################
-## Core Module:
-#####################################################################
-
-qt_add_module(Core
- GENERATE_METATYPES
- QMAKE_MODULE_CONFIG moc resources
- EXCEPTIONS
- SOURCES
- global/archdetect.cpp
- global/qcompilerdetection.h
- global/qendian.cpp global/qendian.h global/qendian_p.h
- global/qflags.h
- global/qfloat16.cpp global/qfloat16.h
- global/qglobal.cpp global/qglobal.h
- global/qglobalstatic.h
- global/qhooks.cpp global/qhooks_p.h
- global/qisenum.h
- global/qlibraryinfo.cpp global/qlibraryinfo.h
- global/qlogging.cpp global/qlogging.h
- global/qmalloc.cpp
- global/qmemory_p.h
- global/qnamespace.h
- global/qnumeric.cpp global/qnumeric.h global/qnumeric_p.h
- global/qoperatingsystemversion.cpp global/qoperatingsystemversion.h global/qoperatingsystemversion_p.h
- global/qprocessordetection.h
- global/qrandom.cpp global/qrandom.h global/qrandom_p.h
- global/qsimd.cpp global/qsimd.h global/qsimd_p.h
- global/qsysinfo.h
- global/qsystemdetection.h
- global/qtypeinfo.h
- global/qtypetraits.h
- global/qversiontagging.h
- io/qabstractfileengine.cpp io/qabstractfileengine_p.h
- io/qbuffer.cpp io/qbuffer.h
- io/qdataurl.cpp io/qdataurl_p.h
- io/qdebug.cpp io/qdebug.h io/qdebug_p.h
- io/qdir.cpp io/qdir.h io/qdir_p.h
- io/qdiriterator.cpp io/qdiriterator.h
- io/qfile.cpp io/qfile.h
- io/qfiledevice.cpp io/qfiledevice.h io/qfiledevice_p.h
- io/qfileinfo.cpp io/qfileinfo.h io/qfileinfo_p.h
- io/qfileselector.cpp io/qfileselector.h io/qfileselector_p.h
- io/qfilesystemengine.cpp io/qfilesystemengine_p.h
- io/qfilesystementry.cpp io/qfilesystementry_p.h
- io/qfilesystemiterator_p.h
- io/qfilesystemmetadata_p.h
- io/qfsfileengine.cpp io/qfsfileengine_p.h
- io/qfsfileengine_iterator.cpp io/qfsfileengine_iterator_p.h
- io/qiodevice.cpp io/qiodevice.h io/qiodevice_p.h
- io/qipaddress.cpp io/qipaddress_p.h
- io/qlockfile.cpp io/qlockfile.h io/qlockfile_p.h
- io/qloggingcategory.cpp io/qloggingcategory.h
- io/qloggingregistry.cpp io/qloggingregistry_p.h
- io/qnoncontiguousbytedevice.cpp io/qnoncontiguousbytedevice_p.h
- io/qresource.cpp io/qresource_p.h
- io/qresource_iterator.cpp io/qresource_iterator_p.h
- io/qsavefile.cpp io/qsavefile.h
- io/qstandardpaths.cpp io/qstandardpaths.h
- io/qstorageinfo.cpp io/qstorageinfo.h io/qstorageinfo_p.h
- io/qtemporarydir.cpp io/qtemporarydir.h
- io/qtemporaryfile.cpp io/qtemporaryfile.h io/qtemporaryfile_p.h
- io/qurl.cpp io/qurl.h io/qurl_p.h
- io/qurlidna.cpp
- io/qurlquery.cpp io/qurlquery.h
- io/qurlrecode.cpp
- itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
- itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_p.h
- kernel/qabstracteventdispatcher.cpp kernel/qabstracteventdispatcher.h kernel/qabstracteventdispatcher_p.h
- kernel/qabstractnativeeventfilter.cpp kernel/qabstractnativeeventfilter.h
- kernel/qbasictimer.cpp kernel/qbasictimer.h
- kernel/qcoreapplication.cpp kernel/qcoreapplication.h kernel/qcoreapplication_p.h
- kernel/qcorecmdlineargs_p.h
- kernel/qcoreevent.cpp kernel/qcoreevent.h
- kernel/qcoreglobaldata.cpp kernel/qcoreglobaldata_p.h
- kernel/qdeadlinetimer.cpp kernel/qdeadlinetimer.h kernel/qdeadlinetimer_p.h
- kernel/qelapsedtimer.cpp kernel/qelapsedtimer.h
- kernel/qeventloop.cpp kernel/qeventloop.h
- kernel/qfunctions_p.h
- kernel/qmath.cpp kernel/qmath.h
- kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h
- kernel/qmetaobject_moc_p.h
- kernel/qmetaobjectbuilder.cpp kernel/qmetaobjectbuilder_p.h
- kernel/qmetatype.cpp kernel/qmetatype.h kernel/qmetatype_p.h
- kernel/qmetatypeswitcher_p.h
- kernel/qmimedata.cpp kernel/qmimedata.h
- kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h
- kernel/qobject_impl.h
- kernel/qobjectcleanuphandler.cpp kernel/qobjectcleanuphandler.h
- kernel/qobjectdefs.h
- kernel/qobjectdefs_impl.h
- kernel/qpointer.cpp kernel/qpointer.h
- kernel/qproperty.cpp kernel/qproperty.h kernel/qproperty_p.h
- kernel/qpropertybinding.cpp kernel/qpropertybinding_p.h
- kernel/qpropertyprivate.h
- kernel/qsharedmemory.cpp kernel/qsharedmemory.h kernel/qsharedmemory_p.h
- kernel/qsignalmapper.cpp kernel/qsignalmapper.h
- kernel/qsocketnotifier.cpp kernel/qsocketnotifier.h
- kernel/qsystemerror.cpp kernel/qsystemerror_p.h
- kernel/qsystemsemaphore.cpp kernel/qsystemsemaphore.h kernel/qsystemsemaphore_p.h
- kernel/qtestsupport_core.cpp kernel/qtestsupport_core.h
- kernel/qtimer.cpp kernel/qtimer.h
- kernel/qtranslator.cpp kernel/qtranslator.h kernel/qtranslator_p.h
- kernel/qvariant.cpp kernel/qvariant.h kernel/qvariant_p.h
- plugin/qfactoryinterface.cpp plugin/qfactoryinterface.h
- plugin/qfactoryloader.cpp plugin/qfactoryloader_p.h
- plugin/qplugin.h plugin/qplugin_p.h
- plugin/qpluginloader.cpp plugin/qpluginloader.h
- plugin/quuid.cpp plugin/quuid.h
- serialization/qcborarray.h
- serialization/qcborcommon.cpp serialization/qcborcommon.h serialization/qcborcommon_p.h
- serialization/qcbordiagnostic.cpp
- serialization/qcbormap.h
- serialization/qcborstream.h
- serialization/qcborvalue.cpp serialization/qcborvalue.h serialization/qcborvalue_p.h
- serialization/qdatastream.cpp serialization/qdatastream.h serialization/qdatastream_p.h
- serialization/qjson_p.h
- serialization/qjsonarray.cpp serialization/qjsonarray.h
- serialization/qjsoncbor.cpp
- serialization/qjsondocument.cpp serialization/qjsondocument.h
- serialization/qjsonobject.cpp serialization/qjsonobject.h
- serialization/qjsonparser.cpp serialization/qjsonparser_p.h
- serialization/qjsonvalue.cpp serialization/qjsonvalue.h
- serialization/qjsonwriter.cpp serialization/qjsonwriter_p.h
- serialization/qtextstream.cpp serialization/qtextstream.h serialization/qtextstream_p.h
- serialization/qxmlstream.cpp serialization/qxmlstream.h serialization/qxmlstream_p.h
- serialization/qxmlutils.cpp serialization/qxmlutils_p.h
- statemachine/qabstractstate.cpp statemachine/qabstractstate.h statemachine/qabstractstate_p.h
- statemachine/qabstracttransition.cpp statemachine/qabstracttransition.h statemachine/qabstracttransition_p.h
- statemachine/qfinalstate.cpp statemachine/qfinalstate.h statemachine/qfinalstate_p.h
- statemachine/qhistorystate.cpp statemachine/qhistorystate.h statemachine/qhistorystate_p.h
- statemachine/qsignaleventgenerator_p.h
- statemachine/qsignaltransition.cpp statemachine/qsignaltransition.h statemachine/qsignaltransition_p.h
- statemachine/qstate.cpp statemachine/qstate.h statemachine/qstate_p.h
- statemachine/qstatemachine.cpp statemachine/qstatemachine.h statemachine/qstatemachine_p.h
- text/qbytearray.cpp text/qbytearray.h text/qbytearray_p.h
- text/qbytearraylist.cpp text/qbytearraylist.h
- text/qbytearraymatcher.cpp text/qbytearraymatcher.h
- text/qbytedata_p.h
- text/qchar.h
- text/qcollator.cpp text/qcollator.h text/qcollator_p.h
- text/qdoublescanprint_p.h
- text/qlocale.cpp text/qlocale.h text/qlocale_p.h
- text/qlocale_data_p.h
- text/qlocale_tools.cpp text/qlocale_tools_p.h
- text/qregexp.cpp text/qregexp.h
- text/qstring.cpp text/qstring.h
- text/qstring_compat.cpp
- text/qstringalgorithms.h text/qstringalgorithms_p.h
- text/qstringbuilder.cpp text/qstringbuilder.h
- text/qstringconverter.cpp text/qstringconverter.h text/qstringconverter_p.h
- text/qstringiterator_p.h
- text/qstringlist.cpp text/qstringlist.h
- text/qstringliteral.h
- text/qstringmatcher.h
- text/qstringtokenizer.cpp text/qstringtokenizer.h
- text/qstringview.cpp text/qstringview.h
- text/qtextboundaryfinder.cpp text/qtextboundaryfinder.h
- text/qunicodetables_p.h
- text/qunicodetools.cpp text/qunicodetools_p.h
- text/qvsnprintf.cpp
- thread/qmutex.h
- thread/qreadwritelock.h
- thread/qrunnable.cpp thread/qrunnable.h
- thread/qthread.cpp thread/qthread.h
- thread/qthreadstorage.h
- thread/qwaitcondition.h thread/qwaitcondition_p.h
- time/qcalendar.cpp time/qcalendar.h
- time/qcalendarbackend_p.h
- time/qcalendarmath_p.h
- time/qdatetime.cpp time/qdatetime.h time/qdatetime_p.h
- time/qgregoriancalendar.cpp time/qgregoriancalendar_p.h
- time/qjuliancalendar.cpp time/qjuliancalendar_p.h
- time/qmilankoviccalendar.cpp time/qmilankoviccalendar_p.h
- time/qromancalendar.cpp time/qromancalendar_p.h
- time/qromancalendar_data_p.h
- tools/qalgorithms.h
- tools/qarraydata.cpp tools/qarraydata.h
- tools/qarraydataops.h
- tools/qarraydatapointer.h
- tools/qbitarray.cpp tools/qbitarray.h
- tools/qcache.h
- tools/qcontainerfwd.h
- tools/qcontainertools_impl.h
- tools/qcontiguouscache.cpp tools/qcontiguouscache.h
- tools/qcryptographichash.cpp tools/qcryptographichash.h
- tools/qduplicatetracker_p.h
- tools/qflatmap_p.h
- tools/qfreelist.cpp tools/qfreelist_p.h
- tools/qhash.cpp tools/qhash.h
- tools/qhashfunctions.h
- tools/qiterator.h
- tools/qline.cpp tools/qline.h
- tools/qlist.cpp tools/qlist.h
- tools/qmakearray_p.h
- tools/qmap.cpp tools/qmap.h
- tools/qmargins.cpp tools/qmargins.h
- tools/qmessageauthenticationcode.cpp tools/qmessageauthenticationcode.h
- tools/qoffsetstringarray_p.h
- tools/qpair.h
- tools/qpoint.cpp tools/qpoint.h
- tools/qqueue.h
- tools/qrect.cpp tools/qrect.h
- tools/qrefcount.cpp tools/qrefcount.h
- tools/qringbuffer.cpp tools/qringbuffer_p.h
- tools/qscopedpointer.h tools/qscopedpointer_p.h
- tools/qscopedvaluerollback.h
- tools/qscopeguard.h
- tools/qset.h
- tools/qshareddata.cpp tools/qshareddata.h
- tools/qsharedpointer.cpp tools/qsharedpointer.h
- tools/qsharedpointer_impl.h
- tools/qsize.cpp tools/qsize.h
- tools/qstack.h
- tools/qtaggedpointer.h
- tools/qtools_p.h
- tools/qvarlengtharray.h
- tools/qvector.h
- tools/qversionnumber.cpp tools/qversionnumber.h
- DEFINES
- QT_NO_FOREACH
- QT_NO_USING_NAMESPACE
- INCLUDE_DIRECTORIES
- ${PROJECT_BINARY_DIR}/src/corelib/global
- ../3rdparty/md4
- ../3rdparty/md5
- ../3rdparty/sha3
- ../3rdparty/tinycbor/src
- PRECOMPILED_HEADER
- "global/qt_pch.h"
- NO_PCH_SOURCES
- "text/qstring_compat.cpp"
-)
-
-
-qt_add_simd_part(Core SIMD mips_dsp
- SOURCES
- ../gui/painting/qt_mips_asm_dsp_p.h
- text/qstring_mips_dsp_asm.S
-)
-
-if(QT_FEATURE_reduce_relocations AND UNIX AND GCC)
- target_link_options(Core PRIVATE
- "LINKER:--dynamic-list=${CMAKE_CURRENT_LIST_DIR}/QtCore.dynlist")
-endif()
-
-if(ANDROID)
- set_property(TARGET Core APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
- jar/QtAndroid.jar
- )
- set_property(TARGET Core APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES
- plugins/platforms/libplugins_platforms_qtforandroid.so
- )
- set_property(TARGET Core APPEND PROPERTY QT_ANDROID_PERMISSIONS
- android.permission.INTERNET android.permission.WRITE_EXTERNAL_STORAGE
- )
-endif()
-
-#### Keys ignored in scope 1:.:.:corelib.pro:<TRUE>:
-# CMAKE_DISABLED_FEATURES = "$$join(QT_DISABLED_FEATURES, "$$escape_expand(\\n) ")"
-# CMAKE_HOST_DATA_DIR = "$$cmakeRelativePath($$[QT_HOST_DATA/src], $$[QT_INSTALL_PREFIX])"
-# CMAKE_INSTALL_DATA_DIR = "$$cmakeRelativePath($$[QT_HOST_DATA], $$[QT_INSTALL_PREFIX])"
-# HOST_BINS = "$$[QT_HOST_BINS]"
-# INSTALLS = "ctest_qt5_module_files" "cmake_qt5_umbrella_module_files"
-# MODULE = "core"
-# MODULE_CONFIG = "moc" "resources"
-# QMAKE_DSYM_DEBUG_SCRIPT = "$$PWD/debug_script.py"
-# QMAKE_PKGCONFIG_VARIABLES = "host_bins" "qt_conf"
-# QMAKE_SUBSTITUTES = "ctest_macros_file" "cmake_umbrella_config_file" "cmake_umbrella_config_module_location" "cmake_umbrella_config_module_location_for_install" "cmake_umbrella_config_version_file" "cmake_extras_mkspec_dir" "cmake_extras_mkspec_dir_for_install"
-# cmake_extras_mkspec_dir.input = "$$PWD/Qt5CoreConfigExtrasMkspecDir.cmake.in"
-# cmake_extras_mkspec_dir.output = "$$DESTDIR/cmake/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake"
-# cmake_extras_mkspec_dir_for_install.input = "$$PWD/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in"
-# cmake_extras_mkspec_dir_for_install.output = "$$DESTDIR/cmake/install/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake"
-# cmake_qt5_umbrella_module_files.files = "$$cmake_umbrella_config_file.output" "$$cmake_umbrella_config_version_file.output" "$$cmake_umbrella_config_module_location_for_install.output"
-# cmake_qt5_umbrella_module_files.path = "$$[QT_INSTALL_LIBS]/cmake/Qt5"
-# cmake_umbrella_config_file.input = "$$PWD/Qt5Config.cmake.in"
-# cmake_umbrella_config_file.output = "$$DESTDIR/cmake/Qt5/Qt5Config.cmake"
-# cmake_umbrella_config_module_location.input = "$$PWD/Qt5ModuleLocation.cmake.in"
-# cmake_umbrella_config_module_location.output = "$$DESTDIR/cmake/Qt5/Qt5ModuleLocation.cmake"
-# cmake_umbrella_config_module_location_for_install.input = "$$PWD/Qt5ModuleLocationForInstall.cmake.in"
-# cmake_umbrella_config_module_location_for_install.output = "$$DESTDIR/cmake/install/Qt5/Qt5ModuleLocation.cmake"
-# cmake_umbrella_config_version_file.input = "$$PWD/../../mkspecs/features/data/cmake/Qt5ConfigVersion.cmake.in"
-# cmake_umbrella_config_version_file.output = "$$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake"
-# ctest_macros_file.CONFIG = "verbatim"
-# ctest_macros_file.input = "$$PWD/Qt5CTestMacros.cmake"
-# ctest_macros_file.output = "$$DESTDIR/cmake/Qt5Core/Qt5CTestMacros.cmake"
-# ctest_qt5_module_files.files = "$$ctest_macros_file.output" "$$cmake_extras_mkspec_dir_for_install.output"
-# ctest_qt5_module_files.path = "$$[QT_INSTALL_LIBS]/cmake/Qt5Core"
-# host_bins.name = "host_bins"
-# host_bins.variable = "HOST_BINS"
-# qt_conf.name = "qt_config"
-# qt_conf.variable = "QT_CONFIG"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 2:.:.:corelib.pro:QT_FEATURE_gc_binaries:
-# MODULE_CONFIG = "gc_binaries"
-
-qt_extend_target(Core CONDITION NOT QT_NAMESPACE_ISEMPTY
- PUBLIC_DEFINES
- QT_NAMESPACE=
-)
-
-qt_extend_target(Core CONDITION ANDROID
- SOURCES
- kernel/qsharedmemory_android.cpp
- kernel/qsystemsemaphore_android.cpp
- DEFINES
- LIBS_SUFFIX="_${CMAKE_SYSTEM_PROCESSOR}.so"
-)
-
-qt_extend_target(Core CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386")
- LINK_OPTIONS
- "/BASE:0x67000000"
-)
-
-#### Keys ignored in scope 6:.:.:corelib.pro:FREEBSD OR OPENBSD:
-# QMAKE_LFLAGS_NOUNDEF = <EMPTY>
-
-qt_extend_target(Core CONDITION QT_FEATURE_animation
- SOURCES
- animation/qabstractanimation.cpp animation/qabstractanimation.h animation/qabstractanimation_p.h
- animation/qanimationgroup.cpp animation/qanimationgroup.h animation/qanimationgroup_p.h
- animation/qparallelanimationgroup.cpp animation/qparallelanimationgroup.h animation/qparallelanimationgroup_p.h
- animation/qpauseanimation.cpp animation/qpauseanimation.h
- animation/qpropertyanimation.cpp animation/qpropertyanimation.h animation/qpropertyanimation_p.h
- animation/qsequentialanimationgroup.cpp animation/qsequentialanimationgroup.h animation/qsequentialanimationgroup_p.h
- animation/qvariantanimation.cpp animation/qvariantanimation.h animation/qvariantanimation_p.h
-)
-
-qt_extend_target(Core CONDITION WIN32
- SOURCES
- global/qoperatingsystemversion_win.cpp global/qoperatingsystemversion_win_p.h
- io/qfilesystemengine_win.cpp
- io/qfsfileengine_win.cpp
- io/qlockfile_win.cpp
- io/qstandardpaths_win.cpp
- io/qstorageinfo_win.cpp
- io/qwindowspipereader.cpp io/qwindowspipereader_p.h
- io/qwindowspipewriter.cpp io/qwindowspipewriter_p.h
- kernel/qcoreapplication_win.cpp
- kernel/qelapsedtimer_win.cpp
- kernel/qeventdispatcher_win.cpp kernel/qeventdispatcher_win_p.h
- kernel/qfunctions_winrt_p.h
- kernel/qsharedmemory_win.cpp
- kernel/qsystemsemaphore_win.cpp
- kernel/qwineventnotifier.cpp kernel/qwineventnotifier.h kernel/qwineventnotifier_p.h
- kernel/qwinregistry.cpp kernel/qwinregistry_p.h
- plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h
- thread/qatomic_msvc.h
- thread/qthread_win.cpp
- DEFINES
- -QT_NO_CAST_TO_ASCII
- LIBRARIES
- advapi32
- kernel32
- netapi32
- ole32
- shell32
- user32
- uuid
- version
- winmm
- ws2_32
- PUBLIC_LIBRARIES
- mpr
- userenv
-)
-
-qt_extend_target(Core CONDITION APPLE
- SOURCES
- global/qoperatingsystemversion_darwin.mm
- io/qfilesystemengine_mac.mm
- io/qstandardpaths_mac.mm
- io/qstorageinfo_mac.cpp
- kernel/qcfsocketnotifier.cpp kernel/qcfsocketnotifier_p.h
- kernel/qcore_foundation.mm
- kernel/qcore_mac.mm kernel/qcore_mac_p.h
- kernel/qcoreapplication_mac.cpp
- kernel/qeventdispatcher_cf.mm kernel/qeventdispatcher_cf_p.h
- LIBRARIES
- ${FWCoreFoundation}
- ${FWFoundation}
-)
-
-qt_extend_target(Core CONDITION MACOS
- LIBRARIES
- ${FWAppKit}
- ${FWApplicationServices}
- ${FWCoreServices}
- ${FWSecurity}
- PUBLIC_LIBRARIES
- ${FWDiskArbitration}
- ${FWIOKit}
-)
-
-qt_extend_target(Core CONDITION INTEGRITY
- LIBRARIES
- ivfs
- net
- posix
- shm_client
- socket
- COMPILE_OPTIONS
- --pending_instantiations=128
-)
-
-#### Keys ignored in scope 14:.:.:corelib.pro:pathIsAbsolute(_ss_CMAKE_HOST_DATA_DIR):
-# CMAKE_HOST_DATA_DIR = "$$[QT_HOST_DATA/src]/"
-# CMAKE_HOST_DATA_DIR_IS_ABSOLUTE = "True"
-
-#### Keys ignored in scope 15:.:.:corelib.pro:pathIsAbsolute(_ss_CMAKE_INSTALL_DATA_DIR):
-# CMAKE_INSTALL_DATA_DIR = "$$[QT_HOST_DATA]/"
-# CMAKE_INSTALL_DATA_DIR_IS_ABSOLUTE = "True"
-
-#### Keys ignored in scope 20:.:global:global/global.pri:QT_CPU_FEATURES__ss_QT_ARCH___contains___f16c:
-# f16c_cxx = "true"
-
-#### Keys ignored in scope 22:.:global:global/global.pri:CLANG OR intel_icl OR ICC:
-# f16c_cxx = "false"
-
-#### Keys ignored in scope 24:.:global:global/global.pri:GCC AND f16c AND x86SimdAlways:
-# f16c_cxx = "true"
-
-#### Keys ignored in scope 26:.:global:global/global.pri:MSVC AND QT_CPU_FEATURES__ss_QT_ARCH___contains___avx:
-# f16c_cxx = "true"
-
-#### Keys ignored in scope 27:.:global:global/global.pri:else:
-# f16c_cxx = "false"
-
-qt_extend_target(Core CONDITION _ss_f16c_cxx
- DEFINES
- QFLOAT16_INCLUDE_FAST
-)
-
-if(NOT _ss_f16c_cxx)
- qt_add_simd_part(Core SIMD f16c
- SOURCES
- global/qfloat16_f16c.c
- )
-endif()
-
-qt_extend_target(Core CONDITION NOT CMAKE_CROSSCOMPILING AND NOT _x_-armcc_x_ AND NOT static AND (hurd_x_ OR linux_x_)
- DEFINES
- ELF_INTERPRETER=\\\"=Creadelf-l/bin/ls|perl-n-e\'['quote', ['if', ['/program', 'interpreter:', ['.*'], ']/'], '{', 'print', '$1;', '}']]\'\\\"
- LINK_OPTIONS
- "-Wl,-e,qt_core_boilerplate"
-)
-
-qt_extend_target(Core CONDITION LINUX AND NOT static
- SOURCES
- global/minimum-linux_p.h
-)
-
-#### Keys ignored in scope 34:.:global:global/global.pri:precompile_header:
-# NO_PCH_ASM = "global/minimum-linux.S"
-# QMAKE_EXTRA_COMPILERS = "no_pch_assembler"
-# no_pch_assembler.commands = "$$QMAKE_CC" "-c" "$(CFLAGS)" "$(INCPATH)" "${QMAKE_FILE_IN}" "-o" "${QMAKE_FILE_OUT}"
-# no_pch_assembler.dependency_type = "TYPE_C"
-# no_pch_assembler.input = "NO_PCH_ASM"
-# no_pch_assembler.name = "compiling[no_pch]" "${QMAKE_FILE_IN}"
-# no_pch_assembler.output = "${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${firstQMAKE_EXT_OBJ}"
-
-#### Keys ignored in scope 35:.:global:global/global.pri:silent:
-# no_pch_assembler.commands = "@echo" "compiling[no_pch]" "${QMAKE_FILE_IN}" "&&"
-
-qt_extend_target(Core CONDITION LINUX AND NOT precompile_header AND NOT static
- SOURCES
- global/minimum-linux.S
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_slog2
- LIBRARIES
- Slog2::Slog2
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_journald
- LIBRARIES
- PkgConfig::Libsystemd
-)
-
-#### Keys ignored in scope 39:.:global:global/global.pri:GCC AND ltcg:
-# QMAKE_EXTRA_COMPILERS = "versiontagging_compiler"
-# versiontagging_compiler.commands = "$$QMAKE_CXX" "-c" "$(CXXFLAGS)" "$(INCPATH)" "-fno-lto" "-o" "${QMAKE_FILE_OUT}" "${QMAKE_FILE_IN}"
-# versiontagging_compiler.dependency_type = "TYPE_C"
-# versiontagging_compiler.input = "VERSIONTAGGING_SOURCES"
-# versiontagging_compiler.name = "compiling[versiontagging]" "${QMAKE_FILE_IN}"
-# versiontagging_compiler.output = "${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${firstQMAKE_EXT_OBJ}"
-# versiontagging_compiler.variable_out = "OBJECTS"
-
-#### Keys ignored in scope 40:.:global:global/global.pri:silent:
-# versiontagging_compiler.commands = "@echo" "compiling[versiontagging]" "${QMAKE_FILE_IN}" "&&"
-
-qt_extend_target(Core CONDITION NOT GCC OR NOT ltcg
- SOURCES
- global/qversiontagging.cpp
-)
-
-qt_extend_target(Core CONDITION UNIX
- SOURCES
- io/qfilesystemengine_unix.cpp
- io/qfilesystemiterator_unix.cpp
- io/qfsfileengine_unix.cpp
- io/qlockfile_unix.cpp
- kernel/qcore_unix.cpp kernel/qcore_unix_p.h
- kernel/qeventdispatcher_unix.cpp kernel/qeventdispatcher_unix_p.h
- kernel/qpoll_p.h
- kernel/qtimerinfo_unix.cpp kernel/qtimerinfo_unix_p.h
- thread/qthread_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_thread
- SOURCES
- thread/qatomic.cpp thread/qatomic.h
- thread/qatomic_bootstrap.h
- thread/qatomic_cxx11.h
- thread/qbasicatomic.h
- thread/qfutex_p.h
- thread/qgenericatomic.h
- thread/qlocking_p.h
- thread/qmutex.cpp thread/qmutex_p.h
- thread/qorderedmutexlocker_p.h
- thread/qreadwritelock.cpp thread/qreadwritelock_p.h
- thread/qsemaphore.cpp thread/qsemaphore.h
- thread/qthread_p.h
- thread/qthreadpool.cpp thread/qthreadpool.h thread/qthreadpool_p.h
- thread/qthreadstorage.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
- SOURCES
- thread/qmutex_win.cpp
- thread/qwaitcondition_win.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX
- SOURCES
- thread/qwaitcondition_unix.cpp
-)
-
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_thread
- SOURCES
- thread/qmutex_mac.cpp
-)
-
-qt_extend_target(Core CONDITION LINUX AND QT_FEATURE_thread
- SOURCES
- thread/qmutex_linux.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX AND NOT APPLE AND NOT LINUX
- SOURCES
- thread/qmutex_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_future
- SOURCES
- thread/qexception.cpp thread/qexception.h
- thread/qfuture.h
- thread/qfuture_impl.h
- thread/qfutureinterface.cpp thread/qfutureinterface.h thread/qfutureinterface_p.h
- thread/qfuturesynchronizer.h
- thread/qfuturewatcher.cpp thread/qfuturewatcher.h thread/qfuturewatcher_p.h
- thread/qpromise.h
- thread/qresultstore.cpp thread/qresultstore.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_std_atomic64
- PUBLIC_LIBRARIES
- WrapAtomic::WrapAtomic
-)
-
-qt_extend_target(Core CONDITION ICC
- COMPILE_OPTIONS
- -fp-model
- strict
-)
-
-qt_extend_target(Core CONDITION MSVC
- SOURCES
- tools/qvector_msvc.cpp
- NO_PCH_SOURCES
- "tools/qvector_msvc.cpp"
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_system_zlib
- LIBRARIES
- ZLIB::ZLIB
-)
-
-qt_extend_target(Core CONDITION NOT QT_FEATURE_system_zlib
- SOURCES
- ../3rdparty/zlib/src/adler32.c
- ../3rdparty/zlib/src/compress.c
- ../3rdparty/zlib/src/crc32.c
- ../3rdparty/zlib/src/deflate.c
- ../3rdparty/zlib/src/gzclose.c
- ../3rdparty/zlib/src/gzlib.c
- ../3rdparty/zlib/src/gzread.c
- ../3rdparty/zlib/src/gzwrite.c
- ../3rdparty/zlib/src/infback.c
- ../3rdparty/zlib/src/inffast.c
- ../3rdparty/zlib/src/inflate.c
- ../3rdparty/zlib/src/inftrees.c
- ../3rdparty/zlib/src/trees.c
- ../3rdparty/zlib/src/uncompr.c
- ../3rdparty/zlib/src/zutil.c
- INCLUDE_DIRECTORIES
- ../3rdparty/zlib/src
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_commandlineparser
- SOURCES
- tools/qcommandlineoption.cpp tools/qcommandlineoption.h
- tools/qcommandlineparser.cpp tools/qcommandlineparser.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_system_doubleconversion
- LIBRARIES
- WrapDoubleConversion::WrapDoubleConversion
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_doubleconversion AND NOT QT_FEATURE_system_doubleconversion
- SOURCES
- ../3rdparty/double-conversion/bignum.cc ../3rdparty/double-conversion/bignum.h
- ../3rdparty/double-conversion/bignum-dtoa.cc ../3rdparty/double-conversion/bignum-dtoa.h
- ../3rdparty/double-conversion/cached-powers.cc ../3rdparty/double-conversion/cached-powers.h
- ../3rdparty/double-conversion/diy-fp.cc ../3rdparty/double-conversion/diy-fp.h
- ../3rdparty/double-conversion/double-conversion.cc
- ../3rdparty/double-conversion/fast-dtoa.cc ../3rdparty/double-conversion/fast-dtoa.h
- ../3rdparty/double-conversion/fixed-dtoa.cc ../3rdparty/double-conversion/fixed-dtoa.h
- ../3rdparty/double-conversion/ieee.h
- ../3rdparty/double-conversion/include/double-conversion/double-conversion.h
- ../3rdparty/double-conversion/include/double-conversion/utils.h
- ../3rdparty/double-conversion/strtod.cc ../3rdparty/double-conversion/strtod.h
- INCLUDE_DIRECTORIES
- ../3rdparty/double-conversion/..
- ../3rdparty/double-conversion/include
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_easingcurve
- SOURCES
- tools/qeasingcurve.cpp tools/qeasingcurve.h
- tools/qtimeline.cpp tools/qtimeline.h
-)
-
-qt_extend_target(Core CONDITION UNIX AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORKS AND NOT WASM AND (NOT ICC OR NOT MACOS)
- LIBRARIES
- m
-)
-
-qt_extend_target(Core CONDITION APPLE AND NOT NACL
- SOURCES
- kernel/qelapsedtimer_mac.cpp
- text/qlocale_mac.mm
-)
-
-qt_extend_target(Core CONDITION UNIX AND (NACL OR NOT APPLE)
- SOURCES
- text/qlocale_unix.cpp
-)
-
-qt_extend_target(Core CONDITION WIN32 AND (NACL OR NOT APPLE)
- SOURCES
- text/qlocale_win.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_icu
- SOURCES
- text/qcollator_icu.cpp
- text/qlocale_icu.cpp
- LIBRARIES
- ICU::i18n ICU::uc ICU::data
-)
-
-qt_extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu
- SOURCES
- text/qcollator_win.cpp
-)
-
-qt_extend_target(Core CONDITION MACOS AND NOT QT_FEATURE_icu
- SOURCES
- text/qcollator_macx.cpp
-)
-
-qt_extend_target(Core CONDITION UNIX AND NOT MACOS AND NOT QT_FEATURE_icu
- SOURCES
- text/qcollator_posix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_regularexpression
- SOURCES
- text/qregularexpression.cpp text/qregularexpression.h
- LIBRARIES
- WrapPCRE2::WrapPCRE2
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_hijricalendar
- SOURCES
- time/qhijricalendar.cpp time/qhijricalendar_p.h
- time/qhijricalendar_data_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_islamiccivilcalendar
- SOURCES
- time/qislamiccivilcalendar.cpp time/qislamiccivilcalendar_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_jalalicalendar
- SOURCES
- time/qjalalicalendar.cpp time/qjalalicalendar_p.h
- time/qjalalicalendar_data_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_timezone
- SOURCES
- time/qtimezone.cpp time/qtimezone.h
- time/qtimezoneprivate.cpp time/qtimezoneprivate_p.h
- time/qtimezoneprivate_data_p.h
-)
-
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_timezone AND NOT NACL
- SOURCES
- time/qtimezoneprivate_mac.mm
-)
-
-qt_extend_target(Core CONDITION ANDROID AND QT_FEATURE_timezone AND NOT ANDROID_EMBEDDED AND (NACL OR NOT APPLE)
- SOURCES
- time/qtimezoneprivate_android.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_timezone AND UNIX AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
- SOURCES
- time/qtimezoneprivate_tz.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_icu AND QT_FEATURE_timezone AND UNIX AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
- SOURCES
- time/qtimezoneprivate_icu.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_icu AND QT_FEATURE_timezone AND WIN32 AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
- SOURCES
- time/qtimezoneprivate_icu.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_timezone AND WIN32 AND NOT QT_FEATURE_icu AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
- SOURCES
- time/qtimezoneprivate_win.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_datetimeparser
- SOURCES
- time/qdatetimeparser.cpp time/qdatetimeparser_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_zstd
- LIBRARIES
- ZSTD::ZSTD
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher
- SOURCES
- io/qfilesystemwatcher.cpp io/qfilesystemwatcher.h io/qfilesystemwatcher_p.h
- io/qfilesystemwatcher_polling.cpp io/qfilesystemwatcher_polling_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND WIN32
- SOURCES
- io/qfilesystemwatcher_win.cpp io/qfilesystemwatcher_win_p.h
-)
-
-qt_extend_target(Core CONDITION MACOS AND QT_FEATURE_filesystemwatcher
- SOURCES
- io/qfilesystemwatcher_fsevents.mm io/qfilesystemwatcher_fsevents_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND QT_FEATURE_inotify AND UNIX AND NOT MACOS
- SOURCES
- io/qfilesystemwatcher_inotify.cpp io/qfilesystemwatcher_inotify_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND UNIX AND NOT MACOS AND NOT QT_FEATURE_inotify AND (APPLE OR FREEBSD OR NETBSD OR OPENBSD)
- SOURCES
- io/qfilesystemwatcher_kqueue.cpp io/qfilesystemwatcher_kqueue_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_processenvironment
- SOURCES
- io/qprocess.cpp io/qprocess.h io/qprocess_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_processenvironment AND WIN32
- SOURCES
- io/qprocess_win.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_processenvironment AND UNIX
- SOURCES
- io/qprocess_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_settings
- SOURCES
- io/qsettings.cpp io/qsettings.h io/qsettings_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_settings AND WIN32
- SOURCES
- io/qsettings_win.cpp
-)
-
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_settings AND NOT NACL
- SOURCES
- io/qsettings_mac.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_settings AND WASM
- SOURCES
- io/qsettings_wasm.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemiterator AND WIN32
- SOURCES
- io/qfilesystemiterator_win.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_process AND UNIX
- SOURCES
- ../3rdparty/forkfd/forkfd.h
- io/forkfd_qt.cpp
- INCLUDE_DIRECTORIES
- ../3rdparty/forkfd
-)
-
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_processenvironment
- SOURCES
- io/qprocess_darwin.mm
-)
-
-qt_extend_target(Core CONDITION APPLE AND NOT MACOS
- PUBLIC_LIBRARIES
- ${FWMobileCoreServices}
-)
-
-qt_extend_target(Core CONDITION ANDROID AND NOT ANDROID_EMBEDDED
- SOURCES
- io/qstandardpaths_android.cpp
- io/qstorageinfo_unix.cpp
- kernel/qjni.cpp kernel/qjni_p.h
- kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h
- kernel/qjnionload.cpp
-)
-
-qt_extend_target(Core CONDITION HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)
- SOURCES
- io/qstandardpaths_haiku.cpp
- io/qstorageinfo_unix.cpp
- PUBLIC_LIBRARIES
- be
-)
-
-qt_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)
- SOURCES
- io/qstandardpaths_unix.cpp
- io/qstorageinfo_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_proxymodel
- SOURCES
- itemmodels/qabstractproxymodel.cpp itemmodels/qabstractproxymodel.h itemmodels/qabstractproxymodel_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_concatenatetablesproxymodel AND QT_FEATURE_proxymodel
- SOURCES
- itemmodels/qconcatenatetablesproxymodel.cpp itemmodels/qconcatenatetablesproxymodel.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_identityproxymodel AND QT_FEATURE_proxymodel
- SOURCES
- itemmodels/qidentityproxymodel.cpp itemmodels/qidentityproxymodel.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_sortfilterproxymodel
- SOURCES
- itemmodels/qsortfilterproxymodel.cpp itemmodels/qsortfilterproxymodel.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_transposeproxymodel
- SOURCES
- itemmodels/qtransposeproxymodel.cpp itemmodels/qtransposeproxymodel.h itemmodels/qtransposeproxymodel_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_stringlistmodel
- SOURCES
- itemmodels/qstringlistmodel.cpp itemmodels/qstringlistmodel.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_library
- SOURCES
- plugin/qelfparser_p.cpp plugin/qelfparser_p.h
- plugin/qlibrary.cpp plugin/qlibrary.h plugin/qlibrary_p.h
- plugin/qmachparser.cpp plugin/qmachparser_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_library AND UNIX
- SOURCES
- plugin/qlibrary_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_library AND WIN32
- SOURCES
- plugin/qlibrary_win.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_dlopen AND QT_FEATURE_library
- LIBRARIES
- ${CMAKE_DL_LIBS}
-)
-
-qt_extend_target(Core CONDITION APPLE AND (IOS OR TVOS)
- LIBRARIES
- ${FWUIKit}
-)
-
-qt_extend_target(Core CONDITION WATCHOS
- LIBRARIES
- ${FWWatchKit}
-)
-
-qt_extend_target(Core CONDITION NACL
- SOURCES
- kernel/qfunctions_nacl.cpp kernel/qfunctions_nacl.h
-)
-
-qt_extend_target(Core CONDITION INTEGRITY OR (NACL AND UNIX) OR (UNIX AND NOT APPLE)
- SOURCES
- kernel/qelapsedtimer_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_poll_select AND UNIX
- SOURCES
- kernel/qpoll.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_glib AND UNIX
- SOURCES
- kernel/qeventdispatcher_glib.cpp kernel/qeventdispatcher_glib_p.h
- LIBRARIES
- GLIB2::GLIB2
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_clock_gettime AND UNIX
- LIBRARIES
- WrapRt::WrapRt
-)
-
-qt_extend_target(Core CONDITION UNIX AND NOT ANDROID
- SOURCES
- kernel/qsharedmemory_posix.cpp
- kernel/qsharedmemory_systemv.cpp
- kernel/qsharedmemory_unix.cpp
- kernel/qsystemsemaphore_posix.cpp
- kernel/qsystemsemaphore_systemv.cpp
- kernel/qsystemsemaphore_unix.cpp
-)
-
-qt_extend_target(Core CONDITION VXWORKS
- SOURCES
- kernel/qfunctions_vxworks.cpp kernel/qfunctions_vxworks.h
-)
-
-qt_extend_target(Core CONDITION QNX AND QT_FEATURE_qqnx_pps
- SOURCES
- kernel/qppsattribute.cpp kernel/qppsattribute_p.h
- kernel/qppsattributeprivate_p.h
- kernel/qppsobject.cpp kernel/qppsobject_p.h
- kernel/qppsobjectprivate_p.h
- LIBRARIES
- PPS::PPS
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_cborstreamreader
- SOURCES
- serialization/qcborstreamreader.cpp serialization/qcborstreamreader.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_cborstreamwriter
- SOURCES
- serialization/qcborstreamwriter.cpp serialization/qcborstreamwriter.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_binaryjson
- SOURCES
- serialization/qbinaryjson.cpp serialization/qbinaryjson_p.h
- serialization/qbinaryjsonarray.cpp serialization/qbinaryjsonarray_p.h
- serialization/qbinaryjsonobject.cpp serialization/qbinaryjsonobject_p.h
- serialization/qbinaryjsonvalue.cpp serialization/qbinaryjsonvalue_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_qeventtransition
- SOURCES
- statemachine/qeventtransition.cpp statemachine/qeventtransition.h statemachine/qeventtransition_p.h
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_mimetype
- SOURCES
- mimetypes/qmimedatabase.cpp mimetypes/qmimedatabase.h mimetypes/qmimedatabase_p.h
- mimetypes/qmimeglobpattern.cpp mimetypes/qmimeglobpattern_p.h
- mimetypes/qmimemagicrule.cpp mimetypes/qmimemagicrule_p.h
- mimetypes/qmimemagicrulematcher.cpp mimetypes/qmimemagicrulematcher_p.h
- mimetypes/qmimeprovider.cpp mimetypes/qmimeprovider_p.h
- mimetypes/qmimetype.cpp mimetypes/qmimetype.h mimetypes/qmimetype_p.h
- mimetypes/qmimetypeparser.cpp mimetypes/qmimetypeparser_p.h
-)
-
-#### Keys ignored in scope 180:.:mimetypes:mimetypes/mimetypes.pri:QT_FEATURE_mimetype:
-# MIME_DATABASE = "mimetypes/mime/packages/freedesktop.org.xml"
-# OTHER_FILES = "$$MIME_DATABASE"
-
-qt_extend_target(Core CONDITION QT_FEATURE_mimetype AND QT_FEATURE_mimetype_database
- INCLUDE_DIRECTORIES
- .rcc
-)
-
-#### Keys ignored in scope 181:.:mimetypes:mimetypes/mimetypes.pri:QT_FEATURE_mimetype_database:
-# QMAKE_EXTRA_COMPILERS = "mimedb"
-# mimedb.commands = "${QMAKE_FILE_IN}" ">" "${QMAKE_FILE_OUT}"
-# mimedb.depends = "$$PWD/mime/generate.pl"
-# mimedb.input = "MIME_DATABASE"
-# mimedb.output = "$$outpath/qmimeprovider_database.cpp"
-# mimedb.variable_out = "INCLUDED_SOURCES"
-
-#### Keys ignored in scope 182:.:mimetypes:mimetypes/mimetypes.pri:ANDROID:
-# outpath = "$$outpath/$${QT_ARCH}"
-
-#### Keys ignored in scope 184:.:mimetypes:mimetypes/mimetypes.pri:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# outpath = "$$outpath/debug"
-
-#### Keys ignored in scope 185:.:mimetypes:mimetypes/mimetypes.pri:else:
-# outpath = "$$outpath/release"
-
-#### Keys ignored in scope 186:.:mimetypes:mimetypes/mimetypes.pri:MAKEFILE_GENERATOR___equals___MSVC.NET OR MAKEFILE_GENERATOR___equals___MSBUILD OR QMAKE_SH_ISEMPTY:
-# mimedb.commands = "cmd" "/c" "$$shell_path($$PWD/mime/generate.bat)"
-# mimedb.depends = "$$PWD/mime/generate.bat" "$$PWD/mime/hexdump.ps1"
-
-#### Keys ignored in scope 187:.:mimetypes:mimetypes/mimetypes.pri:else:
-# mimedb.commands = "perl" "$${mimedb.depends}"
-
-#### Keys ignored in scope 188:.:mimetypes:mimetypes/mimetypes.pri:QT_FEATURE_zstd:
-# mimedb.commands = "--zstd"
-
-qt_extend_target(Core CONDITION WASM
- SOURCES
- platform/wasm/qstdweb.cpp platform/wasm/qstdweb_p.h
-)
-
-
-qt_create_tracepoints(Core qtcore.tracepoints)
-qt_add_docs(Core
- doc/qtcore.qdocconf
-)
-
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 9d6eb3d908..ce3def3cd6 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -1,63 +1,109 @@
-# Generated from corelib.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
-# special case begin
-qt_find_package(Threads PROVIDED_TARGETS Threads::Threads)
qt_find_package(WrapPCRE2 PROVIDED_TARGETS WrapPCRE2::WrapPCRE2)
+qt_find_package(WrapZLIB PROVIDED_TARGETS WrapZLIB::WrapZLIB)
-
-# compute the reverse relative path from QtCoreConfigExtras to the install prefix
-# this is used in QtCoreConfigExtras to make its install paths relocatable
-if(QT_WILL_INSTALL)
- get_filename_component(_clean_prefix
- "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${QT_CONFIG_INSTALL_DIR}" ABSOLUTE)
-else()
- get_filename_component(_clean_prefix "${QT_CONFIG_BUILD_DIR}" ABSOLUTE)
+if(ANDROID)
+ set(corelib_extra_cmake_files
+ "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidMacros.cmake")
+endif()
+if(WASM)
+ set(corelib_extra_cmake_files
+ "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}WasmMacros.cmake")
endif()
-file(RELATIVE_PATH QT_INVERSE_CONFIG_INSTALL_DIR
- "${_clean_prefix}" "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
-
-# special case end
#####################################################################
## Core Module:
#####################################################################
-qt_add_module(Core
- GENERATE_METATYPES
+qt_internal_add_module(Core
QMAKE_MODULE_CONFIG moc resources
+ NO_GENERATE_METATYPES # metatypes are extracted manually below
EXCEPTIONS
SOURCES
+ # Keep these .cpp files in the first and in the order they are so their
+ # static initialization order is retained
+ global/qsimd.cpp global/qsimd.h global/qsimd_p.h
+ tools/qhash.cpp tools/qhash.h
+
+ # Keep the rest alphabetical
+ compat/removed_api.cpp
global/archdetect.cpp
+ global/qassert.cpp global/qassert.h
+ global/qcompare_impl.h
+ global/qcompare.cpp global/qcompare.h
+ global/qcomparehelpers.h
global/qcompilerdetection.h
+ global/qconstructormacros.h
+ global/qcontainerinfo.h
+ global/qdarwinhelpers.h
global/qendian.cpp global/qendian.h global/qendian_p.h
+ global/qexceptionhandling.cpp global/qexceptionhandling.h
global/qflags.h
global/qfloat16.cpp global/qfloat16.h
- global/qglobal.cpp global/qglobal.h
+ global/qforeach.h
+ global/qfunctionpointer.h
+ global/qglobal.cpp global/qglobal.h global/qglobal_p.h
global/qglobalstatic.h
global/qhooks.cpp global/qhooks_p.h
- global/qisenum.h
- global/qlibraryinfo.cpp global/qlibraryinfo.h
- global/qlogging.cpp global/qlogging.h
- global/qmalloc.cpp
- global/qmemory_p.h
- # global/qnamespace.h # special case
+ global/qlibraryinfo.cpp global/qlibraryinfo.h global/qlibraryinfo_p.h
+ global/qlogging.cpp global/qlogging.h global/qlogging_p.h
+ global/qmalloc.cpp global/qmalloc.h
+ global/qminmax.h
+ global/qnamespace.h # this header is specified on purpose so AUTOMOC processes it
+ global/qnativeinterface.h global/qnativeinterface_p.h
global/qnumeric.cpp global/qnumeric.h global/qnumeric_p.h
global/qoperatingsystemversion.cpp global/qoperatingsystemversion.h global/qoperatingsystemversion_p.h
+ global/qoverload.h
global/qprocessordetection.h
global/qrandom.cpp global/qrandom.h global/qrandom_p.h
- global/qsimd.cpp global/qsimd.h global/qsimd_p.h
- global/qsysinfo.h
+ global/qswap.h
+ global/qsysinfo.cpp global/qsysinfo.h
global/qsystemdetection.h
+ global/qtclasshelpermacros.h
+ global/qtconfiginclude.h
+ global/qtconfigmacros.h
+ global/qtdeprecationmarkers.h
+ global/qtenvironmentvariables.cpp global/qtenvironmentvariables.h
+ global/qtenvironmentvariables_p.h
+ global/qtnoop.h
+ global/qtpreprocessorsupport.h
+ global/qtrace_p.h
+ global/qtresource.h
+ global/qtsymbolmacros.h
+ global/qttranslation.h
+ global/qttypetraits.h
+ global/qtversionchecks.h
+ global/qtversion.h
global/qtypeinfo.h
- global/qtypetraits.h
- global/qversiontagging.cpp global/qversiontagging.h # special case
+ global/qtypes.cpp global/qtypes.h
+ global/qvolatile_p.h
+ global/q20algorithm.h
+ global/q20chrono.h
+ global/q20functional.h
+ global/q20iterator.h
+ global/q20map.h
+ global/q20memory.h
+ global/q20type_traits.h
+ global/q20vector.h
+ global/q23functional.h
+ global/q23utility.cpp # remove once we have a user that tests this
+ global/q23utility.h
+ global/qxpfunctional.h
+ global/qxptype_traits.h
+ global/qversiontagging.h
+ ipc/qsharedmemory.cpp ipc/qsharedmemory.h ipc/qsharedmemory_p.h
+ ipc/qsystemsemaphore.cpp ipc/qsystemsemaphore.h ipc/qsystemsemaphore_p.h
+ ipc/qtipccommon.cpp ipc/qtipccommon.h ipc/qtipccommon_p.h
io/qabstractfileengine.cpp io/qabstractfileengine_p.h
io/qbuffer.cpp io/qbuffer.h
io/qdataurl.cpp io/qdataurl_p.h
io/qdebug.cpp io/qdebug.h io/qdebug_p.h
io/qdir.cpp io/qdir.h io/qdir_p.h
+ io/qdirlisting.cpp io/qdirlisting.h io/qdirentryinfo_p.h
io/qdiriterator.cpp io/qdiriterator.h
- io/qfile.cpp io/qfile.h
+ io/qfile.cpp io/qfile.h io/qfile_p.h
io/qfiledevice.cpp io/qfiledevice.h io/qfiledevice_p.h
io/qfileinfo.cpp io/qfileinfo.h io/qfileinfo_p.h
io/qfileselector.cpp io/qfileselector.h io/qfileselector_p.h
@@ -68,14 +114,15 @@ qt_add_module(Core
io/qfsfileengine.cpp io/qfsfileengine_p.h
io/qfsfileengine_iterator.cpp io/qfsfileengine_iterator_p.h
io/qiodevice.cpp io/qiodevice.h io/qiodevice_p.h
+ io/qiodevicebase.h
io/qipaddress.cpp io/qipaddress_p.h
io/qlockfile.cpp io/qlockfile.h io/qlockfile_p.h
io/qloggingcategory.cpp io/qloggingcategory.h
io/qloggingregistry.cpp io/qloggingregistry_p.h
io/qnoncontiguousbytedevice.cpp io/qnoncontiguousbytedevice_p.h
- io/qresource.cpp io/qresource_p.h
+ io/qresource.cpp io/qresource.h io/qresource_p.h
io/qresource_iterator.cpp io/qresource_iterator_p.h
- io/qsavefile.cpp io/qsavefile.h
+ io/qsavefile.cpp io/qsavefile.h io/qsavefile_p.h
io/qstandardpaths.cpp io/qstandardpaths.h
io/qstorageinfo.cpp io/qstorageinfo.h io/qstorageinfo_p.h
io/qtemporarydir.cpp io/qtemporarydir.h
@@ -84,44 +131,49 @@ qt_add_module(Core
io/qurlidna.cpp
io/qurlquery.cpp io/qurlquery.h
io/qurlrecode.cpp
- itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
- itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_p.h
+ io/qzipreader_p.h io/qzipwriter_p.h io/qzip.cpp
kernel/qabstracteventdispatcher.cpp kernel/qabstracteventdispatcher.h kernel/qabstracteventdispatcher_p.h
kernel/qabstractnativeeventfilter.cpp kernel/qabstractnativeeventfilter.h
+ kernel/qapplicationstatic.h
+ kernel/qassociativeiterable.cpp kernel/qassociativeiterable.h
kernel/qbasictimer.cpp kernel/qbasictimer.h
+ kernel/qbindingstorage.h
+ kernel/qchronotimer.cpp kernel/qchronotimer.h
kernel/qcoreapplication.cpp kernel/qcoreapplication.h kernel/qcoreapplication_p.h
+ kernel/qcoreapplication_platform.h
kernel/qcorecmdlineargs_p.h
- kernel/qcoreevent.cpp kernel/qcoreevent.h
- kernel/qcoreglobaldata.cpp kernel/qcoreglobaldata_p.h
- kernel/qdeadlinetimer.cpp kernel/qdeadlinetimer.h kernel/qdeadlinetimer_p.h
+ kernel/qcoreevent.cpp kernel/qcoreevent.h kernel/qcoreevent_p.h
+ kernel/qdeadlinetimer.cpp kernel/qdeadlinetimer.h
kernel/qelapsedtimer.cpp kernel/qelapsedtimer.h
- kernel/qeventloop.cpp kernel/qeventloop.h
+ kernel/qeventloop.cpp kernel/qeventloop.h kernel/qeventloop_p.h
kernel/qfunctions_p.h
+ kernel/qiterable.cpp kernel/qiterable.h kernel/qiterable_p.h
kernel/qmath.cpp kernel/qmath.h
+ kernel/qmetacontainer.cpp kernel/qmetacontainer.h
kernel/qmetaobject.cpp kernel/qmetaobject.h kernel/qmetaobject_p.h
kernel/qmetaobject_moc_p.h
kernel/qmetaobjectbuilder.cpp kernel/qmetaobjectbuilder_p.h
kernel/qmetatype.cpp kernel/qmetatype.h kernel/qmetatype_p.h
- kernel/qmetatypeswitcher_p.h
kernel/qmimedata.cpp kernel/qmimedata.h
- # kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h # special case
+ kernel/qtmetamacros.h kernel/qtmochelpers.h
+ kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h kernel/qobject_p_p.h
kernel/qobject_impl.h
kernel/qobjectcleanuphandler.cpp kernel/qobjectcleanuphandler.h
kernel/qobjectdefs.h
kernel/qobjectdefs_impl.h
- kernel/qpointer.cpp kernel/qpointer.h
+ kernel/qpointer.h
kernel/qproperty.cpp kernel/qproperty.h kernel/qproperty_p.h
- kernel/qpropertybinding.cpp kernel/qpropertybinding_p.h
kernel/qpropertyprivate.h
- kernel/qsharedmemory.cpp kernel/qsharedmemory.h kernel/qsharedmemory_p.h
+ kernel/qsequentialiterable.cpp kernel/qsequentialiterable.h
kernel/qsignalmapper.cpp kernel/qsignalmapper.h
kernel/qsocketnotifier.cpp kernel/qsocketnotifier.h
kernel/qsystemerror.cpp kernel/qsystemerror_p.h
- kernel/qsystemsemaphore.cpp kernel/qsystemsemaphore.h kernel/qsystemsemaphore_p.h
kernel/qtestsupport_core.cpp kernel/qtestsupport_core.h
- kernel/qtimer.cpp kernel/qtimer.h
+ kernel/qsingleshottimer_p.h
+ kernel/qtimer.cpp kernel/qtimer.h kernel/qtimer_p.h
kernel/qtranslator.cpp kernel/qtranslator.h kernel/qtranslator_p.h
kernel/qvariant.cpp kernel/qvariant.h kernel/qvariant_p.h
+ kernel/qvariantmap.h kernel/qvarianthash.h kernel/qvariantlist.h
plugin/qfactoryinterface.cpp plugin/qfactoryinterface.h
plugin/qfactoryloader.cpp plugin/qfactoryloader_p.h
plugin/qplugin.h plugin/qplugin_p.h
@@ -143,32 +195,29 @@ qt_add_module(Core
serialization/qjsonvalue.cpp serialization/qjsonvalue.h
serialization/qjsonwriter.cpp serialization/qjsonwriter_p.h
serialization/qtextstream.cpp serialization/qtextstream.h serialization/qtextstream_p.h
- serialization/qxmlstream.cpp serialization/qxmlstream.h serialization/qxmlstream_p.h
serialization/qxmlutils.cpp serialization/qxmlutils_p.h
- statemachine/qabstractstate.cpp statemachine/qabstractstate.h statemachine/qabstractstate_p.h
- statemachine/qabstracttransition.cpp statemachine/qabstracttransition.h statemachine/qabstracttransition_p.h
- statemachine/qfinalstate.cpp statemachine/qfinalstate.h statemachine/qfinalstate_p.h
- statemachine/qhistorystate.cpp statemachine/qhistorystate.h statemachine/qhistorystate_p.h
- statemachine/qsignaleventgenerator_p.h
- statemachine/qsignaltransition.cpp statemachine/qsignaltransition.h statemachine/qsignaltransition_p.h
- statemachine/qstate.cpp statemachine/qstate.h statemachine/qstate_p.h
- statemachine/qstatemachine.cpp statemachine/qstatemachine.h statemachine/qstatemachine_p.h
- text/qbytearray.cpp text/qbytearray.h text/qbytearray_p.h
+ text/qanystringview.cpp text/qanystringview.h
+ text/qbytearray.cpp text/qbytearray.h
+ text/qbytearrayalgorithms.h
text/qbytearraylist.cpp text/qbytearraylist.h
text/qbytearraymatcher.cpp text/qbytearraymatcher.h
+ text/qbytearrayview.h
text/qbytedata_p.h
text/qchar.h
text/qcollator.cpp text/qcollator.h text/qcollator_p.h
text/qdoublescanprint_p.h
+ text/qlatin1stringmatcher.cpp text/qlatin1stringmatcher.h
+ text/qlatin1stringview.h
text/qlocale.cpp text/qlocale.h text/qlocale_p.h
text/qlocale_data_p.h
text/qlocale_tools.cpp text/qlocale_tools_p.h
- text/qregexp.cpp text/qregexp.h
+ text/qstaticlatin1stringmatcher.h
text/qstring.cpp text/qstring.h
- text/qstring_compat.cpp
text/qstringalgorithms.h text/qstringalgorithms_p.h
text/qstringbuilder.cpp text/qstringbuilder.h
+ text/qstringconverter_base.h
text/qstringconverter.cpp text/qstringconverter.h text/qstringconverter_p.h
+ text/qstringfwd.h
text/qstringiterator_p.h
text/qstringlist.cpp text/qstringlist.h
text/qstringliteral.h
@@ -178,26 +227,38 @@ qt_add_module(Core
text/qtextboundaryfinder.cpp text/qtextboundaryfinder.h
text/qunicodetables_p.h
text/qunicodetools.cpp text/qunicodetools_p.h
+ text/qutf8stringview.h
text/qvsnprintf.cpp
+ thread/qatomic.h
+ thread/qatomic_cxx11.h
+ thread/qbasicatomic.h
+ thread/qgenericatomic.h
+ thread/qlocking_p.h
thread/qmutex.h
+ thread/qorderedmutexlocker_p.h
thread/qreadwritelock.h
thread/qrunnable.cpp thread/qrunnable.h
- thread/qthread.cpp thread/qthread.h
+ thread/qthread.cpp thread/qthread.h thread/qthread_p.h
thread/qthreadstorage.h
+ thread/qtsan_impl.h
thread/qwaitcondition.h thread/qwaitcondition_p.h
+ thread/qyieldcpu.h
time/qcalendar.cpp time/qcalendar.h
time/qcalendarbackend_p.h
time/qcalendarmath_p.h
time/qdatetime.cpp time/qdatetime.h time/qdatetime_p.h
time/qgregoriancalendar.cpp time/qgregoriancalendar_p.h
time/qjuliancalendar.cpp time/qjuliancalendar_p.h
+ time/qlocaltime.cpp time/qlocaltime_p.h
time/qmilankoviccalendar.cpp time/qmilankoviccalendar_p.h
time/qromancalendar.cpp time/qromancalendar_p.h
time/qromancalendar_data_p.h
+ time/qtimezone.cpp time/qtimezone.h
tools/qalgorithms.h
tools/qarraydata.cpp tools/qarraydata.h
tools/qarraydataops.h
tools/qarraydatapointer.h
+ tools/qatomicscopedvaluerollback.h
tools/qbitarray.cpp tools/qbitarray.h
tools/qcache.h
tools/qcontainerfwd.h
@@ -207,15 +268,16 @@ qt_add_module(Core
tools/qduplicatetracker_p.h
tools/qflatmap_p.h
tools/qfreelist.cpp tools/qfreelist_p.h
- tools/qhash.cpp tools/qhash.h
+ tools/qfunctionaltools_impl.cpp tools/qfunctionaltools_impl.h
tools/qhashfunctions.h
tools/qiterator.h
tools/qline.cpp tools/qline.h
- tools/qlist.cpp tools/qlist.h
+ tools/qlist.h
tools/qmakearray_p.h
- tools/qmap.cpp tools/qmap.h
+ tools/qmap.h
tools/qmargins.cpp tools/qmargins.h
- tools/qmessageauthenticationcode.cpp tools/qmessageauthenticationcode.h
+ tools/qmessageauthenticationcode.h
+ tools/qminimalflatset_p.h
tools/qoffsetstringarray_p.h
tools/qpair.h
tools/qpoint.cpp tools/qpoint.h
@@ -223,107 +285,133 @@ qt_add_module(Core
tools/qrect.cpp tools/qrect.h
tools/qrefcount.cpp tools/qrefcount.h
tools/qringbuffer.cpp tools/qringbuffer_p.h
- tools/qscopedpointer.h tools/qscopedpointer_p.h
+ tools/qscopedpointer.h
tools/qscopedvaluerollback.h
tools/qscopeguard.h
tools/qset.h
tools/qshareddata.cpp tools/qshareddata.h
+ tools/qshareddata_impl.h
tools/qsharedpointer.cpp tools/qsharedpointer.h
tools/qsharedpointer_impl.h
tools/qsize.cpp tools/qsize.h
+ tools/qspan.h
+ tools/qspan_p.h
tools/qstack.h
tools/qtaggedpointer.h
tools/qtools_p.h
+ tools/qtyperevision.cpp tools/qtyperevision.h
+ tools/quniquehandle_p.h
tools/qvarlengtharray.h
tools/qvector.h
tools/qversionnumber.cpp tools/qversionnumber.h
+ NO_UNITY_BUILD_SOURCES
+ # MinGW complains about `free-nonheap-object` in ~QSharedDataPointer()
+ # despite the fact that appropriate checks are in place to avoid that!
+ tools/qshareddata.cpp tools/qshareddata.h
+ text/qlocale.cpp text/qlocale.h
+ global/qglobal.cpp # undef qFatal
+ global/qlogging.cpp # undef qFatal/qInfo/qDebug
+ global/qrandom.cpp # undef Q_ASSERT/_X
+ text/qstringconverter.cpp # enum Data
+ tools/qcryptographichash.cpp # KeccakNISTInterface/Final
+ io/qdebug.cpp # undef qDebug
+ NO_PCH_SOURCES
+ compat/removed_api.cpp
+ global/qsimd.cpp
DEFINES
+ QT_NO_CONTEXTLESS_CONNECT
QT_NO_FOREACH
+ QT_NO_QPAIR
QT_NO_USING_NAMESPACE
+ QT_TYPESAFE_FLAGS
+ QT_USE_NODISCARD_FILE_OPEN
INCLUDE_DIRECTORIES
- "${CMAKE_CURRENT_BINARY_DIR}/global" # special case
- # ../3rdparty/md4 # special case remove
- # ../3rdparty/md5 # special case remove
- # ../3rdparty/sha3 # special case remove
+ "${CMAKE_CURRENT_BINARY_DIR}/global"
+ "${CMAKE_CURRENT_BINARY_DIR}/kernel" # for moc_qobject.cpp to be found by qobject.cpp
../3rdparty/tinycbor/src
+ LIBRARIES
+ Qt::GlobalConfigPrivate
+ WrapZLIB::WrapZLIB
PRECOMPILED_HEADER
"global/qt_pch.h"
- NO_PCH_SOURCES
- "text/qstring_compat.cpp"
- LIBRARIES
- Qt::GlobalConfigPrivate # special case
- Threads::Threads # special case
- PUBLIC_LIBRARIES # special case:
- Qt::Platform # special case:
-)
+ GENERATE_CPP_EXPORTS
+ PUBLIC_LIBRARIES
+ Qt::Platform
+ EXTRA_CMAKE_FILES
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CTestMacros.cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreConfigureFileTemplate.in"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreResourceInit.in.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreDeploySupport.cmake"
+ ${corelib_extra_cmake_files}
+ POLICIES
+ QTP0002
+ QTP0003
+)
+_qt_internal_setup_deploy_support()
-# special case begin
add_dependencies(Core qmodule_pri)
-add_dependencies(Core ${QT_CMAKE_EXPORT_NAMESPACE}::moc)
-add_dependencies(Core ${QT_CMAKE_EXPORT_NAMESPACE}::rcc)
-add_dependencies(CorePrivate ${QT_CMAKE_EXPORT_NAMESPACE}::moc)
-add_dependencies(CorePrivate ${QT_CMAKE_EXPORT_NAMESPACE}::rcc)
-if (QT_NAMESPACE STREQUAL "")
-else()
- target_compile_definitions(Core PUBLIC "QT_NAMESPACE=${QT_NAMESPACE}")
+if (NOT QT_NAMESPACE STREQUAL "")
+ set(core_namespace_defs "QT_NAMESPACE=${QT_NAMESPACE}")
+ if(QT_INLINE_NAMESPACE)
+ list(APPEND core_namespace_defs QT_INLINE_NAMESPACE)
+ endif()
+ target_compile_definitions(Core PUBLIC ${core_namespace_defs})
+ set_target_properties(Core PROPERTIES _qt_namespace "${QT_NAMESPACE}")
+ set_property(TARGET Core APPEND PROPERTY EXPORT_PROPERTIES _qt_namespace)
endif()
-qt_generate_qconfig_cpp()
+qt_generate_qconfig_cpp(global/qconfig.cpp.in global/qconfig.cpp)
-# Handle QObject: Automoc does not work for this as it would
-# require to spill internals into users:
-qt_add_module(Core_qobject STATIC
- NO_SYNC_QT
- NO_CONFIG_HEADER_FILE
- NO_MODULE_HEADERS
- INTERNAL_MODULE
- SKIP_DEPENDS_INCLUDE
-)
-set_target_properties(Core_qobject PROPERTIES AUTOMOC OFF)
-qt_manual_moc(qobject_moc_files OUTPUT_MOC_JSON_FILES core_qobject_metatypes_json_list kernel/qobject.h global/qnamespace.h)
+set_target_properties(Core PROPERTIES INTERFACE_QT_COORD_TYPE "${QT_COORD_TYPE}")
+set_property(TARGET Core APPEND PROPERTY COMPATIBLE_INTERFACE_STRING QT_COORD_TYPE)
+
+# Handle qtConfig(thread): CONFIG += thread like in qt.prf.
+# Aka if the feature is enabled, publicly link against the threading library.
+# This also ensures the link flag is in the .prl file.
+if(QT_FEATURE_thread)
+ target_link_libraries(Platform INTERFACE Threads::Threads)
+endif()
+
+# Skip AUTOMOC processing of qobject.cpp and its headers.
+# We do this on purpose, because qobject.cpp contains a bunch of Q_GADGET, Q_NAMESPACE, etc
+# keywords and AUTOMOC gets confused about wanting to compile a qobject.moc file as well.
+# Instead use manual moc.
+set_source_files_properties(kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h kernel/qobject_p_p.h
+ PROPERTIES SKIP_AUTOMOC TRUE)
+
+qt_manual_moc(qobject_moc_files
+ OUTPUT_MOC_JSON_FILES core_qobject_metatypes_json_list
+ kernel/qobject.h)
+# The moc file is included directly by qobject.cpp
set_source_files_properties(${qobject_moc_files} PROPERTIES HEADER_FILE_ONLY ON)
-target_sources(Core_qobject PRIVATE
- global/qnamespace.h
- kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h ${qobject_moc_files})
-set_target_properties(Core_qobject PROPERTIES
- COMPILE_OPTIONS $<TARGET_PROPERTY:Core,COMPILE_OPTIONS>
- COMPILE_DEFINITIONS $<TARGET_PROPERTY:Core,COMPILE_DEFINITIONS>
- INCLUDE_DIRECTORIES $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES>
-)
-target_include_directories(Core_qobject PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/kernel") # for moc_qobject.cpp
-target_link_libraries(Core_qobject PRIVATE Qt::Platform Qt::GlobalConfig)
-extend_target(Core LIBRARIES Qt::Core_qobject)
-add_dependencies(Core_qobject ${QT_CMAKE_EXPORT_NAMESPACE}::moc)
-
-set(core_qobject_metatypes_json_args)
-if (NOT QT_WILL_INSTALL)
- set(core_qobject_metatypes_json_args INSTALL_DIR "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/metatypes")
+
+set(core_metatype_args MANUAL_MOC_JSON_FILES ${core_qobject_metatypes_json_list})
+
+if(QT_WILL_INSTALL)
+ set(metatypes_install_dir ${INSTALL_ARCHDATADIR}/metatypes)
+ list(APPEND core_metatype_args
+ __QT_INTERNAL_INSTALL __QT_INTERNAL_INSTALL_DIR "${metatypes_install_dir}")
endif()
-qt6_generate_meta_types_json_file(Core_qobject
- MANUAL_MOC_JSON_FILES ${core_qobject_metatypes_json_list}
- ${core_qobject_metatypes_json_args}
-)
+# Use qt6_extract_metatypes instead so that we can manually pass the
+# additional json files.
+qt6_extract_metatypes(Core ${core_metatype_args})
-# Core_qobject is never exported so we need to duplicate the metatypes file
-# interface on Core
-get_target_property(core_qobject_metatypes_file_genex_build Core_qobject QT_MODULE_META_TYPES_FILE_GENEX_BUILD)
-get_target_property(core_qobject_metatypes_file_genex_install Core_qobject QT_MODULE_META_TYPES_FILE_GENEX_INSTALL)
-target_sources(Core INTERFACE
- ${core_qobject_metatypes_file_genex_build}
- ${core_qobject_metatypes_file_genex_install}
+target_sources(Core PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h"
+)
+set_source_files_properties(
+ "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h"
+ PROPERTIES GENERATED TRUE
)
-
-set_property(TARGET Core APPEND PROPERTY
- PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h")
-set_property(TARGET Core APPEND PROPERTY
- PRIVATE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h")
# Find ELF interpreter and define a macro for that:
-if (LINUX AND NOT CMAKE_CROSSCOMPILING AND BUILD_SHARED_LIBS)
+if ((LINUX OR HURD) AND NOT CMAKE_CROSSCOMPILING AND BUILD_SHARED_LIBS)
if (NOT DEFINED ELF_INTERPRETER)
- execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C readelf -l /bin/ls
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C readelf -l /bin/sh
RESULT_VARIABLE readelf_ok
OUTPUT_VARIABLE readelf_output
)
@@ -339,9 +427,8 @@ if (LINUX AND NOT CMAKE_CROSSCOMPILING AND BUILD_SHARED_LIBS)
target_compile_definitions(Core PRIVATE ELF_INTERPRETER="${ELF_INTERPRETER}")
endif()
endif()
-# special case end
-qt_add_simd_part(Core SIMD mips_dsp
+qt_internal_add_simd_part(Core SIMD mips_dsp
SOURCES
../gui/painting/qt_mips_asm_dsp_p.h
text/qstring_mips_dsp_asm.S
@@ -354,82 +441,63 @@ endif()
if(ANDROID)
set_property(TARGET Core APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
- jar/QtAndroid.jar
+ jar/Qt${QtBase_VERSION_MAJOR}Android.jar
)
set_property(TARGET Core APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES
- plugins/platforms/libplugins_platforms_qtforandroid.so
+ ${INSTALL_PLUGINSDIR}/platforms/libplugins_platforms_qtforandroid.so
)
set_property(TARGET Core APPEND PROPERTY QT_ANDROID_PERMISSIONS
android.permission.INTERNET android.permission.WRITE_EXTERNAL_STORAGE
)
endif()
-#### Keys ignored in scope 1:.:.:corelib.pro:<TRUE>:
-# CMAKE_DISABLED_FEATURES = "$$join(QT_DISABLED_FEATURES, "$$escape_expand(\\n) ")"
-# CMAKE_HOST_DATA_DIR = "$$cmakeRelativePath($$[QT_HOST_DATA/src], $$[QT_INSTALL_PREFIX])"
-# CMAKE_INSTALL_DATA_DIR = "$$cmakeRelativePath($$[QT_HOST_DATA], $$[QT_INSTALL_PREFIX])"
-# HOST_BINS = "$$[QT_HOST_BINS]"
-# INSTALLS = "ctest_qt5_module_files" "cmake_qt5_umbrella_module_files"
-# MODULE = "core"
-# MODULE_CONFIG = "moc" "resources"
-# QMAKE_DSYM_DEBUG_SCRIPT = "$$PWD/debug_script.py"
-# QMAKE_PKGCONFIG_VARIABLES = "host_bins" "qt_conf"
-# QMAKE_SUBSTITUTES = "ctest_macros_file" "cmake_umbrella_config_file" "cmake_umbrella_config_module_location" "cmake_umbrella_config_module_location_for_install" "cmake_umbrella_config_version_file" "cmake_extras_mkspec_dir" "cmake_extras_mkspec_dir_for_install"
-# cmake_extras_mkspec_dir.input = "$$PWD/Qt5CoreConfigExtrasMkspecDir.cmake.in"
-# cmake_extras_mkspec_dir.output = "$$DESTDIR/cmake/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake"
-# cmake_extras_mkspec_dir_for_install.input = "$$PWD/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in"
-# cmake_extras_mkspec_dir_for_install.output = "$$DESTDIR/cmake/install/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake"
-# cmake_qt5_umbrella_module_files.files = "$$cmake_umbrella_config_file.output" "$$cmake_umbrella_config_version_file.output" "$$cmake_umbrella_config_module_location_for_install.output"
-# cmake_qt5_umbrella_module_files.path = "$$[QT_INSTALL_LIBS]/cmake/Qt5"
-# cmake_umbrella_config_file.input = "$$PWD/Qt5Config.cmake.in"
-# cmake_umbrella_config_file.output = "$$DESTDIR/cmake/Qt5/Qt5Config.cmake"
-# cmake_umbrella_config_module_location.input = "$$PWD/Qt5ModuleLocation.cmake.in"
-# cmake_umbrella_config_module_location.output = "$$DESTDIR/cmake/Qt5/Qt5ModuleLocation.cmake"
-# cmake_umbrella_config_module_location_for_install.input = "$$PWD/Qt5ModuleLocationForInstall.cmake.in"
-# cmake_umbrella_config_module_location_for_install.output = "$$DESTDIR/cmake/install/Qt5/Qt5ModuleLocation.cmake"
-# cmake_umbrella_config_version_file.input = "$$PWD/../../mkspecs/features/data/cmake/Qt5ConfigVersion.cmake.in"
-# cmake_umbrella_config_version_file.output = "$$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake"
-# ctest_macros_file.CONFIG = "verbatim"
-# ctest_macros_file.input = "$$PWD/Qt5CTestMacros.cmake"
-# ctest_macros_file.output = "$$DESTDIR/cmake/Qt5Core/Qt5CTestMacros.cmake"
-# ctest_qt5_module_files.files = "$$ctest_macros_file.output" "$$cmake_extras_mkspec_dir_for_install.output"
-# ctest_qt5_module_files.path = "$$[QT_INSTALL_LIBS]/cmake/Qt5Core"
-# host_bins.name = "host_bins"
-# host_bins.variable = "HOST_BINS"
-# qt_conf.name = "qt_config"
-# qt_conf.variable = "QT_CONFIG"
-
-## Scopes:
-#####################################################################
+# Add version tagging source files if the linker has version script support
+# or the platform supports it.
+set(core_version_tagging_files
+ global/qversiontagging.cpp)
+qt_internal_extend_target(Core
+ CONDITION QT_FEATURE_version_tagging
+ SOURCES ${core_version_tagging_files}
+)
-#### Keys ignored in scope 2:.:.:corelib.pro:QT_FEATURE_gc_binaries:
-# MODULE_CONFIG = "gc_binaries"
-# special case begin
-# remove because it's handled manually
-#qt_extend_target(Core CONDITION NOT QT_NAMESPACE_ISEMPTY
-# PUBLIC_DEFINES
-# QT_NAMESPACE=
-#)
-# special case end
+if(GCC)
+ # Disable LTO, as the symbols disappear somehow under GCC
+ # (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48200)
+ # The issue should be fixed in GCC >= 10
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
+ set_source_files_properties(${core_version_tagging_files}
+ PROPERTIES COMPILE_OPTIONS "-fno-lto")
+ endif()
+endif()
-qt_extend_target(Core CONDITION ANDROID
+qt_internal_extend_target(Core
+ CONDITION ( TEST_architecture_arch STREQUAL i386 ) OR
+ ( TEST_architecture_arch STREQUAL x86_64 ) OR
+ ( CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" ) OR
+ ( CMAKE_OSX_ARCHITECTURES MATCHES "i386" ) OR
SOURCES
- kernel/qsharedmemory_android.cpp
- kernel/qsystemsemaphore_android.cpp
+ global/qsimd_x86_p.h
+)
+
+qt_internal_extend_target(Core CONDITION ANDROID
DEFINES
- LIBS_SUFFIX="_${CMAKE_SYSTEM_PROCESSOR}.so"
+ LIBS_SUFFIX="_${ANDROID_ABI}.so"
)
-qt_extend_target(Core CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386")
+qt_internal_extend_target(Core CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386")
LINK_OPTIONS
"/BASE:0x67000000"
)
-#### Keys ignored in scope 6:.:.:corelib.pro:FREEBSD OR OPENBSD:
-# QMAKE_LFLAGS_NOUNDEF = <EMPTY>
+qt_internal_extend_target(Core CONDITION QT_FEATURE_xmlstream
+ SOURCES
+ serialization/qxmlstream.cpp serialization/qxmlstream.h serialization/qxmlstream_p.h
+ serialization/qxmlstreamgrammar.cpp serialization/qxmlstreamgrammar_p.h
+ serialization/qxmlstreamparser_p.h
+)
-qt_extend_target(Core CONDITION QT_FEATURE_animation
+qt_internal_extend_target(Core CONDITION QT_FEATURE_animation
SOURCES
animation/qabstractanimation.cpp animation/qabstractanimation.h animation/qabstractanimation_p.h
animation/qanimationgroup.cpp animation/qanimationgroup.h animation/qanimationgroup_p.h
@@ -440,9 +508,22 @@ qt_extend_target(Core CONDITION QT_FEATURE_animation
animation/qvariantanimation.cpp animation/qvariantanimation.h animation/qvariantanimation_p.h
)
-qt_extend_target(Core CONDITION WIN32
+# This needs to be done before one below adds kernel32 because the symbols we use
+# from synchronization also appears in kernel32 in the version of MinGW we use in CI.
+# However, when picking the symbols from libkernel32.a it will try to load the symbols
+# from the wrong DLL at runtime and crash!
+qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
+ SOURCES
+ thread/qfutex_win_p.h
+ thread/qwaitcondition_win.cpp
+ LIBRARIES
+ synchronization
+)
+
+qt_internal_extend_target(Core CONDITION WIN32
SOURCES
global/qoperatingsystemversion_win.cpp global/qoperatingsystemversion_win_p.h
+ global/qt_windows.h
io/qfilesystemengine_win.cpp
io/qfsfileengine_win.cpp
io/qlockfile_win.cpp
@@ -450,20 +531,20 @@ qt_extend_target(Core CONDITION WIN32
io/qstorageinfo_win.cpp
io/qwindowspipereader.cpp io/qwindowspipereader_p.h
io/qwindowspipewriter.cpp io/qwindowspipewriter_p.h
+ io/qntdll_p.h
kernel/qcoreapplication_win.cpp
- kernel/qelapsedtimer_win.cpp
kernel/qeventdispatcher_win.cpp kernel/qeventdispatcher_win_p.h
- kernel/qfunctions_winrt_p.h
- kernel/qsharedmemory_win.cpp
- kernel/qsystemsemaphore_win.cpp
+ kernel/qfunctions_win.cpp kernel/qfunctions_win_p.h kernel/qfunctions_winrt_p.h
+ ipc/qsharedmemory_win.cpp
+ ipc/qsystemsemaphore_win.cpp
kernel/qwineventnotifier.cpp kernel/qwineventnotifier.h kernel/qwineventnotifier_p.h
kernel/qwinregistry.cpp kernel/qwinregistry_p.h
plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h
- thread/qatomic_msvc.h
thread/qthread_win.cpp
- # DEFINES # special case: remove
+ platform/windows/qcomobject_p.h
LIBRARIES
advapi32
+ authz
kernel32
netapi32
ole32
@@ -478,7 +559,32 @@ qt_extend_target(Core CONDITION WIN32
userenv
)
-qt_extend_target(Core CONDITION APPLE
+qt_internal_extend_target(Core CONDITION WIN32
+ NO_UNITY_BUILD_SOURCES
+ global/qsimd.cpp # Q_DECL_INIT_PRIORITY
+ serialization/qcborvalue.cpp # various windows.h clashes
+ serialization/qjsoncbor.cpp
+ serialization/qjsonvalue.cpp
+ serialization/qxmlstream.cpp
+ text/qbytearray.cpp
+ text/qlatin1stringmatcher.cpp
+ text/qunicodetools.cpp
+ tools/qhash.cpp # Q_DECL_INIT_PRIORITY
+)
+
+if(NOT WIN32)
+ ### Qt7: remove
+ # Make qwineventnotifier.h available on non-Windows platforms too for code bases that include
+ # it unconditionally.
+ qt_internal_extend_target(Core SOURCES kernel/qwineventnotifier.h)
+ set_source_files_properties(kernel/qwineventnotifier.h PROPERTIES SKIP_AUTOMOC ON)
+endif()
+
+qt_internal_extend_target(Core CONDITION WASM
+ SOURCES
+ kernel/qcore_wasm.cpp)
+
+qt_internal_extend_target(Core CONDITION APPLE
SOURCES
global/qoperatingsystemversion_darwin.mm
io/qfilesystemengine_mac.mm
@@ -492,9 +598,20 @@ qt_extend_target(Core CONDITION APPLE
LIBRARIES
${FWCoreFoundation}
${FWFoundation}
+ PUBLIC_LIBRARIES
+ ${FWIOKit}
+ DEFINES
+ _DARWIN_C_SOURCE # This resolves two issues,
+ # - Provide DT_* macros to qfilesystemengine_unix.cpp
+ # - Enables SOCK_MAXADDRLEN in case its missing during the unity build
+ NO_UNITY_BUILD_SOURCES
+ kernel/qsystemerror.cpp
+ # This makes sure that the tst_qmakelib passes. For some reason,
+ # QtCore ends up returning a corrupted error message in
+ # write_file(): fail
)
-qt_extend_target(Core CONDITION MACOS
+qt_internal_extend_target(Core CONDITION MACOS
LIBRARIES
${FWAppKit}
${FWApplicationServices}
@@ -502,10 +619,9 @@ qt_extend_target(Core CONDITION MACOS
${FWSecurity}
PUBLIC_LIBRARIES
${FWDiskArbitration}
- ${FWIOKit}
)
-qt_extend_target(Core CONDITION INTEGRITY
+qt_internal_extend_target(Core CONDITION INTEGRITY
LIBRARIES
ivfs
net
@@ -516,148 +632,88 @@ qt_extend_target(Core CONDITION INTEGRITY
--pending_instantiations=128
)
-#### Keys ignored in scope 14:.:.:corelib.pro:pathIsAbsolute(_ss_CMAKE_HOST_DATA_DIR):
-# CMAKE_HOST_DATA_DIR = "$$[QT_HOST_DATA/src]/"
-# CMAKE_HOST_DATA_DIR_IS_ABSOLUTE = "True"
-
-#### Keys ignored in scope 15:.:.:corelib.pro:pathIsAbsolute(_ss_CMAKE_INSTALL_DATA_DIR):
-# CMAKE_INSTALL_DATA_DIR = "$$[QT_HOST_DATA]/"
-# CMAKE_INSTALL_DATA_DIR_IS_ABSOLUTE = "True"
-
-#### Keys ignored in scope 20:.:global:global/global.pri:QT_CPU_FEATURES__ss_QT_ARCH___contains___f16c:
-# f16c_cxx = "true"
-
-#### Keys ignored in scope 22:.:global:global/global.pri:CLANG OR intel_icl OR ICC:
-# f16c_cxx = "false"
-
-#### Keys ignored in scope 24:.:global:global/global.pri:GCC AND f16c AND x86SimdAlways:
-# f16c_cxx = "true"
-
-#### Keys ignored in scope 26:.:global:global/global.pri:MSVC AND QT_CPU_FEATURES__ss_QT_ARCH___contains___avx:
-# f16c_cxx = "true"
-
-#### Keys ignored in scope 27:.:global:global/global.pri:else:
-# f16c_cxx = "false"
-
-# extend_target(Core CONDITION _ss_f16c_cxx ... # special case remove: Handled manually
-
-# special case begin
-# Remove this because it's handled manually
-#extend_target(Core CONDITION NOT _x_-armcc_x_ AND NOT cross_compile AND NOT static AND (hurd_x_ OR linux_x_)
-# DEFINES
-# ELF_INTERPRETER=\\\"=Creadelf-l/bin/ls|perl-n-e\'['quote', ['if', ['/program', 'interpreter:', ['.*'], ']/'], '{', 'print', '$1;', '}']]\'\\\"
-# LINK_OPTIONS
-# "-Wl,-e,qt_core_boilerplate"
-#)
-# special case end
-
-qt_extend_target(Core CONDITION LINUX AND NOT static
- SOURCES
- global/minimum-linux_p.h
+# Workaround for QTBUG-101411
+# Remove if QCC (gcc version 8.3.0) for QNX 7.1.0 is no longer supported
+qt_internal_extend_target(Core CONDITION QCC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "8.3.0")
+ PUBLIC_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:CXX>:-Wno-invalid-offsetof>
)
-#### Keys ignored in scope 34:.:global:global/global.pri:precompile_header:
-# NO_PCH_ASM = "global/minimum-linux.S"
-# QMAKE_EXTRA_COMPILERS = "no_pch_assembler"
-# no_pch_assembler.commands = "$$QMAKE_CC" "-c" "$(CFLAGS)" "$(INCPATH)" "${QMAKE_FILE_IN}" "-o" "${QMAKE_FILE_OUT}"
-# no_pch_assembler.dependency_type = "TYPE_C"
-# no_pch_assembler.input = "NO_PCH_ASM"
-# no_pch_assembler.name = "compiling[no_pch]" "${QMAKE_FILE_IN}"
-# no_pch_assembler.output = "${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${firstQMAKE_EXT_OBJ}"
-
-#### Keys ignored in scope 35:.:global:global/global.pri:silent:
-# no_pch_assembler.commands = "@echo" "compiling[no_pch]" "${QMAKE_FILE_IN}" "&&"
-
-qt_extend_target(Core CONDITION LINUX AND NOT precompile_header AND NOT static
+qt_internal_extend_target(Core CONDITION LINUX AND QT_BUILD_SHARED_LIBS
SOURCES
- global/minimum-linux.S
+ global/minimum-linux_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_slog2
+qt_internal_extend_target(Core CONDITION QT_FEATURE_slog2
LIBRARIES
Slog2::Slog2
)
-qt_extend_target(Core CONDITION QT_FEATURE_journald
+qt_internal_extend_target(Core CONDITION QT_FEATURE_journald
LIBRARIES
PkgConfig::Libsystemd
)
-#### Keys ignored in scope 39:.:global:global/global.pri:GCC AND ltcg:
-# QMAKE_EXTRA_COMPILERS = "versiontagging_compiler"
-# versiontagging_compiler.commands = "$$QMAKE_CXX" "-c" "$(CXXFLAGS)" "$(INCPATH)" "-fno-lto" "-o" "${QMAKE_FILE_OUT}" "${QMAKE_FILE_IN}"
-# versiontagging_compiler.dependency_type = "TYPE_C"
-# versiontagging_compiler.input = "VERSIONTAGGING_SOURCES"
-# versiontagging_compiler.name = "compiling[versiontagging]" "${QMAKE_FILE_IN}"
-# versiontagging_compiler.output = "${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${firstQMAKE_EXT_OBJ}"
-# versiontagging_compiler.variable_out = "OBJECTS"
-
-#### Keys ignored in scope 40:.:global:global/global.pri:silent:
-# versiontagging_compiler.commands = "@echo" "compiling[versiontagging]" "${QMAKE_FILE_IN}" "&&"
-
-qt_extend_target(Core CONDITION NOT GCC OR NOT ltcg
- SOURCES
- global/qversiontagging.cpp
-)
-
-qt_extend_target(Core CONDITION UNIX
+qt_internal_extend_target(Core CONDITION UNIX
SOURCES
io/qfilesystemengine_unix.cpp
io/qfilesystemiterator_unix.cpp
io/qfsfileengine_unix.cpp
io/qlockfile_unix.cpp
kernel/qcore_unix.cpp kernel/qcore_unix_p.h
- kernel/qeventdispatcher_unix.cpp kernel/qeventdispatcher_unix_p.h
kernel/qpoll_p.h
kernel/qtimerinfo_unix.cpp kernel/qtimerinfo_unix_p.h
thread/qthread_unix.cpp
)
+if(APPLE)
+ set_source_files_properties(io/qfilesystemengine_unix.cpp PROPERTIES LANGUAGE OBJCXX)
+ qt_internal_extend_target(Core CONDITION
+ PUBLIC_LIBRARIES ${FWUniformTypeIdentifiers}
+ )
+endif()
-qt_extend_target(Core CONDITION QT_FEATURE_thread
+qt_internal_extend_target(Core CONDITION UNIX AND NOT WASM
SOURCES
- thread/qatomic.cpp thread/qatomic.h
- thread/qatomic_bootstrap.h
- thread/qatomic_cxx11.h
- thread/qbasicatomic.h
+ kernel/qeventdispatcher_unix.cpp kernel/qeventdispatcher_unix_p.h
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_thread
+ SOURCES
+ thread/qatomic.cpp
thread/qfutex_p.h
- thread/qgenericatomic.h
- thread/qlocking_p.h
thread/qmutex.cpp thread/qmutex_p.h
- thread/qorderedmutexlocker_p.h
thread/qreadwritelock.cpp thread/qreadwritelock_p.h
thread/qsemaphore.cpp thread/qsemaphore.h
- thread/qthread_p.h
thread/qthreadpool.cpp thread/qthreadpool.h thread/qthreadpool_p.h
thread/qthreadstorage.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
+qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX
SOURCES
- thread/qmutex_win.cpp
- thread/qwaitcondition_win.cpp
+ thread/qwaitcondition_unix.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX
+qt_internal_extend_target(Core CONDITION APPLE AND QT_FEATURE_thread
SOURCES
- thread/qwaitcondition_unix.cpp
+ thread/qfutex_mac_p.h
+ thread/qmutex_mac.cpp
)
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_thread
+qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX AND NOT APPLE AND NOT LINUX
SOURCES
- thread/qmutex_mac.cpp
+ thread/qmutex_unix.cpp
)
-qt_extend_target(Core CONDITION LINUX AND QT_FEATURE_thread
+qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND FREEBSD
SOURCES
- thread/qmutex_linux.cpp
+ thread/qfutex_freebsd_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX AND NOT APPLE AND NOT LINUX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND LINUX
SOURCES
- thread/qmutex_unix.cpp
+ thread/qfutex_linux_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_future
+qt_internal_extend_target(Core CONDITION QT_FEATURE_future
SOURCES
thread/qexception.cpp thread/qexception.h
thread/qfuture.h
@@ -669,107 +725,104 @@ qt_extend_target(Core CONDITION QT_FEATURE_future
thread/qresultstore.cpp thread/qresultstore.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_std_atomic64
+qt_internal_extend_target(Core CONDITION QT_FEATURE_std_atomic64
PUBLIC_LIBRARIES
WrapAtomic::WrapAtomic
)
-qt_extend_target(Core CONDITION ICC
- COMPILE_OPTIONS
- -fp-model
- strict
+qt_internal_extend_target(Core CONDITION NOT QT_FEATURE_system_zlib
+ LIBRARIES
+ Qt::ZlibPrivate
)
-qt_extend_target(Core CONDITION MSVC
+qt_internal_extend_target(Core CONDITION QT_FEATURE_commandlineparser
SOURCES
- tools/qvector_msvc.cpp
- NO_PCH_SOURCES
- "tools/qvector_msvc.cpp"
+ tools/qcommandlineoption.cpp tools/qcommandlineoption.h
+ tools/qcommandlineparser.cpp tools/qcommandlineparser.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_system_zlib
+qt_internal_extend_target(Core CONDITION QT_FEATURE_backtrace
+ DEFINES
+ BACKTRACE_HEADER="${Backtrace_HEADER}"
LIBRARIES
- ZLIB::ZLIB
-)
-
-qt_extend_target(Core CONDITION NOT QT_FEATURE_system_zlib
- SOURCES
- ../3rdparty/zlib/src/adler32.c
- ../3rdparty/zlib/src/compress.c
- ../3rdparty/zlib/src/crc32.c
- ../3rdparty/zlib/src/deflate.c
- ../3rdparty/zlib/src/gzclose.c
- ../3rdparty/zlib/src/gzlib.c
- ../3rdparty/zlib/src/gzread.c
- ../3rdparty/zlib/src/gzwrite.c
- ../3rdparty/zlib/src/infback.c
- ../3rdparty/zlib/src/inffast.c
- ../3rdparty/zlib/src/inflate.c
- ../3rdparty/zlib/src/inftrees.c
- ../3rdparty/zlib/src/trees.c
- ../3rdparty/zlib/src/uncompr.c
- ../3rdparty/zlib/src/zutil.c
- INCLUDE_DIRECTORIES
- ../3rdparty/zlib/src
+ WrapBacktrace::WrapBacktrace
)
-qt_extend_target(Core CONDITION QT_FEATURE_commandlineparser
- SOURCES
- tools/qcommandlineoption.cpp tools/qcommandlineoption.h
- tools/qcommandlineparser.cpp tools/qcommandlineparser.h
+qt_internal_extend_target(Core CONDITION QT_FEATURE_system_doubleconversion
+ LIBRARIES
+ WrapSystemDoubleConversion::WrapSystemDoubleConversion
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_doubleconversion AND NOT QT_FEATURE_system_doubleconversion
+ SOURCES
+ ../3rdparty/double-conversion/double-conversion/bignum.cc
+ ../3rdparty/double-conversion/double-conversion/bignum-dtoa.cc
+ ../3rdparty/double-conversion/double-conversion/bignum-dtoa.h
+ ../3rdparty/double-conversion/double-conversion/bignum.h
+ ../3rdparty/double-conversion/double-conversion/cached-powers.cc
+ ../3rdparty/double-conversion/double-conversion/cached-powers.h
+ ../3rdparty/double-conversion/double-conversion/diy-fp.h
+ ../3rdparty/double-conversion/double-conversion/double-conversion.h
+ ../3rdparty/double-conversion/double-conversion/double-to-string.cc
+ ../3rdparty/double-conversion/double-conversion/double-to-string.h
+ ../3rdparty/double-conversion/double-conversion/fast-dtoa.cc
+ ../3rdparty/double-conversion/double-conversion/fast-dtoa.h
+ ../3rdparty/double-conversion/double-conversion/fixed-dtoa.cc
+ ../3rdparty/double-conversion/double-conversion/fixed-dtoa.h
+ ../3rdparty/double-conversion/double-conversion/ieee.h
+ ../3rdparty/double-conversion/double-conversion/string-to-double.cc
+ ../3rdparty/double-conversion/double-conversion/string-to-double.h
+ ../3rdparty/double-conversion/double-conversion/strtod.cc
+ ../3rdparty/double-conversion/double-conversion/strtod.h
+ ../3rdparty/double-conversion/double-conversion/utils.h
+ INCLUDE_DIRECTORIES
+ ../3rdparty/double-conversion/double-conversion
+ ../3rdparty/double-conversion
)
-qt_extend_target(Core CONDITION QT_FEATURE_system_doubleconversion
+qt_internal_extend_target(Core CONDITION QT_FEATURE_system_libb2
LIBRARIES
- WrapDoubleConversion::WrapDoubleConversion
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_doubleconversion AND NOT QT_FEATURE_system_doubleconversion
- SOURCES
- ../3rdparty/double-conversion/bignum.cc ../3rdparty/double-conversion/bignum.h
- ../3rdparty/double-conversion/bignum-dtoa.cc ../3rdparty/double-conversion/bignum-dtoa.h
- ../3rdparty/double-conversion/cached-powers.cc ../3rdparty/double-conversion/cached-powers.h
- ../3rdparty/double-conversion/diy-fp.cc ../3rdparty/double-conversion/diy-fp.h
- ../3rdparty/double-conversion/double-conversion.cc
- ../3rdparty/double-conversion/fast-dtoa.cc ../3rdparty/double-conversion/fast-dtoa.h
- ../3rdparty/double-conversion/fixed-dtoa.cc ../3rdparty/double-conversion/fixed-dtoa.h
- ../3rdparty/double-conversion/ieee.h
- ../3rdparty/double-conversion/include/double-conversion/double-conversion.h
- ../3rdparty/double-conversion/include/double-conversion/utils.h
- ../3rdparty/double-conversion/strtod.cc ../3rdparty/double-conversion/strtod.h
- INCLUDE_DIRECTORIES
- ../3rdparty/double-conversion/..
- ../3rdparty/double-conversion/include
+ Libb2::Libb2
)
-qt_extend_target(Core CONDITION QT_FEATURE_easingcurve
+qt_internal_extend_target(Core CONDITION QT_FEATURE_easingcurve
SOURCES
tools/qeasingcurve.cpp tools/qeasingcurve.h
tools/qtimeline.cpp tools/qtimeline.h
)
-qt_extend_target(Core CONDITION UNIX AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORKS AND NOT WASM AND (NOT ICC OR NOT MACOS)
+qt_internal_extend_target(Core CONDITION UNIX AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORKS AND NOT WASM AND NOT MACOS
LIBRARIES
m
)
-qt_extend_target(Core CONDITION APPLE AND NOT NACL
+qt_internal_extend_target(Core CONDITION APPLE
SOURCES
- kernel/qelapsedtimer_mac.cpp
text/qlocale_mac.mm
)
-qt_extend_target(Core CONDITION UNIX AND (NACL OR NOT APPLE)
+qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT WASM
SOURCES
text/qlocale_unix.cpp
)
-qt_extend_target(Core CONDITION WIN32 AND (NACL OR NOT APPLE)
+qt_internal_extend_target(Core CONDITION WIN32
SOURCES
text/qlocale_win.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_icu
+qt_internal_extend_target(Core CONDITION WASM
+ SOURCES
+ text/qlocale_wasm.cpp
+)
+
+# On MS-Win, clang has two flavors, one of which immitates MSVC (so claims to be it)
+qt_internal_extend_target(Core CONDITION MSVC
+ LIBRARIES
+ runtimeobject
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_icu
SOURCES
text/qcollator_icu.cpp
text/qlocale_icu.cpp
@@ -777,186 +830,219 @@ qt_extend_target(Core CONDITION QT_FEATURE_icu
ICU::i18n ICU::uc ICU::data
)
-qt_extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu
+qt_internal_extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu
SOURCES
text/qcollator_win.cpp
)
-qt_extend_target(Core CONDITION MACOS AND NOT QT_FEATURE_icu
+qt_internal_extend_target(Core CONDITION MACOS AND NOT QT_FEATURE_icu
SOURCES
text/qcollator_macx.cpp
)
-qt_extend_target(Core CONDITION UNIX AND NOT MACOS AND NOT QT_FEATURE_icu
+qt_internal_extend_target(Core CONDITION UNIX AND NOT MACOS AND NOT QT_FEATURE_icu
SOURCES
text/qcollator_posix.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_regularexpression
+qt_internal_extend_target(Core CONDITION QT_FEATURE_regularexpression
SOURCES
text/qregularexpression.cpp text/qregularexpression.h
LIBRARIES
WrapPCRE2::WrapPCRE2
)
-qt_extend_target(Core CONDITION QT_FEATURE_hijricalendar
+qt_internal_extend_target(Core CONDITION QT_FEATURE_openssl_hash
+ LIBRARIES
+ WrapOpenSSL::WrapOpenSSL
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_hijricalendar
SOURCES
time/qhijricalendar.cpp time/qhijricalendar_p.h
time/qhijricalendar_data_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_islamiccivilcalendar
+qt_internal_extend_target(Core CONDITION QT_FEATURE_islamiccivilcalendar
SOURCES
time/qislamiccivilcalendar.cpp time/qislamiccivilcalendar_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_jalalicalendar
+qt_internal_extend_target(Core CONDITION QT_FEATURE_jalalicalendar
SOURCES
time/qjalalicalendar.cpp time/qjalalicalendar_p.h
time/qjalalicalendar_data_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_timezone
+qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone
SOURCES
- time/qtimezone.cpp time/qtimezone.h
time/qtimezoneprivate.cpp time/qtimezoneprivate_p.h
time/qtimezoneprivate_data_p.h
)
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_timezone AND NOT NACL
+qt_internal_extend_target(Core CONDITION APPLE AND QT_FEATURE_timezone
SOURCES
time/qtimezoneprivate_mac.mm
)
-qt_extend_target(Core CONDITION ANDROID AND QT_FEATURE_timezone AND NOT ANDROID_EMBEDDED AND (NACL OR NOT APPLE)
+qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND ANDROID AND NOT APPLE
SOURCES
time/qtimezoneprivate_android.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_timezone AND UNIX AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
+qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND UNIX AND NOT ANDROID AND NOT APPLE
SOURCES
time/qtimezoneprivate_tz.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_icu AND QT_FEATURE_timezone AND UNIX AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
+qt_internal_extend_target(Core
+ CONDITION
+ QT_FEATURE_icu AND QT_FEATURE_timezone AND NOT ANDROID AND NOT APPLE
SOURCES
time/qtimezoneprivate_icu.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_icu AND QT_FEATURE_timezone AND WIN32 AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
+# Even MS says we should prefer ICU over its APIs for TZ data:
+qt_internal_extend_target(Core
+ CONDITION
+ QT_FEATURE_timezone AND WIN32 AND NOT QT_FEATURE_icu
SOURCES
- time/qtimezoneprivate_icu.cpp
+ time/qtimezoneprivate_win.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_timezone AND WIN32 AND NOT QT_FEATURE_icu AND (ANDROID_EMBEDDED OR NOT ANDROID) AND (NACL OR NOT APPLE)
+qt_internal_extend_target(Core
+ CONDITION QT_FEATURE_timezone_locale
SOURCES
- time/qtimezoneprivate_win.cpp
+ time/qtimezonelocale.cpp time/qtimezonelocale_p.h
+)
+
+qt_internal_extend_target(Core
+ CONDITION QT_FEATURE_timezone_locale AND NOT QT_FEATURE_icu
+ SOURCES
+ time/qtimezonelocale_data_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_datetimeparser
+qt_internal_extend_target(Core CONDITION QT_FEATURE_datetimeparser
SOURCES
time/qdatetimeparser.cpp time/qdatetimeparser_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_zstd
+qt_internal_extend_target(Core CONDITION QT_FEATURE_zstd
LIBRARIES
- ZSTD::ZSTD
+ WrapZSTD::WrapZSTD
)
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher
+qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher
SOURCES
io/qfilesystemwatcher.cpp io/qfilesystemwatcher.h io/qfilesystemwatcher_p.h
io/qfilesystemwatcher_polling.cpp io/qfilesystemwatcher_polling_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND WIN32
+qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND WIN32
SOURCES
io/qfilesystemwatcher_win.cpp io/qfilesystemwatcher_win_p.h
)
-qt_extend_target(Core CONDITION MACOS AND QT_FEATURE_filesystemwatcher
+qt_internal_extend_target(Core CONDITION MACOS AND QT_FEATURE_filesystemwatcher
SOURCES
io/qfilesystemwatcher_fsevents.mm io/qfilesystemwatcher_fsevents_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND QT_FEATURE_inotify AND UNIX AND NOT MACOS
+qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND QT_FEATURE_inotify AND UNIX AND NOT MACOS
SOURCES
io/qfilesystemwatcher_inotify.cpp io/qfilesystemwatcher_inotify_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND UNIX AND NOT MACOS AND NOT QT_FEATURE_inotify AND (APPLE OR FREEBSD OR NETBSD OR OPENBSD)
+qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND UNIX AND NOT MACOS AND NOT QT_FEATURE_inotify AND (APPLE OR FREEBSD OR NETBSD OR OPENBSD)
SOURCES
io/qfilesystemwatcher_kqueue.cpp io/qfilesystemwatcher_kqueue_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_processenvironment
+qt_internal_extend_target(Core CONDITION QT_FEATURE_processenvironment
SOURCES
io/qprocess.cpp io/qprocess.h io/qprocess_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_processenvironment AND WIN32
+qt_internal_extend_target(Core CONDITION QT_FEATURE_processenvironment AND WIN32
SOURCES
io/qprocess_win.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_processenvironment AND UNIX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_processenvironment AND UNIX
SOURCES
io/qprocess_unix.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_settings
+qt_internal_extend_target(Core CONDITION QT_FEATURE_settings
SOURCES
io/qsettings.cpp io/qsettings.h io/qsettings_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_settings AND WIN32
+qt_internal_extend_target(Core CONDITION QT_FEATURE_settings AND WIN32
SOURCES
io/qsettings_win.cpp
)
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_settings AND NOT NACL
+qt_internal_extend_target(Core CONDITION APPLE AND QT_FEATURE_settings
SOURCES
io/qsettings_mac.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_settings AND WASM
+qt_internal_extend_target(Core CONDITION QT_FEATURE_settings AND WASM
SOURCES
io/qsettings_wasm.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_filesystemiterator AND WIN32
+qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemiterator AND WIN32
SOURCES
io/qfilesystemiterator_win.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_process AND UNIX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_process AND UNIX
SOURCES
../3rdparty/forkfd/forkfd.h
- io/forkfd_qt.cpp
+ io/forkfd_qt.c
INCLUDE_DIRECTORIES
../3rdparty/forkfd
)
-qt_extend_target(Core CONDITION APPLE AND QT_FEATURE_processenvironment
+qt_internal_extend_target(Core CONDITION APPLE AND QT_FEATURE_processenvironment
SOURCES
io/qprocess_darwin.mm
)
-qt_extend_target(Core CONDITION APPLE AND NOT MACOS
+qt_internal_extend_target(Core CONDITION APPLE AND NOT MACOS
PUBLIC_LIBRARIES
${FWMobileCoreServices}
)
-qt_extend_target(Core CONDITION ANDROID AND NOT ANDROID_EMBEDDED
+qt_internal_extend_target(Core CONDITION ANDROID
SOURCES
io/qstandardpaths_android.cpp
- io/qstorageinfo_unix.cpp
- kernel/qjni.cpp kernel/qjni_p.h
+ io/qstorageinfo_linux.cpp io/qstorageinfo_linux_p.h
+ kernel/qjniarray.h
+ kernel/qjnitypes.h kernel/qjnitypes_impl.h
+ kernel/qjnienvironment.cpp kernel/qjnienvironment.h
+ kernel/qjniobject.cpp kernel/qjniobject.h
kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h
- kernel/qjnionload.cpp
+ platform/android/qandroidextras_p.h platform/android/qandroidextras.cpp
+ platform/android/qandroidnativeinterface.cpp
+ NO_UNITY_BUILD_SOURCES
+ platform/android/qandroidextras.cpp
+ # qtNativeClassName conflicts with similar symbols in android headers
+ # TODO: Resolve conflicts between various variables set as,
+ # `org/qtproject/qt/android/QtNative` QtAndroidPrivate might be a good
+ # place to put them.
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_cpp_winrt
+ SOURCES
+ platform/windows/qfactorycacheregistration_p.h
+ platform/windows/qfactorycacheregistration.cpp
+ platform/windows/qt_winrtbase_p.h
)
-qt_extend_target(Core CONDITION HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)
+qt_internal_extend_target(Core CONDITION HAIKU AND NOT ANDROID
SOURCES
io/qstandardpaths_haiku.cpp
io/qstorageinfo_unix.cpp
@@ -964,150 +1050,149 @@ qt_extend_target(Core CONDITION HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)
be
)
-qt_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)
+qt_internal_extend_target(Core
+ CONDITION UNIX AND NOT LINUX AND NOT APPLE AND NOT HAIKU AND NOT ANDROID AND NOT VXWORKS
SOURCES
io/qstandardpaths_unix.cpp
io/qstorageinfo_unix.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_proxymodel
+qt_internal_extend_target(Core CONDITION LINUX AND NOT ANDROID AND NOT VXWORKS
+ SOURCES
+ io/qstandardpaths_unix.cpp
+ io/qstorageinfo_linux.cpp
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
+ SOURCES
+ itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
+ itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_p.h
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_proxymodel
SOURCES
itemmodels/qabstractproxymodel.cpp itemmodels/qabstractproxymodel.h itemmodels/qabstractproxymodel_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_concatenatetablesproxymodel AND QT_FEATURE_proxymodel
+qt_internal_extend_target(Core CONDITION QT_FEATURE_concatenatetablesproxymodel AND QT_FEATURE_proxymodel
SOURCES
itemmodels/qconcatenatetablesproxymodel.cpp itemmodels/qconcatenatetablesproxymodel.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_identityproxymodel AND QT_FEATURE_proxymodel
+qt_internal_extend_target(Core CONDITION QT_FEATURE_identityproxymodel AND QT_FEATURE_proxymodel
SOURCES
- itemmodels/qidentityproxymodel.cpp itemmodels/qidentityproxymodel.h
+ itemmodels/qidentityproxymodel.cpp itemmodels/qidentityproxymodel.h itemmodels/qidentityproxymodel_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_sortfilterproxymodel
+qt_internal_extend_target(Core CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_sortfilterproxymodel
SOURCES
itemmodels/qsortfilterproxymodel.cpp itemmodels/qsortfilterproxymodel.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_transposeproxymodel
+qt_internal_extend_target(Core CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_transposeproxymodel
SOURCES
itemmodels/qtransposeproxymodel.cpp itemmodels/qtransposeproxymodel.h itemmodels/qtransposeproxymodel_p.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_stringlistmodel
+qt_internal_extend_target(Core CONDITION QT_FEATURE_stringlistmodel
SOURCES
itemmodels/qstringlistmodel.cpp itemmodels/qstringlistmodel.h
)
-qt_extend_target(Core CONDITION QT_FEATURE_library
+qt_internal_extend_target(Core CONDITION QT_FEATURE_library
SOURCES
- plugin/qelfparser_p.cpp plugin/qelfparser_p.h
plugin/qlibrary.cpp plugin/qlibrary.h plugin/qlibrary_p.h
- plugin/qmachparser.cpp plugin/qmachparser_p.h
)
-
-qt_extend_target(Core CONDITION QT_FEATURE_library AND UNIX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_library AND WIN32
+ SOURCES
+ plugin/qcoffpeparser.cpp plugin/qcoffpeparser_p.h
+ plugin/qlibrary_win.cpp
+)
+qt_internal_extend_target(Core CONDITION QT_FEATURE_library AND APPLE
SOURCES
plugin/qlibrary_unix.cpp
+ plugin/qmachparser.cpp plugin/qmachparser_p.h
)
-
-qt_extend_target(Core CONDITION QT_FEATURE_library AND WIN32
+qt_internal_extend_target(Core CONDITION QT_FEATURE_library AND UNIX AND NOT APPLE
SOURCES
- plugin/qlibrary_win.cpp
+ plugin/qelfparser_p.cpp plugin/qelfparser_p.h
+ plugin/qlibrary_unix.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_dlopen AND QT_FEATURE_library
+qt_internal_extend_target(Core CONDITION QT_FEATURE_dlopen
LIBRARIES
${CMAKE_DL_LIBS}
)
-qt_extend_target(Core CONDITION APPLE AND (IOS OR TVOS)
+qt_internal_extend_target(Core CONDITION APPLE AND UIKIT
LIBRARIES
${FWUIKit}
)
-qt_extend_target(Core CONDITION WATCHOS
+qt_internal_extend_target(Core CONDITION WATCHOS
LIBRARIES
${FWWatchKit}
)
-qt_extend_target(Core CONDITION NACL
- SOURCES
- kernel/qfunctions_nacl.cpp kernel/qfunctions_nacl.h
-)
-
-qt_extend_target(Core CONDITION INTEGRITY OR (NACL AND UNIX) OR (UNIX AND NOT APPLE)
- SOURCES
- kernel/qelapsedtimer_unix.cpp
-)
-
-qt_extend_target(Core CONDITION QT_FEATURE_poll_select AND UNIX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_poll_select AND UNIX
SOURCES
kernel/qpoll.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_glib AND UNIX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_glib AND UNIX
SOURCES
kernel/qeventdispatcher_glib.cpp kernel/qeventdispatcher_glib_p.h
LIBRARIES
GLIB2::GLIB2
)
-qt_extend_target(Core CONDITION QT_FEATURE_clock_gettime AND UNIX
+qt_internal_extend_target(Core CONDITION QT_FEATURE_clock_gettime
LIBRARIES
WrapRt::WrapRt
)
-qt_extend_target(Core CONDITION UNIX AND NOT ANDROID
+qt_internal_extend_target(Core CONDITION QT_FEATURE_posix_shm AND UNIX
SOURCES
- kernel/qsharedmemory_posix.cpp
- kernel/qsharedmemory_systemv.cpp
- kernel/qsharedmemory_unix.cpp
- kernel/qsystemsemaphore_posix.cpp
- kernel/qsystemsemaphore_systemv.cpp
- kernel/qsystemsemaphore_unix.cpp
+ ipc/qsharedmemory_posix.cpp
+ LIBRARIES
+ WrapRt::WrapRt
)
-
-qt_extend_target(Core CONDITION VXWORKS
+qt_internal_extend_target(Core CONDITION QT_FEATURE_sysv_shm
SOURCES
- kernel/qfunctions_vxworks.cpp kernel/qfunctions_vxworks.h
+ ipc/qsharedmemory_systemv.cpp
)
-
-qt_extend_target(Core CONDITION QNX AND QT_FEATURE_qqnx_pps
+qt_internal_extend_target(Core CONDITION QT_FEATURE_posix_sem
SOURCES
- kernel/qppsattribute.cpp kernel/qppsattribute_p.h
- kernel/qppsattributeprivate_p.h
- kernel/qppsobject.cpp kernel/qppsobject_p.h
- kernel/qppsobjectprivate_p.h
+ ipc/qsystemsemaphore_posix.cpp
LIBRARIES
- PPS::PPS
+ WrapRt::WrapRt
)
-
-qt_extend_target(Core CONDITION QT_FEATURE_cborstreamreader
+qt_internal_extend_target(Core CONDITION QT_FEATURE_sysv_sem
SOURCES
- serialization/qcborstreamreader.cpp serialization/qcborstreamreader.h
+ ipc/qsystemsemaphore_systemv.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_cborstreamwriter
+qt_internal_extend_target(Core CONDITION VXWORKS
SOURCES
- serialization/qcborstreamwriter.cpp serialization/qcborstreamwriter.h
+ io/qstandardpaths_unix.cpp
+ io/qstorageinfo_stub.cpp
)
-qt_extend_target(Core CONDITION QT_FEATURE_binaryjson
+qt_internal_extend_target(Core CONDITION QT_FEATURE_cborstreamreader
SOURCES
- serialization/qbinaryjson.cpp serialization/qbinaryjson_p.h
- serialization/qbinaryjsonarray.cpp serialization/qbinaryjsonarray_p.h
- serialization/qbinaryjsonobject.cpp serialization/qbinaryjsonobject_p.h
- serialization/qbinaryjsonvalue.cpp serialization/qbinaryjsonvalue_p.h
+ serialization/qcborstreamreader.cpp serialization/qcborstreamreader.h
+ NO_UNITY_BUILD_SOURCES
+ serialization/qcborstreamreader.cpp # some problem with cbor_value_get_type etc
)
-qt_extend_target(Core CONDITION QT_FEATURE_qeventtransition
+qt_internal_extend_target(Core CONDITION QT_FEATURE_cborstreamwriter
SOURCES
- statemachine/qeventtransition.cpp statemachine/qeventtransition.h statemachine/qeventtransition_p.h
+ serialization/qcborstreamwriter.cpp serialization/qcborstreamwriter.h
+ NO_UNITY_BUILD_SOURCES
+ serialization/qcborstreamwriter.cpp # CBOR macro clashes
)
-qt_extend_target(Core CONDITION QT_FEATURE_mimetype
+qt_internal_extend_target(Core CONDITION QT_FEATURE_mimetype
SOURCES
mimetypes/qmimedatabase.cpp mimetypes/qmimedatabase.h mimetypes/qmimedatabase_p.h
mimetypes/qmimeglobpattern.cpp mimetypes/qmimeglobpattern_p.h
@@ -1118,110 +1203,173 @@ qt_extend_target(Core CONDITION QT_FEATURE_mimetype
mimetypes/qmimetypeparser.cpp mimetypes/qmimetypeparser_p.h
)
-#### Keys ignored in scope 180:.:mimetypes:mimetypes/mimetypes.pri:QT_FEATURE_mimetype:
-# MIME_DATABASE = "mimetypes/mime/packages/freedesktop.org.xml"
-# OTHER_FILES = "$$MIME_DATABASE"
-
-# special case begin
-# qt_extend_target(Core CONDITION QT_FEATURE_mimetype AND QT_FEATURE_mimetype_database
-# INCLUDE_DIRECTORIES
-# .rcc
-#)
-# special case end
-
-#### Keys ignored in scope 181:.:mimetypes:mimetypes/mimetypes.pri:QT_FEATURE_mimetype_database:
-# QMAKE_EXTRA_COMPILERS = "mimedb"
-# mimedb.commands = "${QMAKE_FILE_IN}" ">" "${QMAKE_FILE_OUT}"
-# mimedb.depends = "$$PWD/mime/generate.pl"
-# mimedb.input = "MIME_DATABASE"
-# mimedb.output = "$$outpath/qmimeprovider_database.cpp"
-# mimedb.variable_out = "INCLUDED_SOURCES"
-
-#### Keys ignored in scope 182:.:mimetypes:mimetypes/mimetypes.pri:ANDROID:
-# outpath = "$$outpath/$${QT_ARCH}"
-
-#### Keys ignored in scope 184:.:mimetypes:mimetypes/mimetypes.pri:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# outpath = "$$outpath/debug"
-
-#### Keys ignored in scope 185:.:mimetypes:mimetypes/mimetypes.pri:else:
-# outpath = "$$outpath/release"
-
-#### Keys ignored in scope 186:.:mimetypes:mimetypes/mimetypes.pri:MAKEFILE_GENERATOR___equals___MSVC.NET OR MAKEFILE_GENERATOR___equals___MSBUILD OR QMAKE_SH_ISEMPTY:
-# mimedb.commands = "cmd" "/c" "$$shell_path($$PWD/mime/generate.bat)"
-# mimedb.depends = "$$PWD/mime/generate.bat" "$$PWD/mime/hexdump.ps1"
-
-#### Keys ignored in scope 187:.:mimetypes:mimetypes/mimetypes.pri:else:
-# mimedb.commands = "perl" "$${mimedb.depends}"
-
-#### Keys ignored in scope 188:.:mimetypes:mimetypes/mimetypes.pri:QT_FEATURE_zstd:
-# mimedb.commands = "--zstd"
-# Resources:
-# special case begin
-# We can't specify the resources directly as we have unit tests that
-# depend on these as well and we no longer support the use of hand
-# edited qrc files.
+qt_internal_extend_target(Core CONDITION QT_FEATURE_permissions
+ SOURCES
+ kernel/qpermissions.cpp kernel/qpermissions.h kernel/qpermissions_p.h
+)
+
+if(QT_FEATURE_permissions AND APPLE)
+ qt_internal_extend_target(Core
+ SOURCES
+ kernel/qpermissions_darwin.mm
+ platform/darwin/qdarwinpermissionplugin.mm
+ PLUGIN_TYPES
+ permissions
+ )
+
+ foreach(permission Camera Microphone Bluetooth Contacts Calendar Location)
+ qt_internal_add_darwin_permission_plugin("${permission}")
+ endforeach()
+
+ # Camera
+ qt_internal_extend_target(QDarwinCameraPermissionPlugin
+ LIBRARIES ${FWAVFoundation}
+ )
+ set_property(TARGET QDarwinCameraPermissionPlugin PROPERTY
+ _qt_darwin_permissison_separate_request TRUE
+ )
+
+ # Microphone
+ qt_internal_extend_target(QDarwinMicrophonePermissionPlugin
+ LIBRARIES ${FWAVFoundation}
+ )
+ set_property(TARGET QDarwinMicrophonePermissionPlugin PROPERTY
+ _qt_darwin_permissison_separate_request TRUE
+ )
+
+ # Bluetooth
+ qt_internal_extend_target(QDarwinBluetoothPermissionPlugin
+ LIBRARIES ${FWCoreBluetooth}
+ )
+ set_property(TARGET QDarwinBluetoothPermissionPlugin PROPERTY
+ _qt_info_plist_usage_descriptions "NSBluetoothAlwaysUsageDescription"
+ )
+
+ # Contacts
+ qt_internal_extend_target(QDarwinContactsPermissionPlugin
+ LIBRARIES ${FWContacts}
+ )
+
+ # Calendar
+ qt_internal_extend_target(QDarwinCalendarPermissionPlugin
+ LIBRARIES ${FWEventKit}
+ )
+ set_property(TARGET QDarwinCalendarPermissionPlugin PROPERTY
+ _qt_info_plist_usage_descriptions "NSCalendarsUsageDescription"
+ )
+
+ # Location
+ qt_internal_extend_target(QDarwinLocationPermissionPlugin
+ LIBRARIES ${FWCoreLocation}
+ )
+ if(MACOS)
+ set_property(TARGET QDarwinLocationPermissionPlugin PROPERTY
+ _qt_info_plist_usage_descriptions
+ "NSLocationUsageDescription"
+ )
+ else()
+ set_property(TARGET QDarwinLocationPermissionPlugin PROPERTY
+ _qt_info_plist_usage_descriptions
+ "NSLocationWhenInUseUsageDescription"
+ "NSLocationAlwaysAndWhenInUseUsageDescription"
+ )
+ endif()
+endif()
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_permissions AND ANDROID
+ SOURCES
+ kernel/qpermissions_android.cpp
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_permissions AND WASM
+ SOURCES
+ kernel/qpermissions_wasm.cpp
+)
+
if(QT_FEATURE_mimetype AND QT_FEATURE_mimetype_database)
include(${CMAKE_CURRENT_SOURCE_DIR}/mimetypes/mimetypes_resources.cmake)
- corelib_add_mimetypes_resources(Core)
-# Generate qmimeprovider_database.cpp
- set(qmimeprovider_db_output "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmimeprovider_database.cpp")
- set(command_args "")
- set(mime_dir "${CMAKE_CURRENT_SOURCE_DIR}/mimetypes/mime")
- set(command_depends "${mime_dir}/generate.pl" "${corelib_mimetypes_resource_file}")
- if (MSVC)
- list(APPEND command_args "${mime_dir}/generate.bat")
- list(APPEND command_depends "${mime_dir}/generate.bat" "${mime_dir}/hexdump.ps1" )
+ if(CMAKE_VERSION VERSION_LESS 3.18 OR QT_AVOID_CMAKE_ARCHIVING_API)
+ set(archiving_api "External")
else()
- list(APPEND command_args perl "${mime_dir}/generate.pl" )
+ set(archiving_api "CMake")
+ if(QT_FEATURE_zstd AND NOT QT_CMAKE_ZSTD_SUPPORT)
+ message(FATAL_ERROR
+ "CMake was not built with zstd support. "
+ "Rebuild CMake or set QT_AVOID_CMAKE_ARCHIVING_API=ON.")
+ endif()
endif()
- if (QT_FEATURE_zstd)
- list(APPEND command_args "--zstd")
+ if(DEFINED INPUT_mimetype_database_compression)
+ set(supported_compression_types zstd gzip none)
+ if(INPUT_mimetype_database_compression IN_LIST supported_compression_types)
+ set(compression_type ${INPUT_mimetype_database_compression})
+ else()
+ message(FATAL_ERROR "Unknown mime type database compression is set:"
+ " ${INPUT_mimetype_database_compression}\nSupported compression types:\n"
+ " ${supported_compression_types}")
+ endif()
+ if(compression_type STREQUAL "zstd" AND NOT QT_FEATURE_zstd)
+ message(FATAL_ERROR
+ "zstd compression is selected for mime type database, but the 'zstd'"
+ " feature is disabled.")
+ endif()
+ elseif(QT_FEATURE_zstd)
+ set(compression_type "zstd")
+ else()
+ set(compression_type "gzip")
endif()
- list(APPEND command_args "${corelib_mimetypes_resource_file}" ">" "${qmimeprovider_db_output}")
+ if(QT_INTERNAL_ENABLE_VERBOSE_MIME_DATABASE_COMPRESSION)
+ set(extra_mime_db_compressor_flags "--log-level=STATUS")
+ else()
+ set(extra_mime_db_compressor_flags "--log-level=NOTICE")
+ endif()
+ # Generate qmimeprovider_database.cpp
+ set(qmimeprovider_db_output "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmimeprovider_database.cpp")
add_custom_command(OUTPUT "${qmimeprovider_db_output}"
- DEPENDS ${command_depends}
- COMMAND ${command_args}
- COMMENT "Generating ${qmimeprovider_db_output}"
+ COMMAND ${CMAKE_COMMAND}
+ -DINPUT_FILE=${corelib_mimetypes_resource_file}
+ -DOUTPUT_FILE=${qmimeprovider_db_output}
+ -DARCHIVING_API=${archiving_api}
+ -DCOMPRESSION_TYPE=${compression_type}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/QtCompressMimeDatabase.cmake"
+ ${extra_mime_db_compressor_flags}
+ DEPENDS
+ "${CMAKE_CURRENT_SOURCE_DIR}/QtCompressMimeDatabase.cmake"
+ "${corelib_mimetypes_resource_file}"
+ VERBATIM
)
- target_sources(Core PRIVATE ${qmimeprovider_db_output})
- set_source_files_properties(${qmimeprovider_db_output} PROPERTIES HEADER_FILE_ONLY TRUE)
- target_include_directories(Core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/.rcc")
+ qt_internal_extend_target(Core
+ SOURCES ${qmimeprovider_db_output}
+ INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/.rcc"
+ )
+ set_source_files_properties(${qmimeprovider_db_output} PROPERTIES
+ GENERATED TRUE
+ HEADER_FILE_ONLY TRUE
+ )
endif()
-# special case end
-
-qt_extend_target(Core CONDITION WASM
+qt_internal_extend_target(Core CONDITION WASM
SOURCES
platform/wasm/qstdweb.cpp platform/wasm/qstdweb_p.h
+ kernel/qeventdispatcher_wasm.cpp kernel/qeventdispatcher_wasm_p.h
)
-# special case begin
-# needs refinement for the other compiler specific cases.
-if(TEST_arch_${TEST_architecture_arch}_subarch_f16c)
- # Equivalent to contains(QT_CPU_FEATURES.$$QT_ARCH, f16c)
- extend_target(Core
- DEFINES
- QFLOAT16_INCLUDE_FAST
- )
-else()
- qt_add_simd_part(Core SIMD f16c
- SOURCES
- global/qfloat16_f16c.c
- )
-endif()
+qt_internal_extend_target(Core CONDITION QT_FEATURE_ctf
+ SOURCES
+ tracing/qctf_p.h tracing/qctf.cpp
+ PLUGIN_TYPES
+ tracing
+)
+# These files are included by qmutex.cpp
set_source_files_properties(
- thread/qmutex_linux.cpp
thread/qmutex_mac.cpp
thread/qmutex_unix.cpp
- thread/qmutex_win.cpp
- PROPERTIES HEADER_FILE_ONLY ON) # special case: These files are included by qmutex.cpp!
-
+ PROPERTIES HEADER_FILE_ONLY ON)
# Remove QT_NO_CAST_TO_ASCII to ensure that the symbols are included in the library.
if(WIN32)
@@ -1232,14 +1380,27 @@ endif()
qt_internal_apply_gc_binaries_conditional(Core PUBLIC)
-if(WIN32)
- set(isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
- set(isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
- set(isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:Qt5_NO_LINK_QTMAIN>>>)
- set(isPolicyNEW $<TARGET_POLICY:CMP0020>)
+# Add entry-point on platforms that need it. A project can opt-out of using the
+# entrypoint by setting the qt_no_entrypoint property to TRUE on a target.
+if(WIN32 OR UIKIT)
+ # find_package(Qt6Core) should call find_package(Qt6EntryPointPrivate) so that we can
+ # link against EntryPointPrivate. Normally this is handled automatically for deps, but
+ # for some reason it doesn't work for the EntryPointPrivate, so we need to add it manually.
+ qt_record_extra_qt_package_dependency(Core EntryPointPrivate "${PROJECT_VERSION}")
+
+ set(entrypoint_conditions "$<NOT:$<BOOL:$<TARGET_PROPERTY:qt_no_entrypoint>>>")
+ list(APPEND entrypoint_conditions "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>")
+
+ if(WIN32)
+ list(APPEND entrypoint_conditions "$<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>")
+ endif()
- target_link_libraries(Core INTERFACE $<$<AND:${isExe},${isWin32},${isNotExcluded},${isPolicyNEW}>:Qt::WinMain>)
- qt_record_extra_qt_package_dependency(Core WinMain "${PROJECT_VERSION}")
+ list(JOIN entrypoint_conditions "," entrypoint_conditions)
+ set(entrypoint_conditions "$<AND:${entrypoint_conditions}>")
+
+ target_link_libraries(Core INTERFACE
+ "$<${entrypoint_conditions}:${QT_CMAKE_EXPORT_NAMESPACE}::EntryPointPrivate>"
+ )
endif()
# Record darwin minimum deployment target.
@@ -1249,21 +1410,77 @@ if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET)
set_property(TARGET Core APPEND PROPERTY
EXPORT_PROPERTIES "QT_DARWIN_MIN_DEPLOYMENT_TARGET")
endif()
-# special case end
-qt_create_tracepoints(Core qtcore.tracepoints)
-qt_add_docs(Core
+qt_internal_generate_tracepoints(Core core
+ SOURCES
+ kernel/qcoreapplication.cpp
+ kernel/qcoreevent.cpp
+ kernel/qobject.cpp
+ plugin/qfactoryloader.cpp
+ plugin/qlibrary.cpp
+ global/qlogging.cpp
+)
+qt_internal_add_docs(Core
doc/qtcore.qdocconf
)
-# special case begin
-# Handle qtzlib.pro to create headers for the
-# QtZlibPrivate target, equivalent to Qt += zlib-private
-if(NOT QT_FEATURE_system_zlib)
- qt_add_module(Zlib
- INTERNAL_MODULE
- HEADER_MODULE
- NO_CONFIG_HEADER_FILE
+qt_internal_add_optimize_full_flags()
+
+# Copy / install an lldb python script into the QtCore.framework.dSYM bundle which searches
+# for the latest installed Qt Creator and loads its lldbbridge.py script.
+# When debugging a Qt app, lldb will prompt the developer to explicitly import the shim script.
+# It will then enable Qt C++ type pretty printers when using command-line lldb or Xcode
+# (e.g. show contents of QString).
+if(APPLE AND QT_FEATURE_framework AND QT_FEATURE_separate_debug_info)
+ qt_internal_module_info(dsym_module_name "Core")
+
+ set(dsym_dir "${dsym_module_name}.framework.dSYM")
+ set(script_name "${dsym_module_name}.py")
+ set(dsym_script_dir_suffix "${INSTALL_LIBDIR}/${dsym_dir}/Contents/Resources/Python")
+ set(dsym_script_build_path "${QT_BUILD_DIR}/${dsym_script_dir_suffix}/${script_name}")
+
+ qt_path_join(dsym_script_install_dir
+ ${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX} ${dsym_script_dir_suffix})
+
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/debug_script.py"
+ "${dsym_script_build_path}"
+ @ONLY
+ )
+ qt_install(FILES
+ "${dsym_script_build_path}"
+ DESTINATION "${dsym_script_install_dir}"
)
endif()
-# special case end
+
+if(IOS)
+ qt_internal_set_apple_privacy_manifest(Core
+ "${CMAKE_CURRENT_SOURCE_DIR}/platform/ios/PrivacyInfo.xcprivacy")
+endif()
+
+set(linker_script_contents "")
+if (QT_NAMESPACE STREQUAL "")
+ set(tag_symbol "qt_version_tag")
+else()
+ set(tag_symbol "qt_version_tag_${QT_NAMESPACE}")
+endif()
+foreach(minor_version RANGE ${PROJECT_VERSION_MINOR})
+ set(previous "${current}")
+ set(current "Qt_${PROJECT_VERSION_MAJOR}.${minor_version}")
+ if (minor_version EQUAL ${PROJECT_VERSION_MINOR})
+ string(APPEND linker_script_contents "${current} { ${tag_symbol}; } ${previous};\n")
+ else()
+ string(APPEND linker_script_contents "${current} {} ${previous};\n")
+ endif()
+endforeach()
+qt_internal_extend_target(Core
+ EXTRA_LINKER_SCRIPT_CONTENT "${linker_script_contents}"
+
+ # Workaround for QTBUG-117514:
+ # Function called by inline methods taking a pointer to a private class as a parameter
+ EXTRA_LINKER_SCRIPT_EXPORTS
+ # QFutureInterfaceBase::setContinuation(std::function<void (QFutureInterfaceBase const&)>, QFutureInterfaceBasePrivate*)
+ "_ZN*20QFutureInterfaceBase15setContinuationE*27QFutureInterfaceBasePrivate*"
+ # QReadWriteLock::destroyRecursive(QReadWriteLockPrivate*)
+ "_ZN*14QReadWriteLock16destroyRecursiveEP*21QReadWriteLockPrivate*"
+)
diff --git a/src/corelib/Qt5AndroidSupport.cmake b/src/corelib/Qt5AndroidSupport.cmake
deleted file mode 100644
index 662dd87c1f..0000000000
--- a/src/corelib/Qt5AndroidSupport.cmake
+++ /dev/null
@@ -1,202 +0,0 @@
-if (NOT ${PROJECT_NAME}-MultiAbiBuild)
-
- set(ANDROID_ABIS armeabi-v7a arm64-v8a x86 x86_64)
-
- # Match Android's sysroots
- set(ANDROID_SYSROOT_armeabi-v7a arm-linux-androideabi)
- set(ANDROID_SYSROOT_arm64-v8a aarch64-linux-android)
- set(ANDROID_SYSROOT_x86 i686-linux-android)
- set(ANDROID_SYSROOT_x86_64 x86_64-linux-android)
-
- foreach(abi IN LISTS ANDROID_ABIS)
- set(abi_initial_value OFF)
- if (abi STREQUAL ${ANDROID_ABI})
- set(abi_initial_value ON)
- endif()
- find_library(Qt5Core_${abi}_Probe Qt5Core_${abi})
- if (Qt5Core_${abi}_Probe)
- option(ANDROID_BUILD_ABI_${abi} "Enable the build for Android ${abi}" ${abi_initial_value})
- endif()
- endforeach()
- option(ANDROID_MIN_SDK_VERSION "Android minimum SDK version" "23")
- option(ANDROID_TARGET_SDK_VERSION "Android target SDK version" "28")
-
- # Make sure to delete the "android-build" directory, which contains all the
- # build artefacts, and also the androiddeployqt/gradle artefacts
- set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
- APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${CMAKE_BINARY_DIR}/android-build)
-
- if (CMAKE_VERSION VERSION_LESS 3.15)
- message(STATUS "-----------------------------------------------------------------------------------------------------------")
- message(STATUS "CMake version 3.15 is required to clean the <build_dir>/android-build when issuing the \"clean\" target.\n\n"
- "For this CMake version please use the \"clean-android-build\" support target additionally to the \"clean\" target.")
- message(STATUS "-----------------------------------------------------------------------------------------------------------")
-
- add_custom_target(clean-android-build
- COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/android-build
- VERBATIM)
- endif()
-
- # Write the android_<project_name>_deployment_settings.json file
- file(WRITE ${CMAKE_BINARY_DIR}/android_deployment_settings.json.in
-[=[{
- "_description": "This file is created by CMake to be read by androiddeployqt and should not be modified by hand.",
- "application-binary": "@QT_ANDROID_APPLICATION_BINARY@",
- "architectures": {
-@QT_ANDROID_ARCHITECTURES@
- },
- @QT_ANDROID_DEPLOYMENT_DEPENDENCIES@
- @QT_ANDROID_EXTRA_PLUGINS@
- @QT_ANDROID_PACKAGE_SOURCE_DIR@
- @QT_ANDROID_VERSION_CODE@
- @QT_ANDROID_VERSION_NAME@
- @QT_ANDROID_EXTRA_LIBS@
- @QT_QML_IMPORT_PATH@
- "ndk": "@ANDROID_NDK@",
- "ndk-host": "@ANDROID_HOST_TAG@",
- "qml-root-path": "@CMAKE_CURRENT_SOURCE_DIR@",
- "qt": "@QT_DIR@",
- "sdk": "@ANDROID_SDK@",
- "stdcpp-path": "@ANDROID_TOOLCHAIN_ROOT@/sysroot/usr/lib/",
- "tool-prefix": "llvm",
- "toolchain-prefix": "llvm",
- "useLLVM": true
-}]=])
-
- if (NOT QT_ANDROID_APPLICATION_BINARY)
- set(QT_ANDROID_APPLICATION_BINARY ${PROJECT_NAME})
- endif()
-
- if(NOT ANDROID_SDK)
- get_filename_component(ANDROID_SDK ${ANDROID_NDK}/../ ABSOLUTE)
- endif()
-
- find_program(ANDROID_DEPLOY_QT androiddeployqt)
- get_filename_component(QT_DIR ${ANDROID_DEPLOY_QT}/../../ ABSOLUTE)
-
- unset(QT_ANDROID_ARCHITECTURES)
- foreach(abi IN LISTS ANDROID_ABIS)
- if (ANDROID_BUILD_ABI_${abi})
- list(APPEND QT_ANDROID_ARCHITECTURES " \"${abi}\" : \"${ANDROID_SYSROOT_${abi}}\"")
- endif()
- endforeach()
- string(REPLACE ";" ",\n" QT_ANDROID_ARCHITECTURES "${QT_ANDROID_ARCHITECTURES}")
-
- macro(generate_json_variable_list var_list json_key)
- if (${var_list})
- set(QT_${var_list} "\"${json_key}\": \"")
- string(REPLACE ";" "," joined_var_list "${${var_list}}")
- string(APPEND QT_${var_list} "${joined_var_list}\",")
- endif()
- endmacro()
-
- macro(generate_json_variable var json_key)
- if (${var})
- set(QT_${var} "\"${json_key}\": \"${${var}}\",")
- endif()
- endmacro()
-
- generate_json_variable_list(ANDROID_DEPLOYMENT_DEPENDENCIES "deployment-dependencies")
- generate_json_variable_list(ANDROID_EXTRA_PLUGINS "android-extra-plugins")
- generate_json_variable(ANDROID_PACKAGE_SOURCE_DIR "android-package-source-directory")
- generate_json_variable(ANDROID_VERSION_CODE "android-version-code")
- generate_json_variable(ANDROID_VERSION_NAME "android-version-name")
- generate_json_variable_list(ANDROID_EXTRA_LIBS "android-extra-libs")
- generate_json_variable_list(QML_IMPORT_PATH "qml-import-paths")
- generate_json_variable_list(ANDROID_MIN_SDK_VERSION "android-min-sdk-version")
- generate_json_variable_list(ANDROID_TARGET_SDK_VERSION "android-target-sdk-version")
-
-
- configure_file(
- "${CMAKE_BINARY_DIR}/android_deployment_settings.json.in"
- "${CMAKE_BINARY_DIR}/android_deployment_settings.json" @ONLY)
-
- # Create "apk" and "aab" targets
- if (DEFINED ENV{JAVA_HOME})
- set(JAVA_HOME $ENV{JAVA_HOME} CACHE INTERNAL "Saved JAVA_HOME variable")
- endif()
- if (JAVA_HOME)
- set(android_deploy_qt_jdk "--jdk ${JAVA_HOME}")
- endif()
-
- if (ANDROID_SDK_PLATFORM)
- set(android_deploy_qt_platform "--android-platform ${ANDROID_SDK_PLATFORM}")
- endif()
-
- add_custom_target(apk
- COMMAND ${CMAKE_COMMAND} -E env JAVA_HOME=${JAVA_HOME} ${ANDROID_DEPLOY_QT}
- --input "${CMAKE_BINARY_DIR}/android_deployment_settings.json"
- --output "${CMAKE_BINARY_DIR}/android-build"
- --apk "${CMAKE_BINARY_DIR}/android-build/${PROJECT_NAME}.apk"
- ${android_deploy_qt_platform}
- ${android_deploy_qt_jdk}
- VERBATIM)
-
- add_custom_target(aab
- COMMAND ${CMAKE_COMMAND} -E env JAVA_HOME=${JAVA_HOME} ${ANDROID_DEPLOY_QT}
- --input "${CMAKE_BINARY_DIR}/android_deployment_settings.json"
- --output "${CMAKE_BINARY_DIR}/android-build"
- --apk "${CMAKE_BINARY_DIR}/android-build/${PROJECT_NAME}.apk"
- --aab
- ${android_deploy_qt_platform}
- ${android_deploy_qt_jdk}
- VERBATIM)
-
- include(ExternalProject)
- macro (setup_library library_name android_abi)
- # Use Qt Creator's 4.12 settings file if present
- unset(QTC_SETTINGS_PARAMETER)
- if (EXISTS ${CMAKE_BINARY_DIR}/qtcsettings.cmake)
- set(QTC_SETTINGS_PARAMETER -C ${CMAKE_BINARY_DIR}/qtcsettings.cmake)
- endif()
-
- # Build all the given ABI as an external project
- ExternalProject_Add(${library_name}-builder
- SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
- PREFIX MultiAbi
- BUILD_ALWAYS YES
- DOWNLOAD_COMMAND ""
- INSTALL_COMMAND ""
- UPDATE_COMMAND ""
- PATCH_COMMAND ""
- CMAKE_ARGS
- ${QTC_SETTINGS_PARAMETER}
- -D ANDROID_ABI=${android_abi}
- -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}
- -D CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}
- -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
- -D ANDROID_PLATFORM=${ANDROID_PLATFORM}
- -D ANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL}
- -D CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
- -D CMAKE_FIND_ROOT_PATH_MODE_PROGRAM=${CMAKE_FIND_ROOT_PATH_MODE_PROGRAM}
- -D CMAKE_FIND_ROOT_PATH_MODE_LIBRARY=${CMAKE_FIND_ROOT_PATH_MODE_LIBRARY}
- -D CMAKE_FIND_ROOT_PATH_MODE_INCLUDE=${CMAKE_FIND_ROOT_PATH_MODE_INCLUDE}
- -D CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=${CMAKE_FIND_ROOT_PATH_MODE_PACKAGE}
- -D CMAKE_SHARED_LIBRARY_SUFFIX_CXX=_${android_abi}.so
- -D CMAKE_SHARED_MODULE_SUFFIX_CXX=_${android_abi}.so
- -D CMAKE_SHARED_LIBRARY_SUFFIX_C=_${android_abi}.so
- -D CMAKE_SHARED_MODULE_SUFFIX_C=_${android_abi}.so
- -D CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_BINARY_DIR}/android-build/libs/${android_abi}
- -D ${PROJECT_NAME}-MultiAbiBuild=ON
- )
- endmacro()
-
- foreach(abi IN LISTS ANDROID_ABIS)
- if (NOT abi STREQUAL ${ANDROID_ABI})
- if (ANDROID_BUILD_ABI_${abi})
- setup_library(${PROJECT_NAME}-${abi} ${abi} ${CMAKE_PREFIX_PATH})
- endif()
- else()
- # For the default abi just use the regular cmake run, to have
- # nice IDE integration and so on
- set(CMAKE_SHARED_MODULE_SUFFIX_CXX "_${ANDROID_ABI}.so")
- set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX "_${ANDROID_ABI}.so")
- set(CMAKE_SHARED_MODULE_SUFFIX_C "_${ANDROID_ABI}.so")
- set(CMAKE_SHARED_LIBRARY_SUFFIX_C "_${ANDROID_ABI}.so")
- set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/android-build/libs/${ANDROID_ABI})
- endif()
- endforeach()
-else()
- # unset the variable, just not to issue an unused variable warning
- unset(${PROJECT_NAME}-MultiAbiBuild)
-endif()
diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake
deleted file mode 100644
index 88350cb68b..0000000000
--- a/src/corelib/Qt5CoreMacros.cmake
+++ /dev/null
@@ -1,507 +0,0 @@
-#=============================================================================
-# Copyright 2005-2011 Kitware, Inc.
-# Copyright (C) 2020 The Qt Company Ltd.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# * Neither the name of Kitware, Inc. nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#=============================================================================
-
-######################################
-#
-# Macros for building Qt files
-#
-######################################
-
-include(CMakeParseArguments)
-
-function(_qt5_warn_deprecated command_name)
- if(NOT DEFINED _QT5_INTERNAL_SCOPE)
- message(AUTHOR_WARNING
- "${command_name} is not part of the official API, and might be removed in Qt 6.")
- endif()
-endfunction()
-
-# macro used to create the names of output files preserving relative dirs
-macro(qt5_make_output_file infile prefix ext outfile )
- _qt5_warn_deprecated("qt5_make_output_file")
-
- string(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength)
- string(LENGTH ${infile} _infileLength)
- set(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR})
- if(_infileLength GREATER _binlength)
- string(SUBSTRING "${infile}" 0 ${_binlength} _checkinfile)
- if(_checkinfile STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
- file(RELATIVE_PATH rel ${CMAKE_CURRENT_BINARY_DIR} ${infile})
- else()
- file(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${infile})
- endif()
- else()
- file(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${infile})
- endif()
- if(WIN32 AND rel MATCHES "^([a-zA-Z]):(.*)$") # absolute path
- set(rel "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}")
- endif()
- set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${rel}")
- string(REPLACE ".." "__" _outfile ${_outfile})
- get_filename_component(outpath ${_outfile} PATH)
- if(CMAKE_VERSION VERSION_LESS "3.14")
- get_filename_component(_outfile_ext ${_outfile} EXT)
- get_filename_component(_outfile_ext ${_outfile_ext} NAME_WE)
- get_filename_component(_outfile ${_outfile} NAME_WE)
- string(APPEND _outfile ${_outfile_ext})
- else()
- get_filename_component(_outfile ${_outfile} NAME_WLE)
- endif()
- file(MAKE_DIRECTORY ${outpath})
- set(${outfile} ${outpath}/${prefix}${_outfile}.${ext})
-endmacro()
-
-
-macro(qt5_get_moc_flags _moc_flags)
- _qt5_warn_deprecated("qt5_get_moc_flags")
-
- set(${_moc_flags})
- get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES)
-
- if(CMAKE_INCLUDE_CURRENT_DIR)
- list(APPEND _inc_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
- endif()
-
- foreach(_current ${_inc_DIRS})
- if("${_current}" MATCHES "\\.framework/?$")
- string(REGEX REPLACE "/[^/]+\\.framework" "" framework_path "${_current}")
- set(${_moc_flags} ${${_moc_flags}} "-F${framework_path}")
- else()
- set(${_moc_flags} ${${_moc_flags}} "-I${_current}")
- endif()
- endforeach()
-
- get_directory_property(_defines COMPILE_DEFINITIONS)
- foreach(_current ${_defines})
- set(${_moc_flags} ${${_moc_flags}} "-D${_current}")
- endforeach()
-
- if(WIN32)
- set(${_moc_flags} ${${_moc_flags}} -DWIN32)
- endif()
- if (MSVC)
- set(${_moc_flags} ${${_moc_flags}} --compiler-flavor=msvc)
- endif()
-endmacro()
-
-
-# helper macro to set up a moc rule
-function(qt5_create_moc_command infile outfile moc_flags moc_options moc_target moc_depends)
- _qt5_warn_deprecated("qt5_create_moc_command")
-
- # Pass the parameters in a file. Set the working directory to
- # be that containing the parameters file and reference it by
- # just the file name. This is necessary because the moc tool on
- # MinGW builds does not seem to handle spaces in the path to the
- # file given with the @ syntax.
- get_filename_component(_moc_outfile_name "${outfile}" NAME)
- get_filename_component(_moc_outfile_dir "${outfile}" PATH)
- if(_moc_outfile_dir)
- set(_moc_working_dir WORKING_DIRECTORY ${_moc_outfile_dir})
- endif()
- set (_moc_parameters_file ${outfile}_parameters)
- set (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}")
- string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}")
-
- if(moc_target)
- set(_moc_parameters_file ${_moc_parameters_file}$<$<BOOL:$<CONFIGURATION>>:_$<CONFIGURATION>>)
- set(targetincludes "$<TARGET_PROPERTY:${moc_target},INCLUDE_DIRECTORIES>")
- set(targetdefines "$<TARGET_PROPERTY:${moc_target},COMPILE_DEFINITIONS>")
-
- set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},\n-I>\n>")
- set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},\n-D>\n>")
-
- file (GENERATE
- OUTPUT ${_moc_parameters_file}
- CONTENT "${targetdefines}${targetincludes}${_moc_parameters}\n"
- )
-
- set(targetincludes)
- set(targetdefines)
- else()
- file(WRITE ${_moc_parameters_file} "${_moc_parameters}\n")
- endif()
-
- set(_moc_extra_parameters_file @${_moc_parameters_file})
- add_custom_command(OUTPUT ${outfile}
- COMMAND ${Qt5Core_MOC_EXECUTABLE} ${_moc_extra_parameters_file}
- DEPENDS ${infile} ${moc_depends}
- ${_moc_working_dir}
- VERBATIM)
- set_source_files_properties(${infile} PROPERTIES SKIP_AUTOMOC ON)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
-endfunction()
-
-
-function(qt5_generate_moc infile outfile )
- set(_QT5_INTERNAL_SCOPE ON)
-
- # get include dirs and flags
- qt5_get_moc_flags(moc_flags)
- get_filename_component(abs_infile ${infile} ABSOLUTE)
- set(_outfile "${outfile}")
- if(NOT IS_ABSOLUTE "${outfile}")
- set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}")
- endif()
- if ("x${ARGV2}" STREQUAL "xTARGET")
- set(moc_target ${ARGV3})
- endif()
- qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "")
-endfunction()
-
-if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_generate_moc)
- if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
- qt5_generate_moc(${ARGV})
- elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
- qt6_generate_moc(${ARGV})
- endif()
- endfunction()
-endif()
-
-
-# qt5_wrap_cpp(outfiles inputfile ... )
-
-function(qt5_wrap_cpp outfiles)
- set(_QT5_INTERNAL_SCOPE ON)
-
- # get include dirs
- qt5_get_moc_flags(moc_flags)
-
- set(options)
- set(oneValueArgs TARGET)
- set(multiValueArgs OPTIONS DEPENDS)
-
- cmake_parse_arguments(_WRAP_CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
- set(moc_files ${_WRAP_CPP_UNPARSED_ARGUMENTS})
- set(moc_options ${_WRAP_CPP_OPTIONS})
- set(moc_target ${_WRAP_CPP_TARGET})
- set(moc_depends ${_WRAP_CPP_DEPENDS})
-
- foreach(it ${moc_files})
- get_filename_component(it ${it} ABSOLUTE)
- qt5_make_output_file(${it} moc_ cpp outfile)
- qt5_create_moc_command(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}" "${moc_depends}")
- list(APPEND ${outfiles} ${outfile})
- endforeach()
- set(${outfiles} ${${outfiles}} PARENT_SCOPE)
-endfunction()
-
-# This will override the CMake upstream command, because that one is for Qt 3.
-if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_wrap_cpp outfiles)
- if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
- qt5_wrap_cpp("${outfiles}" ${ARGN})
- elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
- qt6_wrap_cpp("${outfiles}" ${ARGN})
- endif()
- set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
- endfunction()
-endif()
-
-
-# _qt5_parse_qrc_file(infile _out_depends _rc_depends)
-# internal
-
-function(_qt5_parse_qrc_file infile _out_depends _rc_depends)
- get_filename_component(rc_path ${infile} PATH)
-
- if(EXISTS "${infile}")
- # parse file for dependencies
- # all files are absolute paths or relative to the location of the qrc file
- file(READ "${infile}" RC_FILE_CONTENTS)
- string(REGEX MATCHALL "<file[^<]+" RC_FILES "${RC_FILE_CONTENTS}")
- foreach(RC_FILE ${RC_FILES})
- string(REGEX REPLACE "^<file[^>]*>" "" RC_FILE "${RC_FILE}")
- if(NOT IS_ABSOLUTE "${RC_FILE}")
- set(RC_FILE "${rc_path}/${RC_FILE}")
- endif()
- set(RC_DEPENDS ${RC_DEPENDS} "${RC_FILE}")
- endforeach()
- # Since this cmake macro is doing the dependency scanning for these files,
- # let's make a configured file and add it as a dependency so cmake is run
- # again when dependencies need to be recomputed.
- qt5_make_output_file("${infile}" "" "qrc.depends" out_depends)
- configure_file("${infile}" "${out_depends}" COPYONLY)
- else()
- # The .qrc file does not exist (yet). Let's add a dependency and hope
- # that it will be generated later
- set(out_depends)
- endif()
-
- set(${_out_depends} ${out_depends} PARENT_SCOPE)
- set(${_rc_depends} ${RC_DEPENDS} PARENT_SCOPE)
-endfunction()
-
-
-# qt5_add_binary_resources(target inputfiles ... )
-
-function(qt5_add_binary_resources target)
- set(_QT5_INTERNAL_SCOPE ON)
-
- set(options)
- set(oneValueArgs DESTINATION)
- set(multiValueArgs OPTIONS)
-
- cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
- set(rcc_files ${_RCC_UNPARSED_ARGUMENTS})
- set(rcc_options ${_RCC_OPTIONS})
- set(rcc_destination ${_RCC_DESTINATION})
-
- if(NOT rcc_destination)
- set(rcc_destination ${CMAKE_CURRENT_BINARY_DIR}/${target}.rcc)
- endif()
-
- foreach(it ${rcc_files})
- get_filename_component(infile ${it} ABSOLUTE)
-
- _qt5_parse_qrc_file(${infile} _out_depends _rc_depends)
- set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
- set(infiles ${infiles} ${infile})
- set(out_depends ${out_depends} ${_out_depends})
- set(rc_depends ${rc_depends} ${_rc_depends})
- endforeach()
-
- add_custom_command(OUTPUT ${rcc_destination}
- COMMAND ${Qt5Core_RCC_EXECUTABLE}
- ARGS ${rcc_options} --binary --name ${target} --output ${rcc_destination} ${infiles}
- DEPENDS ${rc_depends} ${out_depends} ${infiles} VERBATIM)
- add_custom_target(${target} ALL DEPENDS ${rcc_destination})
-endfunction()
-
-if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_add_binary_resources)
- if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
- qt5_add_binary_resources(${ARGV})
- elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
- qt6_add_binary_resources(${ARGV})
- endif()
- endfunction()
-endif()
-
-
-# qt5_add_resources(outfiles inputfile ... )
-
-function(qt5_add_resources outfiles)
- set(_QT5_INTERNAL_SCOPE ON)
-
- set(options)
- set(oneValueArgs)
- set(multiValueArgs OPTIONS)
-
- cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
- set(rcc_files ${_RCC_UNPARSED_ARGUMENTS})
- set(rcc_options ${_RCC_OPTIONS})
-
- if("${rcc_options}" MATCHES "-binary")
- message(WARNING "Use qt5_add_binary_resources for binary option")
- endif()
-
- foreach(it ${rcc_files})
- get_filename_component(outfilename ${it} NAME_WE)
- get_filename_component(infile ${it} ABSOLUTE)
- set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp)
-
- _qt5_parse_qrc_file(${infile} _out_depends _rc_depends)
- set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
-
- add_custom_command(OUTPUT ${outfile}
- COMMAND ${Qt5Core_RCC_EXECUTABLE}
- ARGS ${rcc_options} --name ${outfilename} --output ${outfile} ${infile}
- MAIN_DEPENDENCY ${infile}
- DEPENDS ${_rc_depends} "${_out_depends}" VERBATIM)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
- list(APPEND ${outfiles} ${outfile})
- endforeach()
- set(${outfiles} ${${outfiles}} PARENT_SCOPE)
-endfunction()
-
-if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_add_resources outfiles)
- if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
- qt5_add_resources("${outfiles}" ${ARGN})
- elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
- qt6_add_resources("${outfiles}" ${ARGN})
- endif()
- set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
- endfunction()
-endif()
-
-
-# qt5_add_big_resources(outfiles inputfile ... )
-
-function(qt5_add_big_resources outfiles)
- set(_QT5_INTERNAL_SCOPE ON)
-
- if (CMAKE_VERSION VERSION_LESS 3.9)
- message(FATAL_ERROR, "qt5_add_big_resources requires CMake 3.9 or newer")
- endif()
-
- set(options)
- set(oneValueArgs)
- set(multiValueArgs OPTIONS)
-
- cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
- set(rcc_files ${_RCC_UNPARSED_ARGUMENTS})
- set(rcc_options ${_RCC_OPTIONS})
-
- if("${rcc_options}" MATCHES "-binary")
- message(WARNING "Use qt5_add_binary_resources for binary option")
- endif()
-
- foreach(it ${rcc_files})
- get_filename_component(outfilename ${it} NAME_WE)
- get_filename_component(infile ${it} ABSOLUTE)
- set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp)
- set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o)
-
- _qt5_parse_qrc_file(${infile} _out_depends _rc_depends)
- set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
- add_custom_command(OUTPUT ${tmpoutfile}
- COMMAND ${Qt5Core_RCC_EXECUTABLE} ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile}
- DEPENDS ${infile} ${_rc_depends} "${out_depends}" VERBATIM)
- add_custom_target(big_resources_${outfilename} ALL DEPENDS ${tmpoutfile})
- add_library(rcc_object_${outfilename} OBJECT ${tmpoutfile})
- set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOMOC OFF)
- set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOUIC OFF)
- add_dependencies(rcc_object_${outfilename} big_resources_${outfilename})
- # The modification of TARGET_OBJECTS needs the following change in cmake
- # https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f
- add_custom_command(OUTPUT ${outfile}
- COMMAND ${Qt5Core_RCC_EXECUTABLE}
- ARGS ${rcc_options} --name ${outfilename} --pass 2 --temp $<TARGET_OBJECTS:rcc_object_${outfilename}> --output ${outfile} ${infile}
- DEPENDS rcc_object_${outfilename}
- VERBATIM)
- list(APPEND ${outfiles} ${outfile})
- endforeach()
- set(${outfiles} ${${outfiles}} PARENT_SCOPE)
-endfunction()
-
-if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_add_big_resources outfiles)
- if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
- qt5_add_big_resources(${outfiles} ${ARGN})
- elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
- qt6_add_big_resources(${outfiles} ${ARGN})
- endif()
- set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
- endfunction()
-endif()
-
-
-set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
-
-macro(qt5_use_modules _target _link_type)
- _qt5_warn_deprecated("qt5_use_modules")
-
- if (NOT TARGET ${_target})
- message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.")
- endif()
- if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" )
- set(_qt5_modules ${ARGN})
- set(_qt5_link_type ${_link_type})
- else()
- set(_qt5_modules ${_link_type} ${ARGN})
- endif()
-
- if ("${_qt5_modules}" STREQUAL "")
- message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.")
- endif()
-
- foreach(_module ${_qt5_modules})
- if (NOT Qt5${_module}_FOUND)
- find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH)
- if (NOT Qt5${_module}_FOUND)
- message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.")
- endif()
- endif()
- target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES})
- set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS})
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS})
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
- if (Qt5_POSITION_INDEPENDENT_CODE
- AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
- OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
- set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})
- endif()
- endforeach()
-endmacro()
-
-function(qt5_import_plugins TARGET_NAME)
- set(_doing "")
- foreach(_arg ${ARGN})
- if(_arg STREQUAL "INCLUDE")
- set(_doing "INCLUDE")
- elseif(_arg STREQUAL "EXCLUDE")
- set(_doing "EXCLUDE")
- elseif(_arg STREQUAL "INCLUDE_BY_TYPE")
- set(_doing "INCLUDE_BY_TYPE")
- elseif(_arg STREQUAL "EXCLUDE_BY_TYPE")
- set(_doing "EXCLUDE_BY_TYPE")
- else()
- if(_doing STREQUAL "INCLUDE")
- set_property(TARGET ${TARGET_NAME} APPEND PROPERTY QT_PLUGINS "${_arg}")
- elseif(_doing STREQUAL "EXCLUDE")
- set_property(TARGET ${TARGET_NAME} APPEND PROPERTY QT_NO_PLUGINS "${_arg}")
- elseif(_doing STREQUAL "INCLUDE_BY_TYPE")
- string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}")
- set(_doing "INCLUDE_BY_TYPE_PLUGINS")
- elseif(_doing STREQUAL "INCLUDE_BY_TYPE_PLUGINS")
- set_property(TARGET ${TARGET_NAME} APPEND PROPERTY "QT_PLUGINS_${_plugin_type}" "${_arg}")
- elseif(_doing STREQUAL "EXCLUDE_BY_TYPE")
- string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}")
- set_property(TARGET ${TARGET_NAME} PROPERTY "QT_PLUGINS_${_plugin_type}" -)
- else()
- message(FATAL_ERROR "Unexpected extra argument: \"${_arg}\"")
- endif()
- endif()
- endforeach()
-endfunction()
-
-if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_import_plugins)
- if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
- qt5_import_plugins(${ARGV})
- elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
- qt6_import_plugins(${ARGV})
- endif()
- endfunction()
-endif()
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
new file mode 100644
index 0000000000..6218df1947
--- /dev/null
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -0,0 +1,1513 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Generate deployment tool json
+
+# Locate newest Android sdk build tools revision
+function(_qt_internal_android_get_sdk_build_tools_revision out_var)
+ if (NOT QT_ANDROID_SDK_BUILD_TOOLS_REVISION)
+ file(GLOB android_build_tools
+ LIST_DIRECTORIES true
+ RELATIVE "${ANDROID_SDK_ROOT}/build-tools"
+ "${ANDROID_SDK_ROOT}/build-tools/*")
+ if (NOT android_build_tools)
+ message(FATAL_ERROR "Could not locate Android SDK build tools under \"${ANDROID_SDK_ROOT}/build-tools\"")
+ endif()
+ list(SORT android_build_tools)
+ list(REVERSE android_build_tools)
+ list(GET android_build_tools 0 android_build_tools_latest)
+ endif()
+ set(${out_var} "${android_build_tools_latest}" PARENT_SCOPE)
+endfunction()
+
+# The function appends to the 'out_var' a 'json_property' that contains the 'tool' path. If 'tool'
+# target or its IMPORTED_LOCATION are not found the function displays warning, but is not failing
+# at the project configuring phase.
+function(_qt_internal_add_tool_to_android_deployment_settings out_var tool json_property target)
+ unset(tool_binary_path)
+ __qt_internal_get_tool_imported_location(tool_binary_path ${tool})
+ if("${tool_binary_path}" STREQUAL "")
+ # Fallback search for the tool in host bin and host libexec directories
+ find_program(tool_binary_path
+ NAMES ${tool} ${tool}.exe
+ PATHS
+ "${QT_HOST_PATH}/${QT6_HOST_INFO_BINDIR}"
+ "${QT_HOST_PATH}/${QT6_HOST_INFO_LIBEXECDIR}"
+ NO_DEFAULT_PATH
+ )
+ if(NOT tool_binary_path)
+ message(WARNING "Unable to locate ${tool}. Android package deployment of ${target}"
+ " target can be incomplete. Make sure the host Qt has ${tool} installed.")
+ return()
+ endif()
+ endif()
+
+ file(TO_CMAKE_PATH "${tool_binary_path}" tool_binary_path)
+ string(APPEND ${out_var}
+ " \"${json_property}\" : \"${tool_binary_path}\",\n")
+
+ set(${out_var} "${${out_var}}" PARENT_SCOPE)
+endfunction()
+
+# Generate the deployment settings json file for a cmake target.
+function(qt6_android_generate_deployment_settings target)
+ # Information extracted from mkspecs/features/android/android_deployment_settings.prf
+ if (NOT TARGET ${target})
+ message(FATAL_ERROR "${target} is not a cmake target")
+ endif()
+
+ # When parsing JSON file format backslashes and follow up symbols are regarded as special
+ # characters. This puts Windows path format into a trouble.
+ # _qt_internal_android_format_deployment_paths converts sensitive paths to the CMake format
+ # that is supported by JSON as well. The function should be called as many times as
+ # qt6_android_generate_deployment_settings, because users may change properties that contain
+ # paths in between the calls.
+ _qt_internal_android_format_deployment_paths(${target})
+
+ # Avoid calling the function body twice because of 'file(GENERATE'.
+ get_target_property(is_called ${target} _qt_is_android_generate_deployment_settings_called)
+ if(is_called)
+ return()
+ endif()
+ set_target_properties(${target} PROPERTIES
+ _qt_is_android_generate_deployment_settings_called TRUE
+ )
+
+ get_target_property(android_executable_finalizer_called
+ ${target} _qt_android_executable_finalizer_called)
+
+ if(android_executable_finalizer_called)
+ # Don't show deprecation when called by our own function implementations.
+ else()
+ message(DEPRECATION
+ "Calling qt_android_generate_deployment_settings directly is deprecated since Qt 6.5. "
+ "Use qt_add_executable instead.")
+ endif()
+
+ get_target_property(target_type ${target} TYPE)
+
+ if (NOT "${target_type}" STREQUAL "MODULE_LIBRARY")
+ message(SEND_ERROR "QT_ANDROID_GENERATE_DEPLOYMENT_SETTINGS only works on Module targets")
+ return()
+ endif()
+
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+ get_target_property(target_output_name ${target} OUTPUT_NAME)
+ if (NOT target_output_name)
+ set(target_output_name ${target})
+ endif()
+
+ # QtCreator requires the file name of deployment settings has no config related suffixes
+ # to run androiddeployqt correctly. If we use multi-config generator for the first config
+ # in a list avoid adding any configuration-specific suffixes.
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
+ set(config_suffix "$<$<NOT:$<CONFIG:${first_config_type}>>:-$<CONFIG>>")
+ endif()
+ set(deploy_file
+ "${target_binary_dir}/android-${target}-deployment-settings${config_suffix}.json")
+
+ set(file_contents "{\n")
+ # content begin
+ string(APPEND file_contents
+ " \"description\": \"This file is generated by cmake to be read by androiddeployqt and should not be modified by hand.\",\n")
+
+ # Host Qt Android install path
+ if (NOT QT_BUILDING_QT OR QT_STANDALONE_TEST_PATH)
+ set(qt_path "${QT6_INSTALL_PREFIX}")
+ set(android_plugin_dir_path "${qt_path}/${QT6_INSTALL_PLUGINS}/platforms")
+ set(glob_expression "${android_plugin_dir_path}/*qtforandroid*${CMAKE_ANDROID_ARCH_ABI}.so")
+ file(GLOB plugin_dir_files LIST_DIRECTORIES FALSE "${glob_expression}")
+ if (NOT plugin_dir_files)
+ message(SEND_ERROR
+ "Detected Qt installation does not contain qtforandroid_${CMAKE_ANDROID_ARCH_ABI}.so in the following dir:\n"
+ "${android_plugin_dir_path}\n"
+ "This is most likely due to the installation not being a Qt for Android build. "
+ "Please recheck your build configuration.")
+ return()
+ else()
+ list(GET plugin_dir_files 0 android_platform_plugin_path)
+ message(STATUS "Found android platform plugin at: ${android_platform_plugin_path}")
+ endif()
+ endif()
+
+ _qt_internal_collect_qt_for_android_paths(file_contents)
+
+ # Android SDK path
+ file(TO_CMAKE_PATH "${ANDROID_SDK_ROOT}" android_sdk_root_native)
+ string(APPEND file_contents
+ " \"sdk\": \"${android_sdk_root_native}\",\n")
+
+ # Android SDK Build Tools Revision
+ _qt_internal_android_get_sdk_build_tools_revision(android_sdk_build_tools)
+ set(android_sdk_build_tools_genex "")
+ string(APPEND android_sdk_build_tools_genex
+ "$<IF:$<BOOL:$<TARGET_PROPERTY:${target},QT_ANDROID_SDK_BUILD_TOOLS_REVISION>>,"
+ "$<TARGET_PROPERTY:${target},QT_ANDROID_SDK_BUILD_TOOLS_REVISION>,"
+ "${android_sdk_build_tools}"
+ ">"
+ )
+ string(APPEND file_contents
+ " \"sdkBuildToolsRevision\": \"${android_sdk_build_tools_genex}\",\n")
+
+ # Android NDK
+ file(TO_CMAKE_PATH "${CMAKE_ANDROID_NDK}" android_ndk_root_native)
+ string(APPEND file_contents
+ " \"ndk\": \"${android_ndk_root_native}\",\n")
+
+ # Setup LLVM toolchain
+ string(APPEND file_contents
+ " \"toolchain-prefix\": \"llvm\",\n")
+ string(APPEND file_contents
+ " \"tool-prefix\": \"llvm\",\n")
+ string(APPEND file_contents
+ " \"useLLVM\": true,\n")
+
+ # NDK Toolchain Version
+ string(APPEND file_contents
+ " \"toolchain-version\": \"${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}\",\n")
+
+ # NDK Host
+ string(APPEND file_contents
+ " \"ndk-host\": \"${ANDROID_NDK_HOST_SYSTEM_NAME}\",\n")
+
+ get_target_property(qt_android_abis ${target} _qt_android_abis)
+ if(NOT qt_android_abis)
+ set(qt_android_abis "")
+ endif()
+ set(architecture_record_list "")
+ foreach(abi IN LISTS qt_android_abis CMAKE_ANDROID_ARCH_ABI)
+ if(abi STREQUAL "x86")
+ set(arch_value "i686-linux-android")
+ elseif(abi STREQUAL "x86_64")
+ set(arch_value "x86_64-linux-android")
+ elseif(abi STREQUAL "arm64-v8a")
+ set(arch_value "aarch64-linux-android")
+ elseif(abi)
+ set(arch_value "arm-linux-androideabi")
+ endif()
+ list(APPEND architecture_record_list "\"${abi}\":\"${arch_value}\"")
+ endforeach()
+
+ list(JOIN architecture_record_list "," architecture_records)
+ # Architecture
+ string(APPEND file_contents
+ " \"architectures\": { ${architecture_records} },\n")
+
+ # deployment dependencies
+ _qt_internal_add_android_deployment_multi_value_property(file_contents "deployment-dependencies"
+ ${target} "QT_ANDROID_DEPLOYMENT_DEPENDENCIES" )
+
+ # Extra plugins
+ _qt_internal_add_android_deployment_multi_value_property(file_contents "android-extra-plugins"
+ ${target} "_qt_android_native_extra_plugins" )
+
+ # Extra libs
+ _qt_internal_add_android_deployment_multi_value_property(file_contents "android-extra-libs"
+ ${target} "_qt_android_native_extra_libs" )
+
+ # Alternative path to Qt libraries on target device
+ _qt_internal_add_android_deployment_property(file_contents "android-system-libs-prefix"
+ ${target} "QT_ANDROID_SYSTEM_LIBS_PREFIX")
+
+ # package source dir
+ _qt_internal_add_android_deployment_property(file_contents "android-package-source-directory"
+ ${target} "_qt_android_native_package_source_dir")
+
+ # version code
+ _qt_internal_add_android_deployment_property(file_contents "android-version-code"
+ ${target} "QT_ANDROID_VERSION_CODE")
+
+ # version name
+ _qt_internal_add_android_deployment_property(file_contents "android-version-name"
+ ${target} "QT_ANDROID_VERSION_NAME")
+
+ # minimum SDK version
+ _qt_internal_add_android_deployment_property(file_contents "android-min-sdk-version"
+ ${target} "QT_ANDROID_MIN_SDK_VERSION")
+
+ # target SDK version
+ _qt_internal_add_android_deployment_property(file_contents "android-target-sdk-version"
+ ${target} "QT_ANDROID_TARGET_SDK_VERSION")
+
+ # should Qt shared libs be excluded from deployment
+ _qt_internal_add_android_deployment_property(file_contents "android-no-deploy-qt-libs"
+ ${target} "QT_ANDROID_NO_DEPLOY_QT_LIBS")
+
+ __qt_internal_collect_plugin_targets_from_dependencies("${target}" plugin_targets)
+ __qt_internal_collect_plugin_library_files("${target}" "${plugin_targets}" plugin_targets)
+ string(APPEND file_contents " \"android-deploy-plugins\":\"${plugin_targets}\",\n")
+
+ # App binary
+ string(APPEND file_contents
+ " \"application-binary\": \"${target_output_name}\",\n")
+
+ # App command-line arguments
+ if (QT_ANDROID_APPLICATION_ARGUMENTS)
+ string(APPEND file_contents
+ " \"android-application-arguments\": \"${QT_ANDROID_APPLICATION_ARGUMENTS}\",\n")
+ endif()
+
+ if(COMMAND _qt_internal_generate_android_qml_deployment_settings)
+ _qt_internal_generate_android_qml_deployment_settings(file_contents ${target})
+ else()
+ string(APPEND file_contents
+ " \"qml-skip-import-scanning\": true,\n")
+ endif()
+
+ # Override rcc binary path
+ _qt_internal_add_tool_to_android_deployment_settings(file_contents rcc "rcc-binary" "${target}")
+
+ # Extra prefix paths
+ foreach(prefix IN LISTS CMAKE_FIND_ROOT_PATH)
+ if (NOT "${prefix}" STREQUAL "${qt_android_install_dir_native}"
+ AND NOT "${prefix}" STREQUAL "${android_ndk_root_native}")
+ file(TO_CMAKE_PATH "${prefix}" prefix)
+ list(APPEND extra_prefix_list "\"${prefix}\"")
+ endif()
+ endforeach()
+ string (REPLACE ";" "," extra_prefix_list "${extra_prefix_list}")
+ string(APPEND file_contents
+ " \"extraPrefixDirs\" : [ ${extra_prefix_list} ],\n")
+
+ # Create an empty target for the cases when we need to generate deployment setting but
+ # qt_finalize_project is never called.
+ if(NOT TARGET _qt_internal_apk_dependencies AND NOT QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
+ add_custom_target(_qt_internal_apk_dependencies)
+ endif()
+
+ # Extra library paths that could be used as a dependency lookup path by androiddeployqt.
+ #
+ # Unlike 'extraPrefixDirs', the 'extraLibraryDirs' key doesn't expect the 'lib' subfolder
+ # when looking for dependencies.
+ # TODO: add a public target property accessible from user space
+ _qt_internal_add_android_deployment_list_property(file_contents "extraLibraryDirs"
+ ${target} "_qt_android_extra_library_dirs"
+ _qt_internal_apk_dependencies "_qt_android_extra_library_dirs"
+ )
+
+ if(QT_FEATURE_zstd)
+ set(is_zstd_enabled "true")
+ else()
+ set(is_zstd_enabled "false")
+ endif()
+ string(APPEND file_contents
+ " \"zstdCompression\": ${is_zstd_enabled},\n")
+
+ # Last item in json file
+
+ # base location of stdlibc++, will be suffixed by androiddeploy qt
+ # Sysroot is set by Android toolchain file and is composed of ANDROID_TOOLCHAIN_ROOT.
+ set(android_ndk_stdlib_base_path "${CMAKE_SYSROOT}/usr/lib/")
+ string(APPEND file_contents
+ " \"stdcpp-path\": \"${android_ndk_stdlib_base_path}\"\n")
+
+ # content end
+ string(APPEND file_contents "}\n")
+
+ file(GENERATE OUTPUT ${deploy_file} CONTENT "${file_contents}")
+
+ set_target_properties(${target}
+ PROPERTIES
+ QT_ANDROID_DEPLOYMENT_SETTINGS_FILE ${deploy_file}
+ )
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_android_generate_deployment_settings)
+ qt6_android_generate_deployment_settings(${ARGV})
+ endfunction()
+endif()
+
+function(qt6_android_apply_arch_suffix target)
+ get_target_property(called_from_qt_impl
+ ${target} _qt_android_apply_arch_suffix_called_from_qt_impl)
+ if(called_from_qt_impl)
+ # Don't show deprecation when called by our own function implementations.
+ else()
+ message(DEPRECATION
+ "Calling qt_android_apply_arch_suffix directly is deprecated since Qt 6.5. "
+ "Use qt_add_executable or qt_add_library instead.")
+ endif()
+
+ get_target_property(target_type ${target} TYPE)
+ if (target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
+ set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.so")
+ elseif (target_type STREQUAL "STATIC_LIBRARY")
+ set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.a")
+ endif()
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_android_apply_arch_suffix)
+ qt6_android_apply_arch_suffix(${ARGV})
+ endfunction()
+endif()
+
+# Add custom target to package the APK
+function(qt6_android_add_apk_target target)
+ # Avoid calling qt6_android_add_apk_target twice
+ get_property(apk_targets GLOBAL PROPERTY _qt_apk_targets)
+ if("${target}" IN_LIST apk_targets)
+ return()
+ endif()
+
+ get_target_property(android_executable_finalizer_called
+ ${target} _qt_android_executable_finalizer_called)
+
+ if(android_executable_finalizer_called)
+ # Don't show deprecation when called by our own function implementations.
+ else()
+ message(DEPRECATION
+ "Calling qt_android_add_apk_target directly is deprecated since Qt 6.5. "
+ "Use qt_add_executable instead.")
+ endif()
+
+ get_target_property(deployment_file ${target} QT_ANDROID_DEPLOYMENT_SETTINGS_FILE)
+ if (NOT deployment_file)
+ message(FATAL_ERROR "Target ${target} is not a valid android executable target\n")
+ endif()
+ # Use genex to get path to the deployment settings, the above check only to confirm that
+ # qt6_android_add_apk_target is called on an android executable target.
+ string(JOIN "" deployment_file
+ "$<GENEX_EVAL:"
+ "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>"
+ ">"
+ )
+
+ # Make global apk and aab targets depend on the current apk target.
+ if(TARGET aab)
+ add_dependencies(aab ${target}_make_aab)
+ endif()
+ if(TARGET apk)
+ add_dependencies(apk ${target}_make_apk)
+ _qt_internal_create_global_apk_all_target_if_needed()
+ endif()
+
+ set(deployment_tool "${QT_HOST_PATH}/${QT6_HOST_INFO_BINDIR}/androiddeployqt")
+ # No need to use genex for the BINARY_DIR since it's read-only.
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+
+ if($CACHE{QT_USE_TARGET_ANDROID_BUILD_DIR})
+ set(apk_final_dir "${target_binary_dir}/android-build-${target}")
+ else()
+ if(QT_USE_TARGET_ANDROID_BUILD_DIR)
+ message(WARNING "QT_USE_TARGET_ANDROID_BUILD_DIR needs to be set in CACHE")
+ endif()
+
+ get_property(known_android_build GLOBAL PROPERTY _qt_internal_known_android_build_dir)
+ get_property(already_warned GLOBAL PROPERTY _qt_internal_already_warned_android_build_dir)
+ set(apk_final_dir "${target_binary_dir}/android-build")
+ if(NOT QT_SKIP_ANDROID_BUILD_DIR_CHECK AND "${apk_final_dir}" IN_LIST known_android_build
+ AND NOT "${apk_final_dir}" IN_LIST already_warned)
+ message(WARNING "${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt contains multiple"
+ " Qt Android executable targets. This can lead to mixing of deployment artifacts"
+ " of targets defined there. Setting QT_USE_TARGET_ANDROID_BUILD_DIR=TRUE"
+ " allows building multiple executable targets within a single CMakeLists.txt."
+ " Note: This option is not supported by Qt Creator versions older than 13."
+ " Set QT_SKIP_ANDROID_BUILD_DIR_CHECK=TRUE to suppress this warning."
+ )
+ set_property(GLOBAL APPEND PROPERTY _qt_internal_already_warned_android_build_dir
+ "${apk_final_dir}")
+ else()
+ set_property(GLOBAL APPEND PROPERTY
+ _qt_internal_known_android_build_dir "${apk_final_dir}")
+ endif()
+ endif()
+
+ set(apk_file_name "${target}.apk")
+ set(dep_file_name "${target}.d")
+ set(apk_final_file_path "${apk_final_dir}/${apk_file_name}")
+ set(dep_file_path "${apk_final_dir}/${dep_file_name}")
+ set(target_file_copy_relative_path
+ "libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
+
+ set(extra_deps "")
+
+ if(QT_ENABLE_VERBOSE_DEPLOYMENT)
+ set(uses_terminal USES_TERMINAL)
+ endif()
+
+ # Plugins still might be added after creating the deployment targets.
+ if(NOT TARGET qt_internal_plugins)
+ add_custom_target(qt_internal_plugins)
+ endif()
+ # Before running androiddeployqt, we need to make sure all plugins are built.
+ list(APPEND extra_deps qt_internal_plugins)
+
+ # This target is used by Qt Creator's Android support and by the ${target}_make_apk target
+ # in case DEPFILEs are not supported.
+ # Also the target is used to copy the library that belongs to ${target} when building multi-abi
+ # apk to the abi-specific directory.
+ _qt_internal_copy_file_if_different_command(copy_command
+ "$<TARGET_FILE:${target}>"
+ "${apk_final_dir}/${target_file_copy_relative_path}"
+ )
+ add_custom_target(${target}_prepare_apk_dir ALL
+ DEPENDS ${target} ${extra_deps}
+ COMMAND ${copy_command}
+ COMMENT "Copying ${target} binary to apk folder"
+ ${uses_terminal}
+ )
+
+ set(sign_apk "")
+ if(QT_ANDROID_SIGN_APK)
+ set(sign_apk "--sign")
+ endif()
+ set(sign_aab "")
+ if(QT_ANDROID_SIGN_AAB)
+ set(sign_aab "--sign")
+ endif()
+
+ set(extra_args "")
+ if(QT_INTERNAL_NO_ANDROID_RCC_BUNDLE_CLEANUP)
+ list(APPEND extra_args "--no-rcc-bundle-cleanup")
+ endif()
+ if(QT_ENABLE_VERBOSE_DEPLOYMENT)
+ list(APPEND extra_args "--verbose")
+ endif()
+
+ if(QT_ANDROID_DEPLOY_RELEASE)
+ message(WARNING "QT_ANDROID_DEPLOY_RELEASE is not a valid Qt variable."
+ " Please set QT_ANDROID_DEPLOYMENT_TYPE to RELEASE instead.")
+ endif()
+ # Setting QT_ANDROID_DEPLOYMENT_TYPE to a value other than Release disables
+ # release package signing regardless of the build type.
+ if(QT_ANDROID_DEPLOYMENT_TYPE)
+ string(TOUPPER "${QT_ANDROID_DEPLOYMENT_TYPE}" deployment_type_upper)
+ if("${deployment_type_upper}" STREQUAL "RELEASE")
+ list(APPEND extra_args "--release")
+ endif()
+ elseif(NOT QT_BUILD_TESTS)
+ # Workaround for tests: do not set automatically --release flag if QT_BUILD_TESTS is set.
+ # Release package need to be signed. Signing is currently not supported by CI.
+ # What is more, also androidtestrunner is not working on release APKs,
+ # For example running "adb shell run-as" on release APK will finish with the error:
+ # run-as: Package '[PACKAGE-NAME]' is not debuggable
+ list(APPEND extra_args $<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:--release>)
+ endif()
+
+ _qt_internal_check_depfile_support(has_depfile_support)
+
+ if(has_depfile_support)
+ cmake_policy(PUSH)
+ if(POLICY CMP0116)
+ # Without explicitly setting this policy to NEW, we get a warning
+ # even though we ensure there's actually no problem here.
+ # See https://gitlab.kitware.com/cmake/cmake/-/issues/21959
+ cmake_policy(SET CMP0116 NEW)
+ set(relative_to_dir ${CMAKE_CURRENT_BINARY_DIR})
+ else()
+ set(relative_to_dir ${CMAKE_BINARY_DIR})
+ endif()
+
+ # Add custom command that creates the apk and triggers rebuild if files listed in
+ # ${dep_file_path} are changed.
+ add_custom_command(OUTPUT "${apk_final_file_path}"
+ COMMAND ${CMAKE_COMMAND}
+ -E copy "$<TARGET_FILE:${target}>"
+ "${apk_final_dir}/${target_file_copy_relative_path}"
+ COMMAND "${deployment_tool}"
+ --input "${deployment_file}"
+ --output "${apk_final_dir}"
+ --apk "${apk_final_file_path}"
+ --depfile "${dep_file_path}"
+ --builddir "${relative_to_dir}"
+ ${extra_args}
+ ${sign_apk}
+ COMMENT "Creating APK for ${target}"
+ DEPENDS "${target}" "${deployment_file}" ${extra_deps}
+ DEPFILE "${dep_file_path}"
+ VERBATIM
+ ${uses_terminal}
+ )
+ cmake_policy(POP)
+
+ # Create a ${target}_make_apk target to trigger the apk build.
+ add_custom_target(${target}_make_apk DEPENDS "${apk_final_file_path}")
+ else()
+ add_custom_target(${target}_make_apk
+ DEPENDS ${target}_prepare_apk_dir
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${apk_final_dir}
+ --apk ${apk_final_file_path}
+ ${extra_args}
+ ${sign_apk}
+ COMMENT "Creating APK for ${target}"
+ VERBATIM
+ ${uses_terminal}
+ )
+ endif()
+
+ # Add target triggering AAB creation. Since the _make_aab target is not added to the ALL
+ # set, we may avoid dependency check for it and admit that the target is "always out
+ # of date".
+ add_custom_target(${target}_make_aab
+ DEPENDS ${target}_prepare_apk_dir
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${apk_final_dir}
+ --apk ${apk_final_file_path}
+ --aab
+ ${sign_aab}
+ ${extra_args}
+ COMMENT "Creating AAB for ${target}"
+ ${uses_terminal}
+ )
+
+ if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
+ # When building per-ABI external projects we only need to copy ABI-specific libraries and
+ # resources to the "main" ABI android build folder.
+
+ if("${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}" STREQUAL "")
+ message(FATAL_ERROR "QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR is not set when building"
+ " ABI specific external project. This should not happen and might mean an issue"
+ " in Qt. Please report a bug with CMake traces attached.")
+ endif()
+ # Assume that external project mirrors build structure of the top-level ABI project and
+ # replace the build root when specifying the output directory of androiddeployqt.
+ file(RELATIVE_PATH androiddeployqt_output_path "${CMAKE_BINARY_DIR}" "${apk_final_dir}")
+ set(androiddeployqt_output_path
+ "${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}/${androiddeployqt_output_path}")
+ _qt_internal_copy_file_if_different_command(copy_command
+ "$<TARGET_FILE:${target}>"
+ "${androiddeployqt_output_path}/${target_file_copy_relative_path}"
+ )
+ if(has_depfile_support)
+ set(deploy_android_deps_dir "${apk_final_dir}/${target}_deploy_android")
+ set(timestamp_file "${deploy_android_deps_dir}/timestamp")
+ set(dep_file "${deploy_android_deps_dir}/${target}.d")
+ add_custom_command(OUTPUT "${timestamp_file}"
+ DEPENDS ${target} ${extra_deps}
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${deploy_android_deps_dir}"
+ COMMAND ${CMAKE_COMMAND} -E touch "${timestamp_file}"
+ COMMAND ${copy_command}
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${androiddeployqt_output_path}
+ --copy-dependencies-only
+ ${extra_args}
+ --depfile "${dep_file}"
+ --builddir "${CMAKE_BINARY_DIR}"
+ COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
+ DEPFILE "${dep_file}"
+ VERBATIM
+ ${uses_terminal}
+ )
+ add_custom_target(qt_internal_${target}_copy_apk_dependencies
+ DEPENDS "${timestamp_file}")
+ else()
+ add_custom_target(qt_internal_${target}_copy_apk_dependencies
+ DEPENDS ${target} ${extra_deps}
+ COMMAND ${copy_command}
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${androiddeployqt_output_path}
+ --copy-dependencies-only
+ ${extra_args}
+ COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
+ ${uses_terminal}
+ )
+ endif()
+ endif()
+
+ set_property(GLOBAL APPEND PROPERTY _qt_apk_targets ${target})
+ _qt_internal_collect_apk_dependencies_defer()
+ _qt_internal_collect_apk_imported_dependencies_defer("${target}")
+endfunction()
+
+function(_qt_internal_create_global_android_targets)
+ macro(_qt_internal_create_global_android_targets_impl target)
+ string(TOUPPER "${target}" target_upper)
+ if(NOT QT_NO_GLOBAL_${target_upper}_TARGET)
+ if(NOT TARGET ${target})
+ add_custom_target(${target} COMMENT "Building all apks")
+ endif()
+ endif()
+ endmacro()
+
+ # Create a top-level "apk" target for convenience, so that users can call 'ninja apk'.
+ # It will trigger building all the apk build targets that are added as part of the project.
+ # Allow opting out.
+ _qt_internal_create_global_android_targets_impl(apk)
+
+ # Create a top-level "aab" target for convenience, so that users can call 'ninja aab'.
+ # It will trigger building all the apk build targets that are added as part of the project.
+ # Allow opting out.
+ _qt_internal_create_global_android_targets_impl(aab)
+endfunction()
+
+# The function collects all known non-imported shared libraries that are created in the build tree.
+# It uses the CMake DEFER CALL feature if the CMAKE_VERSION is greater
+# than or equal to 3.19.
+# Note: Users that use cmake version less that 3.19 need to call qt_finalize_project
+# in the end of a project's top-level CMakeLists.txt.
+function(_qt_internal_collect_apk_dependencies_defer)
+ # User opted-out the functionality
+ if(QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
+ return()
+ endif()
+
+ get_property(is_called GLOBAL PROPERTY _qt_is_collect_apk_dependencies_defer_called)
+ if(is_called) # Already scheduled
+ return()
+ endif()
+ set_property(GLOBAL PROPERTY _qt_is_collect_apk_dependencies_defer_called TRUE)
+
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\"
+ CALL _qt_internal_collect_apk_dependencies)")
+ else()
+ # User don't want to see the warning
+ if(NOT QT_NO_WARN_BUILD_TREE_APK_DEPS)
+ message(WARNING
+ "The CMake version you use is less than 3.19. APK dependencies, that are a"
+ " part of the project tree, might not be collected correctly."
+ " Please call qt_finalize_project in the end of a project's top-level"
+ " CMakeLists.txt file to make sure that all the APK dependencies are"
+ " collected correctly."
+ " You can pass -DQT_NO_WARN_BUILD_TREE_APK_DEPS=ON when configuring the project"
+ " to silence the warning.")
+ endif()
+ endif()
+endfunction()
+
+# The function collects project-built shared libraries that might be dependencies for
+# the main apk targets. It stores their locations in a global custom target property.
+function(_qt_internal_collect_apk_dependencies)
+ # User opted-out the functionality
+ if(QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
+ return()
+ endif()
+
+ get_property(is_called GLOBAL PROPERTY _qt_is_collect_apk_dependencies_called)
+ if(is_called)
+ return()
+ endif()
+ set_property(GLOBAL PROPERTY _qt_is_collect_apk_dependencies_called TRUE)
+
+ get_property(apk_targets GLOBAL PROPERTY _qt_apk_targets)
+
+ _qt_internal_collect_buildsystem_targets(libs
+ "${CMAKE_SOURCE_DIR}" INCLUDE SHARED_LIBRARY MODULE_LIBRARY)
+ list(REMOVE_DUPLICATES libs)
+
+ if(NOT TARGET qt_internal_plugins)
+ add_custom_target(qt_internal_plugins)
+ endif()
+
+ foreach(lib IN LISTS libs)
+ if(NOT lib IN_LIST apk_targets)
+ list(APPEND extra_library_dirs "$<TARGET_FILE_DIR:${lib}>")
+ get_target_property(target_type ${lib} TYPE)
+ # We collect all MODULE_LIBRARY targets since target APK may have implicit dependency
+ # to the plugin that will cause the runtime issue. Plugins that were added using
+ # qt6_add_plugin should be already added to the qt_internal_plugins dependency list,
+ # but it's ok to re-add them.
+ if(target_type STREQUAL "MODULE_LIBRARY")
+ add_dependencies(qt_internal_plugins ${lib})
+ endif()
+ endif()
+ endforeach()
+
+ if(NOT TARGET _qt_internal_apk_dependencies)
+ add_custom_target(_qt_internal_apk_dependencies)
+ endif()
+ set_target_properties(_qt_internal_apk_dependencies PROPERTIES
+ _qt_android_extra_library_dirs "${extra_library_dirs}"
+ )
+endfunction()
+
+# This function collects all imported shared libraries that might be dependencies for
+# the main apk targets. The actual collection is deferred until the target's directory scope
+# is processed.
+# The function requires CMake 3.21 or later.
+function(_qt_internal_collect_apk_imported_dependencies_defer target)
+ # User opted-out of the functionality.
+ if(QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS)
+ return()
+ endif()
+
+ get_target_property(target_source_dir "${target}" SOURCE_DIR)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.21")
+ cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${target_source_dir}\"
+ CALL _qt_internal_collect_apk_imported_dependencies \"${target}\")")
+ endif()
+endfunction()
+
+# This function collects imported shared libraries that might be dependencies for
+# the main apk targets. It stores their locations on a custom target property for the given target.
+# The function requires CMake 3.21 or later.
+function(_qt_internal_collect_apk_imported_dependencies target)
+ # User opted-out the functionality
+ if(QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS)
+ return()
+ endif()
+
+ get_target_property(target_source_dir "${target}" SOURCE_DIR)
+ _qt_internal_collect_imported_shared_libraries_recursive(libs "${target_source_dir}")
+ list(REMOVE_DUPLICATES libs)
+
+ foreach(lib IN LISTS libs)
+ list(APPEND extra_library_dirs "$<TARGET_FILE_DIR:${lib}>")
+ endforeach()
+
+ set_property(TARGET "${target}" APPEND PROPERTY
+ _qt_android_extra_library_dirs "${extra_library_dirs}"
+ )
+endfunction()
+
+# This function recursively walks the current directory and its parent directories to collect
+# imported shared library targets.
+# The recursion goes upwards instead of downwards because imported targets are usually not global,
+# and we can't call get_target_property() on a target which is not available in the current
+# directory or parent scopes.
+# We also can't cache parent directories because the imported targets in a parent directory
+# might change in-between collection calls.
+# The function requires CMake 3.21 or later.
+function(_qt_internal_collect_imported_shared_libraries_recursive out_var subdir)
+ set(result "")
+
+ get_directory_property(imported_targets DIRECTORY "${subdir}" IMPORTED_TARGETS)
+ foreach(imported_target IN LISTS imported_targets)
+ get_target_property(target_type "${imported_target}" TYPE)
+ if(target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
+ # If the target has the _qt_package_version property set, it means it's an
+ # 'official' qt target like a module or plugin, so we don't want to add it
+ # to the list of extra paths to scan for in androiddeployqt, because they are
+ # already handled via the regular 'qt' code path in the androiddeployqt.
+ # Thus this will pick up only non-qt 3rd party targets.
+ get_target_property(qt_package_version "${imported_target}" _qt_package_version)
+ if(NOT qt_package_version)
+ list(APPEND result "${imported_target}")
+ endif()
+ endif()
+ endforeach()
+
+ get_directory_property(parent_dir DIRECTORY "${subdir}" PARENT_DIRECTORY)
+ if(parent_dir)
+ _qt_internal_collect_imported_shared_libraries_recursive(result_inner "${parent_dir}")
+ endif()
+
+ list(APPEND result ${result_inner})
+ set(${out_var} "${result}" PARENT_SCOPE)
+endfunction()
+
+# This function allows deciding whether apks should be built as part of the ALL target at first
+# add_executable call point, rather than when the 'apk' target is created as part of the
+# find_package(Core) call.
+#
+# It does so by creating a custom 'apk_all' target as an implementation detail.
+#
+# This is needed to ensure that the decision is made only when the value of QT_BUILDING_QT is
+# available, which is defined in qt_repo_build() -> include(QtSetup), which is included after the
+# execution of _qt_internal_create_global_apk_target.
+function(_qt_internal_create_global_apk_all_target_if_needed)
+ if(TARGET apk AND NOT TARGET apk_all)
+ # Some Qt tests helper executables have their apk build process failing.
+ # qt_internal_add_executables that are excluded from ALL should also not have apks built
+ # for them.
+ # Don't build apks by default when doing a Qt build.
+ set(skip_add_to_all FALSE)
+ if(QT_BUILDING_QT)
+ set(skip_add_to_all TRUE)
+ endif()
+
+ option(QT_NO_GLOBAL_APK_TARGET_PART_OF_ALL
+ "Skip building apks as part of the default 'ALL' target" ${skip_add_to_all})
+
+ set(part_of_all "ALL")
+ if(QT_NO_GLOBAL_APK_TARGET_PART_OF_ALL)
+ set(part_of_all "")
+ endif()
+
+ add_custom_target(apk_all ${part_of_all})
+ add_dependencies(apk_all apk)
+ endif()
+endfunction()
+
+# The function converts the target property to a json record and appends it to the output
+# variable.
+function(_qt_internal_add_android_deployment_property out_var json_key target property)
+ set(property_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},${property}>>")
+ string(APPEND ${out_var}
+ "$<$<BOOL:${property_genex}>:"
+ " \"${json_key}\": \"${property_genex}\"\,\n"
+ ">"
+ )
+
+ set(${out_var} "${${out_var}}" PARENT_SCOPE)
+endfunction()
+
+# The function converts the list properties of the targets to a json list record and appends it
+# to the output variable.
+# _qt_internal_add_android_deployment_list_property(out_var json_key [<target> <property>]...)
+# The generated JSON object is the normal JSON array, e.g.:
+# "qml-root-path": ["qml/root/path1","qml/root/path2"],
+function(_qt_internal_add_android_deployment_list_property out_var json_key)
+ list(LENGTH ARGN argn_count)
+ math(EXPR is_odd "${argn_count} % 2")
+ if(is_odd)
+ message(FATAL_ERROR "Invalid argument count")
+ endif()
+
+ set(skip_next FALSE)
+ set(property_genex "")
+ math(EXPR last_index "${argn_count} - 1")
+ foreach(idx RANGE ${last_index})
+ if(skip_next)
+ set(skip_next FALSE)
+ continue()
+ endif()
+ set(skip_next TRUE)
+
+ math(EXPR property_idx "${idx} + 1")
+ list(GET ARGN ${idx} target)
+ list(GET ARGN ${property_idx} property)
+
+ # Add comma if we have at least one element from the previous iteration
+ if(property_genex)
+ set(add_comma_genex
+ "$<$<BOOL:${property_genex}>:$<COMMA>>"
+ )
+ endif()
+
+ set(property_genex
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},${property}>>"
+ )
+ set(add_quote_genex
+ "$<$<BOOL:${property_genex}>:\">"
+ )
+
+ # Add comma only if next property genex contains non-empty value.
+ set(add_comma_genex "$<$<BOOL:${property_genex}>:${add_comma_genex}>")
+ string(JOIN "" list_join_genex
+ "${list_join_genex}"
+ "${add_comma_genex}${add_quote_genex}"
+ "$<JOIN:"
+ "${property_genex},"
+ "\"$<COMMA>\""
+ ">"
+ "${add_quote_genex}"
+ )
+ endforeach()
+
+ string(APPEND ${out_var}
+ " \"${json_key}\" : [ ${list_join_genex} ],\n")
+ set(${out_var} "${${out_var}}" PARENT_SCOPE)
+endfunction()
+
+# The function converts the target list property to a json multi-value string record and appends it
+# to the output variable.
+# The generated JSON object is a simple string with the list property items separated by commas,
+# e.g:
+# "android-extra-plugins": "plugin1,plugin2",
+function(_qt_internal_add_android_deployment_multi_value_property out_var json_key target property)
+ set(property_genex
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},${property}>>"
+ )
+ string(JOIN "" list_join_genex
+ "$<JOIN:"
+ "${property_genex},"
+ "$<COMMA>"
+ ">"
+ )
+ string(APPEND ${out_var}
+ "$<$<BOOL:${property_genex}>:"
+ " \"${json_key}\" : \"${list_join_genex}\",\n"
+ ">"
+ )
+
+ set(${out_var} "${${out_var}}" PARENT_SCOPE)
+endfunction()
+
+# The function converts paths to the CMake format to make them acceptable for JSON.
+# It doesn't overwrite public properties, but instead writes formatted values to internal
+# properties.
+function(_qt_internal_android_format_deployment_paths target)
+ if(QT_BUILD_STANDALONE_TESTS OR QT_BUILDING_QT OR QT_INTERNAL_IS_STANDALONE_TEST)
+ set(android_deployment_paths_policy NEW)
+ else()
+ set(policy_path_properties
+ QT_QML_IMPORT_PATH
+ QT_QML_ROOT_PATH
+ QT_ANDROID_PACKAGE_SOURCE_DIR
+ QT_ANDROID_EXTRA_PLUGINS
+ QT_ANDROID_EXTRA_LIBS
+ )
+
+ # Check if any of paths contains the value and stop the evaluation if all properties are
+ # empty or -NOTFOUND
+ set(has_android_paths FALSE)
+ foreach(prop_name IN LISTS policy_path_properties)
+ get_target_property(prop_value ${target} ${prop_name})
+ if(prop_value)
+ set(has_android_paths TRUE)
+ break()
+ endif()
+ endforeach()
+ if(has_android_paths)
+ __qt_internal_setup_policy(QTP0002 "6.6.0"
+ "Target properties that specify android-specific paths may contain generator\
+ expressions but they must evaluate to valid JSON strings.\
+ Check https://doc.qt.io/qt-6/qt-cmake-policy-qtp0002.html for policy details."
+ )
+ qt6_policy(GET QTP0002 android_deployment_paths_policy)
+ endif()
+ endif()
+ if(android_deployment_paths_policy STREQUAL "NEW")
+ # When building standalone tests or Qt itself we obligate developers to not use
+ # windows paths when setting QT_* properties below, so their values are used as is when
+ # generating deployment settings.
+ string(JOIN "" qml_root_path_genex
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},QT_QML_ROOT_PATH>>"
+ "$<"
+ "$<AND:"
+ "$<BOOL:$<GENEX_EVAL:$<TARGET_PROPERTY:${target},QT_QML_ROOT_PATH>>>,"
+ "$<BOOL:$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_internal_qml_root_path>>>"
+ ">:;"
+ ">"
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_internal_qml_root_path>>"
+ )
+ set_target_properties(${target} PROPERTIES
+ _qt_native_qml_import_paths
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},QT_QML_IMPORT_PATH>>"
+ _qt_android_native_qml_root_paths
+ "${qml_root_path_genex}"
+ _qt_android_native_package_source_dir
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},QT_ANDROID_PACKAGE_SOURCE_DIR>>"
+ _qt_android_native_extra_plugins
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},QT_ANDROID_EXTRA_PLUGINS>>"
+ _qt_android_native_extra_libs
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},QT_ANDROID_EXTRA_LIBS>>"
+ )
+ else()
+ # User projects still may use windows paths inside the QT_* properties below, with
+ # obligation to run the finalizer code.
+ _qt_internal_android_format_deployment_path_property(${target}
+ QT_QML_IMPORT_PATH _qt_native_qml_import_paths)
+
+ _qt_internal_android_format_deployment_path_property(${target}
+ QT_QML_ROOT_PATH _qt_android_native_qml_root_paths)
+
+ _qt_internal_android_format_deployment_path_property(${target}
+ _qt_internal_qml_root_path _qt_android_native_qml_root_paths APPEND)
+
+ _qt_internal_android_format_deployment_path_property(${target}
+ QT_ANDROID_PACKAGE_SOURCE_DIR _qt_android_native_package_source_dir)
+
+ _qt_internal_android_format_deployment_path_property(${target}
+ QT_ANDROID_EXTRA_PLUGINS _qt_android_native_extra_plugins)
+
+ _qt_internal_android_format_deployment_path_property(${target}
+ QT_ANDROID_EXTRA_LIBS _qt_android_native_extra_libs)
+ endif()
+endfunction()
+
+# The function converts the value of target property to JSON compatible path and writes the
+# result to out_property. Property might be either single value, semicolon separated list or system
+# path spec.
+# The APPEND argument controls the property is set. The argument should be added after all
+# the required arguments.
+function(_qt_internal_android_format_deployment_path_property target property out_property)
+ set(should_append "")
+ if(ARGC EQUAL 4)
+ if("${ARGV3}" STREQUAL "APPEND")
+ set(should_append APPEND)
+ else()
+ message(FATAL_ERROR "Unexpected argument ${ARGV3}")
+ endif()
+ elseif(ARGC GREATER 4)
+ message(FATAL_ERROR "Unexpected arguments ${ARGN}")
+ endif()
+
+ get_target_property(_paths ${target} ${property})
+ if(_paths)
+ set(native_paths "")
+ foreach(_path IN LISTS _paths)
+ file(TO_CMAKE_PATH "${_path}" _path)
+ list(APPEND native_paths "${_path}")
+ endforeach()
+ set_property(TARGET ${target} ${should_append} PROPERTY
+ ${out_property} "${native_paths}")
+ endif()
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_android_add_apk_target)
+ qt6_android_add_apk_target(${ARGV})
+ endfunction()
+endif()
+
+# The function returns the installation path to Qt for Android for the specified ${abi}.
+# By default function expects to find a layout as is installed by the Qt online installer:
+# Qt_install_dir/Version/
+# |__ gcc_64
+# |__ android_arm64_v8a
+# |__ android_armv7
+# |__ android_x86
+# |__ android_x86_64
+function(_qt_internal_get_android_abi_prefix_path out_path abi)
+ if(CMAKE_ANDROID_ARCH_ABI STREQUAL abi)
+ # Required to build unit tests in developer build
+ if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
+ set(${out_path} "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
+ else()
+ set(${out_path} "${QT6_INSTALL_PREFIX}")
+ endif()
+ elseif(DEFINED QT_PATH_ANDROID_ABI_${abi})
+ get_filename_component(${out_path} "${QT_PATH_ANDROID_ABI_${abi}}" ABSOLUTE)
+ else()
+ # Map the ABI value to the Qt for Android folder.
+ if (abi STREQUAL "x86")
+ set(abi_directory_suffix "${abi}")
+ elseif (abi STREQUAL "x86_64")
+ set(abi_directory_suffix "${abi}")
+ elseif (abi STREQUAL "arm64-v8a")
+ set(abi_directory_suffix "arm64_v8a")
+ else()
+ set(abi_directory_suffix "armv7")
+ endif()
+
+ get_filename_component(${out_path}
+ "${_qt_cmake_dir}/../../../android_${abi_directory_suffix}" ABSOLUTE)
+ endif()
+ set(${out_path} "${${out_path}}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_get_android_abi_cmake_dir_path out_path abi)
+ if(DEFINED QT_ANDROID_PATH_CMAKE_DIR_${abi})
+ set(cmake_dir "${QT_ANDROID_PATH_CMAKE_DIR_${abi}}")
+ else()
+ _qt_internal_get_android_abi_prefix_path(prefix_path ${abi})
+ if((PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD) AND QT_BUILDING_QT AND
+ NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_INTERNAL_IS_STANDALONE_TEST)
+ set(cmake_dir "${QT_CONFIG_BUILD_DIR}")
+ else()
+ string(TOUPPER "${QT_CMAKE_EXPORT_NAMESPACE}" export_namespace_upper)
+ set(cmake_dir "${prefix_path}/${${export_namespace_upper}_INSTALL_LIBS}/cmake")
+ endif()
+ endif()
+
+ set(${out_path} "${cmake_dir}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_get_android_abi_toolchain_path out_path abi)
+ set(toolchain_path "${QT_CMAKE_EXPORT_NAMESPACE}/qt.toolchain.cmake")
+ _qt_internal_get_android_abi_cmake_dir_path(cmake_dir ${abi})
+ get_filename_component(toolchain_path
+ "${cmake_dir}/${toolchain_path}" ABSOLUTE)
+ set(${out_path} "${toolchain_path}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_get_android_abi_subdir_path out_path subdir abi)
+ set(install_paths_path "${QT_CMAKE_EXPORT_NAMESPACE}/QtInstallPaths.cmake")
+ _qt_internal_get_android_abi_cmake_dir_path(cmake_dir ${abi})
+ include("${cmake_dir}/${install_paths_path}")
+ set(${out_path} "${${subdir}}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_collect_qt_for_android_paths out_var)
+ get_target_property(qt_android_abis ${target} _qt_android_abis)
+ if(NOT qt_android_abis)
+ set(qt_android_abis "")
+ endif()
+
+ set(custom_qt_paths data libexecs libs plugins qml)
+ foreach(type IN ITEMS prefix ${custom_qt_paths})
+ set(${type}_records "")
+ endforeach()
+
+ foreach(abi IN LISTS qt_android_abis CMAKE_ANDROID_ARCH_ABI)
+ _qt_internal_get_android_abi_prefix_path(qt_abi_prefix_path ${abi})
+ file(TO_CMAKE_PATH "${qt_abi_prefix_path}" qt_abi_prefix_path)
+ get_filename_component(qt_abi_prefix_path "${qt_abi_prefix_path}" ABSOLUTE)
+ list(APPEND prefix_records " \"${abi}\": \"${qt_abi_prefix_path}\"")
+ foreach(type IN ITEMS ${custom_qt_paths})
+ string(TOUPPER "${type}" upper_case_type)
+ _qt_internal_get_android_abi_subdir_path(qt_abi_path
+ QT6_INSTALL_${upper_case_type} ${abi})
+ list(APPEND ${type}_records
+ " \"${abi}\": \"${qt_abi_path}\"")
+ endforeach()
+ endforeach()
+
+ foreach(type IN ITEMS prefix ${custom_qt_paths})
+ list(JOIN ${type}_records ",\n" ${type}_records_string)
+ set(${type}_records_string "{\n${${type}_records_string}\n }")
+ endforeach()
+
+ string(APPEND ${out_var}
+ " \"qt\": ${prefix_records_string},\n")
+ string(APPEND ${out_var}
+ " \"qtDataDirectory\": ${data_records_string},\n")
+ string(APPEND ${out_var}
+ " \"qtLibExecsDirectory\": ${libexecs_records_string},\n")
+ string(APPEND ${out_var}
+ " \"qtLibsDirectory\": ${libs_records_string},\n")
+ string(APPEND ${out_var}
+ " \"qtPluginsDirectory\": ${plugins_records_string},\n")
+ string(APPEND ${out_var}
+ " \"qtQmlDirectory\": ${qml_records_string},\n")
+
+ set(${out_var} "${${out_var}}" PARENT_SCOPE)
+endfunction()
+
+# The function collects list of existing Qt for Android using
+# _qt_internal_get_android_abi_prefix_path and pre-defined set of known Android ABIs. The result is
+# written to QT_DEFAULT_ANDROID_ABIS cache variable.
+# Note that QT_DEFAULT_ANDROID_ABIS is not intended to be set outside the function and will be
+# rewritten.
+function(_qt_internal_collect_default_android_abis)
+ set(known_android_abis armeabi-v7a arm64-v8a x86 x86_64)
+
+ set(default_abis)
+ foreach(abi IN LISTS known_android_abis)
+ _qt_internal_get_android_abi_toolchain_path(qt_abi_toolchain_path ${abi})
+ # It's expected that Qt for Android contains ABI specific toolchain file.
+ if(EXISTS "${qt_abi_toolchain_path}"
+ OR CMAKE_ANDROID_ARCH_ABI STREQUAL abi)
+ list(APPEND default_abis ${abi})
+ endif()
+ endforeach()
+ set(QT_DEFAULT_ANDROID_ABIS "${default_abis}" CACHE STRING
+ "The list of autodetected Qt for Android ABIs" FORCE
+ )
+ set(QT_ANDROID_ABIS "${CMAKE_ANDROID_ARCH_ABI}" CACHE STRING
+ "The list of Qt for Android ABIs used to build the project apk"
+ )
+ set(QT_ANDROID_BUILD_ALL_ABIS FALSE CACHE BOOL
+ "Build project using the list of autodetected Qt for Android ABIs"
+ )
+endfunction()
+
+# Returns a path to the timestamp file for the specific step of the multi-ABI Android project
+function(_qt_internal_get_android_abi_step_stampfile out project abi step)
+ get_target_property(build_dir ${project} _qt_android_build_directory)
+ get_property(is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi)
+ set(${out} "${build_dir}/$<CONFIG>/${project}_${step}_stamp" PARENT_SCOPE)
+ else()
+ set(${out} "${build_dir}/${project}_${step}_stamp" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Creates the multi-ABI Android projects and assigns the JOB_POOL to them if it's possible
+function(_qt_internal_add_android_abi_project project abi)
+ add_custom_target(${project})
+
+ set(build_dir "${CMAKE_BINARY_DIR}/android_abi_builds/${abi}")
+ set_target_properties(${project} PROPERTIES
+ _qt_android_build_directory "${build_dir}"
+ )
+
+ file(MAKE_DIRECTORY "${build_dir}")
+ if(CMAKE_GENERATOR MATCHES "^Ninja")
+ set_property(GLOBAL APPEND PROPERTY JOB_POOLS _qt_android_${project}_pool=1)
+ endif()
+endfunction()
+
+# Adds the custom build step to the multi-ABI Android project
+function(_qt_internal_add_android_abi_step project abi step)
+ cmake_parse_arguments(arg "" "" "COMMAND;DEPENDS" ${ARGV})
+
+ if(NOT arg_COMMAND)
+ message(FATAL_ERROR "COMMAND is not set for ${project} step ${step} Android ABI ${abi}.")
+ endif()
+
+ set(dep_stamps "")
+ foreach(dep ${arg_DEPENDS})
+ _qt_internal_get_android_abi_step_stampfile(stamp ${project} ${abi} ${dep})
+ list(APPEND dep_stamps "${stamp}")
+ endforeach()
+
+ get_target_property(build_dir ${project} _qt_android_build_directory)
+
+ if(CMAKE_GENERATOR MATCHES "^Ninja")
+ set(add_to_pool JOB_POOL _qt_android_${project}_pool)
+ else()
+ set(add_to_pool "")
+ endif()
+
+ _qt_internal_get_android_abi_step_stampfile(stamp ${project} ${abi} ${step})
+ add_custom_command(OUTPUT "${stamp}"
+ COMMAND ${arg_COMMAND}
+ COMMAND "${CMAKE_COMMAND}" -E touch "${stamp}"
+ ${add_to_pool}
+ DEPENDS
+ ${dep_stamps}
+ WORKING_DIRECTORY
+ "${build_dir}"
+ VERBATIM
+ )
+ add_custom_target("${project}_${step}" DEPENDS "${stamp}")
+
+ get_target_property(known_steps ${project} _qt_android_abi_steps)
+ if(NOT CMAKE_GENERATOR MATCHES "^Ninja")
+ if(NOT QT_NO_WARN_ANDROID_MULTI_ABI_GENERATOR)
+ get_property(is_warned GLOBAL PROPERTY _qt_internal_warn_android_multi_abi_generator)
+ if(NOT is_warned)
+ set_property(GLOBAL PROPERTY _qt_internal_warn_android_multi_abi_generator TRUE)
+ message(WARNING "Building Multi-ABI Qt projects with the '${CMAKE_GENERATOR}'"
+ " generator has limitations. All targets from non-main ABI will be built"
+ " unconditionally. Please use the 'Ninja' or 'Ninja Multi-config' generators"
+ " with ninja build instead. Set QT_NO_WARN_ANDROID_MULTI_ABI_GENERATOR to"
+ " 'TRUE' to suppress this warning."
+ )
+ endif()
+ endif()
+ if(known_steps)
+ list(GET known_steps 0 first)
+ add_dependencies(${first} ${project}_${step})
+ endif()
+ endif()
+
+ list(PREPEND known_steps ${project}_${step})
+ set_target_properties(${project} PROPERTIES _qt_android_abi_steps "${known_steps}")
+endfunction()
+
+# The function configures external projects for ABIs that target packages need to build with.
+# Each target adds build step to the external project that is linked to the
+# qt_internal_android_${abi}-${target}_build target in the primary ABI build tree.
+function(_qt_internal_configure_android_multiabi_target target)
+ # Functionality is only applicable for the primary ABI
+ if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
+ return()
+ endif()
+
+ get_target_property(target_abis ${target} QT_ANDROID_ABIS)
+ if(target_abis)
+ # Use target-specific Qt for Android ABIs.
+ set(android_abis ${target_abis})
+ elseif(QT_ANDROID_BUILD_ALL_ABIS)
+ # Use autodetected Qt for Android ABIs.
+ set(android_abis ${QT_DEFAULT_ANDROID_ABIS})
+ elseif(QT_ANDROID_ABIS)
+ # Use project-wide Qt for Android ABIs.
+ set(android_abis ${QT_ANDROID_ABIS})
+ else()
+ # User have an empty list of Qt for Android ABIs.
+ message(FATAL_ERROR
+ "The list of Android ABIs is empty, when building ${target}.\n"
+ "You have the following options to select ABIs for a target:\n"
+ " - Set the QT_ANDROID_ABIS variable before calling qt6_add_executable\n"
+ " - Set the ANDROID_ABIS property for ${target}\n"
+ " - Set QT_ANDROID_BUILD_ALL_ABIS flag to try building with\n"
+ " the list of autodetected Qt for Android:\n ${QT_DEFAULT_ANDROID_ABIS}"
+ )
+ endif()
+
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ list(JOIN CMAKE_CONFIGURATION_TYPES "$<SEMICOLON>" escaped_configuration_types)
+ set(config_arg "-DCMAKE_CONFIGURATION_TYPES=${escaped_configuration_types}")
+ else()
+ set(config_arg "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
+ endif()
+
+ unset(extra_cmake_args)
+
+ # The flag is needed when building qt standalone tests only to avoid building
+ # qt repo itself
+ if(QT_BUILD_STANDALONE_TESTS)
+ list(APPEND extra_cmake_args "-DQT_BUILD_STANDALONE_TESTS=ON")
+ endif()
+
+ if(NOT QT_ADDITIONAL_PACKAGES_PREFIX_PATH STREQUAL "")
+ list(JOIN QT_ADDITIONAL_PACKAGES_PREFIX_PATH "$<SEMICOLON>" escaped_packages_prefix_path)
+ list(APPEND extra_cmake_args
+ "-DQT_ADDITIONAL_PACKAGES_PREFIX_PATH=${escaped_packages_prefix_path}")
+ endif()
+
+ if(NOT QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH STREQUAL "")
+ list(JOIN QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH "$<SEMICOLON>"
+ escaped_host_packages_prefix_path)
+ list(APPEND extra_cmake_args
+ "-DQT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH=${escaped_host_packages_prefix_path}")
+ endif()
+
+ if(ANDROID_SDK_ROOT)
+ list(APPEND extra_cmake_args "-DANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}")
+ endif()
+
+ # ANDROID_NDK_ROOT is invented by Qt and is what the qt toolchain file expects
+ if(ANDROID_NDK_ROOT)
+ list(APPEND extra_cmake_args "-DANDROID_NDK_ROOT=${ANDROID_NDK_ROOT}")
+
+ # ANDROID_NDK is passed by Qt Creator and is also present in the android toolchain file.
+ elseif(ANDROID_NDK)
+ list(APPEND extra_cmake_args "-DANDROID_NDK_ROOT=${ANDROID_NDK}")
+ endif()
+
+ if(DEFINED QT_NO_PACKAGE_VERSION_CHECK)
+ list(APPEND extra_cmake_args "-DQT_NO_PACKAGE_VERSION_CHECK=${QT_NO_PACKAGE_VERSION_CHECK}")
+ endif()
+
+ if(DEFINED QT_HOST_PATH_CMAKE_DIR)
+ list(APPEND extra_cmake_args "-DQT_HOST_PATH_CMAKE_DIR=${QT_HOST_PATH_CMAKE_DIR}")
+ endif()
+
+ if(CMAKE_MAKE_PROGRAM)
+ list(APPEND extra_cmake_args "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}")
+ endif()
+
+ if(CMAKE_C_COMPILER_LAUNCHER)
+ list(JOIN CMAKE_C_COMPILER_LAUNCHER "$<SEMICOLON>"
+ compiler_launcher)
+ list(APPEND extra_cmake_args
+ "-DCMAKE_C_COMPILER_LAUNCHER=${compiler_launcher}")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_LAUNCHER)
+ list(JOIN CMAKE_CXX_COMPILER_LAUNCHER "$<SEMICOLON>"
+ compiler_launcher)
+ list(APPEND extra_cmake_args
+ "-DCMAKE_CXX_COMPILER_LAUNCHER=${compiler_launcher}")
+ endif()
+
+ unset(user_cmake_args)
+ foreach(var IN LISTS QT_ANDROID_MULTI_ABI_FORWARD_VARS)
+ string(REPLACE ";" "$<SEMICOLON>" var_value "${${var}}")
+ list(APPEND user_cmake_args "-D${var}=${var_value}")
+ endforeach()
+
+ set(missing_qt_abi_toolchains "")
+ set(previous_copy_apk_dependencies_target ${target})
+ # Create external projects for each android ABI except the main one.
+ list(REMOVE_ITEM android_abis "${CMAKE_ANDROID_ARCH_ABI}")
+ foreach(abi IN ITEMS ${android_abis})
+ if(NOT "${abi}" IN_LIST QT_DEFAULT_ANDROID_ABIS)
+ list(APPEND missing_qt_abi_toolchains ${abi})
+ list(REMOVE_ITEM android_abis "${abi}")
+ continue()
+ endif()
+
+ get_property(abi_external_projects GLOBAL
+ PROPERTY _qt_internal_abi_external_projects)
+ if(NOT abi_external_projects
+ OR NOT "qt_internal_android_${abi}" IN_LIST abi_external_projects)
+ _qt_internal_add_android_abi_project(qt_internal_android_${abi} ${abi})
+
+ get_target_property(android_abi_build_dir qt_internal_android_${abi}
+ _qt_android_build_directory)
+ _qt_internal_get_android_abi_toolchain_path(qt_abi_toolchain_path ${abi})
+ _qt_internal_add_android_abi_step(qt_internal_android_${abi} ${abi} configure
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-G${CMAKE_GENERATOR}"
+ "-DCMAKE_TOOLCHAIN_FILE=${qt_abi_toolchain_path}"
+ "-DQT_HOST_PATH=${QT_HOST_PATH}"
+ "-DQT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT=ON"
+ "-DQT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR=${CMAKE_BINARY_DIR}"
+ "${config_arg}"
+ "${extra_cmake_args}"
+ "${user_cmake_args}"
+ "-B" "${android_abi_build_dir}"
+ "-S" "${CMAKE_SOURCE_DIR}"
+ )
+ set_property(GLOBAL APPEND PROPERTY
+ _qt_internal_abi_external_projects "qt_internal_android_${abi}")
+ endif()
+
+ get_target_property(android_abi_build_dir qt_internal_android_${abi}
+ _qt_android_build_directory)
+ _qt_internal_add_android_abi_step(qt_internal_android_${abi} ${abi} ${target}_build
+ DEPENDS
+ configure
+ COMMAND
+ "${CMAKE_COMMAND}"
+ --build "${android_abi_build_dir}"
+ --config $<CONFIG>
+ --target ${target}
+ )
+ add_dependencies(${target} "qt_internal_android_${abi}_${target}_build")
+
+ _qt_internal_add_android_abi_step(qt_internal_android_${abi} ${abi}
+ ${target}_copy_apk_dependencies
+ DEPENDS
+ ${target}_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ --build "${android_abi_build_dir}"
+ --config $<CONFIG>
+ --target qt_internal_${target}_copy_apk_dependencies
+ )
+ set(external_project_copy_target
+ "qt_internal_android_${abi}_${target}_copy_apk_dependencies")
+
+ # Need to build dependency chain between the
+ # qt_internal_android_${abi}-${target}_copy_apk_dependencies targets for all ABI's, to
+ # prevent parallel execution of androiddeployqt processes. We cannot use Ninja job pools
+ # here because it's not possible to define job pool for the step target in ExternalProject.
+ # All tricks with interlayer targets don't work, because we only can bind interlayer target
+ # to the job pool, but its dependencies can still be built in parallel.
+ add_dependencies(${previous_copy_apk_dependencies_target}
+ "${external_project_copy_target}")
+ set(previous_copy_apk_dependencies_target "${external_project_copy_target}")
+ endforeach()
+
+ if(missing_qt_abi_toolchains)
+ list(JOIN missing_qt_abi_toolchains ", " missing_qt_abi_toolchains_string)
+ message(FATAL_ERROR "Cannot find toolchain files for the manually specified Android"
+ " ABIs: ${missing_qt_abi_toolchains_string}"
+ "\nNote that you also may manually specify the path to the required Qt for"
+ " Android ABI using QT_PATH_ANDROID_ABI_<abi> CMake variable with the value"
+ " of the installation prefix, and QT_ANDROID_PATH_CMAKE_DIR_<abi> with"
+ " the location of the cmake directory for that ABI.\n")
+ endif()
+
+ list(JOIN android_abis ", " android_abis_string)
+ if(android_abis_string)
+ set(android_abis_string "${CMAKE_ANDROID_ARCH_ABI} (default), ${android_abis_string}")
+ else()
+ set(android_abis_string "${CMAKE_ANDROID_ARCH_ABI} (default)")
+ endif()
+ if(NOT QT_NO_ANDROID_ABI_STATUS_MESSAGE)
+ message(STATUS "Configuring '${target}' for the following Android ABIs:"
+ " ${android_abis_string}")
+ endif()
+ set_target_properties(${target} PROPERTIES _qt_android_abis "${android_abis}")
+endfunction()
+
+# The wrapper function that contains routines that need to be called to produce a valid Android
+# package for the executable 'target'. The function is added to the finalizer list of the Core
+# module and is executed implicitly when configuring user projects.
+function(_qt_internal_android_executable_finalizer target)
+ set_property(TARGET ${target} PROPERTY _qt_android_executable_finalizer_called TRUE)
+
+ _qt_internal_expose_android_package_source_dir_to_ide(${target})
+
+ _qt_internal_configure_android_multiabi_target("${target}")
+ qt6_android_generate_deployment_settings("${target}")
+ qt6_android_add_apk_target("${target}")
+endfunction()
+
+function(_qt_internal_expose_android_package_source_dir_to_ide target)
+ get_target_property(android_package_source_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
+ if(android_package_source_dir)
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ if(NOT IS_ABSOLUTE "${android_package_source_dir}")
+ string(JOIN "/" android_package_source_dir
+ "${target_source_dir}"
+ "${android_package_source_dir}"
+ )
+ endif()
+
+ if(EXISTS "${android_package_source_dir}")
+ file(GLOB_RECURSE android_package_sources
+ RELATIVE "${target_source_dir}"
+ "${android_package_source_dir}/*"
+ )
+ endif()
+
+ foreach(f IN LISTS android_package_sources)
+ _qt_internal_expose_source_file_to_ide(${target} "${f}")
+ endforeach()
+ endif()
+endfunction()
+
+set(QT_INTERNAL_ANDROID_TARGET_BUILD_DIR_SUPPORT ON CACHE INTERNAL
+ "Indicates that Qt supports per-target Android build directories")
diff --git a/src/corelib/Qt6CTestMacros.cmake b/src/corelib/Qt6CTestMacros.cmake
index 962d49d6b2..8722553cd0 100644
--- a/src/corelib/Qt6CTestMacros.cmake
+++ b/src/corelib/Qt6CTestMacros.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#
# W A R N I N G
# -------------
@@ -8,97 +11,616 @@
#
# We mean it.
-message("CMAKE_VERSION: ${CMAKE_VERSION}")
-message("CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
-message("CMAKE_MODULES_UNDER_TEST: ${CMAKE_MODULES_UNDER_TEST}")
-foreach(_mod ${CMAKE_MODULES_UNDER_TEST})
- message("CMAKE_${_mod}_MODULE_MAJOR_VERSION: ${CMAKE_${_mod}_MODULE_MAJOR_VERSION}")
- message("CMAKE_${_mod}_MODULE_MINOR_VERSION: ${CMAKE_${_mod}_MODULE_MINOR_VERSION}")
- message("CMAKE_${_mod}_MODULE_PATCH_VERSION: ${CMAKE_${_mod}_MODULE_PATCH_VERSION}")
-endforeach()
-
-set(BUILD_OPTIONS_LIST)
-
-if (CMAKE_C_COMPILER)
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}")
-endif()
-
-if (CMAKE_CXX_COMPILER)
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
-endif()
-
-if (CMAKE_BUILD_TYPE)
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
-endif()
-
-if (CMAKE_TOOLCHAIN_FILE)
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
-endif()
-
-if (CMAKE_VERBOSE_MAKEFILE)
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_VERBOSE_MAKEFILE=1")
-endif()
-
-if (NO_GUI)
- list(APPEND BUILD_OPTIONS_LIST "-DNO_GUI=True")
-endif()
-if (NO_WIDGETS)
- list(APPEND BUILD_OPTIONS_LIST "-DNO_WIDGETS=True")
-endif()
-if (NO_DBUS)
- list(APPEND BUILD_OPTIONS_LIST "-DNO_DBUS=True")
-endif()
-
-# Qt requires C++11 features in header files, which means
-# the buildsystem needs to add a -std flag for certain compilers
-# CMake adds the flag automatically in most cases, but notably not
-# on Windows prior to CMake 3.3
-if (CMAKE_VERSION VERSION_LESS 3.3)
- if (CMAKE_CXX_COMPILER_ID STREQUAL AppleClang
- OR (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang))
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_CXX_FLAGS=-std=gnu++0x -stdlib=libc++")
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL GNU
- OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
- list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_CXX_FLAGS=-std=gnu++0x")
- endif()
-endif()
-
-foreach(module ${CMAKE_MODULES_UNDER_TEST})
- list(APPEND BUILD_OPTIONS_LIST
- "-DCMAKE_${module}_MODULE_MAJOR_VERSION=${CMAKE_${module}_MODULE_MAJOR_VERSION}"
- "-DCMAKE_${module}_MODULE_MINOR_VERSION=${CMAKE_${module}_MODULE_MINOR_VERSION}"
- "-DCMAKE_${module}_MODULE_PATCH_VERSION=${CMAKE_${module}_MODULE_PATCH_VERSION}"
- )
-endforeach()
-
-macro(expect_pass _dir)
- cmake_parse_arguments(_ARGS "" "BINARY" "" ${ARGN})
- string(REPLACE "(" "_" testname "${_dir}")
- string(REPLACE ")" "_" testname "${testname}")
- add_test(${testname} ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMAKE_CURRENT_SOURCE_DIR}/${_dir}"
- "${CMAKE_CURRENT_BINARY_DIR}/${_dir}"
- --build-config "${CMAKE_BUILD_TYPE}"
- --build-generator ${CMAKE_GENERATOR}
- --build-makeprogram ${CMAKE_MAKE_PROGRAM}
- --build-project ${_dir}
- --build-options "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" ${BUILD_OPTIONS_LIST}
- --test-command ${_ARGS_BINARY}
- )
+message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}")
+message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
+message(STATUS "CMAKE_MODULES_UNDER_TEST: ${CMAKE_MODULES_UNDER_TEST}")
+
+# Generate a shell script wrapper that calls ninja with -v parameter.
+# Upstream issue to allow specifying custom build tool options when using ctest's --build-and-test
+# https://gitlab.kitware.com/cmake/cmake/-/issues/22443.
+# Only one file is created that is used by all tests.
+function(_qt_internal_get_ninja_wrapper ninja_path out_wrapper_path)
+ if(QT_INTERNAL_CTEST_NINJA_WRAPPER AND EXISTS "${QT_INTERNAL_CTEST_NINJA_WRAPPER}")
+ set(${out_wrapper_path} "${QT_INTERNAL_CTEST_NINJA_WRAPPER}" PARENT_SCOPE)
+ return()
+ endif()
+
+ if(NOT ninja_path)
+ message(FATAL_ERROR "Invalid ninja path specified: '${ninja_path}'.")
+ endif()
+
+ set(wrapper_extension "")
+
+ if(NOT CMAKE_HOST_UNIX)
+ set(wrapper_extension ".bat")
+ endif()
+
+ set(script_name "qt-internal-ninja")
+
+ # the libexec literal is used on purpose for the source, so the file is found
+ # on Windows hosts.
+ set(wrapper_rel_path "libexec/${script_name}${wrapper_extension}.in")
+
+ # Need to find the libexec input file depending whether the qtbase sources are available.
+ # This mirrors the logic in qt_set_up_build_internals_paths.
+ # TODO: Clean this up, together with qt_set_up_build_internals_paths to only use the
+ # the qtbase sources when building qtbase. And perhaps also when doing a non-prefix
+ # developer-build.
+ set(qtbase_wrapper_in_path "${QT_SOURCE_TREE}/${wrapper_rel_path}")
+ set(installed_wrapper_in_path
+ "${_qt_cmake_dir}/${QT_CMAKE_EXPORT_NAMESPACE}/${wrapper_rel_path}")
+
+ # qtbase sources available, always use them, regardless of prefix or non-prefix builds.
+ if(EXISTS "${qtbase_wrapper_in_path}")
+ set(wrapper_in "${qtbase_wrapper_in_path}")
+
+ # qtbase sources unavailable, use installed files.
+ elseif(EXISTS "${installed_wrapper_in_path}")
+ set(wrapper_in "${installed_wrapper_in_path}")
+ else()
+ message(FATAL_ERROR "Can't find ${script_name}${wrapper_extension}.in file.")
+ endif()
+
+ set(wrapper_out "${CMAKE_BINARY_DIR}/.qt/${script_name}${wrapper_extension}")
+
+ set(original_ninja "${ninja_path}")
+ set(ninja_arguments "-v")
+
+ configure_file("${wrapper_in}" "${wrapper_out}" @ONLY)
+
+ set(QT_INTERNAL_CTEST_NINJA_WRAPPER "${wrapper_out}" CACHE STRING
+ "Internal Qt ninja wrapper for ctest tests")
+
+ set(${out_wrapper_path} "${QT_INTERNAL_CTEST_NINJA_WRAPPER}" PARENT_SCOPE)
+endfunction()
+
+# The function collects configuring options for the test projects generated by Qt cmake tests.
+# Arguments:
+# OUT_PREFIX_PATH <variable name>: stores the CMAKE_PREFIX_PATH value in the output variable.
+function(_qt_internal_get_cmake_test_configure_options out_var)
+ cmake_parse_arguments(arg "" "OUT_PREFIX_PATH" "" ${ARGN})
+ set(option_list)
+
+ if (CMAKE_C_COMPILER AND NOT CMAKE_CROSSCOMPILING)
+ list(APPEND option_list "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}")
+ endif()
+
+ if (CMAKE_CXX_COMPILER AND NOT CMAKE_CROSSCOMPILING)
+ list(APPEND option_list "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
+ endif()
+
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ if(CMAKE_CONFIGURATION_TYPES)
+ string(REPLACE ";" "\;" configuration_types "${CMAKE_CONFIGURATION_TYPES}")
+ list(APPEND option_list "-DCMAKE_CONFIGURATION_TYPES=${configuration_types}")
+ endif()
+ else()
+ if(CMAKE_BUILD_TYPE)
+ list(APPEND option_list "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
+ endif()
+ endif()
+
+ if (CMAKE_TOOLCHAIN_FILE)
+ file(TO_CMAKE_PATH "${CMAKE_TOOLCHAIN_FILE}" _CMAKE_TOOLCHAIN_FILE)
+ list(APPEND option_list "-DCMAKE_TOOLCHAIN_FILE=${_CMAKE_TOOLCHAIN_FILE}")
+ endif()
+
+ if (CMAKE_VERBOSE_MAKEFILE)
+ list(APPEND option_list "-DCMAKE_VERBOSE_MAKEFILE=1")
+ endif()
+
+ if (NO_GUI)
+ list(APPEND option_list "-DNO_GUI=True")
+ endif()
+ if (NO_WIDGETS)
+ list(APPEND option_list "-DNO_WIDGETS=True")
+ endif()
+ if (NO_DBUS)
+ list(APPEND option_list "-DNO_DBUS=True")
+ endif()
+
+ list(APPEND option_list "-DCMAKE_MESSAGE_LOG_LEVEL=DEBUG")
+ list(APPEND option_list "-DCMAKE_AUTOGEN_VERBOSE=TRUE")
+
+ if(APPLE AND CMAKE_OSX_ARCHITECTURES)
+ list(LENGTH CMAKE_OSX_ARCHITECTURES osx_arch_count)
+
+ # When Qt is built as universal config (macOS or iOS), force CMake build tests to build one
+ # architecture instead of all of them, because the build machine that builds the cmake tests
+ # might not have a universal SDK installed.
+ if(osx_arch_count GREATER 1)
+ list(APPEND option_list "-DQT_FORCE_SINGLE_QT_OSX_ARCHITECTURE=ON")
+ endif()
+ endif()
+
+ foreach(module ${CMAKE_MODULES_UNDER_TEST})
+ list(APPEND option_list
+ "-DCMAKE_${module}_MODULE_MAJOR_VERSION=${CMAKE_${module}_MODULE_MAJOR_VERSION}"
+ "-DCMAKE_${module}_MODULE_MINOR_VERSION=${CMAKE_${module}_MODULE_MINOR_VERSION}"
+ "-DCMAKE_${module}_MODULE_PATCH_VERSION=${CMAKE_${module}_MODULE_PATCH_VERSION}"
+ )
+ endforeach()
+
+ _qt_internal_get_build_vars_for_external_projects(
+ PREFIXES_VAR prefixes
+ ADDITIONAL_PACKAGES_PREFIXES_VAR additional_prefixes
+ )
+
+ if(arg_OUT_PREFIX_PATH)
+ set(${arg_OUT_PREFIX_PATH} "${prefixes}" PARENT_SCOPE)
+ endif()
+
+ string(REPLACE ";" "\;" prefixes "${prefixes}")
+ list(APPEND option_list "-DCMAKE_PREFIX_PATH=${prefixes}")
+ list(APPEND option_list "-DQT_ADDITIONAL_PACKAGES_PREFIX_PATH=${additional_prefixes}")
+
+ set(${out_var} "${option_list}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_set_up_test_run_environment testname)
+ set(no_value_options NO_PLUGIN_PATH)
+ set(single_value_options "")
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ # This is copy-pasted from qt_add_test and adapted to the standalone project case.
+ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ set(QT_PATH_SEPARATOR "\\;")
+ else()
+ set(QT_PATH_SEPARATOR ":")
+ endif()
+
+ if(NOT INSTALL_BINDIR)
+ set(INSTALL_BINDIR bin)
+ endif()
+
+ if(NOT INSTALL_PLUGINSDIR)
+ set(INSTALL_PLUGINSDIR "plugins")
+ endif()
+
+ set(install_prefixes "")
+ if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(install_prefixes "${CMAKE_INSTALL_PREFIX}")
+ endif()
+
+ # If part of Qt build or standalone tests, use the build internals install prefix.
+ # If the tests are configured as a separate project, use the Qt6 package provided install
+ # prefix.
+ if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
+ list(APPEND install_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
+ else()
+ list(APPEND install_prefixes "${QT6_INSTALL_PREFIX}")
+ endif()
+
+ set(test_env_path "PATH=${CMAKE_CURRENT_BINARY_DIR}")
+ foreach(install_prefix ${install_prefixes})
+ set(test_env_path "${test_env_path}${QT_PATH_SEPARATOR}${install_prefix}/${INSTALL_BINDIR}")
+ endforeach()
+ set(test_env_path "${test_env_path}${QT_PATH_SEPARATOR}$ENV{PATH}")
+ string(REPLACE ";" "\;" test_env_path "${test_env_path}")
+ set_property(TEST "${testname}" APPEND PROPERTY ENVIRONMENT "${test_env_path}")
+ set_property(TEST "${testname}" APPEND PROPERTY ENVIRONMENT "QT_TEST_RUNNING_IN_CTEST=1")
+
+ if(NOT arg_NO_PLUGIN_PATH)
+ # Add the install prefix to list of plugin paths when doing a prefix build
+ if(NOT QT_INSTALL_DIR)
+ foreach(install_prefix ${install_prefixes})
+ list(APPEND plugin_paths "${install_prefix}/${INSTALL_PLUGINSDIR}")
+ endforeach()
+ endif()
+
+ # TODO: Collect all paths from known repositories when performing a super build.
+ list(APPEND plugin_paths "${PROJECT_BINARY_DIR}/${INSTALL_PLUGINSDIR}")
+ list(JOIN plugin_paths "${QT_PATH_SEPARATOR}" plugin_paths_joined)
+ set_property(TEST "${testname}"
+ APPEND PROPERTY ENVIRONMENT "QT_PLUGIN_PATH=${plugin_paths_joined}")
+ endif()
+endfunction()
+
+# Checks if the test project can be built successfully. Arguments:
+#
+# NO_CLEAN_STEP: Skips calling 'clean' target before building.
+#
+# NO_BUILD_PROJECT_ARG: Skips adding --build-project argument. Useful when using Xcode generator.
+#
+# GENERATOR: Use a custom generator. When not specified, uses existing CMAKE_GENERATOR value.
+#
+# NO_IOS_DEFAULT_ARGS: Skips setting default iOS-specific options like the generator to be used.
+#
+# MAKE_PROGRAM: Specify a different make program. Can be useful with a custom make or ninja wrapper.
+#
+# BUILD_TYPE: Specify a different CMake build type. Defaults to CMAKE_BUILD_TYPE if it is not empty.
+# Which means no build type is passed if the top-level project is configured with a
+# multi-config generator.
+#
+# SIMULATE_IN_SOURCE: If the option is specified, the function copies sources of the tests to the
+# CMAKE_CURRENT_BINARY_DIR directory, creates internal build directory in the
+# copied sources and uses this directory to build and test the project.
+# This makes possible to have relative paths to the source files in the
+# generated ninja rules.
+#
+# BUILD_DIR: A custom build dir relative to the calling project CMAKE_CURRENT_BINARY_DIR.
+# Useful when configuring the same test project with different options in separate
+# build dirs.
+#
+# BINARY: Path to the test artifact that will be executed after the build is complete. If a
+# relative path is specified, it will be counted from the build directory.
+# Can also be passed a random executable to be found in PATH, like 'ctest'.
+#
+# BINARY_ARGS: Additional arguments to pass to the BINARY.
+#
+# TESTNAME: a custom test name to use instead of the one derived from the source directory name
+#
+# BUILD_OPTIONS: a list of -D style CMake definitions to pass to ctest's --build-options (which
+# are ultimately passed to the CMake invocation of the test project). You may
+# escape semicolons inside the definitions using:
+# https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#bracket-argument
+# so the argument containing list will look as following:
+# -DLIST_ARGUMENT=item1[[;]]item2[[;]]...itemN.
+macro(_qt_internal_test_expect_pass _dir)
+ if(WASM)
+ return()
+ endif()
+ set(_test_option_args
+ SIMULATE_IN_SOURCE
+ NO_CLEAN_STEP
+ NO_BUILD_PROJECT_ARG
+ NO_IOS_DEFAULT_ARGS
+ NO_RUN_ENVIRONMENT_PLUGIN_PATH
+ )
+ set(_test_single_args
+ BINARY
+ TESTNAME
+ BUILD_DIR
+ GENERATOR
+ MAKE_PROGRAM
+ BUILD_TYPE
+ )
+ set(_test_multi_args
+ BUILD_OPTIONS
+ BINARY_ARGS
+ )
+ cmake_parse_arguments(_ARGS
+ "${_test_option_args}"
+ "${_test_single_args}"
+ "${_test_multi_args}"
+ ${ARGN}
+ )
+
+ if(NOT _ARGS_NO_IOS_DEFAULT_ARGS AND IOS)
+ set(_ARGS_NO_BUILD_PROJECT_ARG TRUE)
+ set(_ARGS_GENERATOR Xcode)
+ set(_ARGS_MAKE_PROGRAM xcodebuild)
+ endif()
+
+ if(_ARGS_TESTNAME)
+ set(testname "${_ARGS_TESTNAME}")
+ else()
+ string(REPLACE "(" "_" testname "${_dir}")
+ string(REPLACE ")" "_" testname "${testname}")
+ string(REPLACE "/" "_" testname "${testname}")
+ endif()
+
+ # Allow setting a different generator. Needed for iOS.
+ set(generator "${CMAKE_GENERATOR}")
+ if(_ARGS_GENERATOR)
+ set(generator "${_ARGS_GENERATOR}")
+ endif()
+
+ # Allow setting a different make program.
+ if(_ARGS_MAKE_PROGRAM)
+ set(make_program "${_ARGS_MAKE_PROGRAM}")
+ elseif(CMAKE_GENERATOR MATCHES "Ninja")
+ # Use a ninja wrapper when generator is ninja
+ _qt_internal_get_ninja_wrapper("${CMAKE_MAKE_PROGRAM}" ninja_wrapper)
+ set(make_program "${ninja_wrapper}")
+ else()
+ set(make_program "${CMAKE_MAKE_PROGRAM}")
+ endif()
+
+ # Only pass build config if it was specified during the initial tests/auto project
+ # configuration. Important when using Qt multi-config builds which won't have CMAKE_BUILD_TYPE
+ # set.
+ set(build_type "")
+
+ if(_ARGS_BUILD_TYPE)
+ set(build_type "${_ARGS_BUILD_TYPE}")
+ elseif(CMAKE_BUILD_TYPE)
+ set(build_type "${CMAKE_BUILD_TYPE}")
+ endif()
+ if(build_type)
+ set(build_type "--build-config" "${build_type}")
+ endif()
+
+ # Allow skipping clean step.
+ set(build_no_clean "")
+ if(_ARGS_NO_CLEAN_STEP)
+ set(build_no_clean "--build-noclean")
+ endif()
+
+ # Allow omitting the --build-project arg. It's relevant for xcode projects where the project
+ # name on disk is different from the project source dir name.
+ if(NOT _ARGS_NO_BUILD_PROJECT_ARG)
+ set(build_project "--build-project" "${_dir}")
+ else()
+ set(build_project)
+ endif()
+
+ # Allow omitting test command if no binary or binary args are provided.
+ set(test_command "")
+ if(_ARGS_BINARY)
+ list(APPEND test_command ${_ARGS_BINARY} ${_ARGS_BINARY_ARGS})
+ endif()
+ if(test_command)
+ set(test_command "--test-command" ${test_command})
+ endif()
+
+ set(additional_configure_args "")
+
+ # Allow passing additional configure options to all projects via either a cache var or env var.
+ # Can be useful for certain catch-all scenarios.
+ if(QT_CMAKE_TESTS_ADDITIONAL_CONFIGURE_OPTIONS)
+ list(APPEND additional_configure_args ${QT_CMAKE_TESTS_ADDITIONAL_CONFIGURE_OPTIONS})
+ endif()
+ if(DEFINED ENV{QT_CMAKE_TESTS_ADDITIONAL_CONFIGURE_OPTIONS})
+ list(APPEND additional_configure_args $ENV{QT_CMAKE_TESTS_ADDITIONAL_CONFIGURE_OPTIONS})
+ endif()
+
+ # When building an iOS CMake test in the CI using a universal Qt build, target the simulator
+ # sdk, because the CI currently doesn't have a proper setup for signing device binaries
+ # (missing a working signing certificate and provisioning profile). Allow opt-out.
+ if(IOS)
+ set(osx_arch_count 0)
+ if(QT_OSX_ARCHITECTURES)
+ list(LENGTH QT_OSX_ARCHITECTURES osx_arch_count)
+ endif()
+
+ set(build_environment "")
+ if(DEFINED ENV{QT_BUILD_ENVIRONMENT})
+ set(build_environment "$ENV{QT_BUILD_ENVIRONMENT}")
+ endif()
+ if(build_environment STREQUAL "ci"
+ AND osx_arch_count GREATER_EQUAL 2
+ AND NOT QT_APPLE_SDK
+ AND NOT QT_NO_IOS_BUILD_ADJUSTMENT_IN_CI)
+ list(APPEND additional_configure_args
+ -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_SYSROOT=iphonesimulator)
+ endif()
+ endif()
+
+ set(__expect_pass_build_dir "${CMAKE_CURRENT_BINARY_DIR}/${_dir}")
+ if(_ARGS_BUILD_DIR)
+ set(__expect_pass_build_dir "${CMAKE_CURRENT_BINARY_DIR}/${_ARGS_BUILD_DIR}")
+ endif()
+
+ set(__expect_pass_source_dir "${CMAKE_CURRENT_SOURCE_DIR}/${_dir}")
+ if(_ARGS_SIMULATE_IN_SOURCE)
+ set(__expect_pass_in_source_build_dir "${CMAKE_CURRENT_BINARY_DIR}/in_source")
+ set(__expect_pass_build_dir "${__expect_pass_in_source_build_dir}/${_dir}/build")
+ set(__expect_pass_source_dir "${__expect_pass_in_source_build_dir}/${_dir}")
+
+ unset(__expect_pass_in_source_build_dir)
+ endif()
+
+ if(_ARGS_BINARY AND NOT IS_ABSOLUTE "${_ARGS_BINARY}")
+ set(_ARGS_BINARY "${__expect_pass_build_dir}/${_ARGS_BINARY}")
+ endif()
+
+ if(_ARGS_SIMULATE_IN_SOURCE)
+ add_test(NAME ${testname}_cleanup
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${__expect_pass_source_dir}"
+ )
+ set_tests_properties(${testname}_cleanup PROPERTIES
+ FIXTURES_SETUP "${testname}SIMULATE_IN_SOURCE_FIXTURE"
+ )
+ add_test(${testname}_copy_sources ${CMAKE_COMMAND} -E copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/${_dir}" "${__expect_pass_source_dir}"
+ )
+ set_tests_properties(${testname}_copy_sources PROPERTIES
+ FIXTURES_SETUP "${testname}SIMULATE_IN_SOURCE_FIXTURE"
+ DEPENDS ${testname}_cleanup
+ )
+ endif()
+
+ string(REPLACE "[[;]]" "\;" _ARGS_BUILD_OPTIONS "${_ARGS_BUILD_OPTIONS}")
+
+ _qt_internal_get_cmake_test_configure_options(option_list)
+ set(ctest_command_args
+ --build-and-test
+ "${__expect_pass_source_dir}"
+ "${__expect_pass_build_dir}"
+ ${build_type}
+ ${build_no_clean}
+ --build-generator "${generator}"
+ --build-makeprogram "${make_program}"
+ ${build_project}
+ --build-options "${option_list}"
+ "${_ARGS_BUILD_OPTIONS}" ${additional_configure_args}
+ ${test_command}
+ )
+ add_test(${testname} ${CMAKE_CTEST_COMMAND} ${ctest_command_args})
+ if(_ARGS_SIMULATE_IN_SOURCE)
+ set_tests_properties(${testname} PROPERTIES
+ FIXTURES_REQUIRED "${testname}SIMULATE_IN_SOURCE_FIXTURE"
+ )
+ endif()
+ set_tests_properties(${testname} PROPERTIES ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0")
+
+ if(_ARGS_BINARY)
+ set(run_env_args "")
+ if(_ARGS_NO_RUN_ENVIRONMENT_PLUGIN_PATH)
+ list(APPEND run_env_args NO_PLUGIN_PATH)
+ endif()
+ _qt_internal_set_up_test_run_environment("${testname}" ${run_env_args})
+ endif()
+
+ unset(__expect_pass_source_dir)
+ unset(__expect_pass_build_dir)
endmacro()
-macro(expect_fail _dir)
+# Checks if a qmake project can be built successfully. Arguments:
+#
+# TESTNAME: a custom test name to use instead of the one derived from the source directory name.
+# the name also applies to the generated build directory.
+#
+# QMAKE_OPTIONS: a list of variable assignments to pass to the qmake invocation.
+# e.g. CONFIG+=debug
+#
+# BUILD_ENVIRONMENT: a list of environment assignments to use when invoking the build tool
+function(_qt_internal_add_qmake_test dir_name)
+ set(test_option_args
+ )
+ set(test_single_args
+ TESTNAME
+ )
+ set(test_multi_args
+ QMAKE_OPTIONS
+ BUILD_ENVIRONMENT
+ )
+
+ # PARSE_ARGV parsing keeps ';' in ENVIRONMENT variables
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${test_option_args}"
+ "${test_single_args}"
+ "${test_multi_args}"
+ )
+
+ if(arg_TESTNAME)
+ set(testname "${arg_TESTNAME}")
+ else()
+ string(REGEX REPLACE "[/)(]" "_" testname "${dir_name}")
+ endif()
+
+ set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/${dir_name}")
+ if(arg_TESTNAME)
+ set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/${arg_TESTNAME}")
+ else()
+ set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/${dir_name}")
+ endif()
+
+ # Find the qmake binary or the wrapper qmake script when cross-compiling..
+ if(QtBase_BINARY_DIR AND NOT QT_BUILD_STANDALONE_TESTS)
+ set(qmake_dir "${QtBase_BINARY_DIR}/${INSTALL_BINDIR}")
+ else()
+ set(qmake_dir "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_BINS}")
+ endif()
+
+ set(qmake_path "${qmake_dir}/qmake${CMAKE_EXECUTABLE_SUFFIX}")
+
+ set(qmake_args
+ "${source_dir}"
+ ${arg_QMAKE_OPTIONS}
+ )
+
+ # Try to choose an appropriate build tool.
+ if(ENV{QT_QMAKE_TEST_BUILD_TOOL})
+ set(build_tool "$ENV{QT_QMAKE_TEST_BUILD_TOOL}")
+ elseif(MSVC)
+ set(build_tool "nmake")
+ elseif(MINGW)
+ set(build_tool "mingw32-make")
+ else()
+ set(build_tool "make")
+ endif()
+
+ set(build_tool_args "")
+ if(ENV{QT_QMAKE_TEST_BUILD_TOOL_OPTIONS})
+ set(build_tool_args "$ENV{QT_QMAKE_TEST_BUILD_TOOL_OPTIONS}")
+ endif()
+
+ # Remove any stale build dir, and create a new one on each test rerun.
+ add_test(${testname}_remove_build_dir
+ ${CMAKE_COMMAND} -E remove_directory "${build_dir}"
+ )
+ set_tests_properties(${testname}_remove_build_dir PROPERTIES
+ FIXTURES_SETUP "${testname}_ensure_clean_build_dir"
+ )
+
+ add_test(${testname}_create_build_dir
+ ${CMAKE_COMMAND} -E make_directory "${build_dir}"
+ )
+ set_tests_properties(${testname}_create_build_dir PROPERTIES
+ FIXTURES_SETUP "${testname}_ensure_clean_build_dir"
+ )
+
+ set_tests_properties(${testname}_create_build_dir
+ PROPERTIES DEPENDS ${testname}_remove_build_dir)
+
+ # Add test to call qmake.
+ #
+ # We can't use the add_test(NAME) signature to set a working directory, because that breaks
+ # when calling ctest without a -C <config> using multi-config generators, and the CI calls
+ # ctest without -C, and we use Xcode when configuring tests for iOS, which is multi-config.
+ # The plain add_test signature does not have this issue.
+ # Work around this by using a wrapper script that sets a working directory and use the plain
+ # signature.
+ # Somewhat related issue https://gitlab.kitware.com/cmake/cmake/-/issues/20283
+ set(qmake_wrapper_file "${CMAKE_CURRENT_BINARY_DIR}/run_qmake_${testname}.cmake")
+ _qt_internal_create_command_script(
+ COMMAND "${qmake_path}" ${qmake_args}
+ COMMAND_ECHO STDOUT
+ OUTPUT_FILE "${qmake_wrapper_file}"
+ WORKING_DIRECTORY "${build_dir}"
+ )
+
+ add_test(${testname}_qmake "${CMAKE_COMMAND}" "-P" "${qmake_wrapper_file}")
+
+ set_tests_properties(${testname}_qmake PROPERTIES
+ DEPENDS ${testname}_create_build_dir
+ FIXTURES_REQUIRED "${testname}_ensure_clean_build_dir"
+ FIXTURES_SETUP "${testname}_configure_project"
+ )
+
+ # Add test to build the generated qmake project.
+ set(build_tool_wrapper_file "${CMAKE_CURRENT_BINARY_DIR}/run_build_${testname}.cmake")
+ _qt_internal_create_command_script(
+ COMMAND "${build_tool}" ${build_tool_args}
+ COMMAND_ECHO STDOUT
+ OUTPUT_FILE "${build_tool_wrapper_file}"
+ WORKING_DIRECTORY "${build_dir}"
+ ENVIRONMENT ${arg_BUILD_ENVIRONMENT}
+ )
+
+ add_test(${testname} "${CMAKE_COMMAND}" "-P" "${build_tool_wrapper_file}")
+
+ set_tests_properties(${testname} PROPERTIES
+ DEPENDS ${testname}_qmake
+ FIXTURES_REQUIRED "${testname}_ensure_clean_build_dir;${testname}_configure_project"
+ )
+endfunction()
+
+# Checks if the build of the test project fails.
+# This test passes if the test project fails either at the
+# configuring or build steps.
+# Arguments: See _qt_internal_test_expect_pass
+macro(_qt_internal_test_expect_fail)
+ _qt_internal_test_expect_pass(${ARGV})
+ set_tests_properties(${testname} PROPERTIES WILL_FAIL TRUE)
+endmacro()
+
+# Checks if the build of the test project fails.
+# This test passes only if the test project fails at the build step,
+# but not at the configuring step.
+macro(_qt_internal_test_expect_build_fail _dir)
string(REPLACE "(" "_" testname "${_dir}")
string(REPLACE ")" "_" testname "${testname}")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/${_dir}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}")
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}/${_dir}/FindPackageHints.cmake" "set(Qt5Tests_PREFIX_PATH \"${CMAKE_PREFIX_PATH}\")")
+ set(__expect_fail_prefixes "")
+ _qt_internal_get_cmake_test_configure_options(option_list OUT_PREFIX_PATH __expect_fail_prefixes)
+
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}/${_dir}/FindPackageHints.cmake"
+ "set(Qt6Tests_PREFIX_PATH \"${__expect_fail_prefixes}\")
+list(APPEND CMAKE_PREFIX_PATH \"${__expect_fail_prefixes}\")
+")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}/CMakeLists.txt"
"
- cmake_minimum_required(VERSION 2.8)
+ cmake_minimum_required(VERSION 3.16)
project(${_dir})
try_compile(Result \${CMAKE_CURRENT_BINARY_DIR}/${_dir}
@@ -112,29 +634,40 @@ macro(expect_fail _dir)
endif()
"
)
+
+
+ if(CMAKE_GENERATOR MATCHES "Ninja")
+ # Use a ninja wrapper when generator is ninja
+ _qt_internal_get_ninja_wrapper("${CMAKE_MAKE_PROGRAM}" ninja_wrapper)
+ set(make_program "${ninja_wrapper}")
+ else()
+ set(make_program "${CMAKE_MAKE_PROGRAM}")
+ endif()
+
add_test(${testname} ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}"
"${CMAKE_CURRENT_BINARY_DIR}/failbuild/${_dir}/build"
--build-config "${CMAKE_BUILD_TYPE}"
- --build-generator ${CMAKE_GENERATOR}
- --build-makeprogram ${CMAKE_MAKE_PROGRAM}
- --build-project ${_dir}
- --build-options "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" ${BUILD_OPTIONS_LIST}
+ --build-generator "${CMAKE_GENERATOR}"
+ --build-makeprogram "${make_program}"
+ --build-project "${_dir}"
+ --build-options ${option_list}
)
+ unset(__expect_fail_prefixes)
endmacro()
-function(test_module_includes)
+function(_qt_internal_test_module_includes)
set(all_args ${ARGN})
set(packages_string "")
set(libraries_string "")
- foreach(_package ${Qt5_MODULE_TEST_DEPENDS})
+ foreach(_package ${Qt6_MODULE_TEST_DEPENDS})
set(packages_string
"
${packages_string}
- find_package(Qt5${_package} 5.0.0 REQUIRED)
+ find_package(Qt6${_package} 6.0.0 REQUIRED)
"
)
endforeach()
@@ -147,52 +680,36 @@ function(test_module_includes)
set(packages_string
"${packages_string}
- find_package(Qt5${qtmodule} 5.0.0 REQUIRED)
- include_directories(\${Qt5${qtmodule}_INCLUDE_DIRS})
- add_definitions(\${Qt5${qtmodule}_DEFINITIONS})\n")
+ find_package(Qt6${qtmodule} 6.0.0 REQUIRED)\n")
list(FIND CMAKE_MODULES_UNDER_TEST ${qtmodule} _findIndex)
if (NOT _findIndex STREQUAL -1)
set(packages_string
"${packages_string}
- if(NOT \"\${Qt5${qtmodule}_VERSION}\" VERSION_EQUAL ${CMAKE_MODULE_VERSION})
- message(SEND_ERROR \"Qt5${qtmodule}_VERSION variable was not ${CMAKE_MODULE_VERSION}. Got \${Qt5${qtmodule}_VERSION} instead.\")
+ if(NOT \"\${Qt6${qtmodule}_VERSION}\" VERSION_EQUAL ${CMAKE_MODULE_VERSION})
+ message(SEND_ERROR \"Qt6${qtmodule}_VERSION variable was not ${CMAKE_MODULE_VERSION}. Got \${Qt6${qtmodule}_VERSION} instead.\")
endif()
- if(NOT \"\${Qt5${qtmodule}_VERSION_MAJOR}\" VERSION_EQUAL ${CMAKE_${qtmodule}_MODULE_MAJOR_VERSION})
- message(SEND_ERROR \"Qt5${qtmodule}_VERSION_MAJOR variable was not ${CMAKE_${qtmodule}_MODULE_MAJOR_VERSION}. Got \${Qt5${qtmodule}_VERSION_MAJOR} instead.\")
+ if(NOT \"\${Qt6${qtmodule}_VERSION_MAJOR}\" VERSION_EQUAL ${CMAKE_${qtmodule}_MODULE_MAJOR_VERSION})
+ message(SEND_ERROR \"Qt6${qtmodule}_VERSION_MAJOR variable was not ${CMAKE_${qtmodule}_MODULE_MAJOR_VERSION}. Got \${Qt6${qtmodule}_VERSION_MAJOR} instead.\")
endif()
- if(NOT \"\${Qt5${qtmodule}_VERSION_MINOR}\" VERSION_EQUAL ${CMAKE_${qtmodule}_MODULE_MINOR_VERSION})
- message(SEND_ERROR \"Qt5${qtmodule}_VERSION_MINOR variable was not ${CMAKE_${qtmodule}_MODULE_MINOR_VERSION}. Got \${Qt5${qtmodule}_VERSION_MINOR} instead.\")
+ if(NOT \"\${Qt6${qtmodule}_VERSION_MINOR}\" VERSION_EQUAL ${CMAKE_${qtmodule}_MODULE_MINOR_VERSION})
+ message(SEND_ERROR \"Qt6${qtmodule}_VERSION_MINOR variable was not ${CMAKE_${qtmodule}_MODULE_MINOR_VERSION}. Got \${Qt6${qtmodule}_VERSION_MINOR} instead.\")
endif()
- if(NOT \"\${Qt5${qtmodule}_VERSION_PATCH}\" VERSION_EQUAL ${CMAKE_${qtmodule}_MODULE_PATCH_VERSION})
- message(SEND_ERROR \"Qt5${qtmodule}_VERSION_PATCH variable was not ${CMAKE_${qtmodule}_MODULE_PATCH_VERSION}. Got \${Qt5${qtmodule}_VERSION_PATCH} instead.\")
- endif()
- if(NOT \"\${Qt5${qtmodule}_VERSION_STRING}\" VERSION_EQUAL ${CMAKE_MODULE_VERSION})
- message(SEND_ERROR \"Qt5${qtmodule}_VERSION_STRING variable was not ${CMAKE_MODULE_VERSION}. Got \${Qt5${qtmodule}_VERSION_STRING} instead.\")
+ if(NOT \"\${Qt6${qtmodule}_VERSION_PATCH}\" VERSION_EQUAL ${CMAKE_${qtmodule}_MODULE_PATCH_VERSION})
+ message(SEND_ERROR \"Qt6${qtmodule}_VERSION_PATCH variable was not ${CMAKE_${qtmodule}_MODULE_PATCH_VERSION}. Got \${Qt6${qtmodule}_VERSION_PATCH} instead.\")
endif()\n"
)
endif()
- set(libraries_string "${libraries_string} Qt5::${qtmodule}")
+ set(libraries_string "${libraries_string} Qt6::${qtmodule}")
endwhile()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/module_includes/CMakeLists.txt"
"
- cmake_minimum_required(VERSION 2.8)
+ cmake_minimum_required(VERSION 3.16)
project(module_includes)
${packages_string}
- set(CMAKE_CXX_FLAGS \"\${CMAKE_CXX_FLAGS} \${Qt5Core_EXECUTABLE_COMPILE_FLAGS}\")
- if (CMAKE_VERSION VERSION_LESS 3.3)
- if (CMAKE_CXX_COMPILER_ID STREQUAL AppleClang
- OR (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang))
- set(CMAKE_CXX_FLAGS \"\${CMAKE_CXX_FLAGS} -std=gnu++0x -stdlib=libc++\")
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL GNU
- OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
- set(CMAKE_CXX_FLAGS \"\${CMAKE_CXX_FLAGS} -std=gnu++0x\")
- endif()
- endif()
-
add_executable(module_includes_exe \"\${CMAKE_CURRENT_SOURCE_DIR}/main.cpp\")
target_link_libraries(module_includes_exe ${libraries_string})\n"
)
@@ -230,14 +747,24 @@ function(test_module_includes)
int main(int, char **) { ${instances_string} return 0; }\n"
)
+ _qt_internal_get_cmake_test_configure_options(option_list)
+
+ if(CMAKE_GENERATOR MATCHES "Ninja")
+ # Use a ninja wrapper when generator is ninja
+ _qt_internal_get_ninja_wrapper("${CMAKE_MAKE_PROGRAM}" ninja_wrapper)
+ set(make_program "${ninja_wrapper}")
+ else()
+ set(make_program "${CMAKE_MAKE_PROGRAM}")
+ endif()
+
add_test(module_includes ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMAKE_CURRENT_BINARY_DIR}/module_includes/"
"${CMAKE_CURRENT_BINARY_DIR}/module_includes/build"
--build-config "${CMAKE_BUILD_TYPE}"
- --build-generator ${CMAKE_GENERATOR}
- --build-makeprogram ${CMAKE_MAKE_PROGRAM}
+ --build-generator "${CMAKE_GENERATOR}"
+ --build-makeprogram "${make_program}"
--build-project module_includes
- --build-options "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" ${BUILD_OPTIONS_LIST}
+ --build-options ${option_list}
)
endfunction()
diff --git a/src/corelib/Qt6Config.cmake.in b/src/corelib/Qt6Config.cmake.in
deleted file mode 100644
index 6b6544f932..0000000000
--- a/src/corelib/Qt6Config.cmake.in
+++ /dev/null
@@ -1,51 +0,0 @@
-
-if (CMAKE_VERSION VERSION_LESS 3.1.0)
- message(FATAL_ERROR \"Qt5 requires at least CMake version 3.1.0\")
-endif()
-
-if (NOT Qt5_FIND_COMPONENTS)
- set(Qt5_NOT_FOUND_MESSAGE \"The Qt5 package requires at least one component\")
- set(Qt5_FOUND False)
- return()
-endif()
-
-set(_Qt5_FIND_PARTS_REQUIRED)
-if (Qt5_FIND_REQUIRED)
- set(_Qt5_FIND_PARTS_REQUIRED REQUIRED)
-endif()
-set(_Qt5_FIND_PARTS_QUIET)
-if (Qt5_FIND_QUIETLY)
- set(_Qt5_FIND_PARTS_QUIET QUIET)
-endif()
-
-get_filename_component(_qt5_install_prefix \"${CMAKE_CURRENT_LIST_DIR}/..\" ABSOLUTE)
-
-set(_Qt5_NOTFOUND_MESSAGE)
-
-include(${CMAKE_CURRENT_LIST_DIR}/Qt5ModuleLocation.cmake)
-
-foreach(module ${Qt5_FIND_COMPONENTS})
- find_package(Qt5${module}
- ${_Qt5_FIND_PARTS_QUIET}
- ${_Qt5_FIND_PARTS_REQUIRED}
- PATHS ${_qt5_module_paths} NO_DEFAULT_PATH
- )
- if (NOT Qt5${module}_FOUND)
- string(CONFIGURE ${_qt5_module_location_template} _expected_module_location @ONLY)
-
- if (Qt5_FIND_REQUIRED_${module})
- set(_Qt5_NOTFOUND_MESSAGE \"${_Qt5_NOTFOUND_MESSAGE}Failed to find Qt5 component \\\"${module}\\\" config file at \\\"${_expected_module_location}\\\"\\n\")
- elseif(NOT Qt5_FIND_QUIETLY)
- message(WARNING \"Failed to find Qt5 component \\\"${module}\\\" config file at \\\"${_expected_module_location}\\\"\")
- endif()
-
- unset(_expected_module_location)
- endif()
-endforeach()
-
-if (_Qt5_NOTFOUND_MESSAGE)
- set(Qt5_NOT_FOUND_MESSAGE \"${_Qt5_NOTFOUND_MESSAGE}\")
- set(Qt5_FOUND False)
-endif()
-
-_qt5_Core_check_file_exists(\"${CMAKE_CURRENT_LIST_DIR}/Qt5ConfigVersion.cmake\")
diff --git a/src/corelib/Qt6CoreConfigExtras.cmake.in b/src/corelib/Qt6CoreConfigExtras.cmake.in
index bd542117e4..7fd929e59b 100644
--- a/src/corelib/Qt6CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt6CoreConfigExtras.cmake.in
@@ -2,43 +2,57 @@ if(NOT DEFINED QT_DEFAULT_MAJOR_VERSION)
set(QT_DEFAULT_MAJOR_VERSION 6)
endif()
-# include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5CoreConfigExtrasMkspecDir.cmake\")
-#
-# foreach(_dir ${_qt5_corelib_extra_includes})
-# _qt5_Core_check_file_exists(${_dir})
-# endforeach()
+if (NOT QT_NO_CREATE_TARGETS)
+ set(__qt_core_target @QT_CMAKE_EXPORT_NAMESPACE@::Core)
+ get_property(__qt_core_aliased_target TARGET ${__qt_core_target} PROPERTY ALIASED_TARGET)
+ if(__qt_core_aliased_target)
+ set(__qt_core_target "${__qt_core_aliased_target}")
+ endif()
+ unset(__qt_core_aliased_target)
+ @qtcore_namespace_definition@
+ set_property(TARGET ${__qt_core_target} APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>)
+ set_property(TARGET ${__qt_core_target} PROPERTY INTERFACE_COMPILE_FEATURES cxx_decltype)
+endif()
-# list(APPEND Qt5Core_INCLUDE_DIRS ${_qt5_corelib_extra_includes})
-# set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${_qt5_corelib_extra_includes})
-# set(_qt5_corelib_extra_includes)
+# note: all the other AUTOMOC_MACRO_NAMES are already set by upstream CMake
+list(APPEND CMAKE_AUTOMOC_MACRO_NAMES Q_GADGET_EXPORT Q_ENUM_NS)
+list(REMOVE_DUPLICATES CMAKE_AUTOMOC_MACRO_NAMES)
-if (NOT QT_NO_CREATE_TARGETS)
- set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core PROPERTY INTERFACE_QT_MAJOR_VERSION @PROJECT_VERSION_MAJOR@)
- set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core PROPERTY INTERFACE_QT_COORD_TYPE @QT_COORD_TYPE@)
- set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core APPEND PROPERTY
- COMPATIBLE_INTERFACE_STRING QT_MAJOR_VERSION QT_COORD_TYPE
- )
- if (NOT "@QT_NAMESPACE@" STREQUAL "")
- set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT_NAMESPACE=@QT_NAMESPACE@)
+set(QT@PROJECT_VERSION_MAJOR@_IS_SHARED_LIBS_BUILD "@BUILD_SHARED_LIBS@")
+set(QT@PROJECT_VERSION_MAJOR@_DEBUG_POSTFIX "@CMAKE_DEBUG_POSTFIX@")
+
+set(_Qt6CTestMacros "${CMAKE_CURRENT_LIST_DIR}/Qt6CTestMacros.cmake")
+
+_qt_internal_setup_deploy_support()
+
+@qtcore_extra_cmake_code@
+
+if(ANDROID_PLATFORM)
+ include("${CMAKE_CURRENT_LIST_DIR}/@QT_CMAKE_EXPORT_NAMESPACE@AndroidMacros.cmake")
+ _qt_internal_create_global_android_targets()
+ _qt_internal_collect_default_android_abis()
+ if(NOT QT_NO_CREATE_TARGETS)
+ set_property(TARGET ${__qt_core_target} APPEND PROPERTY
+ INTERFACE_QT_EXECUTABLE_FINALIZERS
+ _qt_internal_android_executable_finalizer
+ )
+ endif()
+endif()
+
+if(QT_FEATURE_permissions AND APPLE)
+ if(NOT QT_NO_CREATE_TARGETS)
+ set_property(TARGET ${__qt_core_target} APPEND PROPERTY
+ INTERFACE_QT_EXECUTABLE_FINALIZERS
+ _qt_internal_darwin_permission_finalizer
+ )
endif()
- set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>)
- set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core PROPERTY INTERFACE_COMPILE_FEATURES cxx_decltype)
endif()
-set(CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT" "Q_GADGET" "Q_NAMESPACE" "Q_NAMESPACE_EXPORT")
-
-# install layout information, following what qmake -query provides
-get_filename_component(QT@PROJECT_VERSION_MAJOR@_INSTALL_PREFIX ${CMAKE_CURRENT_LIST_DIR}/../@QT_INVERSE_CONFIG_INSTALL_DIR@ ABSOLUTE)
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_ARCHDATA "@INSTALL_ARCHDATADIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_BINS "@INSTALL_BINDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_CONFIGURATION "@INSTALL_SYSCONFDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_DATA "@INSTALL_DATADIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_DOCS "@INSTALL_DOCDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_EXAMPLES "@INSTALL_EXAMPLESDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_HEADERS "@INSTALL_INCLUDEDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_LIBS "@INSTALL_LIBDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_LIBEXECS "@INSTALL_LIBEXECDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_PLUGINS "@INSTALL_PLUGINSDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_QML "@INSTALL_QMLDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_TESTS "@INSTALL_TESTSDIR@")
-set(QT@PROJECT_VERSION_MAJOR@_INSTALL_TRANSLATIONS "@INSTALL_TRANSLATIONSDIR@")
+if(EMSCRIPTEN)
+ set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
+ include("${CMAKE_CURRENT_LIST_DIR}/@QT_CMAKE_EXPORT_NAMESPACE@WasmMacros.cmake")
+endif()
+
+_qt_internal_override_example_install_dir_to_dot()
+
+unset(__qt_core_target)
diff --git a/src/corelib/Qt6CoreConfigExtrasMkspecDir.cmake.in b/src/corelib/Qt6CoreConfigExtrasMkspecDir.cmake.in
deleted file mode 100644
index c357237d0e..0000000000
--- a/src/corelib/Qt6CoreConfigExtrasMkspecDir.cmake.in
+++ /dev/null
@@ -1,6 +0,0 @@
-
-!!IF isEmpty(CMAKE_HOST_DATA_DIR_IS_ABSOLUTE)
-set(_qt5_corelib_extra_includes \"${_qt5Core_install_prefix}/$${CMAKE_HOST_DATA_DIR}/mkspecs/$${CMAKE_MKSPEC}\")
-!!ELSE
-set(_qt5_corelib_extra_includes \"$${CMAKE_HOST_DATA_DIR}mkspecs/$${CMAKE_MKSPEC}\")
-!!ENDIF
diff --git a/src/corelib/Qt6CoreConfigExtrasMkspecDirForInstall.cmake.in b/src/corelib/Qt6CoreConfigExtrasMkspecDirForInstall.cmake.in
deleted file mode 100644
index 706304cf34..0000000000
--- a/src/corelib/Qt6CoreConfigExtrasMkspecDirForInstall.cmake.in
+++ /dev/null
@@ -1,6 +0,0 @@
-
-!!IF isEmpty(CMAKE_INSTALL_DATA_DIR_IS_ABSOLUTE)
-set(_qt5_corelib_extra_includes \"${_qt5Core_install_prefix}/$${CMAKE_INSTALL_DATA_DIR}/mkspecs/$${CMAKE_MKSPEC}\")
-!!ELSE
-set(_qt5_corelib_extra_includes \"$${CMAKE_INSTALL_DATA_DIR}mkspecs/$${CMAKE_MKSPEC}\")
-!!ENDIF
diff --git a/src/corelib/Qt6CoreConfigureFileTemplate.in b/src/corelib/Qt6CoreConfigureFileTemplate.in
new file mode 100644
index 0000000000..5ed5cae0a7
--- /dev/null
+++ b/src/corelib/Qt6CoreConfigureFileTemplate.in
@@ -0,0 +1 @@
+@qt_core_configure_file_contents@
diff --git a/src/corelib/Qt6CoreDeploySupport.cmake b/src/corelib/Qt6CoreDeploySupport.cmake
new file mode 100644
index 0000000000..2fc8f8bf1c
--- /dev/null
+++ b/src/corelib/Qt6CoreDeploySupport.cmake
@@ -0,0 +1,680 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# NOTE: This code should only ever be executed in script mode. It expects to be
+# used either as part of an install(CODE) call or called by a script
+# invoked via cmake -P as a POST_BUILD step.
+
+cmake_minimum_required(VERSION 3.16...3.21)
+
+function(qt6_deploy_qt_conf qt_conf_absolute_path)
+ set(no_value_options "")
+ set(single_value_options
+ PREFIX
+ DOC_DIR
+ HEADERS_DIR
+ LIB_DIR
+ LIBEXEC_DIR
+ BIN_DIR
+ PLUGINS_DIR
+ QML_DIR
+ ARCHDATA_DIR
+ DATA_DIR
+ TRANSLATIONS_DIR
+ EXAMPLES_DIR
+ TESTS_DIR
+ SETTINGS_DIR
+ )
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ if(arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unparsed arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT IS_ABSOLUTE "${qt_conf_absolute_path}")
+ message(FATAL_ERROR
+ "Given qt.conf path is not an absolute path: '${qt_conf_absolute_path}'")
+ endif()
+
+ # Only write out locations that differ from the defaults
+ set(contents "[Paths]\n")
+ if(arg_PREFIX)
+ string(APPEND contents "Prefix = ${arg_PREFIX}\n")
+ endif()
+ if(arg_DOC_DIR AND NOT arg_DOC_DIR STREQUAL "doc")
+ string(APPEND contents "Documentation = ${arg_DOC_DIR}\n")
+ endif()
+ if(arg_HEADERS_DIR AND NOT arg_HEADERS_DIR STREQUAL "include")
+ string(APPEND contents "Headers = ${arg_HEADERS_DIR}\n")
+ endif()
+ if(arg_LIB_DIR AND NOT arg_LIB_DIR STREQUAL "lib")
+ string(APPEND contents "Libraries = ${arg_LIB_DIR}\n")
+ endif()
+
+ # This one is special, the default is platform-specific
+ if(arg_LIBEXEC_DIR AND
+ ((WIN32 AND NOT arg_LIBEXEC_DIR STREQUAL "bin") OR
+ (NOT WIN32 AND NOT arg_LIBEXEC_DIR STREQUAL "libexec")))
+ string(APPEND contents "LibraryExecutables = ${arg_LIBEXEC_DIR}\n")
+ endif()
+
+ if(arg_BIN_DIR AND NOT arg_BIN_DIR STREQUAL "bin")
+ string(APPEND contents "Binaries = ${arg_BIN_DIR}\n")
+ endif()
+ if(arg_PLUGINS_DIR AND NOT arg_PLUGINS_DIR STREQUAL "plugins")
+ string(APPEND contents "Plugins = ${arg_PLUGINS_DIR}\n")
+ endif()
+ if(arg_QML_DIR AND NOT arg_QML_DIR STREQUAL "qml")
+ string(APPEND contents "QmlImports = ${arg_QML_DIR}\n")
+ endif()
+ if(arg_ARCHDATA_DIR AND NOT arg_ARCHDATA_DIR STREQUAL ".")
+ string(APPEND contents "ArchData = ${arg_ARCHDATA_DIR}\n")
+ endif()
+ if(arg_DATA_DIR AND NOT arg_DATA_DIR STREQUAL ".")
+ string(APPEND contents "Data = ${arg_DATA_DIR}\n")
+ endif()
+ if(arg_TRANSLATIONS_DIR AND NOT arg_TRANSLATIONS_DIR STREQUAL "translations")
+ string(APPEND contents "Translations = ${arg_TRANSLATIONS_DIR}\n")
+ endif()
+ if(arg_EXAMPLES_DIR AND NOT arg_EXAMPLES_DIR STREQUAL "examples")
+ string(APPEND contents "Examples = ${arg_EXAMPLES_DIR}\n")
+ endif()
+ if(arg_TESTS_DIR AND NOT arg_TESTS_DIR STREQUAL "tests")
+ string(APPEND contents "Tests = ${arg_TESTS_DIR}\n")
+ endif()
+ if(arg_SETTINGS_DIR AND NOT arg_SETTINGS_DIR STREQUAL ".")
+ string(APPEND contents "Settings = ${arg_SETTINGS_DIR}\n")
+ endif()
+
+ message(STATUS "Writing ${qt_conf_absolute_path}")
+ file(WRITE "${qt_conf_absolute_path}" "${contents}")
+endfunction()
+
+if(NOT __QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_deploy_qt_conf)
+ if(__QT_DEFAULT_MAJOR_VERSION EQUAL 6)
+ qt6_deploy_qt_conf(${ARGV})
+ else()
+ message(FATAL_ERROR "qt_deploy_qt_conf() is only available in Qt 6.")
+ endif()
+ endfunction()
+endif()
+
+# Copied from QtCMakeHelpers.cmake
+function(_qt_internal_re_escape out_var str)
+ string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex "${str}")
+ set(${out_var} ${regex} PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_set_rpath)
+ if(NOT CMAKE_HOST_UNIX OR CMAKE_HOST_APPLE)
+ message(WARNING "_qt_internal_set_rpath is not implemented on this platform.")
+ return()
+ endif()
+
+ set(no_value_options "")
+ set(single_value_options FILE NEW_RPATH)
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+ if(__QT_DEPLOY_USE_PATCHELF)
+ message(STATUS "Setting runtime path of '${arg_FILE}' to '${arg_NEW_RPATH}'.")
+ execute_process(
+ COMMAND ${__QT_DEPLOY_PATCHELF_EXECUTABLE} --set-rpath "${arg_NEW_RPATH}" "${arg_FILE}"
+ RESULT_VARIABLE process_result
+ )
+ if(NOT process_result EQUAL "0")
+ if(process_result MATCHES "^[0-9]+$")
+ message(FATAL_ERROR "patchelf failed with exit code ${process_result}.")
+ else()
+ message(FATAL_ERROR "patchelf failed: ${process_result}.")
+ endif()
+ endif()
+ else()
+ # Warning: file(RPATH_SET) is CMake-internal API.
+ file(RPATH_SET
+ FILE "${arg_FILE}"
+ NEW_RPATH "${arg_NEW_RPATH}"
+ )
+ endif()
+endfunction()
+
+# Store the platform-dependent $ORIGIN marker in out_var.
+function(_qt_internal_get_rpath_origin out_var)
+ if(__QT_DEPLOY_SYSTEM_NAME STREQUAL "Darwin")
+ set(rpath_origin "@loader_path")
+ else()
+ set(rpath_origin "$ORIGIN")
+ endif()
+ set(${out_var} ${rpath_origin} PARENT_SCOPE)
+endfunction()
+
+# Add a function to the list of deployment hooks.
+# The hooks are run at the end of _qt_internal_generic_deployqt.
+#
+# Every hook is passed the parameters of _qt_internal_generic_deployqt plus the following:
+# RESOLVED_DEPENDENCIES: list of resolved dependencies that were installed.
+function(_qt_internal_add_deployment_hook function_name)
+ set_property(GLOBAL APPEND PROPERTY QT_INTERNAL_DEPLOYMENT_HOOKS "${function_name}")
+endfunction()
+
+# Run all registered deployment hooks.
+function(_qt_internal_run_deployment_hooks)
+ get_property(hooks GLOBAL PROPERTY QT_INTERNAL_DEPLOYMENT_HOOKS)
+ foreach(hook IN LISTS hooks)
+ if(NOT COMMAND "${hook}")
+ message(AUTHOR_WARNING "'${hook}' is not a command but was added as deployment hook.")
+ continue()
+ endif()
+ if(CMAKE_VERSION GREATER_EQUAL "3.19")
+ cmake_language(CALL "${hook}" ${ARGV})
+ else()
+ set(temp_file ".qt-run-deploy-hook.cmake")
+ file(WRITE "${temp_file}" "${hook}(${ARGV})")
+ include(${temp_file})
+ file(REMOVE "${temp_file}")
+ endif()
+ endforeach()
+endfunction()
+
+function(_qt_internal_generic_deployqt)
+ set(no_value_options
+ NO_TRANSLATIONS
+ VERBOSE
+ )
+ set(single_value_options
+ LIB_DIR
+ PLUGINS_DIR
+ )
+ set(file_GRD_options
+ EXECUTABLES
+ LIBRARIES
+ MODULES
+ PRE_INCLUDE_REGEXES
+ PRE_EXCLUDE_REGEXES
+ POST_INCLUDE_REGEXES
+ POST_EXCLUDE_REGEXES
+ POST_INCLUDE_FILES
+ POST_EXCLUDE_FILES
+ )
+ set(multi_value_options ${file_GRD_options})
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ if(arg_VERBOSE OR __QT_DEPLOY_VERBOSE)
+ set(verbose TRUE)
+ endif()
+
+ # Make input file paths absolute
+ foreach(var IN ITEMS EXECUTABLES LIBRARIES MODULES)
+ string(PREPEND var arg_)
+ set(abspaths "")
+ foreach(path IN LISTS ${var})
+ get_filename_component(abspath "${path}" REALPATH BASE_DIR "${QT_DEPLOY_PREFIX}")
+ list(APPEND abspaths "${abspath}")
+ endforeach()
+ set(${var} "${abspaths}")
+ endforeach()
+
+ # We need to get the runtime dependencies of plugins too.
+ list(APPEND arg_MODULES ${__QT_DEPLOY_PLUGINS})
+
+ # Forward the arguments that are exactly the same for file(GET_RUNTIME_DEPENDENCIES).
+ set(file_GRD_args "")
+ foreach(var IN LISTS file_GRD_options)
+ if(NOT "${arg_${var}}" STREQUAL "")
+ list(APPEND file_GRD_args ${var} ${arg_${var}})
+ endif()
+ endforeach()
+
+ # Compile a list of regular expressions that represent ignored library directories.
+ if("${arg_POST_EXCLUDE_REGEXES}" STREQUAL "")
+ set(regexes "")
+ foreach(path IN LISTS QT_DEPLOY_IGNORED_LIB_DIRS)
+ _qt_internal_re_escape(path_rex "${path}")
+ list(APPEND regexes "^${path_rex}")
+ endforeach()
+ if(regexes)
+ list(APPEND file_GRD_args POST_EXCLUDE_REGEXES ${regexes})
+ endif()
+ endif()
+
+ # Get the runtime dependencies recursively.
+ file(GET_RUNTIME_DEPENDENCIES
+ ${file_GRD_args}
+ RESOLVED_DEPENDENCIES_VAR resolved
+ UNRESOLVED_DEPENDENCIES_VAR unresolved
+ CONFLICTING_DEPENDENCIES_PREFIX conflicting
+ )
+ if(verbose)
+ message("file(GET_RUNTIME_DEPENDENCIES ${file_args})")
+ foreach(file IN LISTS resolved)
+ message(" resolved: ${file}")
+ endforeach()
+ foreach(file IN LISTS unresolved)
+ message(" unresolved: ${file}")
+ endforeach()
+ foreach(file IN LISTS conflicting_FILENAMES)
+ message(" conflicting: ${file}")
+ message(" with ${conflicting_${file}}")
+ endforeach()
+ endif()
+
+ # Deploy the Qt libraries.
+ file(INSTALL ${resolved}
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/${arg_LIB_DIR}"
+ FOLLOW_SYMLINK_CHAIN
+ )
+
+ # Determine the runtime path origin marker if necessary.
+ if(__QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH)
+ _qt_internal_get_rpath_origin(rpath_origin)
+ endif()
+
+ # Deploy the Qt plugins.
+ foreach(file_path IN LISTS __QT_DEPLOY_PLUGINS)
+ file(RELATIVE_PATH destination
+ "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_PLUGINS}"
+ "${file_path}"
+ )
+ get_filename_component(destination "${destination}" DIRECTORY)
+ string(PREPEND destination "${CMAKE_INSTALL_PREFIX}/${arg_PLUGINS_DIR}/")
+ file(INSTALL ${file_path} DESTINATION ${destination})
+
+ if(__QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH)
+ get_filename_component(file_name ${file_path} NAME)
+ file(RELATIVE_PATH rel_lib_dir "${destination}"
+ "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_LIB_DIR}")
+ _qt_internal_set_rpath(
+ FILE "${destination}/${file_name}"
+ NEW_RPATH "${rpath_origin}/${rel_lib_dir}"
+ )
+ endif()
+ endforeach()
+
+ # Deploy translations.
+ if(NOT arg_NO_TRANSLATIONS)
+ qt6_deploy_translations()
+ endif()
+
+ _qt_internal_run_deployment_hooks(${ARGV} RESOLVED_DEPENDENCIES ${resolved})
+endfunction()
+
+function(qt6_deploy_runtime_dependencies)
+
+ if(NOT __QT_DEPLOY_TOOL)
+ message(FATAL_ERROR "No Qt deploy tool available for this target platform")
+ endif()
+
+ set(no_value_options
+ GENERATE_QT_CONF
+ VERBOSE
+ NO_OVERWRITE
+ NO_APP_STORE_COMPLIANCE # TODO: Might want a better name
+ NO_TRANSLATIONS
+ NO_COMPILER_RUNTIME
+ )
+ set(single_value_options
+ EXECUTABLE
+ BIN_DIR
+ LIB_DIR
+ LIBEXEC_DIR
+ PLUGINS_DIR
+ QML_DIR
+ )
+ set(file_GRD_options
+ # The following include/exclude options are only used if the "generic deploy tool" is
+ # used. The options are what file(GET_RUNTIME_DEPENDENCIES) supports.
+ PRE_INCLUDE_REGEXES
+ PRE_EXCLUDE_REGEXES
+ POST_INCLUDE_REGEXES
+ POST_EXCLUDE_REGEXES
+ POST_INCLUDE_FILES
+ POST_EXCLUDE_FILES
+ )
+ set(multi_value_options
+ # These ADDITIONAL_... options are based on what file(GET_RUNTIME_DEPENDENCIES)
+ # supports. We differentiate between the types of binaries so that we keep
+ # open the possibility of switching to a purely CMake implementation of
+ # the deploy tool based on file(GET_RUNTIME_DEPENDENCIES) instead of the
+ # individual platform-specific tools (macdeployqt, windeployqt, etc.).
+ ADDITIONAL_EXECUTABLES
+ ADDITIONAL_LIBRARIES
+ ADDITIONAL_MODULES
+ ${file_GRD_options}
+ DEPLOY_TOOL_OPTIONS
+ )
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ if(arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unparsed arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT arg_EXECUTABLE)
+ message(FATAL_ERROR "EXECUTABLE must be specified")
+ endif()
+
+ # None of these are used if the executable is a macOS app bundle
+ if(NOT arg_BIN_DIR)
+ set(arg_BIN_DIR "${QT_DEPLOY_BIN_DIR}")
+ endif()
+ if(NOT arg_LIBEXEC_DIR)
+ set(arg_LIBEXEC_DIR "${QT_DEPLOY_LIBEXEC_DIR}")
+ endif()
+ if(NOT arg_LIB_DIR)
+ set(arg_LIB_DIR "${QT_DEPLOY_LIB_DIR}")
+ endif()
+ if(NOT arg_QML_DIR)
+ set(arg_QML_DIR "${QT_DEPLOY_QML_DIR}")
+ endif()
+ if(NOT arg_PLUGINS_DIR)
+ set(arg_PLUGINS_DIR "${QT_DEPLOY_PLUGINS_DIR}")
+ endif()
+
+ # macdeployqt always writes out a qt.conf file. It will complain if one
+ # already exists, so leave it to create it for us if we will be running it.
+ if(__QT_DEPLOY_SYSTEM_NAME STREQUAL Darwin)
+ # We might get EXECUTABLE pointing to either the actual binary under the
+ # Contents/MacOS directory, or it might be pointing to the top of the
+ # app bundle (i.e. the <appname>.app directory). We want the latter to
+ # pass to macdeployqt.
+ if(arg_EXECUTABLE MATCHES "^((.*/)?(.*).app)/Contents/MacOS/(.*)$")
+ set(arg_EXECUTABLE "${CMAKE_MATCH_1}")
+ endif()
+ elseif(arg_GENERATE_QT_CONF)
+ set(exe_dir "${QT_DEPLOY_BIN_DIR}")
+ if(exe_dir STREQUAL "" OR exe_dir STREQUAL ".")
+ set(exe_dir ".")
+ set(prefix ".")
+ else()
+ string(REPLACE "/" ";" path "${exe_dir}")
+ list(LENGTH path path_count)
+ string(REPEAT "../" ${path_count} rel_path)
+ string(REGEX REPLACE "/+$" "" prefix "${rel_path}")
+ endif()
+ qt6_deploy_qt_conf("${QT_DEPLOY_PREFIX}/${exe_dir}/qt.conf"
+ PREFIX "${prefix}"
+ BIN_DIR "${arg_BIN_DIR}"
+ LIB_DIR "${arg_LIB_DIR}"
+ PLUGINS_DIR "${arg_PLUGINS_DIR}"
+ QML_DIR "${arg_QML_DIR}"
+ )
+ endif()
+
+ set(extra_binaries_option "")
+ set(tool_options "")
+
+ if(arg_VERBOSE OR __QT_DEPLOY_VERBOSE)
+ # macdeployqt supports 0-3: 0=no output, 1=error/warn (default), 2=normal, 3=debug
+ # windeployqt supports 0-2: 0=error/warn (default), 1=verbose, 2=full_verbose
+ if(__QT_DEPLOY_SYSTEM_NAME STREQUAL Windows)
+ list(APPEND tool_options --verbose 2)
+ elseif(__QT_DEPLOY_SYSTEM_NAME STREQUAL Darwin)
+ list(APPEND tool_options -verbose=3)
+ else()
+ list(APPEND tool_options VERBOSE)
+ endif()
+ endif()
+
+ if(__QT_DEPLOY_SYSTEM_NAME STREQUAL Windows)
+ list(APPEND tool_options
+ --dir .
+ --libdir "${arg_BIN_DIR}" # NOTE: Deliberately not arg_LIB_DIR
+ --plugindir "${arg_PLUGINS_DIR}"
+ --qml-deploy-dir "${arg_QML_DIR}"
+ --translationdir "${QT_DEPLOY_TRANSLATIONS_DIR}"
+ )
+ if(NOT arg_NO_OVERWRITE)
+ list(APPEND tool_options --force)
+ endif()
+ if(arg_NO_TRANSLATIONS)
+ list(APPEND tool_options --no-translations)
+ endif()
+ if(arg_NO_COMPILER_RUNTIME)
+ list(APPEND tool_options --no-compiler-runtime)
+ endif()
+
+ # Specify path to target Qt's qtpaths .exe or .bat file, so windeployqt deploys the correct
+ # libraries when cross-compiling from x86_64 to arm64 windows.
+ if(__QT_DEPLOY_TARGET_QT_PATHS_PATH AND EXISTS "${__QT_DEPLOY_TARGET_QT_PATHS_PATH}")
+ list(APPEND tool_options --qtpaths "${__QT_DEPLOY_TARGET_QT_PATHS_PATH}")
+ else()
+ message(WARNING
+ "No qtpaths executable found for target Qt "
+ "at: ${__QT_DEPLOY_TARGET_QT_PATHS_PATH}. "
+ "Libraries may not be deployed correctly.")
+ endif()
+
+ list(APPEND tool_options ${arg_DEPLOY_TOOL_OPTIONS})
+ elseif(__QT_DEPLOY_SYSTEM_NAME STREQUAL Darwin)
+ set(extra_binaries_option "-executable=")
+ if(NOT arg_NO_APP_STORE_COMPLIANCE)
+ list(APPEND tool_options -appstore-compliant)
+ endif()
+ if(NOT arg_NO_OVERWRITE)
+ list(APPEND tool_options -always-overwrite)
+ endif()
+ list(APPEND tool_options ${arg_DEPLOY_TOOL_OPTIONS})
+ endif()
+
+ # This is an internal variable. It is normally unset and is only intended
+ # for debugging purposes. It may be removed at any time without warning.
+ list(APPEND tool_options ${__qt_deploy_tool_extra_options})
+
+ if(__QT_DEPLOY_TOOL STREQUAL "GRD")
+ message(STATUS "Running generic Qt deploy tool on ${arg_EXECUTABLE}")
+
+ if(NOT "${arg_DEPLOY_TOOL_OPTIONS}" STREQUAL "")
+ message(WARNING
+ "DEPLOY_TOOL_OPTIONS was specified but has no effect when using the generic "
+ "deployment tool."
+ )
+ endif()
+
+ # Construct the EXECUTABLES, LIBRARIES and MODULES arguments.
+ list(APPEND tool_options EXECUTABLES ${arg_EXECUTABLE})
+ if(NOT "${arg_ADDITIONAL_EXECUTABLES}" STREQUAL "")
+ list(APPEND tool_options ${arg_ADDITIONAL_EXECUTABLES})
+ endif()
+ foreach(file_type LIBRARIES MODULES)
+ if("${arg_ADDITIONAL_${file_type}}" STREQUAL "")
+ continue()
+ endif()
+ list(APPEND tool_options ${file_type} ${arg_ADDITIONAL_${file_type}})
+ endforeach()
+
+ # Forward the arguments that are exactly the same for file(GET_RUNTIME_DEPENDENCIES).
+ foreach(var IN LISTS file_GRD_options)
+ if(NOT "${arg_${var}}" STREQUAL "")
+ list(APPEND tool_options ${var} ${arg_${var}})
+ endif()
+ endforeach()
+
+ if(arg_NO_TRANSLATIONS)
+ list(APPEND tool_options NO_TRANSLATIONS)
+ endif()
+
+ _qt_internal_generic_deployqt(
+ EXECUTABLE "${arg_EXECUTABLE}"
+ LIB_DIR "${arg_LIB_DIR}"
+ PLUGINS_DIR "${arg_PLUGINS_DIR}"
+ ${tool_options}
+ )
+ return()
+ endif()
+
+ # Both windeployqt and macdeployqt don't differentiate between the different
+ # types of binaries, so we merge the lists and treat them all the same.
+ set(additional_binaries
+ ${arg_ADDITIONAL_EXECUTABLES}
+ ${arg_ADDITIONAL_LIBRARIES}
+ ${arg_ADDITIONAL_MODULES}
+ )
+ foreach(extra_binary IN LISTS additional_binaries)
+ list(APPEND tool_options "${extra_binaries_option}${extra_binary}")
+ endforeach()
+
+ message(STATUS
+ "Running Qt deploy tool for ${arg_EXECUTABLE} in working directory '${QT_DEPLOY_PREFIX}'")
+ execute_process(
+ COMMAND_ECHO STDOUT
+ COMMAND "${__QT_DEPLOY_TOOL}" "${arg_EXECUTABLE}" ${tool_options}
+ WORKING_DIRECTORY "${QT_DEPLOY_PREFIX}"
+ RESULT_VARIABLE result
+ )
+ if(result)
+ message(FATAL_ERROR "Executing ${__QT_DEPLOY_TOOL} failed: ${result}")
+ endif()
+
+endfunction()
+
+if(NOT __QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_deploy_runtime_dependencies)
+ if(__QT_DEFAULT_MAJOR_VERSION EQUAL 6)
+ qt6_deploy_runtime_dependencies(${ARGV})
+ else()
+ message(FATAL_ERROR "qt_deploy_runtime_dependencies() is only available in Qt 6.")
+ endif()
+ endfunction()
+endif()
+
+function(_qt_internal_show_skip_runtime_deploy_message qt_build_type_string)
+ set(no_value_options "")
+ set(single_value_options
+ EXTRA_MESSAGE
+ )
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+ message(STATUS
+ "Skipping runtime deployment steps. "
+ "Support for installing runtime dependencies is not implemented for "
+ "this target platform (${__QT_DEPLOY_SYSTEM_NAME}, ${qt_build_type_string}). "
+ "${arg_EXTRA_MESSAGE}"
+ )
+endfunction()
+
+# This function is currently in Technical Preview.
+# Its signature and behavior might change.
+function(qt6_deploy_translations)
+ set(no_value_options VERBOSE)
+ set(single_value_options
+ LCONVERT
+ )
+ set(multi_value_options
+ CATALOGS
+ LOCALES
+ )
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ set(verbose OFF)
+ if(arg_VERBOSE OR __QT_DEPLOY_VERBOSE)
+ set(verbose ON)
+ endif()
+
+ if(arg_CATALOGS)
+ set(catalogs ${arg_CATALOGS})
+ else()
+ set(catalogs ${__QT_DEPLOY_I18N_CATALOGS})
+ endif()
+
+ get_filename_component(qt_translations_dir "${__QT_DEPLOY_QT_INSTALL_TRANSLATIONS}" ABSOLUTE
+ BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}"
+ )
+ set(locales ${arg_LOCALES})
+ if(NOT locales)
+ file(GLOB locales RELATIVE "${qt_translations_dir}" "${qt_translations_dir}/*.qm")
+ list(TRANSFORM locales REPLACE "\\.qm$" "")
+ list(TRANSFORM locales REPLACE "^qt_help" "qt-help")
+ list(TRANSFORM locales REPLACE "^[^_]+" "")
+ list(TRANSFORM locales REPLACE "^_" "")
+ list(REMOVE_DUPLICATES locales)
+ endif()
+
+ # Ensure existence of the output directory.
+ set(output_dir "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}")
+ if(NOT EXISTS "${output_dir}")
+ file(MAKE_DIRECTORY "${output_dir}")
+ endif()
+
+ # Locate lconvert.
+ if(arg_LCONVERT)
+ set(lconvert "${arg_LCONVERT}")
+ else()
+ set(lconvert "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_BINS}/lconvert")
+ if(CMAKE_HOST_WIN32)
+ string(APPEND lconvert ".exe")
+ endif()
+ if(NOT EXISTS ${lconvert})
+ message(STATUS "lconvert was not found. Skipping deployment of translations.")
+ return()
+ endif()
+ endif()
+
+ # Find the .qm files for the selected locales
+ if(verbose)
+ message(STATUS "Looking for translations in ${qt_translations_dir}")
+ endif()
+ foreach(locale IN LISTS locales)
+ set(qm_files "")
+ foreach(catalog IN LISTS catalogs)
+ set(qm_file "${catalog}_${locale}.qm")
+ if(EXISTS "${qt_translations_dir}/${qm_file}")
+ list(APPEND qm_files ${qm_file})
+ endif()
+ endforeach()
+
+ if(NOT qm_files)
+ message(WARNING "No translations found for requested locale '${locale}'.")
+ continue()
+ endif()
+
+ if(verbose)
+ foreach(qm_file IN LISTS qm_files)
+ message(STATUS "found translation file: ${qm_file}")
+ endforeach()
+ endif()
+
+ # Merge the .qm files into one qt_${locale}.qm file.
+ set(output_file_name "qt_${locale}.qm")
+ set(output_file_path "${output_dir}/${output_file_name}")
+ message(STATUS "Creating: ${output_file_path}")
+ set(extra_options)
+ if(verbose)
+ list(APPEND extra_options COMMAND_ECHO STDOUT)
+ endif()
+ execute_process(
+ COMMAND ${lconvert} -if qm -o ${output_file_path} ${qm_files}
+ WORKING_DIRECTORY ${qt_translations_dir}
+ RESULT_VARIABLE process_result
+ ${extra_options}
+ )
+ if(NOT process_result EQUAL "0")
+ if(process_result MATCHES "^[0-9]+$")
+ message(WARNING "lconvert failed with exit code ${process_result}.")
+ else()
+ message(WARNING "lconvert failed: ${process_result}.")
+ endif()
+ endif()
+ endforeach()
+endfunction()
+
+if(NOT __QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_deploy_translations)
+ if(__QT_DEFAULT_MAJOR_VERSION EQUAL 6)
+ qt6_deploy_translations(${ARGV})
+ else()
+ message(FATAL_ERROR "qt_deploy_translations() is only available in Qt 6.")
+ endif()
+ endfunction()
+endif()
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 536928ae60..1a449b4aa3 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -1,34 +1,6 @@
-#=============================================================================
# Copyright 2005-2011 Kitware, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# * Neither the name of Kitware, Inc. nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#=============================================================================
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
######################################
#
@@ -36,10 +8,10 @@
#
######################################
-include(CMakeParseArguments)
+set(__qt_core_macros_module_base_dir "${CMAKE_CURRENT_LIST_DIR}")
# macro used to create the names of output files preserving relative dirs
-macro(qt6_make_output_file infile prefix ext outfile )
+macro(_qt_internal_make_output_file infile prefix ext outfile )
string(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength)
string(LENGTH ${infile} _infileLength)
set(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR})
@@ -71,8 +43,7 @@ macro(qt6_make_output_file infile prefix ext outfile )
set(${outfile} ${outpath}/${prefix}${_outfile}.${ext})
endmacro()
-
-macro(qt6_get_moc_flags _moc_flags)
+macro(_qt_internal_get_moc_flags _moc_flags)
set(${_moc_flags})
get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES)
@@ -102,9 +73,9 @@ macro(qt6_get_moc_flags _moc_flags)
endif()
endmacro()
-
# helper macro to set up a moc rule
-function(qt6_create_moc_command infile outfile moc_flags moc_options moc_target moc_depends)
+function(_qt_internal_create_moc_command infile outfile moc_flags moc_options
+ moc_target moc_depends out_json_file)
# Pass the parameters in a file. Set the working directory to
# be that containing the parameters file and reference it by
# just the file name. This is necessary because the moc tool on
@@ -117,42 +88,69 @@ function(qt6_create_moc_command infile outfile moc_flags moc_options moc_target
endif()
set (_moc_parameters_file ${outfile}_parameters)
set (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}")
- string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}")
+ if(out_json_file)
+ list(APPEND _moc_parameters --output-json)
+ set(extra_output_files "${outfile}.json")
+ set(${out_json_file} "${extra_output_files}" PARENT_SCOPE)
+ endif()
if(moc_target)
- set(_moc_parameters_file ${_moc_parameters_file}$<$<BOOL:$<CONFIGURATION>>:_$<CONFIGURATION>>)
+ set(_moc_parameters_file ${_moc_parameters_file}$<$<BOOL:$<CONFIG>>:_$<CONFIG>>)
set(targetincludes "$<TARGET_PROPERTY:${moc_target},INCLUDE_DIRECTORIES>")
set(targetdefines "$<TARGET_PROPERTY:${moc_target},COMPILE_DEFINITIONS>")
- set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},\n-I>\n>")
- set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},\n-D>\n>")
+ set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},;-I>>")
+ set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},;-D>>")
+ set(_moc_parameters_list_without_genex)
+ set(_moc_parameters_list_with_genex)
+ foreach(_moc_parameter ${_moc_parameters})
+ if(_moc_parameter MATCHES "\\\$<")
+ list(APPEND _moc_parameters_list_with_genex ${_moc_parameter})
+ else()
+ list(APPEND _moc_parameters_list_without_genex ${_moc_parameter})
+ endif()
+ endforeach()
+
+ string(REPLACE ">" "$<ANGLE-R>" _moc_escaped_parameters "${_moc_parameters_list_without_genex}")
+ string(REPLACE "," "$<COMMA>" _moc_escaped_parameters "${_moc_escaped_parameters}")
+ string(REPLACE ";" "$<SEMICOLON>" _moc_escaped_parameters "${_moc_escaped_parameters}")
+ set(concatenated "$<$<BOOL:${targetincludes}>:${targetincludes};>$<$<BOOL:${targetdefines}>:${targetdefines};>$<$<BOOL:${_moc_escaped_parameters}>:${_moc_escaped_parameters};>")
+
+ list(APPEND concatenated ${_moc_parameters_list_with_genex})
+ set(concatenated "$<FILTER:$<REMOVE_DUPLICATES:${concatenated}>,EXCLUDE,^-[DI]$>")
+ set(concatenated "$<JOIN:${concatenated},\n>")
file (GENERATE
OUTPUT ${_moc_parameters_file}
- CONTENT "${targetdefines}${targetincludes}${_moc_parameters}\n"
+ CONTENT "${concatenated}"
)
+ set(concatenated)
set(targetincludes)
set(targetdefines)
else()
+ string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}")
file(WRITE ${_moc_parameters_file} "${_moc_parameters}\n")
endif()
set(_moc_extra_parameters_file @${_moc_parameters_file})
- add_custom_command(OUTPUT ${outfile}
+ add_custom_command(OUTPUT ${outfile} ${extra_output_files}
COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::moc ${_moc_extra_parameters_file}
DEPENDS ${infile} ${moc_depends}
${_moc_working_dir}
VERBATIM)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTOMOC ON)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
+ set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON
+ SKIP_AUTOUIC ON
+ )
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.27")
+ set_source_files_properties(${outfile} PROPERTIES SKIP_LINTING ON)
+ endif()
endfunction()
-
function(qt6_generate_moc infile outfile )
# get include dirs and flags
- qt6_get_moc_flags(moc_flags)
+ _qt_internal_get_moc_flags(moc_flags)
get_filename_component(abs_infile ${infile} ABSOLUTE)
set(_outfile "${outfile}")
if(NOT IS_ABSOLUTE "${outfile}")
@@ -161,7 +159,10 @@ function(qt6_generate_moc infile outfile )
if ("x${ARGV2}" STREQUAL "xTARGET")
set(moc_target ${ARGV3})
endif()
- qt6_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "")
+ _qt_internal_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}"
+ "" # moc_depends
+ "" # out_json_file
+ )
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
@@ -179,10 +180,13 @@ endif()
function(qt6_wrap_cpp outfiles )
# get include dirs
- qt6_get_moc_flags(moc_flags)
+ _qt_internal_get_moc_flags(moc_flags)
set(options)
- set(oneValueArgs TARGET)
+ set(oneValueArgs
+ TARGET
+ __QT_INTERNAL_OUTPUT_MOC_JSON_FILES
+ )
set(multiValueArgs OPTIONS DEPENDS)
cmake_parse_arguments(_WRAP_CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -192,13 +196,76 @@ function(qt6_wrap_cpp outfiles )
set(moc_target ${_WRAP_CPP_TARGET})
set(moc_depends ${_WRAP_CPP_DEPENDS})
+ set(metatypes_json_list "")
+
foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE)
- qt6_make_output_file(${it} moc_ cpp outfile)
- qt6_create_moc_command(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}" "${moc_depends}")
+ get_filename_component(it_ext ${it} EXT)
+ # remove the dot
+ string(SUBSTRING ${it_ext} 1 -1 it_ext)
+ set(HEADER_REGEX "(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$")
+
+ if(it_ext MATCHES "${HEADER_REGEX}")
+ _qt_internal_make_output_file("${it}" moc_ cpp outfile)
+ set(is_header_file TRUE)
+ else()
+ set(found_source_extension FALSE)
+ foreach(LANG C CXX OBJC OBJCXX CUDA)
+ list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${it_ext}"
+ index)
+ if(${index} GREATER -1)
+ set(found_extension TRUE)
+ break()
+ endif()
+ endforeach()
+ if(found_extension)
+ if(TARGET ${moc_target})
+ _qt_internal_make_output_file(${it} "" moc outfile)
+ target_sources(${moc_target} PRIVATE "${outfile}")
+ target_include_directories("${moc_target}" PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}")
+ else()
+ if("${moc_target}" STREQUAL "")
+ string(JOIN "" err_msg
+ "qt6_wrap_cpp: TARGET parameter is empty. "
+ "Since the file ${it} is a source file, "
+ "the TARGET option must be specified.")
+ else()
+ string(JOIN "" err_msg
+ "qt6_wrap_cpp: TARGET \"${moc_target}\" "
+ "not found.")
+ endif()
+ message(FATAL_ERROR "${err_msg}")
+ endif()
+ else()
+ string(JOIN "" err_msg "qt6_wrap_cpp: Unknown file extension: "
+ "\"\.${it_ext}\".")
+ message(FATAL_ERROR "${err_msg}")
+ endif()
+ endif()
+
+ set(out_json_file_var "")
+ if(_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES)
+ set(out_json_file_var "out_json_file")
+ endif()
+
+ _qt_internal_create_moc_command(
+ ${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}" "${moc_depends}"
+ "${out_json_file_var}")
list(APPEND ${outfiles} ${outfile})
+ if(_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES)
+ list(APPEND metatypes_json_list "${${out_json_file_var}}")
+ endif()
endforeach()
- set(${outfiles} ${${outfiles}} PARENT_SCOPE)
+
+ if(is_header_file)
+ set(${outfiles} "${${outfiles}}" PARENT_SCOPE)
+ endif()
+
+ if(metatypes_json_list)
+ set(${_WRAP_CPP___QT_INTERNAL_OUTPUT_MOC_JSON_FILES}
+ "${metatypes_json_list}" PARENT_SCOPE)
+ endif()
endfunction()
# This will override the CMake upstream command, because that one is for Qt 3.
@@ -235,7 +302,7 @@ function(_qt6_parse_qrc_file infile _out_depends _rc_depends)
# Since this cmake macro is doing the dependency scanning for these files,
# let's make a configured file and add it as a dependency so cmake is run
# again when dependencies need to be recomputed.
- qt6_make_output_file("${infile}" "" "qrc.depends" out_depends)
+ _qt_internal_make_output_file("${infile}" "" "qrc.depends" out_depends)
configure_file("${infile}" "${out_depends}" COPYONLY)
else()
# The .qrc file does not exist (yet). Let's add a dependency and hope
@@ -262,6 +329,10 @@ function(qt6_add_binary_resources target )
set(rcc_options ${_RCC_OPTIONS})
set(rcc_destination ${_RCC_DESTINATION})
+ if(NOT QT_FEATURE_zstd)
+ list(APPEND rcc_options "--no-zstd")
+ endif()
+
if(NOT rcc_destination)
set(rcc_destination ${CMAKE_CURRENT_BINARY_DIR}/${target}.rcc)
endif()
@@ -308,7 +379,7 @@ endif()
function(qt6_add_resources outfiles )
if (TARGET ${outfiles})
cmake_parse_arguments(arg "" "OUTPUT_TARGETS" "" ${ARGN})
- qt6_process_resource(${ARGV})
+ _qt_internal_process_resource(${ARGV})
if (arg_OUTPUT_TARGETS)
set(${arg_OUTPUT_TARGETS} ${${arg_OUTPUT_TARGETS}} PARENT_SCOPE)
endif()
@@ -326,6 +397,10 @@ function(qt6_add_resources outfiles )
message(WARNING "Use qt6_add_binary_resources for binary option")
endif()
+ if(NOT QT_FEATURE_zstd)
+ list(APPEND rcc_options "--no-zstd")
+ endif()
+
foreach(it ${rcc_files})
get_filename_component(outfilename ${it} NAME_WE)
get_filename_component(infile ${it} ABSOLUTE)
@@ -340,8 +415,11 @@ function(qt6_add_resources outfiles )
MAIN_DEPENDENCY ${infile}
DEPENDS ${_rc_depends} "${_out_depends}" ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
VERBATIM)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
+ set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON
+ SKIP_AUTOUIC ON
+ SKIP_UNITY_BUILD_INCLUSION ON
+ SKIP_PRECOMPILE_HEADERS ON
+ )
list(APPEND ${outfiles} ${outfile})
endforeach()
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
@@ -355,7 +433,12 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
qt6_add_resources("${outfiles}" ${ARGN})
endif()
- if(NOT TARGET ${outfiles})
+ if(TARGET ${outfiles})
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "OUTPUT_TARGETS" "")
+ if (arg_OUTPUT_TARGETS)
+ set(${arg_OUTPUT_TARGETS} ${${arg_OUTPUT_TARGETS}} PARENT_SCOPE)
+ endif()
+ else()
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
endif()
endfunction()
@@ -365,6 +448,18 @@ endif()
# qt6_add_big_resources(outfiles inputfile ... )
function(qt6_add_big_resources outfiles )
+ if(CMAKE_GENERATOR STREQUAL "Xcode" AND IOS)
+ message(WARNING
+ "Due to CMake limitations, qt6_add_big_resources can't be used when building for iOS. "
+ "See https://bugreports.qt.io/browse/QTBUG-103497 for details. "
+ "Falling back to using qt6_add_resources. "
+ "Consider using qt6_add_resources directly to silence this warning."
+ )
+ qt6_add_resources(${ARGV})
+ set(${outfiles} ${${outfiles}} PARENT_SCOPE)
+ return()
+ endif()
+
if (CMAKE_VERSION VERSION_LESS 3.9)
message(FATAL_ERROR, "qt6_add_big_resources requires CMake 3.9 or newer")
endif()
@@ -382,35 +477,89 @@ function(qt6_add_big_resources outfiles )
message(WARNING "Use qt6_add_binary_resources for binary option")
endif()
+ if(NOT QT_FEATURE_zstd)
+ list(APPEND rcc_options "--no-zstd")
+ endif()
+
foreach(it ${rcc_files})
get_filename_component(outfilename ${it} NAME_WE)
+
+ # Provide unique targets and output file names
+ # in case we add multiple .qrc files with the same base name.
+ string(MAKE_C_IDENTIFIER "_qt_big_resource_count_${outfilename}" prop)
+ get_property(count GLOBAL PROPERTY ${prop})
+ if(count)
+ string(APPEND outfilename "_${count}")
+ else()
+ set(count 0)
+ endif()
+ math(EXPR count "${count} + 1")
+ set_property(GLOBAL PROPERTY ${prop} ${count})
+
get_filename_component(infile ${it} ABSOLUTE)
set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp)
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o)
_qt6_parse_qrc_file(${infile} _out_depends _rc_depends)
- set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
+ set_source_files_properties(${infile} PROPERTIES SKIP_AUTOGEN ON)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.27")
+ set_source_files_properties(${tmpoutfile} PROPERTIES SKIP_LINTING ON)
+ endif()
add_custom_command(OUTPUT ${tmpoutfile}
COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::rcc ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile}
DEPENDS ${infile} ${_rc_depends} "${out_depends}" ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
+ COMMENT "Running rcc pass 1 for resource ${outfilename}"
VERBATIM)
add_custom_target(big_resources_${outfilename} ALL DEPENDS ${tmpoutfile})
- add_library(rcc_object_${outfilename} OBJECT ${tmpoutfile})
- set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOMOC OFF)
- set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOUIC OFF)
+ _qt_internal_add_rcc_pass2(
+ RESOURCE_NAME ${outfilename}
+ RCC_OPTIONS ${rcc_options}
+ OBJECT_LIB rcc_object_${outfilename}
+ QRC_FILE ${infile}
+ PASS1_OUTPUT_FILE ${tmpoutfile}
+ OUT_OBJECT_FILE ${outfile}
+ )
add_dependencies(rcc_object_${outfilename} big_resources_${outfilename})
- # The modification of TARGET_OBJECTS needs the following change in cmake
- # https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f
- add_custom_command(OUTPUT ${outfile}
- COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
- ARGS ${rcc_options} --name ${outfilename} --pass 2 --temp $<TARGET_OBJECTS:rcc_object_${outfilename}> --output ${outfile} ${infile}
- DEPENDS rcc_object_${outfilename} ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
- VERBATIM)
- list(APPEND ${outfiles} ${outfile})
+ list(APPEND ${outfiles} ${outfile})
endforeach()
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
endfunction()
+function(_qt_internal_add_rcc_pass2)
+ set(options)
+ set(oneValueArgs
+ RESOURCE_NAME
+ OBJECT_LIB
+ QRC_FILE
+ PASS1_OUTPUT_FILE
+ OUT_OBJECT_FILE
+ )
+ set(multiValueArgs
+ RCC_OPTIONS
+ )
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ add_library(${arg_OBJECT_LIB} OBJECT ${arg_PASS1_OUTPUT_FILE})
+ _qt_internal_set_up_static_runtime_library(${arg_OBJECT_LIB})
+ target_compile_definitions(${arg_OBJECT_LIB} PUBLIC
+ "$<TARGET_PROPERTY:Qt6::Core,INTERFACE_COMPILE_DEFINITIONS>")
+ set_target_properties(${arg_OBJECT_LIB} PROPERTIES
+ AUTOMOC OFF
+ AUTOUIC OFF)
+ # The modification of TARGET_OBJECTS needs the following change in cmake
+ # https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f
+ add_custom_command(
+ OUTPUT ${arg_OUT_OBJECT_FILE}
+ COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
+ ${arg_RCC_OPTIONS} --name ${arg_RESOURCE_NAME} --pass 2
+ --temp $<TARGET_OBJECTS:${arg_OBJECT_LIB}>
+ --output ${arg_OUT_OBJECT_FILE} ${arg_QRC_FILE}
+ DEPENDS ${arg_OBJECT_LIB} $<TARGET_OBJECTS:${arg_OBJECT_LIB}>
+ ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
+ COMMENT "Running rcc pass 2 for resource ${arg_RESOURCE_NAME}"
+ VERBATIM)
+endfunction()
+
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
function(qt_add_big_resources outfiles)
if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
@@ -422,10 +571,94 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
+function(_qt_internal_apply_win_prefix_and_suffix target)
+ if(WIN32)
+ # Table of prefix / suffixes for MSVC libraries as qmake expects them to be created.
+ # static - Qt6EdidSupport.lib (platform support libraries / or static QtCore, etc)
+ # shared - Qt6Core.dll
+ # shared import library - Qt6Core.lib
+ # module aka Qt plugin - qwindows.dll
+ # module import library - qwindows.lib
+ #
+ # The CMake defaults are fine for us.
+
+ # Table of prefix / suffixes for MinGW libraries as qmake expects them to be created.
+ # static - libQt6EdidSupport.a (platform support libraries / or static QtCore, etc)
+ # shared - Qt6Core.dll
+ # shared import library - libQt6Core.a
+ # module aka Qt plugin - qwindows.dll
+ # module import library - libqwindows.a
+ #
+ # CMake for Windows-GNU platforms defaults the prefix to "lib".
+ # CMake for Windows-GNU platforms defaults the import suffix to ".dll.a".
+ # These CMake defaults are not ok for us.
+
+ # This should cover both MINGW with GCC and CLANG.
+ if(NOT MSVC)
+ set_property(TARGET "${target}" PROPERTY IMPORT_SUFFIX ".a")
+
+ get_target_property(target_type ${target} TYPE)
+ if(target_type STREQUAL "STATIC_LIBRARY")
+ set_property(TARGET "${target}" PROPERTY PREFIX "lib")
+ else()
+ set_property(TARGET "${target}" PROPERTY PREFIX "")
+ set_property(TARGET "${target}" PROPERTY IMPORT_PREFIX "lib")
+ endif()
+ endif()
+ endif()
+endfunction()
+
set(_Qt6_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
-function(add_qt_gui_executable target)
+# Wrapper function that adds an executable with some Qt specific behavior.
+# Some scenarios require steps to be deferred to the end of the current
+# directory scope so that the caller has an opportunity to modify certain
+# target properties.
+function(qt6_add_executable target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "MANUAL_FINALIZATION" "" "")
+
+ _qt_internal_warn_about_example_add_subdirectory()
+
+ _qt_internal_create_executable("${target}" ${arg_UNPARSED_ARGUMENTS})
+ target_link_libraries("${target}" PRIVATE Qt6::Core)
+ set_property(TARGET ${target} PROPERTY _qt_expects_finalization TRUE)
+
+ if(arg_MANUAL_FINALIZATION)
+ # Caller says they will call qt6_finalize_target() themselves later
+ return()
+ endif()
+
+ # Defer the finalization if we can. When the caller's project requires
+ # CMake 3.19 or later, this makes the calls to this function concise while
+ # still allowing target property modification before finalization.
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
+ # Need to wrap in an EVAL CODE or else ${target} won't be evaluated
+ # due to special behavior of cmake_language() argument handling
+ cmake_language(EVAL CODE "cmake_language(DEFER CALL qt6_finalize_target ${target})")
+ else()
+ set_target_properties("${target}" PROPERTIES _qt_is_immediately_finalized TRUE)
+ qt6_finalize_target("${target}")
+ endif()
+endfunction()
+
+# Just like for qt_add_resources, we should disable zstd compression when cross-compiling to a
+# target that doesn't support zstd decompression, even if the host tool supports it.
+# Allow an opt out via a QT_NO_AUTORCC_ZSTD variable.
+function(_qt_internal_disable_autorcc_zstd_when_not_supported target)
+ if(TARGET "${target}"
+ AND DEFINED QT_FEATURE_zstd
+ AND NOT QT_FEATURE_zstd
+ AND NOT QT_NO_AUTORCC_ZSTD)
+ get_target_property(target_type ${target} TYPE)
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set_property(TARGET "${target}" APPEND PROPERTY AUTORCC_OPTIONS "--no-zstd")
+ endif()
+ endif()
+endfunction()
+
+function(_qt_internal_create_executable target)
if(ANDROID)
+ list(REMOVE_ITEM ARGN "WIN32" "MACOSX_BUNDLE")
add_library("${target}" MODULE ${ARGN})
# On our qmake builds we do don't compile the executables with
# visibility=hidden. Not having this flag set will cause the
@@ -435,25 +668,278 @@ function(add_qt_gui_executable target)
set_property(TARGET "${target}" PROPERTY CXX_VISIBILITY_PRESET default)
set_property(TARGET "${target}" PROPERTY OBJC_VISIBILITY_PRESET default)
set_property(TARGET "${target}" PROPERTY OBJCXX_VISIBILITY_PRESET default)
- qt_android_apply_arch_suffix("${target}")
+ set_property(TARGET "${target}"
+ PROPERTY _qt_android_apply_arch_suffix_called_from_qt_impl TRUE)
+ qt6_android_apply_arch_suffix("${target}")
+ set_property(TARGET "${target}" PROPERTY _qt_is_android_executable TRUE)
else()
- add_executable("${target}" WIN32 MACOSX_BUNDLE ${ARGN})
+ add_executable("${target}" ${ARGN})
endif()
- target_link_libraries("${target}" PRIVATE Qt::Core)
- if(TARGET Qt::Gui)
- target_link_libraries("${target}" PRIVATE Qt::Gui)
+
+ _qt_internal_disable_autorcc_zstd_when_not_supported("${target}")
+ _qt_internal_set_up_static_runtime_library("${target}")
+endfunction()
+
+function(_qt_internal_finalize_executable target)
+ # We can't evaluate generator expressions at configure time, so we can't
+ # ask for any transitive properties or even the full library dependency
+ # chain.
+ # We can still look at the immediate dependencies
+ # (and recursively their dependencies) and query
+ # any that are not expressed as generator expressions. For any we can
+ # identify as a CMake target known to the current scope, we can check if
+ # that target has a finalizer to be called. This is expected to cover the
+ # vast majority of use cases, since projects will typically link directly
+ # to Qt::* targets. For the cases where this isn't so, the project will be
+ # responsible for calling any relevant functions themselves instead of
+ # relying on these automatic finalization calls.
+ set(finalizers)
+
+ __qt_internal_collect_all_target_dependencies("${target}" dep_targets)
+
+ if(dep_targets)
+ foreach(dep IN LISTS dep_targets)
+ get_target_property(dep_finalizers ${dep}
+ INTERFACE_QT_EXECUTABLE_FINALIZERS
+ )
+ if(dep_finalizers)
+ list(APPEND finalizers ${dep_finalizers})
+ endif()
+ endforeach()
+ list(REMOVE_DUPLICATES finalizers)
endif()
- if (WIN32)
- qt6_generate_win32_rc_file(${target})
+ if(finalizers)
+ if(CMAKE_VERSION VERSION_LESS 3.18)
+ # cmake_language() not available, fall back to the slower method of
+ # writing a file and including it
+ set(contents "")
+ foreach(finalizer_func IN LISTS finalizers)
+ string(APPEND contents "${finalizer_func}(${target})\n")
+ endforeach()
+ set(finalizer_file "${CMAKE_CURRENT_BINARY_DIR}/.qt/finalize_${target}.cmake")
+ file(WRITE ${finalizer_file} "${contents}")
+ include(${finalizer_file})
+ else()
+ foreach(finalizer_func IN LISTS finalizers)
+ cmake_language(CALL ${finalizer_func} ${target})
+ endforeach()
+ endif()
endif()
- if(ANDROID)
- qt_android_generate_deployment_settings("${target}")
- qt_android_add_apk_target("${target}")
+ if(EMSCRIPTEN)
+ _qt_internal_wasm_add_target_helpers("${target}")
+ _qt_internal_add_wasm_extra_exported_methods("${target}")
+ _qt_internal_set_wasm_export_name("${target}")
+ endif()
+
+ if(APPLE)
+ if(NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ # macOS
+ _qt_internal_finalize_macos_app("${target}")
+ else()
+ _qt_internal_finalize_uikit_app("${target}")
+ endif()
+ endif()
+
+ # For finalizer mode of plugin importing to work safely, we need to know the list of Qt
+ # dependencies the target has, but those might be added later than the qt_add_executable call.
+ # Most of our examples are like that. Only enable finalizer mode when we are sure that the user
+ # manually called qt_finalize_target at the end of their CMake project, or it was automatically
+ # done via a deferred call. This is also applicable to the resource object finalizer.
+ get_target_property(is_immediately_finalized "${target}" _qt_is_immediately_finalized)
+ if(NOT is_immediately_finalized)
+ __qt_internal_apply_plugin_imports_finalizer_mode("${target}")
+ __qt_internal_process_dependency_object_libraries("${target}")
+ endif()
+endfunction()
+
+function(_cat IN_FILE OUT_FILE)
+ file(READ ${IN_FILE} CONTENTS)
+ file(APPEND ${OUT_FILE} "${CONTENTS}\n")
+endfunction()
+
+function(_qt_internal_finalize_batch name)
+ find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Core)
+
+ set(generated_blacklist_file "${CMAKE_CURRENT_BINARY_DIR}/BLACKLIST")
+ get_target_property(blacklist_files "${name}" _qt_blacklist_files)
+ file(WRITE "${generated_blacklist_file}" "")
+ foreach(blacklist_file ${blacklist_files})
+ _cat("${blacklist_file}" "${generated_blacklist_file}")
+ endforeach()
+ qt_internal_add_resource(${name} "batch_blacklist"
+ PREFIX "/"
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/BLACKLIST"
+ BASE ${CMAKE_CURRENT_BINARY_DIR})
+endfunction()
+
+# If a task needs to run before any targets are finalized in the current directory
+# scope, call this function and pass the ID of that task as the argument.
+function(_qt_internal_delay_finalization_until_after defer_id)
+ set_property(DIRECTORY APPEND PROPERTY qt_internal_finalizers_wait_for_ids "${defer_id}")
+endfunction()
+
+function(qt6_finalize_target target)
+ set_property(TARGET ${target} PROPERTY _qt_expects_finalization FALSE)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ cmake_language(DEFER GET_CALL_IDS ids_queued)
+ get_directory_property(wait_for_ids qt_internal_finalizers_wait_for_ids)
+ while(wait_for_ids)
+ list(GET wait_for_ids 0 id_to_wait_for)
+ if(id_to_wait_for IN_LIST ids_queued)
+ # Something else needs to run before we finalize targets.
+ # Try again later by re-deferring ourselves, which effectively
+ # puts us at the end of the current list of deferred actions.
+ cmake_language(EVAL CODE "cmake_language(DEFER CALL ${CMAKE_CURRENT_FUNCTION} ${ARGV})")
+ set_directory_properties(PROPERTIES
+ qt_internal_finalizers_wait_for_ids "${wait_for_ids}"
+ )
+ return()
+ endif()
+ list(POP_FRONT wait_for_ids)
+ endwhile()
+ # No other deferred tasks to wait for
+ set_directory_properties(PROPERTIES qt_internal_finalizers_wait_for_ids "")
+ endif()
+
+ if(NOT TARGET "${target}")
+ message(FATAL_ERROR "No target '${target}' found in current scope.")
+ endif()
+
+ get_target_property(is_finalized "${target}" _qt_is_finalized)
+ if(is_finalized)
+ message(AUTHOR_WARNING
+ "Tried to call qt6_finalize_target twice on target '${target}'. "
+ "Did you forget to specify MANUAL_FINALIZATION to qt6_add_executable, "
+ "qt6_add_library or qt6_add_plugin?")
+ return()
+ endif()
+
+ _qt_internal_expose_deferred_files_to_ide(${target})
+ _qt_internal_finalize_source_groups(${target})
+ get_target_property(target_type ${target} TYPE)
+ get_target_property(is_android_executable "${target}" _qt_is_android_executable)
+
+ if(target_type STREQUAL "EXECUTABLE" OR is_android_executable)
+ _qt_internal_finalize_executable(${ARGV})
+ endif()
+
+ if(APPLE)
+ # Tell CMake to generate run-scheme for the executable when generating
+ # Xcode projects. This avoids Xcode auto-generating default schemes for
+ # all targets, which includes internal and build-only targets.
+ get_target_property(generate_scheme "${target}" XCODE_GENERATE_SCHEME)
+ if(generate_scheme MATCHES "-NOTFOUND" AND (
+ target_type STREQUAL "EXECUTABLE" OR
+ target_type STREQUAL "SHARED_LIBRARY" OR
+ target_type STREQUAL "STATIC_LIBRARY" OR
+ target_type STREQUAL "MODULE_LIBRARY"))
+ set_property(TARGET "${target}" PROPERTY XCODE_GENERATE_SCHEME TRUE)
+ endif()
+ endif()
+
+ if(target_type STREQUAL "SHARED_LIBRARY" OR
+ target_type STREQUAL "STATIC_LIBRARY" OR
+ target_type STREQUAL "MODULE_LIBRARY" OR
+ target_type STREQUAL "OBJECT_LIBRARY")
+ get_target_property(is_immediately_finalized "${target}" _qt_is_immediately_finalized)
+ get_target_property(uses_automoc ${target} AUTOMOC)
+ if(uses_automoc AND NOT is_immediately_finalized)
+ qt6_extract_metatypes(${target})
+ endif()
+ endif()
+
+ set_target_properties(${target} PROPERTIES _qt_is_finalized TRUE)
+endfunction()
+
+function(_qt_internal_finalize_source_groups target)
+ if(NOT ("${CMAKE_GENERATOR}" STREQUAL "Xcode"
+ OR "${CMAKE_GENERATOR}" MATCHES "^Visual Studio"))
+ return()
endif()
+
+ get_target_property(sources ${target} SOURCES)
+ if(NOT sources)
+ return()
+ endif()
+
+ get_target_property(source_dir ${target} SOURCE_DIR)
+ get_target_property(binary_dir ${target} BINARY_DIR)
+
+ get_property(generated_source_group GLOBAL PROPERTY AUTOGEN_SOURCE_GROUP)
+ if(NOT generated_source_group)
+ set(generated_source_group "Source Files/Generated")
+ endif()
+
+ foreach(source IN LISTS sources)
+ string(GENEX_STRIP "${source}" source)
+
+ if(IS_ABSOLUTE ${source})
+ set(source_file_path "${source}")
+ else()
+ # Resolve absolute path. Can't use LOCATION, as that
+ # will error out if the file doesn't exist :(
+ get_filename_component(source_file_path "${source}"
+ ABSOLUTE BASE_DIR "${source_dir}")
+ if(NOT EXISTS ${source_file_path})
+ # Likely generated file, will end up in build dir
+ get_filename_component(source_file_path "${source}"
+ ABSOLUTE BASE_DIR "${binary_dir}")
+ endif()
+ endif()
+
+ # Include qml files in "Source Files". Can not be done via regex,
+ # due to https://gitlab.kitware.com/cmake/cmake/-/issues/25597
+ if(${source_file_path} MATCHES "\\.qml$")
+ source_group("Source Files" FILES ${source_file_path})
+ endif()
+
+ get_source_file_property(is_generated "${source_file_path}" GENERATED)
+ if(${is_generated})
+ source_group(${generated_source_group} FILES ${source_file_path})
+ endif()
+ endforeach()
endfunction()
+function(_qt_internal_darwin_permission_finalizer target)
+ get_target_property(plist_file "${target}" MACOSX_BUNDLE_INFO_PLIST)
+ if(NOT plist_file)
+ return()
+ endif()
+ foreach(plugin_target IN LISTS QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_permissions)
+ set(versioned_plugin_target "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
+ get_target_property(usage_descriptions
+ ${versioned_plugin_target}
+ _qt_info_plist_usage_descriptions)
+ foreach(usage_description_key IN LISTS usage_descriptions)
+ execute_process(COMMAND "/usr/libexec/PlistBuddy"
+ -c "print ${usage_description_key}" "${plist_file}"
+ OUTPUT_VARIABLE usage_description
+ ERROR_VARIABLE plist_error)
+ if(usage_description AND NOT plist_error)
+ set_target_properties("${target}"
+ PROPERTIES "_qt_has_${plugin_target}_usage_description" TRUE)
+ qt6_import_plugins(${target} INCLUDE ${versioned_plugin_target})
+ endif()
+ endforeach()
+ endforeach()
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_add_executable)
+ qt6_add_executable(${ARGV})
+ endfunction()
+ function(qt_finalize_target)
+ qt6_finalize_target(${ARGV})
+ endfunction()
+
+ # Kept for compatibility with Qt Creator 4.15 wizards
+ function(qt_finalize_executable)
+ qt6_finalize_target(${ARGV})
+ endfunction()
+endif()
+
function(_qt_get_plugin_name_with_version target out_var)
string(REGEX REPLACE "^Qt::(.+)" "Qt${QT_DEFAULT_MAJOR_VERSION}::\\1"
qt_plugin_with_version "${target}")
@@ -484,31 +970,16 @@ macro(_qt_import_plugin target plugin)
endif()
endmacro()
-# This function is used to indicate which plug-ins are going to be
-# used by a given target.
-# This allows static linking to a correct set of plugins.
-# Options :
-# NO_DEFAULT: disable linking against any plug-in by default for that target, e.g. no platform plug-in.
-# INCLUDE <list of additional plug-ins to be linked against>
-# EXCLUDE <list of plug-ins to be removed from the default set>
-# INCLUDE_BY_TYPE <type> <included plugins>
-# EXCLUDE_BY_TYPE <type to be excluded>
-#
-# Example :
-# qt_import_plugins(myapp
-# INCLUDE Qt::QCocoaIntegrationPlugin
-# EXCLUDE Qt::QMinimalIntegrationPlugin
-# INCLUDE_BY_TYPE imageformats Qt::QGifPlugin Qt::QJpegPlugin
-# EXCLUDE_BY_TYPE sqldrivers
-# )
-
-# TODO : support qml plug-ins.
+function(_qt_internal_disable_static_default_plugins target)
+ set_target_properties(${target} PROPERTIES QT_DEFAULT_PLUGINS 0)
+endfunction()
+
function(qt6_import_plugins target)
cmake_parse_arguments(arg "NO_DEFAULT" "" "INCLUDE;EXCLUDE;INCLUDE_BY_TYPE;EXCLUDE_BY_TYPE" ${ARGN})
# Handle NO_DEFAULT
if(${arg_NO_DEFAULT})
- set_target_properties(${target} PROPERTIES QT_DEFAULT_PLUGINS 0)
+ _qt_internal_disable_static_default_plugins("${target}")
endif()
# Handle INCLUDE
@@ -536,10 +1007,14 @@ function(qt6_import_plugins target)
# Check if passed plugin target name is a version-less one, and make a version-full
# one.
+ set_property(TARGET "${target}" APPEND PROPERTY "QT_PLUGINS_${_current_type}" "${_arg}")
+ set_property(TARGET "${target}" APPEND PROPERTY "_qt_plugins_by_type" "${_arg}")
_qt_get_plugin_name_with_version("${_arg}" qt_plugin_with_version)
- if(TARGET "${_arg}" OR TARGET "${qt_plugin_with_version}")
- set_property(TARGET "${target}" APPEND PROPERTY "QT_PLUGINS_${_current_type}" "${_arg}")
- else()
+
+ # TODO: Do we really need this check? We didn't have it in Qt5, and plugin targets
+ # wrapped in genexes end up causing warnings, but we explicitly use GENEX_EVAL to
+ # support them.
+ if(NOT TARGET "${_arg}" AND NOT TARGET "${qt_plugin_with_version}")
message("Warning: plug-in ${_arg} is not known to the current Qt installation.")
endif()
endif()
@@ -562,26 +1037,227 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
+# This function is currently in Technical Preview. It's signature may change or be removed entirely.
+function(qt6_set_finalizer_mode target)
+ cmake_parse_arguments(arg "ENABLE;DISABLE" "" "MODES" ${ARGN})
+ if(NOT arg_ENABLE AND NOT arg_DISABLE)
+ message(FATAL_ERROR "No option was specified whether to enable or disable the modes.")
+ elseif(arg_ENABLE AND arg_DISABLE)
+ message(FATAL_ERROR "Both ENABLE and DISABLE options were specified.")
+ endif()
+ if(NOT arg_MODES)
+ message(FATAL_ERROR "No modes were specified in qt6_set_finalizer_mode() call.")
+ endif()
-# Generate Qt metatypes.json for a target. By default we check whether AUTOMOC
-# has been enabled and we extract the information from that target. Should you
-# not wish to use automoc you need to pass in all the generated json files via the
-# MANUAL_MOC_JSON_FILES parameter. The latter can be obtained by running moc with
-# the --output-json parameter.
-# Params:
-# INSTALL_DIR: Location where to install the metatypes file. For public consumption,
-# defaults to a ${CMAKE_INSTALL_PREFIX}/lib/metatypes directory.
-# Executable metatypes files are never installed.
-# COPY_OVER_INSTALL: (Qt Internal) When present will install the file via a post build step
-# copy rather than using install.
-function(qt6_generate_meta_types_json_file target)
+ if(arg_ENABLE)
+ set(value "TRUE")
+ elseif(arg_DISABLE)
+ set(value "FALSE")
+ endif()
+
+ foreach(mode ${arg_MODES})
+ __qt_internal_enable_finalizer_mode("${target}" "${mode}" "${value}")
+ endforeach()
+endfunction()
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_set_finalizer_mode)
+ qt6_set_finalizer_mode(${ARGV})
+ endfunction()
+endif()
+
+function(_qt_internal_assign_to_internal_targets_folder target)
+ get_property(folder_name GLOBAL PROPERTY QT_TARGETS_FOLDER)
+ if(NOT "${folder_name}" STREQUAL "")
+ set_property(TARGET ${target} PROPERTY FOLDER "${folder_name}")
+ endif()
+endfunction()
+
+function(_qt_internal_get_target_autogen_build_dir target out_var)
+ get_property(target_autogen_build_dir TARGET ${target} PROPERTY AUTOGEN_BUILD_DIR)
+ if(target_autogen_build_dir)
+ set(${out_var} "${target_autogen_build_dir}" PARENT_SCOPE)
+ else()
+ get_property(target_binary_dir TARGET ${target} PROPERTY BINARY_DIR)
+ set(${out_var} "${target_binary_dir}/${target}_autogen" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(_qt_internal_should_install_metatypes target)
+ set(args_option
+ INTERNAL_INSTALL
+ )
+ set(args_single
+ OUT_VAR
+ )
+ set(args_multi
+ )
+
+ cmake_parse_arguments(arg
+ "${args_option}"
+ "${args_single}"
+ "${args_multi}" ${ARGN})
+
+ # Check whether the generated json file needs to be installed.
+ # Executable metatypes.json files should not be installed. Qt non-prefix builds should also
+ # not install the files.
+ set(should_install FALSE)
+
+ get_target_property(target_type ${target} TYPE)
+ if(NOT target_type STREQUAL "EXECUTABLE" AND arg_INTERNAL_INSTALL)
+ set(should_install TRUE)
+ endif()
+ set(${arg_OUT_VAR} "${should_install}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_get_metatypes_install_dir internal_install_dir arch_data_dir out_var)
+ # Automatically fill default install args when not specified.
+ if(NOT internal_install_dir)
+ # INSTALL_ARCHDATADIR is not set when QtBuildInternals is not loaded
+ # (when not doing a Qt build). Default to a hardcoded location for user
+ # projects (will likely be wrong).
+ if(arch_data_dir)
+ set(install_dir "${arch_data_dir}/metatypes")
+ else()
+ set(install_dir "lib/metatypes")
+ endif()
+ else()
+ set(install_dir "${internal_install_dir}")
+ endif()
+ set(${out_var} "${install_dir}" PARENT_SCOPE)
+endfunction()
+
+# Propagates the build time metatypes file via INTERFACE_SOURCES (using $<BUILD_INTERFACE>)
+# and saves the path and file name in properties, so that they can be queryied in the qml api
+# implementation for the purpose of duplicating a qml module backing library's metatypes in its
+# associated plugin. This is required for qmltyperegistrar to get the full set of foreign types
+# when projects link to the plugin and not the backing library.
+function(_qt_internal_assign_build_metatypes_files_and_properties target)
get_target_property(existing_meta_types_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
if (existing_meta_types_file)
return()
endif()
- cmake_parse_arguments(arg "COPY_OVER_INSTALL" "INSTALL_DIR" "MANUAL_MOC_JSON_FILES" ${ARGN})
+ set(args_option
+ )
+ set(args_single
+ METATYPES_FILE_NAME
+ METATYPES_FILE_PATH
+ )
+ set(args_multi
+ )
+
+ cmake_parse_arguments(arg
+ "${args_option}"
+ "${args_single}"
+ "${args_multi}" ${ARGN})
+
+ if(NOT arg_METATYPES_FILE_NAME)
+ message(FATAL_ERROR "METATYPES_FILE_NAME must be specified")
+ endif()
+
+ if(NOT arg_METATYPES_FILE_PATH)
+ message(FATAL_ERROR "METATYPES_FILE_PATH must be specified")
+ endif()
+
+ set(metatypes_file_name "${arg_METATYPES_FILE_NAME}")
+ set(metatypes_file_path "${arg_METATYPES_FILE_PATH}")
+
+ # Set up consumption of files via INTERFACE_SOURCES.
+ set(consumes_metatypes "$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>")
+ set(metatypes_file_genex_build
+ "$<BUILD_INTERFACE:$<${consumes_metatypes}:${metatypes_file_path}>>"
+ )
+ target_sources(${target} INTERFACE ${metatypes_file_genex_build})
+
+ set_target_properties(${target} PROPERTIES
+ INTERFACE_QT_MODULE_HAS_META_TYPES YES
+ # The property name is a bit misleading, it's not wrapped in a genex.
+ INTERFACE_QT_META_TYPES_BUILD_FILE "${metatypes_file_path}"
+ INTERFACE_QT_META_TYPES_FILE_NAME "${metatypes_file_name}"
+ )
+endfunction()
+
+# Same as above, but with $<INSTALL_INTERFACE>.
+function(_qt_internal_assign_install_metatypes_files_and_properties target)
+ get_target_property(existing_meta_types_file ${target} INTERFACE_QT_META_TYPES_INSTALL_FILE)
+ if (existing_meta_types_file)
+ return()
+ endif()
+
+ set(args_option
+ )
+ set(args_single
+ INSTALL_DIR
+ )
+ set(args_multi
+ )
+
+ cmake_parse_arguments(arg
+ "${args_option}"
+ "${args_single}"
+ "${args_multi}" ${ARGN})
+
+
+ get_target_property(metatypes_file_name "${target}" INTERFACE_QT_META_TYPES_FILE_NAME)
+
+ if(NOT metatypes_file_name)
+ message(FATAL_ERROR "INTERFACE_QT_META_TYPES_FILE_NAME of target ${target} is empty")
+ endif()
+
+ if(NOT arg_INSTALL_DIR)
+ message(FATAL_ERROR "INSTALL_DIR must be specified")
+ endif()
+
+ # Set up consumption of files via INTERFACE_SOURCES.
+ set(consumes_metatypes "$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>")
+
+ set(install_dir "${arg_INSTALL_DIR}")
+
+ set(metatypes_file_install_path "${install_dir}/${metatypes_file_name}")
+ set(metatypes_file_install_path_genex "$<INSTALL_PREFIX>/${metatypes_file_install_path}")
+ set(metatypes_file_genex_install
+ "$<INSTALL_INTERFACE:$<${consumes_metatypes}:${metatypes_file_install_path_genex}>>"
+ )
+ target_sources(${target} INTERFACE ${metatypes_file_genex_install})
+
+ set_target_properties(${target} PROPERTIES
+ INTERFACE_QT_META_TYPES_INSTALL_FILE "${metatypes_file_install_path}"
+ )
+endfunction()
+
+
+function(qt6_extract_metatypes target)
+
+ get_target_property(existing_meta_types_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
+ if (existing_meta_types_file)
+ return()
+ endif()
+
+ set(args_option
+ # TODO: Move this into a separate internal function, so it doesn't pollute the public one.
+ # When given, metatypes files will be installed into the default Qt
+ # metatypes folder. Only to be used by the Qt build.
+ __QT_INTERNAL_INSTALL
+ )
+ set(args_single
+ # TODO: Move this into a separate internal function, so it doesn't pollute the public one.
+ # Location where to install the metatypes file. Only used if
+ # __QT_INTERNAL_INSTALL is given. It defaults to the
+ # ${CMAKE_INSTALL_PREFIX}/${INSTALL_ARCHDATADIR}/metatypes directory.
+ # Executable metatypes files are never installed.
+ __QT_INTERNAL_INSTALL_DIR
+
+ OUTPUT_FILES
+ )
+ set(args_multi
+ MANUAL_MOC_JSON_FILES
+ )
+
+ cmake_parse_arguments(arg
+ "${args_option}"
+ "${args_single}"
+ "${args_multi}" ${ARGN})
get_target_property(target_type ${target} TYPE)
if (target_type STREQUAL "INTERFACE_LIBRARY")
@@ -594,23 +1270,13 @@ function(qt6_generate_meta_types_json_file target)
return()
endif()
- # Whether the generated json file needs to be installed for prefix-builds, or copied for
- # non-prefix builds. Regardless of the type of build, executable metatypes.json files should
- # not be installed. Only library .json files should be installed.
- set(should_install "TRUE")
- if (target_type STREQUAL "EXECUTABLE")
- set(should_install "FALSE")
- endif()
-
- # Automatically fill default install args when not specified.
- if (NOT arg_INSTALL_DIR)
- set(arg_INSTALL_DIR "lib/metatypes")
- endif()
-
get_target_property(target_binary_dir ${target} BINARY_DIR)
set(type_list_file "${target_binary_dir}/meta_types/${target}_json_file_list.txt")
set(type_list_file_manual "${target_binary_dir}/meta_types/${target}_json_file_list_manual.txt")
+ set(target_autogen_build_dir "")
+ _qt_internal_get_target_autogen_build_dir(${target} target_autogen_build_dir)
+
get_target_property(uses_automoc ${target} AUTOMOC)
set(automoc_args)
set(automoc_dependencies)
@@ -621,17 +1287,18 @@ function(qt6_generate_meta_types_json_file target)
AUTOMOC_MOC_OPTIONS "--output-json"
)
- if(NOT CMAKE_CONFIGURATION_TYPES)
+ get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(NOT is_multi_config)
set(cmake_autogen_cache_file
"${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache.txt")
- set(mutli_config_args
- --cmake-autogen-include-dir-path "${target_binary_dir}/${target}_autogen/include"
+ set(multi_config_args
+ --cmake-autogen-include-dir-path "${target_autogen_build_dir}/include"
)
else()
set(cmake_autogen_cache_file
"${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache_$<CONFIG>.txt")
- set(mutli_config_args
- --cmake-autogen-include-dir-path "${target_binary_dir}/${target}_autogen/include_$<CONFIG>"
+ set(multi_config_args
+ --cmake-autogen-include-dir-path "${target_autogen_build_dir}/include_$<CONFIG>"
"--cmake-multi-config")
endif()
@@ -640,41 +1307,92 @@ function(qt6_generate_meta_types_json_file target)
set (use_dep_files FALSE)
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.17") # Requires automoc changes present only in 3.17
- if(CMAKE_GENERATOR STREQUAL "Ninja" OR CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
- set(use_dep_files TRUE)
+ if(CMAKE_GENERATOR STREQUAL "Ninja" OR
+ CMAKE_GENERATOR STREQUAL "Ninja Multi-Config" OR
+ (CMAKE_GENERATOR MATCHES "Makefiles" AND
+ CMAKE_VERSION VERSION_GREATER_EQUAL "3.28"))
+ if(DEFINED QT_USE_CMAKE_DEPFILES)
+ set(use_dep_files ${QT_USE_CMAKE_DEPFILES})
+ else()
+ set(use_dep_files TRUE)
+ endif()
endif()
endif()
+ set(cmake_automoc_parser_timestamp "${type_list_file}.timestamp")
+
if (NOT use_dep_files)
+ # When a project is configured with a Visual Studio generator, CMake's
+ # cmQtAutoGenInitializer::InitAutogenTarget() can take one of two code paths on how to
+ # handle AUTOMOC rules.
+ # It either creates a ${target}_autogen custom target or uses PRE_BUILD build events.
+ #
+ # The latter in considered an optimization and is used by CMake when possible.
+ # Unfortunately that breaks our add_dependency call because we expect on _autogen target
+ # to always exist.
+ #
+ # Ensure the PRE_BUILD path is not taken by generating a dummy header file and adding it
+ # as a source file to the target. This causes the file to be added to
+ # cmQtAutoGenInitializer::AutogenTarget.DependFiles, which disables the PRE_BUILD path.
+ if(CMAKE_GENERATOR MATCHES "Visual Studio")
+ # The file name should be target specific, but still short, so we don't hit path
+ # length issues.
+ string(MAKE_C_IDENTIFIER "ddf_${target}" dummy_dependency_file)
+ set(dummy_out_file "${CMAKE_CURRENT_BINARY_DIR}/${dummy_dependency_file}.h")
+
+ # The content shouldn't be empty so we don't trigger AUTOMOC warnings about it.
+ file(GENERATE OUTPUT "${dummy_out_file}" CONTENT "//")
+ set_source_files_properties("${dummy_out_file}" PROPERTIES
+ GENERATED TRUE
+ SKIP_AUTOGEN OFF)
+ target_sources("${target}" PRIVATE "${dummy_out_file}")
+ endif()
+
add_custom_target(${target}_automoc_json_extraction
DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::cmake_automoc_parser
- BYPRODUCTS ${type_list_file}
+ BYPRODUCTS
+ ${type_list_file}
+ "${cmake_automoc_parser_timestamp}"
COMMAND
${QT_CMAKE_EXPORT_NAMESPACE}::cmake_automoc_parser
--cmake-autogen-cache-file "${cmake_autogen_cache_file}"
--cmake-autogen-info-file "${cmake_autogen_info_file}"
--output-file-path "${type_list_file}"
- ${mutli_config_args}
- COMMENT "Running Automoc file extraction"
+ --timestamp-file-path "${cmake_automoc_parser_timestamp}"
+ ${multi_config_args}
+ COMMENT "Running AUTOMOC file extraction for target ${target}"
COMMAND_EXPAND_LISTS
)
add_dependencies(${target}_automoc_json_extraction ${target}_autogen)
+ _qt_internal_assign_to_internal_targets_folder(${target}_automoc_json_extraction)
else()
- set(cmake_autogen_timestamp_file
- "${target_binary_dir}/${target}_autogen/timestamp"
- )
+ set(timestamp_file "${target_autogen_build_dir}/timestamp")
+ set(timestamp_file_with_config "${timestamp_file}_$<CONFIG>")
+ if (is_multi_config AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.29"
+ AND NOT QT_INTERNAL_USE_OLD_AUTOGEN_GRAPH_MULTI_CONFIG_METATYPES)
+ string(JOIN "" timestamp_genex
+ "$<IF:$<BOOL:$<TARGET_PROPERTY:${target},"
+ "AUTOGEN_BETTER_GRAPH_MULTI_CONFIG>>,"
+ "${timestamp_file_with_config},${timestamp_file}>")
+ set(cmake_autogen_timestamp_file "${timestamp_genex}")
+ else()
+ set(cmake_autogen_timestamp_file ${timestamp_file})
+ endif()
add_custom_command(OUTPUT ${type_list_file}
DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::cmake_automoc_parser
${cmake_autogen_timestamp_file}
+ BYPRODUCTS "${cmake_automoc_parser_timestamp}"
COMMAND
${QT_CMAKE_EXPORT_NAMESPACE}::cmake_automoc_parser
--cmake-autogen-cache-file "${cmake_autogen_cache_file}"
--cmake-autogen-info-file "${cmake_autogen_info_file}"
--output-file-path "${type_list_file}"
- ${mutli_config_args}
- COMMENT "Running Automoc file extraction"
+ --timestamp-file-path "${cmake_automoc_parser_timestamp}"
+ ${multi_config_args}
+ COMMENT "Running AUTOMOC file extraction for target ${target}"
COMMAND_EXPAND_LISTS
+ VERBATIM
)
endif()
@@ -698,7 +1416,7 @@ function(qt6_generate_meta_types_json_file target)
message(FATAL_ERROR "Metatype generation requires either the use of AUTOMOC or a manual list of generated json files")
endif()
- if (CMAKE_BUILD_TYPE)
+ if (CMAKE_BUILD_TYPE AND NOT is_multi_config)
string(TOLOWER ${target}_${CMAKE_BUILD_TYPE} target_lowercase)
else()
string(TOLOWER ${target} target_lowercase)
@@ -724,18 +1442,11 @@ function(qt6_generate_meta_types_json_file target)
file(TOUCH ${metatypes_file})
endif()
- # Need to make the path absolute during a Qt non-prefix build, otherwise files are written
- # to the source dir because the paths are relative to the source dir when using file(TOUCH).
- if(arg_COPY_OVER_INSTALL AND NOT IS_ABSOLUTE "${arg_INSTALL_DIR}/${metatypes_file_name}")
- set(arg_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${arg_INSTALL_DIR}")
- endif()
-
- if (should_install AND arg_COPY_OVER_INSTALL
- AND NOT EXISTS ${arg_INSTALL_DIR}/${metatypes_file_name})
- file(MAKE_DIRECTORY "${arg_INSTALL_DIR}")
- file(TOUCH "${arg_INSTALL_DIR}/${metatypes_file_name}")
- endif()
- add_custom_command(OUTPUT ${metatypes_file_gen} ${metatypes_file}
+ add_custom_command(
+ OUTPUT
+ ${metatypes_file_gen}
+ BYPRODUCTS
+ ${metatypes_file}
DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::moc ${automoc_dependencies} ${manual_dependencies}
COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::moc
-o ${metatypes_file_gen}
@@ -743,85 +1454,87 @@ function(qt6_generate_meta_types_json_file target)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${metatypes_file_gen}
${metatypes_file}
- COMMENT "Runing automoc with --collect-json"
+ COMMENT "Running moc --collect-json for target ${target}"
+ VERBATIM
)
- # We still need to add this file as a source of Core, otherwise the file
+ if(CMAKE_GENERATOR MATCHES " Makefiles")
+ # Work around https://gitlab.kitware.com/cmake/cmake/-/issues/19005 to trigger the command
+ # that generates ${metatypes_file}.
+ add_custom_command(
+ OUTPUT ${metatypes_file}
+ DEPENDS ${metatypes_file_gen}
+ COMMAND ${CMAKE_COMMAND} -E true
+ VERBATIM
+ )
+ endif()
+
+ # We can't rely on policy CMP0118 since user project controls it
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties(${metatypes_file_gen} ${metatypes_file} ${scope_args}
+ PROPERTIES GENERATED TRUE
+ )
+
+ # We still need to add this file as a source of the target, otherwise the file
# rule above is not triggered. INTERFACE_SOURCES do not properly register
# as dependencies to build the current target.
+ # TODO: Can we pass ${metatypes_file} instead of ${metatypes_file_gen} as a source?
+ # TODO: Do we still need the _gen variant at all?
target_sources(${target} PRIVATE ${metatypes_file_gen})
- set(metatypes_file_genex_build)
- set(metatypes_file_genex_install)
- if (arg_COPY_OVER_INSTALL)
- if(should_install)
- set(metatypes_file_genex_build
- "$<BUILD_INTERFACE:$<$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>:${arg_INSTALL_DIR}/${metatypes_file_name}>>"
- )
- endif()
+ set_source_files_properties(${metatypes_file} ${scope_args}
+ PROPERTIES HEADER_FILE_ONLY TRUE
+ )
+
+ if(arg_OUTPUT_FILES)
+ set(${arg_OUTPUT_FILES} "${metatypes_file}" PARENT_SCOPE)
+ endif()
+
+ # Propagate the build time metatypes file.
+ _qt_internal_assign_build_metatypes_files_and_properties(
+ "${target}"
+ METATYPES_FILE_NAME "${metatypes_file_name}"
+ METATYPES_FILE_PATH "${metatypes_file}"
+ )
+
+ if(arg___QT_INTERNAL_INSTALL)
+ set(internal_install_option "INTERNAL_INSTALL")
else()
- set(metatypes_file_genex_build
- "$<BUILD_INTERFACE:$<$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>:${metatypes_file}>>"
- )
- if(should_install)
- set(metatypes_file_genex_install
- "$<INSTALL_INTERFACE:$<$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>:$<INSTALL_PREFIX>/${arg_INSTALL_DIR}/${metatypes_file_name}>>"
- )
- endif()
+ set(internal_install_option "")
endif()
- set_source_files_properties(${metatypes_file} PROPERTIES HEADER_FILE_ONLY TRUE)
- set_target_properties(${target} PROPERTIES
- INTERFACE_QT_MODULE_HAS_META_TYPES YES
- INTERFACE_QT_MODULE_META_TYPES_FROM_BUILD YES
- INTERFACE_QT_META_TYPES_BUILD_FILE "${metatypes_file}"
- QT_MODULE_META_TYPES_FILE_GENEX_BUILD "${metatypes_file_genex_build}"
- QT_MODULE_META_TYPES_FILE_GENEX_INSTALL "${metatypes_file_genex_install}"
+ # TODO: Clean up Qt-specific installation not to happen in the public api.
+ # Check whether the metatype files should be installed.
+ _qt_internal_should_install_metatypes("${target}"
+ ${internal_install_option}
+ OUT_VAR should_install
)
- target_sources(${target} INTERFACE ${metatypes_file_genex_build} ${metatypes_file_genex_install})
-
- # Installation is complicated, because there are multiple combinations.
- # In non-prefix builds (signaled by arg_COPY_OVER_INSTALL == TRUE), Qt modules are /copied/
- # into the qt_prefix/lib/metatypes.
- # In prefix builds (signaled by arg_COPY_OVER_INSTALL == FALSE), Qt modules are /installed/
- # into the qt_prefix/lib/metatypes.
- # Currently only the internal qt_add_module sets arg_COPY_OVER_INSTALL.
- #
- # Tests and examples are executables, and thus will not have their meta types installed, but
- # they will have them generated (if this function is called).
- #
- # Regular libraries and plugins (which are not part of the Qt build), will be /installed/
- # into a lib/metatypes directory relative to their prefix, rather than the Qt prefix (only
- # outside of a Qt build).
- # We don't support non-prefix builds for libraries or plugins which are not part of the official
- # Qt build. Aka everything non-prefix / COPY_OVER_INSTALL related are implementation details
- # that users shouldn't use.
+
if(should_install)
- if (arg_COPY_OVER_INSTALL)
- set(command_args
- COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${metatypes_file}"
- "${arg_INSTALL_DIR}/${metatypes_file_name}"
- )
- if (target_type STREQUAL "OBJECT_LIBRARY")
- add_custom_target(${target}_metatypes_copy
- DEPENDS "${metatypes_file}"
- ${command_args}
- )
- add_dependencies(${target} ${target}_metatypes_copy)
- else()
- add_custom_command(TARGET ${target} POST_BUILD
- ${command_args}
- )
- endif()
- else()
- install(FILES "${metatypes_file}" DESTINATION "${arg_INSTALL_DIR}")
- endif()
+ _qt_internal_get_metatypes_install_dir(
+ "${arg___QT_INTERNAL_INSTALL_DIR}"
+ "${INSTALL_ARCHDATADIR}"
+ install_dir
+ )
+
+ # Propagate the install time metatypes file.
+ _qt_internal_assign_install_metatypes_files_and_properties(
+ "${target}"
+ INSTALL_DIR "${install_dir}"
+ )
+ install(FILES "${metatypes_file}" DESTINATION "${install_dir}")
endif()
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_generate_meta_types_json_file)
- qt6_generate_meta_types_json_file(${ARGV})
+ function(qt_extract_metatypes)
+ qt6_extract_metatypes(${ARGV})
+ cmake_parse_arguments(PARSE_ARGV 0 arg "" "OUTPUT_FILES" "")
+ if(arg_OUTPUT_FILES)
+ set(${arg_OUTPUT_FILES} "${${arg_OUTPUT_FILES}}" PARENT_SCOPE)
+ endif()
endfunction()
endif()
@@ -842,7 +1555,7 @@ endif()
# If you do not wish to auto-generate rc files, it's possible to provide your
# own RC file by setting the property QT_TARGET_WINDOWS_RC_FILE with a path to
# an existing rc file.
-function(qt6_generate_win32_rc_file target)
+function(_qt_internal_generate_win32_rc_file target)
set(prohibited_target_types INTERFACE_LIBRARY STATIC_LIBRARY OBJECT_LIBRARY)
get_target_property(target_type ${target} TYPE)
if(target_type IN_LIST prohibited_target_types)
@@ -858,9 +1571,16 @@ function(qt6_generate_win32_rc_file target)
return()
endif()
+ if(MSVC)
+ set(extra_rc_flags "-c65001 -DWIN32 -nologo")
+ else()
+ set(extra_rc_flags)
+ endif()
+
if (target_rc_file)
# Use the provided RC file
target_sources(${target} PRIVATE "${target_rc_file}")
+ set_property(SOURCE ${target_rc_file} PROPERTY COMPILE_FLAGS "${extra_rc_flags}")
else()
# Generate RC File
set(rc_file_output "${target_binary_dir}/")
@@ -919,7 +1639,7 @@ function(qt6_generate_win32_rc_file target)
elseif (target_version MATCHES "[0-9]+")
set(target_version "${target_version}.0.0.0")
else()
- message(FATAL_ERROR "Invalid version format")
+ message(FATAL_ERROR "Invalid version format: '${target_version}'")
endif()
set(product_version "${target_version}")
else()
@@ -1013,6 +1733,32 @@ END
set(cfgs "${CMAKE_BUILD_TYPE}")
set(outputs "${rc_file_output}")
endif()
+
+ # We would like to do the following:
+ # target_sources(${target} PRIVATE "$<$<CONFIG:${cfg}>:${output}>")
+ #
+ # However, https://gitlab.kitware.com/cmake/cmake/-/issues/20682 doesn't let us do that
+ # in CMake 3.19 and earlier.
+ # We can do it in CMake 3.20 and later.
+ # And we have to do it with CMake 3.21.0 to avoid a different issue
+ # https://gitlab.kitware.com/cmake/cmake/-/issues/22436
+ #
+ # So use the object lib work around for <= 3.19 and target_sources directly for later
+ # versions.
+ set(use_obj_lib FALSE)
+ set(end_target "${target}")
+ if(CMAKE_VERSION VERSION_LESS 3.20)
+ set(use_obj_lib TRUE)
+ set(end_target "${target}_rc")
+ add_library(${target}_rc OBJECT "${output}")
+ target_link_libraries(${target} PRIVATE $<TARGET_OBJECTS:${target}_rc>)
+ endif()
+
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${end_target})
+ endif()
+
while(outputs)
list(POP_FRONT cfgs cfg)
list(POP_FRONT outputs output)
@@ -1020,164 +1766,592 @@ END
add_custom_command(OUTPUT "${output}"
DEPENDS "${input}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${input}" "${output}"
+ VERBATIM
)
-
- # We would like to do the following:
- # target_sources(${target} PRIVATE "$<$<CONFIG:${cfg}>:${output}>")
- # However, https://gitlab.kitware.com/cmake/cmake/-/issues/20682 doesn't let us.
- add_library(${target}_${cfg}_rc OBJECT "${output}")
- target_link_libraries(${target} PRIVATE "$<$<CONFIG:${cfg}>:${target}_${cfg}_rc>")
+ # We can't rely on policy CMP0118 since user project controls it
+ set_source_files_properties(${output} ${scope_args} PROPERTIES
+ GENERATED TRUE
+ COMPILE_FLAGS "${extra_rc_flags}"
+ )
+ target_sources(${end_target} PRIVATE "$<$<CONFIG:${cfg}>:${output}>")
endwhile()
endif()
endfunction()
+# Generate Win32 longPathAware RC and Manifest files for a target.
+# MSVC needs the manifest file as part of target_sources. MinGW the RC file.
+#
+function(_qt_internal_generate_longpath_win32_rc_file_and_manifest target)
+ set(prohibited_target_types INTERFACE_LIBRARY STATIC_LIBRARY OBJECT_LIBRARY)
+ get_target_property(target_type ${target} TYPE)
+ if(target_type IN_LIST prohibited_target_types)
+ return()
+ endif()
+
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+
+ # Generate manifest
+ set(target_mn_filename "${target}_longpath.manifest")
+ set(mn_file_output "${target_binary_dir}/${target_mn_filename}")
+
+ set(mn_contents [=[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
+ <ws2:longPathAware>true</ws2:longPathAware>
+ </windowsSettings>
+</application>
+</assembly>]=])
+ file(GENERATE OUTPUT "${mn_file_output}" CONTENT "${mn_contents}")
+
+ # Generate RC File
+ set(rc_file_output "${target_binary_dir}/${target}_longpath.rc")
+ set(rc_contents "1 /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 24 /* RT_MANIFEST */ ${target_mn_filename}")
+ file(GENERATE OUTPUT "${rc_file_output}" CONTENT "${rc_contents}")
+
+ if (MINGW)
+ set(outputs "${rc_file_output}")
+ endif()
+ list(APPEND outputs "${mn_file_output}")
+
+ foreach(output IN LISTS outputs)
+ # Needed for CMake versions < 3.19
+ set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
+ target_sources(${target} PRIVATE "${output}")
+ endforeach()
+endfunction()
+
function(__qt_get_relative_resource_path_for_file output_alias file)
get_property(alias SOURCE ${file} PROPERTY QT_RESOURCE_ALIAS)
if (NOT alias)
set(alias "${file}")
+ if(IS_ABSOLUTE "${file}")
+ message(FATAL_ERROR
+ "The source file '${file}' was specified with an absolute path and is used in a Qt "
+ "resource. Please set the QT_RESOURCE_ALIAS property on that source file to a "
+ "relative path to make the file properly accessible via the resource system."
+ )
+ endif()
endif()
set(${output_alias} ${alias} PARENT_SCOPE)
endfunction()
+# Performs linking and propagation of the specified objects via the target's usage requirements.
+# The objects may be given as generator expression.
+#
+# Arguments:
+# EXTRA_CONDITIONS
+# Conditions to be checked before linking the object files to the end-point executable.
+# EXTRA_TARGET_LINK_LIBRARIES_CONDITIONS
+# Conditions for the target_link_libraries call.
+# EXTRA_TARGET_SOURCES_CONDITIONS
+# Conditions for the target_sources call.
+function(__qt_internal_propagate_object_files target objects)
+ set(options "")
+ set(single_args "")
+ set(extra_conditions_args
+ EXTRA_CONDITIONS
+ EXTRA_TARGET_LINK_LIBRARIES_CONDITIONS
+ EXTRA_TARGET_SOURCES_CONDITIONS
+ )
+ set(multi_args ${extra_conditions_args})
+ cmake_parse_arguments(arg "${options}" "${single_args}" "${multi_args}" ${ARGN})
+
+ # Collect additional conditions.
+ foreach(arg IN LISTS extra_conditions_args)
+ string(TOLOWER "${arg}" lcvar)
+ if(arg_${arg})
+ list(JOIN arg_${arg} "," ${lcvar})
+ else()
+ set(${lcvar} "$<BOOL:TRUE>")
+ endif()
+ endforeach()
+
+ # Do not litter the static libraries
+ set(not_static_condition
+ "$<NOT:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>>"
+ )
+
+ # Check if link order matters for the Platform.
+ set(platform_link_order_property
+ "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Platform,_qt_link_order_matters>"
+ )
+ set(platform_link_order_condition
+ "$<BOOL:${platform_link_order_property}>"
+ )
+
+ # Check if link options are propagated according to CMP0099
+ # In user builds the _qt_cmp0099_policy_check is set to FALSE or $<TARGET_POLICY:CMP0099>
+ # depending on the used CMake version.
+ # See __qt_internal_check_cmp0099_available for details.
+ set(cmp0099_policy_check_property
+ "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Platform,_qt_cmp0099_policy_check>"
+ )
+ set(link_objects_using_link_options_condition
+ "$<BOOL:$<GENEX_EVAL:${cmp0099_policy_check_property}>>"
+ )
+
+ # Collect link conditions for the target_sources call.
+ string(JOIN "" target_sources_genex
+ "$<"
+ "$<AND:"
+ "${not_static_condition},"
+ "${platform_link_order_condition},"
+ "$<NOT:${link_objects_using_link_options_condition}>,"
+ "${extra_target_sources_conditions},"
+ "${extra_conditions}"
+ ">"
+ ":${objects}>"
+ )
+ target_sources(${target} INTERFACE
+ "${target_sources_genex}"
+ )
+
+ # Collect link conditions for the target_link_options call.
+ string(JOIN "" target_link_options_genex
+ "$<"
+ "$<AND:"
+ "${not_static_condition},"
+ "${platform_link_order_condition},"
+ "${link_objects_using_link_options_condition},"
+ "${extra_conditions}"
+ ">"
+ ":${objects}>"
+ )
+ # target_link_options works well since CMake 3.17 which has policy CMP0099 set to NEW for the
+ # minimum required CMake version greater than or equal to 3.17. The default is OLD. See
+ # https://cmake.org/cmake/help/git-master/policy/CMP0099.html for details.
+ # This provides yet another way of linking object libraries if user sets the policy to NEW
+ # before calling find_package(Qt...).
+ target_link_options(${target} INTERFACE
+ "${target_link_options_genex}"
+ )
+
+ # Collect link conditions for the target_link_libraries call.
+ string(JOIN "" target_link_libraries_genex
+ "$<"
+ "$<AND:"
+ "${not_static_condition},"
+ "$<NOT:${platform_link_order_condition}>,"
+ "${extra_target_link_libraries_conditions},"
+ "${extra_conditions}"
+ ">"
+ ":${objects}>"
+ )
+ target_link_libraries(${target} INTERFACE
+ "${target_link_libraries_genex}"
+ )
+endfunction()
+
+# Performs linking and propagation of the object library via the target's usage requirements.
+# Arguments:
+# NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET skip linking of ${object_library} to ${target}, only
+# propagate $<TARGET_OBJECTS:${object_library}> by linking it to ${target}. It's useful in case
+# if ${object_library} depends on the ${target}. E.g. resource libraries depend on the Core
+# library so linking them back to Core will cause a CMake error.
+#
+# EXTRA_CONDITIONS object library specific conditions to be checked before link the object library
+# to the end-point executable.
+function(__qt_internal_propagate_object_library target object_library)
+ set(options NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ set(single_args "")
+ set(multi_args EXTRA_CONDITIONS)
+ cmake_parse_arguments(arg "${options}" "${single_args}" "${multi_args}" ${ARGN})
+
+ get_target_property(is_imported ${object_library} IMPORTED)
+ if(NOT is_imported)
+ target_link_libraries(${object_library} PRIVATE ${QT_CMAKE_EXPORT_NAMESPACE}::Platform)
+ _qt_internal_copy_dependency_properties(${object_library} ${target} PRIVATE_ONLY)
+ endif()
+
+ # After internal discussion we decided to not rely on the linker order that CMake
+ # offers, until CMake provides the guaranteed linking order that suites our needs in a
+ # future CMake version.
+ # All object libraries mark themselves with the _is_qt_propagated_object_library property.
+ # Using a finalizer approach we walk through the target dependencies and look for libraries
+ # using the _is_qt_propagated_object_library property. Then, objects of the collected libraries
+ # are moved to the beginning of the linker line using target_sources.
+ #
+ # Note: target_link_libraries works well with linkers other than ld. If user didn't enforce
+ # a finalizer we rely on linker to resolve circular dependencies between objects and static
+ # libraries.
+ set_property(TARGET ${object_library} PROPERTY _is_qt_propagated_object_library TRUE)
+ if(NOT is_imported)
+ set_property(TARGET ${object_library} APPEND PROPERTY
+ EXPORT_PROPERTIES _is_qt_propagated_object_library
+ )
+ endif()
+
+ # Keep the implicit linking if finalizers are not used.
+ set(not_finalizer_mode_condition
+ "$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_object_libraries_finalizer_mode>>>"
+ )
+
+ # Use TARGET_NAME to have the correct namespaced name in the exports.
+ set(objects "$<TARGET_OBJECTS:$<TARGET_NAME:${object_library}>>")
+
+ __qt_internal_propagate_object_files(${target} ${objects}
+ EXTRA_CONDITIONS ${arg_EXTRA_CONDITIONS}
+ EXTRA_TARGET_SOURCES_CONDITIONS ${not_finalizer_mode_condition}
+ EXTRA_TARGET_LINK_LIBRARIES_CONDITIONS ${not_finalizer_mode_condition}
+ )
+
+ if(NOT arg_NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ # It's necessary to link the object library target, since we want to pass the object library
+ # dependencies to the 'target'. Interface linking doesn't add the objects of the library to
+ # the end-point linker line but propagates all the dependencies of the object_library added
+ # before or AFTER the line below.
+ target_link_libraries(${target} INTERFACE ${object_library})
+ endif()
+endfunction()
+
function(__qt_propagate_generated_resource target resource_name generated_source_code output_generated_target)
get_target_property(type ${target} TYPE)
if(type STREQUAL STATIC_LIBRARY)
- set(resource_target "${target}_resources_${resourceName}")
- add_library("${resource_target}" OBJECT "${generated_source_code}")
- set_property(TARGET ${resource_target} APPEND PROPERTY QT_RESOURCE_NAME ${resourceName})
-
- # Use TARGET_NAME genex to map to the correct prefixed target name when it is exported
- # via qt_install(EXPORT), so that the consumers of the target can find the object library
- # as well.
- target_link_libraries(${target} INTERFACE
- "$<TARGET_OBJECTS:$<TARGET_NAME:${resource_target}>>")
+ get_target_property(resource_count ${target} _qt_generated_resource_target_count)
+ if(NOT resource_count)
+ set(resource_count "0")
+ endif()
+ math(EXPR resource_count "${resource_count} + 1")
+ set_target_properties(${target} PROPERTIES _qt_generated_resource_target_count ${resource_count})
+
+ __qt_internal_generate_init_resource_source_file(
+ resource_init_file ${target} ${resource_name})
+
+ set(resource_target "${target}_resources_${resource_count}")
+ add_library("${resource_target}" OBJECT "${resource_init_file}")
+ set_target_properties(${resource_target} PROPERTIES
+ AUTOMOC FALSE
+ AUTOUIC FALSE
+ AUTORCC FALSE
+ )
+ # Needed so that qtsymbolmacros.h and its dependent headers are already created / syncqt'ed.
+ if(TARGET Core_sync_headers)
+ set(headers_available_target "Core_sync_headers")
+ else()
+ set(headers_available_target "${QT_CMAKE_EXPORT_NAMESPACE}::Core")
+ endif()
+ add_dependencies(${resource_target} ${headers_available_target})
+ target_compile_definitions("${resource_target}" PRIVATE
+ "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Core,INTERFACE_COMPILE_DEFINITIONS>"
+ )
+ target_include_directories("${resource_target}" PRIVATE
+ "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Core,INTERFACE_INCLUDE_DIRECTORIES>"
+ )
+ _qt_internal_set_up_static_runtime_library("${resource_target}")
+
+ # Special handling is required for the Core library resources. The linking of the Core
+ # library to the resources adds a circular dependency. This leads to the wrong
+ # objects/library order in the linker command line, since the Core library target is
+ # resolved first.
+ if(NOT target STREQUAL "Core")
+ target_link_libraries(${resource_target} INTERFACE ${QT_CMAKE_EXPORT_NAMESPACE}::Core)
+ endif()
+ set_property(TARGET ${resource_target} APPEND PROPERTY _qt_resource_name ${resource_name})
+
+ # Save the path to the generated source file, relative to the the current build dir.
+ # The path will be used in static library prl file generation to ensure qmake links
+ # against the installed resource object files.
+ # Example saved path:
+ # .rcc/qrc_qprintdialog.cpp
+ file(RELATIVE_PATH generated_cpp_file_relative_path
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${resource_init_file}")
+ set_property(TARGET ${resource_target} APPEND PROPERTY
+ _qt_resource_generated_cpp_relative_path "${generated_cpp_file_relative_path}")
+
+ if(target STREQUAL "Core")
+ set(skip_direct_linking NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ endif()
+ __qt_internal_propagate_object_library(${target} ${resource_target}
+ ${skip_direct_linking}
+ )
+
set(${output_generated_target} "${resource_target}" PARENT_SCOPE)
else()
set(${output_generated_target} "" PARENT_SCOPE)
- target_sources(${target} PRIVATE ${generated_source_code})
endif()
+
+ target_sources(${target} PRIVATE ${generated_source_code})
endfunction()
+function(__qt_internal_sanitize_resource_name out_var name)
+ # The sanitized output should match RCCResourceLibrary::writeInitializer()'s
+ # isAsciiLetterOrNumber-based substituion.
+ # MAKE_C_IDENTIFIER matches that, it replaces non-alphanumeric chars with underscores.
+ string(MAKE_C_IDENTIFIER "${name}" sanitized_resource_name)
+ set(${out_var} "${sanitized_resource_name}" PARENT_SCOPE)
+endfunction()
+
+function(__qt_internal_generate_init_resource_source_file out_var target resource_name)
+ set(template_file "${__qt_core_macros_module_base_dir}/Qt6CoreResourceInit.in.cpp")
+
+ # Gets replaced in the template
+ __qt_internal_sanitize_resource_name(RESOURCE_NAME "${resource_name}")
+ set(resource_init_path "${CMAKE_CURRENT_BINARY_DIR}/.qt/rcc/qrc_${resource_name}_init.cpp")
+
+ configure_file("${template_file}" "${resource_init_path}" @ONLY)
+
+ set(scope_args "")
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties(${resource_init_path} ${scope_args} PROPERTIES
+ SKIP_AUTOGEN TRUE
+ SKIP_UNITY_BUILD_INCLUSION TRUE
+ SKIP_PRECOMPILE_HEADERS TRUE
+ )
+
+ set(${out_var} "${resource_init_path}" PARENT_SCOPE)
+endfunction()
+
+# Make file visible in IDEs.
+# Targets that are finalized add the file as HEADER_FILE_ONLY in the finalizer.
+# Targets that are not finalized add the file under a ${target}_other_files target.
+function(_qt_internal_expose_source_file_to_ide target file)
+ get_target_property(target_expects_finalization ${target} _qt_expects_finalization)
+ if(target_expects_finalization AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ set_property(TARGET ${target} APPEND PROPERTY _qt_deferred_files ${file})
+ return()
+ endif()
+
+ # Fallback for targets that are not finalized: Create fake target under which the file is added.
+ set(ide_target ${target}_other_files)
+ if(NOT TARGET ${ide_target})
+ add_custom_target(${ide_target} SOURCES "${file}")
+
+ # The new Xcode build system requires a common target to drive the generation of files,
+ # otherwise project configuration fails.
+ # By adding ${target} as a dependency of ${target}_other_files,
+ # it becomes the common target, so project configuration succeeds.
+ if(CMAKE_GENERATOR STREQUAL "Xcode")
+ add_dependencies(${ide_target} ${target})
+ endif()
+ else()
+ set_property(TARGET ${ide_target} APPEND PROPERTY SOURCES "${file}")
+ endif()
+
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY "${target}")
+ endif()
+ get_source_file_property(
+ target_dependency "${file}" ${scope_args} _qt_resource_target_dependency)
+ if(target_dependency)
+ if(NOT TARGET "${target_dependency}")
+ message(FATAL_ERROR "Target dependency on source file ${file} is not a cmake target.")
+ endif()
+ add_dependencies(${ide_target} ${target_dependency})
+ endif()
+endfunction()
+
+# Called by the target finalizer.
+# Adds the files that were added to _qt_deferred_files to SOURCES.
+# Sets HEADER_FILES_ONLY if they did not exist yet in SOURCES.
+function(_qt_internal_expose_deferred_files_to_ide target)
+ get_target_property(new_sources ${target} _qt_deferred_files)
+ if(NOT new_sources)
+ return()
+ endif()
+ set(new_sources_real "")
+ foreach(f IN LISTS new_sources)
+ get_filename_component(realf "${f}" REALPATH)
+ list(APPEND new_sources_real ${realf})
+ endforeach()
+
+ set(filtered_new_sources "")
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ get_filename_component(target_source_dir "${target_source_dir}" REALPATH)
+ get_target_property(existing_sources ${target} SOURCES)
+ if(existing_sources)
+ set(existing_sources_real "")
+ set(realf "")
+ foreach(f IN LISTS existing_sources)
+ get_filename_component(realf "${f}" REALPATH BASE_DIR ${target_source_dir})
+ list(APPEND existing_sources_real ${realf})
+ endforeach()
+
+ list(LENGTH new_sources max_i)
+ math(EXPR max_i "${max_i} - 1")
+ foreach(i RANGE 0 ${max_i})
+ list(GET new_sources_real ${i} realf)
+ if(NOT realf IN_LIST existing_sources_real)
+ list(GET new_sources ${i} f)
+ list(APPEND filtered_new_sources ${f})
+ endif()
+ endforeach()
+ endif()
+ if("${filtered_new_sources}" STREQUAL "")
+ return()
+ endif()
+
+ target_sources(${target} PRIVATE ${filtered_new_sources})
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY "${target}")
+ endif()
+ set_source_files_properties(${filtered_new_sources}
+ ${scope_args} PROPERTIES HEADER_FILE_ONLY ON)
+endfunction()
#
# Process resources via file path instead of QRC files. Behind the
-# scnenes, it will generate a qrc file and apply post processing steps
-# when applicable. (e.g.: QtQuickCompiler)
+# scenes, it will generate a qrc file.
#
# The QRC Prefix is set via the PREFIX parameter.
#
# Alias settings for files need to be set via the QT_RESOURCE_ALIAS property
-# via the set_soure_files_properties() command.
+# via the set_source_files_properties() command.
#
# When using this command with static libraries, one or more special targets
# will be generated. Should you wish to perform additional processing on these
# targets pass a value to the OUTPUT_TARGETS parameter.
#
-function(QT6_PROCESS_RESOURCE target resourceName)
+function(_qt_internal_process_resource target resourceName)
+ cmake_parse_arguments(rcc "BIG_RESOURCES"
+ "PREFIX;LANG;BASE;OUTPUT_TARGETS;DESTINATION" "FILES;OPTIONS" ${ARGN})
+
+ if("${rcc_OPTIONS}" MATCHES "-binary")
+ set(isBinary TRUE)
+ if(rcc_BIG_RESOURCES)
+ message(FATAL_ERROR "BIG_RESOURCES cannot be used together with the -binary option.")
+ endif()
+ endif()
+
+ if(rcc_BIG_RESOURCES AND CMAKE_GENERATOR STREQUAL "Xcode" AND IOS)
+ message(WARNING
+ "Due to CMake limitations, the BIG_RESOURCES option can't be used when building "
+ "for iOS. "
+ "See https://bugreports.qt.io/browse/QTBUG-103497 for details. "
+ "Falling back to using regular resources. "
+ )
+ set(rcc_BIG_RESOURCES OFF)
+ endif()
- cmake_parse_arguments(rcc "" "PREFIX;LANG;BASE;OUTPUT_TARGETS" "FILES;OPTIONS" ${ARGN})
+ if(rcc_BIG_RESOURCES AND CMAKE_VERSION VERSION_LESS "3.17")
+ message(WARNING
+ "The BIG_RESOURCES option does not work reliably with CMake < 3.17. "
+ "Consider upgrading to a more recent CMake version or disable the BIG_RESOURCES "
+ "option for older CMake versions."
+ )
+ endif()
string(REPLACE "/" "_" resourceName ${resourceName})
string(REPLACE "." "_" resourceName ${resourceName})
- set(output_targets "")
- # Apply base to all files
- if (rcc_BASE)
- foreach(file IN LISTS rcc_FILES)
- set(resource_file "${rcc_BASE}/${file}")
- __qt_get_relative_resource_path_for_file(alias ${resource_file})
- # Handle case where resources were generated from a directory
- # different than the one where the main .pro file resides.
- # Unless otherwise specified, we should use the original file path
- # as alias.
- if (alias STREQUAL resource_file)
- set_source_files_properties(${resource_file} PROPERTIES QT_RESOURCE_ALIAS ${file})
+ set(resource_files "")
+ # Strip the ending slashes from the file_path. If paths contain slashes in the end
+ # set/get source properties works incorrect and may have the same QT_RESOURCE_ALIAS
+ # for two different paths. See https://gitlab.kitware.com/cmake/cmake/-/issues/23212
+ # for details.
+ foreach(file_path IN LISTS rcc_FILES)
+ if(file_path MATCHES "(.+)/$")
+ set(file_path "${CMAKE_MATCH_1}")
+ endif()
+ list(APPEND resource_files ${file_path})
+ endforeach()
+
+ if(NOT "${rcc_BASE}" STREQUAL "")
+ get_filename_component(abs_base "${rcc_BASE}" ABSOLUTE)
+ foreach(file_path IN LISTS resource_files)
+ get_source_file_property(alias "${file_path}" QT_RESOURCE_ALIAS)
+ if(alias STREQUAL "NOTFOUND")
+ get_filename_component(abs_file "${file_path}" ABSOLUTE)
+ file(RELATIVE_PATH rel_file "${abs_base}" "${abs_file}")
+ set_property(SOURCE "${file_path}" PROPERTY QT_RESOURCE_ALIAS "${rel_file}")
endif()
- file(TO_CMAKE_PATH ${resource_file} resource_file)
- list(APPEND resource_files ${resource_file})
endforeach()
- else()
- set(resource_files ${rcc_FILES})
+ endif()
+
+ if(ANDROID)
+ if(COMMAND _qt_internal_collect_qml_root_paths)
+ _qt_internal_collect_qml_root_paths(${target} ${resource_files})
+ endif()
endif()
if(NOT rcc_PREFIX)
get_target_property(rcc_PREFIX ${target} QT_RESOURCE_PREFIX)
if (NOT rcc_PREFIX)
- message(FATAL_ERROR "QT6_PROCESS_RESOURCE() was called without a PREFIX and the target does not provide QT_RESOURCE_PREFIX. Please either add a PREFIX or make the target ${target} provide a default.")
+ set(rcc_PREFIX "/")
endif()
endif()
- # Apply quick compiler pass. This is only enabled when Qt6QmlMacros is
- # parsed.
- if (QT6_ADD_RESOURCE_DECLARATIVE_EXTENSIONS)
- qt6_quick_compiler_process_resources(${target} ${resourceName}
- FILES ${resource_files}
- PREFIX ${rcc_PREFIX}
- OUTPUT_REMAINING_RESOURCES resources
- OUTPUT_RESOURCE_NAME newResourceName
- OUTPUT_GENERATED_TARGET output_target_quick
- )
- else()
- set(newResourceName ${resourceName})
- set(resources ${resource_files})
- endif()
-
- if (NOT resources)
+ if (NOT resource_files)
if (rcc_OUTPUT_TARGETS)
- set(${rcc_OUTPUT_TARGETS} "${output_target_quick}" PARENT_SCOPE)
+ set(${rcc_OUTPUT_TARGETS} "" PARENT_SCOPE)
endif()
return()
endif()
- list(APPEND output_targets ${output_target_quick})
- set(generatedResourceFile "${CMAKE_CURRENT_BINARY_DIR}/.rcc/generated_${newResourceName}.qrc")
- set(generatedSourceCode "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qrc_${newResourceName}.cpp")
+ set(generatedResourceFile "${CMAKE_CURRENT_BINARY_DIR}/.qt/rcc/${resourceName}.qrc")
+ _qt_internal_expose_source_file_to_ide(${target} ${generatedResourceFile})
+ set_source_files_properties(${generatedResourceFile} PROPERTIES GENERATED TRUE)
# Generate .qrc file:
# <RCC><qresource ...>
set(qrcContents "<RCC>\n <qresource")
- if (rcc_PREFIX)
- string(APPEND qrcContents " prefix=\"${rcc_PREFIX}\"")
- endif()
+ string(APPEND qrcContents " prefix=\"${rcc_PREFIX}\"")
+
if (rcc_LANG)
string(APPEND qrcContents " lang=\"${rcc_LANG}\"")
endif()
string(APPEND qrcContents ">\n")
set(resource_dependencies)
- foreach(file IN LISTS resources)
+ foreach(file IN LISTS resource_files)
__qt_get_relative_resource_path_for_file(file_resource_path ${file})
if (NOT IS_ABSOLUTE ${file})
set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
endif()
+ get_property(is_empty SOURCE ${file} PROPERTY QT_DISCARD_FILE_CONTENTS)
+
### FIXME: escape file paths to be XML conform
# <file ...>...</file>
- string(APPEND qrcContents " <file alias=\"${file_resource_path}\">")
- string(APPEND qrcContents "${file}</file>\n")
+ string(APPEND qrcContents " <file alias=\"${file_resource_path}\"")
+ if(is_empty)
+ string(APPEND qrcContents " empty=\"true\"")
+ endif()
+ string(APPEND qrcContents ">${file}</file>\n")
list(APPEND files "${file}")
- get_source_file_property(target_dependency ${file} QT_RESOURCE_TARGET_DEPENDENCY)
- if (NOT target_dependency)
- list(APPEND resource_dependencies ${file})
- else()
- if (NOT TARGET ${target_dependency})
- message(FATAL_ERROR "Target dependency on resource file ${file} is not a cmake target.")
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ get_source_file_property(
+ target_dependency ${file} ${scope_args} _qt_resource_target_dependency)
+
+ # The target dependency code path does not take care of rebuilds when ${file}
+ # is touched. Limit its usage to the Xcode generator to avoid the Xcode common
+ # dependency issue.
+ # TODO: Figure out how to avoid the issue on Xcode, while also enabling proper
+ # dependency tracking when ${file} is touched.
+ if(target_dependency AND CMAKE_GENERATOR STREQUAL "Xcode")
+ if(NOT TARGET ${target_dependency})
+ message(FATAL_ERROR
+ "Target dependency on resource file ${file} is not a cmake target.")
endif()
list(APPEND resource_dependencies ${target_dependency})
+ else()
+ list(APPEND resource_dependencies ${file})
endif()
+ _qt_internal_expose_source_file_to_ide(${target} "${file}")
endforeach()
# </qresource></RCC>
string(APPEND qrcContents " </qresource>\n</RCC>\n")
- file(GENERATE OUTPUT "${generatedResourceFile}" CONTENT "${qrcContents}")
+ set(template_file "${__qt_core_macros_module_base_dir}/Qt6CoreConfigureFileTemplate.in")
+ set(qt_core_configure_file_contents "${qrcContents}")
+ configure_file("${template_file}" "${generatedResourceFile}")
+
+ set(rccArgs --name "${resourceName}" "${generatedResourceFile}")
+ set(rccArgsAllPasses "")
- set(rccArgs --name "${newResourceName}"
- --output "${generatedSourceCode}" "${generatedResourceFile}")
if(rcc_OPTIONS)
- list(APPEND rccArgs ${rcc_OPTIONS})
+ list(APPEND rccArgsAllPasses ${rcc_OPTIONS})
endif()
# When cross-building, we use host tools to generate target code. If the host rcc was compiled
@@ -1187,58 +2361,172 @@ function(QT6_PROCESS_RESOURCE target resourceName)
# If the target does not support zstd (feature is disabled), tell rcc not to generate
# zstd related code.
if(NOT QT_FEATURE_zstd)
- list(APPEND rccArgs "--no-zstd")
+ list(APPEND rccArgsAllPasses "--no-zstd")
+ endif()
+
+ set_property(SOURCE "${generatedResourceFile}" PROPERTY SKIP_AUTOGEN ON)
+
+ # Set output file name for rcc command
+ if(isBinary)
+ set(generatedOutfile "${CMAKE_CURRENT_BINARY_DIR}/${resourceName}.rcc")
+ if(rcc_DESTINATION)
+ # Add .rcc suffix if it's not specified by user
+ get_filename_component(destinationRccExt "${rcc_DESTINATION}" LAST_EXT)
+ if("${destinationRccExt}" STREQUAL ".rcc")
+ set(generatedOutfile "${rcc_DESTINATION}")
+ else()
+ set(generatedOutfile "${rcc_DESTINATION}.rcc")
+ endif()
+ endif()
+ elseif(rcc_BIG_RESOURCES)
+ set(generatedOutfile "${CMAKE_CURRENT_BINARY_DIR}/.qt/rcc/qrc_${resourceName}_tmp.cpp")
+ else()
+ set(generatedOutfile "${CMAKE_CURRENT_BINARY_DIR}/.qt/rcc/qrc_${resourceName}.cpp")
+ endif()
+
+ set(pass_msg)
+ if(rcc_BIG_RESOURCES)
+ list(PREPEND rccArgs --pass 1)
+ set(pass_msg " pass 1")
endif()
+ list(PREPEND rccArgs --output "${generatedOutfile}")
+
# Process .qrc file:
- add_custom_command(OUTPUT "${generatedSourceCode}"
- COMMAND "${QT_CMAKE_EXPORT_NAMESPACE}::rcc"
- ARGS ${rccArgs}
+ add_custom_command(OUTPUT "${generatedOutfile}"
+ COMMAND "${QT_CMAKE_EXPORT_NAMESPACE}::rcc" ${rccArgs} ${rccArgsAllPasses}
DEPENDS
${resource_dependencies}
${generatedResourceFile}
"${QT_CMAKE_EXPORT_NAMESPACE}::rcc"
- COMMENT "RCC ${newResourceName}"
+ COMMENT "Running rcc${pass_msg} for resource ${resourceName}"
VERBATIM)
- get_target_property(type "${target}" TYPE)
- # Only do this if newResourceName is the same as resourceName, since
- # the resource will be chainloaded by the qt quickcompiler
- # qml cache loader
- if(newResourceName STREQUAL resourceName)
- __qt_propagate_generated_resource(${target} ${resourceName} "${generatedSourceCode}" output_target)
- list(APPEND output_targets ${output_target})
+ if(isBinary)
+ # Add generated .rcc target to 'all' set
+ add_custom_target(binary_resource_${resourceName} ALL DEPENDS "${generatedOutfile}")
+ return()
+ endif()
+
+ # We can't rely on policy CMP0118 since user project controls it.
+ # We also want SKIP_AUTOGEN known in the target's scope, where we can.
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties(${generatedOutfile} ${scope_args} PROPERTIES
+ SKIP_AUTOGEN TRUE
+ GENERATED TRUE
+ SKIP_UNITY_BUILD_INCLUSION TRUE
+ SKIP_PRECOMPILE_HEADERS TRUE
+ )
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.27")
+ set_source_files_properties(${generatedOutfile} ${scope_args} PROPERTIES SKIP_LINTING ON)
+ endif()
+
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ if(NOT target_source_dir STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ # We have to create a separate target in this scope that depends on
+ # the generated file, otherwise the original target won't have the
+ # required dependencies in place to ensure correct build order.
+ add_custom_target(${target}_${resourceName} DEPENDS ${generatedOutfile})
+ add_dependencies(${target} ${target}_${resourceName})
+ endif()
+
+ if(rcc_BIG_RESOURCES)
+ set(pass1OutputFile ${generatedOutfile})
+ set(generatedOutfile
+ "${CMAKE_CURRENT_BINARY_DIR}/.qt/rcc/qrc_${resourceName}${CMAKE_CXX_OUTPUT_EXTENSION}")
+ _qt_internal_add_rcc_pass2(
+ RESOURCE_NAME ${resourceName}
+ RCC_OPTIONS ${rccArgsAllPasses}
+ OBJECT_LIB ${target}_${resourceName}_obj
+ QRC_FILE ${generatedResourceFile}
+ PASS1_OUTPUT_FILE ${pass1OutputFile}
+ OUT_OBJECT_FILE ${generatedOutfile}
+ )
+ get_target_property(type ${target} TYPE)
+ if(type STREQUAL STATIC_LIBRARY)
+ # Create a custom target to trigger the generation of ${generatedOutfile}
+ set(pass2_target ${target}_${resourceName}_pass2)
+ add_custom_target(${pass2_target} DEPENDS ${generatedOutfile})
+ add_dependencies(${target} ${pass2_target})
+
+ # Propagate the object files to the target.
+ __qt_internal_propagate_object_files(${target} "${generatedOutfile}")
+ else()
+ target_sources(${target} PRIVATE ${generatedOutfile})
+ endif()
else()
- target_sources(${target} PRIVATE "${generatedSourceCode}")
+ __qt_propagate_generated_resource(${target} ${resourceName} "${generatedOutfile}"
+ output_targets)
endif()
+
+ set_property(TARGET ${target}
+ APPEND PROPERTY _qt_generated_qrc_files "${generatedResourceFile}")
+
if (rcc_OUTPUT_TARGETS)
set(${rcc_OUTPUT_TARGETS} "${output_targets}" PARENT_SCOPE)
endif()
endfunction()
-function(qt6_add_plugin target)
- cmake_parse_arguments(arg
- "STATIC"
- "OUTPUT_NAME"
- "CLASS_NAME"
- ""
- ${ARGN}
+macro(_qt_internal_get_add_plugin_keywords option_args single_args multi_args)
+ set(${option_args}
+ STATIC
+ SHARED
+ __QT_INTERNAL_NO_PROPAGATE_PLUGIN_INITIALIZER
)
- if (arg_STATIC)
- add_library(${target} STATIC)
+ set(${single_args}
+ PLUGIN_TYPE # Internal use only, may be changed or removed
+ CLASS_NAME
+ OUTPUT_NAME # Internal use only, may be changed or removed
+ OUTPUT_TARGETS
+ )
+ set(${multi_args})
+endmacro()
+
+function(qt6_add_plugin target)
+ _qt_internal_get_add_plugin_keywords(opt_args single_args multi_args)
+ list(APPEND opt_args MANUAL_FINALIZATION)
+
+ cmake_parse_arguments(PARSE_ARGV 1 arg "${opt_args}" "${single_args}" "${multi_args}")
+
+ if(arg_STATIC AND arg_SHARED)
+ message(FATAL_ERROR
+ "Both STATIC and SHARED options were given. Only one of the two should be used."
+ )
+ endif()
+
+ # Explicit option takes priority over the computed default.
+ if(arg_STATIC)
+ set(create_static_plugin TRUE)
+ elseif(arg_SHARED)
+ set(create_static_plugin FALSE)
else()
- add_library(${target} MODULE)
- if(APPLE)
- # CMake defaults to using .so extensions for loadable modules, aka plugins,
- # but Qt plugins are actually suffixed with .dylib.
- set_property(TARGET "${target}" PROPERTY SUFFIX ".dylib")
- endif()
- if(WIN32)
- # CMake sets for Windows-GNU platforms the suffix "lib"
- set_property(TARGET "${target}" PROPERTY PREFIX "")
+ # If no explicit STATIC/SHARED option is set, default to the flavor of the Qt build.
+ if(QT6_IS_SHARED_LIBS_BUILD)
+ set(create_static_plugin FALSE)
+ else()
+ set(create_static_plugin TRUE)
endif()
endif()
+ # The default of _qt_internal_add_library creates SHARED in a shared Qt build, so we need to
+ # be explicit about the MODULE.
+ if(create_static_plugin)
+ set(type_to_create STATIC)
+ else()
+ set(type_to_create MODULE)
+ endif()
+
+ _qt_internal_add_library(${target} ${type_to_create} ${arg_UNPARSED_ARGUMENTS})
+ set_property(TARGET ${target} PROPERTY _qt_expects_finalization TRUE)
+
+ get_target_property(target_type "${target}" TYPE)
+ if (target_type STREQUAL "STATIC_LIBRARY")
+ target_compile_definitions(${target} PRIVATE QT_STATICPLUGIN)
+ endif()
+
set(output_name ${target})
if (arg_OUTPUT_NAME)
set(output_name ${arg_OUTPUT_NAME})
@@ -1246,47 +2534,1296 @@ function(qt6_add_plugin target)
set_property(TARGET "${target}" PROPERTY OUTPUT_NAME "${output_name}")
if (ANDROID)
- qt_android_apply_arch_suffix("${target}")
set_target_properties(${target}
PROPERTIES
- LIBRARY_OUTPUT_NAME "plugins_${arg_TYPE}_${output_name}"
+ LIBRARY_OUTPUT_NAME "plugins_${arg_PLUGIN_TYPE}_${output_name}"
)
endif()
# Derive the class name from the target name if it's not explicitly specified.
set(plugin_class_name "")
- if (NOT arg_CLASS_NAME)
- set(plugin_class_name "${target}")
+ if (NOT "${arg_PLUGIN_TYPE}" STREQUAL "qml_plugin")
+ if (NOT arg_CLASS_NAME)
+ set(plugin_class_name "${target}")
+ else()
+ set(plugin_class_name "${arg_CLASS_NAME}")
+ endif()
else()
- set(plugin_class_name "${arg_CLASS_NAME}")
+ # Make sure to set any passed-in class name for qml plugins as well, because it's used for
+ # building the qml plugin foo_init object libraries.
+ if(arg_CLASS_NAME)
+ set(plugin_class_name "${arg_CLASS_NAME}")
+ else()
+ message(FATAL_ERROR "Qml plugin target has no CLASS_NAME specified: '${target}'")
+ endif()
endif()
+
set_target_properties(${target} PROPERTIES QT_PLUGIN_CLASS_NAME "${plugin_class_name}")
- set(static_plugin_define "")
- if (arg_STATIC)
- set(static_plugin_define "QT_STATICPLUGIN")
+ # Create a plugin initializer object library for static plugins.
+ # It contains a Q_IMPORT_PLUGIN(QT_PLUGIN_CLASS_NAME) call.
+ # Project targets will automatically link to the plugin initializer whenever they link to the
+ # plugin target.
+ # The plugin init target name is stored in OUTPUT_TARGETS, so projects may install them.
+ # Qml plugin inits are handled in Qt6QmlMacros.
+ if(NOT "${arg_PLUGIN_TYPE}" STREQUAL "qml_plugin"
+ AND target_type STREQUAL "STATIC_LIBRARY")
+ __qt_internal_add_static_plugin_init_object_library("${target}" plugin_init_target)
+
+ if(arg_OUTPUT_TARGETS)
+ set(${arg_OUTPUT_TARGETS} ${plugin_init_target} PARENT_SCOPE)
+ endif()
+
+ # We don't automatically propagate the plugin init library for Qt provided plugins, because
+ # there are 2 other code paths that take care of that, one involving finalizers and the
+ # other regular usage requirements.
+ if(NOT arg___QT_INTERNAL_NO_PROPAGATE_PLUGIN_INITIALIZER)
+ __qt_internal_propagate_object_library("${target}" "${plugin_init_target}")
+ endif()
+ else()
+ if(arg_OUTPUT_TARGETS)
+ set(${arg_OUTPUT_TARGETS} "" PARENT_SCOPE)
+ endif()
endif()
+
target_compile_definitions(${target} PRIVATE
QT_PLUGIN
QT_DEPRECATED_WARNINGS
- ${static_plugin_define}
)
+
+ if(target_type STREQUAL "MODULE_LIBRARY")
+ if(NOT TARGET qt_internal_plugins)
+ add_custom_target(qt_internal_plugins)
+ _qt_internal_assign_to_internal_targets_folder(qt_internal_plugins)
+ endif()
+ add_dependencies(qt_internal_plugins ${target})
+ endif()
+
+ if(arg_MANUAL_FINALIZATION)
+ # Caller says they will call qt6_finalize_target() themselves later
+ return()
+ endif()
+
+ # Defer the finalization if we can. When the caller's project requires
+ # CMake 3.19 or later, this makes the calls to this function concise while
+ # still allowing target property modification before finalization.
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
+ # Need to wrap in an EVAL CODE or else ${target} won't be evaluated
+ # due to special behavior of cmake_language() argument handling
+ cmake_language(EVAL CODE "cmake_language(DEFER CALL qt6_finalize_target ${target})")
+ else()
+ set_target_properties("${target}" PROPERTIES _qt_is_immediately_finalized TRUE)
+ qt6_finalize_target("${target}")
+ endif()
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
function(qt_add_plugin)
- if (NOT DEFINED QT_DISABLE_QT_ADD_PLUGIN_COMPATIBILITY
- OR NOT QT_DISABLE_QT_ADD_PLUGIN_COMPATIBILITY)
- qt_internal_add_plugin(${ARGV})
+ qt6_add_plugin(${ARGV})
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "OUTPUT_TARGETS" "")
+ if(arg_OUTPUT_TARGETS)
+ set(${arg_OUTPUT_TARGETS} ${${arg_OUTPUT_TARGETS}} PARENT_SCOPE)
+ endif()
+ endfunction()
+endif()
+
+# Creates a library by forwarding arguments to add_library, applies some Qt naming file name naming
+# conventions and ensures the execution of Qt specific finalizers.
+function(qt6_add_library target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "MANUAL_FINALIZATION" "" "")
+
+ _qt_internal_add_library("${target}" ${arg_UNPARSED_ARGUMENTS})
+ set_property(TARGET ${target} PROPERTY _qt_expects_finalization TRUE)
+
+ if(arg_MANUAL_FINALIZATION)
+ # Caller says they will call qt6_finalize_target() themselves later
+ return()
+ endif()
+
+ # Defer the finalization if we can. When the caller's project requires
+ # CMake 3.19 or later, this makes the calls to this function concise while
+ # still allowing target property modification before finalization.
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
+ # Need to wrap in an EVAL CODE or else ${target} won't be evaluated
+ # due to special behavior of cmake_language() argument handling
+ cmake_language(EVAL CODE "cmake_language(DEFER CALL qt6_finalize_target ${target})")
+ else()
+ set_target_properties("${target}" PROPERTIES _qt_is_immediately_finalized TRUE)
+ qt6_finalize_target("${target}")
+ endif()
+endfunction()
+
+# Creates a library target by forwarding the arguments to add_library.
+#
+# Applies some Qt specific behaviors:
+# - If no type option is specified, rather than defaulting to STATIC it defaults to STATIC or SHARED
+# depending on the Qt configuration.
+# - Applies Qt specific prefixes and suffixes to file names depending on platform.
+function(_qt_internal_add_library target)
+ set(opt_args
+ STATIC
+ SHARED
+ MODULE
+ INTERFACE
+ OBJECT
+ )
+ set(single_args "")
+ set(multi_args "")
+ cmake_parse_arguments(PARSE_ARGV 1 arg "${opt_args}" "${single_args}" "${multi_args}")
+
+ set(option_type_count 0)
+ if(arg_STATIC)
+ set(type_to_create STATIC)
+ math(EXPR option_type_count "${option_type_count}+1")
+ elseif(arg_SHARED)
+ set(type_to_create SHARED)
+ math(EXPR option_type_count "${option_type_count}+1")
+ elseif(arg_MODULE)
+ set(type_to_create MODULE)
+ math(EXPR option_type_count "${option_type_count}+1")
+ elseif(arg_INTERFACE)
+ set(type_to_create INTERFACE)
+ math(EXPR option_type_count "${option_type_count}+1")
+ elseif(arg_OBJECT)
+ set(type_to_create OBJECT)
+ math(EXPR option_type_count "${option_type_count}+1")
+ endif()
+
+ if(option_type_count GREATER 1)
+ message(FATAL_ERROR
+ "Multiple type options were given. Only one should be used."
+ )
+ endif()
+
+ # If no explicit type option is set, default to the flavor of the Qt build.
+ # This in contrast to CMake which defaults to STATIC.
+ if(NOT arg_STATIC AND NOT arg_SHARED AND NOT arg_MODULE AND NOT arg_INTERFACE
+ AND NOT arg_OBJECT)
+ if(DEFINED BUILD_SHARED_LIBS AND NOT QT_BUILDING_QT AND NOT QT_BUILD_STANDALONE_TESTS)
+ __qt_internal_setup_policy(QTP0003 "6.7.0"
+ "BUILD_SHARED_LIBS is set to ${BUILD_SHARED_LIBS} but it has no effect on\
+ default library type created by Qt CMake API commands. The default library type\
+ is set to the Qt build type.\
+ This behavior can be changed by setting QTP0003 to NEW.\
+ Check https://doc.qt.io/qt-6/qt-cmake-policy-qtp0003.html for policy details."
+ )
+ qt6_policy(GET QTP0003 build_shared_libs_policy)
else()
- qt6_add_plugin(${ARGV})
+ set(build_shared_libs_policy "")
+ endif()
+
+ if(build_shared_libs_policy STREQUAL "NEW" OR QT_BUILDING_QT OR QT_BUILD_STANDALONE_TESTS)
+ if(BUILD_SHARED_LIBS OR (NOT DEFINED BUILD_SHARED_LIBS AND QT6_IS_SHARED_LIBS_BUILD))
+ set(type_to_create SHARED)
+ else()
+ set(type_to_create STATIC)
+ endif()
+ else()
+ if(QT6_IS_SHARED_LIBS_BUILD)
+ set(type_to_create SHARED)
+ else()
+ set(type_to_create STATIC)
+ endif()
endif()
+ endif()
+
+ add_library(${target} ${type_to_create} ${arg_UNPARSED_ARGUMENTS})
+ _qt_internal_disable_autorcc_zstd_when_not_supported("${target}")
+ _qt_internal_set_up_static_runtime_library(${target})
+
+ if(NOT type_to_create STREQUAL "INTERFACE" AND NOT type_to_create STREQUAL "OBJECT")
+ _qt_internal_apply_win_prefix_and_suffix("${target}")
+ endif()
+
+ if(arg_MODULE AND APPLE)
+ # CMake defaults to using .so extensions for loadable modules, aka plugins,
+ # but Qt plugins are actually suffixed with .dylib.
+ set_property(TARGET "${target}" PROPERTY SUFFIX ".dylib")
+ endif()
+
+ if(ANDROID)
+ set_property(TARGET "${target}"
+ PROPERTY _qt_android_apply_arch_suffix_called_from_qt_impl TRUE)
+ qt6_android_apply_arch_suffix("${target}")
+ endif()
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_add_library)
+ qt6_add_library(${ARGV})
endfunction()
endif()
-# By default Qt6 forces usage of utf8 sources for consumers of Qt.
-# Users can opt out of utf8 sources by calling this function with the target name of their
-# application or library.
-function(qt_disable_utf8_sources target)
+# TODO: Remove once all repositories use qt_internal_add_example instead of add_subdirectory.
+macro(_qt_internal_override_example_install_dir_to_dot)
+ # Set INSTALL_EXAMPLEDIR to ".".
+ # This overrides the install destination of unclean Qt example projects to install directly
+ # to CMAKE_INSTALL_PREFIX.
+ if(QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT)
+ set(INSTALL_EXAMPLEDIR ".")
+ set(_qt_internal_example_dir_set_to_dot TRUE)
+ endif()
+endmacro()
+
+function(qt6_allow_non_utf8_sources target)
set_target_properties("${target}" PROPERTIES QT_NO_UTF8_SOURCE TRUE)
endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_allow_non_utf8_sources)
+ qt6_allow_non_utf8_sources(${ARGV})
+ endfunction()
+endif()
+
+function(_qt_internal_apply_strict_cpp target)
+ # Disable C, Obj-C and C++ GNU extensions aka no "-std=gnu++11".
+ # Similar to mkspecs/features/default_post.prf's CONFIG += strict_cpp.
+ # Allow opt-out via variable.
+ if(NOT QT_ENABLE_CXX_EXTENSIONS)
+ get_target_property(target_type "${target}" TYPE)
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set_target_properties("${target}" PROPERTIES
+ CXX_EXTENSIONS OFF
+ C_EXTENSIONS OFF
+ OBJC_EXTENSIONS OFF
+ OBJCXX_EXTENSIONS OFF)
+ endif()
+ endif()
+endfunction()
+
+# Copies properties of the dependency to the target.
+# Arguments:
+# PROPERTIES list of properties to copy. If not specified the following properties are copied
+# by default: INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES COMPILE_DEFINITIONS
+# COMPILE_OPTIONS COMPILE_FEATURES
+# PRIVATE_ONLY copy only private properties (without INTERFACE analogues). Optional.
+# INTERFACE_ONLY copy only interface properties (without non-prefixed analogues). Optional.
+# Note: Not all properties have INTERFACE properties analogues.
+# See https://cmake.org/cmake/help/latest/prop_tgt/EXPORT_PROPERTIES.html for details.
+#
+# PRIVATE_ONLY and INTERFACE_ONLY in the same call are not allowed. Omit these options to copy
+# both sets.
+function(_qt_internal_copy_dependency_properties target dependency)
+ cmake_parse_arguments(arg "INTERFACE_ONLY;PRIVATE_ONLY" "" "PROPERTIES" ${ARGN})
+ if(arg_PRIVATE_ONLY AND arg_INTERFACE_ONLY)
+ message("Both PRIVATE_ONLY and INTERFACE_ONLY options are set.\
+Please use _qt_internal_copy_dependency_properties without these options to copy a set of
+properties of both types."
+ )
+ endif()
+
+ if(arg_PROPERTIES)
+ set(common_props_to_set ${arg_PROPERTIES})
+ else()
+ set(common_props_to_set
+ INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES
+ COMPILE_DEFINITIONS COMPILE_OPTIONS
+ COMPILE_FEATURES
+ )
+ endif()
+
+ set(props_to_set "")
+ if(NOT arg_INTERFACE_ONLY)
+ set(props_to_set ${common_props_to_set})
+ endif()
+ if(NOT arg_PRIVATE_ONLY)
+ list(TRANSFORM common_props_to_set PREPEND INTERFACE_
+ OUTPUT_VARIABLE interface_properties)
+ list(APPEND props_to_set ${interface_properties})
+ endif()
+
+ foreach(prop ${props_to_set})
+ set_property(TARGET
+ "${target}" APPEND PROPERTY
+ ${prop} "$<TARGET_PROPERTY:${dependency},${prop}>"
+ )
+ endforeach()
+endfunction()
+
+function(qt6_disable_unicode_defines target)
+ set_target_properties(${target} PROPERTIES QT_NO_UNICODE_DEFINES TRUE)
+endfunction()
+
+# Finalizer function for the top-level user projects.
+#
+# This function is currently in Technical Preview.
+# Its signature and behavior might change.
+function(qt6_finalize_project)
+ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+ message("qt6_finalize_project is called not in the top-level CMakeLists.txt.")
+ endif()
+ if(ANDROID)
+ _qt_internal_collect_apk_dependencies()
+ endif()
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ function(qt_finalize_project)
+ if(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
+ qt6_finalize_project()
+ else()
+ message(FATAL_ERROR "qt_finalize_project() is only available in Qt 6.")
+ endif()
+ endfunction()
+
+ function(qt_disable_unicode_defines)
+ qt6_disable_unicode_defines(${ARGV})
+ endfunction()
+endif()
+
+function(_qt_internal_get_deploy_impl_dir var)
+ set(${var} "${CMAKE_BINARY_DIR}/.qt" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_add_deploy_support deploy_support_file)
+ get_filename_component(deploy_support_file "${deploy_support_file}" REALPATH)
+
+ set(target ${QT_CMAKE_EXPORT_NAMESPACE}::Core)
+ get_target_property(aliased_target ${target} ALIASED_TARGET)
+ if(aliased_target)
+ set(target ${aliased_target})
+ endif()
+
+ get_property(scripts TARGET ${target} PROPERTY _qt_deploy_support_files)
+ if(NOT "${deploy_support_file}" IN_LIST scripts)
+ set_property(TARGET ${target} APPEND PROPERTY
+ _qt_deploy_support_files "${deploy_support_file}"
+ )
+ endif()
+endfunction()
+
+# Sets up the commands for use at install/deploy time
+function(_qt_internal_setup_deploy_support)
+ if(QT_SKIP_SETUP_DEPLOYMENT)
+ return()
+ endif()
+
+ get_property(cmake_role GLOBAL PROPERTY CMAKE_ROLE)
+ if(NOT cmake_role STREQUAL "PROJECT")
+ return()
+ endif()
+
+ # Always set QT_DEPLOY_SUPPORT in the caller's scope, even if we've generated
+ # the deploy support file in a previous call. The project may be calling
+ # find_package() from sibling directories with separate variable scopes.
+ _qt_internal_get_deploy_impl_dir(deploy_impl_dir)
+
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ set(QT_DEPLOY_SUPPORT "${deploy_impl_dir}/QtDeploySupport-$<CONFIG>.cmake")
+ else()
+ set(QT_DEPLOY_SUPPORT "${deploy_impl_dir}/QtDeploySupport.cmake")
+ endif()
+ set(QT_DEPLOY_SUPPORT "${QT_DEPLOY_SUPPORT}" PARENT_SCOPE)
+
+ get_property(have_generated_file GLOBAL PROPERTY _qt_have_generated_deploy_support)
+ if(have_generated_file)
+ return()
+ endif()
+ set_property(GLOBAL PROPERTY _qt_have_generated_deploy_support TRUE)
+
+ include(GNUInstallDirs)
+ set(target ${QT_CMAKE_EXPORT_NAMESPACE}::Core)
+ get_target_property(aliased_target ${target} ALIASED_TARGET)
+ if(aliased_target)
+ set(target ${aliased_target})
+ endif()
+
+ # Generate deployment information for each target if the CMake version is recent enough.
+ # The call is deferred to have all targets of the projects available.
+ if(CMAKE_VERSION GREATER_EQUAL "3.19.0")
+ if(is_multi_config)
+ set(targets_file "${deploy_impl_dir}/QtDeployTargets-$<CONFIG>.cmake")
+ else()
+ set(targets_file "${deploy_impl_dir}/QtDeployTargets.cmake")
+ endif()
+ cmake_language(EVAL CODE
+ "cmake_language(DEFER
+ DIRECTORY [[${CMAKE_SOURCE_DIR}]]
+ CALL _qt_internal_write_target_deploy_info [[${targets_file}]])"
+ )
+ _qt_internal_add_deploy_support("${targets_file}")
+ endif()
+
+ # Make sure to look under the Qt bin dir with find_program, rather than randomly picking up
+ # a deployqt tool in the system.
+ # QT6_INSTALL_PREFIX is not set during Qt build, so add the hints conditionally.
+ set(find_program_hints)
+ if(QT6_INSTALL_PREFIX)
+ set(find_program_hints HINTS ${QT6_INSTALL_PREFIX}/${QT6_INSTALL_BINS})
+ endif()
+
+ # In the generator expression logic below, we need safe_target_file because
+ # CMake evaluates expressions in both the TRUE and FALSE branches of $<IF:...>.
+ # We still need a target to give to $<TARGET_FILE:...> when we have no deploy
+ # tool, so we cannot use something like $<TARGET_FILE:macdeployqt> directly.
+ if(APPLE AND NOT IOS)
+ find_program(MACDEPLOYQT_EXECUTABLE macdeployqt
+ ${find_program_hints})
+ set(fallback "$<$<BOOL:${MACDEPLOYQT_EXECUTABLE}>:${MACDEPLOYQT_EXECUTABLE}>")
+ set(target_if_exists "$<TARGET_NAME_IF_EXISTS:${QT_CMAKE_EXPORT_NAMESPACE}::macdeployqt>")
+ set(have_deploy_tool "$<BOOL:${target_if_exists}>")
+ set(safe_target_file
+ "$<TARGET_FILE:$<IF:${have_deploy_tool},${target_if_exists},${target}>>")
+ set(__QT_DEPLOY_TOOL "$<IF:${have_deploy_tool},${safe_target_file},${fallback}>")
+ elseif(WIN32)
+ find_program(WINDEPLOYQT_EXECUTABLE windeployqt
+ ${find_program_hints})
+ set(fallback "$<$<BOOL:${WINDEPLOYQT_EXECUTABLE}>:${WINDEPLOYQT_EXECUTABLE}>")
+ set(target_if_exists "$<TARGET_NAME_IF_EXISTS:${QT_CMAKE_EXPORT_NAMESPACE}::windeployqt>")
+ set(have_deploy_tool "$<BOOL:${target_if_exists}>")
+ set(safe_target_file
+ "$<TARGET_FILE:$<IF:${have_deploy_tool},${target_if_exists},${target}>>")
+ set(__QT_DEPLOY_TOOL "$<IF:${have_deploy_tool},${safe_target_file},${fallback}>")
+ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT CMAKE_CROSSCOMPILING)
+ set(__QT_DEPLOY_TOOL "GRD")
+ else()
+ # Android is handled as a build target, not via this install-based approach.
+ # Therefore, we don't consider androiddeployqt here.
+ set(__QT_DEPLOY_TOOL "")
+ endif()
+
+ # Determine whether this is a multi-config build with a Debug configuration.
+ set(is_multi_config_build_with_debug_config FALSE)
+ get_target_property(target_is_imported ${target} IMPORTED)
+ if(target_is_imported)
+ get_target_property(target_imported_configs ${target} IMPORTED_CONFIGURATIONS)
+ list(LENGTH target_imported_configs target_imported_configs_length)
+ if(target_imported_configs_length GREATER "1"
+ AND "DEBUG" IN_LIST target_imported_configs)
+ set(is_multi_config_build_with_debug_config TRUE)
+ endif()
+ endif()
+
+ _qt_internal_add_deploy_support("${CMAKE_CURRENT_LIST_DIR}/Qt6CoreDeploySupport.cmake")
+
+ set(deploy_ignored_lib_dirs "")
+ if(__QT_DEPLOY_TOOL STREQUAL "GRD" AND NOT "${QT6_INSTALL_PREFIX}" STREQUAL "")
+ # Set up the directories we want to ignore when running file(GET_RUNTIME_DEPENDENCIES).
+ # If the Qt prefix is the root of one of those directories, don't ignore that directory.
+ # For example, if Qt's installation prefix is /usr, then we don't want to ignore /usr/lib.
+ foreach(link_dir IN LISTS CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES)
+ file(RELATIVE_PATH relative_dir "${QT6_INSTALL_PREFIX}" "${link_dir}")
+ if(relative_dir STREQUAL "")
+ # The Qt prefix is exactly ${link_dir}.
+ continue()
+ endif()
+ if(IS_ABSOLUTE "${relative_dir}" OR relative_dir MATCHES "^\\.\\./")
+ # The Qt prefix is outside of ${link_dir}.
+ list(APPEND deploy_ignored_lib_dirs "${link_dir}")
+ endif()
+ endforeach()
+ endif()
+
+ # Check whether we will have to adjust the RPATH of plugins.
+ if("${QT_DEPLOY_FORCE_ADJUST_RPATHS}" STREQUAL "")
+ set(must_adjust_plugins_rpath "")
+ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows"
+ AND NOT CMAKE_INSTALL_LIBDIR STREQUAL QT6_INSTALL_LIBS)
+ set(must_adjust_plugins_rpath ON)
+ endif()
+ else()
+ set(must_adjust_plugins_rpath "${QT_DEPLOY_FORCE_ADJUST_RPATHS}")
+ endif()
+
+ # Find the patchelf executable if necessary.
+ if(must_adjust_plugins_rpath)
+ if(CMAKE_VERSION VERSION_LESS "3.21")
+ set(QT_DEPLOY_USE_PATCHELF ON)
+ endif()
+ if(QT_DEPLOY_USE_PATCHELF)
+ find_program(QT_DEPLOY_PATCHELF_EXECUTABLE patchelf)
+ if(NOT QT_DEPLOY_PATCHELF_EXECUTABLE)
+ set(QT_DEPLOY_PATCHELF_EXECUTABLE "patchelf")
+ message(WARNING "The patchelf executable could not be located. "
+ "To use Qt's CMake deployment API, install patchelf or upgrade CMake to 3.21 "
+ "or newer.")
+ endif()
+ endif()
+ endif()
+
+ # Generate path to the target (not host) qtpaths file. Needed for windeployqt when
+ # cross-compiling from an x86_64 host to an arm64 target, so it knows which architecture
+ # libraries should be deployed.
+ if(CMAKE_HOST_WIN32)
+ if(CMAKE_CROSSCOMPILING)
+ set(qt_paths_ext ".bat")
+ else()
+ set(qt_paths_ext ".exe")
+ endif()
+ else()
+ set(qt_paths_ext "")
+ endif()
+
+
+
+ set(target_qtpaths_path "")
+ set(qtpaths_prefix "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_BINS}")
+ get_property(qt_major_version TARGET "${target}" PROPERTY INTERFACE_QT_MAJOR_VERSION)
+ if(qt_major_version)
+ set(target_qtpaths_with_major_version_path
+ "${qtpaths_prefix}/qtpaths${qt_major_version}${qt_paths_ext}")
+ if(EXISTS "${target_qtpaths_with_major_version_path}")
+ set(target_qtpaths_path "${target_qtpaths_with_major_version_path}")
+ endif()
+ endif()
+
+ if(NOT target_qtpaths_path)
+ set(target_qtpaths_path_without_version "${qtpaths_prefix}/qtpaths${qt_paths_ext}")
+ if(EXISTS "${target_qtpaths_path_without_version}")
+ set(target_qtpaths_path "${target_qtpaths_path_without_version}")
+ endif()
+ endif()
+
+ if(NOT target_qtpaths_path)
+ message(DEBUG "No qtpaths executable found for deployment purposes.")
+ endif()
+
+ file(GENERATE OUTPUT "${QT_DEPLOY_SUPPORT}" CONTENT
+"cmake_minimum_required(VERSION 3.16...3.21)
+
+# These are part of the public API. Projects should use them to provide a
+# consistent set of prefix-relative destinations.
+if(NOT QT_DEPLOY_BIN_DIR)
+ set(QT_DEPLOY_BIN_DIR \"${CMAKE_INSTALL_BINDIR}\")
+endif()
+if(NOT QT_DEPLOY_LIBEXEC_DIR)
+ set(QT_DEPLOY_LIBEXEC_DIR \"${CMAKE_INSTALL_LIBEXECDIR}\")
+endif()
+if(NOT QT_DEPLOY_LIB_DIR)
+ set(QT_DEPLOY_LIB_DIR \"${CMAKE_INSTALL_LIBDIR}\")
+endif()
+if(NOT QT_DEPLOY_PLUGINS_DIR)
+ set(QT_DEPLOY_PLUGINS_DIR \"plugins\")
+endif()
+if(NOT QT_DEPLOY_QML_DIR)
+ set(QT_DEPLOY_QML_DIR \"qml\")
+endif()
+if(NOT QT_DEPLOY_TRANSLATIONS_DIR)
+ set(QT_DEPLOY_TRANSLATIONS_DIR \"translations\")
+endif()
+if(NOT QT_DEPLOY_PREFIX)
+ set(QT_DEPLOY_PREFIX \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}\")
+endif()
+if(QT_DEPLOY_PREFIX STREQUAL \"\")
+ set(QT_DEPLOY_PREFIX .)
+endif()
+if(NOT QT_DEPLOY_IGNORED_LIB_DIRS)
+ set(QT_DEPLOY_IGNORED_LIB_DIRS \"${deploy_ignored_lib_dirs}\")
+endif()
+
+# These are internal implementation details. They may be removed at any time.
+set(__QT_DEPLOY_SYSTEM_NAME \"${CMAKE_SYSTEM_NAME}\")
+set(__QT_DEPLOY_IS_SHARED_LIBS_BUILD \"${QT6_IS_SHARED_LIBS_BUILD}\")
+set(__QT_DEPLOY_TOOL \"${__QT_DEPLOY_TOOL}\")
+set(__QT_DEPLOY_IMPL_DIR \"${deploy_impl_dir}\")
+set(__QT_DEPLOY_VERBOSE \"${QT_ENABLE_VERBOSE_DEPLOYMENT}\")
+set(__QT_CMAKE_EXPORT_NAMESPACE \"${QT_CMAKE_EXPORT_NAMESPACE}\")
+set(__QT_DEPLOY_GENERATOR_IS_MULTI_CONFIG \"${is_multi_config}\")
+set(__QT_DEPLOY_ACTIVE_CONFIG \"$<CONFIG>\")
+set(__QT_NO_CREATE_VERSIONLESS_FUNCTIONS \"${QT_NO_CREATE_VERSIONLESS_FUNCTIONS}\")
+set(__QT_DEFAULT_MAJOR_VERSION \"${QT_DEFAULT_MAJOR_VERSION}\")
+set(__QT_DEPLOY_QT_ADDITIONAL_PACKAGES_PREFIX_PATH \"${QT_ADDITIONAL_PACKAGES_PREFIX_PATH}\")
+set(__QT_DEPLOY_QT_INSTALL_PREFIX \"${QT6_INSTALL_PREFIX}\")
+set(__QT_DEPLOY_QT_INSTALL_BINS \"${QT6_INSTALL_BINS}\")
+set(__QT_DEPLOY_QT_INSTALL_DATA \"${QT6_INSTALL_DATA}\")
+set(__QT_DEPLOY_QT_INSTALL_LIBEXECS \"${QT6_INSTALL_LIBEXECS}\")
+set(__QT_DEPLOY_QT_INSTALL_PLUGINS \"${QT6_INSTALL_PLUGINS}\")
+set(__QT_DEPLOY_QT_INSTALL_TRANSLATIONS \"${QT6_INSTALL_TRANSLATIONS}\")
+set(__QT_DEPLOY_TARGET_QT_PATHS_PATH \"${target_qtpaths_path}\")
+set(__QT_DEPLOY_PLUGINS \"\")
+set(__QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH \"${must_adjust_plugins_rpath}\")
+set(__QT_DEPLOY_USE_PATCHELF \"${QT_DEPLOY_USE_PATCHELF}\")
+set(__QT_DEPLOY_PATCHELF_EXECUTABLE \"${QT_DEPLOY_PATCHELF_EXECUTABLE}\")
+set(__QT_DEPLOY_QT_IS_MULTI_CONFIG_BUILD_WITH_DEBUG \"${is_multi_config_build_with_debug_config}\")
+set(__QT_DEPLOY_QT_DEBUG_POSTFIX \"${QT6_DEBUG_POSTFIX}\")
+
+# Define the CMake commands to be made available during deployment.
+set(__qt_deploy_support_files
+ \"$<JOIN:$<TARGET_GENEX_EVAL:${target},$<TARGET_PROPERTY:${target},_qt_deploy_support_files>>,\"
+ \">\"
+)
+foreach(__qt_deploy_support_file IN LISTS __qt_deploy_support_files)
+ include(\"\${__qt_deploy_support_file}\")
+endforeach()
+
+unset(__qt_deploy_support_file)
+unset(__qt_deploy_support_files)
+")
+endfunction()
+
+# Write deployment information for the targets of the project.
+function(_qt_internal_write_target_deploy_info out_file)
+ set(targets "")
+ set(dynamic_target_types EXECUTABLE SHARED_LIBRARY MODULE_LIBRARY)
+ _qt_internal_collect_buildsystem_targets(targets
+ "${CMAKE_SOURCE_DIR}" INCLUDE ${dynamic_target_types} STATIC_LIBRARY)
+ set(content "")
+ foreach(target IN LISTS targets)
+ set(var_prefix "__QT_DEPLOY_TARGET_${target}")
+ string(APPEND content "set(${var_prefix}_FILE $<TARGET_FILE:${target}>)\n")
+ get_target_property(target_type ${target} TYPE)
+ string(APPEND content "set(${var_prefix}_TYPE ${target_type})\n")
+ if(WIN32 AND CMAKE_VERSION GREATER_EQUAL "3.21"
+ AND target_type IN_LIST dynamic_target_types)
+ string(APPEND content
+ "set(${var_prefix}_RUNTIME_DLLS $<TARGET_RUNTIME_DLLS:${target}>)\n")
+ endif()
+ endforeach()
+ file(GENERATE OUTPUT "${out_file}" CONTENT "${content}")
+endfunction()
+
+function(_qt_internal_is_examples_deployment_supported_in_current_config out_var out_var_reason)
+ # Deployment API doesn't work when examples / tests are built in-tree of a prefix qt build.
+ if(QT_BUILDING_QT AND QT_WILL_INSTALL AND NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ set(deployment_supported FALSE)
+ set(not_supported_reason "PREFIX_BUILD")
+ else()
+ set(deployment_supported TRUE)
+ set(not_supported_reason "")
+ endif()
+
+ set(${out_var} "${deployment_supported}" PARENT_SCOPE)
+ set(${out_var_reason} "${not_supported_reason}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_should_skip_deployment_api out_var out_var_reason)
+ set(skip_deployment FALSE)
+ _qt_internal_is_examples_deployment_supported_in_current_config(
+ deployment_supported
+ not_supported_reason
+ )
+
+ # Allow opting out of deployment, so that we can add deployment api to all our examples,
+ # but only run it in the CI for a select few, to avoid the overhead of deploying all examples.
+ if(QT_INTERNAL_SKIP_DEPLOYMENT OR (NOT deployment_supported))
+ set(skip_deployment TRUE)
+ endif()
+
+ set(reason "")
+ if(NOT deployment_supported)
+ set(reason "${not_supported_reason}")
+ elseif(QT_INTERNAL_SKIP_DEPLOYMENT)
+ set(reason "SKIP_REQUESTED")
+ endif()
+
+ set(${out_var} "${skip_deployment}" PARENT_SCOPE)
+ set(${out_var_reason} "${reason}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_should_skip_post_build_deployment_api out_var out_var_reason)
+ set(skip_deployment FALSE)
+ set(deployment_supported TRUE)
+
+ # Allow opting out of deployment, so that we can add deployment api to all our examples,
+ # but only run it in the CI for a select few, to avoid the overhead of deploying all examples.
+ if(QT_INTERNAL_SKIP_DEPLOYMENT OR (NOT deployment_supported))
+ set(skip_deployment TRUE)
+ endif()
+
+ set(reason "")
+ if(NOT deployment_supported)
+ set(reason "REASON_UNSPECIFIED")
+ elseif(QT_INTERNAL_SKIP_DEPLOYMENT)
+ set(reason "SKIP_REQUESTED")
+ endif()
+
+ set(${out_var} "${skip_deployment}" PARENT_SCOPE)
+ set(${out_var_reason} "${reason}" PARENT_SCOPE)
+endfunction()
+
+# Generate a deploy script that does nothing aside from showing a warning message.
+# The warning can be hidden by setting the QT_INTERNAL_HIDE_NO_OP_DEPLOYMENT_WARNING variable.
+function(_qt_internal_generate_no_op_deploy_script)
+ set(no_value_options
+ )
+ set(single_value_options
+ FUNCTION_NAME
+ NAME
+ OUTPUT_SCRIPT
+ SKIP_REASON
+ TARGET
+ )
+ set(multi_value_options
+ )
+
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ if(NOT arg_OUTPUT_SCRIPT)
+ message(FATAL_ERROR "No OUTPUT_SCRIPT option specified")
+ endif()
+ if(NOT arg_FUNCTION_NAME)
+ message(FATAL_ERROR "No FUNCTION_NAME option specified")
+ endif()
+
+ set(generate_args "")
+ if(arg_NAME)
+ list(APPEND generate_args NAME "${arg_NAME}")
+ endif()
+ if(arg_TARGET)
+ list(APPEND generate_args TARGET "${arg_TARGET}")
+ endif()
+
+ set(function_name "${arg_FUNCTION_NAME}")
+
+ # The empty space is required, otherwise
+ set(content "
+message(DEBUG \"Running no-op deployment script because QT_INTERNAL_SKIP_DEPLOYMENT was ON.\")
+")
+ if(NOT QT_INTERNAL_HIDE_NO_OP_DEPLOYMENT_WARNING AND arg_SKIP_REASON STREQUAL "PREFIX_BUILD")
+ set(content "
+message(STATUS \"${function_name}(TARGET ${arg_TARGET}) is a no-op for prefix \"
+\"non-standalone builds due to various issues. Consider using a -no-prefix build \"
+\"or qt-internal-configure-tests or qt-internal-configure-examples if you want deployment to run.\")
+")
+ endif()
+
+ qt6_generate_deploy_script(
+ ${generate_args}
+ OUTPUT_SCRIPT deploy_script
+ CONTENT "${content}")
+
+ set("${arg_OUTPUT_SCRIPT}" "${deploy_script}" PARENT_SCOPE)
+endfunction()
+
+# We basically mirror CMake's policy setup
+# A policy can be set to OLD, set to NEW or unset
+# unset is the default state
+#
+function(qt6_policy mode policy behaviorOrVariable)
+ # When building Qt, tests and examples might expect a policy to be known, but they won't be
+ # known depending on which scope or when a find_package(Module) with the respective policy
+ # is called. Check the global list of known policies to accommodate that.
+ if(QT_BUILDING_QT AND NOT DEFINED QT_KNOWN_POLICY_${policy})
+ get_property(global_known_policies GLOBAL PROPERTY _qt_global_known_policies)
+ if(policy IN_LIST global_known_policies)
+ set(QT_KNOWN_POLICY_${policy} TRUE)
+ endif()
+ endif()
+
+ if (NOT DEFINED QT_KNOWN_POLICY_${policy})
+ message(FATAL_ERROR
+ "${policy} is not a known Qt policy. Did you include the necessary Qt module?"
+ )
+ endif()
+ if (${mode} STREQUAL "SET")
+ set(behavior ${behaviorOrVariable})
+ if (${behavior} STREQUAL "NEW" OR ${behavior} STREQUAL "OLD")
+ set(__QT_INTERNAL_POLICY_${policy} ${behavior} PARENT_SCOPE)
+ else()
+ message(FATAL_ERROR "Qt policies must be either set to NEW or OLD, but got ${behavior}")
+ endif()
+ else(${mode} STREQUAL "GET")
+ set(variable "${behaviorOrVariable}")
+ set("${variable}" "${__QT_INTERNAL_POLICY_${policy}}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Internal helper function; can be used in any module before doing a policy check
+function(__qt_internal_setup_policy policy sinceversion policyexplanation)
+ if(DEFINED __QT_INTERNAL_POLICY_${policy})
+ if (__QT_INTERNAL_POLICY_${policy} STREQUAL "OLD")
+ # policy is explicitly disabled
+ message(DEPRECATION
+ "Qt policy ${policy} is set to OLD. "
+ "Support for the old behavior will be removed in a future major version of Qt."
+ )
+ endif()
+ #else: policy is already enabled, nothing to do
+ elseif (${sinceversion} VERSION_LESS_EQUAL __qt_policy_check_version)
+ # we cannot use the public function here as we want to set it in parent scope
+ set(__QT_INTERNAL_POLICY_${policy} "NEW" PARENT_SCOPE)
+ elseif(NOT "${QT_NO_SHOW_OLD_POLICY_WARNINGS}")
+ message(AUTHOR_WARNING
+ "Qt policy ${policy} is not set: "
+ "${policyexplanation} "
+ "Use the qt_policy command to set the policy and suppress this warning.\n"
+ )
+ endif()
+endfunction()
+
+# Note this needs to be a macro because it sets variables intended for the
+# calling scope.
+macro(qt6_standard_project_setup)
+ # A parent project might want to prevent child projects pulled in with
+ # add_subdirectory() from changing the parent's preferred arrangement.
+ # They can set this variable to true to effectively disable this function.
+ if(NOT QT_NO_STANDARD_PROJECT_SETUP)
+
+ set(__qt_sps_args_option)
+ set(__qt_sps_args_single
+ REQUIRES
+ SUPPORTS_UP_TO
+ I18N_SOURCE_LANGUAGE
+ I18N_NATIVE_LANGUAGE # intermediate, remove after dependencies trickled through
+ )
+ set(__qt_sps_args_multi
+ I18N_TRANSLATED_LANGUAGES
+ I18N_LANGUAGES # intermediate, remove after dependencies trickled through
+ )
+ cmake_parse_arguments(__qt_sps_arg
+ "${__qt_sps_args_option}"
+ "${__qt_sps_args_single}"
+ "${__qt_sps_args_multi}"
+ ${ARGN}
+ )
+
+ # intermediate, remove after dependencies trickled through
+ if(DEFINED arg_I18N_NATIVE_LANGUAGE)
+ set(arg_I18N_SOURCE_LANGUAGE ${arg_I18N_NATIVE_LANGUAGE})
+ endif()
+ if(DEFINED arg_I18N_LANGUAGES)
+ set(arg_I18N_TRANSLATED_LANGUAGES ${arg_I18N_LANGUAGES})
+ endif()
+
+ if(__qt_sps_arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unexpected arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+
+ # Set the Qt CMake policy based on the requested version(s)
+ set(__qt_policy_check_version "6.0.0")
+ if(Qt6_VERSION_MAJOR)
+ set(__qt_current_version
+ "${Qt6_VERSION_MAJOR}.${Qt6_VERSION_MINOR}.${Qt6_VERSION_PATCH}")
+ elseif(QT_BUILDING_QT)
+ set(__qt_current_version
+ "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+ else()
+ message(FATAL_ERROR "Can not determine Qt version.")
+ endif()
+ if(__qt_sps_arg_REQUIRES)
+ if("${__qt_current_version}" VERSION_LESS "${__qt_sps_arg_REQUIRES}")
+ message(FATAL_ERROR
+ "Project required a Qt minimum version of ${__qt_sps_arg_REQUIRES}, "
+ "but current version is only ${__qt_current_version}.")
+ endif()
+ set(__qt_policy_check_version "${__qt_sps_arg_REQUIRES}")
+ endif()
+ if(__qt_sps_arg_SUPPORTS_UP_TO)
+ if(__qt_sps_arg_REQUIRES)
+ if(${__qt_sps_arg_SUPPORTS_UP_TO} VERSION_LESS ${__qt_sps_arg_REQUIRES})
+ message(FATAL_ERROR "SUPPORTS_UP_TO must be larger than or equal to REQUIRES.")
+ endif()
+ set(__qt_policy_check_version "${__qt_sps_arg_SUPPORTS_UP_TO}")
+ else()
+ message(FATAL_ERROR "Please specify the REQUIRES as well.")
+ endif()
+ endif()
+
+ # All changes below this point should not result in a change to an
+ # existing value, except for CMAKE_INSTALL_RPATH which may append new
+ # values (but no duplicates).
+
+ # Use standard install locations, provided by GNUInstallDirs. All
+ # platforms should have this included so that we know the
+ # CMAKE_INSTALL_xxxDIR variables will be set.
+ include(GNUInstallDirs)
+ if(WIN32)
+ # Windows has no RPATH support, so we need all non-plugin DLLs in
+ # the same directory as application executables if we want to be
+ # able to run them without having to augment the PATH environment
+ # variable. Don't discard an existing value in case the project has
+ # already set this to somewhere else. Our setting is somewhat
+ # opinionated, so make it easy for projects to choose something else.
+ if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ endif()
+ elseif(NOT APPLE)
+ # Apart from Windows and Apple, most other platforms support RPATH
+ # and $ORIGIN. Make executables and non-static libraries use an
+ # install RPATH that allows them to find library dependencies if the
+ # project installs things to the directories defined by the
+ # CMAKE_INSTALL_xxxDIR variables (which is what CMake's defaults
+ # are based on).
+ file(RELATIVE_PATH __qt_relDir
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
+ )
+ list(APPEND CMAKE_INSTALL_RPATH $ORIGIN $ORIGIN/${__qt_relDir})
+ list(REMOVE_DUPLICATES CMAKE_INSTALL_RPATH)
+ unset(__qt_reldir)
+ endif()
+
+ # Turn these on by default, unless they are already set. Projects can
+ # always turn off any they really don't want after we return.
+ foreach(auto_set IN ITEMS MOC UIC)
+ if(NOT DEFINED CMAKE_AUTO${auto_set})
+ set(CMAKE_AUTO${auto_set} TRUE)
+ endif()
+ endforeach()
+
+ # Enable folder support for IDEs. CMake >= 3.26 enables USE_FOLDERS by default but this is
+ # guarded by CMake policy CMP0143.
+ get_property(__qt_use_folders GLOBAL PROPERTY USE_FOLDERS)
+ if(__qt_use_folders OR "${__qt_use_folders}" STREQUAL "")
+ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+ get_property(__qt_qt_targets_folder GLOBAL PROPERTY QT_TARGETS_FOLDER)
+ if("${__qt_qt_targets_folder}" STREQUAL "")
+ set(__qt_qt_targets_folder QtInternalTargets)
+ set_property(GLOBAL PROPERTY QT_TARGETS_FOLDER ${__qt_qt_targets_folder})
+ endif()
+ get_property(__qt_autogen_targets_folder GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER)
+ if("${__qt_autogen_targets_folder}" STREQUAL "")
+ set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER ${__qt_qt_targets_folder})
+ endif()
+ endif()
+
+ # Hide generated files in dedicated folder. Unfortunately we can't use a
+ # top level "Generated Files" folder for this, as CMake will then put the
+ # folder first in the list of folders, whereas we want to keep Sources and
+ # Headers front and center. See also _qt_internal_finalize_source_groups
+ set_property(GLOBAL PROPERTY AUTOGEN_SOURCE_GROUP "Source Files/Generated")
+
+ # Treat metatypes JSON files as generated. We propagate these INTERFACE_SOURCES,
+ # due to CMake's lack of a generic mechanism for property inheritance (see
+ # https://gitlab.kitware.com/cmake/cmake/-/issues/20416), but we don't want
+ # them to clutter up the user's project.
+ source_group("Source Files/Generated" REGULAR_EXPRESSION "(_metatypes\\.json)$")
+
+ # I18N support.
+ if(DEFINED __qt_sps_arg_I18N_TRANSLATED_LANGUAGES
+ AND NOT DEFINED QT_I18N_TRANSLATED_LANGUAGES)
+ set(QT_I18N_TRANSLATED_LANGUAGES ${__qt_sps_arg_I18N_TRANSLATED_LANGUAGES})
+ endif()
+ if(NOT DEFINED __qt_sps_arg_I18N_SOURCE_LANGUAGE)
+ set(__qt_sps_arg_I18N_SOURCE_LANGUAGE en)
+ endif()
+ if(NOT DEFINED QT_I18N_SOURCE_LANGUAGE)
+ set(QT_I18N_SOURCE_LANGUAGE ${__qt_sps_arg_I18N_SOURCE_LANGUAGE})
+ endif()
+
+ if(CMAKE_GENERATOR STREQUAL "Xcode")
+ # Ensure we always use device SDK for Xcode for single-arch Qt builds
+ set(qt_osx_arch_count 0)
+ if(QT_OSX_ARCHITECTURES)
+ list(LENGTH QT_OSX_ARCHITECTURES qt_osx_arch_count)
+ endif()
+ if(NOT qt_osx_arch_count GREATER 1 AND ${CMAKE_OSX_SYSROOT} MATCHES "^[a-z]+simulator$")
+ # Xcode expects the base SDK to be the device SDK
+ set(simulator_sysroot "${CMAKE_OSX_SYSROOT}")
+ string(REGEX REPLACE "simulator" "os" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}")
+ set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}" CACHE STRING "" FORCE)
+ set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "${simulator_sysroot}")
+ endif()
+ endif()
+ endif()
+endmacro()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ macro(qt_standard_project_setup)
+ qt6_standard_project_setup(${ARGV})
+ endmacro()
+ macro(qt_policy)
+ qt6_policy(${ARGV})
+ endmacro()
+endif()
+
+# Store in ${out_var} the i18n catalogs that belong to the passed Qt modules.
+# The catalog "qtbase" is always added to the result.
+#
+# Example:
+# _qt_internal_get_i18n_catalogs_for_modules(catalogs Quick Help)
+# catalogs -> qtbase;qtdeclarative;qt_help
+function(_qt_internal_get_i18n_catalogs_for_modules out_var)
+ set(result "qtbase")
+ set(modules "${ARGN}")
+ set(module_catalog_mapping
+ "Bluetooth|Nfc" qtconnectivity
+ "Help" qt_help
+ "Multimedia(Widgets|QuickPrivate)?" qtmultimedia
+ "Qml|Quick" qtdeclarative
+ "SerialPort" qtserialport
+ "WebEngine" qtwebengine
+ "WebSockets" qtwebsockets
+ )
+ list(LENGTH module_catalog_mapping max_i)
+ math(EXPR max_i "${max_i} - 1")
+ foreach(module IN LISTS modules)
+ foreach(i RANGE 0 ${max_i} 2)
+ list(GET module_catalog_mapping ${i} module_rex)
+ if(NOT module MATCHES "^(${module_rex})")
+ continue()
+ endif()
+ math(EXPR k "${i} + 1")
+ list(GET module_catalog_mapping ${k} catalog)
+ list(APPEND result ${catalog})
+ endforeach()
+ endforeach()
+ set("${out_var}" "${result}" PARENT_SCOPE)
+endfunction()
+
+function(qt6_generate_deploy_script)
+ set(no_value_options "")
+ set(single_value_options
+ CONTENT
+ OUTPUT_SCRIPT
+ NAME
+ TARGET
+
+ # TODO: For backward compatibility / transitional use only,
+ # remove at some point
+ FILENAME_VARIABLE
+ )
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+ if(arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unexpected arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+
+ # TODO: Remove when FILENAME_VARIABLE is fully removed
+ # Handle the slow deprecation of FILENAME_VARIABLE
+ if(arg_FILENAME_VARIABLE)
+ if(arg_OUTPUT_SCRIPT AND NOT arg_FILENAME_VARIABLE STREQUAL arg_OUTPUT_SCRIPT)
+ message(FATAL_ERROR
+ "Both FILENAME_VARIABLE and OUTPUT_SCRIPT were given and were different. "
+ "Only one of the two should be used."
+ )
+ endif()
+ message(AUTHOR_WARNING
+ "The FILENAME_VARIABLE keyword is deprecated and will be removed soon. Please use OUTPUT_SCRIPT instead.")
+ set(arg_OUTPUT_SCRIPT "${arg_FILENAME_VARIABLE}")
+ unset(arg_FILENAME_VARIABLE)
+ endif()
+
+ if(NOT arg_OUTPUT_SCRIPT)
+ message(FATAL_ERROR "OUTPUT_SCRIPT must be specified")
+ endif()
+
+ if("${arg_CONTENT}" STREQUAL "")
+ message(FATAL_ERROR "CONTENT must be specified")
+ endif()
+
+ # Check whether manual finalization is needed.
+ if(CMAKE_VERSION VERSION_LESS "3.19")
+ get_target_property(is_immediately_finalized ${arg_TARGET} _qt_is_immediately_finalized)
+ if(is_immediately_finalized)
+ message(WARNING
+ "Deployment of plugins for target '${arg_TARGET}' will not work. "
+ "Either, upgrade CMake to version 3.19 or newer, or call "
+ "qt_finalize_target(${arg_TARGET}) after generating the deployment script."
+ )
+ endif()
+ endif()
+
+ # Mark the target as "to be deployed".
+ set_property(TARGET ${arg_TARGET} PROPERTY _qt_marked_for_deployment ON)
+
+ # If the target already was finalized, maybe because it was defined in a subdirectory, generate
+ # the plugin deployment information here.
+ get_target_property(is_finalized "${arg_TARGET}" _qt_is_finalized)
+ if(is_finalized)
+ __qt_internal_generate_plugin_deployment_info(${arg_TARGET})
+ endif()
+
+ # Create a file name that will be unique for this target and the combination
+ # of arguments passed to this command. This allows the project to call us
+ # multiple times with different arguments for the same target (e.g. to
+ # create deployment scripts for different scenarios).
+ set(file_base_name "custom")
+ if(NOT "${arg_NAME}" STREQUAL "")
+ set(file_base_name "${arg_NAME}")
+ elseif(NOT "${arg_TARGET}" STREQUAL "")
+ set(file_base_name "${arg_TARGET}")
+ endif()
+ string(MAKE_C_IDENTIFIER "${file_base_name}" target_id)
+ string(SHA1 args_hash "${ARGV}")
+ string(SUBSTRING "${args_hash}" 0 10 short_hash)
+ _qt_internal_get_deploy_impl_dir(deploy_impl_dir)
+ set(deploy_script "${deploy_impl_dir}/deploy_${target_id}_${short_hash}")
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ set(config_infix "-$<CONFIG>")
+ else()
+ set(config_infix "")
+ endif()
+ string(APPEND deploy_script "${config_infix}.cmake")
+ set(${arg_OUTPUT_SCRIPT} "${deploy_script}" PARENT_SCOPE)
+
+ _qt_internal_get_i18n_catalogs_for_modules(catalogs ${QT_ALL_MODULES_FOUND_VIA_FIND_PACKAGE})
+ set(boiler_plate "include(${QT_DEPLOY_SUPPORT})
+include(\"\${CMAKE_CURRENT_LIST_DIR}/${arg_TARGET}-plugins${config_infix}.cmake\" OPTIONAL)
+set(__QT_DEPLOY_I18N_CATALOGS \"${catalogs}\")
+")
+ list(TRANSFORM arg_CONTENT REPLACE "\\$" "\$")
+ file(GENERATE OUTPUT ${deploy_script} CONTENT "${boiler_plate}${arg_CONTENT}")
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ macro(qt_generate_deploy_script)
+ if(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
+ qt6_generate_deploy_script(${ARGV})
+ else()
+ message(FATAL_ERROR "qt_generate_deploy_script() is only available in Qt 6.")
+ endif()
+ endmacro()
+endif()
+
+function(qt6_generate_deploy_app_script)
+ # We use a TARGET keyword option instead of taking the target as the first
+ # positional argument. This is to keep open the possibility of deploying
+ # an app for which we don't have a target (e.g. an application from a
+ # third party project that the caller may want to include in their own
+ # package). We would add an EXECUTABLE keyword for that, which would be
+ # mutually exclusive with the TARGET keyword.
+ set(no_value_options
+ NO_TRANSLATIONS
+ NO_COMPILER_RUNTIME
+ NO_UNSUPPORTED_PLATFORM_ERROR
+ )
+ set(single_value_options
+ TARGET
+ OUTPUT_SCRIPT
+
+ # TODO: For backward compatibility / transitional use only,
+ # remove at some point
+ FILENAME_VARIABLE
+ )
+ set(qt_deploy_runtime_dependencies_options
+ # These options are forwarded as is to qt_deploy_runtime_dependencies.
+ DEPLOY_TOOL_OPTIONS
+ PRE_INCLUDE_REGEXES
+ PRE_EXCLUDE_REGEXES
+ POST_INCLUDE_REGEXES
+ POST_EXCLUDE_REGEXES
+ POST_INCLUDE_FILES
+ POST_EXCLUDE_FILES
+ )
+ set(multi_value_options
+ ${qt_deploy_runtime_dependencies_options}
+ )
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+ if(arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unexpected arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+ if(NOT arg_TARGET)
+ message(FATAL_ERROR "TARGET must be specified")
+ endif()
+
+ # TODO: Remove when FILENAME_VARIABLE is fully removed
+ # Handle the slow deprecation of FILENAME_VARIABLE
+ if(arg_FILENAME_VARIABLE)
+ if(arg_OUTPUT_SCRIPT AND NOT arg_FILENAME_VARIABLE STREQUAL arg_OUTPUT_SCRIPT)
+ message(FATAL_ERROR
+ "Both FILENAME_VARIABLE and OUTPUT_SCRIPT were given and were different. "
+ "Only one of the two should be used."
+ )
+ endif()
+ message(AUTHOR_WARNING
+ "The FILENAME_VARIABLE keyword is deprecated and will be removed soon. Please use OUTPUT_SCRIPT instead.")
+ set(arg_OUTPUT_SCRIPT "${arg_FILENAME_VARIABLE}")
+ unset(arg_FILENAME_VARIABLE)
+ endif()
+
+ if(NOT arg_OUTPUT_SCRIPT)
+ message(FATAL_ERROR "OUTPUT_SCRIPT must be specified")
+ endif()
+
+ get_target_property(is_bundle ${arg_TARGET} MACOSX_BUNDLE)
+
+ set(unsupported_platform_extra_message "")
+ if(QT6_IS_SHARED_LIBS_BUILD)
+ set(qt_build_type_string "shared Qt libs")
+ else()
+ set(qt_build_type_string "static Qt libs")
+ endif()
+
+ if(CMAKE_CROSSCOMPILING)
+ string(APPEND qt_build_type_string ", cross-compiled")
+ endif()
+
+ if(NOT is_bundle)
+ string(APPEND qt_build_type_string ", non-bundle app")
+ set(unsupported_platform_extra_message
+ "Executable targets have to be app bundles to use this command on Apple platforms.")
+ endif()
+
+ set(generate_args
+ TARGET ${arg_TARGET}
+ OUTPUT_SCRIPT deploy_script
+ )
+
+ set(common_deploy_args "")
+ if(arg_NO_TRANSLATIONS)
+ string(APPEND common_deploy_args " NO_TRANSLATIONS\n")
+ endif()
+ if(arg_NO_COMPILER_RUNTIME)
+ string(APPEND common_deploy_args " NO_COMPILER_RUNTIME\n")
+ endif()
+
+ # Forward the arguments that are exactly the same for qt_deploy_runtime_dependencies.
+ foreach(var IN LISTS qt_deploy_runtime_dependencies_options)
+ if(NOT "${arg_${var}}" STREQUAL "")
+ list(APPEND common_deploy_args ${var} ${arg_${var}})
+ endif()
+ endforeach()
+
+ _qt_internal_should_skip_deployment_api(skip_deployment skip_reason)
+ if(skip_deployment)
+ _qt_internal_generate_no_op_deploy_script(
+ FUNCTION_NAME "qt6_generate_deploy_app_script"
+ SKIP_REASON "${skip_reason}"
+ ${generate_args}
+ )
+ elseif(APPLE AND NOT IOS AND QT6_IS_SHARED_LIBS_BUILD AND is_bundle)
+ # TODO: Consider handling non-bundle applications in the future using the generic cmake
+ # runtime dependency feature.
+ qt6_generate_deploy_script(${generate_args}
+ CONTENT "
+qt6_deploy_runtime_dependencies(
+ EXECUTABLE $<TARGET_FILE_NAME:${arg_TARGET}>.app
+${common_deploy_args})
+")
+
+ elseif(WIN32 AND QT6_IS_SHARED_LIBS_BUILD)
+ qt6_generate_deploy_script(${generate_args}
+ CONTENT "
+qt6_deploy_runtime_dependencies(
+ EXECUTABLE $<TARGET_FILE:${arg_TARGET}>
+ GENERATE_QT_CONF
+${common_deploy_args})
+")
+
+ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND QT6_IS_SHARED_LIBS_BUILD
+ AND NOT CMAKE_CROSSCOMPILING)
+ qt6_generate_deploy_script(${generate_args}
+ CONTENT "
+qt6_deploy_runtime_dependencies(
+ EXECUTABLE $<TARGET_FILE:${arg_TARGET}>
+ GENERATE_QT_CONF
+${common_deploy_args})
+")
+
+ elseif(NOT arg_NO_UNSUPPORTED_PLATFORM_ERROR AND NOT QT_INTERNAL_NO_UNSUPPORTED_PLATFORM_ERROR)
+ # Currently we don't deploy runtime dependencies if cross-compiling or using a static Qt.
+ # Error out by default unless the project opted out of the error.
+ # This provides us a migration path in the future without breaking compatibility promises.
+ message(FATAL_ERROR
+ "Support for installing runtime dependencies is not implemented for "
+ "this target platform (${CMAKE_SYSTEM_NAME}, ${qt_build_type_string}). "
+ ${unsupported_platform_extra_message}
+ )
+ else()
+ set(skip_message
+ "_qt_internal_show_skip_runtime_deploy_message(\"${qt_build_type_string}\"")
+ if(unsupported_platform_extra_message)
+ string(APPEND skip_message
+ "\n EXTRA_MESSAGE \"${unsupported_platform_extra_message}\"")
+ endif()
+ string(APPEND skip_message "\n)")
+ qt6_generate_deploy_script(${generate_args} CONTENT "${skip_message}")
+ endif()
+
+ set(${arg_OUTPUT_SCRIPT} "${deploy_script}" PARENT_SCOPE)
+endfunction()
+
+if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
+ macro(qt_generate_deploy_app_script)
+ qt6_generate_deploy_app_script(${ARGV})
+ endmacro()
+endif()
diff --git a/src/corelib/Qt6CoreResourceInit.in.cpp b/src/corelib/Qt6CoreResourceInit.in.cpp
new file mode 100644
index 0000000000..3f1757362d
--- /dev/null
+++ b/src/corelib/Qt6CoreResourceInit.in.cpp
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+// This file was generated by the qt_add_resources command.
+
+#include <QtCore/qtsymbolmacros.h>
+
+QT_DECLARE_EXTERN_RESOURCE(@RESOURCE_NAME@)
+
+namespace {
+ struct resourceReferenceKeeper {
+ resourceReferenceKeeper() { QT_KEEP_RESOURCE(@RESOURCE_NAME@) }
+ } resourceReferenceKeeperInstance;
+}
diff --git a/src/corelib/Qt6ModuleLocation.cmake.in b/src/corelib/Qt6ModuleLocation.cmake.in
deleted file mode 100644
index cf70f6bc0e..0000000000
--- a/src/corelib/Qt6ModuleLocation.cmake.in
+++ /dev/null
@@ -1,15 +0,0 @@
-!!IF !isEmpty(_QMAKE_SUPER_CACHE_)
-get_filename_component(_qt5_root_dir \"${CMAKE_CURRENT_LIST_DIR}/../../../..\" ABSOLUTE)
-
-file(GLOB qtmodules ${_qt5_root_dir} "${_qt5_root_dir}/*")
-foreach(qtmodule ${qtmodules})
- if(IS_DIRECTORY ${qtmodule})
- list(APPEND _qt5_module_paths "${qtmodule}" "${qtmodule}/lib/cmake")
- endif()
-endforeach()
-!!ELSE
-set(_qt5_root_dir ${_qt5_install_prefix})
-set(_qt5_module_paths ${_qt5_install_prefix})
-!!ENDIF
-
-set(_qt5_module_location_template ${_qt5_root_dir})
diff --git a/src/corelib/Qt6ModuleLocationForInstall.cmake.in b/src/corelib/Qt6ModuleLocationForInstall.cmake.in
deleted file mode 100644
index 8751e4acbc..0000000000
--- a/src/corelib/Qt6ModuleLocationForInstall.cmake.in
+++ /dev/null
@@ -1,6 +0,0 @@
-set(_qt5_root_dir ${_qt5_install_prefix})
-set(_qt5_module_paths ${_qt5_install_prefix})
-
-set(_qt5_at "@")
-set(_qt5_module_location_template ${_qt5_install_prefix}/Qt5${_qt5_at}module${_qt5_at}/Qt5${_qt5_at}module${_qt5_at}Config.cmake)
-unset(_qt5_at)
diff --git a/src/corelib/Qt6WasmMacros.cmake b/src/corelib/Qt6WasmMacros.cmake
new file mode 100644
index 0000000000..1de6e5448c
--- /dev/null
+++ b/src/corelib/Qt6WasmMacros.cmake
@@ -0,0 +1,140 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Copy in Qt HTML/JS launch files for apps.
+function(_qt_internal_wasm_add_target_helpers target)
+
+ _qt_test_emscripten_version()
+ get_target_property(targetType "${target}" TYPE)
+ if("${targetType}" STREQUAL "EXECUTABLE")
+
+ if(QT6_INSTALL_PREFIX)
+ set(WASM_BUILD_DIR "${QT6_INSTALL_PREFIX}")
+ elseif(QT_BUILD_DIR)
+ set(WASM_BUILD_DIR "${QT_BUILD_DIR}")
+ endif()
+
+ get_target_property(output_name ${target} OUTPUT_NAME)
+ if(output_name)
+ set(_target_output_name "${output_name}")
+ else()
+ set(_target_output_name "${target}")
+ endif()
+
+ set(APPNAME ${_target_output_name})
+ _qt_internal_wasm_export_name_for_target(_export_name ${target})
+ set(APPEXPORTNAME ${_export_name})
+
+ # Shared library builds preload plugins and qml imports by default.
+ # The json files are generated by scripts in qtbase/util/wasm/preload
+ if (QT_FEATURE_shared)
+ set(PRELOAD "preload: ['qt_plugins.json', 'qt_qml_imports.json'],")
+ else()
+ set(PRELOAD "")
+ endif()
+
+ get_target_property(target_output_directory ${target} RUNTIME_OUTPUT_DIRECTORY)
+
+ get_target_property(is_test ${target} _qt_is_test_executable)
+ get_target_property(is_manual_test ${target} _qt_is_manual_test)
+ if(is_test AND NOT is_manual_test)
+ # Keep in sync with testrunner_files in testlib/CMakeLists.txt
+ configure_file("${WASM_BUILD_DIR}/libexec/batchedtestrunner.html"
+ "${target_output_directory}/${_target_output_name}.html" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/qtestoutputreporter.css"
+ "${target_output_directory}/qtestoutputreporter.css" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/batchedtestrunner.js"
+ "${target_output_directory}/batchedtestrunner.js" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/emrunadapter.js"
+ "${target_output_directory}/emrunadapter.js" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/qwasmjsruntime.js"
+ "${target_output_directory}/qwasmjsruntime.js" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/qwasmtestmain.js"
+ "${target_output_directory}/qwasmtestmain.js" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/qtestoutputreporter.js"
+ "${target_output_directory}/qtestoutputreporter.js" COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/libexec/util.js"
+ "${target_output_directory}/util.js" COPYONLY)
+ else()
+ if(target_output_directory)
+ set(_target_directory "${target_output_directory}")
+ else()
+ set(_target_directory "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
+
+ configure_file("${WASM_BUILD_DIR}/plugins/platforms/wasm_shell.html"
+ "${_target_directory}/${_target_output_name}.html" @ONLY)
+ configure_file("${WASM_BUILD_DIR}/plugins/platforms/qtloader.js"
+ ${_target_directory}/qtloader.js COPYONLY)
+ configure_file("${WASM_BUILD_DIR}/plugins/platforms/qtlogo.svg"
+ ${_target_directory}/qtlogo.svg COPYONLY)
+ endif()
+
+ if(QT_FEATURE_thread)
+ set(POOL_SIZE 4)
+ get_target_property(_tmp_poolSize "${target}" QT_WASM_PTHREAD_POOL_SIZE)
+ if(_tmp_poolSize)
+ set(POOL_SIZE ${_tmp_poolSize})
+ elseif(DEFINED QT_WASM_PTHREAD_POOL_SIZE)
+ set(POOL_SIZE ${QT_WASM_PTHREAD_POOL_SIZE})
+ endif()
+ target_link_options("${target}" PRIVATE "SHELL:-s PTHREAD_POOL_SIZE=${POOL_SIZE}")
+ message(DEBUG "Setting PTHREAD_POOL_SIZE to ${POOL_SIZE} for ${target}")
+ endif()
+
+ # Set initial memory size, either from user setting or to a minimum amount required by Qt.
+ get_target_property(_tmp_initialMemory "${target}" QT_WASM_INITIAL_MEMORY)
+ if(_tmp_initialMemory)
+ set(QT_WASM_INITIAL_MEMORY "${_tmp_initialMemory}")
+ elseif(NOT DEFINED QT_WASM_INITIAL_MEMORY)
+ set(QT_WASM_INITIAL_MEMORY "50MB")
+ endif()
+ target_link_options("${target}" PRIVATE "SHELL:-s INITIAL_MEMORY=${QT_WASM_INITIAL_MEMORY}")
+
+ # Set maximum memory size, either from user setting or to 4GB (the 32-bit maximum)
+ get_target_property(_tmp_maximumMemory "${target}" QT_WASM_MAXIMUM_MEMORY)
+ if(_tmp_maximumMemory)
+ set(QT_WASM_MAXIMUM_MEMORY "${_tmp_maximumMemory}")
+ elseif(NOT DEFINED QT_WASM_MAXIMUM_MEMORY)
+ set(QT_WASM_MAXIMUM_MEMORY "4GB")
+ endif()
+ target_link_options("${target}" PRIVATE "SHELL:-s MAXIMUM_MEMORY=${QT_WASM_MAXIMUM_MEMORY}")
+
+ endif()
+endfunction()
+
+function(_qt_internal_add_wasm_extra_exported_methods target)
+ get_target_property(wasm_extra_exported_methods "${target}" QT_WASM_EXTRA_EXPORTED_METHODS)
+
+ set(wasm_default_exported_methods "UTF16ToString,stringToUTF16,JSEvents,specialHTMLTargets,FS,callMain")
+
+ if(NOT wasm_extra_exported_methods)
+ set(wasm_extra_exported_methods ${QT_WASM_EXTRA_EXPORTED_METHODS})
+ endif()
+
+ if(wasm_extra_exported_methods)
+ target_link_options("${target}" PRIVATE
+ "SHELL:-s EXPORTED_RUNTIME_METHODS=${wasm_default_exported_methods},${wasm_extra_exported_methods}"
+ )
+ else()
+ # an errant dangling comma will break this
+ target_link_options("${target}" PRIVATE
+ "SHELL:-s EXPORTED_RUNTIME_METHODS=${wasm_default_exported_methods}"
+ )
+ endif()
+endfunction()
+
+function(_qt_internal_set_wasm_export_name target)
+ _qt_internal_wasm_export_name_for_target(export_name ${target})
+ target_link_options("${target}" PRIVATE "SHELL:-s EXPORT_NAME=${export_name}")
+endfunction()
+
+function(_qt_internal_wasm_export_name_for_target out target)
+ get_target_property(export_name "${target}" QT_WASM_EXPORT_NAME)
+ if(export_name)
+ set(${out} "${export_name}" PARENT_SCOPE)
+ else()
+ string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" target "${target}")
+ set(${out} "${target}_entry" PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/src/corelib/QtCompressMimeDatabase.cmake b/src/corelib/QtCompressMimeDatabase.cmake
new file mode 100644
index 0000000000..718d330f28
--- /dev/null
+++ b/src/corelib/QtCompressMimeDatabase.cmake
@@ -0,0 +1,156 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+cmake_minimum_required(VERSION 3.16)
+
+get_filename_component(output_directory "${OUTPUT_FILE}" DIRECTORY)
+file(MAKE_DIRECTORY "${output_directory}")
+
+find_program(xmlstarlet NAMES xmlstarlet xml)
+if(xmlstarlet)
+ set(XML_STARLET_COMMAND COMMAND "${xmlstarlet}" sel -D -B -t -c / "${INPUT_FILE}")
+else()
+ get_filename_component(mime_types_resource_filename "${INPUT_FILE}" NAME)
+ message(STATUS "xmlstarlet command was not found. ${mime_types_resource_filename}"
+ " will not be minified.")
+endif()
+
+# The function tries to minify 'input_file' using the globally defined 'XML_STARLET_COMMAND'.
+# Sets the full path of the output file to the 'out_var' argument. If 'XML_STARLET_COMMAND' fails
+# to minify the 'input_file', 'out_var' is set to 'input_file'.
+function(try_minify_xml out_var input_file output_directory)
+ get_filename_component(output_filename "${input_file}" NAME)
+ set(minified_output "${output_directory}/${output_filename}")
+
+ # Assume XML_STARLET_COMMAND is globally defined.
+ if(XML_STARLET_COMMAND)
+ execute_process(${XML_STARLET_COMMAND}
+ OUTPUT_FILE "${minified_output}"
+ RESULT_VARIABLE failed_to_minify
+ )
+ if(NOT failed_to_minify)
+ set(${out_var} "${minified_output}" PARENT_SCOPE)
+ return()
+ endif()
+ endif()
+ set(${out_var} "${input_file}" PARENT_SCOPE)
+endfunction()
+
+unset(archive_command)
+
+if(COMPRESSION_TYPE STREQUAL "none")
+ try_minify_xml(qmimeprovider_db_data_file "${INPUT_FILE}" "${output_directory}")
+else()
+ # CMake versions less than 3.26 don't support the value of the zstd compression level higher
+ # than 9. We want zstd to compress with level 19 if it's possible, so if zstd executable is
+ # found on a file system we prefer to use the 'External' archiving API instead of the CMake API.
+ # See for details: https://gitlab.kitware.com/cmake/cmake/-/issues/24160
+ if(COMPRESSION_TYPE STREQUAL "zstd" AND CMAKE_VERSION VERSION_LESS 3.26)
+ find_program(archive_command NAMES zstd zstd.exe)
+ if(archive_command)
+ set(ARCHIVING_API "External")
+ endif()
+ endif()
+
+ set(qmimeprovider_db_data_file "${OUTPUT_FILE}.archive")
+ if(ARCHIVING_API STREQUAL "External")
+ message(STATUS "Using external archive command to compress the mime type database")
+ if(COMPRESSION_TYPE STREQUAL "zstd")
+ find_program(archive_command NAMES zstd zstd.exe)
+ if(archive_command)
+ set(archive_command_args -cq19 -T1)
+ else()
+ message(WARNING
+ "Unable to use the preffered ${COMPRESSION_TYPE} compression for the mime type database."
+ " ${COMPRESSION_TYPE} binary is not found. Trying gzip.")
+ endif()
+ endif()
+ if(NOT archive_command)
+ # Trying to use gzip if zstd is binary is not found.
+ set(COMPRESSION_TYPE "gzip")
+ find_program(archive_command NAMES gzip gzip.exe)
+ set(archive_command_args -nc9)
+ endif()
+ if(archive_command)
+ if(NOT XML_STARLET_COMMAND)
+ set(intput_file_arg INPUT_FILE "${INPUT_FILE}")
+ endif()
+ execute_process(${XML_STARLET_COMMAND}
+ COMMAND ${archive_command}
+ ${archive_command_args}
+ ${intput_file_arg}
+ OUTPUT_FILE "${qmimeprovider_db_data_file}"
+ RESULTS_VARIABLE results
+ ERROR_VARIABLE error_string
+ )
+
+ foreach(result IN LISTS results)
+ if(NOT result EQUAL 0)
+ message(WARNING "Unable to compress mime type database: ${error_string}")
+ endif()
+ endforeach()
+ else()
+ message(WARNING "Unable to find ${COMPRESSION_TYPE} binary."
+ " Please make sure that the ${COMPRESSION_TYPE} binary is in PATH."
+ " Adding the uncompressed mime type database.")
+ set(COMPRESSION_TYPE "none")
+ set(qmimeprovider_db_data_file "${INPUT_FILE}")
+ endif()
+ else()
+ message(STATUS "Using CMake archive command to compress the mime type database")
+
+ try_minify_xml(mimetypes_resource_file_minified "${INPUT_FILE}" "${output_directory}")
+
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.26 AND COMPRESSION_TYPE STREQUAL "zstd")
+ set(additional_file_archive_create_parameters COMPRESSION_LEVEL 19)
+ elseif(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
+ set(additional_file_archive_create_parameters COMPRESSION_LEVEL 9)
+ endif()
+
+ if(COMPRESSION_TYPE STREQUAL "gzip")
+ set(cmake_compression_type "GZip")
+ elseif(COMPRESSION_TYPE STREQUAL "zstd")
+ set(cmake_compression_type "Zstd")
+ endif()
+
+ file(ARCHIVE_CREATE OUTPUT "${qmimeprovider_db_data_file}"
+ PATHS "${mimetypes_resource_file_minified}"
+ FORMAT raw
+ COMPRESSION ${cmake_compression_type}
+ ${additional_file_archive_create_parameters}
+ )
+ if(NOT mimetypes_resource_file_minified STREQUAL INPUT_FILE)
+ file(REMOVE "${mimetypes_resource_file_minified}")
+ endif()
+ endif()
+endif()
+file(READ "${qmimeprovider_db_data_file}" qmime_db_data HEX)
+file(SIZE "${qmimeprovider_db_data_file}" qmime_db_data_size)
+if(NOT qmimeprovider_db_data_file STREQUAL INPUT_FILE)
+ file(SIZE "${INPUT_FILE}" qmime_db_resource_size)
+ file(REMOVE "${qmimeprovider_db_data_file}")
+else()
+ set(qmime_db_resource_size ${qmime_db_data_size})
+endif()
+
+string(REGEX MATCHALL "([a-f0-9][a-f0-9])" qmime_db_hex "${qmime_db_data}")
+
+list(TRANSFORM qmime_db_hex PREPEND "0x")
+math(EXPR qmime_db_data_size "${qmime_db_data_size} - 1")
+foreach(index RANGE 0 ${qmime_db_data_size} 12)
+ list(APPEND index_list ${index})
+endforeach()
+list(TRANSFORM qmime_db_hex PREPEND "\n " AT ${index_list})
+list(JOIN qmime_db_hex ", " qmime_db_hex_joined)
+
+if(NOT COMPRESSION_TYPE STREQUAL "none")
+ string(TOUPPER "${COMPRESSION_TYPE}" compression_type_upper)
+ set(qmime_db_content "#define MIME_DATABASE_IS_${compression_type_upper}\n")
+endif()
+string(APPEND qmime_db_content
+ "static const unsigned char mimetype_database[] = {"
+ "${qmime_db_hex_joined}"
+ "\n};\n"
+ "static constexpr size_t MimeTypeDatabaseOriginalSize = ${qmime_db_resource_size};\n"
+)
+
+file(WRITE "${OUTPUT_FILE}" "${qmime_db_content}")
diff --git a/src/corelib/QtCore.dynlist b/src/corelib/QtCore.dynlist
index 51e4c5a34e..cefd7aef37 100644
--- a/src/corelib/QtCore.dynlist
+++ b/src/corelib/QtCore.dynlist
@@ -1,8 +1,6 @@
{
extern "C" {
"qt_startup_hook";
- "qt_addObject";
- "qt_removeObject";
};
extern "C++" {
"QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)";
diff --git a/src/corelib/animation/animation.pri b/src/corelib/animation/animation.pri
deleted file mode 100644
index cb7850c7d6..0000000000
--- a/src/corelib/animation/animation.pri
+++ /dev/null
@@ -1,25 +0,0 @@
-# Qt core animation module
-
-HEADERS += \
- animation/qabstractanimation.h \
- animation/qabstractanimation_p.h \
- animation/qvariantanimation.h \
- animation/qvariantanimation_p.h \
- animation/qpropertyanimation.h \
- animation/qpropertyanimation_p.h \
- animation/qanimationgroup.h \
- animation/qanimationgroup_p.h \
- animation/qsequentialanimationgroup.h \
- animation/qsequentialanimationgroup_p.h \
- animation/qparallelanimationgroup.h \
- animation/qparallelanimationgroup_p.h \
- animation/qpauseanimation.h
-
-SOURCES += \
- animation/qabstractanimation.cpp \
- animation/qvariantanimation.cpp \
- animation/qpropertyanimation.cpp \
- animation/qanimationgroup.cpp \
- animation/qsequentialanimationgroup.cpp \
- animation/qparallelanimationgroup.cpp \
- animation/qpauseanimation.cpp
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index b7136dc055..9687af0987 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QAbstractAnimation
@@ -149,7 +113,6 @@
#include "qabstractanimation_p.h"
#include <QtCore/qmath.h>
-#include <QtCore/qthreadstorage.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qpointer.h>
#include <QtCore/qscopedvaluerollback.h>
@@ -214,12 +177,10 @@ typedef QList<QAbstractAnimation*>::ConstIterator AnimationListConstIt;
QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer.
*/
-Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
-
QUnifiedTimer::QUnifiedTimer() :
QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false),
- startTimersPending(false), stopTimerPending(false),
+ startTimersPending(false), stopTimerPending(false), allowNegativeDelta(false),
slowdownFactor(5.0f), profilerCallback(nullptr),
driverStartTime(0), temporalDrift(0)
{
@@ -227,15 +188,18 @@ QUnifiedTimer::QUnifiedTimer() :
driver = &defaultDriver;
}
+QUnifiedTimer::~QUnifiedTimer()
+ = default;
QUnifiedTimer *QUnifiedTimer::instance(bool create)
{
QUnifiedTimer *inst;
- if (create && !unifiedTimer()->hasLocalData()) {
+ static thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer;
+ if (create && !unifiedTimer) {
inst = new QUnifiedTimer;
- unifiedTimer()->setLocalData(inst);
+ unifiedTimer.reset(inst);
} else {
- inst = unifiedTimer() ? unifiedTimer()->localData() : 0;
+ inst = unifiedTimer.get();
}
return inst;
}
@@ -248,7 +212,7 @@ QUnifiedTimer *QUnifiedTimer::instance()
void QUnifiedTimer::maybeUpdateAnimationsToCurrentTime()
{
if (elapsed() - lastTick > 50)
- updateAnimationTimers(-1);
+ updateAnimationTimers();
}
qint64 QUnifiedTimer::elapsed() const
@@ -290,13 +254,13 @@ void QUnifiedTimer::stopAnimationDriver()
driver->stop();
}
-void QUnifiedTimer::updateAnimationTimers(qint64 currentTick)
+void QUnifiedTimer::updateAnimationTimers()
{
//setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
- if(insideTick)
+ if (insideTick)
return;
- qint64 totalElapsed = currentTick > 0 ? currentTick : elapsed();
+ const qint64 totalElapsed = elapsed();
// ignore consistentTiming in case the pause timer is active
qint64 delta = (consistentTiming && !pauseTimer.isActive()) ?
@@ -315,11 +279,11 @@ void QUnifiedTimer::updateAnimationTimers(qint64 currentTick)
// when the CPU load is high
//* it might happen in some cases that the delta is negative because the animation driver
// advances faster than time.elapsed()
- if (delta > 0) {
+ if (delta != 0 && (allowNegativeDelta || delta > 0)) {
QScopedValueRollback<bool> guard(insideTick, true);
if (profilerCallback)
profilerCallback(delta);
- for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.count(); ++currentAnimationIdx) {
+ for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.size(); ++currentAnimationIdx) {
QAbstractAnimationTimer *animation = animationTimers.at(currentAnimationIdx);
animation->updateAnimationsTime(delta);
}
@@ -330,7 +294,7 @@ void QUnifiedTimer::updateAnimationTimers(qint64 currentTick)
int QUnifiedTimer::runningAnimationCount()
{
int count = 0;
- for (int i = 0; i < animationTimers.count(); ++i)
+ for (int i = 0; i < animationTimers.size(); ++i)
count += animationTimers.at(i)->runningAnimationCount();
return count;
}
@@ -345,7 +309,7 @@ void QUnifiedTimer::localRestart()
if (insideRestart)
return;
- if (!pausedAnimationTimers.isEmpty() && (animationTimers.count() + animationTimersToStart.count() == pausedAnimationTimers.count())) {
+ if (!pausedAnimationTimers.isEmpty() && (animationTimers.size() + animationTimersToStart.size() == pausedAnimationTimers.size())) {
driver->stop();
int closestTimeToFinish = closestPausedAnimationTimerTimeToFinish();
// use a precise timer if the pause will be short
@@ -363,7 +327,7 @@ void QUnifiedTimer::restart()
{
{
QScopedValueRollback<bool> guard(insideRestart, true);
- for (int i = 0; i < animationTimers.count(); ++i)
+ for (int i = 0; i < animationTimers.size(); ++i)
animationTimers.at(i)->restartAnimationTimer();
}
@@ -423,7 +387,7 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event)
if (event->timerId() == pauseTimer.timerId()) {
// update current time on all timers
- updateAnimationTimers(-1);
+ updateAnimationTimers();
restart();
}
}
@@ -517,6 +481,8 @@ void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d)
if (running)
stopAnimationDriver();
driver = d;
+ if (driver)
+ allowNegativeDelta = driver->property("allowNegativeDelta").toBool();
if (running)
startAnimationDriver();
}
@@ -532,6 +498,7 @@ void QUnifiedTimer::uninstallAnimationDriver(QAnimationDriver *d)
if (running)
stopAnimationDriver();
driver = &defaultDriver;
+ allowNegativeDelta = false;
if (running)
startAnimationDriver();
}
@@ -545,10 +512,6 @@ bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d)
return d == driver && driver != &defaultDriver;
}
-#if QT_CONFIG(thread)
-Q_GLOBAL_STATIC(QThreadStorage<QAnimationTimer *>, animationTimer)
-#endif
-
QAnimationTimer::QAnimationTimer() :
QAbstractAnimationTimer(), lastTick(0),
currentAnimationIdx(0), insideTick(false),
@@ -557,15 +520,19 @@ QAnimationTimer::QAnimationTimer() :
{
}
+QAnimationTimer::~QAnimationTimer()
+ = default;
+
QAnimationTimer *QAnimationTimer::instance(bool create)
{
QAnimationTimer *inst;
#if QT_CONFIG(thread)
- if (create && !animationTimer()->hasLocalData()) {
+ static thread_local std::unique_ptr<QAnimationTimer> animationTimer;
+ if (create && !animationTimer) {
inst = new QAnimationTimer;
- animationTimer()->setLocalData(inst);
+ animationTimer.reset(inst);
} else {
- inst = animationTimer() ? animationTimer()->localData() : 0;
+ inst = animationTimer.get();
}
#else
Q_UNUSED(create);
@@ -585,7 +552,7 @@ void QAnimationTimer::ensureTimerUpdate()
QAnimationTimer *inst = QAnimationTimer::instance(false);
QUnifiedTimer *instU = QUnifiedTimer::instance(false);
if (instU && inst && inst->isPaused)
- instU->updateAnimationTimers(-1);
+ instU->updateAnimationTimers();
}
void QAnimationTimer::updateAnimationsTime(qint64 delta)
@@ -601,7 +568,7 @@ void QAnimationTimer::updateAnimationsTime(qint64 delta)
//when the CPU load is high
if (delta) {
QScopedValueRollback<bool> guard(insideTick, true);
- for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
+ for (currentAnimationIdx = 0; currentAnimationIdx < animations.size(); ++currentAnimationIdx) {
QAbstractAnimation *animation = animations.at(currentAnimationIdx);
int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
+ (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
@@ -772,68 +739,33 @@ QAnimationDriver::~QAnimationDriver()
uninstall();
}
-
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- Sets the time at which an animation driver should start at.
-
- This is to take into account that pauses can occur in running
- animations which will stop the driver, but the time still
- increases.
-
- \obsolete
-
- This logic is now handled internally in the animation system.
- */
-void QAnimationDriver::setStartTime(qint64)
-{
-}
-
-/*!
- Returns the start time of the animation.
-
- \obsolete
-
- This logic is now handled internally in the animation system.
- */
-qint64 QAnimationDriver::startTime() const
-{
- return 0;
-}
-#endif
-
-
/*!
- Advances the animation based to the specified \a timeStep. This function should
- be continuously called by the driver subclasses while the animation is running.
-
- If \a timeStep is positive, it will be used as the current time in the
- calculations; otherwise, the current clock time will be used.
+ Advances the animation. This function should be continuously called by
+ the driver subclasses while the animation is running.
- Since 5.4, the timeStep argument is ignored and elapsed() will be
- used instead in combination with the internal time offsets of the
- animation system.
+ The calculation of the new current time will use elapsed() in combination
+ with the internal time offsets of the animation system.
*/
-void QAnimationDriver::advanceAnimation(qint64 timeStep)
+void QAnimationDriver::advanceAnimation()
{
QUnifiedTimer *instance = QUnifiedTimer::instance();
// update current time on all top level animations
- instance->updateAnimationTimers(timeStep);
+ instance->updateAnimationTimers();
instance->restart();
}
/*!
- Advances the animation. This function should be continously called
+ Advances the animation. This function should be continuously called
by the driver while the animation is running.
*/
void QAnimationDriver::advance()
{
- advanceAnimation(-1);
+ advanceAnimation();
}
@@ -924,8 +856,14 @@ qint64 QAnimationDriver::elapsed() const
QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
: QAnimationDriver(nullptr), m_unified_timer(timer)
{
- connect(this, SIGNAL(started()), this, SLOT(startTimer()));
- connect(this, SIGNAL(stopped()), this, SLOT(stopTimer()));
+ connect(this, &QAnimationDriver::started, this, &QDefaultAnimationDriver::startTimer);
+ connect(this, &QAnimationDriver::stopped, this, &QDefaultAnimationDriver::stopTimer);
+}
+
+QDefaultAnimationDriver::~QDefaultAnimationDriver()
+{
+ disconnect(this, &QAnimationDriver::started, this, &QDefaultAnimationDriver::startTimer);
+ disconnect(this, &QAnimationDriver::stopped, this, &QDefaultAnimationDriver::stopTimer);
}
void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
@@ -946,18 +884,33 @@ void QDefaultAnimationDriver::stopTimer()
m_timer.stop();
}
+QAnimationDriverPrivate::QAnimationDriverPrivate()
+ = default;
+
+QAnimationDriverPrivate::~QAnimationDriverPrivate()
+ = default;
+
+QAbstractAnimationTimer::QAbstractAnimationTimer()
+ = default;
+
+QAbstractAnimationTimer::~QAbstractAnimationTimer()
+ = default;
+QAbstractAnimationPrivate::QAbstractAnimationPrivate()
+ = default;
+
+QAbstractAnimationPrivate::~QAbstractAnimationPrivate() { }
void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
{
Q_Q(QAbstractAnimation);
- if (state == newState)
+ const QAbstractAnimation::State oldState = state.valueBypassingBindings();
+ if (oldState == newState)
return;
if (loopCount == 0)
return;
- QAbstractAnimation::State oldState = state;
int oldCurrentTime = currentTime;
int oldCurrentLoop = currentLoop;
QAbstractAnimation::Direction oldDirection = direction;
@@ -965,14 +918,17 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
// check if we should Rewind
if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
&& oldState == QAbstractAnimation::Stopped) {
+ const int oldTotalCurrentTime = totalCurrentTime;
//here we reset the time if needed
//we don't call setCurrentTime because this might change the way the animation
//behaves: changing the state or changing the current value
totalCurrentTime = currentTime = (direction == QAbstractAnimation::Forward) ?
0 : (loopCount == -1 ? q->duration() : q->totalDuration());
+ if (totalCurrentTime != oldTotalCurrentTime)
+ totalCurrentTime.notify();
}
- state = newState;
+ state.setValueBypassingBindings(newState);
QPointer<QAbstractAnimation> guard(q);
//(un)registration of the animation must always happen before calls to
@@ -988,12 +944,15 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
}
q->updateState(newState, oldState);
- if (!guard || newState != state) //this is to be safe if updateState changes the state
+ //this is to be safe if updateState changes the state
+ if (!guard || newState != state.valueBypassingBindings())
return;
// Notify state change
+ state.notify();
emit q->stateChanged(newState, oldState);
- if (!guard || newState != state) //this is to be safe if updateState changes the state
+ //this is to be safe if updateState changes the state
+ if (!guard || newState != state.valueBypassingBindings())
return;
switch (state) {
@@ -1063,6 +1022,7 @@ QAbstractAnimation::~QAbstractAnimation()
if (d->state != Stopped) {
QAbstractAnimation::State oldState = d->state;
d->state = Stopped;
+ d->state.notify();
emit stateChanged(d->state, oldState);
if (oldState == QAbstractAnimation::Running)
QAnimationTimer::unregisterAnimation(this);
@@ -1078,6 +1038,11 @@ QAbstractAnimation::~QAbstractAnimation()
This property describes the current state of the animation. When the
animation state changes, QAbstractAnimation emits the stateChanged()
signal.
+
+ \note State updates might cause updates of the currentTime property,
+ which, in turn, can cancel its bindings. So be careful when setting
+ bindings to the currentTime property, when you expect the state of the
+ animation to change.
*/
QAbstractAnimation::State QAbstractAnimation::state() const
{
@@ -1085,6 +1050,12 @@ QAbstractAnimation::State QAbstractAnimation::state() const
return d->state;
}
+QBindable<QAbstractAnimation::State> QAbstractAnimation::bindableState() const
+{
+ Q_D(const QAbstractAnimation);
+ return &d->state;
+}
+
/*!
If this animation is part of a QAnimationGroup, this function returns a
pointer to the group; otherwise, it returns \nullptr.
@@ -1150,9 +1121,13 @@ QAbstractAnimation::Direction QAbstractAnimation::direction() const
void QAbstractAnimation::setDirection(Direction direction)
{
Q_D(QAbstractAnimation);
- if (d->direction == direction)
+ if (d->direction == direction) {
+ d->direction.removeBindingUnlessInWrapper();
return;
+ }
+ const QScopedPropertyUpdateGroup guard;
+ const int oldCurrentLoop = d->currentLoop;
if (state() == Stopped) {
if (direction == Backward) {
d->currentTime = duration();
@@ -1175,7 +1150,15 @@ void QAbstractAnimation::setDirection(Direction direction)
// needed to update the timer interval in case of a pause animation
QAnimationTimer::updateAnimationTimer();
- emit directionChanged(direction);
+ if (d->currentLoop != oldCurrentLoop)
+ d->currentLoop.notify();
+ d->direction.notify();
+}
+
+QBindable<QAbstractAnimation::Direction> QAbstractAnimation::bindableDirection()
+{
+ Q_D(QAbstractAnimation);
+ return &d->direction;
}
/*!
@@ -1210,6 +1193,12 @@ void QAbstractAnimation::setLoopCount(int loopCount)
d->loopCount = loopCount;
}
+QBindable<int> QAbstractAnimation::bindableLoopCount()
+{
+ Q_D(QAbstractAnimation);
+ return &d->loopCount;
+}
+
/*!
\property QAbstractAnimation::currentLoop
\brief the current loop of the animation
@@ -1229,6 +1218,12 @@ int QAbstractAnimation::currentLoop() const
return d->currentLoop;
}
+QBindable<int> QAbstractAnimation::bindableCurrentLoop() const
+{
+ Q_D(const QAbstractAnimation);
+ return &d->currentLoop;
+}
+
/*!
\fn virtual int QAbstractAnimation::duration() const = 0
@@ -1287,6 +1282,10 @@ int QAbstractAnimation::currentLoopTime() const
The animation's current time starts at 0, and ends at totalDuration().
+ \note You can bind other properties to currentTime, but it is not
+ recommended setting bindings to it. As animation progresses, the currentTime
+ is updated automatically, which cancels its bindings.
+
\sa loopCount, currentLoopTime()
*/
int QAbstractAnimation::currentTime() const
@@ -1294,44 +1293,72 @@ int QAbstractAnimation::currentTime() const
Q_D(const QAbstractAnimation);
return d->totalCurrentTime;
}
+
+QBindable<int> QAbstractAnimation::bindableCurrentTime()
+{
+ Q_D(QAbstractAnimation);
+ return &d->totalCurrentTime;
+}
+
void QAbstractAnimation::setCurrentTime(int msecs)
{
Q_D(QAbstractAnimation);
msecs = qMax(msecs, 0);
// Calculate new time and loop.
- int dura = duration();
- int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount);
+ const int dura = duration();
+ const int totalLoopCount = d->loopCount;
+ const int totalDura = dura <= 0 ? dura : ((totalLoopCount < 0) ? -1 : dura * totalLoopCount);
if (totalDura != -1)
msecs = qMin(totalDura, msecs);
- d->totalCurrentTime = msecs;
+
+ d->totalCurrentTime.removeBindingUnlessInWrapper();
+
+ const int oldCurrentTime = d->totalCurrentTime.valueBypassingBindings();
+ d->totalCurrentTime.setValueBypassingBindings(msecs);
+
+ QAbstractAnimation::Direction currentDirection = d->direction;
// Update new values.
- int oldLoop = d->currentLoop;
- d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
- if (d->currentLoop == d->loopCount) {
+ const int oldLoop = d->currentLoop.valueBypassingBindings();
+ int newCurrentLoop = (dura <= 0) ? 0 : (msecs / dura);
+ if (newCurrentLoop == totalLoopCount) {
//we're at the end
d->currentTime = qMax(0, dura);
- d->currentLoop = qMax(0, d->loopCount - 1);
+ newCurrentLoop = qMax(0, totalLoopCount - 1);
} else {
- if (d->direction == Forward) {
+ if (currentDirection == Forward) {
d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
} else {
d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
if (d->currentTime == dura)
- --d->currentLoop;
+ newCurrentLoop = newCurrentLoop - 1;
}
}
+ d->currentLoop.setValueBypassingBindings(newCurrentLoop);
+ // this is a virtual function, so it can update the properties as well
updateCurrentTime(d->currentTime);
- if (d->currentLoop != oldLoop)
- emit currentLoopChanged(d->currentLoop);
+ // read the property values again
+ newCurrentLoop = d->currentLoop.valueBypassingBindings();
+ currentDirection = d->direction;
+ const int newTotalCurrentTime = d->totalCurrentTime.valueBypassingBindings();
+
+ if (newCurrentLoop != oldLoop)
+ d->currentLoop.notify();
+
+ /* Notify before calling stop: As seen in tst_QSequentialAnimationGroup::clear
+ * we might delete the animation when stop is called. Thus after stop no member
+ * of the object must be used anymore.
+ */
+ if (oldCurrentTime != newTotalCurrentTime)
+ d->totalCurrentTime.notify();
// All animations are responsible for stopping the animation when their
// own end state is reached; in this case the animation is time driven,
// and has reached the end.
- if ((d->direction == Forward && d->totalCurrentTime == totalDura)
- || (d->direction == Backward && d->totalCurrentTime == 0)) {
+ if ((currentDirection == Forward && newTotalCurrentTime == totalDura)
+ || (currentDirection == Backward && newTotalCurrentTime == 0)) {
stop();
}
}
@@ -1355,7 +1382,7 @@ void QAbstractAnimation::setCurrentTime(int msecs)
void QAbstractAnimation::start(DeletionPolicy policy)
{
Q_D(QAbstractAnimation);
- if (d->state == Running)
+ if (d->state.valueBypassingBindings() == Running)
return;
d->deleteWhenStopped = policy;
d->setState(Running);
@@ -1375,7 +1402,7 @@ void QAbstractAnimation::stop()
{
Q_D(QAbstractAnimation);
- if (d->state == Stopped)
+ if (d->state.valueBypassingBindings() == Stopped)
return;
d->setState(Stopped);
@@ -1391,7 +1418,7 @@ void QAbstractAnimation::stop()
void QAbstractAnimation::pause()
{
Q_D(QAbstractAnimation);
- if (d->state == Stopped) {
+ if (d->state.valueBypassingBindings() == Stopped) {
qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
return;
}
@@ -1409,7 +1436,7 @@ void QAbstractAnimation::pause()
void QAbstractAnimation::resume()
{
Q_D(QAbstractAnimation);
- if (d->state != Paused) {
+ if (d->state.valueBypassingBindings() != Paused) {
qWarning("QAbstractAnimation::resume: "
"Cannot resume an animation that is not paused");
return;
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
index 7f2577d7f7..69a30556a3 100644
--- a/src/corelib/animation/qabstractanimation.h
+++ b/src/corelib/animation/qabstractanimation.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTANIMATION_H
#define QABSTRACTANIMATION_H
@@ -49,17 +13,20 @@ QT_BEGIN_NAMESPACE
class QAnimationGroup;
class QSequentialAnimationGroup;
class QAnimationDriver;
+class QUnifiedTimer;
class QAbstractAnimationPrivate;
class Q_CORE_EXPORT QAbstractAnimation : public QObject
{
Q_OBJECT
- Q_PROPERTY(State state READ state NOTIFY stateChanged)
- Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
- Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime)
- Q_PROPERTY(int currentLoop READ currentLoop NOTIFY currentLoopChanged)
- Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(State state READ state NOTIFY stateChanged BINDABLE bindableState)
+ Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount BINDABLE bindableLoopCount)
+ Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime BINDABLE bindableCurrentTime)
+ Q_PROPERTY(int currentLoop READ currentLoop NOTIFY currentLoopChanged
+ BINDABLE bindableCurrentLoop)
+ Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged
+ BINDABLE bindableDirection)
Q_PROPERTY(int duration READ duration)
public:
@@ -85,18 +52,25 @@ public:
virtual ~QAbstractAnimation();
State state() const;
+ QBindable<QAbstractAnimation::State> bindableState() const;
QAnimationGroup *group() const;
Direction direction() const;
void setDirection(Direction direction);
+ QBindable<Direction> bindableDirection();
int currentTime() const;
+ QBindable<int> bindableCurrentTime();
+
int currentLoopTime() const;
int loopCount() const;
void setLoopCount(int loopCount);
+ QBindable<int> bindableLoopCount();
+
int currentLoop() const;
+ QBindable<int> bindableCurrentLoop() const;
virtual int duration() const = 0;
int totalDuration() const;
@@ -147,18 +121,12 @@ public:
virtual qint64 elapsed() const;
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED void setStartTime(qint64 startTime);
- QT_DEPRECATED qint64 startTime() const;
-#endif
-
Q_SIGNALS:
void started();
void stopped();
protected:
- // ### Qt6: Remove timestep argument
- void advanceAnimation(qint64 timeStep = -1);
+ void advanceAnimation();
virtual void start();
virtual void stop();
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index 037d3be74f..cb9042777a 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTANIMATION_P_H
#define QABSTRACTANIMATION_P_H
@@ -56,6 +20,7 @@
#include <QtCore/qtimer.h>
#include <QtCore/qelapsedtimer.h>
#include <private/qobject_p.h>
+#include <private/qproperty_p.h>
#include <qabstractanimation.h>
QT_REQUIRE_CONFIG(animation);
@@ -64,46 +29,48 @@ QT_BEGIN_NAMESPACE
class QAnimationGroup;
class QAbstractAnimation;
-class QAbstractAnimationPrivate : public QObjectPrivate
+class Q_CORE_EXPORT QAbstractAnimationPrivate : public QObjectPrivate
{
public:
- QAbstractAnimationPrivate()
- : state(QAbstractAnimation::Stopped),
- direction(QAbstractAnimation::Forward),
- totalCurrentTime(0),
- currentTime(0),
- loopCount(1),
- currentLoop(0),
- deleteWhenStopped(false),
- hasRegisteredTimer(false),
- isPause(false),
- isGroup(false),
- group(nullptr)
- {
- }
-
- virtual ~QAbstractAnimationPrivate() {}
+ QAbstractAnimationPrivate();
+ virtual ~QAbstractAnimationPrivate();
static QAbstractAnimationPrivate *get(QAbstractAnimation *q)
{
return q->d_func();
}
- QAbstractAnimation::State state;
- QAbstractAnimation::Direction direction;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QAbstractAnimationPrivate, QAbstractAnimation::State,
+ state, QAbstractAnimation::Stopped)
void setState(QAbstractAnimation::State state);
- int totalCurrentTime;
- int currentTime;
- int loopCount;
- int currentLoop;
+ void setDirection(QAbstractAnimation::Direction direction)
+ {
+ q_func()->setDirection(direction);
+ }
+ void emitDirectionChanged() { Q_EMIT q_func()->directionChanged(direction); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractAnimationPrivate, QAbstractAnimation::Direction,
+ direction, &QAbstractAnimationPrivate::setDirection,
+ &QAbstractAnimationPrivate::emitDirectionChanged,
+ QAbstractAnimation::Forward)
+
+ void setCurrentTime(int msecs) { q_func()->setCurrentTime(msecs); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractAnimationPrivate, int, totalCurrentTime,
+ &QAbstractAnimationPrivate::setCurrentTime, 0)
+ int currentTime = 0;
+
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QAbstractAnimationPrivate, int, loopCount, 1)
- bool deleteWhenStopped;
- bool hasRegisteredTimer;
- bool isPause;
- bool isGroup;
+ void emitCurrentLoopChanged() { Q_EMIT q_func()->currentLoopChanged(currentLoop); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractAnimationPrivate, int, currentLoop, nullptr,
+ &QAbstractAnimationPrivate::emitCurrentLoopChanged, 0)
- QAnimationGroup *group;
+ bool deleteWhenStopped = false;
+ bool hasRegisteredTimer = false;
+ bool isPause = false;
+ bool isGroup = false;
+
+ QAnimationGroup *group = nullptr;
private:
Q_DECLARE_PUBLIC(QAbstractAnimation)
@@ -115,7 +82,10 @@ class QDefaultAnimationDriver : public QAnimationDriver
{
Q_OBJECT
public:
- QDefaultAnimationDriver(QUnifiedTimer *timer);
+ explicit QDefaultAnimationDriver(QUnifiedTimer *timer);
+ ~QDefaultAnimationDriver() override;
+
+protected:
void timerEvent(QTimerEvent *e) override;
private Q_SLOTS:
@@ -130,24 +100,27 @@ private:
class Q_CORE_EXPORT QAnimationDriverPrivate : public QObjectPrivate
{
public:
- QAnimationDriverPrivate() : running(false) {}
+ QAnimationDriverPrivate();
+ ~QAnimationDriverPrivate() override;
+
QElapsedTimer timer;
- bool running;
+ bool running = false;
};
class Q_CORE_EXPORT QAbstractAnimationTimer : public QObject
{
Q_OBJECT
public:
- QAbstractAnimationTimer() : isRegistered(false), isPaused(false), pauseDuration(0) {}
+ QAbstractAnimationTimer();
+ ~QAbstractAnimationTimer() override;
virtual void updateAnimationsTime(qint64 delta) = 0;
virtual void restartAnimationTimer() = 0;
virtual int runningAnimationCount() = 0;
- bool isRegistered;
- bool isPaused;
- int pauseDuration;
+ bool isRegistered = false;
+ bool isPaused = false;
+ int pauseDuration = 0;
};
class Q_CORE_EXPORT QUnifiedTimer : public QObject
@@ -157,6 +130,8 @@ private:
QUnifiedTimer();
public:
+ ~QUnifiedTimer() override;
+
static QUnifiedTimer *instance();
static QUnifiedTimer *instance(bool create);
@@ -185,7 +160,7 @@ public:
void restart();
void maybeUpdateAnimationsToCurrentTime();
- void updateAnimationTimers(qint64 currentTick);
+ void updateAnimationTimers();
//useful for profiling/debugging
int runningAnimationCount();
@@ -222,6 +197,7 @@ private:
bool slowMode;
bool startTimersPending;
bool stopTimerPending;
+ bool allowNegativeDelta;
// This factor will be used to divide the DEFAULT_TIMER_INTERVAL at each tick
// when slowMode is enabled. Setting it to 0 or higher than DEFAULT_TIMER_INTERVAL (16)
@@ -247,6 +223,8 @@ private:
QAnimationTimer();
public:
+ ~QAnimationTimer() override;
+
static QAnimationTimer *instance();
static QAnimationTimer *instance(bool create);
@@ -269,7 +247,7 @@ public:
void updateAnimationsTime(qint64 delta) override;
//useful for profiling/debugging
- int runningAnimationCount() override { return animations.count(); }
+ int runningAnimationCount() override { return animations.size(); }
private Q_SLOTS:
void startAnimations();
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
index 729f55d68f..d2572a7462 100644
--- a/src/corelib/animation/qanimationgroup.cpp
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QAnimationGroup
@@ -174,7 +138,7 @@ int QAnimationGroup::indexOfAnimation(QAbstractAnimation *animation) const
void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
{
Q_D(QAnimationGroup);
- insertAnimation(d->animations.count(), animation);
+ insertAnimation(d->animations.size(), animation);
}
/*!
@@ -222,7 +186,7 @@ void QAnimationGroup::removeAnimation(QAbstractAnimation *animation)
qWarning("QAnimationGroup::remove: cannot remove null animation");
return;
}
- int index = d->animations.indexOf(animation);
+ qsizetype index = d->animations.indexOf(animation);
if (index == -1) {
qWarning("QAnimationGroup::remove: animation is not part of this group");
return;
@@ -247,7 +211,7 @@ QAbstractAnimation *QAnimationGroup::takeAnimation(int index)
}
QAbstractAnimation *animation = d->animations.at(index);
QAbstractAnimationPrivate::get(animation)->group = nullptr;
- // ### removing from list before doing setParent to avoid inifinite recursion
+ // ### removing from list before doing setParent to avoid infinite recursion
// in ChildRemoved event
d->animations.removeAt(index);
animation->setParent(nullptr);
@@ -297,7 +261,7 @@ void QAnimationGroupPrivate::clear(bool onDestruction)
const QList<QAbstractAnimation *> animationsCopy = animations; // taking a copy
animations.clear();
// Clearing backwards so the indices doesn't change while we remove animations.
- for (int i = animationsCopy.count() - 1; i >= 0; --i) {
+ for (qsizetype i = animationsCopy.size() - 1; i >= 0; --i) {
QAbstractAnimation *animation = animationsCopy.at(i);
animation->setParent(nullptr);
QAbstractAnimationPrivate::get(animation)->group = nullptr;
@@ -311,7 +275,7 @@ void QAnimationGroupPrivate::clear(bool onDestruction)
}
}
-void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *)
+void QAnimationGroupPrivate::animationRemoved(qsizetype index, QAbstractAnimation *)
{
Q_Q(QAnimationGroup);
Q_UNUSED(index);
diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h
index 7c7666f251..412e2d442e 100644
--- a/src/corelib/animation/qanimationgroup.h
+++ b/src/corelib/animation/qanimationgroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QANIMATIONGROUP_H
#define QANIMATIONGROUP_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
index 4d1d690e69..334f780968 100644
--- a/src/corelib/animation/qanimationgroup_p.h
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QANIMATIONGROUP_P_H
#define QANIMATIONGROUP_P_H
@@ -70,8 +34,8 @@ public:
isGroup = true;
}
- virtual void animationInsertedAt(int) { }
- virtual void animationRemoved(int, QAbstractAnimation *);
+ virtual void animationInsertedAt(qsizetype) { }
+ virtual void animationRemoved(qsizetype, QAbstractAnimation *);
void clear(bool onDestruction);
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
index 492fb82e2b..cea22bcacb 100644
--- a/src/corelib/animation/qparallelanimationgroup.cpp
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QParallelAnimationGroup
@@ -291,7 +255,7 @@ bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAn
return uncontrolledFinishTime.value(anim, -1) >= 0;
}
-void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
+void QParallelAnimationGroupPrivate::animationRemoved(qsizetype index, QAbstractAnimation *anim)
{
QAnimationGroupPrivate::animationRemoved(index, anim);
disconnectUncontrolledAnimation(anim);
diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h
index 683d933861..77bc6eabac 100644
--- a/src/corelib/animation/qparallelanimationgroup.h
+++ b/src/corelib/animation/qparallelanimationgroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPARALLELANIMATIONGROUP_H
#define QPARALLELANIMATIONGROUP_H
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
index fc8f809d5a..62c53d3609 100644
--- a/src/corelib/animation/qparallelanimationgroup_p.h
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPARALLELANIMATIONGROUP_P_H
#define QPARALLELANIMATIONGROUP_P_H
@@ -78,7 +42,7 @@ public:
void connectUncontrolledAnimations();
void disconnectUncontrolledAnimations();
- void animationRemoved(int index, QAbstractAnimation *) override;
+ void animationRemoved(qsizetype index, QAbstractAnimation *) override;
// private slot
void _q_uncontrolledAnimationFinished();
diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp
index 5f8a8b3590..344b21946e 100644
--- a/src/corelib/animation/qpauseanimation.cpp
+++ b/src/corelib/animation/qpauseanimation.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QPauseAnimation
@@ -63,18 +27,22 @@
#include "qpauseanimation.h"
#include "qabstractanimation_p.h"
+#include "private/qproperty_p.h"
QT_BEGIN_NAMESPACE
class QPauseAnimationPrivate : public QAbstractAnimationPrivate
{
+ Q_DECLARE_PUBLIC(QPauseAnimation)
public:
QPauseAnimationPrivate() : QAbstractAnimationPrivate(), duration(250)
{
isPause = true;
}
- int duration;
+ void setDuration(int msecs) { q_func()->setDuration(msecs); }
+ Q_OBJECT_COMPAT_PROPERTY(QPauseAnimationPrivate, int, duration,
+ &QPauseAnimationPrivate::setDuration)
};
/*!
@@ -125,7 +93,18 @@ void QPauseAnimation::setDuration(int msecs)
return;
}
Q_D(QPauseAnimation);
- d->duration = msecs;
+
+ d->duration.removeBindingUnlessInWrapper();
+ if (msecs != d->duration.valueBypassingBindings()) {
+ d->duration.setValueBypassingBindings(msecs);
+ d->duration.notify();
+ }
+}
+
+QBindable<int> QPauseAnimation::bindableDuration()
+{
+ Q_D(QPauseAnimation);
+ return &d->duration;
}
/*!
diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h
index 6bdbeefdbd..f661459f83 100644
--- a/src/corelib/animation/qpauseanimation.h
+++ b/src/corelib/animation/qpauseanimation.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAUSEANIMATION_H
#define QPAUSEANIMATION_H
@@ -51,7 +15,7 @@ class QPauseAnimationPrivate;
class Q_CORE_EXPORT QPauseAnimation : public QAbstractAnimation
{
Q_OBJECT
- Q_PROPERTY(int duration READ duration WRITE setDuration)
+ Q_PROPERTY(int duration READ duration WRITE setDuration BINDABLE bindableDuration)
public:
QPauseAnimation(QObject *parent = nullptr);
QPauseAnimation(int msecs, QObject *parent = nullptr);
@@ -59,6 +23,7 @@ public:
int duration() const override;
void setDuration(int msecs);
+ QBindable<int> bindableDuration();
protected:
bool event(QEvent *e) override;
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index d014b5c441..d461668dbb 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QPropertyAnimation
@@ -58,6 +22,10 @@
\snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \note You can also control an animation's lifespan by choosing a
+ \l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting the
+ animation.
+
The property name and the QObject instance of which property
should be animated are passed to the constructor. You can then
specify the start and end value of the property. The procedure is
@@ -85,13 +53,15 @@
#include "qpropertyanimation_p.h"
#include <QtCore/QMutex>
+#include <QtCore/QHash>
#include <QtCore/private/qlocking_p.h>
QT_BEGIN_NAMESPACE
void QPropertyAnimationPrivate::updateMetaProperty()
{
- if (!target || propertyName.isEmpty()) {
+ const QObject *target = targetObject.valueBypassingBindings();
+ if (!target || propertyName.value().isEmpty()) {
propertyType = QMetaType::UnknownType;
propertyIndex = -1;
return;
@@ -99,18 +69,22 @@ void QPropertyAnimationPrivate::updateMetaProperty()
//propertyType will be set to a valid type only if there is a Q_PROPERTY
//otherwise it will be set to QVariant::Invalid at the end of this function
- propertyType = targetValue->property(propertyName).userType();
- propertyIndex = targetValue->metaObject()->indexOfProperty(propertyName);
+ propertyType = target->property(propertyName.value()).userType();
+ propertyIndex = target->metaObject()->indexOfProperty(propertyName.value());
if (propertyType != QMetaType::UnknownType)
convertValues(propertyType);
if (propertyIndex == -1) {
//there is no Q_PROPERTY on the object
propertyType = QMetaType::UnknownType;
- if (!targetValue->dynamicPropertyNames().contains(propertyName))
- qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData());
- } else if (!targetValue->metaObject()->property(propertyIndex).isWritable()) {
- qWarning("QPropertyAnimation: you're trying to animate the non-writable property %s of your QObject", propertyName.constData());
+ if (!target->dynamicPropertyNames().contains(propertyName))
+ qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of "
+ "your QObject",
+ propertyName.value().constData());
+ } else if (!target->metaObject()->property(propertyIndex).isWritable()) {
+ qWarning("QPropertyAnimation: you're trying to animate the non-writable property %s of "
+ "your QObject",
+ propertyName.value().constData());
}
}
@@ -119,10 +93,8 @@ void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
if (state == QAbstractAnimation::Stopped)
return;
- if (!target) {
- q_func()->stop(); //the target was destroyed we need to stop the animation
+ if (!targetObject)
return;
- }
if (newValue.userType() == propertyType) {
//no conversion is needed, we directly call the QMetaObject::metacall
@@ -130,9 +102,9 @@ void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
int status = -1;
int flags = 0;
void *argv[] = { const_cast<void *>(newValue.constData()), const_cast<QVariant *>(&newValue), &status, &flags };
- QMetaObject::metacall(targetValue, QMetaObject::WriteProperty, propertyIndex, argv);
+ QMetaObject::metacall(targetObject, QMetaObject::WriteProperty, propertyIndex, argv);
} else {
- targetValue->setProperty(propertyName.constData(), newValue);
+ targetObject->setProperty(propertyName.value().constData(), newValue);
}
}
@@ -175,22 +147,37 @@ QPropertyAnimation::~QPropertyAnimation()
*/
QObject *QPropertyAnimation::targetObject() const
{
- return d_func()->target.data();
+ return d_func()->targetObject;
+}
+
+QBindable<QObject *> QPropertyAnimation::bindableTargetObject()
+{
+ return &d_func()->targetObject;
}
void QPropertyAnimation::setTargetObject(QObject *target)
{
Q_D(QPropertyAnimation);
- if (d->target.data() == target)
- return;
-
if (d->state != QAbstractAnimation::Stopped) {
qWarning("QPropertyAnimation::setTargetObject: you can't change the target of a running animation");
return;
}
- d->target = d->targetValue = target;
+ d->targetObject.removeBindingUnlessInWrapper();
+ const QObject *oldTarget = d->targetObject.valueBypassingBindings();
+ if (oldTarget == target)
+ return;
+
+ if (oldTarget != nullptr)
+ QObject::disconnect(oldTarget, &QObject::destroyed, this, nullptr);
+ d->targetObject.setValueBypassingBindings(target);
+
+ if (target != nullptr) {
+ QObject::connect(target, &QObject::destroyed, this,
+ [d] { d->targetObjectDestroyed(); });
+ }
d->updateMetaProperty();
+ d->targetObject.notify();
}
/*!
@@ -214,10 +201,20 @@ void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
return;
}
- d->propertyName = propertyName;
+ d->propertyName.removeBindingUnlessInWrapper();
+
+ if (d->propertyName.valueBypassingBindings() == propertyName)
+ return;
+
+ d->propertyName.setValueBypassingBindings(propertyName);
d->updateMetaProperty();
+ d->propertyName.notify();
}
+QBindable<QByteArray> QPropertyAnimation::bindablePropertyName()
+{
+ return &d_func()->propertyName;
+}
/*!
\reimp
@@ -251,9 +248,10 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
{
Q_D(QPropertyAnimation);
- if (!d->target && oldState == Stopped) {
- qWarning("QPropertyAnimation::updateState (%s): Changing state of an animation without target",
- d->propertyName.constData());
+ if (!d->targetObject && oldState == Stopped) {
+ qWarning("QPropertyAnimation::updateState (%s): Changing state of an animation without "
+ "target",
+ d->propertyName.value().constData());
return;
}
@@ -261,22 +259,30 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
QPropertyAnimation *animToStop = nullptr;
{
- static QBasicMutex mutex;
+ Q_CONSTINIT static QBasicMutex mutex;
auto locker = qt_unique_lock(mutex);
- typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
+ using QPropertyAnimationPair = std::pair<QObject *, QByteArray>;
typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
- static QPropertyAnimationHash hash;
- //here we need to use value because we need to know to which pointer
- //the animation was referring in case stopped because the target was destroyed
- QPropertyAnimationPair key(d->targetValue, d->propertyName);
+ Q_CONSTINIT static QPropertyAnimationHash hash;
+
+ // in case the targetObject gets deleted, the following happens:
+ // 1. targetObject's destroyed signal calls our targetObjectDestroyed.
+ // 2. targetObjectDestroyed calls stop()
+ // 3. QAbstractAnimation::stop() calls setState(Stopped)
+ // 4. setState(Stopped) calls updateState(newState, oldState)
+ // 5. we arrive here. d->targetObject is not yet set to nullptr, we can safely use it.
+ Q_ASSERT(d->targetObject);
+
+ QPropertyAnimationPair key(d->targetObject, d->propertyName);
if (newState == Running) {
d->updateMetaProperty();
- animToStop = hash.value(key, 0);
+ animToStop = hash.value(key, nullptr);
hash.insert(key, this);
locker.unlock();
// update the default start value
if (oldState == Stopped) {
- d->setDefaultStartEndValue(d->targetValue->property(d->propertyName.constData()));
+ d->setDefaultStartEndValue(
+ d->targetObject->property(d->propertyName.value().constData()));
//let's check if we have a start value and an end value
const char *what = nullptr;
if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) {
@@ -289,9 +295,11 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
what = "end";
}
if (Q_UNLIKELY(what)) {
- qWarning("QPropertyAnimation::updateState (%s, %s, %ls): starting an animation without %s value",
- d->propertyName.constData(), d->target.data()->metaObject()->className(),
- qUtf16Printable(d->target.data()->objectName()), what);
+ qWarning("QPropertyAnimation::updateState (%s, %s, %ls): starting an animation "
+ "without %s value",
+ d->propertyName.value().constData(),
+ d->targetObject->metaObject()->className(),
+ qUtf16Printable(d->targetObject->objectName()), what);
}
}
} else if (hash.value(key) == this) {
diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h
index a1caafcad5..038c202b8f 100644
--- a/src/corelib/animation/qpropertyanimation.h
+++ b/src/corelib/animation/qpropertyanimation.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROPERTYANIMATION_H
#define QPROPERTYANIMATION_H
@@ -50,8 +14,10 @@ class QPropertyAnimationPrivate;
class Q_CORE_EXPORT QPropertyAnimation : public QVariantAnimation
{
Q_OBJECT
- Q_PROPERTY(QByteArray propertyName READ propertyName WRITE setPropertyName)
- Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
+ Q_PROPERTY(QByteArray propertyName READ propertyName WRITE setPropertyName
+ BINDABLE bindablePropertyName)
+ Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject
+ BINDABLE bindableTargetObject)
public:
QPropertyAnimation(QObject *parent = nullptr);
@@ -60,9 +26,11 @@ public:
QObject *targetObject() const;
void setTargetObject(QObject *target);
+ QBindable<QObject *> bindableTargetObject();
QByteArray propertyName() const;
void setPropertyName(const QByteArray &propertyName);
+ QBindable<QByteArray> bindablePropertyName();
protected:
bool event(QEvent *event) override;
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
index cbd3ce287d..9e41d4dc6d 100644
--- a/src/corelib/animation/qpropertyanimation_p.h
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROPERTYANIMATION_P_H
#define QPROPERTYANIMATION_P_H
@@ -54,6 +18,7 @@
#include "qpropertyanimation.h"
#include "private/qvariantanimation_p.h"
+#include "private/qproperty_p.h"
QT_REQUIRE_CONFIG(animation);
@@ -63,20 +28,31 @@ class QPropertyAnimationPrivate : public QVariantAnimationPrivate
{
Q_DECLARE_PUBLIC(QPropertyAnimation)
public:
- QPropertyAnimationPrivate()
- : targetValue(nullptr), propertyType(0), propertyIndex(-1)
+ QPropertyAnimationPrivate() : propertyType(0), propertyIndex(-1) { }
+
+ void setTargetObjectForwarder(QObject *target) { q_func()->setTargetObject(target); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QPropertyAnimationPrivate, QObject *, targetObject,
+ &QPropertyAnimationPrivate::setTargetObjectForwarder,
+ nullptr)
+ void targetObjectDestroyed()
{
+ // stop() has to be called before targetObject is set to nullptr.
+ // targetObject must not be nullptr in states unequal to "Stopped".
+ q_func()->stop();
+ targetObject.setValueBypassingBindings(nullptr);
+ targetObject.notify();
}
- QPointer<QObject> target;
- //we use targetValue to be able to unregister the target from the global hash
- QObject *targetValue;
-
//for the QProperty
int propertyType;
int propertyIndex;
- QByteArray propertyName;
+ void setPropertyName(const QByteArray &propertyName)
+ {
+ q_func()->setPropertyName(propertyName);
+ }
+ Q_OBJECT_COMPAT_PROPERTY(QPropertyAnimationPrivate, QByteArray, propertyName,
+ &QPropertyAnimationPrivate::setPropertyName)
void updateProperty(const QVariant &);
void updateMetaProperty();
};
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
index 98ac04a14f..260481dbef 100644
--- a/src/corelib/animation/qsequentialanimationgroup.cpp
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QSequentialAnimationGroup
@@ -208,7 +172,7 @@ void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newA
// we need to force activation because setCurrentAnimation will have no effect
activateCurrentAnimation();
else
- setCurrentAnimation(animations.count() - 1, true);
+ setCurrentAnimation(animations.size() - 1, true);
}
// and now we need to fast rewind from the current position to
@@ -293,7 +257,7 @@ QPauseAnimation *QSequentialAnimationGroup::insertPause(int index, int msecs)
/*!
\property QSequentialAnimationGroup::currentAnimation
- Returns the animation in the current time.
+ \brief the animation in the current time.
*/
QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const
{
@@ -301,6 +265,11 @@ QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const
return d->currentAnimation;
}
+QBindable<QAbstractAnimation *> QSequentialAnimationGroup::bindableCurrentAnimation() const
+{
+ return &d_func()->currentAnimation;
+}
+
/*!
\reimp
*/
@@ -424,8 +393,10 @@ bool QSequentialAnimationGroup::event(QEvent *event)
void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool intermediate)
{
Q_Q(QSequentialAnimationGroup);
+ // currentAnimation.removeBindingUnlessInWrapper()
+ // is not necessary here, since it is read only
- index = qMin(index, animations.count() - 1);
+ index = qMin(index, animations.size() - 1);
if (index == -1) {
Q_ASSERT(animations.isEmpty());
@@ -443,8 +414,8 @@ void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool inter
if (currentAnimation)
currentAnimation->stop();
- currentAnimation = animations.at(index);
currentAnimationIndex = index;
+ currentAnimation = animations.at(index);
emit q->currentAnimationChanged(currentAnimation);
@@ -501,10 +472,12 @@ void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
the group at index \a index.
Note: We only support insertion after the current animation
*/
-void QSequentialAnimationGroupPrivate::animationInsertedAt(int index)
+void QSequentialAnimationGroupPrivate::animationInsertedAt(qsizetype index)
{
- if (currentAnimation == nullptr)
+ if (currentAnimation == nullptr) {
setCurrentAnimation(0); // initialize the current animation
+ Q_ASSERT(currentAnimation);
+ }
if (currentAnimationIndex == index
&& currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) {
@@ -527,7 +500,7 @@ void QSequentialAnimationGroupPrivate::animationInsertedAt(int index)
the group at index \a index. The animation is no more listed when this
method is called.
*/
-void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
+void QSequentialAnimationGroupPrivate::animationRemoved(qsizetype index, QAbstractAnimation *anim)
{
Q_Q(QSequentialAnimationGroup);
QAnimationGroupPrivate::animationRemoved(index, anim);
@@ -538,13 +511,13 @@ void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnim
if (actualDuration.size() > index)
actualDuration.removeAt(index);
- const int currentIndex = animations.indexOf(currentAnimation);
+ const qsizetype currentIndex = animations.indexOf(currentAnimation);
if (currentIndex == -1) {
//we're removing the current animation
disconnectUncontrolledAnimation(currentAnimation);
- if (index < animations.count())
+ if (index < animations.size())
setCurrentAnimation(index); //let's try to take the next one
else if (index > 0)
setCurrentAnimation(index - 1);
@@ -556,7 +529,7 @@ void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnim
// duration of the previous animations up to the current animation
currentTime = 0;
- for (int i = 0; i < currentAnimationIndex; ++i) {
+ for (qsizetype i = 0; i < currentAnimationIndex; ++i) {
const int current = animationActualTotalDuration(i);
currentTime += current;
}
diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h
index a33ff07abf..6786078170 100644
--- a/src/corelib/animation/qsequentialanimationgroup.h
+++ b/src/corelib/animation/qsequentialanimationgroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSEQUENTIALANIMATIONGROUP_H
#define QSEQUENTIALANIMATIONGROUP_H
@@ -52,7 +16,8 @@ class QSequentialAnimationGroupPrivate;
class Q_CORE_EXPORT QSequentialAnimationGroup : public QAnimationGroup
{
Q_OBJECT
- Q_PROPERTY(QAbstractAnimation* currentAnimation READ currentAnimation NOTIFY currentAnimationChanged)
+ Q_PROPERTY(QAbstractAnimation *currentAnimation READ currentAnimation
+ NOTIFY currentAnimationChanged BINDABLE bindableCurrentAnimation)
public:
QSequentialAnimationGroup(QObject *parent = nullptr);
@@ -62,6 +27,7 @@ public:
QPauseAnimation *insertPause(int index, int msecs);
QAbstractAnimation *currentAnimation() const;
+ QBindable<QAbstractAnimation *> bindableCurrentAnimation() const;
int duration() const override;
Q_SIGNALS:
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
index b788771fe5..cbdf204d0a 100644
--- a/src/corelib/animation/qsequentialanimationgroup_p.h
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSEQUENTIALANIMATIONGROUP_P_H
#define QSEQUENTIALANIMATIONGROUP_P_H
@@ -53,6 +17,7 @@
#include "qsequentialanimationgroup.h"
#include "private/qanimationgroup_p.h"
+#include "private/qproperty_p.h"
QT_REQUIRE_CONFIG(animation);
@@ -62,10 +27,7 @@ class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate
{
Q_DECLARE_PUBLIC(QSequentialAnimationGroup)
public:
- QSequentialAnimationGroupPrivate()
- : currentAnimation(nullptr), currentAnimationIndex(-1), lastLoop(0)
- { }
-
+ QSequentialAnimationGroupPrivate() : currentAnimationIndex(-1), lastLoop(0) { }
struct AnimationIndex
{
@@ -82,12 +44,15 @@ public:
void setCurrentAnimation(int index, bool intermediate = false);
void activateCurrentAnimation(bool intermediate = false);
- void animationInsertedAt(int index) override;
- void animationRemoved(int index, QAbstractAnimation *anim) override;
+ void animationInsertedAt(qsizetype index) override;
+ void animationRemoved(qsizetype index, QAbstractAnimation *anim) override;
bool atEnd() const;
- QAbstractAnimation *currentAnimation;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QSequentialAnimationGroupPrivate, QAbstractAnimation *,
+ currentAnimation,
+ nullptr // initial value
+ )
int currentAnimationIndex;
// this is the actual duration of uncontrolled animations
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index e50cdd05ec..b4d47aae8f 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qvariantanimation.h"
#include "qvariantanimation_p.h"
@@ -190,14 +154,15 @@ QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), interpolat
void QVariantAnimationPrivate::convertValues(int t)
{
+ auto type = QMetaType(t);
//this ensures that all the keyValues are of type t
- for (int i = 0; i < keyValues.count(); ++i) {
+ for (int i = 0; i < keyValues.size(); ++i) {
QVariantAnimation::KeyValue &pair = keyValues[i];
- pair.second.convert(t);
+ pair.second.convert(type);
}
//we also need update to the current interval if needed
- currentInterval.start.second.convert(t);
- currentInterval.end.second.convert(t);
+ currentInterval.start.second.convert(type);
+ currentInterval.end.second.convert(type);
//... and the interpolator
updateInterpolator();
@@ -225,11 +190,12 @@ void QVariantAnimationPrivate::updateInterpolator()
void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
{
// can't interpolate if we don't have at least 2 values
- if ((keyValues.count() + (defaultStartEndValue.isValid() ? 1 : 0)) < 2)
+ if ((keyValues.size() + (defaultStartEndValue.isValid() ? 1 : 0)) < 2)
return;
const qreal endProgress = (direction == QAbstractAnimation::Forward) ? qreal(1) : qreal(0);
- const qreal progress = easing.valueForProgress(((duration == 0) ? endProgress : qreal(currentTime) / qreal(duration)));
+ const qreal progress = easing.value().valueForProgress(
+ duration == 0 ? endProgress : qreal(currentTime) / qreal(duration));
//0 and 1 are still the boundaries
if (force || (currentInterval.start.first > 0 && progress < currentInterval.start.first)
@@ -237,27 +203,27 @@ void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
//let's update currentInterval
QVariantAnimation::KeyValues::const_iterator it = std::lower_bound(keyValues.constBegin(),
keyValues.constEnd(),
- qMakePair(progress, QVariant()),
+ std::pair{progress, QVariant{}},
animationValueLessThan);
if (it == keyValues.constBegin()) {
//the item pointed to by it is the start element in the range
- if (it->first == 0 && keyValues.count() > 1) {
+ if (it->first == 0 && keyValues.size() > 1) {
currentInterval.start = *it;
currentInterval.end = *(it+1);
} else {
- currentInterval.start = qMakePair(qreal(0), defaultStartEndValue);
+ currentInterval.start = {qreal(0), defaultStartEndValue};
currentInterval.end = *it;
}
} else if (it == keyValues.constEnd()) {
--it; //position the iterator on the last item
- if (it->first == 1 && keyValues.count() > 1) {
+ if (it->first == 1 && keyValues.size() > 1) {
//we have an end value (item with progress = 1)
currentInterval.start = *(it-1);
currentInterval.end = *it;
} else {
//we use the default end value here
currentInterval.start = *it;
- currentInterval.end = qMakePair(qreal(1), defaultStartEndValue);
+ currentInterval.end = {qreal(1), defaultStartEndValue};
}
} else {
currentInterval.start = *(it-1);
@@ -276,14 +242,16 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
const qreal startProgress = currentInterval.start.first;
const qreal endProgress = currentInterval.end.first;
- const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
+ const qreal localProgress =
+ qIsNull(progress - startProgress) ? 0.0 // avoid 0/0 below
+ /* else */ : (progress - startProgress) / (endProgress - startProgress);
QVariant ret = q->interpolated(currentInterval.start.second,
currentInterval.end.second,
localProgress);
qSwap(currentValue, ret);
q->updateCurrentValue(currentValue);
- static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
if (!changedSignalIndex.loadRelaxed()) {
//we keep the mask so that we emit valueChanged only when needed (for performance reasons)
changedSignalIndex.testAndSetRelaxed(0, signalIndex("valueChanged(QVariant)"));
@@ -296,9 +264,10 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
QVariant QVariantAnimationPrivate::valueAt(qreal step) const
{
- QVariantAnimation::KeyValues::const_iterator result =
- std::lower_bound(keyValues.constBegin(), keyValues.constEnd(), qMakePair(step, QVariant()), animationValueLessThan);
- if (result != keyValues.constEnd() && !animationValueLessThan(qMakePair(step, QVariant()), *result))
+ const auto sought = std::pair{step, QVariant()};
+ const auto result = std::lower_bound(keyValues.cbegin(), keyValues.cend(), sought,
+ animationValueLessThan);
+ if (result != keyValues.cend() && !animationValueLessThan(sought, *result))
return result->second;
return QVariant();
@@ -385,13 +354,23 @@ QEasingCurve QVariantAnimation::easingCurve() const
void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
{
Q_D(QVariantAnimation);
- d->easing = easing;
+ d->easing.removeBindingUnlessInWrapper();
+ const bool valueChanged = easing != d->easing.valueBypassingBindings();
+ d->easing.setValueBypassingBindings(easing);
d->recalculateCurrentInterval();
+ if (valueChanged)
+ d->easing.notify();
+}
+
+QBindable<QEasingCurve> QVariantAnimation::bindableEasingCurve()
+{
+ Q_D(QVariantAnimation);
+ return &d->easing;
}
typedef QList<QVariantAnimation::Interpolator> QInterpolatorVector;
Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
-static QBasicMutex registeredInterpolatorsMutex;
+Q_CONSTINIT static QBasicMutex registeredInterpolatorsMutex;
/*!
\fn template <typename T> void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
@@ -428,8 +407,8 @@ void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator fun
// to continue causes the app to crash on exit with a SEGV
if (interpolators) {
const auto locker = qt_scoped_lock(registeredInterpolatorsMutex);
- if (int(interpolationType) >= interpolators->count())
- interpolators->resize(int(interpolationType) + 1);
+ if (interpolationType >= interpolators->size())
+ interpolators->resize(interpolationType + 1);
interpolators->replace(interpolationType, func);
}
}
@@ -446,7 +425,7 @@ QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int in
QInterpolatorVector *interpolators = registeredInterpolators();
const auto locker = qt_scoped_lock(registeredInterpolatorsMutex);
QVariantAnimation::Interpolator ret = nullptr;
- if (interpolationType < interpolators->count()) {
+ if (interpolationType < interpolators->size()) {
ret = interpolators->at(interpolationType);
if (ret) return ret;
}
@@ -505,10 +484,18 @@ void QVariantAnimation::setDuration(int msecs)
qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
return;
}
- if (d->duration == msecs)
- return;
- d->duration = msecs;
- d->recalculateCurrentInterval();
+ d->duration.removeBindingUnlessInWrapper();
+ if (d->duration.valueBypassingBindings() != msecs) {
+ d->duration.setValueBypassingBindings(msecs);
+ d->recalculateCurrentInterval();
+ d->duration.notify();
+ }
+}
+
+QBindable<int> QVariantAnimation::bindableDuration()
+{
+ Q_D(QVariantAnimation);
+ return &d->duration;
}
/*!
@@ -566,7 +553,7 @@ QVariant QVariantAnimation::keyValueAt(qreal step) const
/*!
\typedef QVariantAnimation::KeyValue
- This is a typedef for QPair<qreal, QVariant>.
+ This is a typedef for std::pair<qreal, QVariant>.
*/
/*!
\typedef QVariantAnimation::KeyValues
diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h
index f1721b8a65..4bdb971357 100644
--- a/src/corelib/animation/qvariantanimation.h
+++ b/src/corelib/animation/qvariantanimation.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVARIANTANIMATION_H
#define QVARIANTANIMATION_H
@@ -57,11 +21,12 @@ class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation
Q_PROPERTY(QVariant startValue READ startValue WRITE setStartValue)
Q_PROPERTY(QVariant endValue READ endValue WRITE setEndValue)
Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY valueChanged)
- Q_PROPERTY(int duration READ duration WRITE setDuration)
- Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
+ Q_PROPERTY(int duration READ duration WRITE setDuration BINDABLE bindableDuration)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve
+ BINDABLE bindableEasingCurve)
public:
- typedef QPair<qreal, QVariant> KeyValue;
+ using KeyValue = std::pair<qreal, QVariant>;
typedef QList<KeyValue> KeyValues;
QVariantAnimation(QObject *parent = nullptr);
@@ -83,9 +48,11 @@ public:
int duration() const override;
void setDuration(int msecs);
+ QBindable<int> bindableDuration();
QEasingCurve easingCurve() const;
void setEasingCurve(const QEasingCurve &easing);
+ QBindable<QEasingCurve> bindableEasingCurve();
typedef QVariant (*Interpolator)(const void *from, const void *to, qreal progress);
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
index 3425777ba5..85f996f7bd 100644
--- a/src/corelib/animation/qvariantanimation_p.h
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVARIANTANIMATION_P_H
#define QVARIANTANIMATION_P_H
@@ -56,6 +20,7 @@
#include <QtCore/qmetaobject.h>
#include "private/qabstractanimation_p.h"
+#include "private/qproperty_p.h"
#include <type_traits>
@@ -87,8 +52,14 @@ public:
QVariantAnimation::KeyValue start, end;
} currentInterval;
- QEasingCurve easing;
- int duration;
+ void setEasingCurve(const QEasingCurve &easing) { q_func()->setEasingCurve(easing); }
+ Q_OBJECT_COMPAT_PROPERTY(QVariantAnimationPrivate, QEasingCurve, easing,
+ &QVariantAnimationPrivate::setEasingCurve)
+
+ void setDuration(int msecs) { q_func()->setDuration(msecs); }
+ Q_OBJECT_COMPAT_PROPERTY(QVariantAnimationPrivate, int, duration,
+ &QVariantAnimationPrivate::setDuration)
+
QVariantAnimation::KeyValues keyValues;
QVariantAnimation::Interpolator interpolator;
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp
new file mode 100644
index 0000000000..05bcda0943
--- /dev/null
+++ b/src/corelib/compat/removed_api.cpp
@@ -0,0 +1,1124 @@
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#define QT_CORE_BUILD_REMOVED_API
+
+#include "qglobal.h"
+
+QT_USE_NAMESPACE
+
+#if QT_CORE_REMOVED_SINCE(6, 1)
+
+#include "qmetatype.h"
+
+// keep in sync with version in header
+int QMetaType::id() const
+{
+ if (d_ptr) {
+ if (int id = d_ptr->typeId.loadRelaxed())
+ return id;
+ return idHelper();
+ }
+ return 0;
+}
+
+#endif // QT_CORE_REMOVED_SINCE(6, 1)
+
+#if QT_CORE_REMOVED_SINCE(6, 2)
+
+#include "qbindingstorage.h"
+
+void QBindingStorage::maybeUpdateBindingAndRegister_helper(const QUntypedPropertyData *data) const
+{
+ registerDependency_helper(data);
+}
+
+#endif // QT_CORE_REMOVED_SINCE(6, 2)
+
+#if QT_CORE_REMOVED_SINCE(6, 3)
+
+#include "qbytearraymatcher.h"
+
+# if QT_POINTER_SIZE != 4
+
+int QStaticByteArrayMatcherBase::indexOfIn(const char *h, uint hl, const char *n, int nl, int from) const noexcept
+{
+ qsizetype r = indexOfIn(h, size_t(hl), n, qsizetype(nl), qsizetype(from));
+ Q_ASSERT(r == int(r));
+ return r;
+}
+
+# endif // QT_POINTER_SIZE != 4
+
+qsizetype QByteArrayMatcher::indexIn(const QByteArray &ba, qsizetype from) const
+{
+ return indexIn(QByteArrayView{ba}, from); // ba.isNull() may be significant, so don't ignore it!
+}
+
+#include "tools/qcryptographichash.h"
+
+void QCryptographicHash::addData(const QByteArray &data)
+{
+ addData(QByteArrayView{data});
+}
+
+QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
+{
+ return hash(QByteArrayView{data}, method);
+}
+
+#include "qdatastream.h"
+
+# ifndef QT_NO_DATASTREAM
+# include "qfloat16.h"
+
+QDataStream &QDataStream::operator>>(qfloat16 &f)
+{
+ return *this >> reinterpret_cast<qint16&>(f);
+}
+
+QDataStream &QDataStream::operator<<(qfloat16 f)
+{
+ return *this << reinterpret_cast<qint16&>(f);
+}
+
+# endif
+
+#include "quuid.h"
+
+QUuid::QUuid(const QString &text)
+ : QUuid{qToAnyStringViewIgnoringNull(text)}
+{
+}
+
+QUuid::QUuid(const char *text)
+ : QUuid{QAnyStringView(text)}
+{
+}
+
+QUuid::QUuid(const QByteArray &text)
+ : QUuid{qToAnyStringViewIgnoringNull(text)}
+{
+}
+
+QUuid QUuid::fromString(QStringView string) noexcept
+{
+ return fromString(QAnyStringView{string});
+}
+
+QUuid QUuid::fromString(QLatin1StringView string) noexcept
+{
+ return fromString(QAnyStringView{string});
+}
+
+QUuid QUuid::fromRfc4122(const QByteArray &bytes)
+{
+ return fromRfc4122(qToByteArrayViewIgnoringNull(bytes));
+}
+
+#include "qbytearraylist.h"
+
+# if QT_POINTER_SIZE != 4
+QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char *sep, int seplen)
+{
+ return QByteArrayList_join(that, sep, qsizetype(seplen));
+}
+# endif
+
+#include "qlocale.h"
+
+QString QLocale::languageToCode(Language language)
+{
+ return languageToCode(language, QLocale::AnyLanguageCode);
+}
+
+QLocale::Language QLocale::codeToLanguage(QStringView languageCode) noexcept
+{
+ return codeToLanguage(languageCode, QLocale::AnyLanguageCode);
+}
+
+#include "qoperatingsystemversion.h"
+
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ return QOperatingSystemVersionBase::current();
+}
+
+QString QOperatingSystemVersion::name() const
+{
+ return QOperatingSystemVersionBase::name();
+}
+
+int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
+ const QOperatingSystemVersion &v2)
+{
+ return QOperatingSystemVersionBase::compare(v1, v2);
+}
+
+#include "qurl.h"
+
+QString QUrl::fromAce(const QByteArray &domain)
+{
+ return fromAce(domain, {});
+}
+
+QByteArray QUrl::toAce(const QString &domain)
+{
+ return toAce(domain, {});
+}
+
+#endif // QT_CORE_REMOVED_SINCE(6, 3)
+
+#if QT_CORE_REMOVED_SINCE(6, 4)
+
+#include "qbytearray.h" // uses QT_CORE_INLINE_SINCE
+
+#include "qcalendar.h"
+
+QCalendar::QCalendar(QStringView name)
+ : QCalendar(QAnyStringView{name}) {}
+
+QCalendar::QCalendar(QLatin1StringView name)
+ : QCalendar(QAnyStringView{name}) {}
+
+#include "qcollator.h" // inline function compare(ptr, n, ptr, n) (for MSVC)
+
+#include "qhashfunctions.h"
+
+size_t qHash(const QByteArray &key, size_t seed) noexcept
+{
+ return qHashBits(key.constData(), size_t(key.size()), seed);
+}
+
+size_t qHash(const QByteArrayView &key, size_t seed) noexcept
+{
+ return qHashBits(key.constData(), size_t(key.size()), seed);
+}
+
+#include "qobject.h"
+
+void QObject::setObjectName(const QString &name)
+{
+ setObjectName<void>(name);
+}
+
+#include "qlocale.h" // uses QT_CORE_INLINE_SINCE
+
+#if QT_CONFIG(settings)
+
+#include "qsettings.h"
+
+void QSettings::beginGroup(const QString &prefix)
+{
+ beginGroup(qToAnyStringViewIgnoringNull(prefix));
+}
+
+int QSettings::beginReadArray(const QString &prefix)
+{
+ return beginReadArray(qToAnyStringViewIgnoringNull(prefix));
+}
+
+void QSettings::beginWriteArray(const QString &prefix, int size)
+{
+ beginWriteArray(qToAnyStringViewIgnoringNull(prefix), size);
+}
+
+void QSettings::setValue(const QString &key, const QVariant &value)
+{
+ setValue(qToAnyStringViewIgnoringNull(key), value);
+}
+
+void QSettings::remove(const QString &key)
+{
+ remove(qToAnyStringViewIgnoringNull(key));
+}
+
+bool QSettings::contains(const QString &key) const
+{
+ return contains(qToAnyStringViewIgnoringNull(key));
+}
+
+QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const
+{
+ return value(qToAnyStringViewIgnoringNull(key), defaultValue);
+}
+
+QVariant QSettings::value(const QString &key) const
+{
+ return value(qToAnyStringViewIgnoringNull(key));
+}
+
+#endif // QT_CONFIG(settings)
+
+#include "qversionnumber.h"
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+
+QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixIndex)
+{
+ return fromString(qToAnyStringViewIgnoringNull(string), suffixIndex);
+}
+
+QVersionNumber QVersionNumber::fromString(QStringView string, int *suffixIndex)
+{
+ return fromString(QAnyStringView{string}, suffixIndex);
+}
+
+QVersionNumber QVersionNumber::fromString(QLatin1StringView string, int *suffixIndex)
+{
+ return fromString(QAnyStringView{string}, suffixIndex);
+}
+
+QT_WARNING_POP
+
+// #include <qotherheader.h>
+// // implement removed functions from qotherheader.h
+// order sections alphabetically to reduce chances of merge conflicts
+
+#endif // QT_CORE_REMOVED_SINCE(6, 4)
+
+#if QT_CORE_REMOVED_SINCE(6, 5)
+
+#include "qbasictimer.h" // inlined API
+
+#include "qbuffer.h" // inline removed API
+
+#include "qdir.h"
+
+uint QDir::count() const
+{
+ return uint(count(QT6_CALL_NEW_OVERLOAD));
+}
+
+#if QT_POINTER_SIZE != 4
+QString QDir::operator[](int i) const
+{
+ return operator[](qsizetype{i});
+}
+#endif
+
+#include "qtenvironmentvariables.h"
+
+bool qputenv(const char *varName, const QByteArray &value)
+{
+ return qputenv(varName, qToByteArrayViewIgnoringNull(value));
+}
+
+#include "qmetatype.h"
+
+int QMetaType::idHelper() const
+{
+ Q_ASSERT(d_ptr);
+ return registerHelper(d_ptr);
+}
+
+#if QT_CONFIG(sharedmemory)
+#include "qsharedmemory.h"
+
+void QSharedMemory::setNativeKey(const QString &key)
+{
+ setNativeKey(key, QNativeIpcKey::legacyDefaultTypeForOs());
+}
+#endif
+
+#include "qvariant.h"
+
+// these implementations aren't as efficient as they used to be prior to
+// replacement, but there's no way to call the ambiguous overload
+QVariant::QVariant(const QUuid &uuid) : QVariant(QVariant::fromValue(uuid)) {}
+#ifndef QT_NO_GEOM_VARIANT
+#include "qline.h"
+#include "qpoint.h"
+#include "qrect.h"
+#include "qsize.h"
+QVariant::QVariant(const QPoint &pt) : QVariant(QVariant::fromValue(pt)) {}
+QVariant::QVariant(const QPointF &pt) : QVariant(QVariant::fromValue(pt)) {}
+QVariant::QVariant(const QRect &r) : QVariant(QVariant::fromValue(r)) {}
+QVariant::QVariant(const QRectF &r) : QVariant(QVariant::fromValue(r)) {}
+QVariant::QVariant(const QLine &l) : QVariant(QVariant::fromValue(l)) {}
+QVariant::QVariant(const QLineF &l) : QVariant(QVariant::fromValue(l)) {}
+QVariant::QVariant(const QSize &s) : QVariant(QVariant::fromValue(s)) {}
+QVariant::QVariant(const QSizeF &s) : QVariant(QVariant::fromValue(s)) {}
+#endif
+
+#if QT_CONFIG(xmlstreamreader)
+
+#include "qxmlstream.h"
+
+QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
+ : QXmlStreamReader(data, PrivateConstructorTag{})
+{
+}
+
+QXmlStreamReader::QXmlStreamReader(const QString &data)
+ : QXmlStreamReader(qToAnyStringViewIgnoringNull(data))
+{
+}
+
+QXmlStreamReader::QXmlStreamReader(const char *data)
+ : QXmlStreamReader(QAnyStringView(data))
+{
+}
+
+void QXmlStreamReader::addData(const QByteArray &data)
+{
+ addData<>(data);
+}
+void QXmlStreamReader::addData(const QString &data)
+{
+ addData(qToAnyStringViewIgnoringNull(data));
+}
+
+void QXmlStreamReader::addData(const char *data)
+{
+ addData(QAnyStringView(data));
+}
+
+#endif // QT_CONFIG(xmlstreamreader)
+
+#if QT_CONFIG(xmlstreamwriter)
+
+#include "qxmlstream.h"
+
+void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
+{
+ writeAttribute(qToAnyStringViewIgnoringNull(qualifiedName),
+ qToAnyStringViewIgnoringNull(value));
+}
+
+void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
+{
+ writeAttribute(qToAnyStringViewIgnoringNull(namespaceUri),
+ qToAnyStringViewIgnoringNull(name),
+ qToAnyStringViewIgnoringNull(value));
+}
+
+void QXmlStreamWriter::writeCDATA(const QString &text)
+{
+ writeCDATA(qToAnyStringViewIgnoringNull(text));
+}
+
+void QXmlStreamWriter::writeCharacters(const QString &text)
+{
+ writeCharacters(qToAnyStringViewIgnoringNull(text));
+}
+
+void QXmlStreamWriter::writeComment(const QString &text)
+{
+ writeComment(qToAnyStringViewIgnoringNull(text));
+}
+
+void QXmlStreamWriter::writeDTD(const QString &dtd)
+{
+ writeDTD(qToAnyStringViewIgnoringNull(dtd));
+}
+
+void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
+{
+ writeEmptyElement(qToAnyStringViewIgnoringNull(qualifiedName));
+}
+
+void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
+{
+ writeEmptyElement(qToAnyStringViewIgnoringNull(namespaceUri),
+ qToAnyStringViewIgnoringNull(name));
+}
+
+void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
+{
+ writeTextElement(qToAnyStringViewIgnoringNull(qualifiedName),
+ qToAnyStringViewIgnoringNull(text));
+}
+
+void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
+{
+ writeTextElement(qToAnyStringViewIgnoringNull(namespaceUri),
+ qToAnyStringViewIgnoringNull(name),
+ qToAnyStringViewIgnoringNull(text));
+}
+
+void QXmlStreamWriter::writeEntityReference(const QString &name)
+{
+ writeEntityReference(qToAnyStringViewIgnoringNull(name));
+}
+
+void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix)
+{
+ writeNamespace(qToAnyStringViewIgnoringNull(namespaceUri),
+ qToAnyStringViewIgnoringNull(prefix));
+}
+
+void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
+{
+ writeDefaultNamespace(qToAnyStringViewIgnoringNull(namespaceUri));
+}
+
+void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const QString &data)
+{
+ writeProcessingInstruction(qToAnyStringViewIgnoringNull(target),
+ qToAnyStringViewIgnoringNull(data));
+}
+
+void QXmlStreamWriter::writeStartDocument(const QString &version)
+{
+ writeStartDocument(qToAnyStringViewIgnoringNull(version));
+}
+
+void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalone)
+{
+ writeStartDocument(qToAnyStringViewIgnoringNull(version),
+ standalone);
+}
+
+void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
+{
+ writeStartElement(qToAnyStringViewIgnoringNull(qualifiedName));
+}
+
+void QXmlStreamWriter::writeStartElement(const QString &namespaceUri, const QString &name)
+{
+ writeStartElement(qToAnyStringViewIgnoringNull(namespaceUri),
+ qToAnyStringViewIgnoringNull(name));
+}
+
+#endif // QT_CONFIG(xmlstreamwriter)
+
+// inlined API
+#include "qfloat16.h"
+#include "qstring.h"
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically to reduce chances of merge conflicts
+
+#endif // QT_CORE_REMOVED_SINCE(6, 5)
+
+#if QT_CORE_REMOVED_SINCE(6, 6)
+
+#include "qmessageauthenticationcode.h"
+
+QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
+ const QByteArray &key)
+ : QMessageAuthenticationCode(method, qToByteArrayViewIgnoringNull(key)) {}
+
+void QMessageAuthenticationCode::setKey(const QByteArray &key)
+{
+ setKey(qToByteArrayViewIgnoringNull(key));
+}
+
+void QMessageAuthenticationCode::addData(const QByteArray &data)
+{
+ addData(qToByteArrayViewIgnoringNull(data));
+}
+
+QByteArray QMessageAuthenticationCode::hash(const QByteArray &msg, const QByteArray &key,
+ QCryptographicHash::Algorithm method)
+{
+ return hash(qToByteArrayViewIgnoringNull(msg),
+ qToByteArrayViewIgnoringNull(key), method);
+}
+
+#include "qobject.h" // inlined API
+
+#include "qrunnable.h"
+
+QRunnable *QRunnable::create(std::function<void()> functionToRun)
+{
+ return QRunnable::create<std::function<void()>>(std::move(functionToRun));
+}
+
+#include "qstring.h"
+
+qsizetype QString::toUcs4_helper(const ushort *uc, qsizetype length, uint *out)
+{
+ return toUcs4_helper(reinterpret_cast<const char16_t *>(uc), length,
+ reinterpret_cast<char32_t *>(out));
+}
+
+#if QT_CONFIG(thread)
+#include "qreadwritelock.h"
+
+bool QReadWriteLock::tryLockForRead()
+{
+ return tryLockForRead(0);
+}
+
+bool QReadWriteLock::tryLockForWrite()
+{
+ return tryLockForWrite(0);
+}
+
+#include "qthreadpool.h"
+#include "private/qthreadpool_p.h"
+
+void QThreadPool::start(std::function<void()> functionToRun, int priority)
+{
+ if (!functionToRun)
+ return;
+ start(QRunnable::create(std::move(functionToRun)), priority);
+}
+
+bool QThreadPool::tryStart(std::function<void()> functionToRun)
+{
+ if (!functionToRun)
+ return false;
+
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ if (!d->allThreads.isEmpty() && d->areAllThreadsActive())
+ return false;
+
+ QRunnable *runnable = QRunnable::create(std::move(functionToRun));
+ if (d->tryStart(runnable))
+ return true;
+ delete runnable;
+ return false;
+}
+
+void QThreadPool::startOnReservedThread(std::function<void()> functionToRun)
+{
+ if (!functionToRun)
+ return releaseThread();
+
+ startOnReservedThread(QRunnable::create(std::move(functionToRun)));
+}
+
+#endif // QT_CONFIG(thread)
+
+#include "qxmlstream.h"
+
+QStringView QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
+{
+ return value(qToAnyStringViewIgnoringNull(namespaceUri), qToAnyStringViewIgnoringNull(name));
+}
+
+QStringView QXmlStreamAttributes::value(const QString &namespaceUri, QLatin1StringView name) const
+{
+ return value(qToAnyStringViewIgnoringNull(namespaceUri), QAnyStringView(name));
+}
+
+QStringView QXmlStreamAttributes::value(QLatin1StringView namespaceUri, QLatin1StringView name) const
+{
+ return value(QAnyStringView(namespaceUri), QAnyStringView(name));
+}
+
+QStringView QXmlStreamAttributes::value(const QString &qualifiedName) const
+{
+ return value(qToAnyStringViewIgnoringNull(qualifiedName));
+}
+
+QStringView QXmlStreamAttributes::value(QLatin1StringView qualifiedName) const
+{
+ return value(QAnyStringView(qualifiedName));
+}
+
+// inlined API
+#if QT_CONFIG(thread)
+#include "qmutex.h"
+#include "qreadwritelock.h"
+#include "qsemaphore.h"
+#endif
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically to reduce chances of merge conflicts
+
+#endif // QT_CORE_REMOVED_SINCE(6, 6)
+
+#if QT_CORE_REMOVED_SINCE(6, 7)
+
+#include "qbitarray.h"
+
+QBitArray QBitArray::operator~() const
+{
+ return QBitArray(*this).inverted_inplace();
+}
+
+#include "qbytearray.h" // also includes inlined API
+
+QByteArray QByteArray::left(qsizetype len) const
+{
+ if (len >= size())
+ return *this;
+ if (len < 0)
+ len = 0;
+ return QByteArray(data(), len);
+}
+
+QByteArray QByteArray::right(qsizetype len) const
+{
+ if (len >= size())
+ return *this;
+ if (len < 0)
+ len = 0;
+ return QByteArray(end() - len, len);
+}
+
+QByteArray QByteArray::mid(qsizetype pos, qsizetype len) const
+{
+ qsizetype p = pos;
+ qsizetype l = len;
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &p, &l)) {
+ case QContainerImplHelper::Null:
+ return QByteArray();
+ case QContainerImplHelper::Empty:
+ {
+ return QByteArray(DataPointer::fromRawData(&_empty, 0));
+ }
+ case QContainerImplHelper::Full:
+ return *this;
+ case QContainerImplHelper::Subset:
+ return QByteArray(d.data() + p, l);
+ }
+ Q_UNREACHABLE_RETURN(QByteArray());
+}
+
+#ifdef Q_CC_MSVC
+// previously inline methods, only needed for MSVC compat
+QByteArray QByteArray::first(qsizetype n) const
+{ return sliced(0, n); }
+QByteArray QByteArray::last(qsizetype n) const
+{ return sliced(size() - n, n); }
+QByteArray QByteArray::sliced(qsizetype pos) const
+{ return sliced(pos, size() - pos); }
+QByteArray QByteArray::sliced(qsizetype pos, qsizetype n) const
+{ verify(pos, n); return QByteArray(d.data() + pos, n); }
+QByteArray QByteArray::chopped(qsizetype n) const
+{ return sliced(0, size() - n); }
+#endif
+
+#include "qcborstreamreader.h"
+
+QCborError QCborStreamReader::lastError()
+{
+ return std::as_const(*this).lastError();
+}
+
+#include "qdatetime.h"
+
+QDateTime::QDateTime(QDate date, QTime time, const QTimeZone &timeZone)
+ : QDateTime(date, time, timeZone, TransitionResolution::LegacyBehavior) {}
+QDateTime::QDateTime(QDate date, QTime time)
+ : QDateTime(date, time, TransitionResolution::LegacyBehavior) {}
+void QDateTime::setDate(QDate date) { setDate(date, TransitionResolution::LegacyBehavior); }
+void QDateTime::setTime(QTime time) { setTime(time, TransitionResolution::LegacyBehavior); }
+void QDateTime::setTimeZone(const QTimeZone &toZone)
+{
+ setTimeZone(toZone, TransitionResolution::LegacyBehavior);
+}
+
+bool QDateTime::precedes(const QDateTime &other) const
+{
+ return compareThreeWay(*this, other) < 0;
+}
+
+#include "qdatastream.h"
+
+QDataStream &QDataStream::writeBytes(const char *s, uint len)
+{
+ return writeBytes(s, qint64(len));
+}
+
+int QDataStream::skipRawData(int len)
+{
+ return int(skipRawData(qint64(len)));
+}
+
+int QDataStream::readBlock(char *data, int len)
+{
+ return int(readBlock(data, qint64(len)));
+}
+
+int QDataStream::readRawData(char *s, int len)
+{
+ return int(readRawData(s, qint64(len)));
+}
+
+int QDataStream::writeRawData(const char *s, int len)
+{
+ return writeRawData(s, qint64(len));
+}
+
+#if defined(Q_OS_ANDROID)
+
+#include "qjniobject.h"
+
+jclass QJniObject::loadClass(const QByteArray &className, JNIEnv *env, bool /*binEncoded*/)
+{
+ return QJniObject::loadClass(className, env);
+}
+
+QByteArray QJniObject::toBinaryEncClassName(const QByteArray &className)
+{
+ return QByteArray(className).replace('/', '.');
+}
+
+void QJniObject::callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const
+{
+ env->CallVoidMethodV(javaObject(), id, args);
+}
+
+#endif // Q_OS_ANDROID
+
+#include "qlocale.h"
+
+QStringList QLocale::uiLanguages() const
+{
+ return uiLanguages(TagSeparator::Dash);
+}
+
+QString QLocale::name() const
+{
+ return name(TagSeparator::Underscore);
+}
+
+QString QLocale::bcp47Name() const
+{
+ return bcp47Name(TagSeparator::Dash);
+}
+
+QDate QLocale::toDate(const QString &string, FormatType format) const
+{
+ return toDate(string, dateFormat(format), DefaultTwoDigitBaseYear);
+}
+
+QDate QLocale::toDate(const QString &string, FormatType format, QCalendar cal) const
+{
+ return toDate(string, dateFormat(format), cal, DefaultTwoDigitBaseYear);
+}
+
+QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
+{
+ return toDateTime(string, dateTimeFormat(format), DefaultTwoDigitBaseYear);
+}
+
+QDateTime QLocale::toDateTime(const QString &string, FormatType format, QCalendar cal) const
+{
+ return toDateTime(string, dateTimeFormat(format), cal, DefaultTwoDigitBaseYear);
+}
+
+QDate QLocale::toDate(const QString &string, const QString &format) const
+{
+ return toDate(string, format, QCalendar(), DefaultTwoDigitBaseYear);
+}
+
+QDate QLocale::toDate(const QString &string, const QString &format, QCalendar cal) const
+{
+ return toDate(string, format, cal, DefaultTwoDigitBaseYear);
+}
+
+QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
+{
+ return toDateTime(string, format, QCalendar(), DefaultTwoDigitBaseYear);
+}
+
+QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCalendar cal) const
+{
+ return toDateTime(string, format, cal, DefaultTwoDigitBaseYear);
+}
+
+#include "qobject.h"
+
+void qt_qFindChildren_helper(const QObject *parent, const QMetaObject &mo,
+ QList<void*> *list, Qt::FindChildOptions options)
+{
+ qt_qFindChildren_helper(parent, QAnyStringView(), mo, list, options);
+}
+
+void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QMetaObject &mo,
+ QList<void*> *list, Qt::FindChildOptions options)
+{
+ qt_qFindChildren_helper(parent, QAnyStringView{name}, mo, list, options);
+}
+
+QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo,
+ Qt::FindChildOptions options)
+{
+ return qt_qFindChild_helper(parent, QAnyStringView{name}, mo, options);
+}
+
+void QObject::moveToThread(QThread *targetThread)
+{
+ moveToThread(targetThread, QT6_CALL_NEW_OVERLOAD);
+}
+
+#include "qobjectdefs.h"
+
+bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret)
+{
+ return invokeMethodImpl(object, slot, type, 1, &ret, nullptr, nullptr);
+}
+
+#include "qstring.h"
+
+QString QString::left(qsizetype n) const
+{
+ if (size_t(n) >= size_t(size()))
+ return *this;
+ return QString((const QChar*) d.data(), n);
+}
+
+QString QString::right(qsizetype n) const
+{
+ if (size_t(n) >= size_t(size()))
+ return *this;
+ return QString(constData() + size() - n, n);
+}
+
+QString QString::mid(qsizetype position, qsizetype n) const
+{
+ qsizetype p = position;
+ qsizetype l = n;
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &p, &l)) {
+ case QContainerImplHelper::Null:
+ return QString();
+ case QContainerImplHelper::Empty:
+ return QString(DataPointer::fromRawData(&_empty, 0));
+ case QContainerImplHelper::Full:
+ return *this;
+ case QContainerImplHelper::Subset:
+ return QString(constData() + p, l);
+ }
+ Q_UNREACHABLE_RETURN(QString());
+}
+
+#ifdef Q_CC_MSVC
+// previously inline methods, only needed for MSVC compat
+QString QString::first(qsizetype n) const
+{ return sliced(0, n); }
+QString QString::last(qsizetype n) const
+{ return sliced(size() - n, n); }
+QString QString::sliced(qsizetype pos) const
+{ return sliced(pos, size() - pos); }
+QString QString::sliced(qsizetype pos, qsizetype n) const
+{ verify(pos, n); return QString(begin() + pos, n); }
+QString QString::chopped(qsizetype n) const
+{ return sliced(0, size() - n); }
+#endif
+
+#include "qtimezone.h"
+
+bool QTimeZone::operator==(const QTimeZone &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+bool QTimeZone::operator!=(const QTimeZone &other) const
+{
+ return !comparesEqual(*this, other);
+}
+
+#include "qurl.h"
+
+QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode mode)
+{
+ return QUrl::fromEncoded(QByteArrayView(input), mode);
+}
+
+#include "qtimer.h" // inlined API
+
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically to reduce chances of merge conflicts
+
+#endif // QT_CORE_REMOVED_SINCE(6, 7)
+
+#if QT_CORE_REMOVED_SINCE(6, 8)
+#include "qbitarray.h" // inlined API
+
+#include "qbytearray.h" // inlined API
+
+#include "qcborarray.h" // inlined API
+
+#include "qcbormap.h" // inlined API
+
+#include "qcborvalue.h" // inlined API
+
+#include "qdatastream.h" // inlined API
+
+QDataStream &QDataStream::operator<<(bool i)
+{
+ return (*this << qint8(i));
+}
+
+#include "qdir.h" // inlined API
+
+bool QDir::operator==(const QDir &dir) const
+{
+ return comparesEqual(*this, dir);
+}
+
+#include "qeasingcurve.h"
+
+bool QEasingCurve::operator==(const QEasingCurve &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+#include "qfileinfo.h" // inlined API
+
+bool QFileInfo::operator==(const QFileInfo &fileinfo) const
+{
+ return comparesEqual(*this, fileinfo);
+}
+
+#include "qitemselectionmodel.h" // inlined API
+
+#include "qjsonarray.h"
+
+bool QJsonArray::operator==(const QJsonArray &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+bool QJsonArray::operator!=(const QJsonArray &other) const
+{
+ return !comparesEqual(*this, other);
+}
+
+#include "qjsondocument.h"
+
+bool QJsonDocument::operator==(const QJsonDocument &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+#include "qjsonobject.h"
+
+bool QJsonObject::operator==(const QJsonObject &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+
+bool QJsonObject::operator!=(const QJsonObject &other) const
+{
+ return !comparesEqual(*this, other);
+}
+
+#include "qjsonvalue.h"
+
+bool QJsonValue::operator==(const QJsonValue &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+bool QJsonValue::operator!=(const QJsonValue &other) const
+{
+ return !comparesEqual(*this, other);
+}
+
+#include "qline.h" // inlined API
+
+#include "qmimetype.h"
+
+bool QMimeType::operator==(const QMimeType &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+#include "qobject.h"
+#include "qnumeric.h"
+
+int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType)
+{
+ using namespace std::chrono;
+ using ratio = std::ratio_divide<std::milli, std::nano>;
+ nanoseconds::rep r;
+ if (qMulOverflow<ratio::num>(time.count(), &r)) {
+ qWarning("QObject::startTimer(std::chrono::milliseconds): "
+ "'time' arg overflowed when converted to nanoseconds.");
+ r = nanoseconds::max().count();
+ }
+ return startTimer(nanoseconds{r}, timerType);
+}
+
+#if QT_CONFIG(processenvironment)
+#include "qprocess.h" // inlined API
+
+bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const
+{
+ return comparesEqual(*this, other);
+}
+#endif // QT_CONFIG(processenvironment)
+
+#if QT_CONFIG(regularexpression)
+#include "qregularexpression.h"
+
+bool QRegularExpressionMatch::hasCaptured(QStringView name) const
+{
+ return hasCaptured(QAnyStringView(name));
+}
+
+QString QRegularExpressionMatch::captured(QStringView name) const
+{
+ return captured(QAnyStringView(name));
+}
+
+QStringView QRegularExpressionMatch::capturedView(QStringView name) const
+{
+ return capturedView(QAnyStringView(name));
+}
+
+qsizetype QRegularExpressionMatch::capturedStart(QStringView name) const
+{
+ return capturedStart(QAnyStringView(name));
+}
+
+qsizetype QRegularExpressionMatch::capturedLength(QStringView name) const
+{
+ return capturedLength(QAnyStringView(name));
+}
+
+qsizetype QRegularExpressionMatch::capturedEnd(QStringView name) const
+{
+ return capturedEnd(QAnyStringView(name));
+}
+
+bool QRegularExpression::operator==(const QRegularExpression &other) const
+{
+ return comparesEqual(*this, other);
+}
+#endif // QT_CONFIG(regularexpression)
+
+#include "qstring.h" // inlined API
+
+#if QT_CONFIG(thread)
+# include "qthreadpool.h" // inlined API
+#endif
+
+#include "qurl.h"
+
+bool QUrl::operator<(const QUrl &url) const
+{
+ return is_lt(compareThreeWay(*this, url));
+}
+
+bool QUrl::operator==(const QUrl &url) const
+{
+ return comparesEqual(*this, url);
+}
+
+bool QUrl::operator!=(const QUrl &url) const
+{
+ return !comparesEqual(*this, url);
+}
+
+#include "qurlquery.h"
+
+bool QUrlQuery::operator==(const QUrlQuery &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+#include "qxmlstream.h" // inlined API
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically to reduce chances of merge conflicts
+
+#endif // QT_CORE_REMOVED_SINCE(6, 8)
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index 2637e2abfc..18c09d2241 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#### Inputs
@@ -6,22 +9,34 @@
set(INPUT_doubleconversion "undefined" CACHE STRING "")
set_property(CACHE INPUT_doubleconversion PROPERTY STRINGS undefined no qt system)
+# input libb2
+set(INPUT_libb2 "undefined" CACHE STRING "")
+set_property(CACHE INPUT_libb2 PROPERTY STRINGS undefined no qt system)
+
#### Libraries
-qt_find_package(WrapDoubleConversion PROVIDED_TARGETS WrapDoubleConversion::WrapDoubleConversion MODULE_NAME core QMAKE_LIB doubleconversion)
+if((UNIX AND NOT QNX) OR QT_FIND_ALL_PACKAGES_ALWAYS)
+ # QNX's libbacktrace has an API wholly different from all the other Unix
+ # offerings
+ qt_find_package(WrapBacktrace PROVIDED_TARGETS WrapBacktrace::WrapBacktrace MODULE_NAME core QMAKE_LIB backtrace)
+endif()
+qt_find_package(WrapSystemDoubleConversion
+ PROVIDED_TARGETS WrapSystemDoubleConversion::WrapSystemDoubleConversion
+ MODULE_NAME core QMAKE_LIB doubleconversion)
qt_find_package(GLIB2 PROVIDED_TARGETS GLIB2::GLIB2 MODULE_NAME core QMAKE_LIB glib)
-qt_find_package(ICU COMPONENTS i18n uc data PROVIDED_TARGETS ICU::i18n ICU::uc ICU::data MODULE_NAME core QMAKE_LIB icu)
+qt_find_package(ICU 50.1 COMPONENTS i18n uc data PROVIDED_TARGETS ICU::i18n ICU::uc ICU::data
+ MODULE_NAME core QMAKE_LIB icu)
+
if(QT_FEATURE_dlopen)
qt_add_qmake_lib_dependency(icu libdl)
endif()
qt_find_package(Libsystemd PROVIDED_TARGETS PkgConfig::Libsystemd MODULE_NAME core QMAKE_LIB journald)
qt_find_package(WrapAtomic PROVIDED_TARGETS WrapAtomic::WrapAtomic MODULE_NAME core QMAKE_LIB libatomic)
+qt_find_package(Libb2 PROVIDED_TARGETS Libb2::Libb2 MODULE_NAME core QMAKE_LIB libb2)
qt_find_package(WrapRt PROVIDED_TARGETS WrapRt::WrapRt MODULE_NAME core QMAKE_LIB librt)
-qt_find_package(LTTngUST PROVIDED_TARGETS LTTng::UST MODULE_NAME core QMAKE_LIB lttng-ust)
-qt_add_qmake_lib_dependency(lttng-ust libdl)
-qt_find_package(WrapSystemPCRE2 PROVIDED_TARGETS WrapSystemPCRE2::WrapSystemPCRE2 MODULE_NAME core QMAKE_LIB pcre2)
+qt_find_package(WrapSystemPCRE2 10.20 PROVIDED_TARGETS WrapSystemPCRE2::WrapSystemPCRE2 MODULE_NAME core QMAKE_LIB pcre2)
set_package_properties(WrapPCRE2 PROPERTIES TYPE REQUIRED)
if((QNX) OR QT_FIND_ALL_PACKAGES_ALWAYS)
qt_find_package(PPS PROVIDED_TARGETS PPS::PPS MODULE_NAME core QMAKE_LIB pps)
@@ -35,8 +50,7 @@ qt_find_package(Slog2 PROVIDED_TARGETS Slog2::Slog2 MODULE_NAME core QMAKE_LIB s
qt_config_compile_test(atomicfptr
LABEL "working std::atomic for function pointers"
CODE
-"
-#include <atomic>
+"#include <atomic>
typedef void (*fptr)(int);
typedef std::atomic<fptr> atomicfptr;
void testfunction(int) { }
@@ -50,9 +64,9 @@ void test(volatile atomicfptr &a)
}
a.store(&testfunction, std::memory_order_release);
}
-int main(int argc, char **argv)
+
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
atomicfptr fptr(testfunction);
test(fptr);
@@ -67,13 +81,11 @@ qt_config_compile_test(clock_monotonic
LIBRARIES
WrapRt::WrapRt
CODE
-"
-#include <unistd.h>
+"#include <unistd.h>
#include <time.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK-0 >= 0)
timespec ts;
@@ -86,6 +98,18 @@ clock_gettime(CLOCK_MONOTONIC, &ts);
}
")
+# close_range
+qt_config_compile_test(close_range
+ LABEL "close_range()"
+ CODE
+"#include <unistd.h>
+
+int main()
+{
+ return close_range(3, 1024, 0) != 0;
+}
+")
+
# cloexec
qt_config_compile_test(cloexec
LABEL "O_CLOEXEC"
@@ -96,9 +120,8 @@ qt_config_compile_test(cloexec
#include <fcntl.h>
#include <unistd.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
int pipes[2];
(void) pipe2(pipes, O_CLOEXEC | O_NONBLOCK);
@@ -114,56 +137,14 @@ int pipes[2];
}
")
-# cxx11_future
-if (UNIX)
- set(cxx11_future_TEST_LIBRARIES pthread)
-endif()
-qt_config_compile_test(cxx11_future
- LABEL "C++11 <future>"
- LIBRARIES
- "${cxx11_future_TEST_LIBRARIES}"
- CODE
-"
-#include <future>
-
-int main(int argc, char **argv)
-{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-std::future<int> f = std::async([]() { return 42; });
-(void)f.get();
- /* END TEST: */
- return 0;
-}
-")
-
-# cxx11_random
-qt_config_compile_test(cxx11_random
- LABEL "C++11 <random>"
- CODE
-"
-#include <random>
-
-int main(int argc, char **argv)
-{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-std::mt19937 mt(0);
- /* END TEST: */
- return 0;
-}
-")
-
# cxx17_filesystem
qt_config_compile_test(cxx17_filesystem
LABEL "C++17 <filesystem>"
CODE
-"
-#include <filesystem>
+"#include <filesystem>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
std::filesystem::copy(
std::filesystem::path(\"./file\"),
@@ -171,74 +152,49 @@ std::filesystem::copy(
/* END TEST: */
return 0;
}
-"# FIXME: qmake: CONFIG += c++17
+"
)
-# eventfd
-qt_config_compile_test(eventfd
- LABEL "eventfd"
+# dladdr
+qt_config_compile_test(dladdr
+ LABEL "dladdr"
+ LIBRARIES
+ dl
CODE
-"
-#include <sys/eventfd.h>
-
-int main(int argc, char **argv)
+"#define _GNU_SOURCE 1
+#include <dlfcn.h>
+int i = 0;
+int main(void)
{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-eventfd_t value;
-int fd = eventfd(0, EFD_CLOEXEC);
-eventfd_read(fd, &value);
-eventfd_write(fd, value);
- /* END TEST: */
+ Dl_info info;
+ dladdr(&i, &info);
return 0;
-}
-")
+}"
+)
# futimens
qt_config_compile_test(futimens
LABEL "futimens()"
CODE
-"
-#include <sys/stat.h>
+"#include <sys/stat.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
futimens(-1, 0);
/* END TEST: */
return 0;
}
-"# FIXME: qmake: ["# Block futimens() on Apple platforms unless it's available on ALL", '# deployment targets. This simplifies the logic at the call site', "# dramatically, as it isn't strictly needed compared to futimes().", 'darwin: QMAKE_CXXFLAGS += -Werror=unguarded-availability -Werror=unguarded-availability-new', 'CONFIG += warn_on']
-)
-
-# futimes
-qt_config_compile_test(futimes
- LABEL "futimes()"
- CODE
-"
-#include <sys/time.h>
-
-int main(int argc, char **argv)
-{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-futimes(-1, 0);
- /* END TEST: */
- return 0;
-}
")
# getauxval
qt_config_compile_test(getauxval
LABEL "getauxval()"
CODE
-"
-#include <sys/auxv.h>
+"#include <sys/auxv.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
(void) getauxval(AT_NULL);
/* END TEST: */
@@ -250,12 +206,13 @@ int main(int argc, char **argv)
qt_config_compile_test(getentropy
LABEL "getentropy()"
CODE
-"
-#include <unistd.h>
+"#include <unistd.h>
+#if __has_include(<sys/random.h>)
+# include <sys/random.h>
+#endif
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
char buf[32];
(void) getentropy(buf, sizeof(buf));
@@ -264,89 +221,88 @@ char buf[32];
}
")
-# glibc
-qt_config_compile_test(glibc
- LABEL "GNU libc"
+# inotify
+qt_config_compile_test(inotify
+ LABEL "inotify"
CODE
-"
-#include <stdlib.h>
+"#include <sys/inotify.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
-return __GLIBC__;
+inotify_init();
+inotify_add_watch(0, \"foobar\", IN_ACCESS);
+inotify_rm_watch(0, 1);
/* END TEST: */
return 0;
}
")
-# inotify
-qt_config_compile_test(inotify
- LABEL "inotify"
+qt_config_compile_test(sysv_shm
+ LABEL "System V/XSI shared memory"
CODE
-"
-#include <sys/inotify.h>
+"#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <fcntl.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-inotify_init();
-inotify_add_watch(0, \"foobar\", IN_ACCESS);
-inotify_rm_watch(0, 1);
- /* END TEST: */
+ key_t unix_key = ftok(\"test\", 'Q');
+ shmget(unix_key, 0, 0666 | IPC_CREAT | IPC_EXCL);
+ shmctl(0, 0, (struct shmid_ds *)(0));
return 0;
}
")
-# ipc_sysv
-qt_config_compile_test(ipc_sysv
- LABEL "SysV IPC"
+qt_config_compile_test(sysv_sem
+ LABEL "System V/XSI semaphores"
CODE
-"
-#include <sys/types.h>
+"#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
-#include <sys/shm.h>
#include <fcntl.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-key_t unix_key = ftok(\"test\", 'Q');
-semctl(semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL), 0, IPC_RMID, 0);
-shmget(unix_key, 0, 0666 | IPC_CREAT | IPC_EXCL);
-shmctl(0, 0, (struct shmid_ds *)(0));
- /* END TEST: */
+ key_t unix_key = ftok(\"test\", 'Q');
+ semctl(semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL), 0, IPC_RMID, 0);
return 0;
}
")
-# ipc_posix
if (LINUX)
- set(ipc_posix_TEST_LIBRARIES pthread rt)
+ set(ipc_posix_TEST_LIBRARIES pthread WrapRt::WrapRt)
endif()
-qt_config_compile_test(ipc_posix
- LABEL "POSIX IPC"
+qt_config_compile_test(posix_shm
+ LABEL "POSIX shared memory"
LIBRARIES
"${ipc_posix_TEST_LIBRARIES}"
CODE
-"
-#include <sys/types.h>
+"#include <sys/types.h>
#include <sys/mman.h>
+#include <fcntl.h>
+
+int main(void)
+{
+ shm_open(\"test\", O_RDWR | O_CREAT | O_EXCL, 0666);
+ shm_unlink(\"test\");
+ return 0;
+}
+")
+
+qt_config_compile_test(posix_sem
+ LABEL "POSIX semaphores"
+ LIBRARIES
+ "${ipc_posix_TEST_LIBRARIES}"
+ CODE
+"#include <sys/types.h>
#include <semaphore.h>
#include <fcntl.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-sem_close(sem_open(\"test\", O_CREAT | O_EXCL, 0666, 0));
-shm_open(\"test\", O_RDWR | O_CREAT | O_EXCL, 0666);
-shm_unlink(\"test\");
- /* END TEST: */
+ sem_close(sem_open(\"test\", O_CREAT | O_EXCL, 0666, 0));
return 0;
}
")
@@ -359,9 +315,8 @@ qt_config_compile_test(linkat
#include <fcntl.h>
#include <unistd.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
linkat(AT_FDCWD, \"foo\", AT_FDCWD, \"bar\", AT_SYMLINK_FOLLOW);
/* END TEST: */
@@ -373,13 +328,11 @@ linkat(AT_FDCWD, \"foo\", AT_FDCWD, \"bar\", AT_SYMLINK_FOLLOW);
qt_config_compile_test(ppoll
LABEL "ppoll()"
CODE
-"
-#include <signal.h>
+"#include <signal.h>
#include <poll.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
struct pollfd pfd;
struct timespec ts;
@@ -394,14 +347,12 @@ ppoll(&pfd, 1, &ts, &sig);
qt_config_compile_test(pollts
LABEL "pollts()"
CODE
-"
-#include <poll.h>
+"#include <poll.h>
#include <signal.h>
#include <time.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
struct pollfd pfd;
struct timespec ts;
@@ -416,12 +367,10 @@ pollts(&pfd, 1, &ts, &sig);
qt_config_compile_test(poll
LABEL "poll()"
CODE
-"
-#include <poll.h>
+"#include <poll.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
struct pollfd pfd;
poll(&pfd, 1, 0);
@@ -438,9 +387,8 @@ qt_config_compile_test(renameat2
#include <fcntl.h>
#include <stdio.h>
-int main(int argc, char **argv)
+int main(int, char **argv)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE | RENAME_WHITEOUT);
/* END TEST: */
@@ -448,82 +396,67 @@ renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE | RENAME_WHITEO
}
")
-# statx
-qt_config_compile_test(statx
- LABEL "statx() in libc"
+# cpp_winrt
+qt_config_compile_test(cpp_winrt
+ LABEL "cpp/winrt"
+ LIBRARIES
+ runtimeobject
CODE
-"#define _ATFILE_SOURCE 1
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
+"// Including winrt/base.h causes an error in some configurations (Windows 10 SDK + c++20)
+# include <winrt/base.h>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-struct statx statxbuf;
-unsigned int mask = STATX_BASIC_STATS;
-return statx(AT_FDCWD, \"\", AT_STATX_SYNC_AS_STAT, mask, &statxbuf);
- /* END TEST: */
return 0;
}
")
-# syslog
-qt_config_compile_test(syslog
- LABEL "syslog"
+# <stacktrace>
+qt_config_compile_test(cxx23_stacktrace
+ LABEL "C++23 <stacktrace> support"
CODE
-"
-#include <syslog.h>
+"#include <stacktrace>
+#if !defined(__cpp_lib_stacktrace)
+#error
+#endif
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
-openlog(\"qt\", 0, LOG_USER);
-syslog(LOG_INFO, \"configure\");
-closelog();
+const auto backtrace = std::stacktrace::current();
/* END TEST: */
- return 0;
}
-")
+"
+ CXX_STANDARD 23
+)
-# xlocalescanprint
-qt_config_compile_test(xlocalescanprint
- LABEL "xlocale.h (or equivalents)"
+# <future>
+qt_config_compile_test(cxx_std_async_noncopyable
+ LABEL "std::async() NonCopyable"
CODE
-"
+"// Calling std::async with lambda which takes non-copyable argument causes compilation error on
+// some platforms (VxWorks 24.03 and older with C++17-compatibility for example)
+#include <future>
-#define QT_BEGIN_NAMESPACE
-#define QT_END_NAMESPACE
+class NonCopyable {
+public:
+ NonCopyable(const NonCopyable&) = delete;
+ NonCopyable(NonCopyable&&) = default;
-#ifdef _MSVC_VER
-#define Q_CC_MSVC _MSVC_VER
-#endif
+ NonCopyable(int value)
+ :value (value)
+ {}
-#define QT_NO_DOUBLECONVERSION
+ int value;
+};
-#include QDSP_P_H
-int main(int argc, char **argv)
-{
- (void)argc; (void)argv;
- /* BEGIN TEST: */
-#ifdef _MSVC_VER
-_locale_t invalidLocale = NULL;
-#else
-locale_t invalidLocale = NULL;
-#endif
-double a = 3.4;
-qDoubleSnprintf(argv[0], 1, invalidLocale, \"invalid format\", a);
-qDoubleSscanf(argv[0], invalidLocale, \"invalid format\", &a, &argc);
- /* END TEST: */
- return 0;
+int main(int argc, char** argv) {
+ return std::async(
+ std::launch::deferred,
+ [](NonCopyable value) { return value.value; },
+ NonCopyable(argc - 1)).get();
}
-"# FIXME: qmake: DEFINES += QDSP_P_H=$$shell_quote(\"@PWD@/text/qdoublescanprint_p.h\")
-)
-
-
+")
#### Features
@@ -536,37 +469,37 @@ qt_feature("clock-monotonic" PUBLIC
CONDITION QT_FEATURE_clock_gettime AND TEST_clock_monotonic
)
qt_feature_definition("clock-monotonic" "QT_NO_CLOCK_MONOTONIC" NEGATE VALUE "1")
-qt_feature("doubleconversion" PUBLIC PRIVATE
+qt_feature("close_range" PRIVATE
+ LABEL "close_range()"
+ CONDITION QT_FEATURE_process AND TEST_close_range
+ AUTODETECT UNIX
+)
+qt_feature("doubleconversion" PRIVATE
LABEL "DoubleConversion"
)
qt_feature_definition("doubleconversion" "QT_NO_DOUBLECONVERSION" NEGATE VALUE "1")
qt_feature("system-doubleconversion" PRIVATE
LABEL " Using system DoubleConversion"
- CONDITION QT_FEATURE_doubleconversion AND WrapDoubleConversion_FOUND
+ CONDITION QT_FEATURE_doubleconversion AND WrapSystemDoubleConversion_FOUND
ENABLE INPUT_doubleconversion STREQUAL 'system'
DISABLE INPUT_doubleconversion STREQUAL 'qt'
)
qt_feature("cxx11_future" PUBLIC
LABEL "C++11 <future>"
- CONDITION TEST_cxx11_future
+ CONDITION TEST_cxx_std_async_noncopyable
)
qt_feature("cxx17_filesystem" PUBLIC
LABEL "C++17 <filesystem>"
CONDITION TEST_cxx17_filesystem
)
-qt_feature("eventfd" PUBLIC
- LABEL "eventfd"
- CONDITION NOT WASM AND TEST_eventfd
+qt_feature("dladdr" PRIVATE
+ LABEL "dladdr"
+ CONDITION QT_FEATURE_dlopen AND TEST_dladdr
)
-qt_feature_definition("eventfd" "QT_NO_EVENTFD" NEGATE VALUE "1")
qt_feature("futimens" PRIVATE
LABEL "futimens()"
CONDITION NOT WIN32 AND TEST_futimens
)
-qt_feature("futimes" PRIVATE
- LABEL "futimes()"
- CONDITION NOT WIN32 AND NOT QT_FEATURE_futimens AND TEST_futimes
-)
qt_feature("getauxval" PRIVATE
LABEL "getauxval()"
CONDITION LINUX AND TEST_getauxval
@@ -581,11 +514,6 @@ qt_feature("glib" PUBLIC PRIVATE
CONDITION GLIB2_FOUND
)
qt_feature_definition("glib" "QT_NO_GLIB" NEGATE VALUE "1")
-qt_feature("glibc" PRIVATE
- LABEL "GNU libc"
- AUTODETECT LINUX
- CONDITION TEST_glibc
-)
qt_feature("icu" PRIVATE
LABEL "ICU"
AUTODETECT NOT WIN32
@@ -597,9 +525,11 @@ qt_feature("inotify" PUBLIC PRIVATE
)
qt_feature_definition("inotify" "QT_NO_INOTIFY" NEGATE VALUE "1")
qt_feature("ipc_posix"
- LABEL "Using POSIX IPC"
- AUTODETECT NOT WIN32
- CONDITION NOT TEST_ipc_sysv AND TEST_ipc_posix
+ LABEL "Defaulting legacy IPC to POSIX"
+ CONDITION TEST_posix_shm AND TEST_posix_sem AND (
+ FEATURE_ipc_posix OR (APPLE AND QT_FEATURE_appstore_compliant)
+ OR NOT TEST_sysv_shm OR NOT TEST_sysv_sem
+ )
)
qt_feature_definition("ipc_posix" "QT_POSIX_IPC")
qt_feature("journald" PRIVATE
@@ -607,10 +537,17 @@ qt_feature("journald" PRIVATE
AUTODETECT OFF
CONDITION Libsystemd_FOUND
)
+# Used by QCryptographicHash for the BLAKE2 hashing algorithms
+qt_feature("system-libb2" PRIVATE
+ LABEL "Using system libb2"
+ CONDITION Libb2_FOUND
+ ENABLE INPUT_libb2 STREQUAL 'system'
+ DISABLE INPUT_libb2 STREQUAL 'no' OR INPUT_libb2 STREQUAL 'qt'
+)
# Currently only used by QTemporaryFile; linkat() exists on Android, but hardlink creation fails due to security rules
qt_feature("linkat" PRIVATE
LABEL "linkat()"
- AUTODETECT LINUX AND NOT ANDROID
+ AUTODETECT ( LINUX AND NOT ANDROID ) OR HURD
CONDITION TEST_linkat
)
qt_feature("std-atomic64" PUBLIC
@@ -629,8 +566,8 @@ qt_feature("mimetype-database" PRIVATE
)
qt_feature("pcre2"
LABEL "PCRE2"
- ENABLE INPUT_pcre STREQUAL 'qt'
- DISABLE INPUT_pcre STREQUAL 'no' OR INPUT_pcre STREQUAL 'system'
+ ENABLE INPUT_pcre STREQUAL 'qt' OR QT_FEATURE_system_pcre2
+ DISABLE INPUT_pcre STREQUAL 'no'
)
qt_feature_config("pcre2" QMAKE_PRIVATE_CONFIG)
qt_feature("system-pcre2" PRIVATE
@@ -660,6 +597,14 @@ qt_feature("poll_select" PRIVATE
EMIT_IF NOT WIN32
)
qt_feature_definition("poll_select" "QT_NO_NATIVE_POLL")
+qt_feature("posix_sem" PRIVATE
+ LABEL "POSIX semaphores"
+ CONDITION TEST_posix_sem AND QT_FEATURE_systemsemaphore
+)
+qt_feature("posix_shm" PRIVATE
+ LABEL "POSIX shared memory"
+ CONDITION TEST_posix_shm AND UNIX
+)
qt_feature("qqnx_pps" PRIVATE
LABEL "PPS"
CONDITION PPS_FOUND
@@ -667,20 +612,23 @@ qt_feature("qqnx_pps" PRIVATE
)
qt_feature("renameat2" PRIVATE
LABEL "renameat2()"
- CONDITION LINUX AND TEST_renameat2
+ CONDITION ( LINUX OR HURD ) AND TEST_renameat2
)
qt_feature("slog2" PRIVATE
LABEL "slog2"
CONDITION Slog2_FOUND
)
-qt_feature("statx" PRIVATE
- LABEL "statx() in libc"
- CONDITION LINUX AND TEST_statx
-)
qt_feature("syslog" PRIVATE
LABEL "syslog"
AUTODETECT OFF
- CONDITION TEST_syslog
+)
+qt_feature("sysv_sem" PRIVATE
+ LABEL "System V / XSI semaphores"
+ CONDITION TEST_sysv_sem AND QT_FEATURE_systemsemaphore
+)
+qt_feature("sysv_shm" PRIVATE
+ LABEL "System V / XSI shared memory"
+ CONDITION TEST_sysv_shm
)
qt_feature("threadsafe-cloexec"
LABEL "Threadsafe pipe creation"
@@ -688,12 +636,6 @@ qt_feature("threadsafe-cloexec"
)
qt_feature_definition("threadsafe-cloexec" "QT_THREADSAFE_CLOEXEC" VALUE "1")
qt_feature_config("threadsafe-cloexec" QMAKE_PUBLIC_QT_CONFIG)
-qt_feature("properties" PUBLIC
- SECTION "Kernel"
- LABEL "Properties"
- PURPOSE "Supports scripting Qt-based applications."
-)
-qt_feature_definition("properties" "QT_NO_PROPERTIES" NEGATE VALUE "1")
qt_feature("regularexpression" PUBLIC
SECTION "Kernel"
LABEL "QRegularExpression"
@@ -701,11 +643,19 @@ qt_feature("regularexpression" PUBLIC
CONDITION QT_FEATURE_system_pcre2 OR QT_FEATURE_pcre2
)
qt_feature_definition("regularexpression" "QT_NO_REGULAREXPRESSION" NEGATE VALUE "1")
+qt_feature("backtrace" PRIVATE
+ LABEL "backtrace"
+ CONDITION UNIX AND QT_FEATURE_regularexpression AND WrapBacktrace_FOUND
+)
+qt_feature("cxx23_stacktrace" PRIVATE
+ LABEL "C++23 <stacktrace>"
+ CONDITION TEST_cxx23_stacktrace AND QT_FEATURE_cxx2b
+)
qt_feature("sharedmemory" PUBLIC
SECTION "Kernel"
LABEL "QSharedMemory"
PURPOSE "Provides access to a shared memory segment."
- CONDITION ( ANDROID OR WIN32 OR ( NOT VXWORKS AND ( TEST_ipc_sysv OR TEST_ipc_posix ) ) )
+ CONDITION WIN32 OR TEST_sysv_shm OR TEST_posix_shm
)
qt_feature_definition("sharedmemory" "QT_NO_SHAREDMEMORY" NEGATE VALUE "1")
qt_feature("shortcut" PUBLIC
@@ -718,7 +668,7 @@ qt_feature("systemsemaphore" PUBLIC
SECTION "Kernel"
LABEL "QSystemSemaphore"
PURPOSE "Provides a general counting system semaphore."
- CONDITION ( NOT INTEGRITY AND NOT VXWORKS AND NOT rtems ) AND ( ANDROID OR WIN32 OR TEST_ipc_sysv OR TEST_ipc_posix )
+ CONDITION WIN32 OR TEST_sysv_sem OR TEST_posix_sem
)
qt_feature_definition("systemsemaphore" "QT_NO_SYSTEMSEMAPHORE" NEGATE VALUE "1")
qt_feature("xmlstream" PUBLIC
@@ -726,21 +676,24 @@ qt_feature("xmlstream" PUBLIC
LABEL "XML Streaming APIs"
PURPOSE "Provides a simple streaming API for XML."
)
-qt_feature_definition("xmlstream" "QT_NO_XMLSTREAM" NEGATE VALUE "1")
+qt_feature("cpp-winrt" PRIVATE PUBLIC
+ LABEL "cpp/winrt base"
+ PURPOSE "basic cpp/winrt language projection support"
+ AUTODETECT WIN32
+ CONDITION WIN32 AND TEST_cpp_winrt
+)
qt_feature("xmlstreamreader" PUBLIC
SECTION "Kernel"
LABEL "QXmlStreamReader"
PURPOSE "Provides a well-formed XML parser with a simple streaming API."
CONDITION QT_FEATURE_xmlstream
)
-qt_feature_definition("xmlstreamreader" "QT_NO_XMLSTREAMREADER" NEGATE VALUE "1")
qt_feature("xmlstreamwriter" PUBLIC
SECTION "Kernel"
LABEL "QXmlStreamWriter"
PURPOSE "Provides a XML writer with a simple streaming API."
CONDITION QT_FEATURE_xmlstream
)
-qt_feature_definition("xmlstreamwriter" "QT_NO_XMLSTREAMWRITER" NEGATE VALUE "1")
qt_feature("textdate" PUBLIC
SECTION "Data structures"
LABEL "Text Date"
@@ -758,7 +711,13 @@ qt_feature("process" PUBLIC
SECTION "File I/O"
LABEL "QProcess"
PURPOSE "Supports external process invocation."
- CONDITION QT_FEATURE_processenvironment AND ( QT_FEATURE_thread OR NOT UNIX ) AND NOT UIKIT AND NOT INTEGRITY AND NOT VXWORKS AND NOT rtems
+ CONDITION QT_FEATURE_processenvironment
+ AND (QT_FEATURE_thread OR NOT UNIX)
+ AND NOT UIKIT
+ AND NOT INTEGRITY
+ AND NOT VXWORKS
+ AND NOT rtems
+ AND NOT WASM
)
qt_feature_definition("process" "QT_NO_PROCESS" NEGATE VALUE "1")
qt_feature("processenvironment" PUBLIC
@@ -777,7 +736,7 @@ qt_feature("library" PUBLIC
SECTION "File I/O"
LABEL "QLibrary"
PURPOSE "Provides a wrapper for dynamically loaded libraries."
- CONDITION WIN32 OR HPUX OR ( NOT NACL AND QT_FEATURE_dlopen )
+ CONDITION WIN32 OR HPUX OR QT_FEATURE_dlopen
)
qt_feature_definition("library" "QT_NO_LIBRARY" NEGATE VALUE "1")
qt_feature("settings" PUBLIC
@@ -815,7 +774,7 @@ qt_feature("sortfilterproxymodel" PUBLIC
SECTION "ItemViews"
LABEL "QSortFilterProxyModel"
PURPOSE "Supports sorting and filtering of data passed between another model and a view."
- CONDITION QT_FEATURE_proxymodel
+ CONDITION QT_FEATURE_proxymodel AND QT_FEATURE_regularexpression
)
qt_feature_definition("sortfilterproxymodel" "QT_NO_SORTFILTERPROXYMODEL" NEGATE VALUE "1")
qt_feature("identityproxymodel" PUBLIC
@@ -861,20 +820,9 @@ qt_feature("animation" PUBLIC
SECTION "Utilities"
LABEL "Animation"
PURPOSE "Provides a framework for animations."
- CONDITION QT_FEATURE_properties AND QT_FEATURE_easingcurve
+ CONDITION QT_FEATURE_easingcurve
)
qt_feature_definition("animation" "QT_NO_ANIMATION" NEGATE VALUE "1")
-qt_feature("statemachine" PUBLIC
- SECTION "Utilities"
- LABEL "State machine"
- PURPOSE "Provides hierarchical finite state machines."
- CONDITION QT_FEATURE_properties
-)
-qt_feature_definition("statemachine" "QT_NO_STATEMACHINE" NEGATE VALUE "1")
-qt_feature("qeventtransition" PUBLIC
- LABEL "QEventTransition class"
- CONDITION QT_FEATURE_statemachine
-)
qt_feature("gestures" PUBLIC
SECTION "Utilities"
LABEL "Gesture"
@@ -906,11 +854,19 @@ qt_feature("timezone" PUBLIC
SECTION "Utilities"
LABEL "QTimeZone"
PURPOSE "Provides support for time-zone handling."
+ CONDITION NOT WASM AND NOT VXWORKS
+)
+qt_feature("timezone_locale" PRIVATE
+ SECTION "Utilities"
+ LABEL "QTimeZone"
+ PURPOSE "Provides support for localized time-zone display names."
+ DISABLE ON # Implementation is currently incomplete, so leave turned off
)
qt_feature("datetimeparser" PRIVATE
SECTION "Utilities"
LABEL "QDateTimeParser"
PURPOSE "Provides support for parsing date-time texts."
+ CONDITION QT_FEATURE_datestring
)
qt_feature("commandlineparser" PUBLIC
SECTION "Utilities"
@@ -931,9 +887,15 @@ qt_feature("etw" PRIVATE
ENABLE INPUT_trace STREQUAL 'etw' OR ( INPUT_trace STREQUAL 'yes' AND WIN32 )
DISABLE INPUT_trace STREQUAL 'lttng' OR INPUT_trace STREQUAL 'no'
)
-qt_feature("win32_system_libs"
- LABEL "Windows System Libraries"
- CONDITION WIN32 AND libs.advapi32 AND libs.gdi32 AND libs.kernel32 AND libs.netapi32 AND libs.ole32 AND libs.shell32 AND libs.uuid AND libs.user32 AND libs.winmm AND libs.ws2_32 OR FIXME
+qt_feature("ctf" PRIVATE
+ LABEL "CTF"
+ AUTODETECT OFF
+ ENABLE INPUT_trace STREQUAL 'ctf'
+ DISABLE INPUT_trace STREQUAL 'etw' OR INPUT_trace STREQUAL 'no' OR INPUT_trace STREQUAL 'lttng'
+)
+qt_feature("forkfd_pidfd" PRIVATE
+ LABEL "CLONE_PIDFD support in forkfd"
+ CONDITION LINUX
)
qt_feature("cborstreamreader" PUBLIC
SECTION "Utilities"
@@ -945,22 +907,42 @@ qt_feature("cborstreamwriter" PUBLIC
LABEL "CBOR stream writing"
PURPOSE "Provides support for writing the CBOR binary format."
)
-qt_feature("binaryjson" PUBLIC
+qt_feature("poll-exit-on-error" PRIVATE
+ LABEL "Poll exit on error"
+ AUTODETECT OFF
+ CONDITION UNIX
+ PURPOSE "Exit on error instead of just printing the error code and continue."
+)
+qt_feature("permissions" PUBLIC
SECTION "Utilities"
- LABEL "Binary JSON (deprecated)"
- PURPOSE "Provides support for the deprecated binary JSON format."
+ LABEL "Application permissions"
+ PURPOSE "Provides support for requesting user permission to access restricted data or APIs"
)
+qt_feature("openssl-hash" PRIVATE
+ LABEL "OpenSSL based cryptographic hash"
+ AUTODETECT OFF
+ CONDITION QT_FEATURE_openssl_linked AND QT_FEATURE_opensslv30
+ PURPOSE "Uses OpenSSL based implementation of cryptographic hash algorithms."
+)
+
qt_configure_add_summary_section(NAME "Qt Core")
+qt_configure_add_summary_entry(ARGS "backtrace")
+qt_configure_add_summary_entry(ARGS "cxx23_stacktrace")
qt_configure_add_summary_entry(ARGS "doubleconversion")
qt_configure_add_summary_entry(ARGS "system-doubleconversion")
+qt_configure_add_summary_entry(ARGS "forkfd_pidfd" CONDITION LINUX)
qt_configure_add_summary_entry(ARGS "glib")
qt_configure_add_summary_entry(ARGS "icu")
+qt_configure_add_summary_entry(ARGS "system-libb2")
qt_configure_add_summary_entry(ARGS "mimetype-database")
+qt_configure_add_summary_entry(ARGS "permissions")
+qt_configure_add_summary_entry(ARGS "ipc_posix" CONDITION UNIX)
qt_configure_add_summary_entry(
TYPE "firstAvailableFeature"
- ARGS "etw lttng"
+ ARGS "etw lttng ctf"
MESSAGE "Tracing backend"
)
+qt_configure_add_summary_entry(ARGS "openssl-hash")
qt_configure_add_summary_section(NAME "Logging backends")
qt_configure_add_summary_entry(ARGS "journald")
qt_configure_add_summary_entry(ARGS "syslog")
@@ -980,16 +962,6 @@ qt_configure_add_report_entry(
)
qt_configure_add_report_entry(
TYPE ERROR
- MESSAGE "C++11 <random> is required and is missing or failed to compile."
- CONDITION NOT TEST_cxx11_random
-)
-qt_configure_add_report_entry(
- TYPE ERROR
- MESSAGE "Your C library does not provide sscanf_l or snprintf_l. You need to use libdouble-conversion for double/string conversion."
- CONDITION INPUT_doubleconversion STREQUAL 'no' AND NOT TEST_xlocalescanprint
-)
-qt_configure_add_report_entry(
- TYPE ERROR
MESSAGE "detected a std::atomic implementation that fails for function pointers. Please apply the patch corresponding to your Standard Library vendor, found in qtbase/config.tests/atomicfptr"
CONDITION NOT TEST_atomicfptr
)
@@ -998,3 +970,8 @@ qt_configure_add_report_entry(
MESSAGE "Qt requires poll(), ppoll(), poll_ts() or select() on this platform"
CONDITION ( UNIX OR INTEGRITY ) AND ( NOT QT_FEATURE_poll_ppoll ) AND ( NOT QT_FEATURE_poll_pollts ) AND ( NOT QT_FEATURE_poll_poll ) AND ( NOT QT_FEATURE_poll_select )
)
+qt_configure_add_report_entry(
+ TYPE WARNING
+ MESSAGE "Basic cpp/winrt support missing. Some features might not be available."
+ CONDITION WIN32 AND NOT QT_FEATURE_cpp_winrt
+)
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
deleted file mode 100644
index 7aa0e0b177..0000000000
--- a/src/corelib/configure.json
+++ /dev/null
@@ -1,1098 +0,0 @@
-{
- "module": "core",
- "testDir": "../../config.tests",
-
- "commandline": {
- "options": {
- "doubleconversion": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "eventfd": "boolean",
- "glib": "boolean",
- "icu": "boolean",
- "inotify": "boolean",
- "journald": "boolean",
- "mimetype-database": "boolean",
- "pcre": { "type": "enum", "values": [ "no", "qt", "system" ] },
- "posix-ipc": { "type": "boolean", "name": "ipc_posix" },
- "pps": { "type": "boolean", "name": "qqnx_pps" },
- "slog2": "boolean",
- "syslog": "boolean",
- "trace": { "type": "optionalString", "values": [ "etw", "lttng", "no", "yes" ] }
- }
- },
-
- "libraries": {
- "doubleconversion": {
- "label": "DoubleConversion",
- "test": {
- "main": "(void) double_conversion::StringToDoubleConverter::NO_FLAGS;"
- },
- "headers": "double-conversion/double-conversion.h",
- "sources": [
- "-ldouble-conversion"
- ]
- },
- "glib": {
- "label": "GLib",
- "test": {
- "head": "typedef struct _GMainContext GMainContext;",
- "main": [
- "g_thread_init(NULL);",
- "(void) g_main_context_default();",
- "(void) g_source_new(0, 0);",
- "g_source_add_poll(NULL, NULL);"
- ]
- },
- "headers": "glib.h",
- "sources": [
- { "type": "pkgConfig", "args": "glib-2.0 gthread-2.0" }
- ]
- },
- "icu": {
- "label": "ICU",
- "test": {
- "main": [
- "UErrorCode status = U_ZERO_ERROR;",
- "UCollator *collator = ucol_open(\"ru_RU\", &status);",
- "if (!U_FAILURE(status))",
- " ucol_close(collator);"
- ]
- },
- "headers": [ "unicode/utypes.h", "unicode/ucol.h", "unicode/ustring.h" ],
- "sources": [
- {
- "builds": {
- "debug": "-lsicuind -lsicuucd -lsicudtd",
- "release": "-lsicuin -lsicuuc -lsicudt"
- },
- "condition": "config.win32 && !features.shared"
- },
- { "libs": "-licuin -licuuc -licudt", "condition": "config.win32 && features.shared" },
- { "libs": "-licui18n -licuuc -licudata", "condition": "!config.win32" }
- ],
- "use": [
- { "lib": "libdl", "condition": "features.dlopen" }
- ]
- },
- "journald": {
- "label": "journald",
- "test": {
- "main": "sd_journal_send(\"PRIORITY=%i\", LOG_INFO, NULL);"
- },
- "headers": [ "systemd/sd-journal.h", "syslog.h" ],
- "sources": [
- { "type": "pkgConfig", "args": "libsystemd" },
- { "type": "pkgConfig", "args": "libsystemd-journal" }
- ]
- },
- "libatomic": {
- "label": "64 bit atomics",
- "test": {
- "tail": [
- "void test(volatile std::atomic<std::int64_t> &a)",
- "{",
- " std::int64_t v = a.load(std::memory_order_acquire);",
- " while (!a.compare_exchange_strong(v, v + 1,",
- " std::memory_order_acq_rel,",
- " std::memory_order_acquire)) {",
- " v = a.exchange(v - 1);",
- " }",
- " a.store(v + 1, std::memory_order_release);",
- "}"
- ],
- "main": [
- "void *ptr = (void*)0xffffffc0; // any random pointer",
- "test(*reinterpret_cast<std::atomic<std::int64_t> *>(ptr));"
- ],
- "qmake": "CONFIG += c++11"
- },
- "headers": [ "atomic", "cstdint" ],
- "sources": [
- "",
- "-latomic"
- ]
- },
- "librt": {
- "label": "clock_gettime()",
- "test": {
- "main": "timespec ts; clock_gettime(CLOCK_REALTIME, &ts);"
- },
- "headers": [ "unistd.h", "time.h" ],
- "sources": [
- "",
- "-lrt"
- ]
- },
- "lttng-ust": {
- "label": "lttng-ust",
- "test": {
- "main": "lttng_session_destroy(nullptr);"
- },
- "headers": "lttng/ust-events.h",
- "sources": [
- { "type": "pkgConfig", "args": "lttng-ust" },
- "-llttng-ust"
- ],
- "use": "libdl"
- },
- "pcre2": {
- "label": "PCRE2",
- "test": {
- "head": "#define PCRE2_CODE_UNIT_WIDTH 16",
- "tail": [
- "#if (PCRE2_MAJOR < 10) || ((PCRE2_MAJOR == 10) && (PCRE2_MINOR < 20))",
- "# error This PCRE version is not supported",
- "#endif"
- ]
- },
- "headers": "pcre2.h",
- "sources": [
- { "type": "pkgConfig", "args": "libpcre2-16" },
- "-lpcre2-16"
- ]
- },
- "pps": {
- "label": "PPS",
- "test": {
- "main": [
- "pps_decoder_t decoder;",
- "pps_decoder_initialize(&decoder, NULL);"
- ]
- },
- "headers": "sys/pps.h",
- "sources": [
- "-lpps"
- ]
- },
- "slog2": {
- "label": "slog2",
- "test": {
- "main": "slog2_set_default_buffer((slog2_buffer_t)-1);"
- },
- "export": "",
- "headers": "sys/slog2.h",
- "sources": [
- "-lslog2"
- ]
- },
- "advapi32": {
- "label": "advapi32",
- "sources": [
- "-ladvapi32"
- ]
- },
- "gdi32": {
- "label": "gdi32",
- "sources": [
- "-lgdi32"
- ]
- },
- "kernel32": {
- "label": "kernel32",
- "sources": [
- "-lkernel32"
- ]
- },
- "netapi32": {
- "label": "netapi32",
- "sources": [
- "-lnetapi32"
- ]
- },
- "ole32": {
- "label": "ole32",
- "sources": [
- "-lole32"
- ]
- },
- "shell32": {
- "label": "shell32",
- "sources": [
- "-lshell32"
- ]
- },
- "uuid": {
- "label": "uuid",
- "sources": [
- "-luuid"
- ]
- },
- "user32": {
- "label": "user32",
- "sources": [
- "-luser32"
- ]
- },
- "winmm": {
- "label": "winmm",
- "sources": [
- "-lwinmm"
- ]
- },
- "ws2_32": {
- "label": "ws2_32",
- "sources": [
- "-lws2_32"
- ]
- }
- },
-
- "tests": {
- "atomicfptr": {
- "label": "working std::atomic for function pointers",
- "type": "compile",
- "test": {
- "include": "atomic",
- "tail": [
- "typedef void (*fptr)(int);",
- "typedef std::atomic<fptr> atomicfptr;",
- "void testfunction(int) { }",
- "void test(volatile atomicfptr &a)",
- "{",
- " fptr v = a.load(std::memory_order_acquire);",
- " while (!a.compare_exchange_strong(v, &testfunction,",
- " std::memory_order_acq_rel,",
- " std::memory_order_acquire)) {",
- " v = a.exchange(&testfunction);",
- " }",
- " a.store(&testfunction, std::memory_order_release);",
- "}"
- ],
- "main": [
- "atomicfptr fptr(testfunction);",
- "test(fptr);"
- ],
- "qmake": "CONFIG += c++11"
- }
- },
- "clock-monotonic": {
- "label": "POSIX monotonic clock",
- "type": "compile",
- "test": {
- "include": [ "unistd.h", "time.h" ],
- "main": [
- "#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK-0 >= 0)",
- "timespec ts;",
- "clock_gettime(CLOCK_MONOTONIC, &ts);",
- "#else",
- "# error Feature _POSIX_MONOTONIC_CLOCK not available",
- "#endif"
- ]
- },
- "use": "librt"
- },
- "cloexec": {
- "label": "O_CLOEXEC",
- "type": "compile",
- "test": {
- "head": "#define _GNU_SOURCE 1",
- "include": [ "sys/types.h", "sys/socket.h", "fcntl.h", "unistd.h" ],
- "main": [
- "int pipes[2];",
- "(void) pipe2(pipes, O_CLOEXEC | O_NONBLOCK);",
- "(void) fcntl(0, F_DUPFD_CLOEXEC, 0);",
- "(void) dup3(0, 3, O_CLOEXEC);",
- "#if defined(__NetBSD__)",
- "(void) paccept(0, 0, 0, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK);",
- "#else",
- "(void) accept4(0, 0, 0, SOCK_CLOEXEC | SOCK_NONBLOCK);",
- "#endif"
- ]
- }
- },
- "cxx11_future": {
- "label": "C++11 <future>",
- "type": "compile",
- "test": {
- "include": "future",
- "main": [
- "std::future<int> f = std::async([]() { return 42; });",
- "(void)f.get();"
- ],
- "qmake": "unix:LIBS += -lpthread"
- }
- },
- "cxx11_random": {
- "label": "C++11 <random>",
- "type": "compile",
- "test": {
- "include": "random",
- "main": "std::mt19937 mt(0);"
- }
- },
- "cxx17_filesystem": {
- "label": "C++17 <filesystem>",
- "type": "compile",
- "test": {
- "include": "filesystem",
- "main": [
- "std::filesystem::copy(",
- " std::filesystem::path(\"./file\"),",
- " std::filesystem::path(\"./other\"));"
- ],
- "qmake": "CONFIG += c++17"
- }
- },
- "eventfd": {
- "label": "eventfd",
- "type": "compile",
- "test": {
- "include": "sys/eventfd.h",
- "main": [
- "eventfd_t value;",
- "int fd = eventfd(0, EFD_CLOEXEC);",
- "eventfd_read(fd, &value);",
- "eventfd_write(fd, value);"
- ]
- }
- },
- "futimens": {
- "label": "futimens()",
- "type": "compile",
- "test": {
- "include": "sys/stat.h",
- "main": "futimens(-1, 0);",
- "qmake": [
- "# Block futimens() on Apple platforms unless it's available on ALL",
- "# deployment targets. This simplifies the logic at the call site",
- "# dramatically, as it isn't strictly needed compared to futimes().",
- "darwin: QMAKE_CXXFLAGS += -Werror=unguarded-availability -Werror=unguarded-availability-new",
- "CONFIG += warn_on"
- ]
- }
- },
- "futimes": {
- "label": "futimes()",
- "type": "compile",
- "test": {
- "include": "sys/time.h",
- "main": "futimes(-1, 0);"
- }
- },
- "getauxval": {
- "label": "getauxval()",
- "type": "compile",
- "test": {
- "include": "sys/auxv.h",
- "main": "(void) getauxval(AT_NULL);"
- }
- },
- "getentropy": {
- "label": "getentropy()",
- "type": "compile",
- "test": {
- "include": "unistd.h",
- "main": [
- "char buf[32];",
- "(void) getentropy(buf, sizeof(buf));"
- ]
- }
- },
- "glibc": {
- "label": "GNU libc",
- "type": "compile",
- "test": {
- "include": "stdlib.h",
- "main": [
- "return __GLIBC__;"
- ]
- }
- },
- "inotify": {
- "label": "inotify",
- "type": "compile",
- "test": {
- "include": "sys/inotify.h",
- "main": [
- "inotify_init();",
- "inotify_add_watch(0, \"foobar\", IN_ACCESS);",
- "inotify_rm_watch(0, 1);"
- ]
- }
- },
- "ipc_sysv": {
- "label": "SysV IPC",
- "type": "compile",
- "test": {
- "include": [ "sys/types.h", "sys/ipc.h", "sys/sem.h", "sys/shm.h", "fcntl.h" ],
- "main": [
- "key_t unix_key = ftok(\"test\", 'Q');",
- "semctl(semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL), 0, IPC_RMID, 0);",
- "shmget(unix_key, 0, 0666 | IPC_CREAT | IPC_EXCL);",
- "shmctl(0, 0, (struct shmid_ds *)(0));"
- ]
- }
- },
- "ipc_posix": {
- "label": "POSIX IPC",
- "type": "compile",
- "test": {
- "include": [ "sys/types.h", "sys/mman.h", "semaphore.h", "fcntl.h" ],
- "main": [
- "sem_close(sem_open(\"test\", O_CREAT | O_EXCL, 0666, 0));",
- "shm_open(\"test\", O_RDWR | O_CREAT | O_EXCL, 0666);",
- "shm_unlink(\"test\");"
- ],
- "qmake": "linux: LIBS += -lpthread -lrt"
- }
- },
- "linkat": {
- "label": "linkat()",
- "type": "compile",
- "test": {
- "head": "#define _ATFILE_SOURCE 1",
- "include": [ "fcntl.h", "unistd.h" ],
- "main": "linkat(AT_FDCWD, \"foo\", AT_FDCWD, \"bar\", AT_SYMLINK_FOLLOW);"
- }
- },
- "ppoll": {
- "label": "ppoll()",
- "type": "compile",
- "test": {
- "include": [ "signal.h", "poll.h" ],
- "main": [
- "struct pollfd pfd;",
- "struct timespec ts;",
- "sigset_t sig;",
- "ppoll(&pfd, 1, &ts, &sig);"
- ]
- }
- },
- "pollts": {
- "label": "pollts()",
- "type": "compile",
- "test": {
- "include": [ "poll.h", "signal.h", "time.h" ],
- "main": [
- "struct pollfd pfd;",
- "struct timespec ts;",
- "sigset_t sig;",
- "pollts(&pfd, 1, &ts, &sig);"
- ]
- }
- },
- "poll": {
- "label": "poll()",
- "type": "compile",
- "test": {
- "include": "poll.h",
- "main": [
- "struct pollfd pfd;",
- "poll(&pfd, 1, 0);"
- ]
- }
- },
- "renameat2": {
- "label": "renameat2()",
- "type": "compile",
- "test": {
- "head": "#define _ATFILE_SOURCE 1",
- "include": [ "fcntl.h", "stdio.h" ],
- "main": "renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE | RENAME_WHITEOUT);"
- }
- },
- "statx": {
- "label": "statx() in libc",
- "type": "compile",
- "test": {
- "head": "#define _ATFILE_SOURCE 1",
- "include": [ "sys/types.h", "sys/stat.h", "unistd.h", "fcntl.h" ],
- "main": [
- "struct statx statxbuf;",
- "unsigned int mask = STATX_BASIC_STATS;",
- "return statx(AT_FDCWD, \"\", AT_STATX_SYNC_AS_STAT, mask, &statxbuf);"
- ]
- }
- },
- "syslog": {
- "label": "syslog",
- "type": "compile",
- "test": {
- "include": "syslog.h",
- "main": [
- "openlog(\"qt\", 0, LOG_USER);",
- "syslog(LOG_INFO, \"configure\");",
- "closelog();"
- ]
- }
- },
- "xlocalescanprint": {
- "label": "xlocale.h (or equivalents)",
- "type": "compile",
- "test": {
- "files": {
- "qglobal.h": [
- "#ifndef QGLOBAL_H",
- "#define QGLOBAL_H",
- "#endif"
- ]
- },
- "tail": [
- "#define QT_BEGIN_NAMESPACE",
- "#define QT_END_NAMESPACE",
- "",
- "#ifdef _MSVC_VER",
- "#define Q_CC_MSVC _MSVC_VER",
- "#endif",
- "",
- "#define QT_NO_DOUBLECONVERSION",
- "",
- "#include QDSP_P_H"
- ],
- "main": [
- "#ifdef _MSVC_VER",
- "_locale_t invalidLocale = NULL;",
- "#else",
- "locale_t invalidLocale = NULL;",
- "#endif",
- "double a = 3.4;",
- "qDoubleSnprintf(argv[0], 1, invalidLocale, \"invalid format\", a);",
- "qDoubleSscanf(argv[0], invalidLocale, \"invalid format\", &a, &argc);"
- ],
- "qmake": "DEFINES += QDSP_P_H=$$shell_quote(\\\"@PWD@/text/qdoublescanprint_p.h\\\")"
- }
- }
- },
-
- "features": {
- "clock-gettime": {
- "label": "clock_gettime()",
- "condition": "config.unix && libs.librt",
- "output": [ "privateFeature" ]
- },
- "clock-monotonic": {
- "label": "POSIX monotonic clock",
- "condition": "features.clock-gettime && tests.clock-monotonic",
- "output": [ "feature" ]
- },
- "doubleconversion": {
- "label": "DoubleConversion",
- "output": [ "privateFeature", "feature" ]
- },
- "system-doubleconversion": {
- "label": " Using system DoubleConversion",
- "enable": "input.doubleconversion == 'system'",
- "disable": "input.doubleconversion == 'qt'",
- "condition": "features.doubleconversion && libs.doubleconversion",
- "output": [ "privateFeature" ]
- },
- "cxx11_future": {
- "label": "C++11 <future>",
- "condition": "tests.cxx11_future",
- "output": [ "publicFeature" ]
- },
- "cxx17_filesystem": {
- "label": "C++17 <filesystem>",
- "condition": "tests.cxx17_filesystem",
- "output": [
- "publicFeature"
- ]
- },
- "eventfd": {
- "label": "eventfd",
- "condition": "!config.wasm && tests.eventfd",
- "output": [ "feature" ]
- },
- "futimens": {
- "label": "futimens()",
- "condition": "!config.win32 && tests.futimens",
- "output": [ "privateFeature" ]
- },
- "futimes": {
- "label": "futimes()",
- "condition": "!config.win32 && !features.futimens && tests.futimes",
- "output": [ "privateFeature" ]
- },
- "getauxval": {
- "label": "getauxval()",
- "condition": "config.linux && tests.getauxval",
- "output": [ "privateFeature" ]
- },
- "getentropy": {
- "label": "getentropy()",
- "condition": "config.unix && tests.getentropy",
- "output": [ "privateFeature" ]
- },
- "glib": {
- "label": "GLib",
- "autoDetect": "!config.win32",
- "condition": "libs.glib",
- "output": [ "privateFeature", "feature" ]
- },
- "glibc": {
- "label": "GNU libc",
- "autoDetect": "config.linux",
- "condition": "tests.glibc",
- "output": [ "privateFeature" ]
- },
- "icu": {
- "label": "ICU",
- "autoDetect": "!config.win32",
- "condition": "libs.icu",
- "output": [ "privateFeature" ]
- },
- "inotify": {
- "label": "inotify",
- "condition": "tests.inotify",
- "output": [ "privateFeature", "feature" ]
- },
- "ipc_posix": {
- "label": "Using POSIX IPC",
- "autoDetect": "!config.win32",
- "condition": "!tests.ipc_sysv && tests.ipc_posix",
- "output": [ { "type": "define", "name": "QT_POSIX_IPC" } ]
- },
- "journald": {
- "label": "journald",
- "autoDetect": false,
- "condition": "libs.journald",
- "output": [ "privateFeature" ]
- },
- "linkat": {
- "label": "linkat()",
- "comment": "Currently only used by QTemporaryFile; linkat() exists on Android, but hardlink creation fails due to security rules",
- "autoDetect": "config.linux && !config.android",
- "condition": "tests.linkat",
- "output": [ "privateFeature" ]
- },
- "std-atomic64": {
- "label": "64 bit atomic operations",
- "condition": "libs.libatomic",
- "output": [ "publicFeature" ]
- },
- "mimetype": {
- "label": "Mimetype handling",
- "purpose": "Provides MIME type handling.",
- "section": "Utilities",
- "output": [ "publicFeature", "feature" ]
- },
- "mimetype-database": {
- "label": "Built-in copy of the MIME database",
- "condition": "features.mimetype",
- "output": [ "privateFeature" ]
- },
- "pcre2": {
- "label": "PCRE2",
- "disable": "input.pcre == 'no' || input.pcre == 'system'",
- "enable": "input.pcre == 'qt'",
- "output": [ "privateConfig" ]
- },
- "system-pcre2": {
- "label": " Using system PCRE2",
- "disable": "input.pcre == 'no' || input.pcre == 'qt'",
- "enable": "input.pcre == 'system'",
- "condition": "libs.pcre2",
- "output": [ "privateFeature" ]
- },
- "poll_ppoll": {
- "label": "Native ppoll()",
- "emitIf": "!config.win32",
- "condition": "!config.wasm && tests.ppoll",
- "output": [ "privateFeature" ]
- },
- "poll_pollts": {
- "label": "Native pollts()",
- "emitIf": "!config.win32",
- "condition": "!features.poll_ppoll && tests.pollts",
- "output": [ "privateFeature" ]
- },
- "poll_poll": {
- "label": "Native poll()",
- "emitIf": "!config.win32",
- "condition": "!features.poll_ppoll && !features.poll_pollts && tests.poll",
- "output": [ "privateFeature" ]
- },
- "poll_select": {
- "label": "Emulated poll()",
- "emitIf": "!config.win32",
- "condition": "!features.poll_ppoll && !features.poll_pollts && !features.poll_poll",
- "output": [
- "privateFeature",
- { "type": "define", "name": "QT_NO_NATIVE_POLL" }
- ]
- },
- "qqnx_pps": {
- "label": "PPS",
- "emitIf": "config.qnx",
- "condition": "libs.pps",
- "output": [ "privateFeature" ]
- },
- "renameat2": {
- "label": "renameat2()",
- "condition": "config.linux && tests.renameat2",
- "output": [ "privateFeature" ]
- },
- "slog2": {
- "label": "slog2",
- "condition": "libs.slog2",
- "output": [ "privateFeature" ]
- },
- "statx": {
- "label": "statx() in libc",
- "condition": "config.linux && tests.statx",
- "output": [ "privateFeature" ]
- },
- "syslog": {
- "label": "syslog",
- "autoDetect": false,
- "condition": "tests.syslog",
- "output": [ "privateFeature" ]
- },
- "threadsafe-cloexec": {
- "label": "Threadsafe pipe creation",
- "condition": "tests.cloexec",
- "output": [
- "publicQtConfig",
- { "type": "define", "name": "QT_THREADSAFE_CLOEXEC", "value": 1 }
- ]
- },
- "properties": {
- "label": "Properties",
- "purpose": "Supports scripting Qt-based applications.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "regularexpression": {
- "label": "QRegularExpression",
- "purpose": "Provides an API to Perl-compatible regular expressions.",
- "section": "Kernel",
- "condition": "features.system-pcre2 || features.pcre2",
- "output": [ "publicFeature", "feature" ]
- },
- "sharedmemory": {
- "label": "QSharedMemory",
- "purpose": "Provides access to a shared memory segment.",
- "section": "Kernel",
- "condition": [
- "config.android || config.win32 || (!config.vxworks && (tests.ipc_sysv || tests.ipc_posix))"
- ],
- "output": [ "publicFeature", "feature" ]
- },
- "shortcut": {
- "label": "QShortcut",
- "purpose": "Provides keyboard accelerators and shortcuts.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "systemsemaphore": {
- "label": "QSystemSemaphore",
- "purpose": "Provides a general counting system semaphore.",
- "section": "Kernel",
- "condition": [
- "!config.integrity && !config.vxworks && !config.rtems",
- "config.android || config.win32 || tests.ipc_sysv || tests.ipc_posix"
- ],
- "output": [ "publicFeature", "feature" ]
- },
- "xmlstream": {
- "label": "XML Streaming APIs",
- "purpose": "Provides a simple streaming API for XML.",
- "section": "Kernel",
- "output": [ "publicFeature", "feature" ]
- },
- "xmlstreamreader": {
- "label": "QXmlStreamReader",
- "purpose": "Provides a well-formed XML parser with a simple streaming API.",
- "section": "Kernel",
- "condition": "features.xmlstream",
- "output": [ "publicFeature", "feature" ]
- },
- "xmlstreamwriter": {
- "label": "QXmlStreamWriter",
- "purpose": "Provides a XML writer with a simple streaming API.",
- "section": "Kernel",
- "condition": "features.xmlstream",
- "output": [ "publicFeature", "feature" ]
- },
- "textdate": {
- "label": "Text Date",
- "purpose": "Supports month and day names in dates.",
- "section": "Data structures",
- "output": [ "publicFeature", "feature" ]
- },
- "datestring": {
- "label": "QDate/QTime/QDateTime",
- "purpose": "Provides conversion between dates and strings.",
- "section": "Data structures",
- "condition": "features.textdate",
- "output": [ "publicFeature", "feature" ]
- },
- "process": {
- "label": "QProcess",
- "purpose": "Supports external process invocation.",
- "section": "File I/O",
- "condition": "features.processenvironment && (features.thread || !config.unix) && !config.uikit && !config.integrity && !config.vxworks && !config.rtems",
- "output": [ "publicFeature", "feature" ]
- },
- "processenvironment": {
- "label": "QProcessEnvironment",
- "purpose": "Provides a higher-level abstraction of environment variables.",
- "section": "File I/O",
- "condition": "!config.integrity && !config.rtems",
- "output": [ "publicFeature" ]
- },
- "temporaryfile": {
- "label": "QTemporaryFile",
- "purpose": "Provides an I/O device that operates on temporary files.",
- "section": "File I/O",
- "output": [ "publicFeature", "feature" ]
- },
- "library": {
- "label": "QLibrary",
- "purpose": "Provides a wrapper for dynamically loaded libraries.",
- "section": "File I/O",
- "condition": "config.win32 || config.hpux || (!config.nacl && features.dlopen)",
- "output": [ "publicFeature", "feature" ]
- },
- "settings": {
- "label": "QSettings",
- "purpose": "Provides persistent application settings.",
- "section": "File I/O",
- "output": [ "publicFeature", "feature" ]
- },
- "filesystemwatcher": {
- "label": "QFileSystemWatcher",
- "purpose": "Provides an interface for monitoring files and directories for modifications.",
- "section": "File I/O",
- "output": [ "publicFeature", "feature" ]
- },
- "filesystemiterator": {
- "label": "QFileSystemIterator",
- "purpose": "Provides fast file system iteration.",
- "section": "File I/O",
- "output": [ "publicFeature", "feature" ]
- },
- "itemmodel": {
- "label": "Qt Item Model",
- "purpose": "Provides the item model for item views",
- "section": "ItemViews",
- "output": [ "publicFeature", "feature" ]
- },
- "proxymodel": {
- "label": "QAbstractProxyModel",
- "purpose": "Supports processing of data passed between another model and a view.",
- "section": "ItemViews",
- "condition": "features.itemmodel",
- "output": [ "publicFeature", "feature" ]
- },
- "sortfilterproxymodel": {
- "label": "QSortFilterProxyModel",
- "purpose": "Supports sorting and filtering of data passed between another model and a view.",
- "section": "ItemViews",
- "condition": "features.proxymodel",
- "output": [ "publicFeature", "feature" ]
- },
- "identityproxymodel": {
- "label": "QIdentityProxyModel",
- "purpose": "Supports proxying a source model unmodified.",
- "section": "ItemViews",
- "condition": "features.proxymodel",
- "output": [ "publicFeature", "feature" ]
- },
- "transposeproxymodel": {
- "label": "QTransposeProxyModel",
- "purpose": "Provides a proxy to swap rows and columns of a model.",
- "section": "ItemViews",
- "condition": "features.proxymodel",
- "output": [ "publicFeature", "feature" ]
- },
- "concatenatetablesproxymodel": {
- "label": "QConcatenateTablesProxyModel",
- "purpose": "Supports concatenating source models.",
- "section": "ItemViews",
- "condition": "features.proxymodel",
- "output": [ "publicFeature", "feature" ]
- },
- "stringlistmodel": {
- "label": "QStringListModel",
- "purpose": "Provides a model that supplies strings to views.",
- "section": "ItemViews",
- "condition": "features.itemmodel",
- "output": [ "publicFeature", "feature" ]
- },
- "translation": {
- "label": "Translation",
- "purpose": "Supports translations using QObject::tr().",
- "section": "Internationalization",
- "output": [ "publicFeature", "feature" ]
- },
- "easingcurve": {
- "label": "Easing curve",
- "purpose": "Provides easing curve.",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- },
- "animation": {
- "label": "Animation",
- "purpose": "Provides a framework for animations.",
- "section": "Utilities",
- "condition": "features.properties && features.easingcurve",
- "output": [ "publicFeature", "feature" ]
- },
- "statemachine": {
- "label": "State machine",
- "purpose": "Provides hierarchical finite state machines.",
- "section": "Utilities",
- "condition": "features.properties",
- "output": [ "publicFeature", "feature" ]
- },
- "qeventtransition": {
- "label": "QEventTransition class",
- "condition": "features.statemachine",
- "output": [ "publicFeature" ]
- },
- "gestures": {
- "label": "Gesture",
- "purpose": "Provides a framework for gestures.",
- "section": "Utilities",
- "output": [ "publicFeature", "feature" ]
- },
- "sha3-fast": {
- "label": "Speed optimized SHA3",
- "purpose": "Optimizes SHA3 for speed instead of size.",
- "section": "Utilities",
- "output": [ "privateFeature" ]
- },
- "jalalicalendar": {
- "label": "QJalaliCalendar",
- "purpose": "Support the Jalali (Persian) calendar",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- },
- "hijricalendar": {
- "label": "QHijriCalendar",
- "purpose": "Generic basis for Islamic calendars, providing shared locale data",
- "section": "Utilities",
- "output": [ "privateFeature" ]
- },
- "islamiccivilcalendar": {
- "label": "QIslamicCivilCalendar",
- "purpose": "Support the Islamic Civil calendar",
- "section": "Utilities",
- "condition": "features.hijricalendar",
- "output": [ "publicFeature" ]
- },
- "timezone": {
- "label": "QTimeZone",
- "purpose": "Provides support for time-zone handling.",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- },
- "datetimeparser": {
- "label": "QDateTimeParser",
- "purpose": "Provides support for parsing date-time texts.",
- "section": "Utilities",
- "output": [ "privateFeature" ]
- },
- "commandlineparser": {
- "label": "QCommandlineParser",
- "purpose": "Provides support for command line parsing.",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- },
- "lttng": {
- "label": "LTTNG",
- "autoDetect": false,
- "enable": "input.trace == 'lttng' || (input.trace =='yes' && config.linux)",
- "disable": "input.trace == 'etw' || input.trace =='no'",
- "condition": "config.linux && libs.lttng-ust",
- "output": [ "privateFeature" ]
- },
- "etw": {
- "label": "ETW",
- "autoDetect": false,
- "enable": "input.trace == 'etw' || (input.trace == 'yes' && config.win32)",
- "disable": "input.trace == 'lttng' || input.trace == 'no'",
- "condition": "config.win32",
- "output": [ "privateFeature" ]
- },
- "win32_system_libs": {
- "label": "Windows System Libraries",
- "condition": "config.win32 && libs.advapi32 && libs.gdi32 && libs.kernel32 && libs.netapi32 && libs.ole32 && libs.shell32 && libs.uuid && libs.user32 && libs.winmm && libs.ws2_32"
- },
- "cborstreamreader": {
- "label": "CBOR stream reading",
- "purpose": "Provides support for reading the CBOR binary format.
-
-Note that this is required for plugin loading. Qt GUI needs QPA plugins for basic operation.",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- },
- "cborstreamwriter": {
- "label": "CBOR stream writing",
- "purpose": "Provides support for writing the CBOR binary format.",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- },
- "binaryjson": {
- "label": "Binary JSON (deprecated)",
- "purpose": "Provides support for the deprecated binary JSON format.",
- "section": "Utilities",
- "output": [ "publicFeature" ]
- }
- },
-
- "report": [
- {
- "type": "note",
- "condition": "features.journald || features.syslog || (config.qnx && features.slog2)",
- "message": "journald, syslog or slog2 integration is enabled. If your users intend to develop applications against this build, ensure that the IDEs they use either set QT_FORCE_STDERR_LOGGING to 1 or are able to read the logged output from journald, syslog or slog2."
- },
- {
- "type": "error",
- "condition": "!tests.cxx11_random",
- "message": "C++11 <random> is required and is missing or failed to compile."
- },
- {
- "type": "error",
- "condition": "input.doubleconversion == 'no' && !tests.xlocalescanprint",
- "message": "Your C library does not provide sscanf_l or snprintf_l. You need to use libdouble-conversion for double/string conversion."
- },
- {
- "type": "error",
- "condition": "!tests.atomicfptr",
- "message": "detected a std::atomic implementation that fails for function pointers. Please apply the patch corresponding to your Standard Library vendor, found in qtbase/config.tests/atomicfptr"
- },
- {
- "type": "error",
- "condition": [
- "config.unix || config.integrity",
- "!features.poll_ppoll",
- "!features.poll_pollts",
- "!features.poll_poll",
- "!features.poll_select"
- ],
- "message": "Qt requires poll(), ppoll(), poll_ts() or select() on this platform"
- }
- ],
-
- "summary": [
- {
- "section": "Qt Core",
- "entries": [
- "doubleconversion",
- "system-doubleconversion",
- "glib",
- "icu",
- "mimetype-database",
- {
- "message": "Tracing backend",
- "type": "firstAvailableFeature",
- "args": "etw lttng"
- },
- {
- "section": "Logging backends",
- "entries": [
- "journald", "syslog", "slog2"
- ]
- },
- {
- "type": "feature",
- "args": "qqnx_pps",
- "condition": "config.qnx"
- },
- "pcre2",
- "system-pcre2"
- ]
- }
- ]
-}
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
deleted file mode 100644
index 7a52cadf05..0000000000
--- a/src/corelib/corelib.pro
+++ /dev/null
@@ -1,164 +0,0 @@
-TARGET = QtCore
-QT =
-CONFIG += exceptions
-
-MODULE = core # not corelib, as per project file
-MODULE_CONFIG = moc resources
-qtConfig(gc_binaries): MODULE_CONFIG += gc_binaries
-!isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE
-
-TRACEPOINT_PROVIDER = $$PWD/qtcore.tracepoints
-CONFIG += qt_tracepoints
-
-CONFIG += $$MODULE_CONFIG
-DEFINES += $$MODULE_DEFINES
-android: DEFINES += LIBS_SUFFIX='\\"_$${QT_ARCH}.so\\"'
-DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
-msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x67000000
-
-CONFIG += simd optimize_full
-CONFIG += metatypes install_metatypes
-
-QMAKE_DOCS = $$PWD/doc/qtcore.qdocconf
-
-ANDROID_LIB_DEPENDENCIES = \
- plugins/platforms/libplugins_platforms_qtforandroid.so
-ANDROID_BUNDLED_JAR_DEPENDENCIES = \
- jar/QtAndroid.jar
-ANDROID_PERMISSIONS = \
- android.permission.INTERNET \
- android.permission.WRITE_EXTERNAL_STORAGE
-
-# QtCore can't be compiled with -Wl,-no-undefined because it uses the "environ"
-# variable and on FreeBSD and OpenBSD, this variable is in the final executable itself.
-# OpenBSD 6.0 will include environ in libc.
-freebsd|openbsd: QMAKE_LFLAGS_NOUNDEF =
-
-qtConfig(animation): include(animation/animation.pri)
-include(global/global.pri)
-include(thread/thread.pri)
-include(tools/tools.pri)
-include(text/text.pri)
-include(time/time.pri)
-include(io/io.pri)
-include(itemmodels/itemmodels.pri)
-include(plugin/plugin.pri)
-include(kernel/kernel.pri)
-include(serialization/serialization.pri)
-include(statemachine/statemachine.pri)
-include(mimetypes/mimetypes.pri)
-include(platform/platform.pri)
-
-win32 {
- QMAKE_USE_PRIVATE += ws2_32
- QMAKE_USE_PRIVATE += advapi32 kernel32 ole32 shell32 uuid user32 winmm
-}
-
-darwin {
- osx {
- LIBS_PRIVATE += -framework ApplicationServices
- LIBS_PRIVATE += -framework CoreServices
- }
- LIBS_PRIVATE += -framework CoreFoundation
- LIBS_PRIVATE += -framework Foundation
-}
-
-integrity {
- LIBS_PRIVATE += -lposix -livfs -lsocket -lnet -lshm_client
-}
-
-QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtCore.dynlist
-
-HOST_BINS = $$[QT_HOST_BINS]
-host_bins.name = host_bins
-host_bins.variable = HOST_BINS
-
-qt_conf.name = qt_config
-qt_conf.variable = QT_CONFIG
-
-QMAKE_PKGCONFIG_VARIABLES += host_bins qt_conf
-
-load(qt_module)
-
-# Override qt_module, so the symbols are actually included into the library.
-win32: DEFINES -= QT_NO_CAST_TO_ASCII
-
-ctest_macros_file.input = $$PWD/Qt5CTestMacros.cmake
-ctest_macros_file.output = $$DESTDIR/cmake/Qt5Core/Qt5CTestMacros.cmake
-ctest_macros_file.CONFIG = verbatim
-
-cmake_umbrella_config_file.input = $$PWD/Qt5Config.cmake.in
-cmake_umbrella_config_file.output = $$DESTDIR/cmake/Qt5/Qt5Config.cmake
-
-cmake_umbrella_config_module_location.input = $$PWD/Qt5ModuleLocation.cmake.in
-cmake_umbrella_config_module_location.output = $$DESTDIR/cmake/Qt5/Qt5ModuleLocation.cmake
-
-cmake_umbrella_config_module_location_for_install.input = $$PWD/Qt5ModuleLocationForInstall.cmake.in
-cmake_umbrella_config_module_location_for_install.output = $$DESTDIR/cmake/install/Qt5/Qt5ModuleLocation.cmake
-
-cmake_umbrella_config_version_file.input = $$PWD/../../mkspecs/features/data/cmake/Qt5ConfigVersion.cmake.in
-cmake_umbrella_config_version_file.output = $$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake
-
-android {
- cmake_android_support.input = $$PWD/Qt5AndroidSupport.cmake
- cmake_android_support.output = $$DESTDIR/cmake/Qt5Core/Qt5AndroidSupport.cmake
- cmake_android_support.CONFIG = verbatim
-}
-
-load(cmake_functions)
-
-defineTest(pathIsAbsolute) {
- p = $$clean_path($$1)
- !isEmpty(p):isEqual(p, $$absolute_path($$p)): return(true)
- return(false)
-}
-
-##### This requires fixing, so that the feature system works with cmake as well
-CMAKE_DISABLED_FEATURES = $$join(QT_DISABLED_FEATURES, "$$escape_expand(\\n) ")
-
-CMAKE_HOST_DATA_DIR = $$cmakeRelativePath($$[QT_HOST_DATA/src], $$[QT_INSTALL_PREFIX])
-pathIsAbsolute($$CMAKE_HOST_DATA_DIR) {
- CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA/src]/
- CMAKE_HOST_DATA_DIR_IS_ABSOLUTE = True
-}
-
-cmake_extras_mkspec_dir.input = $$PWD/Qt5CoreConfigExtrasMkspecDir.cmake.in
-cmake_extras_mkspec_dir.output = $$DESTDIR/cmake/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake
-
-CMAKE_INSTALL_DATA_DIR = $$cmakeRelativePath($$[QT_HOST_DATA], $$[QT_INSTALL_PREFIX])
-pathIsAbsolute($$CMAKE_INSTALL_DATA_DIR) {
- CMAKE_INSTALL_DATA_DIR = $$[QT_HOST_DATA]/
- CMAKE_INSTALL_DATA_DIR_IS_ABSOLUTE = True
-}
-
-cmake_extras_mkspec_dir_for_install.input = $$PWD/Qt5CoreConfigExtrasMkspecDirForInstall.cmake.in
-cmake_extras_mkspec_dir_for_install.output = $$DESTDIR/cmake/install/Qt5Core/Qt5CoreConfigExtrasMkspecDir.cmake
-
-cmake_qt5_umbrella_module_files.files = \
- $$cmake_umbrella_config_file.output \
- $$cmake_umbrella_config_version_file.output \
- $$cmake_umbrella_config_module_location_for_install.output
-
-cmake_qt5_umbrella_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5
-
-QMAKE_SUBSTITUTES += \
- ctest_macros_file \
- cmake_umbrella_config_file \
- cmake_umbrella_config_module_location \
- cmake_umbrella_config_module_location_for_install \
- cmake_umbrella_config_version_file \
- cmake_extras_mkspec_dir \
- cmake_extras_mkspec_dir_for_install
-
-android {
- QMAKE_SUBSTITUTES += cmake_android_support
- ctest_qt5_module_files.files += $$cmake_android_support.output
-}
-
-ctest_qt5_module_files.files += $$ctest_macros_file.output $$cmake_extras_mkspec_dir_for_install.output
-
-ctest_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5Core
-
-INSTALLS += ctest_qt5_module_files cmake_qt5_umbrella_module_files
-
-QMAKE_DSYM_DEBUG_SCRIPT = $$PWD/debug_script.py
diff --git a/src/corelib/debug_script.py b/src/corelib/debug_script.py
index 9111213ef7..b4a58530da 100644
--- a/src/corelib/debug_script.py
+++ b/src/corelib/debug_script.py
@@ -1,30 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2017 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of the QtCore module of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2017 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import os
import sys
@@ -34,10 +9,12 @@ from distutils.version import LooseVersion
MODULE_NAME = 'qt'
-def import_bridge(path, debugger, session_dict, reload_module = False):
+def import_bridge(path, debugger, session_dict, reload_module=False):
if not reload_module and MODULE_NAME in sys.modules:
del sys.modules[MODULE_NAME]
+ if sys.version_info[0] >= 3:
+ sys.path.append(os.path.dirname(path))
bridge = imp.load_source(MODULE_NAME, path)
if not hasattr(bridge, '__lldb_init_module'):
@@ -57,10 +34,6 @@ def import_bridge(path, debugger, session_dict, reload_module = False):
return bridge
-def report_success(bridge):
- print "Using Qt summary providers from Creator %s in '%s'" \
- % (bridge.CREATOR_VERSION, bridge.CREATOR_PATH)
-
def __lldb_init_module(debugger, session_dict):
# Check if the module has already been imported globally. This ensures
# that the Qt Creator application search is only performed once per
@@ -71,28 +44,36 @@ def __lldb_init_module(debugger, session_dict):
bridge = import_bridge(module.__file__, debugger, session_dict,
reload_module = True)
if bridge:
- report_success(bridge)
return
versions = {}
- for install in os.popen(
- 'mdfind kMDItemCFBundleIdentifier=org.qt-project.qtcreator'
- '| while read p;'
- 'do echo $p=$(mdls "$p" -name kMDItemVersion -raw);'
- 'done'):
- install = install.strip()
- (p, v) = install.split('=')
- versions[v] = p
+ for path in os.popen('mdfind kMDItemCFBundleIdentifier=org.qt-project.qtcreator'):
+ path = path.strip()
+ file = open(os.path.join(path, 'Contents', 'Info.plist'), "rb")
+
+ import plistlib
+ plist = plistlib.load(file)
+
+ version = None
+ for key in ["CFBundleVersion", "CFBundleShortVersionString"]:
+ if key in plist:
+ version = plist[key]
+ break
+
+ if not version:
+ print(f"Could not resolve version for '{path}'. Ignoring.")
+ continue
+
+ versions[version] = path
+
+ if not len(versions):
+ print("Could not find Qt Creator installation. No Qt summary providers installed.")
+ return
for version in sorted(versions, key=LooseVersion, reverse=True):
path = versions[version]
-
- bridge_path = path + '/Contents/Resources/debugger/lldbbridge.py'
+ print(f"Loading Qt summary providers from Creator {version} in '{path}'")
+ bridge_path = '{}/Contents/Resources/debugger/lldbbridge.py'.format(path)
bridge = import_bridge(bridge_path, debugger, session_dict)
if bridge:
- bridge.CREATOR_VERSION = version
- bridge.CREATOR_PATH = path
- report_success(bridge)
return
-
- print "Could not find Qt Creator installation, no Qt summary providers installed"
diff --git a/src/corelib/doc/images/resources.png b/src/corelib/doc/images/resources.png
deleted file mode 100644
index eb7af96d77..0000000000
--- a/src/corelib/doc/images/resources.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-button-history.png b/src/corelib/doc/images/statemachine-button-history.png
deleted file mode 100644
index 7f51cae3f2..0000000000
--- a/src/corelib/doc/images/statemachine-button-history.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-button-nested.png b/src/corelib/doc/images/statemachine-button-nested.png
deleted file mode 100644
index 762ac14df1..0000000000
--- a/src/corelib/doc/images/statemachine-button-nested.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-button.png b/src/corelib/doc/images/statemachine-button.png
deleted file mode 100644
index 10102bdf2c..0000000000
--- a/src/corelib/doc/images/statemachine-button.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-customevents.png b/src/corelib/doc/images/statemachine-customevents.png
deleted file mode 100644
index 62a42223ef..0000000000
--- a/src/corelib/doc/images/statemachine-customevents.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-customevents2.png b/src/corelib/doc/images/statemachine-customevents2.png
deleted file mode 100644
index 57b37ef1dd..0000000000
--- a/src/corelib/doc/images/statemachine-customevents2.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-examples.png b/src/corelib/doc/images/statemachine-examples.png
deleted file mode 100644
index b2ec66e19d..0000000000
--- a/src/corelib/doc/images/statemachine-examples.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-finished.png b/src/corelib/doc/images/statemachine-finished.png
deleted file mode 100644
index 0ac081d6ba..0000000000
--- a/src/corelib/doc/images/statemachine-finished.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-nonparallel.png b/src/corelib/doc/images/statemachine-nonparallel.png
deleted file mode 100644
index f9850a74a6..0000000000
--- a/src/corelib/doc/images/statemachine-nonparallel.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/images/statemachine-parallel.png b/src/corelib/doc/images/statemachine-parallel.png
deleted file mode 100644
index a65c297f5b..0000000000
--- a/src/corelib/doc/images/statemachine-parallel.png
+++ /dev/null
Binary files differ
diff --git a/src/corelib/doc/include/QtCoreDoc b/src/corelib/doc/include/QtCoreDoc
new file mode 100644
index 0000000000..5f5490cbc9
--- /dev/null
+++ b/src/corelib/doc/include/QtCoreDoc
@@ -0,0 +1,4 @@
+#include <QtCore/QtCore>
+#include "../../platform/android/qandroidextras_p.h"
+#include "../../kernel/qpermissions.h"
+#include "../../tools/qatomicscopedvaluerollback_p.h"
diff --git a/src/corelib/doc/include/jni.h b/src/corelib/doc/include/jni.h
new file mode 100644
index 0000000000..4eff8636f6
--- /dev/null
+++ b/src/corelib/doc/include/jni.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#pragma once
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Dummy declarations for generating docs on non-Android platforms
+#if !defined(Q_OS_ANDROID) && defined(Q_QDOC)
+typedef struct {} JNIEnv;
+typedef struct {} JNINativeMethod;
+struct _jclass;
+typedef _jclass* jclass;
+struct _jobject;
+typedef _jobject* jobject;
+typedef int jint;
+typedef int jmethodID;
+typedef int jfieldID;
+typedef void* JavaVM;
+#endif
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index 28b926b732..4ed46ae6dd 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -5,6 +5,9 @@ project = QtCore
description = Qt Core Reference Documentation
version = $QT_VERSION
+moduleheader = QtCoreDoc
+includepaths += ./include
+
examplesinstallpath = corelib
qhp.projects = QtCore
@@ -15,9 +18,6 @@ qhp.QtCore.virtualFolder = qtcore
qhp.QtCore.indexTitle = Qt Core
qhp.QtCore.indexRoot =
-qhp.QtCore.filterAttributes = qtcore $QT_VERSION qtrefdoc
-qhp.QtCore.customFilters.Qt.name = QtCore $QT_VERSION
-qhp.QtCore.customFilters.Qt.filterAttributes = qtcore $QT_VERSION
qhp.QtCore.subprojects = classes
qhp.QtCore.subprojects.classes.title = C++ Classes
qhp.QtCore.subprojects.classes.indexTitle = Qt Core C++ Classes
@@ -26,11 +26,16 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags
-depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras qtqml qtcmake
+# Make QtCore depend on all doc modules; this ensures complete inheritance
+# information for classes
+depends = *
headerdirs += ..
-sourcedirs += ..
+sourcedirs += .. \
+ ../../tools/androiddeployqt \
+ ../../android/templates \
+ src/includes
exampledirs += \
../ \
@@ -38,7 +43,8 @@ exampledirs += \
../../../examples/corelib \
../../../examples/network/dnslookup \
../../../examples/widgets/tools \
- ../../../tests/auto/corelib/thread/qpromise/
+ ../../../tests/auto/corelib/thread/qpromise \
+ ../../tools/androiddeployqt
imagedirs += images
@@ -46,11 +52,19 @@ excludedirs += snippets
excludefiles += ../../../examples/widgets/tools/customcompleter/doc/src/customcompleter.qdoc
+defines += QT_BUILD_CORE_LIB
+
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_core.cpp
-manifestmeta.highlighted.names = "QtCore/JSON Save Game Example" \
- "QtCore/Local Fortune*"
-
navigation.landingpage = "Qt Core"
navigation.cppclassespage = "Qt Core C++ Classes"
+
+# Highlighted examples in Data Processing & IO category
+manifestmeta.highlighted.names = \
+ "QtCore/Mandelbrot" \
+ "QtCore/Serialization Converter" \
+ "QtCore/QXmlStream Bookmarks Example"
+
+# Temporarily allow warning: No such parameter 'other' in QFlags::operator=()
+warninglimit = 1
diff --git a/src/corelib/doc/snippets/buffer/buffer.cpp b/src/corelib/doc/snippets/buffer/buffer.cpp
index 66747aad39..160c0327c3 100644
--- a/src/corelib/doc/snippets/buffer/buffer.cpp
+++ b/src/corelib/doc/snippets/buffer/buffer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QBuffer>
diff --git a/src/corelib/doc/snippets/cmake-macros/deployment.cmake b/src/corelib/doc/snippets/cmake-macros/deployment.cmake
new file mode 100644
index 0000000000..ef7aa726c0
--- /dev/null
+++ b/src/corelib/doc/snippets/cmake-macros/deployment.cmake
@@ -0,0 +1,27 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#! [qt_generate_deploy_script_example]
+cmake_minimum_required(VERSION 3.16...3.22)
+project(MyThings)
+
+find_package(Qt6 REQUIRED COMPONENTS Core)
+qt_standard_project_setup()
+
+qt_add_executable(MyApp main.cpp)
+
+install(TARGETS MyApp
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+qt_generate_deploy_script(
+ TARGET MyApp
+ OUTPUT_SCRIPT deploy_script
+ CONTENT "
+qt_deploy_runtime_dependencies(
+ EXECUTABLE $<TARGET_FILE_NAME:MyApp>
+)
+")
+install(SCRIPT ${deploy_script})
+#! [qt_generate_deploy_script_example]
diff --git a/src/corelib/doc/snippets/cmake-macros/examples.cmake b/src/corelib/doc/snippets/cmake-macros/examples.cmake
index 913b39cb4f..09b7470962 100644
--- a/src/corelib/doc/snippets/cmake-macros/examples.cmake
+++ b/src/corelib/doc/snippets/cmake-macros/examples.cmake
@@ -1,75 +1,106 @@
-#! [qt5_wrap_cpp]
-set(SOURCES myapp.cpp main.cpp)
-qt5_wrap_cpp(SOURCES myapp.h)
-add_executable(myapp ${SOURCES})
-#! [qt5_wrap_cpp]
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-#! [qt_wrap_cpp]
+#! [qt_wrap_cpp_1]
set(SOURCES myapp.cpp main.cpp)
qt_wrap_cpp(SOURCES myapp.h)
-add_executable(myapp ${SOURCES})
-#! [qt_wrap_cpp]
+qt_add_executable(myapp ${SOURCES})
+#! [qt_wrap_cpp_1]
-#! [qt5_add_resources]
-set(SOURCES main.cpp)
-qt5_add_resources(SOURCES example.qrc)
-add_executable(myapp ${SOURCES})
-#! [qt5_add_resources]
+#! [qt_wrap_cpp_2]
+set(SOURCES myapp.cpp main.cpp)
+qt_wrap_cpp(SOURCES myapp.h
+ TARGET myapp
+ OPTIONS
+ "$<$<CONFIG:Debug>:-DMY_OPTION_FOR_DEBUG>"
+ "-DDEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int, int> &i)"
+ "$<$<CONFIG:Debug>:-DDEFINE_CMDLINE_SIGNAL_IN_GENEX=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>")
+qt_add_executable(myapp ${SOURCES})
+#! [qt_wrap_cpp_2]
+
+#! [qt_wrap_cpp_3]
+set(SOURCES myapp.cpp main.cpp)
+qt_wrap_cpp(SOURCES myapp.h
+ TARGET myapp)
+qt_add_executable(myapp ${SOURCES})
+target_compile_definitions(myapp PRIVATE "$<$<CONFIG:Debug>:MY_OPTION_FOR_DEBUG>"
+ "DEFINE_CMDLINE_SIGNAL=void cmdlineSignal(const QMap<int, int> &i)"
+ "$<$<BOOL:TRUE>:DEFINE_CMDLINE_SIGNAL_IN_GENEX=void cmdlineSignal(const QMap<int$<COMMA> int$<ANGLE-R> &i)>")
+#! [qt_wrap_cpp_3]
+
+#! [qt_wrap_cpp_4]
+qt_add_executable(myapp myapp.cpp main.cpp)
+qt_wrap_cpp("" myapp.cpp TARGET myapp)
+#! [qt_wrap_cpp_4]
#! [qt_add_resources]
set(SOURCES main.cpp)
qt_add_resources(SOURCES example.qrc)
-add_executable(myapp ${SOURCES})
+qt_add_executable(myapp ${SOURCES})
#! [qt_add_resources]
-#! [qt5_add_big_resources]
-set(SOURCES main.cpp)
-qt5_add_big_resources(SOURCES big_resource.qrc)
-add_executable(myapp ${SOURCES})
-#! [qt5_add_big_resources]
+#! [qt_add_resources_target]
+qt_add_executable(myapp main.cpp)
+qt_add_resources(myapp "images"
+ PREFIX "/images"
+ FILES image1.png image2.png)
+#! [qt_add_resources_target]
#! [qt_add_big_resources]
set(SOURCES main.cpp)
qt_add_big_resources(SOURCES big_resource.qrc)
-add_executable(myapp ${SOURCES})
-#! [qt_add_big_resources]
-#! [qt5_add_binary_resources]
-qt5_add_binary_resources(resources project.qrc OPTIONS -no-compress)
-add_dependencies(myapp resources)
-#! [qt5_add_binary_resources]
+# Have big_resource.qrc treated as a source file by Qt Creator
+list(APPEND SOURCES big_resource.qrc)
+set_property(SOURCE big_resource.qrc PROPERTY SKIP_AUTORCC ON)
+
+qt_add_executable(myapp ${SOURCES})
+#! [qt_add_big_resources]
#! [qt_add_binary_resources]
qt_add_binary_resources(resources project.qrc OPTIONS -no-compress)
add_dependencies(myapp resources)
#! [qt_add_binary_resources]
-#! [qt5_generate_moc]
-qt5_generate_moc(main.cpp main.moc TARGET myapp)
-#! [qt5_generate_moc]
-
#! [qt_generate_moc]
qt_generate_moc(main.cpp main.moc TARGET myapp)
#! [qt_generate_moc]
-#! [qt5_import_plugins]
-add_executable(myapp main.cpp)
-target_link_libraries(myapp Qt5::Gui Qt5::Sql)
-qt5_import_plugins(myapp
- INCLUDE Qt5::QCocoaIntegrationPlugin
- EXCLUDE Qt5::QMinimalIntegrationPlugin
- INCLUDE_BY_TYPE imageformats Qt5::QGifPlugin Qt5::QJpegPlugin
- EXCLUDE_BY_TYPE sqldrivers
-)
-#! [qt5_import_plugins]
-
#! [qt_import_plugins]
-add_executable(myapp main.cpp)
+qt_add_executable(myapp main.cpp)
target_link_libraries(myapp Qt::Gui Qt::Sql)
qt_import_plugins(myapp
INCLUDE Qt::QCocoaIntegrationPlugin
EXCLUDE Qt::QMinimalIntegrationPlugin
- INCLUDE_BY_TYPE imageformats Qt5::QGifPlugin Qt5::QJpegPlugin
+ INCLUDE_BY_TYPE imageformats Qt::QGifPlugin Qt::QJpegPlugin
EXCLUDE_BY_TYPE sqldrivers
)
#! [qt_import_plugins]
+
+#! [qt_add_executable_simple]
+qt_add_executable(simpleapp main.cpp)
+#! [qt_add_executable_simple]
+
+#! [qt_add_executable_deferred]
+qt_add_executable(complexapp MANUAL_FINALIZATION complex.cpp)
+set_target_properties(complexapp PROPERTIES OUTPUT_NAME Complexify)
+qt_finalize_target(complexapp)
+#! [qt_add_executable_deferred]
+
+#! [qt_android_deploy_basic]
+qt_android_generate_deployment_settings(myapp)
+qt_android_add_apk_target(myapp)
+#! [qt_android_deploy_basic]
+
+#! [qt_finalize_project_manual]
+cmake_minimum_required(VERSIONS 3.16)
+
+project(MyProject LANGUAGES CXX)
+
+find_package(Qt6 REQUIRED COMPONENTS Core)
+
+qt_add_executable(MyApp main.cpp)
+add_subdirectory(mylib)
+
+qt_finalize_project()
+#! [qt_finalize_project_manual]
diff --git a/src/corelib/doc/snippets/cmake-macros/examples.cpp b/src/corelib/doc/snippets/cmake-macros/examples.cpp
new file mode 100644
index 0000000000..b17fcd8e77
--- /dev/null
+++ b/src/corelib/doc/snippets/cmake-macros/examples.cpp
@@ -0,0 +1,16 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [qt_wrap_cpp_4]
+// myapp.cpp
+#include "myapp.h"
+#include <QObject>
+
+class MyApp : public QObject {
+ Q_OBJECT
+public:
+ MyApp() = default;
+};
+
+#include "myapp.moc"
+//! [qt_wrap_cpp_4]
diff --git a/src/corelib/doc/snippets/code/doc_src_containers.cpp b/src/corelib/doc/snippets/code/doc_src_containers.cpp
index e791c0c664..b568462492 100644
--- a/src/corelib/doc/snippets/code/doc_src_containers.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_containers.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
//! [0]
class Employee
@@ -63,14 +18,34 @@ private:
};
//! [0]
+//! [range_for]
+QList<QString> list = {"A", "B", "C", "D"};
+for (const auto &item : list) {
+ ...
+}
+//! [range_for]
+
+//! [range_for_as_const]
+QList<QString> list = {"A", "B", "C", "D"};
+for (const auto &item : std::as_const(list)) {
+ ...
+}
+//! [range_for_as_const]
+
+//! [index]
+QList<QString> list = {"A", "B", "C", "D"};
+for (qsizetype i = 0; i < list.size(); ++i) {
+ const auto &item = list.at(i);
+ ...
+}
+//! [index]
//! [1]
-QList<QString> list;
-list << "A" << "B" << "C" << "D";
+QList<QString> list = {"A", "B", "C", "D"};
QListIterator<QString> i(list);
while (i.hasNext())
- qDebug() << i.next();
+ QString s = i.next();
//! [1]
@@ -78,7 +53,7 @@ while (i.hasNext())
QListIterator<QString> i(list);
i.toBack();
while (i.hasPrevious())
- qDebug() << i.previous();
+ QString s = i.previous();
//! [2]
@@ -118,11 +93,12 @@ while (i.hasNext())
//! [7]
-QMap<QString, QString> map;
-map.insert("Paris", "France");
-map.insert("Guatemala City", "Guatemala");
-map.insert("Mexico City", "Mexico");
-map.insert("Moscow", "Russia");
+QMap<QString, QString> map = {
+ {"Paris", "France"},
+ {"Guatemala City", "Guatemala"},
+ {"Mexico City", "Mexico"},
+ {"Moscow", "Russia"}
+};
...
QMutableMapIterator<QString, QString> i(map);
@@ -153,29 +129,23 @@ while (i.findNext(widget))
//! [10]
-QList<QString> list;
-list << "A" << "B" << "C" << "D";
+QList<QString> list = {"A", "B", "C", "D"};
-QList<QString>::iterator i;
-for (i = list.begin(); i != list.end(); ++i)
+for (auto i = list.begin(), end = list.end(); i != end; ++i)
*i = (*i).toLower();
//! [10]
//! [11]
-QList<QString> list;
-list << "A" << "B" << "C" << "D";
+QList<QString> list = {"A", "B", "C", "D"};
-QList<QString>::reverse_iterator i;
-for (i = list.rbegin(); i != list.rend(); ++i)
+for (auto i = list.rbegin(), rend = list.rend(); i != rend; ++i)
*i = i->toLower();
-}
//! [11]
//! [12]
-QList<QString>::const_iterator i;
-for (i = list.constBegin(); i != list.constEnd(); ++i)
+for (auto i = list.cbegin(), end = list.cend(); i != end; ++i)
qDebug() << *i;
//! [12]
@@ -183,8 +153,7 @@ for (i = list.constBegin(); i != list.constEnd(); ++i)
//! [13]
QMap<int, int> map;
...
-QMap<int, int>::const_iterator i;
-for (i = map.constBegin(); i != map.constEnd(); ++i)
+for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
qDebug() << i.key() << ':' << i.value();
//! [13]
@@ -192,13 +161,11 @@ for (i = map.constBegin(); i != map.constEnd(); ++i)
//! [14]
// RIGHT
const QList<int> sizes = splitter->sizes();
-QList<int>::const_iterator i;
-for (i = sizes.begin(); i != sizes.end(); ++i)
+for (auto i = sizes.begin(), end = sizes.end(); i != end; ++i)
...
// WRONG
-QList<int>::const_iterator i;
-for (i = splitter->sizes().begin();
+for (auto i = splitter->sizes().begin();
i != splitter->sizes().end(); ++i)
...
//! [14]
@@ -217,8 +184,10 @@ foreach (str, values)
QList<QString> values;
...
QListIterator<QString> i(values);
-while (i.hasNext())
- qDebug() << i.next();
+while (i.hasNext()) {
+ QString s = i.next();
+ qDebug() << s;
+}
//! [16]
@@ -259,25 +228,23 @@ foreach (const QString &str, map.uniqueKeys()) {
//! [20]
-//! [21]
-forever {
- ...
-}
-//! [21]
-
-
//! [22]
CONFIG += no_keywords
//! [22]
+//! [cmake_no_keywords]
+target_compile_definitions(my_app PRIVATE QT_NO_KEYWORDS)
+//! [cmake_no_keywords]
+
+
//! [23]
QString onlyLetters(const QString &in)
{
QString out;
- for (int j = 0; j < in.size(); ++j) {
- if (in[j].isLetter())
- out += in[j];
+ for (qsizetype j = 0; j < in.size(); ++j) {
+ if (in.at(j).isLetter())
+ out += in.at(j);
}
return out;
}
@@ -314,9 +281,30 @@ int j = *i; // Undefined behavior!
//! [24]
//! [25]
-QList<int> list { 1, 2, 3, 4, 4, 5 };
-QSet<int> set(list.begin(), list.end());
+QList<int> list = {1, 2, 3, 4, 4, 5};
+QSet<int> set(list.cbegin(), list.cend());
/*
- Will generate a QSet containing 1, 2, 4, 5.
+ Will generate a QSet containing 1, 2, 3, 4, 5.
*/
//! [25]
+
+//! [26]
+QList<int> list = {2, 3, 1};
+
+std::sort(list.begin(), list.end());
+/*
+ Sort the list, now contains { 1, 2, 3 }
+*/
+
+std::reverse(list.begin(), list.end());
+/*
+ Reverse the list, now contains { 3, 2, 1 }
+*/
+
+int even_elements =
+ std::count_if(list.begin(), list.end(), [](int element) { return (element % 2 == 0); });
+/*
+ Count how many elements that are even numbers, 1
+*/
+
+//! [26]
diff --git a/src/corelib/doc/snippets/code/doc_src_groups.cpp b/src/corelib/doc/snippets/code/doc_src_groups.cpp
index 2b8ed39447..a0901904db 100644
--- a/src/corelib/doc/snippets/code/doc_src_groups.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_groups.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
void QPen::setStyle(Qt::PenStyle style)
diff --git a/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp b/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp
index 849b628e0c..b7c71ccb6b 100644
--- a/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//![0]
int main()
diff --git a/src/corelib/doc/snippets/code/doc_src_properties.cpp b/src/corelib/doc/snippets/code/doc_src_properties.cpp
index e026a47e23..190a843710 100644
--- a/src/corelib/doc/snippets/code/doc_src_properties.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_properties.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
Q_PROPERTY(type name
@@ -59,9 +12,10 @@ Q_PROPERTY(type name
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
+ [BINDABLE bindableProperty]
[CONSTANT]
- [FINAL])
- [REQUIRED]
+ [FINAL]
+ [REQUIRED])
//! [0]
@@ -106,7 +60,7 @@ class MyClass : public QObject
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
public:
- MyClass(QObject *parent = 0);
+ MyClass(QObject *parent = nullptr);
~MyClass();
enum Priority { High, Low, VeryHigh, VeryLow };
@@ -114,6 +68,9 @@ public:
void setPriority(Priority priority)
{
+ if (m_priority == priority)
+ return;
+
m_priority = priority;
emit priorityChanged(priority);
}
@@ -139,7 +96,7 @@ object->setProperty("priority", "VeryHigh");
//! [7]
-Q_CLASSINFO("Version", "3.0.0")
+Q_CLASSINFO("DefaultProperty", "content")
//! [7]
//! [8]
diff --git a/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp b/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp
index 58f6b196b4..f2b94a7416 100644
--- a/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp
@@ -1,364 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-QStringList list;
-list << "one" << "two" << "three";
-
-qFill(list.begin(), list.end(), "eleven");
-// list: [ "eleven", "eleven", "eleven" ]
-//! [0]
-
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [1]
-qFill(list.begin() + 1, list.end(), "six");
-// list: [ "eleven", "six", "six" ]
-//! [1]
-
-
-//! [2]
-QChar resolveEntity(const QString &entity)
-{
- static const QLatin1String name_table[] = {
- "AElig", "Aacute", ..., "zwnj"
- };
- static const ushort value_table[] = {
- 0x0061, 0x00c1, ..., 0x200c
- };
- int N = sizeof(name_table) / sizeof(name_table[0]);
-
- const QLatin1String *name = qBinaryFind(name_table, name_table + N,
- entity);
- int index = name - name_table;
- if (index == N)
- return QChar();
-
- return QChar(value_table[index]);
-}
-//! [2]
-
-
-//! [3]
-QChar resolveEntity(const QString &entity)
-{
- static QMap<QString, int> entityMap;
-
- if (!entityMap) {
- entityMap.insert("AElig", 0x0061);
- entityMap.insert("Aacute", 0x00c1);
- ...
- entityMap.insert("zwnj", 0x200c);
- }
- return QChar(entityMap.value(entity));
-}
-//! [3]
-
-
-//! [4]
-QStringList list;
-list << "one" << "two" << "three";
-
-QList<QString> list1(3);
-qCopy(list.begin(), list.end(), list1.begin());
-// list1: [ "one", "two", "three" ]
-
-QList<QString> list2(8);
-qCopy(list.begin(), list.end(), list2.begin() + 2);
-// list2: [ "", "", "one", "two", "three", "", "", "" ]
-//! [4]
-
-
-//! [5]
-QStringList list;
-list << "one" << "two" << "three";
-
-QList<QString> backList(5);
-qCopyBackward(list.begin(), list.end(), backList.end());
-// backList: [ "", "", "one", "two", "three" ]
-//! [5]
-
-
-//! [6]
-QStringList listLeft;
-listLeft << "one" << "two" << "three";
-
-QList<QString> listRight(3);
-listRight[0] = "one";
-listRight[1] = "two";
-listRight[2] = "three";
-
-bool ret1 = qEqual(listLeft.begin(), listLeft.end(), listRight.begin());
-// ret1 == true
-
-listRight[2] = "seven";
-bool ret2 = qEqual(listLeft.begin(), listLeft.end(), listRight.begin());
-// ret2 == false
-//! [6]
-
-
-//! [7]
-QStringList list;
-list << "one" << "two" << "three";
-
-qFill(list.begin(), list.end(), "eleven");
-// list: [ "eleven", "eleven", "eleven" ]
-
-qFill(list.begin() + 1, list.end(), "six");
-// list: [ "eleven", "six", "six" ]
-//! [7]
-
-
-//! [8]
-QStringList list;
-list << "one" << "two" << "three";
-
-QStringList::iterator i1 = qFind(list.begin(), list.end(), "two");
-// i1 == list.begin() + 1
-
-QStringList::iterator i2 = qFind(list.begin(), list.end(), "seventy");
-// i2 == list.end()
-//! [8]
-
-
-//! [9]
-QList<int> list;
-list << 3 << 3 << 6 << 6 << 6 << 8;
-
-int countOf6 = 0;
-qCount(list.begin(), list.end(), 6, countOf6);
-// countOf6 == 3
-
-int countOf7 = 0;
-qCount(list.begin(), list.end(), 7, countOf7);
-// countOf7 == 0
-//! [9]
-
-
-//! [10]
-double pi = 3.14;
-double e = 2.71;
-
-qSwap(pi, e);
-// pi == 2.71, e == 3.14
-//! [10]
-
-
-//! [11]
-QList<int> list;
-list << 33 << 12 << 68 << 6 << 12;
-qSort(list.begin(), list.end());
-// list: [ 6, 12, 12, 33, 68 ]
-//! [11]
-
-
-//! [12]
-bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
-{
- return s1.toLower() < s2.toLower();
-}
-
-int doSomething()
-{
- QStringList list;
- list << "AlPha" << "beTA" << "gamma" << "DELTA";
- qSort(list.begin(), list.end(), caseInsensitiveLessThan);
- // list: [ "AlPha", "beTA", "DELTA", "gamma" ]
-}
-//! [12]
-
-
-//! [13]
-QList<int> list;
-list << 33 << 12 << 68 << 6 << 12;
-qSort(list.begin(), list.end(), qGreater<int>());
-// list: [ 68, 33, 12, 12, 6 ]
-//! [13]
-
-
-//! [14]
-QStringList list;
-list << "AlPha" << "beTA" << "gamma" << "DELTA";
-
-QMap<QString, QString> map;
-foreach (const QString &str, list)
- map.insert(str.toLower(), str);
-
-list = map.values();
-//! [14]
-
-
-//! [15]
-QList<int> list;
-list << 33 << 12 << 68 << 6 << 12;
-qStableSort(list.begin(), list.end());
-// list: [ 6, 12, 12, 33, 68 ]
-//! [15]
-
-
-//! [16]
-bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
-{
- return s1.toLower() < s2.toLower();
-}
-
-int doSomething()
-{
- QStringList list;
- list << "AlPha" << "beTA" << "gamma" << "DELTA";
- qStableSort(list.begin(), list.end(), caseInsensitiveLessThan);
- // list: [ "AlPha", "beTA", "DELTA", "gamma" ]
-}
-//! [16]
-
-
-//! [17]
-QList<int> list;
-list << 33 << 12 << 68 << 6 << 12;
-qStableSort(list.begin(), list.end(), qGreater<int>());
-// list: [ 68, 33, 12, 12, 6 ]
-//! [17]
-
-
-//! [18]
-QList<int> list;
-list << 3 << 3 << 6 << 6 << 6 << 8;
-
-QList<int>::iterator i = qLowerBound(list.begin(), list.end(), 5);
-list.insert(i, 5);
-// list: [ 3, 3, 5, 6, 6, 6, 8 ]
-
-i = qLowerBound(list.begin(), list.end(), 12);
-list.insert(i, 12);
-// list: [ 3, 3, 5, 6, 6, 6, 8, 12 ]
-//! [18]
-
-
-//! [19]
-QList<int> list;
-list << 3 << 3 << 6 << 6 << 6 << 8;
-QList<int>::iterator begin6 =
- qLowerBound(list.begin(), list.end(), 6);
-QList<int>::iterator end6 =
- qUpperBound(begin6, list.end(), 6);
-
-QList<int>::iterator i = begin6;
-while (i != end6) {
- *i = 7;
- ++i;
-}
-// list: [ 3, 3, 7, 7, 7, 8 ]
-//! [19]
-
-
-//! [20]
-QList<int> list;
-list << 3 << 3 << 6 << 6 << 6 << 8;
-
-QList<int>::iterator i = qUpperBound(list.begin(), list.end(), 5);
-list.insert(i, 5);
-// list: [ 3, 3, 5, 6, 6, 6, 8 ]
-
-i = qUpperBound(list.begin(), list.end(), 12);
-list.insert(i, 12);
-// list: [ 3, 3, 5, 6, 6, 6, 8, 12 ]
-//! [20]
-
-
-//! [21]
-QList<int> list;
-list << 3 << 3 << 6 << 6 << 6 << 8;
-QList<int>::iterator begin6 =
- qLowerBound(list.begin(), list.end(), 6);
-QList<int>::iterator end6 =
- qUpperBound(list.begin(), list.end(), 6);
-
-QList<int>::iterator i = begin6;
-while (i != end6) {
- *i = 7;
- ++i;
-}
-// list: [ 3, 3, 7, 7, 7, 8 ]
-//! [21]
-
-
-//! [22]
-QList<int> list;
-list << 3 << 3 << 6 << 6 << 6 << 8;
-
-QList<int>::iterator i =
- qBinaryFind(list.begin(), list.end(), 6);
-// i == list.begin() + 2 (or 3 or 4)
-//! [22]
-
-
-//! [23]
QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));
qDeleteAll(list.begin(), list.end());
list.clear();
-//! [23]
-
-
-//! [24]
-QList<int> list;
-list << 33 << 12 << 68 << 6 << 12;
-qSort(list.begin(), list.end(), qLess<int>());
-// list: [ 6, 12, 12, 33, 68 ]
-//! [24]
-
-
-//! [25]
-QList<int> list;
-list << 33 << 12 << 68 << 6 << 12;
-qSort(list.begin(), list.end(), qGreater<int>());
-// list: [ 68, 33, 12, 12, 6 ]
-//! [25]
+//! [1]
diff --git a/src/corelib/doc/snippets/code/doc_src_qcache.cpp b/src/corelib/doc/snippets/code/doc_src_qcache.cpp
index 757a72b521..a15a802760 100644
--- a/src/corelib/doc/snippets/code/doc_src_qcache.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qcache.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QCache<int, Employee> cache;
diff --git a/src/corelib/doc/snippets/code/doc_src_qiterator.cpp b/src/corelib/doc/snippets/code/doc_src_qiterator.cpp
index 265e4a724a..0d921b87e6 100644
--- a/src/corelib/doc/snippets/code/doc_src_qiterator.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qiterator.cpp
@@ -1,59 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QList<float> list;
...
QListIterator<float> i(list);
while (i.hasNext())
- qDebug() << i.next();
+ float f = i.next();
//! [0]
@@ -61,7 +14,7 @@ while (i.hasNext())
QListIterator<float> i(list);
i.toBack();
while (i.hasPrevious())
- qDebug() << i.previous();
+ float f = i.previous();
//! [1]
//! [6]
@@ -69,24 +22,15 @@ QSet<QString> set;
...
QSetIterator<QString> i(set);
while (i.hasNext())
- qDebug() << i.next();
+ float f = i.next();
//! [6]
-
-//! [7]
-QSetIterator<QString> i(set);
-i.toBack();
-while (i.hasPrevious())
- qDebug() << i.previous();
-//! [7]
-
-
//! [8]
QList<float> list;
...
QMutableListIterator<float> i(list);
while (i.hasNext())
- qDebug() << i.next();
+ float f = i.next();
//! [8]
@@ -94,7 +38,7 @@ while (i.hasNext())
QMutableListIterator<float> i(list);
i.toBack();
while (i.hasPrevious())
- qDebug() << i.previous();
+ float f = i.previous();
//! [9]
@@ -115,18 +59,9 @@ QSet<float> set;
...
QMutableSetIterator<float> i(set);
while (i.hasNext())
- qDebug() << i.next();
+ float f = i.next();
//! [17]
-
-//! [18]
-QMutableSetIterator<float> i(set);
-i.toBack();
-while (i.hasPrevious())
- qDebug() << i.previous();
-//! [18]
-
-
//! [19]
QMutableListIterator<int> i(list);
while (i.hasNext()) {
@@ -183,26 +118,45 @@ while (i.findNext(widget)) {
}
//! [28]
-
-//! [29]
-QHash<int, QWidget *> hash;
+//! [26multi]
+QMultiMap<int, QWidget *> multimap;
...
-QHashIterator<int, QWidget *> i(hash);
+QMultiMapIterator<int, QWidget *> i(multimap);
while (i.hasNext()) {
i.next();
qDebug() << i.key() << ": " << i.value();
}
-//! [29]
+//! [26multi]
-//! [30]
-QHashIterator<int, QWidget *> i(hash);
+//! [27multi]
+QMultiMapIterator<int, QWidget *> i(multimap);
i.toBack();
while (i.hasPrevious()) {
i.previous();
qDebug() << i.key() << ": " << i.value();
}
-//! [30]
+//! [27multi]
+
+
+//! [28multi]
+QMultiMapIterator<int, QWidget *> i(multimap);
+while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+}
+//! [28multi]
+
+
+//! [29]
+QHash<int, QWidget *> hash;
+...
+QHashIterator<int, QWidget *> i(hash);
+while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+}
+//! [29]
//! [31]
@@ -254,25 +208,55 @@ while (i.hasNext()) {
//! [35]
-//! [36]
-QHash<int, QWidget *> hash;
+//! [32multi]
+QMultiMap<int, QWidget *> multimap;
...
-QMutableHashIterator<QString, QWidget *> i(hash);
+QMutableMultiMapIterator<int, QWidget *> i(multimap);
while (i.hasNext()) {
i.next();
qDebug() << i.key() << ": " << i.value();
}
-//! [36]
+//! [32multi]
-//! [37]
-QMutableHashIterator<int, QWidget *> i(hash);
+//! [33multi]
+QMutableMultiMapIterator<int, QWidget *> i(multimap);
i.toBack();
while (i.hasPrevious()) {
i.previous();
qDebug() << i.key() << ": " << i.value();
}
-//! [37]
+//! [33multi]
+
+
+//! [34multi]
+QMutableMultiMapIterator<int, QWidget *> i(multimap);
+while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+}
+//! [34multi]
+
+
+//! [35multi]
+QMutableMultiMapIterator<QString, QString> i(multimap);
+while (i.hasNext()) {
+ i.next();
+ if (i.key() == i.value())
+ i.remove();
+}
+//! [35multi]
+
+
+//! [36]
+QHash<int, QWidget *> hash;
+...
+QMutableHashIterator<QString, QWidget *> i(hash);
+while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+}
+//! [36]
//! [38]
diff --git a/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp b/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp
index cc9f9f3929..1084585584 100644
--- a/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [1]
enum CustomEventPriority
diff --git a/src/corelib/doc/snippets/code/doc_src_qnamespace.qdoc b/src/corelib/doc/snippets/code/doc_src_qnamespace.qdoc
index 4d8932f837..6ce29308f1 100644
--- a/src/corelib/doc/snippets/code/doc_src_qnamespace.qdoc
+++ b/src/corelib/doc/snippets/code/doc_src_qnamespace.qdoc
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
//! [0]
QObject::connect: Cannot queue arguments of type 'MyType'
diff --git a/src/corelib/doc/snippets/code/doc_src_qplugin.cpp b/src/corelib/doc/snippets/code/doc_src_qplugin.cpp
index 744f425bbc..3bca27b966 100644
--- a/src/corelib/doc/snippets/code/doc_src_qplugin.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qplugin.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
namespace Foo
@@ -69,9 +22,3 @@ class MyInstance : public QObject
//! [2]
Q_IMPORT_PLUGIN(qjpeg)
//! [2]
-
-
-//! [3]
-TEMPLATE = app
-QTPLUGIN += qjpeg qgif # image formats
-//! [3]
diff --git a/src/corelib/doc/snippets/code/doc_src_qplugin.pro b/src/corelib/doc/snippets/code/doc_src_qplugin.pro
deleted file mode 100644
index 52fb9e3163..0000000000
--- a/src/corelib/doc/snippets/code/doc_src_qplugin.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-#! [3]
-TEMPLATE = app
-QTPLUGIN += qjpeg qgif # image formats
-#! [3]
diff --git a/src/corelib/doc/snippets/code/doc_src_qset.cpp b/src/corelib/doc/snippets/code/doc_src_qset.cpp
index 96ef07738b..98a6f336f5 100644
--- a/src/corelib/doc/snippets/code/doc_src_qset.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qset.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QSet<QString> set;
@@ -73,24 +26,23 @@ if (!set.contains("ninety-nine"))
//! [4]
QSetIterator<QWidget *> i(set);
-while (i.hasNext())
- qDebug() << i.next();
+while (i.hasNext()) {
+ QWidget *w = i.next();
+ qDebug() << w;
+}
//! [4]
//! [5]
-QSet<QWidget *>::const_iterator i = set.constBegin();
-while (i != set.constEnd()) {
+for (auto i = set.cbegin(), end = set.cend(); i != end; ++i)
qDebug() << *i;
- ++i;
-}
//! [5]
//! [6]
QSet<QString> set;
...
-foreach (const QString &value, set)
+for (const auto &value : set)
qDebug() << value;
//! [6]
@@ -104,20 +56,18 @@ for (int i = 0; i < 20000; ++i)
//! [8]
-QSet<QString> set;
-set << "January" << "February" << ... << "December";
+QSet<QString> set = {"January", "February", ... "December"}
-QSet<QString>::iterator i;
-for (i = set.begin(); i != set.end(); ++i)
+// i is a QSet<QString>::iterator
+for (auto i = set.begin(), end = set.end(); i != end; ++i)
qDebug() << *i;
//! [8]
//! [9]
-QSet<QString> set;
-set << "January" << "February" << ... << "December";
+QSet<QString> set = {"January", "February", ... "December"};
-QSet<QString>::iterator i = set.begin();
+auto i = set.begin();
while (i != set.end()) {
if ((*i).startsWith('J')) {
i = set.erase(i);
@@ -139,11 +89,10 @@ if (it != set.end())
//! [11]
-QSet<QString> set;
-set << "January" << "February" << ... << "December";
+QSet<QString> set = {"January", "February", ... "December"};
-QSet<QString>::const_iterator i;
-for (i = set.begin(); i != set.end(); ++i)
+// i is QSet<QString>::const_iterator
+for (auto i = set.cbegin(), end = set.cend(); i != end; ++i)
qDebug() << *i;
//! [11]
@@ -156,23 +105,3 @@ QSet<QString>::const_iterator it = std::find_if(set.cbegin(), set.cend(), predic
if (it != set.constEnd())
cout << "Found Jeanette" << endl;
//! [12]
-
-
-//! [13]
-QSet<QString> set;
-set << "red" << "green" << "blue" << ... << "black";
-
-QList<QString> list = set.toList();
-std::sort(list.begin(), list.end());
-//! [13]
-
-
-//! [14]
-QStringList list;
-list << "Julia" << "Mike" << "Mike" << "Julia" << "Julia";
-
-QSet<QString> set = QSet<QString>::fromList(list);
-set.contains("Julia"); // returns true
-set.contains("Mike"); // returns true
-set.size(); // returns 2
-//! [14]
diff --git a/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp b/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp
index 1cbbffc0e4..080874fc77 100644
--- a/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
int myfunc(int n)
diff --git a/src/corelib/doc/snippets/code/doc_src_resources.cpp b/src/corelib/doc/snippets/code/doc_src_resources.cpp
index b3c556d09a..04ecf810ec 100644
--- a/src/corelib/doc/snippets/code/doc_src_resources.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_resources.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [4]
QResource::registerResource("/path/to/myresource.rcc");
@@ -62,16 +15,3 @@ MyClass::MyClass() : BaseClass()
...
}
//! [5]
-
-
-//! [6]
-int main(int argc, char *argv[])
-{
- QApplication app(argc, argv);
- Q_INIT_RESOURCE(graphlib);
-
- QFile file(":/graph.png");
- ...
- return app.exec();
-}
-//! [6]
diff --git a/src/corelib/doc/snippets/code/doc_src_resources.qdoc b/src/corelib/doc/snippets/code/doc_src_resources.qdoc
index 9cea681a68..70c2a7b7ab 100644
--- a/src/corelib/doc/snippets/code/doc_src_resources.qdoc
+++ b/src/corelib/doc/snippets/code/doc_src_resources.qdoc
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
//! [0]
<file alias="cut-img.png">images/cut.png</file>
@@ -73,3 +26,7 @@
//! [3]
rcc -binary myresource.qrc -o myresource.rcc
//! [3]
+
+//! [4]
+<file empty="true">Button.qml</file>
+//! [4]
diff --git a/src/corelib/doc/snippets/code/qlogging/qlogging.cpp b/src/corelib/doc/snippets/code/qlogging/qlogging.cpp
index 8b7104cba5..e61eb70df3 100644
--- a/src/corelib/doc/snippets/code/qlogging/qlogging.cpp
+++ b/src/corelib/doc/snippets/code/qlogging/qlogging.cpp
@@ -1,61 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
#include <QtGui>
#include <QtDebug>
-#include <QDeclarativeComponent>
+#include <QQmlComponent>
//! [1]
- void statusChanged(QDeclarativeComponent::Status status) {
- if (status == QDeclarativeComponent::Error) {
- foreach (const QDeclarativeError &error, component->errors()) {
+ void statusChanged(QQmlComponent::Status status) {
+ if (status == QQmlComponent::Error) {
+ for (const QQmlError &error: std::as_const(component->errors())) {
const QByteArray file = error.url().toEncoded();
QMessageLogger(file.constData(), error.line(), 0).debug() << error.description();
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
index 472c5d41c4..6328cb0011 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QParallelAnimationGroup *group = new QParallelAnimationGroup;
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
index 7bd8121b90..4b77ab607d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
@@ -1,59 +1,95 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
- QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
- animation->setDuration(10000);
- animation->setStartValue(QRect(0, 0, 100, 30));
- animation->setEndValue(QRect(250, 250, 100, 30));
+#include <QApplication>
+#include <QPushButton>
+#include <QPropertyAnimation>
- animation->start();
+class MyButtonWidget : public QWidget
+{
+public:
+ MyButtonWidget(QWidget *parent = nullptr);
+};
+
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->start();
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MyButtonWidget buttonAnimWidget;
+ buttonAnimWidget.resize(QSize(800, 600));
+ buttonAnimWidget.show();
+ return a.exec();
+}
//! [0]
+
+
+//! [easing-curve]
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->setEasingCurve(QEasingCurve::OutBounce);
+ anim->start();
+}
+//! [easing-curve]
+
+
+//! [animation-group1]
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(100, 250));
+ anim2->setEndValue(QPoint(500, 500));
+
+ QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
+ parallelAnim->addAnimation(anim1);
+ parallelAnim->addAnimation(anim2);
+ parallelAnim->start();
+}
+//! [animation-group1]
+
+//! [animation-group2]
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(0, 0));
+ anim2->setEndValue(QPoint(200, 250));
+
+ QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
+ sequenceAnim->addAnimation(anim1);
+ sequenceAnim->addAnimation(anim2);
+ sequenceAnim->start();
+}
+//! [animation-group2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
index 0eff184926..a429fe20b2 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
index 0808dcc145..be7f549f65 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
diff --git a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
index 8490942048..4cba70e62d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
class HelloWorldTask : public QRunnable
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index a540b88247..25d3abf67e 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
label->setAlignment(Qt::AlignLeft | Qt::AlignTop);
@@ -79,17 +32,6 @@ Q_FLAG(Options)
typedef QFlags<Enum> Flags;
//! [2]
-
-//! [3]
-int myValue = 10;
-int minValue = 2;
-int maxValue = 6;
-
-int boundedValue = qBound(minValue, myValue, maxValue);
-// boundedValue == 6
-//! [3]
-
-
//! [4]
if (!driver()->isOpen() || driver()->isOpenError()) {
qWarning("QSqlQuery::exec: database not open");
@@ -108,11 +50,6 @@ quint64 value = Q_UINT64_C(932838457459459);
//! [6]
-//! [7]
-void myMsgHandler(QtMsgType, const char *);
-//! [7]
-
-
//! [8]
qint64 value = Q_INT64_C(932838457459459);
//! [8]
@@ -203,7 +140,7 @@ int boundedValue = qBound(minValue, myValue, maxValue);
//! [16]
-#if QT_VERSION >= 0x040100
+#if QT_VERSION >= QT_VERSION_CHECK(4, 1, 0)
QIcon icon = style()->standardIcon(QStyle::SP_TrashIcon);
#else
QPixmap pixmap = style()->standardPixmap(QStyle::SP_TrashIcon);
@@ -273,37 +210,26 @@ const TInputType &myMin(const TInputType &value1, const TInputType &value2)
//! [23]
-#include <qapplication.h>
+#include <QApplication>
#include <stdio.h>
#include <stdlib.h>
-void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+QtMessageHandler originalHandler = nullptr;
+
+void logToFile(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
- QByteArray localMsg = msg.toLocal8Bit();
- const char *file = context.file ? context.file : "";
- const char *function = context.function ? context.function : "";
- switch (type) {
- case QtDebugMsg:
- fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
- break;
- case QtInfoMsg:
- fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
- break;
- case QtWarningMsg:
- fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
- break;
- case QtCriticalMsg:
- fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
- break;
- case QtFatalMsg:
- fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
- break;
- }
+ QString message = qFormatLogMessage(type, context, msg);
+ static FILE *f = fopen("log.txt", "a");
+ fprintf(f, "%s\n", qPrintable(message));
+ fflush(f);
+
+ if (originalHandler)
+ *originalHandler(type, context, msg);
}
int main(int argc, char **argv)
{
- qInstallMessageHandler(myMessageOutput);
+ originalHandler = qInstallMessageHandler(logToFile);
QApplication app(argc, argv);
...
return app.exec();
@@ -339,8 +265,7 @@ void f(int c)
//! [27]
-qWarning() << "Brush:" << myQBrush << "Other value:"
-<< i;
+qWarning() << "Brush:" << myQBrush << "Other value:" << i;
//! [27]
@@ -355,8 +280,7 @@ void load(const QString &fileName)
//! [29]
-qCritical() << "Brush:" << myQBrush << "Other
-value:" << i;
+qCritical() << "Brush:" << myQBrush << "Other value:" << i;
//! [29]
@@ -514,16 +438,20 @@ void TheClass::addLabels()
}
//! [qttrid_noop]
+//! [qttrid_n_noop]
+static const char * const ids[] = {
+ //% "%n foo(s) found."
+ QT_TRID_N_NOOP("qtn_foo"),
+ //% "%n bar(s) found."
+ QT_TRID_N_NOOP("qtn_bar"),
+ 0
+};
-//! [37]
-qWarning("%s: %s", qUtf8Printable(key), qUtf8Printable(value));
-//! [37]
-
-
-//! [qUtf16Printable]
-qWarning("%ls: %ls", qUtf16Printable(key), qUtf16Printable(value));
-//! [qUtf16Printable]
-
+QString result(int type, int n)
+{
+ return qtTrId(ids[type], n);
+}
+//! [qttrid_n_noop]
//! [38]
struct Point2D
@@ -553,7 +481,7 @@ private:
int *data;
};
-Q_DECLARE_TYPEINFO(Point2D, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Point2D, Q_RELOCATABLE_TYPE);
//! [39]
@@ -624,11 +552,6 @@ qFuzzyCompare(0.0, 1.0e-200); // This will return false
qFuzzyCompare(1 + 0.0, 1 + 1.0e-200); // This will return true
//! [46]
-//! [47]
-CApaApplication *myApplicationFactory();
-//! [47]
-
-
//! [49]
void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);
//! [49]
@@ -656,11 +579,6 @@ template<> class QTypeInfo<A> : public QTypeInfoMerger<A, B, C, D> {};
... qOverload<int, const QString &>(&Foo::overloadedFunction)
//! [52]
-//! [53]
- ... QOverload<>::of(&Foo::overloadedFunction)
- ... QOverload<int, const QString &>::of(&Foo::overloadedFunction)
-//! [53]
-
//! [54]
struct Foo {
void overloadedFunction(int, const QString &);
@@ -720,7 +638,7 @@ bool readConfiguration(const QFile &file)
//! [qt-version-check]
#include <QtGlobal>
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#else
#include <QtGui>
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp
index 7589050bc2..d04e243b71 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp
index d281089041..d88675d8f1 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
if (qFloatDistance(a, b) < (1 << 7)) { // The last 7 bits are not
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp
index c712dfa432..d86d40bc98 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp
index 9f2884667c..8be3f91120 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp
@@ -1,53 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
quint32 value = QRandomGenerator::global()->generate();
@@ -127,5 +80,5 @@
//! [15]
//! [16]
- qint64 value = QRandomGenerator64::generate() & std::numeric_limits<qint64>::max();
+ qint64 value = QRandomGenerator64::global()->generate() & std::numeric_limits<qint64>::max();
//! [16]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp
index ae2f305313..4300fc2da9 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp
@@ -1,64 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+using namespace Qt::StringLiterals;
//! [0]
class ZipEngineHandler : public QAbstractFileEngineHandler
{
public:
- QAbstractFileEngine *create(const QString &fileName) const override;
+ std::unique_ptr<QAbstractFileEngine> create(const QString &fileName) const override;
};
-QAbstractFileEngine *ZipEngineHandler::create(const QString &fileName) const
+std::unique_ptr<QAbstractFileEngine> ZipEngineHandler::create(const QString &fileName) const
{
// ZipEngineHandler returns a ZipEngine for all .zip files
- return fileName.toLower().endsWith(".zip") ? new ZipEngine(fileName) : 0;
+ if (fileName.toLower().endsWith(".zip"_L1))
+ return std::make_unique<ZipEngine>(fileName);
+ return {};
}
int main(int argc, char **argv)
@@ -74,21 +31,24 @@ int main(int argc, char **argv)
}
//! [0]
-
//! [1]
-QAbstractSocketEngine *ZipEngineHandler::create(const QString &fileName) const
+std::unique_ptr<QAbstractFileEngine> ZipEngineHandler::create(const QString &fileName) const
{
// ZipEngineHandler returns a ZipEngine for all .zip files
- return fileName.toLower().endsWith(".zip") ? new ZipEngine(fileName) : 0;
+ if (fileName.toLower().endsWith(".zip"_L1))
+ return std::make_unique<ZipEngine>(fileName);
+ else
+ return {};
}
//! [1]
//! [2]
-QAbstractFileEngineIterator *
-CustomFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
+QAbstractFileEngine::IteratorUniquePtr
+CustomFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames)
{
- return new CustomFileEngineIterator(filters, filterNames);
+ return std::make_unique<CustomFileEngineIterator>(path, filters, filterNames);
}
//! [2]
@@ -97,25 +57,23 @@ CustomFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filte
class CustomIterator : public QAbstractFileEngineIterator
{
public:
- CustomIterator(const QStringList &nameFilters, QDir::Filters filters)
- : QAbstractFileEngineIterator(nameFilters, filters), index(0)
+ CustomIterator(const QString &path, const QStringList &nameFilters, QDir::Filters filters)
+ : QAbstractFileEngineIterator(path, nameFilters, filters), index(0)
{
// In a real iterator, these entries are fetched from the
// file system based on the value of path().
entries << "entry1" << "entry2" << "entry3";
}
- bool hasNext() const override
- {
- return index < entries.size() - 1;
- }
-
- QString next() override
+ bool advance() override
{
- if (!hasNext())
- return QString();
- ++index;
- return currentFilePath();
+ if (entries.isEmpty())
+ return false;
+ if (index < entries.size() - 1) {
+ ++index;
+ return true;
+ }
+ return false;
}
QString currentFileName() override
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdatastream.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdatastream.cpp
index efc06d8c62..3075913a95 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qdatastream.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdatastream.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void wrapInFunction()
{
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp
index 5154dc5d68..5411ab34f6 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QString s;
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdir.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdir.cpp
index 4e5e25a64a..400b3225d0 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qdir.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdir.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void wrapInFunction()
@@ -54,7 +7,7 @@ void wrapInFunction()
//! [0]
QDir("/home/user/Documents")
-QDir("C:/Documents and Settings")
+QDir("C:/Users")
//! [0]
@@ -154,7 +107,7 @@ if (d1 != d2)
//! [12]
-C:/Documents and Settings/Username
+C:/Users/Username
//! [12]
@@ -182,4 +135,17 @@ namespace MyNamespace
Q_CLEANUP_RESOURCE(myapp);
//! [15]
+//! [16]
+QString absolute = "/local/bin";
+QString relative = "local/bin";
+QFileInfo absFile(absolute);
+QFileInfo relFile(relative);
+
+QDir::setCurrent(QDir::rootPath());
+// absFile and relFile now point to the same file
+
+QDir::setCurrent("/tmp");
+// absFile now points to "/local/bin",
+// while relFile points to "/tmp/local/bin"
+//! [16]
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdiriterator.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdiriterator.cpp
index 31442a5516..ec3f3adc50 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qdiriterator.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdiriterator.cpp
@@ -1,58 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QDirIterator it("/etc", QDirIterator::Subdirectories);
while (it.hasNext()) {
- qDebug() << it.next();
-
+ QString dir = it.next();
+ qDebug() << dir;
// /etc/.
// /etc/..
// /etc/X11
@@ -69,3 +22,7 @@ while (it.hasNext()) {
qDebug() << f.fileName() << f.readAll().trimmed().toDouble() / 1000 << "MHz";
}
//! [1]
+
+//! [2]
+QDirIterator audioFileIt(audioPath, {"*.mp3", "*.wav"}, QDir::Files);
+//! [2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp
new file mode 100644
index 0000000000..231bf48d26
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp
@@ -0,0 +1,70 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QDirListing>
+
+using namespace Qt::StringLiterals;
+
+[[maybe_unused]] static void func() {
+{
+//! [0]
+using ItFlag = QDirListing::IteratorFlag;
+for (const auto &dirEntry : QDirListing(u"/etc"_s, ItFlag::Recursive)) {
+ qDebug() << dirEntry.filePath();
+ // /etc/.
+ // /etc/..
+ // /etc/X11
+ // /etc/X11/fs
+ // ...
+}
+//! [0]
+}
+
+{
+//! [1]
+using ItFlag = QDirListing::IteratorFlag;
+QDirListing dirList(u"/sys"_s, QStringList{u"scaling_cur_freq"_s},
+ QDir::NoFilter, ItFlag::Recursive);
+for (const auto &dirEntry : dirList) {
+ QFile f(dirEntry.filePath());
+ f.open(QIODevice::ReadOnly);
+ qDebug() << f.fileName() << f.readAll().trimmed().toDouble() / 1000 << "MHz";
+}
+//! [1]
+}
+
+{
+//! [2]
+QDirListing audioFileIt(u"/home/johndoe/"_s, {"*.mp3", "*.wav"}, QDir::Files);
+//! [2]
+}
+
+{
+//! [3]
+using ItFlag = QDirListing::IteratorFlag;
+for (const auto &dirEntry : QDirListing(u"/etc"_s, ItFlag::Recursive)) {
+ // Faster
+ if (dirEntry.fileName().endsWith(u".conf")) { /* ... */ }
+
+ // This works, but might be potentially slower, since it has to construct a
+ // QFileInfo, whereas (depending on the implemnetation) the fileName could
+ // be known already
+ if (dirEntry.fileInfo().fileName().endsWith(u".conf")) { /* ... */ }
+}
+//! [3]
+}
+
+{
+//! [4]
+using ItFlag = QDirListing::IteratorFlag;
+for (const auto &dirEntry : QDirListing(u"/etc"_s, ItFlag::Recursive)) {
+ // Both approaches are the same, because DirEntry will have to construct
+ // a QFileInfo to get this info (for example, by calling system stat())
+
+ if (dirEntry.size() >= 4'000 /* 4KB */) { /* ...*/ }
+ if (dirEntry.fileInfo().size() >= 4'000 /* 4KB */) { /* ... */ }
+}
+//! [4]
+}
+
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qfile.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qfile.cpp
index 4123fe4996..3a8f7d2747 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qfile.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qfile.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QFile file;
@@ -57,16 +10,6 @@ file.open(QIODevice::ReadOnly); // opens "/home/readme.txt" under Unix
//! [0]
-//! [1]
-QByteArray myEncoderFunc(const QString &fileName);
-//! [1]
-
-
-//! [2]
-QString myDecoderFunc(const QByteArray &localFileName);
-//! [2]
-
-
//! [3]
#include <stdio.h>
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qfileinfo.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qfileinfo.cpp
index 036625370e..a8dd621111 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qfileinfo.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qfileinfo.cpp
@@ -1,58 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QDir>
+#include <QFileInfo>
+using namespace Qt::StringLiterals;
+
+[[maybe_unused]] static void func()
+{
+{
//![newstuff]
- QFileInfo fi("c:/temp/foo"); => fi.absoluteFilePath() => "C:/temp/foo"
+ QFileInfo fi("c:/temp/foo");
+ qDebug() << fi.absoluteFilePath(); // "C:/temp/foo"
//![newstuff]
+}
+{
//! [0]
#ifdef Q_OS_UNIX
@@ -69,15 +32,15 @@ info2.size(); // returns 56201
#endif
//! [0]
-
+}
//! [1]
#ifdef Q_OS_WIN
-QFileInfo info1("C:\\Documents and Settings\\Bob\\untabify.lnk");
+QFileInfo info1("C:\\Users\\Bob\\untabify.lnk");
info1.isSymLink(); // returns true
-info1.absoluteFilePath(); // returns "C:/Documents and Settings/Bob/untabify.lnk"
-info1.size(); // returns 743
+info1.absoluteFilePath(); // returns "C:/Users/Bob/untabify.lnk"
+info1.size(); // returns 63942
info1.symLinkTarget(); // returns "C:/Pretty++/untabify"
QFileInfo info2(info1.symLinkTarget());
@@ -88,65 +51,72 @@ info2.size(); // returns 63942
#endif
//! [1]
-
+{
//! [2]
-QString absolute = "/local/bin";
-QString relative = "local/bin";
-QFileInfo absFile(absolute);
-QFileInfo relFile(relative);
+QFileInfo info("/usr/bin/env");
-QDir::setCurrent(QDir::rootPath());
-// absFile and relFile now point to the same file
+QString path = info.absolutePath(); // path = /usr/bin
+QString base = info.baseName(); // base = env
-QDir::setCurrent("/tmp");
-// absFile now points to "/local/bin",
-// while relFile points to "/tmp/local/bin"
-//! [2]
+info.setFile("/etc/hosts");
+path = info.absolutePath(); // path = /etc
+base = info.baseName(); // base = hosts
+//! [2]
+}
+{
//! [3]
QFileInfo fi("/tmp/archive.tar.gz");
QString name = fi.fileName(); // name = "archive.tar.gz"
//! [3]
+}
-
+{
//! [4]
QFileInfo fi("/Applications/Safari.app");
QString bundle = fi.bundleName(); // name = "Safari"
//! [4]
+}
-
+{
//! [5]
QFileInfo fi("/tmp/archive.tar.gz");
QString base = fi.baseName(); // base = "archive"
//! [5]
+}
-
+{
//! [6]
QFileInfo fi("/tmp/archive.tar.gz");
QString base = fi.completeBaseName(); // base = "archive.tar"
//! [6]
+}
-
+{
//! [7]
QFileInfo fi("/tmp/archive.tar.gz");
QString ext = fi.completeSuffix(); // ext = "tar.gz"
//! [7]
+}
-
+{
//! [8]
QFileInfo fi("/tmp/archive.tar.gz");
QString ext = fi.suffix(); // ext = "gz"
//! [8]
+}
-
+{
+QString fileName = "foo";
//! [9]
QFileInfo info(fileName);
if (info.isSymLink())
fileName = info.symLinkTarget();
//! [9]
+}
-
+{
//! [10]
QFileInfo fi("/tmp/archive.tar.gz");
if (fi.permission(QFile::WriteUser | QFile::ReadGroup))
@@ -154,3 +124,24 @@ if (fi.permission(QFile::WriteUser | QFile::ReadGroup))
if (fi.permission(QFile::WriteGroup | QFile::WriteOther))
qWarning("The group or others can change the file");
//! [10]
+}
+
+{
+//! [11]
+// Given a current working directory of "/home/user/Documents/memos/"
+QFileInfo info1(u"relativeFile"_s);
+qDebug() << info1.absolutePath(); // "/home/user/Documents/memos/"
+qDebug() << info1.baseName(); // "relativeFile"
+qDebug() << info1.absoluteDir(); // QDir(u"/home/user/Documents/memos"_s)
+qDebug() << info1.absoluteDir().path(); // "/home/user/Documents/memos"
+
+// A QFileInfo on a dir
+QFileInfo info2(u"/home/user/Documents/memos"_s);
+qDebug() << info2.absolutePath(); // "/home/user/Documents"
+qDebug() << info2.baseName(); // "memos"
+qDebug() << info2.absoluteDir(); // QDir(u"/home/user/Documents"_s)
+qDebug() << info2.absoluteDir().path(); // "/home/user/Documents"
+//! [11]
+}
+
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp
index 0d1aa691cf..facf037f46 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QString defaultsBasePath = "data/";
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qiodevice.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qiodevice.cpp
index 981f6b3f12..dc58d722c3 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qiodevice.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qiodevice.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QProcess gzip;
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp
index cab48f1e27..0a7a718e31 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
<category>[.<type>] = true|false
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp
index 8a2825cd10..765c1e41cf 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void wrapInFunction()
@@ -90,34 +43,28 @@ process2.start("command2");
//! [4]
-class SandboxProcess : public QProcess
+void runSandboxed(const QString &name, const QStringList &arguments)
{
- ...
- protected:
- void setupChildProcess() override;
- ...
-};
-
-void SandboxProcess::setupChildProcess()
-{
- // Drop all privileges in the child process, and enter
- // a chroot jail.
-#if defined Q_OS_UNIX
- ::setgroups(0, 0);
- ::chroot("/etc/safe");
- ::chdir("/");
- ::setgid(safeGid);
- ::setuid(safeUid);
- ::umask(0);
-#endif
+ QProcess proc;
+ proc.setChildProcessModifier([] {
+ // Drop all privileges in the child process, and enter
+ // a chroot jail.
+ ::setgroups(0, nullptr);
+ ::chroot("/run/safedir");
+ ::chdir("/");
+ ::setgid(safeGid);
+ ::setuid(safeUid);
+ ::umask(077);
+ });
+ proc.start(name, arguments);
+ proc.waitForFinished();
}
-
//! [4]
//! [5]
QProcess process;
-process.start("del /s *.txt");
+process.startCommand("del /s *.txt");
// same as process.start("del", QStringList() << "/s" << "*.txt");
...
//! [5]
@@ -125,13 +72,13 @@ process.start("del /s *.txt");
//! [6]
QProcess process;
-process.start("dir \"My Documents\"");
+process.startCommand("dir \"My Documents\"");
//! [6]
//! [7]
QProcess process;
-process.start("dir \"Epic 12\"\"\" Singles\"");
+process.startCommand("dir \"Epic 12\"\"\" Singles\"");
//! [7]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qsettings.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qsettings.cpp
index 08ab1fb338..5774add2a7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qsettings.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qsettings.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QSettings settings("MySoft", "Star Runner");
@@ -92,7 +45,7 @@ settings.value("HKEY_CURRENT_USER\\MySoft\\Star Runner\\Galaxy\\Default"); // re
//! [7]
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
QSettings settings("grenoullelogique.fr", "Squash");
#else
QSettings settings("Grenoulle Logique", "Squash");
@@ -185,10 +138,10 @@ QList<Login> logins;
QSettings settings;
settings.beginWriteArray("logins");
-for (int i = 0; i < logins.size(); ++i) {
+for (qsizetype i = 0; i < logins.size(); ++i) {
settings.setArrayIndex(i);
- settings.setValue("userName", list.at(i).userName);
- settings.setValue("password", list.at(i).password);
+ settings.setValue("userName", logins.at(i).userName);
+ settings.setValue("password", logins.at(i).password);
}
settings.endArray();
//! [16]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qstorageinfo.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qstorageinfo.cpp
index c7a1b34f7a..93029274b1 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qstorageinfo.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qstorageinfo.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Ivan Komissarov
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
//! [0]
QStorageInfo storage(qApp->applicationDirPath());
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtemporarydir.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtemporarydir.cpp
index 0fab8566e5..037cf8a36d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qtemporarydir.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qtemporarydir.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
{
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp
index 4e864b3dcd..76adfd3128 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
{
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp
index 4795650748..75a04e654f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QFile data("output.txt");
@@ -131,9 +84,3 @@ out << "Qt rocks!" << Qt::endl;
//! [9]
stream << '\n' << Qt::flush;
//! [9]
-
-
-//! [10]
-QTextStream out(&file);
-out.setEncoding(QStringConverter::Utf8);
-//! [10]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
index e3c3005c33..945f3ae3e7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
@@ -1,52 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [constructor-url-reference]
+QUrl url("example.com");
+//! [constructor-url-reference]
+
+//! [constructor-url]
+QUrl url("https://example.com");
+//! [constructor-url]
//! [0]
QUrl url("http://www.example.com/List of holidays.xml");
@@ -78,7 +39,7 @@ sock.connectToHost(url.host(), url.port(80));
//! [4]
-http://www.example.com/cgi-bin/drawgraph.cgi?type(pie)color(green)
+http://www.example.com/cgi-bin/drawgraph.cgi?type,pie;color,green
//! [4]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp
index 22f1d3260f..c2085fddc3 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
index 2e055ec439..4fd7f97ae8 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
beginInsertRows(parent, 2, 4);
@@ -97,16 +50,6 @@ beginMoveRows(parent, 2, 2, parent, 0);
beginMoveRows(parent, 2, 2, parent, 4);
//! [9]
-//! [10]
-myData.clear();
-reset();
-//! [10]
-
-//! [11]
-beginResetModel();
-myData.clear();
-endResetModel();
-//! [11]
//! [12]
class CustomDataProxy : public QSortFilterProxyModel
@@ -141,3 +84,48 @@ private:
};
//! [12]
+//! [13]
+QVariant text = model->data(index, Qt::DisplayRole);
+QVariant decoration = model->data(index, Qt::DecorationRole);
+QVariant checkState = model->data(index, Qt::CheckStateRole);
+// etc.
+//! [13]
+
+//! [14]
+std::array<QModelRoleData, 3> roleData = { {
+ QModelRoleData(Qt::DisplayRole),
+ QModelRoleData(Qt::DecorationRole),
+ QModelRoleData(Qt::CheckStateRole)
+} };
+
+// Usually, this is not necessary: A QModelRoleDataSpan
+// will be built automatically for you when passing an array-like
+// container to multiData().
+QModelRoleDataSpan span(roleData);
+
+model->multiData(index, span);
+
+// Use roleData[0].data(), roleData[1].data(), etc.
+//! [14]
+
+//! [15]
+void MyModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
+{
+ for (QModelRoleData &roleData : roleDataSpan) {
+ int role = roleData.role();
+
+ // ... obtain the data for index and role ...
+
+ roleData.setData(result);
+ }
+}
+//! [15]
+
+//! [16]
+QVariant MyModel::data(const QModelIndex &index, int role) const
+{
+ QModelRoleData roleData(role);
+ multiData(index, roleData);
+ return roleData.data();
+}
+//! [16]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp
index b84cf0ae2d..62844e08cb 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp
@@ -1,58 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
class MyXcbEventFilter : public QAbstractNativeEventFilter
{
public:
- bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
+ bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
{
if (eventType == "xcb_generic_event_t") {
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h
index bb44782ac5..905a79b105 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include <QAbstractNativeEventFilter>
@@ -54,6 +7,6 @@
class MyCocoaEventFilter : public QAbstractNativeEventFilter
{
public:
- bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override;
+ bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override;
};
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm
index 7c40330de0..fb6d602eaf 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm
@@ -1,59 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include "mycocoaeventfilter.h"
#import <AppKit/AppKit.h>
-bool CocoaNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *)
+bool MyCocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *)
{
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = static_cast<NSEvent *>(message);
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter_win.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter_win.cpp
new file mode 100644
index 0000000000..de03f7b6d4
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter_win.cpp
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 Laszlo Papp <lpapp@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+class MyMSGEventFilter : public QAbstractNativeEventFilter
+{
+public:
+ bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
+ {
+ if (eventType == "windows_generic_MSG") {
+ MSG *msg = static_cast<MSG *>(message);
+ // ...
+ } else if (eventType == "windows_dispatcher_MSG") {
+ MSG *msg = static_cast<MSG *>(message);
+ // ...
+ }
+ return false;
+ }
+};
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qcoreapplication.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qcoreapplication.cpp
index 36b47e6f6e..8087ff8f8b 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qcoreapplication.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qcoreapplication.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
//! [0]
QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
@@ -60,12 +15,6 @@ connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::Qu
//! [1]
-//! [2]
-foreach (const QString &path, app.libraryPaths())
- do_something(path);
-//! [2]
-
-
//! [3]
// Called once QCoreApplication exists
static void preRoutineMyDebugTool()
@@ -126,8 +75,6 @@ private:
//! [6]
static inline QString tr(const char *sourceText,
const char *comment = nullptr);
-static inline QString trUtf8(const char *sourceText,
- const char *comment = nullptr);
//! [6]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp
index 35c06f842e..f7440f2bb0 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp
@@ -1,59 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
void executeOperation(int msecs)
{
QDeadlineTimer deadline(msecs);
do {
- if (readFromDevice(deadline.remainingTime())
+ if (readFromDevice(deadline.remainingTime()))
break;
waitForReadyRead(deadline);
} while (!deadline.hasExpired());
@@ -110,25 +63,25 @@
//! [7]
//! [8]
- return d1.deadlineNSecs() == d2.deadlineNSecs();
+ return lhs.deadlineNSecs() == rhs.deadlineNSecs();
//! [8]
//! [9]
- return d1.deadlineNSecs() != d2.deadlineNSecs();
+ return lhs.deadlineNSecs() != rhs.deadlineNSecs();
//! [9]
//! [10]
- return d1.deadlineNSecs() < d2.deadlineNSecs();
+ return lhs.deadlineNSecs() < rhs.deadlineNSecs();
//! [10]
//! [11]
- return d1.deadlineNSecs() <= d2.deadlineNSecs();
+ return lhs.deadlineNSecs() <= rhs.deadlineNSecs();
//! [11]
//! [12]
- return d1.deadlineNSecs() > d2.deadlineNSecs();
+ return lhs.deadlineNSecs() > rhs.deadlineNSecs();
//! [12]
//! [13]
- return d1.deadlineNSecs() >= d2.deadlineNSecs();
+ return lhs.deadlineNSecs() >= rhs.deadlineNSecs();
//! [13]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmath.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmath.cpp
index 329f7a494a..7d1d3bd98d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmath.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmath.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Laszlo Papp <lpapp@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Laszlo Papp <lpapp@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
float degrees = 180.0f
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp
index 56d1fa5a63..ec4646c520 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void wrapInFunction()
@@ -81,6 +34,21 @@ QMetaObject::invokeMethod(thread, "quit",
QMetaObject::invokeMethod: Unable to handle unregistered datatype 'MyType'
//! [3]
+//! [invokemethod-no-macro]
+QString retVal;
+QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
+ qReturnArg(retVal),
+ QString("sqrt"), 42, 9.7);
+//! [invokemethod-no-macro]
+
+
+//! [invokemethod-no-macro-other-types]
+QString retVal;
+QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
+ qReturnArg(retVal),
+ QStringView("sqrt"), qsizetype(42), 9.7f);
+//! [invokemethod-no-macro-other-types]
+
//! [4]
QString retVal;
@@ -130,6 +98,24 @@ method.invoke(pushButton, Qt::QueuedConnection);
QMetaMethod::invoke: Unable to handle unregistered datatype 'MyType'
//! [7]
+//! [invoke-no-macro]
+QString retVal;
+QByteArray normalizedSignature = QMetaObject::normalizedSignature("compute(QString, int, double)");
+int methodIndex = obj->metaObject()->indexOfMethod(normalizedSignature);
+QMetaMethod method = obj->metaObject()->method(methodIndex);
+method.invoke(obj, Qt::DirectConnection, qReturnArg(retVal),
+ QString("sqrt"), 42, 9.7);
+//! [invoke-no-macro]
+
+//! [invoke-no-macro-other-types]
+QString retVal;
+QByteArray normalizedSignature = QMetaObject::normalizedSignature("compute(QByteArray, qint64, long double)");
+int methodIndex = obj->metaObject()->indexOfMethod(normalizedSignature);
+QMetaMethod method = obj->metaObject()->method(methodIndex);
+method.invoke(obj, Qt::DirectConnection, qReturnArg(retVal),
+ QByteArray("sqrt"), qint64(42), 9.7L);
+//! [invoke-no-macro-other-types]
+
//! [8]
QString retVal;
QByteArray normalizedSignature = QMetaObject::normalizedSignature("compute(QString, int, double)");
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
index d28a0ac956..757700786e 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
struct MyStruct
@@ -82,12 +35,12 @@ MyStruct s2 = var.value<MyStruct>();
//! [3]
-int id = QMetaType::type("MyClass");
-if (id != QMetaType::UnknownType) {
- void *myClassPtr = QMetaType::create(id);
+QMetaType type = QMetaType::fromName("MyClass");
+if (type.isValid()) {
+ void *myClassPtr = type.create();
...
- QMetaType::destroy(id, myClassPtr);
- myClassPtr = 0;
+ type.destroy(myClassPtr);
+ myClassPtr = nullptr;
}
//! [3]
@@ -97,11 +50,6 @@ qRegisterMetaType<MyClass>("MyClass");
//! [4]
-//! [5]
-qRegisterMetaTypeStreamOperators<MyClass>("MyClass");
-//! [5]
-
-
//! [6]
QDataStream &operator<<(QDataStream &out, const MyClass &myObj);
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
@@ -153,16 +101,6 @@ void someFunc()
//! [11]
-//! [12]
-QPointer<QFile> fp(new QFile);
-QVariant var = QVariant::fromValue(fp);
-// ...
-if (var.canConvert<QObject*>()) {
- QObject *sp = var.value<QObject*>();
- qDebug() << sp->metaObject()->className(); // Prints 'QFile'.
-}
-//! [12]
-
//! [13]
#include <memory>
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp
index a87c67dfed..c6a48c8827 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
//! [0]
void MyWidget::dragEnterEvent(QDragEnterEvent *event)
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
index fddda64b19..e3bbac7a3c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [1]
QObject *obj = new QPushButton;
@@ -176,13 +129,6 @@ void MyObject::timerEvent(QTimerEvent *event)
//! [8]
-//! [9]
-QList<QObject *> list = window()->queryList("QAbstractButton"));
-foreach (QObject *obj, list)
- static_cast<QAbstractButton *>(obj)->setEnabled(false);
-//! [9]
-
-
//! [10]
QPushButton *button = parentWidget->findChild<QPushButton *>("button1");
//! [10]
@@ -251,22 +197,6 @@ MyWindow::MyWindow()
}
-//! [18]
-int n = messages.count();
-showMessage(tr("%n message(s) saved", "", n));
-//! [18]
-
-
-//! [19]
-n == 1 ? tr("%n message saved") : tr("%n messages saved")
-//! [19]
-
-
-//! [20]
-label->setText(tr("F\374r \310lise"));
-//! [20]
-
-
//! [21]
if (receivers(SIGNAL(valueChanged(QByteArray))) > 0) {
QByteArray data;
@@ -430,26 +360,18 @@ public:
//! [39]
-//! [40]
-//: This name refers to a host name.
-hostNameLabel->setText(tr("Name:"));
-
-/*: This text refers to a C++ code example. */
-QString example = tr("Example");
-//! [40]
-
//! [41]
QPushButton *button = parentWidget->findChild<QPushButton *>("button1", Qt::FindDirectChildrenOnly);
//! [41]
//! [42]
-QListWidget *list = parentWidget->findChild<QListWidget *>(QString(), Qt::FindDirectChildrenOnly);
+QListWidget *list = parentWidget->findChild<QListWidget *>(Qt::FindDirectChildrenOnly);
//! [42]
//! [43]
-QList<QPushButton *> childButtons = parentWidget.findChildren<QPushButton *>(QString(), Qt::FindDirectChildrenOnly);
+QList<QPushButton *> childButtons = parentWidget.findChildren<QPushButton *>(Qt::FindDirectChildrenOnly);
//! [43]
//! [44]
@@ -534,18 +456,6 @@ public:
};
//! [52]
-//! [meta data]
-//: This is a comment for the translator.
-//= qtn_foo_bar
-//~ loc-layout_id foo_dialog
-//~ loc-blank False
-//~ magic-stuff This might mean something magic.
-QString text = MyMagicClass::tr("Sim sala bim.");
-//! [meta data]
-
-//! [explicit tr context]
-QString text = QScrollBar::tr("Page up");
-//! [explicit tr context]
//! [53]
{
@@ -559,3 +469,16 @@ const bool wasBlocked = someQObject->blockSignals(true);
// no signals here
someQObject->blockSignals(wasBlocked);
//! [54]
+
+{
+//! [invalid-timer-id]
+ QObject *obj;
+ ...
+ int id = obj->startTimer(100ms);
+ if (id > Qt::TimerId::Invalid)
+ // The timer has been started successfully
+
+ if (id > 0) // Equivalent, albeit less readable
+ // The timer has been started successfully
+//! [invalid-timer-id]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qproperty.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qproperty.cpp
new file mode 100644
index 0000000000..c2b55c9684
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qproperty.cpp
@@ -0,0 +1,152 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QObject>
+#include <QDebug>
+
+//! [0]
+class MyClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged BINDABLE bindableX)
+public:
+ int x() const { return xProp; }
+ void setX(int x) { xProp = x; }
+ QBindable<int> bindableX() { return QBindable<int>(&xProp); }
+
+signals:
+ void xChanged();
+
+private:
+ // Declare the instance of the bindable property data.
+ Q_OBJECT_BINDABLE_PROPERTY(MyClass, int, xProp, &MyClass::xChanged)
+};
+//! [0]
+
+//! [1]
+class MyClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged BINDABLE bindableX)
+public:
+ int x() const { return xProp; }
+ void setX(int x) { xProp = x; }
+ QBindable<int> bindableX() { return QBindable<int>(&xProp); }
+
+signals:
+ void xChanged();
+
+private:
+ // Declare the instance of int bindable property data and
+ // initialize it with the value 5.
+ // This is similar to declaring
+ // int xProp = 5;
+ // without using the new QObjectBindableProperty class.
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(MyClass, int, xProp, 5, &MyClass::xChanged)
+};
+//! [1]
+
+//! [2]
+class CustomType
+{
+public:
+ CustomType(int val, int otherVal) : value(val), anotherValue(otherVal) { }
+
+private:
+ int value = 0;
+ int anotherValue = 0;
+};
+
+// later when using CustomType as a property
+Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(MyClass, CustomType xProp, CustomType(5, 10),
+ &MyClass::xChanged)
+//! [2]
+
+void usage_QBindable() {
+ //! [3]
+ MyClass *myObject;
+ QBindable<int> bindableX = myObject->bindableX();
+ qDebug() << bindableX.hasBinding(); // prints false
+ QProperty<int> y {42};
+ bindableX.setBinding([&](){ return 2*y.value(); });
+ qDebug() << bindableX.hasBinding() << myObject->x(); // prints true 84
+ //! [3]
+}
+
+//! [4]
+#include <QObject>
+#include <QProperty>
+#include <QDebug>
+
+class Foo : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int myVal READ myVal WRITE setMyVal BINDABLE bindableMyVal)
+public:
+ int myVal() { return myValMember.value(); }
+ void setMyVal(int newvalue) { myValMember = newvalue; }
+ QBindable<int> bindableMyVal() { return &myValMember; }
+signals:
+ void myValChanged();
+
+private:
+ Q_OBJECT_BINDABLE_PROPERTY(Foo, int, myValMember, &Foo::myValChanged);
+};
+
+int main()
+{
+ bool debugout(true); // enable debug log
+ Foo myfoo;
+ QProperty<int> prop(42);
+ QObject::connect(&myfoo, &Foo::myValChanged, [&]() {
+ if (debugout)
+ qDebug() << myfoo.myVal();
+ });
+ myfoo.bindableMyVal().setBinding([&]() { return prop.value(); }); // prints "42"
+
+ prop = 5; // prints "5"
+ debugout = false;
+ prop = 6; // prints nothing
+ debugout = true;
+ prop = 7; // prints "7"
+}
+
+#include "main.moc"
+//! [4]
+
+//! [5]
+class Client{};
+
+class MyClassPrivate : public QObjectPrivate
+{
+public:
+ QList<Client> clients;
+ bool hasClientsActualCalculation() const { return clients.size() > 0; }
+ Q_OBJECT_COMPUTED_PROPERTY(MyClassPrivate, bool, hasClientsData,
+ &MyClassPrivate::hasClientsActualCalculation)
+};
+
+class MyClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool hasClients READ hasClients STORED false BINDABLE bindableHasClients)
+public:
+ QBindable<bool> bindableHasClients()
+ {
+ return QBindable<bool>(&d_func()->hasClientsData);
+ }
+ bool hasClients() const
+ {
+ return d_func()->hasClientsData.value();
+ }
+ void addClient(const Client &c)
+ {
+ Q_D(MyClass);
+ d->clients.push_back(c);
+ // notify that the value could have changed
+ d->hasClientsData.notify();
+ }
+private:
+ Q_DECLARE_PRIVATE(MyClass)
+};
+//! [5]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp
index 345a59b7ec..45da88c75d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp
@@ -1,55 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
-QSystemSemaphore sem("market", 3, QSystemSemaphore::Create);
+QSystemSemaphore sem(QSystemSemaphore::platformSafeKey("market"), 3, QSystemSemaphore::Create);
// resources available == 3
sem.acquire(); // resources available == 2
sem.acquire(); // resources available == 1
@@ -60,7 +13,7 @@ sem.release(2); // resources available == 3
//! [1]
-QSystemSemaphore sem("market", 5, QSystemSemaphore::Create);
+QSystemSemaphore sem(QSystemSemaphore::platformSafeKey("market"), 5, QSystemSemaphore::Create);
for (int i = 0; i < 5; ++i) // acquire all 5 resources
sem.acquire();
sem.release(5); // release the 5 resources
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qtimer.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qtimer.cpp
index 548e32dc5d..5edcaae755 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qtimer.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qtimer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include <QApplication>
@@ -55,7 +8,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QTimer::singleShot(600000, &app, SLOT(quit()));
+ QTimer::singleShot(600000, &app, QCoreApplication::quit);
...
return app.exec();
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
index ca1ea21b02..7f3f1ce7a0 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
@@ -1,59 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
//! [0]
QDataStream out(...);
QVariant v(123); // The variant now contains an int
int x = v.toInt(); // x = 123
out << v; // Writes a type tag and an int to out
-v = QVariant("hello"); // The variant now contains a QByteArray
v = QVariant(tr("hello")); // The variant now contains a QString
int y = v.toInt(); // y = 0 since v cannot be converted to an int
QString s = v.toString(); // s = tr("hello") (see QObject::tr())
@@ -64,16 +18,13 @@ in >> v; // Reads an Int variant
int z = v.toInt(); // z = 123
qDebug("Type is %s", // prints "Type is int"
v.typeName());
-v = v.toInt() + 100; // The variant now hold the value 223
-v = QVariant(QStringList());
+v = v.toInt() + 100; // The variant now holds the value 223
+v = QVariant(QStringList()); // The variant now holds a QStringList
//! [0]
-
//! [1]
-QVariant x, y(QString()), z(QString(""));
-x.convert(QVariant::Int);
-// x.isNull() == true
-// y.isNull() == true, z.isNull() == false
+QVariant x; // x.isNull() == true
+QVariant y = QVariant::fromValue(nullptr); // y.isNull() == true
//! [1]
@@ -95,7 +46,7 @@ QVariant v;
v.setValue(5);
int i = v.toInt(); // i is now 5
-QString s = v.toString() // s is now "5"
+QString s = v.toString(); // s is now "5"
MyCustomStruct c;
v.setValue(c);
@@ -140,11 +91,6 @@ return QVariant::fromValue(s);
//! [7]
-//! [8]
-QObject *object = getObjectFromSomewhere();
-QVariant data = QVariant::fromValue(object);
-//! [8]
-
//! [9]
QList<int> intList = {7, 11, 42};
diff --git a/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp b/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp
index 3092e32f6f..7ed52617e7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+using namespace Qt::StringLiterals;
//! [0]
QMimeDatabase db;
@@ -57,7 +12,7 @@ if (mime.inherits("text/plain")) {
//! [0]
//! [1]
-QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"),
+QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "mime/packages"_L1,
QStandardPaths::LocateDirectory);
//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_plugin_qlibrary.cpp b/src/corelib/doc/snippets/code/src_corelib_plugin_qlibrary.cpp
index 6abd2f6d2b..6edb937208 100644
--- a/src/corelib/doc/snippets/code/src_corelib_plugin_qlibrary.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_plugin_qlibrary.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QLibrary myLib("mylib");
diff --git a/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp b/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp
index 2ba231d1cc..4d8f0b8d34 100644
--- a/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
// {67C8770B-44F1-410A-AB9A-F9B5446F13EE}
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp
index cb6928b129..acb5a6272e 100644
--- a/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+using namespace Qt::StringLiterals;
//! [0]
QCborValue(QCborTag(2), QByteArray("\x01\0\0\0\0\0\0\0\0", 9));
@@ -55,18 +10,18 @@
//! [1]
writer.startMap(4); // 4 elements in the map
- writer.append(QLatin1String("label"));
- writer.append(QLatin1String("journald"));
+ writer.append("label"_L1);
+ writer.append("journald"_L1);
- writer.append(QLatin1String("autoDetect"));
+ writer.append("autoDetect"_L1);
writer.append(false);
- writer.append(QLatin1String("condition"));
- writer.append(QLatin1String("libs.journald"));
+ writer.append("condition"_L1);
+ writer.append("libs.journald"_L1);
- writer.append(QLatin1String("output"));
+ writer.append("output"_L1);
writer.startArray(1);
- writer.append(QLatin1String("privateFeature"));
+ writer.append("privateFeature"_L1);
writer.endArray();
writer.endMap();
@@ -118,7 +73,7 @@
//! [7]
//! [8]
- writer.append(QLatin1String("Hello, World"));
+ writer.append("Hello, World"_L1);
//! [8]
//! [9]
@@ -228,7 +183,7 @@
//! [21]
//! [22]
- void appendMap(QCborStreamWriter &writer, const QList<QPair<int, QString>> &values)
+ void appendMap(QCborStreamWriter &writer, const QList<std::pair<int, QString>> &values)
{
writer.startMap();
for (const auto pair : values) {
@@ -243,7 +198,7 @@
void appendMap(QCborStreamWriter &writer, const QMap<int, QString> &map)
{
writer.startMap(map.size());
- for (auto it = map.begin(); it != map.end(); ++it) {
+ for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) {
writer.append(it.key());
writer.append(it.value());
}
@@ -316,12 +271,12 @@
{
QString result;
auto r = reader.readString();
- while (r.code == QCborStreamReader::Ok) {
+ while (r.status == QCborStreamReader::Ok) {
result += r.data;
r = reader.readString();
}
- if (r.code == QCborStreamReader::Error) {
+ if (r.status == QCborStreamReader::Error) {
// handle error condition
result.clear();
}
@@ -334,12 +289,12 @@
{
QBytearray result;
auto r = reader.readBytearray();
- while (r.code == QCborStreamReader::Ok) {
+ while (r.status == QCborStreamReader::Ok) {
result += r.data;
r = reader.readByteArray();
}
- if (r.code == QCborStreamReader::Error) {
+ if (r.status == QCborStreamReader::Error) {
// handle error condition
result.clear();
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp
index 5406536cfe..3abee048ab 100644
--- a/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QCborValue(uuid) == QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122());
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp
index cfcc2f8f94..dfdebe6a76 100644
--- a/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp
@@ -1,59 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
- QDataStream &operator<<(QDataStream &, const QXxx &);
- QDataStream &operator>>(QDataStream &, QXxx &);
+QDataStream &operator<<(QDataStream &, const QXxx &);
+QDataStream &operator>>(QDataStream &, QXxx &);
//! [0]
//! [1]
- QDataStream & operator<< (QDataStream& stream, const QImage& image);
- QDataStream & operator>> (QDataStream& stream, QImage& image);
+QDataStream &operator<<(QDataStream &stream, const QImage &image);
+QDataStream &operator>>(QDataStream &stream, QImage &image);
//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp
index 1fe328c0a0..0cb11ed872 100644
--- a/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
{
diff --git a/src/corelib/doc/snippets/code/src_corelib_statemachine_qstatemachine.cpp b/src/corelib/doc/snippets/code/src_corelib_statemachine_qstatemachine.cpp
deleted file mode 100644
index c756116de4..0000000000
--- a/src/corelib/doc/snippets/code/src_corelib_statemachine_qstatemachine.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [simple state machine]
-QPushButton button;
-
-QStateMachine machine;
-QState *s1 = new QState();
-s1->assignProperty(&button, "text", "Click me");
-
-QFinalState *s2 = new QFinalState();
-s1->addTransition(&button, &QPushButton::clicked, s2);
-
-machine.addState(s1);
-machine.addState(s2);
-machine.setInitialState(s1);
-machine.start();
-//! [simple state machine]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qanystringview.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qanystringview.cpp
new file mode 100644
index 0000000000..370c6fd3e0
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qanystringview.cpp
@@ -0,0 +1,12 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+ void myfun1(QAnyStringView sv); // preferred
+ void myfun2(const QAnyStringView &sv); // compiles and works, but slower
+//! [0]
+
+//! [2]
+ auto sv1 = QAnyStringView{std::begin(array), std::end(array) - 1}; // using C++11 std::begin()/std::end()
+ auto sv2 = QAnyStringView(array, std::size(array) - 1); // using C++17 std::size()
+//! [2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp
index 9c07a2e92c..a4fecc41f9 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void wrapInFunction()
@@ -69,9 +22,9 @@ ba[4] = 0xca;
//! [2]
-for (int i = 0; i < ba.size(); ++i) {
+for (qsizetype i = 0; i < ba.size(); ++i) {
if (ba.at(i) >= 'a' && ba.at(i) <= 'f')
- cout << "Found character in range [a-f]" << Qt::endl;
+ cout << "Found character in range [a-f]" << endl;
}
//! [2]
@@ -86,9 +39,9 @@ x.replace(5, 3, "&"); // x == "rock & roll"
//! [4]
QByteArray ba("We must be <b>bold</b>, very <b>bold</b>");
-int j = 0;
+qsizetype j = 0;
while ((j = ba.indexOf("<b>", j)) != -1) {
- cout << "Found <b> tag at index position " << j << Qt::endl;
+ cout << "Found <b> tag at index position " << j << endl;
++j;
}
//! [4]
@@ -108,7 +61,7 @@ QByteArray("abc").isEmpty(); // returns false
//! [6]
QByteArray ba("Hello");
-int n = ba.size(); // n == 5
+qsizetype n = ba.size(); // n == 5
ba.data()[0]; // returns 'H'
ba.data()[4]; // returns 'o'
ba.data()[5]; // returns '\0'
@@ -126,7 +79,7 @@ QByteArray("abc").isEmpty(); // returns false
QByteArray ba("Hello world");
char *data = ba.data();
while (*data) {
- cout << "[" << *data << "]" << Qt::endl;
+ cout << "[" << *data << "]" << endl;
++data;
}
//! [8]
@@ -195,7 +148,7 @@ x.append(y);
//! [17]
QByteArray ba("Meal");
-ba.insert(1, QByteArray("ontr"));
+ba.insert(1, QByteArrayView("ontr"));
// ba == "Montreal"
//! [17]
@@ -224,7 +177,7 @@ ba.replace(QByteArray("ou"), QByteArray("o"));
//! [21]
QByteArray x("sticky question");
-QByteArray y("sti");
+QByteArrayView y("sti");
x.indexOf(y); // returns 0
x.indexOf(y, 1); // returns 10
x.indexOf(y, 10); // returns 10
@@ -243,7 +196,7 @@ ba.indexOf("X"); // returns -1
//! [23]
QByteArray x("crazy azimuths");
-QByteArray y("az");
+QByteArrayView y("az");
x.lastIndexOf(y); // returns 6
x.lastIndexOf(y, 6); // returns 6
x.lastIndexOf(y, 5); // returns 2
@@ -276,22 +229,22 @@ if (url.endsWith(".html"))
//! [27]
QByteArray x("Pineapple");
-QByteArray y = x.left(4);
+QByteArray y = x.first(4);
// y == "Pine"
//! [27]
//! [28]
QByteArray x("Pineapple");
-QByteArray y = x.right(5);
+QByteArray y = x.last(5);
// y == "apple"
//! [28]
//! [29]
QByteArray x("Five pineapples");
-QByteArray y = x.mid(5, 4); // y == "pine"
-QByteArray z = x.mid(5); // z == "pineapples"
+QByteArray y = x.sliced(5, 4); // y == "pine"
+QByteArray z = x.sliced(5); // z == "pineapples"
//! [29]
@@ -422,7 +375,7 @@ text.data(); // returns "Qt is great!"
QByteArray::fromBase64("PHA+SGVsbG8/PC9wPg==", QByteArray::Base64Encoding); // returns "<p>Hello?</p>"
QByteArray::fromBase64("PHA-SGVsbG8_PC9wPg==", QByteArray::Base64UrlEncoding); // returns "<p>Hello?</p>"
-//! [44bis]
+//! [44]
//! [44ter]
void process(const QByteArray &);
@@ -490,13 +443,13 @@ macAddress.toHex(0); // returns "123456abcdef"
//! [51]
QByteArray text = QByteArray::fromPercentEncoding("Qt%20is%20great%33");
-text.data(); // returns "Qt is great!"
+qDebug("%s", text.data()); // reports "Qt is great!"
//! [51]
//! [52]
QByteArray text = "{a fishy string?}";
QByteArray ba = text.toPercentEncoding("{}", "s");
-qDebug(ba.constData());
+qDebug("%s", ba.constData());
// prints "{a fi%73hy %73tring%3F}"
//! [52]
@@ -504,6 +457,25 @@ qDebug(ba.constData());
QByteArray ba = QByteArrayLiteral("byte array contents");
//! [53]
-}
+//! [54]
+QByteArray encoded("Qt%20is%20great%33");
+QByteArray decoded = encoded.percentDecoded(); // Set to "Qt is great!"
+//! [54]
+//! [55]
+emscripten::val uint8array = emscripten::val::global("g_uint8array");
+QByteArray byteArray = QByteArray::fromEcmaUint8Array(uint8array);
+//! [55]
+//! [56]
+QByteArray byteArray = "test";
+emscripten::val uint8array = QByteArray::toEcmaUint8Array(byteArray);
+//! [56]
+
+//! [57]
+QByteArray x = "Five pineapples"_ba;
+x.slice(5); // x == "pineapples"
+x.slice(4, 3); // x == "app"
+//! [57]
+
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qbytearraymatcher.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qbytearraymatcher.cpp
index 9cf94f0494..3d750c44ff 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qbytearraymatcher.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qbytearraymatcher.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
static const auto matcher = qMakeStaticByteArrayMatcher("needle");
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp
new file mode 100644
index 0000000000..4457a71ae5
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QtCore/qbytearrayview.h>
+
+//! [0]
+ void myfun1(QByteArrayView bv); // preferred
+ void myfun2(const QByteArrayView &bv); // compiles and works, but slower
+//! [0]
+
+//! [1]
+ void fun(QByteArrayView bv);
+ void fun(char ch) { fun(QByteArrayView(&ch, 1)); }
+//! [1]
+
+//! [2]
+QByteArrayView str("FF");
+bool ok;
+int hex = str.toInt(&ok, 16); // hex == 255, ok == true
+int dec = str.toInt(&ok, 10); // dec == 0, ok == false
+//! [2]
+
+//! [3]
+QByteArrayView str("FF");
+bool ok;
+long hex = str.toLong(&ok, 16); // hex == 255, ok == true
+long dec = str.toLong(&ok, 10); // dec == 0, ok == false
+//! [3]
+
+//! [4]
+QByteArrayView string("1234.56 Volt");
+bool ok;
+float a = str.toFloat(&ok); // a == 0, ok == false
+a = string.first(7).toFloat(&ok); // a == 1234.56, ok == true
+//! [4]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qcollator.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qcollator.cpp
new file mode 100644
index 0000000000..91da052bf7
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qcollator.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+QStringList sortedStrings(QStringList seq)
+{
+ QCollator order;
+ std::sort(seq.begin(), seq.end(), order);
+ return seq;
+}
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp
index aed14c379f..c3c41b250b 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QLocale egyptian(QLocale::Arabic, QLocale::Egypt);
@@ -59,24 +12,22 @@ int i = egyptian.toInt(s2);
//! [1]
-QLocale::setDefault(QLocale(QLocale::Hebrew, QLocale::Israel));
-QLocale hebrew; // Constructs a default QLocale
-QString s1 = hebrew.toString(15714.3, 'e');
-
bool ok;
double d;
-QLocale::setDefault(QLocale::C);
-d = QString("1234,56").toDouble(&ok); // ok == false
-d = QString("1234.56").toDouble(&ok); // ok == true, d == 1234.56
+QLocale::setDefault(QLocale::C); // uses '.' as a decimal point
+QLocale cLocale; // default-constructed C locale
+d = cLocale.toDouble("1234,56", &ok); // ok == false, d == 0
+d = cLocale.toDouble("1234.56", &ok); // ok == true, d == 1234.56
-QLocale::setDefault(QLocale::German);
-d = QString("1234,56").toDouble(&ok); // ok == true, d == 1234.56
-d = QString("1234.56").toDouble(&ok); // ok == true, d == 1234.56
+QLocale::setDefault(QLocale::German); // uses ',' as a decimal point
+QLocale german; // default-constructed German locale
+d = german.toDouble("1234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble("1234.56", &ok); // ok == false, d == 0
-QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
-str = QString("%1 %L2 %L3")
- .arg(12345).arg(12345).arg(12345, 0, 16);
+QLocale::setDefault(QLocale::English);
+// Default locale now uses ',' as a group separator.
+QString str = QString("%1 %L2 %L3").arg(12345).arg(12345).arg(12345, 0, 16);
// str == "12345 12,345 3039"
//! [1]
@@ -92,16 +43,16 @@ bool ok;
double d;
QLocale c(QLocale::C);
-d = c.toDouble( "1234.56", &ok ); // ok == true, d == 1234.56
-d = c.toDouble( "1,234.56", &ok ); // ok == true, d == 1234.56
-d = c.toDouble( "1234,56", &ok ); // ok == false
+d = c.toDouble("1234.56", &ok); // ok == true, d == 1234.56
+d = c.toDouble("1,234.56", &ok); // ok == true, d == 1234.56
+d = c.toDouble("1234,56", &ok); // ok == false, d == 0
QLocale german(QLocale::German);
-d = german.toDouble( "1234,56", &ok ); // ok == true, d == 1234.56
-d = german.toDouble( "1.234,56", &ok ); // ok == true, d == 1234.56
-d = german.toDouble( "1234.56", &ok ); // ok == false
+d = german.toDouble("1234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble("1.234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble("1234.56", &ok); // ok == false, d == 0
-d = german.toDouble( "1.234", &ok ); // ok == true, d == 1234.0
+d = german.toDouble("1.234", &ok); // ok == true, d == 1234.0
//! [3]
//! [3-qstringview]
@@ -109,14 +60,14 @@ bool ok;
double d;
QLocale c(QLocale::C);
-d = c.toDouble(u"1234.56", &ok); // ok == true, d == 1234.56
-d = c.toDouble(u"1,234.56", &ok); // ok == true, d == 1234.56
-d = c.toDouble(u"1234,56", &ok); // ok == false
+d = c.toDouble(u"1234.56", &ok); // ok == true, d == 1234.56
+d = c.toDouble(u"1,234.56", &ok); // ok == true, d == 1234.56
+d = c.toDouble(u"1234,56", &ok); // ok == false, d == 0
QLocale german(QLocale::German);
-d = german.toDouble(u"1234,56", &ok); // ok == true, d == 1234.56
-d = german.toDouble(u"1.234,56", &ok); // ok == true, d == 1234.56
-d = german.toDouble(u"1234.56", &ok); // ok == false
+d = german.toDouble(u"1234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble(u"1.234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble(u"1234.56", &ok); // ok == false, d == 0
-d = german.toDouble(u"1.234", &ok); // ok == true, d == 1234.0
+d = german.toDouble(u"1.234", &ok); // ok == true, d == 1234.0
//! [3-qstringview]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qregexp.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qregexp.cpp
deleted file mode 100644
index 8339ea413e..0000000000
--- a/src/corelib/doc/snippets/code/src_corelib_text_qregexp.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-QRegExp rx("(\\d+)");
-QString str = "Offsets: 12 14 99 231 7";
-QStringList list;
-int pos = 0;
-
-while ((pos = rx.indexIn(str, pos)) != -1) {
- list << rx.cap(1);
- pos += rx.matchedLength();
-}
-// list: ["12", "14", "99", "231", "7"]
-//! [0]
-
-
-//! [1]
-QRegExp rx("*.txt");
-rx.setPatternSyntax(QRegExp::Wildcard);
-rx.exactMatch("README.txt"); // returns true
-rx.exactMatch("welcome.txt.bak"); // returns false
-//! [1]
-
-
-//! [2]
-QRegExp rx("ro+m");
-rx.setMinimal(true);
-//! [2]
-
-
-//! [3]
-QRegExp mark("\\b" // word boundary
- "[Mm]ark" // the word we want to match
- );
-//! [3]
-
-
-//! [4]
-QRegExp rx("^\\d\\d?$"); // match integers 0 to 99
-rx.indexIn("123"); // returns -1 (no match)
-rx.indexIn("-6"); // returns -1 (no match)
-rx.indexIn("6"); // returns 0 (matched at position 0)
-//! [4]
-
-
-//! [5]
-QRegExp rx("^\\S+$"); // match strings without whitespace
-rx.indexIn("Hello world"); // returns -1 (no match)
-rx.indexIn("This_is-OK"); // returns 0 (matched at position 0)
-//! [5]
-
-
-//! [6]
-QRegExp rx("\\b(mail|letter|correspondence)\\b");
-rx.indexIn("I sent you an email"); // returns -1 (no match)
-rx.indexIn("Please write the letter"); // returns 17
-//! [6]
-
-
-//! [7]
-QString captured = rx.cap(1); // captured == "letter"
-//! [7]
-
-
-//! [8]
-QRegExp rx("&(?!amp;)"); // match ampersands but not &amp;
-QString line1 = "This & that";
-line1.replace(rx, "&amp;");
-// line1 == "This &amp; that"
-QString line2 = "His &amp; hers & theirs";
-line2.replace(rx, "&amp;");
-// line2 == "His &amp; hers &amp; theirs"
-//! [8]
-
-
-//! [9]
-QString str = "One Eric another Eirik, and an Ericsson. "
- "How many Eiriks, Eric?";
-QRegExp rx("\\b(Eric|Eirik)\\b"); // match Eric or Eirik
-int pos = 0; // where we are in the string
-int count = 0; // how many Eric and Eirik's we've counted
-while (pos >= 0) {
- pos = rx.indexIn(str, pos);
- if (pos >= 0) {
- ++pos; // move along in str
- ++count; // count our Eric or Eirik
- }
-}
-//! [9]
-
-
-//! [10]
-str = "The Qt Company Ltd\tqt.io\tFinland";
-QString company, web, country;
-rx.setPattern("^([^\t]+)\t([^\t]+)\t([^\t]+)$");
-if (rx.indexIn(str) != -1) {
- company = rx.cap(1);
- web = rx.cap(2);
- country = rx.cap(3);
-}
-//! [10]
-
-
-//! [11]
-QStringList field = str.split("\t");
-//! [11]
-
-
-//! [12]
-QRegExp rx("*.html");
-rx.setPatternSyntax(QRegExp::Wildcard);
-rx.exactMatch("index.html"); // returns true
-rx.exactMatch("default.htm"); // returns false
-rx.exactMatch("readme.txt"); // returns false
-//! [12]
-
-
-//! [13]
-QString str = "offsets: 1.23 .50 71.00 6.00";
-QRegExp rx("\\d*\\.\\d+"); // primitive floating point matching
-int count = 0;
-int pos = 0;
-while ((pos = rx.indexIn(str, pos)) != -1) {
- ++count;
- pos += rx.matchedLength();
-}
-// pos will be 9, 14, 18 and finally 24; count will end up as 4
-//! [13]
-
-
-//! [14]
-QRegExp rx("(\\d+)(\\s*)(cm|inch(es)?)");
-int pos = rx.indexIn("Length: 36 inches");
-QStringList list = rx.capturedTexts();
-// list is now ("36 inches", "36", " ", "inches", "es")
-//! [14]
-
-
-//! [15]
-QRegExp rx("(\\d+)(?:\\s*)(cm|inch(?:es)?)");
-int pos = rx.indexIn("Length: 36 inches");
-QStringList list = rx.capturedTexts();
-// list is now ("36 inches", "36", "inches")
-//! [15]
-
-
-//! [16]
-QStringList list = rx.capturedTexts();
-QStringList::iterator it = list.begin();
-while (it != list.end()) {
- myProcessing(*it);
- ++it;
-}
-//! [16]
-
-
-//! [17]
-QRegExp rxlen("(\\d+)(?:\\s*)(cm|inch)");
-int pos = rxlen.indexIn("Length: 189cm");
-if (pos > -1) {
- QString value = rxlen.cap(1); // "189"
- QString unit = rxlen.cap(2); // "cm"
- // ...
-}
-//! [17]
-
-
-//! [18]
-QRegExp rx("/([a-z]+)/([a-z]+)");
-rx.indexIn("Output /dev/null"); // returns 7 (position of /dev/null)
-rx.pos(0); // returns 7 (position of /dev/null)
-rx.pos(1); // returns 8 (position of dev)
-rx.pos(2); // returns 12 (position of null)
-//! [18]
-
-
-//! [19]
-s1 = QRegExp::escape("bingo"); // s1 == "bingo"
-s2 = QRegExp::escape("f(x)"); // s2 == "f\\(x\\)"
-//! [19]
-
-
-//! [20]
-QRegExp rx("(" + QRegExp::escape(name) +
- "|" + QRegExp::escape(alias) + ")");
-//! [20]
-
-{
-//! [21]
-QString p("a .*|pattern");
-
-// re matches exactly the pattern string p
-QRegularExpression re(QRegularExpression::anchoredPattern(p));
-//! [21]
-}
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qregularexpression.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qregularexpression.cpp
index b451ed5253..03fdda9987 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qregularexpression.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qregularexpression.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Giuseppe D'Angelo <dangelog@gmail.com>.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QString>
#include <QStringList>
@@ -355,4 +308,35 @@ QString wildcard = QRegularExpression::wildcardToRegularExpression("*.jpeg");
("", "day", "month", "year", "", "name")
//! [33]
+{
+//! [34]
+// using a raw string literal, R"(raw_characters)", to be able to use "\w"
+// without having to escape the backslash as "\\w"
+QRegularExpression re(R"(\w+)");
+QString subject("the quick fox");
+for (const QRegularExpressionMatch &match : re.globalMatch(subject)) {
+ // ...
+}
+//! [34]
+}
+
+{
+//! [35]
+// matches two digits followed by a space and a word
+QRegularExpression re(R"(\d\d \w+)");
+//! [35]
+}
+
+{
+//! [36]
+QRegularExpression re("([a-z]+)|([A-Z]+)");
+QRegularExpressionMatch m = re.match("UPPERCASE");
+if (m.hasMatch()) {
+ qDebug() << m.hasCaptured(0); // true
+ qDebug() << m.hasCaptured(1); // false
+ qDebug() << m.hasCaptured(2); // true
+}
+//! [36]
+}
+
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qstaticlatin1stringmatcher.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qstaticlatin1stringmatcher.cpp
new file mode 100644
index 0000000000..ae6e19e471
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qstaticlatin1stringmatcher.cpp
@@ -0,0 +1,8 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//! [0]
+static constexpr auto matcher = qMakeStaticCaseSensitiveLatin1StringViewMatcher("needle");
+//! [0]
+//! [1]
+static constexpr auto matcher = qMakeStaticCaseInsensitiveLatin1StringViewMatcher("needle");
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp
index 4e79d1e27a..efb529657a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp
@@ -1,61 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-DEFINES += QT_NO_CAST_FROM_ASCII \
- QT_NO_CAST_TO_ASCII
-//! [0]
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+using namespace Qt::StringLiterals;
//! [1]
-QString url = QLatin1String("http://www.unicode.org/");
+QString url = "https://www.unicode.org/"_L1;
//! [1]
@@ -81,19 +30,22 @@ if (str == QString("auto") || str == QString("extern")
}
//! [4]
+//! [4bis]
+str.append("Hello ").append("World");
+//! [4bis]
//! [5]
-if (str == QLatin1String("auto")
- || str == QLatin1String("extern")
- || str == QLatin1String("static")
- || str == QLatin1String("register") {
+if (str == "auto"_L1
+ || str == "extern"_L1
+ || str == "static"_L1
+ || str == "register"_L1 {
...
}
//! [5]
//! [6]
-QLabel *label = new QLabel(QLatin1String("MOD"), this);
+QLabel *label = new QLabel("MOD"_L1, this);
//! [6]
@@ -118,5 +70,13 @@ if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //...
//! [10]
//! [11]
-if (attribute.name() == QLatin1String("http-contents-length")) //...
+if (attribute.name() == "http-contents-length"_L1) //...
//! [11]
+
+//! [qUtf8Printable]
+qWarning("%s: %s", qUtf8Printable(key), qUtf8Printable(value));
+//! [qUtf8Printable]
+
+//! [qUtf16Printable]
+qWarning("%ls: %ls", qUtf16Printable(key), qUtf16Printable(value));
+//! [qUtf16Printable]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qstringconverter.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qstringconverter.cpp
index 97d28d5428..b5bfc9cd55 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qstringconverter.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qstringconverter.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QByteArray encodedString = "...";
@@ -58,7 +11,7 @@ QString string = toUtf16(encodedString);
//! [1]
QString string = "...";
auto fromUtf16 = QStringEncoder(QStringEncoder::Utf8);
-QByteArray encodedString = fromUtf16(encodedString);
+QByteArray encodedString = fromUtf16(string);
//! [1]
@@ -81,3 +34,27 @@ while (new_data_available()) {
encoded += fromUtf16(chunk);
}
//! [3]
+
+{
+//! [4]
+QByteArray encodedString = "...";
+auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
+auto data = toUtf16(encodedString); // data's type is QStringDecoder::EncodedData<const QByteArray &>
+QString string = toUtf16(encodedString); // Implicit conversion to QString
+
+// Here you have to cast "data" to QString
+auto func = [&]() { return !toUtf16.hasError() ? QString(data) : u"foo"_s; }
+//! [4]
+}
+
+{
+//! [5]
+QString string = "...";
+auto fromUtf16 = QStringEncoder(QStringEncoder::Utf8);
+auto data = fromUtf16(string); // data's type is QStringEncoder::DecodedData<const QString &>
+QByteArray encodedString = fromUtf16(string); // Implicit conversion to QByteArray
+
+// Here you have to cast "data" to QByteArray
+auto func = [&]() { return !fromUtf16.hasError() ? QByteArray(data) : "foo"_ba; }
+//! [5]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qstringiterator.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qstringiterator.cpp
index 8085e32787..10e6eb6276 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qstringiterator.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qstringiterator.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QString>
#include <QStringIterator>
@@ -63,7 +16,7 @@ QStringIterator i(string); // implicitly converted to QStringView
//! [1]
while (i.hasNext())
- qDebug() << i.next();
+ char32_t c = i.next();
//! [1]
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qstringview.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qstringview.cpp
index fc426e1977..676baa5aee 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qstringview.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qstringview.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
void myfun1(QStringView sv); // preferred
@@ -56,7 +9,3 @@
//! [1]
void fun(QChar ch) { fun(QStringView(&ch, 1)); }
//! [1]
-
-//! [2]
- auto sv = QStringView(array, std::size(array)); // using C++17 std::size()
-//! [2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qutf8stringview.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qutf8stringview.cpp
new file mode 100644
index 0000000000..4b09796b36
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qutf8stringview.cpp
@@ -0,0 +1,7 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+ void myfun1(QUtf8StringView sv); // preferred
+ void myfun2(const QUtf8StringView &sv); // compiles and works, but slower
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qatomic.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qatomic.cpp
index 21abd2b1a0..2d55e6b706 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qatomic.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qatomic.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
MySharedType &MySharedType::operator=(const MySharedType &other)
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp
index 723c1630f6..74a2e4506e 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
@@ -83,3 +36,19 @@ void MyException::raise() const { throw *this; }
MyException *MyException::clone() const { return new MyException(*this); }
//! [3]
+
+//! [4]
+
+try {
+ auto f = QtConcurrent::run([] { throw MyException {}; });
+ // ...
+} catch (const QUnhandledException &e) {
+ try {
+ if (e.exception())
+ std::rethrow_exception(e.exception());
+ } catch (const MyException &ex) {
+ // Process 'ex'
+ }
+}
+
+//! [4]
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp
index da17b390fd..500d7cc7a5 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp
@@ -1,59 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QFuture<QString> future = ...;
QFuture<QString>::const_iterator i;
for (i = future.constBegin(); i != future.constEnd(); ++i)
- cout << *i << Qt::endl;
+ cout << qPrintable(*i) << endl;
//! [0]
@@ -62,7 +15,7 @@ QFuture<QString> future;
...
QFutureIterator<QString> i(future);
while (i.hasNext())
- qDebug() << i.next();
+ QString s = i.next();
//! [1]
@@ -70,7 +23,7 @@ while (i.hasNext())
QFutureIterator<QString> i(future);
i.toBack();
while (i.hasPrevious())
- qDebug() << i.previous();
+ QString s = i.previous();
//! [2]
//! [3]
@@ -114,10 +67,10 @@ QFuture<int> future = ...;
//! [5]
//! [6]
-QFuture<int> parentFuture = ...;
-auto continuation = parentFuture.then([](int res1){ ... }).then([](int res2){ ... })...
+QFuture<int> future = ...;
+auto continuation = future.then([](int res1){ ... }).then([](int res2){ ... })...
...
-// parentFuture throws an exception
+// future throws an exception
try {
auto result = continuation.result();
} catch (QException &e) {
@@ -252,3 +205,238 @@ auto resultFuture = testFuture.then([](int res) {
// Block 6
});
//! [16]
+
+//! [17]
+// somewhere in the main thread
+auto future = QtConcurrent::run([] {
+ // This will run in a separate thread
+ ...
+}).then(this, [] {
+ // Update UI elements
+});
+//! [17]
+
+//! [18]
+auto future = QtConcurrent::run([] {
+ ...
+}).then(this, [] {
+ // Update UI elements
+}).then([] {
+ // This will also run in the main thread
+});
+//! [18]
+
+//! [19]
+// somewhere in the main thread
+auto future = QtConcurrent::run([] {
+ // This will run in a separate thread
+ ...
+ throw std::exception();
+}).onFailed(this, [] {
+ // Update UI elements
+});
+//! [19]
+
+//! [20]
+QObject *context = ...;
+auto future = cachedResultsReady ? QtFuture::makeReadyValueFuture(result)
+ : QtConcurrent::run([] { /* compute result */});
+auto continuation = future.then(context, [] (Result result) {
+ // Runs in the context's thread
+}).then([] {
+ // May or may not run in the context's thread
+});
+//! [20]
+
+//! [21]
+QFuture<int> testFuture = ...;
+auto resultFuture = testFuture.then([](int res) {
+ // Block 1
+ ...
+ return 1;
+}).then([](int res) {
+ // Block 2
+ ...
+ return 2;
+}).onCanceled([] {
+ // Block 3
+ ...
+ return -1;
+});
+//! [21]
+
+//! [22]
+QList<QFuture<int>> inputFutures {...};
+
+// whenAll has type QFuture<QList<QFuture<int>>>
+auto whenAll = QtFuture::whenAll(inputFutures.begin(), inputFutures.end());
+
+// whenAllVector has type QFuture<std::vector<QFuture<int>>>
+auto whenAllVector =
+ QtFuture::whenAll<std::vector<QFuture<int>>>(inputFutures.begin(), inputFutures.end());
+//! [22]
+
+//! [23]
+QList<QFuture<int>> inputFutures {...};
+
+QtFuture::whenAll(inputFutures.begin(), inputFutures.end())
+ .then([](const QList<QFuture<int>> &results) {
+ for (auto future : results) {
+ if (future.isCanceled())
+ // handle the cancellation (possibly due to an exception)
+ else
+ // do something with the result
+ }
+ });
+//! [23]
+
+//! [24]
+
+QFuture<int> intFuture = ...;
+QFuture<QString> stringFuture = ...;
+QFuture<void> voidFuture = ...;
+
+using FuturesVariant = std::variant<QFuture<int>, QFuture<QString>, QFuture<void>>;
+
+// whenAll has type QFuture<QList<FuturesVariant>>
+auto whenAll = QtFuture::whenAll(intFuture, stringFuture, voidFuture);
+
+// whenAllVector has type QFuture<std::vector<FuturesVariant>>
+auto whenAllVector =
+ QtFuture::whenAll<std::vector<FuturesVariant>>(intFuture, stringFuture, voidFuture);
+
+//! [24]
+
+//! [25]
+QFuture<int> intFuture = ...;
+QFuture<QString> stringFuture = ...;
+QFuture<void> voidFuture = ...;
+
+using FuturesVariant = std::variant<QFuture<int>, QFuture<QString>, QFuture<void>>;
+
+QtFuture::whenAll(intFuture, stringFuture, voidFuture)
+ .then([](const QList<FuturesVariant> &results) {
+ ...
+ for (auto result : results)
+ {
+ // assuming handleResult() is overloaded based on the QFuture type
+ std::visit([](auto &&future) { handleResult(future); }, result);
+ }
+ ...
+ });
+//! [25]
+
+//! [26]
+QList<QFuture<int>> inputFutures = ...;
+
+QtFuture::whenAny(inputFutures.begin(), inputFutures.end())
+ .then([](const QtFuture::WhenAnyResult<int> &result) {
+ qsizetype index = result.index;
+ QFuture<int> future = result.future;
+ // ...
+ });
+//! [26]
+
+//! [27]
+QFuture<int> intFuture = ...;
+QFuture<QString> stringFuture = ...;
+QFuture<void> voidFuture = ...;
+
+using FuturesVariant = std::variant<QFuture<int>, QFuture<QString>, QFuture<void>>;
+
+QtFuture::whenAny(intFuture, stringFuture, voidFuture).then([](const FuturesVariant &result) {
+ ...
+ // assuming handleResult() is overloaded based on the QFuture type
+ std::visit([](auto &&future) { handleResult(future); }, result);
+ ...
+});
+//! [27]
+
+//! [28]
+
+QFuture<QFuture<int>> outerFuture = ...;
+QFuture<int> unwrappedFuture = outerFuture.unwrap();
+
+//! [28]
+
+//! [29]
+
+auto downloadImages = [] (const QUrl &url) {
+ QList<QImage> images;
+ ...
+ return images;
+};
+
+auto processImages = [](const QList<QImage> &images) {
+ return QtConcurrent::mappedReduced(images, scale, reduceImages);
+}
+
+auto show = [](const QImage &image) { ... };
+
+auto future = QtConcurrent::run(downloadImages, url)
+ .then(processImages)
+ .unwrap()
+ .then(show);
+//! [29]
+
+//! [30]
+
+QFuture<QFuture<QFuture<int>>>> outerFuture;
+QFuture<int> unwrappedFuture = outerFuture.unwrap();
+
+//! [30]
+
+//! [31]
+QPromise<int> p;
+
+QFuture<int> f1 = p.future();
+f1.then([](int) { qDebug("first"); });
+
+QFuture<int> f2 = p.future();
+f2.then([](int) { qDebug("second"); });
+
+p.start();
+p.addResult(42);
+p.finish();
+//! [31]
+
+//! [32]
+const std::vector<int> values{1, 2, 3};
+auto f = QtFuture::makeReadyRangeFuture(values);
+//! [32]
+
+//! [33]
+auto f = QtFuture::makeReadyRangeFuture({1, 2, 3});
+//! [33]
+
+//! [34]
+const int count = f.resultCount(); // count == 3
+const auto results = f.results(); // results == { 1, 2, 3 }
+//! [34]
+
+//! [35]
+auto f = QtFuture::makeReadyValueFuture(std::make_unique<int>(42));
+...
+const int result = *f.takeResult(); // result == 42
+//! [35]
+
+//! [36]
+auto f = QtFuture::makeReadyVoidFuture();
+...
+const bool started = f.isStarted(); // started == true
+const bool running = f.isRunning(); // running == false
+const bool finished = f.isFinished(); // finished == true
+//! [36]
+
+//! [37]
+QObject *context = ...;
+auto future = ...;
+auto continuation = future.then(context, [context](Result result) {
+ // ...
+ }).onCanceled([context = QPointer(context)] {
+ if (!context)
+ return; // context was destroyed already
+ // handle cancellation
+ });
+
+//! [37]
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qfuturesynchronizer.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qfuturesynchronizer.cpp
index e4624f7154..0ea226fe06 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qfuturesynchronizer.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qfuturesynchronizer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
void someFunction()
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qfuturewatcher.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qfuturewatcher.cpp
index 336c1e9c79..b3a7747d12 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qfuturewatcher.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qfuturewatcher.cpp
@@ -1,58 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
// Instantiate the objects and connect to the finished signal.
MyClass myObject;
QFutureWatcher<int> watcher;
-connect(&watcher, QFutureWatcher<int>::finished, &myObject, &MyClass::handleFinished);
+connect(&watcher, &QFutureWatcher<int>::finished, &myObject, &MyClass::handleFinished);
// Start the computation.
QFuture<int> future = QtConcurrent::run(...);
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qmutex.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qmutex.cpp
index 63897cabd4..efba262795 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qmutex.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qmutex.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
int number = 6;
@@ -184,7 +137,7 @@ int complexFunction(int flag)
class SignalWaiter
{
private:
- QMutexLocker locker;
+ QMutexLocker<QMutex> locker;
public:
SignalWaiter(QMutex *mutex)
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qmutexpool.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qmutexpool.cpp
deleted file mode 100644
index d9d735cdc9..0000000000
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qmutexpool.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-class Number {
-public:
- Number(double n) : num (n) { }
-
- void setNumber(double n) { num = n; }
- double number() const { return num; }
-
-private:
- double num;
-};
-//! [0]
-
-
-//! [1]
-void calcSquare(Number *num)
-{
- QMutexLocker locker(mutexpool.get(num));
- num.setNumber(num.number() * num.number());
-}
-//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qreadwritelock.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qreadwritelock.cpp
index d9abe2bc3e..3c50f991c2 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qreadwritelock.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qreadwritelock.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QReadWriteLock lock;
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp
index 52105bce0b..d7c9b900af 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QSemaphore sem(5); // sem.available() == 5
@@ -82,6 +35,12 @@ sem.tryAcquire(250, 1000); // sem.available() == 5, waits 1000 milliseconds a
sem.tryAcquire(3, 30000); // sem.available() == 2, returns true without waiting
//! [3]
+//! [tryAcquire-QDeadlineTimer]
+QSemaphore sem(5); // sem.available() == 5
+sem.tryAcquire(250, QDeadlineTimer(1000)); // sem.available() == 5, waits 1000 milliseconds and returns false
+sem.tryAcquire(3, QDeadlineTimer(30s)); // sem.available() == 2, returns true without waiting
+//! [tryAcquire-QDeadlineTimer]
+
//! [4]
// ... do something that may throw or return early
sem.release();
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp
index 7c687a0430..9852ae4d54 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtCore/QThread>
class MyObject;
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp
index 135a727a97..efddcd2df4 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qwaitcondition_unix.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
forever {
diff --git a/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp b/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp
index a477e91548..588e81bab1 100644
--- a/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QDate d1(1995, 5, 17); // May 17, 1995
@@ -118,14 +71,6 @@ QTime::isValid(22, 5, 62); // returns false
//! [9]
-//! [10]
-QTime t;
-t.start();
-some_lengthy_task();
-qDebug("Time elapsed: %d ms", t.elapsed());
-//! [10]
-
-
//! [11]
QDateTime now = QDateTime::currentDateTime();
QDateTime xmas(QDate(now.date().year(), 12, 25).startOfDay());
@@ -216,3 +161,31 @@ QString string = "Tuesday, 23 April 12 22:51:41";
QString format = "dddd, d MMMM yy hh:mm:ss";
QDateTime valid = QDateTime::fromString(string, format);
//! [21]
+
+//! [22]
+// 23 April 2012:
+QDate date = std::chrono::year_month_day(std::chrono::year(2012),
+ std::chrono::month(4),
+ std::chrono::day(23));
+
+// Same, under `using std::chrono` convenience:
+QDate dateWithLiterals1 = 23 / April / 2012y;
+QDate dateWithLiterals2 = 2012y / April / 23;
+
+// Last day of February 2000
+QDate lastDayFeb2020 = 2000y / February / last;
+
+// First Monday of January 2020:
+QDate firstMonday = 2020y / January / Monday[0];
+
+// Last Monday of January 2020:
+QDate lastMonday = 2020y / January / Monday[last];
+//! [22]
+
+//! [23]
+QDateTime local(QDateTime::currentDateTime());
+QDateTime UTC(local.toTimeSpec(QTimeZone::UTC));
+qDebug() << "Local time is:" << local;
+qDebug() << "UTC time is:" << UTC;
+qDebug() << "No difference between times represented:" << local.secsTo(UTC);
+//! [23]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbitarray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbitarray.cpp
index a436dcb358..7c98b6d8ff 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qbitarray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbitarray.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QBitArray ba(200);
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp
index 1871666a56..dbc83127ec 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineoption.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCommandLineOption>
#include <QCommandLineParser>
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp
index a5ce172e71..cc22ba88ce 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <qcommandlineparser.h>
@@ -137,12 +90,4 @@ Arguments:
//! [3]
}
-{
-//! [4]
-QCommandLineParser parser;
-parser.setApplicationDescription(QCoreApplication::translate("main", "The best application in the world"));
-parser.addHelpOption();
-//! [4]
-}
-
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp
index 159d8f4a42..7c06e36313 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcommandlineparser_main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <qcommandlineparser.h>
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp
index 84780374e9..891ec1f549 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
MyRecord record(int row) const
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp
index 88f1e90713..e0be0c3d9a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [typedef]
qreal myEasingFunction(qreal progress);
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index 344fbb241d..c779b9e3e7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QHash<QString, int> hash;
@@ -89,7 +42,7 @@ QHash<int, QWidget *> hash;
...
for (int i = 0; i < 1000; ++i) {
if (hash[i] == okButton)
- cout << "Found button at index " << i << Qt::endl;
+ cout << "Found button at index " << i << endl;
}
//! [6]
@@ -98,17 +51,14 @@ for (int i = 0; i < 1000; ++i) {
QHashIterator<QString, int> i(hash);
while (i.hasNext()) {
i.next();
- cout << i.key() << ": " << i.value() << Qt::endl;
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
}
//! [7]
//! [8]
-QHash<QString, int>::const_iterator i = hash.constBegin();
-while (i != hash.constEnd()) {
- cout << i.key() << ": " << i.value() << Qt::endl;
- ++i;
-}
+for (auto i = hash.cbegin(), end = hash.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
//! [8]
@@ -122,8 +72,8 @@ hash.insert("plenty", 2000);
//! [12]
QHash<QString, int> hash;
...
-foreach (int value, hash)
- cout << value << Qt::endl;
+for (int value : std::as_const(hash))
+ cout << value << endl;
//! [12]
@@ -185,7 +135,7 @@ QHash<QString, int> hash;
...
QHash<QString, int>::const_iterator i = hash.find("HDR");
while (i != hash.end() && i.key() == "HDR") {
- cout << i.value() << Qt::endl;
+ cout << i.value() << endl;
++i;
}
//! [16]
@@ -198,50 +148,20 @@ hash.insert("February", 2);
...
hash.insert("December", 12);
-QHash<QString, int>::iterator i;
-for (i = hash.begin(); i != hash.end(); ++i)
- cout << i.key() << ": " << i.value() << Qt::endl;
+for (auto i = hash.cbegin(), end = hash.cend(); i != end; ++i)
+ cout << qPrintable(key()) << ": " << i.value() << endl;
//! [17]
//! [18]
-QHash<QString, int>::iterator i;
-for (i = hash.begin(); i != hash.end(); ++i)
+for (auto i = hash.begin(), end = hash.end(); i != end; ++i)
i.value() += 2;
//! [18]
-
-//! [19]
-QHash<QString, int>::iterator i = hash.begin();
-while (i != hash.end()) {
- if (i.key().startsWith('_'))
- i = hash.erase(i);
- else
- ++i;
-}
-//! [19]
-
-
-//! [20]
-QHash<QString, int>::iterator i = hash.begin();
-while (i != hash.end()) {
- QHash<QString, int>::iterator prev = i;
- ++i;
- if (prev.key().startsWith('_'))
- hash.erase(prev);
-}
-//! [20]
-
-
//! [21]
-// WRONG
-while (i != hash.end()) {
- if (i.key().startsWith('_'))
- hash.erase(i);
- ++i;
-}
+erase_if(hash, [](const QHash<QString, int>::iterator it) { return it.value() > 10; });
//! [21]
-
+}
//! [22]
if (i.key() == "Hello")
@@ -256,9 +176,8 @@ hash.insert("February", 2);
...
hash.insert("December", 12);
-QHash<QString, int>::const_iterator i;
-for (i = hash.constBegin(); i != hash.constEnd(); ++i)
- cout << i.key() << ": " << i.value() << Qt::endl;
+for (auto i = hash.cbegin(), end = hash.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
//! [23]
@@ -279,24 +198,24 @@ hash3 = hash1 + hash2;
//! [25]
QList<int> values = hash.values("plenty");
-for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << Qt::endl;
+for (auto i : std::as_const(values))
+ cout << i << endl;
//! [25]
//! [26]
-QMultiHash<QString, int>::iterator i = hash.find("plenty");
-while (i != hash.end() && i.key() == "plenty") {
- cout << i.value() << Qt::endl;
+auto i = hash.constFind("plenty");
+while (i != hash.cend() && i.key() == "plenty") {
+ cout << i.value() << endl;
++i;
}
//! [26]
//! [27]
-for (QHash<int, QString>::const_iterator it = hash.cbegin(), end = hash.cend(); it != end; ++it) {
- cout << "The key: " << it.key() << Qt::endl
- cout << "The value: " << it.value() << Qt::endl;
- cout << "Also the value: " << (*it) << Qt::endl;
+for (auto it = hash.cbegin(), end = hash.cend(); it != end; ++it) {
+ cout << "The key: " << it.key() << endl;
+ cout << "The value: " << qPrintable(it.value()) << endl;
+ cout << "Also the value: " << qPrintable(*it) << endl;
}
//! [27]
@@ -335,10 +254,6 @@ inline size_t qHash(const std::unordered_set<int> &key, size_t seed = 0)
}
//! [qhashrangecommutative]
-//! [29]
-qHash(qMakePair(key.first, key.second), seed);
-//! [29]
-
//! [30]
{0, 1, 2}
//! [30]
@@ -348,9 +263,45 @@ qHash(qMakePair(key.first, key.second), seed);
//! [31]
//! [32]
-size_t qHash(K key);
-size_t qHash(const K &key);
-
size_t qHash(K key, size_t seed);
size_t qHash(const K &key, size_t seed);
+
+size_t qHash(K key); // deprecated, do not use
+size_t qHash(const K &key); // deprecated, do not use
//! [32]
+
+//! [33]
+namespace std {
+template <> struct hash<K>
+{
+ // seed is optional
+ size_t operator()(const K &key, size_t seed = 0) const;
+};
+}
+//! [33]
+
+//! [34]
+QHash<QString, int> hash;
+hash.insert("January", 1);
+hash.insert("February", 2);
+// ...
+hash.insert("December", 12);
+
+for (auto [key, value] : hash.asKeyValueRange()) {
+ cout << qPrintable(key) << ": " << value << endl;
+ --value; // convert to JS month indexing
+}
+//! [34]
+
+//! [35]
+QMultiHash<QString, int> hash;
+hash.insert("January", 1);
+hash.insert("February", 2);
+// ...
+hash.insert("December", 12);
+
+for (auto [key, value] : hash.asKeyValueRange()) {
+ cout << qPrintable(key) << ": " << value << endl;
+ --value; // convert to JS month indexing
+}
+//! [35]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp
index 26b952a77a..499e8fe480 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QList<int> integerList;
@@ -71,24 +24,24 @@ if (list[0] == "Liz")
//! [4]
-for (int i = 0; i < list.size(); ++i) {
+for (qsizetype i = 0; i < list.size(); ++i) {
if (list.at(i) == "Alfonso")
- cout << "Found Alfonso at position " << i << Qt::endl;
+ cout << "Found Alfonso at position " << i << endl;
}
//! [4]
//! [5]
-int i = list.indexOf("Harumi");
+qsizetype i = list.indexOf("Harumi");
if (i != -1)
- cout << "First occurrence of Harumi is at position " << i << Qt::endl;
+ cout << "First occurrence of Harumi is at position " << i << endl;
//! [5]
//! [6]
QList<int> list(10);
int *data = list.data();
-for (int i = 0; i < 10; ++i)
+for (qsizetype i = 0; i < 10; ++i)
data[i] = 2 * i;
//! [6]
@@ -148,16 +101,14 @@ list.prepend("three");
//! [9]
-QList<QString> list;
-list << "alpha" << "beta" << "delta";
+QList<QString> list = {"alpha", "beta", "delta"};
list.insert(2, "gamma");
// list: ["alpha", "beta", "gamma", "delta"]
//! [9]
//! [10]
-QList<double> list;
-list << 2.718 << 1.442 << 0.4342;
+QList<double> list = {2.718, 1.442, 0.4342};
list.insert(1, 3, 9.9);
// list: [2.718, 9.9, 9.9, 9.9, 1.442, 0.4342]
//! [10]
@@ -174,8 +125,7 @@ list.fill("oh", 5);
//! [12]
-QList<QString> list;
-list << "A" << "B" << "C" << "B" << "A";
+QList<QString> list{"A", "B", "C", "B", "A"};
list.indexOf("B"); // returns 1
list.indexOf("B", 1); // returns 1
list.indexOf("B", 2); // returns 3
@@ -184,27 +134,9 @@ list.indexOf("X"); // returns -1
//! [13]
-QList<QString> list;
-list << "A" << "B" << "C" << "B" << "A";
+QList<QString> list = {"A", "B", "C", "B", "A"};
list.lastIndexOf("B"); // returns 3
list.lastIndexOf("B", 3); // returns 3
list.lastIndexOf("B", 2); // returns 1
list.lastIndexOf("X"); // returns -1
//! [13]
-
-//! [16]
-std::vector<double> stdvector;
-stdvector.push_back(1.2);
-stdvector.push_back(0.5);
-stdvector.push_back(3.14);
-
-QList<double> list = QList<double>::fromStdVector(stdvector);
-//! [16]
-
-
-//! [17]
-QList<double> list;
-list << 1.2 << 0.5 << 3.14;
-
-std::vector<double> stdlist = list.toStdVector();
-//! [17]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
index 145cd10d84..5f87211968 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QMap<QString, int> map;
@@ -89,7 +42,7 @@ QMap<int, QWidget *> map;
...
for (int i = 0; i < 1000; ++i) {
if (map[i] == okButton)
- cout << "Found button at index " << i << Qt::endl;
+ cout << "Found button at index " << i << endl;
}
//! [6]
@@ -98,17 +51,14 @@ for (int i = 0; i < 1000; ++i) {
QMapIterator<QString, int> i(map);
while (i.hasNext()) {
i.next();
- cout << i.key() << ": " << i.value() << Qt::endl;
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
}
//! [7]
//! [8]
-QMap<QString, int>::const_iterator i = map.constBegin();
-while (i != map.constEnd()) {
- cout << i.key() << ": " << i.value() << Qt::endl;
- ++i;
-}
+for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
//! [8]
@@ -119,27 +69,11 @@ map.insert("plenty", 2000);
//! [9]
-//! [10]
-QList<int> values = map.values("plenty");
-for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << Qt::endl;
-//! [10]
-
-
-//! [11]
-QMap<QString, int>::iterator i = map.find("plenty");
-while (i != map.end() && i.key() == "plenty") {
- cout << i.value() << Qt::endl;
- ++i;
-}
-//! [11]
-
-
//! [12]
QMap<QString, int> map;
...
-foreach (int value, map)
- cout << value << Qt::endl;
+for (int value : std::as_const(map))
+ cout << value << endl;
//! [12]
@@ -170,43 +104,6 @@ inline bool operator<(const Employee &e1, const Employee &e2)
//! [13]
-//! [14]
-QMap<QString, int> map;
-...
-QMap<QString, int>::const_iterator i = map.find("HDR");
-while (i != map.end() && i.key() == "HDR") {
- cout << i.value() << Qt::endl;
- ++i;
-}
-//! [14]
-
-
-//! [15]
-QMap<int, QString> map;
-map.insert(1, "one");
-map.insert(5, "five");
-map.insert(10, "ten");
-
-map.lowerBound(0); // returns iterator to (1, "one")
-map.lowerBound(1); // returns iterator to (1, "one")
-map.lowerBound(2); // returns iterator to (5, "five")
-map.lowerBound(10); // returns iterator to (10, "ten")
-map.lowerBound(999); // returns end()
-//! [15]
-
-
-//! [16]
-QMap<QString, int> map;
-...
-QMap<QString, int>::const_iterator i = map.lowerBound("HDR");
-QMap<QString, int>::const_iterator upperBound = map.upperBound("HDR");
-while (i != upperBound) {
- cout << i.value() << Qt::endl;
- ++i;
-}
-//! [16]
-
-
//! [17]
QMap<int, QString> map;
map.insert(1, "one");
@@ -228,50 +125,33 @@ map.insert("February", 2);
...
map.insert("December", 12);
-QMap<QString, int>::iterator i;
-for (i = map.begin(); i != map.end(); ++i)
- cout << i.key() << ": " << i.value() << Qt::endl;
+for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
//! [18]
//! [19]
-QMap<QString, int>::iterator i;
-for (i = map.begin(); i != map.end(); ++i)
+for (auto i = map.begin(), end = map.end(); i != end; ++i)
i.value() += 2;
//! [19]
+void erase()
+{
+QMap<QString, int> map;
//! [20]
-QMap<QString, int>::iterator i = map.begin();
-while (i != map.end()) {
- if (i.key().startsWith('_'))
+QMap<QString, int>::const_iterator i = map.cbegin();
+while (i != map.cend()) {
+ if (i.value() > 10)
i = map.erase(i);
else
++i;
}
//! [20]
-
-
//! [21]
-QMap<QString, int>::iterator i = map.begin();
-while (i != map.end()) {
- QMap<QString, int>::iterator prev = i;
- ++i;
- if (prev.key().startsWith('_'))
- map.erase(prev);
-}
+erase_if(map, [](const QMap<QString, int>::iterator it) { return it.value() > 10; });
//! [21]
-
-
-//! [22]
-// WRONG
-while (i != map.end()) {
- if (i.key().startsWith('_'))
- map.erase(i);
- ++i;
}
-//! [22]
-
//! [23]
if (i.key() == "Hello")
@@ -286,47 +166,16 @@ map.insert("February", 2);
...
map.insert("December", 12);
-QMap<QString, int>::const_iterator i;
-for (i = map.constBegin(); i != map.constEnd(); ++i)
- cout << i.key() << ": " << i.value() << Qt::endl;
+for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
//! [24]
-//! [25]
-QMultiMap<QString, int> map1, map2, map3;
-
-map1.insert("plenty", 100);
-map1.insert("plenty", 2000);
-// map1.size() == 2
-
-map2.insert("plenty", 5000);
-// map2.size() == 1
-
-map3 = map1 + map2;
-// map3.size() == 3
-//! [25]
-
-
-//! [26]
-QList<int> values = map.values("plenty");
-for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << Qt::endl;
-//! [26]
-
-
-//! [27]
-QMultiMap<QString, int>::iterator i = map.find("plenty");
-while (i != map.end() && i.key() == "plenty") {
- cout << i.value() << Qt::endl;
- ++i;
-}
-//! [27]
-
//! [keyiterator1]
for (QMap<int, QString>::const_iterator it = map.cbegin(), end = map.cend(); it != end; ++it) {
- cout << "The key: " << it.key() << Qt::endl
- cout << "The value: " << it.value() << Qt::endl;
- cout << "Also the value: " << (*it) << Qt::endl;
+ cout << "The key: " << it.key() << endl;
+ cout << "The value: " << qPrintable(it.value()) << endl;
+ cout << "Also the value: " << qPrintable(*it) << endl;
}
//! [keyiterator1]
@@ -340,3 +189,16 @@ qDeleteAll(map2.keys());
int numPrimes = std::count_if(map.keyBegin(), map.keyEnd(), isPrimeNumber);
qDeleteAll(map2.keyBegin(), map2.keyEnd());
//! [keyiterator2]
+
+//! [28]
+QMap<QString, int> map;
+map.insert("January", 1);
+map.insert("February", 2);
+// ...
+map.insert("December", 12);
+
+for (auto [key, value] : map.asKeyValueRange()) {
+ cout << qPrintable(key) << ": " << value << endl;
+ --value; // convert to JS month indexing
+}
+//! [28]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmultimap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmultimap.cpp
new file mode 100644
index 0000000000..42ec46585b
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmultimap.cpp
@@ -0,0 +1,256 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+QMultiMap<QString, int> multimap;
+//! [0]
+
+
+//! [2]
+multimap.insert("a", 1);
+multimap.insert("b", 3);
+multimap.insert("c", 7);
+multimap.insert("c", -5);
+//! [2]
+
+
+//! [3]
+int num2 = multimap.value("a"); // 1
+int num3 = multimap.value("thirteen"); // not found; 0
+int num3 = 0;
+auto it = multimap.constFind("b");
+if (it != multimap.cend()) {
+ num3 = it.value();
+}
+//! [3]
+
+
+//! [4]
+int timeout = 30;
+if (multimap.contains("TIMEOUT"))
+ timeout = multimap.value("TIMEOUT");
+
+// better:
+auto it = multimap.find("TIMEOUT");
+if (it != multimap.end())
+ timeout = it.value();
+//! [4]
+
+
+//! [5]
+int timeout = multimap.value("TIMEOUT", 30);
+//! [5]
+
+
+//! [7]
+QMultiMapIterator<QString, int> i(multimap);
+while (i.hasNext()) {
+ i.next();
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
+}
+//! [7]
+
+
+//! [8]
+for (auto i = multimap.cbegin(), end = multimap.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
+//! [8]
+
+
+//! [9]
+multimap.insert("plenty", 100);
+multimap.insert("plenty", 2000);
+// multimap.size() == 2
+//! [9]
+
+
+//! [10]
+QList<int> values = multimap.values("plenty");
+for (auto i : std::as_const(values))
+ cout << i << endl;
+//! [10]
+
+
+//! [11]
+auto i = multimap.find("plenty");
+while (i != map.end() && i.key() == "plenty") {
+ cout << i.value() << endl;
+ ++i;
+}
+
+// better:
+auto [i, end] = multimap.equal_range("plenty");
+while (i != end) {
+ cout << i.value() << endl;
+ ++i;
+}
+//! [11]
+
+
+//! [12]
+QMap<QString, int> multimap;
+...
+for (int value : std::as_const(multimap))
+ cout << value << endl;
+//! [12]
+
+
+//! [13]
+#ifndef EMPLOYEE_H
+#define EMPLOYEE_H
+
+class Employee
+{
+public:
+ Employee() {}
+ Employee(const QString &name, QDate dateOfBirth);
+ ...
+
+private:
+ QString myName;
+ QDate myDateOfBirth;
+};
+
+inline bool operator<(const Employee &e1, const Employee &e2)
+{
+ if (e1.name() != e2.name())
+ return e1.name() < e2.name();
+ return e1.dateOfBirth() < e2.dateOfBirth();
+}
+
+#endif // EMPLOYEE_H
+//! [13]
+
+
+//! [15]
+QMultiMap<int, QString> multimap;
+multimap.insert(1, "one");
+multimap.insert(5, "five");
+multimap.insert(5, "five (2)");
+multimap.insert(10, "ten");
+
+multimap.lowerBound(0); // returns iterator to (1, "one")
+multimap.lowerBound(1); // returns iterator to (1, "one")
+multimap.lowerBound(2); // returns iterator to (5, "five")
+multimap.lowerBound(5); // returns iterator to (5, "five")
+multimap.lowerBound(6); // returns iterator to (10, "ten")
+multimap.lowerBound(10); // returns iterator to (10, "ten")
+multimap.lowerBound(999); // returns end()
+//! [15]
+
+
+//! [16]
+QMap<QString, int> multimap;
+...
+QMap<QString, int>::const_iterator i = multimap.lowerBound("HDR");
+QMap<QString, int>::const_iterator upperBound = multimap.upperBound("HDR");
+while (i != upperBound) {
+ cout << i.value() << endl;
+ ++i;
+}
+//! [16]
+
+
+//! [17]
+QMultiMap<int, QString> multimap;
+multimap.insert(1, "one");
+multimap.insert(5, "five");
+multimap.insert(5, "five (2)");
+multimap.insert(10, "ten");
+
+multimap.upperBound(0); // returns iterator to (1, "one")
+multimap.upperBound(1); // returns iterator to (5, "five")
+multimap.upperBound(2); // returns iterator to (5, "five")
+multimap.lowerBound(5); // returns iterator to (5, "five (2)")
+multimap.lowerBound(6); // returns iterator to (10, "ten")
+multimap.upperBound(10); // returns end()
+multimap.upperBound(999); // returns end()
+//! [17]
+
+//! [19]
+for (auto it = multimap.begin(), end = multimap.end(); i != end; ++i)
+ i.value() += 2;
+//! [19]
+
+void erase()
+{
+QMultiMap<QString, int> multimap;
+//! [20]
+QMultiMap<QString, int>::const_iterator i = multimap.cbegin();
+while (i != multimap.cend()) {
+ if (i.value() > 10)
+ i = multimap.erase(i);
+ else
+ ++i;
+}
+//! [20]
+//! [21]
+erase_if(multimap, [](const QMultiMap<QString, int>::iterator it) { return it.value() > 10; });
+//! [21]
+}
+
+
+//! [23]
+if (i.key() == "Hello")
+ i.value() = "Bonjour";
+//! [23]
+
+
+//! [24]
+QMultiMap<QString, int> multi;
+multimap.insert("January", 1);
+multimap.insert("February", 2);
+...
+multimap.insert("December", 12);
+
+for (auto i = multimap.cbegin(), end = multimap.cend(); i != end; ++i)
+ cout << qPrintable(i.key()) << ": " << i.value() << endl;
+//! [24]
+
+
+//! [25]
+QMultiMap<QString, int> map1, map2, map3;
+
+map1.insert("plenty", 100);
+map1.insert("plenty", 2000);
+// map1.size() == 2
+
+map2.insert("plenty", 5000);
+// map2.size() == 1
+
+map3 = map1 + map2;
+// map3.size() == 3
+//! [25]
+
+//! [keyiterator1]
+for (auto it = multimap.cbegin(), end = multimap.cend(); it != end; ++it) {
+ cout << "The key: " << it.key() << endl
+ cout << "The value: " << qPrintable(it.value()) << endl;
+ cout << "Also the value: " << qPrintable(*it) << endl;
+}
+//! [keyiterator1]
+
+//! [keyiterator2]
+// Inefficient, keys() is expensive
+QList<int> keys = multimap.keys();
+int numPrimes = std::count_if(multimap.cbegin(), multimap.cend(), isPrimeNumber);
+qDeleteAll(multimap2.keys());
+
+// Efficient, no memory allocation needed
+int numPrimes = std::count_if(multimap.keyBegin(), multimap.keyEnd(), isPrimeNumber);
+qDeleteAll(multimap2.keyBegin(), multimap2.keyEnd());
+//! [keyiterator2]
+
+//! [26]
+QMultiMap<QString, int> map;
+map.insert("January", 1);
+map.insert("February", 2);
+// ...
+map.insert("December", 12);
+
+for (auto [key, value] : map.asKeyValueRange()) {
+ cout << qPrintable(key) << ": " << value << endl;
+ --value; // convert to JS month indexing
+}
+//! [26]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qpoint.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qpoint.cpp
index fd4db5580f..f7c06c17cc 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qpoint.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qpoint.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QPoint p;
@@ -92,7 +45,7 @@ p *= 2.5; // p becomes (-3, 10)
//! [16]
QPoint p( 3, 7);
QPoint q(-1, 4);
-int lengthSquared = QPoint::dotProduct(p, q); // lengthSquared becomes 25
+int dotProduct = QPoint::dotProduct(p, q); // dotProduct becomes 25
//! [16]
@@ -169,5 +122,5 @@ p /= 2.5; // p becomes (-1.1, 4.1)
//! [17]
QPointF p( 3.1, 7.1);
QPointF q(-1.0, 4.1);
-int lengthSquared = QPointF::dotProduct(p, q); // lengthSquared becomes 26.01
+qreal dotProduct = QPointF::dotProduct(p, q); // dotProduct becomes 26.01
//! [17]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp
index 6046c73b0f..c59ec1060a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QQueue<int> queue;
@@ -54,5 +7,5 @@ queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
while (!queue.isEmpty())
- cout << queue.dequeue() << Qt::endl;
+ cout << queue.dequeue() << endl;
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp
index a19dc086ac..403d188806 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QRect r1(100, 200, 11, 16);
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qscopedpointer.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qscopedpointer.cpp
index dde9a92129..ee0e9eafa1 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qscopedpointer.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qscopedpointer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
void myFunction(bool useSubClass)
@@ -122,7 +75,7 @@ public:
private:
Q_DISABLE_COPY(MyClass) // OK - copy constructor and assignment operators
- // are now disabled, so the compiler won't implicitely
+ // are now disabled, so the compiler won't implicitly
// generate them.
};
//! [4]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp
index 2fa4f88011..8a0d8a8012 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
void myComplexCodeWithMultipleReturnPoints(int v)
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp
index 88c8ae4151..2c8ca411f7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
class EmployeeData;
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp
index e2979fa7b4..fd0612590e 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
class Y: public QEnableSharedFromThis<Y>
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qsize.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qsize.cpp
index e1caf867b3..ee3b7b3268 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qsize.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qsize.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QSize t1(10, 12);
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qtimeline.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qtimeline.cpp
index 80859d5ba5..39bcd4faf0 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qtimeline.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qtimeline.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
...
diff --git a/src/corelib/doc/snippets/code/src_corelib_xml_qxmlstream.cpp b/src/corelib/doc/snippets/code/src_corelib_xml_qxmlstream.cpp
index 174c10bd4c..fe95b9939a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_xml_qxmlstream.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_xml_qxmlstream.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QXmlStreamReader xml;
diff --git a/src/corelib/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp b/src/corelib/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp
deleted file mode 100644
index 82f916581e..0000000000
--- a/src/corelib/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-int ret = QMessageBox::warning(this, tr("My Application"),
- tr("The document has been modified.\n"
- "Do you want to save your changes?"),
- QMessageBox::Save | QMessageBox::Discard
- | QMessageBox::Cancel,
- QMessageBox::Save);
-//! [0]
-
-
-//! [1]
-QMessageBox msgBox;
-msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
-switch (msgBox.exec()) {
-case QMessageBox::Yes:
- // yes was clicked
- break;
-case QMessageBox::No:
- // no was clicked
- break;
-default:
- // should never be reached
- break;
-}
-//! [1]
-
-
-//! [2]
-QMessageBox msgBox;
-QPushButton *connectButton = msgBox.addButton(tr("Connect"), QMessageBox::ActionRole);
-QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort);
-
-msgBox.exec();
-
-if (msgBox.clickedButton() == connectButton) {
- // connect
-} else if (msgBox.clickedButton() == abortButton) {
- // abort
-}
-//! [2]
-
-
-//! [3]
-QMessageBox messageBox(this);
-QAbstractButton *disconnectButton =
- messageBox.addButton(tr("Disconnect"), QMessageBox::ActionRole);
-...
-messageBox.exec();
-if (messageBox.clickedButton() == disconnectButton) {
- ...
-}
-//! [3]
-
-
-//! [4]
-#include <QApplication>
-#include <QMessageBox>
-
-int main(int argc, char *argv[])
-{
- QT_REQUIRE_VERSION(argc, argv, "4.0.2")
-
- QApplication app(argc, argv);
- ...
- return app.exec();
-}
-//! [4]
-
-//! [5]
-QMessageBox msgBox;
-msgBox.setText("The document has been modified.");
-msgBox.exec();
-//! [5]
-
-//! [6]
-QMessageBox msgBox;
-msgBox.setText("The document has been modified.");
-msgBox.setInformativeText("Do you want to save your changes?");
-msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
-msgBox.setDefaultButton(QMessageBox::Save);
-int ret = msgBox.exec();
-//! [6]
-
-//! [7]
-switch (ret) {
- case QMessageBox::Save:
- // Save was clicked
- break;
- case QMessageBox::Discard:
- // Don't Save was clicked
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
-}
-//! [7]
-
-//! [9]
-QMessageBox msgBox(this);
-msgBox.setText(tr("The document has been modified.\n"
- "Do you want to save your changes?"));
-msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard
- | QMessageBox::Cancel);
-msgBox.setDefaultButton(QMessageBox::Save);
-//! [9]
diff --git a/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp b/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp
index c1af521c03..4ef1891cdb 100644
--- a/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp
+++ b/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
class DateFormatProxyModel : public QIdentityProxyModel
@@ -64,10 +17,16 @@ class DateFormatProxyModel : public QIdentityProxyModel
return QIdentityProxyModel::data(index, role);
const QDateTime dateTime = sourceModel()->data(SourceClass::DateRole).toDateTime();
-
return dateTime.toString(m_formatString);
}
+ QMap<int, QVariant> itemData(const QModelIndex &proxyIndex) const override
+ {
+ QMap<int, QVariant> map = QIdentityProxyModel::itemData(proxyIndex);
+ map[Qt::DisplayRole] = data(proxyIndex);
+ return map;
+ }
+
private:
QString m_formatString;
};
diff --git a/src/corelib/doc/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp b/src/corelib/doc/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp
index 544e0f5309..0647f7f1c4 100644
--- a/src/corelib/doc/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp
+++ b/src/corelib/doc/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QItemSelection *selection = new QItemSelection(topLeft, bottomRight);
diff --git a/src/corelib/doc/snippets/customtype/customtypeexample.cpp b/src/corelib/doc/snippets/customtype/customtypeexample.cpp
new file mode 100644
index 0000000000..afa2c4b268
--- /dev/null
+++ b/src/corelib/doc/snippets/customtype/customtypeexample.cpp
@@ -0,0 +1,90 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QCoreApplication>
+#include <QDebug>
+#include <QVariant>
+
+//message.h
+
+//! [custom type definition]
+class Message
+{
+public:
+ Message() = default;
+ ~Message() = default;
+ Message(const Message &) = default;
+ Message &operator=(const Message &) = default;
+
+ Message(const QString &body, const QStringList &headers);
+
+ QStringView body() const;
+ QStringList headers() const;
+
+private:
+ QString m_body;
+ QStringList m_headers;
+};
+//! [custom type definition]
+
+//! [custom type meta-type declaration]
+Q_DECLARE_METATYPE(Message);
+//! [custom type meta-type declaration]
+
+//! [custom type streaming operator declaration]
+QDebug operator<<(QDebug dbg, const Message &message);
+//! [custom type streaming operator declaration]
+
+// message.cpp
+
+//! [custom type streaming operator]
+QDebug operator<<(QDebug dbg, const Message &message)
+{
+ const QList<QStringView> pieces = message.body().split(u"\r\n", Qt::SkipEmptyParts);
+ if (pieces.isEmpty())
+ dbg.nospace() << "Message()";
+ else if (pieces.size() == 1)
+ dbg.nospace() << "Message(" << pieces.first() << ")";
+ else
+ dbg.nospace() << "Message(" << pieces.first() << " ...)";
+ return dbg;
+}
+//! [custom type streaming operator]
+
+//! [getter functions]
+QStringView Message::body() const
+{
+ return m_body;
+}
+
+QStringList Message::headers() const
+{
+ return m_headers;
+}
+//! [getter functions]
+
+//main.cpp
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ QStringList headers;
+ headers << "Subject: Hello World"
+ << "From: address@example.com";
+ QString body = "This is a test.\r\n";
+ //! [printing a custom type]
+ Message message(body, headers);
+ qDebug() << "Original:" << message;
+ //! [printing a custom type]
+ //! [storing a custom value]
+ QVariant stored;
+ stored.setValue(message);
+ //! [storing a custom value]
+ qDebug() << "Stored:" << stored;
+ //! [retrieving a custom value]
+ Message retrieved = qvariant_cast<Message>(stored);
+ qDebug() << "Retrieved:" << retrieved;
+ retrieved = qvariant_cast<Message>(stored);
+ qDebug() << "Retrieved:" << retrieved;
+ //! [retrieving a custom value]
+ return 0;
+}
diff --git a/src/corelib/doc/snippets/eventfilters/filterobject.cpp b/src/corelib/doc/snippets/eventfilters/filterobject.cpp
index abe72c2045..385620f97f 100644
--- a/src/corelib/doc/snippets/eventfilters/filterobject.cpp
+++ b/src/corelib/doc/snippets/eventfilters/filterobject.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
diff --git a/src/corelib/doc/snippets/eventfilters/filterobject.h b/src/corelib/doc/snippets/eventfilters/filterobject.h
index 354aa4ff5c..7da2dae2f6 100644
--- a/src/corelib/doc/snippets/eventfilters/filterobject.h
+++ b/src/corelib/doc/snippets/eventfilters/filterobject.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FILTEROBJECT_H
#define FILTEROBJECT_H
@@ -58,7 +11,7 @@ class FilterObject : public QObject
Q_OBJECT
public:
- FilterObject(QObject *parent = 0);
+ FilterObject(QObject *parent = nullptr);
bool eventFilter(QObject *object, QEvent *event) override;
void setFilteredObject(QObject *object);
diff --git a/src/corelib/doc/snippets/eventfilters/main.cpp b/src/corelib/doc/snippets/eventfilters/main.cpp
index e7112ab1f5..f4f58b3300 100644
--- a/src/corelib/doc/snippets/eventfilters/main.cpp
+++ b/src/corelib/doc/snippets/eventfilters/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/corelib/doc/snippets/events/events.cpp b/src/corelib/doc/snippets/events/events.cpp
index 969b0047f0..faeb168d80 100644
--- a/src/corelib/doc/snippets/events/events.cpp
+++ b/src/corelib/doc/snippets/events/events.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCheckBox>
#include <QMouseEvent>
diff --git a/src/corelib/doc/snippets/file/file.cpp b/src/corelib/doc/snippets/file/file.cpp
index ed398984d4..d1244f4bf2 100644
--- a/src/corelib/doc/snippets/file/file.cpp
+++ b/src/corelib/doc/snippets/file/file.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QFile>
#include <QTextStream>
diff --git a/src/corelib/doc/snippets/fileinfo/main.cpp b/src/corelib/doc/snippets/fileinfo/main.cpp
index 6852a36af5..819bde3de5 100644
--- a/src/corelib/doc/snippets/fileinfo/main.cpp
+++ b/src/corelib/doc/snippets/fileinfo/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QPushButton>
@@ -78,14 +31,16 @@ int main(int argc, char *argv[])
qDebug() << fileInfo5.fileName();
qDebug() << fileInfo6.fileName();
+ QGroupBox *groupBox = new QGroupBox(QStringLiteral("QFileInfo::dir() test"));
+
+ QVBoxLayout *vbox = new QVBoxLayout(groupBox);
+
QPushButton* button1 = new QPushButton(fileInfo1.dir().path());
QPushButton* button2 = new QPushButton(fileInfo2.dir().path());
QPushButton* button3 = new QPushButton(fileInfo3.dir().path());
QPushButton* button4 = new QPushButton(fileInfo4.dir().path());
QPushButton* button5 = new QPushButton(fileInfo5.dir().path());
QPushButton* button6 = new QPushButton(fileInfo6.dir().path());
-
- QVBoxLayout* vbox = new QVBoxLayout;
vbox->addWidget(button1);
vbox->addWidget(button2);
vbox->addWidget(button3);
@@ -94,8 +49,6 @@ int main(int argc, char *argv[])
vbox->addWidget(button6);
vbox->addStretch(1);
- QGroupBox *groupBox = new QGroupBox("QFileInfo::dir() test");
- groupBox->setLayout(vbox);
groupBox->show();
return app.exec();
diff --git a/src/corelib/doc/snippets/hellotrmain.cpp b/src/corelib/doc/snippets/hellotrmain.cpp
index 526da44701..d780f19117 100644
--- a/src/corelib/doc/snippets/hellotrmain.cpp
+++ b/src/corelib/doc/snippets/hellotrmain.cpp
@@ -1,52 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+using namespace Qt::StringLiterals;
//! [0]
int main(int argc, char *argv[])
@@ -55,7 +10,7 @@ int main(int argc, char *argv[])
QTranslator translator;
// look up e.g. :/i18n/myapp_de.qm
- if (translator.load(QLocale(), QLatin1String("myapp"), QLatin1String("_"), QLatin1String(":/i18n")))
+ if (translator.load(QLocale(), "myapp"_L1, "_"_L1, ":/i18n"_L1))
QCoreApplication::installTranslator(&translator);
QPushButton hello(QCoreApplication::translate("main", "Hello world!"));
diff --git a/src/corelib/doc/snippets/jni/src_qjniobject.cpp b/src/corelib/doc/snippets/jni/src_qjniobject.cpp
new file mode 100644
index 0000000000..6e66b51383
--- /dev/null
+++ b/src/corelib/doc/snippets/jni/src_qjniobject.cpp
@@ -0,0 +1,63 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [QJniObject scope]
+void functionScope()
+{
+ QString helloString("Hello");
+ jstring myJString = 0;
+ {
+ QJniObject string = QJniObject::fromString(helloString);
+ myJString = string.object<jstring>();
+ }
+
+ // Ops! myJString is no longer valid.
+}
+//! [QJniObject scope]
+
+//! [C++ native methods]
+static void fromJavaOne(JNIEnv *env, jobject thiz, jint x)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ qDebug() << x << "< 100";
+}
+
+static void fromJavaTwo(JNIEnv *env, jobject thiz, jint x)
+{
+ Q_UNUSED(env);
+ Q_UNUSED(thiz);
+ qDebug() << x << ">= 100";
+}
+
+void foo()
+{
+ // register the native methods first, ideally it better be done with the app start
+ const JNINativeMethod methods[] =
+ {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
+ {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
+ QJniEnvironment env;
+ env.registerNativeMethods("my/java/project/FooJavaClass", methods, 2);
+
+ // Call the java method which will calls back to the C++ functions
+ QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 10); // Output: 10 < 100
+ QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 100); // Output: 100 >= 100
+}
+//! [C++ native methods]
+
+//! [Java native methods]
+class FooJavaClass
+{
+ public static void foo(int x)
+ {
+ if (x < 100)
+ callNativeOne(x);
+ else
+ callNativeTwo(x);
+ }
+
+private static native void callNativeOne(int x);
+private static native void callNativeTwo(int x);
+
+}
+//! [Java native methods]
diff --git a/src/corelib/doc/snippets/ntfsp.cpp b/src/corelib/doc/snippets/ntfsp.cpp
index 099480302f..18f9bd0c5e 100644
--- a/src/corelib/doc/snippets/ntfsp.cpp
+++ b/src/corelib/doc/snippets/ntfsp.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
@@ -58,3 +11,18 @@ qt_ntfs_permission_lookup++; // turn checking on
qt_ntfs_permission_lookup--; // turn it off again
//! [1]
+//! [raii]
+void complexFunction()
+{
+ QNtfsPermissionCheckGuard permissionGuard; // check is enabled
+
+ // do complex things here that need permission check enabled
+
+} // as the guard goes out of scope the check is disabled
+//! [raii]
+
+//! [free-funcs]
+qAreNtfsPermissionChecksEnabled(); // check status
+qEnableNtfsPermissionChecks(); // turn checking on
+qDisableNtfsPermissionChecks(); // turn it off again
+//! [free-funcs]
diff --git a/src/corelib/doc/snippets/overview/using-qt-core.cmake b/src/corelib/doc/snippets/overview/using-qt-core.cmake
index a5f43c1472..6e4b8d8028 100644
--- a/src/corelib/doc/snippets/overview/using-qt-core.cmake
+++ b/src/corelib/doc/snippets/overview/using-qt-core.cmake
@@ -1,2 +1,2 @@
-find_package(Qt5 COMPONENTS Core REQUIRED)
-target_link_libraries(mytarget Qt5::Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+target_link_libraries(mytarget PRIVATE Qt6::Core)
diff --git a/src/corelib/doc/snippets/pointer/pointer.cpp b/src/corelib/doc/snippets/pointer/pointer.cpp
index 40c86d4fb2..2cc4529b85 100644
--- a/src/corelib/doc/snippets/pointer/pointer.cpp
+++ b/src/corelib/doc/snippets/pointer/pointer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QLabel>
diff --git a/src/corelib/doc/snippets/process/process.cpp b/src/corelib/doc/snippets/process/process.cpp
index 0449ee221c..ad7e4883e9 100644
--- a/src/corelib/doc/snippets/process/process.cpp
+++ b/src/corelib/doc/snippets/process/process.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QProcess>
diff --git a/src/corelib/doc/snippets/qbytearraylist/main.cpp b/src/corelib/doc/snippets/qbytearraylist/main.cpp
index fd52ef945b..d2164f326c 100644
--- a/src/corelib/doc/snippets/qbytearraylist/main.cpp
+++ b/src/corelib/doc/snippets/qbytearraylist/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 by Southwest Research Institute (R)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 by Southwest Research Institute (R)
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QByteArrayList>
diff --git a/src/corelib/doc/snippets/qbytearraylist/qbytearraylist.pro b/src/corelib/doc/snippets/qbytearraylist/qbytearraylist.pro
deleted file mode 100644
index 87397b491d..0000000000
--- a/src/corelib/doc/snippets/qbytearraylist/qbytearraylist.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-QT = core
-SOURCES = main.cpp
diff --git a/src/corelib/doc/snippets/qdebug/qdebugsnippet.cpp b/src/corelib/doc/snippets/qdebug/qdebugsnippet.cpp
index 90e7e618b5..33f6039995 100644
--- a/src/corelib/doc/snippets/qdebug/qdebugsnippet.cpp
+++ b/src/corelib/doc/snippets/qdebug/qdebugsnippet.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QtDebug>
diff --git a/src/corelib/doc/snippets/qdir-listfiles/main.cpp b/src/corelib/doc/snippets/qdir-listfiles/main.cpp
index 58d512b08e..236b32c73d 100644
--- a/src/corelib/doc/snippets/qdir-listfiles/main.cpp
+++ b/src/corelib/doc/snippets/qdir-listfiles/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include <QDir>
diff --git a/src/corelib/doc/snippets/qdir-namefilters/main.cpp b/src/corelib/doc/snippets/qdir-namefilters/main.cpp
index 500b32159e..b154c66310 100644
--- a/src/corelib/doc/snippets/qdir-namefilters/main.cpp
+++ b/src/corelib/doc/snippets/qdir-namefilters/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QDir>
#include <iostream>
diff --git a/src/corelib/doc/snippets/qelapsedtimer/main.cpp b/src/corelib/doc/snippets/qelapsedtimer/main.cpp
index 408c4eab07..b24e231a25 100644
--- a/src/corelib/doc/snippets/qelapsedtimer/main.cpp
+++ b/src/corelib/doc/snippets/qelapsedtimer/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtCore>
void slowOperation1()
diff --git a/src/corelib/doc/snippets/qloggingcategory/main.cpp b/src/corelib/doc/snippets/qloggingcategory/main.cpp
index f5c47b2ae8..8b3a61d51f 100644
--- a/src/corelib/doc/snippets/qloggingcategory/main.cpp
+++ b/src/corelib/doc/snippets/qloggingcategory/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCoreApplication>
#include <QLoggingCategory>
@@ -86,15 +39,20 @@ void myCategoryFilter(QLoggingCategory *);
//![20]
//![21]
-QLoggingCategory::CategoryFilter oldCategoryFilter;
+static QLoggingCategory::CategoryFilter oldCategoryFilter = nullptr;
void myCategoryFilter(QLoggingCategory *category)
{
- // configure driver.usb category here, otherwise forward to to default filter.
+ // For a category set up after this filter is installed, we first set it up
+ // with the old filter. This ensures that any driver.usb logging configured
+ // by the user is kept, aside from the one level we override; and any new
+ // categories we're not interested in get configured by the old filter.
+ if (oldCategoryFilter)
+ oldCategoryFilter(category);
+
+ // Tweak driver.usb's logging, over-riding the default filter:
if (qstrcmp(category->categoryName(), "driver.usb") == 0)
category->setEnabled(QtDebugMsg, true);
- else
- oldCategoryFilter(category);
}
//![21]
@@ -107,8 +65,6 @@ int main(int argc, char *argv[])
//![2]
//![22]
-
-// ...
oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
//![22]
@@ -175,6 +131,20 @@ oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
//![15]
}
+ {
+//![16]
+ QLoggingCategory category("driver.usb");
+ qCFatal(category) << "a fatal message. Program will be terminated!";
+//![16]
+ }
+
+ {
+//![17]
+ QLoggingCategory category("driver.usb");
+ qCFatal(category, "a fatal message. Program will be terminated!");
+//![17]
+ }
+
return 0;
}
diff --git a/src/corelib/doc/snippets/qmessageauthenticationcode/main.cpp b/src/corelib/doc/snippets/qmessageauthenticationcode/main.cpp
index f93b407761..21c55568ca 100644
--- a/src/corelib/doc/snippets/qmessageauthenticationcode/main.cpp
+++ b/src/corelib/doc/snippets/qmessageauthenticationcode/main.cpp
@@ -1,52 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Ruslan Nigmatullin <euroelessar@yandex.ru>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2016 Ruslan Nigmatullin <euroelessar@yandex.ru>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtCore>
@@ -60,13 +14,12 @@ int main(int argc, char *argv[])
//! [0]
//! [1]
- QMessageAuthenticationCode code(QCryptographicHash::Sha1);
- code.setKey(key);
+ QMessageAuthenticationCode code(QCryptographicHash::Sha256, key);
code.addData(message);
- code.result().toHex(); // returns "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
+ code.result().toHex(); // returns "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"
//! [1]
//! [2]
- QMessageAuthenticationCode::hash(message, key, QCryptographicHash::Sha1).toHex();
+ QMessageAuthenticationCode::hash(message, key, QCryptographicHash::Sha256).toHex();
//! [2]
}
diff --git a/src/corelib/doc/snippets/qmetaobject-invokable/main.cpp b/src/corelib/doc/snippets/qmetaobject-invokable/main.cpp
index 28ef7981d1..c2ef624b7b 100644
--- a/src/corelib/doc/snippets/qmetaobject-invokable/main.cpp
+++ b/src/corelib/doc/snippets/qmetaobject-invokable/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QDebug>
diff --git a/src/corelib/doc/snippets/qmetaobject-invokable/qmetaobject-invokable.pro b/src/corelib/doc/snippets/qmetaobject-invokable/qmetaobject-invokable.pro
deleted file mode 100644
index 4df19215f0..0000000000
--- a/src/corelib/doc/snippets/qmetaobject-invokable/qmetaobject-invokable.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-HEADERS = window.h
-SOURCES = main.cpp \
- window.cpp
diff --git a/src/corelib/doc/snippets/qmetaobject-invokable/window.cpp b/src/corelib/doc/snippets/qmetaobject-invokable/window.cpp
index 4061221857..f5ce70306d 100644
--- a/src/corelib/doc/snippets/qmetaobject-invokable/window.cpp
+++ b/src/corelib/doc/snippets/qmetaobject-invokable/window.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
diff --git a/src/corelib/doc/snippets/qmetaobject-invokable/window.h b/src/corelib/doc/snippets/qmetaobject-invokable/window.h
index 1ffc6df6ae..13ab49a6af 100644
--- a/src/corelib/doc/snippets/qmetaobject-invokable/window.h
+++ b/src/corelib/doc/snippets/qmetaobject-invokable/window.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/corelib/doc/snippets/qmetaobject-revision/main.cpp b/src/corelib/doc/snippets/qmetaobject-revision/main.cpp
index 4854657911..8081f979d3 100644
--- a/src/corelib/doc/snippets/qmetaobject-revision/main.cpp
+++ b/src/corelib/doc/snippets/qmetaobject-revision/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Research In Motion.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QMetaObject>
diff --git a/src/corelib/doc/snippets/qmetaobject-revision/qmetaobject-revision.pro b/src/corelib/doc/snippets/qmetaobject-revision/qmetaobject-revision.pro
deleted file mode 100644
index ec9d7db658..0000000000
--- a/src/corelib/doc/snippets/qmetaobject-revision/qmetaobject-revision.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-QT += widgets
-HEADERS = window.h
-SOURCES = main.cpp \
- window.cpp
diff --git a/src/corelib/doc/snippets/qmetaobject-revision/window.cpp b/src/corelib/doc/snippets/qmetaobject-revision/window.cpp
index b8c13d83ec..77950a5656 100644
--- a/src/corelib/doc/snippets/qmetaobject-revision/window.cpp
+++ b/src/corelib/doc/snippets/qmetaobject-revision/window.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Research In Motion.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
diff --git a/src/corelib/doc/snippets/qmetaobject-revision/window.h b/src/corelib/doc/snippets/qmetaobject-revision/window.h
index f519a6f2dc..d08780330f 100644
--- a/src/corelib/doc/snippets/qmetaobject-revision/window.h
+++ b/src/corelib/doc/snippets/qmetaobject-revision/window.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Research In Motion.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/corelib/doc/snippets/qmetatype/registerConverters.cpp b/src/corelib/doc/snippets/qmetatype/registerConverters.cpp
new file mode 100644
index 0000000000..f53d04b7a6
--- /dev/null
+++ b/src/corelib/doc/snippets/qmetatype/registerConverters.cpp
@@ -0,0 +1,62 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QJsonObject>
+#include <QMetaType>
+#include <QString>
+
+int main() {
+ //! [member]
+ struct Coordinates {
+ int x;
+ int y;
+ int z;
+
+ QString toString() const { return u"[x: %1; y: %2, z: %3]"_s.arg(QString::number(x),
+ QString::number(y),
+ QString::number(z)); }
+ };
+ QMetaType::registerConverter<Coordinates, QString>(&Coordinates::toString);
+ //! [member]
+
+ //! [memberOk]
+ struct BigNumber {
+ long long l;
+
+ int toInt(bool *ok = nullptr) const {
+ const bool canConvertSafely = l < std::numeric_limits<int>::max();
+ if (ok)
+ *ok = canConvertSafely;
+ return l;
+ }
+ };
+ QMetaType::registerConverter<BigNumber, int>(&BigNumber::toInt);
+ //! [memberOk]
+
+ //! [implicit]
+ class Counter {
+ int number = 0;
+ public:
+ int value() const { return number; }
+ operator int() const { return value(); }
+ void increment() {++number;}
+ };
+ QMetaType::registerConverter<Counter, int>();
+ //! [implicit]
+
+ struct CustomStringType {
+ const char *data() const {return nullptr;}
+ };
+ //! [unaryfunc]
+ QMetaType::registerConverter<CustomStringType, QString>([](const CustomStringType &str) {
+ return QString::fromUtf8(str.data());
+ });
+ QMetaType::registerConverter<QJsonValue, QPointF>(
+ [](const QJsonValue &value) -> std::optional<QPointF> {
+ const auto object = value.toObject();
+ if (!object.contains("x") || !object.contains("y"))
+ return std::nullopt; // The conversion fails if the required properties are missing
+ return QPointF{object["x"].toDouble(), object["y"].toDouble()};
+ });
+ //! [unaryfunc]
+}
diff --git a/src/corelib/doc/snippets/qprocess-environment/main.cpp b/src/corelib/doc/snippets/qprocess-environment/main.cpp
index 8e967582ba..f443f0074e 100644
--- a/src/corelib/doc/snippets/qprocess-environment/main.cpp
+++ b/src/corelib/doc/snippets/qprocess-environment/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtCore>
diff --git a/src/corelib/doc/snippets/qprocess/qprocess-createprocessargumentsmodifier.cpp b/src/corelib/doc/snippets/qprocess/qprocess-createprocessargumentsmodifier.cpp
index 4310864ff0..b084e99abd 100644
--- a/src/corelib/doc/snippets/qprocess/qprocess-createprocessargumentsmodifier.cpp
+++ b/src/corelib/doc/snippets/qprocess/qprocess-createprocessargumentsmodifier.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCoreApplication>
#include <QProcess>
diff --git a/src/corelib/doc/snippets/qprocess/qprocess-simpleexecution.cpp b/src/corelib/doc/snippets/qprocess/qprocess-simpleexecution.cpp
index 6e9febe2e4..0715108754 100644
--- a/src/corelib/doc/snippets/qprocess/qprocess-simpleexecution.cpp
+++ b/src/corelib/doc/snippets/qprocess/qprocess-simpleexecution.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QtGui>
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
index 879cdbe329..e2e97fa11c 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "buttonwidget.h"
@@ -58,10 +11,10 @@ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
{
signalMapper = new QSignalMapper(this);
- QGridLayout *gridLayout = new QGridLayout;
+ QGridLayout *gridLayout = new QGridLayout(this);
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
- connect(button, &QPushButton::clicked, signalMapper, &QSignalMapper::map);
+ connect(button, &QPushButton::clicked, signalMapper, qOverload<>(&QSignalMapper::map));
//! [0] //! [1]
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
@@ -70,8 +23,6 @@ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
connect(signalMapper, &QSignalMapper::mappedString,
//! [1] //! [2]
this, &ButtonWidget::clicked);
-
- setLayout(gridLayout);
}
//! [2]
@@ -79,13 +30,12 @@ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
: QWidget(parent)
{
- QGridLayout *gridLayout = new QGridLayout;
+ QGridLayout *gridLayout = new QGridLayout(this);
for (int i = 0; i < texts.size(); ++i) {
QString text = texts[i];
QPushButton *button = new QPushButton(text);
connect(button, &QPushButton::clicked, [this, text] { clicked(text); });
gridLayout->addWidget(button, i / 3, i % 3);
}
- setLayout(gridLayout);
}
//! [3]
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h
index b9d59f8dd8..537c21c914 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef BUTTONWIDGET_H
#define BUTTONWIDGET_H
@@ -55,7 +8,6 @@
class QSignalMapper;
class QString;
-class QStringList;
//! [0]
class ButtonWidget : public QWidget
diff --git a/src/corelib/doc/snippets/qsortfilterproxymodel-details/main.cpp b/src/corelib/doc/snippets/qsortfilterproxymodel-details/main.cpp
index 2a7b310716..962bece207 100644
--- a/src/corelib/doc/snippets/qsortfilterproxymodel-details/main.cpp
+++ b/src/corelib/doc/snippets/qsortfilterproxymodel-details/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QApplication>
@@ -55,7 +8,7 @@
class MyItemModel : public QStandardItemModel
{
public:
- MyItemModel(QWidget *parent = 0);
+ MyItemModel(QWidget *parent = nullptr);
};
MyItemModel::MyItemModel(QWidget *parent)
@@ -65,7 +18,7 @@ MyItemModel::MyItemModel(QWidget *parent)
class Widget : public QWidget
{
public:
- Widget(QWidget *parent = 0);
+ Widget(QWidget *parent = nullptr);
};
Widget::Widget(QWidget *parent)
diff --git a/src/corelib/doc/snippets/qstack/main.cpp b/src/corelib/doc/snippets/qstack/main.cpp
index 66823bcb59..f1f8e6a0fd 100644
--- a/src/corelib/doc/snippets/qstack/main.cpp
+++ b/src/corelib/doc/snippets/qstack/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <iostream>
diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp
index 39c4a8045b..8b39ae2f13 100644
--- a/src/corelib/doc/snippets/qstring/main.cpp
+++ b/src/corelib/doc/snippets/qstring/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QApplication>
@@ -55,7 +8,7 @@
class Widget : public QWidget
{
public:
- Widget(QWidget *parent = 0);
+ Widget(QWidget *parent = nullptr);
void constCharPointer();
void constCharArray();
@@ -85,11 +38,10 @@ public:
void isNullFunction();
void isEmptyFunction();
void lastIndexOfFunction();
- void leftFunction();
+ void firstFunction();
void leftJustifiedFunction();
- void leftRefFunction();
- void midFunction();
- void midRefFunction();
+ void slicedFunction();
+ void sliceFunction();
void numberFunction();
void prependFunction();
@@ -97,9 +49,8 @@ public:
void replaceFunction();
void reserveFunction();
void resizeFunction();
- void rightFunction();
+ void lastFunction();
void rightJustifiedFunction();
- void rightRefFunction();
void sectionFunction();
void setNumFunction();
void simplifiedFunction();
@@ -167,7 +118,7 @@ void Widget::atFunction()
//! [3]
QString str;
- for (int i = 0; i < str.size(); ++i) {
+ for (qsizetype i = 0; i < str.size(); ++i) {
if (str.at(i) >= QChar('a') && str.at(i) <= QChar('f'))
qDebug() << "Found character in range [a-f]";
}
@@ -200,7 +151,7 @@ void Widget::index()
{
//! [6]
QString str = "We must be <b>bold</b>, very <b>bold</b>";
- int j = 0;
+ qsizetype j = 0;
while ((j = str.indexOf("<b>", j)) != -1) {
qDebug() << "Found <b> tag at index position" << j;
@@ -396,7 +347,7 @@ void Widget::fromRawDataFunction()
static const QChar unicode[] = {
0x005A, 0x007F, 0x00A4, 0x0060,
0x1009, 0x0020, 0x0020};
- int size = sizeof(unicode) / sizeof(QChar);
+ qsizetype size = sizeof(unicode) / sizeof(QChar);
QString str = QString::fromRawData(unicode, size);
if (str.contains(pattern) {
@@ -481,11 +432,11 @@ void Widget::lastIndexOfFunction()
//! [94]
}
-void Widget::leftFunction()
+void Widget::firstFunction()
{
//! [31]
QString x = "Pineapple";
- QString y = x.left(4); // y == "Pine"
+ QString y = x.first(4); // y == "Pine"
//! [31]
}
@@ -502,12 +453,12 @@ void Widget::leftJustifiedFunction()
//! [33]
}
-void Widget::midFunction()
+void Widget::slicedFunction()
{
//! [34]
QString x = "Nine pineapples";
- QString y = x.mid(5, 4); // y == "pine"
- QString z = x.mid(5); // z == "pineapples"
+ QString y = x.sliced(5, 4); // y == "pine"
+ QString z = x.sliced(5); // z == "pineapples"
//! [34]
}
@@ -589,7 +540,7 @@ void Widget::reserveFunction()
{
//! [44]
QString result;
- int maxSize;
+ qsizetype maxSize;
bool condition;
QChar nextChar;
@@ -626,11 +577,11 @@ void Widget::resizeFunction()
//! [47]
}
-void Widget::rightFunction()
+void Widget::lastFunction()
{
//! [48]
QString x = "Pineapple";
- QString y = x.right(5); // y == "apple"
+ QString y = x.last(5); // y == "apple"
//! [48]
}
@@ -703,7 +654,7 @@ void Widget::sizeFunction()
{
//! [58]
QString str = "World";
- int n = str.size(); // n == 5
+ qsizetype n = str.size(); // n == 5
str.data()[0]; // returns 'W'
str.data()[4]; // returns 'd'
//! [58]
@@ -738,10 +689,10 @@ void Widget::splitCaseSensitiveFunction()
//! [62]
QString str = QStringLiteral("a,,b,c");
- QStringList list1 = str.split(QLatin1Char(','));
+ QStringList list1 = str.split(u',');
// list1: [ "a", "", "b", "c" ]
- QStringList list2 = str.split(QLatin1Char(','), Qt::SkipEmptyParts);
+ QStringList list2 = str.split(u',', Qt::SkipEmptyParts);
// list2: [ "a", "b", "c" ]
//! [62]
@@ -753,7 +704,7 @@ void Widget::splitCaseSensitiveFunction()
//! [62-slashes]
QString str = "/a/b/c/";
- auto parts = str.split(QLatin1Char('/'));
+ auto parts = str.split(u'/');
// parts: {"", "a", "b", "c", ""}
//! [62-slashes]
}
@@ -959,29 +910,13 @@ void Widget::arrayOperator()
//! [85]
}
-void Widget::midRefFunction()
+void Widget::sliceFunction()
{
- //! [midRef]
- QString x = "Nine pineapples";
- QStringRef y = x.midRef(5, 4); // y == "pine"
- QStringRef z = x.midRef(5); // z == "pineapples"
- //! [midRef]
-}
-
-void Widget::leftRefFunction()
-{
- //! [leftRef]
- QString x = "Pineapple";
- QStringRef y = x.leftRef(4); // y == "Pine"
- //! [leftRef]
-}
-
-void Widget::rightRefFunction()
-{
- //! [rightRef]
- QString x = "Pineapple";
- QStringRef y = x.rightRef(5); // y == "apple"
- //! [rightRef]
+ //! [86]
+ QString x = u"Nine pineapples"_s;
+ x.slice(5); // x == "pineapples"
+ x.slice(4, 3); // x == "app"
+ //! [86]
}
diff --git a/src/corelib/doc/snippets/qstring/stringbuilder.cpp b/src/corelib/doc/snippets/qstring/stringbuilder.cpp
index ca89c3a232..c3a709bd4c 100644
--- a/src/corelib/doc/snippets/qstring/stringbuilder.cpp
+++ b/src/corelib/doc/snippets/qstring/stringbuilder.cpp
@@ -1,72 +1,46 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QString>
+
+using namespace Qt::StringLiterals;
//! [0]
QString foo;
QString type = "long";
- foo->setText(QLatin1String("vector<") + type + QLatin1String(">::iterator"));
+ foo = "vector<"_L1 + type + ">::iterator"_L1;
if (foo.startsWith("(" + type + ") 0x"))
...
//! [0]
-//! [3]
- DEFINES *= QT_USE_QSTRINGBUILDER
-//! [3]
-
//! [5]
#include <QStringBuilder>
QString hello("hello");
- QStringRef el(&hello, 2, 3);
- QLatin1String world("world");
+ QStringView el = QStringView{ hello }.mid(2, 3);
+ QLatin1StringView world("world");
QString message = hello % el % world % QChar('!');
//! [5]
+
+//! [6]
+ QString str("QStringBuilder");
+
+ // "s" type is deduced as QStringBuilder<...>
+ auto s = "Like hot glue, " % str % " concatenates strings";
+
+ // Similarly the return type of this lambda is deduced as QStringBuilder<...>
+ auto concatenateStr = []() {
+ return "Like hot glue, " % str % " concatenates strings";
+ };
+//! [6]
+
+//! [7]
+ QString s = "Like hot glue, " % str % " concatenates strings";
+
+ // With a lambda, specify a trailing return type:
+ auto concatenateStr = []() -> QString {
+ return "Like hot glue, " % str % " concatenates strings";
+ };
+//! [7]
diff --git a/src/corelib/doc/snippets/qstringlist/main.cpp b/src/corelib/doc/snippets/qstringlist/main.cpp
index 5284a5fb78..1b7453cf6a 100644
--- a/src/corelib/doc/snippets/qstringlist/main.cpp
+++ b/src/corelib/doc/snippets/qstringlist/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <iostream>
@@ -55,7 +8,7 @@ using namespace std;
class Widget : public QWidget
{
public:
- Widget(QWidget *parent = 0);
+ Widget(QWidget *parent = nullptr);
};
Widget::Widget(QWidget *parent)
@@ -69,24 +22,6 @@ Widget::Widget(QWidget *parent)
fonts << "Courier" << "Verdana";
//! [0b]
-//! [1]
- for (int i = 0; i < fonts.size(); ++i)
- cout << fonts.at(i).toLocal8Bit().constData() << Qt::endl;
-//! [1]
-
-//! [2]
- QStringListIterator javaStyleIterator(fonts);
- while (javaStyleIterator.hasNext())
- cout << javaStyleIterator.next().toLocal8Bit().constData() << Qt::endl;
-//! [2]
-
-//! [3]
- QStringList::const_iterator constIterator;
- for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd();
- ++constIterator)
- cout << (*constIterator).toLocal8Bit().constData() << Qt::endl;
-//! [3]
-
//! [4]
QString str = fonts.join(", ");
// str == "Arial, Helvetica, Times, Courier"
@@ -131,7 +66,7 @@ Widget::Widget(QWidget *parent)
result.clear();
//! [12]
- foreach (const QString &str, list) {
+ for (const auto &str : std::as_const(list)) {
if (str.contains("Bill"))
result += str;
}
@@ -158,6 +93,13 @@ Widget::Widget(QWidget *parent)
// list == ["Bill Clinton", "Bill Murray"]
//! [17]
+ {
+//! [18]
+ QStringList veryLongList;
+ QStringMatcher matcher(u"Straße", Qt::CaseInsensitive);
+ QStringList filtered = veryLongList.filter(matcher);
+//! [18]
+ }
}
int main(int argc, char *argv[])
diff --git a/src/corelib/doc/snippets/qstringlistmodel/main.cpp b/src/corelib/doc/snippets/qstringlistmodel/main.cpp
index 4c9519d2b2..b0d14e110e 100644
--- a/src/corelib/doc/snippets/qstringlistmodel/main.cpp
+++ b/src/corelib/doc/snippets/qstringlistmodel/main.cpp
@@ -1,59 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
class Widget : public QWidget
{
public:
- Widget(QWidget *parent = 0);
+ Widget(QWidget *parent = nullptr);
};
Widget::Widget(QWidget *parent)
diff --git a/src/corelib/doc/snippets/qtcast/qtcast.cpp b/src/corelib/doc/snippets/qtcast/qtcast.cpp
index ba8582eabb..177446aff9 100644
--- a/src/corelib/doc/snippets/qtcast/qtcast.cpp
+++ b/src/corelib/doc/snippets/qtcast/qtcast.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QLabel>
#include <QPushButton>
diff --git a/src/corelib/doc/snippets/qversionnumber/main.cpp b/src/corelib/doc/snippets/qversionnumber/main.cpp
index 27b7b1a7ef..b78e14edf1 100644
--- a/src/corelib/doc/snippets/qversionnumber/main.cpp
+++ b/src/corelib/doc/snippets/qversionnumber/main.cpp
@@ -1,53 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Keith Gardner <kreios4004@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Keith Gardner <kreios4004@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QVersionNumber>
@@ -90,15 +43,15 @@ void QObject::parse()
{
//! [3]
QString string("5.4.0-alpha");
- int suffixIndex;
+ qsizetype suffixIndex;
QVersionNumber version = QVersionNumber::fromString(string, &suffixIndex);
// version is 5.4.0
// suffixIndex is 5
//! [3]
//! [3-latin1-1]
- QLatin1String string("5.4.0-alpha");
- int suffixIndex;
+ QLatin1StringView string("5.4.0-alpha");
+ qsizetype suffixIndex;
auto version = QVersionNumber::fromString(string, &suffixIndex);
// version is 5.4.0
// suffixIndex is 5
diff --git a/src/corelib/doc/snippets/qxmlstreamwriter/main.cpp b/src/corelib/doc/snippets/qxmlstreamwriter/main.cpp
index 5a300499ba..ccf536c413 100644
--- a/src/corelib/doc/snippets/qxmlstreamwriter/main.cpp
+++ b/src/corelib/doc/snippets/qxmlstreamwriter/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCoreApplication>
#include <QFile>
diff --git a/src/corelib/doc/snippets/resource-system/CMakeLists.txt b/src/corelib/doc/snippets/resource-system/CMakeLists.txt
new file mode 100644
index 0000000000..f0ec0f6816
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/CMakeLists.txt
@@ -0,0 +1,41 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+project(my_app)
+cmake_minimum_required(VERSION 3.16)
+find_package(Qt6 REQUIRED COMPONENTS Widgets Qml)
+
+#! [AUTORCC]
+set(CMAKE_AUTORCC ON)
+
+qt_add_executable(my_app
+ application.qrc
+ main.cpp
+)
+#! [AUTORCC]
+
+#! [qt_add_resources]
+qt_add_resources(my_app "app_images"
+ PREFIX "/"
+ FILES
+ images/copy.png
+ images/cut.png
+ images/new.png
+ images/open.png
+ images/paste.png
+ images/save.png
+)
+#! [qt_add_resources]
+
+#! [qt_add_big_resources]
+qt_add_big_resources(SOURCES application.qrc)
+target_sources(my_app PRIVATE ${SOURCES})
+#! [qt_add_big_resources]
+
+#! [qt_add_binary_resources]
+qt_add_binary_resources(resources application.qrc DESTINATION application.rcc)
+add_dependencies(my_app resources)
+#! [qt_add_binary_resources]
+
+target_link_libraries(my_app
+ PRIVATE Qt6::Qml Qt6::Widgets)
diff --git a/src/corelib/doc/snippets/resource-system/application.pro b/src/corelib/doc/snippets/resource-system/application.pro
index 0f451754f2..42c66eba4c 100644
--- a/src/corelib/doc/snippets/resource-system/application.pro
+++ b/src/corelib/doc/snippets/resource-system/application.pro
@@ -1,12 +1,26 @@
-QT += widgets
-
-HEADERS = mainwindow.h
-SOURCES = main.cpp \
- mainwindow.cpp
-#! [0]
-RESOURCES = application.qrc
-#! [0]
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/application
-INSTALLS += target
+TEMPLATE = app
+
+QT += qml widgets
+
+#! [0] #! [qrc]
+RESOURCES = application.qrc
+#! [0] #! [qrc]
+
+#! [1]
+resources.files = \
+ images/copy.png \
+ images/cut.png \
+ images/new.png \
+ images/open.png \
+ images/paste.png \
+ images/save.png
+resources.prefix = /
+
+RESOURCES = resources
+#! [1]
+
+#! [2]
+CONFIG += resources_big
+#! [2]
+
+SOURCES += main.cpp
diff --git a/src/corelib/doc/snippets/resource-system/application.qrc b/src/corelib/doc/snippets/resource-system/application.qrc
index 0a776fab4d..3eef379234 100644
--- a/src/corelib/doc/snippets/resource-system/application.qrc
+++ b/src/corelib/doc/snippets/resource-system/application.qrc
@@ -1,10 +1,10 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>images/copy.png</file>
- <file>images/cut.png</file>
- <file>images/new.png</file>
- <file>images/open.png</file>
- <file>images/paste.png</file>
- <file>images/save.png</file>
-</qresource>
+<RCC>
+ <qresource prefix="/">
+ <file>images/copy.png</file>
+ <file>images/cut.png</file>
+ <file>images/new.png</file>
+ <file>images/open.png</file>
+ <file>images/paste.png</file>
+ <file>images/save.png</file>
+ </qresource>
</RCC>
diff --git a/src/corelib/doc/snippets/resource-system/images/copy.png b/src/corelib/doc/snippets/resource-system/images/copy.png
new file mode 100644
index 0000000000..91a99b94e2
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/images/copy.png
Binary files differ
diff --git a/src/corelib/doc/snippets/resource-system/images/cut.png b/src/corelib/doc/snippets/resource-system/images/cut.png
new file mode 100644
index 0000000000..91a99b94e2
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/images/cut.png
Binary files differ
diff --git a/src/corelib/doc/snippets/resource-system/images/new.png b/src/corelib/doc/snippets/resource-system/images/new.png
new file mode 100644
index 0000000000..91a99b94e2
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/images/new.png
Binary files differ
diff --git a/src/corelib/doc/snippets/resource-system/images/open.png b/src/corelib/doc/snippets/resource-system/images/open.png
new file mode 100644
index 0000000000..91a99b94e2
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/images/open.png
Binary files differ
diff --git a/src/corelib/doc/snippets/resource-system/images/paste.png b/src/corelib/doc/snippets/resource-system/images/paste.png
new file mode 100644
index 0000000000..91a99b94e2
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/images/paste.png
Binary files differ
diff --git a/src/corelib/doc/snippets/resource-system/images/save.png b/src/corelib/doc/snippets/resource-system/images/save.png
new file mode 100644
index 0000000000..91a99b94e2
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/images/save.png
Binary files differ
diff --git a/src/corelib/doc/snippets/resource-system/main.cpp b/src/corelib/doc/snippets/resource-system/main.cpp
new file mode 100644
index 0000000000..7089ebf576
--- /dev/null
+++ b/src/corelib/doc/snippets/resource-system/main.cpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QQmlApplicationEngine>
+#include <QAction>
+#include <QIcon>
+#include <QApplication>
+#include <QWidget>
+
+class DummyWidget : public QWidget {
+ Q_OBJECT
+
+ QAction *cutAct;
+
+ DummyWidget() {
+ //! [QAction]
+ cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
+ //! [QAction]
+ }
+};
+
+int main()
+{
+//! [url]
+ QQmlApplicationEngine engine;
+ engine.load(QUrl("qrc:/myapp/main.qml"));
+//! [url]
+}
diff --git a/src/corelib/doc/snippets/resource-system/mainwindow.cpp b/src/corelib/doc/snippets/resource-system/mainwindow.cpp
index 6dc525304c..de98aa56ec 100644
--- a/src/corelib/doc/snippets/resource-system/mainwindow.cpp
+++ b/src/corelib/doc/snippets/resource-system/mainwindow.cpp
@@ -1,62 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
#include <QtWidgets>
#include "mainwindow.h"
-//! [0]
-
-//! [1]
MainWindow::MainWindow()
-//! [1] //! [2]
{
textEdit = new QPlainTextEdit;
setCentralWidget(textEdit);
@@ -74,11 +22,8 @@ MainWindow::MainWindow()
setCurrentFile(QString());
setUnifiedTitleAndToolBarOnMac(true);
}
-//! [2]
-//! [3]
void MainWindow::closeEvent(QCloseEvent *event)
-//! [3] //! [4]
{
if (maybeSave()) {
writeSettings();
@@ -87,22 +32,16 @@ void MainWindow::closeEvent(QCloseEvent *event)
event->ignore();
}
}
-//! [4]
-//! [5]
void MainWindow::newFile()
-//! [5] //! [6]
{
if (maybeSave()) {
textEdit->clear();
setCurrentFile(QString());
}
}
-//! [6]
-//! [7]
void MainWindow::open()
-//! [7] //! [8]
{
if (maybeSave()) {
QString fileName = QFileDialog::getOpenFileName(this);
@@ -110,11 +49,8 @@ void MainWindow::open()
loadFile(fileName);
}
}
-//! [8]
-//! [9]
bool MainWindow::save()
-//! [9] //! [10]
{
if (curFile.isEmpty()) {
return saveAs();
@@ -122,11 +58,8 @@ bool MainWindow::save()
return saveFile(curFile);
}
}
-//! [10]
-//! [11]
bool MainWindow::saveAs()
-//! [11] //! [12]
{
QString fileName = QFileDialog::getSaveFileName(this);
if (fileName.isEmpty())
@@ -134,42 +67,31 @@ bool MainWindow::saveAs()
return saveFile(fileName);
}
-//! [12]
-//! [13]
void MainWindow::about()
-//! [13] //! [14]
{
QMessageBox::about(this, tr("About Application"),
tr("The <b>Application</b> example demonstrates how to "
"write modern GUI applications using Qt, with a menu bar, "
"toolbars, and a status bar."));
}
-//! [14]
-//! [15]
void MainWindow::documentWasModified()
-//! [15] //! [16]
{
setWindowModified(textEdit->document()->isModified());
}
-//! [16]
-//! [17]
void MainWindow::createActions()
-//! [17] //! [18]
{
newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
-//! [19]
openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, &QAction::triggered, this, &MainWindow::open);
-//! [18] //! [19]
saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save);
@@ -181,10 +103,8 @@ void MainWindow::createActions()
saveAsAct->setStatusTip(tr("Save the document under a new name"));
connect(saveAsAct, &QAction::triggered, this, &MainWindow::saveAs);
-//! [20]
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);
-//! [20]
exitAct->setStatusTip(tr("Exit the application"));
connect(exitAct, &QAction::triggered, this, &MainWindow::close);
@@ -212,34 +132,24 @@ void MainWindow::createActions()
aboutAct->setStatusTip(tr("Show the application's About box"));
connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
-//! [22]
aboutQtAct = new QAction(tr("About &Qt"), this);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
-//! [22]
-//! [23]
cutAct->setEnabled(false);
-//! [23] //! [24]
copyAct->setEnabled(false);
connect(textEdit, &QTextEdit::copyAvailable,
cutAct, &QAction::setEnabled);
connect(textEdit, &QTextEdit::copyAvailable,
copyAct, &QAction::setEnabled);
}
-//! [24]
-//! [25] //! [26]
void MainWindow::createMenus()
-//! [25] //! [27]
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAct);
-//! [28]
fileMenu->addAction(openAct);
-//! [28]
fileMenu->addAction(saveAct);
-//! [26]
fileMenu->addAction(saveAsAct);
fileMenu->addSeparator();
fileMenu->addAction(exitAct);
@@ -255,16 +165,12 @@ void MainWindow::createMenus()
helpMenu->addAction(aboutAct);
helpMenu->addAction(aboutQtAct);
}
-//! [27]
-//! [29] //! [30]
void MainWindow::createToolBars()
{
fileToolBar = addToolBar(tr("File"));
fileToolBar->addAction(newAct);
-//! [29] //! [31]
fileToolBar->addAction(openAct);
-//! [31]
fileToolBar->addAction(saveAct);
editToolBar = addToolBar(tr("Edit"));
@@ -272,19 +178,13 @@ void MainWindow::createToolBars()
editToolBar->addAction(copyAct);
editToolBar->addAction(pasteAct);
}
-//! [30]
-//! [32]
void MainWindow::createStatusBar()
-//! [32] //! [33]
{
statusBar()->showMessage(tr("Ready"));
}
-//! [33]
-//! [34] //! [35]
void MainWindow::readSettings()
-//! [34] //! [36]
{
QSettings settings("QtProject", "Application Example");
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
@@ -292,21 +192,15 @@ void MainWindow::readSettings()
resize(size);
move(pos);
}
-//! [35] //! [36]
-//! [37] //! [38]
void MainWindow::writeSettings()
-//! [37] //! [39]
{
QSettings settings("QtProject", "Application Example");
settings.setValue("pos", pos());
settings.setValue("size", size());
}
-//! [38] //! [39]
-//! [40]
bool MainWindow::maybeSave()
-//! [40] //! [41]
{
if (textEdit->document()->isModified()) {
QMessageBox::StandardButton ret;
@@ -321,11 +215,8 @@ bool MainWindow::maybeSave()
}
return true;
}
-//! [41]
-//! [42]
void MainWindow::loadFile(const QString &fileName)
-//! [42] //! [43]
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
@@ -348,11 +239,8 @@ void MainWindow::loadFile(const QString &fileName)
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
}
-//! [43]
-//! [44]
bool MainWindow::saveFile(const QString &fileName)
-//! [44] //! [45]
{
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
@@ -376,11 +264,8 @@ bool MainWindow::saveFile(const QString &fileName)
statusBar()->showMessage(tr("File saved"), 2000);
return true;
}
-//! [45]
-//! [46]
void MainWindow::setCurrentFile(const QString &fileName)
-//! [46] //! [47]
{
curFile = fileName;
textEdit->document()->setModified(false);
@@ -391,12 +276,8 @@ void MainWindow::setCurrentFile(const QString &fileName)
shownName = "untitled.txt";
setWindowFilePath(shownName);
}
-//! [47]
-//! [48]
QString MainWindow::strippedName(const QString &fullFileName)
-//! [48] //! [49]
{
return QFileInfo(fullFileName).fileName();
}
-//! [49]
diff --git a/src/corelib/doc/snippets/settings/settings.cpp b/src/corelib/doc/snippets/settings/settings.cpp
index 49312b9cfc..c73b42b2a4 100644
--- a/src/corelib/doc/snippets/settings/settings.cpp
+++ b/src/corelib/doc/snippets/settings/settings.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
@@ -152,8 +105,7 @@ void MainWindow::writeSettings()
QSettings settings("Moose Soft", "Clipper");
settings.beginGroup("MainWindow");
- settings.setValue("size", size());
- settings.setValue("pos", pos());
+ settings.setValue("geometry", saveGeometry());
settings.endGroup();
}
//! [16]
@@ -164,8 +116,11 @@ void MainWindow::readSettings()
QSettings settings("Moose Soft", "Clipper");
settings.beginGroup("MainWindow");
- resize(settings.value("size", QSize(400, 400)).toSize());
- move(settings.value("pos", QPoint(200, 200)).toPoint());
+ const auto geometry = settings.value("geometry", QByteArray()).toByteArray();
+ if (geometry.isEmpty())
+ setGeometry(200, 200, 400, 400);
+ else
+ restoreGeometry(geometry)
settings.endGroup();
}
//! [17]
diff --git a/src/corelib/doc/snippets/sharedemployee/employee.h b/src/corelib/doc/snippets/sharedemployee/employee.h
index 3b8e7133b7..c44f71499e 100644
--- a/src/corelib/doc/snippets/sharedemployee/employee.h
+++ b/src/corelib/doc/snippets/sharedemployee/employee.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
diff --git a/src/corelib/doc/snippets/sharedemployee/main.cpp b/src/corelib/doc/snippets/sharedemployee/main.cpp
index d1f51425b7..f3684e38a8 100644
--- a/src/corelib/doc/snippets/sharedemployee/main.cpp
+++ b/src/corelib/doc/snippets/sharedemployee/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include "employee.h"
diff --git a/src/corelib/doc/snippets/signalsandslots/lcdnumber.h b/src/corelib/doc/snippets/signalsandslots/lcdnumber.h
index b311586e8f..f80b2186a8 100644
--- a/src/corelib/doc/snippets/signalsandslots/lcdnumber.h
+++ b/src/corelib/doc/snippets/signalsandslots/lcdnumber.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#ifndef LCDNUMBER_H
diff --git a/src/corelib/doc/snippets/signalsandslots/signalsandslots.cpp b/src/corelib/doc/snippets/signalsandslots/signalsandslots.cpp
index 31ed6ed08a..fe38a3222a 100644
--- a/src/corelib/doc/snippets/signalsandslots/signalsandslots.cpp
+++ b/src/corelib/doc/snippets/signalsandslots/signalsandslots.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "signalsandslots.h"
diff --git a/src/corelib/doc/snippets/signalsandslots/signalsandslots.h b/src/corelib/doc/snippets/signalsandslots/signalsandslots.h
index 760bc2c7b1..2f5a53231c 100644
--- a/src/corelib/doc/snippets/signalsandslots/signalsandslots.h
+++ b/src/corelib/doc/snippets/signalsandslots/signalsandslots.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef SIGNALSANDSLOTS_H
#define SIGNALSANDSLOTS_H
diff --git a/src/corelib/doc/snippets/statemachine/eventtest.cpp b/src/corelib/doc/snippets/statemachine/eventtest.cpp
deleted file mode 100644
index d7d4ce0d21..0000000000
--- a/src/corelib/doc/snippets/statemachine/eventtest.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-
-class MyTransition : public QAbstractTransition
-{
- Q_OBJECT
-public:
- MyTransition() {}
-
-protected:
-//![0]
- bool eventTest(QEvent *event) override
- {
- if (event->type() == QEvent::Wrapped) {
- QEvent *wrappedEvent = static_cast<QStateMachine::WrappedEvent *>(event)->event();
- if (wrappedEvent->type() == QEvent::KeyPress) {
- QKeyEvent *keyEvent = static_cast<QKeyEvent *>(wrappedEvent);
- // Do your event test
- }
- }
- return false;
- }
-//![0]
-
- void onTransition(QEvent *event) override
- {
-
- }
-};
-
-int main(int argv, char **args)
-{
- return 0;
-}
diff --git a/src/corelib/doc/snippets/statemachine/main.cpp b/src/corelib/doc/snippets/statemachine/main.cpp
deleted file mode 100644
index c399f4f199..0000000000
--- a/src/corelib/doc/snippets/statemachine/main.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtWidgets>
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
-
- QLabel *label = new QLabel;
- QPushButton *button = new QPushButton;
-
-//![0]
- QStateMachine machine;
- QState *s1 = new QState();
- QState *s2 = new QState();
- QState *s3 = new QState();
-//![0]
-
-//![4]
- s1->assignProperty(label, "text", "In state s1");
- s2->assignProperty(label, "text", "In state s2");
- s3->assignProperty(label, "text", "In state s3");
-//![4]
-
-//![5]
- QObject::connect(s3, &QState::entered, button, &QPushButton:showMaximized);
- QObject::connect(s3, &QState::exited, button, &QPushButton::showMinimized);
-//![5]
-
-//![1]
- s1->addTransition(button, &QPushButton::clicked, s2);
- s2->addTransition(button, &QPushButton::clicked, s3);
- s3->addTransition(button, &QPushButton::clicked, s1);
-//![1]
-
-//![2]
- machine.addState(s1);
- machine.addState(s2);
- machine.addState(s3);
- machine.setInitialState(s1);
-//![2]
-
-//![3]
- machine.start();
-//![3]
-
- label->show();
-
- return app.exec();
-}
diff --git a/src/corelib/doc/snippets/statemachine/main2.cpp b/src/corelib/doc/snippets/statemachine/main2.cpp
deleted file mode 100644
index dedd2d29bf..0000000000
--- a/src/corelib/doc/snippets/statemachine/main2.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtWidgets>
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
-
- QStateMachine machine;
-
-//![0]
- QState *s1 = new QState();
- QState *s11 = new QState(s1);
- QState *s12 = new QState(s1);
- QState *s13 = new QState(s1);
- s1->setInitialState(s11);
- machine.addState(s1);
-//![0]
-
-//![2]
- s12->addTransition(quitButton, &QPushButton::clicked, s12);
-//![2]
-
-//![1]
- QFinalState *s2 = new QFinalState();
- s1->addTransition(quitButton, &QPushButton::clicked, s2);
- machine.addState(s2);
- machine.setInitialState(s1);
-
- QObject::connect(&machine, &QStateMachine::finished,
- QCoreApplication::instance(), &QCoreApplication::quit);
-//![1]
-
- QButton *interruptButton = new QPushButton("Interrupt Button");
- QWidget *mainWindow = new QWidget();
-
-//![3]
- QHistoryState *s1h = new QHistoryState(s1);
-
- QState *s3 = new QState();
- s3->assignProperty(label, "text", "In s3");
- QMessageBox *mbox = new QMessageBox(mainWindow);
- mbox->addButton(QMessageBox::Ok);
- mbox->setText("Interrupted!");
- mbox->setIcon(QMessageBox::Information);
- QObject::connect(s3, &QState::entered, mbox, &QMessageBox::exec);
- s3->addTransition(s1h);
- machine.addState(s3);
-
- s1->addTransition(interruptButton, &QPushButton::clicked, s3);
-//![3]
-
- return app.exec();
-}
-
diff --git a/src/corelib/doc/snippets/statemachine/main3.cpp b/src/corelib/doc/snippets/statemachine/main3.cpp
deleted file mode 100644
index b665565aef..0000000000
--- a/src/corelib/doc/snippets/statemachine/main3.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
-
-//![0]
- QState *s1 = new QState(QState::ParallelStates);
- // s11 and s12 will be entered in parallel
- QState *s11 = new QState(s1);
- QState *s12 = new QState(s1);
-//![0]
-
-//![1]
- s1->addTransition(s1, &QState::finished, s2);
-//![1]
-
- return app.exec();
-}
-
diff --git a/src/corelib/doc/snippets/statemachine/main4.cpp b/src/corelib/doc/snippets/statemachine/main4.cpp
deleted file mode 100644
index e21656b91c..0000000000
--- a/src/corelib/doc/snippets/statemachine/main4.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-
-
-//![0]
-struct StringEvent : public QEvent
-{
- StringEvent(const QString &val)
- : QEvent(QEvent::Type(QEvent::User+1)),
- value(val) {}
-
- QString value;
-};
-//![0]
-
-//![1]
-class StringTransition : public QAbstractTransition
-{
- Q_OBJECT
-
-public:
- StringTransition(const QString &value)
- : m_value(value) {}
-
-protected:
- bool eventTest(QEvent *e) override
- {
- if (e->type() != QEvent::Type(QEvent::User+1)) // StringEvent
- return false;
- StringEvent *se = static_cast<StringEvent*>(e);
- return (m_value == se->value);
- }
-
- void onTransition(QEvent *) override {}
-
-private:
- QString m_value;
-};
-//![1]
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
-
-//![2]
- QStateMachine machine;
- QState *s1 = new QState();
- QState *s2 = new QState();
- QFinalState *done = new QFinalState();
-
- StringTransition *t1 = new StringTransition("Hello");
- t1->setTargetState(s2);
- s1->addTransition(t1);
- StringTransition *t2 = new StringTransition("world");
- t2->setTargetState(done);
- s2->addTransition(t2);
-
- machine.addState(s1);
- machine.addState(s2);
- machine.addState(done);
- machine.setInitialState(s1);
-//![2]
-
-//![3]
- machine.postEvent(new StringEvent("Hello"));
- machine.postEvent(new StringEvent("world"));
-//![3]
-
- return app.exec();
-}
-
-#include "main4.moc"
-
diff --git a/src/corelib/doc/snippets/statemachine/main5.cpp b/src/corelib/doc/snippets/statemachine/main5.cpp
deleted file mode 100644
index d701f51e2b..0000000000
--- a/src/corelib/doc/snippets/statemachine/main5.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
- QWidget *button;
-
- {
-//![0]
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QState *s1 = new QState();
- s1->assignProperty(object, "fooBar", 1.0);
- machine.addState(s1);
- machine.setInitialState(s1);
-
- QState *s2 = new QState();
- machine.addState(s2);
-//![0]
- }
-
- {
-
-//![2]
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QState *s1 = new QState();
- s1->assignProperty(object, "fooBar", 1.0);
- machine.addState(s1);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(s1);
- s2->assignProperty(object, "fooBar", 2.0);
- s1->setInitialState(s2);
-
- QState *s3 = new QState(s1);
-//![2]
-
- }
-
- {
-//![3]
- QState *s1 = new QState();
- QState *s2 = new QState();
-
- s1->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
- s2->assignProperty(button, "geometry", QRectF(0, 0, 100, 100));
-
- s1->addTransition(button, &QPushButton::clicked, s2);
-//![3]
-
- }
-
- {
-//![4]
- QState *s1 = new QState();
- QState *s2 = new QState();
-
- s1->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
- s2->assignProperty(button, "geometry", QRectF(0, 0, 100, 100));
-
- QSignalTransition *transition = s1->addTransition(button, &QPushButton::clicked, s2);
- transition->addAnimation(new QPropertyAnimation(button, "geometry"));
-//![4]
-
- }
-
- {
- QMainWindow *mainWindow = 0;
-
-//![5]
- QMessageBox *messageBox = new QMessageBox(mainWindow);
- messageBox->addButton(QMessageBox::Ok);
- messageBox->setText("Button geometry has been set!");
- messageBox->setIcon(QMessageBox::Information);
-
- QState *s1 = new QState();
-
- QState *s2 = new QState();
- s2->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
- connect(s2, &QState::entered, messageBox, SLOT(exec()));
-
- s1->addTransition(button, &QPushButton::clicked, s2);
-//![5]
- }
-
- {
- QMainWindow *mainWindow = 0;
-
-//![6]
- QMessageBox *messageBox = new QMessageBox(mainWindow);
- messageBox->addButton(QMessageBox::Ok);
- messageBox->setText("Button geometry has been set!");
- messageBox->setIcon(QMessageBox::Information);
-
- QState *s1 = new QState();
-
- QState *s2 = new QState();
- s2->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
-
- QState *s3 = new QState();
- connect(s3, &QState::entered, messageBox, SLOT(exec()));
-
- s1->addTransition(button, &QPushButton::clicked, s2);
- s2->addTransition(s2, &QState::propertiesAssigned, s3);
-//![6]
-
- }
-
- {
-
-//![7]
- QState *s1 = new QState();
- QState *s2 = new QState();
-
- s2->assignProperty(object, "fooBar", 2.0);
- s1->addTransition(s2);
-
- QStateMachine machine;
- machine.setInitialState(s1);
- machine.addDefaultAnimation(new QPropertyAnimation(object, "fooBar"));
-//![7]
-
- }
-
-
-
- return app.exec();
-}
-
diff --git a/src/corelib/doc/snippets/streaming/main.cpp b/src/corelib/doc/snippets/streaming/main.cpp
index 0c857b0528..a4f73526c5 100644
--- a/src/corelib/doc/snippets/streaming/main.cpp
+++ b/src/corelib/doc/snippets/streaming/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtCore>
#include <QByteArray>
diff --git a/src/corelib/doc/snippets/streaming/streaming.pro b/src/corelib/doc/snippets/streaming/streaming.pro
deleted file mode 100644
index 8c5eb91f05..0000000000
--- a/src/corelib/doc/snippets/streaming/streaming.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-SOURCES = main.cpp
-CONFIG += CONSOLE \ No newline at end of file
diff --git a/src/corelib/doc/snippets/threads/threads.cpp b/src/corelib/doc/snippets/threads/threads.cpp
index a748755a19..502bc4bfe0 100644
--- a/src/corelib/doc/snippets/threads/threads.cpp
+++ b/src/corelib/doc/snippets/threads/threads.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCache>
#include <QMutex>
@@ -54,9 +7,7 @@
#define Counter ReentrantCounter
-//! [3]
class Counter
-//! [3] //! [4]
{
public:
Counter() { n = 0; }
@@ -68,14 +19,11 @@ public:
private:
int n;
};
-//! [4]
#undef Counter
#define Counter ThreadSafeCounter
-//! [5]
class Counter
-//! [5] //! [6]
{
public:
Counter() { n = 0; }
@@ -88,7 +36,6 @@ private:
mutable QMutex mutex;
int n;
};
-//! [6]
typedef int SomeClass;
diff --git a/src/corelib/doc/snippets/timers/analogclock.cpp b/src/corelib/doc/snippets/timers/analogclock.cpp
index 3edfce3235..5241e57879 100644
--- a/src/corelib/doc/snippets/timers/analogclock.cpp
+++ b/src/corelib/doc/snippets/timers/analogclock.cpp
@@ -1,58 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "analogclock.h"
-//! [0] //! [1]
+// QTimer
+//! [0]
AnalogClock::AnalogClock(QWidget *parent)
//! [0] //! [2]
: QWidget(parent)
@@ -70,11 +24,24 @@ AnalogClock::AnalogClock(QWidget *parent)
resize(200, 200);
//! [7]
}
-//! [1] //! [7]
+//! [7]
+
+//! [analogclock-qchronotimer]
+AnalogClock::AnalogClock(QWidget *parent)
+
+ : QWidget(parent)
+{
+ auto *timer = new QChronoTimer(1s, this);
+ connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));
+ timer->start();
+ ...
+ ...
+ setWindowTitle(tr("Analog Clock"));
+ resize(200, 200);
+}
+//! [analogclock-qchronotimer]
-//! [8] //! [9]
void AnalogClock::paintEvent(QPaintEvent *)
-//! [8] //! [10]
{
static const QPoint hourHand[3] = {
QPoint(7, 8),
@@ -92,64 +59,40 @@ void AnalogClock::paintEvent(QPaintEvent *)
int side = qMin(width(), height());
QTime time = QTime::currentTime();
-//! [10]
-//! [11]
QPainter painter(this);
-//! [11] //! [12]
painter.setRenderHint(QPainter::Antialiasing);
-//! [12] //! [13]
painter.translate(width() / 2, height() / 2);
-//! [13] //! [14]
painter.scale(side / 200.0, side / 200.0);
-//! [9] //! [14]
-//! [15]
painter.setPen(Qt::NoPen);
-//! [15] //! [16]
painter.setBrush(hourColor);
-//! [16]
-//! [17] //! [18]
painter.save();
-//! [17] //! [19]
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
painter.drawConvexPolygon(hourHand, 3);
painter.restore();
-//! [18] //! [19]
-//! [20]
painter.setPen(hourColor);
-//! [20] //! [21]
for (int i = 0; i < 12; ++i) {
painter.drawLine(88, 0, 96, 0);
painter.rotate(30.0);
}
-//! [21]
-//! [22]
painter.setPen(Qt::NoPen);
-//! [22] //! [23]
painter.setBrush(minuteColor);
-//! [24]
painter.save();
painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
painter.drawConvexPolygon(minuteHand, 3);
painter.restore();
-//! [23] //! [24]
-//! [25]
painter.setPen(minuteColor);
-//! [25] //! [26]
-//! [27]
for (int j = 0; j < 60; ++j) {
if ((j % 5) != 0)
painter.drawLine(92, 0, 96, 0);
painter.rotate(6.0);
}
-//! [27]
}
-//! [26]
diff --git a/src/corelib/doc/snippets/timers/timers.cpp b/src/corelib/doc/snippets/timers/timers.cpp
index eb0c82c625..1a97ba535e 100644
--- a/src/corelib/doc/snippets/timers/timers.cpp
+++ b/src/corelib/doc/snippets/timers/timers.cpp
@@ -1,55 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QChronoTimer>
+#include <QObject>
#include <QTimer>
+using namespace std::chrono;
+
class Foo : public QObject
{
public:
@@ -82,7 +39,45 @@ Foo::Foo()
}
}
-int main()
+// QChronoTimer
+class MyWidget : QObject
{
+ MyWidget()
+ {
+//! [qchronotimer-singleshot]
+ MyWidget widget;
+ QChronoTimer::singleShot(200ms, &widget, &MyWidget::updateCaption);
+//! [qchronotimer-singleshot]
+//! [zero-timer]
+ // The default interval is 0ns
+ QChronoTimer *timer = new QChronoTimer(this);
+ connect(timer, &QChronoTimer::timeout, this, &MyWidget::processOneThing);
+ timer->start();
+//! [zero-timer]
+
+ {
+//! [timer-interval-in-ctor]
+ QChronoTimer *timer = new QChronoTimer(1s, this);
+ connect(timer, &QChronoTimer::timeout, this, &MyWidget::processOneThing);
+ timer->start();
+//! [timer-interval-in-ctor]
+ }
+
+ {
+//! [timer-setinterval]
+ QChronoTimer *timer = new QChronoTimer(this);
+ connect(timer, &QChronoTimer::timeout, this, &MyWidget::processOneThing);
+ timer->setInterval(1s);
+ timer->start();
+//! [timer-setinterval]
+ }
+ }
+
+public Q_SLOTS:
+ void processOneThing();
+};
+
+int main()
+{
}
diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc
index 9cbe50d4a9..3d6c1eefa2 100644
--- a/src/corelib/doc/src/animation.qdoc
+++ b/src/corelib/doc/src/animation.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group animation
@@ -46,162 +22,134 @@
\keyword Animation
- The animation framework aims to provide an easy way for creating animated
- and smooth GUIs. By animating Qt properties, the framework provides great
- freedom for animating widgets and other \l{QObject}s. The framework can
- also be used with the Graphics View framework. Many of the concepts
- available in the animation framework are also available in \l{Qt Quick},
- where it offers a declarative way of defining animations. Much of the
- knowledge acquired about the animation framework can be applied to
- \l{Qt Quick}.
+ The animation framework provides an easy way to animate your GUI elements.
+ It enables you to animate a Qt property value of a widget or QObject.
+ Most of the features offered by the framework are also available in
+ \l{Qt Quick}, where it's possible to define animations in a declarative way.
- In this overview, we explain the basics of its architecture. We
- also show examples of the most common techniques that the
- framework allows for animating \l{QObject}s and graphics items.
+ This overview explains the framework's architecture, with examples that
+ demonstrate the common techniques used for animating QObject and
+ GUI elements.
\tableofcontents
- \section1 The Animation Architecture
+ \section1 The Animation architecture
- We will in this section take a high-level look at the animation
- framework's architecture and how it is used to animate Qt
- properties. The following diagram shows the most important classes
- in the animation framework.
+ The following diagram shows the most important classes provided by the
+ framework:
\image animations-architecture.png
- The animation framework foundation consists of the base class
- QAbstractAnimation, and its two subclasses QVariantAnimation and
- QAnimationGroup. QAbstractAnimation is the ancestor of all
- animations. It represents basic properties that are common for all
- animations in the framework; notably, the ability to start, stop,
- and pause an animation. It is also receives the time change
- notifications.
-
- The animation framework further provides the QPropertyAnimation
- class, which inherits QVariantAnimation and performs animation of
- a Qt property, which is part of Qt's \l{Meta-Object
- System}{meta-object system}. The class performs an interpolation
- over the property using an easing curve. So when you want to
- animate a value, you can declare it as a property and make your
- class a QObject. Note that this gives us great freedom in
- animating already existing widgets and other \l{QObject}s.
+ It includes the QAbstractAnimation class, which provides the
+ necessary foundation for animations. This class defines the
+ generic properties for all animations supported by the framework.
+ For example, the ability to start, stop, and pause an animation. The
+ class also receives the time change notifications.
+
+ The framework further provides the QVariantAnimation and
+ QAnimationGroup classes, which build on their base case, QAbstractAnimation.
+ Next in the hierarchy is QPropertyAnimation, which is derived from
+ QVariantAnmiation, and it lets you animate a Qt property of a widget or
+ QObject. The class performs interpolation on the property value using an
+ easing curve. With these in place, you just need a QObject class with a
+ Qt property value that you can animate.
+
+ \note It is required that the target object you are animating is a QObject
+ or its subclass. This is necessary as the animation framework depends on the
+ \l{Meta-Object System}{meta-object system} for all the information about the
+ object it is animating.
Complex animations can be constructed by building a tree structure
- of \l{QAbstractAnimation}s. The tree is built by using
- \l{QAnimationGroup}s, which function as containers for other
- animations. Note also that the groups are subclasses of
- QAbstractAnimation, so groups can themselves contain other groups.
+ of \l{QAbstractAnimation}s, where the tree is a QAnimationGroup that
+ contains other animations. These animation groups can also contain
+ subgroups representing different groups or animations, such as
+ QParallelAnimationGroup and QSequentialAnimationGroup.
- The animation framework can be used on its own, but is also
- designed to be part of the state machine framework (See the
- \l{The State Machine Framework}{state machine framework} for an
- introduction to the Qt state machine). The state machine provides
- a special state that can play an animation. A QState can also set
- properties when the state is entered or exited, and this special
- animation state will interpolate between these values when given a
- QPropertyAnimation. We will look more closely at this later.
+ Behind the scenes, all animations are controlled by a global
+ timer, which sends \l{QAbstractAnimation::updateCurrentTime()}{updates} about
+ all animations that are running.
- Behind the scenes, the animations are controlled by a global
- timer, which sends \l{QAbstractAnimation::updateCurrentTime()}{updates} to
- all animations that are playing.
+ For detailed information of these individual classes' and their roles in
+ the framework, refer to their documentation.
- For detailed descriptions of the classes' function and roles in
- the framework, please look up their class descriptions.
+ \section1 Classes offered by the framework
- \section1 Classes in the Animation Framework
-
- These classes provide a framework for creating both simple and complex
- animations.
+ These classes provide the necessary infrastructure to create both simple and
+ complex animations.
\annotatedlist animation
- \section1 Animating Qt Properties
+ \section1 Animating Qt properties
- As mentioned in the previous section, the QPropertyAnimation class can
- interpolate over Qt properties. It is often this class that should be used
- for animation of values; in fact, its superclass, QVariantAnimation, has an
- empty implementation of \l{QVariantAnimation::}{updateCurrentValue()}, and
- does not change any value unless we change it ourselves on the
+ As the QPropertyAnimation class can interpolate on Qt properties, it is
+ used often. In fact, its superclass---QVariantAnimation---provides an
+ abstract implementation of \l{QVariantAnimation::}{updateCurrentValue()},
+ which does not change any value unless you change it on the
\l{QVariantAnimation::valueChanged()}{valueChanged signal}.
- A major reason we chose to animate Qt properties is that it
- presents us with freedom to animate already existing classes in
- the Qt API. Notably, the QWidget class (which we can also embed in
- a QGraphicsView) has properties for its bounds, colors, etc.
- Let's look at a small example:
-
- \code
- QPushButton button("Animated Button");
- button.show();
+ The framework lets you animate the Qt properties of the existing
+ classes in Qt. For example, the QWidget class---can be embedded in
+ a QGraphicsView---has properties for its bounds, colors, and so on.
+ The following example demonstrates how you can animate a QPushButton
+ widget:
- QPropertyAnimation animation(&button, "geometry");
- animation.setDuration(10000);
- animation.setStartValue(QRect(0, 0, 100, 30));
- animation.setEndValue(QRect(250, 250, 100, 30));
-
- animation.start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
- This code will move \c button from the top left corner of the
- screen to the position (250, 250) in 10 seconds (10000 milliseconds).
+ The example animates the \c pos Qt property of a QPushButton, to move
+ it from the top--left corner of the screen to the end position (250, 250),
+ in 10 seconds (10000 milliseconds).
- The example above will do a linear interpolation between the
- start and end value. It is also possible to set values
- situated between the start and end value. The interpolation
- will then go by these points.
+ It uses the linear interpolation method to control the speed of
+ animation between the start and end values. Try adding another value
+ in--between the start and end value to see how they are interpolated.
+ This time use the QPropertyAnimation::setKeyValueAt function to add
+ these values:
\code
- QPushButton button("Animated Button");
- button.show();
-
- QPropertyAnimation animation(&button, "geometry");
- animation.setDuration(10000);
-
- animation.setKeyValueAt(0, QRect(0, 0, 100, 30));
- animation.setKeyValueAt(0.8, QRect(250, 250, 100, 30));
- animation.setKeyValueAt(1, QRect(0, 0, 100, 30));
-
- animation.start();
+ ...
+ anim->setDuration(10000);
+ anim->setKeyValueAt(0, QPoint(0, 0));
+ anim->setKeyValueAt(0.8, QPoint(250, 250));
+ anim->setKeyValueAt(1, QPoint(0, 0));
+ ...
\endcode
- In this example, the animation will take the button to (250, 250)
- in 8 seconds, and then move it back to its original position in
- the remaining 2 seconds. The movement will be linearly
- interpolated between these points.
+ In this example, the animation moves the button to
+ (250, 250) in 8 seconds, and moves it back to its original position in
+ the remaining 2 seconds. The button's movement is linear-interpolated
+ between these points.
- You also have the possibility to animate values of a QObject
- that is not declared as a Qt property. The only requirement is
- that this value has a setter. You can then subclass the class
- containing the value and declare a property that uses this setter.
- Note that each Qt property requires a getter, so you will need to
- provide a getter yourself if this is not defined.
+ You can also animate a QObject's value that is not declared as a Qt
+ property, if the value has a setter method. In such cases, derive
+ a new class from the class that contains the value, and add a Qt property
+ for that value with the setter.
+
+ \note Each Qt property requires a getter also, so you should provide a
+ getter if that is not defined.
\code
class MyGraphicsRectItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT
- Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos)
};
\endcode
- In the above code example, we subclass QGraphicsRectItem and
- define a geometry property. We can now animate the widgets
- geometry even if QGraphicsRectItem does not provide the geometry
- property.
+ In this example, the \c MyGraphicsRectItem derives from
+ QGraphicsRectItem and QObject, and defines the \c pos property. You can
+ animate the item's \c pos even if QGraphicsRectItem does not provide
+ the \c pos property.
- For a general introduction to the Qt property system, see its
- \l{Qt's Property System}{overview}.
+ For a general introduction to the Qt property system, refer to
+ \l{Qt's Property System}.
\section1 Animations and the Graphics View Framework
- When you want to animate \l{QGraphicsItem}s, you also use
- QPropertyAnimation. However, QGraphicsItem does not inherit QObject.
- A good solution is to subclass the graphics item you wish to animate.
- This class will then also inherit QObject.
- This way, QPropertyAnimation can be used for \l{QGraphicsItem}s.
- The example below shows how this is done. Another possibility is
- to inherit QGraphicsWidget, which already is a QObject.
+ QPropertyAnimation can also be used to animate a QGraphicsItem, which does
+ not inherit QObject. In such cases, you derive a class from the graphics
+ item that you want to animate. This derived class should also inherit form
+ QObject to enable using QPropertyAnimation on a QGraphicsItem. The
+ following example shows how this is done:
\code
class Pixmap : public QObject, public QGraphicsPixmapItem
@@ -209,164 +157,78 @@
Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
...
+ }
\endcode
- As described in the previous section, we need to define
- properties that we wish to animate.
+ \note You can also derive from QGraphicsWidget, which already is a
+ QObject.
- Note that QObject must be the first class inherited as the
- meta-object system demands this.
+ As described in the previous section, you need to define
+ properties that you want to animate. The derived class must inherit
+ from QObject first as the meta-object system requires it.
- \section1 Easing Curves
+ \section1 Easing curves
- As mentioned, QPropertyAnimation performs an interpolation between
- the start and end property value. In addition to adding more key
- values to the animation, you can also use an easing curve. Easing
- curves describe a function that controls how the speed of the
- interpolation between 0 and 1 should be, and are useful if you
- want to control the speed of an animation without changing the
- path of the interpolation.
+ A QPropertyAnimation performs linear interpolation
+ between the start and end property values. In addition to adding more key
+ values to the animation, you can also choose an easing curve to control the
+ speed of interpolation between 0 and 1, without changing the
+ path.
- \code
- QPushButton button("Animated Button");
- button.show();
-
- QPropertyAnimation animation(&button, "geometry");
- animation.setDuration(3000);
- animation.setStartValue(QRect(0, 0, 100, 30));
- animation.setEndValue(QRect(250, 250, 100, 30));
- animation.setEasingCurve(QEasingCurve::OutBounce);
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp easing-curve
- animation.start();
- \endcode
-
- Here the animation will follow a curve that makes it bounce like a
- ball as if it was dropped from the start to the end position.
- QEasingCurve has a large collection of curves for you to choose
- from. These are defined by the QEasingCurve::Type enum. If you are
- in need of another curve, you can also implement one yourself, and
+ In this example, the animation follows a curve that makes the
+ \c button bounce like a ball. QEasingCurve offers a large collection of curves
+ to choose from the QEasingCurve::Type enum. If you want
+ to use another curve that is not available, implement one yourself and
register it with QEasingCurve.
- \omit Drop this for the first Lab release
- (Example of custom easing curve (without the actual impl of
- the function I expect)
- \endomit
-
- \section1 Putting Animations Together
+ \section1 Grouping animations
- An application will often contain more than one animation. For
- instance, you might want to move more than one graphics item
+ An application often contains more than one animation. For
+ example, it wants to move more than one graphics item
simultaneously or move them in sequence after each other.
- The subclasses of QAnimationGroup (QSequentialAnimationGroup and
- QParallelAnimationGroup) are containers for other animations so
+ The subclasses of QAnimationGroup---QSequentialAnimationGroup and
+ QParallelAnimationGroup---are containers for other animations so
that these animations can be animated either in sequence or
- parallel. The QAnimationGroup is an example of an animation that
- does not animate properties, but it gets notified of time changes
- periodically. This enables it to forward those time changes to its
- contained animations, and thereby controlling when its animations
- are played.
-
- Let's look at code examples that use both
- QSequentialAnimationGroup and QParallelAnimationGroup, starting
- off with the latter.
-
- \code
- QPushButton *bonnie = new QPushButton("Bonnie");
- bonnie->show();
-
- QPushButton *clyde = new QPushButton("Clyde");
- clyde->show();
+ parallel. The QAnimationGroup does not animate properties, but it
+ gets notified of time changes periodically. This enables it to
+ forward those time changes to the animation groups, which control when
+ their animations are played.
- QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "geometry");
- // Set up anim1
+ The two following examples demonstrate the use of both
+ QSequentialAnimationGroup and QParallelAnimationGroup:
- QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "geometry");
- // Set up anim2
-
- QParallelAnimationGroup *group = new QParallelAnimationGroup;
- group->addAnimation(anim1);
- group->addAnimation(anim2);
-
- group->start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group1
A parallel group plays more than one animation at the same time.
- Calling its \l{QAbstractAnimation::}{start()} function will start
- all animations it governs.
-
- \code
- QPushButton button("Animated Button");
- button.show();
+ Its \l{QAbstractAnimation::}{start()} function starts all
+ animations that are part of the group.
- QPropertyAnimation anim1(&button, "geometry");
- anim1.setDuration(3000);
- anim1.setStartValue(QRect(0, 0, 100, 30));
- anim1.setEndValue(QRect(500, 500, 100, 30));
-
- QPropertyAnimation anim2(&button, "geometry");
- anim2.setDuration(3000);
- anim2.setStartValue(QRect(500, 500, 100, 30));
- anim2.setEndValue(QRect(1000, 500, 100, 30));
-
- QSequentialAnimationGroup group;
-
- group.addAnimation(&anim1);
- group.addAnimation(&anim2);
-
- group.start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group2
- As you no doubt have guessed, QSequentialAnimationGroup plays
+ As the name suggests, a QSequentialAnimationGroup plays
its animations in sequence. It starts the next animation in
- the list after the previous is finished.
+ the list after the previous finishes.
- Since an animation group is an animation itself, you can add
- it to another group. This way, you can build a tree structure
- of animations which specifies when the animations are played
- in relation to each other.
+ A group is an animation itself, so you can add
+ it to another group. This way, building an animation tree, which define
+ when the animations are played in relation to each other.
- \section1 Animations and States
+ \section1 Object ownership
- When using a \l{The State Machine Framework}{state machine}, we
- can associate one or more animations to a transition between states
- using a QSignalTransition or QEventTransition class. These classes
- are both derived from QAbstractTransition, which defines the
- convenience function \l{QAbstractTransition::}{addAnimation()} that
- enables the appending of one or more animations triggered when the
- transition occurs.
+ A QPropertyAnimation should always have a parent that controls
+ its lifespan. A typical application may include several animations that
+ are grouped, where the animation group takes ownership of those animations.
+ An independent QPropertyAnimation must be explicitly assigned a parent to
+ control its lifespan. In the following example, you can see that an
+ independent QPropertyAnimation has the QApplication instance as its
+ parent:
- We also have the possibility to associate properties with the
- states rather than setting the start and end values ourselves.
- Below is a complete code example that animates the geometry of a
- QPushButton.
-
- \code
- QPushButton *button = new QPushButton("Animated Button");
- button->show();
-
- QStateMachine *machine = new QStateMachine;
-
- QState *state1 = new QState(machine);
- state1->assignProperty(button, "geometry", QRect(0, 0, 100, 30));
- machine->setInitialState(state1);
-
- QState *state2 = new QState(machine);
- state2->assignProperty(button, "geometry", QRect(250, 250, 100, 30));
-
- QSignalTransition *transition1 = state1->addTransition(button,
- &QPushButton::clicked, state2);
- transition1->addAnimation(new QPropertyAnimation(button, "geometry"));
-
- QSignalTransition *transition2 = state2->addTransition(button,
- &QPushButton::clicked, state1);
- transition2->addAnimation(new QPropertyAnimation(button, "geometry"));
-
- machine->start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
- For a more comprehensive example of how to use the state machine
- framework for animations, see the states example (it lives in the
- \c{examples/animation/states} directory).
+ \note You can also control the animation's lifespan by choosing a
+ \l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting it.
*/
diff --git a/src/corelib/doc/src/cbor.qdoc b/src/corelib/doc/src/cbor.qdoc
new file mode 100644
index 0000000000..30d7ddaf60
--- /dev/null
+++ b/src/corelib/doc/src/cbor.qdoc
@@ -0,0 +1,79 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \group cbor
+ \title CBOR Support in Qt
+ \ingroup qt-basic-concepts
+ \brief An overview of CBOR support in Qt.
+ \ingroup explanations-dataprocessingandio
+
+ \ingroup frameworks-technologies
+
+ \keyword CBOR
+
+ Qt provides support for dealing with CBOR data. CBOR is a binary format to
+ store data that has a superset of the types available in JSON, but is more
+ compact.
+
+ The CBOR support in Qt provides an easy to use C++ API to parse,
+ modify and save CBOR data.
+
+ More details about the CBOR data format can be found in \l {RFC 7049}.
+
+ \tableofcontents
+
+ \section1 Overview
+
+ CBOR is a format to store structured data. It has three groups of built-in types:
+
+ \list
+ \li Basic types: integers, floating point, boolean, null, etc.
+ \li String-like types: strings and byte arrays
+ \li Containers: arrays and maps
+ \endlist
+
+ In addition, CBOR can add a "tag" to extend the meaning of the type. The
+ container types can contain basic types, string-like types and containers.
+
+ \sa {Parsing and displaying CBOR data}, {Serialization Converter}, {Saving and Loading a Game}
+
+ \section1 The CBOR Classes
+
+ \section2 The QCborValue Class
+
+ The QCborValue class represents any CBOR type. It also has a simple API for
+ reading and writing to QCborStreamReader and QCborStreamWriter objects, as
+ well as manipulating such objects in memory, with the help of QCborArray
+ and QCborMap. The CborValue API is simplified from the full CBOR data type
+ and always represents all integers as \l qint64 and all floating-point as
+ \c double. This means QCborValue is unable to represent CBOR integer values
+ outside of the range of \l qint64 (-2^63 to 2^63-1). When creating a CBOR
+ stream, QCborValue::toCbor() can be configured to attempt to write the
+ shorter single- and half-precision floating-point representations.
+
+ \section2 The QCborArray Class
+
+ The QCborArray class is used to hold an array of QCborValue objects. A
+ QCborValue object can contain a QCborArray object. It has functions for
+ converting to and from QVariantList, QStringList, QJsonArray.
+
+ \section2 The QCborMap Class
+
+ The QCborMap class is used to hold an map of QCborValue objects. A
+ QCborValue object can contain a QCborMap object. It has functions for
+ converting to and from QVariantMap, QVariantMap, and QJsonObject, but it
+ can have keys of any type, not just QString.
+
+ \section2 The QCborStreamReader Class
+
+ The QCborStreamReader class is a low level API for reading CBOR data from a
+ QIODevice, a QByteArray, or a pointer to memory. It has an API similar to
+ the QXmlStreamReader class.
+
+ \section2 The QCborStreamWriter Class
+
+ The QCborStreamWriter class is a low level API for writing CBOR data to a
+ QIODevice or a QByteArray. It has an API similar to the QXmlStreamWriter
+ class.
+*/
diff --git a/src/corelib/doc/src/cmake-macros.qdoc b/src/corelib/doc/src/cmake-macros.qdoc
deleted file mode 100644
index 8788554616..0000000000
--- a/src/corelib/doc/src/cmake-macros.qdoc
+++ /dev/null
@@ -1,416 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
-\page qtcore-cmake-qt5-wrap-cpp.html
-\ingroup cmake-macros-qtcore
-
-\title qt5_wrap_cpp
-
-\brief Creates \c{.moc} files from sources.
-
-\section1 Synopsis
-
-\badcode
-qt5_wrap_cpp(<VAR> src_file1 [src_file2 ...]
- [TARGET target]
- [OPTIONS ...]
- [DEPENDS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_wrap_cpp.qdocinc description
-
-\note For compatibility with Qt 6, the command is also available under the name \l qt_wrap_cpp.
-
-\section1 Arguments
-
-\include includes/qt_wrap_cpp.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt5_wrap_cpp
-*/
-
-/*!
-\page qtcore-cmake-qt-wrap-cpp.html
-\ingroup cmake-macros-qtcore
-
-\title qt_wrap_cpp
-
-\brief Creates \c{.moc} files from sources.
-
-\section1 Synopsis
-
-\badcode
-qt_wrap_cpp(<VAR> src_file1 [src_file2 ...]
- [TARGET target]
- [OPTIONS ...]
- [DEPENDS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_wrap_cpp.qdocinc description
-
-This command was introduced in Qt 5.15. You can use \l qt5_wrap_cpp in older versions of Qt.
-
-\section1 Arguments
-
-\include includes/qt_wrap_cpp.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt_wrap_cpp
-*/
-
-/*!
-\page qtcore-cmake-qt5-add-resources.html
-\ingroup cmake-macros-qtcore
-
-\title qt5_add_resources
-
-\brief Compiles binary resources into source code.
-
-\section1 Synopsis
-
-\badcode
-qt5_add_resources(<VAR> file1.qrc [file2.qrc ...]
- [OPTIONS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_add_resources.qdocinc arguments
-
-For embedding bigger resources, see \l qt5_add_big_resources.
-
-\note For compatibility with Qt 6, the command is also available under the name \l qt_add_resources.
-
-\section1 Arguments
-
-\include includes/qt_add_resources.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt5_add_resources
-*/
-
-/*!
-\page qtcore-cmake-qt-add-resources.html
-\ingroup cmake-macros-qtcore
-
-\title qt_add_resources
-
-\brief Compiles binary resources into source code.
-
-\section1 Synopsis
-
-\badcode
-qt_add_resources(<VAR> file1.qrc [file2.qrc ...]
- [OPTIONS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_add_resources.qdocinc arguments
-
-For embedding bigger resources, see \l qt_add_big_resources.
-
-This command was introduced in Qt 5.15. You can use \l qt5_add_resources in older versions of Qt.
-
-\section1 Arguments
-
-\include includes/qt_add_resources.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt_add_resources
-*/
-
-/*!
-\page qtcore-cmake-qt5-add-big-resources.html
-\ingroup cmake-macros-qtcore
-
-\title qt5_add_big_resources
-
-\brief Compiles big binary resources into object code.
-
-\section1 Synopsis
-
-\badcode
-qt5_add_big_resources(<VAR> file1.qrc [file2.qrc ...]
- [OPTIONS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_add_big_resources.qdocinc description
-
-\note For compatibility with Qt 6, the command is also available under the name \l qt_add_big_resources.
-
-\section1 Arguments
-
-\include includes/qt_add_big_resources.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt5_add_big_resources
-*/
-
-/*!
-\page qtcore-cmake-qt-add-big-resources.html
-\ingroup cmake-macros-qtcore
-
-\title qt_add_big_resources
-
-\brief Compiles big binary resources into object code.
-
-\section1 Synopsis
-
-\badcode
-qt_add_big_resources(<VAR> file1.qrc [file2.qrc ...]
- [OPTIONS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_add_big_resources.qdocinc description
-
-This command was introduced in Qt 5.15. You can use \l qt5_add_big_resources in older versions of Qt.
-
-\section1 Arguments
-
-\include includes/qt_add_big_resources.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt_add_big_resources
-*/
-
-/*!
-\page qtcore-cmake-qt5_add_binary_resources.html
-\ingroup cmake-macros-qtcore
-
-\title qt5_add_binary_resources
-
-\brief Creates an \c{RCC} file from a list of Qt resource files.
-
-\section1 Synopsis
-
-\badcode
-qt5_add_binary_resources(target file1.qrc [file2.qrc ...]
- [DESTINATION ...]
- [OPTIONS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_add_binary_resources.qdocinc description
-
-\note For compatibility with Qt 6, the command is also available under the name \l qt_add_binary_resources.
-
-\section1 Arguments
-
-\include includes/qt_add_binary_resources.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt5_add_binary_resources
-*/
-
-/*!
-\page qtcore-cmake-qt_add_binary_resources.html
-\ingroup cmake-macros-qtcore
-
-\title qt_add_binary_resources
-
-\brief Creates an \c{RCC} file from a list of Qt resource files.
-
-\section1 Synopsis
-
-\badcode
-qt_add_binary_resources(target file1.qrc [file2.qrc ...]
- [DESTINATION ...]
- [OPTIONS ...])
-\endcode
-
-\section1 Description
-
-\include includes/qt_add_binary_resources.qdocinc description
-
-This command was introduced in Qt 5.15. You can use \l qt5_add_binary_resources in older versions of Qt.
-
-\section1 Arguments
-
-\include includes/qt_add_binary_resources.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt_add_binary_resources
-*/
-
-/*!
-\page qtcore-cmake-qt5-generate-moc.html
-\ingroup cmake-macros-qtcore
-
-\title qt5_generate_moc
-
-\brief Calls moc on an input file.
-
-\section1 Synopsis
-
-\badcode
-qt5_generate_moc(src_file dest_file
- [TARGET target])
-\endcode
-
-\section1 Description
-
-\include includes/qt_generate_moc.qdocinc description
-
-\note For compatibility with Qt 6, the command is also available under the name \l qt_generate_moc.
-
-\section1 Arguments
-
-\include includes/qt_generate_moc.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt5_generate_moc
-*/
-
-/*!
-\page qtcore-cmake-qt-generate-moc.html
-\ingroup cmake-macros-qtcore
-
-\title qt_generate_moc
-
-\brief Calls moc on an input file.
-
-\section1 Synopsis
-
-\badcode
-qt_generate_moc(src_file dest_file
- [TARGET target])
-\endcode
-
-\section1 Description
-
-\include includes/qt_generate_moc.qdocinc description
-
-This command was introduced in Qt 5.15. You can use \l qt5_generate_moc in older versions of Qt.
-
-\section1 Arguments
-
-\include includes/qt_generate_moc.qdocinc arguments
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt_generate_moc
-*/
-
-/*!
-\page qtcore-cmake-qt5-import-plugins.html
-\ingroup cmake-macros-qtcore
-
-\title qt5_import_plugins
-
-\brief Specifies a custom set of plugins to import for a static Qt build
-
-\section1 Synopsis
-
-\badcode
-qt5_import_plugins(target
- [INCLUDE plugin ...]
- [EXCLUDE plugin ...]
- [INCLUDE_BY_TYPE plugin_type plugin ...]
- [EXCLUDE_BY_TYPE plugin_type])
-\endcode
-
-\section1 Description
-
-\include includes/qt_import_plugins.qdocinc description
-
-\note For compatibility with Qt 6, the command is also available under the name \l qt_import_plugins.
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt5_import_plugins
-
-In the snippet above, the following occurs with the executable \c myapp:
-
-\list
-\li The \c Qt5::QCocoaIntegrationPlugin is imported into myapp.
-\li The \c Qt5::QMinimalIntegrationPlugin plugin is
- excluded from being automatically imported into myapp.
-\li The default list of plugins for \c imageformats is
- overridden to only include Qt5::QGifPlugin and Qt5::QJpegPlugin.
-\li All \c sqldrivers plugins are excluded from automatic importing.
-\endlist
-*/
-
-/*!
-\page qtcore-cmake-qt-import-plugins.html
-\ingroup cmake-macros-qtcore
-
-\title qt_import_plugins
-
-\brief Specifies a custom set of plugins to import for a static Qt build
-
-\section1 Synopsis
-
-\badcode
-qt_import_plugins(target
- [INCLUDE plugin ...]
- [EXCLUDE plugin ...]
- [INCLUDE_BY_TYPE plugin_type plugin ...]
- [EXCLUDE_BY_TYPE plugin_type])
-\endcode
-
-\section1 Description
-
-\include includes/qt_import_plugins.qdocinc description
-
-This command was introduced in Qt 5.15. You can use \l qt5_import_plugins in older versions of Qt.
-
-\section1 Examples
-
-\snippet cmake-macros/examples.cmake qt_import_plugins
-
-In the snippet above, the following occurs with the executable \c myapp:
-
-\list
-\li The \c Qt::QCocoaIntegrationPlugin is imported into myapp.
-\li The \c Qt::QMinimalIntegrationPlugin plugin is
- excluded from being automatically imported into myapp.
-\li The default list of plugins for \c imageformats is
- overridden to only include Qt::QGifPlugin and Qt::QJpegPlugin.
-\li All \c sqldrivers plugins are excluded from automatic importing.
-\endlist
-*/
diff --git a/src/corelib/doc/src/cmake/cmake-commands.qdoc b/src/corelib/doc/src/cmake/cmake-commands.qdoc
new file mode 100644
index 0000000000..e185bab624
--- /dev/null
+++ b/src/corelib/doc/src/cmake/cmake-commands.qdoc
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\group cmake-commands-qtcore
+\title CMake Commands in Qt6 Core
+\brief Lists CMake commands defined in Qt6::Core.
+
+The following CMake commands are defined when Qt6::Core is loaded, for instance
+with
+
+\code
+find_package(Qt6 REQUIRED COMPONENTS Core)
+\endcode
+
+\sa{CMake Command Reference}
+*/
diff --git a/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc b/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc
new file mode 100644
index 0000000000..b710ba7275
--- /dev/null
+++ b/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc
@@ -0,0 +1,587 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/* NOTE: The variables documented here are available when running CMake, they
+** are not available in a deployment script. Both these and the set of
+** deploy-time variables are all members of the cmake-variables-qtcore
+** group.
+**/
+
+/*!
+\group cmake-variables-qtcore
+\title CMake Variables in Qt6 Core
+\brief Lists CMake variables defined in Qt6::Core.
+
+The following CMake variables are defined when Qt6::Core is loaded, for instance
+with
+
+\badcode
+find_package(Qt6 REQUIRED COMPONENTS Core)
+\endcode
+
+\sa{CMake Variable Reference}
+*/
+
+/*!
+\page cmake-variable-android-ndk-host-system-name.html
+\ingroup cmake-variables-qtcore
+
+\title ANDROID_NDK_HOST_SYSTEM_NAME
+\target cmake-variable-ANDROID_NDK_HOST_SYSTEM_NAME
+
+\summary {Android-specific architecture of the host system.}
+
+\cmakevariablesince 6.0
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Usually, this variable is set by the Android NDK toolchain file. It is written out as
+part of the deployment settings for a target.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-variable-android-sdk-root.html
+\ingroup cmake-variables-qtcore
+
+\title ANDROID_SDK_ROOT
+\target cmake-variable-ANDROID_SDK_ROOT
+
+\summary {Location of the Android SDK.}
+
+\cmakevariablesince 6.0
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Specifies the location of the Android SDK when building for the Android platform.
+This variable is written out as part of the deployment settings for a target.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}.
+*/
+
+/*!
+\page cmake-variable-qt-android-application-arguments.html
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-manifest-properties
+
+\title QT_ANDROID_APPLICATION_ARGUMENTS
+\target cmake-variable-QT_ANDROID_APPLICATION_ARGUMENTS
+
+\summary {List of arguments to pass to Android applications.}
+
+\cmakevariablesince 6.0
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Contains a list of arguments to be passed to Android applications. This variable
+is written out as part of the deployment settings for a target.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-variable-qt-android-deployment-type.html
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_DEPLOYMENT_TYPE
+\target cmake-variable-QT_ANDROID_DEPLOYMENT_TYPE
+
+\summary {Forces or disables release package signing regardless of the build type.}
+
+\cmakevariablesince 6.7
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+When set to \c Release, the \c --release flag is passed to the \c
+androiddeployqt tool, regardless of the application build type. When set to
+another value, the \c --release flag is never passed to the tool, which
+effectively disables release package signing even in Release or RelWithDebInfo
+builds. When not set, the default behavior is to use release package signing in
+build types other than Debug.
+
+\sa {androiddeployqt}
+*/
+
+/*!
+\page cmake_variable-qt-android-multi-abi-forward-vars
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_MULTI_ABI_FORWARD_VARS
+\target cmake-variable-QT_ANDROID_MULTI_ABI_FORWARD_VARS
+
+\summary {Allows to share CMake variables in multi-ABI builds.}
+
+\cmakevariablesince 6.4.2
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Allows specifying the list of
+CMake variables that need to be forwarded from the main ABI project to
+ABI-specific subprojects. Due to the specifics of the Multi-ABI project build
+process, there is no generic way to forward the CMake cache variables
+that are specified either in the command line or in another similar way.
+
+A typical use case for the variable is propagating CMake cache variables
+specified in the command line. For example, a project has two variables
+\c{PROJECT_WIDE_VARIABLE1} and \c{PROJECT_WIDE_VARIABLE2} that affect the
+project configuration:
+\badcode
+cmake_minimum_required(VERSION 3.18)
+
+project(MyProject LANGUAGES CXX)
+
+find_package(Qt6 REQUIRED COMPONENTS Core)
+
+qt_add_executable(MyApp main.cpp)
+
+if(PROJECT_WIDE_VARIABLE1)
+ target_sources(MyApp PRIVATE sourcefile1.cpp)
+endif()
+if(PROJECT_WIDE_VARIABLE2)
+ target_sources(MyApp PRIVATE sourcefile2.cpp)
+endif()
+\endcode
+
+The above contents of \c{CMakeLists.txt} enable you to control how
+\c{MyApp} is built by setting the corresponding CMake variables from the
+command line:
+\badcode
+qt-cmake -S<source directory> -B<build directory> \
+ -DPROJECT_WIDE_VARIABLE1=ON \
+ -DPROJECT_WIDE_VARIABLE2=ON \
+ -DQT_ANDROID_MULTI_ABI_FORWARD_VARS="PROJECT_WIDE_VARIABLE1;PROJECT_WIDE_VARIABLE2"
+\endcode
+
+When configuring the application for desktop, \c{PROJECT_WIDE_VARIABLE1} and
+\c{PROJECT_WIDE_VARIABLE2} are visible in CMake listings and scripts as global
+cache variables. This doesn't work for Android Multi-ABI builds because
+ABI-specific subprojects do not inherit the cache variables from the main-ABI
+project. This issue can be solved by passing the list of required variables to
+the \c{QT_ANDROID_MULTI_ABI_FORWARD_VARS} variable, so both
+\c{PROJECT_WIDE_VARIABLE1} and \c{PROJECT_WIDE_VARIABLE2} values will be
+propagated to the ABI-specific builds.
+
+The variable can be also defined in the project's CMakeLists.txt:
+\badcode
+...
+qt_add_executable(MyApp main.cpp)
+...
+if(ANDROID)
+ set(QT_ANDROID_MULTI_ABI_FORWARD_VARS "PROJECT_WIDE_VARIABLE1;PROJECT_WIDE_VARIABLE2")
+endif()
+...
+\endcode
+
+Set the variable in this way to have a predefined set of
+variables that will always be forwarded to ABI-specific projects.
+
+\note The forwarding is done in the target finalizer, which is implicitly
+called when \l{qt6_add_executable}{qt_add_executable()} is used. The
+finalization occurs automatically when using CMake 3.19 or later.
+
+\sa {qt6_finalize_target}{qt_finalize_target()},
+ {qt6_add_executable}{qt_add_executable()}
+*/
+
+/*!
+\page cmake-variable-qt-android-build-all-abis.html
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_BUILD_ALL_ABIS
+\target cmake-variable-QT_ANDROID_BUILD_ALL_ABIS
+
+\summary {Enables building multi-ABI packages using the autodetected Qt for Android SDK list.}
+
+\cmakevariablesince 6.3
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Automatically detects available ABIs of Qt for Android and uses them to
+build a package. The automatic detection expects the default directory structure
+supplied by the Qt installer, with the corresponding naming of the directories.
+\include cmake-android-supported-abis.qdocinc
+The typical directory structure looks as below:
+\badcode
+/path/to/Qt/6.x.x
+ android_armv7
+ android_arm64_v8a
+ android_x86
+ android_x86_64
+ ...
+\endcode
+The auto-detected paths can be customized using one of \c{QT_PATH_ANDROID_ABI_<ABI>} variables.
+
+The variable is set to \c FALSE by default.
+
+\sa{QT_PATH_ANDROID_ABI_<ABI>}
+*/
+
+/*!
+\page cmake-variable-qt-android-abis.html
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_ABIS
+\target cmake-variable-QT_ANDROID_ABIS
+
+\summary {List of ABIs that the project packages are built for.}
+
+\cmakevariablesince 6.3
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Specifies a list of ABIs to be used to build the project packages.
+\include cmake-android-supported-abis.qdocinc
+Each ABI should have the corresponding Qt for Android either installed or
+user-built. To specify the path to the Qt for Android ABI, use
+the corresponding \c{QT_PATH_ANDROID_ABI_<ABI>} variable.
+
+\note \c{QT_ANDROID_BUILD_ALL_ABIS} has the higher priority and ignores the
+QT_ANDROID_ABIS logic.
+
+\sa{QT_PATH_ANDROID_ABI_<ABI>}, {QT_ANDROID_BUILD_ALL_ABIS}
+*/
+
+/*!
+\page cmake-variable-qt-path-android-abi.html
+\ingroup cmake-variables-qtcore
+
+\title QT_PATH_ANDROID_ABI_<ABI>
+\target cmake-variable-QT_PATH_ANDROID_ABI_<ABI>
+
+\summary {Set of variables to specify the path to Qt for Android for the corresponding ABI.}
+
+\cmakevariablesince 6.3
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Each variable can be used to specify the path to Qt for Android for the corresponding ABI.
+\include cmake-android-supported-abis.qdocinc
+
+\sa{cmake-variable-QT_ANDROID_ABIS}{QT_ANDROID_ABIS}
+*/
+
+/*!
+\page cmake-variable-qt-android-sign-aab.html
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_SIGN_AAB
+\target cmake-variable-QT_ANDROID_SIGN_AAB
+
+\summary {Signs the .aab package with the specified keystore, alias, and store password.}
+\cmakevariablesince 6.4
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Signs the resulting package. The path of the keystore file, the alias of the key, and passwords
+have to be specified by additional environment variables:
+\badcode
+ QT_ANDROID_KEYSTORE_PATH
+ QT_ANDROID_KEYSTORE_ALIAS
+ QT_ANDROID_KEYSTORE_STORE_PASS
+ QT_ANDROID_KEYSTORE_KEY_PASS
+\endcode
+The mentioned variables are used internally by \l{androiddeployqt}.
+
+\sa{androiddeployqt}
+*/
+
+/*!
+\page cmake-variable-qt-android-sign-apk.html
+\ingroup cmake-variables-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_SIGN_APK
+\target cmake-variable-QT_ANDROID_SIGN_APK
+
+\summary {Signs the package with the specified keystore, alias, and store password.}
+\cmakevariablesince 6.4
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+Signs the resulting package. The path of the keystore file, the alias of the key, and passwords
+have to be specified by additional environment variables:
+\badcode
+ QT_ANDROID_KEYSTORE_PATH
+ QT_ANDROID_KEYSTORE_ALIAS
+ QT_ANDROID_KEYSTORE_STORE_PASS
+ QT_ANDROID_KEYSTORE_KEY_PASS
+\endcode
+The mentioned variables are used internally by \l{androiddeployqt}.
+
+\sa{androiddeployqt}
+*/
+
+/*!
+\page cmake-variable-qt-use-target-android-build-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_USE_TARGET_ANDROID_BUILD_DIR
+\target cmake-variable-QT_USE_TARGET_ANDROID_BUILD_DIR
+
+\summary {Enables the use of per-target Android build directories.}
+
+\cmakevariablesince 6.7
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+The variable appends the target-specific suffix to the android-build directory.
+The variable only takes an effect when it's set in \c CACHE. The variable is
+only supported by Qt Creator starting from version 13.
+If a single \c CMakeLists.txt contains more than one Android executable and
+this option is not set, you will see a warning. To disable the warning, set
+\c QT_SKIP_ANDROID_BUILD_DIR_CHECK to \c TRUE.
+*/
+
+/*!
+\page cmake-variable-qt-no-collect-build-tree-apk-deps.html
+\ingroup cmake-variables-qtcore
+
+\title QT_NO_COLLECT_BUILD_TREE_APK_DEPS
+\target cmake-variable-QT_NO_COLLECT_BUILD_TREE_APK_DEPS
+
+\summary {Prevents collecting of project-built shared library targets during Android deployment.}
+
+\cmakevariablesince 6.3
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+During project finalization, the build system collects the locations of
+all built shared library targets in the project.
+These locations are passed to \l androiddeployqt for deployment consideration when
+resolving dependencies between libraries.
+To disable this behavior, set this variable to \c TRUE.
+
+\sa {qt6_finalize_project}{qt_finalize_project()}
+\sa {cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS}{QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS}
+*/
+
+/*!
+\page cmake-variable-qt-no-collect-imported-target-apk-deps.html
+\ingroup cmake-variables-qtcore
+
+\title QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS
+\target cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS
+
+\summary {Prevents collecting of imported targets during Android deployment.}
+
+\cmakevariablesince 6.5
+\preliminarycmakevariable
+\cmakevariableandroidonly
+
+When using CMake version 3.21 or later, the build system collects the locations of
+imported shared library targets that might be relevant for deployment.
+The collected targets are those that are reachable from the directory scope
+of the currently processed executable target. That includes the target's source directory
+scope and its parents.
+The collected locations are passed to \l androiddeployqt for deployment consideration when
+resolving dependencies between libraries.
+To disable this behavior, set this variable to \c TRUE.
+
+\sa {qt6_finalize_project}{qt_finalize_project()}
+\sa {cmake-variable-QT_NO_COLLECT_BUILD_TREE_APK_DEPS}{QT_NO_COLLECT_BUILD_TREE_APK_DEPS}
+*/
+
+/*!
+\page cmake-variable-qt-host-path.html
+\ingroup cmake-variables-qtcore
+
+\title QT_HOST_PATH
+\target cmake-variable-QT_HOST_PATH
+
+\summary {Location of the host Qt installation when cross-compiling.}
+
+\cmakevariablesince 6.0
+
+When cross-compiling, this variable must be set to the install location of Qt for the host
+platform. It is used to locate tools to be run on the host (\l{moc}, \l{rcc},
+\l{androiddeployqt}, and so on). It's possible to reuse pre-installed tools
+when compiling Qt for host systems too, by using \c QT_HOST_PATH that points to
+a pre-installed host Qt and setting the \c QT_FORCE_FIND_TOOLS to \c ON. The Qt
+versions should match in this case.
+*/
+
+/*!
+\page cmake-variable-qt-no-set-xcode-development-team-id.html
+\ingroup cmake-variables-qtcore
+
+\title QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID
+\target cmake-variable-QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID
+
+\summary {Disables providing a fallback team ID during target finalization on iOS.}
+
+\cmakevariablesince 6.1
+
+When finalizing an executable target on iOS,
+\l{qt6_finalize_target}{qt_finalize_target()} will populate the target's
+\c XCODE_ATTRIBUTE_DEVELOPMENT_TEAM property if it hasn't been set.
+To prevent this, set \c QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID to \c TRUE.
+*/
+
+/*!
+\page cmake-variable-qt-no-set-xcode-bundle-identifier.html
+\ingroup cmake-variables-qtcore
+
+\title QT_NO_SET_XCODE_BUNDLE_IDENTIFIER
+\target cmake-variable-QT_NO_SET_XCODE_BUNDLE_IDENTIFIER
+
+\summary {Disables providing a fallback app bundle ID during target finalization on iOS.}
+
+\cmakevariablesince 6.1
+
+When finalizing an executable target on iOS,
+\l{qt6_finalize_target}{qt_finalize_target()} will populate the target's
+\c XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER and
+\c MACOSX_BUNDLE_GUI_IDENTIFIER properties if they haven't been set.
+To prevent this, set \c QT_NO_SET_XCODE_BUNDLE_IDENTIFIER to \c TRUE.
+*/
+
+/*!
+\page cmake-variable-qt-enable-verbose-deployment.html
+\ingroup cmake-variables-qtcore
+
+\title QT_ENABLE_VERBOSE_DEPLOYMENT
+\target cmake-variable-QT_ENABLE_VERBOSE_DEPLOYMENT
+
+\summary {Enables verbose mode of deployment tools.}
+
+\cmakevariablesince 6.3
+\preliminarycmakevariable
+
+Enables verbose mode of the \l androiddeployqt deployment tool when it is called
+internally at build time, usually during target finalization.
+
+This variable also changes the default verbosity of install-time deployment
+scripts for other platforms (see \l{qt6_deploy_runtime_dependencies()}), but it
+must be set before the first \c{find_package(Qt6)} call to have that effect.
+*/
+
+/*!
+\page cmake-variable-qt-deploy-support.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_SUPPORT
+\target cmake-variable-QT_DEPLOY_SUPPORT
+
+\summary {Name of the file to include for setting up deployment support.}
+
+\cmakevariablesince 6.3
+\preliminarycmakevariable
+\note The value of this variable should never be modified by project code.
+
+This configure-phase variable is set by the Core package. It is intended to be
+used as the first line of any deployment script to ensure access to the
+deployment APIs provided by Qt. Such deployment scripts do not run during
+CMake's configure phase. They are executed during installation or as
+part of a post-build rule.
+
+The following example shows one way the variable would be used when installing
+an application, along with its runtime dependencies:
+
+\include cmake-deploy-modified-variable-values.qdocinc
+
+\sa {qt6_deploy_runtime_dependencies}{qt_deploy_runtime_dependencies()},
+ {qt6_deploy_qml_imports}{qt_deploy_qml_imports()}
+*/
+
+/*!
+\page cmake-variable-qt-no-standard-project-setup.html
+\ingroup cmake-variables-qtcore
+
+\title QT_NO_STANDARD_PROJECT_SETUP
+\target cmake-variable-QT_NO_STANDARD_PROJECT_SETUP
+
+\summary {Prevents subsequent calls to qt_standard_project_setup() from making any changes.}
+
+\cmakevariablesince 6.3
+
+The \l{qt6_standard_project_setup}{qt_standard_project_setup()} command is
+typically called in the top level \c{CMakeLists.txt} file of a project. In some
+scenarios, such a project may be absorbed as a child project of a larger project
+hierarchy. A parent project may want to prevent any child project from applying
+changes to the setup. The parent project can achieve this by setting
+\c{QT_NO_STANDARD_PROJECT_SETUP} to \c TRUE before bringing in the child project
+via \l{add_subdirectory()}, \l{FetchContent_MakeAvailable()}, or other similar
+methods provided by CMake.
+
+\sa {qt6_standard_project_setup}{qt_standard_project_setup()}
+*/
+
+/*!
+\page cmake-variable-qt-i18n-languages.html
+\ingroup cmake-variables-qtcore
+
+\title QT_I18N_TRANSLATED_LANGUAGES
+\target cmake-variable-QT_I18N_TRANSLATED_LANGUAGES
+
+\summary {List of languages to be used for project internationalization.}
+
+\cmakevariablesince 6.7
+
+Specifies a list of languages that are used for project
+internationalization. The single languages must be compatible with the
+string-based \l QLocale constructor.
+
+The languages in \c QT_I18N_TRANSLATED_LANGUAGES are used to:
+\list
+ \li Set up executable targets for consuming \c{.qm} files.
+ \li Automatically construct \c{.ts} file names in
+ \l{qt6_add_translations}{qt_add_translations()}.
+\endlist
+
+This variable can be conveniently set with the
+\l {qt6_standard_project_setup}{qt_standard_project_setup()} command.
+
+By default, translatable strings are considered to be written in \c{en}.
+
+\sa {qt6_standard_project_setup}{qt_standard_project_setup()}
+\sa {qt6_add_translations}{qt_add_translations()}
+*/
+
+/*!
+\page cmake-variable-qt-i18n-native-language.html
+\ingroup cmake-variables-qtcore
+
+\title QT_I18N_SOURCE_LANGUAGE
+\target cmake-variable-QT_I18N_SOURCE_LANGUAGE
+
+\summary {Specifies the language of translatable strings.}
+
+\cmakevariablesince 6.7
+
+Specifies the language of translatable strings in the source code.
+The language must be compatible with the string-based \l QLocale constructor.
+
+Together with \c{QT_I18N_TRANSLATED_LANGUAGES}, this variable is used to determine the
+names of \c{.ts} files for \l{qt6_add_translations}{qt_add_translations()}.
+
+This variable can be conveniently set with the
+\l {qt6_standard_project_setup}{qt_standard_project_setup()} command.
+
+\sa {qt6_standard_project_setup}{qt_standard_project_setup()}
+\sa {qt6_add_translations}{qt_add_translations()}
+*/
+
+/*!
+\page cmake-variable-qt-ios-launch-screen.html
+\ingroup cmake-variables-qtcore
+
+\title QT_IOS_LAUNCH_SCREEN
+\target cmake-variable-QT_IOS_LAUNCH_SCREEN
+
+\summary {Path to iOS launch screen storyboard used by all targets.}
+
+\cmakevariablesince 6.4
+\preliminarycmakevariable
+\cmakevariableiosonly
+
+Specifies the path to an iOS launch screen storyboard file that will be used
+by all targets within a project.
+
+\sa {Launch Screens and Launch Images}
+*/
diff --git a/src/corelib/doc/src/cmake/cmake-deploy-variables.qdoc b/src/corelib/doc/src/cmake/cmake-deploy-variables.qdoc
new file mode 100644
index 0000000000..ac5094e7cb
--- /dev/null
+++ b/src/corelib/doc/src/cmake/cmake-deploy-variables.qdoc
@@ -0,0 +1,307 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/* NOTE: The variables documented here are available when running a deploy
+** script, they are not available at configure time (i.e. when running
+** CMake). Both these and the set of configure-time variables are all
+** members of the cmake-variables-qtcore group.
+**/
+
+/*!
+\page cmake-variable-qt-deploy-prefix.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_PREFIX
+\target cmake-variable-QT_DEPLOY_PREFIX
+
+\summary {Base location for a deployment.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.3
+
+\c{QT_DEPLOY_PREFIX} provides the base deployment directory. The other
+\c{QT_DEPLOY_..._DIR} variables should be treated as relative to this location.
+The value of \c{QT_DEPLOY_PREFIX} may be relative or absolute, so projects
+should not assume one or the other in any given situation. A relative path is
+expected to be treated as relative to the current working directory, as seen
+by the build tool (ninja, make, and so on) at install time.
+
+The default value is \c{$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}}, which is the
+base location CMake uses during installation. If that evaluates to an empty
+string, the default value will be a dot (.) instead, which is generally the
+appropriate value when deploying as part of a post-build rule. This two-step
+fallback logic ensures that projects can assume \c{QT_DEPLOY_PREFIX} will not
+be an empty string, so it can safely be used as part of a path like
+\c{${QT_DEPLOY_PREFIX}/${QT_DEPLOY_BIN_DIR}}.
+
+To change the value of \c QT_DEPLOY_PREFIX, the project can be configured
+with a custom \l CMAKE_INSTALL_PREFIX as described in
+\l {Command Line cmake invocation}.
+
+The \l DESTDIR environment variable can also be used to modify the final
+installation, and thus deployment, location.
+
+Projects should rarely need to use this variable. In typical scenarios, deploy
+scripts should assume that the working directory is already set to the base
+install location and just use the prefix-relative \c{QT_DEPLOY_..._DIR}
+variables.
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_BIN_DIR, QT_DEPLOY_LIBEXEC_DIR,
+ QT_DEPLOY_LIB_DIR, QT_DEPLOY_PLUGINS_DIR, QT_DEPLOY_QML_DIR,
+ QT_DEPLOY_TRANSLATIONS_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-bin-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_BIN_DIR
+\target cmake-variable-QT_DEPLOY_BIN_DIR
+
+\summary {Prefix-relative subdirectory for deploying runtime binaries on some target platforms.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.3
+
+Projects should use \c QT_DEPLOY_BIN_DIR in their deploy scripts to avoid
+hard-coding a particular directory in which to deploy the following types of
+binaries:
+
+\list
+\li Executables on all platforms.
+\li DLLs on Windows.
+\endlist
+
+\c QT_DEPLOY_BIN_DIR defaults to the value of \c${CMAKE_INSTALL_BINDIR}
+(usually \c{bin}), which is provided by CMake's \l{GNUInstallDirs} module.
+To change the value of \c QT_DEPLOY_BIN_DIR, ensure that the project sets
+\c{CMAKE_INSTALL_BINDIR} before the \c Core package is found.
+
+The \c QT_DEPLOY_BIN_DIR path is relative to \l{QT_DEPLOY_PREFIX}.
+
+This variable is not meaningful when deploying into a macOS app bundle and
+should not be used for that scenario.
+
+\section1 Example
+
+\include cmake-deploy-runtime-dependencies.qdocinc
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_PREFIX, QT_DEPLOY_LIBEXEC_DIR,
+ QT_DEPLOY_LIB_DIR, QT_DEPLOY_PLUGINS_DIR, QT_DEPLOY_QML_DIR,
+ QT_DEPLOY_TRANSLATIONS_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-libexec-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_LIBEXEC_DIR
+\target cmake-variable-QT_DEPLOY_LIBEXEC_DIR
+
+\summary {Prefix-relative subdirectory for deploying program executables on some target platforms.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.7
+
+On Unix derivatives, projects should use \c QT_DEPLOY_LIBEXEC_DIR in their
+deploy scripts to avoid hard-coding a particular directory in which to deploy
+helper executables that are local to the project.
+
+For example, projects using QtWebEngine would deploy the \c QtWebEngineProcess
+executable to this directory.
+
+\c QT_DEPLOY_LIBEXEC_DIR defaults to the value of \c${CMAKE_INSTALL_LIBEXECDIR}
+(usually \c{libexec}), which is provided by CMake's \l{GNUInstallDirs} module.
+To change the value of \c QT_DEPLOY_LIBEXEC_DIR, ensure that the project sets
+\c{CMAKE_INSTALL_LIBEXECDIR} before the \c Core package is found.
+
+The \c QT_DEPLOY_LIBEXEC_DIR path is relative to \l{QT_DEPLOY_PREFIX}.
+
+This variable is not meaningful when deploying into a macOS app bundle and
+should not be used for that scenario.
+
+\section1 Example
+
+\include cmake-deploy-modified-variable-values.qdocinc
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_PREFIX, QT_DEPLOY_BIN_DIR, QT_DEPLOY_LIB_DIR,
+ QT_DEPLOY_PLUGINS_DIR, QT_DEPLOY_QML_DIR, QT_DEPLOY_TRANSLATIONS_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-lib-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_LIB_DIR
+\target cmake-variable-QT_DEPLOY_LIB_DIR
+
+\summary {Prefix-relative subdirectory for deploying libraries on some target platforms.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.3
+
+Projects should use \c QT_DEPLOY_LIB_DIR in their deploy scripts to avoid
+hard-coding a particular directory in which to deploy the following types of
+binaries:
+
+\list
+\li Shared libraries on platforms other than Windows.
+\li Import libraries on Windows.
+\endlist
+
+\c QT_DEPLOY_LIB_DIR defaults to the value of \c${CMAKE_INSTALL_LIBDIR}
+(usually \c{lib} or \c{lib64}), which is provided by
+CMake's \l{GNUInstallDirs} module.
+To change the value of \c QT_DEPLOY_LIB_DIR, ensure that the project sets
+\c{CMAKE_INSTALL_LIBDIR} before the \c Core package is found.
+
+The \c QT_DEPLOY_LIB_DIR path is relative to \l{QT_DEPLOY_PREFIX}.
+
+This variable is not meaningful when deploying into a macOS app bundle and
+should not be used for that scenario.
+
+\section1 Example
+
+\include cmake-deploy-modified-variable-values.qdocinc
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_PREFIX, QT_DEPLOY_BIN_DIR,
+ QT_DEPLOY_PLUGINS_DIR, QT_DEPLOY_QML_DIR, QT_DEPLOY_TRANSLATIONS_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-plugins-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_PLUGINS_DIR
+\target cmake-variable-QT_DEPLOY_PLUGINS_DIR
+
+\summary {Prefix-relative subdirectory for deploying Qt plugins on some target platforms.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.3
+
+Projects should use \c QT_DEPLOY_PLUGINS_DIR in their deploy scripts to avoid
+hard-coding a particular directory under which to deploy plugins.
+
+\c QT_DEPLOY_PLUGINS_DIR defaults to the value \c{plugins}. To change the value
+of \c QT_DEPLOY_PLUGINS_DIR, set it in the project deployment script
+before \c QT_DEPLOY_SUPPORT is included.
+
+The \c QT_DEPLOY_PLUGINS_DIR path is relative to \l{QT_DEPLOY_PREFIX}.
+
+This variable is not meaningful when deploying into a macOS app bundle and
+should not be used for that scenario. Apple's macOS app bundle guidelines
+require all plugins to be deployed to the \c{PlugIns} subdirectory of the
+bundle contents.
+
+\section1 Example
+
+\include cmake-deploy-modified-variable-values.qdocinc
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_PREFIX, QT_DEPLOY_BIN_DIR,
+ QT_DEPLOY_LIBEXEC_DIR, QT_DEPLOY_LIB_DIR, QT_DEPLOY_QML_DIR,
+ QT_DEPLOY_TRANSLATIONS_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-qml-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_QML_DIR
+\target cmake-variable-QT_DEPLOY_QML_DIR
+
+\summary {Prefix-relative subdirectory for deploying QML plugins on some target platforms.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.3
+
+Projects should use \c QT_DEPLOY_QML_DIR in their deploy scripts to avoid
+hard-coding a particular directory under which to deploy QML modules.
+
+\c QT_DEPLOY_QML_DIR defaults to the value \c{qml}. To change the value
+of \c QT_DEPLOY_QML_DIR, set it in the project deployment script
+before \c QT_DEPLOY_SUPPORT is included.
+
+The \c QT_DEPLOY_QML_DIR path is relative to \l{QT_DEPLOY_PREFIX}.
+
+This variable is not meaningful when deploying into a macOS app bundle and
+should not be used for that scenario. Apple's macOS app bundle guidelines
+require all plugins to be deployed to the \c{PlugIns} subdirectory of the
+bundle contents, and all other non-binary files should generally be under the
+\c{Resources} subdirectory. The different parts of a QML module therefore need
+to be deployed to different locations within the app bundle.
+
+\section1 Example
+
+\include cmake-deploy-modified-variable-values.qdocinc
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_PREFIX, QT_DEPLOY_BIN_DIR,
+ QT_DEPLOY_LIBEXEC_DIR, QT_DEPLOY_LIB_DIR, QT_DEPLOY_PLUGINS_DIR,
+ QT_DEPLOY_TRANSLATIONS_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-translations-dir.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_TRANSLATIONS_DIR
+\target cmake-variable-QT_DEPLOY_TRANSLATIONS_DIR
+
+\summary {Prefix-relative subdirectory for deploying Qt translations on some target platforms.}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.5
+
+Projects should use \c QT_DEPLOY_TRANSLATIONS_DIR in their deploy scripts to
+avoid hard-coding a particular directory under which to deploy translations.
+
+\c QT_DEPLOY_TRANSLATIONS_DIR defaults to the value \c{translations}. To change
+the value of \c QT_DEPLOY_TRANSLATIONS_DIR, set it in the project deployment
+script before \c QT_DEPLOY_SUPPORT is included.
+
+The \c QT_DEPLOY_TRANSLATIONS_DIR path is relative to \l{QT_DEPLOY_PREFIX}.
+
+This variable is not meaningful when deploying on macOS or Windows.
+
+\section1 Example
+
+\include cmake-deploy-modified-variable-values.qdocinc
+
+\sa QT_DEPLOY_SUPPORT, QT_DEPLOY_PREFIX, QT_DEPLOY_BIN_DIR, QT_DEPLOY_LIB_DIR,
+ QT_DEPLOY_LIBEXEC_DIR, QT_DEPLOY_PLUGINS_DIR, QT_DEPLOY_QML_DIR
+*/
+
+/*!
+\page cmake-variable-qt-deploy-ignored-lib-dirs.html
+\ingroup cmake-variables-qtcore
+
+\title QT_DEPLOY_IGNORED_LIB_DIRS
+\target cmake-variable-QT_DEPLOY_IGNORED_LIB_DIRS
+
+\summary {Directories that are excluded from runtime dependencies search}
+
+\include cmake-deploy-var-usage.qdocinc
+
+\cmakevariablesince 6.5
+
+This variable contains a list of directories that are not taken into account
+when searching for runtime dependencies with \l{qt_deploy_runtime_dependencies}.
+
+Projects may alter this variable before calling
+\l{qt_deploy_runtime_dependencies} to control from which directory runtime
+dependencies are deployed.
+
+This variable is ignored if the \c{POST_EXCLUDE_REGEXES} option is specified in
+the \l{qt_deploy_runtime_dependencies} call.
+
+This variable is not meaningful when deploying on macOS or Windows.
+
+\sa qt_deploy_runtime_dependencies
+*/
diff --git a/src/corelib/doc/src/cmake/cmake-properties.qdoc b/src/corelib/doc/src/cmake/cmake-properties.qdoc
new file mode 100644
index 0000000000..8fe2b0e88f
--- /dev/null
+++ b/src/corelib/doc/src/cmake/cmake-properties.qdoc
@@ -0,0 +1,637 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\group cmake-target-properties-qtcore
+\title CMake Target Properties in Qt6 Core
+\brief Lists CMake target properties known to Qt6::Core.
+
+\l{CMake Commands in Qt6 Core}{CMake Commands} know about the following CMake
+target properties:
+
+\sa{CMake Property Reference}
+*/
+
+/*!
+\page cmake-target-property-qt-android-deployment-dependencies.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_DEPLOYMENT_DEPENDENCIES
+\target cmake-target-property-QT_ANDROID_DEPLOYMENT_DEPENDENCIES
+
+\brief Overrides the Qt dependencies added to the target's deployment.
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+By default, \l androiddeployqt will detect the dependencies of your
+application. However, since run-time usage of plugins cannot be detected,
+there could be false positives, as your application might depend on any
+plugin that is a potential dependency. If you want to minimize the size of
+your \c APK, it's possible to override the automatic detection using this
+property. This should contain a list of all Qt files which need to be
+included, with paths relative to the Qt install root.
+
+\note Only the Qt files specified with this variable are included. Failing
+to include all the correct files can result in crashes. It's also important
+to make sure the files are listed in the correct loading order. This variable
+provides a way to override the automatic detection entirely, so if a library
+is listed before its dependencies, it will fail to load on some devices.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-extra-libs.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_EXTRA_LIBS
+\target cmake-target-property-QT_ANDROID_EXTRA_LIBS
+
+\summary {Extra libraries to deploy with the target.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+A list of external libraries that will be copied into your application's
+\c libs folder and loaded on start-up. This can be used, for instance,
+to enable OpenSSL in your application. For more information, see
+\l{Adding OpenSSL Support for Android}.
+
+When adding extra libraries from the build tree of your project, it's also
+necessary to add dependency relations between library and the application
+target. Using the following project structure may cause an issue, when deploying
+an apk:
+\badcode
+qt_add_executable(MyApp main.cpp)
+
+set_target_properties(MyApp PROPERTIES
+ QT_ANDROID_EXTRA_LIBS
+ ${CMAKE_CURRENT_BINARY_DIR}/libMyService_${ANDROID_ABI}.so
+)
+
+# MyService library doesn't have any relations with MyApp
+qt_add_library(MyService service.cpp)
+\endcode
+
+This leads to uncertainty whether MyService library will be available before
+the deployment of MyApp or not. The easiest solution is adding MyService
+library to the MyApp dependencies:
+\badcode
+add_dependencies(MyApp MyService)
+\endcode
+
+When adding per-architecture libraries to a multi-abi project,
+list all their paths explicitly, rather than rely on variables like
+\c CMAKE_ANDROID_ARCH_ABI to dynamically compute the paths.
+
+Prefer:
+
+\badcode
+set(libs
+ ${CMAKE_CURRENT_BINARY_DIR}/libA_x86so
+ ${CMAKE_CURRENT_BINARY_DIR}/libA_x86_64.so
+ ${CMAKE_CURRENT_BINARY_DIR}/libA_arm64-v8a.so
+ ${CMAKE_CURRENT_BINARY_DIR}/libA_armeabi-v7a.so
+)
+set_target_properties(MyApp PROPERTIES QT_ANDROID_EXTRA_LIBS ${libs})
+
+# When targeting precompiled libs
+target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC libA_${ANDROID_ABI})
+\endcode
+
+over:
+
+\badcode
+set_target_properties(MyApp PROPERTIES
+ QT_ANDROID_EXTRA_LIBS
+ ${CMAKE_CURRENT_BINARY_DIR}/libA_${CMAKE_ANDROID_ARCH_ABI}.so)
+\endcode
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-extra-plugins.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_EXTRA_PLUGINS
+\target cmake-target-property-QT_ANDROID_EXTRA_PLUGINS
+
+\summary {Extra Qt plugins to deploy with the target.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies a path to C++ plugins or resources that your application has to bundle
+but that cannot be delivered through the assets system, such as QML plugins.
+With this variable, \l androiddeployqt will make sure everything is packaged
+and deployed properly.
+
+\c QT_ANDROID_EXTRA_PLUGINS must point to the directory where the extra plugin(s)
+are built. In addition, the build directory structure must follow a naming
+convention similar to Qt plugins, that is, \e {plugins/<plugin name>}.
+\c QT_ANDROID_EXTRA_PLUGINS should point to the \e {plugins} part of that path.
+
+The plugins libraries should have the name format
+\e {libplugins_<type>_<name>_<abi>.so}. This will ensure that the correct name
+mangling is applied to the plugin library.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-min-sdk-version.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_MIN_SDK_VERSION
+\target cmake-target-property-QT_ANDROID_MIN_SDK_VERSION
+
+\summary {Minimum Android SDK version.}
+
+\cmakepropertysince 6.1
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the minimum Android API level for the target.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-package-source-dir.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_PACKAGE_SOURCE_DIR
+\target cmake-target-property-QT_ANDROID_PACKAGE_SOURCE_DIR
+
+\summary {Path to a custom Android package template.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the path for a custom Android package template. The Android package
+template contains:
+\list
+ \li AndroidManifest.xml file
+ \li build.gradle file and other Gradle scripts
+ \li res/values/libs.xml file
+\endlist
+
+The path specified by this variable can contain custom Java classes under
+\c src directory. By default, the \l androiddeployqt tool copies the
+application template from the Qt for Android installation path into your
+project's build directory, then it copies the contents of the path specified
+by this variable on top of that, overwriting any existing files. For
+instance, you can make a custom \c {AndroidManifest.xml} for your application,
+then place this directly into the directory specified by this variable.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-target-sdk-version.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_TARGET_SDK_VERSION
+\target cmake-target-property-QT_ANDROID_TARGET_SDK_VERSION
+
+\summary {Android target SDK version.}
+
+\cmakepropertysince 6.1
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the target Android API level for the target.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-sdk-build-tools-revision.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_SDK_BUILD_TOOLS_REVISION
+\target cmake-target-property-QT_ANDROID_SDK_BUILD_TOOLS_REVISION
+
+\summary {Revision of Android build tools to use.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the Android SDK build tools revision to use. If this is not set then
+CMake will attempt to use the latest installed version.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-version-code.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_ANDROID_VERSION_CODE
+\target cmake-target-property-QT_ANDROID_VERSION_CODE
+\ingroup cmake-android-manifest-properties
+
+\summary {Internal Android app version.}
+
+\cmakepropertysince 6.1
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the app's version number. This is usually a number that
+increments monotonically with each release of your project.
+
+For more information, see \l{Android: App Versioning}{Android App Versioning}.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-version-name.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_ANDROID_VERSION_NAME
+\target cmake-target-property-QT_ANDROID_VERSION_NAME
+\ingroup cmake-android-manifest-properties
+
+\summary {Human-readable Android app version.}
+
+\cmakepropertysince 6.1
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the app's version as a human readable string, usually three
+numbers, separated by dots.
+
+For more information, see \l{Android: App Versioning}{Android App Versioning}.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-abis.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_ABIS
+\target cmake-target-property-QT_ANDROID_ABIS
+
+\summary {List of ABIs that packages of a single target are built for.}
+
+\cmakepropertysince 6.3
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+By setting the \c{QT_ANDROID_ABIS} property for a target, it's possible to control
+the list of ABIs that the single target packages are supposed to be built for.
+\include cmake-android-supported-abis.qdocinc
+The property only affects targets created with
+\l{qt6_add_executable}{qt_add_executable()}.
+
+\sa{cmake-variable-QT_ANDROID_ABIS}{QT_ANDROID_ABIS}, {QT_ANDROID_BUILD_ALL_ABIS}
+*/
+
+/*!
+\page cmake-target-property-qt-qml-root-path.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_QML_ROOT_PATH
+\target cmake-target-property-QT_QML_ROOT_PATH
+
+\summary {Overrides the location of the application's qml directory.}
+
+\cmakepropertysince 6.1
+\preliminarycmakeproperty
+
+This property is currently only used when generating a deployment settings file
+for Android. If the property is set, it specifies the path to the application's
+\c{qml} directory. If it is not set, the \c{SOURCE_DIR} property of the target
+will be used instead.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-qml-import-path.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_QML_IMPORT_PATH
+\target cmake-target-property-QT_QML_IMPORT_PATH
+
+\summary {Specifies a list of directories to search for QML imports.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+
+This property is currently only used when generating a deployment settings file
+for Android. It typically contains just the path to Qt's \c{qml} directory, but
+it can be a list that contains other locations to be searched as well.
+For application-specific QML imports, use
+\l{cmake-target-property-QT_QML_ROOT_PATH}{QT_QML_ROOT_PATH} instead.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
+\page cmake-target-property-qt-android-deployment-settings-file.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_DEPLOYMENT_SETTINGS_FILE
+\target cmake-target-property-QT_ANDROID_DEPLOYMENT_SETTINGS_FILE
+
+\summary {Specifies the location of a target's generated deployment settings file.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+This property will be set by
+\l{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}.
+Projects should not try to set this property themselves, as it will be ignored
+and overwritten by that command.
+*/
+
+/*!
+\page cmake-target-property-qt-android-system-libs-prefix.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_SYSTEM_LIBS_PREFIX
+\target cmake-target-property-QT_ANDROID_SYSTEM_LIBS_PREFIX
+
+\summary {Specifies the location of Qt libraries on the target device.}
+
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+This property can be set to provide a path to Qt libraries on the target device,
+when those libraries are installed outside app's native (JNI) library directory.
+*/
+
+/*!
+\page cmake-target-property-qt-android-no-deploy-qt-libs.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_NO_DEPLOY_QT_LIBS
+\target cmake-target-property-QT_ANDROID_NO_DEPLOY_QT_LIBS
+
+\summary {Whether Qt shared libraries are packaged in the APK on Android.}
+
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+This property can be set to not package Qt shared libraries inside the APK when
+deploying the target. Use
+\l{cmake-target-property-QT_ANDROID_SYSTEM_LIBS_PREFIX}{QT_ANDROID_SYSTEM_LIBS_PREFIX}
+to provide a path to where those libraries will be located on the target device
+instead.
+
+\note Only supported when deploying as an APK.
+*/
+
+/*!
+\page cmake-target-property-qt-no-entrypoint.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title qt_no_entrypoint
+\target cmake-target-property-qt_no_entrypoint
+
+\summary {Specifies to inhibit linking against Qt's entrypoint lib.}
+
+\cmakepropertysince 6.1
+\preliminarycmakeproperty
+
+On certain platforms, Qt applications link against Qt's entrypoint lib by default.
+That library provides implementations of main (or WinMain).
+
+On targets that must provide their own entry point, set the property \c qt_no_entrypoint to inhibit linking against Qt's entrypoint library.
+*/
+
+/*!
+\page cmake-target-property-qt-resource-prefix.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_RESOURCE_PREFIX
+\target cmake-target-property-QT_RESOURCE_PREFIX
+
+\summary {Specifies the default Qt resource prefix.}
+
+\cmakepropertysince 6.0
+\preliminarycmakeproperty
+
+When using \l{qt6_add_resources}{qt_add_resources} without a \c PREFIX
+argument, then the value of this target property will be used as
+resource prefix.
+*/
+
+/*!
+\group cmake-source-file-properties-qtcore
+\title CMake Source File Properties in Qt6 Core
+\brief Lists CMake file properties used in Qt6::Core.
+
+\l{CMake Commands in Qt6 Core}{CMake Commands} know about the following CMake
+source file properties:
+
+\sa{CMake Property Reference}
+*/
+
+/*!
+\page cmake-source-file-property-qt-resource-alias.html
+\ingroup cmake-source-file-properties-qtcore
+
+\title QT_RESOURCE_ALIAS
+\target cmake-source-file-property-QT_RESOURCE_ALIAS
+
+\summary {Specifies the Qt resource alias for a file in a resource.}
+
+\cmakepropertysince 6.0
+
+When using the target-based variant of \l{qt6_add_resources}{qt_add_resources}
+the property value overrides the runtime path where the resource file is found.
+
+\sa{The Qt Resource System}
+*/
+
+/*!
+\page cmake-source-file-property-qt-discard-file-contents.html
+\ingroup cmake-source-file-properties-qtcore
+
+\title QT_DISCARD_FILE_CONTENTS
+\target cmake-source-file-property-QT_DISCARD_FILE_CONTENTS
+
+\summary {Specifies that the given files should be empty in the resource file system}
+
+\cmakepropertysince 6.6
+\preliminarycmakeproperty
+
+When using the target-based variant of \l{qt6_add_resources}{qt_add_resources}
+or \l{qt_add_qml_module}, setting this property to \c TRUE causes the file
+contents to be omitted when creating the resource file system. The file name is
+retained.
+
+This is useful if you want to strip QML source code from the binary.
+
+\note If you omit the QML source code from the binary, the QML engine has to
+rely on the compilation units created by \l{qmlcachegen} or \l{qmlsc}.
+Those are tied to the specific version of Qt they were built with. If you change
+the version of Qt your application uses, they can't be loaded anymore.
+
+\sa{The Qt Resource System}
+*/
+
+/*!
+\page cmake-target-property-qt-wasm-pthread-pool-size.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_WASM_PTHREAD_POOL_SIZE
+\target cmake-target-property-QT_WASM_PTHREAD_POOL_SIZE
+
+\summary {Internal WebAssembly thread pool size.}
+
+\cmakepropertysince 6.2.4
+\preliminarycmakeproperty
+\cmakepropertywebassemblyonly
+
+Specifies the number of web workers (threads) to create at application startup.
+Qt allocates a pool size of 4 by default. This means the app can use
+4 additional threads besides the main thread, without the additional overhead
+of creating a new web worker, which may deadlock if the main thread created it
+and join()s the thread without returning control to the event loop first.
+Translates into the Emscripten compiler setting of PTHREAD_POOL_SIZE.
+
+For more information, see \l{https://emscripten.org/docs/porting/pthreads.html}{Pthreads support}.
+*/
+
+/*!
+\group cmake-global-properties-qtcore
+\title CMake Global Properties in Qt6 Core
+\brief Lists CMake global properties used or defined in Qt6::Core.
+
+\l{CMake Commands in Qt6 Core}{CMake Commands} know about the following global
+CMake properties:
+
+\sa{CMake Property Reference}
+*/
+
+/*!
+\page cmake-global-property-qt-targets-folder.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-global-properties-qtcore
+
+\title QT_TARGETS_FOLDER
+\target cmake-global-property-QT_TARGETS_FOLDER
+
+\brief Sets the FOLDER property for Qt-internal targets.
+
+\cmakepropertysince 6.5
+\preliminarycmakeproperty
+
+Name of the \l FOLDER for internal targets that are added by Qt's CMake
+commands.
+
+By default, this property is not set.
+
+This property only has an effect if CMake's \l USE_FOLDERS property is \c{ON}.
+
+You can use the \l{qt6_standard_project_setup}{qt_standard_project_setup}
+function to enable folder support and initialize the \c{QT_TARGETS_FOLDER}.
+
+\sa{qt6_standard_project_setup}{qt_standard_project_setup}
+*/
+
+/*!
+\page cmake-target-property-qt-wasm-initial-memory.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_WASM_INITIAL_MEMORY
+\target cmake-target-property-QT_WASM_INITIAL_MEMORY
+
+\summary {Internal WebAssembly initial memory.}
+
+\cmakepropertysince 6.2.4
+\preliminarycmakeproperty
+\cmakepropertywebassemblyonly
+
+Specifies the initial amount of memory to use, in bytes. Using more will cause the
+browser to copy the old heap into a new one. Translates into the
+Emscripten compiler setting of INITIAL_MEMORY.
+QT_WASM_INITIAL_MEMORY must be a multiple of 65536 bytes.
+
+For more information, see \l{https://github.com/emscripten-core/emscripten/blob/main/src/settings.js}{Emscripten compiler settings}.
+*/
+
+/*!
+\page cmake-target-property-qt-wasm-maximum-memory.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_WASM_MAXIMUM_MEMORY
+\target cmake-target-property-QT_WASM_MAXIMUM_MEMORY
+
+\summary {Internal WebAssembly maximum memory.}
+
+\cmakepropertysince 6.7
+\preliminarycmakeproperty
+\cmakepropertywebassemblyonly
+
+Specifies the maximum amount of memory the application can use. Translates into
+the Emscripten compiler setting of \c MAXIMUM_MEMORY. The default value
+is 4GB, which is the maximum for 32-bit WebAssembly.
+
+For more information, see the \l{https://github.com/emscripten-core/emscripten/blob/3319a313d3b589624d342b650884caaf8cd9ef30/src/settings.js#L187}{Emscripten compiler settings}.
+*/
+
+
+
+/*!
+\page cmake-target-property-qt-ios-launch-screen.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_IOS_LAUNCH_SCREEN
+\target cmake-target-property-QT_IOS_LAUNCH_SCREEN
+
+\summary {Path to iOS launch screen storyboard}
+
+\cmakepropertysince 6.4
+\preliminarycmakeproperty
+\cmakepropertyiosonly
+
+Specifies the path to an iOS launch screen storyboard file.
+
+\sa {Launch Screens and Launch Images}
+*/
diff --git a/src/corelib/doc/src/cmake/cmake-standard-properties.qdoc b/src/corelib/doc/src/cmake/cmake-standard-properties.qdoc
new file mode 100644
index 0000000000..a8ece6ba8f
--- /dev/null
+++ b/src/corelib/doc/src/cmake/cmake-standard-properties.qdoc
@@ -0,0 +1,24 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page cmake-standard-property-autogen-better-graph-multi-config.html
+\ingroup cmake-standard-properties
+
+\title AUTOGEN_BETTER_GRAPH_MULTI_CONFIG
+
+\brief Improves the dependency graph for multi-configuration generators when you
+set it on a target.
+
+When this boolean property is enabled, \c{CMake} will generate more per-config targets.
+Thus, the dependency graph will be more accurate for multi-configuration
+generators and some recompilations will be avoided.
+
+Since Qt 6.8, this property is enabled by default. For older versions,
+you need to enable it manually to use it.
+However, \l{qt_extract_metatypes} and \l{qt_add_qml_module} were updated to
+support \c{AUTOGEN_BETTER_GRAPH_MULTI_CONFIG} in Qt 6.8, so you will get build
+errors, unless you patch the older Qt version to support it.
+
+See \l{https://cmake.org/cmake/help/latest/prop_tgt/AUTOGEN_BETTER_GRAPH_MULTI_CONFIG.html}{AUTOGEN_BETTER_GRAPH_MULTI_CONFIG} for more information.
+*/
diff --git a/src/corelib/doc/src/cmake/policy/qtp0002.qdoc b/src/corelib/doc/src/cmake/policy/qtp0002.qdoc
new file mode 100644
index 0000000000..a40344a167
--- /dev/null
+++ b/src/corelib/doc/src/cmake/policy/qtp0002.qdoc
@@ -0,0 +1,63 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-cmake-policy-qtp0002.html
+\ingroup qt-cmake-policies
+
+\title QTP0002
+\keyword qt_cmake_policy_qtp0002
+
+\summary {Target properties that specify Android-specific paths may contain generator expressions.}
+
+This policy was introduced in Qt 6.6. It changes the processing of target
+properties that specify Android-specific paths:
+\list
+ \li \l QT_QML_IMPORT_PATH
+ \li \l QT_QML_ROOT_PATH
+ \li \l QT_ANDROID_PACKAGE_SOURCE_DIR
+ \li \l QT_ANDROID_EXTRA_PLUGINS
+ \li \l QT_ANDROID_EXTRA_LIBS
+\endlist
+
+The \c OLD behavior of this policy doesn't allow generator expressions in the
+target properties that specify Android-specific paths but implicitly converts
+the specified paths to valid JSON strings.
+
+The \c NEW behavior of this policy allows using generator expressions in the
+target properties that specify Android-specific paths, but they must evaluate to
+valid JSON strings.
+
+The following value of the \l QT_ANDROID_EXTRA_PLUGINS property is converted to
+a valid JSON string if you set the policy to OLD, but leads to an error if the
+policy is set to NEW:
+\badcode
+set_target_properties(
+ QT_ANDROID_EXTRA_PLUGINS "\\path\\to\\MyPlugin.so"
+)
+\endcode
+If the policy is set to NEW for the above example, the resulting JSON string in
+the deployment settings file will contain escaped symbols instead of path
+separators.
+
+Generator expressions are only supported if the policy is set to NEW, so the
+OLD behavior generates a malformed deployment settings file with the following
+code:
+\badcode
+set_target_properties(
+ QT_ANDROID_EXTRA_PLUGINS "$<TARGET_FILE_DIR:MyPlugin>"
+)
+\endcode
+
+This property value works as expected with both OLD and NEW policy values:
+\badcode
+set_target_properties(
+ QT_ANDROID_EXTRA_PLUGINS "/path/to/MyPlugin.so"
+)
+\endcode
+
+\qtpolicydeprecatedbehavior
+
+\sa qt_policy, {Qt CMake policies}
+
+*/
diff --git a/src/corelib/doc/src/cmake/policy/qtp0003.qdoc b/src/corelib/doc/src/cmake/policy/qtp0003.qdoc
new file mode 100644
index 0000000000..bf11b6f8b5
--- /dev/null
+++ b/src/corelib/doc/src/cmake/policy/qtp0003.qdoc
@@ -0,0 +1,46 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-cmake-policy-qtp0003.html
+\ingroup qt-cmake-policies
+\since 6.7
+\title QTP0003
+\keyword qt_cmake_policy_qtp0003
+
+\summary {Consider the BUILD_SHARED_LIBS value when creating Qt libraries.}
+
+This policy was introduced in Qt 6.7. The policy affects the default type of the
+libraries created using \l {CMake Commands in Qt6 Core}{Qt CMake API}, like
+\l {qt_add_library}, \l{qt_add_plugin}, \l{qt_add_qml_module}.
+
+If the policy is set to \c OLD, the default library type that is selected is
+aligned with the Qt build type, either \c shared or \c static.
+
+If the policy is set to \c NEW, the library type is selected according to the
+\l {CMake BUILD_SHARED_LIBS Documentation}{BUILD_SHARED_LIBS} value if it's set.
+If \c BUILD_SHARED_LIBS is not set, the default library type falls back to the
+Qt build type.
+
+For example, the following code will use the Qt build type as the default
+library type for the \c MyLib target, despite the fact \c BUILD_SHARED_LIBS is
+set to \c ON:
+\badcode
+set(BUILD_SHARED_LIBS ON)
+...
+qt6_add_library(MyLib sourcefile.h sourcefile.cpp)
+\endcode
+
+If you set the QTP0003 to \c NEW before the \l {qt6_add_library}{qt_add_library}
+call, \c BUILD_SHARED_LIBS will affect the library default type and \c MyLib
+will be the shared library.
+\badcode
+set(BUILD_SHARED_LIBS ON)
+...
+qt_policy(SET QTP0003 NEW)
+qt6_add_library(MyLib sourcefile.h sourcefile.cpp)
+\endcode
+
+\sa qt_policy, {Qt CMake policies}, qt_add_library
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_add_big_resources.qdoc b/src/corelib/doc/src/cmake/qt_add_big_resources.qdoc
new file mode 100644
index 0000000000..8215d4c717
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_add_big_resources.qdoc
@@ -0,0 +1,53 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-add-bigresources.html
+\ingroup cmake-commands-qtcore
+
+\title qt_add_big_resources
+\keyword qt6_add_big_resources
+
+\summary {Compiles big binary resources into object code.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 5.12
+
+\section1 Synopsis
+
+\badcode
+qt_add_big_resources(<VAR> file1.qrc [file2.qrc ...]
+ [OPTIONS ...])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_add_big_resources()
+
+\section1 Description
+
+Creates compiled object files from Qt resource files using the
+\l{Resource Compiler (rcc)}. Paths to the generated files are added to
+\c{<VAR>}.
+
+This is similar to \l qt_add_resources, but directly
+generates object files (\c .o, \c .obj) files instead of C++ source code.
+This allows to embed bigger resources, where compiling to C++ sources and then
+to binaries would be too time consuming or memory intensive.
+
+\note The \c{file1.qrc} will not be treated as a source file by Qt Creator. It
+needs to be added as a source file to a CMake target and have the property
+\c{SKIP_AUTORCC} set to \c{ON}.
+
+\warning This command is not supported when building for iOS, use
+\l qt_add_resources instead.
+See \l{https://bugreports.qt.io/browse/QTBUG-103497}{QTBUG-103497} for details.
+
+\section1 Arguments
+
+You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.
+You can find possible options in the \l{rcc}{rcc documentation}.
+
+\section1 Examples
+
+\snippet cmake-macros/examples.cmake qt_add_big_resources
+*/
diff --git a/src/corelib/doc/src/cmake/qt_add_binary_resources.qdoc b/src/corelib/doc/src/cmake/qt_add_binary_resources.qdoc
new file mode 100644
index 0000000000..12ee5e1aff
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_add_binary_resources.qdoc
@@ -0,0 +1,43 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-add-binary-resources.html
+\ingroup cmake-commands-qtcore
+
+\title qt_add_binary_resources
+\keyword qt6_add_binary_resources
+
+\summary {Creates an RCC file from a list of Qt resource files.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 5.10
+
+\section1 Synopsis
+
+\badcode
+qt_add_binary_resources(target file1.qrc [file2.qrc ...]
+ [DESTINATION ...]
+ [OPTIONS ...])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_add_binary_resources()
+
+\section1 Description
+
+Adds a custom \c target that compiles Qt resource files into a binary \c{.rcc}
+file.
+
+\section1 Arguments
+
+\c{DESTINATION} sets the path of the generated \c{.rcc} file. The default is
+\c{${CMAKE_CURRENT_BINARY_DIR}/${target}.rcc}.
+
+You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.
+You can find possible options in the \l{rcc}{rcc documentation}.
+
+\section1 Examples
+
+\snippet cmake-macros/examples.cmake qt_add_binary_resources
+*/
diff --git a/src/corelib/doc/src/cmake/qt_add_executable.qdoc b/src/corelib/doc/src/cmake/qt_add_executable.qdoc
new file mode 100644
index 0000000000..cc8c924c79
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_add_executable.qdoc
@@ -0,0 +1,114 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-add-executable.html
+\ingroup cmake-commands-qtcore
+
+\title qt_add_executable
+\keyword qt6_add_executable
+
+\summary {Creates and finalizes an application target of a platform-specific type.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.0
+
+\section1 Synopsis
+
+\badcode
+qt_add_executable(target
+ [WIN32] [MACOSX_BUNDLE]
+ [MANUAL_FINALIZATION]
+ sources...)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_add_executable()
+
+\section1 Description
+
+This command performs the following tasks:
+
+\list
+\li Create a CMake target of the appropriate type for the target platform.
+\li Link the target to the \c{Qt::Core} library.
+\li Handle finalization of the CMake target.
+\endlist
+
+\section2 Target Creation
+
+On all platforms except Android, an executable target will be created.
+All arguments will be passed through to the standard CMake \c{add_executable()}
+command, except \c{MANUAL_FINALIZATION} (if present). On Android, a \c{MODULE}
+library will be created and any \c{WIN32} or \c{MACOSX_BUNDLE} options will be
+ignored. Some target properties will also be set for Android:
+
+\list
+\li The \c{SUFFIX} target property will be set to give the library file name an
+ architecture-specific suffix.
+\li Various \c{<lang>_VISIBILITY_PRESET} target properties will be set to
+ \c{default} to ensure that the \c{main()} function is visible in the
+ resultant binary.
+\endlist
+
+\section2 Linking Qt::Core
+
+Since all Qt applications need to link to the \c{Qt::Core} library, this is done
+for you as a convenience.
+
+\section2 Finalization
+
+After a target is created, further processing or \e{finalization} steps are
+commonly needed. The steps to perform depend on the platform and on various
+properties of the target.
+
+The finalization processing is implemented by two commands:
+\l{qt6_finalize_target}{qt_finalize_target()} and
+\l{qt6_finalize_project}{qt_finalize_project()}.
+
+Target finalization can occur either as part of calling \c{qt_add_executable}
+or be deferred to sometime after this command returns (but it should still be in
+the same directory scope).
+
+When using CMake 3.19 or later, target finalization is automatically deferred to the
+end of the current directory scope. This gives the caller an opportunity to
+modify properties of the created target before it is finalized. When using
+CMake versions earlier than 3.19, automatic deferral isn't supported. In that
+case, target finalization is performed immediately before this command returns.
+
+Regardless of the CMake version, the \c{MANUAL_FINALIZATION} keyword can be given to
+indicate that you will explicitly call \l{qt6_finalize_target}{qt_finalize_target()}
+yourself instead at some later time. In general, \c MANUAL_FINALIZATION should
+not be needed unless the project has to support CMake 3.18 or earlier.
+
+Project finalization occurs automatically when using CMake 3.19 or later.
+When using an older CMake version, you should call
+\l{qt6_finalize_project}{qt_finalize_project()} manually, at the end
+of the root \c CMakeLists.txt file.
+This is especially important when targeting Android, to collect dependencies
+between project targets for deployment purposes.
+
+\sa {qt6_finalize_target}{qt_finalize_target()},
+ {qt6_set_finalizer_mode}{qt_set_finalizer_mode()},
+ {qt6_add_library}{qt_add_library()},
+ {qt6_finalize_project}{qt_finalize_project()}
+
+\section1 Examples
+
+In the following simple case, finalization is handled automatically. If using a
+CMake version earlier than 3.19, finalization will be performed immediately as
+part of the call. When using CMake 3.19 or later, finalization will occur at the
+end of the current directory scope.
+
+\snippet cmake-macros/examples.cmake qt_add_executable_simple
+
+The following example shows a scenario where finalization must be deferred.
+The \c OUTPUT_NAME target property affects deployment settings on Android, but
+those settings are written out as part of finalizing the target. In order to
+support using CMake versions earlier than 3.19, we take over responsibility
+for finalizing the target by adding the \c{MANUAL_FINALIZATION} keyword.
+
+\snippet cmake-macros/examples.cmake qt_add_executable_deferred
+
+\include cmake-android-qt-finalize-project-warning.qdocinc warning
+*/
diff --git a/src/corelib/doc/src/cmake/qt_add_library.qdoc b/src/corelib/doc/src/cmake/qt_add_library.qdoc
new file mode 100644
index 0000000000..851a2d6210
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_add_library.qdoc
@@ -0,0 +1,80 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-add-library.html
+\ingroup cmake-commands-qtcore
+
+\title qt_add_library
+\keyword qt6_add_library
+
+\summary {Creates and finalizes a library.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.2
+
+\section1 Synopsis
+
+\badcode
+qt_add_library(target
+ [STATIC | SHARED | MODULE | INTERFACE | OBJECT]
+ [MANUAL_FINALIZATION]
+ sources...
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_add_library()
+
+\section1 Description
+
+\c{qt_add_library()} is a wrapper around CMake's built-in
+\c{add_library()} command. It performs the following tasks:
+
+\list
+\li Create a CMake target of an appropriate library type.
+\li Handle finalization of the CMake target.
+\endlist
+
+\section2 Target Creation
+
+The type of library created can be specified explicitly with one of the
+\c STATIC, \c SHARED, \c MODULE, \c INTERFACE or \c OBJECT keywords, just as
+one might for \c{add_library()}. If none of these keywords are given, the
+library type created depends on how Qt was built. If Qt was built statically,
+a static library will be created. Otherwise, a shared library will
+be created. Note that this is different to how CMake's \c{add_library()}
+command works, where the \c BUILD_SHARED_LIBS variable controls the type of
+library created.
+Since 6.7, the \c{qt_add_library()} command considers \c BUILD_SHARED_LIBS
+when deciding the library type only if the variable is set explicitly and
+\l {QTP0003} is set to \c NEW.
+
+Any \c{sources} provided will be passed through to the internal call to
+\c{add_library()}.
+
+\target qt_add_library finalization
+\section2 Finalization
+
+After a target is created, further processing or \e{finalization} steps may be
+needed. The finalization processing is implemented by the
+\l{qt6_finalize_target}{qt_finalize_target()} command.
+
+Finalization can occur either as part of this call or be deferred to sometime
+after this command returns (but it should still be in the same directory scope).
+When using CMake 3.19 or later, finalization is automatically deferred to the
+end of the current directory scope. This gives the caller an opportunity to
+modify properties of the created target before it is finalized. When using
+CMake versions earlier than 3.19, automatic deferral isn't supported. In that
+case, finalization is performed immediately before this command returns.
+
+Regardless of the CMake version, the \c{MANUAL_FINALIZATION} keyword can be
+given to indicate that you will explicitly call
+\l{qt6_finalize_target}{qt_finalize_target()} yourself instead at some later
+time. In general, \c MANUAL_FINALIZATION should not be needed unless the
+project has to support CMake 3.18 or earlier.
+
+\sa {qt6_finalize_target}{qt_finalize_target()},
+ {qt6_add_executable}{qt_add_executable()}, QTP0003
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_add_plugin.qdoc b/src/corelib/doc/src/cmake/qt_add_plugin.qdoc
new file mode 100644
index 0000000000..d2322086e7
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_add_plugin.qdoc
@@ -0,0 +1,87 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-add-plugin.html
+\ingroup cmake-commands-qtcore
+
+\title qt_add_plugin
+\keyword qt6_add_plugin
+
+\summary {Creates a Qt plugin target.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.0
+
+\section1 Synopsis
+
+\badcode
+qt_add_plugin(target
+ [SHARED | STATIC]
+ [CLASS_NAME class_name]
+ [OUTPUT_TARGETS variable_name]
+ [MANUAL_FINALIZATION]
+ sources...
+)
+\endcode
+
+The \c MANUAL_FINALIZATION option and the ability to set sources
+were introduced in Qt 6.5.
+
+\versionlessCMakeCommandsNote qt6_add_plugin()
+
+\section1 Description
+
+Qt plugin targets have additional requirements over and above an ordinary CMake
+library target. The \c{qt_add_plugin()} command adds the necessary handling to
+ensure these requirements are met. It should be called rather than the built-in
+CMake \c{add_library()} command when defining a Qt plugin target.
+
+By default, the plugin will be created as a \c STATIC library if Qt was built
+statically, or as a \c MODULE library otherwise. You can override this default
+by explicitly providing the \c STATIC or \c SHARED option.
+
+Any \c{sources} provided will be passed through to the internal call to
+\c{add_library()}.
+
+\note Non-static plugins are meant to be loaded dynamically at runtime, not
+linked to at build time. CMake differentiates between these two scenarios by
+providing the \c MODULE library type for dynamically loaded libraries, and
+the \c SHARED library type for libraries that may be linked to directly. This
+distinction is important for some toolchains (notably Visual Studio), due to
+the way symbol exports are handled. It may not be possible to link to
+\c MODULE libraries, and generating a \c SHARED library with no exported
+symbols can result in build-time errors. If the \c SHARED option is passed to
+\c{qt_add_plugin()}, it will therefore create a \c MODULE library rather than a
+\c SHARED library.
+
+Every Qt plugin has a class name. By default, this will be the same as the
+\c target, but it can be overridden with the \c CLASS_NAME option. The class
+name corresponds to the name of the C++ class that declares the metadata for
+the plugin. For static plugins, it is also the name passed to
+\l Q_IMPORT_PLUGIN, which imports the plugin into an application and ensures it
+is available at run time.
+
+If the plugin is built statically, \c{qt_add_plugin()} may define additional
+internal targets. These facilitate automatic importing of the plugin for any
+executable or shared library that links to the plugin. If the project installs
+the plugin and intends to make it available for other projects to link to, the
+project should also install these internal targets. The names of these targets
+can be obtained by providing the \c OUTPUT_TARGETS option, followed by the name
+of a variable in which to return the target list.
+
+\section2 Finalization
+
+After a target is created, further processing or \e{finalization} steps may be
+needed. The finalization processing is implemented by the
+\l{qt6_finalize_target}{qt_finalize_target()} command.
+
+For details and the meaning of the \c{MANUAL_FINALIZATION} option, refer to the
+\l{qt_add_library finalization}{finalization documentation} for
+\c{qt_add_library}.
+
+\sa {qt6_finalize_target}{qt_finalize_target()},
+ {qt6_add_executable}{qt_add_executable()}
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_add_resources.qdoc b/src/corelib/doc/src/cmake/qt_add_resources.qdoc
new file mode 100644
index 0000000000..2e713b1b8e
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_add_resources.qdoc
@@ -0,0 +1,110 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-add-resources.html
+\ingroup cmake-commands-qtcore
+
+\title qt_add_resources
+\keyword qt6_add_resources
+
+\summary {Compiles binary resources into source code.}
+
+\include cmake-find-package-core.qdocinc
+
+\section1 Synopsis
+
+\badcode
+qt_add_resources(<VAR> file1.qrc [file2.qrc ...]
+ [OPTIONS ...])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_add_resources()
+
+Since 6.0:
+
+\badcode
+qt_add_resources(<TARGET> <RESOURCE_NAME>
+ [PREFIX <PATH>]
+ [LANG <LANGUAGE>]
+ [BASE <PATH>]
+ [BIG_RESOURCES]
+ [OUTPUT_TARGETS <VARIABLE_NAME>]
+ [FILES ...] [OPTIONS ...])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_add_resources()
+
+\section1 Description
+
+To add resources, you can pass either a variable name or a target as the first
+argument of the command.
+
+When passing a variable name as first argument, \c qt_add_resources creates
+source code from Qt resource files using the \l{Resource Compiler (rcc)}. Paths
+to the generated source files are added to \c{<VAR>}.
+
+When passing a target as first argument, the function creates a resource with
+the name \c{RESOURCE_NAME}, containing the specified \c{FILES}. The resource is
+automatically linked into \c{TARGET}.
+
+See \l{The Qt Resource System} for a general description of Qt resources.
+
+\section1 Arguments of the target-based variant
+
+\c PREFIX specifies a path prefix under which all files of this resource are
+accessible from C++ code. This corresponds to the XML attribute \c prefix of the
+\c .qrc file format. If \c PREFIX is not given, the target property
+\l{cmake-target-property-QT_RESOURCE_PREFIX}{QT_RESOURCE_PREFIX} is used. Since
+6.5, \c{PREFIX} is optional. If it is omitted and not specified by
+\c{QT_RESOURCE_PREFIX}, \c{"/"} will be used as the default path prefix.
+
+\c LANG specifies the locale of this resource. This corresponds to the XML
+attribute \c lang of the \c .qrc file format.
+
+\c BASE is a path prefix that denotes the root point of the file's alias. For
+example, if \c BASE is \c{"assets"} and \c FILES is
+\c{"assets/images/logo.png"}, then the alias of that file is
+\c{"images/logo.png"}.
+
+Alias settings for files need to be set via the \c QT_RESOURCE_ALIAS source file
+property.
+
+\c BIG_RESOURCES can be specified to enable support for big resources. This
+directly generates object files (\c .o, \c .obj) instead of C++ source code.
+This allows embedding bigger resources, without having to compile generated C++
+sources, which can be too time consuming and memory intensive.
+
+Note that \c BIG_RESOURCES is not compatible with iOS due to restrictions of
+CMake's Xcode project generator. See
+\l{https://bugreports.qt.io/browse/QTBUG-103497}{QTBUG-103497} for details.
+Also, \c BIG_RESOURCES only works reliably from CMake 3.17 onwards.
+
+When using this command with static libraries, one or more special targets will
+be generated. Should you wish to perform additional processing on these targets,
+pass a variable name to the \c OUTPUT_TARGETS parameter. The \c qt_add_resources
+function stores the names of the special targets in the specified variable.
+
+\section1 Arguments of both variants
+
+You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.
+You can find possible options in the \l{rcc}{rcc documentation}.
+
+\section1 Examples
+
+Variable variant, using a .qrc file:
+\snippet cmake-macros/examples.cmake qt_add_resources
+
+Target variant, using immediate resources:
+\snippet cmake-macros/examples.cmake qt_add_resources_target
+
+\section1 Caveats
+
+When adding multiple resources, \c{RESOURCE_NAME} must be unique across all
+resources linked into the final target.
+
+This especially affects static builds. There, the same resource name in
+different static libraries conflict in the consuming target.
+
+\sa {qt6_add_big_resources}{qt_add_big_resources()}
+*/
diff --git a/src/corelib/doc/src/cmake/qt_allow_non_utf8_sources.qdoc b/src/corelib/doc/src/cmake/qt_allow_non_utf8_sources.qdoc
new file mode 100644
index 0000000000..ad95401f4d
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_allow_non_utf8_sources.qdoc
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-allow-non-utf8-sources.html
+\ingroup cmake-commands-qtcore
+
+\title qt_allow_non_utf8_sources
+\keyword qt6_allow_non_utf8_sources
+
+\summary {Prevents forcing source files to be treated as UTF-8 for Windows.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.0
+
+\section1 Synopsis
+
+\badcode
+qt_allow_non_utf8_sources(target)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_allow_non_utf8_sources()
+
+\section1 Description
+
+When building with some compilers for Windows, targets that link to a Qt library
+will use flags that force the compiler to treat its source files as UTF-8. This
+is currently implemented for Visual Studio and Intel compilers. You can disable
+this behavior on a per-target basis by calling \c{qt_allow_non_utf8_sources()}
+and passing the target as the argument.
+
+\sa {qt6_disable_unicode_defines}{qt_disable_unicode_defines()}
+*/
diff --git a/src/corelib/doc/src/cmake/qt_android_add_apk_target.qdoc b/src/corelib/doc/src/cmake/qt_android_add_apk_target.qdoc
new file mode 100644
index 0000000000..b2415730f5
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_android_add_apk_target.qdoc
@@ -0,0 +1,55 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-android-add-apk-target.html
+\ingroup cmake-commands-qtcore
+
+\title qt_android_add_apk_target
+\keyword qt6_android_add_apk_target
+
+\summary {Defines a build target that runs androiddeployqt to produce an APK.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.0
+\warning This command is deprecated since Qt 6.5. Use \l qt_add_executable instead.
+\cmakecommandandroidonly
+
+\section1 Synopsis
+
+\badcode
+qt_android_add_apk_target(target)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_android_add_apk_target()
+
+\section1 Description
+
+The \c{<target>_make_apk} and \c{<target>_make_aab} custom targets created by
+this command take an Android deployment settings file and generate APK and
+AAB respectively by running \c{androiddeployqt}.
+The location of the settings file is taken from the \c{target}'s
+\c{QT_ANDROID_DEPLOYMENT_SETTINGS_FILE} property. This file is typically created by
+\l{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}.
+The respective Android package will be generated in an \c{android-build}
+subdirectory below the CMake build directory of the \c{target}.
+
+The \c{<target>_make_apk} and \c{<target>_make_aab} targets will be
+automatically added as dependencies of the \c{apk} and \c{aab} build targets
+respectively, which will be created automatically. Creating of the \c{apk} and
+\c{aab} targets can be disabled by setting the \c{QT_NO_GLOBAL_APK_TARGET} and
+\c{QT_NO_GLOBAL_AAB_TARGET} variables to \c{TRUE}.
+
+\sa {qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()},
+ {qt6_finalize_target}{qt_finalize_target()},
+ {qt6_finalize_project}{qt_finalize_project()}
+
+\section1 Example
+
+\snippet cmake-macros/examples.cmake qt_android_deploy_basic
+
+The above commands define the \c{myapp_make_apk}, \c{myapp_make_aab}, \c{apk},
+and \c{aab} build targets which can be used to generate just the
+\c{myapp} packages or all APKs and AABs in the project respectively.
+*/
diff --git a/src/corelib/doc/src/cmake/qt_android_apply_arch_suffix.qdoc b/src/corelib/doc/src/cmake/qt_android_apply_arch_suffix.qdoc
new file mode 100644
index 0000000000..a29e1f6123
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_android_apply_arch_suffix.qdoc
@@ -0,0 +1,36 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-android-apply-arch-suffix.html
+\ingroup cmake-commands-qtcore
+
+\title qt_android_apply_arch_suffix
+\keyword qt6_android_apply_arch_suffix
+
+\summary {Configures the target binary's name to include an architecture-specific suffix.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.0
+\warning This command is deprecated since Qt 6.5. Use \l qt_add_executable
+or \l qt_add_library instead.
+\cmakecommandandroidonly
+
+\section1 Synopsis
+
+\badcode
+qt_android_apply_arch_suffix(target)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_android_apply_arch_suffix()
+
+\section1 Description
+
+The CMake \c{SUFFIX} target property controls the suffix used on the file name
+of the target's built binary. This command is a convenience for setting that
+property to an architecture-specific value. This is useful when installing
+multiple builds for different Android architectures into the same install
+location, as it prevents the libraries for different architectures from
+overwriting each other.
+*/
diff --git a/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc b/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc
new file mode 100644
index 0000000000..5a7bbdc33f
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc
@@ -0,0 +1,82 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-android-generate-deployment-settings.html
+\ingroup cmake-commands-qtcore
+
+\title qt_android_generate_deployment_settings
+\keyword qt6_android_generate_deployment_settings
+
+\summary {Generates the deployment settings file needed by androiddeployqt.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.0
+\warning This command is deprecated since Qt 6.5. Use \l qt_add_executable instead.
+\cmakecommandandroidonly
+
+\section1 Synopsis
+
+\badcode
+qt_android_generate_deployment_settings(target)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_android_generate_deployment_settings()
+
+\section1 Description
+
+The \c{androiddeployqt} tool expects a deployment settings file as input. This
+command reads CMake variables and properties of the \c{target} to generate such
+a file in the target's binary directory. Upon return, the full path to this file
+is available in the target's \c{QT_ANDROID_DEPLOYMENT_SETTINGS_FILE} property.
+
+\section2 CMake Variables
+
+A number of variables are used while generating the deployment settings file.
+Some are provided by Qt, others by CMake or the Android NDK.
+
+\list
+\li \l{cmake-variable-ANDROID_NDK_HOST_SYSTEM_NAME}{ANDROID_NDK_HOST_SYSTEM_NAME}
+\li \l{cmake-variable-ANDROID_SDK_ROOT}{ANDROID_SDK_ROOT}
+\li \c{CMAKE_ANDROID_ARCH_ABI}
+\li \c{CMAKE_ANDROID_NDK}
+\li \c{CMAKE_SYSROOT}
+\li \l{cmake-variable-QT_ANDROID_APPLICATION_ARGUMENTS}{QT_ANDROID_APPLICATION_ARGUMENTS}
+\li \l{cmake-variable-QT_HOST_PATH}{QT_HOST_PATH}
+\endlist
+
+\section2 Target Properties
+
+The properties below will be read from the specified \c{target}. Note that this
+command is called as part of target finalization (see
+\l{qt6_finalize_target}{qt_finalize_target()}). If you are using
+\l{qt6_add_executable}{qt_add_executable()} to create the target and you need to
+modify some of these target properties, you need to ensure that target
+finalization is deferred. See \l{qt6_add_executable}{qt_add_executable()} for
+how to accomplish this.
+
+\list
+\li \l{cmake-target-property-QT_ANDROID_DEPLOYMENT_DEPENDENCIES}{QT_ANDROID_DEPLOYMENT_DEPENDENCIES}
+\li \l{cmake-target-property-QT_ANDROID_EXTRA_LIBS}{QT_ANDROID_EXTRA_LIBS}
+\li \l{cmake-target-property-QT_ANDROID_EXTRA_PLUGINS}{QT_ANDROID_EXTRA_PLUGINS}
+\li \l{cmake-target-property-QT_ANDROID_MIN_SDK_VERSION}{QT_ANDROID_MIN_SDK_VERSION}
+\li \l{cmake-target-property-QT_ANDROID_PACKAGE_SOURCE_DIR}{QT_ANDROID_PACKAGE_SOURCE_DIR}
+\li \l{cmake-target-property-QT_ANDROID_TARGET_SDK_VERSION}{QT_ANDROID_TARGET_SDK_VERSION}
+\li \l{cmake-target-property-QT_ANDROID_VERSION_NAME}{QT_ANDROID_VERSION_NAME}
+\li \l{cmake-target-property-QT_ANDROID_VERSION_CODE}{QT_ANDROID_VERSION_CODE}
+\li \l{cmake-target-property-QT_QML_IMPORT_PATH}{QT_QML_IMPORT_PATH}
+\li \l{cmake-target-property-QT_QML_ROOT_PATH}{QT_QML_ROOT_PATH}
+\li \l{cmake-target-property-qt_no_entrypoint}{qt_no_entrypoint}
+\endlist
+
+Upon return, the \c{QT_ANDROID_DEPLOYMENT_SETTINGS_FILE} target property will
+contain the location of the generated deployment settings file.
+
+\sa {qt6_android_add_apk_target}{qt_android_add_apk_target()},
+ {qt6_finalize_target}{qt_finalize_target()}
+
+\section1 Example
+
+\snippet cmake-macros/examples.cmake qt_android_deploy_basic
+*/
diff --git a/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc b/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc
new file mode 100644
index 0000000000..45fd8f4c5f
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc
@@ -0,0 +1,78 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-deploy-qt-conf.html
+\ingroup cmake-commands-qtcore
+
+\title qt_deploy_qt_conf
+\keyword qt6_deploy_qt_conf
+
+\summary {Write a qt.conf file at deployment time.}
+
+\include cmake-find-package-core.qdocinc
+
+Unlike most other CMake commands provided by Qt, \c{qt_deploy_qt_conf()} can
+only be called from a deployment script. It cannot be called directly by the
+project.
+
+\cmakecommandsince 6.3
+\note This command does not usually need to be called directly. It is used
+ internally by other higher level commands, but projects wishing to
+ implement more customized deployment logic may find it useful.
+
+\section1 Synopsis
+
+\badcode
+qt_deploy_qt_conf(file_path
+ [PREFIX prefix]
+ [DOC_DIR doc_dir]
+ [HEADERS_DIR headers_dir]
+ [LIB_DIR lib_dir]
+ [LIBEXEC_DIR libexec_dir]
+ [BIN_DIR bin_dir]
+ [PLUGINS_DIR plugins_dir]
+ [QML_DIR qml_dir]
+ [ARCHDATA_DIR archdata_dir]
+ [DATA_DIR data_dir]
+ [TRANSLATIONS_DIR translations_dir]
+ [EXAMPLES_DIR examples_dir]
+ [TESTS_DIR test_dir]
+ [SETTINGS_DIR settings_dir]
+)
+\endcode
+
+\section1 Description
+
+Use this command when you need to generate a \l{Using qt.conf}{qt.conf} file
+during deployment. The default value of any path supported by \c{qt.conf} can
+be overridden with the corresponding \c{..._DIR} option. The command will only
+write a path to the generated \c{qt.conf} file if it differs from the default
+value.
+The default values can be found at \l{Overriding Paths}.
+
+The \c file_path argument expects an absolute path to the location where the
+\c qt.conf file should be written to. The \l{QT_DEPLOY_PREFIX} and \l{QT_DEPLOY_BIN_DIR}
+variables can be used to dynamically specify a path relative to the deployment binary directory,
+as shown in the example below. This helps avoid hard-coding an absolute path.
+
+\sa {qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()},
+ {qt6_deploy_runtime_dependencies}{qt_deploy_runtime_dependencies()}
+
+\section1 Example
+
+\badcode
+# The following script must only be executed at install time
+qt_generate_deploy_script(
+ OUTPUT_SCRIPT deploy_script
+ CONTENT "
+qt_deploy_qt_conf(\"\${QT_DEPLOY_PREFIX}/\${QT_DEPLOY_BIN_DIR}/qt.conf\"
+ DATA_DIR \"./custom_data_dir\"
+ TRANSLATIONS_DIR \"./custom_translations_dir\"
+)
+")
+
+install(SCRIPT ${deploy_script})
+\endcode
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_deploy_runtime_dependencies.qdoc b/src/corelib/doc/src/cmake/qt_deploy_runtime_dependencies.qdoc
new file mode 100644
index 0000000000..f64960492a
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_deploy_runtime_dependencies.qdoc
@@ -0,0 +1,198 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-deploy-runtime-dependencies.html
+\ingroup cmake-commands-qtcore
+
+\title qt_deploy_runtime_dependencies
+\keyword qt6_deploy_runtime_dependencies
+
+\summary {Deploy Qt plugins, Qt and non-Qt libraries needed by an executable.}
+
+\include cmake-find-package-core.qdocinc
+
+Unlike most other CMake commands provided by Qt, \c{qt_deploy_runtime_dependencies()}
+can only be called from a deployment script. It cannot be called directly by the
+project during the configure stage.
+
+\cmakecommandsince 6.3
+\note This command does not usually need to be called directly. It is used
+ internally by other higher level commands, but projects wishing to
+ implement more customized deployment logic may find it useful.
+
+\section1 Synopsis
+
+\badcode
+qt_deploy_runtime_dependencies(
+ EXECUTABLE executable
+ [ADDITIONAL_EXECUTABLES files...]
+ [ADDITIONAL_LIBRARIES files...]
+ [ADDITIONAL_MODULES files...]
+ [GENERATE_QT_CONF]
+ [BIN_DIR bin_dir]
+ [LIBEXEC_DIR libexec_dir]
+ [LIB_DIR lib_dir]
+ [PLUGINS_DIR plugins_dir]
+ [QML_DIR qml_dir]
+ [VERBOSE]
+ [NO_OVERWRITE]
+ [NO_APP_STORE_COMPLIANCE]
+ [NO_TRANSLATIONS]
+ [NO_COMPILER_RUNTIME]
+ [DEPLOY_TOOL_OPTIONS]
+ [PRE_INCLUDE_REGEXES regexes...]
+ [PRE_EXCLUDE_REGEXES regexes...]
+ [POST_INCLUDE_REGEXES regexes...]
+ [POST_EXCLUDE_REGEXES regexes...]
+ [POST_INCLUDE_FILES files...]
+ [POST_EXCLUDE_FILES files...]
+)
+\endcode
+
+\section1 Description
+
+When installing an application, it may be desirable to also install the
+libraries and plugins it depends on. When the application is a macOS app bundle
+or a Windows executable, \c{qt_deploy_runtime_dependencies()} can be called
+from an install-time script to deploy those dependencies. It will install
+non-system Qt libraries plus an appropriate set of Qt plugins.
+
+On Linux, the command will deploy additional libraries, beyond just those
+related to Qt, that are included with the project. However, when executed on
+macOS or Windows, the command will use either \c macdeployqt or \c windeployqt,
+which will only deploy libraries that are specific to Qt.
+
+This command only considers runtime dependencies for which linking
+relationships exist in the underlying binaries. It does not deploy QML modules,
+see \l{qt6_deploy_qml_imports}{qt_deploy_qml_imports()} for that.
+
+\section1 Arguments
+
+The \c{EXECUTABLE} option must be provided.
+
+The \c{executable} argument should be the path to the executable file in the
+build directory. For example, \c{${CMAKE_CURRENT_BINARY_DIR}/MyApp.exe}, or more
+dynamically \c{$<TARGET_FILE:MyApp>}. Specifying raw target names not wrapped in
+a generator expression like \c{<TARGET_FILE:>} is not supported.
+
+For macOS app bundles, the \c{executable} argument should be a path to the
+bundle directory, relative to the base install location.
+For example \c{MyApp.app}, or more dynamically
+\c{$<TARGET_FILE_NAME:MyApp>.app}.
+Specifying raw target names not wrapped in a generator epxression like
+\c{<TARGET_FILE_NAME:>} is not supported.
+
+It may also be desirable to install dependencies for other binaries related to
+the \c{executable}. For example, plugins provided by the project might have
+further dependencies, but because those plugins won't be linked directly to the
+executable, \c{qt_deploy_runtime_dependencies()} won't automatically discover
+them. The \c{ADDITIONAL_EXECUTABLES}, \c{ADDITIONAL_LIBRARIES}, and
+\c{ADDITIONAL_MODULES} options can be used to specify additional binaries
+whose dependencies should also be deployed (installing the named binaries
+themselves is still the project's responsibility). The naming of these keywords
+follows CMake's conventions, so Qt plugins would be specified using
+\c{ADDITIONAL_MODULES}.
+Each value should be a path relative to the base install location. The values
+can use generator expressions, same as with the \c{EXECUTABLE} option.
+Specifying raw target names not wrapped in a generator epxression like
+\c{<TARGET_FILE_NAME:>} is not supported.
+
+When installing a Windows application, it is common to need a
+\l{Using qt.conf}{qt.conf} file when following CMake's default install
+directory structure. If the \c{GENERATE_QT_CONF} option is given, an appropriate
+\c{qt.conf} file will be written to the same directory as the \c{executable}.
+The paths in that \c{qt.conf} file will be based on the \c{CMAKE_INSTALL_xxxDIR}
+variables, whose defaults are provided by CMake's \l{GNUInstallDirs} module.
+
+You can override some of those defaults with the parameters in the following
+table, all of which are expected to be relative to the base install location.
+
+\table
+\header
+ \li parameter
+ \li affected variable
+ \li notes
+\row
+ \li \c BIN_DIR
+ \li \l QT_DEPLOY_BIN_DIR
+ \li
+\row
+ \li \c LIBEXEC_DIR
+ \li \l QT_DEPLOY_LIBEXEC_DIR
+ \li since Qt 6.7
+\row
+ \li \c LIB_DIR
+ \li \l QT_DEPLOY_LIB_DIR
+ \li
+\row
+ \li \c PLUGINS_DIR
+ \li \l QT_DEPLOY_PLUGINS_DIR
+ \li
+\row
+ \li \c QML_DIR
+ \li \l QT_DEPLOY_QML_DIR
+ \li
+\endtable
+
+A \c{qt.conf} file is always written if \c{executable} is a macOS app bundle,
+regardless of whether or not \c{GENERATE_QT_CONF} is provided. The \c{..._DIR}
+options are also ignored in that case, since the directory layout of an app
+bundle is dictated by Apple's requirements.
+
+More verbose output about the deployment steps can be enabled by providing the
+\c{VERBOSE} option. Alternatively, the \l{QT_ENABLE_VERBOSE_DEPLOYMENT}
+variable can be set in the project before the first \c{find_package(Qt6)} call
+to make deployment output verbose by default.
+
+The \c{qt_deploy_runtime_dependencies()} command overwrites existing files by
+default (some warnings may still be issued). Use the \c{NO_OVERWRITE} option
+to prevent overwriting existing files. Note that this option currently only
+affects macOS and Windows deployments.
+
+By default, if \c{executable} is a macOS app bundle, only Qt plugins and Qt
+libraries that comply with Apple's app store requirements are deployed. The
+\c{NO_APP_STORE_COMPLIANCE} option can be given to disable that constraint.
+
+On platforms other than macOS, Qt translations are automatically deployed. To
+inhibit this behavior, specify \c{NO_TRANSLATIONS}. Use
+\l{qt6_deploy_translations}{qt_deploy_translations()} to deploy translations
+in a customized way.
+
+For Windows desktop applications, the required runtime files for the compiler
+are also installed by default. To prevent this, specify \c{NO_COMPILER_RUNTIME}.
+
+Since Qt 6.7, you can use \c{DEPLOY_TOOL_OPTIONS} to pass additional options to
+the underlying deployment tool. This only has an effect if the underlying
+deployment tool is either macdeployqt or windeployqt.
+
+On Linux, deploying runtime dependencies is based on CMake's
+\c{file(GET_RUNTIME_DEPENDENCIES)} command. The options \c{PRE_INCLUDE_REGEXES},
+\c{PRE_EXCLUDE_REGEXES}, \c{POST_INCLUDE_REGEXES}, \c{POST_EXCLUDE_REGEXES},
+\c{POST_INCLUDE_FILES}, and \c{POST_EXCLUDE_FILES} are only meaningful in this
+context and are forwarded unaltered to \c{file(GET_RUNTIME_DEPENDENCIES)}. See
+the documentation of that command for details.
+
+On Linux, runtime dependencies that are located in system library directories
+are not deployed by default. If \c{POST_EXCLUDE_REGEXES} is specified, this
+automatic exclusion is not performed.
+
+The default value of \c{POST_EXCLUDE_REGEXES} is constructed from the value of
+\l{QT_DEPLOY_IGNORED_LIB_DIRS}.
+
+\sa {qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()},
+ {qt6_deploy_qt_conf}{qt_deploy_qt_conf()},
+ {qt6_deploy_qml_imports}{qt_deploy_qml_imports()}
+
+\section1 Example
+
+The following example shows how to deploy an application \c{MyApp}.
+
+\include cmake-deploy-runtime-dependencies.qdocinc
+
+The following example shows how to use the \c{DEPLOY_TOOL_OPTIONS} parameter to
+pass different options to macdeployqt and windeployqt.
+
+\include cmake-deploy-runtime-dependencies-deploy-tool-options.qdocinc
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_deploy_translations.qdoc b/src/corelib/doc/src/cmake/qt_deploy_translations.qdoc
new file mode 100644
index 0000000000..43ff23a35a
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_deploy_translations.qdoc
@@ -0,0 +1,76 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-deploy-translations.html
+\ingroup cmake-commands-qtcore
+
+\title qt_deploy_translations
+\keyword qt6_deploy_translations
+
+\summary {Deploy Qt translations needed by an executable.}
+
+\include cmake-find-package-core.qdocinc
+
+Unlike most other CMake commands provided by Qt, \c{qt_deploy_translations()}
+can only be called from a deployment script. It cannot be called directly by the
+project during the configure stage.
+
+\cmakecommandsince 6.5
+\preliminarycmakecommand
+\note This command does not usually need to be called directly. It is used
+ internally by other higher level commands, but projects wishing to
+ implement more customized deployment logic may find it useful.
+
+\section1 Synopsis
+
+\badcode
+qt_deploy_translations(
+ [CATALOGS catalogs]
+ [LOCALES locales]
+ [LCONVERT lconvert_executable]
+ [VERBOSE]
+)
+\endcode
+
+\section1 Description
+
+When installing an application, it may be desirable to also install the
+translations that belong to the used Qt modules. The \c qt_deploy_translations
+command collects the necessary \c{.qm} file from the Qt installation and
+compiles them into one \c{qt_${language}.qm} file per language. The \c{.qm}
+files are installed into \c{QT_DEPLOY_TRANSLATIONS_DIR}.
+
+\section1 Arguments
+
+The \c LOCALES argument specifies for which locales translations should be
+deployed. This is a list of language/region combinations as described in
+\l{Changing the Target Locale}{Qt Linguist's manual for translators}. Examples
+for valid locales are: \c{de}, \c{pl}, or \c{pt_BR}.
+
+If \c LOCALES is omitted, then all available locales are deployed.
+
+The \c CATALOGS argument specifies a list of \l{Available
+Catalogs}{translation catalogs} to be deployed. If this argument is
+omitted, then all catalogs are deployed that belong to any Qt module
+that is used in the project via \c{find_package}.
+
+The \c LCONVERT argument specifies the \c lconvert executable that is used to
+combine the catalogs. By default, the Qt installation's \c lconvert is used.
+
+For debugging purposes, the \c VERBOSE argument can be set to turn on diagnostic
+messages.
+
+\sa QT_DEPLOY_TRANSLATIONS_DIR
+
+\section1 Example
+
+The following example deploys Danish and German translations of the Qt
+libraries.
+
+\badcode
+qt_deploy_translations(
+ LOCALES da de
+)
+\endcode
+*/
diff --git a/src/corelib/doc/src/cmake/qt_disable_unicode_defines.qdoc b/src/corelib/doc/src/cmake/qt_disable_unicode_defines.qdoc
new file mode 100644
index 0000000000..91de52544e
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_disable_unicode_defines.qdoc
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-disable-unicode-defines.html
+\ingroup cmake-commands-qtcore
+
+\title qt_disable_unicode_defines
+\keyword qt6_disable_unicode_defines
+
+\summary {Prevents some unicode-related compiler definitions being set automatically on a target.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.2
+
+\section1 Synopsis
+
+\badcode
+qt_disable_unicode_defines(target)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_disable_unicode_defines()
+
+\section1 Description
+
+In Qt 6, the \c UNICODE and \c{_UNICODE} compiler definitions are set by
+default for targets that link against Qt modules. This is in line with the
+qmake behavior, but it is a change compared to the CMake API behavior in Qt 5.
+Calling \c{qt_disable_unicode_defines()} on a \c target prevents these compiler
+definitions from being automatically set.
+
+\sa {qt6_allow_non_utf8_sources}{qt_allow_non_utf8_sources()}
+*/
diff --git a/src/corelib/doc/src/cmake/qt_extract_metatypes.qdoc b/src/corelib/doc/src/cmake/qt_extract_metatypes.qdoc
new file mode 100644
index 0000000000..7ec8d90f9b
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_extract_metatypes.qdoc
@@ -0,0 +1,69 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-extract-metatypes.html
+\ingroup cmake-commands-qtcore
+
+\title qt_extract_metatypes
+\keyword qt6_extract_metatypes
+
+\summary {Extracts metatypes from a Qt target and generates an associated metatypes.json file.}
+
+\cmakecommandsince 6.0
+\preliminarycmakecommand
+
+\section1 Synopsis
+
+\badcode
+qt_extract_metatypes(target
+ [MANUAL_MOC_JSON_FILES json_files...]
+ [OUTPUT_FILES variable_name]
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_extract_metatypes()
+
+\section1 Description
+
+Certain operations rely on metatype information being generated and collected
+on targets. This is typically handled internally by Qt commands, but for
+scenarios where this is not the case, \c{qt_extract_metatypes()} can be called
+to force the collection of this information for a specific \c target.
+
+Metatype information is generated for a target's source files in one of the
+following ways:
+
+\list
+\li Automatically by AUTOMOC. The \c{qt_extract_metatypes()} command detects
+ when AUTOMOC is enabled on the \c target and will automatically extract the
+ information it needs.
+\li Manually by invoking \c moc with the \c{--output-json} option. The project
+ is responsible for keeping track of all the JSON files generated using this
+ method and passing them to \c{qt_extract_metatypes()} with the
+ \c MANUAL_MOC_JSON_FILES option.
+\endlist
+
+\c{qt_extract_metatypes()} produces a target-specific metatypes JSON file which
+collects all the metatype details from the AUTOMOC and manual moc inputs.
+It does this by calling \c moc with the \c{--collect-json} option.
+If you need to know where to find the resultant metatypes JSON file (for
+example, to pass it to another command or to install it), use the
+\c OUTPUT_FILES option to provide the name of a variable in which to store its
+absolute path.
+
+\section1 Automatic metatype extraction
+
+Since Qt 6.8, if you have not disabled \c{AUTOMOC} and either are using CMake
+3.19 or later or are calling \l{qt6_finalize_target}{qt_finalize_target()}
+manually, then \c{qt_extract_metatypes()} is automatically called as part of the
+finalization step for \l{qt_add_library}. This has no effect if you have
+manually called \c{qt_extract_metatypes()} before the finalization, possibly
+with custom arguments. However, it does make sure that the metatypes are also
+produced if you haven't. This is important if any of the types in the library
+are used as part of any QML types any time in the future and has no downsides.
+
+Furthermore, \l{qt_add_qml_module} automatically invokes
+\c{qt_extract_metatypes()} for its target.
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_finalize_project.qdoc b/src/corelib/doc/src/cmake/qt_finalize_project.qdoc
new file mode 100644
index 0000000000..5506712691
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_finalize_project.qdoc
@@ -0,0 +1,53 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-finalize-project.html
+\ingroup cmake-commands-qtcore
+
+\title qt_finalize_project
+\keyword qt6_finalize_project
+
+\summary {Handles various common platform-specific tasks associated with a Qt project.}
+\preliminarycmakecommand
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.3
+
+\section1 Synopsis
+
+\badcode
+qt_finalize_project()
+\endcode
+
+\versionlessCMakeCommandsNote qt6_finalize_project()
+
+\section1 Description
+
+Some targets that are created using Qt commands require additional actions
+at the end of CMake configuring phase.
+Depending on the platform, the function typically:
+\list
+ \li Walks the build tree.
+ \li Resolves dependencies.
+ \li Applies any extra deployment steps.
+\endlist
+
+With CMake version 3.19 or later, you don't need to call this command since
+it consists of sub-commands that are ordinarily invoked at the end of
+\c CMAKE_SOURCE_DIR directory scope processing.
+
+\include cmake-android-qt-finalize-project-warning.qdocinc warning
+
+\section2 Examples
+
+For projects that use a CMake version lower than 3.19, you need to call
+\c qt_finalize_project manually. This example shows the typical use of the
+function:
+
+\snippet cmake-macros/examples.cmake qt_finalize_project_manual
+
+\sa {cmake-variable-QT_NO_COLLECT_BUILD_TREE_APK_DEPS}{QT_NO_COLLECT_BUILD_TREE_APK_DEPS}
+\sa {cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS}{QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS}
+*/
diff --git a/src/corelib/doc/src/cmake/qt_finalize_target.qdoc b/src/corelib/doc/src/cmake/qt_finalize_target.qdoc
new file mode 100644
index 0000000000..b74dee64d2
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_finalize_target.qdoc
@@ -0,0 +1,89 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-finalize-target.html
+\ingroup cmake-commands-qtcore
+
+\title qt_finalize_target
+\keyword qt6_finalize_target
+
+\summary {Handles various common platform-specific tasks associated with Qt targets.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.2
+
+\section1 Synopsis
+
+\badcode
+qt_finalize_target(target)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_finalize_target()
+
+\section1 Description
+
+After a target is created, further processing or \e{finalization} steps are
+sometimes needed. The steps to perform depend on the platform, the type of
+target, and on various properties of the target. These steps are expected to be
+performed within the same directory scope as the one in which the \c{target}
+was created, so this command should also be called from that same directory
+scope.
+
+This command is ordinarily invoked as part of a call to
+\l{qt6_add_executable}{qt_add_executable()},
+\l{qt6_add_library}{qt_add_library()}, or \l{qt6_add_plugin}{qt_add_plugin()}.
+The timing of when that call takes place and when a project might need to call
+it explicitly, is discussed in the documentation of those commands.
+
+\sa {qt6_set_finalizer_mode}{qt_set_finalizer_mode()}
+
+\section1 Executable Targets
+
+For executable targets, \c{qt_finalize_target()} implements the logic described
+in the subsections below, as appropriate for the platform and target provided.
+Later Qt releases may expand finalization processing further.
+
+\section2 All Platforms
+
+Some internal processing is performed to facilitate automatic linking of Qt
+plugins. This is especially important if using a statically built Qt or a
+CMake version earlier than 3.21.
+
+\section2 Android
+
+\list
+\li Generate a deployment settings file for the \c target.
+\li Create a build target for generating an APK.
+\endlist
+
+\section2 WASM
+
+Create \c{${target}.html} (a target-specific \c{wasm_shell.html} file),
+\c{qtloader.js}, and \c{qtlogo.svg} files in the \c{CMAKE_CURRENT_BINARY_DIR}.
+
+\section2 iOS
+
+Finalization attempts to provide sensible values for the following target
+properties if they are not already set, and their corresponding \c{CMAKE_...}
+variable is also not set:
+
+\list
+\li \c XCODE_ATTRIBUTE_DEVELOPMENT_TEAM
+\li \c XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER
+\li \c MACOSX_BUNDLE_GUI_IDENTIFIER
+\endlist
+
+If required, the \l QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID variable can be used to
+disable setting \c XCODE_ATTRIBUTE_DEVELOPMENT_TEAM, and the
+\l QT_NO_SET_XCODE_BUNDLE_IDENTIFIER variable can be used to disable setting
+\c XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER and \c MACOSX_BUNDLE_GUI_IDENTIFIER.
+
+\section1 Library Targets
+
+As of this Qt version, finalization for library targets does not perform any
+processing. Future Qt versions may add finalization processing for libraries,
+so you should ensure finalization is still invoked in the expected way.
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc b/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc
new file mode 100644
index 0000000000..31d9e4384b
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc
@@ -0,0 +1,110 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-generate-deploy-app-script.html
+\ingroup cmake-commands-qtcore
+
+\title qt_generate_deploy_app_script
+\keyword qt6_generate_deploy_app_script
+
+\summary {Generate a deployment script for an application.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.3
+\note This command is currently only supported on Windows, macOS, and Linux.
+
+\section1 Synopsis
+
+\badcode
+qt_generate_deploy_app_script(
+ TARGET target
+ OUTPUT_SCRIPT <var>
+ [NO_TRANSLATIONS]
+ [NO_COMPILER_RUNTIME]
+ [NO_UNSUPPORTED_PLATFORM_ERROR]
+ [DEPLOY_TOOL_OPTIONS ...]
+ [PRE_INCLUDE_REGEXES regexes...]
+ [PRE_EXCLUDE_REGEXES regexes...]
+ [POST_INCLUDE_REGEXES regexes...]
+ [POST_EXCLUDE_REGEXES regexes...]
+ [POST_INCLUDE_FILES files...]
+ [POST_EXCLUDE_FILES files...]
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_generate_deploy_app_script()
+
+\section1 Description
+
+Installing an executable target with \l{install(TARGETS)} only installs the
+target's executable (except for macOS app bundles, which will copy the whole
+bundle). You need to explicitly install any other libraries or plugins the
+executable depends on yourself. \c{qt_generate_deploy_app_script()} is a
+convenience command intended to simplify that process. It expects the
+application to follow Qt's recommended install directory structure fairly
+closely. That structure is based on CMake's default install layout, as
+determined by \l{GNUInstallDirs} (except for macOS app bundles, which follow
+Apple's requirements instead).
+
+The command generates a script whose name will be stored in the variable named
+by the \c{OUTPUT_SCRIPT} option. That script is only written at CMake
+generation time. It is intended to be used with the \l{install(SCRIPT)} command,
+which should come after the application's target has been installed using
+\l{install(TARGETS)}.
+
+The deployment script will call \l{qt6_deploy_runtime_dependencies}
+{qt_deploy_runtime_dependencies()} with a suitable set of options for the standard
+install layout. Currently, this is only implemented for
+\list
+ \li macOS app bundles built on a macOS host,
+ \li Linux executables built on a Linux host,
+ \li and Windows executables built on a Windows host.
+\endlist
+Cross-building a Windows executable on a Linux host, as well as similar
+scenarios, are not currently supported.
+Calling \c{qt_generate_deploy_app_script()} in such a case will result
+in a fatal error, unless the \c{NO_UNSUPPORTED_PLATFORM_ERROR} option is given.
+
+On platforms other than macOS, Qt translations are automatically deployed. To
+inhibit this behavior, specify \c{NO_TRANSLATIONS}. Use
+\l{qt6_deploy_translations}{qt_deploy_translations()} to deploy translations in a
+customized way.
+
+For Windows desktop applications, the required runtime files for the compiler
+are also installed by default. To prevent this, specify \c{NO_COMPILER_RUNTIME}.
+
+Since Qt 6.7, you can use \c{DEPLOY_TOOL_OPTIONS} to pass additional options to
+the underlying deployment tool. This only has an effect if the underlying
+deployment tool is either macdeployqt or windeployqt.
+
+For deploying a QML application, use
+\l{qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()}
+instead.
+
+For generating a custom deployment script, use
+\l{qt6_generate_deploy_script}{qt_generate_deploy_script}.
+
+The options \c{PRE_INCLUDE_REGEXES}, \c{PRE_EXCLUDE_REGEXES},
+\c{POST_INCLUDE_REGEXES}, \c{POST_EXCLUDE_REGEXES}, \c{POST_INCLUDE_FILES}, and
+\c{POST_EXCLUDE_FILES} can be specified to control the deployment of runtime
+dependencies. These options do not apply to all platforms and are forwarded
+unmodified to \l{qt6_deploy_runtime_dependencies}{qt_deploy_runtime_dependencies()}.
+
+\sa {qt6_standard_project_setup}{qt_standard_project_setup()},
+ {qt6_generate_deploy_script}{qt_generate_deploy_script()},
+ {qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()}
+
+\section1 Example
+
+The following example shows how to deploy an application \c{MyApp}.
+
+\include cmake-generate-deploy-app-script.qdocinc
+
+The following example shows how to use the \c{DEPLOY_TOOL_OPTIONS} parameter to
+pass different options to macdeployqt and windeployqt.
+
+\include cmake-generate-deploy-app-script-deploy-tool-options.qdocinc
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc b/src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc
new file mode 100644
index 0000000000..eb8ed402a9
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc
@@ -0,0 +1,65 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-generate-deploy-script.html
+\ingroup cmake-commands-qtcore
+
+\title qt_generate_deploy_script
+\keyword qt6_generate_deploy_script
+
+\summary {Generate a custom deployment script.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.5
+
+\section1 Synopsis
+
+\badcode
+qt_generate_deploy_script(
+ OUTPUT_SCRIPT <var>
+ [TARGET target]
+ [NAME script_name]
+ [CONTENT content]
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_generate_deploy_script()
+
+\section1 Description
+
+The command generates a script whose full file path will be stored in the
+variable named by the \c{OUTPUT_SCRIPT} option. That script is only written
+at CMake generation time. It is intended to be used with the \l{install(SCRIPT)}
+command, which should come after the application's target has been installed
+using \l{install(TARGETS)}.
+
+The command takes care of generating a file named suitably for multi-config
+generators. Necessary includes are added such that Qt's CMake deployment
+functions and variables are accessible.
+
+The \c TARGET argument specifies the target that will be deployed by the script.
+This affects the file name of the generated script, unless \c NAME is specified.
+
+The \c NAME argument controls an identifiable portion within the deployment
+script's automatically generated name. The \c NAME argument defaults to \c
+custom if neither \c NAME nor \c TARGET are given.
+
+The \c CONTENT argument specifies the code that is written to the deployment
+script. The content may contain generator expressions.
+
+This command is intended for generating custom deployment scripts that
+directly call functions of Qt's deployment API. For less complex
+deployment purposes, it is more convenient to use
+\l{qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()} or
+\l{qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()}.
+
+\sa {qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()},
+ {qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()}
+
+\section1 Example
+
+\snippet cmake-macros/deployment.cmake qt_generate_deploy_script_example
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_generate_moc.qdoc b/src/corelib/doc/src/cmake/qt_generate_moc.qdoc
new file mode 100644
index 0000000000..9b123f9323
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_generate_moc.qdoc
@@ -0,0 +1,45 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-generate-moc.html
+\ingroup cmake-commands-qtcore
+
+\title qt_generate_moc
+\keyword qt6_generate_moc
+
+\summary {Calls moc on an input file.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 5.0
+
+\section1 Synopsis
+
+\badcode
+qt_generate_moc(src_file dest_file
+ [TARGET target])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_generate_moc()
+
+\section1 Description
+
+Creates a rule to call the \l{moc}{Meta-Object Compiler (moc)} on \c src_file
+and store the output in \c dest_file.
+
+\note This is a low-level macro. See the \l{CMake AUTOMOC Documentation} for a
+more convenient way to let source files be processed with \c{moc}.
+\l qt_wrap_cpp is also similar, but automatically generates a temporary file
+path for you.
+
+\section1 Arguments
+
+You can set an explicit \c{TARGET}. This will make sure that the target
+properties \c{INCLUDE_DIRECTORIES} and \c{COMPILE_DEFINITIONS} are also used
+when scanning the source files with \c{moc}.
+
+\section1 Examples
+
+\snippet cmake-macros/examples.cmake qt_generate_moc
+*/
diff --git a/src/corelib/doc/src/cmake/qt_import_plugins.qdoc b/src/corelib/doc/src/cmake/qt_import_plugins.qdoc
new file mode 100644
index 0000000000..1f81a21cd2
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_import_plugins.qdoc
@@ -0,0 +1,97 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-import-plugins.html
+\ingroup cmake-commands-qtcore
+
+\title qt_import_plugins
+\keyword qt6_import_plugins
+
+\summary {Specifies a custom set of plugins to import or exclude.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 5.14
+
+\section1 Synopsis
+
+\badcode
+qt_import_plugins(target
+ [INCLUDE plugin ...]
+ [EXCLUDE plugin ...]
+ [INCLUDE_BY_TYPE plugin_type plugin ...]
+ [EXCLUDE_BY_TYPE plugin_type]
+ [NO_DEFAULT]
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_import_plugins()
+
+\section1 Description
+
+Specifies a custom set of plugins to import. The optional arguments:
+\c INCLUDE, \c EXCLUDE, \c INCLUDE_BY_TYPE, and \c EXCLUDE_BY_TYPE,
+can be used more than once.
+
+\list
+\li \c INCLUDE -- can be used to specify a list of plugins to import.
+\li \c EXCLUDE -- can be used to specify a list of plugins to exclude.
+\li \c INCLUDE_BY_TYPE -- can be used to override the list of plugins to
+ import for a certain plugin type.
+\li \c EXCLUDE_BY_TYPE -- can be used to specify a plugin type to exclude;
+ then no plugins of that type are imported.
+\li \c NO_DEFAULT -- prevent the default plugins from being included
+ automatically (for example, the default platform plugin).
+\endlist
+
+Qt provides plugin types such as \c imageformats, \c platforms,
+and \c sqldrivers.
+
+\section2 Dynamic plugins
+
+If plugins are dynamic libraries, the function controls the plugin deployment.
+Using this function, you may exclude specific plugin types from
+being packaged into an Android APK, for example:
+
+\badcode
+qt_add_executable(MyApp ...)
+...
+qt_import_plugins(MyApp EXCLUDE_BY_TYPE imageformats)
+\endcode
+
+In the snippet above, all plugins that have the \c imageformats type will
+be excluded when deploying \c MyApp. The resulting Android APK will not
+contain any of the \c imageformats plugins.
+
+If the command isn't used, the target automatically deploys all plugins that
+belong to the Qt modules that the target is linked against.
+
+\section2 Static plugins
+
+If the command isn't used the target automatically links against
+a sane set of default static plugins, for each Qt module that the target is
+linked against. For more information, see
+\l{CMake target_link_libraries Documentation}{target_link_libraries}.
+
+Each plugin comes with a C++ stub file that automatically
+initializes the static plugin. Consequently, any target that links against
+a plugin has this C++ file added to its \c SOURCES.
+
+\section1 Examples
+
+\snippet cmake-macros/examples.cmake qt_import_plugins
+
+In the snippet above, the following occurs with the executable \c myapp:
+
+\list
+\li The \c Qt6::QCocoaIntegrationPlugin is imported into myapp.
+\li The \c Qt6::QMinimalIntegrationPlugin plugin is
+ excluded from being automatically imported into myapp.
+\li The default list of plugins for \c imageformats is
+ overridden to only include Qt6::QGifPlugin and Qt6::QJpegPlugin.
+\li All \c sqldrivers plugins are excluded from automatic importing.
+\endlist
+
+\sa{qt6_import_qml_plugins}{qt_import_qml_plugins()}
+*/
diff --git a/src/corelib/doc/src/cmake/qt_policy.qdoc b/src/corelib/doc/src/cmake/qt_policy.qdoc
new file mode 100644
index 0000000000..6deb7a729c
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_policy.qdoc
@@ -0,0 +1,65 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-policy.html
+\ingroup cmake-commands-qtcore
+
+\title qt_policy
+\keyword qt6_policy
+
+\summary {Modify the default behavior of Qt's CMake API.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.5
+
+\section1 Synopsis
+
+\badcode
+qt_policy(
+ [SET <policy_name> behavior]
+ [GET <policy_name> <variable>]
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_policy()
+
+\section1 Description
+
+This command has two modes:
+
+\list
+\li When the \c{SET} keyword is used, this command can be used to opt in to
+ behavior changes in Qt's CMake API, or to explicitly opt out of them.
+\li When the \c{GET} keyword is used, \c{<variable>} is set to the current
+ behavior for the policy, i.e. \c OLD or \c NEW.
+\endlist
+
+\c{<policy_name>} must be the name of one of the \l{Qt CMake policies}.
+Policy names have the form of \c{QTP<NNNN>} where <NNNN> is
+an integer specifying the index of the policy. Using an invalid policy
+name results in an error.
+
+Code supporting older Qt versions can check the existence of a policy by
+checking the value of the \c{QT_KNOWN_POLICY_<policy_name>} variable before
+getting the value of \c <policy_name> or setting its behavior.
+
+\badcode
+if(QT_KNOWN_POLICY_<policy_name>)
+ qt_policy(SET <policy_name> NEW)
+endif()
+\endcode
+
+You can set \c behavior to one of the following options:
+
+\list
+\li \c{NEW} to opt into the new behavior
+\li \c{OLD} to explicitly opt-out of it
+\endlist
+
+\qtpolicydeprecatedbehavior
+
+\sa qt_standard_project_setup
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_set_finalizer_mode.qdoc b/src/corelib/doc/src/cmake/qt_set_finalizer_mode.qdoc
new file mode 100644
index 0000000000..28622c11e8
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_set_finalizer_mode.qdoc
@@ -0,0 +1,90 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-set-finalizer-mode.html
+\ingroup cmake-commands-qtcore
+
+\title qt_set_finalizer_mode
+\keyword qt6_set_finalizer_mode
+
+\summary {Customizes aspects of a target's finalization.}
+
+\cmakecommandsince 6.2
+\preliminarycmakecommand
+
+\section1 Synopsis
+
+\badcode
+qt_set_finalizer_mode(target
+ ENABLE | DISABLE
+ MODES modes...
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_set_finalizer_mode()
+
+\section1 Description
+
+This command is used to customize some aspects of the finalization of a
+specific \c target. It only has an effect if called before \c target is
+finalized, which occurs in one of the following scenarios:
+
+\list
+\li The project explicitly calls \l{qt6_finalize_target}{qt_finalize_target()}
+ for the \c target. This usually means the \c MANUAL_FINALIZATION keyword was
+ passed to \l{qt6_add_executable}{qt_add_executable()} when the \c target
+ was defined.
+\li CMake 3.17 or earlier is being used, in which case finalization always
+ occurs immediately as part of the call to
+ \l{qt6_add_executable}{qt_add_executable()}.
+\li CMake 3.18 or later is being used, the \c MANUAL_FINALIZATION keyword was
+ not passed to \l{qt6_add_executable}{qt_add_executable()} when the \c target
+ was defined, and deferred finalization has been completed at the end of the
+ \c target's directory scope.
+\endlist
+
+\c{qt_set_finalizer_mode()} is used to enable or disable a list of \e modes,
+where a mode corresponds to a specific aspect of finalization. The currently
+supported finalization modes are:
+
+\table
+\header
+ \li Mode
+ \li Default
+ \li Finalization behavior
+\row
+ \li \c static_plugins
+ \li Enabled
+ \li When Qt is built statically, it creates initializer object libraries
+ for its static plugins. If \c target is an executable and this
+ finalization mode is enabled, any plugin initializer object libraries
+ needed by the \c target will be directly linked to it. This
+ prevents cycles between Qt-provided static libraries and may reduce
+ link time. When this finalizer mode is disabled, each plugin
+ initializer is instead propagated via usage requirements of its
+ associated Qt library, which may cause cycles. If Qt is not built
+ statically, this finalizer mode is not relevant and isn't used.
+\endtable
+
+\sa {qt6_finalize_target}{qt_finalize_target()}
+
+\section1 Example
+
+The following example assumes you are using CMake 3.19 or later (required for
+deferred finalization):
+
+\badcode
+qt_add_executable(my_app main.cpp)
+qt_set_finalizer_mode(my_app ENABLE MODES static_plugins)
+\endcode
+
+The same example using manual finalization might look like this:
+
+\badcode
+qt_add_executable(my_app MANUAL_FINALIZATION main.cpp)
+qt_set_finalizer_mode(my_app ENABLE MODES static_plugins)
+qt_finalize_target(my_app)
+\endcode
+
+*/
diff --git a/src/corelib/doc/src/cmake/qt_standard_project_setup.qdoc b/src/corelib/doc/src/cmake/qt_standard_project_setup.qdoc
new file mode 100644
index 0000000000..59b33f599c
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_standard_project_setup.qdoc
@@ -0,0 +1,101 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-standard-project-setup.html
+\ingroup cmake-commands-qtcore
+
+\title qt_standard_project_setup
+\keyword qt6_standard_project_setup
+
+\summary {Setup project-wide defaults to a standard arrangement.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 6.3
+
+\section1 Synopsis
+
+\badcode
+qt_standard_project_setup(
+ [REQUIRES <version>]
+ [SUPPORTS_UP_TO <version>]
+ [I18N_TRANSLATED_LANGUAGES <language...>]
+ [I18N_SOURCE_LANGUAGE <language>]
+)
+\endcode
+
+\versionlessCMakeCommandsNote qt6_standard_project_setup()
+
+\section1 Description
+
+This command simplifies the task of setting up a typical Qt application.
+It would usually be called immediately after the first \c{find_package(Qt6)}
+call, normally in the top level \c{CMakeLists.txt} file and before any targets
+have been defined. It does the following things:
+
+\list
+\li The standard CMake variables \c{CMAKE_AUTOMOC} and \c{CMAKE_AUTOUIC}
+ are set to true if they are not already defined.
+ This enables all Qt-related autogen features by default for subsequently
+ created targets in the current directory scope and below.
+\li CMake's \l{GNUInstallDirs} module is automatically included. This defines
+ appropriate defaults for variables like \c{CMAKE_INSTALL_BINDIR},
+ \c{CMAKE_INSTALL_LIBDIR}, and so on.
+\li When targeting Windows, if the \c{CMAKE_RUNTIME_OUTPUT_DIRECTORY} variable
+ is not already set, it will be set to
+ \c{${CMAKE_CURRENT_BINARY_DIR}}.
+\li When target platforms other than Apple or Windows, \c{CMAKE_INSTALL_RPATH}
+ will be augmented as described below.
+\li CMake's \l USE_FOLDERS property is set to \c{ON}, and \l QT_TARGETS_FOLDER is
+ set to \c{QtInternalTargets}. IDEs that support folders will display
+ Qt-internal targets in this folder.
+\endlist
+
+Since Qt 6.5, it is possible to change the default behavior of Qt's CMake
+API by opting in to changes from newer Qt versions. If \c{REQUIRES} is
+specified, all suggested changes introduced in Qt up to \c{REQUIRES} are enabled,
+and using an older Qt version will result in an error.
+If additionally \c{SUPPORTS_UP_TO} has been specified, any new changes introduced
+in versions up to \c{SUPPORTS_UP_TO} are also enabled (but using an older Qt
+version is not an error). This is similar to CMake's policy concept
+(compare \l{cmake_policy}).
+
+On platforms that support \c{RPATH} (other than Apple platforms), two values
+are appended to the \c{CMAKE_INSTALL_RPATH} variable by this command.
+\c{$ORIGIN} is appended so that libraries will find other libraries they depend
+on in the same directory as themselves. \c{$ORIGIN/<reldir>} is also appended,
+where \c{<reldir>} is the relative path from \c{CMAKE_INSTALL_BINDIR} to
+\c{CMAKE_INSTALL_LIBDIR}. This allows executables installed to
+\c{CMAKE_INSTALL_BINDIR} to find any libraries they may depend on installed to
+\c{CMAKE_INSTALL_LIBDIR}. Any duplicates in \c{CMAKE_INSTALL_RPATH} are
+removed. In practice, these two values ensure that executables and libraries
+will find their link-time dependencies, assuming projects install them to the
+default locations the \l{install(TARGETS)} command uses when no destination is
+explicitly provided.
+
+To disable folder support for IDEs, set \l USE_FOLDERS to \c OFF before or after
+the call to \c{qt_standard_project_setup}.
+
+The \c{qt_standard_project_setup()} command can effectively be disabled by
+setting the \l{QT_NO_STANDARD_PROJECT_SETUP} variable to true.
+
+\sa {qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()}
+\sa qt_policy
+
+\section1 Internationalization
+
+Since Qt 6.7, it is possible to specify the languages that are used for project
+internationalization with the \c I18N_TRANSLATED_LANGUAGES argument. See \l
+QT_I18N_TRANSLATED_LANGUAGES for details.
+
+Use I18N_SOURCE_LANGUAGE to specify the language that translatable strings are
+written in. By default, \c en is used. See \l QT_I18N_SOURCE_LANGUAGE for
+details.
+
+\section1 Example
+
+\include cmake-generate-deploy-app-script.qdocinc
+
+\sa {Automatic Determination of .ts File Paths}{qt_add_translations()}
+*/
diff --git a/src/corelib/doc/src/cmake/qt_wrap_cpp.qdoc b/src/corelib/doc/src/cmake/qt_wrap_cpp.qdoc
new file mode 100644
index 0000000000..3b298a9d7e
--- /dev/null
+++ b/src/corelib/doc/src/cmake/qt_wrap_cpp.qdoc
@@ -0,0 +1,90 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-wrap-cpp.html
+\ingroup cmake-commands-qtcore
+
+\title qt_wrap_cpp
+\keyword qt6_wrap_cpp
+
+\summary {Creates .moc files from sources.}
+
+\include cmake-find-package-core.qdocinc
+
+\cmakecommandsince 5.0
+
+\section1 Synopsis
+
+\badcode
+qt_wrap_cpp(<VAR> src_file1 [src_file2 ...]
+ [TARGET target]
+ [OPTIONS ...]
+ [DEPENDS ...])
+\endcode
+
+\versionlessCMakeCommandsNote qt6_wrap_cpp()
+
+\section1 Description
+
+Creates rules for calling the \l{moc}{Meta-Object Compiler (moc)} on the given
+source files. For each input file, an output file is generated in the build
+directory. The paths of the generated files are added to \c{<VAR>}.
+
+\note This is a low-level macro. See the \l{CMake AUTOMOC Documentation} for a
+more convenient way to let source files be processed with \c{moc}.
+
+\section1 Arguments
+
+You can set an explicit \c{TARGET}. This will make sure that the target
+properties \c{INCLUDE_DIRECTORIES} and \c{COMPILE_DEFINITIONS} are also used
+when scanning the source files with \c{moc}.
+
+Since Qt 6.8, when a source file is passed to \c{qt_wrap_cpp} instead of a
+header file to generate a \c{.moc} file for a target, the \c{TARGET} parameter
+is needed to set the correct include path for the generated \c{.moc} file in
+the source file. As generated \c{.moc} files are added to the target's
+sources by \c{qt_wrap_cpp}, they are not added to \c{<VAR>}.
+
+You can set additional \c{OPTIONS} that should be added to the \c{moc} calls.
+You can find possible options in the \l{moc}{moc documentation}.
+
+The \c{OPTIONS} can evaluate generator expressions when \c{TARGET} is set.
+\note If the \c{OPTIONS} include both generator expressions and special
+characters, use variables to implement them. For example, use \c{$<ANGLE-R>},
+\c{$<COMMA>} and \c{$<SEMICOLON>} instead of \c{>}, \c{,} and \c{:}. Otherwise,
+the generator expression will not be evaluated correctly. \c {OPTIONS} are
+wrapped in generator expressions, so you must escape special characters in
+them.
+
+\c{DEPENDS} allows you to add additional dependencies for recreation of the
+generated files. This is useful when the sources have implicit dependencies,
+like code for a Qt plugin that includes a \c{.json} file using the
+Q_PLUGIN_METADATA() macro.
+
+\section1 Examples
+
+\snippet cmake-macros/examples.cmake qt_wrap_cpp_1
+
+In the following example, the generator expressions passed to \c{OPTIONS}
+will be evaluated since \c{TARGET} is set. The argument is specified this way to
+avoid syntax errors in the generator expressions.
+
+\snippet cmake-macros/examples.cmake qt_wrap_cpp_2
+
+The following example uses \l{https://cmake.org/cmake/help/latest/command/target_compile_definitions.html}{target_compile_definitions}
+to set \l{https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_DEFINITIONS.html}{COMPILE_DEFINITIONS} which will be added to
+\c{OPTIONS}.
+
+\snippet cmake-macros/examples.cmake qt_wrap_cpp_4
+
+\snippet cmake-macros/examples.cpp qt_wrap_cpp_4
+
+In the above file, \c{myapp.moc} is included in \c{myapp.cpp}.
+To generate the \c{myapp.moc} file, the \c{qt_wrap_cpp} macro is used with the
+\c{TARGET} parameter. The first parameter is empty because the \c{.moc} file
+and its path will be added to the target's sources and include directories by
+the \c{qt_wrap_cpp} macro.
+
+\snippet cmake-macros/examples.cmake qt_wrap_cpp_4
+*/
diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc
index 5b9b700669..847be1bff6 100644
--- a/src/corelib/doc/src/containers.qdoc
+++ b/src/corelib/doc/src/containers.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page containers.html
@@ -56,19 +32,15 @@
in situations where they are used as read-only containers
by all threads used to access them.
- For traversing the items stored in a container, you can use one
- of two types of iterators: \l{Java-style iterators} and
- \l{STL-style iterators}. The Java-style iterators are easier to
- use and provide high-level functionality, whereas the STL-style
- iterators are slightly more efficient and can be used together
- with Qt's and STL's \l{generic algorithms}.
-
- Qt also offers a \l{foreach} keyword that make it very
- easy to iterate over all the items stored in a container.
+ The containers provide iterators for traversal. \l{STL-style iterators}
+ are the most efficient ones and can be used together with Qt's and
+ STL's \l{generic algorithms}.
+ \l{Java-style Iterators} are provided for backwards compatibility.
\note Since Qt 5.14, range constructors are available for most of the
container classes. QMultiMap is a notable exception. Their use is
- encouraged in place of the various from/to methods. For example:
+ encouraged to replace of the various deprecated from/to methods of Qt 5.
+ For example:
\snippet code/doc_src_containers.cpp 25
@@ -220,182 +192,39 @@
the C++ language doesn't specify any initialization; in those
cases, Qt's containers automatically initialize the value to 0.
- \section1 The Iterator Classes
-
- Iterators provide a uniform means to access items in a container.
- Qt's container classes provide two types of iterators: Java-style
- iterators and STL-style iterators. Iterators of both types are
- invalidated when the data in the container is modified or detached
- from \l{Implicit Sharing}{implicitly shared copies} due to a call
- to a non-const member function.
-
- \section2 Java-Style Iterators
-
- The Java-style iterators are new in Qt 4 and are the standard
- ones used in Qt applications. They are more convenient to use than
- the STL-style iterators, at the price of being slightly less
- efficient. Their API is modelled on Java's iterator classes.
+ \section1 Iterating over Containers
- For each container class, there are two Java-style iterator data
- types: one that provides read-only access and one that provides
- read-write access.
+ \section2 Range-based for
- \table
- \header \li Containers \li Read-only iterator
- \li Read-write iterator
- \li QMutableListIterator<T>
- \row \li QList<T>, QQueue<T>, QStack<T>, \li QListIterator<T>
- \li QMutableListIterator<T>
- \row \li QSet<T> \li QSetIterator<T>
- \li QMutableSetIterator<T>
- \row \li QMap<Key, T>, QMultiMap<Key, T> \li QMapIterator<Key, T>
- \li QMutableMapIterator<Key, T>
- \row \li QHash<Key, T>, QMultiHash<Key, T> \li QHashIterator<Key, T>
- \li QMutableHashIterator<Key, T>
- \endtable
+ Range-based \c for should preferably be used for containers:
- In this discussion, we will concentrate on QList and QMap. The
- iterator types for QSet have exactly
- the same interface as QList's iterators; similarly, the iterator
- types for QHash have the same interface as QMap's iterators.
-
- Unlike STL-style iterators (covered \l{STL-style
- iterators}{below}), Java-style iterators point \e between items
- rather than directly \e at items. For this reason, they are
- either pointing to the very beginning of the container (before
- the first item), at the very end of the container (after the last
- item), or between two items. The diagram below shows the valid
- iterator positions as red arrows for a list containing four
- items:
-
- \image javaiterators1.png
-
- Here's a typical loop for iterating through all the elements of a
- QList<QString> in order and printing them to the console:
-
- \snippet code/doc_src_containers.cpp 1
-
- It works as follows: The QList to iterate over is passed to the
- QListIterator constructor. At that point, the iterator is located
- just in front of the first item in the list (before item "A").
- Then we call \l{QListIterator::hasNext()}{hasNext()} to
- check whether there is an item after the iterator. If there is, we
- call \l{QListIterator::next()}{next()} to jump over that
- item. The next() function returns the item that it jumps over. For
- a QList<QString>, that item is of type QString.
-
- Here's how to iterate backward in a QList:
-
- \snippet code/doc_src_containers.cpp 2
-
- The code is symmetric with iterating forward, except that we
- start by calling \l{QListIterator::toBack()}{toBack()}
- to move the iterator after the last item in the list.
-
- The diagram below illustrates the effect of calling
- \l{QListIterator::next()}{next()} and
- \l{QListIterator::previous()}{previous()} on an iterator:
-
- \image javaiterators2.png
-
- The following table summarizes the QListIterator API:
-
- \table
- \header \li Function \li Behavior
- \row \li \l{QListIterator::toFront()}{toFront()}
- \li Moves the iterator to the front of the list (before the first item)
- \row \li \l{QListIterator::toBack()}{toBack()}
- \li Moves the iterator to the back of the list (after the last item)
- \row \li \l{QListIterator::hasNext()}{hasNext()}
- \li Returns \c true if the iterator isn't at the back of the list
- \row \li \l{QListIterator::next()}{next()}
- \li Returns the next item and advances the iterator by one position
- \row \li \l{QListIterator::peekNext()}{peekNext()}
- \li Returns the next item without moving the iterator
- \row \li \l{QListIterator::hasPrevious()}{hasPrevious()}
- \li Returns \c true if the iterator isn't at the front of the list
- \row \li \l{QListIterator::previous()}{previous()}
- \li Returns the previous item and moves the iterator back by one position
- \row \li \l{QListIterator::peekPrevious()}{peekPrevious()}
- \li Returns the previous item without moving the iterator
- \endtable
+ \snippet code/doc_src_containers.cpp range_for
- QListIterator provides no functions to insert or remove items
- from the list as we iterate. To accomplish this, you must use
- QMutableListIterator. Here's an example where we remove all
- odd numbers from a QList<int> using QMutableListIterator:
+ Note that when using a Qt container in a non-const context,
+ \l{implicit sharing} may perform an undesired detach of the container.
+ To prevent this, use \c std::as_const():
- \snippet code/doc_src_containers.cpp 3
+ \snippet code/doc_src_containers.cpp range_for_as_const
- The next() call in the loop is made every time. It jumps over the
- next item in the list. The
- \l{QMutableListIterator::remove()}{remove()} function removes the
- last item that we jumped over from the list. The call to
- \l{QMutableListIterator::remove()}{remove()} does not invalidate
- the iterator, so it is safe to continue using it. This works just
- as well when iterating backward:
+ For associative containers, this will loop over the values.
- \snippet code/doc_src_containers.cpp 4
+ \section2 Index-based
- If we just want to modify the value of an existing item, we can
- use \l{QMutableListIterator::setValue()}{setValue()}. In the code
- below, we replace any value larger than 128 with 128:
+ For sequential containers that store their items contiguously in memory
+ (for example, QList), index-based iteration can be used:
- \snippet code/doc_src_containers.cpp 5
+ \snippet code/doc_src_containers.cpp index
- Just like \l{QMutableListIterator::remove()}{remove()},
- \l{QMutableListIterator::setValue()}{setValue()} operates on the
- last item that we jumped over. If we iterate forward, this is the
- item just before the iterator; if we iterate backward, this is
- the item just after the iterator.
+ \section2 The Iterator Classes
- The \l{QMutableListIterator::next()}{next()} function returns a
- non-const reference to the item in the list. For simple
- operations, we don't even need
- \l{QMutableListIterator::setValue()}{setValue()}:
-
- \snippet code/doc_src_containers.cpp 6
-
- As mentioned above QSet's iterator
- classes have exactly the same API as QList's. We will now turn to
- QMapIterator, which is somewhat different because it iterates on
- (key, value) pairs.
-
- Like QListIterator, QMapIterator provides
- \l{QMapIterator::toFront()}{toFront()},
- \l{QMapIterator::toBack()}{toBack()},
- \l{QMapIterator::hasNext()}{hasNext()},
- \l{QMapIterator::next()}{next()},
- \l{QMapIterator::peekNext()}{peekNext()},
- \l{QMapIterator::hasPrevious()}{hasPrevious()},
- \l{QMapIterator::previous()}{previous()}, and
- \l{QMapIterator::peekPrevious()}{peekPrevious()}. The key and
- value components are extracted by calling \l{QMapIterator::key()}{key()} and \l{QMapIterator::value()}{value()} on
- the object returned by next(), peekNext(), previous(), or
- peekPrevious().
-
- The following example removes all (capital, country) pairs where
- the capital's name ends with "City":
-
- \snippet code/doc_src_containers.cpp 7
-
- QMapIterator also provides a \l{QMapIterator::key()}{key()} and a \l{QMapIterator::value()}{value()} function that
- operate directly on the iterator and that return the key and
- value of the last item that the iterator jumped above. For
- example, the following code copies the contents of a QMap into a
- QHash:
-
- \snippet code/doc_src_containers.cpp 8
-
- If we want to iterate through all the items with the same
- value, we can use \l{QMapIterator::findNext()}{findNext()}
- or \l{QMapIterator::findPrevious()}{findPrevious()}.
- Here's an example where we remove all the items with a particular
- value:
-
- \snippet code/doc_src_containers.cpp 9
+ Iterators provide a uniform means to access items in a container.
+ Qt's container classes provide two types of iterators: STL-style
+ iterators and Java-style iterators. Iterators of both types are
+ invalidated when the data in the container is modified or detached
+ from \l{Implicit Sharing}{implicitly shared copies} due to a call
+ to a non-const member function.
- \section2 STL-Style Iterators
+ \section3 STL-Style Iterators
STL-style iterators have been available since the release of Qt
2.0. They are compatible with Qt's and STL's \l{generic
@@ -438,10 +267,9 @@
\snippet code/doc_src_containers.cpp 10
- Unlike \l{Java-style iterators}, STL-style iterators point
- directly at items. The \l{QList::begin()}{begin()} function of a container returns an
- iterator that points to the first item in the container. The
- \l{QList::end()}{end()} function of a container returns an iterator to the
+ STL-style iterators point directly at items. The \l{QList::begin()}{begin()}
+ function of a container returns an iterator that points to the first item in the
+ container. The \l{QList::end()}{end()} function of a container returns an iterator to the
imaginary item one position past the last item in the container.
\l {QList::end()}{end()} marks an invalid position; it must never be dereferenced.
It is typically used in a loop's break condition. If the list is
@@ -458,12 +286,10 @@
In the code snippets so far, we used the unary \c * operator to
retrieve the item (of type QString) stored at a certain iterator
- position, and we then called QString::toLower() on it. Most C++
- compilers also allow us to write \c{i->toLower()}, but some
- don't.
+ position, and we then called QString::toLower() on it.
- For read-only access, you can use const_iterator, \l{QList::constBegin}{constBegin()},
- and \l{QList::constEnd()}{constEnd()}. For example:
+ For read-only access, you can use const_iterator, \l{QList::cbegin}{cbegin()},
+ and \l{QList::cend()}{cend()}. For example:
\snippet code/doc_src_containers.cpp 12
@@ -511,7 +337,7 @@
This problem doesn't occur with functions that return a const or
non-const reference to a container.
- \section3 Implicit sharing iterator problem
+ \section4 Implicit sharing iterator problem
\l{Implicit sharing} has another consequence on STL-style
iterators: you should avoid copying a container while
@@ -524,83 +350,68 @@
The above example only shows a problem with QList, but
the problem exists for all the implicitly shared Qt containers.
- \target foreach
- \section1 The foreach Keyword
-
- If you just want to iterate over all the items in a container
- in order, you can use Qt's \c foreach keyword. The keyword is a
- Qt-specific addition to the C++ language, and is implemented
- using the preprocessor.
-
- Its syntax is: \c foreach (\e variable, \e container) \e
- statement. For example, here's how to use \c foreach to iterate
- over a QList<QString>:
+ \section3 Java-Style Iterators
+ \l{java-style-iterators}{Java-Style iterators}
+ are modelled
+ on Java's iterator classes.
+ New code should prefer \l{STL-Style Iterators}.
- \snippet code/doc_src_containers.cpp 15
+ \section1 Qt containers compared with std containers
- The \c foreach code is significantly shorter than the equivalent
- code that uses iterators:
+ \table
+ \header \li Qt container \li Closest std container
- \snippet code/doc_src_containers.cpp 16
+ \row \li \l{QList}<T>
+ \li Similar to std::vector<T>
- Unless the data type contains a comma (e.g., \c{QPair<int,
- int>}), the variable used for iteration can be defined within the
- \c foreach statement:
+ \l{QList} and \l{QVector} were unified in Qt 6. Both
+ use the datamodel from QVector. QVector is now an alias to QList.
- \snippet code/doc_src_containers.cpp 17
+ This means that QList is not implemented as a linked list, so if
+ you need constant time insert, delete, append or prepend,
+ consider \c std::list<T>. See \l{QList} for details.
- And like any other C++ loop construct, you can use braces around
- the body of a \c foreach loop, and you can use \c break to leave
- the loop:
+ \row \li \l{QVarLengthArray}<T, Prealloc>
+ \li Resembles a mix of std::array<T> and std::vector<T>.
- \snippet code/doc_src_containers.cpp 18
+ For performance reasons, QVarLengthArray lives on the stack unless
+ resized. Resizing it automatically causes it to use the heap instead.
- With QMap and QHash, \c foreach accesses the value component of
- the (key, value) pairs automatically, so you should not call
- values() on the container (it would generate an unnecessary copy,
- see below). If you want to iterate over both the keys and the
- values, you can use iterators (which are faster), or you can
- obtain the keys, and use them to get the values too:
+ \row \li \l{QStack}<T>
+ \li Similar to std::stack<T>, inherits from \l{QList}.
- \snippet code/doc_src_containers.cpp 19
+ \row \li \l{QQueue}<T>
+ \li Similar to std::queue<T>, inherits from \l{QList}.
- For a multi-valued map:
+ \row \li \l{QSet}<T>
+ \li Similar to std::unordered_set<T>. Internally, \l{QSet} is implemented with a
+ \l{QHash}.
- \snippet code/doc_src_containers.cpp 20
+ \row \li \l{QMap}<Key, T>
+ \li Similar to std::map<Key, T>.
- Qt automatically takes a copy of the container when it enters a
- \c foreach loop. If you modify the container as you are
- iterating, that won't affect the loop. (If you do not modify the
- container, the copy still takes place, but thanks to \l{implicit
- sharing} copying a container is very fast.)
+ \row \li \l{QMultiMap}<Key, T>
+ \li Similar to std::multimap<Key, T>.
- Since foreach creates a copy of the container, using a non-const
- reference for the variable does not allow you to modify the original
- container. It only affects the copy, which is probably not what you
- want.
+ \row \li \l{QHash}<Key, T>
+ \li Most similar to std::unordered_map<Key, T>.
- An alternative to Qt's \c foreach loop is the range-based \c for that is
- part of C++ 11 and newer. However, keep in mind that the range-based
- \c for might force a Qt container to \l{Implicit Sharing}{detach}, whereas
- \c foreach would not. But using \c foreach always copies the container,
- which is usually not cheap for STL containers. If in doubt, prefer
- \c foreach for Qt containers, and range based \c for for STL ones.
+ \row \li \l{QMultiHash}<Key, T>
+ \li Most similar to std::unordered_multimap<Key, T>.
- In addition to \c foreach, Qt also provides a \c forever
- pseudo-keyword for infinite loops:
+ \endtable
- \snippet code/doc_src_containers.cpp 21
+ \section1 Qt containers and std algorithms
- If you're worried about namespace pollution, you can disable
- these macros by adding the following line to your \c .pro file:
+ You can use Qt containers with functions from \c{#include <algorithm>}.
- \snippet code/doc_src_containers.cpp 22
+ \snippet code/doc_src_containers.cpp 26
\section1 Other Container-Like Classes
Qt includes other template classes that resemble containers in
some respects. These classes don't provide iterators and cannot
- be used with the \c foreach keyword.
+ be used with the \l foreach keyword.
\list
\li QCache<Key, T> provides a cache to store objects of a certain
@@ -691,6 +502,29 @@
with the expected number of items before you insert the items.
The next section discusses this topic in more depth.
+ \section1 Optimizations for Primitive and Relocatable Types
+
+ Qt containers can use optimized code paths if the stored
+ elements are relocatable or even primitive.
+ However, whether types are primitive or relocatable
+ cannot be detected in all cases.
+ You can declare your types to be primitive or relocatable
+ by using the Q_DECLARE_TYPEINFO macro with the Q_PRIMITIVE_TYPE
+ flag or the Q_RELOCATABLE_TYPE flag. See the documentation
+ of Q_DECLARE_TYPEINFO for further details and usage examples.
+
+ If you do not use Q_DECLARE_TYPEINFO,
+ Qt will use
+ \l {https://en.cppreference.com/w/cpp/types/is_trivial} {std::is_trivial_v<T>}
+ to identify primitive
+ types and it will require both
+ \l {https://en.cppreference.com/w/cpp/types/is_trivially_copyable} {std::is_trivially_copyable_v<T>}
+ and
+ \l {https://en.cppreference.com/w/cpp/types/is_destructible} {std::is_trivially_destructible_v<T>}
+ to identify relocatable types.
+ This is always a safe choice, albeit
+ of maybe suboptimal performance.
+
\section1 Growth Strategies
QList<T>, QString, and QByteArray store their items
@@ -707,39 +541,23 @@
We build the string \c out dynamically by appending one character
to it at a time. Let's assume that we append 15000 characters to
- the QString string. Then the following 18 reallocations (out of a
- possible 15000) occur when QString runs out of space: 4, 8, 12,
- 16, 20, 52, 116, 244, 500, 1012, 2036, 4084, 6132, 8180, 10228,
- 12276, 14324, 16372. At the end, the QString has 16372 Unicode
+ the QString string. Then the following 11 reallocations (out of a
+ possible 15000) occur when QString runs out of space: 8, 24, 56,
+ 120, 248, 504, 1016, 2040, 4088, 8184, 16376.
+ At the end, the QString has 16376 Unicode
characters allocated, 15000 of which are occupied.
- The values above may seem a bit strange, but here are the guiding
- principles:
- \list
- \li QString allocates 4 characters at a time until it reaches size 20.
- \li From 20 to 4084, it advances by doubling the size each time.
- More precisely, it advances to the next power of two, minus
- 12. (Some memory allocators perform worst when requested exact
- powers of two, because they use a few bytes per block for
- book-keeping.)
- \li From 4084 on, it advances by blocks of 2048 characters (4096
- bytes). This makes sense because modern operating systems
- don't copy the entire data when reallocating a buffer; the
- physical memory pages are simply reordered, and only the data
- on the first and last pages actually needs to be copied.
- \endlist
+ The values above may seem a bit strange, but there is a guiding
+ principle. It advances by doubling the size each time.
+ More precisely, it advances to the next power of two, minus
+ 16 bytes. 16 bytes corresponds to eight characters, as QString
+ uses UTF-16 internally.
+
+ QByteArray uses the same algorithm as
+ QString, but 16 bytes correspond to 16 characters.
- QByteArray uses more or less the same algorithm as
- QString.
-
- QList<T> also uses that algorithm for data types that can be
- moved around in memory using \c memcpy() (including the basic C++
- types, the pointer types, and Qt's \l{shared classes}) but uses a
- different algorithm for data types that can only be moved by
- calling the copy constructor and a destructor. Since the cost of
- reallocating is higher in that case, QList<T> reduces the
- number of reallocations by always doubling the memory when
- running out of space.
+ QList<T> also uses that algorithm, but 16 bytes correspond to
+ 16/sizeof(T) elements.
QHash<Key, T> is a totally different case. QHash's internal hash
table grows by powers of two, and each time it grows, the items
diff --git a/src/corelib/doc/src/custom-types.qdoc b/src/corelib/doc/src/custom-types.qdoc
index d881a32e62..7922fd9477 100644
--- a/src/corelib/doc/src/custom-types.qdoc
+++ b/src/corelib/doc/src/custom-types.qdoc
@@ -1,36 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page custom-types.html
\title Creating Custom Qt Types
\brief How to create and register new types with Qt.
- \ingroup best-practices
+ \ingroup how-to
\tableofcontents
@@ -61,7 +37,7 @@
The following \c Message class definition includes these members:
- \snippet tools/customtype/message.h custom type definition
+ \snippet customtype/customtypeexample.cpp custom type definition
The class also provides a constructor for normal use and two public member functions
that are used to obtain the private data.
@@ -77,11 +53,14 @@
to this class, we invoke the Q_DECLARE_METATYPE() macro on the class in the header
file where it is defined:
- \snippet tools/customtype/message.h custom type meta-type declaration
+ \snippet customtype/customtypeexample.cpp custom type meta-type declaration
This now makes it possible for \c Message values to be stored in QVariant objects
- and retrieved later. See the \l{Custom Type Example} for code that demonstrates
- this.
+ and retrieved later:
+
+ \snippet customtype/customtypeexample.cpp storing a custom value
+ \dots
+ \snippet customtype/customtypeexample.cpp retrieving a custom value
The Q_DECLARE_METATYPE() macro also makes it possible for these values to be used as
arguments to signals, but \e{only in direct signal-slot connections}.
@@ -101,7 +80,7 @@
available for queued signal-slot communication as long as you call it before you
make the first connection that uses the type.
- The \l{Queued Custom Type Example} declares a \c Block class which is registered
+ The \l{Queued Custom Type} example declares a \c Block class which is registered
in the \c{main.cpp} file:
\snippet threads/queuedcustomtype/main.cpp main start
@@ -131,18 +110,17 @@
It is often quite useful to make a custom type printable for debugging purposes,
as in the following code:
- \snippet tools/customtype/main.cpp printing a custom type
+ \snippet customtype/customtypeexample.cpp printing a custom type
This is achieved by creating a streaming operator for the type, which is often
defined in the header file for that type:
- \snippet tools/customtype/message.h custom type streaming operator
+ \snippet customtype/customtypeexample.cpp custom type streaming operator declaration
- The implementation for the \c Message type in the \l{Custom Type Example}
- goes to some effort to make the printable representation as readable as
- possible:
+ The implementation for the \c Message type here goes to some effort to make the
+ printable representation as readable as possible:
- \snippet tools/customtype/message.cpp custom type streaming operator
+ \snippet customtype/customtypeexample.cpp custom type streaming operator
The output sent to the debug stream can, of course, be made as simple or as
complicated as you like. Note that the value returned by this function is
@@ -155,9 +133,8 @@
The Q_DECLARE_METATYPE() macro and qRegisterMetaType() function documentation
contain more detailed information about their uses and limitations.
- The \l{Custom Type Example}{Custom Type} and \l{Queued Custom Type Example}
- {Queued Custom Type} examples show how to implement a custom type with the
- features outlined in this document.
+ The \l{Queued Custom Type} example shows how to implement a custom type with
+ the features outlined in this document.
The \l{Debugging Techniques} document provides an overview of the debugging
mechanisms discussed above.
diff --git a/src/corelib/doc/src/datastreamformat.qdoc b/src/corelib/doc/src/datastreamformat.qdoc
index 303d374678..65b7eb5a20 100644
--- a/src/corelib/doc/src/datastreamformat.qdoc
+++ b/src/corelib/doc/src/datastreamformat.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page datastreamformat.html
@@ -31,7 +7,7 @@
\brief List of data types that can be serialized by QDataStream.
The \l QDataStream class allows you to serialize the Qt data types
- listed in this section as of \l{QDataStream::setVersion()}{version 18}.
+ listed in this section.
It is always best to cast integers to a Qt integer type, such as
\l{qint16} or \l{quint32}, when reading and writing. This ensures that
@@ -55,7 +31,11 @@
\li QBitArray
\li QBrush
\li QByteArray
+ \li QCborArray
+ \li QCborMap
+ \li QCborValue
\li QColor
+ \li QColorSpace
\li QCursor
\li QDate
\li QDateTime
@@ -63,33 +43,73 @@
\li QFont
\li QGenericMatrix
\li QHash<Key, T>
+ \li QHostAddress
\li QIcon
\li QImage
+ \li QJsonArray
+ \li QJsonDocument
+ \li QJsonObject
+ \li QJsonValue
\li QKeySequence
+ \li QLine
+ \li QLineF
\li QList<T>
+ \li QListWidgetItem
+ \li QLocale
\li QMap<Key, T>
\li QMargins
+ \li QMarginsF
\li QMatrix4x4
- \li QPair<T1, T2>
+ \li QModelIndex
+ \li QModelIndexList
+ \li QMultiHash<Key
+ \li QMultiMap<Key
+ \li QNetworkCacheMetaData
+ \li QNetworkCacheMetaData::AttributesMap
+ \li QPageRanges
+ \li QPainterPath
+ \li std::pair<T1, T2>
\li QPalette
\li QPen
\li QPicture
\li QPixmap
\li QPoint
+ \li QPointF
+ \li QPolygon
+ \li QPolygonF
\li QQuaternion
\li QRect
+ \li QRectF
\li QRegularExpression
\li QRegion
+ \li QSet
\li QSize
+ \li QSizeF
+ \li QSizePolicy
+ \li QStandardItem
\li QString
+ \li QTableWidgetItem
+ \li QTextBlockFormat
+ \li QTextCharFormat
+ \li QTextFormat
+ \li QTextFrameFormat
+ \li QTextLength
+ \li QTextListFormat
+ \li QTextTableCellFormat
+ \li QTimeZone
\li QTime
\li QTransform
+ \li QTreeWidgetItem
+ \li QTypeRevision
\li QUrl
+ \li QUuid
\li QVariant
\li QVector2D
\li QVector3D
\li QVector4D
+ \li QVersionNumber
\endlist
- \sa {JSON Support in Qt}
+ \sa {JSON Support in Qt}, {CBOR Support in Qt}
+
*/
diff --git a/src/corelib/doc/src/dontdocument.qdoc b/src/corelib/doc/src/dontdocument.qdoc
index 9ed5345777..456e6dfab2 100644
--- a/src/corelib/doc/src/dontdocument.qdoc
+++ b/src/corelib/doc/src/dontdocument.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\dontdocument (QMacAutoReleasePool QIncompatibleFlag QGenericAtomicOps QAtomicTraits
diff --git a/src/corelib/doc/src/eventsandfilters.qdoc b/src/corelib/doc/src/eventsandfilters.qdoc
index 947a24f4e5..38a4d2a39a 100644
--- a/src/corelib/doc/src/eventsandfilters.qdoc
+++ b/src/corelib/doc/src/eventsandfilters.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group events
diff --git a/src/corelib/doc/src/external-resources.qdoc b/src/corelib/doc/src/external-resources.qdoc
index f16a21d521..b787651aba 100644
--- a/src/corelib/doc/src/external-resources.qdoc
+++ b/src/corelib/doc/src/external-resources.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -47,21 +23,151 @@
*/
/*!
- \externalpage http://www.ietf.org/rfc/rfc4648.txt
- \title RFC 4648
-*/
-
-/*!
\externalpage http://www.iana.org/assignments/character-sets/character-sets.xml
\title IANA character-sets encoding file
*/
/*!
- \externalpage http://marcmutz.wordpress.com/effective-qt/containers/#containers-qlist
+ \externalpage https://marcmutz.wordpress.com/effective-qt/containers/#containers-qlist
\title Pros and Cons of Using QList
*/
/*!
- \externalpage http://marcmutz.wordpress.com/effective-qt/containers/
+ \externalpage https://marcmutz.wordpress.com/effective-qt/containers/
\title Understand the Qt Containers
*/
+
+/*!
+ \externalpage https://developer.android.com/training/articles/perf-jni#javavm-and-jnienv
+ \title JNI tips: JavaVM and JNIEnv
+*/
+
+/*!
+ \externalpage https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
+ \title Java Native Interface Specification
+*/
+
+/*!
+ \externalpage https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
+ \title Java: JNI Functions
+*/
+
+/*!
+ \externalpage https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references
+ \title JNI Design Overview: Global and Local References
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/articles/perf-jni#local-and-global-references
+ \title JNI tips: Local and global references
+*/
+
+/*!
+ \externalpage https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html#attach_current_thread
+ \title Java: AttachCurrentThread
+*/
+
+/*!
+ \externalpage https://docs.oracle.com/en/java/javase/13/docs/specs/jni/functions.html#interface-function-table
+ \title Java: Interface Function Table
+*/
+
+/*!
+ \externalpage https://doc.qt.io/qtcreator/creator-deploying-android.html#editing-manifest-files
+ \title Qt Creator: Editing Manifest Files
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/articles/perf-anr
+ \title Android: Keeping your app responsive
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/data-storage/shared/documents-files
+ \title Android: Access documents and other files from shared storage
+*/
+
+/*!
+ \externalpage https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile#getParentFile()
+ \title Android: DocumentFile.getParentFile()
+*/
+
+/*!
+ \externalpage https://developer.android.com/guide/topics/providers/content-provider-basics#ContentURIs
+ \title Android: Content URIs
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/data-storage#scoped-storage
+ \title Android: Scoped storage
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/data-storage/use-cases
+ \title Android: storage best practices
+*/
+
+/*!
+ \externalpage https://developer.android.com/reference/android/provider/MediaStore
+ \title Android: MediaStore
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
+ \title GNUInstallDirs
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
+ \title CMAKE_INSTALL_PREFIX
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#command-line-cmake-tool
+ \title Command Line cmake invocation
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/envvar/DESTDIR.html
+ \title DESTDIR
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/command/install.html#targets
+ \title install(TARGETS)
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/command/install.html#script
+ \title install(SCRIPT)
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/command/add_subdirectory.html
+ \title add_subdirectory()
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/module/FetchContent.html#command:fetchcontent_makeavailable
+ \title FetchContent_MakeAvailable()
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/prop_gbl/USE_FOLDERS.html
+ \title USE_FOLDERS
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/prop_tgt/FOLDER.html
+ \title FOLDER
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/command/cmake_policy.html
+ \title cmake_policy
+*/
+
+/*!
+ \externalpage https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html#creating-packages
+ \title Creating CMake packages
+*/
diff --git a/src/corelib/doc/src/filestorage.qdoc b/src/corelib/doc/src/filestorage.qdoc
index e291ba1375..6c93955320 100644
--- a/src/corelib/doc/src/filestorage.qdoc
+++ b/src/corelib/doc/src/filestorage.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page io-functions.html
diff --git a/src/corelib/doc/src/foreach-keyword.qdoc b/src/corelib/doc/src/foreach-keyword.qdoc
new file mode 100644
index 0000000000..6aa21d5880
--- /dev/null
+++ b/src/corelib/doc/src/foreach-keyword.qdoc
@@ -0,0 +1,90 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page foreach-keyword.html
+ \title Qt's foreach Keyword
+ \ingroup groups
+ \ingroup qt-basic-concepts
+
+ \brief Qt's foreach keyword.
+
+ \tableofcontents
+
+ \target foreach-keyword
+ \section1 The foreach Keyword
+
+ \note The foreach keyword was introduced before the C++11 range-based loops
+ existed. New code should prefer C++11 range-based loops.
+
+ The \c foreach keyword is a Qt-specific addition to the C++ language,
+ and is implemented using the preprocessor.
+
+ Its syntax is: \c foreach (\e variable, \e container) \e
+ statement. For example, here's how to use \c foreach to iterate
+ over a QList<QString>:
+
+ \snippet code/doc_src_containers.cpp 15
+
+ The \c foreach code is significantly shorter than the equivalent
+ code that uses iterators:
+
+ \snippet code/doc_src_containers.cpp 16
+
+ Unless the data type contains a comma (e.g., \c{std::pair<int,
+ int>}), the variable used for iteration can be defined within the
+ \c foreach statement:
+
+ \snippet code/doc_src_containers.cpp 17
+
+ And like any other C++ loop construct, you can use braces around
+ the body of a \c foreach loop, and you can use \c break to leave
+ the loop:
+
+ \snippet code/doc_src_containers.cpp 18
+
+ With QMap and QHash, \c foreach accesses the value component of
+ the (key, value) pairs automatically, so you should not call
+ values() on the container (it would generate an unnecessary copy,
+ see below). If you want to iterate over both the keys and the
+ values, you can use iterators (which are faster), or you can
+ obtain the keys, and use them to get the values too:
+
+ \snippet code/doc_src_containers.cpp 19
+
+ For a multi-valued map:
+
+ \snippet code/doc_src_containers.cpp 20
+
+ Qt automatically takes a copy of the container when it enters a
+ \c foreach loop. If you modify the container as you are
+ iterating, that won't affect the loop. (If you do not modify the
+ container, the copy still takes place, but thanks to \l{implicit
+ sharing} copying a container is very fast.)
+
+ Since foreach creates a copy of the container, using a non-const
+ reference for the variable does not allow you to modify the original
+ container. It only affects the copy, which is probably not what you
+ want.
+
+ An alternative to Qt's \c foreach loop is the range-based \c for that is
+ part of C++11 and newer. However, keep in mind that the range-based
+ \c for might force a Qt container to \l{Implicit Sharing}{detach}, whereas
+ \c foreach would not. But using \c foreach always copies the container,
+ which is usually not cheap for STL containers. If in doubt, prefer
+ \c foreach for Qt containers, and range based \c for for STL ones.
+
+ You can remove the availability of the Qt's \c foreach loop by
+ defining the \c{QT_NO_FOREACH} macro.
+*/
+
+/*!
+ \macro QT_NO_FOREACH
+ \since 6.0
+ \relates <QtGlobal>
+
+ Defining this macro removes the availability of Qt's \c foreach
+ loop.
+
+ \sa QT_NO_KEYWORDS
+*/
diff --git a/src/corelib/doc/src/implicit-sharing.qdoc b/src/corelib/doc/src/implicit-sharing.qdoc
index d789f8bf92..46daebe311 100644
--- a/src/corelib/doc/src/implicit-sharing.qdoc
+++ b/src/corelib/doc/src/implicit-sharing.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/* TODO: Move some of the documentation from QSharedDataPointer into this
document. */
diff --git a/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc b/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc
new file mode 100644
index 0000000000..0521aff662
--- /dev/null
+++ b/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc
@@ -0,0 +1,13 @@
+On Android, some limitations apply when dealing with
+\l {Android: Content URIs}{content URIs}:
+\list
+ \li Access permissions might be needed by prompting the user through the
+ \l QFileDialog which implements
+ \l {Android: Access documents and other files from shared storage}{Android's native file picker}.
+ \li Aim to follow the \l {Android: Scoped storage}{Scoped storage} guidelines,
+ such as using app specific directories instead of other public external directories.
+ For more information, also see
+ \l {Android: storage best practices}{storage best practices}.
+ \li Due to the design of Qt APIs (e.g. QFile), it's not possible to fully
+ integrate the latter APIs with Android's \l {Android: MediaStore}{MediaStore} APIs.
+\endlist
diff --git a/src/corelib/doc/src/includes/cmake-android-qt-finalize-project-warning.qdocinc b/src/corelib/doc/src/includes/cmake-android-qt-finalize-project-warning.qdocinc
new file mode 100644
index 0000000000..47133f6d10
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-android-qt-finalize-project-warning.qdocinc
@@ -0,0 +1,8 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+//! [warning]
+\warning If your \e Android project is built using a CMake version lower than
+3.19, make sure that you call \l{qt_finalize_project}{qt6_finalize_project()} at
+the end of a top-level CMakeLists.txt.
+//! [warning]
diff --git a/src/corelib/doc/src/includes/cmake-android-supported-abis.qdocinc b/src/corelib/doc/src/includes/cmake-android-supported-abis.qdocinc
new file mode 100644
index 0000000000..887866739c
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-android-supported-abis.qdocinc
@@ -0,0 +1 @@
+The supported ABIs are \c{armeabi-v7a, arm64-v8a, x86, x86_64}.
diff --git a/src/corelib/doc/src/includes/cmake-deploy-modified-variable-values.qdocinc b/src/corelib/doc/src/includes/cmake-deploy-modified-variable-values.qdocinc
new file mode 100644
index 0000000000..632ddf756f
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-deploy-modified-variable-values.qdocinc
@@ -0,0 +1,30 @@
+\badcode
+cmake_minimum_required(VERSION 3.16...3.22)
+project(MyThings)
+
+# The following CMAKE_INSTALL_*DIR variables are used to initialize their
+# QT_DEPLOY_*_DIR counterparts.
+set(CMAKE_INSTALL_BINDIR "mybindir")
+set(CMAKE_INSTALL_LIBDIR "mylibdir")
+set(CMAKE_INSTALL_LIBEXECDIR "mylibexecdir")
+
+find_package(Qt6 REQUIRED COMPONENTS Core)
+qt_standard_project_setup()
+
+qt_add_executable(MyApp main.cpp)
+
+set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_MyApp.cmake")
+file(GENERATE OUTPUT ${deploy_script} CONTENT "
+
+set(QT_DEPLOY_PLUGINS_DIR \"mypluginsdir\")
+set(QT_DEPLOY_QML_DIR \"myqmldir\")
+set(QT_DEPLOY_TRANSLATIONS_DIR \"i18n\")
+
+include(\"${QT_DEPLOY_SUPPORT}\")
+
+qt_deploy_runtime_dependencies(
+ EXECUTABLE \"\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:MyApp>\"
+)")
+
+install(SCRIPT ${deploy_script})
+\endcode
diff --git a/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies-deploy-tool-options.qdocinc b/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies-deploy-tool-options.qdocinc
new file mode 100644
index 0000000000..0f46379c45
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies-deploy-tool-options.qdocinc
@@ -0,0 +1,20 @@
+\badcode
+set(deploy_tool_options_arg "")
+if(APPLE)
+ set(deploy_tool_options_arg --hardened-runtime)
+elseif(WIN32)
+ set(deploy_tool_options_arg --no-compiler-runtime)
+endif()
+
+# Generate a deployment script to be executed at install time
+qt_generate_deploy_script(
+ TARGET MyApp
+ OUTPUT_SCRIPT deploy_script
+ CONTENT "
+qt_deploy_runtime_dependencies(
+ EXECUTABLE \"${executable_path}\"
+ DEPLOY_TOOL_OPTIONS "${deploy_tool_options_arg}"
+ GENERATE_QT_CONF
+ VERBOSE
+)")
+\endcode
diff --git a/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc b/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc
new file mode 100644
index 0000000000..6d026d6301
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc
@@ -0,0 +1,46 @@
+\badcode
+cmake_minimum_required(VERSION 3.16...3.22)
+project(MyThings)
+
+find_package(Qt6 REQUIRED COMPONENTS Core)
+qt_standard_project_setup()
+
+qt_add_executable(MyApp main.cpp)
+
+set_target_properties(MyApp PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+# App bundles on macOS have an .app suffix
+if(APPLE)
+ set(executable_path "$<TARGET_FILE_NAME:MyApp>.app")
+else()
+ set(executable_path "\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:MyApp>")
+endif()
+
+# Helper app, not necessarily built as part of this project.
+qt_add_executable(HelperApp helper.cpp)
+set(helper_app_path "\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:HelperApp>")
+
+# Generate a deployment script to be executed at install time
+qt_generate_deploy_script(
+ TARGET MyApp
+ OUTPUT_SCRIPT deploy_script
+ CONTENT "
+qt_deploy_runtime_dependencies(
+ EXECUTABLE \"${executable_path}\"
+ ADDITIONAL_EXECUTABLES \"${helper_app_path}\"
+ GENERATE_QT_CONF
+ VERBOSE
+)")
+
+# Omitting RUNTIME DESTINATION will install a non-bundle target to CMAKE_INSTALL_BINDIR,
+# which coincides with the default value of QT_DEPLOY_BIN_DIR used above, './bin'.
+# Installing macOS bundles always requires an explicit BUNDLE DESTINATION option.
+install(TARGETS MyApp HelperApp # Install to CMAKE_INSTALL_PREFIX/bin/MyApp.exe
+ # and ./binHelperApp.exe
+ BUNDLE DESTINATION . # Install to CMAKE_INSTALL_PREFIX/MyApp.app/Contents/MacOS/MyApp
+)
+install(SCRIPT ${deploy_script}) # Add its runtime dependencies
+\endcode
diff --git a/src/corelib/doc/src/includes/cmake-deploy-var-usage.qdocinc b/src/corelib/doc/src/includes/cmake-deploy-var-usage.qdocinc
new file mode 100644
index 0000000000..27e04b5b08
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-deploy-var-usage.qdocinc
@@ -0,0 +1,6 @@
+This variable is defined by the script named by \l QT_DEPLOY_SUPPORT. It should
+only be used as part of deployment during installation or a post-build rule.
+
+\note This is a low-level deployment API variable, and should only be used in
+advanced use-cases that are not covered by the higher-level API commands, like
+\l{qt_generate_deploy_app_script}.
diff --git a/src/corelib/doc/src/includes/cmake-find-package-core.qdocinc b/src/corelib/doc/src/includes/cmake-find-package-core.qdocinc
new file mode 100644
index 0000000000..66649eec5a
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-find-package-core.qdocinc
@@ -0,0 +1,6 @@
+The command is defined in the \c Core component of the \c Qt6 package, which
+can be loaded like so:
+
+\badcode
+find_package(Qt6 REQUIRED COMPONENTS Core)
+\endcode
diff --git a/src/corelib/doc/src/includes/cmake-generate-deploy-app-script-deploy-tool-options.qdocinc b/src/corelib/doc/src/includes/cmake-generate-deploy-app-script-deploy-tool-options.qdocinc
new file mode 100644
index 0000000000..64c6b3e49f
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-generate-deploy-app-script-deploy-tool-options.qdocinc
@@ -0,0 +1,16 @@
+\badcode
+set(deploy_tool_options_arg "")
+if(APPLE)
+ set(deploy_tool_options_arg --hardened-runtime)
+elseif(WIN32)
+ set(deploy_tool_options_arg --no-compiler-runtime)
+endif()
+
+qt_generate_deploy_app_script(
+ TARGET MyApp
+ OUTPUT_SCRIPT deploy_script
+ NO_UNSUPPORTED_PLATFORM_ERROR
+ DEPLOY_TOOL_OPTIONS ${deploy_tool_options_arg}
+)
+install(SCRIPT ${deploy_script})
+\endcode
diff --git a/src/corelib/doc/src/includes/cmake-generate-deploy-app-script.qdocinc b/src/corelib/doc/src/includes/cmake-generate-deploy-app-script.qdocinc
new file mode 100644
index 0000000000..d5c1d2cf4a
--- /dev/null
+++ b/src/corelib/doc/src/includes/cmake-generate-deploy-app-script.qdocinc
@@ -0,0 +1,21 @@
+\badcode
+cmake_minimum_required(VERSION 3.16...3.22)
+project(MyThings)
+
+find_package(Qt6 REQUIRED COMPONENTS Core)
+qt_standard_project_setup()
+
+qt_add_executable(MyApp main.cpp)
+
+install(TARGETS MyApp
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+qt_generate_deploy_app_script(
+ TARGET MyApp
+ OUTPUT_SCRIPT deploy_script
+ NO_UNSUPPORTED_PLATFORM_ERROR
+)
+install(SCRIPT ${deploy_script})
+\endcode
diff --git a/src/corelib/doc/src/includes/models.qdocinc b/src/corelib/doc/src/includes/models.qdocinc
new file mode 100644
index 0000000000..cf840b1cae
--- /dev/null
+++ b/src/corelib/doc/src/includes/models.qdocinc
@@ -0,0 +1,14 @@
+//! [thread-safety-section1]
+\section1 Thread safety
+
+Being a \l {Accessing QObject Subclasses from Other Threads}{subclass of
+QObject}, \1 is not \l {Reentrancy and Thread-Safety}{thread-safe}. Any \1
+model-related API should only be called from the thread the model object lives
+in. If the \1 is connected with a view, that means the GUI thread, as that is
+where the view lives, and it will call into the model from the GUI thread.
+Using a background thread to populate or modify the contents of a model is
+possible, but requires care, as the background thread cannot call any
+model-related API directly. Instead, you should queue the updates and apply
+them in the main thread. This can be done with \l {Signals and Slots Across
+Threads}{queued connections}.
+//! [thread-safety-section1]
diff --git a/src/corelib/doc/src/includes/permissions.qdocinc b/src/corelib/doc/src/includes/permissions.qdocinc
new file mode 100644
index 0000000000..00bf848d37
--- /dev/null
+++ b/src/corelib/doc/src/includes/permissions.qdocinc
@@ -0,0 +1,51 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+//! [requestPermission-functor]
+ When the request is ready, \a functor will be called as
+ \c {functor(const QPermission &permission)}, with
+ \c permission describing the result of the request.
+//! [requestPermission-functor]
+
+//! [requestPermission-postamble]
+ If the user explicitly grants the application the requested \a permission,
+ or the \a permission is known to not require user authorization on the given
+ platform, the status will be Qt::PermissionStatus::Granted.
+
+ If the user explicitly denies the application the requested \a permission,
+ or the \a permission is known to not be accessible or applicable to applications
+ on the given platform, the status will be Qt::PermissionStatus::Denied.
+
+ The result of a request will never be Qt::PermissionStatus::Undetermined.
+
+ \note Permissions can only be requested from the main thread.
+//! [requestPermission-postamble]
+
+//! [permission-metadata]
+ \inmodule QtCore
+ \inheaderfile QPermissions
+ \ingroup permissions
+ \since 6.5
+ \sa QPermission,
+ QCoreApplication::requestPermission(),
+ QCoreApplication::checkPermission(),
+ {Application Permissions}
+//! [permission-metadata]
+
+//! [begin-usage-declarations]
+ To request this permission at runtime, the following platform
+ specific usage declarations have to be made at build time:
+
+ \table
+ \header
+ \li Platform
+ \li Type
+ \li
+//! [begin-usage-declarations]
+
+//! [end-usage-declarations]
+ \endtable
+
+ Please see the individual usage declaration types for how
+ to add them to your project.
+//! [end-usage-declarations]
diff --git a/src/corelib/doc/src/includes/qfile-copy.qdocinc b/src/corelib/doc/src/includes/qfile-copy.qdocinc
new file mode 100644
index 0000000000..5ff68eac81
--- /dev/null
+++ b/src/corelib/doc/src/includes/qfile-copy.qdocinc
@@ -0,0 +1,11 @@
+This file is closed before it is copied.
+
+If the copied file is a symbolic link (symlink), the
+file it refers to is copied, not the link itself. With the
+exception of permissions, which are copied, no other file metadata
+is copied.
+
+Returns \c true if successful; otherwise returns \c false.
+
+Note that if a file with the name \a newName already exists,
+copy() returns \c false. This means QFile will not overwrite it.
diff --git a/src/corelib/doc/src/includes/qobject.qdocinc b/src/corelib/doc/src/includes/qobject.qdocinc
new file mode 100644
index 0000000000..65630c82ee
--- /dev/null
+++ b/src/corelib/doc/src/includes/qobject.qdocinc
@@ -0,0 +1,10 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+//! [disconnect-all]
+\note Disconnecting all signal-slot connections will also disconnect the
+\l QObject::destroyed() signal if it is connected. Doing so can adversely
+affect classes that rely on this signal for cleaning up resources. It is
+recommended to disconnect only the specific signals that were connected by
+application code.
+//! [disconnect-all]
diff --git a/src/corelib/doc/src/includes/qstring.qdocinc b/src/corelib/doc/src/includes/qstring.qdocinc
new file mode 100644
index 0000000000..66ed12dff3
--- /dev/null
+++ b/src/corelib/doc/src/includes/qstring.qdocinc
@@ -0,0 +1,36 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+// \1 is either "search" or "comparison"
+//! [search-comparison-case-sensitivity]
+If \a cs is Qt::CaseSensitive (the default), the \1 is case-sensitive;
+otherwise the \1 is case-insensitive.
+//! [search-comparison-case-sensitivity]
+
+//! [negative-index-start-search-from-end]
+If \a from is -1, the search starts at the last character; if it is
+-2, at the next to last character and so on.
+//! [negative-index-start-search-from-end]
+
+//! [qstring-first-index-of]
+Returns the index position of the first occurrence of the \1 \a \2
+in this string, searching forward from index position \a from.
+Returns -1 if \a \2 is not found.
+//! [qstring-first-index-of]
+
+//! [qstring-last-index-of]
+Returns the index position of the last occurrence of the \1 \a \2
+in this string, searching backward from index position \a from.
+//! [qstring-last-index-of]
+
+//! [qstring-local-8-bit-equivalent]
+On Unix systems this is equivalent to \1().
+Note that on Apple systems this function does not take
+\l{https://developer.apple.com/documentation/foundation/nsstring/1410091-defaultcstringencoding?language=objc}
+{NSString.defaultCStringEncoding} or
+\l{https://developer.apple.com/documentation/corefoundation/1541720-cfstringgetsystemencoding?language=objc}
+{CFStringGetSystemEncoding()} into account, as these functions
+typically return the legacy "Western (Mac OS Roman)" encoding,
+which should not be used on modern Apple operating systems.
+On Windows the system's current code page is used.
+//! [qstring-local-8-bit-equivalent]
diff --git a/src/corelib/doc/src/includes/qt_add_big_resources.qdocinc b/src/corelib/doc/src/includes/qt_add_big_resources.qdocinc
deleted file mode 100644
index 0a76bdd844..0000000000
--- a/src/corelib/doc/src/includes/qt_add_big_resources.qdocinc
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [description]
-Creates compiled object files from Qt resource files using the
-\l{Resource Compiler (rcc)}. Paths to the generated files are added to
-\c{<VAR>}.
-
-This is similar to \l qt5_add_resources / \l qt_add_resources, but directly
-generates object files (\c .o, \c .obj) files instead of C++ source code.
-This allows to embed bigger resources, where compiling to C++ sources and then
-to binaries would be too time consuming or memory intensive.
-
-\note This macro is only available if using \c{CMake} 3.9 or later.
-//! [description]
-
-//! [arguments]
-You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.
-You can find possible options in the \l{rcc}{rcc documentation}.
-//! [arguments]
diff --git a/src/corelib/doc/src/includes/qt_add_binary_resources.qdocinc b/src/corelib/doc/src/includes/qt_add_binary_resources.qdocinc
deleted file mode 100644
index 21d3ca5990..0000000000
--- a/src/corelib/doc/src/includes/qt_add_binary_resources.qdocinc
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [description]
-Adds a custom \c target that compiles Qt resource files into a binary \c{.rcc}
-file.
-//! [description]
-
-//! [arguments]
-\c{DESTINATION} sets the path of the generated \c{.rcc} file. The default is
-\c{${CMAKE_CURRENT_BINARY_DIR}/${target}.rcc}.
-
-You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.
-You can find possible options in the \l{rcc}{rcc documentation}.
-//! [arguments]
diff --git a/src/corelib/doc/src/includes/qt_add_resources.qdocinc b/src/corelib/doc/src/includes/qt_add_resources.qdocinc
deleted file mode 100644
index b3c032a04b..0000000000
--- a/src/corelib/doc/src/includes/qt_add_resources.qdocinc
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [description]
-Creates source code from Qt resource files using the
-\l{Resource Compiler (rcc)}. Paths to the generated source files are added to
-\c{<VAR>}.
-
-\note This is a low-level macro. See the \l{CMake AUTORCC Documentation} for a
-more convenient way to let Qt resource files be processed with \c{rcc}.
-//! [description]
-
-//! [arguments]
-You can set additional \c{OPTIONS} that should be added to the \c{rcc} calls.
-You can find possible options in the \l{rcc}{rcc documentation}.
-//! [arguments]
diff --git a/src/corelib/doc/src/includes/qt_generate_moc.qdocinc b/src/corelib/doc/src/includes/qt_generate_moc.qdocinc
deleted file mode 100644
index c1c0ada978..0000000000
--- a/src/corelib/doc/src/includes/qt_generate_moc.qdocinc
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [description]
-Creates a rule to call the \l{moc}{Meta-Object Compiler (moc)} on \c src_file
-and store the output in \c dest_file.
-
-\note This is a low-level macro. See the \l{CMake AUTOMOC Documentation} for a
-more convenient way to let source files be processed with \c{moc}.
-\l qt5_wrap_cpp is also similar, but automatically generates a temporary file
-path for you.
-//! [description]
-
-//! [arguments]
-You can set an explicit \c{TARGET}. This will make sure that the target
-properties \c{INCLUDE_DIRECTORIES} and \c{COMPILE_DEFINITIONS} are also used
-when scanning the source files with \c{moc}.
-//! [arguments]
diff --git a/src/corelib/doc/src/includes/qt_import_plugins.qdocinc b/src/corelib/doc/src/includes/qt_import_plugins.qdocinc
deleted file mode 100644
index 005a73d1d7..0000000000
--- a/src/corelib/doc/src/includes/qt_import_plugins.qdocinc
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [description]
-Specifies a custom set of plugins to import. The optional arguments:
-\c INCLUDE, \c EXCLUDE, \c INCLUDE_BY_TYPE, and \c EXCLUDE_BY_TYPE,
-can be used more than once.
-
-This CMake command was introduced in Qt 5.14.
-
-\list
-\li \c INCLUDE -- can be used to specify a list of plugins to import.
-\li \c EXCLUDE -- can be used to specify a list of plugins to exclude.
-\li \c INCLUDE_BY_TYPE -- can be used to override the list of plugins to
- import for a certain plugin type.
-\li \c EXCLUDE_BY_TYPE -- can be used to specify a plugin type to exclude;
- then no plugins of that type are imported.
-\endlist
-
-Qt provides plugin types such as \c imageformats, \c platforms,
-and \c sqldrivers.
-
-If the command isn't used the target automatically links against
-a sane set of default plugins, for each Qt module that the target is linked
-against. For more information, see
-\l{CMake target_link_libraries Documentation}{target_link_libraries}.
-
-Each plugin comes with a C++ stub file that automatically
-initializes the plugin. Consequently, any target that links against a plugin
-has this C++ file added to its \c SOURCES.
-
-\note This command imports plugins from static Qt builds only.
-On shared builds, it does nothing.
-//! [description]
diff --git a/src/corelib/doc/src/includes/qt_wrap_cpp.qdocinc b/src/corelib/doc/src/includes/qt_wrap_cpp.qdocinc
deleted file mode 100644
index 3f6b278557..0000000000
--- a/src/corelib/doc/src/includes/qt_wrap_cpp.qdocinc
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [description]
-Creates rules for calling the \l{moc}{Meta-Object Compiler (moc)} on the given
-source files. For each input file, an output file is generated in the build
-directory. The paths of the generated files are added to \c{<VAR>}.
-
-\note This is a low-level macro. See the \l{CMake AUTOMOC Documentation} for a
-more convenient way to let source files be processed with \c{moc}.
-//! [description]
-
-//! [arguments]
-You can set an explicit \c{TARGET}. This will make sure that the target
-properties \c{INCLUDE_DIRECTORIES} and \c{COMPILE_DEFINITIONS} are also used
-when scanning the source files with \c{moc}.
-
-You can set additional \c{OPTIONS} that should be added to the \c{moc} calls.
-You can find possible options in the \l{moc}{moc documentation}.
-
-\c{DEPENDS} allows you to add additional dependencies for recreation of the
-generated files. This is useful when the sources have implicit dependencies,
-like code for a Qt plugin that includes a \c{.json} file using the
-Q_PLUGIN_METADATA() macro.
-//! [arguments]
diff --git a/src/corelib/doc/src/io.qdoc b/src/corelib/doc/src/io.qdoc
index a1bbc623a1..443d324f75 100644
--- a/src/corelib/doc/src/io.qdoc
+++ b/src/corelib/doc/src/io.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group io
@@ -34,7 +10,7 @@
network handling.
These \l{Qt Core} classes are used to handle input and output to and from
- external devices, processes, files etc. as well as manipulating files and
+ external devices, processes, files etc., as well as manipulating files and
directories.
*/
diff --git a/src/corelib/doc/src/ipc.qdoc b/src/corelib/doc/src/ipc.qdoc
new file mode 100644
index 0000000000..7ec6f5fa3b
--- /dev/null
+++ b/src/corelib/doc/src/ipc.qdoc
@@ -0,0 +1,492 @@
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page ipc.html
+ \title Inter-Process Communication
+ \ingroup groups
+ \ingroup frameworks-technologies
+ \keyword ipc
+ \ingroup explanations-networkingandconnectivity
+
+ \brief An overview of Qt's inter-process communication functionality
+
+ Qt supports many ways of communicating with other processes running in the
+ same system or in different systems. There are basically three types of
+ inter-process communication mechanisms:
+
+ \list 1
+ \li Synchronization primitives
+ \li Exchanging of arbitrary byte-level data
+ \li Passing structured messages
+ \endlist
+
+ \section1 Synchronization primitives
+
+ Qt only provides one class for explicit inter-process synchronization:
+ \l{QSystemSemaphore}. A QSystemSemaphore is like a \l{QSemaphore} that is
+ accessible by multiple processes in the same system. It is globally
+ identified by a "key", which in Qt is represented by the \l{QNativeIpcKey}
+ class. Additionally, depending on the OS, Qt may support multiple different
+ backends for sharing memory; see the \l{Native IPC Keys} documentation for
+ more information and limitations.
+
+ It is possible to use regular thread-synchronization primitives such as
+ mutexes, wait conditions, and read-write locks, located in memory that is
+ shared between processes. Qt does not provide any class to support this,
+ but applications can use low-level operations on certain operating systems.
+
+ Other Qt classes may be used to provide higher-level locking, like
+ \l{QLockFile}, or by acquiring a unique, system-wide resource. Such
+ techniques include \l{QTcpServer}{TCP} or \l{QUdpSocket}{UDP} ports or
+ well-known names in \l{QDBusConnection::registerService}{D-Bus}.
+
+ \section1 Byte-level data sharing
+
+ Using byte-level data, applications can implement any communication
+ protocol they may choose. Sharing of byte data can be stream-oriented
+ (serialized) or can allow random access (a similar condition to
+ QFileDevice::isSequential()).
+
+ For serial communication, Qt provides a number of different classes and
+ even full modules:
+ \list
+ \li Pipes and FIFOs: \l QFile
+ \li Child processes: \l QProcess
+ \li Sockets: \l QTcpSocket, \l QUdpSocket (in \l{Qt Network})
+ \li HTTP(S): \l QNetworkAccessManager (in \l{Qt Network}) and
+ \l QHttpServer (in \l{Qt HTTP Server})
+ \li CoAP(S): \l QCoapClient (in \l{Qt CoAP})
+ \endlist
+
+ For random-access data sharing within the same system, Qt provides
+ \l{QSharedMemory}. See the \l{Shared Memory} documentation for detailed
+ information.
+
+ \section1 Structured message passing
+
+ Qt also provides a number of techniques to exchange structured messages
+ with other processes. Applications can build on top of the byte-level
+ solutions above, such as by using \l QJsonDocument or \l QXmlStreamReader /
+ \l QXmlStreamWriter over HTTP to perform JSONRPC or XMLRPC, respectively,
+ or \l QCborValue with QtCoAP.
+
+ Dedicated Qt modules for structured messages and remote procedure-calling
+ include:
+ \list
+ \li \l{Qt D-Bus}
+ \li \l{Qt Remote Objects}
+ \li \l{Qt WebSockets}
+ \endlist
+*/
+
+/*!
+ \page shared-memory.html
+ \title Shared Memory
+ \keyword ipc
+ \keyword shared memory
+
+ \brief Overview of the techniques for sharing memory between processes.
+
+ Qt provides two techniques to share memory with other processes in the same
+ system: \l{QSharedMemory} and memory-mapped files using \l{QFile}. Memory
+ that is shared with other processes is often referred to as a "segment",
+ and although it may have been implemented as specific segments on
+ processors with segmented memory models in the past, this is not the case
+ in any modern operating system. Shared memory segments are simply regions
+ of memory that the operating system will ensure are available to all
+ processes participating.
+
+ \note The address at which the segment is located in memory will almost
+ always be different for each process that is participating in the sharing.
+ Therefore, applications must take care to share only position-independent
+ data, such as primitive C++ types or arrays of such types.
+
+ \section1 Sharing memory using QSharedMemory
+
+ QSharedMemory provides a simple API to create a shared memory segment of a
+ given size or attach to one that was created by another process.
+ Additionally, it provides a pair of methods to \l{QSharedMemory::}{lock}
+ and \l{QSharedMemory::}{unlock} the whole segment, using an internal
+ \l{QSystemSemaphore}.
+
+ Shared memory segments and system semaphores are globally identified in the
+ system through a "key", which in Qt is represented by the \l{QNativeIpcKey}
+ class. Additionally, depending on the OS, Qt may support multiple different
+ backends for sharing memory; see the \l{Native IPC Keys} documentation for
+ more information and limitations.
+
+ QSharedMemory is designed to share memory only within the same privilege
+ level (that is, not with untrusted other processes, such as those started
+ by other users). For backends that support it, QSharedMemory will create
+ segments such that only processes with the same privilege level can attach.
+
+ \section1 Sharing memory via memory-mapped files
+
+ Most files can be mapped to memory using QFile::map() and, if the
+ \l{QFileDevice::MapPrivateOption}{MapPrivateOption} option is not specified,
+ any writes to the mapped segment will be observed by all other processes
+ that have mapped the same file. Exceptions to files that can be mapped to
+ memory include remote files found in network shares or those located in
+ certain filesystems. Even if the operating system does allow mapping remote
+ files to memory, I/O operations on the file will likely be cached and
+ delayed, thus making true memory sharing impossible.
+
+ This solution has the major advantages of being independent of any backend
+ API and of being simpler to interoperate with from non-Qt applications.
+ Since \l{QTemporaryFile} is a \l{QFile}, applications can use that class to
+ achieve clean-up semantics and to create unique shared memory segments too.
+
+ To achieve locking of the shared memory segment, applications will need to
+ deploy their own mechanisms. One way may be to use \l QLockFile. Another
+ and less costly solution is to use QBasicAtomicInteger or \c{std::atomic} in
+ a pre-determined offset in the segment itself. Higher-level locking
+ primitives may be available on some operating systems; for example, on
+ Linux, applications can set the "pshared" flag in the mutex attribute
+ passed to \c{pthread_mutex_create()} to indicate that the mutex resides in
+ a shared memory segment.
+
+ Be aware that the operating system will likely attempt to commit to
+ permanent storage any writes made to the shared memory. This may be desired
+ or it may be a performance penalty if the file itself was meant to be
+ temporary. In that case, applications should locate a RAM-backed
+ filesystem, such as \c{tmpfs} on Linux (see
+ QStorageInfo::fileSystemType()), or pass a flag to the native file-opening
+ function to inform the OS to avoid committing the contents to storage.
+
+ It is possible to use file-backed shared memory to communicate with
+ untrusted processes, in which case the application should exercise great
+ care. The files may be truncated/shrunk and cause applications accessing
+ memory beyond the file's size to crash.
+
+ \section2 Linux hints on memory-mapped files
+
+ On modern Linux systems, while the \c{/tmp} directory is often a \c{tmpfs}
+ mount point, that is not a requirement. However, the \c{/dev/shm} directory
+ is required to be a \c{tmpfs} and exists for the very purpose of sharing
+ memory. Do note that it is world-readable and writable (like \c{/tmp} and
+ \c{/var/tmp}), so applications must be careful of the contents revealed
+ there. Another alternative is to use the XDG Runtime Directory (see
+ QStandardPaths::writableLocation() and \l{QStandardPaths::RuntimeLocation}),
+ which on Linux systems using systemd is a user-specific \c{tmpfs}.
+
+ An even more secure solution is to create a "memfd" using \c{memfd_create(2)}
+ and use interprocess communication to pass the file descriptor, like
+ \l{QDBusUnixFileDescriptor} or by letting the child process of a \l{QProcess}
+ inherit it. "memfds" can also be sealed against being shrunk, so they are
+ safe to be used when communicating with processes with a different privilege
+ level.
+
+ \section2 FreeBSD hints on memory-mapped files
+
+ FreeBSD also has \c{memfd_create(2)} and can pass file descriptors to other
+ processes using the same techniques as Linux. It does not have temporary
+ filesystems mounted by default.
+
+ \section2 Windows hints on memory-mapped files
+
+ On Windows, the application can request the operating system avoid saving
+ the file's contents on permanent storage. This request is performed by
+ passing the \c{FILE_ATTRIBUTE_TEMPORARY} flag in the
+ \c{dwFlagsAndAttributes} parameter to the \c{CreateFile} Win32 function,
+ the \c{_O_SHORT_LIVED} flag to \c{_open()} low-level function, or by
+ including the modifier "T" to the
+ \c{fopen()} C runtime function.
+
+ There's also a flag to inform the operating system to delete the file when
+ the last handle to it is closed (\c{FILE_FLAG_DELETE_ON_CLOSE},
+ \c{_O_TEMPORARY}, and the "D" modifier), but do note that all processes
+ attempting to open the file must agree on using this flag or not using it. A
+ mismatch will likely cause a sharing violation and failure to open the file.
+*/
+
+/*!
+ \page native-ipc-keys.html
+ \title Native IPC Keys
+ \keyword ipc
+ \keyword shared memory
+ \keyword system semaphore
+
+ \brief An overview of keys for QSharedMemory and QSystemSemaphore
+
+ The \l QSharedMemory and \l QSystemSemaphore classes identify their
+ resource using a system-wide identifier known as a "key". The low-level key
+ value as well as the key type are encapsulated in Qt using the \l
+ QNativeIpcKey class. That class also provides the proper means of
+ exchanging the key with other processes, by way of
+ QNativeIpcKey::toString() and QNativeIpcKey::fromString().
+
+ Qt currently supports three distinct backends for those two classes, which
+ match the values available in the \l{QNativeIpcKey::Type} enumeration.
+ \list
+ \li POSIX Realtime extensions (IEEE 1003.1b, POSIX.1b)
+ \li X/Open System Interfaces (XSI) or System V (SVr4), though also now part of POSIX
+ \li Windows primitives
+ \endlist
+
+ As the name indicates, the Windows primitives are only available on the
+ Windows operating system, where they are the default backend. The other two
+ are usually both available on Unix operating systems. The following table
+ provides an overview of typical availability since Qt 6.6:
+
+ \table
+ \header \li Operating system \li POSIX \li System V \li Windows
+ \row \li Android \li \li \li
+ \row \li INTEGRITY \li \li \li
+ \row \li QNX \li Yes \li \li
+ \row \li \macos \li Yes \li Usually (1) \li
+ \row \li Other Apple OSes \li Yes \li \li
+ \row \li Other Unix systems \li Yes \li Yes \li
+ \row \li Windows \li Rarely (2) \li \li Yes
+ \endtable
+
+ \note 1 Sandboxed \macos applications, which include all applications
+ distributed via the Apple App Store, may not use System V objects.
+
+ \note 2 Some GCC-compatible C runtimes on Windows provide POSIX-compatible
+ shared memory support, but this is rare. It is always absent with the
+ Microsoft compiler.
+
+ To determine whether a given key type is supported, applications should
+ call QSharedMemory::isKeyTypeSupported() and
+ QSystemSemaphore::isKeyTypeSupported().
+
+ QNativeIpcKey also provides support for compatibility with Qt applications
+ prior to its introduction. The following sections detail the limitations of
+ the backends, the contents of the string keys themselves, and
+ compatibility.
+
+ \section1 Cross-platform safe key format
+
+ QNativeIpcKey::setNativeKey() and QNativeIpcKey::nativeKey() handle the
+ low-level native key, which may be used with the native APIs and shared
+ with other, non-Qt processes (see below for the API). This format is not
+ usually cross-platform, so both QSharedMemory and QSystemSemaphore provide
+ a function to translate a cross-platform identifier string to the native
+ key: QSharedMemory::platformSafeKey() and
+ QSystemSemaphore::platformSafeKey().
+
+ The length of the cross-platform key on most platforms is the same as that
+ of a file name, but is severely limited on Apple platforms to only 30
+ usable bytes (be mindful of UTF-8 encoding if using characters outside the
+ US-ASCII range). The format of the key is also similar to that of a file
+ path component, meaning it should not contain any characters not allowed in
+ file names, in particular those that separate path components (slash and
+ backslash), with the exception of sandboxed applications on Apple operating
+ systems. The following are good examples of cross-platform keys: "myapp",
+ "org.example.myapp", "org.example.myapp-12345". Note that it is up to the
+ caller to prevent oversized keys, and to ensure that the key contains legal
+ characters on the respective platform. Qt will silently truncate keys that
+ are too long.
+
+ \b{Apple sandbox limitations:} if the application is running inside of a
+ sandbox in an Apple operating system, the key must be in a very specific
+ format: \c {<application group identifier>/<custom identifier>}. Sandboxing
+ is implied for all applications distributed through the Apple App Store.
+ See Apple's documentation
+ \l{https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24}
+ {here} and \l{https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups}
+ {here} for more information, including how to obtain the application's group identifier.
+
+ \section1 Native key format
+
+ This section details the format of the native keys of the supported
+ backends.
+
+ \section3 POSIX Realtime
+ Native keys resemble file names and may contain any character that file
+ names do, except for a slash. POSIX requires the first character in the key
+ name to be a slash and leaves undetermined whether any additional slashes
+ are permitted. On most operating systems, the key length is the same as a
+ file name, but it is limited to 32 characters on Apple operating systems
+ (this includes the first slash and the terminating null, so only 30 usable
+ characters are possible).
+
+ The following are good examples of native POSIX keys: "/myapp",
+ "/org.example.myapp", "/org.example.myapp-12345".
+
+ QSharedMemory::platformSafeKey() and QSystemSemaphore::platformSafeKey()
+ simply prepend the slash. On Apple operating systems, they also truncate
+ the result to the available size.
+
+ \section3 Windows
+ Windows key types are NT
+ \l{https://learn.microsoft.com/en-us/windows/win32/sync/object-namespaces}{kernel
+ object names} and may be up to \c{MAX_PATH} (260) characters in length.
+ They look like relative paths (that is, they don't start with a backslash
+ or a drive letter), but unlike file names on Windows, they are
+ case-sensitive.
+
+ The following are good examples of native Windows keys: "myapp",
+ "org.example.myapp", "org.example.myapp-12345".
+
+ QSharedMemory::platformSafeKey() and QSystemSemaphore::platformSafeKey()
+ insert a prefix to disambiguate shared memory and system semaphores,
+ respectively.
+
+ \section3 X/Open System Interfaces (XSI) / System V
+ System V keys take the form of the name of a file in the system, and thus
+ have the exact same limitations as file paths do. Both QSharedMemory and
+ QSystemSemaphore will create this file if it does not exist when creating
+ the object. If auto-removal is disabled, it may also be shared between
+ QSharedMemory and QSystemSemaphore without conflict and can be any extant
+ file (for example, it can be the process executable itself, see
+ QCoreApplication::applicationFilePath()). The path should be an absolute
+ one to avoid mistakes due to different current directories.
+
+ QSharedMemory::platformSafeKey() and QSystemSemaphore::platformSafeKey()
+ always return an absolute path. If the input was already absolute, they
+ will return their input unchanged. Otherwise, they will prepend a suitable
+ path where the application usually has permission to create files in.
+
+ \section1 Ownership
+
+ Shared memory and system semaphore objects need to be created before use,
+ which is accomplished with QSharedMemory::create() or by passing
+ QSystemSemaphore::Create to the constructor, respectively.
+
+ On Unix systems, the Qt classes that created the object will be responsible
+ for cleaning up the object in question. Therefore, if the application with
+ that C++ object exits uncleanly (a crash, qFatal(), etc.), the object may
+ be left behind. If that happens, applications may fail to create the
+ object again and should instead attach to an existing one. For example, for
+ QSharedMemory:
+
+ \code
+ if (!shm.create(4096) && shm.error() == QSharedMemory::AlreadyExists)
+ shm.attach();
+ \endcode
+
+ Re-attaching to a QSystemSemaphore is probably unwise, as the token counter
+ in it is probably in an unknown state and therefore may lead to deadlocks.
+
+ \section3 POSIX Realtime
+ POSIX Realtime object ownership is patterned after files, in the sense that
+ they exist independent of any process using them or not. Qt is unable to
+ determine if the object is still in use, so auto-removal will remove it
+ even then, which will make attaching to the same object impossible but
+ otherwise not affecting existing attachments.
+
+ Prior to Qt 6.6, Qt never cleaned up POSIX Realtime objects, except on QNX.
+
+ \section3 X/Open System Interfaces (XSI) / System V
+ There are two resources managed by the Qt classes: the file the key refers
+ to and the object itself. QSharedMemory manages the object cooperatively:
+ the last attachment is responsible for removing the object itself and then
+ removing the key file. QSystemSemaphore will remove the object if and only
+ if it was passed QSystemSemaphore::Create; additionally, if it created the
+ key file, it will remove that too.
+
+ Since Qt 6.6, it is possible to ask either class not to clean up.
+
+ \section3 Windows
+ The operating system owns the object and will clean up after the last
+ handle to the object is closed.
+
+ \section1 Interoperability with old Qt applications
+
+ The QNativeIpcKey class was introduced in Qt 6.6. Prior to this version,
+ QSharedMemory and QSystemSemaphore backends were determined at the time of
+ Qt's own build. For Windows systems, it was always the Windows backend. For
+ Unix systems, it defaulted to the System V backend if the configuration
+ script determined it was available. If it was not available, it fell back
+ to the POSIX one. The POSIX backend could be explicitly
+ selected using the \c{-feature-ipc_posix} option to the Qt configure
+ script; if it was enabled, the \c{QT_POSIX_IPC} macro would be defined.
+
+ Qt 6.6 retains the configure script option but it no longer controls the
+ availability of the backends. Instead, it changes what
+ QNativeIpcKey::legacyDefaultTypeForOs() will return. Applications that need
+ to retain compatibility must use this key type exclusively to guarantee
+ interoperability.
+
+ The API in both QSharedMemory and QSystemSemaphore had the concept of a
+ cross-platform key, which is now deprecated in favor of using
+ QSharedMemory::legacyNativeKey() and QSystemSemaphore::legacyNativeKey().
+ Those two functions produce the same native key as the deprecated functions
+ did in prior versions. If the old code was for example:
+
+ \code
+ QSharedMemory shm("org.example.myapplication");
+ QSystemSemaphore sem("org.example.myapplication");
+ \endcode
+
+ It can be updated to be:
+ \code
+ QSharedMemory shm(QSharedMemory::legacyNativeKey("org.example.myapplication"));
+ QSystemSemaphore sem(QSystemSemaphore::legacyNativeKey("org.example.myapplication"));
+ \endcode
+
+ If the two applications exchanged native keys, there is no need to update
+ code such as:
+
+ \code
+ QSharedMemory shm;
+ shm.setNativeKey(key);
+ \endcode
+
+ Though if the older application did accept a native key, the new one may
+ opt to use \c{platformSafeKey()} with a second argument of
+ QNativeIpcKey::legacyDefaultTypeForOs().
+
+ \section3 X/Open System Interfaces (XSI) / System V
+ Never use existing files for QSharedMemory keys, as the old Qt application
+ may attempt to remove it. Instead, let QSharedMemory create it.
+
+ \section1 Interoperability with non-Qt applications
+
+ Interoperability with non-Qt applications is possible, with some limitations:
+ \list
+ \li Creation of shared memory segments must not race
+ \li QSharedMemory support for locking the segment is unavailable
+ \endlist
+
+ Communication with non-Qt applications must always be through the native
+ key.
+
+ QSharedMemory always maps the entire segment to memory. The non-Qt
+ application may choose to only map a subset of it to memory, with no ill
+ effects.
+
+ \section3 POSIX Realtime
+ POSIX shared memory can be opened using
+ \l{https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html}{shm_open()}
+ and POSIX system semaphores can be opened using
+ \l{https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_open.html}{sem_open()}.
+
+ Both of those functions take a \c name parameter that is the result of
+ QNativeIpcKey::nativeKey(), encoded for file names using
+ QFile::encodeName() / QFile::decodeName().
+
+ \section3 Windows
+ Windows shared memory objects can be opened using
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-createfilemappingw}{CreateFileMappingW}
+ and Windows system semaphore objects can be opened using
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createsemaphorew}{CreateSemaphoreW}.
+ Despite the name of both functions starting with "Create", they are able
+ to attach to existing objects.
+
+ The \c lpName parameter to those functions is the result of
+ QNativeIpcKey::nativeKey(), without transformation.
+
+ If the foreign application uses the non-Unicode version of those functions
+ (ending in "A"), the name can be converted to and from 8-bit using QString.
+
+ \section3 X/Open System Interfaces (XSI) / System V
+ System V shared memory can be obtained using
+ \l{https://pubs.opengroup.org/onlinepubs/9699919799/functions/shmget.html}{shmget()}
+ and System V system semaphores can be obtained using
+ \l{https://pubs.opengroup.org/onlinepubs/9699919799/functions/semget.html}{semget()}.
+
+ The \c{key} parameter to either of those functions is the result of the
+ \l{https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftok.html}{ftok()}
+ function when passed the file name obtained from QNativeIpcKey::nativeKey()
+ with an \c id of 81 or 0x51 (the ASCII capital letter 'Q').
+
+ System V semaphore objects may contain multiple semaphores, but
+ QSystemSemaphore only uses the first one (number 0 for \c{sem_num}).
+
+ Both QSharedMemory and QSystemSemaphore default to removing the object
+ using the \c{IPC_RMID} operation to \c{shmctl()} and \c{semctl()}
+ respectively if they are the last attachment.
+*/
diff --git a/src/corelib/doc/src/java-style-iterators.qdoc b/src/corelib/doc/src/java-style-iterators.qdoc
new file mode 100644
index 0000000000..d486b73488
--- /dev/null
+++ b/src/corelib/doc/src/java-style-iterators.qdoc
@@ -0,0 +1,174 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page java-style-iterators.html
+ \title Java-style Iterators in Qt
+ \ingroup groups
+ \ingroup qt-basic-concepts
+ \brief Java style iterators for Qt's containers.
+
+ \tableofcontents
+
+ \section1 Java-Style Iterators
+
+ For each container class, there are two Java-style iterator data
+ types: one that provides read-only access and one that provides
+ read-write access.
+
+ \note New code should use \l{STL-Style iterators} since these are more efficient
+ and can be used together with Qt's and STL's \l{generic algorithms}.
+
+ \table
+ \header \li Containers \li Read-only iterator
+ \li Read-write iterator
+ \row \li QList<T>, QQueue<T>, QStack<T>, \li QListIterator<T>
+ \li QMutableListIterator<T>
+ \row \li QSet<T> \li QSetIterator<T>
+ \li QMutableSetIterator<T>
+ \row \li QMap<Key, T>, QMultiMap<Key, T> \li QMapIterator<Key, T>
+ \li QMutableMapIterator<Key, T>
+ \row \li QHash<Key, T>, QMultiHash<Key, T> \li QHashIterator<Key, T>
+ \li QMutableHashIterator<Key, T>
+ \endtable
+
+ In this discussion, we will concentrate on QList and QMap. The
+ iterator types for QSet have exactly
+ the same interface as QList's iterators; similarly, the iterator
+ types for QHash have the same interface as QMap's iterators.
+
+ Unlike \l{STL-Style iterators}, Java-style iterators point \e between items
+ rather than directly \e at items. For this reason, they are either pointing
+ to the very beginning of the container (before the first item), at the very
+ end of the container (after the last item), or between two items. The
+ diagram below shows the valid iterator positions as red arrows for a list
+ containing four items:
+
+ \image javaiterators1.png
+
+ Here's a typical loop for iterating through all the elements of a
+ QList<QString> in order:
+
+ \snippet code/doc_src_containers.cpp 1
+
+ It works as follows: The QList to iterate over is passed to the
+ QListIterator constructor. At that point, the iterator is located
+ just in front of the first item in the list (before item "A").
+ Then we call \l{QListIterator::hasNext()}{hasNext()} to
+ check whether there is an item after the iterator. If there is, we
+ call \l{QListIterator::next()}{next()} to jump over that
+ item. The next() function returns the item that it jumps over. For
+ a QList<QString>, that item is of type QString.
+
+ Here's how to iterate backward in a QList:
+
+ \snippet code/doc_src_containers.cpp 2
+
+ The code is symmetric with iterating forward, except that we
+ start by calling \l{QListIterator::toBack()}{toBack()}
+ to move the iterator after the last item in the list.
+
+ The diagram below illustrates the effect of calling
+ \l{QListIterator::next()}{next()} and
+ \l{QListIterator::previous()}{previous()} on an iterator:
+
+ \image javaiterators2.png
+
+ The following table summarizes the QListIterator API:
+
+ \table
+ \header \li Function \li Behavior
+ \row \li \l{QListIterator::toFront()}{toFront()}
+ \li Moves the iterator to the front of the list (before the first item)
+ \row \li \l{QListIterator::toBack()}{toBack()}
+ \li Moves the iterator to the back of the list (after the last item)
+ \row \li \l{QListIterator::hasNext()}{hasNext()}
+ \li Returns \c true if the iterator isn't at the back of the list
+ \row \li \l{QListIterator::next()}{next()}
+ \li Returns the next item and advances the iterator by one position
+ \row \li \l{QListIterator::peekNext()}{peekNext()}
+ \li Returns the next item without moving the iterator
+ \row \li \l{QListIterator::hasPrevious()}{hasPrevious()}
+ \li Returns \c true if the iterator isn't at the front of the list
+ \row \li \l{QListIterator::previous()}{previous()}
+ \li Returns the previous item and moves the iterator back by one position
+ \row \li \l{QListIterator::peekPrevious()}{peekPrevious()}
+ \li Returns the previous item without moving the iterator
+ \endtable
+
+ QListIterator provides no functions to insert or remove items
+ from the list as we iterate. To accomplish this, you must use
+ QMutableListIterator. Here's an example where we remove all
+ odd numbers from a QList<int> using QMutableListIterator:
+
+ \snippet code/doc_src_containers.cpp 3
+
+ The next() call in the loop is made every time. It jumps over the
+ next item in the list. The
+ \l{QMutableListIterator::remove()}{remove()} function removes the
+ last item that we jumped over from the list. The call to
+ \l{QMutableListIterator::remove()}{remove()} does not invalidate
+ the iterator, so it is safe to continue using it. This works just
+ as well when iterating backward:
+
+ \snippet code/doc_src_containers.cpp 4
+
+ If we just want to modify the value of an existing item, we can
+ use \l{QMutableListIterator::setValue()}{setValue()}. In the code
+ below, we replace any value larger than 128 with 128:
+
+ \snippet code/doc_src_containers.cpp 5
+
+ Just like \l{QMutableListIterator::remove()}{remove()},
+ \l{QMutableListIterator::setValue()}{setValue()} operates on the
+ last item that we jumped over. If we iterate forward, this is the
+ item just before the iterator; if we iterate backward, this is
+ the item just after the iterator.
+
+ The \l{QMutableListIterator::next()}{next()} function returns a
+ non-const reference to the item in the list. For simple
+ operations, we don't even need
+ \l{QMutableListIterator::setValue()}{setValue()}:
+
+ \snippet code/doc_src_containers.cpp 6
+
+ As mentioned above QSet's iterator
+ classes have exactly the same API as QList's. We will now turn to
+ QMapIterator, which is somewhat different because it iterates on
+ (key, value) pairs.
+
+ Like QListIterator, QMapIterator provides
+ \l{QMapIterator::toFront()}{toFront()},
+ \l{QMapIterator::toBack()}{toBack()},
+ \l{QMapIterator::hasNext()}{hasNext()},
+ \l{QMapIterator::next()}{next()},
+ \l{QMapIterator::peekNext()}{peekNext()},
+ \l{QMapIterator::hasPrevious()}{hasPrevious()},
+ \l{QMapIterator::previous()}{previous()}, and
+ \l{QMapIterator::peekPrevious()}{peekPrevious()}. The key and
+ value components are extracted by calling \l{QMapIterator::key()}{key()} and \l{QMapIterator::value()}{value()} on
+ the object returned by next(), peekNext(), previous(), or
+ peekPrevious().
+
+ The following example removes all (capital, country) pairs where
+ the capital's name ends with "City":
+
+ \snippet code/doc_src_containers.cpp 7
+
+ QMapIterator also provides a \l{QMapIterator::key()}{key()} and a \l{QMapIterator::value()}{value()} function that
+ operate directly on the iterator and that return the key and
+ value of the last item that the iterator jumped above. For
+ example, the following code copies the contents of a QMap into a
+ QHash:
+
+ \snippet code/doc_src_containers.cpp 8
+
+ If we want to iterate through all the items with the same
+ value, we can use \l{QMapIterator::findNext()}{findNext()}
+ or \l{QMapIterator::findPrevious()}{findPrevious()}.
+ Here's an example where we remove all the items with a particular
+ value:
+
+ \snippet code/doc_src_containers.cpp 9
+
+*/
diff --git a/src/corelib/doc/src/json.qdoc b/src/corelib/doc/src/json.qdoc
index a32772f910..98ae202cfa 100644
--- a/src/corelib/doc/src/json.qdoc
+++ b/src/corelib/doc/src/json.qdoc
@@ -1,36 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group json
\title JSON Support in Qt
\ingroup qt-basic-concepts
\brief An overview of JSON support in Qt.
-
+ \ingroup explanations-dataprocessingandio
\ingroup frameworks-technologies
\keyword JSON
@@ -40,12 +16,10 @@
now widely used as a data exchange format on the internet.
The JSON support in Qt provides an easy to use C++ API to parse,
- modify and save JSON data. It also contains support for saving this
- data in a binary format that is directly "mmap"-able and very fast to
- access.
+ modify and save JSON data.
More details about the JSON data format can be found at \l{http://json.org}{json.org}
- and in \l{http://tools.ietf.org/html/rfc4627}{RFC-4627}.
+ and in \l {RFC 4627}.
\tableofcontents
@@ -99,8 +73,7 @@
A valid JSON document is either an array or an object, so a document always starts
with a square or curly bracket.
- \sa {JSON Save Game Example}
-
+ \sa {Saving and Loading a Game}
\section1 The JSON Classes
@@ -108,5 +81,4 @@
\l{Implicit Sharing}{implicitly shared classes}.
JSON support in Qt consists of these classes:
-
*/
diff --git a/src/corelib/doc/src/objectmodel/bindableproperties.qdoc b/src/corelib/doc/src/objectmodel/bindableproperties.qdoc
new file mode 100644
index 0000000000..9b3ea6ae66
--- /dev/null
+++ b/src/corelib/doc/src/objectmodel/bindableproperties.qdoc
@@ -0,0 +1,264 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page bindableproperties.html
+ \title Qt Bindable Properties
+ \brief Qt's bindable properties.
+
+ \ingroup qt-basic-concepts
+ \keyword Qt's Bindable Properties
+
+ Qt provides bindable properties. Bindable properties are properties
+ which either have a value or are specified using any C++ function,
+ typically a C++ lambda expression.
+ In case they are specified using a C++ function, they are
+ updated automatically whenever their dependencies change.
+
+ Bindable properties are implemented in the class QProperty, which
+ consists of the data object and a pointer to a management data structure, and
+ in class QObjectBindableProperty, which consists only of the data object and
+ uses the encapsulating QObject to store the pointer to the
+ management data structure.
+
+ \section1 Why Use Bindable Properties?
+
+ Property bindings are one of the core features of QML. They allow to specify
+ relationships between different object properties and automatically update
+ properties' values whenever their dependencies change. Bindable properties
+ allow to achieve the same not only in QML code, but also in C++. Using
+ bindable properties can help to simplify your program, by eliminating a lot
+ of boilerplate code for tracking and reacting to dependency updates of
+ different objects.
+
+ The \l {Introductory Example} below demonstrates the usage of bindable
+ properties in C++ code. You can also check \l {Bindable Properties} example
+ to see how the bindable properties can help to improve your code.
+
+ \section1 Introductory Example
+
+ The binding expression computes the value by reading other QProperty values.
+ Behind the scenes this dependency is tracked. Whenever a change in any property's
+ dependency is detected, the binding expression is re-evaluated and the new
+ result is applied to the property. For example:
+
+ \code
+ QProperty<QString> firstname("John");
+ QProperty<QString> lastname("Smith");
+ QProperty<int> age(41);
+
+ QProperty<QString> fullname;
+ fullname.setBinding([&]() { return firstname.value() + " " + lastname.value() + " age: " + QString::number(age.value()); });
+
+ qDebug() << fullname.value(); // Prints "John Smith age: 41"
+
+ firstname = "Emma"; // Triggers binding reevaluation
+
+ qDebug() << fullname.value(); // Prints the new value "Emma Smith age: 41"
+
+ // Birthday is coming up
+ age.setValue(age.value() + 1); // Triggers re-evaluation
+
+ qDebug() << fullname.value(); // Prints "Emma Smith age: 42"
+ \endcode
+
+ When a new value is assigned to the \c firstname property, the binding
+ expression for \c fullname is reevaluated. So when the last \c qDebug() statement
+ tries to read the name value of the \c fullname property, the new value is returned.
+
+ Since bindings are C++ functions, they may do anything that's possible
+ in C++. This includes calling other functions. If those functions access values
+ held by QProperty, they automatically become dependencies to the binding.
+
+ Binding expressions may use properties of any type, so in the above example the age
+ is an integer and folded into the string value using conversion to integer, but
+ the dependency is fully tracked.
+
+ \section1 Bindable Property Getters and Setters
+
+ When a class has a bindable property, either using QProperty
+ or QObjectBindableProperty, special care has to be taken when formulating
+ getters and setters for that property.
+
+ \section2 Bindable Property Getters
+
+ To ensure proper operation of the automatic dependency-tracking system,
+ every possible code path in a getter needs to read from the underlying
+ property object.
+ In addition, the property must not be written inside the getter.
+ Design patterns which recompute or refresh anything in the getter
+ are not compatible with bindable properties.
+
+ It is therefore recommended to only use trivial getters with bindable properties.
+
+ \section2 Bindable Property Setters
+
+ To ensure proper operation of the automatic dependency-tracking system,
+ every possible code path in a setter needs to write to the underlying
+ property object, even if the value did not change.
+
+ Any other code in a setter has a high propability of being incorrect.
+ Any code doing updates based on the new value is most likely a bug,
+ as this code won't be executed when the property is changed
+ through a binding.
+
+ It is therefore recommended to only use trivial setters with bindable properties.
+
+ \section1 Writing to a Bindable Property
+
+ Bindable properties inform their dependent properties about each change.
+ This might trigger change handlers, which in turn might call arbitrary code.
+ Thus, every write to a bindable property has to be inspected carefully.
+ The following problems might occur.
+
+ \section2 Writing Intermediate Values to Bindable Properties
+
+ Bindable properties must not be used as variables in algorithms. Each value written
+ would be communicated to dependent properties.
+ For example, in the following code, other properties that depend on
+ \b myProperty would be first informed about the change to \b 42, then about
+ the change to \b maxValue.
+
+ \badcode
+ myProperty = somecomputation(); // returning, say, 42
+ if (myProperty.value() > maxValue)
+ myProperty = maxValue;
+ \endcode
+
+ Instead, perform the computation in a separate variable. Correct usage is shown in the
+ following example.
+
+ \code
+ int newValue = someComputation();
+ if (newValue > maxValue)
+ newValue = maxValue;
+ myProperty = newValue; // only write to the property once
+ \endcode
+
+ \section2 Writing Bindable Properties in Transitional States
+
+ When a bindable property is a member of a class, each write to that property
+ might expose the current state to the outside. So bindable properties must
+ not be written in transient states, when class invariants are not met.
+
+ For example, in a class representing a circle which holds two members
+ \b radius and \b area consistent, a setter might look like this (where radius
+ is a bindable property):
+
+ \badcode
+ void setRadius(double newValue)
+ {
+ radius = newValue; // this might trigger change handlers
+ area = M_PI * radius * radius;
+ emit radiusChanged();
+ }
+ \endcode
+
+ Here, code triggered in change handlers might use the circle, while it has
+ the new radius, but still the old area.
+
+ \section1 Bindable Properties with Virtual Setters and Getters
+
+ Property setters and getters should normally be minimal and do nothing but
+ setting the property; hence it is not normally appropriate for such setters
+ and getters to be virtual. There is nothing it makes sense for the derived
+ class to do.
+
+ However some Qt classes can have properties with virtual setters. When
+ subclassing such a Qt class, overriding such setters requires special care.
+
+ In any case the base implementation \e must be called for the binding to
+ work correctly.
+
+ The following illustrates this approach.
+
+ \badcode
+ void DerivedClass::setValue(int val)
+ {
+ // do something
+ BaseClass::setValue(val);
+ // probably do something else
+ }
+ \endcode
+
+ All the common rules and recommendations regarding writing to bindable
+ properties also apply here. As soon as the base class implementation is
+ called, all the observers are notified about the change to the property.
+ This means that class invariants must be met before calling the base
+ implementation.
+
+ In the rare case where such virtual getters or setters are necessary, the
+ base class should document the requirements it imposes on overrides.
+
+ \section1 Formulating a Property Binding
+
+ Any C++ expression evaluating to the correct type can be used as a binding
+ expression and be given to the setBinding() method. However, to formulate
+ a correct binding, some rules must be followed.
+
+ Dependency tracking only works on bindable properties. It's the developer's
+ responsibility to ensure that all properties used in the binding expression
+ are bindable properties. When non-bindable properties are used in a binding
+ expression, changes to those properties do not trigger updates to the bound
+ property. No warning or error is generated either at compile-time or at run-time.
+ The bound property will be updated only when bindable properties used in the
+ binding expression are changed.
+ Non-bindable properties might be used in a binding if it's possible
+ to ensure that markDirty is called on the property being bound on each
+ change of the non-bindable dependency.
+
+ The bound property might evaluate its binding several times during its lifetime.
+ The developer must make sure that all objects used in the binding expression
+ live longer than the binding.
+
+ The bindable property system is not thread-safe. Properties used in the binding
+ expression on one thread must not be read or modified by any other thread.
+ An object of a QObject-derived class which has a property with a binding must
+ not be moved to a different thread.
+ Also, an object of a QObject-derived class which has a property which is used
+ in a binding must not be moved to a different thread. In this context, it's
+ irrelevant whether it's used in a binding of a property in the same object
+ or in a binding of a property in another object.
+
+ The binding expression should not read from the property it's a binding for. Otherwise,
+ an evaluation loop exists.
+
+ The binding expression must not write to the property it's a binding for.
+
+ Functions used as bindings as well as all code which is called inside a binding
+ must not co_await. Doing so can confuse the property system's tracking of dependencies.
+
+ \section1 Bindable Properties and Multithreading
+
+ Bindable properties are not threadsafe, unless stated otherwise.
+ A bindable property must not be read or modified by any thread other than
+ the one is was created in.
+
+ \section1 Tracking Bindable Properties
+
+ Sometimes the relationships between properties cannot be expressed using
+ bindings. Instead you may need to run custom code whenever the value of a property
+ changes and instead of assigning the value to another property, pass it to
+ other parts of your application. For example writing data into a network socket
+ or printing debug output. QProperty provides two mechanisms for tracking.
+
+ You can register for a callback function to be called whenever the value of
+ a property changes, by using onValueChanged(). If you want the callback to also
+ be called for the current value of the property, register your callback using
+ subscribe() instead.
+
+ \section1 Interaction with Q_PROPERTYs
+
+ A \l {The Property System}{Q_PROPERTY} that defines \c BINDABLE can be bound and
+ used in binding expressions. You can implement such properties using \l {QProperty},
+ \l {QObjectBindableProperty}, or \l {QObjectComputedProperty}.
+
+ Q_PROPERTYs without \c BINDABLE can also be bound and be used in binding expressions,
+ as long as they define a \c NOTIFY signal. You must wrap the property in a \l QBindable
+ using the \c {QBindable(QObject* obj, const char* property)} constructor. Then, the
+ property can be bound using \l QBindable::setBinding() or used in a binding
+ expression via \l QBindable::value(). You must use \c QBindable::value() in binding
+ expressions instead of the normal property \c READ function (or \c MEMBER) to enable
+ dependency tracking if the property is not \c BINDABLE.
+
+*/
diff --git a/src/corelib/doc/src/objectmodel/metaobjects.qdoc b/src/corelib/doc/src/objectmodel/metaobjects.qdoc
index 53b34fe120..3d7685447f 100644
--- a/src/corelib/doc/src/objectmodel/metaobjects.qdoc
+++ b/src/corelib/doc/src/objectmodel/metaobjects.qdoc
@@ -1,35 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page metaobjects.html
\title The Meta-Object System
\brief An overview of Qt's meta-object system and introspection capabilities.
-
+ \ingroup explanations-basics
\ingroup qt-basic-concepts
\keyword meta-object
\keyword Meta-Object System
@@ -72,7 +48,7 @@
\li QObject::inherits() function returns whether an object is an
instance of a class that inherits a specified class within the
QObject inheritance tree.
- \li QObject::tr() and QObject::trUtf8() translate strings for
+ \li QObject::tr() translates strings for
\l{Internationalization with Qt}{internationalization}.
\li QObject::setProperty() and QObject::property()
dynamically set and get properties by name.
diff --git a/src/corelib/doc/src/objectmodel/object.qdoc b/src/corelib/doc/src/objectmodel/object.qdoc
index 2dd2594ae4..7b6b840df0 100644
--- a/src/corelib/doc/src/objectmodel/object.qdoc
+++ b/src/corelib/doc/src/objectmodel/object.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page object.html
diff --git a/src/corelib/doc/src/objectmodel/objecttrees.qdoc b/src/corelib/doc/src/objectmodel/objecttrees.qdoc
index 29e2393e57..8939a534d4 100644
--- a/src/corelib/doc/src/objectmodel/objecttrees.qdoc
+++ b/src/corelib/doc/src/objectmodel/objecttrees.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page objecttrees.html
diff --git a/src/corelib/doc/src/objectmodel/properties.qdoc b/src/corelib/doc/src/objectmodel/properties.qdoc
index e3c506e8bc..99a3e60d88 100644
--- a/src/corelib/doc/src/objectmodel/properties.qdoc
+++ b/src/corelib/doc/src/objectmodel/properties.qdoc
@@ -1,35 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page properties.html
\title The Property System
\brief An overview of Qt's property system.
-
+ \ingroup explanations-basics
\ingroup qt-basic-concepts
\keyword Qt's Property System
@@ -68,14 +44,21 @@
specified. It is for reading the property value. Ideally, a const function
is used for this purpose, and it must return either the property's type or a
const reference to that type. e.g., QWidget::focus is a read-only
- property with \c READ function, QWidget::hasFocus().
+ property with \c READ function, QWidget::hasFocus(). If a \c BINDABLE is
+ specified, you can write \c{READ default} to have the \c READ accessor
+ generated from the \c BINDABLE.
\li A \c WRITE accessor function is optional. It is for setting the
property value. It must return void and must take exactly one
argument, either of the property's type or a pointer or reference
to that type. e.g., QWidget::enabled has the \c WRITE function
QWidget::setEnabled(). Read-only properties do not need \c WRITE
- functions. e.g., QWidget::focus has no \c WRITE function.
+ functions. e.g., QWidget::focus has no \c WRITE function. If you specify
+ both a \c BINDABLE and \c{WRITE default}, a \c WRITE accessor will be
+ generated from the \c BINDABLE. The generated \c WRITE accessor will \e not
+ explicitly emit any signal declared with \c NOTIFY. You should register
+ the signal as change handler to the \c BINDABLE, for example using
+ \l{Q_OBJECT_BINDABLE_PROPERTY}.
\li A \c MEMBER variable association is required if no \c READ accessor
function is specified. This makes the given member variable
@@ -99,8 +82,9 @@
which must be of the same type as the property. The parameter will take the
new value of the property. The \c NOTIFY signal should only be emitted when
the property has really been changed, to avoid bindings being unnecessarily
- re-evaluated in QML, for example. Qt emits automatically that signal when
- needed for MEMBER properties that do not have an explicit setter.
+ re-evaluated in QML, for example. The signal is emitted automatically when
+ the property is changed via the Qt API (QObject::setProperty,
+ QMetaProperty, etc.), but not when the MEMBER is changed directly.
\li A \c REVISION number or \c REVISION() macro is optional. If included,
it defines the property and its notifier signal to be used in a particular
@@ -109,7 +93,7 @@
\li The \c DESIGNABLE attribute indicates whether the property
should be visible in the property editor of GUI design tool (e.g.,
- \l {Qt Designer Manual}{Qt Designer}). Most properties are \c DESIGNABLE
+ \l {Qt Widgets Designer Manual}{\QD}). Most properties are \c DESIGNABLE
(default true). Valid values are true and false.
\li The \c SCRIPTABLE attribute indicates whether this property
@@ -131,6 +115,13 @@
editable property for (checkable) buttons. Note that QItemDelegate
gets and sets a widget's \c USER property.
+ \li The \c {BINDABLE bindableProperty} attribute indicates that the
+ property supports \l {Qt Bindable Properties}{bindings},
+ and that it is possible to set and inspect
+ bindings to this property via the meta object system (QMetaProperty).
+ \c bindableProperty names a class member of type QBindable<T>, where T
+ is the property type. This attribute was introduced in Qt 6.0.
+
\li The presence of the \c CONSTANT attribute indicates that the property
value is constant. For a given object instance, the READ method of a
constant property must return the same value every time it is called. This
@@ -217,7 +208,10 @@
The \c READ function is const and returns the property type. The
\c WRITE function returns void and has exactly one parameter of
the property type. The meta-object compiler enforces these
- requirements.
+ requirements. The equality check in the \c WRITE function, while not
+ mandatory, is good practice as there is no point in notifying and
+ potentially forcing re-evaluation in other places if nothing has
+ changed.
Given a pointer to an instance of MyClass or a pointer to a
QObject that is an instance of MyClass, we have two ways to set
@@ -283,10 +277,29 @@
Connected to the property system is an additional macro,
Q_CLASSINFO(), that can be used to attach additional
- \e{name}--\e{value} pairs to a class's meta-object, for example:
+ \e{name}--\e{value} pairs to a class's meta-object. This is
+ used for instance to mark a property as the \e default one
+ in the context of \l{QML Object Types}:
\snippet code/doc_src_properties.cpp 7
Like other meta-data, class information is accessible at run-time
through the meta-object; see QMetaObject::classInfo() for details.
+
+ \section1 Using Bindable Properties
+
+ Three different types can be used to implement bindable properties:
+ \list
+ \li \l QProperty
+ \li \l QObjectBindableProperty
+ \li \l QObjectComputedProperty.
+ \endlist
+ The first one is a general class for bindable properties. The latter
+ two can only be used inside a \l QObject.
+
+ For more information, including examples, see the classes mentioned above
+ and the general tips on implementing and using
+ \l {Qt Bindable Properties}{bindable properties}.
+
+ \sa {Qt Bindable Properties}, {Defining QML Types from C++}
*/
diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
index 85fe4df2ce..f0eeb20048 100644
--- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
+++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page signalsandslots.html
@@ -32,7 +8,7 @@
\ingroup qt-basic-concepts
\brief An overview of Qt's signals and slots inter-object
communication mechanism.
-
+ \ingroup explanations-basics
Signals and slots are used for communication between objects. The
signals and slots mechanism is a central feature of Qt and
probably the part that differs most from the features provided by
@@ -133,8 +109,7 @@
when the signal is emitted.
Signals are automatically generated by the \l moc and must not be
- implemented in the \c .cpp file. They can never have return types
- (i.e. use \c void).
+ implemented in the \c .cpp file.
A note about arguments: Our experience shows that signals and slots
are more reusable if they do not use special types. If
@@ -321,8 +296,7 @@
callbacks, you'd have to find five different names and keep track
of the types yourself.
- \sa QLCDNumber, QObject::connect(), {Digital Clock Example},
- {Tetrix Example}
+ \sa QLCDNumber, QObject::connect()
\section1 Signals And Slots With Default Arguments
@@ -412,8 +386,12 @@
\section2 Using Qt with 3rd Party Signals and Slots
It is possible to use Qt with a 3rd party signal/slot mechanism.
- You can even use both mechanisms in the same project. Just add the
- following line to your qmake project (.pro) file.
+ You can even use both mechanisms in the same project. To do that,
+ write the following into your CMake project file:
+
+ \snippet code/doc_src_containers.cpp cmake_no_keywords
+
+ In a qmake project (.pro) file, you need to write:
\snippet code/doc_src_containers.cpp 22
@@ -423,4 +401,19 @@
with the \c{no_keywords} flag, simply replace all uses of the Qt
moc keywords in your sources with the corresponding Qt macros
Q_SIGNALS (or Q_SIGNAL), Q_SLOTS (or Q_SLOT), and Q_EMIT.
-*/
+
+ \section2 Signals and slots in Qt-based libraries
+
+ The public API of Qt-based libraries should use the keywords
+ \c{Q_SIGNALS} and \c{Q_SLOTS} instead of \c{signals} and
+ \c{slots}. Otherwise it is hard to use such a library in a project
+ that defines \c{QT_NO_KEYWORDS}.
+
+ To enforce this restriction, the library creator may set the
+ preprocessor define \c{QT_NO_SIGNALS_SLOTS_KEYWORDS} when building
+ the library.
+
+ This define excludes signals and slots without affecting whether
+ other Qt-specific keywords can be used in the library
+ implementation.
+ */
diff --git a/src/corelib/doc/src/plugin-classes.qdoc b/src/corelib/doc/src/plugin-classes.qdoc
index 3becad48be..dab3e74e82 100644
--- a/src/corelib/doc/src/plugin-classes.qdoc
+++ b/src/corelib/doc/src/plugin-classes.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group plugins
diff --git a/src/corelib/doc/src/qt6-changes.qdoc b/src/corelib/doc/src/qt6-changes.qdoc
index 21bbd499ed..011568ef75 100644
--- a/src/corelib/doc/src/qt6-changes.qdoc
+++ b/src/corelib/doc/src/qt6-changes.qdoc
@@ -1,33 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtcore-changes-qt6.html
- \title Porting to Qt 6 - Qt Core
+ \title Changes to Qt Core
+ \ingroup changes-qt-5-to-6
+ \brief Changes to containers, strings, serialization and I/O classes.
Qt 6 is a result of the conscious effort to make the framework more
efficient and easy to use.
@@ -46,7 +24,7 @@
\section3 qHash() Signature
For custom types, QHash and QMultiHash rely on you providing
- a \l{The qHash() hashing function} {custom qHash() function}
+ a \l{qHash}{custom qHash() function}
in the same namespace. In Qt 4 and Qt 5, the return
value and optional second argument of a \c qHash function
was of type \c uint. In Qt 6, it is \c size_t.
@@ -68,12 +46,12 @@
\section3 Stability of References
- The implementation of QHash and QMultiHash in Qt 6 got changed from
+ The implementation of QHash, QMultiHash and QSet in Qt 6 got changed from
a node based approach to a two stage lookup table. This design allows
to keep the memory overhead of a hash instance very small, while
at the same time giving good performance.
- One behavioral change to note is that the new QHash implementation
+ One behavioral change to note is that the new implementation
will not provide stable references to elements in the hash when the
table needs to grow, or when entries are removed. Applications that
rely on such stability might now run into undefined behavior.
@@ -85,4 +63,572 @@
In Qt 6, both types and use cases are distinct, and QHash::insertMulti
got removed.
+
+ \section2 QVector, QList
+
+ Prior to Qt 6, QVector and QList were separate classes. In Qt 6, they are
+ unified: Qt 5 QList implementation is gone and both classes use updated
+ QVector implementation instead. QList is the class with the actual
+ implementation and QVector is an alias (typedef) to QList.
+
+ QList's fromVector() and toVector(), and QVector's fromList() and toList(),
+ no longer involve data copying in Qt 6. They now return the object that they
+ were called for.
+
+ \section3 API Changes
+
+ QList's (and hence QVector's) size type is changed from \c int to \c
+ qsizetype. Together with the size type, all relevant methods' signatures are
+ updated to use \c qsizetype. This allows QList to hold more than 2^31 items
+ on 64 bit platforms.
+
+ When upgrading the code base to Qt 6, this API change would most likely
+ result in compiler warnings about narrowing type conversions. Having the
+ following example code:
+
+ \code
+ void myFunction(QList<MyType> &data) {
+ int size = data.size();
+ // ...
+ const int pos = getInsertPosition(size);
+ data.insert(pos, MyType());
+ // ...
+ }
+ \endcode
+
+ you would need to update it to use either \c qsizetype or an auto keyword:
+
+ \code
+ void myFunction(QList<MyType> &data) {
+ auto size = data.size();
+ // ...
+ const auto pos = getInsertPosition(size);
+ data.insert(pos, MyType());
+ // ...
+ }
+ \endcode
+
+ Alternatively, you may use type casting and cast everything to \c int or to
+ \c qsizetype.
+
+ \note If you want to build against both Qt 5 and Qt 6, the auto keyword is a
+ good solution to cover signature differences between the versions.
+
+ \section3 Memory Layout
+
+ QList received multiple changes related to the memory layout in Qt 6.
+
+ In Qt 5, \c{sizeof(QList<T>)} was equal to a size of a pointer. Now, the
+ extra pointer indirection is removed and QList data members are directly
+ stored in the object. By default, expect \c{sizeof(QList<T>)} to be equal to
+ the size of 3 pointers.
+
+ At the same time, memory layout of the elements is also updated. QList now
+ always stores its elements directly in the allocated memory region as
+ opposed to Qt 5, where certain objects were separately allocated on the heap
+ and pointers to the objects were placed into the QList instead.
+
+ Note that the latter, in particular, affects large objects. To have Qt 5
+ behavior, you could wrap your objects into smart pointers and store these
+ smart pointers in QList directly. In this case, the type of your QList would
+ be \c{QList<MySmartPointer<MyLargeObject>>} as opposed to
+ \c{QList<MyLargeObject>} in Qt 5.
+
+ \section3 Stability of References
+
+ There are several changes made to the QVector/QList implementation. The
+ QVector related one is: insertion at the beginning is optimized (similarly
+ to QList in Qt 5). The QList related one is: memory layout for the elements
+ is simplified.
+
+ \important These changes impact the stability of references. In Qt 6, you
+ should consider any size or capacity modifying method to invalidate all
+ references, even when QList is not \l{Implicit Sharing}{implicitly shared}.
+ Exceptions to this rule are documented explicitly.
+
+ Applications that rely on certain reference stability might run into
+ undefined behavior when upgraded to use Qt 6. You should pay extra attention
+ to cases where QVector or QList with a non C-compatible array layout were
+ used originally.
+
+ \section1 View classes in Qt6
+
+ \section2 General Overview
+
+ There are several new \c View classes coming with Qt6. There is the already
+ existing \l QStringView, now accompanied by \l QByteArrayView and followed
+ by a specialized \l QUtf8StringView and a more universal \l QAnyStringView.
+
+ \section2 Introduction to view classes on the example of QStringView
+
+ The QStringView class provides a unified view on UTF-16 strings with a
+ read-only subset of the QString API. Unlike QString, which keeps its own
+ copy of the string (possibly ref-counted), QStringView provides a view of
+ a string that is stored elsewhere.
+
+ \code
+ char hello[]{ "Hello." }; // narrow multi-byte string literal
+ QString str{hello}; // needs to make a copy of the string literal
+ QString strToStr(str); // atomic increment involved to not create a copy of hello again
+
+ // The above code can be re-written to avoid copying and atomic increment.
+
+ QStringView view{ u"Hello." }; // view to UTF-16 encoded string literal
+ QStringView viewToView{ view }; // view of the same UTF-16 encoded string literal
+ \endcode
+
+ The string \c "Hello." is stored in the binary and is not allocated at
+ run-time. \c view is only a view onto the string \c "Hello.", therefore
+ no copy has to be created. When we copy a QStringView, the \c viewToView
+ observes the same string as the copied-from \c view is observing. This
+ means that \c viewToView does not need to create a copy or an atomic
+ increment. They are views onto the existing string \c "Hello.".
+
+ \section2 Views as function argument
+
+ Views should be passed by value, not by reference-to-const.
+
+ \code
+ void myfun1(QStringView sv); // preferred
+ void myfun2(const QStringView &sv); // compiles and works, but slower
+ \endcode
+
+ \section2 View manipulation functions
+
+ QStringView supports functions that let us manipulate the view of the
+ string. This allows us to change the view without creating a partial copy
+ of the viewed string.
+
+ \code
+ QString pineapple = "Pineapple";
+ QString pine = pineapple.left(4);
+
+ // The above code can be re-written to avoid creating a partial copy.
+
+ QStringView pineappleView{ pineapple };
+ QStringView pineView = pineappleView.left(4);
+ \endcode
+
+ \section2 Non null-terminated strings and strings containing \c {'\0'}
+
+ QStringView supports both null-terminated and non null-terminated strings.
+ The difference comes from the way you initialize the QStringView:
+
+ \code
+ QChar aToE[]{ 'a', 'b', 'c', 'd', 'e' };
+
+ QStringView nonNull{ aToE, std::size(aToE) }; // with length given
+ QStringView nonNull{ aToE }; // automatically determines the length
+
+ QChar fToJ[]{ 'f', 'g', 'h', '\0', 'j' };
+
+ // uses given length, doesn't search for '\0', so '\0' at position 3
+ // is considered to be a part of the string similarly to 'h' and 'j
+ QStringView nonNull{ fToJ, std::size(fToJ) };
+ QStringView part{ fToJ }; //stops on the first encounter of '\0'
+ \endcode
+
+ \section2 Ownership model of views
+
+ As \c views do not own the memory they reference, care must be taken to
+ ensure that the referenced data (for example, owned by a \l QString)
+ outlives the \c view on all code paths.
+
+ \badcode
+ QStringView sayHello()
+ {
+ QString hello("Hello.");
+ return QStringView{ hello }; // hello gets out of scope and destroyed
+ }
+
+ void main()
+ {
+ QStringView hello{ sayHello() };
+ qDebug() << hello; // undefined behavior
+ }
+ \endcode
+
+ \section2 Converting an QStringView to QString
+
+ QStringView will not implicitly or explicitly convert to a QString, but can
+ create a deep copy of its data:
+
+ \code
+ void print(const QString &s) { qDebug() << s; }
+
+ void main()
+ {
+ QStringView string{ u"string"};
+
+ // print(string); // invalid, no implicit conversion
+ // QString str{ string }; // invalid, no explicit conversion
+
+ print(string.toString());
+ QString str = string.toString(); // create QString from view
+ }
+ \endcode
+
+ \section2 Important notes
+
+ By leveraging the new view classes, one can achieve a lot of performance
+ boost in many use cases. However, it is important to know that there might
+ be some caveats. Therefore it is important to remember:
+
+ \list
+ \li Views should be passed by value, not by reference-to-const.
+ \li Constructing a view with a negative length is undefined behavior.
+ \li Care must be taken to ensure that the referenced data (for example,
+ owned by a \l QString) outlives the view on all code paths.
+ \endlist
+
+ \section1 String related classes
+
+ \section2 The QStringView class
+
+ Starting with Qt6 it is generally recommended to use \l QStringView over
+ \c QStringRef. \l QStringView references a contiguous portion of a UTF-16
+ string it does not own. It acts as an interface type to all kinds of UTF-16
+ strings, without the need to construct a \l QString first. The \l QStringView
+ class exposes almost all read-only methods of \l QString and the previously
+ existing \c QStringRef class.
+
+ \note Care must be taken to ensure that the referenced string data (for
+ example, owned by a \l QString) outlives the \l QStringView on all code paths.
+
+ \note If a \l QStringView wraps a \l QString, care needs to be taken since
+ unlike \c QStringRef \l QStringView will not update the internal data pointer
+ once the \l QString data relocates.
+
+ \code
+ QString string = ...;
+ QStringView view{string};
+
+ // Appending something very long might cause a relocation and will
+ // ultimately result in a garbled QStringView.
+ string += ...;
+ \endcode
+
+ \section2 The QStringRef class
+
+ In Qt6 \l QStringRef got removed from Qt Core. To ease porting of existing
+ applications without touching the whole code-base, the \c QStringRef class
+ did not vanish completely and instead it got moved into the Qt5Compat module.
+ If you want to use \c QStringRef further, see \l {Using the Qt5Compat module}.
+
+ Unfortunately, some methods exposed by \l QString returning a \c QStringRef,
+ could not be moved to Qt5Compat. Therefore some manual porting may be
+ needed. If your code uses one or more of the following functions you need to
+ port them to use \l QStringView or \l QStringTokenizer. It is also
+ recommended to use \l {QStringView::tokenize} over \l {QStringView::split}
+ for performance critical code.
+
+ Change code using \c QStringRef:
+ \code
+ QString string = ...;
+ QStringRef left = string.leftRef(n);
+ QStringRef mid = string.midRef(n);
+ QStringRef right = string.rightRef(n);
+
+ QString value = ...;
+ const QVector<QStringRef> refs = string.splitRef(' ');
+ if (refs.contains(value))
+ return true;
+ \endcode
+
+ to:
+
+ \code
+ QString string = ...;
+ QStringView left = QStringView{string}.left(n);
+ QStringView mid = QStringView{string}.mid(n);
+ QStringView right = QStringView{string}.right(n);
+
+ QString value = ...;
+ const QList<QStringView> refs = QStringView{string}.split(u' ');
+ if (refs.contains(QStringView{value}))
+ return true;
+ // or
+ const auto refs = QStringView{string}.tokenize(u' ');
+ for (auto ref : refs) {
+ if (ref == value)
+ return true;
+ }
+ \endcode
+
+ \section1 QMutex and Related Classes
+
+ In Qt 6, QRecursiveMutex does not inherit from QMutex anymore. This change was
+ done to improve the performance of both QMutex and QRecursiveMutex.
+
+ Due to those changes, the QMutex::RecursionMode enum has been removed, and
+ QMutexLocker is now a templated class that can operate on both QMutex and
+ QRecursiveMutex.
+
+ \section1 QFuture and Related Classes
+
+ \section2 The QFuture class
+
+ To avoid unintended usage of QFuture, there were some changes to
+ QFuture API in Qt 6, which may introduce source compatibility breaks.
+
+ \section3 Implicit conversions between QFuture and other types
+
+ Conversion of \c QFuture<T> to \c T has been disabled. The casting
+ operator was calling QFuture::result(), which may lead to undefined
+ behavior if the user has moved the results from QFuture via
+ QFuture::takeResult() before trying to do the conversion. Use
+ QFuture::result() or QFuture::takeResult() methods explicitly,
+ where you need to convert \c QFuture<T> to \c T.
+
+ The implicit conversion from \c QFuture<T> to \c QFuture<void> has
+ been also disabled. If you really intend to do the conversion, use the
+ explicit \c {QFuture<void>(const QFuture<T> &)} constructor:
+
+ \code
+ QFuture<int> future = ...
+ QFuture<void> voidFuture = QFuture<void>(future);
+ \endcode
+
+ \section3 Equality operators
+
+ The equality operators of QFuture have been removed. They were comparing
+ the underlying d-pointers instead of comparing the results, which is not
+ what users might expect. If you need to compare QFuture objects, use
+ \c QFuture::result() or \c QFuture::takeResult() methods. For example:
+
+ \code
+ QFuture<int> future1 = ...;
+ QFuture<int> future2 = ...;
+ if (future1.result() == future2.result())
+ // ...
+ \endcode
+
+ \section2 Behavioral Changes to QFuture and QFutureWatcher
+
+ In Qt 6, there were some improvements to QFuture and QFutureWatcher which
+ caused the following behavioral changes:
+
+ \list
+
+ \li After pausing QFuture or QFutureWatcher (by calling \c pause() or
+ \c setPaused(true)), QFutureWatcher will not immediately stop delivering
+ progress and result ready signals. At the moment of pausing there may be
+ still computations that are in progress and cannot be stopped. Signals
+ for such computations may be still delivered after pause, instead of being
+ postponed and reported only after next resume. To get notified when pause
+ actually took effect, QFutureWatcher::suspended() signal can be used. In
+ addition, there are new \c isSuspending() and \c isSuspended() methods,
+ to check if the QFuture is in the process of suspending or it's already in
+ the suspended state. Note that for consistency reasons, for both QFuture
+ and QFutureWatcher the pause-related APIs were deprecated and replaced by
+ similar methods having "suspend" in the name instead.
+
+ \li QFuture::waitForFinished() will now wait until QFuture is actually in
+ the finished state, instead of exiting as soon as it is not in the running
+ state. This prevents \c waitForFinished() from exiting immediately, if at
+ the moment of calling it the future is not started yet. The same applies to
+ QFutureWatcher::waitForFinished(). This change won't affect the behavior of
+ code that was using QFuture with QtConcurrent. Only the code that was using
+ it with the undocumented \c QFutureInterface may be affected.
+
+ \li QFutureWatcher::isFinished() now reflects the finished-state of the
+ QFuture rather than returning false until QFutureWatcher::finished() has
+ been emitted.
+
+ \endlist
+
+ \section2 The QPromise class
+
+ In Qt 6, the new QPromise class should be used instead of unofficial
+ QFutureInterface as a "setter" counterpart of QFuture.
+
+ \section1 IO Classes
+
+ \section2 The QProcess class
+
+ In Qt 6, the QProcess::start() overload that interprets a single command string
+ by splitting it into program name and arguments is renamed to QProcess::startCommand().
+ However, a QProcess::start() overload that takes a single string, as well as a QStringList
+ for arguments exists. Since the QStringList parameter defaults to the empty list, existing
+ code only passing a string will still compile, but will fail to execute the process if it
+ is a complete command string that includes arguments.
+
+ Qt 5.15 introduced deprecation warnings for the respective overload to make it easy to
+ discover and update existing code:
+
+ \code
+ QProcess process;
+
+ // compiles with warnings in 5.15, compiles but fails with Qt 6
+ process.start("dir \"My Documents\"");
+
+ // works with both Qt 5 and Qt 6; also see QProcess::splitCommand()
+ process.start("dir", QStringList({"My Documents"});
+
+ // works with Qt 6
+ process.startCommand("dir \"My Documents\"");
+ \endcode
+
+ QProcess::pid() and the Q_PID type have been removed; use QProcess::processId() instead to
+ get the native process identifier. Code using native Win32 APIs to access the data in the
+ Q_PID as a Win32 \c{PROCESS_INFORMATION} struct is no longer supported.
+
+ \section1 Meta-Type system
+
+ \section2 The QVariant class
+
+ \c QVariant has been rewritten to use \c QMetaType for all of its operations. This implies
+ behavior changes in a few methods:
+
+ \list
+
+ \li \c QVariant::isNull() now only returns \c true if the \c QVariant is empty or contains a
+ \c nullptr. In Qt 5, it also returned true for classes in qtbase which had an \c isNull method
+ themselves if that one returned true. Code relying on the old behavior needs to check whether
+ the contained value returns isNull – however such code is unlikely to occur in practice, as
+ \c isNull() is rarely the property one is interested in (compare \c QString::isEmpty() / \c isNull()
+ and \c QTime::isValid / \c isNull).
+
+ \li \c QVariant::operator== uses \c QMetaType::equals in Qt 6. Therefore, some graphical
+ types like \c QPixmap, \c QImage and \c QIcon will never compare equal. Moreover, floating
+ point numbers stored in \c QVariant are no longer compared with \c qFuzzyCompare, but instead
+ use exact comparisons.
+
+ \endlist
+
+ Furthermore, QVariant::operator<, QVariant::operator<=, QVariant::operator> and
+ QVariant::operator>= were removed, because different variants are not always orderable. This
+ also means that QVariant cannot be used anymore as a key in a QMap.
+
+ \section2 The QMetaType class
+
+ In Qt 6, registration of comparators, and QDebug and QDataStream streaming operators is
+ done automatically. Consequently, \c QMetaType::registerEqualsComparator(),
+ \c QMetaType::registerComparators(), \c qRegisterMetaTypeStreamOperators() and
+ \c QMetaType::registerDebugStreamOperator() do no longer exist. Calls to those methods
+ have to be removed when porting to Qt 6.
+
+ \section2 Type registration
+
+ Types used in \c Q_PROPERTY have their meta-type stored in the class' \c QMetaObject. This
+ requires the types to be complete when moc sees them, which can lead to compilation errors
+ in code that worked in Qt 5. There are three ways to fix this issue:
+
+ \list
+
+ \li Include the header which defines the type.
+ \li Instead of using an include, use the \c Q_MOC_INCLUDE macro. This helps if including the header
+ would cause a cyclic dependency, or when it would slow down compilation.
+ \li If the header is present in the cpp file which implements the class, it is also possible to include
+ the moc generated file there.
+
+ \endlist
+
+ \section1 Regular expression classes
+
+ \section2 The QRegularExpression class
+
+ In Qt 6, the \c QRegExp type has been retired to the Qt5Compat module
+ and all Qt APIs using it have been removed from other modules.
+ Client code which used it can be ported to use \l QRegularExpression
+ in its place. As \l QRegularExpression is present already in Qt 5,
+ this can be done and tested before migration to Qt 6.
+
+ \include corelib/port-from-qregexp.qdocinc porting-to-qregularexpression
+
+ \section2 The QRegExp class
+
+ In Qt6 \l QRegExp got removed from Qt Core. If your application cannot be
+ ported right now, \c QRegExp still exists in Qt5Compat to keep these
+ code-bases working. If you want to use \c QRegExp further, see
+ \l {Using the Qt5Compat module}.
+
+ \section1 QEvent and subclasses
+
+ The QEvent class defined a copy constructor and an assignment operator,
+ in spite of being a polymorphic class. Copying classes with virtual methods
+ can result in slicing when assigning objects from different classes to each
+ other. Since copying and assigning often happens implicilty, this could
+ lead to hard-to-debug problems.
+
+ In Qt 6, the copy constructor and assignment operator for QEvent subclasses
+ have been made protected to prevent implicit copying. If you need to copy
+ events, use the \l{QEvent::}{clone} method, which will return a heap-allocated
+ copy of the QEvent object. Make sure you delete the clone, perhaps using
+ std::unique_ptr, unless you post it (in which case Qt will delete it once it
+ has been delivered).
+
+ In your QEvent subclasses, override clone(), and declare the protected and
+ default-implemented copy constructor and assignment operator like this:
+
+ \code
+ class MyEvent : public QEvent
+ {
+ public:
+ // ...
+
+ MyEvent *clone() const override { return new MyEvent(*this); }
+
+ protected:
+ MyEvent(const MyEvent &other) = default;
+ MyEvent &operator=(const MyEvent &other) = default;
+ MyEvent(MyEvent &&) = delete;
+ MyEvent &operator=(MyEvent &&) = delete;
+ // member data
+ };
+ \endcode
+
+ Note that if your MyEvent class allocates memory (e.g. through a
+ pointer-to-implementation pattern), then you will have to implement
+ custom copy semantics.
+
+ \section1 Serialization classes
+
+ In Qt 6, QJsonDocument methods for converting it to/from Qt's legacy
+ JSON binary format were removed in favor of the standardized CBOR format.
+ Qt JSON types can be converted to Qt CBOR types, which can in turn be
+ serialized into the CBOR binary format and vice versa. See, for example,
+ \l QCborValue::fromJsonValue() and \l QCborValue::toJsonValue().
+
+ If you still need to use the binary JSON format, you can use the
+ replacements provided in the Qt5Compat module. They can be found in the
+ \l QBinaryJson namespace. See \l {Using the Qt5Compat module} to find out
+ how to use the module in your application.
+
+ \section1 Other classes
+
+ In Qt 5, QCoreApplication::quit() was equivalent to calling
+ \l{QCoreApplication::exit()}. This just exited the main event loop.
+
+ In Qt 6, the method will instead try to close all top-level windows by posting
+ a close event. The windows are free to cancel the shutdown process by
+ ignoring the event.
+
+ Call QCoreApplication::exit() to keep the non-conditional behavior.
+
+ QLibraryInfo::location() and QLibraryInfo::Location were deprecated due to inconsistent
+ naming. Use the new API QLibraryInfo::path() and QLibraryInfo::LibraryPath instead.
+
+ \section1 Qt State Machine Framework
+
+ \l {Qt State Machine} was moved into the Qt SCXML module (soon to be renamed to Qt
+ State Machines) and therefore it is no longer part of Qt Core. There were very few
+ cross dependencies inside Qt Core which ultimately led to this decision.
+
+ \section1 Using the Qt5Compat module
+
+ To use the \l {Qt 5 Core Compatibility APIs}{Qt5Compat} module, you need
+ to build with its headers in your include path and link against its library.
+ If you are using \l qmake, add the following to your \c .pro file:
+
+ \code
+ QT += core5compat
+ \endcode
+
+ If you build your application or library using \l {Build with CMake}{cmake},
+ add the following to your \c CMakeList.txt:
+ \code
+ PUBLIC_LIBRARIES
+ Qt::Core5Compat
+ \endcode
*/
diff --git a/src/corelib/doc/src/qtcore-index.qdoc b/src/corelib/doc/src/qtcore-index.qdoc
index 34a4446ccc..38452e1b2b 100644
--- a/src/corelib/doc/src/qtcore-index.qdoc
+++ b/src/corelib/doc/src/qtcore-index.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtcore-index.html
@@ -31,16 +7,15 @@
\brief The Qt Core module is part of Qt's essential modules.
- \section1 Core Functionalities
- Qt Core adds these features to C++:
+ The Qt Core module adds these features to C++:
\list
\li a very powerful mechanism for seamless object communication called
signals and slots
\li queryable and designable object properties
- \li hierarchical and queryable object trees that organize
- \li object ownership in a natural way with guarded pointers (QPointer)
+ \li hierarchical and queryable object trees that organize object ownership
+ in a natural way with guarded pointers (QPointer)
\li a dynamic cast that works across library boundaries
\endlist
@@ -53,14 +28,17 @@
\li \l{Signals & Slots}
\endlist
- \include module-use.qdocinc using qt module
- \quotefile overview/using-qt-core.cmake
+ \section1 Using the Module
- See also the \l{Build with CMake} overview.
+ \include {module-use.qdocinc} {using the c++ api}
+
+ \section2 Building with CMake
+
+ \include {module-use.qdocinc} {building with cmake} {Core}
\section2 Building with qmake
- If you use \l qmake to build your projects, Qt5Core is linked by default.
+ If you use \l qmake to build your projects, Qt Core is linked by default.
\section1 Threading and Concurrent Programming
@@ -97,15 +75,38 @@
\list
\li \l{The Animation Framework}
\li \l{JSON Support in Qt}
- \li \l{The State Machine Framework}
+ \li \l{CBOR Support in Qt}
+ \li \l{Inter-Process Communication}
\li \l{How to Create Qt Plugins}
\li \l{The Event System}
+ \li \l{Application Permissions}
+ \endlist
+
+ \section1 Reference
+
+ \list
+ \li \l{Qt Core C++ Classes}{C++ Classes}
+ \list
+ \li \l{Animation Framework}{Animation Classes}
+ \li \l{Threading Classes}
+ \li \l{Container Classes}
+ \li \l{Plugin Classes}
+ \li \l{Implicitly Shared Classes}
+ \li \l{Input/Output and Networking}{Input/Output Classes}
+ \li \l{Event Classes}
+ \endlist
+ \li CMake API
+ \list
+ \li \l{CMake Commands in Qt6 Core}{CMake Commands}
+ \li \l{CMake Variables in Qt6 Core}{CMake Variables}
+ \li \l{CMake Target Properties in Qt6 Core}{CMake Target Properties}
+ \endlist
\endlist
\section1 Module Evolution
- \l{Porting to Qt 6 - Qt Core} lists important changes in the module API
- and functionality that were done for the Qt 6 series of Qt.
+ \l{Changes to Qt Core} lists important changes in the module API
+ and functionality that were made for the Qt 6 series of Qt.
\section1 Licenses and Attributions
@@ -116,29 +117,12 @@
See \l{Qt Licensing} for further details.
Executables on Windows potentially link
- against \l{The qtmain Library}. This library is available
+ against \l{The QtEntryPoint Library}. This library is available
under commercial licenses and also under the
\l{BSD 3-clause "New" or "Revised" License}.
Furthermore, Qt Core in Qt \QtVersion may contain third party
- modules under following permissive licenses:
+ modules under the following permissive licenses:
\generatelist{groupsbymodule attributions-qtcore}
-
- \section1 Reference
- These are links to the API reference materials.
- \list
- \li \l{Qt Core C++ Classes}{C++ Classes}
- \list
- \li \l{Animation Framework}{Animation Classes}
- \li \l{Threading Classes}
- \li \l{Container Classes}
- \li \l{Plugin Classes}
- \li \l{Implicitly Shared Classes}
- \li \l{State Machine Classes}
- \li \l{Input/Output and Networking}{Input/Output Classes}
- \li \l{Event Classes}
- \endlist
- \endlist
-
*/
diff --git a/src/corelib/doc/src/qtcore.qdoc b/src/corelib/doc/src/qtcore.qdoc
index 70b14e755a..a46add1342 100644
--- a/src/corelib/doc/src/qtcore.qdoc
+++ b/src/corelib/doc/src/qtcore.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\module QtCore
@@ -35,4 +11,24 @@
\brief Provides core non-GUI functionality.
All other Qt modules rely on this module.
+
+ The \l{Qt Core} page contains information about how to use the module.
+*/
+
+/*!
+ \module QtCorePrivate
+ \title Qt Core Private C++ Classes
+ \qtvariable core-private
+ \preliminary
+ \brief Provides private core functionality.
+
+//! [qtcoreprivate-usage]
+ When building with CMake, use the following commands to use
+ private Qt Core APIs:
+
+ \badcode
+ find_package(Qt6 REQUIRED COMPONENTS Core)
+ target_link_libraries(mytarget PRIVATE Qt6::CorePrivate)
+ \endcode
+//! [qtcoreprivate-usage]
*/
diff --git a/src/corelib/doc/src/qtserialization.qdoc b/src/corelib/doc/src/qtserialization.qdoc
new file mode 100644
index 0000000000..14ee5e7a9c
--- /dev/null
+++ b/src/corelib/doc/src/qtserialization.qdoc
@@ -0,0 +1,145 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page qtserialization.html
+ \title Qt Serialization
+ \brief Serializations provided by Qt API
+
+ The purpose of serialization is to save the state of an object to be able to
+ recreate it when needed. It allows you to perform actions like:
+
+ \list
+ \li Sending the object to a remote application by using a web service
+ \li Passing the object as a JSON or XML string
+ \li Saving and restoring user information or sharing it across applications
+ \endlist
+
+ The Qt API provides support for serialization for several use cases:
+
+ \list
+ \li \l JSON support in Qt provides an easy to use C++ API to parse, modify
+ and save JSON data. \l {CBOR} {CBOR Support in Qt} is a compact form
+ of binary data encoding that is a superset of JSON.
+ \li \l QDataStream provides serialization of binary data to a QIODevice
+ \li \l {Qt XML C++ Classes} provide C++ implementations of the \l {XML Streaming}
+ and DOM standards for XML
+ \li \l CBOR is Qt's implementation for the CBOR serialization format.
+ \li \l QSettings provides a way of serializing and storing platform independent
+ application settings.
+ \endlist
+
+ \section1 Advantages of JSON and CBOR
+
+ When you use \l JSON information is stored in a QJsonObject and a QJsonDocument
+ takes care to stream values into a QByteArray.
+
+ For example
+ \code
+ QJsonObject jobject;
+ jobject["SensorID"] = m_id;
+ jobject["AmbientTemperature"] = m_ambientTemperature;
+ jobject["ObjectTemperature"] = m_objectTemperature;
+ jobject["AccelerometerX"] = m_accelerometerX;
+ jobject["AccelerometerY"] = m_accelerometerY;
+ jobject["AccelerometerZ"] = m_accelerometerZ;
+ jobject["Altitude"] = m_altitude;
+ jobject["Light"] = m_light;
+ jobject["Humidity"] = m_humidity;
+ QJsonDocument doc( jobject );
+
+ return doc.toJson();
+ \endcode
+
+ JSON has several advantages:
+
+ \list
+ \li Textual JSON is declarative, which makes it readable to humans
+ \li The information is structured
+ \li Exchanging generic information is easy
+ \li JSON allows extending messages with additional values
+ \li Many solutions exist to receive and parse JSON in cloud-based solutions
+ \endlist
+
+ \l CBOR is the Concise Binary Object Representation, a very compact form of
+ binary data encoding that is a superset of JSON. It was created by the IETF
+ Constrained RESTful Environments (CoRE) WG, which has been used in many new
+ RFCs. CBOR shares many of the advantages of JSON, but sacrifices human
+ readability for compactness.
+
+ \section1 Advantages of QDataStream Classes
+
+ \l QDataStream is a viable option when the whole flow of data is determined
+ and not about to change. In addition, both the reader and the writer of the
+ data must be written in Qt.
+
+ Adding support for this to a class requires two additional operators.
+ For example, for a class named SensorInformation:
+
+ \code
+ QDataStream &operator<<(QDataStream &, const SensorInformation &);
+ QDataStream &operator>>(QDataStream &, SensorInformation &);
+ \endcode
+
+ The implementation for the serialization is shown below:
+
+ \code
+ QDataStream &operator<<(QDataStream &out, const SensorInformation &item)
+ {
+ QDataStream::FloatingPointPrecision prev = out.floatingPointPrecision();
+ out.setFloatingPointPrecision(QDataStream::DoublePrecision);
+ out << item.m_id
+ << item.m_ambientTemperature
+ << item.m_objectTemperature
+ << item.m_accelerometerX
+ << item.m_accelerometerY
+ << item.m_accelerometerZ
+ << item.m_altitude
+ << item.m_light
+ << item.m_humidity;
+ out.setFloatingPointPrecision(prev);
+ return out;
+ }
+ \endcode
+
+ Deserialization works similarly, but using the \c {>>} operator.
+ For example, \c {out >> item.m_id}, and so on.
+
+ Usually, using QDataStream is faster than using textual JSON.
+
+ \section1 Advantages of Qt XML C++ Classes
+
+ Qt provides both DOM classes and stream-based classes to read and write
+ XML content.
+
+ Qt provides the QDomDocument class that represents the XML document and
+ two classes for reading and writing the XML through a simple streaming API:
+ QXmlStreamReader and QXmlStreamWriter.
+
+ \section2 The DOM XML Classes
+
+ QDomDocument class represents the entire XML document. It is the root of the
+ document tree and provides primary access to the document's data.
+
+ \section2 The Stream-Based XML Classes
+
+ A stream reader reports an XML document as a stream of tokens. This differs
+ from SAX as SAX applications provide handlers to receive XML events from the
+ parser, whereas the QXmlStreamReader drives the loop, pulling tokens from the
+ reader when they are needed. This pulling approach makes it possible to build
+ recursive descent parsers, allowing XML parsing code to be split into
+ different methods or classes.
+
+ QXmlStreamReader a parser for well-formed XML 1.0, excluding external parsed
+ entities. Hence, data provided to the stream reader adheres to the
+ W3C's criteria for well-formed XML, or an error will be raised. Functions
+ such as \c atEnd(), \c error(), and \c hasError() can be used to test for
+ such errors and obtain a description of them.
+
+ The QXmlStreamWriter is a streaming API that takes care of prefixing namespaces,
+ when the namespaceUri is specified when writing elements or attributes.
+
+ \section1 Classes that Provide Serialization
+
+ \annotatedlist qtserialization
+*/
diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc
index 9b80c31b00..7c7613c9b8 100644
--- a/src/corelib/doc/src/resource-system.qdoc
+++ b/src/corelib/doc/src/resource-system.qdoc
@@ -1,115 +1,219 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page resources.html
\title The Qt Resource System
- \brief A platform-independent mechanism for storing binary files in an application.
+ \brief A platform-independent mechanism for shipping resource files in an
+ application.
\keyword resource system
- The Qt resource system is a platform-independent mechanism for
- storing binary files in the application's executable. This is
- useful if your application always needs a certain set of files
- (icons, translation files, etc.) and you don't want to run the
- risk of losing the files.
+ The Qt resource system is a platform-independent mechanism for shipping
+ resource files in an application. Use it if your application always needs a
+ certain set of files (like icons, translation files, images), and you don't
+ want to use system-specific means to package and locate these resources.
- The resource system is based on tight cooperation between \l qmake,
- \l rcc (Qt's resource compiler), and QFile.
+ Most commonly, the resource files are embedded into your application
+ executable, or in libraries and plugins that are loaded by the application
+ executable. Alternatively, the resource files can also be stored in an
+ \l{External Resource Files}{external resource file}.
- \section1 Resource Collection Files (\c{.qrc})
+ The resource system is based on tight cooperation between Qt's \l rcc
+ resource compiler, the build system, and the Qt runtime API.
+
+ \note Currently, the Qt resource system does not make use of any
+ system-specific capabilities for handling resources, such as the ones on
+ Windows, \macos, and iOS. This might change in a future Qt release.
+
+ \section1 The Qt Resource Compiler (rcc)
+
+ The \l{Resource Compiler (rcc)} command line tool reads resource files and
+ generates either a C++ or Python source file, or an \c .rcc file.
+
+ The list of files and related metadata is passed to \c rcc in the form of a
+ \l{Qt Resource Collection File}.
+
+ By default, rcc will generate C++ source code that is then compiled as part
+ of an executable or library. The \c{-g python} option generates Python
+ source code instead. The \c -binary option generates a binary archive that
+ is by convention saved in an \c .rcc file and can be loaded at runtime.
+
+ \note While it is possible to run \c rcc from the command line, this is
+ typically best left to a build system. See also the sections about
+ \l{qmake} and \l{CMake} below.
+
+ \section1 Qt Resource Collection File (.qrc)
+ \target {Qt Resource Collection File}
\target {Resource Collection Files}
- The resources associated with an application are specified in a
- \c .qrc file, an XML-based file format that lists files on the
- disk and optionally assigns them a resource name that the
- application must use to access the resource.
+ A \c .qrc file is an XML document that enumerates local files to be
+ included as runtime resources. It serves as input to \c{rcc}.
Here's an example \c .qrc file:
\quotefile resource-system/application.qrc
- The resource files listed in the \c .qrc file are files that are
- part of the application's source tree. The specified paths are
- relative to the directory containing the \c .qrc file. Note that
- the listed resource files must be located in the same directory as
- the \c .qrc file, or one of its subdirectories.
-
- Resource data can either be compiled into the binary and thus accessed
- immediately in application code, or a binary resource can be created
- and at a later point in application code registered with the resource
- system.
-
- By default, resources are accessible in the application under the
- same file name as they have in the source tree, with a \c :/ prefix,
- or by a \l{QUrl}{URL} with a \c qrc scheme.
-
- For example, the file path \c :/images/cut.png or the URL
- \c qrc:///images/cut.png would give access to the
- \c cut.png file, whose location in the application's source tree
- is \c images/cut.png. This can be changed using the \c file tag's
+ Each \c <file> element in the XML identifies a file in the application's
+ source tree. The path is resolved relative to the directory containing
+ the \c .qrc file.
+
+ The path is also used by default to identify the file's content at runtime.
+ That is, the file \c titlebarLeft.png will be available in the resource system as
+ \c{:/res/titlebarLeft.png} or \c{qrc:/res/titlebarLeft.png}.
+ To override this default run-time name, see \l{Prefixes} and \l{Aliases}.
+
+ \e{Qt Creator}, \e{Qt Design Studio}, \QD, and \e{Qt Visual Studio Tools}
+ allow you to create, inspect and edit \c .qrc files through a convenient
+ user interface. Except for \QD, they also provide wizards for projects
+ using the Qt resource system.
+
+ \section1 Build System Integration
+
+ The processing of resource files with \c rcc is typically done at the time
+ the application is built. Several build tools have dedicated support for
+ this, including \l CMake and \l qmake.
+
+ \section2 CMake
+
+ If \c CMAKE_AUTORCC is enabled, you can just add \c .qrc files as sources
+ to your executable or library. The referenced resource files will then be
+ embedded into the binary:
+
+ \snippet resource-system/CMakeLists.txt AUTORCC
+
+ See \l {https://cmake.org/cmake/help/latest/prop_tgt/AUTORCC.html}
+ {CMake's AUTORCC documentation} for more details about AUTORCC.
+
+ An alternative to AUTORCC is using Qt6Core's CMake function
+ \l qt_add_resources, which gives more control over the creation of
+ resources. For example, it allows you to specify the content of the
+ resource directly in the project file without writing a \c .qrc file first:
+
+ \snippet resource-system/CMakeLists.txt qt_add_resources
+
+ Finally, \l qt_add_qml_module allows you to embed Qt Quick resources into
+ the resource system of your application. The function is defined in the
+ \c Qml component of the \c Qt6 CMake package.
+
+ \section2 qmake
+
+ \l{qmake Manual}{qmake} supports handing resources with the \l{RESOURCES}
+ variable. If you add a \c .qrc file path to the variable, the listed
+ resource files will be embedded into the generated library or executable:
+
+ \snippet resource-system/application.pro qrc
+
+ This creates a resource of several \c{.png} files, that are addressable
+ like this: \c{":/res/titlebarLeft.png"}.
+
+ If the directory layout of the files you want to embed into the resource
+ doesn't match the expectations of the application, you can specify
+ \c{resources.base}. \c base is a path prefix that denotes the root point of
+ the file's alias. In the example above, if \c{resources.base} is set to
+ \c{"res"}, then \c{titlebarLeft.png} is addressable as \c{":/titlebarLeft.png"}.
+
+ \section1 Runtime API
+
+ Qt API that deals with iterating and reading files has built-in support for
+ the Qt Resource System. You can pass a resource path instead of a local
+ file path to QFile and QDir, but also for instance to the QIcon, QImage, and
+ QPixmap constructors:
+
+ \snippet resource-system/mainwindow.cpp 21
+
+ The \c : prefix makes it explicit that "/images/cut.png" should be loaded
+ from the Qt Resource System.
+
+ You can also reference the Qt resource system through a QUrl. Use the
+ \c qrc scheme in this case:
+
+ \snippet resource-system/main.cpp url
+
+ \section1 Advanced Topics
+
+ \section2 Prefixes
+
+ A \c .qrc file can set a prefix to be added to each local file name, given
+ in a \c <file> element, to get the name by which the file shall be known
+ within the resource system.
+
+ Prefixes allow you to structure the resources, avoiding clashes between
+ resource files added through different \c .qrc files in different libraries
+ or plugins.
+
+ \note The \c /qt and \c /qt-project.org prefixes are reserved for documented
+ use cases in Qt. The \l{Using qt.conf}{qt.conf} file is for instance looked
+ up in \c{:/qt/etc/qt.conf} or \c{qrc:/qt/etc/qt.conf}.
+
+ \section2 Aliases
+
+ Sometimes it is convenient to make a resource file available under a
+ different path at runtime. \c .qrc files allow this by setting an
\c alias attribute:
\snippet code/doc_src_resources.qdoc 0
- The file is then accessible as \c :/cut-img.png from the
- application. It is also possible to specify a path prefix for all
- files in the \c .qrc file using the \c qresource tag's \c prefix
- attribute:
+ The file is from the application then only accessible as \c :/cut-img.png
+ or \c{qrc:/cut-img.png}.
+
+ \section2 Discarding the file contents
+
+ Sometimes you want to add a file node to the resource file system but
+ don't actually want to add the file contents. \c .qrc files allow this
+ by setting the \c empty attribute to \c{true}.
+
+ \snippet code/doc_src_resources.qdoc 4
- \snippet code/doc_src_resources.qdoc 1
+ The resulting file is then still accessible from the application, but
+ its contents are empty.
- In this case, the file is accessible as \c
- :/myresources/cut-img.png.
+ This is useful to strip QML source code from an application binary.
- Some resources need to change based on the user's locale,
- such as translation files or icons. This is done by adding a \c lang
- attribute to the \c qresource tag, specifying a suitable locale
- string. For example:
+ \note If you omit the QML source code from the binary, the QML engine has to
+ rely on the compilation units created by \l{qmlcachegen} or \l{qmlsc}.
+ Those are tied to the specific version of Qt they were built with. If you
+ change the version of Qt your application uses, they can't be loaded
+ anymore.
+
+ \section2 Language Selectors
+
+ Some resources need to change based on the user's locale, such as
+ translation files or icons. \l{Resource Collection Files} support this
+ through a \c lang attribute to the \c qresource tag, specifying a suitable
+ locale string. For example:
\snippet code/doc_src_resources.qdoc 2
- If the user's locale is French (i.e., QLocale::system().name() returns
- "fr_FR"), \c :/cut.jpg becomes a reference to the \c cut_fr.jpg
- image. For other locales, \c cut.jpg is used.
+ If the user's locale is French (i.e., QLocale::system().language() is
+ French), \c :/cut.jpg or \c qrc:/cut.jpg becomes a reference to the
+ \c cut_fr.jpg image. For other locales, \c cut.jpg is used.
- See the QLocale documentation for a description of the format to use
- for locale strings.
+ See the QLocale documentation for a description of the format to use for
+ locale strings.
See QFileSelector for an additional mechanism to select locale-specific
- resources, in addition to the ability to select OS-specific and other
- features.
+ resources.
+
+ \section2 Embedding Large Files
+
+ By default, \c rcc embeds the resource files into executables in the form
+ of C++ arrays. This can be problematic especially for large resources.
- \section2 External Binary Resources
+ If the compiler takes too long, or even fails because of memory overflow,
+ you can opt into a special mode where the resources are embedded as part of
+ a two-step process. The C++ compiler only reserves enough space in the
+ target executable or library for the resources. The actual embedding of the
+ resource file's content and metadata is then done after the compilation and
+ linking phase, through another rcc call.
- For an external binary resource to be created you must create the resource
- data (commonly given the \c .rcc extension) by passing the -binary switch to
- \l rcc. Once the binary resource is created you can register the resource
- with the QResource API.
+ For CMake, you need to use the \l{qt_add_big_resources} function.
+
+ \section2 External Resource Files
+
+ An alternative to embedding the resource files into the binary is to store
+ them in a separate \c .rcc file. \c rcc allows this with the \c -binary
+ option. Such a \c .rcc file must then be loaded at runtime with QResource.
For example, a set of resource data specified in a \c .qrc file can be
compiled in the following way:
@@ -120,46 +224,27 @@
\snippet code/doc_src_resources.cpp 4
- \section2 Compiled-In Resources
-
- For a resource to be compiled into the binary the \c .qrc file must be
- mentioned in the application's \c .pro file so that \c qmake knows
- about it. For example:
-
- \snippet resource-system/application.pro 0
+ If you use CMake, you can use the \l{qt_add_binary_resources} function
+ to schedule the \c rcc call above:
- \c qmake will produce make rules to generate a file called \c
- qrc_application.cpp that is linked into the application. This
- file contains all the data for the images and other resources as
- static C++ arrays of compressed binary data. The \c
- qrc_application.cpp file is automatically regenerated whenever
- the \c .qrc file changes or one of the files that it refers to
- changes. If you don't use \c .pro files, you can either invoke
- \c rcc manually or add build rules to your build system.
+ \snippet resource-system/CMakeLists.txt qt_add_binary_resources
- \image resources.png Building resources into an application
+ \section2 Resources in a Qt for Python application
- Currently, Qt always stores the data directly in the executable,
- even on Windows, \macos, and iOS, where the operating system provides
- native support for resources. This might change in a future Qt
- release.
-
- \section2 Resources in a Qt for Python application
-
- The resource collection file is converted to a Python module by using
- the resource compiler \l rcc:
+ The resource collection file is converted to a Python module by using the
+ resource compiler \l rcc:
\code
- rcc -g python application.qrc > application_rc.py
+ rcc -g python mainwindow.qrc > mainwindow_rc.py
\endcode
- The module needs to be imported in the application:
+ The module can then be imported in the application:
\code
- import application_rc.py
+ import mainwindow_rc.py
\endcode
- \section1 Compression
+ \section2 Compression
\c rcc attempts to compress the content to optimize disk space usage in the
final binaries. By default, it will perform a heuristic check to determine
@@ -176,7 +261,7 @@
The default value is "70", indicating that the compressed file must be 70%
smaller than the original (no more than 30% of the original file size).
- It is possible to turn off compression, if desired. This can be useful if
+ It is possible to turn off compression if desired. This can be useful if
your resources already contain a compressed format, such as \c .png files,
and you do not want to incur the CPU cost at build time to confirm that it
can't be compressed. Another reason is if disk usage is not a problem and
@@ -209,25 +294,25 @@
levels:
\list
- \li \c{best}: use the best algorithm among the ones below, at its highest
+ \li \c best: use the best algorithm among the ones below, at its highest
compression level, to achieve the most compression at the expense of
using a lot of CPU time during compilation. This value is useful in the
XML file to indicate a file should be most compressed, regardless of
which algorithms \c rcc supports.
- \li \c{zstd}: use the \l{https://zstd.net}{Zstandard} library to compress
+ \li \c zstd: use the \l{Zstandard Site}{Zstandard} library to compress
contents. Valid compression levels range from 1 to 19, 1 is least
compression (least CPU time) and 19 is the most compression (most CPU
- time). The default level is 14. A special value of 0 tells the \c{zstd}
+ time). The default level is 14. A special value of 0 tells the \c zstd
library to choose an implementation-defined default.
- \li \c{zlib}: use the \l{https://zlib.net}{zlib} library to compress
+ \li \c zlib: use the \l{https://zlib.net}{zlib} library to compress
contents. Valid compression levels range from 1 to 9, with 1 applying
the least compression (least CPU time) and 9 the most compression (most
CPU time). The special value 0 means "no compression" and should not be
used. The default is implementation-defined, but usually is level 6.
- \li \c{none}: no compression. This is the same as the \c{-no-compress}
+ \li \c none: no compression. This is the same as the \c -no-compress
option.
\endlist
@@ -236,67 +321,27 @@
that library will result in an error. The default compression algorithm is
\c zstd if it is enabled, \c zlib if not.
- \section1 Using Resources in the Application
-
- In the application, resource paths can be used in most places
- instead of ordinary file system paths. In particular, you can
- pass a resource path instead of a file name to the QIcon, QImage,
- or QPixmap constructor:
-
- \snippet resource-system/mainwindow.cpp 21
-
- See the \l{mainwindows/application}{Application} example for an
- actual application that uses Qt's resource system to store its
- icons.
-
- In memory, resources are represented by a tree of resource
- objects. The tree is automatically built at startup and used by
- QFile for resolving paths to resources. You can use a QDir initialized
- with ":/" to navigate through the resource tree from the root.
-
- Qt's resources support the concept of a search path list. If you then
- refer to a resource with \c : instead of \c :/ as the prefix, the
- resource will be looked up using the search path list. The search
- path list is empty at startup; call QDir::addSearchPath() to
- add paths to it.
+ \section2 Explicit Loading and Unloading of Embedded Resources
- \section1 Using Resources in a Library
+ Resources embedded in C++ executable or library code are automatically
+ registered to the Qt resource system in a constructor of an internal
+ global variable. Since the global variables are initialized before
+ main() runs, the resources are available when the program starts to
+ run.
- If you have resources in a library, you need to force initialization
- of your resources by calling \l Q_INIT_RESOURCE() with the base name
- of the \c .qrc file. For example:
+ When embedding resources in \e{static} libraries, the C++ linker might
+ remove the static variables that register the resources. If you
+ embed resources in a static library, you therefore need to explicitly
+ register your resources by calling \l Q_INIT_RESOURCE() with the base
+ name of the \c .qrc file.
+ For example:
\snippet code/doc_src_resources.cpp 5
- This ensures that the resources are linked into the final application
- binary in the case of static linking. You should put the initialization
- code close to where the resources are used in your library, so that
- clients of your library will only link in the resources if they use
- the feature of the library that depends on them.
+ You can also explicitly remove registered resources from the application,
+ for instance when unloading a plugin. Use \l Q_CLEANUP_RESOURCE() for this.
Note: As the resource initializers generated by rcc are declared in the
- global namespace, your calls to \l Q_INIT_RESOURCE() also need to be done
- outside of any namespace.
-
- If the library includes resources that are not used internally, but
- instead exposed to clients of the library, the initialization needs
- to happen in the application code. For example:
-
- \snippet code/doc_src_resources.cpp 6
-
- As before, this ensures that the resources are linked into the final
- application binary in the case of static linking, but also triggers
- loading of the library in the case of dynamic linking, such as plugins.
-
- Similarly, if you must unload a set of resources explicitly
- (because a plugin is being unloaded or the resources are not valid
- any longer), you can force removal of your resources by calling
- \l Q_CLEANUP_RESOURCE() with the same base name as above.
-
- \note The use of \l Q_INIT_RESOURCE() and \l Q_CLEANUP_RESOURCE() is
- not necessary in the following cases:
- \list
- \li When the resource is built as part of the application.
- \li When the resource is built with CMake as part of a static library.
- \endlist
+ global namespace, your calls to \l Q_INIT_RESOURCE() and
+ \l Q_CLEANUP_RESOURCE() need to be done outside any namespace.
*/
diff --git a/src/corelib/doc/src/statemachine.qdoc b/src/corelib/doc/src/statemachine.qdoc
deleted file mode 100644
index 881a0785c6..0000000000
--- a/src/corelib/doc/src/statemachine.qdoc
+++ /dev/null
@@ -1,577 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \group statemachine
- \brief How to create and execute state graphs.
- \title State Machine Classes
-
- These \l{Qt Core} classes are part of the \l{The State Machine Framework}{
- State Machine Framework}.
-
-*/
-
-/*!
- \page statemachine-api.html
- \title The State Machine Framework
- \brief An overview of the State Machine framework for constructing and executing state graphs.
-
- \ingroup frameworks-technologies
-
- \tableofcontents
-
- The State Machine framework provides classes for creating and executing
- state graphs. The concepts and notation are based on those from Harel's
- \l{http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf}{Statecharts: A visual formalism for complex systems}, which
- is also the basis of UML state diagrams. The semantics of state machine
- execution are based on \l{State Chart XML: State Machine Notation for
- Control Abstraction}{State Chart XML (SCXML)}.
-
- Statecharts provide a graphical way of modeling how a system reacts to
- stimuli. This is done by defining the possible \e states that the system can
- be in, and how the system can move from one state to another (\e transitions
- between states). A key characteristic of event-driven systems (such as Qt
- applications) is that behavior often depends not only on the last or current
- event, but also the events that preceded it. With statecharts, this
- information is easy to express.
-
- The State Machine framework provides an API and execution model that can be
- used to effectively embed the elements and semantics of statecharts in Qt
- applications. The framework integrates tightly with Qt's meta-object system;
- for example, transitions between states can be triggered by signals, and
- states can be configured to set properties and invoke methods on {QObject}s.
- Qt's event system is used to drive the state machines.
-
- The state graph in the State Machine framework is hierarchical. States can be nested inside of
- other states, and the current configuration of the state machine consists of the set of states
- which are currently active. All the states in a valid configuration of the state machine will
- have a common ancestor.
-
- \sa {The Declarative State Machine Framework}
-
- \section1 Classes in the State Machine Framework
-
- These classes are provided by qt for creating event-driven state machines.
-
- \annotatedlist statemachine
-
- \section1 A Simple State Machine
-
- To demonstrate the core functionality of the State Machine API, let's look
- at a small example: A state machine with three states, \c s1, \c s2 and \c
- s3. The state machine is controlled by a single QPushButton; when the button
- is clicked, the machine transitions to another state. Initially, the state
- machine is in state \c s1. The statechart for this machine is as follows:
-
- \image statemachine-button.png
- \omit
- \caption This is a caption
- \endomit
-
- The following snippet shows the code needed to create such a state machine.
- First, we create the state machine and states:
-
- \snippet statemachine/main.cpp 0
-
- Then, we create the transitions by using the QState::addTransition()
- function:
-
- \snippet statemachine/main.cpp 1
-
- Next, we add the states to the machine and set the machine's initial state:
-
- \snippet statemachine/main.cpp 2
-
- Finally, we start the state machine:
-
- \snippet statemachine/main.cpp 3
-
- The state machine executes asynchronously, i.e. it becomes part of your
- application's event loop.
-
- \section1 Doing Useful Work on State Entry and Exit
-
- The above state machine merely transitions from one state to another, it
- doesn't perform any operations. The QState::assignProperty() function can be
- used to have a state set a property of a QObject when the state is
- entered. In the following snippet, the value that should be assigned to a
- QLabel's text property is specified for each state:
-
- \snippet statemachine/main.cpp 4
-
- When any of the states is entered, the label's text will be changed
- accordingly.
-
- The QState::entered() signal is emitted when the state is entered, and the
- QState::exited() signal is emitted when the state is exited. In the
- following snippet, the button's \l {QPushButton::}{showMaximized()} slot
- will be called when state \c s3 is entered, and the button's \l {QPushButton::}{showMinimized()}
- slot will be called when \c s3 is exited:
-
- \snippet statemachine/main.cpp 5
-
- Custom states can reimplement QAbstractState::onEntry() and
- QAbstractState::onExit().
-
- \section1 State Machines That Finish
-
- The state machine defined in the previous section never finishes. In order
- for a state machine to be able to finish, it needs to have a top-level \e
- final state (QFinalState object). When the state machine enters a top-level
- final state, the machine will emit the QStateMachine::finished() signal and
- halt.
-
- All you need to do to introduce a final state in the graph is create a
- QFinalState object and use it as the target of one or more transitions.
-
- \section1 Sharing Transitions By Grouping States
-
- Assume we wanted the user to be able to quit the application at any time by
- clicking a Quit button. In order to achieve this, we need to create a final
- state and make it the target of a transition associated with the Quit
- button's \l{QPushButton::}{clicked()} signal. We could add a transition from each of \c s1, \c
- s2 and \c s3; however, this seems redundant, and one would also have to
- remember to add such a transition from every new state that is added in the
- future.
-
- We can achieve the same behavior (namely that clicking the Quit button quits
- the state machine, regardless of which state the state machine is in) by
- grouping states \c s1, \c s2 and \c s3. This is done by creating a new
- top-level state and making the three original states children of the new
- state. The following diagram shows the new state machine.
-
- \image statemachine-button-nested.png
- \omit
- \caption This is a caption
- \endomit
-
- The three original states have been renamed \c s11, \c s12 and \c s13 to
- reflect that they are now children of the new top-level state, \c s1. Child
- states implicitly inherit the transitions of their parent state. This means
- it is now sufficient to add a single transition from \c s1 to the final
- state \c s2. New states added to \c s1 will also automatically inherit this
- transition.
-
- All that's needed to group states is to specify the proper parent when the
- state is created. You also need to specify which of the child states is the
- initial one (i.e. which child state the state machine should enter when the
- parent state is the target of a transition).
-
- \snippet statemachine/main2.cpp 0
-
- \snippet statemachine/main2.cpp 1
-
- In this case we want the application to quit when the state machine is
- finished, so the machine's \l {QStateMachine::}{finished()} signal is connected to the
- application's \l {QCoreApplication::}{quit()} slot.
-
- A child state can override an inherited transition. For example, the
- following code adds a transition that effectively causes the Quit button to
- be ignored when the state machine is in state \c s12.
-
- \snippet statemachine/main2.cpp 2
-
- A transition can have any state as its target, i.e. the target state does
- not have to be on the same level in the state hierarchy as the source state.
-
- \section1 Using History States to Save and Restore the Current State
-
- Imagine that we wanted to add an "interrupt" mechanism to the example
- discussed in the previous section; the user should be able to click a button
- to have the state machine perform some non-related task, after which the
- state machine should resume whatever it was doing before (i.e. return to the
- old state, which is one of \c s11, \c s12 and \c s13 in this case).
-
- Such behavior can easily be modeled using \e{history states}. A history
- state (QHistoryState object) is a pseudo-state that represents the child
- state that the parent state was in the last time the parent state was
- exited.
-
- A history state is created as a child of the state for which we wish to
- record the current child state; when the state machine detects the presence
- of such a state at runtime, it automatically records the current (real)
- child state when the parent state is exited. A transition to the history
- state is in fact a transition to the child state that the state machine had
- previously saved; the state machine automatically "forwards" the transition
- to the real child state.
-
- The following diagram shows the state machine after the interrupt mechanism
- has been added.
-
- \image statemachine-button-history.png
- \omit
- \caption This is a caption
- \endomit
-
- The following code shows how it can be implemented; in this example we
- simply display a message box when \c s3 is entered, then immediately return
- to the previous child state of \c s1 via the history state.
-
- \snippet statemachine/main2.cpp 3
-
- \section1 Using Parallel States to Avoid a Combinatorial Explosion of States
-
- Assume that you wanted to model a set of mutually exclusive properties of a
- car in a single state machine. Let's say the properties we are interested in
- are Clean vs Dirty, and Moving vs Not moving. It would take four mutually
- exclusive states and eight transitions to be able to represent and freely
- move between all possible combinations.
-
- \image statemachine-nonparallel.png
- \omit
- \caption This is a caption
- \endomit
-
- If we added a third property (say, Red vs Blue), the total number of states
- would double, to eight; and if we added a fourth property (say, Enclosed vs
- Convertible), the total number of states would double again, to 16.
-
- Using parallel states, the total number of states and transitions grows
- linearly as we add more properties, instead of exponentially. Furthermore,
- states can be added to or removed from the parallel state without affecting
- any of their sibling states.
-
- \image statemachine-parallel.png
- \omit
- \caption This is a caption
- \endomit
-
- To create a parallel state group, pass QState::ParallelStates to the QState
- constructor.
-
- \snippet statemachine/main3.cpp 0
-
- When a parallel state group is entered, all its child states will be
- simultaneously entered. Transitions within the individual child states
- operate normally. However, any of the child states may take a transition which exits the parent
- state. When this happens, the parent state and all of its child states are exited.
-
- The parallelism in the State Machine framework follows an interleaved semantics. All parallel
- operations will be executed in a single, atomic step of the event processing, so no event can
- interrupt the parallel operations. However, events will still be processed sequentially, since
- the machine itself is single threaded. As an example: Consider the situation where there are two
- transitions that exit the same parallel state group, and their conditions become true
- simultaneously. In this case, the event that is processed last of the two will not have any
- effect, since the first event will already have caused the machine to exit from the parallel
- state.
-
- \section1 Detecting that a Composite State has Finished
-
- A child state can be final (a QFinalState object); when a final child state
- is entered, the parent state emits the QState::finished() signal. The
- following diagram shows a composite state \c s1 which does some processing
- before entering a final state:
-
- \image statemachine-finished.png
- \omit
- \caption This is a caption
- \endomit
-
- When \c s1 's final state is entered, \c s1 will automatically emit
- \l {QState::}{finished()}. We use a signal transition to cause this event to trigger a
- state change:
-
- \snippet statemachine/main3.cpp 1
-
- Using final states in composite states is useful when you want to hide the
- internal details of a composite state; i.e. the only thing the outside world
- should be able to do is enter the state, and get a notification when the
- state has completed its work. This is a very powerful abstraction and
- encapsulation mechanism when building complex (deeply nested) state
- machines. (In the above example, you could of course create a transition
- directly from \c s1 's \c done state rather than relying on \c s1 's
- \l {QState::}{finished()} signal, but with the consequence that implementation details of
- \c s1 are exposed and depended on).
-
- For parallel state groups, the QState::finished() signal is emitted when \e
- all the child states have entered final states.
-
- \section1 Targetless Transitions
-
- A transition need not have a target state. A transition without a target can
- be triggered the same way as any other transition; the difference is that
- when a targetless transition is triggered, it doesn't cause any state
- changes. This allows you to react to a signal or event when your machine is
- in a certain state, without having to leave that state. Example:
-
- \code
- QStateMachine machine;
- QState *s1 = new QState(&machine);
-
- QPushButton button;
- QSignalTransition *trans = new QSignalTransition(&button, &QPushButton::clicked);
- s1->addTransition(trans);
-
- QMessageBox msgBox;
- msgBox.setText("The button was clicked; carry on.");
- QObject::connect(trans, QSignalTransition::triggered, &msgBox, &QMessageBox::exec);
-
- machine.setInitialState(s1);
- \endcode
-
- The message box will be displayed each time the button is clicked, but the
- state machine will remain in its current state (s1). If the target state
- were explicitly set to s1, however, s1 would be exited and re-entered each
- time (e.g. the QAbstractState::entered() and QAbstractState::exited()
- signals would be emitted).
-
- \section1 Events, Transitions and Guards
-
- A QStateMachine runs its own event loop. For signal transitions
- (QSignalTransition objects), QStateMachine automatically posts a
- QStateMachine::SignalEvent to itself when it intercepts the corresponding
- signal; similarly, for QObject event transitions (QEventTransition objects)
- a QStateMachine::WrappedEvent is posted.
-
- You can post your own events to the state machine using
- QStateMachine::postEvent().
-
- When posting a custom event to the state machine, you typically also have
- one or more custom transitions that can be triggered from events of that
- type. To create such a transition, you subclass QAbstractTransition and
- reimplement QAbstractTransition::eventTest(), where you check if an event
- matches your event type (and optionally other criteria, e.g. attributes of
- the event object).
-
- Here we define our own custom event type, \c StringEvent, for posting
- strings to the state machine:
-
- \snippet statemachine/main4.cpp 0
-
- Next, we define a transition that only triggers when the event's string
- matches a particular string (a \e guarded transition):
-
- \snippet statemachine/main4.cpp 1
-
- In the \l {QAbstractTransition::}{eventTest()} reimplementation, we first check if the event type is the
- desired one; if so, we cast the event to a \c StringEvent and perform the
- string comparison.
-
- The following is a statechart that uses the custom event and transition:
-
- \image statemachine-customevents.png
- \omit
- \caption This is a caption
- \endomit
-
- Here's what the implementation of the statechart looks like:
-
- \snippet statemachine/main4.cpp 2
-
- Once the machine is started, we can post events to it.
-
- \snippet statemachine/main4.cpp 3
-
- An event that is not handled by any relevant transition will be silently
- consumed by the state machine. It can be useful to group states and provide
- a default handling of such events; for example, as illustrated in the
- following statechart:
-
- \image statemachine-customevents2.png
- \omit
- \caption This is a caption
- \endomit
-
- For deeply nested statecharts, you can add such "fallback" transitions at
- the level of granularity that's most appropriate.
-
- \section1 Using Restore Policy To Automatically Restore Properties
-
- In some state machines it can be useful to focus the attention on assigning properties in states,
- not on restoring them when the state is no longer active. If you know that a property should
- always be restored to its initial value when the machine enters a state that does not explicitly
- give the property a value, you can set the global restore policy to
- QStateMachine::RestoreProperties.
-
- \code
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
- \endcode
-
- When this restore policy is set, the machine will automatically restore all properties. If it
- enters a state where a given property is not set, it will first search the hierarchy of ancestors
- to see if the property is defined there. If it is, the property will be restored to the value
- defined by the closest ancestor. If not, it will be restored to its initial value (i.e. the
- value of the property before any property assignments in states were executed.)
-
- Take the following code:
-
- \snippet statemachine/main5.cpp 0
-
- Lets say the property \c fooBar is 0.0 when the machine starts. When the machine is in state
- \c s1, the property will be 1.0, since the state explicitly assigns this value to it. When the
- machine is in state \c s2, no value is explicitly defined for the property, so it will implicitly
- be restored to 0.0.
-
- If we are using nested states, the parent defines a value for the property which is inherited by
- all descendants that do not explicitly assign a value to the property.
-
- \snippet statemachine/main5.cpp 2
-
- Here \c s1 has two children: \c s2 and \c s3. When \c s2 is entered, the property \c fooBar
- will have the value 2.0, since this is explicitly defined for the state. When the machine is in
- state \c s3, no value is defined for the state, but \c s1 defines the property to be 1.0, so this
- is the value that will be assigned to \c fooBar.
-
- \section1 Animating Property Assignments
-
- The State Machine API connects with the Animation API in Qt to allow automatically animating
- properties as they are assigned in states.
-
- Say we have the following code:
-
- \snippet statemachine/main5.cpp 3
-
- Here we define two states of a user interface. In \c s1 the \c button is small, and in \c s2
- it is bigger. If we click the button to transition from \c s1 to \c s2, the geometry of the button
- will be set immediately when a given state has been entered. If we want the transition to be
- smooth, however, all we need to do is make a QPropertyAnimation and add this to the transition
- object.
-
- \snippet statemachine/main5.cpp 4
-
- Adding an animation for the property in question means that the property assignment will no
- longer take immediate effect when the state has been entered. Instead, the animation will start
- playing when the state has been entered and smoothly animate the property assignment. Since we
- do not set the start value or end value of the animation, these will be set implicitly. The
- start value of the animation will be the property's current value when the animation starts, and
- the end value will be set based on the property assignments defined for the state.
-
- If the global restore policy of the state machine is set to QStateMachine::RestoreProperties,
- it is possible to also add animations for the property restorations.
-
- \section1 Detecting That All Properties Have Been Set In A State
-
- When animations are used to assign properties, a state no longer defines the exact values that a
- property will have when the machine is in the given state. While the animation is running, the
- property can potentially have any value, depending on the animation.
-
- In some cases, it can be useful to be able to detect when the property has actually been assigned
- the value defined by a state.
-
- Say we have the following code:
-
- \snippet statemachine/main5.cpp 5
-
- When \c button is clicked, the machine will transition into state \c s2, which will set the
- geometry of the button, and then pop up a message box to alert the user that the geometry has
- been changed.
-
- In the normal case, where animations are not used, this will operate as expected. However, if
- an animation for the \c geometry of \c button is set on the transition between \c s1 and \c s2,
- the animation will be started when \c s2 is entered, but the \c geometry property will not
- actually reach its defined value before the animation is finished running. In this case, the
- message box will pop up before the geometry of the button has actually been set.
-
- To ensure that the message box does not pop up until the geometry actually reaches its final
- value, we can use the state's \l {QState::}{propertiesAssigned()} signal. The \l {QState::}{propertiesAssigned()} signal will be
- emitted when the property is assigned its final value, whether this is done immediately or
- after the animation has finished playing.
-
- \snippet statemachine/main5.cpp 6
-
- In this example, when \c button is clicked, the machine will enter \c s2. It will remain in state
- \c s2 until the \c geometry property has been set to \c QRect(0, 0, 50, 50). Then it will
- transition into \c s3. When \c s3 is entered, the message box will pop up. If the transition into
- \c s2 has an animation for the \c geometry property, then the machine will stay in \c s2 until the
- animation has finished playing. If there is no such animation, it will simply set the property and
- immediately enter state \c s3.
-
- Either way, when the machine is in state \c s3, you are guaranteed that the property \c geometry
- has been assigned the defined value.
-
- If the global restore policy is set to QStateMachine::RestoreProperties, the state will not emit
- the \l {QState::}{propertiesAssigned()} signal until these have been executed as well.
-
- \section1 What Happens If A State Is Exited Before The Animation Has Finished
-
- If a state has property assignments, and the transition into the state has animations for the
- properties, the state can potentially be exited before the properties have been assigned to the
- values defines by the state. This is true in particular when there are transitions out from the
- state that do not depend on the \l {QState::}{propertiesAssigned()} signal, as described in the previous section.
-
- The State Machine API guarantees that a property assigned by the state machine either:
- \list
- \li Has a value explicitly assigned to the property.
- \li Is currently being animated into a value explicitly assigned to the property.
- \endlist
-
- When a state is exited prior to the animation finishing, the behavior of the state machine depends
- on the target state of the transition. If the target state explicitly assigns a value to the
- property, no additional action will be taken. The property will be assigned the value defined by
- the target state.
-
- If the target state does not assign any value to the property, there are two
- options: By default, the property will be assigned the value defined by the state it is leaving
- (the value it would have been assigned if the animation had been permitted to finish playing). If
- a global restore policy is set, however, this will take precedence, and the property will be
- restored as usual.
-
- \section1 Default Animations
-
- As described earlier, you can add animations to transitions to make sure property assignments
- in the target state are animated. If you want a specific animation to be used for a given property
- regardless of which transition is taken, you can add it as a default animation to the state
- machine. This is in particular useful when the properties assigned (or restored) by specific
- states is not known when the machine is constructed.
-
- \code
- QState *s1 = new QState();
- QState *s2 = new QState();
-
- s2->assignProperty(object, "fooBar", 2.0);
- s1->addTransition(s2);
-
- QStateMachine machine;
- machine.setInitialState(s1);
- machine.addDefaultAnimation(new QPropertyAnimation(object, "fooBar"));
- \endcode
-
- When the machine is in state \c s2, the machine will play the default animation for the
- property \c fooBar since this property is assigned by \c s2.
-
- Note that animations explicitly set on transitions will take precedence over any default
- animation for the given property.
-
- \section1 Nesting State Machines
-
- QStateMachine is a subclass of QState. This allows for a state machine to be a child state of
- another machine. QStateMachine reimplements QState::onEntry() and calls QStateMachine::start(),
- so that when the child state machine is entered, it will automatically start running.
-
- The parent state machine treats the child machine as an \e atomic state in the state machine
- algorithm. The child state machine is self-contained; it maintains its own event queue and
- configuration. In particular, note that the \l{QStateMachine::}{configuration()}
- of the child machine is not part of the parent machine's configuration (only the child machine
- itself is).
-
- States of the child state machine cannot be specified as targets of transitions in the parent
- state machine; only the child state machine itself can. Conversely, states of the parent state
- machine cannot be specified as targets of transitions in the child state machine. The child
- state machine's \l{QState::}{finished}() signal can be used to trigger a transition
- in the parent machine.
-*/
diff --git a/src/corelib/doc/src/timers.qdoc b/src/corelib/doc/src/timers.qdoc
index 1fa62a6afb..dc205a47b9 100644
--- a/src/corelib/doc/src/timers.qdoc
+++ b/src/corelib/doc/src/timers.qdoc
@@ -1,46 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page timers.html
\title Timers
\brief How to use Qt timers in your application.
- \ingroup best-practices
+ \ingroup how-to
QObject, the base class of all Qt objects, provides the basic
timer support in Qt. With QObject::startTimer(), you start a
timer with an interval in milliseconds as argument. The function
- returns a unique integer timer ID. The timer will now fire at
+ returns a unique integral timer ID. The timer will then fire at
regular intervals until you explicitly call QObject::killTimer()
- with the timer ID.
+ with that timer ID.
For this mechanism to work, the application must run in an event
- loop. You start an event loop with QApplication::exec(). When a
+ loop. You cat start an event loop with QApplication::exec(). When a
timer fires, the application sends a QTimerEvent, and the flow of
control leaves the event loop until the timer event is processed.
This implies that a timer cannot fire while your application is
@@ -55,69 +31,65 @@
stop all timers in the object's thread; it is not possible to
start timers for objects in another thread.
- The upper limit for the interval value is determined by the number
- of milliseconds that can be specified in a signed integer
- (in practice, this is a period of just over 24 days). The accuracy
- depends on the underlying operating system. Windows 2000 has 15
- millisecond accuracy; other systems that we have tested can handle
- 1 millisecond intervals.
-
- The main API for the timer functionality is QTimer. That class
- provides regular timers that emit a signal when the timer fires, and
- inherits QObject so that it fits well into the ownership structure
- of most GUI programs. The normal way of using it is like this:
-
- \snippet timers/timers.cpp 0
- \snippet timers/timers.cpp 1
- \snippet timers/timers.cpp 2
-
- The QTimer object is made into a child of this widget so that,
- when this widget is deleted, the timer is deleted too.
- Next, its \l{QTimer::}{timeout()} signal is connected to the slot
- that will do the work, it is started with a value of 1000
- milliseconds, indicating that it will time out every second.
-
- QTimer also provides a static function for single-shot timers.
+ The main API for the timer functionality was \l QTimer. QTimer stores
+ the interval in a signed integer, which limits the maximum interval it
+ supports to the number of milliseconds that can fit in a signed integer
+ (in practice, this is a period of around 24 days).
+
+ Qt 6.8 introduced the \l QChronoTimer class to replace QTimer. QChronoTimer
+ stores the interval as \c std::chrono::nanoseconds, which means that
+ the maximum interval it supports is around 292 years. This mitigates
+ the chances of integer overflow that QTimer had if the interval was more
+ than \c{std::numeric_limits<int>::max()}.
+
+ The accuracy of the timers depends on the underlying operating system.
+ Windows 2000 has 15ms accuracy; other systems that we have tested can
+ handle 1ms intervals.
+
+ QChronoTimer provides regular timers that emit a signal when the timer
+ fires, and inherits from QObject so that it fits well into the ownership
+ structure of most Qt programs. The normal way of using it is like this:
+
+ \snippet timers/timers.cpp timer-interval-in-ctor
+ \snippet timers/timers.cpp timer-setinterval
+
+ The QChronoTimer object is made into a child of the \c this object so
+ that, when \c this is destroyed, the timer is destroyed too. Next, the
+ \l{QChronoTimer::}{timeout()} signal is connected to the slot that will
+ do the work, the timer interval can be either passed to the constructor,
+ or set later on with setInterval().
+
+ QChronoTimer also provides static functions for single-shot timers.
For example:
- \snippet timers/timers.cpp 3
+ \snippet timers/timers.cpp qchronotimer-singleshot
- 200 milliseconds (0.2 seconds) after this line of code is
- executed, the \c updateCaption() slot will be called.
+ 200ms after this line of code is executed, the \c updateCaption() slot
+ will be called.
- For QTimer to work, you must have an event loop in your
- application; that is, you must call QCoreApplication::exec()
- somewhere. Timer events will be delivered only while the event
- loop is running.
+ For QChronoTimer to work, you must have an event loop in your application;
+ that is, you must call QCoreApplication::exec() somewhere. Timer events
+ will be delivered only while the event loop is running.
- In multithreaded applications, you can use QTimer in any thread
- that has an event loop. To start an event loop from a non-GUI
- thread, use QThread::exec(). Qt uses the timer's
- \l{QObject::thread()}{thread affinity} to determine which thread
- will emit the \l{QTimer::}{timeout()} signal. Because of this, you
- must start and stop the timer in its thread; it is not possible to
- start a timer from another thread.
-
- The \l{widgets/analogclock}{Analog Clock} example shows how to use
- QTimer to redraw a widget at regular intervals. From \c{AnalogClock}'s
- implementation:
-
- \snippet timers/analogclock.cpp 0
- \snippet timers/analogclock.cpp 2
- \snippet timers/analogclock.cpp 3
- \snippet timers/analogclock.cpp 4
- \snippet timers/analogclock.cpp 5
- \snippet timers/analogclock.cpp 6
- \dots
- \snippet timers/analogclock.cpp 7
-
- Every second, QTimer will call the QWidget::update() slot to
+ In multithreaded applications, you can use QChronoTimer in any thread
+ that has an event loop. To start an event loop from a non-GUI thread, use
+ QThread::exec(). Qt uses the timer's \l{QObject::thread()}{thread affinity}
+ to determine which thread will emit the \l{QChronoTimer::}{timeout()}
+ signal. Because of this, you must start and stop the timer in its thread;
+ it is not possible to start a timer from another thread.
+
+ The \l{widgets/analogclock}{Analog Clock} example shows how to
+ use QChronoTimer to redraw a widget at regular intervals. From
+ \c{AnalogClock}'s implementation:
+
+ \snippet timers/analogclock.cpp analogclock-qchronotimer
+
+ Every second, QChronoTimer will call the QWidget::update() slot to
refresh the clock's display.
If you already have a QObject subclass and want an easy
optimization, you can use QBasicTimer instead of QTimer. With
QBasicTimer, you must reimplement
\l{QObject::timerEvent()}{timerEvent()} in your QObject subclass
- and handle the timeout there. The \l{widgets/wiggly}{Wiggly}
- example shows how to use QBasicTimer.
+ and handle the timeout there.
*/
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
index b758b2326c..6a1e110a73 100644
--- a/src/corelib/global/archdetect.cpp
+++ b/src/corelib/global/archdetect.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qprocessordetection.h"
@@ -51,14 +15,24 @@
# define ARCH_PROCESSOR "avr32"
#elif defined(Q_PROCESSOR_BLACKFIN)
# define ARCH_PROCESSOR "bfin"
+#elif defined(Q_PROCESSOR_WASM_64)
+# define ARCH_PROCESSOR "wasm64"
#elif defined(Q_PROCESSOR_WASM)
# define ARCH_PROCESSOR "wasm"
+#elif defined(Q_PROCESSOR_HPPA)
+# define ARCH_PROCESSOR "hppa"
#elif defined(Q_PROCESSOR_X86_32)
# define ARCH_PROCESSOR "i386"
#elif defined(Q_PROCESSOR_X86_64)
# define ARCH_PROCESSOR "x86_64"
#elif defined(Q_PROCESSOR_IA64)
# define ARCH_PROCESSOR "ia64"
+#elif defined(Q_PROCESSOR_LOONGARCH_32)
+# define ARCH_PROCESSOR "loongarch32"
+#elif defined(Q_PROCESSOR_LOONGARCH_64)
+# define ARCH_PROCESSOR "loongarch64"
+#elif defined(Q_PROCESSOR_M68K)
+# define ARCH_PROCESSOR "m68k"
#elif defined(Q_PROCESSOR_MIPS_64)
# define ARCH_PROCESSOR "mips64"
#elif defined(Q_PROCESSOR_MIPS)
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
deleted file mode 100644
index 6ba39d41bd..0000000000
--- a/src/corelib/global/global.pri
+++ /dev/null
@@ -1,133 +0,0 @@
-# Qt kernel library base module
-
-HEADERS += \
- global/qglobal.h \
- global/qoperatingsystemversion.h \
- global/qoperatingsystemversion_p.h \
- global/qsystemdetection.h \
- global/qcompilerdetection.h \
- global/qprocessordetection.h \
- global/qmemory_p.h \
- global/qnamespace.h \
- global/qendian.h \
- global/qendian_p.h \
- global/qnumeric_p.h \
- global/qnumeric.h \
- global/qfloat16.h \
- global/qglobalstatic.h \
- global/qlibraryinfo.h \
- global/qlogging.h \
- global/qtypeinfo.h \
- global/qsysinfo.h \
- global/qisenum.h \
- global/qsimd.h \
- global/qsimd_p.h \
- global/qtypetraits.h \
- global/qflags.h \
- global/qrandom.h \
- global/qrandom_p.h \
- global/qhooks_p.h \
- global/qversiontagging.h
-
-SOURCES += \
- global/archdetect.cpp \
- global/qendian.cpp \
- global/qglobal.cpp \
- global/qlibraryinfo.cpp \
- global/qmalloc.cpp \
- global/qnumeric.cpp \
- global/qfloat16.cpp \
- global/qoperatingsystemversion.cpp \
- global/qlogging.cpp \
- global/qrandom.cpp \
- global/qsimd.cpp \
- global/qhooks.cpp
-
-# To get listed in IDEs
-false: SOURCES += \
- global/qfloat16tables.cpp
-
-# Only add global/qfloat16_f16c.c if qfloat16.cpp can't #include it.
-# Any compiler: if it is already generating F16C code, let qfloat16.cpp do it
-# Clang: ICE if not generating F16C code, so use qfloat16_f16c.c
-# ICC: miscompiles if not generating F16C code, so use qfloat16_f16c.c
-# GCC: if it can use F16C intrinsics, let qfloat16.cpp do it
-# MSVC: if it is already generating AVX code, let qfloat16.cpp do it
-# MSVC: otherwise, it generates poorly-performing code, so use qfloat16_f16c.c
-contains(QT_CPU_FEATURES.$$QT_ARCH, f16c): \
- f16c_cxx = true
-else: clang|intel_icl|intel_icc: \
- f16c_cxx = false
-else: gcc:f16c:x86SimdAlways: \
- f16c_cxx = true
-else: msvc:contains(QT_CPU_FEATURES.$$QT_ARCH, avx): \
- f16c_cxx = true
-else: \
- f16c_cxx = false
-$$f16c_cxx: DEFINES += QFLOAT16_INCLUDE_FAST
-else: F16C_SOURCES += global/qfloat16_f16c.c
-unset(f16c_cxx)
-
-VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
-
-darwin: SOURCES += global/qoperatingsystemversion_darwin.mm
-win32 {
- SOURCES += global/qoperatingsystemversion_win.cpp
- HEADERS += global/qoperatingsystemversion_win_p.h
-}
-
-# qlibraryinfo.cpp includes qconfig.cpp
-INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
-
-# Only used on platforms with CONFIG += precompile_header
-PRECOMPILED_HEADER = global/qt_pch.h
-
-# qlogging.cpp uses backtrace(3), which is in a separate library on the BSDs.
-LIBS_PRIVATE += $$QMAKE_LIBS_EXECINFO
-
-if(linux*|hurd*):!cross_compile:!static:!*-armcc* {
- QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate
- prog=$$quote(if (/program interpreter: (.*)]/) { print $1; })
- DEFINES += ELF_INTERPRETER=\\\"$$system(LC_ALL=C readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"
-}
-
-linux:!static {
- precompile_header {
- # we'll get an error if we just use SOURCES +=
- no_pch_assembler.commands = $$QMAKE_CC -c $(CFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
- no_pch_assembler.dependency_type = TYPE_C
- no_pch_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
- no_pch_assembler.input = NO_PCH_ASM
- no_pch_assembler.name = compiling[no_pch] ${QMAKE_FILE_IN}
- silent: no_pch_assembler.commands = @echo compiling[no_pch] ${QMAKE_FILE_IN} && $$no_pch_assembler.commands
- QMAKE_EXTRA_COMPILERS += no_pch_assembler
- NO_PCH_ASM += global/minimum-linux.S
- } else {
- SOURCES += global/minimum-linux.S
- }
- HEADERS += global/minimum-linux_p.h
-}
-
-qtConfig(slog2): \
- LIBS_PRIVATE += -lslog2
-
-qtConfig(journald): \
- QMAKE_USE_PRIVATE += journald
-
-gcc:ltcg {
- versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH)
-
- # Disable LTO, as the symbols disappear somehow under GCC
- versiontagging_compiler.commands += -fno-lto
-
- versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
- versiontagging_compiler.dependency_type = TYPE_C
- versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
- versiontagging_compiler.input = VERSIONTAGGING_SOURCES
- versiontagging_compiler.variable_out = OBJECTS
- versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN}
- silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands
- QMAKE_EXTRA_COMPILERS += versiontagging_compiler
-} else {
- SOURCES += $$VERSIONTAGGING_SOURCES
-}
diff --git a/src/corelib/global/minimum-linux.S b/src/corelib/global/minimum-linux.S
deleted file mode 100644
index e324379efc..0000000000
--- a/src/corelib/global/minimum-linux.S
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "minimum-linux_p.h"
-
-/* Copied from #include <elf.h>:
- */
-#define ELF_NOTE_GNU "GNU"
-#define NT_GNU_ABI_TAG 1
-#define ELF_NOTE_OS_LINUX 0
-
-#ifdef __arm__
-# define progbits %progbits
-# define note %note
-#else
-# define progbits @progbits
-# define note @note
-#endif
-
-/* Add information for the ELF dynamic linker what the minimum Linux version
- * required for Qt is.
- *
- * The .note.ABI-tag note section is defined at
- * https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/noteabitag.html
- */
-
- .section ".note.GNU-stack", "", progbits
- .section ".note.ABI-tag", "a", note
- .balign 4 /* we have 32-bit data */
-
-/* * For the format of the note section's contents, see Elf32_Nhdr / Elf64_Nhdr */
- .long .Lnameend-.Lname /* n_namesz */
- .long 16 /* n_descsz(16 bytes, normative) */
- .long NT_GNU_ABI_TAG /* n_type */
-
-.Lname:
- .asciz ELF_NOTE_GNU
-.Lnameend:
-
-/* Operating systems: */
- .long ELF_NOTE_OS_LINUX
-
- .long MINLINUX_MAJOR
- .long MINLINUX_MINOR
- .long MINLINUX_PATCH
diff --git a/src/corelib/global/minimum-linux_p.h b/src/corelib/global/minimum-linux_p.h
index 5112015663..d52df474fb 100644
--- a/src/corelib/global/minimum-linux_p.h
+++ b/src/corelib/global/minimum-linux_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef MINIMUMLINUX_P_H
#define MINIMUMLINUX_P_H
@@ -58,6 +22,7 @@
//
#include "private/qglobal_p.h"
+#include <sys/stat.h>
QT_BEGIN_NAMESPACE
@@ -71,36 +36,37 @@ QT_BEGIN_NAMESPACE
* - FUTEX_PRIVATE_FLAG 2.6.22
* - O_CLOEXEC 2.6.23
* - eventfd 2.6.23
+ * - FUTEX_WAIT_BITSET 2.6.25
* - pipe2 & dup3 2.6.27
* - accept4 2.6.28
* - renameat2 3.16 QT_CONFIG(renameat2)
* - getrandom 3.17 QT_CONFIG(getentropy)
- * - statx 4.11 QT_CONFIG(statx)
+ * - statx 4.11 STATX_BASIC_STATS
*/
-#if QT_CONFIG(statx) && !QT_CONFIG(glibc)
+#if defined(__GLIBC__) && defined(STATX_BASIC_STATS)
// if using glibc, the statx() function in sysdeps/unix/sysv/linux/statx.c
// falls back to stat() for us.
-// (Using QT_CONFIG(glibc) instead of __GLIBC__ because the macros aren't
-// defined in assembler mode)
-# define MINLINUX_MAJOR 4
-# define MINLINUX_MINOR 11
-# define MINLINUX_PATCH 0
+# define QT_ELF_NOTE_OS_MAJOR 4
+# define QT_ELF_NOTE_OS_MINOR 11
+# define QT_ELF_NOTE_OS_PATCH 0
#elif QT_CONFIG(getentropy)
-# define MINLINUX_MAJOR 3
-# define MINLINUX_MINOR 17
-# define MINLINUX_PATCH 0
+# define QT_ELF_NOTE_OS_MAJOR 3
+# define QT_ELF_NOTE_OS_MINOR 17
+# define QT_ELF_NOTE_OS_PATCH 0
#elif QT_CONFIG(renameat2)
-# define MINLINUX_MAJOR 3
-# define MINLINUX_MINOR 16
-# define MINLINUX_PATCH 0
+# define QT_ELF_NOTE_OS_MAJOR 3
+# define QT_ELF_NOTE_OS_MINOR 16
+# define QT_ELF_NOTE_OS_PATCH 0
#else
-# define MINLINUX_MAJOR 2
-# define MINLINUX_MINOR 6
-# define MINLINUX_PATCH 28
+
+# define QT_ELF_NOTE_OS_MAJOR 2
+# define QT_ELF_NOTE_OS_MINOR 6
+# define QT_ELF_NOTE_OS_PATCH 28
#endif
-#define MINIMUM_LINUX_VERSION QT_VERSION_CHECK(MINLINUX_MAJOR, MINLINUX_MINOR, MINLINUX_PATCH)
+/* you must include <elf.h> */
+#define QT_ELF_NOTE_OS_TYPE ELF_NOTE_OS_LINUX
QT_END_NAMESPACE
diff --git a/src/corelib/global/q20algorithm.h b/src/corelib/global/q20algorithm.h
new file mode 100644
index 0000000000..24d801b2cd
--- /dev/null
+++ b/src/corelib/global/q20algorithm.h
@@ -0,0 +1,191 @@
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef Q20ALGORITHM_H
+#define Q20ALGORITHM_H
+
+#include <QtCore/qglobal.h>
+
+#include <algorithm>
+#include <QtCore/q20functional.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace q20 {
+// like std::<algorithm> (ie. not ranged, but constexpr)
+#ifdef __cpp_lib_constexpr_algorithms
+using std::copy;
+using std::copy_if;
+using std::copy_n;
+using std::fill;
+using std::fill_n;
+using std::is_sorted_until;
+using std::is_sorted;
+using std::transform;
+#else
+template <typename InputIterator, typename OutputIterator>
+constexpr OutputIterator
+copy(InputIterator first, InputIterator last, OutputIterator dest)
+{
+ while (first != last) {
+ *dest = *first;
+ ++first;
+ ++dest;
+ }
+ return dest;
+}
+
+template <typename InputIterator, typename OutputIterator, typename UnaryPredicate>
+constexpr OutputIterator
+copy_if(InputIterator first, InputIterator last, OutputIterator dest, UnaryPredicate pred)
+{
+ while (first != last) {
+ if (pred(*first)) {
+ *dest = *first;
+ ++dest;
+ }
+ ++first;
+ }
+ return dest;
+}
+
+template <typename InputIterator, typename Size, typename OutputIterator>
+constexpr OutputIterator
+copy_n(InputIterator first, Size n, OutputIterator dest)
+{
+ while (n > Size{0}) {
+ *dest = *first;
+ ++first;
+ ++dest;
+ --n;
+ }
+ return dest;
+}
+
+template <typename ForwardIterator, typename Value>
+constexpr void
+fill(ForwardIterator first, ForwardIterator last, const Value &value)
+{
+ while (first != last) {
+ *first = value;
+ ++first;
+ }
+}
+
+template <typename OutputIterator, typename Size, typename Value>
+constexpr OutputIterator
+fill_n(OutputIterator first, Size n, const Value &value)
+{
+ while (n > Size{0}) {
+ *first = value;
+ ++first;
+ --n;
+ }
+ return first;
+}
+
+template <typename ForwardIterator, typename BinaryPredicate = std::less<>>
+constexpr ForwardIterator
+is_sorted_until(ForwardIterator first, ForwardIterator last, BinaryPredicate p = {})
+{
+ if (first == last)
+ return first;
+ auto prev = first;
+ while (++first != last) {
+ if (p(*first, *prev))
+ return first;
+ prev = first;
+ }
+ return first;
+}
+
+template <typename ForwardIterator, typename BinaryPredicate = std::less<>>
+constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, BinaryPredicate p = {})
+{
+ return q20::is_sorted_until(first, last, p) == last;
+}
+
+template <typename InputIterator, typename OutputIterator, typename UnaryFunction>
+constexpr OutputIterator
+transform(InputIterator first, InputIterator last, OutputIterator dest, UnaryFunction op)
+{
+ while (first != last) {
+ *dest = op(*first);
+ ++first;
+ ++dest;
+ }
+ return dest;
+}
+
+// binary transform missing on purpose (no users)
+
+#endif
+}
+
+namespace q20::ranges {
+// like std::ranges::{any,all,none}_of, just unconstrained, so no range-overload
+#ifdef __cpp_lib_ranges
+using std::ranges::any_of;
+using std::ranges::all_of;
+using std::ranges::none_of;
+#else
+[[maybe_unused]] inline constexpr struct { // Niebloid
+ template <typename InputIterator, typename Sentinel,
+ typename Predicate, typename Projection = q20::identity>
+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
+ {
+ while (first != last) {
+ if (std::invoke(pred, std::invoke(proj, *first)))
+ return true;
+ ++first;
+ }
+ return false;
+ }
+} any_of;
+[[maybe_unused]] inline constexpr struct { // Niebloid
+ template <typename InputIterator, typename Sentinel,
+ typename Predicate, typename Projection = q20::identity>
+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
+ {
+ while (first != last) {
+ if (!std::invoke(pred, std::invoke(proj, *first)))
+ return false;
+ ++first;
+ }
+ return true;
+ }
+} all_of;
+[[maybe_unused]] inline constexpr struct { // Niebloid
+ template <typename InputIterator, typename Sentinel,
+ typename Predicate, typename Projection = q20::identity>
+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
+ {
+ while (first != last) {
+ if (std::invoke(pred, std::invoke(proj, *first)))
+ return false;
+ ++first;
+ }
+ return true;
+ }
+} none_of;
+#endif // __cpp_lib_ranges
+} // namespace q20::ranges
+
+QT_END_NAMESPACE
+
+#endif /* Q20ALGORITHM_H */
diff --git a/src/corelib/global/q20chrono.h b/src/corelib/global/q20chrono.h
new file mode 100644
index 0000000000..19c2eabe3d
--- /dev/null
+++ b/src/corelib/global/q20chrono.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2023 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef Q20CHRONO_H
+#define Q20CHRONO_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <chrono>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace q20 {
+namespace chrono {
+
+#if defined(__GLIBCXX__)
+// https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/bits/chrono.h
+using IntRep = int64_t;
+#else
+// https://github.com/llvm/llvm-project/blob/main/libcxx/include/__chrono/duration.h
+// https://github.com/microsoft/STL/blob/main/stl/inc/__msvc_chrono.hpp
+using IntRep = int;
+#endif
+
+#if __cpp_lib_chrono >= 201907L
+using std::chrono::days;
+using std::chrono::weeks;
+using std::chrono::years;
+using std::chrono::months;
+
+static_assert(std::is_same_v<days::rep, IntRep>);
+static_assert(std::is_same_v<weeks::rep, IntRep>);
+static_assert(std::is_same_v<years::rep, IntRep>);
+static_assert(std::is_same_v<months::rep, IntRep>);
+#else
+using days = std::chrono::duration<IntRep, std::ratio<86400>>;
+using weeks = std::chrono::duration<IntRep, std::ratio_multiply<std::ratio<7>, days::period>>;
+using years = std::chrono::duration<IntRep, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;
+using months = std::chrono::duration<IntRep, std::ratio_divide<years::period, std::ratio<12>>>;
+#endif // __cpp_lib_chrono >= 201907L
+} // namespace chrono
+} // namespace q20
+
+QT_END_NAMESPACE
+
+#endif /* Q20CHRONO_H */
diff --git a/src/corelib/global/q20functional.h b/src/corelib/global/q20functional.h
new file mode 100644
index 0000000000..a39b4fceb3
--- /dev/null
+++ b/src/corelib/global/q20functional.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef Q20FUNCTIONAL_H
+#define Q20FUNCTIONAL_H
+
+#include <QtCore/qglobal.h>
+
+#include <functional>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+namespace q20 {
+// like std::identity
+#ifdef __cpp_lib_ranges
+using std::identity;
+#else
+struct identity
+{
+ struct is_transparent {};
+ template <typename T>
+ constexpr T &&operator()(T&& t) const noexcept { return std::forward<T>(t); }
+};
+#endif // __cpp_lib_ranges
+} // namespace q20
+
+QT_END_NAMESPACE
+
+#endif /* Q20FUNCTIONAL_H */
diff --git a/src/corelib/global/q20iterator.h b/src/corelib/global/q20iterator.h
new file mode 100644
index 0000000000..9ed4d69965
--- /dev/null
+++ b/src/corelib/global/q20iterator.h
@@ -0,0 +1,54 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef Q20ITERATOR_H
+#define Q20ITERATOR_H
+
+#include <QtCore/qglobal.h>
+
+#include <iterator>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+// like std::ssize
+namespace q20 {
+#ifdef __cpp_lib_ssize
+ using std::ssize;
+#else
+ template<class C> constexpr auto ssize(const C &c)
+ -> std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>>
+ { return static_cast<std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>>>(c.size()); }
+
+ template<class T, std::ptrdiff_t N> constexpr std::ptrdiff_t ssize(const T (&)[N]) noexcept
+ { return N; }
+#endif
+} // namespace q20
+
+// like q20::iter_reference_t
+namespace q20 {
+#ifdef __cpp_lib_ranges
+ using std::iter_reference_t;
+#else
+ template <typename Dereferencable> // unconstrained (constraint requires concepts)
+ using iter_reference_t = decltype(*std::declval<Dereferencable&>());
+#endif // __cpp_lib_ranges
+} // namespace q20
+
+QT_END_NAMESPACE
+
+#endif /* Q20ITERATOR_H */
diff --git a/src/corelib/global/q20map.h b/src/corelib/global/q20map.h
new file mode 100644
index 0000000000..c719067480
--- /dev/null
+++ b/src/corelib/global/q20map.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2023 Ahmad Samir <a.samirh78@gmail.com>
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef Q20MAP_H
+#define Q20MAP_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <map>
+#if __has_include(<memory_resource>)
+# include <memory_resource>
+#endif
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace q20 {
+// like std::erase/std::erase_if for std::map
+#if defined(__cpp_lib_erase_if) && __cpp_lib_erase_if >= 202002L // the one returning size_type
+using std::erase_if;
+#else
+
+// Make it more specialized than the compiler's, so that our implementation is preferred over
+// the compiler's (which may be present, but return void instead of the number of erased elements).
+
+#define MAKE_OVERLOAD(map, allocator) \
+ template <typename Key, typename T, typename Compare, typename Pred> \
+ constexpr typename std::map<Key, T, Compare, std::allocator<std::pair<const Key, T>>>::size_type \
+ erase_if(std::map<Key, T, Compare, std::allocator<std::pair<const Key, T>>> &c, Pred p) \
+ { \
+ const auto origSize = c.size(); \
+ for (auto it = c.begin(), end = c.end(); it != end; /* erasing */) { \
+ if (p(*it)) \
+ it = c.erase(it); \
+ else \
+ ++it; \
+ } \
+ return origSize - c.size(); \
+ } \
+ /* end */
+
+MAKE_OVERLOAD(map, allocator)
+MAKE_OVERLOAD(multimap, allocator)
+#ifdef __cpp_lib_polymorphic_allocator
+MAKE_OVERLOAD(map, pmr::polymorphic_allocator)
+MAKE_OVERLOAD(multimap, pmr::polymorphic_allocator)
+#endif // __cpp_lib_polymorphic_allocator
+
+#undef MAKE_OVERLOAD
+
+#endif // __cpp_lib_erase_if
+} // namespace q20
+
+QT_END_NAMESPACE
+
+#endif /* Q20MAP_H */
diff --git a/src/corelib/global/q20memory.h b/src/corelib/global/q20memory.h
new file mode 100644
index 0000000000..008f4ddeb2
--- /dev/null
+++ b/src/corelib/global/q20memory.h
@@ -0,0 +1,93 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef Q20MEMORY_H
+#define Q20MEMORY_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <memory>
+
+#include <type_traits>
+#include <utility>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+// like std::construct_at (but not whitelisted for constexpr)
+namespace q20 {
+#ifdef __cpp_lib_constexpr_dynamic_alloc
+using std::construct_at;
+#else
+template <typename T,
+ typename... Args,
+ typename Enable = std::void_t<decltype(::new (std::declval<void *>()) T(std::declval<Args>()...))> >
+T *construct_at(T *ptr, Args && ... args)
+{
+ return ::new (const_cast<void *>(static_cast<const volatile void *>(ptr)))
+ T(std::forward<Args>(args)...);
+}
+#endif // __cpp_lib_constexpr_dynamic_alloc
+} // namespace q20
+
+
+namespace q20 {
+// like std::to_address
+#ifdef __cpp_lib_to_address
+using std::to_address;
+#else
+// http://eel.is/c++draft/pointer.conversion
+template <typename T>
+constexpr T *to_address(T *p) noexcept {
+ // http://eel.is/c++draft/pointer.conversion#1:
+ // Mandates: T is not a function type.
+ static_assert(!std::is_function_v<T>, "to_address must not be used on function types");
+ return p;
+}
+
+template <typename Ptr, typename std::enable_if_t<!std::is_pointer_v<Ptr>, bool> = true>
+constexpr auto to_address(const Ptr &ptr) noexcept; // fwd declared
+
+namespace detail {
+ // http://eel.is/c++draft/pointer.conversion#3
+ template <typename Ptr, typename = void>
+ struct to_address_helper {
+ static auto get(const Ptr &ptr) noexcept
+ { return q20::to_address(ptr.operator->()); }
+ };
+ template <typename Ptr>
+ struct to_address_helper<Ptr, std::void_t<
+ decltype(std::pointer_traits<Ptr>::to_address(std::declval<const Ptr&>()))
+ >>
+ {
+ static auto get(const Ptr &ptr) noexcept
+ { return std::pointer_traits<Ptr>::to_address(ptr); }
+ };
+} // namespace detail
+
+template <typename Ptr, typename std::enable_if_t<!std::is_pointer_v<Ptr>, bool>>
+constexpr auto to_address(const Ptr &ptr) noexcept
+{ return detail::to_address_helper<Ptr>::get(ptr); }
+
+#endif // __cpp_lib_to_address
+} // namespace q20
+
+QT_END_NAMESPACE
+
+#endif /* Q20MEMORY_H */
diff --git a/src/corelib/global/q20type_traits.h b/src/corelib/global/q20type_traits.h
new file mode 100644
index 0000000000..63a453daca
--- /dev/null
+++ b/src/corelib/global/q20type_traits.h
@@ -0,0 +1,81 @@
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef Q20TYPE_TRAITS_H
+#define Q20TYPE_TRAITS_H
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qsystemdetection.h>
+#include <QtCore/qtconfigmacros.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+#include <type_traits>
+
+QT_BEGIN_NAMESPACE
+
+namespace q20 {
+// like std::is_constant_evaluated
+#ifdef __cpp_lib_is_constant_evaluated
+using std::is_constant_evaluated;
+#define QT_SUPPORTS_IS_CONSTANT_EVALUATED
+#else
+constexpr bool is_constant_evaluated() noexcept
+{
+#ifdef Q_OS_INTEGRITY
+ // Integrity complains "calling __has_builtin() from a constant expression".
+ // Avoid the __has_builtin check until we know what's going on.
+ return false;
+#elif __has_builtin(__builtin_is_constant_evaluated) || \
+ (defined(Q_CC_MSVC_ONLY) /* >= 1925, but we require 1927 in qglobal.h */)
+# define QT_SUPPORTS_IS_CONSTANT_EVALUATED
+ return __builtin_is_constant_evaluated();
+#else
+ return false;
+#endif
+}
+#endif // __cpp_lib_is_constant_evaluated
+}
+
+namespace q20 {
+// like std::remove_cvref(_t)
+#ifdef __cpp_lib_remove_cvref
+using std::remove_cvref;
+using std::remove_cvref_t;
+#else
+template <typename T>
+using remove_cvref = std::remove_cv<std::remove_reference_t<T>>;
+template <typename T>
+using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
+#endif // __cpp_lib_remove_cvref
+}
+
+namespace q20 {
+// like std::type_identity(_t)
+#ifdef __cpp_lib_type_identity
+using std::type_identity;
+using std::type_identity_t;
+#else
+template <typename T>
+struct type_identity { using type = T; };
+template <typename T>
+using type_identity_t = typename type_identity<T>::type;
+#endif // __cpp_lib_type_identity
+}
+
+QT_END_NAMESPACE
+
+#endif /* Q20TYPE_TRAITS_H */
diff --git a/src/corelib/global/q20vector.h b/src/corelib/global/q20vector.h
new file mode 100644
index 0000000000..9d312355ea
--- /dev/null
+++ b/src/corelib/global/q20vector.h
@@ -0,0 +1,90 @@
+// Copyright (C) 2023 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef Q20VECTOR_H
+#define Q20VECTOR_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <algorithm>
+#include <vector>
+#if __has_include(<memory_resource>)
+# include <memory_resource>
+#endif
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace q20 {
+// like std::erase/std::erase_if for std::vector
+#if defined(__cpp_lib_erase_if) && __cpp_lib_erase_if >= 202002L // the one returning size_type
+using std::erase;
+using std::erase_if;
+#else
+
+// Make it more specialized than the compiler's, so that our implementation is preferred over
+// the compiler's (which may be present, but return void instead of the number of erased elements).
+
+template <typename T, typename U>
+constexpr typename std::vector<T, std::allocator<T>>::size_type
+erase(std::vector<T, std::allocator<T>> &c, const U &value)
+{
+ const auto origSize = c.size();
+ auto it = std::remove(c.begin(), c.end(), value);
+ c.erase(it, c.end());
+ return origSize - c.size();
+}
+
+template <typename T, typename Pred>
+constexpr typename std::vector<T, std::allocator<T>>::size_type
+erase_if(std::vector<T, std::allocator<T>> &c, Pred pred)
+{
+ const auto origSize = c.size();
+ auto it = std::remove_if(c.begin(), c.end(), pred);
+ c.erase(it, c.end());
+ return origSize - c.size();
+}
+
+#ifdef __cpp_lib_polymorphic_allocator
+template <typename T, typename U>
+constexpr typename std::vector<T, std::pmr::polymorphic_allocator<T>>::size_type
+erase(std::vector<T, std::pmr::polymorphic_allocator<T>> &c, const U &value)
+{
+ const auto origSize = c.size();
+ auto it = std::remove(c.begin(), c.end(), value);
+ c.erase(it, c.end());
+ return origSize - c.size();
+}
+
+template <typename T, typename Pred>
+constexpr typename std::vector<T, std::pmr::polymorphic_allocator<T>>::size_type
+erase_if(std::vector<T, std::pmr::polymorphic_allocator<T>> &c, Pred pred)
+{
+ const auto origSize = c.size();
+ auto it = std::remove_if(c.begin(), c.end(), pred);
+ c.erase(it, c.end());
+ return origSize - c.size();
+}
+#endif // __cpp_lib_polymorphic_allocator
+
+#endif // __cpp_lib_erase_if
+} // namespace q20
+
+QT_END_NAMESPACE
+
+#endif /* Q20VECTOR_H */
diff --git a/src/corelib/global/q23functional.h b/src/corelib/global/q23functional.h
new file mode 100644
index 0000000000..ae8f78a3d0
--- /dev/null
+++ b/src/corelib/global/q23functional.h
@@ -0,0 +1,49 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef Q23FUNCTIONAL_H
+#define Q23FUNCTIONAL_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/q20functional.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace q23 {
+// like std::invoke_r
+#ifdef __cpp_lib_invoke_r
+using std::invoke_r;
+#else
+template <typename R, typename F, typename...Args>
+constexpr
+std::enable_if_t<std::is_invocable_r_v<R, F, Args...>, R>
+invoke_r(F&& f, Args&&... args)
+ noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>)
+{
+ // ### use q20::invoke for a constexpr std::invoke
+ if constexpr (std::is_void_v<R>)
+ std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
+ else
+ return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
+}
+#endif // __cpp_lib_invoke_r
+} // namespace q23
+
+QT_END_NAMESPACE
+
+#endif /* Q23FUNCTIONAL_H */
diff --git a/src/corelib/global/q23utility.cpp b/src/corelib/global/q23utility.cpp
new file mode 100644
index 0000000000..9c5365c547
--- /dev/null
+++ b/src/corelib/global/q23utility.cpp
@@ -0,0 +1,25 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/q23utility.h>
+
+QT_BEGIN_NAMESPACE
+
+#define CHECK2(cvref_in, cvref_out) \
+ static_assert(std::is_same_v< \
+ decltype(q23::forward_like<int cvref_in >(std::declval<long&>())), \
+ long cvref_out \
+ >, "oops: cvref '" #cvref_in "' doesn't work") \
+ /* end */
+#define CHECK(cvref) CHECK2(cvref, cvref)
+CHECK2(/**/, &&);
+CHECK(&);
+CHECK(&&);
+CHECK2(const, const &&);
+CHECK(const &);
+CHECK(const &&);
+// volatile is not supported
+#undef CHECK
+#undef CHECK2
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/q23utility.h b/src/corelib/global/q23utility.h
new file mode 100644
index 0000000000..9ae5389b56
--- /dev/null
+++ b/src/corelib/global/q23utility.h
@@ -0,0 +1,75 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef Q23UTILITY_H
+#define Q23UTILITY_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <utility>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace q23 {
+// like std::forward_like
+#ifdef __cpp_lib_forward_like
+using std::forward_like;
+#else
+
+namespace _detail {
+
+// [forward]/6.1 COPY_CONST
+template <typename A, typename B>
+using copy_const_t = std::conditional_t<
+ std::is_const_v<A>, const B,
+ /* else */ B
+ >;
+
+// [forward]/6.2 OVERRIDE_REF
+template <typename A, typename B>
+using override_ref_t = std::conditional_t<
+ std::is_rvalue_reference_v<A>, std::remove_reference_t<B>&&,
+ /* else */ B&
+ >;
+
+// [forward]/6.3 "V"
+template <typename T, typename U>
+using forward_like_ret_t = override_ref_t<
+ T&&,
+ copy_const_t<
+ std::remove_reference_t<T>,
+ std::remove_reference_t<U>
+ >
+ >;
+
+} // namespace detail
+
+// http://eel.is/c++draft/forward#lib:forward_like
+template <class T, class U>
+[[nodiscard]] constexpr auto forward_like(U &&x) noexcept
+ -> _detail::forward_like_ret_t<T, U>
+{
+ using V = _detail::forward_like_ret_t<T, U>;
+ return static_cast<V>(x);
+}
+#endif // __cpp_lib_forward_like
+} // namespace q23
+
+QT_END_NAMESPACE
+
+#endif /* Q23UTILITY_H */
diff --git a/src/corelib/global/qassert.cpp b/src/corelib/global/qassert.cpp
new file mode 100644
index 0000000000..6a29cbfa21
--- /dev/null
+++ b/src/corelib/global/qassert.cpp
@@ -0,0 +1,277 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qassert.h"
+
+#include <QtCore/qlogging.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <exception>
+#ifndef QT_NO_EXCEPTIONS
+#include <new>
+#endif
+
+#if defined(Q_CC_MSVC)
+# include <crtdbg.h>
+#endif
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+void qAbort()
+{
+#ifdef Q_OS_WIN
+ // std::abort() in the MSVC runtime will call _exit(3) if the abort
+ // behavior is _WRITE_ABORT_MSG - see also _set_abort_behavior(). This is
+ // the default for a debug-mode build of the runtime. Worse, MinGW's
+ // std::abort() implementation (in msvcrt.dll) is basically a call to
+ // _exit(3) too. Unfortunately, _exit() and _Exit() *do* run the static
+ // destructors of objects in DLLs, a violation of the C++ standard (see
+ // [support.start.term]). So we bypass std::abort() and directly
+ // terminate the application.
+
+# if defined(Q_CC_MSVC)
+ if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
+ __fastfail(FAST_FAIL_FATAL_APP_EXIT);
+# else
+ RaiseFailFastException(nullptr, nullptr, 0);
+# endif
+
+ // Fallback
+ TerminateProcess(GetCurrentProcess(), STATUS_FATAL_APP_EXIT);
+
+ // Tell the compiler the application has stopped.
+ Q_UNREACHABLE_IMPL();
+#else // !Q_OS_WIN
+ std::abort();
+#endif
+}
+
+/*!
+ \macro void Q_ASSERT(bool test)
+ \relates <QtAssert>
+
+ Prints a warning message containing the source code file name and
+ line number if \a test is \c false.
+
+ Q_ASSERT() is useful for testing pre- and post-conditions
+ during development. It does nothing if \c QT_NO_DEBUG was defined
+ during compilation.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 17
+
+ If \c b is zero, the Q_ASSERT statement will output the following
+ message using the qFatal() function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 18
+
+ \sa Q_ASSERT_X(), qFatal(), {Debugging Techniques}
+*/
+
+/*!
+ \macro void Q_ASSERT_X(bool test, const char *where, const char *what)
+ \relates <QtAssert>
+
+ Prints the message \a what together with the location \a where,
+ the source file name and line number if \a test is \c false.
+
+ Q_ASSERT_X is useful for testing pre- and post-conditions during
+ development. It does nothing if \c QT_NO_DEBUG was defined during
+ compilation.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 19
+
+ If \c b is zero, the Q_ASSERT_X statement will output the following
+ message using the qFatal() function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 20
+
+ \sa Q_ASSERT(), qFatal(), {Debugging Techniques}
+*/
+
+/*
+ The Q_ASSERT macro calls this function when the test fails.
+*/
+void qt_assert(const char *assertion, const char *file, int line) noexcept
+{
+ QMessageLogger(file, line, nullptr)
+ .fatal("ASSERT: \"%s\" in file %s, line %d", assertion, file, line);
+}
+
+/*
+ The Q_ASSERT_X macro calls this function when the test fails.
+*/
+void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept
+{
+ QMessageLogger(file, line, nullptr)
+ .fatal("ASSERT failure in %s: \"%s\", file %s, line %d", where, what, file, line);
+}
+
+/*!
+ \macro void Q_CHECK_PTR(void *pointer)
+ \relates <QtAssert>
+
+ If \a pointer is \nullptr, prints a message containing the source
+ code's file name and line number, saying that the program ran out
+ of memory and aborts program execution. It throws \c std::bad_alloc instead
+ if exceptions are enabled.
+
+ Q_CHECK_PTR does nothing if \c QT_NO_DEBUG and \c QT_NO_EXCEPTIONS were
+ defined during compilation. Therefore you must not use Q_CHECK_PTR to check
+ for successful memory allocations because the check will be disabled in
+ some cases.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 21
+
+ \sa qWarning(), {Debugging Techniques}
+*/
+
+/*!
+ \fn template <typename T> T *q_check_ptr(T *p)
+ \relates <QtAssert>
+
+ Uses Q_CHECK_PTR on \a p, then returns \a p.
+
+ This can be used as an inline version of Q_CHECK_PTR.
+*/
+
+/*!
+ \internal
+ The Q_CHECK_PTR macro calls this function if an allocation check
+ fails.
+*/
+void qt_check_pointer(const char *n, int l) noexcept
+{
+ // make separate printing calls so that the first one may flush;
+ // the second one could want to allocate memory (fputs prints a
+ // newline and stderr auto-flushes).
+ fputs("Out of memory", stderr);
+ fprintf(stderr, " in %s, line %d\n", n, l);
+
+ std::terminate();
+}
+
+/*
+ \internal
+ Allows you to throw an exception without including <new>
+ Called internally from Q_CHECK_PTR on certain OS combinations
+*/
+void qBadAlloc()
+{
+#ifndef QT_NO_EXCEPTIONS
+ throw std::bad_alloc();
+#else
+ std::terminate();
+#endif
+}
+
+/*!
+ \macro void Q_ASSUME(bool expr)
+ \deprecated
+ \relates <QtAssert>
+ \since 5.0
+
+ Causes the compiler to assume that \a expr is \c true.
+
+ This macro is known to produce worse code than when no assumption was
+ inserted in the code, with some compiler versions. The arguments passed to
+ it are always evaluated, even in release mode, with some compilers and not
+ others, so application code needs to be aware of those possible differences
+ in behavior.
+
+ Do not use it in new code. It is retained as-is for compatibility with old
+ code and will likely be removed in the next major version Qt.
+
+ \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY()
+*/
+
+/*!
+ \macro QT_TERMINATE_ON_EXCEPTION(expr)
+ \relates <QtGlobal>
+ \internal
+
+ In general, use of the Q_DECL_NOEXCEPT macro is preferred over
+ Q_DECL_NOTHROW, because it exhibits well-defined behavior and
+ supports the more powerful Q_DECL_NOEXCEPT_EXPR variant. However,
+ use of Q_DECL_NOTHROW has the advantage that Windows builds
+ benefit on a wide range or compiler versions that do not yet
+ support the C++11 noexcept feature.
+
+ It may therefore be beneficial to use Q_DECL_NOTHROW and emulate
+ the C++11 behavior manually with an embedded try/catch.
+
+ Qt provides the QT_TERMINATE_ON_EXCEPTION(expr) macro for this
+ purpose. It either expands to \c expr (if Qt is compiled without
+ exception support or the compiler supports C++11 noexcept
+ semantics) or to
+ \snippet code/src_corelib_global_qglobal.cpp qterminate
+ otherwise.
+
+ Since this macro expands to just \c expr if the compiler supports
+ C++11 noexcept, expecting the compiler to take over responsibility
+ of calling std::terminate() in that case, it should not be used
+ outside Q_DECL_NOTHROW functions.
+
+ \sa Q_DECL_NOEXCEPT, Q_DECL_NOTHROW, qTerminate()
+*/
+
+/*!
+ \macro void Q_UNREACHABLE()
+ \relates <QtAssert>
+ \since 5.0
+
+ Tells the compiler that the current point cannot be reached by any
+ execution, so it may optimize any code paths leading here as dead code, as
+ well as code continuing from here.
+
+ This macro is useful to mark impossible conditions. For example, given the
+ following enum:
+
+ \snippet code/src_corelib_global_qglobal.cpp qunreachable-enum
+
+ One can write a switch table like so:
+
+ \snippet code/src_corelib_global_qglobal.cpp qunreachable-switch
+
+ The advantage of inserting Q_UNREACHABLE() at that point is that the
+ compiler is told not to generate code for a shape variable containing that
+ value. If the macro is missing, the compiler will still generate the
+ necessary comparisons for that value. If the case label were removed, some
+ compilers could produce a warning that some enum values were not checked.
+
+ By using this macro in impossible conditions, code coverage may be improved
+ as dead code paths may be eliminated.
+
+ In debug builds the condition is enforced by an assert to facilitate debugging.
+
+ \note Use the macro Q_UNREACHABLE_RETURN() to insert return statements for
+ compilers that need them, without causing warnings for compilers that
+ complain about its presence.
+
+ \sa Q_ASSERT(), qFatal(), Q_UNREACHABLE_RETURN()
+*/
+
+/*!
+ \macro void Q_UNREACHABLE_RETURN(...)
+ \relates <QtAssert>
+ \since 6.5
+
+ This is equivalent to
+ \code
+ Q_UNREACHABLE();
+ return __VA_ARGS__;
+ \endcode
+ except it omits the return on compilers that would warn about it.
+
+ \sa Q_UNREACHABLE()
+*/
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qassert.h b/src/corelib/global/qassert.h
new file mode 100644
index 0000000000..388932a8f7
--- /dev/null
+++ b/src/corelib/global/qassert.h
@@ -0,0 +1,116 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QASSERT_H
+#define QASSERT_H
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
+#include <QtCore/qtnoop.h>
+
+#if 0
+#pragma qt_class(QtAssert)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(__cplusplus)
+
+#if !defined(Q_CC_MSVC_ONLY)
+Q_NORETURN
+#endif
+Q_DECL_COLD_FUNCTION
+Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) noexcept;
+
+#if !defined(Q_ASSERT)
+# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
+# define Q_ASSERT(cond) static_cast<void>(false && (cond))
+# else
+# define Q_ASSERT(cond) ((cond) ? static_cast<void>(0) : qt_assert(#cond, __FILE__, __LINE__))
+# endif
+#endif
+
+#if !defined(Q_CC_MSVC_ONLY)
+Q_NORETURN
+#endif
+Q_DECL_COLD_FUNCTION
+Q_CORE_EXPORT
+void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept;
+
+#if !defined(Q_ASSERT_X)
+# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
+# define Q_ASSERT_X(cond, where, what) static_cast<void>(false && (cond))
+# else
+# define Q_ASSERT_X(cond, where, what) ((cond) ? static_cast<void>(0) : qt_assert_x(where, what, __FILE__, __LINE__))
+# endif
+#endif
+
+Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) noexcept;
+Q_NORETURN Q_DECL_COLD_FUNCTION
+Q_CORE_EXPORT void qBadAlloc();
+
+#ifdef QT_NO_EXCEPTIONS
+# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
+# define Q_CHECK_PTR(p) qt_noop()
+# else
+# define Q_CHECK_PTR(p) do {if (!(p)) qt_check_pointer(__FILE__,__LINE__);} while (false)
+# endif
+#else
+# define Q_CHECK_PTR(p) do { if (!(p)) qBadAlloc(); } while (false)
+#endif
+
+template <typename T>
+inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; }
+
+// Q_UNREACHABLE_IMPL() and Q_ASSUME_IMPL() used below are defined in qcompilerdetection.h
+#define Q_UNREACHABLE() \
+ do {\
+ Q_ASSERT_X(false, "Q_UNREACHABLE()", "Q_UNREACHABLE was reached");\
+ Q_UNREACHABLE_IMPL();\
+ } while (false)
+
+#ifndef Q_UNREACHABLE_RETURN
+# ifdef Q_COMPILER_COMPLAINS_ABOUT_RETURN_AFTER_UNREACHABLE
+# define Q_UNREACHABLE_RETURN(...) Q_UNREACHABLE()
+# else
+# define Q_UNREACHABLE_RETURN(...) do { Q_UNREACHABLE(); return __VA_ARGS__; } while (0)
+# endif
+#endif
+
+Q_DECL_DEPRECATED_X("Q_ASSUME() is deprecated because it can produce worse code than when it's absent; "
+ "use C++23 [[assume]] instead")
+inline bool qt_assume_is_deprecated(bool cond) noexcept { return cond; }
+#define Q_ASSUME(Expr) \
+ [] (bool valueOfExpression) {\
+ Q_ASSERT_X(valueOfExpression, "Q_ASSUME()", "Assumption in Q_ASSUME(\"" #Expr "\") was not correct");\
+ Q_ASSUME_IMPL(valueOfExpression);\
+ }(qt_assume_is_deprecated(Expr))
+
+// Don't use these in C++ mode, use static_assert directly.
+// These are here only to keep old code compiling.
+# define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition)
+# define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
+
+#elif defined(Q_COMPILER_STATIC_ASSERT)
+// C11 mode - using the _S version in case <assert.h> doesn't do the right thing
+# define Q_STATIC_ASSERT(Condition) _Static_assert(!!(Condition), #Condition)
+# define Q_STATIC_ASSERT_X(Condition, Message) _Static_assert(!!(Condition), Message)
+#else
+// C89 & C99 version
+# define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
+# define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
+# ifdef __COUNTER__
+# define Q_STATIC_ASSERT(Condition) \
+ typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) [(Condition) ? 1 : -1];
+# else
+# define Q_STATIC_ASSERT(Condition) \
+ typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) [(Condition) ? 1 : -1];
+# endif /* __COUNTER__ */
+# define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
+#endif // __cplusplus
+
+QT_END_NAMESPACE
+
+#endif // QASSERT_H
diff --git a/src/corelib/global/qcompare.cpp b/src/corelib/global/qcompare.cpp
new file mode 100644
index 0000000000..ac220b8434
--- /dev/null
+++ b/src/corelib/global/qcompare.cpp
@@ -0,0 +1,1357 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcompare.h"
+
+#ifdef __cpp_lib_bit_cast
+#include <bit>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef __cpp_lib_three_way_comparison
+#ifdef __cpp_lib_bit_cast
+#define CHECK(type, flag) \
+ static_assert(std::bit_cast<Qt:: type ## _ordering>(std:: type ## _ordering:: flag) \
+ == Qt:: type ## _ordering :: flag); \
+ static_assert(std::bit_cast<std:: type ## _ordering>(Qt:: type ## _ordering:: flag) \
+ == std:: type ## _ordering :: flag) \
+ /* end */
+CHECK(partial, unordered);
+CHECK(partial, less);
+CHECK(partial, greater);
+CHECK(partial, equivalent);
+CHECK(weak, less);
+CHECK(weak, greater);
+CHECK(weak, equivalent);
+CHECK(strong, less);
+CHECK(strong, greater);
+CHECK(strong, equal);
+CHECK(strong, equivalent);
+#undef CHECK
+#endif // __cpp_lib_bit_cast
+#endif //__cpp_lib_three_way_comparison
+
+
+/*!
+ \page comparison-types.html overview
+ \title Comparison types overview
+ \keyword three-way comparison
+ \inmodule QtCore
+ \sa Qt::strong_ordering, Qt::weak_ordering, Qt::partial_ordering
+
+ \note Qt's comparison types provide functionality equivalent to their C++20
+ standard counterparts. The only reason why they exist is to make the
+ functionality available in C++17 builds, too. In a C++20 build, they
+ implicitly convert to and from the \c std types, making them fully
+ interchangeable. We therefore recommended that you prefer to use the C++
+ standard types in your code, if you can use C++20 in your projects already.
+ The Qt comparison types will be removed in Qt 7.
+
+ Qt provides several comparison types for a \l
+ {https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison}
+ {three-way comparison}, which are comparable against a \e {zero literal}.
+ To use these comparison types, you need to include the \c <QtCompare>
+ header. These comparison types are categorized based on their \e order,
+ which is a mathematical concept used to describe the arrangement or ranking
+ of elements. The following categories are provided:
+
+ \table 100 %
+ \header
+ \li C++ type
+ \li Qt type
+ \li strict
+ \li total
+ \li Example
+ \row
+ \li \l {https://en.cppreference.com/w/cpp/utility/compare/strong_ordering}
+ {std::strong_ordering}
+ \li Qt::strong_ordering
+ \li yes
+ \li yes
+ \li integral types, case-sensitive strings, QDate, QTime
+ \row
+ \li \l {https://en.cppreference.com/w/cpp/utility/compare/weak_ordering}
+ {std::weak_ordering}
+ \li Qt::weak_ordering
+ \li no
+ \li yes
+ \li case-insensitive strings, unordered associative containers, QDateTime
+ \row
+ \li \l {https://en.cppreference.com/w/cpp/utility/compare/partial_ordering}
+ {std::partial_ordering}
+ \li Qt::partial_ordering
+ \li no
+ \li no
+ \li floating-point types, QOperatingSystemVersion, QVariant
+ \endtable
+
+ The strongest comparison type, Qt::strong_ordering, represents a strict total
+ order. It requires that any two elements be comparable in a way where
+ equality implies substitutability. In other words, equivalent values
+ cannot be distinguished from each other. A practical example would be the
+ case-sensitive comparison of two strings. For instance, when comparing the
+ values \c "Qt" and \c "Qt" the result would be \l Qt::strong_ordering::equal.
+ Both values are indistinguishable and all deterministic operations performed
+ on these values would yield identical results.
+
+ Qt::weak_ordering represents a total order. While any two values still need to
+ be comparable, equivalent values may be distinguishable. The canonical
+ example here would be the case-insensitive comparison of two strings. For
+ instance, when comparing the values \c "Qt" and \c "qt" both hold the same
+ letters but with different representations. This comparison would
+ result in \l Qt::weak_ordering::equivalent, but not actually \c Equal.
+ Another example would be QDateTime, which can represent a given instant in
+ time in terms of local time or any other time-zone, including UTC. The
+ different representations are equivalent, even though their \c time() and
+ sometimes \c date() may differ.
+
+ Qt::partial_ordering represents, as the name implies, a partial ordering. It
+ allows for the possibility that two values may not be comparable, resulting
+ in an \l {Qt::partial_ordering::}{unordered} state. Additionally, equivalent
+ values may still be distinguishable. A practical example would be the
+ comparison of two floating-point values, comparing with NaN (Not-a-Number)
+ would yield an unordered result. Another example is the comparison of two
+ QOperatingSystemVersion objects. Comparing versions of two different
+ operating systems, such as Android and Windows, would produce an unordered
+ result.
+
+ Utilizing these comparison types enhances the expressiveness of defining
+ relations. Furthermore, they serve as a fundamental component for
+ implementing three-way comparison with C++17.
+*/
+
+/*!
+ \headerfile <QtCompare>
+ \inmodule QtCore
+ \title Classes and helpers for defining comparison operators
+ \keyword qtcompare
+
+ \brief The <QtCompare> header file defines \c {Qt::*_ordering} types and helper
+ macros for defining comparison operators.
+
+ This header introduces the \l Qt::partial_ordering, \l Qt::weak_ordering, and
+ \l Qt::strong_ordering types, which are Qt's C++17 backports of
+ \c {std::*_ordering} types.
+
+ This header also contains functions for implementing three-way comparison
+ in C++17.
+
+ The \c {Qt::compareThreeWay()} function overloads provide three-way
+ comparison for built-in C++ types.
+
+ The \l qCompareThreeWay() template serves as a generic three-way comparison
+ implementation. It relies on \c {Qt::compareThreeWay()} and free
+ \c {compareThreeWay()} functions in its implementation.
+*/
+
+/*!
+ \class Qt::strong_ordering
+ \inmodule QtCore
+ \brief Qt::strong_ordering represents a comparison where equivalent values are
+ indistinguishable.
+ \sa Qt::weak_ordering, Qt::partial_ordering, {Comparison types overview}
+ \since 6.7
+
+ A value of type Qt::strong_ordering is typically returned from a three-way
+ comparison function. Such a function compares two objects and establishes
+ how they are ordered. It uses this return type to indicate that the ordering
+ is strict; that is, the function establishes a well-defined total order.
+
+ Qt::strong_ordering has four values, represented by the following symbolic
+ constants:
+
+ \list
+ \li \l less represents that the left operand is less than the right;
+ \li \l equal represents that the left operand is equivalent to the right;
+ \li \l equivalent is an alias for \c equal;
+ \li \l greater represents that the left operand is greater than the right.
+ \endlist
+
+ Qt::strong_ordering is idiomatically used by comparing an instance against a
+ literal zero, for instance like this:
+
+ \code
+
+ // given a, b, c, d as objects of some type that allows for a 3-way compare,
+ // and a compare function declared as follows:
+
+ Qt::strong_ordering compare(T lhs, T rhs); // defined out-of-line
+ ~~~
+
+ Qt::strong_ordering result = compare(a, b);
+ if (result < 0) {
+ // a is less than b
+ }
+
+ if (compare(c, d) >= 0) {
+ // c is greater than or equal to d
+ }
+
+ \endcode
+*/
+
+/*!
+ \fn Qt::strong_ordering::operator Qt::partial_ordering() const
+
+ Converts this Qt::strong_ordering value to a Qt::partial_ordering object using the
+ following rules:
+
+ \list
+ \li \l less converts to \l {Qt::partial_ordering::less}.
+ \li \l equivalent converts to \l {Qt::partial_ordering::equivalent}.
+ \li \l equal converts to \l {Qt::partial_ordering::equivalent}.
+ \li \l greater converts to \l {Qt::partial_ordering::greater}.
+ \endlist
+*/
+
+/*!
+ \fn Qt::strong_ordering::operator Qt::weak_ordering() const
+
+ Converts this Qt::strong_ordering value to a Qt::weak_ordering object using the
+ following rules:
+
+ \list
+ \li \l less converts to \l {Qt::weak_ordering::less}.
+ \li \l equivalent converts to \l {Qt::weak_ordering::equivalent}.
+ \li \l equal converts to \l {Qt::weak_ordering::equivalent}.
+ \li \l greater converts to \l {Qt::weak_ordering::greater}.
+ \endlist
+*/
+
+/*!
+ \fn Qt::strong_ordering::strong_ordering(std::strong_ordering stdorder)
+
+ Constructs a Qt::strong_ordering object from \a stdorder using the following rules:
+
+ \list
+ \li std::strong_ordering::less converts to \l less.
+ \li std::strong_ordering::equivalent converts to \l equivalent.
+ \li std::strong_ordering::equal converts to \l equal.
+ \li std::strong_ordering::greater converts to \l greater.
+ \endlist
+*/
+
+/*!
+ \fn Qt::strong_ordering::operator std::strong_ordering() const
+
+ Converts this Qt::strong_ordering value to a std::strong_ordering object using
+ the following rules:
+
+ \list
+ \li \l less converts to std::strong_ordering::less.
+ \li \l equivalent converts to std::strong_ordering::equivalent.
+ \li \l equal converts to std::strong_ordering::equal.
+ \li \l greater converts to std::strong_ordering::greater.
+ \endlist
+*/
+
+/*!
+ \fn bool Qt::strong_ordering::operator==(Qt::strong_ordering lhs, Qt::strong_ordering rhs)
+
+ Returns true if \a lhs and \a rhs represent the same result;
+ otherwise, returns false.
+*/
+
+/*!
+ \fn bool Qt::strong_ordering::operator!=(Qt::strong_ordering lhs, Qt::strong_ordering rhs)
+
+ Returns true if \a lhs and \a rhs represent different results;
+ otherwise, returns true.
+*/
+
+/*!
+ \internal
+ \relates Qt::strong_ordering
+ \fn bool operator==(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator!=(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator< (Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator<=(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator> (Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator>=(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+
+ \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs)
+ \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs)
+ \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs)
+ \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs)
+ \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs)
+ \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs)
+*/
+
+/*!
+ \fn Qt::strong_ordering::is_eq (Qt::strong_ordering o)
+ \fn Qt::strong_ordering::is_neq (Qt::strong_ordering o)
+ \fn Qt::strong_ordering::is_lt (Qt::strong_ordering o)
+ \fn Qt::strong_ordering::is_lteq(Qt::strong_ordering o)
+ \fn Qt::strong_ordering::is_gt (Qt::strong_ordering o)
+ \fn Qt::strong_ordering::is_gteq(Qt::strong_ordering o)
+
+//! [is_eq_table]
+ Converts \a o into the result of one of the six relational operators:
+ \table
+ \header \li Function \li Operation
+ \row \li \c{is_eq} \li \a o \c{== 0}
+ \row \li \c{is_neq} \li \a o \c{!= 0}
+ \row \li \c{is_lt} \li \a o \c{< 0}
+ \row \li \c{is_lteq} \li \a o \c{<= 0}
+ \row \li \c{is_gt} \li \a o \c{> 0}
+ \row \li \c{is_gteq} \li \a o \c{>= 0}
+ \endtable
+//! [is_eq_table]
+
+ These functions are provided for compatibility with \c{std::strong_ordering}.
+*/
+
+/*!
+ \variable Qt::strong_ordering::less
+
+ Represents the result of a comparison where the left operand is less
+ than the right operand.
+*/
+
+/*!
+ \variable Qt::strong_ordering::equivalent
+
+ Represents the result of a comparison where the left operand is equal
+ to the right operand. Same as \l {Qt::strong_ordering::equal}.
+*/
+
+/*!
+ \variable Qt::strong_ordering::equal
+
+ Represents the result of a comparison where the left operand is equal
+ to the right operand. Same as \l {Qt::strong_ordering::equivalent}.
+*/
+
+/*!
+ \variable Qt::strong_ordering::greater
+
+ Represents the result of a comparison where the left operand is greater
+ than the right operand.
+*/
+
+/*!
+ \class Qt::weak_ordering
+ \inmodule QtCore
+ \brief Qt::weak_ordering represents a comparison where equivalent values are
+ still distinguishable.
+ \sa Qt::strong_ordering, Qt::partial_ordering, {Comparison types overview}
+ \since 6.7
+
+ A value of type Qt::weak_ordering is typically returned from a three-way
+ comparison function. Such a function compares two objects and establishes
+ how they are ordered. It uses this return type to indicate that the ordering
+ is weak; that is, equivalent values may be distinguishable.
+
+ Qt::weak_ordering has three values, represented by the following symbolic
+ constants:
+
+ \list
+ \li \l less represents that the left operand is less than the right;
+ \li \l equivalent represents that the left operand is equivalent to the
+ right;
+ \li \l greater represents that the left operand is greater than the right,
+ \endlist
+
+ Qt::weak_ordering is idiomatically used by comparing an instance against a
+ literal zero, for instance like this:
+
+ \code
+
+ // given a, b, c, d as objects of some type that allows for a 3-way compare,
+ // and a compare function declared as follows:
+
+ Qt::weak_ordering compare(T lhs, T rhs); // defined out-of-line
+ ~~~
+
+ Qt::weak_ordering result = compare(a, b);
+ if (result < 0) {
+ // a is less than b
+ }
+
+ if (compare(c, d) >= 0) {
+ // c is greater than or equivalent to d
+ }
+
+ \endcode
+*/
+
+/*!
+ \fn Qt::weak_ordering::operator Qt::partial_ordering() const
+
+ Converts this Qt::weak_ordering value to a Qt::partial_ordering object using the
+ following rules:
+
+ \list
+ \li \l less converts to \l {Qt::partial_ordering::less}.
+ \li \l equivalent converts to \l {Qt::partial_ordering::equivalent}.
+ \li \l greater converts to \l {Qt::partial_ordering::greater}.
+ \endlist
+*/
+
+/*!
+ \fn Qt::weak_ordering::weak_ordering(std::weak_ordering stdorder)
+
+ Constructs a Qt::weak_ordering object from \a stdorder using the following rules:
+
+ \list
+ \li std::weak_ordering::less converts to \l less.
+ \li std::weak_ordering::equivalent converts to \l equivalent.
+ \li std::weak_ordering::greater converts to \l greater.
+ \endlist
+*/
+
+/*!
+ \fn Qt::weak_ordering::operator std::weak_ordering() const
+
+ Converts this Qt::weak_ordering value to a std::weak_ordering object using
+ the following rules:
+
+ \list
+ \li \l less converts to std::weak_ordering::less.
+ \li \l equivalent converts to std::weak_ordering::equivalent.
+ \li \l greater converts to std::weak_ordering::greater.
+ \endlist
+*/
+
+/*!
+ \fn bool Qt::weak_ordering::operator==(Qt::weak_ordering lhs, Qt::weak_ordering rhs)
+
+ Return true if \a lhs and \a rhs represent the same result;
+ otherwise, returns false.
+*/
+
+/*!
+ \fn bool Qt::weak_ordering::operator!=(Qt::weak_ordering lhs, Qt::weak_ordering rhs)
+
+ Return true if \a lhs and \a rhs represent different results;
+ otherwise, returns true.
+*/
+
+/*!
+ \internal
+ \relates Qt::weak_ordering
+ \fn bool operator==(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator!=(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator< (Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator<=(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator> (Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator>=(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+
+ \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs)
+ \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs)
+ \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs)
+ \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs)
+ \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs)
+ \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs)
+*/
+
+/*!
+ \fn Qt::weak_ordering::is_eq (Qt::weak_ordering o)
+ \fn Qt::weak_ordering::is_neq (Qt::weak_ordering o)
+ \fn Qt::weak_ordering::is_lt (Qt::weak_ordering o)
+ \fn Qt::weak_ordering::is_lteq(Qt::weak_ordering o)
+ \fn Qt::weak_ordering::is_gt (Qt::weak_ordering o)
+ \fn Qt::weak_ordering::is_gteq(Qt::weak_ordering o)
+
+ \include qcompare.cpp is_eq_table
+
+ These functions are provided for compatibility with \c{std::weak_ordering}.
+*/
+
+/*!
+ \variable Qt::weak_ordering::less
+
+ Represents the result of a comparison where the left operand is less than
+ the right operand.
+*/
+
+/*!
+ \variable Qt::weak_ordering::equivalent
+
+ Represents the result of a comparison where the left operand is equivalent
+ to the right operand.
+*/
+
+/*!
+ \variable Qt::weak_ordering::greater
+
+ Represents the result of a comparison where the left operand is greater
+ than the right operand.
+*/
+
+/*!
+ \class Qt::partial_ordering
+ \inmodule QtCore
+ \brief Qt::partial_ordering represents the result of a comparison that allows
+ for unordered results.
+ \sa Qt::strong_ordering, Qt::weak_ordering, {Comparison types overview}
+ \since 6.7
+
+ A value of type Qt::partial_ordering is typically returned from a
+ three-way comparison function. Such a function compares two objects,
+ establishing whether they are ordered and, if so, their ordering. It uses
+ this return type to indicate that the ordering is partial; that is, not all
+ pairs of values are ordered.
+
+ Qt::partial_ordering has four values, represented by the following symbolic
+ constants:
+
+ \list
+ \li \l less represents that the left operand is less than the right;
+ \li \l equivalent represents that the two operands are equivalent;
+ \li \l greater represents that the left operand is greater than the right;
+ \li \l unordered represents that the two operands are \e {not ordered}.
+ \endlist
+
+ Qt::partial_ordering is idiomatically used by comparing an instance
+ against a literal zero, for instance like this:
+
+ \code
+
+ // given a, b, c, d as objects of some type that allows for a 3-way compare,
+ // and a compare function declared as follows:
+
+ Qt::partial_ordering compare(T lhs, T rhs); // defined out-of-line
+ ~~~
+
+ Qt::partial_ordering result = compare(a, b);
+ if (result < 0) {
+ // a is less than b
+ }
+
+ if (compare(c, d) >= 0) {
+ // c is greater than or equal to d
+ }
+
+ \endcode
+
+ Comparing Qt::partial_ordering::unordered against literal 0 always returns
+ a \c false result.
+*/
+
+/*!
+ \fn Qt::partial_ordering::partial_ordering(std::partial_ordering stdorder)
+
+ Constructs a Qt::partial_ordering object from \a stdorder using the following
+ rules:
+
+ \list
+ \li std::partial_ordering::less converts to \l less.
+ \li std::partial_ordering::equivalent converts to \l equivalent.
+ \li std::partial_ordering::greater converts to \l greater.
+ \li std::partial_ordering::unordered converts to \l unordered
+ \endlist
+*/
+
+/*!
+ \fn Qt::partial_ordering::operator std::partial_ordering() const
+
+ Converts this Qt::partial_ordering value to a std::partial_ordering object using
+ the following rules:
+
+ \list
+ \li \l less converts to std::partial_ordering::less.
+ \li \l equivalent converts to std::partial_ordering::equivalent.
+ \li \l greater converts to std::partial_ordering::greater.
+ \li \l unordered converts to std::partial_ordering::unordered.
+ \endlist
+*/
+
+/*!
+ \fn bool Qt::partial_ordering::operator==(Qt::partial_ordering lhs, Qt::partial_ordering rhs)
+
+ Return true if \a lhs and \a rhs represent the same result;
+ otherwise, returns false.
+*/
+
+/*!
+ \fn bool Qt::partial_ordering::operator!=(Qt::partial_ordering lhs, Qt::partial_ordering rhs)
+
+ Return true if \a lhs and \a rhs represent different results;
+ otherwise, returns true.
+*/
+
+/*!
+ \internal
+ \relates Qt::partial_ordering
+ \fn bool operator==(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator!=(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator< (Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator<=(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator> (Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator>=(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero)
+
+ \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs)
+ \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs)
+ \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs)
+ \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs)
+ \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs)
+ \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs)
+*/
+
+/*!
+ \fn Qt::partial_ordering::is_eq (Qt::partial_ordering o)
+ \fn Qt::partial_ordering::is_neq (Qt::partial_ordering o)
+ \fn Qt::partial_ordering::is_lt (Qt::partial_ordering o)
+ \fn Qt::partial_ordering::is_lteq(Qt::partial_ordering o)
+ \fn Qt::partial_ordering::is_gt (Qt::partial_ordering o)
+ \fn Qt::partial_ordering::is_gteq(Qt::partial_ordering o)
+
+ \include qcompare.cpp is_eq_table
+
+ These functions are provided for compatibility with \c{std::partial_ordering}.
+*/
+
+/*!
+ \variable Qt::partial_ordering::less
+
+ Represents the result of a comparison where the left operand is less than
+ the right operand.
+*/
+
+/*!
+ \variable Qt::partial_ordering::equivalent
+
+ Represents the result of a comparison where the two operands are equivalent.
+*/
+
+/*!
+ \variable Qt::partial_ordering::greater
+
+ Represents the result of a comparison where the left operand is greater
+ than the right operand.
+*/
+
+/*!
+ \variable Qt::partial_ordering::unordered
+
+ Represents the result of a comparison where there is no ordering
+ relationship between the two operands.
+*/
+
+/*!
+ \class QPartialOrdering
+ \inmodule QtCore
+ \brief QPartialOrdering represents the result of a comparison that allows
+ for unordered results.
+ \sa Qt::strong_ordering, Qt::weak_ordering, {Comparison types overview}
+ \since 6.0
+
+ A value of type QPartialOrdering is typically returned from a
+ three-way comparison function. Such a function compares two objects,
+ establishing whether they are ordered and, if so, their ordering. It uses
+ this return type to indicate that the ordering is partial; that is, not all
+ pairs of values are ordered.
+
+ QPartialOrdering has four values, represented by the following symbolic
+ constants:
+
+ \list
+ \li \l less represents that the left operand is less than the right;
+ \li \l equivalent represents that the two operands are equivalent;
+ \li \l greater represents that the left operand is greater than the right;
+ \li \l unordered represents that the two operands are \e {not ordered}.
+ \endlist
+
+ QPartialOrdering is idiomatically used by comparing an instance
+ against a literal zero, for instance like this:
+
+ \code
+
+ // given a, b, c, d as objects of some type that allows for a 3-way compare,
+ // and a compare function declared as follows:
+
+ QPartialOrdering compare(T lhs, T rhs); // defined out-of-line
+ ~~~
+
+ QPartialOrdering result = compare(a, b);
+ if (result < 0) {
+ // a is less than b
+ }
+
+ if (compare(c, d) >= 0) {
+ // c is greater than or equal to d
+ }
+
+ \endcode
+
+ Comparing QPartialOrdering::unordered against literal 0 always returns
+ a \c false result.
+*/
+
+/*!
+ \fn QPartialOrdering::QPartialOrdering(std::partial_ordering stdorder)
+
+ Constructs a QPartialOrdering object from \a stdorder using the following
+ rules:
+
+ \list
+ \li std::partial_ordering::less converts to \l less.
+ \li std::partial_ordering::equivalent converts to \l equivalent.
+ \li std::partial_ordering::greater converts to \l greater.
+ \li std::partial_ordering::unordered converts to \l unordered
+ \endlist
+*/
+
+/*!
+ \fn QPartialOrdering::operator std::partial_ordering() const
+
+ Converts this QPartialOrdering value to a std::partial_ordering object using
+ the following rules:
+
+ \list
+ \li \l less converts to std::partial_ordering::less.
+ \li \l equivalent converts to std::partial_ordering::equivalent.
+ \li \l greater converts to std::partial_ordering::greater.
+ \li \l unordered converts to std::partial_ordering::unordered.
+ \endlist
+*/
+
+/*!
+ \fn bool QPartialOrdering::operator==(QPartialOrdering lhs, QPartialOrdering rhs)
+
+ Return true if \a lhs and \a rhs represent the same result;
+ otherwise, returns false.
+*/
+
+/*!
+ \fn bool QPartialOrdering::operator!=(QPartialOrdering lhs, QPartialOrdering rhs)
+
+ Return true if \a lhs and \a rhs represent different results;
+ otherwise, returns true.
+*/
+
+/*!
+ \internal
+ \relates QPartialOrdering
+ \fn bool operator==(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator!=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator< (QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator<=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator> (QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero)
+ \fn bool operator>=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero)
+
+ \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs)
+ \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs)
+ \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs)
+ \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs)
+ \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs)
+ \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs)
+*/
+
+/*!
+ \fn QPartialOrdering::is_eq (QPartialOrdering o)
+ \fn QPartialOrdering::is_neq (QPartialOrdering o)
+ \fn QPartialOrdering::is_lt (QPartialOrdering o)
+ \fn QPartialOrdering::is_lteq(QPartialOrdering o)
+ \fn QPartialOrdering::is_gt (QPartialOrdering o)
+ \fn QPartialOrdering::is_gteq(QPartialOrdering o)
+
+ \since 6.7
+ \include qcompare.cpp is_eq_table
+
+ These functions are provided for compatibility with \c{std::partial_ordering}.
+*/
+
+/*!
+ \variable QPartialOrdering::less
+
+ Represents the result of a comparison where the left operand is less than
+ the right operand.
+*/
+
+/*!
+ \variable QPartialOrdering::equivalent
+
+ Represents the result of a comparison where the two operands are equivalent.
+*/
+
+/*!
+ \variable QPartialOrdering::greater
+
+ Represents the result of a comparison where the left operand is greater
+ than the right operand.
+*/
+
+/*!
+ \variable QPartialOrdering::unordered
+
+ Represents the result of a comparison where there is no ordering
+ relationship between the two operands.
+*/
+
+/*!
+ \variable QPartialOrdering::Less
+
+ Represents the result of a comparison where the left operand is less than
+ the right operand.
+*/
+
+/*!
+ \variable QPartialOrdering::Equivalent
+
+ Represents the result of a comparison where the two operands are equivalent.
+*/
+
+/*!
+ \variable QPartialOrdering::Greater
+
+ Represents the result of a comparison where the left operand is greater
+ than the right operand.
+*/
+
+/*!
+ \variable QPartialOrdering::Unordered
+
+ Represents the result of a comparison where there is no ordering
+ relationship between the two operands.
+*/
+
+/*!
+ \internal
+ \macro Q_DECLARE_EQUALITY_COMPARABLE(Type)
+ \macro Q_DECLARE_EQUALITY_COMPARABLE(LeftType, RightType)
+ \macro Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(Type)
+ \macro Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(LeftType, RightType)
+ \since 6.7
+ \relates <QtCompare>
+
+ These macros are used to generate \c {operator==()} and \c {operator!=()}.
+
+ In C++17 mode, the mixed-type overloads also generate the reversed
+ operators.
+
+ In C++20 mode, only \c {operator==()} is defined. \c {operator!=()},
+ as well as the reversed operators for mixed-type comparison, are synthesized
+ by the compiler.
+
+ The operators are implemented in terms of a helper function
+ \c {comparesEqual()}.
+ It's the user's responsibility to declare and define this function.
+
+ Consider the following example of a comparison operators declaration:
+
+ \code
+ class MyClass {
+ ...
+ private:
+ friend bool comparesEqual(const MyClass &, const MyClass &) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(MyClass)
+ };
+ \endcode
+
+ When compiled with C++17, the macro will expand into the following code:
+
+ \code
+ friend bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ friend bool operator!=(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ \endcode
+
+ When compiled with C++20, the macro will expand only into \c {operator==()}:
+
+ \code
+ friend bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ \endcode
+
+ The \c {*_LITERAL_TYPE} versions of the macros are used to generate
+ \c constexpr operators. This means that the helper \c {comparesEqual()}
+ function must also be \c constexpr.
+
+ Consider the following example of a mixed-type \c constexpr comparison
+ operators declaration:
+
+ \code
+ class MyClass {
+ ...
+ private:
+ friend constexpr bool comparesEqual(const MyClass &, int) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(MyClass, int)
+ };
+ \endcode
+
+ When compiled with C++17, the macro will expand into the following code:
+
+ \code
+ friend constexpr bool operator==(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ friend constexpr bool operator!=(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ friend constexpr bool operator==(int lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ friend constexpr bool operator!=(int lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ \endcode
+
+ When compiled with C++20, the macro expands only into \c {operator==()}:
+
+ \code
+ friend constexpr bool operator==(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ \endcode
+*/
+
+/*!
+ \internal
+ \macro Q_DECLARE_PARTIALLY_ORDERED(Type)
+ \macro Q_DECLARE_PARTIALLY_ORDERED(LeftType, RightType)
+ \macro Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(Type)
+ \macro Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(LeftType, RightType)
+ \since 6.7
+ \relates <QtCompare>
+
+ These macros are used to generate all six relational operators.
+ The operators represent
+ \l {https://en.cppreference.com/w/cpp/utility/compare/partial_ordering}
+ {partial ordering}.
+
+ These macros use respective overloads of the
+ \l {Q_DECLARE_EQUALITY_COMPARABLE} macro to generate \c {operator==()} and
+ \c {operator!=()}, and also generate the four relational operators:
+ \c {operator<()}, \c {operator>()}, \c {operator<=()}, and \c {operator>()}.
+
+ In C++17 mode, the mixed-type overloads also generate the reversed
+ operators.
+
+ In C++20 mode, only \c {operator==()} and \c {operator<=>()} are defined.
+ Other operators, as well as the reversed operators for mixed-type
+ comparison, are synthesized by the compiler.
+
+ The (in)equality operators are implemented in terms of a helper function
+ \c {comparesEqual()}. The other relational operators are implemented in
+ terms of a helper function \c {compareThreeWay()}.
+ The \c {compareThreeWay()} function \e must return an object of type
+ \l Qt::partial_ordering. It's the user's responsibility to declare and define
+ both helper functions.
+
+ Consider the following example of a comparison operators declaration:
+
+ \code
+ class MyClass {
+ ...
+ private:
+ friend bool comparesEqual(const MyClass &, const MyClass &) noexcept;
+ friend Qt::partial_ordering compareThreeWay(const MyClass &, const MyClass &) noexcept;
+ Q_DECLARE_PARTIALLY_ORDERED(MyClass)
+ };
+ \endcode
+
+ When compiled with C++17, the macro will expand into the following code:
+
+ \code
+ // operator==() and operator!=() are generated from
+ // Q_DECLARE_EQUALITY_COMPARABLE
+ friend bool operator<(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend bool operator>(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend bool operator<=(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend bool operator>=(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ \endcode
+
+ When compiled with C++20, the macro will expand into \c {operator==()} and
+ \c {operator<=>()}:
+
+ \code
+ friend bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ friend std::partial_ordering
+ operator<=>(const MyClass &lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ \endcode
+
+ The \c {*_LITERAL_TYPE} versions of the macros are used to generate
+ \c constexpr operators. This means that the helper \c {comparesEqual()} and
+ \c {compareThreeWay()} functions must also be \c constexpr.
+
+ Consider the following example of a mixed-type \c constexpr comparison
+ operators declaration:
+
+ \code
+ class MyClass {
+ ...
+ private:
+ friend constexpr bool comparesEqual(const MyClass &, int) noexcept;
+ friend constexpr Qt::partial_ordering compareThreeWay(const MyClass &, int) noexcept;
+ Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(MyClass, int)
+ };
+ \endcode
+
+ When compiled with C++17, the macro will expand into the following code:
+
+ \code
+ // operator==(), operator!=(), and their reversed versions are generated
+ // from Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE
+ friend constexpr bool operator<(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator>(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator<=(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator>=(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator<(int lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator>(int lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator<=(int lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ friend constexpr bool operator>=(int lhs, const MyClass &rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ \endcode
+
+ When compiled with C++20, the macro will expand into \c {operator==()} and
+ \c {operator<=>()}:
+
+ \code
+ friend constexpr bool operator==(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses comparesEqual()
+ }
+ friend constexpr std::partial_ordering
+ operator<=>(const MyClass &lhs, int rhs) noexcept
+ {
+ // inline implementation which uses compareThreeWay()
+ }
+ \endcode
+
+ \sa Q_DECLARE_EQUALITY_COMPARABLE, Q_DECLARE_WEAKLY_ORDERED,
+ Q_DECLARE_STRONGLY_ORDERED
+*/
+
+/*!
+ \internal
+ \macro Q_DECLARE_WEAKLY_ORDERED(Type)
+ \macro Q_DECLARE_WEAKLY_ORDERED(LeftType, RightType)
+ \macro Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(Type)
+ \macro Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(LeftType, RightType)
+ \since 6.7
+ \relates <QtCompare>
+
+ These macros behave similarly to the
+ \l {Q_DECLARE_PARTIALLY_ORDERED} overloads, but represent
+ \l {https://en.cppreference.com/w/cpp/utility/compare/weak_ordering}
+ {weak ordering}.
+
+ The (in)equality operators are implemented in terms of a helper function
+ \c {comparesEqual()}. The other relational operators are implemented in
+ terms of a helper function \c {compareThreeWay()}.
+ The \c {compareThreeWay()} function \e must return an object of type
+ \l Qt::weak_ordering. It's the user's responsibility to declare and define both
+ helper functions.
+
+ The \c {*_LITERAL_TYPE} overloads are used to generate \c constexpr
+ operators. This means that the helper \c {comparesEqual()} and
+ \c {compareThreeWay()} functions must also be \c constexpr.
+
+ See \l {Q_DECLARE_PARTIALLY_ORDERED} for usage examples.
+
+ \sa Q_DECLARE_PARTIALLY_ORDERED, Q_DECLARE_STRONGLY_ORDERED,
+ Q_DECLARE_EQUALITY_COMPARABLE
+*/
+
+/*!
+ \internal
+ \macro Q_DECLARE_STRONGLY_ORDERED(Type)
+ \macro Q_DECLARE_STRONGLY_ORDERED(LeftType, RightType)
+ \macro Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(Type)
+ \macro Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(LeftType, RightType)
+ \since 6.7
+ \relates <QtCompare>
+
+ These macros behave similarly to the
+ \l {Q_DECLARE_PARTIALLY_ORDERED} overloads, but represent
+ \l {https://en.cppreference.com/w/cpp/utility/compare/strong_ordering}
+ {strong ordering}.
+
+ The (in)equality operators are implemented in terms of a helper function
+ \c {comparesEqual()}. The other relational operators are implemented in
+ terms of a helper function \c {compareThreeWay()}.
+ The \c {compareThreeWay()} function \e must return an object of type
+ \l Qt::strong_ordering. It's the user's responsibility to declare and define
+ both helper functions.
+
+ The \c {*_LITERAL_TYPE} overloads are used to generate \c constexpr
+ operators. This means that the helper \c {comparesEqual()} and
+ \c {compareThreeWay()} functions must also be \c constexpr.
+
+ See \l {Q_DECLARE_PARTIALLY_ORDERED} for usage examples.
+
+ \sa Q_DECLARE_PARTIALLY_ORDERED, Q_DECLARE_WEAKLY_ORDERED,
+ Q_DECLARE_EQUALITY_COMPARABLE
+*/
+
+/*!
+ \internal
+ \macro Q_DECLARE_EQUALITY_COMPARABLE(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_PARTIALLY_ORDERED(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_WEAKLY_ORDERED(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_STRONGLY_ORDERED(LeftType, RightType, Attributes)
+ \macro Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(LeftType, RightType, Attributes)
+ \since 6.8
+ \relates <QtCompare>
+
+ These macros behave like their two-argument versions, but allow
+ specification of C++ attributes to add before every generated relational
+ operator.
+
+ As an example, the \c Attributes parameter can be used in Qt to pass
+ the \c QT_ASCII_CAST_WARN marco (whose expansion can mark the function as
+ deprecated) when implementing comparison of encoding-aware string types
+ with C-style strings or byte arrays.
+*/
+
+/*!
+ \fn template <typename LeftInt, typename RightInt, Qt::if_integral<LeftInt> = true, Qt::if_integral<RightInt> = true> auto Qt::compareThreeWay(LeftInt lhs, RightInt rhs)
+ \since 6.7
+ \relates <QtCompare>
+ \overload
+
+ Implements three-way comparison of integral types.
+
+ \note This function participates in overload resolution only if both
+ \c LeftInt and \c RightInt are built-in integral types.
+
+ Returns \c {lhs <=> rhs}, provided \c LeftInt and \c RightInt are built-in
+ integral types. Unlike \c {operator<=>()}, this function template is also
+ available in C++17. See
+ \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison}
+ {cppreference} for more details.
+
+ This function can also be used in custom \c {compareThreeWay()} functions,
+ when ordering members of a custom class represented by built-in types:
+
+ \code
+ class MyClass {
+ public:
+ ...
+ private:
+ int value;
+ ...
+ friend Qt::strong_ordering
+ compareThreeWay(const MyClass &lhs, const MyClass &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.value, rhs.value); }
+ Q_DECLARE_STRONGLY_ORDERED(MyClass)
+ };
+ \endcode
+
+ Returns an instance of \l Qt::strong_ordering that represents the relation
+ between \a lhs and \a rhs.
+*/
+
+/*!
+ \fn template <typename LeftFloat, typename RightFloat, Qt::if_floating_point<LeftFloat> = true, Qt::if_floating_point<RightFloat> = true> auto Qt::compareThreeWay(LeftFloat lhs, RightFloat rhs)
+ \since 6.7
+ \relates <QtCompare>
+ \overload
+
+ Implements three-way comparison of floating point types.
+
+ \note This function participates in overload resolution only if both
+ \c LeftFloat and \c RightFloat are built-in floating-point types.
+
+ Returns \c {lhs <=> rhs}, provided \c LeftFloat and \c RightFloat are
+ built-in floating-point types. Unlike \c {operator<=>()}, this function
+ template is also available in C++17. See
+ \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison}
+ {cppreference} for more details.
+
+ This function can also be used in custom \c {compareThreeWay()} functions,
+ when ordering members of a custom class represented by built-in types:
+
+ \code
+ class MyClass {
+ public:
+ ...
+ private:
+ double value;
+ ...
+ friend Qt::partial_ordering
+ compareThreeWay(const MyClass &lhs, const MyClass &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.value, rhs.value); }
+ Q_DECLARE_PARTIALLY_ORDERED(MyClass)
+ };
+ \endcode
+
+ Returns an instance of \l Qt::partial_ordering that represents the relation
+ between \a lhs and \a rhs. If \a lhs or \a rhs is not a number (NaN),
+ \l Qt::partial_ordering::unordered is returned.
+*/
+
+/*!
+ \fn template <typename IntType, typename FloatType, Qt::if_integral<IntType> = true, Qt::if_floating_point<FloatType> = true> auto Qt::compareThreeWay(IntType lhs, FloatType rhs)
+ \since 6.7
+ \relates <QtCompare>
+ \overload
+
+ Implements three-way comparison of integral and floating point types.
+
+ \note This function participates in overload resolution only if \c IntType
+ is a built-in integral type and \c FloatType is a built-in floating-point
+ type.
+
+ This function converts \a lhs to \c FloatType and calls the overload for
+ floating-point types.
+
+ Returns an instance of \l Qt::partial_ordering that represents the relation
+ between \a lhs and \a rhs. If \a rhs is not a number (NaN),
+ \l Qt::partial_ordering::unordered is returned.
+*/
+
+/*!
+ \fn template <typename FloatType, typename IntType, Qt::if_floating_point<FloatType> = true, Qt::if_integral<IntType> = true> auto Qt::compareThreeWay(FloatType lhs, IntType rhs)
+ \since 6.7
+ \relates <QtCompare>
+ \overload
+
+ Implements three-way comparison of floating point and integral types.
+
+ \note This function participates in overload resolution only if \c FloatType
+ is a built-in floating-point type and \c IntType is a built-in integral
+ type.
+
+ This function converts \a rhs to \c FloatType and calls the overload for
+ floating-point types.
+
+ Returns an instance of \l Qt::partial_ordering that represents the relation
+ between \a lhs and \a rhs. If \a lhs is not a number (NaN),
+ \l Qt::partial_ordering::unordered is returned.
+*/
+
+/*!
+ \fn template <typename LeftType, typename RightType, Qt::if_compatible_pointers<LeftType, RightType> = true> Qt::compareThreeWay(const LeftType *lhs, const RightType *rhs)
+ \since 6.7
+ \relates <QtCompare>
+ \overload
+
+ Implements three-way comparison of pointers.
+
+ \note This function participates in overload resolution if \c LeftType and
+ \c RightType are the same type, or base and derived types. It is also used
+ to compare any pointer to \c {std::nullptr_t}.
+
+ Returns an instance of \l Qt::strong_ordering that represents the relation
+ between \a lhs and \a rhs.
+*/
+
+/*!
+ \fn template <class Enum, Qt::if_enum<Enum> = true> Qt::compareThreeWay(Enum lhs, Enum rhs)
+ \since 6.7
+ \relates <QtCompare>
+ \overload
+
+ Implements three-way comparison of enum types.
+
+ \note This function participates in overload resolution only if \c Enum
+ is an enum type.
+
+ This function converts \c Enum to its underlying type and calls the
+ overload for integral types.
+
+ Returns an instance of \l Qt::strong_ordering that represents the relation
+ between \a lhs and \a rhs.
+*/
+
+/*!
+ \fn template <typename LeftType, typename RightType> qCompareThreeWay(const LeftType &lhs, const RightType &rhs)
+ \since 6.7
+ \relates <QtCompare>
+
+ Performs the three-way comparison on \a lhs and \a rhs and returns one of
+ the Qt ordering types as a result. This function is available for both
+ C++17 and C++20.
+
+ The actual returned type depends on \c LeftType and \c RightType.
+
+ \note This function template is only available when \c {compareThreeWay()}
+ is implemented for the \c {(LeftType, RightType)} pair or the reversed
+ \c {(RightType, LeftType)} pair.
+
+ This method is equivalent to
+
+ \code
+ using Qt::compareThreeWay;
+ return compareThreeWay(lhs, rhs);
+ \endcode
+
+ where \c {Qt::compareThreeWay} is the Qt implementation of three-way
+ comparison for built-in types.
+
+ The free \c {compareThreeWay} functions should provide three-way comparison
+ for custom types. The functions should return one of the Qt ordering types.
+
+ Qt provides \c {compareThreeWay} implementation for some of its types.
+
+ \note \b {Do not} re-implement \c {compareThreeWay()} for Qt types, as more
+ Qt types will get support for it in future Qt releases.
+
+ Use this function primarly in generic code, when you know nothing about
+ \c LeftType and \c RightType.
+
+ If you know the types, use
+
+ \list
+ \li \c {Qt::compareThreeWay} for built-in types
+ \li \c {compareThreeWay} for custom types
+ \endlist
+
+ Use \c {operator<=>()} directly in code that will only be compiled with
+ C++20 or later.
+
+ \sa Qt::partial_ordering, Qt::weak_ordering, Qt::strong_ordering
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h
new file mode 100644
index 0000000000..9dd244c8f9
--- /dev/null
+++ b/src/corelib/global/qcompare.h
@@ -0,0 +1,891 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOMPARE_H
+#define QCOMPARE_H
+
+#if 0
+#pragma qt_class(QtCompare)
+#endif
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qcompare_impl.h>
+
+#ifdef __cpp_lib_bit_cast
+#include <bit>
+#endif
+#ifdef __cpp_lib_three_way_comparison
+#include <compare>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+using CompareUnderlyingType = qint8;
+
+// [cmp.categories.pre] / 1
+enum class Ordering : CompareUnderlyingType
+{
+ Equal = 0,
+ Equivalent = Equal,
+ Less = -1,
+ Greater = 1
+};
+
+enum class Uncomparable : CompareUnderlyingType
+{
+ Unordered =
+ #if defined(_LIBCPP_VERSION) // libc++
+ -127
+ #elif defined(__GLIBCXX__) // libstdc++
+ 2
+ #else // assume MSSTL
+ -128
+ #endif
+};
+
+} // namespace QtPrivate
+
+namespace QtOrderingPrivate {
+
+template <typename O>
+constexpr O reversed(O o) noexcept
+{
+ // https://eel.is/c++draft/cmp.partialord#5
+ return is_lt(o) ? O::greater :
+ is_gt(o) ? O::less :
+ /*else*/ o ;
+}
+
+} // namespace QtOrderingPrivate
+
+namespace Qt {
+
+class partial_ordering
+{
+public:
+ static const partial_ordering less;
+ static const partial_ordering equivalent;
+ static const partial_ordering greater;
+ static const partial_ordering unordered;
+
+ friend constexpr bool operator==(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order != 0; }
+
+ friend constexpr bool operator< (partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::partial_ordering
+ operator<=>(partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.partialord#4
+
+ friend constexpr std::partial_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, partial_ordering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT partial_ordering(std::partial_ordering stdorder) noexcept
+ {
+ if (stdorder == std::partial_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::partial_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::partial_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ else if (stdorder == std::partial_ordering::unordered)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered);
+ }
+
+ constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept
+ {
+ static_assert(sizeof(*this) == sizeof(std::partial_ordering));
+#ifdef __cpp_lib_bit_cast
+ return std::bit_cast<std::partial_ordering>(*this);
+#else
+ using O = QtPrivate::Ordering;
+ using U = QtPrivate::Uncomparable;
+ using R = std::partial_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ case qToUnderlying(U::Unordered): return R::unordered;
+ }
+ Q_UNREACHABLE_RETURN(R::unordered);
+#endif // __cpp_lib_bit_cast
+ }
+
+ friend constexpr bool operator==(partial_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(partial_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs == static_cast<std::partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs != static_cast<std::partial_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+private:
+ friend class weak_ordering;
+ friend class strong_ordering;
+
+ constexpr explicit partial_ordering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+ constexpr explicit partial_ordering(QtPrivate::Uncomparable order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (partial_ordering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (partial_ordering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (partial_ordering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(partial_ordering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (partial_ordering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(partial_ordering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ // instead of the exposition only is_ordered member in [cmp.partialord],
+ // use a private function
+ constexpr bool isOrdered() const noexcept
+ { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered); }
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr partial_ordering partial_ordering::less(QtPrivate::Ordering::Less);
+inline constexpr partial_ordering partial_ordering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr partial_ordering partial_ordering::greater(QtPrivate::Ordering::Greater);
+inline constexpr partial_ordering partial_ordering::unordered(QtPrivate::Uncomparable::Unordered);
+
+class weak_ordering
+{
+public:
+ static const weak_ordering less;
+ static const weak_ordering equivalent;
+ static const weak_ordering greater;
+
+ constexpr Q_IMPLICIT operator partial_ordering() const noexcept
+ { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
+
+ friend constexpr bool operator==(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order != 0; }
+
+ friend constexpr bool operator< (weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::weak_ordering
+ operator<=>(weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.weakord#5
+
+ friend constexpr std::weak_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, weak_ordering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+ friend constexpr bool operator==(weak_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<partial_ordering>(rhs); }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT weak_ordering(std::weak_ordering stdorder) noexcept
+ {
+ if (stdorder == std::weak_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::weak_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::weak_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ }
+
+ constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept
+ {
+ static_assert(sizeof(*this) == sizeof(std::weak_ordering));
+#ifdef __cpp_lib_bit_cast
+ return std::bit_cast<std::weak_ordering>(*this);
+#else
+ using O = QtPrivate::Ordering;
+ using R = std::weak_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ }
+ Q_UNREACHABLE_RETURN(R::equivalent);
+#endif // __cpp_lib_bit_cast
+ }
+
+ friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(weak_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(weak_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::strong_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::strong_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<std::weak_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+private:
+ friend class strong_ordering;
+
+ constexpr explicit weak_ordering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (weak_ordering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (weak_ordering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (weak_ordering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(weak_ordering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (weak_ordering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(weak_ordering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr weak_ordering weak_ordering::less(QtPrivate::Ordering::Less);
+inline constexpr weak_ordering weak_ordering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr weak_ordering weak_ordering::greater(QtPrivate::Ordering::Greater);
+
+class strong_ordering
+{
+public:
+ static const strong_ordering less;
+ static const strong_ordering equivalent;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+
+ constexpr Q_IMPLICIT operator partial_ordering() const noexcept
+ { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
+
+ constexpr Q_IMPLICIT operator weak_ordering() const noexcept
+ { return weak_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
+
+ friend constexpr bool operator==(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order != 0; }
+
+ friend constexpr bool operator< (strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::strong_ordering
+ operator<=>(strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.strongord#6
+
+ friend constexpr std::strong_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, strong_ordering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+ friend constexpr bool operator==(strong_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator==(partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<partial_ordering>(rhs); }
+
+ friend constexpr bool operator==(strong_ordering lhs, weak_ordering rhs) noexcept
+ { return static_cast<weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, weak_ordering rhs) noexcept
+ { return static_cast<weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator==(weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<weak_ordering>(rhs); }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT strong_ordering(std::strong_ordering stdorder) noexcept
+ {
+ if (stdorder == std::strong_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::strong_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::strong_ordering::equal)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equal);
+ else if (stdorder == std::strong_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ }
+
+ constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept
+ {
+ static_assert(sizeof(*this) == sizeof(std::strong_ordering));
+#ifdef __cpp_lib_bit_cast
+ return std::bit_cast<std::strong_ordering>(*this);
+#else
+ using O = QtPrivate::Ordering;
+ using R = std::strong_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equal): return R::equal;
+ }
+ Q_UNREACHABLE_RETURN(R::equal);
+#endif // __cpp_lib_bit_cast
+ }
+
+ friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(strong_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(strong_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<std::strong_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+ private:
+ constexpr explicit strong_ordering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (strong_ordering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (strong_ordering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (strong_ordering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(strong_ordering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (strong_ordering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(strong_ordering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr strong_ordering strong_ordering::less(QtPrivate::Ordering::Less);
+inline constexpr strong_ordering strong_ordering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr strong_ordering strong_ordering::equal(QtPrivate::Ordering::Equal);
+inline constexpr strong_ordering strong_ordering::greater(QtPrivate::Ordering::Greater);
+
+} // namespace Qt
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+// This is intentionally included after Qt::*_ordering types and before
+// qCompareThreeWay. Do not change!
+#include <QtCore/qcomparehelpers.h>
+
+QT_END_INCLUDE_NAMESPACE
+
+namespace QtPrivate {
+
+namespace CompareThreeWayTester {
+
+ using Qt::compareThreeWay;
+
+ // Check if compareThreeWay is implemented for the (LT, RT) argument
+ // pair.
+ template <typename LT, typename RT, typename = void>
+ constexpr bool hasCompareThreeWay = false;
+
+ template <typename LT, typename RT>
+ constexpr bool hasCompareThreeWay<
+ LT, RT, std::void_t<decltype(compareThreeWay(std::declval<LT>(), std::declval<RT>()))>
+ > = true;
+
+ // Check if the operation is noexcept. We have two different overloads,
+ // depending on the available compareThreeWay() implementation.
+ // Both are declared, but not implemented. To be used only in unevaluated
+ // context.
+
+ template <typename LT, typename RT,
+ std::enable_if_t<hasCompareThreeWay<LT, RT>, bool> = true>
+ constexpr bool compareThreeWayNoexcept() noexcept
+ { return noexcept(compareThreeWay(std::declval<LT>(), std::declval<RT>())); }
+
+ template <typename LT, typename RT,
+ std::enable_if_t<!hasCompareThreeWay<LT, RT> && hasCompareThreeWay<RT, LT>,
+ bool> = true>
+ constexpr bool compareThreeWayNoexcept() noexcept
+ { return noexcept(compareThreeWay(std::declval<RT>(), std::declval<LT>())); }
+
+} // namespace CompareThreeWayTester
+
+} // namespace QtPrivate
+
+#if defined(Q_QDOC)
+
+template <typename LeftType, typename RightType>
+auto qCompareThreeWay(const LeftType &lhs, const RightType &rhs);
+
+#else
+
+template <typename LT, typename RT,
+ std::enable_if_t<QtPrivate::CompareThreeWayTester::hasCompareThreeWay<LT, RT>
+ || QtPrivate::CompareThreeWayTester::hasCompareThreeWay<RT, LT>,
+ bool> = true>
+auto qCompareThreeWay(const LT &lhs, const RT &rhs)
+ noexcept(QtPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>())
+{
+ using Qt::compareThreeWay;
+ if constexpr (QtPrivate::CompareThreeWayTester::hasCompareThreeWay<LT, RT>) {
+ return compareThreeWay(lhs, rhs);
+ } else {
+ const auto retval = compareThreeWay(rhs, lhs);
+ return QtOrderingPrivate::reversed(retval);
+ }
+}
+
+#endif // defined(Q_QDOC)
+
+//
+// Legacy QPartialOrdering
+//
+
+namespace QtPrivate {
+enum class LegacyUncomparable : CompareUnderlyingType
+{
+ Unordered = -127
+};
+}
+
+// [cmp.partialord]
+class QPartialOrdering
+{
+public:
+ static const QPartialOrdering Less;
+ static const QPartialOrdering Equivalent;
+ static const QPartialOrdering Greater;
+ static const QPartialOrdering Unordered;
+
+ static const QPartialOrdering less;
+ static const QPartialOrdering equivalent;
+ static const QPartialOrdering greater;
+ static const QPartialOrdering unordered;
+
+ friend constexpr bool operator==(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order != 0; }
+
+ friend constexpr bool operator< (QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::partial_ordering
+ operator<=>(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.partialord#4
+
+ friend constexpr std::partial_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(QPartialOrdering lhs, QPartialOrdering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs, QPartialOrdering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+ constexpr Q_IMPLICIT QPartialOrdering(Qt::partial_ordering order) noexcept
+ : m_order{} // == equivalent
+ {
+ if (order == Qt::partial_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (order == Qt::partial_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ else if (order == Qt::partial_ordering::unordered)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered);
+ }
+
+ constexpr Q_IMPLICIT QPartialOrdering(Qt::weak_ordering stdorder) noexcept
+ : QPartialOrdering(Qt::partial_ordering{stdorder}) {}
+
+ constexpr Q_IMPLICIT QPartialOrdering(Qt::strong_ordering stdorder) noexcept
+ : QPartialOrdering(Qt::partial_ordering{stdorder}) {}
+
+ constexpr Q_IMPLICIT operator Qt::partial_ordering() const noexcept
+ {
+ using O = QtPrivate::Ordering;
+ using U = QtPrivate::LegacyUncomparable;
+ using R = Qt::partial_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ case qToUnderlying(U::Unordered): return R::unordered;
+ }
+ // GCC 8.x does not treat __builtin_unreachable() as constexpr
+#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
+ // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
+ Q_UNREACHABLE();
+#endif
+ return R::unordered;
+ }
+
+ friend constexpr bool operator==(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept
+ { Qt::partial_ordering qt = lhs; return qt == rhs; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept
+ { Qt::partial_ordering qt = lhs; return qt != rhs; }
+
+ friend constexpr bool operator==(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { Qt::partial_ordering qt = rhs; return lhs == qt; }
+
+ friend constexpr bool operator!=(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { Qt::partial_ordering qt = rhs; return lhs != qt; }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT QPartialOrdering(std::partial_ordering stdorder) noexcept
+ {
+ if (stdorder == std::partial_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::partial_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::partial_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ else if (stdorder == std::partial_ordering::unordered)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered);
+ }
+
+ constexpr Q_IMPLICIT QPartialOrdering(std::weak_ordering stdorder) noexcept
+ : QPartialOrdering(std::partial_ordering(stdorder)) {}
+
+ constexpr Q_IMPLICIT QPartialOrdering(std::strong_ordering stdorder) noexcept
+ : QPartialOrdering(std::partial_ordering(stdorder)) {}
+
+ constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept
+ {
+ using O = QtPrivate::Ordering;
+ using U = QtPrivate::LegacyUncomparable;
+ using R = std::partial_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ case qToUnderlying(U::Unordered): return R::unordered;
+ }
+ Q_UNREACHABLE_RETURN(R::unordered);
+ }
+
+ friend constexpr bool operator==(QPartialOrdering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { return lhs == static_cast<std::partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { return lhs != static_cast<std::partial_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+private:
+ constexpr explicit QPartialOrdering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+ constexpr explicit QPartialOrdering(QtPrivate::LegacyUncomparable order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (QPartialOrdering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (QPartialOrdering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (QPartialOrdering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(QPartialOrdering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (QPartialOrdering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(QPartialOrdering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ // instead of the exposition only is_ordered member in [cmp.partialord],
+ // use a private function
+ constexpr bool isOrdered() const noexcept
+ { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); }
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr QPartialOrdering QPartialOrdering::Less(QtPrivate::Ordering::Less);
+inline constexpr QPartialOrdering QPartialOrdering::Equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr QPartialOrdering QPartialOrdering::Greater(QtPrivate::Ordering::Greater);
+inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::LegacyUncomparable::Unordered);
+
+inline constexpr QPartialOrdering QPartialOrdering::less(QtPrivate::Ordering::Less);
+inline constexpr QPartialOrdering QPartialOrdering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr QPartialOrdering QPartialOrdering::greater(QtPrivate::Ordering::Greater);
+inline constexpr QPartialOrdering QPartialOrdering::unordered(QtPrivate::LegacyUncomparable::Unordered);
+
+QT_END_NAMESPACE
+
+#endif // QCOMPARE_H
diff --git a/src/corelib/global/qcompare_impl.h b/src/corelib/global/qcompare_impl.h
new file mode 100644
index 0000000000..c52417fcec
--- /dev/null
+++ b/src/corelib/global/qcompare_impl.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOMPARE_IMPL_H
+#define QCOMPARE_IMPL_H
+
+#if 0
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qcompilerdetection.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+// [cmp.categories.pre] / 3, but using a safe bool trick
+// and also rejecting std::nullptr_t (unlike the example)
+class CompareAgainstLiteralZero {
+public:
+ using SafeZero = void (CompareAgainstLiteralZero::*)();
+ Q_IMPLICIT constexpr CompareAgainstLiteralZero(SafeZero) noexcept {}
+
+ template <typename T, std::enable_if_t<std::is_null_pointer_v<T>, bool> = true>
+ CompareAgainstLiteralZero(T) = delete;
+};
+
+} // namespace QtPrivate
+
+QT_END_NAMESPACE
+
+#endif // QCOMPARE_IMPL_H
diff --git a/src/corelib/global/qcomparehelpers.h b/src/corelib/global/qcomparehelpers.h
new file mode 100644
index 0000000000..97c972bfa7
--- /dev/null
+++ b/src/corelib/global/qcomparehelpers.h
@@ -0,0 +1,567 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOMPARE_H
+#error "Do not include qcomparehelpers.h directly. Use qcompare.h instead."
+#endif
+
+#ifndef QCOMPAREHELPERS_H
+#define QCOMPAREHELPERS_H
+
+#if 0
+#pragma qt_no_master_include
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qoverload.h>
+#include <QtCore/qttypetraits.h>
+#include <QtCore/qtypes.h>
+
+#ifdef __cpp_lib_three_way_comparison
+#include <compare>
+#endif
+#include <QtCore/q20type_traits.h>
+
+#include <functional> // std::less
+
+QT_BEGIN_NAMESPACE
+
+class QPartialOrdering;
+
+namespace QtOrderingPrivate {
+#ifdef __cpp_lib_three_way_comparison
+
+template <typename QtOrdering> struct StdOrdering;
+template <typename StdOrdering> struct QtOrdering;
+
+#define QT_STD_MAP(x) \
+ template <> struct StdOrdering< Qt::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
+ template <> struct StdOrdering<std::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
+ template <> struct QtOrdering<std::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
+ template <> struct QtOrdering< Qt::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
+ /* end */
+QT_STD_MAP(partial)
+QT_STD_MAP(weak)
+QT_STD_MAP(strong)
+#undef QT_STD_MAP
+
+template <> struct StdOrdering<QPartialOrdering> : q20::type_identity<std::partial_ordering> {};
+template <> struct QtOrdering<QPartialOrdering> : q20::type_identity< Qt::partial_ordering> {};
+
+template <typename In> constexpr auto to_std(In in) noexcept
+ -> typename QtOrderingPrivate::StdOrdering<In>::type
+{ return in; }
+
+template <typename In> constexpr auto to_Qt(In in) noexcept
+ -> typename QtOrderingPrivate::QtOrdering<In>::type
+{ return in; }
+
+#endif // __cpp_lib_three_way_comparison
+} // namespace QtOrderingPrivate
+
+/*
+ For all the macros these parameter names are used:
+ * LeftType - the type of the left operand of the comparison
+ * RightType - the type of the right operand of the comparison
+ * Constexpr - must be either constexpr or empty. Defines whether the
+ operator is constexpr or not
+ * Attributes - an optional list of attributes. For example, pass
+ \c QT_ASCII_CAST_WARN when defining comparisons between
+ C-style string and an encoding-aware string type.
+
+ The macros require two helper functions. For operators to be constexpr,
+ these must be constexpr, too. Additionally, other attributes (like
+ Q_<Module>_EXPORT, Q_DECL_CONST_FUNCTION, etc) can be applied to them.
+ Aside from that, their declaration should match:
+ bool comparesEqual(LeftType, RightType) noexcept;
+ ReturnType compareThreeWay(LeftType, RightType) noexcept;
+
+ The ReturnType can be one of Qt::{partial,weak,strong}_ordering. The actual
+ type depends on the macro being used.
+ It makes sense to define the helper functions as hidden friends of the
+ class, so that they could be found via ADL, and don't participate in
+ unintended implicit conversions.
+*/
+
+// Seems that qdoc uses C++20 even when Qt is compiled in C++17 mode.
+// Or at least it defines __cpp_lib_three_way_comparison.
+// Let qdoc see only the C++17 operators for now, because that's what our docs
+// currently describe.
+#if defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC)
+// C++20 - provide operator==() for equality, and operator<=>() for ordering
+
+#define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(comparesEqual(lhs, rhs))) \
+ { return comparesEqual(lhs, rhs); }
+
+#define QT_DECLARE_3WAY_HELPER_STRONG(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr std::strong_ordering \
+ operator<=>(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { \
+ return compareThreeWay(lhs, rhs); \
+ }
+
+#define QT_DECLARE_3WAY_HELPER_WEAK(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr std::weak_ordering \
+ operator<=>(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { \
+ return compareThreeWay(lhs, rhs); \
+ }
+
+#define QT_DECLARE_3WAY_HELPER_PARTIAL(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr std::partial_ordering \
+ operator<=>(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { \
+ return compareThreeWay(lhs, rhs); \
+ }
+
+#define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingType, LeftType, RightType, Constexpr, \
+ Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_3WAY_HELPER_ ## OrderingType (LeftType, RightType, Constexpr, Attributes)
+
+#ifdef Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
+
+// define reversed versions of the operators manually, because buggy MSVC versions do not do it
+#define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(comparesEqual(rhs, lhs))) \
+ { return comparesEqual(rhs, lhs); }
+
+#define QT_DECLARE_REVERSED_3WAY_HELPER_STRONG(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr std::strong_ordering \
+ operator<=>(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { \
+ const auto r = compareThreeWay(rhs, lhs); \
+ if (is_gt(r)) return std::strong_ordering::less; \
+ if (is_lt(r)) return std::strong_ordering::greater; \
+ return r; \
+ }
+
+#define QT_DECLARE_REVERSED_3WAY_HELPER_WEAK(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr std::weak_ordering \
+ operator<=>(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { \
+ const auto r = compareThreeWay(rhs, lhs); \
+ if (is_gt(r)) return std::weak_ordering::less; \
+ if (is_lt(r)) return std::weak_ordering::greater; \
+ return r; \
+ }
+
+#define QT_DECLARE_REVERSED_3WAY_HELPER_PARTIAL(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr std::partial_ordering \
+ operator<=>(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { \
+ const auto r = compareThreeWay(rhs, lhs); \
+ if (is_gt(r)) return std::partial_ordering::less; \
+ if (is_lt(r)) return std::partial_ordering::greater; \
+ return r; \
+ }
+
+#define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
+ Constexpr, Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_REVERSED_3WAY_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, Attributes)
+
+#else
+
+// dummy macros for C++17 compatibility, reversed operators are generated by the compiler
+#define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Attributes)
+#define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
+ Constexpr, Attributes)
+
+#endif // Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
+
+#else
+// C++17 - provide operator==() and operator!=() for equality,
+// and all 4 comparison operators for ordering
+
+#define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(comparesEqual(lhs, rhs))) \
+ { return comparesEqual(lhs, rhs); } \
+ Attributes \
+ friend Constexpr bool operator!=(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(comparesEqual(lhs, rhs))) \
+ { return !comparesEqual(lhs, rhs); }
+
+// Helpers for reversed comparison, using the existing comparesEqual() function.
+#define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ Attributes \
+ friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(comparesEqual(rhs, lhs))) \
+ { return comparesEqual(rhs, lhs); } \
+ Attributes \
+ friend Constexpr bool operator!=(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(comparesEqual(rhs, lhs))) \
+ { return !comparesEqual(rhs, lhs); }
+
+#define QT_DECLARE_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr, \
+ Attributes) \
+ Attributes \
+ friend Constexpr bool operator<(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { return is_lt(compareThreeWay(lhs, rhs)); } \
+ Attributes \
+ friend Constexpr bool operator>(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { return is_gt(compareThreeWay(lhs, rhs)); } \
+ Attributes \
+ friend Constexpr bool operator<=(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { return is_lteq(compareThreeWay(lhs, rhs)); } \
+ Attributes \
+ friend Constexpr bool operator>=(LeftType const &lhs, RightType const &rhs) \
+ noexcept(noexcept(compareThreeWay(lhs, rhs))) \
+ { return is_gteq(compareThreeWay(lhs, rhs)); }
+
+#define QT_DECLARE_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, Constexpr, \
+ Attributes)
+
+#define QT_DECLARE_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, Constexpr, \
+ Attributes)
+
+#define QT_DECLARE_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, Constexpr, \
+ Attributes)
+
+#define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingString, LeftType, RightType, Constexpr, \
+ Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, Attributes)
+
+// Helpers for reversed ordering, using the existing compareThreeWay() function.
+#define QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr, \
+ Attributes) \
+ Attributes \
+ friend Constexpr bool operator<(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { return is_gt(compareThreeWay(rhs, lhs)); } \
+ Attributes \
+ friend Constexpr bool operator>(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { return is_lt(compareThreeWay(rhs, lhs)); } \
+ Attributes \
+ friend Constexpr bool operator<=(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { return is_gteq(compareThreeWay(rhs, lhs)); } \
+ Attributes \
+ friend Constexpr bool operator>=(RightType const &lhs, LeftType const &rhs) \
+ noexcept(noexcept(compareThreeWay(rhs, lhs))) \
+ { return is_lteq(compareThreeWay(rhs, lhs)); }
+
+#define QT_DECLARE_REVERSED_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, \
+ Constexpr, Attributes)
+
+#define QT_DECLARE_REVERSED_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, \
+ Constexpr, Attributes)
+
+#define QT_DECLARE_REVERSED_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, \
+ Constexpr, Attributes)
+
+#define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
+ Constexpr, Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Attributes) \
+ QT_DECLARE_REVERSED_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, \
+ Attributes)
+
+#endif // __cpp_lib_three_way_comparison
+
+/* Public API starts here */
+
+// Equality operators
+#define QT_DECLARE_EQUALITY_COMPARABLE_1(Type) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, /* non-constexpr */, /* no attributes */)
+
+#define QT_DECLARE_EQUALITY_COMPARABLE_2(LeftType, RightType) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \
+ /* no attributes */) \
+ QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \
+ /* no attributes */)
+
+#define QT_DECLARE_EQUALITY_COMPARABLE_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \
+ Attributes)
+
+#define Q_DECLARE_EQUALITY_COMPARABLE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE, __VA_ARGS__)
+
+#define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_1(Type) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, constexpr, /* no attributes */)
+
+#define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_2(LeftType, RightType) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr, /* no attributes */) \
+ QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr, \
+ /* no attributes */)
+
+#define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr, Attributes) \
+ QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr, Attributes)
+
+#define Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE, __VA_ARGS__)
+
+// Partial ordering operators
+#define QT_DECLARE_PARTIALLY_ORDERED_1(Type) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, /* non-constexpr */, \
+ /* no attributes */)
+
+#define QT_DECLARE_PARTIALLY_ORDERED_2(LeftType, RightType) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \
+ /* no attributes */) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \
+ /* non-constexpr */, /* no attributes */)
+
+#define QT_DECLARE_PARTIALLY_ORDERED_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \
+ Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \
+ /* non-constexpr */, Attributes)
+
+#define Q_DECLARE_PARTIALLY_ORDERED(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED, __VA_ARGS__)
+
+#define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_1(Type) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, constexpr, /* no attributes */)
+
+#define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr, \
+ /* no attributes */) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr, \
+ /* no attributes */)
+
+#define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr, \
+ Attributes)
+
+#define Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
+
+// Weak ordering operators
+#define QT_DECLARE_WEAKLY_ORDERED_1(Type) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, /* non-constexpr */, /* no attributes */)
+
+#define QT_DECLARE_WEAKLY_ORDERED_2(LeftType, RightType) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
+ /* no attributes */) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
+ /* no attributes */)
+
+#define QT_DECLARE_WEAKLY_ORDERED_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
+ Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
+ Attributes)
+
+#define Q_DECLARE_WEAKLY_ORDERED(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED, __VA_ARGS__)
+
+#define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_1(Type) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, constexpr, /* no attributes */)
+
+#define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr, \
+ /* no attributes */) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr, \
+ /* no attributes */)
+
+#define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, Attributes) \
+QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr, \
+ Attributes)
+
+#define Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
+
+// Strong ordering operators
+#define QT_DECLARE_STRONGLY_ORDERED_1(Type) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, /* non-constexpr */, \
+ /* no attributes */)
+
+#define QT_DECLARE_STRONGLY_ORDERED_2(LeftType, RightType) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \
+ /* no attributes */) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \
+ /* non-constexpr */, /* no attributes */)
+
+#define QT_DECLARE_STRONGLY_ORDERED_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \
+ Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \
+ /* non-constexpr */, Attributes)
+
+#define Q_DECLARE_STRONGLY_ORDERED(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED, __VA_ARGS__)
+
+#define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_1(Type) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, constexpr, /* no attributes */)
+
+#define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr, \
+ /* no attributes */) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr, \
+ /* no attributes */)
+
+#define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr, Attributes) \
+ QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr, \
+ Attributes)
+
+#define Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
+
+namespace QtPrivate {
+
+template <typename T>
+constexpr bool IsIntegralType_v = std::numeric_limits<std::remove_const_t<T>>::is_specialized
+ && std::numeric_limits<std::remove_const_t<T>>::is_integer;
+
+template <typename T>
+constexpr bool IsFloatType_v = std::is_floating_point_v<T>;
+
+#if QFLOAT16_IS_NATIVE
+template <>
+constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true;
+#endif
+
+} // namespace QtPrivate
+
+namespace Qt {
+
+template <typename T>
+using if_integral = std::enable_if_t<QtPrivate::IsIntegralType_v<T>, bool>;
+
+template <typename T>
+using if_floating_point = std::enable_if_t<QtPrivate::IsFloatType_v<T>, bool>;
+
+template <typename T, typename U>
+using if_compatible_pointers =
+ std::enable_if_t<std::disjunction_v<std::is_same<T, U>,
+ std::is_base_of<T, U>,
+ std::is_base_of<U, T>>,
+ bool>;
+
+template <typename Enum>
+using if_enum = std::enable_if_t<std::is_enum_v<Enum>, bool>;
+
+template <typename LeftInt, typename RightInt,
+ if_integral<LeftInt> = true,
+ if_integral<RightInt> = true>
+constexpr Qt::strong_ordering compareThreeWay(LeftInt lhs, RightInt rhs) noexcept
+{
+ static_assert(std::is_signed_v<LeftInt> == std::is_signed_v<RightInt>,
+ "Qt::compareThreeWay() does not allow mixed-sign comparison.");
+
+#ifdef __cpp_lib_three_way_comparison
+ return lhs <=> rhs;
+#else
+ if (lhs == rhs)
+ return Qt::strong_ordering::equivalent;
+ else if (lhs < rhs)
+ return Qt::strong_ordering::less;
+ else
+ return Qt::strong_ordering::greater;
+#endif // __cpp_lib_three_way_comparison
+}
+
+template <typename LeftFloat, typename RightFloat,
+ if_floating_point<LeftFloat> = true,
+ if_floating_point<RightFloat> = true>
+constexpr Qt::partial_ordering compareThreeWay(LeftFloat lhs, RightFloat rhs) noexcept
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_FLOAT_COMPARE
+#ifdef __cpp_lib_three_way_comparison
+ return lhs <=> rhs;
+#else
+ if (lhs < rhs)
+ return Qt::partial_ordering::less;
+ else if (lhs > rhs)
+ return Qt::partial_ordering::greater;
+ else if (lhs == rhs)
+ return Qt::partial_ordering::equivalent;
+ else
+ return Qt::partial_ordering::unordered;
+#endif // __cpp_lib_three_way_comparison
+QT_WARNING_POP
+}
+
+template <typename IntType, typename FloatType,
+ if_integral<IntType> = true,
+ if_floating_point<FloatType> = true>
+constexpr Qt::partial_ordering compareThreeWay(IntType lhs, FloatType rhs) noexcept
+{
+ return compareThreeWay(FloatType(lhs), rhs);
+}
+
+template <typename FloatType, typename IntType,
+ if_floating_point<FloatType> = true,
+ if_integral<IntType> = true>
+constexpr Qt::partial_ordering compareThreeWay(FloatType lhs, IntType rhs) noexcept
+{
+ return compareThreeWay(lhs, FloatType(rhs));
+}
+
+template <typename LeftType, typename RightType,
+ if_compatible_pointers<LeftType, RightType> = true>
+constexpr Qt::strong_ordering compareThreeWay(const LeftType *lhs, const RightType *rhs) noexcept
+{
+#ifdef __cpp_lib_three_way_comparison
+ return std::compare_three_way{}(lhs, rhs);
+#else
+ if (lhs == rhs)
+ return Qt::strong_ordering::equivalent;
+ else if (std::less<>{}(lhs, rhs))
+ return Qt::strong_ordering::less;
+ else
+ return Qt::strong_ordering::greater;
+#endif // __cpp_lib_three_way_comparison
+}
+
+template <typename T>
+constexpr Qt::strong_ordering compareThreeWay(const T *lhs, std::nullptr_t rhs) noexcept
+{
+ return compareThreeWay(lhs, static_cast<const T *>(rhs));
+}
+
+template <typename T>
+constexpr Qt::strong_ordering compareThreeWay(std::nullptr_t lhs, const T *rhs) noexcept
+{
+ return compareThreeWay(static_cast<const T *>(lhs), rhs);
+}
+
+template <class Enum, if_enum<Enum> = true>
+constexpr Qt::strong_ordering compareThreeWay(Enum lhs, Enum rhs) noexcept
+{
+ return compareThreeWay(qToUnderlying(lhs), qToUnderlying(rhs));
+}
+
+} // namespace Qt
+
+QT_END_NAMESPACE
+
+#endif // QCOMPAREHELPERS_H
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 6341d060f1..b2340bff8e 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1,53 +1,24 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QGLOBAL_H
-# include <QtCore/qglobal.h>
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#if 0
+#pragma qt_class(QtCompilerDetection)
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
#endif
#ifndef QCOMPILERDETECTION_H
#define QCOMPILERDETECTION_H
+#include <QtCore/qprocessordetection.h>
+#include <QtCore/qsystemdetection.h>
+#include <QtCore/qtconfiginclude.h>
+
/*
The compiler, must be one of: (Q_CC_x)
+ COVERITY - Coverity cov-scan
SYM - Digital Mars C/C++ (used to be Symantec C++)
MSVC - Microsoft Visual C/C++, Intel C++ for Windows
BOR - Borland/Turbo C++
@@ -74,6 +45,11 @@
Should be sorted most to least authoritative.
*/
+#if defined(__COVERITY__)
+# define Q_CC_COVERITY
+# define Q_COMPILER_COMPLAINS_ABOUT_RETURN_AFTER_UNREACHABLE
+#endif
+
/* Symantec C++ is now Digital Mars */
#if defined(__DMC__) || defined(__SC__)
# define Q_CC_SYM
@@ -83,30 +59,26 @@
# endif
#elif defined(_MSC_VER)
+# define Q_CC_MSVC (_MSC_VER)
+# define Q_CC_MSVC_NET
+# define Q_CC_MSVC_ONLY Q_CC_MSVC
# ifdef __clang__
+# undef Q_CC_MSVC_ONLY
# define Q_CC_CLANG ((__clang_major__ * 100) + __clang_minor__)
+# define Q_CC_CLANG_ONLY Q_CC_CLANG
# endif
-# define Q_CC_MSVC (_MSC_VER)
-# define Q_CC_MSVC_NET
# define Q_OUTOFLINE_TEMPLATE inline
# define Q_COMPILER_MANGLES_RETURN_TYPE
+# define Q_COMPILER_MANGLES_ACCESS_SPECIFIER
# define Q_FUNC_INFO __FUNCSIG__
# define Q_ASSUME_IMPL(expr) __assume(expr)
# define Q_UNREACHABLE_IMPL() __assume(0)
-# define Q_NORETURN __declspec(noreturn)
-# define Q_DECL_DEPRECATED __declspec(deprecated)
-# ifndef Q_CC_CLANG
-# define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text))
-# endif
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
-# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) stdext::make_unchecked_array_iterator(x) // Since _MSC_VER >= 1800
-# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) // Since _MSC_VER >= 1500
-/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
-# if defined(__INTEL_COMPILER)
-# define Q_DECL_VARIABLE_DEPRECATED
-# define Q_CC_INTEL __INTEL_COMPILER
+# if _MSC_VER < 1938 // stdext is deprecated since VS 2022 17.8
+# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) // Since _MSC_VER >= 1500
# endif
+# define Q_COMPILER_COMPLAINS_ABOUT_RETURN_AFTER_UNREACHABLE
#elif defined(__BORLANDC__) || defined(__TURBOC__)
# define Q_CC_BOR
@@ -141,46 +113,39 @@
# if defined(__MINGW32__)
# define Q_CC_MINGW
# endif
-# if defined(__INTEL_COMPILER)
-/* Intel C++ also masquerades as GCC */
-# define Q_CC_INTEL (__INTEL_COMPILER)
-# ifdef __clang__
-/* Intel C++ masquerades as Clang masquerading as GCC */
-# define Q_CC_CLANG 305
-# endif
-# define Q_ASSUME_IMPL(expr) __assume(expr)
-# define Q_UNREACHABLE_IMPL() __builtin_unreachable()
-# if __INTEL_COMPILER >= 1300 && !defined(__APPLE__)
-# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text)))
-# endif
-# elif defined(__clang__)
+# if defined(__clang__)
/* Clang also masquerades as GCC */
# if defined(__apple_build_version__)
-# /* http://en.wikipedia.org/wiki/Xcode#Toolchain_Versions */
-# if __apple_build_version__ >= 8020041
-# define Q_CC_CLANG 309
-# elif __apple_build_version__ >= 8000038
-# define Q_CC_CLANG 308
-# elif __apple_build_version__ >= 7000053
-# define Q_CC_CLANG 306
-# elif __apple_build_version__ >= 6000051
-# define Q_CC_CLANG 305
-# elif __apple_build_version__ >= 5030038
-# define Q_CC_CLANG 304
-# elif __apple_build_version__ >= 5000275
-# define Q_CC_CLANG 303
-# elif __apple_build_version__ >= 4250024
-# define Q_CC_CLANG 302
-# elif __apple_build_version__ >= 3180045
-# define Q_CC_CLANG 301
-# elif __apple_build_version__ >= 2111001
-# define Q_CC_CLANG 300
+ // The Clang version reported by Apple Clang in __clang_major__
+ // and __clang_minor__ does _not_ reflect the actual upstream
+ // version of the compiler. To allow consumers to use a single
+ // define to verify the Clang version we hard-code the versions
+ // based on the best available info we have about the actual
+ // version: http://en.wikipedia.org/wiki/Xcode#Toolchain_Versions
+# if __apple_build_version__ >= 14030022 // Xcode 14.3
+# define Q_CC_CLANG 1500
+# elif __apple_build_version__ >= 14000029 // Xcode 14.0
+# define Q_CC_CLANG 1400
+# elif __apple_build_version__ >= 13160021 // Xcode 13.3
+# define Q_CC_CLANG 1300
+# elif __apple_build_version__ >= 13000029 // Xcode 13.0
+# define Q_CC_CLANG 1200
+# elif __apple_build_version__ >= 12050022 // Xcode 12.5
+# define Q_CC_CLANG 1110
+# elif __apple_build_version__ >= 12000032 // Xcode 12.0
+# define Q_CC_CLANG 1000
+# elif __apple_build_version__ >= 11030032 // Xcode 11.4
+# define Q_CC_CLANG 900
+# elif __apple_build_version__ >= 11000033 // Xcode 11.0
+# define Q_CC_CLANG 800
# else
-# error "Unknown Apple Clang version"
+# error "Unsupported Apple Clang version"
# endif
# else
+ // Non-Apple Clang, so we trust the versions reported
# define Q_CC_CLANG ((__clang_major__ * 100) + __clang_minor__)
# endif
+# define Q_CC_CLANG_ONLY Q_CC_CLANG
# if __has_builtin(__builtin_assume)
# define Q_ASSUME_IMPL(expr) __builtin_assume(expr)
# else
@@ -203,6 +168,7 @@
# endif
# else
/* Plain GCC */
+# define Q_CC_GNU_ONLY Q_CC_GNU
# if Q_CC_GNU >= 405
# define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable()
# define Q_UNREACHABLE_IMPL() __builtin_unreachable()
@@ -213,8 +179,13 @@
# ifdef Q_OS_WIN
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
-# elif defined(QT_VISIBILITY_AVAILABLE)
-# define Q_DECL_EXPORT __attribute__((visibility("default")))
+# else
+# define Q_DECL_EXPORT_OVERRIDABLE __attribute__((visibility("default"), weak))
+# ifdef QT_USE_PROTECTED_VISIBILITY
+# define Q_DECL_EXPORT __attribute__((visibility("protected")))
+# else
+# define Q_DECL_EXPORT __attribute__((visibility("default")))
+# endif
# define Q_DECL_IMPORT __attribute__((visibility("default")))
# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
# endif
@@ -264,7 +235,6 @@
but it is not defined on older compilers like C Set 3.1 */
#elif defined(__xlC__)
# define Q_CC_XLC
-# define Q_FULL_TEMPLATE_INSTANTIATION
# if __xlC__ < 0x400
# error "Compiler not supported"
# elif __xlC__ >= 0x0600
@@ -335,10 +305,6 @@
# elif defined(__KCC)
# define Q_CC_KAI
-/* Using the `using' keyword avoids Intel C++ for Linux warnings */
-# elif defined(__INTEL_COMPILER)
-# define Q_CC_INTEL (__INTEL_COMPILER)
-
/* Uses CFront, make sure to read the manual how to tweak templates. */
# elif defined(__ghs)
# define Q_CC_GHS
@@ -378,7 +344,6 @@
# define Q_COMPILER_STATIC_ASSERT
# define Q_COMPILER_TEMPLATE_ALIAS
# define Q_COMPILER_THREAD_LOCAL
-# define Q_COMPILER_THREADSAFE_STATICS
# define Q_COMPILER_UDL
# define Q_COMPILER_UNICODE_STRINGS
# define Q_COMPILER_UNIFORM_INIT
@@ -410,15 +375,6 @@
documentation. It also follows conventions like _BOOL and this documented */
# elif defined(sinix)
# define Q_CC_CDS
-
-/* The MIPSpro compiler defines __EDG */
-# elif defined(__sgi)
-# define Q_CC_MIPS
-# define Q_NO_TEMPLATE_FRIENDS
-# if defined(_COMPILER_VERSION) && (_COMPILER_VERSION >= 740)
-# define Q_OUTOFLINE_TEMPLATE inline
-# pragma set woff 3624,3625,3649 /* turn off some harmless warnings */
-# endif
# endif
/* VxWorks' DIAB toolchain has an additional EDG type C++ compiler
@@ -447,9 +403,6 @@
# if __SUNPRO_CC >= 0x550
# define Q_DECL_EXPORT __global
# endif
-# if __SUNPRO_CC < 0x5a0
-# define Q_NO_TEMPLATE_FRIENDS
-# endif
# if !defined(_BOOL)
# error "Compiler not supported"
# endif
@@ -468,26 +421,6 @@
# endif
# define Q_BROKEN_TEMPLATE_SPECIALIZATION
-#elif defined(Q_OS_HPUX)
-/* __HP_aCC was not defined in first aCC releases */
-# if defined(__HP_aCC) || __cplusplus >= 199707L
-# define Q_NO_TEMPLATE_FRIENDS
-# define Q_CC_HPACC
-# define Q_FUNC_INFO __PRETTY_FUNCTION__
-# if __HP_aCC-0 < 060000
-# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
-# define Q_DECL_EXPORT __declspec(dllexport)
-# define Q_DECL_IMPORT __declspec(dllimport)
-# endif
-# if __HP_aCC-0 >= 062000
-# define Q_DECL_EXPORT __attribute__((visibility("default")))
-# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
-# define Q_DECL_IMPORT Q_DECL_EXPORT
-# endif
-# else
-# error "Compiler not supported"
-# endif
-
#else
# error "Qt has not been tested with this compiler - see http://www.qt-project.org/"
#endif
@@ -517,13 +450,21 @@
# define __has_include_next(x) 0
#endif
-// Kept around until all submodules have transitioned
-#define QT_HAS_BUILTIN(x) __has_builtin(x)
-#define QT_HAS_FEATURE(x) __has_feature(x)
-#define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
-#define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
-#define QT_HAS_INCLUDE(x) __has_include(x)
-#define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
+/*
+ detecting ASAN can be helpful to disable slow tests
+ clang uses feature, gcc defines __SANITIZE_ADDRESS__
+ unconditionally check both in case other compilers mirror
+ either of those options
+ */
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# define QT_ASAN_ENABLED
+#endif
+
+#ifdef __cplusplus
+# if __has_include(<version>) /* remove this check once Integrity, QNX have caught up */
+# include <version>
+# endif
+#endif
/*
* C++11 support
@@ -565,100 +506,27 @@
* N1653 Q_COMPILER_VARIADIC_MACROS
* N2242 N2555 Q_COMPILER_VARIADIC_TEMPLATES __cpp_variadic_templates = 200704
*
- * For any future version of the C++ standard, we use only the SD-6 macro.
- * For full listing, see
- * http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
+ *
+ * For the C++ standards C++14 and C++17, we use only the SD-6 macro.
+ *
+ * For any future version of the C++ standard, we use only the C++20 feature test macro.
+ * For library features, we assume <version> is present (this header includes it).
+ *
+ * For a full listing of feature test macros, see
+ * https://en.cppreference.com/w/cpp/feature_test
*
* C++ extensions:
* Q_COMPILER_RESTRICTED_VLA variable-length arrays, prior to __cpp_runtime_arrays
*/
-#ifdef __cplusplus
-# if __cplusplus < 201103L && !defined(Q_CC_MSVC)
-# error Qt requires a C++11 compiler and yours does not seem to be that.
-# endif
-#endif
-
-#if defined(Q_CC_INTEL) && !defined(Q_CC_MSVC)
-# define Q_COMPILER_RESTRICTED_VLA
-# define Q_COMPILER_VARIADIC_MACROS // C++11 feature supported as an extension in other modes, too
-# define Q_COMPILER_THREADSAFE_STATICS
-# if __INTEL_COMPILER < 1200
-# define Q_NO_TEMPLATE_FRIENDS
-# endif
-# if __INTEL_COMPILER >= 1310 && !defined(_WIN32)
-// ICC supports C++14 binary literals in C, C++98, and C++11 modes
-// at least since 13.1, but I can't test further back
-# define Q_COMPILER_BINARY_LITERALS
-# endif
-# if __cplusplus >= 201103L || defined(__INTEL_CXX11_MODE__)
-# if __INTEL_COMPILER >= 1200
-# define Q_COMPILER_AUTO_TYPE
-# define Q_COMPILER_CLASS_ENUM
-# define Q_COMPILER_DECLTYPE
-# define Q_COMPILER_DEFAULT_MEMBERS
-# define Q_COMPILER_DELETE_MEMBERS
-# define Q_COMPILER_EXTERN_TEMPLATES
-# define Q_COMPILER_LAMBDA
-# define Q_COMPILER_RVALUE_REFS
-# define Q_COMPILER_STATIC_ASSERT
-# define Q_COMPILER_VARIADIC_MACROS
-# endif
-# if __INTEL_COMPILER >= 1210
-# define Q_COMPILER_ATTRIBUTES
-# define Q_COMPILER_AUTO_FUNCTION
-# define Q_COMPILER_NULLPTR
-# define Q_COMPILER_TEMPLATE_ALIAS
-# ifndef _CHAR16T // MSVC headers
-# define Q_COMPILER_UNICODE_STRINGS
-# endif
-# define Q_COMPILER_VARIADIC_TEMPLATES
-# endif
-# if __INTEL_COMPILER >= 1300
-# define Q_COMPILER_ATOMICS
-// constexpr support is only partial
-//# define Q_COMPILER_CONSTEXPR
-# define Q_COMPILER_INITIALIZER_LISTS
-# define Q_COMPILER_UNIFORM_INIT
-# define Q_COMPILER_NOEXCEPT
-# endif
-# if __INTEL_COMPILER >= 1400
-// causes issues with QArrayData and QtPrivate::RefCount - Intel issue ID 6000056211, bug DPD200534796
-//# define Q_COMPILER_CONSTEXPR
-# define Q_COMPILER_DELEGATING_CONSTRUCTORS
-# define Q_COMPILER_EXPLICIT_CONVERSIONS
-# define Q_COMPILER_EXPLICIT_OVERRIDES
-# define Q_COMPILER_NONSTATIC_MEMBER_INIT
-# define Q_COMPILER_RANGE_FOR
-# define Q_COMPILER_RAW_STRINGS
-# define Q_COMPILER_REF_QUALIFIERS
-# define Q_COMPILER_UNICODE_STRINGS
-# define Q_COMPILER_UNRESTRICTED_UNIONS
-# endif
-# if __INTEL_COMPILER >= 1500
-# if __INTEL_COMPILER * 100 + __INTEL_COMPILER_UPDATE >= 150001
-// the bug mentioned above is fixed in 15.0.1
-# define Q_COMPILER_CONSTEXPR
-# endif
-# define Q_COMPILER_ALIGNAS
-# define Q_COMPILER_ALIGNOF
-# define Q_COMPILER_INHERITING_CONSTRUCTORS
-# define Q_COMPILER_THREAD_LOCAL
-# define Q_COMPILER_UDL
-# endif
-# elif defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L
-// C11 features supported. Only tested with ICC 17 and up.
-# define Q_COMPILER_STATIC_ASSERT
-# if __has_include(<threads.h>)
-# define Q_COMPILER_THREAD_LOCAL
-# endif
-# endif
-#endif
+/*
+ * Now that we require C++17, we unconditionally expect threadsafe statics mandated since C++11
+ */
+#define Q_COMPILER_THREADSAFE_STATICS
-#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !defined(Q_CC_MSVC)
+#if defined(Q_CC_CLANG)
/* General C++ features */
# define Q_COMPILER_RESTRICTED_VLA
-# define Q_COMPILER_THREADSAFE_STATICS
# if __has_feature(attribute_deprecated_with_message)
# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text)))
# endif
@@ -679,7 +547,8 @@
# endif
/* C++11 features, see http://clang.llvm.org/cxx_status.html */
-# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+# if (defined(__cplusplus) && __cplusplus >= 201103L) \
+ || defined(__GXX_EXPERIMENTAL_CXX0X__)
/* Detect C++ features using __has_feature(), see http://clang.llvm.org/docs/LanguageExtensions.html#cxx11 */
# if __has_feature(cxx_alignas)
# define Q_COMPILER_ALIGNAS
@@ -777,10 +646,10 @@
# if Q_CC_CLANG >= 209 /* since clang 2.9 */
# define Q_COMPILER_EXTERN_TEMPLATES
# endif
-# endif
+# endif // (defined(__cplusplus) && __cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X__)
/* C++1y features, deprecated macros. Do not update this list. */
-# if __cplusplus > 201103L
+# if defined(__cplusplus) && __cplusplus > 201103L
//# if __has_feature(cxx_binary_literals)
//# define Q_COMPILER_BINARY_LITERALS // see above
//# endif
@@ -802,7 +671,7 @@
# if __has_feature(cxx_runtime_array)
# define Q_COMPILER_VLA
# endif
-# endif
+# endif // if defined(__cplusplus) && __cplusplus > 201103L
# if defined(__STDC_VERSION__)
# if __has_feature(c_static_assert)
@@ -815,18 +684,14 @@
# endif
# endif
-#endif // Q_CC_CLANG && !Q_CC_INTEL && !Q_CC_MSVC
-
-#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
# ifndef Q_DECL_UNUSED
# define Q_DECL_UNUSED __attribute__((__unused__))
# endif
# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
-#endif
+#endif // defined(Q_CC_CLANG)
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+#if defined(Q_CC_GNU_ONLY)
# define Q_COMPILER_RESTRICTED_VLA
-# define Q_COMPILER_THREADSAFE_STATICS
# if Q_CC_GNU >= 403
// GCC supports binary literals in C, C++98 and C++11 modes
# define Q_COMPILER_BINARY_LITERALS
@@ -928,7 +793,7 @@
# endif
#endif
-#if defined(Q_CC_MSVC)
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
# if defined(__cplusplus)
/* C++11 features supported in VC8 = VC2005: */
# define Q_COMPILER_VARIADIC_MACROS
@@ -980,17 +845,27 @@
# define Q_COMPILER_ATTRIBUTES
// Almost working, see https://connect.microsoft.com/VisualStudio/feedback/details/2011648
//# define Q_COMPILER_CONSTEXPR
-# define Q_COMPILER_THREADSAFE_STATICS
# define Q_COMPILER_UNIFORM_INIT
# endif
# if _MSC_VER >= 1910
# define Q_COMPILER_CONSTEXPR
# endif
+// MSVC versions before 19.36 have a bug in C++20 comparison implementation.
+// This leads to ambiguities when resolving comparison operator overloads in
+// certain scenarios (the buggy MSVC versions were checked using our CI and
+// compiler explorer).
+# if _MSC_VER < 1936
+# define Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
+# endif
+// QTBUG-124376: MSVC is slow at compiling qstrnlen()
+# define Q_COMPILER_SLOW_QSTRNLEN_COMPILATION
# endif /* __cplusplus */
-#endif /* Q_CC_MSVC */
+#endif // defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
#ifdef Q_COMPILER_UNICODE_STRINGS
# define Q_STDLIB_UNICODE_STRINGS
+#elif defined(__cplusplus)
+# error "Qt6 requires Unicode string support in both the compiler and the standard library"
#endif
#ifdef __cplusplus
@@ -1029,51 +904,22 @@
# endif // !_HAS_CONSTEXPR
# endif // !__GLIBCXX__ && !_LIBCPP_VERSION
# endif // Q_OS_QNX
-# if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC) && defined(__GNUC_LIBSTD__) \
- && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
+# if defined(Q_CC_CLANG) && defined(Q_OS_DARWIN)
+# if defined(__GNUC_LIBSTD__) && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
// Apple has not updated libstdc++ since 2007, which means it does not have
// <initializer_list> or std::move. Let's disable these features
-# undef Q_COMPILER_INITIALIZER_LISTS
-# undef Q_COMPILER_RVALUE_REFS
-# undef Q_COMPILER_REF_QUALIFIERS
+# undef Q_COMPILER_INITIALIZER_LISTS
+# undef Q_COMPILER_RVALUE_REFS
+# undef Q_COMPILER_REF_QUALIFIERS
// Also disable <atomic>, since it's clearly not there
-# undef Q_COMPILER_ATOMICS
-# endif
-# if defined(Q_CC_CLANG) && defined(Q_CC_INTEL) && Q_CC_INTEL >= 1500
-// ICC 15.x and 16.0 have their own implementation of std::atomic, which is activated when in Clang mode
-// (probably because libc++'s <atomic> on OS X failed to compile), but they're missing some
-// critical definitions. (Reported as Intel Issue ID 6000117277)
-# define __USE_CONSTEXPR 1
-# define __USE_NOEXCEPT 1
-# endif
-# if defined(Q_COMPILER_THREADSAFE_STATICS) && defined(Q_OS_MAC)
-// Apple's low-level implementation of the C++ support library
-// (libc++abi.dylib, shared between libstdc++ and libc++) has deadlocks. The
-// C++11 standard requires the deadlocks to be removed, so this will eventually
-// be fixed; for now, let's disable this.
-# undef Q_COMPILER_THREADSAFE_STATICS
-# endif
-#endif
-
-/*
- * C++11 keywords and expressions
- */
-#ifdef Q_COMPILER_NULLPTR
-# define Q_NULLPTR nullptr
-#else
-# define Q_NULLPTR NULL
-#endif
-
-#ifdef Q_COMPILER_DEFAULT_MEMBERS
-# define Q_DECL_EQ_DEFAULT = default
-#else
-# define Q_DECL_EQ_DEFAULT
-#endif
-
-#ifdef Q_COMPILER_DELETE_MEMBERS
-# define Q_DECL_EQ_DELETE = delete
-#else
-# define Q_DECL_EQ_DELETE
+# undef Q_COMPILER_ATOMICS
+# endif
+# if defined(__cpp_lib_memory_resource) \
+ && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000) \
+ || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 170000))
+# undef __cpp_lib_memory_resource // Only supported on macOS 14 and iOS 17
+# endif
+# endif // defined(Q_CC_CLANG) && defined(Q_OS_DARWIN)
#endif
// Don't break code that is already using Q_COMPILER_DEFAULT_DELETE_MEMBERS
@@ -1081,73 +927,82 @@
# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
#endif
-#if defined Q_COMPILER_CONSTEXPR
-# if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304
-# define Q_DECL_CONSTEXPR constexpr
-# define Q_DECL_RELAXED_CONSTEXPR constexpr
-# define Q_CONSTEXPR constexpr
-# define Q_RELAXED_CONSTEXPR constexpr
-# else
-# define Q_DECL_CONSTEXPR constexpr
-# define Q_DECL_RELAXED_CONSTEXPR
-# define Q_CONSTEXPR constexpr
-# define Q_RELAXED_CONSTEXPR const
-# endif
+/*
+ * Compatibility macros for C++11/14 keywords and expressions.
+ * Don't use in new code and port away whenever you have a chance.
+ */
+#define Q_ALIGNOF(x) alignof(x)
+#define Q_DECL_ALIGN(n) alignas(n)
+#define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
+#ifdef __cplusplus
+# define Q_CONSTEXPR constexpr
+# define Q_DECL_CONSTEXPR constexpr
+# define Q_DECL_EQ_DEFAULT = default
+# define Q_DECL_EQ_DELETE = delete
+# define Q_DECL_FINAL final
+# define Q_DECL_NOEXCEPT noexcept
+# define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
+# define Q_DECL_OVERRIDE override
+# define Q_DECL_RELAXED_CONSTEXPR constexpr
+# define Q_NULLPTR nullptr
+# define Q_RELAXED_CONSTEXPR constexpr
#else
+# define Q_CONSTEXPR const
# define Q_DECL_CONSTEXPR
# define Q_DECL_RELAXED_CONSTEXPR
-# define Q_CONSTEXPR const
-# define Q_RELAXED_CONSTEXPR const
-#endif
-
-#ifdef Q_COMPILER_EXPLICIT_OVERRIDES
-# define Q_DECL_OVERRIDE override
-# define Q_DECL_FINAL final
-#else
-# ifndef Q_DECL_OVERRIDE
-# define Q_DECL_OVERRIDE
-# endif
-# ifndef Q_DECL_FINAL
-# define Q_DECL_FINAL
+# define Q_NULLPTR NULL
+# define Q_RELAXED_CONSTEXPR const
+# ifdef Q_CC_GNU
+# define Q_DECL_NOEXCEPT __attribute__((__nothrow__))
+# else
+# define Q_DECL_NOEXCEPT
# endif
#endif
-#ifdef Q_COMPILER_NOEXCEPT
-# define Q_DECL_NOEXCEPT noexcept
-# define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
-#else
-# define Q_DECL_NOEXCEPT
-# define Q_DECL_NOEXCEPT_EXPR(x)
+#if __has_cpp_attribute(nodiscard) && (!defined(Q_CC_CLANG) || __cplusplus > 201402L) // P0188R1
+// Can't use [[nodiscard]] with Clang and C++11/14, see https://bugs.llvm.org/show_bug.cgi?id=33518
+# undef Q_REQUIRED_RESULT
+# define Q_REQUIRED_RESULT [[nodiscard]]
#endif
-#define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
-#ifndef Q_ALIGNOF
-# define Q_ALIGNOF(x) alignof(x)
+#if __has_cpp_attribute(nodiscard) >= 201907L /* used for both P1771 and P1301... */
+// [[nodiscard]] constructor (P1771)
+# ifndef Q_NODISCARD_CTOR
+# define Q_NODISCARD_CTOR [[nodiscard]]
+# endif
+// [[nodiscard("reason")]] (P1301)
+# ifndef Q_NODISCARD_X
+# define Q_NODISCARD_X(message) [[nodiscard(message)]]
+# endif
+# ifndef Q_NODISCARD_CTOR_X
+# define Q_NODISCARD_CTOR_X(message) [[nodiscard(message)]]
+# endif
#endif
-#ifndef Q_DECL_ALIGN
-# define Q_DECL_ALIGN(n) alignas(n)
+#if __has_cpp_attribute(maybe_unused)
+# undef Q_DECL_UNUSED
+# define Q_DECL_UNUSED [[maybe_unused]]
#endif
-#if __has_cpp_attribute(nodiscard) && !defined(Q_CC_CLANG) // P0188R1
-// Can't use [[nodiscard]] with Clang, see https://bugs.llvm.org/show_bug.cgi?id=33518
-# undef Q_REQUIRED_RESULT
-# define Q_REQUIRED_RESULT [[nodiscard]]
+#if __has_cpp_attribute(noreturn)
+# undef Q_NORETURN
+# define Q_NORETURN [[noreturn]]
#endif
-#if defined(__cpp_enumerator_attributes) && __cpp_enumerator_attributes >= 201411
-#if defined(Q_CC_MSVC)
-// Can't mark enum values as __declspec(deprecated) with MSVC, also can't move
-// everything to [[deprecated]] because MSVC gives a compilation error when marking
-// friend methods of a class as [[deprecated("text")]], breaking qstring.h
-# define Q_DECL_ENUMERATOR_DEPRECATED [[deprecated]]
-# define Q_DECL_ENUMERATOR_DEPRECATED_X(x) [[deprecated(x)]]
-#else
-# define Q_DECL_ENUMERATOR_DEPRECATED Q_DECL_DEPRECATED
-# define Q_DECL_ENUMERATOR_DEPRECATED_X(x) Q_DECL_DEPRECATED_X(x)
-#endif
+#if __has_cpp_attribute(deprecated)
+# ifdef Q_DECL_DEPRECATED
+# undef Q_DECL_DEPRECATED
+# endif
+# ifdef Q_DECL_DEPRECATED_X
+# undef Q_DECL_DEPRECATED_X
+# endif
+# define Q_DECL_DEPRECATED [[deprecated]]
+# define Q_DECL_DEPRECATED_X(x) [[deprecated(x)]]
#endif
+#define Q_DECL_ENUMERATOR_DEPRECATED Q_DECL_DEPRECATED
+#define Q_DECL_ENUMERATOR_DEPRECATED_X(x) Q_DECL_DEPRECATED_X(x)
+
/*
* Fallback macros to certain compiler features
*/
@@ -1173,6 +1028,15 @@
#ifndef Q_REQUIRED_RESULT
# define Q_REQUIRED_RESULT
#endif
+#ifndef Q_NODISCARD_X
+# define Q_NODISCARD_X(message) Q_REQUIRED_RESULT
+#endif
+#ifndef Q_NODISCARD_CTOR
+# define Q_NODISCARD_CTOR
+#endif
+#ifndef Q_NODISCARD_CTOR_X
+# define Q_NODISCARD_CTOR_X(message) Q_NODISCARD_CTOR
+#endif
#ifndef Q_DECL_DEPRECATED
# define Q_DECL_DEPRECATED
#endif
@@ -1182,15 +1046,12 @@
#ifndef Q_DECL_DEPRECATED_X
# define Q_DECL_DEPRECATED_X(text) Q_DECL_DEPRECATED
#endif
-#ifndef Q_DECL_ENUMERATOR_DEPRECATED
-# define Q_DECL_ENUMERATOR_DEPRECATED
-#endif
-#ifndef Q_DECL_ENUMERATOR_DEPRECATED_X
-# define Q_DECL_ENUMERATOR_DEPRECATED_X(x)
-#endif
#ifndef Q_DECL_EXPORT
# define Q_DECL_EXPORT
#endif
+#ifndef Q_DECL_EXPORT_OVERRIDABLE
+# define Q_DECL_EXPORT_OVERRIDABLE Q_DECL_EXPORT
+#endif
#ifndef Q_DECL_IMPORT
# define Q_DECL_IMPORT
#endif
@@ -1236,35 +1097,42 @@
* "Weak overloads" - makes an otherwise confliciting overload weaker
* (by making it a template)
*/
-#define Q_WEAK_OVERLOAD template <typename = void>
+#ifndef Q_QDOC
+# define Q_WEAK_OVERLOAD template <typename = void>
+#else
+# define Q_WEAK_OVERLOAD
+#endif
+
+/*
+ * If one wants to add functions that use post-C++17 APIs, one needs to:
+ *
+ * 1) make them fully inline; and
+ * 2) guard them using the necessary feature-testing macros.
+ *
+ * This decouples the C++ version used to build Qt with the one used by
+ * end-user applications; Qt and the application can either choose any C++
+ * version.
+ *
+ * A problem arises on MSVC for member functions of exported classes. Client
+ * code that tries to use such a function will see it as exported, and simply
+ * try to consume the function's *symbol*. However, if Qt has been built in
+ * C++17, it won't have such a symbol, and linking will fail.
+ *
+ * The workaround: declare such functions as function templates.
+ * (Obviously a function template does not need this marker.)
+*/
+#ifndef Q_QDOC
+# define QT_POST_CXX17_API_IN_EXPORTED_CLASS template <typename = void>
+#else
+# define QT_POST_CXX17_API_IN_EXPORTED_CLASS
+#endif
/*
* Warning/diagnostic handling
*/
#define QT_DO_PRAGMA(text) _Pragma(#text)
-#if defined(Q_CC_INTEL) && defined(Q_CC_MSVC)
-/* icl.exe: Intel compiler on Windows */
-# undef QT_DO_PRAGMA /* not needed */
-# define QT_WARNING_PUSH __pragma(warning(push))
-# define QT_WARNING_POP __pragma(warning(pop))
-# define QT_WARNING_DISABLE_MSVC(number)
-# define QT_WARNING_DISABLE_INTEL(number) __pragma(warning(disable: number))
-# define QT_WARNING_DISABLE_CLANG(text)
-# define QT_WARNING_DISABLE_GCC(text)
-# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786)
-# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_INTEL(1572)
-#elif defined(Q_CC_INTEL)
-/* icc: Intel compiler on Linux or OS X */
-# define QT_WARNING_PUSH QT_DO_PRAGMA(warning(push))
-# define QT_WARNING_POP QT_DO_PRAGMA(warning(pop))
-# define QT_WARNING_DISABLE_INTEL(number) QT_DO_PRAGMA(warning(disable: number))
-# define QT_WARNING_DISABLE_MSVC(number)
-# define QT_WARNING_DISABLE_CLANG(text)
-# define QT_WARNING_DISABLE_GCC(text)
-# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786)
-# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_INTEL(1572)
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
# undef QT_DO_PRAGMA /* not needed */
# define QT_WARNING_PUSH __pragma(warning(push))
# define QT_WARNING_POP __pragma(warning(pop))
@@ -1274,6 +1142,7 @@
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_MSVC(4996)
# define QT_WARNING_DISABLE_FLOAT_COMPARE
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF
#elif defined(Q_CC_CLANG)
# define QT_WARNING_PUSH QT_DO_PRAGMA(clang diagnostic push)
# define QT_WARNING_POP QT_DO_PRAGMA(clang diagnostic pop)
@@ -1283,6 +1152,7 @@
# define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF QT_WARNING_DISABLE_CLANG("-Winvalid-offsetof")
#elif defined(Q_CC_GNU) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
# define QT_WARNING_PUSH QT_DO_PRAGMA(GCC diagnostic push)
# define QT_WARNING_POP QT_DO_PRAGMA(GCC diagnostic pop)
@@ -1292,6 +1162,7 @@
# define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_GCC("-Wfloat-equal")
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF QT_WARNING_DISABLE_GCC("-Winvalid-offsetof")
#else // All other compilers, GCC < 4.6 and MSVC < 2008
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_PUSH
@@ -1302,6 +1173,7 @@
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED
# define QT_WARNING_DISABLE_FLOAT_COMPARE
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF
#endif
#ifndef QT_IGNORE_DEPRECATIONS
@@ -1312,6 +1184,20 @@
QT_WARNING_POP
#endif
+// The body must be a statement:
+#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
+
+// This macro can be used to calculate member offsets for types with a non standard layout.
+// It uses the fact that offsetof() is allowed to support those types since C++17 as an optional
+// feature. All our compilers do support this, but some issue a warning, so we wrap the offsetof()
+// call in a macro that disables the compiler warning.
+#define Q_OFFSETOF(Class, member) \
+ []() -> size_t { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, member); \
+ QT_WARNING_POP \
+ }()
+
/*
Proper for-scoping in MIPSpro CC
*/
@@ -1327,19 +1213,6 @@
#define qMove(x) (x)
#endif
-#define Q_UNREACHABLE() \
- do {\
- Q_ASSERT_X(false, "Q_UNREACHABLE()", "Q_UNREACHABLE was reached");\
- Q_UNREACHABLE_IMPL();\
- } while (false)
-
-#define Q_ASSUME(Expr) \
- do {\
- const bool valueOfExpression = Expr;\
- Q_ASSERT_X(valueOfExpression, "Q_ASSUME()", "Assumption in Q_ASSUME(\"" #Expr "\") was not correct");\
- Q_ASSUME_IMPL(valueOfExpression);\
- } while (false)
-
#if defined(__cplusplus)
#if __has_cpp_attribute(clang::fallthrough)
# define Q_FALLTHROUGH() [[clang::fallthrough]]
@@ -1350,11 +1223,11 @@
#endif
#endif
#ifndef Q_FALLTHROUGH
-# if (defined(Q_CC_GNU) && Q_CC_GNU >= 700) && !defined(Q_CC_INTEL)
+# ifdef Q_CC_GNU
# define Q_FALLTHROUGH() __attribute__((fallthrough))
# else
# define Q_FALLTHROUGH() (void)0
-#endif
+# endif
#endif
@@ -1369,6 +1242,7 @@
# undef QT_COMPILER_SUPPORTS_SSE4_2
# undef QT_COMPILER_SUPPORTS_AVX
# undef QT_COMPILER_SUPPORTS_AVX2
+# undef QT_COMPILER_SUPPORTS_F16C
#endif
#if !defined(Q_PROCESSOR_ARM)
# undef QT_COMPILER_SUPPORTS_NEON
@@ -1378,4 +1252,177 @@
# undef QT_COMPILER_SUPPORTS_MIPS_DSPR2
#endif
+// Compiler version check
+#if defined(__cplusplus) && (__cplusplus < 201703L)
+# ifdef Q_CC_MSVC
+# error "Qt requires a C++17 compiler, and a suitable value for __cplusplus. On MSVC, you must pass the /Zc:__cplusplus option to the compiler."
+# else
+# error "Qt requires a C++17 compiler"
+# endif
+#endif // __cplusplus
+
+#if defined(__cplusplus) && defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+# if Q_CC_MSVC < 1927
+ // Check below only works with 16.7 or newer
+# error "Qt requires at least Visual Studio 2019 version 16.7 (VC++ version 14.27). Please upgrade."
+# endif
+
+// On MSVC we require /permissive- set by user code. Check that we are
+// under its rules -- for instance, check that std::nullptr_t->bool is
+// not an implicit conversion, as per
+// https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160#nullptr_t-is-only-convertible-to-bool-as-a-direct-initialization
+static_assert(!std::is_convertible_v<std::nullptr_t, bool>,
+ "On MSVC you must pass the /permissive- option to the compiler.");
+#endif
+
+#if defined(QT_BOOTSTRAPPED) || defined(QT_USE_PROTECTED_VISIBILITY) || !defined(__ELF__) || defined(__PIC__)
+// this is fine
+#elif defined(QT_REDUCE_RELOCATIONS)
+# error "You must build your code with position independent code if Qt was configured with -reduce-relocations. "\
+ "Compile your code with -fPIC (and not with -fPIE)."
+#endif
+
+#ifdef Q_PROCESSOR_X86_32
+# if defined(Q_CC_GNU)
+# define QT_FASTCALL __attribute__((regparm(3)))
+# elif defined(Q_CC_MSVC)
+# define QT_FASTCALL __fastcall
+# else
+# define QT_FASTCALL
+# endif
+#else
+# define QT_FASTCALL
+#endif
+
+// enable gcc warnings for printf-style functions
+#if defined(Q_CC_GNU) && !defined(__INSURE__)
+# if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
+# define Q_ATTRIBUTE_FORMAT_PRINTF(A, B) \
+ __attribute__((format(gnu_printf, (A), (B))))
+# else
+# define Q_ATTRIBUTE_FORMAT_PRINTF(A, B) \
+ __attribute__((format(printf, (A), (B))))
+# endif
+#else
+# define Q_ATTRIBUTE_FORMAT_PRINTF(A, B)
+#endif
+
+#ifdef Q_CC_MSVC
+# define Q_NEVER_INLINE __declspec(noinline)
+# define Q_ALWAYS_INLINE __forceinline
+#elif defined(Q_CC_GNU)
+# define Q_NEVER_INLINE __attribute__((noinline))
+# define Q_ALWAYS_INLINE inline __attribute__((always_inline))
+#else
+# define Q_NEVER_INLINE
+# define Q_ALWAYS_INLINE inline
+#endif
+
+//defines the type for the WNDPROC on windows
+//the alignment needs to be forced for sse2 to not crash with mingw
+#if defined(Q_OS_WIN)
+# if defined(Q_CC_MINGW) && defined(Q_PROCESSOR_X86_32)
+# define QT_ENSURE_STACK_ALIGNED_FOR_SSE __attribute__ ((force_align_arg_pointer))
+# else
+# define QT_ENSURE_STACK_ALIGNED_FOR_SSE
+# endif
+# define QT_WIN_CALLBACK CALLBACK QT_ENSURE_STACK_ALIGNED_FOR_SSE
+#endif
+
+#ifdef __cpp_conditional_explicit
+#define Q_IMPLICIT explicit(false)
+#else
+#define Q_IMPLICIT
+#endif
+
+#if defined(__cplusplus)
+
+#ifdef __cpp_constinit
+# if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+ // https://developercommunity.visualstudio.com/t/C:-constinit-for-an-optional-fails-if-/1406069
+# define Q_CONSTINIT
+# else
+# define Q_CONSTINIT constinit
+# endif
+#elif defined(__has_cpp_attribute) && __has_cpp_attribute(clang::require_constant_initialization)
+# define Q_CONSTINIT [[clang::require_constant_initialization]]
+#elif defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1000
+# define Q_CONSTINIT __constinit
+#else
+# define Q_CONSTINIT
+#endif
+
+#ifndef Q_OUTOFLINE_TEMPLATE
+# define Q_OUTOFLINE_TEMPLATE
+#endif
+#ifndef Q_INLINE_TEMPLATE
+# define Q_INLINE_TEMPLATE inline
+#endif
+
+/*
+ Avoid some particularly useless warnings from some stupid compilers.
+ To get ALL C++ compiler warnings, define QT_CC_WARNINGS or comment out
+ the line "#define QT_NO_WARNINGS". See also QTBUG-26877.
+*/
+#if !defined(QT_CC_WARNINGS)
+# define QT_NO_WARNINGS
+#endif
+#if defined(QT_NO_WARNINGS)
+# if defined(Q_CC_MSVC)
+QT_WARNING_DISABLE_MSVC(4251) /* class 'type' needs to have dll-interface to be used by clients of class 'type2' */
+QT_WARNING_DISABLE_MSVC(4244) /* conversion from 'type1' to 'type2', possible loss of data */
+QT_WARNING_DISABLE_MSVC(4275) /* non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' */
+QT_WARNING_DISABLE_MSVC(4514) /* unreferenced inline function has been removed */
+QT_WARNING_DISABLE_MSVC(4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */
+QT_WARNING_DISABLE_MSVC(4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */
+QT_WARNING_DISABLE_MSVC(4706) /* assignment within conditional expression */
+QT_WARNING_DISABLE_MSVC(4355) /* 'this' : used in base member initializer list */
+QT_WARNING_DISABLE_MSVC(4710) /* function not inlined */
+QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */
+# elif defined(Q_CC_BOR)
+# pragma option -w-inl
+# pragma option -w-aus
+# pragma warn -inl
+# pragma warn -pia
+# pragma warn -ccc
+# pragma warn -rch
+# pragma warn -sig
+# endif
+#endif
+
+#if !defined(QT_NO_EXCEPTIONS)
+# if !defined(Q_MOC_RUN)
+# if defined(Q_CC_GNU) && !defined(__cpp_exceptions)
+# define QT_NO_EXCEPTIONS
+# endif
+# elif defined(QT_BOOTSTRAPPED)
+# define QT_NO_EXCEPTIONS
+# endif
+#endif
+
+// libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346
+#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11)
+# define QT_COMPILER_HAS_LWG3346
+#endif
+
+#if defined(__cplusplus) && __cplusplus >= 202002L // P0846 doesn't have a feature macro :/
+# if !defined(Q_CC_MSVC_ONLY) || Q_CC_MSVC < 1939 // claims C++20 support but lacks P0846
+ // 1939 is known to work
+ // 1936 is known to fail
+# define QT_COMPILER_HAS_P0846
+# endif
+#endif
+
+#ifdef QT_COMPILER_HAS_P0846
+# define QT_ENABLE_P0846_SEMANTICS_FOR(func)
+#else
+ class QT_CLASS_JUST_FOR_P0846_SIMULATION;
+# define QT_ENABLE_P0846_SEMANTICS_FOR(func) \
+ template <typename T> \
+ void func (QT_CLASS_JUST_FOR_P0846_SIMULATION *); \
+ /* end */
+#endif // !P0846
+
+#endif // __cplusplus
+
#endif // QCOMPILERDETECTION_H
diff --git a/src/corelib/global/qcompilerdetection.qdoc b/src/corelib/global/qcompilerdetection.qdoc
new file mode 100644
index 0000000000..191f26cc1f
--- /dev/null
+++ b/src/corelib/global/qcompilerdetection.qdoc
@@ -0,0 +1,427 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \headerfile <QtCompilerDetection>
+ \inmodule QtCore
+ \title Compiler-specific Macro Definitions
+ \ingroup funclists
+
+ \brief The <QtCompilerDetection> header file includes various
+ compiler-specific macros.
+
+ The <QtCompilerDetection> header file provides a range of macros (Q_CC_*)
+ that are defined if the application is compiled using the specified
+ compiler. For example, the Q_CC_SUN macro is defined if the application is
+ compiled using Forte Developer, or Sun Studio C++.
+
+ The purpose of these macros is to enable programmers to add
+ compiler-specific code to their application.
+*/
+
+/*!
+ \macro Q_CC_SYM
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Digital Mars C/C++
+ (used to be Symantec C++).
+*/
+
+/*!
+ \macro Q_CC_MSVC
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Microsoft Visual
+ C/C++, Intel C++ for Windows.
+*/
+
+/*!
+ \macro Q_CC_CLANG
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Clang.
+*/
+
+/*!
+ \macro Q_CC_BOR
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Borland/Turbo C++.
+*/
+
+/*!
+ \macro Q_CC_WAT
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Watcom C++.
+*/
+
+/*!
+ \macro Q_CC_GNU
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using GNU Compiler Collection (GCC).
+*/
+
+/*!
+ \macro Q_CC_COMEAU
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Comeau C++.
+*/
+
+/*!
+ \macro Q_CC_EDG
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Edison Design Group
+ C++.
+*/
+
+/*!
+ \macro Q_CC_OC
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using CenterLine C++.
+*/
+
+/*!
+ \macro Q_CC_SUN
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Forte Developer, or
+ Sun Studio C++.
+*/
+
+/*!
+ \macro Q_CC_MIPS
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using MIPSpro C++.
+*/
+
+/*!
+ \macro Q_CC_DEC
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using DEC C++.
+*/
+
+/*!
+ \macro Q_CC_HPACC
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using HP aC++.
+*/
+
+/*!
+ \macro Q_CC_USLC
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using SCO OUDK and UDK.
+*/
+
+/*!
+ \macro Q_CC_CDS
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Reliant C++.
+*/
+
+/*!
+ \macro Q_CC_KAI
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using KAI C++.
+*/
+
+/*!
+ \macro Q_CC_INTEL
+ \relates <QtCompilerDetection>
+ \obsolete
+
+ This macro used to be defined if the application was compiled with the old
+ Intel C++ compiler for Linux, macOS or Windows. The new oneAPI C++ compiler
+ is just a build of Clang and therefore does not define this macro.
+
+ \sa Q_CC_CLANG
+*/
+
+/*!
+ \macro Q_CC_HIGHC
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using MetaWare High C/C++.
+*/
+
+/*!
+ \macro Q_CC_PGI
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Portland Group C++.
+*/
+
+/*!
+ \macro Q_CC_GHS
+ \relates <QtCompilerDetection>
+
+ Defined if the application is compiled using Green Hills
+ Optimizing C++ Compilers.
+*/
+
+/*!
+ \macro void Q_FALLTHROUGH()
+ \relates <QtCompilerDetection>
+ \since 5.8
+
+ Can be used in switch statements at the end of case block to tell the compiler
+ and other developers that the lack of a break statement is intentional.
+
+ This is useful since a missing break statement is often a bug, and some
+ compilers can be configured to emit warnings when one is not found.
+
+ \sa Q_UNREACHABLE(), Q_UNREACHABLE_RETURN()
+*/
+
+/*!
+ \macro Q_LIKELY(expr)
+ \relates <QtCompilerDetection>
+ \since 4.8
+
+ \brief Hints to the compiler that the enclosed condition, \a expr, is
+ likely to evaluate to \c true.
+
+ Use of this macro can help the compiler to optimize the code.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qlikely
+
+ \sa Q_UNLIKELY()
+*/
+
+/*!
+ \macro Q_UNLIKELY(expr)
+ \relates <QtCompilerDetection>
+ \since 4.8
+
+ \brief Hints to the compiler that the enclosed condition, \a expr, is
+ likely to evaluate to \c false.
+
+ Use of this macro can help the compiler to optimize the code.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qunlikely
+
+ \sa Q_LIKELY()
+*/
+
+/*!
+ \macro Q_CONSTINIT
+ \relates <QtCompilerDetection>
+ \since 6.4
+
+ \brief Enforces constant initialization when supported by the compiler.
+
+ If the compiler supports the C++20 \c{constinit} keyword, Clang's
+ \c{[[clang::require_constant_initialization]]} or GCC's \c{__constinit},
+ then this macro expands to the first one of these that is available,
+ otherwise it expands to nothing.
+
+ Variables marked as \c{constinit} cause a compile-error if their
+ initialization would have to be performed at runtime.
+
+ \note Constant-initialized variables may still have load-time impact if
+ they have non-trivial destruction.
+
+ For constants, you can use \c{constexpr} since C++11, but \c{constexpr}
+ makes variables \c{const}, too, whereas \c{constinit} ensures constant
+ initialization, but doesn't make the variable \c{const}:
+
+ \table
+ \header \li Keyword \li Added \li immutable \li constant-initialized
+ \row \li \c{const} \li C++98 \li yes \li not required
+ \row \li \c{constexpr} \li C++11 \li yes \li required
+ \row \li \c{constinit} \li C++20 \li no \li required
+ \endtable
+*/
+
+/*!
+ \macro Q_DECL_EXPORT
+ \relates <QtCompilerDetection>
+
+ This macro marks a symbol for shared library export (see
+ \l{sharedlibrary.html}{Creating Shared Libraries}).
+
+ \sa Q_DECL_IMPORT
+*/
+
+/*!
+ \macro Q_DECL_IMPORT
+ \relates <QtCompilerDetection>
+
+ This macro declares a symbol to be an import from a shared library (see
+ \l{sharedlibrary.html}{Creating Shared Libraries}).
+
+ \sa Q_DECL_EXPORT
+*/
+
+/*!
+ \macro Q_DECL_CONSTEXPR
+ \relates <QtCompilerDetection>
+ \deprecated [6.4] Use the \c constexpr keyword instead.
+
+ This macro can be used to declare variable that should be constructed at compile-time,
+ or an inline function that can be computed at compile-time.
+
+ \sa Q_DECL_RELAXED_CONSTEXPR
+*/
+
+/*!
+ \macro Q_DECL_RELAXED_CONSTEXPR
+ \relates <QtCompilerDetection>
+ \deprecated [6.4] Use the \c constexpr keyword instead.
+
+ This macro can be used to declare an inline function that can be computed
+ at compile-time according to the relaxed rules from C++14.
+
+ \sa Q_DECL_CONSTEXPR
+*/
+
+/*!
+ \macro Q_DECL_NOTHROW
+ \relates <QtCompilerDetection>
+ \since 5.0
+ \deprecated [6.4] Use the \c noexcept keyword instead.
+
+ This macro marks a function as never throwing, under no
+ circumstances. If the function does nevertheless throw, the
+ behavior is undefined.
+
+ \sa Q_DECL_NOEXCEPT, Q_DECL_NOEXCEPT_EXPR()
+*/
+
+/*!
+ \macro Q_DECL_NOEXCEPT
+ \relates <QtCompilerDetection>
+ \since 5.0
+ \deprecated [6.4] Use the \c noexcept keyword instead.
+
+ This macro marks a function as never throwing. If the function
+ does nevertheless throw, the behavior is defined:
+ std::terminate() is called.
+
+
+ \sa Q_DECL_NOTHROW, Q_DECL_NOEXCEPT_EXPR()
+*/
+
+/*!
+ \macro Q_DECL_NOEXCEPT_EXPR(x)
+ \relates <QtCompilerDetection>
+ \since 5.0
+ \deprecated [6.4] Use the \c noexcept keyword instead.
+
+ This macro marks a function as non-throwing if \a x is \c true. If
+ the function does nevertheless throw, the behavior is defined:
+ std::terminate() is called.
+
+
+ \sa Q_DECL_NOTHROW, Q_DECL_NOEXCEPT
+*/
+
+/*!
+ \macro Q_DECL_OVERRIDE
+ \since 5.0
+ \deprecated
+ \relates <QtCompilerDetection>
+
+ This macro can be used to declare an overriding virtual
+ function. Use of this markup will allow the compiler to generate
+ an error if the overriding virtual function does not in fact
+ override anything.
+
+ It expands to "override".
+
+ The macro goes at the end of the function, usually after the
+ \c{const}, if any:
+ \snippet code/src_corelib_global_qglobal.cpp qdecloverride
+
+ \sa Q_DECL_FINAL
+*/
+
+/*!
+ \macro Q_DECL_FINAL
+ \since 5.0
+ \deprecated
+ \relates <QtCompilerDetection>
+
+ This macro can be used to declare an overriding virtual or a class
+ as "final", with Java semantics. Further-derived classes can then
+ no longer override this virtual function, or inherit from this
+ class, respectively.
+
+ It expands to "final".
+
+ The macro goes at the end of the function, usually after the
+ \c{const}, if any:
+ \snippet code/src_corelib_global_qglobal.cpp qdeclfinal-1
+
+ For classes, it goes in front of the \c{:} in the class
+ definition, if any:
+ \snippet code/src_corelib_global_qglobal.cpp qdeclfinal-2
+
+ \sa Q_DECL_OVERRIDE
+*/
+
+/*!
+ \macro const char* Q_FUNC_INFO()
+ \relates <QtCompilerDetection>
+
+ Expands to a string that describe the function the macro resides in. How this string looks
+ more specifically is compiler dependent. With GNU GCC it is typically the function signature,
+ while with other compilers it might be the line and column number.
+
+ Q_FUNC_INFO can be conveniently used with qDebug(). For example, this function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 22
+
+ when instantiated with the integer type, will with the GCC compiler produce:
+
+ \tt{const TInputType& myMin(const TInputType&, const TInputType&) [with TInputType = int] was called with value1: 3 value2: 4}
+
+ If this macro is used outside a function, the behavior is undefined.
+*/
+
+/*!
+ \macro Q_NODISCARD_CTOR
+ \relates <QtCompilerDetection>
+ \since 6.6
+
+ \brief Expands to \c{[[nodiscard]]} on compilers that accept it on constructors.
+
+ Otherwise it expands to nothing.
+
+ Constructors marked as Q_NODISCARD_CTOR cause a compiler warning if a call
+ site doesn't use the resulting object.
+
+ This macro is exists solely to prevent warnings on compilers that don't
+ implement the feature. If your supported platforms all allow \c{[[nodiscard]]}
+ on constructors, we strongly recommend you use the C++ attribute directly instead
+ of this macro.
+
+ \sa Q_NODISCARD_CTOR_X
+*/
+
+/*!
+ \macro Q_NODISCARD_X(message)
+ \macro Q_NODISCARD_CTOR_X(message)
+ \relates <QtCompilerDetection>
+ \since 6.7
+
+ \brief Expand to \c{[[nodiscard(message)]]} on compilers that support the feature.
+
+ Otherwise they expand to \c {[[nodiscard]]} and Q_NODISCARD_CTOR, respectively.
+
+ \sa Q_NODISCARD_CTOR
+*/
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index a9a20a231c..4d80f23786 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//
// W A R N I N G
@@ -59,6 +23,8 @@
#ifdef QT_BOOTSTRAPPED
+#include <stdlib.h> // for __GLIBC_PREREQ
+
#ifndef QT_NO_EXCEPTIONS
#define QT_NO_EXCEPTIONS
#endif
@@ -66,10 +32,6 @@
#define QT_NO_USING_NAMESPACE
#define QT_NO_DEPRECATED
-#ifndef QT_BUILD_QMAKE
-#define QT_NO_REGEXP
-#endif
-
// Keep feature-test macros in alphabetic order by feature name:
#define QT_FEATURE_alloca 1
#define QT_FEATURE_alloca_h -1
@@ -78,18 +40,20 @@
#else
# define QT_FEATURE_alloca_malloc_h -1
#endif
-#define QT_FEATURE_binaryjson -1
#define QT_FEATURE_cborstreamreader -1
#define QT_FEATURE_cborstreamwriter 1
#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1
-#define QT_FEATURE_cxx11_random (__has_include(<random>) ? 1 : -1)
#define QT_FEATURE_cxx17_filesystem -1
#define QT_NO_DATASTREAM
#define QT_FEATURE_datestring 1
#define QT_FEATURE_datetimeparser -1
#define QT_FEATURE_easingcurve -1
#define QT_FEATURE_etw -1
+#if defined(__linux__) || defined(__GLIBC__)
#define QT_FEATURE_getauxval (__has_include(<sys/auxv.h>) ? 1 : -1)
+#else
+#define QT_FEATURE_getauxval -1
+#endif
#define QT_FEATURE_getentropy -1
#define QT_NO_GEOM_VARIANT
#define QT_FEATURE_hijricalendar -1
@@ -98,7 +62,8 @@
#define QT_FEATURE_jalalicalendar -1
#define QT_FEATURE_journald -1
#define QT_FEATURE_futimens -1
-#define QT_FEATURE_futimes -1
+#undef QT_FEATURE_future
+#define QT_FEATURE_future -1
#define QT_FEATURE_itemmodel -1
#define QT_FEATURE_library -1
#ifdef __linux__
@@ -115,40 +80,31 @@
#else
# define QT_FEATURE_renameat2 -1
#endif
-#define QT_FEATURE_sharedmemory -1
#define QT_FEATURE_shortcut -1
-#define QT_FEATURE_signaling_nan -1
#define QT_FEATURE_slog2 -1
-#ifdef __GLIBC_PREREQ
-# define QT_FEATURE_statx (__GLIBC_PREREQ(2, 28) ? 1 : -1)
-#else
-# define QT_FEATURE_statx -1
-#endif
#define QT_FEATURE_syslog -1
#define QT_NO_SYSTEMLOCALE
-#define QT_FEATURE_systemsemaphore -1
-#define QT_FEATURE_temporaryfile 1
+#define QT_FEATURE_temporaryfile -1
#define QT_FEATURE_textdate 1
+#undef QT_FEATURE_thread
#define QT_FEATURE_thread -1
#define QT_FEATURE_timezone -1
#define QT_FEATURE_topleveldomain -1
#define QT_NO_TRANSLATION
#define QT_FEATURE_translation -1
+#define QT_NO_VARIANT -1
+
+#define QT_NO_COMPRESS
// rcc.pro will DEFINES+= this
#ifndef QT_FEATURE_zstd
#define QT_FEATURE_zstd -1
#endif
-#ifdef QT_BUILD_QMAKE
-#define QT_FEATURE_commandlineparser -1
-#define QT_NO_COMPRESS
-#define QT_JSON_READONLY
-#define QT_FEATURE_settings 1
-#define QT_NO_STANDARDPATHS
-#else
#define QT_FEATURE_commandlineparser 1
#define QT_FEATURE_settings -1
-#endif
+#define QT_FEATURE_permissions -1
+
+#define QT_NO_TEMPORARYFILE
#endif // QT_BOOTSTRAPPED
diff --git a/src/corelib/global/qconfig.cpp.in b/src/corelib/global/qconfig.cpp.in
index 5c6ecf2485..016bdf40d1 100644
--- a/src/corelib/global/qconfig.cpp.in
+++ b/src/corelib/global/qconfig.cpp.in
@@ -1,33 +1,20 @@
-/* Installation date */
-static const char qt_configure_installation [12+11] = "qt_instdate=2012-12-20";
+/* This file is used to generate the Qt configuration info for the Core library.
+ * The 'qt_generate_qconfig_cpp' cmake routine
+ * contains variables that replace '@' entries in this file. It's important to
+ * align these values with the following:
+ *
+ * - QLibraryInfo::LibraryPath enum in qtbase/src/corelib/global/qlibraryinfo.h
+ * - qtConfEntries in qtbase/src/corelib/global/qlibraryinfo.cpp
+ */
+#include "private/qoffsetstringarray_p.h"
+
/* Installation Info */
-static const char qt_configure_prefix_path_str [12+256] = "qt_prfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@";
-#ifdef QT_BUILD_QMAKE
-static const char qt_configure_ext_prefix_path_str [12+256] = "qt_epfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@";
-static const char qt_configure_host_prefix_path_str [12+256] = "qt_hpfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@";
-#endif
-static const short qt_configure_str_offsets[] = {
-@QT_CONFIG_STR_OFFSETS_FIRST@
-#ifdef QT_BUILD_QMAKE
-@QT_CONFIG_STR_OFFSETS_SECOND@
-#endif
-};
-static const char qt_configure_strs[] =
-@QT_CONFIG_STRS_FIRST@
-#ifdef QT_BUILD_QMAKE
-@QT_CONFIG_STRS_SECOND@
-#endif
-;
-#define QT_CONFIGURE_SETTINGS_PATH "@QT_DEFAULT_SYS_CONF_DIR@"
-#define QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH "@QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH@"
-#define QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH "@QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH@"
-#define QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH "@QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH@"
-#ifdef QT_BUILD_QMAKE
-# define QT_CONFIGURE_CROSSBUILD 0
-# define QT_CONFIGURE_SYSROOTIFY_PREFIX false
-#endif
+static const char qt_configure_prefix_path_str [12+256] = "qt_prfxpath=@QT_CONFIGURE_PREFIX_PATH_STR@";
+
+static constexpr auto qt_configure_strs = QT_PREPEND_NAMESPACE(qOffsetStringArray)(
+@QT_CONFIG_STRS@
+);
+
+#define QT_CONFIGURE_SETTINGS_PATH "@QT_SYS_CONF_DIR@"
+#define QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH "@QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH@"_L1
#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12
-#ifdef QT_BUILD_QMAKE
-# define QT_CONFIGURE_EXT_PREFIX_PATH qt_configure_ext_prefix_path_str + 12
-# define QT_CONFIGURE_HOST_PREFIX_PATH qt_configure_host_prefix_path_str + 12
-#endif
diff --git a/src/corelib/global/qconstructormacros.h b/src/corelib/global/qconstructormacros.h
new file mode 100644
index 0000000000..21492ac31f
--- /dev/null
+++ b/src/corelib/global/qconstructormacros.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCONSTRUCTORMACROS_H
+#define QCONSTRUCTORMACROS_H
+
+#if 0
+#pragma qt_class(QtConstructorMacros)
+#pragma qt_sync_stop_processing
+#endif
+
+#if defined(__cplusplus)
+
+#ifndef Q_CONSTRUCTOR_FUNCTION
+# define Q_CONSTRUCTOR_FUNCTION0(AFUNC) \
+ namespace { \
+ static const struct AFUNC ## _ctor_class_ { \
+ inline AFUNC ## _ctor_class_() { AFUNC(); } \
+ } AFUNC ## _ctor_instance_; \
+ }
+
+# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
+#endif
+
+#ifndef Q_DESTRUCTOR_FUNCTION
+# define Q_DESTRUCTOR_FUNCTION0(AFUNC) \
+ namespace { \
+ static const struct AFUNC ## _dtor_class_ { \
+ inline AFUNC ## _dtor_class_() { } \
+ inline ~ AFUNC ## _dtor_class_() { AFUNC(); } \
+ } AFUNC ## _dtor_instance_; \
+ }
+# define Q_DESTRUCTOR_FUNCTION(AFUNC) Q_DESTRUCTOR_FUNCTION0(AFUNC)
+#endif
+
+#endif // __cplusplus
+
+#endif // QCONSTRUCTORMACROS_H
diff --git a/src/corelib/global/qcontainerinfo.h b/src/corelib/global/qcontainerinfo.h
new file mode 100644
index 0000000000..14468510a5
--- /dev/null
+++ b/src/corelib/global/qcontainerinfo.h
@@ -0,0 +1,229 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCONTAINERINFO_H
+#define QCONTAINERINFO_H
+
+#include <QtCore/qglobal.h>
+#include <type_traits>
+
+QT_BEGIN_NAMESPACE
+
+namespace QContainerInfo {
+
+template<typename C>
+using value_type = typename C::value_type;
+
+template<typename C>
+using key_type = typename C::key_type;
+
+template<typename C>
+using mapped_type = typename C::mapped_type;
+
+template<typename C>
+using iterator = typename C::iterator;
+
+template<typename C>
+using const_iterator = typename C::const_iterator;
+
+// Some versions of Apple clang warn about the constexpr variables below being unused.
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wunused-const-variable")
+
+template<typename C, typename = void>
+inline constexpr bool has_value_type_v = false;
+template<typename C>
+inline constexpr bool has_value_type_v<C, std::void_t<value_type<C>>> = true;
+
+template<typename C, typename = void>
+inline constexpr bool has_key_type_v = false;
+template<typename C>
+inline constexpr bool has_key_type_v<C, std::void_t<key_type<C>>> = true;
+
+template<typename C, typename = void>
+inline constexpr bool has_mapped_type_v = false;
+template<typename C>
+inline constexpr bool has_mapped_type_v<C, std::void_t<mapped_type<C>>> = true;
+
+template<typename C, typename = void>
+inline constexpr bool has_size_v = false;
+template<typename C>
+inline constexpr bool has_size_v<C, std::void_t<decltype(C().size())>> = true;
+
+template<typename C, typename = void>
+inline constexpr bool has_reserve_v = false;
+template<typename C>
+inline constexpr bool has_reserve_v<C, std::void_t<decltype(C().reserve(0))>> = true;
+
+template<typename C, typename = void>
+inline constexpr bool has_clear_v = false;
+template<typename C>
+inline constexpr bool has_clear_v<C, std::void_t<decltype(C().clear())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_at_index_v = false;
+template<typename C>
+inline constexpr bool has_at_index_v<C, std::void_t<decltype(C().at(0))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_at_key_v = false;
+template<typename C>
+inline constexpr bool has_at_key_v<C, std::void_t<decltype(C().at(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_get_at_index_v = false;
+template<typename C>
+inline constexpr bool can_get_at_index_v<C, std::void_t<value_type<C>(decltype(C()[0]))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_set_at_index_v = false;
+template<typename C>
+inline constexpr bool can_set_at_index_v<C, std::void_t<decltype(C()[0] = value_type<C>())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_push_front_v = false;
+template<typename C>
+inline constexpr bool has_push_front_v<C, std::void_t<decltype(C().push_front(value_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_push_back_v = false;
+template<typename C>
+inline constexpr bool has_push_back_v<C, std::void_t<decltype(C().push_back(value_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_insert_v = false;
+template<typename C>
+inline constexpr bool has_insert_v<C, std::void_t<decltype(C().insert(value_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_pop_front_v = false;
+template<typename C>
+inline constexpr bool has_pop_front_v<C, std::void_t<decltype(C().pop_front())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_pop_back_v = false;
+template<typename C>
+inline constexpr bool has_pop_back_v<C, std::void_t<decltype(C().pop_back())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_iterator_v = false;
+template<typename C>
+inline constexpr bool has_iterator_v<C, std::void_t<iterator<C>>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_const_iterator_v = false;
+template<typename C>
+inline constexpr bool has_const_iterator_v<C, std::void_t<const_iterator<C>>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_set_value_at_iterator_v = false;
+template<typename C>
+inline constexpr bool can_set_value_at_iterator_v<C, std::void_t<decltype(*C().begin() = value_type<C>())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_set_mapped_at_iterator_v = false;
+template<typename C>
+inline constexpr bool can_set_mapped_at_iterator_v<C, std::void_t<decltype(*C().begin() = mapped_type<C>())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_insert_value_at_iterator_v = false;
+template<typename C>
+inline constexpr bool can_insert_value_at_iterator_v<C, std::void_t<decltype(C().insert(C().begin(), value_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_erase_at_iterator_v = false;
+template<typename C>
+inline constexpr bool can_erase_at_iterator_v<C, std::void_t<decltype(C().erase(C().begin()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_erase_range_at_iterator_v = false;
+template<typename C>
+inline constexpr bool can_erase_range_at_iterator_v<C, std::void_t<decltype(C().erase(C().begin(), C().end()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_get_at_key_v = false;
+template<typename C>
+inline constexpr bool can_get_at_key_v<C, std::void_t<mapped_type<C>(decltype(C()[key_type<C>()]))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_set_at_key_v = false;
+template<typename C>
+inline constexpr bool can_set_at_key_v<C, std::void_t<decltype(C()[key_type<C>()] = mapped_type<C>())>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_erase_at_key_v = false;
+template<typename C>
+inline constexpr bool can_erase_at_key_v<C, std::void_t<decltype(C().erase(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_remove_at_key_v = false;
+template<typename C>
+inline constexpr bool can_remove_at_key_v<C, std::void_t<decltype(C().remove(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_insert_key_v = false;
+template<typename C>
+inline constexpr bool can_insert_key_v<C, std::void_t<decltype(C().insert(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_insert_pair_v = false;
+template<typename C>
+inline constexpr bool can_insert_pair_v<C, std::void_t<decltype(C().insert({key_type<C>(), mapped_type<C>()}))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool can_insert_key_mapped_v = false;
+template<typename C>
+inline constexpr bool can_insert_key_mapped_v<C, std::void_t<decltype(C().insert(key_type<C>(), mapped_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_contains_v = false;
+template<typename C>
+inline constexpr bool has_contains_v<C, std::void_t<decltype(bool(C().contains(key_type<C>())))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool has_find_v = false;
+template<typename C>
+inline constexpr bool has_find_v<C, std::void_t<decltype(C().find(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool iterator_dereferences_to_value_v = false;
+template<typename C>
+inline constexpr bool iterator_dereferences_to_value_v<C, std::void_t<decltype(value_type<C>(*C().begin()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool iterator_has_key_v = false;
+template<typename C>
+inline constexpr bool iterator_has_key_v<C, std::void_t<decltype(key_type<C>(C().begin().key()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool value_type_has_first_v = false;
+template<typename C>
+inline constexpr bool value_type_has_first_v<C, std::void_t<decltype(key_type<C>(value_type<C>().first))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool iterator_dereferences_to_key_v = false;
+template<typename C>
+inline constexpr bool iterator_dereferences_to_key_v<C, std::void_t<decltype(key_type<C>(*C().begin()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool iterator_has_value_v = false;
+template<typename C>
+inline constexpr bool iterator_has_value_v<C, std::void_t<decltype(mapped_type<C>(C().begin().value()))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool value_type_has_second_v = false;
+template<typename C>
+inline constexpr bool value_type_has_second_v<C, std::void_t<decltype(mapped_type<C>(value_type<C>().second))>> = true;
+
+template<typename, typename = void>
+inline constexpr bool iterator_dereferences_to_mapped_v = false;
+template<typename C>
+inline constexpr bool iterator_dereferences_to_mapped_v<C, std::void_t<decltype(mapped_type<C>(*C().begin()))>> = true;
+
+QT_WARNING_POP
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QCONTAINERINFO_H
diff --git a/src/corelib/global/qdarwinhelpers.h b/src/corelib/global/qdarwinhelpers.h
new file mode 100644
index 0000000000..ad72211663
--- /dev/null
+++ b/src/corelib/global/qdarwinhelpers.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTDARWINHELPERS_H
+#define QTDARWINHELPERS_H
+
+#if 0
+#pragma qt_class(QtDarwinHelpers)
+#pragma qt_sync_stop_processing
+#endif
+
+/*
+ Utility macros and inline functions
+*/
+
+#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
+# ifdef __OBJC__
+# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
+# else
+# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) class classname
+# endif
+#endif
+#ifndef Q_FORWARD_DECLARE_CF_TYPE
+# define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
+#endif
+#ifndef Q_FORWARD_DECLARE_MUTABLE_CF_TYPE
+# define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
+#endif
+#ifndef Q_FORWARD_DECLARE_CG_TYPE
+# define Q_FORWARD_DECLARE_CG_TYPE(type) typedef const struct type *type##Ref
+#endif
+#ifndef Q_FORWARD_DECLARE_MUTABLE_CG_TYPE
+# define Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(type) typedef struct type *type##Ref
+#endif
+
+
+#endif // QTDARWINHELPERS_H
diff --git a/src/corelib/global/qdarwinhelpers.qdoc b/src/corelib/global/qdarwinhelpers.qdoc
new file mode 100644
index 0000000000..a827526634
--- /dev/null
+++ b/src/corelib/global/qdarwinhelpers.qdoc
@@ -0,0 +1,34 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro Q_FORWARD_DECLARE_OBJC_CLASS(classname)
+ \since 5.2
+ \relates <QtDarwinHelpers>
+
+ Forward-declares an Objective-C \a classname in a manner such that it can be
+ compiled as either Objective-C or C++.
+
+ This is primarily intended for use in header files that may be included by
+ both Objective-C and C++ source files.
+*/
+
+/*!
+ \macro Q_FORWARD_DECLARE_CF_TYPE(type)
+ \since 5.2
+ \relates <QtDarwinHelpers>
+
+ Forward-declares a Core Foundation \a type. This includes the actual
+ type and the ref type. For example, Q_FORWARD_DECLARE_CF_TYPE(CFString)
+ declares __CFString and CFStringRef.
+*/
+
+/*!
+ \macro Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type)
+ \since 5.2
+ \relates <QtDarwinHelpers>
+
+ Forward-declares a mutable Core Foundation \a type. This includes the actual
+ type and the ref type. For example, Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(CFMutableString)
+ declares __CFMutableString and CFMutableStringRef.
+*/
diff --git a/src/corelib/global/qendian.cpp b/src/corelib/global/qendian.cpp
index c69572cccf..5e46109dd1 100644
--- a/src/corelib/global/qendian.cpp
+++ b/src/corelib/global/qendian.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qendian.h"
@@ -47,6 +11,7 @@ QT_BEGIN_NAMESPACE
/*!
\headerfile <QtEndian>
+ \inmodule QtCore
\title Endian Conversion Functions
\ingroup funclists
\brief The <QtEndian> header provides functions to convert between
@@ -434,28 +399,28 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename T> QLEInteger &QLEInteger<T>::operator++()
- Performs a prefix ++ (increment) on this QLEInteger and returns a reference to
+ Performs a prefix \c{++} (increment) on this QLEInteger and returns a reference to
this object.
*/
/*!
\fn template <typename T> QLEInteger QLEInteger<T>::operator++(int)
- Performs a postfix ++ (increment) on this QLEInteger and returns a reference to
+ Performs a postfix \c{++} (increment) on this QLEInteger and returns a reference to
this object.
*/
/*!
\fn template <typename T> QLEInteger &QLEInteger<T>::operator--()
- Performs a prefix -- (decrement) on this QLEInteger and returns a reference to
+ Performs a prefix \c{--} (decrement) on this QLEInteger and returns a reference to
this object.
*/
/*!
\fn template <typename T> QLEInteger QLEInteger<T>::operator--(int)
- Performs a postfix -- (decrement) on this QLEInteger and returns a reference to
+ Performs a postfix \c{--} (decrement) on this QLEInteger and returns a reference to
this object.
*/
@@ -480,8 +445,8 @@ QT_BEGIN_NAMESPACE
The template parameter \c T must be a C++ integer type:
\list
\li 8-bit: char, signed char, unsigned char, qint8, quint8
- \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
- \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t
\li 64-bit: long long, unsigned long long, qint64, quint64
\li platform-specific size: long, unsigned long
\li pointer size: qintptr, quintptr, qptrdiff
@@ -593,28 +558,28 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename T> QBEInteger &QBEInteger<T>::operator++()
- Performs a prefix ++ (increment) on this QBEInteger and returns a reference to
+ Performs a prefix \c{++} (increment) on this QBEInteger and returns a reference to
this object.
*/
/*!
\fn template <typename T> QBEInteger QBEInteger<T>::operator++(int)
- Performs a postfix ++ (increment) on this QBEInteger and returns a reference to
+ Performs a postfix \c{++} (increment) on this QBEInteger and returns a reference to
this object.
*/
/*!
\fn template <typename T> QBEInteger &QBEInteger<T>::operator--()
- Performs a prefix -- (decrement) on this QBEInteger and returns a reference to
+ Performs a prefix \c{--} (decrement) on this QBEInteger and returns a reference to
this object.
*/
/*!
\fn template <typename T> QBEInteger QBEInteger<T>::operator--(int)
- Performs a postfix -- (decrement) on this QBEInteger and returns a reference to
+ Performs a postfix \c{--} (decrement) on this QBEInteger and returns a reference to
this object.
*/
@@ -815,7 +780,7 @@ size_t simdSwapLoop(const uchar *src, size_t bytes, uchar *dst) noexcept
size_t i = sseSwapLoop(src, bytes, dst, shuffleMaskPtr);
// epilogue
- for (size_t _i = 0 ; i < bytes && _i < sizeof(__m128i); i += sizeof(T), _i += sizeof(T))
+ for (size_t _i = 0; i < bytes && _i < sizeof(__m128i); i += sizeof(T), _i += sizeof(T))
qbswap(qFromUnaligned<T>(src + i), dst + i);
// return the total, so the bswapLoop below does nothing
@@ -886,12 +851,13 @@ void *bswapLoop(const uchar *src, size_t n, uchar *dst) noexcept
size_t i = simdSwapLoop<T>(src, n, dst);
- for ( ; i < n; i += sizeof(T))
+ for (; i < n; i += sizeof(T))
qbswap(qFromUnaligned<T>(src + i), dst + i);
return dst + i;
}
-template <> void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcept
+template<>
+void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcept
{
const uchar *src = reinterpret_cast<const uchar *>(source);
uchar *dst = reinterpret_cast<uchar *>(dest);
@@ -899,7 +865,8 @@ template <> void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcep
return bswapLoop<quint16>(src, n << 1, dst);
}
-template <> void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcept
+template<>
+void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcept
{
const uchar *src = reinterpret_cast<const uchar *>(source);
uchar *dst = reinterpret_cast<uchar *>(dest);
@@ -907,7 +874,8 @@ template <> void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcep
return bswapLoop<quint32>(src, n << 2, dst);
}
-template <> void *qbswap<8>(const void *source, qsizetype n, void *dest) noexcept
+template<>
+void *qbswap<8>(const void *source, qsizetype n, void *dest) noexcept
{
const uchar *src = reinterpret_cast<const uchar *>(source);
uchar *dst = reinterpret_cast<uchar *>(dest);
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h
index a50ade4aa4..8c3b5e4374 100644
--- a/src/corelib/global/qendian.h
+++ b/src/corelib/global/qendian.h
@@ -1,49 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QENDIAN_H
#define QENDIAN_H
+#if 0
+#pragma qt_class(QtEndian)
+#endif
+
#include <QtCore/qfloat16.h>
#include <QtCore/qglobal.h>
+#include <limits>
+
// include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
#include <stdlib.h>
#include <string.h>
@@ -89,7 +59,7 @@ template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
// These definitions are written so that they are recognized by most compilers
// as bswap and replaced with single instruction builtins if available.
-inline Q_DECL_CONSTEXPR quint64 qbswap_helper(quint64 source)
+inline constexpr quint64 qbswap_helper(quint64 source)
{
return 0
| ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
@@ -102,7 +72,7 @@ inline Q_DECL_CONSTEXPR quint64 qbswap_helper(quint64 source)
| ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
}
-inline Q_DECL_CONSTEXPR quint32 qbswap_helper(quint32 source)
+inline constexpr quint32 qbswap_helper(quint32 source)
{
return 0
| ((source & 0x000000ff) << 24)
@@ -111,30 +81,47 @@ inline Q_DECL_CONSTEXPR quint32 qbswap_helper(quint32 source)
| ((source & 0xff000000) >> 24);
}
-inline Q_DECL_CONSTEXPR quint16 qbswap_helper(quint16 source)
+inline constexpr quint16 qbswap_helper(quint16 source)
{
return quint16( 0
| ((source & 0x00ff) << 8)
| ((source & 0xff00) >> 8) );
}
-inline Q_DECL_CONSTEXPR quint8 qbswap_helper(quint8 source)
+inline constexpr quint8 qbswap_helper(quint8 source)
{
return source;
}
/*
* T qbswap(T source).
- * Changes the byte order of a value from big endian to little endian or vice versa.
+ * Changes the byte order of a value from big-endian to little-endian or vice versa.
* This function can be used if you are not concerned about alignment issues,
* and it is therefore a bit more convenient and in most cases more efficient.
*/
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
-inline Q_DECL_CONSTEXPR T qbswap(T source)
+inline constexpr T qbswap(T source)
{
return T(qbswap_helper(typename QIntegerForSizeof<T>::Unsigned(source)));
}
+#ifdef QT_SUPPORTS_INT128
+// extra definitions for q(u)int128, in case std::is_integral_v<~~> == false
+inline constexpr quint128 qbswap(quint128 source)
+{
+ quint128 result = {};
+ result = qbswap_helper(quint64(source));
+ result <<= 64;
+ result |= qbswap_helper(quint64(source >> 64));
+ return result;
+}
+
+inline constexpr qint128 qbswap(qint128 source)
+{
+ return qint128(qbswap(quint128(source)));
+}
+#endif
+
// floating specializations
template<typename Float>
Float qbswapFloatHelper(Float source)
@@ -162,7 +149,7 @@ inline double qbswap(double source)
/*
* qbswap(const T src, const void *dest);
- * Changes the byte order of \a src from big endian to little endian or vice versa
+ * Changes the byte order of \a src from big-endian to little-endian or vice versa
* and stores the result in \a dest.
* There is no alignment requirements for \a dest.
*/
@@ -182,13 +169,13 @@ template<> Q_CORE_EXPORT void *qbswap<8>(const void *source, qsizetype count, vo
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
-template <typename T> inline Q_DECL_CONSTEXPR T qToBigEndian(T source)
+template <typename T> inline constexpr T qToBigEndian(T source)
{ return source; }
-template <typename T> inline Q_DECL_CONSTEXPR T qFromBigEndian(T source)
+template <typename T> inline constexpr T qFromBigEndian(T source)
{ return source; }
-template <typename T> inline Q_DECL_CONSTEXPR T qToLittleEndian(T source)
+template <typename T> inline constexpr T qToLittleEndian(T source)
{ return qbswap(source); }
-template <typename T> inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source)
+template <typename T> inline constexpr T qFromLittleEndian(T source)
{ return qbswap(source); }
template <typename T> inline void qToBigEndian(T src, void *dest)
{ qToUnaligned<T>(src, dest); }
@@ -205,13 +192,13 @@ template <typename T> inline void qFromLittleEndian(const void *source, qsizetyp
{ qbswap<sizeof(T)>(source, count, dest); }
#else // Q_LITTLE_ENDIAN
-template <typename T> inline Q_DECL_CONSTEXPR T qToBigEndian(T source)
+template <typename T> inline constexpr T qToBigEndian(T source)
{ return qbswap(source); }
-template <typename T> inline Q_DECL_CONSTEXPR T qFromBigEndian(T source)
+template <typename T> inline constexpr T qFromBigEndian(T source)
{ return qbswap(source); }
-template <typename T> inline Q_DECL_CONSTEXPR T qToLittleEndian(T source)
+template <typename T> inline constexpr T qToLittleEndian(T source)
{ return source; }
-template <typename T> inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source)
+template <typename T> inline constexpr T qFromLittleEndian(T source)
{ return source; }
template <typename T> inline void qToBigEndian(T src, void *dest)
{ qbswap<T>(src, dest); }
@@ -265,7 +252,7 @@ class QSpecialInteger
T val;
public:
QSpecialInteger() = default;
- explicit Q_DECL_CONSTEXPR QSpecialInteger(T i) : val(S::toSpecial(i)) {}
+ explicit constexpr QSpecialInteger(T i) : val(S::toSpecial(i)) {}
QSpecialInteger &operator =(T i) { val = S::toSpecial(i); return *this; }
operator T() const { return S::fromSpecial(val); }
@@ -310,33 +297,33 @@ public:
return pre;
}
- static Q_DECL_CONSTEXPR QSpecialInteger max()
- { return QSpecialInteger(std::numeric_limits<T>::max()); }
- static Q_DECL_CONSTEXPR QSpecialInteger min()
- { return QSpecialInteger(std::numeric_limits<T>::min()); }
+ static constexpr QSpecialInteger max()
+ { return QSpecialInteger((std::numeric_limits<T>::max)()); }
+ static constexpr QSpecialInteger min()
+ { return QSpecialInteger((std::numeric_limits<T>::min)()); }
};
template<typename T>
class QLittleEndianStorageType {
public:
typedef T StorageType;
- static Q_DECL_CONSTEXPR T toSpecial(T source) { return qToLittleEndian(source); }
- static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromLittleEndian(source); }
+ static constexpr T toSpecial(T source) { return qToLittleEndian(source); }
+ static constexpr T fromSpecial(T source) { return qFromLittleEndian(source); }
};
template<typename T>
class QBigEndianStorageType {
public:
typedef T StorageType;
- static Q_DECL_CONSTEXPR T toSpecial(T source) { return qToBigEndian(source); }
- static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromBigEndian(source); }
+ static constexpr T toSpecial(T source) { return qToBigEndian(source); }
+ static constexpr T fromSpecial(T source) { return qFromBigEndian(source); }
};
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
template<typename T>
class QLEInteger {
public:
- explicit Q_DECL_CONSTEXPR QLEInteger(T i);
+ explicit constexpr QLEInteger(T i);
QLEInteger &operator =(T i);
operator T() const;
bool operator ==(QLEInteger i) const;
@@ -353,17 +340,17 @@ public:
QLEInteger &operator ^=(T i);
QLEInteger &operator ++();
QLEInteger &operator --();
- QLEInteger &operator ++(int);
- QLEInteger &operator --(int);
+ QLEInteger operator ++(int);
+ QLEInteger operator --(int);
- static Q_DECL_CONSTEXPR QLEInteger max();
- static Q_DECL_CONSTEXPR QLEInteger min();
+ static constexpr QLEInteger max();
+ static constexpr QLEInteger min();
};
template<typename T>
class QBEInteger {
public:
- explicit Q_DECL_CONSTEXPR QBEInteger(T i);
+ explicit constexpr QBEInteger(T i);
QBEInteger &operator =(T i);
operator T() const;
bool operator ==(QBEInteger i) const;
@@ -380,11 +367,11 @@ public:
QBEInteger &operator ^=(T i);
QBEInteger &operator ++();
QBEInteger &operator --();
- QBEInteger &operator ++(int);
- QBEInteger &operator --(int);
+ QBEInteger operator ++(int);
+ QBEInteger operator --(int);
- static Q_DECL_CONSTEXPR QBEInteger max();
- static Q_DECL_CONSTEXPR QBEInteger min();
+ static constexpr QBEInteger max();
+ static constexpr QBEInteger min();
};
#else
diff --git a/src/corelib/global/qendian_p.h b/src/corelib/global/qendian_p.h
index c830e65b54..8d96eba60c 100644
--- a/src/corelib/global/qendian_p.h
+++ b/src/corelib/global/qendian_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QENDIAN_P_H
#define QENDIAN_P_H
@@ -52,90 +16,195 @@
//
#include <QtCore/qendian.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
-// Note if using multiple of these bitfields in a union; the underlying storage type must
-// match. Since we always use an unsigned storage type, unsigned and signed versions may
-// be used together, but different bit-widths may not.
-template<class S, int pos, int width>
-class QSpecialIntegerBitfield
+enum class QSpecialIntegerBitfieldInitializer {};
+constexpr QSpecialIntegerBitfieldInitializer QSpecialIntegerBitfieldZero{};
+
+template<class S>
+class QSpecialIntegerStorage
+{
+public:
+ using UnsignedStorageType = std::make_unsigned_t<typename S::StorageType>;
+
+ constexpr QSpecialIntegerStorage() = default;
+ constexpr QSpecialIntegerStorage(QSpecialIntegerBitfieldInitializer) : val(0) {}
+ constexpr QSpecialIntegerStorage(UnsignedStorageType initial) : val(initial) {}
+
+ UnsignedStorageType val;
+};
+
+template<class S, int pos, int width, class T = typename S::StorageType>
+class QSpecialIntegerAccessor;
+
+template<class S, int pos, int width, class T = typename S::StorageType>
+class QSpecialIntegerConstAccessor
{
-protected:
- typedef typename S::StorageType T;
- typedef typename std::make_unsigned<T>::type UT;
+ Q_DISABLE_COPY_MOVE(QSpecialIntegerConstAccessor)
+public:
+ using Storage = const QSpecialIntegerStorage<S>;
+ using Type = T;
+ using UnsignedType = std::make_unsigned_t<T>;
- static Q_DECL_CONSTEXPR UT mask()
+ operator Type() const noexcept
{
- return ((UT(1) << width) - 1) << pos;
+ if constexpr (std::is_signed_v<Type>) {
+ UnsignedType i = S::fromSpecial(storage->val);
+ i <<= (sizeof(Type) * 8) - width - pos;
+ Type t = Type(i);
+ t >>= (sizeof(Type) * 8) - width;
+ return t;
+ }
+ return (S::fromSpecial(storage->val) & mask()) >> pos;
}
+
+ bool operator!() const noexcept { return !(storage->val & S::toSpecial(mask())); }
+
+ static constexpr UnsignedType mask() noexcept
+ {
+ if constexpr (width == sizeof(UnsignedType) * 8) {
+ static_assert(pos == 0);
+ return ~UnsignedType(0);
+ } else {
+ return ((UnsignedType(1) << width) - 1) << pos;
+ }
+ }
+
+private:
+ template<class Storage, typename... Accessors>
+ friend class QSpecialIntegerBitfieldUnion;
+ friend class QSpecialIntegerAccessor<S, pos, width, T>;
+
+ explicit QSpecialIntegerConstAccessor(Storage *storage) : storage(storage) {}
+
+ friend bool operator==(const QSpecialIntegerConstAccessor<S, pos, width, T> &i,
+ const QSpecialIntegerConstAccessor<S, pos, width, T> &j) noexcept
+ {
+ return ((i.storage->val ^ j.storage->val) & S::toSpecial(mask())) == 0;
+ }
+
+ friend bool operator!=(const QSpecialIntegerConstAccessor<S, pos, width, T> &i,
+ const QSpecialIntegerConstAccessor<S, pos, width, T> &j) noexcept
+ {
+ return ((i.storage->val ^ j.storage->val) & S::toSpecial(mask())) != 0;
+ }
+
+ Storage *storage;
+};
+
+template<class S, int pos, int width, class T>
+class QSpecialIntegerAccessor
+{
+ Q_DISABLE_COPY_MOVE(QSpecialIntegerAccessor)
public:
- // FIXME: val is public until qtdeclarative is fixed to not access it directly.
- UT val;
+ using Const = QSpecialIntegerConstAccessor<S, pos, width, T>;
+ using Storage = QSpecialIntegerStorage<S>;
+ using Type = T;
+ using UnsignedType = std::make_unsigned_t<T>;
- QSpecialIntegerBitfield &operator =(T t)
+ QSpecialIntegerAccessor &operator=(Type t)
{
- UT i = S::fromSpecial(val);
- i &= ~mask();
- i |= (UT(t) << pos) & mask();
- val = S::toSpecial(i);
+ UnsignedType i = S::fromSpecial(storage->val);
+ i &= ~Const::mask();
+ i |= (UnsignedType(t) << pos) & Const::mask();
+ storage->val = S::toSpecial(i);
return *this;
}
- operator T() const
+
+ operator Const() { return Const(storage); }
+
+private:
+ template<class Storage, typename... Accessors>
+ friend class QSpecialIntegerBitfieldUnion;
+
+ explicit QSpecialIntegerAccessor(Storage *storage) : storage(storage) {}
+
+ Storage *storage;
+};
+
+template<class S, typename... Accessors>
+class QSpecialIntegerBitfieldUnion
+{
+public:
+ constexpr QSpecialIntegerBitfieldUnion() = default;
+ constexpr QSpecialIntegerBitfieldUnion(QSpecialIntegerBitfieldInitializer initial)
+ : storage(initial)
+ {}
+
+ constexpr QSpecialIntegerBitfieldUnion(
+ typename QSpecialIntegerStorage<S>::UnsignedStorageType initial)
+ : storage(initial)
+ {}
+
+ template<typename A>
+ void set(typename A::Type value)
{
- if (std::is_signed<T>::value) {
- UT i = S::fromSpecial(val);
- i <<= (sizeof(T) * 8) - width - pos;
- T t = T(i);
- t >>= (sizeof(T) * 8) - width;
- return t;
- }
- return (S::fromSpecial(val) & mask()) >> pos;
+ member<A>() = value;
+ }
+
+ template<typename A>
+ typename A::Type get() const
+ {
+ return member<A>();
+ }
+
+ typename QSpecialIntegerStorage<S>::UnsignedStorageType data() const
+ {
+ return storage.val;
+ }
+
+private:
+ template<typename A>
+ static constexpr bool isAccessor = std::disjunction_v<std::is_same<A, Accessors>...>;
+
+ template<typename A>
+ A member()
+ {
+ static_assert(isAccessor<A>);
+ return A(&storage);
+ }
+
+ template<typename A>
+ typename A::Const member() const
+ {
+ static_assert(isAccessor<A>);
+ return typename A::Const(&storage);
}
- bool operator !() const { return !(val & S::toSpecial(mask())); }
- bool operator ==(QSpecialIntegerBitfield<S, pos, width> i) const
- { return ((val ^ i.val) & S::toSpecial(mask())) == 0; }
- bool operator !=(QSpecialIntegerBitfield<S, pos, width> i) const
- { return ((val ^ i.val) & S::toSpecial(mask())) != 0; }
-
- QSpecialIntegerBitfield &operator +=(T i)
- { return (*this = (T(*this) + i)); }
- QSpecialIntegerBitfield &operator -=(T i)
- { return (*this = (T(*this) - i)); }
- QSpecialIntegerBitfield &operator *=(T i)
- { return (*this = (T(*this) * i)); }
- QSpecialIntegerBitfield &operator /=(T i)
- { return (*this = (T(*this) / i)); }
- QSpecialIntegerBitfield &operator %=(T i)
- { return (*this = (T(*this) % i)); }
- QSpecialIntegerBitfield &operator |=(T i)
- { return (*this = (T(*this) | i)); }
- QSpecialIntegerBitfield &operator &=(T i)
- { return (*this = (T(*this) & i)); }
- QSpecialIntegerBitfield &operator ^=(T i)
- { return (*this = (T(*this) ^ i)); }
- QSpecialIntegerBitfield &operator >>=(T i)
- { return (*this = (T(*this) >> i)); }
- QSpecialIntegerBitfield &operator <<=(T i)
- { return (*this = (T(*this) << i)); }
+ QSpecialIntegerStorage<S> storage;
};
-template<typename T, int pos, int width>
-using QLEIntegerBitfield = QSpecialIntegerBitfield<QLittleEndianStorageType<T>, pos, width>;
+template<typename T, typename... Accessors>
+using QLEIntegerBitfieldUnion
+ = QSpecialIntegerBitfieldUnion<QLittleEndianStorageType<T>, Accessors...>;
-template<typename T, int pos, int width>
-using QBEIntegerBitfield = QSpecialIntegerBitfield<QBigEndianStorageType<T>, pos, width>;
+template<typename T, typename... Accessors>
+using QBEIntegerBitfieldUnion
+ = QSpecialIntegerBitfieldUnion<QBigEndianStorageType<T>, Accessors...>;
-template<int pos, int width>
-using qint32_le_bitfield = QLEIntegerBitfield<int, pos, width>;
-template<int pos, int width>
-using quint32_le_bitfield = QLEIntegerBitfield<uint, pos, width>;
-template<int pos, int width>
-using qint32_be_bitfield = QBEIntegerBitfield<int, pos, width>;
-template<int pos, int width>
-using quint32_be_bitfield = QBEIntegerBitfield<uint, pos, width>;
+template<typename... Accessors>
+using qint32_le_bitfield_union = QLEIntegerBitfieldUnion<int, Accessors...>;
+template<typename... Accessors>
+using quint32_le_bitfield_union = QLEIntegerBitfieldUnion<uint, Accessors...>;
+template<typename... Accessors>
+using qint32_be_bitfield_union = QBEIntegerBitfieldUnion<int, Accessors...>;
+template<typename... Accessors>
+using quint32_be_bitfield_union = QBEIntegerBitfieldUnion<uint, Accessors...>;
+template<int pos, int width, typename T = int>
+using qint32_le_bitfield_member
+ = QSpecialIntegerAccessor<QLittleEndianStorageType<int>, pos, width, T>;
+template<int pos, int width, typename T = uint>
+using quint32_le_bitfield_member
+ = QSpecialIntegerAccessor<QLittleEndianStorageType<uint>, pos, width, T>;
+template<int pos, int width, typename T = int>
+using qint32_be_bitfield_member
+ = QSpecialIntegerAccessor<QBigEndianStorageType<int>, pos, width, T>;
+template<int pos, int width, typename T = uint>
+using quint32_be_bitfield_member
+ = QSpecialIntegerAccessor<QBigEndianStorageType<uint>, pos, width, T>;
QT_END_NAMESPACE
diff --git a/src/corelib/global/qexceptionhandling.cpp b/src/corelib/global/qexceptionhandling.cpp
new file mode 100644
index 0000000000..f74eb49546
--- /dev/null
+++ b/src/corelib/global/qexceptionhandling.cpp
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qexceptionhandling.h"
+
+#include <exception>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ \internal
+ Allows you to call std::terminate() without including <exception>.
+ Called internally from QT_TERMINATE_ON_EXCEPTION
+*/
+Q_NORETURN void qTerminate() noexcept
+{
+ std::terminate();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qexceptionhandling.h b/src/corelib/global/qexceptionhandling.h
new file mode 100644
index 0000000000..76c6185c3e
--- /dev/null
+++ b/src/corelib/global/qexceptionhandling.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QEXCEPTIONHANDLING_H
+#define QEXCEPTIONHANDLING_H
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtcoreexports.h>
+
+#if 0
+#pragma qt_class(QtExceptionHandling)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/* These wrap try/catch so we can switch off exceptions later.
+
+ Beware - do not use more than one QT_CATCH per QT_TRY, and do not use
+ the exception instance in the catch block.
+ If you can't live with those constraints, don't use these macros.
+ Use the QT_NO_EXCEPTIONS macro to protect your code instead.
+*/
+Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() noexcept;
+#ifdef QT_NO_EXCEPTIONS
+# define QT_TRY if (true)
+# define QT_CATCH(A) else
+# define QT_THROW(A) qt_noop()
+# define QT_RETHROW qt_noop()
+# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
+#else
+# define QT_TRY try
+# define QT_CATCH(A) catch (A)
+# define QT_THROW(A) throw A
+# define QT_RETHROW throw
+# ifdef Q_COMPILER_NOEXCEPT
+# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
+# else
+# define QT_TERMINATE_ON_EXCEPTION(expr) do { try { expr; } catch (...) { qTerminate(); } } while (false)
+# endif
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QEXCEPTIONHANDLING_H
diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h
index 3cb46e3a01..cc028e0095 100644
--- a/src/corelib/global/qflags.h
+++ b/src/corelib/global/qflags.h
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFLAGS_H
#define QFLAGS_H
+#include <QtCore/qcompare_impl.h>
+#include <QtCore/qtypeinfo.h>
+
#include <initializer_list>
QT_BEGIN_NAMESPACE
@@ -52,21 +17,21 @@ class QFlag
{
int i;
public:
- Q_DECL_CONSTEXPR inline QFlag(int value) noexcept : i(value) {}
- Q_DECL_CONSTEXPR inline operator int() const noexcept { return i; }
+ constexpr inline Q_IMPLICIT QFlag(int value) noexcept : i(value) {}
+ constexpr inline Q_IMPLICIT operator int() const noexcept { return i; }
#if !defined(Q_CC_MSVC)
// Microsoft Visual Studio has buggy behavior when it comes to
// unsigned enums: even if the enum is unsigned, the enum tags are
// always signed
-# if !defined(__LP64__) && !defined(Q_CLANG_QDOC)
- Q_DECL_CONSTEXPR inline QFlag(long value) noexcept : i(int(value)) {}
- Q_DECL_CONSTEXPR inline QFlag(ulong value) noexcept : i(int(long(value))) {}
+# if !defined(__LP64__) && !defined(Q_QDOC)
+ constexpr inline Q_IMPLICIT QFlag(long value) noexcept : i(int(value)) {}
+ constexpr inline Q_IMPLICIT QFlag(ulong value) noexcept : i(int(long(value))) {}
# endif
- Q_DECL_CONSTEXPR inline QFlag(uint value) noexcept : i(int(value)) {}
- Q_DECL_CONSTEXPR inline QFlag(short value) noexcept : i(int(value)) {}
- Q_DECL_CONSTEXPR inline QFlag(ushort value) noexcept : i(int(uint(value))) {}
- Q_DECL_CONSTEXPR inline operator uint() const noexcept { return uint(i); }
+ constexpr inline Q_IMPLICIT QFlag(uint value) noexcept : i(int(value)) {}
+ constexpr inline Q_IMPLICIT QFlag(short value) noexcept : i(int(value)) {}
+ constexpr inline Q_IMPLICIT QFlag(ushort value) noexcept : i(int(uint(value))) {}
+ constexpr inline Q_IMPLICIT operator uint() const noexcept { return uint(i); }
#endif
};
Q_DECLARE_TYPEINFO(QFlag, Q_PRIMITIVE_TYPE);
@@ -75,32 +40,24 @@ class QIncompatibleFlag
{
int i;
public:
- Q_DECL_CONSTEXPR inline explicit QIncompatibleFlag(int i) noexcept;
- Q_DECL_CONSTEXPR inline operator int() const noexcept { return i; }
+ constexpr inline explicit QIncompatibleFlag(int i) noexcept;
+ constexpr inline Q_IMPLICIT operator int() const noexcept { return i; }
};
Q_DECLARE_TYPEINFO(QIncompatibleFlag, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline QIncompatibleFlag::QIncompatibleFlag(int value) noexcept : i(value) {}
-
+constexpr inline QIncompatibleFlag::QIncompatibleFlag(int value) noexcept : i(value) {}
-#ifndef Q_NO_TYPESAFE_FLAGS
template<typename Enum>
class QFlags
{
static_assert((sizeof(Enum) <= sizeof(int)),
- "QFlags uses an int as storage, so an enum with underlying "
- "long long will overflow.");
+ "QFlags uses an int as storage, so an enum with underlying "
+ "long long will overflow.");
static_assert((std::is_enum<Enum>::value), "QFlags is only usable on enumeration types.");
-#if QT_DEPRECATED_SINCE(5,15)
- struct Private;
- typedef int (Private::*Zero);
-#endif
- template <typename E> friend QDataStream &operator>>(QDataStream &, QFlags<E> &);
- template <typename E> friend QDataStream &operator<<(QDataStream &, QFlags<E>);
public:
-#if defined(Q_CC_MSVC) || defined(Q_CLANG_QDOC)
+#if defined(Q_CC_MSVC) || defined(Q_QDOC)
// see above for MSVC
// the definition below is too complex for qdoc
typedef int Int;
@@ -113,49 +70,97 @@ public:
#endif
typedef Enum enum_type;
// compiler-generated copy/move ctor/assignment operators are fine!
-#ifdef Q_CLANG_QDOC
- Q_DECL_CONSTEXPR inline QFlags(const QFlags &other);
- Q_DECL_CONSTEXPR inline QFlags &operator=(const QFlags &other);
-#endif
- Q_DECL_CONSTEXPR inline QFlags() noexcept : i(0) {}
- Q_DECL_CONSTEXPR inline QFlags(Enum flags) noexcept : i(Int(flags)) {}
-#if QT_DEPRECATED_SINCE(5,15)
- QT_DEPRECATED_X("Use default constructor instead") Q_DECL_CONSTEXPR inline QFlags(Zero) noexcept : i(0) {}
-#endif
- Q_DECL_CONSTEXPR inline QFlags(QFlag flag) noexcept : i(flag) {}
+ constexpr inline QFlags() noexcept : i(0) {}
+ constexpr inline Q_IMPLICIT QFlags(Enum flags) noexcept : i(Int(flags)) {}
+ constexpr inline Q_IMPLICIT QFlags(QFlag flag) noexcept : i(flag) {}
- Q_DECL_CONSTEXPR inline QFlags(std::initializer_list<Enum> flags) noexcept
+ constexpr inline QFlags(std::initializer_list<Enum> flags) noexcept
: i(initializer_list_helper(flags.begin(), flags.end())) {}
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(QFlags other) noexcept { i |= other.i; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(Enum other) noexcept { i |= Int(other); return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(QFlags other) noexcept { i ^= other.i; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(Enum other) noexcept { i ^= Int(other); return *this; }
-
- Q_DECL_CONSTEXPR inline operator Int() const noexcept { return i; }
-
- Q_DECL_CONSTEXPR inline QFlags operator|(QFlags other) const noexcept { return QFlags(QFlag(i | other.i)); }
- Q_DECL_CONSTEXPR inline QFlags operator|(Enum other) const noexcept { return QFlags(QFlag(i | Int(other))); }
- Q_DECL_CONSTEXPR inline QFlags operator^(QFlags other) const noexcept { return QFlags(QFlag(i ^ other.i)); }
- Q_DECL_CONSTEXPR inline QFlags operator^(Enum other) const noexcept { return QFlags(QFlag(i ^ Int(other))); }
- Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const noexcept { return QFlags(QFlag(i & mask)); }
- Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const noexcept { return QFlags(QFlag(i & mask)); }
- Q_DECL_CONSTEXPR inline QFlags operator&(Enum other) const noexcept { return QFlags(QFlag(i & Int(other))); }
- Q_DECL_CONSTEXPR inline QFlags operator~() const noexcept { return QFlags(QFlag(~i)); }
-
- Q_DECL_CONSTEXPR inline bool operator!() const noexcept { return !i; }
-
- Q_DECL_CONSTEXPR inline bool testFlag(Enum flag) const noexcept { return (i & Int(flag)) == Int(flag) && (Int(flag) != 0 || i == Int(flag) ); }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum flag, bool on = true) noexcept
+ constexpr static inline QFlags fromInt(Int i) noexcept { return QFlags(QFlag(i)); }
+ constexpr inline Int toInt() const noexcept { return i; }
+
+#ifndef QT_TYPESAFE_FLAGS
+ constexpr inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; }
+ constexpr inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; }
+#endif
+ constexpr inline QFlags &operator&=(QFlags mask) noexcept { i &= mask.i; return *this; }
+ constexpr inline QFlags &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
+ constexpr inline QFlags &operator|=(QFlags other) noexcept { i |= other.i; return *this; }
+ constexpr inline QFlags &operator|=(Enum other) noexcept { i |= Int(other); return *this; }
+ constexpr inline QFlags &operator^=(QFlags other) noexcept { i ^= other.i; return *this; }
+ constexpr inline QFlags &operator^=(Enum other) noexcept { i ^= Int(other); return *this; }
+
+#ifdef QT_TYPESAFE_FLAGS
+ constexpr inline explicit operator Int() const noexcept { return i; }
+ constexpr inline explicit operator bool() const noexcept { return i; }
+ // For some reason, moc goes through QFlag in order to read/write
+ // properties of type QFlags; so a conversion to QFlag is also
+ // needed here. (It otherwise goes through a QFlags->int->QFlag
+ // conversion sequence.)
+ constexpr inline explicit operator QFlag() const noexcept { return QFlag(i); }
+#else
+ constexpr inline Q_IMPLICIT operator Int() const noexcept { return i; }
+ constexpr inline bool operator!() const noexcept { return !i; }
+#endif
+
+ constexpr inline QFlags operator|(QFlags other) const noexcept { return QFlags(QFlag(i | other.i)); }
+ constexpr inline QFlags operator|(Enum other) const noexcept { return QFlags(QFlag(i | Int(other))); }
+ constexpr inline QFlags operator^(QFlags other) const noexcept { return QFlags(QFlag(i ^ other.i)); }
+ constexpr inline QFlags operator^(Enum other) const noexcept { return QFlags(QFlag(i ^ Int(other))); }
+#ifndef QT_TYPESAFE_FLAGS
+ constexpr inline QFlags operator&(int mask) const noexcept { return QFlags(QFlag(i & mask)); }
+ constexpr inline QFlags operator&(uint mask) const noexcept { return QFlags(QFlag(i & mask)); }
+#endif
+ constexpr inline QFlags operator&(QFlags other) const noexcept { return QFlags(QFlag(i & other.i)); }
+ constexpr inline QFlags operator&(Enum other) const noexcept { return QFlags(QFlag(i & Int(other))); }
+ constexpr inline QFlags operator~() const noexcept { return QFlags(QFlag(~i)); }
+
+ constexpr inline void operator+(QFlags other) const noexcept = delete;
+ constexpr inline void operator+(Enum other) const noexcept = delete;
+ constexpr inline void operator+(int other) const noexcept = delete;
+ constexpr inline void operator-(QFlags other) const noexcept = delete;
+ constexpr inline void operator-(Enum other) const noexcept = delete;
+ constexpr inline void operator-(int other) const noexcept = delete;
+
+ constexpr inline bool testFlag(Enum flag) const noexcept { return testFlags(flag); }
+ constexpr inline bool testFlags(QFlags flags) const noexcept { return flags.i ? ((i & flags.i) == flags.i) : i == Int(0); }
+ constexpr inline bool testAnyFlag(Enum flag) const noexcept { return testAnyFlags(flag); }
+ constexpr inline bool testAnyFlags(QFlags flags) const noexcept { return (i & flags.i) != Int(0); }
+ constexpr inline QFlags &setFlag(Enum flag, bool on = true) noexcept
{
- return on ? (*this |= flag) : (*this &= ~Int(flag));
+ return on ? (*this |= flag) : (*this &= ~QFlags(flag));
}
+ friend constexpr inline bool operator==(QFlags lhs, QFlags rhs) noexcept
+ { return lhs.i == rhs.i; }
+ friend constexpr inline bool operator!=(QFlags lhs, QFlags rhs) noexcept
+ { return lhs.i != rhs.i; }
+ friend constexpr inline bool operator==(QFlags lhs, Enum rhs) noexcept
+ { return lhs == QFlags(rhs); }
+ friend constexpr inline bool operator!=(QFlags lhs, Enum rhs) noexcept
+ { return lhs != QFlags(rhs); }
+ friend constexpr inline bool operator==(Enum lhs, QFlags rhs) noexcept
+ { return QFlags(lhs) == rhs; }
+ friend constexpr inline bool operator!=(Enum lhs, QFlags rhs) noexcept
+ { return QFlags(lhs) != rhs; }
+
+#ifdef QT_TYPESAFE_FLAGS
+ // Provide means of comparing flags against a literal 0; opt-in
+ // because otherwise they're ambiguous against operator==(int,int)
+ // after a QFlags->int conversion.
+ friend constexpr inline bool operator==(QFlags flags, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return flags.i == Int(0); }
+ friend constexpr inline bool operator!=(QFlags flags, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return flags.i != Int(0); }
+ friend constexpr inline bool operator==(QtPrivate::CompareAgainstLiteralZero, QFlags flags) noexcept
+ { return Int(0) == flags.i; }
+ friend constexpr inline bool operator!=(QtPrivate::CompareAgainstLiteralZero, QFlags flags) noexcept
+ { return Int(0) != flags.i; }
+#endif
+
private:
- Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
+ constexpr static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
typename std::initializer_list<Enum>::const_iterator end)
noexcept
{
@@ -170,27 +175,80 @@ private:
typedef QFlags<Enum> Flags;
#endif
-#define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \
-Q_DECL_CONSTEXPR inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
+#ifdef QT_TYPESAFE_FLAGS
+
+// These are opt-in, for backwards compatibility
+#define QT_DECLARE_TYPESAFE_OPERATORS_FOR_FLAGS_ENUM(Flags) \
+[[maybe_unused]] \
+constexpr inline Flags operator~(Flags::enum_type e) noexcept \
+{ return ~Flags(e); } \
+[[maybe_unused]] \
+constexpr inline void operator|(Flags::enum_type f1, int f2) noexcept = delete;
+#else
+#define QT_DECLARE_TYPESAFE_OPERATORS_FOR_FLAGS_ENUM(Flags) \
+[[maybe_unused]] \
+constexpr inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
{ return QIncompatibleFlag(int(f1) | f2); }
+#endif
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
-Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
+[[maybe_unused]] \
+constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return QFlags<Flags::enum_type>(f1) | f2; } \
-Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
-{ return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags)
-
-
-#else /* Q_NO_TYPESAFE_FLAGS */
-
-#ifndef Q_MOC_RUN
-#define Q_DECLARE_FLAGS(Flags, Enum)\
-typedef uint Flags;
+[[maybe_unused]] \
+constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
+{ return f2 | f1; } \
+[[maybe_unused]] \
+constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, Flags::enum_type f2) noexcept \
+{ return QFlags<Flags::enum_type>(f1) & f2; } \
+[[maybe_unused]] \
+constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
+{ return f2 & f1; } \
+[[maybe_unused]] \
+constexpr inline QFlags<Flags::enum_type> operator^(Flags::enum_type f1, Flags::enum_type f2) noexcept \
+{ return QFlags<Flags::enum_type>(f1) ^ f2; } \
+[[maybe_unused]] \
+constexpr inline QFlags<Flags::enum_type> operator^(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
+{ return f2 ^ f1; } \
+constexpr inline void operator+(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
+constexpr inline void operator+(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
+constexpr inline void operator+(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
+constexpr inline void operator-(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
+constexpr inline void operator-(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
+constexpr inline void operator-(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
+constexpr inline void operator+(int f1, Flags::enum_type f2) noexcept = delete; \
+constexpr inline void operator+(Flags::enum_type f1, int f2) noexcept = delete; \
+constexpr inline void operator-(int f1, Flags::enum_type f2) noexcept = delete; \
+constexpr inline void operator-(Flags::enum_type f1, int f2) noexcept = delete; \
+QT_DECLARE_TYPESAFE_OPERATORS_FOR_FLAGS_ENUM(Flags)
+
+// restore bit-wise enum-enum operators deprecated in C++20,
+// but used in a few places in the API
+#if __cplusplus > 201702L // assume compilers don't warn if in C++17 mode
+ // in C++20 mode, provide user-defined operators to override the deprecated operations:
+# define Q_DECLARE_MIXED_ENUM_OPERATOR(op, Ret, LHS, RHS) \
+ [[maybe_unused]] \
+ constexpr inline Ret operator op (LHS lhs, RHS rhs) noexcept \
+ { return static_cast<Ret>(qToUnderlying(lhs) op qToUnderlying(rhs)); } \
+ /* end */
+#else
+ // in C++17 mode, statically-assert that this compiler's result of the
+ // operation is the same that the C++20 version would produce:
+# define Q_DECLARE_MIXED_ENUM_OPERATOR(op, Ret, LHS, RHS) \
+ static_assert(std::is_same_v<decltype(std::declval<LHS>() op std::declval<RHS>()), Ret>);
#endif
-#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
+#define Q_DECLARE_MIXED_ENUM_OPERATORS(Ret, Flags, Enum) \
+ Q_DECLARE_MIXED_ENUM_OPERATOR(|, Ret, Flags, Enum) \
+ Q_DECLARE_MIXED_ENUM_OPERATOR(&, Ret, Flags, Enum) \
+ Q_DECLARE_MIXED_ENUM_OPERATOR(^, Ret, Flags, Enum) \
+ /* end */
+
+#define Q_DECLARE_MIXED_ENUM_OPERATORS_SYMMETRIC(Ret, Flags, Enum) \
+ Q_DECLARE_MIXED_ENUM_OPERATORS(Ret, Flags, Enum) \
+ Q_DECLARE_MIXED_ENUM_OPERATORS(Ret, Enum, Flags) \
+ /* end */
-#endif /* Q_NO_TYPESAFE_FLAGS */
QT_END_NAMESPACE
diff --git a/src/corelib/global/qflags.qdoc b/src/corelib/global/qflags.qdoc
new file mode 100644
index 0000000000..dd3b1e4c9b
--- /dev/null
+++ b/src/corelib/global/qflags.qdoc
@@ -0,0 +1,459 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \class QFlag
+ \inmodule QtCore
+ \brief The QFlag class is a helper data type for QFlags.
+
+ It is equivalent to a plain \c int, except with respect to
+ function overloading and type conversions. You should never need
+ to use this class in your applications.
+
+ \sa QFlags
+*/
+
+/*!
+ \fn QFlag::QFlag(int value)
+
+ Constructs a QFlag object that stores the \a value.
+*/
+
+/*!
+ \fn QFlag::QFlag(uint value)
+ \since 5.3
+
+ Constructs a QFlag object that stores the \a value.
+*/
+
+/*!
+ \fn QFlag::QFlag(short value)
+ \since 5.3
+
+ Constructs a QFlag object that stores the \a value.
+*/
+
+/*!
+ \fn QFlag::QFlag(ushort value)
+ \since 5.3
+
+ Constructs a QFlag object that stores the \a value.
+*/
+
+/*!
+ \fn QFlag::operator int() const
+
+ Returns the value stored by the QFlag object.
+*/
+
+/*!
+ \fn QFlag::operator uint() const
+ \since 5.3
+
+ Returns the value stored by the QFlag object.
+*/
+
+/*!
+ \class QFlags
+ \inmodule QtCore
+ \brief The QFlags class provides a type-safe way of storing
+ OR-combinations of enum values.
+
+
+ \ingroup tools
+
+ The QFlags<Enum> class is a template class, where Enum is an enum
+ type. QFlags is used throughout Qt for storing combinations of
+ enum values.
+
+ The traditional C++ approach for storing OR-combinations of enum
+ values is to use an \c int or \c uint variable. The inconvenience
+ with this approach is that there's no type checking at all; any
+ enum value can be OR'd with any other enum value and passed on to
+ a function that takes an \c int or \c uint.
+
+ Qt uses QFlags to provide type safety. For example, the
+ Qt::Alignment type is simply a typedef for
+ QFlags<Qt::AlignmentFlag>. QLabel::setAlignment() takes a
+ Qt::Alignment parameter, which means that any combination of
+ Qt::AlignmentFlag values, or \c{{ }}, is legal:
+
+ \snippet code/src_corelib_global_qglobal.cpp 0
+
+ If you try to pass a value from another enum or just a plain
+ integer other than 0, the compiler will report an error. If you
+ need to cast integer values to flags in a untyped fashion, you can
+ use the explicit QFlags constructor as cast operator.
+
+ If you want to use QFlags for your own enum types, use
+ the Q_DECLARE_FLAGS() and Q_DECLARE_OPERATORS_FOR_FLAGS().
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 1
+
+ You can then use the \c MyClass::Options type to store
+ combinations of \c MyClass::Option values.
+
+ \section1 Flags and the Meta-Object System
+
+ The Q_DECLARE_FLAGS() macro does not expose the flags to the meta-object
+ system, so they cannot be used by Qt Script or edited in \QD.
+ To make the flags available for these purposes, the Q_FLAG() macro must
+ be used:
+
+ \snippet code/src_corelib_global_qglobal.cpp meta-object flags
+
+ \section1 Naming Convention
+
+ A sensible naming convention for enum types and associated QFlags
+ types is to give a singular name to the enum type (e.g., \c
+ Option) and a plural name to the QFlags type (e.g., \c Options).
+ When a singular name is desired for the QFlags type (e.g., \c
+ Alignment), you can use \c Flag as the suffix for the enum type
+ (e.g., \c AlignmentFlag).
+
+ \sa QFlag
+*/
+
+/*!
+ \typedef QFlags::Int
+ \since 5.0
+
+ Typedef for the integer type used for storage as well as for
+ implicit conversion. Either \c int or \c{unsigned int}, depending
+ on whether the enum's underlying type is signed or unsigned.
+*/
+
+/*!
+ \typedef QFlags::enum_type
+
+ Typedef for the Enum template type.
+*/
+
+/*!
+ \fn template<typename Enum> QFlags<Enum>::QFlags(const QFlags &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn template <typename Enum> QFlags<Enum>::QFlags(Enum flags)
+
+ Constructs a QFlags object storing the \a flags.
+*/
+
+/*!
+ \fn template <typename Enum> QFlags<Enum>::QFlags()
+ \since 5.15
+
+ Constructs a QFlags object with no flags set.
+*/
+
+/*!
+ \fn template <typename Enum> QFlags<Enum>::QFlags(QFlag flag)
+
+ Constructs a QFlags object initialized with the integer \a flag.
+
+ The QFlag type is a helper type. By using it here instead of \c
+ int, we effectively ensure that arbitrary enum values cannot be
+ cast to a QFlags, whereas untyped enum values (i.e., \c int
+ values) can.
+*/
+
+/*!
+ \fn template <typename Enum> QFlags<Enum>::QFlags(std::initializer_list<Enum> flags)
+ \since 5.4
+
+ Constructs a QFlags object initialized with all \a flags
+ combined using the bitwise OR operator.
+
+ \sa operator|=(), operator|()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator=(const QFlags &other)
+
+ Assigns \a other to this object and returns a reference to this
+ object.
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(int mask)
+
+ Performs a bitwise AND operation with \a mask and stores the
+ result in this QFlags object. Returns a reference to this object.
+
+ \sa operator&(), operator|=(), operator^=()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(uint mask)
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(Enum mask)
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(QFlags mask)
+ \since 6.2
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(QFlags other)
+
+ Performs a bitwise OR operation with \a other and stores the
+ result in this QFlags object. Returns a reference to this object.
+
+ \sa operator|(), operator&=(), operator^=()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(Enum other)
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(QFlags other)
+
+ Performs a bitwise XOR operation with \a other and stores the
+ result in this QFlags object. Returns a reference to this object.
+
+ \sa operator^(), operator&=(), operator|=()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(Enum other)
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags<Enum>::operator Int() const
+
+ Returns the value stored in the QFlags object as an integer.
+
+ \sa Int
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator|(QFlags other) const
+
+ Returns a QFlags object containing the result of the bitwise OR
+ operation on this object and \a other.
+
+ \sa operator|=(), operator^(), operator&(), operator~()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator|(Enum other) const
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator^(QFlags other) const
+
+ Returns a QFlags object containing the result of the bitwise XOR
+ operation on this object and \a other.
+
+ \sa operator^=(), operator&(), operator|(), operator~()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator^(Enum other) const
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator&(int mask) const
+
+ Returns a QFlags object containing the result of the bitwise AND
+ operation on this object and \a mask.
+
+ \sa operator&=(), operator|(), operator^(), operator~()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator&(uint mask) const
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator&(Enum mask) const
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator&(QFlags mask) const
+ \since 6.2
+
+ \overload
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::operator~() const
+
+ Returns a QFlags object that contains the bitwise negation of
+ this object.
+
+ \sa operator&(), operator|(), operator^()
+*/
+
+/*!
+ \fn template <typename Enum> bool QFlags<Enum>::operator!() const
+
+ Returns \c true if no flag is set (i.e., if the value stored by the
+ QFlags object is 0); otherwise returns \c false.
+*/
+
+/*!
+ \fn template <typename Enum> bool QFlags<Enum>::testFlag(Enum flag) const
+ \since 4.2
+
+ Returns \c true if the flag \a flag is set, otherwise \c false.
+
+ \note if \a flag contains multiple bits set to 1 (for instance, if
+ it's an enumerator equal to the bitwise-OR of other enumerators)
+ then this function will return \c true if and only if all the bits
+ are set in this flags object. On the other hand, if \a flag contains
+ no bits set to 1 (that is, its value as a integer is 0), then this
+ function will return \c true if and only if this flags object also
+ has no bits set to 1.
+
+ \sa testAnyFlag()
+*/
+
+/*!
+ \fn template <typename Enum> bool QFlags<Enum>::testFlags(QFlags flags) const noexcept
+ \since 6.2
+
+ Returns \c true if this flags object matches the given \a flags.
+
+ If \a flags has any flags set, this flags object matches precisely
+ if all flags set in \a flags are also set in this flags object.
+ Otherwise, when \a flags has no flags set, this flags object only
+ matches if it also has no flags set.
+
+ \sa testAnyFlags()
+*/
+
+/*!
+ \fn template <typename Enum> bool QFlags<Enum>::testAnyFlag(Enum flag) const noexcept
+ \since 6.2
+
+ Returns \c true if \b any flag set in \a flag is also set in this
+ flags object, otherwise \c false. If \a flag has no flags set, the
+ return will always be \c false.
+
+ \sa testFlag()
+*/
+
+/*!
+ \fn template <typename Enum> bool QFlags<Enum>::testAnyFlags(QFlags flags) const noexcept
+ \since 6.2
+
+ Returns \c true if \b any flag set in \a flags is also set in this
+ flags object, otherwise \c false. If \a flags has no flags set, the
+ return will always be \c false.
+
+ \sa testFlags()
+*/
+
+/*!
+ \fn template <typename Enum> QFlags QFlags<Enum>::setFlag(Enum flag, bool on)
+ \since 5.7
+
+ Sets the flag \a flag if \a on is \c true or unsets it if
+ \a on is \c false. Returns a reference to this object.
+*/
+
+/*!
+ \fn template <typename Enum> QFlags<Enum> QFlags<Enum>::fromInt(Int i) noexcept
+ \since 6.2
+
+ Constructs a QFlags object representing the integer value \a i.
+*/
+
+/*!
+ \fn template <typename Enum> Int QFlags<Enum>::toInt() const noexcept
+ \since 6.2
+
+ Returns the value stored in the QFlags object as an integer. Note
+ that the returned integer may be signed or unsigned, depending on
+ whether the enum's underlying type is signed or unsigned.
+
+ \sa Int
+*/
+
+/*!
+ \fn template <typename Enum> size_t qHash(QFlags<Enum> flags, size_t seed = 0) noexcept
+ \since 6.2
+ \relates QFlags
+
+ Calculates the hash for the flags \a flags, using \a seed
+ to seed the calculation.
+*/
+
+/*!
+ \fn template <typename Enum> bool operator==(QFlags<Enum> lhs, QFlags<Enum> rhs)
+ \fn template <typename Enum> bool operator==(QFlags<Enum> lhs, Enum rhs)
+ \fn template <typename Enum> bool operator==(Enum lhs, QFlags<Enum> rhs)
+ \since 6.2
+ \relates QFlags
+
+ Compares \a lhs and \a rhs for equality; the two arguments are
+ considered equal if they represent exactly the same value
+ (bitmask).
+*/
+
+/*!
+ \fn template <typename Enum> bool operator!=(QFlags<Enum> lhs, QFlags<Enum> rhs)
+ \fn template <typename Enum> bool operator!=(QFlags<Enum> lhs, Enum rhs)
+ \fn template <typename Enum> bool operator!=(Enum lhs, QFlags<Enum> rhs)
+ \since 6.2
+ \relates QFlags
+
+ Compares \a lhs and \a rhs for inequality; the two arguments are
+ considered different if they don't represent exactly the same value
+ (bitmask).
+*/
+
+/*!
+ \macro Q_DECLARE_FLAGS(Flags, Enum)
+ \relates QFlags
+
+ The Q_DECLARE_FLAGS() macro expands to
+
+ \snippet code/src_corelib_global_qglobal.cpp 2
+
+ \a Enum is the name of an existing enum type, whereas \a Flags is
+ the name of the QFlags<\e{Enum}> typedef.
+
+ See the QFlags documentation for details.
+
+ \sa Q_DECLARE_OPERATORS_FOR_FLAGS()
+*/
+
+/*!
+ \macro Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
+ \relates QFlags
+
+ The Q_DECLARE_OPERATORS_FOR_FLAGS() macro declares global \c
+ operator|() functions for \a Flags, which is of type QFlags<T>.
+
+ See the QFlags documentation for details.
+
+ \sa Q_DECLARE_FLAGS()
+*/
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 1f06b10313..f6f782e364 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -1,49 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 by Southwest Research Institute (R)
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 by Southwest Research Institute (R)
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfloat16.h"
#include "private/qsimd_p.h"
#include <cmath> // for fpclassify()'s return values
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qtextstream.h>
+
+QT_DECL_METATYPE_EXTERN(qfloat16, Q_CORE_EXPORT)
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(qfloat16)
+
/*!
\class qfloat16
\keyword 16-bit Floating Point Support
@@ -52,6 +23,15 @@ QT_BEGIN_NAMESPACE
\inheaderfile QFloat16
\brief Provides 16-bit floating point support.
+ \compares partial
+ \compareswith partial float double {long double} qint8 quint8 qint16 quint16 \
+ qint32 quint32 long {unsigned long} qint64 quint64
+ \endcompareswith
+ \compareswith partial qint128 quint128
+ Comparison with 128-bit integral types is only supported if Qt provides
+ these types.
+ \endcompareswith
+
The \c qfloat16 class provides support for half-precision (16-bit) floating
point data. It is fully compliant with IEEE 754 as a storage type. This
implies that any arithmetic operation on a \c qfloat16 instance results in
@@ -65,47 +45,42 @@ QT_BEGIN_NAMESPACE
stating that it supports all arithmetic operators incident to floating point
types.
+ \note On x86 and x86-64 that to get hardware accelerated conversions you must
+ compile with F16C or AVX2 enabled, or use qFloatToFloat16() and qFloatFromFloat16()
+ which will detect F16C at runtime.
+
\since 5.9
*/
/*!
- \macro QT_NO_FLOAT16_OPERATORS
- \relates qfloat16
- \since 5.12.4
+ \fn qfloat16::qfloat16(Qt::Initialization)
+ \since 6.1
- Defining this macro disables the arithmetic operators for qfloat16.
-
- This is only necessary on Visual Studio 2017 (and earlier) when including
- \c {<QFloat16>} and \c{<bitset>} in the same translation unit, which would
- otherwise cause a compilation error due to a toolchain bug (see
- [QTBUG-72073]).
+ Constructs a qfloat16 without initializing the value.
*/
/*!
\fn bool qIsInf(qfloat16 f)
\relates qfloat16
+ \overload qIsInf(float)
Returns true if the \c qfloat16 \a {f} is equivalent to infinity.
-
- \sa qIsInf
*/
/*!
\fn bool qIsNaN(qfloat16 f)
\relates qfloat16
+ \overload qIsNaN(float)
Returns true if the \c qfloat16 \a {f} is not a number (NaN).
-
- \sa qIsNaN
*/
/*!
\fn bool qIsFinite(qfloat16 f)
\relates qfloat16
+ \overload qIsFinite(float)
Returns true if the \c qfloat16 \a {f} is a finite number.
-
- \sa qIsFinite
*/
/*!
@@ -114,8 +89,6 @@ QT_BEGIN_NAMESPACE
\fn bool qfloat16::isInf() const noexcept
Tests whether this \c qfloat16 value is an infinity.
-
- \sa qIsInf()
*/
/*!
@@ -124,8 +97,6 @@ QT_BEGIN_NAMESPACE
\fn bool qfloat16::isNaN() const noexcept
Tests whether this \c qfloat16 value is "not a number".
-
- \sa qIsNaN()
*/
/*!
@@ -143,8 +114,6 @@ QT_BEGIN_NAMESPACE
\fn bool qfloat16::isFinite() const noexcept
Tests whether this \c qfloat16 value is finite.
-
- \sa qIsFinite()
*/
/*!
@@ -156,11 +125,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn int qFpClassify(qfloat16 val)
+ \relates qfloat16
+ \since 5.14
+ \overload qFpClassify(float)
+
+ Returns the floating-point class of \a val.
+*/
+
+/*!
\internal
\since 5.14
Implements qFpClassify() for qfloat16.
-
- \sa qFpClassify()
*/
int qfloat16::fpClassify() const noexcept
{
@@ -170,22 +146,21 @@ int qfloat16::fpClassify() const noexcept
/*! \fn int qRound(qfloat16 value)
\relates qfloat16
+ \overload qRound(float)
Rounds \a value to the nearest integer.
-
- \sa qRound
*/
/*! \fn qint64 qRound64(qfloat16 value)
\relates qfloat16
+ \overload qRound64(float)
Rounds \a value to the nearest 64-bit integer.
-
- \sa qRound64
*/
/*! \fn bool qFuzzyCompare(qfloat16 p1, qfloat16 p2)
\relates qfloat16
+ \overload qFuzzyCompare(float, float)
Compares the floating point value \a p1 and \a p2 and
returns \c true if they are considered equal, otherwise \c false.
@@ -194,25 +169,128 @@ int qfloat16::fpClassify() const noexcept
exactness is stronger the smaller the numbers are.
*/
-#if QT_COMPILER_SUPPORTS(F16C)
+#if QT_COMPILER_SUPPORTS_HERE(F16C)
static inline bool hasFastF16()
{
- // All processors with F16C also support AVX, but YMM registers
- // might not be supported by the OS, or they might be disabled.
- return qCpuHasFeature(F16C) && qCpuHasFeature(AVX);
+ // qsimd.cpp:detectProcessorFeatures() turns off this feature if AVX
+ // state-saving is not enabled by the OS
+ return qCpuHasFeature(F16C);
}
-extern "C" {
-#ifdef QFLOAT16_INCLUDE_FAST
-# define f16cextern static
-#else
-# define f16cextern extern
+#if QT_COMPILER_SUPPORTS_HERE(AVX512VL) && QT_COMPILER_SUPPORTS_HERE(AVX512BW)
+static bool hasFastF16Avx256()
+{
+ // 256-bit AVX512 don't have a performance penalty (see qstring.cpp for more info)
+ return qCpuHasFeature(ArchSkylakeAvx512);
+}
+
+static QT_FUNCTION_TARGET(ARCH_SKYLAKE_AVX512)
+void qFloatToFloat16_tail_avx256(quint16 *out, const float *in, qsizetype len) noexcept
+{
+ __mmask16 mask = _bzhi_u32(-1, len);
+ __m256 f32 = _mm256_maskz_loadu_ps(mask, in );
+ __m128i f16 = _mm256_maskz_cvtps_ph(mask, f32, _MM_FROUND_TO_NEAREST_INT);
+ _mm_mask_storeu_epi16(out, mask, f16);
+};
+
+static QT_FUNCTION_TARGET(ARCH_SKYLAKE_AVX512)
+void qFloatFromFloat16_tail_avx256(float *out, const quint16 *in, qsizetype len) noexcept
+{
+ __mmask16 mask = _bzhi_u32(-1, len);
+ __m128i f16 = _mm_maskz_loadu_epi16(mask, in);
+ __m256 f32 = _mm256_cvtph_ps(f16);
+ _mm256_mask_storeu_ps(out, mask, f32);
+};
#endif
-f16cextern void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) noexcept;
-f16cextern void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) noexcept;
+QT_FUNCTION_TARGET(F16C)
+static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) noexcept
+{
+ constexpr qsizetype Step = sizeof(__m256i) / sizeof(float);
+ constexpr qsizetype HalfStep = sizeof(__m128i) / sizeof(float);
+ qsizetype i = 0;
+
+ if (len >= Step) {
+ auto convertOneChunk = [=](qsizetype offset) QT_FUNCTION_TARGET(F16C) {
+ __m256 f32 = _mm256_loadu_ps(in + offset);
+ __m128i f16 = _mm256_cvtps_ph(f32, _MM_FROUND_TO_NEAREST_INT);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(out + offset), f16);
+ };
+
+ // main loop: convert Step (8) floats per iteration
+ for ( ; i + Step < len; i += Step)
+ convertOneChunk(i);
+
+ // epilogue: convert the last chunk, possibly overlapping with the last
+ // iteration of the loop
+ return convertOneChunk(len - Step);
+ }
+
+#if QT_COMPILER_SUPPORTS_HERE(AVX512VL) && QT_COMPILER_SUPPORTS_HERE(AVX512BW)
+ if (hasFastF16Avx256())
+ return qFloatToFloat16_tail_avx256(out, in, len);
+#endif
+
+ if (len >= HalfStep) {
+ auto convertOneChunk = [=](qsizetype offset) QT_FUNCTION_TARGET(F16C) {
+ __m128 f32 = _mm_loadu_ps(in + offset);
+ __m128i f16 = _mm_cvtps_ph(f32, _MM_FROUND_TO_NEAREST_INT);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(out + offset), f16);
+ };
+
+ // two conversions, possibly overlapping
+ convertOneChunk(0);
+ return convertOneChunk(len - HalfStep);
+ }
+
+ // Inlining "qfloat16::qfloat16(float f)":
+ for ( ; i < len; ++i)
+ out[i] = _mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(in[i]), 0), 0);
+}
+
+QT_FUNCTION_TARGET(F16C)
+static void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) noexcept
+{
+ constexpr qsizetype Step = sizeof(__m256i) / sizeof(float);
+ constexpr qsizetype HalfStep = sizeof(__m128i) / sizeof(float);
+ qsizetype i = 0;
+
+ if (len >= Step) {
+ auto convertOneChunk = [=](qsizetype offset) QT_FUNCTION_TARGET(F16C) {
+ __m128i f16 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + offset));
+ __m256 f32 = _mm256_cvtph_ps(f16);
+ _mm256_storeu_ps(out + offset, f32);
+ };
+
+ // main loop: convert Step (8) floats per iteration
+ for ( ; i + Step < len; i += Step)
+ convertOneChunk(i);
+
+ // epilogue: convert the last chunk, possibly overlapping with the last
+ // iteration of the loop
+ return convertOneChunk(len - Step);
+ }
+
+#if QT_COMPILER_SUPPORTS_HERE(AVX512VL) && QT_COMPILER_SUPPORTS_HERE(AVX512BW)
+ if (hasFastF16Avx256())
+ return qFloatFromFloat16_tail_avx256(out, in, len);
+#endif
-#undef f16cextern
+ if (len >= HalfStep) {
+ auto convertOneChunk = [=](qsizetype offset) QT_FUNCTION_TARGET(F16C) {
+ __m128i f16 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(in + offset));
+ __m128 f32 = _mm_cvtph_ps(f16);
+ _mm_storeu_ps(out + offset, f32);
+ };
+
+ // two conversions, possibly overlapping
+ convertOneChunk(0);
+ return convertOneChunk(len - HalfStep);
+ }
+
+ // Inlining "qfloat16::operator float()":
+ for ( ; i < len; ++i)
+ out[i] = _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(in[i])));
}
#elif defined(__ARM_FP16_FORMAT_IEEE) && defined(__ARM_NEON__) && (__ARM_FP & 2)
@@ -262,6 +340,9 @@ static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) noexcept
Converts \a len floats from \a in to qfloat16 and stores them in \a out.
Both \a in and \a out must have \a len allocated entries.
+
+ This function is faster than converting values one by one, and will do runtime
+ F16C detection on x86 and x86-64 hardware.
*/
Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len) noexcept
{
@@ -278,6 +359,9 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len
Converts \a len qfloat16 from \a in to floats and stores them in \a out.
Both \a in and \a out must have \a len allocated entries.
+
+ This function is faster than converting values one by one, and will do runtime
+ F16C detection on x86 and x86-64 hardware.
*/
Q_CORE_EXPORT void qFloatFromFloat16(float *out, const qfloat16 *in, qsizetype len) noexcept
{
@@ -288,9 +372,67 @@ Q_CORE_EXPORT void qFloatFromFloat16(float *out, const qfloat16 *in, qsizetype l
out[i] = float(in[i]);
}
+/*!
+ \fn size_t qfloat16::qHash(qfloat16 key, size_t seed)
+ \since 6.5.3
+
+ Returns the hash value for the \a key, using \a seed to seed the
+ calculation.
+
+ \note In Qt versions before 6.5, this operation was provided by the
+ qHash(float) overload. In Qt versions 6.5.0 to 6.5.2, this functionality
+ was broken in various ways. In Qt versions 6.5.3 and 6.6 onwards, this
+ overload restores the Qt 6.4 behavior.
+*/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn qfloat16::operator<<(QDataStream &ds, qfloat16 f)
+ \relates QDataStream
+ \since 5.9
+
+ Writes a floating point number, \a f, to the stream \a ds using
+ the standard IEEE 754 format. Returns a reference to the stream.
+
+ \note In Qt versions prior to 6.3, this was a member function on
+ QDataStream.
+*/
+QDataStream &operator<<(QDataStream &ds, qfloat16 f)
+{
+ return ds << f.b16;
+}
+
+/*!
+ \fn qfloat16::operator>>(QDataStream &ds, qfloat16 &f)
+ \relates QDataStream
+ \since 5.9
+
+ Reads a floating point number from the stream \a ds into \a f,
+ using the standard IEEE 754 format. Returns a reference to the
+ stream.
+
+ \note In Qt versions prior to 6.3, this was a member function on
+ QDataStream.
+*/
+QDataStream &operator>>(QDataStream &ds, qfloat16 &f)
+{
+ return ds >> f.b16;
+}
+#endif
+
+QTextStream &operator>>(QTextStream &ts, qfloat16 &f16)
+{
+ float f;
+ ts >> f;
+ f16 = qfloat16(f);
+ return ts;
+}
+
+QTextStream &operator<<(QTextStream &ts, qfloat16 f)
+{
+ return ts << float(f);
+}
+
QT_END_NAMESPACE
#include "qfloat16tables.cpp"
-#ifdef QFLOAT16_INCLUDE_FAST
-# include "qfloat16_f16c.c"
-#endif
diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h
index 9ac811a3e6..30dd9a60af 100644
--- a/src/corelib/global/qfloat16.h
+++ b/src/corelib/global/qfloat16.h
@@ -1,57 +1,30 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 by Southwest Research Institute (R)
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 by Southwest Research Institute (R)
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFLOAT16_H
#define QFLOAT16_H
+#include <QtCore/qcompare.h>
#include <QtCore/qglobal.h>
-#include <QtCore/qmetatype.h>
+#include <QtCore/qhashfunctions.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtypes.h>
+
+#include <limits>
#include <string.h>
+#include <type_traits>
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__AVX2__) && !defined(__F16C__)
-// All processors that support AVX2 do support F16C too. That doesn't mean
-// we're allowed to use the intrinsics directly, so we'll do it only for
-// the Intel and Microsoft's compilers.
-# if defined(Q_CC_INTEL) || defined(Q_CC_MSVC)
+// All processors that support AVX2 do support F16C too, so we could enable the
+// feature unconditionally if __AVX2__ is defined. However, all currently
+// supported compilers except Microsoft's are able to define __F16C__ on their
+// own when the user enables the feature, so we'll trust them.
+# if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
# define __F16C__ 1
-# endif
+# endif
#endif
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
@@ -65,6 +38,11 @@ QT_BEGIN_NAMESPACE
#pragma qt_no_master_include
#endif
+#ifndef QT_NO_DATASTREAM
+class QDataStream;
+#endif
+class QTextStream;
+
class qfloat16
{
struct Wrap
@@ -74,20 +52,64 @@ class qfloat16
quint16 b16;
constexpr inline explicit Wrap(int value) : b16(quint16(value)) {}
};
+
+#ifdef QT_SUPPORTS_INT128
+ template <typename T>
+ using IsIntegral = std::disjunction<std::is_integral<T>,
+ std::is_same<std::remove_const_t<T>, qint128>,
+ std::is_same<std::remove_const_t<T>, quint128>>;
+#else
+ template <typename T>
+ using IsIntegral = std::is_integral<T>;
+#endif
+ template <typename T>
+ using if_type_is_integral = std::enable_if_t<IsIntegral<std::remove_reference_t<T>>::value,
+ bool>;
+
public:
+ using NativeType = QtPrivate::NativeFloat16Type;
+
+ static constexpr bool IsNative = QFLOAT16_IS_NATIVE;
+ using NearestFloat = std::conditional_t<IsNative, NativeType, float>;
+
constexpr inline qfloat16() noexcept : b16(0) {}
+ explicit qfloat16(Qt::Initialization) noexcept { }
+
+#if QFLOAT16_IS_NATIVE
+ constexpr inline qfloat16(NativeType f) : nf(f) {}
+ constexpr operator NativeType() const noexcept { return nf; }
+#else
inline qfloat16(float f) noexcept;
inline operator float() const noexcept;
+#endif
+ template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> && !std::is_same_v<T, NearestFloat>>>
+ constexpr explicit qfloat16(T value) noexcept : qfloat16(NearestFloat(value)) {}
// Support for qIs{Inf,NaN,Finite}:
- bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; }
- bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; }
- bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; }
+ bool isInf() const noexcept { return (b16 & 0x7fff) == 0x7c00; }
+ bool isNaN() const noexcept { return (b16 & 0x7fff) > 0x7c00; }
+ bool isFinite() const noexcept { return (b16 & 0x7fff) < 0x7c00; }
Q_CORE_EXPORT int fpClassify() const noexcept;
// Can't specialize std::copysign() for qfloat16
qfloat16 copySign(qfloat16 sign) const noexcept
{ return qfloat16(Wrap((sign.b16 & 0x8000) | (b16 & 0x7fff))); }
// Support for std::numeric_limits<qfloat16>
+
+#ifdef __STDCPP_FLOAT16_T__
+private:
+ using Bounds = std::numeric_limits<NativeType>;
+public:
+ static constexpr qfloat16 _limit_epsilon() noexcept { return Bounds::epsilon(); }
+ static constexpr qfloat16 _limit_min() noexcept { return Bounds::min(); }
+ static constexpr qfloat16 _limit_denorm_min() noexcept { return Bounds::denorm_min(); }
+ static constexpr qfloat16 _limit_max() noexcept { return Bounds::max(); }
+ static constexpr qfloat16 _limit_lowest() noexcept { return Bounds::lowest(); }
+ static constexpr qfloat16 _limit_infinity() noexcept { return Bounds::infinity(); }
+ static constexpr qfloat16 _limit_quiet_NaN() noexcept { return Bounds::quiet_NaN(); }
+#if QT_CONFIG(signaling_nan)
+ static constexpr qfloat16 _limit_signaling_NaN() noexcept { return Bounds::signaling_NaN(); }
+#endif
+#else
static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); }
static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); }
static constexpr qfloat16 _limit_denorm_min() noexcept { return qfloat16(Wrap(1)); }
@@ -96,24 +118,160 @@ public:
static constexpr qfloat16 _limit_infinity() noexcept { return qfloat16(Wrap(0x7c00)); }
static constexpr qfloat16 _limit_quiet_NaN() noexcept { return qfloat16(Wrap(0x7e00)); }
#if QT_CONFIG(signaling_nan)
- static constexpr qfloat16 _limit_signaling_NaN() noexcept { return qfloat16(Wrap(0x7f00)); }
+ static constexpr qfloat16 _limit_signaling_NaN() noexcept { return qfloat16(Wrap(0x7d00)); }
+#endif
#endif
inline constexpr bool isNormal() const noexcept
- { return (b16 & 0x7fff) == 0 || ((b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00); }
+ { return (b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00; }
private:
- quint16 b16;
- constexpr inline explicit qfloat16(Wrap nibble) noexcept : b16(nibble.b16) {}
+ // ABI note: Qt 6's qfloat16 began with just a quint16 member so it ended
+ // up passed in general purpose registers in any function call taking
+ // qfloat16 by value (it has trivial copy constructors). This means the
+ // integer member in the anonymous union below must remain until a
+ // binary-incompatible version of Qt. If you remove it, on platforms using
+ // the System V ABI for C, the native type is passed in FP registers.
+ union {
+ quint16 b16;
+#if QFLOAT16_IS_NATIVE
+ NativeType nf;
+#endif
+ };
+ constexpr inline explicit qfloat16(Wrap nibble) noexcept :
+#if QFLOAT16_IS_NATIVE && defined(__cpp_lib_bit_cast)
+ nf(std::bit_cast<NativeType>(nibble.b16))
+#else
+ b16(nibble.b16)
+#endif
+ {}
Q_CORE_EXPORT static const quint32 mantissatable[];
Q_CORE_EXPORT static const quint32 exponenttable[];
Q_CORE_EXPORT static const quint32 offsettable[];
- Q_CORE_EXPORT static const quint32 basetable[];
- Q_CORE_EXPORT static const quint32 shifttable[];
+ Q_CORE_EXPORT static const quint16 basetable[];
+ Q_CORE_EXPORT static const quint16 shifttable[];
+ Q_CORE_EXPORT static const quint32 roundtable[];
friend bool qIsNull(qfloat16 f) noexcept;
-#if !defined(QT_NO_FLOAT16_OPERATORS)
- friend qfloat16 operator-(qfloat16 a) noexcept;
+
+ friend inline qfloat16 operator-(qfloat16 a) noexcept
+ {
+ qfloat16 f;
+ f.b16 = a.b16 ^ quint16(0x8000);
+ return f;
+ }
+
+ friend inline qfloat16 operator+(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) + static_cast<NearestFloat>(b)); }
+ friend inline qfloat16 operator-(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) - static_cast<NearestFloat>(b)); }
+ friend inline qfloat16 operator*(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) * static_cast<NearestFloat>(b)); }
+ friend inline qfloat16 operator/(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) / static_cast<NearestFloat>(b)); }
+
+ friend size_t qHash(qfloat16 key, size_t seed = 0) noexcept
+ { return qHash(float(key), seed); } // 6.4 algorithm, so keep using it; ### Qt 7: fix QTBUG-116077
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wfloat-conversion")
+
+#define QF16_MAKE_ARITH_OP_FP(FP, OP) \
+ friend inline FP operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
+ friend inline FP operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
+#define QF16_MAKE_ARITH_OP_EQ_FP(FP, OP_EQ, OP) \
+ friend inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) noexcept \
+ { lhs = qfloat16(NearestFloat(static_cast<FP>(lhs) OP rhs)); return lhs; }
+#define QF16_MAKE_ARITH_OP(FP) \
+ QF16_MAKE_ARITH_OP_FP(FP, +) \
+ QF16_MAKE_ARITH_OP_FP(FP, -) \
+ QF16_MAKE_ARITH_OP_FP(FP, *) \
+ QF16_MAKE_ARITH_OP_FP(FP, /) \
+ QF16_MAKE_ARITH_OP_EQ_FP(FP, +=, +) \
+ QF16_MAKE_ARITH_OP_EQ_FP(FP, -=, -) \
+ QF16_MAKE_ARITH_OP_EQ_FP(FP, *=, *) \
+ QF16_MAKE_ARITH_OP_EQ_FP(FP, /=, /)
+
+ QF16_MAKE_ARITH_OP(long double)
+ QF16_MAKE_ARITH_OP(double)
+ QF16_MAKE_ARITH_OP(float)
+#if QFLOAT16_IS_NATIVE
+ QF16_MAKE_ARITH_OP(NativeType)
+#endif
+#undef QF16_MAKE_ARITH_OP
+#undef QF16_MAKE_ARITH_OP_FP
+
+#define QF16_MAKE_ARITH_OP_INT(OP) \
+ friend inline double operator OP(qfloat16 lhs, int rhs) noexcept { return static_cast<double>(lhs) OP rhs; } \
+ friend inline double operator OP(int lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<double>(rhs); }
+
+ QF16_MAKE_ARITH_OP_INT(+)
+ QF16_MAKE_ARITH_OP_INT(-)
+ QF16_MAKE_ARITH_OP_INT(*)
+ QF16_MAKE_ARITH_OP_INT(/)
+#undef QF16_MAKE_ARITH_OP_INT
+
+QT_WARNING_DISABLE_FLOAT_COMPARE
+
+#if QFLOAT16_IS_NATIVE
+# define QF16_CONSTEXPR constexpr
+# define QF16_PARTIALLY_ORDERED Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE
+#else
+# define QF16_CONSTEXPR
+# define QF16_PARTIALLY_ORDERED Q_DECLARE_PARTIALLY_ORDERED
+#endif
+
+ friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
+ { return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
+ friend QF16_CONSTEXPR
+ Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
+ { return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
+ QF16_PARTIALLY_ORDERED(qfloat16)
+
+#define QF16_MAKE_ORDER_OP_FP(FP) \
+ friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, FP rhs) noexcept \
+ { return static_cast<FP>(lhs) == rhs; } \
+ friend QF16_CONSTEXPR \
+ Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, FP rhs) noexcept \
+ { return Qt::compareThreeWay(static_cast<FP>(lhs), rhs); } \
+ QF16_PARTIALLY_ORDERED(qfloat16, FP)
+
+ QF16_MAKE_ORDER_OP_FP(long double)
+ QF16_MAKE_ORDER_OP_FP(double)
+ QF16_MAKE_ORDER_OP_FP(float)
+#if QFLOAT16_IS_NATIVE
+ QF16_MAKE_ORDER_OP_FP(qfloat16::NativeType)
+#endif
+#undef QF16_MAKE_ORDER_OP_FP
+
+ template <typename T, if_type_is_integral<T> = true>
+ friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, T rhs) noexcept
+ { return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
+ template <typename T, if_type_is_integral<T> = true>
+ friend QF16_CONSTEXPR Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, T rhs) noexcept
+ { return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
+
+ QF16_PARTIALLY_ORDERED(qfloat16, qint8)
+ QF16_PARTIALLY_ORDERED(qfloat16, quint8)
+ QF16_PARTIALLY_ORDERED(qfloat16, qint16)
+ QF16_PARTIALLY_ORDERED(qfloat16, quint16)
+ QF16_PARTIALLY_ORDERED(qfloat16, qint32)
+ QF16_PARTIALLY_ORDERED(qfloat16, quint32)
+ QF16_PARTIALLY_ORDERED(qfloat16, long)
+ QF16_PARTIALLY_ORDERED(qfloat16, unsigned long)
+ QF16_PARTIALLY_ORDERED(qfloat16, qint64)
+ QF16_PARTIALLY_ORDERED(qfloat16, quint64)
+#ifdef QT_SUPPORTS_INT128
+ QF16_PARTIALLY_ORDERED(qfloat16, qint128)
+ QF16_PARTIALLY_ORDERED(qfloat16, quint128)
+#endif
+
+#undef QF16_PARTIALLY_ORDERED
+#undef QF16_CONSTEXPR
+
+QT_WARNING_POP
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, qfloat16 f);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, qfloat16 &f);
#endif
+ friend Q_CORE_EXPORT QTextStream &operator<<(QTextStream &ts, qfloat16 f);
+ friend Q_CORE_EXPORT QTextStream &operator>>(QTextStream &ts, qfloat16 &f);
};
Q_DECLARE_TYPEINFO(qfloat16, Q_PRIMITIVE_TYPE);
@@ -122,23 +280,60 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *, const float *, qsizetype length)
Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length) noexcept;
// Complement qnumeric.h:
-Q_REQUIRED_RESULT inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); }
-Q_REQUIRED_RESULT inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); }
-Q_REQUIRED_RESULT inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); }
-Q_REQUIRED_RESULT inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); }
-// Q_REQUIRED_RESULT quint32 qFloatDistance(qfloat16 a, qfloat16 b);
+[[nodiscard]] inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); }
+[[nodiscard]] inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); }
+[[nodiscard]] inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); }
+[[nodiscard]] inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); }
+// [[nodiscard]] quint32 qFloatDistance(qfloat16 a, qfloat16 b);
+
+[[nodiscard]] inline qfloat16 qSqrt(qfloat16 f)
+{
+#if defined(__cpp_lib_extended_float) && defined(__STDCPP_FLOAT16_T__) && 0
+ // https://wg21.link/p1467 - disabled until tested
+ using namespace std;
+ return sqrt(f);
+#elif QFLOAT16_IS_NATIVE && defined(__HAVE_FLOAT16) && __HAVE_FLOAT16
+ // This C library (glibc) has sqrtf16().
+ return sqrtf16(f);
+#else
+ bool mathUpdatesErrno = true;
+# if defined(__NO_MATH_ERRNO__) || defined(_M_FP_FAST)
+ mathUpdatesErrno = false;
+# elif defined(math_errhandling)
+ mathUpdatesErrno = (math_errhandling & MATH_ERRNO);
+# endif
+
+ // We don't need to set errno to EDOM if (f >= 0 && f != -0 && !isnan(f))
+ // (or if we don't care about errno in the first place). We can merge the
+ // NaN check with by negating and inverting: !(0 > f), and leaving zero to
+ // sqrtf().
+ if (!mathUpdatesErrno || !(0 > f)) {
+# if defined(__AVX512FP16__)
+ __m128h v = _mm_set_sh(f);
+ v = _mm_sqrt_sh(v, v);
+ return _mm_cvtsh_h(v);
+# endif
+ }
+
+ // WG14's N2601 does not provide a way to tell which types an
+ // implementation supports, so we assume it doesn't and fall back to FP32
+ float f32 = float(f);
+ f32 = sqrtf(f32);
+ return qfloat16::NearestFloat(f32);
+#endif
+}
// The remainder of these utility functions complement qglobal.h
-Q_REQUIRED_RESULT inline int qRound(qfloat16 d) noexcept
+[[nodiscard]] inline int qRound(qfloat16 d) noexcept
{ return qRound(static_cast<float>(d)); }
-Q_REQUIRED_RESULT inline qint64 qRound64(qfloat16 d) noexcept
+[[nodiscard]] inline qint64 qRound64(qfloat16 d) noexcept
{ return qRound64(static_cast<float>(d)); }
-Q_REQUIRED_RESULT inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
+[[nodiscard]] inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
{
- float f1 = static_cast<float>(p1);
- float f2 = static_cast<float>(p2);
+ qfloat16::NearestFloat f1 = static_cast<qfloat16::NearestFloat>(p1);
+ qfloat16::NearestFloat f2 = static_cast<qfloat16::NearestFloat>(p2);
// The significand precision for IEEE754 half precision is
// 11 bits (10 explicitly stored), or approximately 3 decimal
// digits. In selecting the fuzzy comparison factor of 102.5f
@@ -148,15 +343,23 @@ Q_REQUIRED_RESULT inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
return (qAbs(f1 - f2) * 102.5f <= qMin(qAbs(f1), qAbs(f2)));
}
-Q_REQUIRED_RESULT inline bool qIsNull(qfloat16 f) noexcept
+/*!
+ \internal
+*/
+[[nodiscard]] inline bool qFuzzyIsNull(qfloat16 f) noexcept
+{
+ return qAbs(f) < 0.00976f; // 1/102.5 to 3 significant digits; see qFuzzyCompare()
+}
+
+[[nodiscard]] inline bool qIsNull(qfloat16 f) noexcept
{
return (f.b16 & static_cast<quint16>(0x7fff)) == 0;
}
inline int qIntCast(qfloat16 f) noexcept
-{ return int(static_cast<float>(f)); }
+{ return int(static_cast<qfloat16::NearestFloat>(f)); }
-#ifndef Q_QDOC
+#if !defined(Q_QDOC) && !QFLOAT16_IS_NATIVE
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wc99-extensions")
QT_WARNING_DISABLE_GCC("-Wold-style-cast")
@@ -172,8 +375,28 @@ inline qfloat16::qfloat16(float f) noexcept
#else
quint32 u;
memcpy(&u, &f, sizeof(quint32));
- b16 = quint16(basetable[(u >> 23) & 0x1ff]
- + ((u & 0x007fffff) >> shifttable[(u >> 23) & 0x1ff]));
+ const quint32 signAndExp = u >> 23;
+ const quint16 base = basetable[signAndExp];
+ const quint16 shift = shifttable[signAndExp];
+ const quint32 round = roundtable[signAndExp];
+ quint32 mantissa = (u & 0x007fffff);
+ if ((signAndExp & 0xff) == 0xff) {
+ if (mantissa) // keep nan from truncating to inf
+ mantissa = qMax(1U << shift, mantissa);
+ } else {
+ // Round half to even. First round up by adding one in the most
+ // significant bit we'll be discarding:
+ mantissa += round;
+ // If the last bit we'll be keeping is now set, but all later bits are
+ // clear, we were at half and shouldn't have rounded up; decrement will
+ // clear this last kept bit. Any later set bit hides the decrement.
+ if (mantissa & (1 << shift))
+ --mantissa;
+ }
+
+ // We use add as the mantissa may overflow causing
+ // the exp part to shift exactly one value.
+ b16 = quint16(base + (mantissa >> shift));
#endif
}
QT_WARNING_POP
@@ -196,103 +419,86 @@ inline qfloat16::operator float() const noexcept
return f;
#endif
}
-#endif
+#endif // Q_QDOC and non-native
-#if !defined(QT_NO_FLOAT16_OPERATORS)
-inline qfloat16 operator-(qfloat16 a) noexcept
+/*
+ qHypot compatibility; see ../kernel/qmath.h
+*/
+namespace QtPrivate {
+template <> struct QHypotType<qfloat16, qfloat16>
{
- qfloat16 f;
- f.b16 = a.b16 ^ quint16(0x8000);
- return f;
+ using type = qfloat16;
+};
+template <typename R> struct QHypotType<R, qfloat16>
+{
+ using type = std::conditional_t<std::is_floating_point_v<R>, R, double>;
+};
+template <typename R> struct QHypotType<qfloat16, R> : QHypotType<R, qfloat16>
+{
+};
}
-inline qfloat16 operator+(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) + static_cast<float>(b)); }
-inline qfloat16 operator-(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) - static_cast<float>(b)); }
-inline qfloat16 operator*(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) * static_cast<float>(b)); }
-inline qfloat16 operator/(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) / static_cast<float>(b)); }
-
-#define QF16_MAKE_ARITH_OP_FP(FP, OP) \
- inline FP operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
- inline FP operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
-#define QF16_MAKE_ARITH_OP_EQ_FP(FP, OP_EQ, OP) \
- inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) noexcept \
- { lhs = qfloat16(float(static_cast<FP>(lhs) OP rhs)); return lhs; }
-#define QF16_MAKE_ARITH_OP(FP) \
- QF16_MAKE_ARITH_OP_FP(FP, +) \
- QF16_MAKE_ARITH_OP_FP(FP, -) \
- QF16_MAKE_ARITH_OP_FP(FP, *) \
- QF16_MAKE_ARITH_OP_FP(FP, /) \
- QF16_MAKE_ARITH_OP_EQ_FP(FP, +=, +) \
- QF16_MAKE_ARITH_OP_EQ_FP(FP, -=, -) \
- QF16_MAKE_ARITH_OP_EQ_FP(FP, *=, *) \
- QF16_MAKE_ARITH_OP_EQ_FP(FP, /=, /)
-QF16_MAKE_ARITH_OP(long double)
-QF16_MAKE_ARITH_OP(double)
-QF16_MAKE_ARITH_OP(float)
-#undef QF16_MAKE_ARITH_OP
-#undef QF16_MAKE_ARITH_OP_FP
-
-#define QF16_MAKE_ARITH_OP_INT(OP) \
- inline double operator OP(qfloat16 lhs, int rhs) noexcept { return static_cast<double>(lhs) OP rhs; } \
- inline double operator OP(int lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<double>(rhs); }
-QF16_MAKE_ARITH_OP_INT(+)
-QF16_MAKE_ARITH_OP_INT(-)
-QF16_MAKE_ARITH_OP_INT(*)
-QF16_MAKE_ARITH_OP_INT(/)
-#undef QF16_MAKE_ARITH_OP_INT
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_FLOAT_COMPARE
+// Avoid passing qfloat16 to std::hypot(), while ensuring return types
+// consistent with the above:
+inline auto qHypot(qfloat16 x, qfloat16 y)
+{
+#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) || QFLOAT16_IS_NATIVE
+ return QtPrivate::QHypotHelper<qfloat16>(x).add(y).result();
+#else
+ return qfloat16(qHypot(float(x), float(y)));
+#endif
+}
-inline bool operator>(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) > static_cast<float>(b); }
-inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) < static_cast<float>(b); }
-inline bool operator>=(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) >= static_cast<float>(b); }
-inline bool operator<=(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) <= static_cast<float>(b); }
-inline bool operator==(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) == static_cast<float>(b); }
-inline bool operator!=(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) != static_cast<float>(b); }
-
-#define QF16_MAKE_BOOL_OP_FP(FP, OP) \
- inline bool operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
- inline bool operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
-#define QF16_MAKE_BOOL_OP(FP) \
- QF16_MAKE_BOOL_OP_FP(FP, <) \
- QF16_MAKE_BOOL_OP_FP(FP, >) \
- QF16_MAKE_BOOL_OP_FP(FP, >=) \
- QF16_MAKE_BOOL_OP_FP(FP, <=) \
- QF16_MAKE_BOOL_OP_FP(FP, ==) \
- QF16_MAKE_BOOL_OP_FP(FP, !=)
-QF16_MAKE_BOOL_OP(long double)
-QF16_MAKE_BOOL_OP(double)
-QF16_MAKE_BOOL_OP(float)
-#undef QF16_MAKE_BOOL_OP
-#undef QF16_MAKE_BOOL_OP_FP
-
-#define QF16_MAKE_BOOL_OP_INT(OP) \
- inline bool operator OP(qfloat16 a, int b) noexcept { return static_cast<float>(a) OP static_cast<float>(b); } \
- inline bool operator OP(int a, qfloat16 b) noexcept { return static_cast<float>(a) OP static_cast<float>(b); }
-QF16_MAKE_BOOL_OP_INT(>)
-QF16_MAKE_BOOL_OP_INT(<)
-QF16_MAKE_BOOL_OP_INT(>=)
-QF16_MAKE_BOOL_OP_INT(<=)
-QF16_MAKE_BOOL_OP_INT(==)
-QF16_MAKE_BOOL_OP_INT(!=)
-#undef QF16_MAKE_BOOL_OP_INT
+// in ../kernel/qmath.h
+template<typename F, typename ...Fs> auto qHypot(F first, Fs... rest);
-QT_WARNING_POP
-#endif // QT_NO_FLOAT16_OPERATORS
+template <typename T> typename QtPrivate::QHypotType<T, qfloat16>::type
+qHypot(T x, qfloat16 y)
+{
+ if constexpr (std::is_floating_point_v<T>)
+ return qHypot(x, float(y));
+ else
+ return qHypot(qfloat16(x), y);
+}
+template <typename T> auto qHypot(qfloat16 x, T y)
+{
+ return qHypot(y, x);
+}
-/*!
- \internal
-*/
-Q_REQUIRED_RESULT inline bool qFuzzyIsNull(qfloat16 f) noexcept
+#if defined(__cpp_lib_hypot) && __cpp_lib_hypot >= 201603L // Expected to be true
+// If any are not qfloat16, convert each qfloat16 to float:
+/* (The following splits the some-but-not-all-qfloat16 cases up, using
+ (X|Y|Z)&~(X&Y&Z) = X ? ~(Y&Z) : Y|Z = X&~(Y&Z) | ~X&Y | ~X&~Y&Z,
+ into non-overlapping cases, to avoid ambiguity.) */
+template <typename Ty, typename Tz,
+ typename std::enable_if<
+ // Ty, Tz aren't both qfloat16:
+ !(std::is_same_v<qfloat16, Ty> && std::is_same_v<qfloat16, Tz>), int>::type = 0>
+auto qHypot(qfloat16 x, Ty y, Tz z) { return qHypot(qfloat16::NearestFloat(x), y, z); }
+template <typename Tx, typename Tz,
+ typename std::enable_if<
+ // Tx isn't qfloat16:
+ !std::is_same_v<qfloat16, Tx>, int>::type = 0>
+auto qHypot(Tx x, qfloat16 y, Tz z) { return qHypot(x, qfloat16::NearestFloat(y), z); }
+template <typename Tx, typename Ty,
+ typename std::enable_if<
+ // Neither Tx nor Ty is qfloat16:
+ !std::is_same_v<qfloat16, Tx> && !std::is_same_v<qfloat16, Ty>, int>::type = 0>
+auto qHypot(Tx x, Ty y, qfloat16 z) { return qHypot(x, y, qfloat16::NearestFloat(z)); }
+
+// If all are qfloat16, stay with qfloat16 (albeit via float, if no native support):
+inline auto qHypot(qfloat16 x, qfloat16 y, qfloat16 z)
{
- return qAbs(static_cast<float>(f)) <= 0.001f;
+#if (defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)) || QFLOAT16_IS_NATIVE
+ return QtPrivate::QHypotHelper<qfloat16>(x).add(y).add(z).result();
+#else
+ return qfloat16(qHypot(float(x), float(y), float(z)));
+#endif
}
+#endif // 3-arg std::hypot() is available
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(qfloat16)
-
namespace std {
template<>
class numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> : public numeric_limits<float>
diff --git a/src/corelib/global/qfloat16_f16c.c b/src/corelib/global/qfloat16_f16c.c
deleted file mode 100644
index ba1e16f481..0000000000
--- a/src/corelib/global/qfloat16_f16c.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "private/qsimd_p.h"
-
-// The x86 F16C instructions operate on AVX registers, so AVX support is
-// required. We don't need to check for __F16C__ because we this file wouldn't
-// have been compiled if the support was missing in the first place, and not
-// all compilers define it. Technically, we didn't need to check for __AVX__
-// either.
-#if !QT_COMPILER_SUPPORTS_HERE(AVX)
-# error "AVX support required"
-#endif
-
-#ifdef __cplusplus
-QT_BEGIN_NAMESPACE
-extern "C" {
-#endif
-
-QT_FUNCTION_TARGET(F16C)
-void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOEXCEPT
-{
- qsizetype i = 0;
- int epilog_i;
- for (; i < len - 7; i += 8)
- _mm_storeu_si128((__m128i *)(out + i), _mm256_cvtps_ph(_mm256_loadu_ps(in + i), 0));
- if (i < len - 3) {
- _mm_storel_epi64((__m128i *)(out + i), _mm_cvtps_ph(_mm_loadu_ps(in + i), 0));
- i += 4;
- }
- // Inlining "qfloat16::qfloat16(float f)":
- for (epilog_i = 0; i < len && epilog_i < 3; ++i, ++epilog_i)
- out[i] = _mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(in[i]), 0), 0);
-}
-
-QT_FUNCTION_TARGET(F16C)
-void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOEXCEPT
-{
- qsizetype i = 0;
- int epilog_i;
- for (; i < len - 7; i += 8)
- _mm256_storeu_ps(out + i, _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(in + i))));
- if (i < len - 3) {
- _mm_storeu_ps(out + i, _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(in + i))));
- i += 4;
- }
- // Inlining "qfloat16::operator float()":
- for (epilog_i = 0; i < len && epilog_i < 3; ++i, ++epilog_i)
- out[i] = _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(in[i])));
-}
-
-#ifdef __cplusplus
-} // extern "C"
-QT_END_NAMESPACE
-#endif
diff --git a/src/corelib/global/qfloat16tables.cpp b/src/corelib/global/qfloat16tables.cpp
index b87986d6b8..4aa620c4e7 100644
--- a/src/corelib/global/qfloat16tables.cpp
+++ b/src/corelib/global/qfloat16tables.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 by Southwest Research Institute (R)
-** Copyright (C) 2019 Intel Corporation.
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 by Southwest Research Institute (R)
+// Copyright (C) 2019 Intel Corporation.
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-/* This file was generated by gen_qfloat16_tables.cpp */
+/* This file was generated by util/qfloat16-tables/gen_qfloat16_tables.cpp */
#include <QtCore/qfloat16.h>
@@ -2231,7 +2196,7 @@ const quint32 qfloat16::offsettable[64] = {
1024U,
};
-const quint32 qfloat16::basetable[512] = {
+const quint16 qfloat16::basetable[512] = {
0x0U,
0x0U,
0x0U,
@@ -2746,7 +2711,7 @@ const quint32 qfloat16::basetable[512] = {
0xFC00U,
};
-const quint32 qfloat16::shifttable[512] = {
+const quint16 qfloat16::shifttable[512] = {
0x18U,
0x18U,
0x18U,
@@ -3261,6 +3226,521 @@ const quint32 qfloat16::shifttable[512] = {
0xDU,
};
-#endif // !__F16C__ && !__ARM_FP16_FORMAT_IEEE
+const quint32 qfloat16::roundtable[512] = {
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x1000000U,
+0x400001U,
+0x200000U,
+0x100000U,
+0x80000U,
+0x40000U,
+0x20000U,
+0x10000U,
+0x8000U,
+0x4000U,
+0x2000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x1000000U,
+0x400001U,
+0x200000U,
+0x100000U,
+0x80000U,
+0x40000U,
+0x20000U,
+0x10000U,
+0x8000U,
+0x4000U,
+0x2000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x1000U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+};
+
+#endif // !__ARM_FP16_FORMAT_IEEE
QT_END_NAMESPACE
diff --git a/src/corelib/global/qforeach.h b/src/corelib/global/qforeach.h
new file mode 100644
index 0000000000..ab0e20b989
--- /dev/null
+++ b/src/corelib/global/qforeach.h
@@ -0,0 +1,84 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFOREACH_H
+#define QFOREACH_H
+
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtdeprecationmarkers.h>
+#include <QtCore/qttypetraits.h>
+
+QT_BEGIN_NAMESPACE
+
+#if 0
+#pragma qt_class(QForeach)
+#pragma qt_sync_stop_processing
+#endif
+
+#ifndef QT_NO_FOREACH
+
+namespace QtPrivate {
+
+template <typename T>
+class QForeachContainer {
+ Q_DISABLE_COPY_MOVE(QForeachContainer)
+public:
+ QForeachContainer(const T &t) : c(t), i(std::as_const(c).begin()), e(std::as_const(c).end()) {}
+ QForeachContainer(T &&t) : c(std::move(t)), i(std::as_const(c).begin()), e(std::as_const(c).end()) {}
+
+ T c;
+ typename T::const_iterator i, e;
+};
+
+// Containers that have a detach function are considered shared, and are OK in a foreach loop
+template <typename T, typename = decltype(std::declval<T>().detach())>
+inline void warnIfContainerIsNotShared(int) {}
+
+#if QT_DEPRECATED_SINCE(6, 0)
+// Other containers will copy themselves if used in foreach, this use is deprecated
+template <typename T>
+QT_DEPRECATED_VERSION_X_6_0("Do not use foreach/Q_FOREACH with containers which are not implicitly shared. "
+ "Prefer using a range-based for loop with these containers: `for (const auto &it : container)`, "
+ "keeping in mind that range-based for doesn't copy the container as Q_FOREACH does")
+inline void warnIfContainerIsNotShared(...) {}
+#endif
+
+template<typename T>
+QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t)
+{
+ warnIfContainerIsNotShared<typename std::decay<T>::type>(0);
+ return QForeachContainer<typename std::decay<T>::type>(std::forward<T>(t));
+}
+
+}
+
+// Use C++17 if statement with initializer. User's code ends up in a else so
+// scoping of different ifs is not broken
+#define Q_FOREACH_IMPL(variable, name, container) \
+ for (auto name = QtPrivate::qMakeForeachContainer(container); name.i != name.e; ++name.i) \
+ if (variable = *name.i; false) {} else
+
+#define Q_FOREACH_JOIN(A, B) Q_FOREACH_JOIN_IMPL(A, B)
+#define Q_FOREACH_JOIN_IMPL(A, B) A ## B
+
+#define Q_FOREACH(variable, container) \
+ Q_FOREACH_IMPL(variable, Q_FOREACH_JOIN(_container_, __LINE__), container)
+#endif // QT_NO_FOREACH
+
+#define Q_FOREVER for(;;)
+#ifndef QT_NO_KEYWORDS
+# ifndef QT_NO_FOREACH
+# ifndef foreach
+# define foreach Q_FOREACH
+# endif
+# endif // QT_NO_FOREACH
+# ifndef forever
+# define forever Q_FOREVER
+# endif
+#endif
+
+QT_END_NAMESPACE
+
+#endif /* QFOREACH_H */
diff --git a/src/corelib/global/qforeach.qdoc b/src/corelib/global/qforeach.qdoc
new file mode 100644
index 0000000000..e6abf0e29c
--- /dev/null
+++ b/src/corelib/global/qforeach.qdoc
@@ -0,0 +1,72 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro forever
+ \relates <QForeach>
+
+ This macro is provided for convenience for writing infinite
+ loops.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 31
+
+ It is equivalent to \c{for (;;)}.
+
+ If you're worried about namespace pollution, you can disable this
+ macro by adding the following line to your \c .pro file:
+
+ \snippet code/src_corelib_global_qglobal.cpp 32
+
+ If using other build systems, you can add \c QT_NO_KEYWORDS to the
+ list of pre-defined macros.
+
+ \sa Q_FOREVER
+*/
+
+/*!
+ \macro Q_FOREVER
+ \relates <QForeach>
+
+ Same as \l{forever}.
+
+ This macro is available even when \c no_keywords is specified
+ using the \c .pro file's \c CONFIG variable.
+
+ \sa foreach()
+*/
+
+/*!
+ \macro foreach(variable, container)
+ \relates <QForeach>
+
+ This macro is used to implement Qt's \c foreach loop. The \a
+ variable parameter is a variable name or variable definition; the
+ \a container parameter is a Qt container whose value type
+ corresponds to the type of the variable. See \l{The foreach
+ Keyword} for details.
+
+ If you're worried about namespace pollution, you can disable this
+ macro by adding the following line to your \c .pro file:
+
+ \snippet code/src_corelib_global_qglobal.cpp 33
+
+ \note Since Qt 5.7, the use of this macro is discouraged.
+ Use C++11 range-based \c for, possibly with \c {std::as_const()},
+ as needed.
+*/
+
+/*!
+ \macro Q_FOREACH(variable, container)
+ \relates <QForeach>
+
+ Same as foreach(\a variable, \a container).
+
+ This macro is available even when \c no_keywords is specified
+ using the \c .pro file's \c CONFIG variable.
+
+ \note Since Qt 5.7, the use of this macro is discouraged.
+ Use C++11 range-based \c for, possibly with \c {std::as_const()},
+ as needed.
+*/
diff --git a/src/corelib/global/qfunctionpointer.h b/src/corelib/global/qfunctionpointer.h
new file mode 100644
index 0000000000..3884954f89
--- /dev/null
+++ b/src/corelib/global/qfunctionpointer.h
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFUNCTIONPOINTER_H
+#define QFUNCTIONPOINTER_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#if 0
+#pragma qt_class(QFunctionPointer)
+#endif
+
+#if defined(__cplusplus)
+
+QT_BEGIN_NAMESPACE
+
+typedef void (*QFunctionPointer)();
+
+QT_END_NAMESPACE
+
+#endif // __cplusplus
+
+#endif // QFUNCTIONPOINTER_H
diff --git a/src/corelib/global/qfunctionpointer.qdoc b/src/corelib/global/qfunctionpointer.qdoc
new file mode 100644
index 0000000000..13f82bc011
--- /dev/null
+++ b/src/corelib/global/qfunctionpointer.qdoc
@@ -0,0 +1,9 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*! \typedef QFunctionPointer
+ \relates <QFunctionPointer>
+
+ This is a typedef for \c{void (*)()}, a pointer to a function that takes
+ no arguments and returns void.
+*/
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 2ed15595b7..99e4e49c9c 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1,73 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qstring.h"
+#include "qbytearrayview.h"
#include "qlist.h"
#include "qdir.h"
#include "qdatetime.h"
-#include "qoperatingsystemversion.h"
-#include "qoperatingsystemversion_p.h"
-#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
-# include "qoperatingsystemversion_win_p.h"
-# include "private/qwinregistry_p.h"
-#endif // Q_OS_WIN || Q_OS_CYGWIN
#include <private/qlocale_tools_p.h>
-
-#include <qmutex.h>
-#include <QtCore/private/qlocking_p.h>
-
-#include <stdlib.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <string.h>
-
-#ifndef QT_NO_EXCEPTIONS
-# include <string>
-# include <exception>
-#endif
-
-#include <errno.h>
-#if defined(Q_CC_MSVC)
-# include <crtdbg.h>
-#endif
+#include "qnativeinterface.h"
+#include "qnativeinterface_p.h"
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -77,28 +20,6 @@
# include <envLib.h>
#endif
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
-#include <private/qjni_p.h>
-#endif
-
-#if defined(Q_OS_SOLARIS)
-# include <sys/systeminfo.h>
-#endif
-
-#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
-# include <IOKit/IOKitLib.h>
-# include <private/qcore_mac_p.h>
-#endif
-
-#ifdef Q_OS_UNIX
-#include <sys/utsname.h>
-#include <private/qcore_unix_p.h>
-#endif
-
-#ifdef Q_OS_BSD4
-#include <sys/sysctl.h>
-#endif
-
#if defined(Q_OS_INTEGRITY)
extern "C" {
// Function mmap resides in libshm_client.a. To be able to link with it one needs
@@ -112,3278 +33,82 @@ extern "C" {
}
#endif
-#include "archdetect.cpp"
-
-#ifdef qFatal
-// the qFatal in this file are just redirections from elsewhere, so
-// don't capture any context again
-# undef qFatal
-#endif
-
QT_BEGIN_NAMESPACE
-#if !QT_DEPRECATED_SINCE(5, 0)
-// Make sure they're defined to be exported
-Q_CORE_EXPORT void *qMemCopy(void *dest, const void *src, size_t n);
-Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n);
-#endif
-
-// Statically check assumptions about the environment we're running
-// in. The idea here is to error or warn if otherwise implicit Qt
-// assumptions are not fulfilled on new hardware or compilers
-// (if this list becomes too long, consider factoring into a separate file)
-static_assert(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
-static_assert(sizeof(int) == 4, "Qt assumes that int is 32 bits");
-static_assert(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined incorrectly");
-static_assert(sizeof(float) == 4, "Qt assumes that float is 32 bits");
-static_assert(sizeof(char16_t) == 2, "Qt assumes that char16_t is 16 bits");
-static_assert(sizeof(char32_t) == 4, "Qt assumes that char32_t is 32 bits");
-static_assert(std::numeric_limits<int>::radix == 2,
- "Qt assumes binary integers");
-static_assert((std::numeric_limits<int>::max() + std::numeric_limits<int>::lowest()) == -1,
- "Qt assumes two's complement integers");
-
-// While we'd like to check for __STDC_IEC_559__, as per ISO/IEC 9899:2011
-// Annex F (C11, normative for C++11), there are a few corner cases regarding
-// denormals where GHS compiler is relying hardware behavior that is not IEC
-// 559 compliant. So split the check in several subchecks.
-
-// On GHC the compiler reports std::numeric_limits<float>::is_iec559 as false.
-// This is all right according to our needs.
-#if !defined(Q_CC_GHS)
-static_assert(std::numeric_limits<float>::is_iec559,
- "Qt assumes IEEE 754 floating point");
-#endif
-
-// Technically, presence of NaN and infinities are implied from the above check,
-// but double checking our environment doesn't hurt...
-static_assert(std::numeric_limits<float>::has_infinity &&
- std::numeric_limits<float>::has_quiet_NaN &&
- std::numeric_limits<float>::has_signaling_NaN,
- "Qt assumes IEEE 754 floating point");
-
-// is_iec559 checks for ISO/IEC/IEEE 60559:2011 (aka IEEE 754-2008) compliance,
-// but that allows for a non-binary radix. We need to recheck that.
-// Note how __STDC_IEC_559__ would instead check for IEC 60559:1989, aka
-// ANSI/IEEE 754−1985, which specifically implies binary floating point numbers.
-static_assert(std::numeric_limits<float>::radix == 2,
- "Qt assumes binary IEEE 754 floating point");
-
-// not required by the definition of size_t, but we depend on this
-static_assert(sizeof(size_t) == sizeof(void *), "size_t and a pointer don't have the same size");
-static_assert(sizeof(size_t) == sizeof(qsizetype)); // implied by the definition
-static_assert((std::is_same<qsizetype, qptrdiff>::value));
-
-/*!
- \class QFlag
- \inmodule QtCore
- \brief The QFlag class is a helper data type for QFlags.
-
- It is equivalent to a plain \c int, except with respect to
- function overloading and type conversions. You should never need
- to use this class in your applications.
-
- \sa QFlags
-*/
-
-/*!
- \fn QFlag::QFlag(int value)
-
- Constructs a QFlag object that stores the \a value.
-*/
-
-/*!
- \fn QFlag::QFlag(uint value)
- \since 5.3
-
- Constructs a QFlag object that stores the \a value.
-*/
-
-/*!
- \fn QFlag::QFlag(short value)
- \since 5.3
-
- Constructs a QFlag object that stores the \a value.
-*/
-
-/*!
- \fn QFlag::QFlag(ushort value)
- \since 5.3
-
- Constructs a QFlag object that stores the \a value.
-*/
-
-/*!
- \fn QFlag::operator int() const
-
- Returns the value stored by the QFlag object.
-*/
-
-/*!
- \fn QFlag::operator uint() const
- \since 5.3
-
- Returns the value stored by the QFlag object.
-*/
-
-/*!
- \class QFlags
- \inmodule QtCore
- \brief The QFlags class provides a type-safe way of storing
- OR-combinations of enum values.
-
-
- \ingroup tools
-
- The QFlags<Enum> class is a template class, where Enum is an enum
- type. QFlags is used throughout Qt for storing combinations of
- enum values.
-
- The traditional C++ approach for storing OR-combinations of enum
- values is to use an \c int or \c uint variable. The inconvenience
- with this approach is that there's no type checking at all; any
- enum value can be OR'd with any other enum value and passed on to
- a function that takes an \c int or \c uint.
-
- Qt uses QFlags to provide type safety. For example, the
- Qt::Alignment type is simply a typedef for
- QFlags<Qt::AlignmentFlag>. QLabel::setAlignment() takes a
- Qt::Alignment parameter, which means that any combination of
- Qt::AlignmentFlag values, or \c{{ }}, is legal:
-
- \snippet code/src_corelib_global_qglobal.cpp 0
-
- If you try to pass a value from another enum or just a plain
- integer other than 0, the compiler will report an error. If you
- need to cast integer values to flags in a untyped fashion, you can
- use the explicit QFlags constructor as cast operator.
-
- If you want to use QFlags for your own enum types, use
- the Q_DECLARE_FLAGS() and Q_DECLARE_OPERATORS_FOR_FLAGS().
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 1
-
- You can then use the \c MyClass::Options type to store
- combinations of \c MyClass::Option values.
-
- \section1 Flags and the Meta-Object System
-
- The Q_DECLARE_FLAGS() macro does not expose the flags to the meta-object
- system, so they cannot be used by Qt Script or edited in Qt Designer.
- To make the flags available for these purposes, the Q_FLAG() macro must
- be used:
-
- \snippet code/src_corelib_global_qglobal.cpp meta-object flags
-
- \section1 Naming Convention
-
- A sensible naming convention for enum types and associated QFlags
- types is to give a singular name to the enum type (e.g., \c
- Option) and a plural name to the QFlags type (e.g., \c Options).
- When a singular name is desired for the QFlags type (e.g., \c
- Alignment), you can use \c Flag as the suffix for the enum type
- (e.g., \c AlignmentFlag).
-
- \sa QFlag
-*/
-
-/*!
- \typedef QFlags::Int
- \since 5.0
-
- Typedef for the integer type used for storage as well as for
- implicit conversion. Either \c int or \c{unsigned int}, depending
- on whether the enum's underlying type is signed or unsigned.
-*/
-
-/*!
- \typedef QFlags::enum_type
-
- Typedef for the Enum template type.
-*/
-
-/*!
- \fn template<typename Enum> QFlags<Enum>::QFlags(const QFlags &other)
-
- Constructs a copy of \a other.
-*/
-
-/*!
- \fn template <typename Enum> QFlags<Enum>::QFlags(Enum flags)
-
- Constructs a QFlags object storing the \a flags.
-*/
-
-/*!
- \fn template <typename Enum> QFlags<Enum>::QFlags()
- \since 5.15
-
- Constructs a QFlags object with no flags set.
-*/
-
-/*!
- \fn template <typename Enum> QFlags<Enum>::QFlags(Zero)
- \deprecated
-
- Constructs a QFlags object with no flags set. The parameter must be a
- literal 0 value.
-
- Deprecated, use default constructor instead.
-*/
-
-/*!
- \fn template <typename Enum> QFlags<Enum>::QFlags(QFlag flag)
-
- Constructs a QFlags object initialized with the integer \a flag.
-
- The QFlag type is a helper type. By using it here instead of \c
- int, we effectively ensure that arbitrary enum values cannot be
- cast to a QFlags, whereas untyped enum values (i.e., \c int
- values) can.
-*/
-
-/*!
- \fn template <typename Enum> QFlags<Enum>::QFlags(std::initializer_list<Enum> flags)
- \since 5.4
-
- Constructs a QFlags object initialized with all \a flags
- combined using the bitwise OR operator.
-
- \sa operator|=(), operator|()
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator=(const QFlags &other)
-
- Assigns \a other to this object and returns a reference to this
- object.
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(int mask)
-
- Performs a bitwise AND operation with \a mask and stores the
- result in this QFlags object. Returns a reference to this object.
-
- \sa operator&(), operator|=(), operator^=()
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(uint mask)
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(Enum mask)
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(QFlags other)
-
- Performs a bitwise OR operation with \a other and stores the
- result in this QFlags object. Returns a reference to this object.
-
- \sa operator|(), operator&=(), operator^=()
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(Enum other)
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(QFlags other)
-
- Performs a bitwise XOR operation with \a other and stores the
- result in this QFlags object. Returns a reference to this object.
-
- \sa operator^(), operator&=(), operator|=()
-*/
-
-/*!
- \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(Enum other)
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags<Enum>::operator Int() const
-
- Returns the value stored in the QFlags object as an integer.
-
- \sa Int
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator|(QFlags other) const
-
- Returns a QFlags object containing the result of the bitwise OR
- operation on this object and \a other.
-
- \sa operator|=(), operator^(), operator&(), operator~()
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator|(Enum other) const
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator^(QFlags other) const
-
- Returns a QFlags object containing the result of the bitwise XOR
- operation on this object and \a other.
-
- \sa operator^=(), operator&(), operator|(), operator~()
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator^(Enum other) const
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator&(int mask) const
-
- Returns a QFlags object containing the result of the bitwise AND
- operation on this object and \a mask.
-
- \sa operator&=(), operator|(), operator^(), operator~()
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator&(uint mask) const
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator&(Enum mask) const
-
- \overload
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::operator~() const
-
- Returns a QFlags object that contains the bitwise negation of
- this object.
-
- \sa operator&(), operator|(), operator^()
-*/
-
-/*!
- \fn template <typename Enum> bool QFlags<Enum>::operator!() const
-
- Returns \c true if no flag is set (i.e., if the value stored by the
- QFlags object is 0); otherwise returns \c false.
-*/
-
-/*!
- \fn template <typename Enum> bool QFlags<Enum>::testFlag(Enum flag) const
- \since 4.2
-
- Returns \c true if the flag \a flag is set, otherwise \c false.
-*/
-
-/*!
- \fn template <typename Enum> QFlags QFlags<Enum>::setFlag(Enum flag, bool on)
- \since 5.7
-
- Sets the flag \a flag if \a on is \c true or unsets it if
- \a on is \c false. Returns a reference to this object.
-*/
-
-/*!
- \macro Q_DISABLE_COPY(Class)
- \relates QObject
-
- Disables the use of copy constructors and assignment operators
- for the given \a Class.
-
- Instances of subclasses of QObject should not be thought of as
- values that can be copied or assigned, but as unique identities.
- This means that when you create your own subclass of QObject
- (director or indirect), you should \e not give it a copy constructor
- or an assignment operator. However, it may not enough to simply
- omit them from your class, because, if you mistakenly write some code
- that requires a copy constructor or an assignment operator (it's easy
- to do), your compiler will thoughtfully create it for you. You must
- do more.
-
- The curious user will have seen that the Qt classes derived
- from QObject typically include this macro in a private section:
-
- \snippet code/src_corelib_global_qglobal.cpp 43
-
- It declares a copy constructor and an assignment operator in the
- private section, so that if you use them by mistake, the compiler
- will report an error.
-
- \snippet code/src_corelib_global_qglobal.cpp 44
-
- But even this might not catch absolutely every case. You might be
- tempted to do something like this:
-
- \snippet code/src_corelib_global_qglobal.cpp 45
-
- First of all, don't do that. Most compilers will generate code that
- uses the copy constructor, so the privacy violation error will be
- reported, but your C++ compiler is not required to generate code for
- this statement in a specific way. It could generate code using
- \e{neither} the copy constructor \e{nor} the assignment operator we
- made private. In that case, no error would be reported, but your
- application would probably crash when you called a member function
- of \c{w}.
-
- \sa Q_DISABLE_COPY_MOVE, Q_DISABLE_MOVE
-*/
-
-/*!
- \macro Q_DISABLE_MOVE(Class)
- \relates QObject
-
- Disables the use of move constructors and move assignment operators
- for the given \a Class.
-
- \sa Q_DISABLE_COPY, Q_DISABLE_COPY_MOVE
- \since 5.13
-*/
-
-/*!
- \macro Q_DISABLE_COPY_MOVE(Class)
- \relates QObject
-
- A convenience macro that disables the use of copy constructors, assignment
- operators, move constructors and move assignment operators for the given
- \a Class, combining Q_DISABLE_COPY and Q_DISABLE_MOVE.
-
- \sa Q_DISABLE_COPY, Q_DISABLE_MOVE
- \since 5.13
-*/
-
-/*!
- \macro Q_DECLARE_FLAGS(Flags, Enum)
- \relates QFlags
-
- The Q_DECLARE_FLAGS() macro expands to
-
- \snippet code/src_corelib_global_qglobal.cpp 2
-
- \a Enum is the name of an existing enum type, whereas \a Flags is
- the name of the QFlags<\e{Enum}> typedef.
-
- See the QFlags documentation for details.
-
- \sa Q_DECLARE_OPERATORS_FOR_FLAGS()
-*/
-
-/*!
- \macro Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
- \relates QFlags
-
- The Q_DECLARE_OPERATORS_FOR_FLAGS() macro declares global \c
- operator|() functions for \a Flags, which is of type QFlags<T>.
-
- See the QFlags documentation for details.
-
- \sa Q_DECLARE_FLAGS()
-*/
+using namespace Qt::StringLiterals;
/*!
\headerfile <QtGlobal>
+ \inmodule QtCore
\title Global Qt Declarations
\ingroup funclists
- \brief The <QtGlobal> header file includes the fundamental global
- declarations. It is included by most other Qt header files.
-
- The global declarations include \l{types}, \l{functions} and
- \l{macros}.
-
- The type definitions are partly convenience definitions for basic
- types (some of which guarantee certain bit-sizes on all platforms
- supported by Qt), partly types related to Qt message handling. The
- functions are related to generating messages, Qt version handling
- and comparing and adjusting object values. And finally, some of
- the declared macros enable programmers to add compiler or platform
- specific code to their applications, while others are convenience
- macros for larger operations.
-
- \section1 Types
-
- The header file declares several type definitions that guarantee a
- specified bit-size on all platforms supported by Qt for various
- basic types, for example \l qint8 which is a signed char
- guaranteed to be 8-bit on all platforms supported by Qt. The
- header file also declares the \l qlonglong type definition for \c
- {long long int } (\c __int64 on Windows).
-
- Several convenience type definitions are declared: \l qreal for \c
- double or \c float, \l uchar for \c unsigned char, \l uint for \c unsigned
- int, \l ulong for \c unsigned long and \l ushort for \c unsigned
- short.
-
- Finally, the QtMsgType definition identifies the various messages
- that can be generated and sent to a Qt message handler;
- QtMessageHandler is a type definition for a pointer to a function with
- the signature
- \c {void myMessageHandler(QtMsgType, const QMessageLogContext &, const char *)}.
- QMessageLogContext class contains the line, file, and function the
- message was logged at. This information is created by the QMessageLogger
- class.
-
- \section1 Functions
-
- The <QtGlobal> header file contains several functions comparing
- and adjusting an object's value. These functions take a template
- type as argument: You can retrieve the absolute value of an object
- using the qAbs() function, and you can bound a given object's
- value by given minimum and maximum values using the qBound()
- function. You can retrieve the minimum and maximum of two given
- objects using qMin() and qMax() respectively. All these functions
- return a corresponding template type; the template types can be
- replaced by any other type.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 3
-
- <QtGlobal> also contains functions that generate messages from the
- given string argument: qDebug(), qInfo(), qWarning(), qCritical(),
- and qFatal(). These functions call the message handler
- with the given message.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 4
-
- The remaining functions are qRound() and qRound64(), which both
- accept a \c double or \c float value as their argument returning
- the value rounded up to the nearest integer and 64-bit integer
- respectively, the qInstallMessageHandler() function which installs
- the given QtMessageHandler, and the qVersion() function which
- returns the version number of Qt at run-time as a string.
-
- \section1 Macros
-
- The <QtGlobal> header file provides a range of macros (Q_CC_*)
- that are defined if the application is compiled using the
- specified platforms. For example, the Q_CC_SUN macro is defined if
- the application is compiled using Forte Developer, or Sun Studio
- C++. The header file also declares a range of macros (Q_OS_*)
- that are defined for the specified platforms. For example,
- Q_OS_UNIX which is defined for the Unix-based systems.
-
- The purpose of these macros is to enable programmers to add
- compiler or platform specific code to their application.
-
- The remaining macros are convenience macros for larger operations:
- The QT_TR_NOOP(), QT_TRANSLATE_NOOP(), and QT_TRANSLATE_NOOP3()
- macros provide the possibility of marking strings for delayed
- translation. QT_TR_N_NOOP(), QT_TRANSLATE_N_NOOP(), and
- QT_TRANSLATE_N_NOOP3() are numerator dependent variants of these.
- The Q_ASSERT() and Q_ASSERT_X() enables warning messages of various
- level of refinement. The Q_FOREACH() and foreach() macros
- implement Qt's foreach loop.
-
- The Q_INT64_C() and Q_UINT64_C() macros wrap signed and unsigned
- 64-bit integer literals in a platform-independent way. The
- Q_CHECK_PTR() macro prints a warning containing the source code's
- file name and line number, saying that the program ran out of
- memory, if the pointer is \nullptr. The qPrintable() and qUtf8Printable()
- macros represent an easy way of printing text.
-
- The QT_POINTER_SIZE macro expands to the size of a pointer in bytes.
-
- The macros QT_VERSION and QT_VERSION_STR expand to a numeric value
- or a string, respectively, that specifies the version of Qt that the
- application is compiled against.
-
- \sa <QtAlgorithms>, QSysInfo
-*/
-
-/*!
- \typedef qreal
- \relates <QtGlobal>
-
- Typedef for \c double unless Qt is configured with the
- \c{-qreal float} option.
-*/
-
-/*! \typedef uchar
- \relates <QtGlobal>
-
- Convenience typedef for \c{unsigned char}.
-*/
-
-/*! \typedef ushort
- \relates <QtGlobal>
-
- Convenience typedef for \c{unsigned short}.
-*/
-
-/*! \typedef uint
- \relates <QtGlobal>
-
- Convenience typedef for \c{unsigned int}.
-*/
-
-/*! \typedef ulong
- \relates <QtGlobal>
-
- Convenience typedef for \c{unsigned long}.
-*/
-
-/*! \typedef qint8
- \relates <QtGlobal>
-
- Typedef for \c{signed char}. This type is guaranteed to be 8-bit
- on all platforms supported by Qt.
-*/
-
-/*!
- \typedef quint8
- \relates <QtGlobal>
-
- Typedef for \c{unsigned char}. This type is guaranteed to
- be 8-bit on all platforms supported by Qt.
-*/
-
-/*! \typedef qint16
- \relates <QtGlobal>
-
- Typedef for \c{signed short}. This type is guaranteed to be
- 16-bit on all platforms supported by Qt.
-*/
-
-/*!
- \typedef quint16
- \relates <QtGlobal>
-
- Typedef for \c{unsigned short}. This type is guaranteed to
- be 16-bit on all platforms supported by Qt.
-*/
-
-/*! \typedef qint32
- \relates <QtGlobal>
-
- Typedef for \c{signed int}. This type is guaranteed to be 32-bit
- on all platforms supported by Qt.
-*/
-
-/*!
- \typedef quint32
- \relates <QtGlobal>
-
- Typedef for \c{unsigned int}. This type is guaranteed to
- be 32-bit on all platforms supported by Qt.
-*/
-
-/*! \typedef qint64
- \relates <QtGlobal>
-
- Typedef for \c{long long int} (\c __int64 on Windows). This type
- is guaranteed to be 64-bit on all platforms supported by Qt.
-
- Literals of this type can be created using the Q_INT64_C() macro:
-
- \snippet code/src_corelib_global_qglobal.cpp 5
-
- \sa Q_INT64_C(), quint64, qlonglong
-*/
-
-/*!
- \typedef quint64
- \relates <QtGlobal>
-
- Typedef for \c{unsigned long long int} (\c{unsigned __int64} on
- Windows). This type is guaranteed to be 64-bit on all platforms
- supported by Qt.
-
- Literals of this type can be created using the Q_UINT64_C()
- macro:
-
- \snippet code/src_corelib_global_qglobal.cpp 6
-
- \sa Q_UINT64_C(), qint64, qulonglong
-*/
-
-/*!
- \typedef qintptr
- \relates <QtGlobal>
-
- Integral type for representing pointers in a signed integer (useful for
- hashing, etc.).
-
- Typedef for either qint32 or qint64. This type is guaranteed to
- be the same size as a pointer on all platforms supported by Qt. On
- a system with 32-bit pointers, qintptr is a typedef for qint32;
- on a system with 64-bit pointers, qintptr is a typedef for
- qint64.
-
- Note that qintptr is signed. Use quintptr for unsigned values.
-
- \sa qptrdiff, qint32, qint64
-*/
-
-/*!
- \typedef quintptr
- \relates <QtGlobal>
-
- Integral type for representing pointers in an unsigned integer (useful for
- hashing, etc.).
-
- Typedef for either quint32 or quint64. This type is guaranteed to
- be the same size as a pointer on all platforms supported by Qt. On
- a system with 32-bit pointers, quintptr is a typedef for quint32;
- on a system with 64-bit pointers, quintptr is a typedef for
- quint64.
-
- Note that quintptr is unsigned. Use qptrdiff for signed values.
-
- \sa qptrdiff, quint32, quint64
-*/
-
-/*!
- \typedef qptrdiff
- \relates <QtGlobal>
-
- Integral type for representing pointer differences.
-
- Typedef for either qint32 or qint64. This type is guaranteed to be
- the same size as a pointer on all platforms supported by Qt. On a
- system with 32-bit pointers, quintptr is a typedef for quint32; on
- a system with 64-bit pointers, quintptr is a typedef for quint64.
-
- Note that qptrdiff is signed. Use quintptr for unsigned values.
-
- \sa quintptr, qint32, qint64
-*/
-
-/*!
- \typedef qsizetype
- \relates <QtGlobal>
- \since 5.10
-
- Integral type providing Posix' \c ssize_t for all platforms.
-
- This type is guaranteed to be the same size as a \c size_t on all
- platforms supported by Qt.
-
- Note that qsizetype is signed. Use \c size_t for unsigned values.
-
- \sa qptrdiff
-*/
-
-/*!
- \enum QtMsgType
- \relates <QtGlobal>
-
- This enum describes the messages that can be sent to a message
- handler (QtMessageHandler). You can use the enum to identify and
- associate the various message types with the appropriate
- actions.
-
- \value QtDebugMsg
- A message generated by the qDebug() function.
- \value QtInfoMsg
- A message generated by the qInfo() function.
- \value QtWarningMsg
- A message generated by the qWarning() function.
- \value QtCriticalMsg
- A message generated by the qCritical() function.
- \value QtFatalMsg
- A message generated by the qFatal() function.
- \value QtSystemMsg
-
- \c QtInfoMsg was added in Qt 5.5.
-
- \sa QtMessageHandler, qInstallMessageHandler()
-*/
-
-/*! \typedef QFunctionPointer
- \relates <QtGlobal>
-
- This is a typedef for \c{void (*)()}, a pointer to a function that takes
- no arguments and returns void.
-*/
-
-/*! \macro qint64 Q_INT64_C(literal)
- \relates <QtGlobal>
-
- Wraps the signed 64-bit integer \a literal in a
- platform-independent way.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 8
-
- \sa qint64, Q_UINT64_C()
-*/
-
-/*! \macro quint64 Q_UINT64_C(literal)
- \relates <QtGlobal>
-
- Wraps the unsigned 64-bit integer \a literal in a
- platform-independent way.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 9
-
- \sa quint64, Q_INT64_C()
-*/
-
-/*! \typedef qlonglong
- \relates <QtGlobal>
-
- Typedef for \c{long long int} (\c __int64 on Windows). This is
- the same as \l qint64.
-
- \sa qulonglong, qint64
-*/
-
-/*!
- \typedef qulonglong
- \relates <QtGlobal>
-
- Typedef for \c{unsigned long long int} (\c{unsigned __int64} on
- Windows). This is the same as \l quint64.
-
- \sa quint64, qlonglong
-*/
-
-/*! \fn template <typename T> T qAbs(const T &t)
- \relates <QtGlobal>
-
- Compares \a t to the 0 of type T and returns the absolute
- value. Thus if T is \e {double}, then \a t is compared to
- \e{(double) 0}.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 10
-*/
-
-/*! \fn int qRound(double d)
- \relates <QtGlobal>
-
- Rounds \a d to the nearest integer.
-
- Rounds half up (e.g. 0.5 -> 1, -0.5 -> 0).
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 11A
-*/
-
-/*! \fn int qRound(float d)
- \relates <QtGlobal>
-
- Rounds \a d to the nearest integer.
-
- Rounds half up (e.g. 0.5f -> 1, -0.5f -> 0).
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 11B
-*/
-
-/*! \fn qint64 qRound64(double d)
- \relates <QtGlobal>
-
- Rounds \a d to the nearest 64-bit integer.
-
- Rounds half up (e.g. 0.5 -> 1, -0.5 -> 0).
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 12A
-*/
-
-/*! \fn qint64 qRound64(float d)
- \relates <QtGlobal>
-
- Rounds \a d to the nearest 64-bit integer.
-
- Rounds half up (e.g. 0.5f -> 1, -0.5f -> 0).
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 12B
-*/
-
-/*! \fn template <typename T> const T &qMin(const T &a, const T &b)
- \relates <QtGlobal>
-
- Returns the minimum of \a a and \a b.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 13
-
- \sa qMax(), qBound()
-*/
-
-/*! \fn template <typename T> const T &qMax(const T &a, const T &b)
- \relates <QtGlobal>
-
- Returns the maximum of \a a and \a b.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 14
-
- \sa qMin(), qBound()
-*/
-
-/*! \fn template <typename T> const T &qBound(const T &min, const T &val, const T &max)
- \relates <QtGlobal>
-
- Returns \a val bounded by \a min and \a max. This is equivalent
- to qMax(\a min, qMin(\a val, \a max)).
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 15
-
- \sa qMin(), qMax()
-*/
-
-/*! \fn template <typename T> auto qOverload(T functionPointer)
- \relates <QtGlobal>
- \since 5.7
-
- Returns a pointer to an overloaded function. The template
- parameter is the list of the argument types of the function.
- \a functionPointer is the pointer to the (member) function:
-
- \snippet code/src_corelib_global_qglobal.cpp 52
-
- If a member function is also const-overloaded \l qConstOverload and
- \l qNonConstOverload need to be used.
-
- qOverload() requires C++14 enabled. In C++11-only code, the helper
- classes QOverload, QConstOverload, and QNonConstOverload can be used directly:
-
- \snippet code/src_corelib_global_qglobal.cpp 53
-
- \note Qt detects the necessary C++14 compiler support by way of the feature
- test recommendations from
- \l{https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations}
- {C++ Committee's Standing Document 6}.
-
- \sa qConstOverload(), qNonConstOverload(), {Differences between String-Based
- and Functor-Based Connections}
-*/
-
-/*! \fn template <typename T> auto qConstOverload(T memberFunctionPointer)
- \relates <QtGlobal>
- \since 5.7
-
- Returns the \a memberFunctionPointer pointer to a constant member function:
-
- \snippet code/src_corelib_global_qglobal.cpp 54
-
- \sa qOverload, qNonConstOverload, {Differences between String-Based
- and Functor-Based Connections}
-*/
-
-/*! \fn template <typename T> auto qNonConstOverload(T memberFunctionPointer)
- \relates <QtGlobal>
- \since 5.7
-
- Returns the \a memberFunctionPointer pointer to a non-constant member function:
-
- \snippet code/src_corelib_global_qglobal.cpp 54
-
- \sa qOverload, qNonConstOverload, {Differences between String-Based
- and Functor-Based Connections}
-*/
-
-/*!
- \macro QT_VERSION_CHECK
- \relates <QtGlobal>
-
- Turns the major, minor and patch numbers of a version into an
- integer, 0xMMNNPP (MM = major, NN = minor, PP = patch). This can
- be compared with another similarly processed version id.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qt-version-check
-
- \sa QT_VERSION
-*/
-
-/*!
- \macro QT_VERSION
- \relates <QtGlobal>
-
- This macro expands a numeric value of the form 0xMMNNPP (MM =
- major, NN = minor, PP = patch) that specifies Qt's version
- number. For example, if you compile your application against Qt
- 4.1.2, the QT_VERSION macro will expand to 0x040102.
-
- You can use QT_VERSION to use the latest Qt features where
- available.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 16
-
- \sa QT_VERSION_STR, qVersion()
-*/
-
-/*!
- \macro QT_VERSION_STR
- \relates <QtGlobal>
-
- This macro expands to a string that specifies Qt's version number
- (for example, "4.1.2"). This is the version against which the
- application is compiled.
-
- \sa qVersion(), QT_VERSION
-*/
-
-/*!
- \relates <QtGlobal>
-
- Returns the version number of Qt at run-time as a string (for
- example, "4.1.2"). This may be a different version than the
- version the application was compiled against.
-
- \sa QT_VERSION_STR, QLibraryInfo::version()
-*/
-
-const char *qVersion() noexcept
-{
- return QT_VERSION_STR;
-}
-
-bool qSharedBuild() noexcept
-{
-#ifdef QT_SHARED
- return true;
-#else
- return false;
-#endif
-}
-
-/*****************************************************************************
- System detection routines
- *****************************************************************************/
-
-/*!
- \class QSysInfo
- \inmodule QtCore
- \brief The QSysInfo class provides information about the system.
-
- \list
- \li \l WordSize specifies the size of a pointer for the platform
- on which the application is compiled.
- \li \l ByteOrder specifies whether the platform is big-endian or
- little-endian.
- \endlist
-
- Some constants are defined only on certain platforms. You can use
- the preprocessor symbols Q_OS_WIN and Q_OS_MACOS to test that
- the application is compiled under Windows or \macos.
-
- \sa QLibraryInfo
-*/
-
-/*!
- \enum QSysInfo::Sizes
-
- This enum provides platform-specific information about the sizes of data
- structures used by the underlying architecture.
-
- \value WordSize The size in bits of a pointer for the platform on which
- the application is compiled (32 or 64).
-*/
-
-#if QT_DEPRECATED_SINCE(5, 9)
-/*!
- \deprecated
- \variable QSysInfo::WindowsVersion
- \brief the version of the Windows operating system on which the
- application is run.
-
- Use QOperatingSystemVersion::current() instead.
-*/
-
-/*!
- \deprecated
- \fn QSysInfo::WindowsVersion QSysInfo::windowsVersion()
- \since 4.4
-
- Use QOperatingSystemVersion::current() instead.
-
- Returns the version of the Windows operating system on which the
- application is run, or WV_None if the operating system is not
- Windows.
-*/
-
-/*!
- \deprecated
- \variable QSysInfo::MacintoshVersion
- \brief the version of the Macintosh operating system on which
- the application is run.
-
- Use QOperatingSystemVersion::current() instead.
-*/
-
-/*!
- \deprecated
- \fn QSysInfo::MacVersion QSysInfo::macVersion()
-
- Use QOperatingSystemVersion::current() instead.
-
- Returns the version of Darwin (\macos or iOS) on which the
- application is run, or MV_None if the operating system
- is not a version of Darwin.
-*/
-#endif
-
-/*!
- \enum QSysInfo::Endian
-
- \value BigEndian Big-endian byte order (also called Network byte order)
- \value LittleEndian Little-endian byte order
- \value ByteOrder Equals BigEndian or LittleEndian, depending on
- the platform's byte order.
-*/
-
-#if QT_DEPRECATED_SINCE(5, 9)
-/*!
- \deprecated
- \enum QSysInfo::WinVersion
-
- Use the versions defined in QOperatingSystemVersion instead.
-
- This enum provides symbolic names for the various versions of the
- Windows operating system. On Windows, the
- QSysInfo::WindowsVersion variable gives the version of the system
- on which the application is run.
-
- MS-DOS-based versions:
-
- \value WV_32s Windows 3.1 with Win 32s
- \value WV_95 Windows 95
- \value WV_98 Windows 98
- \value WV_Me Windows Me
-
- NT-based versions (note that each operating system version is only represented once rather than each Windows edition):
-
- \value WV_NT Windows NT (operating system version 4.0)
- \value WV_2000 Windows 2000 (operating system version 5.0)
- \value WV_XP Windows XP (operating system version 5.1)
- \value WV_2003 Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition (operating system version 5.2)
- \value WV_VISTA Windows Vista, Windows Server 2008 (operating system version 6.0)
- \value WV_WINDOWS7 Windows 7, Windows Server 2008 R2 (operating system version 6.1)
- \value WV_WINDOWS8 Windows 8 (operating system version 6.2)
- \value WV_WINDOWS8_1 Windows 8.1 (operating system version 6.3), introduced in Qt 5.2
- \value WV_WINDOWS10 Windows 10 (operating system version 10.0), introduced in Qt 5.5
-
- Alternatively, you may use the following macros which correspond directly to the Windows operating system version number:
-
- \value WV_4_0 Operating system version 4.0, corresponds to Windows NT
- \value WV_5_0 Operating system version 5.0, corresponds to Windows 2000
- \value WV_5_1 Operating system version 5.1, corresponds to Windows XP
- \value WV_5_2 Operating system version 5.2, corresponds to Windows Server 2003, Windows Server 2003 R2, Windows Home Server, and Windows XP Professional x64 Edition
- \value WV_6_0 Operating system version 6.0, corresponds to Windows Vista and Windows Server 2008
- \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 and Windows Server 2008 R2
- \value WV_6_2 Operating system version 6.2, corresponds to Windows 8
- \value WV_6_3 Operating system version 6.3, corresponds to Windows 8.1, introduced in Qt 5.2
- \value WV_10_0 Operating system version 10.0, corresponds to Windows 10, introduced in Qt 5.5
-
- The following masks can be used for testing whether a Windows
- version is MS-DOS-based or NT-based:
-
- \value WV_DOS_based MS-DOS-based version of Windows
- \value WV_NT_based NT-based version of Windows
-
- \value WV_None Operating system other than Windows.
-
- \omitvalue WV_CE
- \omitvalue WV_CENET
- \omitvalue WV_CE_5
- \omitvalue WV_CE_6
- \omitvalue WV_CE_based
-
- \sa MacVersion
-*/
-
-/*!
- \deprecated
- \enum QSysInfo::MacVersion
-
- Use the versions defined in QOperatingSystemVersion instead.
-
- This enum provides symbolic names for the various versions of the
- Darwin operating system, covering both \macos and iOS. The
- QSysInfo::MacintoshVersion variable gives the version of the
- system on which the application is run.
-
- \value MV_9 \macos 9
- \value MV_10_0 \macos 10.0
- \value MV_10_1 \macos 10.1
- \value MV_10_2 \macos 10.2
- \value MV_10_3 \macos 10.3
- \value MV_10_4 \macos 10.4
- \value MV_10_5 \macos 10.5
- \value MV_10_6 \macos 10.6
- \value MV_10_7 \macos 10.7
- \value MV_10_8 \macos 10.8
- \value MV_10_9 \macos 10.9
- \value MV_10_10 \macos 10.10
- \value MV_10_11 \macos 10.11
- \value MV_10_12 \macos 10.12
- \value MV_Unknown An unknown and currently unsupported platform
-
- \value MV_CHEETAH Apple codename for MV_10_0
- \value MV_PUMA Apple codename for MV_10_1
- \value MV_JAGUAR Apple codename for MV_10_2
- \value MV_PANTHER Apple codename for MV_10_3
- \value MV_TIGER Apple codename for MV_10_4
- \value MV_LEOPARD Apple codename for MV_10_5
- \value MV_SNOWLEOPARD Apple codename for MV_10_6
- \value MV_LION Apple codename for MV_10_7
- \value MV_MOUNTAINLION Apple codename for MV_10_8
- \value MV_MAVERICKS Apple codename for MV_10_9
- \value MV_YOSEMITE Apple codename for MV_10_10
- \value MV_ELCAPITAN Apple codename for MV_10_11
- \value MV_SIERRA Apple codename for MV_10_12
-
- \value MV_IOS iOS (any)
- \value MV_IOS_4_3 iOS 4.3
- \value MV_IOS_5_0 iOS 5.0
- \value MV_IOS_5_1 iOS 5.1
- \value MV_IOS_6_0 iOS 6.0
- \value MV_IOS_6_1 iOS 6.1
- \value MV_IOS_7_0 iOS 7.0
- \value MV_IOS_7_1 iOS 7.1
- \value MV_IOS_8_0 iOS 8.0
- \value MV_IOS_8_1 iOS 8.1
- \value MV_IOS_8_2 iOS 8.2
- \value MV_IOS_8_3 iOS 8.3
- \value MV_IOS_8_4 iOS 8.4
- \value MV_IOS_9_0 iOS 9.0
- \value MV_IOS_9_1 iOS 9.1
- \value MV_IOS_9_2 iOS 9.2
- \value MV_IOS_9_3 iOS 9.3
- \value MV_IOS_10_0 iOS 10.0
-
- \value MV_TVOS tvOS (any)
- \value MV_TVOS_9_0 tvOS 9.0
- \value MV_TVOS_9_1 tvOS 9.1
- \value MV_TVOS_9_2 tvOS 9.2
- \value MV_TVOS_10_0 tvOS 10.0
-
- \value MV_WATCHOS watchOS (any)
- \value MV_WATCHOS_2_0 watchOS 2.0
- \value MV_WATCHOS_2_1 watchOS 2.1
- \value MV_WATCHOS_2_2 watchOS 2.2
- \value MV_WATCHOS_3_0 watchOS 3.0
-
- \value MV_None Not a Darwin operating system
-
- \sa WinVersion
-*/
-#endif
-
-/*!
- \macro Q_OS_DARWIN
- \relates <QtGlobal>
-
- Defined on Darwin-based operating systems such as \macos, iOS, watchOS, and tvOS.
-*/
-
-/*!
- \macro Q_OS_MAC
- \relates <QtGlobal>
-
- Deprecated synonym for \c Q_OS_DARWIN. Do not use.
- */
-
-/*!
- \macro Q_OS_OSX
- \relates <QtGlobal>
-
- Deprecated synonym for \c Q_OS_MACOS. Do not use.
- */
-
-/*!
- \macro Q_OS_MACOS
- \relates <QtGlobal>
-
- Defined on \macos.
- */
-
-/*!
- \macro Q_OS_IOS
- \relates <QtGlobal>
-
- Defined on iOS.
- */
-
-/*!
- \macro Q_OS_WATCHOS
- \relates <QtGlobal>
-
- Defined on watchOS.
- */
-
-/*!
- \macro Q_OS_TVOS
- \relates <QtGlobal>
-
- Defined on tvOS.
- */
-
-/*!
- \macro Q_OS_WIN
- \relates <QtGlobal>
-
- Defined on all supported versions of Windows. That is, if
- \l Q_OS_WIN32 or \l Q_OS_WIN64 is defined.
-*/
-
-/*!
- \macro Q_OS_WINDOWS
- \relates <QtGlobal>
-
- This is a synonym for Q_OS_WIN.
-*/
-
-/*!
- \macro Q_OS_WIN32
- \relates <QtGlobal>
-
- Defined on 32-bit and 64-bit versions of Windows.
-*/
-
-/*!
- \macro Q_OS_WIN64
- \relates <QtGlobal>
-
- Defined on 64-bit versions of Windows.
-*/
-
-/*!
- \macro Q_OS_CYGWIN
- \relates <QtGlobal>
-
- Defined on Cygwin.
-*/
-
-/*!
- \macro Q_OS_SOLARIS
- \relates <QtGlobal>
-
- Defined on Sun Solaris.
-*/
-
-/*!
- \macro Q_OS_HPUX
- \relates <QtGlobal>
-
- Defined on HP-UX.
-*/
-
-/*!
- \macro Q_OS_LINUX
- \relates <QtGlobal>
-
- Defined on Linux.
-*/
-
-/*!
- \macro Q_OS_ANDROID
- \relates <QtGlobal>
-
- Defined on Android.
-*/
-
-/*!
- \macro Q_OS_FREEBSD
- \relates <QtGlobal>
-
- Defined on FreeBSD.
-*/
-
-/*!
- \macro Q_OS_NETBSD
- \relates <QtGlobal>
-
- Defined on NetBSD.
-*/
-
-/*!
- \macro Q_OS_OPENBSD
- \relates <QtGlobal>
-
- Defined on OpenBSD.
-*/
-
-/*!
- \macro Q_OS_AIX
- \relates <QtGlobal>
-
- Defined on AIX.
-*/
-
-/*!
- \macro Q_OS_HURD
- \relates <QtGlobal>
-
- Defined on GNU Hurd.
-*/
-
-/*!
- \macro Q_OS_QNX
- \relates <QtGlobal>
-
- Defined on QNX Neutrino.
-*/
-
-/*!
- \macro Q_OS_LYNX
- \relates <QtGlobal>
-
- Defined on LynxOS.
-*/
-
-/*!
- \macro Q_OS_BSD4
- \relates <QtGlobal>
-
- Defined on Any BSD 4.4 system.
-*/
-
-/*!
- \macro Q_OS_UNIX
- \relates <QtGlobal>
-
- Defined on Any UNIX BSD/SYSV system.
-*/
-
-/*!
- \macro Q_OS_WASM
- \relates <QtGlobal>
-
- Defined on Web Assembly.
-*/
-
-/*!
- \macro Q_CC_SYM
- \relates <QtGlobal>
-
- Defined if the application is compiled using Digital Mars C/C++
- (used to be Symantec C++).
-*/
-
-/*!
- \macro Q_CC_MSVC
- \relates <QtGlobal>
-
- Defined if the application is compiled using Microsoft Visual
- C/C++, Intel C++ for Windows.
-*/
-
-/*!
- \macro Q_CC_CLANG
- \relates <QtGlobal>
-
- Defined if the application is compiled using Clang.
-*/
-
-/*!
- \macro Q_CC_BOR
- \relates <QtGlobal>
-
- Defined if the application is compiled using Borland/Turbo C++.
-*/
-
-/*!
- \macro Q_CC_WAT
- \relates <QtGlobal>
-
- Defined if the application is compiled using Watcom C++.
-*/
-
-/*!
- \macro Q_CC_GNU
- \relates <QtGlobal>
-
- Defined if the application is compiled using GNU C++.
-*/
-
-/*!
- \macro Q_CC_COMEAU
- \relates <QtGlobal>
-
- Defined if the application is compiled using Comeau C++.
-*/
-
-/*!
- \macro Q_CC_EDG
- \relates <QtGlobal>
-
- Defined if the application is compiled using Edison Design Group
- C++.
-*/
-
-/*!
- \macro Q_CC_OC
- \relates <QtGlobal>
-
- Defined if the application is compiled using CenterLine C++.
-*/
-
-/*!
- \macro Q_CC_SUN
- \relates <QtGlobal>
-
- Defined if the application is compiled using Forte Developer, or
- Sun Studio C++.
-*/
-
-/*!
- \macro Q_CC_MIPS
- \relates <QtGlobal>
-
- Defined if the application is compiled using MIPSpro C++.
-*/
-
-/*!
- \macro Q_CC_DEC
- \relates <QtGlobal>
-
- Defined if the application is compiled using DEC C++.
-*/
-
-/*!
- \macro Q_CC_HPACC
- \relates <QtGlobal>
-
- Defined if the application is compiled using HP aC++.
-*/
-
-/*!
- \macro Q_CC_USLC
- \relates <QtGlobal>
-
- Defined if the application is compiled using SCO OUDK and UDK.
-*/
-
-/*!
- \macro Q_CC_CDS
- \relates <QtGlobal>
-
- Defined if the application is compiled using Reliant C++.
-*/
-
-/*!
- \macro Q_CC_KAI
- \relates <QtGlobal>
-
- Defined if the application is compiled using KAI C++.
-*/
-
-/*!
- \macro Q_CC_INTEL
- \relates <QtGlobal>
-
- Defined if the application is compiled using Intel C++ for Linux,
- Intel C++ for Windows.
-*/
-
-/*!
- \macro Q_CC_HIGHC
- \relates <QtGlobal>
-
- Defined if the application is compiled using MetaWare High C/C++.
-*/
-
-/*!
- \macro Q_CC_PGI
- \relates <QtGlobal>
-
- Defined if the application is compiled using Portland Group C++.
-*/
-
-/*!
- \macro Q_CC_GHS
- \relates <QtGlobal>
-
- Defined if the application is compiled using Green Hills
- Optimizing C++ Compilers.
-*/
-
-/*!
- \macro Q_PROCESSOR_ALPHA
- \relates <QtGlobal>
-
- Defined if the application is compiled for Alpha processors.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_ARM
- \relates <QtGlobal>
-
- Defined if the application is compiled for ARM processors. Qt currently
- supports three optional ARM revisions: \l Q_PROCESSOR_ARM_V5, \l
- Q_PROCESSOR_ARM_V6, and \l Q_PROCESSOR_ARM_V7.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_ARM_V5
- \relates <QtGlobal>
-
- Defined if the application is compiled for ARMv5 processors. The \l
- Q_PROCESSOR_ARM macro is also defined when Q_PROCESSOR_ARM_V5 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_ARM_V6
- \relates <QtGlobal>
-
- Defined if the application is compiled for ARMv6 processors. The \l
- Q_PROCESSOR_ARM and \l Q_PROCESSOR_ARM_V5 macros are also defined when
- Q_PROCESSOR_ARM_V6 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_ARM_V7
- \relates <QtGlobal>
-
- Defined if the application is compiled for ARMv7 processors. The \l
- Q_PROCESSOR_ARM, \l Q_PROCESSOR_ARM_V5, and \l Q_PROCESSOR_ARM_V6 macros
- are also defined when Q_PROCESSOR_ARM_V7 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_AVR32
- \relates <QtGlobal>
-
- Defined if the application is compiled for AVR32 processors.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_BLACKFIN
- \relates <QtGlobal>
-
- Defined if the application is compiled for Blackfin processors.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_IA64
- \relates <QtGlobal>
-
- Defined if the application is compiled for IA-64 processors. This includes
- all Itanium and Itanium 2 processors.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_MIPS
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS processors. Qt currently
- supports seven MIPS revisions: \l Q_PROCESSOR_MIPS_I, \l
- Q_PROCESSOR_MIPS_II, \l Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, \l
- Q_PROCESSOR_MIPS_V, \l Q_PROCESSOR_MIPS_32, and \l Q_PROCESSOR_MIPS_64.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_I
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS-I processors. The \l
- Q_PROCESSOR_MIPS macro is also defined when Q_PROCESSOR_MIPS_I is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_II
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS-II processors. The \l
- Q_PROCESSOR_MIPS and \l Q_PROCESSOR_MIPS_I macros are also defined when
- Q_PROCESSOR_MIPS_II is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_32
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS32 processors. The \l
- Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
- are also defined when Q_PROCESSOR_MIPS_32 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_III
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS-III processors. The \l
- Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
- are also defined when Q_PROCESSOR_MIPS_III is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_IV
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS-IV processors. The \l
- Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, and \l
- Q_PROCESSOR_MIPS_III macros are also defined when Q_PROCESSOR_MIPS_IV is
- defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_V
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS-V processors. The \l
- Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
- Q_PROCESSOR_MIPS_III, and \l Q_PROCESSOR_MIPS_IV macros are also defined
- when Q_PROCESSOR_MIPS_V is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_MIPS_64
- \relates <QtGlobal>
-
- Defined if the application is compiled for MIPS64 processors. The \l
- Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
- Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, and \l Q_PROCESSOR_MIPS_V
- macros are also defined when Q_PROCESSOR_MIPS_64 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_POWER
- \relates <QtGlobal>
-
- Defined if the application is compiled for POWER processors. Qt currently
- supports two Power variants: \l Q_PROCESSOR_POWER_32 and \l
- Q_PROCESSOR_POWER_64.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_POWER_32
- \relates <QtGlobal>
-
- Defined if the application is compiled for 32-bit Power processors. The \l
- Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_32 is
- defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_POWER_64
- \relates <QtGlobal>
-
- Defined if the application is compiled for 64-bit Power processors. The \l
- Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_64 is
- defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_RISCV
- \relates <QtGlobal>
- \since 5.13
-
- Defined if the application is compiled for RISC-V processors. Qt currently
- supports two RISC-V variants: \l Q_PROCESSOR_RISCV_32 and \l
- Q_PROCESSOR_RISCV_64.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_RISCV_32
- \relates <QtGlobal>
- \since 5.13
-
- Defined if the application is compiled for 32-bit RISC-V processors. The \l
- Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_32 is
- defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_RISCV_64
- \relates <QtGlobal>
- \since 5.13
-
- Defined if the application is compiled for 64-bit RISC-V processors. The \l
- Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_64 is
- defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_S390
- \relates <QtGlobal>
-
- Defined if the application is compiled for S/390 processors. Qt supports
- one optional variant of S/390: Q_PROCESSOR_S390_X.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_S390_X
- \relates <QtGlobal>
-
- Defined if the application is compiled for S/390x processors. The \l
- Q_PROCESSOR_S390 macro is also defined when Q_PROCESSOR_S390_X is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_SH
- \relates <QtGlobal>
-
- Defined if the application is compiled for SuperH processors. Qt currently
- supports one SuperH revision: \l Q_PROCESSOR_SH_4A.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_SH_4A
- \relates <QtGlobal>
-
- Defined if the application is compiled for SuperH 4A processors. The \l
- Q_PROCESSOR_SH macro is also defined when Q_PROCESSOR_SH_4A is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_SPARC
- \relates <QtGlobal>
-
- Defined if the application is compiled for SPARC processors. Qt currently
- supports one optional SPARC revision: \l Q_PROCESSOR_SPARC_V9.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_SPARC_V9
- \relates <QtGlobal>
+ \brief The <QtGlobal> header file includes an assortment of other headers.
- Defined if the application is compiled for SPARC V9 processors. The \l
- Q_PROCESSOR_SPARC macro is also defined when Q_PROCESSOR_SPARC_V9 is
- defined.
+ Up to Qt 6.5, most Qt header files included <QtGlobal>. Before Qt 6.5,
+ <QtGlobal> defined an assortment of global declarations. Most of these
+ have moved, at Qt 6.5, to separate headers, so that source code can
+ include only what it needs, rather than the whole assortment. For now,
+ <QtGlobal> includes those other headers (see next section), but future
+ releases of Qt may remove some of these headers from <QtGlobal> or
+ condition their inclusion on a version check. Likewise, in future
+ releases, some Qt headers that currently include <QtGlobal> may stop
+ doing so. The hope is that this will improve compilation times by
+ avoiding global declarations when they are not used.
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro Q_PROCESSOR_X86
- \relates <QtGlobal>
-
- Defined if the application is compiled for x86 processors. Qt currently
- supports two x86 variants: \l Q_PROCESSOR_X86_32 and \l Q_PROCESSOR_X86_64.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_X86_32
- \relates <QtGlobal>
-
- Defined if the application is compiled for 32-bit x86 processors. This
- includes all i386, i486, i586, and i686 processors. The \l Q_PROCESSOR_X86
- macro is also defined when Q_PROCESSOR_X86_32 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-/*!
- \macro Q_PROCESSOR_X86_64
- \relates <QtGlobal>
-
- Defined if the application is compiled for 64-bit x86 processors. This
- includes all AMD64, Intel 64, and other x86_64/x64 processors. The \l
- Q_PROCESSOR_X86 macro is also defined when Q_PROCESSOR_X86_64 is defined.
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-
-/*!
- \macro QT_DISABLE_DEPRECATED_BEFORE
- \relates <QtGlobal>
-
- This macro can be defined in the project file to disable functions deprecated in
- a specified version of Qt or any earlier version. The default version number is 5.0,
- meaning that functions deprecated in or before Qt 5.0 will not be included.
-
- For instance, when using a future release of Qt 5, set
- \c{QT_DISABLE_DEPRECATED_BEFORE=0x050100} to disable functions deprecated in
- Qt 5.1 and earlier. In any release, set
- \c{QT_DISABLE_DEPRECATED_BEFORE=0x000000} to enable all functions, including
- the ones deprecated in Qt 5.0.
-
- \sa QT_DEPRECATED_WARNINGS
- */
-
-
-/*!
- \macro QT_DEPRECATED_WARNINGS
- \relates <QtGlobal>
-
- Since Qt 5.13, this macro has no effect. In Qt 5.12 and before, if this macro
- is defined, the compiler will generate warnings if any API declared as
- deprecated by Qt is used.
-
- \sa QT_DISABLE_DEPRECATED_BEFORE, QT_NO_DEPRECATED_WARNINGS
- */
-
-/*!
- \macro QT_NO_DEPRECATED_WARNINGS
- \relates <QtGlobal>
- \since 5.13
-
- This macro can be used to suppress deprecation warnings that would otherwise
- be generated when using deprecated APIs.
-
- \sa QT_DISABLE_DEPRECATED_BEFORE
-*/
-
-#if defined(QT_BUILD_QMAKE)
-// needed to bootstrap qmake
-static const unsigned int qt_one = 1;
-const int QSysInfo::ByteOrder = ((*((unsigned char *) &qt_one) == 0) ? BigEndian : LittleEndian);
-#endif
-
-#if defined(Q_OS_MAC)
-
-QT_BEGIN_INCLUDE_NAMESPACE
-#include "private/qcore_mac_p.h"
-#include "qnamespace.h"
-QT_END_INCLUDE_NAMESPACE
-
-#if QT_DEPRECATED_SINCE(5, 9)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-QSysInfo::MacVersion QSysInfo::macVersion()
-{
- const auto version = QOperatingSystemVersion::current();
-#if defined(Q_OS_MACOS)
- return QSysInfo::MacVersion(Q_MV_OSX(version.majorVersion(), version.minorVersion()));
-#elif defined(Q_OS_IOS)
- return QSysInfo::MacVersion(Q_MV_IOS(version.majorVersion(), version.minorVersion()));
-#elif defined(Q_OS_TVOS)
- return QSysInfo::MacVersion(Q_MV_TVOS(version.majorVersion(), version.minorVersion()));
-#elif defined(Q_OS_WATCHOS)
- return QSysInfo::MacVersion(Q_MV_WATCHOS(version.majorVersion(), version.minorVersion()));
-#else
- return QSysInfo::MV_Unknown;
-#endif
-}
-const QSysInfo::MacVersion QSysInfo::MacintoshVersion = QSysInfo::macVersion();
-QT_WARNING_POP
-#endif
-
-#ifdef Q_OS_DARWIN
-static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
-{
-#ifdef Q_OS_MACOS
- if (version.majorVersion() == 10) {
- switch (version.minorVersion()) {
- case 9:
- return "Mavericks";
- case 10:
- return "Yosemite";
- case 11:
- return "El Capitan";
- case 12:
- return "Sierra";
- case 13:
- return "High Sierra";
- case 14:
- return "Mojave";
- }
- }
- // unknown, future version
-#else
- Q_UNUSED(version);
-#endif
- return 0;
-}
-#endif
-
-#elif defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
-
-QT_BEGIN_INCLUDE_NAMESPACE
-#include "qt_windows.h"
-QT_END_INCLUDE_NAMESPACE
-
-# ifndef QT_BOOTSTRAPPED
-class QWindowsSockInit
-{
-public:
- QWindowsSockInit();
- ~QWindowsSockInit();
- int version;
-};
-
-QWindowsSockInit::QWindowsSockInit()
-: version(0)
-{
- //### should we try for 2.2 on all platforms ??
- WSAData wsadata;
-
- // IPv6 requires Winsock v2.0 or better.
- if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
- qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
- } else {
- version = 0x20;
- }
-}
-
-QWindowsSockInit::~QWindowsSockInit()
-{
- WSACleanup();
-}
-Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
-# endif // QT_BOOTSTRAPPED
-
-#if QT_DEPRECATED_SINCE(5, 9)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-QSysInfo::WinVersion QSysInfo::windowsVersion()
-{
- const auto version = QOperatingSystemVersion::current();
- if (version.majorVersion() == 6 && version.minorVersion() == 1)
- return QSysInfo::WV_WINDOWS7;
- if (version.majorVersion() == 6 && version.minorVersion() == 2)
- return QSysInfo::WV_WINDOWS8;
- if (version.majorVersion() == 6 && version.minorVersion() == 3)
- return QSysInfo::WV_WINDOWS8_1;
- if (version.majorVersion() == 10 && version.minorVersion() == 0)
- return QSysInfo::WV_WINDOWS10;
- return QSysInfo::WV_NT_based;
-}
-const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
-QT_WARNING_POP
-#endif
-
-static QString readVersionRegistryString(const wchar_t *subKey)
-{
-#if !defined(QT_BUILD_QMAKE)
- return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)")
- .stringValue(subKey);
-#else
- Q_UNUSED(subKey);
- return QString();
-#endif
-}
-
-static inline QString windows10ReleaseId()
-{
- return readVersionRegistryString(L"ReleaseId");
-}
-
-static inline QString windows7Build()
-{
- return readVersionRegistryString(L"CurrentBuild");
-}
-
-static QString winSp_helper()
-{
- const auto osv = qWindowsVersionInfo();
- const qint16 major = osv.wServicePackMajor;
- if (major) {
- QString sp = QStringLiteral("SP ") + QString::number(major);
- const qint16 minor = osv.wServicePackMinor;
- if (minor)
- sp += QLatin1Char('.') + QString::number(minor);
-
- return sp;
- }
- return QString();
-}
-
-static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
-{
- Q_UNUSED(version);
- const OSVERSIONINFOEX osver = qWindowsVersionInfo();
- const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
-
-#define Q_WINVER(major, minor) (major << 8 | minor)
- switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) {
- case Q_WINVER(6, 1):
- return workstation ? "7" : "Server 2008 R2";
- case Q_WINVER(6, 2):
- return workstation ? "8" : "Server 2012";
- case Q_WINVER(6, 3):
- return workstation ? "8.1" : "Server 2012 R2";
- case Q_WINVER(10, 0):
- return workstation ? "10" : "Server 2016";
- }
-#undef Q_WINVER
- // unknown, future version
- return 0;
-}
-
-#endif
-#if defined(Q_OS_UNIX)
-# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
-# define USE_ETC_OS_RELEASE
-struct QUnixOSVersion
-{
- // from /etc/os-release older /etc/lsb-release // redhat /etc/redhat-release // debian /etc/debian_version
- QString productType; // $ID $DISTRIB_ID // single line file containing: // Debian
- QString productVersion; // $VERSION_ID $DISTRIB_RELEASE // <Vendor_ID release Version_ID> // single line file <Release_ID/sid>
- QString prettyName; // $PRETTY_NAME $DISTRIB_DESCRIPTION
-};
-
-static QString unquote(const char *begin, const char *end)
-{
- // man os-release says:
- // Variable assignment values must be enclosed in double
- // or single quotes if they include spaces, semicolons or
- // other special characters outside of A–Z, a–z, 0–9. Shell
- // special characters ("$", quotes, backslash, backtick)
- // must be escaped with backslashes, following shell style.
- // All strings should be in UTF-8 format, and non-printable
- // characters should not be used. It is not supported to
- // concatenate multiple individually quoted strings.
- if (*begin == '"') {
- Q_ASSERT(end[-1] == '"');
- return QString::fromUtf8(begin + 1, end - begin - 2);
- }
- return QString::fromUtf8(begin, end - begin);
-}
-static QByteArray getEtcFileContent(const char *filename)
-{
- // we're avoiding QFile here
- int fd = qt_safe_open(filename, O_RDONLY);
- if (fd == -1)
- return QByteArray();
-
- QT_STATBUF sbuf;
- if (QT_FSTAT(fd, &sbuf) == -1) {
- qt_safe_close(fd);
- return QByteArray();
- }
-
- QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
- buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
- qt_safe_close(fd);
- return buffer;
-}
-
-static bool readEtcFile(QUnixOSVersion &v, const char *filename,
- const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
-{
-
- QByteArray buffer = getEtcFileContent(filename);
- if (buffer.isEmpty())
- return false;
-
- const char *ptr = buffer.constData();
- const char *end = buffer.constEnd();
- const char *eol;
- QByteArray line;
- for ( ; ptr != end; ptr = eol + 1) {
- // find the end of the line after ptr
- eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
- if (!eol)
- eol = end - 1;
- line.setRawData(ptr, eol - ptr);
-
- if (line.startsWith(idKey)) {
- ptr += idKey.length();
- v.productType = unquote(ptr, eol);
- continue;
- }
-
- if (line.startsWith(prettyNameKey)) {
- ptr += prettyNameKey.length();
- v.prettyName = unquote(ptr, eol);
- continue;
- }
-
- if (line.startsWith(versionKey)) {
- ptr += versionKey.length();
- v.productVersion = unquote(ptr, eol);
- continue;
- }
- }
-
- return true;
-}
-
-static bool readOsRelease(QUnixOSVersion &v)
-{
- QByteArray id = QByteArrayLiteral("ID=");
- QByteArray versionId = QByteArrayLiteral("VERSION_ID=");
- QByteArray prettyName = QByteArrayLiteral("PRETTY_NAME=");
-
- // man os-release(5) says:
- // The file /etc/os-release takes precedence over /usr/lib/os-release.
- // Applications should check for the former, and exclusively use its data
- // if it exists, and only fall back to /usr/lib/os-release if it is
- // missing.
- return readEtcFile(v, "/etc/os-release", id, versionId, prettyName) ||
- readEtcFile(v, "/usr/lib/os-release", id, versionId, prettyName);
-}
-
-static bool readEtcLsbRelease(QUnixOSVersion &v)
-{
- bool ok = readEtcFile(v, "/etc/lsb-release", QByteArrayLiteral("DISTRIB_ID="),
- QByteArrayLiteral("DISTRIB_RELEASE="), QByteArrayLiteral("DISTRIB_DESCRIPTION="));
- if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) {
- // some distributions have redundant information for the pretty name,
- // so try /etc/<lowercasename>-release
-
- // we're still avoiding QFile here
- QByteArray distrorelease = "/etc/" + v.productType.toLatin1().toLower() + "-release";
- int fd = qt_safe_open(distrorelease, O_RDONLY);
- if (fd != -1) {
- QT_STATBUF sbuf;
- if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.length()) {
- // file apparently contains interesting information
- QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
- buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
- v.prettyName = QString::fromLatin1(buffer.trimmed());
- }
- qt_safe_close(fd);
- }
- }
-
- // some distributions have a /etc/lsb-release file that does not provide the values
- // we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION.
- // Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values,
- // returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing.
- return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
-}
-
-#if defined(Q_OS_LINUX)
-static QByteArray getEtcFileFirstLine(const char *fileName)
-{
- QByteArray buffer = getEtcFileContent(fileName);
- if (buffer.isEmpty())
- return QByteArray();
-
- const char *ptr = buffer.constData();
- int eol = buffer.indexOf("\n");
- return QByteArray(ptr, eol).trimmed();
-}
-
-static bool readEtcRedHatRelease(QUnixOSVersion &v)
-{
- // /etc/redhat-release analysed should be a one line file
- // the format of its content is <Vendor_ID release Version>
- // i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)"
- QByteArray line = getEtcFileFirstLine("/etc/redhat-release");
- if (line.isEmpty())
- return false;
-
- v.prettyName = QString::fromLatin1(line);
-
- const char keyword[] = "release ";
- int releaseIndex = line.indexOf(keyword);
- v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(QLatin1Char(' '));
- int spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword));
- v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword),
- spaceIndex > -1 ? spaceIndex - releaseIndex - int(strlen(keyword)) : -1));
- return true;
-}
-
-static bool readEtcDebianVersion(QUnixOSVersion &v)
-{
- // /etc/debian_version analysed should be a one line file
- // the format of its content is <Release_ID/sid>
- // i.e. "jessie/sid"
- QByteArray line = getEtcFileFirstLine("/etc/debian_version");
- if (line.isEmpty())
- return false;
-
- v.productType = QStringLiteral("Debian");
- v.productVersion = QString::fromLatin1(line);
- return true;
-}
-#endif
-
-static bool findUnixOsVersion(QUnixOSVersion &v)
-{
- if (readOsRelease(v))
- return true;
- if (readEtcLsbRelease(v))
- return true;
-#if defined(Q_OS_LINUX)
- if (readEtcRedHatRelease(v))
- return true;
- if (readEtcDebianVersion(v))
- return true;
-#endif
- return false;
-}
-# endif // USE_ETC_OS_RELEASE
-#endif // Q_OS_UNIX
-
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
-static const char *osVer_helper(QOperatingSystemVersion)
-{
-/* Data:
-
-
-
-Cupcake
-Donut
-Eclair
-Eclair
-Eclair
-Froyo
-Gingerbread
-Gingerbread
-Honeycomb
-Honeycomb
-Honeycomb
-Ice Cream Sandwich
-Ice Cream Sandwich
-Jelly Bean
-Jelly Bean
-Jelly Bean
-KitKat
-KitKat
-Lollipop
-Lollipop
-Marshmallow
-Nougat
-Nougat
-Oreo
- */
- static const char versions_string[] =
- "\0"
- "Cupcake\0"
- "Donut\0"
- "Eclair\0"
- "Froyo\0"
- "Gingerbread\0"
- "Honeycomb\0"
- "Ice Cream Sandwich\0"
- "Jelly Bean\0"
- "KitKat\0"
- "Lollipop\0"
- "Marshmallow\0"
- "Nougat\0"
- "Oreo\0"
- "\0";
-
- static const int versions_indices[] = {
- 0, 0, 0, 1, 9, 15, 15, 15,
- 22, 28, 28, 40, 40, 40, 50, 50,
- 69, 69, 69, 80, 80, 87, 87, 96,
- 108, 108, 115, -1
- };
-
- static const int versions_count = (sizeof versions_indices) / (sizeof versions_indices[0]);
-
- // https://source.android.com/source/build-numbers.html
- // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
- const int sdk_int = QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT");
- return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]];
-}
-#endif
-
-/*!
- \since 5.4
-
- Returns the architecture of the CPU that Qt was compiled for, in text
- format. Note that this may not match the actual CPU that the application is
- running on if there's an emulation layer or if the CPU supports multiple
- architectures (like x86-64 processors supporting i386 applications). To
- detect that, use currentCpuArchitecture().
-
- Values returned by this function are stable and will not change over time,
- so applications can rely on the returned value as an identifier, except
- that new CPU types may be added over time.
-
- Typical returned values are (note: list not exhaustive):
- \list
- \li "arm"
- \li "arm64"
- \li "i386"
- \li "ia64"
- \li "mips"
- \li "mips64"
- \li "power"
- \li "power64"
- \li "sparc"
- \li "sparcv9"
- \li "x86_64"
- \endlist
-
- \sa QSysInfo::buildAbi(), QSysInfo::currentCpuArchitecture()
-*/
-QString QSysInfo::buildCpuArchitecture()
-{
- return QStringLiteral(ARCH_PROCESSOR);
-}
-
-/*!
- \since 5.4
-
- Returns the architecture of the CPU that the application is running on, in
- text format. Note that this function depends on what the OS will report and
- may not detect the actual CPU architecture if the OS hides that information
- or is unable to provide it. For example, a 32-bit OS running on a 64-bit
- CPU is usually unable to determine the CPU is actually capable of running
- 64-bit programs.
-
- Values returned by this function are mostly stable: an attempt will be made
- to ensure that they stay constant over time and match the values returned
- by QSysInfo::builldCpuArchitecture(). However, due to the nature of the
- operating system functions being used, there may be discrepancies.
-
- Typical returned values are (note: list not exhaustive):
- \list
- \li "arm"
- \li "arm64"
- \li "i386"
- \li "ia64"
- \li "mips"
- \li "mips64"
- \li "power"
- \li "power64"
- \li "sparc"
- \li "sparcv9"
- \li "x86_64"
- \endlist
-
- \sa QSysInfo::buildAbi(), QSysInfo::buildCpuArchitecture()
- */
-QString QSysInfo::currentCpuArchitecture()
-{
-#if defined(Q_OS_WIN)
- // We don't need to catch all the CPU architectures in this function;
- // only those where the host CPU might be different than the build target
- // (usually, 64-bit platforms).
- SYSTEM_INFO info;
- GetNativeSystemInfo(&info);
- switch (info.wProcessorArchitecture) {
-# ifdef PROCESSOR_ARCHITECTURE_AMD64
- case PROCESSOR_ARCHITECTURE_AMD64:
- return QStringLiteral("x86_64");
-# endif
-# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
- case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
-# endif
- case PROCESSOR_ARCHITECTURE_IA64:
- return QStringLiteral("ia64");
- }
-#elif defined(Q_OS_DARWIN) && !defined(Q_OS_MACOS)
- // iOS-based OSes do not return the architecture on uname(2)'s result.
- return buildCpuArchitecture();
-#elif defined(Q_OS_UNIX)
- long ret = -1;
- struct utsname u;
-
-# if defined(Q_OS_SOLARIS)
- // We need a special call for Solaris because uname(2) on x86 returns "i86pc" for
- // both 32- and 64-bit CPUs. Reference:
- // http://docs.oracle.com/cd/E18752_01/html/816-5167/sysinfo-2.html#REFMAN2sysinfo-2
- // http://fxr.watson.org/fxr/source/common/syscall/systeminfo.c?v=OPENSOLARIS
- // http://fxr.watson.org/fxr/source/common/conf/param.c?v=OPENSOLARIS;im=10#L530
- if (ret == -1)
- ret = sysinfo(SI_ARCHITECTURE_64, u.machine, sizeof u.machine);
-# endif
-
- if (ret == -1)
- ret = uname(&u);
-
- // we could use detectUnixVersion() above, but we only need a field no other function does
- if (ret != -1) {
- // the use of QT_BUILD_INTERNAL here is simply to ensure all branches build
- // as we don't often build on some of the less common platforms
-# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL)
- if (strcmp(u.machine, "aarch64") == 0)
- return QStringLiteral("arm64");
- if (strncmp(u.machine, "armv", 4) == 0)
- return QStringLiteral("arm");
-# endif
-# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL)
- // harmonize "powerpc" and "ppc" to "power"
- if (strncmp(u.machine, "ppc", 3) == 0)
- return QLatin1String("power") + QLatin1String(u.machine + 3);
- if (strncmp(u.machine, "powerpc", 7) == 0)
- return QLatin1String("power") + QLatin1String(u.machine + 7);
- if (strcmp(u.machine, "Power Macintosh") == 0)
- return QLatin1String("power");
-# endif
-# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL)
- // Solaris sysinfo(2) (above) uses "sparcv9", but uname -m says "sun4u";
- // Linux says "sparc64"
- if (strcmp(u.machine, "sun4u") == 0 || strcmp(u.machine, "sparc64") == 0)
- return QStringLiteral("sparcv9");
- if (strcmp(u.machine, "sparc32") == 0)
- return QStringLiteral("sparc");
-# endif
-# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL)
- // harmonize all "i?86" to "i386"
- if (strlen(u.machine) == 4 && u.machine[0] == 'i'
- && u.machine[2] == '8' && u.machine[3] == '6')
- return QStringLiteral("i386");
- if (strcmp(u.machine, "amd64") == 0) // Solaris
- return QStringLiteral("x86_64");
-# endif
- return QString::fromLatin1(u.machine);
- }
-#endif
- return buildCpuArchitecture();
-}
-
-/*!
- \since 5.4
-
- Returns the full architecture string that Qt was compiled for. This string
- is useful for identifying different, incompatible builds. For example, it
- can be used as an identifier to request an upgrade package from a server.
-
- The values returned from this function are kept stable as follows: the
- mandatory components of the result will not change in future versions of
- Qt, but optional suffixes may be added.
-
- The returned value is composed of three or more parts, separated by dashes
- ("-"). They are:
+ \section1 List of Headers Extracted from <QtGlobal>
\table
- \header \li Component \li Value
- \row \li CPU Architecture \li The same as QSysInfo::buildCpuArchitecture(), such as "arm", "i386", "mips" or "x86_64"
- \row \li Endianness \li "little_endian" or "big_endian"
- \row \li Word size \li Whether it's a 32- or 64-bit application. Possible values are:
- "llp64" (Windows 64-bit), "lp64" (Unix 64-bit), "ilp32" (32-bit)
- \row \li (Optional) ABI \li Zero or more components identifying different ABIs possible in this architecture.
- Currently, Qt has optional ABI components for ARM and MIPS processors: one
- component is the main ABI (such as "eabi", "o32", "n32", "o64"); another is
- whether the calling convention is using hardware floating point registers ("hardfloat"
- is present).
-
- Additionally, if Qt was configured with \c{-qreal float}, the ABI option tag "qreal_float"
- will be present. If Qt was configured with another type as qreal, that type is present after
- "qreal_", with all characters other than letters and digits escaped by an underscore, followed
- by two hex digits. For example, \c{-qreal long double} becomes "qreal_long_20double".
+ \header \li Header \li Summary
+ \row \li <QFlags> \li Type-safe way of combining enum values
+ \row \li \l <QForeach> \li Qt's implementation of foreach and forever loops
+ \row \li \l <QFunctionPointer> \li Typedef for a pointer-to-function type
+ \row \li <QGlobalStatic> \li Thread-safe initialization of global static objects
+ \row \li \l <QOverload> \li Helpers for resolving member function overloads
+ \row \li <QSysInfo> \li A helper class to get system information
+ \row \li \l <QTypeInfo> \li Helpers to get type information
+ \row \li \l <QtAssert> \li Q_ASSERT and other runtime checks
+ \row \li \l <QtClassHelperMacros> \li Qt class helper macros
+ \row \li \l <QtCompilerDetection> \li Compiler-specific macro definitions
+ \row \li \l <QtDeprecationMarkers> \li Deprecation helper macros
+ \row \li \l <QtEnvironmentVariables> \li Helpers for working with environment variables
+ \row \li <QtExceptionHandling> \li Helpers for exception handling
+ \row \li \l <QtLogging> \li Qt logging helpers
+ \row \li <QtMalloc> \li Memory allocation helpers
+ \row \li \l <QtMinMax> \li Helpers for comparing values
+ \row \li \l <QtNumeric> \li Various numeric functions
+ \row \li \l <QtPreprocessorSupport> \li Helper preprocessor macros
+ \row \li \l <QtProcessorDetection> \li Architecture-specific macro definitions
+ \row \li \l <QtResource> \li Helpers for initializing and cleaning resources
+ \row \li \l <QtSwap> \li Implementation of qSwap()
+ \row \li \l <QtSystemDetection> \li Platform-specific macro definitions
+ \row \li \l <QtTranslation> \li Qt translation helpers
+ \row \li \l <QtTypeTraits> \li Qt type traits
+ \row \li \l <QtTypes> \li Qt fundamental type declarations
+ \row \li \l <QtVersionChecks> \li QT_VERSION_CHECK and related checks
+ \row \li \l <QtVersion> \li QT_VERSION_STR and qVersion()
\endtable
-
- \sa QSysInfo::buildCpuArchitecture()
-*/
-QString QSysInfo::buildAbi()
-{
-#ifdef Q_COMPILER_UNICODE_STRINGS
- // ARCH_FULL is a concatenation of strings (incl. ARCH_PROCESSOR), which breaks
- // QStringLiteral on MSVC. Since the concatenation behavior we want is specified
- // the same C++11 paper as the Unicode strings, we'll use that macro and hope
- // that Microsoft implements the new behavior when they add support for Unicode strings.
- return QStringLiteral(ARCH_FULL);
-#else
- return QLatin1String(ARCH_FULL);
-#endif
-}
-
-static QString unknownText()
-{
- return QStringLiteral("unknown");
-}
-
-/*!
- \since 5.4
-
- Returns the type of the operating system kernel Qt was compiled for. It's
- also the kernel the application is running on, unless the host operating
- system is running a form of compatibility or virtualization layer.
-
- Values returned by this function are stable and will not change over time,
- so applications can rely on the returned value as an identifier, except
- that new OS kernel types may be added over time.
-
- On Windows, this function returns the type of Windows kernel, like "winnt".
- On Unix systems, it returns the same as the output of \c{uname
- -s} (lowercased).
-
- \note This function may return surprising values: it returns "linux"
- for all operating systems running Linux (including Android), "qnx" for all
- operating systems running QNX, "freebsd" for
- Debian/kFreeBSD, and "darwin" for \macos and iOS. For information on the type
- of product the application is running on, see productType().
-
- \sa QFileSelector, kernelVersion(), productType(), productVersion(), prettyProductName()
-*/
-QString QSysInfo::kernelType()
-{
-#if defined(Q_OS_WIN)
- return QStringLiteral("winnt");
-#elif defined(Q_OS_UNIX)
- struct utsname u;
- if (uname(&u) == 0)
- return QString::fromLatin1(u.sysname).toLower();
-#endif
- return unknownText();
-}
-
-/*!
- \since 5.4
-
- Returns the release version of the operating system kernel. On Windows, it
- returns the version of the NT kernel. On Unix systems, including
- Android and \macos, it returns the same as the \c{uname -r}
- command would return.
-
- If the version could not be determined, this function may return an empty
- string.
-
- \sa kernelType(), productType(), productVersion(), prettyProductName()
*/
-QString QSysInfo::kernelVersion()
-{
-#ifdef Q_OS_WIN
- const auto osver = QOperatingSystemVersion::current();
- return QString::number(osver.majorVersion()) + QLatin1Char('.') + QString::number(osver.minorVersion())
- + QLatin1Char('.') + QString::number(osver.microVersion());
-#else
- struct utsname u;
- if (uname(&u) == 0)
- return QString::fromLatin1(u.release);
- return QString();
-#endif
-}
-
-
-/*!
- \since 5.4
-
- Returns the product name of the operating system this application is
- running in. If the application is running on some sort of emulation or
- virtualization layer (such as WINE on a Unix system), this function will
- inspect the emulation / virtualization layer.
-
- Values returned by this function are stable and will not change over time,
- so applications can rely on the returned value as an identifier, except
- that new OS types may be added over time.
-
- \b{Linux and Android note}: this function returns "android" for Linux
- systems running Android userspace, notably when using the Bionic library.
- For all other Linux systems, regardless of C library being used, it tries
- to determine the distribution name and returns that. If determining the
- distribution name failed, it returns "unknown".
-
- \b{\macos note}: this function returns "osx" for all \macos systems,
- regardless of Apple naming convention. The returned string will be updated
- for Qt 6. Note that this function erroneously returned "macos" for \macos
- 10.12 in Qt versions 5.6.2, 5.7.1, and 5.8.0.
-
- \b{Darwin, iOS, tvOS, and watchOS note}: this function returns "ios" for
- iOS systems, "tvos" for tvOS systems, "watchos" for watchOS systems, and
- "darwin" in case the system could not be determined.
-
- \b{FreeBSD note}: this function returns "debian" for Debian/kFreeBSD and
- "unknown" otherwise.
-
- \b{Windows note}: this function return "windows"
-
- For other Unix-type systems, this function usually returns "unknown".
-
- \sa QFileSelector, kernelType(), kernelVersion(), productVersion(), prettyProductName()
-*/
-QString QSysInfo::productType()
-{
- // similar, but not identical to QFileSelectorPrivate::platformSelectors
-#if defined(Q_OS_WIN)
- return QStringLiteral("windows");
-
-#elif defined(Q_OS_QNX)
- return QStringLiteral("qnx");
-
-#elif defined(Q_OS_ANDROID)
- return QStringLiteral("android");
-
-#elif defined(Q_OS_IOS)
- return QStringLiteral("ios");
-#elif defined(Q_OS_TVOS)
- return QStringLiteral("tvos");
-#elif defined(Q_OS_WATCHOS)
- return QStringLiteral("watchos");
-#elif defined(Q_OS_MACOS)
- // ### Qt6: remove fallback
-# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- return QStringLiteral("macos");
-# else
- return QStringLiteral("osx");
-# endif
-#elif defined(Q_OS_DARWIN)
- return QStringLiteral("darwin");
-
-#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
- QUnixOSVersion unixOsVersion;
- findUnixOsVersion(unixOsVersion);
- if (!unixOsVersion.productType.isEmpty())
- return unixOsVersion.productType;
-#endif
- return unknownText();
-}
-
-/*!
- \since 5.4
-
- Returns the product version of the operating system in string form. If the
- version could not be determined, this function returns "unknown".
-
- It will return the Android, iOS, \macos, Windows full-product
- versions on those systems.
-
- Typical returned values are (note: list not exhaustive):
- \list
- \li "2016.09" (Amazon Linux AMI 2016.09)
- \li "7.1" (Android Nougat)
- \li "25" (Fedora 25)
- \li "10.1" (iOS 10.1)
- \li "10.12" (macOS Sierra)
- \li "10.0" (tvOS 10)
- \li "16.10" (Ubuntu 16.10)
- \li "3.1" (watchOS 3.1)
- \li "7 SP 1" (Windows 7 Service Pack 1)
- \li "8.1" (Windows 8.1)
- \li "10" (Windows 10)
- \li "Server 2016" (Windows Server 2016)
- \endlist
-
- On Linux systems, it will try to determine the distribution version and will
- return that. This is also done on Debian/kFreeBSD, so this function will
- return Debian version in that case.
-
- In all other Unix-type systems, this function always returns "unknown".
-
- \note The version string returned from this function is not guaranteed to
- be orderable. On Linux, the version of
- the distribution may jump unexpectedly, please refer to the distribution's
- documentation for versioning practices.
-
- \sa kernelType(), kernelVersion(), productType(), prettyProductName()
-*/
-QString QSysInfo::productVersion()
-{
-#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
- const auto version = QOperatingSystemVersion::current();
- return QString::number(version.majorVersion()) + QLatin1Char('.') + QString::number(version.minorVersion());
-#elif defined(Q_OS_WIN)
- const char *version = osVer_helper();
- if (version) {
- const QLatin1Char spaceChar(' ');
- return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
- }
- // fall through
-
-#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
- QUnixOSVersion unixOsVersion;
- findUnixOsVersion(unixOsVersion);
- if (!unixOsVersion.productVersion.isEmpty())
- return unixOsVersion.productVersion;
-#endif
-
- // fallback
- return unknownText();
-}
-
-/*!
- \since 5.4
-
- Returns a prettier form of productType() and productVersion(), containing
- other tokens like the operating system type, codenames and other
- information. The result of this function is suitable for displaying to the
- user, but not for long-term storage, as the string may change with updates
- to Qt.
-
- If productType() is "unknown", this function will instead use the
- kernelType() and kernelVersion() functions.
-
- \sa kernelType(), kernelVersion(), productType(), productVersion()
-*/
-QString QSysInfo::prettyProductName()
-{
-#if (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
- const auto version = QOperatingSystemVersion::current();
- const int majorVersion = version.majorVersion();
- const QString versionString = QString::number(majorVersion) + QLatin1Char('.')
- + QString::number(version.minorVersion());
- QString result = version.name() + QLatin1Char(' ');
- const char *name = osVer_helper(version);
- if (!name)
- return result + versionString;
- result += QLatin1String(name);
-# if !defined(Q_OS_WIN)
- return result + QLatin1String(" (") + versionString + QLatin1Char(')');
-# else
- // (resembling winver.exe): Windows 10 "Windows 10 Version 1809"
- if (majorVersion >= 10) {
- const auto releaseId = windows10ReleaseId();
- if (!releaseId.isEmpty())
- result += QLatin1String(" Version ") + releaseId;
- return result;
- }
- // Windows 7: "Windows 7 Version 6.1 (Build 7601: Service Pack 1)"
- result += QLatin1String(" Version ") + versionString + QLatin1String(" (");
- const auto build = windows7Build();
- if (!build.isEmpty())
- result += QLatin1String("Build ") + build;
- const auto servicePack = winSp_helper();
- if (!servicePack.isEmpty())
- result += QLatin1String(": ") + servicePack;
- return result + QLatin1Char(')');
-# endif // Windows
-#elif defined(Q_OS_HAIKU)
- return QLatin1String("Haiku ") + productVersion();
-#elif defined(Q_OS_UNIX)
-# ifdef USE_ETC_OS_RELEASE
- QUnixOSVersion unixOsVersion;
- findUnixOsVersion(unixOsVersion);
- if (!unixOsVersion.prettyName.isEmpty())
- return unixOsVersion.prettyName;
-# endif
- struct utsname u;
- if (uname(&u) == 0)
- return QString::fromLatin1(u.sysname) + QLatin1Char(' ') + QString::fromLatin1(u.release);
-#endif
- return unknownText();
-}
-
-#ifndef QT_BOOTSTRAPPED
-/*!
- \since 5.6
-
- Returns this machine's host name, if one is configured. Note that hostnames
- are not guaranteed to be globally unique, especially if they were
- configured automatically.
-
- This function does not guarantee the returned host name is a Fully
- Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the
- returned name to an FQDN.
-
- This function returns the same as QHostInfo::localHostName().
-
- \sa QHostInfo::localDomainName, machineUniqueId()
- */
-QString QSysInfo::machineHostName()
-{
- // the hostname can change, so we can't cache it
-#if defined(Q_OS_LINUX)
- // gethostname(3) on Linux just calls uname(2), so do it ourselves
- // and avoid a memcpy
- struct utsname u;
- if (uname(&u) == 0)
- return QString::fromLocal8Bit(u.nodename);
- return QString();
-#else
-# ifdef Q_OS_WIN
- // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
- winsockInit();
-# endif
-
- char hostName[512];
- if (gethostname(hostName, sizeof(hostName)) == -1)
- return QString();
- hostName[sizeof(hostName) - 1] = '\0';
- return QString::fromLocal8Bit(hostName);
-#endif
-}
-#endif // QT_BOOTSTRAPPED
-
-enum {
- UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") - 1
-};
-
-/*!
- \since 5.11
-
- Returns a unique ID for this machine, if one can be determined. If no
- unique ID could be determined, this function returns an empty byte array.
- Unlike machineHostName(), the value returned by this function is likely
- globally unique.
-
- A unique ID is useful in network operations to identify this machine for an
- extended period of time, when the IP address could change or if this
- machine could have more than one IP address. For example, the ID could be
- used when communicating with a server or when storing device-specific data
- in shared network storage.
-
- Note that on some systems, this value will persist across reboots and on
- some it will not. Applications should not blindly depend on this fact
- without verifying the OS capabilities. In particular, on Linux systems,
- this ID is usually permanent and it matches the D-Bus machine ID, except
- for nodes without their own storage (replicated nodes).
-
- \sa machineHostName(), bootUniqueId()
-*/
-QByteArray QSysInfo::machineUniqueId()
-{
-#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
- char uuid[UuidStringLen + 1];
- io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
- QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
- CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman);
- return QByteArray(uuid);
-#elif defined(Q_OS_BSD4) && defined(KERN_HOSTUUID)
- char uuid[UuidStringLen + 1];
- size_t uuidlen = sizeof(uuid);
- int name[] = { CTL_KERN, KERN_HOSTUUID };
- if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0
- && uuidlen == sizeof(uuid))
- return QByteArray(uuid, uuidlen - 1);
-#elif defined(Q_OS_UNIX)
- // The modern name on Linux is /etc/machine-id, but that path is
- // unlikely to exist on non-Linux (non-systemd) systems. The old
- // path is more than enough.
- static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id";
- const char *firstfilename = fullfilename + sizeof("/usr/local") - 1;
- int fd = qt_safe_open(firstfilename, O_RDONLY);
- if (fd == -1 && errno == ENOENT)
- fd = qt_safe_open(fullfilename, O_RDONLY);
-
- if (fd != -1) {
- char buffer[32]; // 128 bits, hex-encoded
- qint64 len = qt_safe_read(fd, buffer, sizeof(buffer));
- qt_safe_close(fd);
-
- if (len != -1)
- return QByteArray(buffer, len);
- }
-#elif defined(Q_OS_WIN)
- // Let's poke at the registry
- // ### Qt 6: Use new helpers from qwinregistry.cpp (once bootstrap builds are obsolete)
- HKEY key = NULL;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ | KEY_WOW64_64KEY, &key)
- == ERROR_SUCCESS) {
- wchar_t buffer[UuidStringLen + 1];
- DWORD size = sizeof(buffer);
- bool ok = (RegQueryValueEx(key, L"MachineGuid", NULL, NULL, (LPBYTE)buffer, &size) ==
- ERROR_SUCCESS);
- RegCloseKey(key);
- if (ok)
- return QStringView(buffer, (size - 1) / 2).toLatin1();
- }
-#endif
- return QByteArray();
-}
-
-/*!
- \since 5.11
-
- Returns a unique ID for this machine's boot, if one can be determined. If
- no unique ID could be determined, this function returns an empty byte
- array. This value is expected to change after every boot and can be
- considered globally unique.
-
- This function is currently only implemented for Linux and Apple operating
- systems.
-
- \sa machineUniqueId()
-*/
-QByteArray QSysInfo::bootUniqueId()
-{
-#ifdef Q_OS_LINUX
- // use low-level API here for simplicity
- int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY);
- if (fd != -1) {
- char uuid[UuidStringLen];
- qint64 len = qt_safe_read(fd, uuid, sizeof(uuid));
- qt_safe_close(fd);
- if (len == UuidStringLen)
- return QByteArray(uuid, UuidStringLen);
- }
-#elif defined(Q_OS_DARWIN)
- // "kern.bootsessionuuid" is only available by name
- char uuid[UuidStringLen + 1];
- size_t uuidlen = sizeof(uuid);
- if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0
- && uuidlen == sizeof(uuid))
- return QByteArray(uuid, uuidlen - 1);
-#endif
- return QByteArray();
-};
-
-/*!
- \macro void Q_ASSERT(bool test)
- \relates <QtGlobal>
-
- Prints a warning message containing the source code file name and
- line number if \a test is \c false.
-
- Q_ASSERT() is useful for testing pre- and post-conditions
- during development. It does nothing if \c QT_NO_DEBUG was defined
- during compilation.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 17
-
- If \c b is zero, the Q_ASSERT statement will output the following
- message using the qFatal() function:
-
- \snippet code/src_corelib_global_qglobal.cpp 18
-
- \sa Q_ASSERT_X(), qFatal(), {Debugging Techniques}
-*/
-
-/*!
- \macro void Q_ASSERT_X(bool test, const char *where, const char *what)
- \relates <QtGlobal>
-
- Prints the message \a what together with the location \a where,
- the source file name and line number if \a test is \c false.
-
- Q_ASSERT_X is useful for testing pre- and post-conditions during
- development. It does nothing if \c QT_NO_DEBUG was defined during
- compilation.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 19
-
- If \c b is zero, the Q_ASSERT_X statement will output the following
- message using the qFatal() function:
-
- \snippet code/src_corelib_global_qglobal.cpp 20
-
- \sa Q_ASSERT(), qFatal(), {Debugging Techniques}
-*/
-
-/*!
- \macro void Q_ASSUME(bool expr)
- \relates <QtGlobal>
- \since 5.0
-
- Causes the compiler to assume that \a expr is \c true. This macro is useful
- for improving code generation, by providing the compiler with hints about
- conditions that it would not otherwise know about. However, there is no
- guarantee that the compiler will actually use those hints.
-
- This macro could be considered a "lighter" version of \l{Q_ASSERT()}. While
- Q_ASSERT will abort the program's execution if the condition is \c false,
- Q_ASSUME will tell the compiler not to generate code for those conditions.
- Therefore, it is important that the assumptions always hold, otherwise
- undefined behaviour may occur.
-
- If \a expr is a constantly \c false condition, Q_ASSUME will tell the compiler
- that the current code execution cannot be reached. That is, Q_ASSUME(false)
- is equivalent to Q_UNREACHABLE().
-
- In debug builds the condition is enforced by an assert to facilitate debugging.
-
- \note Q_LIKELY() tells the compiler that the expression is likely, but not
- the only possibility. Q_ASSUME tells the compiler that it is the only
- possibility.
-
- \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY()
-*/
-
-/*!
- \macro void Q_UNREACHABLE()
- \relates <QtGlobal>
- \since 5.0
-
- Tells the compiler that the current point cannot be reached by any
- execution, so it may optimize any code paths leading here as dead code, as
- well as code continuing from here.
-
- This macro is useful to mark impossible conditions. For example, given the
- following enum:
-
- \snippet code/src_corelib_global_qglobal.cpp qunreachable-enum
-
- One can write a switch table like so:
-
- \snippet code/src_corelib_global_qglobal.cpp qunreachable-switch
-
- The advantage of inserting Q_UNREACHABLE() at that point is that the
- compiler is told not to generate code for a shape variable containing that
- value. If the macro is missing, the compiler will still generate the
- necessary comparisons for that value. If the case label were removed, some
- compilers could produce a warning that some enum values were not checked.
-
- By using this macro in impossible conditions, code coverage may be improved
- as dead code paths may be eliminated.
-
- In debug builds the condition is enforced by an assert to facilitate debugging.
-
- \sa Q_ASSERT(), Q_ASSUME(), qFatal()
-*/
-
-/*!
- \macro void Q_FALLTHROUGH()
- \relates <QtGlobal>
- \since 5.8
-
- Can be used in switch statements at the end of case block to tell the compiler
- and other developers that that the lack of a break statement is intentional.
-
- This is useful since a missing break statement is often a bug, and some
- compilers can be configured to emit warnings when one is not found.
-
- \sa Q_UNREACHABLE()
-*/
-
-/*!
- \macro void Q_CHECK_PTR(void *pointer)
- \relates <QtGlobal>
-
- If \a pointer is \nullptr, prints a message containing the source
- code's file name and line number, saying that the program ran out
- of memory and aborts program execution. It throws \c std::bad_alloc instead
- if exceptions are enabled.
-
- Q_CHECK_PTR does nothing if \c QT_NO_DEBUG and \c QT_NO_EXCEPTIONS were
- defined during compilation. Therefore you must not use Q_CHECK_PTR to check
- for successful memory allocations because the check will be disabled in
- some cases.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 21
-
- \sa qWarning(), {Debugging Techniques}
-*/
-
-/*!
- \fn template <typename T> T *q_check_ptr(T *p)
- \relates <QtGlobal>
-
- Uses Q_CHECK_PTR on \a p, then returns \a p.
-
- This can be used as an inline version of Q_CHECK_PTR.
-*/
-
-/*!
- \macro const char* Q_FUNC_INFO()
- \relates <QtGlobal>
-
- Expands to a string that describe the function the macro resides in. How this string looks
- more specifically is compiler dependent. With GNU GCC it is typically the function signature,
- while with other compilers it might be the line and column number.
-
- Q_FUNC_INFO can be conveniently used with qDebug(). For example, this function:
-
- \snippet code/src_corelib_global_qglobal.cpp 22
-
- when instantiated with the integer type, will with the GCC compiler produce:
-
- \tt{const TInputType& myMin(const TInputType&, const TInputType&) [with TInputType = int] was called with value1: 3 value2: 4}
-
- If this macro is used outside a function, the behavior is undefined.
- */
-
-/*!
- \internal
- The Q_CHECK_PTR macro calls this function if an allocation check
- fails.
-*/
-void qt_check_pointer(const char *n, int l) noexcept
-{
- // make separate printing calls so that the first one may flush;
- // the second one could want to allocate memory (fputs prints a
- // newline and stderr auto-flushes).
- fputs("Out of memory", stderr);
- fprintf(stderr, " in %s, line %d\n", n, l);
-
- std::terminate();
-}
-
-/*
- \internal
- Allows you to throw an exception without including <new>
- Called internally from Q_CHECK_PTR on certain OS combinations
-*/
-void qBadAlloc()
-{
- QT_THROW(std::bad_alloc());
-}
-
-#ifndef QT_NO_EXCEPTIONS
-/*
- \internal
- Allows you to call std::terminate() without including <exception>.
- Called internally from QT_TERMINATE_ON_EXCEPTION
-*/
-Q_NORETURN void qTerminate() noexcept
-{
- std::terminate();
-}
-#endif
-
-/*
- The Q_ASSERT macro calls this function when the test fails.
-*/
-void qt_assert(const char *assertion, const char *file, int line) noexcept
-{
- QMessageLogger(file, line, nullptr).fatal("ASSERT: \"%s\" in file %s, line %d", assertion, file, line);
-}
-
-/*
- The Q_ASSERT_X macro calls this function when the test fails.
-*/
-void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept
-{
- QMessageLogger(file, line, nullptr).fatal("ASSERT failure in %s: \"%s\", file %s, line %d", where, what, file, line);
-}
-
/*
Dijkstra's bisection algorithm to find the square root of an integer.
- Deliberately not exported as part of the Qt API, but used in both
- qsimplerichtext.cpp and qgfxraster_qws.cpp
+ Deliberately not exported as part of the Qt API, but used in
+ qtextdocument.cpp.
*/
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n)
{
// n must be in the range 0...UINT_MAX/2-1
- if (n >= (UINT_MAX>>2)) {
+ if (n >= (UINT_MAX >> 2)) {
unsigned int r = 2 * qt_int_sqrt(n / 4);
unsigned int r2 = r + 1;
return (n >= r2 * r2) ? r2 : r;
}
- uint h, p= 0, q= 1, r= n;
+ uint h, p = 0, q = 1, r = n;
while (q <= n)
q <<= 2;
while (q != 1) {
q >>= 2;
- h= p + q;
+ h = p + q;
p >>= 1;
if (r >= h) {
p += q;
@@ -3393,879 +118,12 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n)
return p;
}
-void *qMemCopy(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); }
-void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); }
-
-// In the C runtime on all platforms access to the environment is not thread-safe. We
-// add thread-safety for the Qt wrappers.
-static QBasicMutex environmentMutex;
-
-/*
- Wraps tzset(), which accesses the environment, so should only be called while
- we hold the lock on the environment mutex.
-*/
-void qTzSet()
-{
- const auto locker = qt_scoped_lock(environmentMutex);
-#if defined(Q_OS_WIN)
- _tzset();
-#else
- tzset();
-#endif // Q_OS_WIN
-}
-
-/*
- Wrap mktime(), which is specified to behave as if it called tzset(), hence
- shares its implicit environment-dependence.
-*/
-time_t qMkTime(struct tm *when)
-{
- const auto locker = qt_scoped_lock(environmentMutex);
- return mktime(when);
-}
-
// Also specified to behave as if they call tzset():
// localtime() -- but not localtime_r(), which we use when threaded
// strftime() -- not used (except in tests)
-/*!
- \relates <QtGlobal>
- \threadsafe
-
- Returns the value of the environment variable with name \a varName as a
- QByteArray. If no variable by that name is found in the environment, this
- function returns a default-constructed QByteArray.
-
- The Qt environment manipulation functions are thread-safe, but this
- requires that the C library equivalent functions like getenv and putenv are
- not directly called.
-
- To convert the data to a QString use QString::fromLocal8Bit().
-
- \note on desktop Windows, qgetenv() may produce data loss if the
- original string contains Unicode characters not representable in the
- ANSI encoding. Use qEnvironmentVariable() instead.
- On Unix systems, this function is lossless.
-
- \sa qputenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet(),
- qEnvironmentVariableIsEmpty()
-*/
-QByteArray qgetenv(const char *varName)
-{
- const auto locker = qt_scoped_lock(environmentMutex);
-#ifdef Q_CC_MSVC
- size_t requiredSize = 0;
- QByteArray buffer;
- getenv_s(&requiredSize, 0, 0, varName);
- if (requiredSize == 0)
- return buffer;
- buffer.resize(int(requiredSize));
- getenv_s(&requiredSize, buffer.data(), requiredSize, varName);
- // requiredSize includes the terminating null, which we don't want.
- Q_ASSERT(buffer.endsWith('\0'));
- buffer.chop(1);
- return buffer;
-#else
- return QByteArray(::getenv(varName));
-#endif
-}
-
-
-/*!
- \fn QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
- \fn QString qEnvironmentVariable(const char *varName)
-
- \relates <QtGlobal>
- \since 5.10
-
- These functions return the value of the environment variable, \a varName, as a
- QString. If no variable \a varName is found in the environment and \a defaultValue
- is provided, \a defaultValue is returned. Otherwise QString() is returned.
-
- The Qt environment manipulation functions are thread-safe, but this
- requires that the C library equivalent functions like getenv and putenv are
- not directly called.
-
- The following table describes how to choose between qgetenv() and
- qEnvironmentVariable():
- \table
- \header \li Condition \li Recommendation
- \row
- \li Variable contains file paths or user text
- \li qEnvironmentVariable()
- \row
- \li Windows-specific code
- \li qEnvironmentVariable()
- \row
- \li Unix-specific code, destination variable is not QString and/or is
- used to interface with non-Qt APIs
- \li qgetenv()
- \row
- \li Destination variable is a QString
- \li qEnvironmentVariable()
- \row
- \li Destination variable is a QByteArray or std::string
- \li qgetenv()
- \endtable
-
- \note on Unix systems, this function may produce data loss if the original
- string contains arbitrary binary data that cannot be decoded by the locale
- codec. Use qgetenv() instead for that case. On Windows, this function is
- lossless.
-
- \note the variable name \a varName must contain only US-ASCII characters.
-
- \sa qputenv(), qgetenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty()
-*/
-QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
-{
-#if defined(Q_OS_WIN)
- const auto locker = qt_scoped_lock(environmentMutex);
- QVarLengthArray<wchar_t, 32> wname(int(strlen(varName)) + 1);
- for (int i = 0; i < wname.size(); ++i) // wname.size() is correct: will copy terminating null
- wname[i] = uchar(varName[i]);
- size_t requiredSize = 0;
- QString buffer;
- _wgetenv_s(&requiredSize, 0, 0, wname.data());
- if (requiredSize == 0)
- return defaultValue;
- buffer.resize(int(requiredSize));
- _wgetenv_s(&requiredSize, reinterpret_cast<wchar_t *>(buffer.data()), requiredSize,
- wname.data());
- // requiredSize includes the terminating null, which we don't want.
- Q_ASSERT(buffer.endsWith(QLatin1Char('\0')));
- buffer.chop(1);
- return buffer;
-#else
- QByteArray value = qgetenv(varName);
- if (value.isNull())
- return defaultValue;
-// duplicated in qfile.h (QFile::decodeName)
-#if defined(Q_OS_DARWIN)
- return QString::fromUtf8(value).normalized(QString::NormalizationForm_C);
-#else // other Unix
- return QString::fromLocal8Bit(value);
-#endif
-#endif
-}
-
-QString qEnvironmentVariable(const char *varName)
+struct QInternal_CallBackTable
{
- return qEnvironmentVariable(varName, QString());
-}
-
-/*!
- \relates <QtGlobal>
- \since 5.1
-
- Returns whether the environment variable \a varName is empty.
-
- Equivalent to
- \snippet code/src_corelib_global_qglobal.cpp is-empty
- except that it's potentially much faster, and can't throw exceptions.
-
- \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
-*/
-bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
-{
- const auto locker = qt_scoped_lock(environmentMutex);
-#ifdef Q_CC_MSVC
- // we provide a buffer that can only hold the empty string, so
- // when the env.var isn't empty, we'll get an ERANGE error (buffer
- // too small):
- size_t dummy;
- char buffer = '\0';
- return getenv_s(&dummy, &buffer, 1, varName) != ERANGE;
-#else
- const char * const value = ::getenv(varName);
- return !value || !*value;
-#endif
-}
-
-/*!
- \relates <QtGlobal>
- \since 5.5
-
- Returns the numerical value of the environment variable \a varName.
- If \a ok is not null, sets \c{*ok} to \c true or \c false depending
- on the success of the conversion.
-
- Equivalent to
- \snippet code/src_corelib_global_qglobal.cpp to-int
- except that it's much faster, and can't throw exceptions.
-
- \note there's a limit on the length of the value, which is sufficient for
- all valid values of int, not counting leading zeroes or spaces. Values that
- are too long will either be truncated or this function will set \a ok to \c
- false.
-
- \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
-*/
-int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
-{
- static const int NumBinaryDigitsPerOctalDigit = 3;
- static const int MaxDigitsForOctalInt =
- (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit;
-
- const auto locker = qt_scoped_lock(environmentMutex);
-#ifdef Q_CC_MSVC
- // we provide a buffer that can hold any int value:
- char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-'
- size_t dummy;
- if (getenv_s(&dummy, buffer, sizeof buffer, varName) != 0) {
- if (ok)
- *ok = false;
- return 0;
- }
-#else
- const char * const buffer = ::getenv(varName);
- if (!buffer || strlen(buffer) > MaxDigitsForOctalInt + 2) {
- if (ok)
- *ok = false;
- return 0;
- }
-#endif
- bool ok_ = true;
- const char *endptr;
- const qlonglong value = qstrtoll(buffer, &endptr, 0, &ok_);
-
- // Keep the following checks in sync with QByteArray::toInt()
- if (!ok_) {
- if (ok)
- *ok = false;
- return 0;
- }
-
- if (*endptr != '\0') {
- while (ascii_isspace(*endptr))
- ++endptr;
- }
-
- if (*endptr != '\0') {
- // we stopped at a non-digit character after converting some digits
- if (ok)
- *ok = false;
- return 0;
- }
-
- if (int(value) != value) {
- if (ok)
- *ok = false;
- return 0;
- } else if (ok) {
- *ok = ok_;
- }
- return int(value);
-}
-
-/*!
- \relates <QtGlobal>
- \since 5.1
-
- Returns whether the environment variable \a varName is set.
-
- Equivalent to
- \snippet code/src_corelib_global_qglobal.cpp is-null
- except that it's potentially much faster, and can't throw exceptions.
-
- \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty()
-*/
-bool qEnvironmentVariableIsSet(const char *varName) noexcept
-{
- const auto locker = qt_scoped_lock(environmentMutex);
-#ifdef Q_CC_MSVC
- size_t requiredSize = 0;
- (void)getenv_s(&requiredSize, 0, 0, varName);
- return requiredSize != 0;
-#else
- return ::getenv(varName) != nullptr;
-#endif
-}
-
-/*!
- \relates <QtGlobal>
-
- This function sets the \a value of the environment variable named
- \a varName. It will create the variable if it does not exist. It
- returns 0 if the variable could not be set.
-
- Calling qputenv with an empty value removes the environment variable on
- Windows, and makes it set (but empty) on Unix. Prefer using qunsetenv()
- for fully portable behavior.
-
- \note qputenv() was introduced because putenv() from the standard
- C library was deprecated in VC2005 (and later versions). qputenv()
- uses the replacement function in VC, and calls the standard C
- library's implementation on all other platforms.
-
- \sa qgetenv(), qEnvironmentVariable()
-*/
-bool qputenv(const char *varName, const QByteArray& value)
-{
- const auto locker = qt_scoped_lock(environmentMutex);
-#if defined(Q_CC_MSVC)
- return _putenv_s(varName, value.constData()) == 0;
-#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU)
- // POSIX.1-2001 has setenv
- return setenv(varName, value.constData(), true) == 0;
-#else
- QByteArray buffer(varName);
- buffer += '=';
- buffer += value;
- char* envVar = qstrdup(buffer.constData());
- int result = putenv(envVar);
- if (result != 0) // error. we have to delete the string.
- delete[] envVar;
- return result == 0;
-#endif
-}
-
-/*!
- \relates <QtGlobal>
-
- This function deletes the variable \a varName from the environment.
-
- Returns \c true on success.
-
- \since 5.1
-
- \sa qputenv(), qgetenv(), qEnvironmentVariable()
-*/
-bool qunsetenv(const char *varName)
-{
- const auto locker = qt_scoped_lock(environmentMutex);
-#if defined(Q_CC_MSVC)
- return _putenv_s(varName, "") == 0;
-#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU)
- // POSIX.1-2001, BSD and Haiku have unsetenv
- return unsetenv(varName) == 0;
-#elif defined(Q_CC_MINGW)
- // On mingw, putenv("var=") removes "var" from the environment
- QByteArray buffer(varName);
- buffer += '=';
- return putenv(buffer.constData()) == 0;
-#else
- // Fallback to putenv("var=") which will insert an empty var into the
- // environment and leak it
- QByteArray buffer(varName);
- buffer += '=';
- char *envVar = qstrdup(buffer.constData());
- return putenv(envVar) == 0;
-#endif
-}
-
-/*!
- \macro forever
- \relates <QtGlobal>
-
- This macro is provided for convenience for writing infinite
- loops.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 31
-
- It is equivalent to \c{for (;;)}.
-
- If you're worried about namespace pollution, you can disable this
- macro by adding the following line to your \c .pro file:
-
- \snippet code/src_corelib_global_qglobal.cpp 32
-
- \sa Q_FOREVER
-*/
-
-/*!
- \macro Q_FOREVER
- \relates <QtGlobal>
-
- Same as \l{forever}.
-
- This macro is available even when \c no_keywords is specified
- using the \c .pro file's \c CONFIG variable.
-
- \sa foreach()
-*/
-
-/*!
- \macro foreach(variable, container)
- \relates <QtGlobal>
-
- This macro is used to implement Qt's \c foreach loop. The \a
- variable parameter is a variable name or variable definition; the
- \a container parameter is a Qt container whose value type
- corresponds to the type of the variable. See \l{The foreach
- Keyword} for details.
-
- If you're worried about namespace pollution, you can disable this
- macro by adding the following line to your \c .pro file:
-
- \snippet code/src_corelib_global_qglobal.cpp 33
-
- \note Since Qt 5.7, the use of this macro is discouraged. It will
- be removed in a future version of Qt. Please use C++11 range-for,
- possibly with qAsConst(), as needed.
-
- \sa qAsConst()
-*/
-
-/*!
- \macro Q_FOREACH(variable, container)
- \relates <QtGlobal>
-
- Same as foreach(\a variable, \a container).
-
- This macro is available even when \c no_keywords is specified
- using the \c .pro file's \c CONFIG variable.
-
- \note Since Qt 5.7, the use of this macro is discouraged. It will
- be removed in a future version of Qt. Please use C++11 range-for,
- possibly with qAsConst(), as needed.
-
- \sa qAsConst()
-*/
-
-/*!
- \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t)
- \relates <QtGlobal>
- \since 5.7
-
- Returns \a t cast to \c{const T}.
-
- This function is a Qt implementation of C++17's std::as_const(),
- a cast function like std::move(). But while std::move() turns
- lvalues into rvalues, this function turns non-const lvalues into
- const lvalues. Like std::as_const(), it doesn't work on rvalues,
- because it cannot be efficiently implemented for rvalues without
- leaving dangling references.
-
- Its main use in Qt is to prevent implicitly-shared Qt containers
- from detaching:
- \snippet code/src_corelib_global_qglobal.cpp as-const-0
-
- Of course, in this case, you could (and probably should) have declared
- \c s as \c const in the first place:
- \snippet code/src_corelib_global_qglobal.cpp as-const-1
- but often that is not easily possible.
-
- It is important to note that qAsConst() does not copy its argument,
- it just performs a \c{const_cast<const T&>(t)}. This is also the reason
- why it is designed to fail for rvalues: The returned reference would go
- stale too soon. So while this works (but detaches the returned object):
- \snippet code/src_corelib_global_qglobal.cpp as-const-2
-
- this would not:
- \snippet code/src_corelib_global_qglobal.cpp as-const-3
-
- To prevent this construct from compiling (and failing at runtime), qAsConst() has
- a second, deleted, overload which binds to rvalues.
-*/
-
-/*!
- \fn template <typename T> void qAsConst(const T &&t)
- \relates <QtGlobal>
- \since 5.7
- \overload
-
- This overload is deleted to prevent a dangling reference in code like
- \snippet code/src_corelib_global_qglobal.cpp as-const-4
-*/
-
-/*!
- \fn template <typename T, typename U = T> T qExchange(T &obj, U &&newValue)
- \relates <QtGlobal>
- \since 5.14
-
- Replaces the value of \a obj with \a newValue and returns the old value of \a obj.
-
- This is Qt's implementation of std::exchange(). It differs from std::exchange()
- only in that it is \c constexpr already in C++14, and available on all supported
- compilers.
-
- Here is how to use qExchange() to implement move constructors:
- \code
- MyClass(MyClass &&other)
- : m_pointer{qExchange(other.m_pointer, nullptr)},
- m_int{qExchange(other.m_int, 0)},
- m_vector{std::move(other.m_vector)},
- ...
- \endcode
-
- For members of class type, we can use std::move(), as their move-constructor will
- do the right thing. But for scalar types such as raw pointers or integer type, move
- is the same as copy, which, particularly for pointers, is not what we expect. So, we
- cannot use std::move() for such types, but we can use std::exchange()/qExchange() to
- make sure the source object's member is already reset by the time we get to the
- initialization of our next data member, which might come in handy if the constructor
- exits with an exception.
-
- Here is how to use qExchange() to write a loop that consumes the collection it
- iterates over:
- \code
- for (auto &e : qExchange(collection, {})
- doSomethingWith(e);
- \endcode
-
- Which is equivalent to the following, much more verbose code:
- \code
- {
- auto tmp = std::move(collection);
- collection = {}; // or collection.clear()
- for (auto &e : tmp)
- doSomethingWith(e);
- } // destroys 'tmp'
- \endcode
-
- This is perfectly safe, as the for-loop keeps the result of qExchange() alive for as
- long as the loop runs, saving the declaration of a temporary variable. Be aware, though,
- that qExchange() returns a non-const object, so Qt containers may detach.
-*/
-
-/*!
- \macro QT_TR_NOOP(sourceText)
- \relates <QtGlobal>
-
- Marks the UTF-8 encoded string literal \a sourceText for delayed
- translation in the current context (class).
-
- The macro tells lupdate to collect the string, and expands to
- \a sourceText itself.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 34
-
- The macro QT_TR_NOOP_UTF8() is identical and obsolete; this applies
- to all other _UTF8 macros as well.
-
- \sa QT_TRANSLATE_NOOP(), {Internationalization with Qt}
-*/
-
-/*!
- \macro QT_TRANSLATE_NOOP(context, sourceText)
- \relates <QtGlobal>
-
- Marks the UTF-8 encoded string literal \a sourceText for delayed
- translation in the given \a context. The \a context is typically
- a class name and also needs to be specified as a string literal.
-
- The macro tells lupdate to collect the string, and expands to
- \a sourceText itself.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 35
-
- \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP3(), {Internationalization with Qt}
-*/
-
-/*!
- \macro QT_TRANSLATE_NOOP3(context, sourceText, disambiguation)
- \relates <QtGlobal>
- \since 4.4
-
- Marks the UTF-8 encoded string literal \a sourceText for delayed
- translation in the given \a context with the given \a disambiguation.
- The \a context is typically a class and also needs to be specified
- as a string literal. The string literal \a disambiguation should be
- a short semantic tag to tell apart otherwise identical strings.
-
- The macro tells lupdate to collect the string, and expands to an
- anonymous struct of the two string literals passed as \a sourceText
- and \a disambiguation.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 36
-
- \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP(), {Internationalization with Qt}
-*/
-
-/*!
- \macro QT_TR_N_NOOP(sourceText)
- \relates <QtGlobal>
- \since 5.12
-
- Marks the UTF-8 encoded string literal \a sourceText for numerator
- dependent delayed translation in the current context (class).
-
- The macro tells lupdate to collect the string, and expands to
- \a sourceText itself.
-
- The macro expands to \a sourceText.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qttrnnoop
-
- \sa QT_TR_NOOP, {Internationalization with Qt}
-*/
-
-/*!
- \macro QT_TRANSLATE_N_NOOP(context, sourceText)
- \relates <QtGlobal>
- \since 5.12
-
- Marks the UTF-8 encoded string literal \a sourceText for numerator
- dependent delayed translation in the given \a context.
- The \a context is typically a class name and also needs to be
- specified as a string literal.
-
- The macro tells lupdate to collect the string, and expands to
- \a sourceText itself.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qttranslatennoop
-
- \sa QT_TRANSLATE_NOOP(), QT_TRANSLATE_N_NOOP3(),
- {Internationalization with Qt}
-*/
-
-/*!
- \macro QT_TRANSLATE_N_NOOP3(context, sourceText, comment)
- \relates <QtGlobal>
- \since 5.12
-
- Marks the UTF-8 encoded string literal \a sourceText for numerator
- dependent delayed translation in the given \a context with the given
- \a comment.
- The \a context is typically a class and also needs to be specified
- as a string literal. The string literal \a comment should be
- a short semantic tag to tell apart otherwise identical strings.
-
- The macro tells lupdate to collect the string, and expands to an
- anonymous struct of the two string literals passed as \a sourceText
- and \a comment.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qttranslatennoop3
-
- \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP(), QT_TRANSLATE_NOOP3(),
- {Internationalization with Qt}
-*/
-
-/*!
- \fn QString qtTrId(const char *id, int n = -1)
- \relates <QtGlobal>
- \reentrant
- \since 4.6
-
- \brief The qtTrId function finds and returns a translated string.
-
- Returns a translated string identified by \a id.
- If no matching string is found, the id itself is returned. This
- should not happen under normal conditions.
-
- If \a n >= 0, all occurrences of \c %n in the resulting string
- are replaced with a decimal representation of \a n. In addition,
- depending on \a n's value, the translation text may vary.
-
- Meta data and comments can be passed as documented for QObject::tr().
- In addition, it is possible to supply a source string template like that:
-
- \tt{//% <C string>}
-
- or
-
- \tt{\\begincomment% <C string> \\endcomment}
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qttrid
-
- Creating QM files suitable for use with this function requires passing
- the \c -idbased option to the \c lrelease tool.
-
- \warning This method is reentrant only if all translators are
- installed \e before calling this method. Installing or removing
- translators while performing translations is not supported. Doing
- so will probably result in crashes or other undesirable behavior.
-
- \sa QObject::tr(), QCoreApplication::translate(), {Internationalization with Qt}
-*/
-
-/*!
- \macro QT_TRID_NOOP(id)
- \relates <QtGlobal>
- \since 4.6
-
- \brief The QT_TRID_NOOP macro marks an id for dynamic translation.
-
- The only purpose of this macro is to provide an anchor for attaching
- meta data like to qtTrId().
-
- The macro expands to \a id.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qttrid_noop
-
- \sa qtTrId(), {Internationalization with Qt}
-*/
-
-/*!
- \macro Q_LIKELY(expr)
- \relates <QtGlobal>
- \since 4.8
-
- \brief Hints to the compiler that the enclosed condition, \a expr, is
- likely to evaluate to \c true.
-
- Use of this macro can help the compiler to optimize the code.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qlikely
-
- \sa Q_UNLIKELY()
-*/
-
-/*!
- \macro Q_UNLIKELY(expr)
- \relates <QtGlobal>
- \since 4.8
-
- \brief Hints to the compiler that the enclosed condition, \a expr, is
- likely to evaluate to \c false.
-
- Use of this macro can help the compiler to optimize the code.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qunlikely
-
- \sa Q_LIKELY()
-*/
-
-/*!
- \macro QT_POINTER_SIZE
- \relates <QtGlobal>
-
- Expands to the size of a pointer in bytes (4 or 8). This is
- equivalent to \c sizeof(void *) but can be used in a preprocessor
- directive.
-*/
-
-/*!
- \macro const char *qPrintable(const QString &str)
- \relates <QtGlobal>
-
- Returns \a str as a \c{const char *}. This is equivalent to
- \a{str}.toLocal8Bit().constData().
-
- The char pointer will be invalid after the statement in which
- qPrintable() is used. This is because the array returned by
- QString::toLocal8Bit() will fall out of scope.
-
- \note qDebug(), qInfo(), qWarning(), qCritical(), qFatal() expect
- %s arguments to be UTF-8 encoded, while qPrintable() converts to
- local 8-bit encoding. Therefore qUtf8Printable() should be used
- for logging strings instead of qPrintable().
-
- \sa qUtf8Printable()
-*/
-
-/*!
- \macro const char *qUtf8Printable(const QString &str)
- \relates <QtGlobal>
- \since 5.4
-
- Returns \a str as a \c{const char *}. This is equivalent to
- \a{str}.toUtf8().constData().
-
- The char pointer will be invalid after the statement in which
- qUtf8Printable() is used. This is because the array returned by
- QString::toUtf8() will fall out of scope.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 37
-
- \sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
-*/
-
-/*!
- \macro const wchar_t *qUtf16Printable(const QString &str)
- \relates <QtGlobal>
- \since 5.7
-
- Returns \a str as a \c{const ushort *}, but cast to a \c{const wchar_t *}
- to avoid warnings. This is equivalent to \a{str}.utf16() plus some casting.
-
- The only useful thing you can do with the return value of this macro is to
- pass it to QString::asprintf() for use in a \c{%ls} conversion. In particular,
- the return value is \e{not} a valid \c{const wchar_t*}!
-
- In general, the pointer will be invalid after the statement in which
- qUtf16Printable() is used. This is because the pointer may have been
- obtained from a temporary expression, which will fall out of scope.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qUtf16Printable
-
- \sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
-*/
-
-/*!
- \macro Q_DECLARE_TYPEINFO(Type, Flags)
- \relates <QtGlobal>
-
- You can use this macro to specify information about a custom type
- \a Type. With accurate type information, Qt's \l{Container Classes}
- {generic containers} can choose appropriate storage methods and
- algorithms.
-
- \a Flags can be one of the following:
-
- \list
- \li \c Q_PRIMITIVE_TYPE specifies that \a Type is a POD (plain old
- data) type with no constructor or destructor, or else a type where
- every bit pattern is a valid object and memcpy() creates a valid
- independent copy of the object.
- \li \c Q_MOVABLE_TYPE specifies that \a Type has a constructor
- and/or a destructor but can be moved in memory using \c
- memcpy(). Note: despite the name, this has nothing to do with move
- constructors or C++ move semantics.
- \li \c Q_COMPLEX_TYPE (the default) specifies that \a Type has
- constructors and/or a destructor and that it may not be moved
- in memory.
- \endlist
-
- Example of a "primitive" type:
-
- \snippet code/src_corelib_global_qglobal.cpp 38
-
- An example of a non-POD "primitive" type is QUuid: Even though
- QUuid has constructors (and therefore isn't POD), every bit
- pattern still represents a valid object, and memcpy() can be used
- to create a valid independent copy of a QUuid object.
-
- Example of a movable type:
-
- \snippet code/src_corelib_global_qglobal.cpp 39
-
- Qt will try to detect the class of a type using std::is_trivial or
- std::is_trivially_copyable. Use this macro to tune the behavior.
- For instance many types would be candidates for Q_MOVABLE_TYPE despite
- not being trivially-copyable. For binary compatibility reasons, QList
- optimizations are only enabled if there is an explicit
- Q_DECLARE_TYPEINFO even for trivially-copyable types.
-*/
-
-/*!
- \macro Q_UNUSED(name)
- \relates <QtGlobal>
-
- Indicates to the compiler that the parameter with the specified
- \a name is not used in the body of a function. This can be used to
- suppress compiler warnings while allowing functions to be defined
- with meaningful parameter names in their signatures.
-*/
-
-struct QInternal_CallBackTable {
QList<QList<qInternalCallback>> callbacks;
};
@@ -4287,7 +145,7 @@ bool QInternal::unregisterCallback(Callback cb, qInternalCallback callback)
if (unsigned(cb) < unsigned(QInternal::LastCallback)) {
if (global_callback_table.exists()) {
QInternal_CallBackTable *cbt = global_callback_table();
- return (bool) cbt->callbacks[cb].removeAll(callback);
+ return cbt->callbacks[cb].removeAll(callback) > 0;
}
}
return false;
@@ -4304,7 +162,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
if (cbt && cb < cbt->callbacks.size()) {
QList<qInternalCallback> callbacks = cbt->callbacks[cb];
bool ret = false;
- for (int i=0; i<callbacks.size(); ++i)
+ for (int i = 0; i < callbacks.size(); ++i)
ret |= (callbacks.at(i))(parameters);
return ret;
}
@@ -4312,54 +170,16 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
}
/*!
- \macro Q_BYTE_ORDER
+ \macro QT_NO_KEYWORDS
\relates <QtGlobal>
- This macro can be used to determine the byte order your system
- uses for storing data in memory. i.e., whether your system is
- little-endian or big-endian. It is set by Qt to one of the macros
- Q_LITTLE_ENDIAN or Q_BIG_ENDIAN. You normally won't need to worry
- about endian-ness, but you might, for example if you need to know
- which byte of an integer or UTF-16 character is stored in the
- lowest address. Endian-ness is important in networking, where
- computers with different values for Q_BYTE_ORDER must pass data
- back and forth.
+ Define this macro to disable the Qt-specific keywords that are usually enabled,
+ such as \c signals and \c slots. Use \c Q_SIGNALS and \c Q_SLOTS instead.
- Use this macro as in the following examples.
+ Libraries should define this macro to make sure that they don't use the generic
+ keywords without the \c Q_ prefix in their public headers.
- \snippet code/src_corelib_global_qglobal.cpp 40
-
- \sa Q_BIG_ENDIAN, Q_LITTLE_ENDIAN
-*/
-
-/*!
- \macro Q_LITTLE_ENDIAN
- \relates <QtGlobal>
-
- This macro represents a value you can compare to the macro
- Q_BYTE_ORDER to determine the endian-ness of your system. In a
- little-endian system, the least significant byte is stored at the
- lowest address. The other bytes follow in increasing order of
- significance.
-
- \snippet code/src_corelib_global_qglobal.cpp 41
-
- \sa Q_BYTE_ORDER, Q_BIG_ENDIAN
-*/
-
-/*!
- \macro Q_BIG_ENDIAN
- \relates <QtGlobal>
-
- This macro represents a value you can compare to the macro
- Q_BYTE_ORDER to determine the endian-ness of your system. In a
- big-endian system, the most significant byte is stored at the
- lowest address. The other bytes follow in decreasing order of
- significance.
-
- \snippet code/src_corelib_global_qglobal.cpp 42
-
- \sa Q_BYTE_ORDER, Q_LITTLE_ENDIAN
+ \sa QT_NO_FOREACH
*/
/*!
@@ -4492,299 +312,9 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
*/
/*!
- \fn bool qFuzzyCompare(double p1, double p2)
- \relates <QtGlobal>
- \since 4.4
- \threadsafe
-
- Compares the floating point value \a p1 and \a p2 and
- returns \c true if they are considered equal, otherwise \c false.
-
- Note that comparing values where either \a p1 or \a p2 is 0.0 will not work,
- nor does comparing values where one of the values is NaN or infinity.
- If one of the values is always 0.0, use qFuzzyIsNull instead. If one of the
- values is likely to be 0.0, one solution is to add 1.0 to both values.
-
- \snippet code/src_corelib_global_qglobal.cpp 46
-
- The two numbers are compared in a relative way, where the
- exactness is stronger the smaller the numbers are.
- */
-
-/*!
- \fn bool qFuzzyCompare(float p1, float p2)
- \relates <QtGlobal>
- \since 4.4
- \threadsafe
-
- Compares the floating point value \a p1 and \a p2 and
- returns \c true if they are considered equal, otherwise \c false.
-
- The two numbers are compared in a relative way, where the
- exactness is stronger the smaller the numbers are.
- */
-
-/*!
- \fn bool qFuzzyIsNull(double d)
- \relates <QtGlobal>
- \since 4.4
- \threadsafe
-
- Returns true if the absolute value of \a d is within 0.000000000001 of 0.0.
-*/
-
-/*!
- \fn bool qFuzzyIsNull(float f)
- \relates <QtGlobal>
- \since 4.4
- \threadsafe
-
- Returns true if the absolute value of \a f is within 0.00001f of 0.0.
-*/
-
-/*!
- \macro QT_REQUIRE_VERSION(int argc, char **argv, const char *version)
- \relates <QtGlobal>
-
- This macro can be used to ensure that the application is run
- against a recent enough version of Qt. This is especially useful
- if your application depends on a specific bug fix introduced in a
- bug-fix release (e.g., 4.0.2).
-
- The \a argc and \a argv parameters are the \c main() function's
- \c argc and \c argv parameters. The \a version parameter is a
- string literal that specifies which version of Qt the application
- requires (e.g., "4.0.2").
-
- Example:
-
- \snippet code/src_gui_dialogs_qmessagebox.cpp 4
-*/
-
-/*!
- \macro Q_DECL_EXPORT
- \relates <QtGlobal>
-
- This macro marks a symbol for shared library export (see
- \l{sharedlibrary.html}{Creating Shared Libraries}).
-
- \sa Q_DECL_IMPORT
-*/
-
-/*!
- \macro Q_DECL_IMPORT
- \relates <QtGlobal>
-
- This macro declares a symbol to be an import from a shared library (see
- \l{sharedlibrary.html}{Creating Shared Libraries}).
-
- \sa Q_DECL_EXPORT
-*/
-
-/*!
- \macro Q_DECL_CONSTEXPR
- \relates <QtGlobal>
-
- This macro can be used to declare variable that should be constructed at compile-time,
- or an inline function that can be computed at compile-time.
-
- It expands to "constexpr" if your compiler supports that C++11 keyword, or to nothing
- otherwise.
-
- \sa Q_DECL_RELAXED_CONSTEXPR
-*/
-
-/*!
- \macro Q_DECL_RELAXED_CONSTEXPR
- \relates <QtGlobal>
-
- This macro can be used to declare an inline function that can be computed
- at compile-time according to the relaxed rules from C++14.
-
- It expands to "constexpr" if your compiler supports C++14 relaxed constant
- expressions, or to nothing otherwise.
-
- \sa Q_DECL_CONSTEXPR
-*/
-
-/*!
- \macro qDebug(const char *message, ...)
- \relates <QtGlobal>
- \threadsafe
-
- Calls the message handler with the debug message \a message. If no
- message handler has been installed, the message is printed to
- stderr. Under Windows the message is sent to the console, if it is a
- console application; otherwise, it is sent to the debugger. On QNX, the
- message is sent to slogger2. This function does nothing if \c QT_NO_DEBUG_OUTPUT
- was defined during compilation.
-
- If you pass the function a format string and a list of arguments,
- it works in similar way to the C printf() function. The format
- should be a Latin-1 string.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp 24
-
- If you include \c <QtDebug>, a more convenient syntax is also
- available:
-
- \snippet code/src_corelib_global_qglobal.cpp 25
-
- With this syntax, the function returns a QDebug object that is
- configured to use the QtDebugMsg message type. It automatically
- puts a single space between each item, and outputs a newline at
- the end. It supports many C++ and Qt types.
-
- To suppress the output at run-time, install your own message handler
- with qInstallMessageHandler().
-
- \sa qInfo(), qWarning(), qCritical(), qFatal(), qInstallMessageHandler(),
- {Debugging Techniques}
-*/
-
-/*!
- \macro qInfo(const char *message, ...)
- \relates <QtGlobal>
- \threadsafe
- \since 5.5
-
- Calls the message handler with the informational message \a message. If no
- message handler has been installed, the message is printed to
- stderr. Under Windows, the message is sent to the console, if it is a
- console application; otherwise, it is sent to the debugger. On QNX the
- message is sent to slogger2. This function does nothing if \c QT_NO_INFO_OUTPUT
- was defined during compilation.
-
- If you pass the function a format string and a list of arguments,
- it works in similar way to the C printf() function. The format
- should be a Latin-1 string.
-
- Example:
-
- \snippet code/src_corelib_global_qglobal.cpp qInfo_printf
-
- If you include \c <QtDebug>, a more convenient syntax is also
- available:
-
- \snippet code/src_corelib_global_qglobal.cpp qInfo_stream
-
- With this syntax, the function returns a QDebug object that is
- configured to use the QtInfoMsg message type. It automatically
- puts a single space between each item, and outputs a newline at
- the end. It supports many C++ and Qt types.
-
- To suppress the output at run-time, install your own message handler
- with qInstallMessageHandler().
-
- \sa qDebug(), qWarning(), qCritical(), qFatal(), qInstallMessageHandler(),
- {Debugging Techniques}
-*/
-
-/*!
- \macro qWarning(const char *message, ...)
- \relates <QtGlobal>
- \threadsafe
-
- Calls the message handler with the warning message \a message. If no
- message handler has been installed, the message is printed to
- stderr. Under Windows, the message is sent to the debugger.
- On QNX the message is sent to slogger2. This
- function does nothing if \c QT_NO_WARNING_OUTPUT was defined
- during compilation; it exits if at the nth warning corresponding to the
- counter in environment variable \c QT_FATAL_WARNINGS. That is, if the
- environment variable contains the value 1, it will exit on the 1st message;
- if it contains the value 10, it will exit on the 10th message. Any
- non-numeric value is equivalent to 1.
-
- This function takes a format string and a list of arguments,
- similar to the C printf() function. The format should be a Latin-1
- string.
-
- Example:
- \snippet code/src_corelib_global_qglobal.cpp 26
-
- If you include <QtDebug>, a more convenient syntax is
- also available:
-
- \snippet code/src_corelib_global_qglobal.cpp 27
-
- This syntax inserts a space between each item, and
- appends a newline at the end.
-
- To suppress the output at runtime, install your own message handler
- with qInstallMessageHandler().
-
- \sa qDebug(), qInfo(), qCritical(), qFatal(), qInstallMessageHandler(),
- {Debugging Techniques}
-*/
-
-/*!
- \macro qCritical(const char *message, ...)
- \relates <QtGlobal>
- \threadsafe
-
- Calls the message handler with the critical message \a message. If no
- message handler has been installed, the message is printed to
- stderr. Under Windows, the message is sent to the debugger.
- On QNX the message is sent to slogger2.
-
- It exits if the environment variable QT_FATAL_CRITICALS is not empty.
-
- This function takes a format string and a list of arguments,
- similar to the C printf() function. The format should be a Latin-1
- string.
-
- Example:
- \snippet code/src_corelib_global_qglobal.cpp 28
-
- If you include <QtDebug>, a more convenient syntax is
- also available:
-
- \snippet code/src_corelib_global_qglobal.cpp 29
-
- A space is inserted between the items, and a newline is
- appended at the end.
-
- To suppress the output at runtime, install your own message handler
- with qInstallMessageHandler().
-
- \sa qDebug(), qInfo(), qWarning(), qFatal(), qInstallMessageHandler(),
- {Debugging Techniques}
-*/
-
-/*!
- \macro qFatal(const char *message, ...)
- \relates <QtGlobal>
-
- Calls the message handler with the fatal message \a message. If no
- message handler has been installed, the message is printed to
- stderr. Under Windows, the message is sent to the debugger.
- On QNX the message is sent to slogger2.
-
- If you are using the \b{default message handler} this function will
- abort to create a core dump. On Windows, for debug builds,
- this function will report a _CRT_ERROR enabling you to connect a debugger
- to the application.
-
- This function takes a format string and a list of arguments,
- similar to the C printf() function.
-
- Example:
- \snippet code/src_corelib_global_qglobal.cpp 30
-
- To suppress the output at runtime, install your own message handler
- with qInstallMessageHandler().
-
- \sa qDebug(), qInfo(), qWarning(), qCritical(), qInstallMessageHandler(),
- {Debugging Techniques}
-*/
-
-/*!
\macro qMove(x)
\relates <QtGlobal>
- \obsolete
+ \deprecated
Use \c std::move instead.
@@ -4794,172 +324,53 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
*/
/*!
- \macro Q_DECL_NOTHROW
- \relates <QtGlobal>
- \since 5.0
-
- This macro marks a function as never throwing, under no
- circumstances. If the function does nevertheless throw, the
- behaviour is undefined.
-
- The macro expands to either "throw()", if that has some benefit on
- the compiler, or to C++11 noexcept, if available, or to nothing
- otherwise.
-
- If you need C++11 noexcept semantics, don't use this macro, use
- Q_DECL_NOEXCEPT/Q_DECL_NOEXCEPT_EXPR instead.
-
- \sa Q_DECL_NOEXCEPT, Q_DECL_NOEXCEPT_EXPR()
-*/
-
-/*!
- \macro QT_TERMINATE_ON_EXCEPTION(expr)
- \relates <QtGlobal>
- \internal
-
- In general, use of the Q_DECL_NOEXCEPT macro is preferred over
- Q_DECL_NOTHROW, because it exhibits well-defined behavior and
- supports the more powerful Q_DECL_NOEXCEPT_EXPR variant. However,
- use of Q_DECL_NOTHROW has the advantage that Windows builds
- benefit on a wide range or compiler versions that do not yet
- support the C++11 noexcept feature.
-
- It may therefore be beneficial to use Q_DECL_NOTHROW and emulate
- the C++11 behavior manually with an embedded try/catch.
-
- Qt provides the QT_TERMINATE_ON_EXCEPTION(expr) macro for this
- purpose. It either expands to \c expr (if Qt is compiled without
- exception support or the compiler supports C++11 noexcept
- semantics) or to
- \snippet code/src_corelib_global_qglobal.cpp qterminate
- otherwise.
-
- Since this macro expands to just \c expr if the compiler supports
- C++11 noexcept, expecting the compiler to take over responsibility
- of calling std::terminate() in that case, it should not be used
- outside Q_DECL_NOTHROW functions.
-
- \sa Q_DECL_NOEXCEPT, Q_DECL_NOTHROW, qTerminate()
-*/
-
-/*!
- \macro Q_DECL_NOEXCEPT
- \relates <QtGlobal>
- \since 5.0
-
- This macro marks a function as never throwing. If the function
- does nevertheless throw, the behaviour is defined:
- std::terminate() is called.
-
- The macro expands to C++11 noexcept, if available, or to nothing
- otherwise.
-
- If you need the operator version of C++11 noexcept, use
- Q_DECL_NOEXCEPT_EXPR(x).
-
- If you don't need C++11 noexcept semantics, e.g. because your
- function can't possibly throw, don't use this macro, use
- Q_DECL_NOTHROW instead.
-
- \sa Q_DECL_NOTHROW, Q_DECL_NOEXCEPT_EXPR()
-*/
-
-/*!
- \macro Q_DECL_NOEXCEPT_EXPR(x)
- \relates <QtGlobal>
- \since 5.0
-
- This macro marks a function as non-throwing if \a x is \c true. If
- the function does nevertheless throw, the behaviour is defined:
- std::terminate() is called.
-
- The macro expands to C++11 noexcept(x), if available, or to
- nothing otherwise.
-
- If you need the always-true version of C++11 noexcept, use
- Q_DECL_NOEXCEPT.
-
- If you don't need C++11 noexcept semantics, e.g. because your
- function can't possibly throw, don't use this macro, use
- Q_DECL_NOTHROW instead.
-
- \sa Q_DECL_NOTHROW, Q_DECL_NOEXCEPT
-*/
-
-/*!
- \macro Q_DECL_OVERRIDE
- \since 5.0
- \obsolete
+ \macro QT_ENABLE_STRICT_MODE_UP_TO
\relates <QtGlobal>
+ \since 6.8
- This macro can be used to declare an overriding virtual
- function. Use of this markup will allow the compiler to generate
- an error if the overriding virtual function does not in fact
- override anything.
+ Defining this macro will disable a number of Qt APIs that are
+ deemed suboptimal or dangerous.
- It expands to "override".
+ This macro's value must be set to a Qt version, using
+ \l{QT_VERSION_CHECK}'s encoding. For instance, in order to set it
+ to Qt 6.6, define \c{QT_ENABLE_STRICT_MODE_UP_TO=0x060600}.
+ This will disable only the APIs introduced in versions up to (and
+ including) the specified Qt version.
- The macro goes at the end of the function, usually after the
- \c{const}, if any:
- \snippet code/src_corelib_global_qglobal.cpp qdecloverride
+ If the \l QT_DISABLE_DEPRECATED_UP_TO macro is \e not defined,
+ then QT_ENABLE_STRICT_MODE_UP_TO will define it as well,
+ to the same value.
- \sa Q_DECL_FINAL
-*/
+ This macro should always be set to the minimum Qt version that
+ your project wants to support.
-/*!
- \macro Q_DECL_FINAL
- \since 5.0
- \obsolete
- \relates <QtGlobal>
-
- This macro can be used to declare an overriding virtual or a class
- as "final", with Java semantics. Further-derived classes can then
- no longer override this virtual function, or inherit from this
- class, respectively.
-
- It expands to "final".
-
- The macro goes at the end of the function, usually after the
- \c{const}, if any:
- \snippet code/src_corelib_global_qglobal.cpp qdeclfinal-1
-
- For classes, it goes in front of the \c{:} in the class
- definition, if any:
- \snippet code/src_corelib_global_qglobal.cpp qdeclfinal-2
-
- \sa Q_DECL_OVERRIDE
-*/
+ The APIs disabled by this macro are listed in the table below,
+ together with the minimum value to use in order to disable them.
-/*!
- \macro Q_FORWARD_DECLARE_OBJC_CLASS(classname)
- \since 5.2
- \relates <QtGlobal>
-
- Forward-declares an Objective-C \a classname in a manner such that it can be
- compiled as either Objective-C or C++.
-
- This is primarily intended for use in header files that may be included by
- both Objective-C and C++ source files.
-*/
+ \table
+ \header \li Version \li Disabled APIs
+ \row \li 6.0.0 \li \l{foreach-keyword}{foreach} (see \l{QT_NO_FOREACH})
+ \row \li 6.0.0 \li QString constructors from \c{const char *} (see \l{QT_NO_CAST_FROM_ASCII})
+ \row \li 6.0.0 \li QString conversions towards \c{const char *} / QByteArray (see \l{QT_NO_CAST_TO_ASCII})
+ \row \li 6.0.0 \li QByteArray implicit conversions towards \c{const char *} (see \l{QT_NO_CAST_FROM_BYTEARRAY})
+ \row \li 6.0.0 \li QUrl implicit conversions from QString (see \l{QT_NO_URL_CAST_FROM_STRING})
+ \row \li 6.0.0 \li Allowing narrowing conversions in signal-slot connections (see \l{QT_NO_NARROWING_CONVERSIONS_IN_CONNECT})
+ \row \li 6.0.0 \li Java-style iterators for Qt containers
+ \row \li 6.6.0 \li The qExchange() function (see \l{QT_NO_QEXCHANGE})
+ \row \li 6.7.0 \li Overloads of QObject::connect that do not take a context object (see \l{QT_NO_CONTEXTLESS_CONNECT})
+ \row \li 6.8.0 \li The qAsConst() function (see \l{QT_NO_QASCONST})
+ \row \li 6.8.0 \li File-related I/O classes have their \c{open()} functions marked \c{[[nodiscard]]} (see \l{QT_USE_NODISCARD_FILE_OPEN})
+ \endtable
-/*!
- \macro Q_FORWARD_DECLARE_CF_TYPE(type)
- \since 5.2
- \relates <QtGlobal>
+ Moreover, individual APIs may also get disabled as part of the
+ setting of QT_DISABLE_DEPRECATED_UP_TO. Please refer to each class'
+ documentation for more details.
- Forward-declares a Core Foundation \a type. This includes the actual
- type and the ref type. For example, Q_FORWARD_DECLARE_CF_TYPE(CFString)
- declares __CFString and CFStringRef.
+ \sa QT_DISABLE_DEPRECATED_UP_TO, QT_NO_KEYWORDS, QT_VERSION_CHECK
*/
-/*!
- \macro Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type)
- \since 5.2
- \relates <QtGlobal>
-
- Forward-declares a mutable Core Foundation \a type. This includes the actual
- type and the ref type. For example, Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(CFMutableString)
- declares __CFMutableString and CFMutableStringRef.
-*/
+namespace QtPrivate {
+Q_LOGGING_CATEGORY(lcNativeInterface, "qt.nativeinterface")
+}
QT_END_NAMESPACE
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 08e631568d..2d70e82370 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1,1298 +1,46 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGLOBAL_H
#define QGLOBAL_H
+#if 0
+#pragma qt_class(QtGlobal)
+#endif
+
#ifdef __cplusplus
# include <type_traits>
# include <cstddef>
# include <utility>
+# include <cstdint>
#endif
#ifndef __ASSEMBLER__
# include <assert.h>
+# include <stdbool.h>
# include <stddef.h>
#endif
-/*
- QT_VERSION is (major << 16) + (minor << 8) + patch.
-*/
-#define QT_VERSION QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH)
-/*
- can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
-*/
-#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+#include <QtCore/qtversionchecks.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
-#ifdef QT_BOOTSTRAPPED
-#include <QtCore/qconfig-bootstrapped.h>
-#else
-#include <QtCore/qconfig.h>
-#include <QtCore/qtcore-config.h>
-#endif
-
-// The QT_SUPPORTS macro is deprecated. Don't use it in new code.
-// Instead, use QT_CONFIG(feature)
-// ### Qt6: remove macro
-#ifdef _MSC_VER
-# define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE)
-#else
-# define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
-#endif
-
-/*
- The QT_CONFIG macro implements a safe compile time check for features of Qt.
- Features can be in three states:
- 0 or undefined: This will lead to a compile error when testing for it
- -1: The feature is not available
- 1: The feature is available
-*/
-#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)
-#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.")
-
-// ### Clean those up, once all code is adjusted
-#define QT6_VIRTUAL virtual
-#define QT6_NOT_VIRTUAL
-
-/* These two macros makes it possible to turn the builtin line expander into a
- * string literal. */
-#define QT_STRINGIFY2(x) #x
-#define QT_STRINGIFY(x) QT_STRINGIFY2(x)
+#include <QtCore/qtpreprocessorsupport.h>
#include <QtCore/qsystemdetection.h>
#include <QtCore/qprocessordetection.h>
#include <QtCore/qcompilerdetection.h>
-#if defined (__ELF__)
-# define Q_OF_ELF
-#endif
-#if defined (__MACH__) && defined (__APPLE__)
-# define Q_OF_MACH_O
-#endif
-
-/*
- Avoid "unused parameter" warnings
-*/
-#define Q_UNUSED(x) (void)x;
-
-#if defined(__cplusplus)
-// Don't use these in C++ mode, use static_assert directly.
-// These are here only to keep old code compiling.
-# define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition)
-# define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
-#elif defined(Q_COMPILER_STATIC_ASSERT)
-// C11 mode - using the _S version in case <assert.h> doesn't do the right thing
-# define Q_STATIC_ASSERT(Condition) _Static_assert(!!(Condition), #Condition)
-# define Q_STATIC_ASSERT_X(Condition, Message) _Static_assert(!!(Condition), Message)
-#else
-// C89 & C99 version
-# define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
-# define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
-# ifdef __COUNTER__
-# define Q_STATIC_ASSERT(Condition) \
- typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) [(Condition) ? 1 : -1];
-# else
-# define Q_STATIC_ASSERT(Condition) \
- typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) [(Condition) ? 1 : -1];
-# endif /* __COUNTER__ */
-# define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
-#endif
-
-#ifdef __cplusplus
-
-#include <algorithm>
-
-#if !defined(QT_NAMESPACE) || defined(Q_MOC_RUN) /* user namespace */
-
-# define QT_PREPEND_NAMESPACE(name) ::name
-# define QT_USE_NAMESPACE
-# define QT_BEGIN_NAMESPACE
-# define QT_END_NAMESPACE
-# define QT_BEGIN_INCLUDE_NAMESPACE
-# define QT_END_INCLUDE_NAMESPACE
-#ifndef QT_BEGIN_MOC_NAMESPACE
-# define QT_BEGIN_MOC_NAMESPACE
-#endif
-#ifndef QT_END_MOC_NAMESPACE
-# define QT_END_MOC_NAMESPACE
-#endif
-# define QT_FORWARD_DECLARE_CLASS(name) class name;
-# define QT_FORWARD_DECLARE_STRUCT(name) struct name;
-# define QT_MANGLE_NAMESPACE(name) name
-
-#else /* user namespace */
-
-# define QT_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
-# define QT_USE_NAMESPACE using namespace ::QT_NAMESPACE;
-# define QT_BEGIN_NAMESPACE namespace QT_NAMESPACE {
-# define QT_END_NAMESPACE }
-# define QT_BEGIN_INCLUDE_NAMESPACE }
-# define QT_END_INCLUDE_NAMESPACE namespace QT_NAMESPACE {
-#ifndef QT_BEGIN_MOC_NAMESPACE
-# define QT_BEGIN_MOC_NAMESPACE QT_USE_NAMESPACE
-#endif
-#ifndef QT_END_MOC_NAMESPACE
-# define QT_END_MOC_NAMESPACE
-#endif
-# define QT_FORWARD_DECLARE_CLASS(name) \
- QT_BEGIN_NAMESPACE class name; QT_END_NAMESPACE \
- using QT_PREPEND_NAMESPACE(name);
-
-# define QT_FORWARD_DECLARE_STRUCT(name) \
- QT_BEGIN_NAMESPACE struct name; QT_END_NAMESPACE \
- using QT_PREPEND_NAMESPACE(name);
-
-# define QT_MANGLE_NAMESPACE0(x) x
-# define QT_MANGLE_NAMESPACE1(a, b) a##_##b
-# define QT_MANGLE_NAMESPACE2(a, b) QT_MANGLE_NAMESPACE1(a,b)
-# define QT_MANGLE_NAMESPACE(name) QT_MANGLE_NAMESPACE2( \
- QT_MANGLE_NAMESPACE0(name), QT_MANGLE_NAMESPACE0(QT_NAMESPACE))
-
-namespace QT_NAMESPACE {}
-
-# ifndef QT_BOOTSTRAPPED
-# ifndef QT_NO_USING_NAMESPACE
- /*
- This expands to a "using QT_NAMESPACE" also in _header files_.
- It is the only way the feature can be used without too much
- pain, but if people _really_ do not want it they can add
- DEFINES += QT_NO_USING_NAMESPACE to their .pro files.
- */
- QT_USE_NAMESPACE
-# endif
-# endif
-
-#endif /* user namespace */
-
-#else /* __cplusplus */
-
-# define QT_BEGIN_NAMESPACE
-# define QT_END_NAMESPACE
-# define QT_USE_NAMESPACE
-# define QT_BEGIN_INCLUDE_NAMESPACE
-# define QT_END_INCLUDE_NAMESPACE
-
-#endif /* __cplusplus */
-
-// ### Qt6: remove me.
-#define QT_BEGIN_HEADER
-#define QT_END_HEADER
-
-#if defined(Q_OS_DARWIN) && !defined(QT_LARGEFILE_SUPPORT)
-# define QT_LARGEFILE_SUPPORT 64
-#endif
-
#ifndef __ASSEMBLER__
-QT_BEGIN_NAMESPACE
-
-/*
- Size-dependent types (architechture-dependent byte order)
-
- Make sure to update QMetaType when changing these typedefs
-*/
-
-typedef signed char qint8; /* 8 bit signed */
-typedef unsigned char quint8; /* 8 bit unsigned */
-typedef short qint16; /* 16 bit signed */
-typedef unsigned short quint16; /* 16 bit unsigned */
-typedef int qint32; /* 32 bit signed */
-typedef unsigned int quint32; /* 32 bit unsigned */
-#if defined(Q_OS_WIN) && !defined(Q_CC_GNU)
-# define Q_INT64_C(c) c ## i64 /* signed 64 bit constant */
-# define Q_UINT64_C(c) c ## ui64 /* unsigned 64 bit constant */
-typedef __int64 qint64; /* 64 bit signed */
-typedef unsigned __int64 quint64; /* 64 bit unsigned */
-#else
-#ifdef __cplusplus
-# define Q_INT64_C(c) static_cast<long long>(c ## LL) /* signed 64 bit constant */
-# define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */
-#else
-# define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */
-# define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */
-#endif
-typedef long long qint64; /* 64 bit signed */
-typedef unsigned long long quint64; /* 64 bit unsigned */
-#endif
-
-typedef qint64 qlonglong;
-typedef quint64 qulonglong;
-
-#ifndef __cplusplus
-// In C++ mode, we define below using QIntegerForSize template
-Q_STATIC_ASSERT_X(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions");
-typedef ptrdiff_t qptrdiff;
-typedef ptrdiff_t qsizetype;
-typedef ptrdiff_t qintptr;
-typedef size_t quintptr;
-#endif
-
-/*
- Useful type definitions for Qt
-*/
-
-QT_BEGIN_INCLUDE_NAMESPACE
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-QT_END_INCLUDE_NAMESPACE
-
-#if defined(QT_COORD_TYPE)
-typedef QT_COORD_TYPE qreal;
-#else
-typedef double qreal;
-#endif
-
-#if defined(QT_NO_DEPRECATED)
-# undef QT_DEPRECATED
-# undef QT_DEPRECATED_X
-# undef QT_DEPRECATED_VARIABLE
-# undef QT_DEPRECATED_CONSTRUCTOR
-#elif !defined(QT_NO_DEPRECATED_WARNINGS)
-# undef QT_DEPRECATED
-# define QT_DEPRECATED Q_DECL_DEPRECATED
-# undef QT_DEPRECATED_X
-# define QT_DEPRECATED_X(text) Q_DECL_DEPRECATED_X(text)
-# undef QT_DEPRECATED_VARIABLE
-# define QT_DEPRECATED_VARIABLE Q_DECL_VARIABLE_DEPRECATED
-# undef QT_DEPRECATED_CONSTRUCTOR
-# define QT_DEPRECATED_CONSTRUCTOR explicit Q_DECL_CONSTRUCTOR_DEPRECATED
-#else
-# undef QT_DEPRECATED
-# define QT_DEPRECATED
-# undef QT_DEPRECATED_X
-# define QT_DEPRECATED_X(text)
-# undef QT_DEPRECATED_VARIABLE
-# define QT_DEPRECATED_VARIABLE
-# undef QT_DEPRECATED_CONSTRUCTOR
-# define QT_DEPRECATED_CONSTRUCTOR
-# undef Q_DECL_ENUMERATOR_DEPRECATED
-# define Q_DECL_ENUMERATOR_DEPRECATED
-#endif
-
-#ifndef QT_DEPRECATED_WARNINGS_SINCE
-# ifdef QT_DISABLE_DEPRECATED_BEFORE
-# define QT_DEPRECATED_WARNINGS_SINCE QT_DISABLE_DEPRECATED_BEFORE
-# else
-# define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION
-# endif
-#endif
-
-#ifndef QT_DISABLE_DEPRECATED_BEFORE
-#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0)
-#endif
-
-/*
- QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than
- the deprecation point specified.
-
- Use it to specify from which version of Qt a function or class has been deprecated
-
- Example:
- #if QT_DEPRECATED_SINCE(5,1)
- QT_DEPRECATED void deprecatedFunction(); //function deprecated since Qt 5.1
- #endif
-
-*/
-#ifdef QT_DEPRECATED
-#define QT_DEPRECATED_SINCE(major, minor) (QT_VERSION_CHECK(major, minor, 0) > QT_DISABLE_DEPRECATED_BEFORE)
-#else
-#define QT_DEPRECATED_SINCE(major, minor) 0
-#endif
-
-/*
- QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text)
- outputs a deprecation warning if QT_DEPRECATED_WARNINGS_SINCE is equal or greater
- than the version specified as major, minor. This makes it possible to deprecate a
- function without annoying a user who needs to stick at a specified minimum version
- and therefore can't use the new function.
-*/
-#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 12, 0)
-# define QT_DEPRECATED_VERSION_X_5_12(text) QT_DEPRECATED_X(text)
-# define QT_DEPRECATED_VERSION_5_12 QT_DEPRECATED
-#else
-# define QT_DEPRECATED_VERSION_X_5_12(text)
-# define QT_DEPRECATED_VERSION_5_12
-#endif
-
-#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 13, 0)
-# define QT_DEPRECATED_VERSION_X_5_13(text) QT_DEPRECATED_X(text)
-# define QT_DEPRECATED_VERSION_5_13 QT_DEPRECATED
-#else
-# define QT_DEPRECATED_VERSION_X_5_13(text)
-# define QT_DEPRECATED_VERSION_5_13
-#endif
-
-#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 14, 0)
-# define QT_DEPRECATED_VERSION_X_5_14(text) QT_DEPRECATED_X(text)
-# define QT_DEPRECATED_VERSION_5_14 QT_DEPRECATED
-#else
-# define QT_DEPRECATED_VERSION_X_5_14(text)
-# define QT_DEPRECATED_VERSION_5_14
-#endif
-
-#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 15, 0)
-# define QT_DEPRECATED_VERSION_X_5_15(text) QT_DEPRECATED_X(text)
-# define QT_DEPRECATED_VERSION_5_15 QT_DEPRECATED
-#else
-# define QT_DEPRECATED_VERSION_X_5_15(text)
-# define QT_DEPRECATED_VERSION_5_15
-#endif
-
-#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(6, 0, 0)
-# define QT_DEPRECATED_VERSION_X_6_0(text) QT_DEPRECATED_X(text)
-# define QT_DEPRECATED_VERSION_6_0 QT_DEPRECATED
-#else
-# define QT_DEPRECATED_VERSION_X_6_0(text)
-# define QT_DEPRECATED_VERSION_6_0
-#endif
-
-#define QT_DEPRECATED_VERSION_X_5(minor, text) QT_DEPRECATED_VERSION_X_5_##minor(text)
-#define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major##_##minor(text)
-
-#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor
-#define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major##_##minor
-
-#ifdef __cplusplus
-// A tag to help mark stuff deprecated (cf. QStringViewLiteral)
-namespace QtPrivate {
-enum class Deprecated_t {};
-constexpr Q_DECL_UNUSED Deprecated_t Deprecated = {};
-}
-#endif
-
-/*
- The Qt modules' export macros.
- The options are:
- - defined(QT_STATIC): Qt was built or is being built in static mode
- - defined(QT_SHARED): Qt was built or is being built in shared/dynamic mode
- If neither was defined, then QT_SHARED is implied. If Qt was compiled in static
- mode, QT_STATIC is defined in qconfig.h. In shared mode, QT_STATIC is implied
- for the bootstrapped tools.
-*/
-
-#ifdef QT_BOOTSTRAPPED
-# ifdef QT_SHARED
-# error "QT_SHARED and QT_BOOTSTRAPPED together don't make sense. Please fix the build"
-# elif !defined(QT_STATIC)
-# define QT_STATIC
-# endif
-#endif
-
-#if defined(QT_SHARED) || !defined(QT_STATIC)
-# ifdef QT_STATIC
-# error "Both QT_SHARED and QT_STATIC defined, please make up your mind"
-# endif
-# ifndef QT_SHARED
-# define QT_SHARED
-# endif
-# if defined(QT_BUILD_CORE_LIB)
-# define Q_CORE_EXPORT Q_DECL_EXPORT
-# else
-# define Q_CORE_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define Q_CORE_EXPORT
-#endif
-
-/*
- Some classes do not permit copies to be made of an object. These
- classes contains a private copy constructor and assignment
- operator to disable copying (the compiler gives an error message).
-*/
-#define Q_DISABLE_COPY(Class) \
- Class(const Class &) = delete;\
- Class &operator=(const Class &) = delete;
-
-#define Q_DISABLE_MOVE(Class) \
- Class(Class &&) = delete; \
- Class &operator=(Class &&) = delete;
-
-#define Q_DISABLE_COPY_MOVE(Class) \
- Q_DISABLE_COPY(Class) \
- Q_DISABLE_MOVE(Class)
-
-/*
- No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
- for Qt's internal unit tests. If you want slower loading times and more
- symbols that can vanish from version to version, feel free to define QT_BUILD_INTERNAL.
-*/
-#if defined(QT_BUILD_INTERNAL) && defined(QT_BUILDING_QT) && defined(QT_SHARED)
-# define Q_AUTOTEST_EXPORT Q_DECL_EXPORT
-#elif defined(QT_BUILD_INTERNAL) && defined(QT_SHARED)
-# define Q_AUTOTEST_EXPORT Q_DECL_IMPORT
-#else
-# define Q_AUTOTEST_EXPORT
-#endif
-
-#define Q_INIT_RESOURCE(name) \
- do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \
- QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (false)
-#define Q_CLEANUP_RESOURCE(name) \
- do { extern int QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); \
- QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); } while (false)
-
-/*
- * If we're compiling C++ code:
- * - and this is a non-namespace build, declare qVersion as extern "C"
- * - and this is a namespace build, declare it as a regular function
- * (we're already inside QT_BEGIN_NAMESPACE / QT_END_NAMESPACE)
- * If we're compiling C code, simply declare the function. If Qt was compiled
- * in a namespace, qVersion isn't callable anyway.
- */
-#if !defined(QT_NAMESPACE) && defined(__cplusplus) && !defined(Q_QDOC)
-extern "C"
-#endif
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOEXCEPT;
+# include <QtCore/qassert.h>
+# include <QtCore/qtnoop.h>
+# include <QtCore/qtypes.h>
+#endif /* !__ASSEMBLER__ */
+#include <QtCore/qtversion.h>
#if defined(__cplusplus)
-#ifndef Q_CONSTRUCTOR_FUNCTION
-# define Q_CONSTRUCTOR_FUNCTION0(AFUNC) \
- namespace { \
- static const struct AFUNC ## _ctor_class_ { \
- inline AFUNC ## _ctor_class_() { AFUNC(); } \
- } AFUNC ## _ctor_instance_; \
- }
-
-# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
-#endif
-
-#ifndef Q_DESTRUCTOR_FUNCTION
-# define Q_DESTRUCTOR_FUNCTION0(AFUNC) \
- namespace { \
- static const struct AFUNC ## _dtor_class_ { \
- inline AFUNC ## _dtor_class_() { } \
- inline ~ AFUNC ## _dtor_class_() { AFUNC(); } \
- } AFUNC ## _dtor_instance_; \
- }
-# define Q_DESTRUCTOR_FUNCTION(AFUNC) Q_DESTRUCTOR_FUNCTION0(AFUNC)
-#endif
-
-/*
- quintptr and qptrdiff is guaranteed to be the same size as a pointer, i.e.
-
- sizeof(void *) == sizeof(quintptr)
- && sizeof(void *) == sizeof(qptrdiff)
-
- size_t and qsizetype are not guaranteed to be the same size as a pointer, but
- they usually are.
-*/
-template <int> struct QIntegerForSize;
-template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; };
-template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; };
-template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; };
-template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; };
-#if defined(Q_CC_GNU) && defined(__SIZEOF_INT128__)
-template <> struct QIntegerForSize<16> { __extension__ typedef unsigned __int128 Unsigned; __extension__ typedef __int128 Signed; };
-#endif
-template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
-typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint;
-typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint;
-typedef QIntegerForSizeof<void*>::Unsigned quintptr;
-typedef QIntegerForSizeof<void*>::Signed qptrdiff;
-typedef qptrdiff qintptr;
-using qsizetype = QIntegerForSizeof<std::size_t>::Signed;
-
-/* moc compats (signals/slots) */
-#ifndef QT_MOC_COMPAT
-# define QT_MOC_COMPAT
-#else
-# undef QT_MOC_COMPAT
-# define QT_MOC_COMPAT
-#endif
-
-#ifdef QT_ASCII_CAST_WARNINGS
-# define QT_ASCII_CAST_WARN Q_DECL_DEPRECATED_X("Use fromUtf8, QStringLiteral, or QLatin1String")
-#else
-# define QT_ASCII_CAST_WARN
-#endif
-
-#ifdef Q_PROCESSOR_X86_32
-# if defined(Q_CC_GNU)
-# define QT_FASTCALL __attribute__((regparm(3)))
-# elif defined(Q_CC_MSVC)
-# define QT_FASTCALL __fastcall
-# else
-# define QT_FASTCALL
-# endif
-#else
-# define QT_FASTCALL
-#endif
-
-// enable gcc warnings for printf-style functions
-#if defined(Q_CC_GNU) && !defined(__INSURE__)
-# if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
-# define Q_ATTRIBUTE_FORMAT_PRINTF(A, B) \
- __attribute__((format(gnu_printf, (A), (B))))
-# else
-# define Q_ATTRIBUTE_FORMAT_PRINTF(A, B) \
- __attribute__((format(printf, (A), (B))))
-# endif
-#else
-# define Q_ATTRIBUTE_FORMAT_PRINTF(A, B)
-#endif
-
-#ifdef Q_CC_MSVC
-# define Q_NEVER_INLINE __declspec(noinline)
-# define Q_ALWAYS_INLINE __forceinline
-#elif defined(Q_CC_GNU)
-# define Q_NEVER_INLINE __attribute__((noinline))
-# define Q_ALWAYS_INLINE inline __attribute__((always_inline))
-#else
-# define Q_NEVER_INLINE
-# define Q_ALWAYS_INLINE inline
-#endif
-
-#if defined(Q_CC_GNU) && defined(Q_OS_WIN) && !defined(QT_NO_DATA_RELOCATION)
-// ### Qt6: you can remove me
-# define QT_INIT_METAOBJECT __attribute__((init_priority(101)))
-#else
-# define QT_INIT_METAOBJECT
-#endif
-
-//defines the type for the WNDPROC on windows
-//the alignment needs to be forced for sse2 to not crash with mingw
-#if defined(Q_OS_WIN)
-# if defined(Q_CC_MINGW) && !defined(Q_OS_WIN64)
-# define QT_ENSURE_STACK_ALIGNED_FOR_SSE __attribute__ ((force_align_arg_pointer))
-# else
-# define QT_ENSURE_STACK_ALIGNED_FOR_SSE
-# endif
-# define QT_WIN_CALLBACK CALLBACK QT_ENSURE_STACK_ALIGNED_FOR_SSE
-#endif
-
-typedef int QNoImplicitBoolCast;
-
-/*
- Utility macros and inline functions
-*/
-
-template <typename T>
-Q_DECL_CONSTEXPR inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
-
-Q_DECL_CONSTEXPR inline int qRound(double d)
-{ return d >= 0.0 ? int(d + 0.5) : int(d - double(int(d-1)) + 0.5) + int(d-1); }
-Q_DECL_CONSTEXPR inline int qRound(float d)
-{ return d >= 0.0f ? int(d + 0.5f) : int(d - float(int(d-1)) + 0.5f) + int(d-1); }
-
-Q_DECL_CONSTEXPR inline qint64 qRound64(double d)
-{ return d >= 0.0 ? qint64(d + 0.5) : qint64(d - double(qint64(d-1)) + 0.5) + qint64(d-1); }
-Q_DECL_CONSTEXPR inline qint64 qRound64(float d)
-{ return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - float(qint64(d-1)) + 0.5f) + qint64(d-1); }
-
-namespace QTypeTraits {
-
-namespace detail {
-template<typename T, typename U,
- typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> &&
- std::is_floating_point_v<T> == std::is_floating_point_v<U> &&
- std::is_signed_v<T> == std::is_signed_v<U>> >
-struct Promoted
-{
- using type = decltype(T() + U());
-};
-}
-
-template <typename T, typename U>
-using Promoted = typename detail::Promoted<T, U>::type;
-
-}
-
-template <typename T>
-constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
-template <typename T>
-constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
-template <typename T>
-constexpr inline const T &qBound(const T &min, const T &val, const T &max)
-{ return qMax(min, qMin(max, val)); }
-template <typename T, typename U>
-constexpr inline QTypeTraits::Promoted<T, U> qMin(const T &a, const U &b)
-{
- using P = QTypeTraits::Promoted<T, U>;
- P _a = a;
- P _b = b;
- return (_a < _b) ? _a : _b;
-}
-template <typename T, typename U>
-constexpr inline QTypeTraits::Promoted<T, U> qMax(const T &a, const U &b)
-{
- using P = QTypeTraits::Promoted<T, U>;
- P _a = a;
- P _b = b;
- return (_a < _b) ? _b : _a;
-}
-template <typename T, typename U>
-constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const U &val, const T &max)
-{ return qMax(min, qMin(max, val)); }
-template <typename T, typename U>
-constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const T &val, const U &max)
-{ return qMax(min, qMin(max, val)); }
-template <typename T, typename U>
-constexpr inline QTypeTraits::Promoted<T, U> qBound(const U &min, const T &val, const T &max)
-{ return qMax(min, qMin(max, val)); }
-
-#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
-# ifdef __OBJC__
-# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
-# else
-# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname
-# endif
-#endif
-#ifndef Q_FORWARD_DECLARE_CF_TYPE
-# define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
-#endif
-#ifndef Q_FORWARD_DECLARE_MUTABLE_CF_TYPE
-# define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
-#endif
-#ifndef Q_FORWARD_DECLARE_CG_TYPE
-#define Q_FORWARD_DECLARE_CG_TYPE(type) typedef const struct type *type ## Ref;
-#endif
-#ifndef Q_FORWARD_DECLARE_MUTABLE_CG_TYPE
-#define Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(type) typedef struct type *type ## Ref;
-#endif
-
-#ifdef Q_OS_DARWIN
-# define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) \
- ((defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && macos != __MAC_NA && __MAC_OS_X_VERSION_MAX_ALLOWED >= macos) || \
- (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MAX_ALLOWED >= ios) || \
- (defined(__TV_OS_VERSION_MAX_ALLOWED) && tvos != __TVOS_NA && __TV_OS_VERSION_MAX_ALLOWED >= tvos) || \
- (defined(__WATCH_OS_VERSION_MAX_ALLOWED) && watchos != __WATCHOS_NA && __WATCH_OS_VERSION_MAX_ALLOWED >= watchos))
-
-# define QT_DARWIN_DEPLOYMENT_TARGET_BELOW(macos, ios, tvos, watchos) \
- ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && macos != __MAC_NA && __MAC_OS_X_VERSION_MIN_REQUIRED < macos) || \
- (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MIN_REQUIRED < ios) || \
- (defined(__TV_OS_VERSION_MIN_REQUIRED) && tvos != __TVOS_NA && __TV_OS_VERSION_MIN_REQUIRED < tvos) || \
- (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && watchos != __WATCHOS_NA && __WATCH_OS_VERSION_MIN_REQUIRED < watchos))
-
-# define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) \
- QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, __TVOS_NA, __WATCHOS_NA)
-# define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) \
- QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, __IPHONE_NA, __TVOS_NA, __WATCHOS_NA)
-# define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) \
- QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, ios, __TVOS_NA, __WATCHOS_NA)
-# define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) \
- QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, __IPHONE_NA, tvos, __WATCHOS_NA)
-# define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) \
- QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, __IPHONE_NA, __TVOS_NA, watchos)
-
-# define QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(macos, ios) \
- QT_DARWIN_DEPLOYMENT_TARGET_BELOW(macos, ios, __TVOS_NA, __WATCHOS_NA)
-# define QT_MACOS_DEPLOYMENT_TARGET_BELOW(macos) \
- QT_DARWIN_DEPLOYMENT_TARGET_BELOW(macos, __IPHONE_NA, __TVOS_NA, __WATCHOS_NA)
-# define QT_IOS_DEPLOYMENT_TARGET_BELOW(ios) \
- QT_DARWIN_DEPLOYMENT_TARGET_BELOW(__MAC_NA, ios, __TVOS_NA, __WATCHOS_NA)
-# define QT_TVOS_DEPLOYMENT_TARGET_BELOW(tvos) \
- QT_DARWIN_DEPLOYMENT_TARGET_BELOW(__MAC_NA, __IPHONE_NA, tvos, __WATCHOS_NA)
-# define QT_WATCHOS_DEPLOYMENT_TARGET_BELOW(watchos) \
- QT_DARWIN_DEPLOYMENT_TARGET_BELOW(__MAC_NA, __IPHONE_NA, __TVOS_NA, watchos)
-
-// Compatibility synonyms, do not use
-# define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios)
-# define QT_MAC_DEPLOYMENT_TARGET_BELOW(osx, ios) QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(osx, ios)
-# define QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(osx) QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(osx)
-# define QT_OSX_DEPLOYMENT_TARGET_BELOW(osx) QT_MACOS_DEPLOYMENT_TARGET_BELOW(osx)
-
-// Implemented in qcore_mac_objc.mm
-class Q_CORE_EXPORT QMacAutoReleasePool
-{
-public:
- QMacAutoReleasePool();
- ~QMacAutoReleasePool();
-private:
- Q_DISABLE_COPY(QMacAutoReleasePool)
- void *pool;
-};
-
-#else
-
-#define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) (0)
-#define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) (0)
-#define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) (0)
-#define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) (0)
-#define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) (0)
-#define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) (0)
-
-#define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) (0)
-#define QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(osx) (0)
-
-#endif // Q_OS_DARWIN
-
-/*
- Data stream functions are provided by many classes (defined in qdatastream.h)
-*/
-
-class QDataStream;
-
-inline void qt_noop(void) {}
-
-/* These wrap try/catch so we can switch off exceptions later.
-
- Beware - do not use more than one QT_CATCH per QT_TRY, and do not use
- the exception instance in the catch block.
- If you can't live with those constraints, don't use these macros.
- Use the QT_NO_EXCEPTIONS macro to protect your code instead.
-*/
-
-#if !defined(QT_NO_EXCEPTIONS)
-# if !defined(Q_MOC_RUN)
-# if (defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_feature(cxx_exceptions)) || \
- (defined(Q_CC_GNU) && !defined(__EXCEPTIONS))
-# define QT_NO_EXCEPTIONS
-# endif
-# elif defined(QT_BOOTSTRAPPED)
-# define QT_NO_EXCEPTIONS
-# endif
-#endif
-
-#ifdef QT_NO_EXCEPTIONS
-# define QT_TRY if (true)
-# define QT_CATCH(A) else
-# define QT_THROW(A) qt_noop()
-# define QT_RETHROW qt_noop()
-# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
-#else
-# define QT_TRY try
-# define QT_CATCH(A) catch (A)
-# define QT_THROW(A) throw A
-# define QT_RETHROW throw
-Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() noexcept;
-# ifdef Q_COMPILER_NOEXCEPT
-# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
-# else
-# define QT_TERMINATE_ON_EXCEPTION(expr) do { try { expr; } catch (...) { qTerminate(); } } while (false)
-# endif
-#endif
-
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() noexcept;
-
-#ifndef Q_OUTOFLINE_TEMPLATE
-# define Q_OUTOFLINE_TEMPLATE
-#endif
-#ifndef Q_INLINE_TEMPLATE
-# define Q_INLINE_TEMPLATE inline
-#endif
-
-/*
- Debugging and error handling
-*/
-
-#if !defined(QT_NO_DEBUG) && !defined(QT_DEBUG)
-# define QT_DEBUG
-#endif
-
-// QtPrivate::asString defined in qstring.h
-#ifndef qPrintable
-# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData()
-#endif
-
-#ifndef qUtf8Printable
-# define qUtf8Printable(string) QtPrivate::asString(string).toUtf8().constData()
-#endif
-
-/*
- Wrap QString::utf16() with enough casts to allow passing it
- to QString::asprintf("%ls") without warnings.
-*/
-#ifndef qUtf16Printable
-# define qUtf16Printable(string) \
- static_cast<const wchar_t*>(static_cast<const void*>(QString(string).utf16()))
-#endif
-
-class QString;
-Q_DECL_COLD_FUNCTION
-Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
-
-#ifndef Q_CC_MSVC
-Q_NORETURN
-#endif
-Q_DECL_COLD_FUNCTION
-Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) noexcept;
-
-#if !defined(Q_ASSERT)
-# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT(cond) static_cast<void>(false && (cond))
-# else
-# define Q_ASSERT(cond) ((cond) ? static_cast<void>(0) : qt_assert(#cond, __FILE__, __LINE__))
-# endif
-#endif
-
-#ifndef Q_CC_MSVC
-Q_NORETURN
-#endif
-Q_DECL_COLD_FUNCTION
-Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept;
-
-#if !defined(Q_ASSERT_X)
-# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT_X(cond, where, what) static_cast<void>(false && (cond))
-# else
-# define Q_ASSERT_X(cond, where, what) ((cond) ? static_cast<void>(0) : qt_assert_x(where, what, __FILE__, __LINE__))
-# endif
-#endif
-
-Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) noexcept;
-Q_DECL_COLD_FUNCTION
-Q_CORE_EXPORT void qBadAlloc();
-
-#ifdef QT_NO_EXCEPTIONS
-# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_CHECK_PTR(p) qt_noop()
-# else
-# define Q_CHECK_PTR(p) do {if (!(p)) qt_check_pointer(__FILE__,__LINE__);} while (false)
-# endif
-#else
-# define Q_CHECK_PTR(p) do { if (!(p)) qBadAlloc(); } while (false)
-#endif
-
-template <typename T>
-inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; }
-
-typedef void (*QFunctionPointer)();
-
-#if !defined(Q_UNIMPLEMENTED)
-# define Q_UNIMPLEMENTED() qWarning("Unimplemented code.")
-#endif
-
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyCompare(double p1, double p2)
-{
- return (qAbs(p1 - p2) * 1000000000000. <= qMin(qAbs(p1), qAbs(p2)));
-}
-
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyCompare(float p1, float p2)
-{
- return (qAbs(p1 - p2) * 100000.f <= qMin(qAbs(p1), qAbs(p2)));
-}
-
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNull(double d)
-{
- return qAbs(d) <= 0.000000000001;
-}
-
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNull(float f)
-{
- return qAbs(f) <= 0.00001f;
-}
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_FLOAT_COMPARE
-
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(double d) noexcept
-{
- return d == 0.0;
-}
-
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(float f) noexcept
-{
- return f == 0.0f;
-}
-
-QT_WARNING_POP
-
-/*
- Compilers which follow outdated template instantiation rules
- require a class to have a comparison operator to exist when
- a QList of this type is instantiated. It's not actually
- used in the list, though. Hence the dummy implementation.
- Just in case other code relies on it we better trigger a warning
- mandating a real implementation.
-*/
-
-#ifdef Q_FULL_TEMPLATE_INSTANTIATION
-# define Q_DUMMY_COMPARISON_OPERATOR(C) \
- bool operator==(const C&) const { \
- qWarning(#C"::operator==(const "#C"&) was called"); \
- return false; \
- }
-#else
-
-# define Q_DUMMY_COMPARISON_OPERATOR(C)
-#endif
-
-QT_WARNING_PUSH
-// warning: noexcept-expression evaluates to 'false' because of a call to 'void swap(..., ...)'
-QT_WARNING_DISABLE_GCC("-Wnoexcept")
-
-namespace QtPrivate
-{
-namespace SwapExceptionTester { // insulate users from the "using std::swap" below
- using std::swap; // import std::swap
- template <typename T>
- void checkSwap(T &t)
- noexcept(noexcept(swap(t, t)));
- // declared, but not implemented (only to be used in unevaluated contexts (noexcept operator))
-}
-} // namespace QtPrivate
-
-template <typename T>
-inline void qSwap(T &value1, T &value2)
- noexcept(noexcept(QtPrivate::SwapExceptionTester::checkSwap(value1)))
-{
- using std::swap;
- swap(value1, value2);
-}
-
-QT_WARNING_POP
-
-#if QT_DEPRECATED_SINCE(5, 0)
-Q_CORE_EXPORT QT_DEPRECATED void *qMalloc(size_t size) Q_ALLOC_SIZE(1);
-Q_CORE_EXPORT QT_DEPRECATED void qFree(void *ptr);
-Q_CORE_EXPORT QT_DEPRECATED void *qRealloc(void *ptr, size_t size) Q_ALLOC_SIZE(2);
-Q_CORE_EXPORT QT_DEPRECATED void *qMemCopy(void *dest, const void *src, size_t n);
-Q_CORE_EXPORT QT_DEPRECATED void *qMemSet(void *dest, int c, size_t n);
-#endif
-Q_CORE_EXPORT void *qMallocAligned(size_t size, size_t alignment) Q_ALLOC_SIZE(1);
-Q_CORE_EXPORT void *qReallocAligned(void *ptr, size_t size, size_t oldsize, size_t alignment) Q_ALLOC_SIZE(2);
-Q_CORE_EXPORT void qFreeAligned(void *ptr);
-
-
-/*
- Avoid some particularly useless warnings from some stupid compilers.
- To get ALL C++ compiler warnings, define QT_CC_WARNINGS or comment out
- the line "#define QT_NO_WARNINGS".
-*/
-#if !defined(QT_CC_WARNINGS)
-# define QT_NO_WARNINGS
-#endif
-#if defined(QT_NO_WARNINGS)
-# if defined(Q_CC_MSVC)
-QT_WARNING_DISABLE_MSVC(4251) /* class 'type' needs to have dll-interface to be used by clients of class 'type2' */
-QT_WARNING_DISABLE_MSVC(4244) /* conversion from 'type1' to 'type2', possible loss of data */
-QT_WARNING_DISABLE_MSVC(4275) /* non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' */
-QT_WARNING_DISABLE_MSVC(4514) /* unreferenced inline function has been removed */
-QT_WARNING_DISABLE_MSVC(4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */
-QT_WARNING_DISABLE_MSVC(4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */
-QT_WARNING_DISABLE_MSVC(4706) /* assignment within conditional expression */
-QT_WARNING_DISABLE_MSVC(4355) /* 'this' : used in base member initializer list */
-QT_WARNING_DISABLE_MSVC(4710) /* function not inlined */
-QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */
-# elif defined(Q_CC_BOR)
-# pragma option -w-inl
-# pragma option -w-aus
-# pragma warn -inl
-# pragma warn -pia
-# pragma warn -ccc
-# pragma warn -rch
-# pragma warn -sig
-# endif
-#endif
-
-// Work around MSVC warning about use of 3-arg algorithms
-// until we can depend on the C++14 4-arg ones.
-//
-// These algortithms do NOT check for equal length.
-// They need to be treated as if they called the 3-arg version (which they do)!
-#ifdef Q_CC_MSVC
-# define QT_3ARG_ALG(alg, f1, l1, f2, l2) \
- std::alg(f1, l1, f2, l2)
-#else
-# define QT_3ARG_ALG(alg, f1, l1, f2, l2) \
- [&f1, &l1, &f2, &l2]() { \
- Q_UNUSED(l2); \
- return std::alg(f1, l1, f2); \
- }()
-#endif
-template <typename ForwardIterator1, typename ForwardIterator2>
-inline bool qt_is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
- ForwardIterator2 first2, ForwardIterator2 last2)
-{
- return QT_3ARG_ALG(is_permutation, first1, last1, first2, last2);
-}
-#undef QT_3ARG_ALG
-
-// this adds const to non-const objects (like std::as_const)
-template <typename T>
-Q_DECL_CONSTEXPR typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; }
-// prevent rvalue arguments:
-template <typename T>
-void qAsConst(const T &&) = delete;
-
-// like std::exchange
-template <typename T, typename U = T>
-Q_DECL_RELAXED_CONSTEXPR T qExchange(T &t, U &&newValue)
-{
- T old = std::move(t);
- t = std::forward<U>(newValue);
- return old;
-}
-
-#ifndef QT_NO_FOREACH
-
-namespace QtPrivate {
-
-template <typename T>
-class QForeachContainer {
- Q_DISABLE_COPY(QForeachContainer)
-public:
- QForeachContainer(const T &t) : c(t), i(qAsConst(c).begin()), e(qAsConst(c).end()) {}
- QForeachContainer(T &&t) : c(std::move(t)), i(qAsConst(c).begin()), e(qAsConst(c).end()) {}
-
- QForeachContainer(QForeachContainer &&other)
- : c(std::move(other.c)),
- i(qAsConst(c).begin()),
- e(qAsConst(c).end()),
- control(std::move(other.control))
- {
- }
-
- QForeachContainer &operator=(QForeachContainer &&other)
- {
- c = std::move(other.c);
- i = qAsConst(c).begin();
- e = qAsConst(c).end();
- control = std::move(other.control);
- return *this;
- }
-
- T c;
- typename T::const_iterator i, e;
- int control = 1;
-};
-
-template<typename T>
-QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t)
-{
- return QForeachContainer<typename std::decay<T>::type>(std::forward<T>(t));
-}
-
-}
-
-#if __cplusplus >= 201703L
-// Use C++17 if statement with initializer. User's code ends up in a else so
-// scoping of different ifs is not broken
-#define Q_FOREACH(variable, container) \
-for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
- _container_.i != _container_.e; ++_container_.i) \
- if (variable = *_container_.i; false) {} else
-#else
-// Explanation of the control word:
-// - it's initialized to 1
-// - that means both the inner and outer loops start
-// - if there were no breaks, at the end of the inner loop, it's set to 0, which
-// causes it to exit (the inner loop is run exactly once)
-// - at the end of the outer loop, it's inverted, so it becomes 1 again, allowing
-// the outer loop to continue executing
-// - if there was a break inside the inner loop, it will exit with control still
-// set to 1; in that case, the outer loop will invert it to 0 and will exit too
-#define Q_FOREACH(variable, container) \
-for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
- _container_.control && _container_.i != _container_.e; \
- ++_container_.i, _container_.control ^= 1) \
- for (variable = *_container_.i; _container_.control; _container_.control = 0)
-#endif
-#endif // QT_NO_FOREACH
-
-#define Q_FOREVER for(;;)
-#ifndef QT_NO_KEYWORDS
-# ifndef QT_NO_FOREACH
-# ifndef foreach
-# define foreach Q_FOREACH
-# endif
-# endif // QT_NO_FOREACH
-# ifndef forever
-# define forever Q_FOREVER
-# endif
-#endif
-
-template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
-template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) -> decltype(ptr.get()) { return ptr.get(); }
-
-// The body must be a statement:
-#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
-#define Q_DECLARE_PRIVATE(Class) \
- inline Class##Private* d_func() \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
- inline const Class##Private* d_func() const \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
- friend class Class##Private;
-
-#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
- inline Class##Private* d_func() \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
- inline const Class##Private* d_func() const \
- { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
- friend class Class##Private;
-
-#define Q_DECLARE_PUBLIC(Class) \
- inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
- inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
- friend class Class;
-
-#define Q_D(Class) Class##Private * const d = d_func()
-#define Q_Q(Class) Class * const q = q_func()
-
-#define QT_TR_NOOP(x) x
-#define QT_TR_NOOP_UTF8(x) x
-#define QT_TRANSLATE_NOOP(scope, x) x
-#define QT_TRANSLATE_NOOP_UTF8(scope, x) x
-#define QT_TRANSLATE_NOOP3(scope, x, comment) {x, comment}
-#define QT_TRANSLATE_NOOP3_UTF8(scope, x, comment) {x, comment}
-
-#ifndef QT_NO_TRANSLATION // ### Qt6: This should enclose the NOOPs above
-
-#define QT_TR_N_NOOP(x) x
-#define QT_TRANSLATE_N_NOOP(scope, x) x
-#define QT_TRANSLATE_N_NOOP3(scope, x, comment) {x, comment}
-
-// Defined in qcoreapplication.cpp
-// The better name qTrId() is reserved for an upcoming function which would
-// return a much more powerful QStringFormatter instead of a QString.
-Q_CORE_EXPORT QString qtTrId(const char *id, int n = -1);
-
-#define QT_TRID_NOOP(id) id
-
-#endif // QT_NO_TRANSLATION
-
-/*
- When RTTI is not available, define this macro to force any uses of
- dynamic_cast to cause a compile failure.
-*/
-
-#if defined(QT_NO_DYNAMIC_CAST) && !defined(dynamic_cast)
-# define dynamic_cast QT_PREPEND_NAMESPACE(qt_dynamic_cast_check)
-
- template<typename T, typename X>
- T qt_dynamic_cast_check(X, T* = 0)
- { return T::dynamic_cast_will_always_fail_because_rtti_is_disabled; }
-#endif
-
-
-#ifdef Q_QDOC
-
-// Just for documentation generation
-template<typename T>
-auto qOverload(T functionPointer);
-template<typename T>
-auto qConstOverload(T memberFunctionPointer);
-template<typename T>
-auto qNonConstOverload(T memberFunctionPointer);
-
-#elif defined(Q_COMPILER_VARIADIC_TEMPLATES)
-
-template <typename... Args>
-struct QNonConstOverload
-{
- template <typename R, typename T>
- Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const noexcept -> decltype(ptr)
- { return ptr; }
-
- template <typename R, typename T>
- static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) noexcept -> decltype(ptr)
- { return ptr; }
-};
-
-template <typename... Args>
-struct QConstOverload
-{
- template <typename R, typename T>
- Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const noexcept -> decltype(ptr)
- { return ptr; }
-
- template <typename R, typename T>
- static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) noexcept -> decltype(ptr)
- { return ptr; }
-};
-
-template <typename... Args>
-struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
-{
- using QConstOverload<Args...>::of;
- using QConstOverload<Args...>::operator();
- using QNonConstOverload<Args...>::of;
- using QNonConstOverload<Args...>::operator();
-
- template <typename R>
- Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const noexcept -> decltype(ptr)
- { return ptr; }
-
- template <typename R>
- static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) noexcept -> decltype(ptr)
- { return ptr; }
-};
-
-#if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304 // C++14
-template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QOverload<Args...> qOverload = {};
-template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QConstOverload<Args...> qConstOverload = {};
-template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> qNonConstOverload = {};
-#endif
-
-#endif
-
-
-class QByteArray;
-Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
-// need it as two functions because QString is only forward-declared here
-Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName);
-Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &defaultValue);
-Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value);
-Q_CORE_EXPORT bool qunsetenv(const char *varName);
-
-Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept;
-Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept;
-Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept;
-
-inline int qIntCast(double f) { return int(f); }
-inline int qIntCast(float f) { return int(f); }
-
-/*
- Reentrant versions of basic rand() functions for random number generation
-*/
-#if QT_DEPRECATED_SINCE(5, 15)
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_5_15("use QRandomGenerator instead") void qsrand(uint seed);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_5_15("use QRandomGenerator instead") int qrand();
-#endif
-
-#define QT_MODULE(x)
-
-#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && \
- (!defined(__PIC__) || (defined(__PIE__) && defined(Q_CC_GNU) && Q_CC_GNU >= 500))
-# error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
- "Compile your code with -fPIC (-fPIE is not enough)."
-#endif
-
-namespace QtPrivate {
-//like std::enable_if
-template <bool B, typename T = void> struct QEnableIf;
-template <typename T> struct QEnableIf<true, T> { typedef T Type; };
-}
-
-QT_END_NAMESPACE
+#include <QtCore/qtclasshelpermacros.h>
// We need to keep QTypeInfo, QSysInfo, QFlags, qDebug & family in qglobal.h for compatibility with Qt 4.
// Be careful when changing the order of these files.
@@ -1303,11 +51,25 @@ QT_END_NAMESPACE
#include <QtCore/qflags.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qconstructormacros.h>
+#include <QtCore/qdarwinhelpers.h>
+#include <QtCore/qexceptionhandling.h>
+#include <QtCore/qforeach.h>
+#include <QtCore/qfunctionpointer.h>
#include <QtCore/qglobalstatic.h>
+#include <QtCore/qmalloc.h>
+#include <QtCore/qminmax.h>
#include <QtCore/qnumeric.h>
+#include <QtCore/qoverload.h>
+#include <QtCore/qswap.h>
+#include <QtCore/qtdeprecationmarkers.h>
+#include <QtCore/qtenvironmentvariables.h>
+#include <QtCore/qtresource.h>
+#include <QtCore/qttranslation.h>
+#include <QtCore/qttypetraits.h>
+#if QT_CONFIG(version_tagging)
#include <QtCore/qversiontagging.h>
-
+#endif
#endif /* __cplusplus */
-#endif /* !__ASSEMBLER__ */
#endif /* QGLOBAL_H */
diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h
index 5ab84fa8be..31f67510e3 100644
--- a/src/corelib/global/qglobal_p.h
+++ b/src/corelib/global/qglobal_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2015 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2015 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGLOBAL_P_H
#define QGLOBAL_P_H
@@ -60,17 +24,37 @@
#include <QtCore/private/qtcore-config_p.h>
#endif
-#if defined(__cplusplus)
-#ifdef Q_CC_MINGW
-# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#if defined(Q_CC_MSVC)
+// By default, dynamic initialization uses subsection "$XCU", which is
+// equivalent to #pragma init_seg(user). Additionally, #pragma
+// init_seg(compiler) and init_seg(lib) use "$XCC" and "$XCL" respectively. So
+// place us between "compiler" and "lib".
+# define QT_SUPPORTS_INIT_PRIORITY 1
+
+// warning C4075: initializers put in unrecognized initialization area
+# define Q_DECL_INIT_PRIORITY(nn) \
+ __pragma(warning(disable: 4075)) \
+ __pragma(init_seg(".CRT$XCK" QT_STRINGIFY(nn))) Q_DECL_UNUSED
+#elif defined(Q_OS_QNX)
+// init_priority fails on QNX and we didn't bother investigating why
+# define QT_SUPPORTS_INIT_PRIORITY 0
+#elif defined(Q_OS_WIN) || defined(Q_OF_ELF)
+# define QT_SUPPORTS_INIT_PRIORITY 1
+// priorities 0 to 1000 are reserved to the runtime;
+// we use above 2000 in case someone REALLY needs to go before us
+# define Q_DECL_INIT_PRIORITY(nn) __attribute__((init_priority(2000 + nn), used))
+#elif defined(QT_SHARED)
+// it doesn't support this exactly, but we can work around it
+# define QT_SUPPORTS_INIT_PRIORITY -1
+# define Q_DECL_INIT_PRIORITY(nn) Q_DECL_UNUSED
+#else
+# define QT_SUPPORTS_INIT_PRIORITY 0
#endif
-#include <time.h>
+#if defined(__cplusplus)
QT_BEGIN_NAMESPACE
-// These behave as if they consult the environment, so need to share its locking:
-Q_CORE_EXPORT void qTzSet();
-Q_CORE_EXPORT time_t qMkTime(struct tm *when);
+Q_NORETURN Q_CORE_EXPORT void qAbort();
QT_END_NAMESPACE
@@ -146,4 +130,3 @@ QT_END_NAMESPACE
#endif // defined(__cplusplus)
#endif // QGLOBAL_P_H
-
diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h
index e56fe1dbcb..93127adab3 100644
--- a/src/corelib/global/qglobalstatic.h
+++ b/src/corelib/global/qglobalstatic.h
@@ -1,48 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGLOBALSTATIC_H
#define QGLOBALSTATIC_H
+#include <QtCore/qassert.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qtclasshelpermacros.h>
+
+#include <atomic> // for bootstrapped (no thread) builds
+#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -53,111 +20,109 @@ enum GuardValues {
Uninitialized = 0,
Initializing = 1
};
-}
-#if !QT_CONFIG(thread) || defined(Q_COMPILER_THREADSAFE_STATICS)
-// some compilers support thread-safe statics
-// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4
-// support it. C++11 also requires this behavior.
-// Clang and Intel CC masquerade as GCC when compiling on Linux.
-//
-// Apple's libc++abi however uses a global lock for initializing local statics,
-// which will block other threads also trying to initialize a local static
-// until the constructor returns ...
-// We better avoid these kind of problems by using our own locked implementation.
-
-#if defined(Q_OS_UNIX) && defined(Q_CC_INTEL)
-// Work around Intel issue ID 6000058488:
-// local statics inside an inline function inside an anonymous namespace are global
-// symbols (this affects the IA-64 C++ ABI, so OS X and Linux only)
-# define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN
-#else
-# define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN inline
-#endif
+template <typename QGS> union Holder
+{
+ using Type = typename QGS::QGS_Type;
+ using PlainType = std::remove_cv_t<Type>;
-#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \
- Q_GLOBAL_STATIC_INTERNAL_DECORATION Type *innerFunction() \
- { \
- struct HolderBase { \
- ~HolderBase() noexcept \
- { if (guard.loadRelaxed() == QtGlobalStatic::Initialized) \
- guard.storeRelaxed(QtGlobalStatic::Destroyed); } \
- }; \
- static struct Holder : public HolderBase { \
- Type value; \
- Holder() \
- noexcept(noexcept(Type ARGS)) \
- : value ARGS \
- { guard.storeRelaxed(QtGlobalStatic::Initialized); } \
- } holder; \
- return &holder.value; \
- }
-#else
-// We don't know if this compiler supports thread-safe global statics
-// so use our own locked implementation
+ static constexpr bool ConstructionIsNoexcept = noexcept(QGS::innerFunction(nullptr));
+ Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
-QT_END_NAMESPACE
-#include <QtCore/qmutex.h>
-#include <mutex>
-QT_BEGIN_NAMESPACE
+ // union's sole member
+ PlainType storage;
-#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \
- Q_DECL_HIDDEN inline Type *innerFunction() \
- { \
- static Type *d; \
- static QBasicMutex mutex; \
- int x = guard.loadAcquire(); \
- if (Q_UNLIKELY(x >= QtGlobalStatic::Uninitialized)) { \
- const std::lock_guard<QBasicMutex> locker(mutex); \
- if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) { \
- d = new Type ARGS; \
- static struct Cleanup { \
- ~Cleanup() { \
- delete d; \
- guard.storeRelaxed(QtGlobalStatic::Destroyed); \
- } \
- } cleanup; \
- guard.storeRelease(QtGlobalStatic::Initialized); \
- } \
- } \
- return d; \
+ Holder() noexcept(ConstructionIsNoexcept)
+ {
+ QGS::innerFunction(pointer());
+ guard.storeRelaxed(QtGlobalStatic::Initialized);
}
+
+ ~Holder()
+ {
+ // TSAN does not support atomic_thread_fence and GCC complains:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97868
+ // https://github.com/google/sanitizers/issues/1352
+QT_WARNING_PUSH
+#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
+QT_WARNING_DISABLE_GCC("-Wtsan")
#endif
+ // import changes to *pointer() by other threads before running ~PlainType():
+ std::atomic_thread_fence(std::memory_order_acquire);
+QT_WARNING_POP
+ pointer()->~PlainType();
+ guard.storeRelease(QtGlobalStatic::Destroyed);
+ }
+
+ PlainType *pointer() noexcept
+ {
+ return &storage;
+ }
-// this class must be POD, unless the compiler supports thread-safe statics
-template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard>
-struct QGlobalStatic
+ Q_DISABLE_COPY_MOVE(Holder)
+};
+}
+
+template <typename Holder> struct QGlobalStatic
{
- typedef T Type;
+ using Type = typename Holder::Type;
- bool isDestroyed() const { return guard.loadRelaxed() <= QtGlobalStatic::Destroyed; }
- bool exists() const { return guard.loadRelaxed() == QtGlobalStatic::Initialized; }
- operator Type *() { if (isDestroyed()) return nullptr; return innerFunction(); }
- Type *operator()() { if (isDestroyed()) return nullptr; return innerFunction(); }
+ bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
+ bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
+ operator Type *()
+ {
+ if (isDestroyed())
+ return nullptr;
+ return instance();
+ }
+ Type *operator()()
+ {
+ if (isDestroyed())
+ return nullptr;
+ return instance();
+ }
Type *operator->()
{
- Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
- return innerFunction();
+ Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
+ "The global static was used after being destroyed");
+ return instance();
}
Type &operator*()
{
- Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
- return *innerFunction();
+ Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
+ "The global static was used after being destroyed");
+ return *instance();
+ }
+
+protected:
+ static Type *instance() noexcept(Holder::ConstructionIsNoexcept)
+ {
+ static Holder holder;
+ return holder.pointer();
+ }
+ static QtGlobalStatic::GuardValues guardValue() noexcept
+ {
+ return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
}
};
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
- namespace { namespace Q_QGS_ ## NAME { \
- typedef TYPE Type; \
- QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized); \
- Q_GLOBAL_STATIC_INTERNAL(ARGS) \
- } } \
- static QGlobalStatic<TYPE, \
- Q_QGS_ ## NAME::innerFunction, \
- Q_QGS_ ## NAME::guard> NAME;
-
-#define Q_GLOBAL_STATIC(TYPE, NAME) \
- Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
+ QT_WARNING_PUSH \
+ QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression") \
+ namespace { struct Q_QGS_ ## NAME { \
+ typedef TYPE QGS_Type; \
+ static void innerFunction(void *pointer) \
+ noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS)) \
+ { \
+ new (pointer) QGS_Type ARGS; \
+ } \
+ }; } \
+ Q_CONSTINIT static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME; \
+ QT_WARNING_POP
+ /**/
+
+#define Q_GLOBAL_STATIC(TYPE, NAME, ...) \
+ Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
QT_END_NAMESPACE
#endif // QGLOBALSTATIC_H
diff --git a/src/corelib/global/qglobalstatic.qdoc b/src/corelib/global/qglobalstatic.qdoc
index e7935d5a9b..38700032b1 100644
--- a/src/corelib/global/qglobalstatic.qdoc
+++ b/src/corelib/global/qglobalstatic.qdoc
@@ -1,32 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
- \macro Q_GLOBAL_STATIC(Type, VariableName)
+ \macro Q_GLOBAL_STATIC(Type, VariableName, ...)
\since 5.1
\relates QGlobalStatic
@@ -36,6 +12,11 @@
will not increase the application or the library's load time. Additionally,
the object is initialized in a thread-safe manner on all platforms.
+ Since Qt 6.3, this macro admits variadic arguments, which are used to
+ initialize the object, thus making the need for \l
+ Q_GLOBAL_STATIC_WITH_ARGS unnecessary. Please note the arguments do not
+ require an extra set of parentheses, unlike the older macro.
+
The typical use of this macro is as follows, in a global context (that is,
outside of any function bodies):
@@ -65,10 +46,6 @@
\li the order of initialization and destruction among different
translation units is not determined, leading to possible uses before
initialization or after destruction;
-
- \li if it is found inside a function (that is, not global), it will be
- initialized on first use, but many current compilers (as of 2013) do
- not guarantee that the initialization will be thread-safe;
\endlist
The Q_GLOBAL_STATIC macro solves all of the above problems by guaranteeing
@@ -195,11 +172,11 @@
\omit
\section1 Compatibility with Qt 4 and Qt 5.0
- This macro, in its current form and behavior, was introduced in Qt 5.1.
- Prior to that version, Qt had another macro with the same name that was
- private API. This section is not meant to document how to use
- Q_GLOBAL_STATIC in those versions, but instead to serve as a porting guide
- for Qt code that used those macros.
+ This macro, in its current behavior, was introduced in Qt 5.1. Prior to
+ that version, Qt had another macro with the same name that was private API.
+ This section is not meant to document how to use Q_GLOBAL_STATIC in those
+ versions, but instead to serve as a porting guide for Qt code that used
+ those macros.
The Qt 4 Q_GLOBAL_STATIC macro differed in behavior in the following ways:
@@ -218,24 +195,38 @@
\section1 Implementation Details
- Q_GLOBAL_STATIC is implemented by creating a QBasicAtomicInt called the \c
- guard and a free, inline function called \c innerFunction. The guard
- variable is initialized to value 0 (chosen so that the guard can be placed
- in the .bss section of the binary file), which denotes that construction
- has not yet taken place (uninitialized). The inner function is implemented
- by the helper macro Q_GLOBAL_STATIC_INTERNAL.
-
- Both the guard variable and the inner function are passed as template
- parameters to QGlobalStatic, along with the type \a Type. Both should also
- have static linkage or be placed inside an anonymous namespace, so that the
- visibility of Q_GLOBAL_STATIC is that of a global static. To permit
- multiple Q_GLOBAL_STATIC per translation unit, the guard variable and the
- inner function must have unique names, which can be accomplished by
- concatenating with \a VariableName or by placing them in a namespace that
- has \a VariableName as part of the name. To simplify and improve
- readability on Q_GLOBAL_STATIC_INTERNAL, we chose the namespace solution.
- It's also required for C++98 builds, since static symbols cannot be used as
- template parameters.
+ Q_GLOBAL_STATIC is implemented by creating a type called \c Q_QGS_NAME
+ where \c NAME is the name of the variable the user passed to the macro,
+ inside an unnamed namespace, and a \c static variable of \l QGlobalStatic
+ type, named \c NAME. The use of unnamed namespaces forces the compiler to emit
+ non-exported symbols, often local to the translation unit, and this
+ propagates to the \l QGlobalStatic template instantiation that uses such
+ types. Additionally, because the type is used only for one variable,
+ there's effectively no difference between static and non-static data
+ members.
+
+ The "QGS" type is a \c struct containing a \c typedef to \a TYPE and a
+ static member function that receives a pointer to storage suitable to hold
+ an instance of \a TYPE. It will initialize the storage using a placement \c
+ new and the variadic arguments.
+
+ The majority of the work is done by the public \l QGlobalStatic class and
+ the private \c QtGlobalStatic::Holder class. The \c Holder union has a
+ single non-static member of type \a TYPE, but because this is a union, its
+ construction and destruction are explicitly controlled in the Holder's
+ constructor and destructor. The constructor calls the "QGS" type's static
+ member function with a pointer to this member so it can be initialized
+ and the destructor calls the type's destructor. The \c{Holder} type is
+ therefore neither trivially constructible nor trivially destructible. It is
+ used as a function-local \c static so its initialization is thread-safe due
+ to C++11's requirement that such variables be thread-safely initialized.
+
+ Additionally, both the constructor and destructor modify a guard variable
+ after construction and before destruction, respectively. The guard variable
+ is implemented as a \c {static inline} member instead of a non-static
+ member so the compiler and linker are free to place this variable in memory
+ far from the actual object. This way, if we wanted to, we could mark it
+ aligned-to-cacheline in the future to prevent false sharing.
The guard variable can assume the following values:
@@ -257,42 +248,15 @@
operate solely on the guard variable: the former returns \c true if the guard
is negative, whereas the latter returns \c true only if it is -2.
- The Q_GLOBAL_STATIC_INTERNAL macro implements the actual construction and
- destruction. There are two implementations of it: one for compilers that
- support thread-safe initialization of function-local statics and one for
- compilers that don't. Thread-safe initialization is required by C++11 in
- [stmt.decl], but as of the time of this writing, only compilers based on
- the IA-64 C++ ABI implemented it properly. The implementation requiring
- thread-safe initialization is also used on the Qt bootstrapped tools, which
- disable the "thread" feature.
-
- The implementation requiring thread-safe initialization from the compiler
- is the simplest: it creates the \a Type object as a function-local static
- and returns its address. The actual object is actually inside a holder
- structure so holder's destructor can set the guard variable to the value -2
- (destroyed) when the type has finished destruction. Since we need to set
- the guard \b after the destruction has finished, this code needs to be in a
- base struct's destructor. And it only sets to -2 (destroyed) if it finds
- the guard at -1 (initialized): this is done to ensure that the guard isn't
- set to -2 in the event the type's constructor threw an exception. A holder
- structure is used to avoid creating two statics, which the ABI might
- require duplicating the thread-safe control structures for.
-
- The other implementation is similar to Qt 4's Q_GLOBAL_STATIC, but unlike
- that one, it uses a \l QBasicMutex to provide locking. It is also more
- efficient memory-wise. It use a simple double-checked locking of the mutex
- and then creates the contents on the heap. After that, it creates a
- function-local structure called "Cleanup", whose destructor will be run at
- program exit and will actually destroy the contents.
-
\endomit
- \sa Q_GLOBAL_STATIC_WITH_ARGS(), QGlobalStatic
+ \sa Q_GLOBAL_STATIC_WITH_ARGS(), Q_APPLICATION_STATIC(), QGlobalStatic
*/
/*!
\macro Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments)
\since 5.1
+ \obsolete
\relates QGlobalStatic
Creates a global and static object of type \l QGlobalStatic, of name \a
@@ -310,7 +274,12 @@
\endcode
The \a Arguments macro parameter must always include the parentheses or, if
- C++11 uniform initialization is allowed, the braces.
+ C++11 uniform initialization is allowed, the braces. The above call is
+ equivalent to
+
+ \code
+ Q_GLOBAL_STATIC(MyType, staticType, 42, "Hello", "World")
+ \endcode
Aside from the actual initialization of the contents with the supplied
arguments, this macro behaves identically to Q_GLOBAL_STATIC(). Please
@@ -356,7 +325,7 @@
*/
/*!
- \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> bool QGlobalStatic<T, innerFunction, guard>::isDestroyed() const
+ \fn template <typename Holder> bool QGlobalStatic<Holder>::isDestroyed() const
This function returns \c true if the global static object has already
completed destruction (that is, if the destructor for the type has already
@@ -386,7 +355,7 @@
*/
/*!
- \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> bool QGlobalStatic<T, innerFunction, guard>::exists() const
+ \fn template <typename Holder> bool QGlobalStatic<Holder>::exists() const
This function returns \c true if the global static object has already
completed initialization (that is, if the constructor for the type has
@@ -436,7 +405,7 @@
/*!
\keyword qglobalstatic-operator-type-ptr
- \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> QGlobalStatic<T, innerFunction, guard>::operator Type*()
+ \fn template <typename Holder> QGlobalStatic<Holder>::operator Type*()
This function returns the address of the contents of this global static. If
the contents have not yet been created, they will be created thread-safely
@@ -469,7 +438,7 @@
*/
/*!
- \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> Type *QGlobalStatic<T, innerFunction, guard>::operator()()
+ \fn template <typename Holder> Type *QGlobalStatic<Holder>::operator()()
\deprecated
This function returns the address of the contents of this global static. If
@@ -485,7 +454,7 @@
*/
/*!
- \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> Type *QGlobalStatic<T, innerFunction, guard>::operator->()
+ \fn template <typename Holder> Type *QGlobalStatic<Holder>::operator->()
This function returns the address of the contents of this global static. If
the contents have not yet been created, they will be created thread-safely
@@ -498,7 +467,7 @@
*/
/*!
- \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> Type &QGlobalStatic<T, innerFunction, guard>::operator*()
+ \fn template <typename Holder> Type &QGlobalStatic<Holder>::operator*()
This function returns a reference to the contents of this global static. If
the contents have not yet been created, they will be created thread-safely
diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp
index 22f01853b7..414b96aac3 100644
--- a/src/corelib/global/qhooks.cpp
+++ b/src/corelib/global/qhooks.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qhooks_p.h"
@@ -67,7 +31,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = {
// The required sizes and offsets are tested in tests/auto/other/toolsupport.
// When this fails and the change was intentional, adjust the test and
// adjust this value here.
- 18
+ 22,
};
static_assert(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]));
diff --git a/src/corelib/global/qhooks_p.h b/src/corelib/global/qhooks_p.h
index a51a2ec86b..e266c2a7f9 100644
--- a/src/corelib/global/qhooks_p.h
+++ b/src/corelib/global/qhooks_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QHOOKS_H
diff --git a/src/corelib/global/qisenum.h b/src/corelib/global/qisenum.h
deleted file mode 100644
index 8f784ef6e3..0000000000
--- a/src/corelib/global/qisenum.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-
-#ifndef QISENUM_H
-#define QISENUM_H
-
-// Use of Q_IS_ENUM is deprecated since 5.8
-#define Q_IS_ENUM(x) std::is_enum<x>::value
-
-// shut up syncqt
-QT_BEGIN_NAMESPACE
-QT_END_NAMESPACE
-#endif // QISENUM_H
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 1380b08372..1b03733d2a 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdir.h"
#include "qstringlist.h"
@@ -45,148 +9,98 @@
#include "qsettings.h"
#endif
#include "qlibraryinfo.h"
+#include "qlibraryinfo_p.h"
#include "qscopedpointer.h"
-#ifdef QT_BUILD_QMAKE
-QT_BEGIN_NAMESPACE
-extern QString qmake_libraryInfoFile();
-QT_END_NAMESPACE
-#else
-# include "qcoreapplication.h"
-#endif
+#include "qcoreapplication.h"
-#ifndef QT_BUILD_QMAKE_BOOTSTRAP
-# include "private/qglobal_p.h"
-# include "qconfig.cpp"
-#endif
+#include "private/qglobal_p.h"
+#include "archdetect.cpp"
+#include "qconfig.cpp"
#ifdef Q_OS_DARWIN
# include "private/qcore_mac_p.h"
#endif // Q_OS_DARWIN
-#include "archdetect.cpp"
-
-#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) && QT_CONFIG(dlopen) && !QT_CONFIG(framework)
-# include <dlfcn.h>
+#if QT_CONFIG(relocatable) && QT_CONFIG(dlopen) && !QT_CONFIG(framework)
+# include <dlfcn.h>
#endif
-#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable) && defined(Q_OS_WIN)
-# include <qt_windows.h>
+#if QT_CONFIG(relocatable) && defined(Q_OS_WIN)
+# include <qt_windows.h>
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
extern void qDumpCPUFeatures(); // in qsimd.cpp
#if QT_CONFIG(settings)
+static QSettings *findConfiguration();
+
struct QLibrarySettings
{
QLibrarySettings();
void load();
+ bool havePaths();
+ QSettings *configuration();
QScopedPointer<QSettings> settings;
-#ifdef QT_BUILD_QMAKE
- bool haveDevicePaths;
- bool haveEffectiveSourcePaths;
- bool haveEffectivePaths;
- bool havePaths;
-#else
+ bool paths;
bool reloadOnQAppAvailable;
-#endif
};
Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
-class QLibraryInfoPrivate
+QLibrarySettings::QLibrarySettings() : paths(false), reloadOnQAppAvailable(false)
{
-public:
- static QSettings *findConfiguration();
-#ifdef QT_BUILD_QMAKE
- static void reload()
- {
- if (qt_library_settings.exists())
- qt_library_settings->load();
- }
- static bool haveGroup(QLibraryInfo::PathGroup group)
- {
- QLibrarySettings *ls = qt_library_settings();
- return ls ? (group == QLibraryInfo::EffectiveSourcePaths
- ? ls->haveEffectiveSourcePaths
- : group == QLibraryInfo::EffectivePaths
- ? ls->haveEffectivePaths
- : group == QLibraryInfo::DevicePaths
- ? ls->haveDevicePaths
- : ls->havePaths) : false;
- }
-#endif
- static QSettings *configuration()
- {
- QLibrarySettings *ls = qt_library_settings();
- if (ls) {
-#ifndef QT_BUILD_QMAKE
- if (ls->reloadOnQAppAvailable && QCoreApplication::instance() != nullptr)
- ls->load();
-#endif
- return ls->settings.data();
- } else {
- return nullptr;
- }
- }
-};
+ load();
+}
-static const char platformsSection[] = "Platforms";
+QSettings *QLibrarySettings::configuration()
+{
+ if (reloadOnQAppAvailable && QCoreApplication::instance() != nullptr)
+ load();
+ return settings.data();
+}
-QLibrarySettings::QLibrarySettings()
+bool QLibrarySettings::havePaths()
{
- load();
+ if (reloadOnQAppAvailable && QCoreApplication::instance() != nullptr)
+ load();
+ return paths;
}
void QLibrarySettings::load()
{
// If we get any settings here, those won't change when the application shows up.
- settings.reset(QLibraryInfoPrivate::findConfiguration());
-#ifndef QT_BUILD_QMAKE
+ settings.reset(findConfiguration());
reloadOnQAppAvailable = (settings.data() == nullptr && QCoreApplication::instance() == nullptr);
- bool haveDevicePaths;
- bool haveEffectivePaths;
- bool havePaths;
-#endif
+
if (settings) {
// This code needs to be in the regular library, as otherwise a qt.conf that
// works for qmake would break things for dynamically built Qt tools.
QStringList children = settings->childGroups();
- haveDevicePaths = children.contains(QLatin1String("DevicePaths"));
-#ifdef QT_BUILD_QMAKE
- haveEffectiveSourcePaths = children.contains(QLatin1String("EffectiveSourcePaths"));
-#else
- // EffectiveSourcePaths is for the Qt build only, so needs no backwards compat trickery.
- bool haveEffectiveSourcePaths = false;
-#endif
- haveEffectivePaths = haveEffectiveSourcePaths || children.contains(QLatin1String("EffectivePaths"));
- // Backwards compat: an existing but empty file is claimed to contain the Paths section.
- havePaths = (!haveDevicePaths && !haveEffectivePaths
- && !children.contains(QLatin1String(platformsSection)))
- || children.contains(QLatin1String("Paths"));
-#ifndef QT_BUILD_QMAKE
- if (!havePaths)
- settings.reset(nullptr);
-#else
- } else {
- haveDevicePaths = false;
- haveEffectiveSourcePaths = false;
- haveEffectivePaths = false;
- havePaths = false;
-#endif
+ paths = !children.contains("Platforms"_L1)
+ || children.contains("Paths"_L1);
}
}
-QSettings *QLibraryInfoPrivate::findConfiguration()
+namespace {
+const QString *qtconfManualPath = nullptr;
+}
+
+void QLibraryInfoPrivate::setQtconfManualPath(const QString *path)
{
-#ifdef QT_BUILD_QMAKE
- QString qtconfig = qmake_libraryInfoFile();
- if (QFile::exists(qtconfig))
- return new QSettings(qtconfig, QSettings::IniFormat);
-#else
+ qtconfManualPath = path;
+}
+
+static QSettings *findConfiguration()
+{
+ if (qtconfManualPath)
+ return new QSettings(*qtconfManualPath, QSettings::IniFormat);
+
QString qtconfig = QStringLiteral(":/qt/etc/qt.conf");
if (QFile::exists(qtconfig))
return new QSettings(qtconfig, QSettings::IniFormat);
@@ -194,7 +108,7 @@ QSettings *QLibraryInfoPrivate::findConfiguration()
CFBundleRef bundleRef = CFBundleGetMainBundle();
if (bundleRef) {
QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
- QCFString(QLatin1String("qt.conf")),
+ QCFString("qt.conf"_L1),
0,
0);
if (urlRef) {
@@ -207,14 +121,33 @@ QSettings *QLibraryInfoPrivate::findConfiguration()
#endif
if (QCoreApplication::instance()) {
QDir pwd(QCoreApplication::applicationDirPath());
- qtconfig = pwd.filePath(QLatin1String("qt.conf"));
+ qtconfig = pwd.filePath(u"qt" QT_STRINGIFY(QT_VERSION_MAJOR) ".conf"_s);
+ if (QFile::exists(qtconfig))
+ return new QSettings(qtconfig, QSettings::IniFormat);
+ qtconfig = pwd.filePath("qt.conf"_L1);
if (QFile::exists(qtconfig))
return new QSettings(qtconfig, QSettings::IniFormat);
}
-#endif
return nullptr; //no luck
}
+QSettings *QLibraryInfoPrivate::configuration()
+{
+ QLibrarySettings *ls = qt_library_settings();
+ return ls ? ls->configuration() : nullptr;
+}
+
+void QLibraryInfoPrivate::reload()
+{
+ if (qt_library_settings.exists())
+ qt_library_settings->load();
+}
+
+static bool havePaths() {
+ QLibrarySettings *ls = qt_library_settings();
+ return ls && ls->havePaths();
+}
+
#endif // settings
/*!
@@ -235,8 +168,6 @@ QSettings *QLibraryInfoPrivate::findConfiguration()
\sa QSysInfo, {Using qt.conf}
*/
-#ifndef QT_BUILD_QMAKE
-
/*!
\internal
@@ -247,42 +178,8 @@ QSettings *QLibraryInfoPrivate::findConfiguration()
QLibraryInfo::QLibraryInfo()
{ }
-#if defined(Q_CC_INTEL) // must be before GNU, Clang and MSVC because ICC/ICL claim to be them
-# ifdef __INTEL_CLANG_COMPILER
-# define ICC_COMPAT "Clang"
-# elif defined(__INTEL_MS_COMPAT_LEVEL)
-# define ICC_COMPAT "Microsoft"
-# elif defined(__GNUC__)
-# define ICC_COMPAT "GCC"
-# else
-# define ICC_COMPAT "no"
-# endif
-# if __INTEL_COMPILER == 1300
-# define ICC_VERSION "13.0"
-# elif __INTEL_COMPILER == 1310
-# define ICC_VERSION "13.1"
-# elif __INTEL_COMPILER == 1400
-# define ICC_VERSION "14.0"
-# elif __INTEL_COMPILER == 1500
-# define ICC_VERSION "15.0"
-# else
-# define ICC_VERSION QT_STRINGIFY(__INTEL_COMPILER)
-# endif
-# ifdef __INTEL_COMPILER_UPDATE
-# define COMPILER_STRING "Intel(R) C++ " ICC_VERSION "." QT_STRINGIFY(__INTEL_COMPILER_UPDATE) \
- " build " QT_STRINGIFY(__INTEL_COMPILER_BUILD_DATE) " [" \
- ICC_COMPAT " compatibility]"
-# else
-# define COMPILER_STRING "Intel(R) C++ " ICC_VERSION \
- " build " QT_STRINGIFY(__INTEL_COMPILER_BUILD_DATE) " [" \
- ICC_COMPAT " compatibility]"
-# endif
-#elif defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
-# ifdef __apple_build_version__ // Apple clang has other version numbers
-# define COMPILER_STRING "Clang " __clang_version__ " (Apple)"
-# else
-# define COMPILER_STRING "Clang " __clang_version__
-# endif
+#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
+# define COMPILER_STRING __VERSION__ /* already includes the compiler's name */
#elif defined(Q_CC_GHS)
# define COMPILER_STRING "GHS " QT_STRINGIFY(__GHS_VERSION_NUMBER)
#elif defined(Q_CC_GNU)
@@ -292,8 +189,10 @@ QLibraryInfo::QLibraryInfo()
# define COMPILER_STRING "MSVC 2015"
# elif _MSC_VER < 1917
# define COMPILER_STRING "MSVC 2017"
-# elif _MSC_VER < 2000
+# elif _MSC_VER < 1930
# define COMPILER_STRING "MSVC 2019"
+# elif _MSC_VER < 2000
+# define COMPILER_STRING "MSVC 2022"
# else
# define COMPILER_STRING "MSVC _MSC_VER " QT_STRINGIFY(_MSC_VER)
# endif
@@ -310,7 +209,10 @@ QLibraryInfo::QLibraryInfo()
#else
# define SHARED_STRING " static"
#endif
-#define QT_BUILD_STR "Qt " QT_VERSION_STR " (" ARCH_FULL SHARED_STRING DEBUG_STRING " build; by " COMPILER_STRING ")"
+static const char *qt_build_string() noexcept
+{
+ return "Qt " QT_VERSION_STR " (" ARCH_FULL SHARED_STRING DEBUG_STRING " build; by " COMPILER_STRING ")";
+}
/*!
Returns a string describing how this version of Qt was built.
@@ -322,7 +224,7 @@ QLibraryInfo::QLibraryInfo()
const char *QLibraryInfo::build() noexcept
{
- return QT_BUILD_STR;
+ return qt_build_string();
}
/*!
@@ -331,7 +233,7 @@ const char *QLibraryInfo::build() noexcept
false if it was built in release mode.
*/
bool
-QLibraryInfo::isDebugBuild()
+QLibraryInfo::isDebugBuild() noexcept
{
#ifdef QT_DEBUG
return true;
@@ -340,7 +242,19 @@ QLibraryInfo::isDebugBuild()
#endif
}
-#ifndef QT_BOOTSTRAPPED
+/*!
+ \since 6.5
+ Returns \c true if this is a shared (dynamic) build of Qt.
+*/
+bool QLibraryInfo::isSharedBuild() noexcept
+{
+#ifdef QT_SHARED
+ return true;
+#else
+ return false;
+#endif
+}
+
/*!
\since 5.8
Returns the version of the Qt library.
@@ -351,76 +265,7 @@ QVersionNumber QLibraryInfo::version() noexcept
{
return QVersionNumber(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH);
}
-#endif // QT_BOOTSTRAPPED
-
-#endif // QT_BUILD_QMAKE
-
-/*
- * To add a new entry in QLibrary::LibraryLocation, add it to the enum above the bootstrapped values and:
- * - add its relative path in the qtConfEntries[] array below
- * (the key is what appears in a qt.conf file)
- * - add a property name in qmake/property.cpp propList[] array
- * (it's used with qmake -query)
- * - add to qt_config.prf, qt_module.prf, qt_module_fwdpri.prf
- */
-
-static const struct {
- char key[19], value[13];
-} qtConfEntries[] = {
- { "Prefix", "." },
- { "Documentation", "doc" }, // should be ${Data}/doc
- { "Headers", "include" },
- { "Libraries", "lib" },
-#ifdef Q_OS_WIN
- { "LibraryExecutables", "bin" },
-#else
- { "LibraryExecutables", "libexec" }, // should be ${ArchData}/libexec
-#endif
- { "Binaries", "bin" },
- { "Plugins", "plugins" }, // should be ${ArchData}/plugins
- { "Qml2Imports", "qml" }, // should be ${ArchData}/qml
- { "ArchData", "." },
- { "Data", "." },
- { "Translations", "translations" }, // should be ${Data}/translations
- { "Examples", "examples" },
- { "Tests", "tests" },
-#ifdef QT_BUILD_QMAKE
- { "Sysroot", "" },
- { "SysrootifyPrefix", "" },
- { "HostBinaries", "bin" },
- { "HostLibraries", "lib" },
- { "HostData", "." },
- { "TargetSpec", "" },
- { "HostSpec", "" },
- { "HostPrefix", "" },
-#endif
-};
-
-#ifdef QT_BUILD_QMAKE
-void QLibraryInfo::reload()
-{
- QLibraryInfoPrivate::reload();
-}
-void QLibraryInfo::sysrootify(QString *path)
-{
- if (!QVariant::fromValue(rawLocation(SysrootifyPrefixPath, FinalPaths)).toBool())
- return;
-
- const QString sysroot = rawLocation(SysrootPath, FinalPaths);
- if (sysroot.isEmpty())
- return;
-
- if (path->length() > 2 && path->at(1) == QLatin1Char(':')
- && (path->at(2) == QLatin1Char('/') || path->at(2) == QLatin1Char('\\'))) {
- path->replace(0, 2, sysroot); // Strip out the drive on Windows targets
- } else {
- path->prepend(sysroot);
- }
-}
-#endif // QT_BUILD_QMAKE
-
-#ifndef QT_BUILD_QMAKE
static QString prefixFromAppDirHelper()
{
QString appDir;
@@ -433,7 +278,7 @@ static QString prefixFromAppDirHelper()
if (urlRef) {
QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
#ifdef Q_OS_MACOS
- QString bundleContentsDir = QString(path) + QLatin1String("/Contents/");
+ QString bundleContentsDir = QString(path) + "/Contents/"_L1;
if (QDir(bundleContentsDir).exists())
return QDir::cleanPath(bundleContentsDir);
#else
@@ -450,17 +295,15 @@ static QString prefixFromAppDirHelper()
return appDir;
}
-#endif
-#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(relocatable)
+#if QT_CONFIG(relocatable)
#if !defined(QT_STATIC) && !(defined(Q_OS_DARWIN) && QT_CONFIG(framework)) \
&& (QT_CONFIG(dlopen) || defined(Q_OS_WIN))
static QString prefixFromQtCoreLibraryHelper(const QString &qtCoreLibraryPath)
{
const QString qtCoreLibrary = QDir::fromNativeSeparators(qtCoreLibraryPath);
const QString libDir = QFileInfo(qtCoreLibrary).absolutePath();
- const QString prefixDir = libDir + QLatin1Char('/')
- + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH);
+ const QString prefixDir = libDir + "/" QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH;
return QDir::cleanPath(prefixDir);
}
#endif
@@ -476,7 +319,7 @@ static HMODULE getWindowsModuleHandle()
}
#endif // Q_OS_WIN
-static QString getRelocatablePrefix()
+static QString getRelocatablePrefix(QLibraryInfoPrivate::UsageMode usageMode)
{
QString prefixPath;
@@ -484,7 +327,14 @@ static QString getRelocatablePrefix()
// For regular builds, the prefix will be relative to the location of the QtCore shared library.
#if defined(QT_STATIC)
prefixPath = prefixFromAppDirHelper();
+ if (usageMode == QLibraryInfoPrivate::UsedFromQtBinDir) {
+ // For Qt tools in a static build, we must chop off the bin directory.
+ constexpr QByteArrayView binDir = qt_configure_strs.viewAt(QLibraryInfo::BinariesPath - 1);
+ constexpr size_t binDirLength = binDir.size() + 1;
+ prefixPath.chop(binDirLength);
+ }
#elif defined(Q_OS_DARWIN) && QT_CONFIG(framework)
+ Q_UNUSED(usageMode);
#ifndef QT_LIBINFIX
#define QT_LIBINFIX ""
#endif
@@ -519,16 +369,22 @@ static QString getRelocatablePrefix()
const QCFString libDirCFString = CFURLCopyFileSystemPath(libDirCFPath, kCFURLPOSIXPathStyle);
- const QString prefixDir = QString(libDirCFString) + QLatin1Char('/')
- + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH);
+ const QString prefixDir = QString(libDirCFString) + "/" QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH;
prefixPath = QDir::cleanPath(prefixDir);
+#elif defined(Q_OS_WASM)
+ // Emscripten expects to find shared libraries at the root of the in-memory
+ // file system when resolving dependencies for for dlopen() calls. So that's
+ // where libqt6core.so would be.
+ prefixPath = QStringLiteral("/");
#elif QT_CONFIG(dlopen)
+ Q_UNUSED(usageMode);
Dl_info info;
int result = dladdr(reinterpret_cast<void *>(&QLibraryInfo::isDebugBuild), &info);
if (result > 0 && info.dli_fname)
prefixPath = prefixFromQtCoreLibraryHelper(QString::fromLocal8Bit(info.dli_fname));
#elif defined(Q_OS_WIN)
+ Q_UNUSED(usageMode);
HMODULE hModule = getWindowsModuleHandle();
const int kBufferSize = 4096;
wchar_t buffer[kBufferSize];
@@ -542,7 +398,7 @@ static QString getRelocatablePrefix()
// executable within the QT_HOST_BIN directory. We're detecting the latter case by checking
// whether there's an import library corresponding to our QtCore DLL in PREFIX/lib.
const QString libdir = QString::fromLocal8Bit(
- qt_configure_strs + qt_configure_str_offsets[QLibraryInfo::LibrariesPath - 1]);
+ qt_configure_strs.viewAt(QLibraryInfo::LibrariesPath - 1));
const QLatin1Char slash('/');
#if defined(Q_CC_MINGW)
const QString implibPrefix = QStringLiteral("lib");
@@ -554,7 +410,7 @@ static QString getRelocatablePrefix()
const QString qtCoreImpLibFileName = implibPrefix
+ QFileInfo(qtCoreFilePath).completeBaseName() + implibSuffix;
const QString qtCoreImpLibPath = qtCoreDirPath
- + slash + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH)
+ + slash + QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH
+ slash + libdir
+ slash + qtCoreImpLibFileName;
if (!QFileInfo::exists(qtCoreImpLibPath)) {
@@ -574,7 +430,7 @@ static QString getRelocatablePrefix()
// See "Hardware capabilities" in the ld.so documentation and the Qt 5.3.0
// changelog regarding SSE2 support.
const QString libdir = QString::fromLocal8Bit(
- qt_configure_strs + qt_configure_str_offsets[QLibraryInfo::LibrariesPath - 1]);
+ qt_configure_strs.viewAt(QLibraryInfo::LibrariesPath - 1));
QDir prefixDir(prefixPath);
while (!prefixDir.exists(libdir)) {
prefixDir.cdUp();
@@ -592,148 +448,133 @@ static QString getRelocatablePrefix()
}
#endif
-#if defined(QT_BUILD_QMAKE) && !defined(QT_BUILD_QMAKE_BOOTSTRAP)
-QString qmake_abslocation();
-
-static QString getPrefixFromHostBinDir(const char *hostBinDirToPrefixPath)
-{
- const QFileInfo qmfi = QFileInfo(qmake_abslocation()).canonicalFilePath();
- return QDir::cleanPath(qmfi.absolutePath() + QLatin1Char('/')
- + QLatin1String(hostBinDirToPrefixPath));
-}
-
-static QString getExtPrefixFromHostBinDir()
+static QString getPrefix(QLibraryInfoPrivate::UsageMode usageMode)
{
- return getPrefixFromHostBinDir(QT_CONFIGURE_HOSTBINDIR_TO_EXTPREFIX_PATH);
+#if QT_CONFIG(relocatable)
+ return getRelocatablePrefix(usageMode);
+#else
+ Q_UNUSED(usageMode);
+ return QString::fromLocal8Bit(QT_CONFIGURE_PREFIX_PATH);
+#endif
}
-static QString getHostPrefixFromHostBinDir()
+QLibraryInfoPrivate::LocationInfo QLibraryInfoPrivate::locationInfo(QLibraryInfo::LibraryPath loc)
{
- return getPrefixFromHostBinDir(QT_CONFIGURE_HOSTBINDIR_TO_HOSTPREFIX_PATH);
-}
+ /*
+ * To add a new entry in QLibraryInfo::LibraryPath, add it to the enum
+ * in qtbase/src/corelib/global/qlibraryinfo.h and:
+ * - add its relative path in the qtConfEntries[] array below
+ * (the key is what appears in a qt.conf file)
+ */
+ static constexpr auto qtConfEntries = qOffsetStringArray(
+ "Prefix", ".",
+ "Documentation", "doc", // should be ${Data}/doc
+ "Headers", "include",
+ "Libraries", "lib",
+#ifdef Q_OS_WIN
+ "LibraryExecutables", "bin",
+#else
+ "LibraryExecutables", "libexec", // should be ${ArchData}/libexec
#endif
+ "Binaries", "bin",
+ "Plugins", "plugins", // should be ${ArchData}/plugins
-#ifndef QT_BUILD_QMAKE_BOOTSTRAP
-static QString getPrefix(
-#ifdef QT_BUILD_QMAKE
- QLibraryInfo::PathGroup group
-#endif
- )
-{
-#if defined(QT_BUILD_QMAKE)
-# if QT_CONFIGURE_CROSSBUILD
- if (group == QLibraryInfo::DevicePaths)
- return QString::fromLocal8Bit(QT_CONFIGURE_PREFIX_PATH);
-# else
- Q_UNUSED(group);
-# endif
- return getExtPrefixFromHostBinDir();
-#elif QT_CONFIG(relocatable)
- return getRelocatablePrefix();
-#else
- return QString::fromLocal8Bit(QT_CONFIGURE_PREFIX_PATH);
+ "QmlImports", "qml", // should be ${ArchData}/qml
+
+ "ArchData", ".",
+ "Data", ".",
+ "Translations", "translations", // should be ${Data}/translations
+ "Examples", "examples",
+ "Tests", "tests"
+ );
+ [[maybe_unused]]
+ constexpr QByteArrayView dot{"."};
+
+ LocationInfo result;
+
+ if (int(loc) < qtConfEntries.count()) {
+ result.key = QLatin1StringView(qtConfEntries.viewAt(loc * 2));
+ result.defaultValue = QLatin1StringView(qtConfEntries.viewAt(loc * 2 + 1));
+ if (result.key == u"QmlImports")
+ result.fallbackKey = u"Qml2Imports"_s;
+#ifndef Q_OS_WIN // On Windows we use the registry
+ } else if (loc == QLibraryInfo::SettingsPath) {
+ result.key = "Settings"_L1;
+ result.defaultValue = QLatin1StringView(dot);
#endif
+ }
+
+ return result;
}
-#endif // QT_BUILD_QMAKE_BOOTSTRAP
+
+/*! \fn QString QLibraryInfo::location(LibraryLocation loc)
+ \deprecated [6.0] Use path() instead.
+
+ Returns the path specified by \a loc.
+*/
/*!
- Returns the location specified by \a loc.
+ \since 6.0
+ Returns the path specified by \a p.
*/
-QString
-QLibraryInfo::location(LibraryLocation loc)
+QString QLibraryInfo::path(LibraryPath p)
{
-#ifdef QT_BUILD_QMAKE // ends inside rawLocation !
- QString ret = rawLocation(loc, FinalPaths);
+ return QLibraryInfoPrivate::path(p);
+}
- // Automatically prepend the sysroot to target paths
- if (loc < SysrootPath || loc > LastHostPath)
- sysrootify(&ret);
- return ret;
-}
+/*
+ Returns the path specified by \a p.
-QString
-QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
+ The usage mode can be set to UsedFromQtBinDir to enable special handling for executables that
+ live in <install-prefix>/bin.
+ */
+QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode)
{
-#endif // QT_BUILD_QMAKE, started inside location !
+ const QLibraryInfo::LibraryPath loc = p;
QString ret;
bool fromConf = false;
#if QT_CONFIG(settings)
-#ifdef QT_BUILD_QMAKE
- // Logic for choosing the right data source: if EffectivePaths are requested
- // and qt.conf with that section is present, use it, otherwise fall back to
- // FinalPaths. For FinalPaths, use qt.conf if present and contains not only
- // [EffectivePaths], otherwise fall back to builtins.
- // EffectiveSourcePaths falls back to EffectivePaths.
- // DevicePaths falls back to FinalPaths.
- PathGroup orig_group = group;
- if (QLibraryInfoPrivate::haveGroup(group)
- || (group == EffectiveSourcePaths
- && (group = EffectivePaths, QLibraryInfoPrivate::haveGroup(group)))
- || ((group == EffectivePaths || group == DevicePaths)
- && (group = FinalPaths, QLibraryInfoPrivate::haveGroup(group)))
- || (group = orig_group, false))
-#else
- if (QLibraryInfoPrivate::configuration())
-#endif
- {
+ if (havePaths()) {
fromConf = true;
- QString key;
- QString defaultValue;
- if (unsigned(loc) < sizeof(qtConfEntries)/sizeof(qtConfEntries[0])) {
- key = QLatin1String(qtConfEntries[loc].key);
- defaultValue = QLatin1String(qtConfEntries[loc].value);
- }
-#ifndef Q_OS_WIN // On Windows we use the registry
- else if (loc == SettingsPath) {
- key = QLatin1String("Settings");
- defaultValue = QLatin1String(".");
- }
-#endif
-
- if(!key.isNull()) {
+ auto li = QLibraryInfoPrivate::locationInfo(loc);
+ if (!li.key.isNull()) {
QSettings *config = QLibraryInfoPrivate::configuration();
- config->beginGroup(QLatin1String(
-#ifdef QT_BUILD_QMAKE
- group == DevicePaths ? "DevicePaths" :
- group == EffectiveSourcePaths ? "EffectiveSourcePaths" :
- group == EffectivePaths ? "EffectivePaths" :
-#endif
- "Paths"));
-
- ret = config->value(key, defaultValue).toString();
-
-#ifdef QT_BUILD_QMAKE
- if (ret.isEmpty()) {
- if (loc == HostPrefixPath)
- ret = config->value(QLatin1String(qtConfEntries[PrefixPath].key),
- QLatin1String(qtConfEntries[PrefixPath].value)).toString();
- else if (loc == TargetSpecPath || loc == HostSpecPath || loc == SysrootifyPrefixPath)
- fromConf = false;
- // The last case here is SysrootPath, which can be legitimately empty.
- // All other keys have non-empty fallbacks to start with.
+ Q_ASSERT(config != nullptr);
+ config->beginGroup("Paths"_L1);
+
+ if (li.fallbackKey.isNull()) {
+ ret = config->value(li.key, li.defaultValue).toString();
+ } else {
+ QVariant v = config->value(li.key);
+ if (!v.isValid())
+ v = config->value(li.fallbackKey, li.defaultValue);
+ ret = v.toString();
}
-#endif
- int startIndex = 0;
- forever {
- startIndex = ret.indexOf(QLatin1Char('$'), startIndex);
+ qsizetype startIndex = 0;
+ /* We support placeholders of the form $(<ENV_VAR>) in qt.conf.
+ The loop below tries to find all such placeholders, and replaces
+ them with the actual value of the ENV_VAR environment variable
+ */
+ while (true) {
+ startIndex = ret.indexOf(u'$', startIndex);
if (startIndex < 0)
break;
- if (ret.length() < startIndex + 3)
+ if (ret.size() < startIndex + 3)
break;
- if (ret.at(startIndex + 1) != QLatin1Char('(')) {
+ if (ret.at(startIndex + 1) != u'(') {
startIndex++;
continue;
}
- int endIndex = ret.indexOf(QLatin1Char(')'), startIndex + 2);
+ qsizetype endIndex = ret.indexOf(u')', startIndex + 2);
if (endIndex < 0)
break;
auto envVarName = QStringView{ret}.mid(startIndex + 2, endIndex - startIndex - 2);
QString value = QString::fromLocal8Bit(qgetenv(envVarName.toLocal8Bit().constData()));
ret.replace(startIndex, endIndex - startIndex + 1, value);
- startIndex += value.length();
+ startIndex += value.size();
}
config->endGroup();
@@ -743,70 +584,32 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
}
#endif // settings
-#ifndef QT_BUILD_QMAKE_BOOTSTRAP
if (!fromConf) {
- // "volatile" here is a hack to prevent compilers from doing a
- // compile-time strlen() on "path". The issue is that Qt installers
- // will binary-patch the Qt installation paths -- in such scenarios, Qt
- // will be built with a dummy path, thus the compile-time result of
- // strlen is meaningless.
- const char * volatile path = nullptr;
- if (loc == PrefixPath) {
- ret = getPrefix(
-#ifdef QT_BUILD_QMAKE
- group
-#endif
- );
- } else if (unsigned(loc) <= sizeof(qt_configure_str_offsets)/sizeof(qt_configure_str_offsets[0])) {
- path = qt_configure_strs + qt_configure_str_offsets[loc - 1];
+ if (loc == QLibraryInfo::PrefixPath) {
+ ret = getPrefix(usageMode);
+ } else if (int(loc) <= qt_configure_strs.count()) {
+ ret = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1));
#ifndef Q_OS_WIN // On Windows we use the registry
- } else if (loc == SettingsPath) {
- path = QT_CONFIGURE_SETTINGS_PATH;
+ } else if (loc == QLibraryInfo::SettingsPath) {
+ // Use of volatile is a hack to discourage compilers from calling
+ // strlen(), in the inlined fromLocal8Bit(const char *)'s body, at
+ // compile-time, as Qt installers binary-patch the path, replacing
+ // the dummy path seen at compile-time, typically changing length.
+ const char *volatile path = QT_CONFIGURE_SETTINGS_PATH;
+ ret = QString::fromLocal8Bit(path);
#endif
-# ifdef QT_BUILD_QMAKE
- } else if (loc == HostPrefixPath) {
- static const QByteArray hostPrefixPath = getHostPrefixFromHostBinDir().toLatin1();
- path = hostPrefixPath.constData();
-# endif
}
-
- if (path)
- ret = QString::fromLocal8Bit(path);
}
-#endif
-
-#ifdef QT_BUILD_QMAKE
- // These values aren't actually paths and thus need to be returned verbatim.
- if (loc == TargetSpecPath || loc == HostSpecPath || loc == SysrootifyPrefixPath)
- return ret;
-#endif
if (!ret.isEmpty() && QDir::isRelativePath(ret)) {
QString baseDir;
-#ifdef QT_BUILD_QMAKE
- if (loc == HostPrefixPath || loc == PrefixPath || loc == SysrootPath) {
- // We make the prefix/sysroot path absolute to the executable's directory.
- // loc == PrefixPath while a sysroot is set would make no sense here.
- // loc == SysrootPath only makes sense if qmake lives inside the sysroot itself.
- baseDir = QFileInfo(qmake_libraryInfoFile()).absolutePath();
- } else if (loc > SysrootPath && loc <= LastHostPath) {
- // We make any other host path absolute to the host prefix directory.
- baseDir = rawLocation(HostPrefixPath, group);
- } else {
- // we make any other path absolute to the prefix directory
- baseDir = rawLocation(PrefixPath, group);
- if (group == EffectivePaths)
- sysrootify(&baseDir);
- }
-#else
- if (loc == PrefixPath) {
+ if (loc == QLibraryInfo::PrefixPath) {
baseDir = prefixFromAppDirHelper();
} else {
// we make any other path absolute to the prefix directory
- baseDir = location(PrefixPath);
+ baseDir = path(QLibraryInfo::PrefixPath, usageMode);
}
-#endif // QT_BUILD_QMAKE
- ret = QDir::cleanPath(baseDir + QLatin1Char('/') + ret);
+ ret = QDir::cleanPath(baseDir + u'/' + ret);
}
return ret;
}
@@ -826,75 +629,148 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
QStringList QLibraryInfo::platformPluginArguments(const QString &platformName)
{
-#if !defined(QT_BUILD_QMAKE) && QT_CONFIG(settings)
- QScopedPointer<const QSettings> settings(QLibraryInfoPrivate::findConfiguration());
+#if QT_CONFIG(settings)
+ QScopedPointer<const QSettings> settings(findConfiguration());
if (!settings.isNull()) {
- const QString key = QLatin1String(platformsSection)
- + QLatin1Char('/')
+ const QString key = "Platforms/"_L1
+ platformName
- + QLatin1String("Arguments");
+ + "Arguments"_L1;
return settings->value(key).toStringList();
}
#else
Q_UNUSED(platformName);
-#endif // !QT_BUILD_QMAKE && settings
+#endif // settings
return QStringList();
}
/*!
- \enum QLibraryInfo::LibraryLocation
+ \enum QLibraryInfo::LibraryPath
\keyword library location
- This enum type is used to specify a specific location
- specifier:
+ This enum type is used to query for a specific path:
\value PrefixPath The default prefix for all paths.
- \value DocumentationPath The location for documentation upon install.
- \value HeadersPath The location for all headers.
- \value LibrariesPath The location of installed libraries.
- \value LibraryExecutablesPath The location of installed executables required by libraries at runtime.
- \value BinariesPath The location of installed Qt binaries (tools and applications).
- \value PluginsPath The location of installed Qt plugins.
- \value Qml2ImportsPath The location of installed QML extensions to import (QML 2.x).
- \value ArchDataPath The location of general architecture-dependent Qt data.
- \value DataPath The location of general architecture-independent Qt data.
- \value TranslationsPath The location of translation information for Qt strings.
- \value ExamplesPath The location for examples upon install.
- \value TestsPath The location of installed Qt testcases.
- \value SettingsPath The location for Qt settings. Not applicable on Windows.
-
- \sa location()
+ \value DocumentationPath The path to documentation upon install.
+ \value HeadersPath The path to all headers.
+ \value LibrariesPath The path to installed libraries.
+ \value LibraryExecutablesPath The path to installed executables required by libraries at runtime.
+ \value BinariesPath The path to installed Qt binaries (tools and applications).
+ \value PluginsPath The path to installed Qt plugins.
+ \value QmlImportsPath The path to installed QML extensions to import.
+ \value Qml2ImportsPath This value is deprecated. Use QmlImportsPath instead.
+ \value ArchDataPath The path to general architecture-dependent Qt data.
+ \value DataPath The path to general architecture-independent Qt data.
+ \value TranslationsPath The path to translation information for Qt strings.
+ \value ExamplesPath The path to examples upon install.
+ \value TestsPath The path to installed Qt testcases.
+ \value SettingsPath The path to Qt settings. Not applicable on Windows.
+
+ \sa path()
*/
+/*!
+ \typealias QLibraryInfo::LibraryLocation
+ \deprecated Use LibraryPath with QLibraryInfo::path() instead.
+*/
+
+/*!
+ \macro QT_VERSION_STR
+ \relates <QtVersion>
+
+ This macro expands to a string that specifies Qt's version number (for
+ example, "6.1.2"). This is the version with which the application is
+ compiled. This may be a different version than the version the application
+ will find itself using at \e runtime.
+
+ \sa qVersion(), QT_VERSION
+*/
+
+/*!
+ \relates <QtVersion>
+
+ Returns the version number of Qt at runtime as a string (for example,
+ "6.1.2"). This is the version of the Qt library in use at \e runtime,
+ which need not be the version the application was \e compiled with.
+
+ \sa QT_VERSION_STR, QLibraryInfo::version()
+*/
+
+const char *qVersion() noexcept
+{
+ return QT_VERSION_STR;
+}
+
+#if QT_DEPRECATED_SINCE(6, 9)
+
+bool qSharedBuild() noexcept
+{
+ return QLibraryInfo::isSharedBuild();
+}
+
+#endif // QT_DEPRECATED_SINCE(6, 9)
+
QT_END_NAMESPACE
#if defined(Q_CC_GNU) && defined(ELF_INTERPRETER)
+# include <elf.h>
# include <stdio.h>
# include <stdlib.h>
#include "private/qcoreapplication_p.h"
+QT_WARNING_DISABLE_GCC("-Wformat-overflow")
QT_WARNING_DISABLE_GCC("-Wattributes")
QT_WARNING_DISABLE_CLANG("-Wattributes")
QT_WARNING_DISABLE_INTEL(2621)
+# if defined(Q_OS_LINUX)
+# include "minimum-linux_p.h"
+# endif
+# ifdef QT_ELF_NOTE_OS_TYPE
+struct ElfNoteAbiTag
+{
+ static_assert(sizeof(Elf32_Nhdr) == sizeof(Elf64_Nhdr),
+ "The size of an ELF note is wrong (should be 12 bytes)");
+ struct Payload {
+ Elf32_Word ostype = QT_ELF_NOTE_OS_TYPE;
+ Elf32_Word major = QT_ELF_NOTE_OS_MAJOR;
+ Elf32_Word minor = QT_ELF_NOTE_OS_MINOR;
+# ifdef QT_ELF_NOTE_OS_PATCH
+ Elf32_Word patch = QT_ELF_NOTE_OS_PATCH;
+# endif
+ };
+
+ Elf32_Nhdr header = {
+ .n_namesz = sizeof(name),
+ .n_descsz = sizeof(Payload),
+ .n_type = NT_GNU_ABI_TAG
+ };
+ char name[sizeof ELF_NOTE_GNU] = ELF_NOTE_GNU; // yes, include the null terminator
+ Payload payload = {};
+};
+__attribute__((section(".note.ABI-tag"), aligned(4), used))
+extern constexpr ElfNoteAbiTag QT_MANGLE_NAMESPACE(qt_abi_tag) = {};
+# endif
+
extern const char qt_core_interpreter[] __attribute__((section(".interp")))
= ELF_INTERPRETER;
extern "C" void qt_core_boilerplate() __attribute__((force_align_arg_pointer));
void qt_core_boilerplate()
{
- printf("This is the QtCore library version " QT_BUILD_STR "\n"
- "Copyright (C) 2016 The Qt Company Ltd.\n"
- "Contact: http://www.qt.io/licensing/\n"
+ printf("This is the QtCore library version %s\n"
+ "%s\n"
+ "Contact: https://www.qt.io/licensing/\n"
"\n"
"Installation prefix: %s\n"
"Library path: %s\n"
"Plugin path: %s\n",
- qt_configure_prefix_path_str + 12,
- qt_configure_strs + qt_configure_str_offsets[QT_PREPEND_NAMESPACE(QLibraryInfo)::LibrariesPath - 1],
- qt_configure_strs + qt_configure_str_offsets[QT_PREPEND_NAMESPACE(QLibraryInfo)::PluginsPath - 1]);
+ QT_PREPEND_NAMESPACE(qt_build_string)(),
+ QT_COPYRIGHT,
+ QT_CONFIGURE_PREFIX_PATH,
+ qt_configure_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::LibrariesPath - 1],
+ qt_configure_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::PluginsPath - 1]);
QT_PREPEND_NAMESPACE(qDumpCPUFeatures)();
diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h
index 4a14a9728a..d4e8f8b050 100644
--- a/src/corelib/global/qlibraryinfo.h
+++ b/src/corelib/global/qlibraryinfo.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLIBRARYINFO_H
#define QLIBRARYINFO_H
@@ -46,21 +10,19 @@
QT_BEGIN_NAMESPACE
-class QStringList;
-
class Q_CORE_EXPORT QLibraryInfo
{
public:
- static const char * build() noexcept;
+ static const char *build() noexcept;
- static bool isDebugBuild();
+ [[nodiscard]] static bool isDebugBuild() noexcept Q_DECL_CONST_FUNCTION;
+ [[nodiscard]] static bool isSharedBuild() noexcept Q_DECL_CONST_FUNCTION;
#ifndef QT_BOOTSTRAPPED
static QVersionNumber version() noexcept Q_DECL_CONST_FUNCTION;
#endif
- enum LibraryLocation
- {
+ enum LibraryPath {
PrefixPath = 0,
DocumentationPath,
HeadersPath,
@@ -68,42 +30,37 @@ public:
LibraryExecutablesPath,
BinariesPath,
PluginsPath,
- Qml2ImportsPath,
+ QmlImportsPath,
+ Qml2ImportsPath = QmlImportsPath,
ArchDataPath,
DataPath,
TranslationsPath,
ExamplesPath,
TestsPath,
// Insert new values above this line
- // Please read the comments in qlibraryinfo.cpp before adding
-#ifdef QT_BUILD_QMAKE
- // These are not subject to binary compatibility constraints
- SysrootPath,
- SysrootifyPrefixPath,
- HostBinariesPath,
- HostLibrariesPath,
- HostDataPath,
- TargetSpecPath,
- HostSpecPath,
- HostPrefixPath,
- LastHostPath = HostPrefixPath,
-#endif
+ // Please read the comments in qconfig.cpp.in before adding
SettingsPath = 100
};
- static QString location(LibraryLocation); // ### Qt 6: consider renaming it to path()
-#ifdef QT_BUILD_QMAKE
- enum PathGroup { FinalPaths, EffectivePaths, EffectiveSourcePaths, DevicePaths };
- static QString rawLocation(LibraryLocation, PathGroup);
- static void reload();
- static void sysrootify(QString *path);
+ static QString path(LibraryPath p);
+#if QT_DEPRECATED_SINCE(6, 0)
+ using LibraryLocation = LibraryPath;
+ QT_DEPRECATED_VERSION_X_6_0("Use path()")
+ static QString location(LibraryLocation location)
+ { return path(location); }
#endif
-
static QStringList platformPluginArguments(const QString &platformName);
private:
QLibraryInfo();
};
+#if QT_DEPRECATED_SINCE(6, 9)
+
+QT_DEPRECATED_VERSION_X_6_9("Use QLibraryInfo::isSharedBuild() instead.")
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() noexcept;
+
+#endif
+
QT_END_NAMESPACE
#endif // QLIBRARYINFO_H
diff --git a/src/corelib/global/qlibraryinfo_p.h b/src/corelib/global/qlibraryinfo_p.h
new file mode 100644
index 0000000000..4b471b932e
--- /dev/null
+++ b/src/corelib/global/qlibraryinfo_p.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QLIBRARYINFO_P_H
+#define QLIBRARYINFO_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qlibraryinfo.h"
+#include "QtCore/private/qglobal_p.h"
+
+#if QT_CONFIG(settings)
+# include "QtCore/qsettings.h"
+#endif
+#include "QtCore/qstring.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QLibraryInfoPrivate final
+{
+public:
+#if QT_CONFIG(settings)
+ static QSettings *configuration();
+ static void reload();
+ static void setQtconfManualPath(const QString *qtconfManualPath);
+#endif
+
+ struct LocationInfo
+ {
+ QString key;
+ QString defaultValue;
+ QString fallbackKey;
+ };
+
+ static LocationInfo locationInfo(QLibraryInfo::LibraryPath loc);
+
+ enum UsageMode {
+ RegularUsage,
+ UsedFromQtBinDir
+ };
+
+ static QString path(QLibraryInfo::LibraryPath p, UsageMode usageMode = RegularUsage);
+};
+
+QT_END_NAMESPACE
+
+#endif // QLIBRARYINFO_P_H
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 5c17679fb1..dec16e4a77 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal_p.h"
#include "qlogging.h"
@@ -53,12 +17,12 @@
#include "qloggingcategory.h"
#ifndef QT_BOOTSTRAPPED
#include "qelapsedtimer.h"
+#include "qdeadlinetimer.h"
#include "qdatetime.h"
#include "qcoreapplication.h"
#include "qthread.h"
#include "private/qloggingregistry_p.h"
#include "private/qcoreapplication_p.h"
-#include "private/qsimd_p.h"
#include <qtcore_tracepoints_p.h>
#endif
#ifdef Q_OS_WIN
@@ -105,17 +69,19 @@
extern char *__progname;
#endif
-#ifndef QT_BOOTSTRAPPED
-#if QT_CONFIG(regularexpression)
-# ifdef __UCLIBC__
-# if __UCLIBC_HAS_BACKTRACE__
-# define QLOGGING_HAVE_BACKTRACE
-# endif
-# elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (__has_include(<cxxabi.h>) && __has_include(<execinfo.h>))
-# define QLOGGING_HAVE_BACKTRACE
-# endif
+#ifdef QLOGGING_HAVE_BACKTRACE
+# include <qregularexpression.h>
#endif
+#ifdef QLOGGING_USE_EXECINFO_BACKTRACE
+# if QT_CONFIG(dladdr)
+# include <dlfcn.h>
+# endif
+# include BACKTRACE_HEADER
+# include <cxxabi.h>
+#endif // QLOGGING_USE_EXECINFO_BACKTRACE
+
+#ifndef QT_BOOTSTRAPPED
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || __has_include(<sys/syscall.h>))
# include <sys/syscall.h>
@@ -151,12 +117,6 @@ static QT_PREPEND_NAMESPACE(qint64) qt_gettid()
return qintptr(QThread::currentThreadId());
}
#endif
-
-#ifdef QLOGGING_HAVE_BACKTRACE
-# include <qregularexpression.h>
-# include <cxxabi.h>
-# include <execinfo.h>
-#endif
#endif // !QT_BOOTSTRAPPED
#include <cstdlib>
@@ -168,12 +128,51 @@ static QT_PREPEND_NAMESPACE(qint64) qt_gettid()
QT_BEGIN_NAMESPACE
-#if !defined(Q_CC_MSVC)
+using namespace Qt::StringLiterals;
+
+#ifndef QT_BOOTSTRAPPED
+Q_TRACE_POINT(qtcore, qt_message_print, int type, const char *category, const char *function, const char *file, int line, const QString &message);
+#endif
+
+/*!
+ \headerfile <QtLogging>
+ \inmodule QtCore
+ \title Qt Logging Types
+
+ \brief The <QtLogging> header file defines Qt logging types, functions
+ and macros.
+
+ The <QtLogging> header file contains several types, functions and
+ macros for logging.
+
+ The QtMsgType enum identifies the various messages that can be generated
+ and sent to a Qt message handler; QtMessageHandler is a type definition for
+ a pointer to a function with the signature
+ \c {void myMessageHandler(QtMsgType, const QMessageLogContext &, const char *)}.
+ qInstallMessageHandler() function can be used to install the given
+ QtMessageHandler. QMessageLogContext class contains the line, file, and
+ function the message was logged at. This information is created by the
+ QMessageLogger class.
+
+ <QtLogging> also contains functions that generate messages from the
+ given string argument: qDebug(), qInfo(), qWarning(), qCritical(),
+ and qFatal(). These functions call the message handler
+ with the given message.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 4
+*/
+
+template <typename String>
+#if !defined(Q_CC_MSVC_ONLY)
Q_NORETURN
#endif
-static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message);
+static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, String &&message);
static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message);
-static void qt_message_print(const QString &message);
+static void preformattedMessageHandler(QtMsgType type, const QMessageLogContext &context,
+ const QString &formattedMessage);
+static QString formatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str);
static int checked_var_value(const char *varname)
{
@@ -189,6 +188,17 @@ static int checked_var_value(const char *varname)
return ok ? value : 1;
}
+static bool is_fatal_count_down(QAtomicInt &n)
+{
+ // it's fatal if the current value is exactly 1,
+ // otherwise decrement if it's non-zero
+
+ int v = n.loadRelaxed();
+ while (v != 0 && !n.testAndSetRelaxed(v, v - 1, v))
+ qYieldCpu();
+ return v == 1; // we exited the loop, so either v == 0 or CAS succeeded to set n from v to v-1
+}
+
static bool isFatal(QtMsgType msgType)
{
if (msgType == QtFatalMsg)
@@ -196,28 +206,17 @@ static bool isFatal(QtMsgType msgType)
if (msgType == QtCriticalMsg) {
static QAtomicInt fatalCriticals = checked_var_value("QT_FATAL_CRITICALS");
-
- // it's fatal if the current value is exactly 1,
- // otherwise decrement if it's non-zero
- return fatalCriticals.loadRelaxed() && fatalCriticals.fetchAndAddRelaxed(-1) == 1;
+ return is_fatal_count_down(fatalCriticals);
}
if (msgType == QtWarningMsg || msgType == QtCriticalMsg) {
static QAtomicInt fatalWarnings = checked_var_value("QT_FATAL_WARNINGS");
-
- // it's fatal if the current value is exactly 1,
- // otherwise decrement if it's non-zero
- return fatalWarnings.loadRelaxed() && fatalWarnings.fetchAndAddRelaxed(-1) == 1;
+ return is_fatal_count_down(fatalWarnings);
}
return false;
}
-static bool isDefaultCategory(const char *category)
-{
- return !category || strcmp(category, "default") == 0;
-}
-
/*!
Returns true if writing to \c stderr is supported.
@@ -229,6 +228,8 @@ static bool systemHasStderr()
return true;
}
+#ifndef Q_OS_WASM
+
/*!
Returns true if writing to \c stderr will end up in a console/terminal visible to the user.
@@ -313,6 +314,8 @@ bool shouldLogToStderr()
using namespace QtPrivate;
+#endif // ifndef Q_OS_WASM
+
/*!
\class QMessageLogContext
\inmodule QtCore
@@ -347,7 +350,7 @@ using namespace QtPrivate;
\sa QMessageLogContext, qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
*/
-#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
+#if defined(Q_CC_MSVC_ONLY) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const char *s) noexcept
{
size_t len = qstrlen(s);
@@ -368,14 +371,15 @@ static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const cha
\internal
*/
Q_NEVER_INLINE
-static QString qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg, va_list ap)
+static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg, va_list ap)
{
QString buf = QString::vasprintf(msg, ap);
qt_message_print(msgType, context, buf);
- return buf;
+
+ if (isFatal(msgType))
+ qt_message_fatal(msgType, context, buf);
}
-#undef qDebug
/*!
Logs a debug message specified with format \a msg. Additional
parameters, specified by \a msg, may be used.
@@ -384,17 +388,13 @@ static QString qt_message(QtMsgType msgType, const QMessageLogContext &context,
*/
void QMessageLogger::debug(const char *msg, ...) const
{
+ QInternalMessageLogContext ctxt(context);
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtDebugMsg, context, msg, ap);
+ qt_message(QtDebugMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtDebugMsg))
- qt_message_fatal(QtDebugMsg, context, message);
}
-
-#undef qInfo
/*!
Logs an informational message specified with format \a msg. Additional
parameters, specified by \a msg, may be used.
@@ -404,13 +404,11 @@ void QMessageLogger::debug(const char *msg, ...) const
*/
void QMessageLogger::info(const char *msg, ...) const
{
+ QInternalMessageLogContext ctxt(context);
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtInfoMsg, context, msg, ap);
+ qt_message(QtInfoMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtInfoMsg))
- qt_message_fatal(QtInfoMsg, context, message);
}
/*!
@@ -421,8 +419,8 @@ void QMessageLogger::info(const char *msg, ...) const
\snippet code/qlogging/qlogging.cpp 2
- A function which this signature is generated by Q_DECLARE_LOGGING_CATEGORY,
- Q_LOGGING_CATEGORY.
+ The \c Q_DECLARE_LOGGING_CATEGORY macro generates a function declaration
+ with this signature, and \c Q_LOGGING_CATEGORY generates its definition.
\since 5.3
*/
@@ -439,17 +437,12 @@ void QMessageLogger::debug(const QLoggingCategory &cat, const char *msg, ...) co
if (!cat.isDebugEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtDebugMsg, ctxt, msg, ap);
+ qt_message(QtDebugMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtDebugMsg))
- qt_message_fatal(QtDebugMsg, ctxt, message);
}
/*!
@@ -466,17 +459,12 @@ void QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc,
if (!cat.isDebugEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtDebugMsg, ctxt, msg, ap);
+ qt_message(QtDebugMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtDebugMsg))
- qt_message_fatal(QtDebugMsg, ctxt, message);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -550,17 +538,12 @@ void QMessageLogger::info(const QLoggingCategory &cat, const char *msg, ...) con
if (!cat.isInfoEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtInfoMsg, ctxt, msg, ap);
+ qt_message(QtInfoMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtInfoMsg))
- qt_message_fatal(QtInfoMsg, ctxt, message);
}
/*!
@@ -577,17 +560,12 @@ void QMessageLogger::info(QMessageLogger::CategoryFunction catFunc,
if (!cat.isInfoEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtInfoMsg, ctxt, msg, ap);
+ qt_message(QtInfoMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtInfoMsg))
- qt_message_fatal(QtInfoMsg, ctxt, message);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -638,7 +616,6 @@ QDebug QMessageLogger::info(QMessageLogger::CategoryFunction catFunc) const
#endif
-#undef qWarning
/*!
Logs a warning message specified with format \a msg. Additional
parameters, specified by \a msg, may be used.
@@ -647,13 +624,11 @@ QDebug QMessageLogger::info(QMessageLogger::CategoryFunction catFunc) const
*/
void QMessageLogger::warning(const char *msg, ...) const
{
+ QInternalMessageLogContext ctxt(context);
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtWarningMsg, context, msg, ap);
+ qt_message(QtWarningMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtWarningMsg))
- qt_message_fatal(QtWarningMsg, context, message);
}
/*!
@@ -668,17 +643,12 @@ void QMessageLogger::warning(const QLoggingCategory &cat, const char *msg, ...)
if (!cat.isWarningEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtWarningMsg, ctxt, msg, ap);
+ qt_message(QtWarningMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtWarningMsg))
- qt_message_fatal(QtWarningMsg, ctxt, message);
}
/*!
@@ -695,17 +665,12 @@ void QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc,
if (!cat.isWarningEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtWarningMsg, ctxt, msg, ap);
+ qt_message(QtWarningMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtWarningMsg))
- qt_message_fatal(QtWarningMsg, ctxt, message);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -753,8 +718,6 @@ QDebug QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc) const
#endif
-#undef qCritical
-
/*!
Logs a critical message specified with format \a msg. Additional
parameters, specified by \a msg, may be used.
@@ -763,13 +726,11 @@ QDebug QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc) const
*/
void QMessageLogger::critical(const char *msg, ...) const
{
+ QInternalMessageLogContext ctxt(context);
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtCriticalMsg, context, msg, ap);
+ qt_message(QtCriticalMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtCriticalMsg))
- qt_message_fatal(QtCriticalMsg, context, message);
}
/*!
@@ -784,17 +745,12 @@ void QMessageLogger::critical(const QLoggingCategory &cat, const char *msg, ...)
if (!cat.isCriticalEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtCriticalMsg, ctxt, msg, ap);
+ qt_message(QtCriticalMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtCriticalMsg))
- qt_message_fatal(QtCriticalMsg, ctxt, message);
}
/*!
@@ -811,17 +767,12 @@ void QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc,
if (!cat.isCriticalEnabled())
return;
- QMessageLogContext ctxt;
- ctxt.copyContextFrom(context);
- ctxt.category = cat.categoryName();
+ QInternalMessageLogContext ctxt(context, cat());
va_list ap;
va_start(ap, msg); // use variable arg list
- const QString message = qt_message(QtCriticalMsg, ctxt, msg, ap);
+ qt_message(QtCriticalMsg, ctxt, msg, ap);
va_end(ap);
-
- if (isFatal(QtCriticalMsg))
- qt_message_fatal(QtCriticalMsg, ctxt, message);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -870,7 +821,51 @@ QDebug QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc) const
#endif
-#undef qFatal
+/*!
+ Logs a fatal message specified with format \a msg for the context \a cat.
+ Additional parameters, specified by \a msg, may be used.
+
+ \since 6.5
+ \sa qCFatal()
+*/
+void QMessageLogger::fatal(const QLoggingCategory &cat, const char *msg, ...) const noexcept
+{
+ QInternalMessageLogContext ctxt(context, cat());
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, ctxt, msg, ap));
+ va_end(ap);
+
+#ifndef Q_CC_MSVC_ONLY
+ Q_UNREACHABLE();
+#endif
+}
+
+/*!
+ Logs a fatal message specified with format \a msg for the context returned
+ by \a catFunc. Additional parameters, specified by \a msg, may be used.
+
+ \since 6.5
+ \sa qCFatal()
+*/
+void QMessageLogger::fatal(QMessageLogger::CategoryFunction catFunc,
+ const char *msg, ...) const noexcept
+{
+ const QLoggingCategory &cat = (*catFunc)();
+
+ QInternalMessageLogContext ctxt(context, cat());
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, ctxt, msg, ap));
+ va_end(ap);
+
+#ifndef Q_CC_MSVC_ONLY
+ Q_UNREACHABLE();
+#endif
+}
+
/*!
Logs a fatal message specified with format \a msg. Additional
parameters, specified by \a msg, may be used.
@@ -879,14 +874,66 @@ QDebug QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc) const
*/
void QMessageLogger::fatal(const char *msg, ...) const noexcept
{
- QString message;
-
+ QInternalMessageLogContext ctxt(context);
va_list ap;
va_start(ap, msg); // use variable arg list
- QT_TERMINATE_ON_EXCEPTION(message = qt_message(QtFatalMsg, context, msg, ap));
+ QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, ctxt, msg, ap));
va_end(ap);
- qt_message_fatal(QtFatalMsg, context, message);
+#ifndef Q_CC_MSVC_ONLY
+ Q_UNREACHABLE();
+#endif
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ Logs a fatal message using a QDebug stream.
+
+ \since 6.5
+
+ \sa qFatal(), QDebug
+*/
+QDebug QMessageLogger::fatal() const
+{
+ QDebug dbg = QDebug(QtFatalMsg);
+ QMessageLogContext &ctxt = dbg.stream->context;
+ ctxt.copyContextFrom(context);
+ return dbg;
+}
+
+/*!
+ Logs a fatal message into category \a cat using a QDebug stream.
+
+ \since 6.5
+ \sa qCFatal(), QDebug
+*/
+QDebug QMessageLogger::fatal(const QLoggingCategory &cat) const
+{
+ QDebug dbg = QDebug(QtFatalMsg);
+
+ QMessageLogContext &ctxt = dbg.stream->context;
+ ctxt.copyContextFrom(context);
+ ctxt.category = cat.categoryName();
+
+ return dbg;
+}
+
+/*!
+ Logs a fatal message into category returned by \a catFunc using a QDebug stream.
+
+ \since 6.5
+ \sa qCFatal(), QDebug
+*/
+QDebug QMessageLogger::fatal(QMessageLogger::CategoryFunction catFunc) const
+{
+ return fatal((*catFunc)());
+}
+#endif // QT_NO_DEBUG_STREAM
+
+#if !defined(QT_BOOTSTRAPPED)
+static bool isDefaultCategory(const char *category)
+{
+ return !category || strcmp(category, "default") == 0;
}
/*!
@@ -901,15 +948,20 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
if (info.isEmpty())
return info;
- int pos;
+ qsizetype pos;
// Skip trailing [with XXX] for templates (gcc), but make
// sure to not affect Objective-C message names.
pos = info.size() - 1;
if (info.endsWith(']') && !(info.startsWith('+') || info.startsWith('-'))) {
while (--pos) {
- if (info.at(pos) == '[')
- info.truncate(pos);
+ if (info.at(pos) == '[') {
+ info.truncate(pos);
+ break;
+ }
+ }
+ if (info.endsWith(' ')) {
+ info.chop(1);
}
}
@@ -923,14 +975,21 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
// canonize operator names
info.replace("operator ", "operator");
+ pos = -1;
// remove argument list
forever {
int parencount = 0;
- pos = info.lastIndexOf(')');
+ pos = info.lastIndexOf(')', pos);
if (pos == -1) {
// Don't know how to parse this function name
return info;
}
+ if (info.indexOf('>', pos) != -1
+ || info.indexOf(':', pos) != -1) {
+ // that wasn't the function argument list.
+ --pos;
+ continue;
+ }
// find the beginning of the argument list
--pos;
@@ -948,7 +1007,7 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
info.truncate(++pos);
if (info.at(pos - 1) == ')') {
- if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
+ if (info.indexOf(operator_call) == pos - qsizetype(strlen(operator_call)))
break;
// this function returns a pointer to a function
@@ -971,19 +1030,19 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
if (pos > -1) {
switch (info.at(pos)) {
case ')':
- if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
+ if (info.indexOf(operator_call) == pos - qsizetype(strlen(operator_call)) + 1)
pos -= 2;
break;
case '<':
- if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
+ if (info.indexOf(operator_lessThan) == pos - qsizetype(strlen(operator_lessThan)) + 1)
--pos;
break;
case '>':
- if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
+ if (info.indexOf(operator_greaterThan) == pos - qsizetype(strlen(operator_greaterThan)) + 1)
--pos;
break;
case '=': {
- int operatorLength = (int)strlen(operator_lessThanEqual);
+ auto operatorLength = qsizetype(strlen(operator_lessThanEqual));
if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
pos -= 2;
else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
@@ -1027,7 +1086,7 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
break;
// find the matching close
- int end = pos;
+ qsizetype end = pos;
templatecount = 1;
--pos;
while (pos && templatecount) {
@@ -1069,8 +1128,8 @@ static const char emptyTokenC[] = "";
static const char defaultPattern[] = "%{if-category}%{category}: %{endif}%{message}";
-
-struct QMessagePattern {
+struct QMessagePattern
+{
QMessagePattern();
~QMessagePattern();
@@ -1078,27 +1137,29 @@ struct QMessagePattern {
// 0 terminated arrays of literal tokens / literal or placeholder tokens
std::unique_ptr<std::unique_ptr<const char[]>[]> literals;
- std::unique_ptr<const char*[]> tokens;
- QList<QString> timeArgs; // timeFormats in sequence of %{time
+ std::unique_ptr<const char *[]> tokens;
+ QList<QString> timeArgs; // timeFormats in sequence of %{time
#ifndef QT_BOOTSTRAPPED
QElapsedTimer timer;
#endif
#ifdef QLOGGING_HAVE_BACKTRACE
- struct BacktraceParams {
+ struct BacktraceParams
+ {
QString backtraceSeparator;
int backtraceDepth;
};
- QList<BacktraceParams> backtraceArgs; // backtrace argumens in sequence of %{backtrace
+ QList<BacktraceParams> backtraceArgs; // backtrace arguments in sequence of %{backtrace
+ int maxBacktraceDepth = 0;
#endif
bool fromEnvironment;
static QBasicMutex mutex;
};
#ifdef QLOGGING_HAVE_BACKTRACE
-Q_DECLARE_TYPEINFO(QMessagePattern::BacktraceParams, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMessagePattern::BacktraceParams, Q_RELOCATABLE_TYPE);
#endif
-QBasicMutex QMessagePattern::mutex;
+Q_CONSTINIT QBasicMutex QMessagePattern::mutex;
QMessagePattern::QMessagePattern()
{
@@ -1107,7 +1168,7 @@ QMessagePattern::QMessagePattern()
#endif
const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
if (envPattern.isEmpty()) {
- setPattern(QLatin1String(defaultPattern));
+ setPattern(QLatin1StringView(defaultPattern));
fromEnvironment = false;
} else {
setPattern(envPattern);
@@ -1115,14 +1176,14 @@ QMessagePattern::QMessagePattern()
}
}
-QMessagePattern::~QMessagePattern()
- = default;
+QMessagePattern::~QMessagePattern() = default;
void QMessagePattern::setPattern(const QString &pattern)
{
timeArgs.clear();
#ifdef QLOGGING_HAVE_BACKTRACE
backtraceArgs.clear();
+ maxBacktraceDepth = 0;
#endif
// scanner
@@ -1131,10 +1192,9 @@ void QMessagePattern::setPattern(const QString &pattern)
bool inPlaceholder = false;
for (int i = 0; i < pattern.size(); ++i) {
const QChar c = pattern.at(i);
- if ((c == QLatin1Char('%'))
- && !inPlaceholder) {
+ if (c == u'%' && !inPlaceholder) {
if ((i + 1 < pattern.size())
- && pattern.at(i + 1) == QLatin1Char('{')) {
+ && pattern.at(i + 1) == u'{') {
// beginning of placeholder
if (!lexeme.isEmpty()) {
lexemes.append(lexeme);
@@ -1146,7 +1206,7 @@ void QMessagePattern::setPattern(const QString &pattern)
lexeme.append(c);
- if ((c == QLatin1Char('}') && inPlaceholder)) {
+ if (c == u'}' && inPlaceholder) {
// end of placeholder
lexemes.append(lexeme);
lexeme.clear();
@@ -1158,7 +1218,7 @@ void QMessagePattern::setPattern(const QString &pattern)
// tokenizer
std::vector<std::unique_ptr<const char[]>> literalsVar;
- tokens.reset(new const char*[lexemes.size() + 1]);
+ tokens.reset(new const char *[lexemes.size() + 1]);
tokens[lexemes.size()] = nullptr;
bool nestedIfError = false;
@@ -1167,37 +1227,36 @@ void QMessagePattern::setPattern(const QString &pattern)
for (int i = 0; i < lexemes.size(); ++i) {
const QString lexeme = lexemes.at(i);
- if (lexeme.startsWith(QLatin1String("%{"))
- && lexeme.endsWith(QLatin1Char('}'))) {
+ if (lexeme.startsWith("%{"_L1) && lexeme.endsWith(u'}')) {
// placeholder
- if (lexeme == QLatin1String(typeTokenC)) {
+ if (lexeme == QLatin1StringView(typeTokenC)) {
tokens[i] = typeTokenC;
- } else if (lexeme == QLatin1String(categoryTokenC))
+ } else if (lexeme == QLatin1StringView(categoryTokenC))
tokens[i] = categoryTokenC;
- else if (lexeme == QLatin1String(messageTokenC))
+ else if (lexeme == QLatin1StringView(messageTokenC))
tokens[i] = messageTokenC;
- else if (lexeme == QLatin1String(fileTokenC))
+ else if (lexeme == QLatin1StringView(fileTokenC))
tokens[i] = fileTokenC;
- else if (lexeme == QLatin1String(lineTokenC))
+ else if (lexeme == QLatin1StringView(lineTokenC))
tokens[i] = lineTokenC;
- else if (lexeme == QLatin1String(functionTokenC))
+ else if (lexeme == QLatin1StringView(functionTokenC))
tokens[i] = functionTokenC;
- else if (lexeme == QLatin1String(pidTokenC))
+ else if (lexeme == QLatin1StringView(pidTokenC))
tokens[i] = pidTokenC;
- else if (lexeme == QLatin1String(appnameTokenC))
+ else if (lexeme == QLatin1StringView(appnameTokenC))
tokens[i] = appnameTokenC;
- else if (lexeme == QLatin1String(threadidTokenC))
+ else if (lexeme == QLatin1StringView(threadidTokenC))
tokens[i] = threadidTokenC;
- else if (lexeme == QLatin1String(qthreadptrTokenC))
+ else if (lexeme == QLatin1StringView(qthreadptrTokenC))
tokens[i] = qthreadptrTokenC;
- else if (lexeme.startsWith(QLatin1String(timeTokenC))) {
+ else if (lexeme.startsWith(QLatin1StringView(timeTokenC))) {
tokens[i] = timeTokenC;
- int spaceIdx = lexeme.indexOf(QChar::fromLatin1(' '));
+ qsizetype spaceIdx = lexeme.indexOf(QChar::fromLatin1(' '));
if (spaceIdx > 0)
- timeArgs.append(lexeme.mid(spaceIdx + 1, lexeme.length() - spaceIdx - 2));
+ timeArgs.append(lexeme.mid(spaceIdx + 1, lexeme.size() - spaceIdx - 2));
else
timeArgs.append(QString());
- } else if (lexeme.startsWith(QLatin1String(backtraceTokenC))) {
+ } else if (lexeme.startsWith(QLatin1StringView(backtraceTokenC))) {
#ifdef QLOGGING_HAVE_BACKTRACE
tokens[i] = backtraceTokenC;
QString backtraceSeparator = QStringLiteral("|");
@@ -1208,7 +1267,7 @@ void QMessagePattern::setPattern(const QString &pattern)
if (m.hasMatch()) {
int depth = m.capturedView(1).toInt();
if (depth <= 0)
- error += QLatin1String("QT_MESSAGE_PATTERN: %{backtrace} depth must be a number greater than 0\n");
+ error += "QT_MESSAGE_PATTERN: %{backtrace} depth must be a number greater than 0\n"_L1;
else
backtraceDepth = depth;
}
@@ -1219,14 +1278,15 @@ void QMessagePattern::setPattern(const QString &pattern)
backtraceParams.backtraceDepth = backtraceDepth;
backtraceParams.backtraceSeparator = backtraceSeparator;
backtraceArgs.append(backtraceParams);
+ maxBacktraceDepth = qMax(maxBacktraceDepth, backtraceDepth);
#else
- error += QLatin1String("QT_MESSAGE_PATTERN: %{backtrace} is not supported by this Qt build\n");
+ error += "QT_MESSAGE_PATTERN: %{backtrace} is not supported by this Qt build\n"_L1;
tokens[i] = "";
#endif
}
#define IF_TOKEN(LEVEL) \
- else if (lexeme == QLatin1String(LEVEL)) { \
+ else if (lexeme == QLatin1StringView(LEVEL)) { \
if (inIf) \
nestedIfError = true; \
tokens[i] = LEVEL; \
@@ -1239,50 +1299,187 @@ void QMessagePattern::setPattern(const QString &pattern)
IF_TOKEN(ifCriticalTokenC)
IF_TOKEN(ifFatalTokenC)
#undef IF_TOKEN
- else if (lexeme == QLatin1String(endifTokenC)) {
+ else if (lexeme == QLatin1StringView(endifTokenC)) {
tokens[i] = endifTokenC;
if (!inIf && !nestedIfError)
- error += QLatin1String("QT_MESSAGE_PATTERN: %{endif} without an %{if-*}\n");
+ error += "QT_MESSAGE_PATTERN: %{endif} without an %{if-*}\n"_L1;
inIf = false;
} else {
tokens[i] = emptyTokenC;
- error += QStringLiteral("QT_MESSAGE_PATTERN: Unknown placeholder %1\n")
- .arg(lexeme);
+ error += "QT_MESSAGE_PATTERN: Unknown placeholder "_L1 + lexeme + '\n'_L1;
}
} else {
- char *literal = new char[lexeme.size() + 1];
- strncpy(literal, lexeme.toLatin1().constData(), lexeme.size());
- literal[lexeme.size()] = '\0';
- literalsVar.emplace_back(literal);
- tokens[i] = literal;
+ using UP = std::unique_ptr<char[]>;
+ tokens[i] = literalsVar.emplace_back(UP(qstrdup(lexeme.toLatin1().constData()))).get();
}
}
if (nestedIfError)
- error += QLatin1String("QT_MESSAGE_PATTERN: %{if-*} cannot be nested\n");
+ error += "QT_MESSAGE_PATTERN: %{if-*} cannot be nested\n"_L1;
else if (inIf)
- error += QLatin1String("QT_MESSAGE_PATTERN: missing %{endif}\n");
+ error += "QT_MESSAGE_PATTERN: missing %{endif}\n"_L1;
+
+ if (!error.isEmpty()) {
+ // remove the last '\n' because the sinks deal with that on their own
+ error.chop(1);
- if (!error.isEmpty())
- qt_message_print(error);
+ QMessageLogContext ctx(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE,
+ "QMessagePattern::setPattern", nullptr);
+ preformattedMessageHandler(QtWarningMsg, ctx, error);
+ }
literals.reset(new std::unique_ptr<const char[]>[literalsVar.size() + 1]);
std::move(literalsVar.begin(), literalsVar.end(), &literals[0]);
}
-#if defined(QLOGGING_HAVE_BACKTRACE) && !defined(QT_BOOTSTRAPPED)
+#if defined(QLOGGING_HAVE_BACKTRACE)
// make sure the function has "Message" in the name so the function is removed
+/*
+ A typical backtrace in debug mode looks like:
+ #0 QInternalMessageLogContext::populateBacktrace (this=0x7fffffffd660, frameCount=5) at qlogging.cpp:1342
+ #1 QInternalMessageLogContext::QInternalMessageLogContext (logContext=..., this=<optimized out>) at qlogging_p.h:42
+ #2 QDebug::~QDebug (this=0x7fffffffdac8, __in_chrg=<optimized out>) at qdebug.cpp:160
+
+ In release mode, the QInternalMessageLogContext constructor will be usually
+ inlined. Empirical testing with GCC 13 and Clang 17 suggest they do obey the
+ Q_ALWAYS_INLINE in that constructor even in debug mode and do inline it.
+ Unfortunately, we can't know for sure if it has been.
+*/
+static constexpr int TypicalBacktraceFrameCount = 3;
+static constexpr const char *QtCoreLibraryName = "Qt" QT_STRINGIFY(QT_VERSION_MAJOR) "Core";
+
+#if defined(QLOGGING_USE_STD_BACKTRACE)
+Q_NEVER_INLINE void QInternalMessageLogContext::populateBacktrace(int frameCount)
+{
+ assert(frameCount >= 0);
+ backtrace = std::stacktrace::current(0, TypicalBacktraceFrameCount + frameCount);
+}
-#if ((defined(Q_CC_GNU) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) || __has_attribute(optimize)) \
- && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
-// force skipping the frame pointer, to save the backtrace() function some work
-__attribute__((optimize("omit-frame-pointer")))
+static QStringList
+backtraceFramesForLogMessage(int frameCount,
+ const QInternalMessageLogContext::BacktraceStorage &buffer)
+{
+ QStringList result;
+ result.reserve(buffer.size());
+
+ const auto shouldSkipFrame = [](QByteArrayView description)
+ {
+#if defined(_MSVC_STL_VERSION)
+ const auto libraryNameEnd = description.indexOf('!');
+ if (libraryNameEnd != -1) {
+ const auto libraryName = description.first(libraryNameEnd);
+ if (!libraryName.contains(QtCoreLibraryName))
+ return false;
+ }
#endif
-static QStringList backtraceFramesForLogMessage(int frameCount)
+ if (description.contains("populateBacktrace"))
+ return true;
+ if (description.contains("QInternalMessageLogContext"))
+ return true;
+ if (description.contains("~QDebug"))
+ return true;
+ return false;
+ };
+
+ for (const auto &entry : buffer) {
+ const std::string description = entry.description();
+ if (result.isEmpty() && shouldSkipFrame(description))
+ continue;
+ result.append(QString::fromStdString(description));
+ }
+
+ return result;
+}
+
+#elif defined(QLOGGING_USE_EXECINFO_BACKTRACE)
+
+Q_NEVER_INLINE void QInternalMessageLogContext::populateBacktrace(int frameCount)
+{
+ assert(frameCount >= 0);
+ BacktraceStorage &result = backtrace.emplace(TypicalBacktraceFrameCount + frameCount);
+ int n = ::backtrace(result.data(), result.size());
+ if (n <= 0)
+ result.clear();
+ else
+ result.resize(n);
+}
+
+static QStringList
+backtraceFramesForLogMessage(int frameCount,
+ const QInternalMessageLogContext::BacktraceStorage &buffer)
{
+ struct DecodedFrame {
+ QString library;
+ QString function;
+ };
+
QStringList result;
if (frameCount == 0)
return result;
+ auto shouldSkipFrame = [&result](const auto &library, const auto &function) {
+ if (!result.isEmpty() || !library.contains(QLatin1StringView(QtCoreLibraryName)))
+ return false;
+ if (function.isEmpty())
+ return true;
+ if (function.contains("6QDebug"_L1))
+ return true;
+ if (function.contains("14QMessageLogger"_L1))
+ return true;
+ if (function.contains("17qt_message_output"_L1))
+ return true;
+ if (function.contains("26QInternalMessageLogContext"_L1))
+ return true;
+ return false;
+ };
+
+ auto demangled = [](auto &function) -> QString {
+ if (!function.startsWith("_Z"_L1))
+ return function;
+
+ // we optimize for the case where __cxa_demangle succeeds
+ auto fn = [&]() {
+ if constexpr (sizeof(function.at(0)) == 1)
+ return function.data(); // -> const char *
+ else
+ return std::move(function).toUtf8(); // -> QByteArray
+ }();
+ QScopedPointer<char, QScopedPointerPodDeleter> demangled;
+ demangled.reset(abi::__cxa_demangle(fn, nullptr, nullptr, nullptr));
+
+ if (demangled)
+ return QString::fromUtf8(qCleanupFuncinfo(demangled.data()));
+ else
+ return QString::fromUtf8(fn); // restore
+ };
+
+# if QT_CONFIG(dladdr)
+ // use dladdr() instead of backtrace_symbols()
+ QString cachedLibrary;
+ const char *cachedFname = nullptr;
+ auto decodeFrame = [&](void *addr) -> DecodedFrame {
+ Dl_info info;
+ if (!dladdr(addr, &info))
+ return {};
+
+ // These are actually UTF-8, so we'll correct below
+ QLatin1StringView fn(info.dli_sname);
+ QLatin1StringView lib;
+ if (const char *lastSlash = strrchr(info.dli_fname, '/'))
+ lib = QLatin1StringView(lastSlash + 1);
+ else
+ lib = QLatin1StringView(info.dli_fname);
+
+ if (shouldSkipFrame(lib, fn))
+ return {};
+
+ QString function = demangled(fn);
+ if (lib.data() != cachedFname) {
+ cachedFname = lib.data();
+ cachedLibrary = QString::fromUtf8(cachedFname, lib.size());
+ }
+ return { cachedLibrary, function };
+ };
+# else
// The results of backtrace_symbols looks like this:
// /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
// The offset and function name are optional.
@@ -1290,63 +1487,68 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
// This code is protected by QMessagePattern::mutex so it is thread safe on all compilers
static const QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"));
- QVarLengthArray<void*, 32> buffer(8 + frameCount);
- int n = backtrace(buffer.data(), buffer.size());
- if (n > 0) {
- int numberPrinted = 0;
- for (int i = 0; i < n && numberPrinted < frameCount; ++i) {
- QScopedPointer<char*, QScopedPointerPodDeleter> strings(backtrace_symbols(buffer.data() + i, 1));
- QString trace = QString::fromLatin1(strings.data()[0]);
- QRegularExpressionMatch m = rx.match(trace);
- if (m.hasMatch()) {
- QString library = m.captured(1);
- QString function = m.captured(2);
-
- // skip the trace from QtCore that are because of the qDebug itself
- if (!numberPrinted && library.contains(QLatin1String("Qt6Core"))
- && (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive)
- || function.contains(QLatin1String("QDebug")))) {
- continue;
- }
+ auto decodeFrame = [&](void *&addr) -> DecodedFrame {
+ QScopedPointer<char*, QScopedPointerPodDeleter> strings(backtrace_symbols(&addr, 1));
+ QString trace = QString::fromUtf8(strings.data()[0]);
+ QRegularExpressionMatch m = rx.match(trace);
+ if (!m.hasMatch())
+ return {};
- if (function.startsWith(QLatin1String("_Z"))) {
- QScopedPointer<char, QScopedPointerPodDeleter> demangled(
- abi::__cxa_demangle(function.toUtf8(), nullptr, nullptr, nullptr));
- if (demangled)
- function = QString::fromUtf8(qCleanupFuncinfo(demangled.data()));
- }
+ QString library = m.captured(1);
+ QString function = m.captured(2);
- if (function.isEmpty()) {
- result.append(QLatin1Char('?') + library + QLatin1Char('?'));
- } else {
- result.append(function);
- }
- } else {
- if (numberPrinted == 0) {
- // innermost, unknown frames are usually the logging framework itself
- continue;
- }
+ // skip the trace from QtCore that are because of the qDebug itself
+ if (shouldSkipFrame(library, function))
+ return {};
+
+ function = demangled(function);
+ return { library, function };
+ };
+# endif
+
+ for (void *const &addr : buffer) {
+ DecodedFrame frame = decodeFrame(addr);
+ if (!frame.library.isEmpty()) {
+ if (frame.function.isEmpty())
+ result.append(u'?' + frame.library + u'?');
+ else
+ result.append(frame.function);
+ } else {
+ // innermost, unknown frames are usually the logging framework itself
+ if (!result.isEmpty())
result.append(QStringLiteral("???"));
- }
- numberPrinted++;
}
+
+ if (result.size() == frameCount)
+ break;
}
return result;
}
+#else
+#error "Internal error: backtrace enabled, but no way to gather backtraces available"
+#endif // QLOGGING_USE_..._BACKTRACE
static QString formatBacktraceForLogMessage(const QMessagePattern::BacktraceParams backtraceParams,
- const char *function)
+ const QMessageLogContext &ctx)
{
+ // do we have a backtrace stored?
+ if (ctx.version <= QMessageLogContext::CurrentVersion)
+ return QString();
+
+ auto &fullctx = static_cast<const QInternalMessageLogContext &>(ctx);
+ if (!fullctx.backtrace.has_value())
+ return QString();
+
QString backtraceSeparator = backtraceParams.backtraceSeparator;
int backtraceDepth = backtraceParams.backtraceDepth;
- QStringList frames = backtraceFramesForLogMessage(backtraceDepth);
+ QStringList frames = backtraceFramesForLogMessage(backtraceDepth, *fullctx.backtrace);
if (frames.isEmpty())
return QString();
// if the first frame is unknown, replace it with the context function
- if (function && frames.at(0).startsWith(QLatin1Char('?')))
- frames[0] = QString::fromUtf8(qCleanupFuncinfo(function));
+ if (ctx.function && frames.at(0).startsWith(u'?'))
+ frames[0] = QString::fromUtf8(qCleanupFuncinfo(ctx.function));
return frames.join(backtraceSeparator);
}
@@ -1355,7 +1557,7 @@ static QString formatBacktraceForLogMessage(const QMessagePattern::BacktracePara
Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
/*!
- \relates <QtGlobal>
+ \relates <QtLogging>
\since 5.4
Generates a formatted string out of the \a type, \a context, \a str arguments.
@@ -1370,6 +1572,14 @@ Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
*/
QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str)
{
+ return formatLogMessage(type, context, str);
+}
+
+// Separate function so the default message handler can bypass the public,
+// exported function above. Static functions can't get added to the dynamic
+// symbol tables, so they never show up in backtrace_symbols() or equivalent.
+static QString formatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str)
+{
QString message;
const auto locker = qt_scoped_lock(QMessagePattern::mutex);
@@ -1383,12 +1593,10 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
bool skip = false;
-#ifndef QT_BOOTSTRAPPED
int timeArgsIdx = 0;
#ifdef QLOGGING_HAVE_BACKTRACE
int backtraceArgsIdx = 0;
#endif
-#endif
// we do not convert file, function, line literals to local encoding due to overhead
for (int i = 0; pattern->tokens[i]; ++i) {
@@ -1398,39 +1606,39 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
} else if (skip) {
// we skip adding messages, but we have to iterate over
// timeArgsIdx and backtraceArgsIdx anyway
-#ifndef QT_BOOTSTRAPPED
if (token == timeTokenC)
timeArgsIdx++;
#ifdef QLOGGING_HAVE_BACKTRACE
else if (token == backtraceTokenC)
backtraceArgsIdx++;
#endif
-#endif
} else if (token == messageTokenC) {
message.append(str);
} else if (token == categoryTokenC) {
- message.append(QLatin1String(context.category));
+#ifndef Q_OS_ANDROID
+ // Don't add the category to the message on Android
+ message.append(QLatin1StringView(context.category));
+#endif
} else if (token == typeTokenC) {
switch (type) {
- case QtDebugMsg: message.append(QLatin1String("debug")); break;
- case QtInfoMsg: message.append(QLatin1String("info")); break;
- case QtWarningMsg: message.append(QLatin1String("warning")); break;
- case QtCriticalMsg:message.append(QLatin1String("critical")); break;
- case QtFatalMsg: message.append(QLatin1String("fatal")); break;
+ case QtDebugMsg: message.append("debug"_L1); break;
+ case QtInfoMsg: message.append("info"_L1); break;
+ case QtWarningMsg: message.append("warning"_L1); break;
+ case QtCriticalMsg:message.append("critical"_L1); break;
+ case QtFatalMsg: message.append("fatal"_L1); break;
}
} else if (token == fileTokenC) {
if (context.file)
- message.append(QLatin1String(context.file));
+ message.append(QLatin1StringView(context.file));
else
- message.append(QLatin1String("unknown"));
+ message.append("unknown"_L1);
} else if (token == lineTokenC) {
message.append(QString::number(context.line));
} else if (token == functionTokenC) {
if (context.function)
message.append(QString::fromLatin1(qCleanupFuncinfo(context.function)));
else
- message.append(QLatin1String("unknown"));
-#ifndef QT_BOOTSTRAPPED
+ message.append("unknown"_L1);
} else if (token == pidTokenC) {
message.append(QString::number(QCoreApplication::applicationPid()));
} else if (token == appnameTokenC) {
@@ -1439,26 +1647,24 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
// print the TID as decimal
message.append(QString::number(qt_gettid()));
} else if (token == qthreadptrTokenC) {
- message.append(QLatin1String("0x"));
+ message.append("0x"_L1);
message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16));
#ifdef QLOGGING_HAVE_BACKTRACE
} else if (token == backtraceTokenC) {
QMessagePattern::BacktraceParams backtraceParams = pattern->backtraceArgs.at(backtraceArgsIdx);
backtraceArgsIdx++;
- message.append(formatBacktraceForLogMessage(backtraceParams, context.function));
+ message.append(formatBacktraceForLogMessage(backtraceParams, context));
#endif
} else if (token == timeTokenC) {
QString timeFormat = pattern->timeArgs.at(timeArgsIdx);
timeArgsIdx++;
- if (timeFormat == QLatin1String("process")) {
- quint64 ms = pattern->timer.elapsed();
- message.append(QString::asprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000)));
- } else if (timeFormat == QLatin1String("boot")) {
+ if (timeFormat == "process"_L1) {
+ quint64 ms = pattern->timer.elapsed();
+ message.append(QString::asprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000)));
+ } else if (timeFormat == "boot"_L1) {
// just print the milliseconds since the elapsed timer reference
// like the Linux kernel does
- QElapsedTimer now;
- now.start();
- uint ms = now.msecsSinceReference();
+ qint64 ms = QDeadlineTimer::current().deadline();
message.append(QString::asprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000)));
#if QT_CONFIG(datestring)
} else if (timeFormat.isEmpty()) {
@@ -1467,7 +1673,6 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
message.append(QDateTime::currentDateTime().toString(timeFormat));
#endif // QT_CONFIG(datestring)
}
-#endif // !QT_BOOTSTRAPPED
} else if (token == ifCategoryTokenC) {
if (isDefaultCategory(context.category))
skip = true;
@@ -1481,30 +1686,35 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
HANDLE_IF_TOKEN(Fatal)
#undef HANDLE_IF_TOKEN
} else {
- message.append(QLatin1String(token));
+ message.append(QLatin1StringView(token));
}
}
return message;
}
-
-#if !QT_DEPRECATED_SINCE(5, 0)
-// make sure they're defined to be exported
-typedef void (*QtMsgHandler)(QtMsgType, const char *);
-Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
+#else // QT_BOOTSTRAPPED
+static QString formatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(context);
+ return str;
+}
+#endif
+#ifndef QLOGGING_HAVE_BACKTRACE
+void QInternalMessageLogContext::populateBacktrace(int)
+{
+ Q_UNREACHABLE();
+}
#endif
-static void qDefaultMsgHandler(QtMsgType type, const char *buf);
static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &buf);
-// pointer to QtMsgHandler debug handler (without context)
-static QBasicAtomicPointer<void (QtMsgType, const char*)> msgHandler = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
// pointer to QtMessageHandler debug handler (with context)
-static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QString &)> messageHandler = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
+Q_CONSTINIT static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QString &)> messageHandler = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
// ------------------------ Alternate logging sinks -------------------------
#if defined(QT_BOOTSTRAPPED)
- // Boostrapped tools always print to stderr, so no need for alternate sinks
+ // Bootstrapped tools always print to stderr, so no need for alternate sinks
#else
#if QT_CONFIG(slog2)
@@ -1512,13 +1722,14 @@ static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QS
#define QT_LOG_CODE 9000
#endif
-static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
+static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &,
+ const QString &message)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
- QString formattedMessage = qFormatLogMessage(type, context, message);
- formattedMessage.append(QLatin1Char('\n'));
+ QString formattedMessage = message;
+ formattedMessage.append(u'\n');
if (slog2_set_default_buffer((slog2_buffer_t)-1) == 0) {
slog2_buffer_set_config_t buffer_config;
slog2_buffer_t buffer_handle;
@@ -1539,7 +1750,7 @@ static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &cont
// Set as the default buffer
slog2_set_default_buffer(buffer_handle);
}
- int severity;
+ int severity = SLOG2_INFO;
//Determines the severity level
switch (type) {
case QtDebugMsg:
@@ -1568,13 +1779,11 @@ static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &cont
#if QT_CONFIG(journald)
static bool systemd_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
- const QString &message)
+ const QString &formattedMessage)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
- QString formattedMessage = qFormatLogMessage(type, context, message);
-
int priority = LOG_INFO; // Informational
switch (type) {
case QtDebugMsg:
@@ -1607,13 +1816,12 @@ static bool systemd_default_message_handler(QtMsgType type,
#endif
#if QT_CONFIG(syslog)
-static bool syslog_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
+static bool syslog_default_message_handler(QtMsgType type, const QMessageLogContext &context,
+ const QString &formattedMessage)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
- QString formattedMessage = qFormatLogMessage(type, context, message);
-
int priority = LOG_INFO; // Informational
switch (type) {
case QtDebugMsg:
@@ -1639,45 +1847,57 @@ static bool syslog_default_message_handler(QtMsgType type, const QMessageLogCont
}
#endif
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
static bool android_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
- const QString &message)
+ const QString &formattedMessage)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
- QString formattedMessage = qFormatLogMessage(type, context, message);
-
android_LogPriority priority = ANDROID_LOG_DEBUG;
switch (type) {
- case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break;
- case QtInfoMsg: priority = ANDROID_LOG_INFO; break;
- case QtWarningMsg: priority = ANDROID_LOG_WARN; break;
- case QtCriticalMsg: priority = ANDROID_LOG_ERROR; break;
- case QtFatalMsg: priority = ANDROID_LOG_FATAL; break;
+ case QtDebugMsg:
+ priority = ANDROID_LOG_DEBUG;
+ break;
+ case QtInfoMsg:
+ priority = ANDROID_LOG_INFO;
+ break;
+ case QtWarningMsg:
+ priority = ANDROID_LOG_WARN;
+ break;
+ case QtCriticalMsg:
+ priority = ANDROID_LOG_ERROR;
+ break;
+ case QtFatalMsg:
+ priority = ANDROID_LOG_FATAL;
+ break;
};
- __android_log_print(priority, qPrintable(QCoreApplication::applicationName()), "%s\n", qPrintable(formattedMessage));
+ // If application name is a tag ensure it has no spaces
+ // If a category is defined, use it as an Android logging tag
+ __android_log_print(priority, isDefaultCategory(context.category) ?
+ qPrintable(QCoreApplication::applicationName().replace(u' ', u'_')) : context.category,
+ "%s\n", qPrintable(formattedMessage));
return true; // Prevent further output to stderr
}
#endif //Q_OS_ANDROID
#ifdef Q_OS_WIN
-static void win_outputDebugString_helper(QStringView message)
+static void win_outputDebugString_helper(const QString &message)
{
- const int maxOutputStringLength = 32766;
- static QBasicMutex m;
+ const qsizetype maxOutputStringLength = 32766;
+ Q_CONSTINIT static QBasicMutex m;
auto locker = qt_unique_lock(m);
// fast path: Avoid string copies if one output is enough
if (message.length() <= maxOutputStringLength) {
OutputDebugString(reinterpret_cast<const wchar_t *>(message.utf16()));
} else {
wchar_t *messagePart = new wchar_t[maxOutputStringLength + 1];
- for (int i = 0; i < message.length(); i += maxOutputStringLength ) {
- const int length = std::min(message.length() - i, maxOutputStringLength );
- const int len = message.mid(i, length).toWCharArray(messagePart);
+ for (qsizetype i = 0; i < message.length(); i += maxOutputStringLength) {
+ const qsizetype length = qMin(message.length() - i, maxOutputStringLength);
+ const qsizetype len = QStringView{message}.mid(i, length).toWCharArray(messagePart);
Q_ASSERT(len == length);
messagePart[len] = 0;
OutputDebugString(messagePart);
@@ -1686,13 +1906,13 @@ static void win_outputDebugString_helper(QStringView message)
}
}
-static bool win_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
+static bool win_message_handler(QtMsgType, const QMessageLogContext &,
+ const QString &formattedMessage)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
- const QString formattedMessage = qFormatLogMessage(type, context, message).append(QLatin1Char('\n'));
- win_outputDebugString_helper(formattedMessage);
+ win_outputDebugString_helper(formattedMessage + u'\n');
return true; // Prevent further output to stderr
}
@@ -1700,15 +1920,15 @@ static bool win_message_handler(QtMsgType type, const QMessageLogContext &contex
#ifdef Q_OS_WASM
static bool wasm_default_message_handler(QtMsgType type,
- const QMessageLogContext &context,
- const QString &message)
+ const QMessageLogContext &,
+ const QString &formattedMessage)
{
- if (shouldLogToStderr())
- return false; // Leave logging up to stderr handler
+ static bool forceStderrLogging = qEnvironmentVariableIntValue("QT_FORCE_STDERR_LOGGING");
+ if (forceStderrLogging)
+ return false;
- QString formattedMessage = qFormatLogMessage(type, context, message);
- int emOutputFlags = (EM_LOG_CONSOLE | EM_LOG_DEMANGLE);
- QByteArray localMsg = message.toLocal8Bit();
+ int emOutputFlags = EM_LOG_CONSOLE;
+ QByteArray localMsg = formattedMessage.toLocal8Bit();
switch (type) {
case QtDebugMsg:
break;
@@ -1733,67 +1953,89 @@ static bool wasm_default_message_handler(QtMsgType type,
// --------------------------------------------------------------------------
-static void stderr_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
+static void stderr_message_handler(QtMsgType type, const QMessageLogContext &context,
+ const QString &formattedMessage)
{
- QString formattedMessage = qFormatLogMessage(type, context, message);
+ Q_UNUSED(type);
+ Q_UNUSED(context);
// print nothing if message pattern didn't apply / was empty.
// (still print empty lines, e.g. because message itself was empty)
if (formattedMessage.isNull())
return;
-
fprintf(stderr, "%s\n", formattedMessage.toLocal8Bit().constData());
fflush(stderr);
}
+namespace {
+struct SystemMessageSink
+{
+ using Fn = bool(QtMsgType, const QMessageLogContext &, const QString &);
+ Fn *sink;
+ bool messageIsUnformatted = false;
+};
+}
+
+static constexpr SystemMessageSink systemMessageSink = {
+#if defined(QT_BOOTSTRAPPED)
+ nullptr
+#elif defined(Q_OS_WIN)
+ win_message_handler
+#elif QT_CONFIG(slog2)
+ slog2_default_handler
+#elif QT_CONFIG(journald)
+ systemd_default_message_handler
+#elif QT_CONFIG(syslog)
+ syslog_default_message_handler
+#elif defined(Q_OS_ANDROID)
+ android_default_message_handler
+#elif defined(QT_USE_APPLE_UNIFIED_LOGGING)
+ AppleUnifiedLogger::messageHandler, true
+#elif defined Q_OS_WASM
+ wasm_default_message_handler
+#else
+ nullptr
+#endif
+};
+
+static void preformattedMessageHandler(QtMsgType type, const QMessageLogContext &context,
+ const QString &formattedMessage)
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Waddress") // "the address of ~~ will never be NULL
+ if (systemMessageSink.sink && systemMessageSink.sink(type, context, formattedMessage))
+ return;
+QT_WARNING_POP
+
+ stderr_message_handler(type, context, formattedMessage);
+}
+
/*!
\internal
*/
static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context,
const QString &message)
{
- bool handledStderr = false;
-
// A message sink logs the message to a structured or unstructured destination,
// optionally formatting the message if the latter, and returns true if the sink
// handled stderr output as well, which will shortcut our default stderr output.
- // In the future, if we allow multiple/dynamic sinks, this will be iterating
- // a list of sinks.
-#if !defined(QT_BOOTSTRAPPED)
-# if defined(Q_OS_WIN)
- handledStderr |= win_message_handler(type, context, message);
-# elif QT_CONFIG(slog2)
- handledStderr |= slog2_default_handler(type, context, message);
-# elif QT_CONFIG(journald)
- handledStderr |= systemd_default_message_handler(type, context, message);
-# elif QT_CONFIG(syslog)
- handledStderr |= syslog_default_message_handler(type, context, message);
-# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- handledStderr |= android_default_message_handler(type, context, message);
-# elif defined(QT_USE_APPLE_UNIFIED_LOGGING)
- handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message);
-# elif defined Q_OS_WASM
- handledStderr |= wasm_default_message_handler(type, context, message);
-# endif
-#endif
+ if (systemMessageSink.messageIsUnformatted) {
+ if (systemMessageSink.sink(type, context, message))
+ return;
+ }
- if (!handledStderr)
- stderr_message_handler(type, context, message);
+ preformattedMessageHandler(type, context, formatLogMessage(type, context, message));
}
-/*!
- \internal
-*/
-static void qDefaultMsgHandler(QtMsgType type, const char *buf)
-{
- QMessageLogContext emptyContext;
- qDefaultMessageHandler(type, emptyContext, QString::fromLocal8Bit(buf));
-}
+#if defined(QT_BOOTSTRAPPED)
+// there's no message handler in bootstrapped mode; force everything to stderr
+static bool grabMessageHandler() { return false; }
+static void ungrabMessageHandler() { }
-#if defined(Q_COMPILER_THREAD_LOCAL)
+#elif defined(Q_COMPILER_THREAD_LOCAL)
-static thread_local bool msgHandlerGrabbed = false;
+Q_CONSTINIT static thread_local bool msgHandlerGrabbed = false;
static bool grabMessageHandler()
{
@@ -1832,34 +2074,17 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex
// itself, e.g. by using Qt API
if (grabMessageHandler()) {
const auto ungrab = qScopeGuard([]{ ungrabMessageHandler(); });
- auto oldStyle = msgHandler.loadAcquire();
- auto newStye = messageHandler.loadAcquire();
- // prefer new message handler over the old one
- if (newStye || !oldStyle) {
- (newStye ? newStye : qDefaultMessageHandler)(msgType, context, message);
- } else {
- (oldStyle ? oldStyle : qDefaultMsgHandler)(msgType, message.toLocal8Bit().constData());
- }
+ auto msgHandler = messageHandler.loadAcquire();
+ (msgHandler ? msgHandler : qDefaultMessageHandler)(msgType, context, message);
} else {
- fprintf(stderr, "%s\n", message.toLocal8Bit().constData());
- }
-}
-
-static void qt_message_print(const QString &message)
-{
-#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
- if (!shouldLogToStderr()) {
- win_outputDebugString_helper(message);
- return;
+ stderr_message_handler(msgType, context, message);
}
-#endif
- fprintf(stderr, "%s", message.toLocal8Bit().constData());
- fflush(stderr);
}
-static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message)
+template <typename String>
+static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, String &&message)
{
-#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
+#if defined(Q_CC_MSVC_ONLY) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
wchar_t contextFileL[256];
// we probably should let the compiler do this for us, by declaring QMessageLogContext::file to
// be const wchar_t * in the first place, but the #ifdefery above is very complex and we
@@ -1878,45 +2103,24 @@ static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const
_CrtDbgBreak();
#else
Q_UNUSED(context);
- Q_UNUSED(message);
#endif
-#ifdef Q_OS_WIN
- // std::abort() in the MSVC runtime will call _exit(3) if the abort
- // behavior is _WRITE_ABORT_MSG - see also _set_abort_behavior(). This is
- // the default for a debug-mode build of the runtime. Worse, MinGW's
- // std::abort() implementation (in msvcrt.dll) is basically a call to
- // _exit(3) too. Unfortunately, _exit() and _Exit() *do* run the static
- // destructors of objects in DLLs, a violation of the C++ standard (see
- // [support.start.term]). So we bypass std::abort() and directly
- // terminate the application.
-
-# if defined(Q_CC_MSVC) && !defined(Q_CC_INTEL)
- if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
- __fastfail(FAST_FAIL_FATAL_APP_EXIT);
-# else
- RaiseFailFastException(nullptr, nullptr, 0);
-# endif
-
- // Fallback
- TerminateProcess(GetCurrentProcess(), STATUS_FATAL_APP_EXIT);
-
- // Tell the compiler the application has stopped.
- Q_UNREACHABLE_IMPL();
-#else // !Q_OS_WIN
- std::abort();
-#endif
+ if constexpr (std::is_class_v<String> && !std::is_const_v<String>)
+ message.clear();
+ else
+ Q_UNUSED(message);
+ qAbort();
}
-
/*!
\internal
*/
void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
{
- qt_message_print(msgType, context, message);
+ QInternalMessageLogContext ctx(context);
+ qt_message_print(msgType, ctx, message);
if (isFatal(msgType))
- qt_message_fatal(msgType, context, message);
+ qt_message_fatal(msgType, ctx, message);
}
void qErrnoWarning(const char *msg, ...)
@@ -1930,9 +2134,9 @@ void qErrnoWarning(const char *msg, ...)
QString buf = QString::vasprintf(msg, ap);
va_end(ap);
- buf += QLatin1String(" (") + error_string + QLatin1Char(')');
- QMessageLogContext context;
- qt_message_output(QtCriticalMsg, context, buf);
+ buf += " ("_L1 + error_string + u')';
+ QInternalMessageLogContext context{QMessageLogContext()};
+ qt_message_output(QtWarningMsg, context, buf);
}
void qErrnoWarning(int code, const char *msg, ...)
@@ -1944,28 +2148,14 @@ void qErrnoWarning(int code, const char *msg, ...)
QString buf = QString::vasprintf(msg, ap);
va_end(ap);
- buf += QLatin1String(" (") + qt_error_string(code) + QLatin1Char(')');
- QMessageLogContext context;
- qt_message_output(QtCriticalMsg, context, buf);
+ buf += " ("_L1 + qt_error_string(code) + u')';
+ QInternalMessageLogContext context{QMessageLogContext()};
+ qt_message_output(QtWarningMsg, context, buf);
}
/*!
- \typedef QtMsgHandler
- \relates <QtGlobal>
- \deprecated
-
- This is a typedef for a pointer to a function with the following
- signature:
-
- \snippet code/src_corelib_global_qglobal.cpp 7
-
- This typedef is deprecated, you should use QtMessageHandler instead.
- \sa QtMsgType, QtMessageHandler, qInstallMsgHandler(), qInstallMessageHandler()
-*/
-
-/*!
\typedef QtMessageHandler
- \relates <QtGlobal>
+ \relates <QtLogging>
\since 5.0
This is a typedef for a pointer to a function with the following
@@ -1978,51 +2168,69 @@ void qErrnoWarning(int code, const char *msg, ...)
/*!
\fn QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)
- \relates <QtGlobal>
+ \relates <QtLogging>
\since 5.0
- Installs a Qt message \a handler which has been defined
- previously. Returns a pointer to the previous message handler.
-
- The message handler is a function that prints out debug messages,
- warnings, critical and fatal error messages. The Qt library (debug
- mode) contains hundreds of warning messages that are printed
- when internal errors (usually invalid function arguments)
- occur. Qt built in release mode also contains such warnings unless
- QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during
- compilation. If you implement your own message handler, you get total
- control of these messages.
-
- The default message handler prints the message to the standard
- output under X11 or to the debugger under Windows. If it is a
- fatal message, the application aborts immediately.
-
- Only one message handler can be defined, since this is usually
- done on an application-wide basis to control debug output.
-
- To restore the message handler, call \c qInstallMessageHandler(0).
-
- Example:
+ Installs a Qt message \a handler.
+ Returns a pointer to the previously installed message handler.
+
+ A message handler is a function that prints out debug, info,
+ warning, critical, and fatal messages from Qt's logging infrastructure.
+ By default, Qt uses a standard message handler that formats and
+ prints messages to different sinks specific to the operating system
+ and Qt configuration. Installing your own message handler allows you
+ to assume full control, and for instance log messages to the
+ file system.
+
+ Note that Qt supports \l{QLoggingCategory}{logging categories} for
+ grouping related messages in semantic categories. You can use these
+ to enable or disable logging per category and \l{QtMsgType}{message type}.
+ As the filtering for logging categories is done even before a message
+ is created, messages for disabled types and categories will not reach
+ the message handler.
+
+ A message handler needs to be
+ \l{Reentrancy and Thread-Safety}{reentrant}. That is, it might be called
+ from different threads, in parallel. Therefore, writes to common sinks
+ (like a database, or a file) often need to be synchronized.
+
+ Qt allows to enrich logging messages with further meta-information
+ by calling \l qSetMessagePattern(), or setting the \c QT_MESSAGE_PATTERN
+ environment variable. To keep this formatting, a custom message handler
+ can use \l qFormatLogMessage().
+
+ Try to keep the code in the message handler itself minimal, as expensive
+ operations might block the application. Also, to avoid recursion, any
+ logging messages generated in the message handler itself will be ignored.
+
+ The message handler should always return. For
+ \l{QtFatalMsg}{fatal messages}, the application aborts immediately after
+ handling that message.
+
+ Only one message handler can be installed at a time, for the whole application.
+ If there was a previous custom message handler installed,
+ the function will return a pointer to it. This handler can then
+ be later reinstalled by another call to the method. Also, calling
+ \c qInstallMessageHandler(nullptr) will restore the default
+ message handler.
+
+ Here is an example of a message handler that logs to a local file
+ before calling the default handler:
\snippet code/src_corelib_global_qglobal.cpp 23
+ Note that the C++ standard guarantees that \c{static FILE *f} is
+ initialized in a thread-safe way. We can also expect \c{fprintf()}
+ and \c{fflush()} to be thread-safe, so no further synchronization
+ is necessary.
+
\sa QtMessageHandler, QtMsgType, qDebug(), qInfo(), qWarning(), qCritical(), qFatal(),
- {Debugging Techniques}
+ {Debugging Techniques}, qFormatLogMessage()
*/
/*!
- \fn QtMsgHandler qInstallMsgHandler(QtMsgHandler handler)
- \relates <QtGlobal>
- \deprecated
-
- Installs a Qt message \a handler which has been defined
- previously. This method is deprecated, use qInstallMessageHandler
- instead.
- \sa QtMsgHandler, qInstallMessageHandler()
-*/
-/*!
\fn void qSetMessagePattern(const QString &pattern)
- \relates <QtGlobal>
+ \relates <QtLogging>
\since 5.0
\brief Changes the output of the default message handler.
@@ -2055,9 +2263,22 @@ void qErrnoWarning(int code, const char *msg, ...)
\row \li \c{%{backtrace [depth=N] [separator="..."]}} \li A backtrace with the number of frames
specified by the optional \c depth parameter (defaults to 5), and separated by the optional
\c separator parameter (defaults to "|").
- This expansion is available only on some platforms (currently only platfoms using glibc).
- Names are only known for exported functions. If you want to see the name of every function
- in your application, use \c{QMAKE_LFLAGS += -rdynamic}.
+
+ This expansion is available only on some platforms:
+
+ \list
+ \li platforms using glibc;
+ \li platforms shipping C++23's \c{<stacktrace>} header (requires compiling Qt in C++23 mode).
+ \endlist
+
+ Depending on the platform, there are some restrictions on the function
+ names printed by this expansion.
+
+ On some platforms,
+ names are only known for exported functions. If you want to see the name of every function
+ in your application, make sure your application is compiled and linked with \c{-rdynamic},
+ or an equivalent of it.
+
When reading backtraces, take into account that frames might be missing due to inlining or
tail call optimization.
\endtable
@@ -2072,19 +2293,23 @@ void qErrnoWarning(int code, const char *msg, ...)
Example:
\snippet code/src_corelib_global_qlogging.cpp 0
- The default \a pattern is "%{if-category}%{category}: %{endif}%{message}".
+ The default \a pattern is \c{%{if-category}%{category}: %{endif}%{message}}.
The \a pattern can also be changed at runtime by setting the QT_MESSAGE_PATTERN
environment variable; if both \l qSetMessagePattern() is called and QT_MESSAGE_PATTERN is
set, the environment variable takes precedence.
+ \note The information for the placeholders \c category, \c file, \c function and \c line is
+ only recorded in debug builds. Alternatively, \c QT_MESSAGELOGCONTEXT can be defined
+ explicitly. For more information refer to the QMessageLogContext documentation.
+
\note The message pattern only applies to unstructured logging, such as the default
\c stderr output. Structured logging such as systemd will record the message as is,
along with as much structured information as can be captured.
Custom message handlers can use qFormatLogMessage() to take \a pattern into account.
- \sa qInstallMessageHandler(), {Debugging Techniques}, {QLoggingCategory}
+ \sa qInstallMessageHandler(), {Debugging Techniques}, {QLoggingCategory}, QMessageLogContext
*/
QtMessageHandler qInstallMessageHandler(QtMessageHandler h)
@@ -2096,15 +2321,7 @@ QtMessageHandler qInstallMessageHandler(QtMessageHandler h)
return qDefaultMessageHandler;
}
-QtMsgHandler qInstallMsgHandler(QtMsgHandler h)
-{
- const auto old = msgHandler.fetchAndStoreOrdered(h);
- if (old)
- return old;
- else
- return qDefaultMsgHandler;
-}
-
+#ifndef QT_BOOTSTRAPPED
void qSetMessagePattern(const QString &pattern)
{
const auto locker = qt_scoped_lock(QMessagePattern::mutex);
@@ -2112,7 +2329,38 @@ void qSetMessagePattern(const QString &pattern)
if (!qMessagePattern()->fromEnvironment)
qMessagePattern()->setPattern(pattern);
}
+#endif
+static void copyInternalContext(QInternalMessageLogContext *self,
+ const QMessageLogContext &logContext) noexcept
+{
+ if (logContext.version == self->version) {
+ auto other = static_cast<const QInternalMessageLogContext *>(&logContext);
+ self->backtrace = other->backtrace;
+ }
+}
+
+/*!
+ \internal
+ Copies context information from \a logContext into this QMessageLogContext.
+ Returns the number of backtrace frames that are desired.
+*/
+int QInternalMessageLogContext::initFrom(const QMessageLogContext &logContext)
+{
+ version = CurrentVersion + 1;
+ copyContextFrom(logContext);
+
+#ifdef QLOGGING_HAVE_BACKTRACE
+ if (backtrace.has_value())
+ return 0; // we have a stored backtrace, no need to get it again
+
+ // initializes the message pattern, if needed
+ if (auto pattern = qMessagePattern())
+ return pattern->maxBacktraceDepth;
+#endif
+
+ return 0;
+}
/*!
Copies context information from \a logContext into this QMessageLogContext.
@@ -2128,6 +2376,8 @@ QMessageLogContext &QMessageLogContext::copyContextFrom(const QMessageLogContext
this->file = logContext.file;
this->line = logContext.line;
this->function = logContext.function;
+ if (Q_UNLIKELY(version == CurrentVersion + 1))
+ copyInternalContext(static_cast<QInternalMessageLogContext *>(this), logContext);
return *this;
}
@@ -2175,4 +2425,219 @@ QMessageLogContext &QMessageLogContext::copyContextFrom(const QMessageLogContext
\a lineNumber, in function \a functionName, and category \a categoryName.
*/
+/*!
+ \macro qDebug(const char *message, ...)
+ \relates <QtLogging>
+ \threadsafe
+
+ Calls the message handler with the debug message \a message. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows the message is sent to the console, if it is a
+ console application; otherwise, it is sent to the debugger. On QNX, the
+ message is sent to slogger2. This function does nothing if \c QT_NO_DEBUG_OUTPUT
+ was defined during compilation.
+
+ If you pass the function a format string and a list of arguments,
+ it works in similar way to the C printf() function. The format
+ should be a Latin-1 string.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 24
+
+ If you include \c <QtDebug>, a more convenient syntax is also
+ available:
+
+ \snippet code/src_corelib_global_qglobal.cpp 25
+
+ With this syntax, the function returns a QDebug object that is
+ configured to use the QtDebugMsg message type. It automatically
+ puts a single space between each item, and outputs a newline at
+ the end. It supports many C++ and Qt types.
+
+ To suppress the output at runtime, install your own message handler
+ with qInstallMessageHandler().
+
+ \sa qInfo(), qWarning(), qCritical(), qFatal(), qInstallMessageHandler(),
+ {Debugging Techniques}
+*/
+
+/*!
+ \macro qInfo(const char *message, ...)
+ \relates <QtLogging>
+ \threadsafe
+ \since 5.5
+
+ Calls the message handler with the informational message \a message. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the console, if it is a
+ console application; otherwise, it is sent to the debugger. On QNX the
+ message is sent to slogger2. This function does nothing if \c QT_NO_INFO_OUTPUT
+ was defined during compilation.
+
+ If you pass the function a format string and a list of arguments,
+ it works in similar way to the C printf() function. The format
+ should be a Latin-1 string.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qInfo_printf
+
+ If you include \c <QtDebug>, a more convenient syntax is also
+ available:
+
+ \snippet code/src_corelib_global_qglobal.cpp qInfo_stream
+
+ With this syntax, the function returns a QDebug object that is
+ configured to use the QtInfoMsg message type. It automatically
+ puts a single space between each item, and outputs a newline at
+ the end. It supports many C++ and Qt types.
+
+ To suppress the output at runtime, install your own message handler
+ using qInstallMessageHandler().
+
+ \sa qDebug(), qWarning(), qCritical(), qFatal(), qInstallMessageHandler(),
+ {Debugging Techniques}
+*/
+
+/*!
+ \macro qWarning(const char *message, ...)
+ \relates <QtLogging>
+ \threadsafe
+
+ Calls the message handler with the warning message \a message. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the debugger.
+ On QNX the message is sent to slogger2.
+
+ This function takes a format string and a list of arguments,
+ similar to the C printf() function. The format should be a Latin-1
+ string.
+
+ Example:
+ \snippet code/src_corelib_global_qglobal.cpp 26
+
+ If you include <QtDebug>, a more convenient syntax is
+ also available:
+
+ \snippet code/src_corelib_global_qglobal.cpp 27
+
+ This syntax inserts a space between each item, and
+ appends a newline at the end.
+
+ This function does nothing if \c QT_NO_WARNING_OUTPUT was defined
+ during compilation.
+ To suppress the output at runtime, you can set
+ \l{QLoggingCategory}{logging rules} or register a custom
+ \l{QLoggingCategory::installFilter()}{filter}.
+
+ For debugging purposes, it is sometimes convenient to let the
+ program abort for warning messages. This allows you then
+ to inspect the core dump, or attach a debugger - see also \l{qFatal()}.
+ To enable this, set the environment variable \c{QT_FATAL_WARNINGS}
+ to a number \c n. The program terminates then for the n-th warning.
+ That is, if the environment variable is set to 1, it will terminate
+ on the first call; if it contains the value 10, it will exit on the 10th
+ call. Any non-numeric value in the environment variable is equivalent to 1.
+
+ \sa qDebug(), qInfo(), qCritical(), qFatal(), qInstallMessageHandler(),
+ {Debugging Techniques}
+*/
+
+/*!
+ \macro qCritical(const char *message, ...)
+ \relates <QtLogging>
+ \threadsafe
+
+ Calls the message handler with the critical message \a message. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the debugger.
+ On QNX the message is sent to slogger2.
+
+ This function takes a format string and a list of arguments,
+ similar to the C printf() function. The format should be a Latin-1
+ string.
+
+ Example:
+ \snippet code/src_corelib_global_qglobal.cpp 28
+
+ If you include <QtDebug>, a more convenient syntax is
+ also available:
+
+ \snippet code/src_corelib_global_qglobal.cpp 29
+
+ A space is inserted between the items, and a newline is
+ appended at the end.
+
+ To suppress the output at runtime, you can define
+ \l{QLoggingCategory}{logging rules} or register a custom
+ \l{QLoggingCategory::installFilter()}{filter}.
+
+ For debugging purposes, it is sometimes convenient to let the
+ program abort for critical messages. This allows you then
+ to inspect the core dump, or attach a debugger - see also \l{qFatal()}.
+ To enable this, set the environment variable \c{QT_FATAL_CRITICALS}
+ to a number \c n. The program terminates then for the n-th critical
+ message.
+ That is, if the environment variable is set to 1, it will terminate
+ on the first call; if it contains the value 10, it will exit on the 10th
+ call. Any non-numeric value in the environment variable is equivalent to 1.
+
+ \sa qDebug(), qInfo(), qWarning(), qFatal(), qInstallMessageHandler(),
+ {Debugging Techniques}
+*/
+
+/*!
+ \macro qFatal(const char *message, ...)
+ \relates <QtLogging>
+
+ Calls the message handler with the fatal message \a message. If no
+ message handler has been installed, the message is printed to
+ stderr. Under Windows, the message is sent to the debugger.
+ On QNX the message is sent to slogger2.
+
+ If you are using the \b{default message handler} this function will
+ abort to create a core dump. On Windows, for debug builds,
+ this function will report a _CRT_ERROR enabling you to connect a debugger
+ to the application.
+
+ This function takes a format string and a list of arguments,
+ similar to the C printf() function.
+
+ Example:
+ \snippet code/src_corelib_global_qglobal.cpp 30
+
+ To suppress the output at runtime, install your own message handler
+ with qInstallMessageHandler().
+
+ \sa qDebug(), qInfo(), qWarning(), qCritical(), qInstallMessageHandler(),
+ {Debugging Techniques}
+*/
+
+/*!
+ \enum QtMsgType
+ \relates <QtLogging>
+
+ This enum describes the messages that can be sent to a message
+ handler (QtMessageHandler). You can use the enum to identify and
+ associate the various message types with the appropriate
+ actions.
+
+ \value QtDebugMsg
+ A message generated by the qDebug() function.
+ \value QtInfoMsg
+ A message generated by the qInfo() function.
+ \value QtWarningMsg
+ A message generated by the qWarning() function.
+ \value QtCriticalMsg
+ A message generated by the qCritical() function.
+ \value QtFatalMsg
+ A message generated by the qFatal() function.
+ \omitvalue QtSystemMsg
+
+ \c QtInfoMsg was added in Qt 5.5.
+
+ \sa QtMessageHandler, qInstallMessageHandler()
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h
index 4a528a2973..aa0ab93a2d 100644
--- a/src/corelib/global/qlogging.h
+++ b/src/corelib/global/qlogging.h
@@ -1,50 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOGGING_H
#define QLOGGING_H
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
+#include <QtCore/qcontainerfwd.h>
+
#if 0
// header is automatically included in qglobal.h
#pragma qt_no_master_include
+#pragma qt_class(QtLogging)
#endif
QT_BEGIN_NAMESPACE
@@ -57,17 +25,29 @@ QT_BEGIN_NAMESPACE
class QDebug;
class QNoDebug;
-enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtInfoMsg, QtSystemMsg = QtCriticalMsg };
+enum QtMsgType {
+ QtDebugMsg,
+ QtWarningMsg,
+ QtCriticalMsg,
+ QtFatalMsg,
+ QtInfoMsg,
+#if QT_DEPRECATED_SINCE(6, 7)
+ QtSystemMsg Q_DECL_ENUMERATOR_DEPRECATED_X("Use QtCriticalMsg instead.") = QtCriticalMsg
+#endif
+};
+
+class QInternalMessageLogContext;
class QMessageLogContext
{
Q_DISABLE_COPY(QMessageLogContext)
public:
- Q_DECL_CONSTEXPR QMessageLogContext() noexcept = default;
- Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) noexcept
+ static constexpr int CurrentVersion = 2;
+ constexpr QMessageLogContext() noexcept = default;
+ constexpr QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) noexcept
: line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
- int version = 2;
+ int version = CurrentVersion;
int line = 0;
const char *file = nullptr;
const char *function = nullptr;
@@ -76,20 +56,26 @@ public:
private:
QMessageLogContext &copyContextFrom(const QMessageLogContext &logContext) noexcept;
+ friend class QInternalMessageLogContext;
friend class QMessageLogger;
- friend class QDebug;
};
class QLoggingCategory;
+#if defined(Q_CC_MSVC_ONLY)
+# define QT_MESSAGE_LOGGER_NORETURN
+#else
+# define QT_MESSAGE_LOGGER_NORETURN Q_NORETURN
+#endif
+
class Q_CORE_EXPORT QMessageLogger
{
Q_DISABLE_COPY(QMessageLogger)
public:
- Q_DECL_CONSTEXPR QMessageLogger() : context() {}
- Q_DECL_CONSTEXPR QMessageLogger(const char *file, int line, const char *function)
+ constexpr QMessageLogger() : context() {}
+ constexpr QMessageLogger(const char *file, int line, const char *function)
: context(file, line, function, "default") {}
- Q_DECL_CONSTEXPR QMessageLogger(const char *file, int line, const char *function, const char *category)
+ constexpr QMessageLogger(const char *file, int line, const char *function, const char *category)
: context(file, line, function, category) {}
void debug(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
@@ -100,6 +86,8 @@ public:
void warning(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
Q_DECL_COLD_FUNCTION
void critical(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
+ QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION
+ void fatal(const char *msg, ...) const noexcept Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
typedef const QLoggingCategory &(*CategoryFunction)();
@@ -115,12 +103,10 @@ public:
void critical(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
Q_DECL_COLD_FUNCTION
void critical(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
-
-#ifndef Q_CC_MSVC
- Q_NORETURN
-#endif
- Q_DECL_COLD_FUNCTION
- void fatal(const char *msg, ...) const noexcept Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
+ QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION
+ void fatal(const QLoggingCategory &cat, const char *msg, ...) const noexcept Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
+ QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION
+ void fatal(CategoryFunction catFunc, const char *msg, ...) const noexcept Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
#ifndef QT_NO_DEBUG_STREAM
QDebug debug() const;
@@ -129,12 +115,24 @@ public:
QDebug info() const;
QDebug info(const QLoggingCategory &cat) const;
QDebug info(CategoryFunction catFunc) const;
+ Q_DECL_COLD_FUNCTION
QDebug warning() const;
+ Q_DECL_COLD_FUNCTION
QDebug warning(const QLoggingCategory &cat) const;
+ Q_DECL_COLD_FUNCTION
QDebug warning(CategoryFunction catFunc) const;
+ Q_DECL_COLD_FUNCTION
QDebug critical() const;
+ Q_DECL_COLD_FUNCTION
QDebug critical(const QLoggingCategory &cat) const;
+ Q_DECL_COLD_FUNCTION
QDebug critical(CategoryFunction catFunc) const;
+ Q_DECL_COLD_FUNCTION
+ QDebug fatal() const;
+ Q_DECL_COLD_FUNCTION
+ QDebug fatal(const QLoggingCategory &cat) const;
+ Q_DECL_COLD_FUNCTION
+ QDebug fatal(CategoryFunction catFunc) const;
QNoDebug noDebug() const noexcept;
#endif // QT_NO_DEBUG_STREAM
@@ -143,6 +141,8 @@ private:
QMessageLogContext context;
};
+#undef QT_MESSAGE_LOGGER_NORETURN
+
#if !defined(QT_MESSAGELOGCONTEXT) && !defined(QT_NO_MESSAGELOGCONTEXT)
# if defined(QT_NO_DEBUG)
# define QT_NO_MESSAGELOGCONTEXT
@@ -188,11 +188,6 @@ Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &contex
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(int code, const char *msg, ...);
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(const char *msg, ...);
-#if QT_DEPRECATED_SINCE(5, 0)// deprecated. Use qInstallMessageHandler instead!
-typedef void (*QtMsgHandler)(QtMsgType, const char *);
-Q_CORE_EXPORT QT_DEPRECATED QtMsgHandler qInstallMsgHandler(QtMsgHandler);
-#endif
-
typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);
Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler);
@@ -200,5 +195,8 @@ Q_CORE_EXPORT void qSetMessagePattern(const QString &messagePattern);
Q_CORE_EXPORT QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context,
const QString &buf);
+Q_DECL_COLD_FUNCTION
+Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
+
QT_END_NAMESPACE
#endif // QLOGGING_H
diff --git a/src/corelib/global/qlogging_p.h b/src/corelib/global/qlogging_p.h
index 3d0c097ffe..bc331c80c0 100644
--- a/src/corelib/global/qlogging_p.h
+++ b/src/corelib/global/qlogging_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOGGING_P_H
#define QLOGGING_P_H
@@ -51,6 +15,24 @@
// We mean it.
//
+#include <QtCore/private/qglobal_p.h>
+#include "qlogging.h"
+#include "qloggingcategory.h"
+
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(regularexpression)
+# if __has_include(<cxxabi.h>) && QT_CONFIG(backtrace)
+# include <optional>
+# include "qvarlengtharray.h"
+# define QLOGGING_USE_EXECINFO_BACKTRACE
+# define QLOGGING_HAVE_BACKTRACE
+# elif QT_CONFIG(cxx23_stacktrace)
+# include <optional>
+# include <stacktrace>
+# define QLOGGING_USE_STD_BACKTRACE
+# define QLOGGING_HAVE_BACKTRACE
+# endif
+#endif // QT_BOOTSTRAPPED
+
QT_BEGIN_NAMESPACE
namespace QtPrivate {
@@ -59,6 +41,38 @@ Q_CORE_EXPORT bool shouldLogToStderr();
}
+class QInternalMessageLogContext : public QMessageLogContext
+{
+public:
+ static constexpr int DefaultBacktraceDepth = 32;
+
+#if defined(QLOGGING_USE_EXECINFO_BACKTRACE)
+ using BacktraceStorage = QVarLengthArray<void *, DefaultBacktraceDepth>;
+#elif defined(QLOGGING_USE_STD_BACKTRACE)
+ using BacktraceStorage = std::stacktrace;
+#else
+ using BacktraceStorage = bool; // dummy
+#endif
+
+ std::optional<BacktraceStorage> backtrace;
+
+ Q_ALWAYS_INLINE QInternalMessageLogContext(const QMessageLogContext &logContext)
+ {
+ int backtraceFrames = initFrom(logContext);
+ if (backtraceFrames)
+ populateBacktrace(backtraceFrames);
+ }
+ QInternalMessageLogContext(const QMessageLogContext &logContext,
+ const QLoggingCategory &categoryOverride)
+ : QInternalMessageLogContext(logContext)
+ {
+ category = categoryOverride.categoryName();
+ }
+
+ int initFrom(const QMessageLogContext &logContext);
+ void populateBacktrace(int frameCount);
+};
+
QT_END_NAMESPACE
#endif // QLOGGING_P_H
diff --git a/src/corelib/global/qmalloc.cpp b/src/corelib/global/qmalloc.cpp
index b071c1df62..d413a35c6b 100644
--- a/src/corelib/global/qmalloc.cpp
+++ b/src/corelib/global/qmalloc.cpp
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qmalloc.h"
#include "qplatformdefs.h"
#include <stdlib.h>
@@ -49,29 +14,6 @@
QT_BEGIN_NAMESPACE
-#if !QT_DEPRECATED_SINCE(5, 0)
-// Make sure they're defined to be exported
-Q_CORE_EXPORT void *qMalloc(size_t size) Q_ALLOC_SIZE(1);
-Q_CORE_EXPORT void qFree(void *ptr);
-Q_CORE_EXPORT void *qRealloc(void *ptr, size_t size) Q_ALLOC_SIZE(2);
-#endif
-
-
-void *qMalloc(size_t size)
-{
- return ::malloc(size);
-}
-
-void qFree(void *ptr)
-{
- ::free(ptr);
-}
-
-void *qRealloc(void *ptr, size_t size)
-{
- return ::realloc(ptr, size);
-}
-
void *qMallocAligned(size_t size, size_t alignment)
{
return qReallocAligned(nullptr, size, 0, alignment);
@@ -81,9 +23,9 @@ void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t align
{
// fake an aligned allocation
void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : nullptr;
- if (alignment <= sizeof(void*)) {
+ if (alignment <= sizeof(void *)) {
// special, fast case
- void **newptr = static_cast<void **>(realloc(actualptr, newsize + sizeof(void*)));
+ void **newptr = static_cast<void **>(realloc(actualptr, newsize + sizeof(void *)));
if (!newptr)
return nullptr;
if (newptr == actualptr) {
@@ -103,6 +45,7 @@ void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t align
// However, we need to store the actual pointer, so we need to allocate actually size +
// alignment anyway.
+ qptrdiff oldoffset = oldptr ? static_cast<char *>(oldptr) - static_cast<char *>(actualptr) : 0;
void *real = realloc(actualptr, newsize + alignment);
if (!real)
return nullptr;
@@ -112,7 +55,6 @@ void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t align
void **faked_ptr = reinterpret_cast<void **>(faked);
if (oldptr) {
- qptrdiff oldoffset = static_cast<char *>(oldptr) - static_cast<char *>(actualptr);
qptrdiff newoffset = reinterpret_cast<char *>(faked_ptr) - static_cast<char *>(real);
if (oldoffset != newoffset)
memmove(faked_ptr, static_cast<char *>(real) + oldoffset, qMin(oldsize, newsize));
@@ -135,4 +77,3 @@ void qFreeAligned(void *ptr)
}
QT_END_NAMESPACE
-
diff --git a/src/corelib/global/qmalloc.h b/src/corelib/global/qmalloc.h
new file mode 100644
index 0000000000..83dfff358b
--- /dev/null
+++ b/src/corelib/global/qmalloc.h
@@ -0,0 +1,26 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMALLOC_H
+#define QMALLOC_H
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
+
+#include <cstddef> // size_t
+
+#if 0
+#pragma qt_class(QtMalloc)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT void *qMallocAligned(size_t size, size_t alignment) Q_ALLOC_SIZE(1);
+Q_CORE_EXPORT void *qReallocAligned(void *ptr, size_t size, size_t oldsize, size_t alignment) Q_ALLOC_SIZE(2);
+Q_CORE_EXPORT void qFreeAligned(void *ptr);
+
+QT_END_NAMESPACE
+
+#endif // QMALLOC_H
diff --git a/src/corelib/global/qmemory_p.h b/src/corelib/global/qmemory_p.h
deleted file mode 100644
index ac791385bd..0000000000
--- a/src/corelib/global/qmemory_p.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QMEMORY_P_H
-#define QMEMORY_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-
-#include <memory>
-#include <type_traits>
-#include <utility>
-
-QT_BEGIN_NAMESPACE
-
-// Like std::make_unique, but less ambitious, so keep as private API, for use in Qt itself:
-template <typename T, typename... Args>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-qt_make_unique(Args &&...args)
-{
- return std::unique_ptr<T>{new T(std::forward<Args>(args)...)};
-}
-
-QT_END_NAMESPACE
-
-#endif /* QMEMORY_P_H */
diff --git a/src/corelib/global/qminmax.h b/src/corelib/global/qminmax.h
new file mode 100644
index 0000000000..e6fb62bf9d
--- /dev/null
+++ b/src/corelib/global/qminmax.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMINMAX_H
+#define QMINMAX_H
+
+#if 0
+#pragma qt_class(QtMinMax)
+#pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qassert.h>
+#include <QtCore/qtconfigmacros.h>
+
+#include <type_traits>
+
+QT_BEGIN_NAMESPACE
+
+namespace QTypeTraits {
+
+namespace detail {
+template<typename T, typename U,
+ typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> &&
+ std::is_floating_point_v<T> == std::is_floating_point_v<U> &&
+ std::is_signed_v<T> == std::is_signed_v<U> &&
+ !std::is_same_v<T, bool> && !std::is_same_v<U, bool> &&
+ !std::is_same_v<T, char> && !std::is_same_v<U, char>>>
+struct Promoted
+{
+ using type = decltype(T() + U());
+};
+}
+
+template <typename T, typename U>
+using Promoted = typename detail::Promoted<T, U>::type;
+
+}
+
+template <typename T>
+constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
+template <typename T>
+constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
+template <typename T>
+constexpr inline const T &qBound(const T &min, const T &val, const T &max)
+{
+ Q_ASSERT(!(max < min));
+ return qMax(min, qMin(max, val));
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qMin(const T &a, const U &b)
+{
+ using P = QTypeTraits::Promoted<T, U>;
+ P _a = a;
+ P _b = b;
+ return (_a < _b) ? _a : _b;
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qMax(const T &a, const U &b)
+{
+ using P = QTypeTraits::Promoted<T, U>;
+ P _a = a;
+ P _b = b;
+ return (_a < _b) ? _b : _a;
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const U &val, const T &max)
+{
+ Q_ASSERT(!(max < min));
+ return qMax(min, qMin(max, val));
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const T &val, const U &max)
+{
+ using P = QTypeTraits::Promoted<T, U>;
+ Q_ASSERT(!(P(max) < P(min)));
+ return qMax(min, qMin(max, val));
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qBound(const U &min, const T &val, const T &max)
+{
+ using P = QTypeTraits::Promoted<T, U>;
+ Q_ASSERT(!(P(max) < P(min)));
+ return qMax(min, qMin(max, val));
+}
+
+QT_END_NAMESPACE
+
+#endif // QMINMAX_H
diff --git a/src/corelib/global/qminmax.qdoc b/src/corelib/global/qminmax.qdoc
new file mode 100644
index 0000000000..36f680b4c7
--- /dev/null
+++ b/src/corelib/global/qminmax.qdoc
@@ -0,0 +1,39 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*! \fn template <typename T> const T &qMin(const T &a, const T &b)
+ \relates <QtMinMax>
+
+ Returns the minimum of \a a and \a b.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 13
+
+ \sa qMax(), qBound()
+*/
+
+/*! \fn template <typename T> const T &qMax(const T &a, const T &b)
+ \relates <QtMinMax>
+
+ Returns the maximum of \a a and \a b.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 14
+
+ \sa qMin(), qBound()
+*/
+
+/*! \fn template <typename T> const T &qBound(const T &min, const T &val, const T &max)
+ \relates <QtMinMax>
+
+ Returns \a val bounded by \a min and \a max. This is equivalent
+ to qMax(\a min, qMin(\a val, \a max)).
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 15
+
+ \sa qMin(), qMax()
+*/
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index cb1c08e4fa..2398c0a1a4 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1,46 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QNAMESPACE_H
#define QNAMESPACE_H
+#if 0
+#pragma qt_class(Qt)
+#endif
+
#include <QtCore/qglobal.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qtmetamacros.h>
#if defined(__OBJC__) && !defined(__cplusplus)
@@ -77,40 +47,17 @@ namespace Qt {
transparent
};
- enum KeyboardModifier {
- NoModifier = 0x00000000,
- ShiftModifier = 0x02000000,
- ControlModifier = 0x04000000,
- AltModifier = 0x08000000,
- MetaModifier = 0x10000000,
- KeypadModifier = 0x20000000,
- GroupSwitchModifier = 0x40000000,
- // Do not extend the mask to include 0x01000000
- KeyboardModifierMask = 0xfe000000
- };
- Q_DECLARE_FLAGS(KeyboardModifiers, KeyboardModifier)
- Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardModifiers)
-
- //shorter names for shortcuts
- // The use of all-caps identifiers has the potential for clashing with
- // user-defined or third-party macros. More so when the identifiers are not
- // "namespace"-prefixed. This is considered bad practice and is why
- // KeypadModifier was not added to the Modifier enum.
- enum Modifier {
- META = Qt::MetaModifier,
- SHIFT = Qt::ShiftModifier,
- CTRL = Qt::ControlModifier,
- ALT = Qt::AltModifier,
- MODIFIER_MASK = KeyboardModifierMask,
- UNICODE_ACCEL = 0x00000000
+ enum class ColorScheme {
+ Unknown,
+ Light,
+ Dark,
};
enum MouseButton {
NoButton = 0x00000000,
LeftButton = 0x00000001,
RightButton = 0x00000002,
- MidButton = 0x00000004, // ### Qt 6: remove me
- MiddleButton = MidButton,
+ MiddleButton = 0x00000004,
BackButton = 0x00000008,
XButton1 = BackButton,
ExtraButton1 = XButton1,
@@ -236,6 +183,7 @@ namespace Qt {
// size of a multi-variant string.
TextLongestVariant = 0x80000
};
+ Q_DECLARE_MIXED_ENUM_OPERATORS_SYMMETRIC(int, AlignmentFlag, TextFlag)
enum TextElideMode {
ElideLeft,
@@ -243,6 +191,7 @@ namespace Qt {
ElideMiddle,
ElideNone
};
+ Q_DECLARE_MIXED_ENUM_OPERATORS_SYMMETRIC(int, TextElideMode, TextFlag)
enum WhiteSpaceMode {
WhiteSpaceNormal,
@@ -264,7 +213,7 @@ namespace Qt {
ToolTip = Popup | Sheet,
SplashScreen = ToolTip | Dialog,
Desktop = 0x00000010 | Window,
- SubWindow = 0x00000012,
+ SubWindow = 0x00000012, // Note QTBUG-115729 before using
ForeignWindow = 0x00000020 | Window,
CoverWindow = 0x00000040 | Window,
@@ -334,20 +283,15 @@ namespace Qt {
WA_Disabled = 0,
WA_UnderMouse = 1,
WA_MouseTracking = 2,
- WA_ContentsPropagated = 3, // ## deprecated
+ // Formerly, 3 was WA_ContentsPropagated.
WA_OpaquePaintEvent = 4,
-#if QT_DEPRECATED_SINCE(5, 14)
- WA_NoBackground Q_DECL_ENUMERATOR_DEPRECATED = WA_OpaquePaintEvent,
-#endif
WA_StaticContents = 5,
WA_LaidOut = 7,
WA_PaintOnScreen = 8,
WA_NoSystemBackground = 9,
WA_UpdatesDisabled = 10,
WA_Mapped = 11,
-#if QT_DEPRECATED_SINCE(5, 14)
- WA_MacNoClickThrough Q_DECL_ENUMERATOR_DEPRECATED = 12,
-#endif
+ // Formerly, 12 was WA_MacNoClickThrough.
WA_InputMethodEnabled = 14,
WA_WState_Visible = 15,
WA_WState_Hidden = 16,
@@ -365,10 +309,7 @@ namespace Qt {
WA_Moved = 43,
WA_PendingUpdate = 44,
WA_InvalidSize = 45,
-#if QT_DEPRECATED_SINCE(5, 14)
- WA_MacBrushedMetal Q_DECL_ENUMERATOR_DEPRECATED = 46,
- WA_MacMetalStyle Q_DECL_ENUMERATOR_DEPRECATED = 46,
-#endif
+ // Formerly 46 was WA_MacBrushedMetal and WA_MacMetalStyle.
WA_CustomWhatsThis = 47,
WA_LayoutOnEntireRect = 48,
WA_OutsideWSRange = 49,
@@ -389,14 +330,13 @@ namespace Qt {
WA_WState_Reparented = 63,
WA_WState_ConfigPending = 64,
WA_WState_Polished = 66,
- WA_WState_DND = 67, // ## deprecated
+ // Formerly, 67 was WA_WState_DND.
WA_WState_OwnSizePolicy = 68,
WA_WState_ExplicitShowHide = 69,
- WA_ShowModal = 70, // ## deprecated
+ WA_ShowModal = 70, // ## deprecated since since 4.5.1 but still in use :-(
WA_MouseNoMask = 71,
- WA_GroupLeader = 72, // ## deprecated
- WA_NoMousePropagation = 73, // ## for now, might go away.
+ WA_NoMousePropagation = 73, // for now, might go away.
WA_Hover = 74,
WA_InputMethodTransparent = 75, // Don't reset IM when user clicks on this (for virtual keyboards on embedded)
WA_QuitOnClose = 76,
@@ -405,7 +345,6 @@ namespace Qt {
WA_AcceptDrops = 78,
WA_DropSiteRegistered = 79, // internal
- WA_ForceAcceptDrops = WA_DropSiteRegistered, // ## deprecated
WA_WindowPropagation = 80,
@@ -425,9 +364,7 @@ namespace Qt {
WA_LayoutUsesWidgetRect = 92,
WA_StyledBackground = 93, // internal
-#if QT_DEPRECATED_SINCE(5, 14)
- WA_MSWindowsUseDirect3D Q_DECL_ENUMERATOR_DEPRECATED = 94,
-#endif
+ // Formerly, 94 was WA_MSWindowsUseDirect3D.
WA_CanHostQMdiSubWindowTitleBar = 95, // Internal
WA_MacAlwaysShowToolWindow = 96, // Mac only
@@ -441,7 +378,7 @@ namespace Qt {
WA_NativeWindow = 100,
WA_DontCreateNativeAncestors = 101,
- WA_MacVariableSize = 102, // Mac only
+ // Formerly WA_MacVariableSize = 102, // Mac only
WA_DontShowOnScreen = 103,
@@ -459,9 +396,7 @@ namespace Qt {
WA_X11NetWmWindowTypeNotification = 114,
WA_X11NetWmWindowTypeCombo = 115,
WA_X11NetWmWindowTypeDND = 116,
-#if QT_DEPRECATED_SINCE(5, 14)
- WA_MacFrameworkScaled Q_DECL_ENUMERATOR_DEPRECATED = 117,
-#endif
+ // Formerly, 117 was WA_MacFrameworkScaled.
WA_SetWindowModality = 118,
WA_WState_WindowOpacitySet = 119, // internal
WA_TranslucentBackground = 120,
@@ -471,7 +406,7 @@ namespace Qt {
WA_TouchPadAcceptSingleTouchEvents = 123,
WA_X11DoNotAcceptFocus = 126,
- WA_MacNoShadow = 127,
+ // Formerly, 127 was WA_MacNoShadow
WA_AlwaysStackOnTop = 128,
@@ -488,7 +423,7 @@ namespace Qt {
enum ApplicationAttribute
{
// AA_ImmediateWidgetCreation = 0,
- // AA_MSWindowsUseDirect3DByDefault = 1,
+ AA_QtQuickUseDefaultSizePolicy = 1 QT_TECH_PREVIEW_API,
AA_DontShowIconsInMenus = 2,
AA_NativeWindows = 3,
AA_DontCreateNativeWidgetSiblings = 4,
@@ -497,18 +432,28 @@ namespace Qt {
AA_MacDontSwapCtrlAndMeta = 7,
AA_Use96Dpi = 8,
AA_DisableNativeVirtualKeyboard = 9,
- // AA_X11InitThreads = 10,
+ AA_DontUseNativeMenuWindows = 10,
AA_SynthesizeTouchForUnhandledMouseEvents = 11,
AA_SynthesizeMouseForUnhandledTouchEvents = 12,
- AA_UseHighDpiPixmaps = 13,
+#if QT_DEPRECATED_SINCE(6, 0)
+ AA_UseHighDpiPixmaps Q_DECL_ENUMERATOR_DEPRECATED_X(
+ "High-DPI pixmaps are always enabled. " \
+ "This attribute no longer has any effect.") = 13,
+#endif
AA_ForceRasterWidgets = 14,
AA_UseDesktopOpenGL = 15,
AA_UseOpenGLES = 16,
AA_UseSoftwareOpenGL = 17,
AA_ShareOpenGLContexts = 18,
AA_SetPalette = 19,
- AA_EnableHighDpiScaling = 20,
- AA_DisableHighDpiScaling = 21,
+#if QT_DEPRECATED_SINCE(6, 0)
+ AA_EnableHighDpiScaling Q_DECL_ENUMERATOR_DEPRECATED_X(
+ "High-DPI scaling is always enabled. " \
+ "This attribute no longer has any effect.") = 20,
+ AA_DisableHighDpiScaling Q_DECL_ENUMERATOR_DEPRECATED_X(
+ "High-DPI scaling is always enabled. " \
+ "This attribute no longer has any effect.") = 21,
+#endif
AA_UseStyleSheetPropagationInWidgetStyles = 22,
AA_DontUseNativeDialogs = 23,
AA_SynthesizeMouseForUnhandledTabletEvents = 24,
@@ -517,7 +462,7 @@ namespace Qt {
AA_DisableShaderDiskCache = 27,
AA_DontShowShortcutsInContextMenus = 28,
AA_CompressTabletEvents = 29,
- // AA_DisableWindowContextHelpButton = 30,
+ AA_DontUsePopupWindows = 30,
AA_DisableSessionManager = 31,
// Add new attributes before this line
@@ -564,77 +509,8 @@ namespace Qt {
};
enum Key {
- Key_Escape = 0x01000000, // misc keys
- Key_Tab = 0x01000001,
- Key_Backtab = 0x01000002,
- Key_Backspace = 0x01000003,
- Key_Return = 0x01000004,
- Key_Enter = 0x01000005,
- Key_Insert = 0x01000006,
- Key_Delete = 0x01000007,
- Key_Pause = 0x01000008,
- Key_Print = 0x01000009, // print screen
- Key_SysReq = 0x0100000a,
- Key_Clear = 0x0100000b,
- Key_Home = 0x01000010, // cursor movement
- Key_End = 0x01000011,
- Key_Left = 0x01000012,
- Key_Up = 0x01000013,
- Key_Right = 0x01000014,
- Key_Down = 0x01000015,
- Key_PageUp = 0x01000016,
- Key_PageDown = 0x01000017,
- Key_Shift = 0x01000020, // modifiers
- Key_Control = 0x01000021,
- Key_Meta = 0x01000022,
- Key_Alt = 0x01000023,
- Key_CapsLock = 0x01000024,
- Key_NumLock = 0x01000025,
- Key_ScrollLock = 0x01000026,
- Key_F1 = 0x01000030, // function keys
- Key_F2 = 0x01000031,
- Key_F3 = 0x01000032,
- Key_F4 = 0x01000033,
- Key_F5 = 0x01000034,
- Key_F6 = 0x01000035,
- Key_F7 = 0x01000036,
- Key_F8 = 0x01000037,
- Key_F9 = 0x01000038,
- Key_F10 = 0x01000039,
- Key_F11 = 0x0100003a,
- Key_F12 = 0x0100003b,
- Key_F13 = 0x0100003c,
- Key_F14 = 0x0100003d,
- Key_F15 = 0x0100003e,
- Key_F16 = 0x0100003f,
- Key_F17 = 0x01000040,
- Key_F18 = 0x01000041,
- Key_F19 = 0x01000042,
- Key_F20 = 0x01000043,
- Key_F21 = 0x01000044,
- Key_F22 = 0x01000045,
- Key_F23 = 0x01000046,
- Key_F24 = 0x01000047,
- Key_F25 = 0x01000048, // F25 .. F35 only on X11
- Key_F26 = 0x01000049,
- Key_F27 = 0x0100004a,
- Key_F28 = 0x0100004b,
- Key_F29 = 0x0100004c,
- Key_F30 = 0x0100004d,
- Key_F31 = 0x0100004e,
- Key_F32 = 0x0100004f,
- Key_F33 = 0x01000050,
- Key_F34 = 0x01000051,
- Key_F35 = 0x01000052,
- Key_Super_L = 0x01000053, // extra keys
- Key_Super_R = 0x01000054,
- Key_Menu = 0x01000055,
- Key_Hyper_L = 0x01000056,
- Key_Hyper_R = 0x01000057,
- Key_Help = 0x01000058,
- Key_Direction_L = 0x01000059,
- Key_Direction_R = 0x01000060,
- Key_Space = 0x20, // 7 bit printable ASCII
+ // Unicode Basic Latin block (0x00-0x7f)
+ Key_Space = 0x20,
Key_Any = Key_Space,
Key_Exclam = 0x21,
Key_QuoteDbl = 0x22,
@@ -705,6 +581,7 @@ namespace Qt {
Key_BraceRight = 0x7d,
Key_AsciiTilde = 0x7e,
+ // Unicode Latin-1 Supplement block (0x80-0xff)
Key_nobreakspace = 0x0a0,
Key_exclamdown = 0x0a1,
Key_cent = 0x0a2,
@@ -726,7 +603,11 @@ namespace Qt {
Key_twosuperior = 0x0b2,
Key_threesuperior = 0x0b3,
Key_acute = 0x0b4,
- Key_mu = 0x0b5,
+ Key_micro = 0x0b5,
+#if QT_DEPRECATED_SINCE(6, 11)
+ Key_mu Q_DECL_ENUMERATOR_DEPRECATED_X("This key was misnamed, use Key_micro instead")
+ = Key_micro,
+#endif
Key_paragraph = 0x0b6,
Key_periodcentered = 0x0b7,
Key_cedilla = 0x0b8,
@@ -772,6 +653,84 @@ namespace Qt {
Key_division = 0x0f7,
Key_ydiaeresis = 0x0ff,
+ // The rest of the Unicode values are skipped here,
+ // so that we can represent them along with Qt::Keys
+ // in the same data type. The maximum Unicode value
+ // is 0x0010ffff, so we start our custom keys at
+ // 0x01000000 to not clash with the Unicode values,
+ // but still give plenty of room to grow.
+
+ Key_Escape = 0x01000000, // misc keys
+ Key_Tab = 0x01000001,
+ Key_Backtab = 0x01000002,
+ Key_Backspace = 0x01000003,
+ Key_Return = 0x01000004,
+ Key_Enter = 0x01000005,
+ Key_Insert = 0x01000006,
+ Key_Delete = 0x01000007,
+ Key_Pause = 0x01000008,
+ Key_Print = 0x01000009, // print screen
+ Key_SysReq = 0x0100000a,
+ Key_Clear = 0x0100000b,
+ Key_Home = 0x01000010, // cursor movement
+ Key_End = 0x01000011,
+ Key_Left = 0x01000012,
+ Key_Up = 0x01000013,
+ Key_Right = 0x01000014,
+ Key_Down = 0x01000015,
+ Key_PageUp = 0x01000016,
+ Key_PageDown = 0x01000017,
+ Key_Shift = 0x01000020, // modifiers
+ Key_Control = 0x01000021,
+ Key_Meta = 0x01000022,
+ Key_Alt = 0x01000023,
+ Key_CapsLock = 0x01000024,
+ Key_NumLock = 0x01000025,
+ Key_ScrollLock = 0x01000026,
+ Key_F1 = 0x01000030, // function keys
+ Key_F2 = 0x01000031,
+ Key_F3 = 0x01000032,
+ Key_F4 = 0x01000033,
+ Key_F5 = 0x01000034,
+ Key_F6 = 0x01000035,
+ Key_F7 = 0x01000036,
+ Key_F8 = 0x01000037,
+ Key_F9 = 0x01000038,
+ Key_F10 = 0x01000039,
+ Key_F11 = 0x0100003a,
+ Key_F12 = 0x0100003b,
+ Key_F13 = 0x0100003c,
+ Key_F14 = 0x0100003d,
+ Key_F15 = 0x0100003e,
+ Key_F16 = 0x0100003f,
+ Key_F17 = 0x01000040,
+ Key_F18 = 0x01000041,
+ Key_F19 = 0x01000042,
+ Key_F20 = 0x01000043,
+ Key_F21 = 0x01000044,
+ Key_F22 = 0x01000045,
+ Key_F23 = 0x01000046,
+ Key_F24 = 0x01000047,
+ Key_F25 = 0x01000048, // F25 .. F35 only on X11
+ Key_F26 = 0x01000049,
+ Key_F27 = 0x0100004a,
+ Key_F28 = 0x0100004b,
+ Key_F29 = 0x0100004c,
+ Key_F30 = 0x0100004d,
+ Key_F31 = 0x0100004e,
+ Key_F32 = 0x0100004f,
+ Key_F33 = 0x01000050,
+ Key_F34 = 0x01000051,
+ Key_F35 = 0x01000052,
+ Key_Super_L = 0x01000053, // extra keys
+ Key_Super_R = 0x01000054,
+ Key_Menu = 0x01000055,
+ Key_Hyper_L = 0x01000056,
+ Key_Hyper_R = 0x01000057,
+ Key_Help = 0x01000058,
+ Key_Direction_L = 0x01000059,
+ Key_Direction_R = 0x01000060,
+
// International input method support (X keycode - 0xEE00, the
// definition follows Qt/Embedded 2.3.7) Only interesting if
// you are writing your own input method
@@ -901,8 +860,8 @@ namespace Qt {
Key_MediaPrevious = 0x01000082,
Key_MediaNext = 0x01000083,
Key_MediaRecord = 0x01000084,
- Key_MediaPause = 0x1000085,
- Key_MediaTogglePlayPause = 0x1000086,
+ Key_MediaPause = 0x01000085,
+ Key_MediaTogglePlayPause = 0x01000086,
Key_HomePage = 0x01000090,
Key_Favorites = 0x01000091,
Key_Search = 0x01000092,
@@ -1019,6 +978,7 @@ namespace Qt {
Key_Suspend = 0x0100010c,
Key_ContrastAdjust = 0x0100010d,
+ // We can remove these two for Qt 7:
Key_LaunchG = 0x0100010e,
Key_LaunchH = 0x0100010f,
@@ -1083,9 +1043,42 @@ namespace Qt {
Key_Camera = 0x01100020,
Key_CameraFocus = 0x01100021,
+ // WARNING: Do not add any keys in the range 0x01200000 to 0xffffffff,
+ // as those bits are reserved for the Qt::KeyboardModifier enum below.
+
Key_unknown = 0x01ffffff
};
+ enum KeyboardModifier {
+ NoModifier = 0x00000000,
+ ShiftModifier = 0x02000000,
+ ControlModifier = 0x04000000,
+ AltModifier = 0x08000000,
+ MetaModifier = 0x10000000,
+ KeypadModifier = 0x20000000,
+ GroupSwitchModifier = 0x40000000,
+ // Do not extend the mask to include 0x01000000
+ KeyboardModifierMask = 0xfe000000
+ };
+ Q_DECLARE_FLAGS(KeyboardModifiers, KeyboardModifier)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardModifiers)
+
+ //shorter names for shortcuts
+ // The use of all-caps identifiers has the potential for clashing with
+ // user-defined or third-party macros. More so when the identifiers are not
+ // "namespace"-prefixed. This is considered bad practice and is why
+ // KeypadModifier was not added to the Modifier enum.
+ // ### Qt 7: consider deprecating in favor of KeyboardModifier.
+ enum Modifier {
+ META = Qt::MetaModifier,
+ SHIFT = Qt::ShiftModifier,
+ CTRL = Qt::ControlModifier,
+ ALT = Qt::AltModifier,
+ MODIFIER_MASK = KeyboardModifierMask,
+ };
+ Q_DECLARE_FLAGS(Modifiers, Modifier)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(Modifiers)
+
enum ArrowType {
NoArrow,
UpArrow,
@@ -1292,7 +1285,8 @@ namespace Qt {
DirectConnection,
QueuedConnection,
BlockingQueuedConnection,
- UniqueConnection = 0x80
+ UniqueConnection = 0x80,
+ SingleShotConnection = 0x100,
};
enum ShortcutContext {
@@ -1365,9 +1359,6 @@ namespace Qt {
enum InputMethodQuery {
ImEnabled = 0x1,
ImCursorRectangle = 0x2,
-#if QT_DEPRECATED_SINCE(5, 14)
- ImMicroFocus Q_DECL_ENUMERATOR_DEPRECATED = 0x2,
-#endif
ImFont = 0x4,
ImCursorPosition = 0x8,
ImSurroundingText = 0x10,
@@ -1384,6 +1375,7 @@ namespace Qt {
ImAnchorRectangle = 0x4000,
ImInputItemClipRectangle = 0x8000,
+ ImReadOnly = 0x10000,
ImPlatformData = 0x80000000,
ImQueryInput = ImCursorRectangle | ImCursorPosition | ImSurroundingText |
ImCurrentSelection | ImAnchorRectangle | ImAnchorPosition,
@@ -1449,6 +1441,7 @@ namespace Qt {
enum LayoutDirection {
LeftToRight,
RightToLeft,
+ // ### Qt 7: make auto the first one (with value 0)
LayoutDirectionAuto
};
@@ -1522,9 +1515,6 @@ namespace Qt {
ItemIsUserCheckable = 16,
ItemIsEnabled = 32,
ItemIsAutoTristate = 64,
-#if QT_DEPRECATED_SINCE(5, 6)
- ItemIsTristate = ItemIsAutoTristate,
-#endif
ItemNeverHasChildren = 128,
ItemIsUserTristate = 256
};
@@ -1537,11 +1527,9 @@ namespace Qt {
MatchStartsWith = 2,
MatchEndsWith = 3,
MatchRegularExpression = 4,
-#if QT_DEPRECATED_SINCE(5, 15)
- MatchRegExp Q_DECL_ENUMERATOR_DEPRECATED_X("MatchRegExp is deprecated. Use MatchRegularExpression instead") = MatchRegularExpression,
-#endif
MatchWildcard = 5,
MatchFixedString = 8,
+ MatchTypeMask = 0x0F,
MatchCaseSensitive = 16,
MatchWrap = 32,
MatchRecursive = 64
@@ -1550,9 +1538,6 @@ namespace Qt {
Q_DECLARE_OPERATORS_FOR_FLAGS(MatchFlags)
typedef void * HANDLE;
-#if QT_DEPRECATED_SINCE(5, 0)
- typedef WindowFlags WFlags;
-#endif
enum WindowModality {
NonModal,
@@ -1601,16 +1586,15 @@ namespace Qt {
TitleBarArea // For move
};
-#if defined(Q_COMPILER_CONSTEXPR)
enum class Initialization {
Uninitialized
};
- static constexpr Q_DECL_UNUSED Initialization Uninitialized = Initialization::Uninitialized;
-#else
- enum Initialization {
- Uninitialized
+ inline constexpr Initialization Uninitialized = Initialization::Uninitialized;
+
+ struct Disambiguated_t {
+ explicit Disambiguated_t() = default;
};
-#endif
+ inline constexpr Disambiguated_t Disambiguated{};
enum CoordinateSystem {
DeviceCoordinates,
@@ -1618,6 +1602,7 @@ namespace Qt {
};
enum TouchPointState {
+ TouchPointUnknownState = 0x00,
TouchPointPressed = 0x01,
TouchPointMoved = 0x02,
TouchPointStationary = 0x04,
@@ -1691,6 +1676,10 @@ namespace Qt {
VeryCoarseTimer
};
+ enum class TimerId {
+ Invalid = 0,
+ };
+
enum ScrollPhase {
NoScrollPhase = 0,
ScrollBegin,
@@ -1707,6 +1696,7 @@ namespace Qt {
};
enum MouseEventFlag {
+ NoMouseEventFlag = 0x00,
MouseEventCreatedDoubleClick = 0x01,
MouseEventFlagMask = 0xFF
};
@@ -1727,6 +1717,12 @@ namespace Qt {
PassThrough
};
+ enum class PermissionStatus {
+ Undetermined,
+ Granted,
+ Denied,
+ };
+
// QTBUG-48701
enum ReturnByValueConstant { ReturnByValue }; // ### Qt 7: Remove me
@@ -1770,6 +1766,7 @@ namespace Qt {
Q_ENUM_NS(DayOfWeek)
Q_ENUM_NS(CursorShape)
Q_ENUM_NS(GlobalColor)
+ Q_ENUM_NS(ColorScheme)
Q_ENUM_NS(AspectRatioMode)
Q_ENUM_NS(TransformationMode)
Q_FLAG_NS(ImageConversionFlags)
@@ -1785,6 +1782,9 @@ namespace Qt {
Q_ENUM_NS(SortOrder)
Q_ENUM_NS(CaseSensitivity)
Q_FLAG_NS(MatchFlags)
+ Q_ENUM_NS(Modifier)
+ Q_FLAG_NS(Modifiers)
+ Q_ENUM_NS(KeyboardModifier)
Q_FLAG_NS(KeyboardModifiers)
Q_FLAG_NS(MouseButtons)
Q_ENUM_NS(WindowType)
@@ -1814,10 +1814,11 @@ namespace Qt {
Q_ENUM_NS(TimerType)
Q_ENUM_NS(ScrollPhase)
Q_ENUM_NS(MouseEventSource)
- Q_FLAG_NS(MouseEventFlag)
+ Q_FLAG_NS(MouseEventFlags)
Q_ENUM_NS(ChecksumType)
Q_ENUM_NS(HighDpiScaleFactorRoundingPolicy)
Q_ENUM_NS(TabFocusBehavior)
+ Q_ENUM_NS(PermissionStatus)
#endif // Q_DOC
}
@@ -1836,7 +1837,6 @@ public:
Pbuffer = 0x06, // GL pbuffer
FramebufferObject = 0x07, // GL framebuffer object
CustomRaster = 0x08,
- MacQuartz = 0x09,
PaintBuffer = 0x0a,
OpenGL = 0x0b
};
@@ -1863,6 +1863,154 @@ public:
static bool activateCallbacks(Callback, void **);
};
+class QKeyCombination
+{
+ int combination;
+
+public:
+ constexpr Q_IMPLICIT QKeyCombination(Qt::Key key = Qt::Key_unknown) noexcept
+ : combination(int(key))
+ {}
+
+ constexpr explicit QKeyCombination(Qt::Modifiers modifiers, Qt::Key key = Qt::Key_unknown) noexcept
+ : combination(modifiers.toInt() | int(key))
+ {}
+
+ constexpr explicit QKeyCombination(Qt::KeyboardModifiers modifiers, Qt::Key key = Qt::Key_unknown) noexcept
+ : combination(modifiers.toInt() | int(key))
+ {}
+
+ constexpr Qt::KeyboardModifiers keyboardModifiers() const noexcept
+ {
+ return Qt::KeyboardModifiers(combination & Qt::KeyboardModifierMask);
+ }
+
+ constexpr Qt::Key key() const noexcept
+ {
+ return Qt::Key(combination & ~int(Qt::KeyboardModifierMask));
+ }
+
+ static constexpr QKeyCombination fromCombined(int combined)
+ {
+ QKeyCombination result;
+ result.combination = combined;
+ return result;
+ }
+
+ constexpr int toCombined() const noexcept
+ {
+ return combination;
+ }
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X(6, 0, "Use QKeyCombination instead of int")
+ constexpr Q_IMPLICIT operator int() const noexcept
+ {
+ return combination;
+ }
+#endif
+ bool operator<(QKeyCombination) const = delete;
+private:
+ friend constexpr bool comparesEqual(const QKeyCombination &lhs,
+ const QKeyCombination &rhs) noexcept
+ {
+ return lhs.combination == rhs.combination;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QKeyCombination)
+};
+
+Q_DECLARE_TYPEINFO(QKeyCombination, Q_RELOCATABLE_TYPE);
+
+constexpr QKeyCombination operator|(Qt::Modifier modifier, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+constexpr QKeyCombination operator|(Qt::Modifiers modifiers, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+constexpr QKeyCombination operator|(Qt::KeyboardModifier modifier, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+constexpr QKeyCombination operator|(Qt::KeyboardModifiers modifiers, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+constexpr QKeyCombination operator|(Qt::Key key, Qt::Modifier modifier) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+constexpr QKeyCombination operator|(Qt::Key key, Qt::Modifiers modifiers) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+constexpr QKeyCombination operator|(Qt::Key key, Qt::KeyboardModifier modifier) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+constexpr QKeyCombination operator|(Qt::Key key, Qt::KeyboardModifiers modifiers) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+#if QT_DEPRECATED_SINCE(6, 0)
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::Modifier modifier, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::Modifiers modifiers, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::KeyboardModifier modifier, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::KeyboardModifiers modifiers, Qt::Key key) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::Key key, Qt::Modifier modifier) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::Key key, Qt::Modifiers modifiers) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::Key key, Qt::KeyboardModifier modifier) noexcept
+{
+ return QKeyCombination(modifier, key);
+}
+
+QT_DEPRECATED_VERSION_X(6, 0, "Use operator| instead")
+constexpr QKeyCombination operator+(Qt::Key key, Qt::KeyboardModifiers modifiers) noexcept
+{
+ return QKeyCombination(modifiers, key);
+}
+#endif
+
QT_END_NAMESPACE
#endif // QNAMESPACE_H
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index d6eabaec0c..ddfade675a 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -1,29 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2020 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\namespace Qt
@@ -107,6 +84,19 @@
QCoreApplication::testAttribute().
+ \value [since 6.7] AA_QtQuickUseDefaultSizePolicy Qt Quick Layouts use the built-in size
+ policy of \l Item. For example, when this is set, \l Button fills the available
+ width, but has a fixed height. When this is not set, it will use the default
+ sizing behavior of the layout it's in, which is to use its implicit size as the
+ preferred size. This is explained in detail in \l {Specifying preferred size} and
+ \l {Size constraints}. When this is set, the default size policy of the item
+ with the layout can be overridden by explicitly setting
+ \l{Layout::fillWidth}{Layout.fillWidth} or
+ \l{Layout::fillHeight}{Layout.fillHeight}.
+ \b Note: This API is considered tech preview and may change or be removed in future
+ versions of Qt.
+
+
\value AA_DontShowIconsInMenus Actions with the Icon property won't be
shown in any menus unless specifically set by the
QAction::iconVisibleInMenu property.
@@ -117,7 +107,11 @@
\value AA_DontShowShortcutsInContextMenus Actions with the Shortcut property
won't be shown in any shortcut menus unless specifically set by the
QAction::shortcutVisibleInContextMenu property. This value was added
- in Qt 5.10.
+ in Qt 5.10, and is by default based on the value reported by
+ QStyleHints::showShortcutsInContextMenus(). To override the default
+ behavior, set the style hint before QCoreApplication has been
+ instantiated, or set this attribute after QCoreApplication has
+ been instantiated.
\value AA_NativeWindows Ensures that widgets have native windows.
@@ -139,13 +133,24 @@
set to true won't be used as a native menubar (e.g, the menubar at
the top of the main screen on \macos).
- \value AA_MacDontSwapCtrlAndMeta On \macos by default, Qt swaps the
- Control and Meta (Command) keys (i.e., whenever Control is pressed, Qt
- sends Meta, and whenever Meta is pressed Control is sent). When this
- attribute is true, Qt will not do the flip. \l QKeySequence::StandardKey
- will also flip accordingly (i.e., QKeySequence::Copy will be
- Command+C on the keyboard regardless of the value set, though what is output for
- QKeySequence::toString() will be different).
+ \value AA_MacDontSwapCtrlAndMeta Keyboard shortcuts on Apple platforms are typically
+ based on the Command (or Cmd) keyboard modifier, represented by
+ the ⌘ symbol. For example, the 'Copy' action is Command+C (⌘+C).
+ To ease cross platform development Qt will by default remap Command
+ to the Qt::ControlModifier, to align with other platforms. This
+ allows creating keyboard shortcuts such as "Ctrl+J", which on
+ \macos will then map to Command+J, as expected by \macos users. The
+ actual Control (or Ctrl) modifier on Apple platforms, represented by ⌃,
+ is mapped to Qt::MetaModifier.
+
+ When this attribute is true Qt will not do the remapping, and pressing
+ the Command modifier will result in Qt::MetaModifier, while pressing
+ the Control modifier will result in Qt::ControlModifier.
+
+ Note that the \l QKeySequence::StandardKey sequences will always be
+ based on the same modifier (i.e., QKeySequence::Copy will be
+ Command+C regardless of the value set), but what is output for
+ QKeySequence::toString() will be different.
\value AA_Use96Dpi Assume the screen has a resolution of 96 DPI rather
than using the OS-provided resolution. This will cause font rendering
@@ -161,13 +166,6 @@
to left button mouse events instead. This attribute is enabled
by default.
- \value AA_UseHighDpiPixmaps Make QIcon::pixmap() generate high-dpi pixmaps
- that can be larger than the requested size. Such pixmaps will have
- \l {QPixmap::devicePixelRatio}{devicePixelRatio()} set to a value higher than 1.
- After setting this attribute, application code that uses pixmap
- sizes in layout geometry calculations should typically divide by
- \l {QPixmap::devicePixelRatio}{devicePixelRatio()} to get device-independent layout geometry.
-
\value AA_ForceRasterWidgets Make top-level widgets use pure raster surfaces,
and do not support non-native GL-based child widgets.
@@ -204,29 +202,11 @@
\value AA_SetPalette Indicates whether a palette was explicitly set on the
QGuiApplication. This value was added in Qt 5.5.
- \value AA_EnableHighDpiScaling Enables high-DPI scaling in Qt on supported
- platforms (see also \l{High DPI Displays}). Supported platforms are
- X11, Windows and Android. Enabling makes Qt scale the main (device
- independent) coordinate system according to display scale factors
- provided by the operating system. This corresponds to setting the
- QT_AUTO_SCREEN\unicode{0x200b}_SCALE_FACTOR environment variable to
- 1. This attribute must be set before QGuiApplication is constructed.
- This value was added in Qt 5.6.
-
- \value AA_DisableHighDpiScaling Disables high-DPI scaling in Qt, exposing window
- system coordinates. Note that the window system may do its own scaling,
- so this does not guarantee that QPaintDevice::devicePixelRatio() will
- be equal to 1. In addition, scale factors set by QT_SCALE_FACTOR will not
- be affected. This corresponds to setting the
- QT_AUTO_SCREEN\unicode{0x200b}_SCALE_FACTOR environment variable to 0.
- This attribute must be set before QGuiApplication is constructed.
- This value was added in Qt 5.6.
-
\value AA_UseStyleSheetPropagationInWidgetStyles By default, Qt Style Sheets
disable regular QWidget palette and font propagation. When this flag
- is enabled, font and palette changes propagate as though the user had
- manually called the corresponding QWidget methods. See
- \l{The Style Sheet Syntax#Inheritance}{The Style Sheet Syntax - Inheritance}
+ is enabled, font and palette changes done from a style sheet will propagate
+ a single time, when the style sheet is set.
+ See \l{The Style Sheet Syntax#Inheritance}{The Style Sheet Syntax - Inheritance}
for more details.
This value was added in Qt 5.7.
@@ -275,10 +255,10 @@
on disk. By default Qt Quick, QPainter's OpenGL backend, and any
application using QOpenGLShaderProgram with one of its
\e addCacheableShaderFromSource overloads will employ a disk-based
- \l{Caching Program Binaries}{program binary cache} in either the shared
- or per-process cache storage location, on systems that support
- \e glProgramBinary(). In the unlikely event of this being problematic,
- set this attribute to disable all disk-based caching of shaders.
+ program binary cache in either the shared or per-process cache storage
+ location, on systems that support \e glProgramBinary(). In the unlikely
+ event of this being problematic, set this attribute to disable all
+ disk-based caching of shaders.
\value AA_DisableSessionManager Disables the QSessionManager.
By default Qt will connect to a running session manager for a GUI
@@ -293,7 +273,21 @@
Currently supported on the Windows platform only.
This value was added in 5.15
+ \value AA_DontUseNativeMenuWindows Menu popup windows (e.g. context menus,
+ combo box menus, and non-native menubar menus) created while this
+ attribute is set to true will not be represented as native top
+ level windows, unless required by the implementation.
+ This value was added in Qt 6.8.
+
+ \value AA_DontUsePopupWindows When this attribute is set, popups will always appear
+ as items in the scene, rather than having their own dedicated windows.
+ Setting this attribute will only affect Qt Quick applications.
+ This value was added in Qt 6.8.
+
\omitvalue AA_AttributeCount
+ \omitvalue AA_EnableHighDpiScaling
+ \omitvalue AA_UseHighDpiPixmaps
+ \omitvalue AA_DisableHighDpiScaling
*/
/*!
@@ -312,7 +306,6 @@
to the left button. (The left button may be the right button on
left-handed mice.)
\value RightButton The right button.
- \value MidButton The middle button.
\value MiddleButton The middle button.
\value BackButton The 'Back' button. (Typically present on
@@ -405,8 +398,6 @@
\value META The Meta keys.
\value CTRL The Ctrl keys.
\value ALT The normal Alt keys, but not keys like AltGr.
- \value UNICODE_ACCEL The shortcut is specified as a Unicode code
- point, not as a Qt Key.
\omitvalue MODIFIER_MASK
\sa KeyboardModifier, MouseButton
@@ -650,7 +641,14 @@
connection types, using a bitwise OR. When Qt::UniqueConnection is
set, QObject::connect() will fail if the connection already exists
(i.e. if the same signal is already connected to the same slot
- for the same pair of objects). This flag was introduced in Qt 4.6.
+ for the same pair of objects).
+
+ \value SingleShotConnection
+ This is a flag that can be combined with any one of the above
+ connection types, using a bitwise OR. When Qt::SingleShotConnection
+ is set, the slot is going to be called only once; the connection
+ will be automatically broken when the signal is emitted.
+ This flag was introduced in Qt 6.0.
With queued connections, the parameters must be of types that are
known to Qt's meta-object system, because Qt needs to copy the
@@ -670,48 +668,111 @@
/*!
\enum Qt::DateFormat
- \value TextDate The default Qt format, which includes the day and month name,
- the day number in the month, and the year in full. The day and month names will
- be short, localized names. This is basically equivalent to using the date format
- string, "ddd MMM d yyyy". See QDate::toString() for more information.
-
- \value ISODate \l{ISO 8601} extended format: either \c{yyyy-MM-dd} for dates or
- \c{yyyy-MM-ddTHH:mm:ss} (e.g. 2017-07-24T15:46:29), or with a time-zone
- suffix (Z for UTC otherwise an offset as [+|-]HH:mm) where appropriate
- for combined dates and times.
-
- \value ISODateWithMs \l{ISO 8601} extended format, including milliseconds if applicable.
-
- \value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format:
- either \c{[ddd,] dd MMM yyyy [HH:mm[:ss]][ ±tzoff]}
- or \c{ddd MMM dd[ HH:mm:ss] yyyy[ ±tzoff]} are recognized for combined dates
- and times, where \c{tzoff} is a timezone offset in \c{HHmm} format. For
- dates and times separately, the same formats are matched and the unwanted
- parts are ignored. In particular, note that a time is not recognized without
- an accompanying date. When converting dates to string form,
- format \c{dd MMM yyyy} is used, for times the format is \c{HH:mm:ss}. For
- combined date and time, these are combined
+ \value TextDate The default Qt format, which includes the day and month
+ name, the day number in the month, and the year in full. The day and month
+ names will be short names in English (C locale). This effectively uses, for
+ a date, format \c{ddd MMM d yyyy}, for a time \c{HH:mm:ss} and combines
+ these as \c{ddd MMM d HH:mm:ss yyyy} for a date-time, with an optional
+ zone-offset suffix, where relevant. When reading from a string, a
+ fractional part is also recognized on the seconds of a time part, as
+ \c{HH:mm:ss.zzz}, and some minor variants on the format may be recognized,
+ for compatibility with earlier versions of Qt and with changes to the format
+ planned for the future. In particular, the zone-offset suffix presently uses
+ \c{GMT[±tzoff]} with a \c{tzoff} in \c{HH[[:]mm]} format (two-digit hour and
+ optional two-digit minutes, with optional colon separator); this shall
+ change to use \c{UTC} in place of \c{GMT} in a future release of Qt, so the
+ planned \c{UTC} format is recognized.
+
+ \value ISODateWithMs \l{ISO 8601} extended format: uses \c{yyyy-MM-dd} for
+ dates, \c{HH:mm:ss.zzz} for times or \c{yyyy-MM-ddTHH:mm:ss.zzz}
+ (e.g. 2017-07-24T15:46:29.739) for combined dates and times, optionally with
+ a time-zone suffix (Z for UTC otherwise an offset as ±HH:mm) where
+ appropriate. When parsed, a single space, \c{' '}, may be used in place of
+ the \c{'T'} separator between date and time; no other spacing characters are
+ permitted. This format also accepts \c{HH:mm} and plain \c{HH} formats for
+ the time part, either of which may include a fractional part, \c{HH:mm.zzz}
+ or \c{HH.zzz}, applied to the last field present (hour or minute).
+
+ \value ISODate \l{ISO 8601} extended format, as for \c ISODateWithMs, but
+ omitting the milliseconds (\c{.zzz}) part when converting to a string. There
+ is no difference when reading from a string: if a fractional part is present
+ on the last time field, either format will accept it.
+
+ \value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format: when
+ converting dates to string form, format \c{dd MMM yyyy} is used, for times
+ the format is \c{HH:mm:ss}. For combined date and time, these are combined
as \c{dd MMM yyyy HH:mm:ss ±tzoff} (omitting the optional leading day of the
- week from the first format recognized).
+ week from the first format recognized). When reading from a string either
+ \c{[ddd,] dd MMM yyyy [HH:mm[:ss]][ ±tzoff]} or \c{ddd MMM dd[ HH:mm:ss]
+ yyyy[ ±tzoff]} will be recognized for combined dates and times, where
+ \c{tzoff} is a timezone offset in \c{HHmm} format. Arbitrary spacing may
+ appear before or after the text and any non-empty spacing may replace the
+ spaces in this format. For dates and times separately, the same formats are
+ matched and the unwanted parts are ignored. In particular, note that a time
+ is not recognized without an accompanying date.
\note For \c ISODate formats, each \c y, \c M and \c d represents a single
digit of the year, month, and day used to specify the date. Each \c H, \c m,
and \c s represents a single digit of the hour (up to 24), minute and second
- used to specify the time. The presence of a literal \c T character is used
- to separate the date and time when both are specified. For the \c
- RFC2822Date format, MMM stands for the first three letters of the month name
- in English, the other format characters have the same meaning as for the
- ISODate format.
+ used to specify the time. An hour of 24, with zero for all other time
+ fields, is understood as the start of the next day. A \c{.zzz} stands for a
+ fractional part suffix on the preceding field, which may be separated from
+ that field either by a comma \c{','} or the dot \c{'.'} shown. Precision
+ beyond milliseconds is accepted but discarded, rounding to the nearest
+ representable millisecond. The presence of a literal \c T character is used
+ to separate the date and time when both are specified. For the \c TextDate
+ and \c RFC2822Date formats, \c{ddd} stands for the first three letters of
+ the name of the day of the week and \c{MMM} stands for the first three
+ letters of the month name. The names of days and months are always in
+ English (C locale) regardless of user preferences or system settings. The
+ other format characters have the same meaning as for the ISODate format,
+ except that 24 is not accepted as an hour. Parts of a format enclosed in
+ square brackets \c{[...]} are optional; the square brackets do not form part
+ of the format. The plus-or-minus character \c{'±'} here stands for either
+ sign character, \c{'-'} for minus or \c{'+'} for plus.
+
+ \note Zone offsets are measured positive to the east of Greenwich, negative
+ to the west, as is usual for UTC-based offset notations (conflicting with
+ some GMT-based zones-names, such as \c{Etc/GMT+3}, which use the opposite
+ convention).
+
+ \sa QDate::toString(), QTime::toString(), QDateTime::toString(),
+ QDate::fromString(), QTime::fromString(), QDateTime::fromString()
*/
-
/*!
\enum Qt::TimeSpec
- \value LocalTime Locale dependent time (Timezones and Daylight Savings Time).
- \value UTC Coordinated Universal Time, replaces Greenwich Mean Time.
+ \value LocalTime Local time, controlled by a system time-zone setting.
+ \value UTC Coordinated Universal Time.
\value OffsetFromUTC An offset in seconds from Coordinated Universal Time.
- \value TimeZone A named time zone using a specific set of Daylight Savings rules.
+ \value TimeZone A named time zone.
+
+ Both LocalTime and TimeZone will take care of transitions, such as
+ the start and end of daylight-saving time. UTC is the standard
+ time relative to which time-zones are usually specified: Greenwich
+ Mean Time has zero offset from it. Neither UTC nor OffsetFromUTC
+ has any transitions.
+
+ When specifying a datetime using OffsetFromUTC, the offset from UTC must
+ also be supplied (it is measured in seconds). To specify a datetime using
+ TimeZone, a QTimeZone must be supplied. From Qt 6.5, a QTimeZone can now
+ package a timespec with, where needed, an offset as a lightweight time
+ description, so that passing a QTimeZone now provides a uniform way to use
+ datetime APIs, saving the need to call them differently for different
+ timespecs.
+
+ \note After a change to the system time-zone setting, the behavior
+ of LocalTime-based QDateTime objects created before the change is
+ undefined: QDateTime may have cached data that the change
+ invalidates. (This is not triggered by \e transitions of the system
+ time-zone.) In long-running processes, updates to the system's
+ time-zone data (e.g. when politicians change the rules for a zone)
+ may likewise lead to conflicts between the updated time-zone
+ information and data cached by QDateTime objects created before
+ the update, using either LocalTime or TimeZone.
+
+ \sa QTimeZone, QDateTime
*/
/*!
@@ -749,14 +810,29 @@
/*!
\enum Qt::DockWidgetArea
- \value LeftDockWidgetArea
- \value RightDockWidgetArea
- \value TopDockWidgetArea
- \value BottomDockWidgetArea
- \value AllDockWidgetAreas
- \value NoDockWidgetArea
+ Represents the areas a QDockWidget can be plugged to.
+ \note A floating dock widget with tabs can be docked anywhere.
+
+ \value LeftDockWidgetArea The left dock area of a QMainWindow.
+ \value RightDockWidgetArea The right dock area of a QMainWindow.
+ \value TopDockWidgetArea The top dock area of a QMainWindow.
+ \value BottomDockWidgetArea The bottom dock area of a QMainWindow.
+ \value AllDockWidgetAreas All dock widget areas (default).
+ \value NoDockWidgetArea No dock widget areas.
\omitvalue DockWidgetArea_Mask
+ \sa QDockWidget::setAllowedAreas, QDockWidget::isAreaAllowed
+*/
+
+/*!
+ \enum Qt::ColorScheme
+
+ Represents the appearance of an application's theme,
+ defined by QGuiApplication::palette().
+
+ \value Unknown The appearance is unknown.
+ \value Light The background colors are lighter than the text color, i.e. the theme is light.
+ \value Dark The background colors are darker than the text color, i.e. the theme is dark.
*/
/*!
@@ -794,11 +870,6 @@
different colors than the size of the color table of the destination format.
\value AutoDither (default) - Only dither when down-converting to 1 or 8-bit indexed formats.
- \omitvalue ColorMode_Mask
- \omitvalue Dither_Mask
- \omitvalue AlphaDither_Mask
- \omitvalue DitherMode_Mask
-
\value NoOpaqueDetection Do not check whether the image contains non-opaque
pixels. Use this if you know that the image is semi-transparent and
you want to avoid the overhead of checking the pixels in the image
@@ -810,6 +881,11 @@
Can be useful when converting a QImage to a QPixmap for a one-time
rendering operation for example. Note that a QPixmap not in the
preferred format will be much slower as a paint device.
+
+ \omitvalue ColorMode_Mask
+ \omitvalue Dither_Mask
+ \omitvalue AlphaDither_Mask
+ \omitvalue DitherMode_Mask
*/
/*!
@@ -899,10 +975,6 @@
\value WA_AlwaysShowToolTips Enables tooltips for inactive windows.
- \value WA_ContentsPropagated This flag is superfluous and
- obsolete; it no longer has any effect. Since Qt 4.1, all widgets
- that do not set WA_PaintOnScreen propagate their contents.
-
\value WA_CustomWhatsThis Indicates that the widget wants to
continue operating normally in "What's This?" mode. This is set by the
widget's author.
@@ -918,9 +990,6 @@
\value WA_DontShowOnScreen Indicates that the widget is hidden or is
not a part of the viewable Desktop.
- \omitvalue WA_DropSiteRegistered
- \omitvalue WA_ForceAcceptDrops
-
\value WA_ForceDisabled Indicates that the widget is
explicitly disabled, i.e. it will remain disabled even when all
its ancestors are set to the enabled state. This implies
@@ -933,14 +1002,9 @@
This implies WA_UpdatesDisabled. This is set/cleared by
QWidget::setUpdatesEnabled().
- \value WA_GroupLeader
- \e{This attribute has been deprecated.} Use QWidget::windowModality
- instead.
-
\value WA_Hover Forces Qt to generate paint events when the mouse
enters or leaves the widget. This feature is typically used when
- implementing custom styles; see the \l{widgets/styles}{Styles}
- example for details.
+ implementing custom styles.
\value WA_InputMethodEnabled Enables input methods for Asian languages.
Must be set when creating custom text editing widgets.
@@ -976,8 +1040,6 @@
\value WA_LayoutUsesWidgetRect Ignore the layout item rect from the style
when laying out this widget with QLayout.
- \value WA_MacNoClickThrough This value is obsolete and has no effect.
-
\value WA_MacOpaqueSizeGrip Indicates that the native size grip
should be opaque instead of transparent (the default). This attribute
is only applicable to \macos and is set by the widget's author.
@@ -1001,14 +1063,6 @@
size for widgets in \macos. This attribute is only applicable to
\macos.
- \value WA_MacVariableSize Indicates the widget can choose between
- alternative sizes for widgets to avoid clipping.
- This attribute is only applicable to \macos.
-
- \value WA_MacBrushedMetal This value is obsolete and has no effect.
-
- \omitvalue WA_MacMetalStyle
-
\value WA_Mapped Indicates that the widget is mapped on screen.
This is set/cleared by the Qt kernel.
@@ -1024,12 +1078,6 @@
position. This is set/cleared by QWidget::move() and
by QWidget::setGeometry().
- \value WA_MSWindowsUseDirect3D This value is obsolete and has no
- effect.
-
- \value WA_NoBackground This value is obsolete. Use
- WA_OpaquePaintEvent instead.
-
\value WA_NoChildEventsForParent Indicates that the widget does
not want ChildAdded or ChildRemoved events sent to its
parent. This is rarely necessary but can help to avoid automatic
@@ -1104,10 +1152,10 @@
e.g., when a hidden widget was resized. This flag is set or cleared by the
Qt kernel.
- \value WA_QuitOnClose Makes Qt quit the application when the last widget
- with the attribute set has accepted closeEvent(). This behavior can be
- modified with the QApplication::quitOnLastWindowClosed property. By default
- this attribute is set for all widgets of type Qt::Window.
+ \value WA_QuitOnClose Indicates that the widget should be taken into account
+ when deciding whether to quit the application when the last window is closed.
+ This behavior can be modified with the QGuiApplication::quitOnLastWindowClosed
+ property. By default this attribute is set for all widgets of type Qt::Window.
\value WA_Resized Indicates that the widget has an explicit size. This flag
is set or cleared by QWidget::resize() and QWidget::setGeometry().
@@ -1150,9 +1198,12 @@
\value WA_TranslucentBackground Indicates that the widget should have a
translucent background, i.e., any non-opaque regions of the widgets will be
translucent because the widget will have an alpha channel. Setting this
- flag causes WA_NoSystemBackground to be set. On Windows the
- widget also needs the Qt::FramelessWindowHint window flag to be set.
- This flag is set or cleared by the widget's author.
+ flag causes WA_NoSystemBackground to be set. On Windows the widget also
+ needs the Qt::FramelessWindowHint window flag to be set. This flag is set
+ or cleared by the widget's author. As of Qt 5.0, toggling this attribute
+ after the widget has been shown is not uniformly supported across
+ platforms. When translucent background is desired, set the attribute early
+ when creating the widget, and avoid altering it afterwards.
\value WA_UnderMouse Indicates that the widget is under the mouse cursor.
The value is not updated correctly during drag and drop operations. There
@@ -1266,8 +1317,6 @@
has no effect on non-X11 platforms. \b Note: Qt automatically sets this
attribute on the feedback widget used during a drag.
- \value WA_MacFrameworkScaled This value is obsolete and has no effect.
-
\value WA_AcceptTouchEvents Allows touch events (see QTouchEvent)
to be sent to the widget. Must be set on all widgets that can
handle touch events. Without this attribute set, events from a
@@ -1280,52 +1329,52 @@
to this top level window. This attribute has no effect on non-X11
platforms.
- \value WA_AlwaysStackOnTop Since Qt 5.4, this value forces QOpenGLWidget and
+ \value [since 5.4] WA_AlwaysStackOnTop Forces QOpenGLWidget and
QQuickWidget to be drawn last, on top of other widgets. Ignored for other
type of widgets. Setting this attribute breaks the stacking order, but
allows having a semi-transparent OpenGL widget with other widgets visible
underneath. It is strongly recommended to call update() on the widget's
top-level window after enabling or disabling this attribute.
- \omitvalue WA_SetLayoutDirection
- \omitvalue WA_InputMethodTransparent
- \omitvalue WA_WState_CompressKeys
- \omitvalue WA_WState_ConfigPending
- \omitvalue WA_WState_Created
- \omitvalue WA_WState_DND
- \omitvalue WA_WState_ExplicitShowHide
- \omitvalue WA_WState_Hidden
- \omitvalue WA_WState_InPaintEvent
- \omitvalue WA_WState_OwnSizePolicy
- \omitvalue WA_WState_Polished
- \omitvalue WA_WState_Reparented
+ \value WA_ContentsMarginsRespectsSafeArea A QWidget respects the safe
+ area margins of a window by incorporating the margins into its contents'
+ margins by default. This means, that a QLayout will use the content area
+ of a widget for its layout, unless the Qt::WA_LayoutOnEntireRect attribute
+ is set. This along with a contents margin of 0 can be used on the actual
+ layout, to allow for example a background image to underlay the status bar and other
+ system areas on an iOS device, while still allowing child widgets of
+ that background to be inset based on the safe area.
+
+ \omitvalue WA_LaidOut
\omitvalue WA_WState_Visible
- \omitvalue WA_SetWindowIcon
+ \omitvalue WA_WState_Hidden
\omitvalue WA_PendingUpdate
- \omitvalue WA_LaidOut
- \omitvalue WA_GrabbedShortcut
- \omitvalue WA_DontShowOnScreen
\omitvalue WA_InvalidSize
+ \omitvalue WA_GrabbedShortcut
+ \omitvalue WA_SetWindowIcon
+ \omitvalue WA_SetLayoutDirection
\omitvalue WA_ForceUpdatesDisabled
+ \omitvalue WA_WState_Created
+ \omitvalue WA_WState_CompressKeys
+ \omitvalue WA_WState_InPaintEvent
+ \omitvalue WA_WState_Reparented
+ \omitvalue WA_WState_ConfigPending
+ \omitvalue WA_WState_Polished
+ \omitvalue WA_WState_OwnSizePolicy
+ \omitvalue WA_WState_ExplicitShowHide
+ \omitvalue WA_InputMethodTransparent
+ \omitvalue WA_DropSiteRegistered
\omitvalue WA_NoX11EventCompression
\omitvalue WA_TintedBackground
\omitvalue WA_X11OpenGLOverlay
\omitvalue WA_CanHostQMdiSubWindowTitleBar
- \omitvalue WA_AttributeCount
- \omitvalue WA_StyleSheet
\omitvalue WA_X11BypassTransientForHint
+ \omitvalue WA_DontShowOnScreen
\omitvalue WA_SetWindowModality
\omitvalue WA_WState_WindowOpacitySet
\omitvalue WA_WState_AcceptedTouchBeginEvent
- \omitvalue WA_MacNoShadow
- \value WA_ContentsMarginsRespectsSafeArea A QWidget respects the safe
- area margins of a window by incorporating the margins into its contents'
- margins by default. This means, that a QLayout will use the content area
- of a widget for its layout, unless the Qt::WA_LayoutOnEntireRect attribute
- is set. This along with a contents margin of 0 can be used on the actual
- layout, to allow for example a background image to underlay the status bar and other
- system areas on an iOS device, while still allowing child widgets of
- that background to be inset based on the safe area.
+ \omitvalue WA_StyleSheet
+ \omitvalue WA_AttributeCount
*/
/*! \typedef Qt::HANDLE
@@ -1416,6 +1465,7 @@
\value Key_Help
\value Key_Direction_L
\value Key_Direction_R
+
\value Key_Space
\value Key_Any
\value Key_Exclam
@@ -1507,7 +1557,8 @@
\value Key_twosuperior
\value Key_threesuperior
\value Key_acute
- \value Key_mu
+ \value [since 6.7] Key_micro
+ \value Key_mu Deprecated alias for Key_micro
\value Key_paragraph
\value Key_periodcentered
\value Key_cedilla
@@ -1552,6 +1603,7 @@
\value Key_ssharp
\value Key_division
\value Key_ydiaeresis
+
\value Key_Multi_key
\value Key_Codeinput
\value Key_SingleCandidate
@@ -1660,24 +1712,24 @@
\value Key_OpenUrl
\value Key_LaunchMail
\value Key_LaunchMedia
- \value Key_Launch0 On X11 this key is mapped to "My Computer" (XF86XK_MyComputer) key for legacy reasons.
- \value Key_Launch1 On X11 this key is mapped to "Calculator" (XF86XK_Calculator) key for legacy reasons.
- \value Key_Launch2 On X11 this key is mapped to XF86XK_Launch0 key for legacy reasons.
- \value Key_Launch3 On X11 this key is mapped to XF86XK_Launch1 key for legacy reasons.
- \value Key_Launch4 On X11 this key is mapped to XF86XK_Launch2 key for legacy reasons.
- \value Key_Launch5 On X11 this key is mapped to XF86XK_Launch3 key for legacy reasons.
- \value Key_Launch6 On X11 this key is mapped to XF86XK_Launch4 key for legacy reasons.
- \value Key_Launch7 On X11 this key is mapped to XF86XK_Launch5 key for legacy reasons.
- \value Key_Launch8 On X11 this key is mapped to XF86XK_Launch6 key for legacy reasons.
- \value Key_Launch9 On X11 this key is mapped to XF86XK_Launch7 key for legacy reasons.
- \value Key_LaunchA On X11 this key is mapped to XF86XK_Launch8 key for legacy reasons.
- \value Key_LaunchB On X11 this key is mapped to XF86XK_Launch9 key for legacy reasons.
- \value Key_LaunchC On X11 this key is mapped to XF86XK_LaunchA key for legacy reasons.
- \value Key_LaunchD On X11 this key is mapped to XF86XK_LaunchB key for legacy reasons.
- \value Key_LaunchE On X11 this key is mapped to XF86XK_LaunchC key for legacy reasons.
- \value Key_LaunchF On X11 this key is mapped to XF86XK_LaunchD key for legacy reasons.
- \value Key_LaunchG On X11 this key is mapped to XF86XK_LaunchE key for legacy reasons.
- \value Key_LaunchH On X11 this key is mapped to XF86XK_LaunchF key for legacy reasons.
+ \value Key_Launch0
+ \value Key_Launch1
+ \value Key_Launch2
+ \value Key_Launch3
+ \value Key_Launch4
+ \value Key_Launch5
+ \value Key_Launch6
+ \value Key_Launch7
+ \value Key_Launch8
+ \value Key_Launch9
+ \value Key_LaunchA
+ \value Key_LaunchB
+ \value Key_LaunchC
+ \value Key_LaunchD
+ \value Key_LaunchE
+ \value Key_LaunchF
+ \value Key_LaunchG
+ \value Key_LaunchH
\value Key_MonBrightnessUp
\value Key_MonBrightnessDown
\value Key_KeyboardLightOnOff
@@ -1703,7 +1755,7 @@
\value Key_ApplicationRight
\value Key_Book
\value Key_CD
- \value Key_Calculator On X11 this key is not mapped for legacy reasons. Use Qt::Key_Launch1 instead.
+ \value Key_Calculator
\value Key_ToDoList
\value Key_ClearGrab
\value Key_Close
@@ -2086,14 +2138,6 @@
*/
/*!
- \typedef Qt::WFlags
- \obsolete
- This typedef is obsolete. Use Qt::WindowFlags instead.
-
- Synonym for Qt::WindowFlags.
-*/
-
-/*!
\enum Qt::WindowType
\keyword window flag
@@ -2134,6 +2178,8 @@
QDialog::open(), instead.
\value Drawer Indicates that the widget is a drawer on \macos.
+ This feature is obsolete. Setting the flag
+ has no effect.
\value Popup Indicates that the widget is a pop-up top-level
window, i.e. that it is modal, but has a window
@@ -2164,8 +2210,7 @@
\value SplashScreen Indicates that the window is a splash screen.
This is the default type for QSplashScreen.
- \value Desktop Indicates that this widget is the desktop. This
- is the type for QDesktopWidget.
+ \omitvalue Desktop Indicates that this widget is the desktop.
\value SubWindow Indicates that this widget is a sub-window, such
as a QMdiSubWindow widget.
@@ -2206,11 +2251,17 @@
you call QWidget::activateWindow() manually).
\value FramelessWindowHint Produces a borderless window.
- The user cannot move or resize a borderless window via the window
- system. On X11, the result of the flag is dependent on the window manager and its
+
+ On X11, the result of the flag is dependent on the window manager and its
ability to understand Motif and/or NETWM hints. Most existing
modern window managers can handle this.
+ \note If the window manager relies on the frame to interactively manipulate
+ the window, the user can no longer move or resize the window via the window
+ system, but this side effect should not be relied on. To produce a fixed
+ size window that can not be resized, please set QWindow::setMinimumSize()
+ and QWindow::setMaximumSize() to the same size.
+
\value NoDropShadowWindowHint Disables window drop shadow on supporting platforms.
The \c CustomizeWindowHint flag is used to enable customization of
@@ -2640,11 +2691,11 @@
\enum Qt::InputMethodQuery
\value ImEnabled The widget accepts input method input.
- \value ImMicroFocus This query is obsolete. Use \c ImCursorRectangle instead.
\value ImCursorRectangle The rectangle covering the area of the input cursor in widget coordinates.
\value ImFont The currently used font for text input.
\value ImCursorPosition The logical position of the cursor within the text surrounding the input area
- (see \c ImSurroundingText).
+ (see \c ImSurroundingText). The position does not incorporate the offset of
+ the cursor within the preedit area, as controlled by QInputMethodEvent::Cursor.
\value ImSurroundingText The plain text around the input area, for example the current paragraph.
\value ImCurrentSelection The currently selected text.
\value ImMaximumTextLength The maximum number of characters that the widget can hold. If there is no limit,
@@ -2655,7 +2706,9 @@
\value ImHints The hints for input method on expected input. (See Qt::InputMethodHints)
\value ImPreferredLanguage The preferred input language.
\value ImPlatformData Platform specific data for input method.
- \value ImAbsolutePosition The logical position of the cursor within the entire document.
+ \value ImAbsolutePosition The logical position of the cursor within the entire document. The position does
+ not incorporate the offset of the cursor within the preedit area, as controlled
+ by QInputMethodEvent::Cursor.
\value ImTextBeforeCursor The plain text before the cursor. The widget can decide how much text to return,
but \b{must} not return an empty string unless the cursor is at the start of the document.
\value ImTextAfterCursor The plain text after the cursor. The widget can decide how much text to return,
@@ -2666,6 +2719,7 @@
\value ImInputItemClipRectangle The actual exposed input item rectangle. Parts of the input item might be
clipped. This value will take clipping into consideration and return the actual painted
item rectangle. The rectangle is in widget coordinates.
+ \value ImReadOnly The widget is read only. This value was added in Qt 6.2.
Masks:
@@ -2736,16 +2790,13 @@
default delegate. (Qt::Alignment)
\value BackgroundRole The background brush used for items rendered with
the default delegate. (QBrush)
- \value BackgroundColorRole This role is obsolete. Use BackgroundRole instead.
\value ForegroundRole The foreground brush (text color, typically)
used for items rendered with the default delegate.
(QBrush)
- \value TextColorRole This role is obsolete. Use ForegroundRole instead.
\value CheckStateRole This role is used to obtain the checked state of
an item. (Qt::CheckState)
\value InitialSortOrderRole This role is used to obtain the initial sort order
- of a header view section. (Qt::SortOrder). This
- role was introduced in Qt 4.8.
+ of a header view section. (Qt::SortOrder).
Accessibility roles (with associated types):
@@ -2785,8 +2836,6 @@
This enables automatic management of the state of parent items in QTreeWidget
(checked if all children are checked, unchecked if all children are unchecked,
or partially checked if only some children are checked).
- \value ItemIsTristate \e{This enum value is deprecated.} Use Qt::ItemIsAutoTristate
- instead.
\value ItemNeverHasChildren The item never has child items.
This is used for optimization purposes only.
\value ItemIsUserTristate The user can cycle through three separate states.
@@ -2818,8 +2867,6 @@
\value MatchStartsWith The search term matches the start of the item.
\value MatchEndsWith The search term matches the end of the item.
\value MatchCaseSensitive The search is case sensitive.
- \value MatchRegExp Same as MatchRegularExpression
- \e{This enum value is deprecated since Qt 5.15.}
\value MatchRegularExpression Performs string-based matching using a regular
expression as the search term. Uses QRegularExpression.
When using this flag, a QRegularExpression object can be passed as
@@ -2833,6 +2880,12 @@
the search reaches the last item in the model, it begins again at
the first item and continues until all items have been examined.
\value MatchRecursive Searches the entire hierarchy.
+ \omitvalue MatchTypeMask
+
+ \note Qt::MatchExactly, Qt::MatchContains, Qt::MatchStartsWith,
+ Qt::MatchEndsWith, Qt::MatchRegularExpression, Qt::MatchWildcard, and
+ Qt::MatchFixedString are mutually exclusive. The behavior achieved by
+ setting several of them in a Qt::MatchFlags argument is undefined.
\sa QString::compare(), QRegularExpression
*/
@@ -2846,7 +2899,10 @@
\value ElideLeft The ellipsis should appear at the beginning of the text.
\value ElideRight The ellipsis should appear at the end of the text.
\value ElideMiddle The ellipsis should appear in the middle of the text.
- \value ElideNone Ellipsis should NOT appear in the text.
+ \value ElideNone Ellipsis should NOT appear in the text. When passed to functions such as
+ QFontMetrics::elidedText(), this will cause the full string to return unless
+ the text contains multi-length variants. Elision in this case must be done
+ by clipping to the component width.
Qt::ElideMiddle is normally the most appropriate choice for URLs (e.g.,
"\l{http://bugreports.qt.io/browse/QTWEBSITE-13}{http://bugreports.qt.../QTWEBSITE-13/}"),
@@ -3011,6 +3067,11 @@
*/
/*!
+ \enum Qt::Disambiguated_t
+ \internal
+*/
+
+/*!
\enum Qt::CoordinateSystem
\since 4.6
@@ -3029,6 +3090,7 @@
This enum represents the state of a touch point at the time a
QTouchEvent occurred.
+ \value TouchPointUnknownState The state of the touch point is not known.
\value TouchPointPressed The touch point is now pressed.
\value TouchPointMoved The touch point moved.
\value TouchPointStationary The touch point did not move.
@@ -3090,8 +3152,8 @@
the Qt::GestureStarted state and ending with a gesture in the
Qt::GestureFinished or Qt::GestureCanceled states.
- \value IgnoredGesturesPropagateToParent Since Qt 4.7, this flag allows you
- to fine-tune gesture event propagation. By setting the flag when
+ \value [since 4.7] IgnoredGesturesPropagateToParent Allows fine-tuning of
+ gesture event propagation. By setting the flag when
\l{QGraphicsObject::grabGesture()}{grabbing} a gesture all ignored partial
gestures will propagate to their parent items.
@@ -3106,12 +3168,11 @@
\value BeginNativeGesture Sent before gesture event stream.
\value EndNativeGesture Sent after gesture event stream.
- \value PanNativeGesture Sent after a panning gesture.
- Similar to a click-and-drag mouse movement.
+ \value PanNativeGesture Specifies the displacement delta in pixels.
\value ZoomNativeGesture Specifies the magnification delta in percent.
\value SmartZoomNativeGesture Boolean magnification state.
- \value RotateNativeGesture Rotation delta in degrees.
- \value SwipeNativeGesture Sent after a swipe movements.
+ \value RotateNativeGesture Specifies the rotation delta in degrees.
+ \value SwipeNativeGesture Sent after a swipe movement.
*/
@@ -3180,6 +3241,26 @@
*/
/*!
+ \enum Qt::TimerId
+ \since 6.8
+ \relates QObject
+ \relates QTimer
+ \relates QChronoTimer
+
+ This is used to represent timer IDs (for example, QTimer and QChronoTimer).
+ The underlying type is \c int. You can use \l qToUnderlying() to convert
+ Qt::TimerId to \c int.
+
+ \value Invalid Represents a no-op timer ID; it's usage depends on the
+ context, for example, this is the value returned by QObject::startTimer()
+ to indicate it failed to start a timer; whereas QChronoTimer::id() returns
+ this value when the timer is inactive, that is, \c timer.isActive()
+ returns \c false.
+
+ \sa QTimer::id(), QChronoTimer::id(), QObject::startTimer()
+*/
+
+/*!
\enum Qt::ScrollPhase
\since 5.2
@@ -3239,6 +3320,7 @@
\l {QEvent::MouseButtonDblClick}{MouseButtonDblClick} event from this event. The flag is set in the causing
\l {QEvent::MouseButtonPress}{MouseButtonPress}, and not in the resulting \l {QEvent::MouseButtonDblClick}{MouseButtonDblClick}.
+ \omitvalue NoMouseEventFlag
\omitvalue MouseEventFlagMask
*/
@@ -3261,11 +3343,9 @@
decide how non-integer scale factors (such as Windows 150%) are handled.
The active policy is set by calling QGuiApplication::setHighDdpiScaleFactorRoundingPolicy() before
- the application object is created, or by setting the QT_SCALE_FACTOR_ROUNDING_POLICY
- environment variable.
+ the application object is created.
\sa QGuiApplication::setHighDpiScaleFactorRoundingPolicy()
- \sa AA_EnableHighDpiScaling.
\omitvalue Unset
\value Round Round up for .5 and above.
@@ -3276,6 +3356,38 @@
*/
/*!
+ \enum Qt::PermissionStatus
+
+ This enum describes the possible statuses of a permissions.
+
+ \value Undetermined
+ The permission status is not yet known. Permission should be requested
+ via QCoreApplication::requestPermission() to determine the actual status.
+ This status will never be the result of requesting a permission.
+
+ \value Granted
+ The user has explicitly granted the application the permission,
+ or the permission is known to not require user authorization on
+ the given platform.
+
+ \value Denied
+ The user has explicitly denied the application the requested permission,
+ or the permission is known to not be accessible or applicable to applications
+ on the given platform.
+
+ \note On Android, there is no \c Undetermined status by the platform's APIs.
+ Thus, if a permission is denied for an app,
+ \l QCoreApplication::checkPermission() returns \c Undetermined
+ by default until \l QCoreApplication::requestPermission() is called.
+ After that \l QCoreApplication::checkPermission() reports a non \c Undetermined
+ status.
+
+ \since 6.5
+ \sa QCoreApplication::requestPermission(), QCoreApplication::checkPermission(),
+ {Application Permissions}
+*/
+
+/*!
\enum Qt::ReturnByValueConstant
\since 5.15
@@ -3288,3 +3400,201 @@
\sa QLabel::picture()
\sa QLabel::pixmap()
*/
+
+/*!
+ \class QKeyCombination
+ \inmodule QtCore
+ \since 6.0
+ \brief The QKeyCombination class stores a combination of a key with optional modifiers.
+
+ \compares equality
+
+ The QKeyCombination class can be used to represent a combination of a key
+ with zero or more keyboard modifiers.
+
+ \sa QKeySequence
+*/
+
+/*!
+ \fn QKeyCombination::QKeyCombination(Qt::Key key = Qt::Key_unknown) noexcept
+
+ Constructs a QKeyCombination object that represents the key \a key
+ and no modifiers.
+
+ \sa key()
+*/
+
+/*!
+ \fn QKeyCombination::QKeyCombination(Qt::Modifiers modifiers, Qt::Key key = Qt::Key_unknown) noexcept
+
+ Constructs a QKeyCombination object that represents the combination
+ of \a key with the modifiers \a modifiers.
+
+ \sa key(), keyboardModifiers()
+*/
+
+/*!
+ \fn QKeyCombination::QKeyCombination(Qt::KeyboardModifiers modifiers, Qt::Key key = Qt::Key_unknown) noexcept
+
+ Constructs a QKeyCombination object that represents the combination
+ of \a key with the modifiers \a modifiers.
+
+ \sa key(), keyboardModifiers()
+*/
+
+/*!
+ \fn Qt::KeyboardModifiers QKeyCombination::keyboardModifiers() const noexcept
+
+ Returns the keyboard modifiers represented by this QKeyCombination object.
+
+ \sa key()
+*/
+
+/*!
+ \fn Qt::Key QKeyCombination::key() const noexcept
+
+ Returns the key represented by this QKeyCombination object.
+
+ \sa keyboardModifiers()
+*/
+
+/*!
+ \fn QKeyCombination QKeyCombination::fromCombined(int combined)
+
+ Constructs a QKeyCombination object by extracting the key and the
+ modifiers out of \a combined, which must be the result of a bitwise
+ OR between a value of type Qt::Key and value of type
+ Qt::KeyboardModifiers. toCombined() can be used in order to produce
+ valid values for \a combined.
+
+ \sa toCombined()
+*/
+
+/*!
+ \fn int QKeyCombination::toCombined() const noexcept
+
+ Returns an integer value obtained by applying a bitwise OR between
+ the values of key() and keyboardModifiers() represented
+ by this object. A QKeyCombination object can be created from the
+ returned integer value by using fromCombined().
+
+ \sa fromCombined(), key(), keyboardModifiers()
+*/
+
+#if QT_DEPRECATED_SINCE(6, 0)
+/*!
+ \fn QKeyCombination::operator int() const noexcept
+ \deprecated
+
+ Use toCombined() instead.
+*/
+#endif
+
+/*!
+ \fn bool QKeyCombination::operator==(const QKeyCombination &lhs, const QKeyCombination &rhs)
+
+ Returns \c true if \a lhs and \a rhs have the same combination
+ of key and modifiers, and \c false otherwise.
+*/
+
+/*!
+ \fn bool QKeyCombination::operator!=(const QKeyCombination &lhs, const QKeyCombination &rhs)
+
+ Returns \c true if \a lhs and \a rhs have different combinations
+ of key and modifiers, otherwise \c false.
+*/
+
+/*!
+ \fn QKeyCombination operator|(Qt::Modifier modifier, Qt::Key key) noexcept
+ \fn QKeyCombination operator|(Qt::KeyboardModifier modifier, Qt::Key key) noexcept
+ \fn QKeyCombination operator|(Qt::Key key, Qt::Modifier modifier) noexcept
+ \fn QKeyCombination operator|(Qt::Key key, Qt::KeyboardModifier modifier) noexcept
+
+ \relates QKeyCombination
+
+ Returns a QKeyCombination object that represents the combination
+ of \a key with the modifier \a modifier.
+*/
+
+/*!
+ \fn QKeyCombination operator|(Qt::Modifiers modifiers, Qt::Key key) noexcept
+ \fn QKeyCombination operator|(Qt::KeyboardModifiers modifiers, Qt::Key key) noexcept
+ \fn QKeyCombination operator|(Qt::Key key, Qt::Modifiers modifiers) noexcept
+ \fn QKeyCombination operator|(Qt::Key key, Qt::KeyboardModifiers modifiers) noexcept
+
+ \relates QKeyCombination
+
+ Returns a QKeyCombination object that represents the combination
+ of \a key with the modifiers \a modifiers.
+*/
+
+/*!
+ \fn QKeyCombination operator+(Qt::Modifier modifier, Qt::Key key) noexcept
+ \fn QKeyCombination operator+(Qt::KeyboardModifier modifier, Qt::Key key) noexcept
+ \fn QKeyCombination operator+(Qt::Key key, Qt::Modifier modifier) noexcept
+ \fn QKeyCombination operator+(Qt::Key key, Qt::KeyboardModifier modifier) noexcept
+
+ \relates QKeyCombination
+ \deprecated
+
+ Use operator| instead.
+
+ Returns a QKeyCombination object that represents the combination
+ of \a key with the modifier \a modifier.
+*/
+
+/*!
+ \fn QKeyCombination operator+(Qt::Modifiers modifiers, Qt::Key key) noexcept
+ \fn QKeyCombination operator+(Qt::KeyboardModifiers modifiers, Qt::Key key) noexcept
+ \fn QKeyCombination operator+(Qt::Key key, Qt::Modifiers modifiers) noexcept
+ \fn QKeyCombination operator+(Qt::Key key, Qt::KeyboardModifiers modifiers) noexcept
+
+ \relates QKeyCombination
+ \deprecated
+
+ Use operator| instead.
+
+ Returns a QKeyCombination object that represents the combination
+ of \a key with the modifiers \a modifiers.
+*/
+
+/*!
+ \fn size_t qHash(QKeyCombination key, size_t seed = 0) noexcept
+ \relates QKeyCombination
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ \fn QDebug operator<<(QDebug debug, QKeyCombination combination)
+ \relates QKeyCombination
+
+ Writes the combination \a combination into the debug object \a debug for
+ debugging purposes.
+
+ \sa {Debugging Techniques}
+*/
+#endif
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &out, QKeyCombination combination)
+ \relates QKeyCombination
+
+ Writes the combination \a combination into the stream \a out.
+ Returns \a out.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &in, QKeyCombination &combination)
+ \relates QKeyCombination
+
+ Reads the combination \a combination from the stream \a in.
+ Returns \a in.
+
+ \sa {Serializing Qt Data Types}
+*/
+#endif
diff --git a/src/corelib/global/qnativeinterface.h b/src/corelib/global/qnativeinterface.h
new file mode 100644
index 0000000000..89f33651c5
--- /dev/null
+++ b/src/corelib/global/qnativeinterface.h
@@ -0,0 +1,148 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QNATIVEINTERFACE_H
+#define QNATIVEINTERFACE_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+// We declare a virtual non-inline function in the form
+// of the destructor, making it the key function. This
+// ensures that the typeinfo of the class is exported.
+// By being protected, we also ensure that pointers to
+// the interface can't be deleted.
+#define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType) \
+ protected: \
+ virtual ~NativeInterface(); \
+ \
+ struct TypeInfo { \
+ using baseType = BaseType; \
+ static constexpr char const *name = QT_STRINGIFY(NativeInterface); \
+ static constexpr int revision = Revision; \
+ }; \
+ \
+ template <typename, typename> \
+ friend struct QNativeInterface::Private::has_type_info; \
+ \
+ template <typename> \
+ friend bool constexpr QNativeInterface::Private::hasTypeInfo(); \
+ \
+ template <typename> \
+ friend struct QNativeInterface::Private::TypeInfo; \
+ public: \
+ NativeInterface() = default; \
+ Q_DISABLE_COPY_MOVE(NativeInterface)
+
+// Revisioned interfaces only make sense when exposed through a base
+// type via QT_DECLARE_NATIVE_INTERFACE_ACCESSOR, as the revision
+// checks happen at that level (and not for normal dynamic_casts).
+#define QT_DECLARE_NATIVE_INTERFACE_2(NativeInterface, Revision) \
+ static_assert(false, "Must provide a base type when specifying revision");
+
+#define QT_DECLARE_NATIVE_INTERFACE_1(NativeInterface) \
+ QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, 0, void)
+
+#define QT_DECLARE_NATIVE_INTERFACE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_NATIVE_INTERFACE, __VA_ARGS__)
+
+namespace QNativeInterface::Private {
+
+ // Basic type-trait to verify that a given native interface has
+ // all the required type information for us to evaluate it.
+ template <typename NativeInterface, typename = void>
+ struct has_type_info : std::false_type {};
+
+ // The type-trait is friended by TypeInfo, so that we can
+ // evaluate TypeInfo in the template arguments.
+ template <typename NativeInterface>
+ struct has_type_info<NativeInterface, std::void_t<
+ typename NativeInterface::TypeInfo,
+ typename NativeInterface::TypeInfo::baseType,
+ decltype(&NativeInterface::TypeInfo::name),
+ decltype(&NativeInterface::TypeInfo::revision)
+ >> : std::true_type {};
+
+ // We need to wrap the instantiation of has_type_info in a
+ // function friended by TypeInfo, otherwise MSVC will not
+ // let us evaluate TypeInfo in the template arguments.
+ template <typename NativeInterface>
+ bool constexpr hasTypeInfo()
+ {
+ return has_type_info<NativeInterface>::value;
+ }
+
+ template <typename NativeInterface>
+ struct TypeInfo
+ {
+ // To ensure SFINAE works for hasTypeInfo we can't use it in a constexpr
+ // variable that also includes an expression that relies on the type
+ // info. This helper variable is okey, as it it self contained.
+ static constexpr bool haveTypeInfo = hasTypeInfo<NativeInterface>();
+
+ // We can then use the helper variable in a constexpr condition in a
+ // function, which does not break SFINAE if haveTypeInfo is false.
+ template <typename BaseType>
+ static constexpr bool isCompatibleHelper()
+ {
+ if constexpr (haveTypeInfo)
+ return std::is_base_of<typename NativeInterface::TypeInfo::baseType, BaseType>::value;
+ else
+ return false;
+ }
+
+ // MSVC however doesn't like constexpr functions in enable_if_t conditions,
+ // so we need to wrap it yet again in a constexpr variable. This is fine,
+ // as all the SFINAE magic has been resolved at this point.
+ template <typename BaseType>
+ static constexpr bool isCompatibleWith = isCompatibleHelper<BaseType>();
+
+ // The revision and name accessors are not used in enable_if_t conditions,
+ // so we can leave them as constexpr functions. As this class template is
+ // friended by TypeInfo we can access the protected members of TypeInfo.
+ static constexpr int revision()
+ {
+ if constexpr (haveTypeInfo)
+ return NativeInterface::TypeInfo::revision;
+ else
+ return 0;
+ }
+
+ static constexpr char const *name()
+ {
+ if constexpr (haveTypeInfo)
+ return NativeInterface::TypeInfo::name;
+ else
+ return nullptr;
+ }
+ };
+
+ // Wrapper type to make the error message in case
+ // of incompatible interface types read better.
+ template <typename I>
+ struct NativeInterface : TypeInfo<I> {};
+} // QNativeInterface::Private
+
+// Declares an accessor for the native interface
+#ifdef Q_QDOC
+#define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
+ template <typename QNativeInterface> \
+ QNativeInterface *nativeInterface() const;
+#else
+#define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
+ template <typename NativeInterface, typename TypeInfo = QNativeInterface::Private::NativeInterface<NativeInterface>, \
+ typename BaseType = T, std::enable_if_t<TypeInfo::template isCompatibleWith<T>, bool> = true> \
+ NativeInterface *nativeInterface() const \
+ { \
+ return static_cast<NativeInterface*>(resolveInterface( \
+ TypeInfo::name(), TypeInfo::revision())); \
+ } \
+ protected: \
+ void *resolveInterface(const char *name, int revision) const; \
+ public:
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QNATIVEINTERFACE_H
diff --git a/src/corelib/global/qnativeinterface_p.h b/src/corelib/global/qnativeinterface_p.h
new file mode 100644
index 0000000000..aa7705e153
--- /dev/null
+++ b/src/corelib/global/qnativeinterface_p.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QNATIVEINTERFACE_P_H
+#define QNATIVEINTERFACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qloggingcategory.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcNativeInterface, Q_CORE_EXPORT)
+}
+
+// Provides a definition for the interface destructor
+#define QT_DEFINE_NATIVE_INTERFACE_2(Namespace, InterfaceClass) \
+ QT_PREPEND_NAMESPACE(Namespace)::InterfaceClass::~InterfaceClass() = default
+
+#define QT_DEFINE_NATIVE_INTERFACE(...) \
+ QT_OVERLOADED_MACRO(QT_DEFINE_NATIVE_INTERFACE, QNativeInterface, __VA_ARGS__)
+#define QT_DEFINE_PRIVATE_NATIVE_INTERFACE(...) \
+ QT_OVERLOADED_MACRO(QT_DEFINE_NATIVE_INTERFACE, QNativeInterface::Private, __VA_ARGS__)
+
+#define QT_NATIVE_INTERFACE_RETURN_IF(NativeInterface, baseType) \
+ { \
+ using QtPrivate::lcNativeInterface; \
+ using QNativeInterface::Private::TypeInfo; \
+ qCDebug(lcNativeInterface, "Comparing requested interface name %s with available %s", \
+ name, TypeInfo<NativeInterface>::name()); \
+ if (qstrcmp(name, TypeInfo<NativeInterface>::name()) == 0) { \
+ qCDebug(lcNativeInterface, \
+ "Match for interface %s. Comparing revisions (requested %d / available %d)", \
+ name, revision, TypeInfo<NativeInterface>::revision()); \
+ if (revision == TypeInfo<NativeInterface>::revision()) { \
+ qCDebug(lcNativeInterface) << "Full match. Returning dynamic cast of" << baseType; \
+ return dynamic_cast<NativeInterface *>(baseType); \
+ } else { \
+ qCWarning(lcNativeInterface, \
+ "Native interface revision mismatch (requested %d / available %d) for " \
+ "interface %s", \
+ revision, TypeInfo<NativeInterface>::revision(), name); \
+ return nullptr; \
+ } \
+ } else { \
+ qCDebug(lcNativeInterface, "No match for requested interface name %s", name); \
+ } \
+ }
+
+QT_END_NAMESPACE
+
+#endif // QNATIVEINTERFACE_P_H
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index b754155b30..a46039c5da 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qnumeric.h"
#include "qnumeric_p.h"
@@ -44,67 +8,81 @@
QT_BEGIN_NAMESPACE
/*!
+ \headerfile <QtNumeric>
+ \inmodule QtCore
+ \title Qt Numeric Functions
+
+ \brief The <QtNumeric> header file provides common numeric functions.
+
+ The <QtNumeric> header file contains various numeric functions
+ for comparing and adjusting a numeric value.
+*/
+
+/*!
Returns \c true if the double \a {d} is equivalent to infinity.
- \relates <QtGlobal>
+ \relates <QtNumeric>
\sa qInf()
*/
Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); }
/*!
Returns \c true if the double \a {d} is not a number (NaN).
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT bool qIsNaN(double d) { return qt_is_nan(d); }
/*!
Returns \c true if the double \a {d} is a finite number.
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); }
/*!
Returns \c true if the float \a {f} is equivalent to infinity.
- \relates <QtGlobal>
+ \relates <QtNumeric>
\sa qInf()
*/
Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); }
/*!
Returns \c true if the float \a {f} is not a number (NaN).
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT bool qIsNaN(float f) { return qt_is_nan(f); }
/*!
Returns \c true if the float \a {f} is a finite number.
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT bool qIsFinite(float f) { return qt_is_finite(f); }
#if QT_CONFIG(signaling_nan)
/*!
Returns the bit pattern of a signalling NaN as a double.
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT double qSNaN() { return qt_snan(); }
#endif
/*!
Returns the bit pattern of a quiet NaN as a double.
- \relates <QtGlobal>
+ \relates <QtNumeric>
\sa qIsNaN()
*/
Q_CORE_EXPORT double qQNaN() { return qt_qnan(); }
/*!
Returns the bit pattern for an infinite number as a double.
- \relates <QtGlobal>
+ \relates <QtNumeric>
\sa qIsInf()
*/
Q_CORE_EXPORT double qInf() { return qt_inf(); }
/*!
- \relates <QtGlobal>
+ \fn int qFpClassify(double val)
+ \fn int qFpClassify(float val)
+
+ \relates <QtNumeric>
Classifies a floating-point value.
The return values are defined in \c{<cmath>}: returns one of the following,
@@ -118,10 +96,6 @@ Q_CORE_EXPORT double qInf() { return qt_inf(); }
\endlist
*/
Q_CORE_EXPORT int qFpClassify(double val) { return qt_fpclassify(val); }
-
-/*!
- \overload
-*/
Q_CORE_EXPORT int qFpClassify(float val) { return qt_fpclassify(val); }
@@ -160,7 +134,7 @@ static inline quint32 f2i(float f)
\sa qFuzzyCompare()
\since 5.2
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT quint32 qFloatDistance(float a, float b)
{
@@ -218,7 +192,7 @@ static inline quint64 d2i(double d)
\sa qFuzzyCompare()
\since 5.2
- \relates <QtGlobal>
+ \relates <QtNumeric>
*/
Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
{
@@ -255,5 +229,268 @@ Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
return a > b ? d2i(a) - d2i(b) : d2i(b) - d2i(a);
}
+/*!
+ \fn template<typename T> bool qAddOverflow(T v1, T v2, T *result)
+ \relates <QtNumeric>
+ \since 6.1
+
+ Adds two values \a v1 and \a v2, of a numeric type \c T and records the
+ value in \a result. If the addition overflows the valid range for type \c T,
+ returns \c true, otherwise returns \c false.
+
+ An implementation is guaranteed to be available for 8-, 16-, and 32-bit
+ integer types, as well as integer types of the size of a pointer. Overflow
+ math for other types, if available, is considered private API.
+*/
+
+/*!
+ \fn template <typename T, T V2> bool qAddOverflow(T v1, std::integral_constant<T, V2>, T *r)
+ \since 6.1
+ \internal
+
+ Equivalent to qAddOverflow(v1, v2, r) with \a v1 as first argument, the
+ compile time constant \c V2 as second argument, and \a r as third argument.
+*/
+
+/*!
+ \fn template <auto V2, typename T> bool qAddOverflow(T v1, T *r)
+ \since 6.1
+ \internal
+
+ Equivalent to qAddOverflow(v1, v2, r) with \a v1 as first argument, the
+ compile time constant \c V2 as second argument, and \a r as third argument.
+*/
+
+/*!
+ \fn template<typename T> bool qSubOverflow(T v1, T v2, T *result)
+ \relates <QtNumeric>
+ \since 6.1
+
+ Subtracts \a v2 from \a v1 and records the resulting value in \a result. If
+ the subtraction overflows the valid range for type \c T, returns \c true,
+ otherwise returns \c false.
+
+ An implementation is guaranteed to be available for 8-, 16-, and 32-bit
+ integer types, as well as integer types of the size of a pointer. Overflow
+ math for other types, if available, is considered private API.
+*/
+
+/*!
+ \fn template <typename T, T V2> bool qSubOverflow(T v1, std::integral_constant<T, V2>, T *r)
+ \since 6.1
+ \internal
+
+ Equivalent to qSubOverflow(v1, v2, r) with \a v1 as first argument, the
+ compile time constant \c V2 as second argument, and \a r as third argument.
+*/
+
+/*!
+ \fn template <auto V2, typename T> bool qSubOverflow(T v1, T *r)
+ \since 6.1
+ \internal
+
+ Equivalent to qSubOverflow(v1, v2, r) with \a v1 as first argument, the
+ compile time constant \c V2 as second argument, and \a r as third argument.
+*/
+
+/*!
+ \fn template<typename T> bool qMulOverflow(T v1, T v2, T *result)
+ \relates <QtNumeric>
+ \since 6.1
+
+ Multiplies \a v1 and \a v2, and records the resulting value in \a result. If
+ the multiplication overflows the valid range for type \c T, returns
+ \c true, otherwise returns \c false.
+
+ An implementation is guaranteed to be available for 8-, 16-, and 32-bit
+ integer types, as well as integer types of the size of a pointer. Overflow
+ math for other types, if available, is considered private API.
+*/
+
+/*!
+ \fn template <typename T, T V2> bool qMulOverflow(T v1, std::integral_constant<T, V2>, T *r)
+ \since 6.1
+ \internal
+
+ Equivalent to qMulOverflow(v1, v2, r) with \a v1 as first argument, the
+ compile time constant \c V2 as second argument, and \a r as third argument.
+ This can be faster than calling the version with only variable arguments.
+*/
+
+/*!
+ \fn template <auto V2, typename T> bool qMulOverflow(T v1, T *r)
+ \since 6.1
+ \internal
+
+ Equivalent to qMulOverflow(v1, v2, r) with \a v1 as first argument, the
+ compile time constant \c V2 as second argument, and \a r as third argument.
+ This can be faster than calling the version with only variable arguments.
+*/
+
+/*! \fn template <typename T> T qAbs(const T &t)
+ \relates <QtNumeric>
+
+ Compares \a t to the 0 of type T and returns the absolute
+ value. Thus if T is \e {double}, then \a t is compared to
+ \e{(double) 0}.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 10
+*/
+
+/*! \fn int qRound(double d)
+ \relates <QtNumeric>
+
+ Rounds \a d to the nearest integer.
+
+ Rounds half away from zero (e.g. 0.5 -> 1, -0.5 -> -1).
+
+ \note This function does not guarantee correctness for high precisions.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 11A
+
+ \note If the value \a d is outside the range of \c int,
+ the behavior is undefined.
+*/
+
+/*! \fn int qRound(float d)
+ \relates <QtNumeric>
+
+ Rounds \a d to the nearest integer.
+
+ Rounds half away from zero (e.g. 0.5f -> 1, -0.5f -> -1).
+
+ \note This function does not guarantee correctness for high precisions.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 11B
+
+ \note If the value \a d is outside the range of \c int,
+ the behavior is undefined.
+*/
+
+/*! \fn qint64 qRound64(double d)
+ \relates <QtNumeric>
+
+ Rounds \a d to the nearest 64-bit integer.
+
+ Rounds half away from zero (e.g. 0.5 -> 1, -0.5 -> -1).
+
+ \note This function does not guarantee correctness for high precisions.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 12A
+
+ \note If the value \a d is outside the range of \c qint64,
+ the behavior is undefined.
+*/
+
+/*! \fn qint64 qRound64(float d)
+ \relates <QtNumeric>
+
+ Rounds \a d to the nearest 64-bit integer.
+
+ Rounds half away from zero (e.g. 0.5f -> 1, -0.5f -> -1).
+
+ \note This function does not guarantee correctness for high precisions.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 12B
+
+ \note If the value \a d is outside the range of \c qint64,
+ the behavior is undefined.
+*/
+
+/*!
+ \fn bool qFuzzyCompare(double p1, double p2)
+ \relates <QtNumeric>
+ \since 4.4
+ \threadsafe
+
+ Compares the floating point value \a p1 and \a p2 and
+ returns \c true if they are considered equal, otherwise \c false.
+
+ Note that comparing values where either \a p1 or \a p2 is 0.0 will not work,
+ nor does comparing values where one of the values is NaN or infinity.
+ If one of the values is always 0.0, use qFuzzyIsNull instead. If one of the
+ values is likely to be 0.0, one solution is to add 1.0 to both values.
+
+ \snippet code/src_corelib_global_qglobal.cpp 46
+
+ The two numbers are compared in a relative way, where the
+ exactness is stronger the smaller the numbers are.
+*/
+
+/*!
+ \fn bool qFuzzyCompare(float p1, float p2)
+ \relates <QtNumeric>
+ \since 4.4
+ \threadsafe
+
+ Compares the floating point value \a p1 and \a p2 and
+ returns \c true if they are considered equal, otherwise \c false.
+
+ The two numbers are compared in a relative way, where the
+ exactness is stronger the smaller the numbers are.
+*/
+
+/*!
+ \fn bool qFuzzyIsNull(double d)
+ \relates <QtNumeric>
+ \since 4.4
+ \threadsafe
+
+ Returns true if the absolute value of \a d is within 0.000000000001 of 0.0.
+*/
+
+/*!
+ \fn bool qFuzzyIsNull(float f)
+ \relates <QtNumeric>
+ \since 4.4
+ \threadsafe
+
+ Returns true if the absolute value of \a f is within 0.00001f of 0.0.
+*/
+
+namespace QtNumericTests {
+
+template <typename T> static constexpr T max = std::numeric_limits<T>::max();
+template <typename T> static constexpr T min = std::numeric_limits<T>::min();
+
+static_assert(qt_saturate<short>(max<unsigned>) == max<short>);
+static_assert(qt_saturate<int>(max<unsigned>) == max<int>);
+static_assert(qt_saturate<qint64>(max<unsigned>) == qint64(max<unsigned>));
+
+static_assert(qt_saturate<short>(max<int>) == max<short>);
+static_assert(qt_saturate<unsigned>(max<int>) == unsigned(max<int>));
+static_assert(qt_saturate<qint64>(max<int>) == qint64(max<int>));
+
+static_assert(qt_saturate<short>(max<qint64>) == max<short>);
+static_assert(qt_saturate<int>(max<qint64>) == max<int>);
+static_assert(qt_saturate<unsigned>(max<qint64>) == max<unsigned>);
+static_assert(qt_saturate<quint64>(max<qint64>) == quint64(max<qint64>));
+
+static_assert(qt_saturate<short>(max<quint64>) == max<short>);
+static_assert(qt_saturate<int>(max<quint64>) == max<int>);
+static_assert(qt_saturate<unsigned>(max<quint64>) == max<unsigned>);
+static_assert(qt_saturate<qint64>(max<quint64>) == max<qint64>);
+
+static_assert(qt_saturate<short>(min<int>) == min<short>);
+static_assert(qt_saturate<qint64>(min<int>) == qint64(min<int>));
+static_assert(qt_saturate<unsigned>(min<int>) == 0);
+static_assert(qt_saturate<quint64>(min<int>) == 0);
+
+static_assert(qt_saturate<short>(min<qint64>) == min<short>);
+static_assert(qt_saturate<int>(min<qint64>) == min<int>);
+static_assert(qt_saturate<unsigned>(min<qint64>) == 0);
+static_assert(qt_saturate<quint64>(min<qint64>) == 0);
+
+} // namespace QtNumericTests
QT_END_NAMESPACE
diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h
index 2771eea64f..2238c13da0 100644
--- a/src/corelib/global/qnumeric.h
+++ b/src/corelib/global/qnumeric.h
@@ -1,49 +1,61 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QNUMERIC_H
#define QNUMERIC_H
-#include <QtCore/qglobal.h>
+#if 0
+#pragma qt_class(QtNumeric)
+#endif
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
+#include <QtCore/qtypes.h>
+
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+// min() and max() may be #defined by windows.h if that is included before, but we need them
+// for std::numeric_limits below. You should not use the min() and max() macros, so we just #undef.
+#ifdef min
+# undef min
+# undef max
+#endif
+
+#if defined(Q_CC_MSVC)
+# include <intrin.h>
+# include <float.h>
+# if defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_ARM_64)
+# define Q_INTRINSIC_MUL_OVERFLOW64
+# define Q_UMULH(v1, v2) __umulh(v1, v2);
+# define Q_SMULH(v1, v2) __mulh(v1, v2);
+# pragma intrinsic(__umulh)
+# pragma intrinsic(__mulh)
+# endif
+#endif
+
+# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
+# include <arm64_ghs.h>
+# define Q_INTRINSIC_MUL_OVERFLOW64
+# define Q_UMULH(v1, v2) __MULUH64(v1, v2);
+# define Q_SMULH(v1, v2) __MULSH64(v1, v2);
+#endif
QT_BEGIN_NAMESPACE
+// To match std::is{inf,nan,finite} functions:
+template <typename T>
+constexpr typename std::enable_if<std::is_integral<T>::value, bool>::type
+qIsInf(T) { return false; }
+template <typename T>
+constexpr typename std::enable_if<std::is_integral<T>::value, bool>::type
+qIsNaN(T) { return false; }
+template <typename T>
+constexpr typename std::enable_if<std::is_integral<T>::value, bool>::type
+qIsFinite(T) { return true; }
+
+// Floating-point types (see qfloat16.h for its overloads).
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d);
@@ -52,6 +64,7 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val);
+
#if QT_CONFIG(signaling_nan)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN();
#endif
@@ -67,6 +80,330 @@ Q_CORE_EXPORT quint64 qFloatDistance(double a, double b);
#endif
#define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)())
+// Overflow math.
+// This provides efficient implementations for int, unsigned, qsizetype and
+// size_t. Implementations for 8- and 16-bit types will work but may not be as
+// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
+
+#if (Q_CC_GNU >= 500 || __has_builtin(__builtin_add_overflow)) \
+ && !(QT_POINTER_SIZE == 4 && defined(Q_CC_CLANG))
+// GCC 5 and Clang 3.8 have builtins to detect overflows
+// 32 bit Clang has the builtins but tries to link a library which hasn't
+#define Q_INTRINSIC_MUL_OVERFLOW64
+
+template <typename T> inline
+typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
+qAddOverflow(T v1, T v2, T *r)
+{ return __builtin_add_overflow(v1, v2, r); }
+
+template <typename T> inline
+typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
+qSubOverflow(T v1, T v2, T *r)
+{ return __builtin_sub_overflow(v1, v2, r); }
+
+template <typename T> inline
+typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
+qMulOverflow(T v1, T v2, T *r)
+{ return __builtin_mul_overflow(v1, v2, r); }
+
+#else
+// Generic implementations
+
+template <typename T> inline typename std::enable_if_t<std::is_unsigned_v<T>, bool>
+qAddOverflow(T v1, T v2, T *r)
+{
+ // unsigned additions are well-defined
+ *r = v1 + v2;
+ return v1 > T(v1 + v2);
+}
+
+template <typename T> inline typename std::enable_if_t<std::is_signed_v<T>, bool>
+qAddOverflow(T v1, T v2, T *r)
+{
+ // Here's how we calculate the overflow:
+ // 1) unsigned addition is well-defined, so we can always execute it
+ // 2) conversion from unsigned back to signed is implementation-
+ // defined and in the implementations we use, it's a no-op.
+ // 3) signed integer overflow happens if the sign of the two input operands
+ // is the same but the sign of the result is different. In other words,
+ // the sign of the result must be the same as the sign of either
+ // operand.
+
+ using U = typename std::make_unsigned_t<T>;
+ *r = T(U(v1) + U(v2));
+
+ // If int is two's complement, assume all integer types are too.
+ if (std::is_same_v<int32_t, int>) {
+ // Two's complement equivalent (generates slightly shorter code):
+ // x ^ y is negative if x and y have different signs
+ // x & y is negative if x and y are negative
+ // (x ^ z) & (y ^ z) is negative if x and z have different signs
+ // AND y and z have different signs
+ return ((v1 ^ *r) & (v2 ^ *r)) < 0;
+ }
+
+ bool s1 = (v1 < 0);
+ bool s2 = (v2 < 0);
+ bool sr = (*r < 0);
+ return s1 != sr && s2 != sr;
+ // also: return s1 == s2 && s1 != sr;
+}
+
+template <typename T> inline typename std::enable_if_t<std::is_unsigned_v<T>, bool>
+qSubOverflow(T v1, T v2, T *r)
+{
+ // unsigned subtractions are well-defined
+ *r = v1 - v2;
+ return v1 < v2;
+}
+
+template <typename T> inline typename std::enable_if_t<std::is_signed_v<T>, bool>
+qSubOverflow(T v1, T v2, T *r)
+{
+ // See above for explanation. This is the same with some signs reversed.
+ // We can't use qAddOverflow(v1, -v2, r) because it would be UB if
+ // v2 == std::numeric_limits<T>::min().
+
+ using U = typename std::make_unsigned_t<T>;
+ *r = T(U(v1) - U(v2));
+
+ if (std::is_same_v<int32_t, int>)
+ return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
+
+ bool s1 = (v1 < 0);
+ bool s2 = !(v2 < 0);
+ bool sr = (*r < 0);
+ return s1 != sr && s2 != sr;
+ // also: return s1 == s2 && s1 != sr;
+}
+
+template <typename T> inline
+typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
+qMulOverflow(T v1, T v2, T *r)
+{
+ // use the next biggest type
+ // Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
+ using LargerInt = QIntegerForSize<sizeof(T) * 2>;
+ using Larger = typename std::conditional_t<std::is_signed_v<T>,
+ typename LargerInt::Signed, typename LargerInt::Unsigned>;
+ Larger lr = Larger(v1) * Larger(v2);
+ *r = T(lr);
+ return lr > (std::numeric_limits<T>::max)() || lr < (std::numeric_limits<T>::min)();
+}
+
+# if defined(Q_INTRINSIC_MUL_OVERFLOW64)
+template <> inline bool qMulOverflow(quint64 v1, quint64 v2, quint64 *r)
+{
+ *r = v1 * v2;
+ return Q_UMULH(v1, v2);
+}
+template <> inline bool qMulOverflow(qint64 v1, qint64 v2, qint64 *r)
+{
+ // This is slightly more complex than the unsigned case above: the sign bit
+ // of 'low' must be replicated as the entire 'high', so the only valid
+ // values for 'high' are 0 and -1. Use unsigned multiply since it's the same
+ // as signed for the low bits and use a signed right shift to verify that
+ // 'high' is nothing but sign bits that match the sign of 'low'.
+
+ qint64 high = Q_SMULH(v1, v2);
+ *r = qint64(quint64(v1) * quint64(v2));
+ return (*r >> 63) != high;
+}
+
+# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
+template <> inline bool qMulOverflow(uint64_t v1, uint64_t v2, uint64_t *r)
+{
+ return qMulOverflow<quint64>(v1,v2,reinterpret_cast<quint64*>(r));
+}
+
+template <> inline bool qMulOverflow(int64_t v1, int64_t v2, int64_t *r)
+{
+ return qMulOverflow<qint64>(v1,v2,reinterpret_cast<qint64*>(r));
+}
+# endif // OS_INTEGRITY ARM64
+# endif // Q_INTRINSIC_MUL_OVERFLOW64
+
+# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
+// We can use intrinsics for the unsigned operations with MSVC
+template <> inline bool qAddOverflow(unsigned v1, unsigned v2, unsigned *r)
+{ return _addcarry_u32(0, v1, v2, r); }
+
+// 32-bit qMulOverflow is fine with the generic code above
+
+template <> inline bool qAddOverflow(quint64 v1, quint64 v2, quint64 *r)
+{
+# if defined(Q_PROCESSOR_X86_64)
+ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r));
+# else
+ uint low, high;
+ uchar carry = _addcarry_u32(0, unsigned(v1), unsigned(v2), &low);
+ carry = _addcarry_u32(carry, v1 >> 32, v2 >> 32, &high);
+ *r = (quint64(high) << 32) | low;
+ return carry;
+# endif // !x86-64
+}
+# endif // MSVC X86
+#endif // !GCC
+
+// Implementations for addition, subtraction or multiplication by a
+// compile-time constant. For addition and subtraction, we simply call the code
+// that detects overflow at runtime. For multiplication, we compare to the
+// maximum possible values before multiplying to ensure no overflow happens.
+
+template <typename T, T V2> bool qAddOverflow(T v1, std::integral_constant<T, V2>, T *r)
+{
+ return qAddOverflow(v1, V2, r);
+}
+
+template <auto V2, typename T> bool qAddOverflow(T v1, T *r)
+{
+ return qAddOverflow(v1, std::integral_constant<T, V2>{}, r);
+}
+
+template <typename T, T V2> bool qSubOverflow(T v1, std::integral_constant<T, V2>, T *r)
+{
+ return qSubOverflow(v1, V2, r);
+}
+
+template <auto V2, typename T> bool qSubOverflow(T v1, T *r)
+{
+ return qSubOverflow(v1, std::integral_constant<T, V2>{}, r);
+}
+
+template <typename T, T V2> bool qMulOverflow(T v1, std::integral_constant<T, V2>, T *r)
+{
+ // Runtime detection for anything smaller than or equal to a register
+ // width, as most architectures' multiplication instructions actually
+ // produce a result twice as wide as the input registers, allowing us to
+ // efficiently detect the overflow.
+ if constexpr (sizeof(T) <= sizeof(qregisteruint)) {
+ return qMulOverflow(v1, V2, r);
+
+#ifdef Q_INTRINSIC_MUL_OVERFLOW64
+ } else if constexpr (sizeof(T) <= sizeof(quint64)) {
+ // If we have intrinsics detecting overflow of 64-bit multiplications,
+ // then detect overflows through them up to 64 bits.
+ return qMulOverflow(v1, V2, r);
+#endif
+
+ } else if constexpr (V2 == 0 || V2 == 1) {
+ // trivial cases (and simplify logic below due to division by zero)
+ *r = v1 * V2;
+ return false;
+ } else if constexpr (V2 == -1) {
+ // multiplication by -1 is valid *except* for signed minimum values
+ // (necessary to avoid diving min() by -1, which is an overflow)
+ if (v1 < 0 && v1 == (std::numeric_limits<T>::min)())
+ return true;
+ *r = -v1;
+ return false;
+ } else {
+ // For 64-bit multiplications on 32-bit platforms, let's instead compare v1
+ // against the bounds that would overflow.
+ constexpr T Highest = (std::numeric_limits<T>::max)() / V2;
+ constexpr T Lowest = (std::numeric_limits<T>::min)() / V2;
+ if constexpr (Highest > Lowest) {
+ if (v1 > Highest || v1 < Lowest)
+ return true;
+ } else {
+ // this can only happen if V2 < 0
+ static_assert(V2 < 0);
+ if (v1 > Lowest || v1 < Highest)
+ return true;
+ }
+
+ *r = v1 * V2;
+ return false;
+ }
+}
+
+template <auto V2, typename T> bool qMulOverflow(T v1, T *r)
+{
+ if constexpr (V2 == 2)
+ return qAddOverflow(v1, v1, r);
+ return qMulOverflow(v1, std::integral_constant<T, V2>{}, r);
+}
+
+template <typename T>
+constexpr inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
+
+// gcc < 10 doesn't have __has_builtin
+#if defined(Q_PROCESSOR_ARM_64) && (__has_builtin(__builtin_round) || defined(Q_CC_GNU)) && !defined(Q_CC_CLANG)
+// ARM64 has a single instruction that can do C++ rounding with conversion to integer.
+// Note current clang versions have non-constexpr __builtin_round, ### allow clang this path when they fix it.
+constexpr inline int qRound(double d)
+{ return int(__builtin_round(d)); }
+constexpr inline int qRound(float f)
+{ return int(__builtin_roundf(f)); }
+constexpr inline qint64 qRound64(double d)
+{ return qint64(__builtin_round(d)); }
+constexpr inline qint64 qRound64(float f)
+{ return qint64(__builtin_roundf(f)); }
+#elif defined(__SSE2__) && (__has_builtin(__builtin_copysign) || defined(Q_CC_GNU))
+// SSE has binary operations directly on floating point making copysign fast
+constexpr inline int qRound(double d)
+{ return int(d + __builtin_copysign(0.5, d)); }
+constexpr inline int qRound(float f)
+{ return int(f + __builtin_copysignf(0.5f, f)); }
+constexpr inline qint64 qRound64(double d)
+{ return qint64(d + __builtin_copysign(0.5, d)); }
+constexpr inline qint64 qRound64(float f)
+{ return qint64(f + __builtin_copysignf(0.5f, f)); }
+#else
+constexpr inline int qRound(double d)
+{ return d >= 0.0 ? int(d + 0.5) : int(d - 0.5); }
+constexpr inline int qRound(float d)
+{ return d >= 0.0f ? int(d + 0.5f) : int(d - 0.5f); }
+
+constexpr inline qint64 qRound64(double d)
+{ return d >= 0.0 ? qint64(d + 0.5) : qint64(d - 0.5); }
+constexpr inline qint64 qRound64(float d)
+{ return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - 0.5f); }
+#endif
+
+namespace QtPrivate {
+template <typename T>
+constexpr inline const T &min(const T &a, const T &b) { return (a < b) ? a : b; }
+}
+
+[[nodiscard]] constexpr bool qFuzzyCompare(double p1, double p2)
+{
+ return (qAbs(p1 - p2) * 1000000000000. <= QtPrivate::min(qAbs(p1), qAbs(p2)));
+}
+
+[[nodiscard]] constexpr bool qFuzzyCompare(float p1, float p2)
+{
+ return (qAbs(p1 - p2) * 100000.f <= QtPrivate::min(qAbs(p1), qAbs(p2)));
+}
+
+[[nodiscard]] constexpr bool qFuzzyIsNull(double d)
+{
+ return qAbs(d) <= 0.000000000001;
+}
+
+[[nodiscard]] constexpr bool qFuzzyIsNull(float f)
+{
+ return qAbs(f) <= 0.00001f;
+}
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_FLOAT_COMPARE
+
+[[nodiscard]] constexpr bool qIsNull(double d) noexcept
+{
+ return d == 0.0;
+}
+
+[[nodiscard]] constexpr bool qIsNull(float f) noexcept
+{
+ return f == 0.0f;
+}
+
+QT_WARNING_POP
+
+inline int qIntCast(double f) { return int(f); }
+inline int qIntCast(float f) { return int(f); }
+
QT_END_NAMESPACE
#endif // QNUMERIC_H
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 790a00bdb5..d40e6b964b 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QNUMERIC_P_H
#define QNUMERIC_P_H
@@ -53,29 +17,17 @@
//
#include "QtCore/private/qglobal_p.h"
+#include "QtCore/qnumeric.h"
+#include "QtCore/qsimd.h"
#include <cmath>
#include <limits>
+#include <type_traits>
-#if defined(Q_CC_MSVC)
-# include <intrin.h>
-# include <float.h>
-# if defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_ARM_64)
-# define Q_INTRINSIC_MUL_OVERFLOW64
-# define Q_UMULH(v1, v2) __umulh(v1, v2);
-# define Q_SMULH(v1, v2) __mulh(v1, v2);
-# pragma intrinsic(__umulh)
-# pragma intrinsic(__mulh)
-# endif
-#endif
-
-# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
-#include <arm64_ghs.h>
-# define Q_INTRINSIC_MUL_OVERFLOW64
-# define Q_UMULH(v1, v2) __MULUH64(v1, v2);
-# define Q_SMULH(v1, v2) __MULSH64(v1, v2);
+#ifndef __has_extension
+# define __has_extension(X) 0
#endif
-#if !defined(Q_CC_MSVC) && (defined(Q_OS_QNX) || defined(Q_CC_INTEL))
+#if !defined(Q_CC_MSVC) && defined(Q_OS_QNX)
# include <math.h>
# ifdef isnan
# define QT_MATH_H_DEFINES_MACROS
@@ -103,6 +55,8 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
+class qfloat16;
+
namespace qnumeric_std_wrapper {
#if defined(QT_MATH_H_DEFINES_MACROS)
# undef QT_MATH_H_DEFINES_MACROS
@@ -126,27 +80,27 @@ Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return std::fpclas
#endif
}
-Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() noexcept
+constexpr Q_DECL_CONST_FUNCTION static inline double qt_inf() noexcept
{
static_assert(std::numeric_limits<double>::has_infinity,
- "platform has no definition for infinity for type double");
+ "platform has no definition for infinity for type double");
return std::numeric_limits<double>::infinity();
}
#if QT_CONFIG(signaling_nan)
-Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() noexcept
+constexpr Q_DECL_CONST_FUNCTION static inline double qt_snan() noexcept
{
static_assert(std::numeric_limits<double>::has_signaling_NaN,
- "platform has no definition for signaling NaN for type double");
+ "platform has no definition for signaling NaN for type double");
return std::numeric_limits<double>::signaling_NaN();
}
#endif
// Quiet NaN
-Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() noexcept
+constexpr Q_DECL_CONST_FUNCTION static inline double qt_qnan() noexcept
{
static_assert(std::numeric_limits<double>::has_quiet_NaN,
- "platform has no definition for quiet NaN for type double");
+ "platform has no definition for quiet NaN for type double");
return std::numeric_limits<double>::quiet_NaN();
}
@@ -190,21 +144,38 @@ Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(float f)
return qnumeric_std_wrapper::fpclassify(f);
}
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
namespace {
/*!
Returns true if the double \a v can be converted to type \c T, false if
it's out of range. If the conversion is successful, the converted value is
stored in \a value; if it was not successful, \a value will contain the
minimum or maximum of T, depending on the sign of \a d. If \c T is
- unsigned, then \a value contains the absolute value of \a v.
+ unsigned, then \a value contains the absolute value of \a v. If \c T is \c
+ float, an underflow is also signalled by returning false and setting \a
+ value to zero.
This function works for v containing infinities, but not NaN. It's the
caller's responsibility to exclude that possibility before calling it.
*/
-template <typename T> static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
+template <typename T> static inline std::enable_if_t<std::is_integral_v<T>, bool>
+convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
{
- static_assert(std::numeric_limits<T>::is_integer);
+ static_assert(std::is_integral_v<T>);
+ constexpr bool TypeIsLarger = std::numeric_limits<T>::digits > std::numeric_limits<double>::digits;
+
+ if constexpr (TypeIsLarger) {
+ using S = std::make_signed_t<T>;
+ constexpr S max_mantissa = S(1) << std::numeric_limits<double>::digits;
+ // T has more bits than double's mantissa, so don't allow "upgrading"
+ // to T (makes it look like the number had more precision than really
+ // was transmitted)
+ if (!allow_precision_upgrade && !(v <= double(max_mantissa) && v >= double(-max_mantissa - 1)))
+ return false;
+ }
+
+ constexpr T Tmin = (std::numeric_limits<T>::min)();
+ constexpr T Tmax = (std::numeric_limits<T>::max)();
// The [conv.fpint] (7.10 Floating-integral conversions) section of the C++
// standard says only exact conversions are guaranteed. Converting
@@ -216,23 +187,90 @@ template <typename T> static inline bool convertDoubleTo(double v, T *value, boo
// correct, but Clang, ICC and MSVC don't realize that it's a constant and
// the math call stays in the compiled code.
+#if defined(Q_PROCESSOR_X86_64) && defined(__SSE2__)
+ // Of course, UB doesn't apply if we use intrinsics, in which case we are
+ // allowed to dpeend on exactly the processor's behavior. This
+ // implementation uses the truncating conversions from Scalar Double to
+ // integral types (CVTTSD2SI and VCVTTSD2USI), which is documented to
+ // return the "indefinite integer value" if the range of the target type is
+ // exceeded. (only implemented for x86-64 to avoid having to deal with the
+ // non-existence of the 64-bit intrinsics on i386)
+
+ if (std::numeric_limits<T>::is_signed) {
+ __m128d mv = _mm_set_sd(v);
+# ifdef __AVX512F__
+ // use explicit round control and suppress exceptions
+ if (sizeof(T) > 4)
+ *value = T(_mm_cvtt_roundsd_i64(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
+ else
+ *value = _mm_cvtt_roundsd_i32(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+# else
+ *value = sizeof(T) > 4 ? T(_mm_cvttsd_si64(mv)) : _mm_cvttsd_si32(mv);
+# endif
+
+ // if *value is the "indefinite integer value", check if the original
+ // variable \a v is the same value (Tmin is an exact representation)
+ if (*value == Tmin && !_mm_ucomieq_sd(mv, _mm_set_sd(Tmin))) {
+ // v != Tmin, so it was out of range
+ if (v > 0)
+ *value = Tmax;
+ return false;
+ }
+
+ // convert the integer back to double and compare for equality with v,
+ // to determine if we've lost any precision
+ __m128d mi = _mm_setzero_pd();
+ mi = sizeof(T) > 4 ? _mm_cvtsi64_sd(mv, *value) : _mm_cvtsi32_sd(mv, *value);
+ return _mm_ucomieq_sd(mv, mi);
+ }
+
+# ifdef __AVX512F__
+ if (!std::numeric_limits<T>::is_signed) {
+ // Same thing as above, but this function operates on absolute values
+ // and the "indefinite integer value" for the 64-bit unsigned
+ // conversion (Tmax) is not representable in double, so it can never be
+ // the result of an in-range conversion. This is implemented for AVX512
+ // and later because of the unsigned conversion instruction. Converting
+ // to unsigned without losing an extra bit of precision prior to AVX512
+ // is left to the compiler below.
+
+ v = fabs(v);
+ __m128d mv = _mm_set_sd(v);
+
+ // use explicit round control and suppress exceptions
+ if (sizeof(T) > 4)
+ *value = T(_mm_cvtt_roundsd_u64(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
+ else
+ *value = _mm_cvtt_roundsd_u32(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+
+ if (*value == Tmax) {
+ // no double can have an exact value of quint64(-1), but they can
+ // quint32(-1), so we need to compare for that
+ if (TypeIsLarger || _mm_ucomieq_sd(mv, _mm_set_sd(Tmax)))
+ return false;
+ }
+
+ // return true if it was an exact conversion
+ __m128d mi = _mm_setzero_pd();
+ mi = sizeof(T) > 4 ? _mm_cvtu64_sd(mv, *value) : _mm_cvtu32_sd(mv, *value);
+ return _mm_ucomieq_sd(mv, mi);
+ }
+# endif
+#endif
+
double supremum;
if (std::numeric_limits<T>::is_signed) {
- supremum = -1.0 * std::numeric_limits<T>::min(); // -1 * (-2^63) = 2^63, exact (for T = qint64)
- *value = std::numeric_limits<T>::min();
- if (v < std::numeric_limits<T>::min())
+ supremum = -1.0 * Tmin; // -1 * (-2^63) = 2^63, exact (for T = qint64)
+ *value = Tmin;
+ if (v < Tmin)
return false;
} else {
using ST = typename std::make_signed<T>::type;
- supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
+ supremum = -2.0 * (std::numeric_limits<ST>::min)(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
v = fabs(v);
}
- if (std::is_integral<T>::value && sizeof(T) > 4 && !allow_precision_upgrade) {
- if (v > double(Q_INT64_C(1)<<53) || v < double(-((Q_INT64_C(1)<<53) + 1)))
- return false;
- }
- *value = std::numeric_limits<T>::max();
+ *value = Tmax;
if (v >= supremum)
return false;
@@ -247,170 +285,186 @@ QT_WARNING_DISABLE_FLOAT_COMPARE
QT_WARNING_POP
}
-// Overflow math.
-// This provides efficient implementations for int, unsigned, qsizetype and
-// size_t. Implementations for 8- and 16-bit types will work but may not be as
-// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
-
-#if ((defined(Q_CC_INTEL) ? (Q_CC_INTEL >= 1800 && !defined(Q_OS_WIN)) : defined(Q_CC_GNU)) \
- && Q_CC_GNU >= 500) || __has_builtin(__builtin_add_overflow)
-// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
-
-template <typename T> inline
-typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
-add_overflow(T v1, T v2, T *r)
-{ return __builtin_add_overflow(v1, v2, r); }
+template <typename T> static
+std::enable_if_t<std::is_floating_point_v<T> || std::is_same_v<T, qfloat16>, bool>
+convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
+{
+ Q_UNUSED(allow_precision_upgrade);
+ constexpr T Huge = std::numeric_limits<T>::infinity();
+
+ if constexpr (std::numeric_limits<double>::max_exponent <=
+ std::numeric_limits<T>::max_exponent) {
+ // no UB can happen
+ *value = T(v);
+ return true;
+ }
-template <typename T> inline
-typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
-sub_overflow(T v1, T v2, T *r)
-{ return __builtin_sub_overflow(v1, v2, r); }
+#if defined(__SSE2__) && (defined(Q_CC_GNU) || __has_extension(gnu_asm))
+ // The x86 CVTSD2SH instruction from SSE2 does what we want:
+ // - converts out-of-range doubles to ±infinity and sets #O
+ // - converts underflows to zero and sets #U
+ // We need to clear any previously-stored exceptions from it before the
+ // operation (3-cycle cost) and obtain the new state afterwards (1 cycle).
+
+ unsigned csr = _MM_MASK_MASK; // clear stored exception indicators
+ auto sse_check_result = [&](auto result) {
+ if ((csr & (_MM_EXCEPT_UNDERFLOW | _MM_EXCEPT_OVERFLOW)) == 0)
+ return true;
+ if (csr & _MM_EXCEPT_OVERFLOW)
+ return false;
-template <typename T> inline
-typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
-mul_overflow(T v1, T v2, T *r)
-{ return __builtin_mul_overflow(v1, v2, r); }
+ // According to IEEE 754[1], #U is also set when the result is tiny and
+ // inexact, but still non-zero, so detect that (this won't generate
+ // good code for types without hardware support).
+ // [1] https://en.wikipedia.org/wiki/Floating-point_arithmetic#Exception_handling
+ return result != 0;
+ };
+
+ // Written directly in assembly because both Clang and GCC have been
+ // observed to reorder the STMXCSR instruction above the conversion
+ // operation. MSVC generates horrid code when using the intrinsics anyway,
+ // so it's not a loss.
+ // See https://github.com/llvm/llvm-project/issues/83661.
+ if constexpr (std::is_same_v<T, float>) {
+# ifdef __AVX__
+ asm ("vldmxcsr %[csr]\n\t"
+ "vcvtsd2ss %[in], %[in], %[out]\n\t"
+ "vstmxcsr %[csr]"
+ : [csr] "+m" (csr), [out] "=v" (*value) : [in] "v" (v));
+# else
+ asm ("ldmxcsr %[csr]\n\t"
+ "cvtsd2ss %[in], %[out]\n\t"
+ "stmxcsr %[csr]"
+ : [csr] "+m" (csr), [out] "=v" (*value) : [in] "v" (v));
+# endif
+ return sse_check_result(*value);
+ }
-#else
-// Generic implementations
+# if defined(__F16C__) || defined(__AVX512FP16__)
+ if constexpr (sizeof(T) == 2 && std::numeric_limits<T>::max_exponent == 16) {
+ // qfloat16 or std::float16_t, but not std::bfloat16_t or std::bfloat8_t
+ auto doConvert = [&](auto *out) {
+ asm ("vldmxcsr %[csr]\n\t"
+# ifdef __AVX512FP16__
+ // AVX512FP16 & AVX10 have an instruction for this
+ "vcvtsd2sh %[in], %[in], %[out]\n\t"
+# else
+ "vcvtsd2ss %[in], %[in], %[out]\n\t" // sets DEST[MAXVL-1:128] := 0
+ "vcvtps2ph %[rc], %[out], %[out]\n\t"
+# endif
+ "vstmxcsr %[csr]"
+ : [csr] "+m" (csr), [out] "=v" (*out)
+ : [in] "v" (v), [rc] "i" (_MM_FROUND_CUR_DIRECTION)
+ );
+ return sse_check_result(out);
+ };
+
+ if constexpr (std::is_same_v<T, qfloat16> && !std::is_void_v<typename T::NativeType>) {
+ typename T::NativeType tmp;
+ bool b = doConvert(&tmp);
+ *value = tmp;
+ return b;
+ } else {
+# ifndef Q_CC_CLANG
+ // Clang can only implement this if it has a native FP16 type
+ return doConvert(value);
+# endif
+ }
+ }
+# endif
+#endif // __SSE2__ && inline assembly
-template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
-add_overflow(T v1, T v2, T *r)
-{
- // unsigned additions are well-defined
- *r = v1 + v2;
- return v1 > T(v1 + v2);
-}
+ if (!qt_is_finite(v) && std::numeric_limits<T>::has_infinity) {
+ // infinity (or NaN)
+ *value = T(v);
+ return true;
+ }
-template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
-add_overflow(T v1, T v2, T *r)
-{
- // Here's how we calculate the overflow:
- // 1) unsigned addition is well-defined, so we can always execute it
- // 2) conversion from unsigned back to signed is implementation-
- // defined and in the implementations we use, it's a no-op.
- // 3) signed integer overflow happens if the sign of the two input operands
- // is the same but the sign of the result is different. In other words,
- // the sign of the result must be the same as the sign of either
- // operand.
-
- using U = typename std::make_unsigned<T>::type;
- *r = T(U(v1) + U(v2));
-
- // If int is two's complement, assume all integer types are too.
- if (std::is_same<int32_t, int>::value) {
- // Two's complement equivalent (generates slightly shorter code):
- // x ^ y is negative if x and y have different signs
- // x & y is negative if x and y are negative
- // (x ^ z) & (y ^ z) is negative if x and z have different signs
- // AND y and z have different signs
- return ((v1 ^ *r) & (v2 ^ *r)) < 0;
+ // Check for in-range value to ensure the conversion is not UB (see the
+ // comment above for Standard language).
+ if (std::fabs(v) > (std::numeric_limits<T>::max)()) {
+ *value = v < 0 ? -Huge : Huge;
+ return false;
}
- bool s1 = (v1 < 0);
- bool s2 = (v2 < 0);
- bool sr = (*r < 0);
- return s1 != sr && s2 != sr;
- // also: return s1 == s2 && s1 != sr;
+ *value = T(v);
+ if (v != 0 && *value == 0) {
+ // Underflow through loss of precision
+ return false;
+ }
+ return true;
}
-template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
-sub_overflow(T v1, T v2, T *r)
-{
- // unsigned subtractions are well-defined
- *r = v1 - v2;
- return v1 < v2;
-}
+template <typename T> inline bool add_overflow(T v1, T v2, T *r) { return qAddOverflow(v1, v2, r); }
+template <typename T> inline bool sub_overflow(T v1, T v2, T *r) { return qSubOverflow(v1, v2, r); }
+template <typename T> inline bool mul_overflow(T v1, T v2, T *r) { return qMulOverflow(v1, v2, r); }
-template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
-sub_overflow(T v1, T v2, T *r)
+template <typename T, T V2> bool add_overflow(T v1, std::integral_constant<T, V2>, T *r)
{
- // See above for explanation. This is the same with some signs reversed.
- // We can't use add_overflow(v1, -v2, r) because it would be UB if
- // v2 == std::numeric_limits<T>::min().
-
- using U = typename std::make_unsigned<T>::type;
- *r = T(U(v1) - U(v2));
-
- if (std::is_same<int32_t, int>::value)
- return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
-
- bool s1 = (v1 < 0);
- bool s2 = !(v2 < 0);
- bool sr = (*r < 0);
- return s1 != sr && s2 != sr;
- // also: return s1 == s2 && s1 != sr;
+ return qAddOverflow<T, V2>(v1, std::integral_constant<T, V2>{}, r);
}
-template <typename T> inline
-typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
-mul_overflow(T v1, T v2, T *r)
+template <auto V2, typename T> bool add_overflow(T v1, T *r)
{
- // use the next biggest type
- // Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
- using LargerInt = QIntegerForSize<sizeof(T) * 2>;
- using Larger = typename std::conditional<std::is_signed<T>::value,
- typename LargerInt::Signed, typename LargerInt::Unsigned>::type;
- Larger lr = Larger(v1) * Larger(v2);
- *r = T(lr);
- return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min();
+ return qAddOverflow<V2, T>(v1, r);
}
-# if defined(Q_INTRINSIC_MUL_OVERFLOW64)
-template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
+template <typename T, T V2> bool sub_overflow(T v1, std::integral_constant<T, V2>, T *r)
{
- *r = v1 * v2;
- return Q_UMULH(v1, v2);
+ return qSubOverflow<T, V2>(v1, std::integral_constant<T, V2>{}, r);
}
-template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
+
+template <auto V2, typename T> bool sub_overflow(T v1, T *r)
{
- // This is slightly more complex than the unsigned case above: the sign bit
- // of 'low' must be replicated as the entire 'high', so the only valid
- // values for 'high' are 0 and -1. Use unsigned multiply since it's the same
- // as signed for the low bits and use a signed right shift to verify that
- // 'high' is nothing but sign bits that match the sign of 'low'.
-
- qint64 high = Q_SMULH(v1, v2);
- *r = qint64(quint64(v1) * quint64(v2));
- return (*r >> 63) != high;
+ return qSubOverflow<V2, T>(v1, r);
}
-# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
-template <> inline bool mul_overflow(uint64_t v1, uint64_t v2, uint64_t *r)
+template <typename T, T V2> bool mul_overflow(T v1, std::integral_constant<T, V2>, T *r)
{
- return mul_overflow<quint64>(v1,v2,reinterpret_cast<quint64*>(r));
+ return qMulOverflow<T, V2>(v1, std::integral_constant<T, V2>{}, r);
}
-template <> inline bool mul_overflow(int64_t v1, int64_t v2, int64_t *r)
+template <auto V2, typename T> bool mul_overflow(T v1, T *r)
{
- return mul_overflow<qint64>(v1,v2,reinterpret_cast<qint64*>(r));
+ return qMulOverflow<V2, T>(v1, r);
}
-# endif // OS_INTEGRITY ARM64
-# endif // Q_INTRINSIC_MUL_OVERFLOW64
-
-# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
-// We can use intrinsics for the unsigned operations with MSVC
-template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
-{ return _addcarry_u32(0, v1, v2, r); }
+}
+#endif // Q_QDOC
-// 32-bit mul_overflow is fine with the generic code above
+/*
+ Safely narrows \a x to \c{To}. Let \c L be
+ \c{std::numeric_limit<To>::min()} and \c H be \c{std::numeric_limit<To>::max()}.
-template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r)
+ If \a x is less than L, returns L. If \a x is greater than H,
+ returns H. Otherwise, returns \c{To(x)}.
+*/
+template <typename To, typename From>
+static constexpr auto qt_saturate(From x)
{
-# if defined(Q_PROCESSOR_X86_64)
- return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r));
-# else
- uint low, high;
- uchar carry = _addcarry_u32(0, unsigned(v1), unsigned(v2), &low);
- carry = _addcarry_u32(carry, v1 >> 32, v2 >> 32, &high);
- *r = (quint64(high) << 32) | low;
- return carry;
-# endif // !x86-64
-}
-# endif // MSVC X86
-#endif // !GCC
+ static_assert(std::is_integral_v<To>);
+ static_assert(std::is_integral_v<From>);
+
+ [[maybe_unused]]
+ constexpr auto Lo = (std::numeric_limits<To>::min)();
+ constexpr auto Hi = (std::numeric_limits<To>::max)();
+
+ if constexpr (std::is_signed_v<From> == std::is_signed_v<To>) {
+ // same signedness, we can accept regular integer conversion rules
+ return x < Lo ? Lo :
+ x > Hi ? Hi :
+ /*else*/ To(x);
+ } else {
+ if constexpr (std::is_signed_v<From>) { // ie. !is_signed_v<To>
+ if (x < From{0})
+ return To{0};
+ }
+
+ // from here on, x >= 0
+ using FromU = std::make_unsigned_t<From>;
+ using ToU = std::make_unsigned_t<To>;
+ return FromU(x) > ToU(Hi) ? Hi : To(x); // assumes Hi >= 0
+ }
}
-#endif // Q_CLANG_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index 261f5c8795..cf6063fca0 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -1,52 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qoperatingsystemversion.h"
+
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
#include "qoperatingsystemversion_p.h"
#endif
+#if defined(Q_OS_DARWIN)
+#include <QtCore/private/qcore_mac_p.h>
+#endif
+
#include <qversionnumber.h>
#include <qdebug.h>
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
-#include <private/qjni_p.h>
+#ifdef Q_OS_ANDROID
+#include <QtCore/private/qjnihelpers_p.h>
+#include <QJniObject>
#endif
QT_BEGIN_NAMESPACE
@@ -64,11 +34,7 @@ QT_BEGIN_NAMESPACE
operating system version (as opposed to the kernel version number or
marketing version).
- This class is also a complete replacement for QSysInfo::macVersion and
- QSysInfo::windowsVersion, additionally providing access to the third (micro)
- version number component.
-
- Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS),
+ Presently, Android, Apple Platforms (iOS, macOS, tvOS, watchOS, and visionOS),
and Windows are supported.
The \a majorVersion(), \a minorVersion(), and \a microVersion() functions
@@ -93,7 +59,8 @@ QT_BEGIN_NAMESPACE
\row
\li Windows
\li dwMajorVersion, dwMinorVersion, and dwBuildNumber from
- \l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{RtlGetVersion} -
+ \l{https://docs.microsoft.com/en-us/windows/win32/devnotes/rtlgetversion}
+ {RtlGetVersion} -
note that this function ALWAYS return the version number of the
underlying operating system, as opposed to the shim underneath
GetVersionEx that hides the real version number if the
@@ -131,6 +98,7 @@ QT_BEGIN_NAMESPACE
\value MacOS The Apple macOS operating system.
\value TvOS The Apple tvOS operating system.
\value WatchOS The Apple watchOS operating system.
+ \value VisionOS The Apple visionOS operating system.
\value Windows The Microsoft Windows operating system.
\value Unknown An unknown or unsupported operating system.
@@ -144,20 +112,25 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QOperatingSystemVersion QOperatingSystemVersion::current()
-
+ \fn QOperatingSystemVersion::current()
Returns a QOperatingSystemVersion indicating the current OS and its version number.
\sa currentType()
*/
+QOperatingSystemVersionBase QOperatingSystemVersionBase::current()
+{
+ static const QOperatingSystemVersionBase v = current_impl();
+ return v;
+}
+
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
-QOperatingSystemVersion QOperatingSystemVersion::current()
+QOperatingSystemVersionBase QOperatingSystemVersionBase::current_impl()
{
- QOperatingSystemVersion version;
+ QOperatingSystemVersionBase version;
version.m_os = currentType();
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
#ifndef QT_BOOTSTRAPPED
- const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField(
+ const QVersionNumber v = QVersionNumber::fromString(QJniObject::getStaticObjectField(
"android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString());
if (!v.isNull()) {
version.m_major = v.majorVersion();
@@ -200,11 +173,17 @@ QOperatingSystemVersion QOperatingSystemVersion::current()
{ 7, 0 }, // API level 24
{ 7, 1 }, // API level 25
{ 8, 0 }, // API level 26
+ { 8, 1 }, // API level 27
+ { 9, 0 }, // API level 28
+ { 10, 0 }, // API level 29
+ { 11, 0 }, // API level 30
+ { 12, 0 }, // API level 31
+ { 12, 0 }, // API level 32
+ { 13, 0 }, // API level 33
};
// This will give us at least the first 2 version components
- const size_t versionIdx = size_t(QJNIObjectPrivate::getStaticField<jint>(
- "android/os/Build$VERSION", "SDK_INT")) - 1;
+ const size_t versionIdx = QtAndroidPrivate::androidSdkVersion() - 1;
if (versionIdx < sizeof(versions) / sizeof(versions[0])) {
version.m_major = versions[versionIdx].major;
version.m_minor = versions[versionIdx].minor;
@@ -221,13 +200,13 @@ QOperatingSystemVersion QOperatingSystemVersion::current()
}
#endif
-static inline int compareVersionComponents(int lhs, int rhs)
+static inline int compareVersionComponents(int lhs, int rhs) noexcept
{
return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0;
}
-int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
- const QOperatingSystemVersion &v2)
+int QOperatingSystemVersionBase::compare(QOperatingSystemVersionBase v1,
+ QOperatingSystemVersionBase v2) noexcept
{
if (v1.m_major == v2.m_major) {
if (v1.m_minor == v2.m_minor) {
@@ -239,6 +218,19 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
}
/*!
+ \fn QVersionNumber QOperatingSystemVersion::version() const
+
+ \since 6.1
+
+ Returns the operating system's version number.
+
+ See the main class documentation for what the version number is on a given
+ operating system.
+
+ \sa majorVersion(), minorVersion(), microVersion()
+*/
+
+/*!
\fn int QOperatingSystemVersion::majorVersion() const
Returns the major version number, that is, the first segment of the
@@ -249,7 +241,7 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
-1 indicates an unknown or absent version number component.
- \sa minorVersion(), microVersion()
+ \sa version(), minorVersion(), microVersion()
*/
/*!
@@ -263,7 +255,7 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
-1 indicates an unknown or absent version number component.
- \sa majorVersion(), microVersion()
+ \sa version(), majorVersion(), microVersion()
*/
/*!
@@ -277,7 +269,7 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
-1 indicates an unknown or absent version number component.
- \sa majorVersion(), minorVersion()
+ \sa version(), majorVersion(), minorVersion()
*/
/*!
@@ -311,32 +303,34 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
\sa type()
*/
-QString QOperatingSystemVersion::name() const
+QString QOperatingSystemVersionBase::name(QOperatingSystemVersionBase osversion)
{
- switch (type()) {
- case QOperatingSystemVersion::Windows:
+ switch (osversion.type()) {
+ case QOperatingSystemVersionBase::Windows:
return QStringLiteral("Windows");
- case QOperatingSystemVersion::MacOS: {
- if (majorVersion() < 10)
+ case QOperatingSystemVersionBase::MacOS: {
+ if (osversion.majorVersion() < 10)
return QStringLiteral("Mac OS");
- if (majorVersion() == 10 && minorVersion() < 8)
+ if (osversion.majorVersion() == 10 && osversion.minorVersion() < 8)
return QStringLiteral("Mac OS X");
- if (majorVersion() == 10 && minorVersion() < 12)
+ if (osversion.majorVersion() == 10 && osversion.minorVersion() < 12)
return QStringLiteral("OS X");
return QStringLiteral("macOS");
}
- case QOperatingSystemVersion::IOS: {
- if (majorVersion() < 4)
+ case QOperatingSystemVersionBase::IOS: {
+ if (osversion.majorVersion() < 4)
return QStringLiteral("iPhone OS");
return QStringLiteral("iOS");
}
- case QOperatingSystemVersion::TvOS:
+ case QOperatingSystemVersionBase::TvOS:
return QStringLiteral("tvOS");
- case QOperatingSystemVersion::WatchOS:
+ case QOperatingSystemVersionBase::WatchOS:
return QStringLiteral("watchOS");
- case QOperatingSystemVersion::Android:
+ case QOperatingSystemVersionBase::VisionOS:
+ return QStringLiteral("visionOS");
+ case QOperatingSystemVersionBase::Android:
return QStringLiteral("Android");
- case QOperatingSystemVersion::Unknown:
+ case QOperatingSystemVersionBase::Unknown:
default:
return QString();
}
@@ -350,13 +344,17 @@ QString QOperatingSystemVersion::name() const
*/
bool QOperatingSystemVersion::isAnyOfType(std::initializer_list<OSType> types) const
{
- for (const auto &t : qAsConst(types)) {
- if (type() == t)
- return true;
- }
- return false;
+ // ### Qt7: Remove this function
+ return std::find(types.begin(), types.end(), type()) != types.end();
+}
+
+bool QOperatingSystemVersionBase::isAnyOfType(std::initializer_list<OSType> types, OSType type)
+{
+ return std::find(types.begin(), types.end(), type) != types.end();
}
+#ifndef QT_BOOTSTRAPPED
+
/*!
\variable QOperatingSystemVersion::Windows7
\brief a version corresponding to Windows 7 (version 6.1).
@@ -383,13 +381,105 @@ const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 =
/*!
\variable QOperatingSystemVersion::Windows10
- \brief a version corresponding to Windows 10 (version 10.0).
+ \brief a version corresponding to general Windows 10 (version 10.0).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::Windows10 =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10);
/*!
+ \variable QOperatingSystemVersion::Windows10_1809
+ \brief a version corresponding to Windows 10 October 2018 Update
+ Version 1809 (version 10.0.17763).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_1809;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_1903
+ \brief a version corresponding to Windows 10 May 2019 Update
+ Version 1903 (version 10.0.18362).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_1903;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_1909
+ \brief a version corresponding to Windows 10 November 2019 Update
+ Version 1909 (version 10.0.18363).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_1909;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_2004
+ \brief a version corresponding to Windows 10 May 2020 Update
+ Version 2004 (version 10.0.19041).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_2004;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_20H2
+ \brief a version corresponding to Windows 10 October 2020 Update
+ Version 20H2 (version 10.0.19042).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_20H2;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_21H1
+ \brief a version corresponding to Windows 10 May 2021 Update
+ Version 21H1 (version 10.0.19043).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_21H1;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_21H2
+ \brief a version corresponding to Windows 10 November 2021 Update
+ Version 21H2 (version 10.0.19044).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_21H2;
+
+/*!
+ \variable QOperatingSystemVersion::Windows10_22H2
+ \brief a version corresponding to Windows 10 October 2022 Update
+ Version 22H2 (version 10.0.19045).
+ \since 6.5
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows10_22H2;
+
+/*!
+ \variable QOperatingSystemVersion::Windows11
+ \brief a version corresponding to the initial release of Windows 11
+ (version 10.0.22000).
+ \since 6.3
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows11;
+
+/*!
+ \variable QOperatingSystemVersion::Windows11_21H2
+ \brief a version corresponding to Windows 11 Version 21H2 (version 10.0.22000).
+ \since 6.4
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows11_21H2;
+
+/*!
+ \variable QOperatingSystemVersion::Windows11_22H2
+ \brief a version corresponding to Windows 11 Version 22H2 (version 10.0.22621).
+ \since 6.4
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Windows11_22H2;
+
+/*!
+ \variable QOperatingSystemVersion::Windows11_23H2
+ \brief a version corresponding to Windows 11 Version 23H2 (version 10.0.22631).
+ \since 6.6
+ */
+
+/*!
\variable QOperatingSystemVersion::OSXMavericks
\brief a version corresponding to OS X Mavericks (version 10.9).
\since 5.9
@@ -446,6 +536,35 @@ const QOperatingSystemVersion QOperatingSystemVersion::MacOSCatalina =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 15);
/*!
+ \variable QOperatingSystemVersion::MacOSBigSur
+ \brief a version corresponding to macOS Big Sur (version 11).
+ \since 6.0
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::MacOSBigSur =
+ QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 11, 0);
+
+/*!
+ \variable QOperatingSystemVersion::MacOSMonterey
+ \brief a version corresponding to macOS Monterey (version 12).
+ \since 6.3
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::MacOSMonterey =
+ QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 12, 0);
+
+/*!
+ \variable QOperatingSystemVersion::MacOSVentura
+ \brief a version corresponding to macOS Ventura (version 13).
+ \since 6.4
+*/
+const QOperatingSystemVersionBase QOperatingSystemVersion::MacOSVentura;
+
+/*!
+ \variable QOperatingSystemVersion::MacOSSonoma
+ \brief a version corresponding to macOS Sonoma (version 14).
+ \since 6.5
+*/
+
+/*!
\variable QOperatingSystemVersion::AndroidJellyBean
\brief a version corresponding to Android Jelly Bean (version 4.1, API level 16).
\since 5.9
@@ -529,6 +648,67 @@ const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 =
const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0);
+/*!
+ \variable QOperatingSystemVersion::AndroidOreo_MR1
+ \brief a version corresponding to Android Oreo_MR1 (version 8.1, API level 27).
+ \since 6.1
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo_MR1 =
+ QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 1);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidPie
+ \brief a version corresponding to Android Pie (version 9.0, API level 28).
+ \since 6.1
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidPie =
+ QOperatingSystemVersion(QOperatingSystemVersion::Android, 9, 0);
+
+/*!
+ \variable QOperatingSystemVersion::Android10
+ \brief a version corresponding to Android 10 (version 10.0, API level 29).
+ \since 6.1
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Android10 =
+ QOperatingSystemVersion(QOperatingSystemVersion::Android, 10, 0);
+
+/*!
+ \variable QOperatingSystemVersion::Android11
+ \brief a version corresponding to Android 11 (version 11.0, API level 30).
+ \since 6.1
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Android11 =
+ QOperatingSystemVersion(QOperatingSystemVersion::Android, 11, 0);
+
+/*!
+ \variable QOperatingSystemVersion::Android12
+ \brief a version corresponding to Android 12 (version 12.0, API level 31).
+ \since 6.5
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Android12;
+
+/*!
+ \variable QOperatingSystemVersion::Android12L
+ \brief a version corresponding to Android 12L (version 12.0, API level 32).
+ \since 6.5
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Android12L;
+
+/*!
+ \variable QOperatingSystemVersion::Android13
+ \brief a version corresponding to Android 13 (version 13.0, API level 33).
+ \since 6.5
+ */
+const QOperatingSystemVersionBase QOperatingSystemVersion::Android13;
+
+/*!
+ \variable QOperatingSystemVersion::Android14
+ \brief a version corresponding to Android 14 (version 14.0, API level 34).
+ \since 6.7
+ */
+
+#endif // !QT_BOOTSTRAPPED
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov)
{
diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h
index f22878de89..a9f30dc275 100644
--- a/src/corelib/global/qoperatingsystemversion.h
+++ b/src/corelib/global/qoperatingsystemversion.h
@@ -1,55 +1,159 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qglobal.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qversionnumber.h>
#ifndef QOPERATINGSYSTEMVERSION_H
#define QOPERATINGSYSTEMVERSION_H
QT_BEGIN_NAMESPACE
+#if 0
+# pragma qt_class(QOperatingSystemVersionBase)
+# pragma qt_class(QOperatingSystemVersion)
+# pragma qt_sync_stop_processing // we have some ifdef'ery fooling syncqt
+#endif
+
class QString;
-class QVersionNumber;
-class Q_CORE_EXPORT QOperatingSystemVersion
+class QOperatingSystemVersionBase
+{
+public:
+ // ### Qt 7: Keep synchronized with the copy in QOperatingSystemVersion until Qt7,
+ // then remove this comment :)
+ enum OSType {
+ Unknown = 0,
+ Windows,
+ MacOS,
+ IOS,
+ TvOS,
+ WatchOS,
+ Android,
+ VisionOS
+ };
+
+ constexpr QOperatingSystemVersionBase(OSType osType,
+ int vmajor, int vminor = -1, int vmicro = -1)
+ : m_os(osType),
+ m_major(vmajor),
+ m_minor(vminor),
+ m_micro(vmicro)
+ { }
+
+ static Q_CORE_EXPORT QOperatingSystemVersionBase current();
+ static Q_CORE_EXPORT QString name(QOperatingSystemVersionBase osversion);
+ static Q_CORE_EXPORT bool isAnyOfType(std::initializer_list<OSType> types, OSType type);
+
+ static constexpr OSType currentType()
+ {
+#if defined(Q_OS_WIN)
+ return Windows;
+#elif defined(Q_OS_MACOS)
+ return MacOS;
+#elif defined(Q_OS_IOS)
+ return IOS;
+#elif defined(Q_OS_TVOS)
+ return TvOS;
+#elif defined(Q_OS_WATCHOS)
+ return WatchOS;
+#elif defined(Q_OS_VISIONOS)
+ return VisionOS;
+#elif defined(Q_OS_ANDROID)
+ return Android;
+#else
+ return Unknown;
+#endif
+ }
+
+ inline QVersionNumber version() const { return QVersionNumber(m_major, m_minor, m_micro); }
+
+ constexpr int majorVersion() const { return m_major; }
+ constexpr int minorVersion() const { return m_minor; }
+ constexpr int microVersion() const { return m_micro; }
+
+ constexpr int segmentCount() const
+ { return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; }
+
+ inline bool isAnyOfType(std::initializer_list<OSType> types) const
+ {
+ return QOperatingSystemVersionBase::isAnyOfType(types, type());
+ }
+ constexpr OSType type() const { return m_os; }
+ inline QString name() const { return name(*this); }
+
+protected:
+ static Q_CORE_EXPORT int compare(QOperatingSystemVersionBase v1,
+ QOperatingSystemVersionBase v2) noexcept;
+
+ friend Qt::partial_ordering compareThreeWay(const QOperatingSystemVersionBase &lhs,
+ const QOperatingSystemVersionBase &rhs) noexcept
+ {
+ if (lhs.type() != rhs.type())
+ return Qt::partial_ordering::unordered;
+ const int res = QOperatingSystemVersionBase::compare(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+#ifdef __cpp_lib_three_way_comparison
+ friend std::partial_ordering
+ operator<=>(QOperatingSystemVersionBase lhs, QOperatingSystemVersionBase rhs) noexcept
+ { return compareThreeWay(lhs, rhs); }
+#else
+ friend bool
+ operator>(QOperatingSystemVersionBase lhs, QOperatingSystemVersionBase rhs) noexcept
+ { return is_gt(compareThreeWay(lhs, rhs)); }
+
+ friend bool
+ operator>=(QOperatingSystemVersionBase lhs, QOperatingSystemVersionBase rhs) noexcept
+ { return is_gteq(compareThreeWay(lhs, rhs)); }
+
+ friend bool
+ operator<(QOperatingSystemVersionBase lhs, QOperatingSystemVersionBase rhs) noexcept
+ { return is_lt(compareThreeWay(lhs, rhs)); }
+
+ friend bool
+ operator<=(QOperatingSystemVersionBase lhs, QOperatingSystemVersionBase rhs) noexcept
+ { return is_lteq(compareThreeWay(lhs, rhs)); }
+#endif
+
+ QOperatingSystemVersionBase() = default;
+private:
+ static QOperatingSystemVersionBase current_impl();
+
+ OSType m_os;
+ int m_major;
+ int m_minor;
+ int m_micro;
+};
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) && !defined(Q_QDOC)
+class QOperatingSystemVersionUnexported : public QOperatingSystemVersionBase
{
public:
+ using QOperatingSystemVersionBase::QOperatingSystemVersionBase;
+ constexpr QOperatingSystemVersionUnexported(QOperatingSystemVersionBase other) noexcept
+ : QOperatingSystemVersionBase(other) {}
+#else
+class QOperatingSystemVersion : public QOperatingSystemVersionBase
+{
+ using QOperatingSystemVersionUnexported = QOperatingSystemVersionBase;
+#endif
+
+ // ### Qt7: Regroup with the rest below
+ static constexpr QOperatingSystemVersionBase MacOSSonoma { QOperatingSystemVersionBase::MacOS, 14, 0 };
+ static constexpr QOperatingSystemVersionBase Android14 { QOperatingSystemVersionBase::Android, 14, 0 };
+ static constexpr QOperatingSystemVersionBase Windows11_23H2 { QOperatingSystemVersionBase::Windows, 10, 0, 22631 };
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) && !defined(Q_QDOC)
+};
+
+class Q_CORE_EXPORT QOperatingSystemVersion : public QOperatingSystemVersionUnexported
+{
+#endif
+public:
+ // ### Qt7: Remove. Keep synchronized with QOperatingSystemVersionBase::OSType until then!
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
enum OSType {
Unknown = 0,
Windows,
@@ -57,9 +161,15 @@ public:
IOS,
TvOS,
WatchOS,
- Android
+ Android,
+ VisionOS
};
+#endif
+ // ### Qt7: remove the branch with static const variables. Then group and
+ // sort the inline ones. Until then, new entries should be added to
+ // QOperatingSystemVersionUnexported.
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
static const QOperatingSystemVersion Windows7;
static const QOperatingSystemVersion Windows8;
static const QOperatingSystemVersion Windows8_1;
@@ -72,6 +182,8 @@ public:
static const QOperatingSystemVersion MacOSHighSierra;
static const QOperatingSystemVersion MacOSMojave;
static const QOperatingSystemVersion MacOSCatalina;
+ static const QOperatingSystemVersion MacOSBigSur;
+ static const QOperatingSystemVersion MacOSMonterey;
static const QOperatingSystemVersion AndroidJellyBean;
static const QOperatingSystemVersion AndroidJellyBean_MR1;
@@ -83,69 +195,105 @@ public:
static const QOperatingSystemVersion AndroidNougat;
static const QOperatingSystemVersion AndroidNougat_MR1;
static const QOperatingSystemVersion AndroidOreo;
+ static const QOperatingSystemVersion AndroidOreo_MR1;
+ static const QOperatingSystemVersion AndroidPie;
+ static const QOperatingSystemVersion Android10;
+ static const QOperatingSystemVersion Android11;
+#else
+ static constexpr QOperatingSystemVersionBase Windows7 { QOperatingSystemVersionBase::Windows, 6, 1 };
+ static constexpr QOperatingSystemVersionBase Windows8 { QOperatingSystemVersionBase::Windows, 6, 2 };
+ static constexpr QOperatingSystemVersionBase Windows8_1 { QOperatingSystemVersionBase::Windows, 6, 3 };
+ static constexpr QOperatingSystemVersionBase Windows10 { QOperatingSystemVersionBase::Windows, 10 };
- Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType,
- int vmajor, int vminor = -1, int vmicro = -1)
- : m_os(osType),
- m_major(qMax(-1, vmajor)),
- m_minor(vmajor < 0 ? -1 : qMax(-1, vminor)),
- m_micro(vmajor < 0 || vminor < 0 ? -1 : qMax(-1, vmicro))
- { }
+ static constexpr QOperatingSystemVersionBase OSXMavericks { QOperatingSystemVersionBase::MacOS, 10, 9 };
+ static constexpr QOperatingSystemVersionBase OSXYosemite { QOperatingSystemVersionBase::MacOS, 10, 10 };
+ static constexpr QOperatingSystemVersionBase OSXElCapitan { QOperatingSystemVersionBase::MacOS, 10, 11 };
+ static constexpr QOperatingSystemVersionBase MacOSSierra { QOperatingSystemVersionBase::MacOS, 10, 12 };
+ static constexpr QOperatingSystemVersionBase MacOSHighSierra { QOperatingSystemVersionBase::MacOS, 10, 13 };
+ static constexpr QOperatingSystemVersionBase MacOSMojave { QOperatingSystemVersionBase::MacOS, 10, 14 };
+ static constexpr QOperatingSystemVersionBase MacOSCatalina { QOperatingSystemVersionBase::MacOS, 10, 15 };
+ static constexpr QOperatingSystemVersionBase MacOSBigSur = { QOperatingSystemVersionBase::MacOS, 11, 0 };
+ static constexpr QOperatingSystemVersionBase MacOSMonterey = { QOperatingSystemVersionBase::MacOS, 12, 0 };
- static QOperatingSystemVersion current();
+ static constexpr QOperatingSystemVersionBase AndroidJellyBean { QOperatingSystemVersionBase::Android, 4, 1 };
+ static constexpr QOperatingSystemVersionBase AndroidJellyBean_MR1 { QOperatingSystemVersionBase::Android, 4, 2 };
+ static constexpr QOperatingSystemVersionBase AndroidJellyBean_MR2 { QOperatingSystemVersionBase::Android, 4, 3 };
+ static constexpr QOperatingSystemVersionBase AndroidKitKat { QOperatingSystemVersionBase::Android, 4, 4 };
+ static constexpr QOperatingSystemVersionBase AndroidLollipop { QOperatingSystemVersionBase::Android, 5, 0 };
+ static constexpr QOperatingSystemVersionBase AndroidLollipop_MR1 { QOperatingSystemVersionBase::Android, 5, 1 };
+ static constexpr QOperatingSystemVersionBase AndroidMarshmallow { QOperatingSystemVersionBase::Android, 6, 0 };
+ static constexpr QOperatingSystemVersionBase AndroidNougat { QOperatingSystemVersionBase::Android, 7, 0 };
+ static constexpr QOperatingSystemVersionBase AndroidNougat_MR1 { QOperatingSystemVersionBase::Android, 7, 1 };
+ static constexpr QOperatingSystemVersionBase AndroidOreo { QOperatingSystemVersionBase::Android, 8, 0 };
+ static constexpr QOperatingSystemVersionBase AndroidOreo_MR1 { QOperatingSystemVersionBase::Android, 8, 1 };
+ static constexpr QOperatingSystemVersionBase AndroidPie { QOperatingSystemVersionBase::Android, 9, 0 };
+ static constexpr QOperatingSystemVersionBase Android10 { QOperatingSystemVersionBase::Android, 10, 0 };
+ static constexpr QOperatingSystemVersionBase Android11 { QOperatingSystemVersionBase::Android, 11, 0 };
+#endif
+
+ static constexpr QOperatingSystemVersionBase Windows10_1809 { QOperatingSystemVersionBase::Windows, 10, 0, 17763 }; // RS5
+ static constexpr QOperatingSystemVersionBase Windows10_1903 { QOperatingSystemVersionBase::Windows, 10, 0, 18362 }; // 19H1
+ static constexpr QOperatingSystemVersionBase Windows10_1909 { QOperatingSystemVersionBase::Windows, 10, 0, 18363 }; // 19H2
+ static constexpr QOperatingSystemVersionBase Windows10_2004 { QOperatingSystemVersionBase::Windows, 10, 0, 19041 }; // 20H1
+ static constexpr QOperatingSystemVersionBase Windows10_20H2 { QOperatingSystemVersionBase::Windows, 10, 0, 19042 };
+ static constexpr QOperatingSystemVersionBase Windows10_21H1 { QOperatingSystemVersionBase::Windows, 10, 0, 19043 };
+ static constexpr QOperatingSystemVersionBase Windows10_21H2 { QOperatingSystemVersionBase::Windows, 10, 0, 19044 };
+ static constexpr QOperatingSystemVersionBase Windows10_22H2 { QOperatingSystemVersionBase::Windows, 10, 0, 19045 };
+ static constexpr QOperatingSystemVersionBase Windows11 { QOperatingSystemVersionBase::Windows, 10, 0, 22000 };
+ static constexpr QOperatingSystemVersionBase Windows11_21H2 = Windows11;
+ static constexpr QOperatingSystemVersionBase Windows11_22H2 { QOperatingSystemVersionBase::Windows, 10, 0, 22621 };
- static Q_DECL_CONSTEXPR OSType currentType()
+ static constexpr QOperatingSystemVersionBase Android12 { QOperatingSystemVersionBase::Android, 12, 0 };
+ static constexpr QOperatingSystemVersionBase Android12L { QOperatingSystemVersionBase::Android, 12, 0 };
+ static constexpr QOperatingSystemVersionBase Android13 { QOperatingSystemVersionBase::Android, 13, 0 };
+
+ static constexpr QOperatingSystemVersionBase MacOSVentura { QOperatingSystemVersionBase::MacOS, 13, 0 };
+
+ constexpr QOperatingSystemVersion(const QOperatingSystemVersionBase &osversion)
+ : QOperatingSystemVersionUnexported(osversion) {}
+
+ constexpr QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1)
+ : QOperatingSystemVersionUnexported(QOperatingSystemVersionBase::OSType(osType), vmajor, vminor,
+ vmicro)
{
-#if defined(Q_OS_WIN)
- return Windows;
-#elif defined(Q_OS_MACOS)
- return MacOS;
-#elif defined(Q_OS_IOS)
- return IOS;
-#elif defined(Q_OS_TVOS)
- return TvOS;
-#elif defined(Q_OS_WATCHOS)
- return WatchOS;
-#elif defined(Q_OS_ANDROID)
- return Android;
-#else
- return Unknown;
-#endif
}
- Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
- Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
- Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
-
- Q_DECL_CONSTEXPR int segmentCount() const
- { return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; }
+#if QT_CORE_REMOVED_SINCE(6, 3) || defined(Q_QDOC)
+ static QOperatingSystemVersion current();
+#endif
- bool isAnyOfType(std::initializer_list<OSType> types) const;
- Q_DECL_CONSTEXPR OSType type() const { return m_os; }
- QString name() const;
+ static constexpr OSType currentType()
+ {
+ return OSType(QOperatingSystemVersionBase::currentType());
+ }
- friend bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
- { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; }
+#if QT_CORE_REMOVED_SINCE(6, 3) || defined(Q_QDOC)
+ QVersionNumber version() const { return QOperatingSystemVersionBase::version(); }
- friend bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
- { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; }
+ constexpr int majorVersion() const { return QOperatingSystemVersionBase::majorVersion(); }
+ constexpr int minorVersion() const { return QOperatingSystemVersionBase::minorVersion(); }
+ constexpr int microVersion() const { return QOperatingSystemVersionBase::microVersion(); }
- friend bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
- { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; }
+ constexpr int segmentCount() const
+ { return QOperatingSystemVersionBase::segmentCount(); }
+#endif // QT_CORE_REMOVED_SINCE(6, 3)
- friend bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
- { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; }
+ constexpr OSType type() const { return OSType(QOperatingSystemVersionBase::type()); }
+ QT7_ONLY(Q_CORE_EXPORT) bool isAnyOfType(std::initializer_list<OSType> types) const;
+#if QT_CORE_REMOVED_SINCE(6, 3) || defined(Q_QDOC)
+ QString name() const;
+#endif
private:
QOperatingSystemVersion() = default;
- OSType m_os;
- int m_major;
- int m_minor;
- int m_micro;
- static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2);
+#if QT_CORE_REMOVED_SINCE(6, 3)
+ // ### Qt 7: Remove. It's only here for backwards compat with previous inline calls.
+ [[maybe_unused]] static int compare(const QOperatingSystemVersion &v1,
+ const QOperatingSystemVersion &v2);
+#endif
};
-Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QOperatingSystemVersion, Q_PRIMITIVE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
diff --git a/src/corelib/global/qoperatingsystemversion_darwin.mm b/src/corelib/global/qoperatingsystemversion_darwin.mm
index d8b927ff5d..f8d9fbd027 100644
--- a/src/corelib/global/qoperatingsystemversion_darwin.mm
+++ b/src/corelib/global/qoperatingsystemversion_darwin.mm
@@ -1,56 +1,57 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qoperatingsystemversion_p.h"
+
#import <Foundation/Foundation.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qversionnumber.h>
+
+#if !defined(QT_BOOTSTRAPPED)
+#include <QtCore/qprocess.h>
+#endif
+
QT_BEGIN_NAMESPACE
-QOperatingSystemVersion QOperatingSystemVersion::current()
+using namespace Qt::StringLiterals;
+
+QOperatingSystemVersionBase QOperatingSystemVersionBase::current_impl()
{
NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion;
- QOperatingSystemVersion v;
- v.m_os = currentType();
- v.m_major = osv.majorVersion;
- v.m_minor = osv.minorVersion;
- v.m_micro = osv.patchVersion;
- return v;
+ QVersionNumber versionNumber(osv.majorVersion, osv.minorVersion, osv.patchVersion);
+
+ if (versionNumber.majorVersion() == 10 && versionNumber.minorVersion() >= 16) {
+ // The process is running in system version compatibility mode,
+ // due to the executable being built against a pre-macOS 11 SDK.
+ // This might happen even if we require a more recent SDK for
+ // building Qt applications, as the Qt 'app' might be a plugin
+ // hosted inside a host that used an earlier SDK. But, since we
+ // require a recent SDK for the Qt app itself, the application
+ // should be prepared for versions numbers beyond 10, and we can
+ // resolve the real version number here.
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(process)
+ QProcess sysctl;
+ QProcessEnvironment nonCompatEnvironment;
+ nonCompatEnvironment.insert("SYSTEM_VERSION_COMPAT"_L1, "0"_L1);
+ sysctl.setProcessEnvironment(nonCompatEnvironment);
+ sysctl.start("/usr/sbin/sysctl"_L1, QStringList() << "-b"_L1 << "kern.osproductversion"_L1);
+ if (sysctl.waitForFinished()) {
+ auto versionString = QString::fromLatin1(sysctl.readAll());
+ auto nonCompatSystemVersion = QVersionNumber::fromString(versionString);
+ if (!nonCompatSystemVersion.isNull())
+ versionNumber = nonCompatSystemVersion;
+ }
+#endif
+ }
+
+ QOperatingSystemVersionBase operatingSystemVersion;
+ operatingSystemVersion.m_os = currentType();
+ operatingSystemVersion.m_major = versionNumber.majorVersion();
+ operatingSystemVersion.m_minor = versionNumber.minorVersion();
+ operatingSystemVersion.m_micro = versionNumber.microVersion();
+
+ return operatingSystemVersion;
}
QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion_p.h b/src/corelib/global/qoperatingsystemversion_p.h
index 6922f4ad54..5d1480d524 100644
--- a/src/corelib/global/qoperatingsystemversion_p.h
+++ b/src/corelib/global/qoperatingsystemversion_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPERATINGSYSTEMVERSION_P_H
#define QOPERATINGSYSTEMVERSION_P_H
@@ -52,6 +16,7 @@
//
#include "qoperatingsystemversion.h"
+#include "private/qglobal_p.h"
#ifdef Q_OS_WIN
#include <qt_windows.h>
diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp
index eb58b60788..a209fb17b6 100644
--- a/src/corelib/global/qoperatingsystemversion_win.cpp
+++ b/src/corelib/global/qoperatingsystemversion_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qoperatingsystemversion_win_p.h"
@@ -50,10 +14,7 @@ static inline OSVERSIONINFOEX determineWinOsVersion()
{
OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
-#define GetProcAddressA GetProcAddress
-#define pGetModuleHandle GetModuleHandleW
-
- HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
+ HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (Q_UNLIKELY(!ntdll))
return result;
@@ -63,7 +24,7 @@ static inline OSVERSIONINFOEX determineWinOsVersion()
// because linking to it at load time will not pass the Windows App Certification Kit
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
- reinterpret_cast<QFunctionPointer>(GetProcAddressA(ntdll, "RtlGetVersion")));
+ reinterpret_cast<QFunctionPointer>(GetProcAddress(ntdll, "RtlGetVersion")));
if (Q_UNLIKELY(!pRtlGetVersion))
return result;
@@ -90,25 +51,18 @@ OSVERSIONINFOEX qWindowsVersionInfo()
result.wServicePackMinor = 0;
const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE");
- if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 1;
- } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 2;
- } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 3;
- } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") {
+ if (winVerOverride == "WINDOWS10" || winVerOverride == "2016"
+ || winVerOverride == "2019" || winVerOverride == "2022") {
+ result.dwMajorVersion = 10;
+ } else if (winVerOverride == "WINDOWS11") {
result.dwMajorVersion = 10;
+ result.dwBuildNumber = 22000;
} else {
return realResult;
}
- if (winVerOverride == "2008_R2"
- || winVerOverride == "2012"
- || winVerOverride == "2012_R2"
- || winVerOverride == "2016") {
+ if (winVerOverride == "2016" || winVerOverride == "2019"
+ || winVerOverride == "2022") {
// If the current host OS is a domain controller and the override OS
// is also a server type OS, preserve that information
if (result.wProductType == VER_NT_WORKSTATION)
@@ -123,9 +77,9 @@ OSVERSIONINFOEX qWindowsVersionInfo()
return realResult;
}
-QOperatingSystemVersion QOperatingSystemVersion::current()
+QOperatingSystemVersionBase QOperatingSystemVersionBase::current_impl()
{
- QOperatingSystemVersion v;
+ QOperatingSystemVersionBase v;
v.m_os = currentType();
const OSVERSIONINFOEX osv = qWindowsVersionInfo();
v.m_major = osv.dwMajorVersion;
diff --git a/src/corelib/global/qoperatingsystemversion_win_p.h b/src/corelib/global/qoperatingsystemversion_win_p.h
index 446bd286fc..92fc0e12f3 100644
--- a/src/corelib/global/qoperatingsystemversion_win_p.h
+++ b/src/corelib/global/qoperatingsystemversion_win_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPERATINGSYSTEMVERSION_WIN_P_H
#define QOPERATINGSYSTEMVERSION_WIN_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/global/qoverload.h b/src/corelib/global/qoverload.h
new file mode 100644
index 0000000000..9376e1e246
--- /dev/null
+++ b/src/corelib/global/qoverload.h
@@ -0,0 +1,80 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QOVERLOAD_H
+#define QOVERLOAD_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#if 0
+#pragma qt_class(QOverload)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_QDOC
+// Just for documentation generation
+template<typename T>
+auto qOverload(T functionPointer);
+template<typename T>
+auto qConstOverload(T memberFunctionPointer);
+template<typename T>
+auto qNonConstOverload(T memberFunctionPointer);
+#else
+template <typename... Args>
+struct QNonConstOverload
+{
+ template <typename R, typename T>
+ constexpr auto operator()(R (T::*ptr)(Args...)) const noexcept -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R, typename T>
+ static constexpr auto of(R (T::*ptr)(Args...)) noexcept -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args>
+struct QConstOverload
+{
+ template <typename R, typename T>
+ constexpr auto operator()(R (T::*ptr)(Args...) const) const noexcept -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R, typename T>
+ static constexpr auto of(R (T::*ptr)(Args...) const) noexcept -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args>
+struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
+{
+ using QConstOverload<Args...>::of;
+ using QConstOverload<Args...>::operator();
+ using QNonConstOverload<Args...>::of;
+ using QNonConstOverload<Args...>::operator();
+
+ template <typename R>
+ constexpr auto operator()(R (*ptr)(Args...)) const noexcept -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R>
+ static constexpr auto of(R (*ptr)(Args...)) noexcept -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args> constexpr inline QOverload<Args...> qOverload = {};
+template <typename... Args> constexpr inline QConstOverload<Args...> qConstOverload = {};
+template <typename... Args> constexpr inline QNonConstOverload<Args...> qNonConstOverload = {};
+
+#endif // Q_QDOC
+
+#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
+#define QT_VA_ARGS_EXPAND(...) __VA_ARGS__ // Needed for MSVC
+#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_EXPAND(QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+#define QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##_##ARGC
+#define QT_OVERLOADED_MACRO_IMP(MACRO, ARGC) QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC)
+#define QT_OVERLOADED_MACRO(MACRO, ...) QT_VA_ARGS_EXPAND(QT_OVERLOADED_MACRO_IMP(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__))
+
+QT_END_NAMESPACE
+
+#endif /* QOVERLOAD_H */
diff --git a/src/corelib/global/qoverload.qdoc b/src/corelib/global/qoverload.qdoc
new file mode 100644
index 0000000000..f11e266483
--- /dev/null
+++ b/src/corelib/global/qoverload.qdoc
@@ -0,0 +1,43 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*! \fn template <typename T> auto qOverload(T functionPointer)
+ \relates <QOverload>
+ \since 5.7
+
+ Returns a pointer to an overloaded function. The template
+ parameter is the list of the argument types of the function.
+ \a functionPointer is the pointer to the (member) function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 52
+
+ If a member function is also const-overloaded \l qConstOverload and
+ \l qNonConstOverload need to be used.
+
+ \sa qConstOverload(), qNonConstOverload(), {Differences between String-Based
+ and Functor-Based Connections}
+*/
+
+/*! \fn template <typename T> auto qConstOverload(T memberFunctionPointer)
+ \relates <QOverload>
+ \since 5.7
+
+ Returns the \a memberFunctionPointer pointer to a constant member function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 54
+
+ \sa qOverload, qNonConstOverload, {Differences between String-Based
+ and Functor-Based Connections}
+*/
+
+/*! \fn template <typename T> auto qNonConstOverload(T memberFunctionPointer)
+ \relates <QOverload>
+ \since 5.7
+
+ Returns the \a memberFunctionPointer pointer to a non-constant member function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 54
+
+ \sa qOverload, qNonConstOverload, {Differences between String-Based
+ and Functor-Based Connections}
+*/
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h
index f7bca43345..f7298bbb86 100644
--- a/src/corelib/global/qprocessordetection.h
+++ b/src/corelib/global/qprocessordetection.h
@@ -1,45 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QGLOBAL_H
-# include <QtCore/qglobal.h>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+#if 0
+#pragma qt_class(QtProcessorDetection)
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
#endif
#ifndef QPROCESSORDETECTION_H
@@ -84,8 +51,8 @@
Alpha is bi-endian, use endianness auto-detection implemented below.
*/
-// #elif defined(__alpha__) || defined(_M_ALPHA)
-// # define Q_PROCESSOR_ALPHA
+#if defined(__alpha__) || defined(_M_ALPHA)
+# define Q_PROCESSOR_ALPHA
// Q_BYTE_ORDER not defined, use endianness auto-detection
/*
@@ -94,7 +61,7 @@
ARM is bi-endian, detect using __ARMEL__ or __ARMEB__, falling back to
auto-detection implemented below.
*/
-#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
+#elif defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
# if defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64)
# define Q_PROCESSOR_ARM_64
# define Q_PROCESSOR_WORDSIZE 8
@@ -176,6 +143,15 @@
// # define Q_BYTE_ORDER Q_LITTLE_ENDIAN
/*
+ PA-RISC family, no revisions or variants
+
+ PA-RISC is big-endian.
+*/
+#elif defined(__hppa__)
+# define Q_PROCESSOR_HPPA
+# define Q_BYTE_ORDER Q_BIG_ENDIAN
+
+/*
X86 family, known variants: 32- and 64-bit
X86 is little-endian.
@@ -224,6 +200,29 @@
// Q_BYTE_ORDER not defined, use endianness auto-detection
/*
+ LoongArch family, known variants: 32- and 64-bit
+
+ LoongArch is little-endian.
+*/
+#elif defined(__loongarch__)
+# define Q_PROCESSOR_LOONGARCH
+# if __loongarch_grlen == 64
+# define Q_PROCESSOR_LOONGARCH_64
+# else
+# define Q_PROCESSOR_LOONGARCH_32
+# endif
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+
+/*
+ Motorola 68000 family, no revisions or variants
+
+ M68K is big-endian.
+*/
+#elif defined(__m68k__)
+# define Q_PROCESSOR_M68K
+# define Q_BYTE_ORDER Q_BIG_ENDIAN
+
+/*
MIPS family, known revisions: I, II, III, IV, 32, 64
MIPS is bi-endian, use endianness auto-detection implemented below.
@@ -327,7 +326,7 @@
*/
#elif defined(__sparc__)
# define Q_PROCESSOR_SPARC
-# if defined(__sparc_v9__)
+# if defined(__sparc_v9__) || defined(__sparcv9)
# define Q_PROCESSOR_SPARC_V9
# endif
# if defined(__sparc64__)
@@ -340,6 +339,12 @@
# define Q_PROCESSOR_WASM
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# define Q_PROCESSOR_WORDSIZE 8
+#ifdef QT_COMPILER_SUPPORTS_SSE2
+# define Q_PROCESSOR_X86 6 // enables SIMD support
+# define Q_PROCESSOR_X86_64 // wasm64
+# define Q_PROCESSOR_WASM_64
+#endif
+
#endif
/*
diff --git a/src/corelib/global/qprocessordetection.qdoc b/src/corelib/global/qprocessordetection.qdoc
new file mode 100644
index 0000000000..e6605fb9b9
--- /dev/null
+++ b/src/corelib/global/qprocessordetection.qdoc
@@ -0,0 +1,448 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \headerfile <QtProcessorDetection>
+ \inmodule QtCore
+ \title Architecture-specific Macro Definitions
+ \ingroup funclists
+
+ \brief The <QtProcessorDetection> header file includes various
+ architecture-specific macros.
+
+ The <QtProcessorDetection> header file declares a range of macros
+ (Q_PROCESSOR_*) that are defined if the application is compiled for
+ specified processor architectures. For example, the Q_PROCESSOR_X86 macro is
+ defined if the application is compiled for x86 processors.
+
+ The purpose of these macros is to enable programmers to add
+ architecture-specific code to their application.
+*/
+
+/*!
+ \macro Q_PROCESSOR_ALPHA
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for Alpha processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_ARM
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for ARM processors. Qt currently
+ supports three optional ARM revisions: \l Q_PROCESSOR_ARM_V5, \l
+ Q_PROCESSOR_ARM_V6, and \l Q_PROCESSOR_ARM_V7.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_ARM_V5
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for ARMv5 processors. The \l
+ Q_PROCESSOR_ARM macro is also defined when Q_PROCESSOR_ARM_V5 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_ARM_V6
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for ARMv6 processors. The \l
+ Q_PROCESSOR_ARM and \l Q_PROCESSOR_ARM_V5 macros are also defined when
+ Q_PROCESSOR_ARM_V6 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_ARM_V7
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for ARMv7 processors. The \l
+ Q_PROCESSOR_ARM, \l Q_PROCESSOR_ARM_V5, and \l Q_PROCESSOR_ARM_V6 macros
+ are also defined when Q_PROCESSOR_ARM_V7 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_AVR32
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for AVR32 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_BLACKFIN
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for Blackfin processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_HPPA
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for PA-RISC processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_IA64
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for IA-64 processors. This includes
+ all Itanium and Itanium 2 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_LOONGARCH
+ \relates <QtProcessorDetection>
+ \since 6.5
+
+ Defined if the application is compiled for LoongArch processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_LOONGARCH_32
+ \relates <QtProcessorDetection>
+ \since 6.5
+
+ Defined if the application is compiled for 32-bit LoongArch processors.
+ The \l Q_PROCESSOR_LOONGARCH macro is also defined when
+ Q_PROCESSOR_LOONGARCH_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_LOONGARCH_64
+ \relates <QtProcessorDetection>
+ \since 6.5
+
+ Defined if the application is compiled for 64-bit LoongArch processors.
+ The \l Q_PROCESSOR_LOONGARCH macro is also defined when
+ Q_PROCESSOR_LOONGARCH_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_M68K
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for Motorola 68000 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_MIPS
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS processors. Qt currently
+ supports seven MIPS revisions: \l Q_PROCESSOR_MIPS_I, \l
+ Q_PROCESSOR_MIPS_II, \l Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, \l
+ Q_PROCESSOR_MIPS_V, \l Q_PROCESSOR_MIPS_32, and \l Q_PROCESSOR_MIPS_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_I
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS-I processors. The \l
+ Q_PROCESSOR_MIPS macro is also defined when Q_PROCESSOR_MIPS_I is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_II
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS-II processors. The \l
+ Q_PROCESSOR_MIPS and \l Q_PROCESSOR_MIPS_I macros are also defined when
+ Q_PROCESSOR_MIPS_II is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_32
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS32 processors. The \l
+ Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
+ are also defined when Q_PROCESSOR_MIPS_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_III
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS-III processors. The \l
+ Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
+ are also defined when Q_PROCESSOR_MIPS_III is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_IV
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS-IV processors. The \l
+ Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, and \l
+ Q_PROCESSOR_MIPS_III macros are also defined when Q_PROCESSOR_MIPS_IV is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_V
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS-V processors. The \l
+ Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
+ Q_PROCESSOR_MIPS_III, and \l Q_PROCESSOR_MIPS_IV macros are also defined
+ when Q_PROCESSOR_MIPS_V is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_MIPS_64
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for MIPS64 processors. The \l
+ Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
+ Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, and \l Q_PROCESSOR_MIPS_V
+ macros are also defined when Q_PROCESSOR_MIPS_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_POWER
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for POWER processors. Qt currently
+ supports two Power variants: \l Q_PROCESSOR_POWER_32 and \l
+ Q_PROCESSOR_POWER_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_POWER_32
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for 32-bit Power processors. The \l
+ Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_32 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_POWER_64
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for 64-bit Power processors. The \l
+ Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_64 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_RISCV
+ \relates <QtProcessorDetection>
+ \since 5.13
+
+ Defined if the application is compiled for RISC-V processors. Qt currently
+ supports two RISC-V variants: \l Q_PROCESSOR_RISCV_32 and \l
+ Q_PROCESSOR_RISCV_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_RISCV_32
+ \relates <QtProcessorDetection>
+ \since 5.13
+
+ Defined if the application is compiled for 32-bit RISC-V processors. The \l
+ Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_32 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_RISCV_64
+ \relates <QtProcessorDetection>
+ \since 5.13
+
+ Defined if the application is compiled for 64-bit RISC-V processors. The \l
+ Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_64 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_S390
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for S/390 processors. Qt supports
+ one optional variant of S/390: Q_PROCESSOR_S390_X.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_S390_X
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for S/390x processors. The \l
+ Q_PROCESSOR_S390 macro is also defined when Q_PROCESSOR_S390_X is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_SH
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for SuperH processors. Qt currently
+ supports one SuperH revision: \l Q_PROCESSOR_SH_4A.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_SH_4A
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for SuperH 4A processors. The \l
+ Q_PROCESSOR_SH macro is also defined when Q_PROCESSOR_SH_4A is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_SPARC
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for SPARC processors. Qt currently
+ supports one optional SPARC revision: \l Q_PROCESSOR_SPARC_V9.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_SPARC_V9
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for SPARC V9 processors. The \l
+ Q_PROCESSOR_SPARC macro is also defined when Q_PROCESSOR_SPARC_V9 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_X86
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for x86 processors. Qt currently
+ supports two x86 variants: \l Q_PROCESSOR_X86_32 and \l Q_PROCESSOR_X86_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_X86_32
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for 32-bit x86 processors. This
+ includes all i386, i486, i586, and i686 processors. The \l Q_PROCESSOR_X86
+ macro is also defined when Q_PROCESSOR_X86_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+/*!
+ \macro Q_PROCESSOR_X86_64
+ \relates <QtProcessorDetection>
+
+ Defined if the application is compiled for 64-bit x86 processors. This
+ includes all AMD64, Intel 64, and other x86_64/x64 processors. The \l
+ Q_PROCESSOR_X86 macro is also defined when Q_PROCESSOR_X86_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_BYTE_ORDER
+ \relates <QtProcessorDetection>
+
+ This macro can be used to determine the byte order your system
+ uses for storing data in memory. i.e., whether your system is
+ little-endian or big-endian. It is set by Qt to one of the macros
+ Q_LITTLE_ENDIAN or Q_BIG_ENDIAN. You normally won't need to worry
+ about endian-ness, but you might, for example if you need to know
+ which byte of an integer or UTF-16 character is stored in the
+ lowest address. Endian-ness is important in networking, where
+ computers with different values for Q_BYTE_ORDER must pass data
+ back and forth.
+
+ Use this macro as in the following examples.
+
+ \snippet code/src_corelib_global_qglobal.cpp 40
+
+ \sa Q_BIG_ENDIAN, Q_LITTLE_ENDIAN
+*/
+
+/*!
+ \macro Q_LITTLE_ENDIAN
+ \relates <QtProcessorDetection>
+
+ This macro represents a value you can compare to the macro
+ Q_BYTE_ORDER to determine the endian-ness of your system. In a
+ little-endian system, the least significant byte is stored at the
+ lowest address. The other bytes follow in increasing order of
+ significance.
+
+ \snippet code/src_corelib_global_qglobal.cpp 41
+
+ \sa Q_BYTE_ORDER, Q_BIG_ENDIAN
+*/
+
+/*!
+ \macro Q_BIG_ENDIAN
+ \relates <QtProcessorDetection>
+
+ This macro represents a value you can compare to the macro
+ Q_BYTE_ORDER to determine the endian-ness of your system. In a
+ big-endian system, the most significant byte is stored at the
+ lowest address. The other bytes follow in decreasing order of
+ significance.
+
+ \snippet code/src_corelib_global_qglobal.cpp 42
+
+ \sa Q_BYTE_ORDER, Q_LITTLE_ENDIAN
+*/
+
+/*!
+ \macro QT_POINTER_SIZE
+ \relates <QtProcessorDetection>
+
+ Expands to the size of a pointer in bytes (4 or 8). This is
+ equivalent to \c sizeof(void *) but can be used in a preprocessor
+ directive.
+*/
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 1ff481762c..fd742898f8 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -1,60 +1,27 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 Intel Corporation.
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// for rand_s
#define _CRT_RAND_S
#include "qrandom.h"
#include "qrandom_p.h"
-#include <qobjectdefs.h>
+#include <qendian.h>
#include <qmutex.h>
-#include <qthreadstorage.h>
+#include <qobjectdefs.h>
#include <errno.h>
-#if !QT_CONFIG(getentropy) && (!defined(Q_OS_BSD4) || defined(__GLIBC__)) && !defined(Q_OS_WIN)
+#if QT_CONFIG(getauxval)
+# include <sys/auxv.h>
+#endif
+
+#if QT_CONFIG(getentropy) && __has_include(<sys/random.h>)
+# include <sys/random.h>
+#elif !QT_CONFIG(getentropy) && (!defined(Q_OS_BSD4) || defined(__GLIBC__)) && !defined(Q_OS_WIN)
# include "qdeadlinetimer.h"
# include "qhashfunctions.h"
-
-# if QT_CONFIG(getauxval)
-# include <sys/auxv.h>
-# endif
#endif // !QT_CONFIG(getentropy)
#ifdef Q_OS_UNIX
@@ -72,10 +39,6 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando
}
#endif
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
-# include <private/qjni_p.h>
-#endif
-
// This file is too low-level for regular Q_ASSERT (the logging framework may
// recurse back), so use regular assert()
#undef NDEBUG
@@ -95,6 +58,10 @@ enum {
FillBufferNoexcept = true
};
+#if defined(QT_BUILD_INTERNAL)
+QBasicAtomicInteger<uint> qt_randomdevice_control = Q_BASIC_ATOMIC_INITIALIZER(0U);
+#endif
+
struct QRandomGenerator::SystemGenerator
{
#if QT_CONFIG(getentropy)
@@ -155,7 +122,7 @@ struct QRandomGenerator::SystemGenerator
qt_safe_close(fd);
}
- Q_DECL_CONSTEXPR SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {}
+ constexpr SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {}
qsizetype fillBuffer(void *buffer, qsizetype count)
{
@@ -168,7 +135,7 @@ struct QRandomGenerator::SystemGenerator
}
#elif defined(Q_OS_WIN)
- qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
+ static qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
{
auto RtlGenRandom = SystemFunction036;
return RtlGenRandom(buffer, ULONG(count)) ? count: 0;
@@ -181,7 +148,8 @@ struct QRandomGenerator::SystemGenerator
// For std::mersenne_twister_engine implementations that use something
// other than quint32 (unsigned int) to fill their buffers.
- template <typename T> void generate(T *begin, T *end)
+ template<typename T>
+ void generate(T *begin, T *end)
{
static_assert(sizeof(T) >= sizeof(quint32));
if (sizeof(T) == sizeof(quint32)) {
@@ -225,10 +193,10 @@ static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
arc4random_buf(ptr, left * sizeof(*ptr));
}
#else
-static QBasicAtomicInteger<unsigned> seed = Q_BASIC_ATOMIC_INITIALIZER(0U);
+Q_CONSTINIT static QBasicAtomicInteger<unsigned> seed = Q_BASIC_ATOMIC_INITIALIZER(0U);
static void fallback_update_seed(unsigned value)
{
- // Update the seed to be used for the fallback mechansim, if we need to.
+ // Update the seed to be used for the fallback mechanism, if we need to.
// We can't use QtPrivate::QHashCombine here because that is not an atomic
// operation. A simple XOR will have to do then.
seed.fetchAndXorRelaxed(value);
@@ -349,41 +317,34 @@ struct QRandomGenerator::SystemAndGlobalGenerators
// the state in case another thread tries to lock the mutex. It's not
// a common scenario, but since sizeof(QRandomGenerator) >= 2560, the
// overhead is actually acceptable.
- // 2) We use both alignas and std::aligned_storage<..., 64> because
- // some implementations of std::aligned_storage can't align to more
- // than a primitive type's alignment.
+ // 2) We use both alignas(T) and alignas(64) because some implementations
+ // can't align to more than a primitive type's alignment.
// 3) We don't store the entire system QRandomGenerator, only the space
// used by the QRandomGenerator::type member. This is fine because we
// (ab)use the common initial sequence exclusion to aliasing rules.
QBasicMutex globalPRNGMutex;
struct ShortenedSystem { uint type; } system_;
SystemGenerator sys;
- alignas(64) std::aligned_storage<sizeof(QRandomGenerator64), 64>::type global_;
+ alignas(64) struct {
+ alignas(QRandomGenerator64) uchar data[sizeof(QRandomGenerator64)];
+ } global_;
-#ifdef Q_COMPILER_CONSTEXPR
constexpr SystemAndGlobalGenerators()
: globalPRNGMutex{}, system_{0}, sys{}, global_{}
{}
-#endif
void confirmLiteral()
{
-#if defined(Q_COMPILER_CONSTEXPR) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
- // Currently fails to compile with MSVC 2017, saying QBasicMutex is not
- // a literal type. Disassembly with MSVC 2013 and 2015 shows it is
- // actually a literal; MSVC 2017 has a bug relating to this, so we're
- // withhold judgement for now. Integrity's compiler is unable to
- // guarantee g's alignment for some reason.
-
+#if !defined(Q_OS_INTEGRITY)
+ // Integrity's compiler is unable to guarantee g's alignment for some reason.
constexpr SystemAndGlobalGenerators g = {};
Q_UNUSED(g);
- static_assert(std::is_literal_type<SystemAndGlobalGenerators>::value);
#endif
}
static SystemAndGlobalGenerators *self()
{
- static SystemAndGlobalGenerators g;
+ Q_CONSTINIT static SystemAndGlobalGenerators g;
static_assert(sizeof(g) > sizeof(QRandomGenerator64));
return &g;
}
@@ -414,9 +375,11 @@ struct QRandomGenerator::SystemAndGlobalGenerators
new (&rng->storage.engine()) RandomEngine(self()->sys);
}
- struct PRNGLocker {
+ struct PRNGLocker
+ {
+ Q_DISABLE_COPY_MOVE(PRNGLocker)
const bool locked;
- PRNGLocker(const QRandomGenerator *that)
+ Q_NODISCARD_CTOR explicit PRNGLocker(const QRandomGenerator *that)
: locked(that == globalNoInit())
{
if (locked)
@@ -595,7 +558,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
\snippet code/src_corelib_global_qrandom.cpp 3
- \sa QRandomGenerator64, qrand()
+ \sa QRandomGenerator64
*/
/*!
@@ -675,7 +638,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
position in the deterministic sequence as the \a other object was. Both
objects will generate the same sequence from this point on.
- For that reason, it is not adviseable to create a copy of
+ For that reason, it is not advisable to create a copy of
QRandomGenerator::global(). If one needs an exclusive deterministic
generator, consider instead using securelySeeded() to obtain a new object
that shares no relationship with the QRandomGenerator::global().
@@ -685,18 +648,17 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
\fn bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
\relates QRandomGenerator
- Returns true if the two the two engines \a rng1 and \a rng2 are at the same
+ Returns true if the two engines \a rng1 and \a rng2 are at the same
state or if they are both reading from the operating system facilities,
false otherwise.
*/
/*!
- \fn bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
- \relates QRandomGenerator
+ \fn bool QRandomGenerator::operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
- Returns true if the two the two engines \a rng1 and \a rng2 are at
+ Returns \c true if the two engines \a rng1 and \a rng2 are at
different states or if one of them is reading from the operating system
- facilities and the other is not, false otherwise.
+ facilities and the other is not, \c false otherwise.
*/
/*!
@@ -804,7 +766,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
*/
/*!
- \fn template <typename UInt> void QRandomGenerator::fillRange(UInt *buffer, qsizetype count)
+ \fn template <typename UInt, QRandomGenerator::IfValidUInt<UInt> = true> void QRandomGenerator::fillRange(UInt *buffer, qsizetype count)
Generates \a count 32- or 64-bit quantities (depending on the type \c UInt)
and stores them in the buffer pointed by \a buffer. This is the most
@@ -820,7 +782,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
*/
/*!
- \fn template <typename UInt, size_t N> void QRandomGenerator::fillRange(UInt (&buffer)[N])
+ \fn template <typename UInt, size_t N, QRandomGenerator::IfValidUInt<UInt> = true> void QRandomGenerator::fillRange(UInt (&buffer)[N])
Generates \c N 32- or 64-bit quantities (depending on the type \c UInt) and
stores them in the \a buffer array. This is the most efficient way to
@@ -876,7 +838,8 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
\a highest (exclusive). The same result may also be obtained by using
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution}
with parameters 0 and \c{highest - 1}. That class can also be used to obtain
- quantities larger than 32 bits.
+ quantities larger than 32 bits; for 64 bits, the 64-bit bounded() overload
+ can be used too.
For example, to obtain a value between 0 and 255 (inclusive), one would write:
@@ -905,6 +868,45 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
*/
/*!
+ \fn quint64 QRandomGenerator::bounded(quint64 highest)
+ \overload
+
+ Generates one random 64-bit quantity in the range between 0 (inclusive) and
+ \a highest (exclusive). The same result may also be obtained by using
+ \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution<quint64>}
+ with parameters 0 and \c{highest - 1}.
+
+ Note that this function cannot be used to obtain values in the full 64-bit
+ range of \c{quint64}. Instead, use generate64().
+
+ \note This function is implemented as a loop, which depends on the random
+ value obtained. On the long run, on average it should loop just under 2
+ times, but if the random generator is defective, this function may take
+ considerably longer to execute.
+
+ \sa generate(), generate64(), generateDouble()
+ */
+
+/*!
+ \fn qint64 QRandomGenerator::bounded(qint64 highest)
+ \overload
+
+ Generates one random 64-bit quantity in the range between 0 (inclusive) and
+ \a highest (exclusive). \a highest must be positive.
+
+ Note that this function cannot be used to obtain values in the full 64-bit
+ range of \c{qint64}. Instead, use generate64() and cast to qint64 or instead
+ use the unsigned version of this function.
+
+ \note This function is implemented as a loop, which depends on the random
+ value obtained. On the long run, on average it should loop just under 2
+ times, but if the random generator is defective, this function may take
+ considerably longer to execute.
+
+ \sa generate(), generate64(), generateDouble()
+ */
+
+/*!
\fn quint32 QRandomGenerator::bounded(quint32 lowest, quint32 highest)
\overload
@@ -943,6 +945,60 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
*/
/*!
+ \fn quint64 QRandomGenerator::bounded(quint64 lowest, quint64 highest)
+ \overload
+
+ Generates one random 64-bit quantity in the range between \a lowest
+ (inclusive) and \a highest (exclusive). The \a highest parameter must be
+ greater than \a lowest.
+
+ The same result may also be obtained by using
+ \l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{\c std::uniform_int_distribution<quint64>}
+ with parameters \a lowest and \c{\a highest - 1}.
+
+ Note that this function cannot be used to obtain values in the full 64-bit
+ range of \c{quint64}. Instead, use generate64().
+
+ \note This function is implemented as a loop, which depends on the random
+ value obtained. On the long run, on average it should loop just under 2
+ times, but if the random generator is defective, this function may take
+ considerably longer to execute.
+
+ \sa generate(), generate64(), generateDouble()
+ */
+
+/*!
+ \fn qint64 QRandomGenerator::bounded(qint64 lowest, qint64 highest)
+ \overload
+
+ Generates one random 64-bit quantity in the range between \a lowest
+ (inclusive) and \a highest (exclusive), both of which may be negative, but
+ \a highest must be greater than \a lowest.
+
+ Note that this function cannot be used to obtain values in the full 64-bit
+ range of \c{qint64}. Instead, use generate64() and cast to qint64.
+
+ \note This function is implemented as a loop, which depends on the random
+ value obtained. On the long run, on average it should loop just under 2
+ times, but if the random generator is defective, this function may take
+ considerably longer to execute.
+
+ \sa generate(), generate64(), generateDouble()
+ */
+
+/*!
+ \fn qint64 QRandomGenerator::bounded(int lowest, qint64 highest)
+ \fn qint64 QRandomGenerator::bounded(qint64 lowest, int highest)
+ \fn quint64 QRandomGenerator::bounded(unsigned lowest, quint64 highest)
+ \fn quint64 QRandomGenerator::bounded(quint64 lowest, unsigned highest)
+ \overload
+
+ This function exists to help with overload resolution when the types of the
+ parameters don't exactly match. They will promote the smaller type to the
+ type of the larger one and call the correct overload.
+ */
+
+/*!
\fn QRandomGenerator *QRandomGenerator::system()
\threadsafe
@@ -1057,7 +1113,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
\sa QRandomGenerator::generate(), QRandomGenerator::generate64()
*/
-Q_DECL_CONSTEXPR QRandomGenerator::Storage::Storage()
+constexpr QRandomGenerator::Storage::Storage()
: dummy(0)
{
// nothing
@@ -1177,127 +1233,82 @@ bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
/*!
\internal
- Fills the range pointed by \a buffer and \a bufferEnd with 32-bit random
- values. The buffer must be correctly aligned.
+ Fills the range pointed by \a buffer with \a count 32-bit random values.
+ The buffer must be correctly aligned.
+
+ Returns the value of the first two 32-bit entries as a \c{quint64}.
*/
-void QRandomGenerator::_fillRange(void *buffer, void *bufferEnd)
+quint64 QRandomGenerator::_fillRange(void *buffer, qptrdiff count)
{
// Verify that the pointers are properly aligned for 32-bit
Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0);
- Q_ASSERT(quintptr(bufferEnd) % sizeof(quint32) == 0);
- quint32 *begin = static_cast<quint32 *>(buffer);
- quint32 *end = static_cast<quint32 *>(bufferEnd);
-
- if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (UseSystemRNG|SetRandomData)))
- return SystemGenerator::self().generate(begin, end);
-
- SystemAndGlobalGenerators::PRNGLocker lock(this);
- std::generate(begin, end, [this]() { return storage.engine()(); });
-}
-
-namespace {
-struct QRandEngine
-{
- std::minstd_rand engine;
- QRandEngine() : engine(1) {}
-
- int generate()
- {
- std::minstd_rand::result_type v = engine();
- if (std::numeric_limits<int>::max() != RAND_MAX)
- v %= uint(RAND_MAX) + 1;
-
- return int(v);
+ Q_ASSERT(count >= 0);
+ Q_ASSERT(buffer || count <= 2);
+
+ quint64 dummy;
+ quint32 *begin = static_cast<quint32 *>(buffer ? buffer : &dummy);
+ quint32 *end = begin + count;
+
+ if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (UseSystemRNG|SetRandomData))) {
+ SystemGenerator::self().generate(begin, end);
+ } else {
+ SystemAndGlobalGenerators::PRNGLocker lock(this);
+ std::generate(begin, end, [this]() { return storage.engine()(); });
}
- void seed(std::minstd_rand::result_type q)
- {
- engine.seed(q);
- }
-};
+ if (end - begin == 1)
+ return *begin;
+ return begin[0] | (quint64(begin[1]) << 32);
}
-#if defined(Q_OS_WIN)
-// On Windows srand() and rand() already use Thread-Local-Storage
-// to store the seed between calls
-static inline QRandEngine *randTLS()
+// helper function to call fillBuffer, since we need something to be
+// argument-dependent
+template <typename Generator, typename FillBufferType, typename T>
+static qsizetype callFillBuffer(FillBufferType f, T *v)
{
- return nullptr;
-}
-#elif defined(Q_COMPILER_THREAD_LOCAL)
-static inline QRandEngine *randTLS()
-{
- thread_local QRandEngine r;
- return &r;
-}
-#else
-Q_GLOBAL_STATIC(QThreadStorage<QRandEngine>, g_randTLS)
-static inline QRandEngine *randTLS()
-{
- auto tls = g_randTLS();
- if (!tls)
- return nullptr;
- return &tls->localData();
-
+ if constexpr (std::is_member_function_pointer_v<FillBufferType>) {
+ // member function, need an object
+ return (Generator::self().*f)(v, sizeof(*v));
+ } else {
+ // static, call directly
+ return f(v, sizeof(*v));
+ }
}
-#endif
/*!
- \relates <QtGlobal>
- \deprecated
- \since 4.2
-
- Thread-safe version of the standard C++ \c srand() function.
-
- Sets the argument \a seed to be used to generate a new random number sequence of
- pseudo random integers to be returned by qrand().
-
- The sequence of random numbers generated is deterministic per thread. For example,
- if two threads call qsrand(1) and subsequently call qrand(), the threads will get
- the same random number sequence.
+ \internal
- \note This function is deprecated. In new applications, use
- QRandomGenerator instead.
+ Returns an initial random value (useful for QHash's global seed). This
+ function attempts to use OS-provided random values to avoid initializing
+ QRandomGenerator::system() and qsimd.cpp.
- \sa qrand(), QRandomGenerator
-*/
-void qsrand(uint seed)
+ Note: on some systems, this functionn may rerturn the same value every time
+ it is called.
+ */
+QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept
{
- auto prng = randTLS();
- if (prng)
- prng->seed(seed);
- else
- srand(seed);
-}
-
-/*!
- \relates <QtGlobal>
- \deprecated
- \since 4.2
-
- Thread-safe version of the standard C++ \c rand() function.
+#if QT_CONFIG(getauxval) && defined(AT_RANDOM)
+ auto at_random_ptr = reinterpret_cast<size_t *>(getauxval(AT_RANDOM));
+ if (at_random_ptr)
+ return qFromUnaligned<QRandomGenerator::InitialRandomData>(at_random_ptr);
+#endif
- Returns a value between 0 and \c RAND_MAX (defined in \c <cstdlib> and
- \c <stdlib.h>), the next number in the current sequence of pseudo-random
- integers.
+ // bypass the hardware RNG, which would mean initializing qsimd.cpp
- Use \c qsrand() to initialize the pseudo-random number generator with a
- seed value. Seeding must be performed at least once on each thread. If that
- step is skipped, then the sequence will be pre-seeded with a constant
- value.
+ QRandomGenerator::InitialRandomData v;
+ for (int attempts = 16; attempts; --attempts) {
+ using Generator = QRandomGenerator::SystemGenerator;
+ auto fillBuffer = &Generator::fillBuffer;
+ if (callFillBuffer<Generator>(fillBuffer, &v) != sizeof(v))
+ continue;
- \note This function is deprecated. In new applications, use
- QRandomGenerator instead.
+ return v;
+ }
- \sa qsrand(), QRandomGenerator
-*/
-int qrand()
-{
- auto prng = randTLS();
- if (prng)
- return prng->generate();
- else
- return rand();
+ quint32 data[sizeof(v) / sizeof(quint32)];
+ fallback_fill(data, std::size(data));
+ memcpy(v.data, data, sizeof(v.data));
+ return v;
}
QT_END_NAMESPACE
diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h
index 4e27ef1edc..f8e53f4009 100644
--- a/src/corelib/global/qrandom.h
+++ b/src/corelib/global/qrandom.h
@@ -1,46 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRANDOM_H
#define QRANDOM_H
-#include <QtCore/qglobal.h>
+#include <QtCore/qalgorithms.h>
#include <algorithm> // for std::generate
#include <random> // for std::mt19937
@@ -83,16 +47,12 @@ public:
quint32 generate()
{
- quint32 ret;
- fillRange(&ret, 1);
- return ret;
+ return quint32(_fillRange(nullptr, 1));
}
quint64 generate64()
{
- quint32 buf[2];
- fillRange(buf);
- return buf[0] | (quint64(buf[1]) << 32);
+ return _fillRange(nullptr, sizeof(quint64) / sizeof(quint32));
}
double generateDouble()
@@ -139,16 +99,54 @@ public:
return bounded(highest - lowest) + lowest;
}
+ quint64 bounded(quint64 highest);
+
+ quint64 bounded(quint64 lowest, quint64 highest)
+ {
+ Q_ASSERT(highest > lowest);
+ return bounded(highest - lowest) + lowest;
+ }
+
+ qint64 bounded(qint64 highest)
+ {
+ Q_ASSERT(highest > 0);
+ return qint64(bounded(quint64(0), quint64(highest)));
+ }
+
+ qint64 bounded(qint64 lowest, qint64 highest)
+ {
+ return bounded(highest - lowest) + lowest;
+ }
+
+ // these functions here only to help with ambiguous overloads
+ qint64 bounded(int lowest, qint64 highest)
+ {
+ return bounded(qint64(lowest), qint64(highest));
+ }
+ qint64 bounded(qint64 lowest, int highest)
+ {
+ return bounded(qint64(lowest), qint64(highest));
+ }
+
+ quint64 bounded(unsigned lowest, quint64 highest)
+ {
+ return bounded(quint64(lowest), quint64(highest));
+ }
+ quint64 bounded(quint64 lowest, unsigned highest)
+ {
+ return bounded(quint64(lowest), quint64(highest));
+ }
+
template <typename UInt, IfValidUInt<UInt> = true>
void fillRange(UInt *buffer, qsizetype count)
{
- _fillRange(buffer, buffer + count);
+ _fillRange(buffer, count * sizeof(UInt) / sizeof(quint32));
}
template <typename UInt, size_t N, IfValidUInt<UInt> = true>
void fillRange(UInt (&buffer)[N])
{
- _fillRange(buffer, buffer + N);
+ _fillRange(buffer, N * sizeof(UInt) / sizeof(quint32));
}
// API like std::seed_seq
@@ -160,7 +158,7 @@ public:
void generate(quint32 *begin, quint32 *end)
{
- _fillRange(begin, end);
+ _fillRange(begin, end - begin);
}
// API like std:: random engines
@@ -169,8 +167,8 @@ public:
void seed(quint32 s = 1) { *this = { s }; }
void seed(std::seed_seq &sseq) noexcept { *this = { sseq }; }
Q_CORE_EXPORT void discard(unsigned long long z);
- static Q_DECL_CONSTEXPR result_type min() { return std::numeric_limits<result_type>::min(); }
- static Q_DECL_CONSTEXPR result_type max() { return std::numeric_limits<result_type>::max(); }
+ static constexpr result_type min() { return (std::numeric_limits<result_type>::min)(); }
+ static constexpr result_type max() { return (std::numeric_limits<result_type>::max)(); }
static inline Q_DECL_CONST_FUNCTION QRandomGenerator *system();
static inline Q_DECL_CONST_FUNCTION QRandomGenerator *global();
@@ -181,8 +179,12 @@ protected:
QRandomGenerator(System);
private:
- Q_CORE_EXPORT void _fillRange(void *buffer, void *bufferEnd);
+ Q_CORE_EXPORT quint64 _fillRange(void *buffer, qptrdiff count);
+ struct InitialRandomData {
+ quintptr data[16 / sizeof(quintptr)];
+ };
+ friend InitialRandomData qt_initial_random_value() noexcept;
friend class QRandomGenerator64;
struct SystemGenerator;
struct SystemAndGlobalGenerators;
@@ -191,19 +193,13 @@ private:
union Storage {
uint dummy;
-#ifdef Q_COMPILER_UNRESTRICTED_UNIONS
RandomEngine twister;
RandomEngine &engine() { return twister; }
const RandomEngine &engine() const { return twister; }
-#else
- std::aligned_storage<sizeof(RandomEngine), alignof(RandomEngine)>::type buffer;
- RandomEngine &engine() { return reinterpret_cast<RandomEngine &>(buffer); }
- const RandomEngine &engine() const { return reinterpret_cast<const RandomEngine &>(buffer); }
-#endif
static_assert(std::is_trivially_destructible<RandomEngine>::value,
"std::mersenne_twister not trivially destructible as expected");
- Q_DECL_CONSTEXPR Storage();
+ constexpr Storage();
};
uint type;
Storage storage;
@@ -245,14 +241,32 @@ public:
QRandomGenerator::discard(z * 2);
}
- static Q_DECL_CONSTEXPR result_type min() { return std::numeric_limits<result_type>::min(); }
- static Q_DECL_CONSTEXPR result_type max() { return std::numeric_limits<result_type>::max(); }
+ static constexpr result_type min() { return (std::numeric_limits<result_type>::min)(); }
+ static constexpr result_type max() { return (std::numeric_limits<result_type>::max)(); }
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *system();
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *global();
static Q_CORE_EXPORT QRandomGenerator64 securelySeeded();
#endif // Q_QDOC
};
+inline quint64 QRandomGenerator::bounded(quint64 highest)
+{
+ // Implement an algorithm similar to libc++'s uniform_int_distribution:
+ // loop around getting a random number, mask off any bits that "highest"
+ // will never need, then check if it's higher than "highest". The number of
+ // times the loop will run is unbounded but the probability of terminating
+ // is better than 1/2 on each iteration. Therefore, the average loop count
+ // should be less than 2.
+
+ const int width = qCountLeadingZeroBits(highest - 1);
+ const quint64 mask = (quint64(1) << (std::numeric_limits<quint64>::digits - width)) - 1;
+ quint64 v;
+ do {
+ v = generate64() & mask;
+ } while (v >= highest);
+ return v;
+}
+
inline QRandomGenerator *QRandomGenerator::system()
{
return QRandomGenerator64::system();
diff --git a/src/corelib/global/qrandom_p.h b/src/corelib/global/qrandom_p.h
index 934a9282b8..c0209f97d2 100644
--- a/src/corelib/global/qrandom_p.h
+++ b/src/corelib/global/qrandom_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRANDOM_P_H
#define QRANDOM_P_H
@@ -52,6 +16,7 @@
//
#include "qglobal_p.h"
+#include <qrandom.h>
#include <private/qsimd_p.h>
QT_BEGIN_NAMESPACE
@@ -71,17 +36,16 @@ enum RNGType {
MersenneTwister = 1
};
-#if defined(QT_BUILD_INTERNAL) && defined(QT_BUILD_CORE_LIB)
-Q_CORE_EXPORT QBasicAtomicInteger<uint> qt_randomdevice_control = Q_BASIC_ATOMIC_INITIALIZER(0U);
-#elif defined(QT_BUILD_INTERNAL)
+#if defined(QT_BUILD_INTERNAL)
extern Q_CORE_EXPORT QBasicAtomicInteger<uint> qt_randomdevice_control;
#else
-static const struct {
+static const struct
+{
uint loadAcquire() const { return 0; }
} qt_randomdevice_control;
#endif
-
+QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept;
QT_END_NAMESPACE
diff --git a/src/corelib/global/qsimd.cpp b/src/corelib/global/qsimd.cpp
index 6ad6795fec..8bc5381591 100644
--- a/src/corelib/global/qsimd.cpp
+++ b/src/corelib/global/qsimd.cpp
@@ -1,76 +1,53 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// we need ICC to define the prototype for _rdseed64_step
#define __INTEL_COMPILER_USE_INTRINSIC_PROTOTYPES
+#undef _FORTIFY_SOURCE // otherwise, the always_inline from stdio.h fail to inline
#include "qsimd_p.h"
#include "qalgorithms.h"
-#include <QByteArray>
+
#include <stdio.h>
+#include <string.h>
+
+#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
+# define NDEBUG
+#endif
+#include <assert.h>
#ifdef Q_OS_LINUX
# include "../testlib/3rdparty/valgrind_p.h"
#endif
+#define QT_FUNCTION_TARGET_BASELINE
+
#if defined(Q_OS_WIN)
# if !defined(Q_CC_GNU)
# include <intrin.h>
# endif
-#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS_32))
-#include "private/qcore_unix_p.h"
+# if defined(Q_PROCESSOR_ARM_64)
+# include <qt_windows.h>
+# include <processthreadsapi.h>
+# endif
+#elif defined(Q_OS_LINUX) && defined(Q_PROCESSOR_MIPS_32)
+# include "private/qcore_unix_p.h"
+#elif QT_CONFIG(getauxval) && defined(Q_PROCESSOR_ARM)
+# include <sys/auxv.h>
// the kernel header definitions for HWCAP_*
// (the ones we need/may need anyway)
// copied from <asm/hwcap.h> (ARM)
-#define HWCAP_CRUNCH 1024
-#define HWCAP_THUMBEE 2048
#define HWCAP_NEON 4096
-#define HWCAP_VFPv3 8192
-#define HWCAP_VFPv3D16 16384
// copied from <asm/hwcap.h> (ARM):
+#define HWCAP2_AES (1 << 0)
#define HWCAP2_CRC32 (1 << 4)
// copied from <asm/hwcap.h> (Aarch64)
+#define HWCAP_AES (1 << 3)
#define HWCAP_CRC32 (1 << 7)
// copied from <linux/auxvec.h>
@@ -78,106 +55,110 @@
#define AT_HWCAP2 26 /* extension of AT_HWCAP */
#elif defined(Q_CC_GHS)
-#include <INTEGRITY_types.h>
+# include <INTEGRITY_types.h>
+#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM)
+# include <sys/sysctl.h>
#endif
QT_BEGIN_NAMESPACE
-/*
- * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note
- * we remove the terminating -1 that the script adds.
- */
+template <typename T, uint N> QT_FUNCTION_TARGET_BASELINE
+uint arraysize(T (&)[N])
+{
+ // Same as std::size, but with QT_FUNCTION_TARGET_BASELIE,
+ // otherwise some versions of GCC fail to compile.
+ return N;
+}
-// begin generated
#if defined(Q_PROCESSOR_ARM)
/* Data:
neon
crc32
+ aes
*/
static const char features_string[] =
+ "\0"
" neon\0"
" crc32\0"
- "\0";
-static const int features_indices[] = { 0, 6 };
+ " aes\0";
+static const int features_indices[] = { 0, 1, 7, 14 };
#elif defined(Q_PROCESSOR_MIPS)
/* Data:
dsp
dspr2
*/
static const char features_string[] =
+ "\0"
" dsp\0"
- " dspr2\0"
- "\0";
+ " dspr2\0";
static const int features_indices[] = {
- 0, 5
+ 0, 1, 6
};
#elif defined(Q_PROCESSOR_X86)
# include "qsimd_x86.cpp" // generated by util/x86simdgen
#else
static const char features_string[] = "";
-static const int features_indices[] = { };
+static const int features_indices[] = { 0 };
#endif
// end generated
-#if defined (Q_OS_NACL)
-static inline uint detectProcessorFeatures()
-{
- return 0;
-}
-#elif defined(Q_PROCESSOR_ARM)
+#if defined(Q_PROCESSOR_ARM)
static inline quint64 detectProcessorFeatures()
{
quint64 features = 0;
-#if defined(Q_OS_LINUX)
-# if defined(Q_PROCESSOR_ARM_V8) && defined(Q_PROCESSOR_ARM_64)
- features |= Q_UINT64_C(1) << CpuFeatureNEON; // NEON is always available on ARMv8 64bit.
-# endif
- int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY);
- if (auxv != -1) {
- unsigned long vector[64];
- int nread;
- while (features == 0) {
- nread = qt_safe_read(auxv, (char *)vector, sizeof vector);
- if (nread <= 0) {
- // EOF or error
- break;
- }
-
- int max = nread / (sizeof vector[0]);
- for (int i = 0; i < max; i += 2) {
- if (vector[i] == AT_HWCAP) {
-# if defined(Q_PROCESSOR_ARM_V8) && defined(Q_PROCESSOR_ARM_64)
- // For Aarch64:
- if (vector[i+1] & HWCAP_CRC32)
- features |= Q_UINT64_C(1) << CpuFeatureCRC32;
-# endif
- // Aarch32, or ARMv7 or before:
- if (vector[i+1] & HWCAP_NEON)
- features |= Q_UINT64_C(1) << CpuFeatureNEON;
- }
-# if defined(Q_PROCESSOR_ARM_32)
- // For Aarch32:
- if (vector[i] == AT_HWCAP2) {
- if (vector[i+1] & HWCAP2_CRC32)
- features |= Q_UINT64_C(1) << CpuFeatureCRC32;
- }
+#if QT_CONFIG(getauxval)
+ unsigned long auxvHwCap = getauxval(AT_HWCAP);
+ if (auxvHwCap != 0) {
+# if defined(Q_PROCESSOR_ARM_64)
+ // For Aarch64:
+ features |= CpuFeatureNEON; // NEON is always available
+ if (auxvHwCap & HWCAP_CRC32)
+ features |= CpuFeatureCRC32;
+ if (auxvHwCap & HWCAP_AES)
+ features |= CpuFeatureAES;
+# else
+ // For ARM32:
+ if (auxvHwCap & HWCAP_NEON)
+ features |= CpuFeatureNEON;
+ auxvHwCap = getauxval(AT_HWCAP2);
+ if (auxvHwCap & HWCAP2_CRC32)
+ features |= CpuFeatureCRC32;
+ if (auxvHwCap & HWCAP2_AES)
+ features |= CpuFeatureAES;
# endif
- }
- }
-
- qt_safe_close(auxv);
return features;
}
- // fall back if /proc/self/auxv wasn't found
+ // fall back to compile-time flags if getauxval failed
+#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM)
+ unsigned feature;
+ size_t len = sizeof(feature);
+ if (sysctlbyname("hw.optional.neon", &feature, &len, nullptr, 0) == 0)
+ features |= feature ? CpuFeatureNEON : 0;
+ if (sysctlbyname("hw.optional.armv8_crc32", &feature, &len, nullptr, 0) == 0)
+ features |= feature ? CpuFeatureCRC32 : 0;
+ // There is currently no optional value for crypto/AES.
+#if defined(__ARM_FEATURE_CRYPTO)
+ features |= CpuFeatureAES;
#endif
-
-#if defined(__ARM_NEON__)
- features |= Q_UINT64_C(1) << CpuFeatureNEON;
+ return features;
+#elif defined(Q_OS_WIN) && defined(Q_PROCESSOR_ARM_64)
+ features |= CpuFeatureNEON;
+ if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0)
+ features |= CpuFeatureCRC32;
+ if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
+ features |= CpuFeatureAES;
+ return features;
+#endif
+#if defined(__ARM_NEON__) || defined(__ARM_NEON)
+ features |= CpuFeatureNEON;
#endif
#if defined(__ARM_FEATURE_CRC32)
- features |= Q_UINT64_C(1) << CpuFeatureCRC32;
+ features |= CpuFeatureCRC32;
+#endif
+#if defined(__ARM_FEATURE_CRYPTO)
+ features |= CpuFeatureAES;
#endif
return features;
@@ -190,9 +171,23 @@ static inline quint64 detectProcessorFeatures()
#else
# define PICreg "%%rbx"
#endif
+#ifdef __SSE2_MATH__
+# define X86_BASELINE "no-sse3"
+#else
+# define X86_BASELINE "no-sse"
+#endif
+
+#if defined(Q_CC_GNU)
+// lower the target for functions in this file
+# undef QT_FUNCTION_TARGET_BASELINE
+# define QT_FUNCTION_TARGET_BASELINE __attribute__((target(X86_BASELINE)))
+# define QT_FUNCTION_TARGET_STRING_BASELINE_RDRND \
+ X86_BASELINE "," QT_FUNCTION_TARGET_STRING_RDRND
+#endif
static bool checkRdrndWorks() noexcept;
+QT_FUNCTION_TARGET_BASELINE
static int maxBasicCpuidSupported()
{
#if defined(Q_CC_EMSCRIPTEN)
@@ -240,6 +235,7 @@ static int maxBasicCpuidSupported()
#endif
}
+QT_FUNCTION_TARGET_BASELINE
static void cpuidFeatures01(uint &ecx, uint &edx)
{
#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
@@ -269,6 +265,7 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));}
#endif
+QT_FUNCTION_TARGET_BASELINE
static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx)
{
#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
@@ -302,6 +299,7 @@ static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx)
#endif
}
+QT_FUNCTION_TARGET_BASELINE
#if defined(Q_OS_WIN) && !(defined(Q_CC_GNU) || defined(Q_CC_GHS))
// fallback overload in case this intrinsic does not exist: unsigned __int64 _xgetbv(unsigned int);
inline quint64 _xgetbv(__int64) { return 0; }
@@ -323,62 +321,74 @@ static void xgetbv(uint in, uint &eax, uint &edx)
#endif
}
-static quint64 detectProcessorFeatures()
+QT_FUNCTION_TARGET_BASELINE
+static quint64 adjustedXcr0(quint64 xcr0)
{
- // Flags from the CR0 / XCR0 state register
- enum XCR0Flags {
- X87 = 1 << 0,
- XMM0_15 = 1 << 1,
- YMM0_15Hi128 = 1 << 2,
- BNDRegs = 1 << 3,
- BNDCSR = 1 << 4,
- OpMask = 1 << 5,
- ZMM0_15Hi256 = 1 << 6,
- ZMM16_31 = 1 << 7,
-
- SSEState = XMM0_15,
- AVXState = XMM0_15 | YMM0_15Hi128,
- AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31
- };
- static const quint64 AllAVX2 = CpuFeatureAVX2 | AllAVX512;
- static const quint64 AllAVX = CpuFeatureAVX | AllAVX2;
+ /*
+ * Some OSes hide their capability of context-switching the AVX512 state in
+ * the XCR0 register. They do that so the first time we execute an
+ * instruction that may access the AVX512 state (requiring the EVEX prefix)
+ * they allocate the necessary context switch space.
+ *
+ * This behavior is deprecated with the XFD (Extended Feature Disable)
+ * register, but we can't change existing OSes.
+ */
+#ifdef Q_OS_DARWIN
+ // from <machine/cpu_capabilities.h> in xnu
+ // <https://github.com/apple/darwin-xnu/blob/xnu-4903.221.2/osfmk/i386/cpu_capabilities.h>
+ constexpr quint64 kHasAVX512F = Q_UINT64_C(0x0000004000000000);
+ constexpr quintptr commpage = sizeof(void *) > 4 ? Q_UINT64_C(0x00007fffffe00000) : 0xffff0000;
+ constexpr quintptr cpu_capabilities64 = commpage + 0x10;
+ quint64 capab = *reinterpret_cast<quint64 *>(cpu_capabilities64);
+ if (capab & kHasAVX512F)
+ xcr0 |= XSave_Avx512State;
+#endif
+ return xcr0;
+}
+
+QT_FUNCTION_TARGET_BASELINE
+static quint64 detectProcessorFeatures()
+{
quint64 features = 0;
int cpuidLevel = maxBasicCpuidSupported();
#if Q_PROCESSOR_X86 < 5
if (cpuidLevel < 1)
return 0;
#else
- Q_ASSERT(cpuidLevel >= 1);
+ assert(cpuidLevel >= 1);
#endif
uint results[X86CpuidMaxLeaf] = {};
- cpuidFeatures01(results[Leaf1ECX], results[Leaf1EDX]);
+ cpuidFeatures01(results[Leaf01ECX], results[Leaf01EDX]);
if (cpuidLevel >= 7)
- cpuidFeatures07_00(results[Leaf7_0EBX], results[Leaf7_0ECX], results[Leaf7_0EDX]);
+ cpuidFeatures07_00(results[Leaf07_00EBX], results[Leaf07_00ECX], results[Leaf07_00EDX]);
// populate our feature list
- for (uint i = 0; i < sizeof(x86_locators) / sizeof(x86_locators[0]); ++i) {
+ for (uint i = 0; i < arraysize(x86_locators); ++i) {
uint word = x86_locators[i] / 32;
uint bit = 1U << (x86_locators[i] % 32);
- quint64 feature = Q_UINT64_C(1) << (i + 1);
+ quint64 feature = Q_UINT64_C(1) << i;
if (results[word] & bit)
features |= feature;
}
// now check the AVX state
- uint xgetbvA = 0, xgetbvD = 0;
- if (results[Leaf1ECX] & (1u << 27)) {
+ quint64 xcr0 = 0;
+ if (results[Leaf01ECX] & (1u << 27)) {
// XGETBV enabled
+ uint xgetbvA = 0, xgetbvD = 0;
xgetbv(0, xgetbvA, xgetbvD);
+
+ xcr0 = xgetbvA;
+ if (sizeof(XSaveBits) > sizeof(xgetbvA))
+ xcr0 |= quint64(xgetbvD) << 32;
+ xcr0 = adjustedXcr0(xcr0);
}
- if ((xgetbvA & AVXState) != AVXState) {
- // support for YMM registers is disabled, disable all AVX
- features &= ~AllAVX;
- } else if ((xgetbvA & AVX512State) != AVX512State) {
- // support for ZMM registers or mask registers is disabled, disable all AVX512
- features &= ~AllAVX512;
+ for (auto req : xsave_requirements) {
+ if ((xcr0 & req.xsave_state) != req.xsave_state)
+ features &= ~req.cpu_features;
}
if (features & CpuFeatureRDRND && !checkRdrndWorks())
@@ -396,38 +406,46 @@ static quint64 detectProcessorFeatures()
// QSimpleBuffer, which has the bare minimum needed to use memory
// dynamically and read lines from /proc/cpuinfo of arbitrary sizes.
//
-struct QSimpleBuffer {
+struct QSimpleBuffer
+{
static const int chunk_size = 256;
char *data;
unsigned alloc;
unsigned size;
- QSimpleBuffer(): data(0), alloc(0), size(0) {}
+ QSimpleBuffer() : data(nullptr), alloc(0), size(0) { }
~QSimpleBuffer() { ::free(data); }
- void resize(unsigned newsize) {
+ void resize(unsigned newsize)
+ {
if (newsize > alloc) {
unsigned newalloc = chunk_size * ((newsize / chunk_size) + 1);
- if (newalloc < newsize) newalloc = newsize;
+ if (newalloc < newsize)
+ newalloc = newsize;
if (newalloc != alloc) {
- data = static_cast<char*>(::realloc(data, newalloc));
+ data = static_cast<char *>(::realloc(data, newalloc));
alloc = newalloc;
}
}
size = newsize;
}
- void append(const QSimpleBuffer &other, unsigned appendsize) {
+ void append(const QSimpleBuffer &other, unsigned appendsize)
+ {
unsigned oldsize = size;
resize(oldsize + appendsize);
::memcpy(data + oldsize, other.data, appendsize);
}
- void popleft(unsigned amount) {
- if (amount >= size) return resize(0);
+ void popleft(unsigned amount)
+ {
+ if (amount >= size)
+ return resize(0);
size -= amount;
::memmove(data, data + amount, size);
}
- char* cString() {
- if (!alloc) resize(1);
+ char *cString()
+ {
+ if (!alloc)
+ resize(1);
return (data[size] = '\0', data);
}
};
@@ -441,7 +459,7 @@ struct QSimpleBuffer {
static void bufReadLine(int fd, QSimpleBuffer &line, QSimpleBuffer &buffer)
{
for (;;) {
- char *newline = static_cast<char*>(::memchr(buffer.data, '\n', buffer.size));
+ char *newline = static_cast<char *>(::memchr(buffer.data, '\n', buffer.size));
if (newline) {
unsigned piece_size = newline - buffer.data + 1;
line.append(buffer, piece_size);
@@ -454,9 +472,12 @@ static void bufReadLine(int fd, QSimpleBuffer &line, QSimpleBuffer &buffer)
buffer.resize(buffer.size + QSimpleBuffer::chunk_size);
buffer.size = oldsize;
}
- ssize_t read_bytes = ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size);
- if (read_bytes > 0) buffer.size += read_bytes;
- else return;
+ ssize_t read_bytes =
+ ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size);
+ if (read_bytes > 0)
+ buffer.size += read_bytes;
+ else
+ return;
}
}
@@ -477,7 +498,7 @@ static bool procCpuinfoContains(const char *prefix, const char *string)
do {
line.resize(0);
bufReadLine(cpuinfo_fd, line, buffer);
- char *colon = static_cast<char*>(::memchr(line.data, ':', line.size));
+ char *colon = static_cast<char *>(::memchr(line.data, ':', line.size));
if (colon && line.size > prefix_len + string_len) {
if (!::strncmp(prefix, line.data, prefix_len)) {
// prefix matches, next character must be ':' or space
@@ -505,18 +526,18 @@ static inline quint64 detectProcessorFeatures()
quint64 flags = 0;
#if defined __mips_dsp
- flags |= Q_UINT64_C(1) << CpuFeatureDSP;
+ flags |= CpuFeatureDSP;
# if defined __mips_dsp_rev && __mips_dsp_rev >= 2
- flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
+ flags |= CpuFeatureDSPR2;
# elif defined(Q_OS_LINUX)
if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
- flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
+ flags |= CpuFeatureDSPR2;
# endif
#elif defined(Q_OS_LINUX)
if (procCpuinfoContains("ASEs implemented", "dsp")) {
- flags |= Q_UINT64_C(1) << CpuFeatureDSP;
+ flags |= CpuFeatureDSP;
if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
- flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
+ flags |= CpuFeatureDSPR2;
}
#endif
@@ -530,26 +551,38 @@ static inline uint detectProcessorFeatures()
}
#endif
-static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]);
-
// record what CPU features were enabled by default in this Qt build
static const quint64 minFeature = qCompilerCpuFeatures;
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
-Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) };
-#else
-Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };
-#endif
+static constexpr auto SimdInitialized = QCpuFeatureType(1) << (sizeof(QCpuFeatureType) * 8 - 1);
+Q_ATOMIC(QCpuFeatureType) QT_MANGLE_NAMESPACE(qt_cpu_features)[1] = { 0 };
-quint64 qDetectCpuFeatures()
+QT_FUNCTION_TARGET_BASELINE
+uint64_t QT_MANGLE_NAMESPACE(qDetectCpuFeatures)()
{
- quint64 f = detectProcessorFeatures();
- QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
- if (!disable.isEmpty()) {
- disable.prepend(' ');
- for (int i = 0; i < features_count; ++i) {
- if (disable.contains(features_string + features_indices[i]))
- f &= ~(Q_UINT64_C(1) << i);
+ auto minFeatureTest = minFeature;
+#if defined(Q_PROCESSOR_X86_64) && defined(cpu_feature_shstk)
+ // Controlflow Enforcement Technology (CET) is an OS-assisted
+ // hardware-feature, meaning the CPUID bit may be disabled if the OS
+ // doesn't support it, but that's ok.
+ minFeatureTest &= ~CpuFeatureSHSTK;
+#endif
+ QCpuFeatureType f = detectProcessorFeatures();
+
+ // Intentionally NOT qgetenv (this code runs too early)
+ if (char *disable = getenv("QT_NO_CPU_FEATURE"); disable && *disable) {
+#if _POSIX_C_SOURCE >= 200112L
+ char *saveptr = nullptr;
+ auto strtok = [&saveptr](char *str, const char *delim) {
+ return ::strtok_r(str, delim, &saveptr);
+ };
+#endif
+ while (char *token = strtok(disable, " ")) {
+ disable = nullptr;
+ for (uint i = 0; i < arraysize(features_indices); ++i) {
+ if (strcmp(token, features_string + features_indices[i]) == 0)
+ f &= ~(Q_UINT64_C(1) << i);
+ }
}
}
@@ -558,38 +591,37 @@ quint64 qDetectCpuFeatures()
#else
bool runningOnValgrind = false;
#endif
- if (Q_UNLIKELY(!runningOnValgrind && minFeature != 0 && (f & minFeature) != minFeature)) {
- quint64 missing = minFeature & ~f;
+ if (Q_UNLIKELY(!runningOnValgrind && minFeatureTest != 0 && (f & minFeatureTest) != minFeatureTest)) {
+ quint64 missing = minFeatureTest & ~quint64(f);
fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n ");
- for (int i = 0; i < features_count; ++i) {
+ for (uint i = 0; i < arraysize(features_indices); ++i) {
if (missing & (Q_UINT64_C(1) << i))
fprintf(stderr, "%s", features_string + features_indices[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
- qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing,
- features_string + features_indices[qCountTrailingZeroBits(missing)]);
+ qAbort();
}
- qt_cpu_features[0].storeRelaxed(f | quint32(QSimdInitialized));
-#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
- qt_cpu_features[1].storeRelaxed(f >> 32);
-#endif
+ assert((f & SimdInitialized) == 0);
+ f |= SimdInitialized;
+ std::atomic_store_explicit(QT_MANGLE_NAMESPACE(qt_cpu_features), f, std::memory_order_relaxed);
return f;
}
+QT_FUNCTION_TARGET_BASELINE
void qDumpCPUFeatures()
{
- quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized);
+ quint64 features = detectProcessorFeatures() & ~SimdInitialized;
printf("Processor features: ");
- for (int i = 0; i < features_count; ++i) {
+ for (uint i = 0; i < arraysize(features_indices); ++i) {
if (features & (Q_UINT64_C(1) << i))
printf("%s%s", features_string + features_indices[i],
minFeature & (Q_UINT64_C(1) << i) ? "[required]" : "");
}
if ((features = (qCompilerCpuFeatures & ~features))) {
printf("\n!!!!!!!!!!!!!!!!!!!!\n!!! Missing required features:");
- for (int i = 0; i < features_count; ++i) {
+ for (uint i = 0; i < arraysize(features_indices); ++i) {
if (features & (Q_UINT64_C(1) << i))
printf("%s", features_string + features_indices[i]);
}
@@ -625,10 +657,10 @@ static QT_FUNCTION_TARGET(RDSEED) unsigned *qt_random_rdseed(unsigned *ptr, unsi
// If the independent bit generator used by RDSEED is out of entropy, it
// may take time to replenish.
// https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
- while (ptr + sizeof(randuint)/sizeof(*ptr) <= end) {
+ while (ptr + sizeof(randuint) / sizeof(*ptr) <= end) {
if (_rdseedXX_step(reinterpret_cast<randuint *>(ptr)) == 0)
goto out;
- ptr += sizeof(randuint)/sizeof(*ptr);
+ ptr += sizeof(randuint) / sizeof(*ptr);
}
if (sizeof(*ptr) != sizeof(randuint) && ptr != end) {
@@ -670,7 +702,8 @@ out:
return ptr;
}
-static QT_FUNCTION_TARGET(RDRND) Q_DECL_COLD_FUNCTION bool checkRdrndWorks() noexcept
+QT_FUNCTION_TARGET(BASELINE_RDRND) Q_DECL_COLD_FUNCTION
+static bool checkRdrndWorks() noexcept
{
/*
* Some AMD CPUs (e.g. AMD A4-6250J and AMD Ryzen 3000-series) have a
@@ -723,8 +756,20 @@ QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) no
ptr = qt_random_rdrnd(ptr, end);
return ptr - reinterpret_cast<unsigned *>(buffer);
}
-#elif defined(Q_PROCESSOR_X86) && !defined(Q_OS_NACL) && !defined(Q_PROCESSOR_ARM)
+#elif defined(Q_PROCESSOR_X86) && !defined(Q_PROCESSOR_ARM)
static bool checkRdrndWorks() noexcept { return false; }
#endif // Q_PROCESSOR_X86 && RDRND
+#if QT_SUPPORTS_INIT_PRIORITY
+namespace {
+struct QSimdInitializer
+{
+ inline QSimdInitializer() { QT_MANGLE_NAMESPACE(qDetectCpuFeatures)(); }
+};
+}
+
+// This is intentionally a dynamic initialization of the variable
+Q_DECL_INIT_PRIORITY(01) static QSimdInitializer initializer;
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/global/qsimd.h b/src/corelib/global/qsimd.h
index 5fd34d0092..4ef925ca33 100644
--- a/src/corelib/global/qsimd.h
+++ b/src/corelib/global/qsimd.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIMD_H
#define QSIMD_H
@@ -89,20 +53,20 @@
# define QT_COMPILER_USES_mips_dspr2 -1
#endif
-#if defined(Q_PROCESSOR_X86)
-#if defined(Q_CC_MSVC)
+#if defined(Q_PROCESSOR_X86) && defined(Q_CC_MSVC)
// MSVC doesn't define __SSE2__, so do it ourselves
-# if (defined(_M_X64) || _M_IX86_FP >= 2)
+# if (defined(_M_X64) || _M_IX86_FP >= 2) && defined(QT_COMPILER_SUPPORTS_SSE2)
# define __SSE__ 1
# define __SSE2__ 1
# endif
-#if (defined(_M_AVX) || defined(__AVX__))
+# if (defined(_M_AVX) || defined(__AVX__))
// Visual Studio defines __AVX__ when /arch:AVX is passed, but not the earlier macros
// See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx
# define __SSE3__ 1
# define __SSSE3__ 1
# define __SSE4_1__ 1
# define __SSE4_2__ 1
+# define __POPCNT__ 1
# ifndef __AVX__
# define __AVX__ 1
# endif
@@ -110,7 +74,17 @@
# ifdef __SSE2__
# define QT_VECTORCALL __vectorcall
# endif
-#endif
+# ifdef __AVX2__
+// MSVC defines __AVX2__ with /arch:AVX2
+# define __F16C__ 1
+# define __RDRND__ 1
+# define __FMA__ 1
+# define __BMI__ 1
+# define __BMI2__ 1
+# define __MOVBE__ 1
+# define __LZCNT__ 1
+# endif
+// Starting with /arch:AVX512, MSVC defines all the macros
#endif
#if defined(Q_PROCESSOR_X86) && defined(__SSE2__)
diff --git a/src/corelib/global/qsimd_p.h b/src/corelib/global/qsimd_p.h
index 2f2d49348f..012eb6cf4f 100644
--- a/src/corelib/global/qsimd_p.h
+++ b/src/corelib/global/qsimd_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIMD_P_H
#define QSIMD_P_H
@@ -55,34 +19,21 @@
#include <QtCore/private/qglobal_p.h>
#include <QtCore/qsimd.h>
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wundef")
+QT_WARNING_DISABLE_GCC("-Wundef")
+QT_WARNING_DISABLE_INTEL(103)
+
+#define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \
+ for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i)
+
+#define ALIGNMENT_PROLOGUE_32BYTES(ptr, i, length) \
+ for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((8 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x7)) & 0x7))); ++i)
+
+#define SIMD_EPILOGUE(i, length, max) \
+ for (int _i = 0; _i < max && i < length; ++i, ++_i)
+
/*
- * qt_module_config.prf defines the QT_COMPILER_SUPPORTS_XXX macros.
- * They mean the compiler supports the necessary flags and the headers
- * for the x86 and ARM intrinsics:
- * - GCC: the -mXXX or march=YYY flag is necessary before #include
- * up to 4.8; GCC >= 4.9 can include unconditionally
- * - Intel CC: #include can happen unconditionally
- * - MSVC: #include can happen unconditionally
- * - RVCT: ???
- *
- * We will try to include all headers possible under this configuration.
- *
- * MSVC does not define __SSE2__ & family, so we will define them. MSVC 2013 &
- * up do define __AVX__ if the -arch:AVX option is passed on the command-line.
- *
- * Supported XXX are:
- * Flag | Arch | GCC | Intel CC | MSVC |
- * ARM_NEON | ARM | I & C | None | ? |
- * SSE2 | x86 | I & C | I & C | I & C |
- * SSE3 | x86 | I & C | I & C | I only |
- * SSSE3 | x86 | I & C | I & C | I only |
- * SSE4_1 | x86 | I & C | I & C | I only |
- * SSE4_2 | x86 | I & C | I & C | I only |
- * AVX | x86 | I & C | I & C | I & C |
- * AVX2 | x86 | I & C | I & C | I only |
- * AVX512xx | x86 | I & C | I & C | I only |
- * I = intrinsics; C = code generation
- *
* Code can use the following constructs to determine compiler support & status:
* - #ifdef __XXX__ (e.g: #ifdef __AVX__ or #ifdef __ARM_NEON__)
* If this test passes, then the compiler is already generating code for that
@@ -103,6 +54,9 @@
* sub-arch. Only inside such functions is the use of the intrisics
* guaranteed to work. This is useful with runtime detection (see below).
*
+ * The distinction between QT_COMPILER_SUPPORTS and QT_COMPILER_SUPPORTS_HERE is
+ * historical: GCC 4.8 needed the distinction.
+ *
* Runtime detection of a CPU sub-architecture can be done with the
* qCpuHasFeature(XXX) function. There are two strategies for generating
* optimized code like that:
@@ -146,16 +100,13 @@
#define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0)
#if defined(Q_PROCESSOR_ARM)
-# define QT_COMPILER_SUPPORTS_HERE(x) (__ARM_FEATURE_ ## x)
-# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600
+# define QT_COMPILER_SUPPORTS_HERE(x) ((__ARM_FEATURE_ ## x) || (__ ## x ## __) || QT_COMPILER_SUPPORTS(x))
+# if defined(Q_CC_GNU)
/* GCC requires attributes for a function */
# define QT_FUNCTION_TARGET(x) __attribute__((__target__(QT_FUNCTION_TARGET_STRING_ ## x)))
# else
# define QT_FUNCTION_TARGET(x)
# endif
-# if !defined(__ARM_FEATURE_NEON) && defined(__ARM_NEON__)
-# define __ARM_FEATURE_NEON // also support QT_COMPILER_SUPPORTS_HERE(NEON)
-# endif
#elif defined(Q_PROCESSOR_MIPS)
# define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __)
# define QT_FUNCTION_TARGET(x)
@@ -165,9 +116,13 @@
# if !defined(__MIPS_DSPR2__) && defined(__mips_dspr2) && defined(Q_PROCESSOR_MIPS_32)
# define __MIPS_DSPR2__
# endif
-#elif defined(Q_PROCESSOR_X86) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)
-# define QT_COMPILER_SUPPORTS_HERE(x) ((__ ## x ## __) || QT_COMPILER_SUPPORTS(x))
-# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+#elif defined(Q_PROCESSOR_X86)
+# if defined(Q_CC_CLANG) && defined(Q_CC_MSVC)
+# define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __)
+# else
+# define QT_COMPILER_SUPPORTS_HERE(x) ((__ ## x ## __) || QT_COMPILER_SUPPORTS(x))
+# endif
+# if defined(Q_CC_GNU)
/* GCC requires attributes for a function */
# define QT_FUNCTION_TARGET(x) __attribute__((__target__(QT_FUNCTION_TARGET_STRING_ ## x)))
# else
@@ -178,116 +133,179 @@
# define QT_FUNCTION_TARGET(x)
#endif
+#if defined(__SSE2__) && !defined(QT_COMPILER_SUPPORTS_SSE2) && !defined(QT_BOOTSTRAPPED)
+// Intrinsic support appears to be missing, so pretend these features don't exist
+# undef __SSE__
+# undef __SSE2__
+# undef __SSE3__
+# undef __SSSE3__
+# undef __SSE4_1__
+# undef __SSE4_2__
+# undef __AES__
+# undef __POPCNT__
+# undef __AVX__
+# undef __F16C__
+# undef __RDRND__
+# undef __AVX2__
+# undef __BMI__
+# undef __BMI2__
+# undef __FMA__
+# undef __MOVBE__
+# undef __RDSEED__
+# undef __AVX512F__
+# undef __AVX512ER__
+# undef __AVX512CD__
+# undef __AVX512PF__
+# undef __AVX512DQ__
+# undef __AVX512BW__
+# undef __AVX512VL__
+# undef __AVX512IFMA__
+# undef __AVX512VBMI__
+# undef __SHA__
+# undef __AVX512VBMI2__
+# undef __AVX512BITALG__
+# undef __AVX512VNNI__
+# undef __AVX512VPOPCNTDQ__
+# undef __GFNI__
+# undef __VAES__
+#endif
+
#ifdef Q_PROCESSOR_X86
/* -- x86 intrinsic support -- */
+# if defined(QT_COMPILER_SUPPORTS_RDSEED) && defined(Q_OS_QNX)
+// The compiler for QNX is missing the intrinsic
+# undef QT_COMPILER_SUPPORTS_RDSEED
+# endif
# if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2)
// MSVC doesn't define __SSE2__, so do it ourselves
# define __SSE__ 1
# endif
-# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
-// GCC 4.4 and Clang 2.8 added a few more intrinsics there
-# include <x86intrin.h>
-# endif
-
-# if defined(__SSE4_2__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
-// POPCNT instructions:
-// All processors that support SSE4.2 support POPCNT
-// (but neither MSVC nor the Intel compiler define this macro)
-# define __POPCNT__ 1
-# endif
-
-// AVX intrinsics
-# if defined(__AVX__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
-// AES, PCLMULQDQ instructions:
-// All processors that support AVX support PCLMULQDQ
-// (but neither MSVC nor the Intel compiler define this macro)
-# define __PCLMUL__ 1
+# if defined(Q_OS_WIN) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
+// 64-bit GCC on Windows does not support AVX, so we hack around it by forcing
+// it to emit unaligned loads & stores
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49001
+asm(
+ ".macro vmovapd args:vararg\n"
+ " vmovupd \\args\n"
+ ".endm\n"
+ ".macro vmovaps args:vararg\n"
+ " vmovups \\args\n"
+ ".endm\n"
+ ".macro vmovdqa args:vararg\n"
+ " vmovdqu \\args\n"
+ ".endm\n"
+ ".macro vmovdqa32 args:vararg\n"
+ " vmovdqu32 \\args\n"
+ ".endm\n"
+ ".macro vmovdqa64 args:vararg\n"
+ " vmovdqu64 \\args\n"
+ ".endm\n"
+);
# endif
-# if defined(__AVX2__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
-// F16C & RDRAND instructions:
-// All processors that support AVX2 support F16C & RDRAND:
-// (but neither MSVC nor the Intel compiler define these macros)
-# define __F16C__ 1
-# define __RDRND__ 1
-# endif
-
-# if defined(__BMI__) && !defined(__BMI2__) && defined(Q_CC_INTEL)
-// BMI2 instructions:
-// All processors that support BMI support BMI2 (and AVX2)
-// (but neither MSVC nor the Intel compiler define this macro)
-# define __BMI2__ 1
+# if defined(Q_CC_GNU) && !defined(Q_OS_WASM)
+// GCC 4.4 and Clang 2.8 added a few more intrinsics there
+# include <x86intrin.h>
# endif
+#ifdef Q_OS_WASM
+# include <immintrin.h>
+# endif
-# include "qsimd_x86_p.h"
+# include <QtCore/private/qsimd_x86_p.h>
-// Haswell sub-architecture
+// x86-64 sub-architecture version 3
//
// The Intel Core 4th generation was codenamed "Haswell" and introduced AVX2,
-// BMI1, BMI2, FMA, LZCNT, MOVBE, which makes it a good divider for a
-// sub-target for us. The first AMD processor with AVX2 support (Zen) has the
-// same features.
-//
-// macOS's fat binaries support the "x86_64h" sub-architecture and the GNU libc
-// ELF loader also supports a "haswell/" subdir (e.g., /usr/lib/haswell).
-# define QT_FUNCTION_TARGET_STRING_ARCH_HASWELL "arch=haswell"
-# if defined(__AVX2__) && defined(__BMI__) && defined(__BMI2__) && defined(__F16C__) && \
- defined(__FMA__) && defined(__LZCNT__) && defined(__RDRND__)
+// BMI1, BMI2, FMA, LZCNT, MOVBE. This feature set was chosen as the version 3
+// of the x86-64 ISA (x86-64-v3) and is supported by GCC and Clang. On systems
+// with the GNU libc, libraries with this feature can be installed on a
+// "glibc-hwcaps/x86-64-v3" subdir. macOS's fat binaries support the "x86_64h"
+// sub-architecture too.
+
+# if defined(__AVX2__)
+// List of features present with -march=x86-64-v3 and not architecturally
+// implied by __AVX2__
+# define ARCH_HASWELL_MACROS \
+ (__AVX2__ + __BMI__ + __BMI2__ + __F16C__ + __FMA__ + __LZCNT__ + __POPCNT__)
+# if ARCH_HASWELL_MACROS != 7
+# error "Please enable all x86-64-v3 extensions; you probably want to use -march=haswell or -march=x86-64-v3 instead of -mavx2"
+# endif
+static_assert(ARCH_HASWELL_MACROS, "Undeclared identifiers indicate which features are missing.");
# define __haswell__ 1
+# undef ARCH_HASWELL_MACROS
# endif
-// This constant does not include all CPU features found in a Haswell, only
-// those that we'd have optimized code for.
-// Note: must use Q_CONSTEXPR here, as this file may be compiled in C mode.
-QT_BEGIN_NAMESPACE
-static const quint64 CpuFeatureArchHaswell = 0
- | CpuFeatureSSE2
- | CpuFeatureSSE3
- | CpuFeatureSSSE3
- | CpuFeatureSSE4_1
- | CpuFeatureSSE4_2
- | CpuFeatureFMA
- | CpuFeaturePOPCNT
- | CpuFeatureAVX
- | CpuFeatureF16C
- | CpuFeatureAVX2
- | CpuFeatureBMI
- | CpuFeatureBMI2;
-QT_END_NAMESPACE
-
+// x86-64 sub-architecture version 4
+//
+// Similar to the above, x86-64-v4 matches the AVX512 variant of the Intel Core
+// 6th generation (codename "Skylake"). AMD Zen4 is the their first processor
+// with AVX512 support and it includes all of these too. The GNU libc subdir for
+// this is "glibc-hwcaps/x86-64-v4".
+//
+# define ARCH_SKX_MACROS (__AVX512F__ + __AVX512BW__ + __AVX512CD__ + __AVX512DQ__ + __AVX512VL__)
+# if ARCH_SKX_MACROS != 0
+# if ARCH_SKX_MACROS != 5
+# error "Please enable all x86-64-v4 extensions; you probably want to use -march=skylake-avx512 or -march=x86-64-v4 instead of -mavx512f"
+# endif
+static_assert(ARCH_SKX_MACROS, "Undeclared identifiers indicate which features are missing.");
+# define __skylake_avx512__ 1
+# endif
+# undef ARCH_SKX_MACROS
#endif /* Q_PROCESSOR_X86 */
-// Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html
-// This should be tweaked with an "upper version" of clang once we know which release fixes the
-// issue. At that point we can rely on __ARM_FEATURE_CRC32 again.
-#if defined(Q_CC_CLANG) && defined(Q_OS_DARWIN) && defined (__ARM_FEATURE_CRC32)
-# undef __ARM_FEATURE_CRC32
-#endif
-
// NEON intrinsics
// note: as of GCC 4.9, does not support function targets for ARM
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
+#if defined(Q_CC_CLANG)
+#define QT_FUNCTION_TARGET_STRING_NEON "neon"
+#else
#define QT_FUNCTION_TARGET_STRING_NEON "+neon" // unused: gcc doesn't support function targets on non-aarch64, and on Aarch64 NEON is always available.
+#endif
#ifndef __ARM_NEON__
// __ARM_NEON__ is not defined on AArch64, but we need it in our NEON detection.
#define __ARM_NEON__
#endif
+
+#ifndef Q_PROCESSOR_ARM_64 // vaddv is only available on Aarch64
+inline uint16_t vaddvq_u16(uint16x8_t v8)
+{
+ const uint64x2_t v2 = vpaddlq_u32(vpaddlq_u16(v8));
+ const uint64x1_t v1 = vadd_u64(vget_low_u64(v2), vget_high_u64(v2));
+ return vget_lane_u16(vreinterpret_u16_u64(v1), 0);
+}
+
+inline uint8_t vaddv_u8(uint8x8_t v8)
+{
+ const uint64x1_t v1 = vpaddl_u32(vpaddl_u16(vpaddl_u8(v8)));
+ return vget_lane_u8(vreinterpret_u8_u64(v1), 0);
+}
#endif
-// AArch64/ARM64
-#if defined(Q_PROCESSOR_ARM_V8) && defined(__ARM_FEATURE_CRC32)
-#if defined(Q_PROCESSOR_ARM_64)
-// only available on aarch64
-#define QT_FUNCTION_TARGET_STRING_CRC32 "+crc"
+
#endif
+
+#if defined(Q_PROCESSOR_ARM) && defined(__ARM_FEATURE_CRC32)
# include <arm_acle.h>
#endif
-#ifdef __cplusplus
-#include <qatomic.h>
-
-QT_BEGIN_NAMESPACE
+#if defined(Q_PROCESSOR_ARM_64)
+#if defined(Q_CC_CLANG)
+#define QT_FUNCTION_TARGET_STRING_AES "crypto"
+#define QT_FUNCTION_TARGET_STRING_CRC32 "crc"
+#elif defined(Q_CC_GNU)
+#define QT_FUNCTION_TARGET_STRING_AES "+crypto"
+#define QT_FUNCTION_TARGET_STRING_CRC32 "+crc"
+#endif
+#elif defined(Q_PROCESSOR_ARM_32)
+#if defined(Q_CC_CLANG)
+#define QT_FUNCTION_TARGET_STRING_AES "armv8-a,crypto"
+#define QT_FUNCTION_TARGET_STRING_CRC32 "armv8-a,crc"
+#elif defined(Q_CC_GNU)
+#define QT_FUNCTION_TARGET_STRING_AES "arch=armv8-a+crypto"
+#define QT_FUNCTION_TARGET_STRING_CRC32 "arch=armv8-a+crc"
+#endif
+#endif
#ifndef Q_PROCESSOR_X86
enum CPUFeatures {
@@ -295,22 +313,31 @@ enum CPUFeatures {
CpuFeatureNEON = 2,
CpuFeatureARM_NEON = CpuFeatureNEON,
CpuFeatureCRC32 = 4,
+ CpuFeatureAES = 8,
+ CpuFeatureARM_CRYPTO = CpuFeatureAES,
#elif defined(Q_PROCESSOR_MIPS)
CpuFeatureDSP = 2,
CpuFeatureDSPR2 = 4,
#endif
-
- // used only to indicate that the CPU detection was initialised
- QSimdInitialized = 1
};
-static const quint64 qCompilerCpuFeatures = 0
+static const uint64_t qCompilerCpuFeatures = 0
#if defined __ARM_NEON__
| CpuFeatureNEON
#endif
+#if !(defined(Q_OS_LINUX) && defined(Q_PROCESSOR_ARM_64))
+ // Yocto Project recipes enable Crypto extension for all ARMv8 configs,
+ // even for targets without the Crypto extension. That's wrong, but as
+ // the compiler never generates the code for them on their own, most
+ // code never notices the problem. But we would. By not setting the
+ // bits here, we force a runtime detection.
#if defined __ARM_FEATURE_CRC32
| CpuFeatureCRC32
#endif
+#if defined __ARM_FEATURE_CRYPTO
+ | CpuFeatureAES
+#endif
+#endif // Q_OS_LINUX && Q_PROCESSOR_ARM64
#if defined __mips_dsp
| CpuFeatureDSP
#endif
@@ -320,58 +347,71 @@ static const quint64 qCompilerCpuFeatures = 0
;
#endif
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
-extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1];
+#ifdef __cplusplus
+# include <atomic>
+# define Q_ATOMIC(T) std::atomic<T>
+QT_BEGIN_NAMESPACE
+using std::atomic_load_explicit;
+static constexpr auto memory_order_relaxed = std::memory_order_relaxed;
+extern "C" {
#else
-extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2];
+# include <stdatomic.h>
+# define Q_ATOMIC(T) _Atomic(T)
#endif
-Q_CORE_EXPORT quint64 qDetectCpuFeatures();
-#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) && !defined(QT_BOOTSTRAPPED)
-Q_CORE_EXPORT qsizetype qRandomCpu(void *, qsizetype) noexcept;
+#ifdef Q_PROCESSOR_X86
+typedef uint64_t QCpuFeatureType;
+static const QCpuFeatureType qCompilerCpuFeatures = _compilerCpuFeatures;
+static const QCpuFeatureType CpuFeatureArchHaswell = cpu_haswell;
+static const QCpuFeatureType CpuFeatureArchSkylakeAvx512 = cpu_skylake_avx512;
#else
-static inline qsizetype qRandomCpu(void *, qsizetype) noexcept
-{
- return 0;
-}
+typedef unsigned QCpuFeatureType;
#endif
+extern Q_CORE_EXPORT Q_ATOMIC(QCpuFeatureType) QT_MANGLE_NAMESPACE(qt_cpu_features)[1];
+Q_CORE_EXPORT uint64_t QT_MANGLE_NAMESPACE(qDetectCpuFeatures)();
-static inline quint64 qCpuFeatures()
+static inline uint64_t qCpuFeatures()
{
- quint64 features = qt_cpu_features[0].loadRelaxed();
-#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
- features |= quint64(qt_cpu_features[1].loadRelaxed()) << 32;
-#endif
- if (Q_UNLIKELY(features == 0)) {
- features = qDetectCpuFeatures();
- Q_ASSUME(features != 0);
+#ifdef QT_BOOTSTRAPPED
+ return qCompilerCpuFeatures; // no detection
+#else
+ quint64 features = atomic_load_explicit(QT_MANGLE_NAMESPACE(qt_cpu_features), memory_order_relaxed);
+ if (!QT_SUPPORTS_INIT_PRIORITY) {
+ if (Q_UNLIKELY(features == 0))
+ features = QT_MANGLE_NAMESPACE(qDetectCpuFeatures)();
}
return features;
+#endif
}
#define qCpuHasFeature(feature) (((qCompilerCpuFeatures & CpuFeature ## feature) == CpuFeature ## feature) \
|| ((qCpuFeatures() & CpuFeature ## feature) == CpuFeature ## feature))
-inline bool qHasHwrng()
+#ifdef __cplusplus
+} // extern "C"
+
+# if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) && !defined(QT_BOOTSTRAPPED)
+Q_CORE_EXPORT qsizetype qRandomCpu(void *, qsizetype) noexcept;
+
+static inline bool qHasHwrng()
{
-#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND)
return qCpuHasFeature(RDRND);
-#else
+}
+# else
+static inline qsizetype qRandomCpu(void *, qsizetype) noexcept
+{
+ return 0;
+}
+static inline bool qHasHwrng()
+{
return false;
-#endif
}
-
-#define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \
- for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i)
-
-#define ALIGNMENT_PROLOGUE_32BYTES(ptr, i, length) \
- for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((8 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x7)) & 0x7))); ++i)
+# endif
QT_END_NAMESPACE
#endif // __cplusplus
-#define SIMD_EPILOGUE(i, length, max) \
- for (int _i = 0; _i < max && i < length; ++i, ++_i)
+QT_WARNING_POP
#endif // QSIMD_P_H
diff --git a/src/corelib/global/qsimd_x86.cpp b/src/corelib/global/qsimd_x86.cpp
index be17f44c09..9a3bd80b39 100644
--- a/src/corelib/global/qsimd_x86.cpp
+++ b/src/corelib/global/qsimd_x86.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// This is a generated file. DO NOT EDIT.
-// Please see util/x86simdgen/generate.pl
-#include "qsimd_p.h"
+// Please see util/x86simdgen/README.md
+
+#include "qsimd_x86_p.h"
static const char features_string[] =
" sse2\0"
@@ -55,101 +19,202 @@ static const char features_string[] =
" f16c\0"
" rdrnd\0"
" bmi\0"
- " hle\0"
" avx2\0"
" bmi2\0"
- " rtm\0"
" avx512f\0"
" avx512dq\0"
" rdseed\0"
" avx512ifma\0"
- " avx512pf\0"
- " avx512er\0"
" avx512cd\0"
" sha\0"
" avx512bw\0"
" avx512vl\0"
" avx512vbmi\0"
+ " waitpkg\0"
" avx512vbmi2\0"
+ " shstk\0"
" gfni\0"
" vaes\0"
- " avx512vnni\0"
" avx512bitalg\0"
" avx512vpopcntdq\0"
- " avx5124nniw\0"
- " avx5124fmaps\0"
+ " hybrid\0"
+ " ibt\0"
+ " avx512fp16\0"
+ " raoint\0"
+ " cmpccxadd\0"
+ " avxifma\0"
+ " lam\0"
"\0";
-static const quint16 features_indices[] = {
- 306, 0, 6, 12, 19, 24, 32, 40,
- 47, 55, 60, 65, 71, 78, 83, 88,
- 94, 100, 105, 114, 124, 132, 144, 154,
- 164, 174, 179, 189, 199, 211, 224, 230,
- 236, 248, 262, 279, 292
+static const uint16_t features_indices[] = {
+ 0, 6, 12, 19, 24, 32, 40, 47,
+ 55, 60, 65, 71, 78, 83, 89, 95,
+ 104, 114, 122, 134, 144, 149, 159, 169,
+ 181, 190, 203, 210, 216, 222, 236, 253,
+ 261, 266, 278, 286, 297, 306,
};
enum X86CpuidLeaves {
- Leaf1ECX,
- Leaf1EDX,
- Leaf7_0EBX,
- Leaf7_0ECX,
- Leaf7_0EDX,
+ Leaf01EDX,
+ Leaf01ECX,
+ Leaf07_00EBX,
+ Leaf07_00ECX,
+ Leaf07_00EDX,
+ Leaf07_01EAX,
+ Leaf07_01EDX,
+ Leaf13_01EAX,
+ Leaf80000001hECX,
+ Leaf80000008hEBX,
X86CpuidMaxLeaf
};
-static const quint8 x86_locators[] = {
- Leaf1EDX*32 + 26, // sse2
- Leaf1ECX*32 + 0, // sse3
- Leaf1ECX*32 + 9, // ssse3
- Leaf1ECX*32 + 12, // fma
- Leaf1ECX*32 + 19, // sse4.1
- Leaf1ECX*32 + 20, // sse4.2
- Leaf1ECX*32 + 22, // movbe
- Leaf1ECX*32 + 23, // popcnt
- Leaf1ECX*32 + 25, // aes
- Leaf1ECX*32 + 28, // avx
- Leaf1ECX*32 + 29, // f16c
- Leaf1ECX*32 + 30, // rdrnd
- Leaf7_0EBX*32 + 3, // bmi
- Leaf7_0EBX*32 + 4, // hle
- Leaf7_0EBX*32 + 5, // avx2
- Leaf7_0EBX*32 + 8, // bmi2
- Leaf7_0EBX*32 + 11, // rtm
- Leaf7_0EBX*32 + 16, // avx512f
- Leaf7_0EBX*32 + 17, // avx512dq
- Leaf7_0EBX*32 + 18, // rdseed
- Leaf7_0EBX*32 + 21, // avx512ifma
- Leaf7_0EBX*32 + 26, // avx512pf
- Leaf7_0EBX*32 + 27, // avx512er
- Leaf7_0EBX*32 + 28, // avx512cd
- Leaf7_0EBX*32 + 29, // sha
- Leaf7_0EBX*32 + 30, // avx512bw
- Leaf7_0EBX*32 + 31, // avx512vl
- Leaf7_0ECX*32 + 1, // avx512vbmi
- Leaf7_0ECX*32 + 6, // avx512vbmi2
- Leaf7_0ECX*32 + 8, // gfni
- Leaf7_0ECX*32 + 9, // vaes
- Leaf7_0ECX*32 + 11, // avx512vnni
- Leaf7_0ECX*32 + 12, // avx512bitalg
- Leaf7_0ECX*32 + 14, // avx512vpopcntdq
- Leaf7_0EDX*32 + 2, // avx5124nniw
- Leaf7_0EDX*32 + 3 // avx5124fmaps
+static const uint16_t x86_locators[] = {
+ Leaf01EDX*32 + 26, // sse2
+ Leaf01ECX*32 + 0, // sse3
+ Leaf01ECX*32 + 9, // ssse3
+ Leaf01ECX*32 + 12, // fma
+ Leaf01ECX*32 + 19, // sse4.1
+ Leaf01ECX*32 + 20, // sse4.2
+ Leaf01ECX*32 + 22, // movbe
+ Leaf01ECX*32 + 23, // popcnt
+ Leaf01ECX*32 + 25, // aes
+ Leaf01ECX*32 + 28, // avx
+ Leaf01ECX*32 + 29, // f16c
+ Leaf01ECX*32 + 30, // rdrnd
+ Leaf07_00EBX*32 + 3, // bmi
+ Leaf07_00EBX*32 + 5, // avx2
+ Leaf07_00EBX*32 + 8, // bmi2
+ Leaf07_00EBX*32 + 16, // avx512f
+ Leaf07_00EBX*32 + 17, // avx512dq
+ Leaf07_00EBX*32 + 18, // rdseed
+ Leaf07_00EBX*32 + 21, // avx512ifma
+ Leaf07_00EBX*32 + 28, // avx512cd
+ Leaf07_00EBX*32 + 29, // sha
+ Leaf07_00EBX*32 + 30, // avx512bw
+ Leaf07_00EBX*32 + 31, // avx512vl
+ Leaf07_00ECX*32 + 1, // avx512vbmi
+ Leaf07_00ECX*32 + 5, // waitpkg
+ Leaf07_00ECX*32 + 6, // avx512vbmi2
+ Leaf07_00ECX*32 + 7, // shstk
+ Leaf07_00ECX*32 + 8, // gfni
+ Leaf07_00ECX*32 + 9, // vaes
+ Leaf07_00ECX*32 + 12, // avx512bitalg
+ Leaf07_00ECX*32 + 14, // avx512vpopcntdq
+ Leaf07_00EDX*32 + 15, // hybrid
+ Leaf07_00EDX*32 + 20, // ibt
+ Leaf07_00EDX*32 + 23, // avx512fp16
+ Leaf07_01EAX*32 + 3, // raoint
+ Leaf07_01EAX*32 + 6, // cmpccxadd
+ Leaf07_01EAX*32 + 23, // avxifma
+ Leaf07_01EAX*32 + 26, // lam
+};
+
+struct X86Architecture
+{
+ uint64_t features;
+ char name[17 + 1];
+};
+
+static const struct X86Architecture x86_architectures[] = {
+ { cpu_core2, "Core2" },
+ { cpu_westmere, "Westmere" },
+ { cpu_sandybridge, "Sandy Bridge" },
+ { cpu_silvermont, "Silvermont" },
+ { cpu_ivybridge, "Ivy Bridge" },
+ { cpu_goldmont, "Goldmont" },
+ { cpu_haswell, "Haswell" },
+ { cpu_broadwell, "Broadwell" },
+ { cpu_tremont, "Tremont" },
+ { cpu_skylake, "Skylake" },
+ { cpu_skylake_avx512, "Skylake (Avx512)" },
+ { cpu_cascadelake, "Cascade Lake" },
+ { cpu_cooperlake, "Cooper Lake" },
+ { cpu_cannonlake, "Cannon Lake" },
+ { cpu_gracemont, "Gracemont" },
+ { cpu_icelake_client, "Ice Lake (Client)" },
+ { cpu_icelake_server, "Ice Lake (Server)" },
+ { cpu_crestmont, "Crestmont" },
+ { cpu_tigerlake, "Tiger Lake" },
+ { cpu_clearwaterforest, "Clearwater Forest" },
+ { cpu_grandridge, "Grand Ridge" },
+ { cpu_raptorcove, "Raptor Cove" },
+ { cpu_redwoodcove, "Redwood Cove" },
+ { cpu_emeraldrapids, "Emerald Rapids" },
+ { cpu_graniterapids, "Granite Rapids" },
+};
+
+enum XSaveBits {
+ XSave_X87 = 0x0001, // X87 and MMX state
+ XSave_SseState = 0x0002, // SSE: 128 bits of XMM registers
+ XSave_Ymm_Hi128 = 0x0004, // AVX: high 128 bits in YMM registers
+ XSave_Bndregs = 0x0008, // Memory Protection Extensions
+ XSave_Bndcsr = 0x0010, // Memory Protection Extensions
+ XSave_OpMask = 0x0020, // AVX512: k0 through k7
+ XSave_Zmm_Hi256 = 0x0040, // AVX512: high 256 bits of ZMM0-15
+ XSave_Hi16_Zmm = 0x0080, // AVX512: all 512 bits of ZMM16-31
+ XSave_PTState = 0x0100, // Processor Trace
+ XSave_PKRUState = 0x0200, // Protection Key
+ XSave_CetUState = 0x0800, // CET: user mode
+ XSave_CetSState = 0x1000, // CET: supervisor mode
+ XSave_HdcState = 0x2000, // Hardware Duty Cycle
+ XSave_UintrState = 0x4000, // User Interrupts
+ XSave_HwpState = 0x10000, // Hardware P-State
+ XSave_Xtilecfg = 0x20000, // AMX: XTILECFG register
+ XSave_Xtiledata = 0x40000, // AMX: data in the tiles
+ XSave_AvxState = XSave_SseState | XSave_Ymm_Hi128,
+ XSave_MPXState = XSave_Bndregs | XSave_Bndcsr,
+ XSave_Avx512State = XSave_AvxState | XSave_OpMask | XSave_Zmm_Hi256 | XSave_Hi16_Zmm,
+ XSave_CetState = XSave_CetUState | XSave_CetSState,
+ XSave_AmxState = XSave_Xtilecfg | XSave_Xtiledata,
+};
+
+// List of features requiring XSave_AvxState
+static const uint64_t XSaveReq_AvxState = 0
+ | cpu_feature_fma
+ | cpu_feature_avx
+ | cpu_feature_f16c
+ | cpu_feature_avx2
+ | cpu_feature_avx512f
+ | cpu_feature_avx512dq
+ | cpu_feature_avx512ifma
+ | cpu_feature_avx512cd
+ | cpu_feature_avx512bw
+ | cpu_feature_avx512vl
+ | cpu_feature_avx512vbmi
+ | cpu_feature_avx512vbmi2
+ | cpu_feature_vaes
+ | cpu_feature_avx512bitalg
+ | cpu_feature_avx512vpopcntdq
+ | cpu_feature_avx512fp16
+ | cpu_feature_avxifma;
+
+// List of features requiring XSave_Avx512State
+static const uint64_t XSaveReq_Avx512State = 0
+ | cpu_feature_avx512f
+ | cpu_feature_avx512dq
+ | cpu_feature_avx512ifma
+ | cpu_feature_avx512cd
+ | cpu_feature_avx512bw
+ | cpu_feature_avx512vl
+ | cpu_feature_avx512vbmi
+ | cpu_feature_avx512vbmi2
+ | cpu_feature_avx512bitalg
+ | cpu_feature_avx512vpopcntdq
+ | cpu_feature_avx512fp16;
+
+// List of features requiring XSave_CetState
+static const uint64_t XSaveReq_CetState = 0
+ | cpu_feature_shstk;
+
+struct XSaveRequirementMapping
+{
+ uint64_t cpu_features;
+ uint64_t xsave_state;
+};
+
+static const struct XSaveRequirementMapping xsave_requirements[] = {
+ { XSaveReq_AvxState, XSave_AvxState },
+ { XSaveReq_Avx512State, XSave_Avx512State },
+ { XSaveReq_CetState, XSave_CetState },
};
-// List of AVX512 features (see detectProcessorFeatures())
-static const quint64 AllAVX512 = 0
- | CpuFeatureAVX512F
- | CpuFeatureAVX512DQ
- | CpuFeatureAVX512IFMA
- | CpuFeatureAVX512PF
- | CpuFeatureAVX512ER
- | CpuFeatureAVX512CD
- | CpuFeatureAVX512BW
- | CpuFeatureAVX512VL
- | CpuFeatureAVX512VBMI
- | CpuFeatureAVX512VBMI2
- | CpuFeatureAVX512VNNI
- | CpuFeatureAVX512BITALG
- | CpuFeatureAVX512VPOPCNTDQ
- | CpuFeatureAVX5124NNIW
- | CpuFeatureAVX5124FMAPS;
diff --git a/src/corelib/global/qsimd_x86_p.h b/src/corelib/global/qsimd_x86_p.h
index 82e3008a24..1ec89d0c6c 100644
--- a/src/corelib/global/qsimd_x86_p.h
+++ b/src/corelib/global/qsimd_x86_p.h
@@ -1,51 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// This is a generated file. DO NOT EDIT.
-// Please see util/x86simdgen/generate.pl
-#ifndef QSIMD_P_H
-# error "Please include <private/qsimd_p.h> instead"
-#endif
-#ifndef QSIMD_X86_P_H
-#define QSIMD_X86_P_H
-
-#include "qsimd_p.h"
+// Please see util/x86simdgen/README.md
//
// W A R N I N G
@@ -58,204 +14,536 @@
// We mean it.
//
-QT_BEGIN_NAMESPACE
+// This is a generated file. DO NOT EDIT.
+// Please see util/x86simdgen/README.md
+#ifndef QSIMD_X86_P_H
+#define QSIMD_X86_P_H
-// used only to indicate that the CPU detection was initialized
-#define QSimdInitialized (Q_UINT64_C(1) << 0)
+#include <stdint.h>
// in CPUID Leaf 1, EDX:
-#define CpuFeatureSSE2 (Q_UINT64_C(1) << 1)
-#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
+#define cpu_feature_sse2 (UINT64_C(1) << 0)
// in CPUID Leaf 1, ECX:
-#define CpuFeatureSSE3 (Q_UINT64_C(1) << 2)
+#define cpu_feature_sse3 (UINT64_C(1) << 1)
+#define cpu_feature_ssse3 (UINT64_C(1) << 2)
+#define cpu_feature_fma (UINT64_C(1) << 3)
+#define cpu_feature_sse4_1 (UINT64_C(1) << 4)
+#define cpu_feature_sse4_2 (UINT64_C(1) << 5)
+#define cpu_feature_movbe (UINT64_C(1) << 6)
+#define cpu_feature_popcnt (UINT64_C(1) << 7)
+#define cpu_feature_aes (UINT64_C(1) << 8)
+#define cpu_feature_avx (UINT64_C(1) << 9)
+#define cpu_feature_f16c (UINT64_C(1) << 10)
+#define cpu_feature_rdrnd (UINT64_C(1) << 11)
+
+// in CPUID Leaf 7, Sub-leaf 0, EBX:
+#define cpu_feature_bmi (UINT64_C(1) << 12)
+#define cpu_feature_avx2 (UINT64_C(1) << 13)
+#define cpu_feature_bmi2 (UINT64_C(1) << 14)
+#define cpu_feature_avx512f (UINT64_C(1) << 15)
+#define cpu_feature_avx512dq (UINT64_C(1) << 16)
+#define cpu_feature_rdseed (UINT64_C(1) << 17)
+#define cpu_feature_avx512ifma (UINT64_C(1) << 18)
+#define cpu_feature_avx512cd (UINT64_C(1) << 19)
+#define cpu_feature_sha (UINT64_C(1) << 20)
+#define cpu_feature_avx512bw (UINT64_C(1) << 21)
+#define cpu_feature_avx512vl (UINT64_C(1) << 22)
+
+// in CPUID Leaf 7, Sub-leaf 0, ECX:
+#define cpu_feature_avx512vbmi (UINT64_C(1) << 23)
+#define cpu_feature_waitpkg (UINT64_C(1) << 24)
+#define cpu_feature_avx512vbmi2 (UINT64_C(1) << 25)
+#define cpu_feature_shstk (UINT64_C(1) << 26)
+#define cpu_feature_gfni (UINT64_C(1) << 27)
+#define cpu_feature_vaes (UINT64_C(1) << 28)
+#define cpu_feature_avx512bitalg (UINT64_C(1) << 29)
+#define cpu_feature_avx512vpopcntdq (UINT64_C(1) << 30)
+
+// in CPUID Leaf 7, Sub-leaf 0, EDX:
+#define cpu_feature_hybrid (UINT64_C(1) << 31)
+#define cpu_feature_ibt (UINT64_C(1) << 32)
+#define cpu_feature_avx512fp16 (UINT64_C(1) << 33)
+
+// in CPUID Leaf 7, Sub-leaf 1, EAX:
+#define cpu_feature_raoint (UINT64_C(1) << 34)
+#define cpu_feature_cmpccxadd (UINT64_C(1) << 35)
+#define cpu_feature_avxifma (UINT64_C(1) << 36)
+#define cpu_feature_lam (UINT64_C(1) << 37)
+
+// CPU architectures
+#define cpu_x86_64 (0 \
+ | cpu_feature_sse2)
+#define cpu_core2 (cpu_x86_64 \
+ | cpu_feature_sse3 \
+ | cpu_feature_ssse3)
+#define cpu_nhm (cpu_core2 \
+ | cpu_feature_sse4_1 \
+ | cpu_feature_sse4_2 \
+ | cpu_feature_popcnt)
+#define cpu_wsm (cpu_nhm)
+#define cpu_snb (cpu_wsm \
+ | cpu_feature_avx)
+#define cpu_ivb (cpu_snb \
+ | cpu_feature_f16c \
+ | cpu_feature_rdrnd)
+#define cpu_hsw (cpu_ivb \
+ | cpu_feature_avx2 \
+ | cpu_feature_fma \
+ | cpu_feature_bmi \
+ | cpu_feature_bmi2 \
+ | cpu_feature_movbe)
+#define cpu_bdw (cpu_hsw \
+ | cpu_feature_rdseed)
+#define cpu_bdx (cpu_bdw)
+#define cpu_skl (cpu_bdw)
+#define cpu_skx (cpu_skl \
+ | cpu_feature_avx512f \
+ | cpu_feature_avx512dq \
+ | cpu_feature_avx512cd \
+ | cpu_feature_avx512bw \
+ | cpu_feature_avx512vl)
+#define cpu_clx (cpu_skx)
+#define cpu_cpx (cpu_clx)
+#define cpu_plc (cpu_skx \
+ | cpu_feature_avx512ifma \
+ | cpu_feature_avx512vbmi)
+#define cpu_snc (cpu_plc \
+ | cpu_feature_avx512vbmi2 \
+ | cpu_feature_gfni \
+ | cpu_feature_vaes \
+ | cpu_feature_avx512bitalg \
+ | cpu_feature_avx512vpopcntdq)
+#define cpu_wlc (cpu_snc \
+ | cpu_feature_shstk \
+ | cpu_feature_ibt)
+#define cpu_glc (cpu_wlc \
+ | cpu_feature_waitpkg)
+#define cpu_rpc (cpu_glc)
+#define cpu_rwc (cpu_rpc)
+#define cpu_slm (cpu_wsm \
+ | cpu_feature_rdrnd \
+ | cpu_feature_movbe)
+#define cpu_glm (cpu_slm \
+ | cpu_feature_rdseed)
+#define cpu_tnt (cpu_glm \
+ | cpu_feature_gfni \
+ | cpu_feature_waitpkg)
+#define cpu_grt (cpu_skl \
+ | cpu_feature_gfni \
+ | cpu_feature_vaes \
+ | cpu_feature_shstk \
+ | cpu_feature_ibt \
+ | cpu_feature_waitpkg)
+#define cpu_cmt (cpu_grt \
+ | cpu_feature_cmpccxadd \
+ | cpu_feature_avxifma)
+#define cpu_cnl (cpu_plc)
+#define cpu_icl (cpu_snc)
+#define cpu_tgl (cpu_wlc)
+#define cpu_adl (cpu_grt)
+#define cpu_rpl (cpu_grt)
+#define cpu_mtl (cpu_cmt)
+#define cpu_arl (cpu_cmt)
+#define cpu_lnl (cpu_cmt)
+#define cpu_icx (cpu_snc)
+#define cpu_spr (cpu_glc)
+#define cpu_emr (cpu_spr)
+#define cpu_gnr (cpu_glc)
+#define cpu_srf (cpu_cmt \
+ | cpu_feature_cmpccxadd \
+ | cpu_feature_avxifma)
+#define cpu_grr (cpu_srf \
+ | cpu_feature_raoint)
+#define cpu_cwf (cpu_srf)
+#define cpu_nehalem (cpu_nhm)
+#define cpu_westmere (cpu_wsm)
+#define cpu_sandybridge (cpu_snb)
+#define cpu_ivybridge (cpu_ivb)
+#define cpu_haswell (cpu_hsw)
+#define cpu_broadwell (cpu_bdw)
+#define cpu_skylake (cpu_skl)
+#define cpu_skylake_avx512 (cpu_skx)
+#define cpu_cascadelake (cpu_clx)
+#define cpu_cooperlake (cpu_cpx)
+#define cpu_palmcove (cpu_plc)
+#define cpu_cannonlake (cpu_cnl)
+#define cpu_sunnycove (cpu_snc)
+#define cpu_icelake_client (cpu_icl)
+#define cpu_icelake_server (cpu_icx)
+#define cpu_willowcove (cpu_wlc)
+#define cpu_tigerlake (cpu_tgl)
+#define cpu_goldencove (cpu_glc)
+#define cpu_alderlake (cpu_adl)
+#define cpu_raptorcove (cpu_rpc)
+#define cpu_raptorlake (cpu_rpl)
+#define cpu_redwoodcove (cpu_rwc)
+#define cpu_meteorlake (cpu_mtl)
+#define cpu_arrowlake (cpu_arl)
+#define cpu_lunarlake (cpu_lnl)
+#define cpu_sapphirerapids (cpu_spr)
+#define cpu_emeraldrapids (cpu_emr)
+#define cpu_graniterapids (cpu_gnr)
+#define cpu_silvermont (cpu_slm)
+#define cpu_goldmont (cpu_glm)
+#define cpu_tremont (cpu_tnt)
+#define cpu_gracemont (cpu_grt)
+#define cpu_crestmont (cpu_cmt)
+#define cpu_grandridge (cpu_grr)
+#define cpu_sierraforest (cpu_srf)
+#define cpu_clearwaterforest (cpu_cwf)
+
+// __attribute__ target strings for GCC and Clang
+#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
-#define CpuFeatureSSSE3 (Q_UINT64_C(1) << 3)
#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3"
-#define CpuFeatureFMA (Q_UINT64_C(1) << 4)
#define QT_FUNCTION_TARGET_STRING_FMA "fma"
-#define CpuFeatureSSE4_1 (Q_UINT64_C(1) << 5)
#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1"
-#define CpuFeatureSSE4_2 (Q_UINT64_C(1) << 6)
#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2"
-#define CpuFeatureMOVBE (Q_UINT64_C(1) << 7)
#define QT_FUNCTION_TARGET_STRING_MOVBE "movbe"
-#define CpuFeaturePOPCNT (Q_UINT64_C(1) << 8)
#define QT_FUNCTION_TARGET_STRING_POPCNT "popcnt"
-#define CpuFeatureAES (Q_UINT64_C(1) << 9)
#define QT_FUNCTION_TARGET_STRING_AES "aes,sse4.2"
-#define CpuFeatureAVX (Q_UINT64_C(1) << 10)
#define QT_FUNCTION_TARGET_STRING_AVX "avx"
-#define CpuFeatureF16C (Q_UINT64_C(1) << 11)
-#define QT_FUNCTION_TARGET_STRING_F16C "f16c"
-#define CpuFeatureRDRND (Q_UINT64_C(1) << 12)
+#define QT_FUNCTION_TARGET_STRING_F16C "f16c,avx"
#define QT_FUNCTION_TARGET_STRING_RDRND "rdrnd"
-
-// in CPUID Leaf 7, Sub-leaf 0, EBX:
-#define CpuFeatureBMI (Q_UINT64_C(1) << 13)
#define QT_FUNCTION_TARGET_STRING_BMI "bmi"
-#define CpuFeatureHLE (Q_UINT64_C(1) << 14)
-#define QT_FUNCTION_TARGET_STRING_HLE "hle"
-#define CpuFeatureAVX2 (Q_UINT64_C(1) << 15)
-#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2"
-#define CpuFeatureBMI2 (Q_UINT64_C(1) << 16)
+#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2,avx"
#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2"
-#define CpuFeatureRTM (Q_UINT64_C(1) << 17)
-#define QT_FUNCTION_TARGET_STRING_RTM "rtm"
-#define CpuFeatureAVX512F (Q_UINT64_C(1) << 18)
-#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f"
-#define CpuFeatureAVX512DQ (Q_UINT64_C(1) << 19)
-#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq"
-#define CpuFeatureRDSEED (Q_UINT64_C(1) << 20)
+#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f,avx"
+#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq,avx512f"
#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
-#define CpuFeatureAVX512IFMA (Q_UINT64_C(1) << 21)
-#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma"
-#define CpuFeatureAVX512PF (Q_UINT64_C(1) << 22)
-#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf"
-#define CpuFeatureAVX512ER (Q_UINT64_C(1) << 23)
-#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er"
-#define CpuFeatureAVX512CD (Q_UINT64_C(1) << 24)
-#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd"
-#define CpuFeatureSHA (Q_UINT64_C(1) << 25)
+#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma,avx512f"
+#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd,avx512f"
#define QT_FUNCTION_TARGET_STRING_SHA "sha"
-#define CpuFeatureAVX512BW (Q_UINT64_C(1) << 26)
-#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw"
-#define CpuFeatureAVX512VL (Q_UINT64_C(1) << 27)
-#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl"
-
-// in CPUID Leaf 7, Sub-leaf 0, ECX:
-#define CpuFeatureAVX512VBMI (Q_UINT64_C(1) << 28)
-#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi"
-#define CpuFeatureAVX512VBMI2 (Q_UINT64_C(1) << 29)
-#define QT_FUNCTION_TARGET_STRING_AVX512VBMI2 "avx512vbmi2"
-#define CpuFeatureGFNI (Q_UINT64_C(1) << 30)
+#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw,avx512f"
+#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl,avx512f"
+#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi,avx512f"
+#define QT_FUNCTION_TARGET_STRING_WAITPKG "waitpkg"
+#define QT_FUNCTION_TARGET_STRING_AVX512VBMI2 "avx512vbmi2,avx512f"
+#define QT_FUNCTION_TARGET_STRING_SHSTK "shstk"
#define QT_FUNCTION_TARGET_STRING_GFNI "gfni"
-#define CpuFeatureVAES (Q_UINT64_C(1) << 31)
-#define QT_FUNCTION_TARGET_STRING_VAES "vaes"
-#define CpuFeatureAVX512VNNI (Q_UINT64_C(1) << 32)
-#define QT_FUNCTION_TARGET_STRING_AVX512VNNI "avx512vnni"
-#define CpuFeatureAVX512BITALG (Q_UINT64_C(1) << 33)
-#define QT_FUNCTION_TARGET_STRING_AVX512BITALG "avx512bitalg"
-#define CpuFeatureAVX512VPOPCNTDQ (Q_UINT64_C(1) << 34)
-#define QT_FUNCTION_TARGET_STRING_AVX512VPOPCNTDQ "avx512vpopcntdq"
-
-// in CPUID Leaf 7, Sub-leaf 0, EDX:
-#define CpuFeatureAVX5124NNIW (Q_UINT64_C(1) << 35)
-#define QT_FUNCTION_TARGET_STRING_AVX5124NNIW "avx5124nniw"
-#define CpuFeatureAVX5124FMAPS (Q_UINT64_C(1) << 36)
-#define QT_FUNCTION_TARGET_STRING_AVX5124FMAPS "avx5124fmaps"
+#define QT_FUNCTION_TARGET_STRING_VAES "vaes,avx2,avx,aes"
+#define QT_FUNCTION_TARGET_STRING_AVX512BITALG "avx512bitalg,avx512f"
+#define QT_FUNCTION_TARGET_STRING_AVX512VPOPCNTDQ "avx512vpopcntdq,avx512f"
+#define QT_FUNCTION_TARGET_STRING_HYBRID "hybrid"
+#define QT_FUNCTION_TARGET_STRING_IBT "ibt"
+#define QT_FUNCTION_TARGET_STRING_AVX512FP16 "avx512fp16,avx512f,f16c"
+#define QT_FUNCTION_TARGET_STRING_RAOINT "raoint"
+#define QT_FUNCTION_TARGET_STRING_CMPCCXADD "cmpccxadd"
+#define QT_FUNCTION_TARGET_STRING_AVXIFMA "avxifma,avx"
+#define QT_FUNCTION_TARGET_STRING_LAM "lam"
+#define QT_FUNCTION_TARGET_STRING_ARCH_X86_64 "sse2"
+#define QT_FUNCTION_TARGET_STRING_ARCH_CORE2 QT_FUNCTION_TARGET_STRING_ARCH_X86_64 ",sse3,ssse3,cx16"
+#define QT_FUNCTION_TARGET_STRING_ARCH_NHM QT_FUNCTION_TARGET_STRING_ARCH_CORE2 ",sse4.1,sse4.2,popcnt"
+#define QT_FUNCTION_TARGET_STRING_ARCH_WSM QT_FUNCTION_TARGET_STRING_ARCH_NHM
+#define QT_FUNCTION_TARGET_STRING_ARCH_SNB QT_FUNCTION_TARGET_STRING_ARCH_WSM ",avx"
+#define QT_FUNCTION_TARGET_STRING_ARCH_IVB QT_FUNCTION_TARGET_STRING_ARCH_SNB ",f16c,rdrnd,fsgsbase"
+#define QT_FUNCTION_TARGET_STRING_ARCH_HSW QT_FUNCTION_TARGET_STRING_ARCH_IVB ",avx2,fma,bmi,bmi2,lzcnt,movbe"
+#define QT_FUNCTION_TARGET_STRING_ARCH_BDW QT_FUNCTION_TARGET_STRING_ARCH_HSW ",adx,rdseed"
+#define QT_FUNCTION_TARGET_STRING_ARCH_BDX QT_FUNCTION_TARGET_STRING_ARCH_BDW
+#define QT_FUNCTION_TARGET_STRING_ARCH_SKL QT_FUNCTION_TARGET_STRING_ARCH_BDW ",xsavec,xsaves"
+#define QT_FUNCTION_TARGET_STRING_ARCH_SKX QT_FUNCTION_TARGET_STRING_ARCH_SKL ",avx512f,avx512dq,avx512cd,avx512bw,avx512vl"
+#define QT_FUNCTION_TARGET_STRING_ARCH_CLX QT_FUNCTION_TARGET_STRING_ARCH_SKX ",avx512vnni"
+#define QT_FUNCTION_TARGET_STRING_ARCH_CPX QT_FUNCTION_TARGET_STRING_ARCH_CLX ",avx512bf16"
+#define QT_FUNCTION_TARGET_STRING_ARCH_PLC QT_FUNCTION_TARGET_STRING_ARCH_SKX ",avx512ifma,avx512vbmi"
+#define QT_FUNCTION_TARGET_STRING_ARCH_SNC QT_FUNCTION_TARGET_STRING_ARCH_PLC ",avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512vpopcntdq"
+#define QT_FUNCTION_TARGET_STRING_ARCH_WLC QT_FUNCTION_TARGET_STRING_ARCH_SNC ",shstk,movdiri,movdir64b,ibt,keylocker"
+#define QT_FUNCTION_TARGET_STRING_ARCH_GLC QT_FUNCTION_TARGET_STRING_ARCH_WLC ",avx512bf16,avxvnni,cldemote,waitpkg,serialize,uintr"
+#define QT_FUNCTION_TARGET_STRING_ARCH_RPC QT_FUNCTION_TARGET_STRING_ARCH_GLC
+#define QT_FUNCTION_TARGET_STRING_ARCH_RWC QT_FUNCTION_TARGET_STRING_ARCH_RPC ",prefetchiti"
+#define QT_FUNCTION_TARGET_STRING_ARCH_SLM QT_FUNCTION_TARGET_STRING_ARCH_WSM ",rdrnd,movbe"
+#define QT_FUNCTION_TARGET_STRING_ARCH_GLM QT_FUNCTION_TARGET_STRING_ARCH_SLM ",fsgsbase,rdseed,lzcnt,xsavec,xsaves"
+#define QT_FUNCTION_TARGET_STRING_ARCH_TNT QT_FUNCTION_TARGET_STRING_ARCH_GLM ",clwb,gfni,cldemote,waitpkg,movdiri,movdir64b"
+#define QT_FUNCTION_TARGET_STRING_ARCH_GRT QT_FUNCTION_TARGET_STRING_ARCH_SKL ",avxvnni,gfni,vaes,vpclmulqdq,serialize,shstk,cldemote,movdiri,movdir64b,ibt,waitpkg,keylocker"
+#define QT_FUNCTION_TARGET_STRING_ARCH_CMT QT_FUNCTION_TARGET_STRING_ARCH_GRT ",cmpccxadd,avxifma,avxneconvert,avxvnniint8"
+#define QT_FUNCTION_TARGET_STRING_ARCH_CNL QT_FUNCTION_TARGET_STRING_ARCH_PLC
+#define QT_FUNCTION_TARGET_STRING_ARCH_ICL QT_FUNCTION_TARGET_STRING_ARCH_SNC
+#define QT_FUNCTION_TARGET_STRING_ARCH_TGL QT_FUNCTION_TARGET_STRING_ARCH_WLC
+#define QT_FUNCTION_TARGET_STRING_ARCH_ADL QT_FUNCTION_TARGET_STRING_ARCH_GRT
+#define QT_FUNCTION_TARGET_STRING_ARCH_RPL QT_FUNCTION_TARGET_STRING_ARCH_GRT
+#define QT_FUNCTION_TARGET_STRING_ARCH_MTL QT_FUNCTION_TARGET_STRING_ARCH_CMT
+#define QT_FUNCTION_TARGET_STRING_ARCH_ARL QT_FUNCTION_TARGET_STRING_ARCH_CMT
+#define QT_FUNCTION_TARGET_STRING_ARCH_LNL QT_FUNCTION_TARGET_STRING_ARCH_CMT
+#define QT_FUNCTION_TARGET_STRING_ARCH_ICX QT_FUNCTION_TARGET_STRING_ARCH_SNC ",pconfig"
+#define QT_FUNCTION_TARGET_STRING_ARCH_SPR QT_FUNCTION_TARGET_STRING_ARCH_GLC ",pconfig,amx-tile,amx-bf16,amx-int8"
+#define QT_FUNCTION_TARGET_STRING_ARCH_EMR QT_FUNCTION_TARGET_STRING_ARCH_SPR
+#define QT_FUNCTION_TARGET_STRING_ARCH_GNR QT_FUNCTION_TARGET_STRING_ARCH_GLC ",pconfig,amx-tile,amx-bf16,amx-int8,amx-fp16,amx-complex"
+#define QT_FUNCTION_TARGET_STRING_ARCH_SRF QT_FUNCTION_TARGET_STRING_ARCH_CMT ",cmpccxadd,avxifma,avxneconvert,avxvnniint8"
+#define QT_FUNCTION_TARGET_STRING_ARCH_GRR QT_FUNCTION_TARGET_STRING_ARCH_SRF ",raoint"
+#define QT_FUNCTION_TARGET_STRING_ARCH_CWF QT_FUNCTION_TARGET_STRING_ARCH_SRF
+#define QT_FUNCTION_TARGET_STRING_ARCH_NEHALEM QT_FUNCTION_TARGET_STRING_ARCH_NHM
+#define QT_FUNCTION_TARGET_STRING_ARCH_WESTMERE QT_FUNCTION_TARGET_STRING_ARCH_WSM
+#define QT_FUNCTION_TARGET_STRING_ARCH_SANDYBRIDGE QT_FUNCTION_TARGET_STRING_ARCH_SNB
+#define QT_FUNCTION_TARGET_STRING_ARCH_IVYBRIDGE QT_FUNCTION_TARGET_STRING_ARCH_IVB
+#define QT_FUNCTION_TARGET_STRING_ARCH_HASWELL QT_FUNCTION_TARGET_STRING_ARCH_HSW
+#define QT_FUNCTION_TARGET_STRING_ARCH_BROADWELL QT_FUNCTION_TARGET_STRING_ARCH_BDW
+#define QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE QT_FUNCTION_TARGET_STRING_ARCH_SKL
+#define QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 QT_FUNCTION_TARGET_STRING_ARCH_SKX
+#define QT_FUNCTION_TARGET_STRING_ARCH_CASCADELAKE QT_FUNCTION_TARGET_STRING_ARCH_CLX
+#define QT_FUNCTION_TARGET_STRING_ARCH_COOPERLAKE QT_FUNCTION_TARGET_STRING_ARCH_CPX
+#define QT_FUNCTION_TARGET_STRING_ARCH_PALMCOVE QT_FUNCTION_TARGET_STRING_ARCH_PLC
+#define QT_FUNCTION_TARGET_STRING_ARCH_CANNONLAKE QT_FUNCTION_TARGET_STRING_ARCH_CNL
+#define QT_FUNCTION_TARGET_STRING_ARCH_SUNNYCOVE QT_FUNCTION_TARGET_STRING_ARCH_SNC
+#define QT_FUNCTION_TARGET_STRING_ARCH_ICELAKE_CLIENT QT_FUNCTION_TARGET_STRING_ARCH_ICL
+#define QT_FUNCTION_TARGET_STRING_ARCH_ICELAKE_SERVER QT_FUNCTION_TARGET_STRING_ARCH_ICX
+#define QT_FUNCTION_TARGET_STRING_ARCH_WILLOWCOVE QT_FUNCTION_TARGET_STRING_ARCH_WLC
+#define QT_FUNCTION_TARGET_STRING_ARCH_TIGERLAKE QT_FUNCTION_TARGET_STRING_ARCH_TGL
+#define QT_FUNCTION_TARGET_STRING_ARCH_GOLDENCOVE QT_FUNCTION_TARGET_STRING_ARCH_GLC
+#define QT_FUNCTION_TARGET_STRING_ARCH_ALDERLAKE QT_FUNCTION_TARGET_STRING_ARCH_ADL
+#define QT_FUNCTION_TARGET_STRING_ARCH_RAPTORCOVE QT_FUNCTION_TARGET_STRING_ARCH_RPC
+#define QT_FUNCTION_TARGET_STRING_ARCH_RAPTORLAKE QT_FUNCTION_TARGET_STRING_ARCH_RPL
+#define QT_FUNCTION_TARGET_STRING_ARCH_REDWOODCOVE QT_FUNCTION_TARGET_STRING_ARCH_RWC
+#define QT_FUNCTION_TARGET_STRING_ARCH_METEORLAKE QT_FUNCTION_TARGET_STRING_ARCH_MTL
+#define QT_FUNCTION_TARGET_STRING_ARCH_ARROWLAKE QT_FUNCTION_TARGET_STRING_ARCH_ARL
+#define QT_FUNCTION_TARGET_STRING_ARCH_LUNARLAKE QT_FUNCTION_TARGET_STRING_ARCH_LNL
+#define QT_FUNCTION_TARGET_STRING_ARCH_SAPPHIRERAPIDS QT_FUNCTION_TARGET_STRING_ARCH_SPR
+#define QT_FUNCTION_TARGET_STRING_ARCH_EMERALDRAPIDS QT_FUNCTION_TARGET_STRING_ARCH_EMR
+#define QT_FUNCTION_TARGET_STRING_ARCH_GRANITERAPIDS QT_FUNCTION_TARGET_STRING_ARCH_GNR
+#define QT_FUNCTION_TARGET_STRING_ARCH_SILVERMONT QT_FUNCTION_TARGET_STRING_ARCH_SLM
+#define QT_FUNCTION_TARGET_STRING_ARCH_GOLDMONT QT_FUNCTION_TARGET_STRING_ARCH_GLM
+#define QT_FUNCTION_TARGET_STRING_ARCH_TREMONT QT_FUNCTION_TARGET_STRING_ARCH_TNT
+#define QT_FUNCTION_TARGET_STRING_ARCH_GRACEMONT QT_FUNCTION_TARGET_STRING_ARCH_GRT
+#define QT_FUNCTION_TARGET_STRING_ARCH_CRESTMONT QT_FUNCTION_TARGET_STRING_ARCH_CMT
+#define QT_FUNCTION_TARGET_STRING_ARCH_GRANDRIDGE QT_FUNCTION_TARGET_STRING_ARCH_GRR
+#define QT_FUNCTION_TARGET_STRING_ARCH_SIERRAFOREST QT_FUNCTION_TARGET_STRING_ARCH_SRF
+#define QT_FUNCTION_TARGET_STRING_ARCH_CLEARWATERFOREST QT_FUNCTION_TARGET_STRING_ARCH_CWF
-static const quint64 qCompilerCpuFeatures = 0
+static const uint64_t _compilerCpuFeatures = 0
#ifdef __SSE2__
- | CpuFeatureSSE2
+ | cpu_feature_sse2
#endif
#ifdef __SSE3__
- | CpuFeatureSSE3
+ | cpu_feature_sse3
#endif
#ifdef __SSSE3__
- | CpuFeatureSSSE3
+ | cpu_feature_ssse3
#endif
#ifdef __FMA__
- | CpuFeatureFMA
+ | cpu_feature_fma
#endif
#ifdef __SSE4_1__
- | CpuFeatureSSE4_1
+ | cpu_feature_sse4_1
#endif
#ifdef __SSE4_2__
- | CpuFeatureSSE4_2
+ | cpu_feature_sse4_2
#endif
#ifdef __MOVBE__
- | CpuFeatureMOVBE
+ | cpu_feature_movbe
#endif
#ifdef __POPCNT__
- | CpuFeaturePOPCNT
+ | cpu_feature_popcnt
#endif
#ifdef __AES__
- | CpuFeatureAES
+ | cpu_feature_aes
#endif
#ifdef __AVX__
- | CpuFeatureAVX
+ | cpu_feature_avx
#endif
#ifdef __F16C__
- | CpuFeatureF16C
+ | cpu_feature_f16c
#endif
#ifdef __RDRND__
- | CpuFeatureRDRND
+ | cpu_feature_rdrnd
#endif
#ifdef __BMI__
- | CpuFeatureBMI
-#endif
-#ifdef __HLE__
- | CpuFeatureHLE
+ | cpu_feature_bmi
#endif
#ifdef __AVX2__
- | CpuFeatureAVX2
+ | cpu_feature_avx2
#endif
#ifdef __BMI2__
- | CpuFeatureBMI2
-#endif
-#ifdef __RTM__
- | CpuFeatureRTM
+ | cpu_feature_bmi2
#endif
#ifdef __AVX512F__
- | CpuFeatureAVX512F
+ | cpu_feature_avx512f
#endif
#ifdef __AVX512DQ__
- | CpuFeatureAVX512DQ
+ | cpu_feature_avx512dq
#endif
#ifdef __RDSEED__
- | CpuFeatureRDSEED
+ | cpu_feature_rdseed
#endif
#ifdef __AVX512IFMA__
- | CpuFeatureAVX512IFMA
-#endif
-#ifdef __AVX512PF__
- | CpuFeatureAVX512PF
-#endif
-#ifdef __AVX512ER__
- | CpuFeatureAVX512ER
+ | cpu_feature_avx512ifma
#endif
#ifdef __AVX512CD__
- | CpuFeatureAVX512CD
+ | cpu_feature_avx512cd
#endif
#ifdef __SHA__
- | CpuFeatureSHA
+ | cpu_feature_sha
#endif
#ifdef __AVX512BW__
- | CpuFeatureAVX512BW
+ | cpu_feature_avx512bw
#endif
#ifdef __AVX512VL__
- | CpuFeatureAVX512VL
+ | cpu_feature_avx512vl
#endif
#ifdef __AVX512VBMI__
- | CpuFeatureAVX512VBMI
+ | cpu_feature_avx512vbmi
+#endif
+#ifdef __WAITPKG__
+ | cpu_feature_waitpkg
#endif
#ifdef __AVX512VBMI2__
- | CpuFeatureAVX512VBMI2
+ | cpu_feature_avx512vbmi2
+#endif
+#ifdef __SHSTK__
+ | cpu_feature_shstk
#endif
#ifdef __GFNI__
- | CpuFeatureGFNI
+ | cpu_feature_gfni
#endif
#ifdef __VAES__
- | CpuFeatureVAES
-#endif
-#ifdef __AVX512VNNI__
- | CpuFeatureAVX512VNNI
+ | cpu_feature_vaes
#endif
#ifdef __AVX512BITALG__
- | CpuFeatureAVX512BITALG
+ | cpu_feature_avx512bitalg
#endif
#ifdef __AVX512VPOPCNTDQ__
- | CpuFeatureAVX512VPOPCNTDQ
+ | cpu_feature_avx512vpopcntdq
+#endif
+#ifdef __HYBRID__
+ | cpu_feature_hybrid
+#endif
+#ifdef __IBT__
+ | cpu_feature_ibt
#endif
-#ifdef __AVX5124NNIW__
- | CpuFeatureAVX5124NNIW
+#ifdef __AVX512FP16__
+ | cpu_feature_avx512fp16
#endif
-#ifdef __AVX5124FMAPS__
- | CpuFeatureAVX5124FMAPS
+#ifdef __RAOINT__
+ | cpu_feature_raoint
+#endif
+#ifdef __CMPCCXADD__
+ | cpu_feature_cmpccxadd
+#endif
+#ifdef __AVXIFMA__
+ | cpu_feature_avxifma
+#endif
+#ifdef __LAM__
+ | cpu_feature_lam
#endif
;
-QT_END_NAMESPACE
+#if (defined __cplusplus) && __cplusplus >= 201103L
+enum X86CpuFeatures : uint64_t {
+ CpuFeatureSSE2 = cpu_feature_sse2, ///< Streaming SIMD Extensions 2
+ CpuFeatureSSE3 = cpu_feature_sse3, ///< Streaming SIMD Extensions 3
+ CpuFeatureSSSE3 = cpu_feature_ssse3, ///< Supplemental Streaming SIMD Extensions 3
+ CpuFeatureFMA = cpu_feature_fma, ///< Fused Multiply-Add
+ CpuFeatureSSE4_1 = cpu_feature_sse4_1, ///< Streaming SIMD Extensions 4.1
+ CpuFeatureSSE4_2 = cpu_feature_sse4_2, ///< Streaming SIMD Extensions 4.2
+ CpuFeatureMOVBE = cpu_feature_movbe, ///< MOV Big Endian
+ CpuFeaturePOPCNT = cpu_feature_popcnt, ///< Population count
+ CpuFeatureAES = cpu_feature_aes, ///< Advenced Encryption Standard
+ CpuFeatureAVX = cpu_feature_avx, ///< Advanced Vector Extensions
+ CpuFeatureF16C = cpu_feature_f16c, ///< 16-bit Float Conversion
+ CpuFeatureRDRND = cpu_feature_rdrnd, ///< Random number generator
+ CpuFeatureBMI = cpu_feature_bmi, ///< Bit Manipulation Instructions
+ CpuFeatureAVX2 = cpu_feature_avx2, ///< Advanced Vector Extensions 2
+ CpuFeatureBMI2 = cpu_feature_bmi2, ///< Bit Manipulation Instructions 2
+ CpuFeatureAVX512F = cpu_feature_avx512f, ///< AVX512 Foundation
+ CpuFeatureAVX512DQ = cpu_feature_avx512dq, ///< AVX512 Double & Quadword
+ CpuFeatureRDSEED = cpu_feature_rdseed, ///< Random number generator for seeding
+ CpuFeatureAVX512IFMA = cpu_feature_avx512ifma, ///< AVX512 Integer Fused Multiply-Add
+ CpuFeatureAVX512CD = cpu_feature_avx512cd, ///< AVX512 Conflict Detection
+ CpuFeatureSHA = cpu_feature_sha, ///< SHA-1 and SHA-256 instructions
+ CpuFeatureAVX512BW = cpu_feature_avx512bw, ///< AVX512 Byte & Word
+ CpuFeatureAVX512VL = cpu_feature_avx512vl, ///< AVX512 Vector Length
+ CpuFeatureAVX512VBMI = cpu_feature_avx512vbmi, ///< AVX512 Vector Byte Manipulation Instructions
+ CpuFeatureWAITPKG = cpu_feature_waitpkg, ///< User-Level Monitor / Wait
+ CpuFeatureAVX512VBMI2 = cpu_feature_avx512vbmi2, ///< AVX512 Vector Byte Manipulation Instructions 2
+ CpuFeatureSHSTK = cpu_feature_shstk, ///< Control Flow Enforcement Technology Shadow Stack
+ CpuFeatureGFNI = cpu_feature_gfni, ///< Galois Field new instructions
+ CpuFeatureVAES = cpu_feature_vaes, ///< 256- and 512-bit AES
+ CpuFeatureAVX512BITALG = cpu_feature_avx512bitalg, ///< AVX512 Bit Algorithms
+ CpuFeatureAVX512VPOPCNTDQ = cpu_feature_avx512vpopcntdq, ///< AVX512 Population Count
+ CpuFeatureHYBRID = cpu_feature_hybrid, ///< Hybrid processor
+ CpuFeatureIBT = cpu_feature_ibt, ///< Control Flow Enforcement Technology Indirect Branch Tracking
+ CpuFeatureAVX512FP16 = cpu_feature_avx512fp16, ///< AVX512 16-bit Floating Point
+ CpuFeatureRAOINT = cpu_feature_raoint, ///< Remote Atomic Operations, Integer
+ CpuFeatureCMPCCXADD = cpu_feature_cmpccxadd, ///< CMPccXADD instructions
+ CpuFeatureAVXIFMA = cpu_feature_avxifma, ///< AVX-IFMA instructions
+ CpuFeatureLAM = cpu_feature_lam, ///< Linear Address Masking
+}; // enum X86CpuFeatures
+
+enum X86CpuArchitectures : uint64_t {
+ CpuArchx8664 = cpu_x86_64,
+ CpuArchCore2 = cpu_core2,
+ CpuArchNHM = cpu_nhm,
+ CpuArchWSM = cpu_wsm,
+ CpuArchSNB = cpu_snb,
+ CpuArchIVB = cpu_ivb,
+ CpuArchHSW = cpu_hsw, ///< hle,rtm
+ CpuArchBDW = cpu_bdw,
+ CpuArchBDX = cpu_bdx,
+ CpuArchSKL = cpu_skl,
+ CpuArchSKX = cpu_skx, ///< clwb
+ CpuArchCLX = cpu_clx,
+ CpuArchCPX = cpu_cpx,
+ CpuArchPLC = cpu_plc, ///< sha
+ CpuArchSNC = cpu_snc, ///< fsrm,rdpid
+ CpuArchWLC = cpu_wlc, ///< avx512vp2intersect
+ CpuArchGLC = cpu_glc, ///< tsxldtrk
+ CpuArchRPC = cpu_rpc,
+ CpuArchRWC = cpu_rwc,
+ CpuArchSLM = cpu_slm,
+ CpuArchGLM = cpu_glm,
+ CpuArchTNT = cpu_tnt,
+ CpuArchGRT = cpu_grt, ///< rdpid
+ CpuArchCMT = cpu_cmt,
+ CpuArchCNL = cpu_cnl,
+ CpuArchICL = cpu_icl,
+ CpuArchTGL = cpu_tgl,
+ CpuArchADL = cpu_adl,
+ CpuArchRPL = cpu_rpl,
+ CpuArchMTL = cpu_mtl,
+ CpuArchARL = cpu_arl,
+ CpuArchLNL = cpu_lnl,
+ CpuArchICX = cpu_icx,
+ CpuArchSPR = cpu_spr,
+ CpuArchEMR = cpu_emr,
+ CpuArchGNR = cpu_gnr,
+ CpuArchSRF = cpu_srf,
+ CpuArchGRR = cpu_grr,
+ CpuArchCWF = cpu_cwf,
+ CpuArchNehalem = cpu_nehalem, ///< Intel Core i3/i5/i7
+ CpuArchWestmere = cpu_westmere, ///< Intel Core i3/i5/i7
+ CpuArchSandyBridge = cpu_sandybridge, ///< Second Generation Intel Core i3/i5/i7
+ CpuArchIvyBridge = cpu_ivybridge, ///< Third Generation Intel Core i3/i5/i7
+ CpuArchHaswell = cpu_haswell, ///< Fourth Generation Intel Core i3/i5/i7
+ CpuArchBroadwell = cpu_broadwell, ///< Fifth Generation Intel Core i3/i5/i7
+ CpuArchSkylake = cpu_skylake, ///< Sixth Generation Intel Core i3/i5/i7
+ CpuArchSkylakeAvx512 = cpu_skylake_avx512, ///< Intel Xeon Scalable
+ CpuArchCascadeLake = cpu_cascadelake, ///< Second Generation Intel Xeon Scalable
+ CpuArchCooperLake = cpu_cooperlake, ///< Third Generation Intel Xeon Scalable
+ CpuArchPalmCove = cpu_palmcove,
+ CpuArchCannonLake = cpu_cannonlake, ///< Intel Core i3-8121U
+ CpuArchSunnyCove = cpu_sunnycove,
+ CpuArchIceLakeClient = cpu_icelake_client, ///< Tenth Generation Intel Core i3/i5/i7
+ CpuArchIceLakeServer = cpu_icelake_server, ///< Third Generation Intel Xeon Scalable
+ CpuArchWillowCove = cpu_willowcove,
+ CpuArchTigerLake = cpu_tigerlake, ///< Eleventh Generation Intel Core i3/i5/i7
+ CpuArchGoldenCove = cpu_goldencove,
+ CpuArchAlderLake = cpu_alderlake, ///< Twelfth Generation Intel Core
+ CpuArchRaptorCove = cpu_raptorcove,
+ CpuArchRaptorLake = cpu_raptorlake, ///< Thirteenth Generation Intel Core
+ CpuArchRedwoodCove = cpu_redwoodcove,
+ CpuArchMeteorLake = cpu_meteorlake,
+ CpuArchArrowLake = cpu_arrowlake,
+ CpuArchLunarLake = cpu_lunarlake,
+ CpuArchSapphireRapids = cpu_sapphirerapids, ///< Fourth Generation Intel Xeon Scalable
+ CpuArchEmeraldRapids = cpu_emeraldrapids, ///< Fifth Generation Intel Xeon Scalable
+ CpuArchGraniteRapids = cpu_graniterapids,
+ CpuArchSilvermont = cpu_silvermont,
+ CpuArchGoldmont = cpu_goldmont,
+ CpuArchTremont = cpu_tremont,
+ CpuArchGracemont = cpu_gracemont,
+ CpuArchCrestmont = cpu_crestmont,
+ CpuArchGrandRidge = cpu_grandridge,
+ CpuArchSierraForest = cpu_sierraforest,
+ CpuArchClearwaterForest = cpu_clearwaterforest,
+}; // enum X86cpuArchitectures
+#endif /* C++11 */
-#endif // QSIMD_X86_P_H
+#endif /* QSIMD_X86_P_H */
diff --git a/src/corelib/global/qswap.h b/src/corelib/global/qswap.h
new file mode 100644
index 0000000000..3d533c8a95
--- /dev/null
+++ b/src/corelib/global/qswap.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTCORE_QSWAP_H
+#define QTCORE_QSWAP_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <type_traits>
+#include <utility>
+
+#if 0
+#pragma qt_class(QtSwap)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+template <typename T>
+constexpr void qSwap(T &value1, T &value2)
+ noexcept(std::is_nothrow_swappable_v<T>)
+{
+ using std::swap;
+ swap(value1, value2);
+}
+
+// pure compile-time micro-optimization for our own headers, so not documented:
+template <typename T>
+constexpr inline void qt_ptr_swap(T* &lhs, T* &rhs) noexcept
+{
+ T *tmp = lhs;
+ lhs = rhs;
+ rhs = tmp;
+}
+
+QT_END_NAMESPACE
+
+#endif // QTCORE_QSWAP_H
diff --git a/src/corelib/global/qswap.qdoc b/src/corelib/global/qswap.qdoc
new file mode 100644
index 0000000000..bffad903f9
--- /dev/null
+++ b/src/corelib/global/qswap.qdoc
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \fn template <typename T> void qSwap(T &lhs, T &rhs)
+ \relates <QtSwap>
+
+ Exchanges the values of variables \a lhs and \a rhs,
+ taking type-specific \c{swap()} overloads into account.
+
+ This function is Qt's version of
+ \l{https://www.boost.org/doc/libs/release/libs/core/doc/html/core/swap.html}{\c{boost::swap()}},
+ and is equivalent to
+ \code
+ using std::swap; // bring std::swap into scope (for built-in types)
+ swap(lhs, rhs); // unqualified call (picks up type-specific overloads
+ // via Argument-Dependent Lookup, or falls back to std::swap)
+ \endcode
+
+ Use this function primarily in generic code, where you would traditionally
+ have written the above two lines, because you don't know anything about \c{T}.
+
+ If you already know what \c{T} is, then use one of the following options, in
+ order of preference:
+
+ \list
+ \li \c{lhs.swap(rhs);} if such a member-swap exists
+ \li \c{std::swap(lhs, rhs);} if no type-specific \c{swap()} exists
+ \endlist
+
+ See
+ \l{https://www.boost.org/doc/libs/release/libs/core/doc/html/core/swap.html}{\c{boost::swap()} on boost.org}
+ for more details.
+
+ See also
+ \l{https://en.cppreference.com/w/cpp/algorithm/swap}{\c{std::swap} on cppreference.com},
+ \l{https://en.cppreference.com/w/cpp/named_req/Swappable}{\c{Swappable} on cppreference.com}.
+*/
diff --git a/src/corelib/global/qsysinfo.cpp b/src/corelib/global/qsysinfo.cpp
new file mode 100644
index 0000000000..79cb76b236
--- /dev/null
+++ b/src/corelib/global/qsysinfo.cpp
@@ -0,0 +1,1072 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsysinfo.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/qstring.h>
+
+#include <private/qoperatingsystemversion_p.h>
+
+#ifdef Q_OS_UNIX
+# include <sys/utsname.h>
+# include <private/qcore_unix_p.h>
+#endif
+
+#ifdef Q_OS_ANDROID
+#include <QtCore/private/qjnihelpers_p.h>
+#include <qjniobject.h>
+#endif
+
+#if defined(Q_OS_SOLARIS)
+# include <sys/systeminfo.h>
+#endif
+
+#if defined(Q_OS_DARWIN)
+# include "qnamespace.h"
+# include <private/qcore_mac_p.h>
+# if __has_include(<IOKit/IOKitLib.h>)
+# include <IOKit/IOKitLib.h>
+# endif
+#endif
+
+#ifdef Q_OS_BSD4
+# include <sys/sysctl.h>
+#endif
+
+#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
+# include "qoperatingsystemversion_win_p.h"
+# include "private/qwinregistry_p.h"
+# include "qt_windows.h"
+#endif // Q_OS_WIN || Q_OS_CYGWIN
+
+#include "archdetect.cpp"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+/*!
+ \class QSysInfo
+ \inmodule QtCore
+ \brief The QSysInfo class provides information about the system.
+
+ \list
+ \li \l WordSize specifies the size of a pointer for the platform
+ on which the application is compiled.
+ \li \l ByteOrder specifies whether the platform is big-endian or
+ little-endian.
+ \endlist
+
+ Some constants are defined only on certain platforms. You can use
+ the preprocessor symbols Q_OS_WIN and Q_OS_MACOS to test that
+ the application is compiled under Windows or \macos.
+
+ \sa QLibraryInfo
+*/
+
+/*!
+ \enum QSysInfo::Sizes
+
+ This enum provides platform-specific information about the sizes of data
+ structures used by the underlying architecture.
+
+ \value WordSize The size in bits of a pointer for the platform on which
+ the application is compiled (32 or 64).
+*/
+
+/*!
+ \enum QSysInfo::Endian
+
+ \value BigEndian Big-endian byte order (also called Network byte order)
+ \value LittleEndian Little-endian byte order
+ \value ByteOrder Equals BigEndian or LittleEndian, depending on
+ the platform's byte order.
+*/
+
+#if defined(Q_OS_DARWIN)
+
+static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
+{
+#ifdef Q_OS_MACOS
+ if (version.majorVersion() == 13)
+ return "Ventura";
+ if (version.majorVersion() == 12)
+ return "Monterey";
+ // Compare against predefined constant to handle 10.16/11.0
+ if (QOperatingSystemVersion::MacOSBigSur.version().isPrefixOf(version.version()))
+ return "Big Sur";
+ if (version.majorVersion() == 10) {
+ switch (version.minorVersion()) {
+ case 9:
+ return "Mavericks";
+ case 10:
+ return "Yosemite";
+ case 11:
+ return "El Capitan";
+ case 12:
+ return "Sierra";
+ case 13:
+ return "High Sierra";
+ case 14:
+ return "Mojave";
+ case 15:
+ return "Catalina";
+ }
+ }
+ // unknown, future version
+#else
+ Q_UNUSED(version);
+#endif
+ return nullptr;
+}
+
+#elif defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
+
+# ifndef QT_BOOTSTRAPPED
+class QWindowsSockInit
+{
+public:
+ QWindowsSockInit();
+ ~QWindowsSockInit();
+ int version;
+};
+
+QWindowsSockInit::QWindowsSockInit()
+: version(0)
+{
+ //### should we try for 2.2 on all platforms ??
+ WSAData wsadata;
+
+ // IPv6 requires Winsock v2.0 or better.
+ if (WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) {
+ qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
+ } else {
+ version = 0x20;
+ }
+}
+
+QWindowsSockInit::~QWindowsSockInit()
+{
+ WSACleanup();
+}
+Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
+# endif // QT_BOOTSTRAPPED
+
+static QString readVersionRegistryString(const wchar_t *subKey)
+{
+ return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)")
+ .stringValue(subKey);
+}
+
+static inline QString windowsDisplayVersion()
+{
+ // https://tickets.puppetlabs.com/browse/FACT-3058
+ // The "ReleaseId" key stopped updating since Windows 10 20H2.
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10_20H2)
+ return readVersionRegistryString(L"DisplayVersion");
+ else
+ return readVersionRegistryString(L"ReleaseId");
+}
+
+static QString winSp_helper()
+{
+ const auto osv = qWindowsVersionInfo();
+ const qint16 major = osv.wServicePackMajor;
+ if (major) {
+ QString sp = QStringLiteral("SP ") + QString::number(major);
+ const qint16 minor = osv.wServicePackMinor;
+ if (minor)
+ sp += u'.' + QString::number(minor);
+
+ return sp;
+ }
+ return QString();
+}
+
+static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
+{
+ Q_UNUSED(version);
+ const OSVERSIONINFOEX osver = qWindowsVersionInfo();
+ const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
+
+#define Q_WINVER(major, minor) (major << 8 | minor)
+ switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) {
+ case Q_WINVER(10, 0):
+ if (workstation) {
+ if (osver.dwBuildNumber >= 22000)
+ return "11";
+ return "10";
+ }
+ // else: Server
+ if (osver.dwBuildNumber >= 20348)
+ return "Server 2022";
+ if (osver.dwBuildNumber >= 17763)
+ return "Server 2019";
+ return "Server 2016";
+ }
+#undef Q_WINVER
+ // unknown, future version
+ return nullptr;
+}
+
+#endif
+#if defined(Q_OS_UNIX)
+# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
+# define USE_ETC_OS_RELEASE
+struct QUnixOSVersion
+{
+ // from /etc/os-release older /etc/lsb-release // redhat /etc/redhat-release // debian /etc/debian_version
+ QString productType; // $ID $DISTRIB_ID // single line file containing: // Debian
+ QString productVersion; // $VERSION_ID $DISTRIB_RELEASE // <Vendor_ID release Version_ID> // single line file <Release_ID/sid>
+ QString prettyName; // $PRETTY_NAME $DISTRIB_DESCRIPTION
+};
+
+static QString unquote(QByteArrayView str)
+{
+ // man os-release says:
+ // Variable assignment values must be enclosed in double
+ // or single quotes if they include spaces, semicolons or
+ // other special characters outside of A–Z, a–z, 0–9. Shell
+ // special characters ("$", quotes, backslash, backtick)
+ // must be escaped with backslashes, following shell style.
+ // All strings should be in UTF-8 format, and non-printable
+ // characters should not be used. It is not supported to
+ // concatenate multiple individually quoted strings.
+ if (str.size() >= 2 && str.front() == '"' && str.back() == '"')
+ str = str.sliced(1).chopped(1);
+ return QString::fromUtf8(str);
+}
+
+static QByteArray getEtcFileContent(const char *filename)
+{
+ // we're avoiding QFile here
+ int fd = qt_safe_open(filename, O_RDONLY);
+ if (fd == -1)
+ return QByteArray();
+
+ QT_STATBUF sbuf;
+ if (QT_FSTAT(fd, &sbuf) == -1) {
+ qt_safe_close(fd);
+ return QByteArray();
+ }
+
+ QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
+ buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
+ qt_safe_close(fd);
+ return buffer;
+}
+
+static bool readEtcFile(QUnixOSVersion &v, const char *filename,
+ const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
+{
+
+ QByteArray buffer = getEtcFileContent(filename);
+ if (buffer.isEmpty())
+ return false;
+
+ const char *ptr = buffer.constData();
+ const char *end = buffer.constEnd();
+ const char *eol;
+ QByteArray line;
+ for (; ptr != end; ptr = eol + 1) {
+ // find the end of the line after ptr
+ eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
+ if (!eol)
+ eol = end - 1;
+ line.setRawData(ptr, eol - ptr);
+
+ if (line.startsWith(idKey)) {
+ ptr += idKey.size();
+ v.productType = unquote({ptr, eol});
+ continue;
+ }
+
+ if (line.startsWith(prettyNameKey)) {
+ ptr += prettyNameKey.size();
+ v.prettyName = unquote({ptr, eol});
+ continue;
+ }
+
+ if (line.startsWith(versionKey)) {
+ ptr += versionKey.size();
+ v.productVersion = unquote({ptr, eol});
+ continue;
+ }
+ }
+
+ return true;
+}
+
+static bool readOsRelease(QUnixOSVersion &v)
+{
+ QByteArray id = QByteArrayLiteral("ID=");
+ QByteArray versionId = QByteArrayLiteral("VERSION_ID=");
+ QByteArray prettyName = QByteArrayLiteral("PRETTY_NAME=");
+
+ // man os-release(5) says:
+ // The file /etc/os-release takes precedence over /usr/lib/os-release.
+ // Applications should check for the former, and exclusively use its data
+ // if it exists, and only fall back to /usr/lib/os-release if it is
+ // missing.
+ return readEtcFile(v, "/etc/os-release", id, versionId, prettyName) ||
+ readEtcFile(v, "/usr/lib/os-release", id, versionId, prettyName);
+}
+
+static bool readEtcLsbRelease(QUnixOSVersion &v)
+{
+ bool ok = readEtcFile(v, "/etc/lsb-release", QByteArrayLiteral("DISTRIB_ID="),
+ QByteArrayLiteral("DISTRIB_RELEASE="), QByteArrayLiteral("DISTRIB_DESCRIPTION="));
+ if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) {
+ // some distributions have redundant information for the pretty name,
+ // so try /etc/<lowercasename>-release
+
+ // we're still avoiding QFile here
+ QByteArray distrorelease = "/etc/" + v.productType.toLatin1().toLower() + "-release";
+ int fd = qt_safe_open(distrorelease, O_RDONLY);
+ if (fd != -1) {
+ QT_STATBUF sbuf;
+ if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.size()) {
+ // file apparently contains interesting information
+ QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
+ buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
+ v.prettyName = QString::fromLatin1(buffer.trimmed());
+ }
+ qt_safe_close(fd);
+ }
+ }
+
+ // some distributions have a /etc/lsb-release file that does not provide the values
+ // we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION.
+ // Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values,
+ // returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing.
+ return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
+}
+
+#if defined(Q_OS_LINUX)
+static QByteArray getEtcFileFirstLine(const char *fileName)
+{
+ QByteArray buffer = getEtcFileContent(fileName);
+ if (buffer.isEmpty())
+ return QByteArray();
+
+ const char *ptr = buffer.constData();
+ return QByteArray(ptr, buffer.indexOf("\n")).trimmed();
+}
+
+static bool readEtcRedHatRelease(QUnixOSVersion &v)
+{
+ // /etc/redhat-release analysed should be a one line file
+ // the format of its content is <Vendor_ID release Version>
+ // i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)"
+ QByteArray line = getEtcFileFirstLine("/etc/redhat-release");
+ if (line.isEmpty())
+ return false;
+
+ v.prettyName = QString::fromLatin1(line);
+
+ const char keyword[] = "release ";
+ const qsizetype releaseIndex = line.indexOf(keyword);
+ v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(u' ');
+ const qsizetype spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword));
+ v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword),
+ spaceIndex > -1 ? spaceIndex - releaseIndex - int(strlen(keyword)) : -1));
+ return true;
+}
+
+static bool readEtcDebianVersion(QUnixOSVersion &v)
+{
+ // /etc/debian_version analysed should be a one line file
+ // the format of its content is <Release_ID/sid>
+ // i.e. "jessie/sid"
+ QByteArray line = getEtcFileFirstLine("/etc/debian_version");
+ if (line.isEmpty())
+ return false;
+
+ v.productType = QStringLiteral("Debian");
+ v.productVersion = QString::fromLatin1(line);
+ return true;
+}
+#endif
+
+static bool findUnixOsVersion(QUnixOSVersion &v)
+{
+ if (readOsRelease(v))
+ return true;
+ if (readEtcLsbRelease(v))
+ return true;
+#if defined(Q_OS_LINUX)
+ if (readEtcRedHatRelease(v))
+ return true;
+ if (readEtcDebianVersion(v))
+ return true;
+#endif
+ return false;
+}
+# endif // USE_ETC_OS_RELEASE
+#endif // Q_OS_UNIX
+
+#ifdef Q_OS_ANDROID
+static const char *osVer_helper(QOperatingSystemVersion)
+{
+ // https://source.android.com/source/build-numbers.html
+ // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
+ const int sdk_int = QtAndroidPrivate::androidSdkVersion();
+ switch (sdk_int) {
+ case 3:
+ return "Cupcake";
+ case 4:
+ return "Donut";
+ case 5:
+ case 6:
+ case 7:
+ return "Eclair";
+ case 8:
+ return "Froyo";
+ case 9:
+ case 10:
+ return "Gingerbread";
+ case 11:
+ case 12:
+ case 13:
+ return "Honeycomb";
+ case 14:
+ case 15:
+ return "Ice Cream Sandwich";
+ case 16:
+ case 17:
+ case 18:
+ return "Jelly Bean";
+ case 19:
+ case 20:
+ return "KitKat";
+ case 21:
+ case 22:
+ return "Lollipop";
+ case 23:
+ return "Marshmallow";
+ case 24:
+ case 25:
+ return "Nougat";
+ case 26:
+ case 27:
+ return "Oreo";
+ case 28:
+ return "Pie";
+ case 29:
+ return "10";
+ case 30:
+ return "11";
+ case 31:
+ return "12";
+ case 32:
+ return "12L";
+ case 33:
+ return "13";
+ default:
+ break;
+ }
+
+ return "";
+}
+#endif
+
+/*!
+ \since 5.4
+
+ Returns the architecture of the CPU that Qt was compiled for, in text
+ format. Note that this may not match the actual CPU that the application is
+ running on if there's an emulation layer or if the CPU supports multiple
+ architectures (like x86-64 processors supporting i386 applications). To
+ detect that, use currentCpuArchitecture().
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new CPU types may be added over time.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "arm"
+ \li "arm64"
+ \li "i386"
+ \li "ia64"
+ \li "mips"
+ \li "mips64"
+ \li "power"
+ \li "power64"
+ \li "sparc"
+ \li "sparcv9"
+ \li "x86_64"
+ \endlist
+
+ \sa QSysInfo::buildAbi(), QSysInfo::currentCpuArchitecture()
+*/
+QString QSysInfo::buildCpuArchitecture()
+{
+ return QStringLiteral(ARCH_PROCESSOR);
+}
+
+/*!
+ \since 5.4
+
+ Returns the architecture of the CPU that the application is running on, in
+ text format. Note that this function depends on what the OS will report and
+ may not detect the actual CPU architecture if the OS hides that information
+ or is unable to provide it. For example, a 32-bit OS running on a 64-bit
+ CPU is usually unable to determine the CPU is actually capable of running
+ 64-bit programs.
+
+ Values returned by this function are mostly stable: an attempt will be made
+ to ensure that they stay constant over time and match the values returned
+ by QSysInfo::builldCpuArchitecture(). However, due to the nature of the
+ operating system functions being used, there may be discrepancies.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "arm"
+ \li "arm64"
+ \li "i386"
+ \li "ia64"
+ \li "mips"
+ \li "mips64"
+ \li "power"
+ \li "power64"
+ \li "sparc"
+ \li "sparcv9"
+ \li "x86_64"
+ \endlist
+
+ \sa QSysInfo::buildAbi(), QSysInfo::buildCpuArchitecture()
+*/
+QString QSysInfo::currentCpuArchitecture()
+{
+#if defined(Q_OS_WIN)
+ // We don't need to catch all the CPU architectures in this function;
+ // only those where the host CPU might be different than the build target
+ // (usually, 64-bit platforms).
+ SYSTEM_INFO info;
+ GetNativeSystemInfo(&info);
+ switch (info.wProcessorArchitecture) {
+# ifdef PROCESSOR_ARCHITECTURE_AMD64
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ return QStringLiteral("x86_64");
+# endif
+# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
+ case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
+# endif
+ case PROCESSOR_ARCHITECTURE_IA64:
+ return QStringLiteral("ia64");
+ }
+#elif defined(Q_OS_DARWIN) && !defined(Q_OS_MACOS)
+ // iOS-based OSes do not return the architecture on uname(2)'s result.
+ return buildCpuArchitecture();
+#elif defined(Q_OS_UNIX)
+ long ret = -1;
+ struct utsname u;
+
+# if defined(Q_OS_SOLARIS)
+ // We need a special call for Solaris because uname(2) on x86 returns "i86pc" for
+ // both 32- and 64-bit CPUs. Reference:
+ // http://docs.oracle.com/cd/E18752_01/html/816-5167/sysinfo-2.html#REFMAN2sysinfo-2
+ // http://fxr.watson.org/fxr/source/common/syscall/systeminfo.c?v=OPENSOLARIS
+ // http://fxr.watson.org/fxr/source/common/conf/param.c?v=OPENSOLARIS;im=10#L530
+ if (ret == -1)
+ ret = sysinfo(SI_ARCHITECTURE_64, u.machine, sizeof u.machine);
+# endif
+
+ if (ret == -1)
+ ret = uname(&u);
+
+ // we could use detectUnixVersion() above, but we only need a field no other function does
+ if (ret != -1) {
+ // the use of QT_BUILD_INTERNAL here is simply to ensure all branches build
+ // as we don't often build on some of the less common platforms
+# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL)
+ if (strcmp(u.machine, "aarch64") == 0)
+ return QStringLiteral("arm64");
+ if (strncmp(u.machine, "armv", 4) == 0)
+ return QStringLiteral("arm");
+# endif
+# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL)
+ // harmonize "powerpc" and "ppc" to "power"
+ if (strncmp(u.machine, "ppc", 3) == 0)
+ return "power"_L1 + QLatin1StringView(u.machine + 3);
+ if (strncmp(u.machine, "powerpc", 7) == 0)
+ return "power"_L1 + QLatin1StringView(u.machine + 7);
+ if (strcmp(u.machine, "Power Macintosh") == 0)
+ return "power"_L1;
+# endif
+# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL)
+ // Solaris sysinfo(2) (above) uses "sparcv9", but uname -m says "sun4u";
+ // Linux says "sparc64"
+ if (strcmp(u.machine, "sun4u") == 0 || strcmp(u.machine, "sparc64") == 0)
+ return QStringLiteral("sparcv9");
+ if (strcmp(u.machine, "sparc32") == 0)
+ return QStringLiteral("sparc");
+# endif
+# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL)
+ // harmonize all "i?86" to "i386"
+ if (strlen(u.machine) == 4 && u.machine[0] == 'i'
+ && u.machine[2] == '8' && u.machine[3] == '6')
+ return QStringLiteral("i386");
+ if (strcmp(u.machine, "amd64") == 0) // Solaris
+ return QStringLiteral("x86_64");
+# endif
+ return QString::fromLatin1(u.machine);
+ }
+#endif
+ return buildCpuArchitecture();
+}
+
+/*!
+ \since 5.4
+
+ Returns the full architecture string that Qt was compiled for. This string
+ is useful for identifying different, incompatible builds. For example, it
+ can be used as an identifier to request an upgrade package from a server.
+
+ The values returned from this function are kept stable as follows: the
+ mandatory components of the result will not change in future versions of
+ Qt, but optional suffixes may be added.
+
+ The returned value is composed of three or more parts, separated by dashes
+ ("-"). They are:
+
+ \table
+ \header \li Component \li Value
+ \row \li CPU Architecture \li The same as QSysInfo::buildCpuArchitecture(), such as "arm", "i386", "mips" or "x86_64"
+ \row \li Endianness \li "little_endian" or "big_endian"
+ \row \li Word size \li Whether it's a 32- or 64-bit application. Possible values are:
+ "llp64" (Windows 64-bit), "lp64" (Unix 64-bit), "ilp32" (32-bit)
+ \row \li (Optional) ABI \li Zero or more components identifying different ABIs possible in this architecture.
+ Currently, Qt has optional ABI components for ARM and MIPS processors: one
+ component is the main ABI (such as "eabi", "o32", "n32", "o64"); another is
+ whether the calling convention is using hardware floating point registers ("hardfloat"
+ is present).
+
+ Additionally, if Qt was configured with \c{-qreal float}, the ABI option tag "qreal_float"
+ will be present. If Qt was configured with another type as qreal, that type is present after
+ "qreal_", with all characters other than letters and digits escaped by an underscore, followed
+ by two hex digits. For example, \c{-qreal long double} becomes "qreal_long_20double".
+ \endtable
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+QString QSysInfo::buildAbi()
+{
+ // ARCH_FULL is a concatenation of strings (incl. ARCH_PROCESSOR), which breaks
+ // QStringLiteral on MSVC. Since the concatenation behavior we want is specified
+ // the same C++11 paper as the Unicode strings, we'll use that macro and hope
+ // that Microsoft implements the new behavior when they add support for Unicode strings.
+ return QStringLiteral(ARCH_FULL);
+}
+
+static QString unknownText()
+{
+ return QStringLiteral("unknown");
+}
+
+/*!
+ \since 5.4
+
+ Returns the type of the operating system kernel Qt was compiled for. It's
+ also the kernel the application is running on, unless the host operating
+ system is running a form of compatibility or virtualization layer.
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new OS kernel types may be added over time.
+
+ On Windows, this function returns the type of Windows kernel, like "winnt".
+ On Unix systems, it returns the same as the output of \c{uname
+ -s} (lowercased).
+
+ \note This function may return surprising values: it returns "linux"
+ for all operating systems running Linux (including Android), "qnx" for all
+ operating systems running QNX, "freebsd" for
+ Debian/kFreeBSD, and "darwin" for \macos and iOS. For information on the type
+ of product the application is running on, see productType().
+
+ \sa QFileSelector, kernelVersion(), productType(), productVersion(), prettyProductName()
+*/
+QString QSysInfo::kernelType()
+{
+#if defined(Q_OS_WIN)
+ return QStringLiteral("winnt");
+#elif defined(Q_OS_UNIX)
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLatin1(u.sysname).toLower();
+#endif
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns the release version of the operating system kernel. On Windows, it
+ returns the version of the NT kernel. On Unix systems, including
+ Android and \macos, it returns the same as the \c{uname -r}
+ command would return.
+
+ If the version could not be determined, this function may return an empty
+ string.
+
+ \sa kernelType(), productType(), productVersion(), prettyProductName()
+*/
+QString QSysInfo::kernelVersion()
+{
+#ifdef Q_OS_WIN
+ const auto osver = QOperatingSystemVersion::current();
+ return QString::asprintf("%d.%d.%d",
+ osver.majorVersion(), osver.minorVersion(), osver.microVersion());
+#else
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLatin1(u.release);
+ return QString();
+#endif
+}
+
+
+/*!
+ \since 5.4
+
+ Returns the product name of the operating system this application is
+ running in. If the application is running on some sort of emulation or
+ virtualization layer (such as WINE on a Unix system), this function will
+ inspect the emulation / virtualization layer.
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new OS types may be added over time.
+
+ \b{Linux and Android note}: this function returns "android" for Linux
+ systems running Android userspace, notably when using the Bionic library.
+ For all other Linux systems, regardless of C library being used, it tries
+ to determine the distribution name and returns that. If determining the
+ distribution name failed, it returns "unknown".
+
+ \b{\macos note}: this function returns "macos" for all \macos systems,
+ regardless of Apple naming convention. Previously, in Qt 5, it returned
+ "osx", again regardless of Apple naming conventions.
+
+ \b{Darwin, iOS, tvOS, and watchOS note}: this function returns "ios" for
+ iOS systems, "tvos" for tvOS systems, "watchos" for watchOS systems, and
+ "darwin" in case the system could not be determined.
+
+ \b{FreeBSD note}: this function returns "debian" for Debian/kFreeBSD and
+ "unknown" otherwise.
+
+ \b{Windows note}: this function return "windows"
+
+ For other Unix-type systems, this function usually returns "unknown".
+
+ \sa QFileSelector, kernelType(), kernelVersion(), productVersion(), prettyProductName()
+*/
+QString QSysInfo::productType()
+{
+ // similar, but not identical to QFileSelectorPrivate::platformSelectors
+#if defined(Q_OS_WIN)
+ return QStringLiteral("windows");
+
+#elif defined(Q_OS_QNX)
+ return QStringLiteral("qnx");
+
+#elif defined(Q_OS_ANDROID)
+ return QStringLiteral("android");
+
+#elif defined(Q_OS_IOS)
+ return QStringLiteral("ios");
+#elif defined(Q_OS_TVOS)
+ return QStringLiteral("tvos");
+#elif defined(Q_OS_WATCHOS)
+ return QStringLiteral("watchos");
+#elif defined(Q_OS_VISIONOS)
+ return QStringLiteral("visionos");
+#elif defined(Q_OS_MACOS)
+ return QStringLiteral("macos");
+#elif defined(Q_OS_DARWIN)
+ return QStringLiteral("darwin");
+#elif defined(Q_OS_WASM)
+ return QStringLiteral("wasm");
+
+#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
+ QUnixOSVersion unixOsVersion;
+ findUnixOsVersion(unixOsVersion);
+ if (!unixOsVersion.productType.isEmpty())
+ return unixOsVersion.productType;
+#endif
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns the product version of the operating system in string form. If the
+ version could not be determined, this function returns "unknown".
+
+ It will return the Android, iOS, \macos, Windows full-product
+ versions on those systems.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "12" (Android 12)
+ \li "36" (Fedora 36)
+ \li "15.5" (iOS 15.5)
+ \li "12.4" (macOS Monterey)
+ \li "22.04" (Ubuntu 22.04)
+ \li "8.6" (watchOS 8.6)
+ \li "11" (Windows 11)
+ \li "Server 2022" (Windows Server 2022)
+ \endlist
+
+ On Linux systems, it will try to determine the distribution version and will
+ return that. This is also done on Debian/kFreeBSD, so this function will
+ return Debian version in that case.
+
+ In all other Unix-type systems, this function always returns "unknown".
+
+ \note The version string returned from this function is not guaranteed to
+ be orderable. On Linux, the version of
+ the distribution may jump unexpectedly, please refer to the distribution's
+ documentation for versioning practices.
+
+ \sa kernelType(), kernelVersion(), productType(), prettyProductName()
+*/
+QString QSysInfo::productVersion()
+{
+#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
+ const auto version = QOperatingSystemVersion::current();
+ return QString::asprintf("%d.%d", version.majorVersion(), version.minorVersion());
+#elif defined(Q_OS_WIN)
+ const char *version = osVer_helper();
+ if (version) {
+ const QLatin1Char spaceChar(' ');
+ return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
+ }
+ // fall through
+
+#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
+ QUnixOSVersion unixOsVersion;
+ findUnixOsVersion(unixOsVersion);
+ if (!unixOsVersion.productVersion.isEmpty())
+ return unixOsVersion.productVersion;
+#endif
+
+ // fallback
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns a prettier form of productType() and productVersion(), containing
+ other tokens like the operating system type, codenames and other
+ information. The result of this function is suitable for displaying to the
+ user, but not for long-term storage, as the string may change with updates
+ to Qt.
+
+ If productType() is "unknown", this function will instead use the
+ kernelType() and kernelVersion() functions.
+
+ \sa kernelType(), kernelVersion(), productType(), productVersion()
+*/
+QString QSysInfo::prettyProductName()
+{
+#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
+ const auto version = QOperatingSystemVersion::current();
+ const int majorVersion = version.majorVersion();
+ const QString versionString = QString::asprintf("%d.%d", majorVersion, version.minorVersion());
+ QString result = version.name() + u' ';
+ const char *name = osVer_helper(version);
+ if (!name)
+ return result + versionString;
+ result += QLatin1StringView(name);
+# if !defined(Q_OS_WIN)
+ return result + " ("_L1 + versionString + u')';
+# else
+ // (resembling winver.exe): Windows 10 "Windows 10 Version 1809"
+ const auto displayVersion = windowsDisplayVersion();
+ if (!displayVersion.isEmpty())
+ result += " Version "_L1 + displayVersion;
+ return result;
+# endif // Windows
+#elif defined(Q_OS_HAIKU)
+ return "Haiku "_L1 + productVersion();
+#elif defined(Q_OS_UNIX)
+# ifdef USE_ETC_OS_RELEASE
+ QUnixOSVersion unixOsVersion;
+ findUnixOsVersion(unixOsVersion);
+ if (!unixOsVersion.prettyName.isEmpty())
+ return unixOsVersion.prettyName;
+# endif
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLatin1(u.sysname) + u' ' + QString::fromLatin1(u.release);
+#endif
+ return unknownText();
+}
+
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \since 5.6
+
+ Returns this machine's host name, if one is configured. Note that hostnames
+ are not guaranteed to be globally unique, especially if they were
+ configured automatically.
+
+ This function does not guarantee the returned host name is a Fully
+ Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the
+ returned name to an FQDN.
+
+ This function returns the same as QHostInfo::localHostName().
+
+ \sa QHostInfo::localDomainName, machineUniqueId()
+*/
+QString QSysInfo::machineHostName()
+{
+ // the hostname can change, so we can't cache it
+#if defined(Q_OS_LINUX)
+ // gethostname(3) on Linux just calls uname(2), so do it ourselves
+ // and avoid a memcpy
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLocal8Bit(u.nodename);
+ return QString();
+#else
+# ifdef Q_OS_WIN
+ // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
+ winsockInit();
+ QString hostName;
+ hostName.resize(512);
+ unsigned long len = hostName.size();
+ BOOL res = GetComputerNameEx(ComputerNameDnsHostname,
+ reinterpret_cast<wchar_t *>(const_cast<quint16 *>(hostName.utf16())), &len);
+ if (!res && len > 512) {
+ hostName.resize(len - 1);
+ GetComputerNameEx(ComputerNameDnsHostname,
+ reinterpret_cast<wchar_t *>(const_cast<quint16 *>(hostName.utf16())), &len);
+ }
+ hostName.truncate(len);
+ return hostName;
+# else // !Q_OS_WIN
+
+ char hostName[512];
+ if (gethostname(hostName, sizeof(hostName)) == -1)
+ return QString();
+ hostName[sizeof(hostName) - 1] = '\0';
+ return QString::fromLocal8Bit(hostName);
+# endif
+#endif
+}
+#endif // QT_BOOTSTRAPPED
+
+enum {
+ UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") - 1
+};
+
+/*!
+ \since 5.11
+
+ Returns a unique ID for this machine, if one can be determined. If no
+ unique ID could be determined, this function returns an empty byte array.
+ Unlike machineHostName(), the value returned by this function is likely
+ globally unique.
+
+ A unique ID is useful in network operations to identify this machine for an
+ extended period of time, when the IP address could change or if this
+ machine could have more than one IP address. For example, the ID could be
+ used when communicating with a server or when storing device-specific data
+ in shared network storage.
+
+ Note that on some systems, this value will persist across reboots and on
+ some it will not. Applications should not blindly depend on this fact
+ without verifying the OS capabilities. In particular, on Linux systems,
+ this ID is usually permanent and it matches the D-Bus machine ID, except
+ for nodes without their own storage (replicated nodes).
+
+ \sa machineHostName(), bootUniqueId()
+*/
+QByteArray QSysInfo::machineUniqueId()
+{
+#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
+ char uuid[UuidStringLen + 1];
+ io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
+ QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
+ CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman);
+ return QByteArray(uuid);
+#elif defined(Q_OS_BSD4) && defined(KERN_HOSTUUID)
+ char uuid[UuidStringLen + 1];
+ size_t uuidlen = sizeof(uuid);
+ int name[] = { CTL_KERN, KERN_HOSTUUID };
+ if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0
+ && uuidlen == sizeof(uuid))
+ return QByteArray(uuid, uuidlen - 1);
+#elif defined(Q_OS_UNIX)
+ // The modern name on Linux is /etc/machine-id, but that path is
+ // unlikely to exist on non-Linux (non-systemd) systems. The old
+ // path is more than enough.
+ static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id";
+ const char *firstfilename = fullfilename + sizeof("/usr/local") - 1;
+ int fd = qt_safe_open(firstfilename, O_RDONLY);
+ if (fd == -1 && errno == ENOENT)
+ fd = qt_safe_open(fullfilename, O_RDONLY);
+
+ if (fd != -1) {
+ char buffer[32]; // 128 bits, hex-encoded
+ qint64 len = qt_safe_read(fd, buffer, sizeof(buffer));
+ qt_safe_close(fd);
+
+ if (len != -1)
+ return QByteArray(buffer, len);
+ }
+#elif defined(Q_OS_WIN)
+ // Let's poke at the registry
+ const QString machineGuid = QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Cryptography)")
+ .stringValue(u"MachineGuid"_s);
+ if (!machineGuid.isEmpty())
+ return machineGuid.toLatin1();
+#endif
+ return QByteArray();
+}
+
+/*!
+ \since 5.11
+
+ Returns a unique ID for this machine's boot, if one can be determined. If
+ no unique ID could be determined, this function returns an empty byte
+ array. This value is expected to change after every boot and can be
+ considered globally unique.
+
+ This function is currently only implemented for Linux and Apple operating
+ systems.
+
+ \sa machineUniqueId()
+*/
+QByteArray QSysInfo::bootUniqueId()
+{
+#ifdef Q_OS_LINUX
+ // use low-level API here for simplicity
+ int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY);
+ if (fd != -1) {
+ char uuid[UuidStringLen];
+ qint64 len = qt_safe_read(fd, uuid, sizeof(uuid));
+ qt_safe_close(fd);
+ if (len == UuidStringLen)
+ return QByteArray(uuid, UuidStringLen);
+ }
+#elif defined(Q_OS_DARWIN)
+ // "kern.bootsessionuuid" is only available by name
+ char uuid[UuidStringLen + 1];
+ size_t uuidlen = sizeof(uuid);
+ if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0
+ && uuidlen == sizeof(uuid))
+ return QByteArray(uuid, uuidlen - 1);
+#endif
+ return QByteArray();
+};
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h
index a3fa0fcb27..01f6313299 100644
--- a/src/corelib/global/qsysinfo.h
+++ b/src/corelib/global/qsysinfo.h
@@ -1,90 +1,33 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSYSINFO_H
#define QSYSINFO_H
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qprocessordetection.h>
+#include <QtCore/qtcoreexports.h>
+
QT_BEGIN_NAMESPACE
/*
System information
*/
-/*
- * GCC (5-7) has a regression that causes it to emit wrong deprecated warnings:
- * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77849
- *
- * Try to work around it by defining our own macro.
- */
-
-#ifdef QT_SYSINFO_DEPRECATED_X
-#error "QT_SYSINFO_DEPRECATED_X already defined"
-#endif
-
-#ifdef Q_CC_GNU
-#define QT_SYSINFO_DEPRECATED_X(x)
-#else
-#define QT_SYSINFO_DEPRECATED_X(x) QT_DEPRECATED_X(x)
-#endif
-
class QString;
-class Q_CORE_EXPORT QSysInfo {
+class QByteArray;
+
+class Q_CORE_EXPORT QSysInfo
+{
public:
enum Sizes {
WordSize = (sizeof(void *)<<3)
};
-#if defined(QT_BUILD_QMAKE)
enum Endian {
BigEndian,
LittleEndian
- };
- /* needed to bootstrap qmake */
- static const int ByteOrder;
-#elif defined(Q_BYTE_ORDER)
- enum Endian {
- BigEndian,
- LittleEndian
-
# ifdef Q_QDOC
, ByteOrder = BigEndian or LittleEndian
# elif Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -95,139 +38,6 @@ public:
# error "Undefined byte order"
# endif
};
-#endif
-#if QT_DEPRECATED_SINCE(5, 9)
- enum QT_DEPRECATED_X("Use QOperatingSystemVersion") WinVersion {
- WV_None = 0x0000,
-
- WV_32s = 0x0001,
- WV_95 = 0x0002,
- WV_98 = 0x0003,
- WV_Me = 0x0004,
- WV_DOS_based= 0x000f,
-
- /* codenames */
- WV_NT = 0x0010,
- WV_2000 = 0x0020,
- WV_XP = 0x0030,
- WV_2003 = 0x0040,
- WV_VISTA = 0x0080,
- WV_WINDOWS7 = 0x0090,
- WV_WINDOWS8 = 0x00a0,
- WV_WINDOWS8_1 = 0x00b0,
- WV_WINDOWS10 = 0x00c0,
- WV_NT_based = 0x00f0,
-
- /* version numbers */
- WV_4_0 = WV_NT,
- WV_5_0 = WV_2000,
- WV_5_1 = WV_XP,
- WV_5_2 = WV_2003,
- WV_6_0 = WV_VISTA,
- WV_6_1 = WV_WINDOWS7,
- WV_6_2 = WV_WINDOWS8,
- WV_6_3 = WV_WINDOWS8_1,
- WV_10_0 = WV_WINDOWS10,
-
- WV_CE = 0x0100,
- WV_CENET = 0x0200,
- WV_CE_5 = 0x0300,
- WV_CE_6 = 0x0400,
- WV_CE_based = 0x0f00
- };
-
-#define Q_MV_OSX(major, minor) (major == 10 ? minor + 2 : (major == 9 ? 1 : 0))
-#define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor)
-#define Q_MV_TVOS(major, minor) (QSysInfo::MV_TVOS | major << 4 | minor)
-#define Q_MV_WATCHOS(major, minor) (QSysInfo::MV_WATCHOS | major << 4 | minor)
- enum QT_DEPRECATED_X("Use QOperatingSystemVersion") MacVersion {
- MV_None = 0xffff,
- MV_Unknown = 0x0000,
-
- /* version */
- MV_9 = Q_MV_OSX(9, 0),
- MV_10_0 = Q_MV_OSX(10, 0),
- MV_10_1 = Q_MV_OSX(10, 1),
- MV_10_2 = Q_MV_OSX(10, 2),
- MV_10_3 = Q_MV_OSX(10, 3),
- MV_10_4 = Q_MV_OSX(10, 4),
- MV_10_5 = Q_MV_OSX(10, 5),
- MV_10_6 = Q_MV_OSX(10, 6),
- MV_10_7 = Q_MV_OSX(10, 7),
- MV_10_8 = Q_MV_OSX(10, 8),
- MV_10_9 = Q_MV_OSX(10, 9),
- MV_10_10 = Q_MV_OSX(10, 10),
- MV_10_11 = Q_MV_OSX(10, 11),
- MV_10_12 = Q_MV_OSX(10, 12),
-
- /* codenames */
- MV_CHEETAH = MV_10_0,
- MV_PUMA = MV_10_1,
- MV_JAGUAR = MV_10_2,
- MV_PANTHER = MV_10_3,
- MV_TIGER = MV_10_4,
- MV_LEOPARD = MV_10_5,
- MV_SNOWLEOPARD = MV_10_6,
- MV_LION = MV_10_7,
- MV_MOUNTAINLION = MV_10_8,
- MV_MAVERICKS = MV_10_9,
- MV_YOSEMITE = MV_10_10,
- MV_ELCAPITAN = MV_10_11,
- MV_SIERRA = MV_10_12,
-
- /* iOS */
- MV_IOS = 1 << 8,
- MV_IOS_4_3 = Q_MV_IOS(4, 3),
- MV_IOS_5_0 = Q_MV_IOS(5, 0),
- MV_IOS_5_1 = Q_MV_IOS(5, 1),
- MV_IOS_6_0 = Q_MV_IOS(6, 0),
- MV_IOS_6_1 = Q_MV_IOS(6, 1),
- MV_IOS_7_0 = Q_MV_IOS(7, 0),
- MV_IOS_7_1 = Q_MV_IOS(7, 1),
- MV_IOS_8_0 = Q_MV_IOS(8, 0),
- MV_IOS_8_1 = Q_MV_IOS(8, 1),
- MV_IOS_8_2 = Q_MV_IOS(8, 2),
- MV_IOS_8_3 = Q_MV_IOS(8, 3),
- MV_IOS_8_4 = Q_MV_IOS(8, 4),
- MV_IOS_9_0 = Q_MV_IOS(9, 0),
- MV_IOS_9_1 = Q_MV_IOS(9, 1),
- MV_IOS_9_2 = Q_MV_IOS(9, 2),
- MV_IOS_9_3 = Q_MV_IOS(9, 3),
- MV_IOS_10_0 = Q_MV_IOS(10, 0),
-
- /* tvOS */
- MV_TVOS = 1 << 9,
- MV_TVOS_9_0 = Q_MV_TVOS(9, 0),
- MV_TVOS_9_1 = Q_MV_TVOS(9, 1),
- MV_TVOS_9_2 = Q_MV_TVOS(9, 2),
- MV_TVOS_10_0 = Q_MV_TVOS(10, 0),
-
- /* watchOS */
- MV_WATCHOS = 1 << 10,
- MV_WATCHOS_2_0 = Q_MV_WATCHOS(2, 0),
- MV_WATCHOS_2_1 = Q_MV_WATCHOS(2, 1),
- MV_WATCHOS_2_2 = Q_MV_WATCHOS(2, 2),
- MV_WATCHOS_3_0 = Q_MV_WATCHOS(3, 0)
- };
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion;
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion();
-#else
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion = WV_None;
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion() { return WV_None; }
-#endif
-#if defined(Q_OS_MAC)
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion;
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion();
-#else
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion = MV_None;
- QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion() { return MV_None; }
-#endif
-QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(5, 9)
static QString buildCpuArchitecture();
static QString currentCpuArchitecture();
@@ -244,7 +54,5 @@ QT_WARNING_POP
static QByteArray bootUniqueId();
};
-#undef QT_SYSINFO_DEPRECATED_X
-
QT_END_NAMESPACE
#endif // QSYSINFO_H
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 2afd84bcd3..b29f2e9496 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#ifndef QGLOBAL_H
-# include <QtCore/qglobal.h>
+#if 0
+#pragma qt_class(QtSystemDetection)
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
#endif
#ifndef QSYSTEMDETECTION_H
@@ -53,6 +19,7 @@
IOS - iOS
WATCHOS - watchOS
TVOS - tvOS
+ VISIONOS - visionOS
WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
CYGWIN - Cygwin
SOLARIS - Sun Solaris
@@ -72,6 +39,7 @@
ANDROID - Android platform
HAIKU - Haiku
WEBOS - LG WebOS
+ WASM - WebAssembly
The following operating systems have variants:
LINUX - both Q_OS_LINUX and Q_OS_ANDROID are defined when building for Android
@@ -84,20 +52,18 @@
#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
# include <TargetConditionals.h>
+# define Q_OS_APPLE
# if defined(TARGET_OS_MAC) && TARGET_OS_MAC
# define Q_OS_DARWIN
# define Q_OS_BSD4
-# ifdef __LP64__
-# define Q_OS_DARWIN64
-# else
-# define Q_OS_DARWIN32
-# endif
# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
# define QT_PLATFORM_UIKIT
# if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH
# define Q_OS_WATCHOS
# elif defined(TARGET_OS_TV) && TARGET_OS_TV
# define Q_OS_TVOS
+# elif defined(TARGET_OS_VISION) && TARGET_OS_VISION
+# define Q_OS_VISIONOS
# else
# // TARGET_OS_IOS is only available in newer SDKs,
# // so assume any other iOS-based platform is iOS for now
@@ -128,8 +94,6 @@
# define Q_OS_SOLARIS
#elif defined(hpux) || defined(__hpux)
# define Q_OS_HPUX
-#elif defined(__native_client__)
-# define Q_OS_NACL
#elif defined(__EMSCRIPTEN__)
# define Q_OS_WASM
#elif defined(__linux__) || defined(__linux)
@@ -161,7 +125,7 @@
# define Q_OS_INTEGRITY
#elif defined(__rtems__)
# define Q_OS_RTEMS
-#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */
+#elif defined(__vxworks)
# define Q_OS_VXWORKS
#elif defined(__HAIKU__)
# define Q_OS_HAIKU
@@ -173,12 +137,10 @@
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
# define Q_OS_WINDOWS
# define Q_OS_WIN
-# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// On Windows, pointers to dllimport'ed variables are not constant expressions,
// so to keep to certain initializations (like QMetaObject) constexpr, we need
// to use functions instead.
-# define QT_NO_DATA_RELOCATION
-# endif
+# define QT_NO_DATA_RELOCATION
#endif
#if defined(Q_OS_WIN)
@@ -189,87 +151,77 @@
// Compatibility synonyms
#ifdef Q_OS_DARWIN
-#define Q_OS_MAC
-#endif
-#ifdef Q_OS_DARWIN32
-#define Q_OS_MAC32
-#endif
-#ifdef Q_OS_DARWIN64
-#define Q_OS_MAC64
-#endif
-#ifdef Q_OS_MACOS
-#define Q_OS_MACX
-#define Q_OS_OSX
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunknown-pragmas"
+# define Q_OS_MAC // FIXME: Deprecate
+# ifdef __LP64__
+# define Q_OS_DARWIN64
+# pragma clang deprecated(Q_OS_DARWIN64, "use Q_OS_DARWIN and QT_POINTER_SIZE/Q_PROCESSOR_* instead")
+# define Q_OS_MAC64
+# pragma clang deprecated(Q_OS_MAC64, "use Q_OS_DARWIN and QT_POINTER_SIZE/Q_PROCESSOR_* instead")
+# else
+# define Q_OS_DARWIN32
+# pragma clang deprecated(Q_OS_DARWIN32, "use Q_OS_DARWIN and QT_POINTER_SIZE/Q_PROCESSOR_* instead")
+# define Q_OS_MAC32
+# pragma clang deprecated(Q_OS_MAC32, "use Q_OS_DARWIN and QT_POINTER_SIZE/Q_PROCESSOR_* instead")
+# endif
+# ifdef Q_OS_MACOS
+# define Q_OS_MACX
+# pragma clang deprecated(Q_OS_MACX, "use Q_OS_MACOS instead")
+# define Q_OS_OSX
+# pragma clang deprecated(Q_OS_OSX, "use Q_OS_MACOS instead")
+# endif
+# pragma clang diagnostic pop
#endif
#ifdef Q_OS_DARWIN
# include <Availability.h>
# include <AvailabilityMacros.h>
-#
-# ifdef Q_OS_MACOS
-# if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6
-# undef __MAC_OS_X_VERSION_MIN_REQUIRED
-# define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_6
-# endif
-# if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
-# undef MAC_OS_X_VERSION_MIN_REQUIRED
-# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
-# endif
-# endif
-#
-# // Numerical checks are preferred to named checks, but to be safe
-# // we define the missing version names in case Qt uses them.
-#
-# if !defined(__MAC_10_11)
-# define __MAC_10_11 101100
-# endif
-# if !defined(__MAC_10_12)
-# define __MAC_10_12 101200
-# endif
-# if !defined(__MAC_10_13)
-# define __MAC_10_13 101300
-# endif
-# if !defined(__MAC_10_14)
-# define __MAC_10_14 101400
-# endif
-# if !defined(__MAC_10_15)
-# define __MAC_10_15 101500
-# endif
-# if !defined(MAC_OS_X_VERSION_10_11)
-# define MAC_OS_X_VERSION_10_11 __MAC_10_11
-# endif
-# if !defined(MAC_OS_X_VERSION_10_12)
-# define MAC_OS_X_VERSION_10_12 __MAC_10_12
-# endif
-# if !defined(MAC_OS_X_VERSION_10_13)
-# define MAC_OS_X_VERSION_10_13 __MAC_10_13
-# endif
-# if !defined(MAC_OS_X_VERSION_10_14)
-# define MAC_OS_X_VERSION_10_14 __MAC_10_14
-# endif
-# if !defined(MAC_OS_X_VERSION_10_15)
-# define MAC_OS_X_VERSION_10_15 __MAC_10_15
-# endif
-#
-# if !defined(__IPHONE_10_0)
-# define __IPHONE_10_0 100000
-# endif
-# if !defined(__IPHONE_10_1)
-# define __IPHONE_10_1 100100
-# endif
-# if !defined(__IPHONE_10_2)
-# define __IPHONE_10_2 100200
-# endif
-# if !defined(__IPHONE_10_3)
-# define __IPHONE_10_3 100300
-# endif
-# if !defined(__IPHONE_11_0)
-# define __IPHONE_11_0 110000
-# endif
-# if !defined(__IPHONE_12_0)
-# define __IPHONE_12_0 120000
-# endif
-#endif
+
+# define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) \
+ ((defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && macos != __MAC_NA && __MAC_OS_X_VERSION_MAX_ALLOWED >= macos) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MAX_ALLOWED >= ios) || \
+ (defined(__TV_OS_VERSION_MAX_ALLOWED) && tvos != __TVOS_NA && __TV_OS_VERSION_MAX_ALLOWED >= tvos) || \
+ (defined(__WATCH_OS_VERSION_MAX_ALLOWED) && watchos != __WATCHOS_NA && __WATCH_OS_VERSION_MAX_ALLOWED >= watchos))
+
+# define QT_DARWIN_DEPLOYMENT_TARGET_BELOW(macos, ios, tvos, watchos) \
+ ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && macos != __MAC_NA && __MAC_OS_X_VERSION_MIN_REQUIRED < macos) || \
+ (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MIN_REQUIRED < ios) || \
+ (defined(__TV_OS_VERSION_MIN_REQUIRED) && tvos != __TVOS_NA && __TV_OS_VERSION_MIN_REQUIRED < tvos) || \
+ (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && watchos != __WATCHOS_NA && __WATCH_OS_VERSION_MIN_REQUIRED < watchos))
+
+# define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) \
+ QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, __TVOS_NA, __WATCHOS_NA)
+# define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) \
+ QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, __IPHONE_NA, __TVOS_NA, __WATCHOS_NA)
+# define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) \
+ QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, ios, __TVOS_NA, __WATCHOS_NA)
+# define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) \
+ QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, __IPHONE_NA, tvos, __WATCHOS_NA)
+# define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) \
+ QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, __IPHONE_NA, __TVOS_NA, watchos)
+
+# define QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(macos, ios) \
+ QT_DARWIN_DEPLOYMENT_TARGET_BELOW(macos, ios, __TVOS_NA, __WATCHOS_NA)
+# define QT_MACOS_DEPLOYMENT_TARGET_BELOW(macos) \
+ QT_DARWIN_DEPLOYMENT_TARGET_BELOW(macos, __IPHONE_NA, __TVOS_NA, __WATCHOS_NA)
+# define QT_IOS_DEPLOYMENT_TARGET_BELOW(ios) \
+ QT_DARWIN_DEPLOYMENT_TARGET_BELOW(__MAC_NA, ios, __TVOS_NA, __WATCHOS_NA)
+# define QT_TVOS_DEPLOYMENT_TARGET_BELOW(tvos) \
+ QT_DARWIN_DEPLOYMENT_TARGET_BELOW(__MAC_NA, __IPHONE_NA, tvos, __WATCHOS_NA)
+# define QT_WATCHOS_DEPLOYMENT_TARGET_BELOW(watchos) \
+ QT_DARWIN_DEPLOYMENT_TARGET_BELOW(__MAC_NA, __IPHONE_NA, __TVOS_NA, watchos)
+
+#else // !Q_OS_DARWIN
+
+#define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) (0)
+#define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) (0)
+#define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) (0)
+#define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) (0)
+#define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) (0)
+#define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) (0)
+
+#endif // Q_OS_DARWIN
#ifdef __LSB_VERSION__
# if __LSB_VERSION__ < 40
@@ -280,4 +232,11 @@
#endif
#endif
+#if defined (__ELF__)
+# define Q_OF_ELF
+#endif
+#if defined (__MACH__) && defined (__APPLE__)
+# define Q_OF_MACH_O
+#endif
+
#endif // QSYSTEMDETECTION_H
diff --git a/src/corelib/global/qsystemdetection.qdoc b/src/corelib/global/qsystemdetection.qdoc
new file mode 100644
index 0000000000..a48a79bbb2
--- /dev/null
+++ b/src/corelib/global/qsystemdetection.qdoc
@@ -0,0 +1,219 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \headerfile <QtSystemDetection>
+ \inmodule QtCore
+ \title Platform-specific Macro Definitions
+ \ingroup funclists
+
+ \brief The <QtSystemDetection> header file includes various
+ platfrom-specific macros.
+
+ The <QtSystemDetection> header file declares a range of macros (Q_OS_*)
+ that are defined for the specified platforms. For example, Q_OS_UNIX which
+ is defined for Unix-based systems.
+
+ The purpose of these macros is to enable programmers to add
+ platform-specific code to their application.
+*/
+
+/*!
+ \macro Q_OS_DARWIN
+ \relates <QtSystemDetection>
+
+ Defined on Darwin-based operating systems such as \macos, iOS, watchOS, and tvOS.
+
+ \note Unless you are dealing with code specific to the Darwin kernel,
+ prefer Q_OS_APPLE to refer to the family of Apple operating systems.
+*/
+
+/*!
+ \macro Q_OS_APPLE
+ \relates <QtSystemDetection>
+
+ Defined on Apple operating systems such as \macos, iOS, watchOS, and tvOS.
+*/
+
+/*!
+ \macro Q_OS_MAC
+ \relates <QtSystemDetection>
+
+ Deprecated synonym for \c Q_OS_DARWIN. Do not use.
+*/
+
+/*!
+ \macro Q_OS_OSX
+ \relates <QtSystemDetection>
+
+ Deprecated synonym for \c Q_OS_MACOS. Do not use.
+*/
+
+/*!
+ \macro Q_OS_MACOS
+ \relates <QtSystemDetection>
+
+ Defined on \macos.
+*/
+
+/*!
+ \macro Q_OS_IOS
+ \relates <QtSystemDetection>
+
+ Defined on iOS.
+*/
+
+/*!
+ \macro Q_OS_WATCHOS
+ \relates <QtSystemDetection>
+
+ Defined on watchOS.
+*/
+
+/*!
+ \macro Q_OS_TVOS
+ \relates <QtSystemDetection>
+
+ Defined on tvOS.
+*/
+
+/*!
+ \macro Q_OS_VISIONOS
+ \relates <QtSystemDetection>
+
+ Defined on visionOS.
+*/
+
+/*!
+ \macro Q_OS_WIN
+ \relates <QtSystemDetection>
+
+ Defined on all supported versions of Windows. That is, if
+ \l Q_OS_WIN32 or \l Q_OS_WIN64 is defined.
+*/
+
+/*!
+ \macro Q_OS_WINDOWS
+ \relates <QtSystemDetection>
+
+ This is a synonym for Q_OS_WIN.
+*/
+
+/*!
+ \macro Q_OS_WIN32
+ \relates <QtSystemDetection>
+
+ Defined on 32-bit and 64-bit versions of Windows.
+*/
+
+/*!
+ \macro Q_OS_WIN64
+ \relates <QtSystemDetection>
+
+ Defined on 64-bit versions of Windows.
+*/
+
+/*!
+ \macro Q_OS_CYGWIN
+ \relates <QtSystemDetection>
+
+ Defined on Cygwin.
+*/
+
+/*!
+ \macro Q_OS_SOLARIS
+ \relates <QtSystemDetection>
+
+ Defined on Sun Solaris.
+*/
+
+/*!
+ \macro Q_OS_HPUX
+ \relates <QtSystemDetection>
+
+ Defined on HP-UX.
+*/
+
+/*!
+ \macro Q_OS_LINUX
+ \relates <QtSystemDetection>
+
+ Defined on Linux.
+*/
+
+/*!
+ \macro Q_OS_ANDROID
+ \relates <QtSystemDetection>
+
+ Defined on Android.
+*/
+
+/*!
+ \macro Q_OS_FREEBSD
+ \relates <QtSystemDetection>
+
+ Defined on FreeBSD.
+*/
+
+/*!
+ \macro Q_OS_NETBSD
+ \relates <QtSystemDetection>
+
+ Defined on NetBSD.
+*/
+
+/*!
+ \macro Q_OS_OPENBSD
+ \relates <QtSystemDetection>
+
+ Defined on OpenBSD.
+*/
+
+/*!
+ \macro Q_OS_AIX
+ \relates <QtSystemDetection>
+
+ Defined on AIX.
+*/
+
+/*!
+ \macro Q_OS_HURD
+ \relates <QtSystemDetection>
+
+ Defined on GNU Hurd.
+*/
+
+/*!
+ \macro Q_OS_QNX
+ \relates <QtSystemDetection>
+
+ Defined on QNX Neutrino.
+*/
+
+/*!
+ \macro Q_OS_LYNX
+ \relates <QtSystemDetection>
+
+ Defined on LynxOS.
+*/
+
+/*!
+ \macro Q_OS_BSD4
+ \relates <QtSystemDetection>
+
+ Defined on any BSD 4.4 system.
+*/
+
+/*!
+ \macro Q_OS_UNIX
+ \relates <QtSystemDetection>
+
+ Defined on any UNIX BSD/SYSV system.
+*/
+
+/*!
+ \macro Q_OS_WASM
+ \relates <QtSystemDetection>
+
+ Defined on Web Assembly.
+*/
diff --git a/src/corelib/global/qt_pch.h b/src/corelib/global/qt_pch.h
index 8e59ace85d..3f224cda85 100644
--- a/src/corelib/global/qt_pch.h
+++ b/src/corelib/global/qt_pch.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
* This is a precompiled header file for use in Xcode / Mac GCC /
@@ -50,26 +14,28 @@
// for rand_s, _CRT_RAND_S must be #defined before #including stdlib.h.
// put it at the beginning so some indirect inclusion doesn't break it
#ifndef _CRT_RAND_S
-#define _CRT_RAND_S
+# define _CRT_RAND_S
#endif
#include <stdlib.h>
#include <qglobal.h>
#ifdef Q_OS_WIN
-# ifdef Q_CC_MINGW
+# ifdef Q_CC_MINGW
// <unistd.h> must be included before any other header pulls in <time.h>.
-# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
-# endif
-# define _POSIX_
-# include <limits.h>
-# undef _POSIX_
-#endif
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+# endif // Q_CC_MINGW
+# define _POSIX_
+# include <limits.h>
+# undef _POSIX_
+#endif // Q_OS_WIN
#include <qcoreapplication.h>
#include <qcoreevent.h>
#include <qiodevice.h>
#include <qlist.h>
-#include <qvariant.h> /* All moc genereated code has this include */
+#include <qvariant.h> /* All moc generated code has this include */
#include <qobject.h>
-#include <qregularexpression.h>
+#if QT_CONFIG(regularexpression)
+# include <qregularexpression.h>
+#endif
#include <qscopedpointer.h>
#include <qshareddata.h>
#include <qstring.h>
diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h
index 67ba27f072..5586d0b927 100644
--- a/src/corelib/global/qt_windows.h
+++ b/src/corelib/global/qt_windows.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_WINDOWS_H
#define QT_WINDOWS_H
@@ -45,17 +9,17 @@
#pragma qt_sync_stop_processing
#endif
-#if defined(Q_CC_MINGW)
-// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation
-# ifndef WINVER
-# define WINVER 0x601
-# endif
-# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x601
-# endif
-# ifndef NTDDI_VERSION
-# define NTDDI_VERSION 0x06000000
-# endif
+#ifndef WINVER
+# define WINVER 0x0A00 // _WIN32_WINNT_WIN10
+#endif
+#ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0A00
+#endif
+#ifndef _WIN32_IE
+# define _WIN32_IE 0x0A00
+#endif
+#ifndef NTDDI_VERSION
+# define NTDDI_VERSION 0x0A00000C // NTDDI_WIN10_NI
#endif
#ifndef NOMINMAX
@@ -63,13 +27,6 @@
#endif
#include <windows.h>
-#if defined(_WIN32_IE) && _WIN32_IE < 0x0501
-# undef _WIN32_IE
-#endif
-#if !defined(_WIN32_IE)
-# define _WIN32_IE 0x0501
-#endif
-
// already defined when compiled with WINVER >= 0x0500
#ifndef SPI_SETMENUANIMATION
#define SPI_SETMENUANIMATION 0x1003
diff --git a/src/corelib/global/qtclasshelpermacros.h b/src/corelib/global/qtclasshelpermacros.h
new file mode 100644
index 0000000000..8839e80fb9
--- /dev/null
+++ b/src/corelib/global/qtclasshelpermacros.h
@@ -0,0 +1,132 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTCLASSHELPERMACROS_H
+#define QTCLASSHELPERMACROS_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#if 0
+#pragma qt_class(QtClassHelperMacros)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(__cplusplus)
+
+/*
+ Some classes do not permit copies to be made of an object. These
+ classes contains a private copy constructor and assignment
+ operator to disable copying (the compiler gives an error message).
+*/
+#define Q_DISABLE_COPY(Class) \
+ Class(const Class &) = delete;\
+ Class &operator=(const Class &) = delete;
+
+#define Q_DISABLE_COPY_MOVE(Class) \
+ Q_DISABLE_COPY(Class) \
+ Class(Class &&) = delete; \
+ Class &operator=(Class &&) = delete;
+
+/*
+ Implementing a move assignment operator using an established
+ technique (move-and-swap, pure swap) is just boilerplate.
+ Here's a couple of *private* macros for convenience.
+
+ To know which one to use:
+
+ * if you don't have a move constructor (*) => use pure swap;
+ * if you have a move constructor, then
+ * if your class holds just memory (no file handles, no user-defined
+ datatypes, etc.) => use pure swap;
+ * use move and swap.
+
+ The preference should always go for the move-and-swap one, as it
+ will deterministically destroy the data previously held in *this,
+ and not "dump" it in the moved-from object (which may then be alive
+ for longer).
+
+ The requirement for either macro is the presence of a member swap(),
+ which any value class that defines its own special member functions
+ should have anyhow.
+
+ (*) Many value classes in Qt do not have move constructors; mostly,
+ the implicitly shared classes using QSharedDataPointer and friends.
+ The reason is mostly historical: those classes require either an
+ out-of-line move constructor, which we could not provide before we
+ made C++11 mandatory (and that we don't like anyhow), or
+ an out-of-line dtor for the Q(E)DSP<Private> member (cf. QPixmap).
+
+ If you can however add a move constructor to a class lacking it,
+ consider doing so, then reevaluate which macro to choose.
+*/
+#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class) \
+ Class &operator=(Class &&other) noexcept { \
+ Class moved(std::move(other)); \
+ swap(moved); \
+ return *this; \
+ }
+
+#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class) \
+ Class &operator=(Class &&other) noexcept { \
+ swap(other); \
+ return *this; \
+ }
+
+template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
+template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
+{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
+
+class QObject;
+class QObjectPrivate;
+namespace QtPrivate {
+ template <typename ObjPrivate> void assertObjectType(QObjectPrivate *d);
+ inline const QObject *getQObject(const QObjectPrivate *d);
+}
+
+#define Q_DECLARE_PRIVATE(Class) \
+ inline Class##Private* d_func() noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
+ inline const Class##Private* d_func() const noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
+ friend class Class##Private;
+
+#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
+ inline Class##Private* d_func() noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
+ inline const Class##Private* d_func() const noexcept \
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
+ friend class Class##Private;
+
+#define Q_DECLARE_PUBLIC(Class) \
+ inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); } \
+ inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); } \
+ friend class Class; \
+ friend const QObject *QtPrivate::getQObject(const QObjectPrivate *d); \
+ template <typename ObjPrivate> friend void QtPrivate::assertObjectType(QObjectPrivate *d);
+
+#define Q_D(Class) Class##Private * const d = d_func()
+#define Q_Q(Class) Class * const q = q_func()
+
+/*
+ Specialize a shared type with:
+
+ Q_DECLARE_SHARED(type)
+
+ where 'type' is the name of the type to specialize. NOTE: shared
+ types must define a member-swap, and be defined in the same
+ namespace as Qt for this to work.
+*/
+
+#define Q_DECLARE_SHARED(TYPE) \
+Q_DECLARE_TYPEINFO(TYPE, Q_RELOCATABLE_TYPE); \
+inline void swap(TYPE &value1, TYPE &value2) \
+ noexcept(noexcept(value1.swap(value2))) \
+{ value1.swap(value2); }
+
+#endif // __cplusplus
+
+QT_END_NAMESPACE
+
+#endif // QTCLASSHELPERMACROS_H
diff --git a/src/corelib/global/qtclasshelpermacros.qdoc b/src/corelib/global/qtclasshelpermacros.qdoc
new file mode 100644
index 0000000000..8eaee7e5d2
--- /dev/null
+++ b/src/corelib/global/qtclasshelpermacros.qdoc
@@ -0,0 +1,59 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro Q_DISABLE_COPY(Class)
+ \relates <QtClassHelperMacros>
+
+ Disables the use of copy constructors and assignment operators
+ for the given \a Class.
+
+ Instances of subclasses of QObject should not be thought of as
+ values that can be copied or assigned, but as unique identities.
+ This means that when you create your own subclass of QObject
+ (director or indirect), you should \e not give it a copy constructor
+ or an assignment operator. However, it may not enough to simply
+ omit them from your class, because, if you mistakenly write some code
+ that requires a copy constructor or an assignment operator (it's easy
+ to do), your compiler will thoughtfully create it for you. You must
+ do more.
+
+ The curious user will have seen that the Qt classes derived
+ from QObject typically include this macro in a private section:
+
+ \snippet code/src_corelib_global_qglobal.cpp 43
+
+ It declares a copy constructor and an assignment operator in the
+ private section, so that if you use them by mistake, the compiler
+ will report an error.
+
+ \snippet code/src_corelib_global_qglobal.cpp 44
+
+ But even this might not catch absolutely every case. You might be
+ tempted to do something like this:
+
+ \snippet code/src_corelib_global_qglobal.cpp 45
+
+ First of all, don't do that. Most compilers will generate code that
+ uses the copy constructor, so the privacy violation error will be
+ reported, but your C++ compiler is not required to generate code for
+ this statement in a specific way. It could generate code using
+ \e{neither} the copy constructor \e{nor} the assignment operator we
+ made private. In that case, no error would be reported, but your
+ application would probably crash when you called a member function
+ of \c{w}.
+
+ \sa Q_DISABLE_COPY_MOVE
+*/
+
+/*!
+ \macro Q_DISABLE_COPY_MOVE(Class)
+ \relates <QtClassHelperMacros>
+
+ A convenience macro that disables the use of copy constructors, assignment
+ operators, move constructors and move assignment operators for the given
+ \a Class.
+
+ \sa Q_DISABLE_COPY
+ \since 5.13
+*/
diff --git a/src/corelib/global/qtconfiginclude.h b/src/corelib/global/qtconfiginclude.h
new file mode 100644
index 0000000000..8b22a47ac7
--- /dev/null
+++ b/src/corelib/global/qtconfiginclude.h
@@ -0,0 +1,22 @@
+// Copyright (C) 2022 Intel Corporation
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTCONFIGINCLUDE_H
+#define QTCONFIGINCLUDE_H
+
+#if 0
+# pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qconfig.h>
+
+#ifdef QT_BOOTSTRAPPED
+// qconfig-bootstrapped.h is not supposed to be a part of the synced header files. So we find it by
+// the include path specified for Bootstrap library in the source tree instead of the build tree as
+// it's done for regular header files.
+#include "qconfig-bootstrapped.h"
+#else
+#include <QtCore/qtcore-config.h>
+#endif
+
+#endif // QTCONFIGINCLUDE_H
diff --git a/src/corelib/global/qtconfigmacros.h b/src/corelib/global/qtconfigmacros.h
new file mode 100644
index 0000000000..03d52d885a
--- /dev/null
+++ b/src/corelib/global/qtconfigmacros.h
@@ -0,0 +1,209 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTCONFIGMACROS_H
+#define QTCONFIGMACROS_H
+
+#if 0
+# pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qtconfiginclude.h>
+#include <QtCore/qtversionchecks.h>
+
+#include <assert.h>
+
+/*
+ The Qt modules' export macros.
+ The options are:
+ - defined(QT_STATIC): Qt was built or is being built in static mode
+ - defined(QT_SHARED): Qt was built or is being built in shared/dynamic mode
+ If neither was defined, then QT_SHARED is implied. If Qt was compiled in static
+ mode, QT_STATIC is defined in qconfig.h. In shared mode, QT_STATIC is implied
+ for the bootstrapped tools.
+*/
+
+#ifdef QT_BOOTSTRAPPED
+# ifdef QT_SHARED
+# error "QT_SHARED and QT_BOOTSTRAPPED together don't make sense. Please fix the build"
+# elif !defined(QT_STATIC)
+# define QT_STATIC
+# endif
+#endif
+
+#if defined(QT_SHARED) || !defined(QT_STATIC)
+# ifdef QT_STATIC
+# error "Both QT_SHARED and QT_STATIC defined, please make up your mind"
+# endif
+# ifndef QT_SHARED
+# define QT_SHARED
+# endif
+#endif
+
+/*
+ No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
+ for Qt's internal unit tests. If you want slower loading times and more
+ symbols that can vanish from version to version, feel free to define QT_BUILD_INTERNAL.
+
+ \note After adding Q_AUTOTEST_EXPORT to a method, you'll need to wrap any unittests
+ that will use that method in "#ifdef QT_BUILD_INTERNAL".
+*/
+#if defined(QT_BUILD_INTERNAL) && defined(QT_BUILDING_QT) && defined(QT_SHARED)
+# define Q_AUTOTEST_EXPORT Q_DECL_EXPORT
+#elif defined(QT_BUILD_INTERNAL) && defined(QT_SHARED)
+# define Q_AUTOTEST_EXPORT Q_DECL_IMPORT
+#else
+# define Q_AUTOTEST_EXPORT
+#endif
+
+/*
+ The QT_CONFIG macro implements a safe compile time check for features of Qt.
+ Features can be in three states:
+ 0 or undefined: This will lead to a compile error when testing for it
+ -1: The feature is not available
+ 1: The feature is available
+*/
+#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)
+#define QT_REQUIRE_CONFIG(feature) static_assert(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.")
+
+/* moc compats (signals/slots) */
+#ifndef QT_MOC_COMPAT
+# define QT_MOC_COMPAT
+#else
+# undef QT_MOC_COMPAT
+# define QT_MOC_COMPAT
+#endif
+
+/*
+ Debugging and error handling
+*/
+
+#if !defined(QT_NO_DEBUG) && !defined(QT_DEBUG)
+# define QT_DEBUG
+#endif
+
+// valid for both C and C++
+#define QT_MANGLE_NAMESPACE0(x) x
+#define QT_MANGLE_NAMESPACE1(a, b) a##_##b
+#define QT_MANGLE_NAMESPACE2(a, b) QT_MANGLE_NAMESPACE1(a,b)
+#if !defined(QT_NAMESPACE) || defined(Q_MOC_RUN) /* user namespace */
+# define QT_MANGLE_NAMESPACE(name) name
+#else
+# define QT_MANGLE_NAMESPACE(name) QT_MANGLE_NAMESPACE2( \
+ QT_MANGLE_NAMESPACE0(name), QT_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#endif
+
+#ifdef __cplusplus
+
+#if !defined(QT_NAMESPACE) || defined(Q_MOC_RUN) /* user namespace */
+
+# define QT_PREPEND_NAMESPACE(name) ::name
+# define QT_USE_NAMESPACE
+# define QT_BEGIN_NAMESPACE
+# define QT_END_NAMESPACE
+# define QT_BEGIN_INCLUDE_NAMESPACE
+# define QT_END_INCLUDE_NAMESPACE
+# define QT_FORWARD_DECLARE_CLASS(name) class name;
+# define QT_FORWARD_DECLARE_STRUCT(name) struct name;
+
+#elif defined(QT_INLINE_NAMESPACE) /* user inline namespace FIXME in Qt 7: Default */
+
+# define QT_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_USE_NAMESPACE
+# define QT_BEGIN_NAMESPACE inline namespace QT_NAMESPACE {
+# define QT_END_NAMESPACE }
+# define QT_BEGIN_INCLUDE_NAMESPACE }
+# define QT_END_INCLUDE_NAMESPACE inline namespace QT_NAMESPACE {
+# define QT_FORWARD_DECLARE_CLASS(name) \
+QT_BEGIN_NAMESPACE class name; QT_END_NAMESPACE
+
+# define QT_FORWARD_DECLARE_STRUCT(name) \
+QT_BEGIN_NAMESPACE struct name; QT_END_NAMESPACE
+
+inline namespace QT_NAMESPACE {}
+
+#else /* user namespace */
+
+# define QT_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_USE_NAMESPACE using namespace ::QT_NAMESPACE;
+# define QT_BEGIN_NAMESPACE namespace QT_NAMESPACE {
+# define QT_END_NAMESPACE }
+# define QT_BEGIN_INCLUDE_NAMESPACE }
+# define QT_END_INCLUDE_NAMESPACE namespace QT_NAMESPACE {
+# define QT_FORWARD_DECLARE_CLASS(name) \
+ QT_BEGIN_NAMESPACE class name; QT_END_NAMESPACE \
+ using QT_PREPEND_NAMESPACE(name);
+
+# define QT_FORWARD_DECLARE_STRUCT(name) \
+ QT_BEGIN_NAMESPACE struct name; QT_END_NAMESPACE \
+ using QT_PREPEND_NAMESPACE(name);
+
+namespace QT_NAMESPACE {}
+
+# ifndef QT_BOOTSTRAPPED
+# ifndef QT_NO_USING_NAMESPACE
+ /*
+ This expands to a "using QT_NAMESPACE" also in _header files_.
+ It is the only way the feature can be used without too much
+ pain, but if people _really_ do not want it they can add
+ QT_NO_USING_NAMESPACE to their build configuration.
+ */
+ QT_USE_NAMESPACE
+# endif
+# endif
+
+#endif /* user namespace */
+
+#else /* __cplusplus */
+
+# define QT_BEGIN_NAMESPACE
+# define QT_END_NAMESPACE
+# define QT_USE_NAMESPACE
+# define QT_BEGIN_INCLUDE_NAMESPACE
+# define QT_END_INCLUDE_NAMESPACE
+
+#endif /* __cplusplus */
+
+/* ### Qt 6.9 (or later): remove *_MOC_* macros (moc does not need them since 6.5) */
+#ifndef QT_BEGIN_MOC_NAMESPACE
+# define QT_BEGIN_MOC_NAMESPACE QT_USE_NAMESPACE
+#endif
+#ifndef QT_END_MOC_NAMESPACE
+# define QT_END_MOC_NAMESPACE
+#endif
+
+/*
+ Strict mode
+*/
+#ifdef QT_ENABLE_STRICT_MODE_UP_TO
+#ifndef QT_DISABLE_DEPRECATED_UP_TO
+# define QT_DISABLE_DEPRECATED_UP_TO QT_ENABLE_STRICT_MODE_UP_TO
+#endif
+
+#if QT_ENABLE_STRICT_MODE_UP_TO >= QT_VERSION_CHECK(6, 0, 0)
+# define QT_NO_FOREACH
+# define QT_NO_CAST_FROM_ASCII
+# define QT_NO_CAST_TO_ASCII
+# define QT_NO_CAST_FROM_BYTEARRAY
+# define QT_NO_URL_CAST_FROM_STRING
+# define QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
+# define QT_NO_JAVA_STYLE_ITERATORS
+#endif // 6.0.0
+
+#if QT_ENABLE_STRICT_MODE_UP_TO >= QT_VERSION_CHECK(6, 6, 0)
+# define QT_NO_QEXCHANGE
+#endif // 6.6.0
+
+#if QT_ENABLE_STRICT_MODE_UP_TO >= QT_VERSION_CHECK(6, 7, 0)
+# define QT_NO_CONTEXTLESS_CONNECT
+#endif // 6.7.0
+
+#if QT_ENABLE_STRICT_MODE_UP_TO >= QT_VERSION_CHECK(6, 8, 0)
+# define QT_NO_QASCONST
+# if !defined(QT_USE_NODISCARD_FILE_OPEN) && !defined(QT_NO_USE_NODISCARD_FILE_OPEN)
+# define QT_USE_NODISCARD_FILE_OPEN
+# endif
+#endif // 6.8.0
+#endif // QT_ENABLE_STRICT_MODE_UP_TO
+
+#endif /* QTCONFIGMACROS_H */
diff --git a/src/corelib/global/qtdeprecationmarkers.h b/src/corelib/global/qtdeprecationmarkers.h
new file mode 100644
index 0000000000..6df5ebce6d
--- /dev/null
+++ b/src/corelib/global/qtdeprecationmarkers.h
@@ -0,0 +1,347 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTDEPRECATIONMARKERS_H
+#define QTDEPRECATIONMARKERS_H
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtversionchecks.h>
+#include <QtCore/qcompilerdetection.h> // for Q_DECL_DEPRECATED
+
+#if 0
+#pragma qt_class(QtDeprecationMarkers)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_NO_DEPRECATED)
+# undef QT_DEPRECATED
+# undef QT_DEPRECATED_X
+# undef QT_DEPRECATED_VARIABLE
+# undef QT_DEPRECATED_CONSTRUCTOR
+#elif !defined(QT_NO_DEPRECATED_WARNINGS)
+# undef QT_DEPRECATED
+# define QT_DEPRECATED Q_DECL_DEPRECATED
+# undef QT_DEPRECATED_X
+# define QT_DEPRECATED_X(text) Q_DECL_DEPRECATED_X(text)
+# undef QT_DEPRECATED_VARIABLE
+# define QT_DEPRECATED_VARIABLE Q_DECL_VARIABLE_DEPRECATED
+# undef QT_DEPRECATED_CONSTRUCTOR
+# define QT_DEPRECATED_CONSTRUCTOR Q_DECL_CONSTRUCTOR_DEPRECATED explicit
+#else
+# undef QT_DEPRECATED
+# define QT_DEPRECATED
+# undef QT_DEPRECATED_X
+# define QT_DEPRECATED_X(text)
+# undef QT_DEPRECATED_VARIABLE
+# define QT_DEPRECATED_VARIABLE
+# undef QT_DEPRECATED_CONSTRUCTOR
+# define QT_DEPRECATED_CONSTRUCTOR
+# undef Q_DECL_ENUMERATOR_DEPRECATED
+# define Q_DECL_ENUMERATOR_DEPRECATED
+# undef Q_DECL_ENUMERATOR_DEPRECATED_X
+# define Q_DECL_ENUMERATOR_DEPRECATED_X(ignored)
+#endif
+
+// If the deprecated macro is defined, use its value
+#if !defined(QT_DISABLE_DEPRECATED_UP_TO) && defined(QT_DISABLE_DEPRECATED_BEFORE)
+# define QT_DISABLE_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_BEFORE
+#endif
+
+// If the deprecated macro is defined, use its value
+#if !defined(QT_WARN_DEPRECATED_UP_TO) && defined(QT_DEPRECATED_WARNINGS_SINCE)
+# define QT_WARN_DEPRECATED_UP_TO QT_DEPRECATED_WARNINGS_SINCE
+#endif
+
+#ifndef QT_WARN_DEPRECATED_UP_TO
+# ifdef QT_DISABLE_DEPRECATED_UP_TO
+# define QT_WARN_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_UP_TO
+# else
+# define QT_WARN_DEPRECATED_UP_TO QT_VERSION
+# endif
+#endif
+
+#ifndef QT_DISABLE_DEPRECATED_UP_TO
+#define QT_DISABLE_DEPRECATED_UP_TO QT_VERSION_CHECK(5, 0, 0)
+#endif
+
+/*
+ QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than
+ the deprecation point specified.
+
+ Use it to specify from which version of Qt a function or class has been deprecated
+
+ Example:
+ #if QT_DEPRECATED_SINCE(5,1)
+ QT_DEPRECATED void deprecatedFunction(); //function deprecated since Qt 5.1
+ #endif
+
+*/
+#ifdef QT_DEPRECATED
+#define QT_DEPRECATED_SINCE(major, minor) (QT_VERSION_CHECK(major, minor, 0) > QT_DISABLE_DEPRECATED_UP_TO)
+#else
+#define QT_DEPRECATED_SINCE(major, minor) 0
+#endif
+
+/*
+ QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text)
+ outputs a deprecation warning if QT_WARN_DEPRECATED_UP_TO is equal to or greater
+ than the version specified as major, minor. This makes it possible to deprecate a
+ function without annoying a user who needs to stay compatible with a specified minimum
+ version and therefore can't use the new function.
+*/
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(5, 12, 0)
+# define QT_DEPRECATED_VERSION_X_5_12(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_12 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_12(text)
+# define QT_DEPRECATED_VERSION_5_12
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(5, 13, 0)
+# define QT_DEPRECATED_VERSION_X_5_13(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_13 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_13(text)
+# define QT_DEPRECATED_VERSION_5_13
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(5, 14, 0)
+# define QT_DEPRECATED_VERSION_X_5_14(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_14 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_14(text)
+# define QT_DEPRECATED_VERSION_5_14
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(5, 15, 0)
+# define QT_DEPRECATED_VERSION_X_5_15(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_15 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_15(text)
+# define QT_DEPRECATED_VERSION_5_15
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 0, 0)
+# define QT_DEPRECATED_VERSION_X_6_0(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_0 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_0(text)
+# define QT_DEPRECATED_VERSION_6_0
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 1, 0)
+# define QT_DEPRECATED_VERSION_X_6_1(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_1 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_1(text)
+# define QT_DEPRECATED_VERSION_6_1
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 2, 0)
+# define QT_DEPRECATED_VERSION_X_6_2(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_2 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_2(text)
+# define QT_DEPRECATED_VERSION_6_2
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 3, 0)
+# define QT_DEPRECATED_VERSION_X_6_3(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_3 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_3(text)
+# define QT_DEPRECATED_VERSION_6_3
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 4, 0)
+# define QT_DEPRECATED_VERSION_X_6_4(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_4 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_4(text)
+# define QT_DEPRECATED_VERSION_6_4
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 5, 0)
+# define QT_DEPRECATED_VERSION_X_6_5(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_5 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_5(text)
+# define QT_DEPRECATED_VERSION_6_5
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 6, 0)
+# define QT_DEPRECATED_VERSION_X_6_6(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_6 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_6(text)
+# define QT_DEPRECATED_VERSION_6_6
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 7, 0)
+# define QT_DEPRECATED_VERSION_X_6_7(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_7 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_7(text)
+# define QT_DEPRECATED_VERSION_6_7
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 8, 0)
+# define QT_DEPRECATED_VERSION_X_6_8(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_8 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_8(text)
+# define QT_DEPRECATED_VERSION_6_8
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 9, 0)
+# define QT_DEPRECATED_VERSION_X_6_9(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_9 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_9(text)
+# define QT_DEPRECATED_VERSION_6_9
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 10, 0)
+# define QT_DEPRECATED_VERSION_X_6_10(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_10 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_10(text)
+# define QT_DEPRECATED_VERSION_6_10
+#endif
+
+#if QT_WARN_DEPRECATED_UP_TO >= QT_VERSION_CHECK(6, 11, 0)
+# define QT_DEPRECATED_VERSION_X_6_11(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_6_11 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_6_11(text)
+# define QT_DEPRECATED_VERSION_6_11
+#endif
+
+#define QT_DEPRECATED_VERSION_X_5(minor, text) QT_DEPRECATED_VERSION_X_5_##minor(text)
+#define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major##_##minor(text)
+
+#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor
+#define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major##_##minor
+
+/*
+ QT_IF_DEPRECATED_SINCE(major, minor, whenTrue, whenFalse) expands to
+ \a whenTrue if the specified (\a major, \a minor) version is less than or
+ equal to the deprecation version defined by QT_DISABLE_DEPRECATED_UP_TO,
+ and to \a whenFalse otherwise.
+
+ Currently used for QT_INLINE_SINCE(maj, min), but can also be helpful for
+ other macros of that kind.
+
+ The implementation uses QT_DEPRECATED_SINCE(maj, min) to define a bunch of
+ helper QT_IF_DEPRECATED_SINCE_X_Y macros, which expand to \a whenTrue or
+ \a whenFalse depending on the value of QT_DEPRECATED_SINCE.
+
+ If you need to use QT_IF_DEPRECATED_SINCE() for a (major, minor) version,
+ that is not yet covered by the list below, you need to copy the definition
+ and change the major and minor versions accordingly. For example, for
+ version (X, Y), you will need to add
+
+ \code
+ #if QT_DEPRECATED_SINCE(X, Y)
+ # define QT_IF_DEPRECATED_SINCE_X_Y(whenTrue, whenFalse) whenFalse
+ #else
+ # define QT_IF_DEPRECATED_SINCE_X_Y(whenTrue, whenFalse) whenTrue
+ #endif
+ \endcode
+*/
+
+#define QT_IF_DEPRECATED_SINCE(major, minor, whenTrue, whenFalse) \
+ QT_IF_DEPRECATED_SINCE_ ## major ## _ ## minor(whenTrue, whenFalse)
+
+#if QT_DEPRECATED_SINCE(6, 0)
+# define QT_IF_DEPRECATED_SINCE_6_0(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_0(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 1)
+# define QT_IF_DEPRECATED_SINCE_6_1(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_1(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 2)
+# define QT_IF_DEPRECATED_SINCE_6_2(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_2(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 3)
+# define QT_IF_DEPRECATED_SINCE_6_3(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_3(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 4)
+# define QT_IF_DEPRECATED_SINCE_6_4(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_4(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 5)
+# define QT_IF_DEPRECATED_SINCE_6_5(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_5(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 6)
+# define QT_IF_DEPRECATED_SINCE_6_6(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_6(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 7)
+# define QT_IF_DEPRECATED_SINCE_6_7(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_7(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 8)
+# define QT_IF_DEPRECATED_SINCE_6_8(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_8(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 9)
+# define QT_IF_DEPRECATED_SINCE_6_9(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_9(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 10)
+# define QT_IF_DEPRECATED_SINCE_6_10(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_10(whenTrue, whenFalse) whenTrue
+#endif
+
+#if QT_DEPRECATED_SINCE(6, 11)
+# define QT_IF_DEPRECATED_SINCE_6_11(whenTrue, whenFalse) whenFalse
+#else
+# define QT_IF_DEPRECATED_SINCE_6_11(whenTrue, whenFalse) whenTrue
+#endif
+
+#ifdef __cplusplus
+// A tag to help mark stuff deprecated (cf. QStringViewLiteral)
+namespace QtPrivate {
+enum class Deprecated_t {};
+constexpr inline Deprecated_t Deprecated = {};
+}
+#endif
+
+#ifdef QT_ASCII_CAST_WARNINGS
+# define QT_ASCII_CAST_WARN \
+ Q_DECL_DEPRECATED_X("Use fromUtf8, QStringLiteral, or QLatin1StringView")
+#else
+# define QT_ASCII_CAST_WARN
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QTDEPRECATIONMARKERS_H
diff --git a/src/corelib/global/qtdeprecationmarkers.qdoc b/src/corelib/global/qtdeprecationmarkers.qdoc
new file mode 100644
index 0000000000..2dd572533e
--- /dev/null
+++ b/src/corelib/global/qtdeprecationmarkers.qdoc
@@ -0,0 +1,64 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \headerfile <QtDeprecationMarkers>
+ \inmodule QtCore
+ \title Qt Deprecation Macros
+
+ \brief The <QtDeprecationMarkers> header file contains deprecation helper macros.
+
+ The header file declares several macros for disabling deprecated Qt APIs
+ and enabling/disabling compiler warnings when they are used.
+*/
+
+/*!
+ \macro QT_DISABLE_DEPRECATED_BEFORE
+ \relates <QtDeprecationMarkers>
+ \deprecated [6.5] Use QT_DISABLE_DEPRECATED_UP_TO instead
+
+ \sa QT_DISABLE_DEPRECATED_UP_TO
+*/
+
+/*!
+ \macro QT_DISABLE_DEPRECATED_UP_TO
+ \relates <QtDeprecationMarkers>
+
+ This macro can be defined in the project file to disable functions
+ deprecated in a specified version of Qt or any earlier version. The default
+ version number is 5.0, meaning that functions deprecated in or before
+ Qt 5.0 will not be included.
+
+ For instance, when preparing to upgrade to Qt 6.3, after eliminating all
+ deprecation warnings, you can set \c{QT_DISABLE_DEPRECATED_UP_TO=0x060300}
+ to exclude from your builds the Qt APIs you no longer use. In your own
+ project's build configuration, this will ensure that anyone adding new calls
+ to the deprecated APIs will know about it right away. If you also build Qt
+ for yourself, including this define in your build configuration for Qt will
+ make your binaries smaller by leaving out even the implementation of the
+ deprecated APIs.
+
+ \sa QT_DEPRECATED_WARNINGS, QT_DISABLE_DEPRECATED_UP_TO
+*/
+
+/*!
+ \macro QT_DEPRECATED_WARNINGS
+ \relates <QtDeprecationMarkers>
+
+ Since Qt 5.13, this macro has no effect. In Qt 5.12 and before, if this macro
+ is defined, the compiler will generate warnings if any API declared as
+ deprecated by Qt is used.
+
+ \sa QT_DISABLE_DEPRECATED_UP_TO, QT_NO_DEPRECATED_WARNINGS
+*/
+
+/*!
+ \macro QT_NO_DEPRECATED_WARNINGS
+ \relates <QtDeprecationMarkers>
+ \since 5.13
+
+ This macro can be used to suppress deprecation warnings that would otherwise
+ be generated when using deprecated APIs.
+
+ \sa QT_DISABLE_DEPRECATED_UP_TO
+*/
diff --git a/src/corelib/global/qtenvironmentvariables.cpp b/src/corelib/global/qtenvironmentvariables.cpp
new file mode 100644
index 0000000000..cf5955902a
--- /dev/null
+++ b/src/corelib/global/qtenvironmentvariables.cpp
@@ -0,0 +1,429 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qtenvironmentvariables.h"
+#include "qtenvironmentvariables_p.h"
+
+#include <qplatformdefs.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvarlengtharray.h>
+
+#include <QtCore/private/qlocking_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// In the C runtime on all platforms access to the environment is not thread-safe. We
+// add thread-safety for the Qt wrappers.
+Q_CONSTINIT static QBasicMutex environmentMutex;
+
+/*!
+ \relates <QtEnvironmentVariables>
+ \threadsafe
+
+ Returns the value of the environment variable with name \a varName as a
+ QByteArray. If no variable by that name is found in the environment, this
+ function returns a default-constructed QByteArray.
+
+ The Qt environment manipulation functions are thread-safe, but this
+ requires that the C library equivalent functions like getenv and putenv are
+ not directly called.
+
+ To convert the data to a QString use QString::fromLocal8Bit().
+
+ \note on desktop Windows, qgetenv() may produce data loss if the
+ original string contains Unicode characters not representable in the
+ ANSI encoding. Use qEnvironmentVariable() instead.
+ On Unix systems, this function is lossless.
+
+ \sa qputenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet(),
+ qEnvironmentVariableIsEmpty()
+*/
+QByteArray qgetenv(const char *varName)
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#ifdef Q_CC_MSVC
+ size_t requiredSize = 0;
+ QByteArray buffer;
+ getenv_s(&requiredSize, 0, 0, varName);
+ if (requiredSize == 0)
+ return buffer;
+ buffer.resize(qsizetype(requiredSize));
+ getenv_s(&requiredSize, buffer.data(), requiredSize, varName);
+ // requiredSize includes the terminating null, which we don't want.
+ Q_ASSERT(buffer.endsWith('\0'));
+ buffer.chop(1);
+ return buffer;
+#else
+ return QByteArray(::getenv(varName));
+#endif
+}
+
+/*!
+ \fn QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
+ \fn QString qEnvironmentVariable(const char *varName)
+
+ \relates <QtEnvironmentVariables>
+ \since 5.10
+
+ These functions return the value of the environment variable, \a varName, as a
+ QString. If no variable \a varName is found in the environment and \a defaultValue
+ is provided, \a defaultValue is returned. Otherwise QString() is returned.
+
+ The Qt environment manipulation functions are thread-safe, but this
+ requires that the C library equivalent functions like getenv and putenv are
+ not directly called.
+
+ The following table describes how to choose between qgetenv() and
+ qEnvironmentVariable():
+ \table
+ \header \li Condition \li Recommendation
+ \row
+ \li Variable contains file paths or user text
+ \li qEnvironmentVariable()
+ \row
+ \li Windows-specific code
+ \li qEnvironmentVariable()
+ \row
+ \li Unix-specific code, destination variable is not QString and/or is
+ used to interface with non-Qt APIs
+ \li qgetenv()
+ \row
+ \li Destination variable is a QString
+ \li qEnvironmentVariable()
+ \row
+ \li Destination variable is a QByteArray or std::string
+ \li qgetenv()
+ \endtable
+
+ \note on Unix systems, this function may produce data loss if the original
+ string contains arbitrary binary data that cannot be decoded by the locale
+ codec. Use qgetenv() instead for that case. On Windows, this function is
+ lossless.
+
+ \note the variable name \a varName must contain only US-ASCII characters.
+
+ \sa qputenv(), qgetenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty()
+*/
+QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
+{
+#if defined(Q_OS_WIN)
+ QVarLengthArray<wchar_t, 32> wname(qsizetype(strlen(varName)) + 1);
+ for (qsizetype i = 0; i < wname.size(); ++i) // wname.size() is correct: will copy terminating null
+ wname[i] = uchar(varName[i]);
+ size_t requiredSize = 0;
+ auto locker = qt_unique_lock(environmentMutex);
+ _wgetenv_s(&requiredSize, 0, 0, wname.data());
+ if (requiredSize == 0)
+ return defaultValue;
+ QString buffer(qsizetype(requiredSize), Qt::Uninitialized);
+ _wgetenv_s(&requiredSize, reinterpret_cast<wchar_t *>(buffer.data()), requiredSize,
+ wname.data());
+ locker.unlock();
+ // requiredSize includes the terminating null, which we don't want.
+ Q_ASSERT(buffer.endsWith(QChar(u'\0')));
+ buffer.chop(1);
+ return buffer;
+#else
+ QByteArray value = qgetenv(varName);
+ if (value.isNull())
+ return defaultValue;
+// duplicated in qfile.h (QFile::decodeName)
+#if defined(Q_OS_DARWIN)
+ return QString::fromUtf8(value).normalized(QString::NormalizationForm_C);
+#else // other Unix
+ return QString::fromLocal8Bit(value);
+#endif
+#endif
+}
+
+QString qEnvironmentVariable(const char *varName)
+{
+ return qEnvironmentVariable(varName, QString());
+}
+
+/*!
+ \relates <QtEnvironmentVariables>
+ \since 5.1
+
+ Returns whether the environment variable \a varName is empty.
+
+ Equivalent to
+ \snippet code/src_corelib_global_qglobal.cpp is-empty
+ except that it's potentially much faster, and can't throw exceptions.
+
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
+*/
+bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#ifdef Q_CC_MSVC
+ // we provide a buffer that can only hold the empty string, so
+ // when the env.var isn't empty, we'll get an ERANGE error (buffer
+ // too small):
+ size_t dummy;
+ char buffer = '\0';
+ return getenv_s(&dummy, &buffer, 1, varName) != ERANGE;
+#else
+ const char * const value = ::getenv(varName);
+ return !value || !*value;
+#endif
+}
+
+/*!
+ \relates <QtEnvironmentVariables>
+ \since 5.5
+
+ Returns the numerical value of the environment variable \a varName.
+ If \a ok is not null, sets \c{*ok} to \c true or \c false depending
+ on the success of the conversion.
+
+ Equivalent to
+ \snippet code/src_corelib_global_qglobal.cpp to-int
+ except that it's much faster, and can't throw exceptions.
+
+ \note there's a limit on the length of the value, which is sufficient for
+ all valid values of int, not counting leading zeroes or spaces. Values that
+ are too long will either be truncated or this function will set \a ok to \c
+ false.
+
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
+*/
+int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
+{
+ static const int NumBinaryDigitsPerOctalDigit = 3;
+ static const int MaxDigitsForOctalInt =
+ (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit;
+
+ const auto locker = qt_scoped_lock(environmentMutex);
+ size_t size;
+#ifdef Q_CC_MSVC
+ // we provide a buffer that can hold any int value:
+ char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-'
+ size_t dummy;
+ if (getenv_s(&dummy, buffer, sizeof buffer, varName) != 0) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+ size = strlen(buffer);
+#else
+ const char * const buffer = ::getenv(varName);
+ if (!buffer || (size = strlen(buffer)) > MaxDigitsForOctalInt + 2) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+#endif
+ return QByteArrayView(buffer, size).toInt(ok, 0);
+}
+
+/*!
+ \relates <QtEnvironmentVariables>
+ \since 5.1
+
+ Returns whether the environment variable \a varName is set.
+
+ Equivalent to
+ \snippet code/src_corelib_global_qglobal.cpp is-null
+ except that it's potentially much faster, and can't throw exceptions.
+
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty()
+*/
+bool qEnvironmentVariableIsSet(const char *varName) noexcept
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#ifdef Q_CC_MSVC
+ size_t requiredSize = 0;
+ (void)getenv_s(&requiredSize, 0, 0, varName);
+ return requiredSize != 0;
+#else
+ return ::getenv(varName) != nullptr;
+#endif
+}
+
+/*!
+ \fn bool qputenv(const char *varName, QByteArrayView value)
+ \relates <QtEnvironmentVariables>
+
+ This function sets the \a value of the environment variable named
+ \a varName. It will create the variable if it does not exist. It
+ returns 0 if the variable could not be set.
+
+ Calling qputenv with an empty value removes the environment variable on
+ Windows, and makes it set (but empty) on Unix. Prefer using qunsetenv()
+ for fully portable behavior.
+
+ \note qputenv() was introduced because putenv() from the standard
+ C library was deprecated in VC2005 (and later versions). qputenv()
+ uses the replacement function in VC, and calls the standard C
+ library's implementation on all other platforms.
+
+ \note In Qt versions prior to 6.5, the \a value argument was QByteArray,
+ not QByteArrayView.
+
+ \sa qgetenv(), qEnvironmentVariable()
+*/
+bool qputenv(const char *varName, QByteArrayView raw)
+{
+ auto protect = [](const char *str) { return str ? str : ""; };
+
+ std::string value{protect(raw.data()), size_t(raw.size())}; // NUL-terminates w/SSO
+
+#if defined(Q_CC_MSVC)
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return _putenv_s(varName, value.data()) == 0;
+#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU)
+ // POSIX.1-2001 has setenv
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return setenv(varName, value.data(), true) == 0;
+#else
+ std::string buffer;
+ buffer += protect(varName);
+ buffer += '=';
+ buffer += value;
+ char *envVar = qstrdup(buffer.data());
+ int result = [&] {
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return putenv(envVar);
+ }();
+ if (result != 0) // error. we have to delete the string.
+ delete[] envVar;
+ return result == 0;
+#endif
+}
+
+/*!
+ \relates <QtEnvironmentVariables>
+
+ This function deletes the variable \a varName from the environment.
+
+ Returns \c true on success.
+
+ \since 5.1
+
+ \sa qputenv(), qgetenv(), qEnvironmentVariable()
+*/
+bool qunsetenv(const char *varName)
+{
+#if defined(Q_CC_MSVC)
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return _putenv_s(varName, "") == 0;
+#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU)
+ // POSIX.1-2001, BSD and Haiku have unsetenv
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return unsetenv(varName) == 0;
+#elif defined(Q_CC_MINGW)
+ // On mingw, putenv("var=") removes "var" from the environment
+ QByteArray buffer(varName);
+ buffer += '=';
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return putenv(buffer.constData()) == 0;
+#else
+ // Fallback to putenv("var=") which will insert an empty var into the
+ // environment and leak it
+ QByteArray buffer(varName);
+ buffer += '=';
+ char *envVar = qstrdup(buffer.constData());
+ const auto locker = qt_scoped_lock(environmentMutex);
+ return putenv(envVar) == 0;
+#endif
+}
+
+/* Various time-related APIs that need to consult system settings also need
+ protection with the same lock as the environment, since those system settings
+ include part of the environment (principally TZ).
+
+ First, tzset(), which POSIX explicitly says accesses the environment.
+*/
+void qTzSet()
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#if defined(Q_OS_WIN)
+ _tzset();
+#else
+ tzset();
+#endif // Q_OS_WIN
+}
+
+/* Wrap mktime(), which is specified to behave as if it called tzset(), hence
+ shares its implicit environment-dependence.
+*/
+time_t qMkTime(struct tm *when)
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#if defined(Q_OS_WIN)
+ // QTBUG-83881 MS's mktime() seems to need _tzset() called first.
+ _tzset();
+#endif
+ return mktime(when);
+}
+
+/* For localtime(), POSIX mandates that it behave as if it called tzset().
+ For the alternatives to it, we need (if only for compatibility) to do the
+ same explicitly, which should ensure a re-parse of timezone info.
+*/
+bool qLocalTime(time_t utc, struct tm *local)
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#if defined(Q_OS_WIN)
+ // The doc of localtime_s() says that it corrects for the same things
+ // _tzset() sets the globals for, but QTBUG-109974 reveals a need for an
+ // explicit call, all the same.
+ _tzset();
+ return !localtime_s(local, &utc);
+#elif QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // Use the reentrant version of localtime() where available, as it is
+ // thread-safe and doesn't use a shared static data area.
+ // As localtime_r() is not specified to work as if it called tzset(),
+ // make an explicit call.
+ tzset();
+ if (tm *res = localtime_r(&utc, local)) {
+ Q_ASSERT(res == local);
+ Q_UNUSED(res);
+ return true;
+ }
+ return false;
+#else
+ // POSIX mandates that localtime() behaves as if it called tzset().
+ // Returns shared static data which may be overwritten at any time (albeit
+ // our lock probably keeps it safe). So copy the result promptly:
+ if (tm *res = localtime(&utc)) {
+ *local = *res;
+ return true;
+ }
+ return false;
+#endif
+}
+
+/* Access to the tzname[] global in one thread is UB if any other is calling
+ tzset() or anything that behaves as if it called tzset(). So also lock this
+ access to prevent such collisions.
+
+ Parameter dstIndex must be 1 for DST or 0 for standard time.
+ Returns the relevant form of the name of local-time's zone.
+*/
+QString qTzName(int dstIndex)
+{
+ char name[512];
+ bool ok;
+#if defined(_UCRT) // i.e., MSVC and MinGW-UCRT
+ size_t s = 0;
+ {
+ const auto locker = qt_scoped_lock(environmentMutex);
+ ok = _get_tzname(&s, name, 512, dstIndex) != 0;
+ }
+#else
+ {
+ const auto locker = qt_scoped_lock(environmentMutex);
+ const char *const src = tzname[dstIndex];
+ ok = src != nullptr;
+ if (ok)
+ memcpy(name, src, std::min(sizeof(name), strlen(src) + 1));
+ }
+#endif // Q_OS_WIN
+ return ok ? QString::fromLocal8Bit(name) : QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qtenvironmentvariables.h b/src/corelib/global/qtenvironmentvariables.h
new file mode 100644
index 0000000000..e7be182677
--- /dev/null
+++ b/src/corelib/global/qtenvironmentvariables.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTENVIRONMENTVARIABLES_H
+#define QTENVIRONMENTVARIABLES_H
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
+#include <QtCore/qtdeprecationmarkers.h>
+
+#if 0
+#pragma qt_class(QtEnvironmentVariables)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+class QByteArrayView;
+class QString;
+
+Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
+// need it as two functions because QString is only forward-declared here
+Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName);
+Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &defaultValue);
+#if QT_CORE_REMOVED_SINCE(6, 5)
+Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray &value);
+#endif
+Q_CORE_EXPORT bool qputenv(const char *varName, QByteArrayView value);
+Q_CORE_EXPORT bool qunsetenv(const char *varName);
+
+Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept;
+Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept;
+Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept;
+
+QT_END_NAMESPACE
+
+#endif /* QTENVIRONMENTVARIABLES_H */
diff --git a/src/corelib/global/qtenvironmentvariables_p.h b/src/corelib/global/qtenvironmentvariables_p.h
new file mode 100644
index 0000000000..0c81d36db6
--- /dev/null
+++ b/src/corelib/global/qtenvironmentvariables_p.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2015 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTENVIRONMENTVARIABLES_P_H
+#define QTENVIRONMENTVARIABLES_P_H
+// Nothing but (tests and) ../time/qlocaltime.cpp should access this.
+#if defined(__cplusplus)
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an implementation
+// detail. This header file may change from version to version without notice,
+// or even be removed.
+//
+// We mean it.
+//
+
+#include "qglobal_p.h"
+
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+// These (behave as if they) consult the environment, so need to share its locking:
+Q_CORE_EXPORT void qTzSet();
+Q_CORE_EXPORT time_t qMkTime(struct tm *when);
+Q_CORE_EXPORT bool qLocalTime(time_t utc, struct tm *local);
+Q_CORE_EXPORT QString qTzName(int dstIndex);
+
+QT_END_NAMESPACE
+
+#endif // defined(__cplusplus)
+#endif // QTENVIRONMENTVARIABLES_P_H
diff --git a/src/corelib/global/qtnoop.h b/src/corelib/global/qtnoop.h
new file mode 100644
index 0000000000..c84e6c8a99
--- /dev/null
+++ b/src/corelib/global/qtnoop.h
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTNOOP_H
+#define QTNOOP_H
+
+#if 0
+#pragma qt_sync_stop_processing
+#endif
+
+#ifdef __cplusplus
+constexpr
+#endif
+inline void qt_noop(void)
+#ifdef __cplusplus
+ noexcept
+#endif
+{}
+
+#endif // QTNOOP_H
diff --git a/src/corelib/global/qtpreprocessorsupport.h b/src/corelib/global/qtpreprocessorsupport.h
new file mode 100644
index 0000000000..73bbeb68b6
--- /dev/null
+++ b/src/corelib/global/qtpreprocessorsupport.h
@@ -0,0 +1,26 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTPREPROCESSORSUPPORT_H
+#define QTPREPROCESSORSUPPORT_H
+
+#if 0
+#pragma qt_class(QtPreprocessorSupport)
+#pragma qt_sync_stop_processing
+#endif
+
+/* These two macros makes it possible to turn the builtin line expander into a
+ * string literal. */
+#define QT_STRINGIFY2(x) #x
+#define QT_STRINGIFY(x) QT_STRINGIFY2(x)
+
+/*
+ Avoid "unused parameter" warnings
+*/
+#define Q_UNUSED(x) (void)x;
+
+#if !defined(Q_UNIMPLEMENTED)
+# define Q_UNIMPLEMENTED() qWarning("Unimplemented code.")
+#endif
+
+#endif // QTPREPROCESSORSUPPORT_H
diff --git a/src/corelib/global/qtpreprocessorsupport.qdoc b/src/corelib/global/qtpreprocessorsupport.qdoc
new file mode 100644
index 0000000000..c9fedf4ec1
--- /dev/null
+++ b/src/corelib/global/qtpreprocessorsupport.qdoc
@@ -0,0 +1,20 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro Q_UNUSED(name)
+ \relates <QtPreprocessorSupport>
+
+ Indicates to the compiler that the parameter with the specified
+ \a name is not used in the body of a function. This can be used to
+ suppress compiler warnings while allowing functions to be defined
+ with meaningful parameter names in their signatures.
+*/
+
+/*!
+ \macro QT_STRINGIFY(arg)
+ \relates <QtPreprocessorSupport>
+
+ The macro can be used to turn the builtin line expander \a arg into a string
+ literal.
+*/
diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h
index d9011c6066..f4e39ffe2b 100644
--- a/src/corelib/global/qtrace_p.h
+++ b/src/corelib/global/qtrace_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRACE_P_H
#define QTRACE_P_H
@@ -93,7 +57,7 @@
* qcoreapplication_qrect(const QRect &rect)
*
* The provider file is then parsed by src/tools/tracegen, which can be
- * switched to output either ETW or LTTNG tracepoint definitions. The provider
+ * switched to output either ETW, CTF or LTTNG tracepoint definitions. The provider
* name is deduced to be basename(provider_file).
*
* To use the above (inside qtcore), you need to include
@@ -111,12 +75,56 @@
* - QByteArray
* - QUrl
* - QRect
+ * - QRectF
+ * - QSize
+ * - QSizeF
*
* Dynamic arrays are supported using the syntax illustrated by
* qcoreapplication_baz above.
+ *
+ * One can also add prefix for the generated providername_tracepoints_p.h file
+ * by specifying it inside brackets '{ }' in the tracepoints file. One can
+ * for example add forward declaration for a type:
+ *
+ * {
+ * QT_BEGIN_NAMESPACE
+ * class QEvent;
+ * QT_END_NAMESPACE
+ * }
+ *
+ * Metadata
+ *
+ * Metadata is used to add textual information for different types such
+ * as enums and flags. How this data is handled depends on the used backend.
+ * For ETW, the values are converted to text, for CTF and LTTNG they are used to add
+ * CTF enumerations, which are converted to text after tracing.
+ *
+ * Enumererations are specified using ENUM:
+ *
+ * ENUM {
+ * Enum0 = 0,
+ * Enum1 = 1,
+ * Enum2,
+ * RANGE(RangeEnum, 3 ... 10),
+ * } Name;
+ *
+ * Name must match to one of the enumerations used in the tracepoints. Range of values
+ * can be provided using RANGE(name, first ... last). All values must be unique.
+ *
+ * Flags are specified using FLAGS:
+ *
+ * FLAGS {
+ * Default = 0,
+ * Flag0 = 1,
+ * Flag1 = 2,
+ * Flag2 = 4,
+ * } Name;
+ *
+ * Name must match to one of the flags used in the tracepoints. Each value must be
+ * power of two and unique.
*/
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
#include <QtCore/qscopeguard.h>
QT_BEGIN_NAMESPACE
@@ -140,6 +148,91 @@ QT_BEGIN_NAMESPACE
# define Q_TRACE_ENABLED(x) false
#endif // defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
+
+/*
+ * The Qt tracepoints can also be defined directly in the source files using
+ * the following macros. If using these macros, the tracepoints file is automatically
+ * generated using the tracepointgen tool. The tool scans the input files for
+ * these macros. These macros are ignored during compile time. Both automatic
+ * generation and manually specifying tracepoints in a file can't be done at the same
+ * time for the same provider.
+ *
+ * - Q_TRACE_INSTRUMENT(provider)
+ * Generate entry/exit tracepoints for a function. For example, member function
+ *
+ * void SomeClass::method(int param1, float param2)
+ * {
+ * ...
+ * }
+ *
+ * converted to use tracepoints:
+ *
+ * void Q_TRACE_INSTRUMENT(provider) SomeClass::method(int param1, float param2)
+ * {
+ * Q_TRACE_SCOPE(SomeClass_method, param1, param2);
+ * ...
+ * }
+ *
+ * generates following tracepoints in provider.tracepoints file:
+ *
+ * SomeClass_method_entry(int param1, float param2)
+ * SomeClass_method_exit()
+ *
+ * - Q_TRACE_PARAM_REPLACE(in, out)
+ * Can be used with Q_TRACE_INSTRUMENT to replace parameter type in with type out.
+ * If a parameter type is not supported by the tracegen tool, one can use this to
+ * change it to another supported type.
+ *
+ * void Q_TRACE_INSTRUMENT(provider) SomeClass::method(int param1, UserType param2)
+ * {
+ * Q_TRACE_PARAM_REPLACE(UserType, QString);
+ * Q_TRACE_SCOPE(SomeClass_method, param1, param2.toQString());
+ * }
+ *
+ * - Q_TRACE_POINT(provider, tracepoint, ...)
+ * Manually specify tracepoint for the provider. 'tracepoint' is the full name
+ * of the tracepoint and ... can be zero or more parameters.
+ *
+ * Q_TRACE_POINT(provider, SomeClass_function_entry, int param1, int param2);
+ *
+ * generates following tracepoint:
+ *
+ * SomeClass_function_entry(int param1, int param2)
+ *
+ * - Q_TRACE_PREFIX(provider, prefix)
+ * Provide prefix for the tracepoint. Multiple prefixes can be specified for the same
+ * provider in different files, they are all concatenated into one in the
+ * provider.tracepoints file.
+ *
+ * Q_TRACE_PREFIX(provider,
+ * "QT_BEGIN_NAMESPACE" \
+ * "class QEvent;" \
+ * "QT_END_NAMESPACE")
+ *
+ * - Q_TRACE_METADATA(provider, metadata)
+ * Provides metadata for the tracepoint provider.
+ *
+ * Q_TRACE_METADATA(qtgui,
+ * "ENUM {" \
+ * "Format_Invalid," \
+ * "Format_Mono," \
+ * "Format_MonoLSB," \
+ * "Format_Indexed8," \
+ * ...
+ * "} QImage::Format;" \
+ * );
+ *
+ * If the content of enum is empty or contains keyword AUTO, then the tracepointgen tool
+ * tries to find the enumeration from header files.
+ *
+ * Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
+ */
+#define Q_TRACE_INSTRUMENT(provider)
+#define Q_TRACE_PARAM_REPLACE(in, out)
+#define Q_TRACE_POINT(provider, tracepoint, ...)
+#define Q_TRACE_PREFIX(provider, prefix)
+#define Q_TRACE_METADATA(provider, metadata)
+
QT_END_NAMESPACE
#endif // QTRACE_P_H
diff --git a/src/corelib/global/qtresource.h b/src/corelib/global/qtresource.h
new file mode 100644
index 0000000000..535903aac0
--- /dev/null
+++ b/src/corelib/global/qtresource.h
@@ -0,0 +1,21 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTRESOURCE_H
+#define QTRESOURCE_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#if 0
+#pragma qt_class(QtResource)
+#pragma qt_sync_stop_processing
+#endif
+
+#define Q_INIT_RESOURCE(name) \
+ do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \
+ QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (false)
+#define Q_CLEANUP_RESOURCE(name) \
+ do { extern int QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); \
+ QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); } while (false)
+
+#endif // QTRESOURCE_H
diff --git a/src/corelib/global/qtresource.qdoc b/src/corelib/global/qtresource.qdoc
new file mode 100644
index 0000000000..abc5265987
--- /dev/null
+++ b/src/corelib/global/qtresource.qdoc
@@ -0,0 +1,54 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro void Q_INIT_RESOURCE(name)
+ \relates <QtResource>
+
+ Initializes the resources specified by the \c .qrc file with the
+ specified base \a name. Normally, when resources are built as part
+ of the application, the resources are loaded automatically at
+ startup. The Q_INIT_RESOURCE() macro is necessary on some platforms
+ for resources stored in a static library.
+
+ For example, if your application's resources are listed in a file
+ called \c myapp.qrc, you can ensure that the resources are
+ initialized at startup by adding this line to your \c main()
+ function:
+
+ \snippet code/src_corelib_io_qdir.cpp 13
+
+ If the file name contains characters that cannot be part of a valid C++ function name
+ (such as '-'), they have to be replaced by the underscore character ('_').
+
+ \note This macro cannot be used in a namespace. It should be called from
+ main(). If that is not possible, the following workaround can be used
+ to init the resource \c myapp from the function \c{MyNamespace::myFunction}:
+
+ \snippet code/src_corelib_io_qdir.cpp 14
+
+ \sa Q_CLEANUP_RESOURCE(), {The Qt Resource System}
+*/
+
+/*!
+ \since 4.1
+ \macro void Q_CLEANUP_RESOURCE(name)
+ \relates <QtResource>
+
+ Unloads the resources specified by the \c .qrc file with the base
+ name \a name.
+
+ Normally, Qt resources are unloaded automatically when the
+ application terminates, but if the resources are located in a
+ plugin that is being unloaded, call Q_CLEANUP_RESOURCE() to force
+ removal of your resources.
+
+ \note This macro cannot be used in a namespace. Please see the
+ Q_INIT_RESOURCE documentation for a workaround.
+
+ Example:
+
+ \snippet code/src_corelib_io_qdir.cpp 15
+
+ \sa Q_INIT_RESOURCE(), {The Qt Resource System}
+*/
diff --git a/src/corelib/global/qtsymbolmacros.h b/src/corelib/global/qtsymbolmacros.h
new file mode 100644
index 0000000000..18cdc85f72
--- /dev/null
+++ b/src/corelib/global/qtsymbolmacros.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTSYMBOLMACROS_H
+#define QTSYMBOLMACROS_H
+
+#if 0
+# pragma qt_sync_stop_processing
+#endif
+
+// For GHS symbol keeping.
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtpreprocessorsupport.h>
+
+// For handling namespaced resources.
+#ifdef QT_NAMESPACE
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+// GHS needs special handling to keep a symbol around.
+#if defined(Q_CC_GHS)
+# define Q_GHS_KEEP_REFERENCE(S) QT_DO_PRAGMA(ghs reference S ##__Fv)
+#else
+# define Q_GHS_KEEP_REFERENCE(S)
+#endif
+
+// Macros to ensure a symbol is not dropped by the linker even if it's not used.
+#define QT_DECLARE_EXTERN_SYMBOL(NAME, RETURN_TYPE) \
+ extern RETURN_TYPE NAME(); \
+ Q_GHS_KEEP_REFERENCE(NAME)
+
+#define QT_DECLARE_EXTERN_SYMBOL_INT(NAME) \
+ QT_DECLARE_EXTERN_SYMBOL(NAME, int)
+
+#define QT_DECLARE_EXTERN_SYMBOL_VOID(NAME) \
+ QT_DECLARE_EXTERN_SYMBOL(NAME, void)
+
+#define QT_KEEP_SYMBOL_VAR_NAME(NAME) NAME ## _keep
+
+#define QT_KEEP_SYMBOL_HELPER(NAME, VAR_NAME) \
+ volatile auto VAR_NAME = &NAME; \
+ Q_UNUSED(VAR_NAME)
+
+#define QT_KEEP_SYMBOL(NAME) \
+ QT_KEEP_SYMBOL_HELPER(NAME, QT_KEEP_SYMBOL_VAR_NAME(NAME))
+
+
+// Similar to the ones above, but for rcc resource symbols specifically.
+#define QT_GET_RESOURCE_INIT_SYMBOL(NAME) \
+ QT_RCC_MANGLE_NAMESPACE(qInitResources_ ## NAME)
+
+#define QT_DECLARE_EXTERN_RESOURCE(NAME) \
+ QT_DECLARE_EXTERN_SYMBOL_INT(QT_GET_RESOURCE_INIT_SYMBOL(NAME))
+
+#define QT_KEEP_RESOURCE(NAME) \
+ QT_KEEP_SYMBOL(QT_GET_RESOURCE_INIT_SYMBOL(NAME))
+
+#endif // QTSYMBOLMACROS_H
+
diff --git a/src/corelib/global/qttranslation.h b/src/corelib/global/qttranslation.h
new file mode 100644
index 0000000000..fb0a2244cc
--- /dev/null
+++ b/src/corelib/global/qttranslation.h
@@ -0,0 +1,44 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTTRANSLATION_H
+#define QTTRANSLATION_H
+
+#include <QtCore/qtconfigmacros.h> // QT_NO_TRANSLATION should be defined here as well
+#include <QtCore/qtcoreexports.h>
+
+#if 0
+#pragma qt_class(QtTranslation)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+#define QT_TR_NOOP(x) x
+#define QT_TR_NOOP_UTF8(x) x
+#define QT_TRANSLATE_NOOP(scope, x) x
+#define QT_TRANSLATE_NOOP_UTF8(scope, x) x
+#define QT_TRANSLATE_NOOP3(scope, x, comment) {x, comment}
+#define QT_TRANSLATE_NOOP3_UTF8(scope, x, comment) {x, comment}
+
+#ifndef QT_NO_TRANSLATION
+
+#define QT_TR_N_NOOP(x) x
+#define QT_TRANSLATE_N_NOOP(scope, x) x
+#define QT_TRANSLATE_N_NOOP3(scope, x, comment) {x, comment}
+
+// Defined in qcoreapplication.cpp
+// The better name qTrId() is reserved for an upcoming function which would
+// return a much more powerful QStringFormatter instead of a QString.
+Q_CORE_EXPORT QString qtTrId(const char *id, int n = -1);
+
+#define QT_TRID_NOOP(id) id
+#define QT_TRID_N_NOOP(id) id
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TRANSLATION
+
+#endif /* QTTRANSLATION_H */
diff --git a/src/corelib/global/qttranslation.qdoc b/src/corelib/global/qttranslation.qdoc
new file mode 100644
index 0000000000..b2b0b1f3c3
--- /dev/null
+++ b/src/corelib/global/qttranslation.qdoc
@@ -0,0 +1,206 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro QT_TR_NOOP(sourceText)
+ \relates <QtTranslation>
+
+ Marks the UTF-8 encoded string literal \a sourceText for delayed
+ translation in the current context (class).
+
+ The macro tells lupdate to collect the string, and expands to
+ \a sourceText itself.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 34
+
+ The macro QT_TR_NOOP_UTF8() is identical and obsolete; this applies
+ to all other _UTF8 macros as well.
+
+ \sa QT_TRANSLATE_NOOP(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_NOOP(context, sourceText)
+ \relates <QtTranslation>
+
+ Marks the UTF-8 encoded string literal \a sourceText for delayed
+ translation in the given \a context. The \a context is typically
+ a class name and also needs to be specified as a string literal.
+
+ The macro tells lupdate to collect the string, and expands to
+ \a sourceText itself.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 35
+
+ \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP3(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_NOOP3(context, sourceText, disambiguation)
+ \relates <QtTranslation>
+ \since 4.4
+
+ Marks the UTF-8 encoded string literal \a sourceText for delayed
+ translation in the given \a context with the given \a disambiguation.
+ The \a context is typically a class and also needs to be specified
+ as a string literal. The string literal \a disambiguation should be
+ a short semantic tag to tell apart otherwise identical strings.
+
+ The macro tells lupdate to collect the string, and expands to an
+ anonymous struct of the two string literals passed as \a sourceText
+ and \a disambiguation.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 36
+
+ \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TR_N_NOOP(sourceText)
+ \relates <QtTranslation>
+ \since 5.12
+
+ Marks the UTF-8 encoded string literal \a sourceText for numerator
+ dependent delayed translation in the current context (class).
+
+ The macro tells lupdate to collect the string, and expands to
+ \a sourceText itself.
+
+ The macro expands to \a sourceText.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttrnnoop
+
+ \sa QT_TR_NOOP, {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_N_NOOP(context, sourceText)
+ \relates <QtTranslation>
+ \since 5.12
+
+ Marks the UTF-8 encoded string literal \a sourceText for numerator
+ dependent delayed translation in the given \a context.
+ The \a context is typically a class name and also needs to be
+ specified as a string literal.
+
+ The macro tells lupdate to collect the string, and expands to
+ \a sourceText itself.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttranslatennoop
+
+ \sa QT_TRANSLATE_NOOP(), QT_TRANSLATE_N_NOOP3(),
+ {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_N_NOOP3(context, sourceText, comment)
+ \relates <QtTranslation>
+ \since 5.12
+
+ Marks the UTF-8 encoded string literal \a sourceText for numerator
+ dependent delayed translation in the given \a context with the given
+ \a comment.
+ The \a context is typically a class and also needs to be specified
+ as a string literal. The string literal \a comment should be
+ a short semantic tag to tell apart otherwise identical strings.
+
+ The macro tells lupdate to collect the string, and expands to an
+ anonymous struct of the two string literals passed as \a sourceText
+ and \a comment.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttranslatennoop3
+
+ \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP(), QT_TRANSLATE_NOOP3(),
+ {Internationalization with Qt}
+*/
+
+/*!
+ \fn QString qtTrId(const char *id, int n = -1)
+ \relates <QtTranslation>
+ \reentrant
+ \since 4.6
+
+ \brief The qtTrId function finds and returns a translated string.
+
+ Returns a translated string identified by \a id.
+ If no matching string is found, the id itself is returned. This
+ should not happen under normal conditions.
+
+ If \a n >= 0, all occurrences of \c %n in the resulting string
+ are replaced with a decimal representation of \a n. In addition,
+ depending on \a n's value, the translation text may vary.
+
+ Meta data and comments can be passed as documented for QObject::tr().
+ In addition, it is possible to supply a source string template like that:
+
+ \tt{//% <C string>}
+
+ or
+
+ \tt{\\begincomment% <C string> \\endcomment}
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttrid
+
+ Creating QM files suitable for use with this function requires passing
+ the \c -idbased option to the \c lrelease tool.
+
+ \warning This method is reentrant only if all translators are
+ installed \e before calling this method. Installing or removing
+ translators while performing translations is not supported. Doing
+ so will probably result in crashes or other undesirable behavior.
+
+ \sa QObject::tr(), QCoreApplication::translate(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRID_NOOP(id)
+ \relates <QtTranslation>
+ \since 4.6
+
+ \brief The QT_TRID_NOOP macro marks an id for dynamic translation.
+
+ The only purpose of this macro is to provide an anchor for attaching
+ meta data like to qtTrId().
+
+ The macro expands to \a id.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttrid_noop
+
+ \sa qtTrId(), {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRID_N_NOOP(id)
+ \relates <QtTranslation>
+ \since 6.3
+
+ \brief The QT_TRID_N_NOOP macro marks an id for numerator
+ dependent dynamic translation.
+
+ The only purpose of this macro is to provide an anchor for attaching
+ meta data like to qtTrId().
+
+ The macro expands to \a id.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttrid_n_noop
+
+ \sa qtTrId(), {Internationalization with Qt}
+*/
diff --git a/src/corelib/global/qttypetraits.h b/src/corelib/global/qttypetraits.h
new file mode 100644
index 0000000000..1efb24bf70
--- /dev/null
+++ b/src/corelib/global/qttypetraits.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTTYPETRAITS_H
+#define QTTYPETRAITS_H
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtdeprecationmarkers.h>
+
+#include <type_traits>
+#include <utility>
+
+#if 0
+#pragma qt_class(QtTypeTraits)
+#pragma qt_sync_stop_processing
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// like std::to_underlying
+template <typename Enum>
+constexpr std::underlying_type_t<Enum> qToUnderlying(Enum e) noexcept
+{
+ return static_cast<std::underlying_type_t<Enum>>(e);
+}
+
+#ifndef QT_NO_QASCONST
+#if QT_DEPRECATED_SINCE(6, 6)
+
+// this adds const to non-const objects (like std::as_const)
+template <typename T>
+QT_DEPRECATED_VERSION_X_6_6("Use std::as_const() instead.")
+constexpr typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; }
+// prevent rvalue arguments:
+template <typename T>
+void qAsConst(const T &&) = delete;
+
+#endif // QT_DEPRECATED_SINCE(6, 6)
+#endif // QT_NO_QASCONST
+
+#ifndef QT_NO_QEXCHANGE
+
+// like std::exchange
+template <typename T, typename U = T>
+constexpr T qExchange(T &t, U &&newValue)
+noexcept(std::conjunction_v<std::is_nothrow_move_constructible<T>,
+ std::is_nothrow_assignable<T &, U>>)
+{
+ T old = std::move(t);
+ t = std::forward<U>(newValue);
+ return old;
+}
+
+#endif // QT_NO_QEXCHANGE
+
+namespace QtPrivate {
+// helper to be used to trigger a "dependent static_assert(false)"
+// (for instance, in a final `else` branch of a `if constexpr`.)
+template <typename T> struct type_dependent_false : std::false_type {};
+template <auto T> struct value_dependent_false : std::false_type {};
+}
+
+QT_END_NAMESPACE
+
+#endif // QTTYPETRAITS_H
diff --git a/src/corelib/global/qttypetraits.qdoc b/src/corelib/global/qttypetraits.qdoc
new file mode 100644
index 0000000000..ed814d6f43
--- /dev/null
+++ b/src/corelib/global/qttypetraits.qdoc
@@ -0,0 +1,146 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \headerfile <QtTypeTraits>
+ \inmodule QtCore
+ \since 6.5
+ \title Qt Type Traits
+ \brief Functionality for type traits and transformations.
+*/
+
+/*!
+ \fn template <typename Enum> std::underlying_type_t<Enum> qToUnderlying(Enum e)
+ \relates <QtTypeTraits>
+ \since 6.2
+
+ Converts the enumerator \a e to the equivalent value expressed in its
+ enumeration's underlying type.
+*/
+
+/*!
+ \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t)
+ \relates <QtTypeTraits>
+ \since 5.7
+
+ \deprecated [6.6] Use std::as_const() instead.
+
+ Returns \a t cast to \c{const T}.
+
+ This function is a Qt implementation of C++17's std::as_const(),
+ a cast function like std::move(). But while std::move() turns
+ lvalues into rvalues, this function turns non-const lvalues into
+ const lvalues. Like std::as_const(), it doesn't work on rvalues,
+ because it cannot be efficiently implemented for rvalues without
+ leaving dangling references.
+
+ Its main use in Qt is to prevent implicitly-shared Qt containers
+ from detaching:
+ \snippet code/src_corelib_global_qglobal.cpp as-const-0
+
+ Of course, in this case, you could (and probably should) have declared
+ \c s as \c const in the first place:
+ \snippet code/src_corelib_global_qglobal.cpp as-const-1
+ but often that is not easily possible.
+
+ It is important to note that qAsConst() does not copy its argument,
+ it just performs a \c{const_cast<const T&>(t)}. This is also the reason
+ why it is designed to fail for rvalues: The returned reference would go
+ stale too soon. So while this works (but detaches the returned object):
+ \snippet code/src_corelib_global_qglobal.cpp as-const-2
+
+ this would not:
+ \snippet code/src_corelib_global_qglobal.cpp as-const-3
+
+ To prevent this construct from compiling (and failing at runtime), qAsConst() has
+ a second, deleted, overload which binds to rvalues.
+
+ \note You can make the qAsConst() function unavailable by defining
+ the \l{QT_NO_QASCONST} macro.
+*/
+
+/*!
+ \macro QT_NO_QASCONST
+ \since 6.8
+ \relates <QtTypeTraits>
+
+ Defining this macro removes the availability of the qAsConst()
+ function.
+
+ \sa qAsConst
+*/
+
+/*!
+ \fn template <typename T> void qAsConst(const T &&t)
+ \relates <QtTypeTraits>
+ \since 5.7
+ \overload
+
+ \deprecated [6.6]
+
+ This overload is deleted to prevent a dangling reference in code like
+ \snippet code/src_corelib_global_qglobal.cpp as-const-4
+*/
+
+/*!
+ \fn template <typename T, typename U = T> T qExchange(T &obj, U &&newValue)
+ \relates <QtTypeTraits>
+ \since 5.14
+
+ Replaces the value of \a obj with \a newValue and returns the old value of \a obj.
+
+ This is Qt's implementation of std::exchange(). It differs from std::exchange()
+ only in that it is \c constexpr already before C++20 and noexcept already before C++23.
+
+ We strongly advise to use std::exchange() when you don't need the C++20 or C++23 variants.
+ You can make qExchange() unavailable by defining the \l{QT_NO_QEXCHANGE} macro.
+
+ Here is how to use qExchange() to implement move constructors:
+ \code
+ MyClass(MyClass &&other)
+ : m_pointer{qExchange(other.m_pointer, nullptr)},
+ m_int{qExchange(other.m_int, 0)},
+ m_vector{std::move(other.m_vector)},
+ ...
+ \endcode
+
+ For members of class type, we can use std::move(), as their move-constructor will
+ do the right thing. But for scalar types such as raw pointers or integer type, move
+ is the same as copy, which, particularly for pointers, is not what we expect. So, we
+ cannot use std::move() for such types, but we can use std::exchange()/qExchange() to
+ make sure the source object's member is already reset by the time we get to the
+ initialization of our next data member, which might come in handy if the constructor
+ exits with an exception.
+
+ Here is how to use qExchange() to write a loop that consumes the collection it
+ iterates over:
+ \code
+ for (auto &e : qExchange(collection, {})
+ doSomethingWith(e);
+ \endcode
+
+ Which is equivalent to the following, much more verbose code:
+ \code
+ {
+ auto tmp = std::move(collection);
+ collection = {}; // or collection.clear()
+ for (auto &e : tmp)
+ doSomethingWith(e);
+ } // destroys 'tmp'
+ \endcode
+
+ This is perfectly safe, as the for-loop keeps the result of qExchange() alive for as
+ long as the loop runs, saving the declaration of a temporary variable. Be aware, though,
+ that qExchange() returns a non-const object, so Qt containers may detach.
+*/
+
+/*!
+ \macro QT_NO_QEXCHANGE
+ \since 6.6
+ \relates <QtTypeTraits>
+
+ Defining this macro removes the availability of the qExchange()
+ function.
+
+ \sa qExchange
+*/
diff --git a/src/corelib/global/qtversion.h b/src/corelib/global/qtversion.h
new file mode 100644
index 0000000000..775f2479a9
--- /dev/null
+++ b/src/corelib/global/qtversion.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTVERSION_H
+#define QTVERSION_H
+
+#if 0
+#pragma qt_class(QtVersion)
+#pragma qt_sync_stop_processing
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtcoreexports.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * If we're compiling C++ code:
+ * - and this is a non-namespace build, declare qVersion as extern "C"
+ * - and this is a namespace build, declare it as a regular function
+ * (we're already inside QT_BEGIN_NAMESPACE / QT_END_NAMESPACE)
+ * If we're compiling C code, simply declare the function. If Qt was compiled
+ * in a namespace, qVersion isn't callable anyway.
+ */
+#if !defined(QT_NAMESPACE) && defined(__cplusplus) && !defined(Q_QDOC)
+extern "C"
+#endif
+/* defined in qlibraryinfo.cpp */
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOEXCEPT;
+
+QT_END_NAMESPACE
+
+#endif // __ASSEMBLER__
+
+#endif // QTVERSION_H
diff --git a/src/corelib/global/qtversionchecks.cpp b/src/corelib/global/qtversionchecks.cpp
new file mode 100644
index 0000000000..3e3f4547f1
--- /dev/null
+++ b/src/corelib/global/qtversionchecks.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+/*!
+ \macro QT_VERSION_CHECK(major, minor, patch)
+ \relates <QtVersionChecks>
+
+ Turns the \a major, \a minor and \a patch numbers of a version into an
+ integer that encodes all three. When expressed in hexadecimal, this integer
+ is of form \c 0xMMNNPP wherein \c{0xMM ==} \a major, \c{0xNN ==} \a minor,
+ and \c{0xPP ==} \a patch. This can be compared with another similarly
+ processed version ID.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qt-version-check
+
+ \note the parameters are read as integers in the normal way, so should
+ normally be written in decimal (so a \c 0x prefix must be used if writing
+ them in hexadecimal). Thus \c{QT_VERSION_CHECK(5, 15, 0)} is equal to \c
+ 0x050f00, which could equally be written \c{QT_VERSION_CHECK(5, 0xf, 0)}.
+
+ \sa QT_VERSION
+*/
+
+/*!
+ \macro QT_VERSION
+ \relates <QtVersionChecks>
+
+ This macro expands to a numeric value of the same form as \l
+ QT_VERSION_CHECK() constructs, that specifies the version of Qt with which
+ code using it is compiled. For example, if you compile your application with
+ Qt 6.1.2, the QT_VERSION macro will expand to \c 0x060102, the same as
+ \c{QT_VERSION_CHECK(6, 1, 2)}. Note that this need not agree with the
+ version the application will find itself using at \e runtime.
+
+ You can use QT_VERSION to select the latest Qt features where available
+ while falling back to older implementations otherwise. Using
+ QT_VERSION_CHECK() for the value to compare with is recommended.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 16
+
+ \sa QT_VERSION_STR, QT_VERSION_CHECK(), qVersion()
+*/
diff --git a/src/corelib/global/qtversionchecks.h b/src/corelib/global/qtversionchecks.h
new file mode 100644
index 0000000000..86fc094f4e
--- /dev/null
+++ b/src/corelib/global/qtversionchecks.h
@@ -0,0 +1,114 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTVERSIONCHECKS_H
+#define QTVERSIONCHECKS_H
+
+#if 0
+#pragma qt_class(QtVersionChecks)
+#pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qtconfiginclude.h>
+
+/*
+ QT_VERSION is (major << 16) | (minor << 8) | patch.
+*/
+#define QT_VERSION QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH)
+/*
+ can be used like #if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
+*/
+#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+
+/*
+ Helper macros to make some simple code active in Qt 6 or Qt 7 only,
+ like:
+ struct QT6_ONLY(Q_CORE_EXPORT) QTrivialClass
+ {
+ void QT7_ONLY(Q_CORE_EXPORT) void operate();
+ }
+*/
+#if QT_VERSION_MAJOR == 7 || defined(QT_BOOTSTRAPPED)
+# define QT7_ONLY(...) __VA_ARGS__
+# define QT6_ONLY(...)
+#elif QT_VERSION_MAJOR == 6
+# define QT7_ONLY(...)
+# define QT6_ONLY(...) __VA_ARGS__
+#else
+# error Qt major version not 6 or 7
+#endif
+
+/* Macro and tag type to help overload resolution on functions
+ that are, e.g., QT_REMOVED_SINCE'ed. Example use:
+
+ #if QT_CORE_REMOVED_SINCE(6, 4)
+ int size() const;
+ #endif
+ qsizetype size(QT6_DECL_NEW_OVERLOAD) const;
+
+ in the normal cpp file:
+
+ qsizetype size(QT6_IMPL_NEW_OVERLOAD) const {
+ ~~~
+ }
+
+ in removed_api.cpp:
+
+ int size() const { return int(size(QT6_CALL_NEW_OVERLOAD)); }
+*/
+#ifdef Q_QDOC
+# define QT6_DECL_NEW_OVERLOAD
+# define QT6_DECL_NEW_OVERLOAD_TAIL
+# define QT6_IMPL_NEW_OVERLOAD
+# define QT6_IMPL_NEW_OVERLOAD_TAIL
+# define QT6_CALL_NEW_OVERLOAD
+# define QT6_CALL_NEW_OVERLOAD_TAIL
+#else
+# define QT6_DECL_NEW_OVERLOAD QT6_ONLY(Qt::Disambiguated_t = Qt::Disambiguated)
+# define QT6_DECL_NEW_OVERLOAD_TAIL QT6_ONLY(, QT6_DECL_NEW_OVERLOAD)
+# define QT6_IMPL_NEW_OVERLOAD QT6_ONLY(Qt::Disambiguated_t)
+# define QT6_IMPL_NEW_OVERLOAD_TAIL QT6_ONLY(, QT6_IMPL_NEW_OVERLOAD)
+# define QT6_CALL_NEW_OVERLOAD QT6_ONLY(Qt::Disambiguated)
+# define QT6_CALL_NEW_OVERLOAD_TAIL QT6_ONLY(, QT6_CALL_NEW_OVERLOAD)
+#endif
+
+/*
+ Macro to tag Tech Preview APIs.
+ It expands to nothing, because we want to use it in places where
+ nothing is generally allowed (not even an attribute); for instance:
+ to tag other macros, Q_PROPERTY declarations, and so on.
+
+ Still: use it as if it were an C++ attribute.
+
+ To mark a class as TP:
+ class QT_TECH_PREVIEW_API Q_CORE_EXPORT QClass { ... };
+
+ To mark a function:
+ QT_TECH_PREVIEW_API void qFunction();
+
+ To mark an enumeration or enumerator:
+ enum class QT_TECH_PREVIEW_API QEnum {
+ Enum1,
+ Enum2 QT_TECH_PREVIEW_API,
+ };
+
+ To mark parts of a class:
+ class QClass : public QObject
+ {
+ // Q_OBJECT omitted d/t QTBUG-123229
+
+ QT_TECH_PREVIEW_API
+ Q_PROPERTY(int countNG ...) // this is TP
+
+ Q_PROPERTY(int count ...) // this is stable API
+
+ public:
+ QT_TECH_PREVIEW_API
+ void f(); // TP
+
+ void g(); // stable
+ };
+*/
+#define QT_TECH_PREVIEW_API
+
+#endif /* QTVERSIONCHECKS_H */
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 121c9fdcd8..255a2b33c6 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -1,64 +1,48 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTYPEINFO_H
#define QTYPEINFO_H
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qcontainerfwd.h>
+
+#include <variant>
+#include <optional>
+#include <tuple>
+#include <type_traits>
+
QT_BEGIN_NAMESPACE
+class QDebug;
+
/*
QTypeInfo - type trait functionality
*/
-template <typename T>
-static constexpr bool qIsRelocatable()
-{
- return std::is_trivially_copyable<T>::value && std::is_trivially_destructible<T>::value;
-}
+namespace QtPrivate {
+// A trivially copyable class must also have a trivial, non-deleted
+// destructor [class.prop/1.3], CWG1734. Some implementations don't
+// check for a trivial destructor, because of backwards compatibility
+// with C++98's definition of trivial copyability.
+// Since trivial copiability has implications for the ABI, implementations
+// can't "just fix" their traits. So, although formally redundant, we
+// explicitly check for trivial destruction here.
template <typename T>
-static constexpr bool qIsTrivial()
-{
- return std::is_trivial<T>::value;
+inline constexpr bool qIsRelocatable = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
+
+// Denotes types that are trivially default constructible, and for which
+// value-initialization can be achieved by filling their storage with 0 bits.
+// There is no type trait we can use for this, so we hardcode a list of
+// possibilities that we know are OK on the architectures that we support.
+// The most notable exception are pointers to data members, which for instance
+// on the Itanium ABI are initialized to -1.
+template <typename T>
+inline constexpr bool qIsValueInitializationBitwiseZero =
+ std::is_scalar_v<T> && !std::is_member_object_pointer_v<T>;
+
}
/*
@@ -70,12 +54,11 @@ class QTypeInfo
{
public:
enum {
- isPointer = false,
- isIntegral = std::is_integral<T>::value,
- isComplex = !qIsTrivial<T>(),
- isStatic = true,
- isRelocatable = qIsRelocatable<T>(),
- sizeOf = sizeof(T)
+ isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v<T>,
+ isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral_v<T>,
+ isComplex = !std::is_trivial_v<T>,
+ isRelocatable = QtPrivate::qIsRelocatable<T>,
+ isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<T>,
};
};
@@ -84,55 +67,14 @@ class QTypeInfo<void>
{
public:
enum {
- isPointer = false,
- isIntegral = false,
+ isPointer [[deprecated("Use std::is_pointer instead")]] = false,
+ isIntegral [[deprecated("Use std::is_integral instead")]] = false,
isComplex = false,
- isStatic = false,
isRelocatable = false,
- sizeOf = 0
+ isValueInitializationBitwiseZero = false,
};
};
-template <typename T>
-class QTypeInfo<T*>
-{
-public:
- enum {
- isPointer = true,
- isIntegral = false,
- isComplex = false,
- isStatic = false,
- isRelocatable = true,
- sizeOf = sizeof(T*)
- };
-};
-
-/*!
- \class QTypeInfoQuery
- \inmodule QtCore
- \internal
- \brief QTypeInfoQuery is used to query the values of a given QTypeInfo<T>
-
- We use it because there may be some QTypeInfo<T> specializations in user
- code that don't provide certain flags that we added after Qt 5.0. They are:
- \list
- \li isRelocatable: defaults to !isStatic
- \endlist
-
- DO NOT specialize this class elsewhere.
-*/
-// apply defaults for a generic QTypeInfo<T> that didn't provide the new values
-template <typename T, typename = void>
-struct QTypeInfoQuery : public QTypeInfo<T>
-{
- enum { isRelocatable = !QTypeInfo<T>::isStatic };
-};
-
-// if QTypeInfo<T>::isRelocatable exists, use it
-template <typename T>
-struct QTypeInfoQuery<T, typename std::enable_if<QTypeInfo<T>::isRelocatable || true>::type> : public QTypeInfo<T>
-{};
-
/*!
\class QTypeInfoMerger
\inmodule QtCore
@@ -158,27 +100,35 @@ class QTypeInfoMerger
{
static_assert(sizeof...(Ts) > 0);
public:
- static constexpr bool isComplex = ((QTypeInfoQuery<Ts>::isComplex) || ...);
- static constexpr bool isStatic = ((QTypeInfoQuery<Ts>::isStatic) || ...);
- static constexpr bool isRelocatable = ((QTypeInfoQuery<Ts>::isRelocatable) && ...);
- static constexpr bool isPointer = false;
- static constexpr bool isIntegral = false;
- static constexpr std::size_t sizeOf = sizeof(T);
+ static constexpr bool isComplex = ((QTypeInfo<Ts>::isComplex) || ...);
+ static constexpr bool isRelocatable = ((QTypeInfo<Ts>::isRelocatable) && ...);
+ [[deprecated("Use std::is_pointer instead")]] static constexpr bool isPointer = false;
+ [[deprecated("Use std::is_integral instead")]] static constexpr bool isIntegral = false;
+ static constexpr bool isValueInitializationBitwiseZero = false;
+ static_assert(!isRelocatable ||
+ std::is_copy_constructible_v<T> ||
+ std::is_move_constructible_v<T>,
+ "All Ts... are Q_RELOCATABLE_TYPE, but T is neither copy- nor move-constructible, "
+ "so cannot be Q_RELOCATABLE_TYPE. Please mark T as Q_COMPLEX_TYPE manually.");
};
+// QTypeInfo for std::pair:
+// std::pair is spec'ed to be struct { T1 first; T2 second; }, so, unlike tuple<>,
+// we _can_ specialize QTypeInfo for pair<>:
+template <class T1, class T2>
+class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
+
#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
-template <typename T> class CONTAINER; \
-template <typename T> \
-class QTypeInfo< CONTAINER<T> > \
+template <typename ...T> \
+class QTypeInfo<CONTAINER<T...>> \
{ \
public: \
enum { \
- isPointer = false, \
- isIntegral = false, \
+ isPointer [[deprecated("Use std::is_pointer instead")]] = false, \
+ isIntegral [[deprecated("Use std::is_integral instead")]] = false, \
isComplex = true, \
isRelocatable = true, \
- isStatic = false, \
- sizeOf = sizeof(CONTAINER<T>) \
+ isValueInitializationBitwiseZero = false, \
}; \
}
@@ -186,29 +136,11 @@ Q_DECLARE_MOVABLE_CONTAINER(QList);
Q_DECLARE_MOVABLE_CONTAINER(QQueue);
Q_DECLARE_MOVABLE_CONTAINER(QStack);
Q_DECLARE_MOVABLE_CONTAINER(QSet);
-
-#undef Q_DECLARE_MOVABLE_CONTAINER
-
-#define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
-template <typename K, typename V> class CONTAINER; \
-template <typename K, typename V> \
-class QTypeInfo< CONTAINER<K, V> > \
-{ \
-public: \
- enum { \
- isPointer = false, \
- isIntegral = false, \
- isComplex = true, \
- isStatic = false, \
- isRelocatable = true, \
- sizeOf = sizeof(CONTAINER<K, V>) \
- }; \
-}
-
Q_DECLARE_MOVABLE_CONTAINER(QMap);
Q_DECLARE_MOVABLE_CONTAINER(QMultiMap);
Q_DECLARE_MOVABLE_CONTAINER(QHash);
Q_DECLARE_MOVABLE_CONTAINER(QMultiHash);
+Q_DECLARE_MOVABLE_CONTAINER(QCache);
#undef Q_DECLARE_MOVABLE_CONTAINER
@@ -223,10 +155,9 @@ Q_DECLARE_MOVABLE_CONTAINER(QMultiHash);
enum { /* TYPEINFO flags */
Q_COMPLEX_TYPE = 0,
Q_PRIMITIVE_TYPE = 0x1,
- Q_STATIC_TYPE = 0,
- Q_MOVABLE_TYPE = 0x2, // ### Qt6: merge movable and relocatable once QList no longer depends on it
+ Q_RELOCATABLE_TYPE = 0x2,
+ Q_MOVABLE_TYPE = 0x2,
Q_DUMMY_TYPE = 0x4,
- Q_RELOCATABLE_TYPE = 0x8
};
#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
@@ -234,14 +165,16 @@ class QTypeInfo<TYPE > \
{ \
public: \
enum { \
- isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !qIsTrivial<TYPE>(), \
- isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \
- isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE) || qIsRelocatable<TYPE>(), \
- isPointer = false, \
- isIntegral = std::is_integral< TYPE >::value, \
- sizeOf = sizeof(TYPE) \
+ isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \
+ isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || QtPrivate::qIsRelocatable<TYPE>, \
+ isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v< TYPE >, \
+ isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral< TYPE >::value, \
+ isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<TYPE>, \
}; \
- static inline const char *name() { return #TYPE; } \
+ static_assert(!isRelocatable || \
+ std::is_copy_constructible_v<TYPE > || \
+ std::is_move_constructible_v<TYPE >, \
+ #TYPE " is neither copy- nor move-constructible, so cannot be Q_RELOCATABLE_TYPE"); \
}
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
@@ -253,74 +186,197 @@ template<typename T> class QFlags;
template<typename T>
Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
-/*
- Specialize a shared type with:
+namespace QTypeTraits
+{
- Q_DECLARE_SHARED(type)
+/*
+ The templates below aim to find out whether one can safely instantiate an operator==() or
+ operator<() for a type.
- where 'type' is the name of the type to specialize. NOTE: shared
- types must define a member-swap, and be defined in the same
- namespace as Qt for this to work.
+ This is tricky for containers, as most containers have unconstrained comparison operators, even though they
+ rely on the corresponding operators for its content.
+ This is especially true for all of the STL template classes that have a comparison operator defined, and
+ leads to the situation, that the compiler would try to instantiate the operator, and fail if any
+ of its template arguments does not have the operator implemented.
- If the type was already released without Q_DECLARE_SHARED applied,
- _and_ without an explicit Q_DECLARE_TYPEINFO(type, Q_MOVABLE_TYPE),
- then use Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(type) to mark the
- type shared (incl. swap()), without marking it movable (which
- would change the memory layout of QList, a BiC change.
+ The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type
+ of a container (if it exists), and checking the template arguments of pair, tuple and variant.
*/
+namespace detail {
-#define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
-Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
-inline void swap(TYPE &value1, TYPE &value2) \
- noexcept(noexcept(value1.swap(value2))) \
-{ value1.swap(value2); }
-#define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_MOVABLE_TYPE)
-#define Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(TYPE) \
- Q_DECLARE_SHARED_IMPL(TYPE, QT_VERSION >= QT_VERSION_CHECK(6,0,0) ? Q_MOVABLE_TYPE : Q_RELOCATABLE_TYPE)
+// find out whether T is a conteiner
+// this is required to check the value type of containers for the existence of the comparison operator
+template <typename, typename = void>
+struct is_container : std::false_type {};
+template <typename T>
+struct is_container<T, std::void_t<
+ typename T::value_type,
+ std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
+>> : std::true_type {};
+
+
+// Checks the existence of the comparison operator for the class itself
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_FLOAT_COMPARE
+template <typename, typename = void>
+struct has_operator_equal : std::false_type {};
+template <typename T>
+struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
+ : std::true_type {};
+QT_WARNING_POP
+
+// Two forward declarations
+template<typename T, bool = is_container<T>::value>
+struct expand_operator_equal_container;
+template<typename T>
+struct expand_operator_equal_tuple;
+
+// the entry point for the public method
+template<typename T>
+using expand_operator_equal = expand_operator_equal_container<T>;
+
+// if T isn't a container check if it's a tuple like object
+template<typename T, bool>
+struct expand_operator_equal_container : expand_operator_equal_tuple<T> {};
+// if T::value_type exists, check first T::value_type, then T itself
+template<typename T>
+struct expand_operator_equal_container<T, true> :
+ std::conjunction<
+ std::disjunction<
+ std::is_same<T, typename T::value_type>, // avoid endless recursion
+ expand_operator_equal<typename T::value_type>
+ >, expand_operator_equal_tuple<T>> {};
+
+// recursively check the template arguments of a tuple like object
+template<typename ...T>
+using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>;
+
+template<typename T>
+struct expand_operator_equal_tuple : has_operator_equal<T> {};
+template<typename T>
+struct expand_operator_equal_tuple<std::optional<T>> : expand_operator_equal_recursive<T> {};
+template<typename T1, typename T2>
+struct expand_operator_equal_tuple<std::pair<T1, T2>> : expand_operator_equal_recursive<T1, T2> {};
+template<typename ...T>
+struct expand_operator_equal_tuple<std::tuple<T...>> : expand_operator_equal_recursive<T...> {};
+template<typename ...T>
+struct expand_operator_equal_tuple<std::variant<T...>> : expand_operator_equal_recursive<T...> {};
+
+// the same for operator<(), see above for explanations
+template <typename, typename = void>
+struct has_operator_less_than : std::false_type{};
+template <typename T>
+struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
+ : std::true_type{};
+
+template<typename T, bool = is_container<T>::value>
+struct expand_operator_less_than_container;
+template<typename T>
+struct expand_operator_less_than_tuple;
+
+template<typename T>
+using expand_operator_less_than = expand_operator_less_than_container<T>;
+
+template<typename T, bool>
+struct expand_operator_less_than_container : expand_operator_less_than_tuple<T> {};
+template<typename T>
+struct expand_operator_less_than_container<T, true> :
+ std::conjunction<
+ std::disjunction<
+ std::is_same<T, typename T::value_type>,
+ expand_operator_less_than<typename T::value_type>
+ >, expand_operator_less_than_tuple<T>
+ > {};
+
+template<typename ...T>
+using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
+
+template<typename T>
+struct expand_operator_less_than_tuple : has_operator_less_than<T> {};
+template<typename T>
+struct expand_operator_less_than_tuple<std::optional<T>> : expand_operator_less_than_recursive<T> {};
+template<typename T1, typename T2>
+struct expand_operator_less_than_tuple<std::pair<T1, T2>> : expand_operator_less_than_recursive<T1, T2> {};
+template<typename ...T>
+struct expand_operator_less_than_tuple<std::tuple<T...>> : expand_operator_less_than_recursive<T...> {};
+template<typename ...T>
+struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_less_than_recursive<T...> {};
+
+}
+
+template<typename T, typename = void>
+struct is_dereferenceable : std::false_type {};
+
+template<typename T>
+struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
+ : std::true_type {};
+
+template <typename T>
+inline constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value;
+
+template<typename T>
+struct has_operator_equal : detail::expand_operator_equal<T> {};
+template<typename T>
+inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value;
+
+template <typename Container, typename T>
+using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
+
+template<typename T>
+struct has_operator_less_than : detail::expand_operator_less_than<T> {};
+template<typename T>
+inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
+
+template <typename Container, typename T>
+using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
+
+template <typename ...T>
+using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
+
+template <typename Container, typename ...T>
+using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
+
+template <typename ...T>
+using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
+
+template <typename Container, typename ...T>
+using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
+
+namespace detail {
+
+template<typename T>
+const T &const_reference();
+template<typename T>
+T &reference();
+
+}
+
+template <typename Stream, typename, typename = void>
+struct has_ostream_operator : std::false_type {};
+template <typename Stream, typename T>
+struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
+ : std::true_type {};
+template <typename Stream, typename T>
+inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
+
+template <typename Stream, typename Container, typename T>
+using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
+
+template <typename Stream, typename, typename = void>
+struct has_istream_operator : std::false_type {};
+template <typename Stream, typename T>
+struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
+ : std::true_type {};
+template <typename Stream, typename T>
+inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value;
+template <typename Stream, typename Container, typename T>
+using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
+
+template <typename Stream, typename T>
+inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
+
+}
-/*
- QTypeInfo primitive specializations
-*/
-Q_DECLARE_TYPEINFO(bool, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(char, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(signed char, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(uchar, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(short, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(ushort, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(int, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(uint, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(long, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(ulong, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(qint64, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(quint64, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(float, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(double, Q_PRIMITIVE_TYPE);
-
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
-// ### Qt 6: remove the other branch
-// This was required so that QList<T> for these types allocates out of the array storage
-Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
-# ifdef Q_COMPILER_UNICODE_STRINGS
-Q_DECLARE_TYPEINFO(char16_t, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE);
-# endif
-# if !defined(Q_CC_MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-Q_DECLARE_TYPEINFO(wchar_t, Q_PRIMITIVE_TYPE);
-# endif
-#else
-# ifndef Q_OS_DARWIN
-Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
-# else
-Q_DECLARE_TYPEINFO(long double, Q_RELOCATABLE_TYPE);
-# endif
-# ifdef Q_COMPILER_UNICODE_STRINGS
-Q_DECLARE_TYPEINFO(char16_t, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(char32_t, Q_RELOCATABLE_TYPE);
-# endif
-# if !defined(Q_CC_MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-Q_DECLARE_TYPEINFO(wchar_t, Q_RELOCATABLE_TYPE);
-# endif
-#endif // Qt 6
QT_END_NAMESPACE
#endif // QTYPEINFO_H
diff --git a/src/corelib/global/qtypeinfo.qdoc b/src/corelib/global/qtypeinfo.qdoc
new file mode 100644
index 0000000000..75a92da197
--- /dev/null
+++ b/src/corelib/global/qtypeinfo.qdoc
@@ -0,0 +1,48 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro Q_DECLARE_TYPEINFO(Type, Flags)
+ \relates <QTypeInfo>
+
+ You can use this macro to specify information about a custom type
+ \a Type. With accurate type information, Qt's \l{Container Classes}
+ {generic containers} can choose appropriate storage methods and
+ algorithms.
+
+ \a Flags can be one of the following:
+
+ \list
+ \li \c Q_PRIMITIVE_TYPE specifies that \a Type requires no
+ operation to be performed in order to be properly destroyed,
+ and that it is possible to use memcpy() in order to create a
+ valid independent copy of an object.
+ \li \c Q_RELOCATABLE_TYPE specifies that \a Type has a constructor
+ and/or a destructor, but it can still be \e{relocated} in memory
+ by using \c memcpy().
+ \li \c Q_MOVABLE_TYPE is the same as \c Q_RELOCATABLE_TYPE. Prefer to use
+ \c Q_RELOCATABLE_TYPE in new code. Note: despite the name, this
+ has nothing to do with move constructors or C++ move semantics.
+ \li \c Q_COMPLEX_TYPE (the default) specifies that \a Type has
+ constructors and/or a destructor and that it may not be moved
+ in memory.
+ \endlist
+
+ Example of a "primitive" type:
+
+ \snippet code/src_corelib_global_qglobal.cpp 38
+
+ An example of a non-POD "primitive" type is QUuid: Even though
+ QUuid has constructors (and therefore isn't POD), every bit
+ pattern still represents a valid object, and memcpy() can be used
+ to create a valid independent copy of a QUuid object.
+
+ Example of a relocatable type:
+
+ \snippet code/src_corelib_global_qglobal.cpp 39
+
+ Qt will try to detect the class of a type using standard C++ type traits;
+ use this macro to tune the behavior.
+ For instance many types would be candidates for Q_RELOCATABLE_TYPE despite
+ not being trivially-copyable.
+*/
diff --git a/src/corelib/global/qtypes.cpp b/src/corelib/global/qtypes.cpp
new file mode 100644
index 0000000000..9de3960e2f
--- /dev/null
+++ b/src/corelib/global/qtypes.cpp
@@ -0,0 +1,528 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qtypes.h"
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qsystemdetection.h>
+#include <QtCore/qprocessordetection.h>
+
+#include <climits>
+#include <limits>
+#include <type_traits>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \headerfile <QtTypes>
+ \inmodule QtCore
+ \title Qt Type Declarations
+
+ \brief The <QtTypes> header file includes Qt fundamental type declarations.
+
+ The header file declares several type definitions that guarantee a
+ specified bit-size on all platforms supported by Qt for various
+ basic types, for example \l qint8 which is a signed char
+ guaranteed to be 8-bit on all platforms supported by Qt. The
+ header file also declares the \l qlonglong type definition for
+ \c {long long int}.
+
+ Several convenience type definitions are declared: \l qreal for \c
+ double or \c float, \l uchar for \c {unsigned char}, \l uint for
+ \c {unsigned int}, \l ulong for \c {unsigned long} and \l ushort
+ for \c {unsigned short}.
+
+ The header also provides series of macros that make it possible to print
+ some Qt type aliases (qsizetype, qintptr, etc.) via a formatted output
+ facility such as printf() or qDebug() without raising formatting warnings
+ and without the need of a type cast.
+*/
+
+/*!
+ \typedef qreal
+ \relates <QtTypes>
+
+ Typedef for \c double unless Qt is configured with the
+ \c{-qreal float} option.
+*/
+
+/*! \typedef uchar
+ \relates <QtTypes>
+
+ Convenience typedef for \c{unsigned char}.
+*/
+
+/*! \typedef ushort
+ \relates <QtTypes>
+
+ Convenience typedef for \c{unsigned short}.
+*/
+
+/*! \typedef uint
+ \relates <QtTypes>
+
+ Convenience typedef for \c{unsigned int}.
+*/
+
+/*! \typedef ulong
+ \relates <QtTypes>
+
+ Convenience typedef for \c{unsigned long}.
+*/
+
+/*! \typedef qint8
+ \relates <QtTypes>
+
+ Typedef for \c{signed char}. This type is guaranteed to be 8-bit
+ on all platforms supported by Qt.
+*/
+
+/*!
+ \typedef quint8
+ \relates <QtTypes>
+
+ Typedef for \c{unsigned char}. This type is guaranteed to
+ be 8-bit on all platforms supported by Qt.
+*/
+
+/*! \typedef qint16
+ \relates <QtTypes>
+
+ Typedef for \c{signed short}. This type is guaranteed to be
+ 16-bit on all platforms supported by Qt.
+*/
+
+/*!
+ \typedef quint16
+ \relates <QtTypes>
+
+ Typedef for \c{unsigned short}. This type is guaranteed to
+ be 16-bit on all platforms supported by Qt.
+*/
+
+/*! \typedef qint32
+ \relates <QtTypes>
+
+ Typedef for \c{signed int}. This type is guaranteed to be 32-bit
+ on all platforms supported by Qt.
+*/
+
+/*!
+ \typedef quint32
+ \relates <QtTypes>
+
+ Typedef for \c{unsigned int}. This type is guaranteed to
+ be 32-bit on all platforms supported by Qt.
+*/
+
+/*! \typedef qint64
+ \relates <QtTypes>
+
+ Typedef for \c{long long int}. This type is guaranteed to be 64-bit
+ on all platforms supported by Qt.
+
+ Literals of this type can be created using the Q_INT64_C() macro:
+
+ \snippet code/src_corelib_global_qglobal.cpp 5
+
+ \sa Q_INT64_C(), quint64, qlonglong
+*/
+
+/*!
+ \typedef quint64
+ \relates <QtTypes>
+
+ Typedef for \c{unsigned long long int}. This type is guaranteed to
+ be 64-bit on all platforms supported by Qt.
+
+ Literals of this type can be created using the Q_UINT64_C()
+ macro:
+
+ \snippet code/src_corelib_global_qglobal.cpp 6
+
+ \sa Q_UINT64_C(), qint64, qulonglong
+*/
+
+/*!
+ \typedef qint128
+ \relates <QtTypes>
+ \since 6.6
+
+ Typedef for \c{__int128} on platforms that support it (Qt defines the macro
+ \l QT_SUPPORTS_INT128 if this is the case).
+
+ Literals of this type can be created using the Q_INT128_C() macro.
+
+ \sa Q_INT128_C(), Q_INT128_MIN, Q_INT128_MAX, quint128, QT_SUPPORTS_INT128
+*/
+
+/*!
+ \typedef quint128
+ \relates <QtTypes>
+ \since 6.6
+
+ Typedef for \c{unsigned __int128} on platforms that support it (Qt defines
+ the macro \l QT_SUPPORTS_INT128 if this is the case).
+
+ Literals of this type can be created using the Q_UINT128_C() macro.
+
+ \sa Q_UINT128_C(), Q_UINT128_MAX, qint128, QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro QT_SUPPORTS_INT128
+ \relates <QtTypes>
+ \since 6.6
+
+ Qt defines this macro as well as the \l qint128 and \l quint128 types if
+ the platform has support for 128-bit integer types.
+
+ \sa qint128, quint128, Q_INT128_C(), Q_UINT128_C(), Q_INT128_MIN, Q_INT128_MAX, Q_UINT128_MAX
+*/
+
+/*!
+ \typedef qintptr
+ \relates <QtTypes>
+
+ Integral type for representing pointers in a signed integer (useful for
+ hashing, etc.).
+
+ Typedef for either qint32 or qint64. This type is guaranteed to
+ be the same size as a pointer on all platforms supported by Qt. On
+ a system with 32-bit pointers, qintptr is a typedef for qint32;
+ on a system with 64-bit pointers, qintptr is a typedef for
+ qint64.
+
+ Note that qintptr is signed. Use quintptr for unsigned values.
+
+ In order to print values of this type by using formatted-output
+ facilities such as \c{printf()}, qDebug(), QString::asprintf() and
+ so on, you can use the \c{PRIdQINTPTR} and \c{PRIiQINTPTR}
+ macros as format specifiers. They will both print the value as a
+ base 10 number.
+
+ \code
+ qintptr p = 123;
+ printf("The pointer is %" PRIdQINTPTR "\n", p);
+ \endcode
+
+ \sa qptrdiff, qint32, qint64
+*/
+
+/*! \typedef qlonglong
+ \relates <QtTypes>
+
+ Typedef for \c{long long int} (\c __int64 on Windows). This is
+ the same as \l qint64.
+
+ \sa qulonglong, qint64
+*/
+
+/*!
+ \typedef qulonglong
+ \relates <QtTypes>
+
+ Typedef for \c{unsigned long long int} (\c{unsigned __int64} on
+ Windows). This is the same as \l quint64.
+
+ \sa quint64, qlonglong
+*/
+
+/*!
+ \macro PRIdQINTPTR
+ \macro PRIiQINTPTR
+ \since 6.2
+ \relates <QtTypes>
+
+ See \l qintptr.
+*/
+
+/*!
+ \typedef quintptr
+ \relates <QtTypes>
+
+ Integral type for representing pointers in an unsigned integer (useful for
+ hashing, etc.).
+
+ Typedef for either quint32 or quint64. This type is guaranteed to
+ be the same size as a pointer on all platforms supported by Qt. On
+ a system with 32-bit pointers, quintptr is a typedef for quint32;
+ on a system with 64-bit pointers, quintptr is a typedef for
+ quint64.
+
+ Note that quintptr is unsigned. Use qptrdiff for signed values.
+
+ In order to print values of this type by using formatted-output
+ facilities such as \c{printf()}, qDebug(), QString::asprintf() and
+ so on, you can use the following macros as format specifiers:
+
+ \list
+ \li \c{PRIuQUINTPTR}: prints the value as a base 10 number.
+ \li \c{PRIoQUINTPTR}: prints the value as a base 8 number.
+ \li \c{PRIxQUINTPTR}: prints the value as a base 16 number, using lowercase \c{a-f} letters.
+ \li \c{PRIXQUINTPTR}: prints the value as a base 16 number, using uppercase \c{A-F} letters.
+ \endlist
+
+ \code
+ quintptr p = 123u;
+ printf("The pointer value is 0x%" PRIXQUINTPTR "\n", p);
+ \endcode
+
+ \sa qptrdiff, quint32, quint64
+*/
+
+/*!
+ \macro PRIoQUINTPTR
+ \macro PRIuQUINTPTR
+ \macro PRIxQUINTPTR
+ \macro PRIXQUINTPTR
+ \since 6.2
+ \relates <QtTypes>
+
+ See quintptr.
+*/
+
+/*!
+ \typedef qptrdiff
+ \relates <QtTypes>
+
+ Integral type for representing pointer differences.
+
+ Typedef for either qint32 or qint64. This type is guaranteed to be
+ the same size as a pointer on all platforms supported by Qt. On a
+ system with 32-bit pointers, quintptr is a typedef for quint32; on
+ a system with 64-bit pointers, quintptr is a typedef for quint64.
+
+ Note that qptrdiff is signed. Use quintptr for unsigned values.
+
+ In order to print values of this type by using formatted-output
+ facilities such as \c{printf()}, qDebug(), QString::asprintf() and
+ so on, you can use the \c{PRIdQPTRDIFF} and \c{PRIiQPTRDIFF}
+ macros as format specifiers. They will both print the value as a
+ base 10 number.
+
+ \code
+ qptrdiff d = 123;
+ printf("The difference is %" PRIdQPTRDIFF "\n", d);
+ \endcode
+
+ \sa quintptr, qint32, qint64
+*/
+
+/*!
+ \macro PRIdQPTRDIFF
+ \macro PRIiQPTRDIFF
+ \since 6.2
+ \relates <QtTypes>
+
+ See qptrdiff.
+*/
+
+/*!
+ \typedef qsizetype
+ \relates <QtTypes>
+ \since 5.10
+
+ Integral type providing Posix' \c ssize_t for all platforms.
+
+ This type is guaranteed to be the same size as a \c size_t on all
+ platforms supported by Qt.
+
+ Note that qsizetype is signed. Use \c size_t for unsigned values.
+
+ In order to print values of this type by using formatted-output
+ facilities such as \c{printf()}, qDebug(), QString::asprintf() and
+ so on, you can use the \c{PRIdQSIZETYPE} and \c{PRIiQSIZETYPE}
+ macros as format specifiers. They will both print the value as a
+ base 10 number.
+
+ \code
+ qsizetype s = 123;
+ printf("The size is %" PRIdQSIZETYPE "\n", s);
+ \endcode
+
+ \sa qptrdiff
+*/
+
+/*!
+ \macro PRIdQSIZETYPE
+ \macro PRIiQSIZETYPE
+ \since 6.2
+ \relates <QtTypes>
+
+ See qsizetype.
+*/
+
+/*! \macro qint64 Q_INT64_C(literal)
+ \relates <QtTypes>
+
+ Wraps the signed 64-bit integer \a literal in a
+ platform-independent way.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 8
+
+ \sa qint64, Q_UINT64_C(), Q_INT128_C()
+*/
+
+/*! \macro quint64 Q_UINT64_C(literal)
+ \relates <QtTypes>
+
+ Wraps the unsigned 64-bit integer \a literal in a
+ platform-independent way.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp 9
+
+ \sa quint64, Q_INT64_C(), Q_UINT128_C()
+*/
+
+/*!
+ \macro qint128 Q_INT128_C(literal)
+ \relates <QtTypes>
+ \since 6.6
+
+ Wraps the signed 128-bit integer \a literal in a
+ platform-independent way.
+
+ \note Unlike Q_INT64_C(), this macro is only available in C++, not in C.
+ This is because compilers do not provide these literals as built-ins and C
+ does not have support for user-defined literals.
+
+ \sa qint128, Q_UINT128_C(), Q_INT128_MIN, Q_INT128_MAX, Q_INT64_C(), QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro quint128 Q_UINT128_C(literal)
+ \relates <QtTypes>
+ \since 6.6
+
+ Wraps the unsigned 128-bit integer \a literal in a
+ platform-independent way.
+
+ \note Unlike Q_UINT64_C(), this macro is only available in C++, not in C.
+ This is because compilers do not provide these literals as built-ins and C
+ does not have support for user-defined literals.
+
+ \sa quint128, Q_INT128_C(), Q_UINT128_MAX, Q_UINT64_C(), QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro Q_UINT128_MAX
+ \relates <QtTypes>
+ \since 6.6
+
+ This macro expands to a compile-time constant representing the
+ maximum value representable in a \l quint128.
+
+ This macro is available in both C++ and C modes.
+
+ The minimum of \l quint128 is 0 (zero), so a \c{Q_UINT128_MIN} is neither
+ needed nor provided.
+
+ \sa Q_INT128_MAX, quint128, Q_UINT128_C, QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro Q_INT128_MIN
+ \relates <QtTypes>
+ \since 6.6
+
+ This macro expands to a compile-time constant representing the
+ minimum value representable in a \l qint128.
+
+ This macro is available in both C++ and C modes.
+
+ \sa Q_INT128_MAX, qint128, Q_INT128_C, QT_SUPPORTS_INT128
+*/
+
+/*!
+ \macro Q_INT128_MAX
+ \relates <QtTypes>
+ \since 6.6
+
+ This macro expands to a compile-time constant representing the
+ maximum value representable in a \l qint128.
+
+ This macro is available in both C++ and C modes.
+
+ \sa Q_INT128_MIN, Q_UINT128_MAX, qint128, Q_INT128_C, QT_SUPPORTS_INT128
+*/
+
+// Statically check assumptions about the environment we're running
+// in. The idea here is to error or warn if otherwise implicit Qt
+// assumptions are not fulfilled on new hardware or compilers
+// (if this list becomes too long, consider factoring into a separate file)
+static_assert(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
+static_assert(sizeof(int) == 4, "Qt assumes that int is 32 bits");
+static_assert(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined incorrectly");
+static_assert(sizeof(float) == 4, "Qt assumes that float is 32 bits");
+static_assert(sizeof(char16_t) == 2, "Qt assumes that char16_t is 16 bits");
+static_assert(sizeof(char32_t) == 4, "Qt assumes that char32_t is 32 bits");
+#if defined(Q_OS_WIN)
+static_assert(sizeof(wchar_t) == sizeof(char16_t));
+#endif
+static_assert(std::numeric_limits<int>::radix == 2,
+ "Qt assumes binary integers");
+static_assert((std::numeric_limits<int>::max() + std::numeric_limits<int>::lowest()) == -1,
+ "Qt assumes two's complement integers");
+static_assert(sizeof(wchar_t) == sizeof(char32_t) || sizeof(wchar_t) == sizeof(char16_t),
+ "Qt assumes wchar_t is compatible with either char32_t or char16_t");
+
+// While we'd like to check for __STDC_IEC_559__, as per ISO/IEC 9899:2011
+// Annex F (C11, normative for C++11), there are a few corner cases regarding
+// denormals where GHS compiler is relying hardware behavior that is not IEC
+// 559 compliant. So split the check in several subchecks.
+
+// On GHS the compiler reports std::numeric_limits<float>::is_iec559 as false.
+// This is all right according to our needs.
+#if !defined(Q_CC_GHS)
+static_assert(std::numeric_limits<float>::is_iec559,
+ "Qt assumes IEEE 754 floating point");
+#endif
+
+// Technically, presence of NaN and infinities are implied from the above check,
+// but double checking our environment doesn't hurt...
+static_assert(std::numeric_limits<float>::has_infinity &&
+ std::numeric_limits<float>::has_quiet_NaN,
+ "Qt assumes IEEE 754 floating point");
+
+// is_iec559 checks for ISO/IEC/IEEE 60559:2011 (aka IEEE 754-2008) compliance,
+// but that allows for a non-binary radix. We need to recheck that.
+// Note how __STDC_IEC_559__ would instead check for IEC 60559:1989, aka
+// ANSI/IEEE 754−1985, which specifically implies binary floating point numbers.
+static_assert(std::numeric_limits<float>::radix == 2,
+ "Qt assumes binary IEEE 754 floating point");
+
+// not required by the definition of size_t, but we depend on this
+static_assert(sizeof(size_t) == sizeof(void *), "size_t and a pointer don't have the same size");
+static_assert(sizeof(size_t) == sizeof(qsizetype)); // implied by the definition
+static_assert((std::is_same<qsizetype, qptrdiff>::value));
+static_assert(std::is_same_v<std::size_t, size_t>);
+
+// Check that our own typedefs are not broken.
+static_assert(sizeof(qint8) == 1, "Internal error, qint8 is misdefined");
+static_assert(sizeof(qint16)== 2, "Internal error, qint16 is misdefined");
+static_assert(sizeof(qint32) == 4, "Internal error, qint32 is misdefined");
+static_assert(sizeof(qint64) == 8, "Internal error, qint64 is misdefined");
+#ifdef QT_SUPPORTS_INT128
+static_assert(sizeof(qint128) == 16, "Internal error, qint128 is misdefined");
+#endif
+
+#ifdef QT_SUPPORTS_INT128
+// Standard Library supports for 128-bit integers:
+// Implementation | Version | Note
+// ---------------------|---------|------
+// GNU libstdc++ | 11.1.0 |
+// LLVM libc++ | 3.5 | May change if compiler has __is_integral()
+// MS STL | none |
+
+# if defined(_LIBCPP_VERSION) || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 11)
+static_assert(std::numeric_limits<quint128>::max() == Q_UINT128_MAX);
+# endif
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qtypes.h b/src/corelib/global/qtypes.h
new file mode 100644
index 0000000000..db9ba38e4c
--- /dev/null
+++ b/src/corelib/global/qtypes.h
@@ -0,0 +1,283 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTYPES_H
+#define QTYPES_H
+
+#include <QtCore/qprocessordetection.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qassert.h>
+
+#ifdef __cplusplus
+# include <cstddef>
+# include <cstdint>
+# if defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>)
+// P1467 implementation - https://wg21.link/p1467
+# include <stdfloat>
+# endif // defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>)
+#else
+# include <assert.h>
+#endif
+
+#if 0
+#pragma qt_class(QtTypes)
+#pragma qt_class(QIntegerForSize)
+#pragma qt_sync_stop_processing
+#endif
+
+/*
+ Useful type definitions for Qt
+*/
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Size-dependent types (architecture-dependent byte order)
+
+ Make sure to update QMetaType when changing these typedefs
+*/
+
+typedef signed char qint8; /* 8 bit signed */
+typedef unsigned char quint8; /* 8 bit unsigned */
+typedef short qint16; /* 16 bit signed */
+typedef unsigned short quint16; /* 16 bit unsigned */
+typedef int qint32; /* 32 bit signed */
+typedef unsigned int quint32; /* 32 bit unsigned */
+// Unlike LL / ULL in C++, for historical reasons, we force the
+// result to be of the requested type.
+#ifdef __cplusplus
+# define Q_INT64_C(c) static_cast<long long>(c ## LL) /* signed 64 bit constant */
+# define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */
+#else
+# define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */
+# define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */
+#endif
+typedef long long qint64; /* 64 bit signed */
+typedef unsigned long long quint64; /* 64 bit unsigned */
+
+typedef qint64 qlonglong;
+typedef quint64 qulonglong;
+
+#if defined(__SIZEOF_INT128__) && !defined(QT_NO_INT128)
+# define QT_SUPPORTS_INT128 __SIZEOF_INT128__
+#else
+# undef QT_SUPPORTS_INT128
+#endif
+
+#if defined(QT_SUPPORTS_INT128)
+__extension__ typedef __int128_t qint128;
+__extension__ typedef __uint128_t quint128;
+
+// limits:
+# ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */
+# define QT_C_STYLE_CAST(type, x) static_cast<type>(x)
+# else /* but C doesn't have constructor-style casts */
+# define QT_C_STYLE_CAST(type, x) ((type)(x))
+# endif
+# ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */
+# define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1)
+# endif
+# define Q_INT128_MAX QT_C_STYLE_CAST(qint128, Q_UINT128_MAX / 2)
+# define Q_INT128_MIN (-Q_INT128_MAX - 1)
+
+# ifdef __cplusplus
+ namespace QtPrivate::NumberLiterals {
+ namespace detail {
+ template <quint128 accu, int base>
+ constexpr quint128 construct() { return accu; }
+
+ template <quint128 accu, int base, char C, char...Cs>
+ constexpr quint128 construct()
+ {
+ if constexpr (C != '\'') { // ignore digit separators
+ const int digitValue = '0' <= C && C <= '9' ? C - '0' :
+ 'a' <= C && C <= 'z' ? C - 'a' + 10 :
+ 'A' <= C && C <= 'Z' ? C - 'A' + 10 :
+ /* else */ -1 ;
+ static_assert(digitValue >= 0 && digitValue < base,
+ "Invalid character");
+ // accu * base + digitValue <= MAX, but without overflow:
+ static_assert(accu <= (Q_UINT128_MAX - digitValue) / base,
+ "Overflow occurred");
+ return construct<accu * base + digitValue, base, Cs...>();
+ } else {
+ return construct<accu, base, Cs...>();
+ }
+ }
+
+ template <char C, char...Cs>
+ constexpr quint128 parse0xb()
+ {
+ constexpr quint128 accu = 0;
+ if constexpr (C == 'x' || C == 'X')
+ return construct<accu, 16, Cs...>(); // base 16, skip 'x'
+ else if constexpr (C == 'b' || C == 'B')
+ return construct<accu, 2, Cs...>(); // base 2, skip 'b'
+ else
+ return construct<accu, 8, C, Cs...>(); // base 8, include C
+ }
+
+ template <char...Cs>
+ constexpr quint128 parse0()
+ {
+ if constexpr (sizeof...(Cs) == 0) // this was just a literal 0
+ return 0;
+ else
+ return parse0xb<Cs...>();
+ }
+
+ template <char C, char...Cs>
+ constexpr quint128 parse()
+ {
+ if constexpr (C == '0')
+ return parse0<Cs...>(); // base 2, 8, or 16 (or just a literal 0), skip '0'
+ else
+ return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C
+ }
+ } // namespace detail
+ template <char...Cs>
+ constexpr quint128 operator""_quint128() noexcept
+ { return QtPrivate::NumberLiterals::detail::parse<Cs...>(); }
+ template <char...Cs>
+ constexpr qint128 operator""_qint128() noexcept
+ { return qint128(QtPrivate::NumberLiterals::detail::parse<Cs...>()); }
+
+ #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override
+ # define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }())
+ #endif
+ #ifndef Q_INT128_C // allow qcompilerdetection.h/user override
+ # define Q_INT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128; }())
+ #endif
+
+ } // namespace QtPrivate::NumberLiterals
+# endif // __cplusplus
+#endif // QT_SUPPORTS_INT128
+
+#ifndef __cplusplus
+// In C++ mode, we define below using QIntegerForSize template
+static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions");
+typedef ptrdiff_t qptrdiff;
+typedef ptrdiff_t qsizetype;
+typedef ptrdiff_t qintptr;
+typedef size_t quintptr;
+
+#define PRIdQPTRDIFF "td"
+#define PRIiQPTRDIFF "ti"
+
+#define PRIdQSIZETYPE "td"
+#define PRIiQSIZETYPE "ti"
+
+#define PRIdQINTPTR "td"
+#define PRIiQINTPTR "ti"
+
+#define PRIuQUINTPTR "zu"
+#define PRIoQUINTPTR "zo"
+#define PRIxQUINTPTR "zx"
+#define PRIXQUINTPTR "zX"
+#endif
+
+#if defined(QT_COORD_TYPE)
+typedef QT_COORD_TYPE qreal;
+#else
+typedef double qreal;
+#endif
+
+#if defined(__cplusplus)
+/*
+ quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e.
+
+ sizeof(void *) == sizeof(quintptr)
+ && sizeof(void *) == sizeof(qptrdiff)
+
+ While size_t and qsizetype are not guaranteed to be the same size as a pointer,
+ they usually are and we do check for that in qtypes.cpp, just to be sure.
+*/
+template <int> struct QIntegerForSize;
+template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; };
+template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; };
+template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; };
+template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; };
+#if defined(QT_SUPPORTS_INT128)
+template <> struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; };
+#endif
+template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
+typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint;
+typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint;
+typedef QIntegerForSizeof<void *>::Unsigned quintptr;
+typedef QIntegerForSizeof<void *>::Signed qptrdiff;
+typedef qptrdiff qintptr;
+using qsizetype = QIntegerForSizeof<std::size_t>::Signed;
+
+// These custom definitions are necessary as we're not defining our
+// datatypes in terms of the language ones, but in terms of integer
+// types that have the sime size. For instance, on a 32-bit platform,
+// qptrdiff is int, while ptrdiff_t may be aliased to long; therefore
+// using %td to print a qptrdiff would be wrong (and raise -Wformat
+// warnings), although both int and long have same bit size on that
+// platform.
+//
+// We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff).
+#if SIZE_MAX == 0xffffffffULL
+#define PRIuQUINTPTR "u"
+#define PRIoQUINTPTR "o"
+#define PRIxQUINTPTR "x"
+#define PRIXQUINTPTR "X"
+
+#define PRIdQPTRDIFF "d"
+#define PRIiQPTRDIFF "i"
+
+#define PRIdQINTPTR "d"
+#define PRIiQINTPTR "i"
+
+#define PRIdQSIZETYPE "d"
+#define PRIiQSIZETYPE "i"
+#elif SIZE_MAX == 0xffffffffffffffffULL
+#define PRIuQUINTPTR "llu"
+#define PRIoQUINTPTR "llo"
+#define PRIxQUINTPTR "llx"
+#define PRIXQUINTPTR "llX"
+
+#define PRIdQPTRDIFF "lld"
+#define PRIiQPTRDIFF "lli"
+
+#define PRIdQINTPTR "lld"
+#define PRIiQINTPTR "lli"
+
+#define PRIdQSIZETYPE "lld"
+#define PRIiQSIZETYPE "lli"
+#else
+#error Unsupported platform (unknown value for SIZE_MAX)
+#endif
+
+// Define a native float16 type
+namespace QtPrivate {
+#if defined(__STDCPP_FLOAT16_T__)
+# define QFLOAT16_IS_NATIVE 1
+using NativeFloat16Type = std::float16_t;
+#elif defined(Q_CC_CLANG) && defined(__FLT16_MAX__) && 0
+// disabled due to https://github.com/llvm/llvm-project/issues/56963
+# define QFLOAT16_IS_NATIVE 1
+using NativeFloat16Type = decltype(__FLT16_MAX__);
+#elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__)
+# define QFLOAT16_IS_NATIVE 1
+# ifdef __ARM_FP16_FORMAT_IEEE
+using NativeFloat16Type = __fp16;
+# else
+using NativeFloat16Type = _Float16;
+# endif
+#else
+# define QFLOAT16_IS_NATIVE 0
+using NativeFloat16Type = void;
+#endif
+} // QtPrivate
+
+#endif // __cplusplus
+
+QT_END_NAMESPACE
+
+#endif // QTYPES_H
diff --git a/src/corelib/global/qtypetraits.h b/src/corelib/global/qtypetraits.h
deleted file mode 100644
index 35e407e2de..0000000000
--- a/src/corelib/global/qtypetraits.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// ### Qt 6: remove this header
-//
-// This header is deliberately empty. Although it did not contain any public API,
-// it was accidentally made public in Qt 5. So: do not remove it for the moment
-// being, to prevent #include breaks in downstreams.
-
-#include "QtCore/qglobal.h"
-
-#ifndef QTYPETRAITS_H
-#define QTYPETRAITS_H
-
-QT_BEGIN_NAMESPACE
-
-QT_END_NAMESPACE
-
-#endif // QTYPETRAITS_H
diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp
index b5e524bf4c..a8191869cc 100644
--- a/src/corelib/global/qversiontagging.cpp
+++ b/src/corelib/global/qversiontagging.cpp
@@ -1,58 +1,43 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
+#include "qversiontagging.h"
+extern "C" {
#define SYM QT_MANGLE_NAMESPACE(qt_version_tag)
-//#define SSYM QT_STRINGIFY(SYM)
+#define SSYM QT_STRINGIFY(SYM)
+
+// With compilers that have the "alias" attribute, the macro creates a global
+// variable "qt_version_tag_M_m" (M: major, m: minor) as an alias to either
+// qt_version_tag or _qt_version_tag. Everywhere else, we simply create a new
+// global variable qt_version_tag_M_m without aliasing to a single variable.
+//
+// Additionally, on systems using ELF binaries (Linux, FreeBSD, etc.), we
+// create ELF versions by way of the .symver assembly directive[1].
+//
+// Unfortunately, Clang on Darwin systems says it supports the "alias"
+// attribute, but fails when used. That's a Clang bug (as of XCode 12).
+//
+// [1] https://sourceware.org/binutils/docs/as/Symver.html
-#if defined(Q_CC_GNU) && defined(Q_OF_ELF) && !defined(Q_OS_ANDROID)
+#if defined(Q_CC_GNU) && defined(Q_OF_ELF)
# define make_versioned_symbol2(sym, m, n, separator) \
- Q_CORE_EXPORT extern const char sym ## _ ## m ## _ ## n = 0; \
+ Q_CORE_EXPORT extern __attribute__((alias("_" SSYM))) const char sym ## _ ## m ## _ ## n; \
asm(".symver " QT_STRINGIFY(sym) "_" QT_STRINGIFY(m) "_" QT_STRINGIFY(n) ", " \
QT_STRINGIFY(sym) separator "Qt_" QT_STRINGIFY(m) "." QT_STRINGIFY(n))
+
+extern const char QT_MANGLE_NAMESPACE(_qt_version_tag) = 0;
+#elif __has_attribute(alias) && !defined(Q_OS_DARWIN)
+# define make_versioned_symbol2(sym, m, n, separator) \
+ Q_CORE_EXPORT extern __attribute__((alias(SSYM))) const char sym ## _ ## m ## _ ## n
+extern const char SYM = 0;
#else
-# define make_versioned_symbol2(sym, m, n, separator)
+# define make_versioned_symbol2(sym, m, n, separator) \
+ Q_CORE_EXPORT extern const char sym ## _ ## m ## _ ## n = 0;
#endif
#define make_versioned_symbol(sym, m, n, separator) make_versioned_symbol2(sym, m, n, separator)
-extern "C" {
#if QT_VERSION_MINOR > 0
make_versioned_symbol(SYM, QT_VERSION_MAJOR, 0, "@");
#endif
@@ -102,10 +87,15 @@ make_versioned_symbol(SYM, QT_VERSION_MAJOR, 14, "@");
make_versioned_symbol(SYM, QT_VERSION_MAJOR, 15, "@");
#endif
#if QT_VERSION_MINOR > 16
-// We don't expect there will be a Qt 5.17
# error "Please update this file with more Qt versions."
#endif
// the default version:
make_versioned_symbol(SYM, QT_VERSION_MAJOR, QT_VERSION_MINOR, "@@");
}
+
+QT_BEGIN_NAMESPACE
+
+static_assert(std::is_trivially_destructible_v<QtPrivate::QVersionTag>);
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h
index 75c2e9df7e..fa2dd23728 100644
--- a/src/corelib/global/qversiontagging.h
+++ b/src/corelib/global/qversiontagging.h
@@ -1,88 +1,140 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// qglobal.h includes this header, so keep it outside of our include guards
-#include <QtCore/qglobal.h>
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#if !defined(QVERSIONTAGGING_H)
#define QVERSIONTAGGING_H
+#if 0
+#pragma qt_no_master_include
+#endif
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtversionchecks.h>
+#include <QtCore/qtypes.h>
+
+QT_REQUIRE_CONFIG(version_tagging);
+
QT_BEGIN_NAMESPACE
/*
- * Ugly hack warning and explanation:
+ * Explanation
+ *
+ * This file causes all libraries, plugins, and applications that #include this
+ * file to automatically pull in a symbol found in QtCore that encodes the
+ * current Qt version number at the time of compilation. The relocation is
+ * designed so that it's impossible for the dynamic linker to perform lazy
+ * binding. Instead, it must resolve at load time or fail. That way, attempting
+ * to load such a library or plugin while an older QtCore is loaded will fail.
+ * Similarly, if an older QtCore is found when launching an application, the
+ * application will fail to launch.
+ *
+ * It's also possible to inspect which version is required by decoding the
+ * .qtversion section. The second pointer-sized variable is the required
+ * version, for example, for Qt 6.4.1:
*
- * This file causes all ELF modules, be they libraries or applications, to use the
- * qt_version_tag symbol that is present in QtCore. Such symbol is versioned,
- * so the linker will automatically pull the current Qt version and add it to
- * the ELF header of the library/application. The assembly produces one section
- * called ".qtversion" containing two 32-bit values. The first is a
- * relocation to the qt_version_tag symbol (which is what causes the ELF
- * version to get used). The second value is the current Qt version at the time
- * of compilation.
+ * Hex dump of section [18] '.qtversion', 16 bytes at offset 0x1ee48:
+ * 0x00000000 b0ffffff ffffffff 01040600 00000000 ................
+ * ^^^^^^^^ ^^^^^^^^
*
* There will only be one copy of the section in the output library or application.
+ *
+ * This functionality can be disabled by defining QT_NO_VERSION_TAGGING. It's
+ * disabled if Qt was built statically.
+ *
+ * Windows notes:
+ *
+ * On Windows, the address of a __declspec(dllimport) variable is not a
+ * constant expression, unlike Unix systems. So we instead use the address of
+ * the import variable, which is created by prefixing the external name with
+ * "__imp_". Using that variable causes an import of the corresponding symbol
+ * from QtCore DLL.
+ *
+ * With MinGW (GCC and Clang), we use a C++17 inline variable, so the compiler
+ * and linker automatically merge the variables. The "used" __attribute__
+ * tells the compiler to always emit that variable, whether it's used or not.
+ *
+ * MSVC has no equivalent to that attribute, so instead we create an extern
+ * const variable and tell the linker to merge them all via
+ * __declspec(selectany).
+ *
+ * Unix notes:
+ *
+ * On Unix, we use the same C++17 inline variable solution as MinGW, but we
+ * don't need the "__imp_" trick.
+ *
+ * Additionally, on ELF systems like Linux and FreeBSD, the symbol in question
+ * is simply "qt_version_tag" in both QtCore and in this ELF module, but it
+ * has an ELF version attached to it (see qversiontagging.cpp and
+ * QtFlagHandlingHelpers.cmake). That way, the error message from the dynamic
+ * linker will say it can't find version "Qt_6.x".
*/
-#if defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_NO_VERSION_TAGGING) || defined(QT_STATIC)
+namespace QtPrivate {
+struct QVersionTag
+{
+ const void *symbol;
+ quintptr version;
+ constexpr QVersionTag(const void *sym, int currentVersion = QT_VERSION)
+ : symbol(sym), version(currentVersion)
+ {}
+};
+}
+
+#if !defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC))
// don't make tags in QtCore, bootstrapped systems or if the user asked not to
-#elif defined(Q_CC_GNU) && !defined(Q_OS_ANDROID)
-# if defined(Q_PROCESSOR_X86) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD_KERNEL))
-# if defined(Q_PROCESSOR_X86_64) && QT_POINTER_SIZE == 8 // x86-64 64-bit
-# define QT_VERSION_TAG_RELOC(sym) ".quad " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOT\n"
-# else // x86 or x86-64 32-bit (x32)
-# define QT_VERSION_TAG_RELOC(sym) ".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOT\n"
-# endif
-# define QT_VERSION_TAG(sym) \
- asm ( \
- ".section .qtversion, \"aG\", @progbits, " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) ", comdat\n" \
- ".align 8\n" \
- QT_VERSION_TAG_RELOC(sym) \
- ".long " QT_STRINGIFY(QT_VERSION) "\n" \
- ".align 8\n" \
- ".previous" \
- )
+# define QT_NO_VERSION_TAGGING
+#endif
+
+#if defined(Q_OS_WIN)
+# ifdef Q_PROCESSOR_X86_32
+// 32-bit x86 convention does prepend a _
+# define QT_MANGLE_IMPORT_PREFIX _imp__
+# else
+// Calling convention on other architectures does not prepend a _
+# define QT_MANGLE_IMPORT_PREFIX __imp_
+# endif
+# if defined(Q_CC_MSVC_ONLY)
+# pragma section(".qtversion",read,shared)
+# define QT_VERSION_TAG_SECTION __declspec(allocate(".qtversion"))
+# define QT_VERSION_TAG_ATTRIBUTE __declspec(selectany) extern const
+# else
+# define QT_VERSION_TAG_ATTRIBUTE __attribute__((used)) constexpr inline
# endif
+# define QT_VERSION_TAG2(sym, imp) \
+ extern "C" const char * const imp; \
+ QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION QtPrivate::QVersionTag sym ## _used(&imp)
+# define QT_VERSION_TAG(sym, imp) QT_VERSION_TAG2(sym, imp)
+#elif defined(Q_CC_GNU) && __has_attribute(used)
+# ifdef Q_OS_DARWIN
+# define QT_VERSION_TAG_SECTION __attribute__((section("__DATA,.qtversion")))
+# endif
+# define QT_VERSION_TAG_ATTRIBUTE __attribute__((visibility("hidden"), used))
+# define QT_VERSION_TAG2(sym, imp) \
+ extern "C" Q_DECL_IMPORT const char sym; \
+ QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION constexpr inline QtPrivate::QVersionTag sym ## _use(&sym)
+# define QT_VERSION_TAG(sym, imp) QT_VERSION_TAG2(sym, imp)
+#endif
+
+#ifdef Q_OF_ELF
+# define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n) sym
+#else
+# define QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n) prefix ## sym ## _ ## m ## _ ## n
+# define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n) QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)
#endif
-#if defined(QT_VERSION_TAG)
-QT_VERSION_TAG(qt_version_tag);
+#if defined(QT_VERSION_TAG) && !defined(QT_NO_VERSION_TAGGING)
+# ifndef QT_VERSION_TAG_SECTION
+# define QT_VERSION_TAG_SECTION __attribute__((section(".qtversion")))
+# endif
+# define QT_MANGLED_VERSION_TAG_IMPORT QT_VERSION_TAG_SYMBOL(QT_MANGLE_IMPORT_PREFIX, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
+# define QT_MANGLED_VERSION_TAG QT_VERSION_TAG_SYMBOL(, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
+
+QT_VERSION_TAG(QT_MANGLED_VERSION_TAG, QT_MANGLED_VERSION_TAG_IMPORT);
+
+# undef QT_MANGLED_VERSION_TAG
+# undef QT_MANGLED_VERSION_TAG_IMPORT
+# undef QT_VERSION_TAG_SECTION
#endif
QT_END_NAMESPACE
diff --git a/src/corelib/global/qvolatile_p.h b/src/corelib/global/qvolatile_p.h
new file mode 100644
index 0000000000..36787ecd87
--- /dev/null
+++ b/src/corelib/global/qvolatile_p.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QVOLATILE_P_H
+#define QVOLATILE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+template <typename T>
+using if_volatile = std::enable_if_t<std::is_volatile_v<T>, bool>;
+
+//
+// C++20-deprecated volatile compound operations, rewritten as separated operations
+//
+
+// these functions return `auto`, not `T`, to strip cv-qualifiers without having
+// to mention the `volatile` keyword
+
+template <typename T, QtPrivate::if_volatile<T> = true>
+auto volatilePreIncrement(T &x) {
+ auto y = x;
+ ++y;
+ x = y;
+ return y;
+}
+
+template <typename T, QtPrivate::if_volatile<T> = true>
+auto volatilePreDecrement(T &x)
+{
+ auto y = x;
+ --y;
+ x = y;
+ return y;
+}
+} // namespace QtPrivate
+
+QT_END_NAMESPACE
+
+#endif // QVOLATILE_H
diff --git a/src/corelib/global/qxpfunctional.h b/src/corelib/global/qxpfunctional.h
new file mode 100644
index 0000000000..cbeef8b293
--- /dev/null
+++ b/src/corelib/global/qxpfunctional.h
@@ -0,0 +1,195 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QXPFUNCTIONAL_H
+#define QXPFUNCTIONAL_H
+
+#include <QtCore/qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+#include <QtCore/q23functional.h>
+#include <QtCore/q20type_traits.h>
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+namespace qxp {
+// like P0792r9's function_ref:
+
+// [func.wrap.ref], non-owning wrapper
+template<class... S> class function_ref; // not defined
+
+// template<class R, class... ArgTypes>
+// class function_ref<R(ArgTypes...) cv noexcept(noex)>; // see below
+//
+// [func.wrap.ref.general]
+// The header provides partial specializations of function_ref for each combination
+// of the possible replacements of the placeholders cv and noex where:
+// - cv is either const or empty.
+// - noex is either true or false.
+
+namespace detail {
+
+template <typename T>
+using if_function = std::enable_if_t<std::is_function_v<T>, bool>;
+template <typename T>
+using if_non_function = std::enable_if_t<!std::is_function_v<T>, bool>;
+
+template <typename From, typename To>
+using copy_const_t = std::conditional_t<
+ std::is_const_v<From>,
+ std::add_const_t<To>,
+ To
+ >;
+
+template <class Const>
+union BoundEntityType {
+ template <typename F, if_function<F> = true>
+ explicit constexpr BoundEntityType(F *f)
+ : fun(reinterpret_cast<QFunctionPointer>(f)) {}
+ template <typename T, if_non_function<T> = true>
+ explicit constexpr BoundEntityType(T *t)
+ : obj(static_cast<Const*>(t)) {}
+ Const *obj;
+ QFunctionPointer fun;
+};
+
+template <bool noex, class Const, class R, class... ArgTypes>
+class function_ref_base
+{
+protected:
+ ~function_ref_base() = default;
+
+ using BoundEntityType = detail::BoundEntityType<Const>;
+
+ template <typename... Ts>
+ using is_invocable_using = std::conditional_t<
+ noex,
+ std::is_nothrow_invocable_r<R, Ts..., ArgTypes...>,
+ std::is_invocable_r<R, Ts..., ArgTypes...>
+ >;
+
+ using ThunkPtr = R(*)(BoundEntityType, ArgTypes&&...) noexcept(noex);
+
+ BoundEntityType m_bound_entity;
+ ThunkPtr m_thunk_ptr;
+
+public:
+ template<
+ class F,
+ std::enable_if_t<std::conjunction_v<
+ std::is_function<F>,
+ is_invocable_using<F>
+ >, bool> = true
+ >
+ Q_IMPLICIT function_ref_base(F* f) noexcept
+ : m_bound_entity(f),
+ m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R {
+ return q23::invoke_r<R>(reinterpret_cast<F*>(ctx.fun),
+ std::forward<ArgTypes>(args)...);
+ })
+ {}
+
+ template<
+ class F,
+ std::enable_if_t<std::conjunction_v<
+ std::negation<std::is_same<q20::remove_cvref_t<F>, function_ref_base>>,
+#ifdef Q_OS_VXWORKS
+ // The VxWorks compiler is trying to match this ctor against
+ // qxp::function_ref in lieu of using the copy-constructor, so ban
+ // matching against the equivalent qxp::function_ref here.
+ // This doesn't change anything on other platforms, so to save
+ // on compile-speed, enable it only for VxWorks:
+ std::negation<
+ std::is_same<
+ q20::remove_cvref_t<F>,
+ std::conditional_t<
+ std::is_const_v<Const>,
+ qxp::function_ref<R(ArgTypes...) const noexcept(noex)>,
+ qxp::function_ref<R(ArgTypes...) noexcept(noex)>
+ >
+ >
+ >,
+#endif // Q_OS_VXWORKS
+ std::negation<std::is_member_pointer<std::remove_reference_t<F>>>,
+ is_invocable_using<copy_const_t<Const, std::remove_reference_t<F>>&>
+ >, bool> = true
+ >
+ Q_IMPLICIT constexpr function_ref_base(F&& f) noexcept
+ : m_bound_entity(std::addressof(f)),
+ m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R {
+ using That = copy_const_t<Const, std::remove_reference_t<F>>;
+ return q23::invoke_r<R>(*static_cast<That*>(ctx.obj),
+ std::forward<ArgTypes>(args)...);
+ })
+ {}
+
+protected:
+ template <
+ class T,
+ std::enable_if_t<std::negation_v<
+ std::disjunction<
+ std::is_same<T, function_ref_base>,
+ std::is_pointer<T>
+ >
+ >, bool> = true
+ >
+ function_ref_base& operator=(T) = delete;
+
+ // Invocation [func.wrap.ref.inv]
+ R operator()(ArgTypes... args) const noexcept(noex)
+ {
+ return m_thunk_ptr(m_bound_entity, std::forward<ArgTypes>(args)...);
+ }
+
+};
+
+} // namespace detail
+
+#define QT_SPECIALIZE_FUNCTION_REF(cv, noex) \
+ template<class R, class... ArgTypes> \
+ class function_ref<R(ArgTypes...) cv noexcept( noex )> \
+ : private detail::function_ref_base< noex , cv void, R, ArgTypes...> \
+ { \
+ using base = detail::function_ref_base< noex , cv void, R, ArgTypes...>; \
+ \
+ public: \
+ using base::base; \
+ using base::operator(); \
+ } \
+ /* end */
+
+QT_SPECIALIZE_FUNCTION_REF( , false);
+QT_SPECIALIZE_FUNCTION_REF(const, false);
+QT_SPECIALIZE_FUNCTION_REF( , true );
+QT_SPECIALIZE_FUNCTION_REF(const, true );
+
+#undef QT_SPECIALIZE_FUNCTION_REF
+
+// deduction guides [func.wrap.ref.deduct]
+
+template <
+ class F,
+ detail::if_function<F> = true
+>
+function_ref(F*) -> function_ref<F>;
+
+} // namespace qxp
+
+QT_END_NAMESPACE
+
+#endif /* QXPFUNCTIONAL_H */
diff --git a/src/corelib/global/qxptype_traits.h b/src/corelib/global/qxptype_traits.h
new file mode 100644
index 0000000000..d1641e1d0d
--- /dev/null
+++ b/src/corelib/global/qxptype_traits.h
@@ -0,0 +1,121 @@
+// Copyright (C) 2023 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>, Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QXPTYPE_TRAITS_H
+#define QXPTYPE_TRAITS_H
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qcompilerdetection.h>
+
+#include <type_traits>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. Types and functions defined in this
+// file can reliably be replaced by their std counterparts, once available.
+// You may use these definitions in your own code, but be aware that we
+// will remove them once Qt depends on the C++ version that supports
+// them in namespace std. There will be NO deprecation warning, the
+// definitions will JUST go away.
+//
+// If you can't agree to these terms, don't use these definitions!
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+// like std::experimental::{nonesuch,is_detected/_v}(LFTSv2)
+namespace qxp {
+
+struct nonesuch {
+ ~nonesuch() = delete;
+ nonesuch(const nonesuch&) = delete;
+ void operator=(const nonesuch&) = delete;
+};
+
+namespace _detail {
+ template <typename T, typename Void, template <typename...> class Op, typename...Args>
+ struct detector {
+ using value_t = std::false_type;
+ using type = T;
+ };
+ template <typename T, template <typename...> class Op, typename...Args>
+ struct detector<T, std::void_t<Op<Args...>>, Op, Args...> {
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+ };
+} // namespace _detail
+
+template <template <typename...> class Op, typename...Args>
+using is_detected = typename _detail::detector<qxp::nonesuch, void, Op, Args...>::value_t;
+
+template <template <typename...> class Op, typename...Args>
+constexpr inline bool is_detected_v = is_detected<Op, Args...>::value;
+
+
+// qxp::is_virtual_base_of_v<B, D> is true if and only if B is a virtual base class of D.
+// Just like is_base_of:
+// * only works on complete types;
+// * B and D must be class types;
+// * ignores cv-qualifications;
+// * B may be inaccessibile.
+
+namespace _detail {
+ // Check that From* can be converted to To*, ignoring accessibility.
+ // This can be done using a C cast (see [expr.cast]/4).
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wold-style-cast")
+QT_WARNING_DISABLE_CLANG("-Wold-style-cast")
+ template <typename From, typename To>
+ using is_virtual_base_conversion_test = decltype(
+ (To *)std::declval<From *>()
+ );
+QT_WARNING_POP
+
+ template <typename Base, typename Derived, typename = void>
+ struct is_virtual_base_of : std::false_type {};
+
+ template <typename Base, typename Derived>
+ struct is_virtual_base_of<
+ Base, Derived,
+ std::enable_if_t<
+ std::conjunction_v<
+ // Base is a base class of Derived.
+ std::is_base_of<Base, Derived>,
+
+ // Check that Derived* can be converted to Base*, ignoring
+ // accessibility. If this is possible, then Base is
+ // an unambiguous base of Derived (=> virtual bases are always
+ // unambiguous).
+ qxp::is_detected<is_virtual_base_conversion_test, Derived, Base>,
+
+ // Check that Base* can _not_ be converted to Derived*,
+ // again ignoring accessibility. This seals the deal:
+ // if this conversion cannot happen, it means that Base is an
+ // ambiguous base and/or it is a virtual base.
+ // But we have already established that Base is an unambiguous
+ // base, hence: Base is a virtual base.
+ std::negation<
+ qxp::is_detected<is_virtual_base_conversion_test, Base, Derived>
+ >
+ >
+ >
+ > : std::true_type {};
+}
+
+template <typename Base, typename Derived>
+using is_virtual_base_of = _detail::is_virtual_base_of<std::remove_cv_t<Base>, std::remove_cv_t<Derived>>;
+
+template <typename Base, typename Derived>
+constexpr inline bool is_virtual_base_of_v = is_virtual_base_of<Base, Derived>::value;
+
+} // namespace qxp
+
+QT_END_NAMESPACE
+
+#endif // QXPTYPE_TRAITS_H
+
diff --git a/src/corelib/io/PSL-LICENSE.txt b/src/corelib/io/PSL-LICENSE.txt
deleted file mode 100644
index d0a1fa1482..0000000000
--- a/src/corelib/io/PSL-LICENSE.txt
+++ /dev/null
@@ -1,373 +0,0 @@
-Mozilla Public License Version 2.0
-==================================
-
-1. Definitions
---------------
-
-1.1. "Contributor"
- means each individual or legal entity that creates, contributes to
- the creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
- means the combination of the Contributions of others (if any) used
- by a Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
- means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
- means Source Code Form to which the initial Contributor has attached
- the notice in Exhibit A, the Executable Form of such Source Code
- Form, and Modifications of such Source Code Form, in each case
- including portions thereof.
-
-1.5. "Incompatible With Secondary Licenses"
- means
-
- (a) that the initial Contributor has attached the notice described
- in Exhibit B to the Covered Software; or
-
- (b) that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the
- terms of a Secondary License.
-
-1.6. "Executable Form"
- means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
- means a work that combines Covered Software with other material, in
- a separate file or files, that is not Covered Software.
-
-1.8. "License"
- means this document.
-
-1.9. "Licensable"
- means having the right to grant, to the maximum extent possible,
- whether at the time of the initial grant or subsequently, any and
- all of the rights conveyed by this License.
-
-1.10. "Modifications"
- means any of the following:
-
- (a) any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered
- Software; or
-
- (b) any new file in Source Code Form that contains any Covered
- Software.
-
-1.11. "Patent Claims" of a Contributor
- means any patent claim(s), including without limitation, method,
- process, and apparatus claims, in any patent Licensable by such
- Contributor that would be infringed, but for the grant of the
- License, by the making, using, selling, offering for sale, having
- made, import, or transfer of either its Contributions or its
- Contributor Version.
-
-1.12. "Secondary License"
- means either the GNU General Public License, Version 2.0, the GNU
- Lesser General Public License, Version 2.1, the GNU Affero General
- Public License, Version 3.0, or any later versions of those
- licenses.
-
-1.13. "Source Code Form"
- means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
- means an individual or a legal entity exercising rights under this
- License. For legal entities, "You" includes any entity that
- controls, is controlled by, or is under common control with You. For
- purposes of this definition, "control" means (a) the power, direct
- or indirect, to cause the direction or management of such entity,
- whether by contract or otherwise, or (b) ownership of more than
- fifty percent (50%) of the outstanding shares or beneficial
- ownership of such entity.
-
-2. License Grants and Conditions
---------------------------------
-
-2.1. Grants
-
-Each Contributor hereby grants You a world-wide, royalty-free,
-non-exclusive license:
-
-(a) under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications, or
- as part of a Larger Work; and
-
-(b) under Patent Claims of such Contributor to make, use, sell, offer
- for sale, have made, import, and otherwise transfer either its
- Contributions or its Contributor Version.
-
-2.2. Effective Date
-
-The licenses granted in Section 2.1 with respect to any Contribution
-become effective for each Contribution on the date the Contributor first
-distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
-The licenses granted in this Section 2 are the only rights granted under
-this License. No additional rights or licenses will be implied from the
-distribution or licensing of Covered Software under this License.
-Notwithstanding Section 2.1(b) above, no patent license is granted by a
-Contributor:
-
-(a) for any code that a Contributor has removed from Covered Software;
- or
-
-(b) for infringements caused by: (i) Your and any other third party's
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its Contributor
- Version); or
-
-(c) under Patent Claims infringed by Covered Software in the absence of
- its Contributions.
-
-This License does not grant any rights in the trademarks, service marks,
-or logos of any Contributor (except as may be necessary to comply with
-the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-No Contributor makes additional grants as a result of Your choice to
-distribute the Covered Software under a subsequent version of this
-License (see Section 10.2) or under the terms of a Secondary License (if
-permitted under the terms of Section 3.3).
-
-2.5. Representation
-
-Each Contributor represents that the Contributor believes its
-Contributions are its original creation(s) or it has sufficient rights
-to grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-This License is not intended to limit any rights You have under
-applicable copyright doctrines of fair use, fair dealing, or other
-equivalents.
-
-2.7. Conditions
-
-Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
-in Section 2.1.
-
-3. Responsibilities
--------------------
-
-3.1. Distribution of Source Form
-
-All distribution of Covered Software in Source Code Form, including any
-Modifications that You create or to which You contribute, must be under
-the terms of this License. You must inform recipients that the Source
-Code Form of the Covered Software is governed by the terms of this
-License, and how they can obtain a copy of this License. You may not
-attempt to alter or restrict the recipients' rights in the Source Code
-Form.
-
-3.2. Distribution of Executable Form
-
-If You distribute Covered Software in Executable Form then:
-
-(a) such Covered Software must also be made available in Source Code
- Form, as described in Section 3.1, and You must inform recipients of
- the Executable Form how they can obtain a copy of such Source Code
- Form by reasonable means in a timely manner, at a charge no more
- than the cost of distribution to the recipient; and
-
-(b) You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter
- the recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-You may create and distribute a Larger Work under terms of Your choice,
-provided that You also comply with the requirements of this License for
-the Covered Software. If the Larger Work is a combination of Covered
-Software with a work governed by one or more Secondary Licenses, and the
-Covered Software is not Incompatible With Secondary Licenses, this
-License permits You to additionally distribute such Covered Software
-under the terms of such Secondary License(s), so that the recipient of
-the Larger Work may, at their option, further distribute the Covered
-Software under the terms of either this License or such Secondary
-License(s).
-
-3.4. Notices
-
-You may not remove or alter the substance of any license notices
-(including copyright notices, patent notices, disclaimers of warranty,
-or limitations of liability) contained within the Source Code Form of
-the Covered Software, except that You may alter any license notices to
-the extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-You may choose to offer, and to charge a fee for, warranty, support,
-indemnity or liability obligations to one or more recipients of Covered
-Software. However, You may do so only on Your own behalf, and not on
-behalf of any Contributor. You must make it absolutely clear that any
-such warranty, support, indemnity, or liability obligation is offered by
-You alone, and You hereby agree to indemnify every Contributor for any
-liability incurred by such Contributor as a result of warranty, support,
-indemnity or liability terms You offer. You may include additional
-disclaimers of warranty and limitations of liability specific to any
-jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
----------------------------------------------------
-
-If it is impossible for You to comply with any of the terms of this
-License with respect to some or all of the Covered Software due to
-statute, judicial order, or regulation then You must: (a) comply with
-the terms of this License to the maximum extent possible; and (b)
-describe the limitations and the code they affect. Such description must
-be placed in a text file included with all distributions of the Covered
-Software under this License. Except to the extent prohibited by statute
-or regulation, such description must be sufficiently detailed for a
-recipient of ordinary skill to be able to understand it.
-
-5. Termination
---------------
-
-5.1. The rights granted under this License will terminate automatically
-if You fail to comply with any of its terms. However, if You become
-compliant, then the rights granted under this License from a particular
-Contributor are reinstated (a) provisionally, unless and until such
-Contributor explicitly and finally terminates Your grants, and (b) on an
-ongoing basis, if such Contributor fails to notify You of the
-non-compliance by some reasonable means prior to 60 days after You have
-come back into compliance. Moreover, Your grants from a particular
-Contributor are reinstated on an ongoing basis if such Contributor
-notifies You of the non-compliance by some reasonable means, this is the
-first time You have received notice of non-compliance with this License
-from such Contributor, and You become compliant prior to 30 days after
-Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-infringement claim (excluding declaratory judgment actions,
-counter-claims, and cross-claims) alleging that a Contributor Version
-directly or indirectly infringes any patent, then the rights granted to
-You by any and all Contributors for the Covered Software under Section
-2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all
-end user license agreements (excluding distributors and resellers) which
-have been validly granted by You or Your distributors under this License
-prior to termination shall survive termination.
-
-************************************************************************
-* *
-* 6. Disclaimer of Warranty *
-* ------------------------- *
-* *
-* Covered Software is provided under this License on an "as is" *
-* basis, without warranty of any kind, either expressed, implied, or *
-* statutory, including, without limitation, warranties that the *
-* Covered Software is free of defects, merchantable, fit for a *
-* particular purpose or non-infringing. The entire risk as to the *
-* quality and performance of the Covered Software is with You. *
-* Should any Covered Software prove defective in any respect, You *
-* (not any Contributor) assume the cost of any necessary servicing, *
-* repair, or correction. This disclaimer of warranty constitutes an *
-* essential part of this License. No use of any Covered Software is *
-* authorized under this License except under this disclaimer. *
-* *
-************************************************************************
-
-************************************************************************
-* *
-* 7. Limitation of Liability *
-* -------------------------- *
-* *
-* Under no circumstances and under no legal theory, whether tort *
-* (including negligence), contract, or otherwise, shall any *
-* Contributor, or anyone who distributes Covered Software as *
-* permitted above, be liable to You for any direct, indirect, *
-* special, incidental, or consequential damages of any character *
-* including, without limitation, damages for lost profits, loss of *
-* goodwill, work stoppage, computer failure or malfunction, or any *
-* and all other commercial damages or losses, even if such party *
-* shall have been informed of the possibility of such damages. This *
-* limitation of liability shall not apply to liability for death or *
-* personal injury resulting from such party's negligence to the *
-* extent applicable law prohibits such limitation. Some *
-* jurisdictions do not allow the exclusion or limitation of *
-* incidental or consequential damages, so this exclusion and *
-* limitation may not apply to You. *
-* *
-************************************************************************
-
-8. Litigation
--------------
-
-Any litigation relating to this License may be brought only in the
-courts of a jurisdiction where the defendant maintains its principal
-place of business and such litigation shall be governed by laws of that
-jurisdiction, without reference to its conflict-of-law provisions.
-Nothing in this Section shall prevent a party's ability to bring
-cross-claims or counter-claims.
-
-9. Miscellaneous
-----------------
-
-This License represents the complete agreement concerning the subject
-matter hereof. If any provision of this License is held to be
-unenforceable, such provision shall be reformed only to the extent
-necessary to make it enforceable. Any law or regulation which provides
-that the language of a contract shall be construed against the drafter
-shall not be used to construe this License against a Contributor.
-
-10. Versions of the License
----------------------------
-
-10.1. New Versions
-
-Mozilla Foundation is the license steward. Except as provided in Section
-10.3, no one other than the license steward has the right to modify or
-publish new versions of this License. Each version will be given a
-distinguishing version number.
-
-10.2. Effect of New Versions
-
-You may distribute the Covered Software under the terms of the version
-of the License under which You originally received the Covered Software,
-or under the terms of any subsequent version published by the license
-steward.
-
-10.3. Modified Versions
-
-If you create software not governed by this License, and you want to
-create a new license for such software, you may create and use a
-modified version of this License if you rename the license and remove
-any references to the name of the license steward (except to note that
-such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
-Licenses
-
-If You choose to distribute Source Code Form that is Incompatible With
-Secondary Licenses under the terms of this version of the License, the
-notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
--------------------------------------------
-
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular
-file, then You may include the notice in a location (such as a LICENSE
-file in a relevant directory) where a recipient would be likely to look
-for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
----------------------------------------------------------
-
- This Source Code Form is "Incompatible With Secondary Licenses", as
- defined by the Mozilla Public License, v. 2.0.
diff --git a/src/corelib/io/forkfd_qt.c b/src/corelib/io/forkfd_qt.c
new file mode 100644
index 0000000000..7107b2c6a0
--- /dev/null
+++ b/src/corelib/io/forkfd_qt.c
@@ -0,0 +1,15 @@
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <QtCore/qglobal.h>
+
+#define FORKFD_NO_SPAWNFD
+#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
+# define NDEBUG
+#endif
+
+#include <forkfd.h>
+#include "../../3rdparty/forkfd/forkfd.c"
diff --git a/src/corelib/io/forkfd_qt.cpp b/src/corelib/io/forkfd_qt.cpp
deleted file mode 100644
index cf44874153..0000000000
--- a/src/corelib/io/forkfd_qt.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-
-#define FORKFD_NO_SPAWNFD
-#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
-# define NDEBUG
-#endif
-
-#include <forkfd.h>
-#include "../../3rdparty/forkfd/forkfd.c"
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
deleted file mode 100644
index c062d9948b..0000000000
--- a/src/corelib/io/io.pri
+++ /dev/null
@@ -1,196 +0,0 @@
-# Qt core io module
-
-HEADERS += \
- io/qabstractfileengine_p.h \
- io/qbuffer.h \
- io/qdataurl_p.h \
- io/qdebug.h \
- io/qdebug_p.h \
- io/qdir.h \
- io/qdir_p.h \
- io/qdiriterator.h \
- io/qfile.h \
- io/qfiledevice.h \
- io/qfiledevice_p.h \
- io/qfileinfo.h \
- io/qfileinfo_p.h \
- io/qipaddress_p.h \
- io/qiodevice.h \
- io/qiodevice_p.h \
- io/qlockfile.h \
- io/qlockfile_p.h \
- io/qnoncontiguousbytedevice_p.h \
- io/qtemporarydir.h \
- io/qtemporaryfile.h \
- io/qtemporaryfile_p.h \
- io/qresource_p.h \
- io/qresource_iterator_p.h \
- io/qsavefile.h \
- io/qstandardpaths.h \
- io/qstorageinfo.h \
- io/qstorageinfo_p.h \
- io/qurl.h \
- io/qurl_p.h \
- io/qurlquery.h \
- io/qfsfileengine_p.h \
- io/qfsfileengine_iterator_p.h \
- io/qfilesystementry_p.h \
- io/qfilesystemengine_p.h \
- io/qfilesystemmetadata_p.h \
- io/qfilesystemiterator_p.h \
- io/qfileselector.h \
- io/qfileselector_p.h \
- io/qloggingcategory.h \
- io/qloggingregistry_p.h
-
-SOURCES += \
- io/qabstractfileengine.cpp \
- io/qbuffer.cpp \
- io/qdataurl.cpp \
- io/qdebug.cpp \
- io/qdir.cpp \
- io/qdiriterator.cpp \
- io/qfile.cpp \
- io/qfiledevice.cpp \
- io/qfileinfo.cpp \
- io/qipaddress.cpp \
- io/qiodevice.cpp \
- io/qlockfile.cpp \
- io/qnoncontiguousbytedevice.cpp \
- io/qstorageinfo.cpp \
- io/qtemporarydir.cpp \
- io/qtemporaryfile.cpp \
- io/qresource.cpp \
- io/qresource_iterator.cpp \
- io/qsavefile.cpp \
- io/qstandardpaths.cpp \
- io/qurl.cpp \
- io/qurlidna.cpp \
- io/qurlquery.cpp \
- io/qurlrecode.cpp \
- io/qfsfileengine.cpp \
- io/qfsfileengine_iterator.cpp \
- io/qfilesystementry.cpp \
- io/qfilesystemengine.cpp \
- io/qfileselector.cpp \
- io/qloggingcategory.cpp \
- io/qloggingregistry.cpp
-
-qtConfig(zstd): QMAKE_USE_PRIVATE += zstd
-
-qtConfig(filesystemwatcher) {
- HEADERS += \
- io/qfilesystemwatcher.h \
- io/qfilesystemwatcher_p.h \
- io/qfilesystemwatcher_polling_p.h
- SOURCES += \
- io/qfilesystemwatcher.cpp \
- io/qfilesystemwatcher_polling.cpp
-
- win32 {
- SOURCES += io/qfilesystemwatcher_win.cpp
- HEADERS += io/qfilesystemwatcher_win_p.h
- } else:macos {
- OBJECTIVE_SOURCES += io/qfilesystemwatcher_fsevents.mm
- HEADERS += io/qfilesystemwatcher_fsevents_p.h
- } else:qtConfig(inotify) {
- SOURCES += io/qfilesystemwatcher_inotify.cpp
- HEADERS += io/qfilesystemwatcher_inotify_p.h
- } else {
- freebsd|darwin|openbsd|netbsd {
- SOURCES += io/qfilesystemwatcher_kqueue.cpp
- HEADERS += io/qfilesystemwatcher_kqueue_p.h
- }
- }
-}
-
-qtConfig(processenvironment) {
- SOURCES += \
- io/qprocess.cpp
- HEADERS += \
- io/qprocess.h \
- io/qprocess_p.h
-
- win32: \
- SOURCES += io/qprocess_win.cpp
- else: unix: \
- SOURCES += io/qprocess_unix.cpp
-}
-
-qtConfig(settings) {
- SOURCES += \
- io/qsettings.cpp
- HEADERS += \
- io/qsettings.h \
- io/qsettings_p.h
-
- win32 {
- SOURCES += io/qsettings_win.cpp
- } else: darwin:!nacl {
- SOURCES += io/qsettings_mac.cpp
- }
- wasm : SOURCES += io/qsettings_wasm.cpp
-}
-
-win32 {
- SOURCES += io/qfsfileengine_win.cpp
- SOURCES += io/qlockfile_win.cpp
- SOURCES += io/qfilesystemengine_win.cpp
-
- qtConfig(filesystemiterator) {
- SOURCES += io/qfilesystemiterator_win.cpp
- }
-
- HEADERS += \
- io/qwindowspipereader_p.h \
- io/qwindowspipewriter_p.h
-
- SOURCES += \
- io/qstandardpaths_win.cpp \
- io/qstorageinfo_win.cpp \
- io/qwindowspipereader.cpp \
- io/qwindowspipewriter.cpp
-
- LIBS += -lmpr -luserenv
- QMAKE_USE_PRIVATE += netapi32
-} else:unix {
- SOURCES += \
- io/qfsfileengine_unix.cpp \
- io/qfilesystemengine_unix.cpp \
- io/qlockfile_unix.cpp \
- io/qfilesystemiterator_unix.cpp
-
- qtConfig(process) {
- SOURCES += io/forkfd_qt.cpp
- HEADERS += \
- ../3rdparty/forkfd/forkfd.h
- INCLUDEPATH += ../3rdparty/forkfd
- }
- mac {
- SOURCES += io/qstorageinfo_mac.cpp
- qtConfig(processenvironment): \
- OBJECTIVE_SOURCES += io/qprocess_darwin.mm
- OBJECTIVE_SOURCES += \
- io/qstandardpaths_mac.mm \
- io/qfilesystemengine_mac.mm
- osx {
- LIBS += -framework DiskArbitration -framework IOKit
- } else {
- LIBS += -framework MobileCoreServices
- }
- } else:android:!android-embedded {
- SOURCES += \
- io/qstandardpaths_android.cpp \
- io/qstorageinfo_unix.cpp
- } else:haiku {
- SOURCES += \
- io/qstandardpaths_haiku.cpp \
- io/qstorageinfo_unix.cpp
- LIBS += -lbe
- } else {
- SOURCES += \
- io/qstandardpaths_unix.cpp \
- io/qstorageinfo_unix.cpp
- }
-}
-
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 070139b608..ea5ce13b5e 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qabstractfileengine_p.h"
#include "private/qfsfileengine_p.h"
@@ -46,7 +10,7 @@
#include "qreadwritelock.h"
#include "qvariant.h"
// built-in handlers
-#include "qdiriterator.h"
+#include "qdirlisting.h"
#include "qstringbuilder.h"
#include <QtCore/private/qfilesystementry_p.h>
@@ -55,6 +19,19 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+static QString appendSlashIfNeeded(const QString &path)
+{
+ if (!path.isEmpty() && !path.endsWith(u'/')
+#ifdef Q_OS_ANDROID
+ && !path.startsWith("content:/"_L1)
+#endif
+ )
+ return QString{path + u'/'};
+ return path;
+}
+
/*!
\class QAbstractFileEngineHandler
\inmodule QtCore
@@ -101,17 +78,20 @@ QT_BEGIN_NAMESPACE
\sa QAbstractFileEngine, QAbstractFileEngine::create()
*/
-static bool qt_file_engine_handlers_in_use = false;
+Q_CONSTINIT static QBasicAtomicInt qt_file_engine_handlers_in_use = Q_BASIC_ATOMIC_INITIALIZER(false);
/*
All application-wide handlers are stored in this list. The mutex must be
acquired to ensure thread safety.
*/
-Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, fileEngineHandlerMutex, (QReadWriteLock::Recursive))
-static bool qt_abstractfileenginehandlerlist_shutDown = false;
+Q_GLOBAL_STATIC(QReadWriteLock, fileEngineHandlerMutex, QReadWriteLock::Recursive)
+Q_CONSTINIT static bool qt_abstractfileenginehandlerlist_shutDown = false;
class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *>
{
+ Q_DISABLE_COPY_MOVE(QAbstractFileEngineHandlerList)
public:
+ QAbstractFileEngineHandlerList() = default;
+
~QAbstractFileEngineHandlerList()
{
QWriteLocker locker(fileEngineHandlerMutex());
@@ -132,7 +112,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
QAbstractFileEngineHandler::QAbstractFileEngineHandler()
{
QWriteLocker locker(fileEngineHandlerMutex());
- qt_file_engine_handlers_in_use = true;
+ qt_file_engine_handlers_in_use.storeRelaxed(true);
fileEngineHandlers()->prepend(this);
}
@@ -148,7 +128,7 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
handlers->removeOne(this);
if (handlers->isEmpty())
- qt_file_engine_handlers_in_use = false;
+ qt_file_engine_handlers_in_use.storeRelaxed(false);
}
}
@@ -157,29 +137,27 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
Handles calls to custom file engine handlers.
*/
-QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
+std::unique_ptr<QAbstractFileEngine> qt_custom_file_engine_handler_create(const QString &path)
{
- QAbstractFileEngine *engine = nullptr;
-
- if (qt_file_engine_handlers_in_use) {
+ if (qt_file_engine_handlers_in_use.loadRelaxed()) {
QReadLocker locker(fileEngineHandlerMutex());
// check for registered handlers that can load the file
- QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
- for (int i = 0; i < handlers->size(); i++) {
- if ((engine = handlers->at(i)->create(path)))
- break;
+ for (QAbstractFileEngineHandler *handler : std::as_const(*fileEngineHandlers())) {
+ if (auto engine = handler->create(path))
+ return engine;
}
}
- return engine;
+ return nullptr;
}
/*!
- \fn QAbstractFileEngine *QAbstractFileEngineHandler::create(const QString &fileName) const
+ \fn std::unique_ptr<QAbstractFileEngine> QAbstractFileEngineHandler::create(const QString &fileName) const
- Creates a file engine for file \a fileName. Returns 0 if this
- file handler cannot handle \a fileName.
+ If this file handler can handle \a fileName, this method creates a file
+ engine and returns it wrapped in a std::unique_ptr; otherwise returns
+ nullptr.
Example:
@@ -201,16 +179,15 @@ QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
\sa QAbstractFileEngineHandler
*/
-QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
+std::unique_ptr<QAbstractFileEngine> QAbstractFileEngine::create(const QString &fileName)
{
QFileSystemEntry entry(fileName);
QFileSystemMetaData metaData;
- QAbstractFileEngine *engine = QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, metaData);
+ auto engine = QFileSystemEngine::createLegacyEngine(entry, metaData);
#ifndef QT_NO_FSFILEENGINE
- if (!engine)
- // fall back to regular file engine
- return new QFSFileEngine(entry.filePath());
+ if (!engine) // fall back to regular file engine
+ engine = std::make_unique<QFSFileEngine>(entry.filePath());
#endif
return engine;
@@ -262,11 +239,15 @@ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
the base name).
\value AbsolutePathName The absolute path to the file (excluding
the base name).
- \value LinkName The full file name of the file that this file is a
+ \value AbsoluteLinkTarget The full file name of the file that this file is a
+ link to. (This will be empty if this file is not a link.)
+ \value RawLinkPath The raw link path of the file that this file is a
link to. (This will be empty if this file is not a link.)
- \value CanonicalName Often very similar to LinkName. Will return the true path to the file.
+ \value CanonicalName Often very similar to AbsoluteLinkTarget. Will return the true path to the file.
\value CanonicalPathName Same as CanonicalName, excluding the base name.
\value BundleName Returns the name of the bundle implies BundleType is set.
+ \value JunctionName The full name of the directory that this NTFS junction
+ is linked to. (This will be empty if this file is not an NTFS junction.)
\omitvalue NFileNames
@@ -324,20 +305,6 @@ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
*/
/*!
- \enum QAbstractFileEngine::FileTime
-
- These are used by the fileTime() function.
-
- \value BirthTime When the file was born (created).
- \value MetadataChangeTime When the file's metadata was last changed.
- \value ModificationTime When the file was most recently modified.
- \value AccessTime When the file was most recently accessed (e.g.
- read or written to).
-
- \sa setFileName()
-*/
-
-/*!
\enum QAbstractFileEngine::FileOwner
\value OwnerUser The user who owns the file.
@@ -381,10 +348,16 @@ QAbstractFileEngine::~QAbstractFileEngine()
The \a mode is an OR combination of QIODevice::OpenMode and
QIODevice::HandlingMode values.
+
+ If the file is created as a result of this call, its permissions are
+ set according to \a permissision. Null value means an implementation-
+ specific default.
*/
-bool QAbstractFileEngine::open(QIODevice::OpenMode openMode)
+bool QAbstractFileEngine::open(QIODevice::OpenMode openMode,
+ std::optional<QFile::Permissions> permissions)
{
Q_UNUSED(openMode);
+ Q_UNUSED(permissions);
return false;
}
@@ -461,7 +434,7 @@ bool QAbstractFileEngine::seek(qint64 pos)
Returns \c true if the file is a sequential access device; returns
false if the file is a direct access device.
- Operations involving size() and seek(int) are not valid on
+ Operations involving size() and seek(qint64) are not valid on
sequential devices.
*/
bool QAbstractFileEngine::isSequential() const
@@ -473,8 +446,6 @@ bool QAbstractFileEngine::isSequential() const
Requests that the file is deleted from the file system. If the
operation succeeds return true; otherwise return false.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName(), rmdir()
*/
bool QAbstractFileEngine::remove()
@@ -497,8 +468,6 @@ bool QAbstractFileEngine::copy(const QString &newName)
system. If the operation succeeds return true; otherwise return
false.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName()
*/
bool QAbstractFileEngine::rename(const QString &newName)
@@ -515,8 +484,6 @@ bool QAbstractFileEngine::rename(const QString &newName)
If the operation succeeds, returns \c true; otherwise returns
false.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName()
*/
bool QAbstractFileEngine::renameOverwrite(const QString &newName)
@@ -538,21 +505,24 @@ bool QAbstractFileEngine::link(const QString &newName)
}
/*!
- Requests that the directory \a dirName be created. If
- \a createParentDirectories is true, then any sub-directories in \a dirName
+ Requests that the directory \a dirName be created with the specified \a permissions.
+ If \a createParentDirectories is true, then any sub-directories in \a dirName
that don't exist must be created. If \a createParentDirectories is false then
any sub-directories in \a dirName must already exist for the function to
succeed. If the operation succeeds return true; otherwise return
false.
- This virtual function must be reimplemented by all subclasses.
+ If \a permissions is null then implementation-specific default permissions are
+ used.
\sa setFileName(), rmdir(), isRelativePath()
*/
-bool QAbstractFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const
+bool QAbstractFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
+ std::optional<QFile::Permissions> permissions) const
{
Q_UNUSED(dirName);
Q_UNUSED(createParentDirectories);
+ Q_UNUSED(permissions);
return false;
}
@@ -565,8 +535,6 @@ bool QAbstractFileEngine::mkdir(const QString &dirName, bool createParentDirecto
using this function if it is non-empty. If the operation succeeds
return true; otherwise return false.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName(), remove(), mkdir(), isRelativePath()
*/
bool QAbstractFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
@@ -582,8 +550,6 @@ bool QAbstractFileEngine::rmdir(const QString &dirName, bool recurseParentDirect
simply truncated. If the operations succceeds return true; otherwise
return false;
- This virtual function must be reimplemented by all subclasses.
-
\sa size()
*/
bool QAbstractFileEngine::setSize(qint64 size)
@@ -595,8 +561,6 @@ bool QAbstractFileEngine::setSize(qint64 size)
/*!
Should return true if the underlying file system is case-sensitive;
otherwise return false.
-
- This virtual function must be reimplemented by all subclasses.
*/
bool QAbstractFileEngine::caseSensitive() const
{
@@ -607,8 +571,6 @@ bool QAbstractFileEngine::caseSensitive() const
Return true if the file referred to by this file engine has a
relative path; otherwise return false.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName()
*/
bool QAbstractFileEngine::isRelativePath() const
@@ -625,19 +587,20 @@ bool QAbstractFileEngine::isRelativePath() const
rather than a directory, or if the directory is unreadable or does
not exist or if nothing matches the specifications.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName()
*/
QStringList QAbstractFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
{
QStringList ret;
- QDirIterator it(fileName(), filterNames, filters);
- while (it.hasNext()) {
- it.next();
- ret << it.fileName();
- }
+#ifdef QT_BOOTSTRAPPED
+ Q_UNUSED(filters);
+ Q_UNUSED(filterNames);
+ Q_UNREACHABLE_RETURN(ret);
+#else
+ for (const auto &dirEntry : QDirListing(fileName(), filterNames, filters))
+ ret.emplace_back(dirEntry.fileName());
return ret;
+#endif
}
/*!
@@ -651,8 +614,6 @@ QStringList QAbstractFileEngine::entryList(QDir::Filters filters, const QStringL
ignore any members not mentioned in \a type, thus avoiding some
potentially expensive lookups or system calls.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName()
*/
QAbstractFileEngine::FileFlags QAbstractFileEngine::fileFlags(FileFlags type) const
@@ -668,8 +629,6 @@ QAbstractFileEngine::FileFlags QAbstractFileEngine::fileFlags(FileFlags type) co
honored. If the operations succceeds return true; otherwise return
false;
- This virtual function must be reimplemented by all subclasses.
-
\sa size()
*/
bool QAbstractFileEngine::setPermissions(uint perms)
@@ -697,8 +656,6 @@ QByteArray QAbstractFileEngine::id() const
file name set in setFileName() when an unhandled format is
requested.
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName(), FileName
*/
QString QAbstractFileEngine::fileName(FileName file) const
@@ -712,8 +669,6 @@ QString QAbstractFileEngine::fileName(FileName file) const
the file. If \a owner is \c OwnerGroup return the ID of the group
that own the file. If you can't determine the owner return -2.
- This virtual function must be reimplemented by all subclasses.
-
\sa owner(), setFileName(), FileOwner
*/
uint QAbstractFileEngine::ownerId(FileOwner owner) const
@@ -728,8 +683,6 @@ uint QAbstractFileEngine::ownerId(FileOwner owner) const
that own the file. If you can't determine the owner return
QString().
- This virtual function must be reimplemented by all subclasses.
-
\sa ownerId(), setFileName(), FileOwner
*/
QString QAbstractFileEngine::owner(FileOwner owner) const
@@ -745,11 +698,9 @@ QString QAbstractFileEngine::owner(FileOwner owner) const
Sets the file \a time to \a newDate, returning true if successful;
otherwise returns false.
- This virtual function must be reimplemented by all subclasses.
-
\sa fileTime()
*/
-bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
+bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
{
Q_UNUSED(newDate);
Q_UNUSED(time);
@@ -764,11 +715,9 @@ bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
most recently accessed (e.g. read or written). If the time cannot be
determined return QDateTime() (an invalid date time).
- This virtual function must be reimplemented by all subclasses.
-
\sa setFileName(), QDateTime, QDateTime::isValid(), FileTime
*/
-QDateTime QAbstractFileEngine::fileTime(FileTime time) const
+QDateTime QAbstractFileEngine::fileTime(QFile::FileTime time) const
{
Q_UNUSED(time);
return QDateTime();
@@ -778,8 +727,6 @@ QDateTime QAbstractFileEngine::fileTime(FileTime time) const
Sets the file engine's file name to \a file. This file name is the
file that the rest of the virtual functions will operate on.
- This virtual function must be reimplemented by all subclasses.
-
\sa rename()
*/
void QAbstractFileEngine::setFileName(const QString &file)
@@ -832,10 +779,7 @@ bool QAbstractFileEngine::atEnd() const
uchar *QAbstractFileEngine::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
{
- MapExtensionOption option;
- option.offset = offset;
- option.size = size;
- option.flags = flags;
+ const MapExtensionOption option(offset, size, flags);
MapExtensionReturn r;
if (!extension(MapExtension, &option, &r))
return nullptr;
@@ -856,8 +800,7 @@ uchar *QAbstractFileEngine::map(qint64 offset, qint64 size, QFile::MemoryMapFlag
*/
bool QAbstractFileEngine::unmap(uchar *address)
{
- UnMapExtensionOption options;
- options.address = address;
+ const UnMapExtensionOption options(address);
return extension(UnMapExtension, &options);
}
@@ -884,11 +827,12 @@ bool QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
\internal
If all you want is to iterate over entries in a directory, see
- QDirIterator instead. This class is only for custom file engine authors.
+ QDirListing instead. This class is useful only for custom file engine
+ authors.
QAbstractFileEngineIterator is a unidirectional single-use virtual
- iterator that plugs into QDirIterator, providing transparent proxy
- iteration for custom file engines.
+ iterator that plugs into QDirListing, providing transparent proxy
+ iteration for custom file engines (for example, QResourceFileEngine).
You can subclass QAbstractFileEngineIterator to provide an iterator when
writing your own file engine. To plug the iterator into your file system,
@@ -909,10 +853,11 @@ bool QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
You can call dirName() to get the directory name, nameFilters() to get a
stringlist of name filters, and filters() to get the entry filters.
- The pure virtual function hasNext() returns \c true if the current directory
- has at least one more entry (i.e., the directory name is valid and
- accessible, and we have not reached the end of the entry list), and false
- otherwise. Reimplement next() to seek to the next entry.
+ The pure virtual function advance(), as its name implies, advances the
+ iterator to the next entry in the current directory; if the operation
+ was successful this method returns \c true, otherwise it returns \c
+ false. You have to reimplement this function in your sub-class to work
+ with your file engine implementation.
The pure virtual function currentFileName() returns the name of the
current entry without advancing the iterator. The currentFilePath()
@@ -927,15 +872,7 @@ bool QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
Note: QAbstractFileEngineIterator does not deal with QDir::IteratorFlags;
it simply returns entries for a single directory.
- \sa QDirIterator
-*/
-
-/*!
- \enum QAbstractFileEngineIterator::EntryInfoType
- \internal
-
- This enum describes the different types of information that can be
- requested through the QAbstractFileEngineIterator::entryInfo() function.
+ \sa QDirListing
*/
/*!
@@ -945,56 +882,45 @@ bool QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
Synonym for QAbstractFileEngineIterator.
*/
-class QAbstractFileEngineIteratorPrivate
-{
-public:
- QString path;
- QDir::Filters filters;
- QStringList nameFilters;
- QFileInfo fileInfo;
-};
+/*!
+ \typedef QAbstractFileEngine::IteratorUniquePtr
+ \since 6.8
+
+ Synonym for std::unique_ptr<Iterator> (that is a
+ std::unique_ptr<QAbstractFileEngineIterator>).
+*/
/*!
Constructs a QAbstractFileEngineIterator, using the entry filters \a
filters, and wildcard name filters \a nameFilters.
*/
-QAbstractFileEngineIterator::QAbstractFileEngineIterator(QDir::Filters filters,
+QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path, QDir::Filters filters,
const QStringList &nameFilters)
- : d(new QAbstractFileEngineIteratorPrivate)
+ : m_filters(filters),
+ m_nameFilters(nameFilters),
+ m_path(appendSlashIfNeeded(path))
{
- d->nameFilters = nameFilters;
- d->filters = filters;
}
/*!
Destroys the QAbstractFileEngineIterator.
- \sa QDirIterator
+ \sa QDirListing
*/
QAbstractFileEngineIterator::~QAbstractFileEngineIterator()
{
}
/*!
- Returns the path for this iterator. QDirIterator is responsible for
- assigning this path; it cannot change during the iterator's lifetime.
+
+ Returns the path for this iterator. The path is set by beginEntryList().
+ The path should't be changed once iteration begins.
\sa nameFilters(), filters()
*/
QString QAbstractFileEngineIterator::path() const
{
- return d->path;
-}
-
-/*!
- \internal
-
- Sets the iterator path to \a path. This function is called from within
- QDirIterator.
-*/
-void QAbstractFileEngineIterator::setPath(const QString &path)
-{
- d->path = path;
+ return m_path;
}
/*!
@@ -1004,7 +930,7 @@ void QAbstractFileEngineIterator::setPath(const QString &path)
*/
QStringList QAbstractFileEngineIterator::nameFilters() const
{
- return d->nameFilters;
+ return m_nameFilters;
}
/*!
@@ -1014,7 +940,7 @@ QStringList QAbstractFileEngineIterator::nameFilters() const
*/
QDir::Filters QAbstractFileEngineIterator::filters() const
{
- return d->filters;
+ return m_filters;
}
/*!
@@ -1035,15 +961,10 @@ QDir::Filters QAbstractFileEngineIterator::filters() const
QString QAbstractFileEngineIterator::currentFilePath() const
{
QString name = currentFileName();
- if (!name.isNull()) {
- QString tmp = path();
- if (!tmp.isEmpty()) {
- if (!tmp.endsWith(QLatin1Char('/')))
- tmp.append(QLatin1Char('/'));
- name.prepend(tmp);
- }
- }
- return name;
+ if (name.isNull())
+ return name;
+
+ return path() + name;
}
/*!
@@ -1058,75 +979,42 @@ QString QAbstractFileEngineIterator::currentFilePath() const
QFileInfo QAbstractFileEngineIterator::currentFileInfo() const
{
QString path = currentFilePath();
- if (d->fileInfo.filePath() != path)
- d->fileInfo.setFile(path);
+ if (m_fileInfo.filePath() != path)
+ m_fileInfo.setFile(path);
// return a shallow copy
- return d->fileInfo;
+ return m_fileInfo;
}
/*!
- \internal
-
- Returns the entry info \a type for this iterator's current directory entry
- as a QVariant. If \a type is undefined for this entry, a null QVariant is
- returned.
-
- \sa QAbstractFileEngine::beginEntryList(), QDir::beginEntryList()
-*/
-QVariant QAbstractFileEngineIterator::entryInfo(EntryInfoType type) const
-{
- Q_UNUSED(type)
- return QVariant();
-}
-
-/*!
- \fn virtual QString QAbstractFileEngineIterator::next() = 0
+ \fn virtual bool QAbstractFileEngineIterator::advance() = 0
This pure virtual function advances the iterator to the next directory
- entry, and returns the file path to the current entry.
+ entry; if the operation was successful this method returns \c true,
+ otherwise it returs \c false.
This function can optionally make use of nameFilters() and filters() to
optimize its performance.
Reimplement this function in a subclass to advance the iterator.
-
- \sa QDirIterator::next()
*/
/*!
- \fn virtual bool QAbstractFileEngineIterator::hasNext() const = 0
+ Returns a QAbstractFileEngine::IteratorUniquePtr, that can be used
+ to iterate over the entries in \a path, using \a filters for entry
+ filtering and \a filterNames for name filtering. This function is called
+ by QDirListing to initiate directory iteration.
- This pure virtual function returns \c true if there is at least one more
- entry in the current directory (i.e., the iterator path is valid and
- accessible, and the iterator has not reached the end of the entry list).
-
- \sa QDirIterator::hasNext()
+ \sa QDirListing
*/
-
-/*!
- Returns an instance of a QAbstractFileEngineIterator using \a filters for
- entry filtering and \a filterNames for name filtering. This function is
- called by QDirIterator to initiate directory iteration.
-
- QDirIterator takes ownership of the returned instance, and deletes it when
- it's done.
-
- \sa QDirIterator
-*/
-QAbstractFileEngine::Iterator *QAbstractFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
+QAbstractFileEngine::IteratorUniquePtr
+QAbstractFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames)
{
+ Q_UNUSED(path);
Q_UNUSED(filters);
Q_UNUSED(filterNames);
- return nullptr;
-}
-
-/*!
- \internal
-*/
-QAbstractFileEngine::Iterator *QAbstractFileEngine::endEntryList()
-{
- return nullptr;
+ return {};
}
/*!
@@ -1199,7 +1087,7 @@ qint64 QAbstractFileEngine::readLine(char *data, qint64 maxlen)
QIODevice can provide a faster implementation by making use of its
internal buffer. For engines that already provide a fast readLine()
implementation, returning false for this extension can avoid
- unnnecessary double-buffering in QIODevice.
+ unnecessary double-buffering in QIODevice.
\value MapExtension Whether the file engine provides the ability to map
a file to memory.
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index c88b66c7ce..b2e0b248da 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEENGINE_P_H
#define QABSTRACTFILEENGINE_P_H
@@ -55,6 +19,9 @@
#include "QtCore/qfile.h"
#include "QtCore/qdir.h"
+#include <memory>
+#include <optional>
+
#ifdef open
#error qabstractfileengine_p.h must be included before any header file that defines open
#endif
@@ -102,26 +69,24 @@ public:
PathName,
AbsoluteName,
AbsolutePathName,
- LinkName,
+ AbsoluteLinkTarget,
CanonicalName,
CanonicalPathName,
BundleName,
- NFileNames = 9
+ JunctionName,
+ RawLinkPath,
+ NFileNames // Must be last.
};
enum FileOwner {
OwnerUser,
OwnerGroup
};
- enum FileTime {
- AccessTime,
- BirthTime,
- MetadataChangeTime,
- ModificationTime
- };
+
virtual ~QAbstractFileEngine();
- virtual bool open(QIODevice::OpenMode openMode);
+ virtual bool open(QIODevice::OpenMode openMode,
+ std::optional<QFile::Permissions> permissions = std::nullopt);
virtual bool close();
virtual bool flush();
virtual bool syncToDisk();
@@ -134,7 +99,8 @@ public:
virtual bool rename(const QString &newName);
virtual bool renameOverwrite(const QString &newName);
virtual bool link(const QString &newName);
- virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
+ virtual bool mkdir(const QString &dirName, bool createParentDirectories,
+ std::optional<QFile::Permissions> permissions = std::nullopt) const;
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
virtual bool setSize(qint64 size);
virtual bool caseSensitive() const;
@@ -146,8 +112,8 @@ public:
virtual QString fileName(FileName file=DefaultName) const;
virtual uint ownerId(FileOwner) const;
virtual QString owner(FileOwner) const;
- virtual bool setFileTime(const QDateTime &newDate, FileTime time);
- virtual QDateTime fileTime(FileTime time) const;
+ virtual bool setFileTime(const QDateTime &newDate, QFile::FileTime time);
+ virtual QDateTime fileTime(QFile::FileTime time) const;
virtual void setFileName(const QString &file);
virtual int handle() const;
virtual bool cloneTo(QAbstractFileEngine *target);
@@ -156,8 +122,11 @@ public:
bool unmap(uchar *ptr);
typedef QAbstractFileEngineIterator Iterator;
- virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
- virtual Iterator *endEntryList();
+ using IteratorUniquePtr = std::unique_ptr<Iterator>;
+
+ virtual IteratorUniquePtr
+ beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames);
+ virtual IteratorUniquePtr endEntryList() { return {}; }
virtual qint64 read(char *data, qint64 maxlen);
virtual qint64 readLine(char *data, qint64 maxlen);
@@ -178,26 +147,33 @@ public:
{};
class MapExtensionOption : public ExtensionOption {
+ Q_DISABLE_COPY_MOVE(MapExtensionOption)
public:
qint64 offset;
qint64 size;
QFile::MemoryMapFlags flags;
+ constexpr MapExtensionOption(qint64 off, qint64 sz, QFile::MemoryMapFlags f)
+ : offset(off), size(sz), flags(f) {}
};
class MapExtensionReturn : public ExtensionReturn {
+ Q_DISABLE_COPY_MOVE(MapExtensionReturn)
public:
- uchar *address;
+ MapExtensionReturn() = default;
+ uchar *address = nullptr;
};
class UnMapExtensionOption : public ExtensionOption {
+ Q_DISABLE_COPY_MOVE(UnMapExtensionOption)
public:
- uchar *address;
+ uchar *address = nullptr;
+ constexpr UnMapExtensionOption(uchar *p) : address(p) {}
};
virtual bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr);
virtual bool supportsExtension(Extension extension) const;
// Factory
- static QAbstractFileEngine *create(const QString &fileName);
+ static std::unique_ptr<QAbstractFileEngine> create(const QString &fileName);
protected:
void setError(QFile::FileError error, const QString &str);
@@ -215,21 +191,21 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFileEngine::FileFlags)
class Q_CORE_EXPORT QAbstractFileEngineHandler
{
+ Q_DISABLE_COPY_MOVE(QAbstractFileEngineHandler)
public:
QAbstractFileEngineHandler();
virtual ~QAbstractFileEngineHandler();
- virtual QAbstractFileEngine *create(const QString &fileName) const = 0;
+ virtual std::unique_ptr<QAbstractFileEngine> create(const QString &fileName) const = 0;
};
-class QAbstractFileEngineIteratorPrivate;
class Q_CORE_EXPORT QAbstractFileEngineIterator
{
public:
- QAbstractFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters);
+ QAbstractFileEngineIterator(const QString &path, QDir::Filters filters,
+ const QStringList &nameFilters);
virtual ~QAbstractFileEngineIterator();
- virtual QString next() = 0;
- virtual bool hasNext() const = 0;
+ virtual bool advance() = 0;
QString path() const;
QStringList nameFilters() const;
@@ -237,19 +213,20 @@ public:
virtual QString currentFileName() const = 0;
virtual QFileInfo currentFileInfo() const;
- QString currentFilePath() const;
+ virtual QString currentFilePath() const;
protected:
- enum EntryInfoType {
- };
- virtual QVariant entryInfo(EntryInfoType type) const;
+ mutable QFileInfo m_fileInfo;
private:
Q_DISABLE_COPY_MOVE(QAbstractFileEngineIterator)
friend class QDirIterator;
friend class QDirIteratorPrivate;
- void setPath(const QString &path);
- QScopedPointer<QAbstractFileEngineIteratorPrivate> d;
+ friend class QDirListingPrivate;
+
+ QDir::Filters m_filters;
+ QStringList m_nameFilters;
+ QString m_path;
};
class QAbstractFileEnginePrivate
@@ -268,7 +245,7 @@ public:
Q_DECLARE_PUBLIC(QAbstractFileEngine)
};
-QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path);
+std::unique_ptr<QAbstractFileEngine> qt_custom_file_engine_handler_create(const QString &path);
QT_END_NAMESPACE
diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp
index 595fcd2724..4e513bc7cf 100644
--- a/src/corelib/io/qbuffer.cpp
+++ b/src/corelib/io/qbuffer.cpp
@@ -1,46 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbuffer.h"
#include <QtCore/qmetaobject.h>
#include "private/qiodevice_p.h"
+#include <limits>
+
QT_BEGIN_NAMESPACE
/** QBufferPrivate **/
@@ -49,15 +15,9 @@ class QBufferPrivate : public QIODevicePrivate
Q_DECLARE_PUBLIC(QBuffer)
public:
- QBufferPrivate()
- : buf(nullptr)
-#ifndef QT_NO_QOBJECT
- , writtenSinceLastEmit(0), signalConnectionCount(0), signalsEmitted(false)
-#endif
- { }
- ~QBufferPrivate() { }
+ QBufferPrivate() = default;
- QByteArray *buf;
+ QByteArray *buf = nullptr;
QByteArray defaultBuf;
qint64 peek(char *data, qint64 maxSize) override;
@@ -67,9 +27,9 @@ public:
// private slots
void _q_emitSignals();
- qint64 writtenSinceLastEmit;
- int signalConnectionCount;
- bool signalsEmitted;
+ qint64 writtenSinceLastEmit = 0;
+ int signalConnectionCount = 0;
+ bool signalsEmitted = false;
#endif
};
@@ -212,7 +172,7 @@ QBuffer::~QBuffer()
}
/*!
- Makes QBuffer uses the QByteArray pointed to by \a
+ Makes QBuffer use the QByteArray pointed to by \a
byteArray as its internal buffer. The caller is responsible for
ensuring that \a byteArray remains valid until the QBuffer is
destroyed, or until setBuffer() is called to change the buffer.
@@ -307,16 +267,30 @@ void QBuffer::setData(const QByteArray &data)
}
/*!
- \fn void QBuffer::setData(const char *data, int size)
-
\overload
Sets the contents of the internal buffer to be the first \a size
bytes of \a data.
+
+ \note In Qt versions prior to 6.5, this function took the length as
+ an \c{int} parameter, potentially truncating sizes.
*/
+void QBuffer::setData(const char *data, qsizetype size)
+{
+ Q_D(QBuffer);
+ if (isOpen()) {
+ qWarning("QBuffer::setData: Buffer is open");
+ return;
+ }
+ d->buf->assign(data, data + size);
+}
/*!
\reimp
+
+ Unlike QFile, opening a QBuffer QIODevice::WriteOnly does not truncate it.
+ However, pos() is set to 0. Use QIODevice::Append or QIODevice::Truncate to
+ change either behavior.
*/
bool QBuffer::open(OpenMode flags)
{
@@ -366,18 +340,19 @@ qint64 QBuffer::size() const
bool QBuffer::seek(qint64 pos)
{
Q_D(QBuffer);
- if (pos > d->buf->size() && isWritable()) {
- if (seek(d->buf->size())) {
- const qint64 gapSize = pos - d->buf->size();
- if (write(QByteArray(gapSize, 0)) != gapSize) {
- qWarning("QBuffer::seek: Unable to fill gap");
- return false;
- }
- } else {
+ const auto oldBufSize = d->buf->size();
+ constexpr qint64 MaxSeekPos = (std::numeric_limits<decltype(oldBufSize)>::max)();
+ if (pos <= MaxSeekPos && pos > oldBufSize && isWritable()) {
+ QT_TRY {
+ d->buf->resize(qsizetype(pos), '\0');
+ } QT_CATCH(const std::bad_alloc &) {} // swallow, failure case is handled below
+ if (d->buf->size() != pos) {
+ qWarning("QBuffer::seek: Unable to fill gap");
return false;
}
- } else if (pos > d->buf->size() || pos < 0) {
- qWarning("QBuffer::seek: Invalid pos: %d", int(pos));
+ }
+ if (pos > d->buf->size() || pos < 0) {
+ qWarning("QBuffer::seek: Invalid pos: %lld", pos);
return false;
}
return QIODevice::seek(pos);
@@ -421,17 +396,19 @@ qint64 QBuffer::readData(char *data, qint64 len)
qint64 QBuffer::writeData(const char *data, qint64 len)
{
Q_D(QBuffer);
- int extraBytes = pos() + len - d->buf->size();
- if (extraBytes > 0) { // overflow
- int newSize = d->buf->size() + extraBytes;
- d->buf->resize(newSize);
- if (d->buf->size() != newSize) { // could not resize
+ const quint64 required = quint64(pos()) + quint64(len); // cannot overflow (pos() ≥ 0, len ≥ 0)
+
+ if (required > quint64(d->buf->size())) { // capacity exceeded
+ // The following must hold, since qsizetype covers half the virtual address space:
+ Q_ASSERT(required <= quint64((std::numeric_limits<qsizetype>::max)()));
+ d->buf->resize(qsizetype(required));
+ if (quint64(d->buf->size()) != required) { // could not resize
qWarning("QBuffer::writeData: Memory allocation error");
return -1;
}
}
- memcpy(d->buf->data() + pos(), data, int(len));
+ memcpy(d->buf->data() + pos(), data, size_t(len));
#ifndef QT_NO_QOBJECT
d->writtenSinceLastEmit += len;
@@ -444,15 +421,22 @@ qint64 QBuffer::writeData(const char *data, qint64 len)
}
#ifndef QT_NO_QOBJECT
+static bool is_tracked_signal(const QMetaMethod &signal)
+{
+ // dynamic initialization: minimize the number of guard variables:
+ static const struct {
+ QMetaMethod readyReadSignal = QMetaMethod::fromSignal(&QBuffer::readyRead);
+ QMetaMethod bytesWrittenSignal = QMetaMethod::fromSignal(&QBuffer::bytesWritten);
+ } sigs;
+ return signal == sigs.readyReadSignal || signal == sigs.bytesWrittenSignal;
+}
/*!
\reimp
\internal
*/
void QBuffer::connectNotify(const QMetaMethod &signal)
{
- static const QMetaMethod readyReadSignal = QMetaMethod::fromSignal(&QBuffer::readyRead);
- static const QMetaMethod bytesWrittenSignal = QMetaMethod::fromSignal(&QBuffer::bytesWritten);
- if (signal == readyReadSignal || signal == bytesWrittenSignal)
+ if (is_tracked_signal(signal))
d_func()->signalConnectionCount++;
}
@@ -463,9 +447,7 @@ void QBuffer::connectNotify(const QMetaMethod &signal)
void QBuffer::disconnectNotify(const QMetaMethod &signal)
{
if (signal.isValid()) {
- static const QMetaMethod readyReadSignal = QMetaMethod::fromSignal(&QBuffer::readyRead);
- static const QMetaMethod bytesWrittenSignal = QMetaMethod::fromSignal(&QBuffer::bytesWritten);
- if (signal == readyReadSignal || signal == bytesWrittenSignal)
+ if (is_tracked_signal(signal))
d_func()->signalConnectionCount--;
} else {
d_func()->signalConnectionCount = 0;
diff --git a/src/corelib/io/qbuffer.h b/src/corelib/io/qbuffer.h
index 39e1e7b39d..4cbbfe7c52 100644
--- a/src/corelib/io/qbuffer.h
+++ b/src/corelib/io/qbuffer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBUFFER_H
#define QBUFFER_H
@@ -45,7 +9,6 @@
QT_BEGIN_NAMESPACE
-
class QObject;
class QBufferPrivate;
@@ -57,11 +20,11 @@ class Q_CORE_EXPORT QBuffer : public QIODevice
public:
#ifndef QT_NO_QOBJECT
- explicit QBuffer(QObject *parent = nullptr);
- QBuffer(QByteArray *buf, QObject *parent = nullptr);
+ explicit QBuffer(QObject *parent = nullptr);
+ QBuffer(QByteArray *buf, QObject *parent = nullptr);
#else
- QBuffer();
- explicit QBuffer(QByteArray *buf);
+ QBuffer();
+ explicit QBuffer(QByteArray *buf);
#endif
~QBuffer();
@@ -70,7 +33,10 @@ public:
void setBuffer(QByteArray *a);
void setData(const QByteArray &data);
- inline void setData(const char *data, int len);
+#if QT_CORE_REMOVED_SINCE(6, 5) && QT_POINTER_SIZE != 4
+ void setData(const char *data, int len) { setData(data, qsizetype(len)); }
+#endif
+ void setData(const char *data, qsizetype len);
const QByteArray &data() const;
bool open(OpenMode openMode) override;
@@ -97,9 +63,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_emitSignals())
};
-inline void QBuffer::setData(const char *adata, int alen)
-{ setData(QByteArray(adata, alen)); }
-
QT_END_NAMESPACE
#endif // QBUFFER_H
diff --git a/src/corelib/io/qdataurl.cpp b/src/corelib/io/qdataurl.cpp
index 9cb1b9abd0..65b934b3f6 100644
--- a/src/corelib/io/qdataurl.cpp
+++ b/src/corelib/io/qdataurl.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qurl.h"
@@ -43,6 +7,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals;
+
/*!
\internal
@@ -51,41 +17,45 @@ QT_BEGIN_NAMESPACE
*/
Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray &payload)
{
- if (uri.scheme() != QLatin1String("data") || !uri.host().isEmpty())
+ if (uri.scheme() != "data"_L1 || !uri.host().isEmpty())
return false;
- mimeType = QLatin1String("text/plain;charset=US-ASCII");
+ mimeType = QStringLiteral("text/plain;charset=US-ASCII");
// the following would have been the correct thing, but
// reality often differs from the specification. People have
// data: URIs with ? and #
//QByteArray data = QByteArray::fromPercentEncoding(uri.path(QUrl::FullyEncoded).toLatin1());
- QByteArray data = QByteArray::fromPercentEncoding(uri.url(QUrl::FullyEncoded | QUrl::RemoveScheme).toLatin1());
+ const QByteArray dataArray =
+ QByteArray::fromPercentEncoding(uri.url(QUrl::FullyEncoded | QUrl::RemoveScheme).toLatin1());
+ QByteArrayView data = dataArray;
// parse it:
- int pos = data.indexOf(',');
+ const qsizetype pos = data.indexOf(',');
if (pos != -1) {
- payload = data.mid(pos + 1);
+ payload = data.mid(pos + 1).toByteArray();
data.truncate(pos);
data = data.trimmed();
// find out if the payload is encoded in Base64
- if (data.endsWith(";base64")) {
+ constexpr auto base64 = ";base64"_L1;
+ if (QLatin1StringView{data}.endsWith(base64, Qt::CaseInsensitive)) {
payload = QByteArray::fromBase64(payload);
- data.chop(7);
+ data.chop(base64.size());
}
- if (data.toLower().startsWith("charset")) {
- int i = 7; // strlen("charset")
+ QLatin1StringView textPlain;
+ constexpr auto charset = "charset"_L1;
+ if (QLatin1StringView{data}.startsWith(charset, Qt::CaseInsensitive)) {
+ qsizetype i = charset.size();
while (data.at(i) == ' ')
++i;
if (data.at(i) == '=')
- data.prepend("text/plain;");
+ textPlain = "text/plain;"_L1;
}
if (!data.isEmpty())
- mimeType = QLatin1String(data.trimmed());
-
+ mimeType = textPlain + QLatin1StringView(data.trimmed());
}
return true;
diff --git a/src/corelib/io/qdataurl_p.h b/src/corelib/io/qdataurl_p.h
index fd5c7df50b..2763056cc4 100644
--- a/src/corelib/io/qdataurl_p.h
+++ b/src/corelib/io/qdataurl_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATAURL_P_H
#define QDATAURL_P_H
@@ -55,7 +19,6 @@
#include "QtCore/qurl.h"
#include "QtCore/qbytearray.h"
#include "QtCore/qstring.h"
-#include "QtCore/qpair.h"
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index bac362dc80..64b693fea5 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1,59 +1,66 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifdef QT_NO_DEBUG
-#undef QT_NO_DEBUG
-#endif
-#ifdef qDebug
-#undef qDebug
-#endif
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdebug.h"
+#include "private/qdebug_p.h"
#include "qmetaobject.h"
+#include <private/qlogging_p.h>
#include <private/qtextstream_p.h>
#include <private/qtools_p.h>
+#include <array>
+#include <q20chrono.h>
+
QT_BEGIN_NAMESPACE
-using QtMiscUtils::toHexUpper;
-using QtMiscUtils::fromHex;
+using namespace QtMiscUtils;
+
+/*
+ Returns a human readable representation of the first \a maxSize
+ characters in \a data. The size, \a len, is a 64-bit quantity to
+ avoid truncation due to implicit conversions in callers.
+*/
+QByteArray QtDebugUtils::toPrintable(const char *data, qint64 len, qsizetype maxSize)
+{
+ if (!data)
+ return "(null)";
+
+ QByteArray out;
+ for (qsizetype i = 0; i < qMin(len, maxSize); ++i) {
+ char c = data[i];
+ if (isAsciiPrintable(c)) {
+ out += c;
+ } else {
+ switch (c) {
+ case '\n':
+ out += "\\n";
+ break;
+ case '\r':
+ out += "\\r";
+ break;
+ case '\t':
+ out += "\\t";
+ break;
+ default: {
+ const char buf[] = {
+ '\\',
+ 'x',
+ toHexLower(uchar(c) / 16),
+ toHexLower(uchar(c) % 16),
+ 0
+ };
+ out += buf;
+ }
+ }
+ }
+ }
+
+ if (maxSize < len)
+ out += "...";
+
+ return out;
+}
// This file is needed to force compilation of QDebug into the kernel library.
@@ -144,15 +151,15 @@ using QtMiscUtils::fromHex;
Flushes any pending data to be written and destroys the debug stream.
*/
-// Has been defined in the header / inlined before Qt 5.4
QDebug::~QDebug()
{
if (stream && !--stream->ref) {
- if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
+ if (stream->space && stream->buffer.endsWith(u' '))
stream->buffer.chop(1);
if (stream->message_output) {
+ QInternalMessageLogContext ctxt(stream->context);
qt_message_output(stream->type,
- stream->context,
+ ctxt,
stream->buffer);
}
delete stream;
@@ -174,7 +181,7 @@ void QDebug::putUcs4(uint ucs4)
stream->ts << "\\u" << qSetFieldWidth(4);
else
stream->ts << "\\U" << qSetFieldWidth(8);
- stream->ts << Qt::hex << qSetPadChar(QLatin1Char('0')) << ucs4 << Qt::reset;
+ stream->ts << Qt::hex << qSetPadChar(u'0') << ucs4 << Qt::reset;
}
maybeQuote('\'');
}
@@ -182,17 +189,15 @@ void QDebug::putUcs4(uint ucs4)
// These two functions return true if the character should be printed by QDebug.
// For QByteArray, this is technically identical to US-ASCII isprint();
// for QString, we use QChar::isPrint, which requires a full UCS-4 decode.
-static inline bool isPrintable(uint ucs4)
-{ return QChar::isPrint(ucs4); }
-static inline bool isPrintable(ushort uc)
-{ return QChar::isPrint(uc); }
+static inline bool isPrintable(char32_t ucs4) { return QChar::isPrint(ucs4); }
+static inline bool isPrintable(char16_t uc) { return QChar::isPrint(uc); }
static inline bool isPrintable(uchar c)
-{ return c >= ' ' && c < 0x7f; }
+{ return isAsciiPrintable(c); }
template <typename Char>
-static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, int length, bool isUnicode = true)
+static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, size_t length, bool isUnicode = true)
{
- QChar quote(QLatin1Char('"'));
+ QChar quote(u'"');
d->write(&quote, 1);
bool lastWasHexEscape = false;
@@ -202,7 +207,7 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
if (Q_UNLIKELY(lastWasHexEscape)) {
if (fromHex(*p) != -1) {
// yes, insert it
- QChar quotes[] = { QLatin1Char('"'), QLatin1Char('"') };
+ QChar quotes[] = { quote, quote };
d->write(quotes, 2);
}
lastWasHexEscape = false;
@@ -210,7 +215,7 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
if (sizeof(Char) == sizeof(QChar)) {
// Surrogate characters are category Cs (Other_Surrogate), so isPrintable = false for them
- int runLength = 0;
+ qsizetype runLength = 0;
while (p + runLength != end &&
isPrintable(p[runLength]) && p[runLength] != '\\' && p[runLength] != '"')
++runLength;
@@ -226,8 +231,8 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
}
// print as an escape sequence (maybe, see below for surrogate pairs)
- int buflen = 2;
- ushort buf[sizeof "\\U12345678" - 1];
+ qsizetype buflen = 2;
+ char16_t buf[std::char_traits<char>::length("\\U12345678")];
buf[0] = '\\';
switch (*p) {
@@ -263,7 +268,7 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
if (QChar::isHighSurrogate(*p)) {
if ((p + 1) != end && QChar::isLowSurrogate(p[1])) {
// properly-paired surrogates
- uint ucs4 = QChar::surrogateToUcs4(*p, p[1]);
+ char32_t ucs4 = QChar::surrogateToUcs4(*p, p[1]);
if (isPrintable(ucs4)) {
buf[0] = *p;
buf[1] = p[1];
@@ -286,8 +291,8 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
// improperly-paired surrogates, fall through
}
buf[1] = 'u';
- buf[2] = toHexUpper(ushort(*p) >> 12);
- buf[3] = toHexUpper(ushort(*p) >> 8);
+ buf[2] = toHexUpper(char16_t(*p) >> 12);
+ buf[3] = toHexUpper(char16_t(*p) >> 8);
buf[4] = toHexUpper(*p >> 4);
buf[5] = toHexUpper(*p);
buflen = 6;
@@ -304,15 +309,15 @@ static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, in
*/
void QDebug::putString(const QChar *begin, size_t length)
{
- if (stream->testFlag(Stream::NoQuotes)) {
+ if (stream->noQuotes) {
// no quotes, write the string directly too (no pretty-printing)
// this respects the QTextStream state, though
- stream->ts.d_ptr->putString(begin, int(length));
+ stream->ts.d_ptr->putString(begin, qsizetype(length));
} else {
// we'll reset the QTextStream formatting mechanisms, so save the state
QDebugStateSaver saver(*this);
stream->ts.d_ptr->params.reset();
- putEscapedString(stream->ts.d_ptr.data(), reinterpret_cast<const ushort *>(begin), int(length));
+ putEscapedString(stream->ts.d_ptr.data(), reinterpret_cast<const char16_t *>(begin), length);
}
}
@@ -322,20 +327,191 @@ void QDebug::putString(const QChar *begin, size_t length)
*/
void QDebug::putByteArray(const char *begin, size_t length, Latin1Content content)
{
- if (stream->testFlag(Stream::NoQuotes)) {
+ if (stream->noQuotes) {
// no quotes, write the string directly too (no pretty-printing)
// this respects the QTextStream state, though
- QString string = content == ContainsLatin1 ? QString::fromLatin1(begin, int(length)) : QString::fromUtf8(begin, int(length));
+ QString string = content == ContainsLatin1 ? QString::fromLatin1(begin, qsizetype(length))
+ : QString::fromUtf8(begin, qsizetype(length));
stream->ts.d_ptr->putString(string);
} else {
// we'll reset the QTextStream formatting mechanisms, so save the state
QDebugStateSaver saver(*this);
stream->ts.d_ptr->params.reset();
putEscapedString(stream->ts.d_ptr.data(), reinterpret_cast<const uchar *>(begin),
- int(length), content == ContainsLatin1);
+ length, content == ContainsLatin1);
+ }
+}
+
+static QByteArray timeUnit(qint64 num, qint64 den)
+{
+ using namespace std::chrono;
+ using namespace q20::chrono;
+
+ if (num == 1 && den > 1) {
+ // sub-multiple of seconds
+ char prefix = '\0';
+ auto tryprefix = [&](auto d, char c) {
+ static_assert(decltype(d)::num == 1, "not an SI prefix");
+ if (den == decltype(d)::den)
+ prefix = c;
+ };
+
+ // "u" should be "µ", but debugging output is not always UTF-8-safe
+ tryprefix(std::milli{}, 'm');
+ tryprefix(std::micro{}, 'u');
+ tryprefix(std::nano{}, 'n');
+ tryprefix(std::pico{}, 'p');
+ tryprefix(std::femto{}, 'f');
+ tryprefix(std::atto{}, 'a');
+ // uncommon ones later
+ tryprefix(std::centi{}, 'c');
+ tryprefix(std::deci{}, 'd');
+ if (prefix) {
+ char unit[3] = { prefix, 's' };
+ return QByteArray(unit, sizeof(unit) - 1);
+ }
+ }
+
+ const char *unit = nullptr;
+ if (num > 1 && den == 1) {
+ // multiple of seconds - but we don't use SI prefixes
+ auto tryunit = [&](auto d, const char *name) {
+ static_assert(decltype(d)::period::den == 1, "not a multiple of a second");
+ if (unit || num % decltype(d)::period::num)
+ return;
+ unit = name;
+ num /= decltype(d)::period::num;
+ };
+ tryunit(years{}, "yr");
+ tryunit(weeks{}, "wk");
+ tryunit(days{}, "d");
+ tryunit(hours{}, "h");
+ tryunit(minutes{}, "min");
+ }
+ if (!unit)
+ unit = "s";
+
+ if (num == 1 && den == 1)
+ return unit;
+ if (Q_UNLIKELY(num < 1 || den < 1))
+ return QString::asprintf("<invalid time unit %lld/%lld>", num, den).toLatin1();
+
+ // uncommon units: will return something like "[2/3]s"
+ // strlen("[/]min") = 6
+ char buf[2 * (std::numeric_limits<qint64>::digits10 + 2) + 10];
+ size_t len = 0;
+ auto appendChar = [&](char c) {
+ Q_ASSERT(len < sizeof(buf));
+ buf[len++] = c;
+ };
+ auto appendNumber = [&](qint64 value) {
+ if (value >= 10'000 && (value % 1000) == 0)
+ len += qsnprintf(buf + len, sizeof(buf) - len, "%.6g", double(value)); // "1e+06"
+ else
+ len += qsnprintf(buf + len, sizeof(buf) - len, "%lld", value);
+ };
+ appendChar('[');
+ appendNumber(num);
+ if (den != 1) {
+ appendChar('/');
+ appendNumber(den);
+ }
+ appendChar(']');
+ memcpy(buf + len, unit, strlen(unit));
+ return QByteArray(buf, len + strlen(unit));
+}
+
+/*!
+ \since 6.6
+ \internal
+ Helper to the std::chrono::duration debug streaming output.
+ */
+void QDebug::putTimeUnit(qint64 num, qint64 den)
+{
+ stream->ts << timeUnit(num, den); // ### optimize
+}
+
+namespace {
+
+#ifdef QT_SUPPORTS_INT128
+
+constexpr char Q_INT128_MIN_STR[] = "-170141183460469231731687303715884105728";
+
+constexpr int Int128BufferSize = sizeof(Q_INT128_MIN_STR);
+using Int128Buffer = std::array<char, Int128BufferSize>;
+ // numeric_limits<qint128>::digits10 may not exist
+
+static char *i128ToStringHelper(Int128Buffer &buffer, quint128 n)
+{
+ auto dst = buffer.data() + buffer.size();
+ *--dst = '\0'; // NUL-terminate
+ if (n == 0) {
+ *--dst = '0'; // and done
+ } else {
+ while (n != 0) {
+ *--dst = "0123456789"[n % 10];
+ n /= 10;
+ }
}
+ return dst;
+}
+#endif // QT_SUPPORTS_INT128
+
+[[maybe_unused]]
+static const char *int128Warning()
+{
+ const char *msg = "Qt was not compiled with int128 support.";
+ qWarning("%s", msg);
+ return msg;
+}
+
+} // unnamed namespace
+
+/*!
+ \since 6.7
+ \internal
+ Helper to the qint128 debug streaming output.
+ */
+void QDebug::putInt128([[maybe_unused]] const void *p)
+{
+#ifdef QT_SUPPORTS_INT128
+ Q_ASSERT(p);
+ qint128 i;
+ memcpy(&i, p, sizeof(i)); // alignment paranoia
+ if (i == Q_INT128_MIN) {
+ // -i is not representable, hardcode the result:
+ stream->ts << Q_INT128_MIN_STR;
+ } else {
+ Int128Buffer buffer;
+ auto dst = i128ToStringHelper(buffer, i < 0 ? -i : i);
+ if (i < 0)
+ *--dst = '-';
+ stream->ts << dst;
+ }
+ return;
+#endif // QT_SUPPORTS_INT128
+ stream->ts << int128Warning();
+}
+
+/*!
+ \since 6.7
+ \internal
+ Helper to the quint128 debug streaming output.
+ */
+void QDebug::putUInt128([[maybe_unused]] const void *p)
+{
+#ifdef QT_SUPPORTS_INT128
+ Q_ASSERT(p);
+ quint128 i;
+ memcpy(&i, p, sizeof(i)); // alignment paranoia
+ Int128Buffer buffer;
+ stream->ts << i128ToStringHelper(buffer, i);
+ return;
+#endif // QT_SUPPORTS_INT128
+ stream->ts << int128Warning();
}
+
/*!
\fn QDebug::swap(QDebug &other)
\since 5.0
@@ -354,9 +530,8 @@ QDebug &QDebug::resetFormat()
{
stream->ts.reset();
stream->space = true;
- if (stream->context.version > 1)
- stream->flags = 0;
- stream->setVerbosity(DefaultVerbosity);
+ stream->noQuotes = false;
+ stream->verbosity = DefaultVerbosity;
return *this;
}
@@ -413,6 +588,29 @@ QDebug &QDebug::resetFormat()
/*!
+ \fn bool QDebug::quoteStrings() const
+ \since 6.7
+
+ Returns \c true if this QDebug instance will quote strings streamed into
+ it (which is the default).
+
+ \sa QDebugStateSaver, quote(), noquote(), setQuoteStrings()
+*/
+
+/*!
+ \fn void QDebug::setQuoteStrings(bool b)
+ \since 6.7
+
+ Enables quoting of strings streamed into this QDebug instance if \a b is
+ \c true; otherwise quoting is disabled.
+
+ The default is to quote strings.
+
+ \sa QDebugStateSaver, quote(), noquote(), quoteStrings()
+*/
+
+
+/*!
\fn QDebug &QDebug::quote()
\since 5.4
@@ -597,9 +795,24 @@ QDebug &QDebug::resetFormat()
/*!
\fn QDebug &QDebug::operator<<(const char *t)
- Writes the '\\0'-terminated string, \a t, to the stream and returns a
- reference to the stream. The string is never quoted nor transformed to the
- output, but note that some QDebug backends might not be 8-bit clean.
+ Writes the '\\0'-terminated UTF-8 string, \a t, to the stream and returns a
+ reference to the stream. The string is never quoted or escaped for the
+ output. Note that QDebug buffers internally as UTF-16 and may need to
+ transform to 8-bit using the locale's codec in order to use some backends,
+ which may cause garbled output (mojibake). Restricting to US-ASCII strings
+ is recommended.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(const char16_t *t)
+ \since 6.0
+
+ Writes the u'\\0'-terminated UTF-16 string, \a t, to the stream and returns
+ a reference to the stream. The string is never quoted or escaped for the
+ output. Note that QDebug buffers internally as UTF-16 and may need to
+ transform to 8-bit using the locale's codec in order to use some backends,
+ which may cause garbled output (mojibake). Restricting to US-ASCII strings
+ is recommended.
*/
/*!
@@ -649,7 +862,24 @@ QDebug &QDebug::resetFormat()
*/
/*!
- \fn QDebug &QDebug::operator<<(QLatin1String t)
+ \since 6.0
+ \fn QDebug &QDebug::operator<<(QUtf8StringView s)
+
+ Writes the string view, \a s, to the stream and returns a reference to the
+ stream.
+
+ Normally, QDebug prints the data inside quotes and transforms control or
+ non-US-ASCII characters to their C escape sequences (\\xAB). This way, the
+ output is always 7-bit clean and the string can be copied from the output
+ and pasted back into C++ sources, if necessary.
+
+ To print non-printable characters without transformation, enable the
+ noquote() functionality. Note that some QDebug backends might not be 8-bit
+ clean.
+*/
+
+/*!
+ \fn QDebug &QDebug::operator<<(QLatin1StringView t)
Writes the string, \a t, to the stream and returns a reference to the
stream. Normally, QDebug prints the string inside quotes and transforms
@@ -684,6 +914,25 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \since 6.0
+ \fn QDebug &QDebug::operator<<(QByteArrayView t)
+
+ Writes the data of the observed byte array, \a t, to the stream and returns
+ a reference to the stream.
+
+ Normally, QDebug prints the data inside quotes and transforms control or
+ non-US-ASCII characters to their C escape sequences (\\xAB). This way, the
+ output is always 7-bit clean and the string can be copied from the output
+ and pasted back into C++ sources, if necessary.
+
+ To print non-printable characters without transformation, enable the
+ noquote() functionality. Note that some QDebug backends might not be 8-bit
+ clean.
+
+ See the QByteArray overload for examples.
+*/
+
+/*!
\fn QDebug &QDebug::operator<<(const void *t)
Writes a pointer, \a t, to the stream and returns a reference to the stream.
@@ -700,14 +949,54 @@ QDebug &QDebug::resetFormat()
*/
/*!
- \fn template <class T> QString QDebug::toString(const T &object)
- \since 6.0
+ \since 6.5
+ \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(const std::basic_string<Char, Args...> &s)
+ \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(std::basic_string_view<Char, Args...> s)
- \include qdebug-toString.qdocinc
+ Writes the string or string-view \a s to the stream and returns a reference
+ to the stream.
+
+ These operators only participate in overload resolution if \c Char is one of
+ \list
+ \li char
+ \li char8_t (C++20 only)
+ \li char16_t
+ \li char32_t
+ \li wchar_t
+ \endlist
+*/
+
+/*!
+ \since 6.6
+ \fn template <typename Rep, typename Period> QDebug &QDebug::operator<<(std::chrono::duration<Rep, Period> duration)
+
+ Prints the time duration \a duration to the stream and returns a reference
+ to the stream. The printed string is the numeric representation of the
+ period followed by the time unit, similar to what the C++ Standard Library
+ would produce with \c{std::ostream}.
+
+ The unit is not localized.
+*/
+
+/*!
+ \fn template <typename T, QDebug::if_qint128<T>> QDebug::operator<<(T i)
+ \fn template <typename T, QDebug::if_quint128<T>> QDebug::operator<<(T i)
+ \since 6.7
+
+ Prints the textual representation of the 128-bit integer \a i.
+
+ \note This operator is only available if Qt supports 128-bit integer types.
+ If 128-bit integer types are available in your build, but the Qt libraries
+ were compiled without, the operator will print a warning instead.
+
+ \note Because the operator is a function template, no implicit conversions
+ are performed on its argument. It must be exactly qint128/quint128.
+
+ \sa QT_SUPPORTS_INT128
*/
/*!
- \fn template <class T> QString QDebug::toString(const T *object)
+ \fn template <class T> QString QDebug::toString(T &&object)
\since 6.0
\include qdebug-toString.qdocinc
@@ -722,6 +1011,15 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \fn template <class T, qsizetype P> QDebug operator<<(QDebug debug, const QVarLengthArray<T,P> &array)
+ \relates QDebug
+ \since 6.3
+
+ Writes the contents of \a array to \a debug. \c T needs to
+ support streaming into QDebug.
+*/
+
+/*!
\fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec)
\relates QDebug
\since 5.7
@@ -756,6 +1054,14 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map)
+ \relates QDebug
+
+ Writes the contents of \a map to \a debug. Both \c Key and
+ \c T need to support streaming into QDebug.
+*/
+
+/*!
\fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
\relates QDebug
\since 5.7
@@ -782,7 +1088,15 @@ QDebug &QDebug::resetFormat()
*/
/*!
- \fn template <class T1, class T2> QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
+ \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
+ \relates QDebug
+
+ Writes the contents of \a hash to \a debug. Both \c Key and
+ \c T need to support streaming into QDebug.
+*/
+
+/*!
+ \fn template <class T1, class T2> QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair)
\relates QDebug
Writes the contents of \a pair to \a debug. Both \c T1 and
@@ -790,6 +1104,23 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \since 6.7
+ \fn template <class T> QDebug operator<<(QDebug debug, const std::optional<T> &opt)
+ \relates QDebug
+
+ Writes the contents of \a opt (or \c nullopt if not set) to \a debug.
+ \c T needs to support streaming into QDebug.
+*/
+
+/*!
+ \fn template <typename T> QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
+ \relates QDebug
+
+ Writes the contents of \a cache to \a debug. \c T needs to
+ support streaming into QDebug.
+*/
+
+/*!
\fn template<typename T> QDebug operator<<(QDebug debug, const QFlags<T> &flags)
\relates QDebug
\since 4.7
@@ -814,6 +1145,13 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \since 6.7
+ \fn QDebug &QDebug::operator<<(std::nullopt_t)
+
+ Writes nullopt to the stream.
+*/
+
+/*!
\class QDebugStateSaver
\inmodule QtCore
\brief Convenience class for custom QDebug operators.
@@ -829,6 +1167,10 @@ QDebug &QDebug::resetFormat()
so that using << Qt::hex in a QDebug operator doesn't affect other QDebug
operators.
+ QDebugStateSaver is typically used in the implementation of an operator<<() for debugging:
+
+ \snippet customtype/customtypeexample.cpp custom type streaming operator
+
\since 5.1
*/
@@ -838,7 +1180,8 @@ public:
QDebugStateSaverPrivate(QDebug::Stream *stream)
: m_stream(stream),
m_spaces(stream->space),
- m_flags(stream->context.version > 1 ? stream->flags : 0),
+ m_noQuotes(stream->noQuotes),
+ m_verbosity(stream->verbosity),
m_streamParams(stream->ts.d_ptr->params)
{
}
@@ -846,13 +1189,13 @@ public:
{
const bool currentSpaces = m_stream->space;
if (currentSpaces && !m_spaces)
- if (m_stream->buffer.endsWith(QLatin1Char(' ')))
+ if (m_stream->buffer.endsWith(u' '))
m_stream->buffer.chop(1);
m_stream->space = m_spaces;
+ m_stream->noQuotes = m_noQuotes;
m_stream->ts.d_ptr->params = m_streamParams;
- if (m_stream->context.version > 1)
- m_stream->flags = m_flags;
+ m_stream->verbosity = m_verbosity;
if (!currentSpaces && m_spaces)
m_stream->ts << ' ';
@@ -862,7 +1205,8 @@ public:
// QDebug state
const bool m_spaces;
- const int m_flags;
+ const bool m_noQuotes;
+ const int m_verbosity;
// QTextStream state
const QTextStreamPrivate::Params m_streamParams;
@@ -906,7 +1250,6 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
#ifndef QT_NO_QOBJECT
/*!
- \fn QDebug qt_QMetaEnum_debugOperator(QDebug &, int value, const QMetaObject *, const char *name)
\internal
Formats the given enum \a value for debug output.
@@ -941,7 +1284,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
MyNamespace::MyClass::MyScopedEnum::Enum3
MyNamespace::MyClass::MyScopedEnum(456)
*/
-QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *meta, const char *name)
+QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, qint64 value, const QMetaObject *meta, const char *name)
{
QDebugStateSaver saver(dbg);
dbg.nospace();
@@ -950,18 +1293,18 @@ QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *met
const int verbosity = dbg.verbosity();
if (verbosity >= QDebug::DefaultVerbosity) {
if (const char *scope = me.scope())
- dbg << scope << "::";
+ dbg << scope << u"::";
}
- const char *key = me.valueToKey(value);
+ const char *key = me.valueToKey(static_cast<int>(value));
const bool scoped = me.isScoped() || verbosity & 1;
if (scoped || !key)
- dbg << me.enumName() << (!key ? "(" : "::");
+ dbg << me.enumName() << (!key ? u"(" : u"::");
if (key)
dbg << key;
else
- dbg << value << ")";
+ dbg << value << ')';
return dbg;
}
@@ -1008,21 +1351,21 @@ QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaO
const bool classScope = verbosity >= QDebug::DefaultVerbosity;
if (classScope) {
- debug << "QFlags<";
+ debug << u"QFlags<";
if (const char *scope = me.scope())
- debug << scope << "::";
+ debug << scope << u"::";
}
const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity;
if (enumScope) {
debug << me.enumName();
if (classScope)
- debug << ">";
- debug << "(";
+ debug << '>';
+ debug << '(';
}
- debug << me.valueToKeys(value);
+ debug << me.valueToKeys(static_cast<int>(value));
if (enumScope)
debug << ')';
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 46fd762874..4797bcd169 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -1,66 +1,41 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDEBUG_H
#define QDEBUG_H
-#include <QtCore/qalgorithms.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qmap.h>
+#if 0
+#pragma qt_class(QtDebug)
+#endif
+
+#include <QtCore/qcontainerfwd.h>
#include <QtCore/qtextstream.h>
+#include <QtCore/qtypes.h>
#include <QtCore/qstring.h>
-#include <QtCore/qset.h>
#include <QtCore/qcontiguouscache.h>
#include <QtCore/qsharedpointer.h>
// all these have already been included by various headers above, but don't rely on indirect includes:
-#include <vector>
+#include <chrono>
#include <list>
#include <map>
+#include <optional>
+#include <string>
+#include <string_view>
#include <utility>
+#include <vector>
-QT_BEGIN_NAMESPACE
+#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
+# include <QtCore/qlist.h>
+# include <QtCore/qmap.h>
+# include <QtCore/qset.h>
+# include <QtCore/qvarlengtharray.h>
+#endif
+QT_BEGIN_NAMESPACE
-class Q_CORE_EXPORT QDebug
+class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
{
friend class QMessageLogger;
friend class QDebugStateSaver;
@@ -68,101 +43,94 @@ class Q_CORE_EXPORT QDebug
struct Stream {
enum { VerbosityShift = 29, VerbosityMask = 0x7 };
- Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg),
- space(true), message_output(false), flags(DefaultVerbosity << VerbosityShift) {}
- Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg),
- space(true), message_output(false), flags(DefaultVerbosity << VerbosityShift) {}
- Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t),
- space(true), message_output(true), flags(DefaultVerbosity << VerbosityShift) {}
+ Stream(QIODevice *device)
+ : ts(device)
+ {}
+ Stream(QString *string)
+ : ts(string, WriteOnly)
+ {}
+ Stream(QtMsgType t)
+ : ts(&buffer, WriteOnly),
+ type(t),
+ message_output(true)
+ {}
QTextStream ts;
QString buffer;
- int ref;
- QtMsgType type;
- bool space;
- bool message_output;
+ int ref = 1;
+ QtMsgType type = QtDebugMsg;
+ bool space = true;
+ bool noQuotes = false;
+ bool message_output = false;
+ int verbosity = DefaultVerbosity;
QMessageLogContext context;
-
- enum FormatFlag { // Note: Bits 29..31 are reserved for the verbose level introduced in 5.6.
- NoQuotes = 0x1
- };
-
- // ### Qt 6: unify with space, introduce own version member
- bool testFlag(FormatFlag flag) const { return (context.version > 1) ? (flags & flag) : false; }
- void setFlag(FormatFlag flag) { if (context.version > 1) { flags |= flag; } }
- void unsetFlag(FormatFlag flag) { if (context.version > 1) { flags &= ~flag; } }
- int verbosity() const
- { return context.version > 1 ? (flags >> VerbosityShift) & VerbosityMask : int(DefaultVerbosity); }
- void setVerbosity(int v)
- {
- if (context.version > 1) {
- flags &= ~(uint(VerbosityMask) << VerbosityShift);
- flags |= (v & VerbosityMask) << VerbosityShift;
- }
- }
- // added in 5.4
- int flags;
} *stream;
enum Latin1Content { ContainsBinary = 0, ContainsLatin1 };
- void putUcs4(uint ucs4);
- void putString(const QChar *begin, size_t length);
- void putByteArray(const char *begin, size_t length, Latin1Content content);
+ QT7_ONLY(Q_CORE_EXPORT) void putUcs4(uint ucs4);
+ QT7_ONLY(Q_CORE_EXPORT) void putString(const QChar *begin, size_t length);
+ QT7_ONLY(Q_CORE_EXPORT) void putByteArray(const char *begin, size_t length, Latin1Content content);
+ QT7_ONLY(Q_CORE_EXPORT) void putTimeUnit(qint64 num, qint64 den);
+ QT7_ONLY(Q_CORE_EXPORT) void putInt128(const void *i);
+ QT7_ONLY(Q_CORE_EXPORT) void putUInt128(const void *i);
public:
explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
explicit QDebug(QString *string) : stream(new Stream(string)) {}
explicit QDebug(QtMsgType t) : stream(new Stream(t)) {}
QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
- QDebug(QDebug &&other) noexcept : stream{qExchange(other.stream, nullptr)} {}
+ QDebug(QDebug &&other) noexcept : stream{std::exchange(other.stream, nullptr)} {}
inline QDebug &operator=(const QDebug &other);
- QDebug &operator=(QDebug &&other) noexcept
- { QDebug{std::move(other)}.swap(*this); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QDebug)
~QDebug();
- inline void swap(QDebug &other) noexcept { qSwap(stream, other.stream); }
+ void swap(QDebug &other) noexcept { qt_ptr_swap(stream, other.stream); }
- QDebug &resetFormat();
+ QT7_ONLY(Q_CORE_EXPORT) QDebug &resetFormat();
inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
inline QDebug &nospace() { stream->space = false; return *this; }
inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
- inline QDebug &verbosity(int verbosityLevel) { setVerbosity(verbosityLevel); return *this; }
- int verbosity() const { return stream->verbosity(); }
- void setVerbosity(int verbosityLevel) { stream->setVerbosity(verbosityLevel); }
+ inline QDebug &verbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; return *this; }
+ int verbosity() const { return stream->verbosity; }
+ void setVerbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; }
enum VerbosityLevel { MinimumVerbosity = 0, DefaultVerbosity = 2, MaximumVerbosity = 7 };
bool autoInsertSpaces() const { return stream->space; }
void setAutoInsertSpaces(bool b) { stream->space = b; }
- inline QDebug &quote() { stream->unsetFlag(Stream::NoQuotes); return *this; }
- inline QDebug &noquote() { stream->setFlag(Stream::NoQuotes); return *this; }
- inline QDebug &maybeQuote(char c = '"') { if (!(stream->testFlag(Stream::NoQuotes))) stream->ts << c; return *this; }
+ [[nodiscard]] bool quoteStrings() const noexcept { return !stream->noQuotes; }
+ void setQuoteStrings(bool b) { stream->noQuotes = !b; }
+
+ inline QDebug &quote() { stream->noQuotes = false; return *this; }
+ inline QDebug &noquote() { stream->noQuotes = true; return *this; }
+ inline QDebug &maybeQuote(char c = '"') { if (!stream->noQuotes) stream->ts << c; return *this; }
inline QDebug &operator<<(QChar t) { putUcs4(t.unicode()); return maybeSpace(); }
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
-#ifdef Q_COMPILER_UNICODE_STRINGS
- inline QDebug &operator<<(char16_t t) { return *this << QChar(ushort(t)); }
+ inline QDebug &operator<<(char16_t t) { return *this << QChar(t); }
inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
-#endif
inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
+ inline QDebug &operator<<(qfloat16 t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
-#if QT_STRINGVIEW_LEVEL < 2
- inline QDebug &operator<<(const QString & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
-#endif
+ inline QDebug &operator<<(const char16_t *t) { stream->ts << QStringView(t); return maybeSpace(); }
+ inline QDebug &operator<<(const QString & t) { putString(t.constData(), size_t(t.size())); return maybeSpace(); }
inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
- inline QDebug &operator<<(QLatin1String t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
+ inline QDebug &operator<<(QUtf8StringView s) { putByteArray(reinterpret_cast<const char*>(s.data()), s.size(), ContainsBinary); return maybeSpace(); }
+ inline QDebug &operator<<(QLatin1StringView t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
+ inline QDebug &operator<<(QByteArrayView t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
+ inline QDebug &operator<<(std::nullopt_t) { stream->ts << "nullopt"; return maybeSpace(); }
inline QDebug &operator<<(QTextStreamFunction f) {
stream->ts << f;
return *this;
@@ -171,21 +139,95 @@ public:
inline QDebug &operator<<(QTextStreamManipulator m)
{ stream->ts << m; return *this; }
- template <typename T>
- static QString toString(const T &object)
+#ifdef Q_QDOC
+ template <typename Char, typename...Args>
+ QDebug &operator<<(const std::basic_string<Char, Args...> &s);
+
+ template <typename Char, typename...Args>
+ QDebug &operator<<(std::basic_string_view<Char, Args...> s);
+#else
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char, Args...> &s)
+ { return *this << QUtf8StringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char, Args...> s)
+ { return *this << QUtf8StringView(s); }
+
+#ifdef __cpp_char8_t
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char8_t, Args...> &s)
+ { return *this << QUtf8StringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char8_t, Args...> s)
+ { return *this << QUtf8StringView(s); }
+#endif // __cpp_char8_t
+
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char16_t, Args...> &s)
+ { return *this << QStringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char16_t, Args...> s)
+ { return *this << QStringView(s); }
+
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<wchar_t, Args...> &s)
{
- QString buffer;
- QDebug stream(&buffer);
- stream.nospace() << object;
- return buffer;
+ if constexpr (sizeof(wchar_t) == 2)
+ return *this << QStringView(s);
+ else
+ return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
}
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<wchar_t, Args...> s)
+ {
+ if constexpr (sizeof(wchar_t) == 2)
+ return *this << QStringView(s);
+ else
+ return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
+ }
+
+ template <typename...Args>
+ QDebug &operator<<(const std::basic_string<char32_t, Args...> &s)
+ { return *this << QString::fromUcs4(s.data(), s.size()); }
+
+ template <typename...Args>
+ QDebug &operator<<(std::basic_string_view<char32_t, Args...> s)
+ { return *this << QString::fromUcs4(s.data(), s.size()); }
+#endif // !Q_QDOC
+
+ template <typename Rep, typename Period>
+ QDebug &operator<<(std::chrono::duration<Rep, Period> duration)
+ {
+ stream->ts << duration.count();
+ putTimeUnit(Period::num, Period::den);
+ return maybeSpace();
+ }
+
+#ifdef QT_SUPPORTS_INT128
+private:
+ // Constrained templates so they only match q(u)int128 without conversions.
+ // Also keeps these operators out of the ABI.
template <typename T>
- static QString toString(const T *object)
+ using if_qint128 = std::enable_if_t<std::is_same_v<T, qint128>, bool>;
+ template <typename T>
+ using if_quint128 = std::enable_if_t<std::is_same_v<T, quint128>, bool>;
+public:
+ template <typename T, if_qint128<T> = true>
+ QDebug &operator<<(T i128) { putInt128(&i128); return maybeSpace(); }
+ template <typename T, if_quint128<T> = true>
+ QDebug &operator<<(T u128) { putUInt128(&u128); return maybeSpace(); }
+#endif // QT_SUPPORTS_INT128
+
+ template <typename T>
+ static QString toString(T &&object)
{
QString buffer;
QDebug stream(&buffer);
- stream.nospace() << object;
+ stream.nospace() << std::forward<T>(object);
return buffer;
}
};
@@ -193,10 +235,12 @@ public:
Q_DECLARE_SHARED(QDebug)
class QDebugStateSaverPrivate;
-class Q_CORE_EXPORT QDebugStateSaver
+class QDebugStateSaver
{
public:
+ Q_NODISCARD_CTOR Q_CORE_EXPORT
QDebugStateSaver(QDebug &dbg);
+ Q_CORE_EXPORT
~QDebugStateSaver();
private:
Q_DISABLE_COPY(QDebugStateSaver)
@@ -261,62 +305,95 @@ inline QDebug printAssociativeContainer(QDebug debug, const char *which, const A
} // namespace QtPrivate
+template<typename ...T>
+using QDebugIfHasDebugStream =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, T>...>, QDebug>;
+
+template<typename Container, typename ...T>
+using QDebugIfHasDebugStreamContainer =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDebug, Container, T>...>, QDebug>;
+
+#ifndef Q_QDOC
+
template<typename T>
-inline QDebug operator<<(QDebug debug, const QList<T> &vec)
+inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec)
+{
+ return QtPrivate::printSequentialContainer(std::move(debug), "QList", vec);
+}
+
+template<typename T, qsizetype P>
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QVarLengthArray<T, P> &vec)
{
- return QtPrivate::printSequentialContainer(debug, "QList", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "QVarLengthArray", vec);
}
template <typename T, typename Alloc>
-inline QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
{
- return QtPrivate::printSequentialContainer(debug, "std::vector", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::vector", vec);
}
template <typename T, typename Alloc>
-inline QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec)
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::list<T, Alloc> &vec)
+{
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::list", vec);
+}
+
+template <typename T>
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, std::initializer_list<T> list)
{
- return QtPrivate::printSequentialContainer(debug, "std::list", vec);
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::initializer_list", list);
}
template <typename Key, typename T, typename Compare, typename Alloc>
-inline QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
+inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
{
- return QtPrivate::printSequentialContainer(debug, "std::map", map); // yes, sequential: *it is std::pair
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::map", map); // yes, sequential: *it is std::pair
}
template <typename Key, typename T, typename Compare, typename Alloc>
-inline QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
+inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
{
- return QtPrivate::printSequentialContainer(debug, "std::multimap", map); // yes, sequential: *it is std::pair
+ return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map); // yes, sequential: *it is std::pair
}
template <class Key, class T>
-inline QDebug operator<<(QDebug debug, const QMap<Key, T> &map)
+inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
{
- return QtPrivate::printAssociativeContainer(debug, "QMap", map);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QMap", map);
}
template <class Key, class T>
-inline QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map)
+inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
{
- return QtPrivate::printAssociativeContainer(debug, "QMultiMap", map);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiMap", map);
}
template <class Key, class T>
-inline QDebug operator<<(QDebug debug, const QHash<Key, T> &hash)
+inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
{
- return QtPrivate::printAssociativeContainer(debug, "QHash", hash);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QHash", hash);
}
template <class Key, class T>
-inline QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
+inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
{
- return QtPrivate::printAssociativeContainer(debug, "QMultiHash", hash);
+ return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash);
+}
+
+template <class T>
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::optional<T> &opt)
+{
+ const QDebugStateSaver saver(debug);
+ if (!opt)
+ debug.nospace() << std::nullopt;
+ else
+ debug.nospace() << "std::optional(" << *opt << ')';
+ return debug;
}
template <class T1, class T2>
-inline QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair)
+inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T1, T2> &pair)
{
const QDebugStateSaver saver(debug);
debug.nospace() << "std::pair(" << pair.first << ',' << pair.second << ')';
@@ -324,17 +401,17 @@ inline QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair)
}
template <typename T>
-inline QDebug operator<<(QDebug debug, const QSet<T> &set)
+inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set)
{
- return QtPrivate::printSequentialContainer(debug, "QSet", set);
+ return QtPrivate::printSequentialContainer(std::move(debug), "QSet", set);
}
template <class T>
-inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
+inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QContiguousCache<T> &cache)
{
const QDebugStateSaver saver(debug);
debug.nospace() << "QContiguousCache(";
- for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
+ for (qsizetype i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
debug << cache[i];
if (i != cache.lastIndex())
debug << ", ";
@@ -343,6 +420,48 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
return debug;
}
+#else
+template <class T>
+QDebug operator<<(QDebug debug, const QList<T> &list);
+
+template <class T, qsizetype P>
+QDebug operator<<(QDebug debug, const QVarLengthArray<T, P> &array);
+
+template <typename T, typename Alloc>
+QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec);
+
+template <typename T, typename Alloc>
+QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec);
+
+template <typename Key, typename T, typename Compare, typename Alloc>
+QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map);
+
+template <typename Key, typename T, typename Compare, typename Alloc>
+QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map);
+
+template <class Key, class T>
+QDebug operator<<(QDebug debug, const QMap<Key, T> &map);
+
+template <class Key, class T>
+QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map);
+
+template <class Key, class T>
+QDebug operator<<(QDebug debug, const QHash<Key, T> &hash);
+
+template <class Key, class T>
+QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash);
+
+template <typename T>
+QDebug operator<<(QDebug debug, const QSet<T> &set);
+
+template <class T1, class T2>
+QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair);
+
+template <typename T>
+QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache);
+
+#endif // Q_QDOC
+
template <class T>
inline QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr)
{
@@ -370,7 +489,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
debug.resetFormat();
debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
bool needSeparator = false;
- for (uint i = 0; i < sizeofT * 8; ++i) {
+ for (size_t i = 0; i < sizeofT * 8; ++i) {
if (value & (Int(1) << i)) {
if (needSeparator)
debug << '|';
@@ -383,7 +502,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
}
#if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC)
-Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, int value, const QMetaObject *meta, const char *name);
+Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, qint64 value, const QMetaObject *meta, const char *name);
Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name);
template<typename T>
@@ -392,7 +511,7 @@ operator<<(QDebug dbg, T value)
{
const QMetaObject *obj = qt_getEnumMetaObject(value);
const char *name = qt_getEnumName(value);
- return qt_QMetaEnum_debugOperator(dbg, typename QFlags<T>::Int(value), obj, name);
+ return qt_QMetaEnum_debugOperator(dbg, static_cast<typename std::underlying_type<T>::type>(value), obj, name);
}
template<typename T,
@@ -416,7 +535,7 @@ qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
{
const QMetaObject *obj = qt_getEnumMetaObject(T());
const char *name = qt_getEnumName(T());
- return qt_QMetaEnum_flagDebugOperator(debug, quint64(flags), obj, name);
+ return qt_QMetaEnum_flagDebugOperator(debug, flags.toInt(), obj, name);
}
template <class T>
@@ -441,7 +560,18 @@ inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
return qt_QMetaEnum_flagDebugOperator_helper(debug, flags);
}
-#ifdef Q_OS_MAC
+inline QDebug operator<<(QDebug debug, QKeyCombination combination)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "QKeyCombination("
+ << combination.keyboardModifiers()
+ << ", "
+ << combination.key()
+ << ")";
+ return debug;
+}
+
+#ifdef Q_OS_DARWIN
// We provide QDebug stream operators for commonly used Core Foundation
// and Core Graphics types, as well as NSObject. Additional CF/CG types
@@ -478,6 +608,7 @@ inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
QT_END_NAMESPACE
Q_FORWARD_DECLARE_CF_TYPE(CFString);
+struct objc_object;
Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_CF_TYPE)
QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_MUTABLE_CF_TYPE)
@@ -502,6 +633,10 @@ QT_BEGIN_NAMESPACE
}
// Defined in qcore_mac_objc.mm
+#if defined(__OBJC__)
+Q_CORE_EXPORT QDebug operator<<(QDebug, id);
+#endif
+Q_CORE_EXPORT QDebug operator<<(QDebug, objc_object *);
Q_CORE_EXPORT QDebug operator<<(QDebug, const NSObject *);
Q_CORE_EXPORT QDebug operator<<(QDebug, CFStringRef);
@@ -515,7 +650,7 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF
#undef QT_FORWARD_DECLARE_CG_TYPE
#undef QT_FORWARD_DECLARE_MUTABLE_CG_TYPE
-#endif // Q_OS_MAC
+#endif // Q_OS_DARWIN
QT_END_NAMESPACE
diff --git a/src/corelib/io/qdebug_p.h b/src/corelib/io/qdebug_p.h
index dcb906d156..810fc3b4b6 100644
--- a/src/corelib/io/qdebug_p.h
+++ b/src/corelib/io/qdebug_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDEBUG_P_H
#define QDEBUG_P_H
@@ -55,11 +19,14 @@
#include "QtCore/qdebug.h"
#include "QtCore/qmetaobject.h"
#include "QtCore/qflags.h"
+#include "QtCore/qbytearray.h"
QT_BEGIN_NAMESPACE
namespace QtDebugUtils {
+Q_CORE_EXPORT QByteArray toPrintable(const char *data, qint64 len, qsizetype maxSize);
+
// inline helpers for formatting basic classes.
template <class Point>
@@ -111,11 +78,10 @@ static inline void formatNonNullQEnum(QDebug &debug, const char *prefix, QEnum v
template <class Enum>
static inline void formatQFlags(QDebug &debug, const QFlags<Enum> &value)
{
- const QMetaObject *metaObject = qt_getEnumMetaObject(Enum());
- const QMetaEnum me = metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(Enum())));
+ const QMetaEnum me = QMetaEnum::fromType<QFlags<Enum>>();
const QDebugStateSaver saver(debug);
debug.noquote();
- debug << me.valueToKeys(value);
+ debug << me.valueToKeys(value.toInt());
}
template <class Enum>
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 8bf87eacae..9291201d88 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qdir.h"
@@ -45,7 +9,7 @@
#ifndef QT_NO_DEBUG_STREAM
#include "qdebug.h"
#endif
-#include "qdiriterator.h"
+#include "qdirlisting.h"
#include "qdatetime.h"
#include "qstring.h"
#if QT_CONFIG(regularexpression)
@@ -57,16 +21,20 @@
#include "qfilesystemengine_p.h"
#include <qstringbuilder.h>
-#ifdef QT_BUILD_CORE_LIB
-# include "qresource.h"
-# include "private/qcoreglobaldata_p.h"
+#ifndef QT_BOOTSTRAPPED
+# include <qcollator.h>
+# include "qreadwritelock.h"
+# include "qmutex.h"
#endif
#include <algorithm>
+#include <memory>
#include <stdlib.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if defined(Q_OS_WIN)
static QString driveSpec(const QString &path)
{
@@ -90,67 +58,65 @@ enum {
};
// Return the length of the root part of an absolute path, for use by cleanPath(), cd().
-static int rootLength(const QString &name, bool allowUncPaths)
+static qsizetype rootLength(QStringView name, bool allowUncPaths)
{
- const int len = name.length();
+ const qsizetype len = name.size();
// starts with double slash
- if (allowUncPaths && name.startsWith(QLatin1String("//"))) {
+ if (allowUncPaths && name.startsWith("//"_L1)) {
// Server name '//server/path' is part of the prefix.
- const int nextSlash = name.indexOf(QLatin1Char('/'), 2);
+ const qsizetype nextSlash = name.indexOf(u'/', 2);
return nextSlash >= 0 ? nextSlash + 1 : len;
}
#if defined(Q_OS_WIN)
- if (len >= 2 && name.at(1) == QLatin1Char(':')) {
+ if (len >= 2 && name.at(1) == u':') {
// Handle a possible drive letter
- return len > 2 && name.at(2) == QLatin1Char('/') ? 3 : 2;
+ return len > 2 && name.at(2) == u'/' ? 3 : 2;
}
#endif
- if (name.at(0) == QLatin1Char('/'))
+ if (name.at(0) == u'/')
return 1;
return 0;
}
//************* QDirPrivate
-QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_, QDir::SortFlags sort_, QDir::Filters filters_)
- : QSharedData()
- , fileListsInitialized(false)
- , nameFilters(nameFilters_)
- , sort(sort_)
- , filters(filters_)
+QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_,
+ QDir::SortFlags sort_, QDir::Filters filters_)
+ : QSharedData(), nameFilters(nameFilters_), sort(sort_), filters(filters_)
{
setPath(path.isEmpty() ? QString::fromLatin1(".") : path);
- bool empty = nameFilters.isEmpty();
- if (!empty) {
- empty = true;
- for (int i = 0; i < nameFilters.size(); ++i) {
- if (!nameFilters.at(i).isEmpty()) {
- empty = false;
- break;
- }
- }
- }
+ auto isEmpty = [](const auto &e) { return e.isEmpty(); };
+ const bool empty = std::all_of(nameFilters.cbegin(), nameFilters.cend(), isEmpty);
if (empty)
nameFilters = QStringList(QString::fromLatin1("*"));
}
QDirPrivate::QDirPrivate(const QDirPrivate &copy)
- : QSharedData(copy)
- , fileListsInitialized(false)
- , nameFilters(copy.nameFilters)
- , sort(copy.sort)
- , filters(copy.filters)
- , dirEntry(copy.dirEntry)
- , metaData(copy.metaData)
-{
+ : QSharedData(copy),
+ // mutex is not copied
+ nameFilters(copy.nameFilters),
+ sort(copy.sort),
+ filters(copy.filters),
+ // fileEngine is not copied
+ dirEntry(copy.dirEntry)
+{
+ QMutexLocker locker(&copy.fileCache.mutex);
+ fileCache.fileListsInitialized = copy.fileCache.fileListsInitialized.load();
+ fileCache.files = copy.fileCache.files;
+ fileCache.fileInfos = copy.fileCache.fileInfos;
+ fileCache.absoluteDirEntry = copy.fileCache.absoluteDirEntry;
+ fileCache.metaData = copy.fileCache.metaData;
}
bool QDirPrivate::exists() const
{
if (!fileEngine) {
- QFileSystemEngine::fillMetaData(dirEntry, metaData,
- QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); // always stat
- return metaData.exists() && metaData.isDirectory();
+ QMutexLocker locker(&fileCache.mutex);
+ QFileSystemEngine::fillMetaData(
+ dirEntry, fileCache.metaData,
+ QFileSystemMetaData::ExistsAttribute
+ | QFileSystemMetaData::DirectoryType); // always stat
+ return fileCache.metaData.exists() && fileCache.metaData.isDirectory();
}
const QAbstractFileEngine::FileFlags info =
fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
@@ -158,16 +124,16 @@ bool QDirPrivate::exists() const
| QAbstractFileEngine::Refresh);
if (!(info & QAbstractFileEngine::DirectoryType))
return false;
- return info & QAbstractFileEngine::ExistsFlag;
+ return info.testAnyFlag(QAbstractFileEngine::ExistsFlag);
}
// static
inline QChar QDirPrivate::getFilterSepChar(const QString &nameFilter)
{
- QChar sep(QLatin1Char(';'));
- int i = nameFilter.indexOf(sep, 0);
- if (i == -1 && nameFilter.indexOf(QLatin1Char(' '), 0) != -1)
- sep = QChar(QLatin1Char(' '));
+ QChar sep(u';');
+ qsizetype i = nameFilter.indexOf(sep, 0);
+ if (i == -1 && nameFilter.indexOf(u' ', 0) != -1)
+ sep = QChar(u' ');
return sep;
}
@@ -176,10 +142,8 @@ inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar se
{
if (sep.isNull())
sep = getFilterSepChar(nameFilter);
- const auto split = QStringView{nameFilter}.split(sep);
QStringList ret;
- ret.reserve(split.size());
- for (const auto &e : split)
+ for (auto e : qTokenize(nameFilter, sep))
ret.append(e.trimmed().toString());
return ret;
}
@@ -187,64 +151,97 @@ inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar se
inline void QDirPrivate::setPath(const QString &path)
{
QString p = QDir::fromNativeSeparators(path);
- if (p.endsWith(QLatin1Char('/'))
- && p.length() > 1
+ if (p.endsWith(u'/')
+ && p.size() > 1
#if defined(Q_OS_WIN)
&& (!(p.length() == 3 && p.at(1).unicode() == ':' && p.at(0).isLetter()))
#endif
) {
- p.truncate(p.length() - 1);
+ p.truncate(p.size() - 1);
}
-
dirEntry = QFileSystemEntry(p, QFileSystemEntry::FromInternalPath());
- metaData.clear();
- initFileEngine();
- clearFileLists();
- absoluteDirEntry = QFileSystemEntry();
+ clearCache(IncludingMetaData);
+ fileCache.absoluteDirEntry = QFileSystemEntry();
}
-inline void QDirPrivate::clearFileLists()
+inline QString QDirPrivate::resolveAbsoluteEntry() const
{
- fileListsInitialized = false;
- files.clear();
- fileInfos.clear();
-}
+ QMutexLocker locker(&fileCache.mutex);
+ if (!fileCache.absoluteDirEntry.isEmpty())
+ return fileCache.absoluteDirEntry.filePath();
-inline void QDirPrivate::resolveAbsoluteEntry() const
-{
- if (!absoluteDirEntry.isEmpty() || dirEntry.isEmpty())
- return;
+ if (dirEntry.isEmpty())
+ return dirEntry.filePath();
QString absoluteName;
if (!fileEngine) {
if (!dirEntry.isRelative() && dirEntry.isClean()) {
- absoluteDirEntry = dirEntry;
- return;
+ fileCache.absoluteDirEntry = dirEntry;
+ return dirEntry.filePath();
}
absoluteName = QFileSystemEngine::absoluteName(dirEntry).filePath();
} else {
absoluteName = fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
}
-
- absoluteDirEntry = QFileSystemEntry(QDir::cleanPath(absoluteName), QFileSystemEntry::FromInternalPath());
+ auto absoluteFileSystemEntry =
+ QFileSystemEntry(QDir::cleanPath(absoluteName), QFileSystemEntry::FromInternalPath());
+ fileCache.absoluteDirEntry = absoluteFileSystemEntry;
+ return absoluteFileSystemEntry.filePath();
}
/* For sorting */
struct QDirSortItem
{
+ QDirSortItem() = default;
+ QDirSortItem(const QFileInfo &fi, QDir::SortFlags sort)
+ : item(fi)
+ {
+ // A dir e.g. "dirA.bar" doesn't have actually have an extension/suffix, when
+ // sorting by type such "suffix" should be ignored but that would complicate
+ // the code and uses can change the behavior by setting DirsFirst/DirsLast
+ if (sort.testAnyFlag(QDir::Type))
+ suffix_cache = item.suffix();
+ }
+
mutable QString filename_cache;
- mutable QString suffix_cache;
+ QString suffix_cache;
QFileInfo item;
};
-
class QDirSortItemComparator
{
- int qt_cmp_si_sort_flags;
+ QDir::SortFlags qt_cmp_si_sort_flags;
+
+#ifndef QT_BOOTSTRAPPED
+ QCollator *collator = nullptr;
+#endif
public:
- QDirSortItemComparator(int flags) : qt_cmp_si_sort_flags(flags) {}
+#ifndef QT_BOOTSTRAPPED
+ QDirSortItemComparator(QDir::SortFlags flags, QCollator *coll = nullptr)
+ : qt_cmp_si_sort_flags(flags), collator(coll)
+ {
+ Q_ASSERT(!qt_cmp_si_sort_flags.testAnyFlag(QDir::LocaleAware) || collator);
+
+ if (collator && qt_cmp_si_sort_flags.testAnyFlag(QDir::IgnoreCase))
+ collator->setCaseSensitivity(Qt::CaseInsensitive);
+ }
+#else
+ QDirSortItemComparator(QDir::SortFlags flags)
+ : qt_cmp_si_sort_flags(flags)
+ {
+ }
+#endif
bool operator()(const QDirSortItem &, const QDirSortItem &) const;
+
+ int compareStrings(const QString &a, const QString &b, Qt::CaseSensitivity cs) const
+ {
+#ifndef QT_BOOTSTRAPPED
+ if (collator)
+ return collator->compare(a, b);
+#endif
+ return a.compare(b, cs);
+ }
};
bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortItem &n2) const
@@ -257,43 +254,25 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt
if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir()))
return !f1->item.isDir();
+ const bool ic = qt_cmp_si_sort_flags.testAnyFlag(QDir::IgnoreCase);
+ const auto qtcase = ic ? Qt::CaseInsensitive : Qt::CaseSensitive;
+
qint64 r = 0;
- int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask)
- | (qt_cmp_si_sort_flags & QDir::Type);
+ int sortBy = ((qt_cmp_si_sort_flags & QDir::SortByMask)
+ | (qt_cmp_si_sort_flags & QDir::Type)).toInt();
switch (sortBy) {
case QDir::Time: {
- QDateTime firstModified = f1->item.lastModified();
- QDateTime secondModified = f2->item.lastModified();
-
- // QDateTime by default will do all sorts of conversions on these to
- // find timezones, which is incredibly expensive. As we aren't
- // presenting these to the user, we don't care (at all) about the
- // local timezone, so force them to UTC to avoid that conversion.
- firstModified.setTimeSpec(Qt::UTC);
- secondModified.setTimeSpec(Qt::UTC);
-
+ const QDateTime firstModified = f1->item.lastModified(QTimeZone::UTC);
+ const QDateTime secondModified = f2->item.lastModified(QTimeZone::UTC);
r = firstModified.msecsTo(secondModified);
break;
}
case QDir::Size:
r = f2->item.size() - f1->item.size();
break;
- case QDir::Type:
- {
- bool ic = qt_cmp_si_sort_flags & QDir::IgnoreCase;
-
- if (f1->suffix_cache.isNull())
- f1->suffix_cache = ic ? f1->item.suffix().toLower()
- : f1->item.suffix();
- if (f2->suffix_cache.isNull())
- f2->suffix_cache = ic ? f2->item.suffix().toLower()
- : f2->item.suffix();
-
- r = qt_cmp_si_sort_flags & QDir::LocaleAware
- ? f1->suffix_cache.localeAwareCompare(f2->suffix_cache)
- : f1->suffix_cache.compare(f2->suffix_cache);
- }
+ case QDir::Type:
+ r = compareStrings(f1->suffix_cache, f2->suffix_cache, qtcase);
break;
default:
;
@@ -301,71 +280,89 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt
if (r == 0 && sortBy != QDir::Unsorted) {
// Still not sorted - sort by name
- bool ic = qt_cmp_si_sort_flags & QDir::IgnoreCase;
if (f1->filename_cache.isNull())
- f1->filename_cache = ic ? f1->item.fileName().toLower()
- : f1->item.fileName();
+ f1->filename_cache = f1->item.fileName();
if (f2->filename_cache.isNull())
- f2->filename_cache = ic ? f2->item.fileName().toLower()
- : f2->item.fileName();
+ f2->filename_cache = f2->item.fileName();
- r = qt_cmp_si_sort_flags & QDir::LocaleAware
- ? f1->filename_cache.localeAwareCompare(f2->filename_cache)
- : f1->filename_cache.compare(f2->filename_cache);
+ r = compareStrings(f1->filename_cache, f2->filename_cache, qtcase);
}
if (qt_cmp_si_sort_flags & QDir::Reversed)
return r > 0;
return r < 0;
}
-inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QFileInfoList &l,
+inline void QDirPrivate::sortFileList(QDir::SortFlags sort, const QFileInfoList &l,
QStringList *names, QFileInfoList *infos)
{
- // names and infos are always empty lists or 0 here
- int n = l.size();
- if (n > 0) {
- if (n == 1 || (sort & QDir::SortByMask) == QDir::Unsorted) {
- if (infos)
- *infos = l;
- if (names) {
- for (int i = 0; i < n; ++i)
- names->append(l.at(i).fileName());
- }
+ Q_ASSERT(names || infos);
+ Q_ASSERT(!infos || infos->isEmpty());
+ Q_ASSERT(!names || names->isEmpty());
+
+ const qsizetype n = l.size();
+ if (n == 0)
+ return;
+
+ if (n == 1 || (sort & QDir::SortByMask) == QDir::Unsorted) {
+ if (infos)
+ *infos = l;
+
+ if (names) {
+ for (const QFileInfo &fi : l)
+ names->append(fi.fileName());
+ }
+ } else {
+ QScopedArrayPointer<QDirSortItem> si(new QDirSortItem[n]);
+ for (qsizetype i = 0; i < n; ++i)
+ si[i] = QDirSortItem{l.at(i), sort};
+
+#ifndef QT_BOOTSTRAPPED
+ if (sort.testAnyFlag(QDir::LocaleAware)) {
+ QCollator coll;
+ std::sort(si.data(), si.data() + n, QDirSortItemComparator(sort, &coll));
} else {
- QScopedArrayPointer<QDirSortItem> si(new QDirSortItem[n]);
- for (int i = 0; i < n; ++i)
- si[i].item = l.at(i);
std::sort(si.data(), si.data() + n, QDirSortItemComparator(sort));
- // put them back in the list(s)
- if (infos) {
- for (int i = 0; i < n; ++i)
- infos->append(si[i].item);
- }
+ }
+#else
+ std::sort(si.data(), si.data() + n, QDirSortItemComparator(sort));
+#endif // QT_BOOTSTRAPPED
+
+ // put them back in the list(s)
+ for (qsizetype i = 0; i < n; ++i) {
+ auto &fileInfo = si[i].item;
+ if (infos)
+ infos->append(fileInfo);
if (names) {
- for (int i = 0; i < n; ++i)
- names->append(si[i].item.fileName());
+ const bool cached = !si[i].filename_cache.isNull();
+ names->append(cached ? si[i].filename_cache : fileInfo.fileName());
}
}
}
}
+
inline void QDirPrivate::initFileLists(const QDir &dir) const
{
- if (!fileListsInitialized) {
+ QMutexLocker locker(&fileCache.mutex);
+ if (!fileCache.fileListsInitialized) {
QFileInfoList l;
- QDirIterator it(dir);
- while (it.hasNext()) {
- it.next();
- l.append(it.fileInfo());
- }
- sortFileList(sort, l, &files, &fileInfos);
- fileListsInitialized = true;
+ for (const auto &dirEntry : QDirListing(dir))
+ l.emplace_back(dirEntry.fileInfo());
+
+ sortFileList(sort, l, &fileCache.files, &fileCache.fileInfos);
+ fileCache.fileListsInitialized = true;
}
}
-inline void QDirPrivate::initFileEngine()
+inline void QDirPrivate::clearCache(MetaDataClearing mode)
{
- fileEngine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData));
+ QMutexLocker locker(&fileCache.mutex);
+ if (mode == IncludingMetaData)
+ fileCache.metaData.clear();
+ fileCache.fileListsInitialized = false;
+ fileCache.files.clear();
+ fileCache.fileInfos.clear();
+ fileEngine = QFileSystemEngine::createLegacyEngine(dirEntry, fileCache.metaData);
}
/*!
@@ -377,6 +374,7 @@ inline void QDirPrivate::initFileEngine()
\ingroup shared
\reentrant
+ \compares equality
A QDir is used to manipulate path names, access information
regarding paths and files, and manipulate the underlying file
@@ -398,7 +396,7 @@ inline void QDirPrivate::initFileEngine()
\snippet code/src_corelib_io_qdir.cpp 0
On Windows, the second example above will be translated to
- \c{C:\Documents and Settings} when used to access files.
+ \c{C:\Users} when used to access files.
Examples of relative paths:
@@ -408,6 +406,9 @@ inline void QDirPrivate::initFileEngine()
a QDir is using a relative or an absolute file path. Call
makeAbsolute() to convert a relative QDir to an absolute one.
+ \note Paths starting with a colon (\e{:}) are always considered
+ absolute, as they denote a QResource.
+
\section1 Navigation and Directory Operations
A directory's path can be obtained with the path() function, and
@@ -529,8 +530,8 @@ inline void QDirPrivate::initFileEngine()
\snippet code/src_corelib_io_qdir.cpp 4
- (We could also use the static convenience function
- QFile::exists().)
+ (We could also use one of the static convenience functions
+ QFileInfo::exists() or QFile::exists().)
Traversing directories and reading a file:
@@ -541,7 +542,12 @@ inline void QDirPrivate::initFileEngine()
\snippet qdir-listfiles/main.cpp 0
- \sa QFileInfo, QFile, QFileDialog, QCoreApplication::applicationDirPath(), {Find Files Example}
+ \section1 Platform Specific Issues
+
+ \include android-content-uri-limitations.qdocinc
+
+ \sa QFileInfo, QFile, QFileDialog, QCoreApplication::applicationDirPath(),
+ {Fetch More Example}
*/
/*!
@@ -583,7 +589,7 @@ QDir::QDir(const QString &path) : d_ptr(new QDirPrivate(path))
directory). If \a nameFilter is an empty string, QDir uses the
name filter "*" (all files).
- Note that \a path need not exist.
+ \note \a path need not exist.
\sa exists(), setPath(), setNameFilters(), setFilter(), setSorting()
*/
@@ -645,7 +651,7 @@ void QDir::setPath(const QString &path)
*/
QString QDir::path() const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
return d->dirEntry.filePath();
}
@@ -659,9 +665,11 @@ QString QDir::path() const
*/
QString QDir::absolutePath() const
{
- const QDirPrivate* d = d_ptr.constData();
- d->resolveAbsoluteEntry();
- return d->absoluteDirEntry.filePath();
+ Q_D(const QDir);
+ if (!d->fileEngine)
+ return d->resolveAbsoluteEntry();
+
+ return d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
}
/*!
@@ -682,9 +690,11 @@ QString QDir::absolutePath() const
*/
QString QDir::canonicalPath() const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (!d->fileEngine) {
- QFileSystemEntry answer = QFileSystemEngine::canonicalName(d->dirEntry, d->metaData);
+ QMutexLocker locker(&d->fileCache.mutex);
+ QFileSystemEntry answer =
+ QFileSystemEngine::canonicalName(d->dirEntry, d->fileCache.metaData);
return answer.filePath();
}
return d->fileEngine->fileName(QAbstractFileEngine::CanonicalName);
@@ -703,29 +713,31 @@ QString QDir::canonicalPath() const
*/
QString QDir::dirName() const
{
- const QDirPrivate* d = d_ptr.constData();
- return d->dirEntry.fileName();
+ Q_D(const QDir);
+ if (!d_ptr->fileEngine)
+ return d->dirEntry.fileName();
+ return d->fileEngine->fileName(QAbstractFileEngine::BaseName);
}
#ifdef Q_OS_WIN
-static int drivePrefixLength(const QString &path)
+static qsizetype drivePrefixLength(QStringView path)
{
// Used to extract path's drive for use as prefix for an "absolute except for drive" path
- const int size = path.length();
- int drive = 2; // length of drive prefix
+ const qsizetype size = path.size();
+ qsizetype drive = 2; // length of drive prefix
if (size > 1 && path.at(1).unicode() == ':') {
if (Q_UNLIKELY(!path.at(0).isLetter()))
return 0;
- } else if (path.startsWith(QLatin1String("//"))) {
+ } else if (path.startsWith("//"_L1)) {
// UNC path; use its //server/share part as "drive" - it's as sane a
// thing as we can do.
- for (int i = 2; i-- > 0; ) { // Scan two "path fragments":
+ for (int i = 0 ; i < 2 ; ++i) { // Scan two "path fragments":
while (drive < size && path.at(drive).unicode() == '/')
drive++;
if (drive >= size) {
qWarning("Base directory starts with neither a drive nor a UNC share: %s",
- qUtf8Printable(QDir::toNativeSeparators(path)));
+ qUtf8Printable(QDir::toNativeSeparators(path.toString())));
return 0;
}
while (drive < size && path.at(drive).unicode() != '/')
@@ -749,7 +761,7 @@ static bool treatAsAbsolute(const QString &path)
// a colon in the path.
// FIXME: relies on virtual file-systems having colons in their prefixes.
// The case of an MS-absolute C:/... path happens to work either way.
- return (path.contains(QLatin1Char(':')) && QFileInfo(path).isAbsolute())
+ return (path.contains(u':') && QFileInfo(path).isAbsolute())
|| QFileSystemEntry(path).isAbsolute();
}
@@ -767,22 +779,22 @@ QString QDir::filePath(const QString &fileName) const
if (treatAsAbsolute(fileName))
return fileName;
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
QString ret = d->dirEntry.filePath();
if (fileName.isEmpty())
return ret;
#ifdef Q_OS_WIN
- if (fileName.startsWith(QLatin1Char('/')) || fileName.startsWith(QLatin1Char('\\'))) {
+ if (fileName.startsWith(u'/') || fileName.startsWith(u'\\')) {
// Handle the "absolute except for drive" case (i.e. \blah not c:\blah):
- const int drive = drivePrefixLength(ret);
+ const qsizetype drive = drivePrefixLength(ret);
return drive > 0 ? QStringView{ret}.left(drive) % fileName : fileName;
}
#endif // Q_OS_WIN
- if (ret.isEmpty() || ret.endsWith(QLatin1Char('/')))
+ if (ret.isEmpty() || ret.endsWith(u'/'))
return ret % fileName;
- return ret % QLatin1Char('/') % fileName;
+ return ret % u'/' % fileName;
}
/*!
@@ -798,16 +810,15 @@ QString QDir::absoluteFilePath(const QString &fileName) const
if (treatAsAbsolute(fileName))
return fileName;
- const QDirPrivate* d = d_ptr.constData();
- d->resolveAbsoluteEntry();
- const QString absoluteDirPath = d->absoluteDirEntry.filePath();
+ Q_D(const QDir);
+ QString absoluteDirPath = d->resolveAbsoluteEntry();
if (fileName.isEmpty())
return absoluteDirPath;
#ifdef Q_OS_WIN
// Handle the "absolute except for drive" case (i.e. \blah not c:\blah):
- if (fileName.startsWith(QLatin1Char('/')) || fileName.startsWith(QLatin1Char('\\'))) {
+ if (fileName.startsWith(u'/') || fileName.startsWith(u'\\')) {
// Combine absoluteDirPath's drive with fileName
- const int drive = drivePrefixLength(absoluteDirPath);
+ const qsizetype drive = drivePrefixLength(absoluteDirPath);
if (Q_LIKELY(drive))
return QStringView{absoluteDirPath}.left(drive) % fileName;
@@ -816,8 +827,8 @@ QString QDir::absoluteFilePath(const QString &fileName) const
return QString();
}
#endif // Q_OS_WIN
- if (!absoluteDirPath.endsWith(QLatin1Char('/')))
- return absoluteDirPath % QLatin1Char('/') % fileName;
+ if (!absoluteDirPath.endsWith(u'/'))
+ return absoluteDirPath % u'/' % fileName;
return absoluteDirPath % fileName;
}
@@ -847,9 +858,10 @@ QString QDir::relativeFilePath(const QString &fileName) const
}
if (fileDrive.toLower() != dirDrive.toLower()
- || (file.startsWith(QLatin1String("//"))
- && !dir.startsWith(QLatin1String("//"))))
+ || (file.startsWith("//"_L1)
+ && !dir.startsWith("//"_L1))) {
return file;
+ }
dir.remove(0, dirDrive.size());
if (!fileDriveMissing)
@@ -857,8 +869,8 @@ QString QDir::relativeFilePath(const QString &fileName) const
#endif
QString result;
- const auto dirElts = dir.tokenize(QLatin1Char('/'), Qt::SkipEmptyParts);
- const auto fileElts = file.tokenize(QLatin1Char('/'), Qt::SkipEmptyParts);
+ const auto dirElts = dir.tokenize(u'/', Qt::SkipEmptyParts);
+ const auto fileElts = file.tokenize(u'/', Qt::SkipEmptyParts);
const auto dend = dirElts.end();
const auto fend = fileElts.end();
@@ -881,20 +893,20 @@ QString QDir::relativeFilePath(const QString &fileName) const
}
while (dit != dend) {
- result += QLatin1String("../");
+ result += "../"_L1;
++dit;
}
if (fit != fend) {
while (fit != fend) {
result += *fit++;
- result += QLatin1Char('/');
+ result += u'/';
}
result.chop(1);
}
if (result.isEmpty())
- result = QLatin1String(".");
+ result = "."_L1;
return result;
}
@@ -916,16 +928,16 @@ QString QDir::relativeFilePath(const QString &fileName) const
QString QDir::toNativeSeparators(const QString &pathName)
{
#if defined(Q_OS_WIN)
- int i = pathName.indexOf(QLatin1Char('/'));
+ qsizetype i = pathName.indexOf(u'/');
if (i != -1) {
QString n(pathName);
QChar * const data = n.data();
- data[i++] = QLatin1Char('\\');
+ data[i++] = u'\\';
for (; i < n.length(); ++i) {
- if (data[i] == QLatin1Char('/'))
- data[i] = QLatin1Char('\\');
+ if (data[i] == u'/')
+ data[i] = u'\\';
}
return n;
@@ -949,28 +961,10 @@ QString QDir::toNativeSeparators(const QString &pathName)
QString QDir::fromNativeSeparators(const QString &pathName)
{
#if defined(Q_OS_WIN)
- int i = pathName.indexOf(QLatin1Char('\\'));
- if (i != -1) {
- QString n(pathName);
- if (n.startsWith(QLatin1String("\\\\?\\"))) {
- n.remove(0, 4);
- i = n.indexOf(QLatin1Char('\\'));
- if (i == -1)
- return n;
- }
-
- QChar * const data = n.data();
- data[i++] = QLatin1Char('/');
-
- for (; i < n.length(); ++i) {
- if (data[i] == QLatin1Char('\\'))
- data[i] = QLatin1Char('/');
- }
-
- return n;
- }
-#endif
+ return QFileSystemEntry::removeUncOrLongPathPrefix(pathName).replace(u'\\', u'/');
+#else
return pathName;
+#endif
}
static QString qt_cleanPath(const QString &path, bool *ok = nullptr);
@@ -991,19 +985,19 @@ bool QDir::cd(const QString &dirName)
// Don't detach just yet.
const QDirPrivate * const d = d_ptr.constData();
- if (dirName.isEmpty() || dirName == QLatin1String("."))
+ if (dirName.isEmpty() || dirName == u'.')
return true;
QString newPath;
if (isAbsolutePath(dirName)) {
newPath = qt_cleanPath(dirName);
} else {
newPath = d->dirEntry.filePath();
- if (!newPath.endsWith(QLatin1Char('/')))
- newPath += QLatin1Char('/');
+ if (!newPath.endsWith(u'/'))
+ newPath += u'/';
newPath += dirName;
- if (dirName.indexOf(QLatin1Char('/')) >= 0
- || dirName == QLatin1String("..")
- || d->dirEntry.filePath() == QLatin1String(".")) {
+ if (dirName.indexOf(u'/') >= 0
+ || dirName == ".."_L1
+ || d->dirEntry.filePath() == u'.') {
bool ok;
newPath = qt_cleanPath(newPath, &ok);
if (!ok)
@@ -1016,18 +1010,18 @@ bool QDir::cd(const QString &dirName)
while (dir.cdUp())
;
*/
- if (newPath.startsWith(QLatin1String(".."))) {
+ if (newPath.startsWith(".."_L1)) {
newPath = QFileInfo(newPath).absoluteFilePath();
}
}
}
- QScopedPointer<QDirPrivate> dir(new QDirPrivate(*d_ptr.constData()));
+ std::unique_ptr<QDirPrivate> dir(new QDirPrivate(*d_ptr.constData()));
dir->setPath(newPath);
if (!dir->exists())
return false;
- d_ptr = dir.take();
+ d_ptr = dir.release();
return true;
}
@@ -1039,6 +1033,9 @@ bool QDir::cd(const QString &dirName)
otherwise returns \c false. Note that the logical cdUp() operation is
not performed if the new directory does not exist.
+ \note On Android, this is not supported for content URIs. For more information,
+ see \l {Android: DocumentFile.getParentFile()}{DocumentFile.getParentFile()}.
+
\sa cd(), isReadable(), exists(), path()
*/
bool QDir::cdUp()
@@ -1051,7 +1048,7 @@ bool QDir::cdUp()
*/
QStringList QDir::nameFilters() const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
return d->nameFilters;
}
@@ -1060,8 +1057,7 @@ QStringList QDir::nameFilters() const
list of filters specified by \a nameFilters.
Each name filter is a wildcard (globbing) filter that understands
- \c{*} and \c{?} wildcards. See \l{QRegularExpression#Wildcard matching}
- {QRegularExpression Wildcard Matching}.
+ \c{*} and \c{?} wildcards. See \l{QRegularExpression::fromWildcard()}.
For example, the following code sets three name filters on a QDir
to ensure that only files with extensions typically used for C++
@@ -1073,39 +1069,22 @@ QStringList QDir::nameFilters() const
*/
void QDir::setNameFilters(const QStringList &nameFilters)
{
- QDirPrivate* d = d_ptr.data();
- d->initFileEngine();
- d->clearFileLists();
-
+ Q_D(QDir);
+ d->clearCache(QDirPrivate::KeepMetaData);
d->nameFilters = nameFilters;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Use QDir::addSearchPath() with a prefix instead.
+#ifndef QT_BOOTSTRAPPED
- Adds \a path to the search paths searched in to find resources
- that are not specified with an absolute path. The default search
- path is to search only in the root (\c{:/}).
-
- \sa {The Qt Resource System}
-*/
-void QDir::addResourceSearchPath(const QString &path)
-{
-#ifdef QT_BUILD_CORE_LIB
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- QResource::addSearchPath(path);
-QT_WARNING_POP
-#else
- Q_UNUSED(path)
-#endif
+namespace {
+struct DirSearchPaths {
+ mutable QReadWriteLock mutex;
+ QHash<QString, QStringList> paths;
+};
}
-#endif
-#ifdef QT_BUILD_CORE_LIB
+Q_GLOBAL_STATIC(DirSearchPaths, dirSearchPaths)
+
/*!
\since 4.3
@@ -1128,24 +1107,24 @@ QT_WARNING_POP
*/
void QDir::setSearchPaths(const QString &prefix, const QStringList &searchPaths)
{
- if (prefix.length() < 2) {
+ if (prefix.size() < 2) {
qWarning("QDir::setSearchPaths: Prefix must be longer than 1 character");
return;
}
- for (int i = 0; i < prefix.count(); ++i) {
- if (!prefix.at(i).isLetterOrNumber()) {
+ for (QChar ch : prefix) {
+ if (!ch.isLetterOrNumber()) {
qWarning("QDir::setSearchPaths: Prefix can only contain letters or numbers");
return;
}
}
- QWriteLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
- QMap<QString, QStringList> &paths = QCoreGlobalData::instance()->dirSearchPaths;
+ DirSearchPaths &conf = *dirSearchPaths;
+ const QWriteLocker lock(&conf.mutex);
if (searchPaths.isEmpty()) {
- paths.remove(prefix);
+ conf.paths.remove(prefix);
} else {
- paths.insert(prefix, searchPaths);
+ conf.paths.insert(prefix, searchPaths);
}
}
@@ -1161,8 +1140,9 @@ void QDir::addSearchPath(const QString &prefix, const QString &path)
if (path.isEmpty())
return;
- QWriteLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
- QCoreGlobalData::instance()->dirSearchPaths[prefix] += path;
+ DirSearchPaths &conf = *dirSearchPaths;
+ const QWriteLocker lock(&conf.mutex);
+ conf.paths[prefix] += path;
}
/*!
@@ -1174,18 +1154,22 @@ void QDir::addSearchPath(const QString &prefix, const QString &path)
*/
QStringList QDir::searchPaths(const QString &prefix)
{
- QReadLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
- return QCoreGlobalData::instance()->dirSearchPaths.value(prefix);
+ if (!dirSearchPaths.exists())
+ return QStringList();
+
+ const DirSearchPaths &conf = *dirSearchPaths;
+ const QReadLocker lock(&conf.mutex);
+ return conf.paths.value(prefix);
}
-#endif // QT_BUILD_CORE_LIB
+#endif // QT_BOOTSTRAPPED
/*!
Returns the value set by setFilter()
*/
QDir::Filters QDir::filter() const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
return d->filters;
}
@@ -1248,9 +1232,9 @@ QDir::Filters QDir::filter() const
files that the application can read, write, or execute, and symlinks
to such files/directories can be listed.
- To retrieve the permissons for a directory, use the
+ To retrieve the permissions for a directory, use the
entryInfoList() function to get the associated QFileInfo objects
- and then use the QFileInfo::permissons() to obtain the permissions
+ and then use the QFileInfo::permissions() to obtain the permissions
and ownership for each file.
*/
@@ -1264,10 +1248,8 @@ QDir::Filters QDir::filter() const
*/
void QDir::setFilter(Filters filters)
{
- QDirPrivate* d = d_ptr.data();
- d->initFileEngine();
- d->clearFileLists();
-
+ Q_D(QDir);
+ d->clearCache(QDirPrivate::KeepMetaData);
d->filters = filters;
}
@@ -1278,7 +1260,7 @@ void QDir::setFilter(Filters filters)
*/
QDir::SortFlags QDir::sorting() const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
return d->sort;
}
@@ -1311,6 +1293,7 @@ QDir::SortFlags QDir::sorting() const
after the directories, again in reverse order.
*/
+#ifndef QT_BOOTSTRAPPED
/*!
Sets the sort order used by entryList() and entryInfoList().
@@ -1321,10 +1304,8 @@ QDir::SortFlags QDir::sorting() const
*/
void QDir::setSorting(SortFlags sort)
{
- QDirPrivate* d = d_ptr.data();
- d->initFileEngine();
- d->clearFileLists();
-
+ Q_D(QDir);
+ d->clearCache(QDirPrivate::KeepMetaData);
d->sort = sort;
}
@@ -1333,13 +1314,16 @@ void QDir::setSorting(SortFlags sort)
Equivalent to entryList().count().
+ \note In Qt versions prior to 6.5, this function returned \c{uint}, not
+ \c{qsizetype}.
+
\sa operator[](), entryList()
*/
-uint QDir::count() const
+qsizetype QDir::count(QT6_IMPL_NEW_OVERLOAD) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
d->initFileLists(*this);
- return d->files.count();
+ return d->fileCache.files.size();
}
/*!
@@ -1347,13 +1331,15 @@ uint QDir::count() const
names. Equivalent to entryList().at(index).
\a pos must be a valid index position in the list (i.e., 0 <= pos < count()).
+ \note In Qt versions prior to 6.5, \a pos was an \c{int}, not \c{qsizetype}.
+
\sa count(), entryList()
*/
-QString QDir::operator[](int pos) const
+QString QDir::operator[](qsizetype pos) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
d->initFileLists(*this);
- return d->files[pos];
+ return d->fileCache.files[pos];
}
/*!
@@ -1377,7 +1363,7 @@ QString QDir::operator[](int pos) const
*/
QStringList QDir::entryList(Filters filters, SortFlags sort) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
return entryList(d->nameFilters, filters, sort);
}
@@ -1400,7 +1386,7 @@ QStringList QDir::entryList(Filters filters, SortFlags sort) const
*/
QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
return entryInfoList(d->nameFilters, filters, sort);
}
@@ -1423,26 +1409,34 @@ QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const
QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
SortFlags sort) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (filters == NoFilter)
filters = d->filters;
if (sort == NoSort)
sort = d->sort;
+ const bool needsSorting = (sort & QDir::SortByMask) != QDir::Unsorted;
+
if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
- d->initFileLists(*this);
- return d->files;
+ // Don't fill a QFileInfo cache if we just need names
+ if (needsSorting || d->fileCache.fileListsInitialized) {
+ d->initFileLists(*this);
+ return d->fileCache.files;
+ }
}
- QFileInfoList l;
- QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
- while (it.hasNext()) {
- it.next();
- l.append(it.fileInfo());
- }
+ QDirListing dirList(d->dirEntry.filePath(), nameFilters, filters);
QStringList ret;
- d->sortFileList(sort, l, &ret, nullptr);
+ if (needsSorting) {
+ QFileInfoList l;
+ for (const auto &dirEntry : dirList)
+ l.emplace_back(dirEntry.fileInfo());
+ d->sortFileList(sort, l, &ret, nullptr);
+ } else {
+ for (const auto &dirEntry : dirList)
+ ret.emplace_back(dirEntry.fileName());
+ }
return ret;
}
@@ -1465,7 +1459,7 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filters,
SortFlags sort) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (filters == NoFilter)
filters = d->filters;
@@ -1474,32 +1468,63 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter
if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
d->initFileLists(*this);
- return d->fileInfos;
+ return d->fileCache.fileInfos;
}
QFileInfoList l;
- QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
- while (it.hasNext()) {
- it.next();
- l.append(it.fileInfo());
- }
+ for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, filters))
+ l.emplace_back(dirEntry.fileInfo());
QFileInfoList ret;
d->sortFileList(sort, l, nullptr, &ret);
return ret;
}
+#endif // !QT_BOOTSTRAPPED
/*!
Creates a sub-directory called \a dirName.
Returns \c true on success; otherwise returns \c false.
- If the directory already exists when this function is called, it will return false.
+ If the directory already exists when this function is called, it will return \c false.
+
+ The permissions of the created directory are set to \a{permissions}.
+
+ On POSIX systems the permissions are influenced by the value of \c umask.
+
+ On Windows the permissions are emulated using ACLs. These ACLs may be in non-canonical
+ order when the group is granted less permissions than others. Files and directories with
+ such permissions will generate warnings when the Security tab of the Properties dialog
+ is opened. Granting the group all permissions granted to others avoids such warnings.
\sa rmdir()
+
+ \since 6.3
+*/
+bool QDir::mkdir(const QString &dirName, QFile::Permissions permissions) const
+{
+ Q_D(const QDir);
+
+ if (dirName.isEmpty()) {
+ qWarning("QDir::mkdir: Empty or null file name");
+ return false;
+ }
+
+ QString fn = filePath(dirName);
+ if (!d->fileEngine)
+ return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), false, permissions);
+ return d->fileEngine->mkdir(fn, false, permissions);
+}
+
+/*!
+ \overload
+ Creates a sub-directory called \a dirName with default permissions.
+
+ On POSIX systems the default is to grant all permissions allowed by \c umask.
+ On Windows, the new directory inherits its permissions from its parent directory.
*/
bool QDir::mkdir(const QString &dirName) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (dirName.isEmpty()) {
qWarning("QDir::mkdir: Empty or null file name");
@@ -1523,7 +1548,7 @@ bool QDir::mkdir(const QString &dirName) const
*/
bool QDir::rmdir(const QString &dirName) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (dirName.isEmpty()) {
qWarning("QDir::rmdir: Empty or null file name");
@@ -1551,7 +1576,7 @@ bool QDir::rmdir(const QString &dirName) const
*/
bool QDir::mkpath(const QString &dirPath) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (dirPath.isEmpty()) {
qWarning("QDir::mkpath: Empty or null file name");
@@ -1577,7 +1602,7 @@ bool QDir::mkpath(const QString &dirPath) const
*/
bool QDir::rmpath(const QString &dirPath) const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (dirPath.isEmpty()) {
qWarning("QDir::rmpath: Empty or null file name");
@@ -1590,6 +1615,7 @@ bool QDir::rmpath(const QString &dirPath) const
return d->fileEngine->rmdir(fn, true);
}
+#ifndef QT_BOOTSTRAPPED
/*!
\since 5.0
Removes the directory, including all its contents.
@@ -1603,7 +1629,7 @@ bool QDir::rmpath(const QString &dirPath) const
If the directory was already removed, the method returns \c true
(expected result already reached).
- Note: this function is meant for removing a small application-internal
+ \note This function is meant for removing a small application-internal
directory (such as a temporary directory), but not user-visible
directories. For user-visible operations, it is rather recommended
to report errors more precisely to the user, to offer solutions
@@ -1618,13 +1644,11 @@ bool QDir::removeRecursively()
bool success = true;
const QString dirPath = path();
// not empty -- we must empty it first
- QDirIterator di(dirPath, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
- while (di.hasNext()) {
- di.next();
- const QFileInfo& fi = di.fileInfo();
- const QString &filePath = di.filePath();
+ constexpr auto dirFilters = QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
+ for (const auto &dirEntry : QDirListing(dirPath, dirFilters)) {
+ const QString &filePath = dirEntry.filePath();
bool ok;
- if (fi.isDir() && !fi.isSymLink()) {
+ if (dirEntry.isDir() && !dirEntry.isSymLink()) {
ok = QDir(filePath).removeRecursively(); // recursive
} else {
ok = QFile::remove(filePath);
@@ -1644,6 +1668,7 @@ bool QDir::removeRecursively()
return success;
}
+#endif // !QT_BOOTSTRAPPED
/*!
Returns \c true if the directory is readable \e and we can open files
@@ -1656,13 +1681,15 @@ bool QDir::removeRecursively()
*/
bool QDir::isReadable() const
{
- const QDirPrivate* d = d_ptr.constData();
+ Q_D(const QDir);
if (!d->fileEngine) {
- if (!d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission))
- QFileSystemEngine::fillMetaData(d->dirEntry, d->metaData, QFileSystemMetaData::UserReadPermission);
-
- return (d->metaData.permissions() & QFile::ReadUser) != 0;
+ QMutexLocker locker(&d->fileCache.mutex);
+ if (!d->fileCache.metaData.hasFlags(QFileSystemMetaData::UserReadPermission)) {
+ QFileSystemEngine::fillMetaData(d->dirEntry, d->fileCache.metaData,
+ QFileSystemMetaData::UserReadPermission);
+ }
+ return d->fileCache.metaData.permissions().testAnyFlag(QFile::ReadUser);
}
const QAbstractFileEngine::FileFlags info =
@@ -1670,7 +1697,7 @@ bool QDir::isReadable() const
| QAbstractFileEngine::PermsMask);
if (!(info & QAbstractFileEngine::DirectoryType))
return false;
- return info & QAbstractFileEngine::ReadUserPerm;
+ return info.testAnyFlag(QAbstractFileEngine::ReadUserPerm);
}
/*!
@@ -1693,7 +1720,7 @@ bool QDir::exists() const
Returns \c true if the directory is the root directory; otherwise
returns \c false.
- Note: If the directory is a symbolic link to the root directory
+ \note If the directory is a symbolic link to the root directory
this function returns \c false. If you want to test for this use
canonicalPath(), e.g.
@@ -1705,7 +1732,7 @@ bool QDir::isRoot() const
{
if (!d_ptr->fileEngine)
return d_ptr->dirEntry.isRoot();
- return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::RootFlag;
+ return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask).testAnyFlag(QAbstractFileEngine::RootFlag);
}
/*!
@@ -1714,6 +1741,9 @@ bool QDir::isRoot() const
Returns \c true if the directory's path is absolute; otherwise
returns \c false. See isAbsolutePath().
+ \note Paths starting with a colon (\e{:}) are always considered
+ absolute, as they denote a QResource.
+
\sa isRelative(), makeAbsolute(), cleanPath()
*/
@@ -1723,7 +1753,10 @@ bool QDir::isRoot() const
Returns \c true if \a path is absolute; returns \c false if it is
relative.
- \sa isAbsolute(), isRelativePath(), makeAbsolute(), cleanPath()
+ \note Paths starting with a colon (\e{:}) are always considered
+ absolute, as they denote a QResource.
+
+ \sa isAbsolute(), isRelativePath(), makeAbsolute(), cleanPath(), QResource
*/
/*!
@@ -1731,6 +1764,9 @@ bool QDir::isRoot() const
false. (Under Unix a path is relative if it does not start with a
"/").
+ \note Paths starting with a colon (\e{:}) are always considered
+ absolute, as they denote a QResource.
+
\sa makeAbsolute(), isAbsolute(), isAbsolutePath(), cleanPath()
*/
bool QDir::isRelative() const
@@ -1750,8 +1786,8 @@ bool QDir::isRelative() const
*/
bool QDir::makeAbsolute()
{
- const QDirPrivate *d = d_ptr.constData();
- QScopedPointer<QDirPrivate> dir;
+ Q_D(const QDir);
+ std::unique_ptr<QDirPrivate> dir;
if (!!d->fileEngine) {
QString absolutePath = d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
if (QDir::isRelativePath(absolutePath))
@@ -1760,16 +1796,18 @@ bool QDir::makeAbsolute()
dir.reset(new QDirPrivate(*d_ptr.constData()));
dir->setPath(absolutePath);
} else { // native FS
- d->resolveAbsoluteEntry();
+ QString absoluteFilePath = d->resolveAbsoluteEntry();
dir.reset(new QDirPrivate(*d_ptr.constData()));
- dir->setPath(d->absoluteDirEntry.filePath());
+ dir->setPath(absoluteFilePath);
}
- d_ptr = dir.take(); // actually detach
+ d_ptr = dir.release(); // actually detach
return true;
}
/*!
- Returns \c true if directory \a dir and this directory have the same
+ \fn bool QDir::operator==(const QDir &lhs, const QDir &rhs)
+
+ Returns \c true if directory \a lhs and directory \a rhs have the same
path and their sort and filter settings are the same; otherwise
returns \c false.
@@ -1777,10 +1815,10 @@ bool QDir::makeAbsolute()
\snippet code/src_corelib_io_qdir.cpp 10
*/
-bool QDir::operator==(const QDir &dir) const
+bool comparesEqual(const QDir &lhs, const QDir &rhs)
{
- const QDirPrivate *d = d_ptr.constData();
- const QDirPrivate *other = dir.d_ptr.constData();
+ const QDirPrivate *d = lhs.d_ptr.constData();
+ const QDirPrivate *other = rhs.d_ptr.constData();
if (d == other)
return true;
@@ -1804,18 +1842,18 @@ bool QDir::operator==(const QDir &dir) const
if (d->dirEntry.filePath() == other->dirEntry.filePath())
return true;
- if (exists()) {
- if (!dir.exists())
+ if (lhs.exists()) {
+ if (!rhs.exists())
return false; //can't be equal if only one exists
// Both exist, fallback to expensive canonical path computation
- return canonicalPath().compare(dir.canonicalPath(), sensitive) == 0;
+ return lhs.canonicalPath().compare(rhs.canonicalPath(), sensitive) == 0;
} else {
- if (dir.exists())
+ if (rhs.exists())
return false; //can't be equal if only one exists
// Neither exists, compare absolute paths rather than canonical (which would be empty strings)
- d->resolveAbsoluteEntry();
- other->resolveAbsoluteEntry();
- return d->absoluteDirEntry.filePath().compare(other->absoluteDirEntry.filePath(), sensitive) == 0;
+ QString thisFilePath = d->resolveAbsoluteEntry();
+ QString otherFilePath = other->resolveAbsoluteEntry();
+ return thisFilePath.compare(otherFilePath, sensitive) == 0;
}
}
return false;
@@ -1831,22 +1869,6 @@ QDir &QDir::operator=(const QDir &dir)
return *this;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \overload
- \obsolete
-
- Sets the directory path to the given \a path.
-
- Use setPath() instead.
-*/
-QDir &QDir::operator=(const QString &path)
-{
- d_ptr->setPath(path);
- return *this;
-}
-#endif
-
/*!
\fn void QDir::swap(QDir &other)
\since 5.0
@@ -1856,11 +1878,10 @@ QDir &QDir::operator=(const QString &path)
*/
/*!
- \fn bool QDir::operator!=(const QDir &dir) const
+ \fn bool QDir::operator!=(const QDir &lhs, const QDir &rhs)
- Returns \c true if directory \a dir and this directory have different
- paths or different sort or filter settings; otherwise returns
- false.
+ Returns \c true if directory \a lhs and directory \a rhs have different
+ paths or different sort or filter settings; otherwise returns \c false.
Example:
@@ -1927,9 +1948,10 @@ bool QDir::exists(const QString &name) const
qWarning("QDir::exists: Empty or null file name");
return false;
}
- return QFile::exists(filePath(name));
+ return QFileInfo::exists(filePath(name));
}
+#ifndef QT_BOOTSTRAPPED
/*!
Returns whether the directory is empty.
@@ -1945,16 +1967,18 @@ bool QDir::exists(const QString &name) const
*/
bool QDir::isEmpty(Filters filters) const
{
- const auto d = d_ptr.constData();
- QDirIterator it(d->dirEntry.filePath(), d->nameFilters, filters);
- return !it.hasNext();
+ Q_D(const QDir);
+ QDirListing dirList(d->dirEntry.filePath(), d->nameFilters, filters);
+ return dirList.cbegin() == dirList.cend();
}
+#endif // !QT_BOOTSTRAPPED
/*!
Returns a list of the root directories on this system.
On Windows this returns a list of QFileInfo objects containing "C:/",
- "D:/", etc. On other operating systems, it returns a list containing
+ "D:/", etc. This does not return drives with ejectable media that are empty.
+ On other operating systems, it returns a list containing
just one root directory (i.e. "/").
\sa root(), rootPath()
@@ -1969,6 +1993,8 @@ QFileInfoList QDir::drives()
}
/*!
+ \fn QChar QDir::separator()
+
Returns the native directory separator: "/" under Unix
and "\\" under Windows.
@@ -1980,14 +2006,6 @@ QFileInfoList QDir::drives()
\sa listSeparator()
*/
-QChar QDir::separator()
-{
-#if defined(Q_OS_WIN)
- return QLatin1Char('\\');
-#else
- return QLatin1Char('/');
-#endif
-}
/*!
\fn QDir::listSeparator()
@@ -2004,6 +2022,8 @@ QChar QDir::separator()
Returns \c true if the directory was successfully changed; otherwise
returns \c false.
+ \snippet code/src_corelib_io_qdir.cpp 16
+
\sa current(), currentPath(), home(), root(), temp()
*/
bool QDir::setCurrent(const QString &path)
@@ -2148,8 +2168,7 @@ QString QDir::rootPath()
patterns in the list of \a filters; otherwise returns \c false. The
matching is case insensitive.
- \sa {QRegularExpression#Wildcard matching}{QRegularExpression Wildcard Matching},
- entryList(), entryInfoList()
+ \sa QRegularExpression::fromWildcard(), entryList(), entryInfoList()
*/
bool QDir::match(const QStringList &filters, const QString &fileName)
{
@@ -2168,8 +2187,7 @@ bool QDir::match(const QStringList &filters, const QString &fileName)
contain multiple patterns separated by spaces or semicolons.
The matching is case insensitive.
- \sa {QRegularExpression#Wildcard matching}{QRegularExpression Wildcard Matching},
- entryList(), entryInfoList()
+ \sa QRegularExpression::fromWildcard(), entryList(), entryInfoList()
*/
bool QDir::match(const QString &filter, const QString &fileName)
{
@@ -2187,9 +2205,9 @@ bool QDir::match(const QString &filter, const QString &fileName)
*/
QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormalizations flags, bool *ok)
{
- const bool allowUncPaths = QDirPrivate::AllowUncPaths & flags;
- const bool isRemote = QDirPrivate::RemotePath & flags;
- const int len = name.length();
+ const bool allowUncPaths = flags.testAnyFlag(QDirPrivate::AllowUncPaths);
+ const bool isRemote = flags.testAnyFlag(QDirPrivate::RemotePath);
+ const qsizetype len = name.size();
if (ok)
*ok = false;
@@ -2197,15 +2215,15 @@ QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormaliza
if (len == 0)
return name;
- int i = len - 1;
+ qsizetype i = len - 1;
QVarLengthArray<char16_t> outVector(len);
- int used = len;
+ qsizetype used = len;
char16_t *out = outVector.data();
- const ushort *p = name.utf16();
- const ushort *prefix = p;
- int up = 0;
+ const char16_t *p = reinterpret_cast<const char16_t *>(name.data());
+ const char16_t *prefix = p;
+ qsizetype up = 0;
- const int prefixLength = rootLength(name, allowUncPaths);
+ const qsizetype prefixLength = rootLength(name, allowUncPaths);
p += prefixLength;
i -= prefixLength;
@@ -2216,10 +2234,10 @@ QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormaliza
--i;
}
- auto isDot = [](const ushort *p, int i) {
+ auto isDot = [](const char16_t *p, qsizetype i) {
return i > 1 && p[i - 1] == '.' && p[i - 2] == '/';
};
- auto isDotDot = [](const ushort *p, int i) {
+ auto isDotDot = [](const char16_t *p, qsizetype i) {
return i > 2 && p[i - 1] == '.' && p[i - 2] == '.' && p[i - 3] == '/';
};
@@ -2318,11 +2336,11 @@ QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormaliza
if (prefixLength) {
if (!isEmpty && out[used] == '/') {
- // Eventhough there is a prefix the out string is a slash. This happens, if the input
+ // Even though there is a prefix the out string is a slash. This happens, if the input
// string only consists of a prefix followed by one or more slashes. Just skip the slash.
++used;
}
- for (int i = prefixLength - 1; i >= 0; --i)
+ for (qsizetype i = prefixLength - 1; i >= 0; --i)
out[--used] = prefix[i];
} else {
if (isEmpty) {
@@ -2340,29 +2358,23 @@ QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormaliza
// If path was not modified return the original value
if (used == 0)
return name;
- return QString::fromUtf16(out + used, len - used);
+ return QStringView(out + used, len - used).toString();
}
static QString qt_cleanPath(const QString &path, bool *ok)
{
- if (path.isEmpty())
+ if (path.isEmpty()) {
+ Q_ASSERT(!ok); // The only caller passing ok knows its path is non-empty
return path;
- QString name = path;
-#if defined (Q_OS_WIN)
- if (name.startsWith(QLatin1String("\\\\?\\")))
- name.remove(0, 4);
-#endif
-
- QChar dir_separator = QDir::separator();
- if (dir_separator != QLatin1Char('/'))
- name.replace(dir_separator, QLatin1Char('/'));
+ }
+ QString name = QDir::fromNativeSeparators(path);
QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths ? QDirPrivate::AllowUncPaths : QDirPrivate::DefaultNormalization, ok);
// Strip away last slash except for root directories
- if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
+ if (ret.size() > 1 && ret.endsWith(u'/')) {
#if defined (Q_OS_WIN)
- if (!(ret.length() == 3 && ret.at(1) == QLatin1Char(':')))
+ if (!(ret.length() == 3 && ret.at(1) == u':'))
#endif
ret.chop(1);
}
@@ -2391,6 +2403,9 @@ QString QDir::cleanPath(const QString &path)
Returns \c true if \a path is relative; returns \c false if it is
absolute.
+ \note Paths starting with a colon (\e{:}) are always considered
+ absolute, as they denote a QResource.
+
\sa isRelative(), isAbsolutePath(), makeAbsolute()
*/
bool QDir::isRelativePath(const QString &path)
@@ -2403,10 +2418,8 @@ bool QDir::isRelativePath(const QString &path)
*/
void QDir::refresh() const
{
- QDirPrivate *d = const_cast<QDir*>(this)->d_ptr.data();
- d->metaData.clear();
- d->initFileEngine();
- d->clearFileLists();
+ QDirPrivate *d = const_cast<QDir *>(this)->d_func();
+ d->clearCache(QDirPrivate::IncludingMetaData);
}
/*!
@@ -2429,59 +2442,6 @@ QStringList QDir::nameFiltersFromString(const QString &nameFilter)
return QDirPrivate::splitFilters(nameFilter);
}
-/*!
- \macro void Q_INIT_RESOURCE(name)
- \relates QDir
-
- Initializes the resources specified by the \c .qrc file with the
- specified base \a name. Normally, when resources are built as part
- of the application, the resources are loaded automatically at
- startup. The Q_INIT_RESOURCE() macro is necessary on some platforms
- for resources stored in a static library.
-
- For example, if your application's resources are listed in a file
- called \c myapp.qrc, you can ensure that the resources are
- initialized at startup by adding this line to your \c main()
- function:
-
- \snippet code/src_corelib_io_qdir.cpp 13
-
- If the file name contains characters that cannot be part of a valid C++ function name
- (such as '-'), they have to be replaced by the underscore character ('_').
-
- Note: This macro cannot be used in a namespace. It should be called from
- main(). If that is not possible, the following workaround can be used
- to init the resource \c myapp from the function \c{MyNamespace::myFunction}:
-
- \snippet code/src_corelib_io_qdir.cpp 14
-
- \sa Q_CLEANUP_RESOURCE(), {The Qt Resource System}
-*/
-
-/*!
- \since 4.1
- \macro void Q_CLEANUP_RESOURCE(name)
- \relates QDir
-
- Unloads the resources specified by the \c .qrc file with the base
- name \a name.
-
- Normally, Qt resources are unloaded automatically when the
- application terminates, but if the resources are located in a
- plugin that is being unloaded, call Q_CLEANUP_RESOURCE() to force
- removal of your resources.
-
- Note: This macro cannot be used in a namespace. Please see the
- Q_INIT_RESOURCE documentation for a workaround.
-
- Example:
-
- \snippet code/src_corelib_io_qdir.cpp 15
-
- \sa Q_INIT_RESOURCE(), {The Qt Resource System}
-*/
-
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, QDir::Filters filters)
{
@@ -2489,25 +2449,25 @@ QDebug operator<<(QDebug debug, QDir::Filters filters)
debug.resetFormat();
QStringList flags;
if (filters == QDir::NoFilter) {
- flags << QLatin1String("NoFilter");
+ flags << "NoFilter"_L1;
} else {
- if (filters & QDir::Dirs) flags << QLatin1String("Dirs");
- if (filters & QDir::AllDirs) flags << QLatin1String("AllDirs");
- if (filters & QDir::Files) flags << QLatin1String("Files");
- if (filters & QDir::Drives) flags << QLatin1String("Drives");
- if (filters & QDir::NoSymLinks) flags << QLatin1String("NoSymLinks");
- if (filters & QDir::NoDot) flags << QLatin1String("NoDot");
- if (filters & QDir::NoDotDot) flags << QLatin1String("NoDotDot");
- if ((filters & QDir::AllEntries) == QDir::AllEntries) flags << QLatin1String("AllEntries");
- if (filters & QDir::Readable) flags << QLatin1String("Readable");
- if (filters & QDir::Writable) flags << QLatin1String("Writable");
- if (filters & QDir::Executable) flags << QLatin1String("Executable");
- if (filters & QDir::Modified) flags << QLatin1String("Modified");
- if (filters & QDir::Hidden) flags << QLatin1String("Hidden");
- if (filters & QDir::System) flags << QLatin1String("System");
- if (filters & QDir::CaseSensitive) flags << QLatin1String("CaseSensitive");
+ if (filters & QDir::Dirs) flags << "Dirs"_L1;
+ if (filters & QDir::AllDirs) flags << "AllDirs"_L1;
+ if (filters & QDir::Files) flags << "Files"_L1;
+ if (filters & QDir::Drives) flags << "Drives"_L1;
+ if (filters & QDir::NoSymLinks) flags << "NoSymLinks"_L1;
+ if (filters & QDir::NoDot) flags << "NoDot"_L1;
+ if (filters & QDir::NoDotDot) flags << "NoDotDot"_L1;
+ if ((filters & QDir::AllEntries) == QDir::AllEntries) flags << "AllEntries"_L1;
+ if (filters & QDir::Readable) flags << "Readable"_L1;
+ if (filters & QDir::Writable) flags << "Writable"_L1;
+ if (filters & QDir::Executable) flags << "Executable"_L1;
+ if (filters & QDir::Modified) flags << "Modified"_L1;
+ if (filters & QDir::Hidden) flags << "Hidden"_L1;
+ if (filters & QDir::System) flags << "System"_L1;
+ if (filters & QDir::CaseSensitive) flags << "CaseSensitive"_L1;
}
- debug.noquote() << "QDir::Filters(" << flags.join(QLatin1Char('|')) << ')';
+ debug.noquote() << "QDir::Filters(" << flags.join(u'|') << ')';
return debug;
}
@@ -2519,18 +2479,18 @@ static QDebug operator<<(QDebug debug, QDir::SortFlags sorting)
debug << "QDir::SortFlags(NoSort)";
} else {
QString type;
- if ((sorting & 3) == QDir::Name) type = QLatin1String("Name");
- if ((sorting & 3) == QDir::Time) type = QLatin1String("Time");
- if ((sorting & 3) == QDir::Size) type = QLatin1String("Size");
- if ((sorting & 3) == QDir::Unsorted) type = QLatin1String("Unsorted");
+ if ((sorting & QDir::SortByMask) == QDir::Name) type = "Name"_L1;
+ if ((sorting & QDir::SortByMask) == QDir::Time) type = "Time"_L1;
+ if ((sorting & QDir::SortByMask) == QDir::Size) type = "Size"_L1;
+ if ((sorting & QDir::SortByMask) == QDir::Unsorted) type = "Unsorted"_L1;
QStringList flags;
- if (sorting & QDir::DirsFirst) flags << QLatin1String("DirsFirst");
- if (sorting & QDir::DirsLast) flags << QLatin1String("DirsLast");
- if (sorting & QDir::IgnoreCase) flags << QLatin1String("IgnoreCase");
- if (sorting & QDir::LocaleAware) flags << QLatin1String("LocaleAware");
- if (sorting & QDir::Type) flags << QLatin1String("Type");
- debug.noquote() << "QDir::SortFlags(" << type << '|' << flags.join(QLatin1Char('|')) << ')';
+ if (sorting & QDir::DirsFirst) flags << "DirsFirst"_L1;
+ if (sorting & QDir::DirsLast) flags << "DirsLast"_L1;
+ if (sorting & QDir::IgnoreCase) flags << "IgnoreCase"_L1;
+ if (sorting & QDir::LocaleAware) flags << "LocaleAware"_L1;
+ if (sorting & QDir::Type) flags << "Type"_L1;
+ debug.noquote() << "QDir::SortFlags(" << type << '|' << flags.join(u'|') << ')';
}
return debug;
}
@@ -2540,7 +2500,7 @@ QDebug operator<<(QDebug debug, const QDir &dir)
QDebugStateSaver save(debug);
debug.resetFormat();
debug << "QDir(" << dir.path() << ", nameFilters = {"
- << dir.nameFilters().join(QLatin1Char(','))
+ << dir.nameFilters().join(u',')
<< "}, "
<< dir.sorting()
<< ','
@@ -2578,7 +2538,7 @@ QDebug operator<<(QDebug debug, const QDir &dir)
directory). If \a nameFilter is an empty string, QDir uses the
name filter "*" (all files).
- Note that \a path need not exist.
+ \note \a path need not exist.
\sa exists(), setPath(), setNameFilters(), setFilter(), setSorting()
*/
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index f0dda73ebb..53c0900f95 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDIR_H
#define QDIR_H
+#include <QtCore/qcompare.h>
#include <QtCore/qstring.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
@@ -102,7 +67,7 @@ public:
QDir(const QString &path = QString());
QDir(const QString &path, const QString &nameFilter,
SortFlags sort = SortFlags(Name | IgnoreCase), Filters filter = AllEntries);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QDir(const std::filesystem::path &path);
QDir(const std::filesystem::path &path, const QString &nameFilter,
SortFlags sort = SortFlags(Name | IgnoreCase), Filters filter = AllEntries);
@@ -121,17 +86,13 @@ public:
~QDir();
QDir &operator=(const QDir &);
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QDir::setPath() instead")
- QDir &operator=(const QString &path);
-#endif
- QDir &operator=(QDir &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QDir)
void swap(QDir &other) noexcept
- { qSwap(d_ptr, other.d_ptr); }
+ { d_ptr.swap(other.d_ptr); }
void setPath(const QString &path);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
void setPath(const std::filesystem::path &path);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
@@ -143,7 +104,7 @@ public:
QString path() const;
QString absolutePath() const;
QString canonicalPath() const;
-#if QT_CONFIG(cxx17_filesystem)
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
std::filesystem::path filesystemPath() const
{ return QtPrivate::toFilesystemPath(path()); }
std::filesystem::path filesystemAbsolutePath() const
@@ -152,14 +113,10 @@ public:
{ return QtPrivate::toFilesystemPath(canonicalPath()); }
#endif // QT_CONFIG(cxx17_filesystem)
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QDir::addSearchPath() instead")
- static void addResourceSearchPath(const QString &path);
-#endif
-
+#ifndef QT_BOOTSTRAPPED
static void setSearchPaths(const QString &prefix, const QStringList &searchPaths);
static void addSearchPath(const QString &prefix, const QString &path);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
static void addSearchPath(const QString &prefix, const std::filesystem::path &path);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
@@ -169,6 +126,7 @@ public:
}
#endif // QT_CONFIG(cxx17_filesystem)
static QStringList searchPaths(const QString &prefix);
+#endif // QT_BOOTSTRAPPED
QString dirName() const;
QString filePath(const QString &fileName) const;
@@ -189,10 +147,16 @@ public:
SortFlags sorting() const;
void setSorting(SortFlags sort);
+#if QT_CORE_REMOVED_SINCE(6, 5)
uint count() const;
+#endif
+ qsizetype count(QT6_DECL_NEW_OVERLOAD) const;
bool isEmpty(Filters filters = Filters(AllEntries | NoDotAndDotDot)) const;
+#if QT_CORE_REMOVED_SINCE(6, 5) && QT_POINTER_SIZE != 4
QString operator[](int) const;
+#endif
+ QString operator[](qsizetype) const;
static QStringList nameFiltersFromString(const QString &nameFilter);
@@ -205,6 +169,7 @@ public:
SortFlags sort = NoSort) const;
bool mkdir(const QString &dirName) const;
+ bool mkdir(const QString &dirName, QFile::Permissions permissions) const;
bool rmdir(const QString &dirName) const;
bool mkpath(const QString &dirPath) const;
bool rmpath(const QString &dirPath) const;
@@ -221,8 +186,10 @@ public:
inline bool isAbsolute() const { return !isRelative(); }
bool makeAbsolute();
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QDir &dir) const;
- inline bool operator!=(const QDir &dir) const { return !operator==(dir); }
+ inline bool operator!=(const QDir &dir) const { return !operator==(dir); }
+#endif
bool remove(const QString &fileName);
bool rename(const QString &oldName, const QString &newName);
@@ -230,16 +197,23 @@ public:
static QFileInfoList drives();
- Q_DECL_CONSTEXPR static inline QChar listSeparator() noexcept
+ constexpr static inline QChar listSeparator() noexcept
{
#if defined(Q_OS_WIN)
- return QLatin1Char(';');
+ return u';';
#else
- return QLatin1Char(':');
+ return u':';
#endif
}
- static QChar separator(); // ### Qt6: Make it inline
+ static QChar separator()
+ {
+#if defined(Q_OS_WIN)
+ return u'\\';
+#else
+ return u'/';
+#endif
+ }
static bool setCurrent(const QString &path);
static inline QDir current() { return QDir(currentPath()); }
@@ -266,14 +240,13 @@ protected:
QSharedDataPointer<QDirPrivate> d_ptr;
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QDir &lhs, const QDir &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QDir)
friend class QDirIterator;
+ friend class QDirListing;
// Q_DECLARE_PRIVATE equivalent for shared data pointers
- QDirPrivate* d_func();
- inline const QDirPrivate* d_func() const
- {
- return d_ptr.constData();
- }
-
+ QDirPrivate *d_func();
+ const QDirPrivate *d_func() const { return d_ptr.constData(); }
};
Q_DECLARE_SHARED(QDir)
diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h
index af105de8db..7dce69c195 100644
--- a/src/corelib/io/qdir_p.h
+++ b/src/corelib/io/qdir_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDIR_P_H
#define QDIR_P_H
@@ -54,6 +18,8 @@
#include "qfilesystementry_p.h"
#include "qfilesystemmetadata_p.h"
+#include <QtCore/qmutex.h>
+
#include <memory>
QT_BEGIN_NAMESPACE
@@ -73,14 +39,13 @@ public:
QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
QDir::Filters filters_ = QDir::AllEntries);
- explicit QDirPrivate(const QDirPrivate &copy);
+ explicit QDirPrivate(const QDirPrivate &copy); // Copies everything except mutex and fileEngine
bool exists() const;
- void initFileEngine();
void initFileLists(const QDir &dir) const;
- static void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *);
+ static void sortFileList(QDir::SortFlags, const QFileInfoList &, QStringList *, QFileInfoList *);
static inline QChar getFilterSepChar(const QString &nameFilter);
@@ -88,13 +53,10 @@ public:
void setPath(const QString &path);
- void clearFileLists();
-
- void resolveAbsoluteEntry() const;
+ enum MetaDataClearing { KeepMetaData, IncludingMetaData };
+ void clearCache(MetaDataClearing mode);
- mutable bool fileListsInitialized;
- mutable QStringList files;
- mutable QFileInfoList fileInfos;
+ QString resolveAbsoluteEntry() const;
QStringList nameFilters;
QDir::SortFlags sort;
@@ -103,8 +65,17 @@ public:
std::unique_ptr<QAbstractFileEngine> fileEngine;
QFileSystemEntry dirEntry;
- mutable QFileSystemEntry absoluteDirEntry;
- mutable QFileSystemMetaData metaData;
+
+ struct FileCache
+ {
+ QMutex mutex;
+ QStringList files;
+ QFileInfoList fileInfos;
+ std::atomic<bool> fileListsInitialized = false;
+ QFileSystemEntry absoluteDirEntry;
+ QFileSystemMetaData metaData;
+ };
+ mutable FileCache fileCache;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDirPrivate::PathNormalizations)
diff --git a/src/corelib/io/qdirentryinfo_p.h b/src/corelib/io/qdirentryinfo_p.h
new file mode 100644
index 0000000000..7ed5391ff0
--- /dev/null
+++ b/src/corelib/io/qdirentryinfo_p.h
@@ -0,0 +1,156 @@
+// Copyright (C) 2024 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QDIRENTRYINFO_P_H
+#define QDIRENTRYINFO_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qfileinfo_p.h>
+#include <QtCore/private/qfilesystementry_p.h>
+#include <QtCore/private/qfilesystemmetadata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDirEntryInfo
+{
+ const QFileSystemMetaData &ensureFilled(QFileSystemMetaData::MetaDataFlags what)
+ {
+ if (!metaData.hasFlags(what))
+ QFileSystemEngine::fillMetaData(entry, metaData, what);
+ return metaData;
+ }
+
+public:
+ const QFileInfo &fileInfo()
+ {
+ if (!fileInfoOpt) {
+ fileInfoOpt.emplace(new QFileInfoPrivate(entry, metaData));
+ metaData.clear();
+ }
+ return *fileInfoOpt;
+ }
+
+ QString fileName()
+ { return fileInfoOpt ? fileInfoOpt->fileName() : entry.fileName(); }
+ QString baseName()
+ { return fileInfoOpt ? fileInfoOpt->baseName() : entry.baseName(); }
+ QString completeBaseName() const
+ { return fileInfoOpt ? fileInfoOpt->completeBaseName() : entry.completeBaseName(); }
+ QString suffix() const
+ { return fileInfoOpt ? fileInfoOpt->suffix() : entry.suffix(); }
+ QString completeSuffix() const
+ { return fileInfoOpt ? fileInfoOpt->completeSuffix() : entry.completeSuffix(); }
+ QString filePath()
+ { return fileInfoOpt ? fileInfoOpt->filePath() : entry.filePath(); }
+
+ QString bundleName() { return fileInfo().bundleName(); }
+
+ QString canonicalFilePath()
+ {
+ // QFileInfo caches these strings
+ return fileInfo().canonicalFilePath();
+ }
+
+ QString absoluteFilePath() {
+ // QFileInfo caches these strings
+ return fileInfo().absoluteFilePath();
+ }
+
+ QString absolutePath() {
+ // QFileInfo caches these strings
+ return fileInfo().absolutePath();
+ }
+
+
+ bool isDir() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isDir();
+
+ return ensureFilled(QFileSystemMetaData::DirectoryType).isDirectory();
+ }
+
+ bool isFile() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isFile();
+
+ return ensureFilled(QFileSystemMetaData::FileType).isFile();
+ }
+
+ bool isSymLink() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isSymLink();
+
+ return ensureFilled(QFileSystemMetaData::LegacyLinkType).isLegacyLink();
+ }
+
+ bool isSymbolicLink() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isSymbolicLink();
+
+ return ensureFilled(QFileSystemMetaData::LinkType).isLink();
+ }
+
+ bool exists() {
+ if (fileInfoOpt)
+ return fileInfoOpt->exists();
+
+ return ensureFilled(QFileSystemMetaData::ExistsAttribute).exists();
+ }
+
+ bool isHidden() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isHidden();
+
+ return ensureFilled(QFileSystemMetaData::HiddenAttribute).isHidden();
+ }
+
+ bool isReadable() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isReadable();
+
+ return ensureFilled(QFileSystemMetaData::UserReadPermission).isReadable();
+ }
+
+ bool isWritable() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isWritable();
+
+ return ensureFilled(QFileSystemMetaData::UserWritePermission).isWritable();
+ }
+
+ bool isExecutable() {
+ if (fileInfoOpt)
+ return fileInfoOpt->isExecutable();
+
+ return ensureFilled(QFileSystemMetaData::UserExecutePermission).isExecutable();
+ }
+
+ qint64 size() { return fileInfo().size(); }
+
+ QDateTime fileTime(QFile::FileTime type, const QTimeZone &tz)
+ {
+ return fileInfo().fileTime(type, tz);
+ }
+
+private:
+ friend class QDirListingPrivate;
+ friend class QDirListing;
+
+ QFileSystemEntry entry;
+ QFileSystemMetaData metaData;
+ std::optional<QFileInfo> fileInfoOpt;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDIRENTRYINFO_P_H
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index 4486a92741..3604e673e2 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\since 4.3
@@ -60,16 +24,19 @@
\snippet code/src_corelib_io_qdiriterator.cpp 1
- The next() function returns the path to the next directory entry and
- advances the iterator. You can also call filePath() to get the current
- file path without advancing the iterator. The fileName() function returns
- only the name of the file, similar to how QDir::entryList() works. You can
- also call fileInfo() to get a QFileInfo for the current entry.
+ The next() and nextFileInfo() functions advance the iterator and return
+ the path or the QFileInfo of the next directory entry. You can also call
+ filePath() or fileInfo() to get the current file path or QFileInfo without
+ first advancing the iterator. The fileName() function returns only the
+ name of the file, similar to how QDir::entryList() works.
Unlike Qt's container iterators, QDirIterator is uni-directional (i.e.,
you cannot iterate directories in reverse order) and does not allow random
access.
+ \note This class is deprecated and may be removed in a Qt release. Use
+ QDirListing instead.
+
\sa QDir, QDir::entryList()
*/
@@ -92,6 +59,8 @@
#include "qdiriterator.h"
#include "qdir_p.h"
#include "qabstractfileengine_p.h"
+#include "qdirlisting.h"
+#include "qdirentryinfo_p.h"
#include <QtCore/qset.h>
#include <QtCore/qstack.h>
@@ -108,295 +77,74 @@
#include <QtCore/private/qduplicatetracker_p.h>
#include <memory>
+#include <stack>
+#include <vector>
QT_BEGIN_NAMESPACE
-template <class Iterator>
-class QDirIteratorPrivateIteratorStack : public QStack<Iterator *>
-{
-public:
- ~QDirIteratorPrivateIteratorStack()
- {
- qDeleteAll(*this);
- }
-};
+using namespace Qt::StringLiterals;
class QDirIteratorPrivate
{
-public:
- QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters,
- QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine = true);
-
- void advance();
-
- bool entryMatches(const QString & fileName, const QFileInfo &fileInfo);
- void pushDirectory(const QFileInfo &fileInfo);
- void checkAndPushDirectory(const QFileInfo &);
- bool matchesFilters(const QString &fileName, const QFileInfo &fi) const;
-
- std::unique_ptr<QAbstractFileEngine> engine;
-
- QFileSystemEntry dirEntry;
- const QStringList nameFilters;
- const QDir::Filters filters;
- const QDirIterator::IteratorFlags iteratorFlags;
-
-#if QT_CONFIG(regularexpression)
- QList<QRegularExpression> nameRegExps;
-#endif
-
- QDirIteratorPrivateIteratorStack<QAbstractFileEngineIterator> fileEngineIterators;
-#ifndef QT_NO_FILESYSTEMITERATOR
- QDirIteratorPrivateIteratorStack<QFileSystemIterator> nativeIterators;
-#endif
-
- QFileInfo currentFileInfo;
- QFileInfo nextFileInfo;
+ static QDirListing::IteratorFlags toDirListingFlags(QDirIterator::IteratorFlags flags)
+ {
+ using F = QDirListing::IteratorFlag;
+ QDirListing::IteratorFlags listerFlags;
- // Loop protection
- QDuplicateTracker<QString> visitedLinks;
-};
+ if (flags & QDirIterator::NoIteratorFlags)
+ listerFlags.setFlag(F::NoFlag);
+ if (flags & QDirIterator::FollowSymlinks)
+ listerFlags.setFlag(F::FollowSymlinks);
+ if (flags & QDirIterator::Subdirectories)
+ listerFlags.setFlag(F::Recursive);
-/*!
- \internal
-*/
-QDirIteratorPrivate::QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters,
- QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine)
- : dirEntry(entry)
- , nameFilters(nameFilters.contains(QLatin1String("*")) ? QStringList() : nameFilters)
- , filters(QDir::NoFilter == filters ? QDir::AllEntries : filters)
- , iteratorFlags(flags)
-{
-#if QT_CONFIG(regularexpression)
- nameRegExps.reserve(nameFilters.size());
- for (const auto &filter : nameFilters) {
- auto re = QRegularExpression::fromWildcard(filter, (filters & QDir::CaseSensitive ?
- Qt::CaseSensitive : Qt::CaseInsensitive));
- nameRegExps.append(re);
+ return listerFlags;
}
-#endif
- QFileSystemMetaData metaData;
- if (resolveEngine)
- engine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData));
- QFileInfo fileInfo(new QFileInfoPrivate(dirEntry, metaData));
-
- // Populate fields for hasNext() and next()
- pushDirectory(fileInfo);
- advance();
-}
-/*!
- \internal
-*/
-void QDirIteratorPrivate::pushDirectory(const QFileInfo &fileInfo)
-{
- QString path = fileInfo.filePath();
-
-#ifdef Q_OS_WIN
- if (fileInfo.isSymLink())
- path = fileInfo.canonicalFilePath();
-#endif
-
- if ((iteratorFlags & QDirIterator::FollowSymlinks)) {
- // Stop link loops
- if (visitedLinks.hasSeen(fileInfo.canonicalFilePath()))
- return;
+public:
+ QDirIteratorPrivate(const QDir &dir, QDirIterator::IteratorFlags flags)
+ : lister(dir, toDirListingFlags(flags))
+ {
+ init();
}
-
- if (engine) {
- engine->setFileName(path);
- QAbstractFileEngineIterator *it = engine->beginEntryList(filters, nameFilters);
- if (it) {
- it->setPath(path);
- fileEngineIterators << it;
- } else {
- // No iterator; no entry list.
- }
- } else {
-#ifndef QT_NO_FILESYSTEMITERATOR
- QFileSystemIterator *it = new QFileSystemIterator(fileInfo.d_ptr->fileEntry,
- filters, nameFilters, iteratorFlags);
- nativeIterators << it;
-#else
- qWarning("Qt was built with -no-feature-filesystemiterator: no files/plugins will be found!");
-#endif
+ QDirIteratorPrivate(const QString &path, QDirIterator::IteratorFlags flags)
+ : lister(path, toDirListingFlags(flags))
+ {
+ init();
}
-}
-
-inline bool QDirIteratorPrivate::entryMatches(const QString & fileName, const QFileInfo &fileInfo)
-{
- checkAndPushDirectory(fileInfo);
-
- if (matchesFilters(fileName, fileInfo)) {
- currentFileInfo = nextFileInfo;
- nextFileInfo = fileInfo;
-
- //We found a matching entry.
- return true;
+ QDirIteratorPrivate(const QString &path, QDir::Filters filters,
+ QDirIterator::IteratorFlags flags)
+ : lister(path, filters, toDirListingFlags(flags))
+ {
+ init();
}
-
- return false;
-}
-
-/*!
- \internal
-*/
-void QDirIteratorPrivate::advance()
-{
- if (engine) {
- while (!fileEngineIterators.isEmpty()) {
- // Find the next valid iterator that matches the filters.
- QAbstractFileEngineIterator *it;
- while (it = fileEngineIterators.top(), it->hasNext()) {
- it->next();
- if (entryMatches(it->currentFileName(), it->currentFileInfo()))
- return;
- }
-
- fileEngineIterators.pop();
- delete it;
- }
- } else {
-#ifndef QT_NO_FILESYSTEMITERATOR
- QFileSystemEntry nextEntry;
- QFileSystemMetaData nextMetaData;
-
- while (!nativeIterators.isEmpty()) {
- // Find the next valid iterator that matches the filters.
- QFileSystemIterator *it;
- while (it = nativeIterators.top(), it->advance(nextEntry, nextMetaData)) {
- QFileInfo info(new QFileInfoPrivate(nextEntry, nextMetaData));
-
- if (entryMatches(nextEntry.fileName(), info))
- return;
- nextMetaData = QFileSystemMetaData();
- }
-
- nativeIterators.pop();
- delete it;
- }
-#endif
+ QDirIteratorPrivate(const QString &path, const QStringList &nameFilters, QDir::Filters filters,
+ QDirIterator::IteratorFlags flags)
+ : lister(path, nameFilters, filters, toDirListingFlags(flags))
+ {
+ init();
}
- currentFileInfo = nextFileInfo;
- nextFileInfo = QFileInfo();
-}
-
-/*!
- \internal
- */
-void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo)
-{
- // If we're doing flat iteration, we're done.
- if (!(iteratorFlags & QDirIterator::Subdirectories))
- return;
-
- // Never follow non-directory entries
- if (!fileInfo.isDir())
- return;
-
- // Follow symlinks only when asked
- if (!(iteratorFlags & QDirIterator::FollowSymlinks) && fileInfo.isSymLink())
- return;
-
- // Never follow . and ..
- QString fileName = fileInfo.fileName();
- if (QLatin1String(".") == fileName || QLatin1String("..") == fileName)
- return;
-
- // No hidden directories unless requested
- if (!(filters & QDir::AllDirs) && !(filters & QDir::Hidden) && fileInfo.isHidden())
- return;
-
- pushDirectory(fileInfo);
-}
-
-/*!
- \internal
-
- This convenience function implements the iterator's filtering logics and
- applies then to the current directory entry.
-
- It returns \c true if the current entry matches the filters (i.e., the
- current entry will be returned as part of the directory iteration);
- otherwise, false is returned.
-*/
-
-bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInfo &fi) const
-{
- if (fileName.isEmpty())
- return false;
-
- // filter . and ..?
- const int fileNameSize = fileName.size();
- const bool dotOrDotDot = fileName[0] == QLatin1Char('.')
- && ((fileNameSize == 1)
- ||(fileNameSize == 2 && fileName[1] == QLatin1Char('.')));
- if ((filters & QDir::NoDot) && dotOrDotDot && fileNameSize == 1)
- return false;
- if ((filters & QDir::NoDotDot) && dotOrDotDot && fileNameSize == 2)
- return false;
-
- // name filter
-#if QT_CONFIG(regularexpression)
- // Pass all entries through name filters, except dirs if the AllDirs
- if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) {
- bool matched = false;
- for (const auto &re : nameRegExps) {
- if (re.match(fileName).hasMatch()) {
- matched = true;
- break;
- }
- }
- if (!matched)
- return false;
- }
-#endif
- // skip symlinks
- const bool skipSymlinks = (filters & QDir::NoSymLinks);
- const bool includeSystem = (filters & QDir::System);
- if(skipSymlinks && fi.isSymLink()) {
- // The only reason to save this file is if it is a broken link and we are requesting system files.
- if(!includeSystem || fi.exists())
- return false;
+ void init()
+ {
+ it = lister.begin();
+ if (it != lister.end())
+ nextFileInfo = it->fileInfo();
}
- // filter hidden
- const bool includeHidden = (filters & QDir::Hidden);
- if (!includeHidden && !dotOrDotDot && fi.isHidden())
- return false;
-
- // filter system files
- if (!includeSystem && (!(fi.isFile() || fi.isDir() || fi.isSymLink())
- || (!fi.exists() && fi.isSymLink())))
- return false;
-
- // skip directories
- const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
- if (skipDirs && fi.isDir())
- return false;
-
- // skip files
- const bool skipFiles = !(filters & QDir::Files);
- if (skipFiles && fi.isFile())
- // Basically we need a reason not to exclude this file otherwise we just eliminate it.
- return false;
-
- // filter permissions
- const bool filterPermissions = ((filters & QDir::PermissionMask)
- && (filters & QDir::PermissionMask) != QDir::PermissionMask);
- const bool doWritable = !filterPermissions || (filters & QDir::Writable);
- const bool doExecutable = !filterPermissions || (filters & QDir::Executable);
- const bool doReadable = !filterPermissions || (filters & QDir::Readable);
- if (filterPermissions
- && ((doReadable && !fi.isReadable())
- || (doWritable && !fi.isWritable())
- || (doExecutable && !fi.isExecutable()))) {
- return false;
+ void advance()
+ {
+ currentFileInfo = nextFileInfo;
+ if (++it != lister.end()) {
+ nextFileInfo = it->fileInfo();
+ }
}
- return true;
-}
+ QDirListing lister;
+ QDirListing::const_iterator it = {};
+ QFileInfo currentFileInfo;
+ QFileInfo nextFileInfo;
+};
/*!
Constructs a QDirIterator that can iterate over \a dir's entrylist, using
@@ -414,9 +162,8 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
+ : d(new QDirIteratorPrivate(dir, flags))
{
- const QDirPrivate *other = dir.d_ptr.constData();
- d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, bool(other->fileEngine)));
}
/*!
@@ -433,7 +180,7 @@ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
- : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), filters, flags))
+ : d(new QDirIteratorPrivate(path, filters, flags))
{
}
@@ -450,7 +197,7 @@ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorF
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
- : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), QDir::NoFilter, flags))
+ : d(new QDirIteratorPrivate(path, flags))
{
}
@@ -462,14 +209,19 @@ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
By default, \a flags is NoIteratorFlags, which provides the same behavior
as QDir::entryList().
+ For example, the following iterator could be used to iterate over audio
+ files:
+
+ \snippet code/src_corelib_io_qdiriterator.cpp 2
+
\note To list symlinks that point to non existing files, QDir::System must be
passed to the flags.
- \sa hasNext(), next(), IteratorFlags
+ \sa hasNext(), next(), IteratorFlags, QDir::setNameFilters()
*/
QDirIterator::QDirIterator(const QString &path, const QStringList &nameFilters,
QDir::Filters filters, IteratorFlags flags)
- : d(new QDirIteratorPrivate(QFileSystemEntry(path), nameFilters, filters, flags))
+ : d(new QDirIteratorPrivate(path, nameFilters, filters, flags))
{
}
@@ -485,33 +237,48 @@ QDirIterator::~QDirIterator()
new entry. If hasNext() returns \c false, this function does nothing, and
returns an empty QString.
- You can call fileName() or filePath() to get the current entry file name
+ You can call fileName() or filePath() to get the current entry's file name
or path, or fileInfo() to get a QFileInfo for the current entry.
- \sa hasNext(), fileName(), filePath(), fileInfo()
+ Call nextFileInfo() instead of next() if you're interested in the QFileInfo.
+
+ \sa hasNext(), nextFileInfo(), fileName(), filePath(), fileInfo()
*/
QString QDirIterator::next()
{
d->advance();
- return filePath();
+ return d->currentFileInfo.filePath();
+}
+
+/*!
+ \since 6.3
+
+ Advances the iterator to the next entry, and returns the file info of this
+ new entry. If hasNext() returns \c false, this function does nothing, and
+ returns an empty QFileInfo.
+
+ You can call fileName() or filePath() to get the current entry's file name
+ or path, or fileInfo() to get a QFileInfo for the current entry.
+
+ Call next() instead of nextFileInfo() when all you need is the filePath().
+
+ \sa hasNext(), fileName(), filePath(), fileInfo()
+*/
+QFileInfo QDirIterator::nextFileInfo()
+{
+ d->advance();
+ return d->currentFileInfo;
}
/*!
Returns \c true if there is at least one more entry in the directory;
otherwise, false is returned.
- \sa next(), fileName(), filePath(), fileInfo()
+ \sa next(), nextFileInfo(), fileName(), filePath(), fileInfo()
*/
bool QDirIterator::hasNext() const
{
- if (d->engine)
- return !d->fileEngineIterators.isEmpty();
- else
-#ifndef QT_NO_FILESYSTEMITERATOR
- return !d->nativeIterators.isEmpty();
-#else
- return false;
-#endif
+ return d->it != d->lister.end();
}
/*!
@@ -554,7 +321,7 @@ QFileInfo QDirIterator::fileInfo() const
*/
QString QDirIterator::path() const
{
- return d->dirEntry.filePath();
+ return d->lister.iteratorPath();
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qdiriterator.h b/src/corelib/io/qdiriterator.h
index a8f769eac0..7fa612ebe0 100644
--- a/src/corelib/io/qdiriterator.h
+++ b/src/corelib/io/qdiriterator.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDIRITERATOR_H
#define QDIRITERATOR_H
@@ -44,9 +8,9 @@
QT_BEGIN_NAMESPACE
-
class QDirIteratorPrivate;
-class Q_CORE_EXPORT QDirIterator {
+class Q_CORE_EXPORT QDirIterator
+{
public:
enum IteratorFlag {
NoIteratorFlags = 0x0,
@@ -69,6 +33,7 @@ public:
~QDirIterator();
QString next();
+ QFileInfo nextFileInfo();
bool hasNext() const;
QString fileName() const;
diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp
new file mode 100644
index 0000000000..008003e856
--- /dev/null
+++ b/src/corelib/io/qdirlisting.cpp
@@ -0,0 +1,673 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2024 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+/*!
+ \since 6.8
+ \class QDirListing
+ \inmodule QtCore
+ \brief The QDirListing class provides an STL-style iterator for directory entries.
+
+ You can use QDirListing to navigate entries of a directory one at a time.
+ It is similar to QDir::entryList() and QDir::entryInfoList(), but because
+ it lists entries one at a time instead of all at once, it scales better
+ and is more suitable for large directories. It also supports listing
+ directory contents recursively, and following symbolic links. Unlike
+ QDir::entryList(), QDirListing does not support sorting.
+
+ The QDirListing constructor takes a QDir or a directory path as
+ argument. Here's how to iterate over all entries recursively:
+
+ \snippet code/src_corelib_io_qdirlisting.cpp 0
+
+ Here's how to find and read all files filtered by name, recursively:
+
+ \snippet code/src_corelib_io_qdirlisting.cpp 1
+
+ Iterators constructed by QDirListing (QDirListing::const_iterator) are
+ forward-only (you cannot iterate directories in reverse order) and don't
+ allow random access. They can be used in ranged-for loops (or with STL
+ alogrithms that don't require random access iterators). Dereferencing
+ a valid iterator returns a QDirListing::DirEntry object. The (c)end()
+ iterator marks the end of the iteration. Dereferencing the end iterator
+ is undefiend behavior.
+
+ QDirListing::DirEntry offers a subset of QFileInfo's API (for example,
+ fileName(), filePath(), exists()). Internally, DirEntry only constructs
+ a QFileInfo object if needed, that is, if the info hasn't been already
+ fetched by other system functions. You can use DirEntry::fileInfo()
+ to get a QFileInfo. For example:
+
+ \snippet code/src_corelib_io_qdirlisting.cpp 3
+ \snippet code/src_corelib_io_qdirlisting.cpp 4
+
+ \sa QDir, QDir::entryList()
+*/
+
+/*! \enum QDirListing::IteratorFlag
+
+ This enum class describes flags can be used to configure the behavior of
+ QDirListing. These flags can be bitwise OR'ed together.
+
+ \value NoFlag The default value, representing no flags. The iterator
+ will return entries for the assigned path.
+
+ \value FollowSymlinks When combined with Recursive, this flag enables
+ iterating through all subdirectories of the assigned path, following
+ all symbolic links. Symbolic link loops (e.g., link => . or link =>
+ ..) are automatically detected and ignored.
+
+ \value Recursive List entries inside all subdirectories as well.
+*/
+
+#include "qdirlisting.h"
+#include "qdirentryinfo_p.h"
+
+#include "qdir_p.h"
+#include "qabstractfileengine_p.h"
+
+#include <QtCore/qset.h>
+
+#if QT_CONFIG(regularexpression)
+#include <QtCore/qregularexpression.h>
+#endif
+
+#include <QtCore/private/qfilesystemiterator_p.h>
+#include <QtCore/private/qfilesystementry_p.h>
+#include <QtCore/private/qfilesystemmetadata_p.h>
+#include <QtCore/private/qfilesystemengine_p.h>
+#include <QtCore/private/qfileinfo_p.h>
+#include <QtCore/private/qduplicatetracker_p.h>
+
+#include <memory>
+#include <stack>
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+class QDirListingPrivate
+{
+public:
+ void init(bool resolveEngine);
+ void advance();
+
+ bool entryMatches(QDirEntryInfo &info);
+ void pushDirectory(QDirEntryInfo &info);
+ void pushInitialDirectory();
+
+ void checkAndPushDirectory(QDirEntryInfo &info);
+ bool matchesFilters(QDirEntryInfo &data) const;
+ bool hasIterators() const;
+
+ std::unique_ptr<QAbstractFileEngine> engine;
+ QDirEntryInfo initialEntryInfo;
+ QStringList nameFilters;
+ QDir::Filters filters;
+ QDirListing::IteratorFlags iteratorFlags;
+ QDirEntryInfo currentEntryInfo;
+
+#if QT_CONFIG(regularexpression)
+ QList<QRegularExpression> nameRegExps;
+#endif
+
+ using FEngineIteratorPtr = std::unique_ptr<QAbstractFileEngineIterator>;
+ std::stack<FEngineIteratorPtr, std::vector<FEngineIteratorPtr>> fileEngineIterators;
+#ifndef QT_NO_FILESYSTEMITERATOR
+ using FsIteratorPtr = std::unique_ptr<QFileSystemIterator>;
+ std::stack<FsIteratorPtr, std::vector<FsIteratorPtr>> nativeIterators;
+#endif
+
+ // Loop protection
+ QDuplicateTracker<QString> visitedLinks;
+};
+
+void QDirListingPrivate::init(bool resolveEngine = true)
+{
+ if (nameFilters.contains("*"_L1))
+ nameFilters.clear();
+
+ if (filters == QDir::NoFilter)
+ filters = QDir::AllEntries;
+
+#if QT_CONFIG(regularexpression)
+ nameRegExps.reserve(nameFilters.size());
+ const auto cs = filters.testAnyFlags(QDir::CaseSensitive) ? Qt::CaseSensitive
+ : Qt::CaseInsensitive;
+ for (const auto &filter : nameFilters)
+ nameRegExps.emplace_back(QRegularExpression::fromWildcard(filter, cs));
+#endif
+
+ if (resolveEngine) {
+ engine = QFileSystemEngine::createLegacyEngine(initialEntryInfo.entry,
+ initialEntryInfo.metaData);
+ }
+
+ pushDirectory(initialEntryInfo);
+}
+
+void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
+{
+ const QString path = [&entryInfo] {
+#ifdef Q_OS_WIN
+ if (entryInfo.isSymLink())
+ return entryInfo.canonicalFilePath();
+#endif
+ return entryInfo.filePath();
+ }();
+
+
+ if (iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::FollowSymlinks)) {
+ // Stop link loops
+ if (visitedLinks.hasSeen(entryInfo.canonicalFilePath()))
+ return;
+ }
+
+ if (engine) {
+ engine->setFileName(path);
+ if (auto it = engine->beginEntryList(path, filters, nameFilters)) {
+ fileEngineIterators.emplace(std::move(it));
+ } else {
+ // No iterator; no entry list.
+ }
+ } else {
+#ifndef QT_NO_FILESYSTEMITERATOR
+ QFileSystemEntry *fentry = nullptr;
+ if (entryInfo.fileInfoOpt)
+ fentry = &entryInfo.fileInfoOpt->d_ptr->fileEntry;
+ else
+ fentry = &entryInfo.entry;
+ nativeIterators.emplace(std::make_unique<QFileSystemIterator>(*fentry, filters));
+#else
+ qWarning("Qt was built with -no-feature-filesystemiterator: no files/plugins will be found!");
+#endif
+ }
+}
+
+bool QDirListingPrivate::entryMatches(QDirEntryInfo &entryInfo)
+{
+ checkAndPushDirectory(entryInfo);
+ return matchesFilters(entryInfo);
+}
+
+/*!
+ \internal
+
+ Advances the internal iterator, either a QAbstractFileEngineIterator (e.g.
+ QResourceFileEngineIterator) or a QFileSystemIterator (which uses low-level
+ system methods, e.g. readdir() on Unix).
+
+ An iterator stack is used for holding the iterators.
+
+ A typical example of doing recursive iteration:
+ - while iterating directory A we find a sub-dir B
+ - an iterator for B is added to the iterator stack
+ - B's iterator is processed (the top() of the stack) first; then loop
+ goes back to processing A's iterator
+*/
+void QDirListingPrivate::advance()
+{
+ // Use get() in both code paths below because the iterator returned by top()
+ // may be invalidated due to reallocation when appending new iterators in
+ // pushDirectory().
+
+ if (engine) {
+ while (!fileEngineIterators.empty()) {
+ // Find the next valid iterator that matches the filters.
+ QAbstractFileEngineIterator *it;
+ while (it = fileEngineIterators.top().get(), it->advance()) {
+ QDirEntryInfo entryInfo;
+ entryInfo.fileInfoOpt = it->currentFileInfo();
+ if (entryMatches(entryInfo)) {
+ currentEntryInfo = std::move(entryInfo);
+ return;
+ }
+ }
+
+ fileEngineIterators.pop();
+ }
+ } else {
+#ifndef QT_NO_FILESYSTEMITERATOR
+ QDirEntryInfo entryInfo;
+ while (!nativeIterators.empty()) {
+ // Find the next valid iterator that matches the filters.
+ QFileSystemIterator *it;
+ while (it = nativeIterators.top().get(), it->advance(entryInfo.entry, entryInfo.metaData)) {
+ if (entryMatches(entryInfo)) {
+ currentEntryInfo = std::move(entryInfo);
+ return;
+ }
+ entryInfo = {};
+ }
+
+ nativeIterators.pop();
+ }
+#endif
+ }
+}
+
+void QDirListingPrivate::checkAndPushDirectory(QDirEntryInfo &entryInfo)
+{
+ using F = QDirListing::IteratorFlag;
+ // If we're doing flat iteration, we're done.
+ if (!iteratorFlags.testAnyFlags(F::Recursive))
+ return;
+
+ // Never follow non-directory entries
+ if (!entryInfo.isDir())
+ return;
+
+ // Follow symlinks only when asked
+ if (!iteratorFlags.testAnyFlags(F::FollowSymlinks) && entryInfo.isSymLink())
+ return;
+
+ // Never follow . and ..
+ const QString &fileName = entryInfo.fileName();
+ if ("."_L1 == fileName || ".."_L1 == fileName)
+ return;
+
+ // No hidden directories unless requested
+ if (!filters.testAnyFlags(QDir::AllDirs | QDir::Hidden) && entryInfo.isHidden())
+ return;
+
+ pushDirectory(entryInfo);
+}
+
+/*!
+ \internal
+
+ This functions returns \c true if the current entry matches the filters
+ (i.e., the current entry will be returned as part of the directory
+ iteration); otherwise, \c false is returned.
+*/
+bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
+{
+ const QString &fileName = entryInfo.fileName();
+ if (fileName.isEmpty())
+ return false;
+
+ // filter . and ..?
+ const qsizetype fileNameSize = fileName.size();
+ const bool dotOrDotDot = fileName[0] == u'.'
+ && ((fileNameSize == 1)
+ ||(fileNameSize == 2 && fileName[1] == u'.'));
+ if ((filters & QDir::NoDot) && dotOrDotDot && fileNameSize == 1)
+ return false;
+ if ((filters & QDir::NoDotDot) && dotOrDotDot && fileNameSize == 2)
+ return false;
+
+ // name filter
+#if QT_CONFIG(regularexpression)
+ // Pass all entries through name filters, except dirs if AllDirs is set
+ if (!nameRegExps.isEmpty() && !(filters.testAnyFlags(QDir::AllDirs) && entryInfo.isDir())) {
+ auto regexMatchesName = [&fileName](const auto &re) {
+ return re.match(fileName).hasMatch();
+ };
+ if (std::none_of(nameRegExps.cbegin(), nameRegExps.cend(), regexMatchesName))
+ return false;
+ }
+#endif
+ // skip symlinks
+ const bool skipSymlinks = filters.testAnyFlag(QDir::NoSymLinks);
+ const bool includeSystem = filters.testAnyFlag(QDir::System);
+ if (skipSymlinks && entryInfo.isSymLink()) {
+ // The only reason to save this file is if it is a broken link and we are requesting system files.
+ if (!includeSystem || entryInfo.exists())
+ return false;
+ }
+
+ // filter hidden
+ const bool includeHidden = filters.testAnyFlag(QDir::Hidden);
+ if (!includeHidden && !dotOrDotDot && entryInfo.isHidden())
+ return false;
+
+ // filter system files
+ if (!includeSystem) {
+ if (!entryInfo.isFile() && !entryInfo.isDir() && !entryInfo.isSymLink())
+ return false;
+ if (entryInfo.isSymLink() && !entryInfo.exists())
+ return false;
+ }
+
+ // skip directories
+ const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
+ if (skipDirs && entryInfo.isDir())
+ return false;
+
+ // skip files
+ const bool skipFiles = !(filters & QDir::Files);
+ if (skipFiles && entryInfo.isFile())
+ // Basically we need a reason not to exclude this file otherwise we just eliminate it.
+ return false;
+
+ // filter permissions
+ const auto perms = filters & QDir::PermissionMask;
+ const bool filterPermissions = perms != 0 && perms != QDir::PermissionMask;
+ if (filterPermissions) {
+ const bool doWritable = filters.testAnyFlags(QDir::Writable);
+ const bool doExecutable = filters.testAnyFlags(QDir::Executable);
+ const bool doReadable = filters.testAnyFlags(QDir::Readable);
+ if ((doReadable && !entryInfo.isReadable())
+ || (doWritable && !entryInfo.isWritable())
+ || (doExecutable && !entryInfo.isExecutable())) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool QDirListingPrivate::hasIterators() const
+{
+ if (engine)
+ return !fileEngineIterators.empty();
+
+#if !defined(QT_NO_FILESYSTEMITERATOR)
+ return !nativeIterators.empty();
+#endif
+
+ return false;
+}
+
+/*!
+ Constructs a QDirListing that can iterate over \a dir's entries, using
+ \a dir's name filters and the QDir::Filters set in \a dir. You can pass
+ options via \a flags to decide how the directory should be iterated.
+
+ By default, \a flags is NoIteratorFlags, which provides the same behavior
+ as in QDir::entryList().
+
+ The sorting in \a dir is ignored.
+
+ \note To list symlinks that point to non existing files, QDir::System
+ must be set in \a dir's QDir::Filters.
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirListing::QDirListing(const QDir &dir, IteratorFlags flags)
+ : d(new QDirListingPrivate)
+{
+ const QDirPrivate *other = dir.d_ptr.constData();
+ d->initialEntryInfo.entry = other->dirEntry;
+ d->nameFilters = other->nameFilters;
+ d->filters = other->filters;
+ d->iteratorFlags = flags;
+ const bool resolveEngine = other->fileEngine ? true : false;
+ d->init(resolveEngine);
+}
+
+/*!
+ Constructs a QDirListing that can iterate over \a path. Entries are
+ filtered according to \a filters. You can pass options via \a flags to
+ decide how the directory should be iterated.
+
+ By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags,
+ which provides the same behavior as in QDir::entryList().
+
+ \note To list symlinks that point to non existing files, QDir::System
+ must be set in \a filters.
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirListing::QDirListing(const QString &path, QDir::Filters filters, IteratorFlags flags)
+ : d(new QDirListingPrivate)
+{
+ d->initialEntryInfo.entry = QFileSystemEntry(path);
+ d->filters = filters;
+ d->iteratorFlags = flags;
+ d->init();
+}
+
+/*!
+ Constructs a QDirListing that can iterate over \a path. You can pass
+ options via \a flags to decide how the directory should be iterated.
+
+ By default, \a flags is NoIteratorFlags, which provides the same behavior
+ as in QDir::entryList().
+
+ \sa hasNext(), next(), IteratorFlags
+*/
+QDirListing::QDirListing(const QString &path, IteratorFlags flags)
+ : d(new QDirListingPrivate)
+{
+ d->initialEntryInfo.entry = QFileSystemEntry(path);
+ d->filters = QDir::NoFilter;
+ d->iteratorFlags = flags;
+ d->init();
+}
+
+/*!
+ Constructs a QDirListing that can iterate over \a path, using \a
+ nameFilters and \a filters. You can pass options via \a flags to decide
+ how the directory should be iterated.
+
+ By default, \a flags is NoIteratorFlags, which provides the same behavior
+ as QDir::entryList().
+
+ For example, the following iterator could be used to iterate over audio
+ files:
+
+ \snippet code/src_corelib_io_qdirlisting.cpp 2
+
+ \note To list symlinks that point to non existing files, QDir::System
+ must be set in \a flags.
+
+ \sa hasNext(), next(), IteratorFlags, QDir::setNameFilters()
+*/
+QDirListing::QDirListing(const QString &path, const QStringList &nameFilters, QDir::Filters filters,
+ IteratorFlags flags)
+ : d(new QDirListingPrivate)
+{
+ d->initialEntryInfo.entry = QFileSystemEntry(path);
+ d->nameFilters = nameFilters;
+ d->filters = filters;
+ d->iteratorFlags = flags;
+ d->init();
+}
+
+/*!
+ Destroys the QDirListing.
+*/
+QDirListing::~QDirListing() = default;
+
+/*!
+ Returns the directory path used to construct this QDirListing.
+*/
+QString QDirListing::iteratorPath() const
+{
+ return d->initialEntryInfo.filePath();
+}
+
+/*!
+ \fn QDirListing::const_iterator QDirListing::begin() const
+ \fn QDirListing::const_iterator QDirListing::cbegin() const
+ \fn QDirListing::const_iterator QDirListing::end() const
+ \fn QDirListing::const_iterator QDirListing::cend() const
+
+ begin()/cbegin() returns a QDirListing::const_iterator that enables
+ iterating over directory entries using a ranged-for loop; dereferencing
+ this iterator returns a \c{const QFileInfo &}.
+
+ end()/cend() return a sentinel const_iterator that signals the end of
+ the iteration. Dereferencing this iterator is undefined behavior.
+
+ For example:
+ \snippet code/src_corelib_io_qdirlisting.cpp 0
+
+ Here's how to find and read all files filtered by name, recursively:
+ \snippet code/src_corelib_io_qdirlisting.cpp 1
+
+ \note As this is a unidirectional (forward-only) iterator, calling
+ begin()/cbegin() more than once on the same QDirListing object could
+ result in unexpected behavior (for example, some entries being skipped).
+
+ \sa fileInfo(), fileName(), filePath()
+*/
+QDirListing::const_iterator QDirListing::begin() const
+{
+ const_iterator it{d.get()};
+ return ++it;
+}
+
+/*!
+ \fn const QDirListing::DirEntry &QDirListing::const_iterator::operator*() const
+
+ Returns a \c{const QDirListing::DirEntry &} of the directory entry this
+ iterator points to.
+*/
+
+/*!
+ \fn const QDirListing::DirEntry *QDirListing::const_iterator::operator->() const
+
+ Returns a \c{const QDirListing::DirEntry *} to the directory entry this
+ iterator points to.
+*/
+
+/*!
+ Advances the iterator and returns a reference to it.
+*/
+QDirListing::const_iterator &QDirListing::const_iterator::operator++()
+{
+ dirListPtr->advance();
+ if (!dirListPtr->hasIterators())
+ *this = {}; // All done, make `this` the end() iterator
+ return *this;
+}
+
+/*!
+ \fn QFileInfo QDirListing::DirEntry::fileInfo() const
+ \fn QString QDirListing::DirEntry::fileName() const
+ \fn QString QDirListing::DirEntry::baseName() const
+ \fn QString QDirListing::DirEntry::completeBaseName() const
+ \fn QString QDirListing::DirEntry::suffix() const
+ \fn QString QDirListing::DirEntry::bundleName() const
+ \fn QString QDirListing::DirEntry::completeSuffix() const
+ \fn QString QDirListing::DirEntry::filePath() const
+ \fn QString QDirListing::DirEntry::canonicalFilePath() const
+ \fn QString QDirListing::DirEntry::absoluteFilePath() const
+ \fn QString QDirListing::DirEntry::absolutePath() const
+ \fn bool QDirListing::DirEntry::isDir() const
+ \fn bool QDirListing::DirEntry::isFile() const
+ \fn bool QDirListing::DirEntry::isSymLink() const
+ \fn bool QDirListing::DirEntry::exists() const
+ \fn bool QDirListing::DirEntry::isHidden() const
+ \fn bool QDirListing::DirEntry::isReadable() const
+ \fn bool QDirListing::DirEntry::isWritable() const
+ \fn bool QDirListing::DirEntry::isExecutable() const
+ \fn qint64 QDirListing::DirEntry::size() const
+ \fn QDateTime QDirListing::DirEntry::fileTime(QFile::FileTime type, const QTimeZone &tz) const
+ \fn QDateTime QDirListing::DirEntry::birthTime(const QTimeZone &tz) const;
+ \fn QDateTime QDirListing::DirEntry::metadataChangeTime(const QTimeZone &tz) const;
+ \fn QDateTime QDirListing::DirEntry::lastModified(const QTimeZone &tz) const;
+ \fn QDateTime QDirListing::DirEntry::lastRead(const QTimeZone &tz) const;
+
+ See the QFileInfo methods with the same names.
+*/
+
+QFileInfo QDirListing::DirEntry::fileInfo() const
+{
+ return dirListPtr->currentEntryInfo.fileInfo();
+}
+
+QString QDirListing::DirEntry::fileName() const
+{
+ return dirListPtr->currentEntryInfo.fileName();
+}
+
+QString QDirListing::DirEntry::baseName() const
+{
+ return dirListPtr->currentEntryInfo.baseName();
+}
+
+QString QDirListing::DirEntry::completeBaseName() const
+{
+ return dirListPtr->currentEntryInfo.completeBaseName();
+}
+
+QString QDirListing::DirEntry::suffix() const
+{
+ return dirListPtr->currentEntryInfo.suffix();
+}
+
+QString QDirListing::DirEntry::bundleName() const
+{
+ return dirListPtr->currentEntryInfo.bundleName();
+}
+
+QString QDirListing::DirEntry::completeSuffix() const
+{
+ return dirListPtr->currentEntryInfo.completeSuffix();
+}
+
+QString QDirListing::DirEntry::filePath() const
+{
+ return dirListPtr->currentEntryInfo.filePath();
+}
+
+QString QDirListing::DirEntry::canonicalFilePath() const
+{
+ return dirListPtr->currentEntryInfo.canonicalFilePath();
+}
+
+QString QDirListing::DirEntry::absoluteFilePath() const
+{
+ return dirListPtr->currentEntryInfo.absoluteFilePath();
+}
+
+QString QDirListing::DirEntry::absolutePath() const
+{
+ return dirListPtr->currentEntryInfo.absolutePath();
+}
+
+bool QDirListing::DirEntry::isDir() const
+{
+ return dirListPtr->currentEntryInfo.isDir();
+}
+
+bool QDirListing::DirEntry::isFile() const
+{
+ return dirListPtr->currentEntryInfo.isFile();
+}
+
+bool QDirListing::DirEntry::isSymLink() const
+{
+ return dirListPtr->currentEntryInfo.isSymLink();
+}
+
+bool QDirListing::DirEntry::exists() const
+{
+ return dirListPtr->currentEntryInfo.exists();
+}
+
+bool QDirListing::DirEntry::isHidden() const
+{
+ return dirListPtr->currentEntryInfo.isHidden();
+}
+
+bool QDirListing::DirEntry::isReadable() const
+{
+ return dirListPtr->currentEntryInfo.isReadable();
+}
+
+bool QDirListing::DirEntry::isWritable() const
+{
+ return dirListPtr->currentEntryInfo.isWritable();
+}
+
+bool QDirListing::DirEntry::isExecutable() const
+{
+ return dirListPtr->currentEntryInfo.isExecutable();
+}
+
+qint64 QDirListing::DirEntry::size() const
+{
+ return dirListPtr->currentEntryInfo.size();
+}
+
+QDateTime QDirListing::DirEntry::fileTime(QFile::FileTime type, const QTimeZone &tz) const
+{
+ return dirListPtr->currentEntryInfo.fileTime(type, tz);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qdirlisting.h b/src/corelib/io/qdirlisting.h
new file mode 100644
index 0000000000..d19fe3c666
--- /dev/null
+++ b/src/corelib/io/qdirlisting.h
@@ -0,0 +1,119 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2024 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QDILISTING_H
+#define QDILISTING_H
+
+#include <QtCore/qdir.h>
+
+#include <iterator>
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+class QDirListingPrivate;
+
+class Q_CORE_EXPORT QDirListing
+{
+public:
+ enum class IteratorFlag {
+ NoFlag = 0x0,
+ FollowSymlinks = 0x1,
+ Recursive = 0x2
+ };
+ Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag)
+
+ QDirListing(const QDir &dir, IteratorFlags flags = IteratorFlag::NoFlag);
+ QDirListing(const QString &path, IteratorFlags flags = IteratorFlag::NoFlag);
+ QDirListing(const QString &path, QDir::Filters filter,
+ IteratorFlags flags = IteratorFlag::NoFlag);
+ QDirListing(const QString &path, const QStringList &nameFilters,
+ QDir::Filters filters = QDir::NoFilter,
+ IteratorFlags flags = IteratorFlag::NoFlag);
+
+ ~QDirListing();
+
+ QString iteratorPath() const;
+
+ class Q_CORE_EXPORT DirEntry
+ {
+ friend class QDirListing;
+ QDirListingPrivate *dirListPtr = nullptr;
+ public:
+ QString fileName() const;
+ QString baseName() const;
+ QString completeBaseName() const;
+ QString suffix() const;
+ QString bundleName() const;
+ QString completeSuffix() const;
+ QString filePath() const;
+ bool isDir() const;
+ bool isFile() const;
+ bool isSymLink() const;
+ bool exists() const;
+ bool isHidden() const;
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isExecutable() const;
+ QFileInfo fileInfo() const;
+ QString canonicalFilePath() const;
+ QString absoluteFilePath() const;
+ QString absolutePath() const;
+ qint64 size() const;
+
+ QDateTime birthTime(const QTimeZone &tz) const { return fileTime(QFile::FileBirthTime, tz); }
+ QDateTime metadataChangeTime(const QTimeZone &tz) const { return fileTime(QFile::FileMetadataChangeTime, tz); }
+ QDateTime lastModified(const QTimeZone &tz) const { return fileTime(QFile::FileModificationTime, tz); }
+ QDateTime lastRead(const QTimeZone &tz) const { return fileTime(QFile::FileAccessTime, tz); }
+ QDateTime fileTime(QFile::FileTime type, const QTimeZone &tz) const;
+ };
+
+ class const_iterator
+ {
+ friend class QDirListing;
+ const_iterator(QDirListingPrivate *dp) : dirListPtr(dp) { dirEntry.dirListPtr = dp; }
+ QDirListingPrivate *dirListPtr = nullptr;
+ DirEntry dirEntry;
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = DirEntry;
+ using difference_type = qint64;
+ using pointer = const value_type *;
+ using reference = const value_type &;
+
+ const_iterator() = default;
+ reference operator*() const { return dirEntry; }
+ pointer operator->() const { return &dirEntry; }
+ Q_CORE_EXPORT const_iterator &operator++();
+ const_iterator operator++(int) { auto tmp = *this; operator++(); return tmp; };
+ friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
+ {
+ // This is only used for the sentinel end iterator
+ return lhs.dirListPtr == nullptr && rhs.dirListPtr == nullptr;
+ }
+ friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
+ { return !(lhs == rhs); }
+ };
+
+ const_iterator begin() const;
+ const_iterator cbegin() const { return begin(); }
+ const_iterator end() const { return {}; }
+ const_iterator cend() const { return end(); }
+
+ // Qt compatibility
+ const_iterator constBegin() const { return begin(); }
+ const_iterator constEnd() const { return end(); }
+
+private:
+ Q_DISABLE_COPY(QDirListing)
+
+ std::unique_ptr<QDirListingPrivate> d;
+ friend class QDir;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDirListing::IteratorFlags)
+
+QT_END_NAMESPACE
+
+#endif // QDILISTING_H
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 2544496c32..52188dde51 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qdebug.h"
@@ -55,14 +19,14 @@
# include "qcoreapplication.h"
#endif
-#include <private/qmemory_p.h>
-
#ifdef QT_NO_QOBJECT
#define tr(X) QString::fromLatin1(X)
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_DECL_COLD_FUNCTION
static bool file_already_open(QFile &file, const char *where = nullptr)
{
@@ -80,39 +44,39 @@ QFilePrivate::~QFilePrivate()
}
bool
-QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags)
+QFilePrivate::openExternalFile(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags)
{
#ifdef QT_NO_FSFILEENGINE
Q_UNUSED(flags);
Q_UNUSED(fd);
return false;
#else
- auto fs = qt_make_unique<QFSFileEngine>();
+ auto fs = std::make_unique<QFSFileEngine>();
auto fe = fs.get();
fileEngine = std::move(fs);
- return fe->open(QIODevice::OpenMode(flags), fd, handleFlags);
+ return fe->open(flags, fd, handleFlags);
#endif
}
bool
-QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags)
+QFilePrivate::openExternalFile(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags)
{
#ifdef QT_NO_FSFILEENGINE
Q_UNUSED(flags);
Q_UNUSED(fh);
return false;
#else
- auto fs = qt_make_unique<QFSFileEngine>();
+ auto fs = std::make_unique<QFSFileEngine>();
auto fe = fs.get();
fileEngine = std::move(fs);
- return fe->open(QIODevice::OpenMode(flags), fh, handleFlags);
+ return fe->open(flags, fh, handleFlags);
#endif
}
QAbstractFileEngine *QFilePrivate::engine() const
{
if (!fileEngine)
- fileEngine.reset(QAbstractFileEngine::create(fileName));
+ fileEngine = QAbstractFileEngine::create(fileName);
return fileEngine.get();
}
@@ -186,13 +150,20 @@ QAbstractFileEngine *QFilePrivate::engine() const
data and operator>>() to read it back. See the class
documentation for details.
- When you use QFile, QFileInfo, and QDir to access the file system
- with Qt, you can use Unicode file names. On Unix, these file
- names are converted to an 8-bit encoding. If you want to use
- standard C++ APIs (\c <cstdio> or \c <iostream>) or
- platform-specific APIs to access files instead of QFile, you can
- use the encodeName() and decodeName() functions to convert
- between Unicode file names and 8-bit file names.
+ \section1 Signals
+
+ Unlike other QIODevice implementations, such as QTcpSocket, QFile does not
+ emit the aboutToClose(), bytesWritten(), or readyRead() signals. This
+ implementation detail means that QFile is not suitable for reading and
+ writing certain types of files, such as device files on Unix platforms.
+
+ \section1 Platform Specific Issues
+
+ \l{Input/Output and Networking}{Qt APIs related to I/O} use UTF-16 based
+ QStrings to represent file paths. Standard C++ APIs (\c <cstdio> or
+ \c <iostream>) or platform-specific APIs however often need a 8-bit encoded
+ path. You can use encodeName() and decodeName() to convert between both
+ representations.
On Unix, there are some special system files (e.g. in \c /proc) for which
size() will always return 0, yet you may still be able to read more data
@@ -205,15 +176,6 @@ QAbstractFileEngine *QFilePrivate::engine() const
\snippet file/file.cpp 3
- \section1 Signals
-
- Unlike other QIODevice implementations, such as QTcpSocket, QFile does not
- emit the aboutToClose(), bytesWritten(), or readyRead() signals. This
- implementation detail means that QFile is not suitable for reading and
- writing certain types of files, such as device files on Unix platforms.
-
- \section1 Platform Specific Issues
-
File permissions are handled differently on Unix-like systems and
Windows. In a non \l{QIODevice::isWritable()}{writable}
directory on Unix-like systems, files cannot be created. This is not always
@@ -228,6 +190,8 @@ QAbstractFileEngine *QFilePrivate::engine() const
function mostly useless for NTFS volumes. It may still be of use for USB
sticks that use VFAT file systems. POSIX ACLs are not manipulated, either.
+ \include android-content-uri-limitations.qdocinc
+
\sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
*/
@@ -262,6 +226,15 @@ QFile::QFile(QObject *parent)
}
/*!
Constructs a new file object to represent the file with the given \a name.
+
+//! [qfile-explicit-constructor-note]
+ \note In versions up to and including Qt 6.8, this constructor is
+ implicit, for backward compatibility. Starting from Qt 6.9 this
+ constructor is unconditionally \c{explicit}. Users can force this
+ constructor to be \c{explicit} even in earlier versions of Qt by
+ defining the \c{QT_EXPLICIT_QFILE_CONSTRUCTION_FROM_PATH} macro
+ before including any Qt header.
+//! [qfile-explicit-constructor-note]
*/
QFile::QFile(const QString &name)
: QFileDevice(*new QFilePrivate, nullptr)
@@ -349,27 +322,15 @@ QFile::setFileName(const QString &name)
/*!
\fn QByteArray QFile::encodeName(const QString &fileName)
- Converts \a fileName to the local 8-bit
- encoding determined by the user's locale. This is sufficient for
- file names that the user chooses. File names hard-coded into the
- application should only use 7-bit ASCII filename characters.
+ Converts \a fileName to an 8-bit encoding that you can use in native
+ APIs. On Windows, the encoding is the one from active Windows (ANSI)
+ codepage. On other platforms, this is UTF-8, for \macos in decomposed
+ form (NFD).
\sa decodeName()
*/
/*!
- \typedef QFile::EncoderFn
- \obsolete
-
- This is a typedef for a pointer to a function with the following
- signature:
-
- \snippet code/src_corelib_io_qfile.cpp 1
-
- \sa setEncodingFunction(), encodeName()
-*/
-
-/*!
\fn QString QFile::decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using \a localFileName.
@@ -378,39 +339,6 @@ QFile::setFileName(const QString &name)
*/
/*!
- \fn void QFile::setEncodingFunction(EncoderFn function)
- \obsolete
-
- This function does nothing. It is provided for compatibility with Qt 4 code
- that attempted to set a different encoding function for file names. That
- feature is flawed and no longer supported in Qt 5.
-
- \sa encodeName(), setDecodingFunction()
-*/
-
-/*!
- \typedef QFile::DecoderFn
-
- This is a typedef for a pointer to a function with the following
- signature:
-
- \snippet code/src_corelib_io_qfile.cpp 2
-
- \sa setDecodingFunction()
-*/
-
-/*!
- \fn void QFile::setDecodingFunction(DecoderFn function)
- \obsolete
-
- This function does nothing. It is provided for compatibility with Qt 4 code
- that attempted to set a different decoding function for file names. That
- feature is flawed and no longer supported in Qt 5.
-
- \sa setEncodingFunction(), decodeName()
-*/
-
-/*!
\overload
Returns \c true if the file specified by fileName() exists; otherwise
@@ -424,8 +352,8 @@ QFile::exists() const
{
Q_D(const QFile);
// 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
- return (d->engine()->fileFlags(QAbstractFileEngine::FlagsMask
- | QAbstractFileEngine::Refresh) & QAbstractFileEngine::ExistsFlag);
+ return d->engine()->fileFlags(QAbstractFileEngine::FlagsMask
+ | QAbstractFileEngine::Refresh).testAnyFlag(QAbstractFileEngine::ExistsFlag);
}
/*!
@@ -459,22 +387,9 @@ QFile::exists(const QString &fileName)
QString QFile::symLinkTarget() const
{
Q_D(const QFile);
- return d->engine()->fileName(QAbstractFileEngine::LinkName);
+ return d->engine()->fileName(QAbstractFileEngine::AbsoluteLinkTarget);
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Use symLinkTarget() instead.
-*/
-QString
-QFile::readLink() const
-{
- return symLinkTarget();
-}
-#endif
-
/*!
\fn static QString QFile::symLinkTarget(const QString &fileName)
\since 4.2
@@ -491,19 +406,6 @@ QString QFile::symLinkTarget(const QString &fileName)
return QFileInfo(fileName).symLinkTarget();
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Use symLinkTarget() instead.
-*/
-QString
-QFile::readLink(const QString &fileName)
-{
- return symLinkTarget(fileName);
-}
-#endif
-
/*!
Removes the file specified by fileName(). Returns \c true if successful;
otherwise returns \c false.
@@ -524,7 +426,7 @@ QFile::remove()
}
unsetError();
close();
- if(error() == QFile::NoError) {
+ if (error() == QFile::NoError) {
if (d->engine()->remove()) {
unsetError();
return true;
@@ -557,6 +459,24 @@ QFile::remove(const QString &fileName)
and sets the fileName() to the path at which the file can be found within the trash;
otherwise returns \c false.
+//! [move-to-trash-common]
+ The time for this function to run is independent of the size of the file
+ being trashed. If this function is called on a directory, it may be
+ proportional to the number of files being trashed.
+
+ This function uses the Windows and \macos APIs to perform the trashing on
+ those two operating systems. Elsewhere (Unix systems), this function
+ implements the \l{FreeDesktop.org Trash specification version 1.0}.
+
+ \note When using the FreeDesktop.org Trash implementation, this function
+ will fail if it is unable to move the files to the trash location by way of
+ file renames and hardlinks. This condition arises if the file being trashed
+ resides on a volume (mount point) on which the current user does not have
+ permission to create the \c{.Trash} directory, or with some unusual
+ filesystem types or configurations (such as sub-volumes that aren't
+ themselves mount points).
+//! [move-to-trash-common]
+
\note On systems where the system API doesn't report the location of the file in the
trash, fileName() will be set to the null string once the file has been moved. On
systems that don't have a trash can, this function always returns false.
@@ -594,9 +514,12 @@ QFile::moveToTrash()
and sets \a pathInTrash (if provided) to the path at which the file can be found within
the trash; otherwise returns \c false.
+ \include qfile.cpp move-to-trash-common
+
\note On systems where the system API doesn't report the path of the file in the
trash, \a pathInTrash will be set to the null string once the file has been moved.
On systems that don't have a trash can, this function always returns false.
+
*/
bool
QFile::moveToTrash(const QString &fileName, QString *pathInTrash)
@@ -661,7 +584,7 @@ QFile::rename(const QString &newName)
return false;
}
-#ifdef Q_OS_LINUX
+#if defined(Q_OS_LINUX) && QT_CONFIG(temporaryfile)
// rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive
// FS, such as FAT32. Move the file away and rename in 2 steps to work around.
QTemporaryFileName tfn(d->fileName);
@@ -689,7 +612,7 @@ QFile::rename(const QString &newName)
// report both errors
d->setError(QFile::RenameError,
tr("Error while renaming: %1").arg(error.toString())
- + QLatin1Char('\n')
+ + u'\n'
+ tr("Unable to restore from %1: %2").
arg(QDir::toNativeSeparators(tmp.filePath()), error2.toString()));
return false;
@@ -701,7 +624,7 @@ QFile::rename(const QString &newName)
}
unsetError();
close();
- if(error() == QFile::NoError) {
+ if (error() == QFile::NoError) {
if (changingCase ? d->engine()->renameOverwrite(newName) : d->engine()->rename(newName)) {
unsetError();
// engine was able to handle the new name so we just reset it
@@ -732,7 +655,7 @@ QFile::rename(const QString &newName)
d->setError(QFile::RenameError, errorString());
error = true;
}
- if(!error) {
+ if (!error) {
if (!remove()) {
d->setError(QFile::RenameError, tr("Cannot remove source file"));
error = true;
@@ -828,13 +751,12 @@ QFile::link(const QString &fileName, const QString &linkName)
}
/*!
- Copies the file currently specified by fileName() to a file called
- \a newName. Returns \c true if successful; otherwise returns \c false.
+ Copies the file named fileName() to \a newName.
- Note that if a file with the name \a newName already exists,
- copy() returns \c false (i.e. QFile will not overwrite it).
+ \include qfile-copy.qdocinc
- The source file is closed before it is copied.
+ \note On Android, this operation is not yet supported for \c content
+ scheme URIs.
\sa setFileName()
*/
@@ -856,18 +778,18 @@ QFile::copy(const QString &newName)
}
unsetError();
close();
- if(error() == QFile::NoError) {
+ if (error() == QFile::NoError) {
if (d->engine()->copy(newName)) {
unsetError();
return true;
} else {
bool error = false;
- if(!open(QFile::ReadOnly)) {
+ if (!open(QFile::ReadOnly)) {
error = true;
d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
} else {
- const auto fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
-#ifdef QT_NO_TEMPORARYFILE
+ const auto fileTemplate = "%1/qt_temp.XXXXXX"_L1;
+#if !QT_CONFIG(temporaryfile)
QFile out(fileTemplate.arg(QFileInfo(newName).path()));
if (!out.open(QIODevice::ReadWrite))
error = true;
@@ -880,9 +802,9 @@ QFile::copy(const QString &newName)
}
#endif
if (error) {
+ d->setError(QFile::CopyError, tr("Cannot open for output: %1").arg(out.errorString()));
out.close();
close();
- d->setError(QFile::CopyError, tr("Cannot open for output: %1").arg(out.errorString()));
} else {
if (!d->engine()->cloneTo(out.d_func()->engine())) {
char block[4096];
@@ -894,7 +816,8 @@ QFile::copy(const QString &newName)
totalRead += in;
if (in != out.write(block, in)) {
close();
- d->setError(QFile::CopyError, tr("Failure to write block"));
+ d->setError(QFile::CopyError, tr("Failure to write block: %1")
+ .arg(out.errorString()));
error = true;
break;
}
@@ -909,15 +832,16 @@ QFile::copy(const QString &newName)
if (!error) {
// Sync to disk if possible. Ignore errors (e.g. not supported).
- d->fileEngine->syncToDisk();
+ out.d_func()->fileEngine->syncToDisk();
if (!out.rename(newName)) {
error = true;
close();
- d->setError(QFile::CopyError, tr("Cannot create %1 for output").arg(newName));
+ d->setError(QFile::CopyError, tr("Cannot create %1 for output: %2")
+ .arg(newName, out.errorString()));
}
}
-#ifdef QT_NO_TEMPORARYFILE
+#if !QT_CONFIG(temporaryfile)
if (error)
out.remove();
#else
@@ -926,7 +850,7 @@ QFile::copy(const QString &newName)
#endif
}
}
- if(!error) {
+ if (!error) {
QFile::setPermissions(newName, permissions());
close();
unsetError();
@@ -940,11 +864,12 @@ QFile::copy(const QString &newName)
/*!
\overload
- Copies the file \a fileName to \a newName. Returns \c true if successful;
- otherwise returns \c false.
+ Copies the file named \a fileName to \a newName.
- If a file with the name \a newName already exists, copy() returns \c false
- (i.e., QFile will not overwrite it).
+ \include qfile-copy.qdocinc
+
+ \note On Android, this operation is not yet supported for \c content
+ scheme URIs.
\sa rename()
*/
@@ -965,7 +890,14 @@ QFile::copy(const QString &fileName, const QString &newName)
\note In \l{QIODevice::}{WriteOnly} or \l{QIODevice::}{ReadWrite}
mode, if the relevant file does not already exist, this function
- will try to create a new file before opening it.
+ will try to create a new file before opening it. The file will be
+ created with mode 0666 masked by the umask on POSIX systems, and
+ with permissions inherited from the parent directory on Windows.
+ On Android, it's expected to have access permission to the parent
+ of the file name, otherwise, it won't be possible to create this
+ non-existing file.
+
+ \sa QT_USE_NODISCARD_FILE_OPEN
\sa QIODevice::OpenMode, setFileName()
*/
@@ -991,7 +923,52 @@ bool QFile::open(OpenMode mode)
return true;
}
QFile::FileError err = d->fileEngine->error();
- if(err == QFile::UnspecifiedError)
+ if (err == QFile::UnspecifiedError)
+ err = QFile::OpenError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+}
+
+/*!
+ \overload
+
+ If the file does not exist and \a mode implies creating it, it is created
+ with the specified \a permissions.
+
+ On POSIX systems the actual permissions are influenced by the
+ value of \c umask.
+
+ On Windows the permissions are emulated using ACLs. These ACLs may be in non-canonical
+ order when the group is granted less permissions than others. Files and directories with
+ such permissions will generate warnings when the Security tab of the Properties dialog
+ is opened. Granting the group all permissions granted to others avoids such warnings.
+
+ \sa QIODevice::OpenMode, setFileName(), QT_USE_NODISCARD_FILE_OPEN
+ \since 6.3
+*/
+bool QFile::open(OpenMode mode, QFile::Permissions permissions)
+{
+ Q_D(QFile);
+ if (isOpen())
+ return file_already_open(*this);
+ // Either Append or NewOnly implies WriteOnly
+ if (mode & (Append | NewOnly))
+ mode |= WriteOnly;
+ unsetError();
+ if ((mode & (ReadOnly | WriteOnly)) == 0) {
+ qWarning("QIODevice::open: File access not specified");
+ return false;
+ }
+
+ // QIODevice provides the buffering, so there's no need to request it from the file engine.
+ if (d->engine()->open(mode | QIODevice::Unbuffered, permissions)) {
+ QIODevice::open(mode);
+ if (mode & Append)
+ seek(size());
+ return true;
+ }
+ QFile::FileError err = d->fileEngine->error();
+ if (err == QFile::UnspecifiedError)
err = QFile::OpenError;
d->setError(err, d->fileEngine->errorString());
return false;
@@ -1023,7 +1000,7 @@ bool QFile::open(OpenMode mode)
you cannot use this QFile with a QFileInfo.
\endlist
- \sa close()
+ \sa close(), QT_USE_NODISCARD_FILE_OPEN
\b{Note for the Windows Platform}
@@ -1081,11 +1058,6 @@ bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
then calling close() closes the adopted handle.
Otherwise, close() does not actually close the file, but only flushes it.
- The QFile that is opened using this function is automatically set
- to be in raw mode; this means that the file input/output functions
- are slow. If you run into performance issues, you should try to
- use one of the other open functions.
-
\warning If \a fd is not a regular file, e.g, it is 0 (\c stdin),
1 (\c stdout), or 2 (\c stderr), you may not be able to seek(). In
those cases, size() returns \c 0. See QIODevice::isSequential()
@@ -1094,7 +1066,7 @@ bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
\warning Since this function opens the file without specifying the file name,
you cannot use this QFile with a QFileInfo.
- \sa close()
+ \sa close(), QT_USE_NODISCARD_FILE_OPEN
*/
bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
{
@@ -1214,6 +1186,8 @@ qint64 QFile::size() const
\since 6.0
Constructs a new file object to represent the file with the given \a name.
+
+ \include qfile.cpp qfile-explicit-constructor-note
*/
/*!
\fn QFile::QFile(const std::filesystem::path &name, QObject *parent)
@@ -1257,7 +1231,148 @@ qint64 QFile::size() const
\since 6.0
\overload
*/
+/*!
+ \fn bool exists(const std::filesystem::path &fileName)
+ \since 6.3
+ \overload
+*/
+/*!
+ \fn std::filesystem::path QFile::filesystemSymLinkTarget() const
+ \since 6.3
+ Returns symLinkTarget() as \c{std::filesystem::path}.
+*/
+/*!
+ \fn std::filesystem::path QFile::filesystemSymLinkTarget(const std::filesystem::path &fileName)
+ \since 6.3
+ Returns symLinkTarget() as \c{std::filesystem::path} of \a fileName.
+*/
+/*!
+ \fn bool remove(const std::filesystem::path &fileName)
+ \since 6.3
+ \overload
+*/
+/*!
+ \fn bool moveToTrash(const std::filesystem::path &fileName, QString *pathInTrash)
+ \since 6.3
+ \overload
+*/
+/*!
+ \fn bool rename(const std::filesystem::path &oldName, const std::filesystem::path &newName)
+ \since 6.3
+ \overload
+*/
+/*!
+ \fn bool link(const std::filesystem::path &fileName, const std::filesystem::path &newName);
+ \since 6.3
+ \overload
+*/
+/*!
+ \fn bool copy(const std::filesystem::path &fileName, const std::filesystem::path &newName);
+ \since 6.3
+ \overload
+*/
+
+/*!
+ \class QNtfsPermissionCheckGuard
+ \since 6.6
+ \inmodule QtCore
+ \brief The QNtfsPermissionCheckGuard class is a RAII class to manage NTFS
+ permission checking.
+
+ \ingroup io
+
+ For performance reasons, QFile, QFileInfo, and related classes do not
+ perform full ownership and permission (ACL) checking on NTFS file systems
+ by default. During the lifetime of any instance of this class, that
+ default is overridden and advanced checking is performed. This provides
+ a safe and easy way to manage enabling and disabling this change to the
+ default behavior.
+
+ Example:
+
+ \snippet ntfsp.cpp raii
+
+ This class is available only on Windows.
+
+ \section1 qt_ntfs_permission_lookup
+
+ Prior to Qt 6.6, the user had to directly manipulate the global variable
+ \c qt_ntfs_permission_lookup. However, this was a non-atomic global
+ variable and as such it was prone to data races.
+
+ The variable \c qt_ntfs_permission_lookup is therefore deprecated since Qt
+ 6.6.
+*/
+
+/*!
+ \fn QNtfsPermissionCheckGuard::QNtfsPermissionCheckGuard()
+
+ Creates a guard and calls the function qEnableNtfsPermissionChecks().
+*/
+
+/*!
+ \fn QNtfsPermissionCheckGuard::~QNtfsPermissionCheckGuard()
+
+ Destroys the guard and calls the function qDisableNtfsPermissionChecks().
+*/
+
+
+/*!
+ \fn bool qEnableNtfsPermissionChecks()
+ \since 6.6
+ \threadsafe
+ \relates QNtfsPermissionCheckGuard
+
+ Enables permission checking on NTFS file systems. Returns \c true if the check
+ was already enabled before the call to this function, meaning that there
+ are other users.
+
+ This function is only available on Windows and makes the direct
+ manipulation of \l qt_ntfs_permission_lookup obsolete.
+
+ This is a low-level function, please consider the RAII class
+ \l QNtfsPermissionCheckGuard instead.
+
+ \note The thread-safety of this function holds only as long as there are no
+ concurrent updates to \l qt_ntfs_permission_lookup.
+*/
+
+/*!
+ \fn bool qDisableNtfsPermissionChecks()
+ \since 6.6
+ \threadsafe
+ \relates QNtfsPermissionCheckGuard
+
+ Disables permission checking on NTFS file systems. Returns \c true if the
+ check is disabled, meaning that there are no more users.
+
+ This function is only available on Windows and makes the direct
+ manipulation of \l qt_ntfs_permission_lookup obsolete.
+
+ This is a low-level function and must (only) be called to match one earlier
+ call to qEnableNtfsPermissionChecks(). Please consider the RAII class
+ \l QNtfsPermissionCheckGuard instead.
+
+ \note The thread-safety of this function holds only as long as there are no
+ concurrent updates to \l qt_ntfs_permission_lookup.
+*/
+
+/*!
+ \fn bool qAreNtfsPermissionChecksEnabled()
+ \since 6.6
+ \threadsafe
+ \relates QNtfsPermissionCheckGuard
+
+ Checks the status of the permission checks on NTFS file systems. Returns
+ \c true if the check is enabled.
+
+ This function is only available on Windows and makes the direct
+ manipulation of \l qt_ntfs_permission_lookup obsolete.
+
+ \note The thread-safety of this function holds only as long as there are no
+ concurrent updates to \l qt_ntfs_permission_lookup.
+*/
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index dab20b85a1..058b2fa236 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILE_H
#define QFILE_H
@@ -47,6 +11,13 @@
#if QT_CONFIG(cxx17_filesystem)
#include <filesystem>
+#elif defined(Q_QDOC)
+namespace std {
+ namespace filesystem {
+ class path {
+ };
+ };
+};
#endif
#ifdef open
@@ -55,6 +26,34 @@
QT_BEGIN_NAMESPACE
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+#if QT_DEPRECATED_SINCE(6,6)
+QT_DEPRECATED_VERSION_X_6_6("Use QNtfsPermissionCheckGuard RAII class instead.")
+Q_CORE_EXPORT extern int qt_ntfs_permission_lookup; // defined in qfilesystemengine_win.cpp
+#endif
+
+Q_CORE_EXPORT bool qEnableNtfsPermissionChecks() noexcept;
+Q_CORE_EXPORT bool qDisableNtfsPermissionChecks() noexcept;
+Q_CORE_EXPORT bool qAreNtfsPermissionChecksEnabled() noexcept;
+
+class QNtfsPermissionCheckGuard
+{
+ Q_DISABLE_COPY_MOVE(QNtfsPermissionCheckGuard)
+public:
+ Q_NODISCARD_CTOR
+ QNtfsPermissionCheckGuard()
+ {
+ qEnableNtfsPermissionChecks();
+ }
+
+ ~QNtfsPermissionCheckGuard()
+ {
+ qDisableNtfsPermissionChecks();
+ }
+};
+#endif // Q_OS_WIN
+
#if QT_CONFIG(cxx17_filesystem)
namespace QtPrivate {
inline QString fromFilesystemPath(const std::filesystem::path &path)
@@ -68,11 +67,8 @@ inline QString fromFilesystemPath(const std::filesystem::path &path)
inline std::filesystem::path toFilesystemPath(const QString &path)
{
-#ifdef Q_OS_WIN
- return std::filesystem::path(path.toStdU16String());
-#else
- return std::filesystem::path(path.toStdString());
-#endif
+ return std::filesystem::path(reinterpret_cast<const char16_t *>(path.cbegin()),
+ reinterpret_cast<const char16_t *>(path.cend()));
}
// Both std::filesystem::path and QString (without QT_NO_CAST_FROM_ASCII) can be implicitly
@@ -86,6 +82,13 @@ using ForceFilesystemPath = typename std::enable_if_t<std::is_same_v<std::filesy
class QTemporaryFile;
class QFilePrivate;
+// ### Qt 7: remove this, and make constructors always explicit.
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)) || defined(QT_EXPLICIT_QFILE_CONSTRUCTION_FROM_PATH)
+# define QFILE_MAYBE_EXPLICIT explicit
+#else
+# define QFILE_MAYBE_EXPLICIT Q_IMPLICIT
+#endif
+
class Q_CORE_EXPORT QFile : public QFileDevice
{
#ifndef QT_NO_QOBJECT
@@ -95,12 +98,12 @@ class Q_CORE_EXPORT QFile : public QFileDevice
public:
QFile();
- QFile(const QString &name);
-#ifdef Q_CLANG_QDOC
- QFile(const std::filesystem::path &name);
+ QFILE_MAYBE_EXPLICIT QFile(const QString &name);
+#ifdef Q_QDOC
+ QFILE_MAYBE_EXPLICIT QFile(const std::filesystem::path &name);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
- QFile(const T &name) : QFile(QtPrivate::fromFilesystemPath(name))
+ QFILE_MAYBE_EXPLICIT QFile(const T &name) : QFile(QtPrivate::fromFilesystemPath(name))
{
}
#endif // QT_CONFIG(cxx17_filesystem)
@@ -109,7 +112,7 @@ public:
explicit QFile(QObject *parent);
QFile(const QString &name, QObject *parent);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QFile(const std::filesystem::path &path, QObject *parent);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
@@ -121,12 +124,12 @@ public:
~QFile();
QString fileName() const override;
-#if QT_CONFIG(cxx17_filesystem)
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
std::filesystem::path filesystemFileName() const
{ return QtPrivate::toFilesystemPath(fileName()); }
#endif
void setFileName(const QString &name);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
void setFileName(const std::filesystem::path &name);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
@@ -166,70 +169,123 @@ public:
}
#endif
-#if QT_DEPRECATED_SINCE(5,0)
- typedef QByteArray (*EncoderFn)(const QString &fileName);
- typedef QString (*DecoderFn)(const QByteArray &localfileName);
- QT_DEPRECATED static void setEncodingFunction(EncoderFn) {}
- QT_DEPRECATED static void setDecodingFunction(DecoderFn) {}
-#endif
-
bool exists() const;
static bool exists(const QString &fileName);
+#ifdef Q_QDOC
+ static bool exists(const std::filesystem::path &fileName);
+#elif QT_CONFIG(cxx17_filesystem)
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static bool exists(const T &fileName)
+ {
+ return exists(QtPrivate::fromFilesystemPath(fileName));
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QFile::symLinkTarget() instead")
- QString readLink() const;
- QT_DEPRECATED_X("Use QFile::symLinkTarget(QString) instead")
- static QString readLink(const QString &fileName);
-#endif
QString symLinkTarget() const;
static QString symLinkTarget(const QString &fileName);
+#ifdef Q_QDOC
+ std::filesystem::path filesystemSymLinkTarget() const;
+ static std::filesystem::path filesystemSymLinkTarget(const std::filesystem::path &fileName);
+#elif QT_CONFIG(cxx17_filesystem)
+ std::filesystem::path filesystemSymLinkTarget() const
+ {
+ return QtPrivate::toFilesystemPath(symLinkTarget());
+ }
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static std::filesystem::path filesystemSymLinkTarget(const T &fileName)
+ {
+ return QtPrivate::toFilesystemPath(symLinkTarget(QtPrivate::fromFilesystemPath(fileName)));
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
bool remove();
static bool remove(const QString &fileName);
+#ifdef Q_QDOC
+ static bool remove(const std::filesystem::path &fileName);
+#elif QT_CONFIG(cxx17_filesystem)
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static bool remove(const T &fileName)
+ {
+ return remove(QtPrivate::fromFilesystemPath(fileName));
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
bool moveToTrash();
static bool moveToTrash(const QString &fileName, QString *pathInTrash = nullptr);
+#ifdef Q_QDOC
+ static bool moveToTrash(const std::filesystem::path &fileName, QString *pathInTrash = nullptr);
+#elif QT_CONFIG(cxx17_filesystem)
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static bool moveToTrash(const T &fileName, QString *pathInTrash = nullptr)
+ {
+ return moveToTrash(QtPrivate::fromFilesystemPath(fileName), pathInTrash);
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
bool rename(const QString &newName);
-#ifdef Q_CLANG_QDOC
+ static bool rename(const QString &oldName, const QString &newName);
+#ifdef Q_QDOC
bool rename(const std::filesystem::path &newName);
+ static bool rename(const std::filesystem::path &oldName,
+ const std::filesystem::path &newName);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
bool rename(const T &newName)
{
return rename(QtPrivate::fromFilesystemPath(newName));
}
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static bool rename(const T &oldName, const T &newName)
+ {
+ return rename(QtPrivate::fromFilesystemPath(oldName),
+ QtPrivate::fromFilesystemPath(newName));
+ }
#endif // QT_CONFIG(cxx17_filesystem)
- static bool rename(const QString &oldName, const QString &newName);
bool link(const QString &newName);
-#ifdef Q_CLANG_QDOC
+ static bool link(const QString &fileName, const QString &newName);
+#ifdef Q_QDOC
bool link(const std::filesystem::path &newName);
+ static bool link(const std::filesystem::path &fileName,
+ const std::filesystem::path &newName);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
bool link(const T &newName)
{
return link(QtPrivate::fromFilesystemPath(newName));
}
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static bool link(const T &fileName, const T &newName)
+ {
+ return link(QtPrivate::fromFilesystemPath(fileName),
+ QtPrivate::fromFilesystemPath(newName));
+ }
#endif // QT_CONFIG(cxx17_filesystem)
- static bool link(const QString &oldname, const QString &newName);
bool copy(const QString &newName);
-#ifdef Q_CLANG_QDOC
+ static bool copy(const QString &fileName, const QString &newName);
+#ifdef Q_QDOC
bool copy(const std::filesystem::path &newName);
+ static bool copy(const std::filesystem::path &fileName,
+ const std::filesystem::path &newName);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
bool copy(const T &newName)
{
return copy(QtPrivate::fromFilesystemPath(newName));
}
+ template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
+ static bool copy(const T &fileName, const T &newName)
+ {
+ return copy(QtPrivate::fromFilesystemPath(fileName),
+ QtPrivate::fromFilesystemPath(newName));
+ }
#endif // QT_CONFIG(cxx17_filesystem)
- static bool copy(const QString &fileName, const QString &newName);
- bool open(OpenMode flags) override;
- bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
- bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
+ QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override;
+ QFILE_MAYBE_NODISCARD bool open(OpenMode flags, Permissions permissions);
+ QFILE_MAYBE_NODISCARD bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
+ QFILE_MAYBE_NODISCARD bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
qint64 size() const override;
@@ -240,7 +296,7 @@ public:
static Permissions permissions(const QString &filename);
bool setPermissions(Permissions permissionSpec) override;
static bool setPermissions(const QString &filename, Permissions permissionSpec);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
static Permissions permissions(const std::filesystem::path &filename);
static bool setPermissions(const std::filesystem::path &filename, Permissions permissionSpec);
#elif QT_CONFIG(cxx17_filesystem)
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index 545890c6b3..e4e305309a 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILE_P_H
#define QFILE_P_H
@@ -67,8 +31,8 @@ protected:
QFilePrivate();
~QFilePrivate();
- bool openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags);
- bool openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags);
+ bool openExternalFile(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags);
+ bool openExternalFile(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags);
QAbstractFileEngine *engine() const override;
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index 4b1809010b..431dc65f5b 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -1,49 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qfiledevice.h"
#include "qfiledevice_p.h"
#include "qfsfileengine_p.h"
-#include <private/qmemory_p.h>
-
#ifdef QT_NO_QOBJECT
#define tr(X) QString::fromLatin1(X)
#endif
@@ -61,13 +23,12 @@ QFileDevicePrivate::QFileDevicePrivate()
writeBufferChunkSize = QFILE_WRITEBUFFER_SIZE;
}
-QFileDevicePrivate::~QFileDevicePrivate()
- = default;
+QFileDevicePrivate::~QFileDevicePrivate() = default;
-QAbstractFileEngine * QFileDevicePrivate::engine() const
+QAbstractFileEngine *QFileDevicePrivate::engine() const
{
if (!fileEngine)
- fileEngine = qt_make_unique<QFSFileEngine>();
+ fileEngine = std::make_unique<QFSFileEngine>();
return fileEngine.get();
}
@@ -128,9 +89,9 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
\value ReadGroup The file is readable by the group.
\value WriteGroup The file is writable by the group.
\value ExeGroup The file is executable by the group.
- \value ReadOther The file is readable by anyone.
- \value WriteOther The file is writable by anyone.
- \value ExeOther The file is executable by anyone.
+ \value ReadOther The file is readable by others.
+ \value WriteOther The file is writable by others.
+ \value ExeOther The file is executable by others.
\warning Because of differences in the platforms supported by Qt,
the semantics of ReadUser, WriteUser and ExeUser are
@@ -148,6 +109,25 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
decrementing \c qt_ntfs_permission_lookup by 1.
\snippet ntfsp.cpp 1
+
+ \note Since this is a non-atomic global variable, it is only safe
+ to increment or decrement \c qt_ntfs_permission_lookup before any
+ threads other than the main thread have started or after every thread
+ other than the main thread has ended.
+
+ \note From Qt 6.6 the variable \c qt_ntfs_permission_lookup is
+ deprecated. Please use the following alternatives.
+
+ The safe and easy way to manage permission checks is to use the RAII class
+ \c QNtfsPermissionCheckGuard.
+
+ \snippet ntfsp.cpp raii
+
+ If you need more fine-grained control, it is possible to manage the permission
+ with the following functions instead:
+
+ \snippet ntfsp.cpp free-funcs
+
*/
//************* QFileDevice
@@ -166,10 +146,10 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
QFileDevice is the base class for I/O devices that can read and write text and binary files
and \l{The Qt Resource System}{resources}. QFile offers the main functionality,
QFileDevice serves as a base class for sharing functionality with other file devices such
- as QTemporaryFile, by providing all the operations that can be done on files that have
- been opened by QFile or QTemporaryFile.
+ as QSaveFile, by providing all the operations that can be done on files that have
+ been opened by QFile or QSaveFile.
- \sa QFile, QTemporaryFile
+ \sa QFile, QSaveFile
*/
/*!
@@ -188,6 +168,35 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
handle is left open when the QFile object is destroyed.
*/
+/*!
+ \macro QT_USE_NODISCARD_FILE_OPEN
+ \macro QT_NO_USE_NODISCARD_FILE_OPEN
+ \relates QFileDevice
+ \since 6.8
+
+ File-related I/O classes (such as QFile, QSaveFile, QTemporaryFile)
+ have an \c{open()} method to open the file they act upon. It is
+ important to check the return value of the call to \c{open()}
+ before proceeding with reading or writing data into the file.
+
+ For this reason, starting with Qt 6.8, some overloads of \c{open()}
+ have been marked with the \c{[[nodiscard]]} attribute. Since this
+ change may raise warnings in existing codebases, user code can
+ opt-in or opt-out from having the attribute applied by defining
+ certain macros:
+
+ \list
+ \li If the \c{QT_USE_NODISCARD_FILE_OPEN} macro is defined,
+ overloads of \c{open()} are marked as \c{[[nodiscard]]}.
+ \li If the \c{QT_NO_USE_NODISCARD_FILE_OPEN} is defined, the
+ overloads of \c{open()} are \e{not} marked as \c{[[nodiscard]]}.
+ \li If neither macro is defined, then the default up to and
+ including Qt 6.9 is not to have the attribute. Starting from Qt 6.10,
+ the attribute is automatically applied.
+ \li If both macros are defined, the program is ill-formed.
+ \endlist
+*/
+
#ifdef QT_NO_QOBJECT
QFileDevice::QFileDevice()
: QIODevice(*new QFileDevicePrivate)
@@ -645,7 +654,7 @@ QFile::Permissions QFileDevice::permissions() const
{
Q_D(const QFileDevice);
QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
- return QFile::Permissions((int)perms); //ewww
+ return QFile::Permissions::fromInt(perms.toInt()); //ewww
}
/*!
@@ -661,7 +670,7 @@ QFile::Permissions QFileDevice::permissions() const
bool QFileDevice::setPermissions(Permissions permissions)
{
Q_D(QFileDevice);
- if (d->engine()->setPermissions(permissions)) {
+ if (d->engine()->setPermissions(permissions.toInt())) {
unsetError();
return true;
}
@@ -670,7 +679,7 @@ bool QFileDevice::setPermissions(Permissions permissions)
}
/*!
- \enum QFileDevice::MemoryMapFlags
+ \enum QFileDevice::MemoryMapFlag
\since 4.4
This enum describes special options that may be used by the map()
@@ -754,15 +763,6 @@ bool QFileDevice::unmap(uchar *address)
\sa setFileTime(), fileTime(), QFileInfo::fileTime()
*/
-static inline QAbstractFileEngine::FileTime FileDeviceTimeToAbstractFileEngineTime(QFileDevice::FileTime time)
-{
- static_assert(int(QFileDevice::FileAccessTime) == int(QAbstractFileEngine::AccessTime));
- static_assert(int(QFileDevice::FileBirthTime) == int(QAbstractFileEngine::BirthTime));
- static_assert(int(QFileDevice::FileMetadataChangeTime) == int(QAbstractFileEngine::MetadataChangeTime));
- static_assert(int(QFileDevice::FileModificationTime) == int(QAbstractFileEngine::ModificationTime));
- return QAbstractFileEngine::FileTime(time);
-}
-
/*!
\since 5.10
Returns the file time specified by \a time.
@@ -776,7 +776,7 @@ QDateTime QFileDevice::fileTime(QFileDevice::FileTime time) const
Q_D(const QFileDevice);
if (d->engine())
- return d->engine()->fileTime(FileDeviceTimeToAbstractFileEngineTime(time));
+ return d->engine()->fileTime(time);
return QDateTime();
}
@@ -799,7 +799,7 @@ bool QFileDevice::setFileTime(const QDateTime &newDate, QFileDevice::FileTime fi
return false;
}
- if (!d->fileEngine->setFileTime(newDate, FileDeviceTimeToAbstractFileEngineTime(fileTime))) {
+ if (!d->fileEngine->setFileTime(newDate, fileTime)) {
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
return false;
}
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
index 2d524193c5..5274025715 100644
--- a/src/corelib/io/qfiledevice.h
+++ b/src/corelib/io/qfiledevice.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILEDEVICE_H
#define QFILEDEVICE_H
@@ -48,6 +12,22 @@ QT_BEGIN_NAMESPACE
class QDateTime;
class QFileDevicePrivate;
+#if !defined(QT_USE_NODISCARD_FILE_OPEN) && !defined(QT_NO_USE_NODISCARD_FILE_OPEN)
+# if QT_VERSION < QT_VERSION_CHECK(6, 10, 0)
+# define QT_NO_USE_NODISCARD_FILE_OPEN
+# else
+# define QT_USE_NODISCARD_FILE_OPEN
+# endif
+#endif
+
+#if defined(QT_USE_NODISCARD_FILE_OPEN) && defined(QT_NO_USE_NODISCARD_FILE_OPEN)
+#error "Inconsistent macro definition for nodiscard QFile::open"
+#elif defined(QT_USE_NODISCARD_FILE_OPEN)
+#define QFILE_MAYBE_NODISCARD [[nodiscard]]
+#else /* QT_NO_USE_NODISCARD_FILE_OPEN */
+#define QFILE_MAYBE_NODISCARD
+#endif
+
class Q_CORE_EXPORT QFileDevice : public QIODevice
{
#ifndef QT_NO_QOBJECT
@@ -118,11 +98,11 @@ public:
virtual Permissions permissions() const;
virtual bool setPermissions(Permissions permissionSpec);
- // ### Qt 6: rename to MemoryMapFlag & make it a QFlags
- enum MemoryMapFlags {
+ enum MemoryMapFlag {
NoOptions = 0,
MapPrivateOption = 0x0001
};
+ Q_DECLARE_FLAGS(MemoryMapFlags, MemoryMapFlag)
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
bool unmap(uchar *address);
@@ -148,6 +128,8 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::Permissions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::FileHandleFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::MemoryMapFlags)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfiledevice_p.h b/src/corelib/io/qfiledevice_p.h
index aef3fca811..72b43ed5a1 100644
--- a/src/corelib/io/qfiledevice_p.h
+++ b/src/corelib/io/qfiledevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILEDEVICE_P_H
#define QFILEDEVICE_P_H
@@ -52,8 +16,22 @@
//
#include "private/qiodevice_p.h"
+#include "qfiledevice.h"
#include <memory>
+#if defined(Q_OS_UNIX)
+# include <sys/types.h> // for mode_t
+# include <sys/stat.h> // for mode_t constants
+#elif defined(Q_OS_WINDOWS)
+# include <qt_windows.h>
+# include <winnt.h> // for SECURITY_DESCRIPTOR
+# include <optional>
+# if defined(QT_BOOTSTRAPPED)
+# define QT_FEATURE_fslibs -1
+# else
+# define QT_FEATURE_fslibs 1
+# endif // QT_BOOTSTRAPPED
+#endif
QT_BEGIN_NAMESPACE
@@ -98,6 +76,63 @@ inline bool QFileDevicePrivate::ensureFlushed() const
return true;
}
+#ifdef Q_OS_UNIX
+namespace QtPrivate {
+
+constexpr mode_t toMode_t(QFileDevice::Permissions permissions)
+{
+ mode_t mode = 0;
+ if (permissions & (QFileDevice::ReadOwner | QFileDevice::ReadUser))
+ mode |= S_IRUSR;
+ if (permissions & (QFileDevice::WriteOwner | QFileDevice::WriteUser))
+ mode |= S_IWUSR;
+ if (permissions & (QFileDevice::ExeOwner | QFileDevice::ExeUser))
+ mode |= S_IXUSR;
+ if (permissions & QFileDevice::ReadGroup)
+ mode |= S_IRGRP;
+ if (permissions & QFileDevice::WriteGroup)
+ mode |= S_IWGRP;
+ if (permissions & QFileDevice::ExeGroup)
+ mode |= S_IXGRP;
+ if (permissions & QFileDevice::ReadOther)
+ mode |= S_IROTH;
+ if (permissions & QFileDevice::WriteOther)
+ mode |= S_IWOTH;
+ if (permissions & QFileDevice::ExeOther)
+ mode |= S_IXOTH;
+ return mode;
+}
+
+} // namespace QtPrivate
+#elif defined(Q_OS_WINDOWS)
+
+class QNativeFilePermissions
+{
+public:
+ QNativeFilePermissions(std::optional<QFileDevice::Permissions> perms, bool isDir);
+
+ SECURITY_ATTRIBUTES *securityAttributes();
+ bool isOk() const { return ok; }
+
+private:
+ bool ok = false;
+ bool isNull = true;
+
+ // At most 1 allow + 1 deny ACEs for user and group, 1 allow ACE for others
+ static constexpr auto MaxNumACEs = 5;
+
+ static constexpr auto MaxACLSize =
+ sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) + SECURITY_MAX_SID_SIZE) * MaxNumACEs;
+
+ SECURITY_ATTRIBUTES sa;
+#if QT_CONFIG(fslibs)
+ SECURITY_DESCRIPTOR sd;
+ alignas(DWORD) char aclStorage[MaxACLSize];
+#endif
+};
+
+#endif // Q_OS_UNIX
+
QT_END_NAMESPACE
#endif // QFILEDEVICE_P_H
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index fb5aeac189..6bc0128aff 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qfileinfo.h"
@@ -46,6 +10,10 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN(QFileInfo)
+
QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
{
if (cache_enabled && !fileNames[(int)name].isNull())
@@ -67,9 +35,15 @@ QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
ret = entry.path();
break;
}
- case QAbstractFileEngine::LinkName:
+ case QAbstractFileEngine::AbsoluteLinkTarget:
ret = QFileSystemEngine::getLinkTarget(fileEntry, metaData).filePath();
break;
+ case QAbstractFileEngine::RawLinkPath:
+ ret = QFileSystemEngine::getRawLinkPath(fileEntry, metaData).filePath();
+ break;
+ case QAbstractFileEngine::JunctionName:
+ ret = QFileSystemEngine::getJunctionTarget(fileEntry, metaData).filePath();
+ break;
case QAbstractFileEngine::BundleName:
ret = QFileSystemEngine::bundleName(fileEntry);
break;
@@ -92,7 +66,7 @@ QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
ret = fileEngine->fileName(name);
}
if (ret.isNull())
- ret = QLatin1String("");
+ ret = ""_L1;
if (cache_enabled)
fileNames[(int)name] = ret;
return ret;
@@ -116,7 +90,7 @@ QString QFileInfoPrivate::getFileOwner(QAbstractFileEngine::FileOwner own) const
ret = fileEngine->owner(own);
}
if (ret.isNull())
- ret = QLatin1String("");
+ ret = ""_L1;
if (cache_enabled)
fileOwners[(int)own] = ret;
return ret;
@@ -127,11 +101,11 @@ uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) cons
Q_ASSERT(fileEngine); // should never be called when using the native FS
// We split the testing into tests for for LinkType, BundleType, PermsMask
// and the rest.
- // Tests for file permissions on Windows can be slow, expecially on network
+ // Tests for file permissions on Windows can be slow, especially on network
// paths and NTFS drives.
// In order to determine if a file is a symlink or not, we have to lstat().
// If we're not interested in that information, we might as well avoid one
- // extra syscall. Bundle detecton on Mac can be slow, expecially on network
+ // extra syscall. Bundle detecton on Mac can be slow, especially on network
// paths, so we separate out that as well.
QAbstractFileEngine::FileFlags req;
@@ -176,14 +150,14 @@ uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) cons
req |= QAbstractFileEngine::Refresh;
QAbstractFileEngine::FileFlags flags = fileEngine->fileFlags(req);
- fileFlags |= uint(flags);
+ fileFlags |= uint(flags.toInt());
setCachedFlag(cachedFlags);
}
- return fileFlags & request;
+ return fileFlags & request.toInt();
}
-QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) const
+QDateTime &QFileInfoPrivate::getFileTime(QFile::FileTime request) const
{
Q_ASSERT(fileEngine); // should never be called when using the native FS
if (!cache_enabled)
@@ -191,16 +165,16 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
uint cf = 0;
switch (request) {
- case QAbstractFileEngine::AccessTime:
+ case QFile::FileAccessTime:
cf = CachedATime;
break;
- case QAbstractFileEngine::BirthTime:
+ case QFile::FileBirthTime:
cf = CachedBTime;
break;
- case QAbstractFileEngine::MetadataChangeTime:
+ case QFile::FileMetadataChangeTime:
cf = CachedMCTime;
break;
- case QAbstractFileEngine::ModificationTime:
+ case QFile::FileModificationTime:
cf = CachedMTime;
break;
}
@@ -218,69 +192,84 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
\class QFileInfo
\inmodule QtCore
\reentrant
- \brief The QFileInfo class provides system-independent file information.
+ \brief The QFileInfo class provides an OS-independent API to retrieve
+ information about file system entries.
\ingroup io
\ingroup shared
- QFileInfo provides information about a file's name and position
- (path) in the file system, its access rights and whether it is a
- directory or symbolic link, etc. The file's size and last
- modified/read times are also available. QFileInfo can also be
- used to obtain information about a Qt \l{resource
- system}{resource}.
-
- A QFileInfo can point to a file with either a relative or an
- absolute file path. Absolute file paths begin with the directory
- separator "/" (or with a drive specification on Windows). Relative
- file names begin with a directory name or a file name and specify
- a path relative to the current working directory. An example of an
- absolute path is the string "/tmp/quartz". A relative path might
- look like "src/fatlib". You can use the function isRelative() to
- check whether a QFileInfo is using a relative or an absolute file
- path. You can call the function makeAbsolute() to convert a
- relative QFileInfo's path to an absolute path.
-
- The file that the QFileInfo works on is set in the constructor or
- later with setFile(). Use exists() to see if the file exists and
- size() to get its size.
-
- The file's type is obtained with isFile(), isDir() and
- isSymLink(). The symLinkTarget() function provides the name of the file
- the symlink points to.
-
- On Unix (including \macos and iOS), the property getter functions in this
- class return the properties such as times and size of the target file, not
- the symlink, because Unix handles symlinks transparently. Opening a symlink
- using QFile effectively opens the link's target. For example:
+ \compares equality
+
+ QFileInfo provides information about a file system entry, such as its
+ name, path, access rights and whether it is a regular file, directory or
+ symbolic link. The entry's size and last modified/read times are also
+ available. QFileInfo can also be used to obtain information about a Qt
+ \l{resource system}{resource}.
+
+ A QFileInfo can point to a file system entry with either an absolute or
+ a relative path:
+ \list
+ \li \include qfileinfo.cpp absolute-path-unix-windows
+
+ \li \include qfileinfo.cpp relative-path-note
+ \endlist
+
+ An example of an absolute path is the string \c {"/tmp/quartz"}. A relative
+ path may look like \c {"src/fatlib"}. You can use the function isRelative()
+ to check whether a QFileInfo is using a relative or an absolute path. You
+ can call the function makeAbsolute() to convert a relative QFileInfo's
+ path to an absolute path.
+
+//! [qresource-virtual-fs-colon]
+ \note Paths starting with a colon (\e{:}) are always considered
+ absolute, as they denote a QResource.
+//! [qresource-virtual-fs-colon]
+
+ The file system entry path that the QFileInfo works on is set in the
+ constructor or later with setFile(). Use exists() to see if the entry
+ actually exists and size() to get its size.
+
+ The file system entry's type is obtained with isFile(), isDir(), and
+ isSymLink(). The symLinkTarget() function provides the absolute path of
+ the target the symlink points to.
+
+ The path elements of the file system entry can be extracted with path()
+ and fileName(). The fileName()'s parts can be extracted with baseName(),
+ suffix(), or completeSuffix(). QFileInfo objects referring to directories
+ created by Qt classes will not have a trailing directory separator
+ \c{'/'}. If you wish to use trailing separators in your own file info
+ objects, just append one to the entry's path given to the constructors
+ or setFile().
+
+ Date and time related information are returned by birthTime(), fileTime(),
+ lastModified(), lastRead(), and metadataChangeTime().
+ Information about
+ access permissions can be obtained with isReadable(), isWritable(), and
+ isExecutable(). Ownership information can be obtained with
+ owner(), ownerId(), group(), and groupId(). You can also examine
+ permissions and ownership in a single statement using the permission()
+ function.
+
+ \section1 Symbolic Links and Shortcuts
+
+ On Unix (including \macos and iOS), the property getter functions in
+ this class return the properties such as times and size of the target,
+ not the symlink, because Unix handles symlinks transparently. Opening
+ a symlink using QFile effectively opens the link's target. For example:
\snippet code/src_corelib_io_qfileinfo.cpp 0
On Windows, shortcuts (\c .lnk files) are currently treated as symlinks. As
- on Unix systems, the property getters return the size of the targeted file,
- not the \c .lnk file itself. This behavior is deprecated and will likely be
- removed in a future version of Qt, after which \c .lnk files will be treated
- as regular files.
+ on Unix systems, the property getters return the size of the target,
+ not the \c .lnk file itself. This behavior is deprecated and will likely
+ be removed in a future version of Qt, after which \c .lnk files will be
+ treated as regular files.
\snippet code/src_corelib_io_qfileinfo.cpp 1
- Elements of the file's name can be extracted with path() and
- fileName(). The fileName()'s parts can be extracted with
- baseName(), suffix() or completeSuffix(). QFileInfo objects to
- directories created by Qt classes will not have a trailing file
- separator. If you wish to use trailing separators in your own file
- info objects, just append one to the file name given to the constructors
- or setFile().
-
- The file's dates are returned by birthTime(), lastModified(), lastRead() and
- fileTime(). Information about the file's access permissions is
- obtained with isReadable(), isWritable() and isExecutable(). The
- file's ownership is available from owner(), ownerId(), group() and
- groupId(). You can examine a file's permissions and ownership in a
- single statement using the permission() function.
+ \section1 NTFS permissions
- \target NTFS permissions
- \note On NTFS file systems, ownership and permissions checking is
+ On NTFS file systems, ownership and permissions checking is
disabled by default for performance reasons. To enable it,
include the following line:
@@ -291,23 +280,54 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
\snippet ntfsp.cpp 1
- \section1 Performance Issues
+ \note Since this is a non-atomic global variable, it is only safe
+ to increment or decrement \c qt_ntfs_permission_lookup before any
+ threads other than the main thread have started or after every thread
+ other than the main thread has ended.
+
+ \note From Qt 6.6 the variable \c qt_ntfs_permission_lookup is
+ deprecated. Please use the following alternatives.
+
+ The safe and easy way to manage permission checks is to use the RAII class
+ \c QNtfsPermissionCheckGuard.
+
+ \snippet ntfsp.cpp raii
+
+ If you need more fine-grained control, it is possible to manage the permission
+ with the following functions instead:
+
+ \snippet ntfsp.cpp free-funcs
+
+ \section1 Performance Considerations
+
+ Some of QFileInfo's functions have to query the file system, but for
+ performance reasons, some functions only operate on the path string.
+ For example: To return the absolute path of a relative entry's path,
+ absolutePath() has to query the file system. The path() function, however,
+ can work on the file name directly, and so it is faster.
+
+ QFileInfo also caches information about the file system entry it refers
+ to. Because the file system can be changed by other users or programs,
+ or even by other parts of the same program, there is a function that
+ refreshes the information stored in QFileInfo, namely refresh(). To switch
+ off a QFileInfo's caching (that is, force it to query the underlying file
+ system every time you request information from it), call setCaching(false).
- Some of QFileInfo's functions query the file system, but for
- performance reasons, some functions only operate on the
- file name itself. For example: To return the absolute path of
- a relative file name, absolutePath() has to query the file system.
- The path() function, however, can work on the file name directly,
- and so it is faster.
+ Fetching information from the file system is typically done by calling
+ (possibly) expensive system functions, so QFileInfo (depending on the
+ implementation) might not fetch all the information from the file system
+ at construction. To make sure that all information is read from the file
+ system immediately, use the stat() member function.
- \note To speed up performance, QFileInfo caches information about
- the file.
+ \l{birthTime()}, \l{fileTime()}, \l{lastModified()}, \l{lastRead()},
+ and \l{metadataChangeTime()} return times in \e{local time} by default.
+ Since native file system API typically uses UTC, this requires a conversion.
+ If you don't actually need the local time, you can avoid this by requesting
+ the time in QTimeZone::UTC directly.
- Because files can be changed by other users or programs, or
- even by other parts of the same program, there is a function that
- refreshes the file information: refresh(). If you want to switch
- off a QFileInfo's caching and force it to access the file system
- every time you request information from it call setCaching(false).
+ \section1 Platform Specific Issues
+
+ \include android-content-uri-limitations.qdocinc
\sa QDir, QFile
*/
@@ -328,9 +348,8 @@ QFileInfo::QFileInfo(QFileInfoPrivate *p) : d_ptr(p)
}
/*!
- Constructs an empty QFileInfo object.
-
- Note that an empty QFileInfo object contain no file reference.
+ Constructs an empty QFileInfo object that doesn't refer to any file
+ system entry.
\sa setFile()
*/
@@ -339,12 +358,16 @@ QFileInfo::QFileInfo() : d_ptr(new QFileInfoPrivate())
}
/*!
- Constructs a new QFileInfo that gives information about the given
- file. The \a file can also include an absolute or relative path.
+ Constructs a QFileInfo that gives information about a file system entry
+ located at \a path that can be absolute or relative.
+
+//! [preserve-relative-path]
+ If \a path is relative, the QFileInfo will also have a relative path.
+//! [preserve-relative-path]
\sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath()
*/
-QFileInfo::QFileInfo(const QString &file) : d_ptr(new QFileInfoPrivate(file))
+QFileInfo::QFileInfo(const QString &path) : d_ptr(new QFileInfoPrivate(path))
{
}
@@ -357,24 +380,26 @@ QFileInfo::QFileInfo(const QString &file) : d_ptr(new QFileInfoPrivate(file))
\sa isRelative()
*/
-QFileInfo::QFileInfo(const QFile &file) : d_ptr(new QFileInfoPrivate(file.fileName()))
+QFileInfo::QFileInfo(const QFileDevice &file) : d_ptr(new QFileInfoPrivate(file.fileName()))
{
}
/*!
Constructs a new QFileInfo that gives information about the given
- \a file relative to the directory \a dir.
+ file system entry \a path that is relative to the directory \a dir.
+//! [preserve-relative-or-absolute]
If \a dir has a relative path, the QFileInfo will also have a
relative path.
- If \a file is an absolute path, then the directory specified
- by \a dir will be disregarded.
+ If \a path is absolute, then the directory specified by \a dir
+ will be disregarded.
+//! [preserve-relative-or-absolute]
\sa isRelative()
*/
-QFileInfo::QFileInfo(const QDir &dir, const QString &file)
- : d_ptr(new QFileInfoPrivate(dir.filePath(file)))
+QFileInfo::QFileInfo(const QDir &dir, const QString &path)
+ : d_ptr(new QFileInfoPrivate(dir.filePath(path)))
{
}
@@ -396,58 +421,57 @@ QFileInfo::~QFileInfo()
}
/*!
- \fn bool QFileInfo::operator!=(const QFileInfo &fileinfo) const
+ \fn bool QFileInfo::operator!=(const QFileInfo &lhs, const QFileInfo &rhs)
- Returns \c true if this QFileInfo object refers to a different file
- than the one specified by \a fileinfo; otherwise returns \c false.
+ Returns \c true if QFileInfo \a lhs refers to a different file system
+ entry than the one referred to by \a rhs; otherwise returns \c false.
\sa operator==()
*/
/*!
- Returns \c true if this QFileInfo object refers to a file in the same
- location as \a fileinfo; otherwise returns \c false.
+ \fn bool QFileInfo::operator==(const QFileInfo &lhs, const QFileInfo &rhs)
+
+ Returns \c true if QFileInfo \a lhs and QFileInfo \a rhs refer to the same
+ entry on the file system; otherwise returns \c false.
- Note that the result of comparing two empty QFileInfo objects,
- containing no file references (file paths that do not exist or
- are empty), is undefined.
+ Note that the result of comparing two empty QFileInfo objects, containing
+ no file system entry references (paths that do not exist or are empty),
+ is undefined.
- \warning This will not compare two different symbolic links
- pointing to the same file.
+ \warning This will not compare two different symbolic links pointing to
+ the same target.
- \warning Long and short file names that refer to the same file on Windows
- are treated as if they referred to different files.
+ \warning On Windows, long and short paths that refer to the same file
+ system entry are treated as if they referred to different entries.
\sa operator!=()
*/
-bool QFileInfo::operator==(const QFileInfo &fileinfo) const
+bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
{
- Q_D(const QFileInfo);
- // ### Qt 5: understand long and short file names on Windows
- // ### (GetFullPathName()).
- if (fileinfo.d_ptr == d_ptr)
+ if (rhs.d_ptr == lhs.d_ptr)
return true;
- if (d->isDefaultConstructed || fileinfo.d_ptr->isDefaultConstructed)
+ if (lhs.d_ptr->isDefaultConstructed || rhs.d_ptr->isDefaultConstructed)
return false;
// Assume files are the same if path is the same
- if (d->fileEntry.filePath() == fileinfo.d_ptr->fileEntry.filePath())
+ if (lhs.d_ptr->fileEntry.filePath() == rhs.d_ptr->fileEntry.filePath())
return true;
Qt::CaseSensitivity sensitive;
- if (d->fileEngine == nullptr || fileinfo.d_ptr->fileEngine == nullptr) {
- if (d->fileEngine != fileinfo.d_ptr->fileEngine) // one is native, the other is a custom file-engine
+ if (lhs.d_ptr->fileEngine == nullptr || rhs.d_ptr->fileEngine == nullptr) {
+ if (lhs.d_ptr->fileEngine != rhs.d_ptr->fileEngine) // one is native, the other is a custom file-engine
return false;
sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
} else {
- if (d->fileEngine->caseSensitive() != fileinfo.d_ptr->fileEngine->caseSensitive())
+ if (lhs.d_ptr->fileEngine->caseSensitive() != rhs.d_ptr->fileEngine->caseSensitive())
return false;
- sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ sensitive = lhs.d_ptr->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
}
// Fallback to expensive canonical path computation
- return canonicalFilePath().compare(fileinfo.canonicalFilePath(), sensitive) == 0;
+ return lhs.canonicalFilePath().compare(rhs.canonicalFilePath(), sensitive) == 0;
}
/*!
@@ -468,24 +492,30 @@ QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)
*/
/*!
- Sets the file that the QFileInfo provides information about to \a
- file.
+ Sets the path of the file system entry that this QFileInfo provides
+ information about to \a path that can be absolute or relative.
+
+//! [absolute-path-unix-windows]
+ On Unix, absolute paths begin with the directory separator \c {'/'}.
+ On Windows, absolute paths begin with a drive specification (for example,
+ \c {D:/}).
+//! [ absolute-path-unix-windows]
- The \a file can also include an absolute or relative file path.
- Absolute paths begin with the directory separator (e.g. "/" under
- Unix) or a drive specification (under Windows). Relative file
- names begin with a directory name or a file name and specify a
- path relative to the current directory.
+//! [relative-path-note]
+ Relative paths begin with a directory name or a regular file name and
+ specify a file system entry's path relative to the current working
+ directory.
+//! [relative-path-note]
Example:
\snippet code/src_corelib_io_qfileinfo.cpp 2
\sa isRelative(), QDir::setCurrent(), QDir::isRelativePath()
*/
-void QFileInfo::setFile(const QString &file)
+void QFileInfo::setFile(const QString &path)
{
bool caching = d_ptr.constData()->cache_enabled;
- *this = QFileInfo(file);
+ *this = QFileInfo(path);
d_ptr->cache_enabled = caching;
}
@@ -500,7 +530,7 @@ void QFileInfo::setFile(const QString &file)
\sa isRelative()
*/
-void QFileInfo::setFile(const QFile &file)
+void QFileInfo::setFile(const QFileDevice &file)
{
setFile(file.fileName());
}
@@ -508,27 +538,29 @@ void QFileInfo::setFile(const QFile &file)
/*!
\overload
- Sets the file that the QFileInfo provides information about to \a
- file in directory \a dir.
+ Sets the path of the file system entry that this QFileInfo provides
+ information about to \a path in directory \a dir.
- If \a file includes a relative path, the QFileInfo will also
- have a relative path.
+ \include qfileinfo.cpp preserve-relative-or-absolute
\sa isRelative()
*/
-void QFileInfo::setFile(const QDir &dir, const QString &file)
+void QFileInfo::setFile(const QDir &dir, const QString &path)
{
- setFile(dir.filePath(file));
+ setFile(dir.filePath(path));
}
/*!
- Returns an absolute path including the file name.
+ Returns the absolute full path to the file system entry this QFileInfo
+ refers to, including the entry's name.
+
+ \include qfileinfo.cpp absolute-path-unix-windows
+
+//! [windows-network-shares]
+ On Windows, the paths of network shares that are not mapped to a drive
+ letter begin with \c{//sharename/}.
+//! [windows-network-shares]
- The absolute path name consists of the full path and the file
- name. On Unix this will always begin with the root, '/',
- directory. On Windows this will always begin 'D:/' where D is a
- drive letter, except for network shares that are not mapped to a
- drive letter, in which case the path will begin '//sharename/'.
QFileInfo will uppercase drive letters. Note that QDir does not do
this. The code snippet below shows this.
@@ -547,15 +579,16 @@ QString QFileInfo::absoluteFilePath() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->getFileName(QAbstractFileEngine::AbsoluteName);
}
/*!
- Returns the canonical path including the file name, i.e. an absolute
- path without symbolic links or redundant "." or ".." elements.
+ Returns the file system entry's canonical path, including the entry's
+ name, that is, an absolute path without symbolic links or redundant
+ \c{'.'} or \c{'..'} elements.
- If the file does not exist, canonicalFilePath() returns an empty
+ If the entry does not exist, canonicalFilePath() returns an empty
string.
\sa filePath(), absoluteFilePath(), dir()
@@ -564,19 +597,18 @@ QString QFileInfo::canonicalFilePath() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->getFileName(QAbstractFileEngine::CanonicalName);
}
/*!
- Returns a file's path absolute path. This doesn't include the
- file name.
+ Returns the absolute path of the file system entry this QFileInfo refers to,
+ excluding the entry's name.
+
+ \include qfileinfo.cpp absolute-path-unix-windows
- On Unix the absolute path will always begin with the root, '/',
- directory. On Windows this will always begin 'D:/' where D is a
- drive letter, except for network shares that are not mapped to a
- drive letter, in which case the path will begin '//sharename/'.
+ \include qfileinfo.cpp windows-network-shares
In contrast to canonicalPath() symbolic links or redundant "." or
".." elements are not necessarily removed.
@@ -590,17 +622,16 @@ QString QFileInfo::absolutePath() const
{
Q_D(const QFileInfo);
- if (d->isDefaultConstructed) {
- return QLatin1String("");
- }
+ if (d->isDefaultConstructed)
+ return ""_L1;
return d->getFileName(QAbstractFileEngine::AbsolutePathName);
}
/*!
- Returns the file's path canonical path (excluding the file name),
+ Returns the file system entry's canonical path (excluding the entry's name),
i.e. an absolute path without symbolic links or redundant "." or ".." elements.
- If the file does not exist, canonicalPath() returns an empty string.
+ If the entry does not exist, this method returns an empty string.
\sa path(), absolutePath()
*/
@@ -608,16 +639,16 @@ QString QFileInfo::canonicalPath() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->getFileName(QAbstractFileEngine::CanonicalPathName);
}
/*!
- Returns the file's path. This doesn't include the file name.
+ Returns the path of the file system entry this QFileInfo refers to,
+ excluding the entry's name.
- Note that, if this QFileInfo object is given a path ending in a
- slash, the name of the file is considered empty and this function
- will return the entire path.
+ \include qfileinfo.cpp path-ends-with-slash-empty-name-component
+ In this case, this function will return the entire path.
\sa filePath(), absolutePath(), canonicalPath(), dir(), fileName(), isRelative()
*/
@@ -625,23 +656,28 @@ QString QFileInfo::path() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->fileEntry.path();
}
/*!
\fn bool QFileInfo::isAbsolute() const
- Returns \c true if the file path name is absolute, otherwise returns
- false if the path is relative.
+ Returns \c true if the file system entry's path is absolute, otherwise
+ returns \c false (that is, the path is relative).
+
+ \include qfileinfo.cpp qresource-virtual-fs-colon
\sa isRelative()
*/
/*!
- Returns \c true if the file path name is relative, otherwise returns
- false if the path is absolute (e.g. under Unix a path is absolute
- if it begins with a "/").
+ Returns \c true if the file system entry's path is relative, otherwise
+ returns \c false (that is, the path is absolute).
+
+ \include qfileinfo.cpp absolute-path-unix-windows
+
+ \include qfileinfo.cpp qresource-virtual-fs-colon
\sa isAbsolute()
*/
@@ -656,9 +692,9 @@ bool QFileInfo::isRelative() const
}
/*!
- Converts the file's path to an absolute path if it is not already in that form.
- Returns \c true to indicate that the path was converted; otherwise returns \c false
- to indicate that the path was already absolute.
+ If the file system entry's path is relative, this method converts it to
+ an absolute path and returns \c true; if the path is already absolute,
+ this method returns \c false.
\sa filePath(), isRelative()
*/
@@ -673,10 +709,11 @@ bool QFileInfo::makeAbsolute()
}
/*!
- Returns \c true if the file exists; otherwise returns \c false.
+ Returns \c true if the file system entry this QFileInfo refers to exists;
+ otherwise returns \c false.
- \note If the file is a symlink that points to a non-existing
- file, false is returned.
+ \note If the entry is a symlink that points to a non-existing
+ target, this method returns \c false.
*/
bool QFileInfo::exists() const
{
@@ -694,24 +731,23 @@ bool QFileInfo::exists() const
/*!
\since 5.2
- Returns \c true if the \a file exists; otherwise returns \c false.
+ Returns \c true if the file system entry \a path exists; otherwise
+ returns \c false.
- \note If \a file is a symlink that points to a non-existing
- file, false is returned.
+ \note If \a path is a symlink that points to a non-existing
+ target, this method returns \c false.
\note Using this function is faster than using
- \c QFileInfo(file).exists() for file system access.
+ \c QFileInfo(path).exists() for file system access.
*/
-bool QFileInfo::exists(const QString &file)
+bool QFileInfo::exists(const QString &path)
{
- if (file.isEmpty())
+ if (path.isEmpty())
return false;
- QFileSystemEntry entry(file);
+ QFileSystemEntry entry(path);
QFileSystemMetaData data;
- std::unique_ptr<QAbstractFileEngine> engine
- {QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, data)};
// Expensive fallback to non-QFileSystemEngine implementation
- if (engine)
+ if (auto engine = QFileSystemEngine::createLegacyEngine(entry, data))
return QFileInfo(new QFileInfoPrivate(entry, data, std::move(engine))).exists();
QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute);
@@ -719,8 +755,9 @@ bool QFileInfo::exists(const QString &file)
}
/*!
- Refreshes the information about the file, i.e. reads in information
- from the file system the next time a cached property is fetched.
+ Refreshes the information about the file system entry this QFileInfo
+ refers to, that is, reads in information from the file system the next
+ time a cached property is fetched.
*/
void QFileInfo::refresh()
{
@@ -729,8 +766,8 @@ void QFileInfo::refresh()
}
/*!
- Returns the file name, including the path (which may be absolute
- or relative).
+ Returns the path of the file system entry this QFileInfo refers to;
+ the path may be absolute or relative.
\sa absoluteFilePath(), canonicalFilePath(), isRelative()
*/
@@ -738,18 +775,21 @@ QString QFileInfo::filePath() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->fileEntry.filePath();
}
/*!
- Returns the name of the file, excluding the path.
+ Returns the name of the file system entry this QFileInfo refers to,
+ excluding the path.
Example:
\snippet code/src_corelib_io_qfileinfo.cpp 3
- Note that, if this QFileInfo object is given a path ending in a
- slash, the name of the file is considered empty.
+//! [path-ends-with-slash-empty-name-component]
+ \note If this QFileInfo is given a path ending with a directory separator
+ \c{'/'}, the entry's name part is considered empty.
+//! [path-ends-with-slash-empty-name-component]
\sa isRelative(), filePath(), baseName(), suffix()
*/
@@ -757,8 +797,10 @@ QString QFileInfo::fileName() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
- return d->fileEntry.fileName();
+ return ""_L1;
+ if (!d->fileEngine)
+ return d->fileEntry.fileName();
+ return d->fileEngine->fileName(QAbstractFileEngine::BaseName);
}
/*!
@@ -777,7 +819,7 @@ QString QFileInfo::bundleName() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->getFileName(QAbstractFileEngine::BundleName);
}
@@ -801,8 +843,10 @@ QString QFileInfo::baseName() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
- return d->fileEntry.baseName();
+ return ""_L1;
+ if (!d->fileEngine)
+ return d->fileEntry.baseName();
+ return QFileSystemEntry(d->fileEngine->fileName(QAbstractFileEngine::BaseName)).baseName();
}
/*!
@@ -820,8 +864,11 @@ QString QFileInfo::completeBaseName() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
- return d->fileEntry.completeBaseName();
+ return ""_L1;
+ if (!d->fileEngine)
+ return d->fileEntry.completeBaseName();
+ const QString fileEngineBaseName = d->fileEngine->fileName(QAbstractFileEngine::BaseName);
+ return QFileSystemEntry(fileEngineBaseName).completeBaseName();
}
/*!
@@ -839,7 +886,7 @@ QString QFileInfo::completeSuffix() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->fileEntry.completeSuffix();
}
@@ -862,15 +909,16 @@ QString QFileInfo::suffix() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->fileEntry.suffix();
}
/*!
- Returns the path of the object's parent directory as a QDir object.
+ Returns a QDir object representing the path of the parent directory of the
+ file system entry that this QFileInfo refers to.
- \b{Note:} The QDir returned always corresponds to the object's
+ \note The QDir returned always corresponds to the object's
parent directory, even if the QFileInfo represents a directory.
For each of the following, dir() returns the QDir
@@ -888,12 +936,14 @@ QString QFileInfo::suffix() const
QDir QFileInfo::dir() const
{
Q_D(const QFileInfo);
- // ### Qt 6: Maybe rename this to parentDirectory(), considering what it actually does?
return QDir(d->fileEntry.path());
}
/*!
- Returns the file's absolute path as a QDir object.
+ Returns a QDir object representing the absolute path of the parent
+ directory of the file system entry that this QFileInfo refers to.
+
+ \snippet code/src_corelib_io_qfileinfo.cpp 11
\sa dir(), filePath(), fileName(), isRelative()
*/
@@ -903,13 +953,13 @@ QDir QFileInfo::absoluteDir() const
}
/*!
- Returns \c true if the user can read the file; otherwise returns \c false.
+ Returns \c true if the user can read the file system entry this QFileInfo
+ refers to; otherwise returns \c false.
- If the file is a symlink, this function returns true if the target is
- readable (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\note If the \l{NTFS permissions} check has not been enabled, the result
- on Windows will merely reflect whether the file exists.
+ on Windows will merely reflect whether the entry exists.
\sa isWritable(), isExecutable(), permission()
*/
@@ -918,18 +968,18 @@ bool QFileInfo::isReadable() const
Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::UserReadPermission,
- [d]() { return (d->metaData.permissions() & QFile::ReadUser) != 0; },
+ [d]() { return d->metaData.isReadable(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::ReadUserPerm); });
}
/*!
- Returns \c true if the user can write to the file; otherwise returns \c false.
+ Returns \c true if the user can write to the file system entry this
+ QFileInfo refers to; otherwise returns \c false.
- If the file is a symlink, this function returns true if the target is
- writeable (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\note If the \l{NTFS permissions} check has not been enabled, the result on
- Windows will merely reflect whether the file is marked as Read Only.
+ Windows will merely reflect whether the entry is marked as Read Only.
\sa isReadable(), isExecutable(), permission()
*/
@@ -938,15 +988,18 @@ bool QFileInfo::isWritable() const
Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::UserWritePermission,
- [d]() { return (d->metaData.permissions() & QFile::WriteUser) != 0; },
+ [d]() { return d->metaData.isWritable(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::WriteUserPerm); });
}
/*!
- Returns \c true if the file is executable; otherwise returns \c false.
+ Returns \c true if the file system entry this QFileInfo refers to is
+ executable; otherwise returns \c false.
- If the file is a symlink, this function returns true if the target is
- executable (not the symlink).
+//! [info-about-target-not-symlink]
+ If the file is a symlink, this function returns information about the
+ target, not the symlink.
+//! [info-about-target-not-symlink]
\sa isReadable(), isWritable(), permission()
*/
@@ -955,15 +1008,16 @@ bool QFileInfo::isExecutable() const
Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::UserExecutePermission,
- [d]() { return (d->metaData.permissions() & QFile::ExeUser) != 0; },
+ [d]() { return d->metaData.isExecutable(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::ExeUserPerm); });
}
/*!
- Returns \c true if this is a `hidden' file; otherwise returns \c false.
+ Returns \c true if the file system entry this QFileInfo refers to is
+ `hidden'; otherwise returns \c false.
\b{Note:} This function returns \c true for the special entries "." and
- ".." on Unix, even though QDir::entryList threats them as shown. And note
+ ".." on Unix, even though QDir::entryList treats them as shown. And note
that, since this function inspects the file name, on Unix it will inspect
the name of the symlink, if this file is a symlink, not the target's name.
@@ -1005,10 +1059,10 @@ bool QFileInfo::isNativePath() const
/*!
Returns \c true if this object points to a file or to a symbolic
link to a file. Returns \c false if the
- object points to something which isn't a file, such as a directory.
+ object points to something that is not a file (such as a directory)
+ or that does not exist.
- If the file is a symlink, this function returns true if the target is a
- regular file (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa isDir(), isSymLink(), isBundle()
*/
@@ -1023,10 +1077,11 @@ bool QFileInfo::isFile() const
/*!
Returns \c true if this object points to a directory or to a symbolic
- link to a directory; otherwise returns \c false.
+ link to a directory. Returns \c false if the
+ object points to something that is not a directory (such as a file)
+ or that does not exist.
- If the file is a symlink, this function returns true if the target is a
- directory (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa isFile(), isSymLink(), isBundle()
*/
@@ -1045,8 +1100,7 @@ bool QFileInfo::isDir() const
Returns \c true if this object points to a bundle or to a symbolic
link to a bundle on \macos and iOS; otherwise returns \c false.
- If the file is a symlink, this function returns true if the target is a
- bundle (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa isDir(), isSymLink(), isFile()
*/
@@ -1060,8 +1114,8 @@ bool QFileInfo::isBundle() const
}
/*!
- Returns \c true if this object points to a symbolic link or shortcut;
- otherwise returns \c false.
+ Returns \c true if this object points to a symbolic link, shortcut,
+ or alias; otherwise returns \c false.
Symbolic links exist on Unix (including \macos and iOS) and Windows
and are typically created by the \c{ln -s} or \c{mklink} commands,
@@ -1069,15 +1123,18 @@ bool QFileInfo::isBundle() const
the \l{symLinkTarget()}{link's target}.
In addition, true will be returned for shortcuts (\c *.lnk files) on
- Windows. This behavior is deprecated and will likely change in a future
- version of Qt. Opening those will open the \c .lnk file itself.
+ Windows, and aliases on \macos. This behavior is deprecated and will
+ likely change in a future version of Qt. Opening a shortcut or alias
+ will open the \c .lnk or alias file itself.
Example:
\snippet code/src_corelib_io_qfileinfo.cpp 9
- \note If the symlink points to a non existing file, exists() returns
- false.
+//! [symlink-target-exists-behavior]
+ \note exists() returns \c true if the symlink points to an existing
+ target, otherwise it returns \c false.
+//! [symlink-target-exists-behavior]
\sa isFile(), isDir(), symLinkTarget()
*/
@@ -1102,10 +1159,10 @@ bool QFileInfo::isSymLink() const
opens the \l{symLinkTarget()}{link's target}.
In contrast to isSymLink(), false will be returned for shortcuts
- (\c *.lnk files) on Windows. Use QFileInfo::isShortcut() instead.
+ (\c *.lnk files) on Windows and aliases on \macos. Use QFileInfo::isShortcut()
+ and QFileInfo::isAlias() instead.
- \note If the symlink points to a non existing file, exists() returns
- false.
+ \include qfileinfo.cpp symlink-target-exists-behavior
\sa isFile(), isDir(), isShortcut(), symLinkTarget()
*/
@@ -1145,6 +1202,29 @@ bool QFileInfo::isShortcut() const
[d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); });
}
+/*!
+ Returns \c true if this object points to an alias;
+ otherwise returns \c false.
+
+ \since 6.4
+
+ Aliases only exist on \macos. They are treated as regular files, so
+ opening an alias will open the file itself. In order to open the file
+ or directory an alias references use symLinkTarget().
+
+ \note Even if an alias points to a non existing file,
+ isAlias() returns true.
+
+ \sa isFile(), isDir(), isSymLink(), symLinkTarget()
+*/
+bool QFileInfo::isAlias() const
+{
+ Q_D(const QFileInfo);
+ return d->checkAttribute<bool>(
+ QFileSystemMetaData::LegacyLinkType,
+ [d]() { return d->metaData.isAlias(); },
+ [d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); });
+}
/*!
\since 5.15
@@ -1194,7 +1274,6 @@ bool QFileInfo::isRoot() const
}
/*!
- \fn QString QFileInfo::symLinkTarget() const
\since 4.2
Returns the absolute path to the file or directory a symbolic link
@@ -1202,30 +1281,58 @@ bool QFileInfo::isRoot() const
link.
This name may not represent an existing file; it is only a string.
- QFileInfo::exists() returns \c true if the symlink points to an
- existing file.
+
+ \include qfileinfo.cpp symlink-target-exists-behavior
\sa exists(), isSymLink(), isDir(), isFile()
*/
+QString QFileInfo::symLinkTarget() const
+{
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return ""_L1;
+ return d->getFileName(QAbstractFileEngine::AbsoluteLinkTarget);
+}
-#if QT_DEPRECATED_SINCE(5, 13)
/*!
- \obsolete
+ \since 6.6
+ Read the path the symlink references.
+
+ Returns the raw path referenced by the symbolic link, without resolving a relative
+ path relative to the directory containing the symbolic link. The returned string will
+ only be an absolute path if the symbolic link actually references it as such. Returns
+ an empty string if the object is not a symbolic link.
- Use symLinkTarget() instead.
+ \sa symLinkTarget(), exists(), isSymLink(), isDir(), isFile()
*/
-QString QFileInfo::readLink() const
+QString QFileInfo::readSymLink() const
{
- return symLinkTarget();
+ Q_D(const QFileInfo);
+ if (d->isDefaultConstructed)
+ return {};
+ return d->getFileName(QAbstractFileEngine::RawLinkPath);
}
-#endif
-QString QFileInfo::symLinkTarget() const
+/*!
+ \since 6.2
+
+ Resolves an NTFS junction to the path it references.
+
+ Returns the absolute path to the directory an NTFS junction points to, or
+ an empty string if the object is not an NTFS junction.
+
+ There is no guarantee that the directory named by the NTFS junction actually
+ exists.
+
+ \sa isJunction(), isFile(), isDir(), isSymLink(), isSymbolicLink(),
+ isShortcut()
+*/
+QString QFileInfo::junctionTarget() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
- return d->getFileName(QAbstractFileEngine::LinkName);
+ return ""_L1;
+ return d->getFileName(QAbstractFileEngine::JunctionName);
}
/*!
@@ -1237,8 +1344,7 @@ QString QFileInfo::symLinkTarget() const
milliseconds). On Windows, it will return an empty string unless
the \l{NTFS permissions} check has been enabled.
- If the file is a symlink, this function returns the owner of the target
- (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa ownerId(), group(), groupId()
*/
@@ -1246,7 +1352,7 @@ QString QFileInfo::owner() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->getFileOwner(QAbstractFileEngine::OwnerUser);
}
@@ -1256,8 +1362,7 @@ QString QFileInfo::owner() const
On Windows and on systems where files do not have owners this
function returns ((uint) -2).
- If the file is a symlink, this function returns the id of the owner of the target
- (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa owner(), group(), groupId()
*/
@@ -1278,8 +1383,7 @@ uint QFileInfo::ownerId() const
This function can be time consuming under Unix (in the order of
milliseconds).
- If the file is a symlink, this function returns the owning group of the
- target (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa groupId(), owner(), ownerId()
*/
@@ -1287,7 +1391,7 @@ QString QFileInfo::group() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
- return QLatin1String("");
+ return ""_L1;
return d->getFileOwner(QAbstractFileEngine::OwnerGroup);
}
@@ -1297,8 +1401,7 @@ QString QFileInfo::group() const
On Windows and on systems where files do not have groups this
function always returns (uint) -2.
- If the file is a symlink, this function returns the id of the group owning the
- target (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa group(), owner(), ownerId()
*/
@@ -1325,8 +1428,7 @@ uint QFileInfo::groupId() const
Example:
\snippet code/src_corelib_io_qfileinfo.cpp 10
- If the file is a symlink, this function checks the permissions of the
- target (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa isReadable(), isWritable(), isExecutable()
*/
@@ -1334,13 +1436,13 @@ bool QFileInfo::permission(QFile::Permissions permissions) const
{
Q_D(const QFileInfo);
// the QFileSystemMetaData::MetaDataFlag and QFile::Permissions overlap, so just cast.
- auto fseFlags = QFileSystemMetaData::MetaDataFlag(int(permissions));
- auto feFlags = QAbstractFileEngine::FileFlags(int(permissions));
+ auto fseFlags = QFileSystemMetaData::MetaDataFlags::fromInt(permissions.toInt());
+ auto feFlags = QAbstractFileEngine::FileFlags::fromInt(permissions.toInt());
return d->checkAttribute<bool>(
fseFlags,
[=]() { return (d->metaData.permissions() & permissions) == permissions; },
[=]() {
- return d->getFileFlags(feFlags) == uint(permissions);
+ return d->getFileFlags(feFlags) == uint(permissions.toInt());
});
}
@@ -1351,8 +1453,7 @@ bool QFileInfo::permission(QFile::Permissions permissions) const
\note The result might be inaccurate on Windows if the
\l{NTFS permissions} check has not been enabled.
- If the file is a symlink, this function returns the permissions of the
- target (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
*/
QFile::Permissions QFileInfo::permissions() const
{
@@ -1370,8 +1471,7 @@ QFile::Permissions QFileInfo::permissions() const
Returns the file size in bytes. If the file does not exist or cannot be
fetched, 0 is returned.
- If the file is a symlink, the size of the target file is returned
- (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
\sa exists()
*/
@@ -1390,115 +1490,182 @@ qint64 QFileInfo::size() const
});
}
-#if QT_DEPRECATED_SINCE(5, 10)
/*!
- \deprecated
+ \fn QDateTime QFileInfo::birthTime() const
+
+ Returns the date and time when the file was created (born), in local time.
- Returns the date and time when the file was created, the time its metadata
- was last changed or the time of last modification, whichever one of the
- three is available (in that order).
+ If the file birth time is not available, this function returns an invalid QDateTime.
- This function is deprecated. Instead, use the birthTime() function to get
- the time the file was created, metadataChangeTime() to get the time its
- metadata was last changed, or lastModified() to get the time it was last modified.
+ \include qfileinfo.cpp info-about-target-not-symlink
- If the file is a symlink, the time of the target file is returned
- (not the symlink).
+ This function overloads QFileInfo::birthTime(const QTimeZone &tz), and
+ returns the same as \c{birthTime(QTimeZone::LocalTime)}.
- \sa birthTime(), metadataChangeTime(), lastModified(), lastRead()
+ \since 5.10
+ \sa lastModified(), lastRead(), metadataChangeTime(), fileTime()
*/
-QDateTime QFileInfo::created() const
-{
- QDateTime d = fileTime(QFile::FileBirthTime);
- if (d.isValid())
- return d;
- return fileTime(QFile::FileMetadataChangeTime);
-}
-#endif
/*!
- \since 5.10
- Returns the date and time when the file was created / born.
+ \fn QDateTime QFileInfo::birthTime(const QTimeZone &tz) const
+
+ Returns the date and time when the file was created (born).
+
+ \include qfileinfo.cpp file-times-in-time-zone
If the file birth time is not available, this function returns an invalid
QDateTime.
- If the file is a symlink, the time of the target file is returned
- (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
- \sa lastModified(), lastRead(), metadataChangeTime()
+ \since 6.6
+ \sa lastModified(const QTimeZone &), lastRead(const QTimeZone &),
+ metadataChangeTime(const QTimeZone &),
+ fileTime(QFileDevice::FileTime, const QTimeZone &)
*/
-QDateTime QFileInfo::birthTime() const
-{
- return fileTime(QFile::FileBirthTime);
-}
/*!
+ \fn QDateTime QFileInfo::metadataChangeTime() const
+
+ Returns the date and time when the file's metadata was last changed,
+ in local time.
+
+ A metadata change occurs when the file is first created, but it also
+ occurs whenever the user writes or sets inode information (for example,
+ changing the file permissions).
+
+ \include qfileinfo.cpp info-about-target-not-symlink
+
+ This function overloads QFileInfo::metadataChangeTime(const QTimeZone &tz),
+ and returns the same as \c{metadataChangeTime(QTimeZone::LocalTime)}.
+
\since 5.10
- Returns the date and time when the file metadata was changed. A metadata
- change occurs when the file is created, but it also occurs whenever the
- user writes or sets inode information (for example, changing the file
- permissions).
+ \sa birthTime(), lastModified(), lastRead(), fileTime()
+*/
+
+/*!
+ \fn QDateTime QFileInfo::metadataChangeTime(const QTimeZone &tz) const
+
+ Returns the date and time when the file's metadata was last changed.
+ A metadata change occurs when the file is first created, but it also
+ occurs whenever the user writes or sets inode information (for example,
+ changing the file permissions).
+
+ \include qfileinfo.cpp file-times-in-time-zone
- If the file is a symlink, the time of the target file is returned
- (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
- \sa lastModified(), lastRead()
+ \since 6.6
+ \sa birthTime(const QTimeZone &), lastModified(const QTimeZone &),
+ lastRead(const QTimeZone &),
+ fileTime(QFileDevice::FileTime time, const QTimeZone &)
*/
-QDateTime QFileInfo::metadataChangeTime() const
-{
- return fileTime(QFile::FileMetadataChangeTime);
-}
/*!
- Returns the date and local time when the file was last modified.
+ \fn QDateTime QFileInfo::lastModified() const
+
+ Returns the date and time when the file was last modified.
- If the file is a symlink, the time of the target file is returned
- (not the symlink).
+ \include qfileinfo.cpp info-about-target-not-symlink
+
+ This function overloads \l{QFileInfo::lastModified(const QTimeZone &)},
+ and returns the same as \c{lastModified(QTimeZone::LocalTime)}.
\sa birthTime(), lastRead(), metadataChangeTime(), fileTime()
*/
-QDateTime QFileInfo::lastModified() const
-{
- return fileTime(QFile::FileModificationTime);
-}
/*!
- Returns the date and local time when the file was last read (accessed).
+ \fn QDateTime QFileInfo::lastModified(const QTimeZone &tz) const
+
+ Returns the date and time when the file was last modified.
+
+ \include qfileinfo.cpp file-times-in-time-zone
- On platforms where this information is not available, returns the
- same as lastModified().
+ \include qfileinfo.cpp info-about-target-not-symlink
- If the file is a symlink, the time of the target file is returned
- (not the symlink).
+ \since 6.6
+ \sa birthTime(const QTimeZone &), lastRead(const QTimeZone &),
+ metadataChangeTime(const QTimeZone &),
+ fileTime(QFileDevice::FileTime, const QTimeZone &)
+*/
+
+/*!
+ \fn QDateTime QFileInfo::lastRead() const
+
+ Returns the date and time when the file was last read (accessed).
+
+ On platforms where this information is not available, returns the same
+ time as lastModified().
+
+ \include qfileinfo.cpp info-about-target-not-symlink
+
+ This function overloads \l{QFileInfo::lastRead(const QTimeZone &)},
+ and returns the same as \c{lastRead(QTimeZone::LocalTime)}.
\sa birthTime(), lastModified(), metadataChangeTime(), fileTime()
*/
-QDateTime QFileInfo::lastRead() const
-{
- return fileTime(QFile::FileAccessTime);
-}
/*!
+ \fn QDateTime QFileInfo::lastRead(const QTimeZone &tz) const
+
+ Returns the date and time when the file was last read (accessed).
+
+ \include qfileinfo.cpp file-times-in-time-zone
+
+ On platforms where this information is not available, returns the same
+ time as lastModified().
+
+ \include qfileinfo.cpp info-about-target-not-symlink
+
+ \since 6.6
+ \sa birthTime(const QTimeZone &), lastModified(const QTimeZone &),
+ metadataChangeTime(const QTimeZone &),
+ fileTime(QFileDevice::FileTime, const QTimeZone &)
+*/
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+/*!
+ Returns the file time specified by \a time.
+
+ If the time cannot be determined, an invalid date time is returned.
+
+ \include qfileinfo.cpp info-about-target-not-symlink
+
+ This function overloads
+ \l{QFileInfo::fileTime(QFileDevice::FileTime, const QTimeZone &)},
+ and returns the same as \c{fileTime(time, QTimeZone::LocalTime)}.
+
\since 5.10
+ \sa birthTime(), lastModified(), lastRead(), metadataChangeTime()
+*/
+QDateTime QFileInfo::fileTime(QFile::FileTime time) const {
+ return fileTime(time, QTimeZone::LocalTime);
+}
+#endif
- Returns the file time specified by \a time. If the time cannot be
- determined, an invalid date time is returned.
+/*!
+ Returns the file time specified by \a time.
- If the file is a symlink, the time of the target file is returned
- (not the symlink).
+//! [file-times-in-time-zone]
+ The returned time is in the time zone specified by \a tz. For example,
+ you can use QTimeZone::LocalTime or QTimeZone::UTC to get the time in
+ the Local time zone or UTC, respectively. Since native file system API
+ typically uses UTC, using QTimeZone::UTC is often faster, as it does not
+ require any conversions.
+//! [file-times-in-time-zone]
- \sa QFile::FileTime, QDateTime::isValid()
+ If the time cannot be determined, an invalid date time is returned.
+
+ \include qfileinfo.cpp info-about-target-not-symlink
+
+ \since 6.6
+ \sa birthTime(const QTimeZone &), lastModified(const QTimeZone &),
+ lastRead(const QTimeZone &), metadataChangeTime(const QTimeZone &),
+ QDateTime::isValid()
*/
-QDateTime QFileInfo::fileTime(QFile::FileTime time) const
+QDateTime QFileInfo::fileTime(QFile::FileTime time, const QTimeZone &tz) const
{
- static_assert(int(QFile::FileAccessTime) == int(QAbstractFileEngine::AccessTime));
- static_assert(int(QFile::FileBirthTime) == int(QAbstractFileEngine::BirthTime));
- static_assert(int(QFile::FileMetadataChangeTime) == int(QAbstractFileEngine::MetadataChangeTime));
- static_assert(int(QFile::FileModificationTime) == int(QAbstractFileEngine::ModificationTime));
-
Q_D(const QFileInfo);
- auto fetime = QAbstractFileEngine::FileTime(time);
QFileSystemMetaData::MetaDataFlags flag;
switch (time) {
case QFile::FileAccessTime:
@@ -1515,10 +1682,11 @@ QDateTime QFileInfo::fileTime(QFile::FileTime time) const
break;
}
- return d->checkAttribute<QDateTime>(
- flag,
- [=]() { return d->metaData.fileTime(fetime).toLocalTime(); },
- [=]() { return d->getFileTime(fetime).toLocalTime(); });
+ auto fsLambda = [d, time]() { return d->metaData.fileTime(time); };
+ auto engineLambda = [d, time]() { return d->getFileTime(time); };
+ const auto dt =
+ d->checkAttribute<QDateTime>(flag, std::move(fsLambda), std::move(engineLambda));
+ return dt.toTimeZone(tz);
}
/*!
@@ -1559,6 +1727,22 @@ void QFileInfo::setCaching(bool enable)
}
/*!
+ Reads all attributes from the file system.
+ \since 6.0
+
+ This is useful when information about the file system is collected in a
+ worker thread, and then passed to the UI in the form of caching QFileInfo
+ instances.
+
+ \sa setCaching(), refresh()
+*/
+void QFileInfo::stat()
+{
+ Q_D(QFileInfo);
+ QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::AllMetaDataFlags);
+}
+
+/*!
\typedef QFileInfoList
\relates QFileInfo
@@ -1586,24 +1770,22 @@ QDebug operator<<(QDebug dbg, const QFileInfo &fi)
\sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath()
*/
/*!
- \fn QFileInfo::QFileInfo(const QDir &dir, const std::filesystem::path &file)
+ \fn QFileInfo::QFileInfo(const QDir &dir, const std::filesystem::path &path)
\since 6.0
- Constructs a new QFileInfo that gives information about the given
- \a file relative to the directory \a dir.
-
- If \a dir has a relative path, the QFileInfo will also have a
- relative path.
+ Constructs a new QFileInfo that gives information about the file system
+ entry at \a path that is relative to the directory \a dir.
- If \a file is an absolute path, then the directory specified
- by \a dir will be disregarded.
+ \include qfileinfo.cpp preserve-relative-or-absolute
*/
/*!
- \fn void QFileInfo::setFile(const std::filesystem::path &file)
+ \fn void QFileInfo::setFile(const std::filesystem::path &path)
\since 6.0
- Sets the file that the QFileInfo provides information about to \a
- file.
+ Sets the path of file system entry that this QFileInfo provides
+ information about to \a path.
+
+ \include qfileinfo.cpp preserve-relative-path
*/
/*!
\fn std::filesystem::path QFileInfo::filesystemFilePath() const
@@ -1654,5 +1836,74 @@ QDebug operator<<(QDebug dbg, const QFileInfo &fi)
Returns symLinkTarget() as a \c{std::filesystem::path}.
\sa symLinkTarget()
*/
+/*!
+ \fn std::filesystem::path QFileInfo::filesystemReadSymLink() const
+ \since 6.6
+
+ Returns readSymLink() as a \c{std::filesystem::path}.
+ \sa readSymLink()
+*/
+/*!
+ \fn std::filesystem::path QFileInfo::filesystemJunctionTarget() const
+ \since 6.2
+
+ Returns junctionTarget() as a \c{std::filesystem::path}.
+ \sa junctionTarget()
+*/
+/*!
+ \macro QT_IMPLICIT_QFILEINFO_CONSTRUCTION
+ \since 6.0
+ \relates QFileInfo
+
+ Defining this macro makes most QFileInfo constructors implicit
+ instead of explicit. Since construction of QFileInfo objects is
+ expensive, one should avoid accidentally creating them, especially
+ if cheaper alternatives exist. For instance:
+
+ \badcode
+
+ QDirIterator it(dir);
+ while (it.hasNext()) {
+ // Implicit conversion from QString (returned by it.next()):
+ // may create unnecessary data structures and cause additional
+ // accesses to the file system. Unless this macro is defined,
+ // this line does not compile.
+
+ QFileInfo fi = it.next();
+
+ ~~~
+ }
+
+ \endcode
+
+ Instead, use the right API:
+
+ \code
+
+ QDirIterator it(dir);
+ while (it.hasNext()) {
+ // Extract the QFileInfo from the iterator directly:
+ QFileInfo fi = it.nextFileInfo();
+
+ ~~~
+ }
+
+ \endcode
+
+ Construction from QString, QFile, and so on is always possible by
+ using direct initialization instead of copy initialization:
+
+ \code
+
+ QFileInfo fi1 = some_string; // Does not compile unless this macro is defined
+ QFileInfo fi2(some_string); // OK
+ QFileInfo fi3{some_string}; // Possibly better, avoids the risk of the Most Vexing Parse
+ auto fi4 = QFileInfo(some_string); // OK
+
+ \endcode
+
+ This macro is provided for compatibility reason. Its usage is not
+ recommended in new code.
+*/
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index 2bed64eb1a..72c8519446 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -1,96 +1,74 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILEINFO_H
#define QFILEINFO_H
+#include <QtCore/qcompare.h>
#include <QtCore/qfile.h>
#include <QtCore/qlist.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qmetatype.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimezone.h>
QT_BEGIN_NAMESPACE
class QDir;
class QDirIteratorPrivate;
-class QDateTime;
class QFileInfoPrivate;
class Q_CORE_EXPORT QFileInfo
{
friend class QDirIteratorPrivate;
+ friend class QDirListingPrivate;
public:
explicit QFileInfo(QFileInfoPrivate *d);
+#ifdef QT_IMPLICIT_QFILEINFO_CONSTRUCTION
+#define QFILEINFO_MAYBE_EXPLICIT Q_IMPLICIT
+#else
+#define QFILEINFO_MAYBE_EXPLICIT explicit
+#endif
+
QFileInfo();
- QFileInfo(const QString &file);
- QFileInfo(const QFile &file);
- QFileInfo(const QDir &dir, const QString &file);
+ QFILEINFO_MAYBE_EXPLICIT QFileInfo(const QString &file);
+ QFILEINFO_MAYBE_EXPLICIT QFileInfo(const QFileDevice &file);
+ QFILEINFO_MAYBE_EXPLICIT QFileInfo(const QDir &dir, const QString &file);
QFileInfo(const QFileInfo &fileinfo);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QFileInfo(const std::filesystem::path &file);
QFileInfo(const QDir &dir, const std::filesystem::path &file);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
- QFileInfo(const T &file) : QFileInfo(QtPrivate::fromFilesystemPath(file)) { }
+ QFILEINFO_MAYBE_EXPLICIT QFileInfo(const T &file) : QFileInfo(QtPrivate::fromFilesystemPath(file)) { }
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
- QFileInfo(const QDir &dir, const T &file) : QFileInfo(dir, QtPrivate::fromFilesystemPath(file))
+ QFILEINFO_MAYBE_EXPLICIT QFileInfo(const QDir &dir, const T &file) : QFileInfo(dir, QtPrivate::fromFilesystemPath(file))
{
}
#endif // QT_CONFIG(cxx17_filesystem)
+
+#undef QFILEINFO_MAYBE_EXPLICIT
+
~QFileInfo();
QFileInfo &operator=(const QFileInfo &fileinfo);
- QFileInfo &operator=(QFileInfo &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFileInfo)
void swap(QFileInfo &other) noexcept
- { qSwap(d_ptr, other.d_ptr); }
+ { d_ptr.swap(other.d_ptr); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QFileInfo &fileinfo) const;
inline bool operator!=(const QFileInfo &fileinfo) const { return !(operator==(fileinfo)); }
+#endif
void setFile(const QString &file);
- void setFile(const QFile &file);
+ void setFile(const QFileDevice &file);
void setFile(const QDir &dir, const QString &file);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
void setFile(const std::filesystem::path &file);
#elif QT_CONFIG(cxx17_filesystem)
template<typename T, QtPrivate::ForceFilesystemPath<T> = 0>
@@ -104,7 +82,7 @@ public:
QString filePath() const;
QString absoluteFilePath() const;
QString canonicalFilePath() const;
-#if QT_CONFIG(cxx17_filesystem)
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
std::filesystem::path filesystemFilePath() const
{ return QtPrivate::toFilesystemPath(filePath()); }
std::filesystem::path filesystemAbsoluteFilePath() const
@@ -122,7 +100,7 @@ public:
QString path() const;
QString absolutePath() const;
QString canonicalPath() const;
-#if QT_CONFIG(cxx17_filesystem)
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
std::filesystem::path filesystemPath() const { return QtPrivate::toFilesystemPath(path()); }
std::filesystem::path filesystemAbsolutePath() const
{ return QtPrivate::toFilesystemPath(absolutePath()); }
@@ -147,18 +125,24 @@ public:
bool isSymLink() const;
bool isSymbolicLink() const;
bool isShortcut() const;
+ bool isAlias() const;
bool isJunction() const;
bool isRoot() const;
bool isBundle() const;
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QFileInfo::symLinkTarget() instead")
- QString readLink() const;
-#endif
QString symLinkTarget() const;
-#if QT_CONFIG(cxx17_filesystem)
+ QString readSymLink() const;
+ QString junctionTarget() const;
+
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
std::filesystem::path filesystemSymLinkTarget() const
{ return QtPrivate::toFilesystemPath(symLinkTarget()); }
+
+ std::filesystem::path filesystemReadSymLink() const
+ { return QtPrivate::toFilesystemPath(readSymLink()); }
+
+ std::filesystem::path filesystemJunctionTarget() const
+ { return QtPrivate::toFilesystemPath(junctionTarget()); }
#endif // QT_CONFIG(cxx17_filesystem)
QString owner() const;
@@ -171,24 +155,28 @@ public:
qint64 size() const;
- // ### Qt6: inline these functions
-#if QT_DEPRECATED_SINCE(5, 10)
- QT_DEPRECATED_X("Use either birthTime() or metadataChangeTime()")
- QDateTime created() const;
-#endif
- QDateTime birthTime() const;
- QDateTime metadataChangeTime() const;
- QDateTime lastModified() const;
- QDateTime lastRead() const;
+ QDateTime birthTime() const { return fileTime(QFile::FileBirthTime); }
+ QDateTime metadataChangeTime() const { return fileTime(QFile::FileMetadataChangeTime); }
+ QDateTime lastModified() const { return fileTime(QFile::FileModificationTime); }
+ QDateTime lastRead() const { return fileTime(QFile::FileAccessTime); }
QDateTime fileTime(QFile::FileTime time) const;
+ QDateTime birthTime(const QTimeZone &tz) const { return fileTime(QFile::FileBirthTime, tz); }
+ QDateTime metadataChangeTime(const QTimeZone &tz) const { return fileTime(QFile::FileMetadataChangeTime, tz); }
+ QDateTime lastModified(const QTimeZone &tz) const { return fileTime(QFile::FileModificationTime, tz); }
+ QDateTime lastRead(const QTimeZone &tz) const { return fileTime(QFile::FileAccessTime, tz); }
+ QDateTime fileTime(QFile::FileTime time, const QTimeZone &tz) const;
+
bool caching() const;
void setCaching(bool on);
+ void stat();
protected:
QSharedDataPointer<QFileInfoPrivate> d_ptr;
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QFileInfo)
QFileInfoPrivate* d_func();
inline const QFileInfoPrivate* d_func() const
{
@@ -206,6 +194,6 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QFileInfo &);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QFileInfo)
+QT_DECL_METATYPE_EXTERN(QFileInfo, Q_CORE_EXPORT)
#endif // QFILEINFO_H
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index 333ea70adc..4091a7464a 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILEINFO_P_H
#define QFILEINFO_P_H
@@ -91,7 +55,7 @@ public:
: QSharedData(copy),
fileEntry(copy.fileEntry),
metaData(copy.metaData),
- fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
+ fileEngine(QFileSystemEngine::createLegacyEngine(fileEntry, metaData)),
cachedFlags(0),
#ifndef QT_NO_FSFILEENGINE
isDefaultConstructed(false),
@@ -101,8 +65,8 @@ public:
cache_enabled(copy.cache_enabled), fileFlags(0), fileSize(0)
{}
inline QFileInfoPrivate(const QString &file)
- : fileEntry(QDir::fromNativeSeparators(file)),
- fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
+ : fileEntry(file),
+ fileEngine(QFileSystemEngine::createLegacyEngine(fileEntry, metaData)),
cachedFlags(0),
#ifndef QT_NO_FSFILEENGINE
isDefaultConstructed(file.isEmpty()),
@@ -117,7 +81,7 @@ public:
: QSharedData(),
fileEntry(file),
metaData(data),
- fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
+ fileEngine(QFileSystemEngine::createLegacyEngine(fileEntry, metaData)),
cachedFlags(0),
isDefaultConstructed(false),
cache_enabled(true), fileFlags(0), fileSize(0)
@@ -158,7 +122,7 @@ public:
}
uint getFileFlags(QAbstractFileEngine::FileFlags) const;
- QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
+ QDateTime &getFileTime(QFile::FileTime) const;
QString getFileName(QAbstractFileEngine::FileName) const;
QString getFileOwner(QAbstractFileEngine::FileOwner own) const;
@@ -169,7 +133,7 @@ public:
mutable QString fileNames[QAbstractFileEngine::NFileNames];
mutable QString fileOwners[2]; // QAbstractFileEngine::FileOwner: OwnerUser and OwnerGroup
- mutable QDateTime fileTimes[4]; // QAbstractFileEngine::FileTime: BirthTime, MetadataChangeTime, ModificationTime, AccessTime
+ mutable QDateTime fileTimes[4]; // QFile::FileTime: FileBirthTime, FileMetadataChangeTime, FileModificationTime, FileAccessTime
mutable uint cachedFlags : 30;
bool const isDefaultConstructed : 1; // QFileInfo is a default constructed instance
@@ -182,8 +146,8 @@ public:
{ if (cache_enabled) cachedFlags |= c; }
template <typename Ret, typename FSLambda, typename EngineLambda>
- Ret checkAttribute(Ret defaultValue, QFileSystemMetaData::MetaDataFlags fsFlags, const FSLambda &fsLambda,
- const EngineLambda &engineLambda) const
+ Ret checkAttribute(Ret defaultValue, QFileSystemMetaData::MetaDataFlags fsFlags,
+ FSLambda fsLambda, EngineLambda engineLambda) const
{
if (isDefaultConstructed)
return defaultValue;
@@ -197,10 +161,10 @@ public:
}
template <typename Ret, typename FSLambda, typename EngineLambda>
- Ret checkAttribute(QFileSystemMetaData::MetaDataFlags fsFlags, const FSLambda &fsLambda,
- const EngineLambda &engineLambda) const
+ Ret checkAttribute(QFileSystemMetaData::MetaDataFlags fsFlags, FSLambda fsLambda,
+ EngineLambda engineLambda) const
{
- return checkAttribute(Ret(), fsFlags, fsLambda, engineLambda);
+ return checkAttribute(Ret(), std::move(fsFlags), std::move(fsLambda), engineLambda);
}
};
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 1a58da1e18..7f5480c274 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -1,42 +1,6 @@
-/***************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfileselector.h"
#include "qfileselector_p.h"
@@ -52,11 +16,13 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
//Environment variable to allow tooling full control of file selectors
static const char env_override[] = "QT_NO_BUILTIN_SELECTORS";
Q_GLOBAL_STATIC(QFileSelectorSharedData, sharedData);
-static QBasicMutex sharedDataMutex;
+Q_CONSTINIT static QBasicMutex sharedDataMutex;
QFileSelectorPrivate::QFileSelectorPrivate()
: QObjectPrivate()
@@ -196,9 +162,9 @@ QString QFileSelector::select(const QString &filePath) const
static bool isLocalScheme(const QString &file)
{
- bool local = file == QLatin1String("qrc");
+ bool local = file == "qrc"_L1;
#ifdef Q_OS_ANDROID
- local |= file == QLatin1String("assets");
+ local |= file == "assets"_L1;
#endif
return local;
}
@@ -217,11 +183,11 @@ QUrl QFileSelector::select(const QUrl &filePath) const
return filePath;
QUrl ret(filePath);
if (isLocalScheme(filePath.scheme())) {
- QLatin1String scheme(":");
+ auto scheme = ":"_L1;
#ifdef Q_OS_ANDROID
// use other scheme because ":" means "qrc" here
- if (filePath.scheme() == QLatin1String("assets"))
- scheme = QLatin1String("assets:");
+ if (filePath.scheme() == "assets"_L1)
+ scheme = "assets:"_L1;
#endif
QString equivalentPath = scheme + filePath.path();
@@ -244,19 +210,20 @@ QUrl QFileSelector::select(const QUrl &filePath) const
return ret;
}
-QString QFileSelectorPrivate::selectionHelper(const QString &path, const QString &fileName, const QStringList &selectors, const QChar &indicator)
+QString QFileSelectorPrivate::selectionHelper(const QString &path, const QString &fileName,
+ const QStringList &selectors, QChar indicator)
{
/* selectionHelper does a depth-first search of possible selected files. Because there is strict
selector ordering in the API, we can stop checking as soon as we find the file in a directory
which does not contain any other valid selector directories.
*/
- Q_ASSERT(path.isEmpty() || path.endsWith(QLatin1Char('/')));
+ Q_ASSERT(path.isEmpty() || path.endsWith(u'/'));
for (const QString &s : selectors) {
QString prospectiveBase = path;
if (!indicator.isNull())
prospectiveBase += indicator;
- prospectiveBase += s + QLatin1Char('/');
+ prospectiveBase += s + u'/';
QStringList remainingSelectors = selectors;
remainingSelectors.removeAll(s);
if (!QDir(prospectiveBase).exists())
@@ -278,7 +245,10 @@ QString QFileSelectorPrivate::select(const QString &filePath) const
Q_Q(const QFileSelector);
QFileInfo fi(filePath);
- QString ret = selectionHelper(fi.path().isEmpty() ? QString() : fi.path() + QLatin1Char('/'),
+ QString pathString;
+ if (auto path = fi.path(); !path.isEmpty())
+ pathString = path.endsWith(u'/') ? path : path + u'/';
+ QString ret = selectionHelper(pathString,
fi.fileName(), q->allSelectors());
if (!ret.isEmpty())
@@ -325,7 +295,7 @@ void QFileSelectorPrivate::updateSelectors()
QLatin1Char pathSep(',');
QStringList envSelectors = QString::fromLatin1(qgetenv("QT_FILE_SELECTORS"))
.split(pathSep, Qt::SkipEmptyParts);
- if (envSelectors.count())
+ if (envSelectors.size())
sharedData->staticSelectors << envSelectors;
if (!qEnvironmentVariableIsEmpty(env_override))
@@ -353,7 +323,7 @@ QStringList QFileSelectorPrivate::platformSelectors()
ret << QSysInfo::kernelType();
# endif
QString productName = QSysInfo::productType();
- if (productName != QLatin1String("unknown"))
+ if (productName != "unknown"_L1)
ret << productName; // "opensuse", "fedora", "osx", "ios", "android"
#endif
return ret;
diff --git a/src/corelib/io/qfileselector.h b/src/corelib/io/qfileselector.h
index c9c2f564f6..bb840fe083 100644
--- a/src/corelib/io/qfileselector.h
+++ b/src/corelib/io/qfileselector.h
@@ -1,41 +1,5 @@
-/***************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESELECTOR_H
#define QFILESELECTOR_H
diff --git a/src/corelib/io/qfileselector_p.h b/src/corelib/io/qfileselector_p.h
index 024d0b190d..bc0593bca6 100644
--- a/src/corelib/io/qfileselector_p.h
+++ b/src/corelib/io/qfileselector_p.h
@@ -1,41 +1,5 @@
-/***************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESELECTOR_P_H
#define QFILESELECTOR_P_H
@@ -71,7 +35,7 @@ public:
static QStringList platformSelectors();
static void addStatics(const QStringList &); //For loading GUI statics from other Qt modules
static QString selectionHelper(const QString &path, const QString &fileName,
- const QStringList &selectors, const QChar &indicator = QLatin1Char('+'));
+ const QStringList &selectors, QChar indicator = u'+');
QFileSelectorPrivate();
QString select(const QString &filePath) const;
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index 1a9a01ac92..d8b215816c 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemengine_p.h"
#include <QtCore/qdir.h>
@@ -61,9 +25,9 @@ QString QFileSystemEngine::slowCanonicalized(const QString &path)
return path;
QFileInfo fi;
- const QChar slash(QLatin1Char('/'));
+ const QChar slash(u'/');
QString tmpPath = path;
- int separatorPos = 0;
+ qsizetype separatorPos = 0;
QSet<QString> nonSymlinks;
QDuplicateTracker<QString> known;
@@ -74,7 +38,7 @@ QString QFileSystemEngine::slowCanonicalized(const QString &path)
if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) {
// UNC, skip past the first two elements
separatorPos = tmpPath.indexOf(slash, 2);
- } else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) {
+ } else if (tmpPath.size() >= 3 && tmpPath.at(1) == u':' && tmpPath.at(2) == slash) {
// volume root, skip since it can not be a symlink
separatorPos = 2;
}
@@ -119,12 +83,11 @@ static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &d
return true;
}
-static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEntry)
+static inline bool _q_checkEntry(std::unique_ptr<QAbstractFileEngine> &engine, bool resolvingEntry)
{
if (resolvingEntry) {
if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
- delete engine;
- engine = nullptr;
+ engine.reset();
return false;
}
}
@@ -132,22 +95,23 @@ static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEnt
return true;
}
-static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
- QAbstractFileEngine *&engine, bool resolvingEntry = false)
+static bool _q_createLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
+ std::unique_ptr<QAbstractFileEngine> &engine,
+ bool resolvingEntry = false)
{
QString const &filePath = entry.filePath();
if ((engine = qt_custom_file_engine_handler_create(filePath)))
return _q_checkEntry(engine, resolvingEntry);
#if defined(QT_BUILD_CORE_LIB)
- for (int prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) {
+ for (qsizetype prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) {
QChar const ch = filePath[prefixSeparator];
- if (ch == QLatin1Char('/'))
+ if (ch == u'/')
break;
- if (ch == QLatin1Char(':')) {
+ if (ch == u':') {
if (prefixSeparator == 0) {
- engine = new QResourceFileEngine(filePath);
+ engine = std::make_unique<QResourceFileEngine>(filePath);
return _q_checkEntry(engine, resolvingEntry);
}
@@ -155,10 +119,11 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent
break;
const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator));
- for (int i = 0; i < paths.count(); i++) {
- entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) % QLatin1Char('/') % QStringView{filePath}.mid(prefixSeparator + 1)));
+ for (int i = 0; i < paths.size(); i++) {
+ entry = QFileSystemEntry(QDir::cleanPath(
+ paths.at(i) % u'/' % QStringView{filePath}.mid(prefixSeparator + 1)));
// Recurse!
- if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true))
+ if (_q_createLegacyEngine_recursive(entry, data, engine, true))
return true;
}
@@ -188,12 +153,13 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent
QFileSystemEngine API should be used to query and interact with the file
system object.
*/
-QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
- QFileSystemEntry &entry, QFileSystemMetaData &data) {
+std::unique_ptr<QAbstractFileEngine>
+QFileSystemEngine::createLegacyEngine(QFileSystemEntry &entry, QFileSystemMetaData &data)
+{
QFileSystemEntry copy = entry;
- QAbstractFileEngine *engine = nullptr;
+ std::unique_ptr<QAbstractFileEngine> engine;
- if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
+ if (_q_createLegacyEngine_recursive(copy, data, engine))
// Reset entry to resolved copy.
entry = copy;
else
@@ -232,4 +198,17 @@ QString QFileSystemEngine::resolveGroupName(const QFileSystemEntry &entry, QFile
#endif
}
+//static
+QFileSystemEntry QFileSystemEngine::getJunctionTarget(const QFileSystemEntry &link,
+ QFileSystemMetaData &data)
+{
+#if defined(Q_OS_WIN)
+ return junctionTarget(link, data);
+#else
+ Q_UNUSED(link);
+ Q_UNUSED(data);
+ return {};
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_mac.mm b/src/corelib/io/qfilesystemengine_mac.mm
index 02765322f8..e3f567b7a4 100644
--- a/src/corelib/io/qfilesystemengine_mac.mm
+++ b/src/corelib/io/qfilesystemengine_mac.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qfilesystemengine_p.h"
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index 555483a972..814915407e 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMENGINE_P_H
#define QFILESYSTEMENGINE_P_H
@@ -56,6 +20,9 @@
#include "qfilesystemmetadata_p.h"
#include <QtCore/private/qsystemerror_p.h>
+#include <memory>
+#include <optional>
+
QT_BEGIN_NAMESPACE
#define Q_RETURN_ON_INVALID_FILENAME(message, result) \
@@ -101,6 +68,9 @@ public:
}
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data);
+ static QFileSystemEntry getRawLinkPath(const QFileSystemEntry &link,
+ QFileSystemMetaData &data);
+ static QFileSystemEntry getJunctionTarget(const QFileSystemEntry &link, QFileSystemMetaData &data);
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
static QFileSystemEntry absoluteName(const QFileSystemEntry &entry);
static QByteArray id(const QFileSystemEntry &entry);
@@ -115,7 +85,7 @@ public:
#if defined(Q_OS_DARWIN)
static QString bundleName(const QFileSystemEntry &entry);
#else
- static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
+ static QString bundleName(const QFileSystemEntry &) { return QString(); }
#endif
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
@@ -125,12 +95,12 @@ public:
static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
static QByteArray id(int fd);
static bool setFileTime(int fd, const QDateTime &newDate,
- QAbstractFileEngine::FileTime whatTime, QSystemError &error);
+ QFile::FileTime whatTime, QSystemError &error);
static bool setPermissions(int fd, QFile::Permissions permissions, QSystemError &error,
QFileSystemMetaData *data = nullptr);
#endif
#if defined(Q_OS_WIN)
-
+ static QFileSystemEntry junctionTarget(const QFileSystemEntry &link, QFileSystemMetaData &data);
static bool uncListSharesOnServer(const QString &server, QStringList *list); //Used also by QFSFileEngineIterator::hasNext()
static bool fillMetaData(int fd, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what);
@@ -140,16 +110,18 @@ public:
QFileSystemMetaData::MetaDataFlags what);
static QByteArray id(HANDLE fHandle);
static bool setFileTime(HANDLE fHandle, const QDateTime &newDate,
- QAbstractFileEngine::FileTime whatTime, QSystemError &error);
+ QFile::FileTime whatTime, QSystemError &error);
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
static QString nativeAbsoluteFilePath(const QString &path);
+ static bool isDirPath(const QString &path, bool *existed);
#endif
//homePath, rootPath and tempPath shall return clean paths
static QString homePath();
static QString rootPath();
static QString tempPath();
- static bool createDirectory(const QFileSystemEntry &entry, bool createParents);
+ static bool createDirectory(const QFileSystemEntry &entry, bool createParents,
+ std::optional<QFile::Permissions> permissions = std::nullopt);
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents);
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
@@ -165,13 +137,14 @@ public:
// unused, therefore not implemented
static bool setFileTime(const QFileSystemEntry &entry, const QDateTime &newDate,
- QAbstractFileEngine::FileTime whatTime, QSystemError &error);
+ QFile::FileTime whatTime, QSystemError &error);
static bool setCurrentPath(const QFileSystemEntry &entry);
static QFileSystemEntry currentPath();
- static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
- QFileSystemMetaData &data);
+ static std::unique_ptr<QAbstractFileEngine>
+ createLegacyEngine(QFileSystemEntry &entry, QFileSystemMetaData &data);
+
private:
static QString slowCanonicalized(const QString &path);
#if defined(Q_OS_WIN)
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index d91807c342..2f6c0ae184 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -1,64 +1,34 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qfilesystemengine_p.h"
#include "qfile.h"
#include "qstorageinfo.h"
+#include "qurl.h"
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/private/qcore_unix_p.h>
+#include <QtCore/private/qfiledevice_p.h>
+#include <QtCore/private/qfunctions_p.h>
#include <QtCore/qvarlengtharray.h>
#ifndef QT_BOOTSTRAPPED
# include <QtCore/qstandardpaths.h>
+# include <QtCore/private/qtemporaryfile_p.h>
#endif // QT_BOOTSTRAPPED
+#include <grp.h>
#include <pwd.h>
#include <stdlib.h> // for realpath()
-#include <sys/types.h>
-#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <chrono>
+#include <memory> // for std::unique_ptr
+
#if __has_include(<paths.h>)
# include <paths.h>
#endif
@@ -66,9 +36,14 @@
# define _PATH_TMP "/tmp"
#endif
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
# include <QtCore/private/qcore_mac_p.h>
# include <CoreFoundation/CFBundle.h>
+# include <UniformTypeIdentifiers/UTType.h>
+# include <UniformTypeIdentifiers/UTCoreTypes.h>
+# include <Foundation/Foundation.h>
+# include <sys/clonefile.h>
+# include <copyfile.h>
#endif
#ifdef Q_OS_MACOS
@@ -79,15 +54,6 @@
#include <MobileCoreServices/MobileCoreServices.h>
#endif
-#if defined(Q_OS_DARWIN)
-# include <sys/clonefile.h>
-# include <copyfile.h>
-// We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but
-// we need these declarations:
-Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
-extern "C" NSString *NSTemporaryDirectory();
-#endif
-
#if defined(Q_OS_LINUX)
# include <sys/ioctl.h>
# include <sys/sendfile.h>
@@ -112,6 +78,8 @@ struct statx { mode_t stx_mode; }; // dummy
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
enum {
#ifdef Q_OS_ANDROID
// On Android, the link(2) system call has been observed to always fail
@@ -155,10 +123,9 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
QString suffix = info.suffix();
if (suffix.length() > 0) {
- // First step: is the extension known ?
- QCFType<CFStringRef> extensionRef = suffix.toCFString();
- QCFType<CFStringRef> uniformTypeIdentifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extensionRef, NULL);
- if (UTTypeConformsTo(uniformTypeIdentifier, kUTTypeBundle))
+ // First step: is it a bundle?
+ const auto *utType = [UTType typeWithFilenameExtension:suffix.toNSString()];
+ if ([utType conformsToType:UTTypeBundle])
return true;
// Second step: check if an application knows the package type
@@ -179,7 +146,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, application);
CFStringRef identifier = CFBundleGetIdentifier(bundle);
QString applicationId = QString::fromCFString(identifier);
- if (applicationId != QLatin1String("com.apple.finder"))
+ if (applicationId != "com.apple.finder"_L1)
return true;
}
#endif
@@ -192,92 +159,80 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
namespace {
namespace GetFileTimes {
-#if !QT_CONFIG(futimens) && (QT_CONFIG(futimes))
-template <typename T>
-static inline typename QtPrivate::QEnableIf<(&T::st_atim, &T::st_mtim, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification)
+qint64 time_t_toMsecs(time_t t)
{
- access->tv_sec = p->st_atim.tv_sec;
- access->tv_usec = p->st_atim.tv_nsec / 1000;
-
- modification->tv_sec = p->st_mtim.tv_sec;
- modification->tv_usec = p->st_mtim.tv_nsec / 1000;
+ using namespace std::chrono;
+ return milliseconds{seconds{t}}.count();
}
-template <typename T>
-static inline typename QtPrivate::QEnableIf<(&T::st_atimespec, &T::st_mtimespec, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification)
+// fallback set
+[[maybe_unused]] qint64 atime(const QT_STATBUF &statBuffer, ulong)
{
- access->tv_sec = p->st_atimespec.tv_sec;
- access->tv_usec = p->st_atimespec.tv_nsec / 1000;
-
- modification->tv_sec = p->st_mtimespec.tv_sec;
- modification->tv_usec = p->st_mtimespec.tv_nsec / 1000;
+ return time_t_toMsecs(statBuffer.st_atime);
}
-
-# ifndef st_atimensec
-// if "st_atimensec" is defined, this would expand to invalid C++
-template <typename T>
-static inline typename QtPrivate::QEnableIf<(&T::st_atimensec, &T::st_mtimensec, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification)
+[[maybe_unused]] qint64 birthtime(const QT_STATBUF &, ulong)
{
- access->tv_sec = p->st_atime;
- access->tv_usec = p->st_atimensec / 1000;
-
- modification->tv_sec = p->st_mtime;
- modification->tv_usec = p->st_mtimensec / 1000;
+ return Q_INT64_C(0);
}
-# endif
-#endif
-
-qint64 timespecToMSecs(const timespec &spec)
+[[maybe_unused]] qint64 ctime(const QT_STATBUF &statBuffer, ulong)
+{
+ return time_t_toMsecs(statBuffer.st_ctime);
+}
+[[maybe_unused]] qint64 mtime(const QT_STATBUF &statBuffer, ulong)
{
- return (qint64(spec.tv_sec) * 1000) + (spec.tv_nsec / 1000000);
+ return time_t_toMsecs(statBuffer.st_mtime);
}
-// fallback set
-Q_DECL_UNUSED qint64 atime(const QT_STATBUF &statBuffer, ulong) { return qint64(statBuffer.st_atime) * 1000; }
-Q_DECL_UNUSED qint64 birthtime(const QT_STATBUF &, ulong) { return Q_INT64_C(0); }
-Q_DECL_UNUSED qint64 ctime(const QT_STATBUF &statBuffer, ulong) { return qint64(statBuffer.st_ctime) * 1000; }
-Q_DECL_UNUSED qint64 mtime(const QT_STATBUF &statBuffer, ulong) { return qint64(statBuffer.st_mtime) * 1000; }
+// T is either a stat.timespec or statx.statx_timestamp,
+// both have tv_sec and tv_nsec members
+template<typename T>
+qint64 timespecToMSecs(const T &spec)
+{
+ using namespace std::chrono;
+ const nanoseconds nsecs = seconds{spec.tv_sec} + nanoseconds{spec.tv_nsec};
+ return duration_cast<milliseconds>(nsecs).count();
+}
// Xtim, POSIX.1-2008
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_atim, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_atim, true), qint64>::type
atime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_atim); }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_birthtim, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_birthtim, true), qint64>::type
birthtime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_birthtim); }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_ctim, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_ctim, true), qint64>::type
ctime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_ctim); }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_mtim, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_mtim, true), qint64>::type
mtime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_mtim); }
#ifndef st_mtimespec
// Xtimespec
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_atimespec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_atimespec, true), qint64>::type
atime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_atimespec); }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_birthtimespec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_birthtimespec, true), qint64>::type
birthtime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_birthtimespec); }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_ctimespec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_ctimespec, true), qint64>::type
ctime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_ctimespec); }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_mtimespec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_mtimespec, true), qint64>::type
mtime(const T &statBuffer, int)
{ return timespecToMSecs(statBuffer.st_mtimespec); }
#endif
@@ -285,22 +240,22 @@ mtime(const T &statBuffer, int)
#if !defined(st_mtimensec) && !defined(__alpha__)
// Xtimensec
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_atimensec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_atimensec, true), qint64>::type
atime(const T &statBuffer, int)
{ return statBuffer.st_atime * Q_INT64_C(1000) + statBuffer.st_atimensec / 1000000; }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_birthtimensec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_birthtimensec, true), qint64>::type
birthtime(const T &statBuffer, int)
{ return statBuffer.st_birthtime * Q_INT64_C(1000) + statBuffer.st_birthtimensec / 1000000; }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_ctimensec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_ctimensec, true), qint64>::type
ctime(const T &statBuffer, int)
{ return statBuffer.st_ctime * Q_INT64_C(1000) + statBuffer.st_ctimensec / 1000000; }
template <typename T>
-Q_DECL_UNUSED static typename std::enable_if<(&T::st_mtimensec, true), qint64>::type
+[[maybe_unused]] static typename std::enable_if<(&T::st_mtimensec, true), qint64>::type
mtime(const T &statBuffer, int)
{ return statBuffer.st_mtime * Q_INT64_C(1000) + statBuffer.st_mtimensec / 1000000; }
#endif
@@ -311,7 +266,7 @@ mtime(const T &statBuffer, int)
static int qt_real_statx(int fd, const char *pathname, int flags, struct statx *statxBuffer)
{
unsigned mask = STATX_BASIC_STATS | STATX_BTIME;
- int ret = statx(fd, pathname, flags, mask, statxBuffer);
+ int ret = statx(fd, pathname, flags | AT_NO_AUTOMOUNT, mask, statxBuffer);
return ret == -1 ? -errno : 0;
}
@@ -371,17 +326,12 @@ inline void QFileSystemMetaData::fillFromStatxBuf(const struct statx &statxBuffe
size_ = qint64(statxBuffer.stx_size);
// Times
- auto toMSecs = [](struct statx_timestamp ts)
- {
- return qint64(ts.tv_sec) * 1000 + (ts.tv_nsec / 1000000);
- };
- accessTime_ = toMSecs(statxBuffer.stx_atime);
- metadataChangeTime_ = toMSecs(statxBuffer.stx_ctime);
- modificationTime_ = toMSecs(statxBuffer.stx_mtime);
- if (statxBuffer.stx_mask & STATX_BTIME)
- birthTime_ = toMSecs(statxBuffer.stx_btime);
- else
- birthTime_ = 0;
+ using namespace GetFileTimes;
+ accessTime_ = timespecToMSecs(statxBuffer.stx_atime);
+ metadataChangeTime_ = timespecToMSecs(statxBuffer.stx_ctime);
+ modificationTime_ = timespecToMSecs(statxBuffer.stx_mtime);
+ const bool birthMask = statxBuffer.stx_mask & STATX_BTIME;
+ birthTime_ = birthMask ? timespecToMSecs(statxBuffer.stx_btime) : 0;
userId_ = statxBuffer.stx_uid;
groupId_ = statxBuffer.stx_gid;
@@ -406,10 +356,7 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
- union {
- struct statx statxBuffer;
- QT_STATBUF statBuffer;
- };
+ struct statx statxBuffer;
int ret = qt_fstatx(fd, &statxBuffer);
if (ret != -ENOSYS) {
@@ -420,6 +367,8 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
return false;
}
+ QT_STATBUF statBuffer;
+
if (QT_FSTAT(fd, &statBuffer) == 0) {
data.fillFromStatBuf(statBuffer);
return true;
@@ -504,8 +453,8 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
{
#if defined(_DEXTRA_FIRST)
- knownFlagsMask = 0;
- entryFlags = 0;
+ knownFlagsMask = {};
+ entryFlags = {};
for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry);
extra = _DEXTRA_NEXT(extra)) {
if (extra->d_type == _DTYPE_STAT || extra->d_type == _DTYPE_LSTAT) {
@@ -615,7 +564,7 @@ void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
clear();
}
#else
- Q_UNUSED(entry)
+ Q_UNUSED(entry);
#endif
}
@@ -625,7 +574,7 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
Q_CHECK_FILE_NAME(link, link);
QByteArray s = qt_readlink(link.nativeFilePath().constData());
- if (s.length() > 0) {
+ if (s.size() > 0) {
QString ret;
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
fillMetaData(link, data, QFileSystemMetaData::DirectoryType);
@@ -633,15 +582,15 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
QDir parent(link.filePath());
parent.cdUp();
ret = parent.path();
- if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
- ret += QLatin1Char('/');
+ if (!ret.isEmpty() && !ret.endsWith(u'/'))
+ ret += u'/';
}
ret += QFile::decodeName(s);
- if (!ret.startsWith(QLatin1Char('/')))
- ret.prepend(absoluteName(link).path() + QLatin1Char('/'));
+ if (!ret.startsWith(u'/'))
+ ret.prepend(absoluteName(link).path() + u'/');
ret = QDir::cleanPath(ret);
- if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
+ if (ret.size() > 1 && ret.endsWith(u'/'))
ret.chop(1);
return QFileSystemEntry(ret);
}
@@ -679,45 +628,60 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
}
//static
+QFileSystemEntry QFileSystemEngine::getRawLinkPath(const QFileSystemEntry &link,
+ QFileSystemMetaData &data)
+{
+ Q_UNUSED(data)
+ const QByteArray path = qt_readlink(link.nativeFilePath().constData());
+ const QString ret = QFile::decodeName(path);
+ return QFileSystemEntry(ret);
+}
+
+//static
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
{
Q_CHECK_FILE_NAME(entry, entry);
-#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_HAIKU) && _POSIX_VERSION < 200809L
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_HAIKU) && _POSIX_VERSION < 200809L && !defined(Q_OS_VXWORKS)
// realpath(X,0) is not supported
Q_UNUSED(data);
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
#else
- char stack_result[PATH_MAX+1];
- char *resolved_name = nullptr;
+# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
+ // used to store the result of realpath in case where realpath cannot allocate itself
+ char stack_result[PATH_MAX + 1];
+#else
+ // enables unconditionally passing stack_result below
+ std::nullptr_t stack_result = nullptr;
+# endif
+ auto resolved_path_deleter = [&](char *ptr) {
+ // frees resolved_name if it was allocated by realpath
+# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
+ // ptr is either null, or points to stack_result
+ Q_ASSERT(!ptr || ptr == stack_result);
+ return;
+#else
+ free(ptr);
+# endif
+ };
+ std::unique_ptr<char, decltype (resolved_path_deleter)> resolved_name {nullptr, resolved_path_deleter};
# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
// On some Android and macOS versions, realpath() will return a path even if
// it does not exist. To work around this, we check existence in advance.
if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute))
fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute);
- if (!data.exists()) {
+ if (!data.exists())
errno = ENOENT;
- } else {
- resolved_name = stack_result;
- }
- if (resolved_name && realpath(entry.nativeFilePath().constData(), resolved_name) == nullptr)
- resolved_name = nullptr;
+ else
+ resolved_name.reset(realpath(entry.nativeFilePath().constData(), stack_result));
# else
-# if _POSIX_VERSION >= 200801L // ask realpath to allocate memory
- resolved_name = realpath(entry.nativeFilePath().constData(), nullptr);
-# else
- resolved_name = stack_result;
- if (realpath(entry.nativeFilePath().constData(), resolved_name) == nullptr)
- resolved_name = nullptr;
-# endif
+ resolved_name.reset(realpath(entry.nativeFilePath().constData(), stack_result));
# endif
if (resolved_name) {
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
- QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name));
- if (resolved_name != stack_result)
- free(resolved_name);
+ QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name.get()));
return QFileSystemEntry(canonicalPath);
} else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
@@ -742,13 +706,13 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
QFileSystemEntry cur(currentPath());
result = cur.nativeFilePath();
}
- if (!orig.isEmpty() && !(orig.length() == 1 && orig[0] == '.')) {
+ if (!orig.isEmpty() && !(orig.size() == 1 && orig[0] == '.')) {
if (!result.isEmpty() && !result.endsWith('/'))
result.append('/');
result.append(orig);
}
- if (result.length() == 1 && result[0] == '/')
+ if (result.size() == 1 && result[0] == '/')
return QFileSystemEntry(result, QFileSystemEntry::FromNativePath());
const bool isDir = result.endsWith('/');
@@ -759,7 +723,7 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
QFileSystemEntry resultingEntry(result, QFileSystemEntry::FromNativePath());
QString stringVersion = QDir::cleanPath(resultingEntry.filePath());
if (isDir)
- stringVersion.append(QLatin1Char('/'));
+ stringVersion.append(u'/');
return QFileSystemEntry(stringVersion);
}
@@ -798,7 +762,7 @@ QByteArray QFileSystemEngine::id(int fd)
QString QFileSystemEngine::resolveUserName(uint userId)
{
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
- int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ long size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
if (size_max == -1)
size_max = 1024;
QVarLengthArray<char, 1024> buf(size_max);
@@ -824,7 +788,7 @@ QString QFileSystemEngine::resolveUserName(uint userId)
QString QFileSystemEngine::resolveGroupName(uint groupId)
{
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
- int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ long size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
if (size_max == -1)
size_max = 1024;
QVarLengthArray<char, 1024> buf(size_max);
@@ -840,7 +804,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId)
struct group entry;
// Some large systems have more members than the POSIX max size
// Loop over by doubling the buffer size (upper limit 250k)
- for (unsigned size = size_max; size < 256000; size += size)
+ for (long size = size_max; size < 256000; size += size)
{
buf.resize(size);
// ERANGE indicates that the buffer was too small
@@ -853,7 +817,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId)
#endif
if (gr)
return QFile::decodeName(QByteArray(gr->gr_name));
-#else // Integrity || WASM
+#else // Integrity || WASM || VxWorks
Q_UNUSED(groupId);
#endif
return QString();
@@ -886,6 +850,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
what |= QFileSystemMetaData::DirectoryType;
}
+ if (what & QFileSystemMetaData::AliasType)
+ what |= QFileSystemMetaData::LinkType;
#endif
#ifdef UF_HIDDEN
if (what & QFileSystemMetaData::HiddenAttribute) {
@@ -1021,8 +987,11 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
#if defined(Q_OS_DARWIN)
if (what & QFileSystemMetaData::AliasType) {
- if (entryErrno == 0 && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
- data.entryFlags |= QFileSystemMetaData::AliasType;
+ if (entryErrno == 0 && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey)) {
+ // kCFURLIsAliasFileKey includes symbolic links, so filter those out
+ if (!(data.entryFlags & QFileSystemMetaData::LinkType))
+ data.entryFlags |= QFileSystemMetaData::AliasType;
+ }
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
}
@@ -1037,7 +1006,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
if (what & QFileSystemMetaData::HiddenAttribute
&& !data.isHidden()) {
QString fileName = entry.fileName();
- if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
+ if (fileName.startsWith(u'.')
#if defined(Q_OS_DARWIN)
|| (entryErrno == 0 && hasResourcePropertyFlag(data, entry, kCFURLIsHiddenKey))
#endif
@@ -1112,7 +1081,8 @@ bool QFileSystemEngine::cloneFile(int srcfd, int dstfd, const QFileSystemMetaDat
// Note: if \a shouldMkdirFirst is false, we assume the caller did try to mkdir
// before calling this function.
-static bool createDirectoryWithParents(const QByteArray &nativeName, bool shouldMkdirFirst = true)
+static bool createDirectoryWithParents(const QByteArray &nativeName, mode_t mode,
+ bool shouldMkdirFirst = true)
{
// helper function to check if a given path is a directory, since mkdir can
// fail if the dir already exists (it may have been created by another
@@ -1122,7 +1092,9 @@ static bool createDirectoryWithParents(const QByteArray &nativeName, bool should
return QT_STAT(nativeName.constData(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR;
};
- if (shouldMkdirFirst && QT_MKDIR(nativeName, 0777) == 0)
+ if (shouldMkdirFirst && QT_MKDIR(nativeName, mode) == 0)
+ return true;
+ if (errno == EISDIR)
return true;
if (errno == EEXIST)
return isDir(nativeName);
@@ -1130,38 +1102,39 @@ static bool createDirectoryWithParents(const QByteArray &nativeName, bool should
return false;
// mkdir failed because the parent dir doesn't exist, so try to create it
- int slash = nativeName.lastIndexOf('/');
+ qsizetype slash = nativeName.lastIndexOf('/');
if (slash < 1)
return false;
QByteArray parentNativeName = nativeName.left(slash);
- if (!createDirectoryWithParents(parentNativeName))
+ if (!createDirectoryWithParents(parentNativeName, mode))
return false;
// try again
- if (QT_MKDIR(nativeName, 0777) == 0)
+ if (QT_MKDIR(nativeName, mode) == 0)
return true;
return errno == EEXIST && isDir(nativeName);
}
//static
-bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
+bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents,
+ std::optional<QFile::Permissions> permissions)
{
- QString dirName = entry.filePath();
+ QByteArray dirName = entry.nativeFilePath();
Q_CHECK_FILE_NAME(dirName, false);
// Darwin doesn't support trailing /'s, so remove for everyone
- while (dirName.size() > 1 && dirName.endsWith(QLatin1Char('/')))
+ while (dirName.size() > 1 && dirName.endsWith(u'/'))
dirName.chop(1);
// try to mkdir this directory
- QByteArray nativeName = QFile::encodeName(dirName);
- if (QT_MKDIR(nativeName, 0777) == 0)
+ mode_t mode = permissions ? QtPrivate::toMode_t(*permissions) : 0777;
+ if (QT_MKDIR(dirName, mode) == 0)
return true;
if (!createParents)
return false;
- return createDirectoryWithParents(nativeName, false);
+ return createDirectoryWithParents(dirName, mode, false);
}
//static
@@ -1171,7 +1144,7 @@ bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool remo
if (removeEmptyParents) {
QString dirName = QDir::cleanPath(entry.filePath());
- for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
+ for (qsizetype oldslash = 0, slash=dirName.size(); slash > 0; oldslash = slash) {
const QByteArray chunk = QFile::encodeName(dirName.left(slash));
QT_STATBUF st;
if (QT_STAT(chunk.constData(), &st) != -1) {
@@ -1201,42 +1174,169 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
return false;
}
-#ifndef Q_OS_DARWIN
+#ifdef Q_OS_DARWIN
+// see qfilesystemengine_mac.mm
+#elif defined(QT_BOOTSTRAPPED) || !defined(AT_FDCWD)
+// bootstrapped tools don't need this, and we don't want QStorageInfo
+//static
+bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &, QFileSystemEntry &,
+ QSystemError &error)
+{
+ error = QSystemError(ENOSYS, QSystemError::StandardLibraryError);
+ return false;
+}
+#else
/*
Implementing as per https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html
*/
-// bootstrapped tools don't need this, and we don't want QStorageInfo
-#ifndef QT_BOOTSTRAPPED
-static QString freeDesktopTrashLocation(const QString &sourcePath)
+namespace {
+struct FreeDesktopTrashOperation
{
- auto makeTrashDir = [](const QDir &topDir, const QString &trashDir) -> QString {
- auto ownerPerms = QFileDevice::ReadOwner
- | QFileDevice::WriteOwner
- | QFileDevice::ExeOwner;
- QString targetDir = topDir.filePath(trashDir);
- // deliberately not using mkpath, since we want to fail if topDir doesn't exist
- if (topDir.mkdir(trashDir))
- QFile::setPermissions(targetDir, ownerPerms);
- if (QFileInfo(targetDir).isDir())
- return targetDir;
- return QString();
- };
- auto isSticky = [](const QFileInfo &fileInfo) -> bool {
- struct stat st;
- if (stat(QFile::encodeName(fileInfo.absoluteFilePath()).constData(), &st) == 0)
- return st.st_mode & S_ISVTX;
+ /*
+ "A trash directory contains two subdirectories, named info and files."
+ */
+ QString trashPath;
+ int filesDirFd = -1;
+ int infoDirFd = -1;
+ qsizetype volumePrefixLength = 0;
- return false;
- };
+ // relative file paths to the filesDirFd and infoDirFd from above
+ QByteArray tempTrashFileName;
+ QByteArray infoFilePath;
+
+ int infoFileFd = -1; // if we've already opened it
+ ~FreeDesktopTrashOperation()
+ {
+ close();
+ }
+
+ constexpr bool isTrashDirOpen() const { return filesDirFd != -1 && infoDirFd != -1; }
+
+ void close()
+ {
+ int savedErrno = errno;
+ if (infoFileFd != -1) {
+ Q_ASSERT(infoDirFd != -1);
+ Q_ASSERT(!infoFilePath.isEmpty());
+ Q_ASSERT(!trashPath.isEmpty());
+
+ QT_CLOSE(infoFileFd);
+ unlinkat(infoDirFd, infoFilePath, 0);
+ infoFileFd = -1;
+ }
+ if (!tempTrashFileName.isEmpty()) {
+ Q_ASSERT(filesDirFd != -1);
+ unlinkat(filesDirFd, tempTrashFileName, 0);
+ }
+ if (filesDirFd >= 0)
+ QT_CLOSE(filesDirFd);
+ if (infoDirFd >= 0)
+ QT_CLOSE(infoDirFd);
+ filesDirFd = infoDirFd = -1;
+ errno = savedErrno;
+ }
+
+ bool tryCreateInfoFile(const QString &filePath, QSystemError &error)
+ {
+ QByteArray p = QFile::encodeName(filePath) + ".trashinfo";
+ infoFileFd = qt_safe_openat(infoDirFd, p, QT_OPEN_RDWR | QT_OPEN_CREAT | QT_OPEN_EXCL, 0666);
+ if (infoFileFd < 0) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+ infoFilePath = std::move(p);
+ return true;
+ }
+
+ void commit()
+ {
+ QT_CLOSE(infoFileFd);
+ infoFileFd = -1;
+ tempTrashFileName = {};
+ }
+
+ // opens a directory and returns the file descriptor
+ static int openDirFd(int dfd, const char *path, int mode = 0)
+ {
+ mode |= QT_OPEN_RDONLY | O_NOFOLLOW | O_DIRECTORY;
+ return qt_safe_openat(dfd, path, mode);
+ }
+
+ // opens an XDG Trash directory that is a subdirectory of dfd, creating if necessary
+ static int openOrCreateDir(int dfd, const char *path)
+ {
+ // try to open it as a dir, first
+ int fd = openDirFd(dfd, path);
+ if (fd >= 0 || errno != ENOENT)
+ return fd;
+
+ // try to mkdirat
+ if (mkdirat(dfd, path, 0700) < 0)
+ return -1;
+
+ // try to open it again
+ return openDirFd(dfd, path);
+ }
+
+ // opens or makes the XDG Trash hierarchy on parentfd (may be -1) called targetDir
+ bool getTrashDir(int parentfd, QString targetDir, const QFileSystemEntry &source,
+ QSystemError &error)
+ {
+ if (parentfd == AT_FDCWD)
+ trashPath = targetDir;
+ QByteArray nativePath = QFile::encodeName(targetDir);
+
+ // open the directory
+ int trashfd = openOrCreateDir(parentfd, nativePath);
+ if (trashfd < 0 && errno != ENOENT) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ // check if it is ours (even if we've just mkdirat'ed it)
+ if (QT_STATBUF st; QT_FSTAT(trashfd, &st) < 0) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ } else if (st.st_uid != getuid()) {
+ error = QSystemError(EPERM, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ filesDirFd = openOrCreateDir(trashfd, "files");
+ if (filesDirFd >= 0) {
+ // try to link our file-to-be-trashed here
+ QTemporaryFileName tfn("XXXXXX"_L1);
+ for (int i = 0; i < 16; ++i) {
+ QByteArray attempt = tfn.generateNext();
+ if (linkat(AT_FDCWD, source.nativeFilePath(), filesDirFd, attempt, 0) == 0) {
+ tempTrashFileName = std::move(attempt);
+ break;
+ }
+ if (errno != EEXIST)
+ break;
+ }
+
+ // man 2 link on Linux has:
+ // EPERM The filesystem containing oldpath and newpath does not
+ // support the creation of hard links.
+ // EPERM oldpath is a directory.
+ // EPERM oldpath is marked immutable or append‐only.
+ // EMLINK The file referred to by oldpath already has the maximum
+ // number of links to it.
+ if (!tempTrashFileName.isEmpty() || errno == EPERM || errno == EMLINK)
+ infoDirFd = openOrCreateDir(trashfd, "info");
+ }
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ if (infoDirFd < 0)
+ close();
+ QT_CLOSE(trashfd);
+ return infoDirFd >= 0;
+ }
- QString trash;
- const QStorageInfo sourceStorage(sourcePath);
- const QStorageInfo homeStorage(QDir::home());
- // We support trashing of files outside the users home partition
- if (sourceStorage != homeStorage) {
- const QLatin1String dotTrash(".Trash");
- QDir topDir(sourceStorage.rootPath());
+ bool openMountPointTrashLocation(const QFileSystemEntry &source,
+ const QStorageInfo &sourceStorage, QSystemError &error)
+ {
/*
Method 1:
"An administrator can create an $topdir/.Trash directory. The permissions on this
@@ -1247,21 +1347,31 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
(if it supports trashing in top directories) MUST check for the presence
of $topdir/.Trash."
*/
- const QString userID = QString::number(::getuid());
- if (topDir.cd(dotTrash)) {
- const QFileInfo trashInfo(topDir.path());
- // we MUST check that the sticky bit is set, and that it is not a symlink
- if (trashInfo.isSymLink()) {
+ const auto dotTrash = "/.Trash"_L1;
+ const QString userID = QString::number(::getuid());
+ QFileSystemEntry dotTrashDir(sourceStorage.rootPath() + dotTrash);
+
+ // we MUST check that the sticky bit is set, and that it is not a symlink
+ int genericTrashFd = openDirFd(AT_FDCWD, dotTrashDir.nativeFilePath());
+ QT_STATBUF st = {};
+ if (genericTrashFd < 0 && errno != ENOENT && errno != EACCES) {
+ // O_DIRECTORY + O_NOFOLLOW produces ENOTDIR on Linux
+ if (QT_LSTAT(dotTrashDir.nativeFilePath(), &st) == 0 && S_ISLNK(st.st_mode)) {
// we SHOULD report the failed check to the administrator
qCritical("Warning: '%s' is a symlink to '%s'",
- trashInfo.absoluteFilePath().toLocal8Bit().constData(),
- trashInfo.symLinkTarget().toLatin1().constData());
- } else if (!isSticky(trashInfo)) {
+ dotTrashDir.nativeFilePath().constData(),
+ qt_readlink(dotTrashDir.nativeFilePath()).constData());
+ error = QSystemError(ELOOP, QSystemError::StandardLibraryError);
+ }
+ } else if (genericTrashFd >= 0) {
+ QT_FSTAT(genericTrashFd, &st);
+ if ((st.st_mode & S_ISVTX) == 0) {
// we SHOULD report the failed check to the administrator
qCritical("Warning: '%s' doesn't have sticky bit set!",
- trashInfo.absoluteFilePath().toLocal8Bit().constData());
- } else if (trashInfo.isDir()) {
+ dotTrashDir.nativeFilePath().constData());
+ error = QSystemError(EPERM, QSystemError::StandardLibraryError);
+ } else {
/*
"If the directory exists and passes the checks, a subdirectory of the
$topdir/.Trash directory is to be used as the user's trash directory
@@ -1271,9 +1381,14 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
the implementation MUST immediately create it, without any warnings or
delays for the user."
*/
- trash = makeTrashDir(topDir, userID);
+ if (getTrashDir(genericTrashFd, userID, source, error)) {
+ // recreate the resulting path
+ trashPath = dotTrashDir.filePath() + u'/' + userID;
+ }
}
+ QT_CLOSE(genericTrashFd);
}
+
/*
Method 2:
"If an $topdir/.Trash directory is absent, an $topdir/.Trash-$uid directory is to be
@@ -1281,138 +1396,146 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
file, if an $topdir/.Trash-$uid directory does not exist, the implementation MUST
immediately create it, without any warnings or delays for the user."
*/
- if (trash.isEmpty()) {
- topDir = QDir(sourceStorage.rootPath());
- const QString userTrashDir = dotTrash + QLatin1Char('-') + userID;
- trash = makeTrashDir(topDir, userTrashDir);
+ if (!isTrashDirOpen())
+ getTrashDir(AT_FDCWD, sourceStorage.rootPath() + dotTrash + u'-' + userID, source, error);
+
+ if (isTrashDirOpen()) {
+ volumePrefixLength = sourceStorage.rootPath().size();
+ if (volumePrefixLength == 1)
+ volumePrefixLength = 0; // isRoot
+ else
+ ++volumePrefixLength; // to include the slash
}
+ return isTrashDirOpen();
}
- /*
- "If both (1) and (2) fail [...], the implementation MUST either trash the
- file into the user's “home trash” or refuse to trash it."
- We trash the file into the user's home trash.
-
- "Its name and location are $XDG_DATA_HOME/Trash"; $XDG_DATA_HOME is what
- QStandardPaths returns for GenericDataLocation. If that doesn't exist, then
- we are not running on a freedesktop.org-compliant environment, and give up.
- */
- if (trash.isEmpty()) {
- QDir topDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
- trash = makeTrashDir(topDir, QLatin1String("Trash"));
- if (!QFileInfo(trash).isDir()) {
- qWarning("Unable to establish trash directory in %s",
- topDir.path().toLocal8Bit().constData());
- }
+ bool openHomeTrashLocation(const QFileSystemEntry &source, QSystemError &error)
+ {
+ QString topDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
+ return getTrashDir(AT_FDCWD, topDir + "/Trash"_L1, source, error);
}
- return trash;
-}
-#endif // QT_BOOTSTRAPPED
+ bool findTrashFor(const QFileSystemEntry &source, QSystemError &error)
+ {
+ /*
+ First, try the standard Trash in $XDG_DATA_DIRS:
+ "Its name and location are $XDG_DATA_HOME/Trash"; $XDG_DATA_HOME is what
+ QStandardPaths returns for GenericDataLocation. If that doesn't exist, then
+ we are not running on a freedesktop.org-compliant environment, and give up.
+ */
+ if (openHomeTrashLocation(source, error))
+ return true;
+ if (error.errorCode != EXDEV)
+ return false;
+
+ // didn't work, try to find the trash outside the home filesystem
+ const QStorageInfo sourceStorage(source.filePath());
+ if (!sourceStorage.isValid())
+ return false;
+ return openMountPointTrashLocation(source, sourceStorage, error);
+ }
+};
+} // unnamed namespace
//static
bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
QFileSystemEntry &newLocation, QSystemError &error)
{
-#ifdef QT_BOOTSTRAPPED
- Q_UNUSED(source);
- Q_UNUSED(newLocation);
- error = QSystemError(ENOSYS, QSystemError::StandardLibraryError);
- return false;
-#else
- const QFileInfo sourceInfo(source.filePath());
- if (!sourceInfo.exists()) {
- error = QSystemError(ENOENT, QSystemError::StandardLibraryError);
+ const QFileSystemEntry sourcePath = [&] {
+ if (QString path = source.filePath(); path.size() > 1 && path.endsWith(u'/')) {
+ path.chop(1);
+ return absoluteName(QFileSystemEntry(path));
+ }
+ return absoluteName(source);
+ }();
+ FreeDesktopTrashOperation op;
+ if (!op.findTrashFor(sourcePath, error))
return false;
- }
- const QString sourcePath = sourceInfo.absoluteFilePath();
- QDir trashDir(freeDesktopTrashLocation(sourcePath));
- if (!trashDir.exists())
- return false;
- /*
- "A trash directory contains two subdirectories, named info and files."
- */
- const QLatin1String filesDir("files");
- const QLatin1String infoDir("info");
- trashDir.mkdir(filesDir);
- int savedErrno = errno;
- trashDir.mkdir(infoDir);
- if (!savedErrno)
- savedErrno = errno;
- if (!trashDir.exists(filesDir) || !trashDir.exists(infoDir)) {
- error = QSystemError(savedErrno, QSystemError::StandardLibraryError);
- return false;
- }
/*
"The $trash/files directory contains the files and directories that were trashed.
The names of files in this directory are to be determined by the implementation;
the only limitation is that they must be unique within the directory. Even if a
file with the same name and location gets trashed many times, each subsequent
trashing must not overwrite a previous copy."
- */
- const QString trashedName = sourceInfo.isDir()
- ? QDir(sourcePath).dirName()
- : sourceInfo.fileName();
- QString uniqueTrashedName = QLatin1Char('/') + trashedName;
- QString infoFileName;
- int counter = 0;
- QFile infoFile;
- auto makeUniqueTrashedName = [trashedName, &counter]() -> QString {
- ++counter;
- return QString(QLatin1String("/%1-%2"))
- .arg(trashedName)
- .arg(counter, 4, 10, QLatin1Char('0'));
- };
- do {
- while (QFile::exists(trashDir.filePath(filesDir) + uniqueTrashedName))
- uniqueTrashedName = makeUniqueTrashedName();
- /*
- "The $trash/info directory contains an "information file" for every file and directory
- in $trash/files. This file MUST have exactly the same name as the file or directory in
- $trash/files, plus the extension ".trashinfo"
- [...]
- When trashing a file or directory, the implementation MUST create the corresponding
- file in $trash/info first. Moreover, it MUST try to do this in an atomic fashion,
- so that if two processes try to trash files with the same filename this will result
- in two different trash files. On Unix-like systems this is done by generating a
- filename, and then opening with O_EXCL. If that succeeds the creation was atomic
- (at least on the same machine), if it fails you need to pick another filename."
- */
- infoFileName = trashDir.filePath(infoDir)
- + uniqueTrashedName + QLatin1String(".trashinfo");
- infoFile.setFileName(infoFileName);
- if (!infoFile.open(QIODevice::NewOnly | QIODevice::WriteOnly | QIODevice::Text))
- uniqueTrashedName = makeUniqueTrashedName();
- } while (!infoFile.isOpen());
- const QString targetPath = trashDir.filePath(filesDir) + uniqueTrashedName;
- const QFileSystemEntry target(targetPath);
-
- /*
- We might fail to rename if source and target are on different file systems.
- In that case, we don't try further, i.e. copying and removing the original
- is usually not what the user would expect to happen.
+ We first try the unchanged base name, then try something different if it collides.
+
+ "The $trash/info directory contains an "information file" for every file and directory
+ in $trash/files. This file MUST have exactly the same name as the file or directory in
+ $trash/files, plus the extension ".trashinfo"
+ [...]
+ When trashing a file or directory, the implementation MUST create the corresponding
+ file in $trash/info first. Moreover, it MUST try to do this in an atomic fashion,
+ so that if two processes try to trash files with the same filename this will result
+ in two different trash files. On Unix-like systems this is done by generating a
+ filename, and then opening with O_EXCL. If that succeeds the creation was atomic
+ (at least on the same machine), if it fails you need to pick another filename."
*/
- if (!renameFile(source, target, error)) {
- infoFile.close();
- infoFile.remove();
- return false;
+ QString uniqueTrashedName = sourcePath.fileName();
+ if (!op.tryCreateInfoFile(uniqueTrashedName, error) && error.errorCode == EEXIST) {
+ // we'll use a counter, starting with the file's inode number to avoid
+ // collisions
+ qulonglong counter;
+ if (QT_STATBUF st; Q_LIKELY(QT_STAT(source.nativeFilePath(), &st) == 0)) {
+ counter = st.st_ino;
+ } else {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ QString uniqueTrashBase = std::move(uniqueTrashedName);
+ for (;;) {
+ uniqueTrashedName = QString::asprintf("%ls-%llu", qUtf16Printable(uniqueTrashBase),
+ counter++);
+ if (op.tryCreateInfoFile(uniqueTrashedName, error))
+ break;
+ if (error.errorCode != EEXIST)
+ return false;
+ };
}
QByteArray info =
"[Trash Info]\n"
- "Path=" + sourcePath.toUtf8() + "\n"
- "DeletionDate=" + QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-ddThh:mm:ss")).toUtf8()
+ "Path=" + QUrl::toPercentEncoding(source.filePath().mid(op.volumePrefixLength), "/") + "\n"
+ "DeletionDate=" + QDateTime::currentDateTime().toString(Qt::ISODate).toUtf8()
+ "\n";
- infoFile.write(info);
- infoFile.close();
+ if (QT_WRITE(op.infoFileFd, info.data(), info.size()) < 0) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
- newLocation = QFileSystemEntry(targetPath);
+ /*
+ If we've already linked the file-to-be-trashed into the trash
+ directory, we know it's in the same mountpoint and we won't get ENOSPC
+ renaming the temporary file to the target name either.
+ */
+ bool renamed;
+ if (op.tempTrashFileName.isEmpty()) {
+ /*
+ We did not get a link (we're trying to trash a directory or on a
+ filesystem that doesn't support hardlinking), so rename straight
+ from the original name. We might fail to rename if source and target
+ are on different file systems.
+ */
+ renamed = renameat(AT_FDCWD, source.nativeFilePath(), op.filesDirFd,
+ QFile::encodeName(uniqueTrashedName)) == 0;
+ } else {
+ renamed = renameat(op.filesDirFd, op.tempTrashFileName, op.filesDirFd,
+ QFile::encodeName(uniqueTrashedName)) == 0;
+ if (renamed)
+ removeFile(source, error); // success, delete the original file
+ }
+ if (!renamed) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ op.commit();
+ newLocation = QFileSystemEntry(op.trashPath + "/files/"_L1 + uniqueTrashedName);
return true;
-#endif // QT_BOOTSTRAPPED
}
-#endif // Q_OS_DARWIN
+#endif // !Q_OS_DARWIN && !QT_BOOTSTRAPPED
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
@@ -1526,40 +1649,16 @@ bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &
}
-static mode_t toMode_t(QFile::Permissions permissions)
-{
- mode_t mode = 0;
- if (permissions & (QFile::ReadOwner | QFile::ReadUser))
- mode |= S_IRUSR;
- if (permissions & (QFile::WriteOwner | QFile::WriteUser))
- mode |= S_IWUSR;
- if (permissions & (QFile::ExeOwner | QFile::ExeUser))
- mode |= S_IXUSR;
- if (permissions & QFile::ReadGroup)
- mode |= S_IRGRP;
- if (permissions & QFile::WriteGroup)
- mode |= S_IWGRP;
- if (permissions & QFile::ExeGroup)
- mode |= S_IXGRP;
- if (permissions & QFile::ReadOther)
- mode |= S_IROTH;
- if (permissions & QFile::WriteOther)
- mode |= S_IWOTH;
- if (permissions & QFile::ExeOther)
- mode |= S_IXOTH;
- return mode;
-}
-
//static
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
{
Q_CHECK_FILE_NAME(entry, false);
- mode_t mode = toMode_t(permissions);
+ mode_t mode = QtPrivate::toMode_t(permissions);
bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0;
if (success && data) {
data->entryFlags &= ~QFileSystemMetaData::Permissions;
- data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
+ data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions.toInt()));
data->knownFlagsMask |= QFileSystemMetaData::Permissions;
}
if (!success)
@@ -1570,12 +1669,12 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
//static
bool QFileSystemEngine::setPermissions(int fd, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
{
- mode_t mode = toMode_t(permissions);
+ mode_t mode = QtPrivate::toMode_t(permissions);
bool success = ::fchmod(fd, mode) == 0;
if (success && data) {
data->entryFlags &= ~QFileSystemMetaData::Permissions;
- data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
+ data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions.toInt()));
data->knownFlagsMask |= QFileSystemMetaData::Permissions;
}
if (!success)
@@ -1584,28 +1683,22 @@ bool QFileSystemEngine::setPermissions(int fd, QFile::Permissions permissions, Q
}
//static
-bool QFileSystemEngine::setFileTime(int fd, const QDateTime &newDate, QAbstractFileEngine::FileTime time, QSystemError &error)
+bool QFileSystemEngine::setFileTime(int fd, const QDateTime &newDate, QFile::FileTime time, QSystemError &error)
{
- if (!newDate.isValid() || time == QAbstractFileEngine::BirthTime ||
- time == QAbstractFileEngine::MetadataChangeTime) {
+ if (!newDate.isValid()
+ || time == QFile::FileBirthTime || time == QFile::FileMetadataChangeTime) {
error = QSystemError(EINVAL, QSystemError::StandardLibraryError);
return false;
}
#if QT_CONFIG(futimens)
- struct timespec ts[2];
-
- ts[0].tv_sec = ts[1].tv_sec = 0;
- ts[0].tv_nsec = ts[1].tv_nsec = UTIME_OMIT;
-
- const qint64 msecs = newDate.toMSecsSinceEpoch();
+ // UTIME_OMIT: leave file timestamp unchanged
+ struct timespec ts[2] = {{0, UTIME_OMIT}, {0, UTIME_OMIT}};
- if (time == QAbstractFileEngine::AccessTime) {
- ts[0].tv_sec = msecs / 1000;
- ts[0].tv_nsec = (msecs % 1000) * 1000000;
- } else if (time == QAbstractFileEngine::ModificationTime) {
- ts[1].tv_sec = msecs / 1000;
- ts[1].tv_nsec = (msecs % 1000) * 1000000;
+ if (time == QFile::FileAccessTime || time == QFile::FileModificationTime) {
+ const int idx = time == QFile::FileAccessTime ? 0 : 1;
+ const std::chrono::milliseconds msecs{newDate.toMSecsSinceEpoch()};
+ ts[idx] = durationToTimespec(msecs);
}
if (futimens(fd, ts) == -1) {
@@ -1614,33 +1707,6 @@ bool QFileSystemEngine::setFileTime(int fd, const QDateTime &newDate, QAbstractF
}
return true;
-#elif QT_CONFIG(futimes)
- struct timeval tv[2];
- QT_STATBUF st;
-
- if (QT_FSTAT(fd, &st) == -1) {
- error = QSystemError(errno, QSystemError::StandardLibraryError);
- return false;
- }
-
- GetFileTimes::get(&st, &tv[0], &tv[1]);
-
- const qint64 msecs = newDate.toMSecsSinceEpoch();
-
- if (time == QAbstractFileEngine::AccessTime) {
- tv[0].tv_sec = msecs / 1000;
- tv[0].tv_usec = (msecs % 1000) * 1000;
- } else if (time == QAbstractFileEngine::ModificationTime) {
- tv[1].tv_sec = msecs / 1000;
- tv[1].tv_usec = (msecs % 1000) * 1000;
- }
-
- if (futimes(fd, tv) == -1) {
- error = QSystemError(errno, QSystemError::StandardLibraryError);
- return false;
- }
-
- return true;
#else
Q_UNUSED(fd);
error = QSystemError(ENOSYS, QSystemError::StandardLibraryError);
@@ -1658,13 +1724,13 @@ QString QFileSystemEngine::homePath()
QString QFileSystemEngine::rootPath()
{
- return QLatin1String("/");
+ return u"/"_s;
}
QString QFileSystemEngine::tempPath()
{
#ifdef QT_UNIX_TEMP_PATH_OVERRIDE
- return QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE);
+ return QT_UNIX_TEMP_PATH_OVERRIDE ""_L1;
#else
QString temp = QFile::decodeName(qgetenv("TMPDIR"));
if (temp.isEmpty()) {
@@ -1674,7 +1740,7 @@ QString QFileSystemEngine::tempPath()
temp = QString::fromCFString((CFStringRef)nsPath);
#endif
} else {
- temp = QLatin1String(_PATH_TMP);
+ temp = _PATH_TMP ""_L1;
}
}
return QDir(QDir::cleanPath(temp)).canonicalPath();
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index e91a7558d7..3ec32e31a1 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemengine_p.h"
#include "qoperatingsystemversion.h"
@@ -43,6 +7,7 @@
#include "qsysinfo.h"
#include "qscopeguard.h"
#include "private/qabstractfileengine_p.h"
+#include "private/qfiledevice_p.h"
#include "private/qfsfileengine_p.h"
#include <private/qsystemlibrary_p.h>
#include <qdebug.h>
@@ -55,6 +20,7 @@
#if QT_CONFIG(regularexpression)
#include "qregularexpression.h"
#endif
+#include "qstring.h"
#include <sys/types.h>
#include <direct.h>
@@ -71,6 +37,8 @@
#define SECURITY_WIN32
#include <security.h>
+#include <QtCore/private/qfunctions_win_p.h>
+
#ifndef SPI_GETPLATFORMTYPE
#define SPI_GETPLATFORMTYPE 257
#endif
@@ -132,26 +100,24 @@ typedef struct _REPARSE_DATA_BUFFER {
# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
#ifndef FSCTL_GET_REPARSE_POINT
-# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
+# define FSCTL_GET_REPARSE_POINT \
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
-#if defined(QT_BOOTSTRAPPED)
-# define QT_FEATURE_fslibs -1
-#else
-# define QT_FEATURE_fslibs 1
-#endif // QT_BOOTSTRAPPED
-
#if QT_CONFIG(fslibs)
#include <aclapi.h>
+#include <authz.h>
#include <userenv.h>
-static TRUSTEE_W currentUserTrusteeW;
-static TRUSTEE_W worldTrusteeW;
-static PSID currentUserSID = 0;
-static PSID worldSID = 0;
+static PSID currentUserSID = nullptr;
+static PSID currentGroupSID = nullptr;
+static PSID worldSID = nullptr;
static HANDLE currentUserImpersonatedToken = nullptr;
+#endif // fslibs
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+#if QT_CONFIG(fslibs)
namespace {
struct GlobalSid
{
@@ -162,12 +128,15 @@ struct GlobalSid
GlobalSid::~GlobalSid()
{
free(currentUserSID);
- currentUserSID = 0;
+ currentUserSID = nullptr;
+
+ free(currentGroupSID);
+ currentGroupSID = nullptr;
// worldSID was allocated with AllocateAndInitializeSid so it needs to be freed with FreeSid
if (worldSID) {
::FreeSid(worldSID);
- worldSID = 0;
+ worldSID = nullptr;
}
if (currentUserImpersonatedToken) {
@@ -176,62 +145,464 @@ GlobalSid::~GlobalSid()
}
}
-GlobalSid::GlobalSid()
+/*
+ Helper for GetTokenInformation that allocates chunk of memory to hold the requested information.
+
+ The memory size is determined by doing a dummy call first. The returned memory should be
+ freed by calling free().
+*/
+template<typename T>
+static T *getTokenInfo(HANDLE token, TOKEN_INFORMATION_CLASS infoClass)
{
- {
- {
- // Create TRUSTEE for current user
- HANDLE hnd = ::GetCurrentProcess();
- HANDLE token = 0;
- if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
- DWORD retsize = 0;
- // GetTokenInformation requires a buffer big enough for the TOKEN_USER struct and
- // the SID struct. Since the SID struct can have variable number of subauthorities
- // tacked at the end, its size is variable. Obtain the required size by first
- // doing a dummy GetTokenInformation call.
- ::GetTokenInformation(token, TokenUser, 0, 0, &retsize);
- if (retsize) {
- void *tokenBuffer = malloc(retsize);
- Q_CHECK_PTR(tokenBuffer);
- if (::GetTokenInformation(token, TokenUser, tokenBuffer, retsize, &retsize)) {
- PSID tokenSid = reinterpret_cast<PTOKEN_USER>(tokenBuffer)->User.Sid;
- DWORD sidLen = ::GetLengthSid(tokenSid);
- currentUserSID = reinterpret_cast<PSID>(malloc(sidLen));
- Q_CHECK_PTR(currentUserSID);
- if (::CopySid(sidLen, currentUserSID, tokenSid))
- BuildTrusteeWithSid(&currentUserTrusteeW, currentUserSID);
- }
- free(tokenBuffer);
- }
- ::CloseHandle(token);
- }
+ DWORD retsize = 0;
+ GetTokenInformation(token, infoClass, nullptr, 0, &retsize);
+ if (retsize) {
+ void *tokenBuffer = malloc(retsize);
+ if (::GetTokenInformation(token, infoClass, tokenBuffer, retsize, &retsize))
+ return reinterpret_cast<T *>(tokenBuffer);
+ else
+ free(tokenBuffer);
+ }
+ return nullptr;
+}
- token = nullptr;
- if (::OpenProcessToken(hnd, TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &token)) {
- ::DuplicateToken(token, SecurityImpersonation, &currentUserImpersonatedToken);
- ::CloseHandle(token);
- }
+/*
+ Takes a copy of the original SID and stores it into dstSid.
+ The copy can be destroyed using free().
+*/
+static void copySID(PSID &dstSid, PSID srcSid)
+{
+ DWORD sidLen = GetLengthSid(srcSid);
+ dstSid = reinterpret_cast<PSID>(malloc(sidLen));
+ Q_CHECK_PTR(dstSid);
+ CopySid(sidLen, dstSid, srcSid);
+}
- {
- // Create TRUSTEE for Everyone (World)
- SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY };
- if (AllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID))
- BuildTrusteeWithSid(&worldTrusteeW, worldSID);
- }
+GlobalSid::GlobalSid()
+{
+ HANDLE hnd = ::GetCurrentProcess();
+ HANDLE token = nullptr;
+ if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
+ // Create SID for current user
+ if (auto info = getTokenInfo<TOKEN_USER>(token, TokenUser)) {
+ copySID(currentUserSID, info->User.Sid);
+ free(info);
}
+
+ // Create SID for the current user's primary group.
+ if (auto info = getTokenInfo<TOKEN_GROUPS>(token, TokenGroups)) {
+ copySID(currentGroupSID, info->Groups[0].Sid);
+ free(info);
+ }
+ ::CloseHandle(token);
+ }
+
+ token = nullptr;
+ if (::OpenProcessToken(hnd,
+ TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ,
+ &token)) {
+ ::DuplicateToken(token, SecurityImpersonation, &currentUserImpersonatedToken);
+ ::CloseHandle(token);
}
+
+ // Create SID for Everyone (World)
+ SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY };
+ AllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID);
}
Q_GLOBAL_STATIC(GlobalSid, initGlobalSid)
-QT_END_NAMESPACE
+/*!
+ \class QAuthzResourceManager
+ \internal
+
+ RAII wrapper around Windows Authz resource manager.
+*/
+class QAuthzResourceManager
+{
+public:
+ QAuthzResourceManager();
+ ~QAuthzResourceManager();
+
+ bool isValid() const { return resourceManager != nullptr; }
+
+private:
+ friend class QAuthzClientContext;
+ Q_DISABLE_COPY_MOVE(QAuthzResourceManager)
+
+ AUTHZ_RESOURCE_MANAGER_HANDLE resourceManager;
+};
+
+/*!
+ \class QAuthzClientContext
+ \internal
+
+ RAII wrapper around Windows Authz client context.
+*/
+class QAuthzClientContext
+{
+public:
+ // Tag to differentiate SID and TOKEN constructors. Those two types are pointers to void.
+ struct TokenTag
+ {
+ };
+
+ QAuthzClientContext(const QAuthzResourceManager &rm, PSID pSID);
+ QAuthzClientContext(const QAuthzResourceManager &rm, HANDLE tokenHandle, TokenTag);
+
+ ~QAuthzClientContext();
+
+ bool isValid() const { return context != nullptr; }
+
+ static constexpr ACCESS_MASK InvalidAccess = ~ACCESS_MASK(0);
+
+ ACCESS_MASK accessMask(PSECURITY_DESCRIPTOR pSD) const;
+
+private:
+ Q_DISABLE_COPY_MOVE(QAuthzClientContext)
+ AUTHZ_CLIENT_CONTEXT_HANDLE context = nullptr;
+};
+
+QAuthzResourceManager::QAuthzResourceManager()
+{
+ if (!AuthzInitializeResourceManager(AUTHZ_RM_FLAG_NO_AUDIT, nullptr, nullptr, nullptr, nullptr,
+ &resourceManager)) {
+ resourceManager = nullptr;
+ }
+}
+
+QAuthzResourceManager::~QAuthzResourceManager()
+{
+ if (resourceManager)
+ AuthzFreeResourceManager(resourceManager);
+}
+
+/*!
+ \internal
+
+ Create an Authz client context from a security identifier.
+
+ The created context will not include any group information associated with \a pSID.
+*/
+QAuthzClientContext::QAuthzClientContext(const QAuthzResourceManager &rm, PSID pSID)
+{
+ if (!rm.isValid())
+ return;
+
+ LUID unusedId = {};
+
+ if (!AuthzInitializeContextFromSid(AUTHZ_SKIP_TOKEN_GROUPS, pSID, rm.resourceManager, nullptr,
+ unusedId, nullptr, &context)) {
+ context = nullptr;
+ }
+}
+
+/*!
+ \internal
+
+ Create an Authz client context from a token handle.
+*/
+QAuthzClientContext::QAuthzClientContext(const QAuthzResourceManager &rm, HANDLE tokenHandle,
+ TokenTag)
+{
+ if (!rm.isValid())
+ return;
+
+ LUID unusedId = {};
+
+ if (!AuthzInitializeContextFromToken(0, tokenHandle, rm.resourceManager, nullptr, unusedId,
+ nullptr, &context)) {
+ context = nullptr;
+ }
+}
+
+QAuthzClientContext::~QAuthzClientContext()
+{
+ if (context)
+ AuthzFreeContext(context);
+}
+
+/*!
+ \internal
+
+ Returns permissions that are granted to this client by \a pSD.
+
+ Returns \c InvalidAccess in case of an error.
+*/
+ACCESS_MASK QAuthzClientContext::accessMask(PSECURITY_DESCRIPTOR pSD) const
+{
+ if (!isValid())
+ return InvalidAccess;
+
+ AUTHZ_ACCESS_REQUEST accessRequest = {};
+ AUTHZ_ACCESS_REPLY accessReply = {};
+ ACCESS_MASK accessMask = 0;
+ DWORD error = 0;
+
+ accessRequest.DesiredAccess = MAXIMUM_ALLOWED;
+
+ accessReply.ResultListLength = 1;
+ accessReply.GrantedAccessMask = &accessMask;
+ accessReply.Error = &error;
+
+ if (!AuthzAccessCheck(0, context, &accessRequest, nullptr, pSD, nullptr, 0, &accessReply,
+ nullptr)
+ || error != 0) {
+ return InvalidAccess;
+ }
+
+ return accessMask;
+}
+
+enum NonSpecificPermission {
+ ReadPermission = 0x4,
+ WritePermission = 0x2,
+ ExePermission = 0x1,
+ AllPermissions = ReadPermission | WritePermission | ExePermission
+};
+Q_DECLARE_FLAGS(NonSpecificPermissions, NonSpecificPermission)
+Q_DECLARE_OPERATORS_FOR_FLAGS(NonSpecificPermissions)
+
+enum PermissionTag { OtherTag = 0, GroupTag = 4, UserTag = 8, OwnerTag = 12 };
+
+constexpr NonSpecificPermissions toNonSpecificPermissions(PermissionTag tag,
+ QFileDevice::Permissions permissions)
+{
+ return NonSpecificPermissions::fromInt((permissions.toInt() >> int(tag)) & 0x7);
+}
+
+[[maybe_unused]] // Not currently used; included to show how to do it (without bit-rotting).
+constexpr QFileDevice::Permissions toSpecificPermissions(PermissionTag tag,
+ NonSpecificPermissions permissions)
+{
+ return QFileDevice::Permissions::fromInt(permissions.toInt() << int(tag));
+}
} // anonymous namespace
#endif // QT_CONFIG(fslibs)
-QT_BEGIN_NAMESPACE
+#if QT_DEPRECATED_SINCE(6,6)
+int qt_ntfs_permission_lookup = 0;
+#endif
+
+static QBasicAtomicInt qt_ntfs_permission_lookup_v2 = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+
+bool qEnableNtfsPermissionChecks() noexcept
+{
+ return qt_ntfs_permission_lookup_v2.fetchAndAddRelaxed(1)
+QT_IF_DEPRECATED_SINCE(6, 6, /*nothing*/, + qt_ntfs_permission_lookup)
+ != 0;
+}
+
+bool qDisableNtfsPermissionChecks() noexcept
+{
+ return qt_ntfs_permission_lookup_v2.fetchAndSubRelaxed(1)
+QT_IF_DEPRECATED_SINCE(6, 6, /*nothing*/, + qt_ntfs_permission_lookup)
+ == 1;
+}
+
+bool qAreNtfsPermissionChecksEnabled() noexcept
+{
+ return qt_ntfs_permission_lookup_v2.loadRelaxed()
+QT_IF_DEPRECATED_SINCE(6, 6, /*nothing*/, + qt_ntfs_permission_lookup)
+ ;
+}
+QT_WARNING_POP
+
+/*!
+ \class QNativeFilePermissions
+ \internal
+
+ This class can be used to produce a security descriptor that contains ACL that produces
+ result similar to what is expected for POSIX permission corresponding to the supplied
+ \c QFileDevice::Permissions value. When supplied optional value is empty, a null
+ security descriptor is produced. Files or directories with such null security descriptor
+ will inherit ACLs from parent directories. Otherwise an ACL is generated and applied to
+ the security descriptor. The created ACL has permission bits set similar to what Cygwin
+ does. Unlike Cygwin, this code tries to reorder the access control entries (ACE) inside
+ the ACL to match the canonical ordering (deny ACEs followed by allow ACEs) if possible.
+
+ The default ordering of ACEs is as follows:
+
+ * User deny ACE, only lists permission that may be granted by the subsequent Group and
+ Other allow ACEs.
+ * User allow ACE.
+ * Group deny ACE, only lists permissions that may be granted by the subsequent Other
+ allow ACE.
+ * Group allow ACE.
+ * Other allow ACE.
+
+ Any ACEs that would have zero mask are skipped. Group deny ACE may be moved to before
+ User allow ACE if these 2 ACEs don't have any common mask bits set. This allows use of
+ canonical ordering in more cases. ACLs for permissions with group having less permissions
+ than both user and others (ex.: 0757) are still in noncanonical order. Files with
+ noncanonical ACLs generate warnings when one tries to edit permissions with Windows GUI,
+ and don't work correctly with API like GetEffectiveRightsFromAcl(), but otherwise access
+ checks work fine and such ACLs can still be edited with the "Advanced" GUI.
+*/
+QNativeFilePermissions::QNativeFilePermissions(std::optional<QFileDevice::Permissions> perms,
+ bool isDir)
+{
+#if QT_CONFIG(fslibs)
+ if (!perms) {
+ ok = true;
+ return;
+ }
+
+ initGlobalSid();
+
+ const auto permissions = *perms;
+
+ PACL acl = reinterpret_cast<PACL>(aclStorage);
+
+ if (!InitializeAcl(acl, sizeof(aclStorage), ACL_REVISION))
+ return;
+
+ struct Masks
+ {
+ ACCESS_MASK denyMask, allowMask;
+ };
+
+ auto makeMasks = [isDir](NonSpecificPermissions allowPermissions,
+ NonSpecificPermissions denyPermissions, bool owner) {
+ constexpr ACCESS_MASK AllowRead = FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA;
+ constexpr ACCESS_MASK DenyRead = FILE_READ_DATA | FILE_READ_EA;
+
+ constexpr ACCESS_MASK AllowWrite =
+ FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA;
+ constexpr ACCESS_MASK DenyWrite = AllowWrite | FILE_DELETE_CHILD;
+ constexpr ACCESS_MASK DenyWriteOwner =
+ FILE_WRITE_DATA | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD;
+
+ constexpr ACCESS_MASK AllowExe = FILE_EXECUTE;
+ constexpr ACCESS_MASK DenyExe = AllowExe;
+
+ constexpr ACCESS_MASK StdRightsOther =
+ STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | SYNCHRONIZE;
+ constexpr ACCESS_MASK StdRightsOwner =
+ STANDARD_RIGHTS_ALL | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE;
+
+ ACCESS_MASK allow = owner ? StdRightsOwner : StdRightsOther;
+ ACCESS_MASK deny = 0;
+
+ if (denyPermissions & ReadPermission)
+ deny |= DenyRead;
+
+ if (denyPermissions & WritePermission)
+ deny |= owner ? DenyWriteOwner : DenyWrite;
-Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0;
+ if (denyPermissions & ExePermission)
+ deny |= DenyExe;
+
+ if (allowPermissions & ReadPermission)
+ allow |= AllowRead;
+
+ if (allowPermissions & WritePermission)
+ allow |= AllowWrite;
+
+ if (allowPermissions & ExePermission)
+ allow |= AllowExe;
+
+ // Give the owner "full access" if all the permissions are allowed
+ if (owner && allowPermissions == AllPermissions)
+ allow |= FILE_DELETE_CHILD;
+
+ if (isDir
+ && (allowPermissions & (WritePermission | ExePermission))
+ == (WritePermission | ExePermission)) {
+ allow |= FILE_DELETE_CHILD;
+ }
+
+ return Masks { deny, allow };
+ };
+
+ auto userPermissions = toNonSpecificPermissions(OwnerTag, permissions)
+ | toNonSpecificPermissions(UserTag, permissions);
+ auto groupPermissions = toNonSpecificPermissions(GroupTag, permissions);
+ auto otherPermissions = toNonSpecificPermissions(OtherTag, permissions);
+
+ auto userMasks = makeMasks(userPermissions,
+ ~userPermissions & (groupPermissions | otherPermissions), true);
+ auto groupMasks = makeMasks(groupPermissions, ~groupPermissions & otherPermissions, false);
+ auto otherMasks = makeMasks(otherPermissions, {}, false);
+
+ const DWORD aceFlags = isDir ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0;
+ const bool reorderGroupDeny = (groupMasks.denyMask & userMasks.allowMask) == 0;
+
+ const auto addDenyAce = [acl, aceFlags](const Masks &masks, PSID pSID) {
+ if (masks.denyMask)
+ return AddAccessDeniedAceEx(acl, ACL_REVISION, aceFlags, masks.denyMask, pSID);
+ return TRUE;
+ };
+
+ const auto addAllowAce = [acl, aceFlags](const Masks &masks, PSID pSID) {
+ if (masks.allowMask)
+ return AddAccessAllowedAceEx(acl, ACL_REVISION, aceFlags, masks.allowMask, pSID);
+ return TRUE;
+ };
+
+ if (!addDenyAce(userMasks, currentUserSID))
+ return;
+
+ if (reorderGroupDeny) {
+ if (!addDenyAce(groupMasks, currentGroupSID))
+ return;
+ }
+
+ if (!addAllowAce(userMasks, currentUserSID))
+ return;
+
+ if (!reorderGroupDeny) {
+ if (!addDenyAce(groupMasks, currentGroupSID))
+ return;
+ }
+
+ if (!addAllowAce(groupMasks, currentGroupSID))
+ return;
+
+ if (!addAllowAce(otherMasks, worldSID))
+ return;
+
+ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+ return;
+
+ if (!SetSecurityDescriptorOwner(&sd, currentUserSID, FALSE))
+ return;
+
+ if (!SetSecurityDescriptorGroup(&sd, currentGroupSID, FALSE))
+ return;
+
+ if (!SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE))
+ return;
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = FALSE;
+
+ isNull = false;
+#else
+ Q_UNUSED(perms);
+ Q_UNUSED(isDir);
+#endif // QT_CONFIG(fslibs)
+ ok = true;
+}
+
+/*!
+ \internal
+ Return pointer to a \c SECURITY_ATTRIBUTES object describing the permissions.
+
+ The returned pointer many be null if default permissions were requested or
+ during bootstrap. The callers must call \c isOk() to check if the object
+ was successfully constructed before using this method.
+*/
+SECURITY_ATTRIBUTES *QNativeFilePermissions::securityAttributes()
+{
+ Q_ASSERT(ok);
+ return isNull ? nullptr : &sa;
+}
static inline bool toFileTime(const QDateTime &date, FILETIME *fileTime)
{
@@ -250,7 +621,7 @@ static inline bool toFileTime(const QDateTime &date, FILETIME *fileTime)
lTime.wMilliseconds = t.msec();
lTime.wDayOfWeek = d.dayOfWeek() % 7;
- if (!::TzSpecificLocalTimeToSystemTime(0, &lTime, &sTime))
+ if (!::TzSpecificLocalTimeToSystemTime(nullptr, &lTime, &sTime))
return false;
} else {
QDateTime utcDate = date.toUTC();
@@ -273,19 +644,17 @@ static inline bool toFileTime(const QDateTime &date, FILETIME *fileTime)
static QString readSymLink(const QFileSystemEntry &link)
{
QString result;
- HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(),
- FILE_READ_EA,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0,
+ HANDLE handle = CreateFile((wchar_t *)link.nativeFilePath().utf16(), FILE_READ_EA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
- 0);
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
if (handle != INVALID_HANDLE_VALUE) {
DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)malloc(bufsize);
Q_CHECK_PTR(rdb);
DWORD retsize = 0;
- if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) {
+ if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, nullptr, 0, rdb, bufsize, &retsize,
+ nullptr)) {
if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
@@ -297,33 +666,27 @@ static QString readSymLink(const QFileSystemEntry &link)
const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
result = QString::fromWCharArray(PathBuffer, length);
}
- // cut-off "\\?\" and "\??\"
- if (result.size() > 4
- && result.at(0) == QLatin1Char('\\')
- && result.at(2) == QLatin1Char('?')
- && result.at(3) == QLatin1Char('\\')) {
- result = result.mid(4);
- // cut off UNC in addition when the link points at a UNC share
- // in which case we need to prepend another backslash to get \\server\share
- if (QStringView{result}.left(3) == QLatin1String("UNC")) {
- result.replace(0, 3, QLatin1Char('\\'));
- }
- }
+ // remove "\\?\", "\??\" or "\\?\UNC\"
+ result = QFileSystemEntry::removeUncOrLongPathPrefix(result);
}
free(rdb);
CloseHandle(handle);
#if QT_CONFIG(fslibs) && QT_CONFIG(regularexpression)
initGlobalSid();
- QRegularExpression matchVolumeRe(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), QRegularExpression::CaseInsensitiveOption);
+ QRegularExpression matchVolumeRe("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"_L1,
+ QRegularExpression::CaseInsensitiveOption);
auto matchVolume = matchVolumeRe.match(result);
if (matchVolume.hasMatch()) {
Q_ASSERT(matchVolume.capturedStart() == 0);
DWORD len;
wchar_t buffer[MAX_PATH];
- const QString volumeName = QLatin1String("\\\\?\\") + matchVolume.captured();
- if (GetVolumePathNamesForVolumeName(reinterpret_cast<LPCWSTR>(volumeName.utf16()), buffer, MAX_PATH, &len) != 0)
+ const QString volumeName = "\\\\?\\"_L1 + matchVolume.captured();
+ if (GetVolumePathNamesForVolumeName(reinterpret_cast<LPCWSTR>(volumeName.utf16()),
+ buffer, MAX_PATH, &len)
+ != 0) {
result.replace(0, matchVolume.capturedLength(), QString::fromWCharArray(buffer));
+ }
}
#endif // QT_CONFIG(fslibs)
}
@@ -335,20 +698,16 @@ static QString readLink(const QFileSystemEntry &link)
#if QT_CONFIG(fslibs)
QString ret;
- bool neededCoInit = false;
IShellLink *psl; // pointer to IShellLink i/f
WIN32_FIND_DATA wfd;
wchar_t szGotPath[MAX_PATH];
+ QComHelper comHelper;
+
// Get pointer to the IShellLink interface.
- HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl);
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
+ (LPVOID *)&psl);
- if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
- neededCoInit = true;
- CoInitialize(NULL);
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLink, (LPVOID *)&psl);
- }
if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
IPersistFile *ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
@@ -364,8 +723,6 @@ static QString readLink(const QFileSystemEntry &link)
}
psl->Release();
}
- if (neededCoInit)
- CoUninitialize();
return ret;
#else
@@ -377,11 +734,12 @@ static QString readLink(const QFileSystemEntry &link)
static bool uncShareExists(const QString &server)
{
// This code assumes the UNC path is always like \\?\UNC\server...
- const auto parts = QStringView{server}.split(QLatin1Char('\\'), Qt::SkipEmptyParts);
+ const auto parts = QStringView{server}.split(u'\\', Qt::SkipEmptyParts);
if (parts.count() >= 3) {
QStringList shares;
- if (QFileSystemEngine::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(2), &shares))
- return parts.count() < 4 || shares.contains(parts.at(3).toString(), Qt::CaseInsensitive);
+ if (QFileSystemEngine::uncListSharesOnServer("\\\\"_L1 + parts.at(2), &shares))
+ return parts.count() < 4
+ || shares.contains(parts.at(3).toString(), Qt::CaseInsensitive);
}
return false;
}
@@ -389,11 +747,11 @@ static bool uncShareExists(const QString &server)
static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
{
// path should not end with a trailing slash
- while (path.endsWith(QLatin1Char('\\')))
+ while (path.endsWith(u'\\'))
path.chop(1);
// can't handle drives
- if (!path.endsWith(QLatin1Char(':'))) {
+ if (!path.endsWith(u':')) {
HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData);
if (hFind != INVALID_HANDLE_VALUE) {
::FindClose(hFind);
@@ -404,7 +762,6 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
return false;
}
-#if defined(__IFileOperation_INTERFACE_DEFINED__)
class FileOperationProgressSink : public IFileOperationProgressSink
{
public:
@@ -413,11 +770,8 @@ public:
{}
virtual ~FileOperationProgressSink() {}
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return ++ref;
- }
- ULONG STDMETHODCALLTYPE Release()
+ ULONG STDMETHODCALLTYPE AddRef() override { return ++ref; }
+ ULONG STDMETHODCALLTYPE Release() override
{
if (--ref == 0) {
delete this;
@@ -425,7 +779,7 @@ public:
}
return ref;
}
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override
{
if (!ppvObject)
return E_POINTER;
@@ -446,32 +800,32 @@ public:
return E_NOINTERFACE;
}
- HRESULT STDMETHODCALLTYPE StartOperations()
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT)
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE PreRenameItem(DWORD, IShellItem *, LPCWSTR)
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE PostRenameItem(DWORD, IShellItem *, LPCWSTR, HRESULT, IShellItem *)
+ HRESULT STDMETHODCALLTYPE StartOperations() override { return S_OK; }
+ HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT) override { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PreRenameItem(DWORD, IShellItem *, LPCWSTR) override { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PostRenameItem(DWORD, IShellItem *, LPCWSTR, HRESULT,
+ IShellItem *) override
{ return S_OK; }
- HRESULT STDMETHODCALLTYPE PreMoveItem(DWORD, IShellItem *, IShellItem *, LPCWSTR)
+ HRESULT STDMETHODCALLTYPE PreMoveItem(DWORD, IShellItem *, IShellItem *, LPCWSTR) override
{ return S_OK; }
HRESULT STDMETHODCALLTYPE PostMoveItem(DWORD, IShellItem *, IShellItem *, LPCWSTR, HRESULT,
- IShellItem *)
+ IShellItem *) override
{ return S_OK; }
- HRESULT STDMETHODCALLTYPE PreCopyItem(DWORD, IShellItem *, IShellItem *, LPCWSTR )
+ HRESULT STDMETHODCALLTYPE PreCopyItem(DWORD, IShellItem *, IShellItem *, LPCWSTR) override
{ return S_OK; }
HRESULT STDMETHODCALLTYPE PostCopyItem(DWORD, IShellItem *, IShellItem *, LPCWSTR, HRESULT,
- IShellItem *)
+ IShellItem *) override
{ return S_OK; }
- HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD dwFlags, IShellItem *)
+ HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD dwFlags, IShellItem *) override
{
// stop the operation if the file will be deleted rather than trashed
return (dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE) ? S_OK : E_FAIL;
}
HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD /* dwFlags */, IShellItem * /* psiItem */,
- HRESULT /* hrDelete */, IShellItem *psiNewlyCreated)
+ HRESULT hrDelete,
+ IShellItem *psiNewlyCreated) override
{
+ deleteResult = hrDelete;
if (psiNewlyCreated) {
wchar_t *pszName = nullptr;
psiNewlyCreated->GetDisplayName(SIGDN_FILESYSPATH, &pszName);
@@ -482,25 +836,20 @@ public:
}
return S_OK;
}
- HRESULT STDMETHODCALLTYPE PreNewItem(DWORD, IShellItem *, LPCWSTR)
- { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PreNewItem(DWORD, IShellItem *, LPCWSTR) override { return S_OK; }
HRESULT STDMETHODCALLTYPE PostNewItem(DWORD, IShellItem *, LPCWSTR, LPCWSTR, DWORD, HRESULT,
- IShellItem *)
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE UpdateProgress(UINT,UINT)
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE ResetTimer()
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE PauseTimer()
- { return S_OK; }
- HRESULT STDMETHODCALLTYPE ResumeTimer()
+ IShellItem *) override
{ return S_OK; }
+ HRESULT STDMETHODCALLTYPE UpdateProgress(UINT, UINT) override { return S_OK; }
+ HRESULT STDMETHODCALLTYPE ResetTimer() override { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PauseTimer() override { return S_OK; }
+ HRESULT STDMETHODCALLTYPE ResumeTimer() override { return S_OK; }
QString targetPath;
+ HRESULT deleteResult = S_OK;
private:
ULONG ref;
};
-#endif
bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList *list)
{
@@ -508,7 +857,8 @@ bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList
SHARE_INFO_1 *BufPtr, *p;
DWORD er = 0, tr = 0, resume = 0, i;
do {
- res = NetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
+ res = NetShareEnum((wchar_t *)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr,
+ &resume);
if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
p = BufPtr;
for (i = 1; i <= er; ++i) {
@@ -536,6 +886,18 @@ void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data)
QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
QFileSystemMetaData &data)
{
+ QFileSystemEntry ret = getRawLinkPath(link, data);
+ if (!ret.isEmpty() && ret.isRelative()) {
+ QString target = absoluteName(link).path() + u'/' + ret.filePath();
+ ret = QFileSystemEntry(QDir::cleanPath(target));
+ }
+ return ret;
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::getRawLinkPath(const QFileSystemEntry &link,
+ QFileSystemMetaData &data)
+{
Q_CHECK_FILE_NAME(link, link);
if (data.missingFlags(QFileSystemMetaData::LinkType))
@@ -546,16 +908,32 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
target = readLink(link);
else if (data.isLink())
target = readSymLink(link);
+ return QFileSystemEntry(target);
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::junctionTarget(const QFileSystemEntry &link,
+ QFileSystemMetaData &data)
+{
+ Q_CHECK_FILE_NAME(link, link);
+
+ if (data.missingFlags(QFileSystemMetaData::JunctionType))
+ QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType);
+
+ QString target;
+ if (data.isJunction())
+ target = readSymLink(link);
QFileSystemEntry ret(target);
if (!target.isEmpty() && ret.isRelative()) {
- target.prepend(absoluteName(link).path() + QLatin1Char('/'));
+ target.prepend(absoluteName(link).path() + u'/');
ret = QFileSystemEntry(QDir::cleanPath(target));
}
return ret;
}
//static
-QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
+QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
+ QFileSystemMetaData &data)
{
Q_CHECK_FILE_NAME(entry, entry);
@@ -576,7 +954,7 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
// can be //server or //server/share
QString absPath;
QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1));
- wchar_t *fileName = 0;
+ wchar_t *fileName = nullptr;
DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
if (retLen > (DWORD)buf.size()) {
buf.resize(retLen);
@@ -590,8 +968,8 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
// (which is an invalid filename) this function will strip the space off and viola,
// the file is later reported as existing. Therefore, we re-add the whitespace that
// was at the end of path in order to keep the filename invalid.
- if (!path.isEmpty() && path.at(path.size() - 1) == QLatin1Char(' '))
- absPath.append(QLatin1Char(' '));
+ if (!path.isEmpty() && path.at(path.size() - 1) == u' ')
+ absPath.append(u' ');
return absPath;
}
@@ -608,17 +986,17 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
else
ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(entry.filePath()));
} else {
- ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath());
+ ret = QDir::cleanPath(QDir::currentPath() + u'/' + entry.filePath());
}
// The path should be absolute at this point.
// From the docs :
// Absolute paths begin with the directory separator "/"
// (optionally preceded by a drive specification under Windows).
- if (ret.at(0) != QLatin1Char('/')) {
+ if (ret.at(0) != u'/') {
Q_ASSERT(ret.length() >= 2);
Q_ASSERT(ret.at(0).isLetter());
- Q_ASSERT(ret.at(1) == QLatin1Char(':'));
+ Q_ASSERT(ret.at(1) == u':');
// Force uppercase drive letters.
ret[0] = ret.at(0).toUpper();
@@ -626,15 +1004,6 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath());
}
-#if defined(Q_CC_MINGW) && WINVER < 0x0602 // Windows 8 onwards
-
-typedef struct _FILE_ID_INFO {
- ULONGLONG VolumeSerialNumber;
- FILE_ID_128 FileId;
-} FILE_ID_INFO, *PFILE_ID_INFO;
-
-#endif // if defined (Q_CC_MINGW) && WINVER < 0x0602
-
// File ID for Windows up to version 7 and FAT32 drives
static inline QByteArray fileId(HANDLE handle)
{
@@ -653,21 +1022,25 @@ static inline QByteArray fileId(HANDLE handle)
// File ID for Windows starting from version 8.
QByteArray fileIdWin8(HANDLE handle)
{
-#if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)
+#if !defined(QT_BOOTSTRAPPED)
QByteArray result;
FILE_ID_INFO infoEx;
- if (GetFileInformationByHandleEx(handle,
- static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8
- &infoEx, sizeof(FILE_ID_INFO))) {
+ if (GetFileInformationByHandleEx(
+ handle,
+ static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8
+ &infoEx, sizeof(FILE_ID_INFO))) {
result = QByteArray::number(infoEx.VolumeSerialNumber, 16);
result += ':';
// Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one.
- result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId), int(sizeof(infoEx.FileId))).toHex();
+ result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId),
+ int(sizeof(infoEx.FileId)))
+ .toHex();
} else {
- result = fileId(handle); // GetFileInformationByHandleEx() is observed to fail for FAT32, QTBUG-74759
+ // GetFileInformationByHandleEx() is observed to fail for FAT32, QTBUG-74759
+ result = fileId(handle);
}
return result;
-#else // !QT_BOOTSTRAPPED && !QT_BUILD_QMAKE
+#else // !QT_BOOTSTRAPPED
return fileId(handle);
#endif
}
@@ -679,10 +1052,8 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
QByteArray result;
- const HANDLE handle =
- CreateFile((wchar_t*)entry.nativeFilePath().utf16(), 0,
- FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ const HANDLE handle = CreateFile((wchar_t *)entry.nativeFilePath().utf16(), 0, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (handle != INVALID_HANDLE_VALUE) {
result = id(handle);
CloseHandle(handle);
@@ -693,29 +1064,28 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
//static
QByteArray QFileSystemEngine::id(HANDLE fHandle)
{
- return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
- fileIdWin8(HANDLE(fHandle)) : fileId(HANDLE(fHandle));
+ return fileIdWin8(HANDLE(fHandle));
}
//static
bool QFileSystemEngine::setFileTime(HANDLE fHandle, const QDateTime &newDate,
- QAbstractFileEngine::FileTime time, QSystemError &error)
+ QFile::FileTime time, QSystemError &error)
{
FILETIME fTime;
- FILETIME *pLastWrite = NULL;
- FILETIME *pLastAccess = NULL;
- FILETIME *pCreationTime = NULL;
+ FILETIME *pLastWrite = nullptr;
+ FILETIME *pLastAccess = nullptr;
+ FILETIME *pCreationTime = nullptr;
switch (time) {
- case QAbstractFileEngine::ModificationTime:
+ case QFile::FileModificationTime:
pLastWrite = &fTime;
break;
- case QAbstractFileEngine::AccessTime:
+ case QFile::FileAccessTime:
pLastAccess = &fTime;
break;
- case QAbstractFileEngine::BirthTime:
+ case QFile::FileBirthTime:
pCreationTime = &fTime;
break;
@@ -738,32 +1108,36 @@ QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEng
{
QString name;
#if QT_CONFIG(fslibs)
- extern int qt_ntfs_permission_lookup;
- if (qt_ntfs_permission_lookup > 0) {
+ if (qAreNtfsPermissionChecksEnabled()) {
initGlobalSid();
{
PSID pOwner = 0;
PSECURITY_DESCRIPTOR pSD;
- if (GetNamedSecurityInfo(reinterpret_cast<const wchar_t*>(entry.nativeFilePath().utf16()), SE_FILE_OBJECT,
- own == QAbstractFileEngine::OwnerGroup ? GROUP_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION,
- own == QAbstractFileEngine::OwnerUser ? &pOwner : 0, own == QAbstractFileEngine::OwnerGroup ? &pOwner : 0,
- 0, 0, &pSD) == ERROR_SUCCESS) {
+ if (GetNamedSecurityInfo(
+ reinterpret_cast<const wchar_t *>(entry.nativeFilePath().utf16()),
+ SE_FILE_OBJECT,
+ own == QAbstractFileEngine::OwnerGroup ? GROUP_SECURITY_INFORMATION
+ : OWNER_SECURITY_INFORMATION,
+ own == QAbstractFileEngine::OwnerUser ? &pOwner : nullptr,
+ own == QAbstractFileEngine::OwnerGroup ? &pOwner : nullptr, nullptr,
+ nullptr, &pSD)
+ == ERROR_SUCCESS) {
DWORD lowner = 64;
DWORD ldomain = 64;
QVarLengthArray<wchar_t, 64> owner(lowner);
QVarLengthArray<wchar_t, 64> domain(ldomain);
SID_NAME_USE use = SidTypeUnknown;
// First call, to determine size of the strings (with '\0').
- if (!LookupAccountSid(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
- domain.data(), &ldomain, &use)) {
+ if (!LookupAccountSid(nullptr, pOwner, (LPWSTR)owner.data(), &lowner, domain.data(),
+ &ldomain, &use)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (lowner > (DWORD)owner.size())
owner.resize(lowner);
if (ldomain > (DWORD)domain.size())
domain.resize(ldomain);
// Second call, try on resized buf-s
- if (!LookupAccountSid(NULL, pOwner, owner.data(), &lowner,
- domain.data(), &ldomain, &use)) {
+ if (!LookupAccountSid(nullptr, pOwner, owner.data(), &lowner, domain.data(),
+ &ldomain, &use)) {
lowner = 0;
}
} else {
@@ -788,104 +1162,80 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
QFileSystemMetaData::MetaDataFlags what)
{
#if QT_CONFIG(fslibs)
- if (qt_ntfs_permission_lookup > 0) {
+ if (qAreNtfsPermissionChecksEnabled()) {
initGlobalSid();
- {
- enum { ReadMask = 0x00000001, WriteMask = 0x00000002, ExecMask = 0x00000020 };
- QString fname = entry.nativeFilePath();
- PSID pOwner = 0;
- PSID pGroup = 0;
- PACL pDacl;
- PSECURITY_DESCRIPTOR pSD;
- DWORD res = GetNamedSecurityInfo(reinterpret_cast<const wchar_t*>(fname.utf16()), SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- &pOwner, &pGroup, &pDacl, 0, &pSD);
- if(res == ERROR_SUCCESS) {
- ACCESS_MASK access_mask;
- TRUSTEE_W trustee;
- if (what & QFileSystemMetaData::UserPermissions) { // user
- // Using AccessCheck because GetEffectiveRightsFromAcl doesn't account for elevation
- if (currentUserImpersonatedToken) {
- GENERIC_MAPPING mapping = {FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS};
- PRIVILEGE_SET privileges;
- DWORD grantedAccess;
- BOOL result;
-
- data.knownFlagsMask |= QFileSystemMetaData::UserPermissions;
- DWORD genericAccessRights = GENERIC_READ;
- ::MapGenericMask(&genericAccessRights, &mapping);
-
- DWORD privilegesLength = sizeof(privileges);
- if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights,
- &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) {
- data.entryFlags |= QFileSystemMetaData::UserReadPermission;
- }
+ QString fname = entry.nativeFilePath();
+ PSID pOwner;
+ PSID pGroup;
+ PACL pDacl;
+ PSECURITY_DESCRIPTOR pSD;
+
+ // pDacl is unused directly by the code below, but it is still needed here because
+ // access checks below return incorrect results unless DACL_SECURITY_INFORMATION is
+ // passed to this call.
+ DWORD res = GetNamedSecurityInfo(
+ reinterpret_cast<const wchar_t *>(fname.utf16()), SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ &pOwner, &pGroup, &pDacl, nullptr, &pSD);
+ if (res == ERROR_SUCCESS) {
+ QAuthzResourceManager rm;
+
+ auto addPermissions = [&data](ACCESS_MASK accessMask,
+ QFileSystemMetaData::MetaDataFlag readFlags,
+ QFileSystemMetaData::MetaDataFlag writeFlags,
+ QFileSystemMetaData::MetaDataFlag executeFlags) {
+ // Check for generic permissions and file-specific bits that most closely
+ // represent POSIX permissions.
+
+ // Constants like FILE_GENERIC_{READ,WRITE,EXECUTE} cannot be used
+ // here because they contain permission bits shared between all of them.
+ if (accessMask & (GENERIC_READ | FILE_READ_DATA))
+ data.entryFlags |= readFlags;
+ if (accessMask & (GENERIC_WRITE | FILE_WRITE_DATA))
+ data.entryFlags |= writeFlags;
+ if (accessMask & (GENERIC_EXECUTE | FILE_EXECUTE))
+ data.entryFlags |= executeFlags;
+ };
+
+ if (what & QFileSystemMetaData::UserPermissions && currentUserImpersonatedToken) {
+ data.knownFlagsMask |= QFileSystemMetaData::UserPermissions;
+ QAuthzClientContext context(rm, currentUserImpersonatedToken,
+ QAuthzClientContext::TokenTag {});
+ addPermissions(context.accessMask(pSD),
+ QFileSystemMetaData::UserReadPermission,
+ QFileSystemMetaData::UserWritePermission,
+ QFileSystemMetaData::UserExecutePermission);
+ }
- privilegesLength = sizeof(privileges);
- genericAccessRights = GENERIC_WRITE;
- ::MapGenericMask(&genericAccessRights, &mapping);
- if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights,
- &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) {
- data.entryFlags |= QFileSystemMetaData::UserWritePermission;
- }
+ if (what & QFileSystemMetaData::OwnerPermissions) {
+ data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions;
+ QAuthzClientContext context(rm, pOwner);
+ addPermissions(context.accessMask(pSD),
+ QFileSystemMetaData::OwnerReadPermission,
+ QFileSystemMetaData::OwnerWritePermission,
+ QFileSystemMetaData::OwnerExecutePermission);
+ }
- privilegesLength = sizeof(privileges);
- genericAccessRights = GENERIC_EXECUTE;
- ::MapGenericMask(&genericAccessRights, &mapping);
- if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights,
- &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) {
- data.entryFlags |= QFileSystemMetaData::UserExecutePermission;
- }
- } else { // fallback to GetEffectiveRightsFromAcl
- data.knownFlagsMask |= QFileSystemMetaData::UserPermissions;
- if (GetEffectiveRightsFromAclW(pDacl, &currentUserTrusteeW, &access_mask) != ERROR_SUCCESS)
- access_mask = ACCESS_MASK(-1);
- if (access_mask & ReadMask)
- data.entryFlags |= QFileSystemMetaData::UserReadPermission;
- if (access_mask & WriteMask)
- data.entryFlags|= QFileSystemMetaData::UserWritePermission;
- if (access_mask & ExecMask)
- data.entryFlags|= QFileSystemMetaData::UserExecutePermission;
- }
- }
- if (what & QFileSystemMetaData::OwnerPermissions) { // owner
- data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions;
- BuildTrusteeWithSid(&trustee, pOwner);
- if (GetEffectiveRightsFromAcl(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
- access_mask = (ACCESS_MASK)-1;
- if(access_mask & ReadMask)
- data.entryFlags |= QFileSystemMetaData::OwnerReadPermission;
- if(access_mask & WriteMask)
- data.entryFlags |= QFileSystemMetaData::OwnerWritePermission;
- if(access_mask & ExecMask)
- data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
- }
- if (what & QFileSystemMetaData::GroupPermissions) { // group
- data.knownFlagsMask |= QFileSystemMetaData::GroupPermissions;
- BuildTrusteeWithSid(&trustee, pGroup);
- if (GetEffectiveRightsFromAcl(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
- access_mask = (ACCESS_MASK)-1;
- if(access_mask & ReadMask)
- data.entryFlags |= QFileSystemMetaData::GroupReadPermission;
- if(access_mask & WriteMask)
- data.entryFlags |= QFileSystemMetaData::GroupWritePermission;
- if(access_mask & ExecMask)
- data.entryFlags |= QFileSystemMetaData::GroupExecutePermission;
- }
- if (what & QFileSystemMetaData::OtherPermissions) { // other (world)
- data.knownFlagsMask |= QFileSystemMetaData::OtherPermissions;
- if (GetEffectiveRightsFromAcl(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS)
- access_mask = (ACCESS_MASK)-1; // ###
- if(access_mask & ReadMask)
- data.entryFlags |= QFileSystemMetaData::OtherReadPermission;
- if(access_mask & WriteMask)
- data.entryFlags |= QFileSystemMetaData::OtherWritePermission;
- if(access_mask & ExecMask)
- data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
- }
- LocalFree(pSD);
+ if (what & QFileSystemMetaData::GroupPermissions) {
+ data.knownFlagsMask |= QFileSystemMetaData::GroupPermissions;
+ QAuthzClientContext context(rm, pGroup);
+ addPermissions(context.accessMask(pSD),
+ QFileSystemMetaData::GroupReadPermission,
+ QFileSystemMetaData::GroupWritePermission,
+ QFileSystemMetaData::GroupExecutePermission);
}
+
+ if (what & QFileSystemMetaData::OtherPermissions) {
+ data.knownFlagsMask |= QFileSystemMetaData::OtherPermissions;
+ QAuthzClientContext context(rm, worldSID);
+ addPermissions(context.accessMask(pSD),
+ QFileSystemMetaData::OtherReadPermission,
+ QFileSystemMetaData::OtherWritePermission,
+ QFileSystemMetaData::OtherExecutePermission);
+ }
+
+ LocalFree(pSD);
}
} else
#endif
@@ -905,14 +1255,16 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
QString fname = entry.filePath();
QString ext = fname.right(4).toLower();
- if (data.isDirectory() ||
- ext == QLatin1String(".exe") || ext == QLatin1String(".com") || ext == QLatin1String(".bat") ||
- ext == QLatin1String(".pif") || ext == QLatin1String(".cmd")) {
- data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission | QFileSystemMetaData::GroupExecutePermission
- | QFileSystemMetaData::OtherExecutePermission | QFileSystemMetaData::UserExecutePermission;
+ if (data.isDirectory() || ext == ".exe"_L1 || ext == ".com"_L1
+ || ext == ".bat"_L1 || ext == ".pif"_L1 || ext == ".cmd"_L1) {
+ data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission
+ | QFileSystemMetaData::GroupExecutePermission
+ | QFileSystemMetaData::OtherExecutePermission
+ | QFileSystemMetaData::UserExecutePermission;
}
- data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions | QFileSystemMetaData::GroupPermissions
- | QFileSystemMetaData::OtherPermissions | QFileSystemMetaData::UserExecutePermission;
+ data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions
+ | QFileSystemMetaData::GroupPermissions | QFileSystemMetaData::OtherPermissions
+ | QFileSystemMetaData::UserExecutePermission;
// calculate user permissions
if (what & QFileSystemMetaData::UserReadPermission) {
if (::_waccess((wchar_t*)entry.nativeFilePath().utf16(), R_OK) == 0)
@@ -938,7 +1290,8 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa
const UINT oldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
DWORD drivesBitmask = ::GetLogicalDrives();
::SetErrorMode(oldErrorMode);
- int drivebit = 1 << (fname.filePath().at(0).toUpper().unicode() - QLatin1Char('A').unicode());
+ int drivebit =
+ 1 << (fname.filePath().at(0).toUpper().unicode() - u'A');
if (drivesBitmask & drivebit) {
fileAttrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM;
entryExists = true;
@@ -946,7 +1299,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa
} else {
const QString &path = fname.nativeFilePath();
bool is_dir = false;
- if (path.startsWith(QLatin1String("\\\\?\\UNC"))) {
+ if (path.startsWith("\\\\?\\UNC"_L1)) {
// UNC - stat doesn't work for all cases (Windows bug)
int s = path.indexOf(path.at(0),7);
if (s > 0) {
@@ -1022,8 +1375,6 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
return data.hasFlags(what);
}
-static bool isDirPath(const QString &dirPath, bool *existed);
-
//static
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what)
@@ -1037,7 +1388,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
// Check for ".lnk": Directories named ".lnk" should be skipped, corrupted
// link files should still be detected as links.
const QString origFilePath = entry.filePath();
- if (origFilePath.endsWith(QLatin1String(".lnk")) && !isDirPath(origFilePath, 0)) {
+ if (origFilePath.endsWith(".lnk"_L1) && !isDirPath(origFilePath, nullptr)) {
data.entryFlags |= QFileSystemMetaData::WinLnkType;
fname = QFileSystemEntry(readLink(entry));
} else {
@@ -1056,17 +1407,20 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
WIN32_FIND_DATA findData;
// The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA
// for all members used by fillFindData().
- bool ok = ::GetFileAttributesEx(reinterpret_cast<const wchar_t*>(fname.nativeFilePath().utf16()),
- GetFileExInfoStandard,
- reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA *>(&findData));
+ bool ok = ::GetFileAttributesEx(
+ reinterpret_cast<const wchar_t *>(fname.nativeFilePath().utf16()),
+ GetFileExInfoStandard, reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA *>(&findData));
if (ok) {
data.fillFromFindData(findData, false, fname.isDriveRoot());
} else {
- if (!tryFindFallback(fname, data))
- if (!tryDriveUNCFallback(fname, data)) {
- SetErrorMode(oldmode);
- return false;
- }
+ const DWORD lastError = GetLastError();
+ // disconnected drive
+ if (lastError == ERROR_LOGON_FAILURE || lastError == ERROR_BAD_NETPATH
+ || (!tryFindFallback(fname, data) && !tryDriveUNCFallback(fname, data))) {
+ data.clearFlags();
+ SetErrorMode(oldmode);
+ return false;
+ }
}
SetErrorMode(oldmode);
}
@@ -1085,13 +1439,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
return data.hasFlags(what);
}
-static inline bool mkDir(const QString &path, DWORD *lastError = 0)
+static inline bool mkDir(const QString &path, SECURITY_ATTRIBUTES *securityAttributes,
+ DWORD *lastError = nullptr)
{
if (lastError)
*lastError = 0;
const QString longPath = QFSFileEnginePrivate::longFileName(path);
- const bool result = ::CreateDirectory((wchar_t*)longPath.utf16(), 0);
- if (lastError) // Capture lastError before any QString is freed since custom allocators might change it.
+ const bool result = ::CreateDirectory((wchar_t *)longPath.utf16(), securityAttributes);
+ // Capture lastError before any QString is freed since custom allocators might change it.
+ if (lastError)
*lastError = GetLastError();
return result;
}
@@ -1101,11 +1457,12 @@ static inline bool rmDir(const QString &path)
return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
}
-static bool isDirPath(const QString &dirPath, bool *existed)
+//static
+bool QFileSystemEngine::isDirPath(const QString &dirPath, bool *existed)
{
QString path = dirPath;
- if (path.length() == 2 && path.at(1) == QLatin1Char(':'))
- path += QLatin1Char('\\');
+ if (path.length() == 2 && path.at(1) == u':')
+ path += u'\\';
const QString longPath = QFSFileEnginePrivate::longFileName(path);
DWORD fileAttrib = ::GetFileAttributes(reinterpret_cast<const wchar_t*>(longPath.utf16()));
@@ -1129,24 +1486,27 @@ static bool isDirPath(const QString &dirPath, bool *existed)
// NOTE: if \a shouldMkdirFirst is false, we assume the caller did try to mkdir
// before calling this function.
-static bool createDirectoryWithParents(const QString &nativeName, bool shouldMkdirFirst = true)
+static bool createDirectoryWithParents(const QString &nativeName,
+ SECURITY_ATTRIBUTES *securityAttributes,
+ bool shouldMkdirFirst = true)
{
const auto isUNCRoot = [](const QString &nativeName) {
- return nativeName.startsWith(QLatin1String("\\\\")) && nativeName.count(QDir::separator()) <= 3;
+ return nativeName.startsWith("\\\\"_L1)
+ && nativeName.count(QDir::separator()) <= 3;
};
const auto isDriveName = [](const QString &nativeName) {
- return nativeName.size() == 2 && nativeName.at(1) == QLatin1Char(':');
+ return nativeName.size() == 2 && nativeName.at(1) == u':';
};
const auto isDir = [](const QString &nativeName) {
bool exists = false;
- return isDirPath(nativeName, &exists) && exists;
+ return QFileSystemEngine::isDirPath(nativeName, &exists) && exists;
};
// Do not try to mkdir a UNC root path or a drive letter.
if (isUNCRoot(nativeName) || isDriveName(nativeName))
return false;
if (shouldMkdirFirst) {
- if (mkDir(nativeName))
+ if (mkDir(nativeName, securityAttributes))
return true;
}
@@ -1155,34 +1515,41 @@ static bool createDirectoryWithParents(const QString &nativeName, bool shouldMkd
return false;
const QString parentNativeName = nativeName.left(backSlash);
- if (!createDirectoryWithParents(parentNativeName))
+ if (!createDirectoryWithParents(parentNativeName, securityAttributes))
return false;
// try again
- if (mkDir(nativeName))
+ if (mkDir(nativeName, securityAttributes))
return true;
return isDir(nativeName);
}
//static
-bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
+bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents,
+ std::optional<QFile::Permissions> permissions)
{
QString dirName = entry.filePath();
Q_CHECK_FILE_NAME(dirName, false);
dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
+ QNativeFilePermissions nativePermissions(permissions, true);
+ if (!nativePermissions.isOk())
+ return false;
+
+ auto securityAttributes = nativePermissions.securityAttributes();
+
// try to mkdir this directory
DWORD lastError;
- if (mkDir(dirName, &lastError))
+ if (mkDir(dirName, securityAttributes, &lastError))
return true;
// mkpath should return true, if the directory already exists, mkdir false.
if (!createParents)
return false;
- if (lastError == ERROR_ALREADY_EXISTS)
+ if (lastError == ERROR_ALREADY_EXISTS || lastError == ERROR_ACCESS_DENIED)
return isDirPath(dirName, nullptr);
- return createDirectoryWithParents(dirName, false);
+ return createDirectoryWithParents(dirName, securityAttributes, false);
}
//static
@@ -1195,10 +1562,12 @@ bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool remo
dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
const auto chunkRef = QStringView{dirName}.left(slash);
- if (chunkRef.length() == 2 && chunkRef.at(0).isLetter() && chunkRef.at(1) == QLatin1Char(':'))
+ if (chunkRef.length() == 2 && chunkRef.at(0).isLetter()
+ && chunkRef.at(1) == u':') {
break;
+ }
const QString chunk = chunkRef.toString();
- if (!isDirPath(chunk, 0))
+ if (!isDirPath(chunk, nullptr))
return false;
if (!rmDir(chunk))
return oldslash != 0;
@@ -1214,8 +1583,8 @@ QString QFileSystemEngine::rootPath()
{
QString ret = QString::fromLatin1(qgetenv("SystemDrive"));
if (ret.isEmpty())
- ret = QLatin1String("c:");
- ret.append(QLatin1Char('/'));
+ ret = "c:"_L1;
+ ret.append(u'/');
return ret;
}
@@ -1227,12 +1596,12 @@ QString QFileSystemEngine::homePath()
initGlobalSid();
{
HANDLE hnd = ::GetCurrentProcess();
- HANDLE token = 0;
+ HANDLE token = nullptr;
BOOL ok = ::OpenProcessToken(hnd, TOKEN_QUERY, &token);
if (ok) {
DWORD dwBufferSize = 0;
// First call, to determine size of the strings (with '\0').
- ok = GetUserProfileDirectory(token, NULL, &dwBufferSize);
+ ok = GetUserProfileDirectory(token, nullptr, &dwBufferSize);
if (!ok && dwBufferSize != 0) { // We got the required buffer size
wchar_t *userDirectory = new wchar_t[dwBufferSize];
// Second call, now we can fill the allocated buffer.
@@ -1273,13 +1642,13 @@ QString QFileSystemEngine::tempPath()
QString::fromWCharArray(tempPath, len);
}
if (!ret.isEmpty()) {
- while (ret.endsWith(QLatin1Char('\\')))
+ while (ret.endsWith(u'\\'))
ret.chop(1);
ret = QDir::fromNativeSeparators(ret);
}
if (ret.isEmpty()) {
- ret = QLatin1String("C:/tmp");
- } else if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
+ ret = "C:/tmp"_L1;
+ } else if (ret.length() >= 2 && ret[1] == u':')
ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
return ret;
}
@@ -1287,72 +1656,97 @@ QString QFileSystemEngine::tempPath()
bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry)
{
QFileSystemMetaData meta;
- fillMetaData(entry, meta, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType);
- if(!(meta.exists() && meta.isDirectory()))
+ fillMetaData(entry, meta,
+ QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType);
+ if (!(meta.exists() && meta.isDirectory()))
return false;
- //TODO: this should really be using nativeFilePath(), but that returns a path in long format \\?\c:\foo
- //which causes many problems later on when it's returned through currentPath()
- return ::SetCurrentDirectory(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(entry.filePath()).utf16())) != 0;
+ // TODO: this should really be using nativeFilePath(), but that returns a path
+ // in long format \\?\c:\foo which causes many problems later on when it's
+ // returned through currentPath()
+ return ::SetCurrentDirectory(reinterpret_cast<const wchar_t *>(
+ QDir::toNativeSeparators(entry.filePath()).utf16()))
+ != 0;
}
QFileSystemEntry QFileSystemEngine::currentPath()
{
- QString ret;
- DWORD size = 0;
- wchar_t currentName[PATH_MAX];
- size = ::GetCurrentDirectory(PATH_MAX, currentName);
- if (size != 0) {
- if (size > PATH_MAX) {
- wchar_t *newCurrentName = new wchar_t[size];
- if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0)
- ret = QString::fromWCharArray(newCurrentName, size);
- delete [] newCurrentName;
- } else {
- ret = QString::fromWCharArray(currentName, size);
- }
+ QString ret(PATH_MAX, Qt::Uninitialized);
+ DWORD size = GetCurrentDirectoryW(PATH_MAX, reinterpret_cast<wchar_t *>(ret.data()));
+ if (size > PATH_MAX) {
+ // try again after enlarging the buffer
+ ret.resize(size);
+ size = GetCurrentDirectoryW(size, reinterpret_cast<wchar_t *>(ret.data()));
+
+ // note: the current directory may have changed underneath us; if the
+ // new one is even bigger, we may return a truncated string!
}
- if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
+ if (size >= 2 && ret.at(1) == u':')
ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
- return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath());
+ ret.resize(size);
+ return QFileSystemEntry(std::move(ret), QFileSystemEntry::FromNativePath());
}
//static
-bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target,
+ QSystemError &error)
{
- Q_ASSERT(false);
- Q_UNUSED(source)
- Q_UNUSED(target)
- Q_UNUSED(error)
+ bool ret = false;
+ QComHelper comHelper;
+ IShellLink *psl = nullptr;
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
+ reinterpret_cast<void **>(&psl));
+
+ if (SUCCEEDED(hres)) {
+ const auto name = QDir::toNativeSeparators(source.filePath());
+ const auto pathName = QDir::toNativeSeparators(source.path());
+ if (SUCCEEDED(psl->SetPath(reinterpret_cast<const wchar_t *>(name.utf16())))
+ && SUCCEEDED(psl->SetWorkingDirectory(
+ reinterpret_cast<const wchar_t *>(pathName.utf16())))) {
+ IPersistFile *ppf = nullptr;
+ if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void **>(&ppf)))) {
+ ret = SUCCEEDED(ppf->Save(
+ reinterpret_cast<const wchar_t *>(target.filePath().utf16()), TRUE));
+ ppf->Release();
+ }
+ }
+ psl->Release();
+ }
- return false; // TODO implement; - code needs to be moved from qfsfileengine_win.cpp
+ if (!ret)
+ error = QSystemError(::GetLastError(), QSystemError::NativeError);
+
+ return ret;
}
//static
-bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target,
+ QSystemError &error)
{
bool ret = ::CopyFile((wchar_t*)source.nativeFilePath().utf16(),
(wchar_t*)target.nativeFilePath().utf16(), true) != 0;
- if(!ret)
+ if (!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
return ret;
}
//static
-bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target,
+ QSystemError &error)
{
Q_CHECK_FILE_NAME(source, false);
Q_CHECK_FILE_NAME(target, false);
bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(),
(wchar_t*)target.nativeFilePath().utf16()) != 0;
- if(!ret)
+ if (!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
return ret;
}
//static
-bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source,
+ const QFileSystemEntry &target, QSystemError &error)
{
Q_CHECK_FILE_NAME(source, false);
Q_CHECK_FILE_NAME(target, false);
@@ -1371,7 +1765,7 @@ bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &
Q_CHECK_FILE_NAME(entry, false);
bool ret = ::DeleteFile((wchar_t*)entry.nativeFilePath().utf16()) != 0;
- if(!ret)
+ if (!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
return ret;
}
@@ -1389,85 +1783,52 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
// we need the "display name" of the file, so can't use nativeAbsoluteFilePath
const QString sourcePath = QDir::toNativeSeparators(absoluteName(source).filePath());
- /*
- Windows 7 insists on showing confirmation dialogs and ignores the respective
- flags set on IFileOperation. Fall back to SHFileOperation, even if it doesn't
- give us the new location of the file.
- */
- if (QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7) {
-# if defined(__IFileOperation_INTERFACE_DEFINED__)
- CoInitialize(NULL);
- IFileOperation *pfo = nullptr;
- IShellItem *deleteItem = nullptr;
- FileOperationProgressSink *sink = nullptr;
- HRESULT hres = E_FAIL;
-
- auto coUninitialize = qScopeGuard([&](){
- if (sink)
- sink->Release();
- if (deleteItem)
- deleteItem->Release();
- if (pfo)
- pfo->Release();
- CoUninitialize();
- if (!SUCCEEDED(hres))
- error = QSystemError(hres, QSystemError::NativeError);
- });
-
- hres = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
- if (!pfo)
- return false;
- pfo->SetOperationFlags(FOF_ALLOWUNDO | FOFX_RECYCLEONDELETE | FOF_NOCONFIRMATION
- | FOF_SILENT | FOF_NOERRORUI);
- hres = SHCreateItemFromParsingName(reinterpret_cast<const wchar_t*>(sourcePath.utf16()),
- nullptr, IID_PPV_ARGS(&deleteItem));
- if (!deleteItem)
- return false;
- sink = new FileOperationProgressSink;
- hres = pfo->DeleteItem(deleteItem, static_cast<IFileOperationProgressSink*>(sink));
- if (!SUCCEEDED(hres))
- return false;
- hres = pfo->PerformOperations();
+ QComHelper comHelper;
+
+ IFileOperation *pfo = nullptr;
+ IShellItem *deleteItem = nullptr;
+ FileOperationProgressSink *sink = nullptr;
+ HRESULT hres = E_FAIL;
+
+ auto coUninitialize = qScopeGuard([&](){
+ if (sink)
+ sink->Release();
+ if (deleteItem)
+ deleteItem->Release();
+ if (pfo)
+ pfo->Release();
if (!SUCCEEDED(hres))
- return false;
- newLocation = QFileSystemEntry(sink->targetPath);
+ error = QSystemError(hres, QSystemError::NativeError);
+ });
-# endif // no IFileOperation in SDK (mingw, likely) - fall back to SHFileOperation
- } else {
- // double null termination needed, so can't use QString::utf16
- QVarLengthArray<wchar_t, MAX_PATH + 1> winFile(sourcePath.length() + 2);
- sourcePath.toWCharArray(winFile.data());
- winFile[sourcePath.length()] = wchar_t{};
- winFile[sourcePath.length() + 1] = wchar_t{};
-
- SHFILEOPSTRUCTW operation;
- operation.hwnd = nullptr;
- operation.wFunc = FO_DELETE;
- operation.pFrom = winFile.constData();
- operation.pTo = nullptr;
- operation.fFlags = FOF_ALLOWUNDO | FOF_NO_UI;
- operation.fAnyOperationsAborted = FALSE;
- operation.hNameMappings = nullptr;
- operation.lpszProgressTitle = nullptr;
-
- int result = SHFileOperation(&operation);
- if (result != 0) {
- error = QSystemError(result, QSystemError::NativeError);
- return false;
- }
- /*
- This implementation doesn't let us know where the file ended up, even if
- we would specify FOF_WANTMAPPINGHANDLE | FOF_RENAMEONCOLLISION, as
- FOF_RENAMEONCOLLISION has no effect unless files are moved, copied, or renamed.
- */
- Q_UNUSED(newLocation);
+ hres = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
+ if (!pfo)
+ return false;
+ pfo->SetOperationFlags(FOF_ALLOWUNDO | FOFX_RECYCLEONDELETE | FOF_NOCONFIRMATION
+ | FOF_SILENT | FOF_NOERRORUI);
+ hres = SHCreateItemFromParsingName(reinterpret_cast<const wchar_t*>(sourcePath.utf16()),
+ nullptr, IID_PPV_ARGS(&deleteItem));
+ if (!deleteItem)
+ return false;
+ sink = new FileOperationProgressSink;
+ hres = pfo->DeleteItem(deleteItem, static_cast<IFileOperationProgressSink*>(sink));
+ if (!SUCCEEDED(hres))
+ return false;
+ hres = pfo->PerformOperations();
+ if (!SUCCEEDED(hres))
+ return false;
+
+ if (!SUCCEEDED(sink->deleteResult)) {
+ error = QSystemError(sink->deleteResult, QSystemError::NativeError);
+ return false;
}
+ newLocation = QFileSystemEntry(sink->targetPath);
return true;
-
}
//static
-bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
+bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry,
+ QFile::Permissions permissions, QSystemError &error,
QFileSystemMetaData *data)
{
Q_CHECK_FILE_NAME(entry, false);
@@ -1477,14 +1838,17 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
if (permissions & (QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther))
mode |= _S_IREAD;
- if (permissions & (QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther))
+ if (permissions
+ & (QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) {
mode |= _S_IWRITE;
+ }
if (mode == 0) // not supported
return false;
- bool ret = ::_wchmod(reinterpret_cast<const wchar_t*>(entry.nativeFilePath().utf16()), mode) == 0;
- if(!ret)
+ bool ret =
+ ::_wchmod(reinterpret_cast<const wchar_t *>(entry.nativeFilePath().utf16()), mode) == 0;
+ if (!ret)
error = QSystemError(errno, QSystemError::StandardLibraryError);
return ret;
}
@@ -1498,7 +1862,7 @@ static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
FileTimeToSystemTime(time, &sTime);
return QDateTime(QDate(sTime.wYear, sTime.wMonth, sTime.wDay),
QTime(sTime.wHour, sTime.wMinute, sTime.wSecond, sTime.wMilliseconds),
- Qt::UTC);
+ QTimeZone::UTC);
}
QDateTime QFileSystemMetaData::birthTime() const
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
index 9b474b25b1..ac1691d30e 100644
--- a/src/corelib/io/qfilesystementry.cpp
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystementry_p.h"
@@ -48,14 +12,20 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+// Assigned to m_lastSeparator and m_firstDotInFileName to indicate resolveFilePath()
+// hasn't been called yet
+constexpr int Uninitialized = -2;
+
#ifdef Q_OS_WIN
static bool isUncRoot(const QString &server)
{
QString localPath = QDir::toNativeSeparators(server);
- if (!localPath.startsWith(QLatin1String("\\\\")))
+ if (!localPath.startsWith("\\\\"_L1))
return false;
- int idx = localPath.indexOf(QLatin1Char('\\'), 2);
+ int idx = localPath.indexOf(u'\\', 2);
if (idx == -1 || idx + 1 == localPath.length())
return true;
@@ -65,8 +35,8 @@ static bool isUncRoot(const QString &server)
static inline QString fixIfRelativeUncPath(const QString &path)
{
QString currentPath = QDir::currentPath();
- if (currentPath.startsWith(QLatin1String("//")))
- return currentPath % QChar(QLatin1Char('/')) % path;
+ if (currentPath.startsWith("//"_L1))
+ return currentPath % QChar(u'/') % path;
return path;
}
#endif
@@ -85,8 +55,8 @@ QFileSystemEntry::QFileSystemEntry()
*/
QFileSystemEntry::QFileSystemEntry(const QString &filePath)
: m_filePath(QDir::fromNativeSeparators(filePath)),
- m_lastSeparator(-2),
- m_firstDotInFileName(-2),
+ m_lastSeparator(Uninitialized),
+ m_firstDotInFileName(Uninitialized),
m_lastDotInFileName(0)
{
}
@@ -98,8 +68,8 @@ QFileSystemEntry::QFileSystemEntry(const QString &filePath)
*/
QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /* dummy */)
: m_filePath(filePath),
- m_lastSeparator(-2),
- m_firstDotInFileName(-2),
+ m_lastSeparator(Uninitialized),
+ m_firstDotInFileName(Uninitialized),
m_lastDotInFileName(0)
{
}
@@ -110,8 +80,8 @@ QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /*
*/
QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath /* dummy */)
: m_nativeFilePath(nativeFilePath),
- m_lastSeparator(-2),
- m_firstDotInFileName(-2),
+ m_lastSeparator(Uninitialized),
+ m_firstDotInFileName(Uninitialized),
m_lastDotInFileName(0)
{
}
@@ -119,8 +89,8 @@ QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativeP
QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
: m_filePath(QDir::fromNativeSeparators(filePath)),
m_nativeFilePath(nativeFilePath),
- m_lastSeparator(-2),
- m_firstDotInFileName(-2),
+ m_lastSeparator(Uninitialized),
+ m_firstDotInFileName(Uninitialized),
m_lastDotInFileName(0)
{
}
@@ -140,14 +110,8 @@ QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath() const
void QFileSystemEntry::resolveFilePath() const
{
if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
-#if defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
- m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
#ifdef Q_OS_WIN
- if (m_filePath.startsWith(QLatin1String("//?/UNC/")))
- m_filePath = m_filePath.remove(2,6);
- if (m_filePath.startsWith(QLatin1String("//?/")))
- m_filePath = m_filePath.remove(0,4);
-#endif
+ m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
#else
m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
#endif
@@ -162,8 +126,6 @@ void QFileSystemEntry::resolveNativeFilePath() const
if (isRelative())
filePath = fixIfRelativeUncPath(m_filePath);
m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
-#elif defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
- m_nativeFilePath = QDir::toNativeSeparators(m_filePath);
#else
m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
#endif
@@ -174,7 +136,7 @@ QString QFileSystemEntry::fileName() const
{
findLastSeparator();
#if defined(Q_OS_WIN)
- if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
return m_filePath.mid(2);
#endif
return m_filePath.mid(m_lastSeparator + 1);
@@ -185,15 +147,15 @@ QString QFileSystemEntry::path() const
findLastSeparator();
if (m_lastSeparator == -1) {
#if defined(Q_OS_WIN)
- if (m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ if (m_filePath.length() >= 2 && m_filePath.at(1) == u':')
return m_filePath.left(2);
#endif
- return QString(QLatin1Char('.'));
+ return QString(u'.');
}
if (m_lastSeparator == 0)
- return QString(QLatin1Char('/'));
+ return QString(u'/');
#if defined(Q_OS_WIN)
- if (m_lastSeparator == 2 && m_filePath.at(1) == QLatin1Char(':'))
+ if (m_lastSeparator == 2 && m_filePath.at(1) == u':')
return m_filePath.left(m_lastSeparator + 1);
#endif
return m_filePath.left(m_lastSeparator);
@@ -209,7 +171,7 @@ QString QFileSystemEntry::baseName() const
length--;
}
#if defined(Q_OS_WIN)
- if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
return m_filePath.mid(2, length - 2);
#endif
return m_filePath.mid(m_lastSeparator + 1, length);
@@ -225,7 +187,7 @@ QString QFileSystemEntry::completeBaseName() const
length--;
}
#if defined(Q_OS_WIN)
- if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
+ if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == u':')
return m_filePath.mid(2, length - 2);
#endif
return m_filePath.mid(m_lastSeparator + 1, length);
@@ -267,8 +229,8 @@ bool QFileSystemEntry::isAbsolute() const
&& m_filePath.at(1).unicode() == ':'
&& m_filePath.at(2).unicode() == '/')
|| (m_filePath.length() >= 2
- && m_filePath.at(0) == QLatin1Char('/')
- && m_filePath.at(1) == QLatin1Char('/')));
+ && m_filePath.at(0) == u'/'
+ && m_filePath.at(1) == u'/'));
}
#else
bool QFileSystemEntry::isRelative() const
@@ -293,14 +255,42 @@ bool QFileSystemEntry::isDriveRoot() const
bool QFileSystemEntry::isDriveRootPath(const QString &path)
{
return (path.length() == 3
- && path.at(0).isLetter() && path.at(1) == QLatin1Char(':')
- && path.at(2) == QLatin1Char('/'));
+ && path.at(0).isLetter() && path.at(1) == u':'
+ && path.at(2) == u'/');
+}
+
+QString QFileSystemEntry::removeUncOrLongPathPrefix(QString path)
+{
+ constexpr qsizetype minPrefixSize = 4;
+ if (path.size() < minPrefixSize)
+ return path;
+
+ auto data = path.data();
+ const auto slash = path[0];
+ if (slash != u'\\' && slash != u'/')
+ return path;
+
+ // check for "//?/" or "/??/"
+ if (data[2] == u'?' && data[3] == slash && (data[1] == slash || data[1] == u'?')) {
+ path = path.sliced(minPrefixSize);
+
+ // check for a possible "UNC/" prefix left-over
+ if (path.size() >= 4) {
+ data = path.data();
+ if (data[0] == u'U' && data[1] == u'N' && data[2] == u'C' && data[3] == slash) {
+ data[2] = slash;
+ return path.sliced(2);
+ }
+ }
+ }
+
+ return path;
}
#endif // Q_OS_WIN
bool QFileSystemEntry::isRootPath(const QString &path)
{
- if (path == QLatin1String("/")
+ if (path == "/"_L1
#if defined(Q_OS_WIN)
|| isDriveRootPath(path)
|| isUncRoot(path)
@@ -317,19 +307,24 @@ bool QFileSystemEntry::isRoot() const
return isRootPath(m_filePath);
}
+bool QFileSystemEntry::isEmpty() const
+{
+ return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
+}
+
// private methods
void QFileSystemEntry::findLastSeparator() const
{
- if (m_lastSeparator == -2) {
+ if (m_lastSeparator == Uninitialized) {
resolveFilePath();
- m_lastSeparator = m_filePath.lastIndexOf(QLatin1Char('/'));
+ m_lastSeparator = m_filePath.lastIndexOf(u'/');
}
}
void QFileSystemEntry::findFileNameSeparators() const
{
- if (m_firstDotInFileName == -2) {
+ if (m_firstDotInFileName == Uninitialized) {
resolveFilePath();
int firstDotInFileName = -1;
int lastDotInFileName = -1;
@@ -382,7 +377,7 @@ bool QFileSystemEntry::isClean() const
bool dotok = true; // checking for ".." or "." starts to relative paths
bool slashok = true;
for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); ++iter) {
- if (*iter == QLatin1Char('/')) {
+ if (*iter == u'/') {
if (dots == 1 || dots == 2)
return false; // path contains "./" or "../"
if (!slashok)
@@ -392,7 +387,7 @@ bool QFileSystemEntry::isClean() const
slashok = false;
} else if (dotok) {
slashok = true;
- if (*iter == QLatin1Char('.')) {
+ if (*iter == u'.') {
dots++;
if (dots > 2)
dotok = false;
diff --git a/src/corelib/io/qfilesystementry_p.h b/src/corelib/io/qfilesystementry_p.h
index 251eca553a..8b5d506b0b 100644
--- a/src/corelib/io/qfilesystementry_p.h
+++ b/src/corelib/io/qfilesystementry_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMENTRY_P_H
#define QFILESYSTEMENTRY_P_H
@@ -55,17 +19,13 @@
#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
-#if defined(Q_OS_WIN)
-#define QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
-#endif
-
QT_BEGIN_NAMESPACE
class QFileSystemEntry
{
public:
-#ifndef QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
+#ifndef Q_OS_WIN
typedef QByteArray NativePath;
#else
typedef QString NativePath;
@@ -73,35 +33,34 @@ public:
struct FromNativePath{};
struct FromInternalPath{};
- QFileSystemEntry();
- explicit QFileSystemEntry(const QString &filePath);
-
- QFileSystemEntry(const QString &filePath, FromInternalPath dummy);
- QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath dummy);
- QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath);
-
- QString filePath() const;
- QString fileName() const;
- QString path() const;
- NativePath nativeFilePath() const;
- QString baseName() const;
- QString completeBaseName() const;
- QString suffix() const;
- QString completeSuffix() const;
- bool isAbsolute() const;
- bool isRelative() const;
- bool isClean() const;
+ Q_AUTOTEST_EXPORT QFileSystemEntry();
+ Q_AUTOTEST_EXPORT explicit QFileSystemEntry(const QString &filePath);
+
+ Q_AUTOTEST_EXPORT QFileSystemEntry(const QString &filePath, FromInternalPath dummy);
+ Q_AUTOTEST_EXPORT QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath dummy);
+ Q_AUTOTEST_EXPORT QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath);
+
+ Q_AUTOTEST_EXPORT QString filePath() const;
+ Q_AUTOTEST_EXPORT QString fileName() const;
+ Q_AUTOTEST_EXPORT QString path() const;
+ Q_AUTOTEST_EXPORT NativePath nativeFilePath() const;
+ Q_AUTOTEST_EXPORT QString baseName() const;
+ Q_AUTOTEST_EXPORT QString completeBaseName() const;
+ Q_AUTOTEST_EXPORT QString suffix() const;
+ Q_AUTOTEST_EXPORT QString completeSuffix() const;
+ Q_AUTOTEST_EXPORT bool isAbsolute() const;
+ Q_AUTOTEST_EXPORT bool isRelative() const;
+ Q_AUTOTEST_EXPORT bool isClean() const;
#if defined(Q_OS_WIN)
- bool isDriveRoot() const;
+ Q_AUTOTEST_EXPORT bool isDriveRoot() const;
static bool isDriveRootPath(const QString &path);
+ static QString removeUncOrLongPathPrefix(QString path);
#endif
- bool isRoot() const;
+ Q_AUTOTEST_EXPORT bool isRoot() const;
+
+ Q_AUTOTEST_EXPORT bool isEmpty() const;
- bool isEmpty() const
- {
- return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
- }
void clear()
{
*this = QFileSystemEntry();
diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h
index 5e4e424e69..2973b85cd2 100644
--- a/src/corelib/io/qfilesystemiterator_p.h
+++ b/src/corelib/io/qfilesystemiterator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMITERATOR_P_H
#define QFILESYSTEMITERATOR_P_H
@@ -56,44 +20,48 @@
#ifndef QT_NO_FILESYSTEMITERATOR
#include <QtCore/qdir.h>
-#include <QtCore/qdiriterator.h>
#include <QtCore/qstringlist.h>
#include <QtCore/private/qfilesystementry_p.h>
#include <QtCore/private/qfilesystemmetadata_p.h>
-// Platform-specific headers
#if !defined(Q_OS_WIN)
-#include <QtCore/qscopedpointer.h>
+#include <private/qstringconverter_p.h>
#endif
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QFileSystemIterator
{
public:
- QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
- const QStringList &nameFilters, QDirIterator::IteratorFlags flags
- = QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
+ QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters);
~QFileSystemIterator();
bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData);
private:
- QFileSystemEntry::NativePath nativePath;
+ QString dirPath;
// Platform-specific data
#if defined(Q_OS_WIN)
- QString dirPath;
+ QFileSystemEntry::NativePath nativePath;
HANDLE findFileHandle;
QStringList uncShares;
bool uncFallback;
int uncShareIndex;
bool onlyDirs;
#else
- QT_DIR *dir;
- QT_DIRENT *dirEntry;
- int lastError;
+ struct DirStreamCloser {
+ void operator()(QT_DIR *dir) { if (dir) QT_CLOSEDIR(dir); }
+ };
+ using DirPtr = std::unique_ptr<QT_DIR, DirStreamCloser>;
+ DirPtr dir;
+
+ QT_DIRENT *dirEntry = nullptr;
+ int lastError = 0;
+ QStringDecoder toUtf16;
#endif
Q_DISABLE_COPY_MOVE(QFileSystemIterator)
diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp
index fd96298f69..a1130728ef 100644
--- a/src/corelib/io/qfilesystemiterator_unix.cpp
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -1,49 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qfilesystemiterator_p.h"
-#include <private/qstringconverter_p.h>
-
#ifndef QT_NO_FILESYSTEMITERATOR
+#include <qvarlengtharray.h>
+
#include <memory>
#include <stdlib.h>
@@ -51,53 +15,66 @@
QT_BEGIN_NAMESPACE
-static bool checkNameDecodable(const char *d_name, qsizetype len)
-{
- // This function is called in a loop from advance() below, but the loop is
- // usually run only once.
-
- return QUtf8::isValidUtf8(d_name, len).isValidUtf8;
-}
-
-QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
- const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
- : nativePath(entry.nativeFilePath())
- , dir(nullptr)
- , dirEntry(nullptr)
- , lastError(0)
+/*
+ Native filesystem iterator, which uses ::opendir()/readdir()/dirent from the system
+ libraries to iterate over the directory represented by \a entry.
+*/
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters)
+ : dirPath(entry.filePath()),
+ toUtf16(QStringDecoder::Utf8)
{
- Q_UNUSED(filters)
- Q_UNUSED(nameFilters)
- Q_UNUSED(flags)
+ Q_UNUSED(filters);
- if ((dir = QT_OPENDIR(nativePath.constData())) == nullptr) {
+ dir.reset(QT_OPENDIR(entry.nativeFilePath().constData()));
+ if (!dir) {
lastError = errno;
} else {
- if (!nativePath.endsWith('/'))
- nativePath.append('/');
+ if (!dirPath.endsWith(u'/'))
+ dirPath.append(u'/');
}
}
-QFileSystemIterator::~QFileSystemIterator()
-{
- if (dir)
- QT_CLOSEDIR(dir);
-}
+QFileSystemIterator::~QFileSystemIterator() = default;
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
{
+ auto asFileEntry = [this](QStringView name) {
+#ifdef Q_OS_DARWIN
+ // must match QFile::decodeName
+ QString normalized = name.toString().normalized(QString::NormalizationForm_C);
+ name = normalized;
+#endif
+ return QFileSystemEntry(dirPath + name, QFileSystemEntry::FromInternalPath());
+ };
if (!dir)
return false;
for (;;) {
- dirEntry = QT_READDIR(dir);
+ // From readdir man page:
+ // If the end of the directory stream is reached, NULL is returned and errno is
+ // not changed. If an error occurs, NULL is returned and errno is set to indicate
+ // the error. To distinguish end of stream from an error, set errno to zero before
+ // calling readdir() and then check the value of errno if NULL is returned.
+ errno = 0;
+ dirEntry = QT_READDIR(dir.get());
if (dirEntry) {
- qsizetype len = strlen(dirEntry->d_name);
- if (checkNameDecodable(dirEntry->d_name, len)) {
- fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name, len), QFileSystemEntry::FromNativePath());
+ // POSIX allows readdir() to return a file name in struct dirent that
+ // extends past the end of the d_name array (it's a char[1] array on QNX, for
+ // example). Therefore, we *must* call strlen() on it to get the actual length
+ // of the file name. See:
+ // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html#tag_13_07_05
+ QByteArrayView name(dirEntry->d_name, strlen(dirEntry->d_name));
+ // name.size() is sufficient here, see QUtf8::convertToUnicode() for details
+ QVarLengthArray<char16_t> buffer(name.size());
+ auto *end = toUtf16.appendToBuffer(buffer.data(), name);
+ buffer.resize(end - buffer.constData());
+ if (!toUtf16.hasError()) {
+ fileEntry = asFileEntry(buffer);
metaData.fillFromDirEnt(*dirEntry);
return true;
+ } else {
+ errno = EILSEQ; // Invalid or incomplete multibyte or wide character
}
} else {
break;
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index 65596643bc..7644a1a078 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemiterator_p.h"
#include "qfilesystemengine_p.h"
@@ -46,30 +10,29 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
bool done = true;
-QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
- const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
- : nativePath(entry.nativeFilePath())
- , dirPath(entry.filePath())
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters)
+ : dirPath(entry.filePath())
+ , nativePath(entry.nativeFilePath())
, findFileHandle(INVALID_HANDLE_VALUE)
, uncFallback(false)
, uncShareIndex(0)
, onlyDirs(false)
{
- Q_UNUSED(nameFilters)
- Q_UNUSED(flags)
- if (nativePath.endsWith(QLatin1String(".lnk"))) {
+ if (nativePath.endsWith(u".lnk"_s) && !QFileSystemEngine::isDirPath(dirPath, nullptr)) {
QFileSystemMetaData metaData;
QFileSystemEntry link = QFileSystemEngine::getLinkTarget(entry, metaData);
nativePath = link.nativeFilePath();
}
- if (!nativePath.endsWith(QLatin1Char('\\')))
- nativePath.append(QLatin1Char('\\'));
- nativePath.append(QLatin1Char('*'));
+ if (!nativePath.endsWith(u'\\'))
+ nativePath.append(u'\\');
+ nativePath.append(u'*');
// In MSVC2015+ case we prepend //?/ for longer file-name support
- if (!dirPath.endsWith(QLatin1Char('/')))
- dirPath.append(QLatin1Char('/'));
+ if (!dirPath.endsWith(u'/'))
+ dirPath.append(u'/');
if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files))))
onlyDirs = true;
}
@@ -89,20 +52,18 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa
haveData = true;
int infoLevel = 0 ; // FindExInfoStandard;
DWORD dwAdditionalFlags = 0;
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows7) {
- dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH
- infoLevel = 1 ; // FindExInfoBasic;
- }
+ dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH
+ infoLevel = 1 ; // FindExInfoBasic;
int searchOps = 0; // FindExSearchNameMatch
if (onlyDirs)
searchOps = 1 ; // FindExSearchLimitToDirectories
findFileHandle = FindFirstFileEx((const wchar_t *)nativePath.utf16(), FINDEX_INFO_LEVELS(infoLevel), &findData,
FINDEX_SEARCH_OPS(searchOps), 0, dwAdditionalFlags);
if (findFileHandle == INVALID_HANDLE_VALUE) {
- if (nativePath.startsWith(QLatin1String("\\\\?\\UNC\\"))) {
- const auto parts = QStringView{nativePath}.split(QLatin1Char('\\'), Qt::SkipEmptyParts);
+ if (nativePath.startsWith("\\\\?\\UNC\\"_L1)) {
+ const auto parts = QStringView{nativePath}.split(u'\\', Qt::SkipEmptyParts);
if (parts.count() == 4 && QFileSystemEngine::uncListSharesOnServer(
- QLatin1String("\\\\") + parts.at(2), &uncShares)) {
+ "\\\\"_L1 + parts.at(2), &uncShares)) {
if (uncShares.isEmpty())
return false; // No shares found in the server
uncFallback = true;
@@ -131,7 +92,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa
QString fileName = QString::fromWCharArray(findData.cFileName);
fileEntry = QFileSystemEntry(dirPath + fileName);
metaData = QFileSystemMetaData();
- if (!fileName.endsWith(QLatin1String(".lnk"))) {
+ if (!fileName.endsWith(".lnk"_L1)) {
metaData.fillFromFindData(findData, true);
}
return true;
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index dbd89f5903..c10b66afaf 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMMETADATA_P_H
#define QFILESYSTEMMETADATA_P_H
@@ -54,6 +18,7 @@
#include "qplatformdefs.h"
#include <QtCore/qglobal.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qtimezone.h>
#include <QtCore/private/qabstractfileengine_p.h>
// Platform-specific includes
@@ -193,20 +158,20 @@ public:
knownFlagsMask &= ~flags;
}
- bool exists() const { return (entryFlags & ExistsAttribute); }
+ bool exists() const { return entryFlags.testAnyFlag(ExistsAttribute); }
- bool isLink() const { return (entryFlags & LinkType); }
- bool isFile() const { return (entryFlags & FileType); }
- bool isDirectory() const { return (entryFlags & DirectoryType); }
+ bool isLink() const { return entryFlags.testAnyFlag(LinkType); }
+ bool isFile() const { return entryFlags.testAnyFlag(FileType); }
+ bool isDirectory() const { return entryFlags.testAnyFlag(DirectoryType); }
bool isBundle() const;
bool isAlias() const;
- bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
- bool isSequential() const { return (entryFlags & SequentialType); }
- bool isHidden() const { return (entryFlags & HiddenAttribute); }
- bool wasDeleted() const { return (entryFlags & WasDeletedAttribute); }
+ bool isLegacyLink() const { return entryFlags.testAnyFlag(LegacyLinkType); }
+ bool isSequential() const { return entryFlags.testAnyFlag(SequentialType); }
+ bool isHidden() const { return entryFlags.testAnyFlag(HiddenAttribute); }
+ bool wasDeleted() const { return entryFlags.testAnyFlag(WasDeletedAttribute); }
#if defined(Q_OS_WIN)
- bool isLnkFile() const { return (entryFlags & WinLnkType); }
- bool isJunction() const { return (entryFlags & JunctionType); }
+ bool isLnkFile() const { return entryFlags.testAnyFlag(WinLnkType); }
+ bool isJunction() const { return entryFlags.testAnyFlag(JunctionType); }
#else
bool isLnkFile() const { return false; }
bool isJunction() const { return false; }
@@ -214,18 +179,22 @@ public:
qint64 size() const { return size_; }
- QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
+ QFile::Permissions permissions() const;
QDateTime accessTime() const;
QDateTime birthTime() const;
QDateTime metadataChangeTime() const;
QDateTime modificationTime() const;
- QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
+ QDateTime fileTime(QFile::FileTime time) const;
uint userId() const;
uint groupId() const;
uint ownerId(QAbstractFileEngine::FileOwner owner) const;
+ bool isReadable() const { return permissions().testAnyFlags(QFile::ReadUser); }
+ bool isWritable() const { return permissions().testAnyFlags(QFile::WriteUser); }
+ bool isExecutable() const { return permissions().testAnyFlags(QFile::ExeUser); }
+
#ifdef Q_OS_UNIX
void fillFromStatxBuf(const struct statx &statBuffer);
void fillFromStatBuf(const QT_STATBUF &statBuffer);
@@ -243,7 +212,7 @@ private:
MetaDataFlags knownFlagsMask;
MetaDataFlags entryFlags;
- qint64 size_;
+ qint64 size_ = 0;
// Platform-specific data goes here:
#if defined(Q_OS_WIN)
@@ -254,41 +223,43 @@ private:
FILETIME lastWriteTime_;
#else
// msec precision
- qint64 accessTime_;
- qint64 birthTime_;
- qint64 metadataChangeTime_;
- qint64 modificationTime_;
+ qint64 accessTime_ = 0;
+ qint64 birthTime_ = 0;
+ qint64 metadataChangeTime_ = 0;
+ qint64 modificationTime_ = 0;
- uint userId_;
- uint groupId_;
+ uint userId_ = (uint) -2;
+ uint groupId_ = (uint) -2;
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
+inline QFile::Permissions QFileSystemMetaData::permissions() const { return QFile::Permissions::fromInt((Permissions & entryFlags).toInt()); }
+
#if defined(Q_OS_DARWIN)
-inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
-inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
+inline bool QFileSystemMetaData::isBundle() const { return entryFlags.testAnyFlag(BundleType); }
+inline bool QFileSystemMetaData::isAlias() const { return entryFlags.testAnyFlag(AliasType); }
#else
inline bool QFileSystemMetaData::isBundle() const { return false; }
inline bool QFileSystemMetaData::isAlias() const { return false; }
#endif
#if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
-inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
+inline QDateTime QFileSystemMetaData::fileTime(QFile::FileTime time) const
{
switch (time) {
- case QAbstractFileEngine::ModificationTime:
+ case QFile::FileModificationTime:
return modificationTime();
- case QAbstractFileEngine::AccessTime:
+ case QFile::FileAccessTime:
return accessTime();
- case QAbstractFileEngine::BirthTime:
+ case QFile::FileBirthTime:
return birthTime();
- case QAbstractFileEngine::MetadataChangeTime:
+ case QFile::FileMetadataChangeTime:
return metadataChangeTime();
}
@@ -298,13 +269,29 @@ inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime tim
#if defined(Q_OS_UNIX)
inline QDateTime QFileSystemMetaData::birthTime() const
-{ return birthTime_ ? QDateTime::fromMSecsSinceEpoch(birthTime_) : QDateTime(); }
+{
+ return birthTime_
+ ? QDateTime::fromMSecsSinceEpoch(birthTime_, QTimeZone::UTC)
+ : QDateTime();
+}
inline QDateTime QFileSystemMetaData::metadataChangeTime() const
-{ return metadataChangeTime_ ? QDateTime::fromMSecsSinceEpoch(metadataChangeTime_) : QDateTime(); }
+{
+ return metadataChangeTime_
+ ? QDateTime::fromMSecsSinceEpoch(metadataChangeTime_, QTimeZone::UTC)
+ : QDateTime();
+}
inline QDateTime QFileSystemMetaData::modificationTime() const
-{ return modificationTime_ ? QDateTime::fromMSecsSinceEpoch(modificationTime_) : QDateTime(); }
+{
+ return modificationTime_
+ ? QDateTime::fromMSecsSinceEpoch(modificationTime_, QTimeZone::UTC)
+ : QDateTime();
+}
inline QDateTime QFileSystemMetaData::accessTime() const
-{ return accessTime_ ? QDateTime::fromMSecsSinceEpoch(accessTime_) : QDateTime(); }
+{
+ return accessTime_
+ ? QDateTime::fromMSecsSinceEpoch(accessTime_, QTimeZone::UTC)
+ : QDateTime();
+}
inline uint QFileSystemMetaData::userId() const { return userId_; }
inline uint QFileSystemMetaData::groupId() const { return groupId_; }
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 1712fec751..7138f8260b 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemwatcher.h"
#include "qfilesystemwatcher_p.h"
@@ -67,6 +31,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcWatcher, "qt.core.filesystemwatcher")
QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject *parent)
@@ -92,51 +58,44 @@ QFileSystemWatcherPrivate::QFileSystemWatcherPrivate()
{
}
+void QFileSystemWatcherPrivate::connectEngine(QFileSystemWatcherEngine *engine)
+{
+ QObjectPrivate::connect(engine, &QFileSystemWatcherEngine::fileChanged,
+ this, &QFileSystemWatcherPrivate::fileChanged);
+ QObjectPrivate::connect(engine, &QFileSystemWatcherEngine::directoryChanged,
+ this, &QFileSystemWatcherPrivate::directoryChanged);
+}
+
void QFileSystemWatcherPrivate::init()
{
Q_Q(QFileSystemWatcher);
native = createNativeEngine(q);
if (native) {
- QObject::connect(native,
- SIGNAL(fileChanged(QString,bool)),
- q,
- SLOT(_q_fileChanged(QString,bool)));
- QObject::connect(native,
- SIGNAL(directoryChanged(QString,bool)),
- q,
- SLOT(_q_directoryChanged(QString,bool)));
+ connectEngine(native);
#if defined(Q_OS_WIN)
- QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
- &QWindowsFileSystemWatcherEngine::driveLockForRemoval,
- q, [this] (const QString &p) { _q_winDriveLockForRemoval(p); });
- QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
- &QWindowsFileSystemWatcherEngine::driveLockForRemovalFailed,
- q, [this] (const QString &p) { _q_winDriveLockForRemovalFailed(p); });
- QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
- &QWindowsFileSystemWatcherEngine::driveRemoved,
- q, [this] (const QString &p) { _q_winDriveRemoved(p); });
+ auto *windowsWatcher = static_cast<QWindowsFileSystemWatcherEngine *>(native);
+ using WinE = QWindowsFileSystemWatcherEngine;
+ QObjectPrivate::connect(windowsWatcher, &WinE::driveLockForRemoval,
+ this, &QFileSystemWatcherPrivate::winDriveLockForRemoval);
+ QObjectPrivate::connect(windowsWatcher, &WinE::driveLockForRemovalFailed,
+ this, &QFileSystemWatcherPrivate::winDriveLockForRemovalFailed);
+ QObjectPrivate::connect(windowsWatcher, &WinE::driveRemoved,
+ this, &QFileSystemWatcherPrivate::winDriveRemoved);
#endif // Q_OS_WIN
}
}
void QFileSystemWatcherPrivate::initPollerEngine()
{
- if(poller)
+ if (poller)
return;
Q_Q(QFileSystemWatcher);
poller = new QPollingFileSystemWatcherEngine(q); // that was a mouthful
- QObject::connect(poller,
- SIGNAL(fileChanged(QString,bool)),
- q,
- SLOT(_q_fileChanged(QString,bool)));
- QObject::connect(poller,
- SIGNAL(directoryChanged(QString,bool)),
- q,
- SLOT(_q_directoryChanged(QString,bool)));
+ connectEngine(poller);
}
-void QFileSystemWatcherPrivate::_q_fileChanged(const QString &path, bool removed)
+void QFileSystemWatcherPrivate::fileChanged(const QString &path, bool removed)
{
Q_Q(QFileSystemWatcher);
qCDebug(lcWatcher) << "file changed" << path << "removed?" << removed << "watching?" << files.contains(path);
@@ -149,7 +108,7 @@ void QFileSystemWatcherPrivate::_q_fileChanged(const QString &path, bool removed
emit q->fileChanged(path, QFileSystemWatcher::QPrivateSignal());
}
-void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool removed)
+void QFileSystemWatcherPrivate::directoryChanged(const QString &path, bool removed)
{
Q_Q(QFileSystemWatcher);
qCDebug(lcWatcher) << "directory changed" << path << "removed?" << removed << "watching?" << directories.contains(path);
@@ -164,7 +123,7 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re
#if defined(Q_OS_WIN)
-void QFileSystemWatcherPrivate::_q_winDriveLockForRemoval(const QString &path)
+void QFileSystemWatcherPrivate::winDriveLockForRemoval(const QString &path)
{
// Windows: Request to lock a (removable/USB) drive for removal, release
// its paths under watch, temporarily storing them should the lock fail.
@@ -181,7 +140,7 @@ void QFileSystemWatcherPrivate::_q_winDriveLockForRemoval(const QString &path)
}
}
-void QFileSystemWatcherPrivate::_q_winDriveLockForRemovalFailed(const QString &path)
+void QFileSystemWatcherPrivate::winDriveLockForRemovalFailed(const QString &path)
{
// Windows: Request to lock a (removable/USB) drive failed (blocked by other
// application), restore the watched paths.
@@ -195,7 +154,7 @@ void QFileSystemWatcherPrivate::_q_winDriveLockForRemovalFailed(const QString &p
}
}
-void QFileSystemWatcherPrivate::_q_winDriveRemoved(const QString &path)
+void QFileSystemWatcherPrivate::winDriveRemoved(const QString &path)
{
// Windows: Drive finally removed, clear out paths stored in lock request.
if (!path.isEmpty())
@@ -364,14 +323,14 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths)
#ifdef QT_BUILD_INTERNAL
const QString on = objectName();
- if (Q_UNLIKELY(on.startsWith(QLatin1String("_qt_autotest_force_engine_")))) {
+ if (Q_UNLIKELY(on.startsWith("_qt_autotest_force_engine_"_L1))) {
// Autotest override case - use the explicitly selected engine only
const auto forceName = QStringView{on}.mid(26);
- if (forceName == QLatin1String("poller")) {
+ if (forceName == "poller"_L1) {
qCDebug(lcWatcher, "QFileSystemWatcher: skipping native engine, using only polling engine");
d_func()->initPollerEngine();
return d->poller;
- } else if (forceName == QLatin1String("native")) {
+ } else if (forceName == "native"_L1) {
qCDebug(lcWatcher, "QFileSystemWatcher: skipping polling engine, using only native engine");
return d->native;
}
@@ -379,7 +338,7 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths)
}
#endif
// Normal runtime case - search intelligently for best engine
- if(d->native) {
+ if (d->native) {
return d->native;
} else {
d_func()->initPollerEngine();
diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h
index cd64115f8f..668bc143b2 100644
--- a/src/corelib/io/qfilesystemwatcher.h
+++ b/src/corelib/io/qfilesystemwatcher.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_H
#define QFILESYSTEMWATCHER_H
@@ -70,10 +34,6 @@ public:
Q_SIGNALS:
void fileChanged(const QString &path, QPrivateSignal);
void directoryChanged(const QString &path, QPrivateSignal);
-
-private:
- Q_PRIVATE_SLOT(d_func(), void _q_fileChanged(const QString &path, bool removed))
- Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &path, bool removed))
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index e039559ea3..0d9b84890a 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qplatformdefs.h>
@@ -217,8 +181,8 @@ void QFseventsFileSystemWatcherEngine::processEvent(ConstFSEventStreamRef stream
lastReceivedEvent = qMax(lastReceivedEvent, eventIds[i]);
QString path = QFile::decodeName(eventPaths[i]);
- if (path.endsWith(QDir::separator()))
- path = path.mid(0, path.size() - 1);
+ if (path.size() > 1 && path.endsWith(QDir::separator()))
+ path.chop(1);
if (eFlags & kFSEventStreamEventFlagMustScanSubDirs) {
DEBUG("\tmust rescan directory because of coalesced events");
@@ -311,14 +275,16 @@ QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
{
QMacAutoReleasePool pool;
- // Stop the stream in case we have to wait for the lock below to be acquired.
- if (stream)
- FSEventStreamStop(stream);
+ dispatch_sync(queue, ^{
+ // Stop the stream in case we have to wait for the lock below to be acquired.
+ if (stream)
+ FSEventStreamStop(stream);
- // The assumption with the locking strategy is that this class cannot and will not be subclassed!
- QMutexLocker locker(&lock);
+ // The assumption with the locking strategy is that this class cannot and will not be subclassed!
+ QMutexLocker locker(&lock);
- stopStream(true);
+ stopStream(true);
+ });
dispatch_release(queue);
}
@@ -344,8 +310,8 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
auto sg = qScopeGuard([&]{ unhandled.push_back(path); });
QString origPath = path.normalized(QString::NormalizationForm_C);
QString realPath = origPath;
- if (realPath.endsWith(QDir::separator()))
- realPath = realPath.mid(0, realPath.size() - 1);
+ if (realPath.size() > 1 && realPath.endsWith(QDir::separator()))
+ realPath.chop(1);
QString watchedPath, parentPath;
realPath = QFileInfo(realPath).canonicalFilePath();
@@ -435,8 +401,8 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
for (const QString &origPath : paths) {
auto sg = qScopeGuard([&]{ unhandled.push_back(origPath); });
QString realPath = origPath;
- if (realPath.endsWith(QDir::separator()))
- realPath = realPath.mid(0, realPath.size() - 1);
+ if (realPath.size() > 1 && realPath.endsWith(QDir::separator()))
+ realPath.chop(1);
QFileInfo fi(realPath);
realPath = fi.canonicalFilePath();
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
index ad23805afb..173ad1d52d 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h
+++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_FSEVENTS_P_H
#define QFILESYSTEMWATCHER_FSEVENTS_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 94d9d06bcb..e60f688110 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemwatcher.h"
#include "qfilesystemwatcher_inotify_p.h"
@@ -253,13 +217,14 @@ QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd, QObject
notifier(fd, QSocketNotifier::Read, this)
{
fcntl(inotifyFd, F_SETFD, FD_CLOEXEC);
- connect(&notifier, SIGNAL(activated(QSocketDescriptor)), SLOT(readFromInotify()));
+ QObject::connect(&notifier, &QSocketNotifier::activated,
+ this, &QInotifyFileSystemWatcherEngine::readFromInotify);
}
QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine()
{
notifier.setEnabled(false);
- for (int id : qAsConst(pathToID))
+ for (int id : std::as_const(pathToID))
inotify_rm_watch(inotifyFd, id < 0 ? -id : id);
::close(inotifyFd);
@@ -366,9 +331,11 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
// qDebug("QInotifyFileSystemWatcherEngine::readFromInotify");
int buffSize = 0;
- ioctl(inotifyFd, FIONREAD, (char *) &buffSize);
+ if (ioctl(inotifyFd, FIONREAD, (char *) &buffSize) == -1 || buffSize == 0)
+ return;
+
QVarLengthArray<char, 4096> buffer(buffSize);
- buffSize = read(inotifyFd, buffer.data(), buffSize);
+ buffSize = int(read(inotifyFd, buffer.data(), buffSize));
char *at = buffer.data();
char * const end = at + buffSize;
diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h
index b63729cde4..05f87df14c 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify_p.h
+++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_INOTIFY_P_H
#define QFILESYSTEMWATCHER_INOTIFY_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 06383a103a..7a9be337bf 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qplatformdefs.h>
@@ -87,7 +51,7 @@ QKqueueFileSystemWatcherEngine::~QKqueueFileSystemWatcherEngine()
notifier.setEnabled(false);
close(kqfd);
- for (int id : qAsConst(pathToID))
+ for (int id : std::as_const(pathToID))
::close(id < 0 ? -id : id);
}
@@ -201,7 +165,7 @@ void QKqueueFileSystemWatcherEngine::readFromKqueue()
int r;
struct kevent kev;
struct timespec ts = { 0, 0 }; // 0 ts, because we want to poll
- EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, &ts));
+ QT_EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, &ts));
if (r < 0) {
perror("QKqueueFileSystemWatcherEngine: error during kevent wait");
return;
@@ -254,3 +218,5 @@ void QKqueueFileSystemWatcherEngine::readFromKqueue()
}
QT_END_NAMESPACE
+
+#include "moc_qfilesystemwatcher_kqueue_p.cpp"
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue_p.h b/src/corelib/io/qfilesystemwatcher_kqueue_p.h
index e0c7ff60f2..05844d5be9 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue_p.h
+++ b/src/corelib/io/qfilesystemwatcher_kqueue_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_KQUEUE_P_H
#define QFILESYSTEMWATCHER_KQUEUE_P_H
@@ -71,8 +35,10 @@ public:
static QKqueueFileSystemWatcherEngine *create(QObject *parent);
- QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
- QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList addPaths(const QStringList &paths, QStringList *files,
+ QStringList *directories) override;
+ QStringList removePaths(const QStringList &paths, QStringList *files,
+ QStringList *directories) override;
private Q_SLOTS:
void readFromKqueue();
diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h
index cecfe03ff5..c34e3e2408 100644
--- a/src/corelib/io/qfilesystemwatcher_p.h
+++ b/src/corelib/io/qfilesystemwatcher_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_P_H
#define QFILESYSTEMWATCHER_P_H
@@ -105,13 +69,15 @@ public:
QStringList files, directories;
// private slots
- void _q_fileChanged(const QString &path, bool removed);
- void _q_directoryChanged(const QString &path, bool removed);
+ void fileChanged(const QString &path, bool removed);
+ void directoryChanged(const QString &path, bool removed);
+
+ void connectEngine(QFileSystemWatcherEngine *e);
#if defined(Q_OS_WIN)
- void _q_winDriveLockForRemoval(const QString &);
- void _q_winDriveLockForRemovalFailed(const QString &);
- void _q_winDriveRemoved(const QString &);
+ void winDriveLockForRemoval(const QString &);
+ void winDriveLockForRemovalFailed(const QString &);
+ void winDriveRemoved(const QString &);
private:
QHash<QChar, QStringList> temporarilyRemovedPaths;
diff --git a/src/corelib/io/qfilesystemwatcher_polling.cpp b/src/corelib/io/qfilesystemwatcher_polling.cpp
index 6920eab258..d34c8c49e8 100644
--- a/src/corelib/io/qfilesystemwatcher_polling.cpp
+++ b/src/corelib/io/qfilesystemwatcher_polling.cpp
@@ -1,53 +1,25 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemwatcher_polling_p.h"
+
+#include <QtCore/qlatin1stringview.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qtimer.h>
+#include <chrono>
+
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+static constexpr auto PollingInterval = 1s;
+
QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine(QObject *parent)
- : QFileSystemWatcherEngine(parent),
- timer(this)
+ : QFileSystemWatcherEngine(parent)
{
- connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
}
QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
@@ -64,8 +36,8 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
if (directories->contains(path))
continue;
directories->append(path);
- if (!path.endsWith(QLatin1Char('/')))
- fi = QFileInfo(path + QLatin1Char('/'));
+ if (!path.endsWith(u'/'))
+ fi = QFileInfo(path + u'/');
this->directories.insert(path, fi);
} else {
if (files->contains(path))
@@ -76,10 +48,17 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
sg.dismiss();
}
+ std::chrono::milliseconds interval = PollingInterval;
+#ifdef QT_BUILD_INTERNAL
+ if (Q_UNLIKELY(parent()->objectName().startsWith("_qt_autotest_force_engine_"_L1))) {
+ interval = 10ms; // Special case to speed up the unittests
+ }
+#endif
+
if ((!this->files.isEmpty() ||
!this->directories.isEmpty()) &&
!timer.isActive()) {
- timer.start(PollingInterval);
+ timer.start(interval, this);
}
return unhandled;
@@ -108,8 +87,11 @@ QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &path
return unhandled;
}
-void QPollingFileSystemWatcherEngine::timeout()
+void QPollingFileSystemWatcherEngine::timerEvent(QTimerEvent *e)
{
+ if (e->timerId() != timer.timerId())
+ return QFileSystemWatcherEngine::timerEvent(e);
+
for (auto it = files.begin(), end = files.end(); it != end; /*erasing*/) {
QString path = it.key();
QFileInfo fi(path);
@@ -127,8 +109,8 @@ void QPollingFileSystemWatcherEngine::timeout()
for (auto it = directories.begin(), end = directories.end(); it != end; /*erasing*/) {
QString path = it.key();
QFileInfo fi(path);
- if (!path.endsWith(QLatin1Char('/')))
- fi = QFileInfo(path + QLatin1Char('/'));
+ if (!path.endsWith(u'/'))
+ fi = QFileInfo(path + u'/');
if (!fi.exists()) {
it = directories.erase(it);
emit directoryChanged(path, true);
diff --git a/src/corelib/io/qfilesystemwatcher_polling_p.h b/src/corelib/io/qfilesystemwatcher_polling_p.h
index e60132381b..b65ff05575 100644
--- a/src/corelib/io/qfilesystemwatcher_polling_p.h
+++ b/src/corelib/io/qfilesystemwatcher_polling_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_POLLING_P_H
#define QFILESYSTEMWATCHER_POLLING_P_H
@@ -51,11 +15,11 @@
// We mean it.
//
+#include <QtCore/qbasictimer.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qmutex.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qdir.h>
-#include <QtCore/qtimer.h>
#include <QtCore/qhash.h>
#include "qfilesystemwatcher_p.h"
@@ -63,8 +27,6 @@
QT_REQUIRE_CONFIG(filesystemwatcher);
QT_BEGIN_NAMESPACE
-enum { PollingInterval = 1000 };
-
class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
{
Q_OBJECT
@@ -82,7 +44,7 @@ class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
: ownerId(fileInfo.ownerId()),
groupId(fileInfo.groupId()),
permissions(fileInfo.permissions()),
- lastModified(fileInfo.lastModified())
+ lastModified(fileInfo.lastModified(QTimeZone::UTC))
{
if (fileInfo.isDir()) {
entries = fileInfo.absoluteDir().entryList(QDir::AllEntries);
@@ -101,7 +63,7 @@ class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
return (ownerId != fileInfo.ownerId()
|| groupId != fileInfo.groupId()
|| permissions != fileInfo.permissions()
- || lastModified != fileInfo.lastModified());
+ || lastModified != fileInfo.lastModified(QTimeZone::UTC));
}
};
@@ -113,11 +75,11 @@ public:
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories) override;
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories) override;
-private Q_SLOTS:
- void timeout();
+private:
+ void timerEvent(QTimerEvent *) final;
private:
- QTimer timer;
+ QBasicTimer timer;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 9544dd7a04..5418265ba2 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemwatcher.h"
#include "qfilesystemwatcher_win_p.h"
@@ -63,6 +27,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// #define WINQFSW_DEBUG
#ifdef WINQFSW_DEBUG
# define DEBUG qDebug
@@ -75,8 +41,8 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags)
// Volume and folder paths need a trailing slash for proper notification
// (e.g. "c:" -> "c:/").
QString nativePath = QDir::toNativeSeparators(path);
- if ((flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) == 0 && !nativePath.endsWith(QLatin1Char('\\')))
- nativePath.append(QLatin1Char('\\'));
+ if ((flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) == 0 && !nativePath.endsWith(u'\\'))
+ nativePath.append(u'\\');
const HANDLE result = FindFirstChangeNotification(reinterpret_cast<const wchar_t *>(nativePath.utf16()),
FALSE, flags);
DEBUG() << __FUNCTION__ << nativePath << Qt::hex << Qt::showbase << flags << "returns" << result;
@@ -107,11 +73,7 @@ public:
// Call from QFileSystemWatcher::addPaths() to set up notifications on drives
void addPath(const QString &path);
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool nativeEventFilter(const QByteArray &, void *messageIn, qintptr *) override;
-#else
- bool nativeEventFilter(const QByteArray &, void *messageIn, long *) override;
-#endif
signals:
void driveAdded();
@@ -258,11 +220,7 @@ inline void QWindowsRemovableDriveListener::handleDbtDriveArrivalRemoval(const M
}
}
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, qintptr *)
-#else
-bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, long *)
-#endif
{
const MSG *msg = reinterpret_cast<const MSG *>(messageIn);
if (msg->message == WM_DEVICECHANGE) {
@@ -282,7 +240,7 @@ bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void
// Set up listening for WM_DEVICECHANGE+DBT_CUSTOMEVENT for a removable drive path,
void QWindowsRemovableDriveListener::addPath(const QString &p)
{
- const wchar_t drive = p.size() >= 2 && p.at(0).isLetter() && p.at(1) == QLatin1Char(':')
+ const wchar_t drive = p.size() >= 2 && p.at(0).isLetter() && p.at(1) == u':'
? wchar_t(p.at(0).toUpper().unicode()) : L'\0';
if (!drive)
return;
@@ -359,9 +317,9 @@ QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine(QObject *parent
QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
{
- for (auto *thread : qAsConst(threads))
+ for (auto *thread : std::as_const(threads))
thread->stop();
- for (auto *thread : qAsConst(threads))
+ for (auto *thread : std::as_const(threads))
thread->wait();
qDeleteAll(threads);
}
@@ -374,12 +332,8 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList unhandled;
for (const QString &path : paths) {
auto sg = qScopeGuard([&] { unhandled.push_back(path); });
- QString normalPath = path;
- if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/")))
- || (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\")))) {
- normalPath.chop(1);
- }
- QFileInfo fileInfo(normalPath);
+ QFileInfo fileInfo(path);
+ fileInfo.stat();
if (!fileInfo.exists())
continue;
@@ -392,7 +346,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
continue;
}
- DEBUG() << "Looking for a thread/handle for" << normalPath;
+ DEBUG() << "Looking for a thread/handle for" << fileInfo.path();
const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath();
const uint flags = isDir
@@ -413,7 +367,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
pathInfo = fileInfo;
// Look for a thread
- QWindowsFileSystemWatcherEngineThread *thread = 0;
+ QWindowsFileSystemWatcherEngineThread *thread = nullptr;
QWindowsFileSystemWatcherEngine::Handle handle;
QList<QWindowsFileSystemWatcherEngineThread *>::const_iterator jt, end;
end = threads.constEnd();
@@ -437,8 +391,9 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
FindCloseChangeNotification(hit.value().handle);
thread->handles[index] = hit.value().handle = fileHandle;
hit.value().flags = flags;
- thread->pathInfoForHandle.insert(fileHandle, pit.value());
+ auto value = std::move(*pit);
thread->pathInfoForHandle.erase(pit);
+ thread->pathInfoForHandle.insert(fileHandle, std::move(value));
}
}
// In addition, check on flags for sufficient notification attributes
@@ -473,7 +428,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
// now look for a thread to insert
bool found = false;
- for (QWindowsFileSystemWatcherEngineThread *thread : qAsConst(threads)) {
+ for (QWindowsFileSystemWatcherEngineThread *thread : std::as_const(threads)) {
const auto locker = qt_scoped_lock(thread->mutex);
if (thread->handles.count() < MAXIMUM_WAIT_OBJECTS) {
DEBUG() << "Added handle" << handle.handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath()
@@ -535,11 +490,8 @@ QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &path
QStringList unhandled;
for (const QString &path : paths) {
auto sg = qScopeGuard([&] { unhandled.push_back(path); });
- QString normalPath = path;
- if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
- normalPath.chop(1);
- QFileInfo fileInfo(normalPath);
- DEBUG() << "removing" << normalPath;
+ QFileInfo fileInfo(path);
+ DEBUG() << "removing" << fileInfo.path();
QString absolutePath = fileInfo.absoluteFilePath();
QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
end = threads.end();
@@ -603,7 +555,7 @@ QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &path
}
}
- threads.removeAll(0);
+ threads.removeAll(nullptr);
return unhandled;
}
@@ -626,7 +578,7 @@ QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread()
CloseHandle(handles.at(0));
handles[0] = INVALID_HANDLE_VALUE;
- for (HANDLE h : qAsConst(handles)) {
+ for (HANDLE h : std::as_const(handles)) {
if (h == INVALID_HANDLE_VALUE)
continue;
FindCloseChangeNotification(h);
@@ -637,10 +589,10 @@ Q_DECL_COLD_FUNCTION
static QString msgFindNextFailed(const QWindowsFileSystemWatcherEngineThread::PathInfoHash &pathInfos)
{
QString str;
- str += QLatin1String("QFileSystemWatcher: FindNextChangeNotification failed for");
+ str += "QFileSystemWatcher: FindNextChangeNotification failed for"_L1;
for (const QWindowsFileSystemWatcherEngine::PathInfo &pathInfo : pathInfos)
- str += QLatin1String(" \"") + QDir::toNativeSeparators(pathInfo.absolutePath) + QLatin1Char('"');
- str += QLatin1Char(' ');
+ str += " \""_L1 + QDir::toNativeSeparators(pathInfo.absolutePath) + u'"';
+ str += u' ';
return str;
}
@@ -756,3 +708,4 @@ void QWindowsFileSystemWatcherEngineThread::wakeup()
QT_END_NAMESPACE
# include "qfilesystemwatcher_win.moc"
+# include "moc_qfilesystemwatcher_win_p.cpp"
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
index 7808aff2ac..79cec00c39 100644
--- a/src/corelib/io/qfilesystemwatcher_win_p.h
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMWATCHER_WIN_P_H
#define QFILESYSTEMWATCHER_WIN_P_H
@@ -138,9 +102,12 @@ public:
bool operator==(const QFileSystemWatcherPathKey &other) const { return !compare(other, Qt::CaseInsensitive); }
};
-Q_DECLARE_TYPEINFO(QFileSystemWatcherPathKey, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QFileSystemWatcherPathKey, Q_RELOCATABLE_TYPE);
-inline size_t qHash(const QFileSystemWatcherPathKey &key) { return qHash(key.toCaseFolded()); }
+inline size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed = 0)
+{
+ return qHash(key.toCaseFolded(), seed);
+}
class QWindowsFileSystemWatcherEngineThread : public QThread
{
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 1a1a9076c7..f49106edd4 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfsfileengine_p.h"
#include "qfsfileengine_iterator_p.h"
#include "qfilesystemengine_p.h"
#include "qdatetime.h"
-#include "qdiriterator.h"
#include "qset.h"
#include <QtCore/qdebug.h>
@@ -54,12 +17,14 @@
#endif
#include <stdio.h>
#include <stdlib.h>
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
# include <private/qcore_mac_p.h>
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#ifdef Q_OS_WIN
# ifndef S_ISREG
# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
@@ -173,14 +138,14 @@ ProcessOpenModeResult processOpenModeFlags(QIODevice::OpenMode openMode)
result.ok = false;
if ((openMode & QFile::NewOnly) && (openMode & QFile::ExistingOnly)) {
qWarning("NewOnly and ExistingOnly are mutually exclusive");
- result.error = QLatin1String("NewOnly and ExistingOnly are mutually exclusive");
+ result.error = "NewOnly and ExistingOnly are mutually exclusive"_L1;
return result;
}
if ((openMode & QFile::ExistingOnly) && !(openMode & (QFile::ReadOnly | QFile::WriteOnly))) {
qWarning("ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite");
- result.error = QLatin1String(
- "ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite");
+ result.error =
+ "ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite"_L1;
return result;
}
@@ -226,7 +191,8 @@ void QFSFileEngine::setFileName(const QString &file)
/*!
\reimp
*/
-bool QFSFileEngine::open(QIODevice::OpenMode openMode)
+bool QFSFileEngine::open(QIODevice::OpenMode openMode,
+ std::optional<QFile::Permissions> permissions)
{
Q_ASSERT_X(openMode & QIODevice::Unbuffered, "QFSFileEngine::open",
"QFSFileEngine no longer supports buffered mode; upper layer must buffer");
@@ -234,7 +200,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode)
Q_D(QFSFileEngine);
if (d->fileEntry.isEmpty()) {
qWarning("QFSFileEngine::open: No file name specified");
- setError(QFile::OpenError, QLatin1String("No file name specified"));
+ setError(QFile::OpenError, "No file name specified"_L1);
return false;
}
@@ -250,7 +216,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode)
d->fh = nullptr;
d->fd = -1;
- return d->nativeOpen(d->openMode);
+ return d->nativeOpen(d->openMode, permissions);
}
/*!
@@ -277,7 +243,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHand
d->openMode = res.openMode;
d->lastFlushFailed = false;
- d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
+ d->closeFileHandle = handleFlags.testAnyFlag(QFile::AutoCloseHandle);
d->fileEntry.clear();
d->tried_stat = 0;
d->fd = -1;
@@ -306,7 +272,7 @@ bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
if (ret != 0) {
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
- QSystemError::stdString());
+ QSystemError::stdString(errno));
this->openMode = QIODevice::NotOpen;
this->fh = nullptr;
@@ -339,7 +305,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle
d->openMode = res.openMode;
d->lastFlushFailed = false;
- d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
+ d->closeFileHandle = handleFlags.testAnyFlag(QFile::AutoCloseHandle);
d->fileEntry.clear();
d->fh = nullptr;
d->fd = -1;
@@ -361,14 +327,14 @@ bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
// Seek to the end when in Append mode.
if (openMode & QFile::Append) {
- int ret;
+ QT_OFF_T ret;
do {
ret = QT_LSEEK(fd, 0, SEEK_END);
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
- QSystemError::stdString());
+ QSystemError::stdString(errno));
this->openMode = QIODevice::NotOpen;
this->fd = -1;
@@ -427,7 +393,7 @@ bool QFSFileEnginePrivate::closeFdFh()
if (!flushed || !closed) {
if (flushed) {
// If not flushed, we want the flush error to fall through.
- q->setError(QFile::UnspecifiedError, QSystemError::stdString());
+ q->setError(QFile::UnspecifiedError, QSystemError::stdString(errno));
}
return false;
}
@@ -479,7 +445,7 @@ bool QFSFileEnginePrivate::flushFh()
if (ret != 0) {
q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
- QSystemError::stdString());
+ QSystemError::stdString(errno));
return false;
}
return true;
@@ -501,7 +467,7 @@ void QFSFileEnginePrivate::unmapAll()
{
if (!maps.isEmpty()) {
const QList<uchar*> keys = maps.keys(); // Make a copy since unmap() modifies the map.
- for (int i = 0; i < keys.count(); ++i)
+ for (int i = 0; i < keys.size(); ++i)
unmap(keys.at(i));
}
}
@@ -554,11 +520,11 @@ bool QFSFileEngine::seek(qint64 pos)
/*!
\reimp
*/
-QDateTime QFSFileEngine::fileTime(FileTime time) const
+QDateTime QFSFileEngine::fileTime(QFile::FileTime time) const
{
Q_D(const QFSFileEngine);
- if (time == AccessTime) {
+ if (time == QFile::FileAccessTime) {
// always refresh for the access time
d->metaData.clearFlags(QFileSystemMetaData::AccessTime);
}
@@ -594,14 +560,14 @@ bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
} while (ret != 0 && errno == EINTR);
if (ret != 0) {
- q->setError(QFile::ReadError, QSystemError::stdString());
+ q->setError(QFile::ReadError, QSystemError::stdString(errno));
return false;
}
} else {
// Unbuffered stdio mode.
if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
+ q->setError(QFile::PositionError, QSystemError::stdString(errno));
qWarning("QFile::at: Cannot set file position %lld", pos);
- q->setError(QFile::PositionError, QSystemError::stdString());
return false;
}
}
@@ -654,17 +620,15 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
// Buffered stdlib mode.
size_t result;
- bool retry = true;
do {
result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
- eof = feof(fh);
- if (retry && eof && result == 0) {
+ eof = feof(fh); // Doesn't change errno
+ if (eof && result == 0) {
// On OS X, this is needed, e.g., if a file was written to
// through another stream since our last read. See test
// tst_QFile::appendAndRead
QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream.
- retry = false;
- continue;
+ break;
}
readBytes += result;
} while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
@@ -684,12 +648,13 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
result = QT_READ(fd, data + readBytes, chunkSize);
} while (result > 0 && (readBytes += result) < len);
- eof = !(result == -1);
+ // QT_READ (::read()) returns 0 to indicate end-of-file
+ eof = result == 0;
}
if (!eof && readBytes == 0) {
readBytes = -1;
- q->setError(QFile::ReadError, QSystemError::stdString());
+ q->setError(QFile::ReadError, QSystemError::stdString(errno));
}
return readBytes;
@@ -734,8 +699,8 @@ qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen)
// does the same, so we'd get two '\0' at the end - passing maxlen + 1
// solves this.
if (!fgets(data, int(maxlen + 1), fh)) {
- if (!feof(fh))
- q->setError(QFile::ReadError, QSystemError::stdString());
+ if (!feof(fh)) // Doesn't change errno
+ q->setError(QFile::ReadError, QSystemError::stdString(errno));
return -1; // error
}
@@ -812,7 +777,8 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
if (len && writtenBytes == 0) {
writtenBytes = -1;
- q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, QSystemError::stdString());
+ q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
+ QSystemError::stdString(errno));
} else {
// reset the cached size, if any
metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
@@ -825,18 +791,13 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
/*!
\internal
*/
-QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
+QAbstractFileEngine::IteratorUniquePtr
+QFSFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames)
{
- return new QFSFileEngineIterator(filters, filterNames);
+ return std::make_unique<QFSFileEngineIterator>(path, filters, filterNames);
}
-/*!
- \internal
-*/
-QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
-{
- return nullptr;
-}
#endif // QT_NO_FILESYSTEMITERATOR
/*!
@@ -939,7 +900,7 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
\reimp
*/
-/*! \fn bool QFSFileEngine::setFileTime(const QDateTime &newDate, QAbstractFileEngine::FileTime time)
+/*! \fn bool QFSFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
\reimp
*/
@@ -981,7 +942,10 @@ QString QFSFileEngine::tempPath()
Creates a link from the file currently specified by fileName() to
\a newName. What a link is depends on the underlying filesystem
(be it a shortcut on Windows or a symbolic link on Unix). Returns
- true if successful; otherwise returns \c false.
+ \c true if successful; otherwise returns \c false.
+
+ \note On Windows \a newName is expected to end with .lnk as the filename
+ extension.
*/
@@ -1026,37 +990,42 @@ bool QFSFileEngine::remove()
return ret;
}
-/*!
- \reimp
+/*
+ An alternative to setFileName() when you have already constructed
+ a QFileSystemEntry.
*/
-bool QFSFileEngine::rename(const QString &newName)
+void QFSFileEngine::setFileEntry(QFileSystemEntry &&entry)
{
Q_D(QFSFileEngine);
- QSystemError error;
- bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
- if (!ret)
- setError(QFile::RenameError, error.toString());
- return ret;
+ d->init();
+ d->fileEntry = std::move(entry);
}
-/*!
- \reimp
-*/
-bool QFSFileEngine::renameOverwrite(const QString &newName)
+
+bool QFSFileEngine::rename_helper(const QString &newName, RenameMode mode)
{
Q_D(QFSFileEngine);
+
+ auto func = mode == Rename ? QFileSystemEngine::renameFile
+ : QFileSystemEngine::renameOverwriteFile;
QSystemError error;
- bool ret = QFileSystemEngine::renameOverwriteFile(d->fileEntry, QFileSystemEntry(newName), error);
- if (!ret)
+ auto newEntry = QFileSystemEntry(newName);
+ const bool ret = func(d->fileEntry, newEntry, error);
+ if (!ret) {
setError(QFile::RenameError, error.toString());
- return ret;
+ return false;
+ }
+ setFileEntry(std::move(newEntry));
+ return true;
}
/*!
\reimp
*/
-bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
+bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories,
+ std::optional<QFile::Permissions> permissions) const
{
- return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
+ return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories,
+ permissions);
}
/*!
diff --git a/src/corelib/io/qfsfileengine_iterator.cpp b/src/corelib/io/qfsfileengine_iterator.cpp
index 2494ea856c..fb0332f7f3 100644
--- a/src/corelib/io/qfsfileengine_iterator.cpp
+++ b/src/corelib/io/qfsfileengine_iterator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfsfileengine_iterator_p.h"
#include "qfileinfo_p.h"
@@ -45,9 +9,10 @@
QT_BEGIN_NAMESPACE
-QFSFileEngineIterator::QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames)
- : QAbstractFileEngineIterator(filters, filterNames)
- , done(false)
+QFSFileEngineIterator::QFSFileEngineIterator(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames)
+ : QAbstractFileEngineIterator(path, filters, filterNames),
+ nativeIterator(new QFileSystemIterator(QFileSystemEntry(path), filters))
{
}
@@ -55,48 +20,30 @@ QFSFileEngineIterator::~QFSFileEngineIterator()
{
}
-bool QFSFileEngineIterator::hasNext() const
+bool QFSFileEngineIterator::advance()
{
- if (!done && !nativeIterator) {
- nativeIterator.reset(new QFileSystemIterator(QFileSystemEntry(path()),
- filters(), nameFilters()));
- advance();
- }
-
- return !done;
-}
-
-QString QFSFileEngineIterator::next()
-{
- if (!hasNext())
- return QString();
-
- advance();
- return currentFilePath();
-}
-
-void QFSFileEngineIterator::advance() const
-{
- currentInfo = nextInfo;
+ if (!nativeIterator)
+ return false;
QFileSystemEntry entry;
QFileSystemMetaData data;
if (nativeIterator->advance(entry, data)) {
- nextInfo = QFileInfo(new QFileInfoPrivate(entry, data));
+ m_fileInfo = QFileInfo(new QFileInfoPrivate(entry, data));
+ return true;
} else {
- done = true;
nativeIterator.reset();
+ return false;
}
}
QString QFSFileEngineIterator::currentFileName() const
{
- return currentInfo.fileName();
+ return m_fileInfo.fileName();
}
QFileInfo QFSFileEngineIterator::currentFileInfo() const
{
- return currentInfo;
+ return m_fileInfo;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfsfileengine_iterator_p.h b/src/corelib/io/qfsfileengine_iterator_p.h
index bde00bf578..b91c5d9973 100644
--- a/src/corelib/io/qfsfileengine_iterator_p.h
+++ b/src/corelib/io/qfsfileengine_iterator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFSFILEENGINE_ITERATOR_P_H
#define QFSFILEENGINE_ITERATOR_P_H
@@ -59,27 +23,19 @@
QT_BEGIN_NAMESPACE
-class QFSFileEngineIteratorPrivate;
-class QFSFileEngineIteratorPlatformSpecificData;
-
class QFSFileEngineIterator : public QAbstractFileEngineIterator
{
public:
- QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames);
+ QFSFileEngineIterator(const QString &path, QDir::Filters filters, const QStringList &filterNames);
~QFSFileEngineIterator();
- QString next() override;
- bool hasNext() const override;
+ bool advance() override;
QString currentFileName() const override;
QFileInfo currentFileInfo() const override;
private:
- void advance() const;
mutable QScopedPointer<QFileSystemIterator> nativeIterator;
- mutable QFileInfo currentInfo;
- mutable QFileInfo nextInfo;
- mutable bool done;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 639c01571a..dfc40e20b6 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFSFILEENGINE_P_H
#define QFSFILEENGINE_P_H
@@ -57,11 +21,18 @@
#include <QtCore/private/qfilesystemmetadata_p.h>
#include <qhash.h>
+#include <optional>
+
+#ifdef Q_OS_UNIX
+#include <sys/types.h> // for mode_t
+#endif
+
#ifndef QT_NO_FSFILEENGINE
QT_BEGIN_NAMESPACE
-struct ProcessOpenModeResult {
+struct ProcessOpenModeResult
+{
bool ok;
QIODevice::OpenMode openMode;
QString error;
@@ -78,7 +49,7 @@ public:
explicit QFSFileEngine(const QString &file);
~QFSFileEngine();
- bool open(QIODevice::OpenMode openMode) override;
+ bool open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions) override;
bool open(QIODevice::OpenMode flags, FILE *fh);
bool close() override;
bool flush() override;
@@ -89,10 +60,15 @@ public:
bool isSequential() const override;
bool remove() override;
bool copy(const QString &newName) override;
- bool rename(const QString &newName) override;
- bool renameOverwrite(const QString &newName) override;
+
+ bool rename(const QString &newName) override
+ { return rename_helper(newName, Rename); }
+ bool renameOverwrite(const QString &newName) override
+ { return rename_helper(newName, RenameOverwrite); }
+
bool link(const QString &newName) override;
- bool mkdir(const QString &dirName, bool createParentDirectories) const override;
+ bool mkdir(const QString &dirName, bool createParentDirectories,
+ std::optional<QFile::Permissions> permissions) const override;
bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
bool setSize(qint64 size) override;
bool caseSensitive() const override;
@@ -104,14 +80,15 @@ public:
QString fileName(FileName file) const override;
uint ownerId(FileOwner) const override;
QString owner(FileOwner) const override;
- bool setFileTime(const QDateTime &newDate, FileTime time) override;
- QDateTime fileTime(FileTime time) const override;
+ bool setFileTime(const QDateTime &newDate, QFile::FileTime time) override;
+ QDateTime fileTime(QFile::FileTime time) const override;
void setFileName(const QString &file) override;
+ void setFileEntry(QFileSystemEntry &&entry);
int handle() const override;
#ifndef QT_NO_FILESYSTEMITERATOR
- Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
- Iterator *endEntryList() override;
+ IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames) override;
#endif
qint64 read(char *data, qint64 maxlen) override;
@@ -138,6 +115,10 @@ public:
protected:
QFSFileEngine(QFSFileEnginePrivate &dd);
+
+private:
+ enum RenameMode : int { Rename, RenameOverwrite };
+ bool rename_helper(const QString &newName, RenameMode mode);
};
class Q_AUTOTEST_EXPORT QFSFileEnginePrivate : public QAbstractFileEnginePrivate
@@ -152,7 +133,7 @@ public:
QFileSystemEntry fileEntry;
QIODevice::OpenMode openMode;
- bool nativeOpen(QIODevice::OpenMode openMode);
+ bool nativeOpen(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions);
bool openFh(QIODevice::OpenMode flags, FILE *fh);
bool openFd(QIODevice::OpenMode flags, int fd);
bool nativeClose();
@@ -179,6 +160,9 @@ public:
#ifndef Q_OS_WIN
bool isSequentialFdFh() const;
#endif
+#ifdef Q_OS_WIN
+ bool nativeRenameOverwrite(const QFileSystemEntry &newEntry);
+#endif
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr);
@@ -196,7 +180,11 @@ public:
mutable int cachedFd;
mutable DWORD fileAttrib;
#else
- QHash<uchar *, QPair<int /*offset % PageSize*/, size_t /*length + offset % PageSize*/> > maps;
+ struct StartAndLength {
+ int start; // offset % PageSize
+ size_t length; // length + offset % PageSize
+ };
+ QHash<uchar *, StartAndLength> maps;
#endif
int fd;
@@ -238,6 +226,10 @@ protected:
void init();
QAbstractFileEngine::FileFlags getPermissions(QAbstractFileEngine::FileFlags type) const;
+
+#ifdef Q_OS_UNIX
+ bool nativeOpenImpl(QIODevice::OpenMode openMode, mode_t mode);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 4610e9306c..5806689182 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "private/qabstractfileengine_p.h"
+#include "private/qfiledevice_p.h"
#include "private/qfsfileengine_p.h"
#include "private/qcore_unix_p.h"
#include "qfilesystementry_p.h"
@@ -56,7 +21,7 @@
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
-#if !defined(QWS) && defined(Q_OS_MAC)
+#if defined(Q_OS_MACOS)
# include <private/qcore_mac_p.h>
#endif
@@ -100,14 +65,23 @@ static inline QString msgOpenDirectory()
#if QT_CONFIG(translation)
return QIODevice::tr(message);
#else
- return QLatin1String(message);
+ return QLatin1StringView(message);
#endif
}
/*!
\internal
*/
-bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
+bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode,
+ std::optional<QFile::Permissions> permissions)
+{
+ return nativeOpenImpl(openMode, permissions ? QtPrivate::toMode_t(*permissions) : 0666);
+}
+
+/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::nativeOpenImpl(QIODevice::OpenMode openMode, mode_t mode)
{
Q_Q(QFSFileEngine);
@@ -118,7 +92,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
// Try to open the file in unbuffered mode.
do {
- fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666);
+ fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, mode);
} while (fd == -1 && errno == EINTR);
// On failure, return and report the error.
@@ -141,14 +115,14 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
// Seek to the end when in Append mode.
if (flags & QFile::Append) {
- int ret;
+ QT_OFF_T ret;
do {
ret = QT_LSEEK(fd, 0, SEEK_END);
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
- qt_error_string(int(errno)));
+ qt_error_string(errno));
return false;
}
}
@@ -186,9 +160,9 @@ bool QFSFileEnginePrivate::nativeSyncToDisk()
Q_Q(QFSFileEngine);
int ret;
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
- EINTR_LOOP(ret, fdatasync(nativeHandle()));
+ QT_EINTR_LOOP(ret, fdatasync(nativeHandle()));
#else
- EINTR_LOOP(ret, fsync(nativeHandle()));
+ QT_EINTR_LOOP(ret, fsync(nativeHandle()));
#endif
if (ret != 0)
q->setError(QFile::WriteError, qt_error_string(errno));
@@ -247,7 +221,7 @@ qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len)
}
if (readBytes == 0 && !feof(fh)) {
// if we didn't read anything and we're not at EOF, it must be an error
- q->setError(QFile::ReadError, qt_error_string(int(errno)));
+ q->setError(QFile::ReadError, qt_error_string(errno));
return -1;
}
return readBytes;
@@ -383,7 +357,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
{
QFileSystemMetaData::MetaDataFlags queryFlags = { };
- queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
+ queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type.toInt()))
& QFileSystemMetaData::Permissions;
if (type & TypesMask)
@@ -409,7 +383,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
return ret;
if (exists && (type & PermsMask))
- ret |= FileFlags(uint(d->metaData.permissions()));
+ ret |= FileFlags(uint(d->metaData.permissions().toInt()));
if (type & TypesMask) {
if (d->metaData.isAlias()) {
@@ -470,12 +444,20 @@ QString QFSFileEngine::fileName(FileName file) const
QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData));
return file == CanonicalPathName ? entry.path() : entry.filePath();
}
- case LinkName:
+ case AbsoluteLinkTarget:
if (d->isSymlink()) {
QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData);
return entry.filePath();
}
return QString();
+ case RawLinkPath:
+ if (d->isSymlink()) {
+ QFileSystemEntry entry = QFileSystemEngine::getRawLinkPath(d->fileEntry, d->metaData);
+ return entry.filePath();
+ }
+ return QString();
+ case JunctionName:
+ return QString();
case DefaultName:
case NFileNames:
break;
@@ -486,7 +468,8 @@ QString QFSFileEngine::fileName(FileName file) const
bool QFSFileEngine::isRelativePath() const
{
Q_D(const QFSFileEngine);
- return d->fileEntry.filePath().length() ? d->fileEntry.filePath().at(0) != QLatin1Char('/') : true;
+ const QString fp = d->fileEntry.filePath();
+ return fp.isEmpty() || fp.at(0) != u'/';
}
uint QFSFileEngine::ownerId(FileOwner own) const
@@ -512,6 +495,10 @@ bool QFSFileEngine::setPermissions(uint perms)
Q_D(QFSFileEngine);
QSystemError error;
bool ok;
+
+ // clear cached state (if any)
+ d->metaData.clearFlags(QFileSystemMetaData::Permissions);
+
if (d->fd != -1)
ok = QFileSystemEngine::setPermissions(d->fd, QFile::Permissions(perms), error);
else
@@ -538,7 +525,7 @@ bool QFSFileEngine::setSize(qint64 size)
return ret;
}
-bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
+bool QFSFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
{
Q_D(QFSFileEngine);
@@ -573,16 +560,16 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
Q_Q(QFSFileEngine);
if (openMode == QIODevice::NotOpen) {
- q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
+ q->setError(QFile::PermissionsError, qt_error_string(EACCES));
return nullptr;
}
if (offset < 0 || offset > maxFileOffset
- || size < 0 || quint64(size) > quint64(size_t(-1))) {
- q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
+ || size <= 0
+ || quint64(size) > quint64(size_t(-1))) {
+ q->setError(QFile::UnspecifiedError, qt_error_string(EINVAL));
return nullptr;
}
-
// If we know the mapping will extend beyond EOF, fail early to avoid
// undefined behavior. Otherwise, let mmap have its say.
if (doStat(QFileSystemMetaData::SizeAttribute)
@@ -607,7 +594,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
int extra = offset % pageSize;
if (quint64(size + extra) > quint64((size_t)-1)) {
- q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
+ q->setError(QFile::UnspecifiedError, qt_error_string(EINVAL));
return nullptr;
}
@@ -619,22 +606,22 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
access, sharemode, nativeHandle(), realOffset);
if (MAP_FAILED != mapAddress) {
uchar *address = extra + static_cast<uchar*>(mapAddress);
- maps[address] = QPair<int,size_t>(extra, realSize);
+ maps[address] = {extra, realSize};
return address;
}
switch(errno) {
case EBADF:
- q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
+ q->setError(QFile::PermissionsError, qt_error_string(EACCES));
break;
case ENFILE:
case ENOMEM:
- q->setError(QFile::ResourceError, qt_error_string(int(errno)));
+ q->setError(QFile::ResourceError, qt_error_string(errno));
break;
case EINVAL:
// size are out of bounds
default:
- q->setError(QFile::UnspecifiedError, qt_error_string(int(errno)));
+ q->setError(QFile::UnspecifiedError, qt_error_string(errno));
break;
}
return nullptr;
@@ -644,18 +631,19 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
{
#if !defined(Q_OS_INTEGRITY)
Q_Q(QFSFileEngine);
- if (!maps.contains(ptr)) {
+ const auto it = std::as_const(maps).find(ptr);
+ if (it == maps.cend()) {
q->setError(QFile::PermissionsError, qt_error_string(EACCES));
return false;
}
- uchar *start = ptr - maps[ptr].first;
- size_t len = maps[ptr].second;
+ uchar *start = ptr - it->start;
+ size_t len = it->length;
if (-1 == munmap(start, len)) {
q->setError(QFile::UnspecifiedError, qt_error_string(errno));
return false;
}
- maps.remove(ptr);
+ maps.erase(it);
return true;
#else
return false;
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 6b1ab5739e..4ac305f49b 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "private/qabstractfileengine_p.h"
+#include "private/qfiledevice_p.h"
#include "private/qfsfileengine_p.h"
#include "qfilesystemengine_p.h"
#include <qdebug.h>
@@ -62,17 +27,21 @@
#define SECURITY_WIN32
#include <security.h>
+#include <memory>
+
#ifndef PATH_MAX
#define PATH_MAX FILENAME_MAX
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static inline bool isUncPath(const QString &path)
{
// Starts with \\, but not \\.
- return (path.startsWith(QLatin1String("\\\\"))
- && path.size() > 2 && path.at(2) != QLatin1Char('.'));
+ return (path.startsWith("\\\\"_L1)
+ && path.size() > 2 && path.at(2) != u'.');
}
/*!
@@ -80,13 +49,13 @@ static inline bool isUncPath(const QString &path)
*/
QString QFSFileEnginePrivate::longFileName(const QString &path)
{
- if (path.startsWith(QLatin1String("\\\\.\\")))
+ if (path.startsWith("\\\\.\\"_L1))
return path;
QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path);
- QString prefix = QLatin1String("\\\\?\\");
+ QString prefix = "\\\\?\\"_L1;
if (isUncPath(absPath)) {
- prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\"
+ prefix.append("UNC\\"_L1); // "\\\\?\\UNC\\"
absPath.remove(0, 2);
}
return prefix + absPath;
@@ -95,7 +64,8 @@ QString QFSFileEnginePrivate::longFileName(const QString &path)
/*
\internal
*/
-bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
+bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode,
+ std::optional<QFile::Permissions> permissions)
{
Q_Q(QFSFileEngine);
@@ -115,11 +85,14 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
? OPEN_ALWAYS
: OPEN_EXISTING;
// Create the file handle.
- SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
+ QNativeFilePermissions nativePermissions(permissions, false);
+ if (!nativePermissions.isOk())
+ return false;
+
fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
accessRights,
shareMode,
- &securityAtts,
+ nativePermissions.securityAttributes(),
creationDisp,
FILE_ATTRIBUTE_NORMAL,
NULL);
@@ -214,7 +187,7 @@ qint64 QFSFileEnginePrivate::nativeSize() const
// ### Don't flush; for buffered files, we should get away with ftell.
thatQ->flush();
- // Always retrive the current information
+ // Always retrieve the current information
metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
bool filled = false;
if (fileHandle != INVALID_HANDLE_VALUE && openMode != QIODevice::NotOpen )
@@ -423,6 +396,35 @@ bool QFSFileEnginePrivate::nativeIsSequential() const
|| (fileType == FILE_TYPE_PIPE);
}
+bool QFSFileEnginePrivate::nativeRenameOverwrite(const QFileSystemEntry &newEntry)
+{
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ return false;
+ const QString newFilePath = newEntry.nativeFilePath();
+ const size_t nameByteLength = newFilePath.length() * sizeof(wchar_t);
+ if (nameByteLength + sizeof(wchar_t) > std::numeric_limits<DWORD>::max())
+ return false;
+
+ constexpr size_t RenameInfoSize = sizeof(FILE_RENAME_INFO);
+ const size_t renameDataSize = RenameInfoSize + nameByteLength + sizeof(wchar_t);
+ QVarLengthArray<char> v(qsizetype(renameDataSize), 0);
+
+ auto *renameInfo = q20::construct_at(reinterpret_cast<FILE_RENAME_INFO *>(v.data()));
+ auto renameInfoRAII = qScopeGuard([&] { std::destroy_at(renameInfo); });
+ renameInfo->ReplaceIfExists = TRUE;
+ renameInfo->RootDirectory = nullptr;
+ renameInfo->FileNameLength = DWORD(nameByteLength);
+ memcpy(renameInfo->FileName, newFilePath.data(), nameByteLength);
+
+ bool res = SetFileInformationByHandle(fileHandle, FileRenameInfo, renameInfo,
+ DWORD(renameDataSize));
+ if (!res) {
+ DWORD error = GetLastError();
+ q_func()->setError(QFile::RenameError, qt_error_string(int(error)));
+ }
+ return res;
+}
+
bool QFSFileEngine::caseSensitive() const
{
return false;
@@ -433,7 +435,7 @@ QString QFSFileEngine::currentPath(const QString &fileName)
QString ret;
//if filename is a drive: then get the pwd of that drive
if (fileName.length() >= 2 &&
- fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':')) {
+ fileName.at(0).isLetter() && fileName.at(1) == u':') {
int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1;
if (_getdrive() != drv) {
wchar_t buf[PATH_MAX];
@@ -445,7 +447,7 @@ QString QFSFileEngine::currentPath(const QString &fileName)
//just the pwd
ret = QFileSystemEngine::currentPath().filePath();
}
- if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
+ if (ret.length() >= 2 && ret[1] == u':')
ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
return ret;
}
@@ -494,52 +496,14 @@ bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) cons
return metaData.exists();
}
-
+// ### assume that they add .lnk to newName
bool QFSFileEngine::link(const QString &newName)
{
- bool ret = false;
-
- QString linkName = newName;
- //### assume that they add .lnk
-
- IShellLink *psl;
- bool neededCoInit = false;
-
- HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
- reinterpret_cast<void **>(&psl));
-
- if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
- neededCoInit = true;
- CoInitialize(nullptr);
- hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
- reinterpret_cast<void **>(&psl));
- }
-
- if (SUCCEEDED(hres)) {
- const QString nativeAbsoluteName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\'));
- hres = psl->SetPath(reinterpret_cast<const wchar_t *>(nativeAbsoluteName.utf16()));
- if (SUCCEEDED(hres)) {
- const QString nativeAbsolutePathName = fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\'));
- hres = psl->SetWorkingDirectory(reinterpret_cast<const wchar_t *>(nativeAbsolutePathName.utf16()));
- if (SUCCEEDED(hres)) {
- IPersistFile *ppf;
- hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void **>(&ppf));
- if (SUCCEEDED(hres)) {
- hres = ppf->Save(reinterpret_cast<const wchar_t *>(linkName.utf16()), TRUE);
- if (SUCCEEDED(hres))
- ret = true;
- ppf->Release();
- }
- }
- }
- psl->Release();
- }
+ QSystemError error;
+ bool ret = QFileSystemEngine::createLink(QFileSystemEntry(fileName(AbsoluteName)),
+ QFileSystemEntry(newName), error);
if (!ret)
- setError(QFile::RenameError, qt_error_string());
-
- if (neededCoInit)
- CoUninitialize();
-
+ setError(QFile::RenameError, error.toString());
return ret;
}
@@ -562,7 +526,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
{
QFileSystemMetaData::MetaDataFlags queryFlags;
- queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
+ queryFlags |= QFileSystemMetaData::MetaDataFlags::fromInt(type.toInt())
& QFileSystemMetaData::Permissions;
// AliasType and BundleType are 0x0
@@ -583,7 +547,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
}
if (exists && (type & PermsMask))
- ret |= FileFlags(uint(d->metaData.permissions()));
+ ret |= FileFlags::fromInt(d->metaData.permissions().toInt());
if (type & TypesMask) {
if ((type & LinkType) && d->metaData.isLegacyLink())
@@ -629,62 +593,74 @@ QByteArray QFSFileEngine::id() const
QString QFSFileEngine::fileName(FileName file) const
{
Q_D(const QFSFileEngine);
- if (file == BaseName) {
+ switch (file) {
+ case BaseName:
return d->fileEntry.fileName();
- } else if (file == PathName) {
+ case PathName:
return d->fileEntry.path();
- } else if (file == AbsoluteName || file == AbsolutePathName) {
- QString ret;
-
- if (!isRelativePath()) {
- if (d->fileEntry.filePath().startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt
- d->fileEntry.filePath().size() == 2 || // It's a drive letter that needs to get a working dir appended
- (d->fileEntry.filePath().size() > 2 && d->fileEntry.filePath().at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
- d->fileEntry.filePath().contains(QLatin1String("/../")) || d->fileEntry.filePath().contains(QLatin1String("/./")) ||
- d->fileEntry.filePath().endsWith(QLatin1String("/..")) || d->fileEntry.filePath().endsWith(QLatin1String("/.")))
- {
- ret = QDir::fromNativeSeparators(QFileSystemEngine::nativeAbsoluteFilePath(d->fileEntry.filePath()));
- } else {
- ret = d->fileEntry.filePath();
- }
- } else {
- ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->fileEntry.filePath());
+ case AbsoluteName:
+ case AbsolutePathName: {
+ QString ret = d->fileEntry.filePath();
+ if (isRelativePath()) {
+ ret = QDir::cleanPath(QDir::currentPath() + u'/' + ret);
+ } else if (ret.startsWith(u'/') // absolute path to the current drive, so \a.txt -> Z:\a.txt
+ || ret.size() == 2 // or a drive letter that needs to get a working dir appended
+ // or a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
+ || (ret.size() > 2 && ret.at(2) != u'/')
+ || ret.contains(QStringView(u"/../"))
+ || ret.contains(QStringView(u"/./"))
+ || ret.endsWith(QStringView(u"/.."))
+ || ret.endsWith(QStringView(u"/."))) {
+ ret = QDir::fromNativeSeparators(QFileSystemEngine::nativeAbsoluteFilePath(ret));
}
// The path should be absolute at this point.
// From the docs :
// Absolute paths begin with the directory separator "/"
// (optionally preceded by a drive specification under Windows).
- if (ret.at(0) != QLatin1Char('/')) {
+ if (ret.at(0) != u'/') {
Q_ASSERT(ret.length() >= 2);
Q_ASSERT(ret.at(0).isLetter());
- Q_ASSERT(ret.at(1) == QLatin1Char(':'));
+ Q_ASSERT(ret.at(1) == u':');
// Force uppercase drive letters.
ret[0] = ret.at(0).toUpper();
}
if (file == AbsolutePathName) {
- int slash = ret.lastIndexOf(QLatin1Char('/'));
+ int slash = ret.lastIndexOf(u'/');
if (slash < 0)
return ret;
- if (ret.at(0) != QLatin1Char('/') && slash == 2)
+ if (ret.at(0) != u'/' && slash == 2)
return ret.left(3); // include the slash
return ret.left(slash > 0 ? slash : 1);
}
return ret;
- } else if (file == CanonicalName || file == CanonicalPathName) {
+ }
+ case CanonicalName:
+ case CanonicalPathName: {
if (!(fileFlags(ExistsFlag) & ExistsFlag))
return QString();
- QFileSystemEntry entry(QFileSystemEngine::canonicalName(QFileSystemEntry(fileName(AbsoluteName)), d->metaData));
+ const QFileSystemEntry entry =
+ QFileSystemEngine::canonicalName(QFileSystemEntry(fileName(AbsoluteName)), d->metaData);
if (file == CanonicalPathName)
return entry.path();
return entry.filePath();
- } else if (file == LinkName) {
+ }
+ case AbsoluteLinkTarget:
return QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData).filePath();
- } else if (file == BundleName) {
+ case RawLinkPath:
+ return QFileSystemEngine::getRawLinkPath(d->fileEntry, d->metaData).filePath();
+ case BundleName:
return QString();
+ case JunctionName:
+ return QFileSystemEngine::getJunctionTarget(d->fileEntry, d->metaData).filePath();
+ case DefaultName:
+ break;
+ case NFileNames:
+ Q_ASSERT(false);
+ break;
}
return d->fileEntry.filePath();
}
@@ -712,6 +688,10 @@ bool QFSFileEngine::setPermissions(uint perms)
{
Q_D(QFSFileEngine);
QSystemError error;
+
+ // clear cached state (if any)
+ d->metaData.clearFlags(QFileSystemMetaData::Permissions);
+
bool ret = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error);
if (!ret)
setError(QFile::PermissionsError, error.toString());
@@ -757,7 +737,7 @@ bool QFSFileEngine::setSize(qint64 size)
return false;
}
-bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
+bool QFSFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
{
Q_D(QFSFileEngine);
@@ -766,7 +746,7 @@ bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
return false;
}
- if (!newDate.isValid() || time == QAbstractFileEngine::MetadataChangeTime) {
+ if (!newDate.isValid() || time == QFile::FileMetadataChangeTime) {
setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
return false;
}
@@ -842,7 +822,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
NULL);
// Since this is a special case, we check if the return value was NULL and if so
// we change it to INVALID_HANDLE_VALUE to follow the logic inside this function.
- if(0 == handle)
+ if (!handle)
handle = INVALID_HANDLE_VALUE;
#endif
@@ -899,17 +879,18 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
bool QFSFileEnginePrivate::unmap(uchar *ptr)
{
Q_Q(QFSFileEngine);
- if (!maps.contains(ptr)) {
+ const auto it = std::as_const(maps).find(ptr);
+ if (it == maps.cend()) {
q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
return false;
}
- uchar *start = ptr - maps[ptr];
+ uchar *start = ptr - *it;
if (!UnmapViewOfFile(start)) {
q->setError(QFile::PermissionsError, qt_error_string());
return false;
}
- maps.remove(ptr);
+ maps.erase(it);
if (maps.isEmpty()) {
::CloseHandle(mapHandle);
mapHandle = NULL;
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index cc1d110252..b0029e2af7 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QIODEVICE_DEBUG
@@ -45,48 +9,42 @@
#include "qfile.h"
#include "qstringlist.h"
#include "qdir.h"
-#include "private/qbytearray_p.h"
+#include "private/qtools_p.h"
#include <algorithm>
-#ifdef QIODEVICE_DEBUG
-# include <ctype.h>
-#endif
-
QT_BEGIN_NAMESPACE
-#ifdef QIODEVICE_DEBUG
-void debugBinaryString(const QByteArray &input)
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
+[[maybe_unused]]
+static void debugBinaryString(const char *input, qint64 maxlen)
{
QByteArray tmp;
- int startOffset = 0;
- for (int i = 0; i < input.size(); ++i) {
+ qlonglong startOffset = 0;
+ for (qint64 i = 0; i < maxlen; ++i) {
tmp += input[i];
- if ((i % 16) == 15 || i == (input.size() - 1)) {
- printf("\n%15d:", startOffset);
+ if ((i % 16) == 15 || i == (maxlen - 1)) {
+ printf("\n%15lld:", startOffset);
startOffset += tmp.size();
- for (int j = 0; j < tmp.size(); ++j)
+ for (qsizetype j = 0; j < tmp.size(); ++j)
printf(" %02x", int(uchar(tmp[j])));
- for (int j = tmp.size(); j < 16 + 1; ++j)
+ for (qsizetype j = tmp.size(); j < 16 + 1; ++j)
printf(" ");
- for (int j = 0; j < tmp.size(); ++j)
- printf("%c", isprint(int(uchar(tmp[j]))) ? tmp[j] : '.');
+ for (qsizetype j = 0; j < tmp.size(); ++j)
+ printf("%c", isAsciiPrintable(tmp[j]) ? tmp[j] : '.');
tmp.clear();
}
}
printf("\n\n");
}
-void debugBinaryString(const char *data, qint64 maxlen)
-{
- debugBinaryString(QByteArray(data, maxlen));
-}
-#endif
-
#define Q_VOID
+Q_DECL_COLD_FUNCTION
static void checkWarnMessage(const QIODevice *device, const char *function, const char *what)
{
#ifndef QT_NO_WARNING_OUTPUT
@@ -102,7 +60,7 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons
d << ", \"" << QDir::toNativeSeparators(f->fileName()) << '"';
d << ')';
#else
- Q_UNUSED(device)
+ Q_UNUSED(device);
#endif // !QT_NO_QOBJECT
d << ": " << what;
#else
@@ -120,11 +78,19 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons
} \
} while (0)
+#define CHECK_LINEMAXLEN(function, returnType) \
+ do { \
+ if (maxSize < 2) { \
+ checkWarnMessage(this, #function, "Called with maxSize < 2"); \
+ return returnType; \
+ } \
+ } while (0)
+
#define CHECK_MAXBYTEARRAYSIZE(function) \
do { \
- if (maxSize >= MaxByteArraySize) { \
+ if (maxSize >= QByteArray::max_size()) { \
checkWarnMessage(this, #function, "maxSize argument exceeds QByteArray size limit"); \
- maxSize = MaxByteArraySize - 1; \
+ maxSize = QByteArray::max_size() - 1; \
} \
} while (0)
@@ -156,21 +122,6 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons
\internal
*/
QIODevicePrivate::QIODevicePrivate()
- : openMode(QIODevice::NotOpen),
- pos(0), devicePos(0),
- readChannelCount(0),
- writeChannelCount(0),
- currentReadChannel(0),
- currentWriteChannel(0),
- readBufferChunkSize(QIODEVICE_BUFFERSIZE),
- writeBufferChunkSize(0),
- transactionPos(0),
- transactionStarted(false)
- , baseReadLineDataCalled(false)
- , accessMode(Unset)
-#ifdef QT_NO_QOBJECT
- , q_ptr(nullptr)
-#endif
{
}
@@ -305,10 +256,18 @@ QIODevicePrivate::~QIODevicePrivate()
*/
/*!
- \enum QIODevice::OpenModeFlag
+ \class QIODeviceBase
+ \inheaderfile QIODevice
+ \inmodule QtCore
+ \brief Base class for QIODevice that provides flags describing the mode in
+ which a device is opened.
+*/
- This enum is used with open() to describe the mode in which a device
- is opened. It is also returned by openMode().
+/*!
+ \enum QIODeviceBase::OpenModeFlag
+
+ This enum is used with QIODevice::open() to describe the mode in which a
+ device is opened. It is also returned by QIODevice::openMode().
\value NotOpen The device is not open.
\value ReadOnly The device is open for reading.
@@ -534,7 +493,7 @@ bool QIODevice::isSequential() const
\sa OpenMode
*/
-QIODevice::OpenMode QIODevice::openMode() const
+QIODeviceBase::OpenMode QIODevice::openMode() const
{
return d_func()->openMode;
}
@@ -546,11 +505,11 @@ QIODevice::OpenMode QIODevice::openMode() const
\sa openMode(), OpenMode
*/
-void QIODevice::setOpenMode(OpenMode openMode)
+void QIODevice::setOpenMode(QIODeviceBase::OpenMode openMode)
{
Q_D(QIODevice);
#if defined QIODEVICE_DEBUG
- printf("%p QIODevice::setOpenMode(0x%x)\n", this, int(openMode));
+ printf("%p QIODevice::setOpenMode(0x%x)\n", this, openMode.toInt());
#endif
d->openMode = openMode;
d->accessMode = QIODevicePrivate::Unset;
@@ -587,7 +546,7 @@ void QIODevice::setTextModeEnabled(bool enabled)
*/
bool QIODevice::isTextModeEnabled() const
{
- return d_func()->openMode & Text;
+ return d_func()->openMode.testAnyFlag(Text);
}
/*!
@@ -596,7 +555,7 @@ bool QIODevice::isTextModeEnabled() const
default, this function returns \c false if openMode() returns
\c NotOpen.
- \sa openMode(), OpenMode
+ \sa openMode(), QIODeviceBase::OpenMode
*/
bool QIODevice::isOpen() const
{
@@ -702,8 +661,18 @@ void QIODevice::setCurrentReadChannel(int channel)
void QIODevicePrivate::setReadChannelCount(int count)
{
if (count > readBuffers.size()) {
- readBuffers.insert(readBuffers.end(), count - readBuffers.size(),
- QRingBuffer(readBufferChunkSize));
+ readBuffers.reserve(count);
+
+ // If readBufferChunkSize is zero, we should bypass QIODevice's
+ // read buffers, even if the QIODeviceBase::Unbuffered flag is not
+ // set when opened. However, if a read transaction is started or
+ // ungetChar() is called, we still have to use the internal buffer.
+ // To support these cases, pass a default value to the QRingBuffer
+ // constructor.
+
+ while (readBuffers.size() < count)
+ readBuffers.emplace_back(readBufferChunkSize != 0 ? readBufferChunkSize
+ : QIODEVICE_BUFFERSIZE);
} else {
readBuffers.resize(count);
}
@@ -754,8 +723,9 @@ void QIODevicePrivate::setWriteChannelCount(int count)
// If writeBufferChunkSize is zero (default value), we don't use
// QIODevice's write buffers.
if (writeBufferChunkSize != 0) {
- writeBuffers.insert(writeBuffers.end(), count - writeBuffers.size(),
- QRingBuffer(writeBufferChunkSize));
+ writeBuffers.reserve(count);
+ while (writeBuffers.size() < count)
+ writeBuffers.emplace_back(writeBufferChunkSize);
}
} else {
writeBuffers.resize(count);
@@ -781,9 +751,9 @@ bool QIODevicePrivate::allWriteBuffersEmpty() const
otherwise returns \c false. This function should be called from any
reimplementations of open() or other functions that open the device.
- \sa openMode(), OpenMode
+ \sa openMode(), QIODeviceBase::OpenMode
*/
-bool QIODevice::open(OpenMode mode)
+bool QIODevice::open(QIODeviceBase::OpenMode mode)
{
Q_D(QIODevice);
d->openMode = mode;
@@ -795,7 +765,7 @@ bool QIODevice::open(OpenMode mode)
d->setWriteChannelCount(isWritable() ? 1 : 0);
d->errorString.clear();
#if defined QIODEVICE_DEBUG
- printf("%p QIODevice::open(0x%x)\n", this, quint32(mode));
+ printf("%p QIODevice::open(0x%x)\n", this, mode.toInt());
#endif
return true;
}
@@ -804,7 +774,7 @@ bool QIODevice::open(OpenMode mode)
First emits aboutToClose(), then closes the device and sets its
OpenMode to NotOpen. The error string is also reset.
- \sa setOpenMode(), OpenMode
+ \sa setOpenMode(), QIODeviceBase::OpenMode
*/
void QIODevice::close()
{
@@ -861,7 +831,7 @@ qint64 QIODevice::pos() const
*/
qint64 QIODevice::size() const
{
- return d_func()->isSequential() ? bytesAvailable() : qint64(0);
+ return d_func()->isSequential() ? bytesAvailable() : qint64(0);
}
/*!
@@ -944,7 +914,7 @@ bool QIODevice::atEnd() const
&& bytesAvailable() == 0));
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %lld\n", this,
- result ? "true" : "false", int(d->openMode), d->pos);
+ result ? "true" : "false", d->openMode.toInt(), d->pos);
#endif
return result;
}
@@ -1018,12 +988,12 @@ qint64 QIODevice::bytesToWrite() const
qint64 QIODevice::read(char *data, qint64 maxSize)
{
Q_D(QIODevice);
-
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, data, maxSize, d->pos, d->buffer.size());
#endif
+ CHECK_READABLE(read, qint64(-1));
const bool sequential = d->isSequential();
// Short-cut for getChar(), unless we need to keep the data in the buffer.
@@ -1039,7 +1009,7 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
*data = c;
#if defined QIODEVICE_DEBUG
printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this,
- int(c), isprint(c) ? c : '?');
+ int(c), isAsciiPrintable(c) ? c : '?');
#endif
if (d->buffer.isEmpty())
readData(data, 0);
@@ -1048,8 +1018,6 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
}
CHECK_MAXLEN(read, qint64(-1));
- CHECK_READABLE(read, qint64(-1));
-
const qint64 readBytes = d->read(data, maxSize);
#if defined QIODEVICE_DEBUG
@@ -1069,7 +1037,7 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking)
{
Q_Q(QIODevice);
- const bool buffered = (openMode & QIODevice::Unbuffered) == 0;
+ const bool buffered = (readBufferChunkSize != 0 && (openMode & QIODevice::Unbuffered) == 0);
const bool sequential = isSequential();
const bool keepDataInBuffer = sequential
? peeking || transactionStarted
@@ -1122,9 +1090,9 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking)
}
} else {
// Do not read more than maxSize on unbuffered devices
- const qint64 bytesToBuffer = (buffered || readBufferChunkSize < maxSize)
- ? qint64(readBufferChunkSize)
- : maxSize;
+ const qint64 bytesToBuffer = (!buffered && maxSize < buffer.chunkSize())
+ ? maxSize
+ : qint64(buffer.chunkSize());
// Try to fill QIODevice buffer by single read
readFromDevice = q->readData(buffer.reserve(bytesToBuffer), bytesToBuffer);
deviceAtEof = (readFromDevice != bytesToBuffer);
@@ -1211,17 +1179,18 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking)
QByteArray QIODevice::read(qint64 maxSize)
{
Q_D(QIODevice);
- QByteArray result;
-
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, maxSize, d->pos, d->buffer.size());
#endif
+ QByteArray result;
+ CHECK_READABLE(read, result);
+
// Try to prevent the data from being copied, if we have a chunk
// with the same size in the read buffer.
if (maxSize == d->buffer.nextDataBlockSize() && !d->transactionStarted
- && (d->openMode & (QIODevice::ReadOnly | QIODevice::Text)) == QIODevice::ReadOnly) {
+ && (d->openMode & QIODevice::Text) == 0) {
result = d->buffer.read();
if (!d->isSequential())
d->pos += maxSize;
@@ -1233,13 +1202,13 @@ QByteArray QIODevice::read(qint64 maxSize)
CHECK_MAXLEN(read, result);
CHECK_MAXBYTEARRAYSIZE(read);
- result.resize(int(maxSize));
- qint64 readBytes = read(result.data(), result.size());
+ result.resize(qsizetype(maxSize));
+ qint64 readBytes = d->read(result.data(), result.size());
if (readBytes <= 0)
result.clear();
else
- result.resize(int(readBytes));
+ result.resize(qsizetype(readBytes));
return result;
}
@@ -1250,7 +1219,9 @@ QByteArray QIODevice::read(qint64 maxSize)
This function has no way of reporting errors; returning an empty
QByteArray can mean either that no data was currently available
- for reading, or that an error occurred.
+ for reading, or that an error occurred. This function also has no
+ way of indicating that more data may have been available and
+ couldn't be read.
*/
QByteArray QIODevice::readAll()
{
@@ -1261,39 +1232,40 @@ QByteArray QIODevice::readAll()
#endif
QByteArray result;
+ CHECK_READABLE(read, result);
+
qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size());
if (readBytes == 0) {
// Size is unknown, read incrementally.
- qint64 readChunkSize = qMax(qint64(d->readBufferChunkSize),
+ qint64 readChunkSize = qMax(qint64(d->buffer.chunkSize()),
d->isSequential() ? (d->buffer.size() - d->transactionPos)
: d->buffer.size());
qint64 readResult;
do {
- if (readBytes + readChunkSize >= MaxByteArraySize) {
+ if (readBytes + readChunkSize >= QByteArray::max_size()) {
// If resize would fail, don't read more, return what we have.
break;
}
result.resize(readBytes + readChunkSize);
- readResult = read(result.data() + readBytes, readChunkSize);
+ readResult = d->read(result.data() + readBytes, readChunkSize);
if (readResult > 0 || readBytes == 0) {
readBytes += readResult;
- readChunkSize = d->readBufferChunkSize;
+ readChunkSize = d->buffer.chunkSize();
}
} while (readResult > 0);
} else {
// Read it all in one go.
- // If resize fails, don't read anything.
readBytes -= d->pos;
- if (readBytes >= MaxByteArraySize)
- return QByteArray();
+ if (readBytes >= QByteArray::max_size())
+ readBytes = QByteArray::max_size();
result.resize(readBytes);
- readBytes = read(result.data(), readBytes);
+ readBytes = d->read(result.data(), readBytes);
}
if (readBytes <= 0)
result.clear();
else
- result.resize(int(readBytes));
+ result.resize(qsizetype(readBytes));
return result;
}
@@ -1302,7 +1274,7 @@ QByteArray QIODevice::readAll()
This function reads a line of ASCII characters from the device, up
to a maximum of \a maxSize - 1 bytes, stores the characters in \a
data, and returns the number of bytes read. If a line could not be
- read but no error ocurred, this function returns 0. If an error
+ read but no error occurred, this function returns 0. If an error
occurs, this function returns the length of what could be read, or
-1 if nothing was read.
@@ -1327,60 +1299,81 @@ QByteArray QIODevice::readAll()
newline will not be inserted into the buffer. On windows newline
characters are replaced with '\\n'.
+ Note that on sequential devices, data may not be immediately available,
+ which may result in a partial line being returned. By calling the
+ canReadLine() function before reading, you can check whether a complete
+ line (including the newline character) can be read.
+
This function calls readLineData(), which is implemented using
repeated calls to getChar(). You can provide a more efficient
implementation by reimplementing readLineData() in your own
subclass.
- \sa getChar(), read(), write()
+ \sa getChar(), read(), canReadLine(), write()
*/
qint64 QIODevice::readLine(char *data, qint64 maxSize)
{
Q_D(QIODevice);
- if (maxSize < 2) {
- checkWarnMessage(this, "readLine", "Called with maxSize < 2");
- return qint64(-1);
- }
-
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, data, maxSize, d->pos, d->buffer.size());
#endif
+ CHECK_READABLE(readLine, qint64(-1));
+ CHECK_LINEMAXLEN(readLine, qint64(-1));
+ const qint64 readBytes = d->readLine(data, maxSize);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n",
+ this, readBytes, d->pos, d->buffer.size(), size());
+ debugBinaryString(data, readBytes);
+#endif
+
+ return readBytes;
+}
+
+/*!
+ \internal
+*/
+qint64 QIODevicePrivate::readLine(char *data, qint64 maxSize)
+{
+ Q_Q(QIODevice);
+ Q_ASSERT(maxSize >= 2);
+
// Leave room for a '\0'
--maxSize;
- const bool sequential = d->isSequential();
- const bool keepDataInBuffer = sequential && d->transactionStarted;
+ const bool sequential = isSequential();
+ const bool keepDataInBuffer = sequential && transactionStarted;
qint64 readSoFar = 0;
if (keepDataInBuffer) {
- if (d->transactionPos < d->buffer.size()) {
+ if (transactionPos < buffer.size()) {
// Peek line from the specified position
- const qint64 i = d->buffer.indexOf('\n', maxSize, d->transactionPos);
- readSoFar = d->buffer.peek(data, i >= 0 ? (i - d->transactionPos + 1) : maxSize,
- d->transactionPos);
- d->transactionPos += readSoFar;
- if (d->transactionPos == d->buffer.size())
- readData(data, 0);
+ const qint64 i = buffer.indexOf('\n', maxSize, transactionPos);
+ readSoFar = buffer.peek(data, i >= 0 ? (i - transactionPos + 1) : maxSize,
+ transactionPos);
+ transactionPos += readSoFar;
+ if (transactionPos == buffer.size())
+ q->readData(data, 0);
}
- } else if (!d->buffer.isEmpty()) {
+ } else if (!buffer.isEmpty()) {
// QRingBuffer::readLine() terminates the line with '\0'
- readSoFar = d->buffer.readLine(data, maxSize + 1);
- if (d->buffer.isEmpty())
- readData(data,0);
+ readSoFar = buffer.readLine(data, maxSize + 1);
+ if (buffer.isEmpty())
+ q->readData(data, 0);
if (!sequential)
- d->pos += readSoFar;
+ pos += readSoFar;
}
if (readSoFar) {
#if defined QIODEVICE_DEBUG
- printf("%p \tread from buffer: %lld bytes, last character read: %hhx\n", this,
+ printf("%p \tread from buffer: %lld bytes, last character read: %hhx\n", q,
readSoFar, data[readSoFar - 1]);
- debugBinaryString(data, int(readSoFar));
+ debugBinaryString(data, readSoFar);
#endif
if (data[readSoFar - 1] == '\n') {
- if (d->openMode & Text) {
+ if (openMode & QIODevice::Text) {
// QRingBuffer::readLine() isn't Text aware.
if (readSoFar > 1 && data[readSoFar - 2] == '\r') {
--readSoFar;
@@ -1392,19 +1385,19 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
}
}
- if (d->pos != d->devicePos && !sequential && !seek(d->pos))
+ if (pos != devicePos && !sequential && !q->seek(pos))
return qint64(-1);
- d->baseReadLineDataCalled = false;
+ baseReadLineDataCalled = false;
// Force base implementation for transaction on sequential device
// as it stores the data in internal buffer automatically.
qint64 readBytes = keepDataInBuffer
- ? QIODevice::readLineData(data + readSoFar, maxSize - readSoFar)
- : readLineData(data + readSoFar, maxSize - readSoFar);
+ ? q->QIODevice::readLineData(data + readSoFar, maxSize - readSoFar)
+ : q->readLineData(data + readSoFar, maxSize - readSoFar);
#if defined QIODEVICE_DEBUG
- printf("%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", this,
+ printf("%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", q,
readBytes, readSoFar);
if (readBytes > 0) {
- debugBinaryString(data, int(readSoFar + readBytes));
+ debugBinaryString(data, readSoFar + readBytes);
}
#endif
if (readBytes < 0) {
@@ -1412,15 +1405,15 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
return readSoFar ? readSoFar : -1;
}
readSoFar += readBytes;
- if (!d->baseReadLineDataCalled && !sequential) {
- d->pos += readBytes;
+ if (!baseReadLineDataCalled && !sequential) {
+ pos += readBytes;
// If the base implementation was not called, then we must
// assume the device position is invalid and force a seek.
- d->devicePos = qint64(-1);
+ devicePos = qint64(-1);
}
data[readSoFar] = '\0';
- if (d->openMode & Text) {
+ if (openMode & QIODevice::Text) {
if (readSoFar > 1 && data[readSoFar - 1] == '\n' && data[readSoFar - 2] == '\r') {
data[readSoFar - 2] = '\n';
data[readSoFar - 1] = '\0';
@@ -1428,11 +1421,6 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
}
}
-#if defined QIODEVICE_DEBUG
- printf("%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n",
- this, readSoFar, d->pos, d->buffer.size(), size());
- debugBinaryString(data, int(readSoFar));
-#endif
return readSoFar;
}
@@ -1449,42 +1437,44 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
QByteArray QIODevice::readLine(qint64 maxSize)
{
Q_D(QIODevice);
- QByteArray result;
-
- CHECK_MAXLEN(readLine, result);
- CHECK_MAXBYTEARRAYSIZE(readLine);
-
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::readLine(%lld), d->pos = %lld, d->buffer.size() = %lld\n",
this, maxSize, d->pos, d->buffer.size());
#endif
- result.resize(int(maxSize));
+ QByteArray result;
+ CHECK_READABLE(readLine, result);
+
qint64 readBytes = 0;
- if (!result.size()) {
- // If resize fails or maxSize == 0, read incrementally
- if (maxSize == 0)
- maxSize = MaxByteArraySize - 1;
+ if (maxSize == 0) {
+ // Size is unknown, read incrementally.
+ maxSize = QByteArray::max_size() - 1;
// The first iteration needs to leave an extra byte for the terminating null
result.resize(1);
qint64 readResult;
do {
- result.resize(int(qMin(maxSize, qint64(result.size() + d->readBufferChunkSize))));
- readResult = readLine(result.data() + readBytes, result.size() - readBytes);
+ result.resize(qsizetype(qMin(maxSize, qint64(result.size() + d->buffer.chunkSize()))));
+ readResult = d->readLine(result.data() + readBytes, result.size() - readBytes);
if (readResult > 0 || readBytes == 0)
readBytes += readResult;
- } while (readResult == d->readBufferChunkSize
- && result[int(readBytes - 1)] != '\n');
- } else
- readBytes = readLine(result.data(), result.size());
+ } while (readResult == d->buffer.chunkSize()
+ && result[qsizetype(readBytes - 1)] != '\n');
+ } else {
+ CHECK_LINEMAXLEN(readLine, result);
+ CHECK_MAXBYTEARRAYSIZE(readLine);
+
+ result.resize(maxSize);
+ readBytes = d->readLine(result.data(), result.size());
+ }
if (readBytes <= 0)
result.clear();
else
result.resize(readBytes);
+ result.squeeze();
return result;
}
@@ -1510,7 +1500,7 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize)
Q_D(QIODevice);
qint64 readSoFar = 0;
char c;
- int lastReadReturn = 0;
+ qint64 lastReadReturn = 0;
d->baseReadLineDataCalled = true;
while (readSoFar < maxSize && (lastReadReturn = read(&c, 1)) == 1) {
@@ -1739,16 +1729,45 @@ qint64 QIODevice::write(const char *data)
return write(data, qstrlen(data));
}
-/*! \fn qint64 QIODevice::write(const QByteArray &byteArray)
-
+/*!
\overload
- Writes the content of \a byteArray to the device. Returns the number of
+ Writes the content of \a data to the device. Returns the number of
bytes that were actually written, or -1 if an error occurred.
\sa read(), writeData()
*/
+qint64 QIODevice::write(const QByteArray &data)
+{
+ Q_D(QIODevice);
+
+ // Keep the chunk pointer for further processing in
+ // QIODevicePrivate::write(). To reduce fragmentation,
+ // the chunk size must be sufficiently large.
+ if (data.size() >= QRINGBUFFER_CHUNKSIZE)
+ d->currentWriteChunk = &data;
+
+ const qint64 ret = write(data.constData(), data.size());
+
+ d->currentWriteChunk = nullptr;
+ return ret;
+}
+
+/*!
+ \internal
+*/
+void QIODevicePrivate::write(const char *data, qint64 size)
+{
+ if (isWriteChunkCached(data, size)) {
+ // We are called from write(const QByteArray &) overload.
+ // So, we can make a shallow copy of chunk.
+ writeBuffer.append(*currentWriteChunk);
+ } else {
+ writeBuffer.append(data, size);
+ }
+}
+
/*!
Puts the character \a c back into the device, and decrements the
current position unless the position is 0. This function is
@@ -1771,7 +1790,7 @@ void QIODevice::ungetChar(char c)
}
#if defined QIODEVICE_DEBUG
- printf("%p QIODevice::ungetChar(0x%hhx '%c')\n", this, c, isprint(c) ? c : '?');
+ printf("%p QIODevice::ungetChar(0x%hhx '%c')\n", this, c, isAsciiPrintable(c) ? c : '?');
#endif
d->buffer.ungetChar(c);
@@ -1915,7 +1934,7 @@ QByteArray QIODevice::peek(qint64 maxSize)
For random-access devices, skip() can be used to seek forward from the
current position. Negative \a maxSize values are not allowed.
- \sa peek(), seek(), read()
+ \sa skipData(), peek(), seek(), read()
*/
qint64 QIODevice::skip(qint64 maxSize)
{
@@ -1968,7 +1987,7 @@ qint64 QIODevice::skip(qint64 maxSize)
}
}
- const qint64 skipResult = d->skip(maxSize);
+ const qint64 skipResult = skipData(maxSize);
if (skippedSoFar == 0)
return skipResult;
@@ -2008,14 +2027,23 @@ qint64 QIODevicePrivate::skipByReading(qint64 maxSize)
}
/*!
- \internal
+ \since 6.0
+
+ Skips up to \a maxSize bytes from the device. Returns the number of bytes
+ actually skipped, or -1 on error.
+
+ This function is called by QIODevice. Consider reimplementing it
+ when creating a subclass of QIODevice.
+
+ The base implementation discards the data by reading into a dummy buffer.
+ This is slow, but works for all types of devices. Subclasses can
+ reimplement this function to improve on that.
+
+ \sa skip(), peek(), seek(), read()
*/
-qint64 QIODevicePrivate::skip(qint64 maxSize)
+qint64 QIODevice::skipData(qint64 maxSize)
{
- // Base implementation discards the data by reading into the dummy buffer.
- // It's slow, but this works for all types of devices. Subclasses can
- // reimplement this function to improve on that.
- return skipByReading(maxSize);
+ return d_func()->skipByReading(maxSize);
}
/*!
@@ -2101,7 +2129,7 @@ QString QIODevice::errorString() const
Q_D(const QIODevice);
if (d->errorString.isEmpty()) {
#ifdef QT_NO_QOBJECT
- return QLatin1String(QT_TRANSLATE_NOOP(QIODevice, "Unknown error"));
+ return QLatin1StringView(QT_TRANSLATE_NOOP(QIODevice, "Unknown error"));
#else
return tr("Unknown error");
#endif
@@ -2176,23 +2204,23 @@ QDebug operator<<(QDebug debug, QIODevice::OpenMode modes)
debug << "OpenMode(";
QStringList modeList;
if (modes == QIODevice::NotOpen) {
- modeList << QLatin1String("NotOpen");
+ modeList << "NotOpen"_L1;
} else {
if (modes & QIODevice::ReadOnly)
- modeList << QLatin1String("ReadOnly");
+ modeList << "ReadOnly"_L1;
if (modes & QIODevice::WriteOnly)
- modeList << QLatin1String("WriteOnly");
+ modeList << "WriteOnly"_L1;
if (modes & QIODevice::Append)
- modeList << QLatin1String("Append");
+ modeList << "Append"_L1;
if (modes & QIODevice::Truncate)
- modeList << QLatin1String("Truncate");
+ modeList << "Truncate"_L1;
if (modes & QIODevice::Text)
- modeList << QLatin1String("Text");
+ modeList << "Text"_L1;
if (modes & QIODevice::Unbuffered)
- modeList << QLatin1String("Unbuffered");
+ modeList << "Unbuffered"_L1;
}
std::sort(modeList.begin(), modeList.end());
- debug << modeList.join(QLatin1Char('|'));
+ debug << modeList.join(u'|');
debug << ')';
return debug;
}
diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h
index 2e4debe339..7844e0f125 100644
--- a/src/corelib/io/qiodevice.h
+++ b/src/corelib/io/qiodevice.h
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIODEVICE_H
#define QIODEVICE_H
#include <QtCore/qglobal.h>
+#include <QtCore/qiodevicebase.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobject.h>
#else
@@ -61,34 +26,23 @@ class QIODevicePrivate;
class Q_CORE_EXPORT QIODevice
#ifndef QT_NO_QOBJECT
- : public QObject
+ : public QObject,
+#else
+ :
#endif
+ public QIODeviceBase
{
#ifndef QT_NO_QOBJECT
Q_OBJECT
#endif
public:
- enum OpenModeFlag {
- NotOpen = 0x0000,
- ReadOnly = 0x0001,
- WriteOnly = 0x0002,
- ReadWrite = ReadOnly | WriteOnly,
- Append = 0x0004,
- Truncate = 0x0008,
- Text = 0x0010,
- Unbuffered = 0x0020,
- NewOnly = 0x0040,
- ExistingOnly = 0x0080
- };
- Q_DECLARE_FLAGS(OpenMode, OpenModeFlag)
-
QIODevice();
#ifndef QT_NO_QOBJECT
explicit QIODevice(QObject *parent);
#endif
virtual ~QIODevice();
- OpenMode openMode() const;
+ QIODeviceBase::OpenMode openMode() const;
void setTextModeEnabled(bool enabled);
bool isTextModeEnabled() const;
@@ -105,10 +59,10 @@ public:
int currentWriteChannel() const;
void setCurrentWriteChannel(int channel);
- virtual bool open(OpenMode mode);
+ virtual bool open(QIODeviceBase::OpenMode mode);
virtual void close();
- // ### Qt 6: pos() and seek() should not be virtual, and
+ // ### Qt 7 - QTBUG-76492: pos() and seek() should not be virtual, and
// ### seek() should call a virtual seekData() function.
virtual qint64 pos() const;
virtual qint64 size() const;
@@ -133,8 +87,7 @@ public:
qint64 write(const char *data, qint64 len);
qint64 write(const char *data);
- inline qint64 write(const QByteArray &data)
- { return write(data.constData(), data.size()); }
+ qint64 write(const QByteArray &data);
qint64 peek(char *data, qint64 maxlen);
QByteArray peek(qint64 maxlen);
@@ -167,9 +120,10 @@ protected:
#endif
virtual qint64 readData(char *data, qint64 maxlen) = 0;
virtual qint64 readLineData(char *data, qint64 maxlen);
+ virtual qint64 skipData(qint64 maxSize);
virtual qint64 writeData(const char *data, qint64 len) = 0;
- void setOpenMode(OpenMode openMode);
+ void setOpenMode(QIODeviceBase::OpenMode openMode);
void setErrorString(const QString &errorString);
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index da46b983cd..f69c055ac5 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIODEVICE_P_H
#define QIODEVICE_P_H
@@ -53,9 +17,9 @@
#include "QtCore/qbytearray.h"
#include "QtCore/qiodevice.h"
-#include "QtCore/qlist.h"
#include "QtCore/qobjectdefs.h"
#include "QtCore/qstring.h"
+#include "QtCore/qvarlengtharray.h"
#include "private/qringbuffer_p.h"
#ifndef QT_NO_QOBJECT
#include "private/qobject_p.h"
@@ -75,18 +39,23 @@ class Q_CORE_EXPORT QIODevicePrivate
#endif
{
Q_DECLARE_PUBLIC(QIODevice)
+ Q_DISABLE_COPY_MOVE(QIODevicePrivate)
public:
QIODevicePrivate();
virtual ~QIODevicePrivate();
- QIODevice::OpenMode openMode;
- QString errorString;
-
- QList<QRingBuffer> readBuffers;
- QList<QRingBuffer> writeBuffers;
+ // The size of this class is a subject of the library hook data.
+ // When adding a new member, do not make gaps and be aware
+ // about the padding. Accordingly, adjust offsets in
+ // tests/auto/other/toolsupport and bump the TypeInformationVersion
+ // field in src/corelib/global/qhooks.cpp, to notify the developers.
+ qint64 pos = 0;
+ qint64 devicePos = 0;
+ qint64 transactionPos = 0;
- class QRingBufferRef {
+ class QRingBufferRef
+ {
QRingBuffer *m_buf;
inline QRingBufferRef() : m_buf(nullptr) { }
friend class QIODevicePrivate;
@@ -122,26 +91,30 @@ public:
QRingBufferRef buffer;
QRingBufferRef writeBuffer;
- qint64 pos;
- qint64 devicePos;
- int readChannelCount;
- int writeChannelCount;
- int currentReadChannel;
- int currentWriteChannel;
- int readBufferChunkSize;
- int writeBufferChunkSize;
- qint64 transactionPos;
- bool transactionStarted;
- bool baseReadLineDataCalled;
+ const QByteArray *currentWriteChunk = nullptr;
+ int readChannelCount = 0;
+ int writeChannelCount = 0;
+ int currentReadChannel = 0;
+ int currentWriteChannel = 0;
+ int readBufferChunkSize = QIODEVICE_BUFFERSIZE;
+ int writeBufferChunkSize = 0;
+
+ QVarLengthArray<QRingBuffer, 2> readBuffers;
+ QVarLengthArray<QRingBuffer, 1> writeBuffers;
+ QString errorString;
+ QIODevice::OpenMode openMode = QIODevice::NotOpen;
+
+ bool transactionStarted = false;
+ bool baseReadLineDataCalled = false;
virtual bool putCharHelper(char c);
- enum AccessMode {
+ enum AccessMode : quint8 {
Unset,
Sequential,
RandomAccess
};
- mutable AccessMode accessMode;
+ mutable AccessMode accessMode = Unset;
inline bool isSequential() const
{
if (accessMode == Unset)
@@ -172,14 +145,21 @@ public:
void setWriteChannelCount(int count);
qint64 read(char *data, qint64 maxSize, bool peeking = false);
+ qint64 readLine(char *data, qint64 maxSize);
virtual qint64 peek(char *data, qint64 maxSize);
virtual QByteArray peek(qint64 maxSize);
qint64 skipByReading(qint64 maxSize);
- // ### Qt6: consider replacing with a protected virtual QIODevice::skipData().
- virtual qint64 skip(qint64 maxSize);
+ void write(const char *data, qint64 size);
+
+ inline bool isWriteChunkCached(const char *data, qint64 size) const
+ {
+ return currentWriteChunk != nullptr
+ && currentWriteChunk->constData() == data
+ && currentWriteChunk->size() == size;
+ }
#ifdef QT_NO_QOBJECT
- QIODevice *q_ptr;
+ QIODevice *q_ptr = nullptr;
#endif
};
diff --git a/src/corelib/io/qiodevicebase.h b/src/corelib/io/qiodevicebase.h
new file mode 100644
index 0000000000..aab63d4351
--- /dev/null
+++ b/src/corelib/io/qiodevicebase.h
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QIODEVICEBASE_H
+#define QIODEVICEBASE_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIODeviceBase
+{
+protected:
+ ~QIODeviceBase() = default;
+public:
+ enum OpenModeFlag {
+ NotOpen = 0x0000,
+ ReadOnly = 0x0001,
+ WriteOnly = 0x0002,
+ ReadWrite = ReadOnly | WriteOnly,
+ Append = 0x0004,
+ Truncate = 0x0008,
+ Text = 0x0010,
+ Unbuffered = 0x0020,
+ NewOnly = 0x0040,
+ ExistingOnly = 0x0080
+ };
+ Q_DECLARE_FLAGS(OpenMode, OpenModeFlag)
+};
+
+QT_END_NAMESPACE
+
+#endif // QIODEVICEBASE_H
diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp
index 15f759156d..c2b274f8b5 100644
--- a/src/corelib/io/qipaddress.cpp
+++ b/src/corelib/io/qipaddress.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qipaddress_p.h"
#include "private/qlocale_tools_p.h"
@@ -43,20 +8,23 @@
#include "qvarlengtharray.h"
QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
namespace QIPAddressUtils {
-static QString number(quint8 val, int base = 10)
+static QString number(quint8 val)
{
QString zero = QStringLiteral("0");
- return val ? qulltoa(val, base, zero) : zero;
+ return val ? qulltoa(val, 10, zero) : zero;
}
typedef QVarLengthArray<char, 64> Buffer;
static const QChar *checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
{
- const ushort *const ubegin = reinterpret_cast<const ushort *>(begin);
- const ushort *const uend = reinterpret_cast<const ushort *>(end);
- const ushort *src = ubegin;
+ const auto *const ubegin = reinterpret_cast<const char16_t *>(begin);
+ const auto *const uend = reinterpret_cast<const char16_t *>(end);
+ auto *src = ubegin;
buffer.resize(uend - ubegin + 1);
char *dst = buffer.data();
@@ -86,19 +54,18 @@ static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptL
{
address = 0;
int dotCount = 0;
+ const char *const stop = ptr + qstrlen(ptr);
while (dotCount < 4) {
if (!acceptLeadingZero && *ptr == '0' &&
ptr[1] != '.' && ptr[1] != '\0')
return false;
- const char *endptr;
- bool ok;
- quint64 ll = qstrtoull(ptr, &endptr, 0, &ok);
- quint32 x = ll;
- if (!ok || endptr == ptr || ll != x)
+ auto [ll, used] = qstrntoull(ptr, stop - ptr, 0);
+ const quint32 x = quint32(ll);
+ if (used <= 0 || ll != x)
return false;
- if (*endptr == '.' || dotCount == 3) {
+ if (ptr[used] == '.' || dotCount == 3) {
if (x & ~0xff)
return false;
address <<= 8;
@@ -113,15 +80,13 @@ static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptL
}
address |= x;
- if (dotCount == 3 && *endptr != '\0')
- return false;
- else if (dotCount == 3 || *endptr == '\0')
- return true;
- if (*endptr != '.')
+ if (dotCount == 3 || ptr[used] == '\0')
+ return ptr[used] == '\0';
+ if (ptr[used] != '.')
return false;
++dotCount;
- ptr = endptr + 1;
+ ptr += used + 1;
}
return false;
}
@@ -130,12 +95,9 @@ void toString(QString &appendTo, IPv4Address address)
{
// reconstructing is easy
// use the fast operator% that pre-calculates the size
- appendTo += number(address >> 24)
- % QLatin1Char('.')
- % number(address >> 16)
- % QLatin1Char('.')
- % number(address >> 8)
- % QLatin1Char('.')
+ appendTo += number(address >> 24) % u'.'
+ % number(address >> 16) % u'.'
+ % number(address >> 8) % u'.'
% number(address);
}
@@ -158,6 +120,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
return ret;
const char *ptr = buffer.data();
+ const char *const stop = ptr + buffer.size();
// count the colons
int colonCount = 0;
@@ -211,18 +174,16 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
continue;
}
- const char *endptr;
- bool ok;
- quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
+ auto [ll, used] = qstrntoull(ptr, stop - ptr, 16);
quint16 x = ll;
// Reject malformed fields:
// - failed to parse
// - too many hex digits
- if (!ok || endptr > ptr + 4)
+ if (used <= 0 || used > 4)
return begin + (ptr - buffer.data());
- if (*endptr == '.') {
+ if (ptr[used] == '.') {
// this could be an IPv4 address
// it's only valid in the last element
if (pos != 12)
@@ -242,11 +203,11 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
address[pos++] = x >> 8;
address[pos++] = x & 0xff;
- if (*endptr == '\0')
+ if (ptr[used] == '\0')
break;
- if (*endptr != ':')
- return begin + (endptr - buffer.data());
- ptr = endptr + 1;
+ if (ptr[used] != ':')
+ return begin + (used + ptr - buffer.data());
+ ptr += used + 1;
}
return pos == 16 ? nullptr : end;
}
@@ -282,7 +243,7 @@ void toString(QString &appendTo, const IPv6Address address)
if (address[12] != 0 || address[13] != 0 || address[14] != 0) {
embeddedIp4 = true;
} else if (address[15] == 0) {
- appendTo.append(QLatin1String("::"));
+ appendTo.append("::"_L1);
return;
}
}
diff --git a/src/corelib/io/qipaddress_p.h b/src/corelib/io/qipaddress_p.h
index ea31e5883d..af3ab52dfd 100644
--- a/src/corelib/io/qipaddress_p.h
+++ b/src/corelib/io/qipaddress_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIPADDRESS_P_H
#define QIPADDRESS_P_H
diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp
index aa84ce6bc1..0eb6acb694 100644
--- a/src/corelib/io/qlockfile.cpp
+++ b/src/corelib/io/qlockfile.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlockfile.h"
#include "qlockfile_p.h"
@@ -50,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace {
struct LockFileInfo
{
@@ -94,7 +60,7 @@ static QString machineName()
When protecting for a short-term operation, it is acceptable to call lock() and wait
until any running operation finishes.
When protecting a resource over a long time, however, the application should always
- call setStaleLockTime(0) and then tryLock() with a short timeout, in order to
+ call setStaleLockTime(0ms) and then tryLock() with a short timeout, in order to
warn the user that the resource is locked.
If the process holding the lock crashes, the lock file stays on disk and can prevent
@@ -151,6 +117,14 @@ QLockFile::~QLockFile()
}
/*!
+ * Returns the file name of the lock file
+ */
+QString QLockFile::fileName() const
+{
+ return d_ptr->fileName;
+}
+
+/*!
Sets \a staleLockTime to be the time in milliseconds after which
a lock file is considered stale.
The default value is 30000, i.e. 30 seconds.
@@ -164,10 +138,38 @@ QLockFile::~QLockFile()
meanwhile, so one way to detect a stale lock file is by the fact that
it has been around for a long time.
+ This is an overloaded function, equivalent to calling:
+ \code
+ setStaleLockTime(std::chrono::milliseconds{staleLockTime});
+ \endcode
+
\sa staleLockTime()
*/
void QLockFile::setStaleLockTime(int staleLockTime)
{
+ setStaleLockTime(std::chrono::milliseconds{staleLockTime});
+}
+
+/*!
+ \since 6.2
+
+ Sets the interval after which a lock file is considered stale to \a staleLockTime.
+ The default value is 30s.
+
+ If your application typically keeps the file locked for more than 30 seconds
+ (for instance while saving megabytes of data for 2 minutes), you should set
+ a bigger value using setStaleLockTime().
+
+ The value of staleLockTime() is used by lock() and tryLock() in order
+ to determine when an existing lock file is considered stale, i.e. left over
+ by a crashed process. This is useful for the case where the PID got reused
+ meanwhile, so one way to detect a stale lock file is by the fact that
+ it has been around for a long time.
+
+ \sa staleLockTime()
+*/
+void QLockFile::setStaleLockTime(std::chrono::milliseconds staleLockTime)
+{
Q_D(QLockFile);
d->staleLockTime = staleLockTime;
}
@@ -180,6 +182,20 @@ void QLockFile::setStaleLockTime(int staleLockTime)
*/
int QLockFile::staleLockTime() const
{
+ return int(staleLockTimeAsDuration().count());
+}
+
+/*! \fn std::chrono::milliseconds QLockFile::staleLockTimeAsDuration() const
+ \overload
+ \since 6.2
+
+ Returns a std::chrono::milliseconds object which denotes the time after
+ which a lock file is considered stale.
+
+ \sa setStaleLockTime()
+*/
+std::chrono::milliseconds QLockFile::staleLockTimeAsDuration() const
+{
Q_D(const QLockFile);
return d->staleLockTime;
}
@@ -213,7 +229,7 @@ bool QLockFile::isLocked() const
*/
bool QLockFile::lock()
{
- return tryLock(-1);
+ return tryLock(std::chrono::milliseconds::max());
}
/*!
@@ -238,10 +254,38 @@ bool QLockFile::lock()
*/
bool QLockFile::tryLock(int timeout)
{
+ return tryLock(std::chrono::milliseconds{ timeout });
+}
+
+/*!
+ \overload
+ \since 6.2
+
+ Attempts to create the lock file. This function returns \c true if the
+ lock was obtained; otherwise it returns \c false. If another process (or
+ another thread) has created the lock file already, this function will
+ wait for at most \a timeout for the lock file to become available.
+
+ If the lock was obtained, it must be released with unlock()
+ before another process (or thread) can successfully lock it.
+
+ Calling this function multiple times on the same lock from the same
+ thread without unlocking first is not allowed, this function will
+ \e always return false when attempting to lock the file recursively.
+
+ \sa lock(), unlock()
+*/
+bool QLockFile::tryLock(std::chrono::milliseconds timeout)
+{
+ using namespace std::chrono_literals;
+ using Msec = std::chrono::milliseconds;
+
Q_D(QLockFile);
- QDeadlineTimer timer(qMax(timeout, -1)); // QDT only takes -1 as "forever"
- int sleepTime = 100;
- forever {
+
+ QDeadlineTimer timer(timeout < 0ms ? Msec::max() : timeout);
+
+ Msec sleepTime = 100ms;
+ while (true) {
d->lockError = d->tryLock_sys();
switch (d->lockError) {
case NoError:
@@ -252,11 +296,11 @@ bool QLockFile::tryLock(int timeout)
return false;
case LockFailedError:
if (!d->isLocked && d->isApparentlyStale()) {
- if (Q_UNLIKELY(QFileInfo(d->fileName).lastModified() > QDateTime::currentDateTime()))
+ if (Q_UNLIKELY(QFileInfo(d->fileName).lastModified(QTimeZone::UTC) > QDateTime::currentDateTimeUtc()))
qInfo("QLockFile: Lock file '%ls' has a modification time in the future", qUtf16Printable(d->fileName));
// Stale lock from another thread/process
// Ensure two processes don't remove it at the same time
- QLockFile rmlock(d->fileName + QLatin1String(".rmlock"));
+ QLockFile rmlock(d->fileName + ".rmlock"_L1);
if (rmlock.tryLock()) {
if (d->isApparentlyStale() && d->removeStaleLock())
continue;
@@ -265,14 +309,15 @@ bool QLockFile::tryLock(int timeout)
break;
}
- int remainingTime = timer.remainingTime();
- if (remainingTime == 0)
+ auto remainingTime = std::chrono::duration_cast<Msec>(timer.remainingTimeAsDuration());
+ if (remainingTime == 0ms)
return false;
- else if (uint(sleepTime) > uint(remainingTime))
+
+ if (sleepTime > remainingTime)
sleepTime = remainingTime;
- QThread::msleep(sleepTime);
- if (sleepTime < 5 * 1000)
+ QThread::sleep(sleepTime);
+ if (sleepTime < 5s)
sleepTime *= 2;
}
// not reached
@@ -391,8 +436,10 @@ bool QLockFilePrivate::isApparentlyStale() const
}
}
- const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTimeUtc());
- return staleLockTime > 0 && qAbs(age) > staleLockTime;
+ const QDateTime lastMod = QFileInfo(fileName).lastModified(QTimeZone::UTC);
+ using namespace std::chrono;
+ const milliseconds age{lastMod.msecsTo(QDateTime::currentDateTimeUtc())};
+ return staleLockTime > 0ms && abs(age) > staleLockTime;
}
/*!
diff --git a/src/corelib/io/qlockfile.h b/src/corelib/io/qlockfile.h
index 8b94900901..af481ab59b 100644
--- a/src/corelib/io/qlockfile.h
+++ b/src/corelib/io/qlockfile.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOCKFILE_H
#define QLOCKFILE_H
@@ -43,6 +7,8 @@
#include <QtCore/qstring.h>
#include <QtCore/qscopedpointer.h>
+#include <chrono>
+
QT_BEGIN_NAMESPACE
class QLockFilePrivate;
@@ -53,13 +19,20 @@ public:
QLockFile(const QString &fileName);
~QLockFile();
+ QString fileName() const;
+
bool lock();
- bool tryLock(int timeout = 0);
+ bool tryLock(int timeout);
void unlock();
void setStaleLockTime(int);
int staleLockTime() const;
+ bool tryLock(std::chrono::milliseconds timeout = std::chrono::milliseconds::zero());
+
+ void setStaleLockTime(std::chrono::milliseconds value);
+ std::chrono::milliseconds staleLockTimeAsDuration() const;
+
bool isLocked() const;
bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const;
bool removeStaleLockFile();
diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index 5b69347206..299b13b21a 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOCKFILE_P_H
#define QLOCKFILE_P_H
@@ -68,15 +32,7 @@ class QLockFilePrivate
{
public:
QLockFilePrivate(const QString &fn)
- : fileName(fn),
-#ifdef Q_OS_WIN
- fileHandle(INVALID_HANDLE_VALUE),
-#else
- fileHandle(-1),
-#endif
- staleLockTime(30 * 1000), // 30 seconds
- lockError(QLockFile::NoError),
- isLocked(false)
+ : fileName(fn)
{
}
QLockFile::LockError tryLock_sys();
@@ -91,14 +47,16 @@ public:
static bool isProcessRunning(qint64 pid, const QString &appname);
QString fileName;
+
#ifdef Q_OS_WIN
- Qt::HANDLE fileHandle;
+ Qt::HANDLE fileHandle = INVALID_HANDLE_VALUE;
#else
- int fileHandle;
+ int fileHandle = -1;
#endif
- int staleLockTime; // "int milliseconds" is big enough for 24 days
- QLockFile::LockError lockError;
- bool isLocked;
+
+ std::chrono::milliseconds staleLockTime = std::chrono::seconds{30};
+ QLockFile::LockError lockError = QLockFile::NoError;
+ bool isLocked = false;
static int getLockFileHandle(QLockFile *f)
{
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index b531140437..47aff8b973 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
-** Copyright (C) 2017 Intel Corporation.
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+// Copyright (C) 2017 Intel Corporation.
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qlockfile_p.h"
@@ -52,13 +16,14 @@
#include "private/qcore_unix_p.h" // qt_safe_open
#include "private/qabstractfileengine_p.h"
+#include "private/qfilesystementry_p.h"
#include "private/qtemporaryfile_p.h"
#if !defined(Q_OS_INTEGRITY)
#include <sys/file.h> // flock
#endif
-#if defined(Q_OS_RTEMS) || defined(Q_OS_QNX)
+#if defined(Q_OS_RTEMS)
// flock() does not work in these OSes and produce warnings when we try to use
# undef LOCK_EX
# undef LOCK_NB
@@ -205,7 +170,7 @@ bool QLockFilePrivate::removeStaleLock()
bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname)
{
- if (::kill(pid, 0) == -1 && errno == ESRCH)
+ if (::kill(pid_t(pid), 0) == -1 && errno == ESRCH)
return false; // PID doesn't exist anymore
const QString processName = processNameByPid(pid);
@@ -238,7 +203,13 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
// The pid is gone. Return some invalid process name to fail the test.
return QStringLiteral("/ERROR/");
}
- return QFileInfo(QFile::decodeName(buf)).fileName();
+
+ // remove the " (deleted)" suffix, if any
+ static const char deleted[] = " (deleted)";
+ if (buf.endsWith(deleted))
+ buf.chop(strlen(deleted));
+
+ return QFileSystemEntry(buf, QFileSystemEntry::FromNativePath()).fileName();
#elif defined(Q_OS_HAIKU)
thread_info info;
if (get_thread_info(pid, &info) != B_OK)
@@ -271,7 +242,27 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
QString name = QFile::decodeName(kp.ki_comm);
# endif
return name;
+#elif defined(Q_OS_QNX)
+ char exePath[PATH_MAX];
+ sprintf(exePath, "/proc/%lld/exefile", pid);
+
+ int fd = qt_safe_open(exePath, O_RDONLY);
+ if (fd == -1)
+ return QString();
+ QT_STATBUF sbuf;
+ if (QT_FSTAT(fd, &sbuf) == -1) {
+ qt_safe_close(fd);
+ return QString();
+ }
+
+ QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
+ buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size - 1));
+ if (buffer.isEmpty()) {
+ // The pid is gone. Return some invalid process name to fail the test.
+ return QStringLiteral("/ERROR/");
+ }
+ return QFileSystemEntry(buffer, QFileSystemEntry::FromNativePath()).fileName();
#else
Q_UNUSED(pid);
return QString();
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 77cdf66694..b9d7721517 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qlockfile_p.h"
#include "private/qfilesystementry_p.h"
#include <qt_windows.h>
+#include <psapi.h>
#include "QtCore/qfileinfo.h"
#include "QtCore/qdatetime.h"
@@ -131,34 +96,20 @@ bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname)
QString QLockFilePrivate::processNameByPid(qint64 pid)
{
- typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
-
- HMODULE hPsapi = LoadLibraryA("psapi");
- if (!hPsapi)
- return QString();
- GetModuleFileNameExFunc qGetModuleFileNameEx = reinterpret_cast<GetModuleFileNameExFunc>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hPsapi, "GetModuleFileNameExW")));
- if (!qGetModuleFileNameEx) {
- FreeLibrary(hPsapi);
- return QString();
- }
-
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
if (!hProcess) {
- FreeLibrary(hPsapi);
return QString();
}
wchar_t buf[MAX_PATH];
- const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
+ const DWORD length = GetModuleFileNameExW(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
CloseHandle(hProcess);
- FreeLibrary(hPsapi);
if (!length)
return QString();
QString name = QString::fromWCharArray(buf, length);
- int i = name.lastIndexOf(QLatin1Char('\\'));
+ int i = name.lastIndexOf(u'\\');
if (i >= 0)
name.remove(0, i + 1);
- i = name.lastIndexOf(QLatin1Char('.'));
+ i = name.lastIndexOf(u'.');
if (i >= 0)
name.truncate(i);
return name;
@@ -167,21 +118,24 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
void QLockFile::unlock()
{
Q_D(QLockFile);
- if (!d->isLocked)
+ if (!d->isLocked)
return;
- CloseHandle(d->fileHandle);
- int attempts = 0;
- static const int maxAttempts = 500; // 500ms
- while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) {
- // Someone is reading the lock file right now (on Windows this prevents deleting it).
- QThread::msleep(1);
- }
- if (attempts == maxAttempts) {
- qWarning() << "Could not remove our own lock file" << d->fileName << ". Either other users of the lock file are reading it constantly for 500 ms, or we (no longer) have permissions to delete the file";
- // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
- }
- d->lockError = QLockFile::NoError;
- d->isLocked = false;
+ CloseHandle(d->fileHandle);
+ int attempts = 0;
+ static const int maxAttempts = 500; // 500ms
+ while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) {
+ // Someone is reading the lock file right now (on Windows this prevents deleting it).
+ QThread::msleep(1);
+ }
+ if (attempts == maxAttempts) {
+ qWarning() << "Could not remove our own lock file" << d->fileName
+ << ". Either other users of the lock file are reading it constantly for 500 ms, "
+ "or we (no longer) have permissions to delete the file";
+ // This is bad because other users of this lock file will now have to wait for the
+ // stale-lock-timeout...
+ }
+ d->lockError = QLockFile::NoError;
+ d->isLocked = false;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 5de8be116c..10763dd65a 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qloggingcategory.h"
#include "qloggingregistry_p.h"
@@ -43,21 +7,7 @@
QT_BEGIN_NAMESPACE
const char qtDefaultCategoryName[] = "default";
-
-Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
- (qtDefaultCategoryName))
-
-#ifndef Q_ATOMIC_INT8_IS_SUPPORTED
-static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
-{
- const int bit = 1 << shift;
-
- if (enable)
- atomic->fetchAndOrRelaxed(bit);
- else
- atomic->fetchAndAndRelaxed(~bit);
-}
-#endif
+Q_GLOBAL_STATIC(QLoggingCategory, qtDefaultCategory, qtDefaultCategoryName)
/*!
\class QLoggingCategory
@@ -70,7 +20,8 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
QLoggingCategory represents a certain logging category - identified by a
string - at runtime. A category can be configured to enable or disable
- logging of messages per message type.
+ logging of messages per message type. An exception are fatal messages,
+ which are always enabled.
To check whether a message type is enabled or not, use one of these methods:
\l isDebugEnabled(), \l isInfoEnabled(), \l isWarningEnabled(), and
@@ -89,6 +40,9 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\snippet qloggingcategory/main.cpp 1
+ There is also the Q_DECLARE_EXPORTED_LOGGING_CATEGORY() macro in
+ order to use a logging category across library boundaries.
+
Category names are free text; to configure categories using \l{Logging Rules}, their
names should follow this convention:
\list
@@ -124,7 +78,14 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
logs messages of type \c QtWarningMsg, \c QtCriticalMsg, \c QtFatalMsg, but
ignores messages of type \c QtDebugMsg and \c QtInfoMsg.
- If no argument is passed, all messages are logged.
+ If no argument is passed, all messages are logged. Only Qt internal categories
+ which start with \c{qt} are handled differently: For these, only messages of type
+ \c QtInfoMsg, \c QtWarningMsg, \c QtCriticalMsg, and \c QFatalMsg are logged by default.
+
+ \note Logging categories are not affected by your C++ build configuration.
+ That is, whether messages are printed does not change depending on whether
+ the code is compiled with debug symbols ('Debug Build'), optimizations
+ ('Release Build'), or some other combination.
\section1 Configuring Categories
@@ -197,27 +158,14 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
*/
/*!
- Constructs a QLoggingCategory object with the provided \a category name.
- All message types for this category are enabled by default.
-
- If \a category is \c{0}, the category name is changed to \c "default".
-
- \note \a category must be kept valid during the lifetime of this object.
-*/
-QLoggingCategory::QLoggingCategory(const char *category)
- : d(nullptr),
- name(nullptr)
-{
- init(category, QtDebugMsg);
-}
-
-/*!
Constructs a QLoggingCategory object with the provided \a category name,
- and enables all messages with types more severe or equal than \a enableForLevel.
+ and enables all messages with types at least as verbose as \a enableForLevel,
+ which defaults to QtDebugMsg (which enables all categories).
- If \a category is \c{0}, the category name is changed to \c "default".
+ If \a category is \nullptr, the category name \c "default" is used.
\note \a category must be kept valid during the lifetime of this object.
+ Using a string literal for it is the usual way to achieve this.
\since 5.4
*/
@@ -332,17 +280,10 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
{
switch (type) {
-#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
case QtDebugMsg: bools.enabledDebug.storeRelaxed(enable); break;
case QtInfoMsg: bools.enabledInfo.storeRelaxed(enable); break;
case QtWarningMsg: bools.enabledWarning.storeRelaxed(enable); break;
case QtCriticalMsg: bools.enabledCritical.storeRelaxed(enable); break;
-#else
- case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break;
- case QtInfoMsg: setBoolLane(&enabled, enable, InfoShift); break;
- case QtWarningMsg: setBoolLane(&enabled, enable, WarningShift); break;
- case QtCriticalMsg: setBoolLane(&enabled, enable, CriticalShift); break;
-#endif
case QtFatalMsg: break;
}
}
@@ -352,7 +293,7 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
Returns the object itself. This allows for both: a QLoggingCategory variable, and
a factory method that returns a QLoggingCategory, to be used in \l qCDebug(),
- \l qCWarning(), or \l qCCritical() macros.
+ \l qCWarning(), \l qCCritical(), or \l qCFatal() macros.
*/
/*!
@@ -360,7 +301,7 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
Returns the object itself. This allows for both: a QLoggingCategory variable, and
a factory method that returns a QLoggingCategory, to be used in \l qCDebug(),
- \l qCWarning(), or \l qCCritical() macros.
+ \l qCWarning(), \l qCCritical(), or \l qCFatal() macros.
*/
/*!
@@ -387,13 +328,27 @@ QLoggingCategory *QLoggingCategory::defaultCategory()
*/
/*!
- Installs a function \a filter that is used to determine which categories
- and message types should be enabled. Returns a pointer to the previous
- installed filter.
-
- Every QLoggingCategory object created is passed to the filter, and the
- filter is free to change the respective category configuration with
- \l setEnabled().
+ \brief Take control of how logging categories are configured.
+
+ Installs a function \a filter that is used to determine which categories and
+ message types should be enabled. If \a filter is \nullptr, the default
+ message filter is reinstated. Returns a pointer to the previously-installed
+ filter.
+
+ Every QLoggingCategory object that already exists is passed to the filter
+ before \c installFilter() returns, and the filter is free to change each
+ category's configuration with \l setEnabled(). Any category it doesn't
+ change will retain the configuration it was given by the prior filter, so
+ the new filter does not need to delegate to the prior filter during this
+ initial pass over existing categories.
+
+ Any new categories added later will be passed to the new filter; a filter
+ that only aims to tweak the configuration of a select few categories, rather
+ than completely overriding the logging policy, can first pass the new
+ category to the prior filter, to give it its standard configuration, and
+ then tweak that as desired, if it is one of the categories of specific
+ interest to the filter. The code that installs the new filter can record the
+ return from \c installFilter() for the filter to use in such later calls.
When you define your filter, note that it can be called from different threads; but never
concurrently. This filter cannot call any static functions from QLoggingCategory.
@@ -401,6 +356,10 @@ QLoggingCategory *QLoggingCategory::defaultCategory()
Example:
\snippet qloggingcategory/main.cpp 21
+ installed (in \c{main()}, for example) by
+
+ \snippet qloggingcategory/main.cpp 22
+
Alternatively, you can configure the default filter via \l setFilterRules().
*/
QLoggingCategory::CategoryFilter
@@ -598,9 +557,49 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\sa qCritical()
*/
+
+/*!
+ \macro qCFatal(category)
+ \relates QLoggingCategory
+ \since 6.5
+
+ Returns an output stream for fatal messages in the logging category,
+ \a category.
+
+ If you are using the \b{default message handler}, the returned stream will abort
+ to create a core dump. On Windows, for debug builds, this function will
+ report a \c _CRT_ERROR enabling you to connect a debugger to the application.
+
+ Example:
+
+ \snippet qloggingcategory/main.cpp 16
+
+ \sa qFatal()
+*/
+
+/*!
+ \macro qCFatal(category, const char *message, ...)
+ \relates QLoggingCategory
+ \since 6.5
+
+ Logs a fatal message, \a message, in the logging category, \a category.
+ \a message may contain place holders to be replaced by additional arguments,
+ similar to the C printf() function.
+
+ Example:
+
+ \snippet qloggingcategory/main.cpp 17
+
+ If you are using the \b{default message handler}, this function will abort
+ to create a core dump. On Windows, for debug builds, this function will
+ report a \c _CRT_ERROR enabling you to connect a debugger to the application.
+
+ \sa qFatal()
+*/
+
/*!
\macro Q_DECLARE_LOGGING_CATEGORY(name)
- \sa Q_LOGGING_CATEGORY()
+ \sa Q_LOGGING_CATEGORY(), Q_DECLARE_EXPORTED_LOGGING_CATEGORY()
\relates QLoggingCategory
\since 5.2
@@ -611,8 +610,31 @@ void QLoggingCategory::setFilterRules(const QString &rules)
*/
/*!
+ \macro Q_DECLARE_EXPORTED_LOGGING_CATEGORY(name, EXPORT_MACRO)
+ \sa Q_LOGGING_CATEGORY(), Q_DECLARE_LOGGING_CATEGORY()
+ \relates QLoggingCategory
+ \since 6.5
+
+ Declares a logging category \a name. The macro can be used to declare
+ a common logging category shared in different parts of the program.
+
+ This works exactly like Q_DECLARE_LOGGING_CATEGORY(). However,
+ the logging category declared by this macro is additionally
+ qualified with \a EXPORT_MACRO. This is useful if the logging
+ category needs to be exported from a dynamic library.
+
+ For example:
+
+ \code
+ Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcCore, LIB_EXPORT_MACRO)
+ \endcode
+
+ This macro must be used outside of a class or function.
+*/
+
+/*!
\macro Q_LOGGING_CATEGORY(name, string)
- \sa Q_DECLARE_LOGGING_CATEGORY()
+ \sa Q_DECLARE_LOGGING_CATEGORY(), Q_DECLARE_EXPORTED_LOGGING_CATEGORY()
\relates QLoggingCategory
\since 5.2
@@ -640,8 +662,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
with a specific name. The implicitly-defined QLoggingCategory object is
created on first use, in a thread-safe manner.
- This macro must be used outside of a class or method. It is only defined
- if variadic macros are supported.
+ This macro must be used outside of a class or method.
*/
QT_END_NAMESPACE
diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h
index 1c3e10b493..7c32beea1a 100644
--- a/src/corelib/io/qloggingcategory.h
+++ b/src/corelib/io/qloggingcategory.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOGGINGCATEGORY_H
#define QLOGGINGCATEGORY_H
@@ -49,25 +13,17 @@ class Q_CORE_EXPORT QLoggingCategory
{
Q_DISABLE_COPY(QLoggingCategory)
public:
- // ### Qt 6: Merge constructors
- explicit QLoggingCategory(const char *category);
- QLoggingCategory(const char *category, QtMsgType severityLevel);
+ explicit QLoggingCategory(const char *category, QtMsgType severityLevel = QtDebugMsg);
~QLoggingCategory();
bool isEnabled(QtMsgType type) const;
void setEnabled(QtMsgType type, bool enable);
-#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
bool isDebugEnabled() const { return bools.enabledDebug.loadRelaxed(); }
bool isInfoEnabled() const { return bools.enabledInfo.loadRelaxed(); }
bool isWarningEnabled() const { return bools.enabledWarning.loadRelaxed(); }
bool isCriticalEnabled() const { return bools.enabledCritical.loadRelaxed(); }
-#else
- bool isDebugEnabled() const { return enabled.loadRelaxed() >> DebugShift & 1; }
- bool isInfoEnabled() const { return enabled.loadRelaxed() >> InfoShift & 1; }
- bool isWarningEnabled() const { return enabled.loadRelaxed() >> WarningShift & 1; }
- bool isCriticalEnabled() const { return enabled.loadRelaxed() >> CriticalShift & 1; }
-#endif
+
const char *categoryName() const { return name; }
// allows usage of both factory method and variable in qCX macros
@@ -87,19 +43,11 @@ private:
Q_DECL_UNUSED_MEMBER void *d; // reserved for future use
const char *name;
-#ifdef Q_BIG_ENDIAN
- enum { DebugShift = 0, WarningShift = 8, CriticalShift = 16, InfoShift = 24 };
-#else
- enum { DebugShift = 24, WarningShift = 16, CriticalShift = 8, InfoShift = 0};
-#endif
-
struct AtomicBools {
-#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
QBasicAtomicInteger<bool> enabledDebug;
QBasicAtomicInteger<bool> enabledWarning;
QBasicAtomicInteger<bool> enabledCritical;
QBasicAtomicInteger<bool> enabledInfo;
-#endif
};
union {
AtomicBools bools;
@@ -108,8 +56,58 @@ private:
Q_DECL_UNUSED_MEMBER bool placeholder[4]; // reserved for future use
};
+namespace { // allow different TUs to have different QT_NO_xxx_OUTPUT
+template <QtMsgType Which> struct QLoggingCategoryMacroHolder
+{
+ static const bool IsOutputEnabled;
+ const QLoggingCategory *category = nullptr;
+ bool control = false;
+ explicit QLoggingCategoryMacroHolder(const QLoggingCategory &cat)
+ {
+ if (IsOutputEnabled)
+ init(cat);
+ }
+ void init(const QLoggingCategory &cat) noexcept
+ {
+ category = &cat;
+ // same as:
+ // control = cat.isEnabled(Which);
+ // but without an out-of-line call
+ if constexpr (Which == QtDebugMsg) {
+ control = cat.isDebugEnabled();
+ } else if constexpr (Which == QtInfoMsg) {
+ control = cat.isInfoEnabled();
+ } else if constexpr (Which == QtWarningMsg) {
+ control = cat.isWarningEnabled();
+ } else if constexpr (Which == QtCriticalMsg) {
+ control = cat.isCriticalEnabled();
+ } else if constexpr (Which == QtFatalMsg) {
+ control = true;
+ } else {
+ static_assert(QtPrivate::value_dependent_false<Which>(), "Unknown Qt message type");
+ }
+ }
+ const char *name() const { return category->categoryName(); }
+ explicit operator bool() const { return Q_UNLIKELY(control); }
+};
+
+template <QtMsgType Which> const bool QLoggingCategoryMacroHolder<Which>::IsOutputEnabled = true;
+#if defined(QT_NO_DEBUG_OUTPUT)
+template <> const bool QLoggingCategoryMacroHolder<QtDebugMsg>::IsOutputEnabled = false;
+#endif
+#if defined(QT_NO_INFO_OUTPUT)
+template <> const bool QLoggingCategoryMacroHolder<QtInfoMsg>::IsOutputEnabled = false;
+#endif
+#if defined(QT_NO_WARNING_OUTPUT)
+template <> const bool QLoggingCategoryMacroHolder<QtWarningMsg>::IsOutputEnabled = false;
+#endif
+} // unnamed namespace
+
#define Q_DECLARE_LOGGING_CATEGORY(name) \
- extern const QLoggingCategory &name();
+ const QLoggingCategory &name();
+
+#define Q_DECLARE_EXPORTED_LOGGING_CATEGORY(name, export_macro) \
+ export_macro Q_DECLARE_LOGGING_CATEGORY(name)
#define Q_LOGGING_CATEGORY(name, ...) \
const QLoggingCategory &name() \
@@ -118,33 +116,15 @@ private:
return category; \
}
-#if !defined(QT_NO_DEBUG_OUTPUT)
-# define qCDebug(category, ...) \
- for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \
- QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).debug(__VA_ARGS__)
-#else
-# define qCDebug(category, ...) QT_NO_QDEBUG_MACRO()
-#endif
-
-#if !defined(QT_NO_INFO_OUTPUT)
-# define qCInfo(category, ...) \
- for (bool qt_category_enabled = category().isInfoEnabled(); qt_category_enabled; qt_category_enabled = false) \
- QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).info(__VA_ARGS__)
-#else
-# define qCInfo(category, ...) QT_NO_QDEBUG_MACRO()
-#endif
-
-#if !defined(QT_NO_WARNING_OUTPUT)
-# define qCWarning(category, ...) \
- for (bool qt_category_enabled = category().isWarningEnabled(); qt_category_enabled; qt_category_enabled = false) \
- QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).warning(__VA_ARGS__)
-#else
-# define qCWarning(category, ...) QT_NO_QDEBUG_MACRO()
-#endif
+#define QT_MESSAGE_LOGGER_COMMON(category, level) \
+ for (QLoggingCategoryMacroHolder<level> qt_category((category)()); qt_category; qt_category.control = false) \
+ QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, qt_category.name())
-#define qCCritical(category, ...) \
- for (bool qt_category_enabled = category().isCriticalEnabled(); qt_category_enabled; qt_category_enabled = false) \
- QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).critical(__VA_ARGS__)
+#define qCDebug(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtDebugMsg).debug(__VA_ARGS__)
+#define qCInfo(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtInfoMsg).info(__VA_ARGS__)
+#define qCWarning(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtWarningMsg).warning(__VA_ARGS__)
+#define qCCritical(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtCriticalMsg).critical(__VA_ARGS__)
+#define qCFatal(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtFatalMsg).fatal(__VA_ARGS__)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index 91d3e5a73c..b4181a2fa6 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qloggingregistry_p.h"
@@ -43,6 +7,7 @@
#include <QtCore/qlibraryinfo.h>
#include <QtCore/private/qlocking_p.h>
#include <QtCore/qstandardpaths.h>
+#include <QtCore/qstringtokenizer.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qdir.h>
#include <QtCore/qcoreapplication.h>
@@ -54,20 +19,20 @@
// We can't use the default macros because this would lead to recursion.
// Instead let's define our own one that unconditionally logs...
-#define debugMsg QMessageLogger(__FILE__, __LINE__, __FUNCTION__, "qt.core.logging").debug
-#define warnMsg QMessageLogger(__FILE__, __LINE__, __FUNCTION__, "qt.core.logging").warning
-
+#define debugMsg QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, "qt.core.logging").debug
+#define warnMsg QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, "qt.core.logging").warning
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry)
/*!
\internal
Constructs a logging rule with default values.
*/
-QLoggingRule::QLoggingRule() :
- enabled(false)
+QLoggingRule::QLoggingRule()
{
}
@@ -75,9 +40,7 @@ QLoggingRule::QLoggingRule() :
\internal
Constructs a logging rule.
*/
-QLoggingRule::QLoggingRule(QStringView pattern, bool enabled) :
- messageType(-1),
- enabled(enabled)
+QLoggingRule::QLoggingRule(QStringView pattern, bool enabled) : enabled(enabled)
{
parse(pattern);
}
@@ -87,7 +50,7 @@ QLoggingRule::QLoggingRule(QStringView pattern, bool enabled) :
Return value 1 means filter passed, 0 means filter doesn't influence this
category, -1 means category doesn't pass this filter.
*/
-int QLoggingRule::pass(QLatin1String cat, QtMsgType msgType) const
+int QLoggingRule::pass(QLatin1StringView cat, QtMsgType msgType) const
{
// check message type
if (messageType > -1 && messageType != msgType)
@@ -101,7 +64,7 @@ int QLoggingRule::pass(QLatin1String cat, QtMsgType msgType) const
return 0;
}
- const int idx = cat.indexOf(category);
+ const qsizetype idx = cat.indexOf(category);
if (idx >= 0) {
if (flags == MidFilter) {
// matches somewhere
@@ -112,7 +75,7 @@ int QLoggingRule::pass(QLatin1String cat, QtMsgType msgType) const
return (enabled ? 1 : -1);
} else if (flags == RightFilter) {
// matches right
- if (idx == (cat.size() - category.count()))
+ if (idx == (cat.size() - category.size()))
return (enabled ? 1 : -1);
}
}
@@ -133,34 +96,35 @@ void QLoggingRule::parse(QStringView pattern)
QStringView p;
// strip trailing ".messagetype"
- if (pattern.endsWith(QLatin1String(".debug"))) {
+ if (pattern.endsWith(".debug"_L1)) {
p = pattern.chopped(6); // strlen(".debug")
messageType = QtDebugMsg;
- } else if (pattern.endsWith(QLatin1String(".info"))) {
+ } else if (pattern.endsWith(".info"_L1)) {
p = pattern.chopped(5); // strlen(".info")
messageType = QtInfoMsg;
- } else if (pattern.endsWith(QLatin1String(".warning"))) {
+ } else if (pattern.endsWith(".warning"_L1)) {
p = pattern.chopped(8); // strlen(".warning")
messageType = QtWarningMsg;
- } else if (pattern.endsWith(QLatin1String(".critical"))) {
+ } else if (pattern.endsWith(".critical"_L1)) {
p = pattern.chopped(9); // strlen(".critical")
messageType = QtCriticalMsg;
} else {
p = pattern;
}
- if (!p.contains(QLatin1Char('*'))) {
+ const QChar asterisk = u'*';
+ if (!p.contains(asterisk)) {
flags = FullText;
} else {
- if (p.endsWith(QLatin1Char('*'))) {
+ if (p.endsWith(asterisk)) {
flags |= LeftFilter;
p = p.chopped(1);
}
- if (p.startsWith(QLatin1Char('*'))) {
+ if (p.startsWith(asterisk)) {
flags |= RightFilter;
p = p.mid(1);
}
- if (p.contains(QLatin1Char('*'))) // '*' only supported at start/end
+ if (p.contains(asterisk)) // '*' only supported at start/end
flags = PatternFlags();
}
@@ -186,11 +150,10 @@ void QLoggingRule::parse(QStringView pattern)
\internal
Parses configuration from \a content.
*/
-void QLoggingSettingsParser::setContent(const QString &content)
+void QLoggingSettingsParser::setContent(QStringView content)
{
_rules.clear();
- const auto lines = QStringView{content}.split(QLatin1Char('\n'));
- for (const auto &line : lines)
+ for (auto line : qTokenize(content, u'\n'))
parseNextLine(line);
}
@@ -208,7 +171,7 @@ void QLoggingSettingsParser::setContent(QTextStream &stream)
/*!
\internal
- Parses one line of the configuation file
+ Parses one line of the configuration file
*/
void QLoggingSettingsParser::parseNextLine(QStringView line)
@@ -217,33 +180,33 @@ void QLoggingSettingsParser::parseNextLine(QStringView line)
line = line.trimmed();
// comment
- if (line.startsWith(QLatin1Char(';')))
+ if (line.startsWith(u';'))
return;
- if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) {
+ if (line.startsWith(u'[') && line.endsWith(u']')) {
// new section
auto sectionName = line.mid(1).chopped(1).trimmed();
- m_inRulesSection = sectionName.compare(QLatin1String("rules"), Qt::CaseInsensitive) == 0;
+ m_inRulesSection = sectionName.compare("rules"_L1, Qt::CaseInsensitive) == 0;
return;
}
if (m_inRulesSection) {
- int equalPos = line.indexOf(QLatin1Char('='));
+ const qsizetype equalPos = line.indexOf(u'=');
if (equalPos != -1) {
- if (line.lastIndexOf(QLatin1Char('=')) == equalPos) {
+ if (line.lastIndexOf(u'=') == equalPos) {
const auto key = line.left(equalPos).trimmed();
#if QT_CONFIG(settings)
QString tmp;
- QSettingsPrivate::iniUnescapedKey(key.toUtf8(), 0, key.length(), tmp);
+ QSettingsPrivate::iniUnescapedKey(key.toUtf8(), tmp);
QStringView pattern = qToStringViewIgnoringNull(tmp);
#else
QStringView pattern = key;
#endif
const auto valueStr = line.mid(equalPos + 1).trimmed();
int value = -1;
- if (valueStr == QLatin1String("true"))
+ if (valueStr == "true"_L1)
value = 1;
- else if (valueStr == QLatin1String("false"))
+ else if (valueStr == "false"_L1)
value = 0;
QLoggingRule rule(pattern, (value == 1));
if (rule.flags != 0 && (value != -1))
@@ -278,20 +241,29 @@ QLoggingRegistry::QLoggingRegistry()
static bool qtLoggingDebug()
{
- static const bool debugEnv = qEnvironmentVariableIsSet("QT_LOGGING_DEBUG");
+ static const bool debugEnv = [] {
+ bool debug = qEnvironmentVariableIsSet("QT_LOGGING_DEBUG");
+ if (debug)
+ debugMsg("QT_LOGGING_DEBUG environment variable is set.");
+ return debug;
+ }();
return debugEnv;
}
static QList<QLoggingRule> loadRulesFromFile(const QString &filePath)
{
+ if (qtLoggingDebug()) {
+ debugMsg("Checking \"%s\" for rules",
+ QDir::toNativeSeparators(filePath).toUtf8().constData());
+ }
+
QFile file(filePath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- if (qtLoggingDebug())
- debugMsg("Loading \"%s\" ...",
- QDir::toNativeSeparators(file.fileName()).toUtf8().constData());
QTextStream stream(&file);
QLoggingSettingsParser parser;
parser.setContent(stream);
+ if (qtLoggingDebug())
+ debugMsg("Loaded %td rules", static_cast<ptrdiff_t>(parser.rules().size()));
return parser.rules();
}
return QList<QLoggingRule>();
@@ -304,19 +276,30 @@ static QList<QLoggingRule> loadRulesFromFile(const QString &filePath)
*/
void QLoggingRegistry::initializeRules()
{
+ if (qtLoggingDebug()) {
+ debugMsg("Initializing the rules database ...");
+ debugMsg("Checking %s environment variable", "QTLOGGING_CONF");
+ }
QList<QLoggingRule> er, qr, cr;
// get rules from environment
const QByteArray rulesFilePath = qgetenv("QT_LOGGING_CONF");
if (!rulesFilePath.isEmpty())
er = loadRulesFromFile(QFile::decodeName(rulesFilePath));
+ if (qtLoggingDebug())
+ debugMsg("Checking %s environment variable", "QT_LOGGING_RULES");
+
const QByteArray rulesSrc = qgetenv("QT_LOGGING_RULES").replace(';', '\n');
if (!rulesSrc.isEmpty()) {
- QTextStream stream(rulesSrc);
- QLoggingSettingsParser parser;
- parser.setImplicitRulesSection(true);
- parser.setContent(stream);
- er += parser.rules();
+ QTextStream stream(rulesSrc);
+ QLoggingSettingsParser parser;
+ parser.setImplicitRulesSection(true);
+ parser.setContent(stream);
+
+ if (qtLoggingDebug())
+ debugMsg("Loaded %td rules", static_cast<ptrdiff_t>(parser.rules().size()));
+
+ er += parser.rules();
}
const QString configFileName = QStringLiteral("qtlogging.ini");
@@ -324,7 +307,7 @@ void QLoggingRegistry::initializeRules()
#if !defined(QT_BOOTSTRAPPED)
// get rules from Qt data configuration path
const QString qtConfigPath
- = QDir(QLibraryInfo::location(QLibraryInfo::DataPath)).absoluteFilePath(configFileName);
+ = QDir(QLibraryInfo::path(QLibraryInfo::DataPath)).absoluteFilePath(configFileName);
qr = loadRulesFromFile(qtConfigPath);
#endif
@@ -354,8 +337,11 @@ void QLoggingRegistry::registerCategory(QLoggingCategory *cat, QtMsgType enableF
{
const auto locker = qt_scoped_lock(registryMutex);
- if (!categories.contains(cat)) {
- categories.insert(cat, enableForLevel);
+ const auto oldSize = categories.size();
+ auto &e = categories[cat];
+ if (categories.size() != oldSize) {
+ // new entry
+ e = enableForLevel;
(*categoryFilter)(cat);
}
}
@@ -371,6 +357,20 @@ void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat)
}
/*!
+ \since 6.3
+ \internal
+
+ Registers the environment variable \a environment as the control variable
+ for enabling debugging by default for category \a categoryName. The
+ category name must start with "qt."
+*/
+void QLoggingRegistry::registerEnvironmentOverrideForCategory(const char *categoryName,
+ const char *environment)
+{
+ qtCategoryEnvironmentOverrides.insert_or_assign(categoryName, environment);
+}
+
+/*!
\internal
Installs logging rules as specified in \a content.
*/
@@ -451,11 +451,19 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
// qt.debug=false
if (const char *categoryName = cat->categoryName()) {
// == "qt" or startsWith("qt.")
- if (strcmp(categoryName, "qt") == 0 || strncmp(categoryName, "qt.", 3) == 0)
+ if (strcmp(categoryName, "qt") == 0) {
debug = false;
+ } else if (strncmp(categoryName, "qt.", 3) == 0) {
+ // may be overridden
+ auto it = reg->qtCategoryEnvironmentOverrides.find(categoryName);
+ if (it == reg->qtCategoryEnvironmentOverrides.end())
+ debug = false;
+ else
+ debug = qEnvironmentVariableIntValue(it->second);
+ }
}
- const auto categoryName = QLatin1String(cat->categoryName());
+ const auto categoryName = QLatin1StringView(cat->categoryName());
for (const auto &ruleSet : reg->ruleSets) {
for (const auto &rule : ruleSet) {
diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h
index 1a924f07dc..92b96f0ba4 100644
--- a/src/corelib/io/qloggingregistry_p.h
+++ b/src/corelib/io/qloggingregistry_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOGGINGREGISTRY_P_H
#define QLOGGINGREGISTRY_P_H
@@ -54,48 +18,60 @@
#include <QtCore/private/qglobal_p.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qlist.h>
-#include <QtCore/qmap.h>
+#include <QtCore/qhash.h>
#include <QtCore/qmutex.h>
#include <QtCore/qstring.h>
#include <QtCore/qtextstream.h>
+#include <map>
+
class tst_QLoggingRegistry;
QT_BEGIN_NAMESPACE
+#define Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(name, env, categoryName) \
+ const QLoggingCategory &name() \
+ { \
+ static constexpr char cname[] = categoryName; \
+ static_assert(cname[0] == 'q' && cname[1] == 't' && cname[2] == '.' \
+ && cname[4] != '\0', "Category name must start with 'qt.'"); \
+ static const QLoggingCategoryWithEnvironmentOverride category(cname, env); \
+ return category; \
+ }
+
class Q_AUTOTEST_EXPORT QLoggingRule
{
public:
QLoggingRule();
QLoggingRule(QStringView pattern, bool enabled);
- int pass(QLatin1String categoryName, QtMsgType type) const;
+ int pass(QLatin1StringView categoryName, QtMsgType type) const;
enum PatternFlag {
FullText = 0x1,
LeftFilter = 0x2,
RightFilter = 0x4,
- MidFilter = LeftFilter | RightFilter
+ MidFilter = LeftFilter | RightFilter
};
Q_DECLARE_FLAGS(PatternFlags, PatternFlag)
QString category;
- int messageType;
+ int messageType = -1;
PatternFlags flags;
- bool enabled;
+ bool enabled = false;
private:
void parse(QStringView pattern);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
-Q_DECLARE_TYPEINFO(QLoggingRule, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QLoggingRule, Q_RELOCATABLE_TYPE);
class Q_AUTOTEST_EXPORT QLoggingSettingsParser
{
public:
void setImplicitRulesSection(bool inRulesSection) { m_inRulesSection = inRulesSection; }
- void setContent(const QString &content);
+ void setContent(QStringView content);
void setContent(QTextStream &stream);
QList<QLoggingRule> rules() const { return _rules; }
@@ -110,6 +86,7 @@ private:
class Q_AUTOTEST_EXPORT QLoggingRegistry
{
+ Q_DISABLE_COPY_MOVE(QLoggingRegistry)
public:
QLoggingRegistry();
@@ -118,6 +95,11 @@ public:
void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel);
void unregisterCategory(QLoggingCategory *category);
+#ifndef QT_BUILD_INTERNAL
+ Q_CORE_EXPORT // always export from QtCore
+#endif
+ void registerEnvironmentOverrideForCategory(const char *categoryName, const char *environment);
+
void setApiRules(const QString &content);
QLoggingCategory::CategoryFilter
@@ -144,12 +126,30 @@ private:
// protected by mutex:
QList<QLoggingRule> ruleSets[NumRuleSets];
- QHash<QLoggingCategory*,QtMsgType> categories;
+ QHash<QLoggingCategory *, QtMsgType> categories;
QLoggingCategory::CategoryFilter categoryFilter;
+ std::map<QByteArrayView, const char *> qtCategoryEnvironmentOverrides;
friend class ::tst_QLoggingRegistry;
};
+class QLoggingCategoryWithEnvironmentOverride : public QLoggingCategory
+{
+public:
+ QLoggingCategoryWithEnvironmentOverride(const char *category, const char *env)
+ : QLoggingCategory(registerOverride(category, env), QtInfoMsg)
+ {}
+
+private:
+ static const char *registerOverride(const char *categoryName, const char *environment)
+ {
+ QLoggingRegistry *c = QLoggingRegistry::instance();
+ if (c)
+ c->registerEnvironmentOverrideForCategory(categoryName, environment);
+ return categoryName;
+ }
+};
+
QT_END_NAMESPACE
#endif // QLOGGINGREGISTRY_P_H
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index df0197e8eb..260fea7969 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qnoncontiguousbytedevice_p.h"
#include <qbuffer.h>
@@ -136,14 +100,18 @@ QNonContiguousByteDevice::~QNonContiguousByteDevice()
}
// FIXME we should scrap this whole implementation and instead change the ByteArrayImpl to be able to cope with sub-arrays?
-QNonContiguousByteDeviceBufferImpl::QNonContiguousByteDeviceBufferImpl(QBuffer *b) : QNonContiguousByteDevice()
+QNonContiguousByteDeviceBufferImpl::QNonContiguousByteDeviceBufferImpl(QBuffer *b)
+ : QNonContiguousByteDevice(),
+ buffer(b),
+ byteArray(QByteArray::fromRawData(buffer->buffer().constData() + buffer->pos(),
+ buffer->size() - buffer->pos())),
+ arrayImpl(new QNonContiguousByteDeviceByteArrayImpl(&byteArray))
{
- buffer = b;
- byteArray = QByteArray::fromRawData(buffer->buffer().constData() + buffer->pos(), buffer->size() - buffer->pos());
- arrayImpl = new QNonContiguousByteDeviceByteArrayImpl(&byteArray);
arrayImpl->setParent(this);
- connect(arrayImpl, SIGNAL(readyRead()), SIGNAL(readyRead()));
- connect(arrayImpl, SIGNAL(readProgress(qint64,qint64)), SIGNAL(readProgress(qint64,qint64)));
+ connect(arrayImpl, &QNonContiguousByteDevice::readyRead, this,
+ &QNonContiguousByteDevice::readyRead);
+ connect(arrayImpl, &QNonContiguousByteDevice::readProgress, this,
+ &QNonContiguousByteDevice::readProgress);
}
QNonContiguousByteDeviceBufferImpl::~QNonContiguousByteDeviceBufferImpl()
@@ -175,9 +143,9 @@ qint64 QNonContiguousByteDeviceBufferImpl::size() const
return arrayImpl->size();
}
-QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba) : QNonContiguousByteDevice(), currentPosition(0)
+QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba)
+ : QNonContiguousByteDevice(), byteArray(ba), currentPosition(0)
{
- byteArray = ba;
}
QNonContiguousByteDeviceByteArrayImpl::~QNonContiguousByteDeviceByteArrayImpl()
@@ -227,10 +195,9 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::pos() const
return currentPosition;
}
-QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
- : QNonContiguousByteDevice(), currentPosition(0)
+QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(std::shared_ptr<QRingBuffer> rb)
+ : QNonContiguousByteDevice(), ringBuffer(std::move(rb))
{
- ringBuffer = rb;
}
QNonContiguousByteDeviceRingBufferImpl::~QNonContiguousByteDeviceRingBufferImpl()
@@ -282,14 +249,19 @@ qint64 QNonContiguousByteDeviceRingBufferImpl::size() const
QNonContiguousByteDeviceIoDeviceImpl::QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d)
: QNonContiguousByteDevice(),
- currentReadBuffer(nullptr), currentReadBufferSize(16*1024),
- currentReadBufferAmount(0), currentReadBufferPosition(0), totalAdvancements(0),
- eof(false)
+ device(d),
+ currentReadBuffer(nullptr),
+ currentReadBufferSize(16 * 1024),
+ currentReadBufferAmount(0),
+ currentReadBufferPosition(0),
+ totalAdvancements(0),
+ eof(false),
+ initialPosition(d->pos())
{
- device = d;
- initialPosition = d->pos();
- connect(device, SIGNAL(readyRead()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
- connect(device, SIGNAL(readChannelFinished()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+ connect(device, &QIODevice::readyRead, this,
+ &QNonContiguousByteDevice::readyRead);
+ connect(device, &QIODevice::readChannelFinished, this,
+ &QNonContiguousByteDevice::readyRead);
}
QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl()
@@ -297,9 +269,9 @@ QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl()
delete currentReadBuffer;
}
-const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len)
+const char *QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len)
{
- if (eof == true) {
+ if (eof) {
len = -1;
return nullptr;
}
@@ -315,7 +287,8 @@ const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLeng
return currentReadBuffer->data() + currentReadBufferPosition;
}
- qint64 haveRead = device->read(currentReadBuffer->data(), qMin(maximumLength, currentReadBufferSize));
+ qint64 haveRead = device->read(currentReadBuffer->data(),
+ qMin(maximumLength, currentReadBufferSize));
if ((haveRead == -1) || (haveRead == 0 && device->atEnd() && !device->isSequential())) {
eof = true;
@@ -349,7 +322,7 @@ bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount)
if (currentReadBufferPosition > currentReadBufferAmount) {
qint64 i = currentReadBufferPosition - currentReadBufferAmount;
while (i > 0) {
- if (device->getChar(nullptr) == false) {
+ if (!device->getChar(nullptr)) {
emit readProgress(totalAdvancements - i, size());
return false; // ### FIXME handle eof
}
@@ -360,13 +333,12 @@ bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount)
currentReadBufferAmount = 0;
}
-
return true;
}
bool QNonContiguousByteDeviceIoDeviceImpl::atEnd() const
{
- return eof == true;
+ return eof;
}
bool QNonContiguousByteDeviceIoDeviceImpl::reset()
@@ -374,7 +346,7 @@ bool QNonContiguousByteDeviceIoDeviceImpl::reset()
bool reset = (initialPosition == 0) ? device->reset() : device->seek(initialPosition);
if (reset) {
eof = false; // assume eof is false, it will be true after a read has been attempted
- totalAdvancements = 0; //reset the progress counter
+ totalAdvancements = 0; // reset the progress counter
if (currentReadBuffer) {
delete currentReadBuffer;
currentReadBuffer = nullptr;
@@ -405,18 +377,16 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::pos() const
return device->pos();
}
-QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)nullptr)
+QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd)
+ : QIODevice(nullptr), byteDevice(bd)
{
- byteDevice = bd;
- connect(bd, SIGNAL(readyRead()), SIGNAL(readyRead()));
+ connect(bd, &QNonContiguousByteDevice::readyRead, this, &QIODevice::readyRead);
open(ReadOnly);
}
QByteDeviceWrappingIoDevice::~QByteDeviceWrappingIoDevice()
-{
-
-}
+ = default;
bool QByteDeviceWrappingIoDevice::isSequential() const
{
@@ -441,8 +411,7 @@ qint64 QByteDeviceWrappingIoDevice::size() const
return byteDevice->size();
}
-
-qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize)
+qint64 QByteDeviceWrappingIoDevice::readData(char *data, qint64 maxSize)
{
qint64 len;
const char *readPointer = byteDevice->readPointer(maxSize, len);
@@ -454,7 +423,7 @@ qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize)
return len;
}
-qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize)
+qint64 QByteDeviceWrappingIoDevice::writeData(const char *data, qint64 maxSize)
{
Q_UNUSED(data);
Q_UNUSED(maxSize);
@@ -482,10 +451,10 @@ qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize)
\internal
*/
-QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device)
+QNonContiguousByteDevice *QNonContiguousByteDeviceFactory::create(QIODevice *device)
{
// shortcut if it is a QBuffer
- if (QBuffer* buffer = qobject_cast<QBuffer*>(device)) {
+ if (QBuffer *buffer = qobject_cast<QBuffer *>(device)) {
return new QNonContiguousByteDeviceBufferImpl(buffer);
}
@@ -497,44 +466,46 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *dev
}
/*!
- Create a QNonContiguousByteDevice out of a QIODevice, return it in a QSharedPointer.
+ Create a QNonContiguousByteDevice out of a QIODevice, return it in a std::shared_ptr.
For QFile, QBuffer and all other QIODevice, sequential or not.
\internal
*/
-QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QIODevice *device)
+std::shared_ptr<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QIODevice *device)
{
// shortcut if it is a QBuffer
if (QBuffer *buffer = qobject_cast<QBuffer*>(device))
- return QSharedPointer<QNonContiguousByteDeviceBufferImpl>::create(buffer);
+ return std::make_shared<QNonContiguousByteDeviceBufferImpl>(buffer);
// ### FIXME special case if device is a QFile that supports map()
// then we can actually deal with the file without using read/peek
// generic QIODevice
- return QSharedPointer<QNonContiguousByteDeviceIoDeviceImpl>::create(device); // FIXME
+ return std::make_shared<QNonContiguousByteDeviceIoDeviceImpl>(device); // FIXME
}
/*!
- \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer<QRingBuffer> ringBuffer)
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(std::shared_ptr<QRingBuffer> ringBuffer)
Create a QNonContiguousByteDevice out of a QRingBuffer.
\internal
*/
-QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer<QRingBuffer> ringBuffer)
+QNonContiguousByteDevice *
+QNonContiguousByteDeviceFactory::create(std::shared_ptr<QRingBuffer> ringBuffer)
{
- return new QNonContiguousByteDeviceRingBufferImpl(ringBuffer);
+ return new QNonContiguousByteDeviceRingBufferImpl(std::move(ringBuffer));
}
/*!
- Create a QNonContiguousByteDevice out of a QRingBuffer, return it in a QSharedPointer.
+ Create a QNonContiguousByteDevice out of a QRingBuffer, return it in a std::shared_ptr.
\internal
*/
-QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QSharedPointer<QRingBuffer> ringBuffer)
+std::shared_ptr<QNonContiguousByteDevice>
+QNonContiguousByteDeviceFactory::createShared(std::shared_ptr<QRingBuffer> ringBuffer)
{
- return QSharedPointer<QNonContiguousByteDeviceRingBufferImpl>::create(std::move(ringBuffer));
+ return std::make_shared<QNonContiguousByteDeviceRingBufferImpl>(std::move(ringBuffer));
}
/*!
@@ -554,9 +525,10 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *by
\internal
*/
-QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QByteArray *byteArray)
+std::shared_ptr<QNonContiguousByteDevice>
+QNonContiguousByteDeviceFactory::createShared(QByteArray *byteArray)
{
- return QSharedPointer<QNonContiguousByteDeviceByteArrayImpl>::create(byteArray);
+ return std::make_shared<QNonContiguousByteDeviceByteArrayImpl>(byteArray);
}
/*!
@@ -566,7 +538,7 @@ QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::create
\internal
*/
-QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
+QIODevice *QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice *byteDevice)
{
// ### FIXME if it already has been based on QIoDevice, we could that one out again
// and save some calling
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index bbc4ea5ae2..eb75034c6a 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QNONCONTIGUOUSBYTEDEVICE_P_H
#define QNONCONTIGUOUSBYTEDEVICE_P_H
@@ -55,16 +19,17 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qiodevice.h>
-#include <QtCore/QSharedPointer>
#include "private/qringbuffer_p.h"
+#include <memory>
+
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QNonContiguousByteDevice : public QObject
{
Q_OBJECT
public:
- virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
+ virtual const char *readPointer(qint64 maximumLength, qint64 &len) = 0;
virtual bool advanceReadPointer(qint64 amount) = 0;
virtual bool atEnd() const = 0;
virtual qint64 pos() const { return -1; }
@@ -76,7 +41,6 @@ public:
protected:
QNonContiguousByteDevice();
-
Q_SIGNALS:
void readyRead();
void readProgress(qint64 current, qint64 total);
@@ -85,16 +49,16 @@ Q_SIGNALS:
class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
{
public:
- static QNonContiguousByteDevice* create(QIODevice *device);
- static QSharedPointer<QNonContiguousByteDevice> createShared(QIODevice *device);
+ static QNonContiguousByteDevice *create(QIODevice *device);
+ static std::shared_ptr<QNonContiguousByteDevice> createShared(QIODevice *device);
- static QNonContiguousByteDevice* create(QByteArray *byteArray);
- static QSharedPointer<QNonContiguousByteDevice> createShared(QByteArray *byteArray);
+ static QNonContiguousByteDevice *create(QByteArray *byteArray);
+ static std::shared_ptr<QNonContiguousByteDevice> createShared(QByteArray *byteArray);
- static QNonContiguousByteDevice* create(QSharedPointer<QRingBuffer> ringBuffer);
- static QSharedPointer<QNonContiguousByteDevice> createShared(QSharedPointer<QRingBuffer> ringBuffer);
+ static QNonContiguousByteDevice *create(std::shared_ptr<QRingBuffer> ringBuffer);
+ static std::shared_ptr<QNonContiguousByteDevice> createShared(std::shared_ptr<QRingBuffer> ringBuffer);
- static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
+ static QIODevice *wrap(QNonContiguousByteDevice *byteDevice);
};
// the actual implementations
@@ -102,52 +66,56 @@ public:
class QNonContiguousByteDeviceByteArrayImpl : public QNonContiguousByteDevice
{
+ Q_OBJECT
public:
- QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba);
+ explicit QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba);
~QNonContiguousByteDeviceByteArrayImpl();
- const char* readPointer(qint64 maximumLength, qint64 &len) override;
+ const char *readPointer(qint64 maximumLength, qint64 &len) override;
bool advanceReadPointer(qint64 amount) override;
bool atEnd() const override;
bool reset() override;
qint64 size() const override;
qint64 pos() const override;
+
protected:
- QByteArray* byteArray;
+ QByteArray *byteArray;
qint64 currentPosition;
};
class QNonContiguousByteDeviceRingBufferImpl : public QNonContiguousByteDevice
{
+ Q_OBJECT
public:
- QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb);
+ explicit QNonContiguousByteDeviceRingBufferImpl(std::shared_ptr<QRingBuffer> rb);
~QNonContiguousByteDeviceRingBufferImpl();
- const char* readPointer(qint64 maximumLength, qint64 &len) override;
+ const char *readPointer(qint64 maximumLength, qint64 &len) override;
bool advanceReadPointer(qint64 amount) override;
bool atEnd() const override;
bool reset() override;
qint64 size() const override;
qint64 pos() const override;
+
protected:
- QSharedPointer<QRingBuffer> ringBuffer;
- qint64 currentPosition;
+ std::shared_ptr<QRingBuffer> ringBuffer;
+ qint64 currentPosition = 0;
};
-
class QNonContiguousByteDeviceIoDeviceImpl : public QNonContiguousByteDevice
{
Q_OBJECT
public:
- QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d);
+ explicit QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d);
~QNonContiguousByteDeviceIoDeviceImpl();
- const char* readPointer(qint64 maximumLength, qint64 &len) override;
+ const char *readPointer(qint64 maximumLength, qint64 &len) override;
bool advanceReadPointer(qint64 amount) override;
bool atEnd() const override;
bool reset() override;
qint64 size() const override;
qint64 pos() const override;
+
protected:
- QIODevice* device;
- QByteArray* currentReadBuffer;
+ QIODevice *device;
+ QByteArray *currentReadBuffer;
qint64 currentReadBufferSize;
qint64 currentReadBufferAmount;
qint64 currentReadBufferPosition;
@@ -160,34 +128,37 @@ class QNonContiguousByteDeviceBufferImpl : public QNonContiguousByteDevice
{
Q_OBJECT
public:
- QNonContiguousByteDeviceBufferImpl(QBuffer *b);
+ explicit QNonContiguousByteDeviceBufferImpl(QBuffer *b);
~QNonContiguousByteDeviceBufferImpl();
- const char* readPointer(qint64 maximumLength, qint64 &len) override;
+ const char *readPointer(qint64 maximumLength, qint64 &len) override;
bool advanceReadPointer(qint64 amount) override;
bool atEnd() const override;
bool reset() override;
qint64 size() const override;
+
protected:
- QBuffer* buffer;
+ QBuffer *buffer;
QByteArray byteArray;
- QNonContiguousByteDeviceByteArrayImpl* arrayImpl;
+ QNonContiguousByteDeviceByteArrayImpl *arrayImpl;
};
// ... and the reverse thing
class QByteDeviceWrappingIoDevice : public QIODevice
{
+ Q_OBJECT
public:
- QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd);
- ~QByteDeviceWrappingIoDevice ();
+ explicit QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd);
+ ~QByteDeviceWrappingIoDevice();
bool isSequential() const override;
bool atEnd() const override;
bool reset() override;
qint64 size() const override;
+
protected:
qint64 readData(char *data, qint64 maxSize) override;
qint64 writeData(const char *data, qint64 maxSize) override;
- QNonContiguousByteDevice *byteDevice;
+ QNonContiguousByteDevice *byteDevice;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qntdll_p.h b/src/corelib/io/qntdll_p.h
new file mode 100644
index 0000000000..1669d4a6dd
--- /dev/null
+++ b/src/corelib/io/qntdll_p.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QNTDLL_P_H
+#define QNTDLL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+#include <winternl.h>
+
+QT_BEGIN_NAMESPACE
+
+// keep the following structure as is, taken from
+// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_file_fs_sector_size_information
+// Unfortunately we can't include the ntddk.h header, so we duplicate the code here.
+typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION {
+ ULONG LogicalBytesPerSector;
+ ULONG PhysicalBytesPerSectorForAtomicity;
+ ULONG PhysicalBytesPerSectorForPerformance;
+ ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
+ ULONG Flags;
+ ULONG ByteOffsetForSectorAlignment;
+ ULONG ByteOffsetForPartitionAlignment;
+} FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION;
+
+#if !defined(Q_CC_MINGW)
+// keep the following enumeration as is, taken from
+// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_fsinfoclass
+// Unfortunately we can't include the wdm.h header, so we duplicate the code here.
+typedef enum _FSINFOCLASS {
+ FileFsVolumeInformation,
+ FileFsLabelInformation,
+ FileFsSizeInformation,
+ FileFsDeviceInformation,
+ FileFsAttributeInformation,
+ FileFsControlInformation,
+ FileFsFullSizeInformation,
+ FileFsObjectIdInformation,
+ FileFsDriverPathInformation,
+ FileFsVolumeFlagsInformation,
+ FileFsSectorSizeInformation,
+ FileFsDataCopyInformation,
+ FileFsMetadataSizeInformation,
+ FileFsFullSizeInformationEx,
+ FileFsMaximumInformation
+} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QNTDLL_P_H
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 5e19f7256f..108ee0b7c3 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1,105 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QPROCESS_DEBUG
#include <qdebug.h>
#include <qdir.h>
#include <qscopedvaluerollback.h>
-#if defined(Q_OS_WIN)
-#include <qtimer.h>
-#endif
-#if defined QPROCESS_DEBUG
-#include <qstring.h>
-#include <ctype.h>
-
-QT_BEGIN_NAMESPACE
-/*
- Returns a human readable representation of the first \a len
- characters in \a data.
-*/
-static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
-{
- if (!data) return "(null)";
- QByteArray out;
- for (int i = 0; i < len && i < maxSize; ++i) {
- char c = data[i];
- if (isprint(c)) {
- out += c;
- } else switch (c) {
- case '\n': out += "\\n"; break;
- case '\r': out += "\\r"; break;
- case '\t': out += "\\t"; break;
- default:
- char buf[5];
- qsnprintf(buf, sizeof(buf), "\\%3o", c);
- buf[4] = '\0';
- out += QByteArray(buf);
- }
- }
-
- if (len < maxSize)
- out += "...";
-
- return out;
-}
-
-QT_END_NAMESPACE
-
-#endif
#include "qprocess.h"
#include "qprocess_p.h"
#include <qbytearray.h>
-#include <qelapsedtimer.h>
+#include <qdeadlinetimer.h>
#include <qcoreapplication.h>
-#include <qsocketnotifier.h>
#include <qtimer.h>
-#ifdef Q_OS_WIN
-#include <qwineventnotifier.h>
-#else
-#include <private/qcore_unix_p.h>
-#endif
-
#if __has_include(<paths.h>)
#include <paths.h>
#endif
@@ -119,6 +35,8 @@ QT_BEGIN_NAMESPACE
\reentrant
\since 4.6
+ \compares equality
+
A process's environment is composed of a set of key=value pairs known as
environment variables. The QProcessEnvironment class wraps that concept
and allows easy manipulation of those variables. It's meant to be used
@@ -146,7 +64,7 @@ QStringList QProcessEnvironmentPrivate::toList() const
QStringList result;
result.reserve(vars.size());
for (auto it = vars.cbegin(), end = vars.cend(); it != end; ++it)
- result << nameToString(it.key()) + QLatin1Char('=') + valueToString(it.value());
+ result << nameToString(it.key()) + u'=' + valueToString(it.value());
return result;
}
@@ -156,7 +74,7 @@ QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list
QStringList::ConstIterator it = list.constBegin(),
end = list.constEnd();
for ( ; it != end; ++it) {
- int pos = it->indexOf(QLatin1Char('='), 1);
+ const qsizetype pos = it->indexOf(u'=', 1);
if (pos < 1)
continue;
@@ -196,14 +114,43 @@ void QProcessEnvironmentPrivate::insert(const QProcessEnvironmentPrivate &other)
}
/*!
+ \enum QProcessEnvironment::Initialization
+
+ This enum contains a token that is used to disambiguate constructors.
+
+ \value InheritFromParent A QProcessEnvironment will be created that, when
+ set on a QProcess, causes it to inherit variables from its parent.
+
+ \since 6.3
+*/
+
+/*!
Creates a new QProcessEnvironment object. This constructor creates an
empty environment. If set on a QProcess, this will cause the current
- environment variables to be removed.
+ environment variables to be removed (except for PATH and SystemRoot
+ on Windows).
*/
-QProcessEnvironment::QProcessEnvironment()
- : d(nullptr)
-{
-}
+QProcessEnvironment::QProcessEnvironment() : d(new QProcessEnvironmentPrivate) { }
+
+/*!
+ Creates an object that when set on QProcess will cause it to be executed with
+ environment variables inherited from its parent process.
+
+ \note The created object does not store any environment variables by itself,
+ it just indicates to QProcess to arrange for inheriting the environment at the
+ time when the new process is started. Adding any environment variables to
+ the created object will disable inheritance of the environment and result in
+ an environment containing only the added environment variables.
+
+ If a modified version of the parent environment is wanted, start with the
+ return value of \c systemEnvironment() and modify that (but note that changes to
+ the parent process's environment after that is created won't be reflected
+ in the modified environment).
+
+ \sa inheritsFromParent(), systemEnvironment()
+ \since 6.3
+*/
+QProcessEnvironment::QProcessEnvironment(QProcessEnvironment::Initialization) noexcept { }
/*!
Frees the resources associated with this QProcessEnvironment object.
@@ -239,15 +186,17 @@ QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &o
*/
/*!
- \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const
+ \fn bool QProcessEnvironment::operator!=(const QProcessEnvironment &lhs, const QProcessEnvironment &rhs)
- Returns \c true if this and the \a other QProcessEnvironment objects are different.
+ Returns \c true if the process environment objects \a lhs and \a rhs are different.
\sa operator==()
*/
/*!
- Returns \c true if this and the \a other QProcessEnvironment objects are equal.
+ \fn bool QProcessEnvironment::operator==(const QProcessEnvironment &lhs, const QProcessEnvironment &rhs)
+
+ Returns \c true if the process environment objects \a lhs and \a rhs are equal.
Two QProcessEnvironment objects are considered equal if they have the same
set of key=value pairs. The comparison of keys is done case-sensitive on
@@ -255,26 +204,22 @@ QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &o
\sa operator!=(), contains()
*/
-bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const
+bool comparesEqual(const QProcessEnvironment &lhs, const QProcessEnvironment &rhs)
{
- if (d == other.d)
+ if (lhs.d == rhs.d)
return true;
- if (d) {
- if (other.d) {
- return d->vars == other.d->vars;
- } else {
- return isEmpty();
- }
- } else {
- return other.isEmpty();
- }
+
+ return lhs.d && rhs.d && lhs.d->vars == rhs.d->vars;
}
/*!
Returns \c true if this QProcessEnvironment object is empty: that is
there are no key=value pairs set.
- \sa clear(), systemEnvironment(), insert()
+ This method also returns \c true for objects that were constructed using
+ \c{QProcessEnvironment::InheritFromParent}.
+
+ \sa clear(), systemEnvironment(), insert(), inheritsFromParent()
*/
bool QProcessEnvironment::isEmpty() const
{
@@ -283,14 +228,29 @@ bool QProcessEnvironment::isEmpty() const
}
/*!
+ Returns \c true if this QProcessEnvironment was constructed using
+ \c{QProcessEnvironment::InheritFromParent}.
+
+ \since 6.3
+ \sa isEmpty()
+*/
+bool QProcessEnvironment::inheritsFromParent() const
+{
+ return !d;
+}
+
+/*!
Removes all key=value pairs from this QProcessEnvironment object, making
it empty.
+ If the environment was constructed using \c{QProcessEnvironment::InheritFromParent}
+ it remains unchanged.
+
\sa isEmpty(), systemEnvironment()
*/
void QProcessEnvironment::clear()
{
- if (d)
+ if (d.constData())
d->vars.clear();
// Unix: Don't clear d->nameMap, as the environment is likely to be
// re-populated with the same keys again.
@@ -339,9 +299,9 @@ void QProcessEnvironment::insert(const QString &name, const QString &value)
*/
void QProcessEnvironment::remove(const QString &name)
{
- if (d) {
- d.detach(); // detach before prepareName()
- d->vars.remove(d->prepareName(name));
+ if (d.constData()) {
+ QProcessEnvironmentPrivate *p = d.data();
+ p->vars.remove(p->prepareName(name));
}
}
@@ -389,6 +349,9 @@ QStringList QProcessEnvironment::toStringList() const
Returns a list containing all the variable names in this QProcessEnvironment
object.
+
+ The returned list is empty for objects constructed using
+ \c{QProcessEnvironment::InheritFromParent}.
*/
QStringList QProcessEnvironment::keys() const
{
@@ -428,6 +391,8 @@ void QProcessPrivate::Channel::clear()
process->stdoutChannel.type = Normal;
process->stdoutChannel.process = nullptr;
break;
+ default:
+ break;
}
type = Normal;
@@ -491,6 +456,97 @@ void QProcessPrivate::Channel::clear()
\note QProcess is not supported on VxWorks, iOS, tvOS, or watchOS.
+ \section1 Finding the Executable
+
+ The program to be run can be set either by calling setProgram() or directly
+ in the start() call. The effect of calling start() with the program name
+ and arguments is equivalent to calling setProgram() and setArguments()
+ before that function and then calling the overload without those
+ parameters.
+
+ QProcess interprets the program name in one of three different ways,
+ similar to how Unix shells and the Windows command interpreter operate in
+ their own command-lines:
+
+ \list
+ \li If the program name is an absolute path, then that is the exact
+ executable that will be launched and QProcess performs no searching.
+
+ \li If the program name is a relative path with more than one path
+ component (that is, it contains at least one slash), the starting
+ directory where that relative path is searched is OS-dependent: on
+ Windows, it's the parent process' current working dir, while on Unix it's
+ the one set with setWorkingDirectory().
+
+ \li If the program name is a plain file name with no slashes, the
+ behavior is operating-system dependent. On Unix systems, QProcess will
+ search the \c PATH environment variable; on Windows, the search is
+ performed by the OS and will first the parent process' current directory
+ before the \c PATH environment variable (see the documentation for
+ \l{CreateProcess} for the full list).
+ \endlist
+
+ To avoid platform-dependent behavior or any issues with how the current
+ application was launched, it is advisable to always pass an absolute path
+ to the executable to be launched. For auxiliary binaries shipped with the
+ application, one can construct such a path starting with
+ QCoreApplication::applicationDirPath(). Similarly, to explicitly run an
+ executable that is to be found relative to the directory set with
+ setWorkingDirectory(), use a program path starting with "./" or "../" as
+ the case may be.
+
+ On Windows, the ".exe" suffix is not required for most uses, except those
+ outlined in the \l{CreateProcess} documentation. Additionally, QProcess
+ will convert the Unix-style forward slashes to Windows path backslashes for
+ the program name. This allows code using QProcess to be written in a
+ cross-platform manner, as shown in the examples above.
+
+ QProcess does not support directly executing Unix shell or Windows command
+ interpreter built-in functions, such as \c{cmd.exe}'s \c dir command or the
+ Bourne shell's \c export. On Unix, even though many shell built-ins are
+ also provided as separate executables, their behavior may differ from those
+ implemented as built-ins. To run those commands, one should explicitly
+ execute the interpreter with suitable options. For Unix systems, launch
+ "/bin/sh" with two arguments: "-c" and a string with the command-line to be
+ run. For Windows, due to the non-standard way \c{cmd.exe} parses its
+ command-line, use setNativeArguments() (for example, "/c dir d:").
+
+ \section1 Environment variables
+
+ The QProcess API offers methods to manipulate the environment variables
+ that the child process will see. By default, the child process will have a
+ copy of the current process environment variables that exist at the time
+ the start() function is called. This means that any modifications performed
+ using qputenv() prior to that call will be reflected in the child process'
+ environment. Note that QProcess makes no attempt to prevent race conditions
+ with qputenv() happening in other threads, so it is recommended to avoid
+ qputenv() after the application's initial start up.
+
+ The environment for a specific child can be modified using the
+ processEnvironment() and setProcessEnvironment() functions, which use the
+ \l QProcessEnvironment class. By default, processEnvironment() will return
+ an object for which QProcessEnvironment::inheritsFromParent() is true.
+ Setting an environment that does not inherit from the parent will cause
+ QProcess to use exactly that environment for the child when it is started.
+
+ The normal scenario starts from the current environment by calling
+ QProcessEnvironment::systemEnvironment() and then proceeds to adding,
+ changing, or removing specific variables. The resulting variable roster can
+ then be applied to a QProcess with setProcessEnvironment().
+
+ It is possible to remove all variables from the environment or to start
+ from an empty environment, using the QProcessEnvironment() default
+ constructor. This is not advisable outside of controlled and
+ system-specific conditions, as there may be system variables that are set
+ in the current process environment and are required for proper execution
+ of the child process.
+
+ On Windows, QProcess will copy the current process' \c "PATH" and \c
+ "SystemRoot" environment variables if they were unset. It is not possible
+ to unset them completely, but it is possible to set them to empty values.
+ Setting \c "PATH" to empty on Windows will likely cause the child process
+ to fail to start.
+
\section1 Communicating via Channels
Processes have two predefined output channels: The standard
@@ -539,11 +595,6 @@ void QProcessPrivate::Channel::clear()
command line option; X11 applications generally accept a
\c{-geometry} command line option.
- \note On QNX, setting the working directory may cause all
- application threads, with the exception of the QProcess caller
- thread, to temporarily freeze during the spawning process,
- owing to a limitation in the operating system.
-
\section1 Synchronous Process API
QProcess provides a set of functions which allow it to be used
@@ -571,15 +622,6 @@ void QProcessPrivate::Channel::clear()
\snippet process/process.cpp 0
- \section1 Notes for Windows Users
-
- Some Windows commands (for example, \c dir) are not provided by
- separate applications, but by the command interpreter itself.
- If you attempt to use QProcess to execute these commands directly,
- it won't work. One possible solution is to execute the command
- interpreter itself (\c{cmd.exe} on some Windows systems), and ask
- the interpreter to execute the desired command.
-
\sa QBuffer, QFile, QTcpSocket
*/
@@ -616,7 +658,8 @@ void QProcessPrivate::Channel::clear()
process into the standard output channel (\c stdout). The
standard error channel (\c stderr) will not receive any data. The
standard output and standard error data of the running process
- are interleaved.
+ are interleaved. For detached processes, the merged output of the
+ running process is forwarded onto the main process.
\value ForwardedChannels QProcess forwards the output of the
running process onto the main process. Anything the child process
@@ -673,7 +716,7 @@ void QProcessPrivate::Channel::clear()
\value FailedToStart The process failed to start. Either the
invoked program is missing, or you may have insufficient
- permissions to invoke the program.
+ permissions or resources to invoke the program.
\value Crashed The process crashed some time after starting
successfully.
@@ -766,10 +809,95 @@ void QProcessPrivate::Channel::clear()
*/
/*!
- \fn void QProcess::error(QProcess::ProcessError error)
- \obsolete
+ \class QProcess::UnixProcessParameters
+ \inmodule QtCore
+ \note This struct is only available on Unix platforms
+ \since 6.6
+
+ This struct can be used to pass extra, Unix-specific configuration for the
+ child process using QProcess::setUnixProcessParameters().
- Use errorOccurred() instead.
+ Its members are:
+ \list
+ \li UnixProcessParameters::flags Flags, see QProcess::UnixProcessFlags
+ \li UnixProcessParameters::lowestFileDescriptorToClose The lowest file
+ descriptor to close.
+ \endlist
+
+ When the QProcess::UnixProcessFlags::CloseFileDescriptors flag is set in
+ the \c flags field, QProcess closes the application's open file descriptors
+ before executing the child process. The descriptors 0, 1, and 2 (that is,
+ \c stdin, \c stdout, and \c stderr) are left alone, along with the ones
+ numbered lower than the value of the \c lowestFileDescriptorToClose field.
+
+ All of the settings above can also be manually achieved by calling the
+ respective POSIX function from a handler set with
+ QProcess::setChildProcessModifier(). This structure allows QProcess to deal
+ with any platform-specific differences, benefit from certain optimizations,
+ and reduces code duplication. Moreover, if any of those functions fail,
+ QProcess will enter QProcess::FailedToStart state, while the child process
+ modifier callback is not allowed to fail.
+
+ \sa QProcess::setUnixProcessParameters(), QProcess::setChildProcessModifier()
+*/
+
+/*!
+ \enum QProcess::UnixProcessFlag
+ \since 6.6
+
+ These flags can be used in the \c flags field of \l UnixProcessParameters.
+
+ \value CloseFileDescriptors Close all file descriptors above the threshold
+ defined by \c lowestFileDescriptorToClose, preventing any currently
+ open descriptor in the parent process from accidentally leaking to the
+ child. The \c stdin, \c stdout, and \c stderr file descriptors are
+ never closed.
+
+ \value [since 6.7] CreateNewSession Starts a new process session, by calling
+ \c{setsid(2)}. This allows the child process to outlive the session
+ the current process is in. This is one of the steps that
+ startDetached() takes to allow the process to detach, and is also one
+ of the steps to daemonize a process.
+
+ \value [since 6.7] DisconnectControllingTerminal Requests that the process
+ disconnect from its controlling terminal, if it has one. If it has
+ none, nothing happens. Processes still connected to a controlling
+ terminal may get a Hang Up (\c SIGHUP) signal if the terminal
+ closes, or one of the other terminal-control signals (\c SIGTSTP, \c
+ SIGTTIN, \c SIGTTOU). Note that on some operating systems, a process
+ may only disconnect from the controlling terminal if it is the
+ session leader, meaning the \c CreateNewSession flag may be
+ required. Like it, this is one of the steps to daemonize a process.
+
+ \value IgnoreSigPipe Always sets the \c SIGPIPE signal to ignored
+ (\c SIG_IGN), even if the \c ResetSignalHandlers flag was set. By
+ default, if the child attempts to write to its standard output or
+ standard error after the respective channel was closed with
+ QProcess::closeReadChannel(), it would get the \c SIGPIPE signal and
+ terminate immediately; with this flag, the write operation fails
+ without a signal and the child may continue executing.
+
+ \value [since 6.7] ResetIds Drops any retained, effective user or group
+ ID the current process may still have (see \c{setuid(2)} and
+ \c{setgid(2)}, plus QCoreApplication::setSetuidAllowed()). This is
+ useful if the current process was setuid or setgid and does not wish
+ the child process to retain the elevated privileges.
+
+ \value ResetSignalHandlers Resets all Unix signal handlers back to their
+ default state (that is, pass \c SIG_DFL to \c{signal(2)}). This flag
+ is useful to ensure any ignored (\c SIG_IGN) signal does not affect
+ the child's behavior.
+
+ \value UseVFork Requests that QProcess use \c{vfork(2)} to start the child
+ process. Use this flag to indicate that the callback function set
+ with setChildProcessModifier() is safe to execute in the child side of
+ a \c{vfork(2)}; that is, the callback does not modify any non-local
+ variables (directly or through any function it calls), nor attempts
+ to communicate with the parent process. It is implementation-defined
+ if QProcess will actually use \c{vfork(2)} and if \c{vfork(2)} is
+ different from standard \c{fork(2)}.
+
+ \sa setUnixProcessParameters(), unixProcessParameters()
*/
/*!
@@ -834,28 +962,9 @@ void QProcessPrivate::Channel::clear()
QProcessPrivate::QProcessPrivate()
{
readBufferChunkSize = QRINGBUFFER_CHUNKSIZE;
+#ifndef Q_OS_WIN
writeBufferChunkSize = QRINGBUFFER_CHUNKSIZE;
- processChannelMode = QProcess::SeparateChannels;
- inputChannelMode = QProcess::ManagedInputChannel;
- processError = QProcess::UnknownError;
- processState = QProcess::NotRunning;
- pid = 0;
- sequenceNumber = 0;
- exitCode = 0;
- exitStatus = QProcess::NormalExit;
- startupSocketNotifier = nullptr;
- deathNotifier = nullptr;
- childStartedPipe[0] = INVALID_Q_PIPE;
- childStartedPipe[1] = INVALID_Q_PIPE;
- forkfd = -1;
- crashed = false;
- dying = false;
- emittedReadyRead = false;
- emittedBytesWritten = false;
-#ifdef Q_OS_WIN
- stdinWriteTrigger = 0;
- processFinishedNotifier = 0;
-#endif // Q_OS_WIN
+#endif
}
/*!
@@ -872,63 +981,6 @@ QProcessPrivate::~QProcessPrivate()
/*!
\internal
*/
-void QProcessPrivate::cleanup()
-{
- q_func()->setProcessState(QProcess::NotRunning);
-#ifdef Q_OS_WIN
- if (pid) {
- CloseHandle(pid->hThread);
- CloseHandle(pid->hProcess);
- delete pid;
- pid = 0;
- }
- if (stdinWriteTrigger) {
- delete stdinWriteTrigger;
- stdinWriteTrigger = 0;
- }
- if (processFinishedNotifier) {
- delete processFinishedNotifier;
- processFinishedNotifier = 0;
- }
-
-#endif
- pid = 0;
- sequenceNumber = 0;
-
- if (stdoutChannel.notifier) {
- delete stdoutChannel.notifier;
- stdoutChannel.notifier = nullptr;
- }
- if (stderrChannel.notifier) {
- delete stderrChannel.notifier;
- stderrChannel.notifier = nullptr;
- }
- if (stdinChannel.notifier) {
- delete stdinChannel.notifier;
- stdinChannel.notifier = nullptr;
- }
- if (startupSocketNotifier) {
- delete startupSocketNotifier;
- startupSocketNotifier = nullptr;
- }
- if (deathNotifier) {
- delete deathNotifier;
- deathNotifier = nullptr;
- }
- closeChannel(&stdoutChannel);
- closeChannel(&stderrChannel);
- closeChannel(&stdinChannel);
- destroyPipe(childStartedPipe);
-#ifdef Q_OS_UNIX
- if (forkfd != -1)
- qt_safe_close(forkfd);
- forkfd = -1;
-#endif
-}
-
-/*!
- \internal
-*/
void QProcessPrivate::setError(QProcess::ProcessError error, const QString &description)
{
processError = error;
@@ -966,7 +1018,95 @@ void QProcessPrivate::setErrorAndEmit(QProcess::ProcessError error, const QStrin
Q_Q(QProcess);
Q_ASSERT(error != QProcess::UnknownError);
setError(error, description);
- emit q->errorOccurred(processError);
+ emit q->errorOccurred(QProcess::ProcessError(processError));
+}
+
+/*!
+ \internal
+*/
+bool QProcessPrivate::openChannels()
+{
+ // stdin channel.
+ if (inputChannelMode == QProcess::ForwardedInputChannel) {
+ if (stdinChannel.type != Channel::Normal)
+ qWarning("QProcess::openChannels: Inconsistent stdin channel configuration");
+ } else if (!openChannel(stdinChannel)) {
+ return false;
+ }
+
+ // stdout channel.
+ if (processChannelMode == QProcess::ForwardedChannels
+ || processChannelMode == QProcess::ForwardedOutputChannel) {
+ if (stdoutChannel.type != Channel::Normal)
+ qWarning("QProcess::openChannels: Inconsistent stdout channel configuration");
+ } else if (!openChannel(stdoutChannel)) {
+ return false;
+ }
+
+ // stderr channel.
+ if (processChannelMode == QProcess::ForwardedChannels
+ || processChannelMode == QProcess::ForwardedErrorChannel
+ || processChannelMode == QProcess::MergedChannels) {
+ if (stderrChannel.type != Channel::Normal)
+ qWarning("QProcess::openChannels: Inconsistent stderr channel configuration");
+ } else if (!openChannel(stderrChannel)) {
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \internal
+*/
+void QProcessPrivate::closeChannels()
+{
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
+ closeChannel(&stdinChannel);
+}
+
+/*!
+ \internal
+*/
+bool QProcessPrivate::openChannelsForDetached()
+{
+ // stdin channel.
+ bool needToOpen = (stdinChannel.type == Channel::Redirect
+ || stdinChannel.type == Channel::PipeSink);
+ if (stdinChannel.type != Channel::Normal
+ && (!needToOpen
+ || inputChannelMode == QProcess::ForwardedInputChannel)) {
+ qWarning("QProcess::openChannelsForDetached: Inconsistent stdin channel configuration");
+ }
+ if (needToOpen && !openChannel(stdinChannel))
+ return false;
+
+ // stdout channel.
+ needToOpen = (stdoutChannel.type == Channel::Redirect
+ || stdoutChannel.type == Channel::PipeSource);
+ if (stdoutChannel.type != Channel::Normal
+ && (!needToOpen
+ || processChannelMode == QProcess::ForwardedChannels
+ || processChannelMode == QProcess::ForwardedOutputChannel)) {
+ qWarning("QProcess::openChannelsForDetached: Inconsistent stdout channel configuration");
+ }
+ if (needToOpen && !openChannel(stdoutChannel))
+ return false;
+
+ // stderr channel.
+ needToOpen = (stderrChannel.type == Channel::Redirect);
+ if (stderrChannel.type != Channel::Normal
+ && (!needToOpen
+ || processChannelMode == QProcess::ForwardedChannels
+ || processChannelMode == QProcess::ForwardedErrorChannel
+ || processChannelMode == QProcess::MergedChannels)) {
+ qWarning("QProcess::openChannelsForDetached: Inconsistent stderr channel configuration");
+ }
+ if (needToOpen && !openChannel(stderrChannel))
+ return false;
+
+ return true;
}
/*!
@@ -1006,8 +1146,6 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel)
}
if (readBytes == 0) {
// EOF
- if (channel->notifier)
- channel->notifier->setEnabled(false);
closeChannel(channel);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available",
@@ -1062,92 +1200,61 @@ bool QProcessPrivate::_q_canReadStandardError()
/*!
\internal
*/
-bool QProcessPrivate::_q_canWrite()
+void QProcessPrivate::_q_processDied()
{
- if (writeBuffer.isEmpty()) {
- if (stdinChannel.notifier)
- stdinChannel.notifier->setEnabled(false);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
+ qDebug("QProcessPrivate::_q_processDied()");
#endif
- return false;
- }
- const bool writeSucceeded = writeToStdin();
+ // in case there is data in the pipeline and this slot by chance
+ // got called before the read notifications, call these functions
+ // so the data is made available before we announce death.
+#ifdef Q_OS_WIN
+ drainOutputPipes();
+#else
+ _q_canReadStandardOutput();
+ _q_canReadStandardError();
+#endif
- if (writeBuffer.isEmpty() && stdinChannel.closed)
- closeWriteChannel();
- else if (stdinChannel.notifier)
- stdinChannel.notifier->setEnabled(!writeBuffer.isEmpty());
- return writeSucceeded;
+ // Slots connected to signals emitted by the functions called above
+ // might call waitFor*(), which would synchronously reap the process.
+ // So check the state to avoid trying to reap a second time.
+ if (processState != QProcess::NotRunning)
+ processFinished();
}
/*!
\internal
*/
-bool QProcessPrivate::_q_processDied()
+void QProcessPrivate::processFinished()
{
Q_Q(QProcess);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::_q_processDied()");
+ qDebug("QProcessPrivate::processFinished()");
#endif
+
#ifdef Q_OS_UNIX
- if (!waitForDeadChild())
- return false;
-#endif
-#ifdef Q_OS_WIN
- if (processFinishedNotifier)
- processFinishedNotifier->setEnabled(false);
- drainOutputPipes();
+ waitForDeadChild();
+#else
+ findExitCode();
#endif
- // the process may have died before it got a chance to report that it was
- // either running or stopped, so we will call _q_startupNotification() and
- // give it a chance to emit started() or errorOccurred(FailedToStart).
- if (processState == QProcess::Starting) {
- if (!_q_startupNotification())
- return true;
- }
-
- if (dying) {
- // at this point we know the process is dead. prevent
- // reentering this slot recursively by calling waitForFinished()
- // or opening a dialog inside slots connected to the readyRead
- // signals emitted below.
- return true;
- }
- dying = true;
-
- // in case there is data in the pipe line and this slot by chance
- // got called before the read notifications, call these two slots
- // so the data is made available before the process dies.
- _q_canReadStandardOutput();
- _q_canReadStandardError();
-
- findExitCode();
+ cleanup();
- if (crashed) {
- exitStatus = QProcess::CrashExit;
+ if (exitStatus == QProcess::CrashExit)
setErrorAndEmit(QProcess::Crashed);
- }
- bool wasRunning = (processState == QProcess::Running);
+ // we received EOF now:
+ emit q->readChannelFinished();
+ // in the future:
+ //emit q->standardOutputClosed();
+ //emit q->standardErrorClosed();
- cleanup();
-
- if (wasRunning) {
- // we received EOF now:
- emit q->readChannelFinished();
- // in the future:
- //emit q->standardOutputClosed();
- //emit q->standardErrorClosed();
+ emit q->finished(exitCode, QProcess::ExitStatus(exitStatus));
- emit q->finished(exitCode, exitStatus);
- }
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::_q_processDied() process is dead");
+ qDebug("QProcessPrivate::processFinished(): process is dead");
#endif
- return true;
}
/*!
@@ -1160,8 +1267,6 @@ bool QProcessPrivate::_q_startupNotification()
qDebug("QProcessPrivate::startupNotification()");
#endif
- if (startupSocketNotifier)
- startupSocketNotifier->setEnabled(false);
QString errorMessage;
if (processStarted(&errorMessage)) {
q->setProcessState(QProcess::Running);
@@ -1172,9 +1277,7 @@ bool QProcessPrivate::_q_startupNotification()
q->setProcessState(QProcess::NotRunning);
setErrorAndEmit(QProcess::FailedToStart, errorMessage);
#ifdef Q_OS_UNIX
- // make sure the process manager removes this entry
waitForDeadChild();
- findExitCode();
#endif
cleanup();
return false;
@@ -1188,15 +1291,7 @@ void QProcessPrivate::closeWriteChannel()
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::closeWriteChannel()");
#endif
- if (stdinChannel.notifier) {
- delete stdinChannel.notifier;
- stdinChannel.notifier = nullptr;
- }
-#ifdef Q_OS_WIN
- // ### Find a better fix, feeding the process little by little
- // instead.
- flushPipeWriter();
-#endif
+
closeChannel(&stdinChannel);
}
@@ -1226,10 +1321,6 @@ QProcess::~QProcess()
kill();
waitForFinished();
}
-#ifdef Q_OS_UNIX
- // make sure the process manager removes this entry
- d->findExitCode();
-#endif
d->cleanup();
}
@@ -1244,7 +1335,7 @@ QProcess::~QProcess()
QProcess::ProcessChannelMode QProcess::processChannelMode() const
{
Q_D(const QProcess);
- return d->processChannelMode;
+ return ProcessChannelMode(d->processChannelMode);
}
/*!
@@ -1274,7 +1365,7 @@ void QProcess::setProcessChannelMode(ProcessChannelMode mode)
QProcess::InputChannelMode QProcess::inputChannelMode() const
{
Q_D(const QProcess);
- return d->inputChannelMode;
+ return InputChannelMode(d->inputChannelMode);
}
/*!
@@ -1358,7 +1449,7 @@ void QProcess::closeWriteChannel()
{
Q_D(QProcess);
d->stdinChannel.closed = true; // closing
- if (d->writeBuffer.isEmpty())
+ if (bytesToWrite() == 0)
d->closeWriteChannel();
}
@@ -1412,6 +1503,9 @@ void QProcess::setStandardInputFile(const QString &fileName)
Calling setStandardOutputFile() after the process has started has
no effect.
+ If \a fileName is an empty string, it stops redirecting the standard
+ output. This is useful for restoring the standard output after redirection.
+
\sa setStandardInputFile(), setStandardErrorFile(),
setStandardOutputProcess()
*/
@@ -1471,7 +1565,7 @@ void QProcess::setStandardOutputProcess(QProcess *destination)
dto->stdinChannel.pipeFrom(dfrom);
}
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
/*!
\since 4.7
@@ -1536,7 +1630,7 @@ QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier
\note This function is available only on the Windows platform and requires
C++11.
- \sa QProcess::CreateProcessArgumentModifier
+ \sa QProcess::CreateProcessArgumentModifier, setChildProcessModifier()
*/
void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier)
{
@@ -1546,6 +1640,180 @@ void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier m
#endif
+#if defined(Q_OS_UNIX) || defined(Q_QDOC)
+/*!
+ \since 6.0
+
+ Returns the modifier function previously set by calling
+ setChildProcessModifier().
+
+ \note This function is only available on Unix platforms.
+
+ \sa setChildProcessModifier(), unixProcessParameters()
+*/
+std::function<void(void)> QProcess::childProcessModifier() const
+{
+ Q_D(const QProcess);
+ return d->unixExtras ? d->unixExtras->childProcessModifier : std::function<void(void)>();
+}
+
+/*!
+ \since 6.0
+
+ Sets the \a modifier function for the child process, for Unix systems
+ (including \macos; for Windows, see setCreateProcessArgumentsModifier()).
+ The function contained by the \a modifier argument will be invoked in the
+ child process after \c{fork()} or \c{vfork()} is completed and QProcess has
+ set up the standard file descriptors for the child process, but before
+ \c{execve()}, inside start().
+
+ The following shows an example of setting up a child process to run without
+ privileges:
+
+ \snippet code/src_corelib_io_qprocess.cpp 4
+
+ If the modifier function experiences a failure condition, it can use
+ failChildProcessModifier() to report the situation to the QProcess caller.
+ Alternatively, it may use other methods of stopping the process, like
+ \c{_exit()}, or \c{abort()}.
+
+ Certain properties of the child process, such as closing all extraneous
+ file descriptors or disconnecting from the controlling TTY, can be more
+ readily achieved by using setUnixProcessParameters(), which can detect
+ failure and report a \l{QProcess::}{FailedToStart} condition. The modifier
+ is useful to change certain uncommon properties of the child process, such
+ as setting up additional file descriptors. If both a child process modifier
+ and Unix process parameters are set, the modifier is run before these
+ parameters are applied.
+
+ \note In multithreaded applications, this function must be careful not to
+ call any functions that may lock mutexes that may have been in use in
+ other threads (in general, using only functions defined by POSIX as
+ "async-signal-safe" is advised). Most of the Qt API is unsafe inside this
+ callback, including qDebug(), and may lead to deadlocks.
+
+ \note If the UnixProcessParameters::UseVFork flag is set via
+ setUnixProcessParameters(), QProcess may use \c{vfork()} semantics to
+ start the child process, so this function must obey even stricter
+ constraints. First, because it is still sharing memory with the parent
+ process, it must not write to any non-local variable and must obey proper
+ ordering semantics when reading from them, to avoid data races. Second,
+ even more library functions may misbehave; therefore, this function should
+ only make use of low-level system calls, such as \c{read()},
+ \c{write()}, \c{setsid()}, \c{nice()}, and similar.
+
+ \sa childProcessModifier(), failChildProcessModifier(), setUnixProcessParameters()
+*/
+void QProcess::setChildProcessModifier(const std::function<void(void)> &modifier)
+{
+ Q_D(QProcess);
+ if (!d->unixExtras)
+ d->unixExtras.reset(new QProcessPrivate::UnixExtras);
+ d->unixExtras->childProcessModifier = modifier;
+}
+
+/*!
+ \fn void QProcess::failChildProcessModifier(const char *description, int error) noexcept
+ \since 6.7
+
+ This functions can be used inside the modifier set with
+ setChildProcessModifier() to indicate an error condition was encountered.
+ When the modifier calls these functions, QProcess will emit errorOccurred()
+ with code QProcess::FailedToStart in the parent process. The \a description
+ can be used to include some information in errorString() to help diagnose
+ the problem, usually the name of the call that failed, similar to the C
+ Library function \c{perror()}. Additionally, the \a error parameter can be
+ an \c{<errno.h>} error code whose text form will also be included.
+
+ For example, a child modifier could prepare an extra file descriptor for
+ the child process this way:
+
+ \code
+ process.setChildProcessModifier([fd, &process]() {
+ if (dup2(fd, TargetFileDescriptor) < 0)
+ process.failChildProcessModifier(errno, "aux comm channel");
+ });
+ process.start();
+ \endcode
+
+ Where \c{fd} is a file descriptor currently open in the parent process. If
+ the \c{dup2()} system call resulted in an \c EBADF condition, the process
+ errorString() could be "Child process modifier reported error: aux comm
+ channel: Bad file descriptor".
+
+ This function does not return to the caller. Using it anywhere except in
+ the child modifier and with the correct QProcess object is undefined
+ behavior.
+
+ \note The implementation imposes a length limit to the \a description
+ parameter to about 500 characters. This does not include the text from the
+ \a error code.
+
+ \sa setChildProcessModifier(), setUnixProcessParameters()
+*/
+
+/*!
+ \since 6.6
+ Returns the \l UnixProcessParameters object describing extra flags and
+ settings that will be applied to the child process on Unix systems. The
+ default settings correspond to a default-constructed UnixProcessParameters.
+
+ \note This function is only available on Unix platforms.
+
+ \sa childProcessModifier()
+*/
+auto QProcess::unixProcessParameters() const noexcept -> UnixProcessParameters
+{
+ Q_D(const QProcess);
+ return d->unixExtras ? d->unixExtras->processParameters : UnixProcessParameters{};
+}
+
+/*!
+ \since 6.6
+ Sets the extra settings and parameters for the child process on Unix
+ systems to be \a params. This function can be used to ask QProcess to
+ modify the child process before launching the target executable.
+
+ This function can be used to change certain properties of the child
+ process, such as closing all extraneous file descriptors, changing the nice
+ level of the child, or disconnecting from the controlling TTY. For more
+ fine-grained control of the child process or to modify it in other ways,
+ use the setChildProcessModifier() function. If both a child process
+ modifier and Unix process parameters are set, the modifier is run before
+ these parameters are applied.
+
+ \note This function is only available on Unix platforms.
+
+ \sa unixProcessParameters(), setChildProcessModifier()
+*/
+void QProcess::setUnixProcessParameters(const UnixProcessParameters &params)
+{
+ Q_D(QProcess);
+ if (!d->unixExtras)
+ d->unixExtras.reset(new QProcessPrivate::UnixExtras);
+ d->unixExtras->processParameters = params;
+}
+
+/*!
+ \since 6.6
+ \overload
+
+ Sets the extra settings for the child process on Unix systems to \a
+ flagsOnly. This is the same as the overload with just the \c flags field
+ set.
+ \note This function is only available on Unix platforms.
+
+ \sa unixProcessParameters(), setChildProcessModifier()
+*/
+void QProcess::setUnixProcessParameters(UnixProcessFlags flagsOnly)
+{
+ Q_D(QProcess);
+ if (!d->unixExtras)
+ d->unixExtras.reset(new QProcessPrivate::UnixExtras);
+ d->unixExtras->processParameters = { flagsOnly };
+}
+#endif
+
/*!
If QProcess has been assigned a working directory, this function returns
the working directory that the QProcess will enter before the program has
@@ -1566,9 +1834,6 @@ QString QProcess::workingDirectory() const
process in this directory. The default behavior is to start the
process in the working directory of the calling process.
- \note On QNX, this may cause all application threads to
- temporarily freeze.
-
\sa workingDirectory(), start()
*/
void QProcess::setWorkingDirectory(const QString &dir)
@@ -1577,24 +1842,6 @@ void QProcess::setWorkingDirectory(const QString &dir)
d->workingDirectory = dir;
}
-
-/*!
- \deprecated
- Use processId() instead.
-
- Returns the native process identifier for the running process, if
- available. If no process is currently running, \c 0 is returned.
-
- \note Unlike \l processId(), pid() returns an integer on Unix and a pointer on Windows.
-
- \sa Q_PID, processId()
-*/
-Q_PID QProcess::pid() const // ### Qt 6 remove or rename this method to processInformation()
-{
- Q_D(const QProcess);
- return d->pid;
-}
-
/*!
\since 5.3
@@ -1639,11 +1886,11 @@ bool QProcess::isSequential() const
*/
qint64 QProcess::bytesToWrite() const
{
- qint64 size = QIODevice::bytesToWrite();
#ifdef Q_OS_WIN
- size += d_func()->pipeWriterBytesToWrite();
+ return d_func()->pipeWriterBytesToWrite();
+#else
+ return QIODevice::bytesToWrite();
#endif
- return size;
}
/*!
@@ -1654,7 +1901,7 @@ qint64 QProcess::bytesToWrite() const
QProcess::ProcessError QProcess::error() const
{
Q_D(const QProcess);
- return d->processError;
+ return ProcessError(d->processError);
}
/*!
@@ -1665,7 +1912,7 @@ QProcess::ProcessError QProcess::error() const
QProcess::ProcessState QProcess::state() const
{
Q_D(const QProcess);
- return d->processState;
+ return ProcessState(d->processState);
}
/*!
@@ -1712,7 +1959,8 @@ QStringList QProcess::environment() const
Note how, on Windows, environment variable names are case-insensitive.
- \sa processEnvironment(), QProcessEnvironment::systemEnvironment(), setEnvironment()
+ \sa processEnvironment(), QProcessEnvironment::systemEnvironment(),
+ {Environment variables}
*/
void QProcess::setProcessEnvironment(const QProcessEnvironment &environment)
{
@@ -1722,12 +1970,12 @@ void QProcess::setProcessEnvironment(const QProcessEnvironment &environment)
/*!
\since 4.6
- Returns the environment that QProcess will pass to its child
- process, or an empty object if no environment has been set using
- setEnvironment() or setProcessEnvironment(). If no environment has
- been set, the environment of the calling process will be used.
+ Returns the environment that QProcess will pass to its child process. If no
+ environment has been set using setProcessEnvironment(), this method returns
+ an object indicating the environment will be inherited from the parent.
- \sa setProcessEnvironment(), setEnvironment(), QProcessEnvironment::isEmpty()
+ \sa setProcessEnvironment(), QProcessEnvironment::inheritsFromParent(),
+ {Environment variables}
*/
QProcessEnvironment QProcess::processEnvironment() const
{
@@ -1741,7 +1989,8 @@ QProcessEnvironment QProcess::processEnvironment() const
Returns \c true if the process was started successfully; otherwise
returns \c false (if the operation timed out or if an error
- occurred).
+ occurred). If the process had already started successfully before this
+ function, it returns immediately.
This function can operate without an event loop. It is
useful when writing non-GUI applications and when performing
@@ -1752,16 +2001,13 @@ QProcessEnvironment QProcess::processEnvironment() const
If msecs is -1, this function will not time out.
- \note On some UNIX operating systems, this function may return true but
- the process may later report a QProcess::FailedToStart error.
-
\sa started(), waitForReadyRead(), waitForBytesWritten(), waitForFinished()
*/
bool QProcess::waitForStarted(int msecs)
{
Q_D(QProcess);
if (d->processState == QProcess::Starting)
- return d->waitForStarted(msecs);
+ return d->waitForStarted(QDeadlineTimer(msecs));
return d->processState == QProcess::Running;
}
@@ -1778,7 +2024,15 @@ bool QProcess::waitForReadyRead(int msecs)
return false;
if (d->currentReadChannel == QProcess::StandardError && d->stderrChannel.closed)
return false;
- return d->waitForReadyRead(msecs);
+
+ QDeadlineTimer deadline(msecs);
+ if (d->processState == QProcess::Starting) {
+ bool started = d->waitForStarted(deadline);
+ if (!started)
+ return false;
+ }
+
+ return d->waitForReadyRead(deadline);
}
/*! \reimp
@@ -1788,16 +2042,15 @@ bool QProcess::waitForBytesWritten(int msecs)
Q_D(QProcess);
if (d->processState == QProcess::NotRunning)
return false;
+
+ QDeadlineTimer deadline(msecs);
if (d->processState == QProcess::Starting) {
- QElapsedTimer stopWatch;
- stopWatch.start();
- bool started = waitForStarted(msecs);
+ bool started = d->waitForStarted(deadline);
if (!started)
return false;
- msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
}
- return d->waitForBytesWritten(msecs);
+ return d->waitForBytesWritten(deadline);
}
/*!
@@ -1824,16 +2077,15 @@ bool QProcess::waitForFinished(int msecs)
Q_D(QProcess);
if (d->processState == QProcess::NotRunning)
return false;
+
+ QDeadlineTimer deadline(msecs);
if (d->processState == QProcess::Starting) {
- QElapsedTimer stopWatch;
- stopWatch.start();
- bool started = waitForStarted(msecs);
+ bool started = d->waitForStarted(deadline);
if (!started)
return false;
- msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
}
- return d->waitForFinished(msecs);
+ return d->waitForFinished(deadline);
}
/*!
@@ -1850,25 +2102,15 @@ void QProcess::setProcessState(ProcessState state)
emit stateChanged(state, QPrivateSignal());
}
+#if QT_VERSION < QT_VERSION_CHECK(7,0,0)
/*!
- This function is called in the child process context just before the
- program is executed on Unix or \macos (i.e., after \c fork(), but before
- \c execve()). Reimplement this function to do last minute initialization
- of the child process. Example:
-
- \snippet code/src_corelib_io_qprocess.cpp 4
-
- You cannot exit the process (by calling exit(), for instance) from
- this function. If you need to stop the program before it starts
- execution, your workaround is to emit finished() and then call
- exit().
-
- \warning This function is called by QProcess on Unix and \macos
- only. On Windows and QNX, it is not called.
+ \internal
*/
-void QProcess::setupChildProcess()
+auto QProcess::setupChildProcess() -> Use_setChildProcessModifier_Instead
{
+ Q_UNREACHABLE_RETURN({});
}
+#endif
/*! \reimp
*/
@@ -1883,44 +2125,6 @@ qint64 QProcess::readData(char *data, qint64 maxlen)
return 0;
}
-/*! \reimp
-*/
-qint64 QProcess::writeData(const char *data, qint64 len)
-{
- Q_D(QProcess);
-
- if (d->stdinChannel.closed) {
-#if defined QPROCESS_DEBUG
- qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
- data, qt_prettyDebug(data, len, 16).constData(), len);
-#endif
- return 0;
- }
-
-#if defined(Q_OS_WIN)
- if (!d->stdinWriteTrigger) {
- d->stdinWriteTrigger = new QTimer;
- d->stdinWriteTrigger->setSingleShot(true);
- QObjectPrivate::connect(d->stdinWriteTrigger, &QTimer::timeout,
- d, &QProcessPrivate::_q_canWrite);
- }
-#endif
-
- d->writeBuffer.append(data, len);
-#ifdef Q_OS_WIN
- if (!d->stdinWriteTrigger->isActive())
- d->stdinWriteTrigger->start();
-#else
- if (d->stdinChannel.notifier)
- d->stdinChannel.notifier->setEnabled(true);
-#endif
-#if defined QPROCESS_DEBUG
- qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
- data, qt_prettyDebug(data, len, 16).constData(), len, len);
-#endif
- return len;
-}
-
/*!
Regardless of the current read channel, this function returns all
data available from the standard output of the process as a
@@ -1946,27 +2150,38 @@ QByteArray QProcess::readAllStandardOutput()
*/
QByteArray QProcess::readAllStandardError()
{
- ProcessChannel tmp = readChannel();
- setReadChannel(StandardError);
- QByteArray data = readAll();
- setReadChannel(tmp);
+ Q_D(QProcess);
+ QByteArray data;
+ if (d->processChannelMode == MergedChannels) {
+ qWarning("QProcess::readAllStandardError: Called with MergedChannels");
+ } else {
+ ProcessChannel tmp = readChannel();
+ setReadChannel(StandardError);
+ data = readAll();
+ setReadChannel(tmp);
+ }
return data;
}
/*!
Starts the given \a program in a new process, passing the command line
- arguments in \a arguments.
+ arguments in \a arguments. See setProgram() for information about how
+ QProcess searches for the executable to be run. The OpenMode is set to \a
+ mode. No further splitting of the arguments is performed.
The QProcess object will immediately enter the Starting state. If the
process starts successfully, QProcess will emit started(); otherwise,
- errorOccurred() will be emitted.
-
- \note Processes are started asynchronously, which means the started()
- and errorOccurred() signals may be delayed. Call waitForStarted() to make
- sure the process has started (or has failed to start) and those signals
- have been emitted.
-
- \note No further splitting of the arguments is performed.
+ errorOccurred() will be emitted. Do note that on platforms that are able to
+ start child processes synchronously (notably Windows), those signals will
+ be emitted before this function returns and this QProcess object will
+ transition to either QProcess::Running or QProcess::NotRunning state,
+ respectively. On others paltforms, the started() and errorOccurred()
+ signals will be delayed.
+
+ Call waitForStarted() to make sure the process has started (or has failed
+ to start) and those signals have been emitted. It is safe to call that
+ function even if the process starting state is already known, though the
+ signal will not be emitted again.
\b{Windows:} The arguments are quoted and joined into a command line
that is compatible with the \c CommandLineToArgvW() Windows function.
@@ -1975,12 +2190,16 @@ QByteArray QProcess::readAllStandardError()
not follow the \c CommandLineToArgvW() rules is cmd.exe and, by
consequence, all batch scripts.
- The OpenMode is set to \a mode.
-
If the QProcess object is already running a process, a warning may be
printed at the console, and the existing process will continue running
unaffected.
+ \note Success at starting the child process only implies the operating
+ system has successfully created the process and assigned the resources
+ every process has, such as its process ID. The child process may crash or
+ otherwise fail very early and thus not produce its expected output. On most
+ operating systems, this may include dynamic linking errors.
+
\sa processId(), started(), waitForStarted(), setNativeArguments()
*/
void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
@@ -2026,6 +2245,51 @@ void QProcess::start(OpenMode mode)
}
/*!
+ \since 6.0
+
+ Starts the command \a command in a new process.
+ The OpenMode is set to \a mode.
+
+ \a command is a single string of text containing both the program name
+ and its arguments. The arguments are separated by one or more spaces.
+ For example:
+
+ \snippet code/src_corelib_io_qprocess.cpp 5
+
+ Arguments containing spaces must be quoted to be correctly supplied to
+ the new process. For example:
+
+ \snippet code/src_corelib_io_qprocess.cpp 6
+
+ Literal quotes in the \a command string are represented by triple quotes.
+ For example:
+
+ \snippet code/src_corelib_io_qprocess.cpp 7
+
+ After the \a command string has been split and unquoted, this function
+ behaves like start().
+
+ On operating systems where the system API for passing command line
+ arguments to a subprocess natively uses a single string (Windows), one can
+ conceive command lines which cannot be passed via QProcess's portable
+ list-based API. In these rare cases you need to use setProgram() and
+ setNativeArguments() instead of this function.
+
+ \sa splitCommand()
+ \sa start()
+ */
+void QProcess::startCommand(const QString &command, OpenMode mode)
+{
+ QStringList args = splitCommand(command);
+ if (args.isEmpty()) {
+ qWarning("QProcess::startCommand: empty or whitespace-only command was provided");
+ return;
+ }
+ const QString program = args.takeFirst();
+ start(program, args, mode);
+}
+
+/*!
\since 5.10
Starts the program set by setProgram() with arguments set by setArguments()
@@ -2040,15 +2304,13 @@ void QProcess::start(OpenMode mode)
If workingDirectory() is empty, the working directory is inherited
from the calling process.
- \note On QNX, this may cause all application threads to
- temporarily freeze.
-
If the function is successful then *\a pid is set to the process identifier
- of the started process. Note that the child process may exit and the PID
- may become invalid without notice. Furthermore, after the child process
- exits, the same PID may be recycled and used by a completely different
- process. User code should be careful when using this variable, especially
- if one intends to forcibly terminate the process by operating system means.
+ of the started process; otherwise, it's set to -1. Note that the child
+ process may exit and the PID may become invalid without notice.
+ Furthermore, after the child process exits, the same PID may be recycled
+ and used by a completely different process. User code should be careful
+ when using this variable, especially if one intends to forcibly terminate
+ the process by operating system means.
Only the following property setters are supported by startDetached():
\list
@@ -2060,6 +2322,8 @@ void QProcess::start(OpenMode mode)
\li setStandardErrorFile()
\li setStandardInputFile()
\li setStandardOutputFile()
+ \li setProcessChannelMode(QProcess::MergedChannels)
+ \li setStandardOutputProcess()
\li setWorkingDirectory()
\endlist
All other properties of the QProcess object are ignored.
@@ -2071,7 +2335,6 @@ void QProcess::start(OpenMode mode)
\sa start()
\sa startDetached(const QString &program, const QStringList &arguments,
const QString &workingDirectory, qint64 *pid)
- \sa startDetached(const QString &command)
*/
bool QProcess::startDetached(qint64 *pid)
{
@@ -2147,7 +2410,6 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
stderrChannel.closed = false;
exitCode = 0;
- dying = false;
exitStatus = QProcess::NormalExit;
processError = QProcess::UnknownError;
errorString.clear();
@@ -2174,7 +2436,7 @@ QStringList QProcess::splitCommand(QStringView command)
// "hello world". three consecutive double quotes represent
// the quote character itself.
for (int i = 0; i < command.size(); ++i) {
- if (command.at(i) == QLatin1Char('"')) {
+ if (command.at(i) == u'"') {
++quoteCount;
if (quoteCount == 3) {
// third consecutive quote
@@ -2222,7 +2484,12 @@ QString QProcess::program() const
Set the \a program to use when starting the process.
This function must be called before start().
- \sa start(), setArguments(), program()
+ If \a program is an absolute path, it specifies the exact executable that
+ will be launched. Relative paths will be resolved in a platform-specific
+ manner, which includes searching the \c PATH environment variable (see
+ \l{Finding the Executable} for details).
+
+ \sa start(), setArguments(), program(), QStandardPaths::findExecutable()
*/
void QProcess::setProgram(const QString &program)
{
@@ -2324,7 +2591,7 @@ int QProcess::exitCode() const
QProcess::ExitStatus QProcess::exitStatus() const
{
Q_D(const QProcess);
- return d->exitStatus;
+ return ExitStatus(d->exitStatus);
}
/*!
@@ -2385,18 +2652,6 @@ bool QProcess::startDetached(const QString &program,
return process.startDetached(pid);
}
-QT_BEGIN_INCLUDE_NAMESPACE
-#if defined(Q_OS_MACX)
-# include <crt_externs.h>
-# define environ (*_NSGetEnviron())
-#elif defined(QT_PLATFORM_UIKIT)
- static char *qt_empty_environ[] = { 0 };
-#define environ qt_empty_environ
-#elif !defined(Q_OS_WIN)
- extern char **environ;
-#endif
-QT_END_INCLUDE_NAMESPACE
-
/*!
\since 4.1
@@ -2418,12 +2673,7 @@ QT_END_INCLUDE_NAMESPACE
*/
QStringList QProcess::systemEnvironment()
{
- QStringList tmp;
- char *entry = nullptr;
- int count = 0;
- while ((entry = environ[count++]))
- tmp << QString::fromLocal8Bit(entry);
- return tmp;
+ return QProcessEnvironment::systemEnvironment().toStringList();
}
/*!
@@ -2466,17 +2716,6 @@ QString QProcess::nullDevice()
#endif
}
-/*!
- \typedef Q_PID
- \relates QProcess
-
- Typedef for the identifiers used to represent processes on the underlying
- platform. On Unix, this corresponds to \l qint64; on Windows, it
- corresponds to \c{_PROCESS_INFORMATION*}.
-
- \sa QProcess::pid()
-*/
-
#endif // QT_CONFIG(process)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index f43dfad840..34724a6794 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROCESS_H
#define QPROCESS_H
+#include <QtCore/qcompare.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qshareddata.h>
@@ -48,13 +14,13 @@
QT_REQUIRE_CONFIG(processenvironment);
-#ifdef Q_OS_WIN
-typedef struct _PROCESS_INFORMATION *Q_PID;
-#endif
-
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
-typedef struct _SECURITY_ATTRIBUTES Q_SECURITY_ATTRIBUTES;
-typedef struct _STARTUPINFOW Q_STARTUPINFO;
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+struct _PROCESS_INFORMATION;
+struct _SECURITY_ATTRIBUTES;
+struct _STARTUPINFOW;
+using Q_PROCESS_INFORMATION = _PROCESS_INFORMATION;
+using Q_SECURITY_ATTRIBUTES = _SECURITY_ATTRIBUTES;
+using Q_STARTUPINFO = _STARTUPINFOW;
#endif
QT_BEGIN_NAMESPACE
@@ -62,26 +28,28 @@ QT_BEGIN_NAMESPACE
class QProcessPrivate;
class QProcessEnvironmentPrivate;
-#ifndef Q_OS_WIN
-typedef qint64 Q_PID;
-#endif
-
class Q_CORE_EXPORT QProcessEnvironment
{
public:
+ enum Initialization { InheritFromParent };
+
QProcessEnvironment();
+ QProcessEnvironment(Initialization) noexcept;
QProcessEnvironment(const QProcessEnvironment &other);
~QProcessEnvironment();
- QProcessEnvironment &operator=(QProcessEnvironment && other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QProcessEnvironment)
QProcessEnvironment &operator=(const QProcessEnvironment &other);
- void swap(QProcessEnvironment &other) noexcept { qSwap(d, other.d); }
+ void swap(QProcessEnvironment &other) noexcept { d.swap(other.d); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QProcessEnvironment &other) const;
inline bool operator!=(const QProcessEnvironment &other) const
- { return !(*this == other); }
+ { return !operator==(other); }
+#endif
bool isEmpty() const;
+ [[nodiscard]] bool inheritsFromParent() const;
void clear();
bool contains(const QString &name) const;
@@ -98,6 +66,9 @@ public:
static QProcessEnvironment systemEnvironment();
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QProcessEnvironment &lhs,
+ const QProcessEnvironment &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QProcessEnvironment)
friend class QProcessPrivate;
friend class QProcessEnvironmentPrivate;
QSharedDataPointer<QProcessEnvironmentPrivate> d;
@@ -112,7 +83,7 @@ class Q_CORE_EXPORT QProcess : public QIODevice
Q_OBJECT
public:
enum ProcessError {
- FailedToStart, //### file not found, resource error
+ FailedToStart,
Crashed,
Timedout,
ReadError,
@@ -160,6 +131,7 @@ public:
void start(const QString &program, const QStringList &arguments = {}, OpenMode mode = ReadWrite);
void start(OpenMode mode = ReadWrite);
+ void startCommand(const QString &command, OpenMode mode = ReadWrite);
bool startDetached(qint64 *pid = nullptr);
bool open(OpenMode mode = ReadWrite) override;
@@ -185,7 +157,7 @@ public:
void setStandardErrorFile(const QString &fileName, OpenMode mode = Truncate);
void setStandardOutputProcess(QProcess *destination);
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
QString nativeArguments() const;
void setNativeArguments(const QString &arguments);
struct CreateProcessArguments
@@ -199,12 +171,39 @@ public:
void *environment;
const wchar_t *currentDirectory;
Q_STARTUPINFO *startupInfo;
- Q_PID processInformation;
+ Q_PROCESS_INFORMATION *processInformation;
};
typedef std::function<void(CreateProcessArguments *)> CreateProcessArgumentModifier;
CreateProcessArgumentModifier createProcessArgumentsModifier() const;
void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier);
-#endif // Q_OS_WIN || Q_CLANG_QDOC
+#endif // Q_OS_WIN || Q_QDOC
+#if defined(Q_OS_UNIX) || defined(Q_QDOC)
+ std::function<void(void)> childProcessModifier() const;
+ void setChildProcessModifier(const std::function<void(void)> &modifier);
+ Q_NORETURN void failChildProcessModifier(const char *description, int error = 0) noexcept;
+
+ enum class UnixProcessFlag : quint32 {
+ ResetSignalHandlers = 0x0001, // like POSIX_SPAWN_SETSIGDEF
+ IgnoreSigPipe = 0x0002,
+ // some room if we want to add IgnoreSigHup or so
+ CloseFileDescriptors = 0x0010,
+ UseVFork = 0x0020, // like POSIX_SPAWN_USEVFORK
+ CreateNewSession = 0x0040, // like POSIX_SPAWN_SETSID
+ DisconnectControllingTerminal = 0x0080,
+ ResetIds = 0x0100, // like POSIX_SPAWN_RESETIDS
+ };
+ Q_DECLARE_FLAGS(UnixProcessFlags, UnixProcessFlag)
+ struct UnixProcessParameters
+ {
+ UnixProcessFlags flags = {};
+ int lowestFileDescriptorToClose = 0;
+
+ quint32 _reserved[6] {};
+ };
+ UnixProcessParameters unixProcessParameters() const noexcept;
+ void setUnixProcessParameters(const UnixProcessParameters &params);
+ void setUnixProcessParameters(UnixProcessFlags flagsOnly);
+#endif
QString workingDirectory() const;
void setWorkingDirectory(const QString &dir);
@@ -217,8 +216,6 @@ public:
QProcess::ProcessError error() const;
QProcess::ProcessState state() const;
- // #### Qt 5: Q_PID is a pointer on Windows and a value on Unix
- Q_PID pid() const;
qint64 processId() const;
bool waitForStarted(int msecs = 30000);
@@ -263,8 +260,6 @@ Q_SIGNALS:
protected:
void setProcessState(ProcessState state);
- virtual void setupChildProcess();
-
// QIODevice
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
@@ -273,14 +268,28 @@ private:
Q_DECLARE_PRIVATE(QProcess)
Q_DISABLE_COPY(QProcess)
+#if QT_VERSION < QT_VERSION_CHECK(7,0,0)
+ // ### Qt7: Remove this struct and the virtual function; they're here only
+ // to cause build errors in Qt 5 code that wasn't updated to Qt 6's
+ // setChildProcessModifier()
+ struct Use_setChildProcessModifier_Instead {};
+ QT_DEPRECATED_X("Use setChildProcessModifier() instead")
+ virtual Use_setChildProcessModifier_Instead setupChildProcess();
+#endif
+
Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardOutput())
Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardError())
+#ifdef Q_OS_UNIX
Q_PRIVATE_SLOT(d_func(), bool _q_canWrite())
+#endif
Q_PRIVATE_SLOT(d_func(), bool _q_startupNotification())
- Q_PRIVATE_SLOT(d_func(), bool _q_processDied())
- friend class QProcessManager;
+ Q_PRIVATE_SLOT(d_func(), void _q_processDied())
};
+#ifdef Q_OS_UNIX
+Q_DECLARE_OPERATORS_FOR_FLAGS(QProcess::UnixProcessFlags)
+#endif
+
#endif // QT_CONFIG(process)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qprocess_darwin.mm b/src/corelib/io/qprocess_darwin.mm
index 2c3c296cb4..29b6c6f25d 100644
--- a/src/corelib/io/qprocess_darwin.mm
+++ b/src/corelib/io/qprocess_darwin.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qprocess_p.h>
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 2587530c09..9510101e74 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROCESS_P_H
#define QPROCESS_P_H
@@ -57,6 +21,7 @@
#include "QtCore/qhash.h"
#include "QtCore/qmap.h"
#include "QtCore/qshareddata.h"
+#include "QtCore/qdeadlinetimer.h"
#include "private/qiodevice_p.h"
QT_REQUIRE_CONFIG(processenvironment);
@@ -80,7 +45,6 @@ class QSocketNotifier;
class QWindowsPipeReader;
class QWindowsPipeWriter;
class QWinEventNotifier;
-class QTimer;
#ifdef Q_OS_WIN
class QProcEnvKey : public QString
@@ -99,7 +63,7 @@ inline bool operator<(const QProcEnvKey &a, const QProcEnvKey &b)
return a.compare(b, Qt::CaseInsensitive) < 0;
}
-Q_DECLARE_TYPEINFO(QProcEnvKey, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QProcEnvKey, Q_RELOCATABLE_TYPE);
typedef QString QProcEnvValue;
#else
@@ -133,7 +97,7 @@ public:
mutable QByteArray byteValue;
mutable QString stringValue;
};
-Q_DECLARE_TYPEINFO(QProcEnvValue, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QProcEnvValue, Q_RELOCATABLE_TYPE);
#endif
class QProcessEnvironmentPrivate: public QSharedData
@@ -147,7 +111,7 @@ public:
inline Value prepareValue(const QString &value) const { return value; }
inline QString valueToString(const Value &value) const { return value; }
#else
- struct NameMapMutexLocker : public QMutexLocker
+ struct NameMapMutexLocker : public QMutexLocker<QMutex>
{
NameMapMutexLocker(const QProcessEnvironmentPrivate *d) : QMutexLocker(&d->nameMapMutex) {}
};
@@ -230,23 +194,13 @@ public:
Q_DECLARE_PUBLIC(QProcess)
struct Channel {
- enum ProcessChannelType {
+ enum ProcessChannelType : char {
Normal = 0,
PipeSource = 1,
PipeSink = 2,
Redirect = 3
- // if you add "= 4" here, increase the number of bits below
};
- Channel() : process(nullptr), notifier(nullptr), type(Normal), closed(false), append(false)
- {
- pipe[0] = INVALID_Q_PIPE;
- pipe[1] = INVALID_Q_PIPE;
-#ifdef Q_OS_WIN
- reader = 0;
-#endif
- }
-
void clear();
Channel &operator=(const QString &fileName)
@@ -272,19 +226,20 @@ public:
}
QString file;
- QProcessPrivate *process;
- QSocketNotifier *notifier;
-#ifdef Q_OS_WIN
+ QProcessPrivate *process = nullptr;
+#ifdef Q_OS_UNIX
+ QSocketNotifier *notifier = nullptr;
+#else
union {
- QWindowsPipeReader *reader;
+ QWindowsPipeReader *reader = nullptr;
QWindowsPipeWriter *writer;
};
#endif
- Q_PIPE pipe[2];
+ Q_PIPE pipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
- unsigned type : 2;
- bool closed : 1;
- bool append : 1;
+ ProcessChannelType type = Normal;
+ bool closed = false;
+ bool append = false;
};
QProcessPrivate();
@@ -293,88 +248,95 @@ public:
// private slots
bool _q_canReadStandardOutput();
bool _q_canReadStandardError();
+#ifdef Q_OS_WIN
+ qint64 pipeWriterBytesToWrite() const;
+ void _q_bytesWritten(qint64 bytes);
+ void _q_writeFailed();
+#else
bool _q_canWrite();
+ bool writeToStdin();
+#endif
bool _q_startupNotification();
- bool _q_processDied();
-
- QProcess::ProcessChannelMode processChannelMode;
- QProcess::InputChannelMode inputChannelMode;
- QProcess::ProcessError processError;
- QProcess::ProcessState processState;
- QString workingDirectory;
- Q_PID pid;
- int sequenceNumber;
-
- bool dying;
- bool emittedReadyRead;
- bool emittedBytesWritten;
+ void _q_processDied();
Channel stdinChannel;
Channel stdoutChannel;
Channel stderrChannel;
+ bool openChannels();
+ bool openChannelsForDetached();
bool openChannel(Channel &channel);
void closeChannel(Channel *channel);
void closeWriteChannel();
+ void closeChannels();
bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr
QString program;
QStringList arguments;
+ QString workingDirectory;
+ QProcessEnvironment environment = QProcessEnvironment::InheritFromParent;
#if defined(Q_OS_WIN)
QString nativeArguments;
QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs;
+ QWinEventNotifier *processFinishedNotifier = nullptr;
+ Q_PROCESS_INFORMATION *pid = nullptr;
+#else
+ struct UnixExtras {
+ std::function<void(void)> childProcessModifier;
+ QProcess::UnixProcessParameters processParameters;
+ };
+ std::unique_ptr<UnixExtras> unixExtras;
+ QSocketNotifier *stateNotifier = nullptr;
+ Q_PIPE childStartedPipe[2] = {INVALID_Q_PIPE, INVALID_Q_PIPE};
+ pid_t pid = 0;
+ int forkfd = -1;
#endif
- QProcessEnvironment environment;
-
- Q_PIPE childStartedPipe[2];
- void destroyPipe(Q_PIPE pipe[2]);
- QSocketNotifier *startupSocketNotifier;
- QSocketNotifier *deathNotifier;
-
- int forkfd;
-
-#ifdef Q_OS_WIN
- QTimer *stdinWriteTrigger;
- QWinEventNotifier *processFinishedNotifier;
-#endif
+ int exitCode = 0;
+ quint8 processState = QProcess::NotRunning;
+ quint8 exitStatus = QProcess::NormalExit;
+ quint8 processError = QProcess::UnknownError;
+ quint8 processChannelMode = QProcess::SeparateChannels;
+ quint8 inputChannelMode = QProcess::ManagedInputChannel;
+ bool emittedReadyRead = false;
+ bool emittedBytesWritten = false;
void start(QIODevice::OpenMode mode);
void startProcess();
#if defined(Q_OS_UNIX)
- void execChild(const char *workingDirectory, char **argv, char **envp);
+ void commitChannels() const;
#endif
bool processStarted(QString *errorMessage = nullptr);
+ void processFinished();
void terminateProcess();
void killProcess();
- void findExitCode();
#ifdef Q_OS_UNIX
- bool waitForDeadChild();
+ void waitForDeadChild();
+#else
+ void findExitCode();
#endif
#ifdef Q_OS_WIN
+ STARTUPINFOW createStartupInfo();
bool callCreateProcess(QProcess::CreateProcessArguments *cpargs);
bool drainOutputPipes();
- void flushPipeWriter();
- qint64 pipeWriterBytesToWrite() const;
#endif
bool startDetached(qint64 *pPid);
- int exitCode;
- QProcess::ExitStatus exitStatus;
- bool crashed;
-
- bool waitForStarted(int msecs = 30000);
- bool waitForReadyRead(int msecs = 30000);
- bool waitForBytesWritten(int msecs = 30000);
- bool waitForFinished(int msecs = 30000);
+ bool waitForStarted(const QDeadlineTimer &deadline);
+ bool waitForReadyRead(const QDeadlineTimer &deadline);
+ bool waitForBytesWritten(const QDeadlineTimer &deadline);
+ bool waitForFinished(const QDeadlineTimer &deadline);
qint64 bytesAvailableInChannel(const Channel *channel) const;
qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
- bool writeToStdin();
+ void destroyPipe(Q_PIPE pipe[2]);
void cleanup();
void setError(QProcess::ProcessError error, const QString &description = QString());
void setErrorAndEmit(QProcess::ProcessError error, const QString &description = QString());
+
+ const QProcessEnvironmentPrivate *environmentPrivate() const
+ { return environment.d.constData(); }
};
#endif // QT_CONFIG(process)
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 50390e57f5..5c696433fd 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -1,88 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// Copyright (C) 2021 Alex Trotsenko.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QPROCESS_DEBUG
#include "qdebug.h"
-
-#if QT_CONFIG(process) && defined(QPROCESS_DEBUG)
-#include "private/qtools_p.h"
-#include <ctype.h>
-
-/*
- Returns a human readable representation of the first \a len
- characters in \a data.
-*/
-QT_BEGIN_NAMESPACE
-static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
-{
- if (!data) return "(null)";
- QByteArray out;
- for (int i = 0; i < len; ++i) {
- char c = data[i];
- if (isprint(c)) {
- out += c;
- } else switch (c) {
- case '\n': out += "\\n"; break;
- case '\r': out += "\\r"; break;
- case '\t': out += "\\t"; break;
- default: {
- const char buf[] = {
- '\\',
- QtMiscUtils::toOct(uchar(c) / 64),
- QtMiscUtils::toOct(uchar(c) % 64 / 8),
- QtMiscUtils::toOct(uchar(c) % 8),
- 0
- };
- out += buf;
- }
- }
- }
-
- if (len < maxSize)
- out += "...";
-
- return out;
-}
-QT_END_NAMESPACE
-#endif
-
+#include <private/qdebug_p.h>
#include "qplatformdefs.h"
#include "qprocess.h"
@@ -91,7 +14,7 @@ QT_END_NAMESPACE
#include "private/qcore_unix_p.h"
#include "private/qlocking_p.h"
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
#include <private/qcore_mac_p.h>
#endif
@@ -104,27 +27,51 @@ QT_END_NAMESPACE
#include <qmutex.h>
#include <qsocketnotifier.h>
#include <qthread.h>
-#include <qelapsedtimer.h>
#ifdef Q_OS_QNX
# include <sys/neutrino.h>
#endif
#include <errno.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/resource.h>
+#include <termios.h>
+#include <unistd.h>
+
+#if __has_include(<paths.h>)
+# include <paths.h>
+#endif
+#if __has_include(<linux/close_range.h>)
+// FreeBSD's is in <unistd.h>
+# include <linux/close_range.h>
+#endif
#if QT_CONFIG(process)
#include <forkfd.h>
#endif
+#ifndef O_PATH
+# define O_PATH 0
+#endif
+#ifndef _PATH_DEV
+# define _PATH_DEV "/dev/"
+#endif
+#ifndef _PATH_TTY
+# define _PATH_TTY _PATH_DEV "tty"
+#endif
+
+#ifdef Q_OS_FREEBSD
+__attribute__((weak))
+#endif
+extern char **environ;
+
QT_BEGIN_NAMESPACE
-#if !defined(Q_OS_DARWIN)
+using namespace Qt::StringLiterals;
-QT_BEGIN_INCLUDE_NAMESPACE
-extern char **environ;
-QT_END_INCLUDE_NAMESPACE
+#if !defined(Q_OS_DARWIN)
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
@@ -147,20 +94,113 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
#if QT_CONFIG(process)
+namespace QtVforkSafe {
+// Certain libc functions we need to call in the child process scenario aren't
+// safe under vfork() because they do more than just place the system call to
+// the kernel and set errno on return. For those, we'll create a function
+// pointer like:
+// static constexpr auto foobar = __libc_foobar;
+// while for all other OSes, it'll be
+// using ::foobar;
+// allowing the code for the child side of the vfork to simply use
+// QtVforkSafe::foobar(args);
+//
+// Currently known issues are:
+//
+// - FreeBSD's libthr sigaction() wrapper locks a rwlock
+// https://github.com/freebsd/freebsd-src/blob/8dad5ece49479ba6cdcd5bb4c2799bbd61add3e6/lib/libthr/thread/thr_sig.c#L575-L641
+// - MUSL's sigaction() locks a mutex if the signal is SIGABR
+// https://github.com/bminor/musl/blob/718f363bc2067b6487900eddc9180c84e7739f80/src/signal/sigaction.c#L63-L85
+//
+// All other functions called in the child side are vfork-safe, provided that
+// PThread cancellation is disabled and Unix signals are blocked.
+#if defined(__MUSL__)
+# define LIBC_PREFIX __libc_
+#elif defined(Q_OS_FREEBSD)
+// will cause QtCore to link to ELF version "FBSDprivate_1.0"
+# define LIBC_PREFIX _
+#endif
+
+#ifdef LIBC_PREFIX
+# define CONCAT(x, y) CONCAT2(x, y)
+# define CONCAT2(x, y) x ## y
+# define DECLARE_FUNCTIONS(NAME) \
+ extern decltype(::NAME) CONCAT(LIBC_PREFIX, NAME); \
+ static constexpr auto NAME = std::addressof(CONCAT(LIBC_PREFIX, NAME));
+#else // LIBC_PREFIX
+# define DECLARE_FUNCTIONS(NAME) using ::NAME;
+#endif // LIBC_PREFIX
+
+extern "C" {
+DECLARE_FUNCTIONS(sigaction)
+}
+
+#undef LIBC_PREFIX
+#undef DECLARE_FUNCTIONS
+
+// similar to qt_ignore_sigpipe() in qcore_unix_p.h, but vfork-safe
+static void change_sigpipe(decltype(SIG_DFL) new_handler)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = new_handler;
+ sigaction(SIGPIPE, &sa, nullptr);
+}
+} // namespace QtVforkSafe
+
+static int opendirfd(QByteArray encodedName)
+{
+ // We append "/." to the name to ensure that the directory is actually
+ // traversable (i.e., has the +x bit set). This avoids later problems
+ // with fchdir().
+ if (encodedName != "/" && !encodedName.endsWith("/."))
+ encodedName += "/.";
+ return qt_safe_open(encodedName, QT_OPEN_RDONLY | O_DIRECTORY | O_PATH);
+}
+
namespace {
+struct AutoPipe
+{
+ int pipe[2] = { -1, -1 };
+ AutoPipe(int flags = 0)
+ {
+ qt_safe_pipe(pipe, flags);
+ }
+ ~AutoPipe()
+ {
+ for (int fd : pipe) {
+ if (fd >= 0)
+ qt_safe_close(fd);
+ }
+ }
+
+ explicit operator bool() const { return pipe[0] >= 0; }
+ int &operator[](int idx) { return pipe[idx]; }
+ int operator[](int idx) const { return pipe[idx]; }
+};
+
+struct ChildError
+{
+ int code;
+ char function[_POSIX_PIPE_BUF - sizeof(code)];
+};
+static_assert(std::is_trivial_v<ChildError>);
+#ifdef PIPE_BUF
+static_assert(PIPE_BUF >= sizeof(ChildError)); // PIPE_BUF may be bigger
+#endif
+
struct QProcessPoller
{
QProcessPoller(const QProcessPrivate &proc);
- int poll(int timeout);
+ int poll(const QDeadlineTimer &deadline);
pollfd &stdinPipe() { return pfds[0]; }
pollfd &stdoutPipe() { return pfds[1]; }
pollfd &stderrPipe() { return pfds[2]; }
pollfd &forkfd() { return pfds[3]; }
- pollfd &childStartedPipe() { return pfds[4]; }
- enum { n_pfds = 5 };
+ enum { n_pfds = 4 };
pollfd pfds[n_pfds];
};
@@ -178,15 +218,196 @@ QProcessPoller::QProcessPoller(const QProcessPrivate &proc)
}
forkfd().fd = proc.forkfd;
+}
+
+int QProcessPoller::poll(const QDeadlineTimer &deadline)
+{
+ return qt_safe_poll(pfds, n_pfds, deadline);
+}
+
+struct QChildProcess
+{
+ // Used for argv and envp arguments to execve()
+ struct CharPointerList
+ {
+ std::unique_ptr<char *[]> pointers;
+
+ CharPointerList(const QString &argv0, const QStringList &args);
+ explicit CharPointerList(const QProcessEnvironmentPrivate *env);
+ /*implicit*/ operator char **() const { return pointers.get(); }
+
+ private:
+ QByteArray data;
+ void updatePointers(qsizetype count);
+ };
+
+ const QProcessPrivate *d;
+ CharPointerList argv;
+ CharPointerList envp;
+ sigset_t oldsigset;
+ int workingDirectory = -2;
+ bool isUsingVfork = usingVfork();
+
+ bool ok() const
+ {
+ return workingDirectory != -1;
+ }
+
+ QChildProcess(QProcessPrivate *d)
+ : d(d), argv(resolveExecutable(d->program), d->arguments),
+ envp(d->environmentPrivate())
+ {
+ // Block Unix signals, to ensure the user's handlers aren't run in the
+ // child side and do something weird, especially if the handler and the
+ // user of QProcess are completely different codebases.
+ maybeBlockSignals();
+
+ // Disable PThread cancellation until the child has successfully been
+ // executed. We make a number of POSIX calls in the child that are thread
+ // cancellation points and could cause an unexpected stack unwind. That
+ // would be bad enough with regular fork(), but it's likely fatal with
+ // vfork().
+ disableThreadCancellations();
+
+ if (!d->workingDirectory.isEmpty()) {
+ workingDirectory = opendirfd(QFile::encodeName(d->workingDirectory));
+ if (workingDirectory < 0) {
+ d->setErrorAndEmit(QProcess::FailedToStart, "chdir: "_L1 + qt_error_string());
+ d->cleanup();
+ }
+ }
+
+ }
+ ~QChildProcess() noexcept(false)
+ {
+ if (workingDirectory >= 0)
+ close(workingDirectory);
+
+ restoreThreadCancellations();
+ restoreSignalMask();
+ }
+
+ void maybeBlockSignals() noexcept
+ {
+ // We only block Unix signals if we're using vfork(), to avoid a
+ // changing behavior to the user's modifier and because in some OSes
+ // this action would block crashing signals too.
+ if (isUsingVfork) {
+ sigset_t emptyset;
+ sigfillset(&emptyset);
+ pthread_sigmask(SIG_SETMASK, &emptyset, &oldsigset);
+ }
+ }
+
+ void restoreSignalMask() const noexcept
+ {
+ if (isUsingVfork)
+ pthread_sigmask(SIG_SETMASK, &oldsigset, nullptr);
+ }
+
+ bool usingVfork() const noexcept;
+
+ template <typename Lambda> int doFork(Lambda &&childLambda)
+ {
+ pid_t pid;
+ if (isUsingVfork) {
+ QT_IGNORE_DEPRECATIONS(pid = vfork();)
+ } else {
+ pid = fork();
+ }
+ if (pid == 0)
+ _exit(childLambda());
+ return pid;
+ }
+
+ int startChild(pid_t *pid)
+ {
+ int ffdflags = FFD_CLOEXEC | (isUsingVfork ? 0 : FFD_USE_FORK);
+ return ::vforkfd(ffdflags, pid, &QChildProcess::startProcess, this);
+ }
+
+private:
+ Q_NORETURN void startProcess() const noexcept;
+ static int startProcess(void *self) noexcept
+ {
+ static_cast<QChildProcess *>(self)->startProcess();
+ Q_UNREACHABLE_RETURN(-1);
+ }
+
+#if defined(PTHREAD_CANCEL_DISABLE)
+ int oldstate;
+ void disableThreadCancellations() noexcept
+ {
+ // the following is *not* noexcept, but it won't throw while disabling
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
+ }
+ void restoreThreadCancellations() noexcept(false)
+ {
+ // this doesn't touch errno
+ pthread_setcancelstate(oldstate, nullptr);
+ }
+#else
+ void disableThreadCancellations() noexcept {}
+ void restoreThreadCancellations() {}
+#endif
+
+ static QString resolveExecutable(const QString &program);
+};
+
+QChildProcess::CharPointerList::CharPointerList(const QString &program, const QStringList &args)
+{
+ qsizetype count = 1 + args.size();
+ pointers.reset(new char *[count + 1]);
+ pointers[count] = nullptr;
+
+ // we abuse the pointer array to store offsets first (QByteArray will
+ // reallocate, after all)
+ pointers[0] = reinterpret_cast<char *>(0);
+ data = QFile::encodeName(program);
+ data += '\0';
+
+ const auto end = args.end();
+ auto it = args.begin();
+ for (qsizetype i = 1; it != end; ++it, ++i) {
+ pointers[i] = reinterpret_cast<char *>(data.size());
+ data += QFile::encodeName(*it);
+ data += '\0';
+ }
- if (proc.processState == QProcess::Starting)
- childStartedPipe().fd = proc.childStartedPipe[0];
+ updatePointers(count);
}
-int QProcessPoller::poll(int timeout)
+QChildProcess::CharPointerList::CharPointerList(const QProcessEnvironmentPrivate *environment)
{
- const nfds_t nfds = (childStartedPipe().fd == -1) ? 4 : 5;
- return qt_poll_msecs(pfds, nfds, timeout);
+ if (!environment)
+ return;
+
+ const QProcessEnvironmentPrivate::Map &env = environment->vars;
+ qsizetype count = env.size();
+ pointers.reset(new char *[count + 1]);
+ pointers[count] = nullptr;
+
+ const auto end = env.end();
+ auto it = env.begin();
+ for (qsizetype i = 0; it != end; ++it, ++i) {
+ // we abuse the pointer array to store offsets first (QByteArray will
+ // reallocate, after all)
+ pointers[i] = reinterpret_cast<char *>(data.size());
+
+ data += it.key();
+ data += '=';
+ data += it->bytes();
+ data += '\0';
+ }
+
+ updatePointers(count);
+}
+
+void QChildProcess::CharPointerList::updatePointers(qsizetype count)
+{
+ char *const base = const_cast<char *>(data.constBegin());
+ for (qsizetype i = 0; i < count; ++i)
+ pointers[i] = base + qptrdiff(pointers[i]);
}
} // anonymous namespace
@@ -203,7 +424,8 @@ static int qt_create_pipe(int *pipe)
qt_safe_close(pipe[1]);
int pipe_ret = qt_safe_pipe(pipe);
if (pipe_ret != 0) {
- qErrnoWarning("QProcessPrivate::createPipe: Cannot create pipe %p", pipe);
+ QScopedValueRollback rollback(errno);
+ qErrnoWarning("QProcess: Cannot create pipe");
}
return pipe_ret;
}
@@ -222,40 +444,51 @@ void QProcessPrivate::destroyPipe(int *pipe)
void QProcessPrivate::closeChannel(Channel *channel)
{
+ delete channel->notifier;
+ channel->notifier = nullptr;
+
destroyPipe(channel->pipe);
}
+void QProcessPrivate::cleanup()
+{
+ q_func()->setProcessState(QProcess::NotRunning);
+
+ closeChannels();
+ delete stateNotifier;
+ stateNotifier = nullptr;
+ destroyPipe(childStartedPipe);
+ pid = 0;
+ if (forkfd != -1) {
+ qt_safe_close(forkfd);
+ forkfd = -1;
+ }
+}
+
/*
Create the pipes to a QProcessPrivate::Channel.
-
- This function must be called in order: stdin, stdout, stderr
*/
bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
- if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) {
- channel.pipe[0] = -1;
- channel.pipe[1] = -1;
- return true;
- }
-
if (channel.type == Channel::Normal) {
// we're piping this channel to our own process
- if (qt_create_pipe(channel.pipe) != 0)
+ if (qt_create_pipe(channel.pipe) != 0) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
return false;
+ }
// create the socket notifiers
if (threadData.loadRelaxed()->hasEventDispatcher()) {
if (&channel == &stdinChannel) {
- channel.notifier = new QSocketNotifier(channel.pipe[1],
- QSocketNotifier::Write, q);
- channel.notifier->setEnabled(false);
+ channel.notifier = new QSocketNotifier(QSocketNotifier::Write, q);
+ channel.notifier->setSocket(channel.pipe[1]);
QObject::connect(channel.notifier, SIGNAL(activated(QSocketDescriptor)),
q, SLOT(_q_canWrite()));
} else {
- channel.notifier = new QSocketNotifier(channel.pipe[0],
- QSocketNotifier::Read, q);
+ channel.notifier = new QSocketNotifier(QSocketNotifier::Read, q);
+ channel.notifier->setSocket(channel.pipe[0]);
const char *receiver;
if (&channel == &stdoutChannel)
receiver = SLOT(_q_canReadStandardOutput());
@@ -292,7 +525,6 @@ bool QProcessPrivate::openChannel(Channel &channel)
setErrorAndEmit(QProcess::FailedToStart,
QProcess::tr("Could not open input redirection for reading"));
}
- cleanup();
return false;
} else {
Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
@@ -324,8 +556,10 @@ bool QProcessPrivate::openChannel(Channel &channel)
Q_ASSERT(sink->pipe[0] == INVALID_Q_PIPE && sink->pipe[1] == INVALID_Q_PIPE);
Q_PIPE pipe[2] = { -1, -1 };
- if (qt_create_pipe(pipe) != 0)
+ if (qt_create_pipe(pipe) != 0) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
return false;
+ }
sink->pipe[0] = pipe[0];
source->pipe[1] = pipe[1];
@@ -334,77 +568,37 @@ bool QProcessPrivate::openChannel(Channel &channel)
}
}
-static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Map &environment, int *envc)
+void QProcessPrivate::commitChannels() const
{
- *envc = 0;
- if (environment.isEmpty())
- return nullptr;
-
- char **envp = new char *[environment.count() + 2];
- envp[environment.count()] = nullptr;
- envp[environment.count() + 1] = nullptr;
-
- auto it = environment.constBegin();
- const auto end = environment.constEnd();
- for ( ; it != end; ++it) {
- QByteArray key = it.key();
- QByteArray value = it.value().bytes();
- key.reserve(key.length() + 1 + value.length());
- key.append('=');
- key.append(value);
-
- envp[(*envc)++] = ::strdup(key.constData());
- }
+ // copy the stdin socket if asked to (without closing on exec)
+ if (stdinChannel.pipe[0] != INVALID_Q_PIPE)
+ qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0);
- return envp;
+ // copy the stdout and stderr if asked to
+ if (stdoutChannel.pipe[1] != INVALID_Q_PIPE)
+ qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0);
+ if (stderrChannel.pipe[1] != INVALID_Q_PIPE) {
+ qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0);
+ } else {
+ // merge stdout and stderr if asked to
+ if (processChannelMode == QProcess::MergedChannels)
+ qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0);
+ }
}
-void QProcessPrivate::startProcess()
+inline QString QChildProcess::resolveExecutable(const QString &program)
{
- Q_Q(QProcess);
-
-#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::startProcess()");
-#endif
-
- // Initialize pipes
- if (!openChannel(stdinChannel) ||
- !openChannel(stdoutChannel) ||
- !openChannel(stderrChannel) ||
- qt_create_pipe(childStartedPipe) != 0) {
- setErrorAndEmit(QProcess::FailedToStart, qt_error_string(errno));
- cleanup();
- return;
- }
-
- if (threadData.loadRelaxed()->hasEventDispatcher()) {
- startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
- QSocketNotifier::Read, q);
- QObject::connect(startupSocketNotifier, SIGNAL(activated(QSocketDescriptor)),
- q, SLOT(_q_startupNotification()));
- }
-
- // Start the process (platform dependent)
- q->setProcessState(QProcess::Starting);
-
- // Create argument list with right number of elements, and set the final
- // one to 0.
- char **argv = new char *[arguments.count() + 2];
- argv[arguments.count() + 1] = nullptr;
-
- // Encode the program name.
- QByteArray encodedProgramName = QFile::encodeName(program);
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
// allow invoking of .app bundles on the Mac.
QFileInfo fileInfo(program);
- if (encodedProgramName.endsWith(".app") && fileInfo.isDir()) {
+ if (program.endsWith(".app"_L1) && fileInfo.isDir()) {
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0,
QCFString(fileInfo.absoluteFilePath()),
kCFURLPOSIXPathStyle, true);
{
// CFBundle is not reentrant, since CFBundleCreate might return a reference
// to a cached bundle object. Protect the bundle calls with a mutex lock.
- static QBasicMutex cfbundleMutex;
+ Q_CONSTINIT static QBasicMutex cfbundleMutex;
const auto locker = qt_scoped_lock(cfbundleMutex);
QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
// 'executableURL' can be either relative or absolute ...
@@ -414,71 +608,116 @@ void QProcessPrivate::startProcess()
}
if (url) {
const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
- encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QString::fromCFString(str))).toUtf8();
+ return QString::fromCFString(str);
}
}
#endif
- // Add the program name to the argument list.
- argv[0] = nullptr;
- if (!program.contains(QLatin1Char('/'))) {
- const QString &exeFilePath = QStandardPaths::findExecutable(program);
- if (!exeFilePath.isEmpty()) {
- const QByteArray &tmp = QFile::encodeName(exeFilePath);
- argv[0] = ::strdup(tmp.constData());
- }
+ if (!program.contains(u'/')) {
+ // findExecutable() returns its argument if it's an absolute path,
+ // otherwise it searches $PATH; returns empty if not found (we handle
+ // that case much later)
+ return QStandardPaths::findExecutable(program);
+ }
+ return program;
+}
+
+extern "C" {
+__attribute__((weak)) pid_t __interceptor_vfork();
+}
+
+inline bool globalUsingVfork() noexcept
+{
+#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
+ // ASan writes to global memory, so we mustn't use vfork().
+ return false;
+#endif
+#if defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer)
+ // Ditto, apparently
+ return false;
+#endif
+#if defined(Q_OS_LINUX) && !QT_CONFIG(forkfd_pidfd)
+ // some broken environments are known to have problems with the new Linux
+ // API, so we have a way for users to opt-out during configure time (see
+ // QTBUG-86285)
+ return false;
+#endif
+#if defined(Q_OS_DARWIN)
+ // Using vfork() for startDetached() is causing problems. We don't know
+ // why: without the tools to investigate why it happens, we didn't bother.
+ return false;
+#endif
+
+ // Dynamically detect whether libasan or libtsan are loaded into the
+ // process' memory. We need this because the user's code may be compiled
+ // with ASan or TSan, but not Qt.
+ return __interceptor_vfork == nullptr;
+}
+
+inline bool QChildProcess::usingVfork() const noexcept
+{
+ if (!globalUsingVfork())
+ return false;
+
+ if (!d->unixExtras || !d->unixExtras->childProcessModifier)
+ return true; // no modifier was supplied
+
+ // if a modifier was supplied, use fork() unless the user opts in to
+ // vfork()
+ auto flags = d->unixExtras->processParameters.flags;
+ return flags.testFlag(QProcess::UnixProcessFlag::UseVFork);
+}
+
+#ifdef QT_BUILD_INTERNAL
+Q_AUTOTEST_EXPORT bool _qprocessUsingVfork() noexcept
+{
+ return globalUsingVfork();
+}
+#endif
+
+void QProcessPrivate::startProcess()
+{
+ Q_Q(QProcess);
+ q->setProcessState(QProcess::Starting);
+
+#if defined (QPROCESS_DEBUG)
+ qDebug("QProcessPrivate::startProcess()");
+#endif
+
+ // Initialize pipes
+ if (!openChannels()) {
+ // openChannel sets the error string
+ Q_ASSERT(!errorString.isEmpty());
+ cleanup();
+ return;
+ }
+ if (qt_create_pipe(childStartedPipe) != 0) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
+ cleanup();
+ return;
}
- if (!argv[0])
- argv[0] = ::strdup(encodedProgramName.constData());
-
- // Add every argument to the list
- for (int i = 0; i < arguments.count(); ++i)
- argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
-
- // Duplicate the environment.
- int envc = 0;
- char **envp = nullptr;
- if (environment.d.constData()) {
- envp = _q_dupEnvironment(environment.d.constData()->vars, &envc);
+
+ if (threadData.loadRelaxed()->hasEventDispatcher()) {
+ // Set up to notify about startup completion (and premature death).
+ // Once the process has started successfully, we reconfigure the
+ // notifier to watch the fork_fd for expected death.
+ stateNotifier = new QSocketNotifier(childStartedPipe[0],
+ QSocketNotifier::Read, q);
+ QObject::connect(stateNotifier, SIGNAL(activated(QSocketDescriptor)),
+ q, SLOT(_q_startupNotification()));
}
- // Encode the working directory if it's non-empty, otherwise just pass 0.
- const char *workingDirPtr = nullptr;
- QByteArray encodedWorkingDirectory;
- if (!workingDirectory.isEmpty()) {
- encodedWorkingDirectory = QFile::encodeName(workingDirectory);
- workingDirPtr = encodedWorkingDirectory.constData();
+ // Prepare the arguments and the environment
+ QChildProcess childProcess(this);
+ if (!childProcess.ok()) {
+ Q_ASSERT(processError != QProcess::UnknownError);
+ return;
}
- // Select FFD_USE_FORK and FFD_VFORK_SEMANTICS based on whether there's
- // user code running in the child process: if there is, we don't know what
- // the user will want to do, so we err on the safe side and request an
- // actual fork() (for example, the user could attempt to do some
- // synchronization with the parent process). But if there isn't, then our
- // code in execChild() is just a handful of dup2() and a chdir(), so it's
- // safe with vfork semantics: suspend the parent execution until the child
- // either execve()s or _exit()s.
- int ffdflags = FFD_CLOEXEC;
- if (typeid(*q) != typeid(QProcess))
- ffdflags |= FFD_USE_FORK;
- pid_t childPid;
- forkfd = ::forkfd(ffdflags , &childPid);
+ // Start the child.
+ forkfd = childProcess.startChild(&pid);
int lastForkErrno = errno;
- if (forkfd != FFD_CHILD_PROCESS) {
- // Parent process.
- // Clean up duplicated memory.
- for (int i = 0; i <= arguments.count(); ++i)
- free(argv[i]);
- for (int i = 0; i < envc; ++i)
- free(envp[i]);
- delete [] argv;
- delete [] envp;
- }
- // On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0.
- // This is intentional because we only want to handle failure to fork()
- // here, which is a rare occurrence. Handling of the failure to start is
- // done elsewhere.
if (forkfd == -1) {
// Cleanup, report error and return
#if defined (QPROCESS_DEBUG)
@@ -491,13 +730,7 @@ void QProcessPrivate::startProcess()
return;
}
- // Start the child.
- if (forkfd == FFD_CHILD_PROCESS) {
- execChild(workingDirPtr, argv, envp);
- ::_exit(-1);
- }
-
- pid = Q_PID(childPid);
+ Q_ASSERT(pid > 0);
// parent
// close the ends we don't use and make all pipes non-blocking
@@ -526,100 +759,229 @@ void QProcessPrivate::startProcess()
}
if (stderrChannel.pipe[0] != -1)
::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK);
+}
- if (threadData.loadRelaxed()->eventDispatcher.loadAcquire()) {
- deathNotifier = new QSocketNotifier(forkfd, QSocketNotifier::Read, q);
- QObject::connect(deathNotifier, SIGNAL(activated(QSocketDescriptor)),
- q, SLOT(_q_processDied()));
- }
+// we need an errno number to use to indicate the child process modifier threw,
+// something the regular operations shouldn't set.
+static constexpr int FakeErrnoForThrow = std::numeric_limits<int>::max();
+
+static QString startFailureErrorMessage(ChildError &err, [[maybe_unused]] ssize_t bytesRead)
+{
+ // ChildError is less than the POSIX pipe buffer atomic size, so the read
+ // must not have been truncated
+ Q_ASSERT(bytesRead == sizeof(err));
+
+ qsizetype len = qstrnlen(err.function, sizeof(err.function));
+ QString complement = QString::fromUtf8(err.function, len);
+ if (err.code == FakeErrnoForThrow)
+ return QProcess::tr("Child process modifier threw an exception: %1")
+ .arg(std::move(complement));
+ if (err.code == 0)
+ return QProcess::tr("Child process modifier reported error: %1")
+ .arg(std::move(complement));
+ if (err.code < 0)
+ return QProcess::tr("Child process modifier reported error: %1: %2")
+ .arg(std::move(complement), qt_error_string(-err.code));
+ return QProcess::tr("Child process set up failed: %1: %2")
+ .arg(std::move(complement), qt_error_string(err.code));
}
-struct ChildError
+Q_NORETURN void
+failChildProcess(const QProcessPrivate *d, const char *description, int code) noexcept
{
- int code;
- char function[8];
-};
+ ChildError error = {};
+ error.code = code;
+ qstrncpy(error.function, description, sizeof(error.function));
+ qt_safe_write(d->childStartedPipe[1], &error, sizeof(error));
+ _exit(-1);
+}
-void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp)
+void QProcess::failChildProcessModifier(const char *description, int error) noexcept
{
- ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored
+ // We signal user errors with negative errnos
+ failChildProcess(d_func(), description, -error);
+}
- Q_Q(QProcess);
- ChildError error = { 0, {} }; // force zeroing of function[8]
+// See IMPORTANT notice below
+static const char *applyProcessParameters(const QProcess::UnixProcessParameters &params)
+{
+ // Apply Unix signal handler parameters.
+ // We don't expect signal() to fail, so we ignore its return value
+ bool ignore_sigpipe = params.flags.testFlag(QProcess::UnixProcessFlag::IgnoreSigPipe);
+ if (ignore_sigpipe)
+ QtVforkSafe::change_sigpipe(SIG_IGN);
+ if (params.flags.testFlag(QProcess::UnixProcessFlag::ResetSignalHandlers)) {
+ struct sigaction sa = {};
+ sa.sa_handler = SIG_DFL;
+ for (int sig = 1; sig < NSIG; ++sig) {
+ if (!ignore_sigpipe || sig != SIGPIPE)
+ QtVforkSafe::sigaction(sig, &sa, nullptr);
+ }
- // copy the stdin socket if asked to (without closing on exec)
- if (inputChannelMode != QProcess::ForwardedInputChannel)
- qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0);
+ // and unmask all signals
+ sigset_t set;
+ sigemptyset(&set);
+ sigprocmask(SIG_SETMASK, &set, nullptr);
+ }
- // copy the stdout and stderr if asked to
- if (processChannelMode != QProcess::ForwardedChannels) {
- if (processChannelMode != QProcess::ForwardedOutputChannel)
- qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0);
+ // Close all file descriptors above stderr.
+ // This isn't expected to fail, so we ignore close()'s return value.
+ if (params.flags.testFlag(QProcess::UnixProcessFlag::CloseFileDescriptors)) {
+ int r = -1;
+ int fd = qMax(STDERR_FILENO + 1, params.lowestFileDescriptorToClose);
+#if QT_CONFIG(close_range)
+ // On FreeBSD, this probably won't fail.
+ // On Linux, this will fail with ENOSYS before kernel 5.9.
+ r = close_range(fd, INT_MAX, 0);
+#endif
+ if (r == -1) {
+ // We *could* read /dev/fd to find out what file descriptors are
+ // open, but we won't. We CANNOT use opendir() here because it
+ // allocates memory. Using getdents(2) plus either strtoul() or
+ // std::from_chars() would be acceptable.
+ int max_fd = INT_MAX;
+ if (struct rlimit limit; getrlimit(RLIMIT_NOFILE, &limit) == 0)
+ max_fd = limit.rlim_cur;
+ for ( ; fd < max_fd; ++fd)
+ close(fd);
+ }
+ }
- // merge stdout and stderr if asked to
- if (processChannelMode == QProcess::MergedChannels) {
- qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0);
- } else if (processChannelMode != QProcess::ForwardedErrorChannel) {
- qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0);
+ // Apply session and process group settings. This may fail.
+ if (params.flags.testFlag(QProcess::UnixProcessFlag::CreateNewSession)) {
+ if (setsid() < 0)
+ return "setsid";
+ }
+
+ // Disconnect from the controlling TTY. This probably won't fail. Must be
+ // done after the session settings from above.
+ if (params.flags.testFlag(QProcess::UnixProcessFlag::DisconnectControllingTerminal)) {
+ if (int fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY); fd >= 0) {
+ // we still have a controlling TTY; give it up
+ int r = ioctl(fd, TIOCNOTTY);
+ int savedErrno = errno;
+ close(fd);
+ if (r != 0) {
+ errno = savedErrno;
+ return "ioctl";
+ }
}
}
+ // Apply UID and GID parameters last. This isn't expected to fail either:
+ // either we're trying to impersonate what we already are, or we're EUID or
+ // EGID root, in which case we are allowed to do this.
+ if (params.flags.testFlag(QProcess::UnixProcessFlag::ResetIds)) {
+ int r = setgid(getgid());
+ r = setuid(getuid());
+ (void) r;
+ }
+
+ return nullptr;
+}
+
+// the noexcept here adds an extra layer of protection
+static void callChildProcessModifier(const QProcessPrivate *d) noexcept
+{
+ QT_TRY {
+ if (d->unixExtras->childProcessModifier)
+ d->unixExtras->childProcessModifier();
+ } QT_CATCH (std::exception &e) {
+ failChildProcess(d, e.what(), FakeErrnoForThrow);
+ } QT_CATCH (...) {
+ failChildProcess(d, "throw", FakeErrnoForThrow);
+ }
+}
+
+// IMPORTANT:
+//
+// This function is called in a vfork() context on some OSes (notably, Linux
+// with forkfd), so it MUST NOT modify any non-local variable because it's
+// still sharing memory with the parent process.
+void QChildProcess::startProcess() const noexcept
+{
+ // Render channels configuration.
+ d->commitChannels();
+
// make sure this fd is closed if execv() succeeds
- qt_safe_close(childStartedPipe[0]);
+ qt_safe_close(d->childStartedPipe[0]);
// enter the working directory
- if (workingDir && QT_CHDIR(workingDir) == -1) {
- // failed, stop the process
- strcpy(error.function, "chdir");
- goto report_errno;
+ if (workingDirectory >= 0 && fchdir(workingDirectory) == -1)
+ failChildProcess(d, "fchdir", errno);
+
+ bool sigpipeHandled = false;
+ bool sigmaskHandled = false;
+ if (d->unixExtras) {
+ // FIRST we call the user modifier function, before we dropping
+ // privileges or closing non-standard file descriptors
+ callChildProcessModifier(d);
+
+ // then we apply our other user-provided parameters
+ if (const char *what = applyProcessParameters(d->unixExtras->processParameters))
+ failChildProcess(d, what, errno);
+
+ auto flags = d->unixExtras->processParameters.flags;
+ using P = QProcess::UnixProcessFlag;
+ sigpipeHandled = flags.testAnyFlags(P::ResetSignalHandlers | P::IgnoreSigPipe);
+ sigmaskHandled = flags.testFlag(P::ResetSignalHandlers);
+ }
+ if (!sigpipeHandled) {
+ // reset the signal that we ignored
+ QtVforkSafe::change_sigpipe(SIG_DFL); // reset the signal that we ignored
+ }
+ if (!sigmaskHandled) {
+ // restore the signal mask from the parent, if applyProcessParameters()
+ // hasn't completely reset it
+ restoreSignalMask();
}
-
- // this is a virtual call, and it base behavior is to do nothing.
- q->setupChildProcess();
// execute the process
- if (!envp) {
+ if (!envp.pointers)
qt_safe_execv(argv[0], argv);
- strcpy(error.function, "execvp");
- } else {
-#if defined (QPROCESS_DEBUG)
- fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
-#endif
+ else
qt_safe_execve(argv[0], argv, envp);
- strcpy(error.function, "execve");
- }
-
- // notify failure
- // don't use strerror or any other routines that may allocate memory, since
- // some buggy libc versions can deadlock on locked mutexes.
-report_errno:
- error.code = errno;
- qt_safe_write(childStartedPipe[1], &error, sizeof(error));
- childStartedPipe[1] = -1;
+ failChildProcess(d, "execve", errno);
}
bool QProcessPrivate::processStarted(QString *errorMessage)
{
+ Q_Q(QProcess);
+
ChildError buf;
- int ret = qt_safe_read(childStartedPipe[0], &buf, sizeof(buf));
+ ssize_t ret = qt_safe_read(childStartedPipe[0], &buf, sizeof(buf));
- if (startupSocketNotifier) {
- startupSocketNotifier->setEnabled(false);
- startupSocketNotifier->deleteLater();
- startupSocketNotifier = nullptr;
+ if (stateNotifier) {
+ stateNotifier->setEnabled(false);
+ stateNotifier->disconnect(q);
}
qt_safe_close(childStartedPipe[0]);
childStartedPipe[0] = -1;
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::processStarted() == %s", i <= 0 ? "true" : "false");
+ qDebug("QProcessPrivate::processStarted() == %s", ret <= 0 ? "true" : "false");
#endif
+ if (ret <= 0) { // process successfully started
+ if (stateNotifier) {
+ QObject::connect(stateNotifier, SIGNAL(activated(QSocketDescriptor)),
+ q, SLOT(_q_processDied()));
+ stateNotifier->setSocket(forkfd);
+ stateNotifier->setEnabled(true);
+ }
+ if (stdoutChannel.notifier)
+ stdoutChannel.notifier->setEnabled(true);
+ if (stderrChannel.notifier)
+ stderrChannel.notifier->setEnabled(true);
+
+ return true;
+ }
+
// did we read an error message?
- if (ret > 0 && errorMessage)
- *errorMessage = QLatin1String(buf.function) + QLatin1String(": ") + qt_error_string(buf.code);
+ if (errorMessage)
+ *errorMessage = startFailureErrorMessage(buf, ret);
- return ret <= 0;
+ return false;
}
qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
@@ -643,7 +1005,7 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint
int save_errno = errno;
qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld",
int(channel - &stdinChannel),
- data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
+ data, QtDebugUtils::toPrintable(data, bytesRead, 16).constData(), maxlen, bytesRead);
errno = save_errno;
#endif
if (bytesRead == -1 && errno == EWOULDBLOCK)
@@ -651,6 +1013,52 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint
return bytesRead;
}
+/*! \reimp
+*/
+qint64 QProcess::writeData(const char *data, qint64 len)
+{
+ Q_D(QProcess);
+
+ if (d->stdinChannel.closed) {
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
+ data, QtDebugUtils::toPrintable(data, len, 16).constData(), len);
+#endif
+ return 0;
+ }
+
+ d->write(data, len);
+ if (d->stdinChannel.notifier)
+ d->stdinChannel.notifier->setEnabled(true);
+
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
+ data, QtDebugUtils::toPrintable(data, len, 16).constData(), len, len);
+#endif
+ return len;
+}
+
+bool QProcessPrivate::_q_canWrite()
+{
+ if (writeBuffer.isEmpty()) {
+ if (stdinChannel.notifier)
+ stdinChannel.notifier->setEnabled(false);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
+#endif
+ return false;
+ }
+
+ const bool writeSucceeded = writeToStdin();
+
+ if (writeBuffer.isEmpty() && stdinChannel.closed)
+ closeWriteChannel();
+ else if (stdinChannel.notifier)
+ stdinChannel.notifier->setEnabled(!writeBuffer.isEmpty());
+
+ return writeSucceeded;
+}
+
bool QProcessPrivate::writeToStdin()
{
const char *data = writeBuffer.readPointer();
@@ -658,8 +1066,8 @@ bool QProcessPrivate::writeToStdin()
qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, bytesToWrite);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::writeToStdin(), write(%p \"%s\", %lld) == %lld",
- data, qt_prettyDebug(data, bytesToWrite, 16).constData(), bytesToWrite, written);
+ qDebug("QProcessPrivate::writeToStdin(), write(%p \"%s\", %lld) == %lld", data,
+ QtDebugUtils::toPrintable(data, bytesToWrite, 16).constData(), bytesToWrite, written);
if (written == -1)
qDebug("QProcessPrivate::writeToStdin(), failed to write (%ls)", qUtf16Printable(qt_error_string(errno)));
#endif
@@ -686,34 +1094,35 @@ bool QProcessPrivate::writeToStdin()
void QProcessPrivate::terminateProcess()
{
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::terminateProcess()");
+ qDebug("QProcessPrivate::terminateProcess() pid=%jd", intmax_t(pid));
#endif
- if (pid)
- ::kill(pid_t(pid), SIGTERM);
+ if (pid > 0)
+ ::kill(pid, SIGTERM);
}
void QProcessPrivate::killProcess()
{
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::killProcess()");
+ qDebug("QProcessPrivate::killProcess() pid=%jd", intmax_t(pid));
#endif
- if (pid)
- ::kill(pid_t(pid), SIGKILL);
+ if (pid > 0)
+ ::kill(pid, SIGKILL);
}
-bool QProcessPrivate::waitForStarted(int msecs)
+bool QProcessPrivate::waitForStarted(const QDeadlineTimer &deadline)
{
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::waitForStarted(%d) waiting for child to start (fd = %d)", msecs,
- childStartedPipe[0]);
+ const qint64 msecs = deadline.remainingTime();
+ qDebug("QProcessPrivate::waitForStarted(%lld) waiting for child to start (fd = %d)",
+ msecs, childStartedPipe[0]);
#endif
pollfd pfd = qt_make_pollfd(childStartedPipe[0], POLLIN);
- if (qt_poll_msecs(&pfd, 1, msecs) == 0) {
+ if (qt_safe_poll(&pfd, 1, deadline) == 0) {
setError(QProcess::Timedout);
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::waitForStarted(%d) == false (timed out)", msecs);
+ qDebug("QProcessPrivate::waitForStarted(%lld) == false (timed out)", msecs);
#endif
return false;
}
@@ -725,20 +1134,16 @@ bool QProcessPrivate::waitForStarted(int msecs)
return startedEmitted;
}
-bool QProcessPrivate::waitForReadyRead(int msecs)
+bool QProcessPrivate::waitForReadyRead(const QDeadlineTimer &deadline)
{
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::waitForReadyRead(%d)", msecs);
+ qDebug("QProcessPrivate::waitForReadyRead(%lld)", deadline.remainingTime());
#endif
- QElapsedTimer stopWatch;
- stopWatch.start();
-
forever {
QProcessPoller poller(*this);
- int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- int ret = poller.poll(timeout);
+ int ret = poller.poll(deadline);
if (ret < 0) {
break;
@@ -748,22 +1153,14 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
return false;
}
- if (qt_pollfd_check(poller.childStartedPipe(), POLLIN)) {
- if (!_q_startupNotification())
- return false;
- }
-
+ // This calls QProcessPrivate::tryReadFromChannel(), which returns true
+ // if we emitted readyRead() signal on the current read channel.
bool readyReadEmitted = false;
- if (qt_pollfd_check(poller.stdoutPipe(), POLLIN)) {
- bool canRead = _q_canReadStandardOutput();
- if (currentReadChannel == QProcess::StandardOutput && canRead)
- readyReadEmitted = true;
- }
- if (qt_pollfd_check(poller.stderrPipe(), POLLIN)) {
- bool canRead = _q_canReadStandardError();
- if (currentReadChannel == QProcess::StandardError && canRead)
- readyReadEmitted = true;
- }
+ if (qt_pollfd_check(poller.stdoutPipe(), POLLIN) && _q_canReadStandardOutput())
+ readyReadEmitted = true;
+ if (qt_pollfd_check(poller.stderrPipe(), POLLIN) && _q_canReadStandardError())
+ readyReadEmitted = true;
+
if (readyReadEmitted)
return true;
@@ -774,28 +1171,26 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
if (processState == QProcess::NotRunning)
return false;
+ // We do this after checking the pipes, so we cannot reach it as long
+ // as there is any data left to be read from an already dead process.
if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
- if (_q_processDied())
- return false;
+ processFinished();
+ return false;
}
}
return false;
}
-bool QProcessPrivate::waitForBytesWritten(int msecs)
+bool QProcessPrivate::waitForBytesWritten(const QDeadlineTimer &deadline)
{
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::waitForBytesWritten(%d)", msecs);
+ qDebug("QProcessPrivate::waitForBytesWritten(%lld)", deadline.remainingTime());
#endif
- QElapsedTimer stopWatch;
- stopWatch.start();
-
while (!writeBuffer.isEmpty()) {
QProcessPoller poller(*this);
- int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- int ret = poller.poll(timeout);
+ int ret = poller.poll(deadline);
if (ret < 0) {
break;
@@ -806,11 +1201,6 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
return false;
}
- if (qt_pollfd_check(poller.childStartedPipe(), POLLIN)) {
- if (!_q_startupNotification())
- return false;
- }
-
if (qt_pollfd_check(poller.stdinPipe(), POLLOUT))
return _q_canWrite();
@@ -825,28 +1215,24 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
return false;
if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
- if (_q_processDied())
- return false;
+ processFinished();
+ return false;
}
}
return false;
}
-bool QProcessPrivate::waitForFinished(int msecs)
+bool QProcessPrivate::waitForFinished(const QDeadlineTimer &deadline)
{
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
+ qDebug("QProcessPrivate::waitForFinished(%lld)", deadline.remainingTime());
#endif
- QElapsedTimer stopWatch;
- stopWatch.start();
-
forever {
QProcessPoller poller(*this);
- int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- int ret = poller.poll(timeout);
+ int ret = poller.poll(deadline);
if (ret < 0) {
break;
@@ -856,10 +1242,6 @@ bool QProcessPrivate::waitForFinished(int msecs)
return false;
}
- if (qt_pollfd_check(poller.childStartedPipe(), POLLIN)) {
- if (!_q_startupNotification())
- return false;
- }
if (qt_pollfd_check(poller.stdinPipe(), POLLOUT))
_q_canWrite();
@@ -874,185 +1256,113 @@ bool QProcessPrivate::waitForFinished(int msecs)
return true;
if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
- if (_q_processDied())
- return true;
+ processFinished();
+ return true;
}
}
return false;
}
-void QProcessPrivate::findExitCode()
-{
-}
-
-bool QProcessPrivate::waitForDeadChild()
+void QProcessPrivate::waitForDeadChild()
{
- if (forkfd == -1)
- return true; // child has already exited
+ Q_ASSERT(forkfd != -1);
// read the process information from our fd
- forkfd_info info;
+ forkfd_info info = {}; // Silence -Wmaybe-uninitialized; Thiago says forkfd_wait cannot fail here
+ // (QTBUG-119081)
int ret;
- EINTR_LOOP(ret, forkfd_wait(forkfd, &info, nullptr));
+ QT_EINTR_LOOP(ret, forkfd_wait(forkfd, &info, nullptr));
exitCode = info.status;
- crashed = info.code != CLD_EXITED;
+ exitStatus = info.code == CLD_EXITED ? QProcess::NormalExit : QProcess::CrashExit;
- delete deathNotifier;
- deathNotifier = nullptr;
+ delete stateNotifier;
+ stateNotifier = nullptr;
- EINTR_LOOP(ret, forkfd_close(forkfd));
+ QT_EINTR_LOOP(ret, forkfd_close(forkfd));
forkfd = -1; // Child is dead, don't try to kill it anymore
#if defined QPROCESS_DEBUG
qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode"
- << exitCode << ", crashed?" << crashed;
+ << exitCode << ", crashed?" << (info.code != CLD_EXITED);
#endif
- return true;
}
bool QProcessPrivate::startDetached(qint64 *pid)
{
- QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory);
-
- // To catch the startup of the child
- int startedPipe[2];
- if (qt_safe_pipe(startedPipe) != 0)
- return false;
- // To communicate the pid of the child
- int pidPipe[2];
- if (qt_safe_pipe(pidPipe) != 0) {
- qt_safe_close(startedPipe[0]);
- qt_safe_close(startedPipe[1]);
+ AutoPipe startedPipe, pidPipe;
+ if (!startedPipe || !pidPipe) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
return false;
}
- if ((stdinChannel.type == Channel::Redirect && !openChannel(stdinChannel))
- || (stdoutChannel.type == Channel::Redirect && !openChannel(stdoutChannel))
- || (stderrChannel.type == Channel::Redirect && !openChannel(stderrChannel))) {
- closeChannel(&stdinChannel);
- closeChannel(&stdoutChannel);
- closeChannel(&stderrChannel);
- qt_safe_close(pidPipe[0]);
- qt_safe_close(pidPipe[1]);
- qt_safe_close(startedPipe[0]);
- qt_safe_close(startedPipe[1]);
+ if (!openChannelsForDetached()) {
+ // openChannel sets the error string
+ closeChannels();
return false;
}
- pid_t childPid = fork();
- if (childPid == 0) {
- struct sigaction noaction;
- memset(&noaction, 0, sizeof(noaction));
- noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, nullptr);
+ // see startProcess() for more information
+ QChildProcess childProcess(this);
+ if (!childProcess.ok()) {
+ Q_ASSERT(processError != QProcess::UnknownError);
+ return false;
+ }
+ childStartedPipe[1] = startedPipe[1]; // for failChildProcess()
+ pid_t childPid = childProcess.doFork([&] {
::setsid();
qt_safe_close(startedPipe[0]);
qt_safe_close(pidPipe[0]);
- pid_t doubleForkPid = fork();
- if (doubleForkPid == 0) {
- qt_safe_close(pidPipe[1]);
-
- // copy the stdin socket if asked to (without closing on exec)
- if (stdinChannel.type == Channel::Redirect)
- qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0);
-
- // copy the stdout and stderr if asked to
- if (stdoutChannel.type == Channel::Redirect)
- qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0);
- if (stderrChannel.type == Channel::Redirect)
- qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0);
-
- if (!encodedWorkingDirectory.isEmpty()) {
- if (QT_CHDIR(encodedWorkingDirectory.constData()) == -1)
- qWarning("QProcessPrivate::startDetached: failed to chdir to %s", encodedWorkingDirectory.constData());
- }
-
- char **argv = new char *[arguments.size() + 2];
- for (int i = 0; i < arguments.size(); ++i)
- argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
- argv[arguments.size() + 1] = nullptr;
+ pid_t doubleForkPid;
+ if (childProcess.startChild(&doubleForkPid) == -1)
+ failChildProcess(this, "fork", errno);
- // Duplicate the environment.
- int envc = 0;
- char **envp = nullptr;
- if (environment.d.constData()) {
- envp = _q_dupEnvironment(environment.d.constData()->vars, &envc);
- }
-
- QByteArray tmp;
- if (!program.contains(QLatin1Char('/'))) {
- const QString &exeFilePath = QStandardPaths::findExecutable(program);
- if (!exeFilePath.isEmpty())
- tmp = QFile::encodeName(exeFilePath);
- }
- if (tmp.isEmpty())
- tmp = QFile::encodeName(program);
- argv[0] = tmp.data();
+ // success
+ qt_safe_write(pidPipe[1], &doubleForkPid, sizeof(pid_t));
+ return 0;
+ });
+ childStartedPipe[1] = -1;
- if (envp)
- qt_safe_execve(argv[0], argv, envp);
- else
- qt_safe_execv(argv[0], argv);
-
- struct sigaction noaction;
- memset(&noaction, 0, sizeof(noaction));
- noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, nullptr);
-
- // '\1' means execv failed
- char c = '\1';
- qt_safe_write(startedPipe[1], &c, 1);
- qt_safe_close(startedPipe[1]);
- ::_exit(1);
- } else if (doubleForkPid == -1) {
- struct sigaction noaction;
- memset(&noaction, 0, sizeof(noaction));
- noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, nullptr);
-
- // '\2' means internal error
- char c = '\2';
- qt_safe_write(startedPipe[1], &c, 1);
- }
+ int savedErrno = errno;
+ closeChannels();
- qt_safe_close(startedPipe[1]);
- qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t));
- if (QT_CHDIR("/") == -1)
- qWarning("QProcessPrivate::startDetached: failed to chdir to /");
- ::_exit(1);
+ if (childPid == -1) {
+ setErrorAndEmit(QProcess::FailedToStart, "fork: "_L1 + qt_error_string(savedErrno));
+ return false;
}
- closeChannel(&stdinChannel);
- closeChannel(&stdoutChannel);
- closeChannel(&stderrChannel);
- qt_safe_close(startedPipe[1]);
+ // close the writing ends of the pipes so we can properly get EOFs
qt_safe_close(pidPipe[1]);
+ qt_safe_close(startedPipe[1]);
+ pidPipe[1] = startedPipe[1] = -1;
- if (childPid == -1) {
- qt_safe_close(startedPipe[0]);
- qt_safe_close(pidPipe[0]);
- return false;
- }
+ // This read() will block until we're cleared to proceed. If it returns 0
+ // (EOF), it means the direct child has exited and the grandchild
+ // successfully execve()'d the target process. If it returns any positive
+ // result, it means one of the two children wrote an error result. Negative
+ // values should not happen.
+ ChildError childStatus;
+ ssize_t startResult = qt_safe_read(startedPipe[0], &childStatus, sizeof(childStatus));
- char reply = '\0';
- int startResult = qt_safe_read(startedPipe[0], &reply, 1);
+ // reap the intermediate child
int result;
- qt_safe_close(startedPipe[0]);
qt_safe_waitpid(childPid, &result, 0);
- bool success = (startResult != -1 && reply == '\0');
+
+ bool success = (startResult == 0); // nothing written -> no error
if (success && pid) {
- pid_t actualPid = 0;
- if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) {
- *pid = actualPid;
- } else {
- *pid = 0;
- }
+ pid_t actualPid;
+ if (qt_safe_read(pidPipe[0], &actualPid, sizeof(pid_t)) != sizeof(pid_t))
+ actualPid = 0; // this shouldn't happen!
+ *pid = actualPid;
+ } else if (!success) {
+ if (pid)
+ *pid = -1;
+ setErrorAndEmit(QProcess::FailedToStart,
+ startFailureErrorMessage(childStatus, startResult));
}
- qt_safe_close(pidPipe[0]);
return success;
}
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 148c6378c6..e64b133815 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -1,44 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QPROCESS_DEBUG
+#include <qdebug.h>
+#include <private/qdebug_p.h>
+
#include "qprocess.h"
#include "qprocess_p.h"
#include "qwindowspipereader_p.h"
@@ -46,13 +13,12 @@
#include <qdatetime.h>
#include <qdir.h>
-#include <qelapsedtimer.h>
#include <qfileinfo.h>
#include <qrandom.h>
#include <qwineventnotifier.h>
+#include <qscopedvaluerollback.h>
#include <private/qsystemlibrary_p.h>
#include <private/qthread_p.h>
-#include <qdebug.h>
#include "private/qfsfileengine_p.h" // for longFileName
@@ -62,6 +28,10 @@
QT_BEGIN_NAMESPACE
+constexpr UINT KillProcessExitCode = 0xf291;
+
+using namespace Qt::StringLiterals;
+
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
@@ -86,14 +56,56 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
#if QT_CONFIG(process)
-static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
+namespace {
+struct QProcessPoller
+{
+ QProcessPoller(const QProcessPrivate &proc);
+
+ int poll(const QDeadlineTimer &deadline);
+
+ enum { maxHandles = 4 };
+ HANDLE handles[maxHandles];
+ DWORD handleCount = 0;
+};
+
+QProcessPoller::QProcessPoller(const QProcessPrivate &proc)
+{
+ if (proc.stdinChannel.writer)
+ handles[handleCount++] = proc.stdinChannel.writer->syncEvent();
+ if (proc.stdoutChannel.reader)
+ handles[handleCount++] = proc.stdoutChannel.reader->syncEvent();
+ if (proc.stderrChannel.reader)
+ handles[handleCount++] = proc.stderrChannel.reader->syncEvent();
+
+ handles[handleCount++] = proc.pid->hProcess;
+}
+
+int QProcessPoller::poll(const QDeadlineTimer &deadline)
+{
+ DWORD waitRet;
+
+ do {
+ waitRet = WaitForMultipleObjectsEx(handleCount, handles, FALSE,
+ deadline.remainingTime(), TRUE);
+ } while (waitRet == WAIT_IO_COMPLETION);
+
+ if (waitRet - WAIT_OBJECT_0 < handleCount)
+ return 1;
+
+ return (waitRet == WAIT_TIMEOUT) ? 0 : -1;
+}
+} // anonymous namespace
+
+static bool qt_create_pipe(Q_PIPE *pipe, bool isInputPipe, BOOL defInheritFlag)
{
// Anomymous pipes do not support asynchronous I/O. Thus we
// create named pipes for redirecting stdout, stderr and stdin.
// The write handle must be non-inheritable for input pipes.
// The read handle must be non-inheritable for output pipes.
- SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), 0, false };
+ // When one process pipes to another (setStandardOutputProcess() was called),
+ // both handles must be inheritable (defInheritFlag == TRUE).
+ SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), 0, defInheritFlag };
HANDLE hServer;
wchar_t pipeName[256];
@@ -128,7 +140,8 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
DWORD dwError = GetLastError();
if (dwError != ERROR_PIPE_BUSY || !--attempts) {
qErrnoWarning(dwError, "QProcess: CreateNamedPipe failed.");
- return;
+ SetLastError(dwError);
+ return false;
}
}
@@ -142,9 +155,11 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
FILE_FLAG_OVERLAPPED,
NULL);
if (hClient == INVALID_HANDLE_VALUE) {
+ DWORD dwError = GetLastError();
qErrnoWarning("QProcess: CreateFile failed.");
CloseHandle(hServer);
- return;
+ SetLastError(dwError);
+ return false;
}
// Wait until connection is in place.
@@ -160,11 +175,13 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
WaitForSingleObject(overlapped.hEvent, INFINITE);
break;
default:
+ dwError = GetLastError();
qErrnoWarning(dwError, "QProcess: ConnectNamedPipe failed.");
CloseHandle(overlapped.hEvent);
CloseHandle(hClient);
CloseHandle(hServer);
- return;
+ SetLastError(dwError);
+ return false;
}
}
CloseHandle(overlapped.hEvent);
@@ -176,73 +193,47 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
pipe[0] = hServer;
pipe[1] = hClient;
}
-}
-
-static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle)
-{
- pipe[0] = INVALID_Q_PIPE;
- HANDLE hStdWriteChannel = GetStdHandle(nStdHandle);
- HANDLE hCurrentProcess = GetCurrentProcess();
- DuplicateHandle(hCurrentProcess, hStdWriteChannel, hCurrentProcess,
- &pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS);
+ return true;
}
/*
Create the pipes to a QProcessPrivate::Channel.
-
- This function must be called in order: stdin, stdout, stderr
*/
bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
- if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) {
- return DuplicateHandle(GetCurrentProcess(), stdoutChannel.pipe[1], GetCurrentProcess(),
- &stderrChannel.pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS);
- }
-
switch (channel.type) {
- case Channel::Normal:
+ case Channel::Normal: {
// we're piping this channel to our own process
if (&channel == &stdinChannel) {
- if (inputChannelMode != QProcess::ForwardedInputChannel) {
- qt_create_pipe(channel.pipe, true);
- } else {
- channel.pipe[1] = INVALID_Q_PIPE;
- HANDLE hStdReadChannel = GetStdHandle(STD_INPUT_HANDLE);
- HANDLE hCurrentProcess = GetCurrentProcess();
- DuplicateHandle(hCurrentProcess, hStdReadChannel, hCurrentProcess,
- &channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS);
+ if (!qt_create_pipe(channel.pipe, true, FALSE)) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
+ return false;
}
- } else {
- if (&channel == &stdoutChannel) {
- if (processChannelMode != QProcess::ForwardedChannels
- && processChannelMode != QProcess::ForwardedOutputChannel) {
- if (!stdoutChannel.reader) {
- stdoutChannel.reader = new QWindowsPipeReader(q);
- q->connect(stdoutChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
- }
- } else {
- duplicateStdWriteChannel(channel.pipe, STD_OUTPUT_HANDLE);
- }
- } else /* if (&channel == &stderrChannel) */ {
- if (processChannelMode != QProcess::ForwardedChannels
- && processChannelMode != QProcess::ForwardedErrorChannel) {
- if (!stderrChannel.reader) {
- stderrChannel.reader = new QWindowsPipeReader(q);
- q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
- }
- } else {
- duplicateStdWriteChannel(channel.pipe, STD_ERROR_HANDLE);
- }
+ return true;
+ }
+
+ if (&channel == &stdoutChannel) {
+ if (!stdoutChannel.reader) {
+ stdoutChannel.reader = new QWindowsPipeReader(q);
+ q->connect(stdoutChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
}
- if (channel.reader) {
- qt_create_pipe(channel.pipe, false);
- channel.reader->setHandle(channel.pipe[0]);
- channel.reader->startAsyncRead();
+ } else /* if (&channel == &stderrChannel) */ {
+ if (!stderrChannel.reader) {
+ stderrChannel.reader = new QWindowsPipeReader(q);
+ q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
}
}
+ if (!qt_create_pipe(channel.pipe, false, FALSE)) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
+ return false;
+ }
+
+ channel.reader->setHandle(channel.pipe[0]);
+ channel.reader->startAsyncRead();
return true;
+ }
case Channel::Redirect: {
// we're redirecting the channel to/from a file
SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
@@ -286,7 +277,6 @@ bool QProcessPrivate::openChannel(Channel &channel)
setErrorAndEmit(QProcess::FailedToStart,
QProcess::tr("Could not open output redirection for writing"));
}
- cleanup();
return false;
}
case Channel::PipeSource: {
@@ -297,22 +287,17 @@ bool QProcessPrivate::openChannel(Channel &channel)
if (source->pipe[1] != INVALID_Q_PIPE) {
// already constructed by the sink
- // make it inheritable
- HANDLE tmpHandle = source->pipe[1];
- if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,
- GetCurrentProcess(), &source->pipe[1],
- 0, TRUE, DUPLICATE_SAME_ACCESS)) {
- return false;
- }
-
- CloseHandle(tmpHandle);
return true;
}
Q_ASSERT(source == &stdoutChannel);
Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
- qt_create_pipe(source->pipe, /* in = */ false); // source is stdout
+ if (!qt_create_pipe(source->pipe, /* in = */ false, TRUE)) { // source is stdout
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
+ return false;
+ }
+
sink->pipe[0] = source->pipe[0];
source->pipe[0] = INVALID_Q_PIPE;
@@ -325,21 +310,16 @@ bool QProcessPrivate::openChannel(Channel &channel)
if (sink->pipe[0] != INVALID_Q_PIPE) {
// already constructed by the source
- // make it inheritable
- HANDLE tmpHandle = sink->pipe[0];
- if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,
- GetCurrentProcess(), &sink->pipe[0],
- 0, TRUE, DUPLICATE_SAME_ACCESS)) {
- return false;
- }
-
- CloseHandle(tmpHandle);
return true;
}
Q_ASSERT(sink == &stdinChannel);
Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
- qt_create_pipe(sink->pipe, /* in = */ true); // sink is stdin
+ if (!qt_create_pipe(sink->pipe, /* in = */ true, TRUE)) { // sink is stdin
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
+ return false;
+ }
+
source->pipe[1] = sink->pipe[1];
sink->pipe[1] = INVALID_Q_PIPE;
@@ -361,23 +341,31 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
}
}
-template <class T>
-void deleteWorker(T *&worker)
+void QProcessPrivate::closeChannel(Channel *channel)
{
- if (!worker)
- return;
- worker->stop();
- worker->deleteLater();
- worker = nullptr;
+ if (channel == &stdinChannel) {
+ delete channel->writer;
+ channel->writer = nullptr;
+ } else {
+ delete channel->reader;
+ channel->reader = nullptr;
+ }
+ destroyPipe(channel->pipe);
}
-void QProcessPrivate::closeChannel(Channel *channel)
+void QProcessPrivate::cleanup()
{
- if (channel == &stdinChannel)
- deleteWorker(channel->writer);
- else
- deleteWorker(channel->reader);
- destroyPipe(channel->pipe);
+ q_func()->setProcessState(QProcess::NotRunning);
+
+ closeChannels();
+ delete processFinishedNotifier;
+ processFinishedNotifier = nullptr;
+ if (pid) {
+ CloseHandle(pid->hThread);
+ CloseHandle(pid->hProcess);
+ delete pid;
+ pid = nullptr;
+ }
}
static QString qt_create_commandline(const QString &program, const QStringList &arguments,
@@ -386,44 +374,44 @@ static QString qt_create_commandline(const QString &program, const QStringList &
QString args;
if (!program.isEmpty()) {
QString programName = program;
- if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1Char(' ')))
- programName = QLatin1Char('\"') + programName + QLatin1Char('\"');
- programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ if (!programName.startsWith(u'\"') && !programName.endsWith(u'\"') && programName.contains(u' '))
+ programName = u'\"' + programName + u'\"';
+ programName.replace(u'/', u'\\');
- // add the prgram as the first arg ... it works better
- args = programName + QLatin1Char(' ');
+ // add the program as the first arg ... it works better
+ args = programName + u' ';
}
- for (int i=0; i<arguments.size(); ++i) {
+ for (qsizetype i = 0; i < arguments.size(); ++i) {
QString tmp = arguments.at(i);
// Quotes are escaped and their preceding backslashes are doubled.
- int index = tmp.indexOf(QLatin1Char('"'));
+ qsizetype index = tmp.indexOf(u'"');
while (index >= 0) {
// Escape quote
- tmp.insert(index++, QLatin1Char('\\'));
+ tmp.insert(index++, u'\\');
// Double preceding backslashes (ignoring the one we just inserted)
- for (int i = index - 2 ; i >= 0 && tmp.at(i) == QLatin1Char('\\') ; --i) {
- tmp.insert(i, QLatin1Char('\\'));
+ for (qsizetype i = index - 2 ; i >= 0 && tmp.at(i) == u'\\' ; --i) {
+ tmp.insert(i, u'\\');
index++;
}
- index = tmp.indexOf(QLatin1Char('"'), index + 1);
+ index = tmp.indexOf(u'"', index + 1);
}
- if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
+ if (tmp.isEmpty() || tmp.contains(u' ') || tmp.contains(u'\t')) {
// The argument must not end with a \ since this would be interpreted
// as escaping the quote -- rather put the \ behind the quote: e.g.
// rather use "foo"\ than "foo\"
- int i = tmp.length();
- while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\'))
+ qsizetype i = tmp.length();
+ while (i > 0 && tmp.at(i - 1) == u'\\')
--i;
- tmp.insert(i, QLatin1Char('"'));
- tmp.prepend(QLatin1Char('"'));
+ tmp.insert(i, u'"');
+ tmp.prepend(u'"');
}
- args += QLatin1Char(' ') + tmp;
+ args += u' ' + tmp;
}
if (!nativeArguments.isEmpty()) {
if (!args.isEmpty())
- args += QLatin1Char(' ');
+ args += u' ';
args += nativeArguments;
}
@@ -433,63 +421,89 @@ static QString qt_create_commandline(const QString &program, const QStringList &
static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Map &environment)
{
QByteArray envlist;
- if (!environment.isEmpty()) {
- QProcessEnvironmentPrivate::Map copy = environment;
-
- // add PATH if necessary (for DLL loading)
- QProcessEnvironmentPrivate::Key pathKey(QLatin1String("PATH"));
- if (!copy.contains(pathKey)) {
- QByteArray path = qgetenv("PATH");
- if (!path.isEmpty())
- copy.insert(pathKey, QString::fromLocal8Bit(path));
- }
+ QProcessEnvironmentPrivate::Map copy = environment;
- // add systemroot if needed
- QProcessEnvironmentPrivate::Key rootKey(QLatin1String("SystemRoot"));
- if (!copy.contains(rootKey)) {
- QByteArray systemRoot = qgetenv("SystemRoot");
- if (!systemRoot.isEmpty())
- copy.insert(rootKey, QString::fromLocal8Bit(systemRoot));
- }
+ // add PATH if necessary (for DLL loading)
+ QProcessEnvironmentPrivate::Key pathKey("PATH"_L1);
+ if (!copy.contains(pathKey)) {
+ QByteArray path = qgetenv("PATH");
+ if (!path.isEmpty())
+ copy.insert(pathKey, QString::fromLocal8Bit(path));
+ }
- int pos = 0;
- auto it = copy.constBegin();
- const auto end = copy.constEnd();
+ // add systemroot if needed
+ QProcessEnvironmentPrivate::Key rootKey("SystemRoot"_L1);
+ if (!copy.contains(rootKey)) {
+ QByteArray systemRoot = qgetenv("SystemRoot");
+ if (!systemRoot.isEmpty())
+ copy.insert(rootKey, QString::fromLocal8Bit(systemRoot));
+ }
- static const wchar_t equal = L'=';
- static const wchar_t nul = L'\0';
+ qsizetype pos = 0;
+ auto it = copy.constBegin();
+ const auto end = copy.constEnd();
- for ( ; it != end; ++it) {
- uint tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2);
- // ignore empty strings
- if (tmpSize == sizeof(wchar_t) * 2)
- continue;
- envlist.resize(envlist.size() + tmpSize);
+ static const wchar_t equal = L'=';
+ static const wchar_t nul = L'\0';
- tmpSize = it.key().length() * sizeof(wchar_t);
- memcpy(envlist.data()+pos, it.key().utf16(), tmpSize);
- pos += tmpSize;
+ for (; it != end; ++it) {
+ qsizetype tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2);
+ // ignore empty strings
+ if (tmpSize == sizeof(wchar_t) * 2)
+ continue;
+ envlist.resize(envlist.size() + tmpSize);
- memcpy(envlist.data()+pos, &equal, sizeof(wchar_t));
- pos += sizeof(wchar_t);
+ tmpSize = it.key().length() * sizeof(wchar_t);
+ memcpy(envlist.data() + pos, it.key().data(), tmpSize);
+ pos += tmpSize;
- tmpSize = it.value().length() * sizeof(wchar_t);
- memcpy(envlist.data()+pos, it.value().utf16(), tmpSize);
- pos += tmpSize;
+ memcpy(envlist.data() + pos, &equal, sizeof(wchar_t));
+ pos += sizeof(wchar_t);
- memcpy(envlist.data()+pos, &nul, sizeof(wchar_t));
- pos += sizeof(wchar_t);
- }
- // add the 2 terminating 0 (actually 4, just to be on the safe side)
- envlist.resize( envlist.size()+4 );
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
+ tmpSize = it.value().length() * sizeof(wchar_t);
+ memcpy(envlist.data() + pos, it.value().data(), tmpSize);
+ pos += tmpSize;
+
+ memcpy(envlist.data() + pos, &nul, sizeof(wchar_t));
+ pos += sizeof(wchar_t);
}
+ // add the 2 terminating 0 (actually 4, just to be on the safe side)
+ envlist.resize(envlist.size() + 4);
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+
return envlist;
}
+static Q_PIPE pipeOrStdHandle(Q_PIPE pipe, DWORD handleNumber)
+{
+ return pipe != INVALID_Q_PIPE ? pipe : GetStdHandle(handleNumber);
+}
+
+STARTUPINFOW QProcessPrivate::createStartupInfo()
+{
+ Q_PIPE stdinPipe = pipeOrStdHandle(stdinChannel.pipe[0], STD_INPUT_HANDLE);
+ Q_PIPE stdoutPipe = pipeOrStdHandle(stdoutChannel.pipe[1], STD_OUTPUT_HANDLE);
+ Q_PIPE stderrPipe = stderrChannel.pipe[1];
+ if (stderrPipe == INVALID_Q_PIPE) {
+ stderrPipe = (processChannelMode == QProcess::MergedChannels)
+ ? stdoutPipe
+ : GetStdHandle(STD_ERROR_HANDLE);
+ }
+
+ return STARTUPINFOW{
+ sizeof(STARTUPINFOW), 0, 0, 0,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ 0, 0, 0,
+ STARTF_USESTDHANDLES,
+ 0, 0, 0,
+ stdinPipe, stdoutPipe, stderrPipe
+ };
+}
+
bool QProcessPrivate::callCreateProcess(QProcess::CreateProcessArguments *cpargs)
{
if (modifyCreateProcessArgs)
@@ -518,32 +532,21 @@ void QProcessPrivate::startProcess()
{
Q_Q(QProcess);
- bool success = false;
-
- if (pid) {
- CloseHandle(pid->hThread);
- CloseHandle(pid->hProcess);
- delete pid;
- pid = 0;
- }
pid = new PROCESS_INFORMATION;
memset(pid, 0, sizeof(PROCESS_INFORMATION));
q->setProcessState(QProcess::Starting);
- if (!openChannel(stdinChannel) ||
- !openChannel(stdoutChannel) ||
- !openChannel(stderrChannel)) {
- QString errorString = QProcess::tr("Process failed to start: %1").arg(qt_error_string());
+ if (!openChannels()) {
+ // openChannel sets the error string
+ Q_ASSERT(!errorString.isEmpty());
cleanup();
- setErrorAndEmit(QProcess::FailedToStart, errorString);
- q->setProcessState(QProcess::NotRunning);
return;
}
const QString args = qt_create_commandline(program, arguments, nativeArguments);
QByteArray envlist;
- if (environment.d.constData())
+ if (!environment.inheritsFromParent())
envlist = qt_create_environment(environment.d.constData()->vars);
#if defined QPROCESS_DEBUG
@@ -560,39 +563,31 @@ void QProcessPrivate::startProcess()
// create new console windows (behavior consistent with UNIX).
DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW);
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
- STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- 0, 0, 0,
- STARTF_USESTDHANDLES,
- 0, 0, 0,
- stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1]
- };
-
+ STARTUPINFOW startupInfo = createStartupInfo();
const QString nativeWorkingDirectory = QDir::toNativeSeparators(workingDirectory);
QProcess::CreateProcessArguments cpargs = {
nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())),
nullptr, nullptr, true, dwCreationFlags,
- environment.isEmpty() ? nullptr : envlist.data(),
+ environment.inheritsFromParent() ? nullptr : envlist.data(),
nativeWorkingDirectory.isEmpty()
? nullptr : reinterpret_cast<const wchar_t *>(nativeWorkingDirectory.utf16()),
&startupInfo, pid
};
- success = callCreateProcess(&cpargs);
- QString errorString;
- if (!success) {
+ if (!callCreateProcess(&cpargs)) {
// Capture the error string before we do CloseHandle below
- errorString = QProcess::tr("Process failed to start: %1").arg(qt_error_string());
- }
-
- if (!success) {
+ QString errorString = QProcess::tr("Process failed to start: %1").arg(qt_error_string());
cleanup();
setErrorAndEmit(QProcess::FailedToStart, errorString);
- q->setProcessState(QProcess::NotRunning);
return;
}
+ // The pipe writer may have already been created before we had
+ // the pipe handle, specifically if the user wrote data from the
+ // stateChanged() slot.
+ if (stdinChannel.writer)
+ stdinChannel.writer->setHandle(stdinChannel.pipe[1]);
+
q->setProcessState(QProcess::Running);
// User can call kill()/terminate() from the stateChanged() slot
// so check before proceeding
@@ -654,10 +649,10 @@ void QProcessPrivate::terminateProcess()
void QProcessPrivate::killProcess()
{
if (pid)
- TerminateProcess(pid->hProcess, 0xf291);
+ TerminateProcess(pid->hProcess, KillProcessExitCode);
}
-bool QProcessPrivate::waitForStarted(int)
+bool QProcessPrivate::waitForStarted(const QDeadlineTimer &)
{
if (processStarted())
return true;
@@ -671,180 +666,180 @@ bool QProcessPrivate::waitForStarted(int)
bool QProcessPrivate::drainOutputPipes()
{
- if (!stdoutChannel.reader && !stderrChannel.reader)
- return false;
+ bool readyReadEmitted = false;
- bool someReadyReadEmitted = false;
- forever {
- bool readyReadEmitted = false;
- bool readOperationActive = false;
- if (stdoutChannel.reader) {
- readyReadEmitted |= stdoutChannel.reader->waitForReadyRead(0);
- readOperationActive = stdoutChannel.reader && stdoutChannel.reader->isReadOperationActive();
- }
- if (stderrChannel.reader) {
- readyReadEmitted |= stderrChannel.reader->waitForReadyRead(0);
- readOperationActive |= stderrChannel.reader && stderrChannel.reader->isReadOperationActive();
- }
- someReadyReadEmitted |= readyReadEmitted;
- if (!readOperationActive || !readyReadEmitted)
- break;
- QThread::yieldCurrentThread();
+ if (stdoutChannel.reader) {
+ stdoutChannel.reader->drainAndStop();
+ readyReadEmitted = _q_canReadStandardOutput();
+ }
+ if (stderrChannel.reader) {
+ stderrChannel.reader->drainAndStop();
+ readyReadEmitted |= _q_canReadStandardError();
}
- return someReadyReadEmitted;
+ return readyReadEmitted;
}
-bool QProcessPrivate::waitForReadyRead(int msecs)
+bool QProcessPrivate::waitForReadyRead(const QDeadlineTimer &deadline)
{
- QIncrementalSleepTimer timer(msecs);
-
forever {
- if (!writeBuffer.isEmpty() && !_q_canWrite())
+ QProcessPoller poller(*this);
+ int ret = poller.poll(deadline);
+ if (ret < 0)
return false;
- if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
- timer.resetIncrements();
+ if (ret == 0)
+ break;
+
+ if (stdinChannel.writer)
+ stdinChannel.writer->checkForWrite();
- if ((stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
- || (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)))
+ if ((stdoutChannel.reader && stdoutChannel.reader->checkForReadyRead())
+ || (stderrChannel.reader && stderrChannel.reader->checkForReadyRead()))
return true;
if (!pid)
return false;
- if (WaitForSingleObjectEx(pid->hProcess, 0, false) == WAIT_OBJECT_0) {
+
+ if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
bool readyReadEmitted = drainOutputPipes();
if (pid)
- _q_processDied();
+ processFinished();
return readyReadEmitted;
}
-
- Sleep(timer.nextSleepTime());
- if (timer.hasTimedOut())
- break;
}
setError(QProcess::Timedout);
return false;
}
-bool QProcessPrivate::waitForBytesWritten(int msecs)
+bool QProcessPrivate::waitForBytesWritten(const QDeadlineTimer &deadline)
{
- QIncrementalSleepTimer timer(msecs);
-
forever {
- bool pendingDataInPipe = stdinChannel.writer && stdinChannel.writer->bytesToWrite();
-
- // If we don't have pending data, and our write buffer is
- // empty, we fail.
- if (!pendingDataInPipe && writeBuffer.isEmpty())
+ // At entry into the loop the pipe writer's buffer can be empty to
+ // start with, in which case we fail immediately. Also, if the input
+ // pipe goes down somewhere in the code below, we avoid waiting for
+ // a full timeout.
+ if (!stdinChannel.writer || !stdinChannel.writer->isWriteOperationActive())
return false;
- // If we don't have pending data and we do have data in our
- // write buffer, try to flush that data over to the pipe
- // writer. Fail on error.
- if (!pendingDataInPipe) {
- if (!_q_canWrite())
- return false;
- }
+ QProcessPoller poller(*this);
+ int ret = poller.poll(deadline);
+ if (ret < 0)
+ return false;
+ if (ret == 0)
+ break;
- // Wait for the pipe writer to acknowledge that it has
- // written. This will succeed if either the pipe writer has
- // already written the data, or if it manages to write data
- // within the given timeout. If the write buffer was non-empty
- // and the stdinChannel.writer is now dead, that means _q_canWrite()
- // destroyed the writer after it successfully wrote the last
- // batch.
- if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0))
+ if (stdinChannel.writer->checkForWrite())
return true;
// If we wouldn't write anything, check if we can read stdout.
- if (stdoutChannel.pipe[0] != INVALID_Q_PIPE
- && bytesAvailableInChannel(&stdoutChannel) != 0) {
- tryReadFromChannel(&stdoutChannel);
- timer.resetIncrements();
- }
+ if (stdoutChannel.reader)
+ stdoutChannel.reader->checkForReadyRead();
// Check if we can read stderr.
- if (stderrChannel.pipe[0] != INVALID_Q_PIPE
- && bytesAvailableInChannel(&stderrChannel) != 0) {
- tryReadFromChannel(&stderrChannel);
- timer.resetIncrements();
- }
+ if (stderrChannel.reader)
+ stderrChannel.reader->checkForReadyRead();
// Check if the process died while reading.
if (!pid)
return false;
- // Wait for the process to signal any change in its state,
- // such as incoming data, or if the process died.
- if (WaitForSingleObjectEx(pid->hProcess, 0, false) == WAIT_OBJECT_0) {
- _q_processDied();
+ // Check if the process is signaling completion.
+ if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
+ drainOutputPipes();
+ if (pid)
+ processFinished();
return false;
}
-
- // Only wait for as long as we've been asked.
- if (timer.hasTimedOut())
- break;
}
setError(QProcess::Timedout);
return false;
}
-bool QProcessPrivate::waitForFinished(int msecs)
+bool QProcessPrivate::waitForFinished(const QDeadlineTimer &deadline)
{
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
+ qDebug("QProcessPrivate::waitForFinished(%lld)", deadline.remainingTime());
#endif
- QIncrementalSleepTimer timer(msecs);
-
forever {
- if (!writeBuffer.isEmpty() && !_q_canWrite())
+ QProcessPoller poller(*this);
+ int ret = poller.poll(deadline);
+ if (ret < 0)
return false;
- if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
- timer.resetIncrements();
- if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
- timer.resetIncrements();
- if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))
- timer.resetIncrements();
-
- if (!pid) {
- drainOutputPipes();
+ if (ret == 0)
+ break;
+
+ if (stdinChannel.writer)
+ stdinChannel.writer->checkForWrite();
+ if (stdoutChannel.reader)
+ stdoutChannel.reader->checkForReadyRead();
+ if (stderrChannel.reader)
+ stderrChannel.reader->checkForReadyRead();
+
+ if (!pid)
return true;
- }
- if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
+ if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
drainOutputPipes();
if (pid)
- _q_processDied();
+ processFinished();
return true;
}
-
- if (timer.hasTimedOut())
- break;
}
setError(QProcess::Timedout);
return false;
}
-
void QProcessPrivate::findExitCode()
{
DWORD theExitCode;
Q_ASSERT(pid);
if (GetExitCodeProcess(pid->hProcess, &theExitCode)) {
exitCode = theExitCode;
- crashed = (exitCode == 0xf291 // our magic number, see killProcess
- || (theExitCode >= 0x80000000 && theExitCode < 0xD0000000));
+ if (exitCode == KillProcessExitCode
+ || (theExitCode >= 0x80000000 && theExitCode < 0xD0000000))
+ exitStatus = QProcess::CrashExit;
+ else
+ exitStatus = QProcess::NormalExit;
}
}
-void QProcessPrivate::flushPipeWriter()
+/*! \reimp
+ \internal
+*/
+qint64 QProcess::writeData(const char *data, qint64 len)
{
- if (stdinChannel.writer && stdinChannel.writer->bytesToWrite() > 0)
- stdinChannel.writer->waitForWrite(ULONG_MAX);
+ Q_D(QProcess);
+
+ if (d->stdinChannel.closed) {
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
+ data, QtDebugUtils::toPrintable(data, len, 16).constData(), len);
+#endif
+ return 0;
+ }
+
+ if (!d->stdinChannel.writer) {
+ d->stdinChannel.writer = new QWindowsPipeWriter(d->stdinChannel.pipe[1], this);
+ QObjectPrivate::connect(d->stdinChannel.writer, &QWindowsPipeWriter::bytesWritten,
+ d, &QProcessPrivate::_q_bytesWritten);
+ QObjectPrivate::connect(d->stdinChannel.writer, &QWindowsPipeWriter::writeFailed,
+ d, &QProcessPrivate::_q_writeFailed);
+ }
+
+ if (d->isWriteChunkCached(data, len))
+ d->stdinChannel.writer->write(*(d->currentWriteChunk));
+ else
+ d->stdinChannel.writer->write(data, len);
+
+#if defined QPROCESS_DEBUG
+ qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
+ data, QtDebugUtils::toPrintable(data, len, 16).constData(), len, len);
+#endif
+ return len;
}
qint64 QProcessPrivate::pipeWriterBytesToWrite() const
@@ -852,23 +847,22 @@ qint64 QProcessPrivate::pipeWriterBytesToWrite() const
return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
}
-bool QProcessPrivate::writeToStdin()
+void QProcessPrivate::_q_bytesWritten(qint64 bytes)
{
Q_Q(QProcess);
- if (!stdinChannel.writer) {
- stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
- QObject::connect(stdinChannel.writer, &QWindowsPipeWriter::bytesWritten,
- q, &QProcess::bytesWritten);
- QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite,
- this, &QProcessPrivate::_q_canWrite);
- } else {
- if (stdinChannel.writer->isWriteOperationActive())
- return true;
+ if (!emittedBytesWritten) {
+ QScopedValueRollback<bool> guard(emittedBytesWritten, true);
+ emit q->bytesWritten(bytes);
}
+ if (stdinChannel.closed && pipeWriterBytesToWrite() == 0)
+ closeWriteChannel();
+}
- stdinChannel.writer->write(writeBuffer.read());
- return true;
+void QProcessPrivate::_q_writeFailed()
+{
+ closeWriteChannel();
+ setErrorAndEmit(QProcess::WriteError);
}
// Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails
@@ -877,14 +871,6 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList &
const QString &nativeArguments,
const QString &workingDir, qint64 *pid)
{
- typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *);
-
- static const ShellExecuteExType shellExecuteEx = // XP ServicePack 1 onwards.
- reinterpret_cast<ShellExecuteExType>(QSystemLibrary::resolve(QLatin1String("shell32"),
- "ShellExecuteExW"));
- if (!shellExecuteEx)
- return false;
-
const QString args = qt_create_commandline(QString(), // needs arguments only
arguments, nativeArguments);
SHELLEXECUTEINFOW shellExecuteExInfo;
@@ -901,7 +887,7 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList &
shellExecuteExInfo.lpDirectory = reinterpret_cast<LPCWSTR>(workingDir.utf16());
shellExecuteExInfo.nShow = SW_SHOWNORMAL;
- if (!shellExecuteEx(&shellExecuteExInfo))
+ if (!ShellExecuteExW(&shellExecuteExInfo))
return false;
if (pid)
*pid = qint64(GetProcessId(shellExecuteExInfo.hProcess));
@@ -909,21 +895,13 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList &
return true;
}
-static Q_PIPE pipeOrStdHandle(Q_PIPE pipe, DWORD handleNumber)
-{
- return pipe != INVALID_Q_PIPE ? pipe : GetStdHandle(handleNumber);
-}
-
bool QProcessPrivate::startDetached(qint64 *pid)
{
static const DWORD errorElevationRequired = 740;
- if ((stdinChannel.type == Channel::Redirect && !openChannel(stdinChannel))
- || (stdoutChannel.type == Channel::Redirect && !openChannel(stdoutChannel))
- || (stderrChannel.type == Channel::Redirect && !openChannel(stderrChannel))) {
- closeChannel(&stdinChannel);
- closeChannel(&stdoutChannel);
- closeChannel(&stderrChannel);
+ if (!openChannelsForDetached()) {
+ // openChannel sets the error string
+ closeChannels();
return false;
}
@@ -933,24 +911,14 @@ bool QProcessPrivate::startDetached(qint64 *pid)
void *envPtr = nullptr;
QByteArray envlist;
- if (environment.d.constData()) {
+ if (!environment.inheritsFromParent()) {
envlist = qt_create_environment(environment.d.constData()->vars);
envPtr = envlist.data();
}
DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW);
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
- STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- 0, 0, 0,
- STARTF_USESTDHANDLES,
- 0, 0, 0,
- pipeOrStdHandle(stdinChannel.pipe[0], STD_INPUT_HANDLE),
- pipeOrStdHandle(stdoutChannel.pipe[1], STD_OUTPUT_HANDLE),
- pipeOrStdHandle(stderrChannel.pipe[1], STD_ERROR_HANDLE)
- };
-
+ STARTUPINFOW startupInfo = createStartupInfo();
QProcess::CreateProcessArguments cpargs = {
nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())),
nullptr, nullptr, true, dwCreationFlags, envPtr,
@@ -975,10 +943,13 @@ bool QProcessPrivate::startDetached(qint64 *pid)
success = startDetachedUacPrompt(program, arguments, nativeArguments,
workingDirectory, pid);
}
+ if (!success) {
+ if (pid)
+ *pid = -1;
+ setErrorAndEmit(QProcess::FailedToStart);
+ }
- closeChannel(&stdinChannel);
- closeChannel(&stdoutChannel);
- closeChannel(&stderrChannel);
+ closeChannels();
return success;
}
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 5c5a796278..581e1e75ef 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qresource.h"
#include "qresource_p.h"
@@ -69,15 +33,27 @@
# include <zstd.h>
#endif
-#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
# define QT_USE_MMAP
# include <sys/mman.h>
+# ifdef Q_OS_LINUX
+// since 5.7, so define in case we're being compiled with older kernel headers
+# define MREMAP_DONTUNMAP 4
+# elif defined(Q_OS_DARWIN)
+# include <mach/mach.h>
+# include <mach/vm_map.h>
+# endif
+#endif
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
#endif
//#define DEBUG_RESOURCE_MATCH
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// Symbols used by code generated by RCC.
// They cause compilation errors if the RCC content couldn't
// be interpreted by this QtCore version.
@@ -99,6 +75,7 @@ RCC_FEATURE_SYMBOL(Zstd)
#undef RCC_FEATURE_SYMBOL
+namespace {
class QStringSplitter
{
public:
@@ -107,14 +84,16 @@ public:
{
}
- inline bool hasNext() {
+ inline bool hasNext()
+ {
while (m_pos < m_len && m_data[m_pos] == m_splitChar)
++m_pos;
return m_pos < m_len;
}
- inline QStringView next() {
- int start = m_pos;
+ inline QStringView next()
+ {
+ const qsizetype start = m_pos;
while (m_pos < m_len && m_data[m_pos] != m_splitChar)
++m_pos;
return QStringView(m_data + start, m_pos - start);
@@ -123,21 +102,20 @@ public:
const QChar *m_data;
qsizetype m_len;
qsizetype m_pos = 0;
- QChar m_splitChar = QLatin1Char('/');
+ QChar m_splitChar = u'/';
};
-
-//resource glue
+// resource glue
class QResourceRoot
{
public:
- enum Flags
- {
+ enum Flags {
// must match rcc.h
Compressed = 0x01,
Directory = 0x02,
CompressedZstd = 0x04
};
+
private:
const uchar *tree, *names, *payloads;
int version;
@@ -163,7 +141,7 @@ public:
return QResource::NoCompression;
}
const uchar *data(int node, qint64 *size) const;
- quint64 lastModified(int node) const;
+ qint64 lastModified(int node) const;
QStringList children(int node) const;
virtual QString mappingRoot() const { return QString(); }
bool mappingRootSubdir(const QString &path, QString *match = nullptr) const;
@@ -188,20 +166,22 @@ static QString cleanPath(const QString &_path)
QString path = QDir::cleanPath(_path);
// QDir::cleanPath does not remove two trailing slashes under _Windows_
// due to support for UNC paths. Remove those manually.
- if (path.startsWith(QLatin1String("//")))
+ if (path.startsWith("//"_L1))
path.remove(0, 1);
return path;
}
+} // unnamed namespace
-Q_DECLARE_TYPEINFO(QResourceRoot, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QResourceRoot, Q_RELOCATABLE_TYPE);
typedef QList<QResourceRoot*> ResourceList;
+namespace {
struct QResourceGlobalData
{
QRecursiveMutex resourceMutex;
ResourceList resourceList;
- QStringList resourceSearchPaths;
};
+}
Q_GLOBAL_STATIC(QResourceGlobalData, resourceGlobalData)
static inline QRecursiveMutex &resourceMutex()
@@ -210,9 +190,6 @@ static inline QRecursiveMutex &resourceMutex()
static inline ResourceList *resourceList()
{ return &resourceGlobalData->resourceList; }
-static inline QStringList *resourceSearchPaths()
-{ return &resourceGlobalData->resourceSearchPaths; }
-
/*!
\class QResource
\inmodule QtCore
@@ -270,6 +247,19 @@ static inline QStringList *resourceSearchPaths()
itself will be unmapped from memory when the last QResource that points
to it is destroyed.
+ \section2 Corruption and Security
+
+ The QResource class performs some checks on the file passed to determine
+ whether it is supported by the current version of Qt. Those tests are only
+ to check the file header does not request features (such as Zstandard
+ decompression) that have not been compiled in or that the file is not of a
+ future version of Qt. They do not confirm the validity of the entire file.
+
+ QResource should not be used on files whose provenance cannot be trusted.
+ Applications should be designed to attempt to load only resource files
+ whose provenance is at least as trustworthy as that of the application
+ itself or its plugins.
+
\sa {The Qt Resource System}, QFile, QDir, QFileInfo
*/
@@ -283,7 +273,7 @@ static inline QStringList *resourceSearchPaths()
\value NoCompression Contents are not compressed
\value ZlibCompression Contents are compressed using \l{https://zlib.net}{zlib} and can
be decompressed using the qUncompress() function.
- \value ZstdCompression Contents are compressed using \l{https://zstd.net}{zstd}. To
+ \value ZstdCompression Contents are compressed using \l{Zstandard Site}{zstd}. To
decompress, use the \c{ZSTD_decompress} function from the zstd
library.
@@ -303,14 +293,16 @@ public:
bool load(const QString &file);
void clear();
+ static bool mayRemapData(const QResource &resource);
+
QLocale locale;
QString fileName, absoluteFilePath;
- QList<QResourceRoot*> related;
- mutable qint64 size;
- mutable quint64 lastModified;
- mutable const uchar *data;
+ QList<QResourceRoot *> related;
+ qint64 size;
+ qint64 lastModified;
+ const uchar *data;
mutable QStringList children;
- mutable quint8 compressionAlgo;
+ quint8 compressionAlgo;
bool container;
/* 2 or 6 padding bytes */
@@ -318,8 +310,7 @@ public:
Q_DECLARE_PUBLIC(QResource)
};
-void
-QResourcePrivate::clear()
+void QResourcePrivate::clear()
{
absoluteFilePath.clear();
compressionAlgo = QResource::NoCompression;
@@ -328,28 +319,27 @@ QResourcePrivate::clear()
children.clear();
lastModified = 0;
container = 0;
- for(int i = 0; i < related.size(); ++i) {
+ for (int i = 0; i < related.size(); ++i) {
QResourceRoot *root = related.at(i);
- if(!root->ref.deref())
+ if (!root->ref.deref())
delete root;
}
related.clear();
}
-bool
-QResourcePrivate::load(const QString &file)
+bool QResourcePrivate::load(const QString &file)
{
related.clear();
const auto locker = qt_scoped_lock(resourceMutex());
const ResourceList *list = resourceList();
QString cleaned = cleanPath(file);
- for(int i = 0; i < list->size(); ++i) {
+ for (int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
const int node = res->findNode(cleaned, locale);
- if(node != -1) {
- if(related.isEmpty()) {
+ if (node != -1) {
+ if (related.isEmpty()) {
container = res->isContainer(node);
- if(!container) {
+ if (!container) {
data = res->data(node, &size);
compressionAlgo = res->compressionAlgo(node);
} else {
@@ -358,12 +348,13 @@ QResourcePrivate::load(const QString &file)
compressionAlgo = QResource::NoCompression;
}
lastModified = res->lastModified(node);
- } else if(res->isContainer(node) != container) {
- qWarning("QResourceInfo: Resource [%s] has both data and children!", file.toLatin1().constData());
+ } else if (res->isContainer(node) != container) {
+ qWarning("QResourceInfo: Resource [%s] has both data and children!",
+ file.toLatin1().constData());
}
res->ref.ref();
related.append(res);
- } else if(res->mappingRootSubdir(file)) {
+ } else if (res->mappingRootSubdir(file)) {
container = true;
data = nullptr;
size = 0;
@@ -376,61 +367,52 @@ QResourcePrivate::load(const QString &file)
return !related.isEmpty();
}
-void
-QResourcePrivate::ensureInitialized() const
+void QResourcePrivate::ensureInitialized() const
{
- if(!related.isEmpty())
+ if (!related.isEmpty())
return;
QResourcePrivate *that = const_cast<QResourcePrivate *>(this);
- if(fileName == QLatin1String(":"))
- that->fileName += QLatin1Char('/');
+ if (fileName == ":"_L1)
+ that->fileName += u'/';
that->absoluteFilePath = fileName;
- if(!that->absoluteFilePath.startsWith(QLatin1Char(':')))
- that->absoluteFilePath.prepend(QLatin1Char(':'));
+ if (!that->absoluteFilePath.startsWith(u':'))
+ that->absoluteFilePath.prepend(u':');
QStringView path(fileName);
- if(path.startsWith(QLatin1Char(':')))
+ if (path.startsWith(u':'))
path = path.mid(1);
- if(path.startsWith(QLatin1Char('/'))) {
+ if (path.startsWith(u'/')) {
that->load(path.toString());
} else {
- const auto locker = qt_scoped_lock(resourceMutex());
- QStringList searchPaths = *resourceSearchPaths();
- searchPaths << QLatin1String("");
- for(int i = 0; i < searchPaths.size(); ++i) {
- const QString searchPath(searchPaths.at(i) + QLatin1Char('/') + path);
- if(that->load(searchPath)) {
- that->absoluteFilePath = QLatin1Char(':') + searchPath;
- break;
- }
- }
+ // Should we search QDir::searchPath() before falling back to root ?
+ const QString searchPath(u'/' + path);
+ if (that->load(searchPath))
+ that->absoluteFilePath = u':' + searchPath;
}
}
-void
-QResourcePrivate::ensureChildren() const
+void QResourcePrivate::ensureChildren() const
{
ensureInitialized();
- if(!children.isEmpty() || !container || related.isEmpty())
+ if (!children.isEmpty() || !container || related.isEmpty())
return;
QString path = absoluteFilePath, k;
- if(path.startsWith(QLatin1Char(':')))
+ if (path.startsWith(u':'))
path = path.mid(1);
- QDuplicateTracker<QString> kids;
- kids.reserve(related.size());
+ QDuplicateTracker<QString> kids(related.size());
QString cleaned = cleanPath(path);
- for(int i = 0; i < related.size(); ++i) {
+ for (int i = 0; i < related.size(); ++i) {
QResourceRoot *res = related.at(i);
- if(res->mappingRootSubdir(path, &k) && !k.isEmpty()) {
+ if (res->mappingRootSubdir(path, &k) && !k.isEmpty()) {
if (!kids.hasSeen(k))
children += k;
} else {
const int node = res->findNode(cleaned);
- if(node != -1) {
+ if (node != -1) {
QStringList related_children = res->children(node);
- for(int kid = 0; kid < related_children.size(); ++kid) {
+ for (int kid = 0; kid < related_children.size(); ++kid) {
k = related_children.at(kid);
if (!kids.hasSeen(k))
children += k;
@@ -466,7 +448,6 @@ qint64 QResourcePrivate::uncompressedSize() const
Q_UNREACHABLE();
#endif
}
-
}
return -1;
}
@@ -474,6 +455,10 @@ qint64 QResourcePrivate::uncompressedSize() const
qsizetype QResourcePrivate::decompress(char *buffer, qsizetype bufferSize) const
{
Q_ASSERT(data);
+#if defined(QT_NO_COMPRESS) && !QT_CONFIG(zstd)
+ Q_UNUSED(buffer);
+ Q_UNUSED(bufferSize);
+#endif
switch (compressionAlgo) {
case QResource::NoCompression:
@@ -483,8 +468,8 @@ qsizetype QResourcePrivate::decompress(char *buffer, qsizetype bufferSize) const
case QResource::ZlibCompression: {
#ifndef QT_NO_COMPRESS
uLong len = uLong(bufferSize);
- int res = ::uncompress(reinterpret_cast<Bytef *>(buffer), &len,
- data + sizeof(quint32), uLong(size - sizeof(quint32)));
+ int res = ::uncompress(reinterpret_cast<Bytef *>(buffer), &len, data + sizeof(quint32),
+ uLong(size - sizeof(quint32)));
if (res != Z_OK) {
qWarning("QResource: error decompressing zlib content (%d)", res);
return -1;
@@ -623,29 +608,6 @@ bool QResource::isValid() const
\sa isDir()
*/
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Returns \c true if the resource represents a file and the data backing it
- is in a compressed format, false otherwise. If the data is compressed,
- check compressionAlgorithm() to verify what algorithm to use to decompress
- the data.
-
- \note This function is deprecated and can be replaced with
- \code
- compressionAlgorithm() != NoCompression
- \endcode
-
- \sa data(), compressionAlgorithm(), isFile()
-*/
-
-bool QResource::isCompressed() const
-{
- return compressionAlgorithm() != NoCompression;
-}
-#endif
-
/*!
\since 5.13
@@ -657,7 +619,7 @@ bool QResource::isCompressed() const
possible compression algorithm.
If this function returns QResource::ZstdCompression, you need to use the
- Zstandard library functios (\c{<zstd.h> header). Qt does not provide a
+ Zstandard library functions (\c{<zstd.h>} header). Qt does not provide a
wrapper.
See \l{http://facebook.github.io/zstd/zstd_manual.html}{Zstandard manual}.
@@ -730,7 +692,7 @@ const uchar *QResource::data() const
\note If the data was compressed, this function will decompress every time
it is called. The result is not cached between calls.
- \sa uncompressedSize(), size(), isCompressed(), isFile()
+ \sa uncompressedSize(), size(), compressionAlgorithm(), isFile()
*/
QByteArray QResource::uncompressedData() const
@@ -797,62 +759,18 @@ QStringList QResource::children() const
return d->children;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Use QDir::addSearchPath() with a prefix instead.
-
- Adds \a path to the search paths searched in to find resources that are
- not specified with an absolute path. The \a path must be an absolute
- path (start with \c{/}).
-
- The default search path is to search only in the root (\c{:/}). The last
- path added will be consulted first upon next QResource creation.
-*/
-void
-QResource::addSearchPath(const QString &path)
-{
- if (!path.startsWith(QLatin1Char('/'))) {
- qWarning("QResource::addResourceSearchPath: Search paths must be absolute (start with /) [%ls]",
- qUtf16Printable(path));
- return;
- }
- const auto locker = qt_scoped_lock(resourceMutex());
- resourceSearchPaths()->prepend(path);
-}
-
-/*!
- \obsolete
-
- Use QDir::searchPaths() instead.
-
- Returns the current search path list. This list is consulted when
- creating a relative resource.
-
- \sa QDir::addSearchPath(), QDir::setSearchPaths()
-*/
-
-QStringList
-QResource::searchPaths()
-{
- const auto locker = qt_scoped_lock(resourceMutex());
- return *resourceSearchPaths();
-}
-#endif
-
inline uint QResourceRoot::hash(int node) const
{
- if(!node) //root
+ if (!node) // root
return 0;
const int offset = findOffset(node);
qint32 name_offset = qFromBigEndian<qint32>(tree + offset);
- name_offset += 2; //jump past name length
+ name_offset += 2; // jump past name length
return qFromBigEndian<quint32>(names + name_offset);
}
inline QString QResourceRoot::name(int node) const
{
- if(!node) // root
+ if (!node) // root
return QString();
const int offset = findOffset(node);
@@ -860,11 +778,11 @@ inline QString QResourceRoot::name(int node) const
qint32 name_offset = qFromBigEndian<qint32>(tree + offset);
quint16 name_length = qFromBigEndian<qint16>(names + name_offset);
name_offset += 2;
- name_offset += 4; //jump past hash
+ name_offset += 4; // jump past hash
ret.resize(name_length);
QChar *strData = ret.data();
- qFromBigEndian<ushort>(names + name_offset, name_length, strData);
+ qFromBigEndian<char16_t>(names + name_offset, name_length, strData);
return ret;
}
@@ -873,31 +791,31 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
QString path = _path;
{
QString root = mappingRoot();
- if(!root.isEmpty()) {
- if(root == path) {
- path = QLatin1Char('/');
+ if (!root.isEmpty()) {
+ if (root == path) {
+ path = u'/';
} else {
- if(!root.endsWith(QLatin1Char('/')))
- root += QLatin1Char('/');
- if(path.size() >= root.size() && path.startsWith(root))
- path = path.mid(root.length()-1);
- if(path.isEmpty())
- path = QLatin1Char('/');
+ if (!root.endsWith(u'/'))
+ root += u'/';
+ if (path.size() >= root.size() && path.startsWith(root))
+ path = path.mid(root.size() - 1);
+ if (path.isEmpty())
+ path = u'/';
}
}
}
#ifdef DEBUG_RESOURCE_MATCH
- qDebug() << "!!!!" << "START" << path << locale.country() << locale.language();
+ qDebug() << "!!!!" << "START" << path << locale.territory() << locale.language();
#endif
- if(path == QLatin1String("/"))
+ if (path == "/"_L1)
return 0;
- //the root node is always first
+ // the root node is always first
qint32 child_count = qFromBigEndian<qint32>(tree + 6);
qint32 child = qFromBigEndian<qint32>(tree + 10);
- //now iterate up the tree
+ // now iterate up the tree
int node = -1;
QStringSplitter splitter(path);
@@ -906,20 +824,20 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << " CHILDREN" << segment;
- for(int j = 0; j < child_count; ++j) {
- qDebug() << " " << child+j << " :: " << name(child+j);
+ for (int j = 0; j < child_count; ++j) {
+ qDebug() << " " << child + j << " :: " << name(child + j);
}
#endif
const uint h = qt_hash(segment);
- //do the binary search for the hash
- int l = 0, r = child_count-1;
- int sub_node = (l+r+1)/2;
- while(r != l) {
- const uint sub_node_hash = hash(child+sub_node);
- if(h == sub_node_hash)
+ // do the binary search for the hash
+ int l = 0, r = child_count - 1;
+ int sub_node = (l + r + 1) / 2;
+ while (r != l) {
+ const uint sub_node_hash = hash(child + sub_node);
+ if (h == sub_node_hash)
break;
- else if(h < sub_node_hash)
+ else if (h < sub_node_hash)
r = sub_node - 1;
else
l = sub_node;
@@ -927,26 +845,27 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
}
sub_node += child;
- //now do the "harder" compares
+ // now do the "harder" compares
bool found = false;
- if(hash(sub_node) == h) {
- while(sub_node > child && hash(sub_node-1) == h) //backup for collisions
+ if (hash(sub_node) == h) {
+ while (sub_node > child && hash(sub_node - 1) == h) // backup for collisions
--sub_node;
- for(; sub_node < child+child_count && hash(sub_node) == h; ++sub_node) { //here we go...
- if(name(sub_node) == segment) {
+ for (; sub_node < child + child_count && hash(sub_node) == h;
+ ++sub_node) { // here we go...
+ if (name(sub_node) == segment) {
found = true;
int offset = findOffset(sub_node);
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << " TRY" << sub_node << name(sub_node) << offset;
#endif
- offset += 4; //jump past name
+ offset += 4; // jump past name
const qint16 flags = qFromBigEndian<qint16>(tree + offset);
offset += 2;
- if(!splitter.hasNext()) {
- if(!(flags & Directory)) {
- const qint16 country = qFromBigEndian<qint16>(tree + offset);
+ if (!splitter.hasNext()) {
+ if (!(flags & Directory)) {
+ const qint16 territory = qFromBigEndian<qint16>(tree + offset);
offset += 2;
const qint16 language = qFromBigEndian<qint16>(tree + offset);
@@ -954,13 +873,16 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << " " << "LOCALE" << country << language;
#endif
- if(country == locale.country() && language == locale.language()) {
+ if (territory == locale.territory() && language == locale.language()) {
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << "!!!!" << "FINISHED" << __LINE__ << sub_node;
#endif
return sub_node;
- } else if((country == QLocale::AnyCountry && language == locale.language()) ||
- (country == QLocale::AnyCountry && language == QLocale::C && node == -1)) {
+ } else if ((territory == QLocale::AnyTerritory
+ && language == locale.language())
+ || (territory == QLocale::AnyTerritory
+ && language == QLocale::C
+ && node == -1)) {
node = sub_node;
}
continue;
@@ -973,7 +895,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
}
}
- if(!(flags & Directory))
+ if (!(flags & Directory))
return -1;
child_count = qFromBigEndian<qint32>(tree + offset);
@@ -983,7 +905,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
}
}
}
- if(!found)
+ if (!found)
break;
}
#ifdef DEBUG_RESOURCE_MATCH
@@ -993,28 +915,28 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
}
short QResourceRoot::flags(int node) const
{
- if(node == -1)
+ if (node == -1)
return 0;
- const int offset = findOffset(node) + 4; //jump past name
+ const int offset = findOffset(node) + 4; // jump past name
return qFromBigEndian<qint16>(tree + offset);
}
const uchar *QResourceRoot::data(int node, qint64 *size) const
{
- if(node == -1) {
+ if (node == -1) {
*size = 0;
return nullptr;
}
- int offset = findOffset(node) + 4; //jump past name
+ int offset = findOffset(node) + 4; // jump past name
const qint16 flags = qFromBigEndian<qint16>(tree + offset);
offset += 2;
- offset += 4; //jump past locale
+ offset += 4; // jump past locale
- if(!(flags & Directory)) {
+ if (!(flags & Directory)) {
const qint32 data_offset = qFromBigEndian<qint32>(tree + offset);
const quint32 data_length = qFromBigEndian<quint32>(payloads + data_offset);
- const uchar *ret = payloads+data_offset+4;
+ const uchar *ret = payloads + data_offset + 4;
*size = data_length;
return ret;
}
@@ -1022,32 +944,32 @@ const uchar *QResourceRoot::data(int node, qint64 *size) const
return nullptr;
}
-quint64 QResourceRoot::lastModified(int node) const
+qint64 QResourceRoot::lastModified(int node) const
{
if (node == -1 || version < 0x02)
return 0;
const int offset = findOffset(node) + 14;
- return qFromBigEndian<quint64>(tree + offset);
+ return qFromBigEndian<qint64>(tree + offset);
}
QStringList QResourceRoot::children(int node) const
{
- if(node == -1)
+ if (node == -1)
return QStringList();
- int offset = findOffset(node) + 4; //jump past name
+ int offset = findOffset(node) + 4; // jump past name
const qint16 flags = qFromBigEndian<qint16>(tree + offset);
offset += 2;
QStringList ret;
- if(flags & Directory) {
+ if (flags & Directory) {
const qint32 child_count = qFromBigEndian<qint32>(tree + offset);
offset += 4;
const qint32 child_off = qFromBigEndian<qint32>(tree + offset);
ret.reserve(child_count);
- for(int i = child_off; i < child_off+child_count; ++i)
+ for (int i = child_off; i < child_off + child_count; ++i)
ret << name(i);
}
return ret;
@@ -1091,7 +1013,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
break;
}
}
- if(!found) {
+ if (!found) {
QResourceRoot *root = new QResourceRoot(version, tree, name, data);
root->ref.ref();
list->append(root);
@@ -1111,10 +1033,10 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre
if (version >= 0x01 && version <= 0x3) {
QResourceRoot res(version, tree, name, data);
ResourceList *list = resourceList();
- for (int i = 0; i < list->size(); ) {
+ for (int i = 0; i < list->size();) {
if (*list->at(i) == res) {
QResourceRoot *root = list->takeAt(i);
- if(!root->ref.deref())
+ if (!root->ref.deref())
delete root;
} else {
++i;
@@ -1125,9 +1047,9 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre
return false;
}
-//run time resource creation
-
-class QDynamicBufferResourceRoot: public QResourceRoot
+namespace {
+// run time resource creation
+class QDynamicBufferResourceRoot : public QResourceRoot
{
QString root;
const uchar *buffer;
@@ -1146,12 +1068,12 @@ public:
if (size >= 0 && size < 20)
return false;
- //setup the data now
+ // setup the data now
int offset = 0;
- //magic number
- if(b[offset+0] != 'q' || b[offset+1] != 'r' ||
- b[offset+2] != 'e' || b[offset+3] != 's') {
+ // magic number
+ if (b[offset + 0] != 'q' || b[offset + 1] != 'r' || b[offset + 2] != 'e'
+ || b[offset + 3] != 's') {
return false;
}
offset += 4;
@@ -1190,15 +1112,20 @@ public:
if (version >= 0x01 && version <= 0x03) {
buffer = b;
- setSource(version, b+tree_offset, b+name_offset, b+data_offset);
+ setSource(version, b + tree_offset, b + name_offset, b + data_offset);
return true;
}
return false;
}
};
-class QDynamicFileResourceRoot: public QDynamicBufferResourceRoot
+class QDynamicFileResourceRoot : public QDynamicBufferResourceRoot
{
+public:
+ static uchar *map_sys(QFile &file, qint64 base, qsizetype size);
+ static void unmap_sys(void *base, qsizetype size);
+
+private:
QString fileName;
// for mmap'ed files, this is what needs to be unmapped.
uchar *unmapPointer;
@@ -1209,22 +1136,18 @@ public:
: QDynamicBufferResourceRoot(_root), unmapPointer(nullptr), unmapLength(0)
{ }
~QDynamicFileResourceRoot() {
-#if defined(QT_USE_MMAP)
- if (unmapPointer) {
- munmap((char*)unmapPointer, unmapLength);
- unmapPointer = nullptr;
- unmapLength = 0;
- } else
-#endif
- {
- delete [] mappingBuffer();
- }
+ if (wasMemoryMapped())
+ unmap_sys(unmapPointer, unmapLength);
+ else
+ delete[] mappingBuffer();
}
QString mappingFile() const { return fileName; }
ResourceRootType type() const override { return Resource_File; }
+ bool wasMemoryMapped() const { return unmapPointer; }
bool registerSelf(const QString &f);
};
+} // unnamed namespace
#ifndef MAP_FILE
# define MAP_FILE 0
@@ -1233,49 +1156,69 @@ public:
# define MAP_FAILED reinterpret_cast<void *>(-1)
#endif
-bool QDynamicFileResourceRoot::registerSelf(const QString &f)
+void QDynamicFileResourceRoot::unmap_sys(void *base, qsizetype size)
+{
+#if defined(QT_USE_MMAP)
+ munmap(base, size);
+#elif defined(Q_OS_WIN)
+ Q_UNUSED(size)
+ UnmapViewOfFile(reinterpret_cast<void *>(base));
+#endif
+}
+
+// Note: caller must ensure \a offset and \a size are acceptable to the OS.
+uchar *QDynamicFileResourceRoot::map_sys(QFile &file, qint64 offset, qsizetype size)
{
- bool fromMM = false;
- uchar *data = nullptr;
- qsizetype data_len = 0;
+ Q_ASSERT(file.isOpen());
+ void *ptr = nullptr;
+ if (size < 0)
+ size = qMin(file.size() - offset, (std::numeric_limits<qsizetype>::max)());
+ // We don't use QFile::map() here because we want to dispose of the QFile object
#if defined(QT_USE_MMAP)
- int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY, 0666);
- if (fd >= 0) {
- QT_STATBUF st;
- if (!QT_FSTAT(fd, &st) && st.st_size <= std::numeric_limits<qsizetype>::max()) {
- int protection = PROT_READ; // read-only memory
- int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file
- void *ptr = QT_MMAP(nullptr, st.st_size, // any address, whole file
- protection, flags,
- fd, 0); // from offset 0 of fd
- if (ptr != MAP_FAILED) {
- data = static_cast<uchar *>(ptr);
- data_len = st.st_size;
- fromMM = true;
- }
+ int fd = file.handle();
+ int protection = PROT_READ; // read-only memory
+ int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file
+ ptr = QT_MMAP(nullptr, size, protection, flags, fd, offset);
+ if (ptr == MAP_FAILED)
+ ptr = nullptr;
+#elif defined(Q_OS_WIN)
+ int fd = file.handle();
+ HANDLE fileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ if (fileHandle != INVALID_HANDLE_VALUE) {
+ HANDLE mapHandle = CreateFileMapping(fileHandle, 0, PAGE_WRITECOPY, 0, 0, 0);
+ if (mapHandle) {
+ ptr = MapViewOfFile(mapHandle, FILE_MAP_COPY, DWORD(offset >> 32), DWORD(offset), size);
+ CloseHandle(mapHandle);
}
- QT_CLOSE(fd);
}
#endif // QT_USE_MMAP
- if (!data) {
- QFile file(f);
+ return static_cast<uchar *>(ptr);
+}
+
+bool QDynamicFileResourceRoot::registerSelf(const QString &f)
+{
+ QFile file(f);
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+
+ qint64 data_len = file.size();
+ if (data_len > std::numeric_limits<qsizetype>::max())
+ return false;
+
+ uchar *data = map_sys(file, 0, data_len);
+ bool fromMM = !!data;
+
+ if (!fromMM) {
bool ok = false;
- if (file.open(QIODevice::ReadOnly)) {
- qint64 fsize = file.size();
- if (fsize <= std::numeric_limits<qsizetype>::max()) {
- data_len = file.size();
- data = new uchar[data_len];
- ok = (data_len == file.read((char*)data, data_len));
- }
- }
+ data = new uchar[data_len];
+ ok = (data_len == file.read(reinterpret_cast<char *>(data), data_len));
if (!ok) {
- delete [] data;
+ delete[] data;
data = nullptr;
data_len = 0;
return false;
}
- fromMM = false;
}
if (data && QDynamicBufferResourceRoot::registerSelf(data, data_len)) {
if (fromMM) {
@@ -1288,17 +1231,17 @@ bool QDynamicFileResourceRoot::registerSelf(const QString &f)
return false;
}
-static QString qt_resource_fixResourceRoot(QString r) {
- if(!r.isEmpty()) {
- if(r.startsWith(QLatin1Char(':')))
+static QString qt_resource_fixResourceRoot(QString r)
+{
+ if (!r.isEmpty()) {
+ if (r.startsWith(u':'))
r = r.mid(1);
- if(!r.isEmpty())
+ if (!r.isEmpty())
r = QDir::cleanPath(r);
}
return r;
}
-
/*!
\fn bool QResource::registerResource(const QString &rccFileName, const QString &mapRoot)
@@ -1309,18 +1252,18 @@ static QString qt_resource_fixResourceRoot(QString r) {
\sa unregisterResource()
*/
-bool
-QResource::registerResource(const QString &rccFilename, const QString &resourceRoot)
+bool QResource::registerResource(const QString &rccFilename, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
- if(!r.isEmpty() && r[0] != QLatin1Char('/')) {
- qWarning("QDir::registerResource: Registering a resource [%ls] must be rooted in an absolute path (start with /) [%ls]",
+ if (!r.isEmpty() && r[0] != u'/') {
+ qWarning("QDir::registerResource: Registering a resource [%ls] must be rooted in an "
+ "absolute path (start with /) [%ls]",
qUtf16Printable(rccFilename), qUtf16Printable(resourceRoot));
return false;
}
QDynamicFileResourceRoot *root = new QDynamicFileResourceRoot(r);
- if(root->registerSelf(rccFilename)) {
+ if (root->registerSelf(rccFilename)) {
root->ref.ref();
const auto locker = qt_scoped_lock(resourceMutex());
resourceList()->append(root);
@@ -1341,20 +1284,19 @@ QResource::registerResource(const QString &rccFilename, const QString &resourceR
\sa registerResource()
*/
-bool
-QResource::unregisterResource(const QString &rccFilename, const QString &resourceRoot)
+bool QResource::unregisterResource(const QString &rccFilename, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
const auto locker = qt_scoped_lock(resourceMutex());
ResourceList *list = resourceList();
- for(int i = 0; i < list->size(); ++i) {
+ for (int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
- if(res->type() == QResourceRoot::Resource_File) {
- QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res);
+ if (res->type() == QResourceRoot::Resource_File) {
+ QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot *>(res);
if (root->mappingFile() == rccFilename && root->mappingRoot() == r) {
list->removeAt(i);
- if(!root->ref.deref()) {
+ if (!root->ref.deref()) {
delete root;
return true;
}
@@ -1365,7 +1307,6 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc
return false;
}
-
/*!
\fn bool QResource::registerResource(const uchar *rccData, const QString &mapRoot)
\since 4.3
@@ -1380,12 +1321,12 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc
\sa unregisterResource()
*/
-bool
-QResource::registerResource(const uchar *rccData, const QString &resourceRoot)
+bool QResource::registerResource(const uchar *rccData, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
- if(!r.isEmpty() && r[0] != QLatin1Char('/')) {
- qWarning("QDir::registerResource: Registering a resource [%p] must be rooted in an absolute path (start with /) [%ls]",
+ if (!r.isEmpty() && r[0] != u'/') {
+ qWarning("QDir::registerResource: Registering a resource [%p] must be rooted in an "
+ "absolute path (start with /) [%ls]",
rccData, qUtf16Printable(resourceRoot));
return false;
}
@@ -1412,20 +1353,19 @@ QResource::registerResource(const uchar *rccData, const QString &resourceRoot)
\sa registerResource()
*/
-bool
-QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot)
+bool QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
const auto locker = qt_scoped_lock(resourceMutex());
ResourceList *list = resourceList();
- for(int i = 0; i < list->size(); ++i) {
+ for (int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
- if(res->type() == QResourceRoot::Resource_Buffer) {
- QDynamicBufferResourceRoot *root = reinterpret_cast<QDynamicBufferResourceRoot*>(res);
+ if (res->type() == QResourceRoot::Resource_Buffer) {
+ QDynamicBufferResourceRoot *root = reinterpret_cast<QDynamicBufferResourceRoot *>(res);
if (root->mappingBuffer() == rccData && root->mappingRoot() == r) {
list->removeAt(i);
- if(!root->ref.deref()) {
+ if (!root->ref.deref()) {
delete root;
return true;
}
@@ -1437,7 +1377,7 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot)
}
#if !defined(QT_BOOTSTRAPPED)
-//resource engine
+// resource engine
class QResourceFileEnginePrivate : public QAbstractFileEnginePrivate
{
protected:
@@ -1446,33 +1386,24 @@ private:
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr);
void uncompress() const;
- qint64 offset;
+ void mapUncompressed();
+ bool mapUncompressed_sys();
+ void unmapUncompressed_sys();
+ qint64 offset = 0;
QResource resource;
mutable QByteArray uncompressed;
+ bool mustUnmap = false;
+
+ // minimum size for which we'll try to re-open ourselves in mapUncompressed()
+ static constexpr qsizetype RemapCompressedThreshold = 16384;
protected:
- QResourceFileEnginePrivate() : offset(0) { }
+ ~QResourceFileEnginePrivate()
+ {
+ if (mustUnmap)
+ unmapUncompressed_sys();
+ }
};
-bool QResourceFileEngine::mkdir(const QString &, bool) const
-{
- return false;
-}
-
-bool QResourceFileEngine::rmdir(const QString &, bool) const
-{
- return false;
-}
-
-bool QResourceFileEngine::setSize(qint64)
-{
- return false;
-}
-
-QStringList QResourceFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
-{
- return QAbstractFileEngine::entryList(filters, filterNames);
-}
-
bool QResourceFileEngine::caseSensitive() const
{
return true;
@@ -1495,8 +1426,11 @@ void QResourceFileEngine::setFileName(const QString &file)
d->resource.setFileName(file);
}
-bool QResourceFileEngine::open(QIODevice::OpenMode flags)
+bool QResourceFileEngine::open(QIODevice::OpenMode flags,
+ std::optional<QFile::Permissions> permissions)
{
+ Q_UNUSED(permissions);
+
Q_D(QResourceFileEngine);
if (d->resource.fileName().isEmpty()) {
qWarning("QResourceFileEngine::open: Missing file name");
@@ -1533,43 +1467,18 @@ bool QResourceFileEngine::flush()
qint64 QResourceFileEngine::read(char *data, qint64 len)
{
Q_D(QResourceFileEngine);
- if(len > size()-d->offset)
- len = size()-d->offset;
- if(len <= 0)
+ if (len > size() - d->offset)
+ len = size() - d->offset;
+ if (len <= 0)
return 0;
if (!d->uncompressed.isNull())
- memcpy(data, d->uncompressed.constData()+d->offset, len);
+ memcpy(data, d->uncompressed.constData() + d->offset, len);
else
- memcpy(data, d->resource.data()+d->offset, len);
+ memcpy(data, d->resource.data() + d->offset, len);
d->offset += len;
return len;
}
-qint64 QResourceFileEngine::write(const char *, qint64)
-{
- return -1;
-}
-
-bool QResourceFileEngine::remove()
-{
- return false;
-}
-
-bool QResourceFileEngine::copy(const QString &)
-{
- return false;
-}
-
-bool QResourceFileEngine::rename(const QString &)
-{
- return false;
-}
-
-bool QResourceFileEngine::link(const QString &)
-{
- return false;
-}
-
qint64 QResourceFileEngine::size() const
{
Q_D(const QResourceFileEngine);
@@ -1585,7 +1494,7 @@ qint64 QResourceFileEngine::pos() const
bool QResourceFileEngine::atEnd() const
{
Q_D(const QResourceFileEngine);
- if(!d->resource.isValid())
+ if (!d->resource.isValid())
return true;
return d->offset == size();
}
@@ -1593,69 +1502,61 @@ bool QResourceFileEngine::atEnd() const
bool QResourceFileEngine::seek(qint64 pos)
{
Q_D(QResourceFileEngine);
- if(!d->resource.isValid())
+ if (!d->resource.isValid())
return false;
- if(d->offset > size())
+ if (d->offset > size())
return false;
d->offset = pos;
return true;
}
-bool QResourceFileEngine::isSequential() const
-{
- return false;
-}
-
QAbstractFileEngine::FileFlags QResourceFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const
{
Q_D(const QResourceFileEngine);
QAbstractFileEngine::FileFlags ret;
- if(!d->resource.isValid())
+ if (!d->resource.isValid())
return ret;
- if(type & PermsMask)
- ret |= QAbstractFileEngine::FileFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm);
- if(type & TypesMask) {
- if(d->resource.isDir())
+ if (type & PermsMask)
+ ret |= QAbstractFileEngine::FileFlags(ReadOwnerPerm | ReadUserPerm | ReadGroupPerm
+ | ReadOtherPerm);
+ if (type & TypesMask) {
+ if (d->resource.isDir())
ret |= DirectoryType;
else
ret |= FileType;
}
- if(type & FlagsMask) {
+ if (type & FlagsMask) {
ret |= ExistsFlag;
- if(d->resource.absoluteFilePath() == QLatin1String(":/"))
+ if (d->resource.absoluteFilePath() == ":/"_L1)
ret |= RootFlag;
}
return ret;
}
-bool QResourceFileEngine::setPermissions(uint)
-{
- return false;
-}
-
QString QResourceFileEngine::fileName(FileName file) const
{
Q_D(const QResourceFileEngine);
- if(file == BaseName) {
- int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/'));
+ if (file == BaseName) {
+ const qsizetype slash = d->resource.fileName().lastIndexOf(u'/');
if (slash == -1)
return d->resource.fileName();
return d->resource.fileName().mid(slash + 1);
- } else if(file == PathName || file == AbsolutePathName) {
- const QString path = (file == AbsolutePathName) ? d->resource.absoluteFilePath() : d->resource.fileName();
- const int slash = path.lastIndexOf(QLatin1Char('/'));
+ } else if (file == PathName || file == AbsolutePathName) {
+ const QString path = (file == AbsolutePathName) ? d->resource.absoluteFilePath()
+ : d->resource.fileName();
+ const qsizetype slash = path.lastIndexOf(u'/');
if (slash == -1)
- return QLatin1String(":");
+ return ":"_L1;
else if (slash <= 1)
- return QLatin1String(":/");
+ return ":/"_L1;
return path.left(slash);
- } else if(file == CanonicalName || file == CanonicalPathName) {
+ } else if (file == CanonicalName || file == CanonicalPathName) {
const QString absoluteFilePath = d->resource.absoluteFilePath();
- if(file == CanonicalPathName) {
- const int slash = absoluteFilePath.lastIndexOf(QLatin1Char('/'));
+ if (file == CanonicalPathName) {
+ const qsizetype slash = absoluteFilePath.lastIndexOf(u'/');
if (slash != -1)
return absoluteFilePath.left(slash);
}
@@ -1664,26 +1565,16 @@ QString QResourceFileEngine::fileName(FileName file) const
return d->resource.fileName();
}
-bool QResourceFileEngine::isRelativePath() const
-{
- return false;
-}
-
uint QResourceFileEngine::ownerId(FileOwner) const
{
- static const uint nobodyID = (uint) -2;
+ static const uint nobodyID = static_cast<uint>(-2);
return nobodyID;
}
-QString QResourceFileEngine::owner(FileOwner) const
-{
- return QString();
-}
-
-QDateTime QResourceFileEngine::fileTime(FileTime time) const
+QDateTime QResourceFileEngine::fileTime(QFile::FileTime time) const
{
Q_D(const QResourceFileEngine);
- if (time == ModificationTime)
+ if (time == QFile::FileModificationTime)
return d->resource.lastModified();
return QDateTime();
}
@@ -1691,31 +1582,24 @@ QDateTime QResourceFileEngine::fileTime(FileTime time) const
/*!
\internal
*/
-QAbstractFileEngine::Iterator *QResourceFileEngine::beginEntryList(QDir::Filters filters,
- const QStringList &filterNames)
+QAbstractFileEngine::IteratorUniquePtr
+QResourceFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames)
{
- return new QResourceFileEngineIterator(filters, filterNames);
-}
-
-/*!
- \internal
-*/
-QAbstractFileEngine::Iterator *QResourceFileEngine::endEntryList()
-{
- return nullptr;
+ return std::make_unique<QResourceFileEngineIterator>(path, filters, filterNames);
}
bool QResourceFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
{
Q_D(QResourceFileEngine);
if (extension == MapExtension) {
- const MapExtensionOption *options = (const MapExtensionOption*)(option);
- MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
+ const auto *options = static_cast<const MapExtensionOption *>(option);
+ auto *returnValue = static_cast<MapExtensionReturn *>(output);
returnValue->address = d->map(options->offset, options->size, options->flags);
return (returnValue->address != nullptr);
}
if (extension == UnMapExtension) {
- const UnMapExtensionOption *options = (const UnMapExtensionOption*)option;
+ const auto *options = static_cast<const UnMapExtensionOption *>(option);
return d->unmap(options->address);
}
return false;
@@ -1729,21 +1613,27 @@ bool QResourceFileEngine::supportsExtension(Extension extension) const
uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
{
Q_Q(QResourceFileEngine);
- Q_UNUSED(flags);
+ Q_ASSERT_X(resource.compressionAlgorithm() == QResource::NoCompression
+ || !uncompressed.isNull(), "QFile::map()",
+ "open() should have uncompressed compressed resources");
qint64 max = resource.uncompressedSize();
qint64 end;
if (offset < 0 || size <= 0 || !resource.isValid() ||
- add_overflow(offset, size, &end) || end > max) {
+ qAddOverflow(offset, size, &end) || end > max) {
q->setError(QFile::UnspecifiedError, QString());
return nullptr;
}
- const uchar *address = resource.data();
- if (resource.compressionAlgorithm() != QResource::NoCompression) {
- uncompress();
- if (uncompressed.isNull())
- return nullptr;
+ const uchar *address = reinterpret_cast<const uchar *>(uncompressed.constBegin());
+ if (!uncompressed.isNull())
+ return const_cast<uchar *>(address) + offset;
+
+ // resource was not compressed
+ address = resource.data();
+ if (flags & QFile::MapPrivateOption) {
+ // We need to provide read-write memory
+ mapUncompressed();
address = reinterpret_cast<const uchar *>(uncompressed.constData());
}
@@ -1764,6 +1654,131 @@ void QResourceFileEnginePrivate::uncompress() const
uncompressed = resource.uncompressedData();
}
+void QResourceFileEnginePrivate::mapUncompressed()
+{
+ Q_ASSERT(resource.compressionAlgorithm() == QResource::NoCompression);
+ if (!uncompressed.isNull())
+ return; // nothing to do
+
+ if (resource.uncompressedSize() >= RemapCompressedThreshold) {
+ if (mapUncompressed_sys())
+ return;
+ }
+
+ uncompressed = resource.uncompressedData();
+ uncompressed.detach();
+}
+
+#if defined(MREMAP_MAYMOVE) && defined(MREMAP_DONTUNMAP)
+inline bool QResourcePrivate::mayRemapData(const QResource &resource)
+{
+ auto d = resource.d_func();
+
+ // assumptions from load():
+ // - d->related is not empty
+ // - the first item in d->related is the one with our data
+ // by current construction, it's also the only item
+ const QResourceRoot *root = d->related.at(0);
+
+ switch (root->type()) {
+ case QResourceRoot::Resource_Builtin:
+ return true; // always acceptable, memory is read-only
+ case QResourceRoot::Resource_Buffer:
+ return false; // never acceptable, memory is heap
+ case QResourceRoot::Resource_File:
+ break;
+ }
+
+ auto df = static_cast<const QDynamicFileResourceRoot *>(root);
+ return df->wasMemoryMapped();
+}
+#endif
+
+// Returns the page boundaries of where \a location is located in memory.
+static auto mappingBoundaries(const void *location, qsizetype size)
+{
+#ifdef Q_OS_WIN
+ auto getpagesize = [] {
+ SYSTEM_INFO sysinfo;
+ ::GetSystemInfo(&sysinfo);
+ return sysinfo.dwAllocationGranularity;
+ };
+#endif
+ struct R {
+ void *begin;
+ qsizetype size;
+ qptrdiff offset;
+ } r;
+
+ const quintptr pageMask = getpagesize() - 1;
+ quintptr data = quintptr(location);
+ quintptr begin = data & ~pageMask;
+ quintptr end = (data + size + pageMask) & ~pageMask;
+ r.begin = reinterpret_cast<void *>(begin);
+ r.size = end - begin;
+ r.offset = data & pageMask;
+ return r;
+}
+
+bool QResourceFileEnginePrivate::mapUncompressed_sys()
+{
+ auto r = mappingBoundaries(resource.data(), resource.uncompressedSize());
+ void *ptr = nullptr;
+
+#if defined(MREMAP_MAYMOVE) && defined(MREMAP_DONTUNMAP)
+ // Use MREMAP_MAYMOVE to tell the kernel to give us a new address and use
+ // MREMAP_DONTUNMAP (supported since kernel 5.7) to request that it create
+ // a new mapping of the same pages, instead of moving. We can only do that
+ // for pages that are read-only, otherwise the kernel replaces the source
+ // with pages full of nulls.
+ if (!QResourcePrivate::mayRemapData(resource))
+ return false;
+
+ ptr = mremap(r.begin, r.size, r.size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP);
+ if (ptr == MAP_FAILED)
+ return false;
+
+ // Allow writing, which the documentation says we allow. This is safe
+ // because MREMAP_DONTUNMAP only works for private mappings.
+ if (mprotect(ptr, r.size, PROT_READ | PROT_WRITE) != 0) {
+ munmap(ptr, r.size);
+ return false;
+ }
+#elif defined(Q_OS_DARWIN)
+ mach_port_t self = mach_task_self();
+ vm_address_t addr = 0;
+ vm_address_t mask = 0;
+ bool anywhere = true;
+ bool copy = true;
+ vm_prot_t cur_prot = VM_PROT_READ | VM_PROT_WRITE;
+ vm_prot_t max_prot = VM_PROT_ALL;
+ kern_return_t res = vm_remap(self, &addr, r.size, mask, anywhere,
+ self, vm_address_t(r.begin), copy, &cur_prot,
+ &max_prot, VM_INHERIT_DEFAULT);
+ if (res != KERN_SUCCESS)
+ return false;
+
+ ptr = reinterpret_cast<void *>(addr);
+ if ((max_prot & VM_PROT_WRITE) == 0 || mprotect(ptr, r.size, PROT_READ | PROT_WRITE) != 0) {
+ munmap(ptr, r.size);
+ return false;
+ }
+#endif
+
+ if (!ptr)
+ return false;
+ const char *newdata = static_cast<char *>(ptr) + r.offset;
+ uncompressed = QByteArray::fromRawData(newdata, resource.uncompressedSize());
+ mustUnmap = true;
+ return true;
+}
+
+void QResourceFileEnginePrivate::unmapUncompressed_sys()
+{
+ auto r = mappingBoundaries(uncompressed.constBegin(), uncompressed.size());
+ QDynamicFileResourceRoot::unmap_sys(r.begin, r.size);
+}
+
#endif // !defined(QT_BOOTSTRAPPED)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
index 52b0d74d29..ca968b5180 100644
--- a/src/corelib/io/qresource.h
+++ b/src/corelib/io/qresource.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRESOURCE_H
#define QRESOURCE_H
@@ -61,7 +25,7 @@ public:
ZstdCompression
};
- QResource(const QString &file=QString(), const QLocale &locale=QLocale());
+ QResource(const QString &file = QString(), const QLocale &locale = QLocale());
~QResource();
void setFileName(const QString &file);
@@ -80,17 +44,6 @@ public:
QByteArray uncompressedData() const;
QDateTime lastModified() const;
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QDir::addSearchPath() instead")
- static void addSearchPath(const QString &path);
- QT_DEPRECATED_X("Use QDir::searchPaths() instead")
- static QStringList searchPaths();
-#endif
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_VERSION_X_5_15("Use QResource::compressionAlgorithm() instead")
- bool isCompressed() const;
-#endif
-
static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString());
static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString());
diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp
index 29a9e22294..abb61d3b46 100644
--- a/src/corelib/io/qresource_iterator.cpp
+++ b/src/corelib/io/qresource_iterator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qresource.h"
#include "qresource_iterator_p.h"
@@ -44,9 +8,10 @@
QT_BEGIN_NAMESPACE
-QResourceFileEngineIterator::QResourceFileEngineIterator(QDir::Filters filters,
+QResourceFileEngineIterator::QResourceFileEngineIterator(const QString &path, QDir::Filters filters,
const QStringList &filterNames)
- : QAbstractFileEngineIterator(filters, filterNames), index(-1)
+ : QAbstractFileEngineIterator(path, filters, filterNames),
+ index(-1)
{
}
@@ -54,15 +19,7 @@ QResourceFileEngineIterator::~QResourceFileEngineIterator()
{
}
-QString QResourceFileEngineIterator::next()
-{
- if (!hasNext())
- return QString();
- ++index;
- return currentFilePath();
-}
-
-bool QResourceFileEngineIterator::hasNext() const
+bool QResourceFileEngineIterator::advance()
{
if (index == -1) {
// Lazy initialization of the iterator
@@ -70,19 +27,34 @@ bool QResourceFileEngineIterator::hasNext() const
if (!resource.isValid())
return false;
- // Initialize and move to the next entry.
+ // Initialize and move to the first entry.
entries = resource.children();
+ if (entries.isEmpty())
+ return false;
+
index = 0;
+ return true;
}
- return index < entries.size();
+ if (index < entries.size() - 1) {
+ ++index;
+ return true;
+ }
+
+ return false;
}
QString QResourceFileEngineIterator::currentFileName() const
{
- if (index <= 0 || index > entries.size())
+ if (index < 0 || index > entries.size())
return QString();
- return entries.at(index - 1);
+ return entries.at(index);
+}
+
+QFileInfo QResourceFileEngineIterator::currentFileInfo() const
+{
+ m_fileInfo = QFileInfo(currentFilePath());
+ return m_fileInfo;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h
index 207a88b0ba..bcbbc46b51 100644
--- a/src/corelib/io/qresource_iterator_p.h
+++ b/src/corelib/io/qresource_iterator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRESOURCE_ITERATOR_P_H
#define QRESOURCE_ITERATOR_P_H
@@ -60,13 +24,14 @@ class QResourceFileEngineIteratorPrivate;
class QResourceFileEngineIterator : public QAbstractFileEngineIterator
{
public:
- QResourceFileEngineIterator(QDir::Filters filters, const QStringList &filterNames);
+ QResourceFileEngineIterator(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames);
~QResourceFileEngineIterator();
- QString next() override;
- bool hasNext() const override;
+ bool advance() override;
QString currentFileName() const override;
+ QFileInfo currentFileInfo() const override;
private:
mutable QStringList entries;
diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h
index fedf95bb33..37fddd7a41 100644
--- a/src/corelib/io/qresource_p.h
+++ b/src/corelib/io/qresource_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRESOURCE_P_H
#define QRESOURCE_P_H
@@ -66,7 +30,7 @@ public:
void setFileName(const QString &file) override;
- bool open(QIODevice::OpenMode flags) override;
+ bool open(QIODevice::OpenMode flags, std::optional<QFile::Permissions> permissions) override;
bool close() override;
bool flush() override;
qint64 size() const override;
@@ -74,39 +38,19 @@ public:
virtual bool atEnd() const;
bool seek(qint64) override;
qint64 read(char *data, qint64 maxlen) override;
- qint64 write(const char *data, qint64 len) override;
-
- bool remove() override;
- bool copy(const QString &newName) override;
- bool rename(const QString &newName) override;
- bool link(const QString &newName) override;
-
- bool isSequential() const override;
-
- bool isRelativePath() const override;
-
- bool mkdir(const QString &dirName, bool createParentDirectories) const override;
- bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
-
- bool setSize(qint64 size) override;
-
- QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
bool caseSensitive() const override;
FileFlags fileFlags(FileFlags type) const override;
- bool setPermissions(uint perms) override;
-
QString fileName(QAbstractFileEngine::FileName file) const override;
uint ownerId(FileOwner) const override;
- QString owner(FileOwner) const override;
- QDateTime fileTime(FileTime time) const override;
+ QDateTime fileTime(QFile::FileTime time) const override;
- Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
- Iterator *endEntryList() override;
+ IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters,
+ const QStringList &filterNames) override;
bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr) override;
bool supportsExtension(Extension extension) const override;
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp
index 067ccda3df..cc59bb3725 100644
--- a/src/corelib/io/qsavefile.cpp
+++ b/src/corelib/io/qsavefile.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2012 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsavefile.h"
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
#include "qplatformdefs.h"
#include "private/qsavefile_p.h"
@@ -55,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QSaveFilePrivate::QSaveFilePrivate()
: writeError(QFileDevice::NoError),
useTemporaryFile(true),
@@ -147,10 +113,10 @@ QSaveFile::QSaveFile(const QString &name, QObject *parent)
QSaveFile::~QSaveFile()
{
Q_D(QSaveFile);
- QFileDevice::close();
- if (d->fileEngine) {
+ if (isOpen()) {
+ QFileDevice::close();
+ Q_ASSERT(d->fileEngine);
d->fileEngine->remove();
- d->fileEngine.reset();
}
}
@@ -186,7 +152,7 @@ void QSaveFile::setFileName(const QString &name)
QIODevice::ReadWrite, QIODevice::Append, QIODevice::NewOnly and
QIODevice::ExistingOnly are not supported at the moment.
- \sa QIODevice::OpenMode, setFileName()
+ \sa QIODevice::OpenMode, setFileName(), QT_USE_NODISCARD_FILE_OPEN
*/
bool QSaveFile::open(OpenMode mode)
{
@@ -204,7 +170,7 @@ bool QSaveFile::open(OpenMode mode)
// In the future we could implement ReadWrite by copying from the existing file to the temp file...
// The implications of NewOnly and ExistingOnly when used with QSaveFile need to be considered carefully...
if (mode & (ReadOnly | Append | NewOnly | ExistingOnly)) {
- qWarning("QSaveFile::open: Unsupported open mode 0x%x", int(mode));
+ qWarning("QSaveFile::open: Unsupported open mode 0x%x", uint(mode.toInt()));
return false;
}
@@ -234,7 +200,7 @@ bool QSaveFile::open(OpenMode mode)
}
auto openDirectly = [&]() {
- d->fileEngine.reset(QAbstractFileEngine::create(d->finalFileName));
+ d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
d->useTemporaryFile = false;
QFileDevice::open(mode);
@@ -246,10 +212,10 @@ bool QSaveFile::open(OpenMode mode)
bool requiresDirectWrite = false;
#ifdef Q_OS_WIN
// check if it is an Alternate Data Stream
- requiresDirectWrite = d->finalFileName == d->fileName && d->fileName.indexOf(QLatin1Char(':'), 2) > 1;
+ requiresDirectWrite = d->finalFileName == d->fileName && d->fileName.indexOf(u':', 2) > 1;
#elif defined(Q_OS_ANDROID)
// check if it is a content:// URL
- requiresDirectWrite = d->fileName.startsWith(QLatin1String("content://"));
+ requiresDirectWrite = d->fileName.startsWith("content://"_L1);
#endif
if (requiresDirectWrite) {
// yes, we can't rename onto it...
@@ -332,7 +298,7 @@ bool QSaveFile::commit()
}
QFileDevice::close(); // calls flush()
- const auto fe = std::move(d->fileEngine);
+ const auto &fe = d->fileEngine;
// Sync to disk if possible. Ignore errors (e.g. not supported).
fe->syncToDisk();
@@ -446,4 +412,4 @@ QT_END_NAMESPACE
#include "moc_qsavefile.cpp"
#endif
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
diff --git a/src/corelib/io/qsavefile.h b/src/corelib/io/qsavefile.h
index 200068d30d..4dd712d4b6 100644
--- a/src/corelib/io/qsavefile.h
+++ b/src/corelib/io/qsavefile.h
@@ -1,48 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2012 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSAVEFILE_H
#define QSAVEFILE_H
#include <QtCore/qglobal.h>
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
#include <QtCore/qfiledevice.h>
#include <QtCore/qstring.h>
@@ -75,7 +39,7 @@ public:
QString fileName() const override;
void setFileName(const QString &name);
- bool open(OpenMode flags) override;
+ QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override;
bool commit();
void cancelWriting();
@@ -98,6 +62,6 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
#endif // QSAVEFILE_H
diff --git a/src/corelib/io/qsavefile_p.h b/src/corelib/io/qsavefile_p.h
index 3f81df9ae2..4d0f40fbb0 100644
--- a/src/corelib/io/qsavefile_p.h
+++ b/src/corelib/io/qsavefile_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSAVEFILE_P_H
#define QSAVEFILE_P_H
@@ -53,7 +17,7 @@
#include <QtCore/qglobal.h>
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
#include "private/qfiledevice_p.h"
@@ -78,6 +42,6 @@ protected:
QT_END_NAMESPACE
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
#endif // QSAVEFILE_P_H
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index b9bb237544..6934ca4404 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qdebug.h>
#include "qplatformdefs.h"
@@ -48,11 +12,12 @@
#include "qfileinfo.h"
#include "qmutex.h"
#include "private/qlocking_p.h"
+#include "private/qtools_p.h"
#include "qlibraryinfo.h"
#include "qtemporaryfile.h"
#include "qstandardpaths.h"
#include <qdatastream.h>
-#include <qstringconverter.h>
+#include "private/qstringconverter_p.h"
#ifndef QT_NO_GEOM_VARIANT
#include "qsize.h"
@@ -60,9 +25,7 @@
#include "qrect.h"
#endif // !QT_NO_GEOM_VARIANT
-#ifndef QT_BUILD_QMAKE
-# include "qcoreapplication.h"
-#endif
+#include "qcoreapplication.h"
#ifndef QT_BOOTSTRAPPED
#include "qsavefile.h"
@@ -81,12 +44,13 @@
# include <shlobj.h>
#endif
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID)
#define Q_XDG_PLATFORM
#endif
-#if !defined(QT_NO_STANDARDPATHS) && (defined(Q_XDG_PLATFORM) || defined(QT_PLATFORM_UIKIT))
-#define QSETTINGS_USE_QSTANDARDPATHS
+#if !defined(QT_NO_STANDARDPATHS) \
+ && (defined(Q_XDG_PLATFORM) || defined(QT_PLATFORM_UIKIT) || defined(Q_OS_ANDROID))
+# define QSETTINGS_USE_QSTANDARDPATHS
#endif
// ************************************************************************
@@ -101,6 +65,9 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
struct QConfFileCustomFormat
{
QString extension;
@@ -108,7 +75,7 @@ struct QConfFileCustomFormat
QSettings::WriteFunc writeFunc;
Qt::CaseSensitivity caseSensitivity;
};
-Q_DECLARE_TYPEINFO(QConfFileCustomFormat, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QConfFileCustomFormat, Q_RELOCATABLE_TYPE);
typedef QHash<QString, QConfFile *> ConfFileHash;
typedef QCache<QString, QConfFile> ConfFileCache;
@@ -131,9 +98,9 @@ Q_GLOBAL_STATIC(ConfFileCache, unusedCacheFunc)
Q_GLOBAL_STATIC(PathHash, pathHashFunc)
Q_GLOBAL_STATIC(CustomFormatVector, customFormatVectorFunc)
-static QBasicMutex settingsGlobalMutex;
+Q_CONSTINIT static QBasicMutex settingsGlobalMutex;
-static QSettings::Format globalDefaultFormat = QSettings::NativeFormat;
+Q_CONSTINIT static QSettings::Format globalDefaultFormat = QSettings::NativeFormat;
QConfFile::QConfFile(const QString &fileName, bool _userPerms)
: name(fileName), size(0), ref(1), userPerms(_userPerms)
@@ -150,11 +117,10 @@ QConfFile::~QConfFile()
ParsedSettingsMap QConfFile::mergedKeyMap() const
{
ParsedSettingsMap result = originalKeys;
- ParsedSettingsMap::const_iterator i;
- for (i = removedKeys.begin(); i != removedKeys.end(); ++i)
+ for (auto i = removedKeys.begin(); i != removedKeys.end(); ++i)
result.remove(i.key());
- for (i = addedKeys.begin(); i != addedKeys.end(); ++i)
+ for (auto i = addedKeys.begin(); i != addedKeys.end(); ++i)
result.insert(i.key(), i.value());
return result;
}
@@ -163,12 +129,12 @@ bool QConfFile::isWritable() const
{
QFileInfo fileInfo(name);
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
if (fileInfo.exists()) {
#endif
QFile file(name);
return file.open(QFile::ReadWrite);
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
} else {
// Create the directories to the file.
QDir dir(fileInfo.absolutePath());
@@ -231,13 +197,30 @@ QSettingsPrivate::~QSettingsPrivate()
{
}
-QString QSettingsPrivate::actualKey(const QString &key) const
+QString QSettingsPrivate::actualKey(QAnyStringView key) const
{
- QString n = normalizedKey(key);
+ auto n = normalizedKey(key);
Q_ASSERT_X(!n.isEmpty(), "QSettings", "empty key");
return groupPrefix + n;
}
+namespace {
+ // ### this needs some public API (QStringConverter?)
+ QChar *write(QChar *out, QUtf8StringView v)
+ {
+ return QUtf8::convertToUnicode(out, QByteArrayView(v));
+ }
+ QChar *write(QChar *out, QLatin1StringView v)
+ {
+ return QLatin1::convertToUnicode(out, v);
+ }
+ QChar *write(QChar *out, QStringView v)
+ {
+ memcpy(out, v.data(), v.size() * sizeof(QChar));
+ return out + v.size();
+ }
+}
+
/*
Returns a string that never starts nor ends with a slash (or an
empty string). Examples:
@@ -245,38 +228,49 @@ QString QSettingsPrivate::actualKey(const QString &key) const
"foo" becomes "foo"
"/foo//bar///" becomes "foo/bar"
"///" becomes ""
-
- This function is optimized to avoid a QString deep copy in the
- common case where the key is already normalized.
*/
-QString QSettingsPrivate::normalizedKey(const QString &key)
+QString QSettingsPrivate::normalizedKey(QAnyStringView key)
{
- QString result = key;
+ QString result(key.size(), Qt::Uninitialized);
+ auto out = const_cast<QChar*>(result.constData()); // don't detach
- int i = 0;
- while (i < result.size()) {
- while (result.at(i) == QLatin1Char('/')) {
- result.remove(i, 1);
- if (i == result.size())
- goto after_loop;
- }
- while (result.at(i) != QLatin1Char('/')) {
- ++i;
- if (i == result.size())
- return result;
+ const bool maybeEndsInSlash = key.visit([&out](auto key) {
+ using View = decltype(key);
+
+ auto it = key.begin();
+ const auto end = key.end();
+
+ while (it != end) {
+ while (*it == u'/') {
+ ++it;
+ if (it == end)
+ return true;
+ }
+ auto mark = it;
+ while (*it != u'/') {
+ ++it;
+ if (it == end)
+ break;
+ }
+ out = write(out, View{mark, it});
+ if (it == end)
+ return false;
+ Q_ASSERT(*it == u'/');
+ *out++ = u'/';
+ ++it;
}
- ++i; // leave the slash alone
- }
+ return true;
+ });
-after_loop:
- if (!result.isEmpty())
- result.truncate(i - 1); // remove the trailing slash
+ if (maybeEndsInSlash && out != result.constData())
+ --out; // remove the trailing slash
+ result.truncate(out - result.constData());
return result;
}
// see also qsettings_win.cpp and qsettings_mac.cpp
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_WASM)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) && !defined(Q_OS_WASM)
QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
const QString &organization, const QString &application)
{
@@ -294,7 +288,7 @@ QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::F
void QSettingsPrivate::processChild(QStringView key, ChildSpec spec, QStringList &result)
{
if (spec != AllKeys) {
- int slashPos = key.indexOf(QLatin1Char('/'));
+ qsizetype slashPos = key.indexOf(u'/');
if (slashPos == -1) {
if (spec != ChildKeys)
return;
@@ -312,7 +306,7 @@ void QSettingsPrivate::beginGroupOrArray(const QSettingsGroup &group)
groupStack.push(group);
const QString name = group.name();
if (!name.isEmpty())
- groupPrefix += name + QLatin1Char('/');
+ groupPrefix += name + u'/';
}
/*
@@ -348,30 +342,27 @@ void QSettingsPrivate::requestUpdate()
QStringList QSettingsPrivate::variantListToStringList(const QVariantList &l)
{
QStringList result;
- result.reserve(l.count());
- QVariantList::const_iterator it = l.constBegin();
- for (; it != l.constEnd(); ++it)
- result.append(variantToString(*it));
+ result.reserve(l.size());
+ for (auto v : l)
+ result.append(variantToString(v));
return result;
}
QVariant QSettingsPrivate::stringListToVariantList(const QStringList &l)
{
QStringList outStringList = l;
- for (int i = 0; i < outStringList.count(); ++i) {
+ for (qsizetype i = 0; i < outStringList.size(); ++i) {
const QString &str = outStringList.at(i);
- if (str.startsWith(QLatin1Char('@'))) {
- if (str.length() >= 2 && str.at(1) == QLatin1Char('@')) {
- outStringList[i].remove(0, 1);
- } else {
+ if (str.startsWith(u'@')) {
+ if (str.size() < 2 || str.at(1) != u'@') {
QVariantList variantList;
- const int stringCount = l.count();
- variantList.reserve(stringCount);
- for (int j = 0; j < stringCount; ++j)
- variantList.append(stringToVariant(l.at(j)));
+ variantList.reserve(l.size());
+ for (const auto &s : l)
+ variantList.append(stringToVariant(s));
return variantList;
}
+ outStringList[i].remove(0, 1);
}
}
return outStringList;
@@ -381,16 +372,14 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
{
QString result;
- switch (v.userType()) {
+ switch (v.metaType().id()) {
case QMetaType::UnknownType:
- result = QLatin1String("@Invalid()");
+ result = "@Invalid()"_L1;
break;
case QMetaType::QByteArray: {
QByteArray a = v.toByteArray();
- result = QLatin1String("@ByteArray(")
- + QLatin1String(a.constData(), a.size())
- + QLatin1Char(')');
+ result = "@ByteArray("_L1 + QLatin1StringView(a) + u')';
break;
}
@@ -403,12 +392,13 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
case QMetaType::Int:
case QMetaType::UInt:
case QMetaType::Bool:
+ case QMetaType::Float:
case QMetaType::Double: {
result = v.toString();
if (result.contains(QChar::Null))
- result = QLatin1String("@String(") + result + QLatin1Char(')');
- else if (result.startsWith(QLatin1Char('@')))
- result.prepend(QLatin1Char('@'));
+ result = "@String("_L1 + result + u')';
+ else if (result.startsWith(u'@'))
+ result.prepend(u'@');
break;
}
#ifndef QT_NO_GEOM_VARIANT
@@ -447,9 +437,9 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
s << v;
}
- result = QLatin1String(typeSpec)
- + QLatin1String(a.constData(), a.size())
- + QLatin1Char(')');
+ result = QLatin1StringView(typeSpec)
+ + QLatin1StringView(a.constData(), a.size())
+ + u')';
#else
Q_ASSERT(!"QSettings: Cannot save custom types without QDataStream support");
#endif
@@ -463,25 +453,25 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
QVariant QSettingsPrivate::stringToVariant(const QString &s)
{
- if (s.startsWith(QLatin1Char('@'))) {
- if (s.endsWith(QLatin1Char(')'))) {
- if (s.startsWith(QLatin1String("@ByteArray("))) {
- return QVariant(QStringView{s}.mid(11, s.size() - 12).toLatin1());
- } else if (s.startsWith(QLatin1String("@String("))) {
- return QVariant(QStringView{s}.mid(8, s.size() - 9).toString());
- } else if (s.startsWith(QLatin1String("@Variant("))
- || s.startsWith(QLatin1String("@DateTime("))) {
+ if (s.startsWith(u'@')) {
+ if (s.endsWith(u')')) {
+ if (s.startsWith("@ByteArray("_L1)) {
+ return QVariant(QStringView{s}.sliced(11).chopped(1).toLatin1());
+ } else if (s.startsWith("@String("_L1)) {
+ return QVariant(QStringView{s}.sliced(8).chopped(1).toString());
+ } else if (s.startsWith("@Variant("_L1)
+ || s.startsWith("@DateTime("_L1)) {
#ifndef QT_NO_DATASTREAM
QDataStream::Version version;
int offset;
- if (s.at(1) == QLatin1Char('D')) {
+ if (s.at(1) == u'D') {
version = QDataStream::Qt_5_6;
offset = 10;
} else {
version = QDataStream::Qt_4_0;
offset = 9;
}
- QByteArray a = QStringView{s}.mid(offset).toLatin1();
+ QByteArray a = QStringView{s}.sliced(offset).toLatin1();
QDataStream stream(&a, QIODevice::ReadOnly);
stream.setVersion(version);
QVariant result;
@@ -491,53 +481,50 @@ QVariant QSettingsPrivate::stringToVariant(const QString &s)
Q_ASSERT(!"QSettings: Cannot load custom types without QDataStream support");
#endif
#ifndef QT_NO_GEOM_VARIANT
- } else if (s.startsWith(QLatin1String("@Rect("))) {
+ } else if (s.startsWith("@Rect("_L1)) {
QStringList args = QSettingsPrivate::splitArgs(s, 5);
if (args.size() == 4)
return QVariant(QRect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()));
- } else if (s.startsWith(QLatin1String("@Size("))) {
+ } else if (s.startsWith("@Size("_L1)) {
QStringList args = QSettingsPrivate::splitArgs(s, 5);
if (args.size() == 2)
return QVariant(QSize(args[0].toInt(), args[1].toInt()));
- } else if (s.startsWith(QLatin1String("@Point("))) {
+ } else if (s.startsWith("@Point("_L1)) {
QStringList args = QSettingsPrivate::splitArgs(s, 6);
if (args.size() == 2)
return QVariant(QPoint(args[0].toInt(), args[1].toInt()));
#endif
- } else if (s == QLatin1String("@Invalid()")) {
+ } else if (s == "@Invalid()"_L1) {
return QVariant();
}
}
- if (s.startsWith(QLatin1String("@@")))
- return QVariant(s.mid(1));
+ if (s.startsWith("@@"_L1))
+ return QVariant(s.sliced(1));
}
return QVariant(s);
}
-static const char hexDigits[] = "0123456789ABCDEF";
-
void QSettingsPrivate::iniEscapedKey(const QString &key, QByteArray &result)
{
- result.reserve(result.length() + key.length() * 3 / 2);
- for (int i = 0; i < key.size(); ++i) {
+ result.reserve(result.size() + key.size() * 3 / 2);
+ for (qsizetype i = 0; i < key.size(); ++i) {
uint ch = key.at(i).unicode();
if (ch == '/') {
result += '\\';
- } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')
- || ch == '_' || ch == '-' || ch == '.') {
+ } else if (isAsciiLetterOrNumber(ch) || ch == '_' || ch == '-' || ch == '.') {
result += (char)ch;
} else if (ch <= 0xFF) {
result += '%';
- result += hexDigits[ch / 16];
- result += hexDigits[ch % 16];
+ result += QtMiscUtils::toHexUpper(ch / 16);
+ result += QtMiscUtils::toHexUpper(ch % 16);
} else {
result += "%U";
QByteArray hexCode;
- for (int i = 0; i < 4; ++i) {
- hexCode.prepend(hexDigits[ch % 16]);
+ for (int j = 0; j < 4; ++j) {
+ hexCode.prepend(QtMiscUtils::toHexUpper(ch % 16));
ch >>= 4;
}
result += hexCode;
@@ -545,49 +532,50 @@ void QSettingsPrivate::iniEscapedKey(const QString &key, QByteArray &result)
}
}
-bool QSettingsPrivate::iniUnescapedKey(const QByteArray &key, int from, int to, QString &result)
+bool QSettingsPrivate::iniUnescapedKey(QByteArrayView key, QString &result)
{
+ const QString decoded = QString::fromUtf8(key);
+ const qsizetype size = decoded.size();
+ result.reserve(result.size() + size);
+ qsizetype i = 0;
bool lowercaseOnly = true;
- int i = from;
- result.reserve(result.length() + (to - from));
- while (i < to) {
- char16_t ch = (uchar)key.at(i);
+ while (i < size) {
+ char16_t ch = decoded.at(i).unicode();
if (ch == '\\') {
- result += QLatin1Char('/');
+ result += u'/';
++i;
continue;
}
- if (ch != '%' || i == to - 1) {
- if (uint(ch - 'A') <= 'Z' - 'A') // only for ASCII
+ if (ch != '%' || i == size - 1) {
+ QChar qch(ch);
+ if (qch.isUpper())
lowercaseOnly = false;
- result += ch;
+ result += qch;
++i;
continue;
}
int numDigits = 2;
- int firstDigitPos = i + 1;
+ qsizetype firstDigitPos = i + 1;
- ch = key.at(i + 1);
+ ch = decoded.at(i + 1).unicode();
if (ch == 'U') {
++firstDigitPos;
numDigits = 4;
}
- if (firstDigitPos + numDigits > to) {
- result += QLatin1Char('%');
- // ### missing U
+ if (firstDigitPos + numDigits > size) {
+ result += u'%';
++i;
continue;
}
bool ok;
- ch = key.mid(firstDigitPos, numDigits).toUShort(&ok, 16);
+ ch = QStringView(decoded).sliced(firstDigitPos, numDigits).toUShort(&ok, 16);
if (!ok) {
- result += QLatin1Char('%');
- // ### missing U
+ result += u'%';
++i;
continue;
}
@@ -605,25 +593,20 @@ void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result)
{
bool needsQuotes = false;
bool escapeNextIfDigit = false;
- bool useCodec = !str.startsWith(QLatin1String("@ByteArray("))
- && !str.startsWith(QLatin1String("@Variant("));
-
- int i;
- int startPos = result.size();
+ const bool useCodec = !(str.startsWith("@ByteArray("_L1)
+ || str.startsWith("@Variant("_L1)
+ || str.startsWith("@DateTime("_L1));
+ const qsizetype startPos = result.size();
QStringEncoder toUtf8(QStringEncoder::Utf8);
result.reserve(startPos + str.size() * 3 / 2);
- const QChar *unicode = str.unicode();
- for (i = 0; i < str.size(); ++i) {
- uint ch = unicode[i].unicode();
+ for (QChar qch : str) {
+ uint ch = qch.unicode();
if (ch == ';' || ch == ',' || ch == '=')
needsQuotes = true;
- if (escapeNextIfDigit
- && ((ch >= '0' && ch <= '9')
- || (ch >= 'a' && ch <= 'f')
- || (ch >= 'A' && ch <= 'F'))) {
+ if (escapeNextIfDigit && isHexDigit(ch)) {
result += "\\x" + QByteArray::number(ch, 16);
continue;
}
@@ -667,7 +650,7 @@ void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result)
escapeNextIfDigit = true;
} else if (useCodec) {
// slow
- result += toUtf8(&unicode[i], 1);
+ result += toUtf8(qch);
} else {
result += (char)ch;
}
@@ -682,11 +665,11 @@ void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result)
}
}
-inline static void iniChopTrailingSpaces(QString &str, int limit)
+inline static void iniChopTrailingSpaces(QString &str, qsizetype limit)
{
- int n = str.size() - 1;
+ qsizetype n = str.size() - 1;
QChar ch;
- while (n >= limit && ((ch = str.at(n)) == QLatin1Char(' ') || ch == QLatin1Char('\t')))
+ while (n >= limit && ((ch = str.at(n)) == u' ' || ch == u'\t'))
str.truncate(n--);
}
@@ -703,7 +686,7 @@ void QSettingsPrivate::iniEscapedStringList(const QStringList &strs, QByteArray
*/
result += "@Invalid()";
} else {
- for (int i = 0; i < strs.size(); ++i) {
+ for (qsizetype i = 0; i < strs.size(); ++i) {
if (i != 0)
result += ", ";
iniEscapedString(strs.at(i), result);
@@ -711,7 +694,7 @@ void QSettingsPrivate::iniEscapedStringList(const QStringList &strs, QByteArray
}
}
-bool QSettingsPrivate::iniUnescapedStringList(const QByteArray &str, int from, int to,
+bool QSettingsPrivate::iniUnescapedStringList(QByteArrayView str,
QString &stringResult, QStringList &stringListResult)
{
static const char escapeCodes[][2] =
@@ -733,22 +716,22 @@ bool QSettingsPrivate::iniUnescapedStringList(const QByteArray &str, int from, i
bool inQuotedString = false;
bool currentValueIsQuoted = false;
char16_t escapeVal = 0;
- int i = from;
+ qsizetype i = 0;
char ch;
QStringDecoder fromUtf8(QStringDecoder::Utf8);
StSkipSpaces:
- while (i < to && ((ch = str.at(i)) == ' ' || ch == '\t'))
+ while (i < str.size() && ((ch = str.at(i)) == ' ' || ch == '\t'))
++i;
// fallthrough
StNormal:
- int chopLimit = stringResult.length();
- while (i < to) {
+ qsizetype chopLimit = stringResult.size();
+ while (i < str.size()) {
switch (str.at(i)) {
case '\\':
++i;
- if (i >= to)
+ if (i >= str.size())
goto end;
ch = str.at(i++);
@@ -762,17 +745,17 @@ StNormal:
if (ch == 'x') {
escapeVal = 0;
- if (i >= to)
+ if (i >= str.size())
goto end;
ch = str.at(i);
- if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'))
+ if (isHexDigit(ch))
goto StHexEscape;
- } else if (ch >= '0' && ch <= '7') {
- escapeVal = ch - '0';
+ } else if (const int o = fromOct(ch); o != -1) {
+ escapeVal = o;
goto StOctEscape;
} else if (ch == '\n' || ch == '\r') {
- if (i < to) {
+ if (i < str.size()) {
char ch2 = str.at(i);
// \n, \r, \r\n, and \n\r are legitimate line terminators in INI files
if ((ch2 == '\n' || ch2 == '\r') && ch2 != ch)
@@ -781,7 +764,7 @@ StNormal:
} else {
// the character is skipped
}
- chopLimit = stringResult.length();
+ chopLimit = stringResult.size();
break;
case '"':
++i;
@@ -807,15 +790,15 @@ StNormal:
}
Q_FALLTHROUGH();
default: {
- int j = i + 1;
- while (j < to) {
+ qsizetype j = i + 1;
+ while (j < str.size()) {
ch = str.at(j);
if (ch == '\\' || ch == '"' || ch == ',')
break;
++j;
}
- stringResult += fromUtf8(str.constData() + i, j - i);
+ stringResult += fromUtf8(str.first(j).sliced(i));
i = j;
}
}
@@ -825,17 +808,15 @@ StNormal:
goto end;
StHexEscape:
- if (i >= to) {
+ if (i >= str.size()) {
stringResult += escapeVal;
goto end;
}
ch = str.at(i);
- if (ch >= 'a')
- ch -= 'a' - 'A';
- if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) {
+ if (const int h = fromHex(ch); h != -1) {
escapeVal <<= 4;
- escapeVal += strchr(hexDigits, ch) - hexDigits;
+ escapeVal += h;
++i;
goto StHexEscape;
} else {
@@ -844,15 +825,15 @@ StHexEscape:
}
StOctEscape:
- if (i >= to) {
+ if (i >= str.size()) {
stringResult += escapeVal;
goto end;
}
ch = str.at(i);
- if (ch >= '0' && ch <= '7') {
+ if (const int o = fromOct(ch); o != -1) {
escapeVal <<= 3;
- escapeVal += ch - '0';
+ escapeVal += o;
++i;
goto StOctEscape;
} else {
@@ -866,22 +847,22 @@ end:
return isStringList;
}
-QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
+QStringList QSettingsPrivate::splitArgs(const QString &s, qsizetype idx)
{
- int l = s.length();
+ qsizetype l = s.size();
Q_ASSERT(l > 0);
- Q_ASSERT(s.at(idx) == QLatin1Char('('));
- Q_ASSERT(s.at(l - 1) == QLatin1Char(')'));
+ Q_ASSERT(s.at(idx) == u'(');
+ Q_ASSERT(s.at(l - 1) == u')');
QStringList result;
QString item;
for (++idx; idx < l; ++idx) {
QChar c = s.at(idx);
- if (c == QLatin1Char(')')) {
+ if (c == u')') {
Q_ASSERT(idx == l - 1);
result.append(item);
- } else if (c == QLatin1Char(' ')) {
+ } else if (c == u' ') {
result.append(item);
item.clear();
} else {
@@ -897,20 +878,30 @@ QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
void QConfFileSettingsPrivate::initFormat()
{
- extension = (format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini");
+#if defined(Q_OS_WASM)
+ extension = (format == QSettings::NativeFormat || format == QSettings::WebIndexedDBFormat)
+ ? ".conf"_L1
+ : ".ini"_L1;
+#else
+ extension = (format == QSettings::NativeFormat) ? ".conf"_L1 : ".ini"_L1;
+#endif
readFunc = nullptr;
writeFunc = nullptr;
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
caseSensitivity = (format == QSettings::NativeFormat) ? Qt::CaseSensitive : IniCaseSensitivity;
#else
caseSensitivity = IniCaseSensitivity;
#endif
+#if defined Q_OS_WASM
+ if (format > QSettings::IniFormat && format != QSettings::WebIndexedDBFormat) {
+#else
if (format > QSettings::IniFormat) {
+#endif
const auto locker = qt_scoped_lock(settingsGlobalMutex);
const CustomFormatVector *customFormatVector = customFormatVectorFunc();
- int i = (int)format - (int)QSettings::CustomFormat1;
+ qsizetype i = qsizetype(format) - qsizetype(QSettings::CustomFormat1);
if (i >= 0 && i < customFormatVector->size()) {
QConfFileCustomFormat info = customFormatVector->at(i);
extension = info.extension;
@@ -924,7 +915,11 @@ void QConfFileSettingsPrivate::initFormat()
void QConfFileSettingsPrivate::initAccess()
{
if (!confFiles.isEmpty()) {
+#if defined Q_OS_WASM
+ if (format > QSettings::IniFormat && format != QSettings::WebIndexedDBFormat) {
+#else
if (format > QSettings::IniFormat) {
+#endif
if (!readFunc)
setStatus(QSettings::AccessError);
}
@@ -946,9 +941,9 @@ static QString windowsConfigPath(const KNOWNFOLDERID &type)
if (result.isEmpty()) {
if (type == FOLDERID_ProgramData) {
- result = QLatin1String("C:\\temp\\qt-common");
+ result = "C:\\temp\\qt-common"_L1;
} else if (type == FOLDERID_RoamingAppData) {
- result = QLatin1String("C:\\temp\\qt-user");
+ result = "C:\\temp\\qt-user"_L1;
}
}
@@ -962,26 +957,43 @@ static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope)
}
#ifndef Q_OS_WIN
-static QString make_user_path()
+static constexpr QChar sep = u'/';
+
+#if !defined(QSETTINGS_USE_QSTANDARDPATHS) || defined(Q_OS_ANDROID)
+static QString make_user_path_without_qstandard_paths()
{
- static Q_CONSTEXPR QChar sep = QLatin1Char('/');
-#ifndef QSETTINGS_USE_QSTANDARDPATHS
- // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously
- // for some time now. Moving away from that would require migrating existing settings.
QByteArray env = qgetenv("XDG_CONFIG_HOME");
if (env.isEmpty()) {
- return QDir::homePath() + QLatin1String("/.config/");
+ return QDir::homePath() + "/.config/"_L1;
} else if (env.startsWith('/')) {
return QFile::decodeName(env) + sep;
- } else {
- return QDir::homePath() + sep + QFile::decodeName(env) + sep;
}
+
+ return QDir::homePath() + sep + QFile::decodeName(env) + sep;
+}
+#endif // !QSETTINGS_USE_QSTANDARDPATHS || Q_OS_ANDROID
+
+static QString make_user_path()
+{
+#ifndef QSETTINGS_USE_QSTANDARDPATHS
+ // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously
+ // for some time now. Moving away from that would require migrating existing settings.
+ // The migration has already been done for Android.
+ return make_user_path_without_qstandard_paths();
#else
- // When using a proper XDG platform, use QStandardPaths rather than the above hand-written code;
- // it makes the use of test mode from unit tests possible.
+
+#ifdef Q_OS_ANDROID
+ // If an old settings path exists, use it instead of creating a new one
+ QString ret = make_user_path_without_qstandard_paths();
+ if (QFile(ret).exists())
+ return ret;
+#endif // Q_OS_ANDROID
+
+ // When using a proper XDG platform or Android platform, use QStandardPaths rather than the
+ // above hand-written code. It makes the use of test mode from unit tests possible.
// Ideally all platforms should use this, but see above for the migration issue.
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + sep;
-#endif
+#endif // !QSETTINGS_USE_QSTANDARDPATHS
}
#endif // !Q_OS_WIN
@@ -992,11 +1004,11 @@ static std::unique_lock<QBasicMutex> initDefaultPaths(std::unique_lock<QBasicMut
locker.unlock();
/*
- QLibraryInfo::location() uses QSettings, so in order to
+ QLibraryInfo::path() uses QSettings, so in order to
avoid a dead-lock, we can't hold the global mutex while
calling it.
*/
- QString systemPath = QLibraryInfo::location(QLibraryInfo::SettingsPath) + QLatin1Char('/');
+ QString systemPath = QLibraryInfo::path(QLibraryInfo::SettingsPath) + u'/';
locker.lock();
if (pathHash->isEmpty()) {
@@ -1017,7 +1029,7 @@ static std::unique_lock<QBasicMutex> initDefaultPaths(std::unique_lock<QBasicMut
const QString userPath = make_user_path();
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), Path(userPath, false));
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), Path(systemPath, false));
-#ifndef Q_OS_MAC
+#ifndef Q_OS_DARWIN
pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), Path(userPath, false));
pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), Path(systemPath, false));
#endif
@@ -1029,8 +1041,8 @@ static std::unique_lock<QBasicMutex> initDefaultPaths(std::unique_lock<QBasicMut
static Path getPath(QSettings::Format format, QSettings::Scope scope)
{
- Q_ASSERT((int)QSettings::NativeFormat == 0);
- Q_ASSERT((int)QSettings::IniFormat == 1);
+ Q_ASSERT(int(QSettings::NativeFormat) == 0);
+ Q_ASSERT(int(QSettings::IniFormat) == 1);
auto locker = qt_unique_lock(settingsGlobalMutex);
PathHash *pathHash = pathHashFunc();
@@ -1066,7 +1078,7 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
QString org = organization;
if (org.isEmpty()) {
setStatus(QSettings::AccessError);
- org = QLatin1String("Unknown Organization");
+ org = "Unknown Organization"_L1;
}
QString appFile = org + QDir::separator() + application + extension;
@@ -1093,16 +1105,16 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
QStringList paths;
if (!application.isEmpty()) {
paths.reserve(dirs.size() * 2);
- for (const auto &dir : qAsConst(dirs))
- paths.append(dir + QLatin1Char('/') + appFile);
+ for (const auto &dir : std::as_const(dirs))
+ paths.append(dir + u'/' + appFile);
} else {
paths.reserve(dirs.size());
}
- for (const auto &dir : qAsConst(dirs))
- paths.append(dir + QLatin1Char('/') + orgFile);
+ for (const auto &dir : std::as_const(dirs))
+ paths.append(dir + u'/' + orgFile);
- // Note: No check for existence of files is done intentionaly.
- for (const auto &path : qAsConst(paths))
+ // Note: No check for existence of files is done intentionally.
+ for (const auto &path : std::as_const(paths))
confFiles.append(QConfFile::fromName(path, false));
} else
#endif // Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS
@@ -1112,9 +1124,7 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
confFiles.append(QConfFile::fromName(systemPath.path + orgFile, false));
}
-#ifndef Q_OS_WASM // wasm needs to delay access until after file sync
initAccess();
-#endif
}
QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
@@ -1135,7 +1145,7 @@ QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
ConfFileHash *usedHash = usedHashFunc();
ConfFileCache *unusedCache = unusedCacheFunc();
- for (auto conf_file : qAsConst(confFiles)) {
+ for (auto conf_file : std::as_const(confFiles)) {
if (!conf_file->ref.deref()) {
if (conf_file->size == 0) {
delete conf_file;
@@ -1169,18 +1179,18 @@ void QConfFileSettingsPrivate::remove(const QString &key)
QConfFile *confFile = confFiles.at(0);
QSettingsKey theKey(key, caseSensitivity);
- QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity);
+ QSettingsKey prefix(key + u'/', caseSensitivity);
const auto locker = qt_scoped_lock(confFile->mutex);
ensureSectionParsed(confFile, theKey);
ensureSectionParsed(confFile, prefix);
- ParsedSettingsMap::iterator i = confFile->addedKeys.lowerBound(prefix);
+ auto i = confFile->addedKeys.lowerBound(prefix);
while (i != confFile->addedKeys.end() && i.key().startsWith(prefix))
i = confFile->addedKeys.erase(i);
confFile->addedKeys.remove(theKey);
- ParsedSettingsMap::const_iterator j = const_cast<const ParsedSettingsMap *>(&confFile->originalKeys)->lowerBound(prefix);
+ auto j = const_cast<const ParsedSettingsMap *>(&confFile->originalKeys)->lowerBound(prefix);
while (j != confFile->originalKeys.constEnd() && j.key().startsWith(prefix)) {
confFile->removedKeys.insert(j.key(), QVariant());
++j;
@@ -1203,13 +1213,13 @@ void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
confFile->addedKeys.insert(theKey, value);
}
-bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
+std::optional<QVariant> QConfFileSettingsPrivate::get(const QString &key) const
{
QSettingsKey theKey(key, caseSensitivity);
ParsedSettingsMap::const_iterator j;
bool found = false;
- for (auto confFile : qAsConst(confFiles)) {
+ for (auto confFile : std::as_const(confFiles)) {
const auto locker = qt_scoped_lock(confFile->mutex);
if (!confFile->addedKeys.isEmpty()) {
@@ -1223,26 +1233,22 @@ bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
&& !confFile->removedKeys.contains(theKey));
}
- if (found && value)
- *value = *j;
-
if (found)
- return true;
+ return *j;
if (!fallbacks)
break;
}
- return false;
+ return std::nullopt;
}
QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
{
QStringList result;
- ParsedSettingsMap::const_iterator j;
QSettingsKey thePrefix(prefix, caseSensitivity);
- int startPos = prefix.size();
+ qsizetype startPos = prefix.size();
- for (auto confFile : qAsConst(confFiles)) {
+ for (auto confFile : std::as_const(confFiles)) {
const auto locker = qt_scoped_lock(confFile->mutex);
if (thePrefix.isEmpty())
@@ -1250,18 +1256,18 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
else
ensureSectionParsed(confFile, thePrefix);
- j = const_cast<const ParsedSettingsMap *>(
- &confFile->originalKeys)->lowerBound( thePrefix);
- while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
- if (!confFile->removedKeys.contains(j.key()))
- processChild(QStringView{j.key().originalCaseKey()}.mid(startPos), spec, result);
- ++j;
+ const auto &originalKeys = confFile->originalKeys;
+ auto i = originalKeys.lowerBound(thePrefix);
+ while (i != originalKeys.end() && i.key().startsWith(thePrefix)) {
+ if (!confFile->removedKeys.contains(i.key()))
+ processChild(QStringView{i.key().originalCaseKey()}.sliced(startPos), spec, result);
+ ++i;
}
- j = const_cast<const ParsedSettingsMap *>(
- &confFile->addedKeys)->lowerBound(thePrefix);
- while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
- processChild(QStringView{j.key().originalCaseKey()}.mid(startPos), spec, result);
+ const auto &addedKeys = confFile->addedKeys;
+ auto j = addedKeys.lowerBound(thePrefix);
+ while (j != addedKeys.end() && j.key().startsWith(thePrefix)) {
+ processChild(QStringView{j.key().originalCaseKey()}.sliced(startPos), spec, result);
++j;
}
@@ -1293,7 +1299,7 @@ void QConfFileSettingsPrivate::sync()
// people probably won't be checking the status a whole lot, so in case of
// error we just try to go on and make the best of it
- for (auto confFile : qAsConst(confFiles)) {
+ for (auto confFile : std::as_const(confFiles)) {
const auto locker = qt_scoped_lock(confFile->mutex);
syncConfFile(confFile);
}
@@ -1315,7 +1321,11 @@ QString QConfFileSettingsPrivate::fileName() const
bool QConfFileSettingsPrivate::isWritable() const
{
+#if defined(Q_OS_WASM)
+ if (format > QSettings::IniFormat && format != QSettings::WebIndexedDBFormat && !writeFunc)
+#else
if (format > QSettings::IniFormat && !writeFunc)
+#endif
return false;
if (confFiles.isEmpty())
@@ -1328,13 +1338,13 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
{
bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty();
+ QFileInfo fileInfo(confFile->name);
/*
We can often optimize the read-only case, if the file on disk
hasn't changed.
*/
if (readOnly && confFile->size > 0) {
- QFileInfo fileInfo(confFile->name);
- if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified())
+ if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified(QTimeZone::UTC))
return;
}
@@ -1344,6 +1354,14 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
}
#ifndef QT_BOOTSTRAPPED
+ QString lockFileName = confFile->name + ".lock"_L1;
+
+# if defined(Q_OS_ANDROID) && defined(QSETTINGS_USE_QSTANDARDPATHS)
+ // On android and if it is a content URL put the lock file in a
+ // writable location to prevent permissions issues and invalid paths.
+ if (confFile->name.startsWith("content:"_L1))
+ lockFileName = make_user_path() + QFileInfo(lockFileName).fileName();
+# endif
/*
Use a lockfile in order to protect us against other QSettings instances
trying to write the same settings at the same time.
@@ -1351,7 +1369,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
We only need to lock if we are actually writing as only concurrent writes are a problem.
Concurrent read and write are not a problem because the writing operation is atomic.
*/
- QLockFile lockFile(confFile->name + QLatin1String(".lock"));
+ QLockFile lockFile(lockFileName);
if (!readOnly && !lockFile.lock() && atomicSyncOnly) {
setStatus(QSettings::AccessError);
return;
@@ -1362,13 +1380,13 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
We hold the lock. Let's reread the file if it has changed
since last time we read it.
*/
- QFileInfo fileInfo(confFile->name);
+ fileInfo.refresh();
bool mustReadFile = true;
bool createFile = !fileInfo.exists();
if (!readOnly)
mustReadFile = (confFile->size != fileInfo.size()
- || (confFile->size != 0 && confFile->timeStamp != fileInfo.lastModified()));
+ || (confFile->size != 0 && confFile->timeStamp != fileInfo.lastModified(QTimeZone::UTC)));
if (mustReadFile) {
confFile->unparsedIniSections.clear();
@@ -1386,7 +1404,14 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
*/
if (file.isReadable() && file.size() != 0) {
bool ok = false;
-#ifdef Q_OS_MAC
+
+#ifdef Q_OS_WASM
+ if (format == QSettings::WebIndexedDBFormat) {
+ QByteArray data = file.readAll();
+ ok = readIniFile(data, &confFile->unparsedIniSections);
+ } else
+#endif
+#ifdef Q_OS_DARWIN
if (format == QSettings::NativeFormat) {
QByteArray data = file.readAll();
ok = readPlistFile(data, &confFile->originalKeys);
@@ -1400,7 +1425,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
ok = readFunc(file, tempNewKeys);
if (ok) {
- QSettings::SettingsMap::const_iterator i = tempNewKeys.constBegin();
+ auto i = tempNewKeys.constBegin();
while (i != tempNewKeys.constEnd()) {
confFile->originalKeys.insert(QSettingsKey(i.key(), caseSensitivity),
i.value());
@@ -1414,7 +1439,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
}
confFile->size = fileInfo.size();
- confFile->timeStamp = fileInfo.lastModified();
+ confFile->timeStamp = fileInfo.lastModified(QTimeZone::UTC);
}
/*
@@ -1429,6 +1454,11 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile)
QSaveFile sf(confFile->name);
sf.setDirectWriteFallback(!atomicSyncOnly);
+# ifdef Q_OS_ANDROID
+ // QSaveFile requires direct write when using content scheme URL in Android
+ if (confFile->name.startsWith("content:"_L1))
+ sf.setDirectWriteFallback(true);
+# endif
#else
QFile sf(confFile->name);
#endif
@@ -1437,7 +1467,12 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
return;
}
-#ifdef Q_OS_MAC
+#ifdef Q_OS_WASM
+ if (format == QSettings::WebIndexedDBFormat) {
+ ok = writeIniFile(sf, mergedKeys);
+ } else
+#endif
+#ifdef Q_OS_DARWIN
if (format == QSettings::NativeFormat) {
ok = writePlistFile(sf, mergedKeys);
} else
@@ -1447,7 +1482,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
} else if (writeFunc) {
QSettings::SettingsMap tempOriginalKeys;
- ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
+ auto i = mergedKeys.constBegin();
while (i != mergedKeys.constEnd()) {
tempOriginalKeys.insert(i.key(), i.value());
++i;
@@ -1466,9 +1501,9 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
confFile->addedKeys.clear();
confFile->removedKeys.clear();
- QFileInfo fileInfo(confFile->name);
+ fileInfo.refresh();
confFile->size = fileInfo.size();
- confFile->timeStamp = fileInfo.lastModified();
+ confFile->timeStamp = fileInfo.lastModified(QTimeZone::UTC);
// If we have created the file, apply the file perms
if (createFile) {
@@ -1483,6 +1518,8 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
}
}
+namespace SettingsImpl {
+
enum { Space = 0x1, Special = 0x2 };
static const char charTraits[256] =
@@ -1509,10 +1546,16 @@ static const char charTraits[256] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-bool QConfFileSettingsPrivate::readIniLine(const QByteArray &data, int &dataPos,
- int &lineStart, int &lineLen, int &equalsPos)
+} // namespace SettingsImpl
+
+using SettingsImpl::charTraits;
+
+bool QConfFileSettingsPrivate::readIniLine(QByteArrayView data, qsizetype &dataPos,
+ qsizetype &lineStart, qsizetype &lineLen,
+ qsizetype &equalsPos)
{
- int dataLen = data.length();
+ using namespace SettingsImpl;
+ qsizetype dataLen = data.size();
bool inQuotes = false;
equalsPos = -1;
@@ -1521,7 +1564,7 @@ bool QConfFileSettingsPrivate::readIniLine(const QByteArray &data, int &dataPos,
while (lineStart < dataLen && (charTraits[uint(uchar(data.at(lineStart)))] & Space))
++lineStart;
- int i = lineStart;
+ qsizetype i = lineStart;
while (i < dataLen) {
char ch = data.at(i);
while (!(charTraits[uchar(ch)] & Special)) {
@@ -1580,7 +1623,7 @@ break_out_of_outer_loop:
possible, so if the user doesn't check the status he will get the
most out of the file anyway.
*/
-bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data,
+bool QConfFileSettingsPrivate::readIniFile(QByteArrayView data,
UnparsedSettingsMap *unparsedIniSections)
{
#define FLUSH_CURRENT_SECTION() \
@@ -1590,59 +1633,56 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data,
sectionPosition)]; \
if (!sectionData.isEmpty()) \
sectionData.append('\n'); \
- sectionData += data.mid(currentSectionStart, lineStart - currentSectionStart); \
+ sectionData += data.first(lineStart).sliced(currentSectionStart); \
sectionPosition = ++position; \
}
QString currentSection;
- int currentSectionStart = 0;
- int dataPos = 0;
- int lineStart;
- int lineLen;
- int equalsPos;
- int position = 0;
- int sectionPosition = 0;
+ qsizetype currentSectionStart = 0;
+ qsizetype dataPos = 0;
+ qsizetype lineStart;
+ qsizetype lineLen;
+ qsizetype equalsPos;
+ qsizetype position = 0;
+ qsizetype sectionPosition = 0;
bool ok = true;
- // skip potential utf8 BOM
- const uchar *dd = (const uchar *)data.constData();
- if (data.size() >= 3 && dd[0] == 0xef && dd[1] == 0xbb && dd[2] == 0xbf)
- dataPos = 3;
+ // Skip possible UTF-8 BOM:
+ if (data.startsWith("\xef\xbb\xbf"))
+ data = data.sliced(3);
while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) {
- char ch = data.at(lineStart);
- if (ch == '[') {
+ QByteArrayView line = data.sliced(lineStart, lineLen);
+ if (line.startsWith('[')) {
FLUSH_CURRENT_SECTION();
- // this is a section
- QByteArray iniSection;
- int idx = data.indexOf(']', lineStart);
- if (idx == -1 || idx >= lineStart + lineLen) {
+ // This starts a new section.
+ qsizetype idx = line.indexOf(']');
+ Q_ASSERT(idx == -1 || idx > 0); // line[0] is '[', not ']'.
+ Q_ASSERT(idx < lineLen); // (including -1 < lineLen, if no ']' present.)
+ if (idx < 0) {
ok = false;
- iniSection = data.mid(lineStart + 1, lineLen - 1);
- } else {
- iniSection = data.mid(lineStart + 1, idx - lineStart - 1);
+ idx = lineLen; // so line.first(idx) is just line
}
-
- iniSection = iniSection.trimmed();
+ QByteArrayView iniSection = line.first(idx).sliced(1).trimmed();
if (iniSection.compare("general", Qt::CaseInsensitive) == 0) {
currentSection.clear();
} else {
if (iniSection.compare("%general", Qt::CaseInsensitive) == 0) {
- currentSection = QLatin1String(iniSection.constData() + 1);
+ currentSection = QLatin1StringView(iniSection.constData() + 1, iniSection.size() - 1);
} else {
currentSection.clear();
- iniUnescapedKey(iniSection, 0, iniSection.size(), currentSection);
+ iniUnescapedKey(iniSection, currentSection);
}
- currentSection += QLatin1Char('/');
+ currentSection += u'/';
}
currentSectionStart = dataPos;
}
++position;
}
- Q_ASSERT(lineStart == data.length());
+ Q_ASSERT(lineStart == data.size());
FLUSH_CURRENT_SECTION();
return ok;
@@ -1650,57 +1690,53 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data,
#undef FLUSH_CURRENT_SECTION
}
-bool QConfFileSettingsPrivate::readIniSection(const QSettingsKey &section, const QByteArray &data,
+bool QConfFileSettingsPrivate::readIniSection(const QSettingsKey &section, QByteArrayView data,
ParsedSettingsMap *settingsMap)
{
QStringList strListValue;
bool sectionIsLowercase = (section == section.originalCaseKey());
- int equalsPos;
+ qsizetype equalsPos;
bool ok = true;
- int dataPos = 0;
- int lineStart;
- int lineLen;
- int position = section.originalKeyPosition();
+ qsizetype dataPos = 0;
+ qsizetype lineStart;
+ qsizetype lineLen;
+ qsizetype position = section.originalKeyPosition();
while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) {
- char ch = data.at(lineStart);
- Q_ASSERT(ch != '[');
+ QByteArrayView line = data.sliced(lineStart, lineLen);
+ Q_ASSERT(!line.startsWith('['));
if (equalsPos == -1) {
- if (ch != ';')
+ if (!line.startsWith(';'))
ok = false;
continue;
}
+ // Shift equalPos indexing to be within line, rather than data:
+ equalsPos -= lineStart;
+ // Assured by readIniLine:
+ Q_ASSERT(equalsPos >= 0 && equalsPos < lineLen);
- int keyEnd = equalsPos;
- while (keyEnd > lineStart && ((ch = data.at(keyEnd - 1)) == ' ' || ch == '\t'))
- --keyEnd;
- int valueStart = equalsPos + 1;
+ QByteArrayView key = line.first(equalsPos).trimmed();
+ QByteArrayView value = line.sliced(equalsPos + 1);
- QString key = section.originalCaseKey();
- bool keyIsLowercase = (iniUnescapedKey(data, lineStart, keyEnd, key) && sectionIsLowercase);
+ QString strKey = section.originalCaseKey();
+ const Qt::CaseSensitivity casing = iniUnescapedKey(key, strKey) && sectionIsLowercase
+ ? Qt::CaseSensitive
+ : IniCaseSensitivity;
QString strValue;
- strValue.reserve(lineLen - (valueStart - lineStart));
- bool isStringList = iniUnescapedStringList(data, valueStart, lineStart + lineLen,
- strValue, strListValue);
- QVariant variant;
- if (isStringList) {
- variant = stringListToVariantList(strListValue);
- } else {
- variant = stringToVariant(strValue);
- }
+ strValue.reserve(value.size());
+ QVariant variant = iniUnescapedStringList(value, strValue, strListValue)
+ ? stringListToVariantList(strListValue)
+ : stringToVariant(strValue);
/*
We try to avoid the expensive toLower() call in
QSettingsKey by passing Qt::CaseSensitive when the
key is already in lowercase.
*/
- settingsMap->insert(QSettingsKey(key, keyIsLowercase ? Qt::CaseSensitive
- : IniCaseSensitivity,
- position),
- variant);
+ settingsMap->insert(QSettingsKey(strKey, casing, position), std::move(variant));
++position;
}
@@ -1711,11 +1747,11 @@ class QSettingsIniKey : public QString
{
public:
inline QSettingsIniKey() : position(-1) {}
- inline QSettingsIniKey(const QString &str, int pos = -1) : QString(str), position(pos) {}
+ inline QSettingsIniKey(const QString &str, qsizetype pos = -1) : QString(str), position(pos) {}
- int position;
+ qsizetype position;
};
-Q_DECLARE_TYPEINFO(QSettingsIniKey, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSettingsIniKey, Q_RELOCATABLE_TYPE);
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
{
@@ -1728,13 +1764,13 @@ typedef QMap<QSettingsIniKey, QVariant> IniKeyMap;
struct QSettingsIniSection
{
- int position;
+ qsizetype position;
IniKeyMap keyMap;
inline QSettingsIniSection() : position(-1) {}
};
-Q_DECLARE_TYPEINFO(QSettingsIniSection, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSettingsIniSection, Q_RELOCATABLE_TYPE);
typedef QMap<QString, QSettingsIniSection> IniMap;
@@ -1745,7 +1781,6 @@ typedef QMap<QString, QSettingsIniSection> IniMap;
bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSettingsMap &map)
{
IniMap iniMap;
- IniMap::const_iterator i;
#ifdef Q_OS_WIN
const char * const eol = "\r\n";
@@ -1753,12 +1788,12 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
const char eol = '\n';
#endif
- for (ParsedSettingsMap::const_iterator j = map.constBegin(); j != map.constEnd(); ++j) {
+ for (auto j = map.constBegin(); j != map.constEnd(); ++j) {
QString section;
QSettingsIniKey key(j.key().originalCaseKey(), j.key().originalKeyPosition());
- int slashPos;
+ qsizetype slashPos;
- if ((slashPos = key.indexOf(QLatin1Char('/'))) != -1) {
+ if ((slashPos = key.indexOf(u'/')) != -1) {
section = key.left(slashPos);
key.remove(0, slashPos + 1);
}
@@ -1766,21 +1801,21 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
QSettingsIniSection &iniSection = iniMap[section];
// -1 means infinity
- if (uint(key.position) < uint(iniSection.position))
+ if (size_t(key.position) < size_t(iniSection.position))
iniSection.position = key.position;
iniSection.keyMap[key] = j.value();
}
- const int sectionCount = iniMap.size();
+ const qsizetype sectionCount = iniMap.size();
QList<QSettingsIniKey> sections;
sections.reserve(sectionCount);
- for (i = iniMap.constBegin(); i != iniMap.constEnd(); ++i)
+ for (auto i = iniMap.constBegin(); i != iniMap.constEnd(); ++i)
sections.append(QSettingsIniKey(i.key(), i.value().position));
std::sort(sections.begin(), sections.end());
bool writeError = false;
- for (int j = 0; !writeError && j < sectionCount; ++j) {
- i = iniMap.constFind(sections.at(j));
+ for (qsizetype j = 0; !writeError && j < sectionCount; ++j) {
+ auto i = iniMap.constFind(sections.at(j));
Q_ASSERT(i != iniMap.constEnd());
QByteArray realSection;
@@ -1803,7 +1838,7 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
device.write(realSection);
const IniKeyMap &ents = i.value().keyMap;
- for (IniKeyMap::const_iterator j = ents.constBegin(); j != ents.constEnd(); ++j) {
+ for (auto j = ents.constBegin(); j != ents.constEnd(); ++j) {
QByteArray block;
iniEscapedKey(j.key(), block);
block += '=';
@@ -1815,8 +1850,8 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
QVariant(QString("foo")).toList() returns an empty
list, not a list containing "foo".
*/
- if (value.userType() == QMetaType::QStringList
- || (value.userType() == QMetaType::QVariantList && value.toList().size() != 1)) {
+ if (value.metaType().id() == QMetaType::QStringList
+ || (value.metaType().id() == QMetaType::QVariantList && value.toList().size() != 1)) {
iniEscapedStringList(variantListToStringList(value.toList()), block);
} else {
iniEscapedString(variantToString(value), block);
@@ -1833,8 +1868,8 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
void QConfFileSettingsPrivate::ensureAllSectionsParsed(QConfFile *confFile) const
{
- UnparsedSettingsMap::const_iterator i = confFile->unparsedIniSections.constBegin();
- const UnparsedSettingsMap::const_iterator end = confFile->unparsedIniSections.constEnd();
+ auto i = confFile->unparsedIniSections.constBegin();
+ const auto end = confFile->unparsedIniSections.constEnd();
for (; i != end; ++i) {
if (!QConfFileSettingsPrivate::readIniSection(i.key(), i.value(), &confFile->originalKeys))
@@ -1851,7 +1886,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
UnparsedSettingsMap::iterator i;
- int indexOfSlash = key.indexOf(QLatin1Char('/'));
+ qsizetype indexOfSlash = key.indexOf(u'/');
if (indexOfSlash != -1) {
i = confFile->unparsedIniSections.upperBound(key);
if (i == confFile->unparsedIniSections.begin())
@@ -1979,8 +2014,9 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\snippet code/src_corelib_io_qsettings.cpp 1
- Custom types registered using qRegisterMetaType() and
- qRegisterMetaTypeStreamOperators() can be stored using QSettings.
+ Custom types registered using qRegisterMetaType() that have
+ operators for streaming to and from a QDataStream can be stored
+ using QSettings.
\section1 Section and Key Syntax
@@ -2087,12 +2123,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\snippet settings/settings.cpp 15
- Note that type information is not preserved when reading settings from INI
- files; all values will be returned as QString.
-
- The \l{tools/settingseditor}{Settings Editor} example lets you
- experiment with different settings location and with fallbacks
- turned on or off.
+ Note that INI files lose the distinction between numeric data and the
+ strings used to encode them, so values written as numbers shall be read back
+ as QString. The numeric value can be recovered using \l QString::toInt(), \l
+ QString::toDouble() and related functions.
\section1 Restoring the State of a GUI Application
@@ -2119,9 +2153,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\codeline
\snippet settings/settings.cpp 21
- See the \l{mainwindows/application}{Application} example for a
- self-contained example that uses QSettings.
-
\section1 Accessing Settings from Multiple Threads or Processes Simultaneously
QSettings is \l{reentrant}. This means that you can use
@@ -2163,14 +2194,14 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
following files are used by default:
\list 1
- \li \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf})
- \li \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf})
+ \li \c{$HOME/.config/MySoft/Star Runner.conf}
+ \li \c{$HOME/.config/MySoft.conf}
\li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.conf}
\li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.conf}
\endlist
\note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used.
- On \macos versions 10.2 and 10.3, these files are used by
+ On \macos and iOS, if the file format is NativeFormat, these files are used by
default:
\list 1
@@ -2201,8 +2232,8 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
used on Unix, \macos, and iOS:
\list 1
- \li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini})
- \li \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini})
+ \li \c{$HOME/.config/MySoft/Star Runner.ini}
+ \li \c{$HOME/.config/MySoft.ini}
\li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.ini}
\li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.ini}
\endlist
@@ -2337,7 +2368,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\endlist
- \sa QVariant, QSessionManager, {Settings Editor Example}, {Application Example}
+ \sa QVariant, QSessionManager
*/
/*! \enum QSettings::Status
@@ -2371,9 +2402,20 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
On 32-bit Windows or from a 64-bit application on 64-bit Windows,
this works the same as specifying NativeFormat.
This enum value was added in Qt 5.7.
- \value IniFormat Store the settings in INI files. Note that type information
- is not preserved when reading settings from INI files;
- all values will be returned as QString.
+ \value IniFormat Store the settings in INI files. Note that INI files
+ lose the distinction between numeric data and the
+ strings used to encode them, so values written as
+ numbers shall be read back as QString.
+ \value WebLocalStorageFormat
+ WASM only: Store the settings in window.localStorage for the current
+ origin. If cookies are not allowed, this falls back to the INI format.
+ This provides up to 5MiB storage per origin, but access to it is
+ synchronous and JSPI is not required.
+ \value WebIndexedDBFormat
+ WASM only: Store the settings in an Indexed DB for the current
+ origin. If cookies are not allowed, this falls back to the INI format.
+ This requires JSPI, but provides more storage than
+ WebLocalStorageFormat.
\value InvalidFormat Special value returned by registerFormat().
\omitvalue CustomFormat1
@@ -2431,16 +2473,19 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
such as "General/someKey", the key will be located in the
"%General" section, \e not in the "General" section.
- \li In line with most implementations today, QSettings will
- assume the INI file is utf-8 encoded. This means that keys and values
+ \li In line with most implementations today, QSettings will assume that
+ \e values in the INI file are utf-8 encoded. This means that \e values
will be decoded as utf-8 encoded entries and written back as utf-8.
+ To retain backward compatibility with older Qt versions, \e keys in the
+ INI file are written in %-encoded format, but can be read in both
+ %-encoded and utf-8 formats.
\endlist
\section2 Compatibility with older Qt versions
Please note that this behavior is different to how QSettings behaved
- in versions of Qt prior to Qt 6. INI files written with Qt 5 or earlier aree
+ in versions of Qt prior to Qt 6. INI files written with Qt 5 or earlier are
however fully readable by a Qt 6 based application (unless a ini codec
different from utf8 had been set). But INI files written with Qt 6
will only be readable by older Qt versions if you set the "iniCodec" to
@@ -2659,7 +2704,6 @@ QSettings::QSettings(const QString &fileName, Format format)
d_ptr->q_ptr = this;
}
-# ifndef QT_BUILD_QMAKE
QSettings::QSettings(Scope scope)
: d_ptr(QSettingsPrivate::create(globalDefaultFormat, scope,
# ifdef Q_OS_DARWIN
@@ -2676,7 +2720,6 @@ QSettings::QSettings(Scope scope)
{
d_ptr->q_ptr = this;
}
-# endif
#endif
/*!
@@ -2691,10 +2734,11 @@ QSettings::~QSettings()
{
Q_D(QSettings);
if (d->pendingChanges) {
+ // Don't cause a failing flush() to std::terminate() the whole
+ // application - dtors are implicitly noexcept!
QT_TRY {
d->flush();
} QT_CATCH(...) {
- ; // ok. then don't flush but at least don't throw in the destructor
}
}
}
@@ -2886,9 +2930,12 @@ void QSettings::setAtomicSyncRequired(bool enable)
Call endGroup() to reset the current group to what it was before
the corresponding beginGroup() call. Groups can be nested.
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa endGroup(), group()
*/
-void QSettings::beginGroup(const QString &prefix)
+void QSettings::beginGroup(QAnyStringView prefix)
{
Q_D(QSettings);
d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix)));
@@ -2913,7 +2960,7 @@ void QSettings::endGroup()
}
QSettingsGroup group = d->groupStack.pop();
- int len = group.toString().size();
+ qsizetype len = group.toString().size();
if (len > 0)
d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
@@ -2942,13 +2989,16 @@ QString QSettings::group() const
Use beginWriteArray() to write the array in the first place.
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa beginWriteArray(), endArray(), setArrayIndex()
*/
-int QSettings::beginReadArray(const QString &prefix)
+int QSettings::beginReadArray(QAnyStringView prefix)
{
Q_D(QSettings);
d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), false));
- return value(QLatin1String("size")).toInt();
+ return value("size"_L1).toInt();
}
/*!
@@ -2978,17 +3028,20 @@ int QSettings::beginReadArray(const QString &prefix)
To read back an array, use beginReadArray().
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa beginReadArray(), endArray(), setArrayIndex()
*/
-void QSettings::beginWriteArray(const QString &prefix, int size)
+void QSettings::beginWriteArray(QAnyStringView prefix, int size)
{
Q_D(QSettings);
d->beginGroupOrArray(QSettingsGroup(d->normalizedKey(prefix), size < 0));
if (size < 0)
- remove(QLatin1String("size"));
+ remove("size"_L1);
else
- setValue(QLatin1String("size"), size);
+ setValue("size"_L1, size);
}
/*!
@@ -3006,13 +3059,13 @@ void QSettings::endArray()
}
QSettingsGroup group = d->groupStack.top();
- int len = group.toString().size();
+ qsizetype len = group.toString().size();
d->groupStack.pop();
if (len > 0)
d->groupPrefix.truncate(d->groupPrefix.size() - (len + 1));
if (group.arraySizeGuess() != -1)
- setValue(group.name() + QLatin1String("/size"), group.arraySizeGuess());
+ setValue(group.name() + "/size"_L1, group.arraySizeGuess());
if (!group.isArray())
qWarning("QSettings::endArray: Expected endGroup() instead");
@@ -3035,7 +3088,7 @@ void QSettings::setArrayIndex(int i)
}
QSettingsGroup &top = d->groupStack.top();
- int len = top.toString().size();
+ qsizetype len = top.toString().size();
top.setArrayIndex(qMax(i, 0));
d->groupPrefix.replace(d->groupPrefix.size() - len - 1, len, top.toString());
}
@@ -3141,17 +3194,19 @@ bool QSettings::isWritable() const
\snippet code/src_corelib_io_qsettings.cpp 23
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa value(), remove(), contains()
*/
-void QSettings::setValue(const QString &key, const QVariant &value)
+void QSettings::setValue(QAnyStringView key, const QVariant &value)
{
Q_D(QSettings);
if (key.isEmpty()) {
qWarning("QSettings::setValue: Empty key passed");
return;
}
- QString k = d->actualKey(key);
- d->set(k, value);
+ d->set(d->actualKey(key), value);
d->requestUpdate();
}
@@ -3176,9 +3231,12 @@ void QSettings::setValue(const QString &key, const QVariant &value)
case-sensitive keys. To avoid portability problems, see the
\l{Section and Key Syntax} rules.
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa setValue(), value(), contains()
*/
-void QSettings::remove(const QString &key)
+void QSettings::remove(QAnyStringView key)
{
Q_D(QSettings);
/*
@@ -3211,13 +3269,15 @@ void QSettings::remove(const QString &key)
case-sensitive keys. To avoid portability problems, see the
\l{Section and Key Syntax} rules.
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa value(), setValue()
*/
-bool QSettings::contains(const QString &key) const
+bool QSettings::contains(QAnyStringView key) const
{
Q_D(const QSettings);
- QString k = d->actualKey(key);
- return d->get(k, nullptr);
+ return d->get(d->actualKey(key)) != std::nullopt;
}
/*!
@@ -3262,6 +3322,9 @@ bool QSettings::event(QEvent *event)
#endif
/*!
+ \fn QSettings::value(QAnyStringView key) const
+ \fn QSettings::value(QAnyStringView key, const QVariant &defaultValue) const
+
Returns the value for setting \a key. If the setting doesn't
exist, returns \a defaultValue.
@@ -3277,19 +3340,34 @@ bool QSettings::event(QEvent *event)
\snippet code/src_corelib_io_qsettings.cpp 26
+ \note In Qt versions prior to 6.4, this function took QString, not
+ QAnyStringView.
+
\sa setValue(), contains(), remove()
*/
-QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const
+QVariant QSettings::value(QAnyStringView key) const
{
Q_D(const QSettings);
+ return d->value(key, nullptr);
+}
+
+QVariant QSettings::value(QAnyStringView key, const QVariant &defaultValue) const
+{
+ Q_D(const QSettings);
+ return d->value(key, &defaultValue);
+}
+
+QVariant QSettingsPrivate::value(QAnyStringView key, const QVariant *defaultValue) const
+{
if (key.isEmpty()) {
qWarning("QSettings::value: Empty key passed");
return QVariant();
}
- QVariant result = defaultValue;
- QString k = d->actualKey(key);
- d->get(k, &result);
- return result;
+ if (std::optional r = get(actualKey(key)))
+ return std::move(*r);
+ if (defaultValue)
+ return *defaultValue;
+ return QVariant();
}
/*!
@@ -3322,41 +3400,6 @@ QSettings::Format QSettings::defaultFormat()
return globalDefaultFormat;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Use setPath() instead.
-
- \oldcode
- setSystemIniPath(path);
- \newcode
- setPath(QSettings::NativeFormat, QSettings::SystemScope, path);
- setPath(QSettings::IniFormat, QSettings::SystemScope, path);
- \endcode
-*/
-void QSettings::setSystemIniPath(const QString &dir)
-{
- setPath(IniFormat, SystemScope, dir);
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
- setPath(NativeFormat, SystemScope, dir);
-#endif
-}
-
-/*!
- \obsolete
-
- Use setPath() instead.
-*/
-
-void QSettings::setUserIniPath(const QString &dir)
-{
- setPath(IniFormat, UserScope, dir);
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
- setPath(NativeFormat, UserScope, dir);
-#endif
-}
-#endif
/*!
\since 4.1
@@ -3371,8 +3414,6 @@ void QSettings::setUserIniPath(const QString &dir)
\row \li SystemScope \li \c FOLDERID_ProgramData
\row \li{1,2} Unix \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/.config
\row \li SystemScope \li \c /etc/xdg
- \row \li{1,2} Qt for Embedded Linux \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/Settings
- \row \li SystemScope \li \c /etc/xdg
\row \li{1,2} \macos and iOS \li{1,2} IniFormat \li UserScope \li \c $HOME/.config
\row \li SystemScope \li \c /etc/xdg
\endtable
@@ -3478,18 +3519,18 @@ QSettings::Format QSettings::registerFormat(const QString &extension, ReadFunc r
const auto locker = qt_scoped_lock(settingsGlobalMutex);
CustomFormatVector *customFormatVector = customFormatVectorFunc();
- int index = customFormatVector->size();
+ qsizetype index = customFormatVector->size();
if (index == 16) // the QSettings::Format enum has room for 16 custom formats
return QSettings::InvalidFormat;
QConfFileCustomFormat info;
- info.extension = QLatin1Char('.') + extension;
+ info.extension = u'.' + extension;
info.readFunc = readFunc;
info.writeFunc = writeFunc;
info.caseSensitivity = caseSensitivity;
customFormatVector->append(info);
- return QSettings::Format((int)QSettings::CustomFormat1 + index);
+ return QSettings::Format(int(QSettings::CustomFormat1) + index);
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
index 0ca5c99432..8bc73eb016 100644
--- a/src/corelib/io/qsettings.h
+++ b/src/corelib/io/qsettings.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSETTINGS_H
#define QSETTINGS_H
@@ -82,12 +46,17 @@ public:
#endif
enum Format {
- NativeFormat,
- IniFormat,
+ NativeFormat = 0,
+ IniFormat = 1,
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
- Registry32Format,
- Registry64Format,
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+ Registry32Format = 2,
+ Registry64Format = 3,
+#endif
+
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+ WebLocalStorageFormat = 4,
+ WebIndexedDBFormat = 5,
#endif
InvalidFormat = 16,
@@ -138,9 +107,7 @@ public:
QSettings(Format format, Scope scope, const QString &organization,
const QString &application = QString());
QSettings(const QString &fileName, Format format);
-# ifndef QT_BUILD_QMAKE
explicit QSettings(Scope scope = UserScope);
-# endif
#endif
~QSettings();
@@ -150,12 +117,19 @@ public:
bool isAtomicSyncRequired() const;
void setAtomicSyncRequired(bool enable);
+#if QT_CORE_REMOVED_SINCE(6, 4)
void beginGroup(const QString &prefix);
+#endif
+ void beginGroup(QAnyStringView prefix);
void endGroup();
QString group() const;
+#if QT_CORE_REMOVED_SINCE(6, 4)
int beginReadArray(const QString &prefix);
void beginWriteArray(const QString &prefix, int size = -1);
+#endif
+ int beginReadArray(QAnyStringView prefix);
+ void beginWriteArray(QAnyStringView prefix, int size = -1);
void endArray();
void setArrayIndex(int i);
@@ -164,11 +138,21 @@ public:
QStringList childGroups() const;
bool isWritable() const;
+#if QT_CORE_REMOVED_SINCE(6, 4)
void setValue(const QString &key, const QVariant &value);
- QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+ QVariant value(const QString &key, const QVariant &defaultValue) const;
+ QVariant value(const QString &key) const;
+#endif
+ void setValue(QAnyStringView key, const QVariant &value);
+ QVariant value(QAnyStringView key, const QVariant &defaultValue) const;
+ QVariant value(QAnyStringView key) const;
+#if QT_CORE_REMOVED_SINCE(6, 4)
void remove(const QString &key);
bool contains(const QString &key) const;
+#endif
+ void remove(QAnyStringView key);
+ bool contains(QAnyStringView key) const;
void setFallbacksEnabled(bool b);
bool fallbacksEnabled() const;
@@ -181,12 +165,6 @@ public:
static void setDefaultFormat(Format format);
static Format defaultFormat();
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QSettings::setPath() instead")
- static void setSystemIniPath(const QString &dir);
- QT_DEPRECATED_X("Use QSettings::setPath() instead")
- static void setUserIniPath(const QString &dir);
-#endif
static void setPath(Format format, Scope scope, const QString &path);
typedef QMap<QString, QVariant> SettingsMap;
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
index a2b943f9ec..144ed59dc2 100644
--- a/src/corelib/io/qsettings_mac.cpp
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsettings.h"
@@ -50,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static const CFStringRef hostNames[2] = { kCFPreferencesCurrentHost, kCFPreferencesAnyHost };
static const int numHostNames = 2;
@@ -95,7 +61,7 @@ static QCFType<CFPropertyListRef> macValue(const QVariant &value);
static CFArrayRef macList(const QList<QVariant> &list)
{
int n = list.size();
- QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(n);
+ QVarLengthArray<QCFType<CFPropertyListRef>> cfvalues(n);
for (int i = 0; i < n; ++i)
cfvalues[i] = macValue(list.at(i));
return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(cfvalues.data()),
@@ -106,8 +72,8 @@ static QCFType<CFPropertyListRef> macValue(const QVariant &value)
{
CFPropertyListRef result = 0;
- switch (value.type()) {
- case QVariant::ByteArray:
+ switch (value.metaType().id()) {
+ case QMetaType::QByteArray:
{
QByteArray ba = value.toByteArray();
result = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(ba.data()),
@@ -115,64 +81,37 @@ static QCFType<CFPropertyListRef> macValue(const QVariant &value)
}
break;
// should be same as below (look for LIST)
- case QVariant::List:
- case QVariant::StringList:
- case QVariant::Polygon:
+ case QMetaType::QVariantList:
+ case QMetaType::QStringList:
+ case QMetaType::QPolygon:
result = macList(value.toList());
break;
- case QVariant::Map:
+ case QMetaType::QVariantMap:
{
- /*
- QMap<QString, QVariant> is potentially a multimap,
- whereas CFDictionary is a single-valued map. To allow
- for multiple values with the same key, we store
- multiple values in a CFArray. To avoid ambiguities,
- we also wrap lists in a CFArray singleton.
- */
- QMap<QString, QVariant> map = value.toMap();
- QMap<QString, QVariant>::const_iterator i = map.constBegin();
-
- int maxUniqueKeys = map.size();
- int numUniqueKeys = 0;
- QVarLengthArray<QCFType<CFPropertyListRef> > cfkeys(maxUniqueKeys);
- QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(maxUniqueKeys);
-
- while (i != map.constEnd()) {
- const QString &key = i.key();
- QList<QVariant> values;
-
- do {
- values << i.value();
- ++i;
- } while (i != map.constEnd() && i.key() == key);
-
- bool singleton = (values.count() == 1);
- if (singleton) {
- switch (values.constFirst().type()) {
- // should be same as above (look for LIST)
- case QVariant::List:
- case QVariant::StringList:
- case QVariant::Polygon:
- singleton = false;
- default:
- ;
- }
- }
+ const QVariantMap &map = value.toMap();
+ const int mapSize = map.size();
- cfkeys[numUniqueKeys] = key.toCFString();
- cfvalues[numUniqueKeys] = singleton ? macValue(values.constFirst()) : macList(values);
- ++numUniqueKeys;
- }
+ QVarLengthArray<QCFType<CFPropertyListRef>> cfkeys;
+ cfkeys.reserve(mapSize);
+ std::transform(map.keyBegin(), map.keyEnd(),
+ std::back_inserter(cfkeys),
+ [](const auto &key) { return key.toCFString(); });
+
+ QVarLengthArray<QCFType<CFPropertyListRef>> cfvalues;
+ cfvalues.reserve(mapSize);
+ std::transform(map.begin(), map.end(),
+ std::back_inserter(cfvalues),
+ [](const auto &value) { return macValue(value); });
result = CFDictionaryCreate(kCFAllocatorDefault,
reinterpret_cast<const void **>(cfkeys.data()),
reinterpret_cast<const void **>(cfvalues.data()),
- CFIndex(numUniqueKeys),
+ CFIndex(mapSize),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
break;
- case QVariant::DateTime:
+ case QMetaType::QDateTime:
{
QDateTime dateTime = value.toDateTime();
// CFDate, unlike QDateTime, doesn't store timezone information
@@ -182,30 +121,30 @@ static QCFType<CFPropertyListRef> macValue(const QVariant &value)
goto string_case;
}
break;
- case QVariant::Bool:
+ case QMetaType::Bool:
result = value.toBool() ? kCFBooleanTrue : kCFBooleanFalse;
break;
- case QVariant::Int:
- case QVariant::UInt:
+ case QMetaType::Int:
+ case QMetaType::UInt:
{
int n = value.toInt();
result = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &n);
}
break;
- case QVariant::Double:
+ case QMetaType::Double:
{
double n = value.toDouble();
result = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &n);
}
break;
- case QVariant::LongLong:
- case QVariant::ULongLong:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
{
qint64 n = value.toLongLong();
result = CFNumberCreate(0, kCFNumberLongLongType, &n);
}
break;
- case QVariant::String:
+ case QMetaType::QString:
string_case:
default:
QString string = QSettingsPrivate::variantToString(value);
@@ -253,7 +192,7 @@ static QVariant qtValue(CFPropertyListRef cfvalue)
bool metNonString = false;
for (CFIndex i = 0; i < size; ++i) {
QVariant value = qtValue(CFArrayGetValueAtIndex(cfarray, i));
- if (value.type() != QVariant::String)
+ if (value.typeId() != QMetaType::QString)
metNonString = true;
list << value;
}
@@ -274,7 +213,15 @@ static QVariant qtValue(CFPropertyListRef cfvalue)
}
const QString str = QString::fromUtf8(byteArray.constData(), byteArray.size());
- return QSettingsPrivate::stringToVariant(str);
+ QVariant variant = QSettingsPrivate::stringToVariant(str);
+ if (variant == QVariant(str)) {
+ // We did not find an encoded variant in the string,
+ // so return the raw byte array instead.
+ byteArray.detach();
+ return byteArray;
+ }
+
+ return variant;
} else if (typeId == CFDictionaryGetTypeID()) {
CFDictionaryRef cfdict = static_cast<CFDictionaryRef>(cfvalue);
CFTypeID arrayTypeId = CFArrayGetTypeID();
@@ -283,15 +230,18 @@ static QVariant qtValue(CFPropertyListRef cfvalue)
QVarLengthArray<CFPropertyListRef> values(size);
CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
- QMultiMap<QString, QVariant> map;
+ QVariantMap map;
for (int i = 0; i < size; ++i) {
QString key = QString::fromCFString(static_cast<CFStringRef>(keys[i]));
if (CFGetTypeID(values[i]) == arrayTypeId) {
CFArrayRef cfarray = static_cast<CFArrayRef>(values[i]);
CFIndex arraySize = CFArrayGetCount(cfarray);
- for (CFIndex j = arraySize - 1; j >= 0; --j)
- map.insert(key, qtValue(CFArrayGetValueAtIndex(cfarray, j)));
+ QVariantList list;
+ list.reserve(arraySize);
+ for (CFIndex j = 0; j < arraySize; ++j)
+ list.append(qtValue(CFArrayGetValueAtIndex(cfarray, j)));
+ map.insert(key, list);
} else {
map.insert(key, qtValue(values[i]));
}
@@ -307,18 +257,16 @@ static QString comify(const QString &organization)
{
for (int i = organization.size() - 1; i >= 0; --i) {
QChar ch = organization.at(i);
- if (ch == QLatin1Char('.') || ch == QChar(0x3002) || ch == QChar(0xff0e)
+ if (ch == u'.' || ch == QChar(0x3002) || ch == QChar(0xff0e)
|| ch == QChar(0xff61)) {
QString suffix = organization.mid(i + 1).toLower();
- if (suffix.size() == 2 || suffix == QLatin1String("com")
- || suffix == QLatin1String("org") || suffix == QLatin1String("net")
- || suffix == QLatin1String("edu") || suffix == QLatin1String("gov")
- || suffix == QLatin1String("mil") || suffix == QLatin1String("biz")
- || suffix == QLatin1String("info") || suffix == QLatin1String("name")
- || suffix == QLatin1String("pro") || suffix == QLatin1String("aero")
- || suffix == QLatin1String("coop") || suffix == QLatin1String("museum")) {
+ if (suffix.size() == 2 || suffix == "com"_L1 || suffix == "org"_L1
+ || suffix == "net"_L1 || suffix == "edu"_L1 || suffix == "gov"_L1
+ || suffix == "mil"_L1 || suffix == "biz"_L1 || suffix == "info"_L1
+ || suffix == "name"_L1 || suffix == "pro"_L1 || suffix == "aero"_L1
+ || suffix == "coop"_L1 || suffix == "museum"_L1) {
QString result = organization;
- result.replace(QLatin1Char('/'), QLatin1Char(' '));
+ result.replace(u'/', u' ');
return result;
}
break;
@@ -337,13 +285,13 @@ static QString comify(const QString &organization)
} else if (uc >= 'A' && uc <= 'Z') {
domain += ch.toLower();
} else {
- domain += QLatin1Char(' ');
+ domain += u' ';
}
}
domain = domain.simplified();
- domain.replace(QLatin1Char(' '), QLatin1Char('-'));
+ domain.replace(u' ', u'-');
if (!domain.isEmpty())
- domain.append(QLatin1String(".com"));
+ domain.append(".com"_L1);
return domain;
}
@@ -356,7 +304,7 @@ public:
void remove(const QString &key) override;
void set(const QString &key, const QVariant &value) override;
- bool get(const QString &key, QVariant *value) const override;
+ std::optional<QVariant> get(const QString &key) const override;
QStringList children(const QString &prefix, ChildSpec spec) const override;
void clear() override;
void sync() override;
@@ -396,35 +344,34 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString &
if (main_bundle_identifier != NULL) {
QString bundle_identifier(qtKey(main_bundle_identifier));
// CFBundleGetIdentifier returns identifier separated by slashes rather than periods.
- QStringList bundle_identifier_components = bundle_identifier.split(QLatin1Char('/'));
+ QStringList bundle_identifier_components = bundle_identifier.split(u'/');
// pre-reverse them so that when they get reversed again below, they are in the com.company.product format.
QStringList bundle_identifier_components_reversed;
for (int i=0; i<bundle_identifier_components.size(); ++i) {
const QString &bundle_identifier_component = bundle_identifier_components.at(i);
bundle_identifier_components_reversed.push_front(bundle_identifier_component);
}
- domainName = bundle_identifier_components_reversed.join(QLatin1Char('.'));
+ domainName = bundle_identifier_components_reversed.join(u'.');
}
}
}
// if no bundle identifier yet. use a hard coded string.
- if (domainName.isEmpty()) {
- domainName = QLatin1String("unknown-organization.trolltech.com");
- }
+ if (domainName.isEmpty())
+ domainName = "unknown-organization.trolltech.com"_L1;
- while ((nextDot = domainName.indexOf(QLatin1Char('.'), curPos)) != -1) {
+ while ((nextDot = domainName.indexOf(u'.', curPos)) != -1) {
javaPackageName.prepend(QStringView{domainName}.mid(curPos, nextDot - curPos));
- javaPackageName.prepend(QLatin1Char('.'));
+ javaPackageName.prepend(u'.');
curPos = nextDot + 1;
}
javaPackageName.prepend(QStringView{domainName}.mid(curPos));
javaPackageName = std::move(javaPackageName).toLower();
if (curPos == 0)
- javaPackageName.prepend(QLatin1String("com."));
+ javaPackageName.prepend("com."_L1);
suiteId = javaPackageName;
if (!application.isEmpty()) {
- javaPackageName += QLatin1Char('.') + application;
+ javaPackageName += u'.' + application;
applicationId = javaPackageName;
}
@@ -452,13 +399,13 @@ QMacSettingsPrivate::~QMacSettingsPrivate()
void QMacSettingsPrivate::remove(const QString &key)
{
- QStringList keys = children(key + QLatin1Char('/'), AllKeys);
+ QStringList keys = children(key + u'/', AllKeys);
// If i == -1, then delete "key" itself.
for (int i = -1; i < keys.size(); ++i) {
QString subKey = key;
if (i >= 0) {
- subKey += QLatin1Char('/');
+ subKey += u'/';
subKey += keys.at(i);
}
CFPreferencesSetValue(macKey(subKey), 0, domains[0].applicationOrSuiteId,
@@ -472,7 +419,7 @@ void QMacSettingsPrivate::set(const QString &key, const QVariant &value)
domains[0].userName, hostName);
}
-bool QMacSettingsPrivate::get(const QString &key, QVariant *value) const
+std::optional<QVariant> QMacSettingsPrivate::get(const QString &key) const
{
QCFString k = macKey(key);
for (int i = 0; i < numDomains; ++i) {
@@ -480,17 +427,14 @@ bool QMacSettingsPrivate::get(const QString &key, QVariant *value) const
QCFType<CFPropertyListRef> ret =
CFPreferencesCopyValue(k, domains[i].applicationOrSuiteId, domains[i].userName,
hostNames[j]);
- if (ret) {
- if (value)
- *value = qtValue(ret);
- return true;
- }
+ if (ret)
+ return qtValue(ret);
}
if (!fallbacks)
break;
}
- return false;
+ return std::nullopt;
}
QStringList QMacSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
@@ -553,14 +497,14 @@ void QMacSettingsPrivate::flush()
bool QMacSettingsPrivate::isWritable() const
{
QMacSettingsPrivate *that = const_cast<QMacSettingsPrivate *>(this);
- QString impossibleKey(QLatin1String("qt_internal/"));
+ QString impossibleKey("qt_internal/"_L1);
QSettings::Status oldStatus = that->status;
that->status = QSettings::NoError;
that->set(impossibleKey, QVariant());
that->sync();
- bool writable = (status == QSettings::NoError) && that->get(impossibleKey, 0);
+ bool writable = (status == QSettings::NoError) && that->get(impossibleKey).has_value();
that->remove(impossibleKey);
that->sync();
@@ -573,9 +517,9 @@ QString QMacSettingsPrivate::fileName() const
QString result;
if (scope == QSettings::UserScope)
result = QDir::homePath();
- result += QLatin1String("/Library/Preferences/");
+ result += "/Library/Preferences/"_L1;
result += QString::fromCFString(domains[0].applicationOrSuiteId);
- result += QLatin1String(".plist");
+ result += ".plist"_L1;
return result;
}
@@ -585,7 +529,7 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format,
const QString &application)
{
#ifndef QT_BOOTSTRAPPED
- if (organization == QLatin1String("Qt"))
+ if (organization == "Qt"_L1)
{
QString organizationDomain = QCoreApplication::organizationDomain();
QString applicationName = QCoreApplication::applicationName();
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index bd8a40a324..4229abd874 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSETTINGS_P_H
#define QSETTINGS_P_H
@@ -64,7 +28,6 @@
#ifndef QT_NO_QOBJECT
#include "private/qobject_p.h"
#endif
-#include "private/qscopedpointer_p.h"
QT_BEGIN_NAMESPACE
@@ -81,11 +44,11 @@ static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseSensitive;
class QSettingsKey : public QString
{
public:
- inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, int /* position */ = -1)
+ inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, qsizetype /* position */ = -1)
: QString(key) { Q_ASSERT(cs == Qt::CaseSensitive); Q_UNUSED(cs); }
inline QString originalCaseKey() const { return *this; }
- inline int originalKeyPosition() const { return -1; }
+ inline qsizetype originalKeyPosition() const { return -1; }
};
#else
static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseInsensitive;
@@ -93,23 +56,23 @@ static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseInsensitive;
class QSettingsKey : public QString
{
public:
- inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, int position = -1)
- : QString(key), theOriginalKey(key), theOriginalKeyPosition(position)
+ inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, qsizetype position = -1)
+ : QString(key), theOriginalKey(key), theOriginalKeyPosition(position)
{
if (cs == Qt::CaseInsensitive)
QString::operator=(toLower());
}
inline QString originalCaseKey() const { return theOriginalKey; }
- inline int originalKeyPosition() const { return theOriginalKeyPosition; }
+ inline qsizetype originalKeyPosition() const { return theOriginalKeyPosition; }
private:
QString theOriginalKey;
- int theOriginalKeyPosition;
+ qsizetype theOriginalKeyPosition;
};
#endif
-Q_DECLARE_TYPEINFO(QSettingsKey, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSettingsKey, Q_RELOCATABLE_TYPE);
typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap;
typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap;
@@ -127,28 +90,28 @@ public:
inline QString name() const { return str; }
inline QString toString() const;
inline bool isArray() const { return num != -1; }
- inline int arraySizeGuess() const { return maxNum; }
- inline void setArrayIndex(int i)
+ inline qsizetype arraySizeGuess() const { return maxNum; }
+ inline void setArrayIndex(qsizetype i)
{ num = i + 1; if (maxNum != -1 && num > maxNum) maxNum = num; }
QString str;
- int num;
- int maxNum;
+ qsizetype num;
+ qsizetype maxNum;
};
-Q_DECLARE_TYPEINFO(QSettingsGroup, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSettingsGroup, Q_RELOCATABLE_TYPE);
inline QString QSettingsGroup::toString() const
{
QString result;
result = str;
if (num > 0) {
- result += QLatin1Char('/');
+ result += u'/';
result += QString::number(num);
}
return result;
}
-class Q_AUTOTEST_EXPORT QConfFile
+class QConfFile
{
public:
~QConfFile();
@@ -157,6 +120,7 @@ public:
bool isWritable() const;
static QConfFile *fromName(const QString &name, bool _userPerms);
+ Q_AUTOTEST_EXPORT
static void clearCache();
QString name;
@@ -198,7 +162,7 @@ public:
virtual void remove(const QString &key) = 0;
virtual void set(const QString &key, const QVariant &value) = 0;
- virtual bool get(const QString &key, QVariant *value) const = 0;
+ virtual std::optional<QVariant> get(const QString &key) const = 0;
enum ChildSpec { AllKeys, ChildKeys, ChildGroups };
virtual QStringList children(const QString &prefix, ChildSpec spec) const = 0;
@@ -209,13 +173,14 @@ public:
virtual bool isWritable() const = 0;
virtual QString fileName() const = 0;
- QString actualKey(const QString &key) const;
+ QVariant value(QAnyStringView key, const QVariant *defaultValue) const;
+ QString actualKey(QAnyStringView key) const;
void beginGroupOrArray(const QSettingsGroup &group);
void setStatus(QSettings::Status status) const;
void requestUpdate();
void update();
- static QString normalizedKey(const QString &key);
+ static QString normalizedKey(QAnyStringView key);
static QSettingsPrivate *create(QSettings::Format format, QSettings::Scope scope,
const QString &organization, const QString &application);
static QSettingsPrivate *create(const QString &fileName, QSettings::Format format);
@@ -230,12 +195,12 @@ public:
static QString variantToString(const QVariant &v);
static QVariant stringToVariant(const QString &s);
static void iniEscapedKey(const QString &key, QByteArray &result);
- static bool iniUnescapedKey(const QByteArray &key, int from, int to, QString &result);
+ static bool iniUnescapedKey(QByteArrayView key, QString &result);
static void iniEscapedString(const QString &str, QByteArray &result);
static void iniEscapedStringList(const QStringList &strs, QByteArray &result);
- static bool iniUnescapedStringList(const QByteArray &str, int from, int to,
- QString &stringResult, QStringList &stringListResult);
- static QStringList splitArgs(const QString &s, int idx);
+ static bool iniUnescapedStringList(QByteArrayView str, QString &stringResult,
+ QStringList &stringListResult);
+ static QStringList splitArgs(const QString &s, qsizetype idx);
QSettings::Format format;
QSettings::Scope scope;
@@ -251,10 +216,6 @@ protected:
mutable QSettings::Status status;
};
-#ifdef Q_OS_WASM
-class QWasmSettingsPrivate;
-#endif
-
class QConfFileSettingsPrivate : public QSettingsPrivate
{
public:
@@ -265,7 +226,7 @@ public:
void remove(const QString &key) override;
void set(const QString &key, const QVariant &value) override;
- bool get(const QString &key, QVariant *value) const override;
+ std::optional<QVariant> get(const QString &key) const override;
QStringList children(const QString &prefix, ChildSpec spec) const override;
@@ -275,18 +236,22 @@ public:
bool isWritable() const override;
QString fileName() const override;
- bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections);
- static bool readIniSection(const QSettingsKey &section, const QByteArray &data,
+ bool readIniFile(QByteArrayView data, UnparsedSettingsMap *unparsedIniSections);
+ static bool readIniSection(const QSettingsKey &section, QByteArrayView data,
ParsedSettingsMap *settingsMap);
- static bool readIniLine(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen,
- int &equalsPos);
+ static bool readIniLine(QByteArrayView data, qsizetype &dataPos,
+ qsizetype &lineStart, qsizetype &lineLen,
+ qsizetype &equalsPos);
+
+protected:
+ const QList<QConfFile *> &getConfFiles() const { return confFiles; }
private:
void initFormat();
virtual void initAccess();
void syncConfFile(QConfFile *confFile);
bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map);
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
bool readPlistFile(const QByteArray &data, ParsedSettingsMap *map) const;
bool writePlistFile(QIODevice &file, const ParsedSettingsMap &map) const;
#endif
@@ -298,9 +263,9 @@ private:
QSettings::WriteFunc writeFunc;
QString extension;
Qt::CaseSensitivity caseSensitivity;
- int nextPosition;
+ qsizetype nextPosition;
#ifdef Q_OS_WASM
- friend class QWasmSettingsPrivate;
+ friend class QWasmIDBSettingsPrivate;
#endif
};
diff --git a/src/corelib/io/qsettings_wasm.cpp b/src/corelib/io/qsettings_wasm.cpp
index 8d8f4b505c..7d80ff82d3 100644
--- a/src/corelib/io/qsettings_wasm.cpp
+++ b/src/corelib/io/qsettings_wasm.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsettings.h"
#ifndef QT_NO_SETTINGS
@@ -46,213 +10,393 @@
#include <QFile>
#endif // QT_NO_QOBJECT
#include <QDebug>
+#include <QtCore/private/qstdweb_p.h>
#include <QFileInfo>
#include <QDir>
+#include <QList>
+#include <QSet>
+
#include <emscripten.h>
+# include <emscripten/proxying.h>
+# include <emscripten/threading.h>
+# include <emscripten/val.h>
QT_BEGIN_NAMESPACE
-static bool isReadReady = false;
+using emscripten::val;
+using namespace Qt::StringLiterals;
-class QWasmSettingsPrivate : public QConfFileSettingsPrivate
+namespace {
+QStringView keyNameFromPrefixedStorageName(QStringView prefix, QStringView prefixedStorageName)
+{
+ // Return the key slice after m_keyPrefix, or an empty string view if no match
+ if (!prefixedStorageName.startsWith(prefix))
+ return QStringView();
+ return prefixedStorageName.sliced(prefix.length());
+}
+} // namespace
+
+//
+// Native settings implementation for WebAssembly using window.localStorage
+// as the storage backend. localStorage is a key-value store with a synchronous
+// API and a 5MB storage limit.
+//
+class QWasmLocalStorageSettingsPrivate final : public QSettingsPrivate
{
public:
- QWasmSettingsPrivate(QSettings::Scope scope, const QString &organization,
- const QString &application);
- ~QWasmSettingsPrivate();
-
- bool get(const QString &key, QVariant *value) const override;
- QStringList children(const QString &prefix, ChildSpec spec) const override;
- void clear() override;
- void sync() override;
- void flush() override;
- bool isWritable() const override;
-
- void syncToLocal(const char *data, int size);
- void loadLocal(const QByteArray &filename);
- void setReady();
- void initAccess() override;
+ QWasmLocalStorageSettingsPrivate(QSettings::Scope scope, const QString &organization,
+ const QString &application);
+ ~QWasmLocalStorageSettingsPrivate() final = default;
+
+ void remove(const QString &key) final;
+ void set(const QString &key, const QVariant &value) final;
+ std::optional<QVariant> get(const QString &key) const final;
+ QStringList children(const QString &prefix, ChildSpec spec) const final;
+ void clear() final;
+ void sync() final;
+ void flush() final;
+ bool isWritable() const final;
+ QString fileName() const final;
private:
- QString databaseName;
- QString id;
+ QStringList m_keyPrefixes;
};
-static void QWasmSettingsPrivate_onLoad(void *userData, void *dataPtr, int size)
+QWasmLocalStorageSettingsPrivate::QWasmLocalStorageSettingsPrivate(QSettings::Scope scope,
+ const QString &organization,
+ const QString &application)
+ : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
{
- QWasmSettingsPrivate *wasm = reinterpret_cast<QWasmSettingsPrivate *>(userData);
-
- QFile file(wasm->fileName());
- QFileInfo fileInfo(wasm->fileName());
- QDir dir(fileInfo.path());
- if (!dir.exists())
- dir.mkpath(fileInfo.path());
+ if (organization.isEmpty()) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
- if (file.open(QFile::WriteOnly)) {
- file.write(reinterpret_cast<char *>(dataPtr), size);
- file.close();
- wasm->setReady();
+ // The key prefix contians "qt" to separate Qt keys from other keys on localStorage, a
+ // version tag to allow for making changes to the key format in the future, the org
+ // and app names.
+ //
+ // User code could could create separate settings object with different org and app names,
+ // and would expect them to have separate settings. Also, different webassembly instances
+ // on the page could write to the same window.localStorage. Add the org and app name
+ // to the key prefix to differentiate, even if that leads to keys with redundant sections
+ // for the common case of a single org and app name.
+ //
+ // Also, the common Qt mechanism for user/system scope and all-application settings are
+ // implemented, using different prefixes.
+ const QString allAppsSetting = QStringLiteral("all-apps");
+ const QString systemSetting = QStringLiteral("sys-tem");
+
+ const QLatin1String separator("-");
+ const QLatin1String doubleSeparator("--");
+ const QString escapedOrganization = QString(organization).replace(separator, doubleSeparator);
+ const QString escapedApplication = QString(application).replace(separator, doubleSeparator);
+ const QString prefix = "qt-v0-" + escapedOrganization + separator;
+ if (scope == QSettings::Scope::UserScope) {
+ if (!escapedApplication.isEmpty())
+ m_keyPrefixes.push_back(prefix + escapedApplication + separator);
+ m_keyPrefixes.push_back(prefix + allAppsSetting + separator);
+ }
+ if (!escapedApplication.isEmpty()) {
+ m_keyPrefixes.push_back(prefix + escapedApplication + separator + systemSetting
+ + separator);
}
+ m_keyPrefixes.push_back(prefix + allAppsSetting + separator + systemSetting + separator);
}
-static void QWasmSettingsPrivate_onError(void *userData)
+void QWasmLocalStorageSettingsPrivate::remove(const QString &key)
{
- QWasmSettingsPrivate *wasm = reinterpret_cast<QWasmSettingsPrivate *>(userData);
- if (wasm)
- wasm->setStatus(QSettings::AccessError);
+ const std::string removed = QString(m_keyPrefixes.first() + key).toStdString();
+
+ qstdweb::runTaskOnMainThread<void>([this, &removed, &key]() {
+ std::vector<std::string> children = { removed };
+ const int length = val::global("window")["localStorage"]["length"].as<int>();
+ for (int i = 0; i < length; ++i) {
+ const QString storedKeyWithPrefix = QString::fromStdString(
+ val::global("window")["localStorage"].call<val>("key", i).as<std::string>());
+
+ const QStringView storedKey = keyNameFromPrefixedStorageName(
+ m_keyPrefixes.first(), QStringView(storedKeyWithPrefix));
+ if (storedKey.isEmpty() || !storedKey.startsWith(key))
+ continue;
+
+ children.push_back(storedKeyWithPrefix.toStdString());
+ }
+
+ for (const auto &child : children)
+ val::global("window")["localStorage"].call<val>("removeItem", child);
+ });
}
-static void QWasmSettingsPrivate_onStore(void *userData)
+void QWasmLocalStorageSettingsPrivate::set(const QString &key, const QVariant &value)
{
- QWasmSettingsPrivate *wasm = reinterpret_cast<QWasmSettingsPrivate *>(userData);
- if (wasm)
- wasm->setStatus(QSettings::NoError);
+ qstdweb::runTaskOnMainThread<void>([this, &key, &value]() {
+ const std::string keyString = QString(m_keyPrefixes.first() + key).toStdString();
+ const std::string valueString = QSettingsPrivate::variantToString(value).toStdString();
+ val::global("window")["localStorage"].call<void>("setItem", keyString, valueString);
+ });
}
-static void QWasmSettingsPrivate_onCheck(void *userData, int exists)
+std::optional<QVariant> QWasmLocalStorageSettingsPrivate::get(const QString &key) const
{
- QWasmSettingsPrivate *wasm = reinterpret_cast<QWasmSettingsPrivate *>(userData);
- if (wasm) {
- if (exists)
- wasm->loadLocal(wasm->fileName().toLocal8Bit());
- else
- wasm->setReady();
- }
+ return qstdweb::runTaskOnMainThread<std::optional<QVariant>>(
+ [this, &key]() -> std::optional<QVariant> {
+ for (const auto &prefix : m_keyPrefixes) {
+ const std::string keyString = QString(prefix + key).toStdString();
+ const emscripten::val value =
+ val::global("window")["localStorage"].call<val>("getItem", keyString);
+ if (!value.isNull()) {
+ return QSettingsPrivate::stringToVariant(
+ QString::fromStdString(value.as<std::string>()));
+ }
+ if (!fallbacks) {
+ return std::nullopt;
+ }
+ }
+ return std::nullopt;
+ });
}
-QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format,
- QSettings::Scope scope,
- const QString &organization,
- const QString &application)
+QStringList QWasmLocalStorageSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
{
- Q_UNUSED(format)
- if (organization == QLatin1String("Qt"))
- {
- QString organizationDomain = QCoreApplication::organizationDomain();
- QString applicationName = QCoreApplication::applicationName();
+ return qstdweb::runTaskOnMainThread<QStringList>([this, &prefix, &spec]() -> QStringList {
+ QSet<QString> nodes;
+ // Loop through all keys on window.localStorage, return Qt keys belonging to
+ // this application, with the correct prefix, and according to ChildSpec.
+ QStringList children;
+ const int length = val::global("window")["localStorage"]["length"].as<int>();
+ for (int i = 0; i < length; ++i) {
+ for (const auto &storagePrefix : m_keyPrefixes) {
+ const QString keyString =
+ QString::fromStdString(val::global("window")["localStorage"]
+ .call<val>("key", i)
+ .as<std::string>());
+
+ const QStringView key =
+ keyNameFromPrefixedStorageName(storagePrefix, QStringView(keyString));
+ if (!key.isEmpty() && key.startsWith(prefix)) {
+ QStringList children;
+ QSettingsPrivate::processChild(key.sliced(prefix.length()), spec, children);
+ if (!children.isEmpty())
+ nodes.insert(children.first());
+ }
+ if (!fallbacks)
+ break;
+ }
+ }
+
+ return QStringList(nodes.begin(), nodes.end());
+ });
+}
- QSettingsPrivate *newSettings;
- newSettings = new QWasmSettingsPrivate(scope, organizationDomain, applicationName);
+void QWasmLocalStorageSettingsPrivate::clear()
+{
+ qstdweb::runTaskOnMainThread<void>([this]() {
+ // Get all Qt keys from window.localStorage
+ const int length = val::global("window")["localStorage"]["length"].as<int>();
+ QStringList keys;
+ keys.reserve(length);
+ for (int i = 0; i < length; ++i)
+ keys.append(QString::fromStdString(
+ (val::global("window")["localStorage"].call<val>("key", i).as<std::string>())));
+
+ // Remove all Qt keys. Note that localStorage does not guarantee a stable
+ // iteration order when the storage is mutated, which is why removal is done
+ // in a second step after getting all keys.
+ for (const QString &key : keys) {
+ if (!keyNameFromPrefixedStorageName(m_keyPrefixes.first(), key).isEmpty())
+ val::global("window")["localStorage"].call<val>("removeItem", key.toStdString());
+ }
+ });
+}
- newSettings->beginGroupOrArray(QSettingsGroup(normalizedKey(organization)));
- if (!application.isEmpty())
- newSettings->beginGroupOrArray(QSettingsGroup(normalizedKey(application)));
+void QWasmLocalStorageSettingsPrivate::sync() { }
- return newSettings;
- }
- return new QWasmSettingsPrivate(scope, organization, application);
-}
+void QWasmLocalStorageSettingsPrivate::flush() { }
-QWasmSettingsPrivate::QWasmSettingsPrivate(QSettings::Scope scope, const QString &organization,
- const QString &application)
- : QConfFileSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
+bool QWasmLocalStorageSettingsPrivate::isWritable() const
{
- setStatus(QSettings::AccessError); // access error until sandbox gets loaded
- databaseName = organization;
- id = application;
-
- emscripten_idb_async_exists("/home/web_user",
- fileName().toLocal8Bit(),
- reinterpret_cast<void*>(this),
- QWasmSettingsPrivate_onCheck,
- QWasmSettingsPrivate_onError);
+ return true;
}
-QWasmSettingsPrivate::~QWasmSettingsPrivate()
+QString QWasmLocalStorageSettingsPrivate::fileName() const
{
+ return QString();
}
- void QWasmSettingsPrivate::initAccess()
+//
+// Native settings implementation for WebAssembly using the indexed database as
+// the storage backend
+//
+class QWasmIDBSettingsPrivate : public QConfFileSettingsPrivate
{
- if (isReadReady)
- QConfFileSettingsPrivate::initAccess();
-}
+public:
+ QWasmIDBSettingsPrivate(QSettings::Scope scope, const QString &organization,
+ const QString &application);
+ ~QWasmIDBSettingsPrivate();
+
+ void clear() override;
+ void sync() override;
+
+private:
+ bool writeSettingsToTemporaryFile(const QString &fileName, void *dataPtr, int size);
+ void loadIndexedDBFiles();
+
+
+ QString databaseName;
+ QString id;
+};
-bool QWasmSettingsPrivate::get(const QString &key, QVariant *value) const
+constexpr char DbName[] = "/home/web_user";
+
+QWasmIDBSettingsPrivate::QWasmIDBSettingsPrivate(QSettings::Scope scope,
+ const QString &organization,
+ const QString &application)
+ : QConfFileSettingsPrivate(QSettings::WebIndexedDBFormat, scope, organization, application)
{
- if (isReadReady)
- return QConfFileSettingsPrivate::get(key, value);
+ Q_ASSERT_X(qstdweb::haveJspi(), Q_FUNC_INFO, "QWasmIDBSettingsPrivate needs JSPI to work");
+
+ if (organization.isEmpty()) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
+ databaseName = organization;
+ id = application;
- return false;
+ loadIndexedDBFiles();
+
+ QConfFileSettingsPrivate::initAccess();
}
-QStringList QWasmSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
+QWasmIDBSettingsPrivate::~QWasmIDBSettingsPrivate() = default;
+
+bool QWasmIDBSettingsPrivate::writeSettingsToTemporaryFile(const QString &fileName, void *dataPtr,
+ int size)
{
- return QConfFileSettingsPrivate::children(prefix, spec);
+ QFile file(fileName);
+ QFileInfo fileInfo(fileName);
+ QDir dir(fileInfo.path());
+ if (!dir.exists())
+ dir.mkpath(fileInfo.path());
+
+ if (!file.open(QFile::WriteOnly))
+ return false;
+
+ return size == file.write(reinterpret_cast<char *>(dataPtr), size);
}
-void QWasmSettingsPrivate::clear()
+void QWasmIDBSettingsPrivate::clear()
{
QConfFileSettingsPrivate::clear();
- emscripten_idb_async_delete("/home/web_user",
- fileName().toLocal8Bit(),
- reinterpret_cast<void*>(this),
- QWasmSettingsPrivate_onStore,
- QWasmSettingsPrivate_onError);
+
+ int error = 0;
+ emscripten_idb_delete(DbName, fileName().toLocal8Bit(), &error);
+ setStatus(!!error ? QSettings::AccessError : QSettings::NoError);
}
-void QWasmSettingsPrivate::sync()
+void QWasmIDBSettingsPrivate::sync()
{
+ // Reload the files, in case there were any changes in IndexedDB, and flush them to disk.
+ // Thanks to this, QConfFileSettingsPrivate::sync will handle key merging correctly.
+ loadIndexedDBFiles();
+
QConfFileSettingsPrivate::sync();
QFile file(fileName());
if (file.open(QFile::ReadOnly)) {
QByteArray dataPointer = file.readAll();
- emscripten_idb_async_store("/home/web_user",
- fileName().toLocal8Bit(),
- reinterpret_cast<void *>(dataPointer.data()),
- dataPointer.length(),
- reinterpret_cast<void*>(this),
- QWasmSettingsPrivate_onStore,
- QWasmSettingsPrivate_onError);
+ int error = 0;
+ emscripten_idb_store(DbName, fileName().toLocal8Bit(),
+ reinterpret_cast<void *>(dataPointer.data()), dataPointer.length(),
+ &error);
+ setStatus(!!error ? QSettings::AccessError : QSettings::NoError);
}
}
-void QWasmSettingsPrivate::flush()
-{
- sync();
-}
-
-bool QWasmSettingsPrivate::isWritable() const
-{
- return isReadReady && QConfFileSettingsPrivate::isWritable();
-}
-
-void QWasmSettingsPrivate::syncToLocal(const char *data, int size)
+void QWasmIDBSettingsPrivate::loadIndexedDBFiles()
{
- QFile file(fileName());
-
- if (file.open(QFile::WriteOnly)) {
- file.write(data, size + 1);
- QByteArray data = file.readAll();
-
- emscripten_idb_async_store("/home/web_user",
- fileName().toLocal8Bit(),
- reinterpret_cast<void *>(data.data()),
- data.length(),
- reinterpret_cast<void*>(this),
- QWasmSettingsPrivate_onStore,
- QWasmSettingsPrivate_onError);
- setReady();
+ for (const auto *confFile : getConfFiles()) {
+ int exists = 0;
+ int error = 0;
+ emscripten_idb_exists(DbName, confFile->name.toLocal8Bit(), &exists, &error);
+ if (error) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+ if (exists) {
+ void *contents;
+ int size;
+ emscripten_idb_load(DbName, confFile->name.toLocal8Bit(), &contents, &size, &error);
+ if (error || !writeSettingsToTemporaryFile(confFile->name, contents, size)) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+ }
}
}
-void QWasmSettingsPrivate::loadLocal(const QByteArray &filename)
+QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
+ const QString &organization, const QString &application)
{
- emscripten_idb_async_load("/home/web_user",
- filename.data(),
- reinterpret_cast<void*>(this),
- QWasmSettingsPrivate_onLoad,
- QWasmSettingsPrivate_onError);
-}
+ // Make WebLocalStorageFormat the default native format
+ if (format == QSettings::NativeFormat)
+ format = QSettings::WebLocalStorageFormat;
+
+ // Check if cookies are enabled (required for using persistent storage)
+
+ const bool cookiesEnabled = qstdweb::runTaskOnMainThread<bool>(
+ []() { return val::global("navigator")["cookieEnabled"].as<bool>(); });
+
+ constexpr QLatin1StringView cookiesWarningMessage(
+ "QSettings::%1 requires cookies, falling back to IniFormat with temporary file");
+ if (!cookiesEnabled) {
+ if (format == QSettings::WebLocalStorageFormat) {
+ qWarning() << cookiesWarningMessage.arg("WebLocalStorageFormat");
+ format = QSettings::IniFormat;
+ } else if (format == QSettings::WebIndexedDBFormat) {
+ qWarning() << cookiesWarningMessage.arg("WebIndexedDBFormat");
+ format = QSettings::IniFormat;
+ }
+ }
+ if (format == QSettings::WebIndexedDBFormat && !qstdweb::haveJspi()) {
+ qWarning() << "QSettings::WebIndexedDBFormat requires JSPI, falling back to IniFormat with "
+ "temporary file";
+ format = QSettings::IniFormat;
+ }
-void QWasmSettingsPrivate::setReady()
-{
- isReadReady = true;
- setStatus(QSettings::NoError);
- QConfFileSettingsPrivate::initAccess();
+ // Create settings backend according to selected format
+ switch (format) {
+ case QSettings::Format::WebLocalStorageFormat:
+ return new QWasmLocalStorageSettingsPrivate(scope, organization, application);
+ case QSettings::Format::WebIndexedDBFormat:
+ return new QWasmIDBSettingsPrivate(scope, organization, application);
+ case QSettings::Format::IniFormat:
+ case QSettings::Format::CustomFormat1:
+ case QSettings::Format::CustomFormat2:
+ case QSettings::Format::CustomFormat3:
+ case QSettings::Format::CustomFormat4:
+ case QSettings::Format::CustomFormat5:
+ case QSettings::Format::CustomFormat6:
+ case QSettings::Format::CustomFormat7:
+ case QSettings::Format::CustomFormat8:
+ case QSettings::Format::CustomFormat9:
+ case QSettings::Format::CustomFormat10:
+ case QSettings::Format::CustomFormat11:
+ case QSettings::Format::CustomFormat12:
+ case QSettings::Format::CustomFormat13:
+ case QSettings::Format::CustomFormat14:
+ case QSettings::Format::CustomFormat15:
+ case QSettings::Format::CustomFormat16:
+ return new QConfFileSettingsPrivate(format, scope, organization, application);
+ case QSettings::Format::InvalidFormat:
+ return nullptr;
+ case QSettings::Format::NativeFormat:
+ Q_UNREACHABLE();
+ break;
+ }
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index b2167aa2bc..e88d738fe4 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsettings.h"
@@ -43,6 +7,7 @@
#include "qlist.h"
#include "qmap.h"
#include "qdebug.h"
+#include "qscopeguard.h"
#include <qt_windows.h>
// See "Accessing an Alternate Registry View" at:
@@ -59,6 +24,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user"
key, ie. "foo/bar/alpha/beta". If the variable name starts with 'r', this is a "registry"
key, ie. "\foo\bar\alpha\beta". */
@@ -75,7 +42,7 @@ static const REGSAM registryPermissions = KEY_READ | KEY_WRITE;
static QString keyPath(const QString &rKey)
{
- int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ int idx = rKey.lastIndexOf(u'\\');
if (idx == -1)
return QString();
return rKey.left(idx + 1);
@@ -83,7 +50,7 @@ static QString keyPath(const QString &rKey)
static QString keyName(const QString &rKey)
{
- int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ int idx = rKey.lastIndexOf(u'\\');
QString res;
if (idx == -1)
@@ -91,8 +58,8 @@ static QString keyName(const QString &rKey)
else
res = rKey.mid(idx + 1);
- if (res == QLatin1String("Default") || res == QLatin1String("."))
- res = QLatin1String("");
+ if (res == "Default"_L1 || res == "."_L1)
+ res = ""_L1;
return res;
}
@@ -233,7 +200,7 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
QByteArray buff(m * sizeof(wchar_t), 0);
for (int i = 0; i < n; ++i) {
QString item;
- DWORD l = buff.size() / sizeof(wchar_t);
+ DWORD l = DWORD(buff.size()) / DWORD(sizeof(wchar_t));
if (spec == QSettingsPrivate::ChildKeys) {
res = RegEnumValue(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
} else {
@@ -247,7 +214,7 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
continue;
}
if (item.isEmpty())
- item = QLatin1String(".");
+ item = "."_L1;
result.append(item);
}
return result;
@@ -266,7 +233,7 @@ static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result,
for (int i = 0; i < childKeys.size(); ++i) {
QString s = rSubKey;
if (!s.isEmpty())
- s += QLatin1Char('\\');
+ s += u'\\';
s += childKeys.at(i);
result->insert(s, QString());
}
@@ -274,7 +241,7 @@ static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result,
for (int i = 0; i < childGroups.size(); ++i) {
QString s = rSubKey;
if (!s.isEmpty())
- s += QLatin1Char('\\');
+ s += u'\\';
s += childGroups.at(i);
allKeys(parentHandle, s, result, access);
}
@@ -386,14 +353,14 @@ public:
void remove(const QString &uKey) override;
void set(const QString &uKey, const QVariant &value) override;
- bool get(const QString &uKey, QVariant *value) const override;
+ std::optional<QVariant> get(const QString &uKey) const override;
QStringList children(const QString &uKey, ChildSpec spec) const override;
void clear() override;
void sync() override;
void flush() override;
bool isWritable() const override;
HKEY writeHandle() const;
- bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const;
+ std::optional<QVariant> readKey(HKEY parentHandle, const QString &rSubKey) const;
QString fileName() const override;
private:
@@ -410,9 +377,9 @@ QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &
deleteWriteHandleOnExit = false;
if (!organization.isEmpty()) {
- QString prefix = QLatin1String("Software\\") + organization;
- QString orgPrefix = prefix + QLatin1String("\\OrganizationDefaults");
- QString appPrefix = prefix + QLatin1Char('\\') + application;
+ QString prefix = "Software\\"_L1 + organization;
+ QString orgPrefix = prefix + "\\OrganizationDefaults"_L1;
+ QString appPrefix = prefix + u'\\' + application;
if (scope == QSettings::UserScope) {
if (!application.isEmpty())
@@ -437,34 +404,34 @@ QWinSettingsPrivate::QWinSettingsPrivate(QString rPath, REGSAM access)
{
deleteWriteHandleOnExit = false;
- if (rPath.startsWith(QLatin1Char('\\')))
+ if (rPath.startsWith(u'\\'))
rPath.remove(0, 1);
int keyLength;
HKEY keyName;
- if (rPath.startsWith(QLatin1String("HKEY_CURRENT_USER"))) {
+ if (rPath.startsWith("HKEY_CURRENT_USER"_L1)) {
keyLength = 17;
keyName = HKEY_CURRENT_USER;
- } else if (rPath.startsWith(QLatin1String("HKCU"))) {
+ } else if (rPath.startsWith("HKCU"_L1)) {
keyLength = 4;
keyName = HKEY_CURRENT_USER;
- } else if (rPath.startsWith(QLatin1String("HKEY_LOCAL_MACHINE"))) {
+ } else if (rPath.startsWith("HKEY_LOCAL_MACHINE"_L1)) {
keyLength = 18;
keyName = HKEY_LOCAL_MACHINE;
- } else if (rPath.startsWith(QLatin1String("HKLM"))) {
+ } else if (rPath.startsWith("HKLM"_L1)) {
keyLength = 4;
keyName = HKEY_LOCAL_MACHINE;
- } else if (rPath.startsWith(QLatin1String("HKEY_CLASSES_ROOT"))) {
+ } else if (rPath.startsWith("HKEY_CLASSES_ROOT"_L1)) {
keyLength = 17;
keyName = HKEY_CLASSES_ROOT;
- } else if (rPath.startsWith(QLatin1String("HKCR"))) {
+ } else if (rPath.startsWith("HKCR"_L1)) {
keyLength = 4;
keyName = HKEY_CLASSES_ROOT;
- } else if (rPath.startsWith(QLatin1String("HKEY_USERS"))) {
+ } else if (rPath.startsWith("HKEY_USERS"_L1)) {
keyLength = 10;
keyName = HKEY_USERS;
- } else if (rPath.startsWith(QLatin1String("HKU"))) {
+ } else if (rPath.startsWith("HKU"_L1)) {
keyLength = 3;
keyName = HKEY_USERS;
} else {
@@ -473,11 +440,11 @@ QWinSettingsPrivate::QWinSettingsPrivate(QString rPath, REGSAM access)
if (rPath.length() == keyLength)
regList.append(RegistryKey(keyName, QString(), false, access));
- else if (rPath[keyLength] == QLatin1Char('\\'))
+ else if (rPath[keyLength] == u'\\')
regList.append(RegistryKey(keyName, rPath.mid(keyLength+1), false, access));
}
-bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
+std::optional<QVariant> QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey) const
{
QString rSubkeyName = keyName(rSubKey);
QString rSubkeyPath = keyPath(rSubKey);
@@ -485,16 +452,16 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
// open a handle on the subkey
HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath, access);
if (handle == 0)
- return false;
+ return std::nullopt;
+
+ const auto closeKey = qScopeGuard([handle] { RegCloseKey(handle); });
// get the size and type of the value
DWORD dataType;
DWORD dataSize;
LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize);
- if (res != ERROR_SUCCESS) {
- RegCloseKey(handle);
- return false;
- }
+ if (res != ERROR_SUCCESS)
+ return std::nullopt;
// workaround for rare cases where trailing '\0' are missing in registry
if (dataType == REG_SZ || dataType == REG_EXPAND_SZ)
@@ -506,10 +473,8 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
QByteArray data(dataSize, 0);
res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0,
reinterpret_cast<unsigned char*>(data.data()), &dataSize);
- if (res != ERROR_SUCCESS) {
- RegCloseKey(handle);
- return false;
- }
+ if (res != ERROR_SUCCESS)
+ return std::nullopt;
switch (dataType) {
case REG_EXPAND_SZ:
@@ -518,9 +483,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
if (dataSize) {
s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()));
}
- if (value != 0)
- *value = stringToVariant(s);
- break;
+ return stringToVariant(s);
}
case REG_MULTI_SZ: {
@@ -536,9 +499,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
l.append(s);
}
}
- if (value != 0)
- *value = stringListToVariantList(l);
- break;
+ return stringListToVariantList(l);
}
case REG_NONE:
@@ -547,9 +508,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
if (dataSize) {
s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()), data.size() / 2);
}
- if (value != 0)
- *value = stringToVariant(s);
- break;
+ return stringToVariant(s);
}
case REG_DWORD_BIG_ENDIAN:
@@ -557,29 +516,22 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
Q_ASSERT(data.size() == sizeof(int));
int i;
memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(int));
- if (value != 0)
- *value = i;
- break;
+ return i;
}
case REG_QWORD: {
Q_ASSERT(data.size() == sizeof(qint64));
qint64 i;
memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(qint64));
- if (value != 0)
- *value = i;
- break;
+ return i;
}
default:
qWarning("QSettings: Unknown data %d type in Windows registry", static_cast<int>(dataType));
- if (value != 0)
- *value = QVariant();
break;
}
- RegCloseKey(handle);
- return true;
+ return std::nullopt;
}
HKEY QWinSettingsPrivate::writeHandle() const
@@ -670,9 +622,9 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
QByteArray regValueBuff;
// Determine the type
- switch (value.type()) {
- case QVariant::List:
- case QVariant::StringList: {
+ switch (value.typeId()) {
+ case QMetaType::QVariantList:
+ case QMetaType::QStringList: {
// If none of the elements contains '\0', we can use REG_MULTI_SZ, the
// native registry string list type. Otherwise we use REG_BINARY.
type = REG_MULTI_SZ;
@@ -686,8 +638,8 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
}
if (type == REG_BINARY) {
- QString s = variantToString(value);
- regValueBuff = QByteArray(reinterpret_cast<const char*>(s.utf16()), s.length() * 2);
+ const QString s = variantToString(value);
+ regValueBuff = QByteArray(reinterpret_cast<const char *>(s.data()), s.length() * 2);
} else {
QStringList::const_iterator it = l.constBegin();
for (; it != l.constEnd(); ++it) {
@@ -700,23 +652,23 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
break;
}
- case QVariant::Int:
- case QVariant::UInt: {
+ case QMetaType::Int:
+ case QMetaType::UInt: {
type = REG_DWORD;
qint32 i = value.toInt();
regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint32));
break;
}
- case QVariant::LongLong:
- case QVariant::ULongLong: {
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong: {
type = REG_QWORD;
qint64 i = value.toLongLong();
regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint64));
break;
}
- case QVariant::ByteArray:
+ case QMetaType::QByteArray:
Q_FALLTHROUGH();
default: {
@@ -749,20 +701,21 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
RegCloseKey(handle);
}
-bool QWinSettingsPrivate::get(const QString &uKey, QVariant *value) const
+std::optional<QVariant> QWinSettingsPrivate::get(const QString &uKey) const
{
QString rKey = escapedKey(uKey);
for (const RegistryKey &r : regList) {
HKEY handle = r.handle();
- if (handle != 0 && readKey(handle, rKey, value))
- return true;
-
+ if (handle != 0) {
+ if (auto result = readKey(handle, rKey))
+ return result;
+ }
if (!fallbacks)
- return false;
+ return std::nullopt;
}
- return false;
+ return std::nullopt;
}
QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) const
@@ -772,15 +725,21 @@ QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) c
for (const RegistryKey &r : regList) {
HKEY parent_handle = r.handle();
- if (parent_handle == 0)
- continue;
+ if (parent_handle == 0) {
+ if (fallbacks)
+ continue;
+ break;
+ }
HKEY handle = openKey(parent_handle, KEY_READ, rKey, access);
- if (handle == 0)
- continue;
+ if (handle == 0) {
+ if (fallbacks)
+ continue;
+ break;
+ }
if (spec == AllKeys) {
NameSet keys;
- allKeys(handle, QLatin1String(""), &keys, access);
+ allKeys(handle, ""_L1, &keys, access);
mergeKeySets(&result, keys);
} else { // ChildGroups or ChildKeys
QStringList names = childKeysOrGroups(handle, spec);
@@ -820,9 +779,9 @@ QString QWinSettingsPrivate::fileName() const
const RegistryKey &key = regList.at(0);
QString result;
if (key.parentHandle() == HKEY_CURRENT_USER)
- result = QLatin1String("\\HKEY_CURRENT_USER\\");
+ result = "\\HKEY_CURRENT_USER\\"_L1;
else
- result = QLatin1String("\\HKEY_LOCAL_MACHINE\\");
+ result = "\\HKEY_LOCAL_MACHINE\\"_L1;
return result + regList.at(0).key();
}
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index d95c9015cc..792721f50d 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardpaths.h"
@@ -60,6 +24,7 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
/*!
\class QStandardPaths
\inmodule QtCore
@@ -119,9 +84,9 @@ QT_BEGIN_NAMESPACE
\value HomeLocation Returns the user's home directory (the same as QDir::homePath()). On Unix
systems, this is equal to the HOME environment variable. This value might be
generic or application-specific, but the returned path is never empty.
- \value DataLocation Returns the same value as AppLocalDataLocation. This enumeration value
- is deprecated. Using AppDataLocation is preferable since on Windows, the roaming path is
- recommended.
+ \value AppLocalDataLocation Returns the local settings path on the Windows operating
+ system. On all other platforms, it returns the same value as AppDataLocation.
+ This enum value was added in Qt 5.4.
\value CacheLocation Returns a directory location where user-specific
non-essential (cached) data should be written. This is an application-specific directory.
The returned path is never empty.
@@ -149,13 +114,24 @@ QT_BEGIN_NAMESPACE
QStandardPaths::GenericDataLocation. The returned path is never empty.
On the Windows operating system, this returns the roaming path.
This enum value was added in Qt 5.4.
- \value AppLocalDataLocation Returns the local settings path on the Windows operating
- system. On all other platforms, it returns the same value as AppDataLocation.
- This enum value was added in Qt 5.4.
\value AppConfigLocation Returns a directory location where user-specific
configuration files should be written. This is an application-specific directory,
and the returned path is never empty.
This enum value was added in Qt 5.5.
+ \value PublicShareLocation Returns a directory location where user-specific publicly shared files
+ and directories can be stored. This is a generic value. Note that the returned path may be
+ empty if the system has no concept of a publicly shared location.
+ This enum value was added in Qt 6.4.
+ \value TemplatesLocation Returns a directory location where user-specific
+ template files can be stored. This is a generic value. Note that the returned path may be
+ empty if the system has no concept of a templates location.
+ This enum value was added in Qt 6.4.
+ \value [since 6.7] StateLocation Returns a directory location where user-specific application
+ state data files should be written. This is an application-specific directory,
+ and the returned path is never empty.
+ \value [since 6.7] GenericStateLocation Returns a directory location where shared state data files
+ across applications should be written. This value might be generic or application-specific,
+ but the returned path is never empty.
The following table gives examples of paths on different operating systems.
The first path is the writable path (unless noted). Other, additional
@@ -190,12 +166,15 @@ QT_BEGIN_NAMESPACE
\row \li HomeLocation
\li "~"
\li "C:/Users/<USER>"
- \row \li DataLocation
+ \row \li AppLocalDataLocation
\li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
\li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data", "<APPDIR>/data/<APPNAME>"
\row \li CacheLocation
\li "~/Library/Caches/<APPNAME>", "/Library/Caches/<APPNAME>"
\li "C:/Users/<USER>/AppData/Local/<APPNAME>/cache"
+ \row \li StateLocation
+ \li "~/Library/Preferences/<APPNAME>/State"
+ \li "C:/Users/<USER>/AppData/Local/<APPNAME>/State", "C:/ProgramData/<APPNAME>/State"
\row \li GenericDataLocation
\li "~/Library/Application Support", "/Library/Application Support"
\li "C:/Users/<USER>/AppData/Local", "C:/ProgramData", "<APPDIR>", "<APPDIR>/data"
@@ -210,23 +189,29 @@ QT_BEGIN_NAMESPACE
\li "C:/Users/<USER>/AppData/Local", "C:/ProgramData"
\row \li DownloadLocation
\li "~/Downloads"
- \li "C:/Users/<USER>/Documents"
+ \li "C:/Users/<USER>/Downloads"
\row \li GenericCacheLocation
\li "~/Library/Caches", "/Library/Caches"
\li "C:/Users/<USER>/AppData/Local/cache"
+ \row \li GenericStateLocation
+ \li "~/Library/Preferences/State"
+ \li "C:/Users/<USER>/AppData/Local/State", "C:/ProgramData/State"
\row \li AppDataLocation
\li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
\li "C:/Users/<USER>/AppData/Roaming/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data", "<APPDIR>/data/<APPNAME>"
- \row \li AppLocalDataLocation
- \li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
- \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data", "<APPDIR>/data/<APPNAME>"
\row \li AppConfigLocation
\li "~/Library/Preferences/<APPNAME>"
\li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>"
+ \row \li PublicShareLocation
+ \li "~/Public"
+ \li "C:/Users/Public"
+ \row \li TemplatesLocation
+ \li "~/Templates"
+ \li "C:/Users/<USER>/AppData/Roaming/Microsoft/Windows/Templates"
\endtable
\table
- \header \li Path type \li Linux
+ \header \li Path type \li Linux and other UNIX operating systems
\row \li DesktopLocation
\li "~/Desktop"
\row \li DocumentsLocation
@@ -245,10 +230,12 @@ QT_BEGIN_NAMESPACE
\li "/tmp"
\row \li HomeLocation
\li "~"
- \row \li DataLocation
+ \row \li AppLocalDataLocation
\li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
\row \li CacheLocation
\li "~/.cache/<APPNAME>"
+ \row \li StateLocation
+ \li "~/.local/state/<APPNAME>"
\row \li GenericDataLocation
\li "~/.local/share", "/usr/local/share", "/usr/share"
\row \li RuntimeLocation
@@ -261,12 +248,16 @@ QT_BEGIN_NAMESPACE
\li "~/Downloads"
\row \li GenericCacheLocation
\li "~/.cache"
+ \row \li GenericStateLocation
+ \li "~/.local/state"
\row \li AppDataLocation
\li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
- \row \li AppLocalDataLocation
- \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
\row \li AppConfigLocation
\li "~/.config/<APPNAME>", "/etc/xdg/<APPNAME>"
+ \row \li PublicShareLocation
+ \li "~/Public"
+ \row \li TemplatesLocation
+ \li "~/Templates"
\endtable
\table
@@ -275,7 +266,7 @@ QT_BEGIN_NAMESPACE
\li "<APPROOT>/files"
\li "<APPROOT>/Documents/Desktop"
\row \li DocumentsLocation
- \li "<USER>/Documents", "<USER>/<APPNAME>/Documents"
+ \li "<USER>/Documents" [*], "<USER>/<APPNAME>/Documents"
\li "<APPROOT>/Documents"
\row \li FontsLocation
\li "/system/fonts" (not writable)
@@ -284,13 +275,13 @@ QT_BEGIN_NAMESPACE
\li not supported (directory not readable)
\li not supported
\row \li MusicLocation
- \li "<USER>/Music", "<USER>/<APPNAME>/Music"
+ \li "<USER>/Music" [*], "<USER>/<APPNAME>/Music"
\li "<APPROOT>/Documents/Music"
\row \li MoviesLocation
- \li "<USER>/Movies", "<USER>/<APPNAME>/Movies"
+ \li "<USER>/Movies" [*], "<USER>/<APPNAME>/Movies"
\li "<APPROOT>/Documents/Movies"
\row \li PicturesLocation
- \li "<USER>/Pictures", "<USER>/<APPNAME>/Pictures"
+ \li "<USER>/Pictures" [*], "<USER>/<APPNAME>/Pictures"
\li "<APPROOT>/Documents/Pictures", "assets-library://"
\row \li TempLocation
\li "<APPROOT>/cache"
@@ -298,15 +289,19 @@ QT_BEGIN_NAMESPACE
\row \li HomeLocation
\li "<APPROOT>/files"
\li system defined
- \row \li DataLocation
+ \row \li AppLocalDataLocation
\li "<APPROOT>/files", "<USER>/<APPNAME>/files"
\li "<APPROOT>/Library/Application Support"
\row \li CacheLocation
\li "<APPROOT>/cache", "<USER>/<APPNAME>/cache"
\li "<APPROOT>/Library/Caches"
+ \row \li StateLocation
+ \li "<APPROOT>/files/state"
+ \row \li GenericStateLocation (there is shared state)
+ \li "<APPROOT>/files/state"
\row \li GenericDataLocation
- \li "<USER>"
- \li "<APPROOT>/Documents"
+ \li "<USER>" [*] or "<USER>/<APPNAME>/files"
+ \li "<APPROOT>/Library/Application Support"
\row \li RuntimeLocation
\li "<APPROOT>/cache"
\li not supported
@@ -317,7 +312,7 @@ QT_BEGIN_NAMESPACE
\li "<APPROOT>/files/settings" (there is no shared settings)
\li "<APPROOT>/Library/Preferences"
\row \li DownloadLocation
- \li "<USER>/Downloads", "<USER>/<APPNAME>/Downloads"
+ \li "<USER>/Downloads" [*], "<USER>/<APPNAME>/Downloads"
\li "<APPROOT>/Documents/Downloads"
\row \li GenericCacheLocation
\li "<APPROOT>/cache" (there is no shared cache)
@@ -328,9 +323,12 @@ QT_BEGIN_NAMESPACE
\row \li AppConfigLocation
\li "<APPROOT>/files/settings"
\li "<APPROOT>/Library/Preferences/<APPNAME>"
- \row \li AppLocalDataLocation
- \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
- \li "<APPROOT>/Library/Application Support"
+ \row \li PublicShareLocation
+ \li not supported
+ \li not supported
+ \row \li TemplatesLocation
+ \li not supported
+ \li not supported
\endtable
In the table above, \c <APPNAME> is usually the organization name, the
@@ -350,6 +348,11 @@ QT_BEGIN_NAMESPACE
\note On Android, reading/writing to GenericDataLocation needs the READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE permission granted.
+ \note [*] On Android 11 and above, public directories are no longer directly accessible
+ in scoped storage mode. Thus, paths of the form \c "<USER>/DirName" are not returned.
+ Instead, you can use \l QFileDialog which uses the Storage Access Framework (SAF)
+ to access such directories.
+
\note On iOS, if you do pass \c {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()}
as argument to \l{QFileDialog::setDirectory()},
a native image picker dialog will be used for accessing the user's photo album.
@@ -399,7 +402,7 @@ QString QStandardPaths::locate(StandardLocation type, const QString &fileName, L
{
const QStringList &dirs = standardLocations(type);
for (QStringList::const_iterator dir = dirs.constBegin(); dir != dirs.constEnd(); ++dir) {
- const QString path = *dir + QLatin1Char('/') + fileName;
+ const QString path = *dir + u'/' + fileName;
if (existsAsSpecified(path, options))
return path;
}
@@ -414,7 +417,7 @@ QStringList QStandardPaths::locateAll(StandardLocation type, const QString &file
const QStringList &dirs = standardLocations(type);
QStringList result;
for (QStringList::const_iterator dir = dirs.constBegin(); dir != dirs.constEnd(); ++dir) {
- const QString path = *dir + QLatin1Char('/') + fileName;
+ const QString path = *dir + u'/' + fileName;
if (existsAsSpecified(path, options))
result.append(path);
}
@@ -425,11 +428,9 @@ QStringList QStandardPaths::locateAll(StandardLocation type, const QString &file
static QStringList executableExtensions()
{
// If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
- const QStringList pathExt = QString::fromLocal8Bit(qgetenv("PATHEXT")).toLower().split(QLatin1Char(';'));
- return pathExt.contains(QLatin1String(".exe"), Qt::CaseInsensitive) ?
- pathExt :
- QStringList() << QLatin1String(".exe") << QLatin1String(".com")
- << QLatin1String(".bat") << QLatin1String(".cmd");
+ const QStringList pathExt = QString::fromLocal8Bit(qgetenv("PATHEXT")).toLower().split(u';');
+ return pathExt.contains(".exe"_L1, Qt::CaseInsensitive) ?
+ pathExt : QStringList{".exe"_L1, ".com"_L1, ".bat"_L1, ".cmd"_L1};
}
#endif
@@ -448,7 +449,7 @@ static inline QString searchExecutable(const QStringList &searchPaths,
{
const QDir currentDir = QDir::current();
for (const QString &searchPath : searchPaths) {
- const QString candidate = currentDir.absoluteFilePath(searchPath + QLatin1Char('/') + executableName);
+ const QString candidate = currentDir.absoluteFilePath(searchPath + u'/' + executableName);
const QString absPath = checkExecutable(candidate);
if (!absPath.isEmpty())
return absPath;
@@ -467,7 +468,7 @@ static inline QString
{
const QDir currentDir = QDir::current();
for (const QString &searchPath : searchPaths) {
- const QString candidateRoot = currentDir.absoluteFilePath(searchPath + QLatin1Char('/') + executableName);
+ const QString candidateRoot = currentDir.absoluteFilePath(searchPath + u'/' + executableName);
for (const QString &suffix : suffixes) {
const QString absPath = checkExecutable(candidateRoot + suffix);
if (!absPath.isEmpty())
@@ -517,7 +518,7 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr
searchPaths.reserve(rawPaths.size());
for (const QString &rawPath : rawPaths) {
QString cleanPath = QDir::cleanPath(rawPath);
- if (cleanPath.size() > 1 && cleanPath.endsWith(QLatin1Char('/')))
+ if (cleanPath.size() > 1 && cleanPath.endsWith(u'/'))
cleanPath.truncate(cleanPath.size() - 1);
searchPaths.push_back(cleanPath);
}
@@ -527,9 +528,9 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr
// On Windows, if the name does not have a suffix or a suffix not
// in PATHEXT ("xx.foo"), append suffixes from PATHEXT.
static const QStringList executable_extensions = executableExtensions();
- if (executableName.contains(QLatin1Char('.'))) {
+ if (executableName.contains(u'.')) {
const QString suffix = QFileInfo(executableName).suffix();
- if (suffix.isEmpty() || !executable_extensions.contains(QLatin1Char('.') + suffix, Qt::CaseInsensitive))
+ if (suffix.isEmpty() || !executable_extensions.contains(u'.' + suffix, Qt::CaseInsensitive))
return searchExecutableAppendSuffix(searchPaths, executableName, executable_extensions);
} else {
return searchExecutableAppendSuffix(searchPaths, executableName, executable_extensions);
@@ -539,10 +540,12 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr
}
/*!
+ \fn QString QStandardPaths::displayName(StandardLocation type)
+
\include standardpath/functiondocs.qdocinc displayName
*/
-#if !defined(Q_OS_MAC) && !defined(QT_BOOTSTRAPPED)
+#if !defined(Q_OS_DARWIN) && !defined(QT_BOOTSTRAPPED)
QString QStandardPaths::displayName(StandardLocation type)
{
switch (type) {
@@ -564,8 +567,12 @@ QString QStandardPaths::displayName(StandardLocation type)
return QCoreApplication::translate("QStandardPaths", "Temporary Directory");
case HomeLocation:
return QCoreApplication::translate("QStandardPaths", "Home");
+ case AppLocalDataLocation:
+ return QCoreApplication::translate("QStandardPaths", "Application Data");
case CacheLocation:
return QCoreApplication::translate("QStandardPaths", "Cache");
+ case StateLocation:
+ return QCoreApplication::translate("QStandardPaths", "State");
case GenericDataLocation:
return QCoreApplication::translate("QStandardPaths", "Shared Data");
case RuntimeLocation:
@@ -576,13 +583,17 @@ QString QStandardPaths::displayName(StandardLocation type)
return QCoreApplication::translate("QStandardPaths", "Shared Configuration");
case GenericCacheLocation:
return QCoreApplication::translate("QStandardPaths", "Shared Cache");
+ case GenericStateLocation:
+ return QCoreApplication::translate("QStandardPaths", "Shared State");
case DownloadLocation:
return QCoreApplication::translate("QStandardPaths", "Download");
case AppDataLocation:
- case AppLocalDataLocation:
- return QCoreApplication::translate("QStandardPaths", "Application Data");
case AppConfigLocation:
return QCoreApplication::translate("QStandardPaths", "Application Configuration");
+ case PublicShareLocation:
+ return QCoreApplication::translate("QStandardPaths", "Public");
+ case TemplatesLocation:
+ return QCoreApplication::translate("QStandardPaths", "Templates");
}
// not reached
return QString();
@@ -590,23 +601,12 @@ QString QStandardPaths::displayName(StandardLocation type)
#endif
/*!
- \fn void QStandardPaths::enableTestMode(bool testMode)
- \obsolete Use QStandardPaths::setTestModeEnabled
- */
-/*!
\fn void QStandardPaths::setTestModeEnabled(bool testMode)
\include standardpath/functiondocs.qdocinc setTestModeEnabled
*/
-static bool qsp_testMode = false;
-
-#if QT_DEPRECATED_SINCE(5, 2)
-void QStandardPaths::enableTestMode(bool testMode)
-{
- qsp_testMode = testMode;
-}
-#endif
+Q_CONSTINIT static bool qsp_testMode = false;
void QStandardPaths::setTestModeEnabled(bool testMode)
{
diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h
index df76d73eae..56aa2b100c 100644
--- a/src/corelib/io/qstandardpaths.h
+++ b/src/corelib/io/qstandardpaths.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTANDARDPATHS_H
#define QSTANDARDPATHS_H
@@ -53,7 +17,6 @@ class Q_CORE_EXPORT QStandardPaths
Q_GADGET
public:
- // Do not re-order, must match QDesktopServices
enum StandardLocation {
DesktopLocation,
DocumentsLocation,
@@ -64,7 +27,7 @@ public:
PicturesLocation,
TempLocation,
HomeLocation,
- DataLocation,
+ AppLocalDataLocation,
CacheLocation,
GenericDataLocation,
RuntimeLocation,
@@ -74,7 +37,10 @@ public:
GenericConfigLocation,
AppDataLocation,
AppConfigLocation,
- AppLocalDataLocation = DataLocation
+ PublicShareLocation,
+ TemplatesLocation,
+ StateLocation,
+ GenericStateLocation,
};
Q_ENUM(StandardLocation)
@@ -96,9 +62,6 @@ public:
static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList());
-#if QT_DEPRECATED_SINCE(5, 2)
- static QT_DEPRECATED void enableTestMode(bool testMode);
-#endif
static void setTestModeEnabled(bool testMode);
static bool isTestModeEnabled();
diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp
index 1f4e0de1e7..f39b6855b6 100644
--- a/src/corelib/io/qstandardpaths_android.cpp
+++ b/src/corelib/io/qstandardpaths_android.cpp
@@ -1,84 +1,35 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardpaths.h"
#ifndef QT_NO_STANDARDPATHS
-#include <QtCore/private/qjni_p.h>
-#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qjniobject.h>
#include <QtCore/qmap.h>
+#include <QtCore/qcoreapplication.h>
#include <QDir>
QT_BEGIN_NAMESPACE
+Q_DECLARE_JNI_CLASS(Environment, "android/os/Environment");
+Q_DECLARE_JNI_CLASS(File, "java/io/File");
+
+using namespace QNativeInterface;
+using namespace Qt::StringLiterals;
+
typedef QMap<QString, QString> AndroidDirCache;
Q_GLOBAL_STATIC(AndroidDirCache, androidDirCache)
static QString testDir()
{
- return QStandardPaths::isTestModeEnabled() ? QLatin1String("/qttest")
- : QLatin1String("");
+ return QStandardPaths::isTestModeEnabled() ? "/qttest"_L1 : ""_L1;
}
-static QJNIObjectPrivate applicationContext()
+static inline QString getAbsolutePath(const QJniObject &file)
{
- static QJNIObjectPrivate appCtx;
- if (appCtx.isValid())
- return appCtx;
-
- QJNIObjectPrivate context(QtAndroidPrivate::activity());
- if (!context.isValid()) {
- context = QtAndroidPrivate::service();
- if (!context.isValid())
- return appCtx;
- }
+ QJniObject path = file.callMethod<jstring>("getAbsolutePath");
- appCtx = context.callObjectMethod("getApplicationContext",
- "()Landroid/content/Context;");
- return appCtx;
-}
-
-static inline QString getAbsolutePath(const QJNIObjectPrivate &file)
-{
- QJNIObjectPrivate path = file.callObjectMethod("getAbsolutePath",
- "()Ljava/lang/String;");
if (!path.isValid())
return QString();
@@ -95,9 +46,8 @@ static QString getExternalStorageDirectory()
if (!path.isEmpty())
return path;
- QJNIObjectPrivate file = QJNIObjectPrivate::callStaticObjectMethod("android/os/Environment",
- "getExternalStorageDirectory",
- "()Ljava/io/File;");
+ QJniObject file = QJniObject::callStaticMethod<QtJniTypes::File>("android/os/Environment",
+ "getExternalStorageDirectory");
if (!file.isValid())
return QString();
@@ -105,7 +55,7 @@ static QString getExternalStorageDirectory()
}
/*
- * Locations where applications can place user files (public).
+ * Locations where applications can place user files shared by all apps (public).
* E.g., /storage/Music
*/
static QString getExternalStoragePublicDirectory(const char *directoryField)
@@ -114,16 +64,14 @@ static QString getExternalStoragePublicDirectory(const char *directoryField)
if (!path.isEmpty())
return path;
- QJNIObjectPrivate dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment",
- directoryField,
- "Ljava/lang/String;");
+ QJniObject dirField = QJniObject::getStaticField<jstring>("android/os/Environment",
+ directoryField);
if (!dirField.isValid())
return QString();
- QJNIObjectPrivate file = QJNIObjectPrivate::callStaticObjectMethod("android/os/Environment",
- "getExternalStoragePublicDirectory",
- "(Ljava/lang/String;)Ljava/io/File;",
- dirField.object());
+ QJniObject file = QJniObject::callStaticMethod<QtJniTypes::File>("android/os/Environment",
+ "getExternalStoragePublicDirectory",
+ dirField.object<jstring>());
if (!file.isValid())
return QString();
@@ -134,28 +82,25 @@ static QString getExternalStoragePublicDirectory(const char *directoryField)
* Locations where applications can place persistent files it owns.
* E.g., /storage/org.app/Music
*/
-static QString getExternalFilesDir(const char *directoryField = 0)
+static QString getExternalFilesDir(const char *directoryField = nullptr)
{
- QString &path = (*androidDirCache)[QLatin1String("APPNAME_%1").arg(QLatin1String(directoryField))];
+ QString &path = (*androidDirCache)["APPNAME_%1"_L1.arg(QLatin1StringView(directoryField))];
if (!path.isEmpty())
return path;
- QJNIObjectPrivate appCtx = applicationContext();
+ QJniObject appCtx = QAndroidApplication::context();
if (!appCtx.isValid())
return QString();
- QJNIObjectPrivate dirField = QJNIObjectPrivate::fromString(QLatin1String(""));
- if (directoryField) {
- dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment",
- directoryField,
- "Ljava/lang/String;");
+ QJniObject dirField = QJniObject::fromString(""_L1);
+ if (directoryField && strlen(directoryField) > 0) {
+ dirField = QJniObject::getStaticField<QtJniTypes::Environment, jstring>(directoryField);
if (!dirField.isValid())
return QString();
}
- QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalFilesDir",
- "(Ljava/lang/String;)Ljava/io/File;",
- dirField.object());
+ QJniObject file = appCtx.callMethod<QtJniTypes::File>("getExternalFilesDir",
+ dirField.object<jstring>());
if (!file.isValid())
return QString();
@@ -173,12 +118,11 @@ static QString getExternalCacheDir()
if (!path.isEmpty())
return path;
- QJNIObjectPrivate appCtx = applicationContext();
+ QJniObject appCtx = QAndroidApplication::context();
if (!appCtx.isValid())
return QString();
- QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalCacheDir",
- "()Ljava/io/File;");
+ QJniObject file = appCtx.callMethod<QtJniTypes::File>("getExternalCacheDir");
if (!file.isValid())
return QString();
@@ -195,12 +139,11 @@ static QString getCacheDir()
if (!path.isEmpty())
return path;
- QJNIObjectPrivate appCtx = applicationContext();
+ QJniObject appCtx = QAndroidApplication::context();
if (!appCtx.isValid())
return QString();
- QJNIObjectPrivate file = appCtx.callObjectMethod("getCacheDir",
- "()Ljava/io/File;");
+ QJniObject file = appCtx.callMethod<QtJniTypes::File>("getCacheDir");
if (!file.isValid())
return QString();
@@ -217,37 +160,49 @@ static QString getFilesDir()
if (!path.isEmpty())
return path;
- QJNIObjectPrivate appCtx = applicationContext();
+ QJniObject appCtx = QAndroidApplication::context();
if (!appCtx.isValid())
return QString();
- QJNIObjectPrivate file = appCtx.callObjectMethod("getFilesDir",
- "()Ljava/io/File;");
+ QJniObject file = appCtx.callMethod<QtJniTypes::File>("getFilesDir");
if (!file.isValid())
return QString();
return (path = getAbsolutePath(file));
}
+static QString getSdkBasedExternalDir(const char *directoryField = nullptr)
+{
+ return (QNativeInterface::QAndroidApplication::sdkVersion() >= 30)
+ ? getExternalFilesDir(directoryField)
+ : getExternalStoragePublicDirectory(directoryField);
+}
+
QString QStandardPaths::writableLocation(StandardLocation type)
{
switch (type) {
case QStandardPaths::MusicLocation:
- return getExternalStoragePublicDirectory("DIRECTORY_MUSIC");
+ return getSdkBasedExternalDir("DIRECTORY_MUSIC");
case QStandardPaths::MoviesLocation:
- return getExternalStoragePublicDirectory("DIRECTORY_MOVIES");
+ return getSdkBasedExternalDir("DIRECTORY_MOVIES");
case QStandardPaths::PicturesLocation:
- return getExternalStoragePublicDirectory("DIRECTORY_PICTURES");
+ return getSdkBasedExternalDir("DIRECTORY_PICTURES");
case QStandardPaths::DocumentsLocation:
- return getExternalStoragePublicDirectory("DIRECTORY_DOCUMENTS");
+ return getSdkBasedExternalDir("DIRECTORY_DOCUMENTS");
case QStandardPaths::DownloadLocation:
- return getExternalStoragePublicDirectory("DIRECTORY_DOWNLOADS");
+ return getSdkBasedExternalDir("DIRECTORY_DOWNLOADS");
case QStandardPaths::GenericConfigLocation:
case QStandardPaths::ConfigLocation:
case QStandardPaths::AppConfigLocation:
- return getFilesDir() + testDir() + QLatin1String("/settings");
+ return getFilesDir() + testDir() + "/settings"_L1;
+ case QStandardPaths::StateLocation:
+ case QStandardPaths::GenericStateLocation:
+ return getFilesDir() + testDir() + "/state"_L1;
case QStandardPaths::GenericDataLocation:
- return getExternalStorageDirectory() + testDir();
+ {
+ return QAndroidApplication::sdkVersion() >= 30 ?
+ getExternalFilesDir() + testDir() : getExternalStorageDirectory() + testDir();
+ }
case QStandardPaths::AppDataLocation:
case QStandardPaths::AppLocalDataLocation:
return getFilesDir() + testDir();
@@ -261,6 +216,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return getFilesDir();
case QStandardPaths::ApplicationsLocation:
case QStandardPaths::FontsLocation:
+ case QStandardPaths::PublicShareLocation:
+ case QStandardPaths::TemplatesLocation:
default:
break;
}
@@ -270,62 +227,53 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QStringList QStandardPaths::standardLocations(StandardLocation type)
{
- if (type == MusicLocation) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir("DIRECTORY_MUSIC")
- << getExternalStoragePublicDirectory("DIRECTORY_PODCASTS")
- << getExternalFilesDir("DIRECTORY_PODCASTS")
- << getExternalStoragePublicDirectory("DIRECTORY_NOTIFICATIONS")
- << getExternalFilesDir("DIRECTORY_NOTIFICATIONS")
- << getExternalStoragePublicDirectory("DIRECTORY_ALARMS")
- << getExternalFilesDir("DIRECTORY_ALARMS");
- }
-
- if (type == MoviesLocation) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir("DIRECTORY_MOVIES");
- }
+ QStringList locations;
- if (type == PicturesLocation) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir("DIRECTORY_PICTURES");
- }
-
- if (type == DocumentsLocation) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir("DIRECTORY_DOCUMENTS");
- }
-
- if (type == DownloadLocation) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir("DIRECTORY_DOWNLOADS");
- }
-
- if (type == AppDataLocation || type == AppLocalDataLocation) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir();
- }
-
- if (type == CacheLocation) {
- return QStringList() << writableLocation(type)
- << getExternalCacheDir();
- }
-
- if (type == FontsLocation) {
+ if (type == MusicLocation) {
+ locations << getExternalFilesDir("DIRECTORY_MUSIC");
+ // Place the public dirs before the app own dirs
+ if (QNativeInterface::QAndroidApplication::sdkVersion() < 30) {
+ locations << getExternalStoragePublicDirectory("DIRECTORY_PODCASTS")
+ << getExternalStoragePublicDirectory("DIRECTORY_NOTIFICATIONS")
+ << getExternalStoragePublicDirectory("DIRECTORY_ALARMS");
+ }
+ locations << getExternalFilesDir("DIRECTORY_PODCASTS")
+ << getExternalFilesDir("DIRECTORY_NOTIFICATIONS")
+ << getExternalFilesDir("DIRECTORY_ALARMS");
+ } else if (type == MoviesLocation) {
+ locations << getExternalFilesDir("DIRECTORY_MOVIES");
+ } else if (type == PicturesLocation) {
+ locations << getExternalFilesDir("DIRECTORY_PICTURES");
+ } else if (type == DocumentsLocation) {
+ locations << getExternalFilesDir("DIRECTORY_DOCUMENTS");
+ } else if (type == DownloadLocation) {
+ locations << getExternalFilesDir("DIRECTORY_DOWNLOADS");
+ } else if (type == AppDataLocation || type == AppLocalDataLocation) {
+ locations << getExternalFilesDir();
+ } else if (type == CacheLocation) {
+ locations << getExternalCacheDir();
+ } else if (type == FontsLocation) {
QString &fontLocation = (*androidDirCache)[QStringLiteral("FONT_LOCATION")];
- if (!fontLocation.isEmpty())
- return QStringList(fontLocation);
-
- const QByteArray ba = qgetenv("QT_ANDROID_FONT_LOCATION");
- if (!ba.isEmpty())
- return QStringList((fontLocation = QDir::cleanPath(QString::fromLocal8Bit(ba))));
-
- // Don't cache the fallback, as we might just have been called before
- // QT_ANDROID_FONT_LOCATION has been set.
- return QStringList(QLatin1String("/system/fonts"));
+ if (!fontLocation.isEmpty()) {
+ locations << fontLocation;
+ } else {
+ const QByteArray ba = qgetenv("QT_ANDROID_FONT_LOCATION");
+ if (!ba.isEmpty()) {
+ locations << (fontLocation = QDir::cleanPath(QString::fromLocal8Bit(ba)));
+ } else {
+ // Don't cache the fallback, as we might just have been called before
+ // QT_ANDROID_FONT_LOCATION has been set.
+ locations << "/system/fonts"_L1;
+ }
+ }
}
- return QStringList(writableLocation(type));
+ const QString writable = writableLocation(type);
+ if (!writable.isEmpty())
+ locations.prepend(writable);
+
+ locations.removeDuplicates();
+ return locations;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qstandardpaths_haiku.cpp b/src/corelib/io/qstandardpaths_haiku.cpp
index 044d69fe45..93eba134f3 100644
--- a/src/corelib/io/qstandardpaths_haiku.cpp
+++ b/src/corelib/io/qstandardpaths_haiku.cpp
@@ -1,41 +1,5 @@
-/***************************************************************************
-**
-** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardpaths.h"
@@ -61,10 +25,10 @@ void appendOrganizationAndApp(QString &path)
#ifndef QT_BOOTSTRAPPED
const QString org = QCoreApplication::organizationName();
if (!org.isEmpty())
- path += QLatin1Char('/') + org;
+ path += u'/' + org;
const QString appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
- path += QLatin1Char('/') + appName;
+ path += u'/' + appName;
#else
Q_UNUSED(path);
#endif
@@ -137,6 +101,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case MusicLocation:
case MoviesLocation:
case DownloadLocation:
+ case PublicShareLocation:
+ case TemplatesLocation:
case HomeLocation:
return haikuStandardPath(B_USER_DIRECTORY);
case FontsLocation:
@@ -154,8 +120,10 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return haikuAppStandardPath(B_USER_CACHE_DIRECTORY);
case GenericCacheLocation:
return haikuStandardPath(B_USER_CACHE_DIRECTORY);
- case ConfigLocation: // fall through
+ case ConfigLocation:
case AppConfigLocation:
+ case StateLocation:
+ case GenericStateLocation:
return haikuAppStandardPath(B_USER_SETTINGS_DIRECTORY);
case GenericConfigLocation:
return haikuStandardPath(B_USER_SETTINGS_DIRECTORY);
@@ -178,6 +146,8 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
case MusicLocation:
case MoviesLocation:
case DownloadLocation:
+ case PublicShareLocation:
+ case TemplatesLocation:
case HomeLocation:
paths += haikuStandardPath(B_USER_NONPACKAGED_DIRECTORY);
break;
diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm
index 11b5cc8c37..2acbe92736 100644
--- a/src/corelib/io/qstandardpaths_mac.mm
+++ b/src/corelib/io/qstandardpaths_mac.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardpaths.h"
@@ -53,6 +17,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QString pathForDirectory(NSSearchPathDirectory directory,
NSSearchPathDomainMask mask)
{
@@ -85,6 +51,9 @@ static NSSearchPathDirectory searchPathDirectory(QStandardPaths::StandardLocatio
return NSCachesDirectory;
case QStandardPaths::DownloadLocation:
return NSDownloadsDirectory;
+ case QStandardPaths::PublicShareLocation:
+ return NSSharedPublicDirectory;
+ case QStandardPaths::TemplatesLocation:
default:
return (NSSearchPathDirectory)0;
}
@@ -95,10 +64,10 @@ static void appendOrganizationAndApp(QString &path)
#ifndef QT_BOOTSTRAPPED
const QString org = QCoreApplication::organizationName();
if (!org.isEmpty())
- path += QLatin1Char('/') + org;
+ path += u'/' + org;
const QString appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
- path += QLatin1Char('/') + appName;
+ path += u'/' + appName;
#else
Q_UNUSED(path);
#endif
@@ -120,30 +89,42 @@ static QString baseWritableLocation(QStandardPaths::StandardLocation type,
#if defined(QT_PLATFORM_UIKIT)
// These locations point to non-existing write-protected paths. Use sensible fallbacks.
case QStandardPaths::MusicLocation:
- path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Music");
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Music"_L1;
break;
case QStandardPaths::MoviesLocation:
- path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Movies");
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Movies"_L1;
break;
case QStandardPaths::PicturesLocation:
- path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Pictures");
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Pictures"_L1;
break;
case QStandardPaths::DownloadLocation:
- path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Downloads");
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Downloads"_L1;
break;
case QStandardPaths::DesktopLocation:
- path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Desktop");
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Desktop"_L1;
break;
case QStandardPaths::ApplicationsLocation:
break;
+ case QStandardPaths::PublicShareLocation:
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Public"_L1;
+ break;
+ case QStandardPaths::TemplatesLocation:
+ path = pathForDirectory(NSDocumentDirectory, mask) + "/Templates"_L1;
+ break;
#endif
case QStandardPaths::FontsLocation:
- path = pathForDirectory(NSLibraryDirectory, mask) + QLatin1String("/Fonts");
+ path = pathForDirectory(NSLibraryDirectory, mask) + "/Fonts"_L1;
break;
case QStandardPaths::ConfigLocation:
case QStandardPaths::GenericConfigLocation:
case QStandardPaths::AppConfigLocation:
- path = pathForDirectory(NSLibraryDirectory, mask) + QLatin1String("/Preferences");
+ path = pathForDirectory(NSLibraryDirectory, mask) + "/Preferences"_L1;
+ break;
+ case QStandardPaths::StateLocation:
+ if (appendOrgAndApp) { break; }
+ Q_FALLTHROUGH();
+ case QStandardPaths::GenericStateLocation:
+ path = pathForDirectory(NSLibraryDirectory, mask) + "/Preferences/State"_L1;
break;
default:
path = pathForDirectory(dir, mask);
@@ -158,6 +139,11 @@ static QString baseWritableLocation(QStandardPaths::StandardLocation type,
case QStandardPaths::CacheLocation:
appendOrganizationAndApp(path);
break;
+ case QStandardPaths::StateLocation:
+ path = pathForDirectory(NSLibraryDirectory, mask) + "/Preferences"_L1;
+ appendOrganizationAndApp(path);
+ path += "/State"_L1;
+ break;
default:
break;
}
@@ -170,7 +156,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
{
QString location = baseWritableLocation(type, NSUserDomainMask, true);
if (isTestModeEnabled())
- location = location.replace(QDir::homePath(), QDir::homePath() + QLatin1String("/.qttest"));
+ location = location.replace(QDir::homePath(), QDir::homePath() + "/.qttest"_L1);
return location;
}
@@ -181,7 +167,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
#if defined(QT_PLATFORM_UIKIT)
if (type == PicturesLocation)
- dirs << writableLocation(PicturesLocation) << QLatin1String("assets-library://");
+ dirs << writableLocation(PicturesLocation) << "assets-library://"_L1;
#endif
if (type == GenericDataLocation || type == FontsLocation || type == ApplicationsLocation
@@ -230,8 +216,10 @@ QString QStandardPaths::displayName(StandardLocation type)
// The temporary directory returned by the old Carbon APIs is ~/Library/Caches/TemporaryItems,
// the display name of which ("TemporaryItems") isn't translated by the system. The standard
// temporary directory has no reasonable display name either, so use something more sensible.
- if (QStandardPaths::TempLocation == type)
+ if (QStandardPaths::TempLocation == type) {
+ //: macOS: Temporary directory
return QCoreApplication::translate("QStandardPaths", "Temporary Items");
+ }
// standardLocations() may return an empty list on some platforms
if (QStandardPaths::ApplicationsLocation == type)
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index ca2a2689f1..e38f670895 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardpaths.h"
#include <qdir.h>
@@ -57,42 +22,154 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static void appendOrganizationAndApp(QString &path)
{
#ifndef QT_BOOTSTRAPPED
const QString org = QCoreApplication::organizationName();
if (!org.isEmpty())
- path += QLatin1Char('/') + org;
+ path += u'/' + org;
const QString appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
- path += QLatin1Char('/') + appName;
+ path += u'/' + appName;
#else
Q_UNUSED(path);
#endif
}
#if QT_CONFIG(regularexpression)
-static QLatin1String xdg_key_name(QStandardPaths::StandardLocation type)
+static QLatin1StringView xdg_key_name(QStandardPaths::StandardLocation type)
{
switch (type) {
case QStandardPaths::DesktopLocation:
- return QLatin1String("DESKTOP");
+ return "DESKTOP"_L1;
case QStandardPaths::DocumentsLocation:
- return QLatin1String("DOCUMENTS");
+ return "DOCUMENTS"_L1;
case QStandardPaths::PicturesLocation:
- return QLatin1String("PICTURES");
+ return "PICTURES"_L1;
case QStandardPaths::MusicLocation:
- return QLatin1String("MUSIC");
+ return "MUSIC"_L1;
case QStandardPaths::MoviesLocation:
- return QLatin1String("VIDEOS");
+ return "VIDEOS"_L1;
case QStandardPaths::DownloadLocation:
- return QLatin1String("DOWNLOAD");
+ return "DOWNLOAD"_L1;
+ case QStandardPaths::PublicShareLocation:
+ return "PUBLICSHARE"_L1;
+ case QStandardPaths::TemplatesLocation:
+ return "TEMPLATES"_L1;
default:
- return QLatin1String();
+ return {};
}
}
#endif
+static QByteArray unixPermissionsText(QFile::Permissions permissions)
+{
+ mode_t perms = 0;
+ if (permissions & QFile::ReadOwner)
+ perms |= S_IRUSR;
+ if (permissions & QFile::WriteOwner)
+ perms |= S_IWUSR;
+ if (permissions & QFile::ExeOwner)
+ perms |= S_IXUSR;
+ if (permissions & QFile::ReadGroup)
+ perms |= S_IRGRP;
+ if (permissions & QFile::WriteGroup)
+ perms |= S_IWGRP;
+ if (permissions & QFile::ExeGroup)
+ perms |= S_IXGRP;
+ if (permissions & QFile::ReadOther)
+ perms |= S_IROTH;
+ if (permissions & QFile::WriteOther)
+ perms |= S_IWOTH;
+ if (permissions & QFile::ExeOther)
+ perms |= S_IXOTH;
+ return '0' + QByteArray::number(perms, 8);
+}
+
+static bool checkXdgRuntimeDir(const QString &xdgRuntimeDir)
+{
+ auto describeMetaData = [](const QFileSystemMetaData &metaData) -> QByteArray {
+ if (!metaData.exists())
+ return "a broken symlink";
+
+ QByteArray description;
+ if (metaData.isLink())
+ description = "a symbolic link to ";
+
+ if (metaData.isFile())
+ description += "a regular file";
+ else if (metaData.isDirectory())
+ description += "a directory";
+ else if (metaData.isSequential())
+ description += "a character device, socket or FIFO";
+ else
+ description += "a block device";
+
+ description += " permissions " + unixPermissionsText(metaData.permissions());
+
+ return description
+ + " owned by UID " + QByteArray::number(metaData.userId())
+ + " GID " + QByteArray::number(metaData.groupId());
+ };
+
+ // http://standards.freedesktop.org/basedir-spec/latest/
+ const uint myUid = uint(geteuid());
+ const QFile::Permissions wantedPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
+ const QFileSystemMetaData::MetaDataFlags statFlags = QFileSystemMetaData::PosixStatFlags
+ | QFileSystemMetaData::LinkType;
+ QFileSystemMetaData metaData;
+ QFileSystemEntry entry(xdgRuntimeDir);
+
+ // Check that the xdgRuntimeDir is a directory by attempting to create it.
+ // A stat() before mkdir() that concluded it doesn't exist is a meaningless
+ // result: we'd race against someone else attempting to create it.
+ // ### QFileSystemEngine::createDirectory cannot take the extra mode argument.
+ if (QT_MKDIR(entry.nativeFilePath(), 0700) == 0)
+ return true;
+ if (errno != EEXIST) {
+ qErrnoWarning("QStandardPaths: error creating runtime directory '%ls'",
+ qUtf16Printable(xdgRuntimeDir));
+ return false;
+ }
+
+ // We use LinkType to force an lstat(), but fillMetaData() still returns error
+ // on broken symlinks.
+ if (!QFileSystemEngine::fillMetaData(entry, metaData, statFlags) && !metaData.isLink()) {
+ qErrnoWarning("QStandardPaths: error obtaining permissions of runtime directory '%ls'",
+ qUtf16Printable(xdgRuntimeDir));
+ return false;
+ }
+
+ // Checks:
+ // - is a directory
+ // - is not a symlink (even is pointing to a directory)
+ if (metaData.isLink() || !metaData.isDirectory()) {
+ qWarning("QStandardPaths: runtime directory '%ls' is not a directory, but %s",
+ qUtf16Printable(xdgRuntimeDir), describeMetaData(metaData).constData());
+ return false;
+ }
+
+ // - "The directory MUST be owned by the user"
+ if (metaData.userId() != myUid) {
+ qWarning("QStandardPaths: runtime directory '%ls' is not owned by UID %d, but %s",
+ qUtf16Printable(xdgRuntimeDir), myUid, describeMetaData(metaData).constData());
+ return false;
+ }
+
+ // "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700."
+ if (metaData.permissions() != wantedPerms) {
+ qWarning("QStandardPaths: wrong permissions on runtime directory %ls, %s instead of %s",
+ qUtf16Printable(xdgRuntimeDir),
+ unixPermissionsText(metaData.permissions()).constData(),
+ unixPermissionsText(wantedPerms).constData());
+ return false;
+ }
+
+ return true;
+}
+
QString QStandardPaths::writableLocation(StandardLocation type)
{
switch (type) {
@@ -103,25 +180,56 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case CacheLocation:
case GenericCacheLocation:
{
- // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
- QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
- if (isTestModeEnabled())
- xdgCacheHome = QDir::homePath() + QLatin1String("/.qttest/cache");
- if (xdgCacheHome.isEmpty())
- xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
+ QString xdgCacheHome;
+ if (isTestModeEnabled()) {
+ xdgCacheHome = QDir::homePath() + "/.qttest/cache"_L1;
+ } else {
+ // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
+ xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
+ if (!xdgCacheHome.startsWith(u'/'))
+ xdgCacheHome.clear(); // spec says relative paths should be ignored
+
+ if (xdgCacheHome.isEmpty())
+ xdgCacheHome = QDir::homePath() + "/.cache"_L1;
+ }
if (type == QStandardPaths::CacheLocation)
appendOrganizationAndApp(xdgCacheHome);
return xdgCacheHome;
}
+ case StateLocation:
+ case GenericStateLocation:
+ {
+ QString xdgStateHome;
+ if (isTestModeEnabled()) {
+ xdgStateHome = QDir::homePath() + "/.qttest/state"_L1;
+ } else {
+ // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
+ xdgStateHome = QFile::decodeName(qgetenv("XDG_STATE_HOME"));
+ if (!xdgStateHome.startsWith(u'/'))
+ xdgStateHome.clear(); // spec says relative paths should be ignored
+
+ if (xdgStateHome.isEmpty())
+ xdgStateHome = QDir::homePath() + "/.local/state"_L1;
+ }
+ if (type == QStandardPaths::StateLocation)
+ appendOrganizationAndApp(xdgStateHome);
+ return xdgStateHome;
+ }
case AppDataLocation:
case AppLocalDataLocation:
case GenericDataLocation:
{
- QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
- if (isTestModeEnabled())
- xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share");
- if (xdgDataHome.isEmpty())
- xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
+ QString xdgDataHome;
+ if (isTestModeEnabled()) {
+ xdgDataHome = QDir::homePath() + "/.qttest/share"_L1;
+ } else {
+ xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
+ if (!xdgDataHome.startsWith(u'/'))
+ xdgDataHome.clear(); // spec says relative paths should be ignored
+
+ if (xdgDataHome.isEmpty())
+ xdgDataHome = QDir::homePath() + "/.local/share"_L1;
+ }
if (type == AppDataLocation || type == AppLocalDataLocation)
appendOrganizationAndApp(xdgDataHome);
return xdgDataHome;
@@ -130,70 +238,43 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case GenericConfigLocation:
case AppConfigLocation:
{
- // http://standards.freedesktop.org/basedir-spec/latest/
- QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
- if (isTestModeEnabled())
- xdgConfigHome = QDir::homePath() + QLatin1String("/.qttest/config");
- if (xdgConfigHome.isEmpty())
- xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
+ QString xdgConfigHome;
+ if (isTestModeEnabled()) {
+ xdgConfigHome = QDir::homePath() + "/.qttest/config"_L1;
+ } else {
+ // http://standards.freedesktop.org/basedir-spec/latest/
+ xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
+ if (!xdgConfigHome.startsWith(u'/'))
+ xdgConfigHome.clear(); // spec says relative paths should be ignored
+
+ if (xdgConfigHome.isEmpty())
+ xdgConfigHome = QDir::homePath() + "/.config"_L1;
+ }
if (type == AppConfigLocation)
appendOrganizationAndApp(xdgConfigHome);
return xdgConfigHome;
}
case RuntimeLocation:
{
- // http://standards.freedesktop.org/basedir-spec/latest/
- const uint myUid = uint(geteuid());
- // since the current user is the owner, set both xxxUser and xxxOwner
- const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
- | QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
- QFileInfo fileInfo;
QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
- if (xdgRuntimeDir.isEmpty()) {
+ if (!xdgRuntimeDir.startsWith(u'/'))
+ xdgRuntimeDir.clear(); // spec says relative paths should be ignored
+
+ bool fromEnv = !xdgRuntimeDir.isEmpty();
+ if (xdgRuntimeDir.isEmpty() || !checkXdgRuntimeDir(xdgRuntimeDir)) {
+ // environment variable not set or is set to something unsuitable
+ const uint myUid = uint(geteuid());
const QString userName = QFileSystemEngine::resolveUserName(myUid);
- xdgRuntimeDir = QDir::tempPath() + QLatin1String("/runtime-") + userName;
- fileInfo.setFile(xdgRuntimeDir);
+ xdgRuntimeDir = QDir::tempPath() + "/runtime-"_L1 + userName;
+
+ if (!fromEnv) {
#ifndef Q_OS_WASM
- qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%ls'", qUtf16Printable(xdgRuntimeDir));
+ qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%ls'", qUtf16Printable(xdgRuntimeDir));
#endif
- } else {
- fileInfo.setFile(xdgRuntimeDir);
- }
- if (fileInfo.exists()) {
- if (!fileInfo.isDir()) {
- qWarning("QStandardPaths: XDG_RUNTIME_DIR points to '%ls' which is not a directory",
- qUtf16Printable(xdgRuntimeDir));
- return QString();
}
- } else {
- QFileSystemEntry entry(xdgRuntimeDir);
- if (!QFileSystemEngine::createDirectory(entry, false)) {
- if (errno != EEXIST) {
- qErrnoWarning("QStandardPaths: error creating runtime directory %ls",
- qUtf16Printable(xdgRuntimeDir));
- return QString();
- }
- } else {
- QSystemError error;
- if (!QFileSystemEngine::setPermissions(entry, wantedPerms, error)) {
- qWarning("QStandardPaths: could not set correct permissions on runtime directory %ls: %ls",
- qUtf16Printable(xdgRuntimeDir), qUtf16Printable(error.toString()));
- return QString();
- }
- }
- }
- // "The directory MUST be owned by the user"
- if (fileInfo.ownerId() != myUid) {
- qWarning("QStandardPaths: wrong ownership on runtime directory %ls, %d instead of %d",
- qUtf16Printable(xdgRuntimeDir),
- fileInfo.ownerId(), myUid);
- return QString();
- }
- // "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700."
- if (fileInfo.permissions() != wantedPerms) {
- qWarning("QStandardPaths: wrong permissions on runtime directory %ls, %x instead of %x",
- qUtf16Printable(xdgRuntimeDir), uint(fileInfo.permissions()), uint(wantedPerms));
- return QString();
+
+ if (!checkXdgRuntimeDir(xdgRuntimeDir))
+ xdgRuntimeDir.clear();
}
return xdgRuntimeDir;
@@ -205,30 +286,33 @@ QString QStandardPaths::writableLocation(StandardLocation type)
#if QT_CONFIG(regularexpression)
// http://www.freedesktop.org/wiki/Software/xdg-user-dirs
QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
+ if (!xdgConfigHome.startsWith(u'/'))
+ xdgConfigHome.clear(); // spec says relative paths should be ignored
+
if (xdgConfigHome.isEmpty())
- xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
- QFile file(xdgConfigHome + QLatin1String("/user-dirs.dirs"));
- const QLatin1String key = xdg_key_name(type);
+ xdgConfigHome = QDir::homePath() + "/.config"_L1;
+ QFile file(xdgConfigHome + "/user-dirs.dirs"_L1);
+ const QLatin1StringView key = xdg_key_name(type);
if (!key.isEmpty() && !isTestModeEnabled() && file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
// Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop"
- QRegularExpression exp(QLatin1String("^XDG_(.*)_DIR=(.*)$"));
+ static const QRegularExpression exp(u"^XDG_(.*)_DIR=(.*)$"_s);
QString result;
while (!stream.atEnd()) {
const QString &line = stream.readLine();
QRegularExpressionMatch match = exp.match(line);
if (match.hasMatch() && match.capturedView(1) == key) {
QStringView value = match.capturedView(2);
- if (value.length() > 2
- && value.startsWith(QLatin1Char('\"'))
- && value.endsWith(QLatin1Char('\"')))
- value = value.mid(1, value.length() - 2);
+ if (value.size() > 2
+ && value.startsWith(u'\"')
+ && value.endsWith(u'\"'))
+ value = value.mid(1, value.size() - 2);
// value can start with $HOME
- if (value.startsWith(QLatin1String("$HOME")))
+ if (value.startsWith("$HOME"_L1))
result = QDir::homePath() + value.mid(5);
else
result = value.toString();
- if (result.length() > 1 && result.endsWith(QLatin1Char('/')))
+ if (result.size() > 1 && result.endsWith(u'/'))
result.chop(1);
}
}
@@ -240,31 +324,39 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString path;
switch (type) {
case DesktopLocation:
- path = QDir::homePath() + QLatin1String("/Desktop");
+ path = QDir::homePath() + "/Desktop"_L1;
break;
case DocumentsLocation:
- path = QDir::homePath() + QLatin1String("/Documents");
+ path = QDir::homePath() + "/Documents"_L1;
break;
case PicturesLocation:
- path = QDir::homePath() + QLatin1String("/Pictures");
+ path = QDir::homePath() + "/Pictures"_L1;
break;
case FontsLocation:
- path = writableLocation(GenericDataLocation) + QLatin1String("/fonts");
+ path = writableLocation(GenericDataLocation) + "/fonts"_L1;
break;
case MusicLocation:
- path = QDir::homePath() + QLatin1String("/Music");
+ path = QDir::homePath() + "/Music"_L1;
break;
case MoviesLocation:
- path = QDir::homePath() + QLatin1String("/Videos");
+ path = QDir::homePath() + "/Videos"_L1;
break;
case DownloadLocation:
- path = QDir::homePath() + QLatin1String("/Downloads");
+ path = QDir::homePath() + "/Downloads"_L1;
break;
case ApplicationsLocation:
- path = writableLocation(GenericDataLocation) + QLatin1String("/applications");
+ path = writableLocation(GenericDataLocation) + "/applications"_L1;
+ break;
+
+ case PublicShareLocation:
+ path = QDir::homePath() + "/Public"_L1;
+ break;
+
+ case TemplatesLocation:
+ path = QDir::homePath() + "/Templates"_L1;
break;
default:
@@ -274,43 +366,48 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return path;
}
-static QStringList xdgDataDirs()
+static QStringList dirsList(const QString &xdgEnvVar)
{
QStringList dirs;
// http://standards.freedesktop.org/basedir-spec/latest/
+ // Normalize paths, skip relative paths (the spec says relative paths
+ // should be ignored)
+ for (const auto dir : qTokenize(xdgEnvVar, u':'))
+ if (dir.startsWith(u'/'))
+ dirs.push_back(QDir::cleanPath(dir.toString()));
+
+ // Remove duplicates from the list, there's no use for duplicated paths
+ // in XDG_* env vars - if whatever is being looked for is not found in
+ // the given directory the first time, it won't be there the second time.
+ // Plus duplicate paths causes problems for example for mimetypes,
+ // where duplicate paths here lead to duplicated mime types returned
+ // for a file, eg "text/plain,text/plain" instead of "text/plain"
+ dirs.removeDuplicates();
+
+ return dirs;
+}
+
+static QStringList xdgDataDirs()
+{
+ // http://standards.freedesktop.org/basedir-spec/latest/
QString xdgDataDirsEnv = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
- if (xdgDataDirsEnv.isEmpty()) {
- dirs.append(QString::fromLatin1("/usr/local/share"));
- dirs.append(QString::fromLatin1("/usr/share"));
- } else {
- const auto parts = QStringView{xdgDataDirsEnv}.split(QLatin1Char(':'), Qt::SkipEmptyParts);
-
- // Normalize paths, skip relative paths
- for (const auto &dir : parts) {
- if (dir.startsWith(QLatin1Char('/')))
- dirs.push_back(QDir::cleanPath(dir.toString()));
- }
- // Remove duplicates from the list, there's no use for duplicated
- // paths in XDG_DATA_DIRS - if it's not found in the given
- // directory the first time, it won't be there the second time.
- // Plus duplicate paths causes problems for example for mimetypes,
- // where duplicate paths here lead to duplicated mime types returned
- // for a file, eg "text/plain,text/plain" instead of "text/plain"
- dirs.removeDuplicates();
- }
+ QStringList dirs = dirsList(xdgDataDirsEnv);
+ if (dirs.isEmpty())
+ dirs = QStringList{u"/usr/local/share"_s, u"/usr/share"_s};
+
return dirs;
}
static QStringList xdgConfigDirs()
{
- QStringList dirs;
// http://standards.freedesktop.org/basedir-spec/latest/
const QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS"));
- if (xdgConfigDirs.isEmpty())
- dirs.append(QString::fromLatin1("/etc/xdg"));
- else
- dirs = xdgConfigDirs.split(QLatin1Char(':'));
+
+ QStringList dirs = dirsList(xdgConfigDirs);
+ if (dirs.isEmpty())
+ dirs.push_back(u"/etc/xdg"_s);
+
return dirs;
}
@@ -324,7 +421,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
break;
case AppConfigLocation:
dirs = xdgConfigDirs();
- for (int i = 0; i < dirs.count(); ++i)
+ for (int i = 0; i < dirs.size(); ++i)
appendOrganizationAndApp(dirs[i]);
break;
case GenericDataLocation:
@@ -332,20 +429,20 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
break;
case ApplicationsLocation:
dirs = xdgDataDirs();
- for (int i = 0; i < dirs.count(); ++i)
- dirs[i].append(QLatin1String("/applications"));
+ for (int i = 0; i < dirs.size(); ++i)
+ dirs[i].append("/applications"_L1);
break;
case AppDataLocation:
case AppLocalDataLocation:
dirs = xdgDataDirs();
- for (int i = 0; i < dirs.count(); ++i)
+ for (int i = 0; i < dirs.size(); ++i)
appendOrganizationAndApp(dirs[i]);
break;
case FontsLocation:
- dirs += QDir::homePath() + QLatin1String("/.fonts");
+ dirs += QDir::homePath() + "/.fonts"_L1;
dirs += xdgDataDirs();
- for (int i = 1; i < dirs.count(); ++i)
- dirs[i].append(QLatin1String("/fonts"));
+ for (int i = 1; i < dirs.size(); ++i)
+ dirs[i].append("/fonts"_L1);
break;
default:
break;
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index a120db32fc..805ce65a5a 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -1,53 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardpaths.h"
#include <qdir.h>
-#include <private/qsystemlibrary_p.h>
#include <qstringlist.h>
#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
#endif
-#include <qoperatingsystemversion.h>
#include <qt_windows.h>
#include <shlobj.h>
#include <intshcut.h>
@@ -57,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QString convertCharArray(const wchar_t *path)
{
return QDir::fromNativeSeparators(QString::fromWCharArray(path));
@@ -79,38 +43,31 @@ static void appendOrganizationAndApp(QString &path) // Courtesy qstandardpaths_u
#ifndef QT_BOOTSTRAPPED
const QString &org = QCoreApplication::organizationName();
if (!org.isEmpty())
- path += QLatin1Char('/') + org;
+ path += u'/' + org;
const QString &appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
- path += QLatin1Char('/') + appName;
+ path += u'/' + appName;
#else // !QT_BOOTSTRAPPED
- Q_UNUSED(path)
+ Q_UNUSED(path);
#endif
}
static inline void appendTestMode(QString &path)
{
if (QStandardPaths::isTestModeEnabled())
- path += QLatin1String("/qttest");
+ path += "/qttest"_L1;
}
-static bool isProcessLowIntegrity() {
-#ifdef Q_CC_MINGW
- // GetCurrentProcessToken was introduced in MinGW w64 in v7
- // Disable function until Qt CI is updated
- return false;
-#else
- if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
- return false;
- // non-leaking pseudo-handle. Expanded inline function GetCurrentProcessToken()
- // (was made an inline function in Windows 8).
+static bool isProcessLowIntegrity()
+{
+ // same as GetCurrentProcessToken()
const auto process_token = HANDLE(quintptr(-4));
QVarLengthArray<char,256> token_info_buf(256);
auto* token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
DWORD token_info_length = token_info_buf.size();
if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)) {
- // grow bufer and retry GetTokenInformation
+ // grow buffer and retry GetTokenInformation
token_info_buf.resize(token_info_length);
token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length))
@@ -121,7 +78,6 @@ static bool isProcessLowIntegrity() {
// there's no point in checking before dereferencing
DWORD integrity_level = *GetSidSubAuthority(token_info->Label.Sid, *GetSidSubAuthorityCount(token_info->Label.Sid) - 1);
return (integrity_level < SECURITY_MANDATORY_MEDIUM_RID);
-#endif
}
// Map QStandardPaths::StandardLocation to KNOWNFOLDERID of SHGetKnownFolderPath()
@@ -137,17 +93,22 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
FOLDERID_Videos, // MoviesLocation
FOLDERID_Pictures, // PicturesLocation
GUID(), GUID(), // TempLocation/HomeLocation
- FOLDERID_LocalAppData, // AppLocalDataLocation ("Local" path), AppLocalDataLocation = DataLocation
+ FOLDERID_LocalAppData, // AppLocalDataLocation ("Local" path)
GUID(), // CacheLocation
FOLDERID_LocalAppData, // GenericDataLocation ("Local" path)
GUID(), // RuntimeLocation
FOLDERID_LocalAppData, // ConfigLocation ("Local" path)
- GUID(), GUID(), // DownloadLocation/GenericCacheLocation
+ FOLDERID_Downloads, // DownloadLocation
+ GUID(), // GenericCacheLocation
FOLDERID_LocalAppData, // GenericConfigLocation ("Local" path)
FOLDERID_RoamingAppData,// AppDataLocation ("Roaming" path)
FOLDERID_LocalAppData, // AppConfigLocation ("Local" path)
+ FOLDERID_Public, // PublicShareLocation
+ FOLDERID_Templates, // TemplatesLocation
+ GUID(), // StateLocation
+ GUID(), // GenericStateLocation
};
- static_assert(sizeof(folderIds) / sizeof(folderIds[0]) == size_t(QStandardPaths::AppConfigLocation + 1));
+ static_assert(sizeof(folderIds) / sizeof(folderIds[0]) == size_t(QStandardPaths::GenericStateLocation + 1));
// folders for low integrity processes
static const GUID folderIds_li[] = {
@@ -159,15 +120,20 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
FOLDERID_Videos, // MoviesLocation
FOLDERID_Pictures, // PicturesLocation
GUID(), GUID(), // TempLocation/HomeLocation
- FOLDERID_LocalAppDataLow,// AppLocalDataLocation ("Local" path), AppLocalDataLocation = DataLocation
+ FOLDERID_LocalAppDataLow,// AppLocalDataLocation ("Local" path)
GUID(), // CacheLocation
FOLDERID_LocalAppDataLow,// GenericDataLocation ("Local" path)
GUID(), // RuntimeLocation
FOLDERID_LocalAppDataLow,// ConfigLocation ("Local" path)
- GUID(), GUID(), // DownloadLocation/GenericCacheLocation
+ FOLDERID_Downloads, // DownloadLocation
+ GUID(), // GenericCacheLocation
FOLDERID_LocalAppDataLow,// GenericConfigLocation ("Local" path)
FOLDERID_RoamingAppData, // AppDataLocation ("Roaming" path)
FOLDERID_LocalAppDataLow,// AppConfigLocation ("Local" path)
+ FOLDERID_Public, // PublicShareLocation
+ FOLDERID_Templates, // TemplatesLocation
+ GUID(), // StateLocation
+ GUID(), // GenericStateLocation
};
static_assert(sizeof(folderIds_li) == sizeof(folderIds));
@@ -181,13 +147,8 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
static QString sHGetKnownFolderPath(const GUID &clsid)
{
QString result;
- typedef HRESULT (WINAPI *GetKnownFolderPath)(const GUID&, DWORD, HANDLE, LPWSTR*);
-
- static const GetKnownFolderPath sHGetKnownFolderPath = // Vista onwards.
- reinterpret_cast<GetKnownFolderPath>(QSystemLibrary::resolve(QLatin1String("shell32"), "SHGetKnownFolderPath"));
-
LPWSTR path;
- if (Q_LIKELY(sHGetKnownFolderPath && SUCCEEDED(sHGetKnownFolderPath(clsid, KF_FLAG_DONT_VERIFY, 0, &path)))) {
+ if (Q_LIKELY(SUCCEEDED(SHGetKnownFolderPath(clsid, KF_FLAG_DONT_VERIFY, 0, &path)))) {
result = convertCharArray(path);
CoTaskMemFree(path);
}
@@ -198,12 +159,6 @@ QString QStandardPaths::writableLocation(StandardLocation type)
{
QString result;
switch (type) {
- case DownloadLocation:
- result = sHGetKnownFolderPath(FOLDERID_Downloads);
- if (result.isEmpty())
- result = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
- break;
-
case CacheLocation:
// Although Microsoft has a Cache key it is a pointer to IE's cache, not a cache
// location for everyone. Most applications seem to be using a
@@ -212,7 +167,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
if (!result.isEmpty()) {
appendTestMode(result);
appendOrganizationAndApp(result);
- result += QLatin1String("/cache");
+ result += "/cache"_L1;
}
break;
@@ -220,7 +175,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
result = sHGetKnownFolderPath(writableSpecialFolderId(GenericDataLocation));
if (!result.isEmpty()) {
appendTestMode(result);
- result += QLatin1String("/cache");
+ result += "/cache"_L1;
}
break;
@@ -233,6 +188,23 @@ QString QStandardPaths::writableLocation(StandardLocation type)
result = QDir::tempPath();
break;
+ case StateLocation:
+ result = sHGetKnownFolderPath(writableSpecialFolderId(AppLocalDataLocation));
+ if (!result.isEmpty()) {
+ appendTestMode(result);
+ appendOrganizationAndApp(result);
+ result += "/State"_L1;
+ }
+ break;
+
+ case GenericStateLocation:
+ result = sHGetKnownFolderPath(writableSpecialFolderId(GenericDataLocation));
+ if (!result.isEmpty()) {
+ appendTestMode(result);
+ result += "/State"_L1;
+ }
+ break;
+
default:
result = sHGetKnownFolderPath(writableSpecialFolderId(type));
if (!result.isEmpty() && isConfigLocation(type)) {
@@ -271,7 +243,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
QString applicationDirPath = qApp ? QCoreApplication::applicationDirPath()
: QFileInfo(qAppFileName()).path();
dirs.append(applicationDirPath);
- const QString dataDir = applicationDirPath + QLatin1String("/data");
+ const QString dataDir = applicationDirPath + "/data"_L1;
dirs.append(dataDir);
if (!isGenericConfigLocation(type)) {
diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp
index e2c1f0232f..b7a17febaf 100644
--- a/src/corelib/io/qstorageinfo.cpp
+++ b/src/corelib/io/qstorageinfo.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2015 Ivan Komissarov <ABBAPOH@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstorageinfo.h"
#include "qstorageinfo_p.h"
@@ -44,6 +9,8 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QStorageInfo)
+
/*!
\class QStorageInfo
\inmodule QtCore
@@ -53,6 +20,8 @@ QT_BEGIN_NAMESPACE
\ingroup io
\ingroup shared
+ \compares equality
+
Allows retrieving information about the volume's space, its mount point,
label, and filesystem name.
@@ -70,6 +39,11 @@ QT_BEGIN_NAMESPACE
\snippet code/src_corelib_io_qstorageinfo.cpp 2
*/
+QStorageInfo::QStorageInfo(QStorageInfoPrivate &dd)
+ : d(&dd)
+{
+}
+
/*!
Constructs an empty QStorageInfo object.
@@ -274,9 +248,10 @@ QByteArray QStorageInfo::device() const
Returns the subvolume name for this volume.
Some filesystem types allow multiple subvolumes inside one device, which
- may be mounted in different paths. If the subvolume could be detected, it
- is returned here. The format of the subvolume name is specific to each
- filesystem type.
+ may be mounted in different paths (e.g. 'bind' mounts on Unix, or Btrfs
+ filesystem subvolumes). If the subvolume could be detected, its name is
+ returned by this function. The format of the subvolume name is specific
+ to each filesystem type.
If this volume was not mounted from a subvolume of a larger filesystem or
if the subvolume could not be detected, this function returns an empty byte
@@ -397,7 +372,7 @@ QList<QStorageInfo> QStorageInfo::mountedVolumes()
return QStorageInfoPrivate::mountedVolumes();
}
-Q_GLOBAL_STATIC_WITH_ARGS(QStorageInfo, getRoot, (QStorageInfoPrivate::root()))
+Q_GLOBAL_STATIC(QStorageInfo, getRoot, QStorageInfoPrivate::root())
/*!
Returns a QStorageInfo object that represents the system root volume.
@@ -413,26 +388,29 @@ QStorageInfo QStorageInfo::root()
}
/*!
- \fn inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
+ \fn bool QStorageInfo::operator==(const QStorageInfo &lhs, const QStorageInfo &rhs)
- \relates QStorageInfo
-
- Returns true if the \a first QStorageInfo object refers to the same drive or volume
- as the \a second; otherwise it returns false.
+ Returns \c true if the QStorageInfo object \a lhs refers to the same drive or
+ volume as the QStorageInfo object \a rhs; otherwise it returns \c false.
Note that the result of comparing two invalid QStorageInfo objects is always
positive.
*/
/*!
- \fn inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
-
- \relates QStorageInfo
+ \fn bool QStorageInfo::operator!=(const QStorageInfo &lhs, const QStorageInfo &rhs)
- Returns true if the \a first QStorageInfo object refers to a different drive or
- volume than the \a second; otherwise returns false.
+ Returns \c true if the QStorageInfo object \a lhs refers to a different drive or
+ volume than the QStorageInfo object \a rhs; otherwise returns \c false.
*/
+bool comparesEqual(const QStorageInfo &lhs, const QStorageInfo &rhs)
+{
+ if (lhs.d == rhs.d)
+ return true;
+ return lhs.device() == rhs.device() && lhs.rootPath() == rhs.rootPath();
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QStorageInfo &s)
{
@@ -456,12 +434,12 @@ QDebug operator<<(QDebug debug, const QStorageInfo &s)
debug << (d->ready ? " [ready]" : " [not ready]");
if (d->bytesTotal > 0) {
debug << ", bytesTotal=" << d->bytesTotal << ", bytesFree=" << d->bytesFree
- << ", bytesAvailable=" << d->bytesAvailable;
+ << ", bytesAvailable=" << d->bytesAvailable;
}
} else {
debug << "invalid";
}
- debug<< ')';
+ debug << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h
index 237e68d2a1..3784fe8e47 100644
--- a/src/corelib/io/qstorageinfo.h
+++ b/src/corelib/io/qstorageinfo.h
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTORAGEINFO_H
#define QSTORAGEINFO_H
#include <QtCore/qbytearray.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qdir.h>
#include <QtCore/qlist.h>
#include <QtCore/qmetatype.h>
@@ -62,10 +27,10 @@ public:
~QStorageInfo();
QStorageInfo &operator=(const QStorageInfo &other);
- QStorageInfo &operator=(QStorageInfo &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QStorageInfo)
inline void swap(QStorageInfo &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
void setPath(const QString &path);
@@ -92,24 +57,15 @@ public:
static QStorageInfo root();
private:
+ explicit QStorageInfo(QStorageInfoPrivate &dd);
friend class QStorageInfoPrivate;
- friend bool operator==(const QStorageInfo &first, const QStorageInfo &second);
+ friend Q_CORE_EXPORT bool comparesEqual(const QStorageInfo &lhs, const QStorageInfo &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QStorageInfo)
+
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QStorageInfo &);
QExplicitlySharedDataPointer<QStorageInfoPrivate> d;
};
-inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
-{
- if (first.d == second.d)
- return true;
- return first.device() == second.device() && first.rootPath() == second.rootPath();
-}
-
-inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
-{
- return !(first == second);
-}
-
inline bool QStorageInfo::isRoot() const
{ return *this == QStorageInfo::root(); }
@@ -121,6 +77,6 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QStorageInfo &);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QStorageInfo)
+QT_DECL_METATYPE_EXTERN(QStorageInfo, Q_CORE_EXPORT)
#endif // QSTORAGEINFO_H
diff --git a/src/corelib/io/qstorageinfo_linux.cpp b/src/corelib/io/qstorageinfo_linux.cpp
new file mode 100644
index 0000000000..a9d46e7395
--- /dev/null
+++ b/src/corelib/io/qstorageinfo_linux.cpp
@@ -0,0 +1,288 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2023 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qstorageinfo_linux_p.h"
+
+#include "qdirlisting.h"
+#include <private/qcore_unix_p.h>
+#include <private/qtools_p.h>
+
+#include <q20memory.h>
+
+#include <sys/ioctl.h>
+#include <sys/statfs.h>
+
+// so we don't have to #include <linux/fs.h>, which is known to cause conflicts
+#ifndef FSLABEL_MAX
+# define FSLABEL_MAX 256
+#endif
+#ifndef FS_IOC_GETFSLABEL
+# define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX])
+#endif
+
+// or <linux/statfs.h>
+#ifndef ST_RDONLY
+# define ST_RDONLY 0x0001 /* mount read-only */
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+// udev encodes the labels with ID_LABEL_FS_ENC which is done with
+// blkid_encode_string(). Within this function some 1-byte utf-8
+// characters not considered safe (e.g. '\' or ' ') are encoded as hex
+static QString decodeFsEncString(QString &&str)
+{
+ using namespace QtMiscUtils;
+ qsizetype start = str.indexOf(u'\\');
+ if (start < 0)
+ return std::move(str);
+
+ // decode in-place
+ QString decoded = std::move(str);
+ auto ptr = reinterpret_cast<char16_t *>(decoded.begin());
+ qsizetype in = start;
+ qsizetype out = start;
+ qsizetype size = decoded.size();
+
+ while (in < size) {
+ Q_ASSERT(ptr[in] == u'\\');
+ if (size - in >= 4 && ptr[in + 1] == u'x') { // we need four characters: \xAB
+ int c = fromHex(ptr[in + 2]) << 4;
+ c |= fromHex(ptr[in + 3]);
+ if (Q_UNLIKELY(c < 0))
+ c = QChar::ReplacementCharacter; // bad hex sequence
+ ptr[out++] = c;
+ in += 4;
+ }
+
+ for ( ; in < size; ++in) {
+ char16_t c = ptr[in];
+ if (c == u'\\')
+ break;
+ ptr[out++] = c;
+ }
+ }
+ decoded.resize(out);
+ return decoded;
+}
+
+static inline dev_t deviceIdForPath(const QString &device)
+{
+ QT_STATBUF st;
+ if (QT_STAT(QFile::encodeName(device), &st) < 0)
+ return 0;
+ return st.st_dev;
+}
+
+static inline quint64 retrieveDeviceId(const QByteArray &device, quint64 deviceId = 0)
+{
+ // major = 0 implies an anonymous block device, so we need to stat() the
+ // actual device to get its dev_t. This is required for btrfs (and possibly
+ // others), which always uses them for all the subvolumes (including the
+ // root):
+ // https://codebrowser.dev/linux/linux/fs/btrfs/disk-io.c.html#btrfs_init_fs_root
+ // https://codebrowser.dev/linux/linux/fs/super.c.html#get_anon_bdev
+ // For everything else, we trust the parameter.
+ if (major(deviceId) != 0)
+ return deviceId;
+
+ // don't even try to stat() a relative path or "/"
+ if (device.size() < 2 || !device.startsWith('/'))
+ return 0;
+
+ QT_STATBUF st;
+ if (QT_STAT(device, &st) < 0)
+ return 0;
+ if (!S_ISBLK(st.st_mode))
+ return 0;
+ return st.st_rdev;
+}
+
+static QDirListing devicesByLabel()
+{
+ static const char pathDiskByLabel[] = "/dev/disk/by-label";
+ static constexpr auto LabelFileFilter =
+ QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot;
+
+ return QDirListing(QLatin1StringView(pathDiskByLabel), LabelFileFilter);
+}
+
+static inline auto retrieveLabels()
+{
+ struct Entry {
+ QString label;
+ quint64 deviceId;
+ };
+ QList<Entry> result;
+
+ for (const auto &dirEntry : devicesByLabel()) {
+ quint64 deviceId = retrieveDeviceId(QFile::encodeName(dirEntry.filePath()));
+ if (!deviceId)
+ continue;
+ result.emplaceBack(Entry{ decodeFsEncString(dirEntry.fileName()), deviceId });
+ }
+ return result;
+}
+
+static std::optional<QString> retrieveLabelViaIoctl(const QString &path)
+{
+ // FS_IOC_GETFSLABEL was introduced in v4.18; previously it was btrfs-specific.
+ int fd = qt_safe_open(QFile::encodeName(path).constData(), QT_OPEN_RDONLY);
+ if (fd < 0)
+ return std::nullopt;
+
+ // Note: it doesn't append the null terminator (despite what the man page
+ // says) and the return code on success (0) does not indicate the length.
+ char label[FSLABEL_MAX] = {};
+ int r = ioctl(fd, FS_IOC_GETFSLABEL, &label);
+ close(fd);
+ if (r < 0)
+ return std::nullopt;
+ return QString::fromUtf8(label);
+}
+
+static inline QString retrieveLabel(const QStorageInfoPrivate &d, quint64 deviceId)
+{
+ if (auto label = retrieveLabelViaIoctl(d.rootPath))
+ return *label;
+
+ deviceId = retrieveDeviceId(d.device, deviceId);
+ if (!deviceId)
+ return QString();
+
+ for (const auto &dirEntry : devicesByLabel()) {
+ if (retrieveDeviceId(QFile::encodeName(dirEntry.filePath())) == deviceId)
+ return decodeFsEncString(dirEntry.fileName());
+ }
+ return QString();
+}
+
+void QStorageInfoPrivate::retrieveVolumeInfo()
+{
+ struct statfs64 statfs_buf;
+ int result;
+ QT_EINTR_LOOP(result, statfs64(QFile::encodeName(rootPath).constData(), &statfs_buf));
+ if (result == 0) {
+ valid = true;
+ ready = true;
+
+ bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
+ bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
+ bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
+ blockSize = int(statfs_buf.f_bsize);
+ readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
+ }
+}
+
+static std::vector<MountInfo> parseMountInfo(FilterMountInfo filter = FilterMountInfo::All)
+{
+ QFile file(u"/proc/self/mountinfo"_s);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return {};
+
+ QByteArray mountinfo = file.readAll();
+ file.close();
+
+ return doParseMountInfo(mountinfo, filter);
+}
+
+void QStorageInfoPrivate::doStat()
+{
+ retrieveVolumeInfo();
+ if (!ready)
+ return;
+
+ rootPath = QFileInfo(rootPath).canonicalFilePath();
+ if (rootPath.isEmpty())
+ return;
+
+ std::vector<MountInfo> infos = parseMountInfo();
+ if (infos.empty()) {
+ rootPath = u'/';
+ return;
+ }
+
+ // We iterate over the /proc/self/mountinfo list backwards because then any
+ // matching isParentOf must be the actual mount point because it's the most
+ // recent mount on that path. Linux does allow mounting over non-empty
+ // directories, such as in:
+ // # mount | tail -2
+ // tmpfs on /tmp/foo/bar type tmpfs (rw,relatime,inode64)
+ // tmpfs on /tmp/foo type tmpfs (rw,relatime,inode64)
+ //
+ // We try to match the device ID in case there's a mount --move.
+ // We can't *rely* on it because some filesystems like btrfs will assign
+ // device IDs to subvolumes that aren't listed in /proc/self/mountinfo.
+
+ const QString oldRootPath = std::exchange(rootPath, QString());
+ const dev_t rootPathDevId = deviceIdForPath(oldRootPath);
+ MountInfo *best = nullptr;
+ for (auto it = infos.rbegin(); it != infos.rend(); ++it) {
+ if (!isParentOf(it->mountPoint, oldRootPath))
+ continue;
+ if (rootPathDevId == it->stDev) {
+ // device ID matches; this is definitely the best option
+ best = q20::to_address(it);
+ break;
+ }
+ if (!best) {
+ // if we can't find a device ID match, this parent path is probably
+ // the correct one
+ best = q20::to_address(it);
+ }
+ }
+ if (best) {
+ auto stDev = best->stDev;
+ setFromMountInfo(std::move(*best));
+ name = retrieveLabel(*this, stDev);
+ }
+}
+
+QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
+{
+ std::vector<MountInfo> infos = parseMountInfo(FilterMountInfo::Filtered);
+ if (infos.empty())
+ return QList{root()};
+
+ std::optional<decltype(retrieveLabels())> labelMap;
+ auto labelForDevice = [&labelMap](const QStorageInfoPrivate &d, quint64 devid) {
+ if (d.fileSystemType == "tmpfs")
+ return QString();
+
+ if (auto label = retrieveLabelViaIoctl(d.rootPath))
+ return *label;
+
+ devid = retrieveDeviceId(d.device, devid);
+ if (!devid)
+ return QString();
+
+ if (!labelMap)
+ labelMap = retrieveLabels();
+ for (auto &[deviceLabel, deviceId] : std::as_const(*labelMap)) {
+ if (devid == deviceId)
+ return deviceLabel;
+ }
+ return QString();
+ };
+
+ QList<QStorageInfo> volumes;
+ for (MountInfo &info : infos) {
+ const auto infoStDev = info.stDev;
+ QStorageInfoPrivate d(std::move(info));
+ d.retrieveVolumeInfo();
+ if (d.bytesTotal <= 0 && d.rootPath != u'/')
+ continue;
+ if (infoStDev != deviceIdForPath(d.rootPath))
+ continue; // probably something mounted over this mountpoint
+ d.name = labelForDevice(d, infoStDev);
+ volumes.emplace_back(QStorageInfo(*new QStorageInfoPrivate(std::move(d))));
+ }
+ return volumes;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qstorageinfo_linux_p.h b/src/corelib/io/qstorageinfo_linux_p.h
new file mode 100644
index 0000000000..6f5e107ec6
--- /dev/null
+++ b/src/corelib/io/qstorageinfo_linux_p.h
@@ -0,0 +1,244 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2023 Ahmad Samir <a.samirh78@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSTORAGEINFO_LINUX_P_H
+#define QSTORAGEINFO_LINUX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API.
+// This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qstorageinfo_p.h"
+
+#include <QtCore/qsystemdetection.h>
+#include <QtCore/private/qlocale_tools_p.h>
+
+#include <sys/sysmacros.h> // makedev()
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+using MountInfo = QStorageInfoPrivate::MountInfo;
+
+static const char MountInfoPath[] = "/proc/self/mountinfo";
+
+static std::optional<dev_t> deviceNumber(QByteArrayView devno)
+{
+ // major:minor
+ auto it = devno.cbegin();
+ auto r = qstrntoll(it, devno.size(), 10);
+ if (!r.ok())
+ return std::nullopt;
+ int rdevmajor = int(r.result);
+ it += r.used;
+
+ if (*it != ':')
+ return std::nullopt;
+
+ r = qstrntoll(++it, devno.size() - r.used + 1, 10);
+ if (!r.ok())
+ return std::nullopt;
+
+ return makedev(rdevmajor, r.result);
+}
+
+// Helper function to parse paths that the kernel inserts escape sequences
+// for.
+static QByteArray parseMangledPath(QByteArrayView path)
+{
+ // The kernel escapes with octal the following characters:
+ // space ' ', tab '\t', backslash '\\', and newline '\n'
+ // See:
+ // https://codebrowser.dev/linux/linux/fs/proc_namespace.c.html#show_mountinfo
+ // https://codebrowser.dev/linux/linux/fs/seq_file.c.html#mangle_path
+
+ QByteArray ret(path.size(), '\0');
+ char *dst = ret.data();
+ const char *src = path.data();
+ const char *srcEnd = path.data() + path.size();
+ while (src != srcEnd) {
+ switch (*src) {
+ case ' ': // Shouldn't happen
+ return {};
+
+ case '\\': {
+ // It always uses exactly three octal characters.
+ ++src;
+ char c = (*src++ - '0') << 6;
+ c |= (*src++ - '0') << 3;
+ c |= (*src++ - '0');
+ *dst++ = c;
+ break;
+ }
+
+ default:
+ *dst++ = *src++;
+ break;
+ }
+ }
+ // If "path" contains any of the characters this method is demangling,
+ // "ret" would be oversized with extra '\0' characters at the end.
+ ret.resize(dst - ret.data());
+ return ret;
+}
+
+// Indexes into the "fields" std::array in parseMountInfo()
+// static constexpr short MountId = 0;
+// static constexpr short ParentId = 1;
+static constexpr short DevNo = 2;
+static constexpr short FsRoot = 3;
+static constexpr short MountPoint = 4;
+static constexpr short MountOptions = 5;
+// static constexpr short OptionalFields = 6;
+// static constexpr short Separator = 7;
+static constexpr short FsType = 8;
+static constexpr short MountSource = 9;
+static constexpr short SuperOptions = 10;
+static constexpr short FieldCount = 11;
+
+// Splits a line from /proc/self/mountinfo into fields; fields are separated
+// by a single space.
+static void tokenizeLine(std::array<QByteArrayView, FieldCount> &fields, QByteArrayView line)
+{
+ size_t fieldIndex = 0;
+ qsizetype from = 0;
+ const char *begin = line.data();
+ const qsizetype len = line.size();
+ qsizetype spaceIndex = -1;
+ while ((spaceIndex = line.indexOf(' ', from)) != -1 && fieldIndex < FieldCount) {
+ fields[fieldIndex] = QByteArrayView{begin + from, begin + spaceIndex};
+ from = spaceIndex;
+
+ // Skip "OptionalFields" and Separator fields
+ if (fieldIndex == MountOptions) {
+ static constexpr char separatorField[] = " - ";
+ const qsizetype sepIndex = line.indexOf(separatorField, from);
+ if (sepIndex == -1) {
+ qCWarning(lcStorageInfo,
+ "Malformed line (missing '-' separator field) while parsing '%s':\n%s",
+ MountInfoPath, line.constData());
+ fields.fill({});
+ return;
+ }
+
+ from = sepIndex + strlen(separatorField);
+ // Continue parsing at FsType field
+ fieldIndex = FsType;
+ continue;
+ }
+
+ if (from + 1 < len)
+ ++from; // Skip the space at spaceIndex
+
+ ++fieldIndex;
+ }
+
+ // Currently we don't use the last field, so just check the index
+ if (fieldIndex != SuperOptions) {
+ qCInfo(lcStorageInfo,
+ "Expected %d fields while parsing line from '%s', but found %zu instead:\n%.*s",
+ FieldCount, MountInfoPath, fieldIndex, int(line.size()), line.data());
+ fields.fill({});
+ }
+}
+
+// parseMountInfo() is called from:
+// - QStorageInfoPrivate::initRootPath(), where a list of all mounted volumes is needed
+// - QStorageInfoPrivate::mountedVolumes(), where some filesystem types are ignored
+// (see shouldIncludefs())
+enum class FilterMountInfo {
+ All,
+ Filtered,
+};
+
+[[maybe_unused]] static std::vector<MountInfo>
+doParseMountInfo(const QByteArray &mountinfo, FilterMountInfo filter = FilterMountInfo::All)
+{
+ // https://www.kernel.org/doc/Documentation/filesystems/proc.txt:
+ // 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
+ // (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
+
+ auto it = mountinfo.cbegin();
+ const auto end = mountinfo.cend();
+ auto nextLine = [&it, &end]() -> QByteArrayView {
+ auto nIt = std::find(it, end, '\n');
+ if (nIt != end) {
+ QByteArrayView ba(it, nIt);
+ it = ++nIt; // Advance
+ return ba;
+ }
+ return {};
+ };
+
+ std::vector<MountInfo> infos;
+ std::array<QByteArrayView, FieldCount> fields;
+ QByteArrayView line;
+
+ auto checkField = [&line](QByteArrayView field) {
+ if (field.isEmpty()) {
+ qDebug("Failed to parse line from %s:\n%.*s", MountInfoPath, int(line.size()),
+ line.data());
+ return false;
+ }
+ return true;
+ };
+
+ // mountinfo has a stable format, no empty lines
+ while (!(line = nextLine()).isEmpty()) {
+ fields.fill({});
+ tokenizeLine(fields, line);
+
+ MountInfo info;
+ QByteArray mountP = parseMangledPath(fields[MountPoint]);
+ if (!checkField(mountP))
+ continue;
+ info.mountPoint = QFile::decodeName(mountP);
+
+ if (!checkField(fields[FsType]))
+ continue;
+ info.fsType = fields[FsType].toByteArray();
+
+ if (filter == FilterMountInfo::Filtered && !shouldIncludeFs(info.mountPoint, info.fsType))
+ continue;
+
+ std::optional<dev_t> devno = deviceNumber(fields[DevNo]);
+ if (!devno) {
+ checkField({});
+ continue;
+ }
+ info.stDev = *devno;
+
+ QByteArrayView fsRootView = fields[FsRoot];
+ if (!checkField(fsRootView))
+ continue;
+
+ // If the filesystem root is "/" -- it's not a *sub*-volume/bind-mount,
+ // in that case we leave info.fsRoot empty
+ if (fsRootView != "/") {
+ info.fsRoot = parseMangledPath(fsRootView);
+ if (!checkField(info.fsRoot))
+ continue;
+ }
+
+ info.device = parseMangledPath(fields[MountSource]);
+ if (!checkField(info.device))
+ continue;
+
+ infos.push_back(std::move(info));
+ }
+ return infos;
+}
+
+QT_END_NAMESPACE
+
+#endif // QSTORAGEINFO_LINUX_P_H
diff --git a/src/corelib/io/qstorageinfo_mac.cpp b/src/corelib/io/qstorageinfo_mac.cpp
index 8b06543d71..c6c0f501da 100644
--- a/src/corelib/io/qstorageinfo_mac.cpp
+++ b/src/corelib/io/qstorageinfo_mac.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstorageinfo_p.h"
@@ -79,9 +43,9 @@ void QStorageInfoPrivate::retrievePosixInfo()
QT_STATFSBUF statfs_buf;
int result = QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf);
if (result == 0) {
- device = QByteArray(statfs_buf.f_mntfromname);
+ device.assign(statfs_buf.f_mntfromname);
readOnly = (statfs_buf.f_flags & MNT_RDONLY) != 0;
- fileSystemType = QByteArray(statfs_buf.f_fstypename);
+ fileSystemType.assign(statfs_buf.f_fstypename);
blockSize = statfs_buf.f_bsize;
}
}
@@ -196,9 +160,4 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
return volumes;
}
-QStorageInfo QStorageInfoPrivate::root()
-{
- return QStorageInfo(QStringLiteral("/"));
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/io/qstorageinfo_p.h b/src/corelib/io/qstorageinfo_p.h
index 421e364311..3af4b81ca4 100644
--- a/src/corelib/io/qstorageinfo_p.h
+++ b/src/corelib/io/qstorageinfo_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTORAGEINFO_P_H
#define QSTORAGEINFO_P_H
@@ -51,34 +15,77 @@
// We mean it.
//
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qsystemdetection.h>
+#include <QtCore/qtenvironmentvariables.h>
#include <QtCore/private/qglobal_p.h>
#include "qstorageinfo.h"
+#ifdef Q_OS_UNIX
+#include <sys/types.h> // dev_t
+#endif
+
QT_BEGIN_NAMESPACE
+inline Q_LOGGING_CATEGORY(lcStorageInfo, "qt.core.qstorageinfo", QtWarningMsg)
+
class QStorageInfoPrivate : public QSharedData
{
public:
- inline QStorageInfoPrivate() : QSharedData(),
- bytesTotal(-1), bytesFree(-1), bytesAvailable(-1), blockSize(-1),
- readOnly(false), ready(false), valid(false)
- {}
+ QStorageInfoPrivate() = default;
- void initRootPath();
void doStat();
static QList<QStorageInfo> mountedVolumes();
- static QStorageInfo root();
+
+ static QStorageInfo root()
+ {
+#ifdef Q_OS_WIN
+ return QStorageInfo(QDir::fromNativeSeparators(QFile::decodeName(qgetenv("SystemDrive"))));
+#else
+ return QStorageInfo(QStringLiteral("/"));
+#endif
+ };
protected:
#if defined(Q_OS_WIN)
+ void initRootPath();
void retrieveVolumeInfo();
void retrieveDiskFreeSpace();
-#elif defined(Q_OS_MAC)
+ bool queryStorageProperty();
+ void queryFileFsSectorSizeInformation();
+#elif defined(Q_OS_DARWIN)
+ void initRootPath();
void retrievePosixInfo();
void retrieveUrlProperties(bool initRootPath = false);
void retrieveLabel();
+#elif defined(Q_OS_LINUX)
+ void retrieveVolumeInfo();
+
+public:
+ struct MountInfo {
+ QString mountPoint;
+ QByteArray fsType;
+ QByteArray device;
+ QByteArray fsRoot;
+ dev_t stDev = 0;
+ };
+
+ void setFromMountInfo(MountInfo &&info)
+ {
+ rootPath = std::move(info.mountPoint);
+ fileSystemType = std::move(info.fsType);
+ device = std::move(info.device);
+ subvolume = std::move(info.fsRoot);
+ }
+
+ QStorageInfoPrivate(MountInfo &&info)
+ {
+ setFromMountInfo(std::move(info));
+ }
+
#elif defined(Q_OS_UNIX)
+ void initRootPath();
void retrieveVolumeInfo();
#endif
@@ -89,16 +96,68 @@ public:
QByteArray fileSystemType;
QString name;
- qint64 bytesTotal;
- qint64 bytesFree;
- qint64 bytesAvailable;
- int blockSize;
+ qint64 bytesTotal = -1;
+ qint64 bytesFree = -1;
+ qint64 bytesAvailable = -1;
+ int blockSize = -1;
- bool readOnly;
- bool ready;
- bool valid;
+ bool readOnly = false;
+ bool ready = false;
+ bool valid = false;
};
+// Common helper functions
+template <typename String>
+static bool isParentOf(const String &parent, const QString &dirName)
+{
+ return dirName.startsWith(parent) &&
+ (dirName.size() == parent.size() || dirName.at(parent.size()) == u'/' ||
+ parent.size() == 1);
+}
+
+static inline bool shouldIncludeFs(const QString &mountDir, const QByteArray &fsType)
+{
+#if defined(Q_OS_ANDROID)
+ // "rootfs" is the filesystem type of "/" on Android
+ static constexpr char RootFsStr[] = "";
+#else
+ // "rootfs" is a type of ramfs on Linux, used in the initrd on some distros
+ static constexpr char RootFsStr[] = "rootfs";
+#endif
+
+ using namespace Qt::StringLiterals;
+ /*
+ * This function implements a heuristic algorithm to determine whether a
+ * given mount should be reported to the user. Our objective is to list
+ * only entries that the end-user would find useful.
+ *
+ * We therefore ignore:
+ * - mounted in /dev, /proc, /sys: special mounts
+ * (this will catch /sys/fs/cgroup, /proc/sys/fs/binfmt_misc, /dev/pts,
+ * some of which are tmpfs on Linux)
+ * - mounted in /var/run or /var/lock: most likely pseudofs
+ * (on earlier systemd versions, /var/run was a bind-mount of /run, so
+ * everything would be unnecessarily duplicated)
+ * - filesystem type is "rootfs": artifact of the root-pivot on some Linux
+ * initrd
+ * - if the filesystem total size is zero, it's a pseudo-fs (not checked here).
+ */
+
+ if (isParentOf("/dev"_L1, mountDir)
+ || isParentOf("/proc"_L1, mountDir)
+ || isParentOf("/sys"_L1, mountDir)
+ || isParentOf("/var/run"_L1, mountDir)
+ || isParentOf("/var/lock"_L1, mountDir)) {
+ return false;
+ }
+
+ if (!fsType.isEmpty() && fsType == RootFsStr)
+ return false;
+
+ // size checking in QStorageInfo::mountedVolumes()
+ return true;
+}
+
QT_END_NAMESPACE
#endif // QSTORAGEINFO_P_H
diff --git a/src/corelib/io/qstorageinfo_stub.cpp b/src/corelib/io/qstorageinfo_stub.cpp
new file mode 100644
index 0000000000..f2f7d2eb65
--- /dev/null
+++ b/src/corelib/io/qstorageinfo_stub.cpp
@@ -0,0 +1,25 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qstorageinfo_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void QStorageInfoPrivate::initRootPath()
+{
+ Q_UNIMPLEMENTED();
+ rootPath = QString();
+}
+
+void QStorageInfoPrivate::doStat()
+{
+ Q_UNIMPLEMENTED();
+}
+
+QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
+{
+ Q_UNIMPLEMENTED();
+ return QList<QStorageInfo>();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index e38f495213..9df098a389 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -1,46 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstorageinfo_p.h"
-#include <QtCore/qdiriterator.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qtextstream.h>
@@ -53,11 +17,7 @@
#if defined(Q_OS_BSD4)
# include <sys/mount.h>
# include <sys/statvfs.h>
-#elif defined(Q_OS_ANDROID)
-# include <sys/mount.h>
-# include <sys/vfs.h>
-# include <mntent.h>
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
+#elif defined(Q_OS_HURD)
# include <mntent.h>
# include <sys/statvfs.h>
# include <sys/sysmacros.h>
@@ -90,12 +50,6 @@
# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
# define _STATFS_F_FLAGS 1
# endif
-#elif defined(Q_OS_ANDROID)
-# define QT_STATFS ::statfs
-# define QT_STATFSBUF struct statfs
-# if !defined(ST_RDONLY)
-# define ST_RDONLY 1 // hack for missing define on Android
-# endif
#elif defined(Q_OS_HAIKU)
# define QT_STATFSBUF struct statvfs
# define QT_STATFS ::statvfs
@@ -118,6 +72,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QStorageIterator
{
public:
@@ -139,43 +95,10 @@ private:
#elif defined(Q_OS_SOLARIS)
FILE *fp;
mnttab mnt;
-#elif defined(Q_OS_ANDROID)
- QFile file;
- QByteArray m_rootPath;
- QByteArray m_fileSystemType;
- QByteArray m_device;
- QByteArray m_options;
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
- struct mountinfoent : public mntent {
- // Details from proc(5) section from /proc/<pid>/mountinfo:
- //(1) mount ID: a unique ID for the mount (may be reused after umount(2)).
- int mount_id;
- //(2) parent ID: the ID of the parent mount (or of self for the top of the mount tree).
-// int parent_id;
- //(3) major:minor: the value of st_dev for files on this filesystem (see stat(2)).
- dev_t rdev;
- //(4) root: the pathname of the directory in the filesystem which forms the root of this mount.
- char *subvolume;
- //(5) mount point: the pathname of the mount point relative to the process's root directory.
-// char *mnt_dir; // in mntent
- //(6) mount options: per-mount options.
-// char *mnt_opts; // in mntent
- //(7) optional fields: zero or more fields of the form "tag[:value]"; see below.
-// int flags;
- //(8) separator: the end of the optional fields is marked by a single hyphen.
-
- //(9) filesystem type: the filesystem type in the form "type[.subtype]".
-// char *mnt_type; // in mntent
- //(10) mount source: filesystem-specific information or "none".
-// char *mnt_fsname; // in mntent
- //(11) super options: per-superblock options.
- char *superopts;
- };
-
+#elif defined(Q_OS_HURD)
FILE *fp;
QByteArray buffer;
mountinfoent mnt;
- bool usingMountinfo;
#elif defined(Q_OS_HAIKU)
BVolumeRoster m_volumeRoster;
@@ -185,51 +108,6 @@ private:
#endif
};
-template <typename String>
-static bool isParentOf(const String &parent, const QString &dirName)
-{
- return dirName.startsWith(parent) &&
- (dirName.size() == parent.size() || dirName.at(parent.size()) == QLatin1Char('/') ||
- parent.size() == 1);
-}
-
-static bool shouldIncludeFs(const QStorageIterator &it)
-{
- /*
- * This function implements a heuristic algorithm to determine whether a
- * given mount should be reported to the user. Our objective is to list
- * only entries that the end-user would find useful.
- *
- * We therefore ignore:
- * - mounted in /dev, /proc, /sys: special mounts
- * (this will catch /sys/fs/cgroup, /proc/sys/fs/binfmt_misc, /dev/pts,
- * some of which are tmpfs on Linux)
- * - mounted in /var/run or /var/lock: most likely pseudofs
- * (on earlier systemd versions, /var/run was a bind-mount of /run, so
- * everything would be unnecessarily duplicated)
- * - filesystem type is "rootfs": artifact of the root-pivot on some Linux
- * initrd
- * - if the filesystem total size is zero, it's a pseudo-fs (not checked here).
- */
-
- QString mountDir = it.rootPath();
- if (isParentOf(QLatin1String("/dev"), mountDir)
- || isParentOf(QLatin1String("/proc"), mountDir)
- || isParentOf(QLatin1String("/sys"), mountDir)
- || isParentOf(QLatin1String("/var/run"), mountDir)
- || isParentOf(QLatin1String("/var/lock"), mountDir)) {
- return false;
- }
-
-#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
- if (it.fileSystemType() == "rootfs")
- return false;
-#endif
-
- // size checking in mountedVolumes()
- return true;
-}
-
#if defined(Q_OS_BSD4)
#ifndef MNT_NOWAIT
@@ -323,67 +201,8 @@ inline QByteArray QStorageIterator::subvolume() const
{
return QByteArray();
}
-#elif defined(Q_OS_ANDROID)
-
-inline QStorageIterator::QStorageIterator()
-{
- file.setFileName(_PATH_MOUNTED);
- file.open(QIODevice::ReadOnly | QIODevice::Text);
-}
-
-inline QStorageIterator::~QStorageIterator()
-{
-}
-
-inline bool QStorageIterator::isValid() const
-{
- return file.isOpen();
-}
-
-inline bool QStorageIterator::next()
-{
- QList<QByteArray> data;
- // If file is virtual, file.readLine() may succeed even when file.atEnd().
- do {
- const QByteArray line = file.readLine();
- if (line.isEmpty() && file.atEnd())
- return false;
- data = line.split(' ');
- } while (data.count() < 4);
-
- m_device = data.at(0);
- m_rootPath = data.at(1);
- m_fileSystemType = data.at(2);
- m_options = data.at(3);
-
- return true;
-}
-
-inline QString QStorageIterator::rootPath() const
-{
- return QFile::decodeName(m_rootPath);
-}
-
-inline QByteArray QStorageIterator::fileSystemType() const
-{
- return m_fileSystemType;
-}
-
-inline QByteArray QStorageIterator::device() const
-{
- return m_device;
-}
-
-inline QByteArray QStorageIterator::options() const
-{
- return m_options;
-}
-inline QByteArray QStorageIterator::subvolume() const
-{
- return QByteArray();
-}
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
+#elif defined(Q_OS_HURD)
static const int bufferSize = 1024; // 2 paths (mount point+device) and metainfo;
// should be enough
@@ -391,28 +210,13 @@ static const int bufferSize = 1024; // 2 paths (mount point+device) and metainfo
inline QStorageIterator::QStorageIterator() :
buffer(QByteArray(bufferSize, 0))
{
- fp = nullptr;
-
-#ifdef Q_OS_LINUX
- // first, try to open /proc/self/mountinfo, which has more details
- fp = ::fopen("/proc/self/mountinfo", "re");
-#endif
- if (fp) {
- usingMountinfo = true;
- } else {
- usingMountinfo = false;
- fp = ::setmntent(_PATH_MOUNTED, "r");
- }
+ fp = ::setmntent(_PATH_MOUNTED, "r");
}
inline QStorageIterator::~QStorageIterator()
{
- if (fp) {
- if (usingMountinfo)
- ::fclose(fp);
- else
- ::endmntent(fp);
- }
+ if (fp)
+ ::endmntent(fp);
}
inline bool QStorageIterator::isValid() const
@@ -422,136 +226,7 @@ inline bool QStorageIterator::isValid() const
inline bool QStorageIterator::next()
{
- mnt.subvolume = nullptr;
- mnt.superopts = nullptr;
- if (!usingMountinfo)
- return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != nullptr;
-
- // Helper function to parse paths that the kernel inserts escape sequences
- // for. The unescaped string is left at \a src and is properly
- // NUL-terminated. Returns a pointer to the delimiter that terminated the
- // path, or nullptr if it failed.
- auto parseMangledPath = [](char *src) {
- // The kernel escapes with octal the following characters:
- // space ' ', tab '\t', backslask '\\', and newline '\n'
- char *dst = src;
- while (*src) {
- switch (*src) {
- case ' ':
- // Unescaped space: end of the field.
- *dst = '\0';
- return src;
-
- default:
- *dst++ = *src++;
- break;
-
- case '\\':
- // It always uses exactly three octal characters.
- ++src;
- char c = (*src++ - '0') << 6;
- c |= (*src++ - '0') << 3;
- c |= (*src++ - '0');
- *dst++ = c;
- break;
- }
- }
-
- // Found a NUL before the end of the field.
- src = nullptr;
- return src;
- };
-
- char *ptr = buffer.data();
- if (fgets(ptr, buffer.size(), fp) == nullptr)
- return false;
-
- size_t len = strlen(buffer.data());
- if (len == 0)
- return false;
- while (Q_UNLIKELY(ptr[len - 1] != '\n' && !feof(fp))) {
- // buffer wasn't large enough. Enlarge and try again.
- // (we're readidng from the kernel, so OOM is unlikely)
- buffer.resize((buffer.size() + 4096) & ~4095);
- ptr = buffer.data();
- if (fgets(ptr + len, buffer.size() - len, fp) == nullptr)
- return false;
-
- len += strlen(ptr + len);
- Q_ASSERT(len < size_t(buffer.size()));
- }
- ptr[len - 1] = '\0';
-
- // parse the line
- bool ok;
- mnt.mnt_freq = 0;
- mnt.mnt_passno = 0;
-
- mnt.mount_id = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok);
- if (!ptr || !ok)
- return false;
-
- int parent_id = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok);
- Q_UNUSED(parent_id);
- if (!ptr || !ok)
- return false;
-
- int rdevmajor = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok);
- if (!ptr || !ok)
- return false;
- if (*ptr != ':')
- return false;
- int rdevminor = qstrtoll(ptr + 1, const_cast<const char **>(&ptr), 10, &ok);
- if (!ptr || !ok)
- return false;
- mnt.rdev = makedev(rdevmajor, rdevminor);
-
- if (*ptr != ' ')
- return false;
-
- mnt.subvolume = ++ptr;
- ptr = parseMangledPath(ptr);
- if (!ptr)
- return false;
-
- // unset a subvolume of "/" -- it's not a *sub* volume
- if (mnt.subvolume + 1 == ptr)
- *mnt.subvolume = '\0';
-
- mnt.mnt_dir = ++ptr;
- ptr = parseMangledPath(ptr);
- if (!ptr)
- return false;
-
- mnt.mnt_opts = ++ptr;
- ptr = strchr(ptr, ' ');
- if (!ptr)
- return false;
-
- // we don't parse the flags, so just find the separator
- if (char *const dashed = strstr(ptr, " - ")) {
- *ptr = '\0';
- ptr = dashed + strlen(" - ") - 1;
- } else {
- return false;
- }
-
- mnt.mnt_type = ++ptr;
- ptr = strchr(ptr, ' ');
- if (!ptr)
- return false;
- *ptr = '\0';
-
- mnt.mnt_fsname = ++ptr;
- ptr = parseMangledPath(ptr);
- if (!ptr)
- return false;
-
- mnt.superopts = ++ptr;
- ptr += strcspn(ptr, " \n");
- *ptr = '\0';
-
- return true;
+ return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != nullptr;
}
inline QString QStorageIterator::rootPath() const
@@ -566,47 +241,17 @@ inline QByteArray QStorageIterator::fileSystemType() const
inline QByteArray QStorageIterator::device() const
{
- // check that the device exists
- if (mnt.mnt_fsname[0] == '/' && access(mnt.mnt_fsname, F_OK) != 0) {
- // It doesn't, so let's try to resolve the dev_t from /dev/block.
- // Note how strlen("4294967295") == digits10 + 1, so we need to add 1
- // for each number, plus the ':'.
- char buf[sizeof("/dev/block/") + 2 * std::numeric_limits<unsigned>::digits10 + 3];
- QByteArray dev(PATH_MAX, Qt::Uninitialized);
- char *devdata = dev.data();
-
- snprintf(buf, sizeof(buf), "/dev/block/%u:%u", major(mnt.rdev), minor(mnt.rdev));
- if (realpath(buf, devdata)) {
- dev.truncate(strlen(devdata));
- return dev;
- }
- }
return QByteArray(mnt.mnt_fsname);
}
inline QByteArray QStorageIterator::options() const
{
- // Merge the two options, starting with the superblock options and letting
- // the per-mount options override.
- const char *superopts = mnt.superopts;
-
- // Both mnt_opts and superopts start with "ro" or "rw", so we can skip the
- // superblock's field (see show_mountinfo() in fs/proc_namespace.c).
- if (superopts && superopts[0] == 'r') {
- if (superopts[2] == '\0') // no other superopts besides "ro" / "rw"?
- superopts = nullptr;
- else if (superopts[2] == ',')
- superopts += 3;
- }
-
- if (superopts)
- return QByteArray(superopts) + ',' + mnt.mnt_opts;
return QByteArray(mnt.mnt_opts);
}
inline QByteArray QStorageIterator::subvolume() const
{
- return QByteArray(mnt.subvolume);
+ return QByteArray();
}
#elif defined(Q_OS_HAIKU)
inline QStorageIterator::QStorageIterator()
@@ -674,6 +319,7 @@ inline QByteArray QStorageIterator::subvolume() const
{
return QByteArray();
}
+
#else
inline QStorageIterator::QStorageIterator()
@@ -720,85 +366,9 @@ inline QByteArray QStorageIterator::subvolume() const
}
#endif
-void QStorageInfoPrivate::initRootPath()
-{
- rootPath = QFileInfo(rootPath).canonicalFilePath();
-
- if (rootPath.isEmpty())
- return;
-
- QStorageIterator it;
- if (!it.isValid()) {
- rootPath = QStringLiteral("/");
- return;
- }
-
- int maxLength = 0;
- const QString oldRootPath = rootPath;
- rootPath.clear();
-
- while (it.next()) {
- const QString mountDir = it.rootPath();
- const QByteArray fsName = it.fileSystemType();
- // we try to find most suitable entry
- if (isParentOf(mountDir, oldRootPath) && maxLength < mountDir.length()) {
- maxLength = mountDir.length();
- rootPath = mountDir;
- device = it.device();
- fileSystemType = fsName;
- subvolume = it.subvolume();
- }
- }
-}
-
-#ifdef Q_OS_LINUX
-// udev encodes the labels with ID_LABEL_FS_ENC which is done with
-// blkid_encode_string(). Within this function some 1-byte utf-8
-// characters not considered safe (e.g. '\' or ' ') are encoded as hex
-static QString decodeFsEncString(const QString &str)
-{
- QString decoded;
- decoded.reserve(str.size());
-
- int i = 0;
- while (i < str.size()) {
- if (i <= str.size() - 4) { // we need at least four characters \xAB
- if (str.at(i) == QLatin1Char('\\') &&
- str.at(i+1) == QLatin1Char('x')) {
- bool bOk;
- const int code = QStringView{str}.mid(i+2, 2).toInt(&bOk, 16);
- // only decode characters between 0x20 and 0x7f but not
- // the backslash to prevent collisions
- if (bOk && code >= 0x20 && code < 0x80 && code != '\\') {
- decoded += QChar(code);
- i += 4;
- continue;
- }
- }
- }
- decoded += str.at(i);
- ++i;
- }
- return decoded;
-}
-#endif
-
static inline QString retrieveLabel(const QByteArray &device)
{
-#ifdef Q_OS_LINUX
- static const char pathDiskByLabel[] = "/dev/disk/by-label";
-
- QFileInfo devinfo(QFile::decodeName(device));
- QString devicePath = devinfo.canonicalFilePath();
-
- QDirIterator it(QLatin1String(pathDiskByLabel), QDir::NoDotAndDotDot);
- while (it.hasNext()) {
- it.next();
- QFileInfo fileInfo(it.fileInfo());
- if (fileInfo.isSymLink() && fileInfo.symLinkTarget() == devicePath)
- return decodeFsEncString(fileInfo.fileName());
- }
-#elif defined Q_OS_HAIKU
+#if defined Q_OS_HAIKU
fs_info fsInfo;
memset(&fsInfo, 0, sizeof(fsInfo));
@@ -832,7 +402,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
{
QT_STATFSBUF statfs_buf;
int result;
- EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
+ QT_EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
if (result == 0) {
valid = true;
ready = true;
@@ -846,7 +416,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
#endif
- blockSize = statfs_buf.f_bsize;
+ blockSize = int(statfs_buf.f_bsize);
#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
#if defined(_STATFS_F_FLAGS)
readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
@@ -857,6 +427,37 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
}
}
+void QStorageInfoPrivate::initRootPath()
+{
+ rootPath = QFileInfo(rootPath).canonicalFilePath();
+
+ if (rootPath.isEmpty())
+ return;
+
+ QStorageIterator it;
+ if (!it.isValid()) {
+ rootPath = QStringLiteral("/");
+ return;
+ }
+
+ int maxLength = 0;
+ const QString oldRootPath = rootPath;
+ rootPath.clear();
+
+ while (it.next()) {
+ const QString mountDir = it.rootPath();
+ const QByteArray fsName = it.fileSystemType();
+ // we try to find most suitable entry
+ if (maxLength < mountDir.size() && isParentOf(mountDir, oldRootPath)) {
+ maxLength = mountDir.size();
+ rootPath = mountDir;
+ device = it.device();
+ fileSystemType = fsName;
+ subvolume = it.subvolume();
+ }
+ }
+}
+
QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
{
QStorageIterator it;
@@ -866,7 +467,7 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
QList<QStorageInfo> volumes;
while (it.next()) {
- if (!shouldIncludeFs(it))
+ if (!shouldIncludeFs(it.rootPath(), it.fileSystemType()))
continue;
const QString mountDir = it.rootPath();
@@ -874,7 +475,7 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
info.d->device = it.device();
info.d->fileSystemType = it.fileSystemType();
info.d->subvolume = it.subvolume();
- if (info.bytesTotal() == 0 && info != root())
+ if (info.bytesTotal() <= 0 && info != root())
continue;
volumes.append(info);
}
@@ -882,9 +483,4 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
return volumes;
}
-QStorageInfo QStorageInfoPrivate::root()
-{
- return QStorageInfo(QStringLiteral("/"));
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/io/qstorageinfo_win.cpp b/src/corelib/io/qstorageinfo_win.cpp
index 8a3db90f87..3ee1df9f3c 100644
--- a/src/corelib/io/qstorageinfo_win.cpp
+++ b/src/corelib/io/qstorageinfo_win.cpp
@@ -1,54 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstorageinfo_p.h"
#include <QtCore/qdir.h>
#include <QtCore/qfileinfo.h>
+#include <QtCore/qmutex.h>
#include <QtCore/qvarlengtharray.h>
#include "qfilesystementry_p.h"
+#include "private/qsystemlibrary_p.h"
-#include <qt_windows.h>
+#include "qntdll_p.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static const int defaultBufferSize = MAX_PATH + 1;
static QString canonicalPath(const QString &rootPath)
@@ -57,16 +25,16 @@ static QString canonicalPath(const QString &rootPath)
if (path.isEmpty())
return path;
- if (path.startsWith(QLatin1String("\\\\?\\")))
+ if (path.startsWith("\\\\?\\"_L1))
path.remove(0, 4);
- if (path.length() < 2 || path.at(1) != QLatin1Char(':'))
+ if (path.length() < 2 || path.at(1) != u':')
return QString();
path[0] = path[0].toUpper();
if (!(path.at(0).unicode() >= 'A' && path.at(0).unicode() <= 'Z'))
return QString();
- if (!path.endsWith(QLatin1Char('\\')))
- path.append(QLatin1Char('\\'));
+ if (!path.endsWith(u'\\'))
+ path.append(u'\\');
return path;
}
@@ -134,6 +102,9 @@ void QStorageInfoPrivate::doStat()
return;
device = getDevice(rootPath);
retrieveDiskFreeSpace();
+
+ if (!queryStorageProperty())
+ queryFileFsSectorSizeInformation();
}
void QStorageInfoPrivate::retrieveVolumeInfo()
@@ -192,16 +163,146 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
if (!drive.rootPath().isEmpty()) // drive exists, but not mounted
volumes.append(drive);
}
- driveName[0] = driveName[0].unicode() + 1;
+ driveName[0] = QChar(driveName[0].unicode() + 1);
driveBits = driveBits >> 1;
}
return volumes;
}
-QStorageInfo QStorageInfoPrivate::root()
+bool QStorageInfoPrivate::queryStorageProperty()
+{
+ QString path = QDir::toNativeSeparators(uR"(\\.\)" + rootPath);
+ if (path.endsWith(u'\\'))
+ path.chop(1);
+
+ HANDLE handle = CreateFile(reinterpret_cast<const wchar_t *>(path.utf16()),
+ 0, // no access to the drive
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ nullptr,
+ OPEN_EXISTING,
+ 0,
+ nullptr);
+ if (handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ STORAGE_PROPERTY_QUERY spq;
+ memset(&spq, 0, sizeof(spq));
+ spq.PropertyId = StorageAccessAlignmentProperty;
+ spq.QueryType = PropertyStandardQuery;
+
+ STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR saad;
+ memset(&saad, 0, sizeof(saad));
+
+ DWORD bytes = 0;
+ BOOL result = DeviceIoControl(handle,
+ IOCTL_STORAGE_QUERY_PROPERTY,
+ &spq, sizeof(spq),
+ &saad, sizeof(saad),
+ &bytes,
+ nullptr);
+ CloseHandle(handle);
+ if (result)
+ blockSize = int(saad.BytesPerPhysicalSector);
+ return result;
+}
+
+struct Helper
+{
+ QBasicMutex mutex;
+ QSystemLibrary ntdll {u"ntdll"_s};
+};
+Q_GLOBAL_STATIC(Helper, gNtdllHelper)
+
+inline QFunctionPointer resolveSymbol(QSystemLibrary *ntdll, const char *name)
{
- return QStorageInfo(QDir::fromNativeSeparators(QFile::decodeName(qgetenv("SystemDrive"))));
+ QFunctionPointer symbolFunctionPointer = ntdll->resolve(name);
+ if (Q_UNLIKELY(!symbolFunctionPointer))
+ qWarning("Failed to resolve the symbol: %s", name);
+ return symbolFunctionPointer;
+}
+
+#define GENERATE_SYMBOL(symbolName, returnType, ...) \
+using Qt##symbolName = returnType (NTAPI *) (__VA_ARGS__); \
+static Qt##symbolName qt##symbolName = nullptr;
+
+#define RESOLVE_SYMBOL(name) \
+ do { \
+ qt##name = reinterpret_cast<Qt##name>(resolveSymbol(ntdll, #name)); \
+ if (!qt##name) \
+ return false; \
+ } while (false)
+
+GENERATE_SYMBOL(RtlInitUnicodeString, void, PUNICODE_STRING, PCWSTR);
+GENERATE_SYMBOL(NtCreateFile, NTSTATUS, PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
+ PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
+GENERATE_SYMBOL(NtQueryVolumeInformationFile, NTSTATUS, HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
+ FS_INFORMATION_CLASS);
+
+void QStorageInfoPrivate::queryFileFsSectorSizeInformation()
+{
+ static bool symbolsResolved = [](auto ntdllHelper) {
+ QMutexLocker locker(&ntdllHelper->mutex);
+ auto ntdll = &ntdllHelper->ntdll;
+ if (!ntdll->isLoaded()) {
+ if (!ntdll->load()) {
+ qWarning("Unable to load ntdll.dll.");
+ return false;
+ }
+ }
+
+ RESOLVE_SYMBOL(RtlInitUnicodeString);
+ RESOLVE_SYMBOL(NtCreateFile);
+ RESOLVE_SYMBOL(NtQueryVolumeInformationFile);
+
+ return true;
+ }(gNtdllHelper());
+ if (!symbolsResolved)
+ return;
+
+ FILE_FS_SECTOR_SIZE_INFORMATION ffssi;
+ memset(&ffssi, 0, sizeof(ffssi));
+
+ HANDLE handle = nullptr;
+
+ OBJECT_ATTRIBUTES attrs;
+ memset(&attrs, 0, sizeof(attrs));
+
+ IO_STATUS_BLOCK isb;
+ memset(&isb, 0, sizeof(isb));
+
+ QString path = QDir::toNativeSeparators(uR"(\??\\)" + rootPath);
+ if (!path.endsWith(u'\\'))
+ path.append(u'\\');
+
+ UNICODE_STRING name;
+ qtRtlInitUnicodeString(&name, reinterpret_cast<const wchar_t *>(path.utf16()));
+
+ InitializeObjectAttributes(&attrs, &name, 0, nullptr, nullptr);
+
+ NTSTATUS status = qtNtCreateFile(&handle,
+ FILE_READ_ATTRIBUTES,
+ &attrs,
+ &isb,
+ nullptr,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN,
+ 0,
+ nullptr,
+ 0);
+ if (!NT_SUCCESS(status))
+ return;
+
+ memset(&isb, 0, sizeof(isb));
+ status = qtNtQueryVolumeInformationFile(handle,
+ &isb,
+ &ffssi,
+ sizeof(ffssi),
+ FS_INFORMATION_CLASS(10)); // FileFsSectorSizeInformation
+ CloseHandle(handle);
+ if (NT_SUCCESS(status))
+ blockSize = ffssi.PhysicalBytesPerSectorForAtomicity;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qt_attribution.json b/src/corelib/io/qt_attribution.json
deleted file mode 100644
index 397d7668a4..0000000000
--- a/src/corelib/io/qt_attribution.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "Id": "psl",
- "Name": "The Public Suffix List",
- "QDocModule": "qtcore",
- "Description": "The Public Suffix List is an initiative of Mozilla,
-but is maintained as a community resource. It is available for use in any software,
-but was originally created to meet the needs of browser manufacturers.
-It allows browsers to, for example:
-
-- Avoid privacy-damaging \"supercookies\" being set for high-level domain name suffixes
-
-- Highlight the most important part of a domain name in the user interface
-
-- Accurately sort history entries by site",
-
- "Files": "qurltlds_p.h",
- "QtUsage": "See util/corelib/qurl-generateTLDs/ for code-generator",
- "QtUsage": "Used in Qt Core to avoid setting \"supercookies\" in the cookie jar
-supported by Qt (by the QNetworkCookieJar class).",
-
- "Homepage": "Consult https://github.com/publicsuffix/list for the sha1 but download from ...",
- "Homepage": "http://publicsuffix.org/",
- "Version": "b880425f09bca902da412bdece4f68e942f3a23b, fetched on 2020-03-13",
- "License": "Mozilla Public License 2.0",
- "LicenseFile": "PSL-LICENSE.txt",
- "LicenseId": "MPL-2.0",
- "Copyright": "The list was originally provided by Jo Hermans <jo.hermans@gmail.com>.
-It is now maintained on github (https://github.com/publicsuffix/list)."
-}
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp
index ed52472ab3..8187524067 100644
--- a/src/corelib/io/qtemporarydir.cpp
+++ b/src/corelib/io/qtemporarydir.cpp
@@ -1,50 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtemporarydir.h"
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
#include "qdebug.h"
-#include "qdiriterator.h"
-#include "qpair.h"
#include "qplatformdefs.h"
#include "qrandom.h"
#include "private/qtemporaryfile_p.h"
@@ -57,8 +19,15 @@
#include <errno.h>
#endif
+#include <type_traits>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+static_assert(std::is_nothrow_move_constructible_v<QTemporaryDir>);
+static_assert(std::is_nothrow_move_assignable_v<QTemporaryDir>);
+
//************* QTemporaryDirPrivate
class QTemporaryDirPrivate
{
@@ -90,9 +59,9 @@ static QString defaultTemplateName()
baseName = QCoreApplication::applicationName();
if (baseName.isEmpty())
#endif
- baseName = QLatin1String("qt_temp");
+ baseName = "qt_temp"_L1;
- return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX");
+ return QDir::tempPath() + u'/' + baseName + "-XXXXXX"_L1;
}
void QTemporaryDirPrivate::create(const QString &templateName)
@@ -101,17 +70,9 @@ void QTemporaryDirPrivate::create(const QString &templateName)
for (int i = 0; i < 256; ++i) {
tfn.generateNext();
QFileSystemEntry fileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath());
- if (QFileSystemEngine::createDirectory(fileSystemEntry, false)) {
- QSystemError error;
- QFileSystemEngine::setPermissions(fileSystemEntry,
- QFile::ReadOwner |
- QFile::WriteOwner |
- QFile::ExeOwner, error);
- if (error.error() != 0) {
- if (!QFileSystemEngine::removeDirectory(fileSystemEntry, false))
- qWarning() << "Unable to remove unused directory" << templateName;
- continue;
- }
+ if (QFileSystemEngine::createDirectory(fileSystemEntry, false,
+ QFile::ReadOwner | QFile::WriteOwner
+ | QFile::ExeOwner)) {
success = true;
pathOrError = fileSystemEntry.filePath();
return;
@@ -206,6 +167,39 @@ QTemporaryDir::QTemporaryDir(const QString &templatePath)
}
/*!
+ \fn QTemporaryDir::QTemporaryDir(QTemporaryDir &&other)
+
+ Move-constructs a new QTemporaryDir from \a other.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 6.4
+*/
+
+/*!
+ \fn QTemporaryDir &QTemporaryDir::operator=(QTemporaryDir&& other)
+
+ Move-assigns \a other to this QTemporaryDir instance.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 6.4
+*/
+
+/*!
+ \fn void QTemporaryDir::swap(QTemporaryDir &other)
+
+ Swaps temporary-dir \a other with this temporary-dir. This operation is
+ very fast and never fails.
+
+ \since 6.4
+*/
+
+/*!
Destroys the temporary directory object.
If auto remove mode was set, it will automatically delete the directory
including all its contents.
@@ -214,8 +208,12 @@ QTemporaryDir::QTemporaryDir(const QString &templatePath)
*/
QTemporaryDir::~QTemporaryDir()
{
- if (d_ptr->autoRemove)
- remove();
+ if (d_ptr) {
+ if (d_ptr->autoRemove)
+ remove();
+
+ delete d_ptr;
+ }
}
/*!
@@ -268,7 +266,7 @@ QString QTemporaryDir::filePath(const QString &fileName) const
QString ret = d_ptr->pathOrError;
if (!fileName.isEmpty()) {
- ret += QLatin1Char('/');
+ ret += u'/';
ret += fileName;
}
return ret;
@@ -313,7 +311,7 @@ bool QTemporaryDir::remove()
if (!d_ptr->success)
return false;
Q_ASSERT(!path().isEmpty());
- Q_ASSERT(path() != QLatin1String("."));
+ Q_ASSERT(path() != "."_L1);
const bool result = QDir(path()).removeRecursively();
if (!result) {
@@ -326,4 +324,4 @@ bool QTemporaryDir::remove()
QT_END_NAMESPACE
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
diff --git a/src/corelib/io/qtemporarydir.h b/src/corelib/io/qtemporarydir.h
index 5864ce5cfc..8737bf9e26 100644
--- a/src/corelib/io/qtemporarydir.h
+++ b/src/corelib/io/qtemporarydir.h
@@ -1,52 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEMPORARYDIR_H
#define QTEMPORARYDIR_H
+#include <QtCore/qglobal.h>
#include <QtCore/qdir.h>
#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
class QTemporaryDirPrivate;
@@ -55,8 +20,17 @@ class Q_CORE_EXPORT QTemporaryDir
public:
QTemporaryDir();
explicit QTemporaryDir(const QString &templateName);
+ QTemporaryDir(QTemporaryDir &&other) noexcept
+ : d_ptr{std::exchange(other.d_ptr, nullptr)}
+ { }
+
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QTemporaryDir)
+
~QTemporaryDir();
+ void swap(QTemporaryDir &other) noexcept
+ { qt_ptr_swap(d_ptr, other.d_ptr); }
+
bool isValid() const;
QString errorString() const;
@@ -68,12 +42,17 @@ public:
QString filePath(const QString &fileName) const;
private:
- QScopedPointer<QTemporaryDirPrivate> d_ptr;
+ QTemporaryDirPrivate *d_ptr;
Q_DISABLE_COPY(QTemporaryDir)
};
-#endif // QT_NO_TEMPORARYFILE
+inline void swap(QTemporaryDir &lhs, QTemporaryDir &rhs) noexcept
+{
+ lhs.swap(rhs);
+}
+
+#endif // QT_CONFIG(temporaryfile)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index e6a160c3b2..4e48a18d91 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtemporaryfile.h"
@@ -59,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if defined(Q_OS_WIN)
typedef ushort Char;
@@ -78,20 +44,20 @@ typedef int NativeFileHandle;
QTemporaryFileName::QTemporaryFileName(const QString &templateName)
{
// Ensure there is a placeholder mask
- QString qfilename = templateName;
- uint phPos = qfilename.length();
- uint phLength = 0;
+ QString qfilename = QDir::fromNativeSeparators(templateName);
+ qsizetype phPos = qfilename.size();
+ qsizetype phLength = 0;
while (phPos != 0) {
--phPos;
- if (qfilename[phPos] == QLatin1Char('X')) {
+ if (qfilename[phPos] == u'X') {
++phLength;
continue;
}
if (phLength >= 6
- || qfilename[phPos] == QLatin1Char('/')) {
+ || qfilename[phPos] == u'/') {
++phPos;
break;
}
@@ -101,15 +67,14 @@ QTemporaryFileName::QTemporaryFileName(const QString &templateName)
}
if (phLength < 6)
- qfilename.append(QLatin1String(".XXXXXX"));
+ qfilename.append(".XXXXXX"_L1);
// "Nativify" :-)
- QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
- QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
- .nativeFilePath();
+ QFileSystemEntry::NativePath filename =
+ QFileSystemEntry(QDir::cleanPath(qfilename)).nativeFilePath();
// Find mask in native path
- phPos = filename.length();
+ phPos = filename.size();
phLength = 0;
while (phPos != 0) {
--phPos;
@@ -143,8 +108,8 @@ QTemporaryFileName::QTemporaryFileName(const QString &templateName)
QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
{
Q_ASSERT(length != 0);
- Q_ASSERT(pos < path.length());
- Q_ASSERT(length <= path.length() - pos);
+ Q_ASSERT(pos < path.size());
+ Q_ASSERT(length <= path.size() - pos);
Char *const placeholderStart = (Char *)path.data() + pos;
Char *const placeholderEnd = placeholderStart + length;
@@ -191,14 +156,14 @@ QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
return path;
}
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
/*!
\internal
Generates a unique file path from the template \a templ and creates a new
- file based based on those parameters: the \c templ.length characters in \c
- templ.path starting at \c templ.pos will be replacd by a random sequence of
+ file based on those parameters: the \c templ.length characters in \c
+ templ.path starting at \c templ.pos will be replaced by a random sequence of
characters. \a mode specifies the file mode bits (not used on Windows).
Returns true on success and sets the file handle on \a file. On error,
@@ -219,8 +184,9 @@ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &t
const DWORD shareMode = (flags & QTemporaryFileEngine::Win32NonShared)
? 0u : (FILE_SHARE_READ | FILE_SHARE_WRITE);
+ const DWORD extraAccessFlags = (flags & QTemporaryFileEngine::Win32NonShared) ? DELETE : 0;
file = CreateFile((const wchar_t *)path.constData(),
- GENERIC_READ | GENERIC_WRITE,
+ GENERIC_READ | GENERIC_WRITE | extraAccessFlags,
shareMode, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
@@ -242,7 +208,7 @@ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &t
return false;
}
#else // POSIX
- Q_UNUSED(flags)
+ Q_UNUSED(flags);
file = QT_OPEN(path.constData(),
QT_OPEN_CREAT | QT_OPEN_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
static_cast<mode_t>(mode));
@@ -340,7 +306,8 @@ void QTemporaryFileEngine::setFileName(const QString &file)
QFSFileEngine::setFileName(file);
}
-bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
+bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode,
+ std::optional<QFile::Permissions> permissions)
{
Q_D(QFSFileEngine);
Q_ASSERT(!isReallyOpen());
@@ -348,7 +315,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
openMode |= QIODevice::ReadWrite;
if (!filePathIsTemplate)
- return QFSFileEngine::open(openMode);
+ return QFSFileEngine::open(openMode, permissions);
QTemporaryFileName tfn(templateName);
@@ -424,6 +391,18 @@ bool QTemporaryFileEngine::renameOverwrite(const QString &newName)
QFSFileEngine::close();
return ok;
}
+#ifdef Q_OS_WIN
+ if (flags & Win32NonShared) {
+ QFileSystemEntry newEntry(newName, QFileSystemEntry::FromInternalPath());
+ bool ok = d_func()->nativeRenameOverwrite(newEntry);
+ QFSFileEngine::close();
+ if (ok) {
+ // Match what QFSFileEngine::renameOverwrite() does
+ setFileEntry(std::move(newEntry));
+ }
+ return ok;
+ }
+#endif
QFSFileEngine::close();
return QFSFileEngine::renameOverwrite(newName);
}
@@ -439,7 +418,7 @@ bool QTemporaryFileEngine::close()
QString QTemporaryFileEngine::fileName(QAbstractFileEngine::FileName file) const
{
if (isUnnamedFile()) {
- if (file == LinkName) {
+ if (file == AbsoluteLinkTarget || file == RawLinkPath) {
// we know our file isn't (won't be) a symlink
return QString();
}
@@ -575,9 +554,9 @@ QString QTemporaryFilePrivate::defaultTemplateName()
baseName = QCoreApplication::applicationName();
if (baseName.isEmpty())
#endif
- baseName = QLatin1String("qt_temp");
+ baseName = "qt_temp"_L1;
- return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String(".XXXXXX");
+ return QDir::tempPath() + u'/' + baseName + ".XXXXXX"_L1;
}
//************* QTemporaryFile
@@ -619,6 +598,9 @@ QString QTemporaryFilePrivate::defaultTemplateName()
be placed into the temporary path as returned by QDir::tempPath().
If you specify your own filename, a relative file path will not be placed in the
temporary directory by default, but be relative to the current working directory.
+ It is important to specify the correct directory if the rename() function will be
+ called, as QTemporaryFile can only rename files within the same volume / filesystem
+ as the temporary file itself was created on.
Specified filenames can contain the following template \c XXXXXX
(six upper case "X" characters), which will be replaced by the
@@ -661,6 +643,12 @@ QTemporaryFile::QTemporaryFile()
}
/*!
+ \fn QTemporaryFile::QTemporaryFile(const std::filesystem::path &templateName, QObject *parent)
+ \overload
+ \since 6.7
+*/
+
+/*!
Constructs a QTemporaryFile with a template filename of \a
templateName. Upon opening the temporary file this will be used to create
a unique filename.
@@ -670,7 +658,11 @@ QTemporaryFile::QTemporaryFile()
If \a templateName is a relative path, the path will be relative to the
current working directory. You can use QDir::tempPath() to construct \a
- templateName if you want use the system's temporary directory.
+ templateName if you want use the system's temporary directory. It is
+ important to specify the correct directory if the rename() function will be
+ called, as QTemporaryFile can only rename files within the same volume /
+ filesystem as the temporary file itself was created on.
+
\sa open(), fileTemplate()
*/
@@ -703,7 +695,10 @@ QTemporaryFile::QTemporaryFile(QObject *parent)
If \a templateName is a relative path, the path will be relative to the
current working directory. You can use QDir::tempPath() to construct \a
- templateName if you want use the system's temporary directory.
+ templateName if you want use the system's temporary directory. It is
+ important to specify the correct directory if the rename() function will be
+ called, as QTemporaryFile can only rename files within the same volume /
+ filesystem as the temporary file itself was created on.
\sa open(), fileTemplate()
*/
@@ -736,7 +731,7 @@ QTemporaryFile::~QTemporaryFile()
return true upon success and will set the fileName() to the unique
filename used.
- \sa fileName()
+ \sa fileName(), QT_USE_NODISCARD_FILE_OPEN
*/
/*!
@@ -797,7 +792,7 @@ QString QTemporaryFile::fileName() const
if (tef && tef->isReallyOpen())
const_cast<QTemporaryFilePrivate *>(d)->materializeUnnamedFile();
- if(d->fileName.isEmpty())
+ if (d->fileName.isEmpty())
return QString();
return d->engine()->fileName(QAbstractFileEngine::DefaultName);
}
@@ -815,6 +810,12 @@ QString QTemporaryFile::fileTemplate() const
}
/*!
+ \fn void QTemporaryFile::setFileTemplate(const std::filesystem::path &name)
+ \overload
+ \since 6.7
+*/
+
+/*!
Sets the static portion of the file name to \a name. If the file
template contains XXXXXX that will automatically be replaced with
the unique part of the filename, otherwise a filename will be
@@ -822,7 +823,10 @@ QString QTemporaryFile::fileTemplate() const
If \a name contains a relative file path, the path will be relative to the
current working directory. You can use QDir::tempPath() to construct \a
- name if you want use the system's temporary directory.
+ name if you want use the system's temporary directory. It is important to
+ specify the correct directory if the rename() function will be called, as
+ QTemporaryFile can only rename files within the same volume / filesystem as
+ the temporary file itself was created on.
\sa fileTemplate()
*/
@@ -833,11 +837,28 @@ void QTemporaryFile::setFileTemplate(const QString &name)
}
/*!
- \internal
+ \fn bool QTemporaryFile::rename(const std::filesystem::path &newName)
+ \overload
+ \since 6.7
+*/
- This is just a simplified version of QFile::rename() because we know a few
- extra details about what kind of file we have. The documentation is hidden
- from the user because QFile::rename() should be enough.
+/*!
+ Renames the current temporary file to \a newName and returns true if it
+ succeeded.
+
+ This function has an important difference compared to QFile::rename(): it
+ will not perform a copy+delete if the low-level system call to rename the
+ file fails, something that could happen if \a newName specifies a file in a
+ different volume or filesystem than the temporary file was created on. In
+ other words, QTemporaryFile only supports atomic file renaming.
+
+ This functionality is intended to support materializing the destination
+ file with all contents already present, so another process cannot see an
+ incomplete file in the process of being written. The \l QSaveFile class can
+ be used for a similar purpose too, particularly if the destination file is
+ not temporary.
+
+ \sa QSaveFile, QSaveFile::commit(), QFile::rename()
*/
bool QTemporaryFile::rename(const QString &newName)
{
@@ -852,7 +873,6 @@ bool QTemporaryFile::rename(const QString &newName)
if (tef->rename(newName)) {
unsetError();
// engine was able to handle the new name so we just reset it
- tef->setFileName(newName);
d->fileName = newName;
return true;
}
@@ -863,28 +883,17 @@ bool QTemporaryFile::rename(const QString &newName)
}
/*!
- \fn QTemporaryFile *QTemporaryFile::createLocalFile(const QString &fileName)
- \overload
- \obsolete
-
- Use QTemporaryFile::createNativeFile(const QString &fileName) instead.
-*/
-
-/*!
- \fn QTemporaryFile *QTemporaryFile::createLocalFile(QFile &file)
- \obsolete
-
- Use QTemporaryFile::createNativeFile(QFile &file) instead.
-*/
-
-/*!
\fn QTemporaryFile *QTemporaryFile::createNativeFile(const QString &fileName)
\overload
Works on the given \a fileName rather than an existing QFile
object.
*/
-
+/*!
+ \fn QTemporaryFile *QTemporaryFile::createNativeFile(const std::filesystem::path &fileName)
+ \overload
+ \since 6.7
+*/
/*!
If \a file is not already a native file, then a QTemporaryFile is created
@@ -902,12 +911,12 @@ bool QTemporaryFile::rename(const QString &newName)
QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file)
{
if (QAbstractFileEngine *engine = file.d_func()->engine()) {
- if(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)
+ if (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)
return nullptr; // native already
//cache
bool wasOpen = file.isOpen();
qint64 old_off = 0;
- if(wasOpen)
+ if (wasOpen)
old_off = file.pos();
else if (!file.open(QIODevice::ReadOnly))
return nullptr;
@@ -928,7 +937,7 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file)
ret = nullptr;
}
//restore
- if(wasOpen)
+ if (wasOpen)
file.seek(old_off);
else
file.close();
@@ -972,7 +981,7 @@ bool QTemporaryFile::open(OpenMode flags)
return false;
}
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h
index 90a6a613e6..9a4476f9d2 100644
--- a/src/corelib/io/qtemporaryfile.h
+++ b/src/corelib/io/qtemporaryfile.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEMPORARYFILE_H
#define QTEMPORARYFILE_H
@@ -50,7 +14,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
class QTemporaryFilePrivate;
class QLockFilePrivate;
@@ -68,32 +32,59 @@ public:
#ifndef QT_NO_QOBJECT
explicit QTemporaryFile(QObject *parent);
QTemporaryFile(const QString &templateName, QObject *parent);
-#endif
+
+# if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
+ Q_WEAK_OVERLOAD
+ explicit QTemporaryFile(const std::filesystem::path &templateName, QObject *parent = nullptr)
+ : QTemporaryFile(QtPrivate::fromFilesystemPath(templateName), parent)
+ {
+ }
+# endif // QT_CONFIG(cxx17_filesystem)
+#endif // !QT_NO_QOBJECT
+
~QTemporaryFile();
bool autoRemove() const;
void setAutoRemove(bool b);
// ### Hides open(flags)
- bool open() { return open(QIODevice::ReadWrite); }
+ QFILE_MAYBE_NODISCARD bool open() { return open(QIODevice::ReadWrite); }
QString fileName() const override;
QString fileTemplate() const;
void setFileTemplate(const QString &name);
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
+ Q_WEAK_OVERLOAD
+ void setFileTemplate(const std::filesystem::path &name)
+ {
+ return setFileTemplate(QtPrivate::fromFilesystemPath(name));
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
// Hides QFile::rename
bool rename(const QString &newName);
-#if QT_DEPRECATED_SINCE(5,1)
- QT_DEPRECATED inline static QTemporaryFile *createLocalFile(const QString &fileName)
- { return createNativeFile(fileName); }
- QT_DEPRECATED inline static QTemporaryFile *createLocalFile(QFile &file)
- { return createNativeFile(file); }
-#endif
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
+ Q_WEAK_OVERLOAD
+ bool rename(const std::filesystem::path &newName)
+ {
+ return rename(QtPrivate::fromFilesystemPath(newName));
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
+
inline static QTemporaryFile *createNativeFile(const QString &fileName)
{ QFile file(fileName); return createNativeFile(file); }
static QTemporaryFile *createNativeFile(QFile &file);
+#if QT_CONFIG(cxx17_filesystem) || defined(Q_QDOC)
+ Q_WEAK_OVERLOAD
+ static QTemporaryFile *createNativeFile(const std::filesystem::path &fileName)
+ {
+ QFile file(fileName);
+ return createNativeFile(file);
+ }
+#endif // QT_CONFIG(cxx17_filesystem)
+
protected:
bool open(OpenMode flags) override;
@@ -103,7 +94,7 @@ private:
Q_DISABLE_COPY(QTemporaryFile)
};
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h
index 6bcff936b4..d160afe41e 100644
--- a/src/corelib/io/qtemporaryfile_p.h
+++ b/src/corelib/io/qtemporaryfile_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEMPORARYFILE_P_H
#define QTEMPORARYFILE_P_H
@@ -81,7 +45,7 @@ struct QTemporaryFileName
QFileSystemEntry::NativePath generateNext();
};
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
class QTemporaryFilePrivate : public QFilePrivate
{
@@ -124,8 +88,7 @@ public:
if (filePathIsTemplate) {
d->fileEntry.clear();
} else {
- d->fileEntry = QFileSystemEntry(file);
- QFSFileEngine::setFileName(file);
+ QFSFileEngine::setFileEntry(QFileSystemEntry(file));
}
}
~QTemporaryFileEngine();
@@ -133,7 +96,7 @@ public:
bool isReallyOpen() const;
void setFileName(const QString &file) override;
- bool open(QIODevice::OpenMode flags) override;
+ bool open(QIODevice::OpenMode flags, std::optional<QFile::Permissions> permissions) override;
bool remove() override;
bool rename(const QString &newName) override;
bool renameOverwrite(const QString &newName) override;
@@ -152,7 +115,7 @@ public:
bool unnamedFile = false;
};
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
QT_END_NAMESPACE
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 1a266702eb..4360b5b076 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QUrl
@@ -50,14 +14,18 @@
\ingroup network
\ingroup shared
+ \compares weak
It can parse and construct URLs in both encoded and unencoded
form. QUrl also has support for internationalized domain names
(IDNs).
- The most common way to use QUrl is to initialize it via the
- constructor by passing a QString. Otherwise, setUrl() can also
- be used.
+ The most common way to use QUrl is to initialize it via the constructor by
+ passing a QString containing a full URL. QUrl objects can also be created
+ from a QByteArray containing a full URL using QUrl::fromEncoded(), or
+ heuristically from incomplete URLs using QUrl::fromUserInput(). The URL
+ representation can be obtained from a QUrl using either QUrl::toString() or
+ QUrl::toEncoded().
URLs can be represented in two forms: encoded or unencoded. The
unencoded representation is suitable for showing to users, but
@@ -390,6 +358,25 @@
*/
/*!
+ \enum QUrl::AceProcessingOption
+ \since 6.3
+
+ The ACE processing options control the way URLs are transformed to and from
+ ASCII-Compatible Encoding.
+
+ \value IgnoreIDNWhitelist Ignore the IDN whitelist when converting URLs
+ to Unicode.
+ \value AceTransitionalProcessing Use transitional processing described in UTS #46.
+ This allows better compatibility with IDNA 2003
+ specification.
+
+ The default is to use nontransitional processing and to allow non-ASCII
+ characters only inside URLs whose top-level domains are listed in the IDN whitelist.
+
+ \sa toAce(), fromAce(), idnWhitelist()
+*/
+
+/*!
\fn QUrl::QUrl(QUrl &&other)
Move-constructs a QUrl instance, making it point at the same
@@ -413,22 +400,21 @@
#include "qstringlist.h"
#include "qdebug.h"
#include "qhash.h"
-#include "qdir.h" // for QDir::fromNativeSeparators
#include "qdatastream.h"
#include "private/qipaddress_p.h"
#include "qurlquery.h"
#include "private/qdir_p.h"
-#include <private/qmemory_p.h>
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
-// in qstring.cpp:
-void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept;
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
inline static bool isHex(char c)
{
c |= 0x20;
- return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
+ return isAsciiDigit(c) || (c >= 'a' && c <= 'f');
}
static inline QString ftpScheme()
@@ -509,8 +495,8 @@ public:
struct Error {
QString source;
+ qsizetype position;
ErrorCode code;
- int position;
};
QUrlPrivate();
@@ -523,11 +509,11 @@ public:
std::unique_ptr<Error> cloneError() const;
void clearError();
- void setError(ErrorCode errorCode, const QString &source, int supplement = -1);
- ErrorCode validityError(QString *source = nullptr, int *position = nullptr) const;
- bool validateComponent(Section section, const QString &input, int begin, int end);
+ void setError(ErrorCode errorCode, const QString &source, qsizetype supplement = -1);
+ ErrorCode validityError(QString *source = nullptr, qsizetype *position = nullptr) const;
+ bool validateComponent(Section section, const QString &input, qsizetype begin, qsizetype end);
bool validateComponent(Section section, const QString &input)
- { return validateComponent(section, input, 0, uint(input.length())); }
+ { return validateComponent(section, input, 0, input.size()); }
// no QString scheme() const;
void appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
@@ -540,15 +526,15 @@ public:
void appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;
// the "end" parameters are like STL iterators: they point to one past the last valid element
- bool setScheme(const QString &value, int len, bool doSetError);
- void setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode);
- void setUserInfo(const QString &userInfo, int from, int end);
- void setUserName(const QString &value, int from, int end);
- void setPassword(const QString &value, int from, int end);
- bool setHost(const QString &value, int from, int end, QUrl::ParsingMode mode);
- void setPath(const QString &value, int from, int end);
- void setQuery(const QString &value, int from, int end);
- void setFragment(const QString &value, int from, int end);
+ bool setScheme(const QString &value, qsizetype len, bool doSetError);
+ void setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode);
+ void setUserInfo(const QString &userInfo, qsizetype from, qsizetype end);
+ void setUserName(const QString &value, qsizetype from, qsizetype end);
+ void setPassword(const QString &value, qsizetype from, qsizetype end);
+ bool setHost(const QString &value, qsizetype from, qsizetype end, QUrl::ParsingMode mode);
+ void setPath(const QString &value, qsizetype from, qsizetype end);
+ void setQuery(const QString &value, qsizetype from, qsizetype end);
+ void setFragment(const QString &value, qsizetype from, qsizetype end);
inline bool hasScheme() const { return sectionIsPresent & Scheme; }
inline bool hasAuthority() const { return sectionIsPresent & Authority; }
@@ -617,7 +603,7 @@ inline QUrlPrivate::~QUrlPrivate()
std::unique_ptr<QUrlPrivate::Error> QUrlPrivate::cloneError() const
{
- return error ? qt_make_unique<Error>(*error) : nullptr;
+ return error ? std::make_unique<Error>(*error) : nullptr;
}
inline void QUrlPrivate::clearError()
@@ -625,13 +611,13 @@ inline void QUrlPrivate::clearError()
error.reset();
}
-inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, int supplement)
+inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, qsizetype supplement)
{
if (error) {
// don't overwrite an error set in a previous section during parsing
return;
}
- error = qt_make_unique<Error>();
+ error = std::make_unique<Error>();
error->code = errorCode;
error->source = source;
error->position = supplement;
@@ -816,11 +802,11 @@ static const ushort * const fragmentInUrl = userNameInUrl + 6;
static inline void parseDecodedComponent(QString &data)
{
- data.replace(QLatin1Char('%'), QLatin1String("%25"));
+ data.replace(u'%', "%25"_L1);
}
static inline QString
-recodeFromUser(const QString &input, const ushort *actions, int from, int to)
+recodeFromUser(const QString &input, const ushort *actions, qsizetype from, qsizetype to)
{
QString output;
const QChar *begin = input.constData() + from;
@@ -836,14 +822,16 @@ recodeFromUser(const QString &input, const ushort *actions, int from, int to)
static inline void appendToUser(QString &appendTo, QStringView value, QUrl::FormattingOptions options,
const ushort *actions)
{
- // Test ComponentFormattingOptions, ignore FormattingOptions.
- if ((options & 0xFFFF0000) == QUrl::PrettyDecoded) {
+ // The stored value is already QUrl::PrettyDecoded, so there's nothing to
+ // do if that's what the user asked for (test only
+ // ComponentFormattingOptions, ignore FormattingOptions).
+ if ((options & 0xFFFF0000) == QUrl::PrettyDecoded ||
+ !qt_urlRecode(appendTo, value, options, actions))
appendTo += value;
- return;
- }
- if (!qt_urlRecode(appendTo, value, options, actions))
- appendTo += value;
+ // copy nullness, if necessary, because QString::operator+=(QStringView) doesn't
+ if (appendTo.isNull() && !value.isNull())
+ appendTo.detach();
}
inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -853,11 +841,11 @@ inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOpti
// add '@' only if we added anything
if (hasUserName() || (hasPassword() && (options & QUrl::RemovePassword) == 0))
- appendTo += QLatin1Char('@');
+ appendTo += u'@';
}
appendHost(appendTo, options);
if (!(options & QUrl::RemovePort) && port != -1)
- appendTo += QLatin1Char(':') + QString::number(port);
+ appendTo += u':' + QString::number(port);
}
inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -899,7 +887,7 @@ inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptio
if (options & QUrl::RemovePassword || !hasPassword()) {
return;
} else {
- appendTo += QLatin1Char(':');
+ appendTo += u':';
if (!qt_urlRecode(appendTo, password, options, passwordActions))
appendTo += password;
}
@@ -928,14 +916,14 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o
QStringView thePathView(thePath);
if (options & QUrl::RemoveFilename) {
- const int slash = path.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = path.lastIndexOf(u'/');
if (slash == -1)
return;
thePathView = QStringView{path}.left(slash + 1);
}
// check if we need to remove trailing slashes
if (options & QUrl::StripTrailingSlash) {
- while (thePathView.length() > 1 && thePathView.endsWith(QLatin1Char('/')))
+ while (thePathView.size() > 1 && thePathView.endsWith(u'/'))
thePathView.chop(1);
}
@@ -958,7 +946,7 @@ inline void QUrlPrivate::appendQuery(QString &appendTo, QUrl::FormattingOptions
// setXXX functions
-inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetError)
+inline bool QUrlPrivate::setScheme(const QString &value, qsizetype len, bool doSetError)
{
// schemes are strictly RFC-compliant:
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
@@ -974,17 +962,17 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
sectionIsPresent |= Scheme;
// validate it:
- int needsLowercasing = -1;
- const ushort *p = value.utf16();
- for (int i = 0; i < len; ++i) {
- if (p[i] >= 'a' && p[i] <= 'z')
+ qsizetype needsLowercasing = -1;
+ const ushort *p = reinterpret_cast<const ushort *>(value.data());
+ for (qsizetype i = 0; i < len; ++i) {
+ if (isAsciiLower(p[i]))
continue;
- if (p[i] >= 'A' && p[i] <= 'Z') {
+ if (isAsciiUpper(p[i])) {
needsLowercasing = i;
continue;
}
if (i) {
- if (p[i] >= '0' && p[i] <= '9')
+ if (isAsciiDigit(p[i]))
continue;
if (p[i] == '+' || p[i] == '-' || p[i] == '.')
continue;
@@ -1003,9 +991,9 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
if (needsLowercasing != -1) {
// schemes are ASCII only, so we don't need the full Unicode toLower
QChar *schemeData = scheme.data(); // force detaching here
- for (int i = needsLowercasing; i >= 0; --i) {
+ for (qsizetype i = needsLowercasing; i >= 0; --i) {
ushort c = schemeData[i].unicode();
- if (c >= 'A' && c <= 'Z')
+ if (isAsciiUpper(c))
schemeData[i] = QChar(c + 0x20);
}
}
@@ -1023,7 +1011,7 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
return true;
}
-inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode)
+inline void QUrlPrivate::setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode)
{
sectionIsPresent &= ~Authority;
sectionIsPresent |= Host;
@@ -1031,33 +1019,33 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
// we never actually _loop_
while (from != end) {
- int userInfoIndex = auth.indexOf(QLatin1Char('@'), from);
- if (uint(userInfoIndex) < uint(end)) {
+ qsizetype userInfoIndex = auth.indexOf(u'@', from);
+ if (size_t(userInfoIndex) < size_t(end)) {
setUserInfo(auth, from, userInfoIndex);
if (mode == QUrl::StrictMode && !validateComponent(UserInfo, auth, from, userInfoIndex))
break;
from = userInfoIndex + 1;
}
- int colonIndex = auth.lastIndexOf(QLatin1Char(':'), end - 1);
+ qsizetype colonIndex = auth.lastIndexOf(u':', end - 1);
if (colonIndex < from)
colonIndex = -1;
- if (uint(colonIndex) < uint(end)) {
+ if (size_t(colonIndex) < size_t(end)) {
if (auth.at(from).unicode() == '[') {
// check if colonIndex isn't inside the "[...]" part
- int closingBracket = auth.indexOf(QLatin1Char(']'), from);
- if (uint(closingBracket) > uint(colonIndex))
+ qsizetype closingBracket = auth.indexOf(u']', from);
+ if (size_t(closingBracket) > size_t(colonIndex))
colonIndex = -1;
}
}
- if (uint(colonIndex) < uint(end) - 1) {
+ if (size_t(colonIndex) < size_t(end) - 1) {
// found a colon with digits after it
unsigned long x = 0;
- for (int i = colonIndex + 1; i < end; ++i) {
+ for (qsizetype i = colonIndex + 1; i < end; ++i) {
ushort c = auth.at(i).unicode();
- if (c >= '0' && c <= '9') {
+ if (isAsciiDigit(c)) {
x *= 10;
x += c - '0';
} else {
@@ -1074,8 +1062,8 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
}
}
- setHost(auth, from, qMin<uint>(end, colonIndex), mode);
- if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<uint>(end, colonIndex))) {
+ setHost(auth, from, qMin<size_t>(end, colonIndex), mode);
+ if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<size_t>(end, colonIndex))) {
// clear host too
sectionIsPresent &= ~Authority;
break;
@@ -1092,12 +1080,12 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU
port = -1;
}
-inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end)
+inline void QUrlPrivate::setUserInfo(const QString &userInfo, qsizetype from, qsizetype end)
{
- int delimIndex = userInfo.indexOf(QLatin1Char(':'), from);
- setUserName(userInfo, from, qMin<uint>(delimIndex, end));
+ qsizetype delimIndex = userInfo.indexOf(u':', from);
+ setUserName(userInfo, from, qMin<size_t>(delimIndex, end));
- if (uint(delimIndex) >= uint(end)) {
+ if (size_t(delimIndex) >= size_t(end)) {
password.clear();
sectionIsPresent &= ~Password;
} else {
@@ -1105,31 +1093,31 @@ inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end)
}
}
-inline void QUrlPrivate::setUserName(const QString &value, int from, int end)
+inline void QUrlPrivate::setUserName(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= UserName;
userName = recodeFromUser(value, userNameInIsolation, from, end);
}
-inline void QUrlPrivate::setPassword(const QString &value, int from, int end)
+inline void QUrlPrivate::setPassword(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= Password;
password = recodeFromUser(value, passwordInIsolation, from, end);
}
-inline void QUrlPrivate::setPath(const QString &value, int from, int end)
+inline void QUrlPrivate::setPath(const QString &value, qsizetype from, qsizetype end)
{
// sectionIsPresent |= Path; // not used, save some cycles
path = recodeFromUser(value, pathInIsolation, from, end);
}
-inline void QUrlPrivate::setFragment(const QString &value, int from, int end)
+inline void QUrlPrivate::setFragment(const QString &value, qsizetype from, qsizetype end)
{
sectionIsPresent |= Fragment;
fragment = recodeFromUser(value, fragmentInIsolation, from, end);
}
-inline void QUrlPrivate::setQuery(const QString &value, int from, int iend)
+inline void QUrlPrivate::setQuery(const QString &value, qsizetype from, qsizetype iend)
{
sectionIsPresent |= Query;
query = recodeFromUser(value, queryInIsolation, from, iend);
@@ -1179,7 +1167,7 @@ inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions o
// this is either an IPv4Address or a reg-name
// if it is a reg-name, it is already stored in Unicode form
if (options & QUrl::EncodeUnicode && !(options & 0x4000000))
- appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot);
+ appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot, {});
else
appendTo += host;
}
@@ -1199,16 +1187,14 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
const QChar *const origBegin = begin;
if (begin[3].unicode() != '.')
return &begin[3];
- if ((begin[2].unicode() >= 'A' && begin[2].unicode() <= 'F') ||
- (begin[2].unicode() >= 'a' && begin[2].unicode() <= 'f') ||
- (begin[2].unicode() >= '0' && begin[2].unicode() <= '9')) {
+ if (isHexDigit(begin[2].unicode())) {
// this is so unlikely that we'll just go down the slow path
// decode the whole string, skipping the "[vH." and "]" which we already know to be there
host += QStringView(begin, 4);
// uppercase the version, if necessary
if (begin[2].unicode() >= 'a')
- host[host.length() - 2] = QChar{begin[2].unicode() - 0x20};
+ host[host.size() - 2] = QChar{begin[2].unicode() - 0x20};
begin += 4;
--end;
@@ -1220,18 +1206,14 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
}
for ( ; begin != end; ++begin) {
- if (begin->unicode() >= 'A' && begin->unicode() <= 'Z')
- host += *begin;
- else if (begin->unicode() >= 'a' && begin->unicode() <= 'z')
- host += *begin;
- else if (begin->unicode() >= '0' && begin->unicode() <= '9')
+ if (isAsciiLetterOrNumber(begin->unicode()))
host += *begin;
else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != nullptr)
host += *begin;
else
return decoded.isEmpty() ? begin : &origBegin[2];
}
- host += QLatin1Char(']');
+ host += u']';
return nullptr;
}
return &origBegin[2];
@@ -1240,54 +1222,57 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
// ONLY the IPv6 address is parsed here, WITHOUT the brackets
static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode)
{
- // ### Update to use QStringView once QStringView::indexOf and QStringView::lastIndexOf exists
- QString decoded;
+ QStringView decoded(begin, end);
+ QString decodedBuffer;
if (mode == QUrl::TolerantMode) {
// this struct is kept in automatic storage because it's only 4 bytes
const ushort decodeColon[] = { decode(':'), 0 };
- if (qt_urlRecode(decoded, QStringView{begin, end}, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon) == 0)
- decoded = QString(begin, end-begin);
- } else {
- decoded = QString(begin, end-begin);
+ if (qt_urlRecode(decodedBuffer, decoded, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon))
+ decoded = decodedBuffer;
}
- const QLatin1String zoneIdIdentifier("%25");
+ const QStringView zoneIdIdentifier(u"%25");
QIPAddressUtils::IPv6Address address;
- QString zoneId;
-
- const QChar *endBeforeZoneId = decoded.constEnd();
+ QStringView zoneId;
- int zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
+ qsizetype zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
if ((zoneIdPosition != -1) && (decoded.lastIndexOf(zoneIdIdentifier) == zoneIdPosition)) {
zoneId = decoded.mid(zoneIdPosition + zoneIdIdentifier.size());
- endBeforeZoneId = decoded.constBegin() + zoneIdPosition;
+ decoded.truncate(zoneIdPosition);
+ // was there anything after the zone ID separator?
if (zoneId.isEmpty())
return end;
}
- const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), endBeforeZoneId);
+ // did the address become empty after removing the zone ID?
+ // (it might have always been empty)
+ if (decoded.isEmpty())
+ return end;
+
+ const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), decoded.constEnd());
if (ret)
return begin + (ret - decoded.constBegin());
- host.reserve(host.size() + (decoded.constEnd() - decoded.constBegin()));
- host += QLatin1Char('[');
+ host.reserve(host.size() + (end - begin) + 2); // +2 for the brackets
+ host += u'[';
QIPAddressUtils::toString(host, address);
if (!zoneId.isEmpty()) {
host += zoneIdIdentifier;
host += zoneId;
}
- host += QLatin1Char(']');
+ host += u']';
return nullptr;
}
-inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode)
+inline bool
+QUrlPrivate::setHost(const QString &value, qsizetype from, qsizetype iend, QUrl::ParsingMode mode)
{
const QChar *begin = value.constData() + from;
const QChar *end = value.constData() + iend;
- const int len = end - begin;
+ const qsizetype len = end - begin;
host.clear();
sectionIsPresent |= Host;
if (len == 0)
@@ -1339,7 +1324,7 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
// Unicode encoding (some non-ASCII characters case-fold to digits
// when nameprepping is done)
//
- // The qt_ACE_do function below applies nameprepping and the STD3 check.
+ // The qt_ACE_do function below does IDNA normalization and the STD3 check.
// That means a Unicode string may become an IPv4 address, but it cannot
// produce a '[' or a '%'.
@@ -1348,17 +1333,17 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
if (mode == QUrl::TolerantMode && qt_urlRecode(s, QStringView{begin, end}, { }, nullptr)) {
// something was decoded
// anything encoded left?
- int pos = s.indexOf(QChar(0x25)); // '%'
+ qsizetype pos = s.indexOf(QChar(0x25)); // '%'
if (pos != -1) {
setError(InvalidRegNameError, s, pos);
return false;
}
// recurse
- return setHost(s, 0, s.length(), QUrl::StrictMode);
+ return setHost(s, 0, s.size(), QUrl::StrictMode);
}
- s = qt_ACE_do(QStringView(begin, len), NormalizeAce, ForbidLeadingDot);
+ s = qt_ACE_do(value.mid(from, iend - from), NormalizeAce, ForbidLeadingDot, {});
if (s.isEmpty()) {
setError(InvalidRegNameError, value);
return false;
@@ -1388,15 +1373,15 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
clearError();
// find the important delimiters
- int colon = -1;
- int question = -1;
- int hash = -1;
- const int len = url.length();
+ qsizetype colon = -1;
+ qsizetype question = -1;
+ qsizetype hash = -1;
+ const qsizetype len = url.size();
const QChar *const begin = url.constData();
const ushort *const data = reinterpret_cast<const ushort *>(begin);
- for (int i = 0; i < len; ++i) {
- uint uc = data[i];
+ for (qsizetype i = 0; i < len; ++i) {
+ size_t uc = data[i];
if (uc == '#' && hash == -1) {
hash = i;
@@ -1413,7 +1398,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
}
// check if we have a scheme
- int hierStart;
+ qsizetype hierStart;
if (colon != -1 && setScheme(url, colon, /* don't set error */ false)) {
hierStart = colon + 1;
} else {
@@ -1423,12 +1408,12 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
hierStart = 0;
}
- int pathStart;
- int hierEnd = qMin<uint>(qMin<uint>(question, hash), len);
+ qsizetype pathStart;
+ qsizetype hierEnd = qMin<size_t>(qMin<size_t>(question, hash), len);
if (hierEnd - hierStart >= 2 && data[hierStart] == '/' && data[hierStart + 1] == '/') {
// we have an authority, it ends at the first slash after these
- int authorityEnd = hierEnd;
- for (int i = hierStart + 2; i < authorityEnd ; ++i) {
+ qsizetype authorityEnd = hierEnd;
+ for (qsizetype i = hierStart + 2; i < authorityEnd ; ++i) {
if (data[i] == '/') {
authorityEnd = i;
break;
@@ -1453,8 +1438,8 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
path.clear();
}
- if (uint(question) < uint(hash))
- setQuery(url, question + 1, qMin<uint>(hash, len));
+ if (size_t(question) < size_t(hash))
+ setQuery(url, question + 1, qMin<size_t>(hash, len));
if (hash != -1)
setFragment(url, hash + 1, len);
@@ -1470,7 +1455,7 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
if (!validateComponent(Path, url, pathStart, hierEnd))
return;
- if (uint(question) < uint(hash) && !validateComponent(Query, url, question + 1, qMin<uint>(hash, len)))
+ if (size_t(question) < size_t(hash) && !validateComponent(Query, url, question + 1, qMin<size_t>(hash, len)))
return;
if (hash != -1)
validateComponent(Fragment, url, hash + 1, len);
@@ -1484,19 +1469,19 @@ QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const
// magic for shared drive on windows
if (!host.isEmpty()) {
- tmp = QLatin1String("//") + host;
+ tmp = "//"_L1 + host;
#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
if (scheme == webDavScheme())
tmp += webDavSslTag();
#endif
- if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
- tmp += QLatin1Char('/');
+ if (!ourPath.isEmpty() && !ourPath.startsWith(u'/'))
+ tmp += u'/';
tmp += ourPath;
} else {
tmp = ourPath;
#ifdef Q_OS_WIN
// magic for drives on windows
- if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
+ if (ourPath.length() > 2 && ourPath.at(0) == u'/' && ourPath.at(2) == u':')
tmp.remove(0, 1);
#endif
}
@@ -1517,7 +1502,7 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
// path, then return a string consisting of "/" concatenated with
// the reference's path; otherwise,
if (!host.isEmpty() && path.isEmpty())
- return QLatin1Char('/') + relativePath;
+ return u'/' + relativePath;
// Return a string consisting of the reference's path component
// appended to all but the last segment of the base URI's path
@@ -1525,10 +1510,10 @@ inline QString QUrlPrivate::mergePaths(const QString &relativePath) const
// base URI path, or excluding the entire base URI path if it does
// not contain any "/" characters).
QString newPath;
- if (!path.contains(QLatin1Char('/')))
+ if (!path.contains(u'/'))
newPath = relativePath;
else
- newPath = QStringView{path}.left(path.lastIndexOf(QLatin1Char('/')) + 1) + relativePath;
+ newPath = QStringView{path}.left(path.lastIndexOf(u'/') + 1) + relativePath;
return newPath;
}
@@ -1574,7 +1559,7 @@ static void removeDotsFromPath(QString *path)
in += 2;
continue;
} else if (in == end - 2 && in[0].unicode() == '/' && in[1].unicode() == '.') {
- *out++ = QLatin1Char('/');
+ *out++ = u'/';
in += 2;
break;
}
@@ -1615,7 +1600,7 @@ static void removeDotsFromPath(QString *path)
path->truncate(out - path->constData());
}
-inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *position) const
+inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, qsizetype *position) const
{
Q_ASSERT(!source == !position);
if (error) {
@@ -1641,8 +1626,8 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
if (path.isEmpty())
return NoError;
- if (path.at(0) == QLatin1Char('/')) {
- if (hasAuthority() || path.length() == 1 || path.at(1) != QLatin1Char('/'))
+ if (path.at(0) == u'/') {
+ if (hasAuthority() || path.size() == 1 || path.at(1) != u'/')
return NoError;
if (source) {
*source = path;
@@ -1662,7 +1647,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
return NoError;
// check for a path of "text:text/"
- for (int i = 0; i < path.length(); ++i) {
+ for (qsizetype i = 0; i < path.size(); ++i) {
ushort c = path.at(i).unicode();
if (c == '/') {
// found the slash before the colon
@@ -1681,7 +1666,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
}
bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString &input,
- int begin, int end)
+ qsizetype begin, qsizetype end)
{
// What we need to look out for, that the regular parser tolerates:
// - percent signs not followed by two hex digits
@@ -1702,13 +1687,13 @@ bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString
Q_ASSERT(section != Authority && section != Hierarchy && section != FullUrl);
const ushort *const data = reinterpret_cast<const ushort *>(input.constData());
- for (uint i = uint(begin); i < uint(end); ++i) {
+ for (size_t i = size_t(begin); i < size_t(end); ++i) {
uint uc = data[i];
if (uc >= 0x80)
continue;
bool error = false;
- if ((uc == '%' && (uint(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
+ if ((uc == '%' && (size_t(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
|| uc <= 0x20 || strchr(forbidden, uc)) {
// found an error
error = true;
@@ -1726,7 +1711,7 @@ bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString
if (section == UserInfo) {
// is it the user name or the password?
errorCode = InvalidUserNameError;
- for (uint j = uint(begin); j < i; ++j)
+ for (size_t j = size_t(begin); j < i; ++j)
if (data[j] == ':') {
errorCode = InvalidPasswordError;
break;
@@ -1759,7 +1744,7 @@ inline void QUrlPrivate::validate() const
if (!isHostValid)
return;
- if (scheme == QLatin1String("mailto")) {
+ if (scheme == "mailto"_L1) {
if (!host.isEmpty() || port != -1 || !userName.isEmpty() || !password.isEmpty()) {
that->isValid = false;
that->errorInfo.setParams(0, QT_TRANSLATE_NOOP(QUrl, "expected empty host, username,"
@@ -1788,9 +1773,15 @@ inline void QUrlPrivate::validate() const
help avoid missing QUrl::resolved() calls, and other misuses of
QString to QUrl conversions.
- \oldcode
+ For example, if you have code like
+
+ \code
url = filename; // probably not what you want
- \newcode
+ \endcode
+
+ you can rewrite it as
+
+ \code
url = QUrl::fromLocalFile(filename);
url = baseurl.resolved(QUrl(filename));
\endcode
@@ -1800,10 +1791,23 @@ inline void QUrlPrivate::validate() const
/*!
- Constructs a URL by parsing \a url. QUrl will automatically percent encode
+ Constructs a URL by parsing \a url. Note this constructor expects a proper
+ URL or URL-Reference and will not attempt to guess intent. For example, the
+ following declaration:
+
+ \snippet code/src_corelib_io_qurl.cpp constructor-url-reference
+
+ Will construct a valid URL but it may not be what one expects, as the
+ scheme() part of the input is missing. For a string like the above,
+ applications may want to use fromUserInput(). For this constructor or
+ setUrl(), the following is probably what was intended:
+
+ \snippet code/src_corelib_io_qurl.cpp constructor-url
+
+ QUrl will automatically percent encode
all characters that are not allowed in a URL and decode the percent-encoded
sequences that represent an unreserved character (letters, digits, hyphens,
- undercores, dots and tildes). All other characters are left in their
+ underscores, dots and tildes). All other characters are left in their
original forms.
Parses the \a url using the parser mode \a parsingMode. In TolerantMode
@@ -1845,7 +1849,7 @@ QUrl::QUrl() : d(nullptr)
/*!
Constructs a copy of \a other.
*/
-QUrl::QUrl(const QUrl &other) : d(other.d)
+QUrl::QUrl(const QUrl &other) noexcept : d(other.d)
{
if (d)
d->ref.ref();
@@ -1907,7 +1911,7 @@ void QUrl::clear()
Parses \a url and sets this object to that value. QUrl will automatically
percent encode all characters that are not allowed in a URL and decode the
percent-encoded sequences that represent an unreserved character (letters,
- digits, hyphens, undercores, dots and tildes). All other characters are
+ digits, hyphens, underscores, dots and tildes). All other characters are
left in their original forms.
Parses the \a url using the parser mode \a parsingMode. In TolerantMode
@@ -1932,21 +1936,6 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
}
/*!
- \fn void QUrl::setEncodedUrl(const QByteArray &encodedUrl, ParsingMode parsingMode)
- \deprecated
- Constructs a URL by parsing the contents of \a encodedUrl.
-
- \a encodedUrl is assumed to be a URL string in percent encoded
- form, containing only ASCII characters.
-
- The parsing mode \a parsingMode is used for parsing \a encodedUrl.
-
- \obsolete Use setUrl(QString::fromUtf8(encodedUrl), parsingMode)
-
- \sa setUrl()
-*/
-
-/*!
Sets the scheme of the URL to \a scheme. As a scheme can only
contain ASCII characters, no conversion or decoding is done on the
input. It must also start with an ASCII letter.
@@ -1954,7 +1943,7 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
The scheme describes the type (or protocol) of the URL. It's
represented by one or more ASCII characters at the start the URL.
- A scheme is strictly \l {http://www.ietf.org/rfc/rfc3986.txt} {RFC 3986}-compliant:
+ A scheme is strictly \l {RFC 3986}-compliant:
\tt {scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )}
The following example shows a URL where the scheme is "ftp":
@@ -1979,7 +1968,7 @@ void QUrl::setScheme(const QString &scheme)
d->flags &= ~QUrlPrivate::IsLocalFile;
d->scheme.clear();
} else {
- d->setScheme(scheme, scheme.length(), /* do set error */ true);
+ d->setScheme(scheme, scheme.size(), /* do set error */ true);
}
}
@@ -2039,7 +2028,7 @@ void QUrl::setAuthority(const QString &authority, ParsingMode mode)
return;
}
- d->setAuthority(authority, 0, authority.length(), mode);
+ d->setAuthority(authority, 0, authority.size(), mode);
if (authority.isNull()) {
// QUrlPrivate::setAuthority cleared almost everything
// but it leaves the Host bit set
@@ -2110,7 +2099,7 @@ void QUrl::setUserInfo(const QString &userInfo, ParsingMode mode)
return;
}
- d->setUserInfo(trimmed, 0, trimmed.length());
+ d->setUserInfo(trimmed, 0, trimmed.size());
if (userInfo.isNull()) {
// QUrlPrivate::setUserInfo cleared almost everything
// but it leaves the UserName bit set
@@ -2182,7 +2171,7 @@ void QUrl::setUserName(const QString &userName, ParsingMode mode)
mode = TolerantMode;
}
- d->setUserName(data, 0, data.length());
+ d->setUserName(data, 0, data.size());
if (userName.isNull())
d->sectionIsPresent &= ~QUrlPrivate::UserName;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::UserName, userName))
@@ -2215,35 +2204,6 @@ QString QUrl::userName(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedUserName(const QByteArray &userName)
- \deprecated
- \since 4.4
-
- Sets the URL's user name to the percent-encoded \a userName. The \a
- userName is part of the user info element in the authority of the
- URL, as described in setUserInfo().
-
- \obsolete Use setUserName(QString::fromUtf8(userName))
-
- \sa setUserName(), encodedUserName(), setUserInfo()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedUserName() const
- \deprecated
- \since 4.4
-
- Returns the user name of the URL if it is defined; otherwise
- an empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use userName(QUrl::FullyEncoded).toLatin1()
-
- \sa setEncodedUserName()
-*/
-
-/*!
Sets the URL's password to \a password. The \a password is part of
the user info element in the authority of the URL, as described in
setUserInfo().
@@ -2274,7 +2234,7 @@ void QUrl::setPassword(const QString &password, ParsingMode mode)
mode = TolerantMode;
}
- d->setPassword(data, 0, data.length());
+ d->setPassword(data, 0, data.size());
if (password.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Password;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Password, password))
@@ -2307,35 +2267,6 @@ QString QUrl::password(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedPassword(const QByteArray &password)
- \deprecated
- \since 4.4
-
- Sets the URL's password to the percent-encoded \a password. The \a
- password is part of the user info element in the authority of the
- URL, as described in setUserInfo().
-
- \obsolete Use setPassword(QString::fromUtf8(password));
-
- \sa setPassword(), encodedPassword(), setUserInfo()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedPassword() const
- \deprecated
- \since 4.4
-
- Returns the password of the URL if it is defined; otherwise an
- empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use password(QUrl::FullyEncoded).toLatin1()
-
- \sa setEncodedPassword(), toEncoded()
-*/
-
-/*!
Sets the host of the URL to \a host. The host is part of the
authority.
@@ -2365,18 +2296,18 @@ void QUrl::setHost(const QString &host, ParsingMode mode)
mode = TolerantMode;
}
- if (d->setHost(data, 0, data.length(), mode)) {
+ if (d->setHost(data, 0, data.size(), mode)) {
if (host.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Host;
- } else if (!data.startsWith(QLatin1Char('['))) {
+ } else if (!data.startsWith(u'[')) {
// setHost failed, it might be IPv6 or IPvFuture in need of bracketing
Q_ASSERT(d->error);
- data.prepend(QLatin1Char('['));
- data.append(QLatin1Char(']'));
- if (!d->setHost(data, 0, data.length(), mode)) {
+ data.prepend(u'[');
+ data.append(u']');
+ if (!d->setHost(data, 0, data.size(), mode)) {
// failed again
- if (data.contains(QLatin1Char(':'))) {
+ if (data.contains(u':')) {
// source data contains ':', so it's an IPv6 error
d->error->code = QUrlPrivate::InvalidIPv6AddressError;
}
@@ -2410,47 +2341,13 @@ QString QUrl::host(ComponentFormattingOptions options) const
QString result;
if (d) {
d->appendHost(result, options);
- if (result.startsWith(QLatin1Char('[')))
- result = result.mid(1, result.length() - 2);
+ if (result.startsWith(u'['))
+ result = result.mid(1, result.size() - 2);
}
return result;
}
/*!
- \fn void QUrl::setEncodedHost(const QByteArray &host)
- \deprecated
- \since 4.4
-
- Sets the URL's host to the ACE- or percent-encoded \a host. The \a
- host is part of the user info element in the authority of the
- URL, as described in setAuthority().
-
- \obsolete Use setHost(QString::fromUtf8(host)).
-
- \sa setHost(), encodedHost(), setAuthority(), fromAce()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedHost() const
- \deprecated
- \since 4.4
-
- Returns the host part of the URL if it is defined; otherwise
- an empty string is returned.
-
- Note: encodedHost() does not return percent-encoded hostnames. Instead,
- the ACE-encoded (bare ASCII in Punycode encoding) form will be
- returned for any non-ASCII hostname.
-
- This function is equivalent to calling QUrl::toAce() on the return
- value of host().
-
- \obsolete Use host(QUrl::FullyEncoded).toLatin1() or toAce(host()).
-
- \sa setEncodedHost()
-*/
-
-/*!
Sets the port of the URL to \a port. The port is part of the
authority of the URL, as described in setAuthority().
@@ -2524,7 +2421,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
mode = TolerantMode;
}
- d->setPath(data, 0, data.length());
+ d->setPath(data, 0, data.size());
// optimized out, since there is no path delimiter
// if (path.isNull())
@@ -2576,42 +2473,6 @@ QString QUrl::path(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedPath(const QByteArray &path)
- \deprecated
- \since 4.4
-
- Sets the URL's path to the percent-encoded \a path. The path is
- the part of the URL that comes after the authority but before the
- query string.
-
- \image qurl-ftppath.png
-
- For non-hierarchical schemes, the path will be everything
- following the scheme declaration, as in the following example:
-
- \image qurl-mailtopath.png
-
- \obsolete Use setPath(QString::fromUtf8(path)).
-
- \sa setPath(), encodedPath(), setUserInfo()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedPath() const
- \deprecated
- \since 4.4
-
- Returns the path of the URL if it is defined; otherwise an
- empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use path(QUrl::FullyEncoded).toLatin1().
-
- \sa setEncodedPath(), toEncoded()
-*/
-
-/*!
\since 5.2
Returns the name of the file, excluding the directory path.
@@ -2635,7 +2496,7 @@ QString QUrl::path(ComponentFormattingOptions options) const
QString QUrl::fileName(ComponentFormattingOptions options) const
{
const QString ourPath = path(options);
- const int slash = ourPath.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = ourPath.lastIndexOf(u'/');
if (slash == -1)
return ourPath;
return ourPath.mid(slash + 1);
@@ -2696,7 +2557,7 @@ void QUrl::setQuery(const QString &query, ParsingMode mode)
mode = TolerantMode;
}
- d->setQuery(data, 0, data.length());
+ d->setQuery(data, 0, data.size());
if (query.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Query;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Query, query))
@@ -2704,29 +2565,6 @@ void QUrl::setQuery(const QString &query, ParsingMode mode)
}
/*!
- \fn void QUrl::setEncodedQuery(const QByteArray &query)
- \deprecated
-
- Sets the query string of the URL to \a query. The string is
- inserted as-is, and no further encoding is performed when calling
- toEncoded().
-
- This function is useful if you need to pass a query string that
- does not fit into the key-value pattern, or that uses a different
- scheme for encoding special characters than what is suggested by
- QUrl.
-
- Passing a value of QByteArray() to \a query (a null QByteArray) unsets
- the query completely. However, passing a value of QByteArray("")
- will set the query to an empty value, as if the original URL
- had a lone "?".
-
- \obsolete Use setQuery, which has the same null / empty behavior.
-
- \sa encodedQuery(), hasQuery()
-*/
-
-/*!
\overload
\since 5.0
Sets the query string of the URL to \a query.
@@ -2751,248 +2589,6 @@ void QUrl::setQuery(const QUrlQuery &query)
}
/*!
- \fn void QUrl::setQueryItems(const QList<QPair<QString, QString> > &query)
- \deprecated
-
- Sets the query string of the URL to an encoded version of \a
- query. The contents of \a query are converted to a string
- internally, each pair delimited by the character returned by
- \l {QUrlQuery::queryPairDelimiter()}{queryPairDelimiter()}, and the key and value are delimited by
- \l {QUrlQuery::queryValueDelimiter()}{queryValueDelimiter()}
-
- \note This method does not encode spaces (ASCII 0x20) as plus (+) signs,
- like HTML forms do. If you need that kind of encoding, you must encode
- the value yourself and use QUrl::setEncodedQueryItems.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa queryItems(), setEncodedQueryItems()
-*/
-
-/*!
- \fn void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query)
- \deprecated
- \since 4.4
-
- Sets the query string of the URL to the encoded version of \a
- query. The contents of \a query are converted to a string
- internally, each pair delimited by the character returned by
- \l {QUrlQuery::queryPairDelimiter()}{queryPairDelimiter()}, and the key and value are delimited by
- \l {QUrlQuery::queryValueDelimiter()}{queryValueDelimiter()}.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa encodedQueryItems(), setQueryItems()
-*/
-
-/*!
- \fn void QUrl::addQueryItem(const QString &key, const QString &value)
- \deprecated
-
- Inserts the pair \a key = \a value into the query string of the
- URL.
-
- The key-value pair is encoded before it is added to the query. The
- pair is converted into separate strings internally. The \a key and
- \a value is first encoded into UTF-8 and then delimited by the
- character returned by \l {QUrlQuery::queryValueDelimiter()}{queryValueDelimiter()}.
- Each key-value pair is delimited by the character returned by
- \l {QUrlQuery::queryPairDelimiter()}{queryPairDelimiter()}
-
- \note This method does not encode spaces (ASCII 0x20) as plus (+) signs,
- like HTML forms do. If you need that kind of encoding, you must encode
- the value yourself and use QUrl::addEncodedQueryItem.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa addEncodedQueryItem()
-*/
-
-/*!
- \fn void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
- \deprecated
- \since 4.4
-
- Inserts the pair \a key = \a value into the query string of the
- URL.
-
- \obsolete Use QUrlQuery and setQuery().
-
- \sa addQueryItem()
-*/
-
-/*!
- \fn QList<QPair<QString, QString> > QUrl::queryItems() const
- \deprecated
-
- Returns the query string of the URL, as a map of keys and values.
-
- \note This method does not decode spaces plus (+) signs as spaces (ASCII
- 0x20), like HTML forms do. If you need that kind of decoding, you must
- use QUrl::encodedQueryItems and decode the data yourself.
-
- \obsolete Use QUrlQuery.
-
- \sa setQueryItems(), setEncodedQuery()
-*/
-
-/*!
- \fn QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
- \deprecated
- \since 4.4
-
- Returns the query string of the URL, as a map of encoded keys and values.
-
- \obsolete Use QUrlQuery.
-
- \sa setEncodedQueryItems(), setQueryItems(), setEncodedQuery()
-*/
-
-/*!
- \fn bool QUrl::hasQueryItem(const QString &key) const
- \deprecated
-
- Returns \c true if there is a query string pair whose key is equal
- to \a key from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa hasEncodedQueryItem()
-*/
-
-/*!
- \fn bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
- \deprecated
- \since 4.4
-
- Returns \c true if there is a query string pair whose key is equal
- to \a key from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa hasQueryItem()
-*/
-
-/*!
- \fn QString QUrl::queryItemValue(const QString &key) const
- \deprecated
-
- Returns the first query string value whose key is equal to \a key
- from the URL.
-
- \note This method does not decode spaces plus (+) signs as spaces (ASCII
- 0x20), like HTML forms do. If you need that kind of decoding, you must
- use QUrl::encodedQueryItemValue and decode the data yourself.
-
- \obsolete Use QUrlQuery.
-
- \sa allQueryItemValues()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
- \deprecated
- \since 4.4
-
- Returns the first query string value whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa queryItemValue(), allQueryItemValues()
-*/
-
-/*!
- \fn QStringList QUrl::allQueryItemValues(const QString &key) const
- \deprecated
-
- Returns the a list of query string values whose key is equal to
- \a key from the URL.
-
- \note This method does not decode spaces plus (+) signs as spaces (ASCII
- 0x20), like HTML forms do. If you need that kind of decoding, you must
- use QUrl::allEncodedQueryItemValues and decode the data yourself.
-
- \obsolete Use QUrlQuery.
-
- \sa queryItemValue()
-*/
-
-/*!
- \fn QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
- \deprecated
- \since 4.4
-
- Returns the a list of query string values whose key is equal to
- \a key from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa allQueryItemValues(), queryItemValue(), encodedQueryItemValue()
-*/
-
-/*!
- \fn void QUrl::removeQueryItem(const QString &key)
- \deprecated
-
- Removes the first query string pair whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeAllQueryItems()
-*/
-
-/*!
- \fn void QUrl::removeEncodedQueryItem(const QByteArray &key)
- \deprecated
- \since 4.4
-
- Removes the first query string pair whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeQueryItem(), removeAllQueryItems()
-*/
-
-/*!
- \fn void QUrl::removeAllQueryItems(const QString &key)
- \deprecated
-
- Removes all the query string pairs whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeQueryItem()
-*/
-
-/*!
- \fn void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
- \deprecated
- \since 4.4
-
- Removes all the query string pairs whose key is equal to \a key
- from the URL.
-
- \obsolete Use QUrlQuery.
-
- \sa removeQueryItem()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedQuery() const
- \deprecated
-
- Returns the query string of the URL in percent encoded form.
-
- \obsolete Use query(QUrl::FullyEncoded).toLatin1()
-
- \sa setEncodedQuery(), query()
-*/
-
-/*!
Returns the query string of the URL if there's a query string, or an empty
result if not. To determine if the parsed URL contained a query string, use
hasQuery().
@@ -3059,7 +2655,7 @@ void QUrl::setFragment(const QString &fragment, ParsingMode mode)
mode = TolerantMode;
}
- d->setFragment(data, 0, data.length());
+ d->setFragment(data, 0, data.size());
if (fragment.isNull())
d->sectionIsPresent &= ~QUrlPrivate::Fragment;
else if (mode == StrictMode && !d->validateComponent(QUrlPrivate::Fragment, fragment))
@@ -3094,45 +2690,6 @@ QString QUrl::fragment(ComponentFormattingOptions options) const
}
/*!
- \fn void QUrl::setEncodedFragment(const QByteArray &fragment)
- \deprecated
- \since 4.4
-
- Sets the URL's fragment to the percent-encoded \a fragment. The fragment is the
- last part of the URL, represented by a '#' followed by a string of
- characters. It is typically used in HTTP for referring to a
- certain link or point on a page:
-
- \image qurl-fragment.png
-
- The fragment is sometimes also referred to as the URL "reference".
-
- Passing an argument of QByteArray() (a null QByteArray) will unset the fragment.
- Passing an argument of QByteArray("") (an empty but not null QByteArray)
- will set the fragment to an empty string (as if the original URL
- had a lone "#").
-
- \obsolete Use setFragment(), which has the same behavior of null / empty.
-
- \sa setFragment(), encodedFragment()
-*/
-
-/*!
- \fn QByteArray QUrl::encodedFragment() const
- \deprecated
- \since 4.4
-
- Returns the fragment of the URL if it is defined; otherwise an
- empty string is returned. The returned value will have its
- non-ASCII and other control characters percent-encoded, as in
- toEncoded().
-
- \obsolete Use query(QUrl::FullyEncoded).toLatin1().
-
- \sa setEncodedFragment(), toEncoded()
-*/
-
-/*!
\since 4.2
Returns \c true if this URL contains a fragment (i.e., if # was seen on it).
@@ -3197,7 +2754,7 @@ QUrl QUrl::resolved(const QUrl &relative) const
t.d->sectionIsPresent |= QUrlPrivate::Query;
}
} else {
- t.d->path = relative.d->path.startsWith(QLatin1Char('/'))
+ t.d->path = relative.d->path.startsWith(u'/')
? relative.d->path
: d->mergePaths(relative.d->path);
if (relative.d->hasQuery()) {
@@ -3304,26 +2861,26 @@ QString QUrl::toString(FormattingOptions options) const
options |= EncodeReserved;
if (!(options & QUrl::RemoveScheme) && d->hasScheme())
- url += d->scheme + QLatin1Char(':');
+ url += d->scheme + u':';
- bool pathIsAbsolute = d->path.startsWith(QLatin1Char('/'));
+ bool pathIsAbsolute = d->path.startsWith(u'/');
if (!((options & QUrl::RemoveAuthority) == QUrl::RemoveAuthority) && d->hasAuthority()) {
- url += QLatin1String("//");
+ url += "//"_L1;
d->appendAuthority(url, options, QUrlPrivate::FullUrl);
} else if (isLocalFile() && pathIsAbsolute) {
// Comply with the XDG file URI spec, which requires triple slashes.
- url += QLatin1String("//");
+ url += "//"_L1;
}
if (!(options & QUrl::RemovePath))
d->appendPath(url, options, QUrlPrivate::FullUrl);
if (!(options & QUrl::RemoveQuery) && d->hasQuery()) {
- url += QLatin1Char('?');
+ url += u'?';
d->appendQuery(url, options, QUrlPrivate::FullUrl);
}
if (!(options & QUrl::RemoveFragment) && d->hasFragment()) {
- url += QLatin1Char('#');
+ url += u'#';
d->appendFragment(url, options, QUrlPrivate::FullUrl);
}
@@ -3392,7 +2949,7 @@ QUrl QUrl::adjusted(QUrl::FormattingOptions options) const
that.detach();
QString path;
d->appendPath(path, options | FullyEncoded, QUrlPrivate::Path);
- that.d->setPath(path, 0, path.length());
+ that.d->setPath(path, 0, path.size());
}
return that;
}
@@ -3413,19 +2970,23 @@ QByteArray QUrl::toEncoded(FormattingOptions options) const
}
/*!
- \fn QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode parsingMode)
-
Parses \a input and returns the corresponding QUrl. \a input is
assumed to be in encoded form, containing only ASCII characters.
- Parses the URL using \a parsingMode. See setUrl() for more information on
+ Parses the URL using \a mode. See setUrl() for more information on
this parameter. QUrl::DecodedMode is not permitted in this context.
+ \note In Qt versions prior to 6.7, this function took a QByteArray, not
+ QByteArrayView. If you experience compile errors, it's because your code
+ is passing objects that are implicitly convertible to QByteArray, but not
+ QByteArrayView. Wrap the corresponding argument in \c{QByteArray{~~~}} to
+ make the cast explicit. This is backwards-compatible with old Qt versions.
+
\sa toEncoded(), setUrl()
*/
-QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode mode)
+QUrl QUrl::fromEncoded(QByteArrayView input, ParsingMode mode)
{
- return QUrl(QString::fromUtf8(input.constData(), input.size()), mode);
+ return QUrl(QString::fromUtf8(input), mode);
}
/*!
@@ -3460,166 +3021,149 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu
}
/*!
- \internal
- \since 5.0
- Used in the setEncodedXXX compatibility functions. Converts \a ba to
- QString form.
-*/
-QString QUrl::fromEncodedComponent_helper(const QByteArray &ba)
-{
- return qt_urlRecodeByteArray(ba);
-}
-
-/*!
- \fn QByteArray QUrl::toPunycode(const QString &uc)
- \obsolete
- Returns a \a uc in Punycode encoding.
-
- Punycode is a Unicode encoding used for internationalized domain
- names, as defined in RFC3492. If you want to convert a domain name from
- Unicode to its ASCII-compatible representation, use toAce().
-*/
-
-/*!
- \fn QString QUrl::fromPunycode(const QByteArray &pc)
- \obsolete
- Returns the Punycode decoded representation of \a pc.
-
- Punycode is a Unicode encoding used for internationalized domain
- names, as defined in RFC3492. If you want to convert a domain from
- its ASCII-compatible encoding to the Unicode representation, use
- fromAce().
-*/
-
-/*!
- \since 4.2
+ \since 6.3
Returns the Unicode form of the given domain name
\a domain, which is encoded in the ASCII Compatible Encoding (ACE).
+ The output can be customized by passing flags with \a options.
The result of this function is considered equivalent to \a domain.
If the value in \a domain cannot be encoded, it will be converted
to QString and returned.
- The ASCII Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
- and RFC 3492. It is part of the Internationalizing Domain Names in
- Applications (IDNA) specification, which allows for domain names
- (like \c "example.com") to be written using international
- characters.
+ The ASCII-Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
+ and RFC 3492 and updated by the Unicode Technical Standard #46. It is part
+ of the Internationalizing Domain Names in Applications (IDNA) specification,
+ which allows for domain names (like \c "example.com") to be written using
+ non-US-ASCII characters.
*/
-QString QUrl::fromAce(const QByteArray &domain)
+QString QUrl::fromAce(const QByteArray &domain, QUrl::AceProcessingOptions options)
{
- QVarLengthArray<char16_t> buffer;
- buffer.resize(domain.size());
- qt_from_latin1(buffer.data(), domain.data(), domain.size());
- return qt_ACE_do(QStringView{buffer.data(), buffer.size()},
- NormalizeAce, ForbidLeadingDot /*FIXME: make configurable*/);
+ return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce,
+ ForbidLeadingDot /*FIXME: make configurable*/, options);
}
/*!
- \since 4.2
+ \since 6.3
Returns the ASCII Compatible Encoding of the given domain name \a domain.
+ The output can be customized by passing flags with \a options.
The result of this function is considered equivalent to \a domain.
The ASCII-Compatible Encoding (ACE) is defined by RFC 3490, RFC 3491
- and RFC 3492. It is part of the Internationalizing Domain Names in
- Applications (IDNA) specification, which allows for domain names
- (like \c "example.com") to be written using international
- characters.
+ and RFC 3492 and updated by the Unicode Technical Standard #46. It is part
+ of the Internationalizing Domain Names in Applications (IDNA) specification,
+ which allows for domain names (like \c "example.com") to be written using
+ non-US-ASCII characters.
This function returns an empty QByteArray if \a domain is not a valid
hostname. Note, in particular, that IPv6 literals are not valid domain
names.
*/
-QByteArray QUrl::toAce(const QString &domain)
+QByteArray QUrl::toAce(const QString &domain, AceProcessingOptions options)
{
- return qt_ACE_do(domain, ToAceOnly, ForbidLeadingDot /*FIXME: make configurable*/).toLatin1();
+ return qt_ACE_do(domain, ToAceOnly, ForbidLeadingDot /*FIXME: make configurable*/, options)
+ .toLatin1();
}
/*!
\internal
- Returns \c true if this URL is "less than" the given \a url. This
+ \fn bool QUrl::operator<(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if URL \a lhs is "less than" URL \a rhs. This
provides a means of ordering URLs.
*/
-bool QUrl::operator <(const QUrl &url) const
+
+Qt::weak_ordering compareThreeWay(const QUrl &lhs, const QUrl &rhs)
{
- if (!d || !url.d) {
- bool thisIsEmpty = !d || d->isEmpty();
- bool thatIsEmpty = !url.d || url.d->isEmpty();
+ if (!lhs.d || !rhs.d) {
+ bool thisIsEmpty = !lhs.d || lhs.d->isEmpty();
+ bool thatIsEmpty = !rhs.d || rhs.d->isEmpty();
// sort an empty URL first
- return thisIsEmpty && !thatIsEmpty;
+ if (thisIsEmpty) {
+ if (!thatIsEmpty)
+ return Qt::weak_ordering::less;
+ else
+ return Qt::weak_ordering::equivalent;
+ } else {
+ return Qt::weak_ordering::greater;
+ }
}
int cmp;
- cmp = d->scheme.compare(url.d->scheme);
+ cmp = lhs.d->scheme.compare(rhs.d->scheme);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->userName.compare(url.d->userName);
+ cmp = lhs.d->userName.compare(rhs.d->userName);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->password.compare(url.d->password);
+ cmp = lhs.d->password.compare(rhs.d->password);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- cmp = d->host.compare(url.d->host);
+ cmp = lhs.d->host.compare(rhs.d->host);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->port != url.d->port)
- return d->port < url.d->port;
+ if (lhs.d->port != rhs.d->port)
+ return Qt::compareThreeWay(lhs.d->port, rhs.d->port);
- cmp = d->path.compare(url.d->path);
+ cmp = lhs.d->path.compare(rhs.d->path);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->hasQuery() != url.d->hasQuery())
- return url.d->hasQuery();
+ if (lhs.d->hasQuery() != rhs.d->hasQuery())
+ return rhs.d->hasQuery() ? Qt::weak_ordering::less : Qt::weak_ordering::greater;
- cmp = d->query.compare(url.d->query);
+ cmp = lhs.d->query.compare(rhs.d->query);
if (cmp != 0)
- return cmp < 0;
+ return Qt::compareThreeWay(cmp, 0);
- if (d->hasFragment() != url.d->hasFragment())
- return url.d->hasFragment();
+ if (lhs.d->hasFragment() != rhs.d->hasFragment())
+ return rhs.d->hasFragment() ? Qt::weak_ordering::less : Qt::weak_ordering::greater;
- cmp = d->fragment.compare(url.d->fragment);
- return cmp < 0;
+ cmp = lhs.d->fragment.compare(rhs.d->fragment);
+ return Qt::compareThreeWay(cmp, 0);
}
/*!
- Returns \c true if this URL and the given \a url are equal;
+ \fn bool QUrl::operator==(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if \a lhs and \a rhs URLs are equivalent;
otherwise returns \c false.
+
+ \sa matches()
*/
-bool QUrl::operator ==(const QUrl &url) const
+
+bool comparesEqual(const QUrl &lhs, const QUrl &rhs)
{
- if (!d && !url.d)
+ if (!lhs.d && !rhs.d)
return true;
- if (!d)
- return url.d->isEmpty();
- if (!url.d)
- return d->isEmpty();
+ if (!lhs.d)
+ return rhs.d->isEmpty();
+ if (!rhs.d)
+ return lhs.d->isEmpty();
// First, compare which sections are present, since it speeds up the
// processing considerably. We just have to ignore the host-is-present flag
// for local files (the "file" protocol), due to the requirements of the
// XDG file URI specification.
int mask = QUrlPrivate::FullUrl;
- if (isLocalFile())
+ if (lhs.isLocalFile())
mask &= ~QUrlPrivate::Host;
- return (d->sectionIsPresent & mask) == (url.d->sectionIsPresent & mask) &&
- d->scheme == url.d->scheme &&
- d->userName == url.d->userName &&
- d->password == url.d->password &&
- d->host == url.d->host &&
- d->port == url.d->port &&
- d->path == url.d->path &&
- d->query == url.d->query &&
- d->fragment == url.d->fragment;
+ return (lhs.d->sectionIsPresent & mask) == (rhs.d->sectionIsPresent & mask) &&
+ lhs.d->scheme == rhs.d->scheme &&
+ lhs.d->userName == rhs.d->userName &&
+ lhs.d->password == rhs.d->password &&
+ lhs.d->host == rhs.d->host &&
+ lhs.d->port == rhs.d->port &&
+ lhs.d->path == rhs.d->path &&
+ lhs.d->query == rhs.d->query &&
+ lhs.d->fragment == rhs.d->fragment;
}
/*!
@@ -3699,18 +3243,18 @@ bool QUrl::matches(const QUrl &url, FormattingOptions options) const
}
/*!
- Returns \c true if this URL and the given \a url are not equal;
+ \fn bool QUrl::operator !=(const QUrl &lhs, const QUrl &rhs)
+
+ Returns \c true if \a lhs and \a rhs URLs are not equal;
otherwise returns \c false.
+
+ \sa matches()
*/
-bool QUrl::operator !=(const QUrl &url) const
-{
- return !(*this == url);
-}
/*!
Assigns the specified \a url to this object.
*/
-QUrl &QUrl::operator =(const QUrl &url)
+QUrl &QUrl::operator =(const QUrl &url) noexcept
{
if (!d) {
if (url.d) {
@@ -3769,6 +3313,25 @@ bool QUrl::isDetached() const
return !d || d->ref.loadRelaxed() == 1;
}
+static QString fromNativeSeparators(const QString &pathName)
+{
+#if defined(Q_OS_WIN)
+ QString result(pathName);
+ const QChar nativeSeparator = u'\\';
+ auto i = result.indexOf(nativeSeparator);
+ if (i != -1) {
+ QChar * const data = result.data();
+ const auto length = result.length();
+ for (; i < length; ++i) {
+ if (data[i] == nativeSeparator)
+ data[i] = u'/';
+ }
+ }
+ return result;
+#else
+ return pathName;
+#endif
+}
/*!
Returns a QUrl representation of \a localFile, interpreted as a local
@@ -3807,26 +3370,34 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
if (localFile.isEmpty())
return url;
QString scheme = fileScheme();
- QString deslashified = QDir::fromNativeSeparators(localFile);
+ QString deslashified = fromNativeSeparators(localFile);
// magic for drives on windows
- if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) {
- deslashified.prepend(QLatin1Char('/'));
- } else if (deslashified.startsWith(QLatin1String("//"))) {
+ if (deslashified.size() > 1 && deslashified.at(1) == u':' && deslashified.at(0) != u'/') {
+ deslashified.prepend(u'/');
+ } else if (deslashified.startsWith("//"_L1)) {
// magic for shared drive on windows
- int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
+ qsizetype indexOfPath = deslashified.indexOf(u'/', 2);
QStringView hostSpec = QStringView{deslashified}.mid(2, indexOfPath - 2);
// Check for Windows-specific WebDAV specification: "//host@SSL/path".
if (hostSpec.endsWith(webDavSslTag(), Qt::CaseInsensitive)) {
hostSpec.truncate(hostSpec.size() - 4);
scheme = webDavScheme();
}
- url.setHost(hostSpec.toString());
- if (indexOfPath > 2)
- deslashified = deslashified.right(deslashified.length() - indexOfPath);
- else
+ // hosts can't be IPv6 addresses without [], so we can use QUrlPrivate::setHost
+ url.detach();
+ if (!url.d->setHost(hostSpec.toString(), 0, hostSpec.size(), StrictMode)) {
+ if (url.d->error->code != QUrlPrivate::InvalidRegNameError)
+ return url;
+
+ // Path hostname is not a valid URL host, so set it entirely in the path
+ // (by leaving deslashified unchanged)
+ } else if (indexOfPath > 2) {
+ deslashified = deslashified.right(deslashified.size() - indexOfPath);
+ } else {
deslashified.clear();
+ }
}
url.setScheme(scheme);
@@ -3887,16 +3458,16 @@ bool QUrl::isParentOf(const QUrl &childUrl) const
if (!d)
return ((childUrl.scheme().isEmpty())
&& (childUrl.authority().isEmpty())
- && childPath.length() > 0 && childPath.at(0) == QLatin1Char('/'));
+ && childPath.size() > 0 && childPath.at(0) == u'/');
QString ourPath = path();
return ((childUrl.scheme().isEmpty() || d->scheme == childUrl.scheme())
&& (childUrl.authority().isEmpty() || authority() == childUrl.authority())
&& childPath.startsWith(ourPath)
- && ((ourPath.endsWith(QLatin1Char('/')) && childPath.length() > ourPath.length())
- || (!ourPath.endsWith(QLatin1Char('/'))
- && childPath.length() > ourPath.length() && childPath.at(ourPath.length()) == QLatin1Char('/'))));
+ && ((ourPath.endsWith(u'/') && childPath.size() > ourPath.size())
+ || (!ourPath.endsWith(u'/') && childPath.size() > ourPath.size()
+ && childPath.at(ourPath.size()) == u'/')));
}
@@ -3942,34 +3513,31 @@ QDebug operator<<(QDebug d, const QUrl &url)
}
#endif
-static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, int errorPosition)
+static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
{
- QChar c = uint(errorPosition) < uint(errorSource.length()) ?
+ QChar c = size_t(errorPosition) < size_t(errorSource.size()) ?
errorSource.at(errorPosition) : QChar(QChar::Null);
switch (errorCode) {
case QUrlPrivate::NoError:
- Q_ASSERT_X(false, "QUrl::errorString",
- "Impossible: QUrl::errorString should have treated this condition");
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString()); // QUrl::errorString should have treated this condition
case QUrlPrivate::InvalidSchemeError: {
- auto msg = QLatin1String("Invalid scheme (character '%1' not permitted)");
+ auto msg = "Invalid scheme (character '%1' not permitted)"_L1;
return msg.arg(c);
}
case QUrlPrivate::InvalidUserNameError:
- return QLatin1String("Invalid user name (character '%1' not permitted)")
+ return "Invalid user name (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidPasswordError:
- return QLatin1String("Invalid password (character '%1' not permitted)")
+ return "Invalid password (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidRegNameError:
- if (errorPosition != -1)
- return QLatin1String("Invalid hostname (character '%1' not permitted)")
+ if (errorPosition >= 0)
+ return "Invalid hostname (character '%1' not permitted)"_L1
.arg(c);
else
return QStringLiteral("Invalid hostname (contains invalid characters)");
@@ -3978,9 +3546,9 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
case QUrlPrivate::InvalidIPv6AddressError:
return QStringLiteral("Invalid IPv6 address");
case QUrlPrivate::InvalidCharacterInIPv6Error:
- return QLatin1String("Invalid IPv6 address (character '%1' not permitted)").arg(c);
+ return "Invalid IPv6 address (character '%1' not permitted)"_L1.arg(c);
case QUrlPrivate::InvalidIPvFutureError:
- return QLatin1String("Invalid IPvFuture address (character '%1' not permitted)").arg(c);
+ return "Invalid IPvFuture address (character '%1' not permitted)"_L1.arg(c);
case QUrlPrivate::HostMissingEndBracket:
return QStringLiteral("Expected ']' to match '[' in hostname");
@@ -3990,15 +3558,15 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Port field was empty");
case QUrlPrivate::InvalidPathError:
- return QLatin1String("Invalid path (character '%1' not permitted)")
+ return "Invalid path (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidQueryError:
- return QLatin1String("Invalid query (character '%1' not permitted)")
+ return "Invalid query (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::InvalidFragmentError:
- return QLatin1String("Invalid fragment (character '%1' not permitted)")
+ return "Invalid fragment (character '%1' not permitted)"_L1
.arg(c);
case QUrlPrivate::AuthorityPresentAndPathIsRelative:
@@ -4009,20 +3577,14 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Relative URL's path component contains ':' before any '/'");
}
- Q_ASSERT_X(false, "QUrl::errorString", "Cannot happen, unknown error");
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString());
}
static inline void appendComponentIfPresent(QString &msg, bool present, const char *componentName,
const QString &component)
{
- if (present) {
- msg += QLatin1String(componentName);
- msg += QLatin1Char('"');
- msg += component;
- msg += QLatin1String("\",");
- }
+ if (present)
+ msg += QLatin1StringView(componentName) % u'"' % component % "\","_L1;
}
/*!
@@ -4045,15 +3607,15 @@ QString QUrl::errorString() const
return msg;
QString errorSource;
- int errorPosition = 0;
+ qsizetype errorPosition = 0;
QUrlPrivate::ErrorCode errorCode = d->validityError(&errorSource, &errorPosition);
if (errorCode == QUrlPrivate::NoError)
return msg;
msg += errorMessage(errorCode, errorSource, errorPosition);
- msg += QLatin1String("; source was \"");
+ msg += "; source was \""_L1;
msg += errorSource;
- msg += QLatin1String("\";");
+ msg += "\";"_L1;
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::Scheme,
" scheme = ", d->scheme);
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::UserInfo,
@@ -4068,7 +3630,7 @@ QString QUrl::errorString() const
" query = ", d->query);
appendComponentIfPresent(msg, d->sectionIsPresent & QUrlPrivate::Fragment,
" fragment = ", d->fragment);
- if (msg.endsWith(QLatin1Char(',')))
+ if (msg.endsWith(u','))
msg.chop(1);
return msg;
}
@@ -4139,8 +3701,8 @@ static QUrl adjustFtpPath(QUrl url)
{
if (url.scheme() == ftpScheme()) {
QString path = url.path(QUrl::PrettyDecoded);
- if (path.startsWith(QLatin1String("//")))
- url.setPath(QLatin1String("/%2F") + QStringView{path}.mid(2), QUrl::TolerantMode);
+ if (path.startsWith("//"_L1))
+ url.setPath("/%2F"_L1 + QStringView{path}.mid(2), QUrl::TolerantMode);
}
return url;
}
@@ -4155,65 +3717,12 @@ static bool isIp6(const QString &text)
Returns a valid URL from a user supplied \a userInput string if one can be
deduced. In the case that is not possible, an invalid QUrl() is returned.
- This overload takes a \a workingDirectory path, in order to be able to
- handle relative paths. This is especially useful when handling command
- line arguments.
- If \a workingDirectory is empty, no handling of relative paths will be done,
- so this method will behave like its one argument overload.
-
- By default, an input string that looks like a relative path will only be treated
- as such if the file actually exists in the given working directory.
-
- If the application can handle files that don't exist yet, it should pass the
- flag AssumeLocalFile in \a options.
-
- \since 5.4
-*/
-QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
- UserInputResolutionOptions options)
-{
- QString trimmedString = userInput.trimmed();
-
- if (trimmedString.isEmpty())
- return QUrl();
-
-
- // Check for IPv6 addresses, since a path starting with ":" is absolute (a resource)
- // and IPv6 addresses can start with "c:" too
- if (isIp6(trimmedString)) {
- QUrl url;
- url.setHost(trimmedString);
- url.setScheme(QStringLiteral("http"));
- return url;
- }
-
- const QFileInfo fileInfo(QDir(workingDirectory), userInput);
- if (fileInfo.exists()) {
- return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
- }
-
- QUrl url = QUrl(userInput, QUrl::TolerantMode);
- // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
- if ((options & AssumeLocalFile) && url.isRelative() && !QDir::isAbsolutePath(userInput)) {
- return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
- }
-
- return fromUserInput(trimmedString);
-}
-
-/*!
- Returns a valid URL from a user supplied \a userInput string if one can be
- deducted. In the case that is not possible, an invalid QUrl() is returned.
-
- \since 4.6
-
- Most applications that can browse the web, allow the user to input a URL
- in the form of a plain string. This string can be manually typed into
- a location bar, obtained from the clipboard, or passed in via command
- line arguments.
+ This allows the user to input a URL or a local file path in the form of a plain
+ string. This string can be manually typed into a location bar, obtained from
+ the clipboard, or passed in via command line arguments.
When the string is not already a valid URL, a best guess is performed,
- making various web related assumptions.
+ making various assumptions.
In the case the string corresponds to a valid file path on the system,
a file:// URL is constructed, using QUrl::fromLocalFile().
@@ -4231,11 +3740,27 @@ QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirecto
\li hostname becomes http://hostname
\li /home/user/test.html becomes file:///home/user/test.html
\endlist
+
+ In order to be able to handle relative paths, this method takes an optional
+ \a workingDirectory path. This is especially useful when handling command
+ line arguments.
+ If \a workingDirectory is empty, no handling of relative paths will be done.
+
+ By default, an input string that looks like a relative path will only be treated
+ as such if the file actually exists in the given working directory.
+ If the application can handle files that don't exist yet, it should pass the
+ flag AssumeLocalFile in \a options.
+
+ \since 5.4
*/
-QUrl QUrl::fromUserInput(const QString &userInput)
+QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
+ UserInputResolutionOptions options)
{
QString trimmedString = userInput.trimmed();
+ if (trimmedString.isEmpty())
+ return QUrl();
+
// Check for IPv6 addresses, since a path starting with ":" is absolute (a resource)
// and IPv6 addresses can start with "c:" too
if (isIp6(trimmedString)) {
@@ -4245,25 +3770,36 @@ QUrl QUrl::fromUserInput(const QString &userInput)
return url;
}
- // Check first for files, since on Windows drive letters can be interpretted as schemes
+ const QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
+
+ // Check for a relative path
+ if (!workingDirectory.isEmpty()) {
+ const QFileInfo fileInfo(QDir(workingDirectory), userInput);
+ if (fileInfo.exists())
+ return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+
+ // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
+ if ((options & AssumeLocalFile) && url.isRelative() && !QDir::isAbsolutePath(userInput))
+ return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ }
+
+ // Check first for files, since on Windows drive letters can be interpreted as schemes
if (QDir::isAbsolutePath(trimmedString))
return QUrl::fromLocalFile(trimmedString);
- QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
- QUrl urlPrepended = QUrl(QLatin1String("http://") + trimmedString, QUrl::TolerantMode);
+ QUrl urlPrepended = QUrl("http://"_L1 + trimmedString, QUrl::TolerantMode);
// Check the most common case of a valid url with a scheme
// We check if the port would be valid by adding the scheme to handle the case host:port
- // where the host would be interpretted as the scheme
+ // where the host would be interpreted as the scheme
if (url.isValid()
&& !url.scheme().isEmpty()
&& urlPrepended.port() == -1)
return adjustFtpPath(url);
// Else, try the prepended one and adjust the scheme from the host name
- if (urlPrepended.isValid() && (!urlPrepended.host().isEmpty() || !urlPrepended.path().isEmpty()))
- {
- int dotIndex = trimmedString.indexOf(QLatin1Char('.'));
+ if (urlPrepended.isValid() && (!urlPrepended.host().isEmpty() || !urlPrepended.path().isEmpty())) {
+ qsizetype dotIndex = trimmedString.indexOf(u'.');
const QStringView hostscheme = QStringView{trimmedString}.left(dotIndex);
if (hostscheme.compare(ftpScheme(), Qt::CaseInsensitive) == 0)
urlPrepended.setScheme(ftpScheme());
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 0425502a52..d6779cf485 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -1,51 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QURL_H
#define QURL_H
#include <QtCore/qbytearray.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qobjectdefs.h>
#include <QtCore/qstring.h>
#include <QtCore/qlist.h>
-#include <QtCore/qpair.h>
#include <QtCore/qglobal.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
@@ -64,54 +28,59 @@ template <typename E1, typename E2>
class QUrlTwoFlags
{
int i;
- typedef int QUrlTwoFlags:: *Zero;
public:
- Q_DECL_CONSTEXPR inline QUrlTwoFlags(E1 f) : i(f) {}
- Q_DECL_CONSTEXPR inline QUrlTwoFlags(E2 f) : i(f) {}
- Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlag f) : i(f) {}
- Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlags<E1> f) : i(f.operator typename QFlags<E1>::Int()) {}
- Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlags<E2> f) : i(f.operator typename QFlags<E2>::Int()) {}
- Q_DECL_CONSTEXPR inline QUrlTwoFlags(Zero = 0) : i(0) {}
+ constexpr inline QUrlTwoFlags() : i(0) {}
+ constexpr inline QUrlTwoFlags(E1 f) : i(f) {}
+ constexpr inline QUrlTwoFlags(E2 f) : i(f) {}
+ constexpr inline QUrlTwoFlags(QFlag f) : i(f) {}
+ constexpr inline QUrlTwoFlags(QFlags<E1> f) : i(f.operator typename QFlags<E1>::Int()) {}
+ constexpr inline QUrlTwoFlags(QFlags<E2> f) : i(f.operator typename QFlags<E2>::Int()) {}
inline QUrlTwoFlags &operator&=(int mask) { i &= mask; return *this; }
inline QUrlTwoFlags &operator&=(uint mask) { i &= mask; return *this; }
+ inline QUrlTwoFlags &operator&=(QFlags<E1> mask) { i &= mask.toInt(); return *this; }
+ inline QUrlTwoFlags &operator&=(QFlags<E2> mask) { i &= mask.toInt(); return *this; }
inline QUrlTwoFlags &operator|=(QUrlTwoFlags f) { i |= f.i; return *this; }
inline QUrlTwoFlags &operator|=(E1 f) { i |= f; return *this; }
inline QUrlTwoFlags &operator|=(E2 f) { i |= f; return *this; }
+ inline QUrlTwoFlags &operator|=(QFlags<E1> mask) { i |= mask.toInt(); return *this; }
+ inline QUrlTwoFlags &operator|=(QFlags<E2> mask) { i |= mask.toInt(); return *this; }
inline QUrlTwoFlags &operator^=(QUrlTwoFlags f) { i ^= f.i; return *this; }
inline QUrlTwoFlags &operator^=(E1 f) { i ^= f; return *this; }
inline QUrlTwoFlags &operator^=(E2 f) { i ^= f; return *this; }
+ inline QUrlTwoFlags &operator^=(QFlags<E1> mask) { i ^= mask.toInt(); return *this; }
+ inline QUrlTwoFlags &operator^=(QFlags<E2> mask) { i ^= mask.toInt(); return *this; }
- Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return QFlag(i); }
- Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return QFlag(i); }
- Q_DECL_CONSTEXPR inline operator int() const { return i; }
- Q_DECL_CONSTEXPR inline bool operator!() const { return !i; }
+ constexpr inline operator QFlags<E1>() const { return QFlag(i); }
+ constexpr inline operator QFlags<E2>() const { return QFlag(i); }
+ constexpr inline operator int() const { return i; }
+ constexpr inline bool operator!() const { return !i; }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(QUrlTwoFlags f) const
+ constexpr inline QUrlTwoFlags operator|(QUrlTwoFlags f) const
{ return QUrlTwoFlags(QFlag(i | f.i)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E1 f) const
+ constexpr inline QUrlTwoFlags operator|(E1 f) const
{ return QUrlTwoFlags(QFlag(i | f)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E2 f) const
+ constexpr inline QUrlTwoFlags operator|(E2 f) const
{ return QUrlTwoFlags(QFlag(i | f)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(QUrlTwoFlags f) const
+ constexpr inline QUrlTwoFlags operator^(QUrlTwoFlags f) const
{ return QUrlTwoFlags(QFlag(i ^ f.i)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E1 f) const
+ constexpr inline QUrlTwoFlags operator^(E1 f) const
{ return QUrlTwoFlags(QFlag(i ^ f)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E2 f) const
+ constexpr inline QUrlTwoFlags operator^(E2 f) const
{ return QUrlTwoFlags(QFlag(i ^ f)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(int mask) const
+ constexpr inline QUrlTwoFlags operator&(int mask) const
{ return QUrlTwoFlags(QFlag(i & mask)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(uint mask) const
+ constexpr inline QUrlTwoFlags operator&(uint mask) const
{ return QUrlTwoFlags(QFlag(i & mask)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E1 f) const
+ constexpr inline QUrlTwoFlags operator&(E1 f) const
{ return QUrlTwoFlags(QFlag(i & f)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E2 f) const
+ constexpr inline QUrlTwoFlags operator&(E2 f) const
{ return QUrlTwoFlags(QFlag(i & f)); }
- Q_DECL_CONSTEXPR inline QUrlTwoFlags operator~() const
+ constexpr inline QUrlTwoFlags operator~() const
{ return QUrlTwoFlags(QFlag(~i)); }
- Q_DECL_CONSTEXPR inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
- Q_DECL_CONSTEXPR inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
+ constexpr inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
+ constexpr inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
};
template<typename E1, typename E2>
@@ -131,7 +100,7 @@ public:
};
// encoding / toString values
- enum UrlFormattingOption {
+ enum UrlFormattingOption : unsigned int {
None = 0x0,
RemoveScheme = 0x1,
RemovePassword = 0x2,
@@ -148,7 +117,7 @@ public:
NormalizePathSegments = 0x1000
};
- enum ComponentFormattingOption {
+ enum ComponentFormattingOption : unsigned int {
PrettyDecoded = 0x000000,
EncodeSpaces = 0x100000,
EncodeUnicode = 0x200000,
@@ -164,7 +133,7 @@ public:
#ifdef Q_QDOC
private:
// We need to let qdoc think that FormattingOptions is a normal QFlags, but
- // it needs to be a QUrlTwoFlags for compiling default arguments of somme functions.
+ // it needs to be a QUrlTwoFlags for compiling default arguments of some functions.
template<typename T> struct QFlags : QUrlTwoFlags<T, ComponentFormattingOption>
{ using QUrlTwoFlags<T, ComponentFormattingOption>::QUrlTwoFlags; };
public:
@@ -174,8 +143,8 @@ public:
#endif
QUrl();
- QUrl(const QUrl &copy);
- QUrl &operator =(const QUrl &copy);
+ QUrl(const QUrl &copy) noexcept;
+ QUrl &operator =(const QUrl &copy) noexcept;
#ifdef QT_NO_URL_CAST_FROM_STRING
explicit QUrl(const QString &url, ParsingMode mode = TolerantMode);
#else
@@ -184,20 +153,22 @@ public:
#endif
QUrl(QUrl &&other) noexcept : d(other.d)
{ other.d = nullptr; }
- inline QUrl &operator=(QUrl &&other) noexcept
- { qSwap(d, other.d); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QUrl)
~QUrl();
- inline void swap(QUrl &other) noexcept { qSwap(d, other.d); }
+ void swap(QUrl &other) noexcept { qt_ptr_swap(d, other.d); }
void setUrl(const QString &url, ParsingMode mode = TolerantMode);
QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toDisplayString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
- Q_REQUIRED_RESULT QUrl adjusted(FormattingOptions options) const;
+ [[nodiscard]] QUrl adjusted(FormattingOptions options) const;
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
+#if QT_CORE_REMOVED_SINCE(6, 7)
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
+#endif
+ static QUrl fromEncoded(QByteArrayView input, ParsingMode mode = TolerantMode);
enum UserInputResolutionOption {
DefaultResolution,
@@ -205,9 +176,7 @@ public:
};
Q_DECLARE_FLAGS(UserInputResolutionOptions, UserInputResolutionOption)
- static QUrl fromUserInput(const QString &userInput);
- // ### Qt6 merge with fromUserInput(QString), by adding = QString()
- static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory,
+ static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory = QString(),
UserInputResolutionOptions options = DefaultResolution);
bool isValid() const;
@@ -250,7 +219,7 @@ public:
QString fragment(ComponentFormattingOptions options = PrettyDecoded) const;
void setFragment(const QString &fragment, ParsingMode mode = TolerantMode);
- Q_REQUIRED_RESULT QUrl resolved(const QUrl &relative) const;
+ [[nodiscard]] QUrl resolved(const QUrl &relative) const;
bool isRelative() const;
bool isParentOf(const QUrl &url) const;
@@ -262,9 +231,11 @@ public:
void detach();
bool isDetached() const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator <(const QUrl &url) const;
bool operator ==(const QUrl &url) const;
bool operator !=(const QUrl &url) const;
+#endif
bool matches(const QUrl &url, FormattingOptions options) const;
@@ -279,78 +250,19 @@ public:
NSURL *toNSURL() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
-#if QT_DEPRECATED_SINCE(5,0)
- QT_DEPRECATED static QString fromPunycode(const QByteArray &punycode)
- { return fromAce(punycode); }
- QT_DEPRECATED static QByteArray toPunycode(const QString &string)
- { return toAce(string); }
-
- QT_DEPRECATED inline void setQueryItems(const QList<QPair<QString, QString> > &qry);
- QT_DEPRECATED inline void addQueryItem(const QString &key, const QString &value);
- QT_DEPRECATED inline QList<QPair<QString, QString> > queryItems() const;
- QT_DEPRECATED inline bool hasQueryItem(const QString &key) const;
- QT_DEPRECATED inline QString queryItemValue(const QString &key) const;
- QT_DEPRECATED inline QStringList allQueryItemValues(const QString &key) const;
- QT_DEPRECATED inline void removeQueryItem(const QString &key);
- QT_DEPRECATED inline void removeAllQueryItems(const QString &key);
-
- QT_DEPRECATED inline void setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query);
- QT_DEPRECATED inline void addEncodedQueryItem(const QByteArray &key, const QByteArray &value);
- QT_DEPRECATED inline QList<QPair<QByteArray, QByteArray> > encodedQueryItems() const;
- QT_DEPRECATED inline bool hasEncodedQueryItem(const QByteArray &key) const;
- QT_DEPRECATED inline QByteArray encodedQueryItemValue(const QByteArray &key) const;
- QT_DEPRECATED inline QList<QByteArray> allEncodedQueryItemValues(const QByteArray &key) const;
- QT_DEPRECATED inline void removeEncodedQueryItem(const QByteArray &key);
- QT_DEPRECATED inline void removeAllEncodedQueryItems(const QByteArray &key);
-
- QT_DEPRECATED void setEncodedUrl(const QByteArray &u, ParsingMode mode = TolerantMode)
- { setUrl(fromEncodedComponent_helper(u), mode); }
-
- QT_DEPRECATED QByteArray encodedUserName() const
- { return userName(FullyEncoded).toLatin1(); }
- QT_DEPRECATED void setEncodedUserName(const QByteArray &value)
- { setUserName(fromEncodedComponent_helper(value)); }
-
- QT_DEPRECATED QByteArray encodedPassword() const
- { return password(FullyEncoded).toLatin1(); }
- QT_DEPRECATED void setEncodedPassword(const QByteArray &value)
- { setPassword(fromEncodedComponent_helper(value)); }
-
- QT_DEPRECATED QByteArray encodedHost() const
- { return host(FullyEncoded).toLatin1(); }
- QT_DEPRECATED void setEncodedHost(const QByteArray &value)
- { setHost(fromEncodedComponent_helper(value)); }
-
- QT_DEPRECATED QByteArray encodedPath() const
- { return path(FullyEncoded).toLatin1(); }
- QT_DEPRECATED void setEncodedPath(const QByteArray &value)
- { setPath(fromEncodedComponent_helper(value)); }
-
- QT_DEPRECATED QByteArray encodedQuery() const
- { return toLatin1_helper(query(FullyEncoded)); }
- QT_DEPRECATED void setEncodedQuery(const QByteArray &value)
- { setQuery(fromEncodedComponent_helper(value)); }
-
- QT_DEPRECATED QByteArray encodedFragment() const
- { return toLatin1_helper(fragment(FullyEncoded)); }
- QT_DEPRECATED void setEncodedFragment(const QByteArray &value)
- { setFragment(fromEncodedComponent_helper(value)); }
-
-private:
- // helper function for the encodedQuery and encodedFragment functions
- static QByteArray toLatin1_helper(const QString &string)
- {
- if (string.isEmpty())
- return string.isNull() ? QByteArray() : QByteArray("");
- return string.toLatin1();
- }
-#endif
-private:
- static QString fromEncodedComponent_helper(const QByteArray &ba);
+ enum AceProcessingOption : unsigned int {
+ IgnoreIDNWhitelist = 0x1,
+ AceTransitionalProcessing = 0x2,
+ };
+ Q_DECLARE_FLAGS(AceProcessingOptions, AceProcessingOption)
-public:
+#if QT_CORE_REMOVED_SINCE(6, 3)
static QString fromAce(const QByteArray &);
static QByteArray toAce(const QString &);
+#endif
+ static QString fromAce(const QByteArray &domain, AceProcessingOptions options = {});
+ static QByteArray toAce(const QString &domain, AceProcessingOptions options = {});
+
static QStringList idnWhitelist();
static QStringList toStringList(const QList<QUrl> &uris, FormattingOptions options = FormattingOptions(PrettyDecoded));
static QList<QUrl> fromStringList(const QStringList &uris, ParsingMode mode = TolerantMode);
@@ -359,6 +271,11 @@ public:
friend Q_CORE_EXPORT size_t qHash(const QUrl &url, size_t seed) noexcept;
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QUrl &lhs, const QUrl &rhs);
+ friend Q_CORE_EXPORT Qt::weak_ordering
+ compareThreeWay(const QUrl &lhs, const QUrl &rhs);
+ Q_DECLARE_WEAKLY_ORDERED(QUrl)
+
QUrlPrivate *d;
friend class QUrlQuery;
@@ -370,32 +287,33 @@ public:
Q_DECLARE_SHARED(QUrl)
Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::ComponentFormattingOptions)
//Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::FormattingOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::AceProcessingOptions)
#ifndef Q_QDOC
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::UrlFormattingOption f2)
+constexpr inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::UrlFormattingOption f2)
{ return QUrl::FormattingOptions(f1) | f2; }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::FormattingOptions f2)
+constexpr inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::FormattingOptions f2)
{ return f2 | f1; }
-Q_DECL_CONSTEXPR inline QIncompatibleFlag operator|(QUrl::UrlFormattingOption f1, int f2)
-{ return QIncompatibleFlag(int(f1) | f2); }
+constexpr inline QIncompatibleFlag operator|(QUrl::UrlFormattingOption f1, int f2)
+{ return QIncompatibleFlag(uint(f1) | f2); }
// add operators for OR'ing the two types of flags
inline QUrl::FormattingOptions &operator|=(QUrl::FormattingOptions &i, QUrl::ComponentFormattingOptions f)
-{ i |= QUrl::UrlFormattingOption(int(f)); return i; }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOption f)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOptions f)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::UrlFormattingOption i)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::UrlFormattingOption i)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::FormattingOptions i, QUrl::ComponentFormattingOptions f)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::FormattingOptions i)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
-Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::FormattingOptions i)
-{ return i | QUrl::UrlFormattingOption(int(f)); }
+{ i |= QUrl::UrlFormattingOption(f.toInt()); return i; }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOption f)
+{ return i | QUrl::UrlFormattingOption(qToUnderlying(f)); }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOptions f)
+{ return i | QUrl::UrlFormattingOption(f.toInt()); }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::UrlFormattingOption i)
+{ return i | QUrl::UrlFormattingOption(qToUnderlying(f)); }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::UrlFormattingOption i)
+{ return i | QUrl::UrlFormattingOption(f.toInt()); }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::FormattingOptions i, QUrl::ComponentFormattingOptions f)
+{ return i | QUrl::UrlFormattingOption(f.toInt()); }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::FormattingOptions i)
+{ return i | QUrl::UrlFormattingOption(qToUnderlying(f)); }
+constexpr inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::FormattingOptions i)
+{ return i | QUrl::UrlFormattingOption(f.toInt()); }
//inline QUrl::UrlFormattingOption &operator=(const QUrl::UrlFormattingOption &i, QUrl::ComponentFormattingOptions f)
//{ i = int(f); f; }
@@ -412,8 +330,4 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QUrl &);
QT_END_NAMESPACE
-#if QT_DEPRECATED_SINCE(5,0)
-# include <QtCore/qurlquery.h>
-#endif
-
#endif // QURL_H
diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h
index 9a063a37e6..9562d1993d 100644
--- a/src/corelib/io/qurl_p.h
+++ b/src/corelib/io/qurl_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QURL_P_H
#define QURL_P_H
@@ -65,12 +29,10 @@ extern Q_AUTOTEST_EXPORT qsizetype qt_urlRecode(QString &appendTo, QStringView u
// in qurlidna.cpp
enum AceLeadingDot { AllowLeadingDot, ForbidLeadingDot };
enum AceOperation { ToAceOnly, NormalizeAce };
-extern QString qt_ACE_do(QStringView domain, AceOperation op, AceLeadingDot dot);
-extern Q_AUTOTEST_EXPORT bool qt_nameprep(QString *source, int from);
-extern Q_AUTOTEST_EXPORT bool qt_check_std3rules(QStringView in);
+QString Q_CORE_EXPORT qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot,
+ QUrl::AceProcessingOptions options = {});
extern Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output);
extern Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc);
-extern Q_AUTOTEST_EXPORT QString qt_urlRecodeByteArray(const QByteArray &ba);
QT_END_NAMESPACE
diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp
index fb74fc7a64..a2a81c7605 100644
--- a/src/corelib/io/qurlidna.cpp
+++ b/src/corelib/io/qurlidna.cpp
@@ -1,54 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qurl_p.h"
#include <QtCore/qstringlist.h>
+#include <QtCore/private/qnumeric_p.h>
+#include <QtCore/private/qoffsetstringarray_p.h>
#include <QtCore/private/qstringiterator_p.h>
+#include <QtCore/private/qunicodetables_p.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// needed by the punycode encoder/decoder
-#define Q_MAXINT ((uint)((uint)(-1)>>1))
static const uint base = 36;
static const uint tmin = 1;
static const uint tmax = 26;
@@ -57,2115 +25,7 @@ static const uint damp = 700;
static const uint initial_bias = 72;
static const uint initial_n = 128;
-struct NameprepCaseFoldingEntry {
- char32_t uc;
- char16_t mapping[4];
-};
-
-inline bool operator<(char32_t one, const NameprepCaseFoldingEntry &other)
-{ return one < other.uc; }
-
-inline bool operator<(const NameprepCaseFoldingEntry &one, char32_t other)
-{ return one.uc < other; }
-
-static const NameprepCaseFoldingEntry NameprepCaseFolding[] = {
-/* { 0x0041, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x0042, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x0043, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x0044, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x0045, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x0046, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x0047, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x0048, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x0049, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x004A, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x004B, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x004C, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x004D, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x004E, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x004F, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x0050, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x0051, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x0052, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x0053, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x0054, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x0055, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x0056, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x0057, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x0058, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x0059, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x005A, { 0x007A, 0x0000, 0x0000, 0x0000 } },*/
- { 0x00B5, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x00C0, { 0x00E0, 0x0000, 0x0000, 0x0000 } },
- { 0x00C1, { 0x00E1, 0x0000, 0x0000, 0x0000 } },
- { 0x00C2, { 0x00E2, 0x0000, 0x0000, 0x0000 } },
- { 0x00C3, { 0x00E3, 0x0000, 0x0000, 0x0000 } },
- { 0x00C4, { 0x00E4, 0x0000, 0x0000, 0x0000 } },
- { 0x00C5, { 0x00E5, 0x0000, 0x0000, 0x0000 } },
- { 0x00C6, { 0x00E6, 0x0000, 0x0000, 0x0000 } },
- { 0x00C7, { 0x00E7, 0x0000, 0x0000, 0x0000 } },
- { 0x00C8, { 0x00E8, 0x0000, 0x0000, 0x0000 } },
- { 0x00C9, { 0x00E9, 0x0000, 0x0000, 0x0000 } },
- { 0x00CA, { 0x00EA, 0x0000, 0x0000, 0x0000 } },
- { 0x00CB, { 0x00EB, 0x0000, 0x0000, 0x0000 } },
- { 0x00CC, { 0x00EC, 0x0000, 0x0000, 0x0000 } },
- { 0x00CD, { 0x00ED, 0x0000, 0x0000, 0x0000 } },
- { 0x00CE, { 0x00EE, 0x0000, 0x0000, 0x0000 } },
- { 0x00CF, { 0x00EF, 0x0000, 0x0000, 0x0000 } },
- { 0x00D0, { 0x00F0, 0x0000, 0x0000, 0x0000 } },
- { 0x00D1, { 0x00F1, 0x0000, 0x0000, 0x0000 } },
- { 0x00D2, { 0x00F2, 0x0000, 0x0000, 0x0000 } },
- { 0x00D3, { 0x00F3, 0x0000, 0x0000, 0x0000 } },
- { 0x00D4, { 0x00F4, 0x0000, 0x0000, 0x0000 } },
- { 0x00D5, { 0x00F5, 0x0000, 0x0000, 0x0000 } },
- { 0x00D6, { 0x00F6, 0x0000, 0x0000, 0x0000 } },
- { 0x00D8, { 0x00F8, 0x0000, 0x0000, 0x0000 } },
- { 0x00D9, { 0x00F9, 0x0000, 0x0000, 0x0000 } },
- { 0x00DA, { 0x00FA, 0x0000, 0x0000, 0x0000 } },
- { 0x00DB, { 0x00FB, 0x0000, 0x0000, 0x0000 } },
- { 0x00DC, { 0x00FC, 0x0000, 0x0000, 0x0000 } },
- { 0x00DD, { 0x00FD, 0x0000, 0x0000, 0x0000 } },
- { 0x00DE, { 0x00FE, 0x0000, 0x0000, 0x0000 } },
- { 0x00DF, { 0x0073, 0x0073, 0x0000, 0x0000 } },
- { 0x0100, { 0x0101, 0x0000, 0x0000, 0x0000 } },
- { 0x0102, { 0x0103, 0x0000, 0x0000, 0x0000 } },
- { 0x0104, { 0x0105, 0x0000, 0x0000, 0x0000 } },
- { 0x0106, { 0x0107, 0x0000, 0x0000, 0x0000 } },
- { 0x0108, { 0x0109, 0x0000, 0x0000, 0x0000 } },
- { 0x010A, { 0x010B, 0x0000, 0x0000, 0x0000 } },
- { 0x010C, { 0x010D, 0x0000, 0x0000, 0x0000 } },
- { 0x010E, { 0x010F, 0x0000, 0x0000, 0x0000 } },
- { 0x0110, { 0x0111, 0x0000, 0x0000, 0x0000 } },
- { 0x0112, { 0x0113, 0x0000, 0x0000, 0x0000 } },
- { 0x0114, { 0x0115, 0x0000, 0x0000, 0x0000 } },
- { 0x0116, { 0x0117, 0x0000, 0x0000, 0x0000 } },
- { 0x0118, { 0x0119, 0x0000, 0x0000, 0x0000 } },
- { 0x011A, { 0x011B, 0x0000, 0x0000, 0x0000 } },
- { 0x011C, { 0x011D, 0x0000, 0x0000, 0x0000 } },
- { 0x011E, { 0x011F, 0x0000, 0x0000, 0x0000 } },
- { 0x0120, { 0x0121, 0x0000, 0x0000, 0x0000 } },
- { 0x0122, { 0x0123, 0x0000, 0x0000, 0x0000 } },
- { 0x0124, { 0x0125, 0x0000, 0x0000, 0x0000 } },
- { 0x0126, { 0x0127, 0x0000, 0x0000, 0x0000 } },
- { 0x0128, { 0x0129, 0x0000, 0x0000, 0x0000 } },
- { 0x012A, { 0x012B, 0x0000, 0x0000, 0x0000 } },
- { 0x012C, { 0x012D, 0x0000, 0x0000, 0x0000 } },
- { 0x012E, { 0x012F, 0x0000, 0x0000, 0x0000 } },
- { 0x0130, { 0x0069, 0x0307, 0x0000, 0x0000 } },
- { 0x0132, { 0x0133, 0x0000, 0x0000, 0x0000 } },
- { 0x0134, { 0x0135, 0x0000, 0x0000, 0x0000 } },
- { 0x0136, { 0x0137, 0x0000, 0x0000, 0x0000 } },
- { 0x0139, { 0x013A, 0x0000, 0x0000, 0x0000 } },
- { 0x013B, { 0x013C, 0x0000, 0x0000, 0x0000 } },
- { 0x013D, { 0x013E, 0x0000, 0x0000, 0x0000 } },
- { 0x013F, { 0x0140, 0x0000, 0x0000, 0x0000 } },
- { 0x0141, { 0x0142, 0x0000, 0x0000, 0x0000 } },
- { 0x0143, { 0x0144, 0x0000, 0x0000, 0x0000 } },
- { 0x0145, { 0x0146, 0x0000, 0x0000, 0x0000 } },
- { 0x0147, { 0x0148, 0x0000, 0x0000, 0x0000 } },
- { 0x0149, { 0x02BC, 0x006E, 0x0000, 0x0000 } },
- { 0x014A, { 0x014B, 0x0000, 0x0000, 0x0000 } },
- { 0x014C, { 0x014D, 0x0000, 0x0000, 0x0000 } },
- { 0x014E, { 0x014F, 0x0000, 0x0000, 0x0000 } },
- { 0x0150, { 0x0151, 0x0000, 0x0000, 0x0000 } },
- { 0x0152, { 0x0153, 0x0000, 0x0000, 0x0000 } },
- { 0x0154, { 0x0155, 0x0000, 0x0000, 0x0000 } },
- { 0x0156, { 0x0157, 0x0000, 0x0000, 0x0000 } },
- { 0x0158, { 0x0159, 0x0000, 0x0000, 0x0000 } },
- { 0x015A, { 0x015B, 0x0000, 0x0000, 0x0000 } },
- { 0x015C, { 0x015D, 0x0000, 0x0000, 0x0000 } },
- { 0x015E, { 0x015F, 0x0000, 0x0000, 0x0000 } },
- { 0x0160, { 0x0161, 0x0000, 0x0000, 0x0000 } },
- { 0x0162, { 0x0163, 0x0000, 0x0000, 0x0000 } },
- { 0x0164, { 0x0165, 0x0000, 0x0000, 0x0000 } },
- { 0x0166, { 0x0167, 0x0000, 0x0000, 0x0000 } },
- { 0x0168, { 0x0169, 0x0000, 0x0000, 0x0000 } },
- { 0x016A, { 0x016B, 0x0000, 0x0000, 0x0000 } },
- { 0x016C, { 0x016D, 0x0000, 0x0000, 0x0000 } },
- { 0x016E, { 0x016F, 0x0000, 0x0000, 0x0000 } },
- { 0x0170, { 0x0171, 0x0000, 0x0000, 0x0000 } },
- { 0x0172, { 0x0173, 0x0000, 0x0000, 0x0000 } },
- { 0x0174, { 0x0175, 0x0000, 0x0000, 0x0000 } },
- { 0x0176, { 0x0177, 0x0000, 0x0000, 0x0000 } },
- { 0x0178, { 0x00FF, 0x0000, 0x0000, 0x0000 } },
- { 0x0179, { 0x017A, 0x0000, 0x0000, 0x0000 } },
- { 0x017B, { 0x017C, 0x0000, 0x0000, 0x0000 } },
- { 0x017D, { 0x017E, 0x0000, 0x0000, 0x0000 } },
- { 0x017F, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x0181, { 0x0253, 0x0000, 0x0000, 0x0000 } },
- { 0x0182, { 0x0183, 0x0000, 0x0000, 0x0000 } },
- { 0x0184, { 0x0185, 0x0000, 0x0000, 0x0000 } },
- { 0x0186, { 0x0254, 0x0000, 0x0000, 0x0000 } },
- { 0x0187, { 0x0188, 0x0000, 0x0000, 0x0000 } },
- { 0x0189, { 0x0256, 0x0000, 0x0000, 0x0000 } },
- { 0x018A, { 0x0257, 0x0000, 0x0000, 0x0000 } },
- { 0x018B, { 0x018C, 0x0000, 0x0000, 0x0000 } },
- { 0x018E, { 0x01DD, 0x0000, 0x0000, 0x0000 } },
- { 0x018F, { 0x0259, 0x0000, 0x0000, 0x0000 } },
- { 0x0190, { 0x025B, 0x0000, 0x0000, 0x0000 } },
- { 0x0191, { 0x0192, 0x0000, 0x0000, 0x0000 } },
- { 0x0193, { 0x0260, 0x0000, 0x0000, 0x0000 } },
- { 0x0194, { 0x0263, 0x0000, 0x0000, 0x0000 } },
- { 0x0196, { 0x0269, 0x0000, 0x0000, 0x0000 } },
- { 0x0197, { 0x0268, 0x0000, 0x0000, 0x0000 } },
- { 0x0198, { 0x0199, 0x0000, 0x0000, 0x0000 } },
- { 0x019C, { 0x026F, 0x0000, 0x0000, 0x0000 } },
- { 0x019D, { 0x0272, 0x0000, 0x0000, 0x0000 } },
- { 0x019F, { 0x0275, 0x0000, 0x0000, 0x0000 } },
- { 0x01A0, { 0x01A1, 0x0000, 0x0000, 0x0000 } },
- { 0x01A2, { 0x01A3, 0x0000, 0x0000, 0x0000 } },
- { 0x01A4, { 0x01A5, 0x0000, 0x0000, 0x0000 } },
- { 0x01A6, { 0x0280, 0x0000, 0x0000, 0x0000 } },
- { 0x01A7, { 0x01A8, 0x0000, 0x0000, 0x0000 } },
- { 0x01A9, { 0x0283, 0x0000, 0x0000, 0x0000 } },
- { 0x01AC, { 0x01AD, 0x0000, 0x0000, 0x0000 } },
- { 0x01AE, { 0x0288, 0x0000, 0x0000, 0x0000 } },
- { 0x01AF, { 0x01B0, 0x0000, 0x0000, 0x0000 } },
- { 0x01B1, { 0x028A, 0x0000, 0x0000, 0x0000 } },
- { 0x01B2, { 0x028B, 0x0000, 0x0000, 0x0000 } },
- { 0x01B3, { 0x01B4, 0x0000, 0x0000, 0x0000 } },
- { 0x01B5, { 0x01B6, 0x0000, 0x0000, 0x0000 } },
- { 0x01B7, { 0x0292, 0x0000, 0x0000, 0x0000 } },
- { 0x01B8, { 0x01B9, 0x0000, 0x0000, 0x0000 } },
- { 0x01BC, { 0x01BD, 0x0000, 0x0000, 0x0000 } },
- { 0x01C4, { 0x01C6, 0x0000, 0x0000, 0x0000 } },
- { 0x01C5, { 0x01C6, 0x0000, 0x0000, 0x0000 } },
- { 0x01C7, { 0x01C9, 0x0000, 0x0000, 0x0000 } },
- { 0x01C8, { 0x01C9, 0x0000, 0x0000, 0x0000 } },
- { 0x01CA, { 0x01CC, 0x0000, 0x0000, 0x0000 } },
- { 0x01CB, { 0x01CC, 0x0000, 0x0000, 0x0000 } },
- { 0x01CD, { 0x01CE, 0x0000, 0x0000, 0x0000 } },
- { 0x01CF, { 0x01D0, 0x0000, 0x0000, 0x0000 } },
- { 0x01D1, { 0x01D2, 0x0000, 0x0000, 0x0000 } },
- { 0x01D3, { 0x01D4, 0x0000, 0x0000, 0x0000 } },
- { 0x01D5, { 0x01D6, 0x0000, 0x0000, 0x0000 } },
- { 0x01D7, { 0x01D8, 0x0000, 0x0000, 0x0000 } },
- { 0x01D9, { 0x01DA, 0x0000, 0x0000, 0x0000 } },
- { 0x01DB, { 0x01DC, 0x0000, 0x0000, 0x0000 } },
- { 0x01DE, { 0x01DF, 0x0000, 0x0000, 0x0000 } },
- { 0x01E0, { 0x01E1, 0x0000, 0x0000, 0x0000 } },
- { 0x01E2, { 0x01E3, 0x0000, 0x0000, 0x0000 } },
- { 0x01E4, { 0x01E5, 0x0000, 0x0000, 0x0000 } },
- { 0x01E6, { 0x01E7, 0x0000, 0x0000, 0x0000 } },
- { 0x01E8, { 0x01E9, 0x0000, 0x0000, 0x0000 } },
- { 0x01EA, { 0x01EB, 0x0000, 0x0000, 0x0000 } },
- { 0x01EC, { 0x01ED, 0x0000, 0x0000, 0x0000 } },
- { 0x01EE, { 0x01EF, 0x0000, 0x0000, 0x0000 } },
- { 0x01F0, { 0x006A, 0x030C, 0x0000, 0x0000 } },
- { 0x01F1, { 0x01F3, 0x0000, 0x0000, 0x0000 } },
- { 0x01F2, { 0x01F3, 0x0000, 0x0000, 0x0000 } },
- { 0x01F4, { 0x01F5, 0x0000, 0x0000, 0x0000 } },
- { 0x01F6, { 0x0195, 0x0000, 0x0000, 0x0000 } },
- { 0x01F7, { 0x01BF, 0x0000, 0x0000, 0x0000 } },
- { 0x01F8, { 0x01F9, 0x0000, 0x0000, 0x0000 } },
- { 0x01FA, { 0x01FB, 0x0000, 0x0000, 0x0000 } },
- { 0x01FC, { 0x01FD, 0x0000, 0x0000, 0x0000 } },
- { 0x01FE, { 0x01FF, 0x0000, 0x0000, 0x0000 } },
- { 0x0200, { 0x0201, 0x0000, 0x0000, 0x0000 } },
- { 0x0202, { 0x0203, 0x0000, 0x0000, 0x0000 } },
- { 0x0204, { 0x0205, 0x0000, 0x0000, 0x0000 } },
- { 0x0206, { 0x0207, 0x0000, 0x0000, 0x0000 } },
- { 0x0208, { 0x0209, 0x0000, 0x0000, 0x0000 } },
- { 0x020A, { 0x020B, 0x0000, 0x0000, 0x0000 } },
- { 0x020C, { 0x020D, 0x0000, 0x0000, 0x0000 } },
- { 0x020E, { 0x020F, 0x0000, 0x0000, 0x0000 } },
- { 0x0210, { 0x0211, 0x0000, 0x0000, 0x0000 } },
- { 0x0212, { 0x0213, 0x0000, 0x0000, 0x0000 } },
- { 0x0214, { 0x0215, 0x0000, 0x0000, 0x0000 } },
- { 0x0216, { 0x0217, 0x0000, 0x0000, 0x0000 } },
- { 0x0218, { 0x0219, 0x0000, 0x0000, 0x0000 } },
- { 0x021A, { 0x021B, 0x0000, 0x0000, 0x0000 } },
- { 0x021C, { 0x021D, 0x0000, 0x0000, 0x0000 } },
- { 0x021E, { 0x021F, 0x0000, 0x0000, 0x0000 } },
- { 0x0220, { 0x019E, 0x0000, 0x0000, 0x0000 } },
- { 0x0222, { 0x0223, 0x0000, 0x0000, 0x0000 } },
- { 0x0224, { 0x0225, 0x0000, 0x0000, 0x0000 } },
- { 0x0226, { 0x0227, 0x0000, 0x0000, 0x0000 } },
- { 0x0228, { 0x0229, 0x0000, 0x0000, 0x0000 } },
- { 0x022A, { 0x022B, 0x0000, 0x0000, 0x0000 } },
- { 0x022C, { 0x022D, 0x0000, 0x0000, 0x0000 } },
- { 0x022E, { 0x022F, 0x0000, 0x0000, 0x0000 } },
- { 0x0230, { 0x0231, 0x0000, 0x0000, 0x0000 } },
- { 0x0232, { 0x0233, 0x0000, 0x0000, 0x0000 } },
- { 0x0345, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x037A, { 0x0020, 0x03B9, 0x0000, 0x0000 } },
- { 0x0386, { 0x03AC, 0x0000, 0x0000, 0x0000 } },
- { 0x0388, { 0x03AD, 0x0000, 0x0000, 0x0000 } },
- { 0x0389, { 0x03AE, 0x0000, 0x0000, 0x0000 } },
- { 0x038A, { 0x03AF, 0x0000, 0x0000, 0x0000 } },
- { 0x038C, { 0x03CC, 0x0000, 0x0000, 0x0000 } },
- { 0x038E, { 0x03CD, 0x0000, 0x0000, 0x0000 } },
- { 0x038F, { 0x03CE, 0x0000, 0x0000, 0x0000 } },
- { 0x0390, { 0x03B9, 0x0308, 0x0301, 0x0000 } },
- { 0x0391, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
- { 0x0392, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x0393, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x0394, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
- { 0x0395, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x0396, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
- { 0x0397, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
- { 0x0398, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x0399, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x039A, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x039B, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
- { 0x039C, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x039D, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
- { 0x039E, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
- { 0x039F, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
- { 0x03A0, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x03A1, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x03A3, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x03A4, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
- { 0x03A5, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x03A6, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x03A7, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
- { 0x03A8, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
- { 0x03A9, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x03AA, { 0x03CA, 0x0000, 0x0000, 0x0000 } },
- { 0x03AB, { 0x03CB, 0x0000, 0x0000, 0x0000 } },
- { 0x03B0, { 0x03C5, 0x0308, 0x0301, 0x0000 } },
- { 0x03C2, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x03D0, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x03D1, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x03D2, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x03D3, { 0x03CD, 0x0000, 0x0000, 0x0000 } },
- { 0x03D4, { 0x03CB, 0x0000, 0x0000, 0x0000 } },
- { 0x03D5, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x03D6, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x03D8, { 0x03D9, 0x0000, 0x0000, 0x0000 } },
- { 0x03DA, { 0x03DB, 0x0000, 0x0000, 0x0000 } },
- { 0x03DC, { 0x03DD, 0x0000, 0x0000, 0x0000 } },
- { 0x03DE, { 0x03DF, 0x0000, 0x0000, 0x0000 } },
- { 0x03E0, { 0x03E1, 0x0000, 0x0000, 0x0000 } },
- { 0x03E2, { 0x03E3, 0x0000, 0x0000, 0x0000 } },
- { 0x03E4, { 0x03E5, 0x0000, 0x0000, 0x0000 } },
- { 0x03E6, { 0x03E7, 0x0000, 0x0000, 0x0000 } },
- { 0x03E8, { 0x03E9, 0x0000, 0x0000, 0x0000 } },
- { 0x03EA, { 0x03EB, 0x0000, 0x0000, 0x0000 } },
- { 0x03EC, { 0x03ED, 0x0000, 0x0000, 0x0000 } },
- { 0x03EE, { 0x03EF, 0x0000, 0x0000, 0x0000 } },
- { 0x03F0, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x03F1, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x03F2, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x03F4, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x03F5, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x0400, { 0x0450, 0x0000, 0x0000, 0x0000 } },
- { 0x0401, { 0x0451, 0x0000, 0x0000, 0x0000 } },
- { 0x0402, { 0x0452, 0x0000, 0x0000, 0x0000 } },
- { 0x0403, { 0x0453, 0x0000, 0x0000, 0x0000 } },
- { 0x0404, { 0x0454, 0x0000, 0x0000, 0x0000 } },
- { 0x0405, { 0x0455, 0x0000, 0x0000, 0x0000 } },
- { 0x0406, { 0x0456, 0x0000, 0x0000, 0x0000 } },
- { 0x0407, { 0x0457, 0x0000, 0x0000, 0x0000 } },
- { 0x0408, { 0x0458, 0x0000, 0x0000, 0x0000 } },
- { 0x0409, { 0x0459, 0x0000, 0x0000, 0x0000 } },
- { 0x040A, { 0x045A, 0x0000, 0x0000, 0x0000 } },
- { 0x040B, { 0x045B, 0x0000, 0x0000, 0x0000 } },
- { 0x040C, { 0x045C, 0x0000, 0x0000, 0x0000 } },
- { 0x040D, { 0x045D, 0x0000, 0x0000, 0x0000 } },
- { 0x040E, { 0x045E, 0x0000, 0x0000, 0x0000 } },
- { 0x040F, { 0x045F, 0x0000, 0x0000, 0x0000 } },
- { 0x0410, { 0x0430, 0x0000, 0x0000, 0x0000 } },
- { 0x0411, { 0x0431, 0x0000, 0x0000, 0x0000 } },
- { 0x0412, { 0x0432, 0x0000, 0x0000, 0x0000 } },
- { 0x0413, { 0x0433, 0x0000, 0x0000, 0x0000 } },
- { 0x0414, { 0x0434, 0x0000, 0x0000, 0x0000 } },
- { 0x0415, { 0x0435, 0x0000, 0x0000, 0x0000 } },
- { 0x0416, { 0x0436, 0x0000, 0x0000, 0x0000 } },
- { 0x0417, { 0x0437, 0x0000, 0x0000, 0x0000 } },
- { 0x0418, { 0x0438, 0x0000, 0x0000, 0x0000 } },
- { 0x0419, { 0x0439, 0x0000, 0x0000, 0x0000 } },
- { 0x041A, { 0x043A, 0x0000, 0x0000, 0x0000 } },
- { 0x041B, { 0x043B, 0x0000, 0x0000, 0x0000 } },
- { 0x041C, { 0x043C, 0x0000, 0x0000, 0x0000 } },
- { 0x041D, { 0x043D, 0x0000, 0x0000, 0x0000 } },
- { 0x041E, { 0x043E, 0x0000, 0x0000, 0x0000 } },
- { 0x041F, { 0x043F, 0x0000, 0x0000, 0x0000 } },
- { 0x0420, { 0x0440, 0x0000, 0x0000, 0x0000 } },
- { 0x0421, { 0x0441, 0x0000, 0x0000, 0x0000 } },
- { 0x0422, { 0x0442, 0x0000, 0x0000, 0x0000 } },
- { 0x0423, { 0x0443, 0x0000, 0x0000, 0x0000 } },
- { 0x0424, { 0x0444, 0x0000, 0x0000, 0x0000 } },
- { 0x0425, { 0x0445, 0x0000, 0x0000, 0x0000 } },
- { 0x0426, { 0x0446, 0x0000, 0x0000, 0x0000 } },
- { 0x0427, { 0x0447, 0x0000, 0x0000, 0x0000 } },
- { 0x0428, { 0x0448, 0x0000, 0x0000, 0x0000 } },
- { 0x0429, { 0x0449, 0x0000, 0x0000, 0x0000 } },
- { 0x042A, { 0x044A, 0x0000, 0x0000, 0x0000 } },
- { 0x042B, { 0x044B, 0x0000, 0x0000, 0x0000 } },
- { 0x042C, { 0x044C, 0x0000, 0x0000, 0x0000 } },
- { 0x042D, { 0x044D, 0x0000, 0x0000, 0x0000 } },
- { 0x042E, { 0x044E, 0x0000, 0x0000, 0x0000 } },
- { 0x042F, { 0x044F, 0x0000, 0x0000, 0x0000 } },
- { 0x0460, { 0x0461, 0x0000, 0x0000, 0x0000 } },
- { 0x0462, { 0x0463, 0x0000, 0x0000, 0x0000 } },
- { 0x0464, { 0x0465, 0x0000, 0x0000, 0x0000 } },
- { 0x0466, { 0x0467, 0x0000, 0x0000, 0x0000 } },
- { 0x0468, { 0x0469, 0x0000, 0x0000, 0x0000 } },
- { 0x046A, { 0x046B, 0x0000, 0x0000, 0x0000 } },
- { 0x046C, { 0x046D, 0x0000, 0x0000, 0x0000 } },
- { 0x046E, { 0x046F, 0x0000, 0x0000, 0x0000 } },
- { 0x0470, { 0x0471, 0x0000, 0x0000, 0x0000 } },
- { 0x0472, { 0x0473, 0x0000, 0x0000, 0x0000 } },
- { 0x0474, { 0x0475, 0x0000, 0x0000, 0x0000 } },
- { 0x0476, { 0x0477, 0x0000, 0x0000, 0x0000 } },
- { 0x0478, { 0x0479, 0x0000, 0x0000, 0x0000 } },
- { 0x047A, { 0x047B, 0x0000, 0x0000, 0x0000 } },
- { 0x047C, { 0x047D, 0x0000, 0x0000, 0x0000 } },
- { 0x047E, { 0x047F, 0x0000, 0x0000, 0x0000 } },
- { 0x0480, { 0x0481, 0x0000, 0x0000, 0x0000 } },
- { 0x048A, { 0x048B, 0x0000, 0x0000, 0x0000 } },
- { 0x048C, { 0x048D, 0x0000, 0x0000, 0x0000 } },
- { 0x048E, { 0x048F, 0x0000, 0x0000, 0x0000 } },
- { 0x0490, { 0x0491, 0x0000, 0x0000, 0x0000 } },
- { 0x0492, { 0x0493, 0x0000, 0x0000, 0x0000 } },
- { 0x0494, { 0x0495, 0x0000, 0x0000, 0x0000 } },
- { 0x0496, { 0x0497, 0x0000, 0x0000, 0x0000 } },
- { 0x0498, { 0x0499, 0x0000, 0x0000, 0x0000 } },
- { 0x049A, { 0x049B, 0x0000, 0x0000, 0x0000 } },
- { 0x049C, { 0x049D, 0x0000, 0x0000, 0x0000 } },
- { 0x049E, { 0x049F, 0x0000, 0x0000, 0x0000 } },
- { 0x04A0, { 0x04A1, 0x0000, 0x0000, 0x0000 } },
- { 0x04A2, { 0x04A3, 0x0000, 0x0000, 0x0000 } },
- { 0x04A4, { 0x04A5, 0x0000, 0x0000, 0x0000 } },
- { 0x04A6, { 0x04A7, 0x0000, 0x0000, 0x0000 } },
- { 0x04A8, { 0x04A9, 0x0000, 0x0000, 0x0000 } },
- { 0x04AA, { 0x04AB, 0x0000, 0x0000, 0x0000 } },
- { 0x04AC, { 0x04AD, 0x0000, 0x0000, 0x0000 } },
- { 0x04AE, { 0x04AF, 0x0000, 0x0000, 0x0000 } },
- { 0x04B0, { 0x04B1, 0x0000, 0x0000, 0x0000 } },
- { 0x04B2, { 0x04B3, 0x0000, 0x0000, 0x0000 } },
- { 0x04B4, { 0x04B5, 0x0000, 0x0000, 0x0000 } },
- { 0x04B6, { 0x04B7, 0x0000, 0x0000, 0x0000 } },
- { 0x04B8, { 0x04B9, 0x0000, 0x0000, 0x0000 } },
- { 0x04BA, { 0x04BB, 0x0000, 0x0000, 0x0000 } },
- { 0x04BC, { 0x04BD, 0x0000, 0x0000, 0x0000 } },
- { 0x04BE, { 0x04BF, 0x0000, 0x0000, 0x0000 } },
- { 0x04C1, { 0x04C2, 0x0000, 0x0000, 0x0000 } },
- { 0x04C3, { 0x04C4, 0x0000, 0x0000, 0x0000 } },
- { 0x04C5, { 0x04C6, 0x0000, 0x0000, 0x0000 } },
- { 0x04C7, { 0x04C8, 0x0000, 0x0000, 0x0000 } },
- { 0x04C9, { 0x04CA, 0x0000, 0x0000, 0x0000 } },
- { 0x04CB, { 0x04CC, 0x0000, 0x0000, 0x0000 } },
- { 0x04CD, { 0x04CE, 0x0000, 0x0000, 0x0000 } },
- { 0x04D0, { 0x04D1, 0x0000, 0x0000, 0x0000 } },
- { 0x04D2, { 0x04D3, 0x0000, 0x0000, 0x0000 } },
- { 0x04D4, { 0x04D5, 0x0000, 0x0000, 0x0000 } },
- { 0x04D6, { 0x04D7, 0x0000, 0x0000, 0x0000 } },
- { 0x04D8, { 0x04D9, 0x0000, 0x0000, 0x0000 } },
- { 0x04DA, { 0x04DB, 0x0000, 0x0000, 0x0000 } },
- { 0x04DC, { 0x04DD, 0x0000, 0x0000, 0x0000 } },
- { 0x04DE, { 0x04DF, 0x0000, 0x0000, 0x0000 } },
- { 0x04E0, { 0x04E1, 0x0000, 0x0000, 0x0000 } },
- { 0x04E2, { 0x04E3, 0x0000, 0x0000, 0x0000 } },
- { 0x04E4, { 0x04E5, 0x0000, 0x0000, 0x0000 } },
- { 0x04E6, { 0x04E7, 0x0000, 0x0000, 0x0000 } },
- { 0x04E8, { 0x04E9, 0x0000, 0x0000, 0x0000 } },
- { 0x04EA, { 0x04EB, 0x0000, 0x0000, 0x0000 } },
- { 0x04EC, { 0x04ED, 0x0000, 0x0000, 0x0000 } },
- { 0x04EE, { 0x04EF, 0x0000, 0x0000, 0x0000 } },
- { 0x04F0, { 0x04F1, 0x0000, 0x0000, 0x0000 } },
- { 0x04F2, { 0x04F3, 0x0000, 0x0000, 0x0000 } },
- { 0x04F4, { 0x04F5, 0x0000, 0x0000, 0x0000 } },
- { 0x04F8, { 0x04F9, 0x0000, 0x0000, 0x0000 } },
- { 0x0500, { 0x0501, 0x0000, 0x0000, 0x0000 } },
- { 0x0502, { 0x0503, 0x0000, 0x0000, 0x0000 } },
- { 0x0504, { 0x0505, 0x0000, 0x0000, 0x0000 } },
- { 0x0506, { 0x0507, 0x0000, 0x0000, 0x0000 } },
- { 0x0508, { 0x0509, 0x0000, 0x0000, 0x0000 } },
- { 0x050A, { 0x050B, 0x0000, 0x0000, 0x0000 } },
- { 0x050C, { 0x050D, 0x0000, 0x0000, 0x0000 } },
- { 0x050E, { 0x050F, 0x0000, 0x0000, 0x0000 } },
- { 0x0531, { 0x0561, 0x0000, 0x0000, 0x0000 } },
- { 0x0532, { 0x0562, 0x0000, 0x0000, 0x0000 } },
- { 0x0533, { 0x0563, 0x0000, 0x0000, 0x0000 } },
- { 0x0534, { 0x0564, 0x0000, 0x0000, 0x0000 } },
- { 0x0535, { 0x0565, 0x0000, 0x0000, 0x0000 } },
- { 0x0536, { 0x0566, 0x0000, 0x0000, 0x0000 } },
- { 0x0537, { 0x0567, 0x0000, 0x0000, 0x0000 } },
- { 0x0538, { 0x0568, 0x0000, 0x0000, 0x0000 } },
- { 0x0539, { 0x0569, 0x0000, 0x0000, 0x0000 } },
- { 0x053A, { 0x056A, 0x0000, 0x0000, 0x0000 } },
- { 0x053B, { 0x056B, 0x0000, 0x0000, 0x0000 } },
- { 0x053C, { 0x056C, 0x0000, 0x0000, 0x0000 } },
- { 0x053D, { 0x056D, 0x0000, 0x0000, 0x0000 } },
- { 0x053E, { 0x056E, 0x0000, 0x0000, 0x0000 } },
- { 0x053F, { 0x056F, 0x0000, 0x0000, 0x0000 } },
- { 0x0540, { 0x0570, 0x0000, 0x0000, 0x0000 } },
- { 0x0541, { 0x0571, 0x0000, 0x0000, 0x0000 } },
- { 0x0542, { 0x0572, 0x0000, 0x0000, 0x0000 } },
- { 0x0543, { 0x0573, 0x0000, 0x0000, 0x0000 } },
- { 0x0544, { 0x0574, 0x0000, 0x0000, 0x0000 } },
- { 0x0545, { 0x0575, 0x0000, 0x0000, 0x0000 } },
- { 0x0546, { 0x0576, 0x0000, 0x0000, 0x0000 } },
- { 0x0547, { 0x0577, 0x0000, 0x0000, 0x0000 } },
- { 0x0548, { 0x0578, 0x0000, 0x0000, 0x0000 } },
- { 0x0549, { 0x0579, 0x0000, 0x0000, 0x0000 } },
- { 0x054A, { 0x057A, 0x0000, 0x0000, 0x0000 } },
- { 0x054B, { 0x057B, 0x0000, 0x0000, 0x0000 } },
- { 0x054C, { 0x057C, 0x0000, 0x0000, 0x0000 } },
- { 0x054D, { 0x057D, 0x0000, 0x0000, 0x0000 } },
- { 0x054E, { 0x057E, 0x0000, 0x0000, 0x0000 } },
- { 0x054F, { 0x057F, 0x0000, 0x0000, 0x0000 } },
- { 0x0550, { 0x0580, 0x0000, 0x0000, 0x0000 } },
- { 0x0551, { 0x0581, 0x0000, 0x0000, 0x0000 } },
- { 0x0552, { 0x0582, 0x0000, 0x0000, 0x0000 } },
- { 0x0553, { 0x0583, 0x0000, 0x0000, 0x0000 } },
- { 0x0554, { 0x0584, 0x0000, 0x0000, 0x0000 } },
- { 0x0555, { 0x0585, 0x0000, 0x0000, 0x0000 } },
- { 0x0556, { 0x0586, 0x0000, 0x0000, 0x0000 } },
- { 0x0587, { 0x0565, 0x0582, 0x0000, 0x0000 } },
- { 0x1E00, { 0x1E01, 0x0000, 0x0000, 0x0000 } },
- { 0x1E02, { 0x1E03, 0x0000, 0x0000, 0x0000 } },
- { 0x1E04, { 0x1E05, 0x0000, 0x0000, 0x0000 } },
- { 0x1E06, { 0x1E07, 0x0000, 0x0000, 0x0000 } },
- { 0x1E08, { 0x1E09, 0x0000, 0x0000, 0x0000 } },
- { 0x1E0A, { 0x1E0B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E0C, { 0x1E0D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E0E, { 0x1E0F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E10, { 0x1E11, 0x0000, 0x0000, 0x0000 } },
- { 0x1E12, { 0x1E13, 0x0000, 0x0000, 0x0000 } },
- { 0x1E14, { 0x1E15, 0x0000, 0x0000, 0x0000 } },
- { 0x1E16, { 0x1E17, 0x0000, 0x0000, 0x0000 } },
- { 0x1E18, { 0x1E19, 0x0000, 0x0000, 0x0000 } },
- { 0x1E1A, { 0x1E1B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E1C, { 0x1E1D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E1E, { 0x1E1F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E20, { 0x1E21, 0x0000, 0x0000, 0x0000 } },
- { 0x1E22, { 0x1E23, 0x0000, 0x0000, 0x0000 } },
- { 0x1E24, { 0x1E25, 0x0000, 0x0000, 0x0000 } },
- { 0x1E26, { 0x1E27, 0x0000, 0x0000, 0x0000 } },
- { 0x1E28, { 0x1E29, 0x0000, 0x0000, 0x0000 } },
- { 0x1E2A, { 0x1E2B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E2C, { 0x1E2D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E2E, { 0x1E2F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E30, { 0x1E31, 0x0000, 0x0000, 0x0000 } },
- { 0x1E32, { 0x1E33, 0x0000, 0x0000, 0x0000 } },
- { 0x1E34, { 0x1E35, 0x0000, 0x0000, 0x0000 } },
- { 0x1E36, { 0x1E37, 0x0000, 0x0000, 0x0000 } },
- { 0x1E38, { 0x1E39, 0x0000, 0x0000, 0x0000 } },
- { 0x1E3A, { 0x1E3B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E3C, { 0x1E3D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E3E, { 0x1E3F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E40, { 0x1E41, 0x0000, 0x0000, 0x0000 } },
- { 0x1E42, { 0x1E43, 0x0000, 0x0000, 0x0000 } },
- { 0x1E44, { 0x1E45, 0x0000, 0x0000, 0x0000 } },
- { 0x1E46, { 0x1E47, 0x0000, 0x0000, 0x0000 } },
- { 0x1E48, { 0x1E49, 0x0000, 0x0000, 0x0000 } },
- { 0x1E4A, { 0x1E4B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E4C, { 0x1E4D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E4E, { 0x1E4F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E50, { 0x1E51, 0x0000, 0x0000, 0x0000 } },
- { 0x1E52, { 0x1E53, 0x0000, 0x0000, 0x0000 } },
- { 0x1E54, { 0x1E55, 0x0000, 0x0000, 0x0000 } },
- { 0x1E56, { 0x1E57, 0x0000, 0x0000, 0x0000 } },
- { 0x1E58, { 0x1E59, 0x0000, 0x0000, 0x0000 } },
- { 0x1E5A, { 0x1E5B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E5C, { 0x1E5D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E5E, { 0x1E5F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E60, { 0x1E61, 0x0000, 0x0000, 0x0000 } },
- { 0x1E62, { 0x1E63, 0x0000, 0x0000, 0x0000 } },
- { 0x1E64, { 0x1E65, 0x0000, 0x0000, 0x0000 } },
- { 0x1E66, { 0x1E67, 0x0000, 0x0000, 0x0000 } },
- { 0x1E68, { 0x1E69, 0x0000, 0x0000, 0x0000 } },
- { 0x1E6A, { 0x1E6B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E6C, { 0x1E6D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E6E, { 0x1E6F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E70, { 0x1E71, 0x0000, 0x0000, 0x0000 } },
- { 0x1E72, { 0x1E73, 0x0000, 0x0000, 0x0000 } },
- { 0x1E74, { 0x1E75, 0x0000, 0x0000, 0x0000 } },
- { 0x1E76, { 0x1E77, 0x0000, 0x0000, 0x0000 } },
- { 0x1E78, { 0x1E79, 0x0000, 0x0000, 0x0000 } },
- { 0x1E7A, { 0x1E7B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E7C, { 0x1E7D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E7E, { 0x1E7F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E80, { 0x1E81, 0x0000, 0x0000, 0x0000 } },
- { 0x1E82, { 0x1E83, 0x0000, 0x0000, 0x0000 } },
- { 0x1E84, { 0x1E85, 0x0000, 0x0000, 0x0000 } },
- { 0x1E86, { 0x1E87, 0x0000, 0x0000, 0x0000 } },
- { 0x1E88, { 0x1E89, 0x0000, 0x0000, 0x0000 } },
- { 0x1E8A, { 0x1E8B, 0x0000, 0x0000, 0x0000 } },
- { 0x1E8C, { 0x1E8D, 0x0000, 0x0000, 0x0000 } },
- { 0x1E8E, { 0x1E8F, 0x0000, 0x0000, 0x0000 } },
- { 0x1E90, { 0x1E91, 0x0000, 0x0000, 0x0000 } },
- { 0x1E92, { 0x1E93, 0x0000, 0x0000, 0x0000 } },
- { 0x1E94, { 0x1E95, 0x0000, 0x0000, 0x0000 } },
- { 0x1E96, { 0x0068, 0x0331, 0x0000, 0x0000 } },
- { 0x1E97, { 0x0074, 0x0308, 0x0000, 0x0000 } },
- { 0x1E98, { 0x0077, 0x030A, 0x0000, 0x0000 } },
- { 0x1E99, { 0x0079, 0x030A, 0x0000, 0x0000 } },
- { 0x1E9A, { 0x0061, 0x02BE, 0x0000, 0x0000 } },
- { 0x1E9B, { 0x1E61, 0x0000, 0x0000, 0x0000 } },
- { 0x1EA0, { 0x1EA1, 0x0000, 0x0000, 0x0000 } },
- { 0x1EA2, { 0x1EA3, 0x0000, 0x0000, 0x0000 } },
- { 0x1EA4, { 0x1EA5, 0x0000, 0x0000, 0x0000 } },
- { 0x1EA6, { 0x1EA7, 0x0000, 0x0000, 0x0000 } },
- { 0x1EA8, { 0x1EA9, 0x0000, 0x0000, 0x0000 } },
- { 0x1EAA, { 0x1EAB, 0x0000, 0x0000, 0x0000 } },
- { 0x1EAC, { 0x1EAD, 0x0000, 0x0000, 0x0000 } },
- { 0x1EAE, { 0x1EAF, 0x0000, 0x0000, 0x0000 } },
- { 0x1EB0, { 0x1EB1, 0x0000, 0x0000, 0x0000 } },
- { 0x1EB2, { 0x1EB3, 0x0000, 0x0000, 0x0000 } },
- { 0x1EB4, { 0x1EB5, 0x0000, 0x0000, 0x0000 } },
- { 0x1EB6, { 0x1EB7, 0x0000, 0x0000, 0x0000 } },
- { 0x1EB8, { 0x1EB9, 0x0000, 0x0000, 0x0000 } },
- { 0x1EBA, { 0x1EBB, 0x0000, 0x0000, 0x0000 } },
- { 0x1EBC, { 0x1EBD, 0x0000, 0x0000, 0x0000 } },
- { 0x1EBE, { 0x1EBF, 0x0000, 0x0000, 0x0000 } },
- { 0x1EC0, { 0x1EC1, 0x0000, 0x0000, 0x0000 } },
- { 0x1EC2, { 0x1EC3, 0x0000, 0x0000, 0x0000 } },
- { 0x1EC4, { 0x1EC5, 0x0000, 0x0000, 0x0000 } },
- { 0x1EC6, { 0x1EC7, 0x0000, 0x0000, 0x0000 } },
- { 0x1EC8, { 0x1EC9, 0x0000, 0x0000, 0x0000 } },
- { 0x1ECA, { 0x1ECB, 0x0000, 0x0000, 0x0000 } },
- { 0x1ECC, { 0x1ECD, 0x0000, 0x0000, 0x0000 } },
- { 0x1ECE, { 0x1ECF, 0x0000, 0x0000, 0x0000 } },
- { 0x1ED0, { 0x1ED1, 0x0000, 0x0000, 0x0000 } },
- { 0x1ED2, { 0x1ED3, 0x0000, 0x0000, 0x0000 } },
- { 0x1ED4, { 0x1ED5, 0x0000, 0x0000, 0x0000 } },
- { 0x1ED6, { 0x1ED7, 0x0000, 0x0000, 0x0000 } },
- { 0x1ED8, { 0x1ED9, 0x0000, 0x0000, 0x0000 } },
- { 0x1EDA, { 0x1EDB, 0x0000, 0x0000, 0x0000 } },
- { 0x1EDC, { 0x1EDD, 0x0000, 0x0000, 0x0000 } },
- { 0x1EDE, { 0x1EDF, 0x0000, 0x0000, 0x0000 } },
- { 0x1EE0, { 0x1EE1, 0x0000, 0x0000, 0x0000 } },
- { 0x1EE2, { 0x1EE3, 0x0000, 0x0000, 0x0000 } },
- { 0x1EE4, { 0x1EE5, 0x0000, 0x0000, 0x0000 } },
- { 0x1EE6, { 0x1EE7, 0x0000, 0x0000, 0x0000 } },
- { 0x1EE8, { 0x1EE9, 0x0000, 0x0000, 0x0000 } },
- { 0x1EEA, { 0x1EEB, 0x0000, 0x0000, 0x0000 } },
- { 0x1EEC, { 0x1EED, 0x0000, 0x0000, 0x0000 } },
- { 0x1EEE, { 0x1EEF, 0x0000, 0x0000, 0x0000 } },
- { 0x1EF0, { 0x1EF1, 0x0000, 0x0000, 0x0000 } },
- { 0x1EF2, { 0x1EF3, 0x0000, 0x0000, 0x0000 } },
- { 0x1EF4, { 0x1EF5, 0x0000, 0x0000, 0x0000 } },
- { 0x1EF6, { 0x1EF7, 0x0000, 0x0000, 0x0000 } },
- { 0x1EF8, { 0x1EF9, 0x0000, 0x0000, 0x0000 } },
- { 0x1F08, { 0x1F00, 0x0000, 0x0000, 0x0000 } },
- { 0x1F09, { 0x1F01, 0x0000, 0x0000, 0x0000 } },
- { 0x1F0A, { 0x1F02, 0x0000, 0x0000, 0x0000 } },
- { 0x1F0B, { 0x1F03, 0x0000, 0x0000, 0x0000 } },
- { 0x1F0C, { 0x1F04, 0x0000, 0x0000, 0x0000 } },
- { 0x1F0D, { 0x1F05, 0x0000, 0x0000, 0x0000 } },
- { 0x1F0E, { 0x1F06, 0x0000, 0x0000, 0x0000 } },
- { 0x1F0F, { 0x1F07, 0x0000, 0x0000, 0x0000 } },
- { 0x1F18, { 0x1F10, 0x0000, 0x0000, 0x0000 } },
- { 0x1F19, { 0x1F11, 0x0000, 0x0000, 0x0000 } },
- { 0x1F1A, { 0x1F12, 0x0000, 0x0000, 0x0000 } },
- { 0x1F1B, { 0x1F13, 0x0000, 0x0000, 0x0000 } },
- { 0x1F1C, { 0x1F14, 0x0000, 0x0000, 0x0000 } },
- { 0x1F1D, { 0x1F15, 0x0000, 0x0000, 0x0000 } },
- { 0x1F28, { 0x1F20, 0x0000, 0x0000, 0x0000 } },
- { 0x1F29, { 0x1F21, 0x0000, 0x0000, 0x0000 } },
- { 0x1F2A, { 0x1F22, 0x0000, 0x0000, 0x0000 } },
- { 0x1F2B, { 0x1F23, 0x0000, 0x0000, 0x0000 } },
- { 0x1F2C, { 0x1F24, 0x0000, 0x0000, 0x0000 } },
- { 0x1F2D, { 0x1F25, 0x0000, 0x0000, 0x0000 } },
- { 0x1F2E, { 0x1F26, 0x0000, 0x0000, 0x0000 } },
- { 0x1F2F, { 0x1F27, 0x0000, 0x0000, 0x0000 } },
- { 0x1F38, { 0x1F30, 0x0000, 0x0000, 0x0000 } },
- { 0x1F39, { 0x1F31, 0x0000, 0x0000, 0x0000 } },
- { 0x1F3A, { 0x1F32, 0x0000, 0x0000, 0x0000 } },
- { 0x1F3B, { 0x1F33, 0x0000, 0x0000, 0x0000 } },
- { 0x1F3C, { 0x1F34, 0x0000, 0x0000, 0x0000 } },
- { 0x1F3D, { 0x1F35, 0x0000, 0x0000, 0x0000 } },
- { 0x1F3E, { 0x1F36, 0x0000, 0x0000, 0x0000 } },
- { 0x1F3F, { 0x1F37, 0x0000, 0x0000, 0x0000 } },
- { 0x1F48, { 0x1F40, 0x0000, 0x0000, 0x0000 } },
- { 0x1F49, { 0x1F41, 0x0000, 0x0000, 0x0000 } },
- { 0x1F4A, { 0x1F42, 0x0000, 0x0000, 0x0000 } },
- { 0x1F4B, { 0x1F43, 0x0000, 0x0000, 0x0000 } },
- { 0x1F4C, { 0x1F44, 0x0000, 0x0000, 0x0000 } },
- { 0x1F4D, { 0x1F45, 0x0000, 0x0000, 0x0000 } },
- { 0x1F50, { 0x03C5, 0x0313, 0x0000, 0x0000 } },
- { 0x1F52, { 0x03C5, 0x0313, 0x0300, 0x0000 } },
- { 0x1F54, { 0x03C5, 0x0313, 0x0301, 0x0000 } },
- { 0x1F56, { 0x03C5, 0x0313, 0x0342, 0x0000 } },
- { 0x1F59, { 0x1F51, 0x0000, 0x0000, 0x0000 } },
- { 0x1F5B, { 0x1F53, 0x0000, 0x0000, 0x0000 } },
- { 0x1F5D, { 0x1F55, 0x0000, 0x0000, 0x0000 } },
- { 0x1F5F, { 0x1F57, 0x0000, 0x0000, 0x0000 } },
- { 0x1F68, { 0x1F60, 0x0000, 0x0000, 0x0000 } },
- { 0x1F69, { 0x1F61, 0x0000, 0x0000, 0x0000 } },
- { 0x1F6A, { 0x1F62, 0x0000, 0x0000, 0x0000 } },
- { 0x1F6B, { 0x1F63, 0x0000, 0x0000, 0x0000 } },
- { 0x1F6C, { 0x1F64, 0x0000, 0x0000, 0x0000 } },
- { 0x1F6D, { 0x1F65, 0x0000, 0x0000, 0x0000 } },
- { 0x1F6E, { 0x1F66, 0x0000, 0x0000, 0x0000 } },
- { 0x1F6F, { 0x1F67, 0x0000, 0x0000, 0x0000 } },
- { 0x1F80, { 0x1F00, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F81, { 0x1F01, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F82, { 0x1F02, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F83, { 0x1F03, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F84, { 0x1F04, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F85, { 0x1F05, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F86, { 0x1F06, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F87, { 0x1F07, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F88, { 0x1F00, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F89, { 0x1F01, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F8A, { 0x1F02, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F8B, { 0x1F03, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F8C, { 0x1F04, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F8D, { 0x1F05, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F8E, { 0x1F06, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F8F, { 0x1F07, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F90, { 0x1F20, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F91, { 0x1F21, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F92, { 0x1F22, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F93, { 0x1F23, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F94, { 0x1F24, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F95, { 0x1F25, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F96, { 0x1F26, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F97, { 0x1F27, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F98, { 0x1F20, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F99, { 0x1F21, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F9A, { 0x1F22, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F9B, { 0x1F23, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F9C, { 0x1F24, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F9D, { 0x1F25, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F9E, { 0x1F26, 0x03B9, 0x0000, 0x0000 } },
- { 0x1F9F, { 0x1F27, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA0, { 0x1F60, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA1, { 0x1F61, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA2, { 0x1F62, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA3, { 0x1F63, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA4, { 0x1F64, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA5, { 0x1F65, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA6, { 0x1F66, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA7, { 0x1F67, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA8, { 0x1F60, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FA9, { 0x1F61, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FAA, { 0x1F62, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FAB, { 0x1F63, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FAC, { 0x1F64, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FAD, { 0x1F65, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FAE, { 0x1F66, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FAF, { 0x1F67, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FB2, { 0x1F70, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FB3, { 0x03B1, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FB4, { 0x03AC, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FB6, { 0x03B1, 0x0342, 0x0000, 0x0000 } },
- { 0x1FB7, { 0x03B1, 0x0342, 0x03B9, 0x0000 } },
- { 0x1FB8, { 0x1FB0, 0x0000, 0x0000, 0x0000 } },
- { 0x1FB9, { 0x1FB1, 0x0000, 0x0000, 0x0000 } },
- { 0x1FBA, { 0x1F70, 0x0000, 0x0000, 0x0000 } },
- { 0x1FBB, { 0x1F71, 0x0000, 0x0000, 0x0000 } },
- { 0x1FBC, { 0x03B1, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FBE, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x1FC2, { 0x1F74, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FC3, { 0x03B7, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FC4, { 0x03AE, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FC6, { 0x03B7, 0x0342, 0x0000, 0x0000 } },
- { 0x1FC7, { 0x03B7, 0x0342, 0x03B9, 0x0000 } },
- { 0x1FC8, { 0x1F72, 0x0000, 0x0000, 0x0000 } },
- { 0x1FC9, { 0x1F73, 0x0000, 0x0000, 0x0000 } },
- { 0x1FCA, { 0x1F74, 0x0000, 0x0000, 0x0000 } },
- { 0x1FCB, { 0x1F75, 0x0000, 0x0000, 0x0000 } },
- { 0x1FCC, { 0x03B7, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FD2, { 0x03B9, 0x0308, 0x0300, 0x0000 } },
- { 0x1FD3, { 0x03B9, 0x0308, 0x0301, 0x0000 } },
- { 0x1FD6, { 0x03B9, 0x0342, 0x0000, 0x0000 } },
- { 0x1FD7, { 0x03B9, 0x0308, 0x0342, 0x0000 } },
- { 0x1FD8, { 0x1FD0, 0x0000, 0x0000, 0x0000 } },
- { 0x1FD9, { 0x1FD1, 0x0000, 0x0000, 0x0000 } },
- { 0x1FDA, { 0x1F76, 0x0000, 0x0000, 0x0000 } },
- { 0x1FDB, { 0x1F77, 0x0000, 0x0000, 0x0000 } },
- { 0x1FE2, { 0x03C5, 0x0308, 0x0300, 0x0000 } },
- { 0x1FE3, { 0x03C5, 0x0308, 0x0301, 0x0000 } },
- { 0x1FE4, { 0x03C1, 0x0313, 0x0000, 0x0000 } },
- { 0x1FE6, { 0x03C5, 0x0342, 0x0000, 0x0000 } },
- { 0x1FE7, { 0x03C5, 0x0308, 0x0342, 0x0000 } },
- { 0x1FE8, { 0x1FE0, 0x0000, 0x0000, 0x0000 } },
- { 0x1FE9, { 0x1FE1, 0x0000, 0x0000, 0x0000 } },
- { 0x1FEA, { 0x1F7A, 0x0000, 0x0000, 0x0000 } },
- { 0x1FEB, { 0x1F7B, 0x0000, 0x0000, 0x0000 } },
- { 0x1FEC, { 0x1FE5, 0x0000, 0x0000, 0x0000 } },
- { 0x1FF2, { 0x1F7C, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FF3, { 0x03C9, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FF4, { 0x03CE, 0x03B9, 0x0000, 0x0000 } },
- { 0x1FF6, { 0x03C9, 0x0342, 0x0000, 0x0000 } },
- { 0x1FF7, { 0x03C9, 0x0342, 0x03B9, 0x0000 } },
- { 0x1FF8, { 0x1F78, 0x0000, 0x0000, 0x0000 } },
- { 0x1FF9, { 0x1F79, 0x0000, 0x0000, 0x0000 } },
- { 0x1FFA, { 0x1F7C, 0x0000, 0x0000, 0x0000 } },
- { 0x1FFB, { 0x1F7D, 0x0000, 0x0000, 0x0000 } },
- { 0x1FFC, { 0x03C9, 0x03B9, 0x0000, 0x0000 } },
- { 0x20A8, { 0x0072, 0x0073, 0x0000, 0x0000 } },
- { 0x2102, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x2103, { 0x00B0, 0x0063, 0x0000, 0x0000 } },
- { 0x2107, { 0x025B, 0x0000, 0x0000, 0x0000 } },
- { 0x2109, { 0x00B0, 0x0066, 0x0000, 0x0000 } },
- { 0x210B, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x210C, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x210D, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x2110, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x2111, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x2112, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x2115, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x2116, { 0x006E, 0x006F, 0x0000, 0x0000 } },
- { 0x2119, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x211A, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x211B, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x211C, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x211D, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x2120, { 0x0073, 0x006D, 0x0000, 0x0000 } },
- { 0x2121, { 0x0074, 0x0065, 0x006C, 0x0000 } },
- { 0x2122, { 0x0074, 0x006D, 0x0000, 0x0000 } },
- { 0x2124, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x2126, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x2128, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x212A, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x212B, { 0x00E5, 0x0000, 0x0000, 0x0000 } },
- { 0x212C, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x212D, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x2130, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x2131, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x2133, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x213E, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x213F, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x2145, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x2160, { 0x2170, 0x0000, 0x0000, 0x0000 } },
- { 0x2161, { 0x2171, 0x0000, 0x0000, 0x0000 } },
- { 0x2162, { 0x2172, 0x0000, 0x0000, 0x0000 } },
- { 0x2163, { 0x2173, 0x0000, 0x0000, 0x0000 } },
- { 0x2164, { 0x2174, 0x0000, 0x0000, 0x0000 } },
- { 0x2165, { 0x2175, 0x0000, 0x0000, 0x0000 } },
- { 0x2166, { 0x2176, 0x0000, 0x0000, 0x0000 } },
- { 0x2167, { 0x2177, 0x0000, 0x0000, 0x0000 } },
- { 0x2168, { 0x2178, 0x0000, 0x0000, 0x0000 } },
- { 0x2169, { 0x2179, 0x0000, 0x0000, 0x0000 } },
- { 0x216A, { 0x217A, 0x0000, 0x0000, 0x0000 } },
- { 0x216B, { 0x217B, 0x0000, 0x0000, 0x0000 } },
- { 0x216C, { 0x217C, 0x0000, 0x0000, 0x0000 } },
- { 0x216D, { 0x217D, 0x0000, 0x0000, 0x0000 } },
- { 0x216E, { 0x217E, 0x0000, 0x0000, 0x0000 } },
- { 0x216F, { 0x217F, 0x0000, 0x0000, 0x0000 } },
- { 0x24B6, { 0x24D0, 0x0000, 0x0000, 0x0000 } },
- { 0x24B7, { 0x24D1, 0x0000, 0x0000, 0x0000 } },
- { 0x24B8, { 0x24D2, 0x0000, 0x0000, 0x0000 } },
- { 0x24B9, { 0x24D3, 0x0000, 0x0000, 0x0000 } },
- { 0x24BA, { 0x24D4, 0x0000, 0x0000, 0x0000 } },
- { 0x24BB, { 0x24D5, 0x0000, 0x0000, 0x0000 } },
- { 0x24BC, { 0x24D6, 0x0000, 0x0000, 0x0000 } },
- { 0x24BD, { 0x24D7, 0x0000, 0x0000, 0x0000 } },
- { 0x24BE, { 0x24D8, 0x0000, 0x0000, 0x0000 } },
- { 0x24BF, { 0x24D9, 0x0000, 0x0000, 0x0000 } },
- { 0x24C0, { 0x24DA, 0x0000, 0x0000, 0x0000 } },
- { 0x24C1, { 0x24DB, 0x0000, 0x0000, 0x0000 } },
- { 0x24C2, { 0x24DC, 0x0000, 0x0000, 0x0000 } },
- { 0x24C3, { 0x24DD, 0x0000, 0x0000, 0x0000 } },
- { 0x24C4, { 0x24DE, 0x0000, 0x0000, 0x0000 } },
- { 0x24C5, { 0x24DF, 0x0000, 0x0000, 0x0000 } },
- { 0x24C6, { 0x24E0, 0x0000, 0x0000, 0x0000 } },
- { 0x24C7, { 0x24E1, 0x0000, 0x0000, 0x0000 } },
- { 0x24C8, { 0x24E2, 0x0000, 0x0000, 0x0000 } },
- { 0x24C9, { 0x24E3, 0x0000, 0x0000, 0x0000 } },
- { 0x24CA, { 0x24E4, 0x0000, 0x0000, 0x0000 } },
- { 0x24CB, { 0x24E5, 0x0000, 0x0000, 0x0000 } },
- { 0x24CC, { 0x24E6, 0x0000, 0x0000, 0x0000 } },
- { 0x24CD, { 0x24E7, 0x0000, 0x0000, 0x0000 } },
- { 0x24CE, { 0x24E8, 0x0000, 0x0000, 0x0000 } },
- { 0x24CF, { 0x24E9, 0x0000, 0x0000, 0x0000 } },
- { 0x3371, { 0x0068, 0x0070, 0x0061, 0x0000 } },
- { 0x3373, { 0x0061, 0x0075, 0x0000, 0x0000 } },
- { 0x3375, { 0x006F, 0x0076, 0x0000, 0x0000 } },
- { 0x3380, { 0x0070, 0x0061, 0x0000, 0x0000 } },
- { 0x3381, { 0x006E, 0x0061, 0x0000, 0x0000 } },
- { 0x3382, { 0x03BC, 0x0061, 0x0000, 0x0000 } },
- { 0x3383, { 0x006D, 0x0061, 0x0000, 0x0000 } },
- { 0x3384, { 0x006B, 0x0061, 0x0000, 0x0000 } },
- { 0x3385, { 0x006B, 0x0062, 0x0000, 0x0000 } },
- { 0x3386, { 0x006D, 0x0062, 0x0000, 0x0000 } },
- { 0x3387, { 0x0067, 0x0062, 0x0000, 0x0000 } },
- { 0x338A, { 0x0070, 0x0066, 0x0000, 0x0000 } },
- { 0x338B, { 0x006E, 0x0066, 0x0000, 0x0000 } },
- { 0x338C, { 0x03BC, 0x0066, 0x0000, 0x0000 } },
- { 0x3390, { 0x0068, 0x007A, 0x0000, 0x0000 } },
- { 0x3391, { 0x006B, 0x0068, 0x007A, 0x0000 } },
- { 0x3392, { 0x006D, 0x0068, 0x007A, 0x0000 } },
- { 0x3393, { 0x0067, 0x0068, 0x007A, 0x0000 } },
- { 0x3394, { 0x0074, 0x0068, 0x007A, 0x0000 } },
- { 0x33A9, { 0x0070, 0x0061, 0x0000, 0x0000 } },
- { 0x33AA, { 0x006B, 0x0070, 0x0061, 0x0000 } },
- { 0x33AB, { 0x006D, 0x0070, 0x0061, 0x0000 } },
- { 0x33AC, { 0x0067, 0x0070, 0x0061, 0x0000 } },
- { 0x33B4, { 0x0070, 0x0076, 0x0000, 0x0000 } },
- { 0x33B5, { 0x006E, 0x0076, 0x0000, 0x0000 } },
- { 0x33B6, { 0x03BC, 0x0076, 0x0000, 0x0000 } },
- { 0x33B7, { 0x006D, 0x0076, 0x0000, 0x0000 } },
- { 0x33B8, { 0x006B, 0x0076, 0x0000, 0x0000 } },
- { 0x33B9, { 0x006D, 0x0076, 0x0000, 0x0000 } },
- { 0x33BA, { 0x0070, 0x0077, 0x0000, 0x0000 } },
- { 0x33BB, { 0x006E, 0x0077, 0x0000, 0x0000 } },
- { 0x33BC, { 0x03BC, 0x0077, 0x0000, 0x0000 } },
- { 0x33BD, { 0x006D, 0x0077, 0x0000, 0x0000 } },
- { 0x33BE, { 0x006B, 0x0077, 0x0000, 0x0000 } },
- { 0x33BF, { 0x006D, 0x0077, 0x0000, 0x0000 } },
- { 0x33C0, { 0x006B, 0x03C9, 0x0000, 0x0000 } },
- { 0x33C1, { 0x006D, 0x03C9, 0x0000, 0x0000 } },
- { 0x33C3, { 0x0062, 0x0071, 0x0000, 0x0000 } },
- { 0x33C6, { 0x0063, 0x2215, 0x006B, 0x0067 } },
- { 0x33C7, { 0x0063, 0x006F, 0x002E, 0x0000 } },
- { 0x33C8, { 0x0064, 0x0062, 0x0000, 0x0000 } },
- { 0x33C9, { 0x0067, 0x0079, 0x0000, 0x0000 } },
- { 0x33CB, { 0x0068, 0x0070, 0x0000, 0x0000 } },
- { 0x33CD, { 0x006B, 0x006B, 0x0000, 0x0000 } },
- { 0x33CE, { 0x006B, 0x006D, 0x0000, 0x0000 } },
- { 0x33D7, { 0x0070, 0x0068, 0x0000, 0x0000 } },
- { 0x33D9, { 0x0070, 0x0070, 0x006D, 0x0000 } },
- { 0x33DA, { 0x0070, 0x0072, 0x0000, 0x0000 } },
- { 0x33DC, { 0x0073, 0x0076, 0x0000, 0x0000 } },
- { 0x33DD, { 0x0077, 0x0062, 0x0000, 0x0000 } },
- { 0xFB00, { 0x0066, 0x0066, 0x0000, 0x0000 } },
- { 0xFB01, { 0x0066, 0x0069, 0x0000, 0x0000 } },
- { 0xFB02, { 0x0066, 0x006C, 0x0000, 0x0000 } },
- { 0xFB03, { 0x0066, 0x0066, 0x0069, 0x0000 } },
- { 0xFB04, { 0x0066, 0x0066, 0x006C, 0x0000 } },
- { 0xFB05, { 0x0073, 0x0074, 0x0000, 0x0000 } },
- { 0xFB06, { 0x0073, 0x0074, 0x0000, 0x0000 } },
- { 0xFB13, { 0x0574, 0x0576, 0x0000, 0x0000 } },
- { 0xFB14, { 0x0574, 0x0565, 0x0000, 0x0000 } },
- { 0xFB15, { 0x0574, 0x056B, 0x0000, 0x0000 } },
- { 0xFB16, { 0x057E, 0x0576, 0x0000, 0x0000 } },
- { 0xFB17, { 0x0574, 0x056D, 0x0000, 0x0000 } },
- { 0xFF21, { 0xFF41, 0x0000, 0x0000, 0x0000 } },
- { 0xFF22, { 0xFF42, 0x0000, 0x0000, 0x0000 } },
- { 0xFF23, { 0xFF43, 0x0000, 0x0000, 0x0000 } },
- { 0xFF24, { 0xFF44, 0x0000, 0x0000, 0x0000 } },
- { 0xFF25, { 0xFF45, 0x0000, 0x0000, 0x0000 } },
- { 0xFF26, { 0xFF46, 0x0000, 0x0000, 0x0000 } },
- { 0xFF27, { 0xFF47, 0x0000, 0x0000, 0x0000 } },
- { 0xFF28, { 0xFF48, 0x0000, 0x0000, 0x0000 } },
- { 0xFF29, { 0xFF49, 0x0000, 0x0000, 0x0000 } },
- { 0xFF2A, { 0xFF4A, 0x0000, 0x0000, 0x0000 } },
- { 0xFF2B, { 0xFF4B, 0x0000, 0x0000, 0x0000 } },
- { 0xFF2C, { 0xFF4C, 0x0000, 0x0000, 0x0000 } },
- { 0xFF2D, { 0xFF4D, 0x0000, 0x0000, 0x0000 } },
- { 0xFF2E, { 0xFF4E, 0x0000, 0x0000, 0x0000 } },
- { 0xFF2F, { 0xFF4F, 0x0000, 0x0000, 0x0000 } },
- { 0xFF30, { 0xFF50, 0x0000, 0x0000, 0x0000 } },
- { 0xFF31, { 0xFF51, 0x0000, 0x0000, 0x0000 } },
- { 0xFF32, { 0xFF52, 0x0000, 0x0000, 0x0000 } },
- { 0xFF33, { 0xFF53, 0x0000, 0x0000, 0x0000 } },
- { 0xFF34, { 0xFF54, 0x0000, 0x0000, 0x0000 } },
- { 0xFF35, { 0xFF55, 0x0000, 0x0000, 0x0000 } },
- { 0xFF36, { 0xFF56, 0x0000, 0x0000, 0x0000 } },
- { 0xFF37, { 0xFF57, 0x0000, 0x0000, 0x0000 } },
- { 0xFF38, { 0xFF58, 0x0000, 0x0000, 0x0000 } },
- { 0xFF39, { 0xFF59, 0x0000, 0x0000, 0x0000 } },
- { 0xFF3A, { 0xFF5A, 0x0000, 0x0000, 0x0000 } },
- { 0x10400, { 0xd801, 0xdc28, 0x0000, 0x0000 } },
- { 0x10401, { 0xd801, 0xdc29, 0x0000, 0x0000 } },
- { 0x10402, { 0xd801, 0xdc2A, 0x0000, 0x0000 } },
- { 0x10403, { 0xd801, 0xdc2B, 0x0000, 0x0000 } },
- { 0x10404, { 0xd801, 0xdc2C, 0x0000, 0x0000 } },
- { 0x10405, { 0xd801, 0xdc2D, 0x0000, 0x0000 } },
- { 0x10406, { 0xd801, 0xdc2E, 0x0000, 0x0000 } },
- { 0x10407, { 0xd801, 0xdc2F, 0x0000, 0x0000 } },
- { 0x10408, { 0xd801, 0xdc30, 0x0000, 0x0000 } },
- { 0x10409, { 0xd801, 0xdc31, 0x0000, 0x0000 } },
- { 0x1040A, { 0xd801, 0xdc32, 0x0000, 0x0000 } },
- { 0x1040B, { 0xd801, 0xdc33, 0x0000, 0x0000 } },
- { 0x1040C, { 0xd801, 0xdc34, 0x0000, 0x0000 } },
- { 0x1040D, { 0xd801, 0xdc35, 0x0000, 0x0000 } },
- { 0x1040E, { 0xd801, 0xdc36, 0x0000, 0x0000 } },
- { 0x1040F, { 0xd801, 0xdc37, 0x0000, 0x0000 } },
- { 0x10410, { 0xd801, 0xdc38, 0x0000, 0x0000 } },
- { 0x10411, { 0xd801, 0xdc39, 0x0000, 0x0000 } },
- { 0x10412, { 0xd801, 0xdc3A, 0x0000, 0x0000 } },
- { 0x10413, { 0xd801, 0xdc3B, 0x0000, 0x0000 } },
- { 0x10414, { 0xd801, 0xdc3C, 0x0000, 0x0000 } },
- { 0x10415, { 0xd801, 0xdc3D, 0x0000, 0x0000 } },
- { 0x10416, { 0xd801, 0xdc3E, 0x0000, 0x0000 } },
- { 0x10417, { 0xd801, 0xdc3F, 0x0000, 0x0000 } },
- { 0x10418, { 0xd801, 0xdc40, 0x0000, 0x0000 } },
- { 0x10419, { 0xd801, 0xdc41, 0x0000, 0x0000 } },
- { 0x1041A, { 0xd801, 0xdc42, 0x0000, 0x0000 } },
- { 0x1041B, { 0xd801, 0xdc43, 0x0000, 0x0000 } },
- { 0x1041C, { 0xd801, 0xdc44, 0x0000, 0x0000 } },
- { 0x1041D, { 0xd801, 0xdc45, 0x0000, 0x0000 } },
- { 0x1041E, { 0xd801, 0xdc46, 0x0000, 0x0000 } },
- { 0x1041F, { 0xd801, 0xdc47, 0x0000, 0x0000 } },
- { 0x10420, { 0xd801, 0xdc48, 0x0000, 0x0000 } },
- { 0x10421, { 0xd801, 0xdc49, 0x0000, 0x0000 } },
- { 0x10422, { 0xd801, 0xdc4A, 0x0000, 0x0000 } },
- { 0x10423, { 0xd801, 0xdc4B, 0x0000, 0x0000 } },
- { 0x10424, { 0xd801, 0xdc4C, 0x0000, 0x0000 } },
- { 0x10425, { 0xd801, 0xdc4D, 0x0000, 0x0000 } },
- { 0x1D400, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D401, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D402, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D403, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D404, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D405, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D406, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D407, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D408, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D409, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D40A, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D40B, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D40C, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D40D, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D40E, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D40F, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D410, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D411, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D412, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D413, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D414, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D415, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D416, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D417, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D418, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D419, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D434, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D435, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D436, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D437, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D438, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D439, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D43A, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D43B, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D43C, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D43D, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D43E, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D43F, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D440, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D441, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D442, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D443, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D444, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D445, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D446, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D447, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D448, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D449, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D44A, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D44B, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D44C, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D44D, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D468, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D469, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D46A, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D46B, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D46C, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D46D, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D46E, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D46F, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D470, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D471, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D472, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D473, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D474, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D475, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D476, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D477, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D478, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D479, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D47A, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D47B, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D47C, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D47D, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D47E, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D47F, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D480, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D481, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D49C, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D49E, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D49F, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4A2, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4A5, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4A6, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4A9, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4AA, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4AB, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4AC, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4AE, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4AF, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4B0, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4B1, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4B2, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4B3, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4B4, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4B5, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D0, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D1, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D2, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D3, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D4, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D5, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D6, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D7, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D8, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4D9, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4DA, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4DB, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4DC, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4DD, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4DE, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4DF, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E0, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E1, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E2, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E3, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E4, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E5, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E6, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E7, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E8, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D4E9, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D504, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D505, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D507, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D508, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D509, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D50A, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D50D, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D50E, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D50F, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D510, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D511, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D512, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D513, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D514, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D516, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D517, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D518, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D519, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D51A, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D51B, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D51C, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D538, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D539, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D53B, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D53C, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D53D, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D53E, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D540, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D541, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D542, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D543, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D544, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D546, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D54A, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D54B, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D54C, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D54D, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D54E, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D54F, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D550, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D56C, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D56D, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D56E, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D56F, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D570, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D571, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D572, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D573, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D574, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D575, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D576, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D577, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D578, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D579, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D57A, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D57B, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D57C, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D57D, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D57E, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D57F, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D580, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D581, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D582, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D583, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D584, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D585, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A0, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A1, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A2, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A3, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A4, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A5, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A6, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A7, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A8, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5A9, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5AA, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5AB, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5AC, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5AD, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5AE, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5AF, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B0, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B1, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B2, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B3, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B4, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B5, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B6, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B7, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B8, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5B9, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5D4, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5D5, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5D6, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5D7, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5D8, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5D9, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5DA, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5DB, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5DC, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5DD, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5DE, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5DF, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E0, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E1, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E2, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E3, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E4, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E5, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E6, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E7, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E8, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5E9, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5EA, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5EB, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5EC, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D5ED, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D608, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D609, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D60A, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D60B, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D60C, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D60D, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D60E, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D60F, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D610, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D611, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D612, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D613, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D614, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D615, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D616, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D617, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D618, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D619, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D61A, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D61B, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D61C, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D61D, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D61E, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D61F, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D620, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D621, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D63C, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D63D, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D63E, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D63F, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D640, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D641, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D642, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D643, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D644, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D645, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D646, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D647, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D648, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D649, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D64A, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D64B, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D64C, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D64D, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D64E, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D64F, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D650, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D651, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D652, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D653, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D654, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D655, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D670, { 0x0061, 0x0000, 0x0000, 0x0000 } },
- { 0x1D671, { 0x0062, 0x0000, 0x0000, 0x0000 } },
- { 0x1D672, { 0x0063, 0x0000, 0x0000, 0x0000 } },
- { 0x1D673, { 0x0064, 0x0000, 0x0000, 0x0000 } },
- { 0x1D674, { 0x0065, 0x0000, 0x0000, 0x0000 } },
- { 0x1D675, { 0x0066, 0x0000, 0x0000, 0x0000 } },
- { 0x1D676, { 0x0067, 0x0000, 0x0000, 0x0000 } },
- { 0x1D677, { 0x0068, 0x0000, 0x0000, 0x0000 } },
- { 0x1D678, { 0x0069, 0x0000, 0x0000, 0x0000 } },
- { 0x1D679, { 0x006A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D67A, { 0x006B, 0x0000, 0x0000, 0x0000 } },
- { 0x1D67B, { 0x006C, 0x0000, 0x0000, 0x0000 } },
- { 0x1D67C, { 0x006D, 0x0000, 0x0000, 0x0000 } },
- { 0x1D67D, { 0x006E, 0x0000, 0x0000, 0x0000 } },
- { 0x1D67E, { 0x006F, 0x0000, 0x0000, 0x0000 } },
- { 0x1D67F, { 0x0070, 0x0000, 0x0000, 0x0000 } },
- { 0x1D680, { 0x0071, 0x0000, 0x0000, 0x0000 } },
- { 0x1D681, { 0x0072, 0x0000, 0x0000, 0x0000 } },
- { 0x1D682, { 0x0073, 0x0000, 0x0000, 0x0000 } },
- { 0x1D683, { 0x0074, 0x0000, 0x0000, 0x0000 } },
- { 0x1D684, { 0x0075, 0x0000, 0x0000, 0x0000 } },
- { 0x1D685, { 0x0076, 0x0000, 0x0000, 0x0000 } },
- { 0x1D686, { 0x0077, 0x0000, 0x0000, 0x0000 } },
- { 0x1D687, { 0x0078, 0x0000, 0x0000, 0x0000 } },
- { 0x1D688, { 0x0079, 0x0000, 0x0000, 0x0000 } },
- { 0x1D689, { 0x007A, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6A8, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6A9, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6AA, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6AB, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6AC, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6AD, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6AE, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6AF, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B0, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B1, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B2, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B3, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B4, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B5, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B6, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B7, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B8, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6B9, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6BA, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6BB, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6BC, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6BD, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6BE, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6BF, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6C0, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6D3, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E2, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E3, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E4, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E5, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E6, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E7, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E8, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6E9, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6EA, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6EB, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6EC, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6ED, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6EE, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6EF, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F0, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F1, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F2, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F3, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F4, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F5, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F6, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F7, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F8, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6F9, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D6FA, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D70D, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D71C, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D71D, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x1D71E, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D71F, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D720, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D721, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D722, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D723, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D724, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D725, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x1D726, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
- { 0x1D727, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x1D728, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
- { 0x1D729, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
- { 0x1D72A, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
- { 0x1D72B, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x1D72C, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D72D, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D72E, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D72F, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D730, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D731, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D732, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D733, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D734, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D747, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D756, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D757, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x1D758, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D759, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D75A, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D75B, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D75C, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D75D, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D75E, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D75F, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x1D760, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
- { 0x1D761, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x1D762, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
- { 0x1D763, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
- { 0x1D764, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
- { 0x1D765, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x1D766, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D767, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D768, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D769, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D76A, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D76B, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D76C, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D76D, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D76E, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D781, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D790, { 0x03B1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D791, { 0x03B2, 0x0000, 0x0000, 0x0000 } },
- { 0x1D792, { 0x03B3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D793, { 0x03B4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D794, { 0x03B5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D795, { 0x03B6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D796, { 0x03B7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D797, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D798, { 0x03B9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D799, { 0x03BA, 0x0000, 0x0000, 0x0000 } },
- { 0x1D79A, { 0x03BB, 0x0000, 0x0000, 0x0000 } },
- { 0x1D79B, { 0x03BC, 0x0000, 0x0000, 0x0000 } },
- { 0x1D79C, { 0x03BD, 0x0000, 0x0000, 0x0000 } },
- { 0x1D79D, { 0x03BE, 0x0000, 0x0000, 0x0000 } },
- { 0x1D79E, { 0x03BF, 0x0000, 0x0000, 0x0000 } },
- { 0x1D79F, { 0x03C0, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A0, { 0x03C1, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A1, { 0x03B8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A2, { 0x03C3, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A3, { 0x03C4, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A4, { 0x03C5, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A5, { 0x03C6, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A6, { 0x03C7, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A7, { 0x03C8, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7A8, { 0x03C9, 0x0000, 0x0000, 0x0000 } },
- { 0x1D7BB, { 0x03C3, 0x0000, 0x0000, 0x0000 } }
-};
-
-static void mapToLowerCase(QString *str, int from)
-{
- ushort *d = nullptr;
- for (int i = from; i < str->size(); ++i) {
- uint uc = str->at(i).unicode();
- if (uc < 0x80) {
- if (uc <= 'Z' && uc >= 'A') {
- if (!d)
- d = reinterpret_cast<ushort *>(str->data());
- d[i] = (uc | 0x20);
- }
- } else {
- if (QChar(uc).isHighSurrogate() && i < str->size() - 1) {
- ushort low = str->at(i + 1).unicode();
- if (QChar(low).isLowSurrogate()) {
- uc = QChar::surrogateToUcs4(uc, low);
- ++i;
- }
- }
- const auto entry = std::lower_bound(std::begin(NameprepCaseFolding),
- std::end(NameprepCaseFolding),
- uc);
- if ((entry != std::end(NameprepCaseFolding)) && !(uc < *entry)) {
- int l = 1;
- while (l < 4 && entry->mapping[l])
- ++l;
- if (l > 1 || uc > 0xffff) {
- if (uc <= 0xffff)
- str->replace(i, 1, reinterpret_cast<const QChar *>(&entry->mapping[0]), l);
- else
- str->replace(--i, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l);
- i += l - 1;
- d = nullptr;
- } else {
- if (!d)
- d = reinterpret_cast<ushort *>(str->data());
- d[i] = entry->mapping[0];
- }
- }
- }
- }
-}
-
-static bool isMappedToNothing(uint uc)
-{
- if (uc < 0xad)
- return false;
- switch (uc) {
- case 0x00AD: case 0x034F: case 0x1806: case 0x180B: case 0x180C: case 0x180D:
- case 0x200B: case 0x200C: case 0x200D: case 0x2060: case 0xFE00: case 0xFE01:
- case 0xFE02: case 0xFE03: case 0xFE04: case 0xFE05: case 0xFE06: case 0xFE07:
- case 0xFE08: case 0xFE09: case 0xFE0A: case 0xFE0B: case 0xFE0C: case 0xFE0D:
- case 0xFE0E: case 0xFE0F: case 0xFEFF:
- return true;
- default:
- return false;
- }
-}
-
-namespace {
- static constexpr bool isProhibitedOutputChar(char32_t uc)
- {
- if (uc <= 0xFFFF) {
- if (uc < 0x80 ||
- !(uc <= 0x009F
- || uc == 0x00A0
- || uc == 0x0340
- || uc == 0x0341
- || uc == 0x06DD
- || uc == 0x070F
- || uc == 0x1680
- || uc == 0x180E
- || (uc >= 0x2000 && uc <= 0x200F)
- || (uc >= 0x2028 && uc <= 0x202F)
- || uc == 0x205F
- || (uc >= 0x2060 && uc <= 0x2063)
- || (uc >= 0x206A && uc <= 0x206F)
- || (uc >= 0x2FF0 && uc <= 0x2FFB)
- || uc == 0x3000
- || (uc >= 0xD800 && uc <= 0xDFFF)
- || (uc >= 0xE000 && uc <= 0xF8FF)
- || (uc >= 0xFDD0 && uc <= 0xFDEF)
- || uc == 0xFEFF
- || uc >= 0xFFF9)) {
- return false;
- }
- } else {
- if (!((uc >= 0x1D173 && uc <= 0x1D17A)
- || (uc >= 0x1FFFE && uc <= 0x1FFFF)
- || (uc >= 0x2FFFE && uc <= 0x2FFFF)
- || (uc >= 0x3FFFE && uc <= 0x3FFFF)
- || (uc >= 0x4FFFE && uc <= 0x4FFFF)
- || (uc >= 0x5FFFE && uc <= 0x5FFFF)
- || (uc >= 0x6FFFE && uc <= 0x6FFFF)
- || (uc >= 0x7FFFE && uc <= 0x7FFFF)
- || (uc >= 0x8FFFE && uc <= 0x8FFFF)
- || (uc >= 0x9FFFE && uc <= 0x9FFFF)
- || (uc >= 0xAFFFE && uc <= 0xAFFFF)
- || (uc >= 0xBFFFE && uc <= 0xBFFFF)
- || (uc >= 0xCFFFE && uc <= 0xCFFFF)
- || (uc >= 0xDFFFE && uc <= 0xDFFFF)
- || uc == 0xE0001
- || (uc >= 0xE0020 && uc <= 0xE007F)
- || (uc >= 0xEFFFE && uc <= 0xEFFFF)
- || (uc >= 0xF0000 && uc <= 0xFFFFD)
- || (uc >= 0xFFFFE && uc <= 0xFFFFF)
- || (uc >= 0x100000 && uc <= 0x10FFFD)
- || (uc >= 0x10FFFE && uc <= 0x10FFFF))) {
- return false;
- }
- }
- return true;
- }
-} // unnamed namespace
-
-static bool containsProhibitedOuptut(QStringView str, qsizetype from)
-{
- constexpr char32_t invalid = 0xDEAD;
- static_assert(isProhibitedOutputChar(invalid));
-
- QStringIterator it{str, from};
- while (it.hasNext()) {
- if (isProhibitedOutputChar(it.next(invalid)))
- return true;
- }
-
- return false;
-}
-
-static bool isBidirectionalRorAL(uint uc)
-{
- if (uc < 0x5b0)
- return false;
- return uc == 0x05BE
- || uc == 0x05C0
- || uc == 0x05C3
- || (uc >= 0x05D0 && uc <= 0x05EA)
- || (uc >= 0x05F0 && uc <= 0x05F4)
- || uc == 0x061B
- || uc == 0x061F
- || (uc >= 0x0621 && uc <= 0x063A)
- || (uc >= 0x0640 && uc <= 0x064A)
- || (uc >= 0x066D && uc <= 0x066F)
- || (uc >= 0x0671 && uc <= 0x06D5)
- || uc == 0x06DD
- || (uc >= 0x06E5 && uc <= 0x06E6)
- || (uc >= 0x06FA && uc <= 0x06FE)
- || (uc >= 0x0700 && uc <= 0x070D)
- || uc == 0x0710
- || (uc >= 0x0712 && uc <= 0x072C)
- || (uc >= 0x0780 && uc <= 0x07A5)
- || uc == 0x07B1
- || uc == 0x200F
- || uc == 0xFB1D
- || (uc >= 0xFB1F && uc <= 0xFB28)
- || (uc >= 0xFB2A && uc <= 0xFB36)
- || (uc >= 0xFB38 && uc <= 0xFB3C)
- || uc == 0xFB3E
- || (uc >= 0xFB40 && uc <= 0xFB41)
- || (uc >= 0xFB43 && uc <= 0xFB44)
- || (uc >= 0xFB46 && uc <= 0xFBB1)
- || (uc >= 0xFBD3 && uc <= 0xFD3D)
- || (uc >= 0xFD50 && uc <= 0xFD8F)
- || (uc >= 0xFD92 && uc <= 0xFDC7)
- || (uc >= 0xFDF0 && uc <= 0xFDFC)
- || (uc >= 0xFE70 && uc <= 0xFE74)
- || (uc >= 0xFE76 && uc <= 0xFEFC);
-}
-
-static bool isBidirectionalL(uint uc)
-{
- if (uc < 0xaa)
- return (uc >= 0x0041 && uc <= 0x005A)
- || (uc >= 0x0061 && uc <= 0x007A);
-
- if (uc == 0x00AA
- || uc == 0x00B5
- || uc == 0x00BA
- || (uc >= 0x00C0 && uc <= 0x00D6)
- || (uc >= 0x00D8 && uc <= 0x00F6)
- || (uc >= 0x00F8 && uc <= 0x0220)
- || (uc >= 0x0222 && uc <= 0x0233)
- || (uc >= 0x0250 && uc <= 0x02AD)
- || (uc >= 0x02B0 && uc <= 0x02B8)
- || (uc >= 0x02BB && uc <= 0x02C1)
- || (uc >= 0x02D0 && uc <= 0x02D1)
- || (uc >= 0x02E0 && uc <= 0x02E4)
- || uc == 0x02EE
- || uc == 0x037A
- || uc == 0x0386
- || (uc >= 0x0388 && uc <= 0x038A)) {
- return true;
- }
-
- if (uc == 0x038C
- || (uc >= 0x038E && uc <= 0x03A1)
- || (uc >= 0x03A3 && uc <= 0x03CE)
- || (uc >= 0x03D0 && uc <= 0x03F5)
- || (uc >= 0x0400 && uc <= 0x0482)
- || (uc >= 0x048A && uc <= 0x04CE)
- || (uc >= 0x04D0 && uc <= 0x04F5)
- || (uc >= 0x04F8 && uc <= 0x04F9)
- || (uc >= 0x0500 && uc <= 0x050F)
- || (uc >= 0x0531 && uc <= 0x0556)
- || (uc >= 0x0559 && uc <= 0x055F)
- || (uc >= 0x0561 && uc <= 0x0587)
- || uc == 0x0589
- || uc == 0x0903
- || (uc >= 0x0905 && uc <= 0x0939)
- || (uc >= 0x093D && uc <= 0x0940)
- || (uc >= 0x0949 && uc <= 0x094C)
- || uc == 0x0950) {
- return true;
- }
-
- if ((uc >= 0x0958 && uc <= 0x0961)
- || (uc >= 0x0964 && uc <= 0x0970)
- || (uc >= 0x0982 && uc <= 0x0983)
- || (uc >= 0x0985 && uc <= 0x098C)
- || (uc >= 0x098F && uc <= 0x0990)
- || (uc >= 0x0993 && uc <= 0x09A8)
- || (uc >= 0x09AA && uc <= 0x09B0)
- || uc == 0x09B2
- || (uc >= 0x09B6 && uc <= 0x09B9)
- || (uc >= 0x09BE && uc <= 0x09C0)
- || (uc >= 0x09C7 && uc <= 0x09C8)
- || (uc >= 0x09CB && uc <= 0x09CC)
- || uc == 0x09D7
- || (uc >= 0x09DC && uc <= 0x09DD)
- || (uc >= 0x09DF && uc <= 0x09E1)
- || (uc >= 0x09E6 && uc <= 0x09F1)
- || (uc >= 0x09F4 && uc <= 0x09FA)
- || (uc >= 0x0A05 && uc <= 0x0A0A)
- || (uc >= 0x0A0F && uc <= 0x0A10)
- || (uc >= 0x0A13 && uc <= 0x0A28)
- || (uc >= 0x0A2A && uc <= 0x0A30)
- || (uc >= 0x0A32 && uc <= 0x0A33)) {
- return true;
- }
-
- if ((uc >= 0x0A35 && uc <= 0x0A36)
- || (uc >= 0x0A38 && uc <= 0x0A39)
- || (uc >= 0x0A3E && uc <= 0x0A40)
- || (uc >= 0x0A59 && uc <= 0x0A5C)
- || uc == 0x0A5E
- || (uc >= 0x0A66 && uc <= 0x0A6F)
- || (uc >= 0x0A72 && uc <= 0x0A74)
- || uc == 0x0A83
- || (uc >= 0x0A85 && uc <= 0x0A8B)
- || uc == 0x0A8D
- || (uc >= 0x0A8F && uc <= 0x0A91)
- || (uc >= 0x0A93 && uc <= 0x0AA8)
- || (uc >= 0x0AAA && uc <= 0x0AB0)
- || (uc >= 0x0AB2 && uc <= 0x0AB3)
- || (uc >= 0x0AB5 && uc <= 0x0AB9)
- || (uc >= 0x0ABD && uc <= 0x0AC0)
- || uc == 0x0AC9
- || (uc >= 0x0ACB && uc <= 0x0ACC)
- || uc == 0x0AD0
- || uc == 0x0AE0
- || (uc >= 0x0AE6 && uc <= 0x0AEF)
- || (uc >= 0x0B02 && uc <= 0x0B03)
- || (uc >= 0x0B05 && uc <= 0x0B0C)
- || (uc >= 0x0B0F && uc <= 0x0B10)
- || (uc >= 0x0B13 && uc <= 0x0B28)
- || (uc >= 0x0B2A && uc <= 0x0B30)) {
- return true;
- }
-
- if ((uc >= 0x0B32 && uc <= 0x0B33)
- || (uc >= 0x0B36 && uc <= 0x0B39)
- || (uc >= 0x0B3D && uc <= 0x0B3E)
- || uc == 0x0B40
- || (uc >= 0x0B47 && uc <= 0x0B48)
- || (uc >= 0x0B4B && uc <= 0x0B4C)
- || uc == 0x0B57
- || (uc >= 0x0B5C && uc <= 0x0B5D)
- || (uc >= 0x0B5F && uc <= 0x0B61)
- || (uc >= 0x0B66 && uc <= 0x0B70)
- || uc == 0x0B83
- || (uc >= 0x0B85 && uc <= 0x0B8A)
- || (uc >= 0x0B8E && uc <= 0x0B90)
- || (uc >= 0x0B92 && uc <= 0x0B95)
- || (uc >= 0x0B99 && uc <= 0x0B9A)
- || uc == 0x0B9C
- || (uc >= 0x0B9E && uc <= 0x0B9F)
- || (uc >= 0x0BA3 && uc <= 0x0BA4)
- || (uc >= 0x0BA8 && uc <= 0x0BAA)
- || (uc >= 0x0BAE && uc <= 0x0BB5)
- || (uc >= 0x0BB7 && uc <= 0x0BB9)
- || (uc >= 0x0BBE && uc <= 0x0BBF)
- || (uc >= 0x0BC1 && uc <= 0x0BC2)
- || (uc >= 0x0BC6 && uc <= 0x0BC8)
- || (uc >= 0x0BCA && uc <= 0x0BCC)
- || uc == 0x0BD7
- || (uc >= 0x0BE7 && uc <= 0x0BF2)
- || (uc >= 0x0C01 && uc <= 0x0C03)
- || (uc >= 0x0C05 && uc <= 0x0C0C)
- || (uc >= 0x0C0E && uc <= 0x0C10)
- || (uc >= 0x0C12 && uc <= 0x0C28)
- || (uc >= 0x0C2A && uc <= 0x0C33)
- || (uc >= 0x0C35 && uc <= 0x0C39)) {
- return true;
- }
- if ((uc >= 0x0C41 && uc <= 0x0C44)
- || (uc >= 0x0C60 && uc <= 0x0C61)
- || (uc >= 0x0C66 && uc <= 0x0C6F)
- || (uc >= 0x0C82 && uc <= 0x0C83)
- || (uc >= 0x0C85 && uc <= 0x0C8C)
- || (uc >= 0x0C8E && uc <= 0x0C90)
- || (uc >= 0x0C92 && uc <= 0x0CA8)
- || (uc >= 0x0CAA && uc <= 0x0CB3)
- || (uc >= 0x0CB5 && uc <= 0x0CB9)
- || uc == 0x0CBE
- || (uc >= 0x0CC0 && uc <= 0x0CC4)
- || (uc >= 0x0CC7 && uc <= 0x0CC8)
- || (uc >= 0x0CCA && uc <= 0x0CCB)
- || (uc >= 0x0CD5 && uc <= 0x0CD6)
- || uc == 0x0CDE
- || (uc >= 0x0CE0 && uc <= 0x0CE1)
- || (uc >= 0x0CE6 && uc <= 0x0CEF)
- || (uc >= 0x0D02 && uc <= 0x0D03)
- || (uc >= 0x0D05 && uc <= 0x0D0C)
- || (uc >= 0x0D0E && uc <= 0x0D10)
- || (uc >= 0x0D12 && uc <= 0x0D28)
- || (uc >= 0x0D2A && uc <= 0x0D39)
- || (uc >= 0x0D3E && uc <= 0x0D40)
- || (uc >= 0x0D46 && uc <= 0x0D48)
- || (uc >= 0x0D4A && uc <= 0x0D4C)
- || uc == 0x0D57
- || (uc >= 0x0D60 && uc <= 0x0D61)
- || (uc >= 0x0D66 && uc <= 0x0D6F)
- || (uc >= 0x0D82 && uc <= 0x0D83)
- || (uc >= 0x0D85 && uc <= 0x0D96)
- || (uc >= 0x0D9A && uc <= 0x0DB1)
- || (uc >= 0x0DB3 && uc <= 0x0DBB)
- || uc == 0x0DBD) {
- return true;
- }
- if ((uc >= 0x0DC0 && uc <= 0x0DC6)
- || (uc >= 0x0DCF && uc <= 0x0DD1)
- || (uc >= 0x0DD8 && uc <= 0x0DDF)
- || (uc >= 0x0DF2 && uc <= 0x0DF4)
- || (uc >= 0x0E01 && uc <= 0x0E30)
- || (uc >= 0x0E32 && uc <= 0x0E33)
- || (uc >= 0x0E40 && uc <= 0x0E46)
- || (uc >= 0x0E4F && uc <= 0x0E5B)
- || (uc >= 0x0E81 && uc <= 0x0E82)
- || uc == 0x0E84
- || (uc >= 0x0E87 && uc <= 0x0E88)
- || uc == 0x0E8A
- || uc == 0x0E8D
- || (uc >= 0x0E94 && uc <= 0x0E97)
- || (uc >= 0x0E99 && uc <= 0x0E9F)
- || (uc >= 0x0EA1 && uc <= 0x0EA3)
- || uc == 0x0EA5
- || uc == 0x0EA7
- || (uc >= 0x0EAA && uc <= 0x0EAB)
- || (uc >= 0x0EAD && uc <= 0x0EB0)
- || (uc >= 0x0EB2 && uc <= 0x0EB3)
- || uc == 0x0EBD
- || (uc >= 0x0EC0 && uc <= 0x0EC4)
- || uc == 0x0EC6
- || (uc >= 0x0ED0 && uc <= 0x0ED9)
- || (uc >= 0x0EDC && uc <= 0x0EDD)
- || (uc >= 0x0F00 && uc <= 0x0F17)
- || (uc >= 0x0F1A && uc <= 0x0F34)
- || uc == 0x0F36
- || uc == 0x0F38
- || (uc >= 0x0F3E && uc <= 0x0F47)
- || (uc >= 0x0F49 && uc <= 0x0F6A)
- || uc == 0x0F7F
- || uc == 0x0F85
- || (uc >= 0x0F88 && uc <= 0x0F8B)
- || (uc >= 0x0FBE && uc <= 0x0FC5)
- || (uc >= 0x0FC7 && uc <= 0x0FCC)
- || uc == 0x0FCF) {
- return true;
- }
-
- if ((uc >= 0x1000 && uc <= 0x1021)
- || (uc >= 0x1023 && uc <= 0x1027)
- || (uc >= 0x1029 && uc <= 0x102A)
- || uc == 0x102C
- || uc == 0x1031
- || uc == 0x1038
- || (uc >= 0x1040 && uc <= 0x1057)
- || (uc >= 0x10A0 && uc <= 0x10C5)
- || (uc >= 0x10D0 && uc <= 0x10F8)
- || uc == 0x10FB
- || (uc >= 0x1100 && uc <= 0x1159)
- || (uc >= 0x115F && uc <= 0x11A2)
- || (uc >= 0x11A8 && uc <= 0x11F9)
- || (uc >= 0x1200 && uc <= 0x1206)
- || (uc >= 0x1208 && uc <= 0x1246)
- || uc == 0x1248
- || (uc >= 0x124A && uc <= 0x124D)
- || (uc >= 0x1250 && uc <= 0x1256)
- || uc == 0x1258
- || (uc >= 0x125A && uc <= 0x125D)
- || (uc >= 0x1260 && uc <= 0x1286)
- || uc == 0x1288
- || (uc >= 0x128A && uc <= 0x128D)
- || (uc >= 0x1290 && uc <= 0x12AE)
- || uc == 0x12B0
- || (uc >= 0x12B2 && uc <= 0x12B5)
- || (uc >= 0x12B8 && uc <= 0x12BE)
- || uc == 0x12C0
- || (uc >= 0x12C2 && uc <= 0x12C5)
- || (uc >= 0x12C8 && uc <= 0x12CE)
- || (uc >= 0x12D0 && uc <= 0x12D6)
- || (uc >= 0x12D8 && uc <= 0x12EE)
- || (uc >= 0x12F0 && uc <= 0x130E)
- || uc == 0x1310) {
- return true;
- }
-
- if ((uc >= 0x1312 && uc <= 0x1315)
- || (uc >= 0x1318 && uc <= 0x131E)
- || (uc >= 0x1320 && uc <= 0x1346)
- || (uc >= 0x1348 && uc <= 0x135A)
- || (uc >= 0x1361 && uc <= 0x137C)
- || (uc >= 0x13A0 && uc <= 0x13F4)
- || (uc >= 0x1401 && uc <= 0x1676)
- || (uc >= 0x1681 && uc <= 0x169A)
- || (uc >= 0x16A0 && uc <= 0x16F0)
- || (uc >= 0x1700 && uc <= 0x170C)
- || (uc >= 0x170E && uc <= 0x1711)
- || (uc >= 0x1720 && uc <= 0x1731)
- || (uc >= 0x1735 && uc <= 0x1736)
- || (uc >= 0x1740 && uc <= 0x1751)
- || (uc >= 0x1760 && uc <= 0x176C)
- || (uc >= 0x176E && uc <= 0x1770)
- || (uc >= 0x1780 && uc <= 0x17B6)
- || (uc >= 0x17BE && uc <= 0x17C5)
- || (uc >= 0x17C7 && uc <= 0x17C8)
- || (uc >= 0x17D4 && uc <= 0x17DA)
- || uc == 0x17DC
- || (uc >= 0x17E0 && uc <= 0x17E9)
- || (uc >= 0x1810 && uc <= 0x1819)
- || (uc >= 0x1820 && uc <= 0x1877)
- || (uc >= 0x1880 && uc <= 0x18A8)
- || (uc >= 0x1E00 && uc <= 0x1E9B)
- || (uc >= 0x1EA0 && uc <= 0x1EF9)
- || (uc >= 0x1F00 && uc <= 0x1F15)
- || (uc >= 0x1F18 && uc <= 0x1F1D)
- || (uc >= 0x1F20 && uc <= 0x1F45)
- || (uc >= 0x1F48 && uc <= 0x1F4D)
- || (uc >= 0x1F50 && uc <= 0x1F57)
- || uc == 0x1F59
- || uc == 0x1F5B
- || uc == 0x1F5D) {
- return true;
- }
-
- if ((uc >= 0x1F5F && uc <= 0x1F7D)
- || (uc >= 0x1F80 && uc <= 0x1FB4)
- || (uc >= 0x1FB6 && uc <= 0x1FBC)
- || uc == 0x1FBE
- || (uc >= 0x1FC2 && uc <= 0x1FC4)
- || (uc >= 0x1FC6 && uc <= 0x1FCC)
- || (uc >= 0x1FD0 && uc <= 0x1FD3)
- || (uc >= 0x1FD6 && uc <= 0x1FDB)
- || (uc >= 0x1FE0 && uc <= 0x1FEC)
- || (uc >= 0x1FF2 && uc <= 0x1FF4)
- || (uc >= 0x1FF6 && uc <= 0x1FFC)
- || uc == 0x200E
- || uc == 0x2071
- || uc == 0x207F
- || uc == 0x2102
- || uc == 0x2107
- || (uc >= 0x210A && uc <= 0x2113)
- || uc == 0x2115
- || (uc >= 0x2119 && uc <= 0x211D)) {
- return true;
- }
-
- if (uc == 0x2124
- || uc == 0x2126
- || uc == 0x2128
- || (uc >= 0x212A && uc <= 0x212D)
- || (uc >= 0x212F && uc <= 0x2131)
- || (uc >= 0x2133 && uc <= 0x2139)
- || (uc >= 0x213D && uc <= 0x213F)
- || (uc >= 0x2145 && uc <= 0x2149)
- || (uc >= 0x2160 && uc <= 0x2183)
- || (uc >= 0x2336 && uc <= 0x237A)
- || uc == 0x2395
- || (uc >= 0x249C && uc <= 0x24E9)
- || (uc >= 0x3005 && uc <= 0x3007)
- || (uc >= 0x3021 && uc <= 0x3029)
- || (uc >= 0x3031 && uc <= 0x3035)
- || (uc >= 0x3038 && uc <= 0x303C)
- || (uc >= 0x3041 && uc <= 0x3096)
- || (uc >= 0x309D && uc <= 0x309F)
- || (uc >= 0x30A1 && uc <= 0x30FA)) {
- return true;
- }
-
- if ((uc >= 0x30FC && uc <= 0x30FF)
- || (uc >= 0x3105 && uc <= 0x312C)
- || (uc >= 0x3131 && uc <= 0x318E)
- || (uc >= 0x3190 && uc <= 0x31B7)
- || (uc >= 0x31F0 && uc <= 0x321C)
- || (uc >= 0x3220 && uc <= 0x3243)) {
- return true;
- }
-
- if ((uc >= 0x3260 && uc <= 0x327B)
- || (uc >= 0x327F && uc <= 0x32B0)
- || (uc >= 0x32C0 && uc <= 0x32CB)
- || (uc >= 0x32D0 && uc <= 0x32FE)
- || (uc >= 0x3300 && uc <= 0x3376)
- || (uc >= 0x337B && uc <= 0x33DD)) {
- return true;
- }
- if ((uc >= 0x33E0 && uc <= 0x33FE)
- || (uc >= 0x3400 && uc <= 0x4DB5)
- || (uc >= 0x4E00 && uc <= 0x9FA5)
- || (uc >= 0xA000 && uc <= 0xA48C)
- || (uc >= 0xAC00 && uc <= 0xD7A3)
- || (uc >= 0xD800 && uc <= 0xFA2D)
- || (uc >= 0xFA30 && uc <= 0xFA6A)
- || (uc >= 0xFB00 && uc <= 0xFB06)
- || (uc >= 0xFB13 && uc <= 0xFB17)
- || (uc >= 0xFF21 && uc <= 0xFF3A)
- || (uc >= 0xFF41 && uc <= 0xFF5A)
- || (uc >= 0xFF66 && uc <= 0xFFBE)
- || (uc >= 0xFFC2 && uc <= 0xFFC7)
- || (uc >= 0xFFCA && uc <= 0xFFCF)
- || (uc >= 0xFFD2 && uc <= 0xFFD7)
- || (uc >= 0xFFDA && uc <= 0xFFDC)) {
- return true;
- }
-
- if ((uc >= 0x10300 && uc <= 0x1031E)
- || (uc >= 0x10320 && uc <= 0x10323)
- || (uc >= 0x10330 && uc <= 0x1034A)
- || (uc >= 0x10400 && uc <= 0x10425)
- || (uc >= 0x10428 && uc <= 0x1044D)
- || (uc >= 0x1D000 && uc <= 0x1D0F5)
- || (uc >= 0x1D100 && uc <= 0x1D126)
- || (uc >= 0x1D12A && uc <= 0x1D166)
- || (uc >= 0x1D16A && uc <= 0x1D172)
- || (uc >= 0x1D183 && uc <= 0x1D184)
- || (uc >= 0x1D18C && uc <= 0x1D1A9)
- || (uc >= 0x1D1AE && uc <= 0x1D1DD)
- || (uc >= 0x1D400 && uc <= 0x1D454)
- || (uc >= 0x1D456 && uc <= 0x1D49C)
- || (uc >= 0x1D49E && uc <= 0x1D49F)
- || uc == 0x1D4A2
- || (uc >= 0x1D4A5 && uc <= 0x1D4A6)
- || (uc >= 0x1D4A9 && uc <= 0x1D4AC)
- || (uc >= 0x1D4AE && uc <= 0x1D4B9)
- || uc == 0x1D4BB
- || (uc >= 0x1D4BD && uc <= 0x1D4C0)
- || (uc >= 0x1D4C2 && uc <= 0x1D4C3)
- || (uc >= 0x1D4C5 && uc <= 0x1D505)
- || (uc >= 0x1D507 && uc <= 0x1D50A)
- || (uc >= 0x1D50D && uc <= 0x1D514)
- || (uc >= 0x1D516 && uc <= 0x1D51C)
- || (uc >= 0x1D51E && uc <= 0x1D539)
- || (uc >= 0x1D53B && uc <= 0x1D53E)
- || (uc >= 0x1D540 && uc <= 0x1D544)
- || uc == 0x1D546
- || (uc >= 0x1D54A && uc <= 0x1D550)
- || (uc >= 0x1D552 && uc <= 0x1D6A3)
- || (uc >= 0x1D6A8 && uc <= 0x1D7C9)
- || (uc >= 0x20000 && uc <= 0x2A6D6)
- || (uc >= 0x2F800 && uc <= 0x2FA1D)
- || (uc >= 0xF0000 && uc <= 0xFFFFD)
- || (uc >= 0x100000 && uc <= 0x10FFFD)) {
- return true;
- }
-
- return false;
-}
-
-Q_AUTOTEST_EXPORT bool qt_nameprep(QString *source, int from)
-{
- QChar *src = source->data(); // causes a detach, so we're sure the only one using it
- QChar *out = src + from;
- const QChar *e = src + source->size();
-
- for ( ; out < e; ++out) {
- ushort uc = out->unicode();
- if (uc >= 0x80) {
- break;
- } else if (uc >= 'A' && uc <= 'Z') {
- *out = QChar(uc | 0x20);
- }
- }
- if (out == e)
- return true; // everything was mapped easily (lowercased, actually)
- int firstNonAscii = out - src;
-
- // Characters unassigned in Unicode 3.2 are not allowed in "stored string" scheme
- // but allowed in "query" scheme
- // (Table A.1)
- const bool isUnassignedAllowed = false; // ###
- // Characters commonly mapped to nothing are simply removed
- // (Table B.1)
- const QChar *in = out;
- for ( ; in < e; ++in) {
- uint uc = in->unicode();
- if (QChar(uc).isHighSurrogate() && in < e - 1) {
- ushort low = in[1].unicode();
- if (QChar(low).isLowSurrogate()) {
- ++in;
- uc = QChar::surrogateToUcs4(uc, low);
- }
- }
- if (!isUnassignedAllowed) {
- QChar::UnicodeVersion version = QChar::unicodeVersion(uc);
- if (version == QChar::Unicode_Unassigned || version > QChar::Unicode_3_2) {
- source->resize(from); // not allowed, clear the label
- return false;
- }
- }
- if (!isMappedToNothing(uc)) {
- if (uc <= 0xFFFF) {
- *out++ = *in;
- } else {
- *out++ = in[-1];
- *out++ = in[0];
- }
- }
- }
- if (out != in)
- source->truncate(out - src);
-
- // Map to lowercase (Table B.2)
- mapToLowerCase(source, firstNonAscii);
-
- // Normalize to Unicode 3.2 form KC
- extern void qt_string_normalize(QString *data, QString::NormalizationForm mode,
- QChar::UnicodeVersion version, int from);
- qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2,
- firstNonAscii > from ? firstNonAscii - 1 : from);
-
- // Check for prohibited output
- if (containsProhibitedOuptut(*source, firstNonAscii)) {
- source->resize(from);
- return false;
- }
-
- // Check for valid bidirectional characters
- bool containsLCat = false;
- bool containsRandALCat = false;
- src = source->data();
- e = src + source->size();
- for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) {
- uint uc = in->unicode();
- if (QChar(uc).isHighSurrogate() && in < e - 1) {
- ushort low = in[1].unicode();
- if (QChar(low).isLowSurrogate()) {
- ++in;
- uc = QChar::surrogateToUcs4(uc, low);
- }
- }
- if (isBidirectionalL(uc))
- containsLCat = true;
- else if (isBidirectionalRorAL(uc))
- containsRandALCat = true;
- }
- if (containsRandALCat) {
- if (containsLCat || (!isBidirectionalRorAL(src[from].unicode())
- || !isBidirectionalRorAL(e[-1].unicode()))) {
- source->resize(from); // not allowed, clear the label
- return false;
- }
- }
-
- return true;
-}
-
-static const QChar *qt_find_nonstd3(QStringView in, Qt::CaseSensitivity cs)
-{
- const QChar * const uc = in.data();
- const qsizetype len = in.size();
-
- if (len > 63)
- return uc;
-
- for (qsizetype i = 0; i < len; ++i) {
- const char16_t c = uc[i].unicode();
- if (c == '-' && (i == 0 || i == len - 1))
- return uc + i;
-
- // verifying the absence of non-LDH is the same as verifying that
- // only LDH is present
- if (cs == Qt::CaseInsensitive && (c >= 'A' && c <= 'Z'))
- continue;
- if (c == '-' || (c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'z')
- //underscore is not supposed to be allowed, but other browser accept it (QTBUG-7434)
- || c == '_')
- continue;
-
- return uc + i;
- }
-
- return nullptr;
-}
-
-Q_AUTOTEST_EXPORT bool qt_check_std3rules(QStringView in)
-{
- return qt_find_nonstd3(in, Qt::CaseInsensitive) == nullptr;
-}
-
-static bool qt_check_nameprepped_std3(QStringView in)
-{
- // fast path: check for lowercase ASCII
- const QChar *firstNonAscii = qt_find_nonstd3(in, Qt::CaseSensitive);
- if (firstNonAscii == nullptr) {
- // everything was lowercase ASCII, digits or hyphen
- return true;
- }
-
- QString origin = QString::fromRawData(firstNonAscii, in.end() - firstNonAscii);
- QString copy = origin;
- qt_nameprep(&copy, 0);
- return origin == copy;
-}
+static constexpr qsizetype MaxDomainLabelLength = 63;
static inline uint encodeDigit(uint digit)
{
@@ -2184,14 +44,13 @@ static inline uint adapt(uint delta, uint numpoints, bool firsttime)
return k + (((base - tmin + 1) * delta) / (delta + skew));
}
-static inline void appendEncode(QString* output, uint& delta, uint& bias, uint& b, uint& h)
+static inline void appendEncode(QString *output, uint delta, uint bias)
{
uint qq;
uint k;
uint t;
- // insert the variable length delta integer; fail on
- // overflow.
+ // insert the variable length delta integer.
for (qq = delta, k = base;; k += base) {
// stop generating digits when the threshold is
// detected.
@@ -2203,9 +62,6 @@ static inline void appendEncode(QString* output, uint& delta, uint& bias, uint&
}
*output += QChar(encodeDigit(qq));
- bias = adapt(delta, h + 1, h == b);
- delta = 0;
- ++h;
}
Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output)
@@ -2214,8 +70,14 @@ Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output)
uint delta = 0;
uint bias = initial_bias;
- int outLen = output->length();
- output->resize(outLen + in.length());
+ // Do not try to encode strings that certainly will result in output
+ // that is longer than allowable domain name label length. Note that
+ // non-BMP codepoints are encoded as two QChars.
+ if (in.size() > MaxDomainLabelLength * 2)
+ return;
+
+ int outLen = output->size();
+ output->resize(outLen + in.size());
QChar *d = output->data() + outLen;
bool skipped = false;
@@ -2241,44 +103,59 @@ Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output)
// if basic code points were copied, add the delimiter character.
if (h > 0)
- *output += QLatin1Char{'-'};
+ *output += u'-';
+
+ // compute the input length in Unicode code points.
+ uint inputLength = 0;
+ for (QStringIterator iter(in); iter.hasNext();) {
+ inputLength++;
+
+ if (iter.next(char32_t(-1)) == char32_t(-1)) {
+ output->truncate(outLen);
+ return; // invalid surrogate pair
+ }
+ }
// while there are still unprocessed non-basic code points left in
// the input string...
- while (h < (uint) in.length()) {
- // find the character in the input string with the lowest
- // unicode value.
- uint m = Q_MAXINT;
- for (QChar c : in) {
- if (c.unicode() >= n && c.unicode() < m)
- m = (uint) c.unicode();
+ while (h < inputLength) {
+ // find the character in the input string with the lowest unprocessed value.
+ uint m = std::numeric_limits<uint>::max();
+ for (QStringIterator iter(in); iter.hasNext();) {
+ auto c = iter.nextUnchecked();
+ static_assert(std::numeric_limits<decltype(m)>::max()
+ >= std::numeric_limits<decltype(c)>::max(),
+ "Punycode uint should be able to cover all codepoints");
+ if (c >= n && c < m)
+ m = c;
}
- // reject out-of-bounds unicode characters
- if (m - n > (Q_MAXINT - delta) / (h + 1)) {
+ // delta = delta + (m - n) * (h + 1), fail on overflow
+ uint tmp;
+ if (qMulOverflow<uint>(m - n, h + 1, &tmp) || qAddOverflow<uint>(delta, tmp, &delta)) {
output->truncate(outLen);
return; // punycode_overflow
}
-
- delta += (m - n) * (h + 1);
n = m;
- for (QChar c : in) {
+ for (QStringIterator iter(in); iter.hasNext();) {
+ auto c = iter.nextUnchecked();
- // increase delta until we reach the character with the
- // lowest unicode code. fail if delta overflows.
- if (c.unicode() < n) {
- ++delta;
- if (!delta) {
+ // increase delta until we reach the character processed in this iteration;
+ // fail if delta overflows.
+ if (c < n) {
+ if (qAddOverflow<uint>(delta, 1, &delta)) {
output->truncate(outLen);
return; // punycode_overflow
}
}
- // if j is the index of the character with the lowest
- // unicode code...
- if (c.unicode() == n) {
- appendEncode(output, delta, bias, b, h);
+ if (c == n) {
+ appendEncode(output, delta, bias);
+
+ bias = adapt(delta, h + 1, h == b);
+ delta = 0;
+ ++h;
}
}
@@ -2287,7 +164,7 @@ Q_AUTOTEST_EXPORT void qt_punycodeEncoder(QStringView in, QString *output)
}
// prepend ACE prefix
- output->insert(outLen, QLatin1String("xn--"));
+ output->insert(outLen, "xn--"_L1);
return;
}
@@ -2297,16 +174,22 @@ Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc)
uint i = 0;
uint bias = initial_bias;
+ // Do not try to decode strings longer than allowable for a domain label.
+ // Non-ASCII strings are not allowed here anyway, so there is no need
+ // to account for surrogates.
+ if (pc.size() > MaxDomainLabelLength)
+ return QString();
+
// strip any ACE prefix
- int start = pc.startsWith(QLatin1String("xn--")) ? 4 : 0;
+ int start = pc.startsWith("xn--"_L1) ? 4 : 0;
if (!start)
return pc;
// find the last delimiter character '-' in the input array. copy
// all data before this delimiter directly to the output array.
- int delimiterPos = pc.lastIndexOf(QLatin1Char{'-'});
- QString output = delimiterPos < 4 ?
- QString() : pc.mid(start, delimiterPos - start);
+ int delimiterPos = pc.lastIndexOf(u'-');
+ auto output = delimiterPos < 4 ? std::u32string()
+ : pc.mid(start, delimiterPos - start).toStdU32String();
// if a delimiter was found, skip to the position after it;
// otherwise start at the front of the input string. everything
@@ -2330,39 +213,71 @@ Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc)
else if (digit - 97 < 26) digit -= 97;
else digit = base;
- // reject out of range digits
- if (digit >= base || digit > (Q_MAXINT - i) / w)
- return QStringLiteral("");
+ // Fail if the code point has no digit value
+ if (digit >= base)
+ return QString();
- i += (digit * w);
+ // i = i + digit * w, fail on overflow
+ uint tmp;
+ if (qMulOverflow<uint>(digit, w, &tmp) || qAddOverflow<uint>(i, tmp, &i))
+ return QString();
// detect threshold to stop reading delta digits
uint t;
if (k <= bias) t = tmin;
else if (k >= bias + tmax) t = tmax;
else t = k - bias;
+
if (digit < t) break;
- w *= (base - t);
+ // w = w * (base - t), fail on overflow
+ if (qMulOverflow<uint>(w, base - t, &w))
+ return QString();
}
// find new bias and calculate the next non-basic code
// character.
- bias = adapt(i - oldi, output.length() + 1, oldi == 0);
- n += i / (output.length() + 1);
+ uint outputLength = static_cast<uint>(output.length());
+ bias = adapt(i - oldi, outputLength + 1, oldi == 0);
+
+ // n = n + i div (length(output) + 1), fail on overflow
+ if (qAddOverflow<uint>(n, i / (outputLength + 1), &n))
+ return QString();
// allow the deltas to wrap around
- i %= (output.length() + 1);
+ i %= (outputLength + 1);
+
+ // if n is a basic code point then fail; this should not happen with
+ // correct implementation of Punycode, but check just n case.
+ if (n < initial_n) {
+ // Don't use Q_ASSERT() to avoid possibility of DoS
+ qWarning("Attempt to insert a basic codepoint. Unhandled overflow?");
+ return QString();
+ }
+
+ // Surrogates should normally be rejected later by other IDNA code.
+ // But because of Qt's use of UTF-16 to represent strings the
+ // IDNA code is not able to distinguish characters represented as pairs
+ // of surrogates from normal code points. This is why surrogates are
+ // not allowed here.
+ //
+ // Allowing surrogates would lead to non-unique (after normalization)
+ // encoding of strings with non-BMP characters.
+ //
+ // Punycode that encodes characters outside the Unicode range is also
+ // invalid and is rejected here.
+ if (QChar::isSurrogate(n) || n > QChar::LastValidCodePoint)
+ return QString();
// insert the character n at position i
- output.insert((uint) i, QChar((ushort) n));
+ output.insert(i, 1, static_cast<char32_t>(n));
++i;
}
- return output;
+ return QString::fromStdU32String(output);
}
-static const char * const idn_whitelist[] = {
+static constexpr auto idn_whitelist = qOffsetStringArray(
"ac", "ar", "asia", "at",
"biz", "br",
"cat", "ch", "cl", "cn", "com",
@@ -2399,26 +314,25 @@ static const char * const idn_whitelist[] = {
"xn--wgbh1c", // Egypt
"xn--wgbl6a", // Qatar
"xn--xkc2al3hye2a" // Sri Lanka
-};
-static const size_t idn_whitelist_size = sizeof idn_whitelist / sizeof *idn_whitelist;
+);
-static QStringList *user_idn_whitelist = nullptr;
+Q_CONSTINIT static QStringList *user_idn_whitelist = nullptr;
static bool lessThan(const QChar *a, int l, const char *c)
{
- const ushort *uc = (const ushort *)a;
- const ushort *e = uc + l;
+ const auto *uc = reinterpret_cast<const char16_t *>(a);
+ const char16_t *e = uc + l;
if (!c || *c == 0)
return false;
while (*c) {
- if (uc == e || *uc != *c)
+ if (uc == e || *uc != static_cast<unsigned char>(*c))
break;
++uc;
++c;
}
- return (uc == e ? *c : *uc < *c);
+ return uc == e ? *c : (*uc < static_cast<unsigned char>(*c));
}
static bool equal(const QChar *a, int l, const char *b)
@@ -2433,13 +347,13 @@ static bool equal(const QChar *a, int l, const char *b)
return l == 0;
}
-static bool qt_is_idn_enabled(QStringView domain)
+static bool qt_is_idn_enabled(QStringView aceDomain)
{
- const auto idx = domain.lastIndexOf(QLatin1Char('.'));
+ auto idx = aceDomain.lastIndexOf(u'.');
if (idx == -1)
return false;
- QString tldString = qt_ACE_do(domain.mid(idx + 1), ToAceOnly, ForbidLeadingDot);
+ auto tldString = aceDomain.mid(idx + 1);
const auto len = tldString.size();
const QChar *tld = tldString.constData();
@@ -2448,150 +362,591 @@ static bool qt_is_idn_enabled(QStringView domain)
return user_idn_whitelist->contains(tldString);
int l = 0;
- int r = idn_whitelist_size - 1;
+ int r = idn_whitelist.count() - 1;
int i = (l + r + 1) / 2;
while (r != l) {
- if (lessThan(tld, len, idn_whitelist[i]))
+ if (lessThan(tld, len, idn_whitelist.at(i)))
r = i - 1;
else
l = i;
i = (l + r + 1) / 2;
}
- return equal(tld, len, idn_whitelist[i]);
+ return equal(tld, len, idn_whitelist.at(i));
+}
+
+template<typename C>
+static inline bool isValidInNormalizedAsciiLabel(C c)
+{
+ return c == u'-' || c == u'_' || (c >= u'0' && c <= u'9') || (c >= u'a' && c <= u'z');
}
-static inline bool isDotDelimiter(ushort uc)
+template<typename C>
+static inline bool isValidInNormalizedAsciiName(C c)
{
- // IDNA / rfc3490 describes these four delimiters used for
- // separating labels in unicode international domain
- // names.
- return uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61;
+ return isValidInNormalizedAsciiLabel(c) || c == u'.';
}
-static qsizetype nextDotDelimiter(QStringView domain, qsizetype from = 0)
+/*
+ Map domain name according to algorithm in UTS #46, 4.1
+
+ Returns empty string if there are disallowed characters in the input.
+
+ Sets resultIsAscii if the result is known for sure to be all ASCII.
+*/
+static QString mapDomainName(const QString &in, QUrl::AceProcessingOptions options,
+ bool *resultIsAscii)
{
- const QChar *b = domain.data();
- const QChar *ch = b + from;
- const QChar *e = b + domain.length();
- while (ch < e) {
- if (isDotDelimiter(ch->unicode()))
+ *resultIsAscii = true;
+
+ // Check if the input is already normalized ASCII first and can be returned as is.
+ int i = 0;
+ for (auto c : in) {
+ if (c.unicode() >= 0x80 || !isValidInNormalizedAsciiName(c))
break;
- else
- ++ch;
+ i++;
+ }
+
+ if (i == in.size())
+ return in;
+
+ QString result;
+ result.reserve(in.size());
+ result.append(in.constData(), i);
+ bool allAscii = true;
+
+ for (QStringIterator iter(QStringView(in).sliced(i)); iter.hasNext();) {
+ char32_t uc = iter.next();
+
+ // Fast path for ASCII-only inputs
+ if (Q_LIKELY(uc < 0x80)) {
+ if (uc >= U'A' && uc <= U'Z')
+ uc |= 0x20; // lower-case it
+
+ if (isValidInNormalizedAsciiName(uc)) {
+ result.append(static_cast<char16_t>(uc));
+ continue;
+ }
+ }
+
+ allAscii = false;
+
+ // Capital sharp S is a special case since UTR #46 revision 31 (Unicode 15.1)
+ if (uc == 0x1E9E && options.testFlag(QUrl::AceTransitionalProcessing)) {
+ result.append(u"ss"_s);
+ continue;
+ }
+
+ QUnicodeTables::IdnaStatus status = QUnicodeTables::idnaStatus(uc);
+
+ if (status == QUnicodeTables::IdnaStatus::Deviation)
+ status = options.testFlag(QUrl::AceTransitionalProcessing)
+ ? QUnicodeTables::IdnaStatus::Mapped
+ : QUnicodeTables::IdnaStatus::Valid;
+
+ switch (status) {
+ case QUnicodeTables::IdnaStatus::Ignored:
+ continue;
+ case QUnicodeTables::IdnaStatus::Valid:
+ case QUnicodeTables::IdnaStatus::Disallowed:
+ for (auto c : QChar::fromUcs4(uc))
+ result.append(c);
+ break;
+ case QUnicodeTables::IdnaStatus::Mapped:
+ result.append(QUnicodeTables::idnaMapping(uc));
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
}
- return ch - b;
+
+ *resultIsAscii = allAscii;
+ return result;
}
-QString qt_ACE_do(QStringView domain, AceOperation op, AceLeadingDot dot)
+/*
+ Check the rules for an ASCII label.
+
+ Check the size restriction and that the label does not start or end with dashes.
+
+ The label should be nonempty.
+*/
+static bool validateAsciiLabel(QStringView label)
{
- QString result;
- if (domain.isEmpty())
- return result;
+ if (label.size() > MaxDomainLabelLength)
+ return false;
+
+ if (label.first() == u'-' || label.last() == u'-')
+ return false;
+
+ return std::all_of(label.begin(), label.end(), isValidInNormalizedAsciiLabel<QChar>);
+}
+
+namespace {
+
+class DomainValidityChecker
+{
+ bool domainNameIsBidi = false;
+ bool hadBidiErrors = false;
+ bool ignoreBidiErrors;
+
+ static constexpr char32_t ZWNJ = U'\u200C';
+ static constexpr char32_t ZWJ = U'\u200D';
+
+public:
+ DomainValidityChecker(bool ignoreBidiErrors = false) : ignoreBidiErrors(ignoreBidiErrors) { }
+ bool checkLabel(const QString &label, QUrl::AceProcessingOptions options);
+
+private:
+ static bool checkContextJRules(QStringView label);
+ static bool checkBidiRules(QStringView label);
+};
+
+} // anonymous namespace
+
+/*
+ Check CONTEXTJ rules according to RFC 5892, appendix A.1 & A.2.
+
+ Rule Set for U+200C (ZWNJ):
+
+ False;
+
+ If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
+
+ If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C
+
+ (Joining_Type:T)*(Joining_Type:{R,D})) Then True;
+
+ Rule Set for U+200D (ZWJ):
+
+ False;
+
+ If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
+
+*/
+bool DomainValidityChecker::checkContextJRules(QStringView label)
+{
+ constexpr unsigned char CombiningClassVirama = 9;
+
+ enum class State {
+ Initial,
+ LD_T, // L,D with possible following T*
+ ZWNJ_T, // ZWNJ with possible following T*
+ };
+ State regexpState = State::Initial;
+ bool previousIsVirama = false;
+
+ for (QStringIterator iter(label); iter.hasNext();) {
+ auto ch = iter.next();
+
+ if (ch == ZWJ) {
+ if (!previousIsVirama)
+ return false;
+ regexpState = State::Initial;
+ } else if (ch == ZWNJ) {
+ if (!previousIsVirama && regexpState != State::LD_T)
+ return false;
+ regexpState = previousIsVirama ? State::Initial : State::ZWNJ_T;
+ } else {
+ switch (QChar::joiningType(ch)) {
+ case QChar::Joining_Left:
+ if (regexpState == State::ZWNJ_T)
+ return false;
+ regexpState = State::LD_T;
+ break;
+ case QChar::Joining_Right:
+ regexpState = State::Initial;
+ break;
+ case QChar::Joining_Dual:
+ regexpState = State::LD_T;
+ break;
+ case QChar::Joining_Transparent:
+ break;
+ default:
+ regexpState = State::Initial;
+ break;
+ }
+ }
+
+ previousIsVirama = QChar::combiningClass(ch) == CombiningClassVirama;
+ }
+
+ return regexpState != State::ZWNJ_T;
+}
+
+/*
+ Check if the label conforms to BiDi rule of RFC 5893.
+
+ 1. The first character must be a character with Bidi property L, R,
+ or AL. If it has the R or AL property, it is an RTL label; if it
+ has the L property, it is an LTR label.
+
+ 2. In an RTL label, only characters with the Bidi properties R, AL,
+ AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
+
+ 3. In an RTL label, the end of the label must be a character with
+ Bidi property R, AL, EN, or AN, followed by zero or more
+ characters with Bidi property NSM.
+
+ 4. In an RTL label, if an EN is present, no AN may be present, and
+ vice versa.
+
+ 5. In an LTR label, only characters with the Bidi properties L, EN,
+ ES, CS, ET, ON, BN, or NSM are allowed.
+
+ 6. In an LTR label, the end of the label must be a character with
+ Bidi property L or EN, followed by zero or more characters with
+ Bidi property NSM.
+*/
+bool DomainValidityChecker::checkBidiRules(QStringView label)
+{
+ if (label.isEmpty())
+ return true;
+
+ QStringIterator iter(label);
+ Q_ASSERT(iter.hasNext());
+
+ char32_t ch = iter.next();
+ bool labelIsRTL = false;
+
+ switch (QChar::direction(ch)) {
+ case QChar::DirL:
+ break;
+ case QChar::DirR:
+ case QChar::DirAL:
+ labelIsRTL = true;
+ break;
+ default:
+ return false;
+ }
+
+ bool tailOk = true;
+ bool labelHasEN = false;
+ bool labelHasAN = false;
+
+ while (iter.hasNext()) {
+ ch = iter.next();
+
+ switch (QChar::direction(ch)) {
+ case QChar::DirR:
+ case QChar::DirAL:
+ if (!labelIsRTL)
+ return false;
+ tailOk = true;
+ break;
+
+ case QChar::DirL:
+ if (labelIsRTL)
+ return false;
+ tailOk = true;
+ break;
+
+ case QChar::DirES:
+ case QChar::DirCS:
+ case QChar::DirET:
+ case QChar::DirON:
+ case QChar::DirBN:
+ tailOk = false;
+ break;
+
+ case QChar::DirNSM:
+ break;
+
+ case QChar::DirAN:
+ if (labelIsRTL) {
+ if (labelHasEN)
+ return false;
+ labelHasAN = true;
+ tailOk = true;
+ } else {
+ return false;
+ }
+ break;
+
+ case QChar::DirEN:
+ if (labelIsRTL) {
+ if (labelHasAN)
+ return false;
+ labelHasEN = true;
+ }
+ tailOk = true;
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ return tailOk;
+}
+
+/*
+ Check if the given label is valid according to UTS #46 validity criteria.
+
+ NFC check can be skipped if the label was transformed to NFC before calling
+ this function (as optimization).
+
+ The domain name is considered invalid if this function returns false at least
+ once.
+
+ 1. The label must be in Unicode Normalization Form NFC.
+ 2. If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
+ in both the third and fourth positions.
+ 3. If CheckHyphens, the label must neither begin nor end with a U+002D HYPHEN-MINUS character.
+ 4. The label must not contain a U+002E ( . ) FULL STOP.
+ 5. The label must not begin with a combining mark, that is: General_Category=Mark.
+ 6. Each code point in the label must only have certain status values according to Section 5,
+ IDNA Mapping Table:
+ 1. For Transitional Processing, each value must be valid.
+ 2. For Nontransitional Processing, each value must be either valid or deviation.
+ 7. If CheckJoiners, the label must satisfy the ContextJ rules from Appendix A, in The Unicode
+ Code Points and Internationalized Domain Names for Applications (IDNA).
+ 8. If CheckBidi, and if the domain name is a Bidi domain name, then the label must satisfy
+ all six of the numbered conditions in RFC 5893, Section 2.
+
+ NOTE: Don't use QStringView for label, so that call to QString::normalized() can avoid
+ memory allocation when there is nothing to normalize.
+*/
+bool DomainValidityChecker::checkLabel(const QString &label, QUrl::AceProcessingOptions options)
+{
+ if (label.isEmpty())
+ return true;
+
+ if (label != label.normalized(QString::NormalizationForm_C))
+ return false;
+
+ if (label.size() >= 4) {
+ // This assumes that the first two characters are in BMP, but that's ok
+ // because non-BMP characters are unlikely to be used for specifying
+ // future extensions.
+ if (label[2] == u'-' && label[3] == u'-')
+ return ignoreBidiErrors && label.startsWith(u"xn") && validateAsciiLabel(label);
+ }
+
+ if (label.startsWith(u'-') || label.endsWith(u'-'))
+ return false;
+
+ if (label.contains(u'.'))
+ return false;
- result.reserve(domain.length());
+ QStringIterator iter(label);
+ auto c = iter.next();
- const bool isIdnEnabled = op == NormalizeAce ? qt_is_idn_enabled(domain) : false;
+ if (QChar::isMark(c))
+ return false;
+
+ // As optimization, CONTEXTJ rules check can be skipped if no
+ // ZWJ/ZWNJ characters were found during the first pass.
+ bool hasJoiners = false;
+
+ for (;;) {
+ hasJoiners = hasJoiners || c == ZWNJ || c == ZWJ;
+
+ if (!ignoreBidiErrors && !domainNameIsBidi) {
+ switch (QChar::direction(c)) {
+ case QChar::DirR:
+ case QChar::DirAL:
+ case QChar::DirAN:
+ domainNameIsBidi = true;
+ if (hadBidiErrors)
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (QUnicodeTables::idnaStatus(c)) {
+ case QUnicodeTables::IdnaStatus::Valid:
+ break;
+ case QUnicodeTables::IdnaStatus::Deviation:
+ if (options.testFlag(QUrl::AceTransitionalProcessing))
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ if (!iter.hasNext())
+ break;
+ c = iter.next();
+ }
+
+ if (hasJoiners && !checkContextJRules(label))
+ return false;
+
+ hadBidiErrors = hadBidiErrors || !checkBidiRules(label);
+
+ if (domainNameIsBidi && hadBidiErrors)
+ return false;
+
+ return true;
+}
+
+static QString convertToAscii(QStringView normalizedDomain, AceLeadingDot dot)
+{
qsizetype lastIdx = 0;
QString aceForm; // this variable is here for caching
+ QString aceResult;
+
+ while (true) {
+ qsizetype idx = normalizedDomain.indexOf(u'.', lastIdx);
+ if (idx == -1)
+ idx = normalizedDomain.size();
+
+ const qsizetype labelLength = idx - lastIdx;
+ if (labelLength) {
+ const auto label = normalizedDomain.sliced(lastIdx, labelLength);
+ aceForm.clear();
+ qt_punycodeEncoder(label, &aceForm);
+ if (aceForm.isEmpty())
+ return {};
+
+ aceResult.append(aceForm);
+ }
+
+ if (idx == normalizedDomain.size())
+ break;
+
+ if (labelLength == 0 && (dot == ForbidLeadingDot || idx > 0))
+ return {}; // two delimiters in a row -- empty label not allowed
+
+ lastIdx = idx + 1;
+ aceResult += u'.';
+ }
+
+ return aceResult;
+}
+
+static bool checkAsciiDomainName(QStringView normalizedDomain, AceLeadingDot dot,
+ bool *usesPunycode)
+{
+ qsizetype lastIdx = 0;
+ bool hasPunycode = false;
+ *usesPunycode = false;
+
+ while (lastIdx < normalizedDomain.size()) {
+ auto idx = normalizedDomain.indexOf(u'.', lastIdx);
+ if (idx == -1)
+ idx = normalizedDomain.size();
- while (1) {
- const auto idx = nextDotDelimiter(domain, lastIdx);
const auto labelLength = idx - lastIdx;
if (labelLength == 0) {
- if (idx == domain.size())
+ if (idx == normalizedDomain.size())
break;
if (dot == ForbidLeadingDot || idx > 0)
- return QString(); // two delimiters in a row -- empty label not allowed
- }
+ return false; // two delimiters in a row -- empty label not allowed
+ } else {
+ const auto label = normalizedDomain.sliced(lastIdx, labelLength);
+ if (!validateAsciiLabel(label))
+ return false;
- // RFC 3490 says, about the ToASCII operation:
- // 3. If the UseSTD3ASCIIRules flag is set, then perform these checks:
- //
- // (a) Verify the absence of non-LDH ASCII code points; that is, the
- // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
- //
- // (b) Verify the absence of leading and trailing hyphen-minus; that
- // is, the absence of U+002D at the beginning and end of the
- // sequence.
- // and:
- // 8. Verify that the number of code points is in the range 1 to 63
- // inclusive.
-
- // copy the label to the destination, which also serves as our scratch area, lowercasing it
- int prevLen = result.size();
- bool simple = true;
- result.resize(prevLen + labelLength);
- {
- QChar *out = result.data() + prevLen;
- for (QChar c : domain.mid(lastIdx, labelLength)) {
- const auto uc = c.unicode();
- if (uc > 0x7f)
- simple = false;
- if (uc >= 'A' && uc <= 'Z')
- *out++ = QChar(uc | 0x20);
- else
- *out++ = c;
- }
+ hasPunycode = hasPunycode || label.startsWith("xn--"_L1);
}
- if (simple && labelLength > 6) {
- // ACE form domains contain only ASCII characters, but we can't consider them simple
- // is this an ACE form?
- // the shortest valid ACE domain is 6 characters long (U+0080 would be 1, but it's not allowed)
- static const ushort acePrefixUtf16[] = { 'x', 'n', '-', '-' };
- if (memcmp(result.constData() + prevLen, acePrefixUtf16, sizeof acePrefixUtf16) == 0)
- simple = false;
- }
+ lastIdx = idx + 1;
+ }
- if (simple) {
- // fastest case: this is the common case (non IDN-domains)
- // so we're done
- if (!qt_check_std3rules(QStringView{result.constData() + prevLen, labelLength}))
- return QString();
+ *usesPunycode = hasPunycode;
+ return true;
+}
+
+static QString convertToUnicode(const QString &asciiDomain, QUrl::AceProcessingOptions options)
+{
+ QString result;
+ result.reserve(asciiDomain.size());
+ qsizetype lastIdx = 0;
+
+ DomainValidityChecker checker;
+
+ while (true) {
+ auto idx = asciiDomain.indexOf(u'.', lastIdx);
+ if (idx == -1)
+ idx = asciiDomain.size();
+
+ const auto labelLength = idx - lastIdx;
+ if (labelLength == 0) {
+ if (idx == asciiDomain.size())
+ break;
} else {
- // Punycode encoding and decoding cannot be done in-place
- // That means we need one or two temporaries
- if (!qt_nameprep(&result, prevLen))
- return QString(); // failed
- const auto toReserve = result.length() - prevLen + 4 + 6; // "xn--" plus some extra bytes
- aceForm.resize(0);
- if (toReserve > aceForm.capacity())
- aceForm.reserve(toReserve);
- qt_punycodeEncoder(QStringView{result}.mid(prevLen), &aceForm);
-
- // We use resize()+memcpy() here because we're overwriting the data we've copied
- bool appended = false;
- if (isIdnEnabled) {
- QString tmp = qt_punycodeDecoder(aceForm);
- if (tmp.isEmpty())
- return QString(); // shouldn't happen, since we've just punycode-encoded it
- if (qt_check_nameprepped_std3(tmp)) {
- result.resize(prevLen + tmp.size());
- memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar));
- appended = true;
- }
- }
+ const auto label = asciiDomain.sliced(lastIdx, labelLength);
+ const auto unicodeLabel = qt_punycodeDecoder(label);
- if (!appended) {
- result.resize(prevLen + aceForm.size());
- memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar));
- }
+ if (unicodeLabel.isEmpty())
+ return asciiDomain;
- if (!qt_check_std3rules(aceForm))
- return QString();
+ if (!checker.checkLabel(unicodeLabel, options))
+ return asciiDomain;
+
+ result.append(unicodeLabel);
}
+ if (idx == asciiDomain.size())
+ break;
lastIdx = idx + 1;
- if (lastIdx < domain.size() + 1)
- result += QLatin1Char('.');
- else
- break;
+ result += u'.';
}
return result;
}
+static bool checkUnicodeName(const QString &domainName, QUrl::AceProcessingOptions options)
+{
+ qsizetype lastIdx = 0;
+
+ DomainValidityChecker checker(true);
+
+ while (true) {
+ qsizetype idx = domainName.indexOf(u'.', lastIdx);
+ if (idx == -1)
+ idx = domainName.size();
+
+ const qsizetype labelLength = idx - lastIdx;
+ if (labelLength) {
+ const auto label = domainName.sliced(lastIdx, labelLength);
+
+ if (!checker.checkLabel(label, options))
+ return false;
+ }
+
+ if (idx == domainName.size())
+ break;
+
+ lastIdx = idx + 1;
+ }
+ return true;
+}
+
+QString qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot,
+ QUrl::AceProcessingOptions options)
+{
+ if (domain.isEmpty())
+ return {};
+
+ bool mappedToAscii;
+ const QString mapped = mapDomainName(domain, options, &mappedToAscii);
+ const QString normalized =
+ mappedToAscii ? mapped : mapped.normalized(QString::NormalizationForm_C);
+
+ if (normalized.isEmpty())
+ return {};
+
+ if (!mappedToAscii && !checkUnicodeName(normalized, options))
+ return {};
+
+ bool needsConversionToUnicode;
+ const QString aceResult = mappedToAscii ? normalized : convertToAscii(normalized, dot);
+ if (aceResult.isEmpty() || !checkAsciiDomainName(aceResult, dot, &needsConversionToUnicode))
+ return {};
+
+ if (op == ToAceOnly || !needsConversionToUnicode
+ || (!options.testFlag(QUrl::IgnoreIDNWhitelist) && !qt_is_idn_enabled(aceResult))) {
+ return aceResult;
+ }
+
+ return convertToUnicode(aceResult, options);
+}
+
/*!
\since 4.2
@@ -2599,6 +954,8 @@ QString qt_ACE_do(QStringView domain, AceOperation op, AceLeadingDot dot)
to have non-ASCII characters in their compositions.
See setIdnWhitelist() for the rationale of this list.
+
+ \sa AceProcessingOption
*/
QStringList QUrl::idnWhitelist()
{
@@ -2606,10 +963,10 @@ QStringList QUrl::idnWhitelist()
return *user_idn_whitelist;
static const QStringList list = [] {
QStringList list;
- list.reserve(idn_whitelist_size);
- unsigned int i = 0;
- while (i < idn_whitelist_size) {
- list << QLatin1String(idn_whitelist[i]);
+ list.reserve(idn_whitelist.count());
+ int i = 0;
+ while (i < idn_whitelist.count()) {
+ list << QLatin1StringView(idn_whitelist.at(i));
++i;
}
return list;
diff --git a/src/corelib/io/qurlquery.cpp b/src/corelib/io/qurlquery.cpp
index b889eb131b..31f3ee1d90 100644
--- a/src/corelib/io/qurlquery.cpp
+++ b/src/corelib/io/qurlquery.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qurlquery.h"
#include "qurl_p.h"
@@ -60,6 +24,8 @@ QT_BEGIN_NAMESPACE
\ingroup network
\ingroup shared
+ \compares equality
+
It is used to parse the query strings found in URLs like the following:
\image qurl-querystring.png
@@ -89,6 +55,19 @@ QT_BEGIN_NAMESPACE
sequences not decodable to UTF-8). For that reason, the percent character is
always represented by the string "%25".
+ All of the setter methods and the query methods like hasQueryItem() in
+ QUrlQuery take encoded forms only. Unlike in QUrl, there's no optional
+ parameter to specify that the strings being passed are decoded. If
+ improperly-encoded strings are passed to the setter or query methods,
+ QUrlQuery will attempt to recover instead of failing. That is to say, all
+ functions in this class parse their string arguments as if the
+ QUrl::TolerantMode decoding mode was specified.
+
+ Application code should strive to always ensure proper encoding and not rely
+ on TolerantMode parsing fixing the strings. Notably, all user input must be
+ first percent-encoded using QUrl::toPercentEncoding() or similar functions
+ before being passed to the functions in this class.
+
\section2 Handling of spaces and plus ("+")
Web browsers usually encode spaces found in HTML FORM elements to a plus sign
@@ -146,14 +125,14 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QUrlQuery::QUrlQuery(std::initializer_list<QPair<QString, QString>> list)
+ \fn QUrlQuery::QUrlQuery(std::initializer_list<std::pair<QString, QString>> list)
\since 5.13
Constructs a QUrlQuery object from the \a list of key/value pair.
*/
-typedef QList<QPair<QString, QString> > Map;
+typedef QList<std::pair<QString, QString> > Map;
class QUrlQueryPrivate : public QSharedData
{
@@ -169,7 +148,7 @@ public:
void setQuery(const QString &query);
void addQueryItem(const QString &key, const QString &value)
- { itemList.append(qMakePair(recodeFromUser(key), recodeFromUser(value))); }
+ { itemList.append(std::make_pair(recodeFromUser(key), recodeFromUser(value))); }
int findRecodedKey(const QString &key, int from = 0) const
{
for (int i = from; i < itemList.size(); ++i)
@@ -313,17 +292,17 @@ void QUrlQueryPrivate::setQuery(const QString &query)
if (delimiter == pos) {
// the value delimiter wasn't found, store a null value
- itemList.append(qMakePair(key, QString()));
+ itemList.append(std::make_pair(key, QString()));
} else if (delimiter + 1 == pos) {
// if the delimiter was found but the value is empty, store empty-but-not-null
- itemList.append(qMakePair(key, QString(0, Qt::Uninitialized)));
+ itemList.append(std::make_pair(key, QString(0, Qt::Uninitialized)));
} else {
QString value;
if (!qt_urlRecode(value, QStringView{delimiter + 1, pos},
QUrl::DecodeReserved,
prettyDecodedActions))
value = QString(delimiter + 1, pos - delimiter - 1);
- itemList.append(qMakePair(key, value));
+ itemList.append(std::make_pair(key, value));
}
if (pos != end)
@@ -387,6 +366,16 @@ QUrlQuery::QUrlQuery(const QUrlQuery &other)
}
/*!
+ \since 6.5
+ Moves the contents of the \a other QUrlQuery object, including the query
+ delimiters.
+*/
+QUrlQuery::QUrlQuery(QUrlQuery &&other) noexcept
+ : d(std::move(other.d))
+{
+}
+
+/*!
Copies the contents of the \a other QUrlQuery object, including the query
delimiters.
*/
@@ -412,19 +401,26 @@ QUrlQuery::~QUrlQuery()
}
/*!
- Returns \c true if this object and the \a other object contain the same
+ \fn bool QUrlQuery::operator==(const QUrlQuery &lhs, const QUrlQuery &rhs)
+
+ Returns \c true if QUrlQuery objects \a lhs and \a rhs contain the same
contents, in the same order, and use the same query delimiters.
*/
-bool QUrlQuery::operator ==(const QUrlQuery &other) const
+
+bool comparesEqual(const QUrlQuery &lhs, const QUrlQuery &rhs)
{
- if (d == other.d)
+ if (lhs.d == rhs.d)
return true;
- if (d && other.d)
+ if (lhs.d && rhs.d)
// keep in sync with qHash(QUrlQuery):
- return d->valueDelimiter == other.d->valueDelimiter &&
- d->pairDelimiter == other.d->pairDelimiter &&
- d->itemList == other.d->itemList;
- return false;
+ return lhs.d->valueDelimiter == rhs.d->valueDelimiter &&
+ lhs.d->pairDelimiter == rhs.d->pairDelimiter &&
+ lhs.d->itemList == rhs.d->itemList;
+
+ const QUrlQueryPrivate *x = lhs.d ? lhs.d.data() : rhs.d.data();
+ return x->valueDelimiter == QUrlQuery::defaultQueryValueDelimiter() &&
+ x->pairDelimiter == QUrlQuery::defaultQueryPairDelimiter() &&
+ x->itemList.isEmpty();
}
/*!
@@ -538,7 +534,7 @@ QString QUrlQuery::query(QUrl::ComponentFormattingOptions encoding) const
{
int size = 0;
for ( ; it != end; ++it)
- size += it->first.length() + 1 + it->second.length() + 1;
+ size += it->first.size() + 1 + it->second.size() + 1;
result.reserve(size + size / 4);
}
@@ -567,7 +563,7 @@ QString QUrlQuery::query(QUrl::ComponentFormattingOptions encoding) const
representation of the keys and values of the query string are
percent encoded when returned in query().
- If \a valueDelimiter is set to '(' and \a pairDelimiter is ')',
+ If \a valueDelimiter is set to ',' and \a pairDelimiter is ';',
the above query string would instead be represented like this:
\snippet code/src_corelib_io_qurl.cpp 4
@@ -578,7 +574,7 @@ QString QUrlQuery::query(QUrl::ComponentFormattingOptions encoding) const
\snippet code/src_corelib_io_qurlquery.cpp 0
Use of other characters is not supported and may result in unexpected
- behaviour. This method does not verify that you passed a valid delimiter.
+ behavior. This method does not verify that you passed a valid delimiter.
\sa queryValueDelimiter(), queryPairDelimiter()
*/
@@ -618,16 +614,18 @@ QChar QUrlQuery::queryPairDelimiter() const
as the same, like HTML forms do. If you need spaces to be represented as
plus signs, use actual plus signs.
+ \note The keys and values are expected to be in percent-encoded form.
+
\sa queryItems(), isEmpty()
*/
-void QUrlQuery::setQueryItems(const QList<QPair<QString, QString> > &query)
+void QUrlQuery::setQueryItems(const QList<std::pair<QString, QString> > &query)
{
clear();
if (query.isEmpty())
return;
QUrlQueryPrivate *dd = d;
- QList<QPair<QString, QString> >::const_iterator it = query.constBegin(),
+ QList<std::pair<QString, QString> >::const_iterator it = query.constBegin(),
end = query.constEnd();
for ( ; it != end; ++it)
dd->addQueryItem(it->first, it->second);
@@ -641,20 +639,20 @@ void QUrlQuery::setQueryItems(const QList<QPair<QString, QString> > &query)
\sa setQueryItems(), {encoding}{Encoding}
*/
-QList<QPair<QString, QString> > QUrlQuery::queryItems(QUrl::ComponentFormattingOptions encoding) const
+QList<std::pair<QString, QString> > QUrlQuery::queryItems(QUrl::ComponentFormattingOptions encoding) const
{
if (!d)
- return QList<QPair<QString, QString> >();
+ return QList<std::pair<QString, QString> >();
if (idempotentRecodeToUser(encoding))
return d->itemList;
- QList<QPair<QString, QString> > result;
+ QList<std::pair<QString, QString> > result;
Map::const_iterator it = d->itemList.constBegin();
Map::const_iterator end = d->itemList.constEnd();
- result.reserve(d->itemList.count());
+ result.reserve(d->itemList.size());
for ( ; it != end; ++it)
- result << qMakePair(d->recodeToUser(it->first, encoding),
- d->recodeToUser(it->second, encoding));
+ result << std::make_pair(d->recodeToUser(it->first, encoding),
+ d->recodeToUser(it->second, encoding));
return result;
}
@@ -662,6 +660,8 @@ QList<QPair<QString, QString> > QUrlQuery::queryItems(QUrl::ComponentFormattingO
Returns \c true if there is a query string pair whose key is equal
to \a key from the URL.
+ \note The key expected to be in percent-encoded form.
+
\sa addQueryItem(), queryItemValue()
*/
bool QUrlQuery::hasQueryItem(const QString &key) const
@@ -680,6 +680,8 @@ bool QUrlQuery::hasQueryItem(const QString &key) const
as the same, like HTML forms do. If you need spaces to be represented as
plus signs, use actual plus signs.
+ \note The key and value strings are expected to be in percent-encoded form.
+
\sa hasQueryItem(), queryItemValue()
*/
void QUrlQuery::addQueryItem(const QString &key, const QString &value)
@@ -698,6 +700,8 @@ void QUrlQuery::addQueryItem(const QString &key, const QString &value)
one found, in the order they were present in the query string or added
using addQueryItem().
+ \note The key is expected to be in percent-encoded form.
+
\sa addQueryItem(), allQueryItemValues(), {encoding}{Encoding}
*/
QString QUrlQuery::queryItemValue(const QString &key, QUrl::ComponentFormattingOptions encoding) const
@@ -716,6 +720,8 @@ QString QUrlQuery::queryItemValue(const QString &key, QUrl::ComponentFormattingO
the URL, using the options specified in \a encoding to encode the return
value. If the key \a key is not found, this function returns an empty list.
+ \note The key is expected to be in percent-encoded form.
+
\sa queryItemValue(), addQueryItem()
*/
QStringList QUrlQuery::allQueryItemValues(const QString &key, QUrl::ComponentFormattingOptions encoding) const
@@ -738,14 +744,17 @@ QStringList QUrlQuery::allQueryItemValues(const QString &key, QUrl::ComponentFor
item in the order they were present in the query string or added with
addQueryItem().
+ \note The key is expected to be in percent-encoded form.
+
\sa removeAllQueryItems()
*/
void QUrlQuery::removeQueryItem(const QString &key)
{
if (d.constData()) {
- Map::iterator it = d->findKey(key);
- if (it != d->itemList.end())
- d->itemList.erase(it);
+ auto *p = d.data();
+ Map::iterator it = p->findKey(key);
+ if (it != p->itemList.end())
+ p->itemList.erase(it);
}
}
@@ -753,17 +762,19 @@ void QUrlQuery::removeQueryItem(const QString &key)
Removes all the query string pairs whose key is equal to \a key
from the URL.
+ \note The key is expected to be in percent-encoded form.
+
\sa removeQueryItem()
*/
void QUrlQuery::removeAllQueryItems(const QString &key)
{
if (d.constData()) {
- const QString encodedKey = d->recodeFromUser(key);
- auto firstEqualsEncodedKey = [&encodedKey](const QPair<QString, QString> &item) {
+ auto *p = d.data();
+ const QString encodedKey = p->recodeFromUser(key);
+ auto firstEqualsEncodedKey = [&encodedKey](const std::pair<QString, QString> &item) {
return item.first == encodedKey;
};
- const auto end = d->itemList.end();
- d->itemList.erase(std::remove_if(d->itemList.begin(), end, firstEqualsEncodedKey), end);
+ p->itemList.removeIf(firstEqualsEncodedKey);
}
}
@@ -804,10 +815,15 @@ void QUrlQuery::removeAllQueryItems(const QString &key)
*/
/*!
- \fn bool QUrlQuery::operator!=(const QUrlQuery &other) const
+ \fn bool QUrlQuery::operator!=(const QUrlQuery &lhs, const QUrlQuery &rhs)
- Returns \c true if \a other is not equal to this QUrlQuery. Otherwise, returns \c false.
+ Returns \c true if the QUrlQuery object \a rhs is not equal to \a lhs.
+ Otherwise, returns \c false.
\sa operator==()
*/
QT_END_NAMESPACE
+
+#undef decode
+#undef leave
+#undef encode
diff --git a/src/corelib/io/qurlquery.h b/src/corelib/io/qurlquery.h
index d91bd98e0d..061107606e 100644
--- a/src/corelib/io/qurlquery.h
+++ b/src/corelib/io/qurlquery.h
@@ -1,53 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QURLQUERY_H
#define QURLQUERY_H
-#include <QtCore/qpair.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qurl.h>
-#if QT_DEPRECATED_SINCE(5,0)
-#include <QtCore/qstringlist.h>
-#endif
-
#include <initializer_list>
QT_BEGIN_NAMESPACE
@@ -61,23 +22,26 @@ public:
QUrlQuery();
explicit QUrlQuery(const QUrl &url);
explicit QUrlQuery(const QString &queryString);
- QUrlQuery(std::initializer_list<QPair<QString, QString>> list)
+ QUrlQuery(std::initializer_list<std::pair<QString, QString>> list)
: QUrlQuery()
{
- for (const QPair<QString, QString> &item : list)
+ for (const std::pair<QString, QString> &item : list)
addQueryItem(item.first, item.second);
}
QUrlQuery(const QUrlQuery &other);
+ QUrlQuery(QUrlQuery &&other) noexcept;
QUrlQuery &operator=(const QUrlQuery &other);
- QUrlQuery &operator=(QUrlQuery &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QUrlQuery)
~QUrlQuery();
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QUrlQuery &other) const;
bool operator!=(const QUrlQuery &other) const
- { return !(*this == other); }
+ { return !operator==(other); }
+#endif
- void swap(QUrlQuery &other) noexcept { qSwap(d, other.d); }
+ void swap(QUrlQuery &other) noexcept { d.swap(other.d); }
bool isEmpty() const;
bool isDetached() const;
@@ -92,8 +56,8 @@ public:
QChar queryValueDelimiter() const;
QChar queryPairDelimiter() const;
- void setQueryItems(const QList<QPair<QString, QString> > &query);
- QList<QPair<QString, QString> > queryItems(QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const;
+ void setQueryItems(const QList<std::pair<QString, QString> > &query);
+ QList<std::pair<QString, QString> > queryItems(QUrl::ComponentFormattingOptions encoding = QUrl::PrettyDecoded) const;
bool hasQueryItem(const QString &key) const;
void addQueryItem(const QString &key, const QString &value);
@@ -106,9 +70,12 @@ public:
static constexpr char16_t defaultQueryPairDelimiter() noexcept { return u'&'; }
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QUrlQuery &lhs, const QUrlQuery &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QUrlQuery)
friend class QUrl;
friend Q_CORE_EXPORT size_t qHash(const QUrlQuery &key, size_t seed) noexcept;
QSharedDataPointer<QUrlQueryPrivate> d;
+
public:
typedef QSharedDataPointer<QUrlQueryPrivate> DataPtr;
inline DataPtr &data_ptr() { return d; }
@@ -116,64 +83,6 @@ public:
Q_DECLARE_SHARED(QUrlQuery)
-#if QT_DEPRECATED_SINCE(5,0)
-inline void QUrl::setQueryItems(const QList<QPair<QString, QString> > &qry)
-{ QUrlQuery q(*this); q.setQueryItems(qry); setQuery(q); }
-inline void QUrl::addQueryItem(const QString &key, const QString &value)
-{ QUrlQuery q(*this); q.addQueryItem(key, value); setQuery(q); }
-inline QList<QPair<QString, QString> > QUrl::queryItems() const
-{ return QUrlQuery(*this).queryItems(); }
-inline bool QUrl::hasQueryItem(const QString &key) const
-{ return QUrlQuery(*this).hasQueryItem(key); }
-inline QString QUrl::queryItemValue(const QString &key) const
-{ return QUrlQuery(*this).queryItemValue(key); }
-inline QStringList QUrl::allQueryItemValues(const QString &key) const
-{ return QUrlQuery(*this).allQueryItemValues(key); }
-inline void QUrl::removeQueryItem(const QString &key)
-{ QUrlQuery q(*this); q.removeQueryItem(key); setQuery(q); }
-inline void QUrl::removeAllQueryItems(const QString &key)
-{ QUrlQuery q(*this); q.removeAllQueryItems(key); setQuery(q); }
-
-inline void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
-{ QUrlQuery q(*this); q.addQueryItem(fromEncodedComponent_helper(key), fromEncodedComponent_helper(value)); setQuery(q); }
-inline bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
-{ return QUrlQuery(*this).hasQueryItem(fromEncodedComponent_helper(key)); }
-inline QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
-{ return QUrlQuery(*this).queryItemValue(fromEncodedComponent_helper(key), QUrl::FullyEncoded).toLatin1(); }
-inline void QUrl::removeEncodedQueryItem(const QByteArray &key)
-{ QUrlQuery q(*this); q.removeQueryItem(fromEncodedComponent_helper(key)); setQuery(q); }
-inline void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
-{ QUrlQuery q(*this); q.removeAllQueryItems(fromEncodedComponent_helper(key)); setQuery(q); }
-
-inline void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &qry)
-{
- QUrlQuery q;
- QList<QPair<QByteArray, QByteArray> >::ConstIterator it = qry.constBegin();
- for ( ; it != qry.constEnd(); ++it)
- q.addQueryItem(fromEncodedComponent_helper(it->first), fromEncodedComponent_helper(it->second));
- setQuery(q);
-}
-inline QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
-{
- QList<QPair<QString, QString> > items = QUrlQuery(*this).queryItems(QUrl::FullyEncoded);
- QList<QPair<QString, QString> >::ConstIterator it = items.constBegin();
- QList<QPair<QByteArray, QByteArray> > result;
- result.reserve(items.size());
- for ( ; it != items.constEnd(); ++it)
- result << qMakePair(it->first.toLatin1(), it->second.toLatin1());
- return result;
-}
-inline QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
-{
- const QStringList items = QUrlQuery(*this).allQueryItemValues(fromEncodedComponent_helper(key), QUrl::FullyEncoded);
- QList<QByteArray> result;
- result.reserve(items.size());
- for (const QString &item : items)
- result << item.toLatin1();
- return result;
-}
-#endif
-
QT_END_NAMESPACE
#endif // QURLQUERY_H
diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp
index ad23588978..60dad31a3e 100644
--- a/src/corelib/io/qurlrecode.cpp
+++ b/src/corelib/io/qurlrecode.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qurl.h"
#include "private/qstringconverter_p.h"
@@ -167,48 +131,45 @@ static const uchar reservedMask[96] = {
0xff // BSKP
};
-static inline bool isHex(ushort c)
+static inline bool isHex(char16_t c)
{
- return (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F') ||
- (c >= '0' && c <= '9');
+ return (c >= u'a' && c <= u'f') || (c >= u'A' && c <= u'F') || (c >= u'0' && c <= u'9');
}
-static inline bool isUpperHex(ushort c)
+static inline bool isUpperHex(char16_t c)
{
// undefined behaviour if c isn't an hex char!
return c < 0x60;
}
-static inline ushort toUpperHex(ushort c)
+static inline char16_t toUpperHex(char16_t c)
{
return isUpperHex(c) ? c : c - 0x20;
}
-static inline ushort decodeNibble(ushort c)
+static inline ushort decodeNibble(char16_t c)
{
- return c >= 'a' ? c - 'a' + 0xA :
- c >= 'A' ? c - 'A' + 0xA : c - '0';
+ return c >= u'a' ? c - u'a' + 0xA : c >= u'A' ? c - u'A' + 0xA : c - u'0';
}
// if the sequence at input is 2*HEXDIG, returns its decoding
// returns -1 if it isn't.
// assumes that the range has been checked already
-static inline ushort decodePercentEncoding(const ushort *input)
+static inline char16_t decodePercentEncoding(const char16_t *input)
{
- ushort c1 = input[1];
- ushort c2 = input[2];
+ char16_t c1 = input[1];
+ char16_t c2 = input[2];
if (!isHex(c1) || !isHex(c2))
- return ushort(-1);
+ return char16_t(-1);
return decodeNibble(c1) << 4 | decodeNibble(c2);
}
-static inline ushort encodeNibble(ushort c)
+static inline char16_t encodeNibble(ushort c)
{
- return ushort(QtMiscUtils::toHexUpper(c));
+ return QtMiscUtils::toHexUpper(c);
}
-static void ensureDetached(QString &result, ushort *&output, const ushort *begin, const ushort *input, const ushort *end,
+static void ensureDetached(QString &result, char16_t *&output, const char16_t *begin, const char16_t *input, const char16_t *end,
int add = 0)
{
if (!output) {
@@ -221,7 +182,7 @@ static void ensureDetached(QString &result, ushort *&output, const ushort *begin
result.resize(origSize + spaceNeeded);
// we know that resize() above detached, so we bypass the reference count check
- output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData()))
+ output = const_cast<char16_t *>(reinterpret_cast<const char16_t *>(result.constData()))
+ origSize;
// copy the chars we've already processed
@@ -260,7 +221,7 @@ struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii
static const bool allowNonCharacters = false;
// override: our "bytes" are three percent-encoded UTF-16 characters
- static void appendByte(ushort *&ptr, uchar b)
+ static void appendByte(char16_t *&ptr, uchar b)
{
// b >= 0x80, by construction, so percent-encode
*ptr++ = '%';
@@ -268,9 +229,9 @@ struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii
*ptr++ = encodeNibble(b & 0xf);
}
- static uchar peekByte(const ushort *ptr, qsizetype n = 0)
+ static uchar peekByte(const char16_t *ptr, qsizetype n = 0)
{
- // decodePercentEncoding returns ushort(-1) if it can't decode,
+ // decodePercentEncoding returns char16_t(-1) if it can't decode,
// which means we return 0xff, which is not a valid continuation byte.
// If ptr[i * 3] is not '%', we'll multiply by zero and return 0,
// also not a valid continuation byte (if it's '%', we multiply by 1).
@@ -278,12 +239,12 @@ struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii
* uchar(ptr[n * 3] == '%');
}
- static qptrdiff availableBytes(const ushort *ptr, const ushort *end)
+ static qptrdiff availableBytes(const char16_t *ptr, const char16_t *end)
{
return (end - ptr) / 3;
}
- static void advanceByte(const ushort *&ptr, int n = 1)
+ static void advanceByte(const char16_t *&ptr, int n = 1)
{
ptr += n * 3;
}
@@ -291,11 +252,11 @@ struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii
}
// returns true if we performed an UTF-8 decoding
-static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input,
- const ushort *end, ushort decoded)
+static bool encodedUtf8ToUtf16(QString &result, char16_t *&output, const char16_t *begin,
+ const char16_t *&input, const char16_t *end, char16_t decoded)
{
- uint ucs4, *dst = &ucs4;
- const ushort *src = input + 3;// skip the %XX that yielded \a decoded
+ char32_t ucs4 = 0, *dst = &ucs4;
+ const char16_t *src = input + 3;// skip the %XX that yielded \a decoded
int charsNeeded = QUtf8Functions::fromUtf8<QUrlUtf8Traits>(decoded, dst, src, end);
if (charsNeeded < 0)
return false;
@@ -318,8 +279,8 @@ static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *b
return true;
}
-static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort *begin,
- const ushort *&input, const ushort *end, ushort decoded)
+static void unicodeToEncodedUtf8(QString &result, char16_t *&output, const char16_t *begin,
+ const char16_t *&input, const char16_t *end, char16_t decoded)
{
// calculate the utf8 length and ensure enough space is available
int utf8len = QChar::isHighSurrogate(decoded) ? 4 : decoded >= 0x800 ? 3 : 2;
@@ -332,14 +293,14 @@ static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort
} else {
// verify that there's enough space or expand
int charsRemaining = end - input - 1; // not including this one
- int pos = output - reinterpret_cast<const ushort *>(result.constData());
+ int pos = output - reinterpret_cast<const char16_t *>(result.constData());
int spaceRemaining = result.size() - pos;
if (spaceRemaining < 3*charsRemaining + 3*utf8len) {
// must resize
result.resize(result.size() + 3*utf8len);
// we know that resize() above detached, so we bypass the reference count check
- output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData()));
+ output = const_cast<char16_t *>(reinterpret_cast<const char16_t *>(result.constData()));
output += pos;
}
}
@@ -372,16 +333,17 @@ static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort
}
}
-static int recode(QString &result, const ushort *begin, const ushort *end, QUrl::ComponentFormattingOptions encoding,
- const uchar *actionTable, bool retryBadEncoding)
+static int recode(QString &result, const char16_t *begin, const char16_t *end,
+ QUrl::ComponentFormattingOptions encoding, const uchar *actionTable,
+ bool retryBadEncoding)
{
const int origSize = result.size();
- const ushort *input = begin;
- ushort *output = nullptr;
+ const char16_t *input = begin;
+ char16_t *output = nullptr;
EncodingAction action = EncodeCharacter;
for ( ; input != end; ++input) {
- ushort c;
+ char16_t c;
// try a run where no change is necessary
for ( ; input != end; ++input) {
c = *input;
@@ -398,7 +360,7 @@ static int recode(QString &result, const ushort *begin, const ushort *end, QUrl:
break;
non_trivial:
- uint decoded;
+ char16_t decoded;
if (c == '%' && retryBadEncoding) {
// always write "%25"
ensureDetached(result, output, begin, input, end);
@@ -408,7 +370,7 @@ non_trivial:
continue;
} else if (c == '%') {
// check if the input is valid
- if (input + 2 >= end || (decoded = decodePercentEncoding(input)) == ushort(-1)) {
+ if (input + 2 >= end || (decoded = decodePercentEncoding(input)) == char16_t(-1)) {
// not valid, retry
result.resize(origSize);
return recode(result, begin, end, encoding, actionTable, true);
@@ -468,7 +430,7 @@ non_trivial:
}
if (output) {
- int len = output - reinterpret_cast<const ushort *>(result.constData());
+ int len = output - reinterpret_cast<const char16_t *>(result.constData());
result.truncate(len);
return len - origSize;
}
@@ -603,7 +565,8 @@ static qsizetype decode(QString &appendTo, QStringView in)
if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) {
// badly-encoded data
appendTo.resize(origSize + (end - begin));
- memcpy(static_cast<void *>(appendTo.begin() + origSize), static_cast<const void *>(begin), (end - begin) * sizeof(ushort));
+ memcpy(static_cast<void *>(appendTo.begin() + origSize),
+ static_cast<const void *>(begin), (end - begin) * sizeof(*end));
return end - begin;
}
@@ -677,7 +640,7 @@ qt_urlRecode(QString &appendTo, QStringView in,
{
uchar actionTable[sizeof defaultActionTable];
if ((encoding & QUrl::FullyDecoded) == QUrl::FullyDecoded) {
- return int(decode(appendTo, in));
+ return decode(appendTo, in);
}
memcpy(actionTable, defaultActionTable, sizeof actionTable);
@@ -691,56 +654,8 @@ qt_urlRecode(QString &appendTo, QStringView in,
actionTable[uchar(*p) - ' '] = *p >> 8;
}
- return recode(appendTo, reinterpret_cast<const ushort *>(in.begin()), reinterpret_cast<const ushort *>(in.end()),
- encoding, actionTable, false);
-}
-
-// qstring.cpp
-bool qt_is_ascii(const char *&ptr, const char *end) noexcept;
-
-/*!
- \internal
- \since 5.0
-
- \a ba contains an 8-bit form of the component and it might be
- percent-encoded already. We can't use QString::fromUtf8 because it might
- contain non-UTF8 sequences. We can't use QByteArray::toPercentEncoding
- because it might already contain percent-encoded sequences. We can't use
- qt_urlRecode because it needs UTF-16 input.
-*/
-Q_AUTOTEST_EXPORT
-QString qt_urlRecodeByteArray(const QByteArray &ba)
-{
- if (ba.isNull())
- return QString();
-
- // scan ba for anything above or equal to 0x80
- // control points below 0x20 are fine in QString
- const char *in = ba.constData();
- const char *const end = ba.constEnd();
- if (qt_is_ascii(in, end)) {
- // no non-ASCII found, we're safe to convert to QString
- return QString::fromLatin1(ba, ba.size());
- }
-
- // we found something that we need to encode
- QByteArray intermediate = ba;
- intermediate.resize(ba.size() * 3 - (in - ba.constData()));
- uchar *out = reinterpret_cast<uchar *>(intermediate.data() + (in - ba.constData()));
- for ( ; in < end; ++in) {
- if (*in & 0x80) {
- // encode
- *out++ = '%';
- *out++ = encodeNibble(uchar(*in) >> 4);
- *out++ = encodeNibble(uchar(*in) & 0xf);
- } else {
- // keep
- *out++ = uchar(*in);
- }
- }
-
- // now it's safe to call fromLatin1
- return QString::fromLatin1(intermediate, out - reinterpret_cast<uchar *>(intermediate.data()));
+ return recode(appendTo, reinterpret_cast<const char16_t *>(in.begin()),
+ reinterpret_cast<const char16_t *>(in.end()), encoding, actionTable, false);
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 1f03ac5d5a..31d0dc1417 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -1,92 +1,66 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2021 Alex Trotsenko <alex1973tr@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowspipereader_p.h"
-#include "qiodevice_p.h"
-#include <qelapsedtimer.h>
-#include <qscopedvaluerollback.h>
+#include <qcoreapplication.h>
+#include <QMutexLocker>
+#include <QPointer>
QT_BEGIN_NAMESPACE
-QWindowsPipeReader::Overlapped::Overlapped(QWindowsPipeReader *reader)
- : pipeReader(reader)
-{
-}
-
-void QWindowsPipeReader::Overlapped::clear()
-{
- ZeroMemory(this, sizeof(OVERLAPPED));
-}
+using namespace Qt::StringLiterals;
+static const DWORD minReadBufferSize = 4096;
QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
: QObject(parent),
handle(INVALID_HANDLE_VALUE),
- overlapped(nullptr),
+ eventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
+ syncHandle(CreateEvent(NULL, TRUE, FALSE, NULL)),
+ waitObject(NULL),
readBufferMaxSize(0),
actualReadBufferSize(0),
- stopped(true),
+ pendingReadBytes(0),
+ lastError(ERROR_SUCCESS),
+ state(Stopped),
readSequenceStarted(false),
- notifiedCalled(false),
- pipeBroken(false),
+ pipeBroken(true),
readyReadPending(false),
- inReadyRead(false)
+ winEventActPosted(false)
{
- connect(this, &QWindowsPipeReader::_q_queueReadyRead,
- this, &QWindowsPipeReader::emitPendingReadyRead, Qt::QueuedConnection);
+ ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+ overlapped.hEvent = eventHandle;
+ waitObject = CreateThreadpoolWait(waitCallback, this, NULL);
+ if (waitObject == NULL)
+ qErrnoWarning("QWindowsPipeReader: CreateThreadpollWait failed.");
}
QWindowsPipeReader::~QWindowsPipeReader()
{
stop();
- delete overlapped;
+
+ // Wait for thread pool callback to complete, as it can be still
+ // executing some completion code.
+ WaitForThreadpoolWaitCallbacks(waitObject, FALSE);
+ CloseThreadpoolWait(waitObject);
+ CloseHandle(eventHandle);
+ CloseHandle(syncHandle);
}
/*!
Sets the handle to read from. The handle must be valid.
+ Do not call this function while the pipe is running.
*/
void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
{
readBuffer.clear();
actualReadBufferSize = 0;
+ readyReadPending = false;
+ pendingReadBytes = 0;
handle = hPipeReadEnd;
pipeBroken = false;
+ lastError = ERROR_SUCCESS;
}
/*!
@@ -95,19 +69,90 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
*/
void QWindowsPipeReader::stop()
{
- stopped = true;
+ cancelAsyncRead(Stopped);
+ pipeBroken = true;
+}
+
+/*!
+ Stops the asynchronous read sequence.
+ Reads all pending bytes into the internal buffer.
+ */
+void QWindowsPipeReader::drainAndStop()
+{
+ cancelAsyncRead(Draining);
+ pipeBroken = true;
+}
+
+/*!
+ Stops the asynchronous read sequence.
+ Clears the internal buffer and discards any pending data.
+ */
+void QWindowsPipeReader::stopAndClear()
+{
+ cancelAsyncRead(Stopped);
+ readBuffer.clear();
+ actualReadBufferSize = 0;
+ // QLocalSocket is supposed to write data in the 'Closing'
+ // state, so we don't set 'pipeBroken' flag here. Also, avoid
+ // setting this flag in checkForReadyRead().
+ lastError = ERROR_SUCCESS;
+}
+
+/*!
+ Stops the asynchronous read sequence.
+ */
+void QWindowsPipeReader::cancelAsyncRead(State newState)
+{
+ if (state != Running)
+ return;
+
+ mutex.lock();
+ state = newState;
if (readSequenceStarted) {
- overlapped->pipeReader = nullptr;
- if (!CancelIoEx(handle, overlapped)) {
+ // This can legitimately fail due to the GetOverlappedResult()
+ // in the callback not being locked. We ignore ERROR_NOT_FOUND
+ // in this case.
+ if (!CancelIoEx(handle, &overlapped)) {
const DWORD dwError = GetLastError();
if (dwError != ERROR_NOT_FOUND) {
qErrnoWarning(dwError, "QWindowsPipeReader: CancelIoEx on handle %p failed.",
handle);
}
}
- overlapped = nullptr; // The object will be deleted in the I/O callback.
- readSequenceStarted = false;
+
+ // Wait for callback to complete.
+ do {
+ mutex.unlock();
+ waitForNotification();
+ mutex.lock();
+ } while (readSequenceStarted);
}
+ mutex.unlock();
+
+ // Finish reading to keep the class state consistent. Note that
+ // signals are not emitted in the call below, as the caller is
+ // expected to do that synchronously.
+ consumePending();
+}
+
+/*!
+ Sets the size of internal read buffer.
+ */
+void QWindowsPipeReader::setMaxReadBufferSize(qint64 size)
+{
+ QMutexLocker locker(&mutex);
+ readBufferMaxSize = size;
+}
+
+/*!
+ Returns \c true if async operation is in progress, there is
+ pending data to read, or a read error is pending.
+*/
+bool QWindowsPipeReader::isReadOperationActive() const
+{
+ QMutexLocker locker(&mutex);
+ return readSequenceStarted || readyReadPending
+ || (lastError != ERROR_SUCCESS && !pipeBroken);
}
/*!
@@ -123,10 +168,9 @@ qint64 QWindowsPipeReader::bytesAvailable() const
*/
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
{
- if (pipeBroken && actualReadBufferSize == 0)
- return 0; // signal EOF
-
+ QMutexLocker locker(&mutex);
qint64 readSoFar;
+
// If startAsyncRead() has read data, copy it to its destination.
if (maxlen == 1 && actualReadBufferSize > 0) {
*data = readBuffer.getChar();
@@ -138,8 +182,31 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
}
if (!pipeBroken) {
- if (!readSequenceStarted && !stopped)
- startAsyncRead();
+ startAsyncReadHelper(&locker);
+ if (readSoFar == 0)
+ return -2; // signal EWOULDBLOCK
+ }
+
+ return readSoFar;
+}
+
+/*!
+ Reads a line from the internal buffer, but no more than \c{maxlen}
+ characters. A terminating '\0' byte is always appended to \c{data},
+ so \c{maxlen} must be larger than 1.
+ */
+qint64 QWindowsPipeReader::readLine(char *data, qint64 maxlen)
+{
+ QMutexLocker locker(&mutex);
+ qint64 readSoFar = 0;
+
+ if (actualReadBufferSize > 0) {
+ readSoFar = readBuffer.readLine(data, qMin(actualReadBufferSize + 1, maxlen));
+ actualReadBufferSize -= readSoFar;
+ }
+
+ if (!pipeBroken) {
+ startAsyncReadHelper(&locker);
if (readSoFar == 0)
return -2; // signal EWOULDBLOCK
}
@@ -147,188 +214,269 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
return readSoFar;
}
+/*!
+ Skips up to \c{maxlen} bytes from the internal read buffer.
+ */
+qint64 QWindowsPipeReader::skip(qint64 maxlen)
+{
+ QMutexLocker locker(&mutex);
+
+ const qint64 skippedSoFar = readBuffer.skip(qMin(actualReadBufferSize, maxlen));
+ actualReadBufferSize -= skippedSoFar;
+
+ if (!pipeBroken) {
+ startAsyncReadHelper(&locker);
+ if (skippedSoFar == 0)
+ return -2; // signal EWOULDBLOCK
+ }
+
+ return skippedSoFar;
+}
+
+/*!
+ Returns \c true if a complete line of data can be read from the buffer.
+ */
bool QWindowsPipeReader::canReadLine() const
{
+ QMutexLocker locker(&mutex);
return readBuffer.indexOf('\n', actualReadBufferSize) >= 0;
}
/*!
- \internal
- Will be called whenever the read operation completes.
+ Starts an asynchronous read sequence on the pipe.
*/
-void QWindowsPipeReader::notified(DWORD errorCode, DWORD numberOfBytesRead)
+void QWindowsPipeReader::startAsyncRead()
{
- notifiedCalled = true;
- readSequenceStarted = false;
-
- switch (errorCode) {
- case ERROR_SUCCESS:
- break;
- case ERROR_MORE_DATA:
- // This is not an error. We're connected to a message mode
- // pipe and the message didn't fit into the pipe's system
- // buffer. We will read the remaining data in the next call.
- break;
- case ERROR_BROKEN_PIPE:
- case ERROR_PIPE_NOT_CONNECTED:
- pipeBroken = true;
- break;
- case ERROR_OPERATION_ABORTED:
- if (stopped)
- break;
- Q_FALLTHROUGH();
- default:
- emit winError(errorCode, QLatin1String("QWindowsPipeReader::notified"));
- pipeBroken = true;
- break;
- }
+ QMutexLocker locker(&mutex);
+ startAsyncReadHelper(&locker);
+}
- // After the reader was stopped, the only reason why this function can be called is the
- // completion of a cancellation. No signals should be emitted, and no new read sequence should
- // be started in this case.
- if (stopped)
+void QWindowsPipeReader::startAsyncReadHelper(QMutexLocker<QMutex> *locker)
+{
+ if (readSequenceStarted || lastError != ERROR_SUCCESS)
return;
- if (pipeBroken) {
- emit pipeClosed();
+ state = Running;
+ startAsyncReadLocked();
+
+ // Do not post the event, if the read operation will be completed asynchronously.
+ if (!readyReadPending && lastError == ERROR_SUCCESS)
return;
- }
- actualReadBufferSize += numberOfBytesRead;
- readBuffer.truncate(actualReadBufferSize);
- startAsyncRead();
- if (!readyReadPending) {
- readyReadPending = true;
- emit _q_queueReadyRead(QWindowsPipeReader::QPrivateSignal());
+ if (!winEventActPosted) {
+ winEventActPosted = true;
+ locker->unlock();
+ QCoreApplication::postEvent(this, new QEvent(QEvent::WinEventAct));
+ } else {
+ locker->unlock();
}
+
+ SetEvent(syncHandle);
}
/*!
- \internal
- Reads data from the pipe into the readbuffer.
+ Starts a new read sequence. Thread-safety should be ensured
+ by the caller.
*/
-void QWindowsPipeReader::startAsyncRead()
+void QWindowsPipeReader::startAsyncReadLocked()
{
- const DWORD minReadBufferSize = 4096;
- qint64 bytesToRead = qMax(checkPipeState(), minReadBufferSize);
- if (pipeBroken)
+ // Determine the number of bytes to read.
+ qint64 bytesToRead = qMax(checkPipeState(), state == Running ? minReadBufferSize : 0);
+
+ // This can happen only while draining; just do nothing in this case.
+ if (bytesToRead == 0)
return;
- if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
- bytesToRead = readBufferMaxSize - readBuffer.size();
- if (bytesToRead <= 0) {
- // Buffer is full. User must read data from the buffer
- // before we can read more from the pipe.
- return;
+ while (lastError == ERROR_SUCCESS) {
+ if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
+ bytesToRead = readBufferMaxSize - readBuffer.size();
+ if (bytesToRead <= 0) {
+ // Buffer is full. User must read data from the buffer
+ // before we can read more from the pipe.
+ return;
+ }
}
- }
- char *ptr = readBuffer.reserve(bytesToRead);
-
- stopped = false;
- readSequenceStarted = true;
- if (!overlapped)
- overlapped = new Overlapped(this);
- overlapped->clear();
- if (!ReadFileEx(handle, ptr, bytesToRead, overlapped, &readFileCompleted)) {
- readSequenceStarted = false;
-
- const DWORD dwError = GetLastError();
- switch (dwError) {
- case ERROR_BROKEN_PIPE:
- case ERROR_PIPE_NOT_CONNECTED:
- // It may happen, that the other side closes the connection directly
- // after writing data. Then we must set the appropriate socket state.
- pipeBroken = true;
- emit pipeClosed();
- break;
- default:
- emit winError(dwError, QLatin1String("QWindowsPipeReader::startAsyncRead"));
- break;
+ char *ptr = readBuffer.reserve(bytesToRead);
+
+ // ReadFile() returns true, if the read operation completes synchronously.
+ // We don't need to call GetOverlappedResult() additionally, because
+ // 'numberOfBytesRead' is valid in this case.
+ DWORD numberOfBytesRead;
+ DWORD errorCode = ERROR_SUCCESS;
+ if (!ReadFile(handle, ptr, bytesToRead, &numberOfBytesRead, &overlapped)) {
+ errorCode = GetLastError();
+ if (errorCode == ERROR_IO_PENDING) {
+ Q_ASSERT(state == Running);
+ // Operation has been queued and will complete in the future.
+ readSequenceStarted = true;
+ SetThreadpoolWait(waitObject, eventHandle, NULL);
+ return;
+ }
+ }
+
+ if (!readCompleted(errorCode, numberOfBytesRead))
+ return;
+
+ // In the 'Draining' state, we have to get all the data with one call
+ // to ReadFile(). Note that message mode pipes are not supported here.
+ if (state == Draining) {
+ Q_ASSERT(bytesToRead == qint64(numberOfBytesRead));
+ return;
}
+
+ // We need to loop until all pending data has been read and an
+ // operation is queued for asynchronous completion.
+ // If the pipe is configured to work in message mode, we read
+ // the data in chunks.
+ bytesToRead = qMax(checkPipeState(), minReadBufferSize);
}
}
/*!
\internal
- Called when ReadFileEx finished the read operation.
+
+ Thread pool callback procedure.
*/
-void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
- OVERLAPPED *overlappedBase)
+void QWindowsPipeReader::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult)
{
- Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
- if (overlapped->pipeReader)
- overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered);
- else
- delete overlapped;
+ Q_UNUSED(instance);
+ Q_UNUSED(wait);
+ Q_UNUSED(waitResult);
+ QWindowsPipeReader *pipeReader = reinterpret_cast<QWindowsPipeReader *>(context);
+
+ // Get the result of the asynchronous operation.
+ DWORD numberOfBytesTransfered = 0;
+ DWORD errorCode = ERROR_SUCCESS;
+ if (!GetOverlappedResult(pipeReader->handle, &pipeReader->overlapped,
+ &numberOfBytesTransfered, FALSE))
+ errorCode = GetLastError();
+
+ pipeReader->mutex.lock();
+
+ pipeReader->readSequenceStarted = false;
+
+ // Do not overwrite error code, if error has been detected by
+ // checkPipeState() in waitForPipeClosed(). Also, if the reader was
+ // stopped, the only reason why this function can be called is the
+ // completion of a cancellation. No signals should be emitted, and
+ // no new read sequence should be started in this case.
+ if (pipeReader->lastError == ERROR_SUCCESS && pipeReader->state != Stopped) {
+ // Ignore ERROR_OPERATION_ABORTED. We have canceled the I/O operation
+ // specifically for flushing the pipe.
+ if (pipeReader->state == Draining && errorCode == ERROR_OPERATION_ABORTED)
+ errorCode = ERROR_SUCCESS;
+
+ if (pipeReader->readCompleted(errorCode, numberOfBytesTransfered))
+ pipeReader->startAsyncReadLocked();
+
+ if (pipeReader->state == Running && !pipeReader->winEventActPosted) {
+ pipeReader->winEventActPosted = true;
+ pipeReader->mutex.unlock();
+ QCoreApplication::postEvent(pipeReader, new QEvent(QEvent::WinEventAct));
+ } else {
+ pipeReader->mutex.unlock();
+ }
+ } else {
+ pipeReader->mutex.unlock();
+ }
+
+ // We set the event only after unlocking to avoid additional context
+ // switches due to the released thread immediately running into the lock.
+ SetEvent(pipeReader->syncHandle);
}
/*!
- \internal
- Returns the number of available bytes in the pipe.
- Sets QWindowsPipeReader::pipeBroken to true if the connection is broken.
+ Will be called whenever the read operation completes. Returns \c true if
+ no error occurred; otherwise returns \c false.
*/
-DWORD QWindowsPipeReader::checkPipeState()
+bool QWindowsPipeReader::readCompleted(DWORD errorCode, DWORD numberOfBytesRead)
{
- DWORD bytes;
- if (PeekNamedPipe(handle, nullptr, 0, nullptr, &bytes, nullptr))
- return bytes;
- if (!pipeBroken) {
- pipeBroken = true;
- emit pipeClosed();
+ // ERROR_MORE_DATA is not an error. We're connected to a message mode
+ // pipe and the message didn't fit into the pipe's system
+ // buffer. We will read the remaining data in the next call.
+ if (errorCode == ERROR_SUCCESS || errorCode == ERROR_MORE_DATA) {
+ readyReadPending = true;
+ pendingReadBytes += numberOfBytesRead;
+ readBuffer.truncate(actualReadBufferSize + pendingReadBytes);
+ return true;
}
- return 0;
-}
-bool QWindowsPipeReader::waitForNotification(int timeout)
-{
- QElapsedTimer t;
- t.start();
- notifiedCalled = false;
- int msecs = timeout;
- while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
- if (notifiedCalled)
- return true;
-
- // Some other I/O completion routine was called. Wait some more.
- msecs = qt_subtract_from_timeout(timeout, t.elapsed());
- if (!msecs)
- break;
- }
- return notifiedCalled;
+ lastError = errorCode;
+ return false;
}
-void QWindowsPipeReader::emitPendingReadyRead()
+/*!
+ Receives notification that the read operation has completed.
+ */
+bool QWindowsPipeReader::event(QEvent *e)
{
- if (readyReadPending) {
- readyReadPending = false;
- QScopedValueRollback<bool> guard(inReadyRead, true);
- emit readyRead();
+ if (e->type() == QEvent::WinEventAct) {
+ consumePendingAndEmit(true);
+ return true;
}
+ return QObject::event(e);
}
/*!
- Waits for the completion of the asynchronous read operation.
- Returns \c true, if we've emitted the readyRead signal (non-recursive case)
- or readyRead will be emitted by the event loop (recursive case).
+ Updates the read buffer size and emits pending signals in the main thread.
+ Returns \c true, if readyRead() was emitted.
*/
-bool QWindowsPipeReader::waitForReadyRead(int msecs)
+bool QWindowsPipeReader::consumePendingAndEmit(bool allowWinActPosting)
{
- if (readyReadPending) {
- if (!inReadyRead)
- emitPendingReadyRead();
- return true;
- }
+ ResetEvent(syncHandle);
+ mutex.lock();
- if (!readSequenceStarted)
- return false;
+ // Enable QEvent::WinEventAct posting.
+ if (allowWinActPosting)
+ winEventActPosted = false;
+
+ const bool emitReadyRead = consumePending();
+ const DWORD dwError = lastError;
- if (!waitForNotification(msecs))
+ mutex.unlock();
+
+ // Trigger 'pipeBroken' only once. This flag must be updated before
+ // emitting the readyRead() signal. Otherwise, the read sequence will
+ // be considered not finished, and we may hang if a slot connected
+ // to readyRead() calls waitForReadyRead().
+ const bool emitPipeClosed = (dwError != ERROR_SUCCESS && !pipeBroken);
+ if (emitPipeClosed)
+ pipeBroken = true;
+
+ // Disable any further processing, if the pipe was stopped.
+ // We are not allowed to emit signals in either 'Stopped'
+ // or 'Draining' state.
+ if (state != Running)
return false;
+ if (!emitPipeClosed) {
+ if (emitReadyRead)
+ emit readyRead();
+ } else {
+ QPointer<QWindowsPipeReader> alive(this);
+ if (emitReadyRead)
+ emit readyRead();
+ if (alive && dwError != ERROR_BROKEN_PIPE && dwError != ERROR_PIPE_NOT_CONNECTED)
+ emit winError(dwError, "QWindowsPipeReader::consumePendingAndEmit"_L1);
+ if (alive)
+ emit pipeClosed();
+ }
+
+ return emitReadyRead;
+}
+
+/*!
+ Updates the read buffer size. Returns \c true, if readyRead()
+ should be emitted. Thread-safety should be ensured by the caller.
+ */
+bool QWindowsPipeReader::consumePending()
+{
if (readyReadPending) {
- if (!inReadyRead)
- emitPendingReadyRead();
+ readyReadPending = false;
+ actualReadBufferSize += pendingReadBytes;
+ pendingReadBytes = 0;
return true;
}
@@ -336,22 +484,32 @@ bool QWindowsPipeReader::waitForReadyRead(int msecs)
}
/*!
- Waits until the pipe is closed.
+ Returns the number of available bytes in the pipe.
*/
-bool QWindowsPipeReader::waitForPipeClosed(int msecs)
+DWORD QWindowsPipeReader::checkPipeState()
{
- const int sleepTime = 10;
- QElapsedTimer stopWatch;
- stopWatch.start();
- forever {
- waitForReadyRead(0);
- checkPipeState();
- if (pipeBroken)
+ DWORD bytes;
+ if (PeekNamedPipe(handle, nullptr, 0, nullptr, &bytes, nullptr))
+ return bytes;
+
+ lastError = GetLastError();
+ return 0;
+}
+
+bool QWindowsPipeReader::waitForNotification()
+{
+ DWORD waitRet;
+ do {
+ waitRet = WaitForSingleObjectEx(syncHandle, INFINITE, TRUE);
+ if (waitRet == WAIT_OBJECT_0)
return true;
- if (stopWatch.hasExpired(msecs - sleepTime))
- return false;
- Sleep(sleepTime);
- }
+
+ // Some I/O completion routine was called. Wait some more.
+ } while (waitRet == WAIT_IO_COMPLETION);
+
+ return false;
}
QT_END_NAMESPACE
+
+#include "moc_qwindowspipereader_p.cpp"
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index c757753c9c..14db4f9313 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2021 Alex Trotsenko <alex1973tr@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSPIPEREADER_P_H
#define QWINDOWSPIPEREADER_P_H
@@ -52,6 +17,7 @@
//
#include <qobject.h>
+#include <qmutex.h>
#include <private/qringbuffer_p.h>
#include <qt_windows.h>
@@ -62,59 +28,68 @@ class Q_CORE_EXPORT QWindowsPipeReader : public QObject
{
Q_OBJECT
public:
- explicit QWindowsPipeReader(QObject *parent = 0);
+ explicit QWindowsPipeReader(QObject *parent = nullptr);
~QWindowsPipeReader();
void setHandle(HANDLE hPipeReadEnd);
void startAsyncRead();
void stop();
+ void drainAndStop();
+ void stopAndClear();
- void setMaxReadBufferSize(qint64 size) { readBufferMaxSize = size; }
+ void setMaxReadBufferSize(qint64 size);
qint64 maxReadBufferSize() const { return readBufferMaxSize; }
bool isPipeClosed() const { return pipeBroken; }
qint64 bytesAvailable() const;
qint64 read(char *data, qint64 maxlen);
+ qint64 readLine(char *data, qint64 maxlen);
+ qint64 skip(qint64 maxlen);
bool canReadLine() const;
- bool waitForReadyRead(int msecs);
- bool waitForPipeClosed(int msecs);
+ DWORD checkPipeState();
+ bool checkForReadyRead() { return consumePendingAndEmit(false); }
- bool isReadOperationActive() const { return readSequenceStarted; }
+ bool isReadOperationActive() const;
+ HANDLE syncEvent() const { return syncHandle; }
Q_SIGNALS:
void winError(ulong, const QString &);
void readyRead();
void pipeClosed();
- void _q_queueReadyRead(QPrivateSignal);
+
+protected:
+ bool event(QEvent *e) override;
private:
- static void CALLBACK readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
- OVERLAPPED *overlappedBase);
- void notified(DWORD errorCode, DWORD numberOfBytesRead);
- DWORD checkPipeState();
- bool waitForNotification(int timeout);
- void emitPendingReadyRead();
-
- class Overlapped : public OVERLAPPED
- {
- Q_DISABLE_COPY_MOVE(Overlapped)
- public:
- explicit Overlapped(QWindowsPipeReader *reader);
- void clear();
- QWindowsPipeReader *pipeReader;
- };
+ enum State { Stopped, Running, Draining };
+
+ void startAsyncReadHelper(QMutexLocker<QMutex> *locker);
+ void startAsyncReadLocked();
+ void cancelAsyncRead(State newState);
+ static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult);
+ bool readCompleted(DWORD errorCode, DWORD numberOfBytesRead);
+ bool waitForNotification();
+ bool consumePendingAndEmit(bool allowWinActPosting);
+ bool consumePending();
HANDLE handle;
- Overlapped *overlapped;
+ HANDLE eventHandle;
+ HANDLE syncHandle;
+ PTP_WAIT waitObject;
+ OVERLAPPED overlapped;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
qint64 actualReadBufferSize;
- bool stopped;
+ qint64 pendingReadBytes;
+ mutable QMutex mutex;
+ DWORD lastError;
+
+ State state;
bool readSequenceStarted;
- bool notifiedCalled;
bool pipeBroken;
bool readyReadPending;
- bool inReadyRead;
+ bool winEventActPosted;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 32536f495b..9d0f6a8a3e 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -1,234 +1,318 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2021 Alex Trotsenko <alex1973tr@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowspipewriter_p.h"
-#include "qiodevice_p.h"
-#include <qscopedvaluerollback.h>
+#include <qcoreapplication.h>
+#include <QMutexLocker>
+#include <QPointer>
QT_BEGIN_NAMESPACE
-QWindowsPipeWriter::Overlapped::Overlapped(QWindowsPipeWriter *pipeWriter)
- : pipeWriter(pipeWriter)
-{
-}
-
-void QWindowsPipeWriter::Overlapped::clear()
-{
- ZeroMemory(this, sizeof(OVERLAPPED));
-}
-
-
QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent)
: QObject(parent),
handle(pipeWriteEnd),
- overlapped(nullptr),
+ eventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
+ syncHandle(CreateEvent(NULL, TRUE, FALSE, NULL)),
+ waitObject(NULL),
pendingBytesWrittenValue(0),
+ lastError(ERROR_SUCCESS),
+ completionState(NoError),
stopped(true),
writeSequenceStarted(false),
- notifiedCalled(false),
bytesWrittenPending(false),
- inBytesWritten(false)
+ winEventActPosted(false)
{
- connect(this, &QWindowsPipeWriter::_q_queueBytesWritten,
- this, &QWindowsPipeWriter::emitPendingBytesWrittenValue, Qt::QueuedConnection);
+ ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+ overlapped.hEvent = eventHandle;
+ waitObject = CreateThreadpoolWait(waitCallback, this, NULL);
+ if (waitObject == NULL)
+ qErrnoWarning("QWindowsPipeWriter: CreateThreadpollWait failed.");
}
QWindowsPipeWriter::~QWindowsPipeWriter()
{
stop();
- delete overlapped;
+ CloseThreadpoolWait(waitObject);
+ CloseHandle(eventHandle);
+ CloseHandle(syncHandle);
}
-bool QWindowsPipeWriter::waitForWrite(int msecs)
+/*!
+ Assigns the handle to this writer. The handle must be valid.
+ Call this function if data was buffered before getting the handle.
+ */
+void QWindowsPipeWriter::setHandle(HANDLE hPipeWriteEnd)
{
- if (bytesWrittenPending) {
- emitPendingBytesWrittenValue();
- return true;
- }
+ Q_ASSERT(!stopped);
- if (!writeSequenceStarted)
- return false;
+ handle = hPipeWriteEnd;
+ QMutexLocker locker(&mutex);
+ startAsyncWriteHelper(&locker);
+}
- if (!waitForNotification(msecs))
- return false;
+/*!
+ Stops the asynchronous write sequence.
+ If the write sequence is running then the I/O operation is canceled.
+ */
+void QWindowsPipeWriter::stop()
+{
+ if (stopped)
+ return;
- if (bytesWrittenPending) {
- emitPendingBytesWrittenValue();
- return true;
+ mutex.lock();
+ stopped = true;
+ if (writeSequenceStarted) {
+ // Trying to disable callback before canceling the operation.
+ // Callback invocation is unnecessary here.
+ SetThreadpoolWait(waitObject, NULL, NULL);
+ if (!CancelIoEx(handle, &overlapped)) {
+ const DWORD dwError = GetLastError();
+ if (dwError != ERROR_NOT_FOUND) {
+ qErrnoWarning(dwError, "QWindowsPipeWriter: CancelIoEx on handle %p failed.",
+ handle);
+ }
+ }
+ writeSequenceStarted = false;
}
+ mutex.unlock();
- return false;
+ WaitForThreadpoolWaitCallbacks(waitObject, TRUE);
}
+/*!
+ Returns the number of bytes that are waiting to be written.
+ */
qint64 QWindowsPipeWriter::bytesToWrite() const
{
- return buffer.size() + pendingBytesWrittenValue;
+ QMutexLocker locker(&mutex);
+ return writeBuffer.size() + pendingBytesWrittenValue;
}
-void QWindowsPipeWriter::emitPendingBytesWrittenValue()
+/*!
+ Returns \c true if async operation is in progress.
+*/
+bool QWindowsPipeWriter::isWriteOperationActive() const
{
- if (bytesWrittenPending) {
- // Reset the state even if we don't emit bytesWritten().
- // It's a defined behavior to not re-emit this signal recursively.
- bytesWrittenPending = false;
- const qint64 bytes = pendingBytesWrittenValue;
- pendingBytesWrittenValue = 0;
+ return completionState == NoError && bytesToWrite() != 0;
+}
- emit canWrite();
- if (!inBytesWritten) {
- QScopedValueRollback<bool> guard(inBytesWritten, true);
- emit bytesWritten(bytes);
- }
- }
+/*!
+ Writes a shallow copy of \a ba to the internal buffer.
+ */
+void QWindowsPipeWriter::write(const QByteArray &ba)
+{
+ if (completionState != WriteDisabled)
+ writeImpl(ba);
}
-void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
- OVERLAPPED *overlappedBase)
+/*!
+ Writes data to the internal buffer.
+ */
+void QWindowsPipeWriter::write(const char *data, qint64 size)
{
- Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
- if (overlapped->pipeWriter)
- overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered);
- else
- delete overlapped;
+ if (completionState != WriteDisabled)
+ writeImpl(data, size);
+}
+
+template <typename... Args>
+inline void QWindowsPipeWriter::writeImpl(Args... args)
+{
+ QMutexLocker locker(&mutex);
+
+ writeBuffer.append(args...);
+
+ if (writeSequenceStarted || (lastError != ERROR_SUCCESS))
+ return;
+
+ stopped = false;
+
+ // If we don't have an assigned handle yet, defer writing until
+ // setHandle() is called.
+ if (handle != INVALID_HANDLE_VALUE)
+ startAsyncWriteHelper(&locker);
+}
+
+void QWindowsPipeWriter::startAsyncWriteHelper(QMutexLocker<QMutex> *locker)
+{
+ startAsyncWriteLocked();
+
+ // Do not post the event, if the write operation will be completed asynchronously.
+ if (!bytesWrittenPending && lastError == ERROR_SUCCESS)
+ return;
+
+ notifyCompleted(locker);
+}
+
+/*!
+ Starts a new write sequence.
+ */
+void QWindowsPipeWriter::startAsyncWriteLocked()
+{
+ while (!writeBuffer.isEmpty()) {
+ // WriteFile() returns true, if the write operation completes synchronously.
+ // We don't need to call GetOverlappedResult() additionally, because
+ // 'numberOfBytesWritten' is valid in this case.
+ DWORD numberOfBytesWritten;
+ DWORD errorCode = ERROR_SUCCESS;
+ if (!WriteFile(handle, writeBuffer.readPointer(), writeBuffer.nextDataBlockSize(),
+ &numberOfBytesWritten, &overlapped)) {
+ errorCode = GetLastError();
+ if (errorCode == ERROR_IO_PENDING) {
+ // Operation has been queued and will complete in the future.
+ writeSequenceStarted = true;
+ SetThreadpoolWait(waitObject, eventHandle, NULL);
+ break;
+ }
+ }
+
+ if (!writeCompleted(errorCode, numberOfBytesWritten))
+ break;
+ }
}
/*!
\internal
- Will be called whenever the write operation completes.
+ Thread pool callback procedure.
*/
-void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten)
+void QWindowsPipeWriter::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult)
{
- notifiedCalled = true;
- writeSequenceStarted = false;
- Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == DWORD(buffer.size()));
- buffer.clear();
+ Q_UNUSED(instance);
+ Q_UNUSED(wait);
+ Q_UNUSED(waitResult);
+ QWindowsPipeWriter *pipeWriter = reinterpret_cast<QWindowsPipeWriter *>(context);
+
+ // Get the result of the asynchronous operation.
+ DWORD numberOfBytesTransfered = 0;
+ DWORD errorCode = ERROR_SUCCESS;
+ if (!GetOverlappedResult(pipeWriter->handle, &pipeWriter->overlapped,
+ &numberOfBytesTransfered, FALSE))
+ errorCode = GetLastError();
+
+ QMutexLocker locker(&pipeWriter->mutex);
+ // After the writer was stopped, the only reason why this function can be called is the
+ // completion of a cancellation. No signals should be emitted, and no new write sequence
+ // should be started in this case.
+ if (pipeWriter->stopped)
+ return;
+
+ pipeWriter->writeSequenceStarted = false;
+
+ if (pipeWriter->writeCompleted(errorCode, numberOfBytesTransfered))
+ pipeWriter->startAsyncWriteLocked();
+
+ // We post the notification even if the write operation failed,
+ // to unblock the main thread, in case it is waiting for the event.
+ pipeWriter->notifyCompleted(&locker);
+}
+
+/*!
+ Will be called whenever the write operation completes. Returns \c true if
+ no error occurred; otherwise returns \c false.
+ */
+bool QWindowsPipeWriter::writeCompleted(DWORD errorCode, DWORD numberOfBytesWritten)
+{
switch (errorCode) {
case ERROR_SUCCESS:
+ bytesWrittenPending = true;
+ pendingBytesWrittenValue += numberOfBytesWritten;
+ writeBuffer.free(numberOfBytesWritten);
+ return true;
+ case ERROR_PIPE_NOT_CONNECTED: // the other end has closed the pipe
+ case ERROR_OPERATION_ABORTED: // the operation was canceled
+ case ERROR_NO_DATA: // the pipe is being closed
break;
- case ERROR_OPERATION_ABORTED:
- if (stopped)
- break;
- Q_FALLTHROUGH();
default:
- qErrnoWarning(errorCode, "QWindowsPipeWriter: asynchronous write failed.");
+ qErrnoWarning(errorCode, "QWindowsPipeWriter: write failed.");
break;
}
- // After the writer was stopped, the only reason why this function can be called is the
- // completion of a cancellation. No signals should be emitted, and no new write sequence should
- // be started in this case.
- if (stopped)
- return;
+ // The buffer is not cleared here, because the write progress
+ // should appear on the main thread synchronously.
+ lastError = errorCode;
+ return false;
+}
- pendingBytesWrittenValue += qint64(numberOfBytesWritten);
- if (!bytesWrittenPending) {
- bytesWrittenPending = true;
- emit _q_queueBytesWritten(QWindowsPipeWriter::QPrivateSignal());
+/*!
+ Posts a notification event to the main thread.
+ */
+void QWindowsPipeWriter::notifyCompleted(QMutexLocker<QMutex> *locker)
+{
+ if (!winEventActPosted) {
+ winEventActPosted = true;
+ locker->unlock();
+ QCoreApplication::postEvent(this, new QEvent(QEvent::WinEventAct));
+ } else {
+ locker->unlock();
}
+
+ // We set the event only after unlocking to avoid additional context
+ // switches due to the released thread immediately running into the lock.
+ SetEvent(syncHandle);
}
-bool QWindowsPipeWriter::waitForNotification(int timeout)
+/*!
+ Receives notification that the write operation has completed.
+ */
+bool QWindowsPipeWriter::event(QEvent *e)
{
- QElapsedTimer t;
- t.start();
- notifiedCalled = false;
- int msecs = timeout;
- while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
- if (notifiedCalled)
- return true;
-
- // Some other I/O completion routine was called. Wait some more.
- msecs = qt_subtract_from_timeout(timeout, t.elapsed());
- if (!msecs)
- break;
+ if (e->type() == QEvent::WinEventAct) {
+ consumePendingAndEmit(true);
+ return true;
}
- return notifiedCalled;
+ return QObject::event(e);
}
-bool QWindowsPipeWriter::write(const QByteArray &ba)
+/*!
+ Updates the state and emits pending signals in the main thread.
+ Returns \c true, if bytesWritten() was emitted.
+ */
+bool QWindowsPipeWriter::consumePendingAndEmit(bool allowWinActPosting)
{
- if (writeSequenceStarted)
- return false;
+ ResetEvent(syncHandle);
+ QMutexLocker locker(&mutex);
- if (!overlapped)
- overlapped = new Overlapped(this);
- overlapped->clear();
- buffer = ba;
- stopped = false;
- writeSequenceStarted = true;
- if (!WriteFileEx(handle, buffer.constData(), buffer.size(),
- overlapped, &writeFileCompleted)) {
- writeSequenceStarted = false;
- buffer.clear();
+ // Enable QEvent::WinEventAct posting.
+ if (allowWinActPosting)
+ winEventActPosted = false;
- const DWORD errorCode = GetLastError();
- switch (errorCode) {
- case ERROR_NO_DATA: // "The pipe is being closed."
- // The other end has closed the pipe. This can happen in QLocalSocket. Do not warn.
- break;
- default:
- qErrnoWarning(errorCode, "QWindowsPipeWriter::write failed.");
- }
- return false;
+ const qint64 numberOfBytesWritten = pendingBytesWrittenValue;
+ const bool emitBytesWritten = bytesWrittenPending;
+ if (emitBytesWritten) {
+ bytesWrittenPending = false;
+ pendingBytesWrittenValue = 0;
}
+ const DWORD dwError = lastError;
- return true;
-}
+ locker.unlock();
-void QWindowsPipeWriter::stop()
-{
- stopped = true;
- bytesWrittenPending = false;
- pendingBytesWrittenValue = 0;
- if (writeSequenceStarted) {
- overlapped->pipeWriter = nullptr;
- if (!CancelIoEx(handle, overlapped)) {
- const DWORD dwError = GetLastError();
- if (dwError != ERROR_NOT_FOUND) {
- qErrnoWarning(dwError, "QWindowsPipeWriter: CancelIoEx on handle %p failed.",
- handle);
- }
+ // Disable any further processing, if the pipe was stopped.
+ if (stopped)
+ return false;
+
+ // Trigger 'ErrorDetected' state only once. This state must be set before
+ // emitting the bytesWritten() signal. Otherwise, the write sequence will
+ // be considered not finished, and we may hang if a slot connected
+ // to bytesWritten() calls waitForBytesWritten().
+ if (dwError != ERROR_SUCCESS && completionState == NoError) {
+ QPointer<QWindowsPipeWriter> alive(this);
+ completionState = ErrorDetected;
+ if (emitBytesWritten)
+ emit bytesWritten(numberOfBytesWritten);
+ if (alive) {
+ writeBuffer.clear();
+ completionState = WriteDisabled;
+ emit writeFailed();
}
- overlapped = nullptr; // The object will be deleted in the I/O callback.
- writeSequenceStarted = false;
+ } else if (emitBytesWritten) {
+ emit bytesWritten(numberOfBytesWritten);
}
+
+ return emitBytesWritten;
}
QT_END_NAMESPACE
+
+#include "moc_qwindowspipewriter_p.cpp"
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index 6c269e86b7..c8c82310b8 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2021 Alex Trotsenko <alex1973tr@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSPIPEWRITER_P_H
#define QWINDOWSPIPEWRITER_P_H
@@ -51,106 +16,66 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-#include <qelapsedtimer.h>
#include <qobject.h>
-#include <qbytearray.h>
+#include <qmutex.h>
+#include <private/qringbuffer_p.h>
+
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
-#define SLEEPMIN 10
-#define SLEEPMAX 500
-
-class QIncrementalSleepTimer
-{
-
-public:
- QIncrementalSleepTimer(int msecs)
- : totalTimeOut(msecs)
- , nextSleep(qMin(SLEEPMIN, totalTimeOut))
- {
- if (totalTimeOut == -1)
- nextSleep = SLEEPMIN;
- timer.start();
- }
-
- int nextSleepTime()
- {
- int tmp = nextSleep;
- nextSleep = qMin(nextSleep * 2, qMin(SLEEPMAX, timeLeft()));
- return tmp;
- }
-
- int timeLeft() const
- {
- if (totalTimeOut == -1)
- return SLEEPMAX;
- return qMax(int(totalTimeOut - timer.elapsed()), 0);
- }
-
- bool hasTimedOut() const
- {
- if (totalTimeOut == -1)
- return false;
- return timer.elapsed() >= totalTimeOut;
- }
-
- void resetIncrements()
- {
- nextSleep = qMin(SLEEPMIN, timeLeft());
- }
-
-private:
- QElapsedTimer timer;
- int totalTimeOut;
- int nextSleep;
-};
-
class Q_CORE_EXPORT QWindowsPipeWriter : public QObject
{
Q_OBJECT
public:
- explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0);
+ explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = nullptr);
~QWindowsPipeWriter();
- bool write(const QByteArray &ba);
+ void setHandle(HANDLE hPipeWriteEnd);
+ void write(const QByteArray &ba);
+ void write(const char *data, qint64 size);
void stop();
- bool waitForWrite(int msecs);
- bool isWriteOperationActive() const { return writeSequenceStarted; }
+ bool checkForWrite() { return consumePendingAndEmit(false); }
qint64 bytesToWrite() const;
+ bool isWriteOperationActive() const;
+ HANDLE syncEvent() const { return syncHandle; }
Q_SIGNALS:
- void canWrite();
void bytesWritten(qint64 bytes);
- void _q_queueBytesWritten(QPrivateSignal);
+ void writeFailed();
+
+protected:
+ bool event(QEvent *e) override;
private:
- static void CALLBACK writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
- OVERLAPPED *overlappedBase);
- void notified(DWORD errorCode, DWORD numberOfBytesWritten);
- bool waitForNotification(int timeout);
- void emitPendingBytesWrittenValue();
-
- class Overlapped : public OVERLAPPED
- {
- Q_DISABLE_COPY_MOVE(Overlapped)
- public:
- explicit Overlapped(QWindowsPipeWriter *pipeWriter);
- void clear();
-
- QWindowsPipeWriter *pipeWriter;
- };
+ enum CompletionState { NoError, ErrorDetected, WriteDisabled };
+
+ template <typename... Args>
+ inline void writeImpl(Args... args);
+
+ void startAsyncWriteHelper(QMutexLocker<QMutex> *locker);
+ void startAsyncWriteLocked();
+ static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult);
+ bool writeCompleted(DWORD errorCode, DWORD numberOfBytesWritten);
+ void notifyCompleted(QMutexLocker<QMutex> *locker);
+ bool consumePendingAndEmit(bool allowWinActPosting);
HANDLE handle;
- Overlapped *overlapped;
- QByteArray buffer;
+ HANDLE eventHandle;
+ HANDLE syncHandle;
+ PTP_WAIT waitObject;
+ OVERLAPPED overlapped;
+ QRingBuffer writeBuffer;
qint64 pendingBytesWrittenValue;
+ mutable QMutex mutex;
+ DWORD lastError;
+
+ CompletionState completionState;
bool stopped;
bool writeSequenceStarted;
- bool notifiedCalled;
bool bytesWrittenPending;
- bool inBytesWritten;
+ bool winEventActPosted;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qzip.cpp b/src/corelib/io/qzip.cpp
new file mode 100644
index 0000000000..173563ec29
--- /dev/null
+++ b/src/corelib/io/qzip.cpp
@@ -0,0 +1,1347 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qzipreader_p.h"
+#include "qzipwriter_p.h"
+
+#include <qdatetime.h>
+#include <qendian.h>
+#include <qdebug.h>
+#include <qdir.h>
+
+#include <memory>
+
+#include <zlib.h>
+
+// Zip standard version for archives handled by this API
+// (actually, the only basic support of this version is implemented but it is enough for now)
+#define ZIP_VERSION 20
+
+#if 0
+#define ZDEBUG qDebug
+#else
+#define ZDEBUG if (0) qDebug
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static inline uint readUInt(const uchar *data)
+{
+ return (data[0]) + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
+}
+
+static inline ushort readUShort(const uchar *data)
+{
+ return (data[0]) + (data[1]<<8);
+}
+
+static inline void writeUInt(uchar *data, uint i)
+{
+ data[0] = i & 0xff;
+ data[1] = (i>>8) & 0xff;
+ data[2] = (i>>16) & 0xff;
+ data[3] = (i>>24) & 0xff;
+}
+
+static inline void writeUShort(uchar *data, ushort i)
+{
+ data[0] = i & 0xff;
+ data[1] = (i>>8) & 0xff;
+}
+
+static inline void copyUInt(uchar *dest, const uchar *src)
+{
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest[3] = src[3];
+}
+
+static inline void copyUShort(uchar *dest, const uchar *src)
+{
+ dest[0] = src[0];
+ dest[1] = src[1];
+}
+
+static void writeMSDosDate(uchar *dest, const QDateTime& dt)
+{
+ if (dt.isValid()) {
+ quint16 time =
+ (dt.time().hour() << 11) // 5 bit hour
+ | (dt.time().minute() << 5) // 6 bit minute
+ | (dt.time().second() >> 1); // 5 bit double seconds
+
+ dest[0] = time & 0xff;
+ dest[1] = time >> 8;
+
+ quint16 date =
+ ((dt.date().year() - 1980) << 9) // 7 bit year 1980-based
+ | (dt.date().month() << 5) // 4 bit month
+ | (dt.date().day()); // 5 bit day
+
+ dest[2] = char(date);
+ dest[3] = char(date >> 8);
+ } else {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ }
+}
+
+static int inflate(Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = const_cast<Bytef*>(source);
+ stream.avail_in = (uInt)sourceLen;
+ if ((uLong)stream.avail_in != sourceLen)
+ return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen)
+ return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)nullptr;
+ stream.zfree = (free_func)nullptr;
+
+ err = inflateInit2(&stream, -MAX_WBITS);
+ if (err != Z_OK)
+ return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
+
+static int deflate (Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = const_cast<Bytef*>(source);
+ stream.avail_in = (uInt)sourceLen;
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)nullptr;
+ stream.zfree = (free_func)nullptr;
+ stream.opaque = (voidpf)nullptr;
+
+ err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+
+namespace WindowsFileAttributes {
+enum {
+ Dir = 0x10, // FILE_ATTRIBUTE_DIRECTORY
+ File = 0x80, // FILE_ATTRIBUTE_NORMAL
+ TypeMask = 0x90,
+
+ ReadOnly = 0x01, // FILE_ATTRIBUTE_READONLY
+ PermMask = 0x01
+};
+}
+
+namespace UnixFileAttributes {
+enum {
+ Dir = 0040000, // __S_IFDIR
+ File = 0100000, // __S_IFREG
+ SymLink = 0120000, // __S_IFLNK
+ TypeMask = 0170000, // __S_IFMT
+
+ ReadUser = 0400, // __S_IRUSR
+ WriteUser = 0200, // __S_IWUSR
+ ExeUser = 0100, // __S_IXUSR
+ ReadGroup = 0040, // __S_IRGRP
+ WriteGroup = 0020, // __S_IWGRP
+ ExeGroup = 0010, // __S_IXGRP
+ ReadOther = 0004, // __S_IROTH
+ WriteOther = 0002, // __S_IWOTH
+ ExeOther = 0001, // __S_IXOTH
+ PermMask = 0777
+};
+}
+
+static QFile::Permissions modeToPermissions(quint32 mode)
+{
+ QFile::Permissions ret;
+ if (mode & UnixFileAttributes::ReadUser)
+ ret |= QFile::ReadOwner | QFile::ReadUser;
+ if (mode & UnixFileAttributes::WriteUser)
+ ret |= QFile::WriteOwner | QFile::WriteUser;
+ if (mode & UnixFileAttributes::ExeUser)
+ ret |= QFile::ExeOwner | QFile::ExeUser;
+ if (mode & UnixFileAttributes::ReadGroup)
+ ret |= QFile::ReadGroup;
+ if (mode & UnixFileAttributes::WriteGroup)
+ ret |= QFile::WriteGroup;
+ if (mode & UnixFileAttributes::ExeGroup)
+ ret |= QFile::ExeGroup;
+ if (mode & UnixFileAttributes::ReadOther)
+ ret |= QFile::ReadOther;
+ if (mode & UnixFileAttributes::WriteOther)
+ ret |= QFile::WriteOther;
+ if (mode & UnixFileAttributes::ExeOther)
+ ret |= QFile::ExeOther;
+ return ret;
+}
+
+static quint32 permissionsToMode(QFile::Permissions perms)
+{
+ quint32 mode = 0;
+ if (perms & (QFile::ReadOwner | QFile::ReadUser))
+ mode |= UnixFileAttributes::ReadUser;
+ if (perms & (QFile::WriteOwner | QFile::WriteUser))
+ mode |= UnixFileAttributes::WriteUser;
+ if (perms & (QFile::ExeOwner | QFile::ExeUser))
+ mode |= UnixFileAttributes::WriteUser;
+ if (perms & QFile::ReadGroup)
+ mode |= UnixFileAttributes::ReadGroup;
+ if (perms & QFile::WriteGroup)
+ mode |= UnixFileAttributes::WriteGroup;
+ if (perms & QFile::ExeGroup)
+ mode |= UnixFileAttributes::ExeGroup;
+ if (perms & QFile::ReadOther)
+ mode |= UnixFileAttributes::ReadOther;
+ if (perms & QFile::WriteOther)
+ mode |= UnixFileAttributes::WriteOther;
+ if (perms & QFile::ExeOther)
+ mode |= UnixFileAttributes::ExeOther;
+ return mode;
+}
+
+static QDateTime readMSDosDate(const uchar *src)
+{
+ uint dosDate = readUInt(src);
+ quint64 uDate;
+ uDate = (quint64)(dosDate >> 16);
+ uint tm_mday = (uDate & 0x1f);
+ uint tm_mon = ((uDate & 0x1E0) >> 5);
+ uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980);
+ uint tm_hour = ((dosDate & 0xF800) >> 11);
+ uint tm_min = ((dosDate & 0x7E0) >> 5);
+ uint tm_sec = ((dosDate & 0x1f) << 1);
+
+ return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
+}
+
+// for details, see http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+
+enum HostOS {
+ HostFAT = 0,
+ HostAMIGA = 1,
+ HostVMS = 2, // VAX/VMS
+ HostUnix = 3,
+ HostVM_CMS = 4,
+ HostAtari = 5, // what if it's a minix filesystem? [cjh]
+ HostHPFS = 6, // filesystem used by OS/2 (and NT 3.x)
+ HostMac = 7,
+ HostZ_System = 8,
+ HostCPM = 9,
+ HostTOPS20 = 10, // pkzip 2.50 NTFS
+ HostNTFS = 11, // filesystem used by Windows NT
+ HostQDOS = 12, // SMS/QDOS
+ HostAcorn = 13, // Archimedes Acorn RISC OS
+ HostVFAT = 14, // filesystem used by Windows 95, NT
+ HostMVS = 15,
+ HostBeOS = 16, // hybrid POSIX/database filesystem
+ HostTandem = 17,
+ HostOS400 = 18,
+ HostOSX = 19
+};
+Q_DECLARE_TYPEINFO(HostOS, Q_PRIMITIVE_TYPE);
+
+enum GeneralPurposeFlag {
+ Encrypted = 0x01,
+ AlgTune1 = 0x02,
+ AlgTune2 = 0x04,
+ HasDataDescriptor = 0x08,
+ PatchedData = 0x20,
+ StrongEncrypted = 0x40,
+ Utf8Names = 0x0800,
+ CentralDirectoryEncrypted = 0x2000
+};
+Q_DECLARE_TYPEINFO(GeneralPurposeFlag, Q_PRIMITIVE_TYPE);
+
+enum CompressionMethod {
+ CompressionMethodStored = 0,
+ CompressionMethodShrunk = 1,
+ CompressionMethodReduced1 = 2,
+ CompressionMethodReduced2 = 3,
+ CompressionMethodReduced3 = 4,
+ CompressionMethodReduced4 = 5,
+ CompressionMethodImploded = 6,
+ CompressionMethodReservedTokenizing = 7, // reserved for tokenizing
+ CompressionMethodDeflated = 8,
+ CompressionMethodDeflated64 = 9,
+ CompressionMethodPKImploding = 10,
+
+ CompressionMethodBZip2 = 12,
+
+ CompressionMethodLZMA = 14,
+
+ CompressionMethodTerse = 18,
+ CompressionMethodLz77 = 19,
+
+ CompressionMethodJpeg = 96,
+ CompressionMethodWavPack = 97,
+ CompressionMethodPPMd = 98,
+ CompressionMethodWzAES = 99
+};
+Q_DECLARE_TYPEINFO(CompressionMethod, Q_PRIMITIVE_TYPE);
+
+struct LocalFileHeader
+{
+ uchar signature[4]; // 0x04034b50
+ uchar version_needed[2];
+ uchar general_purpose_bits[2];
+ uchar compression_method[2];
+ uchar last_mod_file[4];
+ uchar crc_32[4];
+ uchar compressed_size[4];
+ uchar uncompressed_size[4];
+ uchar file_name_length[2];
+ uchar extra_field_length[2];
+};
+Q_DECLARE_TYPEINFO(LocalFileHeader, Q_PRIMITIVE_TYPE);
+
+struct DataDescriptor
+{
+ uchar crc_32[4];
+ uchar compressed_size[4];
+ uchar uncompressed_size[4];
+};
+Q_DECLARE_TYPEINFO(DataDescriptor, Q_PRIMITIVE_TYPE);
+
+struct CentralFileHeader
+{
+ uchar signature[4]; // 0x02014b50
+ uchar version_made[2];
+ uchar version_needed[2];
+ uchar general_purpose_bits[2];
+ uchar compression_method[2];
+ uchar last_mod_file[4];
+ uchar crc_32[4];
+ uchar compressed_size[4];
+ uchar uncompressed_size[4];
+ uchar file_name_length[2];
+ uchar extra_field_length[2];
+ uchar file_comment_length[2];
+ uchar disk_start[2];
+ uchar internal_file_attributes[2];
+ uchar external_file_attributes[4];
+ uchar offset_local_header[4];
+};
+Q_DECLARE_TYPEINFO(CentralFileHeader, Q_PRIMITIVE_TYPE);
+
+struct EndOfDirectory
+{
+ uchar signature[4]; // 0x06054b50
+ uchar this_disk[2];
+ uchar start_of_directory_disk[2];
+ uchar num_dir_entries_this_disk[2];
+ uchar num_dir_entries[2];
+ uchar directory_size[4];
+ uchar dir_start_offset[4];
+ uchar comment_length[2];
+};
+Q_DECLARE_TYPEINFO(EndOfDirectory, Q_PRIMITIVE_TYPE);
+
+struct FileHeader
+{
+ CentralFileHeader h;
+ QByteArray file_name;
+ QByteArray extra_field;
+ QByteArray file_comment;
+};
+Q_DECLARE_TYPEINFO(FileHeader, Q_RELOCATABLE_TYPE);
+
+class QZipPrivate
+{
+public:
+ QZipPrivate(QIODevice *device, bool ownDev)
+ : device(device), ownDevice(ownDev), dirtyFileTree(true), start_of_directory(0)
+ {
+ }
+
+ ~QZipPrivate()
+ {
+ if (ownDevice)
+ delete device;
+ }
+
+ QZipReader::FileInfo fillFileInfo(int index) const;
+
+ QIODevice *device;
+ bool ownDevice;
+ bool dirtyFileTree;
+ QList<FileHeader> fileHeaders;
+ QByteArray comment;
+ uint start_of_directory;
+};
+
+QZipReader::FileInfo QZipPrivate::fillFileInfo(int index) const
+{
+ QZipReader::FileInfo fileInfo;
+ FileHeader header = fileHeaders.at(index);
+ quint32 mode = readUInt(header.h.external_file_attributes);
+ const HostOS hostOS = HostOS(readUShort(header.h.version_made) >> 8);
+ switch (hostOS) {
+ case HostUnix:
+ mode = (mode >> 16) & 0xffff;
+ switch (mode & UnixFileAttributes::TypeMask) {
+ case UnixFileAttributes::SymLink:
+ fileInfo.isSymLink = true;
+ break;
+ case UnixFileAttributes::Dir:
+ fileInfo.isDir = true;
+ break;
+ case UnixFileAttributes::File:
+ default: // ### just for the case; should we warn?
+ fileInfo.isFile = true;
+ break;
+ }
+ fileInfo.permissions = modeToPermissions(mode);
+ break;
+ case HostFAT:
+ case HostNTFS:
+ case HostHPFS:
+ case HostVFAT:
+ switch (mode & WindowsFileAttributes::TypeMask) {
+ case WindowsFileAttributes::Dir:
+ fileInfo.isDir = true;
+ break;
+ case WindowsFileAttributes::File:
+ default:
+ fileInfo.isFile = true;
+ break;
+ }
+ fileInfo.permissions |= QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther;
+ if ((mode & WindowsFileAttributes::ReadOnly) == 0)
+ fileInfo.permissions |= QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther;
+ if (fileInfo.isDir)
+ fileInfo.permissions |= QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther;
+ break;
+ default:
+ qWarning("QZip: Zip entry format at %d is not supported.", index);
+ return fileInfo; // we don't support anything else
+ }
+
+ ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);
+ // if bit 11 is set, the filename and comment fields must be encoded using UTF-8
+ const bool inUtf8 = (general_purpose_bits & Utf8Names) != 0;
+ fileInfo.filePath = inUtf8 ? QString::fromUtf8(header.file_name) : QString::fromLocal8Bit(header.file_name);
+ fileInfo.crc = readUInt(header.h.crc_32);
+ fileInfo.size = readUInt(header.h.uncompressed_size);
+ fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
+
+ // fix the file path, if broken (convert separators, eat leading and trailing ones)
+ fileInfo.filePath = QDir::fromNativeSeparators(fileInfo.filePath);
+ QStringView filePathRef(fileInfo.filePath);
+ while (filePathRef.startsWith(u'.') || filePathRef.startsWith(u'/'))
+ filePathRef = filePathRef.mid(1);
+ while (filePathRef.endsWith(u'/'))
+ filePathRef.chop(1);
+
+ fileInfo.filePath = filePathRef.toString();
+ return fileInfo;
+}
+
+class QZipReaderPrivate : public QZipPrivate
+{
+public:
+ QZipReaderPrivate(QIODevice *device, bool ownDev)
+ : QZipPrivate(device, ownDev), status(QZipReader::NoError)
+ {
+ }
+
+ void scanFiles();
+
+ QZipReader::Status status;
+};
+
+class QZipWriterPrivate : public QZipPrivate
+{
+public:
+ QZipWriterPrivate(QIODevice *device, bool ownDev)
+ : QZipPrivate(device, ownDev),
+ status(QZipWriter::NoError),
+ permissions(QFile::ReadOwner | QFile::WriteOwner),
+ compressionPolicy(QZipWriter::AlwaysCompress)
+ {
+ }
+
+ QZipWriter::Status status;
+ QFile::Permissions permissions;
+ QZipWriter::CompressionPolicy compressionPolicy;
+
+ enum EntryType { Directory, File, Symlink };
+
+ void addEntry(EntryType type, const QString &fileName, const QByteArray &contents);
+};
+
+static LocalFileHeader toLocalHeader(const CentralFileHeader &ch)
+{
+ LocalFileHeader h;
+ writeUInt(h.signature, 0x04034b50);
+ copyUShort(h.version_needed, ch.version_needed);
+ copyUShort(h.general_purpose_bits, ch.general_purpose_bits);
+ copyUShort(h.compression_method, ch.compression_method);
+ copyUInt(h.last_mod_file, ch.last_mod_file);
+ copyUInt(h.crc_32, ch.crc_32);
+ copyUInt(h.compressed_size, ch.compressed_size);
+ copyUInt(h.uncompressed_size, ch.uncompressed_size);
+ copyUShort(h.file_name_length, ch.file_name_length);
+ copyUShort(h.extra_field_length, ch.extra_field_length);
+ return h;
+}
+
+void QZipReaderPrivate::scanFiles()
+{
+ if (!dirtyFileTree)
+ return;
+
+ if (! (device->isOpen() || device->open(QIODevice::ReadOnly))) {
+ status = QZipReader::FileOpenError;
+ return;
+ }
+
+ if ((device->openMode() & QIODevice::ReadOnly) == 0) { // only read the index from readable files.
+ status = QZipReader::FileReadError;
+ return;
+ }
+
+ dirtyFileTree = false;
+ uchar tmp[4];
+ device->read((char *)tmp, 4);
+ if (readUInt(tmp) != 0x04034b50) {
+ qWarning("QZip: not a zip file!");
+ return;
+ }
+
+ // find EndOfDirectory header
+ int i = 0;
+ int start_of_directory = -1;
+ int num_dir_entries = 0;
+ EndOfDirectory eod;
+ while (start_of_directory == -1) {
+ const int pos = device->size() - int(sizeof(EndOfDirectory)) - i;
+ if (pos < 0 || i > 65535) {
+ qWarning("QZip: EndOfDirectory not found");
+ return;
+ }
+
+ device->seek(pos);
+ device->read((char *)&eod, sizeof(EndOfDirectory));
+ if (readUInt(eod.signature) == 0x06054b50)
+ break;
+ ++i;
+ }
+
+ // have the eod
+ start_of_directory = readUInt(eod.dir_start_offset);
+ num_dir_entries = readUShort(eod.num_dir_entries);
+ ZDEBUG("start_of_directory at %d, num_dir_entries=%d", start_of_directory, num_dir_entries);
+ int comment_length = readUShort(eod.comment_length);
+ if (comment_length != i)
+ qWarning("QZip: failed to parse zip file.");
+ comment = device->read(qMin(comment_length, i));
+
+
+ device->seek(start_of_directory);
+ for (i = 0; i < num_dir_entries; ++i) {
+ FileHeader header;
+ int read = device->read((char *) &header.h, sizeof(CentralFileHeader));
+ if (read < (int)sizeof(CentralFileHeader)) {
+ qWarning("QZip: Failed to read complete header, index may be incomplete");
+ break;
+ }
+ if (readUInt(header.h.signature) != 0x02014b50) {
+ qWarning("QZip: invalid header signature, index may be incomplete");
+ break;
+ }
+
+ int l = readUShort(header.h.file_name_length);
+ header.file_name = device->read(l);
+ if (header.file_name.size() != l) {
+ qWarning("QZip: Failed to read filename from zip index, index may be incomplete");
+ break;
+ }
+ l = readUShort(header.h.extra_field_length);
+ header.extra_field = device->read(l);
+ if (header.extra_field.size() != l) {
+ qWarning("QZip: Failed to read extra field in zip file, skipping file, index may be incomplete");
+ break;
+ }
+ l = readUShort(header.h.file_comment_length);
+ header.file_comment = device->read(l);
+ if (header.file_comment.size() != l) {
+ qWarning("QZip: Failed to read read file comment, index may be incomplete");
+ break;
+ }
+
+ ZDEBUG("found file '%s'", header.file_name.data());
+ fileHeaders.append(header);
+ }
+}
+
+void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const QByteArray &contents/*, QFile::Permissions permissions, QZip::Method m*/)
+{
+#ifndef NDEBUG
+ static const char *const entryTypes[] = {
+ "directory",
+ "file ",
+ "symlink " };
+ ZDEBUG() << "adding" << entryTypes[type] <<":" << fileName.toUtf8().data() << (type == 2 ? QByteArray(" -> " + contents).constData() : "");
+#endif
+
+ if (! (device->isOpen() || device->open(QIODevice::WriteOnly))) {
+ status = QZipWriter::FileOpenError;
+ return;
+ }
+ device->seek(start_of_directory);
+
+ // don't compress small files
+ QZipWriter::CompressionPolicy compression = compressionPolicy;
+ if (compressionPolicy == QZipWriter::AutoCompress) {
+ if (contents.size() < 64)
+ compression = QZipWriter::NeverCompress;
+ else
+ compression = QZipWriter::AlwaysCompress;
+ }
+
+ FileHeader header;
+ memset(&header.h, 0, sizeof(CentralFileHeader));
+ writeUInt(header.h.signature, 0x02014b50);
+
+ writeUShort(header.h.version_needed, ZIP_VERSION);
+ writeUInt(header.h.uncompressed_size, contents.size());
+ writeMSDosDate(header.h.last_mod_file, QDateTime::currentDateTime());
+ QByteArray data = contents;
+ if (compression == QZipWriter::AlwaysCompress) {
+ writeUShort(header.h.compression_method, CompressionMethodDeflated);
+
+ ulong len = contents.size();
+ // shamelessly copied form zlib
+ len += (len >> 12) + (len >> 14) + 11;
+ int res;
+ do {
+ data.resize(len);
+ res = deflate((uchar*)data.data(), &len, (const uchar*)contents.constData(), contents.size());
+
+ switch (res) {
+ case Z_OK:
+ data.resize(len);
+ break;
+ case Z_MEM_ERROR:
+ qWarning("QZip: Z_MEM_ERROR: Not enough memory to compress file, skipping");
+ data.resize(0);
+ break;
+ case Z_BUF_ERROR:
+ len *= 2;
+ break;
+ }
+ } while (res == Z_BUF_ERROR);
+ }
+// TODO add a check if data.length() > contents.length(). Then try to store the original and revert the compression method to be uncompressed
+ writeUInt(header.h.compressed_size, data.size());
+ uint crc_32 = ::crc32(0, nullptr, 0);
+ crc_32 = ::crc32(crc_32, (const uchar *)contents.constData(), contents.size());
+ writeUInt(header.h.crc_32, crc_32);
+
+ // if bit 11 is set, the filename and comment fields must be encoded using UTF-8
+ ushort general_purpose_bits = Utf8Names; // always use utf-8
+ writeUShort(header.h.general_purpose_bits, general_purpose_bits);
+
+ const bool inUtf8 = (general_purpose_bits & Utf8Names) != 0;
+ header.file_name = inUtf8 ? fileName.toUtf8() : fileName.toLocal8Bit();
+ if (header.file_name.size() > 0xffff) {
+ qWarning("QZip: Filename is too long, chopping it to 65535 bytes");
+ header.file_name = header.file_name.left(0xffff); // ### don't break the utf-8 sequence, if any
+ }
+ if (header.file_comment.size() + header.file_name.size() > 0xffff) {
+ qWarning("QZip: File comment is too long, chopping it to 65535 bytes");
+ header.file_comment.truncate(0xffff - header.file_name.size()); // ### don't break the utf-8 sequence, if any
+ }
+ writeUShort(header.h.file_name_length, header.file_name.size());
+ //h.extra_field_length[2];
+
+ writeUShort(header.h.version_made, HostUnix << 8);
+ //uchar internal_file_attributes[2];
+ //uchar external_file_attributes[4];
+ quint32 mode = permissionsToMode(permissions);
+ switch (type) {
+ case Symlink:
+ mode |= UnixFileAttributes::SymLink;
+ break;
+ case Directory:
+ mode |= UnixFileAttributes::Dir;
+ break;
+ case File:
+ mode |= UnixFileAttributes::File;
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ writeUInt(header.h.external_file_attributes, mode << 16);
+ writeUInt(header.h.offset_local_header, start_of_directory);
+
+
+ fileHeaders.append(header);
+
+ LocalFileHeader h = toLocalHeader(header.h);
+ device->write((const char *)&h, sizeof(LocalFileHeader));
+ device->write(header.file_name);
+ device->write(data);
+ start_of_directory = device->pos();
+ dirtyFileTree = true;
+}
+
+////////////////////////////// Reader
+
+/*!
+ \class QZipReader::FileInfo
+ \internal
+ Represents one entry in the zip table of contents.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::filePath
+ The full filepath inside the archive.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::isDir
+ A boolean type indicating if the entry is a directory.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::isFile
+ A boolean type, if it is one this entry is a file.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::isSymLink
+ A boolean type, if it is one this entry is symbolic link.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::permissions
+ A list of flags for the permissions of this entry.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::crc
+ The calculated checksum as a crc type.
+*/
+
+/*!
+ \variable QZipReader::FileInfo::size
+ The total size of the unpacked content.
+*/
+
+/*!
+ \class QZipReader
+ \internal
+ \since 4.5
+
+ \brief the QZipReader class provides a way to inspect the contents of a zip
+ archive and extract individual files from it.
+
+ QZipReader can be used to read a zip archive either from a file or from any
+ device. An in-memory QBuffer for instance. The reader can be used to read
+ which files are in the archive using fileInfoList() and entryInfoAt() but
+ also to extract individual files using fileData() or even to extract all
+ files in the archive using extractAll()
+*/
+
+/*!
+ Create a new zip archive that operates on the \a fileName. The file will be
+ opened with the \a mode.
+*/
+QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)
+{
+ auto f = std::make_unique<QFile>(archive);
+ const bool result = f->open(mode);
+ QZipReader::Status status;
+ const QFileDevice::FileError error = f->error();
+ if (result && error == QFile::NoError) {
+ status = NoError;
+ } else {
+ if (error == QFile::ReadError)
+ status = FileReadError;
+ else if (error == QFile::OpenError)
+ status = FileOpenError;
+ else if (error == QFile::PermissionsError)
+ status = FilePermissionsError;
+ else
+ status = FileError;
+ }
+
+ d = new QZipReaderPrivate(f.get(), /*ownDevice=*/true);
+ Q_UNUSED(f.release());
+ d->status = status;
+}
+
+/*!
+ Create a new zip archive that operates on the archive found in \a device.
+ You have to open the device previous to calling the constructor and only a
+ device that is readable will be scanned for zip filecontent.
+ */
+QZipReader::QZipReader(QIODevice *device)
+ : d(new QZipReaderPrivate(device, /*ownDevice=*/false))
+{
+ Q_ASSERT(device);
+}
+
+/*!
+ Destructor
+*/
+QZipReader::~QZipReader()
+{
+ close();
+ delete d;
+}
+
+/*!
+ Returns device used for reading zip archive.
+*/
+QIODevice* QZipReader::device() const
+{
+ return d->device;
+}
+
+/*!
+ Returns \c true if the user can read the file; otherwise returns \c false.
+*/
+bool QZipReader::isReadable() const
+{
+ return d->device->isReadable();
+}
+
+/*!
+ Returns \c true if the file exists; otherwise returns \c false.
+*/
+bool QZipReader::exists() const
+{
+ QFile *f = qobject_cast<QFile*> (d->device);
+ if (f == nullptr)
+ return true;
+ return f->exists();
+}
+
+/*!
+ Returns the list of files the archive contains.
+*/
+QList<QZipReader::FileInfo> QZipReader::fileInfoList() const
+{
+ d->scanFiles();
+ QList<FileInfo> files;
+ const int numFileHeaders = d->fileHeaders.size();
+ files.reserve(numFileHeaders);
+ for (int i = 0; i < numFileHeaders; ++i)
+ files.append(d->fillFileInfo(i));
+ return files;
+
+}
+
+/*!
+ Return the number of items in the zip archive.
+*/
+int QZipReader::count() const
+{
+ d->scanFiles();
+ return d->fileHeaders.size();
+}
+
+/*!
+ Returns a FileInfo of an entry in the zipfile.
+ The \a index is the index into the directory listing of the zipfile.
+ Returns an invalid FileInfo if \a index is out of boundaries.
+
+ \sa fileInfoList()
+*/
+QZipReader::FileInfo QZipReader::entryInfoAt(int index) const
+{
+ d->scanFiles();
+ if (index >= 0 && index < d->fileHeaders.size())
+ return d->fillFileInfo(index);
+ return QZipReader::FileInfo();
+}
+
+/*!
+ Fetch the file contents from the zip archive and return the uncompressed bytes.
+*/
+QByteArray QZipReader::fileData(const QString &fileName) const
+{
+ d->scanFiles();
+ int i;
+ for (i = 0; i < d->fileHeaders.size(); ++i) {
+ if (QString::fromLocal8Bit(d->fileHeaders.at(i).file_name) == fileName)
+ break;
+ }
+ if (i == d->fileHeaders.size())
+ return QByteArray();
+
+ FileHeader header = d->fileHeaders.at(i);
+
+ ushort version_needed = readUShort(header.h.version_needed);
+ if (version_needed > ZIP_VERSION) {
+ qWarning("QZip: .ZIP specification version %d implementationis needed to extract the data.", version_needed);
+ return QByteArray();
+ }
+
+ ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);
+ int compressed_size = readUInt(header.h.compressed_size);
+ int uncompressed_size = readUInt(header.h.uncompressed_size);
+ int start = readUInt(header.h.offset_local_header);
+ //qDebug("uncompressing file %d: local header at %d", i, start);
+
+ d->device->seek(start);
+ LocalFileHeader lh;
+ d->device->read((char *)&lh, sizeof(LocalFileHeader));
+ uint skip = readUShort(lh.file_name_length) + readUShort(lh.extra_field_length);
+ d->device->seek(d->device->pos() + skip);
+
+ int compression_method = readUShort(lh.compression_method);
+ //qDebug("file=%s: compressed_size=%d, uncompressed_size=%d", fileName.toLocal8Bit().data(), compressed_size, uncompressed_size);
+
+ if ((general_purpose_bits & Encrypted) != 0) {
+ qWarning("QZip: Unsupported encryption method is needed to extract the data.");
+ return QByteArray();
+ }
+
+ //qDebug("file at %lld", d->device->pos());
+ QByteArray compressed = d->device->read(compressed_size);
+ if (compression_method == CompressionMethodStored) {
+ // no compression
+ compressed.truncate(uncompressed_size);
+ return compressed;
+ } else if (compression_method == CompressionMethodDeflated) {
+ // Deflate
+ //qDebug("compressed=%d", compressed.size());
+ compressed.truncate(compressed_size);
+ QByteArray baunzip;
+ ulong len = qMax(uncompressed_size, 1);
+ int res;
+ do {
+ baunzip.resize(len);
+ res = inflate((uchar*)baunzip.data(), &len,
+ (const uchar*)compressed.constData(), compressed_size);
+
+ switch (res) {
+ case Z_OK:
+ if ((int)len != baunzip.size())
+ baunzip.resize(len);
+ break;
+ case Z_MEM_ERROR:
+ qWarning("QZip: Z_MEM_ERROR: Not enough memory");
+ break;
+ case Z_BUF_ERROR:
+ len *= 2;
+ break;
+ case Z_DATA_ERROR:
+ qWarning("QZip: Z_DATA_ERROR: Input data is corrupted");
+ break;
+ }
+ } while (res == Z_BUF_ERROR);
+ return baunzip;
+ }
+
+ qWarning("QZip: Unsupported compression method %d is needed to extract the data.", compression_method);
+ return QByteArray();
+}
+
+/*!
+ Extracts the full contents of the zip file into \a destinationDir on
+ the local filesystem.
+ In case writing or linking a file fails, the extraction will be aborted.
+*/
+bool QZipReader::extractAll(const QString &destinationDir) const
+{
+ QDir baseDir(destinationDir);
+
+ // create directories first
+ const QList<FileInfo> allFiles = fileInfoList();
+ bool foundDirs = false;
+ bool hasDirs = false;
+ for (const FileInfo &fi : allFiles) {
+ const QString absPath = destinationDir + QDir::separator() + fi.filePath;
+ if (fi.isDir) {
+ foundDirs = true;
+ if (!baseDir.mkpath(fi.filePath))
+ return false;
+ if (!QFile::setPermissions(absPath, fi.permissions))
+ return false;
+ } else if (!hasDirs && fi.filePath.contains(u"/")) {
+ // filePath does not have leading or trailing '/', so if we find
+ // one, than the file path contains directories.
+ hasDirs = true;
+ }
+ }
+
+ // Some zip archives can be broken in the sense that they do not report
+ // separate entries for directories, only for files. In this case we
+ // need to recreate directory structure based on the file paths.
+ if (hasDirs && !foundDirs) {
+ for (const FileInfo &fi : allFiles) {
+ const auto dirPath = fi.filePath.left(fi.filePath.lastIndexOf(u"/"));
+ if (!baseDir.mkpath(dirPath))
+ return false;
+ // We will leave the directory permissions default in this case,
+ // because setting dir permissions based on file is incorrect
+ }
+ }
+
+ // set up symlinks
+ for (const FileInfo &fi : allFiles) {
+ const QString absPath = destinationDir + QDir::separator() + fi.filePath;
+ if (fi.isSymLink) {
+ QString destination = QFile::decodeName(fileData(fi.filePath));
+ if (destination.isEmpty())
+ return false;
+ QFileInfo linkFi(absPath);
+ if (!QFile::exists(linkFi.absolutePath()))
+ QDir::root().mkpath(linkFi.absolutePath());
+ if (!QFile::link(destination, absPath))
+ return false;
+ /* cannot change permission of links
+ if (!QFile::setPermissions(absPath, fi.permissions))
+ return false;
+ */
+ }
+ }
+
+ for (const FileInfo &fi : allFiles) {
+ const QString absPath = destinationDir + QDir::separator() + fi.filePath;
+ if (fi.isFile) {
+ QFile f(absPath);
+ if (!f.open(QIODevice::WriteOnly))
+ return false;
+ f.write(fileData(fi.filePath));
+ f.setPermissions(fi.permissions);
+ f.close();
+ }
+ }
+
+ return true;
+}
+
+/*!
+ \enum QZipReader::Status
+
+ The following status values are possible:
+
+ \value NoError No error occurred.
+ \value FileReadError An error occurred when reading from the file.
+ \value FileOpenError The file could not be opened.
+ \value FilePermissionsError The file could not be accessed.
+ \value FileError Another file error occurred.
+*/
+
+/*!
+ Returns a status code indicating the first error that was met by QZipReader,
+ or QZipReader::NoError if no error occurred.
+*/
+QZipReader::Status QZipReader::status() const
+{
+ return d->status;
+}
+
+/*!
+ Close the zip file.
+*/
+void QZipReader::close()
+{
+ d->device->close();
+}
+
+////////////////////////////// Writer
+
+/*!
+ \class QZipWriter
+ \internal
+ \since 4.5
+
+ \brief the QZipWriter class provides a way to create a new zip archive.
+
+ QZipWriter can be used to create a zip archive containing any number of files
+ and directories. The files in the archive will be compressed in a way that is
+ compatible with common zip reader applications.
+*/
+
+
+/*!
+ Create a new zip archive that operates on the \a archive filename. The file will
+ be opened with the \a mode.
+ \sa isValid()
+*/
+QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)
+{
+ auto f = std::make_unique<QFile>(fileName);
+ QZipWriter::Status status;
+ if (f->open(mode) && f->error() == QFile::NoError)
+ status = QZipWriter::NoError;
+ else {
+ if (f->error() == QFile::WriteError)
+ status = QZipWriter::FileWriteError;
+ else if (f->error() == QFile::OpenError)
+ status = QZipWriter::FileOpenError;
+ else if (f->error() == QFile::PermissionsError)
+ status = QZipWriter::FilePermissionsError;
+ else
+ status = QZipWriter::FileError;
+ }
+
+ d = new QZipWriterPrivate(f.get(), /*ownDevice=*/true);
+ Q_UNUSED(f.release());
+ d->status = status;
+}
+
+/*!
+ Create a new zip archive that operates on the archive found in \a device.
+ You have to open the device previous to calling the constructor and
+ only a device that is readable will be scanned for zip filecontent.
+ */
+QZipWriter::QZipWriter(QIODevice *device)
+ : d(new QZipWriterPrivate(device, /*ownDevice=*/false))
+{
+ Q_ASSERT(device);
+}
+
+QZipWriter::~QZipWriter()
+{
+ close();
+ delete d;
+}
+
+/*!
+ Returns device used for writing zip archive.
+*/
+QIODevice* QZipWriter::device() const
+{
+ return d->device;
+}
+
+/*!
+ Returns \c true if the user can write to the archive; otherwise returns \c false.
+*/
+bool QZipWriter::isWritable() const
+{
+ return d->device->isWritable();
+}
+
+/*!
+ Returns \c true if the file exists; otherwise returns \c false.
+*/
+bool QZipWriter::exists() const
+{
+ QFile *f = qobject_cast<QFile*> (d->device);
+ if (f == nullptr)
+ return true;
+ return f->exists();
+}
+
+/*!
+ \enum QZipWriter::Status
+
+ The following status values are possible:
+
+ \value NoError No error occurred.
+ \value FileWriteError An error occurred when writing to the device.
+ \value FileOpenError The file could not be opened.
+ \value FilePermissionsError The file could not be accessed.
+ \value FileError Another file error occurred.
+*/
+
+/*!
+ Returns a status code indicating the first error that was met by QZipWriter,
+ or QZipWriter::NoError if no error occurred.
+*/
+QZipWriter::Status QZipWriter::status() const
+{
+ return d->status;
+}
+
+/*!
+ \enum QZipWriter::CompressionPolicy
+
+ \value AlwaysCompress A file that is added is compressed.
+ \value NeverCompress A file that is added will be stored without changes.
+ \value AutoCompress A file that is added will be compressed only if that will give a smaller file.
+*/
+
+/*!
+ Sets the policy for compressing newly added files to the new \a policy.
+
+ \note the default policy is AlwaysCompress
+
+ \sa compressionPolicy()
+ \sa addFile()
+*/
+void QZipWriter::setCompressionPolicy(CompressionPolicy policy)
+{
+ d->compressionPolicy = policy;
+}
+
+/*!
+ Returns the currently set compression policy.
+ \sa setCompressionPolicy()
+ \sa addFile()
+*/
+QZipWriter::CompressionPolicy QZipWriter::compressionPolicy() const
+{
+ return d->compressionPolicy;
+}
+
+/*!
+ Sets the permissions that will be used for newly added files.
+
+ \note the default permissions are QFile::ReadOwner | QFile::WriteOwner.
+
+ \sa creationPermissions()
+ \sa addFile()
+*/
+void QZipWriter::setCreationPermissions(QFile::Permissions permissions)
+{
+ d->permissions = permissions;
+}
+
+/*!
+ Returns the currently set creation permissions.
+
+ \sa setCreationPermissions()
+ \sa addFile()
+*/
+QFile::Permissions QZipWriter::creationPermissions() const
+{
+ return d->permissions;
+}
+
+/*!
+ Add a file to the archive with \a data as the file contents.
+ The file will be stored in the archive using the \a fileName which
+ includes the full path in the archive.
+
+ The new file will get the file permissions based on the current
+ creationPermissions and it will be compressed using the zip compression
+ based on the current compression policy.
+
+ \sa setCreationPermissions()
+ \sa setCompressionPolicy()
+*/
+void QZipWriter::addFile(const QString &fileName, const QByteArray &data)
+{
+ d->addEntry(QZipWriterPrivate::File, QDir::fromNativeSeparators(fileName), data);
+}
+
+/*!
+ Add a file to the archive with \a device as the source of the contents.
+ The contents returned from QIODevice::readAll() will be used as the
+ filedata.
+ The file will be stored in the archive using the \a fileName which
+ includes the full path in the archive.
+*/
+void QZipWriter::addFile(const QString &fileName, QIODevice *device)
+{
+ Q_ASSERT(device);
+ QIODevice::OpenMode mode = device->openMode();
+ bool opened = false;
+ if ((mode & QIODevice::ReadOnly) == 0) {
+ opened = true;
+ if (! device->open(QIODevice::ReadOnly)) {
+ d->status = FileOpenError;
+ return;
+ }
+ }
+ d->addEntry(QZipWriterPrivate::File, QDir::fromNativeSeparators(fileName), device->readAll());
+ if (opened)
+ device->close();
+}
+
+/*!
+ Create a new directory in the archive with the specified \a dirName and
+ the \a permissions;
+*/
+void QZipWriter::addDirectory(const QString &dirName)
+{
+ QString name(QDir::fromNativeSeparators(dirName));
+ // separator is mandatory
+ if (!name.endsWith(u'/'))
+ name.append(u'/');
+ d->addEntry(QZipWriterPrivate::Directory, name, QByteArray());
+}
+
+/*!
+ Create a new symbolic link in the archive with the specified \a dirName
+ and the \a permissions;
+ A symbolic link contains the destination (relative) path and name.
+*/
+void QZipWriter::addSymLink(const QString &fileName, const QString &destination)
+{
+ d->addEntry(QZipWriterPrivate::Symlink, QDir::fromNativeSeparators(fileName), QFile::encodeName(destination));
+}
+
+/*!
+ Closes the zip file.
+*/
+void QZipWriter::close()
+{
+ if (!(d->device->openMode() & QIODevice::WriteOnly)) {
+ d->device->close();
+ return;
+ }
+
+ //qDebug("QZip::close writing directory, %d entries", d->fileHeaders.size());
+ d->device->seek(d->start_of_directory);
+ // write new directory
+ for (int i = 0; i < d->fileHeaders.size(); ++i) {
+ const FileHeader &header = d->fileHeaders.at(i);
+ d->device->write((const char *)&header.h, sizeof(CentralFileHeader));
+ d->device->write(header.file_name);
+ d->device->write(header.extra_field);
+ d->device->write(header.file_comment);
+ }
+ int dir_size = d->device->pos() - d->start_of_directory;
+ // write end of directory
+ EndOfDirectory eod;
+ memset(&eod, 0, sizeof(EndOfDirectory));
+ writeUInt(eod.signature, 0x06054b50);
+ //uchar this_disk[2];
+ //uchar start_of_directory_disk[2];
+ writeUShort(eod.num_dir_entries_this_disk, d->fileHeaders.size());
+ writeUShort(eod.num_dir_entries, d->fileHeaders.size());
+ writeUInt(eod.directory_size, dir_size);
+ writeUInt(eod.dir_start_offset, d->start_of_directory);
+ writeUShort(eod.comment_length, d->comment.size());
+
+ d->device->write((const char *)&eod, sizeof(EndOfDirectory));
+ d->device->write(d->comment);
+ d->device->close();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qzipreader_p.h b/src/corelib/io/qzipreader_p.h
new file mode 100644
index 0000000000..e6ddd0dc99
--- /dev/null
+++ b/src/corelib/io/qzipreader_p.h
@@ -0,0 +1,87 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QZIPREADER_H
+#define QZIPREADER_H
+
+#include <QtCore/private/qglobal_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QZipReader class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class QZipReaderPrivate;
+
+class Q_CORE_EXPORT QZipReader
+{
+public:
+ explicit QZipReader(const QString &fileName, QIODevice::OpenMode mode = QIODevice::ReadOnly );
+
+ explicit QZipReader(QIODevice *device);
+ ~QZipReader();
+
+ QIODevice* device() const;
+
+ bool isReadable() const;
+ bool exists() const;
+
+ struct FileInfo
+ {
+ FileInfo() noexcept
+ : isDir(false), isFile(false), isSymLink(false), crc(0), size(0)
+ {}
+
+ bool isValid() const noexcept { return isDir || isFile || isSymLink; }
+
+ QString filePath;
+ uint isDir : 1;
+ uint isFile : 1;
+ uint isSymLink : 1;
+ QFile::Permissions permissions;
+ uint crc;
+ qint64 size;
+ QDateTime lastModified;
+ };
+
+ QList<FileInfo> fileInfoList() const;
+ int count() const;
+
+ FileInfo entryInfoAt(int index) const;
+ QByteArray fileData(const QString &fileName) const;
+ bool extractAll(const QString &destinationDir) const;
+
+ enum Status {
+ NoError,
+ FileReadError,
+ FileOpenError,
+ FilePermissionsError,
+ FileError
+ };
+
+ Status status() const;
+
+ void close();
+
+private:
+ QZipReaderPrivate *d;
+ Q_DISABLE_COPY_MOVE(QZipReader)
+};
+Q_DECLARE_TYPEINFO(QZipReader::FileInfo, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QZipReader::Status, Q_PRIMITIVE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QZIPREADER_H
diff --git a/src/corelib/io/qzipwriter_p.h b/src/corelib/io/qzipwriter_p.h
new file mode 100644
index 0000000000..770e6118b6
--- /dev/null
+++ b/src/corelib/io/qzipwriter_p.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QZIPWRITER_H
+#define QZIPWRITER_H
+
+#include <QtCore/private/qglobal_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QZipWriter class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qstring.h>
+#include <QtCore/qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+class QZipWriterPrivate;
+
+class Q_CORE_EXPORT QZipWriter
+{
+public:
+ explicit QZipWriter(const QString &fileName, QIODevice::OpenMode mode = (QIODevice::WriteOnly | QIODevice::Truncate) );
+
+ explicit QZipWriter(QIODevice *device);
+ ~QZipWriter();
+
+ QIODevice* device() const;
+
+ bool isWritable() const;
+ bool exists() const;
+
+ enum Status {
+ NoError,
+ FileWriteError,
+ FileOpenError,
+ FilePermissionsError,
+ FileError
+ };
+
+ Status status() const;
+
+ enum CompressionPolicy {
+ AlwaysCompress,
+ NeverCompress,
+ AutoCompress
+ };
+
+ void setCompressionPolicy(CompressionPolicy policy);
+ CompressionPolicy compressionPolicy() const;
+
+ void setCreationPermissions(QFile::Permissions permissions);
+ QFile::Permissions creationPermissions() const;
+
+ void addFile(const QString &fileName, const QByteArray &data);
+
+ void addFile(const QString &fileName, QIODevice *device);
+
+ void addDirectory(const QString &dirName);
+
+ void addSymLink(const QString &fileName, const QString &destination);
+
+ void close();
+private:
+ QZipWriterPrivate *d;
+ Q_DISABLE_COPY_MOVE(QZipWriter)
+};
+
+QT_END_NAMESPACE
+
+#endif // QZIPWRITER_H
diff --git a/src/corelib/ipc/qsharedmemory.cpp b/src/corelib/ipc/qsharedmemory.cpp
new file mode 100644
index 0000000000..02761c0263
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory.cpp
@@ -0,0 +1,689 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+
+#include "qtipccommon_p.h"
+#include "qsystemsemaphore.h"
+
+#include <q20memory.h>
+#include <qdebug.h>
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
+#ifndef MAX_PATH
+# define MAX_PATH PATH_MAX
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(sharedmemory)
+
+using namespace QtIpcCommon;
+using namespace Qt::StringLiterals;
+
+QSharedMemoryPrivate::~QSharedMemoryPrivate()
+{
+ destructBackend();
+}
+
+inline void QSharedMemoryPrivate::constructBackend()
+{
+ using namespace q20;
+ visit([](auto p) { construct_at(p); });
+}
+
+inline void QSharedMemoryPrivate::destructBackend()
+{
+ visit([](auto p) { std::destroy_at(p); });
+}
+
+#if QT_CONFIG(systemsemaphore)
+inline QNativeIpcKey QSharedMemoryPrivate::semaphoreNativeKey() const
+{
+ if (isIpcSupported(IpcType::SharedMemory, QNativeIpcKey::Type::Windows)
+ && nativeKey.type() == QNativeIpcKey::Type::Windows) {
+ // native keys are plain kernel object names, limited to MAX_PATH
+ auto suffix = "_sem"_L1;
+ QString semkey = nativeKey.nativeKey();
+ semkey.truncate(MAX_PATH - suffix.size() - 1);
+ semkey += suffix;
+ return { semkey, QNativeIpcKey::Type::Windows };
+ }
+
+ // System V and POSIX keys appear to operate in different namespaces, so we
+ // can just use the same native key
+ return nativeKey;
+}
+#endif
+
+/*!
+ \class QSharedMemory
+ \inmodule QtCore
+ \since 4.4
+
+ \brief The QSharedMemory class provides access to a shared memory segment.
+
+ QSharedMemory provides access to a \l{Shared Memory}{shared memory segment}
+ by multiple threads and processes. Shared memory segments are identified by a
+ key, represented by \l QNativeIpcKey. A key can be created in a
+ cross-platform manner by using platformSafeKey().
+
+ One QSharedMemory object must create() the segment and this call specifies
+ the size of the segment. All other processes simply attach() to the segment
+ that must already exist. After either operation is successful, the
+ application may call data() to obtain a pointer to the data.
+
+ To support non-atomic operations, QSharedMemory provides API to gain
+ exclusive access: you may lock the shared memory with lock() before reading
+ from or writing to the shared memory, but remember to release the lock with
+ unlock() after you are done.
+
+ By default, QSharedMemory automatically destroys the shared memory segment
+ when the last instance of QSharedMemory is \l{detach()}{detached} from the
+ segment, and no references to the segment remain.
+
+ For details on the key types, platform-specific limitations, and
+ interoperability with older or non-Qt applications, see the \l{Native IPC
+ Keys} documentation. That includes important information for sandboxed
+ applications on Apple platforms, including all apps obtained via the Apple
+ App Store.
+
+ \sa {Inter-Process Communication}, QSystemSemaphore
+ */
+
+/*!
+ \overload QSharedMemory()
+
+ Constructs a shared memory object with the given \a parent. The shared memory
+ object's key is not set by the constructor, so the shared memory object does
+ not have an underlying shared memory segment attached. The key must be set
+ with setNativeKey() before create() or attach() can be used.
+
+ \sa setNativeKey()
+ */
+
+QSharedMemory::QSharedMemory(QObject *parent)
+ : QSharedMemory(QNativeIpcKey(), parent)
+{
+}
+
+/*!
+ \overload
+
+ Constructs a shared memory object with the given \a parent and with
+ its key set to \a key. Because its key is set, its create() and
+ attach() functions can be called.
+
+ \sa setNativeKey(), create(), attach()
+ */
+QSharedMemory::QSharedMemory(const QNativeIpcKey &key, QObject *parent)
+ : QObject(*new QSharedMemoryPrivate(key.type()), parent)
+{
+ setNativeKey(key);
+}
+
+/*!
+ Constructs a shared memory object with the given \a parent and with
+ the legacy key set to \a key. Because its key is set, its create() and
+ attach() functions can be called.
+
+ \sa setKey(), create(), attach()
+ */
+QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
+ : QSharedMemory(legacyNativeKey(key), parent)
+{
+}
+
+/*!
+ The destructor clears the key, which forces the shared memory object
+ to \l {detach()} {detach} from its underlying shared memory
+ segment. If this shared memory object is the last one connected to
+ the shared memory segment, the detach() operation destroys the
+ shared memory segment.
+
+ \sa detach(), isAttached()
+ */
+QSharedMemory::~QSharedMemory()
+{
+ Q_D(QSharedMemory);
+ if (isAttached())
+ detach();
+ d->cleanHandle();
+}
+
+/*!
+ \overload
+
+ Sets the legacy \a key for this shared memory object. If \a key is the same
+ as the current key, the function returns without doing anything. Otherwise,
+ if the shared memory object is attached to an underlying shared memory
+ segment, it will \l {detach()} {detach} from it before setting the new key.
+ This function does not do an attach().
+
+ You can call key() to retrieve the legacy key. This function is mostly the
+ same as:
+
+ \code
+ shm.setNativeKey(QSharedMemory::legacyNativeKey(key));
+ \endcode
+
+ except that it enables obtaining the legacy key using key().
+
+ \sa key(), nativeKey(), isAttached()
+*/
+void QSharedMemory::setKey(const QString &key)
+{
+ setNativeKey(legacyNativeKey(key));
+}
+
+/*!
+ \since 4.8
+ \fn void QSharedMemory::setNativeKey(const QString &key, QNativeIpcKey::Type type)
+
+ Sets the native, platform specific, \a key for this shared memory object of
+ type \a type (the type parameter has been available since Qt 6.6). If \a key
+ is the same as the current native key, the function returns without doing
+ anything. Otherwise, if the shared memory object is attached to an underlying
+ shared memory segment, it will \l {detach()} {detach} from it before setting
+ the new key. This function does not do an attach().
+
+ This function is useful if the native key was shared from another process,
+ though the application must take care to ensure the key type matches what the
+ other process expects. See \l{Native IPC Keys} for more information.
+
+ Portable native keys can be obtained using platformSafeKey().
+
+ You can call nativeKey() to retrieve the native key.
+
+ \sa nativeKey(), nativeIpcKey(), isAttached()
+*/
+
+/*!
+ \since 6.6
+
+ Sets the native, platform specific, \a key for this shared memory object. If
+ \a key is the same as the current native key, the function returns without
+ doing anything. Otherwise, if the shared memory object is attached to an
+ underlying shared memory segment, it will \l {detach()} {detach} from it
+ before setting the new key. This function does not do an attach().
+
+ This function is useful if the native key was shared from another process.
+ See \l{Native IPC Keys} for more information.
+
+ Portable native keys can be obtained using platformSafeKey().
+
+ You can call nativeKey() to retrieve the native key.
+
+ \sa nativeKey(), nativeIpcKey(), isAttached()
+*/
+void QSharedMemory::setNativeKey(const QNativeIpcKey &key)
+{
+ Q_D(QSharedMemory);
+ if (key == d->nativeKey && key.isEmpty())
+ return;
+ if (!isKeyTypeSupported(key.type())) {
+ d->setError(KeyError, tr("%1: unsupported key type")
+ .arg("QSharedMemory::setNativeKey"_L1));
+ return;
+ }
+
+ if (isAttached())
+ detach();
+ d->cleanHandle();
+ if (key.type() == d->nativeKey.type()) {
+ // we can reuse the backend
+ d->nativeKey = key;
+ } else {
+ // we must recreate the backend
+ d->destructBackend();
+ d->nativeKey = key;
+ d->constructBackend();
+ }
+}
+
+bool QSharedMemoryPrivate::initKey(SemaphoreAccessMode mode)
+{
+ if (!cleanHandle())
+ return false;
+#if QT_CONFIG(systemsemaphore)
+ const QString legacyKey = QNativeIpcKeyPrivate::legacyKey(nativeKey);
+ const QNativeIpcKey semKey = legacyKey.isEmpty()
+ ? semaphoreNativeKey()
+ : QSystemSemaphore::legacyNativeKey(legacyKey, nativeKey.type());
+ systemSemaphore.setNativeKey(semKey, 1, mode);
+ if (systemSemaphore.error() != QSystemSemaphore::NoError) {
+ QString function = "QSharedMemoryPrivate::initKey"_L1;
+ errorString = QSharedMemory::tr("%1: unable to set key on lock (%2)")
+ .arg(function, systemSemaphore.errorString());
+ switch(systemSemaphore.error()) {
+ case QSystemSemaphore::PermissionDenied:
+ error = QSharedMemory::PermissionDenied;
+ break;
+ case QSystemSemaphore::KeyError:
+ error = QSharedMemory::KeyError;
+ break;
+ case QSystemSemaphore::AlreadyExists:
+ error = QSharedMemory::AlreadyExists;
+ break;
+ case QSystemSemaphore::NotFound:
+ error = QSharedMemory::NotFound;
+ break;
+ case QSystemSemaphore::OutOfResources:
+ error = QSharedMemory::OutOfResources;
+ break;
+ case QSystemSemaphore::UnknownError:
+ default:
+ error = QSharedMemory::UnknownError;
+ break;
+ }
+ return false;
+ }
+#else
+ Q_UNUSED(mode);
+#endif
+ errorString = QString();
+ error = QSharedMemory::NoError;
+ return true;
+}
+
+/*!
+ Returns the legacy key assigned with setKey() to this shared memory, or a null key
+ if no key has been assigned, or if the segment is using a nativeKey(). The
+ key is the identifier used by Qt applications to identify the shared memory
+ segment.
+
+ You can find the native, platform specific, key used by the operating system
+ by calling nativeKey().
+
+ \sa setKey(), setNativeKey()
+ */
+QString QSharedMemory::key() const
+{
+ Q_D(const QSharedMemory);
+ return QNativeIpcKeyPrivate::legacyKey(d->nativeKey);
+}
+
+/*!
+ \since 4.8
+
+ Returns the native, platform specific, key for this shared memory object. The
+ native key is the identifier used by the operating system to identify the
+ shared memory segment.
+
+ You can use the native key to access shared memory segments that have not
+ been created by Qt, or to grant shared memory access to non-Qt applications.
+ See \l{Native IPC Keys} for more information.
+
+ \sa setNativeKey(), nativeIpcKey()
+*/
+QString QSharedMemory::nativeKey() const
+{
+ Q_D(const QSharedMemory);
+ return d->nativeKey.nativeKey();
+}
+
+/*!
+ \since 6.6
+
+ Returns the key type for this shared memory object. The key type complements
+ the nativeKey() as the identifier used by the operating system to identify
+ the shared memory segment.
+
+ You can use the native key to access shared memory segments that have not
+ been created by Qt, or to grant shared memory access to non-Qt applications.
+ See \l{Native IPC Keys} for more information.
+
+ \sa nativeKey(), setNativeKey()
+*/
+QNativeIpcKey QSharedMemory::nativeIpcKey() const
+{
+ Q_D(const QSharedMemory);
+ return d->nativeKey;
+}
+
+/*!
+ Creates a shared memory segment of \a size bytes with the key passed to the
+ constructor or set with setNativeKey(), then attaches to
+ the new shared memory segment with the given access \a mode and returns
+ \tt true. If a shared memory segment identified by the key already exists,
+ the attach operation is not performed and \tt false is returned. When the
+ return value is \tt false, call error() to determine which error occurred.
+
+ \sa error()
+ */
+bool QSharedMemory::create(qsizetype size, AccessMode mode)
+{
+ Q_D(QSharedMemory);
+ QLatin1StringView function = "QSharedMemory::create"_L1;
+
+#if QT_CONFIG(systemsemaphore)
+ if (!d->initKey(QSystemSemaphore::Create))
+ return false;
+ QSharedMemoryLocker lock(this);
+ if (!d->nativeKey.isEmpty() && !d->tryLocker(&lock, function))
+ return false;
+#else
+ if (!d->initKey({}))
+ return false;
+#endif
+
+ if (size <= 0) {
+ d->error = QSharedMemory::InvalidSize;
+ d->errorString =
+ QSharedMemory::tr("%1: create size is less then 0").arg(function);
+ return false;
+ }
+
+ if (!d->create(size))
+ return false;
+
+ return d->attach(mode);
+}
+
+/*!
+ Returns the size of the attached shared memory segment. If no shared
+ memory segment is attached, 0 is returned.
+
+ \note The size of the segment may be larger than the requested size that was
+ passed to create().
+
+ \sa create(), attach()
+ */
+qsizetype QSharedMemory::size() const
+{
+ Q_D(const QSharedMemory);
+ return d->size;
+}
+
+/*!
+ \enum QSharedMemory::AccessMode
+
+ \value ReadOnly The shared memory segment is read-only. Writing to
+ the shared memory segment is not allowed. An attempt to write to a
+ shared memory segment created with ReadOnly causes the program to
+ abort.
+
+ \value ReadWrite Reading and writing the shared memory segment are
+ both allowed.
+*/
+
+/*!
+ Attempts to attach the process to the shared memory segment
+ identified by the key that was passed to the constructor or to a
+ call to setNativeKey(). The access \a mode is \l {QSharedMemory::}
+ {ReadWrite} by default. It can also be \l {QSharedMemory::}
+ {ReadOnly}. Returns \c true if the attach operation is successful. If
+ false is returned, call error() to determine which error occurred.
+ After attaching the shared memory segment, a pointer to the shared
+ memory can be obtained by calling data().
+
+ \sa isAttached(), detach(), create()
+ */
+bool QSharedMemory::attach(AccessMode mode)
+{
+ Q_D(QSharedMemory);
+
+ if (isAttached() || !d->initKey({}))
+ return false;
+#if QT_CONFIG(systemsemaphore)
+ QSharedMemoryLocker lock(this);
+ if (!d->nativeKey.isEmpty() && !d->tryLocker(&lock, "QSharedMemory::attach"_L1))
+ return false;
+#endif
+
+ if (isAttached() || !d->handle())
+ return false;
+
+ return d->attach(mode);
+}
+
+/*!
+ Returns \c true if this process is attached to the shared memory
+ segment.
+
+ \sa attach(), detach()
+ */
+bool QSharedMemory::isAttached() const
+{
+ Q_D(const QSharedMemory);
+ return (nullptr != d->memory);
+}
+
+/*!
+ Detaches the process from the shared memory segment. If this was the
+ last process attached to the shared memory segment, then the shared
+ memory segment is released by the system, i.e., the contents are
+ destroyed. The function returns \c true if it detaches the shared
+ memory segment. If it returns \c false, it usually means the segment
+ either isn't attached, or it is locked by another process.
+
+ \sa attach(), isAttached()
+ */
+bool QSharedMemory::detach()
+{
+ Q_D(QSharedMemory);
+ if (!isAttached())
+ return false;
+
+#if QT_CONFIG(systemsemaphore)
+ QSharedMemoryLocker lock(this);
+ if (!d->nativeKey.isEmpty() && !d->tryLocker(&lock, "QSharedMemory::detach"_L1))
+ return false;
+#endif
+
+ return d->detach();
+}
+
+/*!
+ Returns a pointer to the contents of the shared memory segment, if one is
+ attached. Otherwise it returns null. The value returned by this function will
+ not change until a \l {detach()}{detach} happens, so it is safe to store this
+ pointer.
+
+ If the memory operations are not atomic, you may lock the shared memory with
+ lock() before reading from or writing, but remember to release the lock with
+ unlock() after you are done.
+
+ \sa attach()
+ */
+void *QSharedMemory::data()
+{
+ Q_D(QSharedMemory);
+ return d->memory;
+}
+
+/*!
+ Returns a const pointer to the contents of the shared memory segment, if one
+ is attached. Otherwise it returns null. The value returned by this function
+ will not change until a \l {detach()}{detach} happens, so it is safe to store
+ this pointer.
+
+ If the memory operations are not atomic, you may lock the shared memory with
+ lock() before reading from or writing, but remember to release the lock with
+ unlock() after you are done.
+
+ \sa attach(), create()
+ */
+const void *QSharedMemory::constData() const
+{
+ Q_D(const QSharedMemory);
+ return d->memory;
+}
+
+/*!
+ \overload data()
+ */
+const void *QSharedMemory::data() const
+{
+ Q_D(const QSharedMemory);
+ return d->memory;
+}
+
+#if QT_CONFIG(systemsemaphore)
+/*!
+ This is a semaphore that locks the shared memory segment for access
+ by this process and returns \c true. If another process has locked the
+ segment, this function blocks until the lock is released. Then it
+ acquires the lock and returns \c true. If this function returns \c false,
+ it means that you have ignored a false return from create() or attach(),
+ that you have set the key with setNativeKey() or that
+ QSystemSemaphore::acquire() failed due to an unknown system error.
+
+ \sa unlock(), data(), QSystemSemaphore::acquire()
+ */
+bool QSharedMemory::lock()
+{
+ Q_D(QSharedMemory);
+ if (d->lockedByMe) {
+ qWarning("QSharedMemory::lock: already locked");
+ return true;
+ }
+ if (d->systemSemaphore.acquire()) {
+ d->lockedByMe = true;
+ return true;
+ }
+ const auto function = "QSharedMemory::lock"_L1;
+ d->errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
+ d->error = QSharedMemory::LockError;
+ return false;
+}
+
+/*!
+ Releases the lock on the shared memory segment and returns \c true, if
+ the lock is currently held by this process. If the segment is not
+ locked, or if the lock is held by another process, nothing happens
+ and false is returned.
+
+ \sa lock()
+ */
+bool QSharedMemory::unlock()
+{
+ Q_D(QSharedMemory);
+ if (!d->lockedByMe)
+ return false;
+ d->lockedByMe = false;
+ if (d->systemSemaphore.release())
+ return true;
+ const auto function = "QSharedMemory::unlock"_L1;
+ d->errorString = QSharedMemory::tr("%1: unable to unlock").arg(function);
+ d->error = QSharedMemory::LockError;
+ return false;
+}
+#endif // QT_CONFIG(systemsemaphore)
+
+/*!
+ \enum QSharedMemory::SharedMemoryError
+
+ \value NoError No error occurred.
+
+ \value PermissionDenied The operation failed because the caller
+ didn't have the required permissions.
+
+ \value InvalidSize A create operation failed because the requested
+ size was invalid.
+
+ \value KeyError The operation failed because of an invalid key.
+
+ \value AlreadyExists A create() operation failed because a shared
+ memory segment with the specified key already existed.
+
+ \value NotFound An attach() failed because a shared memory segment
+ with the specified key could not be found.
+
+ \value LockError The attempt to lock() the shared memory segment
+ failed because create() or attach() failed and returned false, or
+ because a system error occurred in QSystemSemaphore::acquire().
+
+ \value OutOfResources A create() operation failed because there was
+ not enough memory available to fill the request.
+
+ \value UnknownError Something else happened and it was bad.
+*/
+
+/*!
+ Returns a value indicating whether an error occurred, and, if so,
+ which error it was.
+
+ \sa errorString()
+ */
+QSharedMemory::SharedMemoryError QSharedMemory::error() const
+{
+ Q_D(const QSharedMemory);
+ return d->error;
+}
+
+/*!
+ Returns a text description of the last error that occurred. If
+ error() returns an \l {QSharedMemory::SharedMemoryError} {error
+ value}, call this function to get a text string that describes the
+ error.
+
+ \sa error()
+ */
+QString QSharedMemory::errorString() const
+{
+ Q_D(const QSharedMemory);
+ return d->errorString;
+}
+
+void QSharedMemoryPrivate::setUnixErrorString(QLatin1StringView function)
+{
+ // EINVAL is handled in functions so they can give better error strings
+ switch (errno) {
+ case EACCES:
+ errorString = QSharedMemory::tr("%1: permission denied").arg(function);
+ error = QSharedMemory::PermissionDenied;
+ break;
+ case EEXIST:
+ errorString = QSharedMemory::tr("%1: already exists").arg(function);
+ error = QSharedMemory::AlreadyExists;
+ break;
+ case ENOENT:
+ errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
+ error = QSharedMemory::NotFound;
+ break;
+ case EMFILE:
+ case ENOMEM:
+ case ENOSPC:
+ errorString = QSharedMemory::tr("%1: out of resources").arg(function);
+ error = QSharedMemory::OutOfResources;
+ break;
+ default:
+ errorString = QSharedMemory::tr("%1: unknown error: %2")
+ .arg(function, qt_error_string(errno));
+ error = QSharedMemory::UnknownError;
+#if defined QSHAREDMEMORY_DEBUG
+ qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
+#endif
+ }
+}
+
+bool QSharedMemory::isKeyTypeSupported(QNativeIpcKey::Type type)
+{
+ if (!isIpcSupported(IpcType::SharedMemory, type))
+ return false;
+ using Variant = decltype(QSharedMemoryPrivate::backend);
+ return Variant::staticVisit(type, [](auto ptr) {
+ using Impl = std::decay_t<decltype(*ptr)>;
+ return Impl::runtimeSupportCheck();
+ });
+}
+
+QNativeIpcKey QSharedMemory::platformSafeKey(const QString &key, QNativeIpcKey::Type type)
+{
+ return QtIpcCommon::platformSafeKey(key, IpcType::SharedMemory, type);
+}
+
+QNativeIpcKey QSharedMemory::legacyNativeKey(const QString &key, QNativeIpcKey::Type type)
+{
+ return QtIpcCommon::legacyPlatformSafeKey(key, IpcType::SharedMemory, type);
+}
+
+#endif // QT_CONFIG(sharedmemory)
+
+QT_END_NAMESPACE
+
+#include "moc_qsharedmemory.cpp"
diff --git a/src/corelib/ipc/qsharedmemory.h b/src/corelib/ipc/qsharedmemory.h
new file mode 100644
index 0000000000..ab448b15c1
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory.h
@@ -0,0 +1,99 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSHAREDMEMORY_H
+#define QSHAREDMEMORY_H
+
+#include <QtCore/qtipccommon.h>
+#ifndef QT_NO_QOBJECT
+# include <QtCore/qobject.h>
+#else
+# include <QtCore/qobjectdefs.h>
+# include <QtCore/qscopedpointer.h>
+# include <QtCore/qstring.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(sharedmemory)
+
+class QSharedMemoryPrivate;
+
+class Q_CORE_EXPORT QSharedMemory : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSharedMemory)
+
+public:
+ enum AccessMode
+ {
+ ReadOnly,
+ ReadWrite
+ };
+ Q_ENUM(AccessMode)
+
+ enum SharedMemoryError
+ {
+ NoError,
+ PermissionDenied,
+ InvalidSize,
+ KeyError,
+ AlreadyExists,
+ NotFound,
+ LockError,
+ OutOfResources,
+ UnknownError
+ };
+ Q_ENUM(SharedMemoryError)
+
+ QSharedMemory(QObject *parent = nullptr);
+ QSharedMemory(const QNativeIpcKey &key, QObject *parent = nullptr);
+ ~QSharedMemory();
+
+ QSharedMemory(const QString &key, QObject *parent = nullptr);
+ void setKey(const QString &key);
+ QString key() const;
+
+ void setNativeKey(const QNativeIpcKey &key);
+ void setNativeKey(const QString &key, QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs())
+ { setNativeKey({ key, type }); }
+ QString nativeKey() const;
+ QNativeIpcKey nativeIpcKey() const;
+#if QT_CORE_REMOVED_SINCE(6, 5)
+ void setNativeKey(const QString &key);
+#endif
+
+ bool create(qsizetype size, AccessMode mode = ReadWrite);
+ qsizetype size() const;
+
+ bool attach(AccessMode mode = ReadWrite);
+ bool isAttached() const;
+ bool detach();
+
+ void *data();
+ const void* constData() const;
+ const void *data() const;
+
+#if QT_CONFIG(systemsemaphore)
+ bool lock();
+ bool unlock();
+#endif
+
+ SharedMemoryError error() const;
+ QString errorString() const;
+
+ static bool isKeyTypeSupported(QNativeIpcKey::Type type) Q_DECL_CONST_FUNCTION;
+ static QNativeIpcKey platformSafeKey(const QString &key,
+ QNativeIpcKey::Type type = QNativeIpcKey::DefaultTypeForOs);
+ static QNativeIpcKey legacyNativeKey(const QString &key,
+ QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs());
+
+private:
+ Q_DISABLE_COPY(QSharedMemory)
+};
+
+#endif // QT_CONFIG(sharedmemory)
+
+QT_END_NAMESPACE
+
+#endif // QSHAREDMEMORY_H
diff --git a/src/corelib/ipc/qsharedmemory_p.h b/src/corelib/ipc/qsharedmemory_p.h
new file mode 100644
index 0000000000..987bb38642
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory_p.h
@@ -0,0 +1,215 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSHAREDMEMORY_P_H
+#define QSHAREDMEMORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsharedmemory.h"
+
+#include <QtCore/qstring.h>
+
+#if QT_CONFIG(sharedmemory)
+#include "qsystemsemaphore.h"
+#include "qtipccommon_p.h"
+#include "private/qobject_p.h"
+
+#if QT_CONFIG(posix_shm)
+# include <sys/mman.h>
+#endif
+#if QT_CONFIG(sysv_shm)
+# include <sys/shm.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSharedMemoryPrivate;
+
+#if QT_CONFIG(systemsemaphore)
+/*!
+ Helper class
+ */
+class QSharedMemoryLocker
+{
+
+public:
+ Q_NODISCARD_CTOR QSharedMemoryLocker(QSharedMemory *sharedMemory) : q_sm(sharedMemory)
+ {
+ Q_ASSERT(q_sm);
+ }
+
+ inline ~QSharedMemoryLocker()
+ {
+ if (q_sm)
+ q_sm->unlock();
+ }
+
+ inline bool lock()
+ {
+ if (q_sm && q_sm->lock())
+ return true;
+ q_sm = nullptr;
+ return false;
+ }
+
+private:
+ QSharedMemory *q_sm;
+};
+#endif // QT_CONFIG(systemsemaphore)
+
+class QSharedMemoryPosix
+{
+public:
+ static constexpr bool Enabled = QT_CONFIG(posix_shm);
+ static bool supports(QNativeIpcKey::Type type)
+ { return type == QNativeIpcKey::Type::PosixRealtime; }
+ static bool runtimeSupportCheck();
+
+ bool handle(QSharedMemoryPrivate *self);
+ bool cleanHandle(QSharedMemoryPrivate *self);
+ bool create(QSharedMemoryPrivate *self, qsizetype size);
+ bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
+ bool detach(QSharedMemoryPrivate *self);
+
+ int hand = -1;
+};
+
+class QSharedMemorySystemV
+{
+public:
+ static constexpr bool Enabled = QT_CONFIG(sysv_shm);
+ static bool supports(QNativeIpcKey::Type type)
+ { return quint16(type) <= 0xff; }
+ static bool runtimeSupportCheck();
+
+#if QT_CONFIG(sysv_sem)
+ key_t handle(QSharedMemoryPrivate *self);
+ bool cleanHandle(QSharedMemoryPrivate *self);
+ bool create(QSharedMemoryPrivate *self, qsizetype size);
+ bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
+ bool detach(QSharedMemoryPrivate *self);
+
+private:
+ void updateNativeKeyFile(const QNativeIpcKey &nativeKey);
+
+ QByteArray nativeKeyFile;
+ key_t unix_key = 0;
+#endif
+};
+
+class QSharedMemoryWin32
+{
+public:
+#ifdef Q_OS_WIN32
+ static constexpr bool Enabled = true;
+#else
+ static constexpr bool Enabled = false;
+#endif
+ static bool runtimeSupportCheck() { return Enabled; }
+ static bool supports(QNativeIpcKey::Type type)
+ { return type == QNativeIpcKey::Type::Windows; }
+
+ Qt::HANDLE handle(QSharedMemoryPrivate *self);
+ bool cleanHandle(QSharedMemoryPrivate *self);
+ bool create(QSharedMemoryPrivate *self, qsizetype size);
+ bool attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode);
+ bool detach(QSharedMemoryPrivate *self);
+
+ Qt::HANDLE hand = nullptr;
+};
+
+class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSharedMemory)
+
+public:
+ QSharedMemoryPrivate(QNativeIpcKey::Type type) : nativeKey(type)
+ { constructBackend(); }
+ ~QSharedMemoryPrivate();
+
+ void *memory = nullptr;
+ qsizetype size = 0;
+ QNativeIpcKey nativeKey;
+ QString errorString;
+#if QT_CONFIG(systemsemaphore)
+ using SemaphoreAccessMode = QSystemSemaphore::AccessMode;
+ QSystemSemaphore systemSemaphore{ QNativeIpcKey() };
+ bool lockedByMe = false;
+#else
+ enum SemaphoreAccessMode {};
+#endif
+ QSharedMemory::SharedMemoryError error = QSharedMemory::NoError;
+
+ union Backend {
+ Backend() {}
+ ~Backend() {}
+ QSharedMemoryPosix posix;
+ QSharedMemorySystemV sysv;
+ QSharedMemoryWin32 win32;
+ };
+ QtIpcCommon::IpcStorageVariant<&Backend::posix, &Backend::sysv, &Backend::win32> backend;
+
+ void constructBackend();
+ void destructBackend();
+ bool initKey(SemaphoreAccessMode mode);
+
+ template <typename Lambda> auto visit(const Lambda &lambda)
+ {
+ return backend.visit(nativeKey.type(), lambda);
+ }
+
+ bool handle()
+ {
+ return visit([&](auto p) { return !!p->handle(this); });
+ }
+ bool cleanHandle()
+ {
+ return visit([&](auto p) { return p->cleanHandle(this); });
+ }
+ bool create(qsizetype size)
+ {
+ return visit([&](auto p) { return p->create(this, size); });
+ }
+ bool attach(QSharedMemory::AccessMode mode)
+ {
+ return visit([&](auto p) { return p->attach(this, mode); });
+ }
+ bool detach()
+ {
+ return visit([&](auto p) { return p->detach(this); });
+ }
+
+ inline void setError(QSharedMemory::SharedMemoryError e, const QString &message)
+ { error = e; errorString = message; }
+ void setUnixErrorString(QLatin1StringView function);
+ void setWindowsErrorString(QLatin1StringView function);
+
+#if QT_CONFIG(systemsemaphore)
+ bool tryLocker(QSharedMemoryLocker *locker, const QString &function) {
+ if (!locker->lock()) {
+ errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
+ error = QSharedMemory::LockError;
+ return false;
+ }
+ return true;
+ }
+ QNativeIpcKey semaphoreNativeKey() const;
+#endif // QT_CONFIG(systemsemaphore)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(sharedmemory)
+
+#endif // QSHAREDMEMORY_P_H
+
diff --git a/src/corelib/ipc/qsharedmemory_posix.cpp b/src/corelib/ipc/qsharedmemory_posix.cpp
new file mode 100644
index 0000000000..582c6628e1
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory_posix.cpp
@@ -0,0 +1,196 @@
+// Copyright (C) 2015 Konstantin Ritt <ritt.ks@gmail.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qtipccommon_p.h"
+#include <qfile.h>
+
+#include <errno.h>
+
+#if QT_CONFIG(sharedmemory)
+#if QT_CONFIG(posix_shm)
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "private/qcore_unix_p.h"
+
+#ifndef O_CLOEXEC
+# define O_CLOEXEC 0
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+using namespace QtIpcCommon;
+
+bool QSharedMemoryPosix::runtimeSupportCheck()
+{
+ static const bool result = []() {
+ (void)shm_open("", 0, 0); // this WILL fail
+ return errno != ENOSYS;
+ }();
+ return result;
+}
+
+bool QSharedMemoryPosix::handle(QSharedMemoryPrivate *self)
+{
+ // don't allow making handles on empty keys
+ if (self->nativeKey.isEmpty()) {
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: key is empty").arg("QSharedMemory::handle"_L1));
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPosix::cleanHandle(QSharedMemoryPrivate *)
+{
+ if (hand != -1)
+ qt_safe_close(hand);
+ hand = -1;
+
+ return true;
+}
+
+bool QSharedMemoryPosix::create(QSharedMemoryPrivate *self, qsizetype size)
+{
+ if (!handle(self))
+ return false;
+
+ const QByteArray shmName = QFile::encodeName(self->nativeKey.nativeKey());
+
+ int fd;
+ QT_EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600));
+ if (fd == -1) {
+ const int errorNumber = errno;
+ const auto function = "QSharedMemory::attach (shm_open)"_L1;
+ switch (errorNumber) {
+ case EINVAL:
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: bad name").arg(function));
+ break;
+ default:
+ self->setUnixErrorString(function);
+ }
+ return false;
+ }
+
+ // the size may only be set once
+ int ret;
+ QT_EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
+ if (ret == -1) {
+ self->setUnixErrorString("QSharedMemory::create (ftruncate)"_L1);
+ qt_safe_close(fd);
+ return false;
+ }
+
+ qt_safe_close(fd);
+
+ return true;
+}
+
+bool QSharedMemoryPosix::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
+{
+ const QByteArray shmName = QFile::encodeName(self->nativeKey.nativeKey());
+
+ const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
+ const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
+
+ QT_EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag | O_CLOEXEC, omode));
+ if (hand == -1) {
+ const int errorNumber = errno;
+ const auto function = "QSharedMemory::attach (shm_open)"_L1;
+ switch (errorNumber) {
+ case EINVAL:
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: bad name").arg(function));
+ break;
+ default:
+ self->setUnixErrorString(function);
+ }
+ hand = -1;
+ return false;
+ }
+
+ // grab the size
+ QT_STATBUF st;
+ if (QT_FSTAT(hand, &st) == -1) {
+ self->setUnixErrorString("QSharedMemory::attach (fstat)"_L1);
+ cleanHandle(self);
+ return false;
+ }
+ self->size = qsizetype(st.st_size);
+
+ // grab the memory
+ const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
+ self->memory = QT_MMAP(0, size_t(self->size), mprot, MAP_SHARED, hand, 0);
+ if (self->memory == MAP_FAILED || !self->memory) {
+ self->setUnixErrorString("QSharedMemory::attach (mmap)"_L1);
+ cleanHandle(self);
+ self->memory = 0;
+ self->size = 0;
+ return false;
+ }
+
+#ifdef F_ADD_SEALS
+ // Make sure the shared memory region will not shrink
+ // otherwise someone could cause SIGBUS on us.
+ // (see http://lwn.net/Articles/594919/)
+ fcntl(hand, F_ADD_SEALS, F_SEAL_SHRINK);
+#endif
+
+ return true;
+}
+
+bool QSharedMemoryPosix::detach(QSharedMemoryPrivate *self)
+{
+ // detach from the memory segment
+ if (::munmap(self->memory, size_t(self->size)) == -1) {
+ self->setUnixErrorString("QSharedMemory::detach (munmap)"_L1);
+ return false;
+ }
+ self->memory = 0;
+ self->size = 0;
+
+#ifdef Q_OS_QNX
+ // On QNX the st_nlink field of struct stat contains the number of
+ // active shm_open() connections to the shared memory file, so we
+ // can use it to automatically clean up the file once the last
+ // user has detached from it.
+
+ // get the number of current attachments
+ int shm_nattch = 0;
+ QT_STATBUF st;
+ if (QT_FSTAT(hand, &st) == 0) {
+ // subtract 2 from linkcount: one for our own open and one for the dir entry
+ shm_nattch = st.st_nlink - 2;
+ }
+
+ cleanHandle(self);
+
+ // if there are no attachments then unlink the shared memory
+ if (shm_nattch == 0) {
+ const QByteArray shmName = QFile::encodeName(self->nativeKey.nativeKey());
+ if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
+ self->setUnixErrorString("QSharedMemory::detach (shm_unlink)"_L1);
+ }
+#else
+ // On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
+ // so we'll simply leak the shared memory files.
+ cleanHandle(self);
+#endif
+
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(posix_shm)
+#endif // QT_CONFIG(sharedmemory)
diff --git a/src/corelib/ipc/qsharedmemory_systemv.cpp b/src/corelib/ipc/qsharedmemory_systemv.cpp
new file mode 100644
index 0000000000..dc9de11091
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory_systemv.cpp
@@ -0,0 +1,212 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+
+#include "qtipccommon_p.h"
+
+#include <qdir.h>
+#include <qdebug.h>
+
+#include <errno.h>
+
+#if QT_CONFIG(sharedmemory)
+#if QT_CONFIG(sysv_shm)
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "private/qcore_unix_p.h"
+#if defined(Q_OS_DARWIN)
+#include "private/qcore_mac_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+using namespace QtIpcCommon;
+
+bool QSharedMemorySystemV::runtimeSupportCheck()
+{
+#if defined(Q_OS_DARWIN)
+ if (qt_apple_isSandboxed())
+ return false;
+#endif
+ static const bool result = []() {
+ (void)shmget(IPC_PRIVATE, ~size_t(0), 0); // this will fail
+ return errno != ENOSYS;
+ }();
+ return result;
+}
+
+
+inline void QSharedMemorySystemV::updateNativeKeyFile(const QNativeIpcKey &nativeKey)
+{
+ Q_ASSERT(nativeKeyFile.isEmpty() );
+ if (!nativeKey.nativeKey().isEmpty())
+ nativeKeyFile = QFile::encodeName(nativeKey.nativeKey());
+}
+
+/*!
+ \internal
+
+ If not already made create the handle used for accessing the shared memory.
+*/
+key_t QSharedMemorySystemV::handle(QSharedMemoryPrivate *self)
+{
+ // already made
+ if (unix_key)
+ return unix_key;
+
+ // don't allow making handles on empty keys
+ if (nativeKeyFile.isEmpty())
+ updateNativeKeyFile(self->nativeKey);
+ if (nativeKeyFile.isEmpty()) {
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: key is empty")
+ .arg("QSharedMemory::handle:"_L1));
+ return 0;
+ }
+
+ unix_key = ftok(nativeKeyFile, int(self->nativeKey.type()));
+ if (unix_key < 0) {
+ self->setUnixErrorString("QSharedMemory::handle"_L1);
+ nativeKeyFile.clear();
+ unix_key = 0;
+ }
+ return unix_key;
+}
+
+bool QSharedMemorySystemV::cleanHandle(QSharedMemoryPrivate *self)
+{
+ if (unix_key == 0)
+ return true;
+
+ // Get the number of current attachments
+ struct shmid_ds shmid_ds;
+ QByteArray keyfile = std::exchange(nativeKeyFile, QByteArray());
+
+ int id = shmget(unix_key, 0, 0400);
+ unix_key = 0;
+ if (shmctl(id, IPC_STAT, &shmid_ds))
+ return errno != EINVAL;
+
+ // If there are still attachments, keep the keep file and shm
+ if (shmid_ds.shm_nattch != 0)
+ return true;
+
+ if (shmctl(id, IPC_RMID, &shmid_ds) < 0) {
+ if (errno != EINVAL) {
+ self->setUnixErrorString("QSharedMemory::remove"_L1);
+ return false;
+ }
+ };
+
+ // remove file
+ return unlink(keyfile) == 0;
+}
+
+bool QSharedMemorySystemV::create(QSharedMemoryPrivate *self, qsizetype size)
+{
+ // build file if needed
+ bool createdFile = false;
+ updateNativeKeyFile(self->nativeKey);
+ int built = createUnixKeyFile(nativeKeyFile);
+ if (built == -1) {
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: unable to make key")
+ .arg("QSharedMemory::handle:"_L1));
+ return false;
+ }
+ if (built == 1) {
+ createdFile = true;
+ }
+
+ // get handle
+ if (!handle(self)) {
+ if (createdFile)
+ unlink(nativeKeyFile);
+ return false;
+ }
+
+ // create
+ if (-1 == shmget(unix_key, size_t(size), 0600 | IPC_CREAT | IPC_EXCL)) {
+ const auto function = "QSharedMemory::create"_L1;
+ switch (errno) {
+ case EINVAL:
+ self->setError(QSharedMemory::InvalidSize,
+ QSharedMemory::tr("%1: system-imposed size restrictions")
+ .arg("QSharedMemory::handle"_L1));
+ break;
+ default:
+ self->setUnixErrorString(function);
+ }
+ if (createdFile && self->error != QSharedMemory::AlreadyExists)
+ unlink(nativeKeyFile);
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemorySystemV::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
+{
+ // grab the shared memory segment id
+ int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
+ if (-1 == id) {
+ self->setUnixErrorString("QSharedMemory::attach (shmget)"_L1);
+ unix_key = 0;
+ nativeKeyFile.clear();
+ return false;
+ }
+
+ // grab the memory
+ self->memory = shmat(id, nullptr, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
+ if (self->memory == MAP_FAILED) {
+ self->memory = nullptr;
+ self->setUnixErrorString("QSharedMemory::attach (shmat)"_L1);
+ return false;
+ }
+
+ // grab the size
+ shmid_ds shmid_ds;
+ if (!shmctl(id, IPC_STAT, &shmid_ds)) {
+ self->size = (qsizetype)shmid_ds.shm_segsz;
+ } else {
+ self->setUnixErrorString("QSharedMemory::attach (shmctl)"_L1);
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemorySystemV::detach(QSharedMemoryPrivate *self)
+{
+ // detach from the memory segment
+ if (shmdt(self->memory) < 0) {
+ const auto function = "QSharedMemory::detach"_L1;
+ switch (errno) {
+ case EINVAL:
+ self->setError(QSharedMemory::NotFound,
+ QSharedMemory::tr("%1: not attached").arg(function));
+ break;
+ default:
+ self->setUnixErrorString(function);
+ }
+ return false;
+ }
+ self->memory = nullptr;
+ self->size = 0;
+
+ return cleanHandle(self);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(sysv_shm)
+#endif // QT_CONFIG(sharedmemory)
diff --git a/src/corelib/ipc/qsharedmemory_win.cpp b/src/corelib/ipc/qsharedmemory_win.cpp
new file mode 100644
index 0000000000..472f34f9a1
--- /dev/null
+++ b/src/corelib/ipc/qsharedmemory_win.cpp
@@ -0,0 +1,148 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdebug.h>
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+#if QT_CONFIG(sharedmemory)
+
+void QSharedMemoryPrivate::setWindowsErrorString(QLatin1StringView function)
+{
+ DWORD windowsError = GetLastError();
+ if (windowsError == 0)
+ return;
+ switch (windowsError) {
+ case ERROR_ALREADY_EXISTS:
+ error = QSharedMemory::AlreadyExists;
+ errorString = QSharedMemory::tr("%1: already exists").arg(function);
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ error = QSharedMemory::NotFound;
+ errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
+ break;
+ case ERROR_COMMITMENT_LIMIT:
+ error = QSharedMemory::InvalidSize;
+ errorString = QSharedMemory::tr("%1: invalid size").arg(function);
+ break;
+ case ERROR_NO_SYSTEM_RESOURCES:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ error = QSharedMemory::OutOfResources;
+ errorString = QSharedMemory::tr("%1: out of resources").arg(function);
+ break;
+ case ERROR_ACCESS_DENIED:
+ error = QSharedMemory::PermissionDenied;
+ errorString = QSharedMemory::tr("%1: permission denied").arg(function);
+ break;
+ default:
+ errorString = QSharedMemory::tr("%1: unknown error: %2")
+ .arg(function, qt_error_string(windowsError));
+ error = QSharedMemory::UnknownError;
+#if defined QSHAREDMEMORY_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+ }
+}
+
+HANDLE QSharedMemoryWin32::handle(QSharedMemoryPrivate *self)
+{
+ if (!hand) {
+ const auto function = "QSharedMemory::handle"_L1;
+ if (self->nativeKey.isEmpty()) {
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: unable to make key").arg(function));
+ return 0;
+ }
+ hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
+ reinterpret_cast<const wchar_t *>(self->nativeKey.nativeKey().utf16()));
+ if (!hand) {
+ self->setWindowsErrorString(function);
+ return 0;
+ }
+ }
+ return hand;
+}
+
+bool QSharedMemoryWin32::cleanHandle(QSharedMemoryPrivate *)
+{
+ if (hand != 0 && !CloseHandle(hand)) {
+ hand = 0;
+ return false;
+ }
+ hand = 0;
+ return true;
+}
+
+bool QSharedMemoryWin32::create(QSharedMemoryPrivate *self, qsizetype size)
+{
+ const auto function = "QSharedMemory::create"_L1;
+ if (self->nativeKey.isEmpty()) {
+ self->setError(QSharedMemory::KeyError,
+ QSharedMemory::tr("%1: key error").arg(function));
+ return false;
+ }
+
+ // Create the file mapping.
+ DWORD high, low;
+ if constexpr (sizeof(qsizetype) == 8)
+ high = DWORD(quint64(size) >> 32);
+ else
+ high = 0;
+ low = DWORD(size_t(size) & 0xffffffff);
+ hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, high, low,
+ reinterpret_cast<const wchar_t *>(self->nativeKey.nativeKey().utf16()));
+ self->setWindowsErrorString(function);
+
+ // hand is valid when it already exists unlike unix so explicitly check
+ return self->error != QSharedMemory::AlreadyExists && hand;
+}
+
+bool QSharedMemoryWin32::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
+{
+ // Grab a pointer to the memory block
+ int permissions = (mode == QSharedMemory::ReadOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
+ self->memory = (void *)MapViewOfFile(handle(self), permissions, 0, 0, 0);
+ if (!self->memory) {
+ self->setWindowsErrorString("QSharedMemory::attach"_L1);
+ cleanHandle(self);
+ return false;
+ }
+
+ // Grab the size of the memory we have been given (a multiple of 4K on windows)
+ MEMORY_BASIC_INFORMATION info;
+ if (!VirtualQuery(self->memory, &info, sizeof(info))) {
+ // Windows doesn't set an error code on this one,
+ // it should only be a kernel memory error.
+ self->setError(QSharedMemory::UnknownError,
+ QSharedMemory::tr("%1: size query failed")
+ .arg("QSharedMemory::attach: "_L1));
+ return false;
+ }
+ self->size = qsizetype(info.RegionSize);
+
+ return true;
+}
+
+bool QSharedMemoryWin32::detach(QSharedMemoryPrivate *self)
+{
+ // umap memory
+ if (!UnmapViewOfFile(self->memory)) {
+ self->setWindowsErrorString("QSharedMemory::detach"_L1);
+ return false;
+ }
+ self->memory = 0;
+ self->size = 0;
+
+ // close handle
+ return cleanHandle(self);
+}
+
+#endif // QT_CONFIG(sharedmemory)
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/ipc/qsystemsemaphore.cpp
index 011a673d69..4c24ef6043 100644
--- a/src/corelib/kernel/qsystemsemaphore.cpp
+++ b/src/corelib/ipc/qsystemsemaphore.cpp
@@ -1,49 +1,26 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsystemsemaphore.h"
#include "qsystemsemaphore_p.h"
-#include <qglobal.h>
+
+#if QT_CONFIG(systemsemaphore)
+#include <QtCore/q20memory.h>
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_SYSTEMSEMAPHORE
+using namespace QtIpcCommon;
+using namespace Qt::StringLiterals;
+
+inline void QSystemSemaphorePrivate::constructBackend()
+{
+ visit([](auto p) { q20::construct_at(p); });
+}
+
+inline void QSystemSemaphorePrivate::destructBackend()
+{
+ visit([](auto p) { std::destroy_at(p); });
+}
/*!
\class QSystemSemaphore
@@ -52,12 +29,10 @@ QT_BEGIN_NAMESPACE
\brief The QSystemSemaphore class provides a general counting system semaphore.
- A semaphore is a generalization of a mutex. While a mutex can be
- locked only once, a semaphore can be acquired multiple times.
- Typically, a semaphore is used to protect a certain number of
- identical resources.
+ A system semaphore is a generalization of \l QSemaphore. Typically, a
+ semaphore is used to protect a certain number of identical resources.
- Like its lighter counterpart QSemaphore, a QSystemSemaphore can be
+ Like its lighter counterpart, a QSystemSemaphore can be
accessed from multiple \l {QThread} {threads}. Unlike QSemaphore, a
QSystemSemaphore can also be accessed from multiple \l {QProcess}
{processes}. This means QSystemSemaphore is a much heavier class, so
@@ -74,60 +49,34 @@ QT_BEGIN_NAMESPACE
process. The function can also be called with a parameter n > 1,
which releases n resources.
- A system semaphore is created with a string key that other processes
- can use to use the same semaphore.
+ System semaphores are identified by a key, represented by \l QNativeIpcKey. A
+ key can be created in a cross-platform manner by using platformSafeKey(). A
+ system semaphore is created by the QSystemSemaphore constructor when passed
+ an access mode parameter of AccessMode::Create. Once it is created, other
+ processes may attach to the same semaphore using the same key and an access
+ mode parameter of AccessMode::Open.
Example: Create a system semaphore
\snippet code/src_corelib_kernel_qsystemsemaphore.cpp 0
- A typical application of system semaphores is for controlling access
- to a circular buffer shared by a producer process and a consumer
- processes.
-
- \section1 Platform-Specific Behavior
-
- When using this class, be aware of the following platform
- differences:
-
- \b{Windows:} QSystemSemaphore does not own its underlying system
- semaphore. Windows owns it. This means that when all instances of
- QSystemSemaphore for a particular key have been destroyed, either by
- having their destructors called, or because one or more processes
- crash, Windows removes the underlying system semaphore.
-
- \b{Unix:}
-
- \list
- \li QSystemSemaphore owns the underlying system semaphore
- in Unix systems. This means that the last process having an instance of
- QSystemSemaphore for a particular key must remove the underlying
- system semaphore in its destructor. If the last process crashes
- without running the QSystemSemaphore destructor, Unix does not
- automatically remove the underlying system semaphore, and the
- semaphore survives the crash. A subsequent process that constructs a
- QSystemSemaphore with the same key will then be given the existing
- system semaphore. In that case, if the QSystemSemaphore constructor
- has specified its \l {QSystemSemaphore::AccessMode} {access mode} as
- \l {QSystemSemaphore::} {Open}, its initial resource count will not
- be reset to the one provided but remain set to the value it received
- in the crashed process. To protect against this, the first process
- to create a semaphore for a particular key (usually a server), must
- pass its \l {QSystemSemaphore::AccessMode} {access mode} as \l
- {QSystemSemaphore::} {Create}, which will force Unix to reset the
- resource count in the underlying system semaphore.
-
- \li When a process using QSystemSemaphore terminates for
- any reason, Unix automatically reverses the effect of all acquire
- operations that were not released. Thus if the process acquires a
- resource and then exits without releasing it, Unix will release that
- resource.
-
- \endlist
-
- \sa QSharedMemory, QSemaphore
+ For details on the key types, platform-specific limitations, and
+ interoperability with older or non-Qt applications, see the \l{Native IPC
+ Keys} documentation. That includes important information for sandboxed
+ applications on Apple platforms, including all apps obtained via the Apple
+ App Store.
+
+ \sa {Inter-Process Communication}, QSharedMemory, QSemaphore
*/
/*!
+ Requests a system semaphore identified by the legacy key \a key.
+ */
+QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
+ : QSystemSemaphore(legacyNativeKey(key), initialValue, mode)
+{
+}
+
+/*!
Requests a system semaphore for the specified \a key. The parameters
\a initialValue and \a mode are used according to the following
rules, which are system dependent.
@@ -163,10 +112,10 @@ QT_BEGIN_NAMESPACE
\sa acquire(), key()
*/
-QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
- : d(new QSystemSemaphorePrivate)
+QSystemSemaphore::QSystemSemaphore(const QNativeIpcKey &key, int initialValue, AccessMode mode)
+ : d(new QSystemSemaphorePrivate(key.type()))
{
- setKey(key, initialValue, mode);
+ setNativeKey(key, initialValue, mode);
}
/*!
@@ -221,27 +170,33 @@ QSystemSemaphore::~QSystemSemaphore()
create a new semaphore with the new \a key. The \a initialValue and
\a mode parameters are as defined for the constructor.
- \sa QSystemSemaphore(), key()
+ This function is useful if the native key was shared from another process.
+ See \l{Native IPC Keys} for more information.
+
+ \sa QSystemSemaphore(), nativeIpcKey()
*/
-void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode mode)
+void QSystemSemaphore::setNativeKey(const QNativeIpcKey &key, int initialValue, AccessMode mode)
{
- if (key == d->key && mode == Open)
+ if (key == d->nativeKey && mode == Open)
return;
- d->clearError();
-#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
- // optimization to not destroy/create the file & semaphore
- if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) {
- d->initialValue = initialValue;
- d->unix_key = -1;
- d->handle(mode);
+ if (!isKeyTypeSupported(key.type())) {
+ d->setError(KeyError, tr("%1: unsupported key type")
+ .arg("QSystemSemaphore::setNativeKey"_L1));
return;
}
-#endif
+
+ d->clearError();
d->cleanHandle();
- d->key = key;
+ if (key.type() == d->nativeKey.type()) {
+ // we can reuse the backend
+ d->nativeKey = key;
+ } else {
+ // we must recreate the backend
+ d->destructBackend();
+ d->nativeKey = key;
+ d->constructBackend();
+ }
d->initialValue = initialValue;
- // cache the file name so it doesn't have to be generated all the time.
- d->fileName = d->makeKeyFileName();
d->handle(mode);
}
@@ -249,11 +204,41 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m
Returns the key assigned to this system semaphore. The key is the
name by which the semaphore can be accessed from other processes.
+ You can use the native key to access system semaphores that have not been
+ created by Qt, or to grant access to non-Qt applications. See \l{Native IPC
+ Keys} for more information.
+
+ \sa setNativeKey()
+ */
+QNativeIpcKey QSystemSemaphore::nativeIpcKey() const
+{
+ return d->nativeKey;
+}
+
+/*!
+ This function works the same as the constructor. It reconstructs
+ this QSystemSemaphore object. If the new \a key is different from
+ the old key, calling this function is like calling the destructor of
+ the semaphore with the old key, then calling the constructor to
+ create a new semaphore with the new \a key. The \a initialValue and
+ \a mode parameters are as defined for the constructor.
+
+ \sa QSystemSemaphore(), key()
+ */
+void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode mode)
+{
+ setNativeKey(legacyNativeKey(key), initialValue, mode);
+}
+
+/*!
+ Returns the legacy key assigned to this system semaphore. The key is the
+ name by which the semaphore can be accessed from other processes.
+
\sa setKey()
*/
QString QSystemSemaphore::key() const
{
- return d->key;
+ return QNativeIpcKeyPrivate::legacyKey(d->nativeKey);
}
/*!
@@ -352,6 +337,66 @@ QString QSystemSemaphore::errorString() const
return d->errorString;
}
-#endif // QT_NO_SYSTEMSEMAPHORE
+void QSystemSemaphorePrivate::setUnixErrorString(QLatin1StringView function)
+{
+ // EINVAL is handled in functions so they can give better error strings
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ errorString = QSystemSemaphore::tr("%1: permission denied").arg(function);
+ error = QSystemSemaphore::PermissionDenied;
+ break;
+ case EEXIST:
+ errorString = QSystemSemaphore::tr("%1: already exists").arg(function);
+ error = QSystemSemaphore::AlreadyExists;
+ break;
+ case ENOENT:
+ errorString = QSystemSemaphore::tr("%1: does not exist").arg(function);
+ error = QSystemSemaphore::NotFound;
+ break;
+ case ERANGE:
+ case ENOSPC:
+ case EMFILE:
+ errorString = QSystemSemaphore::tr("%1: out of resources").arg(function);
+ error = QSystemSemaphore::OutOfResources;
+ break;
+ case ENAMETOOLONG:
+ errorString = QSystemSemaphore::tr("%1: key too long").arg(function);
+ error = QSystemSemaphore::KeyError;
+ break;
+ default:
+ errorString = QSystemSemaphore::tr("%1: unknown error: %2")
+ .arg(function, qt_error_string(errno));
+ error = QSystemSemaphore::UnknownError;
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
+#endif
+ }
+}
+
+bool QSystemSemaphore::isKeyTypeSupported(QNativeIpcKey::Type type)
+{
+ if (!isIpcSupported(IpcType::SystemSemaphore, type))
+ return false;
+ using Variant = decltype(QSystemSemaphorePrivate::backend);
+ return Variant::staticVisit(type, [](auto ptr) {
+ using Impl = std::decay_t<decltype(*ptr)>;
+ return Impl::runtimeSupportCheck();
+ });
+}
+
+QNativeIpcKey QSystemSemaphore::platformSafeKey(const QString &key, QNativeIpcKey::Type type)
+{
+ return QtIpcCommon::platformSafeKey(key, IpcType::SystemSemaphore, type);
+}
+
+QNativeIpcKey QSystemSemaphore::legacyNativeKey(const QString &key, QNativeIpcKey::Type type)
+{
+ return QtIpcCommon::legacyPlatformSafeKey(key, IpcType::SystemSemaphore, type);
+}
QT_END_NAMESPACE
+
+#include "moc_qsystemsemaphore.cpp"
+
+#endif // QT_CONFIG(systemsemaphore)
diff --git a/src/corelib/ipc/qsystemsemaphore.h b/src/corelib/ipc/qsystemsemaphore.h
new file mode 100644
index 0000000000..df6fd28342
--- /dev/null
+++ b/src/corelib/ipc/qsystemsemaphore.h
@@ -0,0 +1,75 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSYSTEMSEMAPHORE_H
+#define QSYSTEMSEMAPHORE_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qtipccommon.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(systemsemaphore)
+
+class QSystemSemaphorePrivate;
+
+class Q_CORE_EXPORT QSystemSemaphore
+{
+ Q_GADGET
+ Q_DECLARE_TR_FUNCTIONS(QSystemSemaphore)
+public:
+ enum AccessMode
+ {
+ Open,
+ Create
+ };
+ Q_ENUM(AccessMode)
+
+ enum SystemSemaphoreError
+ {
+ NoError,
+ PermissionDenied,
+ KeyError,
+ AlreadyExists,
+ NotFound,
+ OutOfResources,
+ UnknownError
+ };
+
+ QSystemSemaphore(const QNativeIpcKey &key, int initialValue = 0, AccessMode = Open);
+ ~QSystemSemaphore();
+
+ void setNativeKey(const QNativeIpcKey &key, int initialValue = 0, AccessMode = Open);
+ void setNativeKey(const QString &key, int initialValue = 0, AccessMode mode = Open,
+ QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs())
+ { setNativeKey({ key, type }, initialValue, mode); }
+ QNativeIpcKey nativeIpcKey() const;
+
+ QSystemSemaphore(const QString &key, int initialValue = 0, AccessMode mode = Open);
+ void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open);
+ QString key() const;
+
+ bool acquire();
+ bool release(int n = 1);
+
+ SystemSemaphoreError error() const;
+ QString errorString() const;
+
+ static bool isKeyTypeSupported(QNativeIpcKey::Type type) Q_DECL_CONST_FUNCTION;
+ static QNativeIpcKey platformSafeKey(const QString &key,
+ QNativeIpcKey::Type type = QNativeIpcKey::DefaultTypeForOs);
+ static QNativeIpcKey legacyNativeKey(const QString &key,
+ QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs());
+
+private:
+ Q_DISABLE_COPY(QSystemSemaphore)
+ QScopedPointer<QSystemSemaphorePrivate> d;
+};
+
+#endif // QT_CONFIG(systemsemaphore)
+
+QT_END_NAMESPACE
+
+#endif // QSYSTEMSEMAPHORE_H
diff --git a/src/corelib/ipc/qsystemsemaphore_p.h b/src/corelib/ipc/qsystemsemaphore_p.h
new file mode 100644
index 0000000000..788c4fb784
--- /dev/null
+++ b/src/corelib/ipc/qsystemsemaphore_p.h
@@ -0,0 +1,152 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSYSTEMSEMAPHORE_P_H
+#define QSYSTEMSEMAPHORE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsystemsemaphore.h"
+
+#if QT_CONFIG(systemsemaphore)
+
+#include "qcoreapplication.h"
+#include "qtipccommon_p.h"
+#include "private/qtcore-config_p.h"
+
+#include <sys/types.h>
+#if QT_CONFIG(posix_sem)
+# include <semaphore.h>
+#endif
+#ifndef SEM_FAILED
+# define SEM_FAILED nullptr
+struct sem_t;
+#endif
+#if QT_CONFIG(sysv_sem)
+# include <sys/sem.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSystemSemaphorePrivate;
+
+struct QSystemSemaphorePosix
+{
+ static constexpr bool Enabled = QT_CONFIG(posix_sem);
+ static bool supports(QNativeIpcKey::Type type)
+ { return type == QNativeIpcKey::Type::PosixRealtime; }
+ static bool runtimeSupportCheck();
+
+ bool handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
+ void cleanHandle(QSystemSemaphorePrivate *self);
+ bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
+
+ sem_t *semaphore = SEM_FAILED;
+ bool createdSemaphore = false;
+};
+
+struct QSystemSemaphoreSystemV
+{
+ static constexpr bool Enabled = QT_CONFIG(sysv_sem);
+ static bool supports(QNativeIpcKey::Type type)
+ { return quint16(type) <= 0xff; }
+ static bool runtimeSupportCheck();
+
+#if QT_CONFIG(sysv_sem)
+ key_t handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
+ void cleanHandle(QSystemSemaphorePrivate *self);
+ bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
+
+ QByteArray nativeKeyFile;
+ key_t unix_key = -1;
+ int semaphore = -1;
+ bool createdFile = false;
+ bool createdSemaphore = false;
+#endif
+};
+
+struct QSystemSemaphoreWin32
+{
+#ifdef Q_OS_WIN32
+ static constexpr bool Enabled = true;
+#else
+ static constexpr bool Enabled = false;
+#endif
+ static bool supports(QNativeIpcKey::Type type)
+ { return type == QNativeIpcKey::Type::Windows; }
+ static bool runtimeSupportCheck() { return Enabled; }
+
+ // we can declare the members without the #if
+ Qt::HANDLE handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode);
+ void cleanHandle(QSystemSemaphorePrivate *self);
+ bool modifySemaphore(QSystemSemaphorePrivate *self, int count);
+
+ Qt::HANDLE semaphore = nullptr;
+};
+
+class QSystemSemaphorePrivate
+{
+public:
+ QSystemSemaphorePrivate(QNativeIpcKey::Type type) : nativeKey(type)
+ { constructBackend(); }
+ ~QSystemSemaphorePrivate() { destructBackend(); }
+
+ void setWindowsErrorString(QLatin1StringView function); // Windows only
+ void setUnixErrorString(QLatin1StringView function);
+ inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
+ { error = e; errorString = message; }
+ inline void clearError()
+ { setError(QSystemSemaphore::NoError, QString()); }
+
+ QNativeIpcKey nativeKey;
+ QString errorString;
+ int initialValue;
+ QSystemSemaphore::SystemSemaphoreError error = QSystemSemaphore::NoError;
+
+ union Backend {
+ Backend() {}
+ ~Backend() {}
+ QSystemSemaphorePosix posix;
+ QSystemSemaphoreSystemV sysv;
+ QSystemSemaphoreWin32 win32;
+ };
+ QtIpcCommon::IpcStorageVariant<&Backend::posix, &Backend::sysv, &Backend::win32> backend;
+
+ void constructBackend();
+ void destructBackend();
+
+ template <typename Lambda> auto visit(const Lambda &lambda)
+ {
+ return backend.visit(nativeKey.type(), lambda);
+ }
+
+ void handle(QSystemSemaphore::AccessMode mode)
+ {
+ visit([&](auto p) { p->handle(this, mode); });
+ }
+ void cleanHandle()
+ {
+ visit([&](auto p) { p->cleanHandle(this); });
+ }
+ bool modifySemaphore(int count)
+ {
+ return visit([&](auto p) { return p->modifySemaphore(this, count); });
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(systemsemaphore)
+
+#endif // QSYSTEMSEMAPHORE_P_H
+
diff --git a/src/corelib/ipc/qsystemsemaphore_posix.cpp b/src/corelib/ipc/qsystemsemaphore_posix.cpp
new file mode 100644
index 0000000000..7df9593513
--- /dev/null
+++ b/src/corelib/ipc/qsystemsemaphore_posix.cpp
@@ -0,0 +1,171 @@
+// Copyright (C) 2015 Konstantin Ritt <ritt.ks@gmail.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qcoreapplication.h>
+
+#if QT_CONFIG(posix_sem)
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef Q_OS_UNIX
+# include "private/qcore_unix_p.h"
+#else
+# define QT_EINTR_LOOP_VAL(var, val, cmd) \
+ (void)var; var = cmd
+# define QT_EINTR_LOOP(var, cmd) QT_EINTR_LOOP_VAL(var, -1, cmd)
+#endif
+
+// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
+// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
+#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
+#define EIDRM EINVAL
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+bool QSystemSemaphorePosix::runtimeSupportCheck()
+{
+ static const bool result = []() {
+ sem_open("/", 0, 0, 0); // this WILL fail
+ return errno != ENOSYS;
+ }();
+ return result;
+}
+
+bool QSystemSemaphorePosix::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode)
+{
+ if (semaphore != SEM_FAILED)
+ return true; // we already have a semaphore
+
+ const QByteArray semName = QFile::encodeName(self->nativeKey.nativeKey());
+ if (semName.isEmpty()) {
+ self->setError(QSystemSemaphore::KeyError,
+ QSystemSemaphore::tr("%1: key is empty")
+ .arg("QSystemSemaphore::handle"_L1));
+ return false;
+ }
+
+ // Always try with O_EXCL so we know whether we created the semaphore.
+ int oflag = O_CREAT | O_EXCL;
+ for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) {
+ do {
+ semaphore = ::sem_open(semName.constData(), oflag, 0600, self->initialValue);
+ } while (semaphore == SEM_FAILED && errno == EINTR);
+ if (semaphore == SEM_FAILED && errno == EEXIST) {
+ if (mode == QSystemSemaphore::Create) {
+ if (::sem_unlink(semName.constData()) == -1 && errno != ENOENT) {
+ self->setUnixErrorString("QSystemSemaphore::handle (sem_unlink)"_L1);
+ return false;
+ }
+ // Race condition: the semaphore might be recreated before
+ // we call sem_open again, so we'll retry several times.
+ maxTries = 3;
+ } else {
+ // Race condition: if it no longer exists at the next sem_open
+ // call, we won't realize we created it, so we'll leak it later.
+ oflag &= ~O_EXCL;
+ maxTries = 2;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (semaphore == SEM_FAILED) {
+ self->setUnixErrorString("QSystemSemaphore::handle"_L1);
+ return false;
+ }
+
+ createdSemaphore = (oflag & O_EXCL) != 0;
+
+ return true;
+}
+
+void QSystemSemaphorePosix::cleanHandle(QSystemSemaphorePrivate *self)
+{
+ if (semaphore != SEM_FAILED) {
+ if (::sem_close(semaphore) == -1) {
+ self->setUnixErrorString("QSystemSemaphore::cleanHandle (sem_close)"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphore::cleanHandle sem_close failed.");
+#endif
+ }
+ semaphore = SEM_FAILED;
+ }
+
+ if (createdSemaphore) {
+ const QByteArray semName = QFile::encodeName(self->nativeKey.nativeKey());
+ if (::sem_unlink(semName) == -1 && errno != ENOENT) {
+ self->setUnixErrorString("QSystemSemaphore::cleanHandle (sem_unlink)"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphorePosix::cleanHandle sem_unlink failed.");
+#endif
+ }
+ createdSemaphore = false;
+ }
+}
+
+bool QSystemSemaphorePosix::modifySemaphore(QSystemSemaphorePrivate *self, int count)
+{
+ if (!handle(self, QSystemSemaphore::Open))
+ return false;
+
+ if (count > 0) {
+ int cnt = count;
+ do {
+ if (::sem_post(semaphore) == -1) {
+#if defined(Q_OS_VXWORKS)
+ if (errno == EINVAL) {
+ semaphore = SEM_FAILED;
+ return modifySemaphore(self, cnt);
+ }
+#endif
+ self->setUnixErrorString("QSystemSemaphore::modifySemaphore (sem_post)"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphorePosix::modify sem_post failed %d %d", count, errno);
+#endif
+ // rollback changes to preserve the SysV semaphore behavior
+ for ( ; cnt < count; ++cnt) {
+ int res;
+ QT_EINTR_LOOP(res, ::sem_wait(semaphore));
+ }
+ return false;
+ }
+ --cnt;
+ } while (cnt > 0);
+ } else {
+ int res;
+ QT_EINTR_LOOP(res, ::sem_wait(semaphore));
+ if (res == -1) {
+ // If the semaphore was removed be nice and create it and then modifySemaphore again
+ if (errno == EINVAL || errno == EIDRM) {
+ semaphore = SEM_FAILED;
+ return modifySemaphore(self, count);
+ }
+ self->setUnixErrorString("QSystemSemaphore::modifySemaphore (sem_wait)"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphorePosix::modify sem_wait failed %d %d", count, errno);
+#endif
+ return false;
+ }
+ }
+
+ self->clearError();
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(posix_sem)
diff --git a/src/corelib/ipc/qsystemsemaphore_systemv.cpp b/src/corelib/ipc/qsystemsemaphore_systemv.cpp
new file mode 100644
index 0000000000..e5d231d1d4
--- /dev/null
+++ b/src/corelib/ipc/qsystemsemaphore_systemv.cpp
@@ -0,0 +1,201 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qcoreapplication.h>
+
+#if QT_CONFIG(sysv_sem)
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#if defined(Q_OS_DARWIN)
+#include "private/qcore_mac_p.h"
+#endif
+
+#include "private/qcore_unix_p.h"
+
+// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
+// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
+#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
+#define EIDRM EINVAL
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+bool QSystemSemaphoreSystemV::runtimeSupportCheck()
+{
+#if defined(Q_OS_DARWIN)
+ if (qt_apple_isSandboxed())
+ return false;
+#endif
+ static const bool result = []() {
+ (void)semget(IPC_PRIVATE, -1, 0); // this will fail
+ return errno != ENOSYS;
+ }();
+ return result;
+}
+
+/*!
+ \internal
+
+ Setup unix_key
+ */
+key_t QSystemSemaphoreSystemV::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode mode)
+{
+ if (unix_key != -1)
+ return unix_key; // we already have a semaphore
+
+#if defined(Q_OS_DARWIN)
+ if (qt_apple_isSandboxed()) {
+ // attempting to use System V semaphores will get us a SIGSYS
+ self->setError(QSystemSemaphore::PermissionDenied,
+ QSystemSemaphore::tr("%1: System V semaphores are not available for "
+ "sandboxed applications. Please build Qt with "
+ "-feature-ipc_posix")
+ .arg("QSystemSemaphore::handle:"_L1));
+ return -1;
+ }
+#endif
+
+ nativeKeyFile = QFile::encodeName(self->nativeKey.nativeKey());
+ if (nativeKeyFile.isEmpty()) {
+ self->setError(QSystemSemaphore::KeyError,
+ QSystemSemaphore::tr("%1: key is empty")
+ .arg("QSystemSemaphore::handle:"_L1));
+ return -1;
+ }
+
+ // ftok requires that an actual file exists somewhere
+ int built = QtIpcCommon::createUnixKeyFile(nativeKeyFile);
+ if (-1 == built) {
+ self->setError(QSystemSemaphore::KeyError,
+ QSystemSemaphore::tr("%1: unable to make key")
+ .arg("QSystemSemaphore::handle:"_L1));
+
+ return -1;
+ }
+ createdFile = (1 == built);
+
+ // Get the unix key for the created file
+ unix_key = ftok(nativeKeyFile, int(self->nativeKey.type()));
+ if (-1 == unix_key) {
+ self->setError(QSystemSemaphore::KeyError,
+ QSystemSemaphore::tr("%1: ftok failed")
+ .arg("QSystemSemaphore::handle:"_L1));
+ return -1;
+ }
+
+ // Get semaphore
+ semaphore = semget(unix_key, 1, 0600 | IPC_CREAT | IPC_EXCL);
+ if (-1 == semaphore) {
+ if (errno == EEXIST)
+ semaphore = semget(unix_key, 1, 0600 | IPC_CREAT);
+ if (-1 == semaphore) {
+ self->setUnixErrorString("QSystemSemaphore::handle"_L1);
+ cleanHandle(self);
+ return -1;
+ }
+ } else {
+ createdSemaphore = true;
+ // Force cleanup of file, it is possible that it can be left over from a crash
+ createdFile = true;
+ }
+
+ if (mode == QSystemSemaphore::Create) {
+ createdSemaphore = true;
+ createdFile = true;
+ }
+
+ // Created semaphore so initialize its value.
+ if (createdSemaphore && self->initialValue >= 0) {
+ qt_semun init_op;
+ init_op.val = self->initialValue;
+ if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
+ self->setUnixErrorString("QSystemSemaphore::handle"_L1);
+ cleanHandle(self);
+ return -1;
+ }
+ }
+
+ return unix_key;
+}
+
+/*!
+ \internal
+
+ Cleanup the unix_key
+ */
+void QSystemSemaphoreSystemV::cleanHandle(QSystemSemaphorePrivate *self)
+{
+ unix_key = -1;
+
+ // remove the file if we made it
+ if (createdFile) {
+ unlink(nativeKeyFile.constData());
+ createdFile = false;
+ }
+
+ if (createdSemaphore) {
+ if (-1 != semaphore) {
+ if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
+ self->setUnixErrorString("QSystemSemaphore::cleanHandle"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphoreSystemV::cleanHandle semctl failed.");
+#endif
+ }
+ semaphore = -1;
+ }
+ createdSemaphore = false;
+ }
+}
+
+/*!
+ \internal
+ */
+bool QSystemSemaphoreSystemV::modifySemaphore(QSystemSemaphorePrivate *self, int count)
+{
+ if (handle(self, QSystemSemaphore::Open) == -1)
+ return false;
+
+ struct sembuf operation;
+ operation.sem_num = 0;
+ operation.sem_op = count;
+ operation.sem_flg = SEM_UNDO;
+
+ int res;
+ QT_EINTR_LOOP(res, semop(semaphore, &operation, 1));
+ if (-1 == res) {
+ // If the semaphore was removed be nice and create it and then modifySemaphore again
+ if (errno == EINVAL || errno == EIDRM) {
+ semaphore = -1;
+ cleanHandle(self);
+ handle(self, QSystemSemaphore::Open);
+ return modifySemaphore(self, count);
+ }
+ self->setUnixErrorString("QSystemSemaphore::modifySemaphore"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphoreSystemV::modify failed %d %d %d %d %d",
+ count, int(semctl(semaphore, 0, GETVAL)), int(errno), int(EIDRM), int(EINVAL);
+#endif
+ return false;
+ }
+
+ self->clearError();
+ return true;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(sysv_sem)
diff --git a/src/corelib/ipc/qsystemsemaphore_win.cpp b/src/corelib/ipc/qsystemsemaphore_win.cpp
new file mode 100644
index 0000000000..f42fecf71f
--- /dev/null
+++ b/src/corelib/ipc/qsystemsemaphore_win.cpp
@@ -0,0 +1,98 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include "qcoreapplication.h"
+#include <qdebug.h>
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+#if QT_CONFIG(systemsemaphore)
+
+void QSystemSemaphorePrivate::setWindowsErrorString(QLatin1StringView function)
+{
+ BOOL windowsError = GetLastError();
+ if (windowsError == 0)
+ return;
+
+ switch (windowsError) {
+ case ERROR_NO_SYSTEM_RESOURCES:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ error = QSystemSemaphore::OutOfResources;
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function);
+ break;
+ case ERROR_ACCESS_DENIED:
+ error = QSystemSemaphore::PermissionDenied;
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: permission denied").arg(function);
+ break;
+ default:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error: %2")
+ .arg(function, qt_error_string(windowsError));
+ error = QSystemSemaphore::UnknownError;
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+ }
+}
+
+HANDLE QSystemSemaphoreWin32::handle(QSystemSemaphorePrivate *self, QSystemSemaphore::AccessMode)
+{
+ // don't allow making handles on empty keys
+ if (self->nativeKey.isEmpty())
+ return 0;
+
+ // Create it if it doesn't already exists.
+ if (semaphore == 0) {
+ semaphore = CreateSemaphore(0, self->initialValue, MAXLONG,
+ reinterpret_cast<const wchar_t*>(self->nativeKey.nativeKey().utf16()));
+ if (semaphore == NULL)
+ self->setWindowsErrorString("QSystemSemaphore::handle"_L1);
+ }
+
+ return semaphore;
+}
+
+void QSystemSemaphoreWin32::cleanHandle(QSystemSemaphorePrivate *)
+{
+ if (semaphore && !CloseHandle(semaphore)) {
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphoreWin32::CloseHandle: sem failed");
+#endif
+ }
+ semaphore = 0;
+}
+
+bool QSystemSemaphoreWin32::modifySemaphore(QSystemSemaphorePrivate *self, int count)
+{
+ if (handle(self, QSystemSemaphore::Open) == nullptr)
+ return false;
+
+ if (count > 0) {
+ if (0 == ReleaseSemaphore(semaphore, count, 0)) {
+ self->setWindowsErrorString("QSystemSemaphore::modifySemaphore"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
+#endif
+ return false;
+ }
+ } else {
+ if (WAIT_OBJECT_0 != WaitForSingleObjectEx(semaphore, INFINITE, FALSE)) {
+ self->setWindowsErrorString("QSystemSemaphore::modifySemaphore"_L1);
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphore::modifySemaphore WaitForSingleObject failed");
+#endif
+ return false;
+ }
+ }
+
+ self->clearError();
+ return true;
+}
+
+#endif // QT_CONFIG(systemsemaphore)
+
+QT_END_NAMESPACE
diff --git a/src/corelib/ipc/qtipccommon.cpp b/src/corelib/ipc/qtipccommon.cpp
new file mode 100644
index 0000000000..b2ae9172fa
--- /dev/null
+++ b/src/corelib/ipc/qtipccommon.cpp
@@ -0,0 +1,610 @@
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qtipccommon.h"
+#include "qtipccommon_p.h"
+
+#include <qcryptographichash.h>
+#include <qstandardpaths.h>
+#include <qstringconverter.h>
+#include <qurl.h>
+#include <qurlquery.h>
+
+#if defined(Q_OS_DARWIN)
+# include "private/qcore_mac_p.h"
+# if !defined(SHM_NAME_MAX)
+ // Based on PSEMNAMLEN in XNU's posix_sem.c, which would
+ // indicate the max length is 31, _excluding_ the zero
+ // terminator. But in practice (possibly due to an off-
+ // by-one bug in the kernel) the usable bytes are only 30.
+# define SHM_NAME_MAX 30
+# endif
+#elif defined(Q_OS_WINDOWS)
+# include "qt_windows.h"
+#endif
+
+#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+static QStringView staticTypeToString(QNativeIpcKey::Type type)
+{
+ switch (type) {
+ case QNativeIpcKey::Type::SystemV:
+ return u"systemv";
+ case QNativeIpcKey::Type::PosixRealtime:
+ return u"posix";
+ case QNativeIpcKey::Type::Windows:
+ return u"windows";
+ }
+ return {};
+}
+
+static QString typeToString(QNativeIpcKey::Type type)
+{
+ QStringView typeString = staticTypeToString(type);
+ switch (type) {
+ case QNativeIpcKey::Type::SystemV:
+ case QNativeIpcKey::Type::PosixRealtime:
+ case QNativeIpcKey::Type::Windows:
+ return QString::fromRawData(typeString.constData(), typeString.size());
+ }
+
+ int value = int(type);
+ if (value >= 1 && value <= 0xff) {
+ // System V key with id different from 'Q'
+ typeString = staticTypeToString(QNativeIpcKey::Type::SystemV);
+ return typeString + QString::number(-value); // negative so it prepends a dash
+ }
+
+ return QString(); // invalid!
+}
+
+static QNativeIpcKey::Type stringToType(QStringView typeString)
+{
+ if (typeString == staticTypeToString(QNativeIpcKey::Type::PosixRealtime))
+ return QNativeIpcKey::Type::PosixRealtime;
+ if (typeString == staticTypeToString(QNativeIpcKey::Type::Windows))
+ return QNativeIpcKey::Type::Windows;
+
+ auto fromNumber = [](QStringView number, int low, int high) {
+ bool ok;
+ int n = -number.toInt(&ok, 10);
+ if (!ok || n < low || n > high)
+ return QNativeIpcKey::Type{};
+ return QNativeIpcKey::Type(n);
+ };
+
+ QStringView sysv = staticTypeToString(QNativeIpcKey::Type::SystemV);
+ if (typeString.startsWith(sysv)) {
+ if (typeString.size() == sysv.size())
+ return QNativeIpcKey::Type::SystemV;
+ return fromNumber(typeString.sliced(sysv.size()), 1, 0xff);
+ }
+
+ // invalid!
+ return QNativeIpcKey::Type{};
+}
+
+/*!
+ \internal
+
+ Legacy: this exists for compatibility with QSharedMemory and
+ QSystemSemaphore between 4.4 and 6.6.
+
+ Returns a QNativeIpcKey that contains a platform-safe key using rules
+ similar to QtIpcCommon::platformSafeKey() below, but using an algorithm
+ that is compatible with Qt 4.4 to 6.6. Additionally, the returned
+ QNativeIpcKey will record the input \a key so it can be included in the
+ string form if necessary to pass to other processes.
+*/
+QNativeIpcKey QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
+ QNativeIpcKey::Type type)
+{
+ QNativeIpcKey k(type);
+ if (key.isEmpty())
+ return k;
+
+ QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
+
+ if (type == QNativeIpcKey::Type::PosixRealtime) {
+#if defined(Q_OS_DARWIN)
+ if (qt_apple_isSandboxed()) {
+ // Sandboxed applications on Apple platforms require the shared memory name
+ // to be in the form <application group identifier>/<custom identifier>.
+ // Since we don't know which application group identifier the user wants
+ // to apply, we instead document that requirement, and use the key directly.
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, key, key);
+ } else {
+ // The shared memory name limit on Apple platforms is very low (30 characters),
+ // so we can't use the logic below of combining the prefix, key, and a hash,
+ // to ensure a unique and valid name. Instead we use the first part of the
+ // hash, which should still long enough to avoid collisions in practice.
+ QString native = u'/' + QLatin1StringView(hex).left(SHM_NAME_MAX - 1);
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, native, key);
+ }
+ return k;
+#endif
+ }
+
+ QString result;
+ result.reserve(1 + 18 + key.size() + 40);
+ switch (ipcType) {
+ case IpcType::SharedMemory:
+ result += "qipc_sharedmemory_"_L1;
+ break;
+ case IpcType::SystemSemaphore:
+ result += "qipc_systemsem_"_L1;
+ break;
+ }
+
+ for (QChar ch : key) {
+ if ((ch >= u'a' && ch <= u'z') ||
+ (ch >= u'A' && ch <= u'Z'))
+ result += ch;
+ }
+ result.append(QLatin1StringView(hex));
+
+ switch (type) {
+ case QNativeIpcKey::Type::Windows:
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows))
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
+ return k;
+ case QNativeIpcKey::Type::PosixRealtime:
+ result.prepend(u'/');
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime))
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
+ return k;
+ case QNativeIpcKey::Type::SystemV:
+ break;
+ }
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV)) {
+ result = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u'/' + result;
+ QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
+ }
+ return k;
+}
+
+/*!
+ \internal
+ Returns a QNativeIpcKey of type \a type, suitable for QSystemSemaphore or
+ QSharedMemory depending on \a ipcType. The returned native key is generated
+ from the Unicode input \a key and is safe for use on for the key type in
+ question in the current OS.
+*/
+QNativeIpcKey QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
+ QNativeIpcKey::Type type)
+{
+ QNativeIpcKey k(type);
+ if (key.isEmpty())
+ return k;
+
+ switch (type) {
+ case QNativeIpcKey::Type::PosixRealtime:
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime)) {
+#ifdef SHM_NAME_MAX
+ // The shared memory name limit on Apple platforms is very low (30
+ // characters), so we have to cut it down to avoid ENAMETOOLONG. We
+ // hope that there won't be too many collisions...
+ k.setNativeKey(u'/' + QStringView(key).left(SHM_NAME_MAX - 1));
+#else
+ k.setNativeKey(u'/' + key);
+#endif
+ }
+ return k;
+
+ case QNativeIpcKey::Type::Windows:
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows)) {
+ QStringView prefix;
+ QStringView payload = key;
+ // see https://learn.microsoft.com/en-us/windows/win32/termserv/kernel-object-namespaces
+ for (QStringView candidate : { u"Local\\", u"Global\\" }) {
+ if (!key.startsWith(candidate))
+ continue;
+ prefix = candidate;
+ payload = payload.sliced(prefix.size());
+ break;
+ }
+
+ QStringView mid;
+ switch (ipcType) {
+ case IpcType::SharedMemory: mid = u"shm_"; break;
+ case IpcType::SystemSemaphore: mid = u"sem_"; break;
+ }
+
+ QString result = prefix + mid + payload;
+#ifdef Q_OS_WINDOWS
+ result.truncate(MAX_PATH);
+#endif
+ k.setNativeKey(result);
+ }
+ return k;
+
+ case QNativeIpcKey::Type::SystemV:
+ break;
+ }
+
+ // System V
+ if (isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV)) {
+ if (key.startsWith(u'/')) {
+ k.setNativeKey(key);
+ } else {
+ QString baseDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+ k.setNativeKey(baseDir + u'/' + key);
+ }
+ }
+ return k;
+}
+
+/*!
+ \class QNativeIpcKey
+ \inmodule QtCore
+ \since 6.6
+ \brief The QNativeIpcKey class holds a native key used by QSystemSemaphore and QSharedMemory.
+
+ \compares equality
+
+ The \l QSharedMemory and \l QSystemSemaphore classes identify their
+ resource using a system-wide identifier known as a "key". The low-level key
+ value as well as the key type are encapsulated in Qt using the \l
+ QNativeIpcKey class.
+
+ Those two classes also provide the means to create native keys from a
+ cross-platform identifier, using QSharedMemory::platformSafeKey() and
+ QSystemSemaphore::platformSafeKey(). Applications should never share the
+ input to those functions, as different versions of Qt may perform different
+ transformations, resulting in different native keys. Instead, the
+ application that created the IPC object should communicate the resulting
+ native key using the methods described below.
+
+ For details on the key types, platform-specific limitations, and
+ interoperability with older or non-Qt applications, see the \l{Native IPC
+ Keys} documentation. That includes important information for sandboxed
+ applications on Apple platforms, including all apps obtained via the Apple
+ App Store.
+
+ \section1 Communicating keys to other processes
+ \section2 Communicating keys to other Qt processes
+
+ If the other process supports QNativeIpcKey, the best way of communicating
+ is via the string representation obtained from toString() and parsing it
+ using fromString(). This representation can be stored on a file whose name
+ is well-known or passed on the command-line to a child process using
+ QProcess::setArguments().
+
+ If the other process does not support QNativeIpcKey, then the two processes
+ can exchange the nativeKey() but the older code is likely unable to adjust
+ its key type. The legacyDefaultTypeForOs() function returns the type that
+ legacy code used, which may not match the \l{DefaultTypeForOs} constant.
+ This is still true even if the old application is not using the same build
+ as the new one (for example, it is a Qt 5 application), provided the
+ options passed to the Qt configure script are the same.
+
+ \section2 Communicating keys to non-Qt processes
+
+ When communicating with non-Qt processes, the application must arrange to
+ obtain the key type the other process is using. This is important
+ particularly on Unix systems, where both \l PosixRealtime and \l SystemV
+ are common.
+
+ \section1 String representation of native keys
+
+ The format of the string representation of a QNativeIpcKey is meant to be
+ stable and therefore backwards and forwards compatible, provided the key
+ type is supported by the Qt version in question. That is to say, an older
+ Qt will fail to parse the string representation of a key type introduced
+ after it was released. However, successfully parsing a string
+ representation does not imply the Qt classes can successfully create an
+ object of that type; applications should verify support using
+ QSharedMemory::isKeyTypeSupported() and QSystemSemaphore::isKeyTypeSupported().
+
+ The format of the string representation is formed by two components,
+ separated by a colon (':'). The first component is the key type, described
+ in the table below. The second component is a type-specific payload, using
+ \l{QByteArray::fromPercentEncoding}{percent-encoding}. For all currently
+ supported key types, the decoded form is identical to the contents of the
+ nativeKey() field.
+
+ \table
+ \row \li Key type \li String representation
+ \row \li \l PosixRealtime \li \c "posix"
+ \row \li \l SystemV \li \c "systemv"
+ \row \li \l Windows \li \c "windows"
+ \row \li Non-standard SystemV \li \c "systemv-" followed by a decimal number
+ \endtable
+
+ This format resembles a URI and allows parsing using URI/URL-parsing
+ functions, such as \l QUrl. When parsed by such API, the key type will show
+ up as the \l{QUrl::scheme()}{scheme}, and the payload will be the
+ \l{QUrl::path()}{path}. Use of query or fragments is reserved.
+
+ \sa QSharedMemory, QSystemSemaphore
+*/
+
+/*!
+ \enum QNativeIpcKey::Type
+
+ This enum describes the backend type for the IPC object. For details on the
+ key types, see the \l{Native IPC Keys} documentation.
+
+ \value SystemV X/Open System Initiative (XSI) or System V (SVr4) API
+ \value PosixRealtime IEEE 1003.1b (POSIX.1b) API
+ \value Windows Win32 API
+
+ \sa setType(), type()
+*/
+
+/*!
+ \variable QNativeIpcKey::DefaultTypeForOs
+
+ This constant expression variable holds the default native IPC type for the
+ current OS. It will be Type::Windows for Windows systems and
+ Type::PosixRealtime elsewhere. Note that this constant is different from
+ what \l QSharedMemory and \l QSystemSemaphore defaulted to on the majority
+ of Unix systems prior to Qt 6.6; see legacyDefaultTypeForOs() for more
+ information.
+*/
+
+/*!
+ \fn QNativeIpcKey::legacyDefaultTypeForOs() noexcept
+
+ Returns the \l{Type} that corresponds to the native IPC key that
+ \l{QSharedMemory} and \l{QSystemSemaphore} used to use prior to Qt 6.6.
+ Applications and libraries that must retain compatibility with code using
+ either class that was compiled with Qt prior to version 6.6 can use this
+ function to determine what IPC type the other applications may be using.
+
+ Note that this function relies on Qt having been built with identical
+ configure-time options.
+*/
+#if defined(Q_OS_DARWIN)
+QNativeIpcKey::Type QNativeIpcKey::defaultTypeForOs_internal() noexcept
+{
+ if (qt_apple_isSandboxed())
+ return Type::PosixRealtime;
+ return Type::SystemV;
+}
+#endif
+
+/*!
+ \fn QNativeIpcKey::QNativeIpcKey() noexcept
+
+ Constructs a QNativeIpcKey object of type \l DefaultTypeForOs with an empty key.
+*/
+
+/*!
+ \fn QNativeIpcKey::QNativeIpcKey(Type type) noexcept
+ \fn QNativeIpcKey::QNativeIpcKey(const QString &key, Type type)
+
+ Constructs a QNativeIpcKey object holding native key \a key (or empty on
+ the overload without the parameter) for type \a type.
+*/
+
+/*!
+ \fn QNativeIpcKey::QNativeIpcKey(const QNativeIpcKey &other)
+ \fn QNativeIpcKey::QNativeIpcKey(QNativeIpcKey &&other) noexcept
+ \fn QNativeIpcKey &QNativeIpcKey::operator=(const QNativeIpcKey &other)
+ \fn QNativeIpcKey &QNativeIpcKey::operator=(QNativeIpcKey &&other) noexcept
+
+ Copies or moves the content of \a other.
+*/
+void QNativeIpcKey::copy_internal(const QNativeIpcKey &other)
+{
+ d = new QNativeIpcKeyPrivate(*other.d);
+}
+
+void QNativeIpcKey::move_internal(QNativeIpcKey &&) noexcept
+{
+ // inline code already moved properly, nothing for us to do here
+}
+
+QNativeIpcKey &QNativeIpcKey::assign_internal(const QNativeIpcKey &other)
+{
+ Q_ASSERT(d || other.d); // only 3 cases to handle
+ if (d && !other.d)
+ *d = {};
+ else if (d)
+ *d = *other.d;
+ else
+ d = new QNativeIpcKeyPrivate(*other.d);
+ return *this;
+}
+
+/*!
+ \fn QNativeIpcKey::~QNativeIpcKey()
+
+ Disposes of this QNativeIpcKey object.
+*/
+void QNativeIpcKey::destroy_internal() noexcept
+{
+ delete d;
+}
+
+/*!
+ \fn QNativeIpcKey::swap(QNativeIpcKey &other) noexcept
+
+ Swaps the native IPC key and type \a other with this object.
+ This operation is very fast and never fails.
+*/
+
+/*!
+ \fn swap(QNativeIpcKey &value1, QNativeIpcKey &value2) noexcept
+ \relates QNativeIpcKey
+
+ Swaps the native IPC key and type \a value1 with \a value2.
+ This operation is very fast and never fails.
+*/
+
+/*!
+ \fn QNativeIpcKey::isEmpty() const
+
+ Returns true if the nativeKey() is empty.
+
+ \sa nativeKey()
+*/
+
+/*!
+ \fn QNativeIpcKey::isValid() const
+
+ Returns true if this object contains a valid native IPC key type. Invalid
+ types are usually the result of a failure to parse a string representation
+ using fromString().
+
+ This function performs no check on the whether the key string is actually
+ supported or valid for the current operating system.
+
+ \sa type(), fromString()
+*/
+
+/*!
+ \fn QNativeIpcKey::type() const noexcept
+
+ Returns the key type associated with this object.
+
+ \sa nativeKey(), setType()
+*/
+
+/*!
+ \fn QNativeIpcKey::setType(Type type)
+
+ Sets the IPC type of this object to \a type.
+
+ \sa type(), setNativeKey()
+*/
+void QNativeIpcKey::setType_internal(Type type)
+{
+ Q_UNUSED(type);
+}
+
+/*!
+ \fn QNativeIpcKey::nativeKey() const noexcept
+
+ Returns the native key string associated with this object.
+
+ \sa setNativeKey(), type()
+*/
+
+/*!
+ \fn QNativeIpcKey::setNativeKey(const QString &newKey)
+
+ Sets the native key for this object to \a newKey.
+
+ \sa nativeKey(), setType()
+*/
+void QNativeIpcKey::setNativeKey_internal(const QString &)
+{
+ d->legacyKey_.clear();
+}
+
+/*!
+ \fn size_t QNativeIpcKey::qHash(const QNativeIpcKey &ipcKey) noexcept
+
+ Returns the hash value for \a ipcKey, using a default seed of \c 0.
+*/
+
+/*!
+ \fn size_t QNativeIpcKey::qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept
+
+ Returns the hash value for \a ipcKey, using \a seed to seed the calculation.
+*/
+size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept
+{
+ // by *choice*, we're not including d->legacyKey_ in the hash -- it's
+ // already partially encoded in the key
+ return qHashMulti(seed, ipcKey.key, ipcKey.type());
+}
+
+/*!
+ \fn bool QNativeIpcKey::operator==(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
+ \fn bool QNativeIpcKey::operator!=(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
+
+ Returns true if the \a lhs and \a rhs objects hold the same (or different) contents.
+*/
+int QNativeIpcKey::compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
+{
+ return (QNativeIpcKeyPrivate::legacyKey(lhs) == QNativeIpcKeyPrivate::legacyKey(rhs)) ? 0 : 1;
+}
+
+/*!
+ Returns the string representation of this object. String representations
+ are useful to inform other processes of the key this process created and
+ that they should attach to.
+
+ This function returns a null string if the current object is
+ \l{isValid()}{invalid}.
+
+ \sa fromString()
+*/
+QString QNativeIpcKey::toString() const
+{
+ QString prefix = typeToString(type());
+ if (prefix.isEmpty()) {
+ Q_ASSERT(prefix.isNull());
+ return prefix;
+ }
+
+ QString copy = nativeKey();
+ copy.replace(u'%', "%25"_L1);
+ if (copy.startsWith("//"_L1))
+ copy.replace(0, 2, u"/%2F"_s); // ensure it's parsed as a URL path
+
+ QUrl u;
+ u.setScheme(prefix);
+ u.setPath(copy, QUrl::TolerantMode);
+ if (isSlowPath()) {
+ QUrlQuery q;
+ if (!d->legacyKey_.isEmpty())
+ q.addQueryItem(u"legacyKey"_s, QString(d->legacyKey_).replace(u'%', "%25"_L1));
+ u.setQuery(q);
+ }
+ return u.toString(QUrl::DecodeReserved);
+}
+
+/*!
+ Parses the string form \a text and returns the corresponding QNativeIpcKey.
+ String representations are useful to inform other processes of the key this
+ process created and they should attach to.
+
+ If the string could not be parsed, this function returns an
+ \l{isValid()}{invalid} object.
+
+ \sa toString(), isValid()
+*/
+QNativeIpcKey QNativeIpcKey::fromString(const QString &text)
+{
+ QUrl u(text, QUrl::TolerantMode);
+ Type invalidType = {};
+ Type type = stringToType(u.scheme());
+ if (type == invalidType || !u.isValid() || !u.userInfo().isEmpty() || !u.host().isEmpty()
+ || u.port() != -1)
+ return QNativeIpcKey(invalidType);
+
+ QNativeIpcKey result(QString(), type);
+ if (result.type() != type) // range check, just in case
+ return QNativeIpcKey(invalidType);
+
+ // decode the payload
+ result.setNativeKey(u.path());
+
+ if (u.hasQuery()) {
+ const QList items = QUrlQuery(u).queryItems();
+ for (const auto &item : items) {
+ if (item.first == u"legacyKey"_s) {
+ QString legacyKey = QUrl::fromPercentEncoding(item.second.toUtf8());
+ QNativeIpcKeyPrivate::setLegacyKey(result, std::move(legacyKey));
+ } else {
+ // unknown query item
+ return QNativeIpcKey(invalidType);
+ }
+ }
+ }
+ return result;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtipccommon.cpp"
+
+#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
diff --git a/src/corelib/ipc/qtipccommon.h b/src/corelib/ipc/qtipccommon.h
new file mode 100644
index 0000000000..74f30cb6a4
--- /dev/null
+++ b/src/corelib/ipc/qtipccommon.h
@@ -0,0 +1,206 @@
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QNATIVEIPCKEY_H
+#define QNATIVEIPCKEY_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qtcore-config.h>
+
+#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
+# include <QtCore/qstring.h>
+# include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNativeIpcKeyPrivate;
+class QNativeIpcKey
+{
+ Q_GADGET_EXPORT(Q_CORE_EXPORT)
+public:
+ enum class Type : quint16 {
+ // 0 is reserved for the invalid type
+ // keep 1 through 0xff free, except for SystemV
+ SystemV = 0x51, // 'Q'
+
+ PosixRealtime = 0x100,
+ Windows,
+ };
+ Q_ENUM(Type)
+
+ static constexpr Type DefaultTypeForOs =
+#ifdef Q_OS_WIN
+ Type::Windows
+#else
+ Type::PosixRealtime
+#endif
+ ;
+ static Type legacyDefaultTypeForOs() noexcept;
+
+ constexpr QNativeIpcKey() noexcept = default;
+
+ explicit constexpr QNativeIpcKey(Type type) noexcept
+ : typeAndFlags{type}
+ {
+ }
+
+ Q_IMPLICIT QNativeIpcKey(const QString &k, Type type = DefaultTypeForOs)
+ : key(k), typeAndFlags{type}
+ {
+ }
+
+ QNativeIpcKey(const QNativeIpcKey &other)
+ : d(other.d), key(other.key), typeAndFlags(other.typeAndFlags)
+ {
+ if (isSlowPath())
+ copy_internal(other);
+ }
+
+ QNativeIpcKey(QNativeIpcKey &&other) noexcept
+ : d(std::exchange(other.d, nullptr)), key(std::move(other.key)),
+ typeAndFlags(std::move(other.typeAndFlags))
+ {
+ if (isSlowPath())
+ move_internal(std::move(other));
+ }
+
+ ~QNativeIpcKey()
+ {
+ if (isSlowPath())
+ destroy_internal();
+ }
+
+ QNativeIpcKey &operator=(const QNativeIpcKey &other)
+ {
+ typeAndFlags = other.typeAndFlags;
+ key = other.key;
+ if (isSlowPath() || other.isSlowPath())
+ return assign_internal(other);
+ Q_ASSERT(!d);
+ return *this;
+ }
+
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QNativeIpcKey)
+ void swap(QNativeIpcKey &other) noexcept
+ {
+ std::swap(d, other.d);
+ key.swap(other.key);
+ typeAndFlags.swap(other.typeAndFlags);
+ }
+
+ bool isEmpty() const noexcept
+ {
+ return key.isEmpty();
+ }
+
+ bool isValid() const noexcept
+ {
+ return type() != Type{};
+ }
+
+ constexpr Type type() const noexcept
+ {
+ return typeAndFlags.type;
+ }
+
+ constexpr void setType(Type type)
+ {
+ if (isSlowPath())
+ return setType_internal(type);
+ typeAndFlags.type = type;
+ }
+
+ QString nativeKey() const noexcept
+ {
+ return key;
+ }
+ void setNativeKey(const QString &newKey)
+ {
+ key = newKey;
+ if (isSlowPath())
+ setNativeKey_internal(newKey);
+ }
+
+ Q_CORE_EXPORT QString toString() const;
+ Q_CORE_EXPORT static QNativeIpcKey fromString(const QString &string);
+
+private:
+ struct TypeAndFlags {
+ Type type = DefaultTypeForOs;
+ quint16 reserved1 = {};
+ quint32 reserved2 = {};
+
+ void swap(TypeAndFlags &other) noexcept
+ {
+ std::swap(type, other.type);
+ std::swap(reserved1, other.reserved1);
+ std::swap(reserved2, other.reserved2);
+ }
+
+ friend constexpr bool operator==(const TypeAndFlags &lhs, const TypeAndFlags &rhs) noexcept
+ {
+ return lhs.type == rhs.type &&
+ lhs.reserved1 == rhs.reserved1 &&
+ lhs.reserved2 == rhs.reserved2;
+ }
+ };
+
+ QNativeIpcKeyPrivate *d = nullptr;
+ QString key;
+ TypeAndFlags typeAndFlags;
+
+ friend class QNativeIpcKeyPrivate;
+ constexpr bool isSlowPath() const noexcept
+ { return Q_UNLIKELY(d); }
+
+ friend Q_CORE_EXPORT size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept;
+ friend size_t qHash(const QNativeIpcKey &ipcKey) noexcept
+ { return qHash(ipcKey, 0); }
+
+ Q_CORE_EXPORT void copy_internal(const QNativeIpcKey &other);
+ Q_CORE_EXPORT void move_internal(QNativeIpcKey &&other) noexcept;
+ Q_CORE_EXPORT QNativeIpcKey &assign_internal(const QNativeIpcKey &other);
+ Q_CORE_EXPORT void destroy_internal() noexcept;
+ Q_CORE_EXPORT void setType_internal(Type);
+ Q_CORE_EXPORT void setNativeKey_internal(const QString &);
+ Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static int
+ compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept;
+
+#ifdef Q_OS_DARWIN
+ Q_DECL_CONST_FUNCTION Q_CORE_EXPORT static Type defaultTypeForOs_internal() noexcept;
+#endif
+ friend bool comparesEqual(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
+ {
+ if (!(lhs.typeAndFlags == rhs.typeAndFlags))
+ return false;
+ if (lhs.key != rhs.key)
+ return false;
+ if (lhs.d == rhs.d)
+ return true;
+ return compare_internal(lhs, rhs) == 0;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QNativeIpcKey)
+};
+
+// not a shared type, exactly, but this works too
+Q_DECLARE_SHARED(QNativeIpcKey)
+
+inline auto QNativeIpcKey::legacyDefaultTypeForOs() noexcept -> Type
+{
+#if defined(Q_OS_WIN)
+ return Type::Windows;
+#elif defined(QT_POSIX_IPC)
+ return Type::PosixRealtime;
+#elif defined(Q_OS_DARWIN)
+ return defaultTypeForOs_internal();
+#else
+ return Type::SystemV;
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
+
+
+#endif // QNATIVEIPCKEY_H
diff --git a/src/corelib/ipc/qtipccommon_p.h b/src/corelib/ipc/qtipccommon_p.h
new file mode 100644
index 0000000000..72762c5ba7
--- /dev/null
+++ b/src/corelib/ipc/qtipccommon_p.h
@@ -0,0 +1,173 @@
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTIPCCOMMON_P_H
+#define QTIPCCOMMON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtipccommon.h"
+#include <private/qglobal_p.h>
+#include <private/qtcore-config_p.h>
+
+#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
+
+#if defined(Q_OS_UNIX)
+# include <qfile.h>
+# include <private/qcore_unix_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QNativeIpcKeyPrivate
+{
+public:
+ QString legacyKey_;
+
+ static QString legacyKey(const QNativeIpcKey &key)
+ {
+ if (key.isSlowPath())
+ return key.d->legacyKey_;
+ return QString();
+ }
+ static void setLegacyKey(QNativeIpcKey &key, const QString &legacyKey)
+ {
+ QNativeIpcKeyPrivate::makeExtended(key)->legacyKey_ = legacyKey;
+ }
+ static void setNativeAndLegacyKeys(QNativeIpcKey &key, const QString &nativeKey,
+ const QString &legacyKey)
+ {
+ key.setNativeKey(nativeKey);
+ setLegacyKey(key, legacyKey);
+ }
+
+private:
+ static QNativeIpcKeyPrivate *makeExtended(QNativeIpcKey &key)
+ {
+ if (!key.isSlowPath())
+ key.d = new QNativeIpcKeyPrivate;
+ return key.d;
+ }
+};
+
+namespace QtIpcCommon {
+enum class IpcType {
+ SharedMemory,
+ SystemSemaphore
+};
+
+static constexpr bool isIpcSupported(IpcType ipcType, QNativeIpcKey::Type type)
+{
+ switch (type) {
+ case QNativeIpcKey::Type::SystemV:
+ break;
+
+ case QNativeIpcKey::Type::PosixRealtime:
+ if (ipcType == IpcType::SharedMemory)
+ return QT_CONFIG(posix_shm);
+ return QT_CONFIG(posix_sem);
+
+ case QNativeIpcKey::Type::Windows:
+#ifdef Q_OS_WIN
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ if (ipcType == IpcType::SharedMemory)
+ return QT_CONFIG(sysv_shm);
+ return QT_CONFIG(sysv_sem);
+}
+
+template <auto Member1, auto... Members> class IpcStorageVariant
+{
+ template <typename T, typename C> static C extractClass(T C::*);
+ template <typename T, typename C> static T extractObject(T C::*);
+
+ template <auto M>
+ static constexpr bool IsEnabled = decltype(extractObject(M))::Enabled;
+
+ static_assert(std::is_member_object_pointer_v<decltype(Member1)>);
+ using StorageType = decltype(extractClass(Member1));
+ StorageType d;
+
+public:
+ template <typename Lambda> static auto
+ visit_internal(StorageType &storage, QNativeIpcKey::Type keyType, const Lambda &lambda)
+ {
+ if constexpr ((IsEnabled<Member1> || ... || IsEnabled<Members>)) {
+ if constexpr (IsEnabled<Member1>) {
+ using MemberType1 = decltype(extractObject(Member1));
+ if (MemberType1::supports(keyType))
+ return lambda(&(storage.*Member1));
+ }
+ if constexpr ((... || IsEnabled<Members>))
+ return IpcStorageVariant<Members...>::visit_internal(storage, keyType, lambda);
+ Q_UNREACHABLE();
+ } else {
+ // no backends enabled, but we can't return void
+ return false;
+ }
+ }
+
+ template <typename Lambda> auto visit(QNativeIpcKey::Type keyType, const Lambda &lambda)
+ {
+ return visit_internal(d, keyType, lambda);
+ }
+
+ template <typename Lambda> static auto
+ staticVisit(QNativeIpcKey::Type keyType, const Lambda &lambda)
+ {
+ if constexpr ((IsEnabled<Member1> || ... || IsEnabled<Members>)) {
+ if constexpr (IsEnabled<Member1>) {
+ using MemberType1 = decltype(extractObject(Member1));
+ if (MemberType1::supports(keyType))
+ return lambda(static_cast<MemberType1 *>(nullptr));
+ }
+ if constexpr ((... || IsEnabled<Members>))
+ return IpcStorageVariant<Members...>::staticVisit(keyType, lambda);
+ Q_UNREACHABLE();
+ } else {
+ // no backends enabled, but we can't return void
+ return false;
+ }
+ }
+};
+
+QNativeIpcKey legacyPlatformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
+QNativeIpcKey platformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
+
+#ifdef Q_OS_UNIX
+// Convenience function to create the file if needed
+inline int createUnixKeyFile(const QByteArray &fileName)
+{
+ int fd = qt_safe_open(fileName.constData(), O_EXCL | O_CREAT | O_RDWR, 0640);
+ if (fd < 0) {
+ if (errno == EEXIST)
+ return 0;
+ return -1;
+ } else {
+ close(fd);
+ }
+ return 1;
+
+}
+#endif // Q_OS_UNIX
+} // namespace QtIpcCommon
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
+
+
+#endif // QTIPCCOMMON_P_H
diff --git a/src/corelib/itemmodels/itemmodels.pri b/src/corelib/itemmodels/itemmodels.pri
deleted file mode 100644
index ebeac6e211..0000000000
--- a/src/corelib/itemmodels/itemmodels.pri
+++ /dev/null
@@ -1,63 +0,0 @@
-# Qt itemmodels core module
-
-!qtConfig(itemmodel): return()
-
-HEADERS += \
- itemmodels/qabstractitemmodel.h \
- itemmodels/qabstractitemmodel_p.h \
- itemmodels/qitemselectionmodel.h \
- itemmodels/qitemselectionmodel_p.h
-
-SOURCES += \
- itemmodels/qabstractitemmodel.cpp \
- itemmodels/qitemselectionmodel.cpp
-
-qtConfig(proxymodel) {
- HEADERS += \
- itemmodels/qabstractproxymodel.h \
- itemmodels/qabstractproxymodel_p.h
-
- SOURCES += \
- itemmodels/qabstractproxymodel.cpp
-
- qtConfig(concatenatetablesproxymodel) {
- HEADERS += \
- itemmodels/qconcatenatetablesproxymodel.h
-
- SOURCES += \
- itemmodels/qconcatenatetablesproxymodel.cpp
- }
-
- qtConfig(identityproxymodel) {
- HEADERS += \
- itemmodels/qidentityproxymodel.h
-
- SOURCES += \
- itemmodels/qidentityproxymodel.cpp
- }
-
- qtConfig(sortfilterproxymodel) {
- HEADERS += \
- itemmodels/qsortfilterproxymodel.h
-
- SOURCES += \
- itemmodels/qsortfilterproxymodel.cpp
- }
-
- qtConfig(transposeproxymodel) {
- HEADERS += \
- itemmodels/qtransposeproxymodel.h \
- itemmodels/qtransposeproxymodel_p.h
-
- SOURCES += \
- itemmodels/qtransposeproxymodel.cpp
- }
-}
-
-qtConfig(stringlistmodel) {
- HEADERS += \
- itemmodels/qstringlistmodel.h
-
- SOURCES += \
- itemmodels/qstringlistmodel.cpp
-}
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 27885bcb9b..cd29f2fcc2 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractitemmodel.h"
#include <private/qabstractitemmodel_p.h>
@@ -49,16 +14,21 @@
# include <qregularexpression.h>
#endif
#include <qstack.h>
+#include <qmap.h>
#include <qbitarray.h>
#include <qdatetime.h>
#include <qloggingcategory.h>
+#include <functional>
+
#include <limits.h>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcCheckIndex, "qt.core.qabstractitemmodel.checkindex")
+QT_IMPL_METATYPE_EXTERN(QModelIndexList)
+
QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &index)
{
Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
@@ -91,6 +61,226 @@ void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
}
/*!
+ \class QModelRoleData
+ \inmodule QtCore
+ \since 6.0
+ \ingroup model-view
+ \brief The QModelRoleData class holds a role and the data associated to that role.
+
+ QModelRoleData objects store an item role (which is a value from the
+ Qt::ItemDataRole enumeration, or an arbitrary integer for a custom role)
+ as well as the data associated with that role.
+
+ A QModelRoleData object is typically created by views or delegates,
+ setting which role they want to fetch the data for. The object
+ is then passed to models (see QAbstractItemModel::multiData()),
+ which populate the data corresponding to the role stored. Finally,
+ the view visualizes the data retrieved from the model.
+
+ \sa {Model/View Programming}, QModelRoleDataSpan
+*/
+
+/*!
+ \fn QModelRoleData::QModelRoleData(int role) noexcept
+
+ Constructs a QModelRoleData object for the given \a role.
+
+ \sa Qt::ItemDataRole
+*/
+
+/*!
+ \fn int QModelRoleData::role() const noexcept
+
+ Returns the role held by this object.
+
+ \sa Qt::ItemDataRole
+*/
+
+/*!
+ \fn const QVariant &QModelRoleData::data() const noexcept
+
+ Returns the data held by this object.
+
+ \sa setData()
+*/
+
+/*!
+ \fn QVariant &QModelRoleData::data() noexcept
+
+ Returns the data held by this object as a modifiable reference.
+
+ \sa setData()
+*/
+
+/*!
+ \fn template <typename T> void QModelRoleData::setData(T &&value)
+
+ Sets the data held by this object to \a value.
+ \a value must be of a datatype which can be stored in a QVariant.
+
+ \sa data(), clearData(), Q_DECLARE_METATYPE
+*/
+
+/*!
+ \fn void QModelRoleData::clearData() noexcept
+
+ Clears the data held by this object. Note that the role is
+ unchanged; only the data is cleared.
+
+ \sa data()
+*/
+
+/*!
+ \class QModelRoleDataSpan
+ \inmodule QtCore
+ \since 6.0
+ \ingroup model-view
+ \brief The QModelRoleDataSpan class provides a span over QModelRoleData objects.
+
+ A QModelRoleDataSpan is used as an abstraction over an array of
+ QModelRoleData objects.
+
+ Like a view, QModelRoleDataSpan provides a small object (pointer
+ and size) that can be passed to functions that need to examine the
+ contents of the array. A QModelRoleDataSpan can be constructed from
+ any array-like sequence (plain arrays, QVector, std::vector,
+ QVarLengthArray, and so on). Moreover, it does not own the
+ sequence, which must therefore be kept alive longer than any
+ QModelRoleDataSpan objects referencing it.
+
+ Unlike a view, QModelRoleDataSpan is a span, so it allows for
+ modifications to the underlying elements.
+
+ QModelRoleDataSpan's main use case is making it possible
+ for a model to return the data corresponding to different roles
+ in one call.
+
+ In order to draw one element from a model, a view (through its
+ delegates) will generally request multiple roles for the same index
+ by calling \c{data()} as many times as needed:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 13
+
+ QModelRoleDataSpan allows a view to request the same data
+ using just one function call.
+
+ This is achieved by having the view prepare a suitable array of
+ QModelRoleData objects, each initialized with the role that should
+ be fetched. The array is then wrapped in a QModelRoleDataSpan
+ object, which is then passed to a model's \c{multiData()} function.
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 14
+
+ Views are encouraged to store the array of QModelRoleData objects
+ (and, possibly, the corresponding span) and re-use it in subsequent
+ calls to the model. This allows to reduce the memory allocations
+ related with creating and returning QVariant objects.
+
+ Finally, given a QModelRoleDataSpan object, the model's
+ responsibility is to fill in the data corresponding to each role in
+ the span. How this is done depends on the concrete model class.
+ Here's a sketch of a possible implementation that iterates over the
+ span and uses \c{setData()} on each element:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 15
+
+ \sa {Model/View Programming}, QAbstractItemModel::multiData()
+*/
+
+/*!
+ \fn QModelRoleDataSpan::QModelRoleDataSpan() noexcept
+
+ Constructs an empty QModelRoleDataSpan. Its data() will be set to
+ \nullptr, and its length to zero.
+*/
+
+/*!
+ \fn QModelRoleDataSpan::QModelRoleDataSpan(QModelRoleData &modelRoleData) noexcept
+
+ Constructs an QModelRoleDataSpan spanning over \a modelRoleData,
+ seen as a 1-element array.
+*/
+
+/*!
+ \fn QModelRoleDataSpan::QModelRoleDataSpan(QModelRoleData *modelRoleData, qsizetype len)
+
+ Constructs an QModelRoleDataSpan spanning over the array beginning
+ at \a modelRoleData and with length \a len.
+
+ \note The array must be kept alive as long as this object has not
+ been destructed.
+*/
+
+/*!
+ \fn template <typename Container, QModelRoleDataSpan::if_compatible_container<Container> = true> QModelRoleDataSpan::QModelRoleDataSpan(Container &c) noexcept
+
+ Constructs an QModelRoleDataSpan spanning over the container \a c,
+ which can be any contiguous container of QModelRoleData objects.
+ For instance, it can be a \c{QVector<QModelRoleData>},
+ a \c{std::array<QModelRoleData, 10>} and so on.
+
+ \note The container must be kept alive as long as this object has not
+ been destructed.
+*/
+
+/*!
+ \fn qsizetype QModelRoleDataSpan::size() const noexcept
+
+ Returns the length of the span represented by this object.
+*/
+
+/*!
+ \fn qsizetype QModelRoleDataSpan::length() const noexcept
+
+ Returns the length of the span represented by this object.
+*/
+
+/*!
+ \fn QModelRoleData *QModelRoleDataSpan::data() const noexcept
+
+ Returns a pointer to the beginning of the span represented by this
+ object.
+*/
+
+/*!
+ \fn QModelRoleData *QModelRoleDataSpan::begin() const noexcept
+
+ Returns a pointer to the beginning of the span represented by this
+ object.
+*/
+
+/*!
+ \fn QModelRoleData *QModelRoleDataSpan::end() const noexcept
+
+ Returns a pointer to the imaginary element one past the end of the
+ span represented by this object.
+*/
+
+/*!
+ \fn QModelRoleData &QModelRoleDataSpan::operator[](qsizetype index) const
+
+ Returns a modifiable reference to the QModelRoleData at position
+ \a index in the span.
+
+ \note \a index must be a valid index for this span (0 <= \a index < size()).
+*/
+
+/*!
+ \fn const QVariant *QModelRoleDataSpan::dataForRole(int role) const
+
+ Returns the data associated with the first QModelRoleData in the
+ span that has its role equal to \a role. If such a QModelRoleData
+ object does not exist, the behavior is undefined.
+
+ \note Avoid calling this function from the model's side, as a
+ model cannot possibly know in advance which roles are in a given
+ QModelRoleDataSpan. This function is instead suitable for views and
+ delegates, which have control over the roles in the span.
+
+ \sa QModelRoleData::data()
+*/
+
+/*!
\class QPersistentModelIndex
\inmodule QtCore
\ingroup shared
@@ -192,7 +382,7 @@ QPersistentModelIndex::~QPersistentModelIndex()
model index are used when comparing with another persistent model index.
*/
-bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const
+bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const noexcept
{
if (d && other.d)
return d->index == other.d->index;
@@ -209,12 +399,12 @@ bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const
model index are used when comparing with another persistent model index.
*/
-bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const
+bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const noexcept
{
if (d && other.d)
return d->index < other.d->index;
- return d < other.d;
+ return std::less<>{}(d, other.d);
}
/*!
@@ -267,17 +457,16 @@ QPersistentModelIndex &QPersistentModelIndex::operator=(const QModelIndex &other
}
/*!
- \fn QPersistentModelIndex::operator const QModelIndex&() const
+ \fn QPersistentModelIndex::operator QModelIndex() const
- Cast operator that returns a const QModelIndex&.
+ Cast operator that returns a QModelIndex.
*/
-QPersistentModelIndex::operator const QModelIndex&() const
+QPersistentModelIndex::operator QModelIndex() const
{
- static const QModelIndex invalid;
if (d)
return d->index;
- return invalid;
+ return QModelIndex();
}
/*!
@@ -288,7 +477,7 @@ QPersistentModelIndex::operator const QModelIndex&() const
model index are used when comparing with another model index.
*/
-bool QPersistentModelIndex::operator==(const QModelIndex &other) const
+bool QPersistentModelIndex::operator==(const QModelIndex &other) const noexcept
{
if (d)
return d->index == other;
@@ -302,7 +491,7 @@ bool QPersistentModelIndex::operator==(const QModelIndex &other) const
location as the \a other model index; otherwise returns \c{false}.
*/
-bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+bool QPersistentModelIndex::operator!=(const QModelIndex &other) const noexcept
{
if (d)
return d->index != other;
@@ -423,6 +612,20 @@ QVariant QPersistentModelIndex::data(int role) const
return QVariant();
}
+
+/*!
+ Populates the given \a roleDataSpan for the item referred to by the
+ index.
+
+ \since 6.0
+ \sa Qt::ItemDataRole, QAbstractItemModel::setData()
+*/
+void QPersistentModelIndex::multiData(QModelRoleDataSpan roleDataSpan) const
+{
+ if (d)
+ d->index.multiData(roleDataSpan);
+}
+
/*!
\since 4.2
@@ -483,6 +686,7 @@ QDebug operator<<(QDebug dbg, const QPersistentModelIndex &idx)
class QEmptyItemModel : public QAbstractItemModel
{
+ Q_OBJECT
public:
explicit QEmptyItemModel(QObject *parent = nullptr) : QAbstractItemModel(parent) {}
QModelIndex index(int, int, const QModelIndex &) const override { return QModelIndex(); }
@@ -512,7 +716,7 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
void QAbstractItemModelPrivate::invalidatePersistentIndexes()
{
- for (QPersistentModelIndexData *data : qAsConst(persistent.indexes))
+ for (QPersistentModelIndexData *data : std::as_const(persistent.indexes))
data->index = QModelIndex();
persistent.indexes.clear();
}
@@ -532,7 +736,7 @@ void QAbstractItemModelPrivate::invalidatePersistentIndex(const QModelIndex &ind
}
using DefaultRoleNames = QHash<int, QByteArray>;
-Q_GLOBAL_STATIC_WITH_ARGS(DefaultRoleNames, qDefaultRoleNames, (
+Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames,
{
{ Qt::DisplayRole, "display" },
{ Qt::DecorationRole, "decoration" },
@@ -540,7 +744,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(DefaultRoleNames, qDefaultRoleNames, (
{ Qt::ToolTipRole, "toolTip" },
{ Qt::StatusTipRole, "statusTip" },
{ Qt::WhatsThisRole, "whatsThis" },
- }))
+ })
const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
{
@@ -639,13 +843,13 @@ void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexD
Q_UNUSED(removed);
}
// make sure our optimization still works
- for (int i = persistent.moved.count() - 1; i >= 0; --i) {
+ for (int i = persistent.moved.size() - 1; i >= 0; --i) {
int idx = persistent.moved.at(i).indexOf(data);
if (idx >= 0)
persistent.moved[i].remove(idx);
}
// update the references to invalidated persistent indexes
- for (int i = persistent.invalidated.count() - 1; i >= 0; --i) {
+ for (int i = persistent.invalidated.size() - 1; i >= 0; --i) {
int idx = persistent.invalidated.at(i).indexOf(data);
if (idx >= 0)
persistent.invalidated[i].remove(idx);
@@ -660,7 +864,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent,
Q_UNUSED(last);
QList<QPersistentModelIndexData *> persistent_moved;
if (first < q->rowCount(parent)) {
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
const QModelIndex &index = data->index;
if (index.row() >= first && index.isValid() && index.parent() == parent) {
persistent_moved.append(data);
@@ -696,7 +900,7 @@ void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent
const bool sameParent = (srcParent == destinationParent);
const bool movingUp = (srcFirst > destinationChild);
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
const QModelIndex &index = data->index;
const QModelIndex &parent = index.parent();
const bool isSourceIndex = (parent == srcParent);
@@ -794,7 +998,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent,
QList<QPersistentModelIndexData *> persistent_invalidated;
// find the persistent indexes that are affected by the change, either by being in the removed subtree
// or by being on the same level and below the removed rows
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
bool level_changed = false;
QModelIndex current = data->index;
while (current.isValid()) {
@@ -846,7 +1050,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeInserted(const QModelIndex &pare
Q_UNUSED(last);
QList<QPersistentModelIndexData *> persistent_moved;
if (first < q->columnCount(parent)) {
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
const QModelIndex &index = data->index;
if (index.column() >= first && index.isValid() && index.parent() == parent)
persistent_moved.append(data);
@@ -879,7 +1083,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeRemoved(const QModelIndex &paren
QList<QPersistentModelIndexData *> persistent_invalidated;
// find the persistent indexes that are affected by the change, either by being in the removed subtree
// or by being on the same level and to the right of the removed columns
- for (auto *data : qAsConst(persistent.indexes)) {
+ for (auto *data : std::as_const(persistent.indexes)) {
bool level_changed = false;
QModelIndex current = data->index;
while (current.isValid()) {
@@ -1109,6 +1313,14 @@ void QAbstractItemModel::resetInternalData()
*/
/*!
+ \fn void QModelIndex::multiData(QModelRoleDataSpan roleDataSpan) const
+ \since 6.0
+
+ Populates the given \a roleDataSpan for the item referred to by the
+ index.
+*/
+
+/*!
\fn Qt::ItemFlags QModelIndex::flags() const
\since 4.2
@@ -1288,10 +1500,12 @@ void QAbstractItemModel::resetInternalData()
rows to the model, \l{QAbstractItemModel::}{beginInsertRows()} and
\l{QAbstractItemModel::}{endInsertRows()} must be called.
+ \include models.qdocinc {thread-safety-section1}{QAbstractItemModel}
+
\sa {Model Classes}, {Model Subclassing Reference}, QModelIndex,
QAbstractItemView, {Using drag and drop with item views},
- {Simple DOM Model Example}, {Simple Tree Model Example},
- {Editable Tree Model Example}, {Fetch More Example}
+ {Simple Tree Model Example}, {Editable Tree Model Example},
+ {Fetch More Example}
*/
/*!
@@ -1530,7 +1744,13 @@ QAbstractItemModel::~QAbstractItemModel()
For example:
- \snippet ../widgets/itemviews/simpledommodel/dommodel.cpp 2
+ \code
+ int MyModel::columnCount(const QModelIndex &parent) const
+ {
+ Q_UNUSED(parent);
+ return 3;
+ }
+ \endcode
\note When implementing a table based model, columnCount() should return 0
when the parent is valid.
@@ -1615,13 +1835,13 @@ QAbstractItemModel::~QAbstractItemModel()
*/
/*!
- \fn void QAbstractItemModel::rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
+ \fn void QAbstractItemModel::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
\since 4.6
This signal is emitted after rows have been moved within the
- model. The items between \a start and \a end
- inclusive, under the given \a parent item have been moved to \a destination
- starting at the row \a row.
+ model. The items between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the row \a destinationRow.
\b{Note:} Components connected to this signal use it to adapt to changes
in the model's dimensions. It can only be emitted by the QAbstractItemModel
@@ -1647,13 +1867,13 @@ QAbstractItemModel::~QAbstractItemModel()
*/
/*!
- \fn void QAbstractItemModel::columnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column)
+ \fn void QAbstractItemModel::columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
\since 4.6
This signal is emitted after columns have been moved within the
- model. The items between \a start and \a end
- inclusive, under the given \a parent item have been moved to \a destination
- starting at the column \a column.
+ model. The items between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the column \a destinationColumn.
\b{Note:} Components connected to this signal use it to adapt to changes
in the model's dimensions. It can only be emitted by the QAbstractItemModel
@@ -1844,7 +2064,7 @@ bool QAbstractItemModel::clearItemData(const QModelIndex &index)
by the \a index.
\note If you do not have a value to return, return an \b invalid
- QVariant instead of returning 0.
+ (default-constructed) QVariant.
\sa Qt::ItemDataRole, setData(), headerData()
*/
@@ -1861,7 +2081,7 @@ bool QAbstractItemModel::clearItemData(const QModelIndex &index)
*/
bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
{
- // ### Qt 6: Consider change the semantics of this function,
+ // ### TODO: Consider change the semantics of this function,
// or deprecating/removing it altogether.
//
// For instance, it should try setting *all* the data
@@ -1904,14 +2124,14 @@ QStringList QAbstractItemModel::mimeTypes() const
mimeTypes(). If you reimplement mimeTypes() in your custom model to return
more MIME types, reimplement this function to make use of them.
- If the list of \a indexes is empty, or there are no supported MIME types, 0
- is returned rather than a serialized empty list.
+ If the list of \a indexes is empty, or there are no supported MIME types,
+ \nullptr is returned rather than a serialized empty list.
\sa mimeTypes(), dropMimeData()
*/
QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const
{
- if (indexes.count() <= 0)
+ if (indexes.size() <= 0)
return nullptr;
QStringList types = mimeTypes();
if (types.isEmpty())
@@ -1919,7 +2139,7 @@ QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const
QMimeData *data = new QMimeData();
QString format = types.at(0);
QByteArray encoded;
- QDataStream stream(&encoded, QIODevice::WriteOnly);
+ QDataStream stream(&encoded, QDataStream::WriteOnly);
encodeData(indexes, stream);
data->setData(format, encoded);
return data;
@@ -1942,15 +2162,15 @@ bool QAbstractItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction a
int row, int column,
const QModelIndex &parent) const
{
- Q_UNUSED(row)
- Q_UNUSED(column)
- Q_UNUSED(parent)
+ Q_UNUSED(row);
+ Q_UNUSED(column);
+ Q_UNUSED(parent);
if (!(action & supportedDropActions()))
return false;
const QStringList modelTypes = mimeTypes();
- for (int i = 0; i < modelTypes.count(); ++i) {
+ for (int i = 0; i < modelTypes.size(); ++i) {
if (data->hasFormat(modelTypes.at(i)))
return true;
}
@@ -2007,7 +2227,7 @@ bool QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
column = 0;
// decode and insert
QByteArray encoded = data->data(format);
- QDataStream stream(&encoded, QIODevice::ReadOnly);
+ QDataStream stream(&encoded, QDataStream::ReadOnly);
return decodeData(row, column, parent, stream);
}
@@ -2291,10 +2511,10 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
Qt::MatchFlags flags) const
{
QModelIndexList result;
- uint matchType = flags & 0x0F;
+ uint matchType = (flags & Qt::MatchTypeMask).toInt();
Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
- bool recurse = flags & Qt::MatchRecursive;
- bool wrap = flags & Qt::MatchWrap;
+ bool recurse = flags.testAnyFlag(Qt::MatchRecursive);
+ bool wrap = flags.testAnyFlag(Qt::MatchWrap);
bool allHits = (hits == -1);
QString text; // only convert to a string if it is needed
#if QT_CONFIG(regularexpression)
@@ -2307,7 +2527,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
// iterates twice if wrapping
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
- for (int r = from; (r < to) && (allHits || result.count() < hits); ++r) {
+ for (int r = from; (r < to) && (allHits || result.size() < hits); ++r) {
QModelIndex idx = index(r, column, p);
if (!idx.isValid())
continue;
@@ -2329,8 +2549,10 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
}
}
} else if (matchType == Qt::MatchWildcard) {
- if (rx.pattern().isEmpty())
- rx.setPattern(QRegularExpression::wildcardToRegularExpression(value.toString()));
+ if (rx.pattern().isEmpty()) {
+ const QString pattern = QRegularExpression::wildcardToRegularExpression(value.toString(), QRegularExpression::NonPathWildcardConversion);
+ rx.setPattern(pattern);
+ }
if (cs == Qt::CaseInsensitive)
rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
} else
@@ -2373,7 +2595,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
if (hasChildren(parent)) { // search the hierarchy
result += match(index(0, column, parent), role,
(text.isEmpty() ? value : text),
- (allHits ? -1 : hits - result.count()), flags);
+ (allHits ? -1 : hits - result.size()), flags);
}
}
}
@@ -2566,15 +2788,15 @@ bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &pare
// Compute the number of continuous rows upon insertion and modify the rows to match
QList<int> rowsToInsert(bottom + 1);
- for (int i = 0; i < rows.count(); ++i)
+ for (int i = 0; i < rows.size(); ++i)
rowsToInsert[rows.at(i)] = 1;
- for (int i = 0; i < rowsToInsert.count(); ++i) {
+ for (int i = 0; i < rowsToInsert.size(); ++i) {
if (rowsToInsert.at(i) == 1){
rowsToInsert[i] = dragRowCount;
++dragRowCount;
}
}
- for (int i = 0; i < rows.count(); ++i)
+ for (int i = 0; i < rows.size(); ++i)
rows[i] = top + rowsToInsert.at(rows.at(i));
QBitArray isWrittenTo(dragRowCount * dragColumnCount);
@@ -2776,6 +2998,13 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star
}
/*!
+ \internal
+
+ see QTBUG-94546
+ */
+void QAbstractItemModelPrivate::executePendingOperations() const { }
+
+/*!
\since 4.6
Begins a row move operation.
@@ -3103,9 +3332,8 @@ bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int s
destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
d->changes.push(destinationChange);
- d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
-
emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
+ d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
return true;
}
@@ -3138,7 +3366,6 @@ void QAbstractItemModel::endMoveColumns()
adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
-
emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
}
@@ -3232,8 +3459,8 @@ void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
if (d->persistent.indexes.isEmpty())
return;
QList<QPersistentModelIndexData *> toBeReinserted;
- toBeReinserted.reserve(to.count());
- for (int i = 0; i < from.count(); ++i) {
+ toBeReinserted.reserve(to.size());
+ for (int i = 0; i < from.size(); ++i) {
if (from.at(i) == to.at(i))
continue;
const auto it = d->persistent.indexes.constFind(from.at(i));
@@ -3246,7 +3473,7 @@ void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
}
}
- for (auto *data : qAsConst(toBeReinserted))
+ for (auto *data : std::as_const(toBeReinserted))
d->persistent.insertMultiAtEnd(data->index, data);
}
@@ -3259,8 +3486,8 @@ QModelIndexList QAbstractItemModel::persistentIndexList() const
{
Q_D(const QAbstractItemModel);
QModelIndexList result;
- result.reserve(d->persistent.indexes.count());
- for (auto *data : qAsConst(d->persistent.indexes))
+ result.reserve(d->persistent.indexes.size());
+ for (auto *data : std::as_const(d->persistent.indexes))
result.append(data->index);
return result;
}
@@ -3401,6 +3628,61 @@ bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions
}
/*!
+ \since 6.0
+
+ Fills the \a roleDataSpan with the requested data for the given \a index.
+
+ The default implementation will call simply data() for each role in
+ the span. A subclass can reimplement this function to provide data
+ to views more efficiently:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 15
+
+ In the snippet above, \c{index} is the same for the entire call.
+ This means that accessing to the necessary data structures in order
+ to retrieve the information for \c{index} can be done only once
+ (hoisting the relevant code out of the loop).
+
+ The usage of QModelRoleData::setData(), or similarly
+ QVariant::setValue(), is encouraged over constructing a QVariant
+ separately and using a plain assignment operator; this is
+ because the former allow to re-use the memory already allocated for
+ the QVariant object stored inside a QModelRoleData, while the latter
+ always allocates the new variant and then destroys the old one.
+
+ Note that views may call multiData() with spans that have been used
+ in previous calls, and therefore may already contain some data.
+ Therefore, it is imperative that if the model cannot return the
+ data for a given role, then it must clear the data in the
+ corresponding QModelRoleData object. This can be done by calling
+ QModelRoleData::clearData(), or similarly by setting a default
+ constructed QVariant, and so on. Failure to clear the data will
+ result in the view believing that the "old" data is meant to be
+ used for the corresponding role.
+
+ Finally, in order to avoid code duplication, a subclass may also
+ decide to reimplement data() in terms of multiData(), by supplying
+ a span of just one element:
+
+ \snippet code/src_corelib_kernel_qabstractitemmodel.cpp 16
+
+ \note Models are not allowed to modify the roles in the span, or
+ to rearrange the span elements. Doing so results in undefined
+ behavior.
+
+ \note It is illegal to pass an invalid model index to this function.
+
+ \sa QModelRoleDataSpan, data()
+*/
+void QAbstractItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
+{
+ Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
+
+ for (QModelRoleData &d : roleDataSpan)
+ d.setData(data(index, d.role()));
+}
+
+/*!
\class QAbstractTableModel
\inmodule QtCore
\brief The QAbstractTableModel class provides an abstract model that can be
@@ -3457,10 +3739,9 @@ bool QAbstractItemModel::checkIndex(const QModelIndex &index, CheckIndexOptions
\note Some general guidelines for subclassing models are available in the
\l{Model Subclassing Reference}.
- \note
+ \include models.qdocinc {thread-safety-section1}{QAbstractTableModel}
- \sa {Model Classes}, QAbstractItemModel, QAbstractListModel,
- {Pixelator Example}
+ \sa {Model Classes}, QAbstractItemModel, QAbstractListModel
*/
/*!
@@ -3611,7 +3892,7 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
\l{Model Subclassing Reference}.
\sa {Model Classes}, {Model Subclassing Reference}, QAbstractItemView,
- QAbstractTableModel, {Item Views Puzzle Example}
+ QAbstractTableModel
*/
/*!
@@ -3730,7 +4011,7 @@ bool QAbstractTableModel::dropMimeData(const QMimeData *data, Qt::DropAction act
return false;
QByteArray encoded = data->data(format);
- QDataStream stream(&encoded, QIODevice::ReadOnly);
+ QDataStream stream(&encoded, QDataStream::ReadOnly);
// if the drop is on an item, replace the data in the items
if (parent.isValid() && row == -1 && column == -1) {
@@ -3781,7 +4062,7 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
return false;
QByteArray encoded = data->data(format);
- QDataStream stream(&encoded, QIODevice::ReadOnly);
+ QDataStream stream(&encoded, QDataStream::ReadOnly);
// if the drop is on an item, replace the data in the items
if (parent.isValid() && row == -1 && column == -1) {
@@ -3889,3 +4170,4 @@ void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex&
QT_END_NAMESPACE
#include "moc_qabstractitemmodel.cpp"
+#include "qabstractitemmodel.moc"
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index a7fb429cf3..8f22f14989 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTITEMMODEL_H
#define QABSTRACTITEMMODEL_H
@@ -49,6 +14,108 @@ QT_REQUIRE_CONFIG(itemmodel);
QT_BEGIN_NAMESPACE
+class QModelRoleData
+{
+ int m_role;
+ QVariant m_data;
+
+public:
+ explicit QModelRoleData(int role) noexcept
+ : m_role(role)
+ {}
+
+ constexpr int role() const noexcept { return m_role; }
+ constexpr QVariant &data() noexcept { return m_data; }
+ constexpr const QVariant &data() const noexcept { return m_data; }
+
+ template <typename T>
+ constexpr void setData(T &&value) noexcept(noexcept(m_data.setValue(std::forward<T>(value))))
+ { m_data.setValue(std::forward<T>(value)); }
+
+ void clearData() noexcept { m_data.clear(); }
+};
+
+Q_DECLARE_TYPEINFO(QModelRoleData, Q_RELOCATABLE_TYPE);
+
+class QModelRoleDataSpan;
+
+namespace QtPrivate {
+template <typename T, typename Enable = void>
+struct IsContainerCompatibleWithModelRoleDataSpan : std::false_type {};
+
+template <typename T>
+struct IsContainerCompatibleWithModelRoleDataSpan<T, std::enable_if_t<std::conjunction_v<
+ // lacking concepts and ranges, we accept any T whose std::data yields a suitable pointer ...
+ std::is_convertible<decltype( std::data(std::declval<T &>()) ), QModelRoleData *>,
+ // ... and that has a suitable size ...
+ std::is_convertible<decltype( std::size(std::declval<T &>()) ), qsizetype>,
+ // ... and it's a range as it defines an iterator-like API
+ std::is_convertible<
+ typename std::iterator_traits<decltype( std::begin(std::declval<T &>()) )>::value_type,
+ QModelRoleData
+ >,
+ std::is_convertible<
+ decltype( std::begin(std::declval<T &>()) != std::end(std::declval<T &>()) ),
+ bool>,
+ // Don't make an accidental copy constructor
+ std::negation<std::is_same<std::decay_t<T>, QModelRoleDataSpan>>
+ >>> : std::true_type {};
+} // namespace QtPrivate
+
+class QModelRoleDataSpan
+{
+ QModelRoleData *m_modelRoleData = nullptr;
+ qsizetype m_len = 0;
+
+ template <typename T>
+ using if_compatible_container = std::enable_if_t<QtPrivate::IsContainerCompatibleWithModelRoleDataSpan<T>::value, bool>;
+
+public:
+ constexpr QModelRoleDataSpan() noexcept {}
+
+ constexpr QModelRoleDataSpan(QModelRoleData &modelRoleData) noexcept
+ : m_modelRoleData(&modelRoleData),
+ m_len(1)
+ {}
+
+ constexpr QModelRoleDataSpan(QModelRoleData *modelRoleData, qsizetype len)
+ : m_modelRoleData(modelRoleData),
+ m_len(len)
+ {}
+
+ template <typename Container, if_compatible_container<Container> = true>
+ constexpr QModelRoleDataSpan(Container &c) noexcept(noexcept(std::data(c)) && noexcept(std::size(c)))
+ : m_modelRoleData(std::data(c)),
+ m_len(qsizetype(std::size(c)))
+ {}
+
+ constexpr qsizetype size() const noexcept { return m_len; }
+ constexpr qsizetype length() const noexcept { return m_len; }
+ constexpr QModelRoleData *data() const noexcept { return m_modelRoleData; }
+ constexpr QModelRoleData *begin() const noexcept { return m_modelRoleData; }
+ constexpr QModelRoleData *end() const noexcept { return m_modelRoleData + m_len; }
+ constexpr QModelRoleData &operator[](qsizetype index) const { return m_modelRoleData[index]; }
+
+ constexpr QVariant *dataForRole(int role) const
+ {
+#ifdef __cpp_lib_constexpr_algorithms
+ auto result = std::find_if(begin(), end(), [role](const QModelRoleData &roleData) {
+ return roleData.role() == role;
+ });
+#else
+ auto result = begin();
+ const auto e = end();
+ for (; result != e; ++result) {
+ if (result->role() == role)
+ break;
+ }
+#endif
+
+ return Q_ASSERT(result != end()), &result->data();
+ }
+};
+
+Q_DECLARE_TYPEINFO(QModelRoleDataSpan, Q_RELOCATABLE_TYPE);
class QAbstractItemModel;
class QPersistentModelIndex;
@@ -57,11 +124,11 @@ class QModelIndex
{
friend class QAbstractItemModel;
public:
- Q_DECL_CONSTEXPR inline QModelIndex() noexcept : r(-1), c(-1), i(0), m(nullptr) {}
+ constexpr inline QModelIndex() noexcept : r(-1), c(-1), i(0), m(nullptr) {}
// compiler-generated copy/move ctors/assignment operators are fine!
- Q_DECL_CONSTEXPR inline int row() const noexcept { return r; }
- Q_DECL_CONSTEXPR inline int column() const noexcept { return c; }
- Q_DECL_CONSTEXPR inline quintptr internalId() const noexcept { return i; }
+ constexpr inline int row() const noexcept { return r; }
+ constexpr inline int column() const noexcept { return c; }
+ constexpr inline quintptr internalId() const noexcept { return i; }
inline void *internalPointer() const noexcept { return reinterpret_cast<void*>(i); }
inline const void *constInternalPointer() const noexcept { return reinterpret_cast<const void *>(i); }
inline QModelIndex parent() const;
@@ -69,14 +136,15 @@ public:
inline QModelIndex siblingAtColumn(int column) const;
inline QModelIndex siblingAtRow(int row) const;
inline QVariant data(int role = Qt::DisplayRole) const;
+ inline void multiData(QModelRoleDataSpan roleDataSpan) const;
inline Qt::ItemFlags flags() const;
- Q_DECL_CONSTEXPR inline const QAbstractItemModel *model() const noexcept { return m; }
- Q_DECL_CONSTEXPR inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); }
- Q_DECL_CONSTEXPR inline bool operator==(const QModelIndex &other) const noexcept
+ constexpr inline const QAbstractItemModel *model() const noexcept { return m; }
+ constexpr inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); }
+ constexpr inline bool operator==(const QModelIndex &other) const noexcept
{ return (other.r == r) && (other.i == i) && (other.c == c) && (other.m == m); }
- Q_DECL_CONSTEXPR inline bool operator!=(const QModelIndex &other) const noexcept
+ constexpr inline bool operator!=(const QModelIndex &other) const noexcept
{ return !(*this == other); }
- Q_DECL_CONSTEXPR inline bool operator<(const QModelIndex &other) const noexcept
+ constexpr inline bool operator<(const QModelIndex &other) const noexcept
{
return r < other.r
|| (r == other.r && (c < other.c
@@ -86,13 +154,13 @@ public:
private:
inline QModelIndex(int arow, int acolumn, const void *ptr, const QAbstractItemModel *amodel) noexcept
: r(arow), c(acolumn), i(reinterpret_cast<quintptr>(ptr)), m(amodel) {}
- Q_DECL_CONSTEXPR inline QModelIndex(int arow, int acolumn, quintptr id, const QAbstractItemModel *amodel) noexcept
+ constexpr inline QModelIndex(int arow, int acolumn, quintptr id, const QAbstractItemModel *amodel) noexcept
: r(arow), c(acolumn), i(id), m(amodel) {}
int r, c;
quintptr i;
const QAbstractItemModel *m;
};
-Q_DECLARE_TYPEINFO(QModelIndex, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QModelIndex, Q_RELOCATABLE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QModelIndex &);
@@ -110,20 +178,19 @@ public:
QPersistentModelIndex(const QModelIndex &index);
QPersistentModelIndex(const QPersistentModelIndex &other);
~QPersistentModelIndex();
- bool operator<(const QPersistentModelIndex &other) const;
- bool operator==(const QPersistentModelIndex &other) const;
- inline bool operator!=(const QPersistentModelIndex &other) const
+ bool operator<(const QPersistentModelIndex &other) const noexcept;
+ bool operator==(const QPersistentModelIndex &other) const noexcept;
+ inline bool operator!=(const QPersistentModelIndex &other) const noexcept
{ return !operator==(other); }
QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
inline QPersistentModelIndex(QPersistentModelIndex &&other) noexcept
- : d(other.d) { other.d = nullptr; }
- inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other) noexcept
- { qSwap(d, other.d); return *this; }
- inline void swap(QPersistentModelIndex &other) noexcept { qSwap(d, other.d); }
- bool operator==(const QModelIndex &other) const;
- bool operator!=(const QModelIndex &other) const;
+ : d(std::exchange(other.d, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPersistentModelIndex)
+ void swap(QPersistentModelIndex &other) noexcept { qt_ptr_swap(d, other.d); }
+ bool operator==(const QModelIndex &other) const noexcept;
+ bool operator!=(const QModelIndex &other) const noexcept;
QPersistentModelIndex &operator=(const QModelIndex &other);
- operator const QModelIndex&() const;
+ operator QModelIndex() const;
int row() const;
int column() const;
void *internalPointer() const;
@@ -132,12 +199,15 @@ public:
QModelIndex parent() const;
QModelIndex sibling(int row, int column) const;
QVariant data(int role = Qt::DisplayRole) const;
+ void multiData(QModelRoleDataSpan roleDataSpan) const;
Qt::ItemFlags flags() const;
const QAbstractItemModel *model() const;
bool isValid() const;
private:
QPersistentModelIndexData *d;
friend size_t qHash(const QPersistentModelIndex &, size_t seed) noexcept;
+ friend bool qHashEquals(const QPersistentModelIndex &a, const QPersistentModelIndex &b) noexcept
+ { return a.d == b.d; }
#ifndef QT_NO_DEBUG_STREAM
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
#endif
@@ -166,8 +236,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject
friend class QPersistentModelIndexData;
friend class QAbstractItemViewPrivate;
- friend class QIdentityProxyModel;
- friend class QTransposeProxyModelPrivate;
+ friend class QAbstractProxyModel;
public:
explicit QAbstractItemModel(QObject *parent = nullptr);
@@ -204,28 +273,28 @@ public:
virtual Qt::DropActions supportedDropActions() const;
virtual Qt::DropActions supportedDragActions() const;
- virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
- virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex());
- virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
- virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex());
- virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
+ Q_INVOKABLE Q_REVISION(6, 4) virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
const QModelIndex &destinationParent, int destinationChild);
- virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
+ Q_INVOKABLE Q_REVISION(6, 4) virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
const QModelIndex &destinationParent, int destinationChild);
- inline bool insertRow(int row, const QModelIndex &parent = QModelIndex());
- inline bool insertColumn(int column, const QModelIndex &parent = QModelIndex());
- inline bool removeRow(int row, const QModelIndex &parent = QModelIndex());
- inline bool removeColumn(int column, const QModelIndex &parent = QModelIndex());
- inline bool moveRow(const QModelIndex &sourceParent, int sourceRow,
+ Q_INVOKABLE Q_REVISION(6, 4) inline bool insertRow(int row, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) inline bool insertColumn(int column, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) inline bool removeRow(int row, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) inline bool removeColumn(int column, const QModelIndex &parent = QModelIndex());
+ Q_INVOKABLE Q_REVISION(6, 4) inline bool moveRow(const QModelIndex &sourceParent, int sourceRow,
const QModelIndex &destinationParent, int destinationChild);
- inline bool moveColumn(const QModelIndex &sourceParent, int sourceColumn,
+ Q_INVOKABLE Q_REVISION(6, 4) inline bool moveColumn(const QModelIndex &sourceParent, int sourceColumn,
const QModelIndex &destinationParent, int destinationChild);
Q_INVOKABLE virtual void fetchMore(const QModelIndex &parent);
Q_INVOKABLE virtual bool canFetchMore(const QModelIndex &parent) const;
Q_INVOKABLE virtual Qt::ItemFlags flags(const QModelIndex &index) const;
- virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
+ Q_INVOKABLE Q_REVISION(6, 4) virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
virtual QModelIndex buddy(const QModelIndex &index) const;
Q_INVOKABLE virtual QModelIndexList match(const QModelIndex &start, int role,
const QVariant &value, int hits = 1,
@@ -254,7 +323,9 @@ public:
Q_ENUM(CheckIndexOption)
Q_DECLARE_FLAGS(CheckIndexOptions, CheckIndexOption)
- Q_REQUIRED_RESULT bool checkIndex(const QModelIndex &index, CheckIndexOptions options = CheckIndexOption::NoOption) const;
+ [[nodiscard]] bool checkIndex(const QModelIndex &index, CheckIndexOptions options = CheckIndexOption::NoOption) const;
+
+ virtual void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const;
Q_SIGNALS:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
@@ -279,10 +350,10 @@ Q_SIGNALS:
void modelReset(QPrivateSignal);
void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal);
- void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row, QPrivateSignal);
+ void rowsMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal);
void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal);
- void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column, QPrivateSignal);
+ void columnsMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal);
public Q_SLOTS:
virtual bool submit();
@@ -421,14 +492,23 @@ inline QModelIndex QModelIndex::siblingAtRow(int arow) const
inline QVariant QModelIndex::data(int arole) const
{ return m ? m->data(*this, arole) : QVariant(); }
+inline void QModelIndex::multiData(QModelRoleDataSpan roleDataSpan) const
+{ if (m) m->multiData(*this, roleDataSpan); }
+
inline Qt::ItemFlags QModelIndex::flags() const
{ return m ? m->flags(*this) : Qt::ItemFlags(); }
-inline size_t qHash(const QModelIndex &index, size_t seed) noexcept
-{ return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed; }
+inline size_t qHash(const QModelIndex &index, size_t seed = 0) noexcept
+{
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
+ return qHashMulti(seed, index.row(), index.column(), index.internalId());
+#else
+ return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed;
+#endif
+}
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QModelIndexList)
+QT_DECL_METATYPE_EXTERN(QModelIndexList, Q_CORE_EXPORT)
#endif // QABSTRACTITEMMODEL_H
diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h
index 6b2f69cf30..e34dc3262c 100644
--- a/src/corelib/itemmodels/qabstractitemmodel_p.h
+++ b/src/corelib/itemmodels/qabstractitemmodel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTITEMMODEL_P_H
#define QABSTRACTITEMMODEL_P_H
@@ -99,6 +63,9 @@ public:
void itemsMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation);
bool allowMove(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation);
+ // ugly hack for QTreeModel, see QTBUG-94546
+ virtual void executePendingOperations() const;
+
inline QModelIndex createIndex(int row, int column, void *data = nullptr) const {
return q_func()->createIndex(row, column, data);
}
@@ -115,8 +82,8 @@ public:
void invalidatePersistentIndex(const QModelIndex &index);
struct Change {
- Q_DECL_CONSTEXPR Change() : parent(), first(-1), last(-1), needsAdjust(false) {}
- Q_DECL_CONSTEXPR Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l), needsAdjust(false) {}
+ constexpr Change() : parent(), first(-1), last(-1), needsAdjust(false) {}
+ constexpr Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l), needsAdjust(false) {}
QModelIndex parent;
int first, last;
@@ -136,7 +103,7 @@ public:
// rowsMoved signal.
bool needsAdjust;
- Q_DECL_CONSTEXPR bool isValid() const { return first >= 0 && last >= 0; }
+ constexpr bool isValid() const { return first >= 0 && last >= 0; }
};
QStack<Change> changes;
@@ -152,7 +119,57 @@ public:
static bool isVariantLessThan(const QVariant &left, const QVariant &right,
Qt::CaseSensitivity cs = Qt::CaseSensitive, bool isLocaleAware = false);
};
-Q_DECLARE_TYPEINFO(QAbstractItemModelPrivate::Change, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QAbstractItemModelPrivate::Change, Q_RELOCATABLE_TYPE);
+
+namespace QtPrivate {
+
+/*!
+ \internal
+ This is a workaround for QTBUG-75172.
+
+ Some predefined model roles are supposed to use certain enum/flag
+ types (e.g. fetching Qt::TextAlignmentRole is supposed to return a
+ variant containing a Qt::Alignment object).
+
+ For historical reasons, a plain `int` was used sometimes. This is
+ surprising to end-users and also sloppy on Qt's part; users were
+ forced to use `int` rather than the correct datatype.
+
+ This function tries both the "right" type and plain `int`, for a
+ given QVariant. This fixes the problem (using the correct datatype)
+ but also keeps compatibility with existing code using `int`.
+
+ ### Qt 7: get rid of this. Always use the correct datatype.
+*/
+template <typename T>
+T legacyEnumValueFromModelData(const QVariant &data)
+{
+ static_assert(std::is_enum_v<T>);
+ if (data.userType() == qMetaTypeId<T>()) {
+ return data.value<T>();
+ } else if (std::is_same_v<std::underlying_type_t<T>, int> ||
+ std::is_same_v<std::underlying_type_t<T>, uint>) {
+ return T(data.toInt());
+ }
+
+ return T();
+}
+
+template <typename T>
+T legacyFlagValueFromModelData(const QVariant &data)
+{
+ if (data.userType() == qMetaTypeId<T>()) {
+ return data.value<T>();
+ } else if (std::is_same_v<std::underlying_type_t<typename T::enum_type>, int> ||
+ std::is_same_v<std::underlying_type_t<typename T::enum_type>, uint>) {
+ return T::fromInt(data.toInt());
+ }
+
+ return T();
+}
+
+} // namespace QtPrivate
+
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp
index e5d8c68e72..abdeefb4da 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.cpp
+++ b/src/corelib/itemmodels/qabstractproxymodel.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractproxymodel.h"
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
#include <QtCore/QSize>
#include <QtCore/QStringList>
+#include <QtCore/QMap>
QT_BEGIN_NAMESPACE
@@ -90,6 +55,87 @@ void QAbstractProxyModelPrivate::_q_sourceModelDestroyed()
model = QAbstractItemModelPrivate::staticEmptyModel();
}
+void QAbstractProxyModelPrivate::emitHeaderDataChanged()
+{
+ Q_Q(QAbstractProxyModel);
+
+ if (updateHorizontalHeader) {
+ if (auto columnCount = q->columnCount(); columnCount > 0)
+ emit q->headerDataChanged(Qt::Horizontal, 0, columnCount - 1);
+ }
+
+ if (updateVerticalHeader) {
+ if (auto rowCount = q->rowCount(); rowCount > 0)
+ emit q->headerDataChanged(Qt::Vertical, 0, rowCount - 1);
+ }
+
+ updateHorizontalHeader = false;
+ updateVerticalHeader = false;
+}
+
+void QAbstractProxyModelPrivate::scheduleHeaderUpdate(Qt::Orientation orientation)
+{
+ const bool isUpdateScheduled = updateHorizontalHeader || updateVerticalHeader;
+
+ if (orientation == Qt::Horizontal && !updateHorizontalHeader)
+ updateHorizontalHeader = true;
+ else if (orientation == Qt::Vertical && !updateVerticalHeader)
+ updateVerticalHeader = true;
+ else
+ return;
+
+ if (!isUpdateScheduled) {
+ Q_Q(QAbstractProxyModel);
+ QMetaObject::invokeMethod(q, [this]() { emitHeaderDataChanged(); }, Qt::QueuedConnection);
+ }
+}
+
+void QAbstractProxyModelPrivate::_q_sourceModelRowsAboutToBeInserted(const QModelIndex &parent, int, int)
+{
+ if (parent.isValid())
+ return;
+ sourceHadZeroRows = model->rowCount() == 0;
+}
+
+void QAbstractProxyModelPrivate::_q_sourceModelRowsInserted(const QModelIndex &parent, int, int)
+{
+ if (parent.isValid())
+ return;
+ if (sourceHadZeroRows)
+ scheduleHeaderUpdate(Qt::Horizontal);
+}
+
+void QAbstractProxyModelPrivate::_q_sourceModelRowsRemoved(const QModelIndex &parent, int, int)
+{
+ if (parent.isValid())
+ return;
+ if (model->rowCount() == 0)
+ scheduleHeaderUpdate(Qt::Horizontal);
+}
+
+void QAbstractProxyModelPrivate::_q_sourceModelColumnsAboutToBeInserted(const QModelIndex &parent, int, int)
+{
+ if (parent.isValid())
+ return;
+ sourceHadZeroColumns = model->columnCount() == 0;
+}
+
+void QAbstractProxyModelPrivate::_q_sourceModelColumnsInserted(const QModelIndex &parent, int, int)
+{
+ if (parent.isValid())
+ return;
+ if (sourceHadZeroColumns)
+ scheduleHeaderUpdate(Qt::Vertical);
+}
+
+void QAbstractProxyModelPrivate::_q_sourceModelColumnsRemoved(const QModelIndex &parent, int, int)
+{
+ if (parent.isValid())
+ return;
+ if (model->columnCount() == 0)
+ scheduleHeaderUpdate(Qt::Vertical);
+}
+
/*!
Constructs a proxy model with the given \a parent.
*/
@@ -128,17 +174,41 @@ QAbstractProxyModel::~QAbstractProxyModel()
void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
Q_D(QAbstractProxyModel);
- if (sourceModel != d->model) {
- if (d->model)
- disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
+ d->model.removeBindingUnlessInWrapper();
+ // Special case to handle nullptr models. Otherwise we will have unwanted
+ // notifications.
+ const QAbstractItemModel *currentModel = d->model.valueBypassingBindings();
+ if (!sourceModel && currentModel == QAbstractItemModelPrivate::staticEmptyModel())
+ return;
+ static const struct {
+ const char *signalName;
+ const char *slotName;
+ } connectionTable[] = {
+ // clang-format off
+ { SIGNAL(destroyed()), SLOT(_q_sourceModelDestroyed()) },
+ { SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), SLOT(_q_sourceModelRowsAboutToBeInserted(QModelIndex,int,int)) },
+ { SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(_q_sourceModelRowsInserted(QModelIndex,int,int)) },
+ { SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(_q_sourceModelRowsRemoved(QModelIndex,int,int)) },
+ { SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsAboutToBeInserted(QModelIndex,int,int)) },
+ { SIGNAL(columnsInserted(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsInserted(QModelIndex,int,int)) },
+ { SIGNAL(columnsRemoved(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsRemoved(QModelIndex,int,int)) }
+ // clang-format on
+ };
+
+ if (sourceModel != currentModel) {
+ if (currentModel) {
+ for (const auto &c : connectionTable)
+ disconnect(currentModel, c.signalName, this, c.slotName);
+ }
if (sourceModel) {
- d->model = sourceModel;
- connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
+ d->model.setValueBypassingBindings(sourceModel);
+ for (const auto &c : connectionTable)
+ connect(sourceModel, c.signalName, this, c.slotName);
} else {
- d->model = QAbstractItemModelPrivate::staticEmptyModel();
+ d->model.setValueBypassingBindings(QAbstractItemModelPrivate::staticEmptyModel());
}
- emit sourceModelChanged(QPrivateSignal());
+ d->model.notify();
}
}
@@ -153,6 +223,12 @@ QAbstractItemModel *QAbstractProxyModel::sourceModel() const
return d->model;
}
+QBindable<QAbstractItemModel *> QAbstractProxyModel::bindableSourceModel()
+{
+ Q_D(QAbstractProxyModel);
+ return QBindable<QAbstractItemModel *>(&d->model);
+}
+
/*!
\reimp
*/
@@ -241,13 +317,17 @@ QVariant QAbstractProxyModel::data(const QModelIndex &proxyIndex, int role) cons
QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_D(const QAbstractProxyModel);
- int sourceSection;
+ int sourceSection = section;
if (orientation == Qt::Horizontal) {
- const QModelIndex proxyIndex = index(0, section);
- sourceSection = mapToSource(proxyIndex).column();
+ if (rowCount() > 0) {
+ const QModelIndex proxyIndex = index(0, section);
+ sourceSection = mapToSource(proxyIndex).column();
+ }
} else {
- const QModelIndex proxyIndex = index(section, 0);
- sourceSection = mapToSource(proxyIndex).row();
+ if (columnCount() > 0) {
+ const QModelIndex proxyIndex = index(section, 0);
+ sourceSection = mapToSource(proxyIndex).row();
+ }
}
return d->model->headerData(sourceSection, orientation, role);
}
@@ -257,7 +337,8 @@ QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientatio
*/
QMap<int, QVariant> QAbstractProxyModel::itemData(const QModelIndex &proxyIndex) const
{
- return QAbstractItemModel::itemData(proxyIndex);
+ Q_D(const QAbstractProxyModel);
+ return d->model->itemData(mapToSource(proxyIndex));
}
/*!
@@ -283,7 +364,8 @@ bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &valu
*/
bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles)
{
- return QAbstractItemModel::setItemData(index, roles);
+ Q_D(QAbstractProxyModel);
+ return d->model->setItemData(mapToSource(index), roles);
}
/*!
@@ -382,7 +464,7 @@ QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const
{
Q_D(const QAbstractProxyModel);
QModelIndexList list;
- list.reserve(indexes.count());
+ list.reserve(indexes.size());
for (const QModelIndex &index : indexes)
list << mapToSource(index);
return d->model->mimeData(list);
@@ -474,6 +556,26 @@ QHash<int,QByteArray> QAbstractProxyModel::roleNames() const
return d->model->roleNames();
}
+/*!
+ Equivalent to calling createIndex on the source model.
+
+ This method is useful if your proxy model wants to maintain the
+ parent-child relationship of items in the source model.
+ When reimplementing mapToSource(), you can call this method to
+ create an index for row \a row and column \a col of the source model.
+
+ A typical use would be to save the internal pointer coming from the source model
+ in the proxy index when reimplementing mapFromSource() and use the same internal
+ pointer as \a internalPtr to recover the original source index when
+ reimplementing mapToSource().
+ \since 6.2
+ */
+QModelIndex QAbstractProxyModel::createSourceIndex(int row, int col, void *internalPtr) const
+{
+ if (sourceModel())
+ return sourceModel()->createIndex(row, col, internalPtr);
+ return QModelIndex();
+}
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index ef4feb5564..8652f500df 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTPROXYMODEL_H
#define QABSTRACTPROXYMODEL_H
@@ -52,7 +16,8 @@ class QItemSelection;
class Q_CORE_EXPORT QAbstractProxyModel : public QAbstractItemModel
{
Q_OBJECT
- Q_PROPERTY(QAbstractItemModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged)
+ Q_PROPERTY(QAbstractItemModel *sourceModel READ sourceModel WRITE setSourceModel
+ NOTIFY sourceModelChanged BINDABLE bindableSourceModel)
public:
explicit QAbstractProxyModel(QObject *parent = nullptr);
@@ -60,6 +25,7 @@ public:
virtual void setSourceModel(QAbstractItemModel *sourceModel);
QAbstractItemModel *sourceModel() const;
+ QBindable<QAbstractItemModel *> bindableSourceModel();
Q_INVOKABLE virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const = 0;
Q_INVOKABLE virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const = 0;
@@ -102,12 +68,19 @@ Q_SIGNALS:
void sourceModelChanged(QPrivateSignal);
protected:
+ QModelIndex createSourceIndex(int row, int col, void *internalPtr) const;
QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent);
private:
Q_DECLARE_PRIVATE(QAbstractProxyModel)
Q_DISABLE_COPY(QAbstractProxyModel)
Q_PRIVATE_SLOT(d_func(), void _q_sourceModelDestroyed())
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelRowsAboutToBeInserted(QModelIndex, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelRowsInserted(QModelIndex, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelRowsRemoved(QModelIndex, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelColumnsAboutToBeInserted(QModelIndex, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelColumnsInserted(QModelIndex, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelColumnsRemoved(QModelIndex, int, int))
};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h
index a95687c970..d33666d00b 100644
--- a/src/corelib/itemmodels/qabstractproxymodel_p.h
+++ b/src/corelib/itemmodels/qabstractproxymodel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTPROXYMODEL_P_H
#define QABSTRACTPROXYMODEL_P_H
@@ -52,7 +16,9 @@
//
//
+#include "qabstractproxymodel.h"
#include "private/qabstractitemmodel_p.h"
+#include "private/qproperty_p.h"
QT_REQUIRE_CONFIG(proxymodel);
@@ -62,11 +28,45 @@ class Q_CORE_EXPORT QAbstractProxyModelPrivate : public QAbstractItemModelPrivat
{
Q_DECLARE_PUBLIC(QAbstractProxyModel)
public:
- QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(nullptr) {}
- QAbstractItemModel *model;
+ QAbstractProxyModelPrivate()
+ : QAbstractItemModelPrivate(),
+ sourceHadZeroRows(false),
+ sourceHadZeroColumns(false),
+ updateVerticalHeader(false),
+ updateHorizontalHeader(false)
+ {}
+ void setModelForwarder(QAbstractItemModel *sourceModel)
+ {
+ q_func()->setSourceModel(sourceModel);
+ }
+ void modelChangedForwarder()
+ {
+ Q_EMIT q_func()->sourceModelChanged(QAbstractProxyModel::QPrivateSignal());
+ }
+ QAbstractItemModel *getModelForwarder() const { return q_func()->sourceModel(); }
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractProxyModelPrivate, QAbstractItemModel *, model,
+ &QAbstractProxyModelPrivate::setModelForwarder,
+ &QAbstractProxyModelPrivate::modelChangedForwarder,
+ &QAbstractProxyModelPrivate::getModelForwarder, nullptr)
virtual void _q_sourceModelDestroyed();
+ void _q_sourceModelRowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void _q_sourceModelRowsInserted(const QModelIndex &parent, int first, int last);
+ void _q_sourceModelRowsRemoved(const QModelIndex &parent, int first, int last);
+ void _q_sourceModelColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void _q_sourceModelColumnsInserted(const QModelIndex &parent, int first, int last);
+ void _q_sourceModelColumnsRemoved(const QModelIndex &parent, int first, int last);
+
void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
int *source_row, int *source_column, QModelIndex *source_parent) const;
+
+ void scheduleHeaderUpdate(Qt::Orientation orientation);
+ void emitHeaderDataChanged();
+
+ unsigned int sourceHadZeroRows : 1;
+ unsigned int sourceHadZeroColumns : 1;
+ unsigned int updateVerticalHeader : 1;
+ unsigned int updateHorizontalHeader : 1;
};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
index 05baa7eed2..3a49d37cff 100644
--- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
+++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qconcatenatetablesproxymodel.h"
#include <private/qabstractitemmodel_p.h>
#include "qsize.h"
+#include "qmap.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -61,26 +26,43 @@ public:
};
SourceModelForRowResult sourceModelForRow(int row) const;
- void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end);
- void _q_slotRowsInserted(const QModelIndex &, int start, int end);
- void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end);
- void _q_slotRowsRemoved(const QModelIndex &, int start, int end);
- void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
- void _q_slotColumnsInserted(const QModelIndex &parent, int, int);
- void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- void _q_slotColumnsRemoved(const QModelIndex &parent, int, int);
- void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles);
- void _q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
- void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
- void _q_slotModelAboutToBeReset();
- void _q_slotModelReset();
+ void slotRowsAboutToBeInserted(const QModelIndex &, int start, int end);
+ void slotRowsInserted(const QModelIndex &, int start, int end);
+ void slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end);
+ void slotRowsRemoved(const QModelIndex &, int start, int end);
+ void slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void slotColumnsInserted(const QModelIndex &parent, int, int);
+ void slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void slotColumnsRemoved(const QModelIndex &parent, int, int);
+ void slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles);
+ void slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
+ void slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
+ void slotModelAboutToBeReset();
+ void slotModelReset();
int columnCountAfterChange(const QAbstractItemModel *model, int newCount) const;
int calculatedColumnCount() const;
void updateColumnCount();
bool mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const;
- QList<QAbstractItemModel *> m_models;
+ struct ModelInfo {
+ using ConnArray = std::array<QMetaObject::Connection, 13>;
+ ModelInfo(QAbstractItemModel *m, ConnArray &&con)
+ : model(m), connections(std::move(con)) {}
+ QAbstractItemModel *model = nullptr;
+ ConnArray connections;
+ };
+ QList<ModelInfo> m_models;
+
+ QList<ModelInfo>::const_iterator findSourceModel(const QAbstractItemModel *m) const
+ {
+ auto byModelPtr = [m](const auto &modInfo) { return modInfo.model == m; };
+ return std::find_if(m_models.cbegin(), m_models.cend(), byModelPtr);
+ }
+
+ bool containsSourceModel(const QAbstractItemModel *m) const
+ { return findSourceModel(m) != m_models.cend(); }
+
int m_rowCount; // have to maintain it here since we can't compute during model destruction
int m_columnCount;
@@ -151,7 +133,7 @@ QModelIndex QConcatenateTablesProxyModel::mapFromSource(const QModelIndex &sourc
if (!sourceIndex.isValid())
return QModelIndex();
const QAbstractItemModel *sourceModel = sourceIndex.model();
- if (!d->m_models.contains(const_cast<QAbstractItemModel *>(sourceModel))) {
+ if (!d->containsSourceModel(sourceModel)) {
qWarning("QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource");
Q_ASSERT(!"QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource");
return QModelIndex();
@@ -243,7 +225,7 @@ Qt::ItemFlags QConcatenateTablesProxyModel::flags(const QModelIndex &index) cons
return Qt::NoItemFlags;
Q_ASSERT(checkIndex(index));
if (!index.isValid())
- return d->m_models.at(0)->flags(index);
+ return d->m_models.at(0).model->flags(index);
const QModelIndex sourceIndex = mapToSource(index);
Q_ASSERT(sourceIndex.isValid());
return sourceIndex.model()->flags(sourceIndex);
@@ -261,7 +243,7 @@ QVariant QConcatenateTablesProxyModel::headerData(int section, Qt::Orientation o
return QVariant();
switch (orientation) {
case Qt::Horizontal:
- return d->m_models.at(0)->headerData(section, orientation, role);
+ return d->m_models.at(0).model->headerData(section, orientation, role);
case Qt::Vertical: {
const auto result = d->sourceModelForRow(section);
Q_ASSERT(result.sourceModel);
@@ -313,8 +295,8 @@ QModelIndex QConcatenateTablesProxyModel::parent(const QModelIndex &index) const
int QConcatenateTablesProxyModel::rowCount(const QModelIndex &parent) const
{
Q_D(const QConcatenateTablesProxyModel);
- Q_ASSERT(checkIndex(parent, QAbstractItemModel::CheckIndexOption::ParentIsInvalid)); // flat model
- Q_UNUSED(parent);
+ if (parent.isValid())
+ return 0; // flat model
return d->m_rowCount;
}
@@ -327,7 +309,7 @@ QStringList QConcatenateTablesProxyModel::mimeTypes() const
Q_D(const QConcatenateTablesProxyModel);
if (d->m_models.isEmpty())
return QStringList();
- return d->m_models.at(0)->mimeTypes();
+ return d->m_models.at(0).model->mimeTypes();
}
/*!
@@ -350,7 +332,7 @@ QMimeData *QConcatenateTablesProxyModel::mimeData(const QModelIndexList &indexes
Q_ASSERT(checkIndex(firstIndex, CheckIndexOption::IndexIsValid));
const auto result = d->sourceModelForRow(firstIndex.row());
QModelIndexList sourceIndexes;
- sourceIndexes.reserve(indexes.count());
+ sourceIndexes.reserve(indexes.size());
for (const QModelIndex &index : indexes) {
const QModelIndex sourceIndex = mapToSource(index);
Q_ASSERT(sourceIndex.model() == result.sourceModel); // see documentation above
@@ -369,7 +351,7 @@ bool QConcatenateTablesProxyModelPrivate::mapDropCoordinatesToSource(int row, in
// Drop after the last item
if (row == -1 || row == m_rowCount) {
*sourceRow = -1;
- *sourceModel = m_models.constLast();
+ *sourceModel = m_models.constLast().model;
return true;
}
// Drop between toplevel items
@@ -455,7 +437,11 @@ QSize QConcatenateTablesProxyModel::span(const QModelIndex &index) const
QList<QAbstractItemModel *> QConcatenateTablesProxyModel::sourceModels() const
{
Q_D(const QConcatenateTablesProxyModel);
- return d->m_models.toList();
+ QList<QAbstractItemModel *> ret;
+ ret.reserve(d->m_models.size());
+ for (const auto &info : d->m_models)
+ ret.push_back(info.model);
+ return ret;
}
/*!
@@ -469,30 +455,42 @@ void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceMode
{
Q_D(QConcatenateTablesProxyModel);
Q_ASSERT(sourceModel);
- Q_ASSERT(!d->m_models.contains(sourceModel));
- connect(sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)), this, SLOT(_q_slotDataChanged(QModelIndex,QModelIndex,QList<int>)));
- connect(sourceModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsInserted(QModelIndex,int,int)));
- connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsRemoved(QModelIndex,int,int)));
- connect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeInserted(QModelIndex,int,int)));
- connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeRemoved(QModelIndex,int,int)));
-
- connect(sourceModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsInserted(QModelIndex,int,int)));
- connect(sourceModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsRemoved(QModelIndex,int,int)));
- connect(sourceModel, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeInserted(QModelIndex,int,int)));
- connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeRemoved(QModelIndex,int,int)));
-
- connect(sourceModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)));
- connect(sourceModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_slotSourceLayoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)));
- connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_slotModelAboutToBeReset()));
- connect(sourceModel, SIGNAL(modelReset()), this, SLOT(_q_slotModelReset()));
+ Q_ASSERT(!d->containsSourceModel(sourceModel));
const int newRows = sourceModel->rowCount();
if (newRows > 0)
beginInsertRows(QModelIndex(), d->m_rowCount, d->m_rowCount + newRows - 1);
d->m_rowCount += newRows;
- d->m_models.append(sourceModel);
+ d->m_models.emplace_back(sourceModel, std::array{
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::dataChanged,
+ d, &QConcatenateTablesProxyModelPrivate::slotDataChanged),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsInserted,
+ d, &QConcatenateTablesProxyModelPrivate::slotRowsInserted),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsRemoved,
+ d, &QConcatenateTablesProxyModelPrivate::slotRowsRemoved),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsAboutToBeInserted,
+ d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeInserted),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
+ d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeRemoved),
+
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsInserted,
+ d, &QConcatenateTablesProxyModelPrivate::slotColumnsInserted),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsRemoved,
+ d, &QConcatenateTablesProxyModelPrivate::slotColumnsRemoved),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsAboutToBeInserted,
+ d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeInserted),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsAboutToBeRemoved,
+ d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeRemoved),
+
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged,
+ d, &QConcatenateTablesProxyModelPrivate::slotSourceLayoutAboutToBeChanged),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::layoutChanged,
+ d, &QConcatenateTablesProxyModelPrivate::slotSourceLayoutChanged),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset,
+ d, &QConcatenateTablesProxyModelPrivate::slotModelAboutToBeReset),
+ QObjectPrivate::connect(sourceModel, &QAbstractItemModel::modelReset,
+ d, &QConcatenateTablesProxyModelPrivate::slotModelReset),
+ });
if (newRows > 0)
endInsertRows();
@@ -507,15 +505,18 @@ void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceMode
void QConcatenateTablesProxyModel::removeSourceModel(QAbstractItemModel *sourceModel)
{
Q_D(QConcatenateTablesProxyModel);
- Q_ASSERT(d->m_models.contains(sourceModel));
- disconnect(sourceModel, nullptr, this, nullptr);
+
+ auto it = d->findSourceModel(sourceModel);
+ Q_ASSERT(it != d->m_models.cend());
+ for (auto &c : it->connections)
+ disconnect(c);
const int rowsRemoved = sourceModel->rowCount();
const int rowsPrior = d->computeRowsPrior(sourceModel); // location of removed section
if (rowsRemoved > 0)
beginRemoveRows(QModelIndex(), rowsPrior, rowsPrior + rowsRemoved - 1);
- d->m_models.removeOne(sourceModel);
+ d->m_models.erase(it);
d->m_rowCount -= rowsRemoved;
if (rowsRemoved > 0)
endRemoveRows();
@@ -523,7 +524,8 @@ void QConcatenateTablesProxyModel::removeSourceModel(QAbstractItemModel *sourceM
d->updateColumnCount();
}
-void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeInserted(const QModelIndex &parent,
+ int start, int end)
{
Q_Q(QConcatenateTablesProxyModel);
if (parent.isValid()) // not supported, the proxy is a flat model
@@ -533,7 +535,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeInserted(const QMo
q->beginInsertRows(QModelIndex(), rowsPrior + start, rowsPrior + end);
}
-void QConcatenateTablesProxyModelPrivate::_q_slotRowsInserted(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotRowsInserted(const QModelIndex &parent, int start,
+ int end)
{
Q_Q(QConcatenateTablesProxyModel);
if (parent.isValid()) // flat model
@@ -542,7 +545,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsInserted(const QModelIndex
q->endInsertRows();
}
-void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeRemoved(const QModelIndex &parent,
+ int start, int end)
{
Q_Q(QConcatenateTablesProxyModel);
if (parent.isValid()) // flat model
@@ -552,7 +556,7 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeRemoved(const QMod
q->beginRemoveRows(QModelIndex(), rowsPrior + start, rowsPrior + end);
}
-void QConcatenateTablesProxyModelPrivate::_q_slotRowsRemoved(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotRowsRemoved(const QModelIndex &parent, int start, int end)
{
Q_Q(QConcatenateTablesProxyModel);
if (parent.isValid()) // flat model
@@ -561,7 +565,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotRowsRemoved(const QModelIndex &
q->endRemoveRows();
}
-void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeInserted(const QModelIndex &parent,
+ int start, int end)
{
Q_Q(QConcatenateTablesProxyModel);
if (parent.isValid()) // flat model
@@ -577,7 +582,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeInserted(const
m_newColumnCount = newColCount;
}
-void QConcatenateTablesProxyModelPrivate::_q_slotColumnsInserted(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotColumnsInserted(const QModelIndex &parent, int start,
+ int end)
{
Q_UNUSED(start);
Q_UNUSED(end);
@@ -590,7 +596,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsInserted(const QModelInd
}
}
-void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeRemoved(const QModelIndex &parent,
+ int start, int end)
{
Q_Q(QConcatenateTablesProxyModel);
if (parent.isValid()) // flat model
@@ -604,7 +611,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeRemoved(const Q
m_newColumnCount = newColCount;
}
-void QConcatenateTablesProxyModelPrivate::_q_slotColumnsRemoved(const QModelIndex &parent, int start, int end)
+void QConcatenateTablesProxyModelPrivate::slotColumnsRemoved(const QModelIndex &parent, int start,
+ int end)
{
Q_Q(QConcatenateTablesProxyModel);
Q_UNUSED(start);
@@ -617,19 +625,27 @@ void QConcatenateTablesProxyModelPrivate::_q_slotColumnsRemoved(const QModelInde
}
}
-void QConcatenateTablesProxyModelPrivate::_q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles)
+void QConcatenateTablesProxyModelPrivate::slotDataChanged(const QModelIndex &from,
+ const QModelIndex &to,
+ const QList<int> &roles)
{
Q_Q(QConcatenateTablesProxyModel);
Q_ASSERT(from.isValid());
Q_ASSERT(to.isValid());
+ if (from.column() >= m_columnCount)
+ return;
+ QModelIndex adjustedTo = to;
+ if (to.column() >= m_columnCount)
+ adjustedTo = to.siblingAtColumn(m_columnCount - 1);
const QModelIndex myFrom = q->mapFromSource(from);
Q_ASSERT(q->checkIndex(myFrom, QAbstractItemModel::CheckIndexOption::IndexIsValid));
- const QModelIndex myTo = q->mapFromSource(to);
+ const QModelIndex myTo = q->mapFromSource(adjustedTo);
Q_ASSERT(q->checkIndex(myTo, QAbstractItemModel::CheckIndexOption::IndexIsValid));
emit q->dataChanged(myFrom, myTo, roles);
}
-void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+void QConcatenateTablesProxyModelPrivate::slotSourceLayoutAboutToBeChanged(
+ const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QConcatenateTablesProxyModel);
@@ -651,7 +667,8 @@ void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(co
}
}
-void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+void QConcatenateTablesProxyModelPrivate::slotSourceLayoutChanged(
+ const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QConcatenateTablesProxyModel);
if (!sourceParents.isEmpty() && !sourceParents.contains(QModelIndex()))
@@ -668,20 +685,20 @@ void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutChanged(const QList
emit q->layoutChanged({}, hint);
}
-void QConcatenateTablesProxyModelPrivate::_q_slotModelAboutToBeReset()
+void QConcatenateTablesProxyModelPrivate::slotModelAboutToBeReset()
{
Q_Q(QConcatenateTablesProxyModel);
- Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender()))));
+ Q_ASSERT(containsSourceModel(static_cast<QAbstractItemModel *>(q->sender())));
q->beginResetModel();
// A reset might reduce both rowCount and columnCount, and we can't notify of both at the same time,
// and notifying of one after the other leaves an intermediary invalid situation.
// So the only safe choice is to forward it as a full reset.
}
-void QConcatenateTablesProxyModelPrivate::_q_slotModelReset()
+void QConcatenateTablesProxyModelPrivate::slotModelReset()
{
Q_Q(QConcatenateTablesProxyModel);
- Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender()))));
+ Q_ASSERT(containsSourceModel(static_cast<QAbstractItemModel *>(q->sender())));
m_columnCount = calculatedColumnCount();
m_rowCount = computeRowsPrior(nullptr);
q->endResetModel();
@@ -692,10 +709,11 @@ int QConcatenateTablesProxyModelPrivate::calculatedColumnCount() const
if (m_models.isEmpty())
return 0;
- const auto it = std::min_element(m_models.begin(), m_models.end(), [](const QAbstractItemModel* model1, const QAbstractItemModel* model2) {
- return model1->columnCount() < model2->columnCount();
- });
- return (*it)->columnCount();
+ auto byColumnCount = [](const auto &a, const auto &b) {
+ return a.model->columnCount() < b.model->columnCount();
+ };
+ const auto it = std::min_element(m_models.begin(), m_models.end(), byColumnCount);
+ return it->model->columnCount();
}
void QConcatenateTablesProxyModelPrivate::updateColumnCount()
@@ -718,8 +736,8 @@ void QConcatenateTablesProxyModelPrivate::updateColumnCount()
int QConcatenateTablesProxyModelPrivate::columnCountAfterChange(const QAbstractItemModel *model, int newCount) const
{
int newColumnCount = 0;
- for (int i = 0; i < m_models.count(); ++i) {
- const QAbstractItemModel *mod = m_models.at(i);
+ for (qsizetype i = 0; i < m_models.size(); ++i) {
+ const QAbstractItemModel *mod = m_models.at(i).model;
const int colCount = mod == model ? newCount : mod->columnCount();
if (i == 0)
newColumnCount = colCount;
@@ -732,7 +750,7 @@ int QConcatenateTablesProxyModelPrivate::columnCountAfterChange(const QAbstractI
int QConcatenateTablesProxyModelPrivate::computeRowsPrior(const QAbstractItemModel *sourceModel) const
{
int rowsPrior = 0;
- for (const QAbstractItemModel *model : m_models) {
+ for (const auto &[model, _] : m_models) {
if (model == sourceModel)
break;
rowsPrior += model->rowCount();
@@ -744,7 +762,7 @@ QConcatenateTablesProxyModelPrivate::SourceModelForRowResult QConcatenateTablesP
{
QConcatenateTablesProxyModelPrivate::SourceModelForRowResult result;
int rowCount = 0;
- for (QAbstractItemModel *model : m_models) {
+ for (const auto &[model, _] : m_models) {
const int subRowCount = model->rowCount();
if (rowCount + subRowCount > row) {
result.sourceModel = model;
diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
index a119bab098..9dbebd7b88 100644
--- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
+++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCONCATENATEROWSPROXYMODEL_H
#define QCONCATENATEROWSPROXYMODEL_H
@@ -82,21 +46,6 @@ public:
private:
Q_DECLARE_PRIVATE(QConcatenateTablesProxyModel)
Q_DISABLE_COPY(QConcatenateTablesProxyModel)
-
- Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_slotRowsInserted(const QModelIndex &, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_slotRowsRemoved(const QModelIndex &, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsInserted(const QModelIndex &parent, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsRemoved(const QModelIndex &parent, int, int))
- Q_PRIVATE_SLOT(d_func(),
- void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles))
- Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))
- Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint))
- Q_PRIVATE_SLOT(d_func(), void _q_slotModelAboutToBeReset())
- Q_PRIVATE_SLOT(d_func(), void _q_slotModelReset())
};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp
index 209626a0ee..89fa7e5c07 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.cpp
+++ b/src/corelib/itemmodels/qidentityproxymodel.cpp
@@ -1,84 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qidentityproxymodel.h"
+#include "qidentityproxymodel_p.h"
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
QT_BEGIN_NAMESPACE
-class QIdentityProxyModelPrivate : public QAbstractProxyModelPrivate
-{
- QIdentityProxyModelPrivate()
- {
-
- }
-
- Q_DECLARE_PUBLIC(QIdentityProxyModel)
-
- QList<QPersistentModelIndex> layoutChangePersistentIndexes;
- QModelIndexList proxyIndexes;
-
- void _q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
- void _q_sourceRowsInserted(const QModelIndex &parent, int start, int end);
- void _q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- void _q_sourceRowsRemoved(const QModelIndex &parent, int start, int end);
- void _q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
- void _q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
-
- void _q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
- void _q_sourceColumnsInserted(const QModelIndex &parent, int start, int end);
- void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- void _q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end);
- void _q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
- void _q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
-
- void _q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles);
- void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last);
-
- void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
- void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
- void _q_sourceModelAboutToBeReset();
- void _q_sourceModelReset();
-
-};
-
/*!
\since 4.8
\class QIdentityProxyModel
@@ -215,7 +144,7 @@ QItemSelection QIdentityProxyModel::mapSelectionFromSource(const QItemSelection&
QItemSelection::const_iterator it = selection.constBegin();
const QItemSelection::const_iterator end = selection.constEnd();
- proxySelection.reserve(selection.count());
+ proxySelection.reserve(selection.size());
for ( ; it != end; ++it) {
Q_ASSERT(it->model() == d->model);
const QItemSelectionRange range(mapFromSource(it->topLeft()), mapFromSource(it->bottomRight()));
@@ -238,7 +167,7 @@ QItemSelection QIdentityProxyModel::mapSelectionToSource(const QItemSelection& s
QItemSelection::const_iterator it = selection.constBegin();
const QItemSelection::const_iterator end = selection.constEnd();
- sourceSelection.reserve(selection.count());
+ sourceSelection.reserve(selection.size());
for ( ; it != end; ++it) {
Q_ASSERT(it->model() == this);
const QItemSelectionRange range(mapToSource(it->topLeft()), mapToSource(it->bottomRight()));
@@ -257,7 +186,7 @@ QModelIndex QIdentityProxyModel::mapToSource(const QModelIndex& proxyIndex) cons
if (!d->model || !proxyIndex.isValid())
return QModelIndex();
Q_ASSERT(proxyIndex.model() == this);
- return d->model->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
+ return createSourceIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
}
/*!
@@ -274,7 +203,7 @@ QModelIndexList QIdentityProxyModel::match(const QModelIndex& start, int role, c
QModelIndexList::const_iterator it = sourceList.constBegin();
const QModelIndexList::const_iterator end = sourceList.constEnd();
QModelIndexList proxyList;
- proxyList.reserve(sourceList.count());
+ proxyList.reserve(sourceList.size());
for ( ; it != end; ++it)
proxyList.append(mapFromSource(*it));
return proxyList;
@@ -361,97 +290,108 @@ void QIdentityProxyModel::setSourceModel(QAbstractItemModel* newSourceModel)
{
beginResetModel();
- if (sourceModel()) {
- disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- disconnect(sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
- disconnect(sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int)));
- disconnect(sourceModel(), SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- disconnect(sourceModel(), SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)));
- disconnect(sourceModel(), SIGNAL(modelAboutToBeReset()),
- this, SLOT(_q_sourceModelAboutToBeReset()));
- disconnect(sourceModel(), SIGNAL(modelReset()),
- this, SLOT(_q_sourceModelReset()));
- disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)),
- this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>)));
- disconnect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
- disconnect(sourceModel(), SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- disconnect(sourceModel(), SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- }
+ Q_D(QIdentityProxyModel);
+
+ // Call QObject::disconnect() unconditionally, if there is an existing source
+ // model, it's disconnected, and if there isn't, then calling disconnect() on
+ // a default-constructed Connection does nothing
+ for (const auto &c : d->m_sourceModelConnections)
+ QObject::disconnect(c);
QAbstractProxyModel::setSourceModel(newSourceModel);
if (sourceModel()) {
- connect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
- SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
- SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- connect(sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
- connect(sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)),
- SLOT(_q_sourceColumnsInserted(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
- SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int)));
- connect(sourceModel(), SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- connect(sourceModel(), SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)));
- connect(sourceModel(), SIGNAL(modelAboutToBeReset()),
- SLOT(_q_sourceModelAboutToBeReset()));
- connect(sourceModel(), SIGNAL(modelReset()),
- SLOT(_q_sourceModelReset()));
- connect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)),
- SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>)));
- connect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
- connect(sourceModel(), SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- connect(sourceModel(), SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ auto *m = sourceModel();
+ d->m_sourceModelConnections = {
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeInserted, d,
+ &QIdentityProxyModelPrivate::sourceRowsAboutToBeInserted),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsInserted, d,
+ &QIdentityProxyModelPrivate::sourceRowsInserted),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeRemoved, d,
+ &QIdentityProxyModelPrivate::sourceRowsAboutToBeRemoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsRemoved, d,
+ &QIdentityProxyModelPrivate::sourceRowsRemoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeMoved, d,
+ &QIdentityProxyModelPrivate::sourceRowsAboutToBeMoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsMoved, d,
+ &QIdentityProxyModelPrivate::sourceRowsMoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeInserted, d,
+ &QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsInserted, d,
+ &QIdentityProxyModelPrivate::sourceColumnsInserted),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeRemoved, d,
+ &QIdentityProxyModelPrivate::sourceColumnsAboutToBeRemoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsRemoved, d,
+ &QIdentityProxyModelPrivate::sourceColumnsRemoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeMoved, d,
+ &QIdentityProxyModelPrivate::sourceColumnsAboutToBeMoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsMoved, d,
+ &QIdentityProxyModelPrivate::sourceColumnsMoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::modelAboutToBeReset, d,
+ &QIdentityProxyModelPrivate::sourceModelAboutToBeReset),
+ QObjectPrivate::connect(m, &QAbstractItemModel::modelReset, d,
+ &QIdentityProxyModelPrivate::sourceModelReset),
+ QObjectPrivate::connect(m, &QAbstractItemModel::dataChanged, d,
+ &QIdentityProxyModelPrivate::sourceDataChanged),
+ QObjectPrivate::connect(m, &QAbstractItemModel::headerDataChanged, d,
+ &QIdentityProxyModelPrivate::sourceHeaderDataChanged),
+ };
+
+ if (d->m_handleLayoutChanges) {
+ d->m_sourceModelConnections.emplace_back(
+ QObjectPrivate::connect(m, &QAbstractItemModel::layoutAboutToBeChanged, d,
+ &QIdentityProxyModelPrivate::sourceLayoutAboutToBeChanged));
+ d->m_sourceModelConnections.emplace_back(
+ QObjectPrivate::connect(m, &QAbstractItemModel::layoutChanged, d,
+ &QIdentityProxyModelPrivate::sourceLayoutChanged));
+ }
}
endResetModel();
}
-void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+/*!
+ \since 6.7
+
+ If \a b is \c true, this proxy model will handle the source model layout
+ changes (by connecting to \c QAbstractItemModel::layoutAboutToBeChanged
+ and \c QAbstractItemModel::layoutChanged singals).
+
+ The default is for this proxy model to handle the source model layout
+ changes.
+
+ In sub-classes of QIdentityProxyModel, it may be useful to set this to
+ \c false if you need to specially handle the source model layout changes.
+
+ \note Calling this method will only have an effect after calling setSourceModel().
+*/
+void QIdentityProxyModel::setHandleSourceLayoutChanges(bool b)
+{
+ d_func()->m_handleLayoutChanges = b;
+}
+
+/*!
+ \since 6.7
+
+ Returns \c true if this proxy model handles the source model layout
+ changes, otherwise returns \c false.
+*/
+bool QIdentityProxyModel::isHandleSourceLayoutChanges() const
+{
+ return d_func()->m_handleLayoutChanges;
+}
+
+void QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
q->beginInsertColumns(q->mapFromSource(parent), start, end);
}
-void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+void QIdentityProxyModelPrivate::sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent,
+ int sourceStart, int sourceEnd,
+ const QModelIndex &destParent,
+ int dest)
{
Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
@@ -459,47 +399,51 @@ void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelInde
q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest);
}
-void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
q->beginRemoveColumns(q->mapFromSource(parent), start, end);
}
-void QIdentityProxyModelPrivate::_q_sourceColumnsInserted(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceColumnsInserted(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
- Q_UNUSED(parent)
- Q_UNUSED(start)
- Q_UNUSED(end)
+ Q_UNUSED(parent);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
q->endInsertColumns();
}
-void QIdentityProxyModelPrivate::_q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+void QIdentityProxyModelPrivate::sourceColumnsMoved(const QModelIndex &sourceParent,
+ int sourceStart, int sourceEnd,
+ const QModelIndex &destParent, int dest)
{
Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
Q_Q(QIdentityProxyModel);
- Q_UNUSED(sourceParent)
- Q_UNUSED(sourceStart)
- Q_UNUSED(sourceEnd)
- Q_UNUSED(destParent)
- Q_UNUSED(dest)
+ Q_UNUSED(sourceParent);
+ Q_UNUSED(sourceStart);
+ Q_UNUSED(sourceEnd);
+ Q_UNUSED(destParent);
+ Q_UNUSED(dest);
q->endMoveColumns();
}
-void QIdentityProxyModelPrivate::_q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceColumnsRemoved(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
- Q_UNUSED(parent)
- Q_UNUSED(start)
- Q_UNUSED(end)
+ Q_UNUSED(parent);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
q->endRemoveColumns();
}
-void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles)
+void QIdentityProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight,
+ const QList<int> &roles)
{
Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true);
Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true);
@@ -507,13 +451,15 @@ void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft
emit q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
}
-void QIdentityProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)
+void QIdentityProxyModelPrivate::sourceHeaderDataChanged(Qt::Orientation orientation, int first,
+ int last)
{
Q_Q(QIdentityProxyModel);
emit q->headerDataChanged(orientation, first, last);
}
-void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+void QIdentityProxyModelPrivate::sourceLayoutAboutToBeChanged(
+ const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QIdentityProxyModel);
@@ -541,7 +487,8 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPe
}
}
-void QIdentityProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+void QIdentityProxyModelPrivate::sourceLayoutChanged(
+ const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QIdentityProxyModel);
@@ -567,26 +514,29 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentM
emit q->layoutChanged(parents, hint);
}
-void QIdentityProxyModelPrivate::_q_sourceModelAboutToBeReset()
+void QIdentityProxyModelPrivate::sourceModelAboutToBeReset()
{
Q_Q(QIdentityProxyModel);
q->beginResetModel();
}
-void QIdentityProxyModelPrivate::_q_sourceModelReset()
+void QIdentityProxyModelPrivate::sourceModelReset()
{
Q_Q(QIdentityProxyModel);
q->endResetModel();
}
-void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start,
+ int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
q->beginInsertRows(q->mapFromSource(parent), start, end);
}
-void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+void QIdentityProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &sourceParent,
+ int sourceStart, int sourceEnd,
+ const QModelIndex &destParent, int dest)
{
Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
@@ -594,43 +544,46 @@ void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex &
q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest);
}
-void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start,
+ int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
q->beginRemoveRows(q->mapFromSource(parent), start, end);
}
-void QIdentityProxyModelPrivate::_q_sourceRowsInserted(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
- Q_UNUSED(parent)
- Q_UNUSED(start)
- Q_UNUSED(end)
+ Q_UNUSED(parent);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
q->endInsertRows();
}
-void QIdentityProxyModelPrivate::_q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+void QIdentityProxyModelPrivate::sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart,
+ int sourceEnd, const QModelIndex &destParent,
+ int dest)
{
Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
Q_Q(QIdentityProxyModel);
- Q_UNUSED(sourceParent)
- Q_UNUSED(sourceStart)
- Q_UNUSED(sourceEnd)
- Q_UNUSED(destParent)
- Q_UNUSED(dest)
+ Q_UNUSED(sourceParent);
+ Q_UNUSED(sourceStart);
+ Q_UNUSED(sourceEnd);
+ Q_UNUSED(destParent);
+ Q_UNUSED(dest);
q->endMoveRows();
}
-void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent, int start, int end)
+void QIdentityProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
{
Q_ASSERT(parent.isValid() ? parent.model() == model : true);
Q_Q(QIdentityProxyModel);
- Q_UNUSED(parent)
- Q_UNUSED(start)
- Q_UNUSED(end)
+ Q_UNUSED(parent);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
q->endRemoveRows();
}
diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h
index ce2ac68f89..c8fc9d21b7 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.h
+++ b/src/corelib/itemmodels/qidentityproxymodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIDENTITYPROXYMODEL_H
@@ -80,34 +44,15 @@ public:
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override;
+ bool isHandleSourceLayoutChanges() const;
+
protected:
QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent);
+ void setHandleSourceLayoutChanges(bool);
private:
Q_DECLARE_PRIVATE(QIdentityProxyModel)
Q_DISABLE_COPY(QIdentityProxyModel)
-
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))
-
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))
-
- Q_PRIVATE_SLOT(d_func(), void _q_sourceDataChanged(QModelIndex, QModelIndex, QList<int>))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last))
-
- Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceModelAboutToBeReset())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceModelReset())
};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qidentityproxymodel_p.h b/src/corelib/itemmodels/qidentityproxymodel_p.h
new file mode 100644
index 0000000000..78e1f5316c
--- /dev/null
+++ b/src/corelib/itemmodels/qidentityproxymodel_p.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QIDENTITYPROXYMODEL_P_H
+#define QIDENTITYPROXYMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QAbstractItemModel*. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include <QtCore/private/qabstractproxymodel_p.h>
+#include <QtCore/qidentityproxymodel.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QIdentityProxyModelPrivate : public QAbstractProxyModelPrivate
+{
+ Q_DECLARE_PUBLIC(QIdentityProxyModel)
+
+public:
+ QIdentityProxyModelPrivate()
+ {
+ }
+
+ QList<QPersistentModelIndex> layoutChangePersistentIndexes;
+ QModelIndexList proxyIndexes;
+
+ void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void sourceRowsInserted(const QModelIndex &parent, int start, int end);
+ void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
+ void sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
+ const QModelIndex &destParent, int dest);
+ void sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
+ const QModelIndex &destParent, int dest);
+
+ void sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void sourceColumnsInserted(const QModelIndex &parent, int start, int end);
+ void sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void sourceColumnsRemoved(const QModelIndex &parent, int start, int end);
+ void sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart,
+ int sourceEnd, const QModelIndex &destParent, int dest);
+ void sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
+ const QModelIndex &destParent, int dest);
+
+ void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
+ const QList<int> &roles);
+ void sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last);
+
+ void sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents,
+ QAbstractItemModel::LayoutChangeHint hint);
+ void sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents,
+ QAbstractItemModel::LayoutChangeHint hint);
+ void sourceModelAboutToBeReset();
+ void sourceModelReset();
+
+private:
+ bool m_handleLayoutChanges = true;
+ QVarLengthArray<QMetaObject::Connection, 18> m_sourceModelConnections;
+};
+
+QT_END_NAMESPACE
+
+#endif // QIDENTITYPROXYMODEL_P_H
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index 5eed378f9e..6df60aaf61 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -1,45 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qitemselectionmodel.h"
+#include "qitemselectionmodel_p.h"
+
#include <private/qitemselectionmodel_p.h>
+#include <private/qabstractitemmodel_p.h>
#include <private/qduplicatetracker_p.h>
+#include <private/qoffsetstringarray_p.h>
#include <qdebug.h>
#include <algorithm>
@@ -47,6 +15,9 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QItemSelectionRange)
+QT_IMPL_METATYPE_EXTERN(QItemSelection)
+
/*!
\class QItemSelectionRange
\inmodule QtCore
@@ -56,6 +27,8 @@ QT_BEGIN_NAMESPACE
\ingroup model-view
+ \compares equality
+
A QItemSelectionRange contains information about a range of
selected items in a model. A range of items is a contiguous array
of model items, extending to cover a number of adjacent rows and
@@ -245,68 +218,29 @@ QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &
}
/*!
- \fn bool QItemSelectionRange::operator==(const QItemSelectionRange &other) const
+ \fn bool QItemSelectionRange::operator==(const QItemSelectionRange &lhs, const QItemSelectionRange &rhs)
- Returns \c true if the selection range is exactly the same as the \a other
+ Returns \c true if \a lhs selection range is exactly the same as the \a rhs
range given; otherwise returns \c false.
*/
/*!
- \fn bool QItemSelectionRange::operator!=(const QItemSelectionRange &other) const
+ \fn bool QItemSelectionRange::operator!=(const QItemSelectionRange &lhs, const QItemSelectionRange &rhs)
- Returns \c true if the selection range differs from the \a other range given;
+ Returns \c true if \a lhs selection range differs from the \a rhs range given;
otherwise returns \c false.
*/
/*!
- Returns \c true if the selection range is less than the \a other
- range given; otherwise returns \c false.
-
- The less than calculation is not directly useful to developers - the way that ranges
- with different parents compare is not defined. This operator only exists so that the
- class can be used with QMap.
-
-*/
-bool QItemSelectionRange::operator<(const QItemSelectionRange &other) const
-{
- // ### Qt 6: This is inconsistent with op== and needs to be fixed, nay,
- // ### removed, but cannot, because it was inline up to and including 5.9
-
- // Comparing parents will compare the models, but if two equivalent ranges
- // in two different models have invalid parents, they would appear the same
- if (other.tl.model() == tl.model()) {
- // parent has to be calculated, so we only do so once.
- const QModelIndex topLeftParent = tl.parent();
- const QModelIndex otherTopLeftParent = other.tl.parent();
- if (topLeftParent == otherTopLeftParent) {
- if (other.tl.row() == tl.row()) {
- if (other.tl.column() == tl.column()) {
- if (other.br.row() == br.row()) {
- return br.column() < other.br.column();
- }
- return br.row() < other.br.row();
- }
- return tl.column() < other.tl.column();
- }
- return tl.row() < other.tl.row();
- }
- return topLeftParent < otherTopLeftParent;
- }
-
- std::less<const QAbstractItemModel *> less;
- return less(tl.model(), other.tl.model());
-}
-
-/*!
\fn bool QItemSelectionRange::isValid() const
Returns \c true if the selection range is valid; otherwise returns \c false.
*/
-static void rowLengthsFromRange(const QItemSelectionRange &range, QList<QPair<QPersistentModelIndex, uint>> &result)
+static void rowLengthsFromRange(const QItemSelectionRange &range, QList<std::pair<QPersistentModelIndex, uint>> &result)
{
if (range.isValid() && range.model()) {
const QModelIndex topLeft = range.topLeft();
@@ -317,11 +251,16 @@ static void rowLengthsFromRange(const QItemSelectionRange &range, QList<QPair<QP
// We don't need to keep track of ItemIsSelectable and ItemIsEnabled here. That is
// required in indexesFromRange() because that method is called from public API
// which requires the limitation.
- result.push_back(qMakePair(QPersistentModelIndex(topLeft.sibling(row, column)), width));
+ result.emplace_back(topLeft.sibling(row, column), width);
}
}
}
+static bool isSelectableAndEnabled(Qt::ItemFlags flags)
+{
+ return flags.testFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+}
+
template<typename ModelIndexContainer>
static void indexesFromRange(const QItemSelectionRange &range, ModelIndexContainer &result)
{
@@ -333,8 +272,7 @@ static void indexesFromRange(const QItemSelectionRange &range, ModelIndexContain
const QModelIndex columnLeader = topLeft.sibling(row, topLeft.column());
for (int column = topLeft.column(); column <= right; ++column) {
QModelIndex index = columnLeader.sibling(row, column);
- Qt::ItemFlags flags = range.model()->flags(index);
- if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
+ if (isSelectableAndEnabled(range.model()->flags(index)))
result.push_back(index);
}
}
@@ -351,7 +289,9 @@ static ModelIndexContainer qSelectionIndexes(const QItemSelection &selection)
}
/*!
- Returns \c true if the selection range contains no selectable item
+ Returns \c true if the selection range contains either no items
+ or only items which are either disabled or marked as not selectable.
+
\since 4.7
*/
@@ -363,8 +303,7 @@ bool QItemSelectionRange::isEmpty() const
for (int column = left(); column <= right(); ++column) {
for (int row = top(); row <= bottom(); ++row) {
QModelIndex index = model()->index(row, column, parent());
- Qt::ItemFlags flags = model()->flags(index);
- if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
+ if (isSelectableAndEnabled(model()->flags(index)))
return false;
}
}
@@ -477,7 +416,7 @@ void QItemSelection::select(const QModelIndex &topLeft, const QModelIndex &botto
bool QItemSelection::contains(const QModelIndex &index) const
{
- if (index.flags() & Qt::ItemIsSelectable) {
+ if (isSelectableAndEnabled(index.flags())) {
QList<QItemSelectionRange>::const_iterator it = begin();
for (; it != end(); ++it)
if ((*it).contains(index))
@@ -495,9 +434,9 @@ QModelIndexList QItemSelection::indexes() const
return qSelectionIndexes<QModelIndexList>(*this);
}
-static QList<QPair<QPersistentModelIndex, uint>> qSelectionPersistentRowLengths(const QItemSelection &sel)
+static QList<std::pair<QPersistentModelIndex, uint>> qSelectionPersistentRowLengths(const QItemSelection &sel)
{
- QList<QPair<QPersistentModelIndex, uint>> result;
+ QList<std::pair<QPersistentModelIndex, uint>> result;
for (const QItemSelectionRange &range : sel)
rowLengthsFromRange(range, result);
return result;
@@ -521,25 +460,23 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel
command & QItemSelectionModel::Toggle))
return;
- QItemSelection newSelection = other;
+ QItemSelection newSelection;
+ newSelection.reserve(other.size());
// Collect intersections
QItemSelection intersections;
- QItemSelection::iterator it = newSelection.begin();
- while (it != newSelection.end()) {
- if (!(*it).isValid()) {
- it = newSelection.erase(it);
+ for (const auto &range : other) {
+ if (!range.isValid())
continue;
+ newSelection.push_back(range);
+ for (int t = 0; t < size(); ++t) {
+ if (range.intersects(at(t)))
+ intersections.append(at(t).intersected(range));
}
- for (int t = 0; t < count(); ++t) {
- if ((*it).intersects(at(t)))
- intersections.append(at(t).intersected(*it));
- }
- ++it;
}
// Split the old (and new) ranges using the intersections
- for (int i = 0; i < intersections.count(); ++i) { // for each intersection
- for (int t = 0; t < count();) { // splitt each old range
+ for (int i = 0; i < intersections.size(); ++i) { // for each intersection
+ for (int t = 0; t < size();) { // splitt each old range
if (at(t).intersects(intersections.at(i))) {
split(at(t), intersections.at(i), this);
removeAt(t);
@@ -548,7 +485,7 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel
}
}
// only split newSelection if Toggle is specified
- for (int n = 0; (command & QItemSelectionModel::Toggle) && n < newSelection.count();) {
+ for (int n = 0; (command & QItemSelectionModel::Toggle) && n < newSelection.size();) {
if (newSelection.at(n).intersects(intersections.at(i))) {
split(newSelection.at(n), intersections.at(i), &newSelection);
newSelection.removeAt(n);
@@ -615,52 +552,55 @@ void QItemSelection::split(const QItemSelectionRange &range,
void QItemSelectionModelPrivate::initModel(QAbstractItemModel *m)
{
- struct Cx {
- const char *signal;
- const char *slot;
- };
- static const Cx connections[] = {
- { SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)) },
- { SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)) },
- { SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)) },
- { SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)) },
- { SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_layoutAboutToBeChanged()) },
- { SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_layoutAboutToBeChanged()) },
- { SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_layoutChanged()) },
- { SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- SLOT(_q_layoutChanged()) },
- { SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)) },
- { SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)) },
- { SIGNAL(modelReset()),
- SLOT(reset()) },
- { nullptr, nullptr }
- };
-
- if (model == m)
+ Q_Q(QItemSelectionModel);
+ const QAbstractItemModel *oldModel = model.valueBypassingBindings();
+ if (oldModel == m)
return;
- Q_Q(QItemSelectionModel);
- if (model) {
- for (const Cx *cx = &connections[0]; cx->signal; cx++)
- QObject::disconnect(model, cx->signal, q, cx->slot);
+ if (oldModel) {
q->reset();
+ disconnectModel();
}
- model = m;
- if (model) {
- for (const Cx *cx = &connections[0]; cx->signal; cx++)
- QObject::connect(model, cx->signal, q, cx->slot);
+
+ // Caller has to call notify(), unless calling during construction (the common case).
+ model.setValueBypassingBindings(m);
+
+ if (m) {
+ connections = std::array<QMetaObject::Connection, 12> {
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeRemoved,
+ this, &QItemSelectionModelPrivate::rowsAboutToBeRemoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeRemoved,
+ this, &QItemSelectionModelPrivate::columnsAboutToBeRemoved),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeInserted,
+ this, &QItemSelectionModelPrivate::rowsAboutToBeInserted),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeInserted,
+ this, &QItemSelectionModelPrivate::columnsAboutToBeInserted),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeMoved,
+ this, &QItemSelectionModelPrivate::triggerLayoutToBeChanged),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeMoved,
+ this, &QItemSelectionModelPrivate::triggerLayoutToBeChanged),
+ QObjectPrivate::connect(m, &QAbstractItemModel::rowsMoved,
+ this, &QItemSelectionModelPrivate::triggerLayoutChanged),
+ QObjectPrivate::connect(m, &QAbstractItemModel::columnsMoved,
+ this, &QItemSelectionModelPrivate::triggerLayoutChanged),
+ QObjectPrivate::connect(m, &QAbstractItemModel::layoutAboutToBeChanged,
+ this, &QItemSelectionModelPrivate::layoutAboutToBeChanged),
+ QObjectPrivate::connect(m, &QAbstractItemModel::layoutChanged,
+ this, &QItemSelectionModelPrivate::layoutChanged),
+ QObject::connect(m, &QAbstractItemModel::modelReset,
+ q, &QItemSelectionModel::reset),
+ QObjectPrivate::connect(m, &QAbstractItemModel::destroyed,
+ this, &QItemSelectionModelPrivate::modelDestroyed)
+ };
}
}
+void QItemSelectionModelPrivate::disconnectModel()
+{
+ for (auto &connection : connections)
+ QObject::disconnect(connection);
+}
+
/*!
\internal
@@ -678,7 +618,7 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection
QItemSelection expanded;
if (command & QItemSelectionModel::Rows) {
- for (int i = 0; i < selection.count(); ++i) {
+ for (int i = 0; i < selection.size(); ++i) {
QModelIndex parent = selection.at(i).parent();
int colCount = model->columnCount(parent);
QModelIndex tl = model->index(selection.at(i).top(), 0, parent);
@@ -688,7 +628,7 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection
}
}
if (command & QItemSelectionModel::Columns) {
- for (int i = 0; i < selection.count(); ++i) {
+ for (int i = 0; i < selection.size(); ++i) {
QModelIndex parent = selection.at(i).parent();
int rowCount = model->rowCount(parent);
QModelIndex tl = model->index(0, selection.at(i).left(), parent);
@@ -703,22 +643,27 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection
/*!
\internal
*/
-void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent,
+void QItemSelectionModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent,
int start, int end)
{
Q_Q(QItemSelectionModel);
+ Q_ASSERT(start <= end);
finalize();
// update current index
if (currentIndex.isValid() && parent == currentIndex.parent()
&& currentIndex.row() >= start && currentIndex.row() <= end) {
QModelIndex old = currentIndex;
- if (start > 0) // there are rows left above the change
+ if (start > 0) {
+ // there are rows left above the change
currentIndex = model->index(start - 1, old.column(), parent);
- else if (model && end < model->rowCount(parent) - 1) // there are rows left below the change
+ } else if (model.value() && end < model->rowCount(parent) - 1) {
+ // there are rows left below the change
currentIndex = model->index(end + 1, old.column(), parent);
- else // there are no rows left in the table
+ } else {
+ // there are no rows left in the table
currentIndex = QModelIndex();
+ }
emit q->currentChanged(currentIndex, old);
emit q->currentRowChanged(currentIndex, old);
if (currentIndex.column() != old.column())
@@ -727,6 +672,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
QItemSelection deselected;
QItemSelection newParts;
+ bool indexesOfSelectionChanged = false;
QItemSelection::iterator it = ranges.begin();
while (it != ranges.end()) {
if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range
@@ -738,6 +684,8 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
deselected.append(*it);
it = ranges.erase(it);
} else {
+ if (itParent.isValid() && end < itParent.row())
+ indexesOfSelectionChanged = true;
++it;
}
} else if (start <= it->bottom() && it->bottom() <= end // Full inclusion
@@ -762,19 +710,23 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
deselected.append(removedRange);
QItemSelection::split(*it, removedRange, &newParts);
it = ranges.erase(it);
- } else
+ } else if (end < it->top()) { // deleted row before selection
+ indexesOfSelectionChanged = true;
+ ++it;
+ } else {
++it;
+ }
}
ranges.append(newParts);
- if (!deselected.isEmpty())
+ if (!deselected.isEmpty() || indexesOfSelectionChanged)
emit q->selectionChanged(QItemSelection(), deselected);
}
/*!
\internal
*/
-void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent,
+void QItemSelectionModelPrivate::columnsAboutToBeRemoved(const QModelIndex &parent,
int start, int end)
{
Q_Q(QItemSelectionModel);
@@ -783,12 +735,16 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &p
if (currentIndex.isValid() && parent == currentIndex.parent()
&& currentIndex.column() >= start && currentIndex.column() <= end) {
QModelIndex old = currentIndex;
- if (start > 0) // there are columns to the left of the change
+ if (start > 0) {
+ // there are columns to the left of the change
currentIndex = model->index(old.row(), start - 1, parent);
- else if (model && end < model->columnCount() - 1) // there are columns to the right of the change
+ } else if (model.value() && end < model->columnCount() - 1) {
+ // there are columns to the right of the change
currentIndex = model->index(old.row(), end + 1, parent);
- else // there are no columns left in the table
+ } else {
+ // there are no columns left in the table
currentIndex = QModelIndex();
+ }
emit q->currentChanged(currentIndex, old);
if (currentIndex.row() != old.row())
emit q->currentRowChanged(currentIndex, old);
@@ -807,7 +763,7 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &p
Split selection ranges if columns are about to be inserted in the middle.
*/
-void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &parent,
+void QItemSelectionModelPrivate::columnsAboutToBeInserted(const QModelIndex &parent,
int start, int end)
{
Q_UNUSED(end);
@@ -815,11 +771,12 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &
QList<QItemSelectionRange> split;
QList<QItemSelectionRange>::iterator it = ranges.begin();
for (; it != ranges.end(); ) {
- if ((*it).isValid() && (*it).parent() == parent
+ const QModelIndex &itParent = it->parent();
+ if ((*it).isValid() && itParent == parent
&& (*it).left() < start && (*it).right() >= start) {
- QModelIndex bottomMiddle = model->index((*it).bottom(), start - 1, (*it).parent());
+ QModelIndex bottomMiddle = model->index((*it).bottom(), start - 1, itParent);
QItemSelectionRange left((*it).topLeft(), bottomMiddle);
- QModelIndex topMiddle = model->index((*it).top(), start, (*it).parent());
+ QModelIndex topMiddle = model->index((*it).top(), start, itParent);
QItemSelectionRange right(topMiddle, (*it).bottomRight());
it = ranges.erase(it);
split.append(left);
@@ -836,28 +793,38 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &
Split selection ranges if rows are about to be inserted in the middle.
*/
-void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &parent,
+void QItemSelectionModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent,
int start, int end)
{
+ Q_Q(QItemSelectionModel);
Q_UNUSED(end);
finalize();
QList<QItemSelectionRange> split;
QList<QItemSelectionRange>::iterator it = ranges.begin();
+ bool indexesOfSelectionChanged = false;
for (; it != ranges.end(); ) {
- if ((*it).isValid() && (*it).parent() == parent
+ const QModelIndex &itParent = it->parent();
+ if ((*it).isValid() && itParent == parent
&& (*it).top() < start && (*it).bottom() >= start) {
- QModelIndex middleRight = model->index(start - 1, (*it).right(), (*it).parent());
+ QModelIndex middleRight = model->index(start - 1, (*it).right(), itParent);
QItemSelectionRange top((*it).topLeft(), middleRight);
- QModelIndex middleLeft = model->index(start, (*it).left(), (*it).parent());
+ QModelIndex middleLeft = model->index(start, (*it).left(), itParent);
QItemSelectionRange bottom(middleLeft, (*it).bottomRight());
it = ranges.erase(it);
split.append(top);
split.append(bottom);
+ } else if ((*it).isValid() && itParent == parent // insertion before selection
+ && (*it).top() >= start) {
+ indexesOfSelectionChanged = true;
+ ++it;
} else {
++it;
}
}
ranges += split;
+
+ if (indexesOfSelectionChanged)
+ emit q->selectionChanged(QItemSelection(), QItemSelection());
}
/*!
@@ -867,7 +834,8 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &par
preparation for the layoutChanged() signal, where the indexes can be
merged again.
*/
-void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
+void QItemSelectionModelPrivate::layoutAboutToBeChanged(const QList<QPersistentModelIndex> &,
+ QAbstractItemModel::LayoutChangeHint hint)
{
savedPersistentIndexes.clear();
savedPersistentCurrentIndexes.clear();
@@ -876,7 +844,7 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersiste
// optimization for when all indexes are selected
// (only if there is lots of items (1000) because this is not entirely correct)
- if (ranges.isEmpty() && currentSelection.count() == 1) {
+ if (ranges.isEmpty() && currentSelection.size() == 1) {
QItemSelectionRange range = currentSelection.constFirst();
QModelIndex parent = range.parent();
tableRowCount = model->rowCount(parent);
@@ -909,14 +877,14 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersiste
/*!
\internal
*/
-static QItemSelection mergeRowLengths(const QList<QPair<QPersistentModelIndex, uint>> &rowLengths)
+static QItemSelection mergeRowLengths(const QList<std::pair<QPersistentModelIndex, uint>> &rowLengths)
{
if (rowLengths.isEmpty())
return QItemSelection();
QItemSelection result;
int i = 0;
- while (i < rowLengths.count()) {
+ while (i < rowLengths.size()) {
const QPersistentModelIndex &tl = rowLengths.at(i).first;
if (!tl.isValid()) {
++i;
@@ -924,7 +892,7 @@ static QItemSelection mergeRowLengths(const QList<QPair<QPersistentModelIndex, u
}
QPersistentModelIndex br = tl;
const uint length = rowLengths.at(i).second;
- while (++i < rowLengths.count()) {
+ while (++i < rowLengths.size()) {
const QPersistentModelIndex &next = rowLengths.at(i).first;
if (!next.isValid())
continue;
@@ -954,7 +922,7 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
QItemSelection colSpans;
// merge columns
int i = 0;
- while (i < indexes.count()) {
+ while (i < indexes.size()) {
const QPersistentModelIndex &tl = indexes.at(i);
if (!tl.isValid()) {
++i;
@@ -964,7 +932,7 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
QModelIndex brParent = br.parent();
int brRow = br.row();
int brColumn = br.column();
- while (++i < indexes.count()) {
+ while (++i < indexes.size()) {
const QPersistentModelIndex &next = indexes.at(i);
if (!next.isValid())
continue;
@@ -987,11 +955,11 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
// merge rows
QItemSelection rowSpans;
i = 0;
- while (i < colSpans.count()) {
+ while (i < colSpans.size()) {
QModelIndex tl = colSpans.at(i).topLeft();
QModelIndex br = colSpans.at(i).bottomRight();
QModelIndex prevTl = tl;
- while (++i < colSpans.count()) {
+ while (++i < colSpans.size()) {
QModelIndex nextTl = colSpans.at(i).topLeft();
QModelIndex nextBr = colSpans.at(i).bottomRight();
@@ -1014,7 +982,7 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
/*!
\internal
- Sort predicate function for QItemSelectionModelPrivate::_q_layoutChanged(),
+ Sort predicate function for QItemSelectionModelPrivate::layoutChanged(),
sorting by parent first in addition to operator<(). This is to prevent
fragmentation of the selection by grouping indexes with the same row, column
of different parents next to each other, which may happen when a selection
@@ -1032,7 +1000,7 @@ static bool qt_PersistentModelIndexLessThan(const QPersistentModelIndex &i1, con
Merge the selected indexes into selection ranges again.
*/
-void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
+void QItemSelectionModelPrivate::layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
{
// special case for when all indexes are selected
if (tableSelected && tableColCount == model->columnCount(tableParent)
@@ -1090,6 +1058,40 @@ void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIn
}
/*!
+ \internal
+
+ Called when the used model gets destroyed.
+
+ It is impossible to have a correct implementation here.
+ In the following situation, there are two contradicting rules:
+
+ \code
+ QProperty<QAbstractItemModel *> leader(mymodel);
+ QItemSelectionModel myItemSelectionModel;
+ myItemSelectionModel.bindableModel().setBinding([&](){ return leader.value(); }
+ delete mymodel;
+ QAbstractItemModel *returnedModel = myItemSelectionModel.model();
+ \endcode
+
+ What should returnedModel be in this situation?
+
+ Rules for bindable properties say that myItemSelectionModel.model()
+ should return the same as leader.value(), namely the pointer to the now deleted model.
+
+ However, backward compatibility requires myItemSelectionModel.model() to return a
+ nullptr, because that was done in the past after the model used was deleted.
+
+ We decide to break the new rule, imposed by bindable properties, and not break the old
+ rule, because that may break existing code.
+*/
+void QItemSelectionModelPrivate::modelDestroyed()
+{
+ model.setValueBypassingBindings(nullptr);
+ disconnectModel();
+ model.notify();
+}
+
+/*!
\class QItemSelectionModel
\inmodule QtCore
@@ -1125,7 +1127,7 @@ void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIn
\l{QItemSelectionModel::hasSelection()}{hasSelection}, and
\l{QItemSelectionModel::currentIndex()}{currentIndex} are meta-object properties.
- \sa {Model/View Programming}, QAbstractItemModel, {Chart Example}
+ \sa {Model/View Programming}, QAbstractItemModel
*/
/*!
@@ -1218,6 +1220,11 @@ void QItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::
Note the that the current index changes independently from the selection.
Also note that this signal will not be emitted when the item model is reset.
+ Items which stay selected but change their index are not included in
+ \a selected and \a deselected. Thus, this signal might be emitted with both
+ \a selected and \a deselected empty, if only the indices of selected items
+ change.
+
\sa select(), currentChanged()
*/
@@ -1259,10 +1266,10 @@ struct IsNotValid {
typedef bool result_type;
struct is_transparent : std::true_type {};
template <typename T>
- Q_DECL_CONSTEXPR bool operator()(T &t) const noexcept(noexcept(t.isValid()))
+ constexpr bool operator()(T &t) const noexcept(noexcept(t.isValid()))
{ return !t.isValid(); }
template <typename T>
- Q_DECL_CONSTEXPR bool operator()(T *t) const noexcept(noexcept(t->isValid()))
+ constexpr bool operator()(T *t) const noexcept(noexcept(t->isValid()))
{ return !t->isValid(); }
};
}
@@ -1277,7 +1284,7 @@ struct IsNotValid {
void QItemSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
{
Q_D(QItemSelectionModel);
- if (!d->model) {
+ if (!d->model.value()) {
qWarning("QItemSelectionModel: Selecting when no model has been set will result in a no-op.");
return;
}
@@ -1289,11 +1296,9 @@ void QItemSelectionModel::select(const QItemSelection &selection, QItemSelection
// If d->ranges is non-empty when the source model is reset the persistent indexes
// it contains will be invalid. We can't clear them in a modelReset slot because that might already
// be too late if another model observer is connected to the same modelReset slot and is invoked first
- // it might call select() on this selection model before any such QItemSelectionModelPrivate::_q_modelReset() slot
+ // it might call select() on this selection model before any such QItemSelectionModelPrivate::modelReset() slot
// is invoked, so it would not be cleared yet. We clear it invalid ranges in it here.
- using namespace QtFunctionObjects;
- d->ranges.erase(std::remove_if(d->ranges.begin(), d->ranges.end(), IsNotValid()),
- d->ranges.end());
+ d->ranges.removeIf(QtFunctionObjects::IsNotValid());
QItemSelection old = d->ranges;
old.merge(d->currentSelection, d->currentCommand);
@@ -1364,7 +1369,7 @@ void QItemSelectionModel::reset()
void QItemSelectionModel::clearSelection()
{
Q_D(QItemSelectionModel);
- if (d->ranges.count() == 0 && d->currentSelection.count() == 0)
+ if (d->ranges.size() == 0 && d->currentSelection.size() == 0)
return;
select(QItemSelection(), Clear);
@@ -1384,7 +1389,7 @@ void QItemSelectionModel::clearSelection()
void QItemSelectionModel::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
{
Q_D(QItemSelectionModel);
- if (!d->model) {
+ if (!d->model.value()) {
qWarning("QItemSelectionModel: Setting the current index when no model has been set will result in a no-op.");
return;
}
@@ -1435,7 +1440,7 @@ bool QItemSelectionModel::isSelected(const QModelIndex &index) const
}
// check currentSelection
- if (d->currentSelection.count()) {
+ if (d->currentSelection.size()) {
if ((d->currentCommand & Deselect) && selected)
selected = !d->currentSelection.contains(index);
else if (d->currentCommand & Toggle)
@@ -1444,10 +1449,8 @@ bool QItemSelectionModel::isSelected(const QModelIndex &index) const
selected = d->currentSelection.contains(index);
}
- if (selected) {
- Qt::ItemFlags flags = d->model->flags(index);
- return (flags & Qt::ItemIsSelectable);
- }
+ if (selected)
+ return isSelectableAndEnabled(d->model->flags(index));
return false;
}
@@ -1466,14 +1469,14 @@ bool QItemSelectionModel::isSelected(const QModelIndex &index) const
bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) const
{
Q_D(const QItemSelectionModel);
- if (!d->model)
+ if (!d->model.value())
return false;
if (parent.isValid() && d->model != parent.model())
return false;
// return false if row exist in currentSelection (Deselect)
- if (d->currentCommand & Deselect && d->currentSelection.count()) {
- for (int i=0; i<d->currentSelection.count(); ++i) {
+ if (d->currentCommand & Deselect && d->currentSelection.size()) {
+ for (int i=0; i<d->currentSelection.size(); ++i) {
if (d->currentSelection.at(i).parent() == parent &&
row >= d->currentSelection.at(i).top() &&
row <= d->currentSelection.at(i).bottom())
@@ -1482,19 +1485,18 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons
}
// return false if ranges in both currentSelection and ranges
// intersect and have the same row contained
- if (d->currentCommand & Toggle && d->currentSelection.count()) {
- for (int i=0; i<d->currentSelection.count(); ++i)
+ if (d->currentCommand & Toggle && d->currentSelection.size()) {
+ for (int i=0; i<d->currentSelection.size(); ++i)
if (d->currentSelection.at(i).top() <= row &&
d->currentSelection.at(i).bottom() >= row)
- for (int j=0; j<d->ranges.count(); ++j)
+ for (int j=0; j<d->ranges.size(); ++j)
if (d->ranges.at(j).top() <= row && d->ranges.at(j).bottom() >= row
&& d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid())
return false;
}
auto isSelectable = [&](int row, int column) {
- Qt::ItemFlags flags = d->model->index(row, column, parent).flags();
- return (flags & Qt::ItemIsSelectable);
+ return isSelectableAndEnabled(d->model->index(row, column, parent).flags());
};
const int colCount = d->model->columnCount(parent);
@@ -1502,7 +1504,7 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons
// add ranges and currentSelection and check through them all
QList<QItemSelectionRange>::const_iterator it;
QList<QItemSelectionRange> joined = d->ranges;
- if (d->currentSelection.count())
+ if (d->currentSelection.size())
joined += d->currentSelection;
for (int column = 0; column < colCount; ++column) {
if (!isSelectable(row, column)) {
@@ -1541,14 +1543,14 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons
bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent) const
{
Q_D(const QItemSelectionModel);
- if (!d->model)
+ if (!d->model.value())
return false;
if (parent.isValid() && d->model != parent.model())
return false;
// return false if column exist in currentSelection (Deselect)
- if (d->currentCommand & Deselect && d->currentSelection.count()) {
- for (int i = 0; i < d->currentSelection.count(); ++i) {
+ if (d->currentCommand & Deselect && d->currentSelection.size()) {
+ for (int i = 0; i < d->currentSelection.size(); ++i) {
if (d->currentSelection.at(i).parent() == parent &&
column >= d->currentSelection.at(i).left() &&
column <= d->currentSelection.at(i).right())
@@ -1557,11 +1559,11 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent
}
// return false if ranges in both currentSelection and the selection model
// intersect and have the same column contained
- if (d->currentCommand & Toggle && d->currentSelection.count()) {
- for (int i = 0; i < d->currentSelection.count(); ++i) {
+ if (d->currentCommand & Toggle && d->currentSelection.size()) {
+ for (int i = 0; i < d->currentSelection.size(); ++i) {
if (d->currentSelection.at(i).left() <= column &&
d->currentSelection.at(i).right() >= column) {
- for (int j = 0; j < d->ranges.count(); ++j) {
+ for (int j = 0; j < d->ranges.size(); ++j) {
if (d->ranges.at(j).left() <= column && d->ranges.at(j).right() >= column
&& d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid()) {
return false;
@@ -1572,8 +1574,7 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent
}
auto isSelectable = [&](int row, int column) {
- Qt::ItemFlags flags = d->model->index(row, column, parent).flags();
- return (flags & Qt::ItemIsSelectable);
+ return isSelectableAndEnabled(d->model->index(row, column, parent).flags());
};
const int rowCount = d->model->rowCount(parent);
int unselectable = 0;
@@ -1581,7 +1582,7 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent
// add ranges and currentSelection and check through them all
QList<QItemSelectionRange>::const_iterator it;
QList<QItemSelectionRange> joined = d->ranges;
- if (d->currentSelection.count())
+ if (d->currentSelection.size())
joined += d->currentSelection;
for (int row = 0; row < rowCount; ++row) {
if (!isSelectable(row, column)) {
@@ -1615,14 +1616,14 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent
bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &parent) const
{
Q_D(const QItemSelectionModel);
- if (!d->model)
+ if (!d->model.value())
return false;
if (parent.isValid() && d->model != parent.model())
return false;
QItemSelection sel = d->ranges;
sel.merge(d->currentSelection, d->currentCommand);
- for (const QItemSelectionRange &range : qAsConst(sel)) {
+ for (const QItemSelectionRange &range : std::as_const(sel)) {
if (range.parent() != parent)
return false;
int top = range.top();
@@ -1631,8 +1632,7 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par
int right = range.right();
if (top <= row && bottom >= row) {
for (int j = left; j <= right; j++) {
- const Qt::ItemFlags flags = d->model->index(row, j, parent).flags();
- if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
+ if (isSelectableAndEnabled(d->model->index(row, j, parent).flags()))
return true;
}
}
@@ -1651,14 +1651,14 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par
bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelIndex &parent) const
{
Q_D(const QItemSelectionModel);
- if (!d->model)
+ if (!d->model.value())
return false;
if (parent.isValid() && d->model != parent.model())
return false;
QItemSelection sel = d->ranges;
sel.merge(d->currentSelection, d->currentCommand);
- for (const QItemSelectionRange &range : qAsConst(sel)) {
+ for (const QItemSelectionRange &range : std::as_const(sel)) {
if (range.parent() != parent)
return false;
int top = range.top();
@@ -1667,8 +1667,7 @@ bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelInde
int right = range.right();
if (left <= column && right >= column) {
for (int j = top; j <= bottom; j++) {
- const Qt::ItemFlags flags = d->model->index(j, column, parent).flags();
- if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
+ if (isSelectableAndEnabled(d->model->index(j, column, parent).flags()))
return true;
}
}
@@ -1678,20 +1677,47 @@ bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelInde
}
/*!
+ \internal
+
+ Check whether the selection is empty.
+ In contrast to selection.isEmpty(), this takes into account
+ whether items are enabled and whether they are selectable.
+*/
+static bool selectionIsEmpty(const QItemSelection &selection)
+{
+ return std::all_of(selection.begin(), selection.end(),
+ [](const QItemSelectionRange &r) { return r.isEmpty(); });
+}
+
+/*!
\since 4.2
- Returns \c true if the selection model contains any selection ranges;
+ Returns \c true if the selection model contains any selected item,
otherwise returns \c false.
*/
bool QItemSelectionModel::hasSelection() const
{
Q_D(const QItemSelectionModel);
+
+ // QTreeModel unfortunately sorts itself lazily.
+ // When it sorts itself, it emits are layoutChanged signal.
+ // This layoutChanged signal invalidates d->ranges here.
+ // So QTreeModel must not sort itself while we are iterating over
+ // d->ranges here. It sorts itself in executePendingOperations,
+ // thus preventing the sort to happen inside of selectionIsEmpty below.
+ // Sad story, read more in QTBUG-94546
+ const QAbstractItemModel *model = QItemSelectionModel::model();
+ if (model != nullptr) {
+ auto model_p = static_cast<const QAbstractItemModelPrivate *>(QObjectPrivate::get(model));
+ model_p->executePendingOperations();
+ }
+
if (d->currentCommand & (Toggle | Deselect)) {
QItemSelection sel = d->ranges;
sel.merge(d->currentSelection, d->currentCommand);
- return !sel.isEmpty();
+ return !selectionIsEmpty(sel);
} else {
- return !(d->ranges.isEmpty() && d->currentSelection.isEmpty());
+ return !(selectionIsEmpty(d->ranges) && selectionIsEmpty(d->currentSelection));
}
}
@@ -1740,7 +1766,7 @@ QModelIndexList QItemSelectionModel::selectedRows(int column) const
QDuplicateTracker<RowOrColumnDefinition> rowsSeen;
const QItemSelection ranges = selection();
- for (int i = 0; i < ranges.count(); ++i) {
+ for (int i = 0; i < ranges.size(); ++i) {
const QItemSelectionRange &range = ranges.at(i);
QModelIndex parent = range.parent();
for (int row = range.top(); row <= range.bottom(); row++) {
@@ -1769,7 +1795,7 @@ QModelIndexList QItemSelectionModel::selectedColumns(int row) const
QDuplicateTracker<RowOrColumnDefinition> columnsSeen;
const QItemSelection ranges = selection();
- for (int i = 0; i < ranges.count(); ++i) {
+ for (int i = 0; i < ranges.size(); ++i) {
const QItemSelectionRange &range = ranges.at(i);
QModelIndex parent = range.parent();
for (int column = range.left(); column <= range.right(); column++) {
@@ -1794,10 +1820,7 @@ const QItemSelection QItemSelectionModel::selection() const
selected.merge(d->currentSelection, d->currentCommand);
// make sure we have no invalid ranges
// ### should probably be handled more generic somewhere else
- using namespace QtFunctionObjects;
- selected.erase(std::remove_if(selected.begin(), selected.end(),
- IsNotValid()),
- selected.end());
+ selected.removeIf(QtFunctionObjects::IsNotValid());
return selected;
}
@@ -1838,7 +1861,7 @@ const QItemSelection QItemSelectionModel::selection() const
*/
QAbstractItemModel *QItemSelectionModel::model()
{
- return d_func()->model;
+ return d_func()->model.value();
}
/*!
@@ -1846,7 +1869,12 @@ QAbstractItemModel *QItemSelectionModel::model()
*/
const QAbstractItemModel *QItemSelectionModel::model() const
{
- return d_func()->model;
+ return d_func()->model.value();
+}
+
+QBindable<QAbstractItemModel *> QItemSelectionModel::bindableModel()
+{
+ return &d_func()->model;
}
/*!
@@ -1859,11 +1887,11 @@ const QAbstractItemModel *QItemSelectionModel::model() const
void QItemSelectionModel::setModel(QAbstractItemModel *model)
{
Q_D(QItemSelectionModel);
- if (d->model == model)
+ d->model.removeBindingUnlessInWrapper();
+ if (d->model.valueBypassingBindings() == model)
return;
-
d->initModel(model);
- emit modelChanged(model);
+ d->model.notify();
}
/*!
@@ -1889,9 +1917,9 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio
// remove equal ranges
bool advance;
- for (int o = 0; o < deselected.count(); ++o) {
+ for (int o = 0; o < deselected.size(); ++o) {
advance = true;
- for (int s = 0; s < selected.count() && o < deselected.count();) {
+ for (int s = 0; s < selected.size() && o < deselected.size();) {
if (deselected.at(o) == selected.at(s)) {
deselected.removeAt(o);
selected.removeAt(s);
@@ -1906,17 +1934,17 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio
// find intersections
QItemSelection intersections;
- for (int o = 0; o < deselected.count(); ++o) {
- for (int s = 0; s < selected.count(); ++s) {
+ for (int o = 0; o < deselected.size(); ++o) {
+ for (int s = 0; s < selected.size(); ++s) {
if (deselected.at(o).intersects(selected.at(s)))
intersections.append(deselected.at(o).intersected(selected.at(s)));
}
}
// compare remaining ranges with intersections and split them to find deselected and selected
- for (int i = 0; i < intersections.count(); ++i) {
+ for (int i = 0; i < intersections.size(); ++i) {
// split deselected
- for (int o = 0; o < deselected.count();) {
+ for (int o = 0; o < deselected.size();) {
if (deselected.at(o).intersects(intersections.at(i))) {
QItemSelection::split(deselected.at(o), intersections.at(i), &deselected);
deselected.removeAt(o);
@@ -1925,7 +1953,7 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio
}
}
// split selected
- for (int s = 0; s < selected.count();) {
+ for (int s = 0; s < selected.size();) {
if (selected.at(s).intersects(intersections.at(i))) {
QItemSelection::split(selected.at(s), intersections.at(i), &selected);
selected.removeAt(s);
diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h
index f735bf85a8..c4b8dadc97 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.h
+++ b/src/corelib/itemmodels/qitemselectionmodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QITEMSELECTIONMODEL_H
#define QITEMSELECTIONMODEL_H
@@ -60,8 +24,8 @@ public:
void swap(QItemSelectionRange &other) noexcept
{
- qSwap(tl, other.tl);
- qSwap(br, other.br);
+ tl.swap(other.tl);
+ br.swap(other.br);
}
inline int top() const { return tl.row(); }
@@ -93,13 +57,12 @@ public:
bool intersects(const QItemSelectionRange &other) const;
QItemSelectionRange intersected(const QItemSelectionRange &other) const;
-
+#if QT_CORE_REMOVED_SINCE(6, 8)
inline bool operator==(const QItemSelectionRange &other) const
- { return (tl == other.tl && br == other.br); }
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QItemSelectionRange &other) const
- { return !operator==(other); }
- bool operator<(const QItemSelectionRange &other) const;
-
+ { return !operator==(other); }
+#endif
inline bool isValid() const
{
return (tl.isValid() && br.isValid() && tl.parent() == br.parent()
@@ -111,9 +74,15 @@ public:
QModelIndexList indexes() const;
private:
+ friend bool comparesEqual(const QItemSelectionRange &lhs,
+ const QItemSelectionRange &rhs) noexcept
+ {
+ return (lhs.tl == rhs.tl && lhs.br == rhs.br);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QItemSelectionRange)
QPersistentModelIndex tl, br;
};
-Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_RELOCATABLE_TYPE);
class QItemSelection;
class QItemSelectionModelPrivate;
@@ -121,11 +90,16 @@ class QItemSelectionModelPrivate;
class Q_CORE_EXPORT QItemSelectionModel : public QObject
{
Q_OBJECT
- Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(bool hasSelection READ hasSelection NOTIFY selectionChanged STORED false DESIGNABLE false)
- Q_PROPERTY(QModelIndex currentIndex READ currentIndex NOTIFY currentChanged STORED false DESIGNABLE false)
- Q_PROPERTY(QItemSelection selection READ selection NOTIFY selectionChanged STORED false DESIGNABLE false)
- Q_PROPERTY(QModelIndexList selectedIndexes READ selectedIndexes NOTIFY selectionChanged STORED false DESIGNABLE false)
+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged
+ BINDABLE bindableModel)
+ Q_PROPERTY(bool hasSelection READ hasSelection NOTIFY selectionChanged STORED false
+ DESIGNABLE false)
+ Q_PROPERTY(QModelIndex currentIndex READ currentIndex NOTIFY currentChanged STORED false
+ DESIGNABLE false)
+ Q_PROPERTY(QItemSelection selection READ selection NOTIFY selectionChanged STORED false
+ DESIGNABLE false)
+ Q_PROPERTY(QModelIndexList selectedIndexes READ selectedIndexes NOTIFY selectionChanged
+ STORED false DESIGNABLE false)
Q_DECLARE_PRIVATE(QItemSelectionModel)
@@ -168,9 +142,9 @@ public:
Q_INVOKABLE QModelIndexList selectedColumns(int row = 0) const;
const QItemSelection selection() const;
- // ### Qt 6: Merge these two as "QAbstractItemModel *model() const"
const QAbstractItemModel *model() const;
QAbstractItemModel *model();
+ QBindable<QAbstractItemModel *> bindableModel();
void setModel(QAbstractItemModel *model);
@@ -197,47 +171,25 @@ protected:
private:
Q_DISABLE_COPY(QItemSelectionModel)
- Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeInserted(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoHint))
- Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoHint))
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags)
-#ifdef Q_CC_MSVC
-
-/*
- ### Qt 6:
- ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
- ### Qt exports QItemSelection that inherits QList<QItemSelectionRange>.
-*/
-
-# ifndef Q_TEMPLATE_EXTERN
-# if defined(QT_BUILD_CORE_LIB)
-# define Q_TEMPLATE_EXTERN
-# else
-# define Q_TEMPLATE_EXTERN extern
-# endif
-# endif
-Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QList<QItemSelectionRange>;
-#endif // Q_CC_MSVC
-
-class Q_CORE_EXPORT QItemSelection : public QList<QItemSelectionRange>
+// We export each out-of-line method individually to prevent MSVC from
+// exporting the whole QList class.
+class QItemSelection : public QList<QItemSelectionRange>
{
public:
- QItemSelection() noexcept : QList<QItemSelectionRange>() {}
- QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ using QList<QItemSelectionRange>::QList;
+ Q_CORE_EXPORT QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight);
// reusing QList::swap() here is OK!
- void select(const QModelIndex &topLeft, const QModelIndex &bottomRight);
- bool contains(const QModelIndex &index) const;
- QModelIndexList indexes() const;
- void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command);
- static void split(const QItemSelectionRange &range,
+ Q_CORE_EXPORT void select(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ Q_CORE_EXPORT bool contains(const QModelIndex &index) const;
+ Q_CORE_EXPORT QModelIndexList indexes() const;
+ Q_CORE_EXPORT void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command);
+ Q_CORE_EXPORT static void split(const QItemSelectionRange &range,
const QItemSelectionRange &other,
QItemSelection *result);
};
@@ -249,7 +201,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QItemSelectionRange &);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QItemSelectionRange)
-Q_DECLARE_METATYPE(QItemSelection)
+QT_DECL_METATYPE_EXTERN(QItemSelectionRange, Q_CORE_EXPORT)
+QT_DECL_METATYPE_EXTERN(QItemSelection, Q_CORE_EXPORT)
#endif // QITEMSELECTIONMODEL_H
diff --git a/src/corelib/itemmodels/qitemselectionmodel_p.h b/src/corelib/itemmodels/qitemselectionmodel_p.h
index c520e50517..689cd26bd2 100644
--- a/src/corelib/itemmodels/qitemselectionmodel_p.h
+++ b/src/corelib/itemmodels/qitemselectionmodel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QITEMSELECTIONMODEL_P_H
#define QITEMSELECTIONMODEL_P_H
@@ -51,7 +15,10 @@
// We mean it.
//
+#include "qitemselectionmodel.h"
#include "private/qobject_p.h"
+#include "private/qproperty_p.h"
+#include <array>
QT_REQUIRE_CONFIG(itemmodel);
@@ -62,8 +29,7 @@ class QItemSelectionModelPrivate: public QObjectPrivate
Q_DECLARE_PUBLIC(QItemSelectionModel)
public:
QItemSelectionModelPrivate()
- : model(nullptr),
- currentCommand(QItemSelectionModel::NoUpdate),
+ : currentCommand(QItemSelectionModel::NoUpdate),
tableSelected(false), tableColCount(0), tableRowCount(0) {}
QItemSelection expandSelection(const QItemSelection &selection,
@@ -71,12 +37,23 @@ public:
void initModel(QAbstractItemModel *model);
- void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
- void _q_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
- void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
- void _q_layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void columnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
+ void triggerLayoutToBeChanged()
+ {
+ layoutAboutToBeChanged(QList<QPersistentModelIndex>(), QAbstractItemModel::NoLayoutChangeHint);
+ }
+
+ void layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
+ void triggerLayoutChanged()
+ {
+ layoutChanged(QList<QPersistentModelIndex>(), QAbstractItemModel::NoLayoutChangeHint);
+ }
+
+ void modelDestroyed();
inline void remove(QList<QItemSelectionRange> &r)
{
@@ -92,19 +69,26 @@ public:
currentSelection.clear();
}
- QPointer<QAbstractItemModel> model;
+ void setModel(QAbstractItemModel *mod) { q_func()->setModel(mod); }
+ void disconnectModel();
+ void modelChanged(QAbstractItemModel *mod) { emit q_func()->modelChanged(mod); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QItemSelectionModelPrivate, QAbstractItemModel *, model,
+ &QItemSelectionModelPrivate::setModel,
+ &QItemSelectionModelPrivate::modelChanged, nullptr)
+
QItemSelection ranges;
QItemSelection currentSelection;
QPersistentModelIndex currentIndex;
QItemSelectionModel::SelectionFlags currentCommand;
QList<QPersistentModelIndex> savedPersistentIndexes;
QList<QPersistentModelIndex> savedPersistentCurrentIndexes;
- QList<QPair<QPersistentModelIndex, uint>> savedPersistentRowLengths;
- QList<QPair<QPersistentModelIndex, uint>> savedPersistentCurrentRowLengths;
+ QList<std::pair<QPersistentModelIndex, uint>> savedPersistentRowLengths;
+ QList<std::pair<QPersistentModelIndex, uint>> savedPersistentCurrentRowLengths;
// optimization when all indexes are selected
bool tableSelected;
QPersistentModelIndex tableParent;
int tableColCount, tableRowCount;
+ std::array<QMetaObject::Connection, 12> connections;
};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 728be151c6..a5284dbad4 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -1,57 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsortfilterproxymodel.h"
#include "qitemselectionmodel.h"
#include <qsize.h>
#include <qdebug.h>
#include <qdatetime.h>
-#include <qpair.h>
#include <qstringlist.h>
#include <private/qabstractitemmodel_p.h>
#include <private/qabstractproxymodel_p.h>
+#include <private/qproperty_p.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
-typedef QList<QPair<QModelIndex, QPersistentModelIndex>> QModelIndexPairList;
+using QModelIndexPairList = QList<std::pair<QModelIndex, QPersistentModelIndex>>;
struct QSortFilterProxyModelDataChanged
{
@@ -144,9 +108,9 @@ private:
class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
{
+public:
Q_DECLARE_PUBLIC(QSortFilterProxyModel)
-public:
enum class Direction {
Rows = 1,
Columns = 2,
@@ -164,35 +128,143 @@ public:
mutable QHash<QModelIndex, Mapping*> source_index_mapping;
- int source_sort_column;
- int proxy_sort_column;
- Qt::SortOrder sort_order;
- Qt::CaseSensitivity sort_casesensitivity;
- int sort_role;
- bool sort_localeaware;
+ void setSortCaseSensitivityForwarder(Qt::CaseSensitivity cs)
+ {
+ q_func()->setSortCaseSensitivity(cs);
+ }
+ void sortCaseSensitivityChangedForwarder(Qt::CaseSensitivity cs)
+ {
+ emit q_func()->sortCaseSensitivityChanged(cs);
+ }
+
+ void setSortRoleForwarder(int role) { q_func()->setSortRole(role); }
+ void sortRoleChangedForwarder(int role) { emit q_func()->sortRoleChanged(role); }
- int filter_column;
- int filter_role;
- QRegularExpression filter_data;
- QModelIndex last_top_source;
+ void setSortLocaleAwareForwarder(bool on) { q_func()->setSortLocaleAware(on); }
+ void sortLocaleAwareChangedForwarder(bool on) { emit q_func()->sortLocaleAwareChanged(on); }
+
+ void setFilterKeyColumnForwarder(int column) { q_func()->setFilterKeyColumn(column); }
+
+ void setFilterRoleForwarder(int role) { q_func()->setFilterRole(role); }
+ void filterRoleChangedForwarder(int role) { emit q_func()->filterRoleChanged(role); }
+
+ void setRecursiveFilteringEnabledForwarder(bool recursive)
+ {
+ q_func()->setRecursiveFilteringEnabled(recursive);
+ }
+ void recursiveFilteringEnabledChangedForwarder(bool recursive)
+ {
+ emit q_func()->recursiveFilteringEnabledChanged(recursive);
+ }
+
+ void setAutoAcceptChildRowsForwarder(bool accept) { q_func()->setAutoAcceptChildRows(accept); }
+ void autoAcceptChildRowsChangedForwarder(bool accept)
+ {
+ emit q_func()->autoAcceptChildRowsChanged(accept);
+ }
+
+ void setDynamicSortFilterForwarder(bool enable) { q_func()->setDynamicSortFilter(enable); }
+
+ void setFilterCaseSensitivityForwarder(Qt::CaseSensitivity cs)
+ {
+ q_func()->setFilterCaseSensitivity(cs);
+ }
+ void filterCaseSensitivityChangedForwarder(Qt::CaseSensitivity cs)
+ {
+ emit q_func()->filterCaseSensitivityChanged(cs);
+ }
+
+ void setFilterRegularExpressionForwarder(const QRegularExpression &re)
+ {
+ q_func()->setFilterRegularExpression(re);
+ }
+
+ int source_sort_column = -1;
+ int proxy_sort_column = -1;
+ Qt::SortOrder sort_order = Qt::AscendingOrder;
+ bool complete_insert = false;
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(
+ QSortFilterProxyModelPrivate, Qt::CaseSensitivity, sort_casesensitivity,
+ &QSortFilterProxyModelPrivate::setSortCaseSensitivityForwarder,
+ &QSortFilterProxyModelPrivate::sortCaseSensitivityChangedForwarder, Qt::CaseSensitive)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSortFilterProxyModelPrivate, int, sort_role,
+ &QSortFilterProxyModelPrivate::setSortRoleForwarder,
+ &QSortFilterProxyModelPrivate::sortRoleChangedForwarder,
+ Qt::DisplayRole)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSortFilterProxyModelPrivate, int, filter_column,
+ &QSortFilterProxyModelPrivate::setFilterKeyColumnForwarder,
+ 0)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSortFilterProxyModelPrivate, int, filter_role,
+ &QSortFilterProxyModelPrivate::setFilterRoleForwarder,
+ &QSortFilterProxyModelPrivate::filterRoleChangedForwarder,
+ Qt::DisplayRole)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(
+ QSortFilterProxyModelPrivate, bool, sort_localeaware,
+ &QSortFilterProxyModelPrivate::setSortLocaleAwareForwarder,
+ &QSortFilterProxyModelPrivate::sortLocaleAwareChangedForwarder, false)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(
+ QSortFilterProxyModelPrivate, bool, filter_recursive,
+ &QSortFilterProxyModelPrivate::setRecursiveFilteringEnabledForwarder,
+ &QSortFilterProxyModelPrivate::recursiveFilteringEnabledChangedForwarder, false)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(
+ QSortFilterProxyModelPrivate, bool, accept_children,
+ &QSortFilterProxyModelPrivate::setAutoAcceptChildRowsForwarder,
+ &QSortFilterProxyModelPrivate::autoAcceptChildRowsChangedForwarder, false)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSortFilterProxyModelPrivate, bool, dynamic_sortfilter,
+ &QSortFilterProxyModelPrivate::setDynamicSortFilterForwarder,
+ true)
+
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(
+ QSortFilterProxyModelPrivate, Qt::CaseSensitivity, filter_casesensitive,
+ &QSortFilterProxyModelPrivate::setFilterCaseSensitivityForwarder,
+ &QSortFilterProxyModelPrivate::filterCaseSensitivityChangedForwarder, Qt::CaseSensitive)
- bool filter_recursive;
- bool accept_children;
- bool complete_insert;
- bool dynamic_sortfilter;
+ Q_OBJECT_COMPAT_PROPERTY(QSortFilterProxyModelPrivate, QRegularExpression,
+ filter_regularexpression,
+ &QSortFilterProxyModelPrivate::setFilterRegularExpressionForwarder)
+
+ QModelIndex last_top_source;
QRowsRemoval itemsBeingRemoved;
QModelIndexPairList saved_persistent_indexes;
QList<QPersistentModelIndex> saved_layoutChange_parents;
+ std::array<QMetaObject::Connection, 18> sourceConnections;
+
QHash<QModelIndex, Mapping *>::const_iterator create_mapping(
const QModelIndex &source_parent) const;
+ QHash<QModelIndex, Mapping *>::const_iterator create_mapping_recursive(
+ const QModelIndex &source_parent) const;
QModelIndex proxy_to_source(const QModelIndex &proxyIndex) const;
QModelIndex source_to_proxy(const QModelIndex &sourceIndex) const;
bool can_create_mapping(const QModelIndex &source_parent) const;
void remove_from_mapping(const QModelIndex &source_parent);
+ /*
+ * Legacy: changing the pattern through a string does not change the
+ * case sensitivity.
+ */
+ void set_filter_pattern(const QString &pattern)
+ {
+ QRegularExpression re = filter_regularexpression.valueBypassingBindings();
+ const auto cs = re.patternOptions() & QRegularExpression::CaseInsensitiveOption;
+ re.setPattern(pattern);
+ re.setPatternOptions(cs);
+ // This is a helper function, which is supposed to be called from a
+ // more complicated context. Because of that, the caller is responsible
+ // for calling notify() and removeBindingUnlessInWrapper(), if needed.
+ filter_regularexpression.setValueBypassingBindings(re);
+ }
+
inline QHash<QModelIndex, Mapping *>::const_iterator index_to_iterator(
const QModelIndex &proxy_index) const
{
@@ -260,10 +332,10 @@ public:
int find_source_sort_column() const;
void sort_source_rows(QList<int> &source_rows,
const QModelIndex &source_parent) const;
- QList<QPair<int, QList<int>>> proxy_intervals_for_source_items_to_add(
+ QList<std::pair<int, QList<int>>> proxy_intervals_for_source_items_to_add(
const QList<int> &proxy_to_source, const QList<int> &source_items,
const QModelIndex &source_parent, Qt::Orientation orient) const;
- QList<QPair<int, int>> proxy_intervals_for_source_items(
+ QList<std::pair<int, int>> proxy_intervals_for_source_items(
const QList<int> &source_to_proxy, const QList<int> &source_items) const;
void insert_source_items(
QList<int> &source_to_proxy, QList<int> &proxy_to_source,
@@ -379,7 +451,7 @@ bool QSortFilterProxyModelPrivate::recursiveChildAcceptsRow(int source_row, cons
void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent)
{
if (Mapping *m = source_index_mapping.take(source_parent)) {
- for (const QModelIndex &mappedIdx : qAsConst(m->mapped_children))
+ for (const QModelIndex &mappedIdx : std::as_const(m->mapped_children))
remove_from_mapping(mappedIdx);
delete m;
}
@@ -445,6 +517,29 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping(
return it;
}
+// Go up the tree, creating mappings, unless of course the parent is filtered out
+IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping_recursive(const QModelIndex &source_parent) const
+{
+ if (source_parent.isValid()) {
+ const QModelIndex source_grand_parent = source_parent.parent();
+ IndexMap::const_iterator it = source_index_mapping.constFind(source_grand_parent);
+ IndexMap::const_iterator end = source_index_mapping.constEnd();
+ if (it == end) {
+ it = create_mapping_recursive(source_grand_parent);
+ end = source_index_mapping.constEnd();
+ if (it == end)
+ return end;
+ }
+ Mapping *gm = it.value();
+ if (gm->proxy_rows.at(source_parent.row()) == -1 ||
+ gm->proxy_columns.at(source_parent.column()) == -1) {
+ // Can't do, parent is filtered
+ return end;
+ }
+ }
+ return create_mapping(source_parent);
+}
+
QModelIndex QSortFilterProxyModelPrivate::proxy_to_source(const QModelIndex &proxy_index) const
{
if (!proxy_index.isValid())
@@ -593,8 +688,10 @@ void QSortFilterProxyModelPrivate::sort_source_rows(
QSortFilterProxyModelGreaterThan gt(source_sort_column, source_parent, model, q);
std::stable_sort(source_rows.begin(), source_rows.end(), gt);
}
- } else { // restore the source model order
- std::stable_sort(source_rows.begin(), source_rows.end());
+ } else if (sort_order == Qt::AscendingOrder) {
+ std::stable_sort(source_rows.begin(), source_rows.end(), std::less{});
+ } else {
+ std::stable_sort(source_rows.begin(), source_rows.end(), std::greater{});
}
}
@@ -609,10 +706,10 @@ void QSortFilterProxyModelPrivate::sort_source_rows(
The result is a vector of pairs, where each pair represents a
(start, end) tuple, sorted in ascending order.
*/
-QList<QPair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items(
+QList<std::pair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items(
const QList<int> &source_to_proxy, const QList<int> &source_items) const
{
- QList<QPair<int, int>> proxy_intervals;
+ QList<std::pair<int, int>> proxy_intervals;
if (source_items.isEmpty())
return proxy_intervals;
@@ -629,22 +726,19 @@ QList<QPair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_
++source_items_index;
}
// Add interval to result
- proxy_intervals.append(QPair<int, int>(first_proxy_item, last_proxy_item));
+ proxy_intervals.emplace_back(first_proxy_item, last_proxy_item);
}
std::stable_sort(proxy_intervals.begin(), proxy_intervals.end());
// Consolidate adjacent intervals
for (int i = proxy_intervals.size()-1; i > 0; --i) {
- QPair<int, int> &interval = proxy_intervals[i];
- QPair<int, int> &preceeding_interval = proxy_intervals[i - 1];
+ std::pair<int, int> &interval = proxy_intervals[i];
+ std::pair<int, int> &preceeding_interval = proxy_intervals[i - 1];
if (interval.first == preceeding_interval.second + 1) {
preceeding_interval.second = interval.second;
interval.first = interval.second = -1;
}
}
- proxy_intervals.erase(
- std::remove_if(proxy_intervals.begin(), proxy_intervals.end(),
- [](QPair<int, int> &interval) { return interval.first < 0; }),
- proxy_intervals.end());
+ proxy_intervals.removeIf([](std::pair<int, int> interval) { return interval.first < 0; });
return proxy_intervals;
}
@@ -663,15 +757,17 @@ void QSortFilterProxyModelPrivate::remove_source_items(
{
Q_Q(QSortFilterProxyModel);
QModelIndex proxy_parent = q->mapFromSource(source_parent);
- if (!proxy_parent.isValid() && source_parent.isValid())
+ if (!proxy_parent.isValid() && source_parent.isValid()) {
+ proxy_to_source.clear();
return; // nothing to do (already removed)
+ }
const auto proxy_intervals = proxy_intervals_for_source_items(
source_to_proxy, source_items);
const auto end = proxy_intervals.rend();
for (auto it = proxy_intervals.rbegin(); it != end; ++it) {
- const QPair<int, int> &interval = *it;
+ const std::pair<int, int> &interval = *it;
const int proxy_start = interval.first;
const int proxy_end = interval.second;
remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end,
@@ -725,22 +821,21 @@ void QSortFilterProxyModelPrivate::remove_proxy_interval(
items), where items is a vector containing the (sorted) source items that
should be inserted at that proxy model location.
*/
-QList<QPair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add(
+QList<std::pair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add(
const QList<int> &proxy_to_source, const QList<int> &source_items,
const QModelIndex &source_parent, Qt::Orientation orient) const
{
Q_Q(const QSortFilterProxyModel);
- QList<QPair<int, QList<int>>> proxy_intervals;
+ QList<std::pair<int, QList<int>>> proxy_intervals;
if (source_items.isEmpty())
return proxy_intervals;
int proxy_low = 0;
int proxy_item = 0;
int source_items_index = 0;
- QList<int> source_items_in_interval;
bool compare = (orient == Qt::Vertical && source_sort_column >= 0 && dynamic_sortfilter);
while (source_items_index < source_items.size()) {
- source_items_in_interval.clear();
+ QList<int> source_items_in_interval;
int first_new_source_item = source_items.at(source_items_index);
source_items_in_interval.append(first_new_source_item);
++source_items_index;
@@ -786,7 +881,7 @@ QList<QPair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_
}
// Add interval to result
- proxy_intervals.append(QPair<int, QList<int>>(proxy_item, source_items_in_interval));
+ proxy_intervals.emplace_back(proxy_item, std::move(source_items_in_interval));
}
return proxy_intervals;
}
@@ -814,7 +909,7 @@ void QSortFilterProxyModelPrivate::insert_source_items(
const auto end = proxy_intervals.rend();
for (auto it = proxy_intervals.rbegin(); it != end; ++it) {
- const QPair<int, QList<int>> &interval = *it;
+ const std::pair<int, QList<int>> &interval = *it;
const int proxy_start = interval.first;
const QList<int> &source_items = interval.second;
const int proxy_end = proxy_start + source_items.size() - 1;
@@ -826,8 +921,9 @@ void QSortFilterProxyModelPrivate::insert_source_items(
q->beginInsertColumns(proxy_parent, proxy_start, proxy_end);
}
- for (int i = 0; i < source_items.size(); ++i)
- proxy_to_source.insert(proxy_start + i, source_items.at(i));
+ // TODO: use the range QList::insert() overload once it is implemented (QTBUG-58633).
+ proxy_to_source.insert(proxy_start, source_items.size(), 0);
+ std::copy(source_items.cbegin(), source_items.cend(), proxy_to_source.begin() + proxy_start);
build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start);
@@ -865,12 +961,12 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
it = create_mapping(source_parent);
Mapping *m = it.value();
QModelIndex proxy_parent = q->mapFromSource(source_parent);
- if (m->source_rows.count() > 0) {
- q->beginInsertRows(proxy_parent, 0, m->source_rows.count() - 1);
+ if (m->source_rows.size() > 0) {
+ q->beginInsertRows(proxy_parent, 0, m->source_rows.size() - 1);
q->endInsertRows();
}
- if (m->source_columns.count() > 0) {
- q->beginInsertColumns(proxy_parent, 0, m->source_columns.count() - 1);
+ if (m->source_columns.size() > 0) {
+ q->beginInsertColumns(proxy_parent, 0, m->source_columns.size() - 1);
q->endInsertColumns();
}
return;
@@ -1042,7 +1138,7 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour
Qt::Orientation orient, int start, int end, int delta_item_count, bool remove)
{
// see if any mapped children should be (re)moved
- QList<QPair<QModelIndex, Mapping *>> moved_source_index_mappings;
+ QList<std::pair<QModelIndex, Mapping *>> moved_source_index_mappings;
auto it2 = parent_mapping->mapped_children.begin();
for ( ; it2 != parent_mapping->mapped_children.end();) {
const QModelIndex source_child_index = *it2;
@@ -1076,12 +1172,12 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour
Mapping *cm = source_index_mapping.take(source_child_index);
Q_ASSERT(cm);
// we do not reinsert right away, because the new index might be identical with another, old index
- moved_source_index_mappings.append(QPair<QModelIndex, Mapping*>(new_index, cm));
+ moved_source_index_mappings.emplace_back(new_index, cm);
}
}
// reinsert moved, mapped indexes
- for (auto &pair : qAsConst(moved_source_index_mappings)) {
+ for (auto &pair : std::as_const(moved_source_index_mappings)) {
pair.second->source_parent = pair.first;
source_index_mapping.insert(pair.first, pair.second);
}
@@ -1096,7 +1192,7 @@ void QSortFilterProxyModelPrivate::proxy_item_range(
{
proxy_low = INT_MAX;
proxy_high = INT_MIN;
- for (int i = 0; i < source_items.count(); ++i) {
+ for (int i = 0; i < source_items.size(); ++i) {
int proxy_item = source_to_proxy.at(source_items.at(i));
Q_ASSERT(proxy_item != -1);
if (proxy_item < proxy_low)
@@ -1129,11 +1225,11 @@ QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() con
{
Q_Q(const QSortFilterProxyModel);
QModelIndexPairList source_indexes;
- source_indexes.reserve(persistent.indexes.count());
- for (const QPersistentModelIndexData *data : qAsConst(persistent.indexes)) {
+ source_indexes.reserve(persistent.indexes.size());
+ for (const QPersistentModelIndexData *data : std::as_const(persistent.indexes)) {
const QModelIndex &proxy_index = data->index;
QModelIndex source_index = q->mapToSource(proxy_index);
- source_indexes.append(qMakePair(proxy_index, QPersistentModelIndex(source_index)));
+ source_indexes.emplace_back(proxy_index, source_index);
}
return source_indexes;
}
@@ -1149,7 +1245,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes(
{
Q_Q(QSortFilterProxyModel);
QModelIndexList from, to;
- const int numSourceIndexes = source_indexes.count();
+ const int numSourceIndexes = source_indexes.size();
from.reserve(numSourceIndexes);
to.reserve(numSourceIndexes);
for (const auto &indexPair : source_indexes) {
@@ -1171,9 +1267,10 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes(
*/
void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex &source_parent)
{
- if (!filter_data.pattern().isEmpty() &&
- source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd())
- create_mapping(source_parent);
+ if (!filter_regularexpression.valueBypassingBindings().pattern().isEmpty()
+ && source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd()) {
+ create_mapping(source_parent);
+ }
}
@@ -1232,7 +1329,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
Q_Q(QSortFilterProxyModel);
// Figure out which mapped items to remove
QList<int> source_items_remove;
- for (int i = 0; i < proxy_to_source.count(); ++i) {
+ for (int i = 0; i < proxy_to_source.size(); ++i) {
const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical)
? !filterAcceptsRowInternal(source_item, source_parent)
@@ -1319,11 +1416,20 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
const QModelIndex &source_bottom_right = data_changed.bottomRight;
const QModelIndex source_parent = source_top_left.parent();
+ bool change_in_unmapped_parent = false;
IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
if (it == source_index_mapping.constEnd()) {
- // Don't care, since we don't have mapping for this index
- continue;
+ // We don't have mapping for this index, so we cannot know how things
+ // changed (in case the change affects filtering) in order to forward
+ // the change correctly.
+ // But we can at least forward the signal "as is", if the row isn't
+ // filtered out, this is better than nothing.
+ it = create_mapping_recursive(source_parent);
+ if (it == source_index_mapping.constEnd())
+ continue;
+ change_in_unmapped_parent = true;
}
+
Mapping *m = it.value();
// Figure out how the source changes affect us
@@ -1331,9 +1437,9 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
QList<int> source_rows_insert;
QList<int> source_rows_change;
QList<int> source_rows_resort;
- int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1);
+ int end = qMin(source_bottom_right.row(), m->proxy_rows.size() - 1);
for (int source_row = source_top_left.row(); source_row <= end; ++source_row) {
- if (dynamic_sortfilter) {
+ if (dynamic_sortfilter && !change_in_unmapped_parent) {
if (m->proxy_rows.at(source_row) != -1) {
if (!filterAcceptsRowInternal(source_row, source_parent)) {
// This source row no longer satisfies the filter, so it must be removed
@@ -1404,15 +1510,19 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
while (source_left_column < source_bottom_right.column()
&& m->proxy_columns.at(source_left_column) == -1)
++source_left_column;
- const QModelIndex proxy_top_left = create_index(
- proxy_start_row, m->proxy_columns.at(source_left_column), it);
- int source_right_column = source_bottom_right.column();
- while (source_right_column > source_top_left.column()
- && m->proxy_columns.at(source_right_column) == -1)
- --source_right_column;
- const QModelIndex proxy_bottom_right = create_index(
- proxy_end_row, m->proxy_columns.at(source_right_column), it);
- emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
+ if (m->proxy_columns.at(source_left_column) != -1) {
+ const QModelIndex proxy_top_left = create_index(
+ proxy_start_row, m->proxy_columns.at(source_left_column), it);
+ int source_right_column = source_bottom_right.column();
+ while (source_right_column > source_top_left.column()
+ && m->proxy_columns.at(source_right_column) == -1)
+ --source_right_column;
+ if (m->proxy_columns.at(source_right_column) != -1) {
+ const QModelIndex proxy_bottom_right = create_index(
+ proxy_end_row, m->proxy_columns.at(source_right_column), it);
+ emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
+ }
+ }
}
}
@@ -1479,8 +1589,7 @@ void QSortFilterProxyModelPrivate::_q_sourceReset()
_q_clearMapping();
// All internal structures are deleted in clear()
q->endResetModel();
- update_source_sort_column();
- if (dynamic_sortfilter && update_source_sort_column())
+ if (update_source_sort_column() && dynamic_sortfilter)
sort();
}
@@ -1544,8 +1653,8 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted(
const bool toplevel = !source_parent.isValid();
const bool recursive_accepted = filter_recursive && !toplevel && filterAcceptsRowInternal(source_parent.row(), source_parent.parent());
- //Force the creation of a mapping now, even if its empty.
- //We need it because the proxy can be acessed at the moment it emits rowsAboutToBeInserted in insert_source_items
+ //Force the creation of a mapping now, even if it's empty.
+ //We need it because the proxy can be accessed at the moment it emits rowsAboutToBeInserted in insert_source_items
if (!filter_recursive || toplevel || recursive_accepted) {
if (can_create_mapping(source_parent))
create_mapping(source_parent);
@@ -1664,8 +1773,8 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(
{
Q_UNUSED(start);
Q_UNUSED(end);
- //Force the creation of a mapping now, even if its empty.
- //We need it because the proxy can be acessed at the moment it emits columnsAboutToBeInserted in insert_source_items
+ //Force the creation of a mapping now, even if it's empty.
+ //We need it because the proxy can be accessed at the moment it emits columnsAboutToBeInserted in insert_source_items
if (can_create_mapping(source_parent))
create_mapping(source_parent);
}
@@ -1712,7 +1821,10 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
source_sort_column = -1;
}
- proxy_sort_column = q->mapFromSource(model->index(0,source_sort_column, source_parent)).column();
+ if (source_sort_column >= 0)
+ proxy_sort_column = q->mapFromSource(model->index(0,source_sort_column, source_parent)).column();
+ else
+ proxy_sort_column = -1;
}
void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(
@@ -1897,18 +2009,8 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent)
: QAbstractProxyModel(*new QSortFilterProxyModelPrivate, parent)
{
Q_D(QSortFilterProxyModel);
- d->proxy_sort_column = d->source_sort_column = -1;
- d->sort_order = Qt::AscendingOrder;
- d->sort_casesensitivity = Qt::CaseSensitive;
- d->sort_role = Qt::DisplayRole;
- d->sort_localeaware = false;
- d->filter_column = 0;
- d->filter_role = Qt::DisplayRole;
- d->filter_recursive = false;
- d->accept_children = false;
- d->dynamic_sortfilter = true;
- d->complete_insert = false;
- connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping()));
+ QObjectPrivate::connect(this, &QAbstractItemModel::modelReset, d,
+ &QSortFilterProxyModelPrivate::_q_clearMapping);
}
/*!
@@ -1933,56 +2035,10 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
beginResetModel();
- disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)),
- this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>)));
-
- disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
-
- disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
-
- disconnect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
-
- disconnect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
-
- disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)));
-
- disconnect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
-
- disconnect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
-
- disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset()));
- disconnect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset()));
+ if (d->model) {
+ for (const QMetaObject::Connection &connection : std::as_const(d->sourceConnections))
+ disconnect(connection);
+ }
// same as in _q_sourceReset()
d->invalidatePersistentIndexes();
@@ -1990,57 +2046,61 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
QAbstractProxyModel::setSourceModel(sourceModel);
- connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)),
- this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QList<int>)));
+ d->sourceConnections = std::array<QMetaObject::Connection, 18>{
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::dataChanged, d,
+ &QSortFilterProxyModelPrivate::_q_sourceDataChanged),
- connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::headerDataChanged, d,
+ &QSortFilterProxyModelPrivate::_q_sourceHeaderDataChanged),
- connect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsAboutToBeInserted, d,
+ &QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted),
- connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted, d,
+ &QSortFilterProxyModelPrivate::_q_sourceRowsInserted),
- connect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeInserted, d,
+ &QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted),
- connect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsInserted(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsInserted, d,
+ &QSortFilterProxyModelPrivate::_q_sourceColumnsInserted),
- connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved),
- connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsRemoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceRowsRemoved),
- connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved),
- connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sourceColumnsRemoved(QModelIndex,int,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsRemoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved),
- connect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsAboutToBeMoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeMoved),
- connect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsMoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceRowsMoved),
- connect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeMoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeMoved),
- connect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsMoved, d,
+ &QSortFilterProxyModelPrivate::_q_sourceColumnsMoved),
- connect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::layoutAboutToBeChanged, d,
+ &QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged),
- connect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::layoutChanged, d,
+ &QSortFilterProxyModelPrivate::_q_sourceLayoutChanged),
- connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset()));
- connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset()));
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::modelAboutToBeReset, d,
+ &QSortFilterProxyModelPrivate::_q_sourceAboutToBeReset),
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::modelReset, d,
+ &QSortFilterProxyModelPrivate::_q_sourceReset)
+ };
endResetModel();
if (d->update_source_sort_column() && d->dynamic_sortfilter)
d->sort();
@@ -2057,7 +2117,7 @@ QModelIndex QSortFilterProxyModel::index(int row, int column, const QModelIndex
QModelIndex source_parent = mapToSource(parent); // parent is already mapped at this point
IndexMap::const_iterator it = d->create_mapping(source_parent); // but make sure that the children are mapped
- if (it.value()->source_rows.count() <= row || it.value()->source_columns.count() <= column)
+ if (it.value()->source_rows.size() <= row || it.value()->source_columns.size() <= column)
return QModelIndex();
return d->create_index(row, column, it);
@@ -2088,7 +2148,7 @@ QModelIndex QSortFilterProxyModel::sibling(int row, int column, const QModelInde
return QModelIndex();
const IndexMap::const_iterator it = d->index_to_iterator(idx);
- if (it.value()->source_rows.count() <= row || it.value()->source_columns.count() <= column)
+ if (it.value()->source_rows.size() <= row || it.value()->source_columns.size() <= column)
return QModelIndex();
return d->create_index(row, column, it);
@@ -2104,7 +2164,7 @@ int QSortFilterProxyModel::rowCount(const QModelIndex &parent) const
if (parent.isValid() && !source_parent.isValid())
return 0;
IndexMap::const_iterator it = d->create_mapping(source_parent);
- return it.value()->source_rows.count();
+ return it.value()->source_rows.size();
}
/*!
@@ -2117,7 +2177,7 @@ int QSortFilterProxyModel::columnCount(const QModelIndex &parent) const
if (parent.isValid() && !source_parent.isValid())
return 0;
IndexMap::const_iterator it = d->create_mapping(source_parent);
- return it.value()->source_columns.count();
+ return it.value()->source_columns.size();
}
/*!
@@ -2136,7 +2196,7 @@ bool QSortFilterProxyModel::hasChildren(const QModelIndex &parent) const
return true; //we assume we might have children that can be fetched
QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
- return m->source_rows.count() != 0 && m->source_columns.count() != 0;
+ return m->source_rows.size() != 0 && m->source_columns.size() != 0;
}
/*!
@@ -2170,15 +2230,15 @@ QVariant QSortFilterProxyModel::headerData(int section, Qt::Orientation orientat
{
Q_D(const QSortFilterProxyModel);
IndexMap::const_iterator it = d->create_mapping(QModelIndex());
- if (it.value()->source_rows.count() * it.value()->source_columns.count() > 0)
+ if (it.value()->source_rows.size() * it.value()->source_columns.size() > 0)
return QAbstractProxyModel::headerData(section, orientation, role);
int source_section;
if (orientation == Qt::Vertical) {
- if (section < 0 || section >= it.value()->source_rows.count())
+ if (section < 0 || section >= it.value()->source_rows.size())
return QVariant();
source_section = it.value()->source_rows.at(section);
} else {
- if (section < 0 || section >= it.value()->source_columns.count())
+ if (section < 0 || section >= it.value()->source_columns.size())
return QVariant();
source_section = it.value()->source_columns.at(section);
}
@@ -2193,15 +2253,15 @@ bool QSortFilterProxyModel::setHeaderData(int section, Qt::Orientation orientati
{
Q_D(QSortFilterProxyModel);
IndexMap::const_iterator it = d->create_mapping(QModelIndex());
- if (it.value()->source_rows.count() * it.value()->source_columns.count() > 0)
+ if (it.value()->source_rows.size() * it.value()->source_columns.size() > 0)
return QAbstractProxyModel::setHeaderData(section, orientation, value, role);
int source_section;
if (orientation == Qt::Vertical) {
- if (section < 0 || section >= it.value()->source_rows.count())
+ if (section < 0 || section >= it.value()->source_rows.size())
return false;
source_section = it.value()->source_rows.at(section);
} else {
- if (section < 0 || section >= it.value()->source_columns.count())
+ if (section < 0 || section >= it.value()->source_columns.size())
return false;
source_section = it.value()->source_columns.at(section);
}
@@ -2215,7 +2275,7 @@ QMimeData *QSortFilterProxyModel::mimeData(const QModelIndexList &indexes) const
{
Q_D(const QSortFilterProxyModel);
QModelIndexList source_indexes;
- source_indexes.reserve(indexes.count());
+ source_indexes.reserve(indexes.size());
for (const QModelIndex &idx : indexes)
source_indexes << mapToSource(idx);
return d->model->mimeData(source_indexes);
@@ -2261,10 +2321,10 @@ bool QSortFilterProxyModel::insertRows(int row, int count, const QModelIndex &pa
if (parent.isValid() && !source_parent.isValid())
return false;
QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
- if (row > m->source_rows.count())
+ if (row > m->source_rows.size())
return false;
- int source_row = (row >= m->source_rows.count()
- ? m->proxy_rows.count()
+ int source_row = (row >= m->source_rows.size()
+ ? m->proxy_rows.size()
: m->source_rows.at(row));
return d->model->insertRows(source_row, count, source_parent);
}
@@ -2281,10 +2341,10 @@ bool QSortFilterProxyModel::insertColumns(int column, int count, const QModelInd
if (parent.isValid() && !source_parent.isValid())
return false;
QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
- if (column > m->source_columns.count())
+ if (column > m->source_columns.size())
return false;
- int source_column = (column >= m->source_columns.count()
- ? m->proxy_columns.count()
+ int source_column = (column >= m->source_columns.size()
+ ? m->proxy_columns.size()
: m->source_columns.at(column));
return d->model->insertColumns(source_column, count, source_parent);
}
@@ -2301,10 +2361,10 @@ bool QSortFilterProxyModel::removeRows(int row, int count, const QModelIndex &pa
if (parent.isValid() && !source_parent.isValid())
return false;
QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
- if (row + count > m->source_rows.count())
+ if (row + count > m->source_rows.size())
return false;
if ((count == 1)
- || ((d->source_sort_column < 0) && (m->proxy_rows.count() == m->source_rows.count()))) {
+ || ((d->source_sort_column < 0) && (m->proxy_rows.size() == m->source_rows.size()))) {
int source_row = m->source_rows.at(row);
return d->model->removeRows(source_row, count, source_parent);
}
@@ -2316,7 +2376,7 @@ bool QSortFilterProxyModel::removeRows(int row, int count, const QModelIndex &pa
rows.append(m->source_rows.at(i));
std::sort(rows.begin(), rows.end());
- int pos = rows.count() - 1;
+ int pos = rows.size() - 1;
bool ok = true;
while (pos >= 0) {
const int source_end = rows.at(pos--);
@@ -2343,9 +2403,9 @@ bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelInd
if (parent.isValid() && !source_parent.isValid())
return false;
QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
- if (column + count > m->source_columns.count())
+ if (column + count > m->source_columns.size())
return false;
- if ((count == 1) || (m->proxy_columns.count() == m->source_columns.count())) {
+ if ((count == 1) || (m->proxy_columns.size() == m->source_columns.size())) {
int source_column = m->source_columns.at(column);
return d->model->removeColumns(source_column, count, source_parent);
}
@@ -2355,7 +2415,7 @@ bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelInd
for (int i = column; i < column + count; ++i)
columns.append(m->source_columns.at(i));
- int pos = columns.count() - 1;
+ int pos = columns.size() - 1;
bool ok = true;
while (pos >= 0) {
const int source_end = columns.at(pos--);
@@ -2375,11 +2435,7 @@ bool QSortFilterProxyModel::removeColumns(int column, int count, const QModelInd
*/
void QSortFilterProxyModel::fetchMore(const QModelIndex &parent)
{
- Q_D(QSortFilterProxyModel);
- QModelIndex source_parent;
- if (d->indexValid(parent))
- source_parent = mapToSource(parent);
- d->model->fetchMore(source_parent);
+ QAbstractProxyModel::fetchMore(parent);
}
/*!
@@ -2387,11 +2443,7 @@ void QSortFilterProxyModel::fetchMore(const QModelIndex &parent)
*/
bool QSortFilterProxyModel::canFetchMore(const QModelIndex &parent) const
{
- Q_D(const QSortFilterProxyModel);
- QModelIndex source_parent;
- if (d->indexValid(parent))
- source_parent = mapToSource(parent);
- return d->model->canFetchMore(source_parent);
+ return QAbstractProxyModel::canFetchMore(parent);
}
/*!
@@ -2399,11 +2451,7 @@ bool QSortFilterProxyModel::canFetchMore(const QModelIndex &parent) const
*/
Qt::ItemFlags QSortFilterProxyModel::flags(const QModelIndex &index) const
{
- Q_D(const QSortFilterProxyModel);
- QModelIndex source_index;
- if (d->indexValid(index))
- source_index = mapToSource(index);
- return d->model->flags(source_index);
+ return QAbstractProxyModel::flags(index);
}
/*!
@@ -2444,7 +2492,10 @@ QSize QSortFilterProxyModel::span(const QModelIndex &index) const
}
/*!
- \reimp
+ \reimp
+ Sorts the model by \a column in the given \a order.
+ If the sort \a column is less than zero, the model will be sorted by source model row
+ in the given \a order.
*/
void QSortFilterProxyModel::sort(int column, Qt::SortOrder order)
{
@@ -2459,9 +2510,12 @@ void QSortFilterProxyModel::sort(int column, Qt::SortOrder order)
/*!
\since 4.5
- \brief the column currently used for sorting
+ \return the column currently used for sorting
- This returns the most recently used sort column.
+ This returns the most recently used sort column. The default value is -1,
+ which means that this proxy model does not sort.
+
+ \sa sort()
*/
int QSortFilterProxyModel::sortColumn() const
{
@@ -2471,9 +2525,12 @@ int QSortFilterProxyModel::sortColumn() const
/*!
\since 4.5
- \brief the order currently used for sorting
+ \return the order currently used for sorting
+
+ This returns the most recently used sort order. The default value is
+ Qt::AscendingOrder.
- This returns the most recently used sort order.
+ \sa sort()
*/
Qt::SortOrder QSortFilterProxyModel::sortOrder() const
{
@@ -2481,35 +2538,62 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const
return d->sort_order;
}
-#if QT_CONFIG(regularexpression)
/*!
\since 5.12
\property QSortFilterProxyModel::filterRegularExpression
\brief the QRegularExpression used to filter the contents of the source model
- Setting this property overwrites the current
- \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}.
+ Setting this property through the QRegularExpression overload overwrites the
+ current \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}.
By default, the QRegularExpression is an empty string matching all contents.
If no QRegularExpression or an empty string is set, everything in the source
model will be accepted.
+ \note Setting this property propagates the case sensitivity of the new
+ regular expression to the \l filterCaseSensitivity property, and so breaks
+ its binding. Likewise explicitly setting \l filterCaseSensitivity changes
+ the case sensitivity of the current regular expression, thereby breaking
+ its binding.
+
\sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString()
*/
QRegularExpression QSortFilterProxyModel::filterRegularExpression() const
{
Q_D(const QSortFilterProxyModel);
- return d->filter_data;
+ return d->filter_regularexpression;
+}
+
+QBindable<QRegularExpression> QSortFilterProxyModel::bindableFilterRegularExpression()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<QRegularExpression>(&d->filter_regularexpression);
}
void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression &regularExpression)
{
Q_D(QSortFilterProxyModel);
+ const QScopedPropertyUpdateGroup guard;
+ const bool regExpChanged =
+ regularExpression != d->filter_regularexpression.valueBypassingBindings();
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
+ d->filter_casesensitive.removeBindingUnlessInWrapper();
+ const Qt::CaseSensitivity cs = d->filter_casesensitive.valueBypassingBindings();
d->filter_about_to_be_changed();
- d->filter_data = regularExpression;
+ const Qt::CaseSensitivity updatedCs =
+ regularExpression.patternOptions() & QRegularExpression::CaseInsensitiveOption
+ ? Qt::CaseInsensitive : Qt::CaseSensitive;
+ d->filter_regularexpression.setValueBypassingBindings(regularExpression);
+ if (cs != updatedCs)
+ d->filter_casesensitive.setValueBypassingBindings(updatedCs);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ // Do not change the evaluation logic, but notify only if the regular
+ // expression has actually changed.
+ if (regExpChanged)
+ d->filter_regularexpression.notify();
+ if (cs != updatedCs)
+ d->filter_casesensitive.notify();
}
-#endif
/*!
\property QSortFilterProxyModel::filterKeyColumn
@@ -2527,10 +2611,25 @@ int QSortFilterProxyModel::filterKeyColumn() const
void QSortFilterProxyModel::setFilterKeyColumn(int column)
{
+ // While introducing new bindable properties, we still update the value
+ // unconditionally (even if it didn't really change), and call the
+ // filter_about_to_be_changed()/filter_changed() methods, so that we do
+ // not break any code. However we do notify the observing bindings only
+ // if the column has actually changed
Q_D(QSortFilterProxyModel);
+ d->filter_column.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
- d->filter_column = column;
+ const auto oldColumn = d->filter_column.valueBypassingBindings();
+ d->filter_column.setValueBypassingBindings(column);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ if (oldColumn != column)
+ d->filter_column.notify();
+}
+
+QBindable<int> QSortFilterProxyModel::bindableFilterKeyColumn()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<int>(&d->filter_column);
}
/*!
@@ -2541,6 +2640,11 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column)
By default, the filter is case sensitive.
+ \note Setting this property propagates the new case sensitivity to the
+ \l filterRegularExpression property, and so breaks its binding. Likewise
+ explicitly setting \l filterRegularExpression changes the current case
+ sensitivity, thereby breaking its binding.
+
\sa filterRegularExpression, sortCaseSensitivity
*/
@@ -2553,22 +2657,36 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column)
Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const
{
Q_D(const QSortFilterProxyModel);
- return d->filter_data.patternOptions() & QRegularExpression::CaseInsensitiveOption ?
- Qt::CaseInsensitive : Qt::CaseSensitive;
+ return d->filter_casesensitive;
}
void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
{
Q_D(QSortFilterProxyModel);
- QRegularExpression::PatternOptions o = QRegularExpression::NoPatternOption;
- if (cs == Qt::CaseInsensitive)
- o = QRegularExpression::CaseInsensitiveOption;
- if (o == d->filter_data.patternOptions())
+ d->filter_casesensitive.removeBindingUnlessInWrapper();
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
+ if (cs == d->filter_casesensitive)
return;
+
+ const QScopedPropertyUpdateGroup guard;
+ QRegularExpression::PatternOptions options =
+ d->filter_regularexpression.value().patternOptions();
+ options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseInsensitive);
+ d->filter_casesensitive.setValueBypassingBindings(cs);
+
d->filter_about_to_be_changed();
- d->filter_data.setPatternOptions(o);
+ QRegularExpression re = d->filter_regularexpression;
+ re.setPatternOptions(options);
+ d->filter_regularexpression.setValueBypassingBindings(re);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
- emit filterCaseSensitivityChanged(cs);
+ d->filter_regularexpression.notify();
+ d->filter_casesensitive.notify();
+}
+
+QBindable<Qt::CaseSensitivity> QSortFilterProxyModel::bindableFilterCaseSensitivity()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<Qt::CaseSensitivity>(&d->filter_casesensitive);
}
/*!
@@ -2596,12 +2714,19 @@ Qt::CaseSensitivity QSortFilterProxyModel::sortCaseSensitivity() const
void QSortFilterProxyModel::setSortCaseSensitivity(Qt::CaseSensitivity cs)
{
Q_D(QSortFilterProxyModel);
+ d->sort_casesensitivity.removeBindingUnlessInWrapper();
if (d->sort_casesensitivity == cs)
return;
- d->sort_casesensitivity = cs;
+ d->sort_casesensitivity.setValueBypassingBindings(cs);
d->sort();
- emit sortCaseSensitivityChanged(cs);
+ d->sort_casesensitivity.notify(); // also emits a signal
+}
+
+QBindable<Qt::CaseSensitivity> QSortFilterProxyModel::bindableSortCaseSensitivity()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<Qt::CaseSensitivity>(&d->sort_casesensitivity);
}
/*!
@@ -2629,15 +2754,21 @@ bool QSortFilterProxyModel::isSortLocaleAware() const
void QSortFilterProxyModel::setSortLocaleAware(bool on)
{
Q_D(QSortFilterProxyModel);
+ d->sort_localeaware.removeBindingUnlessInWrapper();
if (d->sort_localeaware == on)
return;
- d->sort_localeaware = on;
+ d->sort_localeaware.setValueBypassingBindings(on);
d->sort();
- emit sortLocaleAwareChanged(on);
+ d->sort_localeaware.notify(); // also emits a signal
+}
+
+QBindable<bool> QSortFilterProxyModel::bindableIsSortLocaleAware()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<bool>(&d->sort_localeaware);
}
-#if QT_CONFIG(regularexpression)
/*!
\since 5.12
@@ -2647,45 +2778,70 @@ void QSortFilterProxyModel::setSortLocaleAware(bool on)
This method should be preferred for new code as it will use
QRegularExpression internally.
+ This method will reset the regular expression options
+ but respect case sensitivity.
+
+ \note Calling this method updates the regular expression, thereby breaking
+ the binding for \l filterRegularExpression. However it has no effect on the
+ \l filterCaseSensitivity bindings.
+
\sa setFilterCaseSensitivity(), setFilterWildcard(), setFilterFixedString(), filterRegularExpression()
*/
void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
- QRegularExpression rx(pattern);
- d->filter_data.setPattern(pattern);
+ d->set_filter_pattern(pattern);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ d->filter_regularexpression.notify();
}
-#endif
/*!
Sets the wildcard expression used to filter the contents
of the source model to the given \a pattern.
+ This method will reset the regular expression options
+ but respect case sensitivity.
+
+ \note Calling this method updates the regular expression, thereby breaking
+ the binding for \l filterRegularExpression. However it has no effect on the
+ \l filterCaseSensitivity bindings.
+
\sa setFilterCaseSensitivity(), setFilterRegularExpression(), setFilterFixedString(), filterRegularExpression()
*/
void QSortFilterProxyModel::setFilterWildcard(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
- QString p = QRegularExpression::wildcardToRegularExpression(pattern, QRegularExpression::UnanchoredWildcardConversion);
- d->filter_data.setPattern(p);
+ d->set_filter_pattern(QRegularExpression::wildcardToRegularExpression(
+ pattern, QRegularExpression::UnanchoredWildcardConversion));
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ d->filter_regularexpression.notify();
}
/*!
Sets the fixed string used to filter the contents
of the source model to the given \a pattern.
+ This method will reset the regular expression options
+ but respect case sensitivity.
+
+ \note Calling this method updates the regular expression, thereby breaking
+ the binding for \l filterRegularExpression. However it has no effect on the
+ \l filterCaseSensitivity bindings.
+
\sa setFilterCaseSensitivity(), setFilterRegularExpression(), setFilterWildcard(), filterRegularExpression()
*/
void QSortFilterProxyModel::setFilterFixedString(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
- d->filter_data.setPattern(QRegularExpression::escape(pattern));
+ d->set_filter_pattern(QRegularExpression::escape(pattern));
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ d->filter_regularexpression.notify();
}
/*!
@@ -2703,6 +2859,8 @@ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern)
QComboBox.
The default value is true.
+
+ \sa sortColumn()
*/
bool QSortFilterProxyModel::dynamicSortFilter() const
{
@@ -2712,10 +2870,25 @@ bool QSortFilterProxyModel::dynamicSortFilter() const
void QSortFilterProxyModel::setDynamicSortFilter(bool enable)
{
+ // While introducing new bindable properties, we still update the value
+ // unconditionally (even if it didn't really change), and call the
+ // sort() method, so that we do not break any code.
+ // However we do notify the observing bindings only if the value has
+ // actually changed.
Q_D(QSortFilterProxyModel);
- d->dynamic_sortfilter = enable;
+ d->dynamic_sortfilter.removeBindingUnlessInWrapper();
+ const bool valueChanged = d->dynamic_sortfilter.value() != enable;
+ d->dynamic_sortfilter.setValueBypassingBindings(enable);
if (enable)
d->sort();
+ if (valueChanged)
+ d->dynamic_sortfilter.notify();
+}
+
+QBindable<bool> QSortFilterProxyModel::bindableDynamicSortFilter()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<bool>(&d->dynamic_sortfilter);
}
/*!
@@ -2743,11 +2916,18 @@ int QSortFilterProxyModel::sortRole() const
void QSortFilterProxyModel::setSortRole(int role)
{
Q_D(QSortFilterProxyModel);
- if (d->sort_role == role)
+ d->sort_role.removeBindingUnlessInWrapper();
+ if (d->sort_role.valueBypassingBindings() == role)
return;
- d->sort_role = role;
+ d->sort_role.setValueBypassingBindings(role);
d->sort();
- emit sortRoleChanged(role);
+ d->sort_role.notify(); // also emits a signal
+}
+
+QBindable<int> QSortFilterProxyModel::bindableSortRole()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<int>(&d->sort_role);
}
/*!
@@ -2775,12 +2955,19 @@ int QSortFilterProxyModel::filterRole() const
void QSortFilterProxyModel::setFilterRole(int role)
{
Q_D(QSortFilterProxyModel);
- if (d->filter_role == role)
+ d->filter_role.removeBindingUnlessInWrapper();
+ if (d->filter_role.valueBypassingBindings() == role)
return;
d->filter_about_to_be_changed();
- d->filter_role = role;
+ d->filter_role.setValueBypassingBindings(role);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
- emit filterRoleChanged(role);
+ d->filter_role.notify(); // also emits a signal
+}
+
+QBindable<int> QSortFilterProxyModel::bindableFilterRole()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<int>(&d->filter_role);
}
/*!
@@ -2810,12 +2997,19 @@ bool QSortFilterProxyModel::isRecursiveFilteringEnabled() const
void QSortFilterProxyModel::setRecursiveFilteringEnabled(bool recursive)
{
Q_D(QSortFilterProxyModel);
+ d->filter_recursive.removeBindingUnlessInWrapper();
if (d->filter_recursive == recursive)
return;
d->filter_about_to_be_changed();
- d->filter_recursive = recursive;
+ d->filter_recursive.setValueBypassingBindings(recursive);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
- emit recursiveFilteringEnabledChanged(recursive);
+ d->filter_recursive.notify(); // also emits a signal
+}
+
+QBindable<bool> QSortFilterProxyModel::bindableRecursiveFilteringEnabled()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<bool>(&d->filter_recursive);
}
/*!
@@ -2832,7 +3026,8 @@ void QSortFilterProxyModel::setRecursiveFilteringEnabled(bool recursive)
/*!
\since 6.0
- \fn void QSortFilterProxyModel::showMatchesChildrenChanged(bool autoAcceptChildRows)
+ \fn void QSortFilterProxyModel::autoAcceptChildRowsChanged(bool autoAcceptChildRows)
+
\brief This signals is emitted when the value of the \a autoAcceptChildRows property is changed.
\sa autoAcceptChildRows
@@ -2846,13 +3041,20 @@ bool QSortFilterProxyModel::autoAcceptChildRows() const
void QSortFilterProxyModel::setAutoAcceptChildRows(bool accept)
{
Q_D(QSortFilterProxyModel);
+ d->accept_children.removeBindingUnlessInWrapper();
if (d->accept_children == accept)
return;
d->filter_about_to_be_changed();
- d->accept_children = accept;
+ d->accept_children.setValueBypassingBindings(accept);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
- emit autoAcceptChildRowsChanged(accept);
+ d->accept_children.notify(); // also emits a signal
+}
+
+QBindable<bool> QSortFilterProxyModel::bindableAutoAcceptChildRows()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<bool>(&d->accept_children);
}
/*!
@@ -2995,23 +3197,25 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
{
Q_D(const QSortFilterProxyModel);
- if (d->filter_data.pattern().isEmpty())
+ if (d->filter_regularexpression.value().pattern().isEmpty())
return true;
+
+ int column_count = d->model->columnCount(source_parent);
if (d->filter_column == -1) {
- int column_count = d->model->columnCount(source_parent);
for (int column = 0; column < column_count; ++column) {
QModelIndex source_index = d->model->index(source_row, column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
- if (d->filter_data.match(key).hasMatch())
+ if (key.contains(d->filter_regularexpression.value()))
return true;
}
return false;
}
- QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
- if (!source_index.isValid()) // the column may not exist
+
+ if (d->filter_column >= column_count) // the column may not exist
return true;
+ QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
- return d->filter_data.match(key).hasMatch();
+ return key.contains(d->filter_regularexpression.value());
}
/*!
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index d2c5054351..9d5b2fac9f 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -1,50 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSORTFILTERPROXYMODEL_H
#define QSORTFILTERPROXYMODEL_H
#include <QtCore/qabstractproxymodel.h>
-#if QT_CONFIG(regularexpression)
-# include <QtCore/qregularexpression.h>
-#endif
+#include <QtCore/qregularexpression.h>
QT_REQUIRE_CONFIG(sortfilterproxymodel);
@@ -61,18 +23,29 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
friend class QSortFilterProxyModelGreaterThan;
Q_OBJECT
-#if QT_CONFIG(regularexpression)
- Q_PROPERTY(QRegularExpression filterRegularExpression READ filterRegularExpression WRITE setFilterRegularExpression)
-#endif
- Q_PROPERTY(int filterKeyColumn READ filterKeyColumn WRITE setFilterKeyColumn)
- Q_PROPERTY(bool dynamicSortFilter READ dynamicSortFilter WRITE setDynamicSortFilter)
- Q_PROPERTY(Qt::CaseSensitivity filterCaseSensitivity READ filterCaseSensitivity WRITE setFilterCaseSensitivity NOTIFY filterCaseSensitivityChanged)
- Q_PROPERTY(Qt::CaseSensitivity sortCaseSensitivity READ sortCaseSensitivity WRITE setSortCaseSensitivity NOTIFY sortCaseSensitivityChanged)
- Q_PROPERTY(bool isSortLocaleAware READ isSortLocaleAware WRITE setSortLocaleAware NOTIFY sortLocaleAwareChanged)
- Q_PROPERTY(int sortRole READ sortRole WRITE setSortRole NOTIFY sortRoleChanged)
- Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole NOTIFY filterRoleChanged)
- Q_PROPERTY(bool recursiveFilteringEnabled READ isRecursiveFilteringEnabled WRITE setRecursiveFilteringEnabled NOTIFY recursiveFilteringEnabledChanged)
- Q_PROPERTY(bool autoAcceptChildRows READ autoAcceptChildRows WRITE setAutoAcceptChildRows NOTIFY autoAcceptChildRowsChanged)
+ Q_PROPERTY(QRegularExpression filterRegularExpression READ filterRegularExpression
+ WRITE setFilterRegularExpression BINDABLE bindableFilterRegularExpression)
+ Q_PROPERTY(int filterKeyColumn READ filterKeyColumn WRITE setFilterKeyColumn
+ BINDABLE bindableFilterKeyColumn)
+ Q_PROPERTY(bool dynamicSortFilter READ dynamicSortFilter WRITE setDynamicSortFilter
+ BINDABLE bindableDynamicSortFilter)
+ Q_PROPERTY(Qt::CaseSensitivity filterCaseSensitivity READ filterCaseSensitivity
+ WRITE setFilterCaseSensitivity NOTIFY filterCaseSensitivityChanged
+ BINDABLE bindableFilterCaseSensitivity)
+ Q_PROPERTY(Qt::CaseSensitivity sortCaseSensitivity READ sortCaseSensitivity
+ WRITE setSortCaseSensitivity NOTIFY sortCaseSensitivityChanged
+ BINDABLE bindableSortCaseSensitivity)
+ Q_PROPERTY(bool isSortLocaleAware READ isSortLocaleAware WRITE setSortLocaleAware
+ NOTIFY sortLocaleAwareChanged BINDABLE bindableIsSortLocaleAware)
+ Q_PROPERTY(int sortRole READ sortRole WRITE setSortRole NOTIFY sortRoleChanged
+ BINDABLE bindableSortRole)
+ Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole NOTIFY filterRoleChanged
+ BINDABLE bindableFilterRole)
+ Q_PROPERTY(bool recursiveFilteringEnabled READ isRecursiveFilteringEnabled
+ WRITE setRecursiveFilteringEnabled NOTIFY recursiveFilteringEnabledChanged
+ BINDABLE bindableRecursiveFilteringEnabled)
+ Q_PROPERTY(bool autoAcceptChildRows READ autoAcceptChildRows WRITE setAutoAcceptChildRows
+ NOTIFY autoAcceptChildRowsChanged BINDABLE bindableAutoAcceptChildRows)
public:
explicit QSortFilterProxyModel(QObject *parent = nullptr);
@@ -86,45 +59,51 @@ public:
QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const override;
QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const override;
-#if QT_CONFIG(regularexpression)
QRegularExpression filterRegularExpression() const;
-#endif
+ QBindable<QRegularExpression> bindableFilterRegularExpression();
int filterKeyColumn() const;
void setFilterKeyColumn(int column);
+ QBindable<int> bindableFilterKeyColumn();
Qt::CaseSensitivity filterCaseSensitivity() const;
void setFilterCaseSensitivity(Qt::CaseSensitivity cs);
+ QBindable<Qt::CaseSensitivity> bindableFilterCaseSensitivity();
Qt::CaseSensitivity sortCaseSensitivity() const;
void setSortCaseSensitivity(Qt::CaseSensitivity cs);
+ QBindable<Qt::CaseSensitivity> bindableSortCaseSensitivity();
bool isSortLocaleAware() const;
void setSortLocaleAware(bool on);
+ QBindable<bool> bindableIsSortLocaleAware();
int sortColumn() const;
Qt::SortOrder sortOrder() const;
bool dynamicSortFilter() const;
void setDynamicSortFilter(bool enable);
+ QBindable<bool> bindableDynamicSortFilter();
int sortRole() const;
void setSortRole(int role);
+ QBindable<int> bindableSortRole();
int filterRole() const;
void setFilterRole(int role);
+ QBindable<int> bindableFilterRole();
bool isRecursiveFilteringEnabled() const;
void setRecursiveFilteringEnabled(bool recursive);
+ QBindable<bool> bindableRecursiveFilteringEnabled();
bool autoAcceptChildRows() const;
void setAutoAcceptChildRows(bool accept);
+ QBindable<bool> bindableAutoAcceptChildRows();
public Q_SLOTS:
-#if QT_CONFIG(regularexpression)
void setFilterRegularExpression(const QString &pattern);
void setFilterRegularExpression(const QRegularExpression &regularExpression);
-#endif
void setFilterWildcard(const QString &pattern);
void setFilterFixedString(const QString &pattern);
void invalidate();
@@ -193,28 +172,6 @@ Q_SIGNALS:
private:
Q_DECLARE_PRIVATE(QSortFilterProxyModel)
Q_DISABLE_COPY(QSortFilterProxyModel)
-
- Q_PRIVATE_SLOT(d_func(),
- void _q_sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right,
- const QList<int> &roles))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceAboutToBeReset())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceReset())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))
- Q_PRIVATE_SLOT(d_func(), void _q_clearMapping())
};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp
index 829d4cf3ed..dfbe72b289 100644
--- a/src/corelib/itemmodels/qstringlistmodel.cpp
+++ b/src/corelib/itemmodels/qstringlistmodel.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
A simple model that uses a QStringList as its data source.
@@ -44,6 +8,7 @@
#include "qstringlistmodel.h"
#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
#include <algorithm>
@@ -121,7 +86,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const
if (parent.isValid())
return 0;
- return lst.count();
+ return lst.size();
}
/*!
@@ -129,7 +94,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const
*/
QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &idx) const
{
- if (!idx.isValid() || column != 0 || row >= lst.count() || row < 0)
+ if (!idx.isValid() || column != 0 || row >= lst.size() || row < 0)
return QModelIndex();
return createIndex(row, 0);
@@ -327,12 +292,12 @@ bool QStringListModel::moveRows(const QModelIndex &sourceParent, int sourceRow,
return true;
}
-static bool ascendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2)
+static bool ascendingLessThan(const std::pair<QString, int> &s1, const std::pair<QString, int> &s2)
{
return s1.first < s2.first;
}
-static bool decendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2)
+static bool decendingLessThan(const std::pair<QString, int> &s1, const std::pair<QString, int> &s2)
{
return s1.first > s2.first;
}
@@ -344,11 +309,11 @@ void QStringListModel::sort(int, Qt::SortOrder order)
{
emit layoutAboutToBeChanged(QList<QPersistentModelIndex>(), VerticalSortHint);
- QList<QPair<QString, int>> list;
- const int lstCount = lst.count();
+ QList<std::pair<QString, int>> list;
+ const int lstCount = lst.size();
list.reserve(lstCount);
for (int i = 0; i < lstCount; ++i)
- list.append(QPair<QString, int>(lst.at(i), i));
+ list.emplace_back(lst.at(i), i);
if (order == Qt::AscendingOrder)
std::sort(list.begin(), list.end(), ascendingLessThan);
@@ -364,7 +329,7 @@ void QStringListModel::sort(int, Qt::SortOrder order)
QModelIndexList oldList = persistentIndexList();
QModelIndexList newList;
- const int numOldIndexes = oldList.count();
+ const int numOldIndexes = oldList.size();
newList.reserve(numOldIndexes);
for (int i = 0; i < numOldIndexes; ++i)
newList.append(index(forwarding.at(oldList.at(i).row()), 0));
diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h
index fb53c19f09..b93a9c7173 100644
--- a/src/corelib/itemmodels/qstringlistmodel.h
+++ b/src/corelib/itemmodels/qstringlistmodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGLISTMODEL_H
#define QSTRINGLISTMODEL_H
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp
index c72128fa7d..621b54782e 100644
--- a/src/corelib/itemmodels/qtransposeproxymodel.cpp
+++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtransposeproxymodel.h"
#include <private/qtransposeproxymodel_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qsize.h>
+#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
@@ -49,9 +14,8 @@ QModelIndex QTransposeProxyModelPrivate::uncheckedMapToSource(const QModelIndex
{
if (!model || !proxyIndex.isValid())
return QModelIndex();
- if (proxyIndex.internalPointer())
- return model->createIndex(proxyIndex.column(), proxyIndex.row(), proxyIndex.internalPointer());
- return model->index(proxyIndex.column(), proxyIndex.row());
+ Q_Q(const QTransposeProxyModel);
+ return q->createSourceIndex(proxyIndex.column(), proxyIndex.row(), proxyIndex.internalPointer());
}
QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelIndex &sourceIndex) const
@@ -65,9 +29,10 @@ QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelInde
void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QTransposeProxyModel);
+ Q_ASSERT(layoutChangeProxyIndexes.size() == layoutChangePersistentIndexes.size());
QModelIndexList toList;
toList.reserve(layoutChangePersistentIndexes.size());
- for (const QPersistentModelIndex &persistIdx : qAsConst(layoutChangePersistentIndexes))
+ for (const QPersistentModelIndex &persistIdx : std::as_const(layoutChangePersistentIndexes))
toList << q->mapFromSource(persistIdx);
q->changePersistentIndexList(layoutChangeProxyIndexes, toList);
layoutChangeProxyIndexes.clear();
@@ -84,9 +49,26 @@ void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIn
emit q->layoutChanged(proxyParents, proxyHint);
}
-void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QTransposeProxyModel);
+ QList<QPersistentModelIndex> proxyParents;
+ proxyParents.reserve(sourceParents.size());
+ for (const QPersistentModelIndex &parent : sourceParents) {
+ if (!parent.isValid()) {
+ proxyParents << QPersistentModelIndex();
+ continue;
+ }
+ const QModelIndex mappedParent = q->mapFromSource(parent);
+ Q_ASSERT(mappedParent.isValid());
+ proxyParents << mappedParent;
+ }
+ QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
+ if (hint == QAbstractItemModel::VerticalSortHint)
+ proxyHint = QAbstractItemModel::HorizontalSortHint;
+ else if (hint == QAbstractItemModel::HorizontalSortHint)
+ proxyHint = QAbstractItemModel::VerticalSortHint;
+ emit q->layoutAboutToBeChanged(proxyParents, proxyHint);
const QModelIndexList proxyPersistentIndexes = q->persistentIndexList();
layoutChangeProxyIndexes.clear();
layoutChangePersistentIndexes.clear();
@@ -99,16 +81,6 @@ void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersiste
Q_ASSERT(srcPersistentIndex.isValid());
layoutChangePersistentIndexes << srcPersistentIndex;
}
- QList<QPersistentModelIndex> proxyParents;
- proxyParents.reserve(parents.size());
- for (auto& srcParent : parents)
- proxyParents << q->mapFromSource(srcParent);
- QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
- if (hint == QAbstractItemModel::VerticalSortHint)
- proxyHint = QAbstractItemModel::HorizontalSortHint;
- else if (hint == QAbstractItemModel::HorizontalSortHint)
- proxyHint = QAbstractItemModel::VerticalSortHint;
- emit q->layoutAboutToBeChanged(proxyParents, proxyHint);
}
void QTransposeProxyModelPrivate::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
@@ -163,6 +135,7 @@ void QTransposeProxyModelPrivate::onRowsAboutToBeMoved(const QModelIndex &source
/*!
\since 5.13
\class QTransposeProxyModel
+ \inmodule QtCore
\brief This proxy transposes the source model.
This model will make the rows of the source model become columns of the proxy model and vice-versa.
@@ -199,7 +172,7 @@ void QTransposeProxyModel::setSourceModel(QAbstractItemModel* newSourceModel)
return;
beginResetModel();
if (d->model) {
- for (const QMetaObject::Connection& discIter : qAsConst(d->sourceConnections))
+ for (const QMetaObject::Connection& discIter : std::as_const(d->sourceConnections))
disconnect(discIter);
}
d->sourceConnections.clear();
@@ -440,8 +413,8 @@ bool QTransposeProxyModel::moveColumns(const QModelIndex &sourceParent, int sour
*/
void QTransposeProxyModel::sort(int column, Qt::SortOrder order)
{
- Q_UNUSED(column)
- Q_UNUSED(order)
+ Q_UNUSED(column);
+ Q_UNUSED(order);
return;
}
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.h b/src/corelib/itemmodels/qtransposeproxymodel.h
index 854a547fd4..67ce6f3bef 100644
--- a/src/corelib/itemmodels/qtransposeproxymodel.h
+++ b/src/corelib/itemmodels/qtransposeproxymodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRANSPOSEPROXYMODEL_H
#define QTRANSPOSEPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qtransposeproxymodel_p.h b/src/corelib/itemmodels/qtransposeproxymodel_p.h
index 8cee3d2288..2e0c09b95b 100644
--- a/src/corelib/itemmodels/qtransposeproxymodel_p.h
+++ b/src/corelib/itemmodels/qtransposeproxymodel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRANSPOSEPROXYMODEL_P_H
#define QTRANSPOSEPROXYMODEL_P_H
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
deleted file mode 100644
index fc48ef430e..0000000000
--- a/src/corelib/kernel/kernel.pri
+++ /dev/null
@@ -1,209 +0,0 @@
-# Qt core object module
-
-HEADERS += \
- kernel/qabstracteventdispatcher.h \
- kernel/qabstractnativeeventfilter.h \
- kernel/qbasictimer.h \
- kernel/qdeadlinetimer.h \
- kernel/qdeadlinetimer_p.h \
- kernel/qelapsedtimer.h \
- kernel/qeventloop.h \
- kernel/qpointer.h \
- kernel/qcorecmdlineargs_p.h \
- kernel/qcoreapplication.h \
- kernel/qcoreevent.h \
- kernel/qmetaobject.h \
- kernel/qmetatype.h \
- kernel/qmimedata.h \
- kernel/qobject.h \
- kernel/qobject_impl.h \
- kernel/qobjectdefs.h \
- kernel/qobjectdefs_impl.h \
- kernel/qsignalmapper.h \
- kernel/qsocketnotifier.h \
- kernel/qtimer.h \
- kernel/qtranslator.h \
- kernel/qtranslator_p.h \
- kernel/qvariant.h \
- kernel/qabstracteventdispatcher_p.h \
- kernel/qcoreapplication_p.h \
- kernel/qobjectcleanuphandler.h \
- kernel/qvariant_p.h \
- kernel/qmetaobject_p.h \
- kernel/qmetaobject_moc_p.h \
- kernel/qmetaobjectbuilder_p.h \
- kernel/qobject_p.h \
- kernel/qcoreglobaldata_p.h \
- kernel/qsharedmemory.h \
- kernel/qsharedmemory_p.h \
- kernel/qsystemsemaphore.h \
- kernel/qsystemsemaphore_p.h \
- kernel/qfunctions_p.h \
- kernel/qmath.h \
- kernel/qsystemerror_p.h \
- kernel/qmetatype_p.h \
- kernel/qmetatypeswitcher_p.h \
- kernel/qtestsupport_core.h \
- kernel/qproperty.h \
- kernel/qpropertyprivate.h \
- kernel/qproperty_p.h \
- kernel/qpropertybinding_p.h
-
-SOURCES += \
- kernel/qabstracteventdispatcher.cpp \
- kernel/qabstractnativeeventfilter.cpp \
- kernel/qbasictimer.cpp \
- kernel/qdeadlinetimer.cpp \
- kernel/qelapsedtimer.cpp \
- kernel/qeventloop.cpp \
- kernel/qcoreapplication.cpp \
- kernel/qcoreevent.cpp \
- kernel/qmetaobject.cpp \
- kernel/qmetatype.cpp \
- kernel/qmetaobjectbuilder.cpp \
- kernel/qmimedata.cpp \
- kernel/qobject.cpp \
- kernel/qobjectcleanuphandler.cpp \
- kernel/qsignalmapper.cpp \
- kernel/qsocketnotifier.cpp \
- kernel/qtimer.cpp \
- kernel/qtranslator.cpp \
- kernel/qvariant.cpp \
- kernel/qcoreglobaldata.cpp \
- kernel/qsharedmemory.cpp \
- kernel/qsystemsemaphore.cpp \
- kernel/qpointer.cpp \
- kernel/qmath.cpp \
- kernel/qsystemerror.cpp \
- kernel/qtestsupport_core.cpp \
- kernel/qproperty.cpp \
- kernel/qpropertybinding.cpp
-
-win32 {
- SOURCES += \
- kernel/qcoreapplication_win.cpp \
- kernel/qelapsedtimer_win.cpp \
- kernel/qwineventnotifier.cpp \
- kernel/qsharedmemory_win.cpp \
- kernel/qsystemsemaphore_win.cpp
- HEADERS += \
- kernel/qwineventnotifier.h \
- kernel/qwineventnotifier_p.h \
- kernel/qfunctions_winrt_p.h
-
- SOURCES += kernel/qeventdispatcher_win.cpp \
- kernel/qwinregistry.cpp
- HEADERS += kernel/qeventdispatcher_win_p.h \
- kernel/qwinregistry_p.h
-
- LIBS_PRIVATE += -lversion
-}
-
-mac {
- HEADERS += \
- kernel/qcfsocketnotifier_p.h \
- kernel/qcore_mac_p.h \
- kernel/qeventdispatcher_cf_p.h
-
- SOURCES += \
- kernel/qcfsocketnotifier.cpp \
- kernel/qcoreapplication_mac.cpp \
- kernel/qcore_foundation.mm \
- kernel/qcore_mac.mm \
- kernel/qeventdispatcher_cf.mm
-
- !nacl: SOURCES += kernel/qelapsedtimer_mac.cpp
-
- LIBS_PRIVATE += -framework Foundation
-
- osx: LIBS_PRIVATE += -framework CoreServices -framework AppKit -framework Security
-
- ios|tvos {
- # We need UIKit for UIApplication in qeventdispatcher_cf.mm
- LIBS_PRIVATE += -framework UIKit
- }
-
- watchos {
- # We need WatchKit for WKExtension in qeventdispatcher_cf.mm
- LIBS_PRIVATE += -framework WatchKit
- }
-}
-
-nacl {
- SOURCES += \
- kernel/qfunctions_nacl.cpp
- HEADERS += \
- kernel/qfunctions_nacl.h
-}
-
-unix|integrity {
- SOURCES += \
- kernel/qcore_unix.cpp \
- kernel/qeventdispatcher_unix.cpp \
- kernel/qtimerinfo_unix.cpp
- !darwin|nacl: SOURCES += kernel/qelapsedtimer_unix.cpp
-
- HEADERS += \
- kernel/qcore_unix_p.h \
- kernel/qeventdispatcher_unix_p.h \
- kernel/qpoll_p.h \
- kernel/qtimerinfo_unix_p.h
-
- qtConfig(poll_select): SOURCES += kernel/qpoll.cpp
-
- qtConfig(glib) {
- SOURCES += \
- kernel/qeventdispatcher_glib.cpp
- HEADERS += \
- kernel/qeventdispatcher_glib_p.h
- QMAKE_USE_PRIVATE += glib
- }
-
- qtConfig(clock-gettime): QMAKE_USE_PRIVATE += librt
-
- !android {
- SOURCES += kernel/qsharedmemory_posix.cpp \
- kernel/qsharedmemory_systemv.cpp \
- kernel/qsharedmemory_unix.cpp \
- kernel/qsystemsemaphore_posix.cpp \
- kernel/qsystemsemaphore_systemv.cpp \
- kernel/qsystemsemaphore_unix.cpp
- } else {
- SOURCES += kernel/qsharedmemory_android.cpp \
- kernel/qsystemsemaphore_android.cpp
- }
-
- # This is needed by QMetaType::typeName array implementation
- integrity: QMAKE_CXXFLAGS += --pending_instantiations=128
-}
-
-vxworks {
- SOURCES += \
- kernel/qfunctions_vxworks.cpp
- HEADERS += \
- kernel/qfunctions_vxworks.h
-}
-
-qnx:qtConfig(qqnx_pps) {
- QMAKE_USE_PRIVATE += pps
- SOURCES += \
- kernel/qppsattribute.cpp \
- kernel/qppsobject.cpp
- HEADERS += \
- kernel/qppsattribute_p.h \
- kernel/qppsattributeprivate_p.h \
- kernel/qppsobject_p.h \
- kernel/qppsobjectprivate_p.h
-}
-
-android:!android-embedded {
- SOURCES += \
- kernel/qjnionload.cpp \
- kernel/qjnihelpers.cpp \
- kernel/qjni.cpp
- HEADERS += \
- kernel/qjnihelpers_p.h \
- kernel/qjni_p.h
-}
-
-!darwin:!unix:!win32: SOURCES += kernel/qelapsedtimer_generic.cpp
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index b2bc199c8c..f3056a399c 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstracteventdispatcher.h"
#include "qabstracteventdispatcher_p.h"
@@ -45,9 +9,12 @@
#include <private/qthread_p.h>
#include <private/qcoreapplication_p.h>
#include <private/qfreelist_p.h>
+#include <private/qnumeric_p.h>
QT_BEGIN_NAMESPACE
+using namespace std::chrono_literals;
+
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
struct QtTimerIdFreeListConstants : public QFreeListDefaultConstants
{
@@ -68,15 +35,15 @@ enum {
Offset4 = 0x00010000,
Offset5 = 0x00100000,
- Size0 = Offset1 - Offset0,
- Size1 = Offset2 - Offset1,
- Size2 = Offset3 - Offset2,
- Size3 = Offset4 - Offset3,
- Size4 = Offset5 - Offset4,
+ Size0 = Offset1 - Offset0,
+ Size1 = Offset2 - Offset1,
+ Size2 = Offset3 - Offset2,
+ Size3 = Offset4 - Offset3,
+ Size4 = Offset5 - Offset4,
Size5 = QtTimerIdFreeListConstants::MaxIndex - Offset5
};
-const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCount] = {
+Q_CONSTINIT const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCount] = {
Size0,
Size1,
Size2,
@@ -88,6 +55,41 @@ const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCou
typedef QFreeList<void, QtTimerIdFreeListConstants> QtTimerIdFreeList;
Q_GLOBAL_STATIC(QtTimerIdFreeList, timerIdFreeList)
+template <typename T> static T fromDuration(std::chrono::nanoseconds interval)
+{
+ using namespace std::chrono;
+ qint64 value = ceil<milliseconds>(interval).count();
+ return qt_saturate<T>(value);
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+static inline QAbstractEventDispatcherV2 *v2(QAbstractEventDispatcher *self)
+{
+ if (QAbstractEventDispatcherPrivate::get(self)->isV2)
+ return static_cast<QAbstractEventDispatcherV2 *>(self);
+ return nullptr;
+}
+
+static inline const QAbstractEventDispatcherV2 *v2(const QAbstractEventDispatcher *self)
+{
+ if (QAbstractEventDispatcherPrivate::get(self)->isV2)
+ return static_cast<const QAbstractEventDispatcherV2 *>(self);
+ return nullptr;
+}
+#endif // Qt 7
+
+QAbstractEventDispatcherPrivate::QAbstractEventDispatcherPrivate()
+{
+ // Create the timer ID free list here to make sure that it is destroyed
+ // after any global static thread that may be using it.
+ // See also QTBUG-58732.
+ if (!timerIdFreeList.isDestroyed())
+ (void)timerIdFreeList();
+}
+
+QAbstractEventDispatcherPrivate::~QAbstractEventDispatcherPrivate()
+ = default;
+
int QAbstractEventDispatcherPrivate::allocateTimerId()
{
// This function may be called after timerIdFreeList() has been destructed
@@ -145,6 +147,15 @@ void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
\sa QEventLoop, QCoreApplication, QThread
*/
+/*!
+ \typedef QAbstractEventDispatcher::Duration
+
+ A \c{std::chrono::duration} type that is used in various API in this class.
+ This type exists to facilitate a possible transition to a higher or lower
+ granularity.
+
+ In all current platforms, it is \c nanoseconds.
+*/
/*!
Constructs a new event dispatcher with the given \a parent.
@@ -210,8 +221,6 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
\b{Note:} This function does not process events continuously; it
returns after all available events are processed.
-
- \sa hasPendingEvents()
*/
/*!
@@ -223,14 +232,6 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
events. For timers and system level events, the situation is unknown.
*/
-/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
- \deprecated
-
- Returns \c true if there is an event waiting; otherwise returns false. This
- function is an implementation detail for
- QCoreApplication::hasPendingEvents() and must not be called directly.
-*/
-
/*!
\fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
@@ -248,36 +249,41 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
*/
/*!
- \obsolete
-
- \fn int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
+ \obsolete [6.8] This function will be removed in Qt 7. Use the overload taking \l Duration.
- Registers a timer with the specified \a interval for the given \a object
- and returns the timer id.
+ Registers a timer with the specified \a interval and \a timerType for the
+ given \a object and returns the timer id.
*/
+int QAbstractEventDispatcher::registerTimer(qint64 interval, Qt::TimerType timerType, QObject *object)
+{
+ return int(registerTimer(interval * 1ms, timerType, object));
+}
/*!
- \obsolete
-
- \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, QObject *object)
+ \since 6.8
+ \overload
- Register a timer with the specified \a timerId and \a interval for the
- given \a object.
-*/
-
-/*!
Registers a timer with the specified \a interval and \a timerType for the
given \a object and returns the timer id.
*/
-int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerType, QObject *object)
+Qt::TimerId QAbstractEventDispatcher::registerTimer(Duration interval, Qt::TimerType timerType,
+ QObject *object)
{
- int id = QAbstractEventDispatcherPrivate::allocateTimerId();
+ auto id = Qt::TimerId(QAbstractEventDispatcherPrivate::allocateTimerId());
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ if (QAbstractEventDispatcherV2 *self = v2(this))
+ self->registerTimer(id, interval, timerType, object);
+ else
+ registerTimer(qToUnderlying(id), fromDuration<qint64>(interval), timerType, object);
+#else
registerTimer(id, interval, timerType, object);
+#endif
return id;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*!
- \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+ \fn void QAbstractEventDispatcher::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
Register a timer with the specified \a timerId, \a interval, and \a
timerType for the given \a object.
@@ -293,15 +299,6 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
*/
/*!
- \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
-
- Unregisters all the timers associated with the given \a object.
- Returns \c true if all timers were successful removed; otherwise returns \c false.
-
- \sa unregisterTimer(), registeredTimers()
-*/
-
-/*!
\fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
Returns a list of registered timers for \a object. The TimerInfo struct has
@@ -319,6 +316,57 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
\sa Qt::TimerType
*/
+#else // Qt 7
+/*!
+ \fn void QAbstractEventDispatcher::registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object)
+ \since 6.8
+
+ Register a timer with the specified \a timerId, \a interval, and \a
+ timerType for the given \a object.
+
+ \sa unregisterTimer(), timersForObject()
+*/
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimer(Qt::TimerId timerId)
+ \since 6.8
+
+ Unregisters the timer with the given \a timerId.
+ Returns \c true if successful; otherwise returns \c false.
+
+ \sa registerTimer(), unregisterTimers()
+*/
+
+/*!
+ \fn QList<TimerInfoV2> QAbstractEventDispatcher::timersForObject(QObject *object) const
+ \since 6.8
+
+ Returns a list of registered timers for \a object. The TimerInfoV2 struct has
+ \c timerId, \c interval, and \c timerType members.
+
+ \sa Qt::TimerType, registerTimer(), unregisterTimer()
+*/
+
+/*!
+ \fn QAbstractEventDispatcher::remainingTime(Qt::TimerId timerId) const
+
+ Returns the remaining time of the timer with the given \a timerId.
+ If the timer is inactive, the returned value will be negative. If the timer
+ is overdue, the returned value will be 0.
+
+ \sa Qt::TimerType, registerTimer(), unregisterTimer()
+*/
+#endif
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
+
+ Unregisters all the timers associated with the given \a object. Returns \c
+ true if all timers were successfully removed; otherwise returns \c false.
+
+ \sa unregisterTimer(), registeredTimers()
+*/
+
/*! \fn void QAbstractEventDispatcher::wakeUp()
\threadsafe
@@ -344,13 +392,6 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
return from processEvents() as soon as possible.
*/
-/*! \fn void QAbstractEventDispatcher::flush()
- \deprecated
-
- Depending from the event dispatcher implementation does nothing or
- calls QApplication::sendPostedEvents().
-*/
-
// ### DOC: Are these called when the _application_ starts/stops or just
// when the current _event loop_ starts/stops?
/*!
@@ -367,6 +408,7 @@ void QAbstractEventDispatcher::closingDown()
/*!
\class QAbstractEventDispatcher::TimerInfo
+ \deprecated [6.8] Use TimerInfoV2
\inmodule QtCore
This struct represents information about a timer:
@@ -374,7 +416,7 @@ void QAbstractEventDispatcher::closingDown()
\l{QAbstractEventDispatcher::TimerInfo::interval}{interval}, and
\l{QAbstractEventDispatcher::TimerInfo::timerType}{timerType}.
- \sa registeredTimers()
+ \sa registeredTimers(), QAbstractEventDispatcher::TimerInfoV2, timersForObject()
*/
/*! \fn QAbstractEventDispatcher::TimerInfo::TimerInfo(int timerId, int interval, Qt::TimerType timerType)
@@ -400,6 +442,37 @@ void QAbstractEventDispatcher::closingDown()
*/
/*!
+ \class QAbstractEventDispatcher::TimerInfoV2
+ \inmodule QtCore
+
+ This struct represents information about a timer:
+ \l{QAbstractEventDispatcher::TimerInfoV2::timerId}{timerId},
+ \l{QAbstractEventDispatcher::TimerInfoV2::interval}{interval}, and
+ \l{QAbstractEventDispatcher::TimerInfoV2::timerType}{timerType}.
+
+ \sa timersForObject()
+*/
+/*!
+ \variable QAbstractEventDispatcher::TimerInfoV2::timerId
+
+ The timer's unique id. This is created by registerTimer() upon creation and
+ uniquely identifies a timer while it is active. It is also used by
+ QTimer::id() and returned by QObject::startTimer().
+*/
+/*!
+ \variable QAbstractEventDispatcher::TimerInfoV2::interval
+
+ The timer's interval.
+*/
+/*!
+ \variable QAbstractEventDispatcher::TimerInfoV2::timerType
+
+ The timer's type
+
+ \sa Qt::TimerType
+*/
+
+/*!
Installs an event filter \a filterObj for all native events received by the application.
The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
@@ -429,7 +502,7 @@ void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilt
Q_D(QAbstractEventDispatcher);
// clean up unused items in the list
- d->eventFilters.removeAll(0);
+ d->eventFilters.removeAll(nullptr);
d->eventFilters.removeAll(filterObj);
d->eventFilters.prepend(filterObj);
}
@@ -450,9 +523,9 @@ void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilt
void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilter *filter)
{
Q_D(QAbstractEventDispatcher);
- for (int i = 0; i < d->eventFilters.count(); ++i) {
+ for (int i = 0; i < d->eventFilters.size(); ++i) {
if (d->eventFilters.at(i) == filter) {
- d->eventFilters[i] = 0;
+ d->eventFilters[i] = nullptr;
break;
}
}
@@ -477,17 +550,13 @@ void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilte
\sa installNativeEventFilter(), QAbstractNativeEventFilter::nativeEventFilter()
\since 5.0
*/
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
-#else
-bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result)
-#endif
{
Q_D(QAbstractEventDispatcher);
if (!d->eventFilters.isEmpty()) {
// Raise the loopLevel so that deleteLater() calls in or triggered
// by event_filter() will be processed from the main event loop.
- QScopedScopeLevelCounter scopeLevelCounter(d->threadData);
+ QScopedScopeLevelCounter scopeLevelCounter(d->threadData.loadAcquire());
for (int i = 0; i < d->eventFilters.size(); ++i) {
QAbstractNativeEventFilter *filter = d->eventFilters.at(i);
if (!filter)
@@ -499,54 +568,141 @@ bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, vo
return false;
}
-/*! \fn bool QAbstractEventDispatcher::filterEvent(void *message)
- \deprecated
+/*! \fn void QAbstractEventDispatcher::awake()
- Calls filterNativeEvent() with an empty eventType and \a message.
- This function returns \c true as soon as an
- event filter returns \c true, and false otherwise to indicate that
- the processing of the event should continue.
+ This signal is emitted after the event loop returns from a
+ function that could block.
+
+ \sa wakeUp(), aboutToBlock()
*/
-/*! \fn bool QAbstractEventDispatcher::registerEventNotifier(QWinEventNotifier *notifier)
+/*! \fn void QAbstractEventDispatcher::aboutToBlock()
+
+ This signal is emitted before the event loop calls a function that
+ could block.
- This pure virtual method exists on windows only and has to be reimplemented by a Windows specific
- event dispatcher implementation. \a notifier is the QWinEventNotifier instance to be registered.
+ \sa awake()
+*/
- The method should return true if the registration of \a notifier was successful, otherwise false.
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+void QAbstractEventDispatcher::registerTimer(Qt::TimerId timerId, Duration interval,
+ Qt::TimerType timerType, QObject *object)
+{
+ if (QAbstractEventDispatcherV2 *self = v2(this))
+ self->registerTimer(timerId, interval, timerType, object);
+ else
+ registerTimer(int(timerId), fromDuration<qint64>(interval), timerType, object);
+}
- QWinEventNotifier calls this method in it's constructor and there should never be a need to call this
- method directly.
+bool QAbstractEventDispatcher::unregisterTimer(Qt::TimerId timerId)
+{
+ if (QAbstractEventDispatcherV2 *self = v2(this))
+ return self->unregisterTimer(timerId);
+ return unregisterTimer(int(timerId));
+}
- \sa QWinEventNotifier, unregisterEventNotifier()
-*/
+QList<QAbstractEventDispatcher::TimerInfoV2>
+QAbstractEventDispatcher::timersForObject(QObject *object) const
+{
+ if (const QAbstractEventDispatcherV2 *self = v2(this))
+ return self->timersForObject(object);
+ QList<TimerInfo> timers = registeredTimers(object);
+ QList<TimerInfoV2> result;
+ result.reserve(timers.size());
+ for (const TimerInfo &t : timers)
+ result.emplaceBack(TimerInfoV2{ t.interval * 1ms, Qt::TimerId(t.timerId), t.timerType });
+ return result;
+}
-/*! \fn bool QAbstractEventDispatcher::unregisterEventNotifier(QWinEventNotifier *notifier)
+QAbstractEventDispatcher::Duration
+QAbstractEventDispatcher::remainingTime(Qt::TimerId timerId) const
+{
+ if (const QAbstractEventDispatcherV2 *self = v2(this))
+ return self->remainingTime(timerId);
+ return const_cast<QAbstractEventDispatcher *>(this)->remainingTime(int(timerId)) * 1ms;
+}
- This pure virtual method exists on windows only and has to be reimplemented by a Windows specific
- event dispatcher implementation. \a notifier is the QWinEventNotifier instance to be unregistered.
+/*!
+ \class QAbstractEventDispatcherV2
+ \inmodule QtCore
- QWinEventNotifier calls this method in it's destructor and there should never be a need to call this
- method directly.
+ This class is a temporary hack to enable transition to an API based on
+ \c{std::chrono} for the Qt event dispatcher. In Qt 7, it will be merged
+ with QAbstractEventDispatcher, replacing the pure virtuals there with the
+ ones defined here.
- \sa QWinEventNotifier, registerEventNotifier()
+ It is recommended applications and libraries port to the new API before
+ that future release to simplify work when the time comes.
*/
-/*! \fn void QAbstractEventDispatcher::awake()
+/*!
+ Constructs a new event dispatcher with the given \a parent.
+*/
+QAbstractEventDispatcherV2::QAbstractEventDispatcherV2(QObject *parent)
+ : QAbstractEventDispatcherV2(*new QAbstractEventDispatcherPrivate, parent)
+{
+}
- This signal is emitted after the event loop returns from a
- function that could block.
+/*!
+ \internal
+*/
+QAbstractEventDispatcherV2::QAbstractEventDispatcherV2(QAbstractEventDispatcherPrivate &dd,
+ QObject *parent)
+ : QAbstractEventDispatcher((dd.isV2 = true, dd), parent)
+{
+}
- \sa wakeUp(), aboutToBlock()
+/*!
+ Destroys the event dispatcher.
*/
+QAbstractEventDispatcherV2::~QAbstractEventDispatcherV2() = default;
-/*! \fn void QAbstractEventDispatcher::aboutToBlock()
+/*!
+ \internal
+ Temporary compatibility override.
+*/
+void QAbstractEventDispatcherV2::registerTimer(int timerId, qint64 interval,
+ Qt::TimerType timerType, QObject *object)
+{
+ auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
+ self->registerTimer(Qt::TimerId(timerId), interval * 1ms, timerType, object);
+}
- This signal is emitted before the event loop calls a function that
- could block.
+/*!
+ \internal
+ Temporary compatibility override.
+*/
+bool QAbstractEventDispatcherV2::unregisterTimer(int timerId)
+{
+ auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
+ return self->unregisterTimer(Qt::TimerId(timerId));
+}
- \sa awake()
+/*!
+ \internal
+ Temporary compatibility override.
+*/
+auto QAbstractEventDispatcherV2::registeredTimers(QObject *object) const -> QList<TimerInfo>
+{
+ auto self = static_cast<const QAbstractEventDispatcherV2 *>(this);
+ QList<TimerInfoV2> timers = self->timersForObject(object);
+ QList<TimerInfo> result;
+ result.reserve(timers.size());
+ for (const TimerInfoV2 &t : timers)
+ result.emplaceBack(qToUnderlying(t.timerId), fromDuration<int>(t.interval), t.timerType);
+ return result;
+}
+
+/*!
+ \internal
+ Temporary compatibility override.
*/
+int QAbstractEventDispatcherV2::remainingTime(int timerId)
+{
+ auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
+ return fromDuration<int>(self->remainingTime(Qt::TimerId(timerId)));
+}
+#endif // ! Qt 7
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
index 4ef9c068df..ad97a93ba2 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.h
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTEVENTDISPATCHER_H
#define QABSTRACTEVENTDISPATCHER_H
@@ -49,16 +13,13 @@ class QAbstractNativeEventFilter;
class QAbstractEventDispatcherPrivate;
class QSocketNotifier;
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
-class QWinEventNotifier;
-#endif
-
class Q_CORE_EXPORT QAbstractEventDispatcher : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QAbstractEventDispatcher)
public:
+ using Duration = std::chrono::nanoseconds;
struct TimerInfo
{
int timerId;
@@ -66,8 +27,13 @@ public:
Qt::TimerType timerType;
inline TimerInfo(int id, int i, Qt::TimerType t)
- : timerId(id), interval(i), timerType(t)
- { }
+ : timerId(id), interval(i), timerType(t) { }
+ };
+ struct TimerInfoV2
+ {
+ Duration interval;
+ Qt::TimerId timerId;
+ Qt::TimerType timerType;
};
explicit QAbstractEventDispatcher(QObject *parent = nullptr);
@@ -76,49 +42,42 @@ public:
static QAbstractEventDispatcher *instance(QThread *thread = nullptr);
virtual bool processEvents(QEventLoop::ProcessEventsFlags flags) = 0;
- virtual bool hasPendingEvents() = 0; // ### Qt6: remove, mark final or make protected
virtual void registerSocketNotifier(QSocketNotifier *notifier) = 0;
virtual void unregisterSocketNotifier(QSocketNotifier *notifier) = 0;
-#if QT_DEPRECATED_SINCE(5,0)
- QT_DEPRECATED inline int registerTimer(int interval, QObject *object)
- { return registerTimer(interval, Qt::CoarseTimer, object); }
- QT_DEPRECATED inline void registerTimer(int timerId, int interval, QObject *object)
- { registerTimer(timerId, interval, Qt::CoarseTimer, object); }
-#endif
- // ### Qt6: change interval range to qint64 (or use QDeadlineTimer)
- int registerTimer(int interval, Qt::TimerType timerType, QObject *object);
- virtual void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) = 0;
+ Qt::TimerId registerTimer(Duration interval, Qt::TimerType timerType, QObject *object);
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ int registerTimer(qint64 interval, Qt::TimerType timerType, QObject *object);
+
+ // old, integer-based API
+ virtual void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object) = 0;
virtual bool unregisterTimer(int timerId) = 0;
- virtual bool unregisterTimers(QObject *object) = 0;
virtual QList<TimerInfo> registeredTimers(QObject *object) const = 0;
-
virtual int remainingTime(int timerId) = 0;
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
- virtual bool registerEventNotifier(QWinEventNotifier *notifier) = 0;
- virtual void unregisterEventNotifier(QWinEventNotifier *notifier) = 0;
+ void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object);
+ bool unregisterTimer(Qt::TimerId timerId);
+ QList<TimerInfoV2> timersForObject(QObject *object) const;
+ Duration remainingTime(Qt::TimerId timerId) const;
+#else
+ virtual void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object) = 0;
+ virtual bool unregisterTimer(Qt::TimerId timerId) = 0;
+ virtual QList<TimerInfoV2> timersForObject(QObject *object) const = 0;
+ virtual Duration remainingTime(Qt::TimerId timerId) const = 0;
#endif
+ virtual bool unregisterTimers(QObject *object) = 0;
virtual void wakeUp() = 0;
virtual void interrupt() = 0;
- virtual void flush() = 0; // ### Qt6: remove, mark final or make protected
virtual void startingUp();
virtual void closingDown();
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj);
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj);
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result);
-#else
- bool filterNativeEvent(const QByteArray &eventType, void *message, long *result);
-#endif
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED bool filterEvent(void *message)
- { return filterNativeEvent("", message, nullptr); }
-#endif
Q_SIGNALS:
void aboutToBlock();
@@ -129,7 +88,41 @@ protected:
QObject *parent);
};
-Q_DECLARE_TYPEINFO(QAbstractEventDispatcher::TimerInfo, (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) ? Q_PRIMITIVE_TYPE : Q_RELOCATABLE_TYPE));
+Q_DECLARE_TYPEINFO(QAbstractEventDispatcher::TimerInfo, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QAbstractEventDispatcher::TimerInfoV2, Q_PRIMITIVE_TYPE);
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+class Q_CORE_EXPORT QAbstractEventDispatcherV2 : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAbstractEventDispatcher) // not V2
+
+public:
+ explicit QAbstractEventDispatcherV2(QObject *parent = nullptr);
+ ~QAbstractEventDispatcherV2();
+
+ // new virtuals
+ virtual void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType,
+ QObject *object) = 0;
+ virtual bool unregisterTimer(Qt::TimerId timerId) = 0;
+ virtual QList<TimerInfoV2> timersForObject(QObject *object) const = 0;
+ virtual Duration remainingTime(Qt::TimerId timerId) const = 0;
+
+protected:
+ QAbstractEventDispatcherV2(QAbstractEventDispatcherPrivate &, QObject *parent);
+
+private:
+ // final overrides from V1
+ virtual void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType,
+ QObject *object) override final;
+ virtual bool unregisterTimer(int timerId) override final;
+ virtual QList<TimerInfo> registeredTimers(QObject *object) const override final;
+
+ virtual int remainingTime(int timerId) override final;
+};
+#else
+using QAbstractEventDispatcherV2 = QAbstractEventDispatcher;
+#endif // Qt 7
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstracteventdispatcher_p.h b/src/corelib/kernel/qabstracteventdispatcher_p.h
index 5679cae076..2576027d52 100644
--- a/src/corelib/kernel/qabstracteventdispatcher_p.h
+++ b/src/corelib/kernel/qabstracteventdispatcher_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTEVENTDISPATCHER_P_H
#define QABSTRACTEVENTDISPATCHER_P_H
@@ -52,23 +16,34 @@
//
#include "QtCore/qabstracteventdispatcher.h"
+#include "QtCore/qnamespace.h"
#include "private/qobject_p.h"
+#include "QtCore/qttypetraits.h"
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT uint qGlobalPostedEventsCount();
+Q_AUTOTEST_EXPORT qsizetype qGlobalPostedEventsCount();
class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QAbstractEventDispatcher)
public:
- inline QAbstractEventDispatcherPrivate()
- { }
+ QAbstractEventDispatcherPrivate();
+ ~QAbstractEventDispatcherPrivate() override;
QList<QAbstractNativeEventFilter *> eventFilters;
+ bool isV2 = false;
+
static int allocateTimerId();
static void releaseTimerId(int id);
+ static void releaseTimerId(Qt::TimerId id)
+ { releaseTimerId(qToUnderlying(id)); }
+
+ static QAbstractEventDispatcherPrivate *get(QAbstractEventDispatcher *o)
+ { return o->d_func(); }
+ static const QAbstractEventDispatcherPrivate *get(const QAbstractEventDispatcher *o)
+ { return o->d_func(); }
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp
index eaadea4c12..7b31c0fac5 100644
--- a/src/corelib/kernel/qabstractnativeeventfilter.cpp
+++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractnativeeventfilter.h"
#include "qabstracteventdispatcher.h"
@@ -74,9 +38,8 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter()
eventDispatcher->removeNativeEventFilter(this);
}
-// ### fixme Qt 6: result will be qintptr *
/*!
- \fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+ \fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
This method is called for every native event.
@@ -106,6 +69,9 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter()
\b {Linux example}
\snippet code/src_corelib_kernel_qabstractnativeeventfilter.cpp 0
+ \b {Windows example}
+ \snippet code/src_corelib_kernel_qabstractnativeeventfilter_win.cpp 0
+
\b {macOS example}
mycocoaeventfilter.h:
diff --git a/src/corelib/kernel/qabstractnativeeventfilter.h b/src/corelib/kernel/qabstractnativeeventfilter.h
index a468bffd61..3660a31dba 100644
--- a/src/corelib/kernel/qabstractnativeeventfilter.h
+++ b/src/corelib/kernel/qabstractnativeeventfilter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTNATIVEEVENTFILTER_H
#define QABSTRACTNATIVEEVENTFILTER_H
@@ -52,11 +16,7 @@ public:
QAbstractNativeEventFilter();
virtual ~QAbstractNativeEventFilter();
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) = 0;
-#else
- virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0;
-#endif
private:
Q_DISABLE_COPY(QAbstractNativeEventFilter)
diff --git a/src/corelib/kernel/qapplicationstatic.h b/src/corelib/kernel/qapplicationstatic.h
new file mode 100644
index 0000000000..bf5e79b8bf
--- /dev/null
+++ b/src/corelib/kernel/qapplicationstatic.h
@@ -0,0 +1,86 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QAPPLICATIONSTATIC_H
+#define QAPPLICATIONSTATIC_H
+
+#include <QtCore/QMutex>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qglobalstatic.h>
+
+#include <new>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtGlobalStatic {
+template <typename QAS> struct ApplicationHolder
+{
+ using Type = typename QAS::QAS_Type;
+ using PlainType = std::remove_cv_t<Type>;
+
+ Q_CONSTINIT static inline struct { alignas(Type) unsigned char data[sizeof(Type)]; } storage = {};
+ Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
+ Q_CONSTINIT static inline QBasicMutex mutex {};
+
+ static constexpr bool MutexLockIsNoexcept = noexcept(mutex.lock());
+ static constexpr bool ConstructionIsNoexcept = noexcept(QAS::innerFunction(nullptr));
+
+ ApplicationHolder() = default;
+ Q_DISABLE_COPY_MOVE(ApplicationHolder)
+ ~ApplicationHolder()
+ {
+ if (guard.loadAcquire() == QtGlobalStatic::Initialized) {
+ // No mutex! Up to external code to ensure no race happens.
+ guard.storeRelease(QtGlobalStatic::Destroyed);
+ realPointer()->~PlainType();
+ }
+ }
+
+ static PlainType *realPointer()
+ {
+ return std::launder(reinterpret_cast<PlainType *>(&storage));
+ }
+
+ // called from QGlobalStatic::instance()
+ PlainType *pointer() noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept)
+ {
+ if (guard.loadAcquire() == QtGlobalStatic::Initialized)
+ return realPointer();
+ QMutexLocker locker(&mutex);
+ if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) {
+ QAS::innerFunction(&storage);
+ const auto *app = QCoreApplication::instance();
+ Q_ASSERT_X(app, Q_FUNC_INFO,
+ "The application static was used without a QCoreApplication instance");
+ QObject::connect(app, &QObject::destroyed, app, reset, Qt::DirectConnection);
+ guard.storeRelease(QtGlobalStatic::Initialized);
+ }
+ return realPointer();
+ }
+
+ static void reset()
+ {
+ // we only synchronize using the mutex here, not the guard
+ QMutexLocker locker(&mutex);
+ realPointer()->~PlainType();
+ guard.storeRelaxed(QtGlobalStatic::Uninitialized);
+ }
+};
+} // namespace QtGlobalStatic
+
+#define Q_APPLICATION_STATIC(TYPE, NAME, ...) \
+ namespace { struct Q_QAS_ ## NAME { \
+ typedef TYPE QAS_Type; \
+ static void innerFunction(void *pointer) \
+ noexcept(noexcept(std::remove_cv_t<QAS_Type>(__VA_ARGS__))) \
+ { \
+ new (pointer) QAS_Type(__VA_ARGS__); \
+ } \
+ }; } \
+ static QGlobalStatic<QtGlobalStatic::ApplicationHolder<Q_QAS_ ## NAME>> NAME;\
+ /**/
+
+QT_END_NAMESPACE
+
+#endif // QAPPLICATIONSTATIC_H
diff --git a/src/corelib/kernel/qapplicationstatic.qdoc b/src/corelib/kernel/qapplicationstatic.qdoc
new file mode 100644
index 0000000000..5cbac65df9
--- /dev/null
+++ b/src/corelib/kernel/qapplicationstatic.qdoc
@@ -0,0 +1,109 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \macro Q_APPLICATION_STATIC(Type, VariableName, ...)
+ \since 6.3
+ \relates QGlobalStatic
+
+ This macro extends Q_GLOBAL_STATIC and creates a global and static object
+ of type \l QGlobalStatic, of name \a VariableName, initialized by the
+ variadic arguments, and that behaves as a pointer to \a Type, where the
+ actual lifetime of the type is bound to the QCoreApplication. The object
+ created by Q_APPLICATION_STATIC initializes itself on the first use, which
+ means that it will not increase the application or the library's load time.
+ Additionally, the object is initialized in a thread-safe manner on all
+ platforms.
+
+ In contrast to Q_GLOBAL_STATIC where the type is only meant to be destroyed at
+ program exit, here the actual lifetime of the type is bound to the lifetime of
+ the QCoreApplication. This makes it ideal to store semi-static QObjects, which
+ should also be destroyed once the QCoreApplication is destroyed. This means the
+ type will get deleted once the QCoreApplication emits the destroyed signal.
+ It is permitted for the object to be recreated when it's accessed again, if
+ a new QCoreApplication has also been created.
+
+ Since the value is bound to the QCoreApplication, it should only ever be
+ accessed if there is a valid QCoreApplication::instance(). Accessing this
+ object before QCoreApplication is created or after it's destroyed will
+ produce warnings and may have unpredictable behavior.
+
+ The typical use of this macro is as follows, in a global context (that is,
+ outside of any function bodies):
+
+ \code
+ Q_APPLICATION_STATIC(MyQObjectType, staticType, "some string", function())
+ \endcode
+
+ Do note that the arguments passed in variadic fashion to this macro are
+ evaluated every time the object is constructed, so in the above example,
+ the function \c{function} will be called more than once if the object is
+ recreated.
+
+ Aside from the value also being bound to the lifetime of the QCoreApplication,
+ this macro behaves identically to Q_GLOBAL_STATIC(). Please see that macro's
+ documentation for more information.
+
+ \section1 Threading guarantees
+
+ The Q_APPLICATION_STATIC macro ensures that the object is initialized only
+ once (per lifetime of a QCoreApplication), even if multiple threads try to
+ concurrently access the object. This is done by providing a per-object
+ mutex; application and library developers need to be aware that their
+ object will be constructed with this mutex locked and therefore must not
+ reenter the same object's initialization, or a deadlock will occur.
+
+ There is no thread-safety on the destruction of the object: user code must
+ not access this object once the QCoreApplication destructor starts to run.
+ User code must arrange to ensure this does not happen, such as by not
+ accessing it once the main thread's event loop has exited.
+
+ Like Q_GLOBAL_STATIC, Q_APPLICATION_STATIC provides no thread-safety
+ guarantees for accesses to the object once creation is finished. It is up
+ to user code to ensure that no racy data accesses happen.
+
+ In case the object created by this operation is a QObject, its associated
+ thread will be the one that succeeded in creating it. It will be destroyed
+ by the main thread, so a \l{QObject::}{moveToThread()} to the main thread
+ or to no thread before destruction is adviseable. Doing so from the
+ constructor of the class in question is a sensible solution if one can't
+ guarantee that the main thread will be the one to initialize the object.
+
+ \omit
+ \section1 Implementation details
+ See \l Q_GLOBAL_STATIC implementation details for an introduction.
+
+ Q_APPLICATION_STATIC uses the same \l QGlobalStatic public class that
+ Q_GLOBAL_STATIC does, but instead uses a QtGlobalStatic::ApplicationHolder
+ template class as the template parameter. The differences to
+ QtGlobalStatic::Holder are:
+
+ \list
+ \li The ApplicationHolder class is empty. Unlike Holder, the storage is
+ provided as a \c {static inline} member, simply so that the static
+ member reset() function can access it without having to save the
+ pointer in a lambda.
+
+ \li The ApplicationHolder constructor is trivial; initialization of the
+ type is instead deferred to the \c pointer() function. This means the
+ C++11 thread-safe initialization of statics does not protect the
+ object.
+
+ \li Instead, ApplicationHolder provides a mutex (implemented as a \c
+ {static inline} member of type \l QBasicMutex) and locks it before
+ constructing or destructing the object.
+
+ \li After constructing the object, it will QObject::connect() the
+ QCoreApplication::destroyed() signal to a function that will in turn
+ destroy the object.
+
+ \li The destructor will destroy the object if the application is
+ exiting without first destroying the QCoreApplication object (i.e., a
+ call to \c ::exit) or this Q_APPLICATION_STATIC is part of a plugin
+ that is being unloaded.
+ \endlist
+
+ \endomit
+
+ \sa Q_GLOBAL_STATIC, QGlobalStatic
+*/
diff --git a/src/corelib/kernel/qassociativeiterable.cpp b/src/corelib/kernel/qassociativeiterable.cpp
new file mode 100644
index 0000000000..db17c392a2
--- /dev/null
+++ b/src/corelib/kernel/qassociativeiterable.cpp
@@ -0,0 +1,287 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qassociativeiterable.h>
+#include <QtCore/qvariant.h>
+
+#include <QtCore/private/qiterable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Returns the key this iterator points to.
+*/
+QVariant QAssociativeIterator::key() const
+{
+ return QIterablePrivate::retrieveElement(
+ metaContainer().keyMetaType(), [this](void *dataPtr) {
+ metaContainer().keyAtIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the mapped value this iterator points to. If the container does not
+ provide a mapped value (for example a set), returns an invalid QVariantRef.
+*/
+QVariantRef<QAssociativeIterator> QAssociativeIterator::value() const
+{
+ const QMetaType mappedMetaType(metaContainer().mappedMetaType());
+ return QVariantRef<QAssociativeIterator>(mappedMetaType.isValid() ? this : nullptr);
+}
+
+/*!
+ Returns the current item, converted to a QVariantRef. The resulting
+ QVariantRef resolves to the mapped value if there is one, or to the key
+ value if not.
+*/
+QVariantRef<QAssociativeIterator> QAssociativeIterator::operator*() const
+{
+ return QVariantRef<QAssociativeIterator>(this);
+}
+
+/*!
+ Returns the current item, converted to a QVariantPointer. The resulting
+ QVariantPointer resolves to the mapped value if there is one, or to the key
+ value if not.
+*/
+QVariantPointer<QAssociativeIterator> QAssociativeIterator::operator->() const
+{
+ return QVariantPointer<QAssociativeIterator>(this);
+}
+
+/*!
+ Returns the key this iterator points to.
+*/
+QVariant QAssociativeConstIterator::key() const
+{
+ return QIterablePrivate::retrieveElement(
+ metaContainer().keyMetaType(), [this](void *dataPtr) {
+ metaContainer().keyAtConstIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the mapped value this iterator points to, or an invalid QVariant if
+ there is no mapped value.
+*/
+QVariant QAssociativeConstIterator::value() const
+{
+ return QIterablePrivate::retrieveElement(
+ metaContainer().mappedMetaType(), [this](void *dataPtr) {
+ metaContainer().mappedAtConstIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the current item, converted to a QVariant. The returned value is the
+ mapped value at the current iterator if there is one, or otherwise the key.
+*/
+QVariant QAssociativeConstIterator::operator*() const
+{
+ const QMetaType mappedMetaType(metaContainer().mappedMetaType());
+ return mappedMetaType.isValid() ? value() : key();
+}
+
+/*!
+ Returns the current item, converted to a QVariantConstPointer. The
+ QVariantConstPointer will resolve to the mapped value at the current
+ iterator if there is one, or otherwise the key.
+*/
+QVariantConstPointer QAssociativeConstIterator::operator->() const
+{
+ return QVariantConstPointer(operator*());
+}
+
+/*!
+ \class QAssociativeIterable
+ \since 5.2
+ \inmodule QtCore
+ \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
+
+ This class allows several methods of accessing the elements of an associative container held within
+ a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
+ be converted to a QVariantHash or QVariantMap or if a custom mutable view has been registered.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ The container itself is not copied before iterating over it.
+
+ \sa QVariant
+*/
+
+/*!
+ \typedef QAssociativeIterable::RandomAccessIterator
+ Exposes an iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::BidirectionalIterator
+ Exposes an iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::ForwardIterator
+ Exposes an iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::InputIterator
+ Exposes an iterator using std::input_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::RandomAccessConstIterator
+ Exposes a const_iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::BidirectionalConstIterator
+ Exposes a const_iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::ForwardConstIterator
+ Exposes a const_iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QAssociativeIterable::InputConstIterator
+ Exposes a const_iterator using std::input_iterator_tag.
+*/
+
+/*!
+ Retrieves a const_iterator pointing to the element at the given \a key, or
+ the end of the container if that key does not exist. If the \a key isn't
+ convertible to the expected type, the end of the container is returned.
+ */
+QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
+{
+ const QMetaAssociation meta = metaContainer();
+ QtPrivate::QVariantTypeCoercer coercer;
+ if (const void *keyData = coercer.convert(key, meta.keyMetaType())) {
+ return const_iterator(QConstIterator(this, meta.createConstIteratorAtKey(
+ constIterable(), keyData)));
+ }
+ return constEnd();
+}
+
+/*!
+ Retrieves an iterator pointing to the element at the given \a key, or
+ the end of the container if that key does not exist. If the \a key isn't
+ convertible to the expected type, the end of the container is returned.
+ */
+QAssociativeIterable::iterator QAssociativeIterable::mutableFind(const QVariant &key)
+{
+ const QMetaAssociation meta = metaContainer();
+ QtPrivate::QVariantTypeCoercer coercer;
+ if (const void *keyData = coercer.convert(key, meta.keyMetaType()))
+ return iterator(QIterator(this, meta.createIteratorAtKey(mutableIterable(), keyData)));
+ return mutableEnd();
+}
+
+/*!
+ Returns \c true if the container has an entry with the given \a key, or
+ \c false otherwise. If the \a key isn't convertible to the expected type,
+ \c false is returned.
+ */
+bool QAssociativeIterable::containsKey(const QVariant &key)
+{
+ QtPrivate::QVariantTypeCoercer keyCoercer;
+ QMetaAssociation meta = metaContainer();
+ if (const void *keyData = keyCoercer.convert(key, meta.keyMetaType()))
+ return meta.containsKey(constIterable(), keyData);
+ return false;
+}
+
+/*!
+ Inserts a new entry with the given \a key, or resets the mapped value of
+ any existing entry with the given \a key to the default constructed
+ mapped value. The \a key is coerced to the expected type: If it isn't
+ convertible, a default value is inserted.
+ */
+void QAssociativeIterable::insertKey(const QVariant &key)
+{
+ QMetaAssociation meta = metaContainer();
+ QtPrivate::QVariantTypeCoercer keyCoercer;
+ meta.insertKey(mutableIterable(), keyCoercer.coerce(key, meta.keyMetaType()));
+}
+
+/*!
+ Removes the entry with the given \a key from the container. The \a key is
+ coerced to the expected type: If it isn't convertible, the default value
+ is removed.
+ */
+void QAssociativeIterable::removeKey(const QVariant &key)
+{
+ QMetaAssociation meta = metaContainer();
+ QtPrivate::QVariantTypeCoercer keyCoercer;
+ meta.removeKey(mutableIterable(), keyCoercer.coerce(key, meta.keyMetaType()));
+}
+
+
+/*!
+ Retrieves the mapped value at the given \a key, or a default-constructed
+ QVariant of the mapped type, if the key does not exist. If the \a key is not
+ convertible to the key type, the mapped value associated with the
+ default-constructed key is returned.
+ */
+QVariant QAssociativeIterable::value(const QVariant &key) const
+{
+ const QMetaAssociation meta = metaContainer();
+ const QMetaType mappedMetaType = meta.mappedMetaType();
+
+ QtPrivate::QVariantTypeCoercer coercer;
+ const void *keyData = coercer.coerce(key, meta.keyMetaType());
+
+ if (mappedMetaType == QMetaType::fromType<QVariant>()) {
+ QVariant result;
+ meta.mappedAtKey(constIterable(), keyData, &result);
+ return result;
+ }
+
+ QVariant result(mappedMetaType);
+ meta.mappedAtKey(constIterable(), keyData, result.data());
+ return result;
+}
+
+/*!
+ Sets the mapped value associated with \a key to \a mapped, if possible.
+ Inserts a new entry if none exists yet, for the given \a key. If the \a key
+ is not convertible to the key type, the value for the default-constructed
+ key type is overwritten.
+ */
+void QAssociativeIterable::setValue(const QVariant &key, const QVariant &mapped)
+{
+ QtPrivate::QVariantTypeCoercer keyCoercer;
+ QtPrivate::QVariantTypeCoercer mappedCoercer;
+ QMetaAssociation meta = metaContainer();
+ meta.setMappedAtKey(mutableIterable(), keyCoercer.coerce(key, meta.keyMetaType()),
+ mappedCoercer.coerce(mapped, meta.mappedMetaType()));
+}
+
+/*!
+ \typealias QAssociativeIterable::const_iterator
+ \inmodule QtCore
+ \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
+
+ A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 10
+
+ \sa QAssociativeIterable
+*/
+
+/*!
+ \typealias QAssociativeIterable::iterator
+ \since 6.0
+ \inmodule QtCore
+ \brief The QAssociativeIterable::iterator allows iteration over a container in a QVariant.
+
+ A QAssociativeIterable::iterator can only be created by a QAssociativeIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \sa QAssociativeIterable
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qassociativeiterable.h b/src/corelib/kernel/qassociativeiterable.h
new file mode 100644
index 0000000000..f3963d350e
--- /dev/null
+++ b/src/corelib/kernel/qassociativeiterable.h
@@ -0,0 +1,173 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QASSOCIATIVEITERABLE_H
+#define QASSOCIATIVEITERABLE_H
+
+#include <QtCore/qiterable.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QAssociativeIterator : public QIterator<QMetaAssociation>
+{
+public:
+ using key_type = QVariant;
+ using mapped_type = QVariant;
+ using reference = QVariantRef<QAssociativeIterator>;
+ using pointer = QVariantPointer<QAssociativeIterator>;
+
+ QAssociativeIterator(QIterator &&it)
+ : QIterator(std::move(it))
+ {}
+
+ QVariant key() const;
+ QVariantRef<QAssociativeIterator> value() const;
+
+ QVariantRef<QAssociativeIterator> operator*() const;
+ QVariantPointer<QAssociativeIterator> operator->() const;
+};
+
+class Q_CORE_EXPORT QAssociativeConstIterator : public QConstIterator<QMetaAssociation>
+{
+public:
+ using key_type = QVariant;
+ using mapped_type = QVariant;
+ using reference = const QVariant &;
+ using pointer = QVariantConstPointer;
+
+ QAssociativeConstIterator(QConstIterator &&it)
+ : QConstIterator(std::move(it))
+ {}
+
+ QVariant key() const;
+ QVariant value() const;
+
+ QVariant operator*() const;
+ QVariantConstPointer operator->() const;
+};
+
+class Q_CORE_EXPORT QAssociativeIterable : public QIterable<QMetaAssociation>
+{
+public:
+ using iterator = QTaggedIterator<QAssociativeIterator, void>;
+ using const_iterator = QTaggedIterator<QAssociativeConstIterator, void>;
+
+ using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
+ using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
+ using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
+ using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
+
+ using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
+ using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
+ using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
+ using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
+
+ template<class T>
+ QAssociativeIterable(const T *p)
+ : QIterable(QMetaAssociation::fromContainer<T>(), p)
+ {
+ }
+
+ template<class T>
+ QAssociativeIterable(T *p)
+ : QIterable(QMetaAssociation::fromContainer<T>(), p)
+ {
+ }
+
+ QAssociativeIterable()
+ : QIterable(QMetaAssociation(), nullptr)
+ {
+ }
+
+ template<typename Pointer>
+ QAssociativeIterable(const QMetaAssociation &metaAssociation, Pointer iterable)
+ : QIterable(metaAssociation, iterable)
+ {
+ }
+
+ // ### Qt7: Pass QMetaType as value rather than const ref.
+ QAssociativeIterable(const QMetaAssociation &metaAssociation, const QMetaType &metaType,
+ void *iterable)
+ : QIterable(metaAssociation, metaType.alignOf(), iterable)
+ {
+ }
+
+ // ### Qt7: Pass QMetaType as value rather than const ref.
+ QAssociativeIterable(const QMetaAssociation &metaAssociation, const QMetaType &metaType,
+ const void *iterable)
+ : QIterable(metaAssociation, metaType.alignOf(), iterable)
+ {
+ }
+
+ QAssociativeIterable(QIterable<QMetaAssociation> &&other) : QIterable(std::move(other)) {}
+
+ QAssociativeIterable &operator=(QIterable<QMetaAssociation> &&other)
+ {
+ QIterable::operator=(std::move(other));
+ return *this;
+ }
+
+ const_iterator begin() const { return constBegin(); }
+ const_iterator end() const { return constEnd(); }
+
+ const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
+ const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
+
+ iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
+ iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
+
+ const_iterator find(const QVariant &key) const;
+ const_iterator constFind(const QVariant &key) const { return find(key); }
+ iterator mutableFind(const QVariant &key);
+
+ bool containsKey(const QVariant &key);
+ void insertKey(const QVariant &key);
+ void removeKey(const QVariant &key);
+
+ QVariant value(const QVariant &key) const;
+ void setValue(const QVariant &key, const QVariant &mapped);
+};
+
+template<>
+inline QVariantRef<QAssociativeIterator>::operator QVariant() const
+{
+ if (m_pointer == nullptr)
+ return QVariant();
+
+ const auto metaAssociation = m_pointer->metaContainer();
+ const QMetaType metaType(metaAssociation.mappedMetaType());
+ if (!metaType.isValid())
+ return m_pointer->key();
+
+ QVariant v(metaType);
+ metaAssociation.mappedAtIterator(m_pointer->constIterator(),
+ metaType == QMetaType::fromType<QVariant>() ? &v : v.data());
+ return v;
+}
+
+template<>
+inline QVariantRef<QAssociativeIterator> &QVariantRef<QAssociativeIterator>::operator=(
+ const QVariant &value)
+{
+ if (m_pointer == nullptr)
+ return *this;
+
+ const auto metaAssociation = m_pointer->metaContainer();
+ const QMetaType metaType(metaAssociation.mappedMetaType());
+ if (metaType.isValid()) {
+ QtPrivate::QVariantTypeCoercer coercer;
+ metaAssociation.setMappedAtIterator(m_pointer->constIterator(),
+ coercer.coerce(value, metaType));
+ }
+
+ return *this;
+}
+
+Q_DECLARE_TYPEINFO(QAssociativeIterable, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QAssociativeIterable::iterator, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QAssociativeIterable::const_iterator, Q_RELOCATABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QASSOCIATIVEITERABLE_H
diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp
index 623ecb9b8b..17711a355e 100644
--- a/src/corelib/kernel/qbasictimer.cpp
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbasictimer.h"
#include "qabstracteventdispatcher.h"
@@ -69,17 +33,15 @@ QT_BEGIN_NAMESPACE
can maintain a list of basic timers by holding them in container
that supports move-only types, e.g. std::vector.
- The \l{widgets/wiggly}{Wiggly} example uses QBasicTimer to repaint
- a widget at regular intervals.
-
- \sa QTimer, QTimerEvent, QObject::timerEvent(), Timers, {Wiggly Example}
+ \sa QTimer, QChronoTimer, QTimerEvent, QObject::timerEvent(),
+ Timers, {Affine Transformations}
*/
/*!
\fn QBasicTimer::QBasicTimer()
- Contructs a basic timer.
+ Constructs a basic timer.
\sa start()
*/
@@ -105,29 +67,6 @@ QT_BEGIN_NAMESPACE
\sa stop(), isActive(), swap()
*/
-#if QT_DEPRECATED_SINCE(5, 14)
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- \internal
-*/
-QBasicTimer::QBasicTimer(const QBasicTimer &other)
- : id{other.id}
-{
- qWarning("QBasicTimer can't be copied");
-}
-
-/*!
- \internal
-*/
-QBasicTimer &QBasicTimer::operator=(const QBasicTimer &other)
-{
- id = other.id;
- qWarning("QBasicTimer can't be assigned to");
- return *this;
-}
-#endif
-#endif
-
/*!
\fn QBasicTimer::~QBasicTimer()
@@ -145,10 +84,18 @@ QBasicTimer &QBasicTimer::operator=(const QBasicTimer &other)
/*!
\fn QBasicTimer::swap(QBasicTimer &other)
+ \since 5.14
+
+ Swaps the timer \a other with this timer.
+ This operation is very fast and never fails.
+*/
+
+/*!
\fn swap(QBasicTimer &lhs, QBasicTimer &rhs)
+ \relates QBasicTimer
\since 5.14
- Swaps string \a other with this string, or \a lhs with \a rhs.
+ Swaps the timer \a lhs with \a rhs.
This operation is very fast and never fails.
*/
@@ -163,7 +110,13 @@ QBasicTimer &QBasicTimer::operator=(const QBasicTimer &other)
/*!
\fn void QBasicTimer::start(int msec, QObject *object)
- Starts (or restarts) the timer with a \a msec milliseconds timeout. The
+ \obsolete Use chrono overload instead.
+*/
+
+/*!
+ \since 6.5
+
+ Starts (or restarts) the timer with a \a duration timeout. The
timer will be a Qt::CoarseTimer. See Qt::TimerType for information on the
different timer types.
@@ -171,15 +124,23 @@ QBasicTimer &QBasicTimer::operator=(const QBasicTimer &other)
\sa stop(), isActive(), QObject::timerEvent(), Qt::CoarseTimer
*/
-void QBasicTimer::start(int msec, QObject *obj)
+void QBasicTimer::start(std::chrono::milliseconds duration, QObject *object)
{
- start(msec, Qt::CoarseTimer, obj);
+ start(duration, Qt::CoarseTimer, object);
}
/*!
+ \fn QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
\overload
+ \obsolete
+
+ Use chrono overload instead.
+*/
+
+/*!
+ \since 6.5
- Starts (or restarts) the timer with a \a msec milliseconds timeout and the
+ Starts (or restarts) the timer with a \a duration timeout and the
given \a timerType. See Qt::TimerType for information on the different
timer types.
@@ -187,10 +148,10 @@ void QBasicTimer::start(int msec, QObject *obj)
\sa stop(), isActive(), QObject::timerEvent(), Qt::TimerType
*/
-void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
+void QBasicTimer::start(std::chrono::milliseconds duration, Qt::TimerType timerType, QObject *obj)
{
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (Q_UNLIKELY(msec < 0)) {
+ if (Q_UNLIKELY(duration.count() < 0)) {
qWarning("QBasicTimer::start: Timers cannot have negative timeouts");
return;
}
@@ -204,7 +165,7 @@ void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
}
stop();
if (obj)
- id = eventDispatcher->registerTimer(msec, timerType, obj);
+ id = int(eventDispatcher->registerTimer(duration, timerType, obj));
}
/*!
@@ -216,7 +177,7 @@ void QBasicTimer::stop()
{
if (id) {
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (eventDispatcher && !eventDispatcher->unregisterTimer(id)) {
+ if (eventDispatcher && !eventDispatcher->unregisterTimer(Qt::TimerId(id))) {
qWarning("QBasicTimer::stop: Failed. Possibly trying to stop from a different thread");
return;
}
diff --git a/src/corelib/kernel/qbasictimer.h b/src/corelib/kernel/qbasictimer.h
index 769898f835..ccc93f6e9b 100644
--- a/src/corelib/kernel/qbasictimer.h
+++ b/src/corelib/kernel/qbasictimer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBASICTIMER_H
#define QBASICTIMER_H
@@ -43,6 +7,8 @@
#include <QtCore/qglobal.h>
#include <QtCore/qnamespace.h>
+#include <chrono>
+
QT_BEGIN_NAMESPACE
@@ -51,41 +17,43 @@ class QObject;
class Q_CORE_EXPORT QBasicTimer
{
int id;
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
Q_DISABLE_COPY(QBasicTimer)
-#elif QT_DEPRECATED_SINCE(5, 14)
-public:
- // Just here to preserve BC, we can't remove them yet
- QT_DEPRECATED_X("copy-construction is unsupported; use move-construction instead")
- QBasicTimer(const QBasicTimer &);
- QT_DEPRECATED_X("copy-assignment is unsupported; use move-assignment instead")
- QBasicTimer &operator=(const QBasicTimer &);
-#endif
public:
constexpr QBasicTimer() noexcept : id{0} {}
inline ~QBasicTimer() { if (id) stop(); }
QBasicTimer(QBasicTimer &&other) noexcept
- : id{qExchange(other.id, 0)}
+ : id{std::exchange(other.id, 0)}
{}
- QBasicTimer& operator=(QBasicTimer &&other) noexcept
- {
- QBasicTimer{std::move(other)}.swap(*this);
- return *this;
- }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QBasicTimer)
- void swap(QBasicTimer &other) noexcept { qSwap(id, other.id); }
+ void swap(QBasicTimer &other) noexcept { std::swap(id, other.id); }
bool isActive() const noexcept { return id != 0; }
int timerId() const noexcept { return id; }
-
+ QT_CORE_INLINE_SINCE(6, 5)
void start(int msec, QObject *obj);
+ QT_CORE_INLINE_SINCE(6, 5)
void start(int msec, Qt::TimerType timerType, QObject *obj);
+ void start(std::chrono::milliseconds duration, QObject *obj);
+ void start(std::chrono::milliseconds duration, Qt::TimerType timerType, QObject *obj);
void stop();
};
-Q_DECLARE_TYPEINFO(QBasicTimer, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QBasicTimer, Q_RELOCATABLE_TYPE);
+
+#if QT_CORE_INLINE_IMPL_SINCE(6, 5)
+void QBasicTimer::start(int msec, QObject *obj)
+{
+ start(std::chrono::milliseconds{msec}, obj);
+}
+
+void QBasicTimer::start(int msec, Qt::TimerType t, QObject *obj)
+{
+ start(std::chrono::milliseconds{msec}, t, obj);
+}
+#endif
inline void swap(QBasicTimer &lhs, QBasicTimer &rhs) noexcept { lhs.swap(rhs); }
diff --git a/src/corelib/kernel/qbindingstorage.h b/src/corelib/kernel/qbindingstorage.h
new file mode 100644
index 0000000000..1c03b23bfa
--- /dev/null
+++ b/src/corelib/kernel/qbindingstorage.h
@@ -0,0 +1,94 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QBINDINGSTORAGE_H
+#define QBINDINGSTORAGE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+template <typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
+class QObjectCompatProperty;
+struct QPropertyDelayedNotifications;
+class QUntypedPropertyData;
+
+namespace QtPrivate {
+
+class QPropertyBindingData;
+struct BindingEvaluationState;
+struct CompatPropertySafePoint;
+}
+
+struct QBindingStatus
+{
+ QtPrivate::BindingEvaluationState *currentlyEvaluatingBinding = nullptr;
+ QtPrivate::CompatPropertySafePoint *currentCompatProperty = nullptr;
+ Qt::HANDLE threadId = nullptr;
+ QPropertyDelayedNotifications *groupUpdateData = nullptr;
+};
+
+namespace QtPrivate {
+struct QBindingStatusAccessToken;
+Q_AUTOTEST_EXPORT QBindingStatus *getBindingStatus(QBindingStatusAccessToken);
+}
+
+
+struct QBindingStorageData;
+class Q_CORE_EXPORT QBindingStorage
+{
+ mutable QBindingStorageData *d = nullptr;
+ QBindingStatus *bindingStatus = nullptr;
+
+ template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
+ friend class QObjectCompatProperty;
+ friend class QObjectPrivate;
+ friend class QtPrivate::QPropertyBindingData;
+public:
+ QBindingStorage();
+ ~QBindingStorage();
+
+ bool isEmpty() { return !d; }
+ bool isValid() const noexcept { return bindingStatus; }
+
+ const QBindingStatus *status(QtPrivate::QBindingStatusAccessToken) const;
+
+ void registerDependency(const QUntypedPropertyData *data) const
+ {
+ if (!bindingStatus || !bindingStatus->currentlyEvaluatingBinding)
+ return;
+ registerDependency_helper(data);
+ }
+ QtPrivate::QPropertyBindingData *bindingData(const QUntypedPropertyData *data) const
+ {
+ if (!d)
+ return nullptr;
+ return bindingData_helper(data);
+ }
+
+#if QT_CORE_REMOVED_SINCE(6, 2)
+ void maybeUpdateBindingAndRegister(const QUntypedPropertyData *data) const { registerDependency(data); }
+#endif
+
+ QtPrivate::QPropertyBindingData *bindingData(QUntypedPropertyData *data, bool create)
+ {
+ if (!d && !create)
+ return nullptr;
+ return bindingData_helper(data, create);
+ }
+private:
+ void reinitAfterThreadMove();
+ void clear();
+ void registerDependency_helper(const QUntypedPropertyData *data) const;
+#if QT_CORE_REMOVED_SINCE(6, 2)
+ // ### Unused, but keep for BC
+ void maybeUpdateBindingAndRegister_helper(const QUntypedPropertyData *data) const;
+#endif
+ QtPrivate::QPropertyBindingData *bindingData_helper(const QUntypedPropertyData *data) const;
+ QtPrivate::QPropertyBindingData *bindingData_helper(QUntypedPropertyData *data, bool create);
+};
+
+QT_END_NAMESPACE
+
+#endif // QBINDINGSTORAGE_H
diff --git a/src/corelib/kernel/qcfsocketnotifier.cpp b/src/corelib/kernel/qcfsocketnotifier.cpp
index 920ec9cd86..21a22a7439 100644
--- a/src/corelib/kernel/qcfsocketnotifier.cpp
+++ b/src/corelib/kernel/qcfsocketnotifier.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcfsocketnotifier_p.h"
#include <QtCore/qcoreapplication.h>
@@ -48,7 +12,7 @@ QT_BEGIN_NAMESPACE
Socket Notifiers
*************************************************************************/
void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef,
- const void *, void *info)
+ const void *data, void *info)
{
QCFSocketNotifier *cfSocketNotifier = static_cast<QCFSocketNotifier *>(info);
@@ -61,7 +25,15 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF
// notification after we've successfully disabled the CFSocket, but our Qt
// notifier is now gone. The upshot is we have to check the notifier
// every time.
- if (callbackType == kCFSocketReadCallBack) {
+ if (callbackType == kCFSocketConnectCallBack) {
+ // The data pointer will be non-null on connection error
+ if (data) {
+ if (socketInfo->readNotifier)
+ QCoreApplication::sendEvent(socketInfo->readNotifier, &notifierEvent);
+ if (socketInfo->writeNotifier)
+ QCoreApplication::sendEvent(socketInfo->writeNotifier, &notifierEvent);
+ }
+ } else if (callbackType == kCFSocketReadCallBack) {
if (socketInfo->readNotifier && socketInfo->readEnabled) {
socketInfo->readEnabled = false;
QCoreApplication::sendEvent(socketInfo->readNotifier, &notifierEvent);
@@ -152,7 +124,7 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
// Create CFSocket, specify that we want both read and write callbacks (the callbacks
// are enabled/disabled later on).
- const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
+ const int callbackTypes = kCFSocketConnectCallBack | kCFSocketReadCallBack | kCFSocketWriteCallBack;
CFSocketContext context = {0, this, 0, 0, 0};
socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
if (CFSocketIsValid(socketInfo->socket) == false) {
@@ -163,7 +135,7 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
// QSocketNotifier doesn't close the socket upon destruction/invalidation
flags &= ~kCFSocketCloseOnInvalidate;
- // Expicitly disable automatic re-enable, as we do that manually on each runloop pass
+ // Explicitly disable automatic re-enable, as we do that manually on each runloop pass
flags &= ~(kCFSocketAutomaticallyReenableWriteCallBack | kCFSocketAutomaticallyReenableReadCallBack);
CFSocketSetSocketFlags(socketInfo->socket, flags);
@@ -241,7 +213,7 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier)
void QCFSocketNotifier::removeSocketNotifiers()
{
// Remove CFSockets from the runloop.
- for (MacSocketInfo *socketInfo : qAsConst(macSockets)) {
+ for (MacSocketInfo *socketInfo : std::as_const(macSockets)) {
unregisterSocketInfo(socketInfo);
delete socketInfo;
}
diff --git a/src/corelib/kernel/qcfsocketnotifier_p.h b/src/corelib/kernel/qcfsocketnotifier_p.h
index 12c5bf6334..9bffe132dd 100644
--- a/src/corelib/kernel/qcfsocketnotifier_p.h
+++ b/src/corelib/kernel/qcfsocketnotifier_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCFSOCKETNOTIFIER_P_H
#define QCFSOCKETNOTIFIER_P_H
diff --git a/src/corelib/kernel/qchronotimer.cpp b/src/corelib/kernel/qchronotimer.cpp
new file mode 100644
index 0000000000..a517c4446b
--- /dev/null
+++ b/src/corelib/kernel/qchronotimer.cpp
@@ -0,0 +1,452 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qchronotimer.h"
+#include "qtimer_p.h"
+#include "qsingleshottimer_p.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qdeadlinetimer.h"
+#include "qmetaobject_p.h"
+#include "qobject_p.h"
+#include "qproperty_p.h"
+#include "qthread.h"
+
+using namespace std::chrono_literals;
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QChronoTimer
+ \inmodule QtCore
+ \since 6.8
+ \ingroup events
+
+ \brief The QChronoTimer class provides repetitive and single-shot timers.
+
+ The QChronoTimer class provides a high-level programming interface for
+ timers. To use it, create a QChronoTimer, either passing the interval to the
+ constructor, or setting it after construction using setInterval(), connect
+ its timeout() signal to the appropriate slots, and call start(). From then
+ on, it will emit the timeout() signal at constant intervals. For example:
+
+ \snippet timers/timers.cpp timer-interval-in-ctor
+ \snippet timers/timers.cpp timer-setinterval
+
+ You can set a timer to time out only once by calling setSingleShot(true).
+
+ QChronoTimer also has singleShot() static methods:
+
+ \snippet timers/timers.cpp qchronotimer-singleshot
+
+ In multithreaded applications, you can use QChronoTimer in any thread
+ that has an event loop. To start an event loop from a non-GUI
+ thread, use QThread::exec(). Qt uses the timer's
+ \l{QObject::thread()}{thread affinity} to determine which thread
+ will emit the \l{QChronoTimer::}{timeout()} signal. Because of this, you
+ must start and stop the timer in its thread; it is not possible to
+ start a timer from another thread.
+
+ As a special case, a QChronoTimer with a timeout of \c 0ns will time out
+ as soon as possible, though the ordering between zero timers and other
+ sources of events is unspecified. Zero timers can be used to do some
+ work while still providing a responsive user interface:
+
+ \snippet timers/timers.cpp zero-timer
+
+ From then on, \c processOneThing() will be called repeatedly. It should
+ be written in such a way that it always returns quickly (for example,
+ after processing one data item) so that Qt can deliver events to the user
+ interface and stop the timer as soon as it has done all its work. This
+ is the traditional way of implementing heavy work in GUI applications,
+ but as multithreading is becoming available on more platforms, a modern
+ alternative is doing the heavy work in a thread other than the GUI (main)
+ thread. Qt has the QThread class, which can be used to achieve that.
+
+ \section1 Accuracy and Timer Resolution
+
+ The accuracy of timers depends on the underlying operating system and
+ hardware. Most platforms support requesting nano-second precision for
+ timers (for example, libc's \c nanosleep), though the accuracy of the
+ timer will not equal this resolution in many real-world situations.
+
+ You can set the \l{Qt::TimerType}{timer type} to tell QChronoTimer which
+ precision to request from the system.
+
+ For Qt::PreciseTimer, QChronoTimer will try to keep the precision at
+ \c 1ns. Precise timers will never time out earlier than expected.
+
+ For Qt::CoarseTimer and Qt::VeryCoarseTimer types, QChronoTimer may wake
+ up earlier than expected, within the margins for those types:
+ \list
+ \li 5% of the interval for Qt::CoarseTimer
+ \li \c 500ms for Qt::VeryCoarseTimer
+ \endlist
+
+ All timer types may time out later than expected if the system is busy or
+ unable to provide the requested accuracy. In such a case of timeout
+ overrun, Qt will emit timeout() only once, even if multiple timeouts have
+ expired, and then will resume the original interval.
+
+ \section1 Alternatives to QChronoTimer
+
+ An alternative to using QChronoTimer is to call QObject::startTimer()
+ for your object and reimplement the QObject::timerEvent() event handler
+ in your class (which must be a sub-class of QObject). The disadvantage
+ is that timerEvent() does not support such high-level features as
+ single-shot timers or signals.
+
+ Another alternative is QBasicTimer. It is typically less cumbersome
+ than using QObject::startTimer() directly. See \l{Timers} for an
+ overview of all three approaches.
+
+ Some operating systems limit the number of timers that may be used;
+ Qt does its best to work around these limitations.
+
+ \sa QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers,
+ {Analog Clock}
+*/
+
+/*!
+ Constructs a timer with the given \a parent, using the default interval,
+ \c 0ns.
+*/
+QChronoTimer::QChronoTimer(QObject *parent)
+ : QChronoTimer(0ns, parent)
+{
+}
+
+/*!
+ Constructs a timer with the given \a parent, using an interval of \a nsec.
+*/
+QChronoTimer::QChronoTimer(std::chrono::nanoseconds nsec, QObject *parent)
+ : QObject(*new QTimerPrivate(nsec, this), parent)
+{
+ Q_ASSERT(!d_func()->isQTimer);
+}
+
+/*!
+ Destroys the timer.
+*/
+QChronoTimer::~QChronoTimer()
+{
+ if (d_func()->isActive()) // stop running timer
+ stop();
+}
+
+/*!
+ \fn void QChronoTimer::timeout()
+
+ This signal is emitted when the timer times out.
+
+ \sa interval, start(), stop()
+*/
+
+/*!
+ \property QChronoTimer::active
+
+ This boolean property is \c true if the timer is running; otherwise
+ \c false.
+*/
+
+/*!
+ Returns \c true if the timer is running (pending); otherwise returns
+ false.
+*/
+bool QChronoTimer::isActive() const
+{
+ return d_func()->isActiveData.value();
+}
+
+QBindable<bool> QChronoTimer::bindableActive()
+{
+ return QBindable<bool>(&d_func()->isActiveData);
+}
+
+/*!
+ Returns a Qt::TimerId representing the timer ID if the timer is running;
+ otherwise returns \c Qt::TimerId::Invalid.
+
+ \sa Qt::TimerId
+*/
+Qt::TimerId QChronoTimer::id() const
+{
+ return d_func()->id;
+}
+
+/*! \overload start()
+
+ Starts or restarts the timer with the timeout specified in \l interval.
+
+ If the timer is already running, it will be
+ \l{QChronoTimer::stop()}{stopped} and restarted.
+
+ If \l singleShot is true, the timer will be activated only once.
+*/
+void QChronoTimer::start()
+{
+ auto *d = d_func();
+ if (d->isActive()) // stop running timer
+ stop();
+ const auto id = Qt::TimerId{QObject::startTimer(d->intervalDuration, d->type)};
+ if (id > Qt::TimerId::Invalid) {
+ d->id = id;
+ d->isActiveData.notify();
+ }
+}
+
+/*!
+ Stops the timer.
+
+ \sa start()
+*/
+void QChronoTimer::stop()
+{
+ auto *d = d_func();
+ if (d->isActive()) {
+ QObject::killTimer(d->id);
+ d->id = Qt::TimerId::Invalid;
+ d->isActiveData.notify();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QChronoTimer::timerEvent(QTimerEvent *e)
+{
+ auto *d = d_func();
+ if (Qt::TimerId{e->timerId()} == d->id) {
+ if (d->single)
+ stop();
+ Q_EMIT timeout(QPrivateSignal());
+ }
+}
+
+/*!
+ \fn template <typename Functor> QMetaObject::Connection QChronoTimer::callOnTimeout(const QObject *context, Functor &&slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \overload callOnTimeout()
+
+ Creates a connection from the timeout() signal to \a slot to be placed in a
+ specific event loop of \a context, with connection type \a connectionType,
+ and returns a handle to the connection.
+
+ This method is provided as a convenience. It's equivalent to calling:
+ \code
+ QObject::connect(timer, &QChronoTimer::timeout, context, slot, connectionType);
+ \endcode
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
+ \property QChronoTimer::singleShot
+ \brief Whether the timer is a single-shot timer
+
+ A single-shot timer fires only once, non-single-shot timers fire every
+ \l interval.
+
+ The default value for this property is \c false.
+
+ \sa interval, singleShot()
+*/
+void QChronoTimer::setSingleShot(bool singleShot)
+{
+ d_func()->single = singleShot;
+}
+
+bool QChronoTimer::isSingleShot() const
+{
+ return d_func()->single;
+}
+
+QBindable<bool> QChronoTimer::bindableSingleShot()
+{
+ return QBindable<bool>(&d_func()->single);
+}
+
+/*!
+ \property QChronoTimer::interval
+ \brief The timeout interval
+
+ The default value for this property is \c 0ns.
+
+ A QChronoTimer with a timeout of \c 0ns will time out as soon as all
+ the events in the window system's event queue have been processed.
+
+ Setting the interval of an active timer changes the interval and acquires
+ a new id(). If the timer is not active, only the interval is changed.
+
+ \sa singleShot
+*/
+void QChronoTimer::setInterval(std::chrono::nanoseconds nsec)
+{
+ auto *d = d_func();
+ d->intervalDuration.removeBindingUnlessInWrapper();
+ const bool intervalChanged = nsec != d->intervalDuration.valueBypassingBindings();
+ d->intervalDuration.setValueBypassingBindings(nsec);
+ if (d->isActive()) { // Create new timer
+ QObject::killTimer(d->id); // Restart timer
+ const auto newId = Qt::TimerId{QObject::startTimer(nsec, d->type)};
+ if (newId > Qt::TimerId::Invalid) {
+ // Restarted successfully. No need to update the active state.
+ d->id = newId;
+ } else {
+ // Failed to start the timer.
+ // Need to notify about active state change.
+ d->id = Qt::TimerId::Invalid;
+ d->isActiveData.notify();
+ }
+ }
+ if (intervalChanged)
+ d->intervalDuration.notify();
+}
+
+std::chrono::nanoseconds QChronoTimer::interval() const
+{
+ return d_func()->intervalDuration.value();
+}
+
+QBindable<std::chrono::nanoseconds> QChronoTimer::bindableInterval()
+{
+ return {&d_func()->intervalDuration};
+}
+
+/*!
+ \property QChronoTimer::remainingTime
+ \brief The remaining time
+
+ Returns the remaining duration until the timeout.
+
+ If the timer is inactive, the returned duration will be negative.
+
+ If the timer is overdue, the returned duration will be \c 0ns.
+
+ \sa interval
+*/
+std::chrono::nanoseconds QChronoTimer::remainingTime() const
+{
+ if (isActive())
+ return QAbstractEventDispatcher::instance()->remainingTime(d_func()->id);
+ return std::chrono::nanoseconds::min();
+}
+
+/*!
+ \property QChronoTimer::timerType
+ \brief Controls the accuracy of the timer
+
+ The default value for this property is \c Qt::CoarseTimer.
+
+ \sa Qt::TimerType
+*/
+void QChronoTimer::setTimerType(Qt::TimerType atype)
+{
+ d_func()->type = atype;
+}
+
+Qt::TimerType QChronoTimer::timerType() const
+{
+ return d_func()->type;
+}
+
+QBindable<Qt::TimerType> QChronoTimer::bindableTimerType()
+{
+ return {&d_func()->type};
+}
+
+/*!
+ \overload
+ \reentrant
+
+ This static function calls the slot \a member, on object \a receiver, after
+ time interval \a interval. \a timerType affects the precision of the timer
+
+ \a member has to be a member function of \a receiver; you need to use the
+ \c SLOT() macro to get this parameter.
+
+ This function is provided as a convenience to save the need to use a
+ \l{QObject::timerEvent()}{timerEvent} or create a local QChronoTimer
+ object.
+
+ \sa start(), Qt::TimerType
+*/
+void QChronoTimer::singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
+ const QObject *receiver, const char *member)
+{
+ if (Q_UNLIKELY(interval < 0ns)) {
+ qWarning("QChronoTimer::singleShot: Timers cannot have negative timeouts");
+ return;
+ }
+ if (receiver && member) {
+ if (interval == 0ns) {
+ // special code shortpath for 0-timers
+ const char* bracketPosition = strchr(member, '(');
+ if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) {
+ qWarning("QChronoTimer::singleShot: Invalid slot specification");
+ return;
+ }
+ const auto methodName = QByteArrayView(member + 1, // extract method name
+ bracketPosition - 1 - member).trimmed();
+ QMetaObject::invokeMethod(const_cast<QObject *>(receiver),
+ methodName.toByteArray().constData(),
+ Qt::QueuedConnection);
+ return;
+ }
+ (void) new QSingleShotTimer(interval, timerType, receiver, member);
+ }
+}
+
+/*!
+ \internal
+
+ \list
+ \li \a interval the time interval
+ \li \a timerType the type of the timer; this affects the precision of
+ the timer
+ \li \a receiver the receiver or context object; if this is \c nullptr,
+ this method will figure out a context object to use, see code
+ comments below
+ \li \a slotObj a callable, for example a lambda
+ \endlist
+*/
+void QChronoTimer::singleShotImpl(std::chrono::nanoseconds interval, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
+{
+ if (interval == 0ns) {
+ bool deleteReceiver = false;
+ // Optimize: set a receiver context when none is given, such that we can use
+ // QMetaObject::invokeMethod which is more efficient than going through a timer.
+ // We need a QObject living in the current thread. But the QThread itself lives
+ // in a different thread - with the exception of the main QThread which lives in
+ // itself. And QThread::currentThread() is among the few QObjects we know that will
+ // most certainly be there. Note that one can actually call singleShot before the
+ // QApplication is created!
+ if (!receiver && QThread::currentThread() == QCoreApplicationPrivate::mainThread()) {
+ // reuse main thread as context object
+ receiver = QThread::currentThread();
+ } else if (!receiver) {
+ // Create a receiver context object on-demand. According to the benchmarks,
+ // this is still more efficient than going through a timer.
+ receiver = new QObject;
+ deleteReceiver = true;
+ }
+
+ auto h = QtPrivate::invokeMethodHelper({});
+ QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
+ Qt::QueuedConnection, h.parameterCount(), h.parameters.data(), h.typeNames.data(),
+ h.metaTypes.data());
+
+ if (deleteReceiver)
+ const_cast<QObject *>(receiver)->deleteLater();
+ return;
+ }
+
+ new QSingleShotTimer(interval, timerType, receiver, slotObj);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qchronotimer.cpp"
diff --git a/src/corelib/kernel/qchronotimer.h b/src/corelib/kernel/qchronotimer.h
new file mode 100644
index 0000000000..79c475e93c
--- /dev/null
+++ b/src/corelib/kernel/qchronotimer.h
@@ -0,0 +1,149 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCHRONOTIMER_H
+#define QCHRONOTIMER_H
+
+#ifndef QT_NO_QOBJECT
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+
+#include <chrono>
+
+QT_BEGIN_NAMESPACE
+
+class QTimerPrivate;
+class Q_CORE_EXPORT QChronoTimer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot
+ BINDABLE bindableSingleShot FINAL)
+ Q_PROPERTY(std::chrono::nanoseconds interval READ interval WRITE setInterval
+ BINDABLE bindableInterval FINAL)
+ Q_PROPERTY(std::chrono::nanoseconds remainingTime READ remainingTime FINAL)
+ Q_PROPERTY(Qt::TimerType timerType READ timerType WRITE setTimerType
+ BINDABLE bindableTimerType FINAL)
+ Q_PROPERTY(bool active READ isActive STORED false BINDABLE bindableActive FINAL)
+
+ template <typename Functor>
+ using FunctorContext = typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType;
+
+public:
+ explicit QChronoTimer(std::chrono::nanoseconds nsec, QObject *parent = nullptr);
+ explicit QChronoTimer(QObject *parent = nullptr);
+ ~QChronoTimer() override;
+
+ bool isActive() const;
+ QBindable<bool> bindableActive();
+ Qt::TimerId id() const;
+
+ void setInterval(std::chrono::nanoseconds nsec);
+ std::chrono::nanoseconds interval() const;
+ QBindable<std::chrono::nanoseconds> bindableInterval();
+
+ std::chrono::nanoseconds remainingTime() const;
+
+ void setTimerType(Qt::TimerType atype);
+ Qt::TimerType timerType() const;
+ QBindable<Qt::TimerType> bindableTimerType();
+
+ void setSingleShot(bool singleShot);
+ bool isSingleShot() const;
+ QBindable<bool> bindableSingleShot();
+
+ // singleShot with context
+#ifdef Q_QDOC
+ template <typename Functor>
+ static inline void singleShot(std::chrono::nanoseconds interval,
+ const QObject *receiver, Functor &&slot);
+ template <typename Functor>
+ static inline void singleShot(std::chrono::nanoseconds interval interval,
+ Qt::TimerType timerType,
+ const QObject *receiver, Functor &&slot);
+#else
+ template <typename Functor>
+ static void singleShot(std::chrono::nanoseconds interval,
+ const FunctorContext<Functor> *receiver, Functor &&slot)
+ {
+ singleShot(interval, defaultTimerTypeFor(interval), receiver, std::forward<Functor>(slot));
+ }
+ template <typename Functor>
+ static void singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
+ const FunctorContext<Functor> *receiver, Functor &&slot)
+ {
+ using Prototype = void(*)();
+ auto *slotObj = QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(slot));
+ singleShotImpl(interval, timerType, receiver, slotObj);
+ }
+#endif
+
+ template <typename Functor>
+ static void singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
+ Functor &&slot)
+ { singleShot(interval, timerType, nullptr, std::forward<Functor>(slot)); }
+
+ template <typename Functor>
+ static void singleShot(std::chrono::nanoseconds interval, Functor &&slot)
+ {
+ singleShot(interval, defaultTimerTypeFor(interval), nullptr, std::forward<Functor>(slot));
+ }
+
+ static void singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
+ const QObject *receiver, const char *member);
+ static void singleShot(std::chrono::nanoseconds interval, const QObject *receiver,
+ const char *member)
+ { singleShot(interval, defaultTimerTypeFor(interval), receiver, member); }
+
+#ifdef Q_QDOC
+ template <typename Functor>
+ QMetaObject::Connection callOnTimeout(const QObject *context, Functor &&slot,
+ Qt::ConnectionType connectionType = Qt::AutoConnection);
+#else
+ template <typename ... Args>
+ QMetaObject::Connection callOnTimeout(Args && ...args)
+ {
+ return QObject::connect(this, &QChronoTimer::timeout, std::forward<Args>(args)... );
+ }
+#endif
+
+public Q_SLOTS:
+ void start();
+ void stop();
+
+Q_SIGNALS:
+ void timeout(QPrivateSignal);
+
+protected:
+ void timerEvent(QTimerEvent *) override;
+
+private:
+ Q_DISABLE_COPY(QChronoTimer)
+
+ // QChronoTimer uses QTimerPrivate
+ inline QTimerPrivate *d_func() noexcept
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<QTimerPrivate *>(qGetPtrHelper(d_ptr));) }
+ inline const QTimerPrivate *d_func() const noexcept
+ { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const QTimerPrivate *>(qGetPtrHelper(d_ptr));) }
+
+ // These two functions are inherited from QObject
+ int startTimer(std::chrono::nanoseconds) = delete;
+ void killTimer(int) = delete;
+
+ static constexpr Qt::TimerType defaultTimerTypeFor(std::chrono::nanoseconds interval) noexcept
+ {
+ using namespace std::chrono_literals;
+ return interval >= 2s ? Qt::CoarseTimer : Qt::PreciseTimer;
+ }
+
+ static void singleShotImpl(std::chrono::nanoseconds interval, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QOBJECT
+
+#endif // QCHRONOTIMER_H
diff --git a/src/corelib/kernel/qcore_foundation.mm b/src/corelib/kernel/qcore_foundation.mm
index eb3c70756a..a31040944f 100644
--- a/src/corelib/kernel/qcore_foundation.mm
+++ b/src/corelib/kernel/qcore_foundation.mm
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2014 Petroules Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2014 Petroules Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qstring.h>
#include <QtCore/qurl.h>
@@ -46,7 +10,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qrect.h>
-#if QT_CONFIG(timezone) && !defined(QT_NO_SYSTEMLOCALE)
+#if QT_CONFIG(timezone)
#include <QtCore/qtimezone.h>
#include <QtCore/private/qtimezoneprivate_p.h>
#include <QtCore/private/qcore_mac_p.h>
@@ -62,9 +26,10 @@
QT_BEGIN_NAMESPACE
/*!
- \since 5.3
+ \brief Constructs a new QByteArray containing a copy of the CFData \a data.
- Constructs a new QByteArray containing a copy of the CFData \a data.
+ \since 5.3
+ \ingroup platform-type-conversions
\sa fromRawCFData(), fromRawData(), toRawCFData(), toCFData()
*/
@@ -77,15 +42,16 @@ QByteArray QByteArray::fromCFData(CFDataRef data)
}
/*!
- \since 5.3
-
- Constructs a QByteArray that uses the bytes of the CFData \a data.
+ \brief Constructs a QByteArray that uses the bytes of the CFData \a data.
The \a data's bytes are not copied.
The caller guarantees that the CFData will not be deleted
or modified as long as this QByteArray object exists.
+ \since 5.3
+ \ingroup platform-type-conversions
+
\sa fromCFData(), fromRawData(), toRawCFData(), toCFData()
*/
QByteArray QByteArray::fromRawCFData(CFDataRef data)
@@ -97,10 +63,12 @@ QByteArray QByteArray::fromRawCFData(CFDataRef data)
}
/*!
- \since 5.3
+ \brief Creates a CFData from a QByteArray.
- Creates a CFData from a QByteArray. The caller owns the CFData object
- and is responsible for releasing it.
+ The caller owns the CFData object and is responsible for releasing it.
+
+ \since 5.3
+ \ingroup platform-type-conversions
\sa toRawCFData(), fromCFData(), fromRawCFData(), fromRawData()
*/
@@ -110,15 +78,16 @@ CFDataRef QByteArray::toCFData() const
}
/*!
- \since 5.3
-
- Constructs a CFData that uses the bytes of the QByteArray.
+ \brief Constructs a CFData that uses the bytes of the QByteArray.
The QByteArray's bytes are not copied.
The caller guarantees that the QByteArray will not be deleted
or modified as long as this CFData object exists.
+ \since 5.3
+ \ingroup platform-type-conversions
+
\sa toCFData(), fromRawCFData(), fromCFData(), fromRawData()
*/
CFDataRef QByteArray::toRawCFData() const
@@ -128,9 +97,10 @@ CFDataRef QByteArray::toRawCFData() const
}
/*!
- \since 5.3
+ \brief Constructs a new QByteArray containing a copy of the NSData \a data.
- Constructs a new QByteArray containing a copy of the NSData \a data.
+ \since 5.3
+ \ingroup platform-type-conversions
\sa fromRawNSData(), fromRawData(), toNSData(), toRawNSData()
*/
@@ -142,15 +112,16 @@ QByteArray QByteArray::fromNSData(const NSData *data)
}
/*!
- \since 5.3
-
- Constructs a QByteArray that uses the bytes of the NSData \a data.
+ \brief Constructs a QByteArray that uses the bytes of the NSData \a data.
The \a data's bytes are not copied.
The caller guarantees that the NSData will not be deleted
or modified as long as this QByteArray object exists.
+ \since 5.3
+ \ingroup platform-type-conversions
+
\sa fromNSData(), fromRawData(), toRawNSData(), toNSData()
*/
QByteArray QByteArray::fromRawNSData(const NSData *data)
@@ -161,9 +132,12 @@ QByteArray QByteArray::fromRawNSData(const NSData *data)
}
/*!
- \since 5.3
+ \brief Creates a NSData from a QByteArray.
- Creates a NSData from a QByteArray. The NSData object is autoreleased.
+ The NSData object is autoreleased.
+
+ \since 5.3
+ \ingroup platform-type-conversions
\sa fromNSData(), fromRawNSData(), fromRawData(), toRawNSData()
*/
@@ -173,15 +147,16 @@ NSData *QByteArray::toNSData() const
}
/*!
- \since 5.3
-
- Constructs a NSData that uses the bytes of the QByteArray.
+ \brief Constructs a NSData that uses the bytes of the QByteArray.
The QByteArray's bytes are not copied.
The caller guarantees that the QByteArray will not be deleted
or modified as long as this NSData object exists.
+ \since 5.3
+ \ingroup platform-type-conversions
+
\sa fromRawNSData(), fromNSData(), fromRawData(), toNSData()
*/
NSData *QByteArray::toRawNSData() const
@@ -193,11 +168,12 @@ NSData *QByteArray::toRawNSData() const
// ----------------------------------------------------------------------------
/*!
- \since 5.2
-
- Constructs a new QString containing a copy of the \a string CFString.
+ \brief Constructs a new QString containing a copy of the \a string CFString.
\note this function is only available on \macos and iOS.
+
+ \since 5.2
+ \ingroup platform-type-conversions
*/
QString QString::fromCFString(CFStringRef string)
{
@@ -217,12 +193,14 @@ QString QString::fromCFString(CFStringRef string)
}
/*!
- \since 5.2
+ \brief Creates a CFString from a QString.
- Creates a CFString from a QString. The caller owns the CFString and is
- responsible for releasing it.
+ The caller owns the CFString and is responsible for releasing it.
\note this function is only available on \macos and iOS.
+
+ \since 5.2
+ \ingroup platform-type-conversions
*/
CFStringRef QString::toCFString() const
{
@@ -230,12 +208,14 @@ CFStringRef QString::toCFString() const
}
/*!
- \since 6.0
+ \brief Creates a CFString from this QStringView.
- Creates a CFString from this QStringView. The caller owns the CFString and is
- responsible for releasing it.
+ The caller owns the CFString and is responsible for releasing it.
\note this function is only available on \macos and iOS.
+
+ \since 6.0
+ \ingroup platform-type-conversions
*/
CFStringRef QStringView::toCFString() const
{
@@ -243,11 +223,12 @@ CFStringRef QStringView::toCFString() const
}
/*!
- \since 5.2
-
- Constructs a new QString containing a copy of the \a string NSString.
+ \brief Constructs a new QString containing a copy of the \a string NSString.
\note this function is only available on \macos and iOS.
+
+ \since 5.2
+ \ingroup platform-type-conversions
*/
QString QString::fromNSString(const NSString *string)
{
@@ -260,11 +241,14 @@ QString QString::fromNSString(const NSString *string)
}
/*!
- \since 5.2
+ \brief Creates a NSString from a QString.
- Creates a NSString from a QString. The NSString is autoreleased.
+ The NSString is autoreleased.
\note this function is only available on \macos and iOS.
+
+ \since 5.2
+ \ingroup platform-type-conversions
*/
NSString *QString::toNSString() const
{
@@ -272,11 +256,14 @@ NSString *QString::toNSString() const
}
/*!
- \since 6.0
+ \brief Creates an NSString from this QStringView.
- Creates an NSString from this QStringView. The NSString is autoreleased.
+ The NSString is autoreleased.
\note this function is only available on \macos and iOS.
+
+ \since 6.0
+ \ingroup platform-type-conversions
*/
NSString *QStringView::toNSString() const
{
@@ -286,27 +273,30 @@ NSString *QStringView::toNSString() const
// ----------------------------------------------------------------------------
/*!
- \since 5.7
-
- Constructs a new QUuid containing a copy of the \a uuid CFUUID.
+ \brief Constructs a new QUuid containing a copy of the \a uuid CFUUID.
\note this function is only available on Apple platforms.
+
+ \since 5.7
+ \ingroup platform-type-conversions
*/
QUuid QUuid::fromCFUUID(CFUUIDRef uuid)
{
if (!uuid)
return QUuid();
const CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
- return QUuid::fromRfc4122(QByteArray::fromRawData(reinterpret_cast<const char *>(&bytes), sizeof(bytes)));
+ return QUuid::fromRfc4122(QByteArrayView(reinterpret_cast<const char *>(&bytes), sizeof(bytes)));
}
/*!
- \since 5.7
+ \brief Creates a CFUUID from a QUuid.
- Creates a CFUUID from a QUuid. The caller owns the CFUUID and is
- responsible for releasing it.
+ The caller owns the CFUUID and is responsible for releasing it.
\note this function is only available on Apple platforms.
+
+ \since 5.7
+ \ingroup platform-type-conversions
*/
CFUUIDRef QUuid::toCFUUID() const
{
@@ -315,11 +305,12 @@ CFUUIDRef QUuid::toCFUUID() const
}
/*!
- \since 5.7
-
- Constructs a new QUuid containing a copy of the \a uuid NSUUID.
+ \brief Constructs a new QUuid containing a copy of the \a uuid NSUUID.
\note this function is only available on Apple platforms.
+
+ \since 5.7
+ \ingroup platform-type-conversions
*/
QUuid QUuid::fromNSUUID(const NSUUID *uuid)
{
@@ -327,15 +318,18 @@ QUuid QUuid::fromNSUUID(const NSUUID *uuid)
return QUuid();
uuid_t bytes;
[uuid getUUIDBytes:bytes];
- return QUuid::fromRfc4122(QByteArray::fromRawData(reinterpret_cast<const char *>(bytes), sizeof(bytes)));
+ return QUuid::fromRfc4122(QByteArrayView(reinterpret_cast<const char *>(bytes), sizeof(bytes)));
}
/*!
- \since 5.7
+ \brief Creates a NSUUID from a QUuid.
- Creates a NSUUID from a QUuid. The NSUUID is autoreleased.
+ The NSUUID is autoreleased.
\note this function is only available on Apple platforms.
+
+ \since 5.7
+ \ingroup platform-type-conversions
*/
NSUUID *QUuid::toNSUUID() const
{
@@ -347,9 +341,10 @@ NSUUID *QUuid::toNSUUID() const
/*!
- \since 5.2
+ \brief Constructs a QUrl containing a copy of the CFURL \a url.
- Constructs a QUrl containing a copy of the CFURL \a url.
+ \since 5.2
+ \ingroup platform-type-conversions
*/
QUrl QUrl::fromCFURL(CFURLRef url)
{
@@ -359,10 +354,12 @@ QUrl QUrl::fromCFURL(CFURLRef url)
}
/*!
- \since 5.2
+ \brief Creates a CFURL from a QUrl.
- Creates a CFURL from a QUrl. The caller owns the CFURL and is
- responsible for releasing it.
+ The caller owns the CFURL and is responsible for releasing it.
+
+ \since 5.2
+ \ingroup platform-type-conversions
*/
CFURLRef QUrl::toCFURL() const
{
@@ -376,9 +373,10 @@ CFURLRef QUrl::toCFURL() const
}
/*!
- \since 5.2
+ \brief Constructs a QUrl containing a copy of the NSURL \a url.
- Constructs a QUrl containing a copy of the NSURL \a url.
+ \since 5.2
+ \ingroup platform-type-conversions
*/
QUrl QUrl::fromNSURL(const NSURL *url)
{
@@ -388,9 +386,12 @@ QUrl QUrl::fromNSURL(const NSURL *url)
}
/*!
- \since 5.2
+ \brief Creates a NSURL from a QUrl.
- Creates a NSURL from a QUrl. The NSURL is autoreleased.
+ The NSURL is autoreleased.
+
+ \since 5.2
+ \ingroup platform-type-conversions
*/
NSURL *QUrl::toNSURL() const
{
@@ -401,9 +402,10 @@ NSURL *QUrl::toNSURL() const
/*!
- \since 5.5
+ \brief Constructs a new QDateTime containing a copy of the CFDate \a date.
- Constructs a new QDateTime containing a copy of the CFDate \a date.
+ \since 5.5
+ \ingroup platform-type-conversions
\sa toCFDate()
*/
@@ -416,10 +418,12 @@ QDateTime QDateTime::fromCFDate(CFDateRef date)
}
/*!
- \since 5.5
+ \brief Creates a CFDate from a QDateTime.
+
+ The caller owns the CFDate object and is responsible for releasing it.
- Creates a CFDate from a QDateTime. The caller owns the CFDate object
- and is responsible for releasing it.
+ \since 5.5
+ \ingroup platform-type-conversions
\sa fromCFDate()
*/
@@ -430,9 +434,10 @@ CFDateRef QDateTime::toCFDate() const
}
/*!
- \since 5.5
+ \brief Constructs a new QDateTime containing a copy of the NSDate \a date.
- Constructs a new QDateTime containing a copy of the NSDate \a date.
+ \since 5.5
+ \ingroup platform-type-conversions
\sa toNSDate()
*/
@@ -444,9 +449,12 @@ QDateTime QDateTime::fromNSDate(const NSDate *date)
}
/*!
- \since 5.5
+ \brief Creates an NSDate from a QDateTime.
- Creates an NSDate from a QDateTime. The NSDate object is autoreleased.
+ The NSDate object is autoreleased.
+
+ \since 5.5
+ \ingroup platform-type-conversions
\sa fromNSDate()
*/
@@ -458,11 +466,12 @@ NSDate *QDateTime::toNSDate() const
// ----------------------------------------------------------------------------
-#if QT_CONFIG(timezone) && !defined(QT_NO_SYSTEMLOCALE)
+#if QT_CONFIG(timezone)
/*!
- \since 5.9
+ \brief Constructs a new QTimeZone containing a copy of the CFTimeZone \a timeZone.
- Constructs a new QTimeZone containing a copy of the CFTimeZone \a timeZone.
+ \since 5.9
+ \ingroup platform-type-conversions
\sa toCFTimeZone()
*/
@@ -474,26 +483,29 @@ QTimeZone QTimeZone::fromCFTimeZone(CFTimeZoneRef timeZone)
}
/*!
- \since 5.9
+ \brief Creates a CFTimeZone from a QTimeZone.
- Creates a CFTimeZone from a QTimeZone. The caller owns the CFTimeZone object
- and is responsible for releasing it.
+ The caller owns the CFTimeZone object and is responsible for releasing it.
+
+ \since 5.9
+ \ingroup platform-type-conversions
\sa fromCFTimeZone()
*/
CFTimeZoneRef QTimeZone::toCFTimeZone() const
{
#ifndef QT_NO_DYNAMIC_CAST
- Q_ASSERT(dynamic_cast<const QMacTimeZonePrivate *>(d.data()));
+ Q_ASSERT(dynamic_cast<const QMacTimeZonePrivate *>(d.d));
#endif
- const QMacTimeZonePrivate *p = static_cast<const QMacTimeZonePrivate *>(d.data());
+ const QMacTimeZonePrivate *p = static_cast<const QMacTimeZonePrivate *>(d.d);
return reinterpret_cast<CFTimeZoneRef>([p->nsTimeZone() copy]);
}
/*!
- \since 5.9
+ \brief Constructs a new QTimeZone containing a copy of the NSTimeZone \a timeZone.
- Constructs a new QTimeZone containing a copy of the NSTimeZone \a timeZone.
+ \since 5.9
+ \ingroup platform-type-conversions
\sa toNSTimeZone()
*/
@@ -505,9 +517,12 @@ QTimeZone QTimeZone::fromNSTimeZone(const NSTimeZone *timeZone)
}
/*!
- \since 5.9
+ \brief Creates an NSTimeZone from a QTimeZone.
- Creates an NSTimeZone from a QTimeZone. The NSTimeZone object is autoreleased.
+ The NSTimeZone object is autoreleased.
+
+ \since 5.9
+ \ingroup platform-type-conversions
\sa fromNSTimeZone()
*/
@@ -520,9 +535,10 @@ NSTimeZone *QTimeZone::toNSTimeZone() const
// ----------------------------------------------------------------------------
/*!
- \since 5.8
+ \brief Creates a CGRect from a QRect.
- Creates a CGRect from a QRect.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa QRectF::fromCGRect()
*/
@@ -532,9 +548,10 @@ CGRect QRect::toCGRect() const noexcept
}
/*!
- \since 5.8
+ \brief Creates a CGRect from a QRectF.
- Creates a CGRect from a QRectF.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa fromCGRect()
*/
@@ -544,9 +561,10 @@ CGRect QRectF::toCGRect() const noexcept
}
/*!
- \since 5.8
+ \brief Creates a QRectF from CGRect \a rect.
- Creates a QRectF from CGRect \a rect.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa toCGRect()
*/
@@ -558,9 +576,10 @@ QRectF QRectF::fromCGRect(CGRect rect) noexcept
// ----------------------------------------------------------------------------
/*!
- \since 5.8
+ \brief Creates a CGPoint from a QPoint.
- Creates a CGPoint from a QPoint.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa QPointF::fromCGPoint()
*/
@@ -570,9 +589,10 @@ CGPoint QPoint::toCGPoint() const noexcept
}
/*!
- \since 5.8
+ \brief Creates a CGPoint from a QPointF.
- Creates a CGPoint from a QPointF.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa fromCGPoint()
*/
@@ -582,9 +602,10 @@ CGPoint QPointF::toCGPoint() const noexcept
}
/*!
- \since 5.8
+ \brief Creates a QRectF from CGPoint \a point.
- Creates a QRectF from CGPoint \a point.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa toCGPoint()
*/
@@ -596,9 +617,10 @@ QPointF QPointF::fromCGPoint(CGPoint point) noexcept
// ----------------------------------------------------------------------------
/*!
- \since 5.8
+ \brief Creates a CGSize from a QSize.
- Creates a CGSize from a QSize.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa QSizeF::fromCGSize()
*/
@@ -608,9 +630,10 @@ CGSize QSize::toCGSize() const noexcept
}
/*!
- \since 5.8
+ \brief Creates a CGSize from a QSizeF.
- Creates a CGSize from a QSizeF.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa fromCGSize()
*/
@@ -620,9 +643,10 @@ CGSize QSizeF::toCGSize() const noexcept
}
/*!
- \since 5.8
+ \brief Creates a QRectF from \a size.
- Creates a QRectF from \a size.
+ \since 5.8
+ \ingroup platform-type-conversions
\sa toCGSize()
*/
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
index c1ba9a7b9e..54c4373aed 100644
--- a/src/corelib/kernel/qcore_mac.mm
+++ b/src/corelib/kernel/qcore_mac.mm
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Petroules Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 Petroules Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qcore_mac_p.h>
@@ -53,19 +17,58 @@
#include <dlfcn.h>
#include <cxxabi.h>
#include <objc/runtime.h>
+#include <mach-o/dyld.h>
+#include <sys/sysctl.h>
+#include <spawn.h>
#include <qdebug.h>
+#include "qendian.h"
#include "qhash.h"
-#include "qpair.h"
#include "qmutex.h"
#include "qvarlengtharray.h"
#include "private/qlocking_p.h"
+#if !defined(QT_BOOTSTRAPPED)
+#include <thread>
+#endif
+
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+extern "C" {
+typedef uint32_t csr_config_t;
+extern int csr_get_active_config(csr_config_t *) __attribute__((weak_import));
+
+#ifdef QT_BUILD_INTERNAL
+int responsibility_spawnattrs_setdisclaim(posix_spawnattr_t attrs, int disclaim)
+__attribute__((availability(macos,introduced=10.14),weak_import));
+pid_t responsibility_get_pid_responsible_for_pid(pid_t) __attribute__((weak_import));
+char *** _NSGetArgv();
+extern char **environ;
+#endif
+}
+#endif
+
QT_BEGIN_NAMESPACE
// --------------------------------------------------------------------------
+#if defined(Q_OS_MACOS)
+static void initializeStandardUserDefaults()
+{
+ // The standard user defaults are initialized from an ordered list of domains,
+ // as documented by NSUserDefaults.standardUserDefaults. This includes e.g.
+ // parsing command line arguments, such as -AppleFooBar "baz", as well as
+ // global defaults. To ensure that these defaults are available through
+ // the lower level Core Foundation preferences APIs, we need to initialize
+ // them as early as possible via the Foundation-API, as the lower level APIs
+ // do not do this initialization.
+ Q_UNUSED(NSUserDefaults.standardUserDefaults);
+}
+Q_CONSTRUCTOR_FUNCTION(initializeStandardUserDefaults);
+#endif
+
+// --------------------------------------------------------------------------
+
QCFString::operator QString() const
{
if (string.isEmpty() && value)
@@ -84,17 +87,35 @@ QCFString::operator CFStringRef() const
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
-bool AppleUnifiedLogger::willMirrorToStderr()
+bool AppleUnifiedLogger::preventsStderrLogging()
{
- // When running under Xcode or LLDB, one or more of these variables will
- // be set, which triggers libsystem_trace.dyld to log messages to stderr
- // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables
- // is not an option, as that would silence normal NSLog or os_log calls,
- // so instead we skip our own stderr output. See rdar://36919139.
+ // os_log will mirror to stderr if OS_ACTIVITY_DT_MODE is set,
+ // regardless of its value. OS_ACTIVITY_MODE then controls whether
+ // to include info and/or debug messages in this mirroring.
+ // For some reason, when launched under lldb (via Xcode or not),
+ // all levels are included.
+
+ // CFLog will normally log to both stderr, and via os_log.
+ // Setting CFLOG_FORCE_DISABLE_STDERR disables the stderr
+ // logging. Setting CFLOG_FORCE_STDERR will both duplicate
+ // CFLog's output to stderr, and trigger OS_ACTIVITY_DT_MODE,
+ // resulting in os_log calls also being mirrored to stderr.
+ // Setting ACTIVITY_LOG_STDERR has the same effect.
+
+ // NSLog is plumbed to CFLog, and will respond to the same
+ // environment variables as CFLog.
+
+ // We want to disable Qt's default stderr log handler when
+ // os_log has already mirrored to stderr.
static bool willMirror = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE")
- || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR")
- || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR");
- return willMirror;
+ || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR")
+ || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR");
+
+ // As well as when we suspect that Xcode is going to present os_log
+ // as structured log messages.
+ static bool disableStderr = qEnvironmentVariableIsSet("CFLOG_FORCE_DISABLE_STDERR");
+
+ return willMirror || disableStderr;
}
QT_MAC_WEAK_IMPORT(_os_log_default);
@@ -115,7 +136,7 @@ bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogCont
const bool isDefault = !context.category || !strcmp(context.category, "default");
os_log_t log = isDefault ? OS_LOG_DEFAULT :
- cachedLog(subsystem, QString::fromLatin1(context.category));
+ os_log_create(subsystem.toLatin1().constData(), context.category);
os_log_type_t logType = logTypeForMessageType(msgType);
if (!os_log_type_enabled(log, logType))
@@ -135,7 +156,7 @@ bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogCont
// system from redacting our log message.
os_log_with_type(log, logType, "%{public}s", qPrintable(message));
- return willMirrorToStderr();
+ return preventsStderrLogging();
}
os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType)
@@ -151,33 +172,31 @@ os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType)
return OS_LOG_TYPE_DEFAULT;
}
-os_log_t AppleUnifiedLogger::cachedLog(const QString &subsystem, const QString &category)
-{
- static QBasicMutex mutex;
- const auto locker = qt_scoped_lock(mutex);
+#endif // QT_USE_APPLE_UNIFIED_LOGGING
- static QHash<QPair<QString, QString>, os_log_t> logs;
- const auto cacheKey = qMakePair(subsystem, category);
- os_log_t log = logs.value(cacheKey);
+// -------------------------------------------------------------------------
- if (!log) {
- log = os_log_create(subsystem.toLatin1().constData(),
- category.toLatin1().constData());
- logs.insert(cacheKey, log);
+QDebug operator<<(QDebug dbg, id obj)
+{
+ if (!obj) {
+ // Match NSLog
+ dbg << "(null)";
+ return dbg;
+ }
- // Technically we should release the os_log_t resource when done
- // with it, but since we don't know when a category is disabled
- // we keep all cached os_log_t instances until shutdown, where
- // the OS will clean them up for us.
+ for (Class cls = object_getClass(obj); cls; cls = class_getSuperclass(cls)) {
+ if (cls == NSObject.class) {
+ dbg << static_cast<NSObject*>(obj);
+ return dbg;
+ }
}
- return log;
+ // Match NSObject.debugDescription
+ const QDebugStateSaver saver(dbg);
+ dbg.nospace() << '<' << object_getClassName(obj) << ": " << static_cast<void*>(obj) << '>';
+ return dbg;
}
-#endif // QT_USE_APPLE_UNIFIED_LOGGING
-
-// -------------------------------------------------------------------------
-
QDebug operator<<(QDebug dbg, const NSObject *nsObject)
{
return dbg << (nsObject ?
@@ -214,63 +233,42 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
QT_END_NAMESPACE
QT_USE_NAMESPACE
+
+#ifdef QT_DEBUG
@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
@end
-@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) {
- NSAutoreleasePool **m_pool;
-}
-
-- (instancetype)initWithPool:(NSAutoreleasePool **)pool
-{
- if ((self = [self init]))
- m_pool = pool;
- return self;
-}
-
-- (void)dealloc
-{
- if (*m_pool) {
- // The pool is still valid, which means we're not being drained from
- // the corresponding QMacAutoReleasePool (see below).
-
- // QMacAutoReleasePool has only a single member, the NSAutoreleasePool*
- // so the address of that member is also the QMacAutoReleasePool itself.
- QMacAutoReleasePool *pool = reinterpret_cast<QMacAutoReleasePool *>(m_pool);
- qWarning() << "Premature drain of" << pool << "This can happen if you've allocated"
- << "the pool on the heap, or as a member of a heap-allocated object. This is not a"
- << "supported use of QMacAutoReleasePool, and might result in crashes when objects"
- << "in the pool are deallocated and then used later on under the assumption they"
- << "will be valid until" << pool << "has been drained.";
+@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
+@end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
+#endif // QT_DEBUG
- // Reset the pool so that it's not drained again later on
- *m_pool = nullptr;
- }
+// Use the direct runtime interface to manage autorelease pools, as it
+// has less overhead then allocating NSAutoreleasePools, and allows for
+// a future where we use ARC (where NSAutoreleasePool is not allowed).
+// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
- [super dealloc];
+extern "C" {
+void *objc_autoreleasePoolPush(void);
+void objc_autoreleasePoolPop(void *pool);
}
-@end
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
QT_BEGIN_NAMESPACE
QMacAutoReleasePool::QMacAutoReleasePool()
- : pool([[NSAutoreleasePool alloc] init])
+ : pool(objc_autoreleasePoolPush())
{
+#ifdef QT_DEBUG
+ static const bool debugAutoReleasePools = qEnvironmentVariableIsSet("QT_DARWIN_DEBUG_AUTORELEASEPOOLS");
+ if (!debugAutoReleasePools)
+ return;
+
Class trackerClass = [QMacAutoReleasePoolTracker class];
-#ifdef QT_DEBUG
void *poolFrame = nullptr;
- if (__builtin_available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 5.0, *)) {
- void *frame;
- if (backtrace_from_fp(__builtin_frame_address(0), &frame, 1))
- poolFrame = frame;
- } else {
- static const int maxFrames = 3;
- void *callstack[maxFrames];
- if (backtrace(callstack, maxFrames) == maxFrames)
- poolFrame = callstack[maxFrames - 1];
- }
+ void *frames[2];
+ if (backtrace_from_fp(__builtin_frame_address(0), frames, 2))
+ poolFrame = frames[1];
if (poolFrame) {
Dl_info info;
@@ -296,30 +294,14 @@ QMacAutoReleasePool::QMacAutoReleasePool()
free((char*)symbolName);
}
}
-#endif
- [[[trackerClass alloc] initWithPool:
- reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
+ [[trackerClass new] autorelease];
+#endif // QT_DEBUG
}
QMacAutoReleasePool::~QMacAutoReleasePool()
{
- if (!pool) {
- qWarning() << "Prematurely drained pool" << this << "finally drained. Any objects belonging"
- << "to this pool have already been released, and have potentially been invalid since the"
- << "premature drain earlier on.";
- return;
- }
-
- // Save and reset pool before draining, so that the pool tracker can know
- // that it's being drained by its owning pool.
- NSAutoreleasePool *savedPool = static_cast<NSAutoreleasePool*>(pool);
- pool = nullptr;
-
- // Drain behaves the same as release, with the advantage that
- // if we're ever used in a garbage-collected environment, the
- // drain acts as a hint to the garbage collector to collect.
- [savedPool drain];
+ objc_autoreleasePoolPop(pool);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -341,15 +323,102 @@ QDebug operator<<(QDebug debug, const QCFString &string)
#ifdef Q_OS_MACOS
bool qt_mac_applicationIsInDarkMode()
{
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
- if (__builtin_available(macOS 10.14, *)) {
- auto appearance = [NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:
- @[ NSAppearanceNameAqua, NSAppearanceNameDarkAqua ]];
- return [appearance isEqualToString:NSAppearanceNameDarkAqua];
+ auto appearance = [NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:
+ @[ NSAppearanceNameAqua, NSAppearanceNameDarkAqua ]];
+ return [appearance isEqualToString:NSAppearanceNameDarkAqua];
+}
+
+bool qt_mac_runningUnderRosetta()
+{
+ int translated = 0;
+ auto size = sizeof(translated);
+ if (sysctlbyname("sysctl.proc_translated", &translated, &size, nullptr, 0) == 0)
+ return translated;
+ return false;
+}
+
+std::optional<uint32_t> qt_mac_sipConfiguration()
+{
+ static auto configuration = []() -> std::optional<uint32_t> {
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+ csr_config_t config;
+ if (csr_get_active_config && csr_get_active_config(&config) == 0)
+ return config;
+#endif
+
+ QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMainPortDefault, "IODeviceTree:/options");
+ if (!nvram) {
+ qWarning("Failed to locate NVRAM entry in IO registry");
+ return {};
+ }
+
+ QCFType<CFTypeRef> csrConfig = IORegistryEntryCreateCFProperty(nvram,
+ CFSTR("csr-active-config"), kCFAllocatorDefault, IOOptionBits{});
+ if (!csrConfig)
+ return {}; // SIP config is not available
+
+ if (auto type = CFGetTypeID(csrConfig); type != CFDataGetTypeID()) {
+ qWarning() << "Unexpected SIP config type" << CFCopyTypeIDDescription(type);
+ return {};
+ }
+
+ QByteArray data = QByteArray::fromRawCFData(csrConfig.as<CFDataRef>());
+ if (data.size() != sizeof(uint32_t)) {
+ qWarning() << "Unexpected SIP config size" << data.size();
+ return {};
+ }
+
+ return qFromLittleEndian<uint32_t>(data.constData());
+ }();
+ return configuration;
+}
+
+#define CHECK_SPAWN(expr) \
+ if (int err = (expr)) { \
+ posix_spawnattr_destroy(&attr); \
+ return; \
}
+
+#ifdef QT_BUILD_INTERNAL
+void qt_mac_ensureResponsible()
+{
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+ if (!responsibility_get_pid_responsible_for_pid || !responsibility_spawnattrs_setdisclaim)
+ return;
+
+ auto pid = getpid();
+ if (responsibility_get_pid_responsible_for_pid(pid) == pid)
+ return; // Already responsible
+
+ posix_spawnattr_t attr = {};
+ CHECK_SPAWN(posix_spawnattr_init(&attr));
+
+ // Behave as exec
+ short flags = POSIX_SPAWN_SETEXEC;
+
+ // Reset signal mask
+ sigset_t no_signals;
+ sigemptyset(&no_signals);
+ CHECK_SPAWN(posix_spawnattr_setsigmask(&attr, &no_signals));
+ flags |= POSIX_SPAWN_SETSIGMASK;
+
+ // Reset all signals to their default handlers
+ sigset_t all_signals;
+ sigfillset(&all_signals);
+ CHECK_SPAWN(posix_spawnattr_setsigdefault(&attr, &all_signals));
+ flags |= POSIX_SPAWN_SETSIGDEF;
+
+ CHECK_SPAWN(posix_spawnattr_setflags(&attr, flags));
+
+ CHECK_SPAWN(responsibility_spawnattrs_setdisclaim(&attr, 1));
+
+ char **argv = *_NSGetArgv();
+ posix_spawnp(&pid, argv[0], nullptr, &attr, argv, environ);
+ posix_spawnattr_destroy(&attr);
#endif
- return false;
}
+#endif // QT_BUILD_INTERNAL
+
#endif
bool qt_apple_isApplicationExtension()
@@ -380,32 +449,64 @@ AppleApplication *qt_apple_sharedApplication()
}
#endif
-#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
+#if !defined(QT_BOOTSTRAPPED)
+
+#if defined(Q_OS_MACOS)
+namespace {
+struct SandboxChecker
+{
+ SandboxChecker() : m_thread([this]{
+ m_isSandboxed = []{
+ QCFType<SecStaticCodeRef> staticCode = nullptr;
+ NSURL *executableUrl = NSBundle.mainBundle.executableURL;
+ if (SecStaticCodeCreateWithPath((__bridge CFURLRef)executableUrl,
+ kSecCSDefaultFlags, &staticCode) != errSecSuccess)
+ return false;
+
+ QCFType<SecRequirementRef> sandboxRequirement;
+ if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"),
+ kSecCSDefaultFlags, &sandboxRequirement) != errSecSuccess)
+ return false;
+
+ if (SecStaticCodeCheckValidityWithErrors(staticCode,
+ kSecCSBasicValidateOnly, sandboxRequirement, nullptr) != errSecSuccess)
+ return false;
+
+ return true;
+ }();
+ })
+ {}
+ ~SandboxChecker() {
+ std::scoped_lock lock(m_mutex);
+ if (m_thread.joinable())
+ m_thread.detach();
+ }
+ bool isSandboxed() const {
+ std::scoped_lock lock(m_mutex);
+ if (m_thread.joinable())
+ m_thread.join();
+ return m_isSandboxed;
+ }
+private:
+ bool m_isSandboxed;
+ mutable std::thread m_thread;
+ mutable std::mutex m_mutex;
+};
+} // namespace
+static SandboxChecker sandboxChecker;
+#endif // Q_OS_MACOS
+
bool qt_apple_isSandboxed()
{
- static bool isSandboxed = []() {
- QCFType<SecStaticCodeRef> staticCode = nullptr;
- NSURL *bundleUrl = [[NSBundle mainBundle] bundleURL];
- if (SecStaticCodeCreateWithPath((__bridge CFURLRef)bundleUrl,
- kSecCSDefaultFlags, &staticCode) != errSecSuccess)
- return false;
-
- QCFType<SecRequirementRef> sandboxRequirement;
- if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"),
- kSecCSDefaultFlags, &sandboxRequirement) != errSecSuccess)
- return false;
-
- if (SecStaticCodeCheckValidityWithErrors(staticCode,
- kSecCSBasicValidateOnly, sandboxRequirement, nullptr) != errSecSuccess)
- return false;
-
- return true;
- }();
- return isSandboxed;
+#if defined(Q_OS_MACOS)
+ return sandboxChecker.isSandboxed();
+#else
+ return true; // All other Apple platforms
+#endif
}
QT_END_NAMESPACE
-@implementation NSObject (QtSandboxHelpers)
+@implementation NSObject (QtExtras)
- (id)qt_valueForPrivateKey:(NSString *)key
{
if (qt_apple_isSandboxed())
@@ -415,7 +516,7 @@ QT_END_NAMESPACE
}
@end
QT_BEGIN_NAMESPACE
-#endif
+#endif // !QT_BOOTSTRAPPED
#ifdef Q_OS_MACOS
/*
@@ -458,148 +559,6 @@ QMacRootLevelAutoReleasePool::~QMacRootLevelAutoReleasePool()
// -------------------------------------------------------------------------
-#ifdef Q_OS_MACOS
-
-// Use this method to keep all the information in the TextSegment. As long as it is ordered
-// we are in OK shape, and we can influence that ourselves.
-struct KeyPair
-{
- QChar cocoaKey;
- Qt::Key qtKey;
-};
-
-bool operator==(const KeyPair &entry, QChar qchar)
-{
- return entry.cocoaKey == qchar;
-}
-
-bool operator<(const KeyPair &entry, QChar qchar)
-{
- return entry.cocoaKey < qchar;
-}
-
-bool operator<(QChar qchar, const KeyPair &entry)
-{
- return qchar < entry.cocoaKey;
-}
-
-bool operator<(const Qt::Key &key, const KeyPair &entry)
-{
- return key < entry.qtKey;
-}
-
-bool operator<(const KeyPair &entry, const Qt::Key &key)
-{
- return entry.qtKey < key;
-}
-
-struct qtKey2CocoaKeySortLessThan
-{
- typedef bool result_type;
- Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const noexcept
- {
- return entry1.qtKey < entry2.qtKey;
- }
-};
-
-static const int NSEscapeCharacter = 27; // not defined by Cocoa headers
-static const int NumEntries = 59;
-static const KeyPair entries[NumEntries] = {
- { NSEnterCharacter, Qt::Key_Enter },
- { NSBackspaceCharacter, Qt::Key_Backspace },
- { NSTabCharacter, Qt::Key_Tab },
- { NSNewlineCharacter, Qt::Key_Return },
- { NSCarriageReturnCharacter, Qt::Key_Return },
- { NSBackTabCharacter, Qt::Key_Backtab },
- { NSEscapeCharacter, Qt::Key_Escape },
- // Cocoa sends us delete when pressing backspace!
- // (NB when we reverse this list in qtKey2CocoaKey, there
- // will be two indices of Qt::Key_Backspace. But is seems to work
- // ok for menu shortcuts (which uses that function):
- { NSDeleteCharacter, Qt::Key_Backspace },
- { NSUpArrowFunctionKey, Qt::Key_Up },
- { NSDownArrowFunctionKey, Qt::Key_Down },
- { NSLeftArrowFunctionKey, Qt::Key_Left },
- { NSRightArrowFunctionKey, Qt::Key_Right },
- { NSF1FunctionKey, Qt::Key_F1 },
- { NSF2FunctionKey, Qt::Key_F2 },
- { NSF3FunctionKey, Qt::Key_F3 },
- { NSF4FunctionKey, Qt::Key_F4 },
- { NSF5FunctionKey, Qt::Key_F5 },
- { NSF6FunctionKey, Qt::Key_F6 },
- { NSF7FunctionKey, Qt::Key_F7 },
- { NSF8FunctionKey, Qt::Key_F8 },
- { NSF9FunctionKey, Qt::Key_F9 },
- { NSF10FunctionKey, Qt::Key_F10 },
- { NSF11FunctionKey, Qt::Key_F11 },
- { NSF12FunctionKey, Qt::Key_F12 },
- { NSF13FunctionKey, Qt::Key_F13 },
- { NSF14FunctionKey, Qt::Key_F14 },
- { NSF15FunctionKey, Qt::Key_F15 },
- { NSF16FunctionKey, Qt::Key_F16 },
- { NSF17FunctionKey, Qt::Key_F17 },
- { NSF18FunctionKey, Qt::Key_F18 },
- { NSF19FunctionKey, Qt::Key_F19 },
- { NSF20FunctionKey, Qt::Key_F20 },
- { NSF21FunctionKey, Qt::Key_F21 },
- { NSF22FunctionKey, Qt::Key_F22 },
- { NSF23FunctionKey, Qt::Key_F23 },
- { NSF24FunctionKey, Qt::Key_F24 },
- { NSF25FunctionKey, Qt::Key_F25 },
- { NSF26FunctionKey, Qt::Key_F26 },
- { NSF27FunctionKey, Qt::Key_F27 },
- { NSF28FunctionKey, Qt::Key_F28 },
- { NSF29FunctionKey, Qt::Key_F29 },
- { NSF30FunctionKey, Qt::Key_F30 },
- { NSF31FunctionKey, Qt::Key_F31 },
- { NSF32FunctionKey, Qt::Key_F32 },
- { NSF33FunctionKey, Qt::Key_F33 },
- { NSF34FunctionKey, Qt::Key_F34 },
- { NSF35FunctionKey, Qt::Key_F35 },
- { NSInsertFunctionKey, Qt::Key_Insert },
- { NSDeleteFunctionKey, Qt::Key_Delete },
- { NSHomeFunctionKey, Qt::Key_Home },
- { NSEndFunctionKey, Qt::Key_End },
- { NSPageUpFunctionKey, Qt::Key_PageUp },
- { NSPageDownFunctionKey, Qt::Key_PageDown },
- { NSPrintScreenFunctionKey, Qt::Key_Print },
- { NSScrollLockFunctionKey, Qt::Key_ScrollLock },
- { NSPauseFunctionKey, Qt::Key_Pause },
- { NSSysReqFunctionKey, Qt::Key_SysReq },
- { NSMenuFunctionKey, Qt::Key_Menu },
- { NSHelpFunctionKey, Qt::Key_Help },
-};
-static const KeyPair * const end = entries + NumEntries;
-
-QChar qt_mac_qtKey2CocoaKey(Qt::Key key)
-{
- // The first time this function is called, create a reverse
- // lookup table sorted on Qt Key rather than Cocoa key:
- static QVector<KeyPair> rev_entries(NumEntries);
- static bool mustInit = true;
- if (mustInit){
- mustInit = false;
- for (int i=0; i<NumEntries; ++i)
- rev_entries[i] = entries[i];
- std::sort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan());
- }
- const QVector<KeyPair>::iterator i
- = std::lower_bound(rev_entries.begin(), rev_entries.end(), key);
- if ((i == rev_entries.end()) || (key < *i))
- return QChar();
- return i->cocoaKey;
-}
-
-Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
-{
- const KeyPair *i = std::lower_bound(entries, end, keyCode);
- if ((i == end) || (keyCode < *i))
- return Qt::Key(keyCode.toUpper().unicode());
- return i->qtKey;
-}
-
-#endif // Q_OS_MACOS
-
void qt_apple_check_os_version()
{
#if defined(__WATCH_OS_VERSION_MIN_REQUIRED)
@@ -608,6 +567,9 @@ void qt_apple_check_os_version()
#elif defined(__TV_OS_VERSION_MIN_REQUIRED)
const char *os = "tvOS";
const int version = __TV_OS_VERSION_MIN_REQUIRED;
+#elif defined(__VISION_OS_VERSION_MIN_REQUIRED)
+ const char *os = "visionOS";
+ const int version = __VISION_OS_VERSION_MIN_REQUIRED;
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
const char *os = "iOS";
const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
@@ -615,10 +577,18 @@ void qt_apple_check_os_version()
const char *os = "macOS";
const int version = __MAC_OS_X_VERSION_MIN_REQUIRED;
#endif
- const NSOperatingSystemVersion required = (NSOperatingSystemVersion){
- version / 10000, version / 100 % 100, version % 100};
- const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
- if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
+
+ const auto required = QVersionNumber(version / 10000, version / 100 % 100, version % 100);
+ const auto current = QOperatingSystemVersion::current().version();
+
+#if defined(Q_OS_MACOS)
+ // Check for compatibility version, in which case we can't do a
+ // comparison to the deployment target, which might be e.g. 11.0
+ if (current.majorVersion() == 10 && current.minorVersion() >= 16)
+ return;
+#endif
+
+ if (current < required) {
NSDictionary *plist = NSBundle.mainBundle.infoDictionary;
NSString *applicationName = plist[@"CFBundleDisplayName"];
if (!applicationName)
@@ -629,8 +599,8 @@ void qt_apple_check_os_version()
fprintf(stderr, "Sorry, \"%s\" cannot be run on this version of %s. "
"Qt requires %s %ld.%ld.%ld or later, you have %s %ld.%ld.%ld.\n",
applicationName.UTF8String, os,
- os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion),
- os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion));
+ os, long(required.majorVersion()), long(required.minorVersion()), long(required.microVersion()),
+ os, long(current.majorVersion()), long(current.minorVersion()), long(current.microVersion()));
exit(1);
}
@@ -667,7 +637,7 @@ void QMacKeyValueObserver::removeObserver() {
KeyValueObserver *QMacKeyValueObserver::observer = [[KeyValueObserver alloc] init];
QT_END_NAMESPACE
-@implementation KeyValueObserver
+@implementation QT_MANGLE_NAMESPACE(KeyValueObserver)
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
{
@@ -682,6 +652,127 @@ QT_BEGIN_NAMESPACE
// -------------------------------------------------------------------------
+QOperatingSystemVersion QMacVersion::buildSDK(VersionTarget target)
+{
+ switch (target) {
+ case ApplicationBinary: return applicationVersion().second;
+ case QtLibraries: return libraryVersion().second;
+ }
+ Q_UNREACHABLE();
+}
+
+QOperatingSystemVersion QMacVersion::deploymentTarget(VersionTarget target)
+{
+ switch (target) {
+ case ApplicationBinary: return applicationVersion().first;
+ case QtLibraries: return libraryVersion().first;
+ }
+ Q_UNREACHABLE();
+}
+
+QOperatingSystemVersion QMacVersion::currentRuntime()
+{
+ return QOperatingSystemVersion::current();
+}
+
+// Mach-O platforms
+enum Platform {
+ macOS = 1,
+ iOS = 2,
+ tvOS = 3,
+ watchOS = 4,
+ bridgeOS = 5,
+ macCatalyst = 6,
+ iOSSimulator = 7,
+ tvOSSimulator = 8,
+ watchOSSimulator = 9
+};
+
+QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader)
+{
+ static auto osForLoadCommand = [](uint32_t cmd) {
+ switch (cmd) {
+ case LC_VERSION_MIN_MACOSX: return QOperatingSystemVersion::MacOS;
+ case LC_VERSION_MIN_IPHONEOS: return QOperatingSystemVersion::IOS;
+ case LC_VERSION_MIN_TVOS: return QOperatingSystemVersion::TvOS;
+ case LC_VERSION_MIN_WATCHOS: return QOperatingSystemVersion::WatchOS;
+ default: return QOperatingSystemVersion::Unknown;
+ }
+ };
+
+ static auto osForPlatform = [](uint32_t platform) {
+ switch (platform) {
+ case Platform::macOS:
+ return QOperatingSystemVersion::MacOS;
+ case Platform::iOS:
+ case Platform::iOSSimulator:
+ return QOperatingSystemVersion::IOS;
+ case Platform::tvOS:
+ case Platform::tvOSSimulator:
+ return QOperatingSystemVersion::TvOS;
+ case Platform::watchOS:
+ case Platform::watchOSSimulator:
+ return QOperatingSystemVersion::WatchOS;
+ default:
+ return QOperatingSystemVersion::Unknown;
+ }
+ };
+
+ static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk, QOperatingSystemVersion::OSType osType) {
+ return std::pair(
+ QOperatingSystemVersion(osType, dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
+ QOperatingSystemVersion(osType, sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff)
+ );
+ };
+
+ const bool is64Bit = machHeader->magic == MH_MAGIC_64 || machHeader->magic == MH_CIGAM_64;
+ auto commandCursor = uintptr_t(machHeader) + (is64Bit ? sizeof(mach_header_64) : sizeof(mach_header));
+
+ for (uint32_t i = 0; i < machHeader->ncmds; ++i) {
+ load_command *loadCommand = reinterpret_cast<load_command *>(commandCursor);
+ if (loadCommand->cmd == LC_VERSION_MIN_MACOSX || loadCommand->cmd == LC_VERSION_MIN_IPHONEOS
+ || loadCommand->cmd == LC_VERSION_MIN_TVOS || loadCommand->cmd == LC_VERSION_MIN_WATCHOS) {
+ auto versionCommand = reinterpret_cast<version_min_command *>(loadCommand);
+ return makeVersionTuple(versionCommand->version, versionCommand->sdk, osForLoadCommand(loadCommand->cmd));
+ } else if (loadCommand->cmd == LC_BUILD_VERSION) {
+ auto versionCommand = reinterpret_cast<build_version_command *>(loadCommand);
+ return makeVersionTuple(versionCommand->minos, versionCommand->sdk, osForPlatform(versionCommand->platform));
+ }
+ commandCursor += loadCommand->cmdsize;
+ }
+ Q_ASSERT_X(false, "QMacVersion", "Could not find any version load command");
+ Q_UNREACHABLE();
+}
+
+QMacVersion::VersionTuple QMacVersion::applicationVersion()
+{
+ static VersionTuple version = []() {
+ const mach_header *executableHeader = nullptr;
+ for (uint32_t i = 0; i < _dyld_image_count(); ++i) {
+ auto header = _dyld_get_image_header(i);
+ if (header->filetype == MH_EXECUTE) {
+ executableHeader = header;
+ break;
+ }
+ }
+ Q_ASSERT_X(executableHeader, "QMacVersion", "Failed to resolve Mach-O header of executable");
+ return versionsForImage(executableHeader);
+ }();
+ return version;
+}
+
+QMacVersion::VersionTuple QMacVersion::libraryVersion()
+{
+ static VersionTuple version = []() {
+ Dl_info qtCoreImage;
+ dladdr((const void *)&QMacVersion::libraryVersion, &qtCoreImage);
+ Q_ASSERT_X(qtCoreImage.dli_fbase, "QMacVersion", "Failed to resolve Mach-O header of QtCore");
+ return versionsForImage(static_cast<mach_header*>(qtCoreImage.dli_fbase));
+ }();
+ return version;
+}
+
+// -------------------------------------------------------------------------
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index a21ce5e65a..e63c320805 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCORE_MAC_P_H
#define QCORE_MAC_P_H
@@ -53,6 +17,19 @@
#include "private/qglobal_p.h"
+#include <QtCore/qoperatingsystemversion.h>
+
+#ifdef Q_OS_MACOS
+#include <mach/port.h>
+struct mach_header;
+typedef int kern_return_t;
+typedef mach_port_t io_object_t;
+extern "C" {
+kern_return_t IOObjectRetain(io_object_t object);
+kern_return_t IOObjectRelease(io_object_t object);
+}
+#endif
+
#ifndef __IMAGECAPTURE__
# define __IMAGECAPTURE__
#endif
@@ -72,6 +49,7 @@
#include "qstring.h"
#include "qscopedpointer.h"
+#include "qpair.h"
#if defined( __OBJC__) && defined(QT_NAMESPACE)
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
@@ -99,20 +77,26 @@
Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
+// @compatibility_alias doesn't work with categories or their methods
+#define QtExtras QT_MANGLE_NAMESPACE(QtExtras)
+
QT_BEGIN_NAMESPACE
-template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
+template <typename T, typename U, auto RetainFunction, auto ReleaseFunction>
class QAppleRefCounted
{
public:
- QAppleRefCounted() : value() {}
- QAppleRefCounted(const T &t) : value(t) {}
- QAppleRefCounted(T &&t) noexcept(std::is_nothrow_move_constructible<T>::value)
+ Q_NODISCARD_CTOR QAppleRefCounted() : value() {}
+ Q_NODISCARD_CTOR QAppleRefCounted(const T &t) : value(t) {}
+ Q_NODISCARD_CTOR QAppleRefCounted(T &&t)
+ noexcept(std::is_nothrow_move_constructible<T>::value)
: value(std::move(t)) {}
- QAppleRefCounted(QAppleRefCounted &&other)
+ Q_NODISCARD_CTOR QAppleRefCounted(QAppleRefCounted &&other)
noexcept(std::is_nothrow_move_assignable<T>::value &&
std::is_nothrow_move_constructible<T>::value)
- : value(qExchange(other.value, T())) {}
- QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); }
+ : value(std::exchange(other.value, T())) {}
+ Q_NODISCARD_CTOR QAppleRefCounted(const QAppleRefCounted &other)
+ : value(other.value)
+ { if (value) RetainFunction(value); }
~QAppleRefCounted() { if (value) ReleaseFunction(value); }
operator T() const { return value; }
void swap(QAppleRefCounted &other) noexcept(noexcept(qSwap(value, other.value)))
@@ -128,12 +112,21 @@ protected:
T value;
};
+class QMacAutoReleasePool
+{
+public:
+ Q_NODISCARD_CTOR Q_CORE_EXPORT QMacAutoReleasePool();
+ Q_CORE_EXPORT ~QMacAutoReleasePool();
+private:
+ Q_DISABLE_COPY(QMacAutoReleasePool)
+ void *pool;
+};
#ifdef Q_OS_MACOS
class QMacRootLevelAutoReleasePool
{
public:
- QMacRootLevelAutoReleasePool();
+ Q_NODISCARD_CTOR QMacRootLevelAutoReleasePool();
~QMacRootLevelAutoReleasePool();
private:
QScopedPointer<QMacAutoReleasePool> pool;
@@ -141,7 +134,7 @@ private:
#endif
/*
- Helper class that automates refernce counting for CFtypes.
+ Helper class that automates reference counting for CFtypes.
After constructing the QCFType object, it can be copied like a
value-based type.
@@ -158,7 +151,7 @@ class QCFType : public QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>
using Base = QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>;
public:
using Base::Base;
- explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {}
+ Q_NODISCARD_CTOR explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {}
template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
static QCFType constructFromGet(const T &t)
{
@@ -168,24 +161,35 @@ public:
}
};
-class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
+#ifdef Q_OS_MACOS
+template <typename T>
+class QIOType : public QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>
+{
+ using QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>::QAppleRefCounted;
+};
+#endif
+
+class QCFString : public QCFType<CFStringRef>
{
public:
using QCFType<CFStringRef>::QCFType;
- inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
- inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
- inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
- operator QString() const;
- operator CFStringRef() const;
+ Q_NODISCARD_CTOR QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
+ Q_NODISCARD_CTOR QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
+ Q_NODISCARD_CTOR QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
+ Q_CORE_EXPORT operator QString() const;
+ Q_CORE_EXPORT operator CFStringRef() const;
private:
QString string;
};
#ifdef Q_OS_MACOS
-Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
-Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
+Q_CORE_EXPORT bool qt_mac_runningUnderRosetta();
+Q_CORE_EXPORT std::optional<uint32_t> qt_mac_sipConfiguration();
+#ifdef QT_BUILD_INTERNAL
+Q_AUTOTEST_EXPORT void qt_mac_ensureResponsible();
+#endif
#endif
#ifndef QT_NO_DEBUG_STREAM
@@ -195,16 +199,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string);
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
-#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
+#if !defined(QT_BOOTSTRAPPED)
Q_CORE_EXPORT bool qt_apple_isSandboxed();
-# ifdef __OBJC__
+
+#if defined(__OBJC__)
QT_END_NAMESPACE
-@interface NSObject (QtSandboxHelpers)
+@interface NSObject (QtExtras)
- (id)qt_valueForPrivateKey:(NSString *)key;
@end
QT_BEGIN_NAMESPACE
-# endif
#endif
+#endif // !QT_BOOTSTRAPPED
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
QT_END_NAMESPACE
@@ -231,9 +236,12 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT AppleUnifiedLogger
{
public:
- static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message,
- const QString &subsystem = QString());
- static bool willMirrorToStderr();
+ static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context,
+ const QString &message)
+ { return messageHandler(msgType, context, message, QString()); }
+ static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context,
+ const QString &message, const QString &subsystem);
+ static bool preventsStderrLogging();
private:
static os_log_type_t logTypeForMessageType(QtMsgType msgType);
static os_log_t cachedLog(const QString &subsystem, const QString &category);
@@ -258,30 +266,24 @@ public:
QAppleLogActivity(os_activity_t activity) : activity(activity) {}
~QAppleLogActivity() { if (activity) leave(); }
- QAppleLogActivity(const QAppleLogActivity &) = delete;
- QAppleLogActivity& operator=(const QAppleLogActivity &) = delete;
-
- QAppleLogActivity(QAppleLogActivity&& other)
- : activity(other.activity), state(other.state) { other.activity = nullptr; }
+ Q_DISABLE_COPY(QAppleLogActivity)
- QAppleLogActivity& operator=(QAppleLogActivity &&other)
+ QAppleLogActivity(QAppleLogActivity &&other)
+ : activity(std::exchange(other.activity, nullptr)), state(other.state)
{
- if (this != &other) {
- activity = other.activity;
- state = other.state;
- other.activity = nullptr;
- }
- return *this;
}
- QAppleLogActivity&& enter()
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QAppleLogActivity)
+
+ QAppleLogActivity &&enter()
{
if (activity)
os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
return std::move(*this);
}
- void leave() {
+ void leave()
+ {
if (activity)
os_activity_scope_leave(&state);
}
@@ -291,6 +293,12 @@ public:
return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
}
+ void swap(QAppleLogActivity &other)
+ {
+ activity.swap(other.activity);
+ std::swap(state, other.state);
+ }
+
private:
// Work around API_AVAILABLE not working for templates by using void*
QAppleOsType<void *> activity;
@@ -303,20 +311,13 @@ private:
return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
}()
-#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
-#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
-
-#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)
-#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC)
-#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC
-
-#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
-#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent)
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(true, description, parent)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
QT_MAC_WEAK_IMPORT(_os_activity_current);
-#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
-#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description)
+#define QT_APPLE_LOG_ACTIVITY_2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
+#define QT_APPLE_LOG_ACTIVITY_1(description) QT_APPLE_LOG_ACTIVITY_2(true, description)
#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)
#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
@@ -341,19 +342,18 @@ public:
}
#endif
- QMacNotificationObserver(const QMacNotificationObserver& other) = delete;
- QMacNotificationObserver(QMacNotificationObserver&& other) : observer(other.observer) {
- other.observer = nullptr;
+ QMacNotificationObserver(const QMacNotificationObserver &other) = delete;
+ QMacNotificationObserver(QMacNotificationObserver &&other)
+ : observer(std::exchange(other.observer, nullptr))
+ {
}
- QMacNotificationObserver &operator=(const QMacNotificationObserver& other) = delete;
- QMacNotificationObserver &operator=(QMacNotificationObserver&& other) {
- if (this != &other) {
- remove();
- observer = other.observer;
- other.observer = nullptr;
- }
- return *this;
+ QMacNotificationObserver &operator=(const QMacNotificationObserver &other) = delete;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacNotificationObserver)
+
+ void swap(QMacNotificationObserver &other) noexcept
+ {
+ qt_ptr_swap(observer, other.observer);
}
void remove();
@@ -372,7 +372,7 @@ class Q_CORE_EXPORT QMacKeyValueObserver
public:
using Callback = std::function<void()>;
- QMacKeyValueObserver() {}
+ QMacKeyValueObserver() = default;
#if defined( __OBJC__)
// Note: QMacKeyValueObserver must not outlive the object observed!
@@ -386,31 +386,29 @@ public:
QMacKeyValueObserver(const QMacKeyValueObserver &other);
- QMacKeyValueObserver(QMacKeyValueObserver &&other) { swap(other, *this); }
+ QMacKeyValueObserver(QMacKeyValueObserver &&other) noexcept { swap(other); }
~QMacKeyValueObserver() { removeObserver(); }
- QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other) {
+ QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other)
+ {
QMacKeyValueObserver tmp(other);
- swap(tmp, *this);
+ swap(tmp);
return *this;
}
- QMacKeyValueObserver &operator=(QMacKeyValueObserver &&other) {
- QMacKeyValueObserver tmp(std::move(other));
- swap(tmp, *this);
- return *this;
- }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacKeyValueObserver)
void removeObserver();
-private:
- void swap(QMacKeyValueObserver &first, QMacKeyValueObserver &second) {
- std::swap(first.object, second.object);
- std::swap(first.keyPath, second.keyPath);
- std::swap(first.callback, second.callback);
+ void swap(QMacKeyValueObserver &other) noexcept
+ {
+ qt_ptr_swap(object, other.object);
+ qt_ptr_swap(keyPath, other.keyPath);
+ callback.swap(other.callback);
}
+private:
#if defined( __OBJC__)
void addObserver(NSKeyValueObservingOptions options);
#endif
@@ -424,6 +422,42 @@ private:
// -------------------------------------------------------------------------
+class Q_CORE_EXPORT QMacVersion
+{
+public:
+ enum VersionTarget {
+ ApplicationBinary,
+ QtLibraries
+ };
+
+ static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary);
+ static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary);
+ static QOperatingSystemVersion currentRuntime();
+
+private:
+ QMacVersion() = default;
+ using VersionTuple = std::pair<QOperatingSystemVersion, QOperatingSystemVersion>;
+ static VersionTuple versionsForImage(const mach_header *machHeader);
+ static VersionTuple applicationVersion();
+ static VersionTuple libraryVersion();
+};
+
+// -------------------------------------------------------------------------
+
+#ifdef __OBJC__
+template <typename T>
+typename std::enable_if<std::is_pointer<T>::value, T>::type
+qt_objc_cast(id object)
+{
+ if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
+ return static_cast<T>(object);
+
+ return nil;
+}
+#endif
+
+// -------------------------------------------------------------------------
+
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index ff0c957770..6861251bc2 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -1,46 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qbasicatomic.h>
#include "qcore_unix_p.h"
-#include "qelapsedtimer.h"
#include <stdlib.h>
@@ -50,12 +14,27 @@
# include <unistd.h>
#endif
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
#include <mach/mach_time.h>
#endif
QT_BEGIN_NAMESPACE
+void qt_ignore_sigpipe() noexcept // noexcept: sigaction(2) is not a Posix Cancellation Point
+{
+ // Set to ignore SIGPIPE once only.
+ Q_CONSTINIT static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if (!atom.loadRelaxed()) {
+ // More than one thread could turn off SIGPIPE at the same time
+ // But that's acceptable because they all would be doing the same
+ // action
+ struct sigaction noaction = {};
+ noaction.sa_handler = SIG_IGN;
+ ::sigaction(SIGPIPE, &noaction, nullptr);
+ atom.storeRelaxed(1);
+ }
+}
+
QByteArray qt_readlink(const char *path)
{
#ifndef PATH_MAX
@@ -105,23 +84,15 @@ int qt_open64(const char *pathname, int flags, mode_t mode)
# define ppoll pollts
#endif
-static inline bool time_update(struct timespec *tv, const struct timespec &start,
- const struct timespec &timeout)
-{
- // clock source is (hopefully) monotonic, so we can recalculate how much timeout is left;
- // if it isn't monotonic, we'll simply hope that it hasn't jumped, because we have no alternative
- struct timespec now = qt_gettime();
- *tv = timeout + start - now;
- return tv->tv_sec >= 0;
-}
-
-#if QT_CONFIG(poll_poll)
+[[maybe_unused]]
static inline int timespecToMillisecs(const struct timespec *ts)
{
- return (ts == NULL) ? -1 :
- (ts->tv_sec * 1000) + (ts->tv_nsec / 1000000);
+ using namespace std::chrono;
+ if (!ts)
+ return -1;
+ auto ms = ceil<milliseconds>(timespecToChrono<nanoseconds>(*ts));
+ return int(ms.count());
}
-#endif
// defined in qpoll.cpp
int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
@@ -147,31 +118,27 @@ static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespe
using select(2) where necessary. In that case, returns -1 and sets errno
to EINVAL if passed any descriptor greater than or equal to FD_SETSIZE.
*/
-int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
+int qt_safe_poll(struct pollfd *fds, nfds_t nfds, QDeadlineTimer deadline)
{
- if (!timeout_ts) {
+ if (deadline.isForever()) {
// no timeout -> block forever
int ret;
- EINTR_LOOP(ret, qt_ppoll(fds, nfds, nullptr));
+ QT_EINTR_LOOP(ret, qt_ppoll(fds, nfds, nullptr));
return ret;
}
- timespec start = qt_gettime();
- timespec timeout = *timeout_ts;
-
+ using namespace std::chrono;
+ nanoseconds remaining = deadline.remainingTimeAsDuration();
// loop and recalculate the timeout as needed
- forever {
- const int ret = qt_ppoll(fds, nfds, &timeout);
+ do {
+ timespec ts = durationToTimespec(remaining);
+ const int ret = qt_ppoll(fds, nfds, &ts);
if (ret != -1 || errno != EINTR)
return ret;
+ remaining = deadline.remainingTimeAsDuration();
+ } while (remaining > 0ns);
- // recalculate the timeout
- if (!time_update(&timeout, start, *timeout_ts)) {
- // timeout during update
- // or clock reset, fake timeout error
- return 0;
- }
- }
+ return 0;
}
#endif // QT_BOOTSTRAPPED
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 6ec7d28318..fd834cb2d9 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCORE_UNIX_P_H
#define QCORE_UNIX_P_H
@@ -54,8 +18,8 @@
#include "qplatformdefs.h"
#include <QtCore/private/qglobal_p.h>
-#include "qatomic.h"
#include "qbytearray.h"
+#include "qdeadlinetimer.h"
#ifndef Q_OS_UNIX
# error "qcore_unix_p.h included on a non-Unix system"
@@ -66,8 +30,7 @@
#include <sys/stat.h>
#include <unistd.h>
-#ifdef Q_OS_NACL
-#elif !defined (Q_OS_VXWORKS)
+#if !defined (Q_OS_VXWORKS)
# if !defined(Q_OS_HPUX) || defined(__ia64)
# include <sys/select.h>
# endif
@@ -76,14 +39,11 @@
# include <selectLib.h>
#endif
+#include <chrono>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
-#if !defined(QT_POSIX_IPC) && !defined(QT_NO_SHAREDMEMORY) && !defined(Q_OS_ANDROID)
-# include <sys/ipc.h>
-#endif
-
#if defined(Q_OS_VXWORKS)
# include <ioLib.h>
#endif
@@ -96,7 +56,7 @@
struct sockaddr;
-#define EINTR_LOOP(var, cmd) \
+#define QT_EINTR_LOOP(var, cmd) \
do { \
var = cmd; \
} while (var == -1 && errno == EINTR)
@@ -105,53 +65,78 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(pollfd, Q_PRIMITIVE_TYPE);
+static constexpr auto OneSecAsNsecs = std::chrono::nanoseconds(std::chrono::seconds{ 1 }).count();
+
+inline timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept
+{
+ using namespace std::chrono;
+ const seconds secs = duration_cast<seconds>(timeout);
+ const nanoseconds frac = timeout - secs;
+ struct timespec ts;
+ ts.tv_sec = secs.count();
+ ts.tv_nsec = frac.count();
+ return ts;
+}
+
+template <typename Duration>
+inline Duration timespecToChrono(timespec ts) noexcept
+{
+ using namespace std::chrono;
+ return duration_cast<Duration>(seconds{ts.tv_sec} + nanoseconds{ts.tv_nsec});
+}
+
+inline std::chrono::milliseconds timespecToChronoMs(timespec ts) noexcept
+{
+ return timespecToChrono<std::chrono::milliseconds>(ts);
+}
+
// Internal operator functions for timespecs
-inline timespec &normalizedTimespec(timespec &t)
+constexpr inline timespec &normalizedTimespec(timespec &t)
{
- while (t.tv_nsec >= 1000000000) {
+ while (t.tv_nsec >= OneSecAsNsecs) {
++t.tv_sec;
- t.tv_nsec -= 1000000000;
+ t.tv_nsec -= OneSecAsNsecs;
}
while (t.tv_nsec < 0) {
--t.tv_sec;
- t.tv_nsec += 1000000000;
+ t.tv_nsec += OneSecAsNsecs;
}
return t;
}
-inline bool operator<(const timespec &t1, const timespec &t2)
+constexpr inline bool operator<(const timespec &t1, const timespec &t2)
{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); }
-inline bool operator==(const timespec &t1, const timespec &t2)
+constexpr inline bool operator==(const timespec &t1, const timespec &t2)
{ return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; }
-inline bool operator!=(const timespec &t1, const timespec &t2)
+constexpr inline bool operator!=(const timespec &t1, const timespec &t2)
{ return !(t1 == t2); }
-inline timespec &operator+=(timespec &t1, const timespec &t2)
+constexpr inline timespec &operator+=(timespec &t1, const timespec &t2)
{
t1.tv_sec += t2.tv_sec;
t1.tv_nsec += t2.tv_nsec;
return normalizedTimespec(t1);
}
-inline timespec operator+(const timespec &t1, const timespec &t2)
+constexpr inline timespec operator+(const timespec &t1, const timespec &t2)
{
- timespec tmp;
+ timespec tmp = {};
tmp.tv_sec = t1.tv_sec + t2.tv_sec;
tmp.tv_nsec = t1.tv_nsec + t2.tv_nsec;
return normalizedTimespec(tmp);
}
-inline timespec operator-(const timespec &t1, const timespec &t2)
+constexpr inline timespec operator-(const timespec &t1, const timespec &t2)
{
- timespec tmp;
+ timespec tmp = {};
tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
- tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + 1000000000);
+ tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + OneSecAsNsecs);
return normalizedTimespec(tmp);
}
-inline timespec operator*(const timespec &t1, int mul)
+constexpr inline timespec operator*(const timespec &t1, int mul)
{
- timespec tmp;
+ timespec tmp = {};
tmp.tv_sec = t1.tv_sec * mul;
tmp.tv_nsec = t1.tv_nsec * mul;
return normalizedTimespec(tmp);
}
-inline timeval timespecToTimeval(const timespec &ts)
+inline timeval timespecToTimeval(timespec ts)
{
timeval tv;
tv.tv_sec = ts.tv_sec;
@@ -159,23 +144,44 @@ inline timeval timespecToTimeval(const timespec &ts)
return tv;
}
+inline timespec &operator+=(timespec &t1, std::chrono::milliseconds msecs)
+{
+ t1 += durationToTimespec(msecs);
+ return t1;
+}
-inline void qt_ignore_sigpipe()
+inline timespec &operator+=(timespec &t1, int ms)
{
- // Set to ignore SIGPIPE once only.
- static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
- if (!atom.loadRelaxed()) {
- // More than one thread could turn off SIGPIPE at the same time
- // But that's acceptable because they all would be doing the same
- // action
- struct sigaction noaction;
- memset(&noaction, 0, sizeof(noaction));
- noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, nullptr);
- atom.storeRelaxed(1);
+ t1 += std::chrono::milliseconds{ms};
+ return t1;
+}
+
+inline timespec operator+(const timespec &t1, std::chrono::milliseconds msecs)
+{
+ timespec tmp = t1;
+ tmp += msecs;
+ return tmp;
+}
+
+inline timespec operator+(const timespec &t1, int ms)
+{
+ return t1 + std::chrono::milliseconds{ms};
+}
+
+inline timespec qAbsTimespec(timespec ts)
+{
+ if (ts.tv_sec < 0) {
+ ts.tv_sec = -ts.tv_sec - 1;
+ ts.tv_nsec -= OneSecAsNsecs;
+ }
+ if (ts.tv_sec == 0 && ts.tv_nsec < 0) {
+ ts.tv_nsec = -ts.tv_nsec;
}
+ return normalizedTimespec(ts);
}
+Q_CORE_EXPORT void qt_ignore_sigpipe() noexcept;
+
#if defined(Q_PROCESSOR_X86_32) && defined(__GLIBC__)
# if !__GLIBC_PREREQ(2, 22)
Q_CORE_EXPORT int qt_open64(const char *pathname, int flags, mode_t);
@@ -184,6 +190,16 @@ Q_CORE_EXPORT int qt_open64(const char *pathname, int flags, mode_t);
# endif
#endif
+#ifdef AT_FDCWD
+static inline int qt_safe_openat(int dfd, const char *pathname, int flags, mode_t mode = 0777)
+{
+ // everyone already has O_CLOEXEC
+ int fd;
+ QT_EINTR_LOOP(fd, openat(dfd, pathname, flags | O_CLOEXEC, mode));
+ return fd;
+}
+#endif
+
// don't call QT_OPEN or ::open
// call qt_safe_open
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
@@ -192,7 +208,7 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07
flags |= O_CLOEXEC;
#endif
int fd;
- EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
+ QT_EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
#ifndef O_CLOEXEC
if (fd != -1)
@@ -264,10 +280,10 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
int ret;
#ifdef QT_THREADSAFE_CLOEXEC
// use dup3
- EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0));
+ QT_EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0));
return ret;
#else
- EINTR_LOOP(ret, ::dup2(oldfd, newfd));
+ QT_EINTR_LOOP(ret, ::dup2(oldfd, newfd));
if (ret == -1)
return -1;
@@ -280,7 +296,7 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
{
qint64 ret = 0;
- EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
+ QT_EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
return ret;
}
#undef QT_READ
@@ -289,7 +305,7 @@ static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
{
qint64 ret = 0;
- EINTR_LOOP(ret, QT_WRITE(fd, data, len));
+ QT_EINTR_LOOP(ret, QT_WRITE(fd, data, len));
return ret;
}
#undef QT_WRITE
@@ -304,7 +320,7 @@ static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len
static inline int qt_safe_close(int fd)
{
int ret;
- EINTR_LOOP(ret, QT_CLOSE(fd));
+ QT_EINTR_LOOP(ret, QT_CLOSE(fd));
return ret;
}
#undef QT_CLOSE
@@ -316,28 +332,28 @@ static inline int qt_safe_execve(const char *filename, char *const argv[],
char *const envp[])
{
int ret;
- EINTR_LOOP(ret, ::execve(filename, argv, envp));
+ QT_EINTR_LOOP(ret, ::execve(filename, argv, envp));
return ret;
}
static inline int qt_safe_execv(const char *path, char *const argv[])
{
int ret;
- EINTR_LOOP(ret, ::execv(path, argv));
+ QT_EINTR_LOOP(ret, ::execv(path, argv));
return ret;
}
static inline int qt_safe_execvp(const char *file, char *const argv[])
{
int ret;
- EINTR_LOOP(ret, ::execvp(file, argv));
+ QT_EINTR_LOOP(ret, ::execvp(file, argv));
return ret;
}
static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
{
int ret;
- EINTR_LOOP(ret, ::waitpid(pid, status, options));
+ QT_EINTR_LOOP(ret, ::waitpid(pid, status, options));
return ret;
}
#endif // QT_CONFIG(process)
@@ -346,9 +362,6 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
# define _POSIX_MONOTONIC_CLOCK -1
#endif
-// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
-timespec qt_gettime() noexcept;
-void qt_nanosleep(timespec amount);
QByteArray qt_readlink(const char *path);
/* non-static */
@@ -366,20 +379,7 @@ inline bool qt_haveLinuxProcfs()
#endif
}
-Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
-
-static inline int qt_poll_msecs(struct pollfd *fds, nfds_t nfds, int timeout)
-{
- timespec ts, *pts = nullptr;
-
- if (timeout >= 0) {
- ts.tv_sec = timeout / 1000;
- ts.tv_nsec = (timeout % 1000) * 1000 * 1000;
- pts = &ts;
- }
-
- return qt_safe_poll(fds, nfds, pts);
-}
+Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, QDeadlineTimer deadline);
static inline struct pollfd qt_make_pollfd(int fd, short events)
{
diff --git a/src/corelib/kernel/qcore_wasm.cpp b/src/corelib/kernel/qcore_wasm.cpp
new file mode 100644
index 0000000000..fb12ae50c3
--- /dev/null
+++ b/src/corelib/kernel/qcore_wasm.cpp
@@ -0,0 +1,97 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qrect.h>
+
+#include <emscripten/val.h>
+
+#if !defined(Q_OS_WASM)
+#error This is a wasm-only file.
+#endif // !defined(Q_OS_WASM)
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Converts the DOMRect (https://www.w3.org/TR/geometry-1/) \a domRect to QRectF. The behavior is
+ undefined if the provided parameter is not a DOMRect.
+
+ \since 6.5
+ \ingroup platform-type-conversions
+
+ \sa toDOMRect()
+*/
+QRectF QRectF::fromDOMRect(emscripten::val domRect)
+{
+ Q_ASSERT_X(domRect["constructor"]["name"].as<std::string>() == "DOMRect", Q_FUNC_INFO,
+ "Passed object is not a DOMRect");
+
+ return QRectF(domRect["left"].as<qreal>(), domRect["top"].as<qreal>(),
+ domRect["width"].as<qreal>(), domRect["height"].as<qreal>());
+}
+
+/*!
+ Converts this object to a DOMRect (https://www.w3.org/TR/geometry-1/).
+
+ \since 6.5
+ \ingroup platform-type-conversions
+
+ \sa fromDOMRect()
+*/
+emscripten::val QRectF::toDOMRect() const
+{
+ return emscripten::val::global("DOMRect").new_(left(), top(), width(), height());
+}
+
+/*!
+ Converts the \l {https://262.ecma-international.org/#sec-string-object}{ECMAScript string} \a
+ jsString to QString. Behavior is undefined if the provided parameter is not a string.
+
+ \since 6.6
+ \ingroup platform-type-conversions
+
+ \sa toEcmaString()
+*/
+QString QString::fromEcmaString(emscripten::val jsString)
+{
+ Q_ASSERT_X(jsString.isString(), Q_FUNC_INFO, "Passed object is not a string");
+
+ const double length = jsString["length"].as<double>();
+
+ Q_ASSERT_X((double(uint64_t(length)) != double(uint64_t(length) - 1)
+ && double(uint64_t(length)) != double(uint64_t(length) + 1))
+ || !std::numeric_limits<double>::is_iec559,
+ Q_FUNC_INFO, "The floating-point length cannot precisely represent an integer");
+
+ constexpr int zeroTerminatorLength = 1;
+ const auto lengthOfUtf16 = (length + zeroTerminatorLength) * 2;
+
+ Q_ASSERT_X((double(uint64_t(lengthOfUtf16)) != double(uint64_t(lengthOfUtf16) - 1)
+ && double(uint64_t(lengthOfUtf16)) != double(uint64_t(lengthOfUtf16) + 1))
+ || !std::numeric_limits<double>::is_iec559,
+ Q_FUNC_INFO,
+ "The floating-point lengthOfUtf16 cannot precisely represent an integer");
+
+ const QString result(uint64_t(length), Qt::Uninitialized);
+
+ static const emscripten::val stringToUTF16(emscripten::val::module_property("stringToUTF16"));
+ stringToUTF16(jsString, emscripten::val(quintptr(result.data())),
+ emscripten::val(lengthOfUtf16));
+ return result;
+}
+
+/*!
+ Converts this object to an
+ \l {https://262.ecma-international.org/#sec-string-object}{ECMAScript string}.
+
+ \since 6.6
+ \ingroup platform-type-conversions
+
+ \sa fromEcmaString()
+*/
+emscripten::val QString::toEcmaString() const
+{
+ static const emscripten::val UTF16ToString(emscripten::val::module_property("UTF16ToString"));
+ return UTF16ToString(emscripten::val(quintptr(utf16())));
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 2894e1a731..a494369c5d 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
@@ -44,9 +8,11 @@
#ifndef QT_NO_QOBJECT
#include "qabstracteventdispatcher.h"
#include "qcoreevent.h"
+#include "qcoreevent_p.h"
#include "qeventloop.h"
#endif
#include "qmetaobject.h"
+#include <private/qproperty_p.h>
#include "qcorecmdlineargs_p.h"
#include <qdatastream.h>
#include <qdebug.h>
@@ -60,13 +26,17 @@
#ifndef QT_NO_QOBJECT
#include <qthread.h>
#include <qthreadstorage.h>
+#if QT_CONFIG(future)
+#include <QtCore/qpromise.h>
+#endif
#include <private/qthread_p.h>
#if QT_CONFIG(thread)
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#endif
-#include <qelapsedtimer.h>
#include <qlibraryinfo.h>
+#include <qpointer.h>
#include <qvarlengtharray.h>
#include <private/qfactoryloader_p.h>
#include <private/qfunctions_p.h>
@@ -74,6 +44,10 @@
#include <private/qlocking_p.h>
#include <private/qhooks_p.h>
+#if QT_CONFIG(permissions)
+#include <private/qpermissions_p.h>
+#endif
+
#ifndef QT_NO_QOBJECT
#if defined(Q_OS_UNIX)
# if defined(Q_OS_DARWIN)
@@ -83,19 +57,20 @@
# include "qeventdispatcher_glib_p.h"
# endif
# endif
-# include "qeventdispatcher_unix_p.h"
+# if !defined(Q_OS_WASM)
+# include "qeventdispatcher_unix_p.h"
+# endif
#endif
#ifdef Q_OS_WIN
#include "qeventdispatcher_win_p.h"
#endif
#endif // QT_NO_QOBJECT
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
-# include <private/qjni_p.h>
-# include <private/qjnihelpers_p.h>
+#if defined(Q_OS_ANDROID)
+#include <QtCore/qjniobject.h>
#endif
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
# include "qcore_mac_p.h"
#endif
@@ -103,9 +78,17 @@
#ifdef Q_OS_UNIX
# include <locale.h>
-# include <langinfo.h>
+# ifndef Q_OS_INTEGRITY
+# include <langinfo.h>
+# endif
# include <unistd.h>
# include <sys/types.h>
+
+# include "qcore_unix_p.h"
+#endif
+
+#if __has_include(<sys/auxv.h>) // Linux and FreeBSD
+# include <sys/auxv.h>
#endif
#ifdef Q_OS_VXWORKS
@@ -123,19 +106,35 @@
#endif
#include <algorithm>
+#include <memory>
+#include <string>
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
-extern QString qAppFileName();
+#ifndef QT_NO_QOBJECT
+Q_LOGGING_CATEGORY(lcDeleteLater, "qt.core.qobject.deletelater")
#endif
-#if QT_VERSION >= 0x070000
-# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x070000"
+using namespace Qt::StringLiterals;
+
+Q_TRACE_PREFIX(qtcore,
+ "#include <qcoreevent.h>"
+);
+Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
+Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_entry, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit);
+Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_compressed, QObject *receiver, QEvent *event);
+Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_event_posted, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtcore, QCoreApplication_sendEvent, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtcore, QCoreApplication_sendSpontaneousEvent, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtcore, QCoreApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtcore, QCoreApplication_notify_exit, bool consumed, bool filtered);
+
+#if defined(Q_OS_WIN) || defined(Q_OS_DARWIN)
+extern QString qAppFileName();
#endif
-int QCoreApplicationPrivate::app_compile_version = 0x060000; //we don't know exactly, but it's at least 6.0.0
-bool QCoreApplicationPrivate::setuidAllowed = false;
+Q_CONSTINIT bool QCoreApplicationPrivate::setuidAllowed = false;
#if !defined(Q_OS_WIN)
#ifdef Q_OS_DARWIN
@@ -166,34 +165,33 @@ QString QCoreApplicationPrivate::appName() const
QString QCoreApplicationPrivate::appVersion() const
{
QString applicationVersion;
-#ifndef QT_BOOTSTRAPPED
-# ifdef Q_OS_DARWIN
+#ifdef QT_BOOTSTRAPPED
+#elif defined(Q_OS_DARWIN)
applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion"));
-# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- QJNIObjectPrivate context(QtAndroidPrivate::context());
+#elif defined(Q_OS_ANDROID)
+ QJniObject context(QNativeInterface::QAndroidApplication::context());
if (context.isValid()) {
- QJNIObjectPrivate pm = context.callObjectMethod(
+ QJniObject pm = context.callObjectMethod(
"getPackageManager", "()Landroid/content/pm/PackageManager;");
- QJNIObjectPrivate pn = context.callObjectMethod<jstring>("getPackageName");
+ QJniObject pn = context.callObjectMethod<jstring>("getPackageName");
if (pm.isValid() && pn.isValid()) {
- QJNIObjectPrivate packageInfo = pm.callObjectMethod(
+ QJniObject packageInfo = pm.callObjectMethod(
"getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
pn.object(), 0);
if (packageInfo.isValid()) {
- QJNIObjectPrivate versionName = packageInfo.getObjectField(
+ QJniObject versionName = packageInfo.getObjectField(
"versionName", "Ljava/lang/String;");
if (versionName.isValid())
return versionName.toString();
}
}
}
-# endif
#endif
return applicationVersion;
}
-#endif
+#endif // !Q_OS_WIN
-QString *QCoreApplicationPrivate::cachedApplicationFilePath = nullptr;
+Q_CONSTINIT QString *QCoreApplicationPrivate::cachedApplicationFilePath = nullptr;
bool QCoreApplicationPrivate::checkInstance(const char *function)
{
@@ -243,7 +241,11 @@ void QCoreApplicationPrivate::processCommandLineArguments()
// Support for introspection
-extern "C" void Q_CORE_EXPORT qt_startup_hook()
+extern "C" void
+#ifdef QT_SHARED
+Q_DECL_EXPORT_OVERRIDABLE
+#endif
+qt_startup_hook()
{
}
@@ -251,7 +253,8 @@ typedef QList<QtStartUpFunction> QStartUpFuncList;
Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
typedef QList<QtCleanUpFunction> QVFuncList;
Q_GLOBAL_STATIC(QVFuncList, postRList)
-static QBasicMutex globalRoutinesMutex;
+Q_CONSTINIT static QBasicMutex globalRoutinesMutex;
+Q_CONSTINIT static bool preRoutinesCalled = false;
/*!
\internal
@@ -265,8 +268,10 @@ void qAddPreRoutine(QtStartUpFunction p)
if (!list)
return;
- if (QCoreApplication::instance())
+ if (preRoutinesCalled) {
+ Q_ASSERT(QCoreApplication::instance());
p();
+ }
// Due to C++11 parallel dynamic initialization, this can be called
// from multiple threads.
@@ -294,19 +299,22 @@ void qRemovePostRoutine(QtCleanUpFunction p)
static void qt_call_pre_routines()
{
+ // After will be allowed invoke QtStartUpFunction when calling qAddPreRoutine
+ preRoutinesCalled = true;
+
if (!preRList.exists())
return;
- QVFuncList list;
- {
+ const QStartUpFuncList list = [] {
const auto locker = qt_scoped_lock(globalRoutinesMutex);
// Unlike qt_call_post_routines, we don't empty the list, because
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// the function to be executed every time QCoreApplication is created.
- list = *preRList;
- }
- for (int i = 0; i < list.count(); ++i)
- list.at(i)();
+ return *preRList;
+ }();
+
+ for (QtStartUpFunction f : list)
+ f();
}
void Q_CORE_EXPORT qt_call_post_routines()
@@ -324,7 +332,7 @@ void Q_CORE_EXPORT qt_call_post_routines()
if (list.isEmpty())
break;
- for (QtCleanUpFunction f : qAsConst(list))
+ for (QtCleanUpFunction f : std::as_const(list))
f();
}
}
@@ -333,25 +341,24 @@ void Q_CORE_EXPORT qt_call_post_routines()
#ifndef QT_NO_QOBJECT
// app starting up if false
-bool QCoreApplicationPrivate::is_app_running = false;
+Q_CONSTINIT bool QCoreApplicationPrivate::is_app_running = false;
// app closing down if true
-bool QCoreApplicationPrivate::is_app_closing = false;
+Q_CONSTINIT bool QCoreApplicationPrivate::is_app_closing = false;
-Q_CORE_EXPORT uint qGlobalPostedEventsCount()
+qsizetype qGlobalPostedEventsCount()
{
- QThreadData *currentThreadData = QThreadData::current();
- return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
+ const QPostEventList &l = QThreadData::current()->postEventList;
+ return l.size() - l.startOffset;
}
-QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = nullptr;
+Q_CONSTINIT QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = nullptr;
#endif // QT_NO_QOBJECT
-QCoreApplication *QCoreApplication::self = nullptr;
-uint QCoreApplicationPrivate::attribs =
+Q_CONSTINIT QCoreApplication *QCoreApplication::self = nullptr;
+Q_CONSTINIT uint QCoreApplicationPrivate::attribs =
(1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents) |
- (1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents) |
- (1 << Qt::AA_UseHighDpiPixmaps);
+ (1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
struct QCoreApplicationData {
QCoreApplicationData() noexcept {
@@ -375,8 +382,8 @@ struct QCoreApplicationData {
bool applicationVersionSet; // true if setApplicationVersion was called
#if QT_CONFIG(library)
- QScopedPointer<QStringList> app_libpaths;
- QScopedPointer<QStringList> manual_libpaths;
+ std::unique_ptr<QStringList> app_libpaths;
+ std::unique_ptr<QStringList> manual_libpaths;
#endif
};
@@ -384,14 +391,15 @@ struct QCoreApplicationData {
Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
#ifndef QT_NO_QOBJECT
-static bool quitLockRefEnabled = true;
+Q_CONSTINIT static bool quitLockEnabled = true;
#endif
#if defined(Q_OS_WIN)
-// Check whether the command line arguments match those passed to main()
-// by comparing to the global __argv/__argc (MS extension).
-// Deep comparison is required since argv/argc is rebuilt by WinMain for
-// GUI apps or when using MinGW due to its globbing.
+// Check whether the command line arguments passed to QCoreApplication
+// match those passed into main(), to see if the user has modified them
+// before passing them on to us. We do this by comparing to the global
+// __argv/__argc (MS extension). Deep comparison is required since
+// argv/argc is rebuilt by our WinMain entrypoint.
static inline bool isArgvModified(int argc, char **argv)
{
if (__argc != argc || !__argv /* wmain() */)
@@ -415,7 +423,7 @@ static inline bool contains(int argc, char **argv, const char *needle)
}
#endif // Q_OS_WIN
-QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
+QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv)
:
#ifndef QT_NO_QOBJECT
QObjectPrivate(),
@@ -435,7 +443,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, q_ptr(nullptr)
#endif
{
- app_compile_version = flags & 0xffffff;
static const char *const empty = "";
if (argc == 0 || argv == nullptr) {
argc = 0;
@@ -470,6 +477,8 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate()
#endif
#if defined(Q_OS_WIN)
delete [] origArgv;
+ if (consoleAllocated)
+ FreeConsole();
#endif
QCoreApplicationPrivate::clearApplicationFilePath();
}
@@ -488,11 +497,10 @@ void QCoreApplicationPrivate::cleanupThreadData()
// need to clear the state of the mainData, just in case a new QCoreApplication comes along.
const auto locker = qt_scoped_lock(thisThreadData->postEventList.mutex);
- for (int i = 0; i < thisThreadData->postEventList.size(); ++i) {
- const QPostEvent &pe = thisThreadData->postEventList.at(i);
+ for (const QPostEvent &pe : std::as_const(thisThreadData->postEventList)) {
if (pe.event) {
--pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
+ pe.event->m_posted = false;
delete pe.event;
}
}
@@ -516,7 +524,8 @@ void QCoreApplicationPrivate::eventDispatcherReady()
{
}
-QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
+Q_CONSTINIT QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
+Q_CONSTINIT QBasicAtomicPointer<void> QCoreApplicationPrivate::theMainThreadId = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
QThread *QCoreApplicationPrivate::mainThread()
{
Q_ASSERT(theMainThread.loadRelaxed() != nullptr);
@@ -551,11 +560,11 @@ void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
{
#if QT_CONFIG(library)
- QStringList *app_libpaths = coreappdata()->app_libpaths.data();
+ QStringList *app_libpaths = coreappdata()->app_libpaths.get();
if (!app_libpaths)
coreappdata()->app_libpaths.reset(app_libpaths = new QStringList);
QString app_location = QCoreApplication::applicationFilePath();
- app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
+ app_location.truncate(app_location.lastIndexOf(u'/'));
app_location = QDir(app_location).canonicalPath();
if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
app_libpaths->append(app_location);
@@ -569,46 +578,117 @@ QString qAppName()
return QCoreApplication::instance()->d_func()->appName();
}
+void QCoreApplicationPrivate::initConsole()
+{
+#ifdef Q_OS_WINDOWS
+ const QString env = qEnvironmentVariable("QT_WIN_DEBUG_CONSOLE");
+ if (env.isEmpty())
+ return;
+ if (env.compare(u"new"_s, Qt::CaseInsensitive) == 0) {
+ if (AllocConsole() == FALSE)
+ return;
+ consoleAllocated = true;
+ } else if (env.compare(u"attach"_s, Qt::CaseInsensitive) == 0) {
+ // If the calling process is already attached to a console,
+ // the error code returned is ERROR_ACCESS_DENIED.
+ if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::GetLastError() != ERROR_ACCESS_DENIED)
+ return;
+ } else {
+ // Unknown input, don't make any decision for the user.
+ return;
+ }
+ // The std{in,out,err} handles are read-only, so we need to pass in dummies.
+ FILE *in = nullptr;
+ FILE *out = nullptr;
+ FILE *err = nullptr;
+ freopen_s(&in, "CONIN$", "r", stdin);
+ freopen_s(&out, "CONOUT$", "w", stdout);
+ freopen_s(&err, "CONOUT$", "w", stderr);
+ // However, things wouldn't work if the runtime did not preserve the pointers.
+ Q_ASSERT(in == stdin);
+ Q_ASSERT(out == stdout);
+ Q_ASSERT(err == stderr);
+#endif
+}
+
void QCoreApplicationPrivate::initLocale()
{
-#if defined(Q_OS_UNIX) && !defined(QT_BOOTSTRAPPED)
- static bool qt_locale_initialized = false;
+#if defined(QT_BOOTSTRAPPED)
+ // Don't try to control bootstrap library locale or encoding.
+#elif defined(Q_OS_UNIX)
+ Q_CONSTINIT static bool qt_locale_initialized = false;
if (qt_locale_initialized)
return;
qt_locale_initialized = true;
- // Android's Bionic didn't get nl_langinfo until NDK 15 (Android 8.0),
- // which is too new for Qt, so we just assume it's always UTF-8.
- auto nl_langinfo = [](int) { return "UTF-8"; };
-
- const char *locale = setlocale(LC_ALL, "");
- const char *codec = nl_langinfo(CODESET);
- if (Q_UNLIKELY(strcmp(codec, "UTF-8") != 0 && strcmp(codec, "utf8") != 0)) {
- QByteArray oldLocale = locale;
- QByteArray newLocale = setlocale(LC_CTYPE, nullptr);
- if (int dot = newLocale.indexOf('.'); dot != -1)
+ // By default the portable "C"/POSIX locale is selected and active.
+ // Apply the locale from the environment, via setlocale(), which will
+ // read LC_ALL, LC_<category>, and LANG, in order (for each category).
+ setlocale(LC_ALL, "");
+
+ // Next, let's ensure that LC_CTYPE is UTF-8, since QStringConverter's
+ // QLocal8Bit hard-codes this, and we need to be consistent.
+# if defined(Q_OS_INTEGRITY)
+ setlocale(LC_CTYPE, "UTF-8");
+# elif defined(Q_OS_QNX)
+ // QNX has no nl_langinfo, so we can't check.
+ // FIXME: Shouldn't we still setlocale("UTF-8")?
+# elif defined(Q_OS_ANDROID) && __ANDROID_API__ < __ANDROID_API_O__
+ // Android 6 still lacks nl_langinfo(), so we can't check.
+ // FIXME: Shouldn't we still setlocale("UTF-8")?
+# elif defined(Q_OS_VXWORKS)
+ // VxWorks has no nl_langinfo, so we can't check.
+# else
+ // std::string's SSO usually saves this the need to allocate:
+ const std::string oldEncoding = nl_langinfo(CODESET);
+ if (!Q_LIKELY(qstricmp(oldEncoding.data(), "UTF-8") == 0
+ || qstricmp(oldEncoding.data(), "utf8") == 0)) {
+ const QByteArray oldLocale = setlocale(LC_ALL, nullptr);
+ QByteArray newLocale;
+ bool warnOnOverride = true;
+# if defined(Q_OS_DARWIN)
+ // Don't warn unless the char encoding has been changed from the
+ // default "C" encoding, or the user touched any of the locale
+ // environment variables to force the "C" char encoding.
+ warnOnOverride = qstrcmp(setlocale(LC_CTYPE, nullptr), "C") != 0
+ || getenv("LC_ALL") || getenv("LC_CTYPE") || getenv("LANG");
+
+ // No need to try language or region specific CTYPEs, as they
+ // all point back to the same generic UTF-8 CTYPE.
+ newLocale = setlocale(LC_CTYPE, "UTF-8");
+# else
+ newLocale = setlocale(LC_CTYPE, nullptr);
+ if (qsizetype dot = newLocale.indexOf('.'); dot != -1)
newLocale.truncate(dot); // remove encoding, if any
- if (int at = newLocale.indexOf('@'); at != -1)
+ if (qsizetype at = newLocale.indexOf('@'); at != -1)
newLocale.truncate(at); // remove variant, as the old de_DE@euro
newLocale += ".UTF-8";
newLocale = setlocale(LC_CTYPE, newLocale);
- // if locale doesn't exist, try some fallbacks
-# ifdef Q_OS_DARWIN
- if (newLocale.isEmpty())
- newLocale = setlocale(LC_CTYPE, "UTF-8");
-# endif
+ // If that locale doesn't exist, try some fallbacks:
if (newLocale.isEmpty())
newLocale = setlocale(LC_CTYPE, "C.UTF-8");
if (newLocale.isEmpty())
newLocale = setlocale(LC_CTYPE, "C.utf8");
-
- qWarning("Detected system locale encoding (%s, locale \"%s\") is not UTF-8.\n"
- "Qt shall use a UTF-8 locale (\"%s\") instead. If this causes problems,\n"
- "reconfigure your locale. See the locale(1) manual for more information.",
- codec, oldLocale.constData(), newLocale.constData());
+# endif
+
+ if (newLocale.isEmpty()) {
+ // Failed to set a UTF-8 locale.
+ qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
+ "Qt depends on a UTF-8 locale, but has failed to switch to one.\n"
+ "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
+ "for more information.", oldLocale.constData(), oldEncoding.data());
+ } else if (warnOnOverride) {
+ // Let the user know we over-rode their configuration.
+ qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n"
+ "Qt depends on a UTF-8 locale, and has switched to \"%s\" instead.\n"
+ "If this causes problems, reconfigure your locale. See the locale(1) manual\n"
+ "for more information.",
+ oldLocale.constData(), oldEncoding.data(), newLocale.constData());
+ }
}
-#endif
+# endif // Platform choice
+#endif // Unix
}
@@ -661,8 +741,7 @@ void QCoreApplicationPrivate::initLocale()
Translation files can be added or removed
using installTranslator() and removeTranslator(). Application
strings can be translated using translate(). The QObject::tr()
- and QObject::trUtf8() functions are implemented in terms of
- translate().
+ function is implemented in terms of translate().
\section1 Accessing Command Line Arguments
@@ -685,7 +764,8 @@ void QCoreApplicationPrivate::initLocale()
to reset the locale that is used for number formatting to "C"-locale.
\sa QGuiApplication, QAbstractEventDispatcher, QEventLoop,
- {Semaphores Example}, {Wait Conditions Example}
+ {Producer and Consumer using Semaphores},
+ {Producer and Consumer using Wait Conditions}
*/
/*!
@@ -712,26 +792,6 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
// QCoreApplicationPrivate::eventDispatcher->startingUp();
}
-#ifndef QT_NO_QOBJECT
-/*!
- \deprecated
- This function is equivalent to calling \c {QCoreApplication::eventDispatcher()->flush()},
- which also is deprecated, see QAbstractEventDispatcher::flush(). Use sendPostedEvents()
- and processEvents() for more fine-grained control of the event loop instead.
-
- Historically this functions was used to flush the platform-specific native event queues.
-
- \sa sendPostedEvents(), processEvents(), QAbstractEventDispatcher::flush()
-*/
-#if QT_DEPRECATED_SINCE(5, 9)
-void QCoreApplication::flush()
-{
- if (self && self->d_func()->eventDispatcher)
- self->d_func()->eventDispatcher->flush();
-}
-#endif
-#endif
-
/*!
Constructs a Qt core application. Core applications are applications without
a graphical user interface. Such applications are used at the console or as
@@ -748,13 +808,13 @@ void QCoreApplication::flush()
*/
QCoreApplication::QCoreApplication(int &argc, char **argv
#ifndef Q_QDOC
- , int _internal
+ , int
#endif
)
#ifdef QT_NO_QOBJECT
- : d_ptr(new QCoreApplicationPrivate(argc, argv, _internal))
+ : d_ptr(new QCoreApplicationPrivate(argc, argv))
#else
- : QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
+ : QObject(*new QCoreApplicationPrivate(argc, argv))
#endif
{
d_func()->q_ptr = this;
@@ -771,7 +831,7 @@ QCoreApplication::QCoreApplication(int &argc, char **argv
\value ApplicationFlags QT_VERSION
*/
-void QCoreApplicationPrivate::init()
+void Q_TRACE_INSTRUMENT(qtcore) QCoreApplicationPrivate::init()
{
Q_TRACE_SCOPE(QCoreApplicationPrivate_init);
@@ -781,6 +841,8 @@ void QCoreApplicationPrivate::init()
Q_Q(QCoreApplication);
+ initConsole();
+
initLocale();
Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
@@ -788,7 +850,11 @@ void QCoreApplicationPrivate::init()
#if QT_CONFIG(thread)
#ifdef Q_OS_WASM
- QThreadPrivate::idealThreadCount = emscripten::val::global("navigator")["hardwareConcurrency"].as<int>();
+ emscripten::val hardwareConcurrency = emscripten::val::global("navigator")["hardwareConcurrency"];
+ if (hardwareConcurrency.isUndefined())
+ QThreadPrivate::idealThreadCount = 2;
+ else
+ QThreadPrivate::idealThreadCount = hardwareConcurrency.as<int>();
#endif
#endif
@@ -811,8 +877,8 @@ void QCoreApplicationPrivate::init()
// Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
// into account. If necessary, recompute right away and replay the manual changes on top of the
// new lib paths.
- QStringList *appPaths = coreappdata()->app_libpaths.take();
- QStringList *manualPaths = coreappdata()->manual_libpaths.take();
+ QStringList *appPaths = coreappdata()->app_libpaths.release();
+ QStringList *manualPaths = coreappdata()->manual_libpaths.release();
if (appPaths) {
if (manualPaths) {
// Replay the delta. As paths can only be prepended to the front or removed from
@@ -820,7 +886,7 @@ void QCoreApplicationPrivate::init()
// have been removed. Once the original list is exhausted we know all the remaining
// items have been added.
QStringList newPaths(q->libraryPaths());
- for (int i = manualPaths->length(), j = appPaths->length(); i > 0 || j > 0; qt_noop()) {
+ for (qsizetype i = manualPaths->size(), j = appPaths->size(); i > 0 || j > 0; qt_noop()) {
if (--j < 0) {
newPaths.prepend((*manualPaths)[--i]);
} else if (--i < 0) {
@@ -862,6 +928,7 @@ void QCoreApplicationPrivate::init()
qt_call_pre_routines();
qt_startup_hook();
#ifndef QT_BOOTSTRAPPED
+ QtPrivate::initBindingStatusThreadId();
if (Q_UNLIKELY(qtHookData[QHooks::Startup]))
reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
#endif
@@ -876,6 +943,8 @@ void QCoreApplicationPrivate::init()
*/
QCoreApplication::~QCoreApplication()
{
+ preRoutinesCalled = false;
+
qt_call_post_routines();
self = nullptr;
@@ -887,8 +956,10 @@ QCoreApplication::~QCoreApplication()
#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
QThreadPool *globalThreadPool = nullptr;
+ QThreadPool *guiThreadPool = nullptr;
QT_TRY {
globalThreadPool = QThreadPool::globalInstance();
+ guiThreadPool = QThreadPoolPrivate::qtGuiInstance();
} QT_CATCH (...) {
// swallow the exception, since destructors shouldn't throw
}
@@ -896,6 +967,10 @@ QCoreApplication::~QCoreApplication()
globalThreadPool->waitForDone();
delete globalThreadPool;
}
+ if (guiThreadPool) {
+ guiThreadPool->waitForDone();
+ delete guiThreadPool;
+ }
#endif
#ifndef QT_NO_QOBJECT
@@ -929,7 +1004,10 @@ QCoreApplication::~QCoreApplication()
and must be set before a QCoreApplication instance is created.
\note It is strongly recommended not to enable this option since
- it introduces security risks.
+ it introduces security risks. If this application does enable the flag and
+ starts child processes, it should drop the privileges as early as possible
+ by calling \c{setuid(2)} for itself, or at the latest by using the
+ QProcess::UnixProcessParameters::ResetIds flag.
*/
void QCoreApplication::setSetuidAllowed(bool allow)
{
@@ -949,7 +1027,6 @@ bool QCoreApplication::isSetuidAllowed()
return QCoreApplicationPrivate::setuidAllowed;
}
-
/*!
Sets the attribute \a attribute if \a on is true;
otherwise clears the attribute.
@@ -962,6 +1039,10 @@ bool QCoreApplication::isSetuidAllowed()
*/
void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
{
+ // Since we bit-shift these values, we can't go higher than 32 on 32 bit operating systems
+ // without changing the storage type of QCoreApplicationPrivate::attribs to quint64.
+ static_assert(Qt::AA_AttributeCount <= sizeof(QCoreApplicationPrivate::attribs) * CHAR_BIT);
+
if (on)
QCoreApplicationPrivate::attribs |= 1 << attribute;
else
@@ -972,8 +1053,6 @@ void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
if (Q_UNLIKELY(QCoreApplicationPrivate::is_app_running)) {
#endif
switch (attribute) {
- case Qt::AA_EnableHighDpiScaling:
- case Qt::AA_DisableHighDpiScaling:
case Qt::AA_PluginApplication:
case Qt::AA_UseDesktopOpenGL:
case Qt::AA_UseOpenGLES:
@@ -1004,7 +1083,6 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
return QCoreApplicationPrivate::testAttribute(attribute);
}
-
#ifndef QT_NO_QOBJECT
/*!
@@ -1013,6 +1091,14 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
\brief Whether the use of the QEventLoopLocker feature can cause the
application to quit.
+ When this property is \c true the release of the last remaining
+ QEventLoopLocker operating on the application will attempt to
+ quit the application.
+
+ Note that attempting a quit may not necessarily result in the
+ application quitting, for example if there still are open windows,
+ or the QEvent::Quit event is ignored.
+
The default is \c true.
\sa QEventLoopLocker
@@ -1020,30 +1106,16 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
bool QCoreApplication::isQuitLockEnabled()
{
- return quitLockRefEnabled;
+ return quitLockEnabled;
}
static bool doNotify(QObject *, QEvent *);
void QCoreApplication::setQuitLockEnabled(bool enabled)
{
- quitLockRefEnabled = enabled;
+ quitLockEnabled = enabled;
}
-#if QT_DEPRECATED_SINCE(5, 6)
-/*!
- \internal
- \deprecated
-
- This function is here to make it possible for Qt extensions to
- hook into event notification without subclassing QApplication
-*/
-bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
-{
- return notifyInternal2(receiver, event);
-}
-#endif
-
/*!
\internal
\since 5.6
@@ -1054,7 +1126,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
{
bool selfRequired = QCoreApplicationPrivate::threadRequiresCoreApplication();
- if (!self && selfRequired)
+ if (selfRequired && !self)
return false;
// Make it possible for Qt Script to hook into events even
@@ -1070,10 +1142,15 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
// equivalent to QThreadData::current(), just without the function
// call overhead.
QObjectPrivate *d = receiver->d_func();
- QThreadData *threadData = d->threadData;
+ QThreadData *threadData = d->threadData.loadAcquire();
QScopedScopeLevelCounter scopeLevelCounter(threadData);
if (!selfRequired)
return doNotify(receiver, event);
+
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
+ if (threadData->thread.loadRelaxed() != QCoreApplicationPrivate::mainThread())
+ return false;
+#endif
return self->notify(receiver, event);
}
@@ -1087,7 +1164,7 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent)
{
if (event && originatingEvent)
- event->spont = originatingEvent->spont;
+ event->m_spont = originatingEvent->m_spont;
return notifyInternal2(receiver, event);
}
@@ -1132,7 +1209,7 @@ bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *or
\endlist
\b{Future direction:} This function will not be called for objects that live
- outside the main thread in Qt 6. Applications that need that functionality
+ outside the main thread in Qt 7. Applications that need that functionality
should find other solutions for their event inspection needs in the meantime.
The change may be extended to the main thread, causing this function to be
deprecated.
@@ -1147,6 +1224,14 @@ bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *or
bool QCoreApplication::notify(QObject *receiver, QEvent *event)
{
+ Q_ASSERT(receiver);
+ Q_ASSERT(event);
+
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
+ Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed()
+ == QCoreApplicationPrivate::mainThread());
+#endif
+
// no events are delivered after ~QCoreApplication() has started
if (QCoreApplicationPrivate::is_app_closing)
return true;
@@ -1155,6 +1240,9 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event)
static bool doNotify(QObject *receiver, QEvent *event)
{
+ Q_ASSERT(event);
+
+ // ### Qt 7: turn into an assert
if (receiver == nullptr) { // serious error
qWarning("QCoreApplication::notify: Unexpected null receiver");
return true;
@@ -1170,15 +1258,15 @@ static bool doNotify(QObject *receiver, QEvent *event)
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{
// We can't access the application event filters outside of the main thread (race conditions)
- Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread());
+ Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed() == mainThread());
if (extraData) {
// application event filters are only called for objects in the GUI thread
- for (int i = 0; i < extraData->eventFilters.size(); ++i) {
+ for (qsizetype i = 0; i < extraData->eventFilters.size(); ++i) {
QObject *obj = extraData->eventFilters.at(i);
if (!obj)
continue;
- if (obj->d_func()->threadData != threadData) {
+ if (obj->d_func()->threadData.loadRelaxed() != threadData.loadRelaxed()) {
qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
continue;
}
@@ -1191,12 +1279,14 @@ bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiv
bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
{
- if (receiver != QCoreApplication::instance() && receiver->d_func()->extraData) {
- for (int i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
+ if ((receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() != mainThread()
+ || receiver != QCoreApplication::instance())
+ && receiver->d_func()->extraData) {
+ for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
if (!obj)
continue;
- if (obj->d_func()->threadData != receiver->d_func()->threadData) {
+ if (obj->d_func()->threadData.loadRelaxed() != receiver->d_func()->threadData.loadRelaxed()) {
qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
continue;
}
@@ -1222,8 +1312,8 @@ bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);
// send to all application event filters (only does anything in the main thread)
- if (QCoreApplication::self
- && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
+ if (receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
+ && QCoreApplication::self
&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
filtered = true;
return filtered;
@@ -1265,11 +1355,13 @@ bool QCoreApplication::closingDown()
/*!
- Processes all pending events for the calling thread according to
- the specified \a flags until there are no more events to process.
+ Processes some pending events for the calling thread according to
+ the specified \a flags.
- You can call this function occasionally when your program is busy
- performing a long operation (e.g. copying a file).
+ Use of this function is discouraged. Instead, prefer to move long
+ operations out of the GUI thread into an auxiliary one and to completely
+ avoid nested event loop processing. If event processing is really
+ necessary, consider using \l QEventLoop instead.
In the event that you are running a local loop which calls this function
continuously, without an event loop, the
@@ -1288,7 +1380,8 @@ bool QCoreApplication::closingDown()
\threadsafe
- \sa exec(), QTimer, QEventLoop::processEvents(), flush(), sendPostedEvents()
+ \sa exec(), QTimer, QChronoTimer, QEventLoop::processEvents(),
+ sendPostedEvents()
*/
void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
{
@@ -1299,36 +1392,57 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
}
/*!
- \overload processEvents()
+ \overload
Processes pending events for the calling thread for \a ms
milliseconds or until there are no more events to process,
whichever is shorter.
- You can call this function occasionally when your program is busy
- doing a long operation (e.g. copying a file).
+ This is equivalent to calling:
+ \code
+ QCoreApplication::processEvents(flags, QDeadlineTimer(ms));
+ \endcode
+*/
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
+{
+ QCoreApplication::processEvents(flags, QDeadlineTimer(ms));
+}
+
+/*!
+ \since 6.7
+ \overload
+
+ Processes pending events for the calling thread untile \a deadline has expired,
+ or until there are no more events to process, whichever happens first.
+
+ Use of this function is discouraged. Instead, prefer to move long
+ operations out of the GUI thread into an auxiliary one and to completely
+ avoid nested event loop processing. If event processing is really
+ necessary, consider using \l QEventLoop instead.
Calling this function processes events only for the calling thread.
\note Unlike the \l{QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)}{processEvents()}
overload, this function also processes events that are posted while the function runs.
+ \note All events that were queued before the timeout will be processed,
+ however long it takes.
+
\threadsafe
- \sa exec(), QTimer, QEventLoop::processEvents()
+ \sa exec(), QTimer, QChronoTimer, QEventLoop::processEvents()
*/
-void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, QDeadlineTimer deadline)
{
- // ### Qt 6: consider splitting this method into a public and a private
+ // ### TODO: consider splitting this method into a public and a private
// one, so that a user-invoked processEvents can be detected
// and handled properly.
QThreadData *data = QThreadData::current();
if (!data->hasEventDispatcher())
return;
- QElapsedTimer start;
- start.start();
+
while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
- if (start.elapsed() > ms)
+ if (deadline.hasExpired())
break;
}
}
@@ -1346,10 +1460,10 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m
main event loop receives events from the window system and
dispatches these to the application widgets.
- To make your application perform idle processing (by executing a
- special function whenever there are no pending events), use a
- QTimer with 0 timeout. More advanced idle processing schemes can
- be achieved using processEvents().
+ To make your application perform idle processing (by executing a special
+ function whenever there are no pending events), use a QChronoTimer
+ with 0ns timeout. More advanced idle processing schemes can be achieved
+ using processEvents().
We recommend that you connect clean-up code to the
\l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in
@@ -1368,7 +1482,7 @@ int QCoreApplication::exec()
if (!QCoreApplicationPrivate::checkInstance("exec"))
return -1;
- QThreadData *threadData = self->d_func()->threadData;
+ QThreadData *threadData = self->d_func()->threadData.loadAcquire();
if (threadData != QThreadData::current()) {
qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
return -1;
@@ -1382,7 +1496,7 @@ int QCoreApplication::exec()
QEventLoop eventLoop;
self->d_func()->in_exec = true;
self->d_func()->aboutToQuitEmitted = false;
- int returnCode = eventLoop.exec();
+ int returnCode = eventLoop.exec(QEventLoop::ApplicationExec);
threadData->quitNow = false;
if (self)
@@ -1401,9 +1515,8 @@ void QCoreApplicationPrivate::execCleanup()
{
threadData.loadRelaxed()->quitNow = false;
in_exec = false;
- if (!aboutToQuitEmitted)
- emit q_func()->aboutToQuit(QCoreApplication::QPrivateSignal());
- aboutToQuitEmitted = true;
+
+ qCDebug(lcDeleteLater) << "Sending deferred delete events as part of exec cleanup";
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
}
@@ -1430,15 +1543,26 @@ void QCoreApplicationPrivate::execCleanup()
function \e does return to the caller -- it is event processing that
stops.
+ Note also that this function is not thread-safe. It should be called only
+ from the main thread (the thread that the QCoreApplication object is
+ processing events on). To ask the application to exit from another thread,
+ either use QCoreApplication::quit() or instead call this function from the
+ main thread with QMetaMethod::invokeMethod().
+
\sa quit(), exec()
*/
void QCoreApplication::exit(int returnCode)
{
if (!self)
return;
- QThreadData *data = self->d_func()->threadData.loadRelaxed();
+ QCoreApplicationPrivate *d = self->d_func();
+ if (!d->aboutToQuitEmitted) {
+ emit self->aboutToQuit(QCoreApplication::QPrivateSignal());
+ d->aboutToQuitEmitted = true;
+ }
+ QThreadData *data = d->threadData.loadRelaxed();
data->quitNow = true;
- for (int i = 0; i < data->eventLoops.size(); ++i) {
+ for (qsizetype i = 0; i < data->eventLoops.size(); ++i) {
QEventLoop *eventLoop = data->eventLoops.at(i);
eventLoop->exit(returnCode);
}
@@ -1465,10 +1589,12 @@ void QCoreApplication::exit(int returnCode)
*/
bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
{
+ Q_ASSERT_X(receiver, "QCoreApplication::sendEvent", "Unexpected null receiver");
+ Q_ASSERT_X(event, "QCoreApplication::sendEvent", "Unexpected null event");
+
Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
- if (event)
- event->spont = false;
+ event->m_spont = false;
return notifyInternal2(receiver, event);
}
@@ -1477,10 +1603,12 @@ bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
*/
bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
{
+ Q_ASSERT_X(receiver, "QCoreApplication::sendSpontaneousEvent", "Unexpected null receiver");
+ Q_ASSERT_X(event, "QCoreApplication::sendSpontaneousEvent", "Unexpected null event");
+
Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
- if (event)
- event->spont = true;
+ event->m_spont = true;
return notifyInternal2(receiver, event);
}
@@ -1545,8 +1673,11 @@ QCoreApplicationPrivate::QPostEventListLocker QCoreApplicationPrivate::lockThrea
*/
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
+ Q_ASSERT_X(event, "QCoreApplication::postEvent", "Unexpected null event");
+
Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
+ // ### Qt 7: turn into an assert
if (receiver == nullptr) {
qWarning("QCoreApplication::postEvent: Unexpected null receiver");
delete event;
@@ -1569,38 +1700,13 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
return;
}
- if (event->type() == QEvent::DeferredDelete)
- receiver->d_ptr->deleteLaterCalled = true;
-
- if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
- // remember the current running eventloop for DeferredDelete
- // events posted in the receiver's thread.
-
- // Events sent by non-Qt event handlers (such as glib) may not
- // have the scopeLevel set correctly. The scope level makes sure that
- // code like this:
- // foo->deleteLater();
- // qApp->processEvents(); // without passing QEvent::DeferredDelete
- // will not cause "foo" to be deleted before returning to the event loop.
-
- // If the scope level is 0 while loopLevel != 0, we are called from a
- // non-conformant code path, and our best guess is that the scope level
- // should be 1. (Loop level 0 is special: it means that no event loops
- // are running.)
- int loopLevel = data->loopLevel;
- int scopeLevel = data->scopeLevel;
- if (scopeLevel == 0 && loopLevel != 0)
- scopeLevel = 1;
- static_cast<QDeferredDeleteEvent *>(event)->level = loopLevel + scopeLevel;
- }
-
// delete the event on exceptions to protect against memory leaks till the event is
// properly owned in the postEventList
- QScopedPointer<QEvent> eventDeleter(event);
+ std::unique_ptr<QEvent> eventDeleter(event);
Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
data->postEventList.addEvent(QPostEvent(receiver, event, priority));
- eventDeleter.take();
- event->posted = true;
+ Q_UNUSED(eventDeleter.release());
+ event->m_posted = true;
++receiver->d_func()->postedEvents;
data->canWait = false;
locker.unlock();
@@ -1616,40 +1722,31 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
*/
bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
{
-#ifdef Q_OS_WIN
Q_ASSERT(event);
Q_ASSERT(receiver);
Q_ASSERT(postedEvents);
+ int receiverPostedEvents = receiver->d_func()->postedEvents.loadRelaxed();
// compress posted timers to this object.
- if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) {
- int timerId = ((QTimerEvent *) event)->timerId();
- for (int i=0; i<postedEvents->size(); ++i) {
- const QPostEvent &e = postedEvents->at(i);
- if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer
- && ((QTimerEvent *) e.event)->timerId() == timerId) {
+ if (event->type() == QEvent::Timer && receiverPostedEvents > 0) {
+ int timerId = static_cast<QTimerEvent *>(event)->timerId();
+ auto sameReceiver = [receiver](const QPostEvent &e) { return e.receiver == receiver; };
+ auto it = std::find_if(postedEvents->cbegin(), postedEvents->cend(), sameReceiver);
+ while (receiverPostedEvents > 0 && it != postedEvents->cend()) {
+ if (it->event && it->event->type() == QEvent::Timer
+ && static_cast<QTimerEvent *>(it->event)->timerId() == timerId) {
delete event;
return true;
}
- }
- return false;
- }
-#endif
- if (event->type() == QEvent::DeferredDelete) {
- if (receiver->d_ptr->deleteLaterCalled) {
- // there was a previous DeferredDelete event, so we can drop the new one
- delete event;
- return true;
+ if (--receiverPostedEvents)
+ it = std::find_if(it + 1, postedEvents->cend(), sameReceiver);
}
- // deleteLaterCalled is set to true in postedEvents when queueing the very first
- // deferred deletion event.
return false;
}
- if (event->type() == QEvent::Quit && receiver->d_func()->postedEvents > 0) {
- for (int i = 0; i < postedEvents->size(); ++i) {
- const QPostEvent &cur = postedEvents->at(i);
+ if (event->type() == QEvent::Quit && receiverPostedEvents > 0) {
+ for (const QPostEvent &cur : std::as_const(*postedEvents)) {
if (cur.receiver != receiver
|| cur.event == nullptr
|| cur.event->type() != event->type())
@@ -1678,11 +1775,11 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven
\note This method must be called from the thread in which its QObject
parameter, \a receiver, lives.
- \sa flush(), postEvent()
+ \sa postEvent()
*/
void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
{
- // ### Qt 6: consider splitting this method into a public and a private
+ // ### TODO: consider splitting this method into a public and a private
// one, so that a user-invoked sendPostedEvents can be detected
// and handled properly.
QThreadData *data = QThreadData::current();
@@ -1698,7 +1795,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
event_type = 0;
}
- if (receiver && receiver->d_func()->threadData != data) {
+ if (receiver && receiver->d_func()->threadData.loadRelaxed() != data) {
qWarning("QCoreApplication::sendPostedEvents: Cannot send "
"posted events for objects in another thread");
return;
@@ -1722,8 +1819,8 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// okay. here is the tricky loop. be careful about optimizing
// this, it looks the way it does for good reasons.
- int startOffset = data->postEventList.startOffset;
- int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
+ qsizetype startOffset = data->postEventList.startOffset;
+ qsizetype &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
data->postEventList.insertionOffset = data->postEventList.size();
// Exception-safe cleaning up without the need for a try/catch block
@@ -1782,14 +1879,37 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// events posted by the current event loop; or
// 3) if the event was posted before the outermost event loop.
- int eventLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
- int loopLevel = data->loopLevel + data->scopeLevel;
- const bool allowDeferredDelete =
- (eventLevel > loopLevel
- || (!eventLevel && loopLevel > 0)
- || (event_type == QEvent::DeferredDelete
- && eventLevel == loopLevel));
+ const auto *event = static_cast<QDeferredDeleteEvent *>(pe.event);
+ qCDebug(lcDeleteLater) << "Processing deferred delete event for" << pe.receiver
+ << "with loop level" << event->loopLevel() << "and scope level" << event->scopeLevel();
+
+ qCDebug(lcDeleteLater) << "Checking" << data->thread << "with loop level"
+ << data->loopLevel << "and scope level" << data->scopeLevel;
+
+ bool allowDeferredDelete = false;
+ if (event->loopLevel() == 0 && data->loopLevel > 0) {
+ qCDebug(lcDeleteLater) << "Event was posted outside outermost event loop"
+ << "and current thread has an event loop running.";
+ allowDeferredDelete = true;
+ } else {
+ const int totalEventLevel = event->loopLevel() + event->scopeLevel();
+ const int totalThreadLevel = data->loopLevel + data->scopeLevel;
+
+ if (totalEventLevel > totalThreadLevel) {
+ qCDebug(lcDeleteLater) << "Combined levels of event" << totalEventLevel
+ << "is higher than thread" << totalThreadLevel;
+ allowDeferredDelete = true;
+ } else if (event_type == QEvent::DeferredDelete && totalEventLevel == totalThreadLevel) {
+ qCDebug(lcDeleteLater) << "Explicit send of DeferredDelete and"
+ << "levels of event" << totalEventLevel
+ << "is same as thread" << totalThreadLevel;
+ allowDeferredDelete = true;
+ }
+ }
+
if (!allowDeferredDelete) {
+ qCDebug(lcDeleteLater) << "Failed conditions for deferred delete. Deferring again";
+
// cannot send deferred delete
if (!event_type && !receiver) {
// we must copy it first; we want to re-post the event
@@ -1806,12 +1926,14 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
data->postEventList.addEvent(pe_copy);
}
continue;
+ } else {
+ qCDebug(lcDeleteLater) << "Sending deferred delete to" << pe.receiver;
}
}
// first, we diddle the event so that we can deliver
// it, and that no one will try to touch it later.
- pe.event->posted = false;
+ pe.event->m_posted = false;
QEvent *e = pe.event;
QObject * r = pe.receiver;
@@ -1872,16 +1994,16 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
//we will collect all the posted events for the QObject
//and we'll delete after the mutex was unlocked
QVarLengthArray<QEvent*> events;
- int n = data->postEventList.size();
- int j = 0;
+ qsizetype n = data->postEventList.size();
+ qsizetype j = 0;
- for (int i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
const QPostEvent &pe = data->postEventList.at(i);
if ((!receiver || pe.receiver == receiver)
&& (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
--pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
+ pe.event->m_posted = false;
events.append(pe.event);
const_cast<QPostEvent &>(pe).event = nullptr;
} else if (!data->postEventList.recursion) {
@@ -1918,7 +2040,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
{
- if (!event || !event->posted)
+ if (!event || !event->m_posted)
return;
QThreadData *data = QThreadData::current();
@@ -1933,8 +2055,7 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
#endif
}
- for (int i = 0; i < data->postEventList.size(); ++i) {
- const QPostEvent & pe = data->postEventList.at(i);
+ for (const QPostEvent &pe : std::as_const(data->postEventList)) {
if (pe.event == event) {
#ifndef QT_NO_DEBUG
qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
@@ -1943,7 +2064,7 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
pe.receiver->objectName().toLocal8Bit().data());
#endif
--pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
+ pe.event->m_posted = false;
delete pe.event;
const_cast<QPostEvent &>(pe).event = nullptr;
return;
@@ -1957,27 +2078,12 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
bool QCoreApplication::event(QEvent *e)
{
if (e->type() == QEvent::Quit) {
- quit();
+ exit(0);
return true;
}
return QObject::event(e);
}
-/*! \enum QCoreApplication::Encoding
- \obsolete
-
- This enum type used to define the 8-bit encoding of character string
- arguments to translate(). This enum is now obsolete and UTF-8 will be
- used in all cases.
-
- \value UnicodeUTF8 UTF-8.
- \omitvalue Latin1
- \omitvalue DefaultCodec \omit UTF-8. \endomit
- \omitvalue CodecForTr
-
- \sa QObject::tr(), QString::fromUtf8()
-*/
-
void QCoreApplicationPrivate::ref()
{
quitLockRef.ref();
@@ -1985,23 +2091,57 @@ void QCoreApplicationPrivate::ref()
void QCoreApplicationPrivate::deref()
{
- if (!quitLockRef.deref())
- maybeQuit();
+ quitLockRef.deref();
+
+ if (quitLockEnabled && canQuitAutomatically())
+ quitAutomatically();
+}
+
+bool QCoreApplicationPrivate::canQuitAutomatically()
+{
+ if (!in_exec)
+ return false;
+
+ // The automatic quit functionality is triggered by
+ // both QEventLoopLocker and maybeLastWindowClosed.
+ // In either case, we don't want to quit if there
+ // are active QEventLoopLockers, even if quitLockEnabled
+ // is not enabled, as the property signals whether to
+ // trigger the automatic quit, not whether to block it.
+ if (quitLockRef.loadRelaxed())
+ return false;
+
+ return true;
}
-void QCoreApplicationPrivate::maybeQuit()
+void QCoreApplicationPrivate::quitAutomatically()
{
- if (quitLockRef.loadRelaxed() == 0 && in_exec && quitLockRefEnabled && shouldQuit())
- QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::Quit));
+ Q_Q(QCoreApplication);
+
+ // Explicit requests by the user to quit() is plumbed via the platform
+ // if possible, and delivers the quit event synchronously. For automatic
+ // quits we implicitly support cancelling the quit by showing another
+ // window, which currently relies on removing any posted quit events
+ // from the event queue. As a result, we can't use the normal quit()
+ // code path, and need to post manually.
+ QCoreApplication::postEvent(q, new QEvent(QEvent::Quit));
}
/*!
- Tells the application to exit with return code 0 (success).
- Equivalent to calling QCoreApplication::exit(0).
+ \threadsafe
+
+ Asks the application to quit.
+
+ The request may be ignored if the application prevents the quit,
+ for example if one of its windows can't be closed. The application
+ can affect this by handling the QEvent::Quit event on the application
+ level, or QEvent::Close events for the individual windows.
+
+ If the quit is not interrupted the application will exit with return
+ code 0 (success).
- It's common to connect the QGuiApplication::lastWindowClosed() signal
- to quit(), and you also often connect e.g. QAbstractButton::clicked() or
- signals in QAction, QMenu, or QMenuBar to it.
+ To exit the application without a chance of being interrupted, call
+ exit() directly. Note that method is not thread-safe.
It's good practice to always connect signals to this slot using a
\l{Qt::}{QueuedConnection}. If a signal connected (non-queued) to this slot
@@ -2014,12 +2154,34 @@ void QCoreApplicationPrivate::maybeQuit()
\snippet code/src_corelib_kernel_qcoreapplication.cpp 1
- \sa exit(), aboutToQuit(), QGuiApplication::lastWindowClosed()
-*/
+ \b{Thread-safety note}: this function may be called from any thread to
+ thread-safely cause the currently-running main application loop to exit.
+ However, thread-safety is not guaranteed if the QCoreApplication object is
+ being destroyed at the same time.
+ \sa exit(), aboutToQuit()
+*/
void QCoreApplication::quit()
{
- exit(0);
+ if (!self)
+ return;
+
+ if (!self->d_func()->in_exec)
+ return;
+
+ self->d_func()->quit();
+}
+
+void QCoreApplicationPrivate::quit()
+{
+ Q_Q(QCoreApplication);
+
+ if (QThread::currentThread() == mainThread()) {
+ QEvent quitEvent(QEvent::Quit);
+ QCoreApplication::sendEvent(q, &quitEvent);
+ } else {
+ QCoreApplication::postEvent(q, new QEvent(QEvent::Quit));
+ }
}
/*!
@@ -2034,6 +2196,12 @@ void QCoreApplication::quit()
last-second cleanup. Note that no user interaction is possible in
this state.
+ \note At this point the main event loop is still running, but will
+ not process further events on return except QEvent::DeferredDelete
+ events for objects deleted via deleteLater(). If event processing is
+ needed, use a nested event loop or call QCoreApplication::processEvents()
+ manually.
+
\sa quit()
*/
@@ -2057,12 +2225,15 @@ void QCoreApplication::quit()
to all toplevel widgets, where a reimplementation of changeEvent can
re-translate the user interface by passing user-visible strings via the
tr() function to the respective property setters. User-interface classes
- generated by Qt Designer provide a \c retranslateUi() function that can be
+ generated by \QD provide a \c retranslateUi() function that can be
called.
The function returns \c true on success and false on failure.
- \sa removeTranslator(), translate(), QTranslator::load(), {Dynamic Translation}
+ \note QCoreApplication does \e not take ownership of \a translationFile.
+
+ \sa removeTranslator(), translate(), QTranslator::load(),
+ {Writing Source Code for Translation#Prepare for Dynamic Language Changes}{Prepare for Dynamic Language Changes}
*/
bool QCoreApplication::installTranslator(QTranslator *translationFile)
@@ -2125,26 +2296,26 @@ bool QCoreApplication::removeTranslator(QTranslator *translationFile)
static void replacePercentN(QString *result, int n)
{
if (n >= 0) {
- int percentPos = 0;
- int len = 0;
- while ((percentPos = result->indexOf(QLatin1Char('%'), percentPos + len)) != -1) {
+ qsizetype percentPos = 0;
+ qsizetype len = 0;
+ while ((percentPos = result->indexOf(u'%', percentPos + len)) != -1) {
len = 1;
- if (percentPos + len == result->length())
+ if (percentPos + len == result->size())
break;
QString fmt;
- if (result->at(percentPos + len) == QLatin1Char('L')) {
+ if (result->at(percentPos + len) == u'L') {
++len;
- if (percentPos + len == result->length())
+ if (percentPos + len == result->size())
break;
- fmt = QLatin1String("%L1");
+ fmt = "%L1"_L1;
} else {
- fmt = QLatin1String("%1");
+ fmt = "%1"_L1;
}
- if (result->at(percentPos + len) == QLatin1Char('n')) {
+ if (result->at(percentPos + len) == u'n') {
fmt = fmt.arg(n);
++len;
result->replace(percentPos, len, fmt);
- len = fmt.length();
+ len = fmt.size();
}
}
}
@@ -2180,7 +2351,8 @@ static void replacePercentN(QString *result, int n)
This function is not virtual. You can use alternative translation
techniques by subclassing \l QTranslator.
- \sa QObject::tr(), installTranslator(), removeTranslator(), translate()
+ \sa QObject::tr(), installTranslator(), removeTranslator(),
+ {Internationalization and Translations}
*/
QString QCoreApplication::translate(const char *context, const char *sourceText,
const char *disambiguation, int n)
@@ -2212,11 +2384,6 @@ QString QCoreApplication::translate(const char *context, const char *sourceText,
return result;
}
-/*! \fn static QString QCoreApplication::translate(const char *context, const char *key, const char *disambiguation, Encoding encoding, int n = -1)
-
- \obsolete
-*/
-
// Declared in qglobal.h
QString qtTrId(const char *id, int n)
{
@@ -2237,11 +2404,11 @@ bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
QString QCoreApplication::translate(const char *context, const char *sourceText,
const char *disambiguation, int n)
{
- Q_UNUSED(context)
- Q_UNUSED(disambiguation)
+ Q_UNUSED(context);
+ Q_UNUSED(disambiguation);
QString ret = QString::fromUtf8(sourceText);
if (n >= 0)
- ret.replace(QLatin1String("%n"), QString::number(n));
+ ret.replace("%n"_L1, QString::number(n));
return ret;
}
@@ -2293,6 +2460,30 @@ QString QCoreApplication::applicationDirPath()
return d->cachedApplicationDirPath;
}
+#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) // qcoreapplication_win.cpp or qcoreapplication_mac.cpp
+static QString qAppFileName()
+{
+# if defined(Q_OS_ANDROID)
+ // the actual process on Android is the Java VM, so this doesn't help us
+ return QString();
+# elif defined(Q_OS_LINUX)
+ // this includes the Embedded Android builds
+ return QFile::decodeName(qt_readlink("/proc/self/exe"));
+# elif defined(AT_EXECPATH)
+ // seen on FreeBSD, but I suppose the other BSDs could adopt this API
+ char execfn[PATH_MAX];
+ if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0)
+ execfn[0] = '\0';
+
+ qsizetype len = qstrlen(execfn);
+ return QFile::decodeName(QByteArray::fromRawData(execfn, len));
+# else
+ // other OS or something
+ return QString();
+#endif
+}
+#endif
+
/*!
Returns the file path of the application executable.
@@ -2319,50 +2510,27 @@ QString QCoreApplication::applicationFilePath()
if (d->argc) {
static QByteArray procName = QByteArray(d->argv[0]);
- if (procName != d->argv[0]) {
+ if (procName != QByteArrayView(d->argv[0])) {
// clear the cache if the procname changes, so we reprocess it.
QCoreApplicationPrivate::clearApplicationFilePath();
- procName = QByteArray(d->argv[0]);
+ procName.assign(d->argv[0]);
}
}
if (QCoreApplicationPrivate::cachedApplicationFilePath)
return *QCoreApplicationPrivate::cachedApplicationFilePath;
-#if defined(Q_OS_WIN)
- QCoreApplicationPrivate::setApplicationFilePath(QFileInfo(qAppFileName()).filePath());
- return *QCoreApplicationPrivate::cachedApplicationFilePath;
-#elif defined(Q_OS_MAC)
- QString qAppFileName_str = qAppFileName();
- if(!qAppFileName_str.isEmpty()) {
- QFileInfo fi(qAppFileName_str);
- if (fi.exists()) {
- QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath());
- return *QCoreApplicationPrivate::cachedApplicationFilePath;
- }
- }
-#endif
-#if defined( Q_OS_UNIX )
-# if defined(Q_OS_LINUX) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED))
- // Try looking for a /proc/<pid>/exe symlink first which points to
- // the absolute path of the executable
- QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid()));
- if (pfi.exists() && pfi.isSymLink()) {
- QCoreApplicationPrivate::setApplicationFilePath(pfi.canonicalFilePath());
- return *QCoreApplicationPrivate::cachedApplicationFilePath;
- }
-# endif
- if (!arguments().isEmpty()) {
+ QString absPath = qAppFileName();
+ if (absPath.isEmpty() && !arguments().isEmpty()) {
QString argv0 = QFile::decodeName(arguments().at(0).toLocal8Bit());
- QString absPath;
- if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
+ if (!argv0.isEmpty() && argv0.at(0) == u'/') {
/*
If argv0 starts with a slash, it is already an absolute
file path.
*/
absPath = argv0;
- } else if (argv0.contains(QLatin1Char('/'))) {
+ } else if (argv0.contains(u'/')) {
/*
If argv0 contains one or more slashes, it is a file path
relative to the current directory.
@@ -2375,17 +2543,13 @@ QString QCoreApplication::applicationFilePath()
*/
absPath = QStandardPaths::findExecutable(argv0);
}
-
- absPath = QDir::cleanPath(absPath);
-
- QFileInfo fi(absPath);
- if (fi.exists()) {
- QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath());
- return *QCoreApplicationPrivate::cachedApplicationFilePath;
- }
}
-#endif
+ absPath = QFileInfo(absPath).canonicalFilePath();
+ if (!absPath.isEmpty()) {
+ QCoreApplicationPrivate::setApplicationFilePath(absPath);
+ return *QCoreApplicationPrivate::cachedApplicationFilePath;
+ }
return QString();
}
@@ -2429,7 +2593,7 @@ qint64 QCoreApplication::applicationPid()
encoding problems might occur.
Otherwise, the arguments() are constructed from the return value of
- \l{http://msdn2.microsoft.com/en-us/library/ms683156(VS.85).aspx}{GetCommandLine()}.
+ \l{https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea}{GetCommandLine()}.
As a result of this, the string given by arguments().at(0) might not be
the program name on Windows, depending on how the application was started.
@@ -2444,32 +2608,46 @@ QStringList QCoreApplication::arguments()
qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
return list;
}
- const int ac = self->d_func()->argc;
- char ** const av = self->d_func()->argv;
- list.reserve(ac);
-
-#if defined(Q_OS_WIN)
- // On Windows, it is possible to pass Unicode arguments on
- // the command line. To restore those, we split the command line
- // and filter out arguments that were deleted by derived application
- // classes by index.
- QString cmdline = QString::fromWCharArray(GetCommandLine());
const QCoreApplicationPrivate *d = self->d_func();
- if (d->origArgv) {
- const QStringList allArguments = qWinCmdArgs(cmdline);
- Q_ASSERT(allArguments.size() == d->origArgc);
- for (int i = 0; i < d->origArgc; ++i) {
- if (contains(ac, av, d->origArgv[i]))
- list.append(allArguments.at(i));
+
+ const int argc = d->argc;
+ char ** const argv = d->argv;
+ list.reserve(argc);
+
+#if defined(Q_OS_WIN)
+ const bool argsModifiedByUser = d->origArgv == nullptr;
+ if (!argsModifiedByUser) {
+ // On Windows, it is possible to pass Unicode arguments on
+ // the command line, but we don't implement any of the wide
+ // entry-points (wmain/wWinMain), so get the arguments from
+ // the Windows API instead of using argv. Note that we only
+ // do this when argv were not modified by the user in main().
+ QString cmdline = QString::fromWCharArray(GetCommandLine());
+ QStringList commandLineArguments = qWinCmdArgs(cmdline);
+
+ // Even if the user didn't modify argv before passing them
+ // on to QCoreApplication, derived QApplications might have.
+ // If that's the case argc will differ from origArgc.
+ if (argc != d->origArgc) {
+ // Note: On MingGW the arguments from GetCommandLine are
+ // not wildcard expanded (if wildcard expansion is enabled),
+ // as opposed to the arguments in argv. This means we can't
+ // compare commandLineArguments to argv/origArgc, but
+ // must remove elements by value, based on whether they
+ // were filtered out from argc.
+ for (int i = 0; i < d->origArgc; ++i) {
+ if (!contains(argc, argv, d->origArgv[i]))
+ commandLineArguments.removeAll(QString::fromLocal8Bit(d->origArgv[i]));
+ }
}
- return list;
+
+ return commandLineArguments;
} // Fall back to rebuilding from argv/argc when a modified argv was passed.
#endif // defined(Q_OS_WIN)
- for (int a = 0; a < ac; ++a) {
- list << QString::fromLocal8Bit(av[a]);
- }
+ for (int a = 0; a < argc; ++a)
+ list << QString::fromLocal8Bit(argv[a]);
return list;
}
@@ -2479,7 +2657,7 @@ QStringList QCoreApplication::arguments()
\brief the name of the organization that wrote this application
The value is used by the QSettings class when it is constructed
- using the empty constructor. This saves having to repeat this
+ using the default constructor. This saves having to repeat this
information each time a QSettings object is created.
On Mac, QSettings uses \l {QCoreApplication::}{organizationDomain()} as the organization
@@ -2519,7 +2697,7 @@ QString QCoreApplication::organizationName()
\brief the Internet domain of the organization that wrote this application
The value is used by the QSettings class when it is constructed
- using the empty constructor. This saves having to repeat this
+ using the default constructor. This saves having to repeat this
information each time a QSettings object is created.
On Mac, QSettings uses organizationDomain() as the organization
@@ -2555,11 +2733,15 @@ QString QCoreApplication::organizationDomain()
\property QCoreApplication::applicationName
\brief the name of this application
- The value is used by the QSettings class when it is constructed
- using the empty constructor. This saves having to repeat this
- information each time a QSettings object is created.
+ The application name is used in various Qt classes and modules,
+ most prominently in \l{QSettings} when it is constructed using the default constructor.
+ Other uses are in formatted logging output (see \l{qSetMessagePattern()}),
+ in output by \l{QCommandLineParser}, in \l{QTemporaryDir} and \l{QTemporaryFile}
+ default paths, and in some file locations of \l{QStandardPaths}.
+ \l{Qt D-Bus}, \l{Accessibility}, and the XCB platform integration make use
+ of the application name, too.
- If not set, the application name defaults to the executable name (since 5.0).
+ If not set, the application name defaults to the executable name.
\sa organizationName, organizationDomain, applicationVersion, applicationFilePath()
*/
@@ -2642,6 +2824,155 @@ QString QCoreApplication::applicationVersion()
return coreappdata() ? coreappdata()->applicationVersion : QString();
}
+#if QT_CONFIG(permissions) || defined(Q_QDOC)
+
+/*!
+ Checks the status of the given \a permission
+
+ If the result is Qt::PermissionStatus::Undetermined then permission should be
+ requested via requestPermission() to determine the user's intent.
+
+ \since 6.5
+ \sa requestPermission(), {Application Permissions}
+*/
+Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permission)
+{
+ return QPermissions::Private::checkPermission(permission);
+}
+
+/*!
+ \fn template <typename Functor> void QCoreApplication::requestPermission(
+ const QPermission &permission, Functor &&functor)
+
+ Requests the given \a permission.
+
+ \include permissions.qdocinc requestPermission-functor
+
+ The \a functor can be a free-standing or static member function:
+
+ \code
+ qApp->requestPermission(QCameraPermission{}, &permissionUpdated);
+ \endcode
+
+ or a lambda:
+
+ \code
+ qApp->requestPermission(QCameraPermission{}, [](const QPermission &permission) {
+ });
+ \endcode
+
+ \include permissions.qdocinc requestPermission-postamble
+
+ \since 6.5
+ \sa checkPermission(), {Application Permissions}
+*/
+
+/*!
+ \fn template<typename Functor> void QCoreApplication::requestPermission(
+ const QPermission &permission, const QObject *context,
+ Functor functor)
+
+ Requests the given \a permission, in the context of \a context.
+
+ \include permissions.qdocinc requestPermission-functor
+
+ The \a functor can be a free-standing or static member function:
+
+ \code
+ qApp->requestPermission(QCameraPermission{}, context, &permissionUpdated);
+ \endcode
+
+ a lambda:
+
+ \code
+ qApp->requestPermission(QCameraPermission{}, context, [](const QPermission &permission) {
+ });
+ \endcode
+
+ or a slot in the \a context object:
+
+ \code
+ qApp->requestPermission(QCameraPermission{}, this, &CamerWidget::permissionUpdated);
+ \endcode
+
+ The \a functor will be called in the thread of the \a context object. If
+ \a context is destroyed before the request completes, the \a functor will
+ not be called.
+
+ \include permissions.qdocinc requestPermission-postamble
+
+ \since 6.5
+ \overload
+ \sa checkPermission(), {Application Permissions}
+*/
+
+/*!
+ \internal
+
+ Called by the various requestPermission overloads to perform the request.
+
+ Calls the functor encapsulated in the \a slotObjRaw in the given \a context
+ (which may be \c nullptr).
+*/
+void QCoreApplication::requestPermission(const QPermission &requestedPermission,
+ QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context)
+{
+ QtPrivate::SlotObjUniquePtr slotObj{slotObjRaw}; // adopts
+ Q_ASSERT(slotObj);
+
+ if (QThread::currentThread() != QCoreApplicationPrivate::mainThread()) {
+ qWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
+ return;
+ }
+
+ class PermissionReceiver : public QObject
+ {
+ public:
+ explicit PermissionReceiver(QtPrivate::SlotObjUniquePtr &&slotObject, const QObject *context)
+ : slotObject(std::move(slotObject)), context(context ? context : this)
+ {
+ Q_ASSERT(this->context);
+ moveToThread(this->context->thread());
+ }
+
+ void finalizePermissionRequest(const QPermission &permission)
+ {
+ Q_ASSERT(slotObject);
+ // only execute if context object is still alive
+ if (context) {
+ void *args[] = { nullptr, const_cast<QPermission *>(&permission) };
+ slotObject->call(const_cast<QObject *>(context.data()), args);
+ }
+ deleteLater();
+ }
+
+ private:
+ QtPrivate::SlotObjSharedPtr slotObject;
+ QPointer<const QObject> context;
+ };
+
+ PermissionReceiver *receiver = new PermissionReceiver(std::move(slotObj), context);
+
+ QPermissions::Private::requestPermission(requestedPermission, [=](Qt::PermissionStatus status) {
+ if (status == Qt::PermissionStatus::Undetermined) {
+ Q_ASSERT_X(false, "QPermission",
+ "Internal error: requestPermission() should never return Undetermined");
+ status = Qt::PermissionStatus::Denied;
+ }
+
+ if (QCoreApplication::self) {
+ QPermission permission = requestedPermission;
+ permission.m_status = status;
+ QMetaObject::invokeMethod(receiver,
+ &PermissionReceiver::finalizePermissionRequest,
+ Qt::QueuedConnection,
+ permission);
+ }
+ });
+}
+
+#endif // QT_CONFIG(permissions)
+
#if QT_CONFIG(library)
Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex)
@@ -2672,11 +3003,6 @@ Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex)
directory (and its existence) may change when the directory of
the application executable becomes known.
- If you want to iterate over the list, you can use the \l foreach
- pseudo-keyword:
-
- \snippet code/src_corelib_kernel_qcoreapplication.cpp 2
-
\sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary,
{How to Create Qt Plugins}
*/
@@ -2711,9 +3037,6 @@ QStringList QCoreApplication::libraryPathsLocked()
}
};
setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
-#ifdef Q_OS_ANDROID
- setPathsFromEnv(qEnvironmentVariable("QT_BUNDLED_LIBS_PATH"));
-#endif
#ifdef Q_OS_DARWIN
// Check the main bundle's PlugIns directory as this is a standard location for Apple OSes.
// Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value
@@ -2734,7 +3057,7 @@ QStringList QCoreApplication::libraryPathsLocked()
}
#endif // Q_OS_DARWIN
- QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ QString installPathPlugins = QLibraryInfo::path(QLibraryInfo::PluginsPath);
if (QFile::exists(installPathPlugins)) {
// Make sure we convert from backslashes to slashes.
installPathPlugins = QDir(installPathPlugins).canonicalPath();
@@ -2753,9 +3076,10 @@ QStringList QCoreApplication::libraryPathsLocked()
/*!
- Sets the list of directories to search when loading libraries to
- \a paths. All existing paths will be deleted and the path list
- will consist of the paths given in \a paths.
+ Sets the list of directories to search when loading plugins with
+ QLibrary to \a paths. All existing paths will be deleted and the
+ path list will consist of the paths given in \a paths and the path
+ to the application.
The library paths are reset to the default when an instance of
QCoreApplication is destructed.
@@ -2786,10 +3110,11 @@ void QCoreApplication::setLibraryPaths(const QStringList &paths)
it is searched for libraries first. If \a path is empty or already in the
path list, the path list is not changed.
- The default path list consists of a single entry, the installation
- directory for plugins. The default installation directory for plugins
- is \c INSTALL/plugins, where \c INSTALL is the directory where Qt was
- installed.
+ The default path list consists of one or two entries. The first is the
+ installation directory for plugins, which is \c INSTALL/plugins, where \c
+ INSTALL is the directory where Qt was installed. The second is the
+ application's own directory (\b not the current directory), but only after
+ the QCoreApplication object is instantiated.
The library paths are reset to the default when an instance of
QCoreApplication is destructed.
@@ -2807,14 +3132,14 @@ void QCoreApplication::addLibraryPath(const QString &path)
QMutexLocker locker(libraryPathMutex());
- QStringList *libpaths = coreappdata()->manual_libpaths.data();
+ QStringList *libpaths = coreappdata()->manual_libpaths.get();
if (libpaths) {
if (libpaths->contains(canonicalPath))
return;
} else {
// make sure that library paths are initialized
libraryPathsLocked();
- QStringList *app_libpaths = coreappdata()->app_libpaths.data();
+ QStringList *app_libpaths = coreappdata()->app_libpaths.get();
if (app_libpaths->contains(canonicalPath))
return;
@@ -2846,14 +3171,14 @@ void QCoreApplication::removeLibraryPath(const QString &path)
QMutexLocker locker(libraryPathMutex());
- QStringList *libpaths = coreappdata()->manual_libpaths.data();
+ QStringList *libpaths = coreappdata()->manual_libpaths.get();
if (libpaths) {
if (libpaths->removeAll(canonicalPath) == 0)
return;
} else {
// make sure that library paths is initialized
libraryPathsLocked();
- QStringList *app_libpaths = coreappdata()->app_libpaths.data();
+ QStringList *app_libpaths = coreappdata()->app_libpaths.get();
if (!app_libpaths->contains(canonicalPath))
return;
@@ -2926,36 +3251,13 @@ void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filt
*/
void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObject)
{
- QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
if (!filterObject || !eventDispatcher)
return;
eventDispatcher->removeNativeEventFilter(filterObject);
}
/*!
- \deprecated
-
- This function returns \c true if there are pending events; otherwise
- returns \c false. Pending events can be either from the window
- system or posted events using postEvent().
-
- \note this function is not thread-safe. It may only be called in the main
- thread and only if there are no other threads running in the application
- (including threads Qt starts for its own purposes).
-
- \sa QAbstractEventDispatcher::hasPendingEvents()
-*/
-#if QT_DEPRECATED_SINCE(5, 3)
-bool QCoreApplication::hasPendingEvents()
-{
- QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (eventDispatcher)
- return eventDispatcher->hasPendingEvents();
- return false;
-}
-#endif
-
-/*!
Returns a pointer to the event dispatcher object for the main thread. If no
event dispatcher exists for the thread, this function returns \nullptr.
*/
@@ -3071,14 +3373,13 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
\macro Q_DECLARE_TR_FUNCTIONS(context)
\relates QCoreApplication
- The Q_DECLARE_TR_FUNCTIONS() macro declares and implements two
- translation functions, \c tr() and \c trUtf8(), with these
- signatures:
+ The Q_DECLARE_TR_FUNCTIONS() macro declares and implements the
+ translation function \c tr() with this signature:
\snippet code/src_corelib_kernel_qcoreapplication.cpp 6
- This macro is useful if you want to use QObject::tr() or
- QObject::trUtf8() in classes that don't inherit from QObject.
+ This macro is useful if you want to use QObject::tr() in classes
+ that don't inherit from QObject.
Q_DECLARE_TR_FUNCTIONS() must appear at the very top of the
class definition (before the first \c{public:} or \c{protected:}).
@@ -3089,9 +3390,15 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
The \a context parameter is normally the class name, but it can
be any text.
- \sa Q_OBJECT, QObject::tr(), QObject::trUtf8()
+ \sa Q_OBJECT, QObject::tr()
*/
+void *QCoreApplication::resolveInterface(const char *name, int revision) const
+{
+ Q_UNUSED(name); Q_UNUSED(revision);
+ return nullptr;
+}
+
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 057a0bc65b..0078dc3295 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOREAPPLICATION_H
#define QCOREAPPLICATION_H
@@ -43,12 +7,17 @@
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#ifndef QT_NO_QOBJECT
-#include <QtCore/qobject.h>
#include <QtCore/qcoreevent.h>
+#include <QtCore/qdeadlinetimer.h>
#include <QtCore/qeventloop.h>
+#include <QtCore/qobject.h>
#else
#include <QtCore/qscopedpointer.h>
#endif
+#include <QtCore/qnativeinterface.h>
+#ifndef QT_NO_DEBUGSTREAM
+#include <QtCore/qdebug.h>
+#endif
#ifndef QT_NO_QOBJECT
#if defined(Q_OS_WIN) && !defined(tagMSG)
@@ -62,9 +31,13 @@ QT_BEGIN_NAMESPACE
class QCoreApplicationPrivate;
class QTranslator;
class QPostEventList;
-class QStringList;
class QAbstractEventDispatcher;
class QAbstractNativeEventFilter;
+class QEventLoopLocker;
+
+#if QT_CONFIG(permissions) || defined(Q_QDOC)
+class QPermission;
+#endif
#define qApp QCoreApplication::instance()
@@ -75,14 +48,23 @@ class Q_CORE_EXPORT QCoreApplication
{
#ifndef QT_NO_QOBJECT
Q_OBJECT
- Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName NOTIFY applicationNameChanged)
- Q_PROPERTY(QString applicationVersion READ applicationVersion WRITE setApplicationVersion NOTIFY applicationVersionChanged)
- Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName NOTIFY organizationNameChanged)
- Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain NOTIFY organizationDomainChanged)
+ Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName
+ NOTIFY applicationNameChanged)
+ Q_PROPERTY(QString applicationVersion READ applicationVersion WRITE setApplicationVersion
+ NOTIFY applicationVersionChanged)
+ Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName
+ NOTIFY organizationNameChanged)
+ Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain
+ NOTIFY organizationDomainChanged)
Q_PROPERTY(bool quitLockEnabled READ isQuitLockEnabled WRITE setQuitLockEnabled)
#endif
Q_DECLARE_PRIVATE(QCoreApplication)
+ friend class QEventLoopLocker;
+#if QT_CONFIG(permissions)
+ using RequestPermissionPrototype = void(*)(QPermission);
+#endif
+
public:
enum { ApplicationFlags = QT_VERSION
};
@@ -112,21 +94,18 @@ public:
static void setSetuidAllowed(bool allow);
static bool isSetuidAllowed();
- static QCoreApplication *instance() { return self; }
+ static QCoreApplication *instance() noexcept { return self; }
#ifndef QT_NO_QOBJECT
static int exec();
static void processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
static void processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime);
- static void exit(int retcode=0);
+ static void processEvents(QEventLoop::ProcessEventsFlags flags, QDeadlineTimer deadline);
static bool sendEvent(QObject *receiver, QEvent *event);
static void postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority);
static void sendPostedEvents(QObject *receiver = nullptr, int event_type = 0);
static void removePostedEvents(QObject *receiver, int eventType = 0);
-#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED static bool hasPendingEvents();
-#endif
static QAbstractEventDispatcher *eventDispatcher();
static void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
@@ -140,6 +119,53 @@ public:
static QString applicationFilePath();
static qint64 applicationPid() Q_DECL_CONST_FUNCTION;
+#if QT_CONFIG(permissions) || defined(Q_QDOC)
+ Qt::PermissionStatus checkPermission(const QPermission &permission);
+
+# ifdef Q_QDOC
+ template <typename Functor>
+ void requestPermission(const QPermission &permission, const QObject *context, Functor functor);
+# else
+ // requestPermission with context or receiver object; need to require here that receiver is the
+ // right type to avoid ambiguity with the private implementation function.
+ template <typename Functor,
+ std::enable_if_t<
+ QtPrivate::AreFunctionsCompatible<RequestPermissionPrototype, Functor>::value,
+ bool> = true>
+ void requestPermission(const QPermission &permission,
+ const typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType *receiver,
+ Functor &&func)
+ {
+ requestPermission(permission,
+ QtPrivate::makeCallableObject<RequestPermissionPrototype>(std::forward<Functor>(func)),
+ receiver);
+ }
+# endif // Q_QDOC
+
+#ifndef QT_NO_CONTEXTLESS_CONNECT
+ #ifdef Q_QDOC
+ template <typename Functor>
+ #else
+ // requestPermission to a functor or function pointer (without context)
+ template <typename Functor,
+ std::enable_if_t<
+ QtPrivate::AreFunctionsCompatible<RequestPermissionPrototype, Functor>::value,
+ bool> = true>
+ #endif
+ void requestPermission(const QPermission &permission, Functor &&func)
+ {
+ requestPermission(permission, nullptr, std::forward<Functor>(func));
+ }
+#endif // QT_NO_CONTEXTLESS_CONNECT
+
+private:
+ // ### Qt 7: rename to requestPermissionImpl to avoid ambiguity
+ void requestPermission(const QPermission &permission,
+ QtPrivate::QSlotObjectBase *slotObj, const QObject *context);
+public:
+
+#endif // QT_CONFIG(permission)
+
#if QT_CONFIG(library)
static void setLibraryPaths(const QStringList &);
static QStringList libraryPaths();
@@ -156,18 +182,10 @@ public:
const char * key,
const char * disambiguation = nullptr,
int n = -1);
-#if QT_DEPRECATED_SINCE(5, 0)
- enum Encoding { UnicodeUTF8, Latin1, DefaultCodec = UnicodeUTF8, CodecForTr = UnicodeUTF8 };
- QT_DEPRECATED static inline QString translate(const char * context, const char * key,
- const char * disambiguation, Encoding, int n = -1)
- { return translate(context, key, disambiguation, n); }
-#endif
-#ifndef QT_NO_QOBJECT
-# if QT_DEPRECATED_SINCE(5, 9)
- QT_DEPRECATED static void flush();
-# endif
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(QCoreApplication)
+#ifndef QT_NO_QOBJECT
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj);
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj);
@@ -176,6 +194,7 @@ public:
public Q_SLOTS:
static void quit();
+ static void exit(int retcode = 0);
Q_SIGNALS:
void aboutToQuit(QPrivateSignal);
@@ -201,9 +220,6 @@ protected:
private:
#ifndef QT_NO_QOBJECT
static bool sendSpontaneousEvent(QObject *receiver, QEvent *event);
-# if QT_DEPRECATED_SINCE(5,6)
- QT_DEPRECATED bool notifyInternal(QObject *receiver, QEvent *event); // ### Qt6 BIC: remove me
-# endif
static bool notifyInternal2(QObject *receiver, QEvent *);
static bool forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent = nullptr);
#endif
@@ -225,26 +241,16 @@ private:
#ifndef QT_NO_QOBJECT
friend class QEventDispatcherUNIXPrivate;
friend class QCocoaEventDispatcherPrivate;
- friend bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+ friend bool qt_sendSpontaneousEvent(QObject *, QEvent *);
#endif
friend Q_CORE_EXPORT QString qAppName();
- friend class QClassFactory;
friend class QCommandLineParserPrivate;
};
-#ifdef QT_NO_DEPRECATED
-# define QT_DECLARE_DEPRECATED_TR_FUNCTIONS(context)
-#else
-# define QT_DECLARE_DEPRECATED_TR_FUNCTIONS(context) \
- QT_DEPRECATED static inline QString trUtf8(const char *sourceText, const char *disambiguation = nullptr, int n = -1) \
- { return QCoreApplication::translate(#context, sourceText, disambiguation, n); }
-#endif
-
#define Q_DECLARE_TR_FUNCTIONS(context) \
public: \
static inline QString tr(const char *sourceText, const char *disambiguation = nullptr, int n = -1) \
{ return QCoreApplication::translate(#context, sourceText, disambiguation, n); } \
- QT_DECLARE_DEPRECATED_TR_FUNCTIONS(context) \
private:
typedef void (*QtStartUpFunction)();
@@ -270,4 +276,6 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const MSG &);
QT_END_NAMESPACE
+#include <QtCore/qcoreapplication_platform.h>
+
#endif // QCOREAPPLICATION_H
diff --git a/src/corelib/kernel/qcoreapplication_mac.cpp b/src/corelib/kernel/qcoreapplication_mac.cpp
index 7fb52708e1..af047fe8cd 100644
--- a/src/corelib/kernel/qcoreapplication_mac.cpp
+++ b/src/corelib/kernel/qcoreapplication_mac.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoreapplication.h"
#include "private/qcoreapplication_p.h"
@@ -51,14 +15,13 @@ QString qAppFileName()
static QString appFileName;
if (appFileName.isEmpty()) {
QCFType<CFURLRef> bundleURL(CFBundleCopyExecutableURL(CFBundleGetMainBundle()));
- if(bundleURL) {
+ if (bundleURL) {
QCFString cfPath(CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle));
- if(cfPath)
+ if (cfPath)
appFileName = cfPath;
}
}
return appFileName;
}
-
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index cb3a5a8a4f..bfd65d2c9a 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOREAPPLICATION_P_H
#define QCOREAPPLICATION_P_H
@@ -55,11 +19,13 @@
#if QT_CONFIG(commandlineparser)
#include "QtCore/qcommandlineoption.h"
#endif
+#include "QtCore/qreadwritelock.h"
#include "QtCore/qtranslator.h"
#if QT_CONFIG(settings)
#include "QtCore/qsettings.h"
#endif
#ifndef QT_NO_QOBJECT
+#include <qloggingcategory.h>
#include "private/qobject_p.h"
#include "private/qlocking_p.h"
#endif
@@ -70,10 +36,18 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_QOBJECT
+Q_DECLARE_LOGGING_CATEGORY(lcDeleteLater)
+#endif
+
typedef QList<QTranslator*> QTranslatorList;
class QAbstractEventDispatcher;
+#ifndef QT_NO_QOBJECT
+class QEvent;
+#endif
+
class Q_CORE_EXPORT QCoreApplicationPrivate
#ifndef QT_NO_QOBJECT
: public QObjectPrivate
@@ -87,7 +61,7 @@ public:
Gui
};
- QCoreApplicationPrivate(int &aargc, char **aargv, uint flags);
+ QCoreApplicationPrivate(int &aargc, char **aargv);
// If not inheriting from QObjectPrivate: force this class to be polymorphic
#ifdef QT_NO_QOBJECT
@@ -104,6 +78,7 @@ public:
static QString infoDictionaryStringProperty(const QString &propertyName);
#endif
+ void initConsole();
static void initLocale();
static bool checkInstance(const char *method);
@@ -116,7 +91,7 @@ public:
bool sendThroughApplicationEventFilters(QObject *, QEvent *);
static bool sendThroughObjectEventFilters(QObject *, QEvent *);
static bool notify_helper(QObject *, QEvent *);
- static inline void setEventSpontaneous(QEvent *e, bool spontaneous) { e->spont = spontaneous; }
+ static inline void setEventSpontaneous(QEvent *e, bool spontaneous) { e->m_spont = spontaneous; }
virtual void createEventDispatcher();
virtual void eventDispatcherReady();
@@ -128,12 +103,12 @@ public:
QAtomicInt quitLockRef;
void ref();
void deref();
- virtual bool shouldQuit() {
- return true;
- }
- void maybeQuit();
+ virtual bool canQuitAutomatically();
+ void quitAutomatically();
+ virtual void quit();
static QBasicAtomicPointer<QThread> theMainThread;
+ static QBasicAtomicPointer<void> theMainThreadId;
static QThread *mainThread();
static bool threadRequiresCoreApplication();
@@ -157,6 +132,7 @@ public:
#if defined(Q_OS_WIN)
int origArgc;
char **origArgv; // store unmodified arguments for QCoreApplication::arguments()
+ bool consoleAllocated = false;
#endif
void appendApplicationPathToLibraryPaths(void);
@@ -188,11 +164,10 @@ public:
static bool setuidAllowed;
static uint attribs;
static inline bool testAttribute(uint flag) { return attribs & (1 << flag); }
- static int app_compile_version;
void processCommandLineArguments();
QString qmljs_debug_arguments; // a string containing arguments for js/qml debugging.
- inline QString qmljsDebugArgumentsString() { return qmljs_debug_arguments; }
+ inline QString qmljsDebugArgumentsString() const { return qmljs_debug_arguments; }
#ifdef QT_NO_QOBJECT
QCoreApplication *q_ptr;
diff --git a/src/corelib/kernel/qcoreapplication_platform.h b/src/corelib/kernel/qcoreapplication_platform.h
new file mode 100644
index 0000000000..d5f266179e
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_platform.h
@@ -0,0 +1,73 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOREAPPLICATION_PLATFORM_H
+#define QCOREAPPLICATION_PLATFORM_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the native interface APIs. Usage of
+// this API may make your code source and binary incompatible
+// with future versions of Qt.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnativeinterface.h>
+#include <QtCore/qcoreapplication.h>
+
+#if defined(Q_OS_ANDROID) || defined(Q_QDOC)
+#include <QtCore/qjnitypes.h>
+#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
+#include <QtCore/qfuture.h>
+#include <QtCore/qvariant.h>
+#endif
+#endif // #if defined(Q_OS_ANDROID) || defined(Q_QDOC)
+
+#if defined(Q_OS_ANDROID)
+class _jobject;
+typedef _jobject* jobject;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_ANDROID)
+Q_DECLARE_JNI_CLASS(Context, "android/content/Context")
+#endif
+
+namespace QNativeInterface
+{
+#if defined(Q_OS_ANDROID) || defined(Q_QDOC)
+struct Q_CORE_EXPORT QAndroidApplication
+{
+ QT_DECLARE_NATIVE_INTERFACE(QAndroidApplication, 1, QCoreApplication)
+#ifdef Q_QDOC
+ static QJniObject context();
+#else
+ static QtJniTypes::Context context();
+#endif
+ static bool isActivityContext();
+ static int sdkVersion();
+ static void hideSplashScreen(int duration = 0);
+
+#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
+ static QFuture<QVariant> runOnAndroidMainThread(const std::function<QVariant()> &runnable,
+ const QDeadlineTimer timeout = QDeadlineTimer::Forever);
+
+ template <class T>
+ std::enable_if_t<std::is_invocable_v<T> && std::is_same_v<std::invoke_result_t<T>, void>,
+ QFuture<void>> static runOnAndroidMainThread(const T &runnable,
+ const QDeadlineTimer timeout = QDeadlineTimer::Forever)
+ {
+ std::function<QVariant()> func = [runnable](){ runnable(); return QVariant(); };
+ return static_cast<QFuture<void>>(runOnAndroidMainThread(func, timeout));
+ }
+#endif
+};
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QCOREAPPLICATION_PLATFORM_H
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 524dd5b25b..3a69bec25b 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
@@ -49,12 +13,15 @@
#include <private/qlocking_p.h>
#endif
#include "qtextstream.h"
+#include "qvarlengtharray.h"
#include <ctype.h>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT QString qAppFileName() // get application file name
+using namespace Qt::StringLiterals;
+
+QString qAppFileName() // get application file name
{
/*
GetModuleFileName() returns the length of the module name, when it has
@@ -120,28 +87,6 @@ QString QCoreApplicationPrivate::appVersion() const
return applicationVersion;
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle
-{
- return GetModuleHandle(0);
-}
-
-Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app handle
-{
- return 0;
-}
-
-Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command
-{
- STARTUPINFO startupInfo;
- GetStartupInfo(&startupInfo);
-
- return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
- ? startupInfo.wShowWindow
- : SW_SHOWDEFAULT;
-}
-#endif
-
#ifndef QT_NO_QOBJECT
#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
@@ -193,8 +138,8 @@ static QString flagsValue(const QWinMessageMapping<IntType> *haystack,
for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
if ((p->value & value) == p->value) {
if (!result.isEmpty())
- result += QLatin1String(" | ");
- result += QLatin1String(p->name);
+ result += " | "_L1;
+ result += QLatin1StringView(p->name);
}
}
return result;
@@ -685,8 +630,8 @@ QString decodeMSG(const MSG& msg)
// decoded message, since some of the common messages are quite long, and
// we don't want the decoded information to vary in output position
if (message.size() < 20)
- message.prepend(QString(20 - message.size(), QLatin1Char(' ')));
- message += QLatin1String(": ");
+ message.prepend(QString(20 - message.size(), u' '));
+ message += ": "_L1;
const QString hwndS = QString::asprintf("(%p)", reinterpret_cast<void *>(msg.hwnd));
const QString wParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(wParam));
@@ -696,11 +641,11 @@ QString decodeMSG(const MSG& msg)
switch (msg.message) {
case WM_ACTIVATE:
if (const char *a = activateParameter(uint(wParam)))
- parameters += QLatin1String(a);
- parameters += QLatin1String(" Hwnd ") + hwndS;
+ parameters += QLatin1StringView(a);
+ parameters += " Hwnd "_L1 + hwndS;
break;
case WM_CAPTURECHANGED:
- parameters = QLatin1String("Hwnd gaining capture ") + hwndS;
+ parameters = "Hwnd gaining capture "_L1 + hwndS;
break;
case WM_CREATE:
{
@@ -725,7 +670,7 @@ QString decodeMSG(const MSG& msg)
}
break;
case WM_DESTROY:
- parameters = QLatin1String("Destroy hwnd ") + hwndS;
+ parameters = "Destroy hwnd "_L1 + hwndS;
break;
case 0x02E0u: { // WM_DPICHANGED
auto rect = reinterpret_cast<const RECT *>(lParam);
@@ -736,20 +681,20 @@ QString decodeMSG(const MSG& msg)
break;
case WM_IME_NOTIFY:
{
- parameters = QLatin1String("Command(");
+ parameters = "Command("_L1;
if (const char *c = imeCommand(uint(wParam)))
- parameters += QLatin1String(c);
- parameters += QLatin1String(" : ") + lParamS;
+ parameters += QLatin1StringView(c);
+ parameters += " : "_L1 + lParamS;
}
break;
case WM_IME_SETCONTEXT:
- parameters = QLatin1String("Input context(")
- + QLatin1String(wParam == TRUE ? "Active" : "Inactive")
- + QLatin1String(") Show flags(")
- + imeShowFlags(DWORD(lParam)) + QLatin1Char(')');
+ parameters = "Input context("_L1
+ + (wParam ? "Active"_L1 : "Inactive"_L1)
+ + ") Show flags("_L1
+ + imeShowFlags(DWORD(lParam)) + u')';
break;
case WM_KILLFOCUS:
- parameters = QLatin1String("Hwnd gaining keyboard focus ") + wParamS;
+ parameters = "Hwnd gaining keyboard focus "_L1 + wParamS;
break;
case WM_CHAR:
case WM_IME_CHAR:
@@ -772,7 +717,7 @@ QString decodeMSG(const MSG& msg)
parameters = QStringLiteral("Keyboard layout changed");
break;
case WM_NCACTIVATE:
- parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
+ parameters = (msg.wParam? "Active Titlebar"_L1 : "Inactive Titlebar"_L1);
break;
case WM_MOUSEACTIVATE:
{
@@ -799,37 +744,37 @@ QString decodeMSG(const MSG& msg)
case WM_MOUSEMOVE:
parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(",
GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
- + virtualKeys(uint(wParam)) + QLatin1Char(')');
+ + virtualKeys(uint(wParam)) + u')';
break;
case WM_MOVE:
parameters = QString::asprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
break;
case WM_ERASEBKGND:
case WM_PAINT:
- parameters = QLatin1String("hdc") + wParamS;
+ parameters = "hdc"_L1 + wParamS;
break;
case WM_QUERYNEWPALETTE:
break; // lParam & wParam are unused
case WM_SETCURSOR:
parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(", LOWORD(lParam));
if (const char *mouseMsg = findWMstr(HIWORD(lParam)))
- parameters += QLatin1String(mouseMsg);
- parameters += QLatin1Char(')');
+ parameters += QLatin1StringView(mouseMsg);
+ parameters += u')';
break;
case WM_SETFOCUS:
- parameters = QLatin1String("Lost Focus ") + wParamS;
+ parameters = "Lost Focus "_L1 + wParamS;
break;
case WM_SETTEXT:
- parameters = QLatin1String("Set Text (")
+ parameters = "Set Text ("_L1
+ QString::fromWCharArray(reinterpret_cast<const wchar_t *>(lParam))
- + QLatin1Char(')');
+ + u')';
break;
case WM_SIZE:
parameters = QString::asprintf("w,h(%4d,%4d) showmode(",
LOWORD(lParam), HIWORD(lParam));
if (const char *showMode = wmSizeParam(uint(wParam)))
- parameters += QLatin1String(showMode);
- parameters += QLatin1Char(')');
+ parameters += QLatin1StringView(showMode);
+ parameters += u')';
break;
case WM_WINDOWPOSCHANGED:
{
@@ -841,23 +786,23 @@ QString decodeMSG(const MSG& msg)
winPos->x, winPos->y, winPos->cx, winPos->cy,
winPosFlags(winPos->flags).toLatin1().constData());
if (const char *h = winPosInsertAfter(insertAfter))
- parameters += QLatin1String(h);
+ parameters += QLatin1StringView(h);
else
parameters += QString::number(insertAfter, 16);
- parameters += QLatin1Char(')');
+ parameters += u')';
}
break;
case WM_QUERYENDSESSION:
- parameters = QLatin1String("End session: ");
+ parameters = "End session: "_L1;
if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))
- parameters += QLatin1String(logoffOption);
+ parameters += QLatin1StringView(logoffOption);
break;
default:
- parameters = QLatin1String("wParam") + wParamS + QLatin1String(" lParam") + lParamS;
+ parameters = "wParam"_L1 + wParamS + " lParam"_L1 + lParamS;
break;
}
- return message + QLatin1String("hwnd") + hwndS + QLatin1Char(' ') + parameters;
+ return message + "hwnd"_L1 + hwndS + u' ' + parameters;
}
QDebug operator<<(QDebug dbg, const MSG &msg)
@@ -887,7 +832,7 @@ void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerI
&& (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
&& static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
--pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
+ pe.event->m_posted = false;
delete pe.event;
const_cast<QPostEvent &>(pe).event = 0;
return;
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
index 849d72901d..2b8d9763f6 100644
--- a/src/corelib/kernel/qcorecmdlineargs_p.h
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCORECMDLINEARGS_P_H
#define QCORECMDLINEARGS_P_H
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index e3326f00d7..9c99530268 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoreevent.h"
+#include "qcoreevent_p.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
@@ -50,6 +15,9 @@
QT_BEGIN_NAMESPACE
+Q_TRACE_POINT(qtcore, QEvent_ctor, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtcore, QEvent_dtor, QEvent *event, QEvent::Type type);
+
/*!
\class QEvent
\inmodule QtCore
@@ -111,6 +79,8 @@ QT_BEGIN_NAMESPACE
\value ChildAdded An object gets a child (QChildEvent).
\value ChildPolished A widget child gets polished (QChildEvent).
\value ChildRemoved An object loses a child (QChildEvent).
+ \value [since 6.7] ChildWindowAdded A child window was added to the window.
+ \value [since 6.7] ChildWindowRemoved A child window was removed from the window.
\value Clipboard The clipboard contents have changed.
\value Close Widget was closed (QCloseEvent).
\value CloseSoftwareInputPanel A widget wants to close the software input panel (SIP).
@@ -118,6 +88,8 @@ QT_BEGIN_NAMESPACE
\value ContextMenu Context popup menu (QContextMenuEvent).
\value CursorChange The widget's cursor has changed.
\value DeferredDelete The object will be deleted after it has cleaned up (QDeferredDeleteEvent)
+ \value [since 6.6] DevicePixelRatioChange
+ The devicePixelRatio has changed for this widget's or window's underlying backing store.
\value DragEnter The cursor enters a widget during a drag and drop operation (QDragEnterEvent).
\value DragLeave The cursor leaves a widget during a drag and drop operation (QDragLeaveEvent).
\value DragMove A drag and drop operation is in progress (QDragMoveEvent).
@@ -153,6 +125,7 @@ QT_BEGIN_NAMESPACE
\value GraphicsSceneMove Widget was moved (QGraphicsSceneMoveEvent).
\value GraphicsSceneResize Widget was resized (QGraphicsSceneResizeEvent).
\value GraphicsSceneWheel Mouse wheel rolled in a graphics scene (QGraphicsSceneWheelEvent).
+ \value GraphicsSceneLeave The cursor leaves a graphics scene (QGraphicsSceneWheelEvent).
\value Hide Widget was hidden (QHideEvent).
\value HideToParent A child widget has been hidden.
\value HoverEnter The mouse cursor enters a hover widget (QHoverEvent).
@@ -189,15 +162,20 @@ QT_BEGIN_NAMESPACE
\value OrientationChange The screens orientation has changes (QScreenOrientationChangeEvent).
\value Paint Screen update necessary (QPaintEvent).
\value PaletteChange Palette of the widget changed.
- \value ParentAboutToChange The widget parent is about to change.
- \value ParentChange The widget parent has changed.
+ \value ParentAboutToChange The object parent is about to change.
+ Only sent to some object types, such as QWidget.
+ \value ParentChange The object parent has changed.
+ Only sent to some object types, such as QWidget.
+ \value [since 6.7] ParentWindowAboutToChange The parent window is about to change.
+ \value [since 6.7] ParentWindowChange The parent window has changed.
\value PlatformPanel A platform specific panel has been requested.
\value PlatformSurface A native platform surface has been created or is about to be destroyed (QPlatformSurfaceEvent).
\omitvalue Pointer
\value Polish The widget is polished.
\value PolishRequest The widget should be polished.
\value QueryWhatsThis The widget should accept the event if it has "What's This?" help (QHelpEvent).
- \value ReadOnlyChange Widget's read-only state has changed (since Qt 5.4).
+ \value Quit The application has exited.
+ \value [since 5.4] ReadOnlyChange Widget's read-only state has changed.
\value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
\value Resize Widget's size changed (QResizeEvent).
\value ScrollPrepare The object needs to fill in its geometry information (QScrollPrepareEvent).
@@ -224,7 +202,7 @@ QT_BEGIN_NAMESPACE
\omitvalue OkRequest
\value TabletEnterProximity Wacom tablet enter proximity event (QTabletEvent), sent to QApplication.
\value TabletLeaveProximity Wacom tablet leave proximity event (QTabletEvent), sent to QApplication.
- \value TabletTrackingChange The Wacom tablet tracking state has changed (since Qt 5.9).
+ \value [since 5.9] TabletTrackingChange The Wacom tablet tracking state has changed.
\omitvalue ThemeChange
\value ThreadChange The object is moved to another thread. This is the last event sent to this object in the previous thread. See QObject::moveToThread().
\value Timer Regular timer events (QTimerEvent).
@@ -250,7 +228,7 @@ QT_BEGIN_NAMESPACE
\value WindowStateChange The \l{QWindow::windowState()}{window's state} (minimized, maximized or full-screen) has changed (QWindowStateChangeEvent).
\value WindowTitleChange The window title has changed.
\value WindowUnblocked The window is unblocked after a modal dialog exited.
- \value WinIdChange The window system identifer for this native widget has changed.
+ \value WinIdChange The window system identifier for this native widget has changed.
\value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows.
User events should have values between \c User and \c{MaxUser}:
@@ -283,59 +261,64 @@ QT_BEGIN_NAMESPACE
\omitvalue ApplicationDeactivate
\omitvalue ApplicationDeactivated
\omitvalue MacGLWindowChange
- \omitvalue MacGLClearDrawable
\omitvalue NetworkReplyUpdated
\omitvalue FutureCallOut
\omitvalue NativeGesture
\omitvalue WindowChangeInternal
\omitvalue ScreenChangeInternal
+ \omitvalue WindowAboutToChangeInternal
*/
/*!
- Contructs an event object of type \a type.
+ Constructs an event object of type \a type.
*/
QEvent::QEvent(Type type)
- : d(nullptr), t(type), posted(false), spont(false), m_accept(true)
+ : t(type), m_reserved(0),
+ m_inputEvent(false), m_pointerEvent(false), m_singlePointEvent(false)
{
- Q_TRACE(QEvent_ctor, this, t);
+ Q_TRACE(QEvent_ctor, this, type);
}
/*!
+ \fn QEvent::QEvent(const QEvent &other)
\internal
- Attempts to copy the \a other event.
+ Copies the \a other event.
+*/
- Copying events is a bad idea, yet some Qt 4 code does it (notably,
- QApplication and the state machine).
- */
-QEvent::QEvent(const QEvent &other)
- : d(other.d), t(other.t), posted(other.posted), spont(other.spont),
- m_accept(other.m_accept)
-{
- Q_TRACE(QEvent_ctor, this, t);
- // if QEventPrivate becomes available, make sure to implement a
- // virtual QEventPrivate *clone() const; function so we can copy here
- Q_ASSERT_X(!d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
-}
+/*!
+ \internal
+ \since 6.0
+ \fn QEvent::QEvent(Type type, QEvent::InputEventTag)
+
+ Constructs an event object of type \a type, setting the inputEvent flag to \c true.
+*/
/*!
\internal
+ \since 6.0
+ \fn QEvent::QEvent(Type type, QEvent::PointerEventTag)
+
+ Constructs an event object of type \a type, setting the pointerEvent and
+ inputEvent flags to \c true.
+*/
+
+/*!
+ \internal
+ \since 6.0
+ \fn QEvent::QEvent(Type type, QEvent::SinglePointEventTag)
+
+ Constructs an event object of type \a type, setting the singlePointEvent,
+ pointerEvent and inputEvent flags to \c true.
+*/
+
+/*!
+ \fn QEvent &QEvent::operator=(const QEvent &other)
+ \internal
Attempts to copy the \a other event.
Copying events is a bad idea, yet some Qt 4 code does it (notably,
QApplication and the state machine).
*/
-QEvent &QEvent::operator=(const QEvent &other)
-{
- // if QEventPrivate becomes available, make sure to implement a
- // virtual QEventPrivate *clone() const; function so we can copy here
- Q_ASSERT_X(!other.d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
-
- t = other.t;
- posted = other.posted;
- spont = other.spont;
- m_accept = other.m_accept;
- return *this;
-}
/*!
Destroys the event. If it was \l{QCoreApplication::postEvent()}{posted},
@@ -344,16 +327,20 @@ QEvent &QEvent::operator=(const QEvent &other)
QEvent::~QEvent()
{
- Q_TRACE(QEvent_dtor, this, t);
- if (posted && QCoreApplication::instance())
+ if (m_posted && QCoreApplication::instance())
QCoreApplicationPrivate::removePostedEvent(this);
- Q_ASSERT_X(!d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
}
+/*!
+ Creates and returns an identical copy of this event.
+ \since 6.0
+*/
+QEvent *QEvent::clone() const
+{ return new QEvent(*this); }
/*!
\property QEvent::accepted
- the accept flag of the event object
+ \brief the accept flag of the event object.
Setting the accept parameter indicates that the event receiver
wants the event. Unwanted events might be propagated to the parent
@@ -362,6 +349,10 @@ QEvent::~QEvent()
For convenience, the accept flag can also be set with accept(),
and cleared with ignore().
+
+ \note Accepting a QPointerEvent implicitly
+ \l {QEventPoint::setAccepted()}{accepts} all the
+ \l {QPointerEvent::points()}{points} that the event carries.
*/
/*!
@@ -403,8 +394,29 @@ QEvent::~QEvent()
Returns \c true if the event originated outside the application (a
system event); otherwise returns \c false.
+*/
+
+/*!
+ \fn bool QEvent::isInputEvent() const
+ \since 6.0
+
+ Returns \c true if the event object is a QInputEvent or one of its
+ subclasses.
+*/
+
+/*!
+ \fn bool QEvent::isPointerEvent() const
+ \since 6.0
+
+ Returns \c true if the event object is a QPointerEvent or one of its
+ subclasses.
+*/
+
+/*!
+ \fn bool QEvent::isSinglePointEvent() const
+ \since 6.0
- The return value of this function is not defined for paint events.
+ Returns \c true if the event object is a subclass of QSinglePointEvent.
*/
namespace {
@@ -421,13 +433,16 @@ struct QBasicAtomicBitField {
QBasicAtomicInteger<uint> next;
QBasicAtomicInteger<uint> data[NumInts];
+ constexpr QBasicAtomicBitField() = default;
+
bool allocateSpecific(int which) noexcept
{
QBasicAtomicInteger<uint> &entry = data[which / BitsPerInt];
const uint old = entry.loadRelaxed();
const uint bit = 1U << (which % BitsPerInt);
- return !(old & bit) // wasn't taken
- && entry.testAndSetRelaxed(old, old | bit); // still wasn't taken
+ if (old & bit)
+ return false; // already taken
+ return (entry.fetchAndOrRelaxed(bit) & bit) == 0;
// don't update 'next' here - it's unlikely that it will need
// to be updated, in the general case, and having 'next'
@@ -461,7 +476,7 @@ struct QBasicAtomicBitField {
typedef QBasicAtomicBitField<QEvent::MaxUser - QEvent::User + 1> UserEventTypeRegistry;
-static UserEventTypeRegistry userEventTypeRegistry;
+Q_CONSTINIT static UserEventTypeRegistry userEventTypeRegistry {};
static inline int registerEventTypeZeroBased(int id) noexcept
{
@@ -504,12 +519,12 @@ int QEvent::registerEventType(int hint) noexcept
started one or more timers. Each timer has a unique identifier. A
timer is started with QObject::startTimer().
- The QTimer class provides a high-level programming interface that
+ The QChronoTimer class provides a high-level programming interface that
uses signals instead of events. It also provides single-shot timers.
The event handler QObject::timerEvent() receives timer events.
- \sa QTimer, QObject::timerEvent(), QObject::startTimer(),
+ \sa QChronoTimer, QObject::timerEvent(), QObject::startTimer(),
QObject::killTimer()
*/
@@ -521,12 +536,7 @@ QTimerEvent::QTimerEvent(int timerId)
: QEvent(Timer), id(timerId)
{}
-/*!
- \internal
-*/
-QTimerEvent::~QTimerEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QTimerEvent)
/*!
\fn int QTimerEvent::timerId() const
@@ -568,12 +578,7 @@ QChildEvent::QChildEvent(Type type, QObject *child)
: QEvent(type), c(child)
{}
-/*!
- \internal
-*/
-QChildEvent::~QChildEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QChildEvent)
/*!
\fn QObject *QChildEvent::child() const
@@ -625,12 +630,7 @@ QDynamicPropertyChangeEvent::QDynamicPropertyChangeEvent(const QByteArray &name)
{
}
-/*!
- \internal
-*/
-QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QDynamicPropertyChangeEvent)
/*!
\fn QByteArray QDynamicPropertyChangeEvent::propertyName() const
@@ -642,26 +642,13 @@ QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent()
*/
/*!
- Constructs a deferred delete event with an initial loopLevel() of zero.
+ Constructs a deferred delete event with the given loop and scope level.
*/
-QDeferredDeleteEvent::QDeferredDeleteEvent()
- : QEvent(QEvent::DeferredDelete)
- , level(0)
+QDeferredDeleteEvent::QDeferredDeleteEvent(int loopLevel, int scopeLevel)
+ : QEvent(QEvent::DeferredDelete), m_loopLevel(loopLevel), m_scopeLevel(scopeLevel)
{ }
-/*!
- \internal
-*/
-QDeferredDeleteEvent::~QDeferredDeleteEvent()
-{ }
-
-/*! \fn int QDeferredDeleteEvent::loopLevel() const
-
- Returns the loop-level in which the event was posted. The
- loop-level is set by QCoreApplication::postEvent().
-
- \sa QObject::deleteLater()
-*/
+Q_IMPL_EVENT_COMMON(QDeferredDeleteEvent)
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index bbd95f7a96..a65dbee7da 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOREEVENT_H
#define QCOREEVENT_H
@@ -46,12 +10,43 @@
QT_BEGIN_NAMESPACE
+#define Q_EVENT_DISABLE_COPY(Class) \
+protected: \
+ Class(const Class &) = default; \
+ Class(Class &&) = delete; \
+ Class &operator=(const Class &other) = default; \
+ Class &operator=(Class &&) = delete
+
+#define Q_DECL_EVENT_COMMON(Class) \
+ protected: \
+ Class(const Class &); \
+ Class(Class &&) = delete; \
+ Class &operator=(const Class &other) = default; \
+ Class &operator=(Class &&) = delete; \
+ public: \
+ Class* clone() const override; \
+ ~Class() override; \
+ private:
+
+#define Q_IMPL_EVENT_COMMON(Class) \
+ Class::Class(const Class &) = default; \
+ Class::~Class() = default; \
+ Class* Class::clone() const \
+ { \
+ auto c = new Class(*this); \
+ [[maybe_unused]] QEvent *e = c; \
+ /* check that covariant return is safe to add */ \
+ Q_ASSERT(reinterpret_cast<quintptr>(c) == reinterpret_cast<quintptr>(e)); \
+ return c; \
+ }
class QEventPrivate;
class Q_CORE_EXPORT QEvent // event base class
{
Q_GADGET
QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+ Q_EVENT_DISABLE_COPY(QEvent);
public:
enum Type {
/*
@@ -82,7 +77,7 @@ public:
Hide = 18, // widget is hidden
Close = 19, // request to close widget
Quit = 20, // request to quit application
- ParentChange = 21, // widget has been reparented
+ ParentChange = 21, // object has been reparented
ParentAboutToChange = 131, // sent just before the parent change is done
ThreadChange = 22, // object has changed threads
WindowActivate = 24, // window was activated
@@ -205,6 +200,7 @@ public:
GraphicsSceneDragLeave = 166,
GraphicsSceneDrop = 167,
GraphicsSceneWheel = 168,
+ GraphicsSceneLeave = 220,
KeyboardLayoutChange = 169, // keyboard layout changed
@@ -238,7 +234,6 @@ public:
UngrabMouse = 187,
GrabKeyboard = 188,
UngrabKeyboard = 189,
- MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
StateMachineSignal = 192,
StateMachineWrapped = 193,
@@ -277,15 +272,25 @@ public:
StyleAnimationUpdate = 213, // style animation target should be updated
ApplicationStateChange = 214,
- WindowChangeInternal = 215, // internal for QQuickWidget
+ WindowChangeInternal = 215, // internal for QQuickWidget and texture-based widgets
ScreenChangeInternal = 216,
PlatformSurface = 217, // Platform surface created or about to be destroyed
- Pointer = 218, // QQuickPointerEvent; ### Qt 6: QPointerEvent
+ Pointer = 218, // Qt 5: QQuickPointerEvent; Qt 6: unused so far
TabletTrackingChange = 219, // tablet tracking state has changed
+ // GraphicsSceneLeave = 220,
+ WindowAboutToChangeInternal = 221, // internal for QQuickWidget and texture-based widgets
+
+ DevicePixelRatioChange = 222,
+
+ ChildWindowAdded = 223,
+ ChildWindowRemoved = 224,
+ ParentWindowAboutToChange = 225,
+ ParentWindowChange = 226,
+
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
@@ -295,53 +300,75 @@ public:
Q_ENUM(Type)
explicit QEvent(Type type);
- QEvent(const QEvent &other);
virtual ~QEvent();
- QEvent &operator=(const QEvent &other);
inline Type type() const { return static_cast<Type>(t); }
- inline bool spontaneous() const { return spont; }
+ inline bool spontaneous() const { return m_spont; }
- inline void setAccepted(bool accepted) { m_accept = accepted; }
+ inline virtual void setAccepted(bool accepted) { m_accept = accepted; }
inline bool isAccepted() const { return m_accept; }
inline void accept() { m_accept = true; }
inline void ignore() { m_accept = false; }
+ inline bool isInputEvent() const noexcept { return m_inputEvent; }
+ inline bool isPointerEvent() const noexcept { return m_pointerEvent; }
+ inline bool isSinglePointEvent() const noexcept { return m_singlePointEvent; }
+
static int registerEventType(int hint = -1) noexcept;
+ virtual QEvent *clone() const;
+
protected:
- QEventPrivate *d;
- ushort t;
+ struct InputEventTag { explicit InputEventTag() = default; };
+ QEvent(Type type, InputEventTag) : QEvent(type) { m_inputEvent = true; }
+ struct PointerEventTag { explicit PointerEventTag() = default; };
+ QEvent(Type type, PointerEventTag) : QEvent(type, InputEventTag{}) { m_pointerEvent = true; }
+ struct SinglePointEventTag { explicit SinglePointEventTag() = default; };
+ QEvent(Type type, SinglePointEventTag) : QEvent(type, PointerEventTag{}) { m_singlePointEvent = true; }
+ quint16 t;
private:
- ushort posted : 1;
- ushort spont : 1;
- ushort m_accept : 1;
- ushort reserved : 13;
+ /*
+ We can assume that C++ types are 8-byte aligned, and we can't assume that compilers
+ coalesce data members from subclasses. Use bitfields to fill up to next 8-byte
+ aligned size, which is 16 bytes. That way we don't waste memory, and have plenty of room
+ for future flags.
+ Don't use bitfields for the most important flags, as that would generate more code, and
+ access is always inline. Bytes used are:
+ 8 vptr + 2 type + 3 bool flags => 3 bytes left, so 24 bits. However, compilers will word-
+ align the quint16s after the bools, so add another unused bool to fill that gap, which
+ leaves us with 16 bits.
+ */
+ bool m_posted = false;
+ bool m_spont = false;
+ bool m_accept = true;
+ bool m_unused = false;
+ quint16 m_reserved : 13;
+ quint16 m_inputEvent : 1;
+ quint16 m_pointerEvent : 1;
+ quint16 m_singlePointEvent : 1;
friend class QCoreApplication;
friend class QCoreApplicationPrivate;
friend class QThreadData;
friend class QApplication;
-#if QT_CONFIG(shortcut)
- friend class QShortcutMap;
-#endif
- friend class QGraphicsView;
- friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
// from QtTest:
+ // QtWebEngine event handling requires forwarding events as spontaneous.
+ // Impersonated QSpontaneKeyEvent in QtWebEngine to handle such cases.
friend class QSpontaneKeyEvent;
// needs this:
Q_ALWAYS_INLINE
- void setSpontaneous() { spont = true; }
+ void setSpontaneous() { m_spont = true; }
};
class Q_CORE_EXPORT QTimerEvent : public QEvent
{
+ Q_DECL_EVENT_COMMON(QTimerEvent)
public:
- explicit QTimerEvent( int timerId );
- ~QTimerEvent();
+ explicit QTimerEvent(int timerId);
int timerId() const { return id; }
+
protected:
int id;
};
@@ -350,22 +377,24 @@ class QObject;
class Q_CORE_EXPORT QChildEvent : public QEvent
{
+ Q_DECL_EVENT_COMMON(QChildEvent)
public:
- QChildEvent( Type type, QObject *child );
- ~QChildEvent();
+ QChildEvent(Type type, QObject *child);
+
QObject *child() const { return c; }
bool added() const { return type() == ChildAdded; }
bool polished() const { return type() == ChildPolished; }
bool removed() const { return type() == ChildRemoved; }
+
protected:
QObject *c;
};
class Q_CORE_EXPORT QDynamicPropertyChangeEvent : public QEvent
{
+ Q_DECL_EVENT_COMMON(QDynamicPropertyChangeEvent)
public:
explicit QDynamicPropertyChangeEvent(const QByteArray &name);
- ~QDynamicPropertyChangeEvent();
inline QByteArray propertyName() const { return n; }
@@ -373,17 +402,6 @@ private:
QByteArray n;
};
-class Q_CORE_EXPORT QDeferredDeleteEvent : public QEvent
-{
-public:
- explicit QDeferredDeleteEvent();
- ~QDeferredDeleteEvent();
- int loopLevel() const { return level; }
-private:
- int level;
- friend class QCoreApplication;
-};
-
QT_END_NAMESPACE
#endif // QCOREEVENT_H
diff --git a/src/corelib/kernel/qcoreevent_p.h b/src/corelib/kernel/qcoreevent_p.h
new file mode 100644
index 0000000000..ac90baad9b
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent_p.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOREEVENT_P_H
+#define QCOREEVENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qcoreevent.h"
+
+QT_BEGIN_NAMESPACE
+
+class QCoreApplication;
+
+class QDeferredDeleteEvent : public QEvent
+{
+ Q_DECL_EVENT_COMMON(QDeferredDeleteEvent)
+public:
+ explicit QDeferredDeleteEvent(int loopLevel, int scopeLevel);
+ int loopLevel() const { return m_loopLevel; }
+ int scopeLevel() const { return m_scopeLevel; }
+
+private:
+ int m_loopLevel = 0;
+ int m_scopeLevel = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOREEVENT_P_H
diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
deleted file mode 100644
index 4df5a40e39..0000000000
--- a/src/corelib/kernel/qcoreglobaldata.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qcoreglobaldata_p.h"
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QCoreGlobalData, globalInstance)
-
-QCoreGlobalData::QCoreGlobalData()
-{
-}
-
-QCoreGlobalData::~QCoreGlobalData()
-{
-}
-
-QCoreGlobalData *QCoreGlobalData::instance()
-{
- return globalInstance();
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreglobaldata_p.h b/src/corelib/kernel/qcoreglobaldata_p.h
deleted file mode 100644
index 2b9677efd9..0000000000
--- a/src/corelib/kernel/qcoreglobaldata_p.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QCOREGLOBALDATA_P_H
-#define QCOREGLOBALDATA_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-#include "QtCore/qmap.h"
-#include "QtCore/qstringlist.h"
-#include "QtCore/qreadwritelock.h"
-#include "QtCore/qhash.h"
-#include "QtCore/qbytearray.h"
-#include "QtCore/qmutex.h"
-
-QT_BEGIN_NAMESPACE
-
-struct QCoreGlobalData {
- QCoreGlobalData();
- ~QCoreGlobalData();
-
- QMap<QString, QStringList> dirSearchPaths;
- QReadWriteLock dirSearchPathsLock;
-
- static QCoreGlobalData *instance();
-};
-
-
-QT_END_NAMESPACE
-#endif // QCOREGLOBALDATA_P_H
-
diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp
index 0ca052764a..f99e68f990 100644
--- a/src/corelib/kernel/qdeadlinetimer.cpp
+++ b/src/corelib/kernel/qdeadlinetimer.cpp
@@ -1,332 +1,47 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdeadlinetimer.h"
-#include "qdeadlinetimer_p.h"
#include "private/qnumeric_p.h"
QT_BEGIN_NAMESPACE
-namespace {
- class TimeReference
- {
- enum : unsigned {
- umega = 1000 * 1000,
- ugiga = umega * 1000
- };
-
- enum : qint64 {
- kilo = 1000,
- mega = kilo * 1000,
- giga = mega * 1000
- };
-
- public:
- enum RoundingStrategy {
- RoundDown,
- RoundUp,
- RoundDefault = RoundDown
- };
-
- static constexpr qint64 Min = std::numeric_limits<qint64>::min();
- static constexpr qint64 Max = std::numeric_limits<qint64>::max();
-
- inline TimeReference(qint64 = 0, unsigned = 0);
- inline void updateTimer(qint64 &, unsigned &);
-
- inline bool addNanoseconds(qint64);
- inline bool addMilliseconds(qint64);
- bool addSecsAndNSecs(qint64, qint64);
-
- inline bool subtract(const qint64, const unsigned);
-
- inline bool toMilliseconds(qint64 *, RoundingStrategy = RoundDefault) const;
- inline bool toNanoseconds(qint64 *) const;
-
- inline void saturate(bool toMax);
- static bool sign(qint64, qint64);
-
- private:
- bool adjust(const qint64, const unsigned, qint64 = 0);
-
- private:
- qint64 secs;
- unsigned nsecs;
- };
-}
+QT_IMPL_METATYPE_EXTERN(QDeadlineTimer)
-inline TimeReference::TimeReference(qint64 t1, unsigned t2)
- : secs(t1), nsecs(t2)
-{
-}
+using namespace std::chrono;
-inline void TimeReference::updateTimer(qint64 &t1, unsigned &t2)
-{
- t1 = secs;
- t2 = nsecs;
-}
-
-inline void TimeReference::saturate(bool toMax)
-{
- secs = toMax ? Max : Min;
-}
-
-/*!
- * \internal
- *
- * Determines the sign of a (seconds, nanoseconds) pair
- * for differentiating overflow from underflow. It doesn't
- * deal with equality as it shouldn't ever be called in that case.
- *
- * Returns true if the pair represents a positive time offset
- * false otherwise.
- */
-bool TimeReference::sign(qint64 secs, qint64 nsecs)
-{
- if (secs > 0) {
- if (nsecs > 0)
- return true;
- } else {
- if (nsecs < 0)
- return false;
- }
-
- // They are different in sign
- secs += nsecs / giga;
- if (secs > 0)
- return true;
- else if (secs < 0)
- return false;
-
- // We should never get over|underflow out of
- // the case: secs * giga == -nsecs
- // So the sign of nsecs is the deciding factor
- Q_ASSERT(nsecs % giga != 0);
- return nsecs > 0;
-}
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
-inline bool TimeReference::addNanoseconds(qint64 arg)
-{
- return addSecsAndNSecs(arg / giga, arg % giga);
-}
-
-inline bool TimeReference::addMilliseconds(qint64 arg)
+namespace {
+struct TimeReference : std::numeric_limits<qint64>
{
- return addSecsAndNSecs(arg / kilo, (arg % kilo) * mega);
+ static constexpr qint64 Min = min();
+ static constexpr qint64 Max = max();
+};
}
-/*!
- * \internal
- *
- * Adds \a t1 addSecs seconds and \a addNSecs nanoseconds to the
- * time reference. The arguments are normalized to seconds (qint64)
- * and nanoseconds (unsigned) before the actual calculation is
- * delegated to adjust(). If the nanoseconds are negative the
- * owed second used for the normalization is passed on to adjust()
- * as third argument.
- *
- * Returns true if operation was successful, false on over|underflow
- */
-bool TimeReference::addSecsAndNSecs(qint64 addSecs, qint64 addNSecs)
+template <typename Duration1, typename... Durations>
+static qint64 add_saturate(qint64 t1, Duration1 dur, Durations... extra)
{
- // Normalize the arguments
- if (qAbs(addNSecs) >= giga) {
- if (add_overflow<qint64>(addSecs, addNSecs / giga, &addSecs))
- return false;
-
- addNSecs %= giga;
- }
+ qint64 v = dur.count();
+ qint64 saturated = std::numeric_limits<qint64>::max();
+ if (v < 0)
+ saturated = std::numeric_limits<qint64>::min();
- if (addNSecs < 0)
- return adjust(addSecs, ugiga - unsigned(-addNSecs), -1);
+ // convert to nanoseconds with saturation
+ using Ratio = std::ratio_divide<typename Duration1::period, nanoseconds::period>;
+ static_assert(Ratio::den == 1, "sub-multiples of nanosecond are not supported");
+ if (qMulOverflow<Ratio::num>(v, &v))
+ return saturated;
- return adjust(addSecs, unsigned(addNSecs));
-}
-
-/*!
- * \internal
- *
- * Adds \a t1 seconds and \a t2 nanoseconds to the internal members.
- * Takes into account the additional \a carrySeconds we may owe or need to carry over.
- *
- * Returns true if operation was successful, false on over|underflow
- */
-bool TimeReference::adjust(const qint64 t1, const unsigned t2, qint64 carrySeconds)
-{
- static_assert(QDeadlineTimerNanosecondsInT2);
- nsecs += t2;
- if (nsecs >= ugiga) {
- nsecs -= ugiga;
- carrySeconds++;
+ qint64 r;
+ if (qAddOverflow(t1, v, &r))
+ return saturated;
+ if constexpr (sizeof...(Durations)) {
+ // chain more additions
+ return add_saturate(r, extra...);
}
-
- // We don't worry about the order of addition, because the result returned by
- // callers of this function is unchanged regardless of us over|underflowing.
- // If we do, we do so by no more than a second, thus saturating the timer to
- // Forever has the same effect as if we did the arithmetic exactly and salvaged
- // the overflow.
- return !add_overflow<qint64>(secs, t1, &secs) && !add_overflow<qint64>(secs, carrySeconds, &secs);
-}
-
-/*!
- * \internal
- *
- * Subtracts \a t1 seconds and \a t2 nanoseconds from the time reference.
- * When normalizing the nanoseconds to a positive number the owed seconds is
- * passed as third argument to adjust() as the seconds may over|underflow
- * if we do the calculation directly. There is little sense to check the
- * seconds for over|underflow here in case we are going to need to carry
- * over a second _after_ we add the nanoseconds.
- *
- * Returns true if operation was successful, false on over|underflow
- */
-inline bool TimeReference::subtract(const qint64 t1, const unsigned t2)
-{
- Q_ASSERT(t2 < ugiga);
- return adjust(-t1, ugiga - t2, -1);
-}
-
-/*!
- * \internal
- *
- * Converts the time reference to milliseconds.
- *
- * Checks are done without making use of mul_overflow because it may
- * not be implemented on some 32bit platforms.
- *
- * Returns true if operation was successful, false on over|underflow
- */
-inline bool TimeReference::toMilliseconds(qint64 *result, RoundingStrategy rounding) const
-{
- static constexpr qint64 maxSeconds = Max / kilo;
- static constexpr qint64 minSeconds = Min / kilo;
- if (secs > maxSeconds || secs < minSeconds)
- return false;
-
- unsigned ns = rounding == RoundDown ? nsecs : nsecs + umega - 1;
-
- return !add_overflow<qint64>(secs * kilo, ns / umega, result);
-}
-
-/*!
- * \internal
- *
- * Converts the time reference to nanoseconds.
- *
- * Checks are done without making use of mul_overflow because it may
- * not be implemented on some 32bit platforms.
- *
- * Returns true if operation was successful, false on over|underflow
- */
-inline bool TimeReference::toNanoseconds(qint64 *result) const
-{
- static constexpr qint64 maxSeconds = Max / giga;
- static constexpr qint64 minSeconds = Min / giga;
- if (secs > maxSeconds || secs < minSeconds)
- return false;
-
- return !add_overflow<qint64>(secs * giga, nsecs, result);
-}
-#else
-inline bool TimeReference::addNanoseconds(qint64 arg)
-{
- return adjust(arg, 0);
-}
-
-inline bool TimeReference::addMilliseconds(qint64 arg)
-{
- static constexpr qint64 maxMilliseconds = Max / mega;
- if (qAbs(arg) > maxMilliseconds)
- return false;
-
- return addNanoseconds(arg * mega);
-}
-
-inline bool TimeReference::addSecsAndNSecs(qint64 addSecs, qint64 addNSecs)
-{
- static constexpr qint64 maxSeconds = Max / giga;
- static constexpr qint64 minSeconds = Min / giga;
- if (addSecs > maxSeconds || addSecs < minSeconds || add_overflow<qint64>(addSecs * giga, addNSecs, &addNSecs))
- return false;
-
- return addNanoseconds(addNSecs);
-}
-
-inline bool TimeReference::adjust(const qint64 t1, const unsigned t2, qint64 carrySeconds)
-{
- static_assert(!QDeadlineTimerNanosecondsInT2);
- Q_UNUSED(t2);
- Q_UNUSED(carrySeconds);
-
- return !add_overflow<qint64>(secs, t1, &secs);
-}
-
-inline bool TimeReference::subtract(const qint64 t1, const unsigned t2)
-{
- Q_UNUSED(t2);
-
- return addNanoseconds(-t1);
+ return r;
}
-inline bool TimeReference::toMilliseconds(qint64 *result, RoundingStrategy rounding) const
-{
- // Force QDeadlineTimer to treat the border cases as
- // over|underflow and saturate the results returned to the user.
- // We don't want to get valid milliseconds out of saturated timers.
- if (secs == Max || secs == Min)
- return false;
-
- *result = secs / mega;
- if (rounding == RoundUp && secs > *result * mega)
- (*result)++;
-
- return true;
-}
-
-inline bool TimeReference::toNanoseconds(qint64 *result) const
-{
- *result = secs;
- return true;
-}
-#endif
-
/*!
\class QDeadlineTimer
\inmodule QtCore
@@ -336,6 +51,8 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
\reentrant
\ingroup tools
+ \compares strong
+
The QDeadlineTimer class is usually used to calculate future deadlines and
verify whether the deadline has expired. QDeadlineTimer can also be used
for deadlines without expiration ("forever"). It forms a counterpart to
@@ -369,11 +86,12 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
\section1 Timer types
- Like QTimer, QDeadlineTimer can select among different levels of coarseness
- on the timers. You can select precise timing by passing Qt::PreciseTimer to
- the functions that set of change the timer, or you can select coarse timing
- by passing Qt::CoarseTimer. Qt::VeryCoarseTimer is currently interpreted
- the same way as Qt::CoarseTimer.
+ Like QTimer and QChronoTimer, QDeadlineTimer can select among
+ different levels of coarseness on the timers. You can select
+ precise timing by passing Qt::PreciseTimer to the functions that
+ set of change the timer, or you can select coarse timing by passing
+ Qt::CoarseTimer. Qt::VeryCoarseTimer is currently interpreted the same
+ way as Qt::CoarseTimer.
This feature is dependent on support from the operating system: if the OS
does not support a coarse timer functionality, then QDeadlineTimer will
@@ -405,7 +123,7 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
\snippet code/src_corelib_kernel_qdeadlinetimer.cpp 2
- \sa QTime, QTimer, QDeadlineTimer, Qt::TimerType
+ \sa QTime, QChronoTimer, QDeadlineTimer, Qt::TimerType
*/
/*!
@@ -416,10 +134,12 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
*/
/*!
+ \fn QDeadlineTimer::QDeadlineTimer()
\fn QDeadlineTimer::QDeadlineTimer(Qt::TimerType timerType)
Constructs an expired QDeadlineTimer object. For this object,
- remainingTime() will return 0.
+ remainingTime() will return 0. If \a timerType is not set, then the object
+ will use the \l{Qt::CoarseTimer}{coarse} \l{QDeadlineTimer#Timer types}{timer type}.
The timer type \a timerType may be ignored, since the timer is already
expired. Similarly, for optimization purposes, this function will not
@@ -449,7 +169,7 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
from the moment of the creation of this object, if msecs is positive. If \a
msecs is zero, this QDeadlineTimer will be marked as expired, causing
remainingTime() to return zero and deadline() to return an indeterminate
- time point in the past. If \a msecs is -1, the timer will be set to never
+ time point in the past. If \a msecs is negative, the timer will be set to never
expire, causing remainingTime() to return -1 and deadline() to return the
maximum value.
@@ -462,10 +182,12 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
functionality is required, use QDeadlineTimer::current() and add time to
it.
+ \note Prior to Qt 6.6, the only value that caused the timer to never expire
+ was -1.
+
\sa hasExpired(), isForever(), remainingTime(), setRemainingTime()
*/
QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept
- : t2(0)
{
setRemainingTime(msecs, type);
}
@@ -529,51 +251,70 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept
/*!
Sets the remaining time for this QDeadlineTimer object to \a msecs
milliseconds from now, if \a msecs has a positive value. If \a msecs is
- zero, this QDeadlineTimer object will be marked as expired, whereas a value
- of -1 will set it to never expire.
+ zero, this QDeadlineTimer object will be marked as expired, whereas a
+ negative value will set it to never expire.
+
+ For optimization purposes, if \a msecs is zero, this function may skip
+ obtaining the current time and may instead use a value known to be in the
+ past. If that happens, deadline() may return an unexpected value and this
+ object cannot be used in calculation of how long it is overdue. If that
+ functionality is required, use QDeadlineTimer::current() and add time to
+ it.
The timer type for this QDeadlineTimer object will be set to the specified \a timerType.
+ \note Prior to Qt 6.6, the only value that caused the timer to never expire
+ was -1.
+
\sa setPreciseRemainingTime(), hasExpired(), isForever(), remainingTime()
*/
void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) noexcept
{
- if (msecs == -1) {
+ if (msecs < 0) {
*this = QDeadlineTimer(Forever, timerType);
- return;
+ } else if (msecs == 0) {
+ *this = QDeadlineTimer(timerType);
+ t1 = std::numeric_limits<qint64>::min();
+ } else {
+ *this = current(timerType);
+ milliseconds ms(msecs);
+ t1 = add_saturate(t1, ms);
}
-
- *this = current(timerType);
-
- TimeReference ref(t1, t2);
- if (!ref.addMilliseconds(msecs))
- ref.saturate(msecs > 0);
- ref.updateTimer(t1, t2);
}
/*!
Sets the remaining time for this QDeadlineTimer object to \a secs seconds
plus \a nsecs nanoseconds from now, if \a secs has a positive value. If \a
- secs is -1, this QDeadlineTimer will be set it to never expire. If both
- parameters are zero, this QDeadlineTimer will be marked as expired.
+ secs is negative, this QDeadlineTimer will be set it to never expire (this
+ behavior does not apply to \a nsecs). If both parameters are zero, this
+ QDeadlineTimer will be marked as expired.
+
+ For optimization purposes, if both \a secs and \a nsecs are zero, this
+ function may skip obtaining the current time and may instead use a value
+ known to be in the past. If that happens, deadline() may return an
+ unexpected value and this object cannot be used in calculation of how long
+ it is overdue. If that functionality is required, use
+ QDeadlineTimer::current() and add time to it.
The timer type for this QDeadlineTimer object will be set to the specified
\a timerType.
+ \note Prior to Qt 6.6, the only condition that caused the timer to never
+ expire was when \a secs was -1.
+
\sa setRemainingTime(), hasExpired(), isForever(), remainingTime()
*/
void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
{
- if (secs == -1) {
+ if (secs < 0) {
*this = QDeadlineTimer(Forever, timerType);
- return;
+ } else if (secs == 0 && nsecs == 0) {
+ *this = QDeadlineTimer(timerType);
+ t1 = std::numeric_limits<qint64>::min();
+ } else {
+ *this = current(timerType);
+ t1 = add_saturate(t1, seconds{secs}, nanoseconds{nsecs});
}
-
- *this = current(timerType);
- TimeReference ref(t1, t2);
- if (!ref.addSecsAndNSecs(secs, nsecs))
- ref.saturate(TimeReference::sign(secs, nsecs));
- ref.updateTimer(t1, t2);
}
/*!
@@ -623,6 +364,8 @@ bool QDeadlineTimer::hasExpired() const noexcept
{
if (isForever())
return false;
+ if (t1 == std::numeric_limits<qint64>::min())
+ return true;
return *this <= current(timerType());
}
@@ -671,19 +414,8 @@ qint64 QDeadlineTimer::remainingTime() const noexcept
if (isForever())
return -1;
- QDeadlineTimer now = current(timerType());
- TimeReference ref(t1, t2);
-
- qint64 msecs;
- if (!ref.subtract(now.t1, now.t2))
- return 0; // We can only underflow here
-
- // If we fail the conversion, t1 < now.t1 means we underflowed,
- // thus the deadline had long expired
- if (!ref.toMilliseconds(&msecs, TimeReference::RoundUp))
- return t1 < now.t1 ? 0 : -1;
-
- return msecs < 0 ? 0 : msecs;
+ nanoseconds nsecs(remainingTimeNSecs());
+ return ceil<milliseconds>(nsecs).count();
}
/*!
@@ -705,23 +437,19 @@ qint64 QDeadlineTimer::remainingTimeNSecs() const noexcept
/*!
\internal
Same as remainingTimeNSecs, but may return negative remaining times. Does
- not deal with Forever. In case of underflow the result is saturated to
- the minimum possible value, on overflow - the maximum possible value.
+ not deal with Forever. In case of underflow, which is only possible if the
+ timer has expired, an arbitrary negative value is returned.
*/
qint64 QDeadlineTimer::rawRemainingTimeNSecs() const noexcept
{
- QDeadlineTimer now = current(timerType());
- TimeReference ref(t1, t2);
+ if (t1 == std::numeric_limits<qint64>::min())
+ return t1; // we'd saturate to this anyway
- qint64 nsecs;
- if (!ref.subtract(now.t1, now.t2))
- return TimeReference::Min; // We can only underflow here
-
- // If we fail the conversion, t1 < now.t1 means we underflowed,
- // thus the deadline had long expired
- if (!ref.toNanoseconds(&nsecs))
- return t1 < now.t1 ? TimeReference::Min : TimeReference::Max;
- return nsecs;
+ QDeadlineTimer now = current(timerType());
+ qint64 r;
+ if (qSubOverflow(t1, now.t1, &r))
+ return -1; // any negative number is fine
+ return r;
}
/*!
@@ -748,12 +476,11 @@ qint64 QDeadlineTimer::deadline() const noexcept
{
if (isForever())
return TimeReference::Max;
+ if (t1 == TimeReference::Min)
+ return t1;
- qint64 result;
- if (!TimeReference(t1, t2).toMilliseconds(&result))
- return t1 < 0 ? TimeReference::Min : TimeReference::Max;
-
- return result;
+ nanoseconds ns(t1);
+ return duration_cast<milliseconds>(ns).count();
}
/*!
@@ -782,11 +509,7 @@ qint64 QDeadlineTimer::deadlineNSecs() const noexcept
if (isForever())
return TimeReference::Max;
- qint64 result;
- if (!TimeReference(t1, t2).toNanoseconds(&result))
- return t1 < 0 ? TimeReference::Min : TimeReference::Max;
-
- return result;
+ return t1;
}
/*!
@@ -810,11 +533,7 @@ void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) noexcept
}
type = timerType;
-
- TimeReference ref;
- if (!ref.addMilliseconds(msecs))
- ref.saturate(msecs > 0);
- ref.updateTimer(t1, t2);
+ t1 = add_saturate(0, milliseconds{msecs});
}
/*!
@@ -832,13 +551,7 @@ void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) noexcept
void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
{
type = timerType;
-
- // We don't pass the seconds to the constructor, because we don't know
- // at this point if t1 holds the seconds or nanoseconds; it's platform specific.
- TimeReference ref;
- if (!ref.addSecsAndNSecs(secs, nsecs))
- ref.saturate(TimeReference::sign(secs, nsecs));
- ref.updateTimer(t1, t2);
+ t1 = add_saturate(0, seconds{secs}, nanoseconds{nsecs});
}
/*!
@@ -854,11 +567,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
if (dt.isForever())
return dt;
- TimeReference ref(dt.t1, dt.t2);
- if (!ref.addNanoseconds(nsecs))
- ref.saturate(nsecs > 0);
- ref.updateTimer(dt.t1, dt.t2);
-
+ dt.t1 = add_saturate(dt.t1, nanoseconds{nsecs});
return dt;
}
@@ -871,12 +580,22 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
The QDeadlineTimer object will be constructed with the specified \a timerType.
*/
+QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
+{
+ // ensure we get nanoseconds; this will work so long as steady_clock's
+ // time_point isn't of finer resolution (picoseconds)
+ std::chrono::nanoseconds ns = std::chrono::steady_clock::now().time_since_epoch();
+
+ QDeadlineTimer result;
+ result.t1 = ns.count();
+ result.type = timerType;
+ return result;
+}
/*!
- \fn bool operator==(QDeadlineTimer d1, QDeadlineTimer d2)
- \relates QDeadlineTimer
+ \fn bool QDeadlineTimer::operator==(const QDeadlineTimer &lhs, const QDeadlineTimer &rhs)
- Returns true if the deadline on \a d1 and the deadline in \a d2 are the
+ Returns true if the deadline on \a lhs and the deadline in \a rhs are the
same, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
@@ -887,11 +606,10 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
*/
/*!
- \fn bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2)
- \relates QDeadlineTimer
+ \fn bool QDeadlineTimer::operator!=(const QDeadlineTimer &lhs, const QDeadlineTimer &rhs)
- Returns true if the deadline on \a d1 and the deadline in \a d2 are
- diferent, false otherwise. The timer type used to create the two deadlines
+ Returns true if the deadline on \a lhs and the deadline in \a rhs are
+ different, false otherwise. The timer type used to create the two deadlines
is ignored. This function is equivalent to:
\snippet code/src_corelib_kernel_qdeadlinetimer.cpp 9
@@ -901,11 +619,10 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
*/
/*!
- \fn bool operator<(QDeadlineTimer d1, QDeadlineTimer d2)
- \relates QDeadlineTimer
+ \fn bool QDeadlineTimer::operator<(const QDeadlineTimer &lhs, const QDeadlineTimer &rhs)
- Returns true if the deadline on \a d1 is earlier than the deadline in \a
- d2, false otherwise. The timer type used to create the two deadlines is
+ Returns true if the deadline on \a lhs is earlier than the deadline in \a
+ rhs, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
\snippet code/src_corelib_kernel_qdeadlinetimer.cpp 10
@@ -915,11 +632,10 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
*/
/*!
- \fn bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2)
- \relates QDeadlineTimer
+ \fn bool QDeadlineTimer::operator<=(const QDeadlineTimer &lhs, const QDeadlineTimer &rhs)
- Returns true if the deadline on \a d1 is earlier than or the same as the
- deadline in \a d2, false otherwise. The timer type used to create the two
+ Returns true if the deadline on \a lhs is earlier than or the same as the
+ deadline in \a rhs, false otherwise. The timer type used to create the two
deadlines is ignored. This function is equivalent to:
\snippet code/src_corelib_kernel_qdeadlinetimer.cpp 11
@@ -929,11 +645,10 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
*/
/*!
- \fn bool operator>(QDeadlineTimer d1, QDeadlineTimer d2)
- \relates QDeadlineTimer
+ \fn bool QDeadlineTimer::operator>(const QDeadlineTimer &lhs, const QDeadlineTimer &rhs)
- Returns true if the deadline on \a d1 is later than the deadline in \a
- d2, false otherwise. The timer type used to create the two deadlines is
+ Returns true if the deadline on \a lhs is later than the deadline in \a
+ rhs, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
\snippet code/src_corelib_kernel_qdeadlinetimer.cpp 12
@@ -943,11 +658,10 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
*/
/*!
- \fn bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2)
- \relates QDeadlineTimer
+ \fn bool QDeadlineTimer::operator>=(const QDeadlineTimer &lhs, const QDeadlineTimer &rhs)
- Returns true if the deadline on \a d1 is later than or the same as the
- deadline in \a d2, false otherwise. The timer type used to create the two
+ Returns true if the deadline on \a lhs is later than or the same as the
+ deadline in \a rhs, false otherwise. The timer type used to create the two
deadlines is ignored. This function is equivalent to:
\snippet code/src_corelib_kernel_qdeadlinetimer.cpp 13
@@ -957,8 +671,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
*/
/*!
- \fn QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
- \relates QDeadlineTimer
+ \fn QDeadlineTimer QDeadlineTimer::operator+(QDeadlineTimer dt, qint64 msecs)
Returns a QDeadlineTimer object whose deadline is \a msecs later than the
deadline stored in \a dt. If \a dt is set to never expire, this function
@@ -972,17 +685,12 @@ QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
if (dt.isForever())
return dt;
- TimeReference ref(dt.t1, dt.t2);
- if (!ref.addMilliseconds(msecs))
- ref.saturate(msecs > 0);
- ref.updateTimer(dt.t1, dt.t2);
-
+ dt.t1 = add_saturate(dt.t1, milliseconds{msecs});
return dt;
}
/*!
- \fn QDeadlineTimer operator+(qint64 msecs, QDeadlineTimer dt)
- \relates QDeadlineTimer
+ \fn QDeadlineTimer QDeadlineTimer::operator+(qint64 msecs, QDeadlineTimer dt)
Returns a QDeadlineTimer object whose deadline is \a msecs later than the
deadline stored in \a dt. If \a dt is set to never expire, this function
@@ -992,8 +700,7 @@ QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
*/
/*!
- \fn QDeadlineTimer operator-(QDeadlineTimer dt, qint64 msecs)
- \relates QDeadlineTimer
+ \fn QDeadlineTimer QDeadlineTimer::operator-(QDeadlineTimer dt, qint64 msecs)
Returns a QDeadlineTimer object whose deadline is \a msecs before the
deadline stored in \a dt. If \a dt is set to never expire, this function
@@ -1044,11 +751,4 @@ QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
Returns the time remaining before the deadline.
*/
-/*!
- \fn QPair<qint64, unsigned> QDeadlineTimer::_q_data() const
- \internal
-*/
-
-// the rest of the functions are in qelapsedtimer_xxx.cpp
-
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index 99e09eb31f..515cdb5387 100644
--- a/src/corelib/kernel/qdeadlinetimer.h
+++ b/src/corelib/kernel/qdeadlinetimer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDEADLINETIMER_H
#define QDEADLINETIMER_H
@@ -43,7 +7,6 @@
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qnamespace.h>
-#include <QtCore/qpair.h>
#ifdef max
// un-pollute the namespace. We need std::numeric_limits::max() and std::chrono::duration::max()
@@ -52,27 +15,27 @@
#include <limits>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QDeadlineTimer
{
public:
- enum ForeverConstant { Forever };
-
- Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) noexcept
- : t1(0), t2(0), type(type_) {}
- Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) noexcept
- : t1(std::numeric_limits<qint64>::max()), t2(0), type(type_) {}
+ enum class ForeverConstant { Forever };
+ static constexpr ForeverConstant Forever = ForeverConstant::Forever;
+
+ constexpr QDeadlineTimer() noexcept = default;
+ constexpr explicit QDeadlineTimer(Qt::TimerType type_) noexcept
+ : type(type_) {}
+ constexpr QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) noexcept
+ : t1((std::numeric_limits<qint64>::max)()), type(type_) {}
explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept;
void swap(QDeadlineTimer &other) noexcept
- { qSwap(t1, other.t1); qSwap(t2, other.t2); qSwap(type, other.type); }
+ { std::swap(t1, other.t1); std::swap(type, other.type); }
- Q_DECL_CONSTEXPR bool isForever() const noexcept
+ constexpr bool isForever() const noexcept
{ return t1 == (std::numeric_limits<qint64>::max)(); }
bool hasExpired() const noexcept;
@@ -95,19 +58,6 @@ public:
static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept Q_DECL_PURE_FUNCTION;
static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) noexcept;
- friend bool operator==(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
- { return d1.t1 == d2.t1 && d1.t2 == d2.t2; }
- friend bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
- { return !(d1 == d2); }
- friend bool operator<(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
- { return d1.t1 < d2.t1 || (d1.t1 == d2.t1 && d1.t2 < d2.t2); }
- friend bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
- { return d1 == d2 || d1 < d2; }
- friend bool operator>(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
- { return d2 < d1; }
- friend bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
- { return !(d1 < d2); }
-
friend Q_CORE_EXPORT QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs);
friend QDeadlineTimer operator+(qint64 msecs, QDeadlineTimer dt)
{ return dt + msecs; }
@@ -120,26 +70,20 @@ public:
QDeadlineTimer &operator-=(qint64 msecs)
{ *this = *this + (-msecs); return *this; }
-#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
- template <class Clock, class Duration>
+ template <class Clock, class Duration = typename Clock::duration>
QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline_,
Qt::TimerType type_ = Qt::CoarseTimer) : t2(0)
{ setDeadline(deadline_, type_); }
- template <class Clock, class Duration>
+ template <class Clock, class Duration = typename Clock::duration>
QDeadlineTimer &operator=(std::chrono::time_point<Clock, Duration> deadline_)
{ setDeadline(deadline_); return *this; }
- template <class Clock, class Duration>
- void setDeadline(std::chrono::time_point<Clock, Duration> deadline_,
- Qt::TimerType type_ = Qt::CoarseTimer)
- { setRemainingTime(deadline_ == deadline_.max() ? Duration::max() : deadline_ - Clock::now(), type_); }
+ template <class Clock, class Duration = typename Clock::duration>
+ void setDeadline(std::chrono::time_point<Clock, Duration> tp,
+ Qt::TimerType type_ = Qt::CoarseTimer);
template <class Clock, class Duration = typename Clock::duration>
- std::chrono::time_point<Clock, Duration> deadline() const
- {
- auto val = std::chrono::nanoseconds(rawRemainingTimeNSecs()) + Clock::now();
- return std::chrono::time_point_cast<Duration>(val);
- }
+ std::chrono::time_point<Clock, Duration> deadline() const;
template <class Rep, class Period>
QDeadlineTimer(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type_ = Qt::CoarseTimer)
@@ -153,10 +97,11 @@ public:
template <class Rep, class Period>
void setRemainingTime(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type_ = Qt::CoarseTimer)
{
+ using namespace std::chrono;
if (remaining == remaining.max())
*this = QDeadlineTimer(Forever, type_);
else
- setPreciseRemainingTime(0, std::chrono::nanoseconds(remaining).count(), type_);
+ setPreciseRemainingTime(0, ceil<nanoseconds>(remaining).count(), type_);
}
std::chrono::nanoseconds remainingTimeAsDuration() const noexcept
@@ -178,24 +123,62 @@ public:
template <class Rep, class Period>
friend QDeadlineTimer operator+=(QDeadlineTimer &dt, std::chrono::duration<Rep, Period> value)
{ return dt = dt + value; }
-#endif
private:
- qint64 t1;
- unsigned t2;
- unsigned type;
+ friend bool comparesEqual(const QDeadlineTimer &lhs,
+ const QDeadlineTimer &rhs) noexcept
+ {
+ return lhs.t1 == rhs.t1;
+ }
+ friend Qt::strong_ordering compareThreeWay(const QDeadlineTimer &lhs,
+ const QDeadlineTimer &rhs) noexcept
+ {
+ return Qt::compareThreeWay(lhs.t1, rhs.t1);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QDeadlineTimer)
- qint64 rawRemainingTimeNSecs() const noexcept;
+ qint64 t1 = 0;
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ unsigned t2 = 0;
+#endif
+ unsigned type = Qt::CoarseTimer;
-public:
- // This is not a public function, it's here only for Qt's internal convenience...
- QPair<qint64, unsigned> _q_data() const { return qMakePair(t1, t2); }
+ qint64 rawRemainingTimeNSecs() const noexcept;
};
+template<class Clock, class Duration>
+std::chrono::time_point<Clock, Duration> QDeadlineTimer::deadline() const
+{
+ using namespace std::chrono;
+ if constexpr (std::is_same_v<Clock, steady_clock>) {
+ auto val = duration_cast<Duration>(nanoseconds(deadlineNSecs()));
+ return time_point<Clock, Duration>(val);
+ } else {
+ auto val = nanoseconds(rawRemainingTimeNSecs()) + Clock::now();
+ return time_point_cast<Duration>(val);
+ }
+}
+
+template<class Clock, class Duration>
+void QDeadlineTimer::setDeadline(std::chrono::time_point<Clock, Duration> tp, Qt::TimerType type_)
+{
+ using namespace std::chrono;
+ if (tp == tp.max()) {
+ *this = Forever;
+ type = type_;
+ } else if constexpr (std::is_same_v<Clock, steady_clock>) {
+ setPreciseDeadline(0,
+ duration_cast<nanoseconds>(tp.time_since_epoch()).count(),
+ type_);
+ } else {
+ setPreciseRemainingTime(0, duration_cast<nanoseconds>(tp - Clock::now()).count(), type_);
+ }
+}
+
Q_DECLARE_SHARED(QDeadlineTimer)
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QDeadlineTimer)
+QT_DECL_METATYPE_EXTERN(QDeadlineTimer, Q_CORE_EXPORT)
#endif // QDEADLINETIMER_H
diff --git a/src/corelib/kernel/qdeadlinetimer_p.h b/src/corelib/kernel/qdeadlinetimer_p.h
deleted file mode 100644
index 46e12de6c1..0000000000
--- a/src/corelib/kernel/qdeadlinetimer_p.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QDEADLINETIMER_P_H
-#define QDEADLINETIMER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-enum {
-#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
- // t1 contains seconds and t2 contains nanoseconds
- QDeadlineTimerNanosecondsInT2 = 1
-#else
- // t1 contains nanoseconds, t2 is always zero
- QDeadlineTimerNanosecondsInT2 = 0
-#endif
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/kernel/qelapsedtimer.cpp b/src/corelib/kernel/qelapsedtimer.cpp
index 57825583dd..511b81a04e 100644
--- a/src/corelib/kernel/qelapsedtimer.cpp
+++ b/src/corelib/kernel/qelapsedtimer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qelapsedtimer.h"
@@ -111,19 +75,7 @@ QT_BEGIN_NAMESPACE
that the clock used is the same as QElapsedTimer (see
QElapsedTimer::clockType()).
- \section2 32-bit overflows
-
- Some of the clocks used by QElapsedTimer have a limited range and may
- overflow after hitting the upper limit (usually 32-bit). QElapsedTimer
- deals with this overflow issue and presents a consistent timing. However,
- when extracting the time since reference from QElapsedTimer, two
- different processes in the same machine may have different understanding
- of how much time has actually elapsed.
-
- The information on which clocks types may overflow and how to remedy that
- issue is documented along with the clock types.
-
- \sa QTime, QTimer, QDeadlineTimer
+ \sa QTime, QChronoTimer, QDeadlineTimer
*/
/*!
@@ -138,10 +90,13 @@ QT_BEGIN_NAMESPACE
used.
\value SystemTime The human-readable system time. This clock is not monotonic.
- \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow.
- \value TickCounter The system's tick counter, used on Windows systems. This clock may overflow.
- \value MachAbsoluteTime The Mach kernel's absolute time (\macos and iOS). This clock is monotonic and does not overflow.
- \value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow.
+ \value MonotonicClock The system's monotonic clock, usually found in Unix systems.
+ This clock is monotonic.
+ \value TickCounter Not used anymore.
+ \value MachAbsoluteTime The Mach kernel's absolute time (\macos and iOS).
+ This clock is monotonic.
+ \value PerformanceCounter The performance counter provided by Windows.
+ This clock is monotonic.
\section2 SystemTime
@@ -159,26 +114,6 @@ QT_BEGIN_NAMESPACE
arbitrary point in the past. This clock type is used on Unix systems
which support POSIX monotonic clocks (\tt{_POSIX_MONOTONIC_CLOCK}).
- This clock does not overflow.
-
- \section2 TickCounter
-
- The tick counter clock type is based on the system's or the processor's
- tick counter, multiplied by the duration of a tick. This clock type is
- used on Windows platforms. If the high-precision performance
- counter is available on Windows, the \tt{PerformanceCounter} clock type
- is used instead.
-
- The TickCounter clock type is the only clock type that may overflow.
- Windows Vista and Windows Server 2008 support the extended 64-bit tick
- counter, which allows avoiding the overflow.
-
- On Windows systems, the clock overflows after 2^32 milliseconds, which
- corresponds to roughly 49.7 days. This means two processes' reckoning of
- the time since the reference may be different by multiples of 2^32
- milliseconds. When comparing such values, it's recommended that the high
- 32 bits of the millisecond count be masked off.
-
\section2 MachAbsoluteTime
This clock type is based on the absolute time presented by Mach kernels,
@@ -187,17 +122,14 @@ QT_BEGIN_NAMESPACE
a POSIX monotonic clock with values differing from the Mach absolute
time.
- This clock is monotonic and does not overflow.
+ This clock is monotonic.
\section2 PerformanceCounter
This clock uses the Windows functions \tt{QueryPerformanceCounter} and
- \tt{QueryPerformanceFrequency} to access the system's high-precision
- performance counter. Since this counter may not be available on all
- systems, QElapsedTimer will fall back to the \tt{TickCounter} clock
- automatically, if this clock cannot be used.
+ \tt{QueryPerformanceFrequency} to access the system's performance counter.
- This clock is monotonic and does not overflow.
+ This clock is monotonic.
\sa clockType(), isMonotonic()
*/
@@ -212,22 +144,250 @@ QT_BEGIN_NAMESPACE
\sa isValid(), start()
*/
+/*!
+ \fn bool QElapsedTimer::operator==(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ Returns \c true if \a lhs and \a rhs contain the same time, false otherwise.
+*/
/*!
- \fn bool QElapsedTimer::operator ==(const QElapsedTimer &other) const
+ \fn bool QElapsedTimer::operator!=(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
- Returns \c true if this object and \a other contain the same time.
+ Returns \c true if \a lhs and \a rhs contain different times, false otherwise.
+*/
+/*!
+ \fn bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ \relates QElapsedTimer
+
+ Returns \c true if \a lhs was started before \a rhs, false otherwise.
+
+ The returned value is undefined if one of the two parameters is invalid
+ and the other isn't. However, two invalid timers are equal and thus this
+ function will return false.
*/
/*!
- \fn bool QElapsedTimer::operator !=(const QElapsedTimer &other) const
+ \fn QElapsedTimer::clockType() noexcept
+
+ Returns the clock type that this QElapsedTimer implementation uses.
- Returns \c true if this object and \a other contain different times.
+ Since Qt 6.6, QElapsedTimer uses \c{std::chrono::steady_clock}, so the
+ clock type is always \l MonotonicClock.
+
+ \sa isMonotonic()
+*/
+
+QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
+{
+ // we use std::chrono::steady_clock
+ return MonotonicClock;
+}
+
+/*!
+ \fn QElapsedTimer::isMonotonic() noexcept
+
+ Returns \c true if this is a monotonic clock, false otherwise. See the
+ information on the different clock types to understand which ones are
+ monotonic.
+
+ Since Qt 6.6, QElapsedTimer uses \c{std::chrono::steady_clock}, so this
+ function now always returns true.
+
+ \sa clockType(), QElapsedTimer::ClockType
*/
+bool QElapsedTimer::isMonotonic() noexcept
+{
+ // We trust std::chrono::steady_clock to be steady (monotonic); if the
+ // Standard Library is lying to us, users must complain to their vendor.
+ return true;
+}
+
+/*!
+ \typealias QElapsedTimer::Duration
+ Synonym for \c std::chrono::nanoseconds.
+*/
+
+/*!
+ \typealias QElapsedTimer::TimePoint
+ Synonym for \c {std::chrono::time_point<std::chrono::steady_clock, Duration>}.
+*/
+
+/*!
+ Starts this timer. Once started, a timer value can be checked with elapsed() or msecsSinceReference().
+
+ Normally, a timer is started just before a lengthy operation, such as:
+ \snippet qelapsedtimer/main.cpp 0
+
+ Also, starting a timer makes it valid again.
+
+ \sa restart(), invalidate(), elapsed()
+*/
+void QElapsedTimer::start() noexcept
+{
+ static_assert(sizeof(t1) == sizeof(Duration::rep));
+
+ // This assignment will work so long as TimePoint uses the same time
+ // duration or one of finer granularity than steady_clock::time_point. That
+ // means it will work until the first steady_clock using picoseconds.
+ TimePoint now = std::chrono::steady_clock::now();
+ t1 = now.time_since_epoch().count();
+ QT6_ONLY(t2 = 0);
+}
+
+/*!
+ Restarts the timer and returns the number of milliseconds elapsed since
+ the previous start.
+ This function is equivalent to obtaining the elapsed time with elapsed()
+ and then starting the timer again with start(), but it does so in one
+ single operation, avoiding the need to obtain the clock value twice.
+
+ Calling this function on a QElapsedTimer that is invalid
+ results in undefined behavior.
+
+ The following example illustrates how to use this function to calibrate a
+ parameter to a slow operation (for example, an iteration count) so that
+ this operation takes at least 250 milliseconds:
+
+ \snippet qelapsedtimer/main.cpp 3
+
+ \sa start(), invalidate(), elapsed(), isValid()
+*/
+qint64 QElapsedTimer::restart() noexcept
+{
+ QElapsedTimer old = *this;
+ start();
+ return old.msecsTo(*this);
+}
+
+/*!
+ \since 6.6
+
+ Returns a \c{std::chrono::nanoseconds} with the time since this QElapsedTimer was last
+ started.
+
+ Calling this function on a QElapsedTimer that is invalid
+ results in undefined behavior.
+
+ On platforms that do not provide nanosecond resolution, the value returned
+ will be the best estimate available.
+
+ \sa start(), restart(), hasExpired(), invalidate()
+*/
+auto QElapsedTimer::durationElapsed() const noexcept -> Duration
+{
+ TimePoint then{Duration(t1)};
+ return std::chrono::steady_clock::now() - then;
+}
+
+/*!
+ \since 4.8
+
+ Returns the number of nanoseconds since this QElapsedTimer was last
+ started.
+
+ Calling this function on a QElapsedTimer that is invalid
+ results in undefined behavior.
+
+ On platforms that do not provide nanosecond resolution, the value returned
+ will be the best estimate available.
+
+ \sa start(), restart(), hasExpired(), invalidate()
+*/
+qint64 QElapsedTimer::nsecsElapsed() const noexcept
+{
+ return durationElapsed().count();
+}
+
+/*!
+ Returns the number of milliseconds since this QElapsedTimer was last
+ started.
+
+ Calling this function on a QElapsedTimer that is invalid
+ results in undefined behavior.
+
+ \sa start(), restart(), hasExpired(), isValid(), invalidate()
+*/
+qint64 QElapsedTimer::elapsed() const noexcept
+{
+ using namespace std::chrono;
+ return duration_cast<milliseconds>(durationElapsed()).count();
+}
+
+/*!
+ Returns the number of milliseconds between last time this QElapsedTimer
+ object was started and its reference clock's start.
+
+ This number is usually arbitrary for all clocks except the
+ QElapsedTimer::SystemTime clock. For that clock type, this number is the
+ number of milliseconds since January 1st, 1970 at 0:00 UTC (that is, it
+ is the Unix time expressed in milliseconds).
+
+ On Linux, Windows and Apple platforms, this value is usually the time
+ since the system boot, though it usually does not include the time the
+ system has spent in sleep states.
+
+ \sa clockType(), elapsed()
+*/
+qint64 QElapsedTimer::msecsSinceReference() const noexcept
+{
+ using namespace std::chrono;
+ return duration_cast<milliseconds>(Duration(t1)).count();
+}
+
+/*!
+ \since 6.6
+
+ Returns the time difference between this QElapsedTimer and \a other as a
+ \c{std::chrono::nanoseconds}. If \a other was started before this object,
+ the returned value will be negative. If it was started later, the returned
+ value will be positive.
+
+ The return value is undefined if this object or \a other were invalidated.
+
+ \sa secsTo(), elapsed()
+*/
+auto QElapsedTimer::durationTo(const QElapsedTimer &other) const noexcept -> Duration
+{
+ Duration d1(t1);
+ Duration d2(other.t1);
+ return d2 - d1;
+}
+
+/*!
+ Returns the number of milliseconds between this QElapsedTimer and \a
+ other. If \a other was started before this object, the returned value
+ will be negative. If it was started later, the returned value will be
+ positive.
+
+ The return value is undefined if this object or \a other were invalidated.
+
+ \sa secsTo(), elapsed()
+*/
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
+{
+ using namespace std::chrono;
+ return duration_cast<milliseconds>(durationTo(other)).count();
+}
+
+/*!
+ Returns the number of seconds between this QElapsedTimer and \a other. If
+ \a other was started before this object, the returned value will be
+ negative. If it was started later, the returned value will be positive.
+
+ Calling this function on or with a QElapsedTimer that is invalid
+ results in undefined behavior.
+
+ \sa msecsTo(), elapsed()
+*/
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
+{
+ using namespace std::chrono;
+ return duration_cast<seconds>(durationTo(other)).count();
+}
static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
/*!
+ \fn QElapsedTimer::invalidate() noexcept
Marks this QElapsedTimer object as invalid.
An invalid object can be checked with isValid(). Calculations of timer
@@ -238,7 +398,7 @@ static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
*/
void QElapsedTimer::invalidate() noexcept
{
- t1 = t2 = invalidData;
+ t1 = t2 = invalidData;
}
/*!
@@ -253,10 +413,12 @@ bool QElapsedTimer::isValid() const noexcept
}
/*!
- Returns \c true if this QElapsedTimer has already expired by \a timeout
- milliseconds (that is, more than \a timeout milliseconds have elapsed).
- The value of \a timeout can be -1 to indicate that this timer does not
- expire, in which case this function will always return false.
+ Returns \c true if elapsed() exceeds the given \a timeout, otherwise \c false.
+
+ A negative \a timeout is interpreted as infinite, so \c false is returned in
+ this case. Otherwise, this is equivalent to \c {elapsed() > timeout}. You
+ can do the same for a duration by comparing durationElapsed() to a duration
+ timeout.
\sa elapsed(), QDeadlineTimer
*/
@@ -267,4 +429,9 @@ bool QElapsedTimer::hasExpired(qint64 timeout) const noexcept
return quint64(elapsed()) > quint64(timeout);
}
+bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+{
+ return lhs.t1 < rhs.t1;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer.h b/src/corelib/kernel/qelapsedtimer.h
index 873847f6b6..7d8b889f61 100644
--- a/src/corelib/kernel/qelapsedtimer.h
+++ b/src/corelib/kernel/qelapsedtimer.h
@@ -1,49 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QELAPSEDTIMER_H
#define QELAPSEDTIMER_H
#include <QtCore/qglobal.h>
-QT_BEGIN_NAMESPACE
+#include <chrono>
+QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QElapsedTimer
{
@@ -51,16 +16,17 @@ public:
enum ClockType {
SystemTime,
MonotonicClock,
- TickCounter,
+ TickCounter Q_DECL_ENUMERATOR_DEPRECATED_X(
+ "Not supported anymore. Use PerformanceCounter instead."),
MachAbsoluteTime,
PerformanceCounter
};
- Q_DECL_CONSTEXPR QElapsedTimer()
- : t1(Q_INT64_C(0x8000000000000000)),
- t2(Q_INT64_C(0x8000000000000000))
- {
- }
+ // similar to std::chrono::*_clock
+ using Duration = std::chrono::nanoseconds;
+ using TimePoint = std::chrono::time_point<std::chrono::steady_clock, Duration>;
+
+ constexpr QElapsedTimer() = default;
static ClockType clockType() noexcept;
static bool isMonotonic() noexcept;
@@ -70,24 +36,26 @@ public:
void invalidate() noexcept;
bool isValid() const noexcept;
+ Duration durationElapsed() const noexcept;
qint64 nsecsElapsed() const noexcept;
qint64 elapsed() const noexcept;
bool hasExpired(qint64 timeout) const noexcept;
qint64 msecsSinceReference() const noexcept;
+ Duration durationTo(const QElapsedTimer &other) const noexcept;
qint64 msecsTo(const QElapsedTimer &other) const noexcept;
qint64 secsTo(const QElapsedTimer &other) const noexcept;
- bool operator==(const QElapsedTimer &other) const noexcept
- { return t1 == other.t1 && t2 == other.t2; }
- bool operator!=(const QElapsedTimer &other) const noexcept
- { return !(*this == other); }
+ friend bool operator==(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ { return lhs.t1 == rhs.t1 && lhs.t2 == rhs.t2; }
+ friend bool operator!=(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ { return !(lhs == rhs); }
- friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept;
+ friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept;
private:
- qint64 t1;
- qint64 t2;
+ qint64 t1 = Q_INT64_C(0x8000000000000000);
+ qint64 t2 = Q_INT64_C(0x8000000000000000);
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_generic.cpp b/src/corelib/kernel/qelapsedtimer_generic.cpp
deleted file mode 100644
index fe959e3c94..0000000000
--- a/src/corelib/kernel/qelapsedtimer_generic.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qelapsedtimer.h"
-#include "qdeadlinetimer.h"
-#include "qdatetime.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- Returns the clock type that this QElapsedTimer implementation uses.
-
- \sa isMonotonic()
-*/
-QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
-{
- return SystemTime;
-}
-
-/*!
- Returns \c true if this is a monotonic clock, false otherwise. See the
- information on the different clock types to understand which ones are
- monotonic.
-
- \sa clockType(), QElapsedTimer::ClockType
-*/
-bool QElapsedTimer::isMonotonic() noexcept
-{
- return false;
-}
-
-/*!
- Starts this timer. Once started, a timer value can be checked with elapsed() or msecsSinceReference().
-
- Normally, a timer is started just before a lengthy operation, such as:
- \snippet qelapsedtimer/main.cpp 0
-
- Also, starting a timer makes it valid again.
-
- \sa restart(), invalidate(), elapsed()
-*/
-void QElapsedTimer::start() noexcept
-{
- restart();
-}
-
-/*!
- Restarts the timer and returns the time elapsed since the previous start.
- This function is equivalent to obtaining the elapsed time with elapsed()
- and then starting the timer again with start(), but it does so in one
- single operation, avoiding the need to obtain the clock value twice.
-
- Calling this function on a QElapsedTimer that is invalid
- results in undefined behavior.
-
- The following example illustrates how to use this function to calibrate a
- parameter to a slow operation (for example, an iteration count) so that
- this operation takes at least 250 milliseconds:
-
- \snippet qelapsedtimer/main.cpp 3
-
- \sa start(), invalidate(), elapsed(), isValid()
-*/
-qint64 QElapsedTimer::restart() noexcept
-{
- qint64 old = t1;
- t1 = QDateTime::currentMSecsSinceEpoch();
- t2 = 0;
- return t1 - old;
-}
-
-/*! \since 4.8
-
- Returns the number of nanoseconds since this QElapsedTimer was last
- started.
-
- Calling this function on a QElapsedTimer that is invalid
- results in undefined behavior.
-
- On platforms that do not provide nanosecond resolution, the value returned
- will be the best estimate available.
-
- \sa start(), restart(), hasExpired(), invalidate()
-*/
-qint64 QElapsedTimer::nsecsElapsed() const noexcept
-{
- return elapsed() * 1000000;
-}
-
-/*!
- Returns the number of milliseconds since this QElapsedTimer was last
- started.
-
- Calling this function on a QElapsedTimer that is invalid
- results in undefined behavior.
-
- \sa start(), restart(), hasExpired(), isValid(), invalidate()
-*/
-qint64 QElapsedTimer::elapsed() const noexcept
-{
- return QDateTime::currentMSecsSinceEpoch() - t1;
-}
-
-/*!
- Returns the number of milliseconds between last time this QElapsedTimer
- object was started and its reference clock's start.
-
- This number is usually arbitrary for all clocks except the
- QElapsedTimer::SystemTime clock. For that clock type, this number is the
- number of milliseconds since January 1st, 1970 at 0:00 UTC (that is, it
- is the Unix time expressed in milliseconds).
-
- On Linux, Windows and Apple platforms, this value is usually the time
- since the system boot, though it usually does not include the time the
- system has spent in sleep states.
-
- \sa clockType(), elapsed()
-*/
-qint64 QElapsedTimer::msecsSinceReference() const noexcept
-{
- return t1;
-}
-
-/*!
- Returns the number of milliseconds between this QElapsedTimer and \a
- other. If \a other was started before this object, the returned value
- will be negative. If it was started later, the returned value will be
- positive.
-
- The return value is undefined if this object or \a other were invalidated.
-
- \sa secsTo(), elapsed()
-*/
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
-{
- qint64 diff = other.t1 - t1;
- return diff;
-}
-
-/*!
- Returns the number of seconds between this QElapsedTimer and \a other. If
- \a other was started before this object, the returned value will be
- negative. If it was started later, the returned value will be positive.
-
- Calling this function on or with a QElapsedTimer that is invalid
- results in undefined behavior.
-
- \sa msecsTo(), elapsed()
-*/
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
-{
- return msecsTo(other) / 1000;
-}
-
-/*!
- \relates QElapsedTimer
-
- Returns \c true if \a v1 was started before \a v2, false otherwise.
-
- The returned value is undefined if one of the two parameters is invalid
- and the other isn't. However, two invalid timers are equal and thus this
- function will return false.
-*/
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
-{
- return v1.t1 < v2.t1;
-}
-
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
-{
- QDeadlineTimer result;
- result.t1 = QDateTime::currentMSecsSinceEpoch() * 1000 * 1000;
- result.type = timerType;
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_mac.cpp b/src/corelib/kernel/qelapsedtimer_mac.cpp
deleted file mode 100644
index 1d9f02dff0..0000000000
--- a/src/corelib/kernel/qelapsedtimer_mac.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// ask for the latest POSIX, just in case
-#define _POSIX_C_SOURCE 200809L
-
-#include "qelapsedtimer.h"
-#include "qdeadlinetimer.h"
-#include "qdeadlinetimer_p.h"
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <mach/mach_time.h>
-#include <private/qcore_unix_p.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifdef __LP64__
-typedef __int128_t LargeInt;
-#else
-typedef qint64 LargeInt;
-#endif
-
-QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
-{
- return MachAbsoluteTime;
-}
-
-bool QElapsedTimer::isMonotonic() noexcept
-{
- return true;
-}
-
-static mach_timebase_info_data_t info = {0,0};
-static qint64 absoluteToNSecs(qint64 cpuTime)
-{
- if (info.denom == 0)
- mach_timebase_info(&info);
-
- // don't do multiplication & division if those are equal
- // (mathematically it would be the same, but it's computationally expensive)
- if (info.numer == info.denom)
- return cpuTime;
- qint64 nsecs = LargeInt(cpuTime) * info.numer / info.denom;
- return nsecs;
-}
-
-static qint64 absoluteToMSecs(qint64 cpuTime)
-{
- return absoluteToNSecs(cpuTime) / 1000000;
-}
-
-timespec qt_gettime() noexcept
-{
- timespec tv;
-
- uint64_t cpu_time = mach_absolute_time();
- uint64_t nsecs = absoluteToNSecs(cpu_time);
- tv.tv_sec = nsecs / 1000000000ull;
- tv.tv_nsec = nsecs - (tv.tv_sec * 1000000000ull);
- return tv;
-}
-
-void qt_nanosleep(timespec amount)
-{
- // Mac doesn't have clock_nanosleep, but it does have nanosleep.
- // nanosleep is POSIX.1-1993
-
- int r;
- EINTR_LOOP(r, nanosleep(&amount, &amount));
-}
-
-void QElapsedTimer::start() noexcept
-{
- t1 = mach_absolute_time();
- t2 = 0;
-}
-
-qint64 QElapsedTimer::restart() noexcept
-{
- qint64 old = t1;
- t1 = mach_absolute_time();
- t2 = 0;
-
- return absoluteToMSecs(t1 - old);
-}
-
-qint64 QElapsedTimer::nsecsElapsed() const noexcept
-{
- uint64_t cpu_time = mach_absolute_time();
- return absoluteToNSecs(cpu_time - t1);
-}
-
-qint64 QElapsedTimer::elapsed() const noexcept
-{
- uint64_t cpu_time = mach_absolute_time();
- return absoluteToMSecs(cpu_time - t1);
-}
-
-qint64 QElapsedTimer::msecsSinceReference() const noexcept
-{
- return absoluteToMSecs(t1);
-}
-
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
-{
- return absoluteToMSecs(other.t1 - t1);
-}
-
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
-{
- return msecsTo(other) / 1000;
-}
-
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
-{
- return v1.t1 < v2.t1;
-}
-
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
-{
- static_assert(!QDeadlineTimerNanosecondsInT2);
- QDeadlineTimer result;
- result.type = timerType;
- result.t1 = absoluteToNSecs(mach_absolute_time());
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_unix.cpp b/src/corelib/kernel/qelapsedtimer_unix.cpp
deleted file mode 100644
index 59f5f90155..0000000000
--- a/src/corelib/kernel/qelapsedtimer_unix.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qelapsedtimer.h"
-#include "qdeadlinetimer.h"
-#include "qdeadlinetimer_p.h"
-#if defined(Q_OS_VXWORKS)
-#include "qfunctions_vxworks.h"
-#else
-#include <sys/time.h>
-#include <time.h>
-#endif
-#include <unistd.h>
-
-#include <qatomic.h>
-#include "private/qcore_unix_p.h"
-
-#if defined(QT_NO_CLOCK_MONOTONIC) || defined(QT_BOOTSTRAPPED)
-// turn off the monotonic clock
-# ifdef _POSIX_MONOTONIC_CLOCK
-# undef _POSIX_MONOTONIC_CLOCK
-# endif
-# define _POSIX_MONOTONIC_CLOCK -1
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/*
- * Design:
- *
- * POSIX offers a facility to select the system's monotonic clock when getting
- * the current timestamp. Whereas the functions are mandatory in POSIX.1-2008,
- * the presence of a monotonic clock is a POSIX Option (see the document
- * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_06 )
- *
- * The macro _POSIX_MONOTONIC_CLOCK can therefore assume the following values:
- * -1 monotonic clock is never supported on this system
- * 0 monotonic clock might be supported, runtime check is needed
- * >1 (such as 200809L) monotonic clock is always supported
- *
- * The unixCheckClockType() function will return the clock to use: either
- * CLOCK_MONOTONIC or CLOCK_REALTIME. In the case the POSIX option has a value
- * of zero, then this function stores a static that contains the clock to be
- * used.
- *
- * There's one extra case, which is when CLOCK_REALTIME isn't defined. When
- * that's the case, we'll emulate the clock_gettime function with gettimeofday.
- *
- * Conforming to:
- * POSIX.1b-1993 section "Clocks and Timers"
- * included in UNIX98 (Single Unix Specification v2)
- * included in POSIX.1-2001
- * see http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html
- */
-
-#if !defined(CLOCK_REALTIME)
-# define CLOCK_REALTIME 0
-static inline void qt_clock_gettime(int, struct timespec *ts)
-{
- // support clock_gettime with gettimeofday
- struct timeval tv;
- gettimeofday(&tv, 0);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
-}
-
-# ifdef _POSIX_MONOTONIC_CLOCK
-# undef _POSIX_MONOTONIC_CLOCK
-# define _POSIX_MONOTONIC_CLOCK -1
-# endif
-#else
-static inline void qt_clock_gettime(clockid_t clock, struct timespec *ts)
-{
- clock_gettime(clock, ts);
-}
-#endif
-
-static int unixCheckClockType()
-{
-#ifdef Q_OS_LINUX
- // Despite glibc claiming that we should check at runtime, the Linux kernel
- // always supports the monotonic clock
- return CLOCK_MONOTONIC;
-#elif (_POSIX_MONOTONIC_CLOCK-0 == 0) && defined(_SC_MONOTONIC_CLOCK)
- // we need a value we can store in a clockid_t that isn't a valid clock
- // check if the valid ones are both non-negative or both non-positive
-# if CLOCK_MONOTONIC >= 0 && CLOCK_REALTIME >= 0
-# define IS_VALID_CLOCK(clock) (clock >= 0)
-# define INVALID_CLOCK -1
-# elif CLOCK_MONOTONIC <= 0 && CLOCK_REALTIME <= 0
-# define IS_VALID_CLOCK(clock) (clock <= 0)
-# define INVALID_CLOCK 1
-# else
-# error "Sorry, your system has weird values for CLOCK_MONOTONIC and CLOCK_REALTIME"
-# endif
-
- static QBasicAtomicInt clockToUse = Q_BASIC_ATOMIC_INITIALIZER(INVALID_CLOCK);
- int clock = clockToUse.loadAcquire();
- if (Q_LIKELY(IS_VALID_CLOCK(clock)))
- return clock;
-
- // detect if the system supports monotonic timers
- clock = sysconf(_SC_MONOTONIC_CLOCK) > 0 ? CLOCK_MONOTONIC : CLOCK_REALTIME;
- clockToUse.storeRelease(clock);
- return clock;
-
-# undef INVALID_CLOCK
-# undef IS_VALID_CLOCK
-#elif (_POSIX_MONOTONIC_CLOCK-0) > 0
- return CLOCK_MONOTONIC;
-#else
- return CLOCK_REALTIME;
-#endif
-}
-
-bool QElapsedTimer::isMonotonic() noexcept
-{
- return clockType() == MonotonicClock;
-}
-
-QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
-{
- return unixCheckClockType() == CLOCK_REALTIME ? SystemTime : MonotonicClock;
-}
-
-static inline void do_gettime(qint64 *sec, qint64 *frac)
-{
- timespec ts;
- qt_clock_gettime(unixCheckClockType(), &ts);
- *sec = ts.tv_sec;
- *frac = ts.tv_nsec;
-}
-
-// used in qcore_unix.cpp and qeventdispatcher_unix.cpp
-struct timespec qt_gettime() noexcept
-{
- qint64 sec, frac;
- do_gettime(&sec, &frac);
-
- timespec tv;
- tv.tv_sec = sec;
- tv.tv_nsec = frac;
-
- return tv;
-}
-
-void qt_nanosleep(timespec amount)
-{
- // We'd like to use clock_nanosleep.
- //
- // But clock_nanosleep is from POSIX.1-2001 and both are *not*
- // affected by clock changes when using relative sleeps, even for
- // CLOCK_REALTIME.
- //
- // nanosleep is POSIX.1-1993
-
- int r;
- EINTR_LOOP(r, nanosleep(&amount, &amount));
-}
-
-static qint64 elapsedAndRestart(qint64 sec, qint64 frac,
- qint64 *nowsec, qint64 *nowfrac)
-{
- do_gettime(nowsec, nowfrac);
- sec = *nowsec - sec;
- frac = *nowfrac - frac;
- return (sec * Q_INT64_C(1000000000) + frac) / Q_INT64_C(1000000);
-}
-
-void QElapsedTimer::start() noexcept
-{
- do_gettime(&t1, &t2);
-}
-
-qint64 QElapsedTimer::restart() noexcept
-{
- return elapsedAndRestart(t1, t2, &t1, &t2);
-}
-
-qint64 QElapsedTimer::nsecsElapsed() const noexcept
-{
- qint64 sec, frac;
- do_gettime(&sec, &frac);
- sec = sec - t1;
- frac = frac - t2;
- return sec * Q_INT64_C(1000000000) + frac;
-}
-
-qint64 QElapsedTimer::elapsed() const noexcept
-{
- return nsecsElapsed() / Q_INT64_C(1000000);
-}
-
-qint64 QElapsedTimer::msecsSinceReference() const noexcept
-{
- return t1 * Q_INT64_C(1000) + t2 / Q_INT64_C(1000000);
-}
-
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
-{
- qint64 secs = other.t1 - t1;
- qint64 fraction = other.t2 - t2;
- return (secs * Q_INT64_C(1000000000) + fraction) / Q_INT64_C(1000000);
-}
-
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
-{
- return other.t1 - t1;
-}
-
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
-{
- return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
-}
-
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
-{
- static_assert(QDeadlineTimerNanosecondsInT2);
- QDeadlineTimer result;
- qint64 cursec, curnsec;
- do_gettime(&cursec, &curnsec);
- result.t1 = cursec;
- result.t2 = curnsec;
- result.type = timerType;
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp
deleted file mode 100644
index deeeb05921..0000000000
--- a/src/corelib/kernel/qelapsedtimer_win.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qelapsedtimer.h"
-#include "qdeadlinetimer.h"
-#include "qdeadlinetimer_p.h"
-#include <qt_windows.h>
-
-QT_BEGIN_NAMESPACE
-
-// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable
-static quint64 counterFrequency = 0;
-
-static void resolveCounterFrequency()
-{
- static bool done = false;
- if (done)
- return;
-
- // Retrieve the number of high-resolution performance counter ticks per second
- LARGE_INTEGER frequency;
- if (!QueryPerformanceFrequency(&frequency)) {
- qFatal("QueryPerformanceFrequency failed, even though Microsoft documentation promises it wouldn't.");
- counterFrequency = 0;
- } else {
- counterFrequency = frequency.QuadPart;
- }
-
- done = true;
-}
-
-static inline qint64 ticksToNanoseconds(qint64 ticks)
-{
- if (counterFrequency > 0) {
- // QueryPerformanceCounter uses an arbitrary frequency
- qint64 seconds = ticks / counterFrequency;
- qint64 nanoSeconds = (ticks - seconds * counterFrequency) * 1000000000 / counterFrequency;
- return seconds * 1000000000 + nanoSeconds;
- }
- // GetTickCount(64) returns milliseconds
- return ticks * 1000000;
-}
-
-
-static quint64 getTickCount()
-{
- resolveCounterFrequency();
-
- // This avoids a division by zero and disables the high performance counter if it's not available
- if (counterFrequency > 0) {
- LARGE_INTEGER counter;
-
- bool ok = QueryPerformanceCounter(&counter);
- Q_ASSERT_X(ok, "QElapsedTimer::start()",
- "QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded.");
- Q_UNUSED(ok);
- return counter.QuadPart;
- }
-
- return GetTickCount64();
-}
-
-quint64 qt_msectime()
-{
- return ticksToNanoseconds(getTickCount()) / 1000000;
-}
-
-QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
-{
- resolveCounterFrequency();
-
- return counterFrequency > 0 ? PerformanceCounter : TickCounter;
-}
-
-bool QElapsedTimer::isMonotonic() noexcept
-{
- return true;
-}
-
-void QElapsedTimer::start() noexcept
-{
- t1 = getTickCount();
- t2 = 0;
-}
-
-qint64 QElapsedTimer::restart() noexcept
-{
- qint64 oldt1 = t1;
- t1 = getTickCount();
- t2 = 0;
- return ticksToNanoseconds(t1 - oldt1) / 1000000;
-}
-
-qint64 QElapsedTimer::nsecsElapsed() const noexcept
-{
- qint64 elapsed = getTickCount() - t1;
- return ticksToNanoseconds(elapsed);
-}
-
-qint64 QElapsedTimer::elapsed() const noexcept
-{
- qint64 elapsed = getTickCount() - t1;
- return ticksToNanoseconds(elapsed) / 1000000;
-}
-
-qint64 QElapsedTimer::msecsSinceReference() const noexcept
-{
- return ticksToNanoseconds(t1) / 1000000;
-}
-
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
-{
- qint64 difference = other.t1 - t1;
- return ticksToNanoseconds(difference) / 1000000;
-}
-
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
-{
- return msecsTo(other) / 1000;
-}
-
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
-{
- return (v1.t1 - v2.t1) < 0;
-}
-
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
-{
- static_assert(!QDeadlineTimerNanosecondsInT2);
- QDeadlineTimer result;
- result.t1 = ticksToNanoseconds(getTickCount());
- result.type = timerType;
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index b482269df2..042b0651f4 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeventdispatcher_cf_p.h"
@@ -89,7 +53,7 @@ QT_USE_NAMESPACE
QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker);
-@implementation RunLoopModeTracker {
+@implementation QT_MANGLE_NAMESPACE(RunLoopModeTracker) {
QStack<CFStringRef> m_runLoopModes;
}
@@ -205,7 +169,7 @@ static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<C
#pragma mark - Class definition
QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
- : QAbstractEventDispatcher(parent)
+ : QAbstractEventDispatcherV2(parent)
, m_processEvents(QEventLoop::EventLoopExec)
, m_postedEventsRunLoopSource(this, &QEventDispatcherCoreFoundation::processPostedEvents)
, m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity, kCFRunLoopAllActivities)
@@ -231,7 +195,7 @@ void QEventDispatcherCoreFoundation::startingUp()
QEventDispatcherCoreFoundation::~QEventDispatcherCoreFoundation()
{
invalidateTimer();
- qDeleteAll(m_timerInfoList);
+ m_timerInfoList.clearTimers();
m_cfSocketNotifier.removeSocketNotifiers();
}
@@ -259,8 +223,7 @@ QEventLoop *QEventDispatcherCoreFoundation::currentEventLoop() const
function should wait only if there were no events ready,
and _then_ process all newly queued/available events.
- These notes apply to other function in this class as well, such as
- hasPendingEvents().
+ These notes apply to other function in this class as well.
*/
bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags)
{
@@ -282,7 +245,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
}
if (m_processEvents.deferredWakeUp) {
- // We may be processing events recursivly as a result of processing a posted event,
+ // We may be processing events recursively as a result of processing a posted event,
// in which case we need to signal the run-loop source so that this iteration of
// processEvents will take care of the newly posted events.
m_postedEventsRunLoopSource.signal();
@@ -367,7 +330,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
// to do another pass.
// But we should only wait for more events the first time
- m_processEvents.flags &= ~QEventLoop::WaitForMoreEvents;
+ m_processEvents.flags &= ~int(QEventLoop::WaitForMoreEvents);
continue;
} else if (m_overdueTimerScheduled && !m_processEvents.processedTimers) {
@@ -499,21 +462,6 @@ void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity act
}
}
-bool QEventDispatcherCoreFoundation::hasPendingEvents()
-{
- // There doesn't seem to be any API on iOS to peek into the other sources
- // to figure out if there are pending non-Qt events. As a workaround, we
- // assume that if the run-loop is currently blocking and waiting for a
- // source to signal then there are no system-events pending. If this
- // function is called from the main thread then the second clause
- // of the condition will always be true, as the run loop is
- // never waiting in that case. The function would be more aptly named
- // 'maybeHasPendingEvents' in our case.
-
- extern uint qGlobalPostedEventsCount();
- return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(m_runLoop);
-}
-
void QEventDispatcherCoreFoundation::wakeUp()
{
if (m_processEvents.processedPostedEvents && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
@@ -544,11 +492,6 @@ void QEventDispatcherCoreFoundation::interrupt()
CFRunLoopStop(m_runLoop);
}
-void QEventDispatcherCoreFoundation::flush()
-{
- // X11 only.
-}
-
#pragma mark - Socket notifiers
void QEventDispatcherCoreFoundation::registerSocketNotifier(QSocketNotifier *notifier)
@@ -563,26 +506,28 @@ void QEventDispatcherCoreFoundation::unregisterSocketNotifier(QSocketNotifier *n
#pragma mark - Timers
-void QEventDispatcherCoreFoundation::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+void QEventDispatcherCoreFoundation::registerTimer(Qt::TimerId timerId, Duration interval,
+ Qt::TimerType timerType, QObject *object)
{
- qCDebug(lcEventDispatcherTimers) << "Registering timer with id =" << timerId << "interval =" << interval
+ qCDebug(lcEventDispatcherTimers) << "Registering timer with id =" << int(timerId) << "interval =" << interval
<< "type =" << timerType << "object =" << object;
- Q_ASSERT(timerId > 0 && interval >= 0 && object);
+ Q_ASSERT(qToUnderlying(timerId) > 0 && interval.count() >= 0 && object);
Q_ASSERT(object->thread() == thread() && thread() == QThread::currentThread());
m_timerInfoList.registerTimer(timerId, interval, timerType, object);
updateTimers();
}
-bool QEventDispatcherCoreFoundation::unregisterTimer(int timerId)
+bool QEventDispatcherCoreFoundation::unregisterTimer(Qt::TimerId timerId)
{
- Q_ASSERT(timerId > 0);
+ Q_ASSERT(qToUnderlying(timerId) > 0);
Q_ASSERT(thread() == QThread::currentThread());
bool returnValue = m_timerInfoList.unregisterTimer(timerId);
- qCDebug(lcEventDispatcherTimers) << "Unegistered timer with id =" << timerId << "Timers left:" << m_timerInfoList.size();
+ qCDebug(lcEventDispatcherTimers) << "Unegistered timer with id =" << qToUnderlying(timerId)
+ << "Timers left:" << m_timerInfoList.size();
updateTimers();
return returnValue;
@@ -600,22 +545,18 @@ bool QEventDispatcherCoreFoundation::unregisterTimers(QObject *object)
return returnValue;
}
-QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherCoreFoundation::registeredTimers(QObject *object) const
+QList<QAbstractEventDispatcher::TimerInfoV2>
+QEventDispatcherCoreFoundation::timersForObject(QObject *object) const
{
Q_ASSERT(object);
return m_timerInfoList.registeredTimers(object);
}
-int QEventDispatcherCoreFoundation::remainingTime(int timerId)
-{
- Q_ASSERT(timerId > 0);
- return m_timerInfoList.timerRemainingTime(timerId);
-}
-
-static double timespecToSeconds(const timespec &spec)
+QEventDispatcherCoreFoundation::Duration
+QEventDispatcherCoreFoundation::remainingTime(Qt::TimerId timerId) const
{
- static double nanosecondsPerSecond = 1.0 * 1000 * 1000 * 1000;
- return spec.tv_sec + (spec.tv_nsec / nanosecondsPerSecond);
+ Q_ASSERT(qToUnderlying(timerId) > 0);
+ return m_timerInfoList.remainingDuration(timerId);
}
void QEventDispatcherCoreFoundation::updateTimers()
@@ -623,12 +564,20 @@ void QEventDispatcherCoreFoundation::updateTimers()
if (m_timerInfoList.size() > 0) {
// We have Qt timers registered, so create or reschedule CF timer to match
- timespec tv = { -1, -1 };
- CFAbsoluteTime timeToFire = m_timerInfoList.timerWait(tv) ?
+ using namespace std::chrono_literals;
+ using DoubleSeconds = std::chrono::duration<double, std::ratio<1>>;
+
+ CFAbsoluteTime timeToFire;
+ auto opt = m_timerInfoList.timerWait();
+ DoubleSeconds secs{};
+ if (opt) {
// We have a timer ready to fire right now, or some time in the future
- CFAbsoluteTimeGetCurrent() + timespecToSeconds(tv)
+ secs = DoubleSeconds{*opt};
+ timeToFire = CFAbsoluteTimeGetCurrent() + secs.count();
+ } else {
// We have timers, but they are all currently blocked by callbacks
- : kCFTimeIntervalDistantFuture;
+ timeToFire = kCFTimeIntervalDistantFuture;
+ }
if (!m_runLoopTimer) {
m_runLoopTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault,
@@ -644,9 +593,9 @@ void QEventDispatcherCoreFoundation::updateTimers()
qCDebug(lcEventDispatcherTimers) << "Re-scheduled CFRunLoopTimer" << m_runLoopTimer;
}
- m_overdueTimerScheduled = !timespecToSeconds(tv);
+ m_overdueTimerScheduled = secs > 0s;
- qCDebug(lcEventDispatcherTimers) << "Next timeout in" << tv << "seconds";
+ qCDebug(lcEventDispatcherTimers) << "Next timeout in" << secs;
} else {
// No Qt timers are registered, so make sure we're not running any CF timers
@@ -668,7 +617,7 @@ void QEventDispatcherCoreFoundation::invalidateTimer()
m_runLoopTimer = 0;
}
+QT_END_NAMESPACE
+
#include "qeventdispatcher_cf.moc"
#include "moc_qeventdispatcher_cf_p.cpp"
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h
index a2cecd9a93..3575a6fb39 100644
--- a/src/corelib/kernel/qeventdispatcher_cf_p.h
+++ b/src/corelib/kernel/qeventdispatcher_cf_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/****************************************************************************
**
@@ -99,8 +63,8 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker));
QT_BEGIN_NAMESPACE
namespace QtPrivate {
-Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
-Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcEventDispatcher, Q_CORE_EXPORT)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcEventDispatcherTimers, Q_CORE_EXPORT)
}
class QEventDispatcherCoreFoundation;
@@ -204,31 +168,29 @@ private:
CFRunLoopObserverRef m_observer;
};
-class Q_CORE_EXPORT QEventDispatcherCoreFoundation : public QAbstractEventDispatcher
+class Q_CORE_EXPORT QEventDispatcherCoreFoundation : public QAbstractEventDispatcherV2
{
Q_OBJECT
public:
- explicit QEventDispatcherCoreFoundation(QObject *parent = 0);
+ explicit QEventDispatcherCoreFoundation(QObject *parent = nullptr);
void startingUp() override;
~QEventDispatcherCoreFoundation();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
- bool hasPendingEvents() override;
void registerSocketNotifier(QSocketNotifier *notifier) override;
void unregisterSocketNotifier(QSocketNotifier *notifier) override;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) override;
- bool unregisterTimer(int timerId) override;
- bool unregisterTimers(QObject *object) override;
- QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const override;
-
- int remainingTime(int timerId) override;
+ void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType,
+ QObject *object) override final;
+ bool unregisterTimer(Qt::TimerId timerId) override final;
+ bool unregisterTimers(QObject *object) override final;
+ QList<TimerInfoV2> timersForObject(QObject *object) const override final;
+ Duration remainingTime(Qt::TimerId timerId) const override final;
void wakeUp() override;
void interrupt() override;
- void flush() override;
protected:
QEventLoop *currentEventLoop() const;
@@ -238,10 +200,29 @@ protected:
struct ProcessEventsState
{
ProcessEventsState(QEventLoop::ProcessEventsFlags f)
- : flags(f), wasInterrupted(false)
+ : flags(f.toInt()), wasInterrupted(false)
, processedPostedEvents(false), processedTimers(false)
, deferredWakeUp(false), deferredUpdateTimers(false) {}
+ ProcessEventsState(const ProcessEventsState &other)
+ : flags(other.flags.loadAcquire())
+ , wasInterrupted(other.wasInterrupted.loadAcquire())
+ , processedPostedEvents(other.processedPostedEvents.loadAcquire())
+ , processedTimers(other.processedTimers.loadAcquire())
+ , deferredWakeUp(other.deferredWakeUp.loadAcquire())
+ , deferredUpdateTimers(other.deferredUpdateTimers) {}
+
+ ProcessEventsState &operator=(const ProcessEventsState &other)
+ {
+ flags.storeRelease(other.flags.loadAcquire());
+ wasInterrupted.storeRelease(other.wasInterrupted.loadAcquire());
+ processedPostedEvents.storeRelease(other.processedPostedEvents.loadAcquire());
+ processedTimers.storeRelease(other.processedTimers.loadAcquire());
+ deferredWakeUp.storeRelease(other.deferredWakeUp.loadAcquire());
+ deferredUpdateTimers = other.deferredUpdateTimers;
+ return *this;
+ }
+
QAtomicInt flags;
QAtomicInteger<char> wasInterrupted;
QAtomicInteger<char> processedPostedEvents;
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 92f3553247..1e906c4b27 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -1,55 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeventdispatcher_glib_p.h"
#include "qeventdispatcher_unix_p.h"
+#include <private/qnumeric_p.h>
#include <private/qthread_p.h>
#include "qcoreapplication.h"
#include "qsocketnotifier.h"
#include <QtCore/qlist.h>
-#include <QtCore/qpair.h>
#include <glib.h>
+using namespace std::chrono;
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
struct GPollFDWithQSocketNotifier
@@ -62,6 +29,7 @@ struct GSocketNotifierSource
{
GSource source;
QList<GPollFDWithQSocketNotifier *> pollfds;
+ int activeNotifierPos;
};
static gboolean socketNotifierSourcePrepare(GSource *, gint *timeout)
@@ -76,12 +44,12 @@ static gboolean socketNotifierSourceCheck(GSource *source)
GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source);
bool pending = false;
- for (int i = 0; !pending && i < src->pollfds.count(); ++i) {
+ for (int i = 0; !pending && i < src->pollfds.size(); ++i) {
GPollFDWithQSocketNotifier *p = src->pollfds.at(i);
if (p->pollfd.revents & G_IO_NVAL) {
// disable the invalid socket notifier
- static const char *t[] = { "Read", "Write", "Exception" };
+ const char * const t[] = { "Read", "Write", "Exception" };
qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
p->pollfd.fd, t[int(p->socketNotifier->type())]);
// ### note, modifies src->pollfds!
@@ -100,8 +68,9 @@ static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpoin
QEvent event(QEvent::SockAct);
GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source);
- for (int i = 0; i < src->pollfds.count(); ++i) {
- GPollFDWithQSocketNotifier *p = src->pollfds.at(i);
+ for (src->activeNotifierPos = 0; src->activeNotifierPos < src->pollfds.size();
+ ++src->activeNotifierPos) {
+ GPollFDWithQSocketNotifier *p = src->pollfds.at(src->activeNotifierPos);
if ((p->pollfd.revents & p->pollfd.events) != 0)
QCoreApplication::sendEvent(p->socketNotifier, &event);
@@ -110,7 +79,7 @@ static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpoin
return true; // ??? don't remove, right?
}
-static GSourceFuncs socketNotifierSourceFuncs = {
+Q_CONSTINIT static GSourceFuncs socketNotifierSourceFuncs = {
socketNotifierSourcePrepare,
socketNotifierSourceCheck,
socketNotifierSourceDispatch,
@@ -129,11 +98,13 @@ struct GTimerSource
static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout)
{
- timespec tv = { 0l, 0l };
- if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv))
- *timeout = (tv.tv_sec * 1000) + ((tv.tv_nsec + 999999) / 1000 / 1000);
- else
+ if (src->processEventsFlags & QEventLoop::X11ExcludeTimers) {
*timeout = -1;
+ return true;
+ }
+
+ auto remaining = src->timerList.timerWait().value_or(-1ms);
+ *timeout = qt_saturate<gint>(ceil<milliseconds>(remaining).count());
return (*timeout == 0);
}
@@ -144,10 +115,7 @@ static gboolean timerSourceCheckHelper(GTimerSource *src)
|| (src->processEventsFlags & QEventLoop::X11ExcludeTimers))
return false;
- if (src->timerList.updateCurrentTime() < src->timerList.constFirst()->timeout)
- return false;
-
- return true;
+ return !src->timerList.hasPendingTimers();
}
static gboolean timerSourcePrepare(GSource *source, gint *timeout)
@@ -184,7 +152,7 @@ static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer)
return true; // ??? don't remove, right again?
}
-static GSourceFuncs timerSourceFuncs = {
+Q_CONSTINIT static GSourceFuncs timerSourceFuncs = {
timerSourcePrepare,
timerSourceCheck,
timerSourceDispatch,
@@ -231,7 +199,7 @@ static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer)
return true;
}
-static GSourceFuncs idleTimerSourceFuncs = {
+Q_CONSTINIT static GSourceFuncs idleTimerSourceFuncs = {
idleTimerSourcePrepare,
idleTimerSourceCheck,
idleTimerSourceDispatch,
@@ -279,7 +247,7 @@ static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer)
return true; // i dunno, george...
}
-static GSourceFuncs postEventSourceFuncs = {
+Q_CONSTINIT static GSourceFuncs postEventSourceFuncs = {
postEventSourcePrepare,
postEventSourceCheck,
postEventSourceDispatch,
@@ -294,7 +262,7 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
{
#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32
if (qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")) {
- static QBasicMutex mutex;
+ Q_CONSTINIT static QBasicMutex mutex;
QMutexLocker locker(&mutex);
if (!g_thread_supported())
g_thread_init(NULL);
@@ -318,32 +286,36 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
#endif
// setup post event source
- postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
- sizeof(GPostEventSource)));
+ GSource *source = g_source_new(&postEventSourceFuncs, sizeof(GPostEventSource));
+ g_source_set_name(source, "[Qt] GPostEventSource");
+ postEventSource = reinterpret_cast<GPostEventSource *>(source);
+
postEventSource->serialNumber.storeRelaxed(1);
postEventSource->d = this;
g_source_set_can_recurse(&postEventSource->source, true);
g_source_attach(&postEventSource->source, mainContext);
// setup socketNotifierSource
- socketNotifierSource =
- reinterpret_cast<GSocketNotifierSource *>(g_source_new(&socketNotifierSourceFuncs,
- sizeof(GSocketNotifierSource)));
+ source = g_source_new(&socketNotifierSourceFuncs, sizeof(GSocketNotifierSource));
+ g_source_set_name(source, "[Qt] GSocketNotifierSource");
+ socketNotifierSource = reinterpret_cast<GSocketNotifierSource *>(source);
(void) new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>();
g_source_set_can_recurse(&socketNotifierSource->source, true);
g_source_attach(&socketNotifierSource->source, mainContext);
// setup normal and idle timer sources
- timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs,
- sizeof(GTimerSource)));
+ source = g_source_new(&timerSourceFuncs, sizeof(GTimerSource));
+ g_source_set_name(source, "[Qt] GTimerSource");
+ timerSource = reinterpret_cast<GTimerSource *>(source);
(void) new (&timerSource->timerList) QTimerInfoList();
timerSource->processEventsFlags = QEventLoop::AllEvents;
timerSource->runWithIdlePriority = false;
g_source_set_can_recurse(&timerSource->source, true);
g_source_attach(&timerSource->source, mainContext);
- idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs,
- sizeof(GIdleTimerSource)));
+ source = g_source_new(&idleTimerSourceFuncs, sizeof(GIdleTimerSource));
+ g_source_set_name(source, "[Qt] GIdleTimerSource");
+ idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
idleTimerSource->timerSource = timerSource;
g_source_set_can_recurse(&idleTimerSource->source, true);
g_source_attach(&idleTimerSource->source, mainContext);
@@ -355,12 +327,12 @@ void QEventDispatcherGlibPrivate::runTimersOnceWithNormalPriority()
}
QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent)
- : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate), parent)
+ : QAbstractEventDispatcherV2(*(new QEventDispatcherGlibPrivate), parent)
{
}
QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent)
- : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent)
+ : QAbstractEventDispatcherV2(*(new QEventDispatcherGlibPrivate(mainContext)), parent)
{ }
QEventDispatcherGlib::~QEventDispatcherGlib()
@@ -368,7 +340,7 @@ QEventDispatcherGlib::~QEventDispatcherGlib()
Q_D(QEventDispatcherGlib);
// destroy all timer sources
- qDeleteAll(d->timerSource->timerList);
+ d->timerSource->timerList.clearTimers();
d->timerSource->timerList.~QTimerInfoList();
g_source_destroy(&d->timerSource->source);
g_source_unref(&d->timerSource->source);
@@ -378,7 +350,7 @@ QEventDispatcherGlib::~QEventDispatcherGlib()
d->idleTimerSource = nullptr;
// destroy socket notifier source
- for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
+ for (int i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds[i];
g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
delete p;
@@ -405,7 +377,7 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherGlib);
- const bool canWait = (flags & QEventLoop::WaitForMoreEvents);
+ const bool canWait = flags.testAnyFlag(QEventLoop::WaitForMoreEvents);
if (canWait)
emit aboutToBlock();
else
@@ -432,16 +404,10 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
return result;
}
-bool QEventDispatcherGlib::hasPendingEvents()
-{
- Q_D(QEventDispatcherGlib);
- return g_main_context_pending(d->mainContext);
-}
-
void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier)
{
Q_ASSERT(notifier);
- int sockfd = notifier->socket();
+ int sockfd = int(notifier->socket());
int type = notifier->type();
#ifndef QT_NO_DEBUG
if (sockfd < 0) {
@@ -481,8 +447,7 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
{
Q_ASSERT(notifier);
#ifndef QT_NO_DEBUG
- int sockfd = notifier->socket();
- if (sockfd < 0) {
+ if (notifier->socket() < 0) {
qWarning("QSocketNotifier: Internal error");
return;
} else if (notifier->thread() != thread()
@@ -494,7 +459,7 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
Q_D(QEventDispatcherGlib);
- for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
+ for (int i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
if (p->socketNotifier == notifier) {
// found it
@@ -503,15 +468,20 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
d->socketNotifierSource->pollfds.removeAt(i);
delete p;
+ // Keep a position in the list for the next item.
+ if (i <= d->socketNotifierSource->activeNotifierPos)
+ --d->socketNotifierSource->activeNotifierPos;
+
return;
}
}
}
-void QEventDispatcherGlib::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+void QEventDispatcherGlib::registerTimer(Qt::TimerId timerId, Duration interval,
+ Qt::TimerType timerType, QObject *object)
{
#ifndef QT_NO_DEBUG
- if (timerId < 1 || interval < 0 || !object) {
+ if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) {
qWarning("QEventDispatcherGlib::registerTimer: invalid arguments");
return;
} else if (object->thread() != thread() || thread() != QThread::currentThread()) {
@@ -524,10 +494,10 @@ void QEventDispatcherGlib::registerTimer(int timerId, int interval, Qt::TimerTyp
d->timerSource->timerList.registerTimer(timerId, interval, timerType, object);
}
-bool QEventDispatcherGlib::unregisterTimer(int timerId)
+bool QEventDispatcherGlib::unregisterTimer(Qt::TimerId timerId)
{
#ifndef QT_NO_DEBUG
- if (timerId < 1) {
+ if (qToUnderlying(timerId) < 1) {
qWarning("QEventDispatcherGlib::unregisterTimer: invalid argument");
return false;
} else if (thread() != QThread::currentThread()) {
@@ -556,28 +526,30 @@ bool QEventDispatcherGlib::unregisterTimers(QObject *object)
return d->timerSource->timerList.unregisterTimers(object);
}
-QList<QEventDispatcherGlib::TimerInfo> QEventDispatcherGlib::registeredTimers(QObject *object) const
+QList<QEventDispatcherGlib::TimerInfoV2> QEventDispatcherGlib::timersForObject(QObject *object) const
{
+#ifndef QT_NO_DEBUG
if (!object) {
- qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
- return QList<TimerInfo>();
+ qWarning("QEventDispatcherGlib:timersForObject: invalid argument");
+ return {};
}
+#endif
Q_D(const QEventDispatcherGlib);
return d->timerSource->timerList.registeredTimers(object);
}
-int QEventDispatcherGlib::remainingTime(int timerId)
+QEventDispatcherGlib::Duration QEventDispatcherGlib::remainingTime(Qt::TimerId timerId) const
{
#ifndef QT_NO_DEBUG
- if (timerId < 1) {
+ if (qToUnderlying(timerId) < 1) {
qWarning("QEventDispatcherGlib::remainingTimeTime: invalid argument");
- return -1;
+ return Duration::min();
}
#endif
- Q_D(QEventDispatcherGlib);
- return d->timerSource->timerList.timerRemainingTime(timerId);
+ Q_D(const QEventDispatcherGlib);
+ return d->timerSource->timerList.remainingDuration(timerId);
}
void QEventDispatcherGlib::interrupt()
@@ -592,10 +564,6 @@ void QEventDispatcherGlib::wakeUp()
g_main_context_wakeup(d->mainContext);
}
-void QEventDispatcherGlib::flush()
-{
-}
-
bool QEventDispatcherGlib::versionSupported()
{
#if !defined(GLIB_MAJOR_VERSION) || !defined(GLIB_MINOR_VERSION) || !defined(GLIB_MICRO_VERSION)
@@ -606,7 +574,7 @@ bool QEventDispatcherGlib::versionSupported()
}
QEventDispatcherGlib::QEventDispatcherGlib(QEventDispatcherGlibPrivate &dd, QObject *parent)
- : QAbstractEventDispatcher(dd, parent)
+ : QAbstractEventDispatcherV2(dd, parent)
{
}
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
index 313825d0a7..30783d3858 100644
--- a/src/corelib/kernel/qeventdispatcher_glib_p.h
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTDISPATCHER_GLIB_P_H
#define QEVENTDISPATCHER_GLIB_P_H
@@ -60,7 +24,7 @@ QT_BEGIN_NAMESPACE
class QEventDispatcherGlibPrivate;
-class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher
+class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcherV2
{
Q_OBJECT
Q_DECLARE_PRIVATE(QEventDispatcherGlib)
@@ -71,21 +35,19 @@ public:
~QEventDispatcherGlib();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
- bool hasPendingEvents() override;
void registerSocketNotifier(QSocketNotifier *socketNotifier) final;
void unregisterSocketNotifier(QSocketNotifier *socketNotifier) final;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) final;
- bool unregisterTimer(int timerId) final;
- bool unregisterTimers(QObject *object) final;
- QList<TimerInfo> registeredTimers(QObject *object) const final;
-
- int remainingTime(int timerId) final;
+ void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType,
+ QObject *object) override final;
+ bool unregisterTimer(Qt::TimerId timerId) override final;
+ bool unregisterTimers(QObject *object) override final;
+ QList<TimerInfoV2> timersForObject(QObject *object) const override final;
+ Duration remainingTime(Qt::TimerId timerId) const override final;
void wakeUp() final;
void interrupt() final;
- void flush() final;
static bool versionSupported();
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index 0165ce9075..21bd224415 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -1,50 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qcoreapplication.h"
-#include "qpair.h"
+#include "qhash.h"
#include "qsocketnotifier.h"
#include "qthread.h"
-#include "qelapsedtimer.h"
#include "qeventdispatcher_unix_p.h"
#include <private/qthread_p.h>
@@ -55,23 +18,19 @@
#include <stdio.h>
#include <stdlib.h>
-#ifndef QT_NO_EVENTFD
+#if __has_include(<sys/eventfd.h>)
# include <sys/eventfd.h>
+static constexpr bool UsingEventfd = true;
+#else
+static constexpr bool UsingEventfd = false;
#endif
-// VxWorks doesn't correctly set the _POSIX_... options
#if defined(Q_OS_VXWORKS)
-# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0)
-# undef _POSIX_MONOTONIC_CLOCK
-# define _POSIX_MONOTONIC_CLOCK 1
-# endif
# include <pipeDrv.h>
-# include <sys/time.h>
#endif
-#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
-# include <sys/times.h>
-#endif
+using namespace std::chrono;
+using namespace std::chrono_literals;
QT_BEGIN_NAMESPACE
@@ -91,11 +50,6 @@ static const char *socketType(QSocketNotifier::Type type)
QThreadPipe::QThreadPipe()
{
- fds[0] = -1;
- fds[1] = -1;
-#if defined(Q_OS_VXWORKS)
- name[0] = '\0';
-#endif
}
QThreadPipe::~QThreadPipe()
@@ -103,7 +57,7 @@ QThreadPipe::~QThreadPipe()
if (fds[0] >= 0)
close(fds[0]);
- if (fds[1] >= 0)
+ if (!UsingEventfd && fds[1] >= 0)
close(fds[1]);
#if defined(Q_OS_VXWORKS)
@@ -130,8 +84,8 @@ static void initThreadPipeFD(int fd)
bool QThreadPipe::init()
{
-#if defined(Q_OS_NACL) || defined(Q_OS_WASM)
- // do nothing.
+#if defined(Q_OS_WASM)
+ // do nothing.
#elif defined(Q_OS_VXWORKS)
qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
@@ -140,23 +94,25 @@ bool QThreadPipe::init()
// create the pipe
if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
- perror("QThreadPipe: Unable to create thread pipe device %s", name);
+ perror("QThreadPipe: Unable to create thread pipe device");
return false;
}
if ((fds[0] = open(name, O_RDWR, 0)) < 0) {
- perror("QThreadPipe: Unable to open pipe device %s", name);
+ perror("QThreadPipe: Unable to open pipe device");
return false;
}
initThreadPipeFD(fds[0]);
fds[1] = fds[0];
#else
-# ifndef QT_NO_EVENTFD
- if ((fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)) >= 0)
- return true;
+ int ret;
+# ifdef EFD_CLOEXEC
+ ret = fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
# endif
- if (qt_safe_pipe(fds, O_NONBLOCK) == -1) {
+ if (!UsingEventfd)
+ ret = qt_safe_pipe(fds, O_NONBLOCK);
+ if (ret == -1) {
perror("QThreadPipe: Unable to create pipe");
return false;
}
@@ -172,15 +128,10 @@ pollfd QThreadPipe::prepare() const
void QThreadPipe::wakeUp()
{
- if (wakeUps.testAndSetAcquire(0, 1)) {
-#ifndef QT_NO_EVENTFD
- if (fds[1] == -1) {
- // eventfd
- eventfd_t value = 1;
- int ret;
- EINTR_LOOP(ret, eventfd_write(fds[0], value));
- return;
- }
+ if ((wakeUps.fetchAndOrAcquire(1) & 1) == 0) {
+# ifdef EFD_CLOEXEC
+ eventfd_write(fds[0], 1);
+ return;
#endif
char c = 0;
qt_safe_write(fds[1], &c, 1);
@@ -201,14 +152,11 @@ int QThreadPipe::check(const pollfd &pfd)
::read(fds[0], c, sizeof(c));
::ioctl(fds[0], FIOFLUSH, 0);
#else
-# ifndef QT_NO_EVENTFD
- if (fds[1] == -1) {
- // eventfd
- eventfd_t value;
- eventfd_read(fds[0], &value);
- } else
+# ifdef EFD_CLOEXEC
+ eventfd_t value;
+ eventfd_read(fds[0], &value);
# endif
- {
+ if (!UsingEventfd) {
while (::read(fds[0], c, sizeof(c)) > 0) {}
}
#endif
@@ -231,7 +179,7 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
{
// cleanup timers
- qDeleteAll(timerList);
+ timerList.clearTimers();
}
void QEventDispatcherUNIXPrivate::setSocketNotifierPending(QSocketNotifier *notifier)
@@ -251,7 +199,7 @@ int QEventDispatcherUNIXPrivate::activateTimers()
void QEventDispatcherUNIXPrivate::markPendingSocketNotifiers()
{
- for (const pollfd &pfd : qAsConst(pollfds)) {
+ for (const pollfd &pfd : std::as_const(pollfds)) {
if (pfd.fd < 0 || pfd.revents == 0)
continue;
@@ -309,11 +257,11 @@ int QEventDispatcherUNIXPrivate::activateSocketNotifiers()
}
QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent)
- : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent)
+ : QAbstractEventDispatcherV2(*new QEventDispatcherUNIXPrivate, parent)
{ }
QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent)
- : QAbstractEventDispatcher(dd, parent)
+ : QAbstractEventDispatcherV2(dd, parent)
{ }
QEventDispatcherUNIX::~QEventDispatcherUNIX()
@@ -322,10 +270,10 @@ QEventDispatcherUNIX::~QEventDispatcherUNIX()
/*!
\internal
*/
-void QEventDispatcherUNIX::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *obj)
+void QEventDispatcherUNIX::registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *obj)
{
#ifndef QT_NO_DEBUG
- if (timerId < 1 || interval < 0 || !obj) {
+ if (qToUnderlying(timerId) < 1 || interval.count() < 0 || !obj) {
qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments");
return;
} else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
@@ -341,10 +289,10 @@ void QEventDispatcherUNIX::registerTimer(int timerId, int interval, Qt::TimerTyp
/*!
\internal
*/
-bool QEventDispatcherUNIX::unregisterTimer(int timerId)
+bool QEventDispatcherUNIX::unregisterTimer(Qt::TimerId timerId)
{
#ifndef QT_NO_DEBUG
- if (timerId < 1) {
+ if (qToUnderlying(timerId) < 1) {
qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument");
return false;
} else if (thread() != QThread::currentThread()) {
@@ -376,12 +324,12 @@ bool QEventDispatcherUNIX::unregisterTimers(QObject *object)
return d->timerList.unregisterTimers(object);
}
-QList<QEventDispatcherUNIX::TimerInfo>
-QEventDispatcherUNIX::registeredTimers(QObject *object) const
+QList<QEventDispatcherUNIX::TimerInfoV2>
+QEventDispatcherUNIX::timersForObject(QObject *object) const
{
if (!object) {
qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
- return QList<TimerInfo>();
+ return QList<TimerInfoV2>();
}
Q_D(const QEventDispatcherUNIX);
@@ -469,7 +417,7 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
const bool include_timers = (flags & QEventLoop::X11ExcludeTimers) == 0;
const bool include_notifiers = (flags & QEventLoop::ExcludeSocketNotifiers) == 0;
- const bool wait_for_events = flags & QEventLoop::WaitForMoreEvents;
+ const bool wait_for_events = (flags & QEventLoop::WaitForMoreEvents) != 0;
const bool canWait = (threadData->canWaitLocked()
&& !d->interrupt.loadRelaxed()
@@ -481,11 +429,19 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
if (d->interrupt.loadRelaxed())
return false;
- timespec *tm = nullptr;
- timespec wait_tm = { 0, 0 };
-
- if (!canWait || (include_timers && d->timerList.timerWait(wait_tm)))
- tm = &wait_tm;
+ QDeadlineTimer deadline;
+ if (canWait) {
+ if (include_timers) {
+ std::optional<nanoseconds> remaining = d->timerList.timerWait();
+ deadline = remaining ? QDeadlineTimer{*remaining}
+ : QDeadlineTimer(QDeadlineTimer::Forever);
+ } else {
+ deadline = QDeadlineTimer(QDeadlineTimer::Forever);
+ }
+ } else {
+ // Using the default-constructed `deadline`, which is already expired,
+ // ensures the code in the do-while loop in qt_safe_poll runs at least once.
+ }
d->pollfds.clear();
d->pollfds.reserve(1 + (include_notifiers ? d->socketNotifiers.size() : 0));
@@ -498,10 +454,11 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
d->pollfds.append(d->threadPipe.prepare());
int nevents = 0;
-
- switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), tm)) {
+ switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), deadline)) {
case -1:
- perror("qt_safe_poll");
+ qErrnoWarning("qt_safe_poll");
+ if (QT_CONFIG(poll_exit_on_error))
+ abort();
break;
case 0:
break;
@@ -519,23 +476,17 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
return (nevents > 0);
}
-bool QEventDispatcherUNIX::hasPendingEvents()
-{
- extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
- return qGlobalPostedEventsCount();
-}
-
-int QEventDispatcherUNIX::remainingTime(int timerId)
+auto QEventDispatcherUNIX::remainingTime(Qt::TimerId timerId) const -> Duration
{
#ifndef QT_NO_DEBUG
- if (timerId < 1) {
+ if (int(timerId) < 1) {
qWarning("QEventDispatcherUNIX::remainingTime: invalid argument");
- return -1;
+ return Duration::min();
}
#endif
- Q_D(QEventDispatcherUNIX);
- return d->timerList.timerRemainingTime(timerId);
+ Q_D(const QEventDispatcherUNIX);
+ return d->timerList.remainingDuration(timerId);
}
void QEventDispatcherUNIX::wakeUp()
@@ -551,9 +502,6 @@ void QEventDispatcherUNIX::interrupt()
wakeUp();
}
-void QEventDispatcherUNIX::flush()
-{ }
-
QT_END_NAMESPACE
#include "moc_qeventdispatcher_unix_p.cpp"
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 5757cc764c..6596e998c9 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTDISPATCHER_UNIX_P_H
#define QEVENTDISPATCHER_UNIX_P_H
@@ -56,6 +20,7 @@
#include "private/qabstracteventdispatcher_p.h"
#include "private/qcore_unix_p.h"
#include "QtCore/qvarlengtharray.h"
+#include "QtCore/qhash.h"
#include "private/qtimerinfo_unix_p.h"
QT_BEGIN_NAMESPACE
@@ -86,17 +51,17 @@ struct QThreadPipe
int check(const pollfd &pfd);
// note for eventfd(7) support:
- // if fds[1] is -1, then eventfd(7) is in use and is stored in fds[0]
- int fds[2];
+ // fds[0] stores the eventfd, fds[1] is unused
+ int fds[2] = { -1, -1 };
QAtomicInt wakeUps;
#if defined(Q_OS_VXWORKS)
- static const int len_name = 20;
- char name[len_name];
+ static constexpr int len_name = 20;
+ char name[len_name] = {};
#endif
};
-class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
+class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcherV2
{
Q_OBJECT
Q_DECLARE_PRIVATE(QEventDispatcherUNIX)
@@ -106,21 +71,19 @@ public:
~QEventDispatcherUNIX();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
- bool hasPendingEvents() override;
void registerSocketNotifier(QSocketNotifier *notifier) final;
void unregisterSocketNotifier(QSocketNotifier *notifier) final;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) final;
- bool unregisterTimer(int timerId) final;
- bool unregisterTimers(QObject *object) final;
- QList<TimerInfo> registeredTimers(QObject *object) const final;
-
- int remainingTime(int timerId) final;
+ void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType,
+ QObject *object) override final;
+ bool unregisterTimer(Qt::TimerId timerId) override final;
+ bool unregisterTimers(QObject *object) override final;
+ QList<TimerInfoV2> timersForObject(QObject *object) const override final;
+ Duration remainingTime(Qt::TimerId timerId) const override final;
void wakeUp() override;
void interrupt() final;
- void flush() override;
protected:
QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = nullptr);
diff --git a/src/corelib/kernel/qeventdispatcher_wasm.cpp b/src/corelib/kernel/qeventdispatcher_wasm.cpp
new file mode 100644
index 0000000000..4aa435b64b
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp
@@ -0,0 +1,1000 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qeventdispatcher_wasm_p.h"
+
+#include <QtCore/private/qabstracteventdispatcher_p.h> // for qGlobalPostedEventsCount()
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/private/qstdweb_p.h>
+
+#include "emscripten.h"
+#include <emscripten/html5.h>
+#include <emscripten/threading.h>
+#include <emscripten/val.h>
+
+using namespace std::chrono;
+using namespace std::chrono_literals;
+
+QT_BEGIN_NAMESPACE
+
+// using namespace emscripten;
+
+Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher");
+Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers");
+
+#if QT_CONFIG(thread)
+#define LOCK_GUARD(M) std::lock_guard<std::mutex> lock(M)
+#else
+#define LOCK_GUARD(M)
+#endif
+
+// Emscripten asyncify currently supports one level of suspend -
+// recursion is not permitted. We track the suspend state here
+// on order to fail (more) gracefully, but we can of course only
+// track Qts own usage of asyncify.
+static bool g_is_asyncify_suspended = false;
+
+#if defined(QT_STATIC)
+
+static bool useAsyncify()
+{
+ return qstdweb::haveAsyncify();
+}
+
+static bool useJspi()
+{
+ return qstdweb::haveJspi();
+}
+
+// clang-format off
+EM_ASYNC_JS(void, qt_jspi_suspend_js, (), {
+ ++Module.qtJspiSuspensionCounter;
+
+ await new Promise(resolve => {
+ Module.qtAsyncifyWakeUp.push(resolve);
+ });
+});
+
+EM_JS(bool, qt_jspi_resume_js, (), {
+ if (!Module.qtJspiSuspensionCounter)
+ return false;
+
+ --Module.qtJspiSuspensionCounter;
+
+ setTimeout(() => {
+ const wakeUp = (Module.qtAsyncifyWakeUp ?? []).pop();
+ if (wakeUp) wakeUp();
+ });
+ return true;
+});
+
+EM_JS(bool, qt_jspi_can_resume_js, (), {
+ return Module.qtJspiSuspensionCounter > 0;
+});
+
+EM_JS(void, init_jspi_support_js, (), {
+ Module.qtAsyncifyWakeUp = [];
+ Module.qtJspiSuspensionCounter = 0;
+});
+// clang-format on
+
+void initJspiSupport() {
+ init_jspi_support_js();
+}
+
+Q_CONSTRUCTOR_FUNCTION(initJspiSupport);
+
+// clang-format off
+EM_JS(void, qt_asyncify_suspend_js, (), {
+ if (Module.qtSuspendId === undefined)
+ Module.qtSuspendId = 0;
+ let sleepFn = (wakeUp) => {
+ Module.qtAsyncifyWakeUp = wakeUp;
+ };
+ ++Module.qtSuspendId;
+ return Asyncify.handleSleep(sleepFn);
+});
+
+EM_JS(void, qt_asyncify_resume_js, (), {
+ let wakeUp = Module.qtAsyncifyWakeUp;
+ if (wakeUp == undefined)
+ return;
+ Module.qtAsyncifyWakeUp = undefined;
+ const suspendId = Module.qtSuspendId;
+
+ // Delayed wakeup with zero-timer. Workaround/fix for
+ // https://github.com/emscripten-core/emscripten/issues/10515
+ setTimeout(() => {
+ // Another suspend occurred while the timeout was in queue.
+ if (Module.qtSuspendId !== suspendId)
+ return;
+ wakeUp();
+ });
+});
+// clang-format on
+
+#else
+
+// EM_JS is not supported for side modules; disable asyncify
+
+static bool useAsyncify()
+{
+ return false;
+}
+
+static bool useJspi()
+{
+ return false;
+}
+
+void qt_jspi_suspend_js()
+{
+ Q_UNREACHABLE();
+}
+
+bool qt_jspi_resume_js()
+{
+ Q_UNREACHABLE();
+ return false;
+}
+
+bool qt_jspi_can_resume_js()
+{
+ Q_UNREACHABLE();
+ return false;
+}
+
+void qt_asyncify_suspend_js()
+{
+ Q_UNREACHABLE();
+}
+
+void qt_asyncify_resume_js()
+{
+ Q_UNREACHABLE();
+}
+
+#endif // defined(QT_STATIC)
+
+// Suspends the main thread until qt_asyncify_resume() is called. Returns
+// false immediately if Qt has already suspended the main thread (recursive
+// suspend is not supported by Emscripten). Returns true (after resuming),
+// if the thread was suspended.
+bool qt_asyncify_suspend()
+{
+ if (g_is_asyncify_suspended)
+ return false;
+ g_is_asyncify_suspended = true;
+ qt_asyncify_suspend_js();
+ return true;
+}
+
+// Wakes any currently suspended main thread. Returns true if the main
+// thread was suspended, in which case it will now be asynchronously woken.
+void qt_asyncify_resume()
+{
+ if (!g_is_asyncify_suspended)
+ return;
+ g_is_asyncify_suspended = false;
+ qt_asyncify_resume_js();
+}
+
+
+Q_CONSTINIT QEventDispatcherWasm *QEventDispatcherWasm::g_mainThreadEventDispatcher = nullptr;
+#if QT_CONFIG(thread)
+Q_CONSTINIT QVector<QEventDispatcherWasm *> QEventDispatcherWasm::g_secondaryThreadEventDispatchers;
+Q_CONSTINIT std::mutex QEventDispatcherWasm::g_staticDataMutex;
+emscripten::ProxyingQueue QEventDispatcherWasm::g_proxyingQueue;
+pthread_t QEventDispatcherWasm::g_mainThread;
+#endif
+// ### dynamic initialization:
+std::multimap<int, QSocketNotifier *> QEventDispatcherWasm::g_socketNotifiers;
+std::map<int, QEventDispatcherWasm::SocketReadyState> QEventDispatcherWasm::g_socketState;
+
+QEventDispatcherWasm::QEventDispatcherWasm()
+{
+ // QEventDispatcherWasm operates in two main modes:
+ // - On the main thread:
+ // The event dispatcher can process native events but can't
+ // block and wait for new events, unless asyncify is used.
+ // - On a secondary thread:
+ // The event dispatcher can't process native events but can
+ // block and wait for new events.
+ //
+ // Which mode is determined by the calling thread: construct
+ // the event dispatcher object on the thread where it will live.
+
+ qCDebug(lcEventDispatcher) << "Creating QEventDispatcherWasm instance" << this
+ << "is main thread" << emscripten_is_main_runtime_thread();
+
+ if (emscripten_is_main_runtime_thread()) {
+ // There can be only one main thread event dispatcher at a time; in
+ // addition the main instance is used by the secondary thread event
+ // dispatchers so we set a global pointer to it.
+ Q_ASSERT(g_mainThreadEventDispatcher == nullptr);
+ g_mainThreadEventDispatcher = this;
+#if QT_CONFIG(thread)
+ g_mainThread = pthread_self();
+#endif
+
+ // Call the "onLoaded" JavaScript callback, unless startup tasks
+ // have been registered which should complete first. Run async
+ // to make sure event dispatcher construction (in particular any
+ // subclass construction) has completed first.
+ runAsync(callOnLoadedIfRequired);
+ } else {
+#if QT_CONFIG(thread)
+ std::lock_guard<std::mutex> lock(g_staticDataMutex);
+ g_secondaryThreadEventDispatchers.append(this);
+#endif
+ }
+}
+
+QEventDispatcherWasm::~QEventDispatcherWasm()
+{
+ qCDebug(lcEventDispatcher) << "Destroying QEventDispatcherWasm instance" << this;
+
+ delete m_timerInfo;
+
+#if QT_CONFIG(thread)
+ if (isSecondaryThreadEventDispatcher()) {
+ std::lock_guard<std::mutex> lock(g_staticDataMutex);
+ g_secondaryThreadEventDispatchers.remove(g_secondaryThreadEventDispatchers.indexOf(this));
+ } else
+#endif
+ {
+ if (m_timerId > 0)
+ emscripten_clear_timeout(m_timerId);
+ if (!g_socketNotifiers.empty()) {
+ qWarning("QEventDispatcherWasm: main thread event dispatcher deleted with active socket notifiers");
+ clearEmscriptenSocketCallbacks();
+ g_socketNotifiers.clear();
+ }
+ g_mainThreadEventDispatcher = nullptr;
+ if (!g_socketNotifiers.empty()) {
+ qWarning("QEventDispatcherWasm: main thread event dispatcher deleted with active socket notifiers");
+ clearEmscriptenSocketCallbacks();
+ g_socketNotifiers.clear();
+ }
+
+ g_socketState.clear();
+ }
+}
+
+bool QEventDispatcherWasm::isMainThreadEventDispatcher()
+{
+ return this == g_mainThreadEventDispatcher;
+}
+
+bool QEventDispatcherWasm::isSecondaryThreadEventDispatcher()
+{
+ return this != g_mainThreadEventDispatcher;
+}
+
+bool QEventDispatcherWasm::isValidEventDispatcherPointer(QEventDispatcherWasm *eventDispatcher)
+{
+ if (eventDispatcher == g_mainThreadEventDispatcher)
+ return true;
+#if QT_CONFIG(thread)
+ if (g_secondaryThreadEventDispatchers.contains(eventDispatcher))
+ return true;
+#endif
+ return false;
+}
+
+bool QEventDispatcherWasm::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ qCDebug(lcEventDispatcher) << "QEventDispatcherWasm::processEvents flags" << flags;
+
+ emit awake();
+
+ if (isMainThreadEventDispatcher()) {
+ if (flags & QEventLoop::DialogExec)
+ handleDialogExec();
+ else if (flags & QEventLoop::ApplicationExec)
+ handleApplicationExec();
+ }
+
+#if QT_CONFIG(thread)
+ {
+ // Reset wakeUp state: if wakeUp() was called at some point before
+ // this then processPostedEvents() below will service that call.
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_wakeUpCalled = false;
+ }
+#endif
+
+ processPostedEvents();
+
+ // The processPostedEvents() call above may process an event which deletes the
+ // application object and the event dispatcher; stop event processing in that case.
+ if (!isValidEventDispatcherPointer(this))
+ return false;
+
+ if (m_interrupted) {
+ m_interrupted = false;
+ return false;
+ }
+
+ if (flags & QEventLoop::WaitForMoreEvents)
+ wait();
+
+ if (m_processTimers) {
+ m_processTimers = false;
+ processTimers();
+ }
+
+ return false;
+}
+
+void QEventDispatcherWasm::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ LOCK_GUARD(g_staticDataMutex);
+
+ bool wasEmpty = g_socketNotifiers.empty();
+ g_socketNotifiers.insert({notifier->socket(), notifier});
+ if (wasEmpty)
+ runOnMainThread([] { setEmscriptenSocketCallbacks(); });
+}
+
+void QEventDispatcherWasm::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ LOCK_GUARD(g_staticDataMutex);
+
+ auto notifiers = g_socketNotifiers.equal_range(notifier->socket());
+ for (auto it = notifiers.first; it != notifiers.second; ++it) {
+ if (it->second == notifier) {
+ g_socketNotifiers.erase(it);
+ break;
+ }
+ }
+
+ if (g_socketNotifiers.empty())
+ runOnMainThread([] { clearEmscriptenSocketCallbacks(); });
+}
+
+void QEventDispatcherWasm::registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) {
+ qWarning("QEventDispatcherWasm::registerTimer: invalid arguments");
+ return;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QEventDispatcherWasm::registerTimer: timers cannot be started from another "
+ "thread");
+ return;
+ }
+#endif
+ qCDebug(lcEventDispatcherTimers) << "registerTimer" << int(timerId) << interval << timerType << object;
+
+ m_timerInfo->registerTimer(timerId, interval, timerType, object);
+ updateNativeTimer();
+}
+
+bool QEventDispatcherWasm::unregisterTimer(Qt::TimerId timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (qToUnderlying(timerId) < 1) {
+ qWarning("QEventDispatcherWasm::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QEventDispatcherWasm::unregisterTimer: timers cannot be stopped from another "
+ "thread");
+ return false;
+ }
+#endif
+
+ qCDebug(lcEventDispatcherTimers) << "unregisterTimer" << int(timerId);
+
+ bool ans = m_timerInfo->unregisterTimer(timerId);
+ updateNativeTimer();
+ return ans;
+}
+
+bool QEventDispatcherWasm::unregisterTimers(QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QEventDispatcherWasm::unregisterTimers: invalid argument");
+ return false;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QEventDispatcherWasm::unregisterTimers: timers cannot be stopped from another "
+ "thread");
+ return false;
+ }
+#endif
+
+ qCDebug(lcEventDispatcherTimers) << "registerTimer" << object;
+
+ bool ans = m_timerInfo->unregisterTimers(object);
+ updateNativeTimer();
+ return ans;
+}
+
+QList<QAbstractEventDispatcher::TimerInfoV2>
+QEventDispatcherWasm::timersForObject(QObject *object) const
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QEventDispatcherWasm:registeredTimers: invalid argument");
+ return {};
+ }
+#endif
+
+ return m_timerInfo->registeredTimers(object);
+}
+
+QEventDispatcherWasm::Duration QEventDispatcherWasm::remainingTime(Qt::TimerId timerId) const
+{
+ return m_timerInfo->remainingDuration(timerId);
+}
+
+void QEventDispatcherWasm::interrupt()
+{
+ m_interrupted = true;
+ wakeUp();
+}
+
+void QEventDispatcherWasm::wakeUp()
+{
+ // The event dispatcher thread may be blocked or suspended by
+ // wait(), or control may have been returned to the browser's
+ // event loop. Make sure the thread is unblocked or make it
+ // process events.
+ bool wasBlocked = wakeEventDispatcherThread();
+ // JSPI does not need a scheduled call to processPostedEvents, as the stack is not unwound
+ // at startup.
+ if (!qstdweb::haveJspi() && !wasBlocked && isMainThreadEventDispatcher()) {
+ {
+ LOCK_GUARD(m_mutex);
+ if (m_pendingProcessEvents)
+ return;
+ m_pendingProcessEvents = true;
+ }
+ runOnMainThreadAsync([this](){
+ QEventDispatcherWasm::callProcessPostedEvents(this);
+ });
+ }
+}
+
+void QEventDispatcherWasm::handleApplicationExec()
+{
+ // Start the main loop, and then stop it on the first callback. This
+ // is done for the "simulateInfiniteLoop" functionality where
+ // emscripten_set_main_loop() throws a JS exception which returns
+ // control to the browser while preserving the C++ stack.
+ //
+ // Note that we don't use asyncify here: Emscripten supports one level of
+ // asyncify only and we want to reserve that for dialog exec() instead of
+ // using it for the one qApp exec().
+ // When JSPI is used, awaited async calls are allowed to be nested, so we
+ // proceed normally.
+ if (!qstdweb::haveJspi()) {
+ const bool simulateInfiniteLoop = true;
+ emscripten_set_main_loop([](){
+ emscripten_pause_main_loop();
+ }, 0, simulateInfiniteLoop);
+ }
+}
+
+void QEventDispatcherWasm::handleDialogExec()
+{
+ if (!useAsyncify()) {
+ qWarning() << "Warning: exec() is not supported on Qt for WebAssembly in this configuration. Please build"
+ << "with asyncify support, or use an asynchronous API like QDialog::open()";
+ emscripten_sleep(1); // This call never returns
+ }
+ // For the asyncify case we do nothing here and wait for events in wait()
+}
+
+// Blocks/suspends the calling thread. This is possible in two cases:
+// - Caller is a secondary thread: block on m_moreEvents
+// - Caller is the main thread and asyncify is enabled: suspend using qt_asyncify_suspend()
+// Returns false if the wait timed out.
+bool QEventDispatcherWasm::wait(int timeout)
+{
+#if QT_CONFIG(thread)
+ using namespace std::chrono_literals;
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ if (isSecondaryThreadEventDispatcher()) {
+ std::unique_lock<std::mutex> lock(m_mutex);
+
+ // If wakeUp() was called there might be pending events in the event
+ // queue which should be processed. Don't block, instead return
+ // so that the event loop can spin and call processEvents() again.
+ if (m_wakeUpCalled)
+ return true;
+
+ auto wait_time = timeout > 0 ? timeout * 1ms : std::chrono::duration<int, std::micro>::max();
+ bool wakeUpCalled = m_moreEvents.wait_for(lock, wait_time, [=] { return m_wakeUpCalled; });
+ return wakeUpCalled;
+ }
+#endif
+ Q_ASSERT(emscripten_is_main_runtime_thread());
+ Q_ASSERT(isMainThreadEventDispatcher());
+ if (useAsyncify()) {
+ if (timeout > 0)
+ qWarning() << "QEventDispatcherWasm asyncify wait with timeout is not supported; timeout will be ignored"; // FIXME
+
+ if (useJspi()) {
+ qt_jspi_suspend_js();
+ } else {
+ bool didSuspend = qt_asyncify_suspend();
+ if (!didSuspend) {
+ qWarning("QEventDispatcherWasm: current thread is already suspended; could not asyncify wait for events");
+ return false;
+ }
+ }
+ return true;
+ } else {
+ qWarning("QEventLoop::WaitForMoreEvents is not supported on the main thread without asyncify");
+ Q_UNUSED(timeout);
+ }
+ return false;
+}
+
+// Wakes a blocked/suspended event dispatcher thread. Returns true if the
+// thread is unblocked or was resumed, false if the thread state could not
+// be determined.
+bool QEventDispatcherWasm::wakeEventDispatcherThread()
+{
+#if QT_CONFIG(thread)
+ if (isSecondaryThreadEventDispatcher()) {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ m_wakeUpCalled = true;
+ m_moreEvents.notify_one();
+ return true;
+ }
+#endif
+ Q_ASSERT(isMainThreadEventDispatcher());
+ if (useJspi()) {
+
+#if QT_CONFIG(thread)
+ return qstdweb::runTaskOnMainThread<bool>(
+ []() { return qt_jspi_can_resume_js() && qt_jspi_resume_js(); }, &g_proxyingQueue);
+#else
+ return qstdweb::runTaskOnMainThread<bool>(
+ []() { return qt_jspi_can_resume_js() && qt_jspi_resume_js(); });
+#endif
+
+ } else {
+ if (!g_is_asyncify_suspended)
+ return false;
+ runOnMainThread([]() { qt_asyncify_resume(); });
+ }
+ return true;
+}
+
+// Process event activation callbacks for the main thread event dispatcher.
+// Must be called on the main thread.
+void QEventDispatcherWasm::callProcessPostedEvents(void *context)
+{
+ Q_ASSERT(emscripten_is_main_runtime_thread());
+
+ // Bail out if Qt has been shut down.
+ if (!g_mainThreadEventDispatcher)
+ return;
+
+ // In the unlikely event that we get a callProcessPostedEvents() call for
+ // a previous main thread event dispatcher (i.e. the QApplication
+ // object was deleted and created again): just ignore it and return.
+ if (context != g_mainThreadEventDispatcher)
+ return;
+
+ {
+ LOCK_GUARD(g_mainThreadEventDispatcher->m_mutex);
+ g_mainThreadEventDispatcher->m_pendingProcessEvents = false;
+ }
+
+ g_mainThreadEventDispatcher->processPostedEvents();
+}
+
+bool QEventDispatcherWasm::processPostedEvents()
+{
+ QCoreApplication::sendPostedEvents();
+ return false;
+}
+
+void QEventDispatcherWasm::processTimers()
+{
+ m_timerInfo->activateTimers();
+ updateNativeTimer(); // schedule next native timer, if any
+}
+
+// Updates the native timer based on currently registered Qt timers.
+// Must be called on the event dispatcher thread.
+void QEventDispatcherWasm::updateNativeTimer()
+{
+#if QT_CONFIG(thread)
+ Q_ASSERT(QThread::currentThread() == thread());
+#endif
+
+ // Multiplex Qt timers down to a single native timer, maintained
+ // to have a timeout corresponding to the shortest Qt timer. This
+ // is done in two steps: first determine the target wakeup time
+ // on the event dispatcher thread (since this thread has exclusive
+ // access to m_timerInfo), and then call native API to set the new
+ // wakeup time on the main thread.
+
+ const std::optional<std::chrono::nanoseconds> wait = m_timerInfo->timerWait();
+ const auto toWaitDuration = duration_cast<milliseconds>(wait.value_or(0ms));
+ const auto newTargetTimePoint = m_timerInfo->currentTime + toWaitDuration;
+ auto epochNsecs = newTargetTimePoint.time_since_epoch();
+ auto newTargetTime = std::chrono::duration_cast<std::chrono::milliseconds>(epochNsecs);
+ auto maintainNativeTimer = [this, wait, toWaitDuration, newTargetTime]() {
+ Q_ASSERT(emscripten_is_main_runtime_thread());
+
+ if (!wait) {
+ if (m_timerId > 0) {
+ emscripten_clear_timeout(m_timerId);
+ m_timerId = 0;
+ m_timerTargetTime = 0ms;
+ }
+ return;
+ }
+
+ if (m_timerTargetTime != 0ms && newTargetTime >= m_timerTargetTime)
+ return; // existing timer is good
+
+ qCDebug(lcEventDispatcherTimers)
+ << "Created new native timer with wait" << toWaitDuration.count() << "ms"
+ << "timeout" << newTargetTime.count() << "ms";
+ emscripten_clear_timeout(m_timerId);
+ m_timerId = emscripten_set_timeout(&QEventDispatcherWasm::callProcessTimers,
+ toWaitDuration.count(), this);
+ m_timerTargetTime = newTargetTime;
+ };
+
+ // Update the native timer for this thread/dispatcher. This must be
+ // done on the main thread where we have access to native API.
+ runOnMainThread([this, maintainNativeTimer]() {
+ Q_ASSERT(emscripten_is_main_runtime_thread());
+
+ // "this" may have been deleted, or may be about to be deleted.
+ // Check if the pointer we have is still a valid event dispatcher,
+ // and keep the mutex locked while updating the native timer to
+ // prevent it from being deleted.
+ LOCK_GUARD(g_staticDataMutex);
+ if (isValidEventDispatcherPointer(this))
+ maintainNativeTimer();
+ });
+}
+
+// Static timer activation callback. Must be called on the main thread
+// and will then either process timers on the main thread or wake and
+// process timers on a secondary thread.
+void QEventDispatcherWasm::callProcessTimers(void *context)
+{
+ Q_ASSERT(emscripten_is_main_runtime_thread());
+
+ // Note: "context" may be a stale pointer here,
+ // take care before casting and dereferencing!
+
+ // Process timers on this thread if this is the main event dispatcher
+ if (reinterpret_cast<QEventDispatcherWasm *>(context) == g_mainThreadEventDispatcher) {
+ g_mainThreadEventDispatcher->m_timerTargetTime = 0ms;
+ g_mainThreadEventDispatcher->processTimers();
+ return;
+ }
+
+ // Wake and process timers on the secondary thread if this a secondary thread dispatcher
+#if QT_CONFIG(thread)
+ std::lock_guard<std::mutex> lock(g_staticDataMutex);
+ if (g_secondaryThreadEventDispatchers.contains(context)) {
+ QEventDispatcherWasm *eventDispatcher = reinterpret_cast<QEventDispatcherWasm *>(context);
+ eventDispatcher->m_timerTargetTime = 0ms;
+ eventDispatcher->m_processTimers = true;
+ eventDispatcher->wakeUp();
+ }
+#endif
+}
+
+void QEventDispatcherWasm::setEmscriptenSocketCallbacks()
+{
+ qCDebug(lcEventDispatcher) << "setEmscriptenSocketCallbacks";
+
+ emscripten_set_socket_error_callback(nullptr, QEventDispatcherWasm::socketError);
+ emscripten_set_socket_open_callback(nullptr, QEventDispatcherWasm::socketOpen);
+ emscripten_set_socket_listen_callback(nullptr, QEventDispatcherWasm::socketListen);
+ emscripten_set_socket_connection_callback(nullptr, QEventDispatcherWasm::socketConnection);
+ emscripten_set_socket_message_callback(nullptr, QEventDispatcherWasm::socketMessage);
+ emscripten_set_socket_close_callback(nullptr, QEventDispatcherWasm::socketClose);
+}
+
+void QEventDispatcherWasm::clearEmscriptenSocketCallbacks()
+{
+ qCDebug(lcEventDispatcher) << "clearEmscriptenSocketCallbacks";
+
+ emscripten_set_socket_error_callback(nullptr, nullptr);
+ emscripten_set_socket_open_callback(nullptr, nullptr);
+ emscripten_set_socket_listen_callback(nullptr, nullptr);
+ emscripten_set_socket_connection_callback(nullptr, nullptr);
+ emscripten_set_socket_message_callback(nullptr, nullptr);
+ emscripten_set_socket_close_callback(nullptr, nullptr);
+}
+
+void QEventDispatcherWasm::socketError(int socket, int err, const char* msg, void *context)
+{
+ Q_UNUSED(err);
+ Q_UNUSED(msg);
+ Q_UNUSED(context);
+
+ // Emscripten makes socket callbacks while the main thread is busy-waiting for a mutex,
+ // which can cause deadlocks if the callback code also tries to lock the same mutex.
+ // This is most easily reproducible by adding print statements, where each print requires
+ // taking a mutex lock. Work around this by running the callback asynchronously, i.e. by using
+ // a native zero-timer, to make sure the main thread stack is completely unwond before calling
+ // the Qt handler.
+ // It is currently unclear if this problem is caused by code in Qt or in Emscripten, or
+ // if this completely fixes the problem.
+ runAsync([socket](){
+ auto notifiersRange = g_socketNotifiers.equal_range(socket);
+ std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
+ for (auto [_, notifier]: notifiers) {
+ QCoreApplication::postEvent(notifier, new QEvent(QEvent::SockAct));
+ }
+ setSocketState(socket, true, true);
+ });
+}
+
+void QEventDispatcherWasm::socketOpen(int socket, void *context)
+{
+ Q_UNUSED(context);
+
+ runAsync([socket](){
+ auto notifiersRange = g_socketNotifiers.equal_range(socket);
+ std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
+ for (auto [_, notifier]: notifiers) {
+ if (notifier->type() == QSocketNotifier::Write) {
+ QCoreApplication::postEvent(notifier, new QEvent(QEvent::SockAct));
+ }
+ }
+ setSocketState(socket, false, true);
+ });
+}
+
+void QEventDispatcherWasm::socketListen(int socket, void *context)
+{
+ Q_UNUSED(socket);
+ Q_UNUSED(context);
+}
+
+void QEventDispatcherWasm::socketConnection(int socket, void *context)
+{
+ Q_UNUSED(socket);
+ Q_UNUSED(context);
+}
+
+void QEventDispatcherWasm::socketMessage(int socket, void *context)
+{
+ Q_UNUSED(context);
+
+ runAsync([socket](){
+ auto notifiersRange = g_socketNotifiers.equal_range(socket);
+ std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
+ for (auto [_, notifier]: notifiers) {
+ if (notifier->type() == QSocketNotifier::Read) {
+ QCoreApplication::postEvent(notifier, new QEvent(QEvent::SockAct));
+ }
+ }
+ setSocketState(socket, true, false);
+ });
+}
+
+void QEventDispatcherWasm::socketClose(int socket, void *context)
+{
+ Q_UNUSED(context);
+
+ // Emscripten makes emscripten_set_socket_close_callback() calls to socket 0,
+ // which is not a valid socket. see https://github.com/emscripten-core/emscripten/issues/6596
+ if (socket == 0)
+ return;
+
+ runAsync([socket](){
+ auto notifiersRange = g_socketNotifiers.equal_range(socket);
+ std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
+ for (auto [_, notifier]: notifiers)
+ QCoreApplication::postEvent(notifier, new QEvent(QEvent::SockClose));
+
+ setSocketState(socket, true, true);
+ clearSocketState(socket);
+ });
+}
+
+void QEventDispatcherWasm::setSocketState(int socket, bool setReadyRead, bool setReadyWrite)
+{
+ LOCK_GUARD(g_staticDataMutex);
+ SocketReadyState &state = g_socketState[socket];
+
+ // Additively update socket ready state, e.g. if it
+ // was already ready read then it stays ready read.
+ state.readyRead |= setReadyRead;
+ state.readyWrite |= setReadyWrite;
+
+ // Wake any waiters for the given readiness. The waiter consumes
+ // the ready state, returning the socket to not-ready.
+ if (QEventDispatcherWasm *waiter = state.waiter)
+ if ((state.readyRead && state.waitForReadyRead) || (state.readyWrite && state.waitForReadyWrite))
+ waiter->wakeEventDispatcherThread();
+}
+
+void QEventDispatcherWasm::clearSocketState(int socket)
+{
+ LOCK_GUARD(g_staticDataMutex);
+ g_socketState.erase(socket);
+}
+
+void QEventDispatcherWasm::waitForSocketState(int timeout, int socket, bool checkRead, bool checkWrite,
+ bool *selectForRead, bool *selectForWrite, bool *socketDisconnect)
+{
+ // Loop until the socket becomes readyRead or readyWrite. Wait for
+ // socket activity if it currently is neither.
+ while (true) {
+ *selectForRead = false;
+ *selectForWrite = false;
+
+ {
+ LOCK_GUARD(g_staticDataMutex);
+
+ // Access or create socket state: we want to register that a thread is waitng
+ // even if we have not received any socket callbacks yet.
+ SocketReadyState &state = g_socketState[socket];
+ if (state.waiter) {
+ qWarning() << "QEventDispatcherWasm::waitForSocketState: a thread is already waiting";
+ break;
+ }
+
+ bool shouldWait = true;
+ if (checkRead && state.readyRead) {
+ shouldWait = false;
+ state.readyRead = false;
+ *selectForRead = true;
+ }
+ if (checkWrite && state.readyWrite) {
+ shouldWait = false;
+ state.readyWrite = false;
+ *selectForRead = true;
+ }
+ if (!shouldWait)
+ break;
+
+ state.waiter = this;
+ state.waitForReadyRead = checkRead;
+ state.waitForReadyWrite = checkWrite;
+ }
+
+ bool didTimeOut = !wait(timeout);
+ {
+ LOCK_GUARD(g_staticDataMutex);
+
+ // Missing socket state after a wakeup means that the socket has been closed.
+ auto it = g_socketState.find(socket);
+ if (it == g_socketState.end()) {
+ *socketDisconnect = true;
+ break;
+ }
+ it->second.waiter = nullptr;
+ it->second.waitForReadyRead = false;
+ it->second.waitForReadyWrite = false;
+ }
+
+ if (didTimeOut)
+ break;
+ }
+}
+
+void QEventDispatcherWasm::socketSelect(int timeout, int socket, bool waitForRead, bool waitForWrite,
+ bool *selectForRead, bool *selectForWrite, bool *socketDisconnect)
+{
+ QEventDispatcherWasm *eventDispatcher = static_cast<QEventDispatcherWasm *>(
+ QAbstractEventDispatcher::instance(QThread::currentThread()));
+
+ if (!eventDispatcher) {
+ qWarning("QEventDispatcherWasm::socketSelect called without eventdispatcher instance");
+ return;
+ }
+
+ eventDispatcher->waitForSocketState(timeout, socket, waitForRead, waitForWrite,
+ selectForRead, selectForWrite, socketDisconnect);
+}
+
+namespace {
+ int g_startupTasks = 0;
+}
+
+// The following functions manages sending the "qtLoaded" event/callback
+// from qtloader.js on startup, once Qt initialization has been completed
+// and the application is ready to display the first frame. This can be
+// either as soon as the event loop is running, or later, if additional
+// startup tasks (e.g. local font loading) have been registered.
+
+void QEventDispatcherWasm::registerStartupTask()
+{
+ ++g_startupTasks;
+}
+
+void QEventDispatcherWasm::completeStarupTask()
+{
+ --g_startupTasks;
+ callOnLoadedIfRequired();
+}
+
+void QEventDispatcherWasm::callOnLoadedIfRequired()
+{
+ if (g_startupTasks > 0)
+ return;
+
+ static bool qtLoadedCalled = false;
+ if (qtLoadedCalled)
+ return;
+ qtLoadedCalled = true;
+
+ Q_ASSERT(g_mainThreadEventDispatcher);
+ g_mainThreadEventDispatcher->onLoaded();
+}
+
+void QEventDispatcherWasm::onLoaded()
+{
+ // TODO: call qtloader.js onLoaded from here, in order to delay
+ // hiding the "Loading..." message until the app is ready to paint
+ // the first frame. Currently onLoaded must be called early before
+ // main() in order to ensure that the screen/container elements
+ // have valid geometry at startup.
+}
+
+namespace {
+ void trampoline(void *context) {
+
+ auto async_fn = [](void *context){
+ std::function<void(void)> *fn = reinterpret_cast<std::function<void(void)> *>(context);
+ (*fn)();
+ delete fn;
+ };
+
+ emscripten_async_call(async_fn, context, 0);
+ }
+}
+
+// Runs a function right away
+void QEventDispatcherWasm::run(std::function<void(void)> fn)
+{
+ fn();
+}
+
+void QEventDispatcherWasm::runOnMainThread(std::function<void(void)> fn)
+{
+#if QT_CONFIG(thread)
+ qstdweb::runTaskOnMainThread<void>(fn, &g_proxyingQueue);
+#else
+ qstdweb::runTaskOnMainThread<void>(fn);
+#endif
+}
+
+// Runs a function asynchronously. Main thread only.
+void QEventDispatcherWasm::runAsync(std::function<void(void)> fn)
+{
+ trampoline(new std::function<void(void)>(fn));
+}
+
+// Runs a function on the main thread. The function always runs asynchronously,
+// also if the calling thread is the main thread.
+void QEventDispatcherWasm::runOnMainThreadAsync(std::function<void(void)> fn)
+{
+ void *context = new std::function<void(void)>(fn);
+#if QT_CONFIG(thread)
+ if (!emscripten_is_main_runtime_thread()) {
+ g_proxyingQueue.proxyAsync(g_mainThread, [context]{
+ trampoline(context);
+ });
+ return;
+ }
+#endif
+ trampoline(context);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qeventdispatcher_wasm_p.cpp"
diff --git a/src/corelib/kernel/qeventdispatcher_wasm_p.h b/src/corelib/kernel/qeventdispatcher_wasm_p.h
new file mode 100644
index 0000000000..7b257e02ad
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_wasm_p.h
@@ -0,0 +1,139 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QEVENTDISPATCHER_WASM_P_H
+#define QEVENTDISPATCHER_WASM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qabstracteventdispatcher.h"
+#include "private/qtimerinfo_unix_p.h"
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qwaitcondition.h>
+
+#include <chrono>
+#include <mutex>
+#include <optional>
+#include <tuple>
+
+#include <emscripten/proxying.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
+Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers)
+
+class Q_CORE_EXPORT QEventDispatcherWasm : public QAbstractEventDispatcherV2
+{
+ Q_OBJECT
+public:
+ QEventDispatcherWasm();
+ ~QEventDispatcherWasm();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+
+ void registerSocketNotifier(QSocketNotifier *notifier) override;
+ void unregisterSocketNotifier(QSocketNotifier *notifier) override;
+
+ void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType,
+ QObject *object) override final;
+ bool unregisterTimer(Qt::TimerId timerId) override final;
+ bool unregisterTimers(QObject *object) override final;
+ QList<TimerInfoV2> timersForObject(QObject *object) const override final;
+ Duration remainingTime(Qt::TimerId timerId) const override final;
+
+ void interrupt() override;
+ void wakeUp() override;
+
+ static void runOnMainThread(std::function<void(void)> fn);
+ static void socketSelect(int timeout, int socket, bool waitForRead, bool waitForWrite,
+ bool *selectForRead, bool *selectForWrite, bool *socketDisconnect);
+
+ static void registerStartupTask();
+ static void completeStarupTask();
+ static void callOnLoadedIfRequired();
+ virtual void onLoaded();
+
+protected:
+ virtual bool processPostedEvents();
+
+private:
+ bool isMainThreadEventDispatcher();
+ bool isSecondaryThreadEventDispatcher();
+ static bool isValidEventDispatcherPointer(QEventDispatcherWasm *eventDispatcher);
+
+ void handleApplicationExec();
+ void handleDialogExec();
+ bool wait(int timeout = -1);
+ bool wakeEventDispatcherThread();
+ static void callProcessPostedEvents(void *eventDispatcher);
+
+ void processTimers();
+ void updateNativeTimer();
+ static void callProcessTimers(void *eventDispatcher);
+
+ static void setEmscriptenSocketCallbacks();
+ static void clearEmscriptenSocketCallbacks();
+ static void socketError(int fd, int err, const char* msg, void *context);
+ static void socketOpen(int fd, void *context);
+ static void socketListen(int fd, void *context);
+ static void socketConnection(int fd, void *context);
+ static void socketMessage(int fd, void *context);
+ static void socketClose(int fd, void *context);
+
+ static void setSocketState(int socket, bool setReadyRead, bool setReadyWrite);
+ static void clearSocketState(int socket);
+ void waitForSocketState(int timeout, int socket, bool checkRead, bool checkWrite,
+ bool *selectForRead, bool *selectForWrite, bool *socketDisconnect);
+
+ static void run(std::function<void(void)> fn);
+ static void runAsync(std::function<void(void)> fn);
+ static void runOnMainThreadAsync(std::function<void(void)> fn);
+
+ static QEventDispatcherWasm *g_mainThreadEventDispatcher;
+
+ bool m_interrupted = false;
+ bool m_processTimers = false;
+ bool m_pendingProcessEvents = false;
+
+ QTimerInfoList *m_timerInfo = new QTimerInfoList();
+ long m_timerId = 0;
+ std::chrono::milliseconds m_timerTargetTime{};
+
+#if QT_CONFIG(thread)
+ std::mutex m_mutex;
+ bool m_wakeUpCalled = false;
+ std::condition_variable m_moreEvents;
+
+ static QVector<QEventDispatcherWasm *> g_secondaryThreadEventDispatchers;
+ static std::mutex g_staticDataMutex;
+ static emscripten::ProxyingQueue g_proxyingQueue;
+ static pthread_t g_mainThread;
+
+ // Note on mutex usage: the global g_staticDataMutex protects the global (g_ prefixed) data,
+ // while the per eventdispatcher m_mutex protects the state accociated with blocking and waking
+ // that eventdispatcher thread. The locking order is g_staticDataMutex first, then m_mutex.
+#endif
+
+ static std::multimap<int, QSocketNotifier *> g_socketNotifiers;
+
+ struct SocketReadyState {
+ QEventDispatcherWasm *waiter = nullptr;
+ bool waitForReadyRead = false;
+ bool waitForReadyWrite = false;
+ bool readyRead = false;
+ bool readyWrite = false;
+ };
+ static std::map<int, SocketReadyState> g_socketState;
+};
+
+#endif // QEVENTDISPATCHER_WASM_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 43872fd027..a7663b2481 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -1,63 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeventdispatcher_win_p.h"
#include "qcoreapplication.h"
#include <private/qsystemlibrary_p.h>
#include "qoperatingsystemversion.h"
-#include "qpair.h"
#include "qset.h"
#include "qsocketnotifier.h"
#include "qvarlengtharray.h"
-#include "qwineventnotifier.h"
#include "qelapsedtimer.h"
#include "qcoreapplication_p.h"
#include <private/qthread_p.h>
-#include <private/qwineventnotifier_p.h>
QT_BEGIN_NAMESPACE
-extern uint qGlobalPostedEventsCount();
-
#ifndef TIME_KILL_SYNCHRONOUS
# define TIME_KILL_SYNCHRONOUS 0x0100
#endif
@@ -96,27 +55,26 @@ class QEventDispatcherWin32Private;
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+static quint64 qt_msectime()
+{
+ using namespace std::chrono;
+ auto t = duration_cast<milliseconds>(steady_clock::now().time_since_epoch());
+ return t.count();
+}
+
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
- : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
- getMessageHook(0), sendPostedEventsTimerId(0), wakeUps(0),
- activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL)
+ : interrupt(false), internalHwnd(0),
+ sendPostedEventsTimerId(0), wakeUps(0),
+ activateNotifiersPosted(false)
{
}
QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
{
- if (winEventNotifierActivatedEvent)
- CloseHandle(winEventNotifierActivatedEvent);
if (internalHwnd)
DestroyWindow(internalHwnd);
}
-void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
-{
- QEvent event(QEvent::WinEventAct);
- QCoreApplication::sendEvent(wen, &event);
-}
-
// This function is called by a workerthread
void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/)
{
@@ -127,18 +85,6 @@ void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/,
QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
}
-static inline UINT inputQueueMask()
-{
- UINT result = QS_ALLEVENTS;
- // QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
- // QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
-#if WINVER > 0x0601
- if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
- result &= ~(QS_TOUCH | QS_POINTER);
-#endif // WINVER > 0x0601
- return result;
-}
-
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
if (message == WM_NCCREATE)
@@ -150,11 +96,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
msg.wParam = wp;
msg.lParam = lp;
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
qintptr result;
-#else
- long result;
-#endif
if (!dispatcher) {
if (message == WM_TIMER)
KillTimer(hwnd, wp);
@@ -163,13 +105,9 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result))
return result;
-#ifdef GWLP_USERDATA
auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
-#else
- auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLong(hwnd, GWL_USERDATA));
-#endif
- QEventDispatcherWin32Private *d = 0;
- if (q != 0)
+ QEventDispatcherWin32Private *d = nullptr;
+ if (q != nullptr)
d = q->d_func();
switch (message) {
@@ -193,11 +131,11 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
break;
}
if (type >= 0) {
- Q_ASSERT(d != 0);
+ Q_ASSERT(d != nullptr);
QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
QSNDict *dict = sn_vec[type];
- QSockNot *sn = dict ? dict->value(wp) : 0;
+ QSockNot *sn = dict ? dict->value(qintptr(wp)) : 0;
if (sn == nullptr) {
d->postActivateSocketNotifiers();
} else {
@@ -223,7 +161,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
return 0;
}
case WM_QT_ACTIVATENOTIFIERS: {
- Q_ASSERT(d != 0);
+ Q_ASSERT(d != nullptr);
// Postpone activation if we have unhandled socket notifier messages
// in the queue. WM_QT_ACTIVATENOTIFIERS will be posted again as a result of
@@ -248,7 +186,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
return 0;
}
case WM_TIMER:
- Q_ASSERT(d != 0);
+ Q_ASSERT(d != nullptr);
if (wp == d->sendPostedEventsTimerId)
q->sendPostedEvents();
@@ -256,39 +194,32 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
d->sendTimerEvent(wp);
return 0;
case WM_QT_SENDPOSTEDEVENTS:
- Q_ASSERT(d != 0);
+ Q_ASSERT(d != nullptr);
// We send posted events manually, if the window procedure was invoked
// by the foreign event loop (e.g. from the native modal dialog).
// Skip sending, if the message queue is not empty.
// sendPostedEventsTimer will deliver posted events later.
- static const UINT mask = inputQueueMask();
+ static const UINT mask = QS_ALLEVENTS;
if (HIWORD(GetQueueStatus(mask)) == 0)
q->sendPostedEvents();
+ else
+ d->startPostedEventsTimer();
return 0;
} // switch (message)
return DefWindowProc(hwnd, message, wp, lp);
}
-LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
+void QEventDispatcherWin32Private::startPostedEventsTimer()
{
- QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
- Q_ASSERT(q != 0);
- QEventDispatcherWin32Private *d = q->d_func();
- MSG *msg = reinterpret_cast<MSG *>(lp);
- // Windows unexpectedly passes PM_NOYIELD flag to the hook procedure,
- // if ::PeekMessage(..., PM_REMOVE | PM_NOYIELD) is called from the event loop.
- // So, retrieve 'removed' tag as a bit field.
- const bool messageRemoved = (wp & PM_REMOVE) != 0;
-
- if (msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS
- && messageRemoved && d->sendPostedEventsTimerId == 0) {
+ // we received WM_QT_SENDPOSTEDEVENTS, so allow posting it again
+ wakeUps.storeRelaxed(0);
+ if (sendPostedEventsTimerId == 0) {
// Start a timer to deliver posted events when the message queue is emptied.
- d->sendPostedEventsTimerId = SetTimer(d->internalHwnd, SendPostedEventsTimerId,
- USER_TIMER_MINIMUM, NULL);
+ sendPostedEventsTimerId = SetTimer(internalHwnd, SendPostedEventsTimerId,
+ USER_TIMER_MINIMUM, NULL);
}
- return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
}
// Provide class name and atom for the message window used by
@@ -360,24 +291,52 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
return 0;
}
-#ifdef GWLP_USERDATA
SetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(eventDispatcher));
-#else
- SetWindowLong(wnd, GWL_USERDATA, reinterpret_cast<LONG>(eventDispatcher));
-#endif
return wnd;
}
-static void calculateNextTimeout(WinTimerInfo *t, quint64 currentTime)
+static ULONG calculateNextTimeout(WinTimerInfo *t, quint64 currentTime)
{
uint interval = t->interval;
- if ((interval >= 20000u && t->timerType != Qt::PreciseTimer) || t->timerType == Qt::VeryCoarseTimer) {
- // round the interval, VeryCoarseTimers only have full second accuracy
- interval = ((interval + 500)) / 1000 * 1000;
+ ULONG tolerance = TIMERV_DEFAULT_COALESCING;
+ switch (t->timerType) {
+ case Qt::PreciseTimer:
+ // high precision timer is based on millisecond precision
+ // so no adjustment is necessary
+ break;
+
+ case Qt::CoarseTimer:
+ // this timer has up to 5% coarseness
+ // so our boundaries are 20 ms and 20 s
+ // below 20 ms, 5% inaccuracy is below 1 ms, so we convert to high precision
+ // above 20 s, 5% inaccuracy is above 1 s, so we convert to VeryCoarseTimer
+ if (interval >= 20000) {
+ t->timerType = Qt::VeryCoarseTimer;
+ } else if (interval <= 20) {
+ // no adjustment necessary
+ t->timerType = Qt::PreciseTimer;
+ break;
+ } else {
+ tolerance = interval / 20;
+ break;
+ }
+ Q_FALLTHROUGH();
+ case Qt::VeryCoarseTimer:
+ // the very coarse timer is based on full second precision,
+ // so we round to closest second (but never to zero)
+ tolerance = 1000;
+ if (interval < 1000)
+ interval = 1000;
+ else
+ interval = (interval + 500) / 1000 * 1000;
+ currentTime = currentTime / 1000 * 1000;
+ break;
}
+
t->interval = interval;
t->timeout = currentTime + interval;
+ return tolerance;
}
void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
@@ -387,13 +346,13 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
Q_Q(QEventDispatcherWin32);
bool ok = false;
- calculateNextTimeout(t, qt_msectime());
+ ULONG tolerance = calculateNextTimeout(t, qt_msectime());
uint interval = t->interval;
if (interval == 0u) {
// optimization for single-shot-zero-timer
QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
ok = true;
- } else if (interval < 20u || t->timerType == Qt::PreciseTimer) {
+ } else if (tolerance == TIMERV_DEFAULT_COALESCING) {
// 3/2016: Although MSDN states timeSetEvent() is deprecated, the function
// is still deemed to be the most reliable precision timer.
t->fastTimerId = timeSetEvent(interval, 1, qt_fast_timer_proc, DWORD_PTR(t),
@@ -403,8 +362,10 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
if (!ok) {
// user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
- ok = SetTimer(internalHwnd, t->timerId, interval, 0);
+ ok = SetCoalescableTimer(internalHwnd, t->timerId, interval, nullptr, tolerance);
}
+ if (!ok)
+ ok = SetTimer(internalHwnd, t->timerId, interval, nullptr);
if (!ok)
qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
@@ -417,7 +378,7 @@ void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t)
} else if (t->fastTimerId != 0) {
timeKillEvent(t->fastTimerId);
QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
- } else if (internalHwnd) {
+ } else {
KillTimer(internalHwnd, t->timerId);
}
t->timerId = -1;
@@ -447,7 +408,7 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
}
}
-void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event)
+void QEventDispatcherWin32Private::doWsaAsyncSelect(qintptr socket, long event)
{
Q_ASSERT(internalHwnd);
// BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
@@ -461,35 +422,18 @@ void QEventDispatcherWin32Private::postActivateSocketNotifiers()
activateNotifiersPosted = PostMessage(internalHwnd, WM_QT_ACTIVATENOTIFIERS, 0, 0);
}
-void QEventDispatcherWin32::createInternalHwnd()
-{
- Q_D(QEventDispatcherWin32);
-
- if (d->internalHwnd)
- return;
- d->internalHwnd = qt_create_internal_window(this);
-
- // setup GetMessage hook needed to drive our posted events
- d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
- if (Q_UNLIKELY(!d->getMessageHook)) {
- int errorCode = GetLastError();
- qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls",
- errorCode, qUtf16Printable(qt_error_string(errorCode)));
- }
-
- // start all normal timers
- for (int i = 0; i < d->timerVec.count(); ++i)
- d->registerTimer(d->timerVec.at(i));
-}
-
QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
- : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
+ : QEventDispatcherWin32(*new QEventDispatcherWin32Private, parent)
{
}
QEventDispatcherWin32::QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent)
: QAbstractEventDispatcher(dd, parent)
-{ }
+{
+ Q_D(QEventDispatcherWin32);
+
+ d->internalHwnd = qt_create_internal_window(this);
+}
QEventDispatcherWin32::~QEventDispatcherWin32()
{
@@ -515,133 +459,105 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWin32);
- if (!d->internalHwnd) {
- createInternalHwnd();
- wakeUp(); // trigger a call to sendPostedEvents()
- }
-
- d->interrupt.storeRelaxed(false);
+ // We don't know _when_ the interrupt occurred so we have to honor it.
+ const bool wasInterrupted = d->interrupt.fetchAndStoreRelaxed(false);
emit awake();
// To prevent livelocks, send posted events once per iteration.
// QCoreApplication::sendPostedEvents() takes care about recursions.
sendPostedEvents();
+ if (wasInterrupted)
+ return false;
+
+ auto threadData = d->threadData.loadRelaxed();
bool canWait;
bool retVal = false;
do {
- DWORD waitRet = 0;
- DWORD nCount = 0;
- HANDLE *pHandles = nullptr;
- if (d->winEventNotifierActivatedEvent) {
- nCount = 1;
- pHandles = &d->winEventNotifierActivatedEvent;
- }
QVarLengthArray<MSG> processedTimers;
while (!d->interrupt.loadRelaxed()) {
MSG msg;
- bool haveMessage;
if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
// process queued user input events
- haveMessage = true;
msg = d->queuedUserInputEvents.takeFirst();
- } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
+ } else if (!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
// process queued socket events
- haveMessage = true;
msg = d->queuedSocketEvents.takeFirst();
- } else {
- haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
- if (haveMessage) {
- if (flags.testFlag(QEventLoop::ExcludeUserInputEvents)
- && isUserInputMessage(msg.message)) {
- // queue user input events for later processing
- d->queuedUserInputEvents.append(msg);
- continue;
- }
- if ((flags & QEventLoop::ExcludeSocketNotifiers)
- && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
- // queue socket events for later processing
- d->queuedSocketEvents.append(msg);
- continue;
- }
+ } else if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
+ if (flags.testFlag(QEventLoop::ExcludeUserInputEvents)
+ && isUserInputMessage(msg.message)) {
+ // queue user input events for later processing
+ d->queuedUserInputEvents.append(msg);
+ continue;
}
- }
- if (!haveMessage) {
- // no message - check for signalled objects
- waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
- if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
- // a new message has arrived, process it
+ if ((flags & QEventLoop::ExcludeSocketNotifiers)
+ && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
+ // queue socket events for later processing
+ d->queuedSocketEvents.append(msg);
continue;
}
+ } else if (MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE)
+ == WAIT_OBJECT_0) {
+ // a new message has arrived, process it
+ continue;
+ } else {
+ // nothing to do, so break
+ break;
}
- if (haveMessage) {
- if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
- // Set result to 'true' because the message was sent by wakeUp().
- retVal = true;
+
+ if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
+ d->startPostedEventsTimer();
+ // Set result to 'true' because the message was sent by wakeUp().
+ retVal = true;
+ continue;
+ }
+ if (msg.message == WM_TIMER) {
+ // Skip timer event intended for use inside foreign loop.
+ if (d->internalHwnd == msg.hwnd && msg.wParam == d->sendPostedEventsTimerId)
continue;
- }
- if (msg.message == WM_TIMER) {
- // Skip timer event intended for use inside foreign loop.
- if (d->internalHwnd == msg.hwnd && msg.wParam == d->sendPostedEventsTimerId)
- continue;
-
- // avoid live-lock by keeping track of the timers we've already sent
- bool found = false;
- for (int i = 0; !found && i < processedTimers.count(); ++i) {
- const MSG processed = processedTimers.constData()[i];
- found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
- }
- if (found)
- continue;
- processedTimers.append(msg);
- } else if (msg.message == WM_QUIT) {
- if (QCoreApplication::instance())
- QCoreApplication::instance()->quit();
- return false;
- }
- if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
+ // avoid live-lock by keeping track of the timers we've already sent
+ bool found = false;
+ for (int i = 0; !found && i < processedTimers.count(); ++i) {
+ const MSG processed = processedTimers.constData()[i];
+ found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
}
- } else if (waitRet - WAIT_OBJECT_0 < nCount) {
- activateEventNotifiers();
- } else {
- // nothing todo so break
- break;
+ if (found)
+ continue;
+ processedTimers.append(msg);
+ } else if (msg.message == WM_QUIT) {
+ if (QCoreApplication::instance())
+ QCoreApplication::instance()->quit();
+ return false;
+ }
+
+ if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
}
retVal = true;
}
- // still nothing - wait for message or signalled objects
+ // wait for message
canWait = (!retVal
&& !d->interrupt.loadRelaxed()
- && (flags & QEventLoop::WaitForMoreEvents));
+ && flags.testFlag(QEventLoop::WaitForMoreEvents)
+ && threadData->canWaitLocked());
if (canWait) {
emit aboutToBlock();
- waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
+ MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
emit awake();
- if (waitRet - WAIT_OBJECT_0 < nCount) {
- activateEventNotifiers();
- retVal = true;
- }
}
} while (canWait);
return retVal;
}
-bool QEventDispatcherWin32::hasPendingEvents()
-{
- MSG msg;
- return qGlobalPostedEventsCount() || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
-}
-
void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
{
Q_ASSERT(notifier);
- int sockfd = notifier->socket();
+ qintptr sockfd = notifier->socket();
int type = notifier->type();
#ifndef QT_NO_DEBUG
if (sockfd < 0) {
@@ -665,11 +581,9 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
const char *t[] = { "Read", "Write", "Exception" };
/* Variable "socket" below is a function pointer. */
qWarning("QSocketNotifier: Multiple socket notifiers for "
- "same socket %d and type %s", sockfd, t[type]);
+ "same socket %" PRIdQINTPTR " and type %s", sockfd, t[type]);
}
- createInternalHwnd();
-
QSockNot *sn = new QSockNot;
sn->obj = notifier;
sn->fd = sockfd;
@@ -692,9 +606,16 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
}
sd.event |= event;
} else {
- // Disable the events which could be implicitly re-enabled. Next activation
- // of socket notifiers will reset the mask.
- d->active_fd.insert(sockfd, QSockFd(event, FD_READ | FD_ACCEPT | FD_WRITE | FD_OOB));
+ // Although WSAAsyncSelect(..., 0), which is called from
+ // unregisterSocketNotifier(), immediately disables event message
+ // posting for the socket, it is possible that messages could be
+ // waiting in the application message queue even if the socket was
+ // closed. Also, some events could be implicitly re-enabled due
+ // to system calls. Ignore these superfluous events until all
+ // pending notifications have been suppressed. Next activation of
+ // socket notifiers will reset the mask.
+ d->active_fd.insert(sockfd, QSockFd(event, FD_READ | FD_CLOSE | FD_ACCEPT | FD_WRITE
+ | FD_CONNECT | FD_OOB));
}
d->postActivateSocketNotifiers();
@@ -704,7 +625,7 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
{
Q_ASSERT(notifier);
#ifndef QT_NO_DEBUG
- int sockfd = notifier->socket();
+ qintptr sockfd = notifier->socket();
if (sockfd < 0) {
qWarning("QEventDispatcherWin32::unregisterSocketNotifier: invalid socket identifier");
return;
@@ -721,7 +642,7 @@ void QEventDispatcherWin32::doUnregisterSocketNotifier(QSocketNotifier *notifier
{
Q_D(QEventDispatcherWin32);
int type = notifier->type();
- int sockfd = notifier->socket();
+ qintptr sockfd = notifier->socket();
Q_ASSERT(sockfd >= 0);
QSFDict::iterator it = d->active_fd.find(sockfd);
@@ -749,7 +670,7 @@ void QEventDispatcherWin32::doUnregisterSocketNotifier(QSocketNotifier *notifier
delete sn;
}
-void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+void QEventDispatcherWin32::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
{
#ifndef QT_NO_DEBUG
if (timerId < 1 || interval < 0 || !object) {
@@ -778,10 +699,8 @@ void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerTy
t->inTimerEvent = false;
t->fastTimerId = 0;
- if (d->internalHwnd)
- d->registerTimer(t);
+ d->registerTimer(t);
- d->timerVec.append(t); // store in timer vector
d->timerDict.insert(t->timerId, t); // store timers in dict
}
@@ -799,15 +718,11 @@ bool QEventDispatcherWin32::unregisterTimer(int timerId)
#endif
Q_D(QEventDispatcherWin32);
- if (d->timerVec.isEmpty() || timerId <= 0)
- return false;
- WinTimerInfo *t = d->timerDict.value(timerId);
+ WinTimerInfo *t = d->timerDict.take(timerId);
if (!t)
return false;
- d->timerDict.remove(t->timerId);
- d->timerVec.removeAll(t);
d->unregisterTimer(t);
return true;
}
@@ -826,16 +741,18 @@ bool QEventDispatcherWin32::unregisterTimers(QObject *object)
#endif
Q_D(QEventDispatcherWin32);
- if (d->timerVec.isEmpty())
+ if (d->timerDict.isEmpty())
return false;
- WinTimerInfo *t;
- for (int i=0; i<d->timerVec.size(); i++) {
- t = d->timerVec.at(i);
- if (t && t->obj == object) { // object found
- d->timerDict.remove(t->timerId);
- d->timerVec.removeAt(i);
+
+ auto it = d->timerDict.begin();
+ while (it != d->timerDict.end()) {
+ WinTimerInfo *t = it.value();
+ Q_ASSERT(t);
+ if (t->obj == object) {
+ it = d->timerDict.erase(it);
d->unregisterTimer(t);
- --i;
+ } else {
+ ++it;
}
}
return true;
@@ -853,91 +770,14 @@ QEventDispatcherWin32::registeredTimers(QObject *object) const
Q_D(const QEventDispatcherWin32);
QList<TimerInfo> list;
- for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
- if (t && t->obj == object)
+ for (WinTimerInfo *t : std::as_const(d->timerDict)) {
+ Q_ASSERT(t);
+ if (t->obj == object)
list << TimerInfo(t->timerId, t->interval, t->timerType);
}
return list;
}
-bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
-{
- Q_ASSERT(notifier);
-#ifndef QT_NO_DEBUG
- if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QEventDispatcherWin32: event notifiers cannot be enabled from another thread");
- return false;
- }
-#endif
-
- Q_D(QEventDispatcherWin32);
-
- if (d->winEventNotifierList.contains(notifier))
- return true;
-
- d->winEventNotifierList.append(notifier);
- d->winEventNotifierListModified = true;
-
- if (!d->winEventNotifierActivatedEvent)
- d->winEventNotifierActivatedEvent = CreateEvent(0, TRUE, FALSE, nullptr);
-
- return QWinEventNotifierPrivate::get(notifier)->registerWaitObject();
-}
-
-void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
-{
- Q_ASSERT(notifier);
-#ifndef QT_NO_DEBUG
- if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QEventDispatcherWin32: event notifiers cannot be disabled from another thread");
- return;
- }
-#endif
- doUnregisterEventNotifier(notifier);
-}
-
-void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier)
-{
- Q_D(QEventDispatcherWin32);
-
- int i = d->winEventNotifierList.indexOf(notifier);
- if (i == -1)
- return;
- d->winEventNotifierList.takeAt(i);
- d->winEventNotifierListModified = true;
- QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
- if (nd->waitHandle)
- nd->unregisterWaitObject();
-}
-
-void QEventDispatcherWin32::activateEventNotifiers()
-{
- Q_D(QEventDispatcherWin32);
- ResetEvent(d->winEventNotifierActivatedEvent);
-
- // Activate signaled notifiers. Our winEventNotifierList can be modified in activation slots.
- do {
- d->winEventNotifierListModified = false;
- for (int i = 0; i < d->winEventNotifierList.count(); ++i) {
- QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
- QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
- if (nd->signaledCount.loadRelaxed() != 0) {
- --nd->signaledCount;
- nd->unregisterWaitObject();
- d->activateEventNotifier(notifier);
- }
- }
- } while (d->winEventNotifierListModified);
-
- // Re-register the remaining activated notifiers.
- for (int i = 0; i < d->winEventNotifierList.count(); ++i) {
- QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
- QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
- if (!nd->waitHandle)
- nd->registerWaitObject();
- }
-}
-
int QEventDispatcherWin32::remainingTime(int timerId)
{
#ifndef QT_NO_DEBUG
@@ -949,20 +789,12 @@ int QEventDispatcherWin32::remainingTime(int timerId)
Q_D(QEventDispatcherWin32);
- if (d->timerVec.isEmpty())
- return -1;
-
quint64 currentTime = qt_msectime();
- for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
- if (t && t->timerId == timerId) {
- // timer found, return time to wait
-
- if (d->internalHwnd)
- return t->timeout > currentTime ? t->timeout - currentTime : 0;
- else
- return t->interval;
- }
+ WinTimerInfo *t = d->timerDict.value(timerId);
+ if (t) {
+ // timer found, return time to wait
+ return t->timeout > currentTime ? t->timeout - currentTime : 0;
}
#ifndef QT_NO_DEBUG
@@ -975,7 +807,7 @@ int QEventDispatcherWin32::remainingTime(int timerId)
void QEventDispatcherWin32::wakeUp()
{
Q_D(QEventDispatcherWin32);
- if (d->internalHwnd && d->wakeUps.testAndSetRelaxed(0, 1)) {
+ if (d->wakeUps.testAndSetRelaxed(0, 1)) {
// post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0))
qErrnoWarning("QEventDispatcherWin32::wakeUp: Failed to post a message");
@@ -989,9 +821,6 @@ void QEventDispatcherWin32::interrupt()
wakeUp();
}
-void QEventDispatcherWin32::flush()
-{ }
-
void QEventDispatcherWin32::startingUp()
{ }
@@ -1008,22 +837,13 @@ void QEventDispatcherWin32::closingDown()
doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj);
Q_ASSERT(d->active_fd.isEmpty());
- // clean up any eventnotifiers
- while (!d->winEventNotifierList.isEmpty())
- doUnregisterEventNotifier(d->winEventNotifierList.first());
-
// clean up any timers
- for (int i = 0; i < d->timerVec.count(); ++i)
- d->unregisterTimer(d->timerVec.at(i));
- d->timerVec.clear();
+ for (WinTimerInfo *t : std::as_const(d->timerDict))
+ d->unregisterTimer(t);
d->timerDict.clear();
d->closingDown = true;
- if (d->getMessageHook)
- UnhookWindowsHookEx(d->getMessageHook);
- d->getMessageHook = 0;
-
if (d->sendPostedEventsTimerId != 0)
KillTimer(d->internalHwnd, d->sendPostedEventsTimerId);
d->sendPostedEventsTimerId = 0;
@@ -1081,9 +901,9 @@ void QEventDispatcherWin32::sendPostedEvents()
HWND QEventDispatcherWin32::internalHwnd()
{
- Q_D(QEventDispatcherWin32);
- createInternalHwnd();
- return d->internalHwnd;
+ return d_func()->internalHwnd;
}
QT_END_NAMESPACE
+
+#include "moc_qeventdispatcher_win_p.cpp"
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index dbb30ab568..558490a85e 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTDISPATCHER_WIN_P_H
#define QEVENTDISPATCHER_WIN_P_H
@@ -54,50 +18,40 @@
#include "QtCore/qabstracteventdispatcher.h"
#include "QtCore/qt_windows.h"
#include "QtCore/qhash.h"
+#include "QtCore/qatomic.h"
#include "qabstracteventdispatcher_p.h"
QT_BEGIN_NAMESPACE
-class QWinEventNotifier;
class QEventDispatcherWin32Private;
// forward declaration
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
-quint64 qt_msectime();
class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
{
Q_OBJECT
Q_DECLARE_PRIVATE(QEventDispatcherWin32)
-protected:
- void createInternalHwnd();
-
public:
- explicit QEventDispatcherWin32(QObject *parent = 0);
+ explicit QEventDispatcherWin32(QObject *parent = nullptr);
~QEventDispatcherWin32();
bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) override;
- bool hasPendingEvents() override;
void registerSocketNotifier(QSocketNotifier *notifier) override;
void unregisterSocketNotifier(QSocketNotifier *notifier) override;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) override;
+ void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object) override;
bool unregisterTimer(int timerId) override;
bool unregisterTimers(QObject *object) override;
QList<TimerInfo> registeredTimers(QObject *object) const override;
- bool registerEventNotifier(QWinEventNotifier *notifier) override;
- void unregisterEventNotifier(QWinEventNotifier *notifier) override;
- void activateEventNotifiers();
-
int remainingTime(int timerId) override;
void wakeUp() override;
void interrupt() override;
- void flush() override;
void startingUp() override;
void closingDown() override;
@@ -107,21 +61,19 @@ public:
HWND internalHwnd();
protected:
- QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0);
+ QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = nullptr);
virtual void sendPostedEvents();
void doUnregisterSocketNotifier(QSocketNotifier *notifier);
- void doUnregisterEventNotifier(QWinEventNotifier *notifier);
private:
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
- friend LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int, WPARAM, LPARAM);
};
struct QSockNot {
QSocketNotifier *obj;
- int fd;
+ qintptr fd;
};
-typedef QHash<int, QSockNot *> QSNDict;
+typedef QHash<qintptr, QSockNot *> QSNDict;
struct QSockFd {
long event;
@@ -130,12 +82,12 @@ struct QSockFd {
explicit inline QSockFd(long ev = 0, long ma = 0) : event(ev), mask(ma), selected(false) { }
};
-typedef QHash<int, QSockFd> QSFDict;
+typedef QHash<qintptr, QSockFd> QSFDict;
struct WinTimerInfo { // internal timer info
QObject *dispatcher;
int timerId;
- int interval;
+ qint64 interval;
Qt::TimerType timerType;
quint64 timeout; // - when to actually fire
QObject *obj; // - object to receive events
@@ -151,7 +103,6 @@ public:
{ t = QEvent::ZeroTimerEvent; }
};
-typedef QList<WinTimerInfo*> WinTimerVec; // vector of TimerInfo structs
typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
class Q_CORE_EXPORT QEventDispatcherWin32Private : public QAbstractEventDispatcherPrivate
@@ -160,22 +111,18 @@ class Q_CORE_EXPORT QEventDispatcherWin32Private : public QAbstractEventDispatch
public:
QEventDispatcherWin32Private();
~QEventDispatcherWin32Private();
- static QEventDispatcherWin32Private *get(QEventDispatcherWin32 *q) { return q->d_func(); }
-
- DWORD threadId;
QAtomicInt interrupt;
// internal window handle used for socketnotifiers/timers/etc
HWND internalHwnd;
- HHOOK getMessageHook;
// for controlling when to send posted events
UINT_PTR sendPostedEventsTimerId;
QAtomicInt wakeUps;
+ void startPostedEventsTimer();
// timers
- WinTimerVec timerVec;
WinTimerDict timerDict;
void registerTimer(WinTimerInfo *t);
void unregisterTimer(WinTimerInfo *t);
@@ -188,15 +135,10 @@ public:
QSFDict active_fd;
bool activateNotifiersPosted;
void postActivateSocketNotifiers();
- void doWsaAsyncSelect(int socket, long event);
+ void doWsaAsyncSelect(qintptr socket, long event);
bool closingDown = false;
- bool winEventNotifierListModified = false;
- HANDLE winEventNotifierActivatedEvent;
- QList<QWinEventNotifier *> winEventNotifierList;
- void activateEventNotifier(QWinEventNotifier * wen);
-
QList<MSG> queuedUserInputEvents;
QList<MSG> queuedSocketEvents;
};
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index 5a5dfb06aa..e314a17ff8 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -1,57 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeventloop.h"
#include "qabstracteventdispatcher.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
-#include "qelapsedtimer.h"
+#include "qdeadlinetimer.h"
#include "qobject_p.h"
#include "qeventloop_p.h"
#include <private/qthread_p.h>
-#ifdef Q_OS_WASM
-#include <emscripten.h>
-#endif
-
QT_BEGIN_NAMESPACE
/*!
@@ -92,6 +52,7 @@ QT_BEGIN_NAMESPACE
\omitvalue X11ExcludeTimers
\omitvalue EventLoopExec
\omitvalue DialogExec
+ \omitvalue ApplicationExec
\sa processEvents()
*/
@@ -118,8 +79,8 @@ QEventLoop::~QEventLoop()
/*!
- Processes pending events that match \a flags until there are no
- more events to process. Returns \c true if pending events were handled;
+ Processes some pending events that match \a flags.
+ Returns \c true if pending events were handled;
otherwise returns \c false.
This function is especially useful if you have a long running
@@ -155,10 +116,10 @@ bool QEventLoop::processEvents(ProcessEventsFlags flags)
can be used before calling exec(), because modal widgets
use their own local event loop.
- To make your application perform idle processing (i.e. executing a
- special function whenever there are no pending events), use a
- QTimer with 0 timeout. More sophisticated idle processing schemes
- can be achieved using processEvents().
+ To make your application perform idle processing (i.e. executing a special
+ function whenever there are no pending events), use a QChronoTimer with
+ 0ns timeout. More sophisticated idle processing schemes can be achieved
+ using processEvents().
\sa QCoreApplication::quit(), exit(), processEvents()
*/
@@ -179,10 +140,10 @@ int QEventLoop::exec(ProcessEventsFlags flags)
struct LoopReference {
QEventLoopPrivate *d;
- QMutexLocker &locker;
+ QMutexLocker<QMutex> &locker;
bool exceptionCaught;
- LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
+ LoopReference(QEventLoopPrivate *d, QMutexLocker<QMutex> &locker) : d(d), locker(locker), exceptionCaught(true)
{
d->inExec = true;
d->exit.storeRelease(false);
@@ -190,6 +151,9 @@ int QEventLoop::exec(ProcessEventsFlags flags)
auto threadData = d->threadData.loadRelaxed();
++threadData->loopLevel;
threadData->eventLoops.push(d->q_func());
+ qCDebug(lcDeleteLater) << "Increased" << threadData->thread
+ << "loop level to" << threadData->loopLevel
+ << "with leaf loop now" << threadData->eventLoops.last();
locker.unlock();
}
@@ -199,9 +163,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
if (exceptionCaught) {
qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
"exceptions from an event handler is not supported in Qt.\n"
- "You must not let any exception whatsoever propagate through Qt code.\n"
- "If that is not possible, in Qt 5 you must at least reimplement\n"
- "QCoreApplication::notify() and catch all exceptions there.\n");
+ "You must not let any exception whatsoever propagate through Qt code.");
}
locker.relock();
auto threadData = d->threadData.loadRelaxed();
@@ -210,6 +172,12 @@ int QEventLoop::exec(ProcessEventsFlags flags)
Q_UNUSED(eventLoop); // --release warning
d->inExec = false;
--threadData->loopLevel;
+
+ qCDebug(lcDeleteLater) << "Decreased" << threadData->thread
+ << "loop level to" << threadData->loopLevel
+ << "with leaf loop now" << (threadData->eventLoops.isEmpty()
+ ? nullptr : threadData->eventLoops.last());
+
}
};
LoopReference ref(d, locker);
@@ -219,15 +187,6 @@ int QEventLoop::exec(ProcessEventsFlags flags)
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
-#ifdef Q_OS_WASM
- // Partial support for nested event loops: Make the runtime throw a JavaSrcript
- // exception, which returns control to the browser while preserving the C++ stack.
- // Event processing then continues as normal. The sleep call below never returns.
- // QTBUG-70185
- if (threadData->loopLevel > 1)
- emscripten_sleep(1);
-#endif
-
while (!d->exit.loadAcquire())
processEvents(flags | WaitForMoreEvents | EventLoopExec);
@@ -236,9 +195,27 @@ int QEventLoop::exec(ProcessEventsFlags flags)
}
/*!
+ \overload
+
Process pending events that match \a flags for a maximum of \a
maxTime milliseconds, or until there are no more events to
process, whichever is shorter.
+
+ Equivalent to calling:
+ \code
+ processEvents(flags, QDeadlineTimer(maxTime));
+ \endcode
+*/
+void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
+{
+ processEvents(flags, QDeadlineTimer(maxTime));
+}
+
+/*!
+ \since 6.7
+
+ Process pending events that match \a flags until \a deadline has expired,
+ or until there are no more events to process, whichever happens first.
This function is especially useful if you have a long running
operation and want to show its progress without allowing user
input, i.e. by using the \l ExcludeUserInputEvents flag.
@@ -251,16 +228,14 @@ int QEventLoop::exec(ProcessEventsFlags flags)
and will be ignored.
\endlist
*/
-void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
+void QEventLoop::processEvents(ProcessEventsFlags flags, QDeadlineTimer deadline)
{
Q_D(QEventLoop);
if (!d->threadData.loadRelaxed()->hasEventDispatcher())
return;
- QElapsedTimer start;
- start.start();
while (processEvents(flags & ~WaitForMoreEvents)) {
- if (start.elapsed() > maxTime)
+ if (deadline.hasExpired())
break;
}
}
@@ -290,17 +265,6 @@ void QEventLoop::exit(int returnCode)
d->returnCode.storeRelaxed(returnCode);
d->exit.storeRelease(true);
threadData->eventDispatcher.loadRelaxed()->interrupt();
-
-#ifdef Q_OS_WASM
- // QEventLoop::exec() never returns in emscripten. We implement approximate behavior here.
- // QTBUG-70185
- if (threadData->loopLevel == 1) {
- emscripten_force_exit(returnCode);
- } else {
- d->inExec = false;
- --threadData->loopLevel;
- }
-#endif
}
/*!
@@ -354,57 +318,10 @@ bool QEventLoop::event(QEvent *event)
void QEventLoop::quit()
{ exit(0); }
-
-class QEventLoopLockerPrivate
-{
-public:
- explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop)
- : loop(loop), type(EventLoop)
- {
- loop->ref();
- }
-
- explicit QEventLoopLockerPrivate(QThreadPrivate *thread)
- : thread(thread), type(Thread)
- {
- thread->ref();
- }
-
- explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app)
- : app(app), type(Application)
- {
- app->ref();
- }
-
- ~QEventLoopLockerPrivate()
- {
- switch (type)
- {
- case EventLoop:
- loop->deref();
- break;
- case Thread:
- thread->deref();
- break;
- default:
- app->deref();
- break;
- }
- }
-
-private:
- union {
- QEventLoopPrivate * loop;
- QThreadPrivate * thread;
- QCoreApplicationPrivate * app;
- };
- enum Type {
- EventLoop,
- Thread,
- Application
- };
- const Type type;
-};
+// If any of these trigger, the Type bits will interfere with the pointer values:
+static_assert(alignof(QEventLoop) >= 4);
+static_assert(alignof(QThread) >= 4);
+static_assert(alignof(QCoreApplication) >= 4);
/*!
\class QEventLoopLocker
@@ -429,12 +346,16 @@ private:
/*!
Creates an event locker operating on the QCoreApplication.
- The application will quit when there are no more QEventLoopLockers operating on it.
+ The application will attempt to quit when there are no more QEventLoopLockers
+ operating on it, as long as QCoreApplication::isQuitLockEnabled() is \c true.
+
+ Note that attempting a quit may not necessarily result in the application quitting,
+ if there for example are open windows, or the QEvent::Quit event is ignored.
\sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled()
*/
-QEventLoopLocker::QEventLoopLocker()
- : d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()))))
+QEventLoopLocker::QEventLoopLocker() noexcept
+ : QEventLoopLocker{QCoreApplication::instance(), Type::Application}
{
}
@@ -446,8 +367,8 @@ QEventLoopLocker::QEventLoopLocker()
\sa QEventLoop::quit()
*/
-QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
- : d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop))))
+QEventLoopLocker::QEventLoopLocker(QEventLoop *loop) noexcept
+ : QEventLoopLocker{loop, Type::EventLoop}
{
}
@@ -459,18 +380,80 @@ QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
\sa QThread::quit()
*/
-QEventLoopLocker::QEventLoopLocker(QThread *thread)
- : d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread))))
+QEventLoopLocker::QEventLoopLocker(QThread *thread) noexcept
+ : QEventLoopLocker{thread, Type::Thread}
{
}
/*!
+ \fn QEventLoopLocker::QEventLoopLocker(QEventLoopLocker &&other)
+ \since 6.7
+
+ Move-constructs an event-loop locker from \a other. \a other will have a
+ no-op destructor, while responsibility for preventing the
+ QEventLoop/QThread/QCoreApplication from quitting is transferred to the new
+ object.
+*/
+
+/*!
+ \fn QEventLoopLocker &QEventLoopLocker::operator=(QEventLoopLocker &&other)
+ \since 6.7
+
+ Move-assigns this event-loop locker from \a other. \a other will have a
+ no-op destructor, while responsibility for preventing the
+ QEventLoop/QThread/QCoreApplication from quitting is transferred to this
+ object.
+*/
+
+/*!
+ \fn QEventLoopLocker::swap(QEventLoopLocker &other)
+ \since 6.7
+
+ Swaps the object and the state of this QEventLoopLocker with \a other.
+ This operation is very fast and never fails.
+*/
+
+/*!
+ \fn QEventLoopLocker::swap(QEventLoopLocker &lhs, QEventLoopLocker &rhs)
+ \since 6.7
+
+ Swaps the object and the state of \a lhs with \a rhs.
+ This operation is very fast and never fails.
+*/
+
+/*!
Destroys this event loop locker object
*/
QEventLoopLocker::~QEventLoopLocker()
{
- delete d_ptr;
+ visit([](auto p) { p->d_func()->deref(); });
+}
+
+/*!
+ \internal
+*/
+QEventLoopLocker::QEventLoopLocker(void *ptr, Type t) noexcept
+ : p{quintptr(ptr) | quintptr(t)}
+{
+ visit([](auto p) { p->d_func()->ref(); });
+}
+
+/*!
+ \internal
+*/
+template <typename Func>
+void QEventLoopLocker::visit(Func f) const
+{
+ const auto ptr = pointer();
+ if (!ptr)
+ return;
+ switch (type()) {
+ case Type::EventLoop: return f(static_cast<QEventLoop *>(ptr));
+ case Type::Thread: return f(static_cast<QThread *>(ptr));
+ case Type::Application: return f(static_cast<QCoreApplication *>(ptr));
+ }
+ Q_UNREACHABLE();
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventloop.h b/src/corelib/kernel/qeventloop.h
index eb1348220b..ec79c07cd7 100644
--- a/src/corelib/kernel/qeventloop.h
+++ b/src/corelib/kernel/qeventloop.h
@@ -1,56 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTLOOP_H
#define QEVENTLOOP_H
#include <QtCore/qobject.h>
+#include <QtCore/qdeadlinetimer.h>
QT_BEGIN_NAMESPACE
-
+class QEventLoopLocker;
class QEventLoopPrivate;
class Q_CORE_EXPORT QEventLoop : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QEventLoop)
+ friend class QEventLoopLocker;
public:
explicit QEventLoop(QObject *parent = nullptr);
@@ -63,15 +29,17 @@ public:
WaitForMoreEvents = 0x04,
X11ExcludeTimers = 0x08,
EventLoopExec = 0x20,
- DialogExec = 0x40
+ DialogExec = 0x40,
+ ApplicationExec = 0x80,
};
Q_DECLARE_FLAGS(ProcessEventsFlags, ProcessEventsFlag)
+ Q_FLAG(ProcessEventsFlags)
bool processEvents(ProcessEventsFlags flags = AllEvents);
void processEvents(ProcessEventsFlags flags, int maximumTime);
+ void processEvents(ProcessEventsFlags flags, QDeadlineTimer deadline);
int exec(ProcessEventsFlags flags = AllEvents);
- void exit(int returnCode = 0);
bool isRunning() const;
void wakeUp();
@@ -79,25 +47,49 @@ public:
bool event(QEvent *event) override;
public Q_SLOTS:
+ void exit(int returnCode = 0);
void quit();
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QEventLoop::ProcessEventsFlags)
-
class QEventLoopLockerPrivate;
-class Q_CORE_EXPORT QEventLoopLocker
+class QEventLoopLocker
{
public:
- QEventLoopLocker();
- explicit QEventLoopLocker(QEventLoop *loop);
- explicit QEventLoopLocker(QThread *thread);
- ~QEventLoopLocker();
+ Q_NODISCARD_CTOR Q_CORE_EXPORT QEventLoopLocker() noexcept;
+ Q_NODISCARD_CTOR Q_CORE_EXPORT explicit QEventLoopLocker(QEventLoop *loop) noexcept;
+ Q_NODISCARD_CTOR Q_CORE_EXPORT explicit QEventLoopLocker(QThread *thread) noexcept;
+ Q_CORE_EXPORT ~QEventLoopLocker();
+
+ Q_NODISCARD_CTOR QEventLoopLocker(QEventLoopLocker &&other) noexcept
+ : p{std::exchange(other.p, 0)} {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QEventLoopLocker)
+
+ void swap(QEventLoopLocker &other) noexcept { std::swap(p, other.p); }
+ friend void swap(QEventLoopLocker &lhs, QEventLoopLocker &rhs) noexcept { lhs.swap(rhs); }
private:
Q_DISABLE_COPY(QEventLoopLocker)
- QEventLoopLockerPrivate *d_ptr;
+ friend class QEventLoopLockerPrivate;
+
+ //
+ // Private implementation details.
+ // Do not call from public inline API!
+ //
+ enum class Type : quintptr {
+ EventLoop,
+ Thread,
+ Application,
+ };
+ explicit QEventLoopLocker(void *ptr, Type t) noexcept;
+ quintptr p;
+ static constexpr quintptr TypeMask = 0x3;
+ Type type() const { return Type(p & TypeMask); }
+ void *pointer() const { return reinterpret_cast<void *>(p & ~TypeMask); }
+ template <typename Func>
+ void visit(Func func) const;
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventloop_p.h b/src/corelib/kernel/qeventloop_p.h
index 4ad6d92007..1fcb7a8b81 100644
--- a/src/corelib/kernel/qeventloop_p.h
+++ b/src/corelib/kernel/qeventloop_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTLOOP_P_H
#define QEVENTLOOP_P_H
diff --git a/src/corelib/kernel/qfunctions_nacl.cpp b/src/corelib/kernel/qfunctions_nacl.cpp
deleted file mode 100644
index 054ae94574..0000000000
--- a/src/corelib/kernel/qfunctions_nacl.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qfunctions_nacl.h"
-#include <pthread.h>
-#include <qglobal.h>
-
-/*
- The purpose of this file is to stub out certain functions
- that are not provided by the Native Client SDK. This is
- done as an alterative to sprinkling the Qt sources with
- NACL ifdefs.
-
- There are two main classes of functions:
-
- - Functions that are called but can have no effect:
- For these we simply give an empty implementation
-
- - Functions that are referenced in the source code, but
- is not/must not be called at run-time:
- These we either leave undefined or implement with a
- qFatal.
-
- This is a work in progress.
-*/
-
-extern "C" {
-
-void pthread_cleanup_push(void (*)(void *), void *)
-{
-
-}
-
-void pthread_cleanup_pop(int)
-{
-
-}
-
-int pthread_setcancelstate(int, int *)
-{
- return 0;
-}
-
-int pthread_setcanceltype(int, int *)
-{
- return 0;
-}
-
-void pthread_testcancel(void)
-{
-
-}
-
-
-int pthread_cancel(pthread_t)
-{
- return 0;
-}
-
-int pthread_attr_setinheritsched(pthread_attr_t *,int)
-{
- return 0;
-}
-
-
-int pthread_attr_getinheritsched(const pthread_attr_t *, int *)
-{
- return 0;
-}
-
-// event dispatcher, select
-//struct fd_set;
-//struct timeval;
-
-int fcntl(int, int, ...)
-{
- return 0;
-}
-
-int sigaction(int, const struct sigaction *, struct sigaction *)
-{
- return 0;
-}
-
-int open(const char *, int, ...)
-{
- return 0;
-}
-
-int open64(const char *, int, ...)
-{
- return 0;
-}
-
-int access(const char *, int)
-{
- return 0;
-}
-
-typedef long off64_t;
-off64_t ftello64(void *)
-{
- qFatal("ftello64 called");
- return 0;
-}
-
-off64_t lseek64(int, off_t, int)
-{
- qFatal("lseek64 called");
- return 0;
-}
-
-} // Extern C
-
-int select(int, fd_set *, fd_set *, fd_set *, struct timeval *)
-{
- return 0;
-}
diff --git a/src/corelib/kernel/qfunctions_nacl.h b/src/corelib/kernel/qfunctions_nacl.h
deleted file mode 100644
index 15e415400a..0000000000
--- a/src/corelib/kernel/qfunctions_nacl.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFUNCTIONS_NACL_H
-#define QFUNCTIONS_NACL_H
-
-#include <QtCore/qglobal.h>
-
-#ifdef Q_OS_NACL
-
-#include <sys/types.h>
-
-// pthread
-#include <pthread.h>
-#define PTHREAD_CANCEL_DISABLE 1
-#define PTHREAD_CANCEL_ENABLE 2
-#define PTHREAD_INHERIT_SCHED 3
-
-QT_BEGIN_NAMESPACE
-
-
-extern "C" {
-
-void pthread_cleanup_push(void (*handler)(void *), void *arg);
-void pthread_cleanup_pop(int execute);
-
-int pthread_setcancelstate(int state, int *oldstate);
-int pthread_setcanceltype(int type, int *oldtype);
-void pthread_testcancel(void);
-int pthread_cancel(pthread_t thread);
-
-int pthread_attr_setinheritsched(pthread_attr_t *attr,
- int inheritsched);
-int pthread_attr_getinheritsched(const pthread_attr_t *attr,
- int *inheritsched);
-
-// event dispatcher, select
-//struct fd_set;
-//struct timeval;
-int fcntl(int fildes, int cmd, ...);
-int sigaction(int sig, const struct sigaction * act, struct sigaction * oact);
-
-typedef long off64_t;
-off64_t ftello64(void *stream);
-off64_t lseek64(int fildes, off_t offset, int whence);
-int open64(const char *path, int oflag, ...);
-
-}
-
-int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout);
-
-QT_END_NAMESPACE
-
-#endif //Q_OS_NACL
-
-#endif //QFUNCTIONS_NACL_H
diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h
index 6744146aa8..58afc207e6 100644
--- a/src/corelib/kernel/qfunctions_p.h
+++ b/src/corelib/kernel/qfunctions_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//
// W A R N I N G
@@ -53,11 +17,5 @@
#include <QtCore/private/qglobal_p.h>
-#if defined(Q_OS_VXWORKS)
-# include "QtCore/qfunctions_vxworks.h"
-#elif defined(Q_OS_NACL)
-# include "QtCore/qfunctions_nacl.h"
-#endif
-
#endif
diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp
deleted file mode 100644
index 61704c1b54..0000000000
--- a/src/corelib/kernel/qfunctions_vxworks.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qglobal.h"
-
-#ifdef Q_OS_VXWORKS
-
-#include "qplatformdefs.h"
-#include "qfunctions_vxworks.h"
-
-#if defined(_WRS_KERNEL)
-#include <vmLib.h>
-#endif
-#include <selectLib.h>
-#include <ioLib.h>
-
-QT_USE_NAMESPACE
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// no lfind() - used by the TIF image format
-void *lfind(const void* key, const void* base, size_t* elements, size_t size,
- int (*compare)(const void*, const void*))
-{
- const char* current = (char*) base;
- const char* const end = (char*) (current + (*elements) * size);
- while (current != end) {
- if (compare(current, key) == 0)
- return (void*)current;
- current += size;
- }
- return 0;
-}
-
-
-// no rand_r(), but rand()
-// NOTE: this implementation is wrong for multi threaded applications,
-// but there is no way to get it right on VxWorks (in kernel mode)
-#if defined(_WRS_KERNEL)
-int rand_r(unsigned int * /*seedp*/)
-{
- return rand();
-}
-#endif
-
-// no usleep() support
-int usleep(unsigned int usec)
-{
- div_t dt = div(usec, 1000000);
- struct timespec ts = { dt.quot, dt.rem * 1000 };
-
- return nanosleep(&ts, 0);
-}
-
-
-// gettimeofday() is declared, but is missing from the library
-// It IS however defined in the Curtis-Wright X11 libraries, so
-// we have to make the symbol 'weak'
-#if defined(Q_CC_DIAB) && !defined(VXWORKS_DKM) && !defined(VXWORKS_RTP)
-# pragma weak gettimeofday
-#endif
-int gettimeofday(struct timeval *tv, void /*struct timezone*/ *)
-{
- // the compiler will optimize this and will only use one code path
- if (sizeof(struct timeval) == sizeof(struct timespec)) {
- int res = clock_gettime(CLOCK_REALTIME, (struct timespec *) tv);
- if (!res)
- tv->tv_usec /= 1000;
- return res;
- } else {
- struct timespec ts;
-
- int res = clock_gettime(CLOCK_REALTIME, &ts);
- if (!res) {
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / 1000;
- }
- return res;
- }
-}
-
-// neither getpagesize() or sysconf(_SC_PAGESIZE) are available
-int getpagesize()
-{
-#if defined(_WRS_KERNEL)
- return vmPageSizeGet();
-#else
- return sysconf(_SC_PAGESIZE);
-#endif
-}
-
-// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h)
-int symlink(const char *, const char *)
-{
- errno = EIO;
- return -1;
-}
-
-ssize_t readlink(const char *, char *, size_t)
-{
- errno = EIO;
- return -1;
-}
-
-// there's no truncate(), but ftruncate() support...
-int truncate(const char *path, off_t length)
-{
- int fd = open(path, O_WRONLY, 00777);
- if (fd >= 0) {
- int res = ftruncate(fd, length);
- int en = errno;
- close(fd);
- errno = en;
- return res;
- }
- // errno is already set by open
- return -1;
-}
-
-
-
-// VxWorks doesn't know about passwd & friends.
-// in order to avoid patching the unix fs path everywhere
-// we introduce some dummy functions that simulate a single
-// 'root' user on the system.
-
-uid_t getuid()
-{
- return 0;
-}
-
-gid_t getgid()
-{
- return 0;
-}
-
-uid_t geteuid()
-{
- return 0;
-}
-
-struct passwd *getpwuid(uid_t uid)
-{
- static struct passwd pwbuf = { "root", 0, 0, 0, 0, 0, 0 };
-
- if (uid == 0) {
- return &pwbuf;
- } else {
- errno = ENOENT;
- return 0;
- }
-}
-
-struct group *getgrgid(gid_t gid)
-{
- static struct group grbuf = { "root", 0, 0, 0 };
-
- if (gid == 0) {
- return &grbuf;
- } else {
- errno = ENOENT;
- return 0;
- }
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // Q_OS_VXWORKS
diff --git a/src/corelib/kernel/qfunctions_vxworks.h b/src/corelib/kernel/qfunctions_vxworks.h
deleted file mode 100644
index 86f243959f..0000000000
--- a/src/corelib/kernel/qfunctions_vxworks.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFUNCTIONS_VXWORKS_H
-#define QFUNCTIONS_VXWORKS_H
-
-#include <QtCore/qglobal.h>
-
-#ifdef Q_OS_VXWORKS
-
-#include <unistd.h>
-#include <pthread.h>
-#include <dirent.h>
-#include <signal.h>
-#include <string.h>
-#include <strings.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#if defined(_WRS_KERNEL)
-#include <sys/times.h>
-#else
-#include <sys/time.h>
-#endif
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-
-// VxWorks has public header mbuf.h which defines following variables for DKM.
-// Let's undef those to because they overlap with Qt variable names-
-// File mbuf.h is included in headers <netinet/in.h> <net/if.h>, so make sure
-// that those are included before undef's.
-#if defined(mbuf)
-# undef mbuf
-#endif
-#if defined(m_data)
-# undef m_data
-#endif
-#if defined(m_type)
-# undef m_type
-#endif
-#if defined(m_next)
-# undef m_next
-#endif
-#if defined(m_len)
-# undef m_len
-#endif
-#if defined(m_flags)
-# undef m_flags
-#endif
-#if defined(m_hdr)
-# undef m_hdr
-#endif
-#if defined(m_ext)
-# undef m_ext
-#endif
-#if defined(m_act)
-# undef m_act
-#endif
-#if defined(m_nextpkt)
-# undef m_nextpkt
-#endif
-#if defined(m_pkthdr)
-# undef m_pkthdr
-#endif
-
-QT_BEGIN_NAMESPACE
-
-#ifdef QT_BUILD_CORE_LIB
-#endif
-
-QT_END_NAMESPACE
-
-#ifndef RTLD_LOCAL
-#define RTLD_LOCAL 0
-#endif
-
-#ifndef NSIG
-#define NSIG _NSIGS
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// isascii is missing (sometimes!!)
-#ifndef isascii
-inline int isascii(int c) { return (c & 0x7f); }
-#endif
-
-// no lfind() - used by the TIF image format
-void *lfind(const void* key, const void* base, size_t* elements, size_t size,
- int (*compare)(const void*, const void*));
-
-// no rand_r(), but rand()
-// NOTE: this implementation is wrong for multi threaded applications,
-// but there is no way to get it right on VxWorks (in kernel mode)
-#if defined(_WRS_KERNEL)
-int rand_r(unsigned int * /*seedp*/);
-#endif
-
-// no usleep() support
-int usleep(unsigned int);
-
-#if defined(VXWORKS_DKM) || defined(VXWORKS_RTP)
-int gettimeofday(struct timeval *, void *);
-#else
-// gettimeofday() is declared, but is missing from the library.
-// It IS however defined in the Curtis-Wright X11 libraries, so
-// we have to make the symbol 'weak'
-int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) __attribute__((weak));
-#endif
-
-// getpagesize() not available
-int getpagesize();
-
-// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h)
-int symlink(const char *, const char *);
-ssize_t readlink(const char *, char *, size_t);
-
-// there's no truncate(), but ftruncate() support...
-int truncate(const char *path, off_t length);
-
-// VxWorks doesn't know about passwd & friends.
-// in order to avoid patching the unix fs path everywhere
-// we introduce some dummy functions that simulate a single
-// 'root' user on the system.
-
-uid_t getuid();
-gid_t getgid();
-uid_t geteuid();
-
-struct passwd {
- char *pw_name; /* user name */
- char *pw_passwd; /* user password */
- uid_t pw_uid; /* user ID */
- gid_t pw_gid; /* group ID */
- char *pw_gecos; /* real name */
- char *pw_dir; /* home directory */
- char *pw_shell; /* shell program */
-};
-
-struct group {
- char *gr_name; /* group name */
- char *gr_passwd; /* group password */
- gid_t gr_gid; /* group ID */
- char **gr_mem; /* group members */
-};
-
-struct passwd *getpwuid(uid_t uid);
-struct group *getgrgid(gid_t gid);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // Q_OS_VXWORKS
-#endif // QFUNCTIONS_VXWORKS_H
diff --git a/src/corelib/kernel/qfunctions_win.cpp b/src/corelib/kernel/qfunctions_win.cpp
new file mode 100644
index 0000000000..048fdbc934
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_win.cpp
@@ -0,0 +1,66 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qfunctions_win_p.h"
+
+#include <QtCore/qdebug.h>
+
+#include <combaseapi.h>
+#include <objbase.h>
+
+#if __has_include(<appmodel.h>)
+# include <appmodel.h>
+# define HAS_APPMODEL
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QComHelper::QComHelper(COINIT concurrencyModel)
+{
+ // Avoid overhead of initializing and using obsolete technology
+ concurrencyModel = COINIT(concurrencyModel | COINIT_DISABLE_OLE1DDE);
+
+ m_initResult = CoInitializeEx(nullptr, concurrencyModel);
+
+ if (FAILED(m_initResult))
+ qErrnoWarning(m_initResult, "Failed to initialize COM library");
+}
+
+QComHelper::~QComHelper()
+{
+ Q_ASSERT(m_threadId == GetCurrentThreadId());
+ if (SUCCEEDED(m_initResult))
+ CoUninitialize();
+}
+
+/*!
+ \internal
+ Checks if the application has a \e{package identity}
+
+ Having a \e{package identity} is required to use many modern
+ Windows APIs.
+
+ https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/modernize-packaged-apps
+*/
+bool qt_win_hasPackageIdentity()
+{
+#if defined(HAS_APPMODEL)
+ static const bool hasPackageIdentity = []() {
+ UINT32 length = 0;
+ switch (const auto result = GetCurrentPackageFullName(&length, nullptr)) {
+ case ERROR_INSUFFICIENT_BUFFER:
+ return true;
+ case APPMODEL_ERROR_NO_PACKAGE:
+ return false;
+ default:
+ qWarning("Failed to resolve package identity (error code %ld)", result);
+ return false;
+ }
+ }();
+ return hasPackageIdentity;
+#else
+ return false;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qfunctions_win_p.h b/src/corelib/kernel/qfunctions_win_p.h
new file mode 100644
index 0000000000..ab5417f8a2
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_win_p.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFUNCTIONS_WIN_P_H
+#define QFUNCTIONS_WIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+#if !defined(QT_BOOTSTRAPPED)
+#include <QtCore/private/qfunctions_winrt_p.h>
+#endif
+
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QComHelper
+{
+ Q_DISABLE_COPY_MOVE(QComHelper)
+public:
+ QComHelper(COINIT concurrencyModel = COINIT_APARTMENTTHREADED);
+ ~QComHelper();
+
+ bool isValid() const { return SUCCEEDED(m_initResult); }
+ explicit operator bool() const { return isValid(); }
+
+private:
+ HRESULT m_initResult = E_FAIL;
+ DWORD m_threadId{ GetCurrentThreadId() };
+};
+
+Q_CORE_EXPORT bool qt_win_hasPackageIdentity();
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_WIN
+
+#endif // QFUNCTIONS_WIN_P_H
diff --git a/src/corelib/kernel/qfunctions_winrt_p.h b/src/corelib/kernel/qfunctions_winrt_p.h
index aa32747bc8..c895733c93 100644
--- a/src/corelib/kernel/qfunctions_winrt_p.h
+++ b/src/corelib/kernel/qfunctions_winrt_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUNCTIONS_WINRT_P_H
#define QFUNCTIONS_WINRT_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
#if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
@@ -101,8 +65,11 @@ enum AwaitStyle
ProcessMainThreadEvents = 2
};
-template <typename T>
-static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle, uint timeout)
+using EarlyExitConditionFunction = std::function<bool(void)>;
+
+template<typename T>
+static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle,
+ uint timeout, EarlyExitConditionFunction func)
{
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
HRESULT hr = asyncOp.As(&asyncInfo);
@@ -117,16 +84,20 @@ static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, Awai
case ProcessMainThreadEvents:
while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
QCoreApplication::processEvents();
+ if (func && func())
+ return E_ABORT;
if (timeout && t.hasExpired(timeout))
- return ERROR_TIMEOUT;
+ return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
}
break;
case ProcessThreadEvents:
if (QAbstractEventDispatcher *dispatcher = QThread::currentThread()->eventDispatcher()) {
while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
dispatcher->processEvents(QEventLoop::AllEvents);
+ if (func && func())
+ return E_ABORT;
if (timeout && t.hasExpired(timeout))
- return ERROR_TIMEOUT;
+ return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
}
break;
}
@@ -136,7 +107,7 @@ static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, Awai
while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
QThread::yieldCurrentThread();
if (timeout && t.hasExpired(timeout))
- return ERROR_TIMEOUT;
+ return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
}
break;
}
@@ -155,20 +126,24 @@ static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, Awai
return hr;
}
-template <typename T>
-static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle = YieldThread, uint timeout = 0)
+template<typename T>
+static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp,
+ AwaitStyle awaitStyle = YieldThread, uint timeout = 0,
+ EarlyExitConditionFunction func = nullptr)
{
- HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout);
+ HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout, func);
if (FAILED(hr))
return hr;
return asyncOp->GetResults();
}
-template <typename T, typename U>
-static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, U *results, AwaitStyle awaitStyle = YieldThread, uint timeout = 0)
+template<typename T, typename U>
+static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, U *results,
+ AwaitStyle awaitStyle = YieldThread, uint timeout = 0,
+ EarlyExitConditionFunction func = nullptr)
{
- HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout);
+ HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout, func);
if (FAILED(hr))
return hr;
diff --git a/src/corelib/kernel/qiterable.cpp b/src/corelib/kernel/qiterable.cpp
new file mode 100644
index 0000000000..a8c93fbc1c
--- /dev/null
+++ b/src/corelib/kernel/qiterable.cpp
@@ -0,0 +1,612 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qiterable.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QBaseIterator
+ \inmodule QtCore
+ QBaseIterator forms the common base class for all iterators operating on
+ subclasses of QIterable.
+*/
+
+/*!
+ \fn template<class Container> QBaseIterator<Container>::QBaseIterator(const QIterable<Container> *iterable, void *iterator)
+
+ \internal
+ Creates a const QBaseIterator from an \a iterable and an \a iterator.
+ */
+
+/*!
+ \fn template<class Container> QBaseIterator<Container>::QBaseIterator(QIterable<Container> *iterable, void *iterator)
+
+ \internal
+ Creates a non-const QBaseIterator from an \a iterable and an \a iterator.
+ */
+
+/*!
+ \fn template<class Container> QBaseIterator<Container>::QBaseIterator(QBaseIterator<Container> &&other)
+
+ \internal
+ Move-constructs a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \fn template<class Container> QBaseIterator<Container>::QBaseIterator(const QBaseIterator<Container> &other)
+
+ \internal
+ Copy-constructs a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \fn template<class Container> QBaseIterator<Container>::~QBaseIterator()
+
+ \internal
+ Destroys a QBaseIterator.
+ */
+
+/*!
+ \fn template<class Container> QBaseIterator<Container> &QBaseIterator<Container>::operator=(const QBaseIterator<Container> &other)
+
+ \internal
+ Copy-assigns a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \fn template<class Container> void QBaseIterator<Container>::initIterator(const void *copy)
+
+ \internal
+ Initializes the internal native iterator by duplicating \a copy, if given.
+ */
+
+/*!
+ \fn template<class Container> void QBaseIterator<Container>::clearIterator()
+
+ \internal
+ Destroys the internal native iterator.
+ */
+
+
+/*!
+ \fn QMetaContainer QBaseIterator<Container>::metaContainer() const
+
+ \internal
+ Returns the meta sequence.
+ */
+
+/*!
+ \fn template<class Container> QIterable *QBaseIterator<Container>::mutableIterable() const
+
+ \internal
+ Returns a non-const pointer to the iterable, if the original iterable was
+ non-const. Otherwise returns nullptr.
+ */
+
+/*!
+ \fn template<class Container> const QIterable *QBaseIterator<Container>::constIterable() const
+
+ \internal
+ Returns a const pointer to the iterable.
+ */
+
+/*!
+ \fn template<class Container> void *QBaseIterator<Container>::mutableIterator()
+
+ Returns a non-const pointer to the internal native iterator.
+ */
+
+/*!
+ \fn template<class Container> const void *QBaseIterator<Container>::constIterator() const
+
+ Returns a const pointer to the internal native iterator.
+ */
+
+/*!
+ \fn template<class Container> QBaseIterator &QBaseIterator<Container>::operator=(QBaseIterator<Container> &&other)
+
+ \internal
+ Move-assigns a QBaseIterator from \a other, preserving its const-ness.
+ */
+
+/*!
+ \class QIterator
+ \since 6.0
+ \inmodule QtCore
+ \brief The QIterator is a template class that allows iteration over a container in a QVariant.
+
+ A QIterator can only be created by a QIterable instance, and can be used
+ in a way similar to other stl-style iterators. Generally, QIterator should
+ not be used directly, but through its derived classes provided by
+ QSequentialIterable and QAssociativeIterable.
+
+ \sa QIterable
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container>::QIterator(QIterable<Container> *iterable, void *iterator)
+
+ Creates an iterator from an \a iterable and a pointer to a native \a iterator.
+ */
+
+/*!
+ \fn template<class Container> bool QIterator<Container>::operator==(const QIterator<Container> &other) const
+
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn template<class Container> bool QIterator<Container>::operator!=(const QIterator<Container> &other) const
+
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> &QIterator<Container>::operator++()
+
+ The prefix \c{++} operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QSequentialIterable::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> QIterator<Container>::operator++(int)
+ \overload
+
+ The postfix \c{++} operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
+*/
+
+
+/*!
+ \fn template<class Container> QIterator<Container> &QIterator<Container>::operator--()
+
+ The prefix \c{--} operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QSequentialIterable::begin() leads to undefined results.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator++(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> QIterator<Container>::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> &QIterator<Container>::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> &QIterator<Container>::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+=(), operator-(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> QIterator<Container>::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> QIterator<Container>::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+(), operator-=(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> qsizetype QIterator<Container>::operator-(const QIterator<Container> &j) const
+ \overload
+
+ Returns the distance between the two iterators.
+
+ \sa operator+(), operator-=(), QIterable::canReverseIterate()
+ */
+
+/*!
+ \fn template <class Container> QIterator<Container> QIterator<Container>::operator+(qsizetype j, const QIterator<Container> &k)
+
+ Returns an iterator to the item at \a j positions forward from iterator \a k.
+*/
+
+/*!
+ \struct QConstIterator
+ \since 6.0
+ \inmodule QtCore
+ \brief The QConstIterator allows iteration over a container in a QVariant.
+ \sa QIterator, QIterable
+*/
+
+/*!
+ \fn template <class Container> QConstIterator<Container>::QConstIterator(const QIterable<Container> *iterable, void *iterator)
+
+ Creates a QConstIterator to wrap \a iterator, operating on \a iterable.
+ */
+
+/*!
+ \fn template<class Container> bool QConstIterator<Container>::operator==(const QConstIterator<Container> &other) const
+
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn template<class Container> bool QConstIterator<Container>::operator!=(const QConstIterator<Container> &other) const
+
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> &QConstIterator<Container>::operator++()
+
+ The prefix \c{++} operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QIterable<Container>::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> QConstIterator<Container>::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> &QConstIterator<Container>::operator--()
+
+ The prefix \c{--} operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QIterable<Container>::begin() leads to undefined results.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator++(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> QConstIterator<Container>::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> &QConstIterator<Container>::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> &QConstIterator<Container>::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+=(), operator-(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> QConstIterator<Container>::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> QConstIterator<Container>::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+(), operator-=(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template <class Container> qsizetype QConstIterator<Container>::operator-(const QConstIterator<Container> &j) const
+
+ \overload
+
+ Returns the distance between the two iterators.
+
+ \sa operator+(), operator-=(), QIterable::canReverseIterate()
+ */
+
+/*!
+ \class QIterable
+ \inmodule QtCore
+ \since 6.0
+ \brief QIterable is a template class that is the base class for QSequentialIterable and QAssociativeIterable.
+*/
+
+/*!
+ \fn template <class Container> bool QIterable<Container>::canInputIterate() const
+
+ Returns whether the container has an input iterator. This corresponds to
+ the std::input_iterator_tag iterator trait of the iterator and
+ const_iterator of the container.
+*/
+
+/*!
+ \fn template<class Container> bool QIterable<Container>::canForwardIterate() const
+
+ Returns whether it is possible to iterate over the container in forward
+ direction. This corresponds to the std::forward_iterator_tag iterator trait
+ of the iterator and const_iterator of the container.
+*/
+
+/*!
+ \fn template<class Container> bool QIterable<Container>::canReverseIterate() const
+
+ Returns whether it is possible to iterate over the container in reverse. This
+ corresponds to the std::bidirectional_iterator_tag iterator trait of the
+ const_iterator of the container.
+*/
+
+/*!
+ \fn template<class Container> bool QIterable<Container>::canRandomAccessIterate() const
+
+ Returns whether it is possible to efficiently skip over multiple values
+ using and iterator. This corresponds to the std::random_access_iterator_tag
+ iterator trait of the iterator and const_iterator of the container.
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> QIterable<Container>::constBegin() const
+
+ Returns a QConstIterator for the beginning of the container. This
+ can be used in stl-style iteration.
+
+ \sa constEnd(), mutableBegin()
+*/
+
+/*!
+ \fn template<class Container> QConstIterator<Container> QIterable<Container>::constEnd() const
+
+ Returns a Qterable::QConstIterator for the end of the container. This
+ can be used in stl-style iteration.
+
+ \sa constBegin(), mutableEnd()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> QIterable<Container>::mutableBegin()
+
+ Returns a QIterator for the beginning of the container. This
+ can be used in stl-style iteration.
+
+ \sa mutableEnd(), constBegin()
+*/
+
+/*!
+ \fn template<class Container> QIterator<Container> QIterable<Container>::mutableEnd()
+
+ Returns a QSequentialIterable::iterator for the end of the container. This
+ can be used in stl-style iteration.
+
+ \sa mutableBegin(), constEnd()
+*/
+
+/*!
+ \fn template<class Container> qsizetype QIterable<Container>::size() const
+
+ Returns the number of values in the container.
+*/
+
+/*!
+ \class QTaggedIterator
+ \since 6.0
+ \inmodule QtCore
+ \brief QTaggedIterator is a template class that wraps an iterator and exposes standard iterator traits.
+
+ In order to use an iterator any of the standard algorithms, its iterator
+ traits need to be known. As QSequentialIterable can work with many different
+ kinds of containers, we cannot declare the traits in the iterator classes
+ themselves. A QTaggedIterator gives you a way to explicitly declare a trait for
+ a concrete instance of an iterator or QConstIterator.
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory>::QTaggedIterator(Iterator &&it)
+
+ Constructs a QTaggedIterator from an iterator or QConstIterator \a it. Checks
+ whether the IteratorCategory passed as template argument matches the run
+ time capabilities of \a it; if there's no match, \a it is refused.
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> bool QTaggedIterator<Iterator, IteratorCategory>::operator==(const QTaggedIterator<Iterator, IteratorCategory> &other) const
+
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> bool QTaggedIterator<Iterator, IteratorCategory>::operator!=(const QTaggedIterator<Iterator, IteratorCategory> &other) const
+
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> &QTaggedIterator<Iterator, IteratorCategory>::operator++()
+
+ The prefix \c{++} operator (\c{++it}) advances the iterator to the
+ next item in the container and returns an iterator to the new current
+ item.
+
+ Calling this function on QSequentialIterable::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> QTaggedIterator<Iterator, IteratorCategory>::operator++(int)
+ \overload
+
+ The postfix \c{++} operator (\c{it++}) advances the iterator to the
+ next item in the container and returns an iterator to the previously
+ current item.
+*/
+
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> &QTaggedIterator<Iterator, IteratorCategory>::operator--()
+
+ The prefix \c{--} operator (\c{--it}) makes the preceding item
+ current and returns an iterator to the new current item.
+
+ Calling this function on QSequentialIterable::begin() leads to undefined results.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator++(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> QTaggedIterator<Iterator, IteratorCategory>::operator--(int)
+ \overload
+
+ The postfix \c{--} operator (\c{it--}) makes the preceding item
+ current and returns an iterator to the previously current item.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa QIterable::canReverseIterate()
+*/
+
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> &QTaggedIterator<Iterator, IteratorCategory>::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> &QTaggedIterator<Iterator, IteratorCategory>::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+=(), operator-(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> QTaggedIterator<Iterator, IteratorCategory>::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from
+ this iterator.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> QTaggedIterator<Iterator, IteratorCategory>::operator+(qsizetype j, const QTaggedIterator &k)
+
+ Returns an iterator to the item at \a j positions forward from iterator \a k.
+*/
+
+/*!
+ \fn template<class Iterator, typename IteratorCategory> QTaggedIterator<Iterator, IteratorCategory> QTaggedIterator<Iterator, IteratorCategory>::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from
+ this iterator.
+
+ If the container in the QVariant does not support bi-directional iteration, calling this function
+ leads to undefined results.
+
+ \sa operator+(), operator-=(), QIterable::canReverseIterate()
+*/
+
+/*!
+ \fn template <class Iterator, typename IteratorCategory> qsizetype QTaggedIterator<Iterator, IteratorCategory>::operator-(const QTaggedIterator<Iterator, IteratorCategory> &j) const
+
+ Returns the distance between this iterator and \a j.
+
+ \sa operator+(), operator-=(), QIterable::canReverseIterate()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qiterable.h b/src/corelib/kernel/qiterable.h
new file mode 100644
index 0000000000..4adcdfd76f
--- /dev/null
+++ b/src/corelib/kernel/qiterable.h
@@ -0,0 +1,516 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QITERABLE_H
+#define QITERABLE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qtypeinfo.h>
+#include <QtCore/qmetacontainer.h>
+#include <QtCore/qtaggedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+ template<typename Type, typename Storage = Type>
+ class QConstPreservingPointer
+ {
+ enum Tag : bool { Const, Mutable };
+ QTaggedPointer<Storage, Tag> m_pointer;
+
+ public:
+ Q_NODISCARD_CTOR QConstPreservingPointer(std::nullptr_t) : m_pointer(nullptr, Const) {}
+
+ Q_NODISCARD_CTOR QConstPreservingPointer(const void *pointer, qsizetype alignment)
+ : m_pointer(reinterpret_cast<Storage *>(const_cast<void *>(pointer)), Const)
+ {
+ Q_UNUSED(alignment);
+ Q_ASSERT(alignment > qsizetype(alignof(Storage)));
+ }
+
+ Q_NODISCARD_CTOR QConstPreservingPointer(void *pointer, qsizetype alignment)
+ : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
+ {
+ Q_UNUSED(alignment);
+ Q_ASSERT(alignment > qsizetype(alignof(Storage)));
+ }
+
+ template<typename InputType>
+ Q_NODISCARD_CTOR QConstPreservingPointer(const InputType *pointer)
+ : m_pointer(reinterpret_cast<Storage *>(const_cast<InputType *>(pointer)), Const)
+ {
+ static_assert(alignof(InputType) >= alignof(Storage));
+ }
+
+ template<typename InputType>
+ Q_NODISCARD_CTOR QConstPreservingPointer(InputType *pointer)
+ : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
+ {
+ static_assert(alignof(InputType) >= alignof(Storage));
+ }
+
+ Q_NODISCARD_CTOR QConstPreservingPointer() = default;
+
+ const Type *constPointer() const
+ {
+ return reinterpret_cast<const Type *>(m_pointer.data());
+ }
+
+ Type *mutablePointer() const
+ {
+ return m_pointer.tag() == Mutable ? reinterpret_cast<Type *>(m_pointer.data()) : nullptr;
+ }
+ };
+}
+
+template<class Iterator, typename IteratorCategory>
+class QTaggedIterator : public Iterator
+{
+public:
+ using iterator_category = IteratorCategory;
+ QTaggedIterator(Iterator &&it) : Iterator(std::move(it))
+ {
+ const QMetaContainer metaContainer = this->metaContainer();
+ if constexpr (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory>) {
+ if (!metaContainer.hasRandomAccessIterator()) {
+ qFatal("You cannot use this iterator as a random access iterator");
+ this->clearIterator();
+ }
+ }
+
+ if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory>) {
+ if (!metaContainer.hasBidirectionalIterator()) {
+ qFatal("You cannot use this iterator as a bidirectional iterator");
+ this->clearIterator();
+ }
+ }
+
+ if constexpr (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory>) {
+ if (!metaContainer.hasForwardIterator()) {
+ qFatal("You cannot use this iterator as a forward iterator");
+ this->clearIterator();
+ }
+ }
+
+ if constexpr (std::is_base_of_v<std::input_iterator_tag, IteratorCategory>) {
+ if (!metaContainer.hasInputIterator()) {
+ qFatal("You cannot use this iterator as an input iterator");
+ this->clearIterator();
+ }
+ }
+ }
+
+ bool operator==(const QTaggedIterator &o) const { return Iterator::operator==(o); }
+ bool operator!=(const QTaggedIterator &o) const { return Iterator::operator!=(o); }
+ QTaggedIterator &operator++() { Iterator::operator++(); return *this; }
+ QTaggedIterator operator++(int x) { return QTaggedIterator(Iterator::operator++(x)); }
+ QTaggedIterator &operator--() { Iterator::operator--(); return *this; }
+ QTaggedIterator operator--(int x) { return QTaggedIterator(Iterator::operator--(x)); }
+ QTaggedIterator &operator+=(qsizetype j) { Iterator::operator+=(j); return *this; }
+ QTaggedIterator &operator-=(qsizetype j) { Iterator::operator-=(j); return *this; }
+ QTaggedIterator operator+(qsizetype j) const { return QTaggedIterator(Iterator::operator+(j)); }
+ QTaggedIterator operator-(qsizetype j) const { return QTaggedIterator(Iterator::operator-(j)); }
+ qsizetype operator-(const QTaggedIterator &j) const { return Iterator::operator-(j); }
+
+ bool operator<(const QTaggedIterator &j) { return operator-(j) < 0; }
+ bool operator>=(const QTaggedIterator &j) { return !operator<(j); }
+ bool operator>(const QTaggedIterator &j) { return operator-(j) > 0; }
+ bool operator<=(const QTaggedIterator &j) { return !operator>(j); }
+
+ friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; }
+};
+
+template<class Container>
+class QIterable;
+
+template<class Container>
+class QBaseIterator
+{
+private:
+ QtPrivate::QConstPreservingPointer<QIterable<Container>> m_iterable;
+ void *m_iterator = nullptr;
+
+protected:
+ QBaseIterator() = default;
+ QBaseIterator(const QIterable<Container> *iterable, void *iterator)
+ : m_iterable(iterable), m_iterator(iterator)
+ {}
+
+ QBaseIterator(QIterable<Container> *iterable, void *iterator)
+ : m_iterable(iterable), m_iterator(iterator)
+ {}
+
+ QBaseIterator(QBaseIterator &&other)
+ : m_iterable(std::move(other.m_iterable)), m_iterator(std::move(other.m_iterator))
+ {
+ other.m_iterator = nullptr;
+ }
+
+ QBaseIterator(const QBaseIterator &other)
+ : m_iterable(other.m_iterable)
+ {
+ initIterator(other.m_iterator);
+ }
+
+ ~QBaseIterator() { clearIterator(); }
+
+ QBaseIterator &operator=(QBaseIterator &&other)
+ {
+ if (this != &other) {
+ clearIterator();
+ m_iterable = std::move(other.m_iterable);
+ m_iterator = std::move(other.m_iterator);
+ other.m_iterator = nullptr;
+ }
+ return *this;
+ }
+
+ QBaseIterator &operator=(const QBaseIterator &other)
+ {
+ if (this != &other) {
+ clearIterator();
+ m_iterable = other.m_iterable;
+ initIterator(other.m_iterator);
+ }
+ return *this;
+ }
+
+ QIterable<Container> *mutableIterable() const
+ {
+ return m_iterable.mutablePointer();
+ }
+
+ const QIterable<Container> *constIterable() const
+ {
+ return m_iterable.constPointer();
+ }
+
+ void initIterator(const void *copy)
+ {
+ if (!copy)
+ return;
+ if (auto *mutableIt = mutableIterable()) {
+ m_iterator = metaContainer().begin(mutableIt->mutableIterable());
+ metaContainer().copyIterator(m_iterator, copy);
+ } else if (auto *constIt = constIterable()) {
+ m_iterator = metaContainer().constBegin(constIt->constIterable());
+ metaContainer().copyConstIterator(m_iterator, copy);
+ }
+ }
+
+ void clearIterator()
+ {
+ if (!m_iterator)
+ return;
+ if (mutableIterable())
+ metaContainer().destroyIterator(m_iterator);
+ else
+ metaContainer().destroyConstIterator(m_iterator);
+ }
+
+public:
+ void *mutableIterator() { return m_iterator; }
+ const void *constIterator() const { return m_iterator; }
+ Container metaContainer() const { return constIterable()->m_metaContainer; }
+};
+
+template<class Container>
+struct QIterator : public QBaseIterator<Container>
+{
+public:
+ using difference_type = qsizetype;
+
+ explicit QIterator(QIterable<Container> *iterable, void *iterator)
+ : QBaseIterator<Container>(iterable, iterator)
+ {
+ Q_ASSERT(iterable != nullptr);
+ }
+
+ bool operator==(const QIterator &o) const
+ {
+ return this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
+ }
+
+ bool operator!=(const QIterator &o) const
+ {
+ return !this->metaContainer().compareIterator(this->constIterator(), o.constIterator());
+ }
+
+ QIterator &operator++()
+ {
+ this->metaContainer().advanceIterator(this->mutableIterator(), 1);
+ return *this;
+ }
+
+ QIterator operator++(int)
+ {
+ QIterable<Container> *iterable = this->mutableIterable();
+ const Container metaContainer = this->metaContainer();
+ QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
+ metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceIterator(this->mutableIterator(), 1);
+ return result;
+ }
+
+ QIterator &operator--()
+ {
+ this->metaContainer().advanceIterator(this->mutableIterator(), -1);
+ return *this;
+ }
+
+ QIterator operator--(int)
+ {
+ QIterable<Container> *iterable = this->mutableIterable();
+ const Container metaContainer = this->metaContainer();
+ QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
+ metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceIterator(this->mutableIterator(), -1);
+ return result;
+ }
+
+ QIterator &operator+=(qsizetype j)
+ {
+ this->metaContainer().advanceIterator(this->mutableIterator(), j);
+ return *this;
+ }
+
+ QIterator &operator-=(qsizetype j)
+ {
+ this->metaContainer().advanceIterator(this->mutableIterator(), -j);
+ return *this;
+ }
+
+ QIterator operator+(qsizetype j) const
+ {
+ QIterable<Container> *iterable = this->mutableIterable();
+ const Container metaContainer = this->metaContainer();
+ QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
+ metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceIterator(result.mutableIterator(), j);
+ return result;
+ }
+
+ QIterator operator-(qsizetype j) const
+ {
+ QIterable<Container> *iterable = this->mutableIterable();
+ const Container metaContainer = this->metaContainer();
+ QIterator result(iterable, metaContainer.begin(iterable->mutableIterable()));
+ metaContainer.copyIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceIterator(result.mutableIterator(), -j);
+ return result;
+ }
+
+ qsizetype operator-(const QIterator &j) const
+ {
+ return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
+ }
+
+ friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; }
+};
+
+template<class Container>
+struct QConstIterator : public QBaseIterator<Container>
+{
+public:
+ using difference_type = qsizetype;
+
+ explicit QConstIterator(const QIterable<Container> *iterable, void *iterator)
+ : QBaseIterator<Container>(iterable, iterator)
+ {
+ }
+
+ bool operator==(const QConstIterator &o) const
+ {
+ return this->metaContainer().compareConstIterator(
+ this->constIterator(), o.constIterator());
+ }
+
+ bool operator!=(const QConstIterator &o) const
+ {
+ return !this->metaContainer().compareConstIterator(
+ this->constIterator(), o.constIterator());
+ }
+
+ QConstIterator &operator++()
+ {
+ this->metaContainer().advanceConstIterator(this->mutableIterator(), 1);
+ return *this;
+ }
+
+ QConstIterator operator++(int)
+ {
+ const Container metaContainer = this->metaContainer();
+ QConstIterator result(this->constIterable(), metaContainer.constBegin(
+ this->constIterable()->constIterable()));
+ metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceConstIterator(this->mutableIterator(), 1);
+ return result;
+ }
+
+ QConstIterator &operator--()
+ {
+ this->metaContainer().advanceConstIterator(this->mutableIterator(), -1);
+ return *this;
+ }
+
+ QConstIterator operator--(int)
+ {
+ const Container metaContainer = this->metaContainer();
+ QConstIterator result(this->constIterable(), metaContainer.constBegin(
+ this->constIterable()->constIterable()));
+ metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceConstIterator(this->mutableIterator(), -1);
+ return result;
+ }
+
+ QConstIterator &operator+=(qsizetype j)
+ {
+ this->metaContainer().advanceConstIterator(this->mutableIterator(), j);
+ return *this;
+ }
+
+ QConstIterator &operator-=(qsizetype j)
+ {
+ this->metaContainer().advanceConstIterator(this->mutableIterator(), -j);
+ return *this;
+ }
+
+ QConstIterator operator+(qsizetype j) const
+ {
+ const Container metaContainer = this->metaContainer();
+ QConstIterator result(
+ this->constIterable(),
+ metaContainer.constBegin(this->constIterable()->constIterable()));
+ metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceConstIterator(result.mutableIterator(), j);
+ return result;
+ }
+
+ QConstIterator operator-(qsizetype j) const
+ {
+ const Container metaContainer = this->metaContainer();
+ QConstIterator result(this->constIterable(), metaContainer.constBegin(
+ this->constIterable()->constIterable()));
+ metaContainer.copyConstIterator(result.mutableIterator(), this->constIterator());
+ metaContainer.advanceConstIterator(result.mutableIterator(), -j);
+ return result;
+ }
+
+ qsizetype operator-(const QConstIterator &j) const
+ {
+ return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());
+ }
+
+ friend inline QConstIterator operator+(qsizetype j, const QConstIterator &k)
+ {
+ return k + j;
+ }
+};
+
+template<class Container>
+class QIterable
+{
+ friend class QBaseIterator<Container>;
+
+protected:
+ uint m_revision = 0;
+ QtPrivate::QConstPreservingPointer<void, quint16> m_iterable;
+ Container m_metaContainer;
+
+public:
+ template<class T>
+ QIterable(const Container &metaContainer, const T *p)
+ : m_iterable(p), m_metaContainer(metaContainer)
+ {
+ }
+
+ template<class T>
+ QIterable(const Container &metaContainer, T *p)
+ : m_iterable(p), m_metaContainer(metaContainer)
+ {
+ }
+
+ template<typename Pointer>
+ QIterable(const Container &metaContainer, Pointer iterable)
+ : m_iterable(iterable), m_metaContainer(metaContainer)
+ {
+ }
+
+ QIterable(const Container &metaContainer, qsizetype alignment, const void *p)
+ : m_iterable(p, alignment), m_metaContainer(metaContainer)
+ {
+ }
+
+ QIterable(const Container &metaContainer, qsizetype alignment, void *p)
+ : m_iterable(p, alignment), m_metaContainer(metaContainer)
+ {
+ }
+
+ bool canInputIterate() const
+ {
+ return m_metaContainer.hasInputIterator();
+ }
+
+ bool canForwardIterate() const
+ {
+ return m_metaContainer.hasForwardIterator();
+ }
+
+ bool canReverseIterate() const
+ {
+ return m_metaContainer.hasBidirectionalIterator();
+ }
+
+ bool canRandomAccessIterate() const
+ {
+ return m_metaContainer.hasRandomAccessIterator();
+ }
+
+ const void *constIterable() const { return m_iterable.constPointer(); }
+ void *mutableIterable() { return m_iterable.mutablePointer(); }
+
+ QConstIterator<Container> constBegin() const
+ {
+ return QConstIterator(this, m_metaContainer.constBegin(constIterable()));
+ }
+
+ QConstIterator<Container> constEnd() const
+ {
+ return QConstIterator(this, m_metaContainer.constEnd(constIterable()));
+ }
+
+ QIterator<Container> mutableBegin()
+ {
+ return QIterator(this, m_metaContainer.begin(mutableIterable()));
+ }
+
+ QIterator<Container> mutableEnd()
+ {
+ return QIterator(this, m_metaContainer.end(mutableIterable()));
+ }
+
+ qsizetype size() const
+ {
+ const void *container = constIterable();
+ if (m_metaContainer.hasSize())
+ return m_metaContainer.size(container);
+ if (!m_metaContainer.hasConstIterator())
+ return -1;
+
+ const void *begin = m_metaContainer.constBegin(container);
+ const void *end = m_metaContainer.constEnd(container);
+ const qsizetype size = m_metaContainer.diffConstIterator(end, begin);
+ m_metaContainer.destroyConstIterator(begin);
+ m_metaContainer.destroyConstIterator(end);
+ return size;
+ }
+
+ Container metaContainer() const
+ {
+ return m_metaContainer;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QITERABLE_H
diff --git a/src/corelib/kernel/qiterable_p.h b/src/corelib/kernel/qiterable_p.h
new file mode 100644
index 0000000000..6a9c804745
--- /dev/null
+++ b/src/corelib/kernel/qiterable_p.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QITERABLE_P_H
+#define QITERABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QIterablePrivate {
+
+template<typename Callback>
+static QVariant retrieveElement(QMetaType type, Callback callback)
+{
+ QVariant v(type);
+ void *dataPtr;
+ if (type == QMetaType::fromType<QVariant>())
+ dataPtr = &v;
+ else
+ dataPtr = v.data();
+ callback(dataPtr);
+ return v;
+}
+
+} // namespace QIterablePrivate
+
+QT_END_NAMESPACE
+
+#endif // QITERABLE_P_H
diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp
deleted file mode 100644
index 5f652d70e3..0000000000
--- a/src/corelib/kernel/qjni.cpp
+++ /dev/null
@@ -1,2386 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qjni_p.h"
-#include "qjnihelpers_p.h"
-#include <QtCore/qthreadstorage.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qstring.h>
-#include <QtCore/QThread>
-#include <QtCore/QReadWriteLock>
-
-QT_BEGIN_NAMESPACE
-
-static inline QLatin1String keyBase()
-{
- return QLatin1String("%1%2:%3");
-}
-
-static QString qt_convertJString(jstring string)
-{
- QJNIEnvironmentPrivate env;
- int strLength = env->GetStringLength(string);
- QString res(strLength, Qt::Uninitialized);
- env->GetStringRegion(string, 0, strLength, reinterpret_cast<jchar *>(res.data()));
- return res;
-}
-
-static inline bool exceptionCheckAndClear(JNIEnv *env)
-{
- if (Q_UNLIKELY(env->ExceptionCheck())) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- return true;
- }
-
- return false;
-}
-
-typedef QHash<QString, jclass> JClassHash;
-Q_GLOBAL_STATIC(JClassHash, cachedClasses)
-Q_GLOBAL_STATIC(QReadWriteLock, cachedClassesLock)
-
-static QByteArray toBinaryEncClassName(const QByteArray &className)
-{
- return QByteArray(className).replace('/', '.');
-}
-
-static jclass getCachedClass(const QByteArray &classBinEnc, bool *isCached = 0)
-{
- QReadLocker locker(cachedClassesLock);
- const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(QString::fromLatin1(classBinEnc));
- const bool found = (it != cachedClasses->constEnd());
-
- if (isCached != 0)
- *isCached = found;
-
- return found ? it.value() : 0;
-}
-
-inline static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false)
-{
- const QByteArray &binEncClassName = binEncoded ? className : toBinaryEncClassName(className);
-
- bool isCached = false;
- jclass clazz = getCachedClass(binEncClassName, &isCached);
- if (clazz != 0 || isCached)
- return clazz;
-
- QJNIObjectPrivate classLoader(QtAndroidPrivate::classLoader());
- if (!classLoader.isValid())
- return 0;
-
- QWriteLocker locker(cachedClassesLock);
- // did we lose the race?
- const QLatin1String key(binEncClassName);
- const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(key);
- if (it != cachedClasses->constEnd())
- return it.value();
-
- QJNIObjectPrivate stringName = QJNIObjectPrivate::fromString(key);
- QJNIObjectPrivate classObject = classLoader.callObjectMethod("loadClass",
- "(Ljava/lang/String;)Ljava/lang/Class;",
- stringName.object());
-
- if (!exceptionCheckAndClear(env) && classObject.isValid())
- clazz = static_cast<jclass>(env->NewGlobalRef(classObject.object()));
-
- cachedClasses->insert(key, clazz);
- return clazz;
-}
-
-typedef QHash<QString, jmethodID> JMethodIDHash;
-Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID)
-Q_GLOBAL_STATIC(QReadWriteLock, cachedMethodIDLock)
-
-static inline jmethodID getMethodID(JNIEnv *env,
- jclass clazz,
- const char *name,
- const char *sig,
- bool isStatic = false)
-{
- jmethodID id = isStatic ? env->GetStaticMethodID(clazz, name, sig)
- : env->GetMethodID(clazz, name, sig);
-
- if (exceptionCheckAndClear(env))
- return 0;
-
- return id;
-}
-
-static jmethodID getCachedMethodID(JNIEnv *env,
- jclass clazz,
- const QByteArray &className,
- const char *name,
- const char *sig,
- bool isStatic = false)
-{
- if (className.isEmpty())
- return getMethodID(env, clazz, name, sig, isStatic);
-
- const QString key = keyBase().arg(QLatin1String(className), QLatin1String(name), QLatin1String(sig));
- QHash<QString, jmethodID>::const_iterator it;
-
- {
- QReadLocker locker(cachedMethodIDLock);
- it = cachedMethodID->constFind(key);
- if (it != cachedMethodID->constEnd())
- return it.value();
- }
-
- {
- QWriteLocker locker(cachedMethodIDLock);
- it = cachedMethodID->constFind(key);
- if (it != cachedMethodID->constEnd())
- return it.value();
-
- jmethodID id = getMethodID(env, clazz, name, sig, isStatic);
-
- cachedMethodID->insert(key, id);
- return id;
- }
-}
-
-typedef QHash<QString, jfieldID> JFieldIDHash;
-Q_GLOBAL_STATIC(JFieldIDHash, cachedFieldID)
-Q_GLOBAL_STATIC(QReadWriteLock, cachedFieldIDLock)
-
-static inline jfieldID getFieldID(JNIEnv *env,
- jclass clazz,
- const char *name,
- const char *sig,
- bool isStatic = false)
-{
- jfieldID id = isStatic ? env->GetStaticFieldID(clazz, name, sig)
- : env->GetFieldID(clazz, name, sig);
-
- if (exceptionCheckAndClear(env))
- return 0;
-
- return id;
-}
-
-static jfieldID getCachedFieldID(JNIEnv *env,
- jclass clazz,
- const QByteArray &className,
- const char *name,
- const char *sig,
- bool isStatic = false)
-{
- if (className.isNull())
- return getFieldID(env, clazz, name, sig, isStatic);
-
- const QString key = keyBase().arg(QLatin1String(className), QLatin1String(name), QLatin1String(sig));
- QHash<QString, jfieldID>::const_iterator it;
-
- {
- QReadLocker locker(cachedFieldIDLock);
- it = cachedFieldID->constFind(key);
- if (it != cachedFieldID->constEnd())
- return it.value();
- }
-
- {
- QWriteLocker locker(cachedFieldIDLock);
- it = cachedFieldID->constFind(key);
- if (it != cachedFieldID->constEnd())
- return it.value();
-
- jfieldID id = getFieldID(env, clazz, name, sig, isStatic);
-
- cachedFieldID->insert(key, id);
- return id;
- }
-}
-
-void QJNILocalRefDeleter::cleanup(jobject obj)
-{
- if (obj == 0)
- return;
-
- QJNIEnvironmentPrivate env;
- env->DeleteLocalRef(obj);
-}
-
-class QJNIEnvironmentPrivateTLS
-{
-public:
- inline ~QJNIEnvironmentPrivateTLS()
- {
- QtAndroidPrivate::javaVM()->DetachCurrentThread();
- }
-};
-
-Q_GLOBAL_STATIC(QThreadStorage<QJNIEnvironmentPrivateTLS *>, jniEnvTLS)
-
-static const char qJniThreadName[] = "QtThread";
-
-QJNIEnvironmentPrivate::QJNIEnvironmentPrivate()
- : jniEnv(0)
-{
- JavaVM *vm = QtAndroidPrivate::javaVM();
- const jint ret = vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6);
- if (ret == JNI_OK) // Already attached
- return;
-
- if (ret == JNI_EDETACHED) { // We need to (re-)attach
- JavaVMAttachArgs args = { JNI_VERSION_1_6, qJniThreadName, nullptr };
- if (vm->AttachCurrentThread(&jniEnv, &args) != JNI_OK)
- return;
-
- if (!jniEnvTLS->hasLocalData()) // If we attached the thread we own it.
- jniEnvTLS->setLocalData(new QJNIEnvironmentPrivateTLS);
- }
-}
-
-JNIEnv *QJNIEnvironmentPrivate::operator->()
-{
- return jniEnv;
-}
-
-jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env)
-{
- const QByteArray &classDotEnc = toBinaryEncClassName(className);
- bool isCached = false;
- jclass clazz = getCachedClass(classDotEnc, &isCached);
-
- const bool found = (clazz != 0) || (clazz == 0 && isCached);
-
- if (found)
- return clazz;
-
- const QLatin1String key(classDotEnc);
- if (env != 0) { // We got an env. pointer (We expect this to be the right env. and call FindClass())
- QWriteLocker locker(cachedClassesLock);
- const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(key);
- // Did we lose the race?
- if (it != cachedClasses->constEnd())
- return it.value();
-
- jclass fclazz = env->FindClass(className);
- if (!exceptionCheckAndClear(env)) {
- clazz = static_cast<jclass>(env->NewGlobalRef(fclazz));
- env->DeleteLocalRef(fclazz);
- }
-
- if (clazz != 0)
- cachedClasses->insert(key, clazz);
- }
-
- if (clazz == 0) // We didn't get an env. pointer or we got one with the WRONG class loader...
- clazz = loadClass(classDotEnc, QJNIEnvironmentPrivate(), true);
-
- return clazz;
-}
-
-QJNIEnvironmentPrivate::operator JNIEnv* () const
-{
- return jniEnv;
-}
-
-QJNIEnvironmentPrivate::~QJNIEnvironmentPrivate()
-{
-}
-
-QJNIObjectData::QJNIObjectData()
- : m_jobject(0),
- m_jclass(0),
- m_own_jclass(true)
-{
-
-}
-
-QJNIObjectData::~QJNIObjectData()
-{
- QJNIEnvironmentPrivate env;
- if (m_jobject)
- env->DeleteGlobalRef(m_jobject);
- if (m_jclass && m_own_jclass)
- env->DeleteGlobalRef(m_jclass);
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate()
- : d(new QJNIObjectData())
-{
-
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(const char *className)
- : d(new QJNIObjectData())
-{
- QJNIEnvironmentPrivate env;
- d->m_className = toBinaryEncClassName(className);
- d->m_jclass = loadClass(d->m_className, env, true);
- d->m_own_jclass = false;
- if (d->m_jclass) {
- // get default constructor
- jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "<init>", "()V");
- if (constructorId) {
- jobject obj = env->NewObject(d->m_jclass, constructorId);
- if (obj) {
- d->m_jobject = env->NewGlobalRef(obj);
- env->DeleteLocalRef(obj);
- }
- }
- }
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, ...)
- : d(new QJNIObjectData())
-{
- QJNIEnvironmentPrivate env;
- d->m_className = toBinaryEncClassName(className);
- d->m_jclass = loadClass(d->m_className, env, true);
- d->m_own_jclass = false;
- if (d->m_jclass) {
- jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "<init>", sig);
- if (constructorId) {
- va_list args;
- va_start(args, sig);
- jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
- va_end(args);
- if (obj) {
- d->m_jobject = env->NewGlobalRef(obj);
- env->DeleteLocalRef(obj);
- }
- }
- }
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, const QVaListPrivate &args)
- : d(new QJNIObjectData())
-{
- QJNIEnvironmentPrivate env;
- d->m_className = toBinaryEncClassName(className);
- d->m_jclass = loadClass(d->m_className, env, true);
- d->m_own_jclass = false;
- if (d->m_jclass) {
- jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "<init>", sig);
- if (constructorId) {
- jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
- if (obj) {
- d->m_jobject = env->NewGlobalRef(obj);
- env->DeleteLocalRef(obj);
- }
- }
- }
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz)
- : d(new QJNIObjectData())
-{
- QJNIEnvironmentPrivate env;
- d->m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz));
- if (d->m_jclass) {
- // get default constructor
- jmethodID constructorId = getMethodID(env, d->m_jclass, "<init>", "()V");
- if (constructorId) {
- jobject obj = env->NewObject(d->m_jclass, constructorId);
- if (obj) {
- d->m_jobject = env->NewGlobalRef(obj);
- env->DeleteLocalRef(obj);
- }
- }
- }
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, ...)
- : d(new QJNIObjectData())
-{
- QJNIEnvironmentPrivate env;
- if (clazz) {
- d->m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz));
- if (d->m_jclass) {
- jmethodID constructorId = getMethodID(env, d->m_jclass, "<init>", sig);
- if (constructorId) {
- va_list args;
- va_start(args, sig);
- jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
- va_end(args);
- if (obj) {
- d->m_jobject = env->NewGlobalRef(obj);
- env->DeleteLocalRef(obj);
- }
- }
- }
- }
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, const QVaListPrivate &args)
- : d(new QJNIObjectData())
-{
- QJNIEnvironmentPrivate env;
- if (clazz) {
- d->m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz));
- if (d->m_jclass) {
- jmethodID constructorId = getMethodID(env, d->m_jclass, "<init>", sig);
- if (constructorId) {
- jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
- if (obj) {
- d->m_jobject = env->NewGlobalRef(obj);
- env->DeleteLocalRef(obj);
- }
- }
- }
- }
-}
-
-QJNIObjectPrivate::QJNIObjectPrivate(jobject obj)
- : d(new QJNIObjectData())
-{
- if (!obj)
- return;
-
- QJNIEnvironmentPrivate env;
- d->m_jobject = env->NewGlobalRef(obj);
- jclass cls = env->GetObjectClass(obj);
- d->m_jclass = static_cast<jclass>(env->NewGlobalRef(cls));
- env->DeleteLocalRef(cls);
-}
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callMethodV<void>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- env->CallVoidMethodV(d->m_jobject, id, args);
- }
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callMethod<void>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- callMethodV<void>(methodName, sig, args);
- va_end(args);
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callMethodV<jboolean>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jboolean res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallBooleanMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callMethod<jboolean>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jboolean res = callMethodV<jboolean>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callMethodV<jbyte>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jbyte res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallByteMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callMethod<jbyte>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jbyte res = callMethodV<jbyte>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callMethodV<jchar>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jchar res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallCharMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callMethod<jchar>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jchar res = callMethodV<jchar>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callMethodV<jshort>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jshort res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallShortMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callMethod<jshort>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jshort res = callMethodV<jshort>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callMethodV<jint>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jint res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallIntMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callMethod<jint>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jint res = callMethodV<jint>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callMethodV<jlong>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jlong res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallLongMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callMethod<jlong>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jlong res = callMethodV<jlong>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callMethodV<jfloat>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jfloat res = 0.f;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallFloatMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callMethod<jfloat>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jfloat res = callMethodV<jfloat>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callMethodV<jdouble>(const char *methodName, const char *sig, va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jdouble res = 0.;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallDoubleMethodV(d->m_jobject, id, args);
- }
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callMethod<jdouble>(const char *methodName, const char *sig, ...) const
-{
- va_list args;
- va_start(args, sig);
- jdouble res = callMethodV<jdouble>(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callMethod<void>(const char *methodName) const
-{
- callMethod<void>(methodName, "()V");
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callMethod<jboolean>(const char *methodName) const
-{
- return callMethod<jboolean>(methodName, "()Z");
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callMethod<jbyte>(const char *methodName) const
-{
- return callMethod<jbyte>(methodName, "()B");
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callMethod<jchar>(const char *methodName) const
-{
- return callMethod<jchar>(methodName, "()C");
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callMethod<jshort>(const char *methodName) const
-{
- return callMethod<jshort>(methodName, "()S");
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callMethod<jint>(const char *methodName) const
-{
- return callMethod<jint>(methodName, "()I");
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callMethod<jlong>(const char *methodName) const
-{
- return callMethod<jlong>(methodName, "()J");
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callMethod<jfloat>(const char *methodName) const
-{
- return callMethod<jfloat>(methodName, "()F");
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callMethod<jdouble>(const char *methodName) const
-{
- return callMethod<jdouble>(methodName, "()D");
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callStaticMethodV<void>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- env->CallStaticVoidMethodV(clazz, id, args);
- }
- }
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callStaticMethod<void>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- callStaticMethodV<void>(className, methodName, sig, args);
- va_end(args);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callStaticMethodV<void>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- env->CallStaticVoidMethodV(clazz, id, args);
- }
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callStaticMethod<void>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- callStaticMethodV<void>(clazz, methodName, sig, args);
- va_end(args);
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callStaticMethodV<jboolean>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jboolean res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticBooleanMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callStaticMethod<jboolean>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jboolean res = callStaticMethodV<jboolean>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callStaticMethodV<jboolean>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jboolean res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticBooleanMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callStaticMethod<jboolean>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jboolean res = callStaticMethodV<jboolean>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callStaticMethodV<jbyte>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jbyte res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticByteMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callStaticMethod<jbyte>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jbyte res = callStaticMethodV<jbyte>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callStaticMethodV<jbyte>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jbyte res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticByteMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callStaticMethod<jbyte>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jbyte res = callStaticMethodV<jbyte>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callStaticMethodV<jchar>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jchar res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticCharMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callStaticMethod<jchar>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jchar res = callStaticMethodV<jchar>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callStaticMethodV<jchar>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jchar res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticCharMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callStaticMethod<jchar>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jchar res = callStaticMethodV<jchar>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callStaticMethodV<jshort>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jshort res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticShortMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callStaticMethod<jshort>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jshort res = callStaticMethodV<jshort>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callStaticMethodV<jshort>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jshort res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticShortMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callStaticMethod<jshort>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jshort res = callStaticMethodV<jshort>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callStaticMethodV<jint>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jint res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticIntMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callStaticMethod<jint>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jint res = callStaticMethodV<jint>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callStaticMethodV<jint>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jint res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticIntMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callStaticMethod<jint>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jint res = callStaticMethodV<jint>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callStaticMethodV<jlong>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jlong res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticLongMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callStaticMethod<jlong>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jlong res = callStaticMethodV<jlong>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callStaticMethodV<jlong>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jlong res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticLongMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callStaticMethod<jlong>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jlong res = callStaticMethodV<jlong>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callStaticMethodV<jfloat>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jfloat res = 0.f;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticFloatMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callStaticMethod<jfloat>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jfloat res = callStaticMethodV<jfloat>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callStaticMethodV<jfloat>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jfloat res = 0.f;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticFloatMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callStaticMethod<jfloat>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jfloat res = callStaticMethodV<jfloat>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callStaticMethodV<jdouble>(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jdouble res = 0.;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticDoubleMethodV(clazz, id, args);
- }
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callStaticMethod<jdouble>(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jdouble res = callStaticMethodV<jdouble>(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callStaticMethodV<jdouble>(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jdouble res = 0.;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticDoubleMethodV(clazz, id, args);
- }
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callStaticMethod<jdouble>(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- jdouble res = callStaticMethodV<jdouble>(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callStaticMethod<void>(const char *className, const char *methodName)
-{
- callStaticMethod<void>(className, methodName, "()V");
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::callStaticMethod<void>(jclass clazz, const char *methodName)
-{
- callStaticMethod<void>(clazz, methodName, "()V");
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callStaticMethod<jboolean>(const char *className, const char *methodName)
-{
- return callStaticMethod<jboolean>(className, methodName, "()Z");
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::callStaticMethod<jboolean>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jboolean>(clazz, methodName, "()Z");
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callStaticMethod<jbyte>(const char *className, const char *methodName)
-{
- return callStaticMethod<jbyte>(className, methodName, "()B");
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::callStaticMethod<jbyte>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jbyte>(clazz, methodName, "()B");
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callStaticMethod<jchar>(const char *className, const char *methodName)
-{
- return callStaticMethod<jchar>(className, methodName, "()C");
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::callStaticMethod<jchar>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jchar>(clazz, methodName, "()C");
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callStaticMethod<jshort>(const char *className, const char *methodName)
-{
- return callStaticMethod<jshort>(className, methodName, "()S");
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::callStaticMethod<jshort>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jshort>(clazz, methodName, "()S");
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callStaticMethod<jint>(const char *className, const char *methodName)
-{
- return callStaticMethod<jint>(className, methodName, "()I");
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::callStaticMethod<jint>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jint>(clazz, methodName, "()I");
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callStaticMethod<jlong>(const char *className, const char *methodName)
-{
- return callStaticMethod<jlong>(className, methodName, "()J");
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::callStaticMethod<jlong>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jlong>(clazz, methodName, "()J");
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callStaticMethod<jfloat>(const char *className, const char *methodName)
-{
- return callStaticMethod<jfloat>(className, methodName, "()F");
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::callStaticMethod<jfloat>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jfloat>(clazz, methodName, "()F");
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callStaticMethod<jdouble>(const char *className, const char *methodName)
-{
- return callStaticMethod<jdouble>(className, methodName, "()D");
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::callStaticMethod<jdouble>(jclass clazz, const char *methodName)
-{
- return callStaticMethod<jdouble>(clazz, methodName, "()D");
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::callObjectMethodV(const char *methodName,
- const char *sig,
- va_list args) const
-{
- QJNIEnvironmentPrivate env;
- jobject res = 0;
- jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
- if (id) {
- res = env->CallObjectMethodV(d->m_jobject, id, args);
- if (res && env->ExceptionCheck())
- res = 0;
- }
-
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName,
- const char *sig,
- ...) const
-{
- va_list args;
- va_start(args, sig);
- QJNIObjectPrivate res = callObjectMethodV(methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jstring>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()Ljava/lang/String;");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jbooleanArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[Z");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jbyteArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[B");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jshortArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[S");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jintArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[I");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jlongArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[J");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jfloatArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[F");
-}
-
-template <>
-Q_CORE_EXPORT QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod<jdoubleArray>(const char *methodName) const
-{
- return callObjectMethod(methodName, "()[D");
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(const char *className,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jobject res = 0;
- jclass clazz = loadClass(className, env);
- if (clazz) {
- jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
- if (id) {
- res = env->CallStaticObjectMethodV(clazz, id, args);
- if (res && env->ExceptionCheck())
- res = 0;
- }
- }
-
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *className,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- QJNIObjectPrivate res = callStaticObjectMethodV(className, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args)
-{
- QJNIEnvironmentPrivate env;
- jobject res = 0;
- jmethodID id = getMethodID(env, clazz, methodName, sig, true);
- if (id) {
- res = env->CallStaticObjectMethodV(clazz, id, args);
- if (res && env->ExceptionCheck())
- res = 0;
- }
-
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz,
- const char *methodName,
- const char *sig,
- ...)
-{
- va_list args;
- va_start(args, sig);
- QJNIObjectPrivate res = callStaticObjectMethodV(clazz, methodName, sig, args);
- va_end(args);
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::getField<jboolean>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jboolean res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Z");
- if (id)
- res = env->GetBooleanField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::getField<jbyte>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jbyte res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "B");
- if (id)
- res = env->GetByteField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::getField<jchar>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jchar res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "C");
- if (id)
- res = env->GetCharField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::getField<jshort>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jshort res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "S");
- if (id)
- res = env->GetShortField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::getField<jint>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jint res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "I");
- if (id)
- res = env->GetIntField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::getField<jlong>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jlong res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "J");
- if (id)
- res = env->GetLongField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::getField<jfloat>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jfloat res = 0.f;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "F");
- if (id)
- res = env->GetFloatField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::getField<jdouble>(const char *fieldName) const
-{
- QJNIEnvironmentPrivate env;
- jdouble res = 0.;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "D");
- if (id)
- res = env->GetDoubleField(d->m_jobject, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::getStaticField<jboolean>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jboolean res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, "Z", true);
- if (id)
- res = env->GetStaticBooleanField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jboolean QJNIObjectPrivate::getStaticField<jboolean>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "Z", true);
- if (id == 0)
- return 0;
-
- return env->GetStaticBooleanField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::getStaticField<jbyte>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jbyte res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, "B", true);
- if (id)
- res = env->GetStaticByteField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jbyte QJNIObjectPrivate::getStaticField<jbyte>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "B", true);
- if (id == 0)
- return 0;
-
- return env->GetStaticByteField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::getStaticField<jchar>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jchar res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, "C", true);
- if (id)
- res = env->GetStaticCharField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jchar QJNIObjectPrivate::getStaticField<jchar>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "C", true);
- if (id == 0)
- return 0;
-
- return env->GetStaticCharField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::getStaticField<jshort>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jshort res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, "S", true);
- if (id)
- res = env->GetStaticShortField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jshort QJNIObjectPrivate::getStaticField<jshort>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "S", true);
- if (id == 0)
- return 0;
-
- return env->GetStaticShortField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::getStaticField<jint>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jint res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, "I", true);
- if (id)
- res = env->GetStaticIntField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jint QJNIObjectPrivate::getStaticField<jint>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "I", true);
- if (id == 0)
- return 0;
-
- return env->GetStaticIntField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::getStaticField<jlong>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jlong res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, "J", true);
- if (id)
- res = env->GetStaticLongField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jlong QJNIObjectPrivate::getStaticField<jlong>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "J", true);
- if (id == 0)
- return 0;
-
- return env->GetStaticLongField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::getStaticField<jfloat>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jfloat res = 0.f;
- jfieldID id = getFieldID(env, clazz, fieldName, "F", true);
- if (id)
- res = env->GetStaticFloatField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jfloat QJNIObjectPrivate::getStaticField<jfloat>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0.f;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "F", true);
- if (id == 0)
- return 0.f;
-
- return env->GetStaticFloatField(clazz, id);
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::getStaticField<jdouble>(jclass clazz, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jdouble res = 0.;
- jfieldID id = getFieldID(env, clazz, fieldName, "D", true);
- if (id)
- res = env->GetStaticDoubleField(clazz, id);
-
- return res;
-}
-
-template <>
-Q_CORE_EXPORT jdouble QJNIObjectPrivate::getStaticField<jdouble>(const char *className, const char *fieldName)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return 0.;
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "D", true);
- if (id == 0)
- return 0.;
-
- return env->GetStaticDoubleField(clazz, id);
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName,
- const char *sig) const
-{
- QJNIEnvironmentPrivate env;
- jobject res = 0;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig);
- if (id) {
- res = env->GetObjectField(d->m_jobject, id);
- if (res && env->ExceptionCheck())
- res = 0;
- }
-
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(const char *className,
- const char *fieldName,
- const char *sig)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return QJNIObjectPrivate();
-
- jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, sig, true);
- if (id == 0)
- return QJNIObjectPrivate();
-
- jobject res = env->GetStaticObjectField(clazz, id);
- if (res && env->ExceptionCheck())
- res = 0;
-
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz,
- const char *fieldName,
- const char *sig)
-{
- QJNIEnvironmentPrivate env;
- jobject res = 0;
- jfieldID id = getFieldID(env, clazz, fieldName, sig, true);
- if (id) {
- res = env->GetStaticObjectField(clazz, id);
- if (res && env->ExceptionCheck())
- res = 0;
- }
-
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jboolean>(const char *fieldName, jboolean value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Z");
- if (id)
- env->SetBooleanField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jbyte>(const char *fieldName, jbyte value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "B");
- if (id)
- env->SetByteField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jchar>(const char *fieldName, jchar value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "C");
- if (id)
- env->SetCharField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jshort>(const char *fieldName, jshort value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "S");
- if (id)
- env->SetShortField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jint>(const char *fieldName, jint value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "I");
- if (id)
- env->SetIntField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jlong>(const char *fieldName, jlong value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "J");
- if (id)
- env->SetLongField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jfloat>(const char *fieldName, jfloat value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "F");
- if (id)
- env->SetFloatField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jdouble>(const char *fieldName, jdouble value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "D");
- if (id)
- env->SetDoubleField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jbooleanArray>(const char *fieldName, jbooleanArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[Z");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jbyteArray>(const char *fieldName, jbyteArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[B");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jcharArray>(const char *fieldName, jcharArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[C");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jshortArray>(const char *fieldName, jshortArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[S");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jintArray>(const char *fieldName, jintArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[I");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jlongArray>(const char *fieldName, jlongArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[J");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jfloatArray>(const char *fieldName, jfloatArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[F");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jdoubleArray>(const char *fieldName, jdoubleArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[D");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jstring>(const char *fieldName, jstring value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Ljava/lang/String;");
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jobject>(const char *fieldName,
- const char *sig,
- jobject value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig);
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setField<jobjectArray>(const char *fieldName,
- const char *sig,
- jobjectArray value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig);
- if (id)
- env->SetObjectField(d->m_jobject, id, value);
-
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jboolean>(jclass clazz,
- const char *fieldName,
- jboolean value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "Z", true);
- if (id)
- env->SetStaticBooleanField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jboolean>(const char *className,
- const char *fieldName,
- jboolean value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "Z", true);
- if (id == 0)
- return;
-
- env->SetStaticBooleanField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jbyte>(jclass clazz,
- const char *fieldName,
- jbyte value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "B", true);
- if (id)
- env->SetStaticByteField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jbyte>(const char *className,
- const char *fieldName,
- jbyte value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "B", true);
- if (id == 0)
- return;
-
- env->SetStaticByteField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jchar>(jclass clazz,
- const char *fieldName,
- jchar value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "C", true);
- if (id)
- env->SetStaticCharField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jchar>(const char *className,
- const char *fieldName,
- jchar value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "C", true);
- if (id == 0)
- return;
-
- env->SetStaticCharField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jshort>(jclass clazz,
- const char *fieldName,
- jshort value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "S", true);
- if (id)
- env->SetStaticShortField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jshort>(const char *className,
- const char *fieldName,
- jshort value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "S", true);
- if (id == 0)
- return;
-
- env->SetStaticShortField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jint>(jclass clazz,
- const char *fieldName,
- jint value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "I", true);
- if (id)
- env->SetStaticIntField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jint>(const char *className,
- const char *fieldName,
- jint value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "I", true);
- if (id == 0)
- return;
-
- env->SetStaticIntField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jlong>(jclass clazz,
- const char *fieldName,
- jlong value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "J", true);
- if (id)
- env->SetStaticLongField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jlong>(const char *className,
- const char *fieldName,
- jlong value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "J", true);
- if (id == 0)
- return;
-
- env->SetStaticLongField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jfloat>(jclass clazz,
- const char *fieldName,
- jfloat value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "F", true);
- if (id)
- env->SetStaticFloatField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jfloat>(const char *className,
- const char *fieldName,
- jfloat value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "F", true);
- if (id == 0)
- return;
-
- env->SetStaticFloatField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jdouble>(jclass clazz,
- const char *fieldName,
- jdouble value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, "D", true);
- if (id)
- env->SetStaticDoubleField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jdouble>(const char *className,
- const char *fieldName,
- jdouble value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "D", true);
- if (id == 0)
- return;
-
- env->SetStaticDoubleField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jobject>(jclass clazz,
- const char *fieldName,
- const char *sig,
- jobject value)
-{
- QJNIEnvironmentPrivate env;
- jfieldID id = getFieldID(env, clazz, fieldName, sig, true);
- if (id)
- env->SetStaticObjectField(clazz, id, value);
-}
-
-template <>
-Q_CORE_EXPORT void QJNIObjectPrivate::setStaticField<jobject>(const char *className,
- const char *fieldName,
- const char *sig,
- jobject value)
-{
- QJNIEnvironmentPrivate env;
- jclass clazz = loadClass(className, env);
- if (clazz == 0)
- return;
-
- jfieldID id = getCachedFieldID(env, clazz, className, fieldName, sig, true);
- if (id == 0)
- return;
-
- env->SetStaticObjectField(clazz, id, value);
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string)
-{
- QJNIEnvironmentPrivate env;
- jstring res = env->NewString(reinterpret_cast<const jchar*>(string.constData()),
- string.length());
- QJNIObjectPrivate obj(res);
- env->DeleteLocalRef(res);
- return obj;
-}
-
-QString QJNIObjectPrivate::toString() const
-{
- if (!isValid())
- return QString();
-
- QJNIObjectPrivate string = callObjectMethod<jstring>("toString");
- return qt_convertJString(static_cast<jstring>(string.object()));
-}
-
-bool QJNIObjectPrivate::isClassAvailable(const char *className)
-{
- QJNIEnvironmentPrivate env;
-
- if (!env)
- return false;
-
- jclass clazz = loadClass(className, env);
- return (clazz != 0);
-}
-
-bool QJNIObjectPrivate::isValid() const
-{
- return d->m_jobject;
-}
-
-QJNIObjectPrivate QJNIObjectPrivate::fromLocalRef(jobject lref)
-{
- QJNIObjectPrivate o(lref);
- QJNIEnvironmentPrivate()->DeleteLocalRef(lref);
- return o;
-}
-
-bool QJNIObjectPrivate::isSameObject(jobject obj) const
-{
- QJNIEnvironmentPrivate env;
- return env->IsSameObject(d->m_jobject, obj);
-}
-
-bool QJNIObjectPrivate::isSameObject(const QJNIObjectPrivate &other) const
-{
- return isSameObject(other.d->m_jobject);
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h
deleted file mode 100644
index ec8525e6e1..0000000000
--- a/src/corelib/kernel/qjni_p.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#ifndef QJNI_P_H
-#define QJNI_P_H
-
-#include <jni.h>
-#include <QtCore/private/qglobal_p.h>
-#include <QtCore/qsharedpointer.h>
-
-QT_BEGIN_NAMESPACE
-
-struct Q_CORE_EXPORT QJNILocalRefDeleter
-{
- static void cleanup(jobject obj);
-};
-
-// To simplify this we only define it for jobjects.
-typedef QScopedPointer<_jobject, QJNILocalRefDeleter> QJNIScopedLocalRef;
-
-class Q_CORE_EXPORT QJNIEnvironmentPrivate
-{
-public:
- QJNIEnvironmentPrivate();
- ~QJNIEnvironmentPrivate();
- JNIEnv *operator->();
- operator JNIEnv*() const;
- static jclass findClass(const char *className, JNIEnv *env = 0);
-
-private:
- friend class QAndroidJniEnvironment;
- Q_DISABLE_COPY_MOVE(QJNIEnvironmentPrivate)
- JNIEnv *jniEnv;
-};
-
-class Q_CORE_EXPORT QJNIObjectData
-{
-public:
- QJNIObjectData();
- ~QJNIObjectData();
- jobject m_jobject;
- jclass m_jclass;
- bool m_own_jclass;
- QByteArray m_className;
-};
-
-class Q_CORE_EXPORT QJNIObjectPrivate
-{
-public:
- QJNIObjectPrivate();
- explicit QJNIObjectPrivate(const char *className);
- QJNIObjectPrivate(const char *className, const char *sig, ...);
- explicit QJNIObjectPrivate(jclass clazz);
- QJNIObjectPrivate(jclass clazz, const char *sig, ...);
- // In most cases you should never call this function with a local ref. unless you intend
- // to manage the local ref. yourself.
- // NOTE: see fromLocalRef() for converting a local ref. to QJNIObjectPrivate.
- explicit QJNIObjectPrivate(jobject globalRef);
-
- template <typename T>
- T callMethod(const char *methodName,
- const char *sig,
- ...) const;
- template <typename T>
- T callMethod(const char *methodName) const;
- template <typename T>
- QJNIObjectPrivate callObjectMethod(const char *methodName) const;
- QJNIObjectPrivate callObjectMethod(const char *methodName,
- const char *sig,
- ...) const;
- template <typename T>
- static T callStaticMethod(const char *className,
- const char *methodName,
- const char *sig, ...);
- template <typename T>
- static T callStaticMethod(const char *className,
- const char *methodName);
- template <typename T>
- static T callStaticMethod(jclass clazz,
- const char *methodName,
- const char *sig, ...);
- template <typename T>
- static T callStaticMethod(jclass clazz,
- const char *methodName);
- static QJNIObjectPrivate callStaticObjectMethod(const char *className,
- const char *methodName,
- const char *sig, ...);
-
- static QJNIObjectPrivate callStaticObjectMethod(jclass clazz,
- const char *methodName,
- const char *sig, ...);
-
- template <typename T>
- T getField(const char *fieldName) const;
- template <typename T>
- static T getStaticField(const char *className, const char *fieldName);
- template <typename T>
- static T getStaticField(jclass clazz, const char *fieldName);
-
- QJNIObjectPrivate getObjectField(const char *fieldName, const char *sig) const;
- static QJNIObjectPrivate getStaticObjectField(const char *className,
- const char *fieldName,
- const char *sig);
- static QJNIObjectPrivate getStaticObjectField(jclass clazz,
- const char *fieldName,
- const char *sig);
-
- template <typename T>
- void setField(const char *fieldName, T value);
- template <typename T>
- void setField(const char *fieldName, const char *sig, T value);
- template <typename T>
- static void setStaticField(const char *className,
- const char *fieldName,
- T value);
- template <typename T>
- static void setStaticField(const char *className,
- const char *fieldName,
- const char *sig,
- T value);
- template <typename T>
- static void setStaticField(jclass clazz,
- const char *fieldName,
- const char *sig,
- T value);
-
- template <typename T>
- static void setStaticField(jclass clazz,
- const char *fieldName,
- T value);
-
- static QJNIObjectPrivate fromString(const QString &string);
- QString toString() const;
-
- static bool isClassAvailable(const char *className);
- bool isValid() const;
- jobject object() const { return d->m_jobject; }
-
- template <typename T>
- inline QJNIObjectPrivate &operator=(T o)
- {
- jobject jobj = static_cast<jobject>(o);
- if (!isSameObject(jobj)) {
- d = QSharedPointer<QJNIObjectData>::create();
- if (jobj) {
- QJNIEnvironmentPrivate env;
- d->m_jobject = env->NewGlobalRef(jobj);
- jclass objectClass = env->GetObjectClass(jobj);
- d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
- env->DeleteLocalRef(objectClass);
- }
- }
-
- return *this;
- }
-
- // This function takes ownership of the jobject and releases the local ref. before returning.
- static QJNIObjectPrivate fromLocalRef(jobject lref);
-
-private:
- friend class QAndroidJniObject;
-
- struct QVaListPrivate { operator va_list &() const { return m_args; } va_list &m_args; };
-
- QJNIObjectPrivate(const char *className, const char *sig, const QVaListPrivate &args);
- QJNIObjectPrivate(jclass clazz, const char *sig, const QVaListPrivate &args);
-
- template <typename T>
- T callMethodV(const char *methodName,
- const char *sig,
- va_list args) const;
- QJNIObjectPrivate callObjectMethodV(const char *methodName,
- const char *sig,
- va_list args) const;
- template <typename T>
- static T callStaticMethodV(const char *className,
- const char *methodName,
- const char *sig,
- va_list args);
- template <typename T>
- static T callStaticMethodV(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args);
- static QJNIObjectPrivate callStaticObjectMethodV(const char *className,
- const char *methodName,
- const char *sig,
- va_list args);
-
- static QJNIObjectPrivate callStaticObjectMethodV(jclass clazz,
- const char *methodName,
- const char *sig,
- va_list args);
-
- bool isSameObject(jobject obj) const;
- bool isSameObject(const QJNIObjectPrivate &other) const;
-
- friend bool operator==(const QJNIObjectPrivate &, const QJNIObjectPrivate &);
- friend bool operator!=(const QJNIObjectPrivate&, const QJNIObjectPrivate&);
- template <typename T> friend bool operator!=(const QJNIObjectPrivate&, T);
- template <typename T> friend bool operator==(const QJNIObjectPrivate&, T);
- template <typename T> friend bool operator!=(T, const QJNIObjectPrivate&);
- template <typename T> friend bool operator==(T, const QJNIObjectPrivate&);
-
- QSharedPointer<QJNIObjectData> d;
-};
-
-inline bool operator==(const QJNIObjectPrivate&obj1, const QJNIObjectPrivate&obj2)
-{
- return obj1.isSameObject(obj2);
-}
-
-inline bool operator!=(const QJNIObjectPrivate&obj1, const QJNIObjectPrivate&obj2)
-{
- return !obj1.isSameObject(obj2);
-}
-
-template <typename T>
-inline bool operator==(const QJNIObjectPrivate &obj1, T obj2)
-{
- return obj1.isSameObject(static_cast<jobject>(obj2));
-}
-
-template <typename T>
-inline bool operator==(T obj1, const QJNIObjectPrivate &obj2)
-{
- return obj2.isSameObject(static_cast<jobject>(obj1));
-}
-
-template <typename T>
-inline bool operator!=(const QJNIObjectPrivate &obj1, T obj2)
-{
- return !obj1.isSameObject(obj2);
-}
-
-template <typename T>
-inline bool operator!=(T obj1, const QJNIObjectPrivate &obj2)
-{
- return !obj2.isSameObject(obj1);
-}
-
-QT_END_NAMESPACE
-
-#endif // QJNI_P_H
diff --git a/src/corelib/kernel/qjniarray.h b/src/corelib/kernel/qjniarray.h
new file mode 100644
index 0000000000..2ea82e39db
--- /dev/null
+++ b/src/corelib/kernel/qjniarray.h
@@ -0,0 +1,464 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QJNIARRAY_H
+#define QJNIARRAY_H
+
+#include <QtCore/qlist.h>
+
+#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
+#include <QtCore/qbytearray.h>
+#include <QtCore/qjniobject.h>
+
+#include <iterator>
+#include <utility>
+#include <QtCore/q20type_traits.h>
+
+QT_BEGIN_NAMESPACE
+
+template <typename T> class QJniArray;
+template <typename T>
+struct QT_TECH_PREVIEW_API QJniArrayIterator
+{
+ QJniArrayIterator() = default;
+
+ constexpr QJniArrayIterator(const QJniArrayIterator &other) noexcept = default;
+ constexpr QJniArrayIterator(QJniArrayIterator &&other) noexcept = default;
+ constexpr QJniArrayIterator &operator=(const QJniArrayIterator &other) noexcept = default;
+ constexpr QJniArrayIterator &operator=(QJniArrayIterator &&other) noexcept = default;
+
+ using difference_type = jsize;
+ using value_type = T;
+ using pointer = T *;
+ using reference = T; // difference to container requirements
+ using const_reference = reference;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ friend bool operator==(const QJniArrayIterator &lhs, const QJniArrayIterator &rhs) noexcept
+ {
+ return lhs.m_array == rhs.m_array && lhs.m_index == rhs.m_index;
+ }
+ friend bool operator!=(const QJniArrayIterator &lhs, const QJniArrayIterator &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+ const_reference operator*() const
+ {
+ return m_array->at(m_index);
+ }
+ friend QJniArrayIterator &operator++(QJniArrayIterator &that) noexcept
+ {
+ ++that.m_index;
+ return that;
+ }
+ friend QJniArrayIterator operator++(QJniArrayIterator &that, int) noexcept
+ {
+ auto copy = that;
+ ++that;
+ return copy;
+ }
+ friend QJniArrayIterator &operator--(QJniArrayIterator &that) noexcept
+ {
+ --that.m_index;
+ return that;
+ }
+ friend QJniArrayIterator operator--(QJniArrayIterator &that, int) noexcept
+ {
+ auto copy = that;
+ --that;
+ return copy;
+ }
+ void swap(QJniArrayIterator &other) noexcept
+ {
+ std::swap(m_index, other.m_index);
+ qt_ptr_swap(m_array, other.m_array);
+ }
+
+private:
+ using VT = std::remove_const_t<T>;
+ friend class QJniArray<VT>;
+
+ qsizetype m_index = 0;
+ const QJniArray<VT> *m_array = nullptr;
+
+ QJniArrayIterator(qsizetype index, const QJniArray<VT> *array)
+ : m_index(index), m_array(array)
+ {}
+};
+
+class QT_TECH_PREVIEW_API QJniArrayBase
+{
+ // for SFINAE'ing out the fromContainer named constructor
+ template <typename Container, typename = void> struct CanConvertHelper : std::false_type {};
+ template <typename Container>
+ struct CanConvertHelper<Container, std::void_t<decltype(std::data(std::declval<Container>())),
+ decltype(std::size(std::declval<Container>())),
+ typename Container::value_type
+ >
+ > : std::true_type {};
+
+public:
+ using size_type = jsize;
+ using difference_type = size_type;
+
+ operator QJniObject() const { return m_object; }
+
+ template <typename T = jobject>
+ T object() const { return m_object.object<T>(); }
+ bool isValid() const { return m_object.isValid(); }
+
+ size_type size() const
+ {
+ if (jarray array = m_object.object<jarray>())
+ return jniEnv()->GetArrayLength(array);
+ return 0;
+ }
+
+ template <typename Container>
+ static constexpr bool canConvert = CanConvertHelper<q20::remove_cvref_t<Container>>::value;
+ template <typename Container>
+ using IfCanConvert = std::enable_if_t<canConvert<Container>, bool>;
+ template <typename Container
+ , IfCanConvert<Container> = true
+ >
+ static auto fromContainer(Container &&container)
+ {
+ Q_ASSERT_X(size_t(std::size(container)) <= size_t((std::numeric_limits<size_type>::max)()),
+ "QJniArray::fromContainer", "Container is too large for a Java array");
+
+ using ElementType = typename std::remove_reference_t<Container>::value_type;
+ if constexpr (std::disjunction_v<std::is_same<ElementType, jobject>,
+ std::is_same<ElementType, QJniObject>,
+ std::is_same<ElementType, QString>,
+ std::is_base_of<QtJniTypes::JObjectBase, ElementType>
+ >) {
+ return makeObjectArray(std::forward<Container>(container));
+ } else if constexpr (std::is_same_v<ElementType, jfloat>) {
+ return makeArray<jfloat>(std::forward<Container>(container), &JNIEnv::NewFloatArray,
+ &JNIEnv::SetFloatArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jdouble>) {
+ return makeArray<jdouble>(std::forward<Container>(container), &JNIEnv::NewDoubleArray,
+ &JNIEnv::SetDoubleArrayRegion);
+ } else if constexpr (std::disjunction_v<std::is_same<ElementType, jboolean>,
+ std::is_same<ElementType, bool>>) {
+ return makeArray<jboolean>(std::forward<Container>(container), &JNIEnv::NewBooleanArray,
+ &JNIEnv::SetBooleanArrayRegion);
+ } else if constexpr (std::disjunction_v<std::is_same<ElementType, jbyte>,
+ std::is_same<ElementType, char>>) {
+ return makeArray<jbyte>(std::forward<Container>(container), &JNIEnv::NewByteArray,
+ &JNIEnv::SetByteArrayRegion);
+ } else if constexpr (std::disjunction_v<std::is_same<ElementType, jchar>,
+ std::is_same<ElementType, QChar>>) {
+ return makeArray<jchar>(std::forward<Container>(container), &JNIEnv::NewCharArray,
+ &JNIEnv::SetCharArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jshort>
+ || sizeof(ElementType) == sizeof(jshort)) {
+ return makeArray<jshort>(std::forward<Container>(container), &JNIEnv::NewShortArray,
+ &JNIEnv::SetShortArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jint>
+ || sizeof(ElementType) == sizeof(jint)) {
+ return makeArray<jint>(std::forward<Container>(container), &JNIEnv::NewIntArray,
+ &JNIEnv::SetIntArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jlong>
+ || sizeof(ElementType) == sizeof(jlong)) {
+ return makeArray<jlong>(std::forward<Container>(container), &JNIEnv::NewLongArray,
+ &JNIEnv::SetLongArrayRegion);
+ }
+ }
+
+protected:
+ QJniArrayBase() = default;
+ ~QJniArrayBase() = default;
+
+ explicit QJniArrayBase(jarray array)
+ : m_object(static_cast<jobject>(array))
+ {
+ }
+ explicit QJniArrayBase(const QJniObject &object)
+ : m_object(object)
+ {}
+ explicit QJniArrayBase(QJniObject &&object) noexcept
+ : m_object(std::move(object))
+ {}
+
+ JNIEnv *jniEnv() const noexcept { return QJniEnvironment::getJniEnv(); }
+
+ template <typename ElementType, typename List, typename NewFn, typename SetFn>
+ static auto makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion);
+ template <typename List>
+ static auto makeObjectArray(List &&list);
+
+private:
+ QJniObject m_object;
+};
+
+template <typename T>
+class QT_TECH_PREVIEW_API QJniArray : public QJniArrayBase
+{
+ friend struct QJniArrayIterator<T>;
+public:
+ using Type = T;
+
+ using value_type = T;
+ using reference = T;
+ using const_reference = const reference;
+
+ // read-only container, so no iterator typedef
+ using const_iterator = QJniArrayIterator<const T>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ QJniArray() = default;
+ explicit QJniArray(jarray array) : QJniArrayBase(array) {}
+ explicit QJniArray(const QJniObject &object) : QJniArrayBase(object) {}
+ explicit QJniArray(QJniObject &&object) noexcept : QJniArrayBase(std::move(object)) {}
+
+ // base class destructor is protected, so need to provide all SMFs
+ QJniArray(const QJniArray &other) = default;
+ QJniArray(QJniArray &&other) noexcept = default;
+ QJniArray &operator=(const QJniArray &other) = default;
+ QJniArray &operator=(QJniArray &&other) noexcept = default;
+
+ template <typename Container
+ , IfCanConvert<Container> = true
+ >
+ explicit QJniArray(Container &&container)
+ : QJniArrayBase(QJniArrayBase::fromContainer(std::forward<Container>(container)))
+ {
+ }
+
+ template <typename E = T
+ , IfCanConvert<std::initializer_list<E>> = true
+ >
+ Q_IMPLICIT inline QJniArray(std::initializer_list<T> list)
+ : QJniArrayBase(QJniArrayBase::fromContainer(list))
+ {
+ }
+
+ template <typename Other, std::enable_if_t<std::is_convertible_v<Other, Type>, bool> = true>
+ QJniArray(QJniArray<Other> &&other)
+ : QJniArrayBase(std::forward<QJniArray<Other>>(other))
+ {
+ }
+ ~QJniArray() = default;
+
+ auto arrayObject() const
+ {
+ if constexpr (std::is_convertible_v<jobject, T>)
+ return object<jobjectArray>();
+ else if constexpr (std::is_same_v<T, jbyte>)
+ return object<jbyteArray>();
+ else if constexpr (std::is_same_v<T, jchar>)
+ return object<jcharArray>();
+ else if constexpr (std::is_same_v<T, jboolean>)
+ return object<jbooleanArray>();
+ else if constexpr (std::is_same_v<T, jshort>)
+ return object<jshortArray>();
+ else if constexpr (std::is_same_v<T, jint>)
+ return object<jintArray>();
+ else if constexpr (std::is_same_v<T, jlong>)
+ return object<jlongArray>();
+ else if constexpr (std::is_same_v<T, jfloat>)
+ return object<jfloatArray>();
+ else if constexpr (std::is_same_v<T, jdouble>)
+ return object<jdoubleArray>();
+ else
+ return object<jarray>();
+ }
+
+ const_iterator begin() const noexcept { return {0, this}; }
+ const_iterator constBegin() const noexcept { return begin(); }
+ const_iterator cbegin() const noexcept { return begin(); }
+ const_iterator end() const noexcept { return {size(), this}; }
+ const_iterator constEnd() const noexcept { return {end()}; }
+ const_iterator cend() const noexcept { return {end()}; }
+
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
+
+ const_reference operator[](size_type i) const { return at(i); }
+ const_reference at(size_type i) const
+ {
+ JNIEnv *env = jniEnv();
+ if constexpr (std::is_convertible_v<jobject, T>) {
+ jobject element = env->GetObjectArrayElement(object<jobjectArray>(), i);
+ if constexpr (std::is_base_of_v<QJniObject, T>)
+ return QJniObject::fromLocalRef(element);
+ else if constexpr (std::is_base_of_v<QtJniTypes::JObjectBase, T>)
+ return T::fromLocalRef(element);
+ else
+ return T{element};
+ } else if constexpr (std::is_base_of_v<std::remove_pointer_t<jobject>, std::remove_pointer_t<T>>) {
+ // jstring, jclass etc
+ return static_cast<T>(env->GetObjectArrayElement(object<jobjectArray>(), i));
+ } else {
+ T res = {};
+ if constexpr (std::is_same_v<T, jbyte>)
+ env->GetByteArrayRegion(object<jbyteArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jchar>)
+ env->GetCharArrayRegion(object<jcharArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jboolean>)
+ env->GetBooleanArrayRegion(object<jbooleanArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jshort>)
+ env->GetShortArrayRegion(object<jshortArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jint>)
+ env->GetIntArrayRegion(object<jbyteArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jlong>)
+ env->GetLongArrayRegion(object<jlongArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jfloat>)
+ env->GetFloatArrayRegion(object<jfloatArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jdouble>)
+ env->GetDoubleArrayRegion(object<jdoubleArray>(), i, 1, &res);
+ return res;
+ }
+ }
+ auto toContainer() const
+ {
+ JNIEnv *env = jniEnv();
+ if constexpr (std::is_same_v<T, jobject>) {
+ QList<jobject> res;
+ res.reserve(size());
+ for (auto element : *this)
+ res.append(element);
+ return res;
+ } else if constexpr (std::is_same_v<T, jstring>) {
+ QStringList res;
+ res.reserve(size());
+ for (auto element : *this)
+ res.append(QJniObject(element).toString());
+ return res;
+ } else if constexpr (std::is_same_v<T, jbyte>) {
+ const qsizetype bytecount = size();
+ QByteArray res(bytecount, Qt::Initialization::Uninitialized);
+ env->GetByteArrayRegion(object<jbyteArray>(),
+ 0, bytecount, reinterpret_cast<jbyte *>(res.data()));
+ return res;
+ } else {
+ QList<T> res;
+ res.resize(size());
+ if constexpr (std::is_same_v<T, jchar>) {
+ env->GetCharArrayRegion(object<jcharArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jboolean>) {
+ env->GetBooleanArrayRegion(object<jbooleanArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jshort>) {
+ env->GetShortArrayRegion(object<jshortArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jint>) {
+ env->GetIntArrayRegion(object<jintArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jlong>) {
+ env->GetLongArrayRegion(object<jlongArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jfloat>) {
+ env->GetFloatArrayRegion(object<jfloatArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jdouble>) {
+ env->GetDoubleArrayRegion(object<jdoubleArray>(),
+ 0, res.size(), res.data());
+ } else {
+ res.clear();
+ }
+ return res;
+ }
+ }
+};
+
+template <typename ElementType, typename List, typename NewFn, typename SetFn>
+auto QJniArrayBase::makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion)
+{
+ const size_type length = size_type(std::size(list));
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ auto localArray = (env->*newArray)(length);
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return QJniArray<ElementType>();
+
+ // can't use static_cast here because we have signed/unsigned mismatches
+ if (length) {
+ (env->*setRegion)(localArray, 0, length,
+ reinterpret_cast<const ElementType *>(std::data(std::as_const(list))));
+ }
+ return QJniArray<ElementType>(localArray);
+};
+
+template <typename List>
+auto QJniArrayBase::makeObjectArray(List &&list)
+{
+ using ElementType = typename q20::remove_cvref_t<List>::value_type;
+ using ResultType = QJniArray<decltype(std::declval<QJniObject::LocalFrame<>>().convertToJni(
+ std::declval<ElementType>()))
+ >;
+
+ if (std::size(list) == 0)
+ return ResultType();
+
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ const size_type length = size_type(std::size(list));
+
+ // this assumes that all objects in the list have the same class
+ jclass elementClass = nullptr;
+ if constexpr (std::disjunction_v<std::is_same<ElementType, QJniObject>,
+ std::is_base_of<QtJniTypes::JObjectBase, ElementType>>) {
+ elementClass = std::begin(list)->objectClass();
+ } else if constexpr (std::is_same_v<ElementType, QString>) {
+ elementClass = env->FindClass("java/lang/String");
+ } else {
+ elementClass = env->GetObjectClass(*std::begin(list));
+ }
+ auto localArray = env->NewObjectArray(length, elementClass, nullptr);
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return ResultType();
+
+ // explicitly manage the frame for local references in chunks of 100
+ QJniObject::LocalFrame frame(env);
+ constexpr jint frameCapacity = 100;
+ qsizetype i = 0;
+ for (const auto &element : std::as_const(list)) {
+ if (i % frameCapacity == 0) {
+ if (i)
+ env->PopLocalFrame(nullptr);
+ if (env->PushLocalFrame(frameCapacity) != 0)
+ return ResultType{};
+ }
+ jobject object = frame.convertToJni(element);
+ env->SetObjectArrayElement(localArray, i, object);
+ ++i;
+ }
+ if (i)
+ env->PopLocalFrame(nullptr);
+ return ResultType(localArray);
+}
+
+namespace QtJniTypes
+{
+template <typename T> struct IsJniArray: std::false_type {};
+template <typename T> struct IsJniArray<QJniArray<T>> : std::true_type {};
+template <typename T> struct Traits<QJniArray<T>> {
+ template <IfValidFieldType<T> = true>
+ static constexpr auto signature()
+ {
+ return CTString("[") + Traits<T>::signature();
+ }
+};
+template <typename T> struct Traits<QList<T>> {
+ template <IfValidFieldType<T> = true>
+ static constexpr auto signature()
+ {
+ return CTString("[") + Traits<T>::signature();
+ }
+};
+template <> struct Traits<QByteArray> {
+ static constexpr auto signature()
+ {
+ return CTString("[B");
+ }
+};
+}
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // QJNIARRAY_H
diff --git a/src/corelib/kernel/qjnienvironment.cpp b/src/corelib/kernel/qjnienvironment.cpp
new file mode 100644
index 0000000000..1e2826e76b
--- /dev/null
+++ b/src/corelib/kernel/qjnienvironment.cpp
@@ -0,0 +1,538 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qjnienvironment.h"
+#include "qjnihelpers_p.h"
+
+#include <QtCore/QThread>
+#include <QtCore/QThreadStorage>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QJniEnvironment
+ \inmodule QtCore
+ \since 6.1
+ \brief The QJniEnvironment class provides access to the JNI Environment (JNIEnv).
+
+ When using JNI, the \l {JNI tips: JavaVM and JNIEnv}{JNIEnv} class is a pointer to a function
+ table and a member function for each JNI function that indirects through the table. \c JNIEnv
+ provides most of the JNI functions. Every C++ native function receives a \c JNIEnv as the first
+ argument. The JNI environment cannot be shared between threads.
+
+ Since \c JNIEnv doesn't do much error checking, such as exception checking and clearing,
+ QJniEnvironment allows you to do that easily.
+
+ For more information about JNIEnv, see \l {Java: Interface Function Table}.
+
+ \note This API has been designed and tested for use with Android.
+ It has not been tested for other platforms.
+*/
+
+class QJniEnvironmentPrivate
+{
+public:
+ JNIEnv *jniEnv = nullptr;
+};
+
+class QJniEnvironmentPrivateTLS
+{
+public:
+ inline ~QJniEnvironmentPrivateTLS()
+ {
+ QtAndroidPrivate::javaVM()->DetachCurrentThread();
+ }
+};
+
+Q_GLOBAL_STATIC(QThreadStorage<QJniEnvironmentPrivateTLS *>, jniEnvTLS)
+
+
+/*!
+ Constructs a new JNI Environment object and attaches the current thread to the Java VM.
+*/
+QJniEnvironment::QJniEnvironment()
+ : d(new QJniEnvironmentPrivate{})
+{
+ d->jniEnv = getJniEnv();
+}
+
+/*!
+ Returns the JNIEnv pointer for the current thread.
+
+ The current thread will be attached to the Java VM.
+*/
+JNIEnv *QJniEnvironment::getJniEnv()
+{
+ JNIEnv *jniEnv = nullptr;
+
+ JavaVM *vm = QtAndroidPrivate::javaVM();
+ const jint ret = vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6);
+
+ if (ret == JNI_EDETACHED) { // We need to (re-)attach
+ const QByteArray threadName = QThread::currentThread()->objectName().toUtf8();
+ JavaVMAttachArgs args = { JNI_VERSION_1_6,
+ threadName.isEmpty() ? "QtThread" : threadName.constData(),
+ nullptr
+ };
+ if (vm->AttachCurrentThread(&jniEnv, &args) == JNI_OK) {
+ if (!jniEnvTLS->hasLocalData()) // If we attached the thread we own it.
+ jniEnvTLS->setLocalData(new QJniEnvironmentPrivateTLS);
+ }
+ }
+ return jniEnv;
+}
+
+/*!
+ \fn QJniEnvironment::~QJniEnvironment()
+
+ Detaches the current thread from the Java VM and destroys the QJniEnvironment object.
+ This will clear any pending exception by calling checkAndClearExceptions().
+*/
+QJniEnvironment::~QJniEnvironment()
+{
+ checkAndClearExceptions();
+}
+
+/*!
+ Returns \c true if this instance holds a valid JNIEnv object.
+
+ \since 6.2
+*/
+bool QJniEnvironment::isValid() const
+{
+ return d->jniEnv;
+}
+
+/*!
+ Provides access to the JNI Environment's \c JNIEnv pointer.
+*/
+JNIEnv *QJniEnvironment::operator->() const
+{
+ return d->jniEnv;
+}
+
+/*!
+ Returns the JNI Environment's \c JNIEnv object.
+*/
+JNIEnv &QJniEnvironment::operator*() const
+{
+ return *d->jniEnv;
+}
+
+/*!
+ Returns the JNI Environment's \c JNIEnv pointer.
+*/
+JNIEnv *QJniEnvironment::jniEnv() const
+{
+ return d->jniEnv;
+}
+
+/*!
+ Searches for \a className using all available class loaders. Qt on Android
+ uses a custom class loader to load all the .jar files and it must be used
+ to find any classes that are created by that class loader because these
+ classes are not visible when using the default class loader.
+
+ Returns the class pointer or null if \a className is not found.
+
+ A use case for this function is searching for a class to call a JNI method
+ that takes a \c jclass. This can be useful when doing multiple JNI calls on
+ the same class object which can a bit faster than using a class name in each
+ call. Additionally, this call looks for internally cached classes first before
+ doing a JNI call, and returns such a class if found. The following code snippet
+ creates an instance of the class \c CustomClass and then calls the
+ \c printFromJava() method:
+
+ \code
+ QJniEnvironment env;
+ jclass javaClass = env.findClass("org/qtproject/example/android/CustomClass");
+ QJniObject javaMessage = QJniObject::fromString("findClass example");
+ QJniObject::callStaticMethod<void>(javaClass, "printFromJava",
+ "(Ljava/lang/String;)V", javaMessage.object<jstring>());
+ \endcode
+
+ \note This call returns a global reference to the class object from the
+ internally cached classes.
+*/
+jclass QJniEnvironment::findClass(const char *className)
+{
+ return QtAndroidPrivate::findClass(className, d->jniEnv);
+}
+
+/*!
+ Searches for an instance method of a class \a clazz. The method is specified
+ by its \a methodName and \a signature.
+
+ Returns the method ID or \c nullptr if the method is not found.
+
+ A usecase for this method is searching for class methods and caching their
+ IDs, so that they could later be used for calling the methods.
+
+ \since 6.2
+*/
+jmethodID QJniEnvironment::findMethod(jclass clazz, const char *methodName, const char *signature)
+{
+ if (clazz) {
+ jmethodID id = d->jniEnv->GetMethodID(clazz, methodName, signature);
+ if (!checkAndClearExceptions(d->jniEnv))
+ return id;
+ }
+
+ return nullptr;
+}
+
+/*!
+ \fn template<typename ...Args> jmethodId QJniEnvironment::findMethod(jclass clazz, const char *methodName)
+ \since 6.4
+
+ Searches for an instance method of a class \a clazz. The method is specified
+ by its \a methodName, the signature is deduced from the template parameters.
+
+ Returns the method ID or \c nullptr if the method is not found.
+*/
+
+/*!
+ Searches for a static method of a class \a clazz. The method is specified
+ by its \a methodName and \a signature.
+
+ Returns the method ID or \c nullptr if the method is not found.
+
+ A usecase for this method is searching for class methods and caching their
+ IDs, so that they could later be used for calling the methods.
+
+ \code
+ QJniEnvironment env;
+ jclass javaClass = env.findClass("org/qtproject/example/android/CustomClass");
+ jmethodID methodId = env.findStaticMethod(javaClass,
+ "staticJavaMethod",
+ "(Ljava/lang/String;)V");
+ QJniObject javaMessage = QJniObject::fromString("findStaticMethod example");
+ QJniObject::callStaticMethod<void>(javaClass,
+ methodId,
+ javaMessage.object<jstring>());
+ \endcode
+
+ \since 6.2
+*/
+jmethodID QJniEnvironment::findStaticMethod(jclass clazz, const char *methodName, const char *signature)
+{
+ if (clazz) {
+ jmethodID id = d->jniEnv->GetStaticMethodID(clazz, methodName, signature);
+ if (!checkAndClearExceptions(d->jniEnv))
+ return id;
+ }
+
+ return nullptr;
+}
+
+/*!
+ \fn template<typename ...Args> jmethodId QJniEnvironment::findStaticMethod(jclass clazz, const char *methodName)
+ \since 6.4
+
+ Searches for an instance method of a class \a clazz. The method is specified
+ by its \a methodName, the signature is deduced from the template parameters.
+
+ Returns the method ID or \c nullptr if the method is not found.
+
+ \code
+ QJniEnvironment env;
+ jclass javaClass = env.findClass("org/qtproject/example/android/CustomClass");
+ jmethodID methodId = env.findStaticMethod<void, jstring>(javaClass, "staticJavaMethod");
+ QJniObject javaMessage = QJniObject::fromString("findStaticMethod example");
+ QJniObject::callStaticMethod<void>(javaClass,
+ methodId,
+ javaMessage.object<jstring>());
+ \endcode
+*/
+
+/*!
+ Searches for a member field of a class \a clazz. The field is specified
+ by its \a fieldName and \a signature.
+
+ Returns the field ID or \c nullptr if the field is not found.
+
+ A usecase for this method is searching for class fields and caching their
+ IDs, so that they could later be used for getting/setting the fields.
+
+ \since 6.2
+*/
+jfieldID QJniEnvironment::findField(jclass clazz, const char *fieldName, const char *signature)
+{
+ if (clazz) {
+ jfieldID id = d->jniEnv->GetFieldID(clazz, fieldName, signature);
+ if (!checkAndClearExceptions())
+ return id;
+ }
+
+ return nullptr;
+}
+
+/*!
+ \fn template<typename T> jfieldID QJniEnvironment::findField(jclass clazz, const char *fieldName)
+ \since 6.4
+
+ Searches for a member field of a class \a clazz. The field is specified
+ by its \a fieldName. The signature of the field is deduced from the template parameter.
+
+ Returns the field ID or \c nullptr if the field is not found.
+*/
+
+/*!
+ Searches for a static field of a class \a clazz. The field is specified
+ by its \a fieldName and \a signature.
+
+ Returns the field ID or \c nullptr if the field is not found.
+
+ A usecase for this method is searching for class fields and caching their
+ IDs, so that they could later be used for getting/setting the fields.
+
+ \since 6.2
+*/
+jfieldID QJniEnvironment::findStaticField(jclass clazz, const char *fieldName, const char *signature)
+{
+ if (clazz) {
+ jfieldID id = d->jniEnv->GetStaticFieldID(clazz, fieldName, signature);
+ if (!checkAndClearExceptions())
+ return id;
+ }
+
+ return nullptr;
+}
+
+/*!
+ \fn template<typename T> jfieldID QJniEnvironment::findStaticField(jclass clazz, const char *fieldName)
+ \since 6.4
+
+ Searches for a static field of a class \a clazz. The field is specified
+ by its \a fieldName. The signature of the field is deduced from the template parameter.
+
+ Returns the field ID or \c nullptr if the field is not found.
+*/
+
+/*!
+ Returns the Java VM interface for the current process. Although it might
+ be possible to have multiple Java VMs per process, Android allows only one.
+
+*/
+JavaVM *QJniEnvironment::javaVM()
+{
+ return QtAndroidPrivate::javaVM();
+}
+
+/*!
+ Registers the Java methods in the array \a methods of size \a size, each of
+ which can call native C++ functions from class \a className. These methods
+ must be registered before any attempt to call them.
+
+ Returns \c true if the registration is successful, otherwise \c false.
+
+ Each element in the methods array consists of:
+ \list
+ \li The Java method name
+ \li Method signature
+ \li The C++ functions that will be executed
+ \endlist
+
+ \code
+ const JNINativeMethod methods[] =
+ {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
+ {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
+ QJniEnvironment env;
+ env.registerNativeMethods("org/qtproject/android/TestJavaClass", methods, 2);
+ \endcode
+*/
+bool QJniEnvironment::registerNativeMethods(const char *className, const JNINativeMethod methods[],
+ int size)
+{
+ const jclass clazz = findClass(className);
+
+ if (!clazz)
+ return false;
+
+ return registerNativeMethods(clazz, methods, size);
+}
+
+/*!
+ \fn bool QJniEnvironment::registerNativeMethods(const char *className, std::initializer_list<JNINativeMethod> methods)
+ \overload
+
+ Registers the native functions methods in \a methods for the Java class \a className.
+ Returns \c true if the registration is successful, otherwise \c false.
+*/
+
+#if QT_DEPRECATED_SINCE(6, 2)
+/*!
+ \overload
+ \deprecated [6.2] Use the overload with a const JNINativeMethod[] instead.
+
+ Registers the Java methods in the array \a methods of size \a size, each of
+ which can call native C++ functions from class \a className. These methods
+ must be registered before any attempt to call them.
+
+ Returns \c true if the registration is successful, otherwise \c false.
+
+ Each element in the methods array consists of:
+ \list
+ \li The Java method name
+ \li Method signature
+ \li The C++ functions that will be executed
+ \endlist
+
+ \code
+ JNINativeMethod methods[] = {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
+ {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
+ QJniEnvironment env;
+ env.registerNativeMethods("org/qtproject/android/TestJavaClass", methods, 2);
+ \endcode
+*/
+bool QJniEnvironment::registerNativeMethods(const char *className, JNINativeMethod methods[],
+ int size)
+{
+ return registerNativeMethods(className, const_cast<const JNINativeMethod*>(methods), size);
+}
+#endif
+/*!
+ \overload
+
+ This overload uses a previously cached jclass instance \a clazz.
+
+ \code
+ JNINativeMethod methods[] {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
+ {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
+ QJniEnvironment env;
+ jclass clazz = env.findClass("org/qtproject/android/TestJavaClass");
+ env.registerNativeMethods(clazz, methods, 2);
+ \endcode
+*/
+bool QJniEnvironment::registerNativeMethods(jclass clazz, const JNINativeMethod methods[],
+ int size)
+{
+ if (d->jniEnv->RegisterNatives(clazz, methods, size) < 0) {
+ checkAndClearExceptions();
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \fn bool QJniEnvironment::registerNativeMethods(jclass clazz, std::initializer_list<JNINativeMethod> methods)
+ \overload
+
+ Registers the native functions methods in \a methods for the Java class \a clazz.
+ Returns \c true if the registration is successful, otherwise \c false.
+*/
+
+/*!
+ \enum QJniEnvironment::OutputMode
+
+ \value Silent The exceptions are cleaned silently
+ \value Verbose Prints the exceptions and their stack backtrace as an error
+ to \c stderr stream.
+*/
+
+/*!
+ \fn QJniEnvironment::checkAndClearExceptions(OutputMode outputMode = OutputMode::Verbose)
+
+ Cleans any pending exceptions either silently or reporting stack backtrace,
+ depending on the \a outputMode.
+
+ In contrast to \l QJniObject, which handles exceptions internally, if you
+ make JNI calls directly via \c JNIEnv, you need to clear any potential
+ exceptions after the call using this function. For more information about
+ \c JNIEnv calls that can throw an exception, see \l {Java: JNI Functions}{JNI Functions}.
+
+ \return \c true when a pending exception was cleared.
+*/
+bool QJniEnvironment::checkAndClearExceptions(QJniEnvironment::OutputMode outputMode)
+{
+ return checkAndClearExceptions(d->jniEnv, outputMode);
+}
+
+namespace {
+ // Any pending exception need to be cleared before calling this
+ QString exceptionMessage(JNIEnv *env, jthrowable exception)
+ {
+ if (!exception)
+ return {};
+
+ auto logError = []() {
+ qWarning() << "QJniEnvironment: a null object returned or an exception occurred while "
+ "fetching a prior exception message";
+ };
+
+ auto checkAndClear = [env]() {
+ if (Q_UNLIKELY(env->ExceptionCheck())) {
+ env->ExceptionClear();
+ return true;
+ }
+ return false;
+ };
+
+ const jclass logClazz = env->FindClass("android/util/Log");
+ if (checkAndClear() || !logClazz) {
+ logError();
+ return {};
+ }
+
+ const jmethodID methodId = env->GetStaticMethodID(logClazz, "getStackTraceString",
+ "(Ljava/lang/Throwable;)Ljava/lang/String;");
+ if (checkAndClear() || !methodId) {
+ logError();
+ return {};
+ }
+
+ jvalue value;
+ value.l = static_cast<jobject>(exception);
+ const jobject messageObj = env->CallStaticObjectMethodA(logClazz, methodId, &value);
+ const jstring jmessage = static_cast<jstring>(messageObj);
+ if (checkAndClear())
+ return {};
+
+ char const *utfMessage = env->GetStringUTFChars(jmessage, 0);
+ const QString message = QString::fromUtf8(utfMessage);
+
+ env->ReleaseStringUTFChars(jmessage, utfMessage);
+
+ return message;
+ }
+} // end namespace
+
+/*!
+ Cleans any pending exceptions for \a env, either silently or reporting
+ stack backtrace, depending on the \a outputMode. This is useful when you
+ already have a \c JNIEnv pointer such as in a native function implementation.
+
+ In contrast to \l QJniObject, which handles exceptions internally, if you
+ make JNI calls directly via \c JNIEnv, you need to clear any potential
+ exceptions after the call using this function. For more information about
+ \c JNIEnv calls that can throw an exception, see \l {Java: JNI Functions}{JNI Functions}.
+
+ \return \c true when a pending exception was cleared.
+*/
+bool QJniEnvironment::checkAndClearExceptions(JNIEnv *env, QJniEnvironment::OutputMode outputMode)
+{
+ if (Q_UNLIKELY(env->ExceptionCheck())) {
+ if (outputMode == OutputMode::Verbose) {
+ if (jthrowable exception = env->ExceptionOccurred()) {
+ env->ExceptionClear();
+ const QString message = exceptionMessage(env, exception);
+ // Print to QWARN since env->ExceptionDescribe() does the same
+ if (!message.isEmpty())
+ qWarning().noquote() << message;
+ env->DeleteLocalRef(exception);
+ } else {
+ // if the exception object is null for some reason just
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ } else {
+ env->ExceptionClear();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjnienvironment.h b/src/corelib/kernel/qjnienvironment.h
new file mode 100644
index 0000000000..09f7ec7948
--- /dev/null
+++ b/src/corelib/kernel/qjnienvironment.h
@@ -0,0 +1,103 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QJNI_ENVIRONMENT_H
+#define QJNI_ENVIRONMENT_H
+
+#include <QtCore/QScopedPointer>
+
+#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
+#include <jni.h>
+#include <QtCore/qjnitypes_impl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJniEnvironmentPrivate;
+
+class Q_CORE_EXPORT QJniEnvironment
+{
+public:
+ QJniEnvironment();
+ ~QJniEnvironment();
+ bool isValid() const;
+ JNIEnv *operator->() const;
+ JNIEnv &operator*() const;
+ JNIEnv *jniEnv() const;
+ jclass findClass(const char *className);
+ template<typename Class>
+ jclass findClass() { return findClass(QtJniTypes::Traits<Class>::className().data()); }
+ jmethodID findMethod(jclass clazz, const char *methodName, const char *signature);
+ template<typename ...Args>
+ jmethodID findMethod(jclass clazz, const char *methodName) {
+ constexpr auto signature = QtJniTypes::methodSignature<Args...>();
+ return findMethod(clazz, methodName, signature.data());
+ }
+ jmethodID findStaticMethod(jclass clazz, const char *methodName, const char *signature);
+ template<typename ...Args>
+ jmethodID findStaticMethod(jclass clazz, const char *methodName) {
+ constexpr auto signature = QtJniTypes::methodSignature<Args...>();
+ return findStaticMethod(clazz, methodName, signature.data());
+ }
+ jfieldID findField(jclass clazz, const char *fieldName, const char *signature);
+ template<typename T>
+ jfieldID findField(jclass clazz, const char *fieldName) {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return findField(clazz, fieldName, signature.data());
+ }
+ jfieldID findStaticField(jclass clazz, const char *fieldName, const char *signature);
+ template<typename T>
+ jfieldID findStaticField(jclass clazz, const char *fieldName) {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return findStaticField(clazz, fieldName, signature.data());
+ }
+ static JavaVM *javaVM();
+ bool registerNativeMethods(const char *className, const JNINativeMethod methods[], int size);
+ bool registerNativeMethods(jclass clazz, const JNINativeMethod methods[], int size);
+
+ bool registerNativeMethods(const char *className, std::initializer_list<JNINativeMethod> methods)
+ {
+ return registerNativeMethods(className, std::data(methods), methods.size());
+ }
+
+ bool registerNativeMethods(jclass clazz, std::initializer_list<JNINativeMethod> methods)
+ {
+ return registerNativeMethods(clazz, std::data(methods), methods.size());
+ }
+
+ template<typename Class
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<Class>(), bool> = true
+#endif
+ >
+ QT_TECH_PREVIEW_API
+ bool registerNativeMethods(std::initializer_list<JNINativeMethod> methods)
+ {
+ return registerNativeMethods(QtJniTypes::Traits<Class>::className().data(), methods);
+ }
+
+#if QT_DEPRECATED_SINCE(6, 2)
+ // ### Qt 7: remove
+ QT_DEPRECATED_VERSION_X_6_2("Use the overload with a const JNINativeMethod[] instead.")
+ bool registerNativeMethods(const char *className, JNINativeMethod methods[], int size);
+#endif
+
+ enum class OutputMode {
+ Silent,
+ Verbose
+ };
+
+ bool checkAndClearExceptions(OutputMode outputMode = OutputMode::Verbose);
+ static bool checkAndClearExceptions(JNIEnv *env, OutputMode outputMode = OutputMode::Verbose);
+
+ static JNIEnv *getJniEnv();
+
+private:
+ Q_DISABLE_COPY_MOVE(QJniEnvironment)
+ QScopedPointer<QJniEnvironmentPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // QJNI_ENVIRONMENT_H
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index f845eb37ed..d900b74d37 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -1,52 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qjnihelpers_p.h"
-#include "qjni_p.h"
-#include "qmutex.h"
+
+#include "qjnienvironment.h"
+#include "qjniobject.h"
#include "qlist.h"
+#include "qmutex.h"
#include "qsemaphore.h"
-#include "qsharedpointer.h"
-#include "qthread.h"
-#include "qcoreapplication.h"
-#include <QtCore/qrunnable.h>
+#include "qreadwritelock.h"
+#include <QtCore/private/qcoreapplication_p.h>
+#include <QtCore/private/qlocking_p.h>
+#include <android/log.h>
#include <deque>
#include <memory>
@@ -60,125 +26,53 @@ namespace QtAndroidPrivate {
ResumePauseListener::~ResumePauseListener() {}
void ResumePauseListener::handlePause() {}
void ResumePauseListener::handleResume() {}
- GenericMotionEventListener::~GenericMotionEventListener() {}
- KeyEventListener::~KeyEventListener() {}
}
static JavaVM *g_javaVM = nullptr;
static jobject g_jActivity = nullptr;
static jobject g_jService = nullptr;
static jobject g_jClassLoader = nullptr;
-static jint g_androidSdkVersion = 0;
-static jclass g_jNativeClass = nullptr;
-static jmethodID g_runPendingCppRunnablesMethodID = nullptr;
-static jmethodID g_hideSplashScreenMethodID = nullptr;
-Q_GLOBAL_STATIC(std::deque<QtAndroidPrivate::Runnable>, g_pendingRunnables);
-static QBasicMutex g_pendingRunnablesMutex;
-
-Q_GLOBAL_STATIC_WITH_ARGS(QtAndroidPrivate::OnBindListener*, g_onBindListener, (nullptr));
-Q_GLOBAL_STATIC(QMutex, g_onBindListenerMutex);
+
+Q_CONSTINIT static QtAndroidPrivate::OnBindListener *g_onBindListener;
+Q_CONSTINIT static QBasicMutex g_onBindListenerMutex;
Q_GLOBAL_STATIC(QSemaphore, g_waitForServiceSetupSemaphore);
-Q_GLOBAL_STATIC(QAtomicInt, g_serviceSetupLockers);
+Q_CONSTINIT static QBasicAtomicInt g_serviceSetupLockers = Q_BASIC_ATOMIC_INITIALIZER(0);
-class PermissionsResultClass : public QObject
-{
- Q_OBJECT
-public:
- PermissionsResultClass(const QtAndroidPrivate::PermissionsResultFunc &func) : m_func(func) {}
- Q_INVOKABLE void sendResult(const QtAndroidPrivate::PermissionsHash &result) { m_func(result); delete this;}
-
-private:
- QtAndroidPrivate::PermissionsResultFunc m_func;
-};
-
-typedef QHash<int, PermissionsResultClass*> PendingPermissionRequestsHash;
-Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests);
-static QBasicMutex g_pendingPermissionRequestsMutex;
-static int nextRequestCode()
-{
- static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0);
- return counter.fetchAndAddRelaxed(1);
-}
+Q_GLOBAL_STATIC(QReadWriteLock, g_updateMutex);
-// function called from Java from Android UI thread
-static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/)
+static jboolean updateNativeActivity(JNIEnv *env, jclass = nullptr)
{
- for (;;) { // run all posted runnables
- QMutexLocker locker(&g_pendingRunnablesMutex);
- if (g_pendingRunnables->empty()) {
- break;
- }
- QtAndroidPrivate::Runnable runnable(std::move(g_pendingRunnables->front()));
- g_pendingRunnables->pop_front();
- locker.unlock();
- runnable(); // run it outside the sync block!
- }
-}
-namespace {
- struct GenericMotionEventListeners {
- QMutex mutex;
- QList<QtAndroidPrivate::GenericMotionEventListener *> listeners;
- };
+ jclass jQtNative = env->FindClass("org/qtproject/qt/android/QtNative");
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return JNI_FALSE;
- enum {
- PERMISSION_GRANTED = 0
- };
-}
-Q_GLOBAL_STATIC(GenericMotionEventListeners, g_genericMotionEventListeners)
+ jmethodID activityMethodID =
+ env->GetStaticMethodID(jQtNative, "activity", "()Landroid/app/Activity;");
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return JNI_FALSE;
-static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requestCode,
- jobjectArray permissions, jintArray grantResults)
-{
- QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- auto it = g_pendingPermissionRequests->find(requestCode);
- if (it == g_pendingPermissionRequests->end()) {
- // show an error or something ?
- return;
- }
- auto request = *it;
- g_pendingPermissionRequests->erase(it);
- locker.unlock();
-
- Qt::ConnectionType connection = QThread::currentThread() == request->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
- QtAndroidPrivate::PermissionsHash hash;
- const int size = env->GetArrayLength(permissions);
- std::unique_ptr<jint[]> results(new jint[size]);
- env->GetIntArrayRegion(grantResults, 0, size, results.get());
- for (int i = 0 ; i < size; ++i) {
- const auto &permission = QJNIObjectPrivate(env->GetObjectArrayElement(permissions, i)).toString();
- auto value = results[i] == PERMISSION_GRANTED ?
- QtAndroidPrivate::PermissionsResult::Granted :
- QtAndroidPrivate::PermissionsResult::Denied;
- hash[permission] = value;
+ jobject activity = env->CallStaticObjectMethod(jQtNative, activityMethodID);
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return JNI_FALSE;
+
+ QWriteLocker locker(g_updateMutex());
+
+ if (g_jActivity) {
+ env->DeleteGlobalRef(g_jActivity);
+ g_jActivity = nullptr;
}
- QMetaObject::invokeMethod(request, "sendResult", connection, Q_ARG(QtAndroidPrivate::PermissionsHash, hash));
-}
-static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event)
-{
- jboolean ret = JNI_FALSE;
- QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- for (auto *listener : qAsConst(g_genericMotionEventListeners()->listeners))
- ret |= listener->handleGenericMotionEvent(event);
- return ret;
-}
+ if (activity) {
+ g_jActivity = env->NewGlobalRef(activity);
+ env->DeleteLocalRef(activity);
+ }
-namespace {
- struct KeyEventListeners {
- QMutex mutex;
- QList<QtAndroidPrivate::KeyEventListener *> listeners;
- };
-}
-Q_GLOBAL_STATIC(KeyEventListeners, g_keyEventListeners)
+ env->DeleteLocalRef(jQtNative);
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return JNI_FALSE;
-static jboolean dispatchKeyEvent(JNIEnv *, jclass, jobject event)
-{
- jboolean ret = JNI_FALSE;
- QMutexLocker locker(&g_keyEventListeners()->mutex);
- for (auto *listener : qAsConst(g_keyEventListeners()->listeners))
- ret |= listener->handleKeyEvent(event);
- return ret;
+ return JNI_TRUE;
}
namespace {
@@ -286,102 +180,50 @@ void QtAndroidPrivate::handleResume()
listeners.at(i)->handleResume();
}
-static inline bool exceptionCheck(JNIEnv *env)
-{
- if (env->ExceptionCheck()) {
-#ifdef QT_DEBUG
- env->ExceptionDescribe();
-#endif // QT_DEBUG
- env->ExceptionClear();
- return true;
- }
-
- return false;
-}
-
-static void setAndroidSdkVersion(JNIEnv *env)
-{
- jclass androidVersionClass = env->FindClass("android/os/Build$VERSION");
- if (exceptionCheck(env))
- return;
-
- jfieldID androidSDKFieldID = env->GetStaticFieldID(androidVersionClass, "SDK_INT", "I");
- if (exceptionCheck(env))
- return;
-
- g_androidSdkVersion = env->GetStaticIntField(androidVersionClass, androidSDKFieldID);
-}
-
-static void setNativeActivity(JNIEnv *env, jclass, jobject activity)
-{
- if (g_jActivity != 0)
- env->DeleteGlobalRef(g_jActivity);
-
- if (activity != 0) {
- g_jActivity = env->NewGlobalRef(activity);
- env->DeleteLocalRef(activity);
- } else {
- g_jActivity = 0;
- }
-}
-
-static void setNativeService(JNIEnv *env, jclass, jobject service)
-{
- if (g_jService != 0)
- env->DeleteGlobalRef(g_jService);
-
- if (service != 0) {
- g_jService = env->NewGlobalRef(service);
- env->DeleteLocalRef(service);
- } else {
- g_jService = 0;
- }
-}
-
jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
{
- jclass jQtNative = env->FindClass("org/qtproject/qt5/android/QtNative");
+ g_javaVM = vm;
- if (exceptionCheck(env))
+ jclass jQtNative = env->FindClass("org/qtproject/qt/android/QtNative");
+
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
jmethodID activityMethodID = env->GetStaticMethodID(jQtNative,
"activity",
"()Landroid/app/Activity;");
- if (exceptionCheck(env))
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
jobject activity = env->CallStaticObjectMethod(jQtNative, activityMethodID);
- if (exceptionCheck(env))
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
jmethodID serviceMethodID = env->GetStaticMethodID(jQtNative,
"service",
"()Landroid/app/Service;");
- if (exceptionCheck(env))
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
jobject service = env->CallStaticObjectMethod(jQtNative, serviceMethodID);
- if (exceptionCheck(env))
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
jmethodID classLoaderMethodID = env->GetStaticMethodID(jQtNative,
"classLoader",
"()Ljava/lang/ClassLoader;");
- if (exceptionCheck(env))
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
jobject classLoader = env->CallStaticObjectMethod(jQtNative, classLoaderMethodID);
- if (exceptionCheck(env))
+ if (QJniEnvironment::checkAndClearExceptions(env))
return JNI_ERR;
- setAndroidSdkVersion(env);
-
g_jClassLoader = env->NewGlobalRef(classLoader);
env->DeleteLocalRef(classLoader);
if (activity) {
@@ -392,52 +234,61 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
g_jService = env->NewGlobalRef(service);
env->DeleteLocalRef(service);
}
- g_javaVM = vm;
static const JNINativeMethod methods[] = {
- {"runPendingCppRunnables", "()V", reinterpret_cast<void *>(runPendingCppRunnables)},
- {"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast<void *>(dispatchGenericMotionEvent)},
- {"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast<void *>(dispatchKeyEvent)},
- {"setNativeActivity", "(Landroid/app/Activity;)V", reinterpret_cast<void *>(setNativeActivity)},
- {"setNativeService", "(Landroid/app/Service;)V", reinterpret_cast<void *>(setNativeService)},
- {"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V", reinterpret_cast<void *>(sendRequestPermissionsResult)},
+ {"updateNativeActivity", "()Z", reinterpret_cast<void *>(updateNativeActivity) },
};
const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK);
+ env->DeleteLocalRef(jQtNative);
+ if (!regOk && QJniEnvironment::checkAndClearExceptions(env))
+ return JNI_ERR;
- if (!regOk && exceptionCheck(env))
+ QJniEnvironment qJniEnv;
+ if (!registerPermissionNatives(qJniEnv))
return JNI_ERR;
- g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative,
- "runPendingCppRunnablesOnAndroidThread",
- "()V");
- g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "(I)V");
- g_jNativeClass = static_cast<jclass>(env->NewGlobalRef(jQtNative));
- env->DeleteLocalRef(jQtNative);
+ if (!registerNativeInterfaceNatives(qJniEnv))
+ return JNI_ERR;
+
+ if (!registerExtrasNatives(qJniEnv))
+ return JNI_ERR;
- qRegisterMetaType<QtAndroidPrivate::PermissionsHash>();
return JNI_OK;
}
+Q_CORE_EXPORT jobject qt_androidActivity()
+{
+ QReadLocker locker(g_updateMutex());
+ return g_jActivity;
+}
+
-jobject QtAndroidPrivate::activity()
+QtJniTypes::Activity QtAndroidPrivate::activity()
{
+ QReadLocker locker(g_updateMutex());
return g_jActivity;
}
-jobject QtAndroidPrivate::service()
+Q_CORE_EXPORT jobject qt_androidService()
+{
+ return g_jService;
+}
+
+QtJniTypes::Service QtAndroidPrivate::service()
{
return g_jService;
}
-jobject QtAndroidPrivate::context()
+QtJniTypes::Context QtAndroidPrivate::context()
{
+ QReadLocker locker(g_updateMutex());
if (g_jActivity)
return g_jActivity;
if (g_jService)
return g_jService;
- return 0;
+ return nullptr;
}
JavaVM *QtAndroidPrivate::javaVM()
@@ -452,169 +303,84 @@ jobject QtAndroidPrivate::classLoader()
jint QtAndroidPrivate::androidSdkVersion()
{
- return g_androidSdkVersion;
-}
-
-void QtAndroidPrivate::runOnUiThread(QRunnable *runnable, JNIEnv *env)
-{
- runOnAndroidThread([runnable]() {
- runnable->run();
- if (runnable->autoDelete())
- delete runnable;
- }, env);
+ static jint sdkVersion = 0;
+ if (!sdkVersion)
+ sdkVersion = QJniObject::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT");
+ return sdkVersion;
}
-void QtAndroidPrivate::runOnAndroidThread(const QtAndroidPrivate::Runnable &runnable, JNIEnv *env)
+void QtAndroidPrivate::waitForServiceSetup()
{
- QMutexLocker locker(&g_pendingRunnablesMutex);
- const bool triggerRun = g_pendingRunnables->empty();
- g_pendingRunnables->push_back(runnable);
- locker.unlock();
- if (triggerRun)
- env->CallStaticVoidMethod(g_jNativeClass, g_runPendingCppRunnablesMethodID);
+ g_waitForServiceSetupSemaphore->acquire();
}
-static bool waitForSemaphore(int timeoutMs, QSharedPointer<QSemaphore> sem)
+int QtAndroidPrivate::acuqireServiceSetup(int flags)
{
- while (timeoutMs > 0) {
- if (sem->tryAcquire(1, 10))
- return true;
- timeoutMs -= 10;
- QCoreApplication::processEvents();
- }
- return false;
+ g_serviceSetupLockers.ref();
+ return flags;
}
-void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable &runnable, JNIEnv *env, int timeoutMs)
+void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *listener)
{
- QSharedPointer<QSemaphore> sem(new QSemaphore);
- runOnAndroidThread([&runnable, sem]{
- runnable();
- sem->release();
- }, env);
- waitForSemaphore(timeoutMs, sem);
+ const auto lock = qt_scoped_lock(g_onBindListenerMutex);
+ g_onBindListener = listener;
+ if (!g_serviceSetupLockers.deref())
+ g_waitForServiceSetupSemaphore->release();
}
-void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permissions, const QtAndroidPrivate::PermissionsResultFunc &callbackFunc, bool directCall)
+jobject QtAndroidPrivate::callOnBindListener(jobject intent)
{
- if (androidSdkVersion() < 23 || !activity()) {
- QHash<QString, QtAndroidPrivate::PermissionsResult> res;
- for (const auto &perm : permissions)
- res[perm] = checkPermission(perm);
- callbackFunc(res);
- return;
- }
- // Check API 23+ permissions
- const int requestCode = nextRequestCode();
- if (!directCall) {
- QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- (*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
- }
-
- runOnAndroidThread([permissions, callbackFunc, requestCode, directCall] {
- if (directCall) {
- QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- (*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
- }
-
- QJNIEnvironmentPrivate env;
- auto array = env->NewObjectArray(permissions.size(), env->FindClass("java/lang/String"), nullptr);
- int index = 0;
- for (const auto &perm : permissions)
- env->SetObjectArrayElement(array, index++, QJNIObjectPrivate::fromString(perm).object());
- QJNIObjectPrivate(activity()).callMethod<void>("requestPermissions", "([Ljava/lang/String;I)V", array, requestCode);
- env->DeleteLocalRef(array);
- }, env);
+ const auto lock = qt_scoped_lock(g_onBindListenerMutex);
+ if (g_onBindListener)
+ return g_onBindListener->onBind(intent);
+ return nullptr;
}
-QtAndroidPrivate::PermissionsHash QtAndroidPrivate::requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs)
-{
- QSharedPointer<QHash<QString, QtAndroidPrivate::PermissionsResult>> res(new QHash<QString, QtAndroidPrivate::PermissionsResult>());
- QSharedPointer<QSemaphore> sem(new QSemaphore);
- requestPermissions(env, permissions, [sem, res](const QHash<QString, PermissionsResult> &result){
- *res = result;
- sem->release();
- }, true);
- if (waitForSemaphore(timeoutMs, sem))
- return std::move(*res);
- else // mustn't touch *res
- return QHash<QString, QtAndroidPrivate::PermissionsResult>();
-}
+Q_CONSTINIT static QBasicAtomicInt g_androidDeadlockProtector = Q_BASIC_ATOMIC_INITIALIZER(0);
-QtAndroidPrivate::PermissionsResult QtAndroidPrivate::checkPermission(const QString &permission)
+bool QtAndroidPrivate::acquireAndroidDeadlockProtector()
{
- const auto res = QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt5/android/QtNative",
- "checkSelfPermission",
- "(Ljava/lang/String;)I",
- QJNIObjectPrivate::fromString(permission).object());
- return res == PERMISSION_GRANTED ? PermissionsResult::Granted : PermissionsResult::Denied;
+ return g_androidDeadlockProtector.testAndSetAcquire(0, 1);
}
-bool QtAndroidPrivate::shouldShowRequestPermissionRationale(const QString &permission)
+void QtAndroidPrivate::releaseAndroidDeadlockProtector()
{
- if (androidSdkVersion() < 23 || !activity())
- return false;
-
- return QJNIObjectPrivate(activity()).callMethod<jboolean>("shouldShowRequestPermissionRationale", "(Ljava/lang/String;)Z",
- QJNIObjectPrivate::fromString(permission).object());
+ g_androidDeadlockProtector.storeRelease(0);
}
-void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener)
-{
- QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- g_genericMotionEventListeners()->listeners.push_back(listener);
-}
+QT_END_NAMESPACE
-void QtAndroidPrivate::unregisterGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener)
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
- QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- g_genericMotionEventListeners()->listeners.removeOne(listener);
-}
+ Q_UNUSED(reserved);
-void QtAndroidPrivate::registerKeyEventListener(QtAndroidPrivate::KeyEventListener *listener)
-{
- QMutexLocker locker(&g_keyEventListeners()->mutex);
- g_keyEventListeners()->listeners.push_back(listener);
-}
+ static const char logTag[] = "QtCore";
+ static bool initialized = false;
+ if (initialized)
+ return JNI_VERSION_1_6;
+ initialized = true;
-void QtAndroidPrivate::unregisterKeyEventListener(QtAndroidPrivate::KeyEventListener *listener)
-{
- QMutexLocker locker(&g_keyEventListeners()->mutex);
- g_keyEventListeners()->listeners.removeOne(listener);
-}
+ typedef union {
+ JNIEnv *nenv;
+ void *venv;
+ } _JNIEnv;
-void QtAndroidPrivate::hideSplashScreen(JNIEnv *env, int duration)
-{
- env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID, duration);
-}
+ __android_log_print(ANDROID_LOG_INFO, logTag, "Start");
-void QtAndroidPrivate::waitForServiceSetup()
-{
- g_waitForServiceSetupSemaphore->acquire();
-}
+ _JNIEnv uenv;
+ uenv.venv = nullptr;
-int QtAndroidPrivate::acuqireServiceSetup(int flags)
-{
- g_serviceSetupLockers->ref();
- return flags;
-}
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed");
+ return JNI_ERR;
+ }
-void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *listener)
-{
- QMutexLocker lock(g_onBindListenerMutex);
- *g_onBindListener = listener;
- if (!g_serviceSetupLockers->deref())
- g_waitForServiceSetupSemaphore->release();
-}
+ JNIEnv *env = uenv.nenv;
+ const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, env));
+ if (ret != 0) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "initJNI failed");
+ return ret;
+ }
-jobject QtAndroidPrivate::callOnBindListener(jobject intent)
-{
- QMutexLocker lock(g_onBindListenerMutex);
- if (*g_onBindListener)
- return (*g_onBindListener)->onBind(intent);
- return nullptr;
+ return JNI_VERSION_1_6;
}
-
-QT_END_NAMESPACE
-
-#include "qjnihelpers.moc"
diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h
index ea5103c173..b5e05fcaf1 100644
--- a/src/corelib/kernel/qjnihelpers_p.h
+++ b/src/corelib/kernel/qjnihelpers_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJNIHELPERS_H
#define QJNIHELPERS_H
@@ -54,13 +18,12 @@
#include <jni.h>
#include <functional>
#include <QtCore/private/qglobal_p.h>
-#include <QHash>
-#include <QMetaType>
+#include <QtCore/qcoreapplication_platform.h>
QT_BEGIN_NAMESPACE
-class QRunnable;
-class QStringList;
+Q_DECLARE_JNI_CLASS(Activity, "android/app/Activity")
+Q_DECLARE_JNI_CLASS(Service, "android/app/Service")
namespace QtAndroidPrivate
{
@@ -86,20 +49,6 @@ namespace QtAndroidPrivate
virtual void handleResume();
};
- class Q_CORE_EXPORT GenericMotionEventListener
- {
- public:
- virtual ~GenericMotionEventListener();
- virtual bool handleGenericMotionEvent(jobject event) = 0;
- };
-
- class Q_CORE_EXPORT KeyEventListener
- {
- public:
- virtual ~KeyEventListener();
- virtual bool handleKeyEvent(jobject event) = 0;
- };
-
class Q_CORE_EXPORT OnBindListener
{
public:
@@ -107,28 +56,18 @@ namespace QtAndroidPrivate
virtual jobject onBind(jobject intent) = 0;
};
- enum class PermissionsResult {
- Granted,
- Denied
- };
- typedef QHash<QString, QtAndroidPrivate::PermissionsResult> PermissionsHash;
- typedef std::function<void()> Runnable;
- typedef std::function<void(const PermissionsHash &)> PermissionsResultFunc;
-
- Q_CORE_EXPORT jobject activity();
- Q_CORE_EXPORT jobject service();
- Q_CORE_EXPORT jobject context();
+ Q_CORE_EXPORT QtJniTypes::Activity activity();
+ Q_CORE_EXPORT QtJniTypes::Service service();
+ Q_CORE_EXPORT QtJniTypes::Context context();
Q_CORE_EXPORT JavaVM *javaVM();
Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env);
+ Q_CORE_EXPORT jclass findClass(const char *className, JNIEnv *env);
jobject classLoader();
Q_CORE_EXPORT jint androidSdkVersion();
- Q_CORE_EXPORT void runOnAndroidThread(const Runnable &runnable, JNIEnv *env);
- Q_CORE_EXPORT void runOnAndroidThreadSync(const Runnable &runnable, JNIEnv *env, int timeoutMs = INT_MAX);
- Q_CORE_EXPORT void runOnUiThread(QRunnable *runnable, JNIEnv *env);
- Q_CORE_EXPORT void requestPermissions(JNIEnv *env, const QStringList &permissions, const PermissionsResultFunc &callbackFunc, bool directCall = false);
- Q_CORE_EXPORT PermissionsHash requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs = INT_MAX);
- Q_CORE_EXPORT PermissionsResult checkPermission(const QString &permission);
- Q_CORE_EXPORT bool shouldShowRequestPermissionRationale(const QString &permission);
+
+ bool registerPermissionNatives(QJniEnvironment &env);
+ bool registerNativeInterfaceNatives(QJniEnvironment &env);
+ bool registerExtrasNatives(QJniEnvironment &env);
Q_CORE_EXPORT void handleActivityResult(jint requestCode, jint resultCode, jobject data);
Q_CORE_EXPORT void registerActivityResultListener(ActivityResultListener *listener);
@@ -143,24 +82,54 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT void registerResumePauseListener(ResumePauseListener *listener);
Q_CORE_EXPORT void unregisterResumePauseListener(ResumePauseListener *listener);
- Q_CORE_EXPORT void registerGenericMotionEventListener(GenericMotionEventListener *listener);
- Q_CORE_EXPORT void unregisterGenericMotionEventListener(GenericMotionEventListener *listener);
-
- Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener);
- Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener);
-
- Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env, int duration = 0);
-
-
Q_CORE_EXPORT void waitForServiceSetup();
Q_CORE_EXPORT int acuqireServiceSetup(int flags);
Q_CORE_EXPORT void setOnBindListener(OnBindListener *listener);
Q_CORE_EXPORT jobject callOnBindListener(jobject intent);
+ Q_CORE_EXPORT bool acquireAndroidDeadlockProtector();
+ Q_CORE_EXPORT void releaseAndroidDeadlockProtector();
}
-QT_END_NAMESPACE
+#define Q_JNI_FIND_AND_CHECK_CLASS(CLASS_NAME) \
+ clazz = env.findClass(CLASS_NAME); \
+ if (!clazz) { \
+ __android_log_print(ANDROID_LOG_FATAL, m_qtTag, QtAndroid::classErrorMsgFmt(), CLASS_NAME);\
+ return JNI_FALSE; \
+ }
+
+#define Q_JNI_GET_AND_CHECK_METHOD(ID, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
+ ID = env.findMethod(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
+ if (!ID) { \
+ __android_log_print(ANDROID_LOG_FATAL, m_qtTag, QtAndroid::methodErrorMsgFmt(), \
+ METHOD_NAME, METHOD_SIGNATURE); \
+ return JNI_FALSE; \
+ }
+
+#define Q_JNI_GET_AND_CHECK_STATIC_METHOD(ID, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
+ ID = env.findStaticMethod(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
+ if (!ID) { \
+ __android_log_print(ANDROID_LOG_FATAL, m_qtTag, QtAndroid::methodErrorMsgFmt(), \
+ METHOD_NAME, METHOD_SIGNATURE); \
+ return JNI_FALSE; \
+ }
+
+#define Q_JNI_GET_AND_CHECK_FIELD(ID, CLASS, FIELD_NAME, FIELD_SIGNATURE) \
+ ID = env.findField(CLASS, FIELD_NAME, FIELD_SIGNATURE); \
+ if (!ID) { \
+ __android_log_print(ANDROID_LOG_FATAL, m_qtTag, QtAndroid::fieldErrorMsgFmt(), \
+ FIELD_NAME, FIELD_SIGNATURE); \
+ return JNI_FALSE; \
+ }
+
+#define Q_JNI_GET_AND_CHECK_STATIC_FIELD(ID, CLASS, FIELD_NAME, FIELD_SIGNATURE) \
+ ID = env.findStaticField(CLASS, FIELD_NAME, FIELD_SIGNATURE); \
+ if (!ID) { \
+ __android_log_print(ANDROID_LOG_FATAL, m_qtTag, QtAndroid::fieldErrorMsgFmt(), \
+ FIELD_NAME, FIELD_SIGNATURE); \
+ return JNI_FALSE; \
+ }
-Q_DECLARE_METATYPE(QtAndroidPrivate::PermissionsHash)
+QT_END_NAMESPACE
#endif // QJNIHELPERS_H
diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp
new file mode 100644
index 0000000000..8244a4390f
--- /dev/null
+++ b/src/corelib/kernel/qjniobject.cpp
@@ -0,0 +1,1432 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qjniobject.h"
+
+#include "qjnihelpers_p.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qreadwritelock.h>
+#include <QtCore/qloggingcategory.h>
+
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcJniThreadCheck, "qt.core.jni.threadcheck")
+
+using namespace Qt::StringLiterals;
+
+/*!
+ \class QJniObject
+ \inmodule QtCore
+ \since 6.1
+ \brief A convenience wrapper around the Java Native Interface (JNI).
+
+ The QJniObject class wraps a reference to a Java object, ensuring it isn't
+ garbage-collected and providing access to most \c JNIEnv method calls
+ (member, static) and fields (setter, getter). It eliminates much
+ boiler-plate that would normally be needed, with direct JNI access, for
+ every operation, including exception-handling.
+
+ \note This API has been designed and tested for use with Android.
+ It has not been tested for other platforms.
+
+ \sa QJniEnvironment
+
+ \section1 General Notes
+
+ \list
+ \li Class names need to be fully-qualified, for example: \c "java/lang/String".
+ \li Method signatures are written as \c "(ArgumentsTypes)ReturnType", see \l {JNI Types}.
+ \li All object types are returned as a QJniObject.
+ \endlist
+
+ \section1 Method Signatures
+
+ QJniObject provides convenience functions that will use the correct signature based on the
+ provided template types. For functions that only return and take \l {JNI types}, the
+ signature can be generate at compile time:
+
+ \code
+ jint x = QJniObject::callMethod<jint>("getSize");
+ QJniObject::callMethod<void>("touch");
+ jint ret = jString1.callMethod<jint>("compareToIgnoreCase", jString2.object<jstring>());
+ \endcode
+
+ These functions are variadic templates, and the compiler will deduce the template arguments
+ from the actual argument types. In many situations, only the return type needs to be provided
+ explicitly.
+
+ For functions that take other argument types, you need to supply the signature yourself. It is
+ important that the signature matches the function you want to call. The example below
+ demonstrates how to call different static functions:
+
+ \code
+ // Java class
+ package org.qtproject.qt;
+ class TestClass
+ {
+ static TestClass create() { ... }
+ static String fromNumber(int x) { ... }
+ static String[] stringArray(String s1, String s2) { ... }
+ }
+ \endcode
+
+ The signature structure is \c "(ArgumentsTypes)ReturnType". Array types in the signature
+ must have the \c {[} prefix, and the fully-qualified \c Object type names must have the
+ \c L prefix and the \c ; suffix. The signature for the \c create function is
+ \c {"()Lorg/qtproject/qt/TestClass;}. The signatures for the second and third functions
+ are \c {"(I)Ljava/lang/String;"} and
+ \c {"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"}, respectively.
+
+ We can call the \c create() function like this:
+
+ \code
+ // C++ code
+ QJniObject testClass = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
+ "create",
+ "()Lorg/qtproject/qt/TestClass;");
+ \endcode
+
+ For the second and third function we can rely on QJniObject's template methods to create
+ the implicit signature string, but we can also pass the signature string explicitly:
+
+ \code
+ // C++ code
+ QJniObject stringNumber = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
+ "fromNumber",
+ "(I)Ljava/lang/String;", 10);
+ \endcode
+
+ For the implicit signature creation to work we need to specify the return type explicitly:
+
+ \code
+ // C++ code
+ QJniObject string1 = QJniObject::fromString("String1");
+ QJniObject string2 = QJniObject::fromString("String2");
+ QJniObject stringArray = QJniObject::callStaticObjectMethod<jstringArray>(
+ "org/qtproject/qt/TestClass",
+ "stringArray"
+ string1.object<jstring>(),
+ string2.object<jstring>());
+ \endcode
+
+ Note that while the first template parameter specifies the return type of the Java
+ function, the method will still return a QJniObject.
+
+ \section1 Handling Java Exception
+
+ After calling Java functions that might throw exceptions, it is important
+ to check for, handle and clear out any exception before continuing. All
+ QJniObject functions handle exceptions internally by reporting and clearing them,
+ saving client code the need to handle exceptions.
+
+ \note The user must handle exceptions manually when doing JNI calls using \c JNIEnv directly.
+ It is unsafe to make other JNI calls when exceptions are pending. For more information, see
+ QJniEnvironment::checkAndClearExceptions().
+
+ \section1 Java Native Methods
+
+ Java native methods makes it possible to call native code from Java, this is done by creating a
+ function declaration in Java and prefixing it with the \c native keyword.
+ Before a native function can be called from Java, you need to map the Java native function to a
+ native function in your code. Mapping functions can be done by calling
+ QJniEnvironment::registerNativeMethods().
+
+ The example below demonstrates how this could be done.
+
+ Java implementation:
+ \snippet jni/src_qjniobject.cpp Java native methods
+
+ C++ Implementation:
+ \snippet jni/src_qjniobject.cpp C++ native methods
+
+ \section1 The Lifetime of a Java Object
+
+ Most \l{Object types}{objects} received from Java will be local references
+ and will only stay valid until you return from the native method. After that,
+ the object becomes eligible for garbage collection. If your code creates
+ many local references in a loop you should delete them manually with each
+ iteration, otherwise you might run out of memory. For more information, see
+ \l {JNI Design Overview: Global and Local References}. Local references
+ created outside a native method scope must be deleted manually, since
+ the garbage collector will not free them automatically because we are using
+ \l {Java: AttachCurrentThread}{AttachCurrentThread}. For more information, see
+ \l {JNI tips: Local and global references}.
+
+ If you want to keep a Java object alive you need to either create a new global
+ reference to the object and release it when you are done, or construct a new
+ QJniObject and let it manage the lifetime of the Java object.
+
+ \sa object()
+
+ \note The QJniObject only manages its own references, if you construct a QJniObject from a
+ global or local reference that reference will not be released by the QJniObject.
+
+ \section1 JNI Types
+
+ \section2 Object Types
+ \table
+ \header
+ \li Type
+ \li Signature
+ \row
+ \li jobject
+ \li Ljava/lang/Object;
+ \row
+ \li jclass
+ \li Ljava/lang/Class;
+ \row
+ \li jstring
+ \li Ljava/lang/String;
+ \row
+ \li jthrowable
+ \li Ljava/lang/Throwable;
+ \row
+ \li jobjectArray
+ \li [Ljava/lang/Object;
+ \row
+ \li jarray
+ \li [\e<type>
+ \row
+ \li jbooleanArray
+ \li [Z
+ \row
+ \li jbyteArray
+ \li [B
+ \row
+ \li jcharArray
+ \li [C
+ \row
+ \li jshortArray
+ \li [S
+ \row
+ \li jintArray
+ \li [I
+ \row
+ \li jlongArray
+ \li [J
+ \row
+ \li jfloatArray
+ \li [F
+ \row
+ \li jdoubleArray
+ \li [D
+ \endtable
+
+ \section2 Primitive Types
+ \table
+ \header
+ \li Type
+ \li Signature
+ \row
+ \li jboolean
+ \li Z
+ \row
+ \li jbyte
+ \li B
+ \row
+ \li jchar
+ \li C
+ \row
+ \li jshort
+ \li S
+ \row
+ \li jint
+ \li I
+ \row
+ \li jlong
+ \li J
+ \row
+ \li jfloat
+ \li F
+ \row
+ \li jdouble
+ \li D
+ \endtable
+
+ \section2 Other
+ \table
+ \header
+ \li Type
+ \li Signature
+ \row
+ \li void
+ \li V
+ \row
+ \li \e{Custom type}
+ \li L\e<fully-qualified-name>;
+ \endtable
+
+ For more information about JNI, see \l {Java Native Interface Specification}.
+*/
+
+/*!
+ \fn bool operator==(const QJniObject &o1, const QJniObject &o2)
+
+ \relates QJniObject
+
+ Returns true if both objects, \a o1 and \a o2, are referencing the same Java object, or if both
+ are NULL. In any other cases false will be returned.
+*/
+
+/*!
+ \fn bool operator!=(const QJniObject &o1, const QJniObject &o2)
+ \relates QJniObject
+
+ Returns true if \a o1 holds a reference to a different object than \a o2.
+*/
+
+class QJniObjectPrivate
+{
+public:
+ QJniObjectPrivate()
+ {
+ }
+ ~QJniObjectPrivate() {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ if (m_jobject)
+ env->DeleteGlobalRef(m_jobject);
+ if (m_jclass && m_own_jclass)
+ env->DeleteGlobalRef(m_jclass);
+ }
+
+ template <typename ...Args>
+ void construct(const char *signature = nullptr, Args &&...args)
+ {
+ if (m_jclass) {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ // get default constructor
+ jmethodID constructorId = QJniObject::getCachedMethodID(env, m_jclass, m_className, "<init>",
+ signature ? signature : "()V");
+ if (constructorId) {
+ jobject obj = nullptr;
+ if constexpr (sizeof...(Args) == 0)
+ obj = env->NewObject(m_jclass, constructorId);
+ else
+ obj = env->NewObjectV(m_jclass, constructorId, std::forward<Args>(args)...);
+ if (obj) {
+ m_jobject = env->NewGlobalRef(obj);
+ env->DeleteLocalRef(obj);
+ }
+ }
+ }
+ }
+
+ QByteArray m_className;
+ jobject m_jobject = nullptr;
+ jclass m_jclass = nullptr;
+ bool m_own_jclass = true;
+};
+
+template <typename ...Args>
+static inline QByteArray cacheKey(Args &&...args)
+{
+ return (QByteArrayView(":") + ... + QByteArrayView(args));
+}
+
+typedef QHash<QByteArray, jclass> JClassHash;
+Q_GLOBAL_STATIC(JClassHash, cachedClasses)
+Q_GLOBAL_STATIC(QReadWriteLock, cachedClassesLock)
+
+static jclass getCachedClass(const QByteArray &className)
+{
+ QReadLocker locker(cachedClassesLock);
+ const auto &it = cachedClasses->constFind(className);
+ return it != cachedClasses->constEnd() ? it.value() : nullptr;
+}
+
+/*!
+ \internal
+
+ Get a JNI object from a jobject variant and do the necessary
+ exception clearing and delete the local reference before returning.
+ The JNI object can be null if there was an exception.
+*/
+static QJniObject getCleanJniObject(jobject object, JNIEnv *env)
+{
+ if (QJniEnvironment::checkAndClearExceptions(env) || !object) {
+ if (object)
+ env->DeleteLocalRef(object);
+ return QJniObject();
+ }
+
+ QJniObject res(object);
+ env->DeleteLocalRef(object);
+ return res;
+}
+
+/*!
+ \internal
+ \a className must be slash-encoded
+*/
+jclass QtAndroidPrivate::findClass(const char *className, JNIEnv *env)
+{
+ Q_ASSERT(env);
+ QByteArray classNameArray(className);
+#ifdef QT_DEBUG
+ if (classNameArray.contains('.')) {
+ qWarning("QtAndroidPrivate::findClass: className '%s' should use slash separators!",
+ className);
+ }
+#endif
+ classNameArray.replace('.', '/');
+ jclass clazz = getCachedClass(classNameArray);
+ if (clazz)
+ return clazz;
+
+ QWriteLocker locker(cachedClassesLock);
+ // Check again; another thread might have added the class to the cache after
+ // our call to getCachedClass and before we acquired the lock.
+ const auto &it = cachedClasses->constFind(classNameArray);
+ if (it != cachedClasses->constEnd())
+ return it.value();
+
+ // JNIEnv::FindClass wants "a fully-qualified class name or an array type signature"
+ // which is a slash-separated class name.
+ jclass localClazz = env->FindClass(classNameArray.constData());
+ if (localClazz) {
+ clazz = static_cast<jclass>(env->NewGlobalRef(localClazz));
+ env->DeleteLocalRef(localClazz);
+ } else {
+ // Clear the exception silently; we are going to try the ClassLoader next,
+ // so no need for warning unless that fails as well.
+ env->ExceptionClear();
+ }
+
+ if (!clazz) {
+ // Wrong class loader, try our own
+ QJniObject classLoader(QtAndroidPrivate::classLoader());
+ if (!classLoader.isValid())
+ return nullptr;
+
+ // ClassLoader::loadClass on the other hand wants the binary name of the class,
+ // e.g. dot-separated. In testing it works also with /, but better to stick to
+ // the specification.
+ const QString binaryClassName = QString::fromLatin1(className).replace(u'/', u'.');
+ jstring classNameObject = env->NewString(reinterpret_cast<const jchar*>(binaryClassName.constData()),
+ binaryClassName.length());
+ QJniObject classObject = classLoader.callMethod<jclass>("loadClass", classNameObject);
+ env->DeleteLocalRef(classNameObject);
+
+ if (!QJniEnvironment::checkAndClearExceptions(env) && classObject.isValid())
+ clazz = static_cast<jclass>(env->NewGlobalRef(classObject.object()));
+ }
+
+ if (clazz)
+ cachedClasses->insert(classNameArray, clazz);
+
+ return clazz;
+}
+
+jclass QJniObject::loadClass(const QByteArray &className, JNIEnv *env)
+{
+ return QtAndroidPrivate::findClass(className, env);
+}
+
+typedef QHash<QByteArray, jmethodID> JMethodIDHash;
+Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID)
+Q_GLOBAL_STATIC(QReadWriteLock, cachedMethodIDLock)
+
+jmethodID QJniObject::getMethodID(JNIEnv *env,
+ jclass clazz,
+ const char *name,
+ const char *signature,
+ bool isStatic)
+{
+ jmethodID id = isStatic ? env->GetStaticMethodID(clazz, name, signature)
+ : env->GetMethodID(clazz, name, signature);
+
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return nullptr;
+
+ return id;
+}
+
+void QJniObject::callVoidMethodV(JNIEnv *env, jmethodID id, ...) const
+{
+ va_list args;
+ va_start(args, id);
+ env->CallVoidMethodV(d->m_jobject, id, args);
+ va_end(args);
+}
+
+jmethodID QJniObject::getCachedMethodID(JNIEnv *env,
+ jclass clazz,
+ const QByteArray &className,
+ const char *name,
+ const char *signature,
+ bool isStatic)
+{
+ if (className.isEmpty())
+ return getMethodID(env, clazz, name, signature, isStatic);
+
+ const QByteArray key = cacheKey(className, name, signature);
+ QHash<QByteArray, jmethodID>::const_iterator it;
+
+ {
+ QReadLocker locker(cachedMethodIDLock);
+ it = cachedMethodID->constFind(key);
+ if (it != cachedMethodID->constEnd())
+ return it.value();
+ }
+
+ {
+ QWriteLocker locker(cachedMethodIDLock);
+ it = cachedMethodID->constFind(key);
+ if (it != cachedMethodID->constEnd())
+ return it.value();
+
+ jmethodID id = getMethodID(env, clazz, name, signature, isStatic);
+
+ cachedMethodID->insert(key, id);
+ return id;
+ }
+}
+
+jmethodID QJniObject::getCachedMethodID(JNIEnv *env, const char *name,
+ const char *signature, bool isStatic) const
+{
+ return QJniObject::getCachedMethodID(env, d->m_jclass, d->m_className, name, signature, isStatic);
+}
+
+typedef QHash<QByteArray, jfieldID> JFieldIDHash;
+Q_GLOBAL_STATIC(JFieldIDHash, cachedFieldID)
+Q_GLOBAL_STATIC(QReadWriteLock, cachedFieldIDLock)
+
+jfieldID QJniObject::getFieldID(JNIEnv *env,
+ jclass clazz,
+ const char *name,
+ const char *signature,
+ bool isStatic)
+{
+ jfieldID id = isStatic ? env->GetStaticFieldID(clazz, name, signature)
+ : env->GetFieldID(clazz, name, signature);
+
+ if (QJniEnvironment::checkAndClearExceptions(env))
+ return nullptr;
+
+ return id;
+}
+
+jfieldID QJniObject::getCachedFieldID(JNIEnv *env,
+ jclass clazz,
+ const QByteArray &className,
+ const char *name,
+ const char *signature,
+ bool isStatic)
+{
+ if (className.isNull())
+ return getFieldID(env, clazz, name, signature, isStatic);
+
+ const QByteArray key = cacheKey(className, name, signature);
+ QHash<QByteArray, jfieldID>::const_iterator it;
+
+ {
+ QReadLocker locker(cachedFieldIDLock);
+ it = cachedFieldID->constFind(key);
+ if (it != cachedFieldID->constEnd())
+ return it.value();
+ }
+
+ {
+ QWriteLocker locker(cachedFieldIDLock);
+ it = cachedFieldID->constFind(key);
+ if (it != cachedFieldID->constEnd())
+ return it.value();
+
+ jfieldID id = getFieldID(env, clazz, name, signature, isStatic);
+
+ cachedFieldID->insert(key, id);
+ return id;
+ }
+}
+
+jfieldID QJniObject::getCachedFieldID(JNIEnv *env,
+ const char *name,
+ const char *signature,
+ bool isStatic) const
+{
+ return QJniObject::getCachedFieldID(env, d->m_jclass, d->m_className, name, signature, isStatic);
+}
+
+/*!
+ \fn QJniObject::QJniObject()
+
+ Constructs an invalid JNI object.
+
+ \sa isValid()
+*/
+QJniObject::QJniObject()
+ : d(new QJniObjectPrivate())
+{
+}
+
+/*!
+ \fn QJniObject::QJniObject(const char *className)
+
+ Constructs a new JNI object by calling the default constructor of \a className.
+
+ \code
+ QJniObject myJavaString("java/lang/String");
+ \endcode
+*/
+QJniObject::QJniObject(const char *className)
+ : d(new QJniObjectPrivate())
+{
+ d->m_className = className;
+ d->m_jclass = loadClass(d->m_className, jniEnv());
+ d->m_own_jclass = false;
+
+ d->construct();
+}
+
+/*!
+ \fn QJniObject::QJniObject(const char *className, const char *signature, ...)
+
+ Constructs a new JNI object by calling the constructor of \a className with
+ \a signature specifying the types of any subsequent arguments.
+
+ \code
+ QJniEnvironment env;
+ char* str = "Hello";
+ jstring myJStringArg = env->NewStringUTF(str);
+ QJniObject myNewJavaString("java/lang/String", "(Ljava/lang/String;)V", myJStringArg);
+ \endcode
+*/
+QJniObject::QJniObject(const char *className, const char *signature, ...)
+ : d(new QJniObjectPrivate())
+{
+ d->m_className = className;
+ d->m_jclass = loadClass(d->m_className, jniEnv());
+ d->m_own_jclass = false;
+
+ va_list args;
+ va_start(args, signature);
+ d->construct(signature, args);
+ va_end(args);
+}
+
+/*!
+ \fn template<typename ...Args> QJniObject::QJniObject(const char *className, Args &&...args)
+ \since 6.4
+
+ Constructs a new JNI object by calling the constructor of \a className with
+ the arguments \a args. This constructor is only available if all \a args are
+ known \l {JNI Types}.
+
+ \code
+ QJniEnvironment env;
+ char* str = "Hello";
+ jstring myJStringArg = env->NewStringUTF(str);
+ QJniObject myNewJavaString("java/lang/String", myJStringArg);
+ \endcode
+*/
+
+/*!
+ Constructs a new JNI object from \a clazz by calling the constructor with
+ \a signature specifying the types of any subsequent arguments.
+
+ \code
+ QJniEnvironment env;
+ jclass myClazz = env.findClass("org/qtproject/qt/TestClass");
+ QJniObject(myClazz, "(I)V", 3);
+ \endcode
+*/
+QJniObject::QJniObject(jclass clazz, const char *signature, ...)
+ : d(new QJniObjectPrivate())
+{
+ if (clazz) {
+ d->m_jclass = static_cast<jclass>(jniEnv()->NewGlobalRef(clazz));
+ va_list args;
+ va_start(args, signature);
+ d->construct(signature, args);
+ va_end(args);
+ }
+}
+
+/*!
+ \fn template<typename ...Args> QJniObject::QJniObject(jclass clazz, Args &&...args)
+ \since 6.4
+
+ Constructs a new JNI object from \a clazz by calling the constructor with
+ the arguments \a args. This constructor is only available if all \a args are
+ known \l {JNI Types}.
+
+ \code
+ QJniEnvironment env;
+ jclass myClazz = env.findClass("org/qtproject/qt/TestClass");
+ QJniObject(myClazz, 3);
+ \endcode
+*/
+
+/*!
+ Constructs a new JNI object by calling the default constructor of \a clazz.
+
+ \note The QJniObject will create a new reference to the class \a clazz
+ and releases it again when it is destroyed. References to the class created
+ outside the QJniObject need to be managed by the caller.
+*/
+
+QJniObject::QJniObject(jclass clazz)
+ : QJniObject(clazz, "()V")
+{
+}
+
+/*!
+ Constructs a new JNI object around the Java object \a object.
+
+ \note The QJniObject will hold a reference to the Java object \a object
+ and release it when destroyed. Any references to the Java object \a object
+ outside QJniObject needs to be managed by the caller. In most cases you
+ should never call this function with a local reference unless you intend
+ to manage the local reference yourself. See QJniObject::fromLocalRef()
+ for converting a local reference to a QJniObject.
+
+ \sa fromLocalRef()
+*/
+QJniObject::QJniObject(jobject object)
+ : d(new QJniObjectPrivate())
+{
+ if (!object)
+ return;
+
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ d->m_jobject = env->NewGlobalRef(object);
+ jclass cls = env->GetObjectClass(object);
+ d->m_jclass = static_cast<jclass>(env->NewGlobalRef(cls));
+ env->DeleteLocalRef(cls);
+}
+
+/*!
+ \fn template<typename Class, typename ...Args> static inline QJniObject QJniObject::construct(Args &&...args)
+ \since 6.4
+
+ Constructs an instance of the Java class that is the equivalent of \c Class and
+ returns a QJniObject containing the JNI object. The arguments in \a args are
+ passed to the Java constructor.
+
+ \code
+ QJniObject javaString = QJniObject::construct<jstring>();
+ \endcode
+
+ This function is only available if all \a args are known \l {JNI Types}.
+*/
+
+/*!
+ \fn QJniObject::~QJniObject()
+
+ Destroys the JNI object and releases any references held by the JNI object.
+*/
+QJniObject::~QJniObject()
+{}
+
+namespace {
+QByteArray getClassNameHelper(JNIEnv *env, const QJniObjectPrivate *d)
+{
+ if (env->PushLocalFrame(3) != JNI_OK) // JVM out of memory
+ return QByteArray();
+
+ jmethodID mid = env->GetMethodID(d->m_jclass, "getClass", "()Ljava/lang/Class;");
+ jobject classObject = env->CallObjectMethod(d->m_jobject, mid);
+ jclass classObjectClass = env->GetObjectClass(classObject);
+ mid = env->GetMethodID(classObjectClass, "getName", "()Ljava/lang/String;");
+ jstring stringObject = static_cast<jstring>(env->CallObjectMethod(classObject, mid));
+ const jsize length = env->GetStringUTFLength(stringObject);
+ const char* nameString = env->GetStringUTFChars(stringObject, NULL);
+ const QByteArray result = QByteArray::fromRawData(nameString, length).replace('.', '/');
+ env->ReleaseStringUTFChars(stringObject, nameString);
+ env->PopLocalFrame(nullptr);
+ return result;
+}
+}
+
+/*! \internal
+
+ Returns the JNIEnv of the calling thread.
+*/
+JNIEnv *QJniObject::jniEnv() const noexcept
+{
+ return QJniEnvironment::getJniEnv();
+}
+
+/*!
+ \fn jobject QJniObject::object() const
+ \fn template <typename T> T QJniObject::object() const
+
+ Returns the object held by the QJniObject either as jobject or as type T.
+ T can be one of \l {Object Types}{JNI Object Types}.
+
+ \code
+ QJniObject string = QJniObject::fromString("Hello, JNI");
+ jstring jstring = string.object<jstring>();
+ \endcode
+
+ \note The returned object is still kept alive by this QJniObject. To keep the
+ object alive beyond the lifetime of this QJniObject, for example to record it
+ for later use, the easiest approach is to store it in another QJniObject with
+ a suitable lifetime. Alternatively, you may create a new global reference to the
+ object and store it, taking care to free it when you are done with it.
+
+ \snippet jni/src_qjniobject.cpp QJniObject scope
+*/
+jobject QJniObject::object() const
+{
+ return javaObject();
+}
+
+/*!
+ \fn jclass QJniObject::objectClass() const
+
+ Returns the class object held by the QJniObject as a \c jclass.
+
+ \note The returned object is still kept alive by this QJniObject. To keep the
+ object alive beyond the lifetime of this QJniObject, for example to record it
+ for later use, the easiest approach is to store it in another QJniObject with
+ a suitable lifetime. Alternatively, you may create a new global reference to the
+ object and store it, taking care to free it when you are done with it.
+
+ \since 6.2
+*/
+jclass QJniObject::objectClass() const
+{
+ return d->m_jclass;
+}
+
+/*!
+ \fn QByteArray QJniObject::className() const
+
+ Returns the name of the class object held by the QJniObject as a \c QByteArray.
+
+ \since 6.2
+*/
+QByteArray QJniObject::className() const
+{
+ if (d->m_className.isEmpty() && d->m_jclass && d->m_jobject) {
+ JNIEnv *env = jniEnv();
+ d->m_className = getClassNameHelper(env, d.get());
+ }
+ return d->m_className;
+}
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callMethod(const char *methodName, const char *signature, Args &&...args) const
+ \since 6.4
+
+ Calls the object's method \a methodName with \a signature specifying the types of any
+ subsequent arguments \a args, and returns the value (unless \c Ret is \c void). If \c Ret
+ is a jobject type, then the returned value will be a QJniObject.
+
+ \code
+ QJniObject myJavaStrin("org/qtproject/qt/TestClass");
+ jint index = myJavaString.callMethod<jint>("indexOf", "(I)I", 0x0051);
+ \endcode
+*/
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callMethod(const char *methodName, Args &&...args) const
+ \since 6.4
+
+ Calls the method \a methodName with arguments \a args and returns the value
+ (unless \c Ret is \c void). If \c Ret is a jobject type, then the returned value
+ will be a QJniObject.
+
+ \code
+ QJniObject myJavaStrin("org/qtproject/qt/TestClass");
+ jint size = myJavaString.callMethod<jint>("length");
+ \endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
+*/
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args)
+ \since 6.4
+
+ Calls the static method \a methodName from class \a className with \a signature
+ specifying the types of any subsequent arguments \a args. Returns the result of
+ the method (unless \c Ret is \c void). If \c Ret is a jobject type, then the
+ returned value will be a QJniObject.
+
+ \code
+ jint a = 2;
+ jint b = 4;
+ jint max = QJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);
+ \endcode
+*/
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callStaticMethod(const char *className, const char *methodName, Args &&...args)
+ \since 6.4
+
+ Calls the static method \a methodName on class \a className with arguments \a args,
+ and returns the value of type \c Ret (unless \c Ret is \c void). If \c Ret
+ is a jobject type, then the returned value will be a QJniObject.
+
+ \code
+ jint value = QJniObject::callStaticMethod<jint>("MyClass", "staticMethod");
+ \endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
+*/
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args)
+
+ Calls the static method \a methodName from \a clazz with \a signature
+ specifying the types of any subsequent arguments. Returns the result of
+ the method (unless \c Ret is \c void). If \c Ret is a jobject type, then the
+ returned value will be a QJniObject.
+
+ \code
+ QJniEnvironment env;
+ jclass javaMathClass = env.findClass("java/lang/Math");
+ jint a = 2;
+ jint b = 4;
+ jint max = QJniObject::callStaticMethod<jint>(javaMathClass, "max", "(II)I", a, b);
+ \endcode
+*/
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args)
+ \since 6.4
+
+ Calls the static method identified by \a methodId from the class \a clazz
+ with any subsequent arguments, and returns the value of type \c Ret (unless
+ \c Ret is \c void). If \c Ret is a jobject type, then the returned value will
+ be a QJniObject.
+
+ Useful when \a clazz and \a methodId are already cached from previous operations.
+
+ \code
+ QJniEnvironment env;
+ jclass javaMathClass = env.findClass("java/lang/Math");
+ jmethodID methodId = env.findStaticMethod(javaMathClass, "max", "(II)I");
+ if (methodId != 0) {
+ jint a = 2;
+ jint b = 4;
+ jint max = QJniObject::callStaticMethod<jint>(javaMathClass, methodId, a, b);
+ }
+ \endcode
+*/
+
+/*!
+ \fn template <typename Ret, typename ...Args> auto QJniObject::callStaticMethod(jclass clazz, const char *methodName, Args &&...args)
+ \since 6.4
+
+ Calls the static method \a methodName on \a clazz and returns the value of type \c Ret
+ (unless \c Ret is \c void). If \c Ret is a jobject type, then the returned value will
+ be a QJniObject.
+
+ \code
+ QJniEnvironment env;
+ jclass javaMathClass = env.findClass("java/lang/Math");
+ jdouble randNr = QJniObject::callStaticMethod<jdouble>(javaMathClass, "random");
+ \endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
+*/
+
+/*!
+ \fn template <typename Klass, typename Ret, typename ...Args> auto QJniObject::callStaticMethod(const char *methodName, Args &&...args)
+ \since 6.7
+
+ Calls the static method \a methodName on the class \c Klass and returns the value of type
+ \c Ret (unless \c Ret is \c void). If \c Ret is a jobject type, then the returned value will
+ be a QJniObject.
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
+ \c Klass needs to be a C++ type with a registered type mapping to a Java type.
+*/
+
+/*!
+ \fn QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const
+
+ Calls the Java object's method \a methodName with \a signature specifying
+ the types of any subsequent arguments.
+
+ \code
+ QJniObject myJavaString = QJniObject::fromString("Hello, Java");
+ QJniObject mySubstring = myJavaString.callObjectMethod("substring",
+ "(II)Ljava/lang/String;", 7, 11);
+ \endcode
+*/
+QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const
+{
+ jmethodID id = getCachedMethodID(jniEnv(), methodName, signature);
+ if (id) {
+ va_list args;
+ va_start(args, signature);
+ QJniObject res = getCleanJniObject(jniEnv()->CallObjectMethodV(d->m_jobject, id, args), jniEnv());
+ va_end(args);
+ return res;
+ }
+
+ return QJniObject();
+}
+
+/*!
+ \fn QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName, const char *signature, ...)
+
+ Calls the static method \a methodName from the class \a className with \a signature
+ specifying the types of any subsequent arguments.
+
+ \code
+ QJniObject thread = QJniObject::callStaticObjectMethod("java/lang/Thread", "currentThread",
+ "()Ljava/lang/Thread;");
+ QJniObject string = QJniObject::callStaticObjectMethod("java/lang/String", "valueOf",
+ "(I)Ljava/lang/String;", 10);
+ \endcode
+*/
+QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName,
+ const char *signature, ...)
+{
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+ if (clazz) {
+ jmethodID id = QJniObject::getCachedMethodID(env, clazz,
+ className,
+ methodName, signature, true);
+ if (id) {
+ va_list args;
+ va_start(args, signature);
+ QJniObject res = getCleanJniObject(env->CallStaticObjectMethodV(clazz, id, args), env);
+ va_end(args);
+ return res;
+ }
+ }
+
+ return QJniObject();
+}
+
+/*!
+ \fn QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName, const char *signature, ...)
+
+ Calls the static method \a methodName from class \a clazz with \a signature
+ specifying the types of any subsequent arguments.
+*/
+QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName,
+ const char *signature, ...)
+{
+ if (clazz) {
+ QJniEnvironment env;
+ jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true);
+ if (id) {
+ va_list args;
+ va_start(args, signature);
+ QJniObject res = getCleanJniObject(env->CallStaticObjectMethodV(clazz, id, args), env.jniEnv());
+ va_end(args);
+ return res;
+ }
+ }
+
+ return QJniObject();
+}
+
+/*!
+ \fn QJniObject QJniObject::callStaticObjectMethod(jclass clazz, jmethodID methodId, ...)
+
+ Calls the static method identified by \a methodId from the class \a clazz
+ with any subsequent arguments. Useful when \a clazz and \a methodId are
+ already cached from previous operations.
+
+ \code
+ QJniEnvironment env;
+ jclass clazz = env.findClass("java/lang/String");
+ jmethodID methodId = env.findStaticMethod(clazz, "valueOf", "(I)Ljava/lang/String;");
+ if (methodId != 0)
+ QJniObject str = QJniObject::callStaticObjectMethod(clazz, methodId, 10);
+ \endcode
+*/
+QJniObject QJniObject::callStaticObjectMethod(jclass clazz, jmethodID methodId, ...)
+{
+ if (clazz && methodId) {
+ QJniEnvironment env;
+ va_list args;
+ va_start(args, methodId);
+ QJniObject res = getCleanJniObject(env->CallStaticObjectMethodV(clazz, methodId, args), env.jniEnv());
+ va_end(args);
+ return res;
+ }
+
+ return QJniObject();
+}
+
+/*!
+ \fn template<typename Ret, typename ...Args> QJniObject QJniObject::callObjectMethod(const char *methodName, Args &&...args) const
+ \since 6.4
+
+ Calls the Java objects method \a methodName with arguments \a args and returns a
+ new QJniObject for the returned Java object.
+
+ \code
+ QJniObject myJavaString = QJniObject::fromString("Hello, Java");
+ QJniObject myJavaString2 = myJavaString1.callObjectMethod<jstring>("toString");
+ \endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
+*/
+
+/*!
+ \fn template<typename Ret, typename ...Args> QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName, Args &&...args)
+ \since 6.4
+
+ Calls the static method with \a methodName on the class \a className, passing
+ arguments \a args, and returns a new QJniObject for the returned Java object.
+
+ \code
+ QJniObject string = QJniObject::callStaticObjectMethod<jstring>("CustomClass", "getClassName");
+ \endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
+*/
+
+/*!
+ \fn template<typename Ret, typename ...Args> QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args)
+ \since 6.4
+
+ Calls the static method with \a methodName on \a clazz, passing arguments \a args,
+ and returns a new QJniObject for the returned Java object.
+*/
+
+/*!
+ \fn template <typename T, std::enable_if_t<std::is_convertible_v<T, jobject>, bool> = true> QJniObject &QJniObject::operator=(T object)
+
+ Replace the current object with \a object. The old Java object will be released.
+*/
+
+/*!
+ \fn template <typename T> void QJniObject::setStaticField(const char *className, const char *fieldName, const char *signature, T value);
+
+ Sets the static field \a fieldName on the class \a className to \a value
+ using the setter with \a signature.
+
+*/
+
+/*!
+ \fn template <typename T> void QJniObject::setStaticField(jclass clazz, const char *fieldName, const char *signature, T value);
+
+ Sets the static field \a fieldName on the class \a clazz to \a value using
+ the setter with \a signature.
+*/
+
+/*!
+ \fn template<typename T> T QJniObject::getField(const char *fieldName) const
+
+ Retrieves the value of the field \a fieldName.
+
+ \code
+ QJniObject volumeControl("org/qtproject/qt/TestClass");
+ jint fieldValue = volumeControl.getField<jint>("FIELD_NAME");
+ \endcode
+*/
+
+/*!
+ \fn template<typename T> T QJniObject::getStaticField(const char *className, const char *fieldName)
+
+ Retrieves the value from the static field \a fieldName on the class \a className.
+*/
+
+/*!
+ \fn template<typename T> T QJniObject::getStaticField(jclass clazz, const char *fieldName)
+
+ Retrieves the value from the static field \a fieldName on \a clazz.
+*/
+
+/*!
+ \fn template <typename Klass, typename T> auto QJniObject::getStaticField(const char *fieldName)
+
+ Retrieves the value from the static field \a fieldName for the class \c Klass.
+
+ \c Klass needs to be a C++ type with a registered type mapping to a Java type.
+*/
+
+/*!
+ \fn template <typename T> void QJniObject::setStaticField(const char *className, const char *fieldName, T value)
+
+ Sets the static field \a fieldName of the class \a className to \a value.
+*/
+
+/*!
+ \fn template <typename T> void QJniObject::setStaticField(jclass clazz, const char *fieldName, T value)
+
+ Sets the static field \a fieldName of the class \a clazz to \a value.
+*/
+
+/*!
+ \fn template <typename Klass, typename T> auto QJniObject::setStaticField(const char *fieldName, T value)
+
+ Sets the static field \a fieldName of the class \c Klass to \a value.
+
+ \c Klass needs to be a C++ type with a registered type mapping to a Java type.
+*/
+
+/*!
+ \fn QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName, const char *signature)
+
+ Retrieves a JNI object from the field \a fieldName with \a signature from
+ class \a className.
+
+ \note This function can be used without a template type.
+
+ \code
+ QJniObject jobj = QJniObject::getStaticObjectField("class/with/Fields", "FIELD_NAME",
+ "Ljava/lang/String;");
+ \endcode
+*/
+QJniObject QJniObject::getStaticObjectField(const char *className,
+ const char *fieldName,
+ const char *signature)
+{
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+ if (!clazz)
+ return QJniObject();
+ jfieldID id = QJniObject::getCachedFieldID(env, clazz,
+ className,
+ fieldName,
+ signature, true);
+ if (!id)
+ return QJniObject();
+
+ return getCleanJniObject(env->GetStaticObjectField(clazz, id), env);
+}
+
+/*!
+ \fn QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName, const char *signature)
+
+ Retrieves a JNI object from the field \a fieldName with \a signature from
+ class \a clazz.
+
+ \note This function can be used without a template type.
+
+ \code
+ QJniObject jobj = QJniObject::getStaticObjectField(clazz, "FIELD_NAME", "Ljava/lang/String;");
+ \endcode
+*/
+QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName,
+ const char *signature)
+{
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jfieldID id = getFieldID(env, clazz, fieldName, signature, true);
+ return getCleanJniObject(env->GetStaticObjectField(clazz, id), env);
+}
+
+/*!
+ \fn template <typename T> void QJniObject::setField(const char *fieldName, const char *signature, T value)
+
+ Sets the value of \a fieldName with \a signature to \a value.
+
+ \code
+ QJniObject stringArray = ...;
+ QJniObject obj = ...;
+ obj.setObjectField<jobjectArray>("KEY_VALUES", "([Ljava/lang/String;)V",
+ stringArray.object<jobjectArray>())
+ \endcode
+*/
+
+/*!
+ \fn template<typename T> QJniObject QJniObject::getObjectField(const char *fieldName) const
+
+ Retrieves a JNI object from the field \a fieldName.
+
+ \code
+ QJniObject field = jniObject.getObjectField<jstring>("FIELD_NAME");
+ \endcode
+*/
+
+/*!
+ \fn QJniObject QJniObject::getObjectField(const char *fieldName, const char *signature) const
+
+ Retrieves a JNI object from the field \a fieldName with \a signature.
+
+ \note This function can be used without a template type.
+
+ \code
+ QJniObject field = jniObject.getObjectField("FIELD_NAME", "Ljava/lang/String;");
+ \endcode
+*/
+QJniObject QJniObject::getObjectField(const char *fieldName, const char *signature) const
+{
+ jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
+ if (!id)
+ return QJniObject();
+
+ return getCleanJniObject(jniEnv()->GetObjectField(d->m_jobject, id), jniEnv());
+}
+
+/*!
+ \fn template <typename T> void QJniObject::setField(const char *fieldName, T value)
+
+ Sets the value of \a fieldName to \a value.
+
+ \code
+ QJniObject obj;
+ obj.setField<jint>("AN_INT_FIELD", 10);
+ jstring myString = ...;
+ obj.setField<jstring>("A_STRING_FIELD", myString);
+ \endcode
+*/
+
+/*!
+ \fn template<typename T> QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName)
+
+ Retrieves the object from the field \a fieldName on the class \a className.
+
+ \code
+ QJniObject jobj = QJniObject::getStaticObjectField<jstring>("class/with/Fields", "FIELD_NAME");
+ \endcode
+*/
+
+/*!
+ \fn template<typename T> QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName)
+
+ Retrieves the object from the field \a fieldName on \a clazz.
+
+ \code
+ QJniObject jobj = QJniObject::getStaticObjectField<jstring>(clazz, "FIELD_NAME");
+ \endcode
+*/
+
+/*!
+ \fn QJniObject QJniObject::fromString(const QString &string)
+
+ Creates a Java string from the QString \a string and returns a QJniObject holding that string.
+
+ \code
+ QString myQString = "QString";
+ QJniObject myJavaString = QJniObject::fromString(myQString);
+ \endcode
+
+ \sa toString()
+*/
+QJniObject QJniObject::fromString(const QString &string)
+{
+ QJniEnvironment env;
+ jstring stringRef = env->NewString(reinterpret_cast<const jchar*>(string.constData()),
+ string.length());
+ QJniObject stringObject = getCleanJniObject(stringRef, env.jniEnv());
+ stringObject.d->m_className = "java/lang/String";
+ return stringObject;
+}
+
+/*!
+ \fn QString QJniObject::toString() const
+
+ Returns a QString with a string representation of the java object.
+ Calling this function on a Java String object is a convenient way of getting the actual string
+ data.
+
+ \code
+ QJniObject string = ...; // "Hello Java"
+ QString qstring = string.toString(); // "Hello Java"
+ \endcode
+
+ \sa fromString()
+*/
+QString QJniObject::toString() const
+{
+ if (!isValid())
+ return QString();
+
+ QJniObject string = callObjectMethod<jstring>("toString");
+ const int strLength = string.jniEnv()->GetStringLength(string.object<jstring>());
+ QString res(strLength, Qt::Uninitialized);
+ string.jniEnv()->GetStringRegion(string.object<jstring>(), 0, strLength, reinterpret_cast<jchar *>(res.data()));
+ return res;
+}
+
+/*!
+ \fn bool QJniObject::isClassAvailable(const char *className)
+
+ Returns true if the Java class \a className is available.
+
+ \code
+ if (QJniObject::isClassAvailable("java/lang/String")) {
+ // condition statement
+ }
+ \endcode
+*/
+bool QJniObject::isClassAvailable(const char *className)
+{
+ QJniEnvironment env;
+
+ if (!env.jniEnv())
+ return false;
+
+ return loadClass(className, env.jniEnv());
+}
+
+/*!
+ \fn bool QJniObject::isValid() const
+
+ Returns true if this instance holds a valid Java object.
+
+ \code
+ QJniObject qjniObject; // ==> isValid() == false
+ QJniObject qjniObject(0) // ==> isValid() == false
+ QJniObject qjniObject("could/not/find/Class") // ==> isValid() == false
+ \endcode
+*/
+bool QJniObject::isValid() const
+{
+ return d->m_jobject;
+}
+
+/*!
+ \fn QJniObject QJniObject::fromLocalRef(jobject localRef)
+
+ Creates a QJniObject from the local JNI reference \a localRef.
+ This function takes ownership of \a localRef and frees it before returning.
+
+ \note Only call this function with a local JNI reference. For example, most raw JNI calls,
+ through the JNI environment, return local references to a java object.
+
+ \code
+ jobject localRef = env->GetObjectArrayElement(array, index);
+ QJniObject element = QJniObject::fromLocalRef(localRef);
+ \endcode
+*/
+QJniObject QJniObject::fromLocalRef(jobject lref)
+{
+ QJniObject obj(lref);
+ obj.jniEnv()->DeleteLocalRef(lref);
+ return obj;
+}
+
+bool QJniObject::isSameObject(jobject obj) const
+{
+ if (d->m_jobject == obj)
+ return true;
+ if (!d->m_jobject || !obj)
+ return false;
+ return jniEnv()->IsSameObject(d->m_jobject, obj);
+}
+
+bool QJniObject::isSameObject(const QJniObject &other) const
+{
+ return isSameObject(other.d->m_jobject);
+}
+
+void QJniObject::assign(jobject obj)
+{
+ if (d && isSameObject(obj))
+ return;
+
+ d = QSharedPointer<QJniObjectPrivate>::create();
+ if (obj) {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ d->m_jobject = env->NewGlobalRef(obj);
+ jclass objectClass = env->GetObjectClass(obj);
+ d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
+ env->DeleteLocalRef(objectClass);
+ }
+}
+
+jobject QJniObject::javaObject() const
+{
+ return d->m_jobject;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h
new file mode 100644
index 0000000000..707d1ae28a
--- /dev/null
+++ b/src/corelib/kernel/qjniobject.h
@@ -0,0 +1,871 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QJNIOBJECT_H
+#define QJNIOBJECT_H
+
+#include <QtCore/qsharedpointer.h>
+
+#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
+#include <jni.h>
+#include <QtCore/qjnienvironment.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJniObjectPrivate;
+
+class Q_CORE_EXPORT QJniObject
+{
+ friend class QJniArrayBase;
+
+ template <typename ...Args>
+ struct LocalFrame {
+ mutable JNIEnv *env;
+ bool hasFrame = false;
+ explicit LocalFrame(JNIEnv *env = nullptr) noexcept
+ : env(env)
+ {
+ }
+ ~LocalFrame()
+ {
+ if (hasFrame)
+ env->PopLocalFrame(nullptr);
+ }
+ template <typename T>
+ auto newLocalRef(jobject object)
+ {
+ if (!hasFrame) {
+ if (jniEnv()->PushLocalFrame(sizeof...(Args)) < 0)
+ return T{}; // JVM is out of memory, avoid making matters worse
+ hasFrame = true;
+ }
+ return static_cast<T>(jniEnv()->NewLocalRef(object));
+ }
+ template <typename T>
+ auto newLocalRef(const QJniObject &object)
+ {
+ return newLocalRef<T>(object.template object<T>());
+ }
+ JNIEnv *jniEnv() const
+ {
+ if (!env)
+ env = QJniEnvironment::getJniEnv();
+ return env;
+ }
+ bool checkAndClearExceptions()
+ {
+ return env ? QJniEnvironment::checkAndClearExceptions(env) : false;
+ }
+ template <typename T>
+ auto convertToJni(T &&value);
+ template <typename T>
+ auto convertFromJni(QJniObject &&object);
+ };
+public:
+ QJniObject();
+ explicit QJniObject(const char *className);
+ explicit QJniObject(const char *className, const char *signature, ...);
+ template<typename ...Args
+#ifndef Q_QDOC
+ , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
+#endif
+ >
+ explicit QJniObject(const char *className, Args &&...args)
+ : QJniObject(LocalFrame<Args...>{}, className, std::forward<Args>(args)...)
+ {
+ }
+private:
+ template<typename ...Args>
+ explicit QJniObject(LocalFrame<Args...> localFrame, const char *className, Args &&...args)
+ : QJniObject(className, QtJniTypes::constructorSignature<Args...>().data(),
+ localFrame.convertToJni(std::forward<Args>(args))...)
+ {
+ }
+public:
+ explicit QJniObject(jclass clazz);
+ explicit QJniObject(jclass clazz, const char *signature, ...);
+ template<typename ...Args
+#ifndef Q_QDOC
+ , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
+#endif
+ >
+ explicit QJniObject(jclass clazz, Args &&...args)
+ : QJniObject(clazz, QtJniTypes::constructorSignature<Args...>().data(),
+ std::forward<Args>(args)...)
+ {}
+ QJniObject(jobject globalRef);
+
+ QJniObject(const QJniObject &other) noexcept = default;
+ QJniObject(QJniObject &&other) noexcept = default;
+ QJniObject &operator=(const QJniObject &other) noexcept = default;
+ QJniObject &operator=(QJniObject &&other) noexcept = default;
+
+ ~QJniObject();
+
+ template<typename Class, typename ...Args>
+ static inline QJniObject construct(Args &&...args)
+ {
+ LocalFrame<Args...> frame;
+ return QJniObject(QtJniTypes::Traits<Class>::className().data(),
+ QtJniTypes::constructorSignature<Args...>().data(),
+ frame.convertToJni(std::forward<Args>(args))...);
+ }
+
+ jobject object() const;
+ template <typename T> T object() const
+ {
+ QtJniTypes::assertObjectType<T>();
+ return static_cast<T>(javaObject());
+ }
+
+ jclass objectClass() const;
+ QByteArray className() const;
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<Ret> = true
+#endif
+ >
+ auto callMethod(const char *methodName, const char *signature, Args &&...args) const
+ {
+ LocalFrame<Args...> frame(jniEnv());
+ if constexpr (QtJniTypes::isObjectType<Ret>()) {
+ return frame.template convertFromJni<Ret>(callObjectMethod(methodName, signature,
+ frame.convertToJni(std::forward<Args>(args))...));
+ } else {
+ jmethodID id = getCachedMethodID(frame.jniEnv(), methodName, signature);
+ if (id) {
+ if constexpr (std::is_same_v<Ret, void>) {
+ callVoidMethodV(frame.jniEnv(), id,
+ frame.convertToJni(std::forward<Args>(args))...);
+ frame.checkAndClearExceptions();
+ } else {
+ Ret res{};
+ callMethodForType<Ret>(frame.jniEnv(), res, object(), id,
+ frame.convertToJni(std::forward<Args>(args))...);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ return res;
+ }
+ }
+ if constexpr (!std::is_same_v<Ret, void>)
+ return Ret{};
+ }
+ }
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ auto callMethod(const char *methodName, Args &&...args) const
+ {
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callMethod<Ret>(methodName, signature.data(), std::forward<Args>(args)...);
+ }
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ QJniObject callObjectMethod(const char *methodName, Args &&...args) const
+ {
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ LocalFrame<Args...> frame(jniEnv());
+ return frame.template convertFromJni<Ret>(callObjectMethod(methodName, signature,
+ frame.convertToJni(std::forward<Args>(args))...));
+ }
+
+ QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const;
+
+ template <typename Ret, typename ...Args>
+ static auto callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args)
+ {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+ return callStaticMethod<Ret>(clazz, methodName, signature, std::forward<Args>(args)...);
+ }
+
+ template <typename Ret, typename ...Args>
+ static auto callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args)
+ {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jmethodID id = clazz ? getMethodID(env, clazz, methodName, signature, true)
+ : 0;
+ return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
+ }
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<Ret> = true
+#endif
+ >
+ static auto callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args)
+ {
+ LocalFrame<Args...> frame;
+ if constexpr (QtJniTypes::isObjectType<Ret>()) {
+ return frame.template convertFromJni<Ret>(callStaticObjectMethod(clazz, methodId,
+ frame.convertToJni(std::forward<Args>(args))...));
+ } else {
+ if (clazz && methodId) {
+ if constexpr (std::is_same_v<Ret, void>) {
+ callStaticMethodForVoid(frame.jniEnv(), clazz, methodId,
+ frame.convertToJni(std::forward<Args>(args))...);
+ frame.checkAndClearExceptions();
+ } else {
+ Ret res{};
+ callStaticMethodForType<Ret>(frame.jniEnv(), res, clazz, methodId,
+ frame.convertToJni(std::forward<Args>(args))...);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ return res;
+ }
+ }
+ if constexpr (!std::is_same_v<Ret, void>)
+ return Ret{};
+ }
+ }
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(const char *className, const char *methodName, Args &&...args)
+ {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+ const jmethodID id = clazz ? getMethodID(env, clazz, methodName,
+ QtJniTypes::methodSignature<Ret, Args...>().data(), true)
+ : 0;
+ return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
+ }
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(jclass clazz, const char *methodName, Args &&...args)
+ {
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callStaticMethod<Ret>(clazz, methodName, signature.data(), std::forward<Args>(args)...);
+ }
+ template <typename Klass, typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(const char *methodName, Args &&...args)
+ {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ const jclass clazz = QJniObject::loadClass(QtJniTypes::Traits<Klass>::className().data(),
+ env);
+ const jmethodID id = clazz ? getMethodID(env, clazz, methodName,
+ QtJniTypes::methodSignature<Ret, Args...>().data(), true)
+ : 0;
+ return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
+ }
+
+ static QJniObject callStaticObjectMethod(const char *className, const char *methodName,
+ const char *signature, ...);
+
+ static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName,
+ const char *signature, ...);
+
+ static QJniObject callStaticObjectMethod(jclass clazz, jmethodID methodId, ...);
+
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static QJniObject callStaticObjectMethod(const char *className, const char *methodName, Args &&...args)
+ {
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ LocalFrame<Args...> frame;
+ return frame.template convertFromJni<Ret>(callStaticObjectMethod(className, methodName, signature.data(),
+ frame.convertToJni(std::forward<Args>(args))...));
+ }
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args)
+ {
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ LocalFrame<Args...> frame;
+ return frame.template convertFromJni<Ret>(callStaticObjectMethod(clazz, methodName, signature.data(),
+ frame.convertToJni(std::forward<Args>(args))...));
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ auto getField(const char *fieldName) const
+ {
+ LocalFrame<T> frame(jniEnv());
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ return frame.template convertFromJni<T>(getObjectField<T>(fieldName));
+ } else {
+ T res{};
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getCachedFieldID(frame.jniEnv(), fieldName, signature);
+ if (id) {
+ getFieldForType<T>(frame.jniEnv(), res, object(), id);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ }
+ return res;
+ }
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(const char *className, const char *fieldName)
+ {
+ LocalFrame<T> frame;
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ return frame.template convertFromJni<T>(getStaticObjectField<T>(className, fieldName));
+ } else {
+ jclass clazz = QJniObject::loadClass(className, frame.jniEnv());
+ if (!clazz)
+ return T{};
+ return getStaticField<T>(clazz, fieldName);
+ }
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(jclass clazz, const char *fieldName)
+ {
+ LocalFrame<T> frame;
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ return frame.template convertFromJni<T>(getStaticObjectField<T>(clazz, fieldName));
+ } else {
+ T res{};
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getFieldID(frame.jniEnv(), clazz, fieldName, signature, true);
+ if (id) {
+ getStaticFieldForType<T>(frame.jniEnv(), res, clazz, id);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ }
+ return res;
+ }
+ }
+
+ template <typename Klass, typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(const char *fieldName)
+ {
+ return getStaticField<T>(QtJniTypes::Traits<Klass>::className(), fieldName);
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
+#endif
+ >
+ QJniObject getObjectField(const char *fieldName) const
+ {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return getObjectField(fieldName, signature);
+ }
+
+ QJniObject getObjectField(const char *fieldName, const char *signature) const;
+
+ template <typename T
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
+#endif
+ >
+ static QJniObject getStaticObjectField(const char *className, const char *fieldName)
+ {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return getStaticObjectField(className, fieldName, signature);
+ }
+
+ static QJniObject getStaticObjectField(const char *className,
+ const char *fieldName,
+ const char *signature);
+
+ template <typename T
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
+#endif
+ >
+ static QJniObject getStaticObjectField(jclass clazz, const char *fieldName)
+ {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return getStaticObjectField(clazz, fieldName, signature);
+ }
+
+ static QJniObject getStaticObjectField(jclass clazz, const char *fieldName,
+ const char *signature);
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ void setField(const char *fieldName, T value)
+ {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
+ if (id) {
+ setFieldForType<T>(jniEnv(), object(), id, value);
+ QJniEnvironment::checkAndClearExceptions(jniEnv());
+ }
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ void setField(const char *fieldName, const char *signature, T value)
+ {
+ jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
+ if (id) {
+ setFieldForType<T>(jniEnv(), object(), id, value);
+ QJniEnvironment::checkAndClearExceptions(jniEnv());
+ }
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(const char *className, const char *fieldName, T value)
+ {
+ LocalFrame<T> frame;
+ jclass clazz = QJniObject::loadClass(className, frame.jniEnv());
+ if (!clazz)
+ return;
+
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getCachedFieldID(frame.jniEnv(), clazz, className, fieldName,
+ signature, true);
+ if (!id)
+ return;
+
+ setStaticFieldForType<T>(frame.jniEnv(), clazz, id, value);
+ frame.checkAndClearExceptions();
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(const char *className, const char *fieldName,
+ const char *signature, T value)
+ {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+
+ if (!clazz)
+ return;
+
+ jfieldID id = getCachedFieldID(env, clazz, className, fieldName,
+ signature, true);
+ if (id) {
+ setStaticFieldForType<T>(env, clazz, id, value);
+ QJniEnvironment::checkAndClearExceptions(env);
+ }
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(jclass clazz, const char *fieldName,
+ const char *signature, T value)
+ {
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jfieldID id = getFieldID(env, clazz, fieldName, signature, true);
+
+ if (id) {
+ setStaticFieldForType<T>(env, clazz, id, value);
+ QJniEnvironment::checkAndClearExceptions(env);
+ }
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(jclass clazz, const char *fieldName, T value)
+ {
+ setStaticField(clazz, fieldName, QtJniTypes::fieldSignature<T>(), value);
+ }
+
+ template <typename Klass, typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(const char *fieldName, T value)
+ {
+ setStaticField(QtJniTypes::Traits<Klass>::className(), fieldName, value);
+ }
+
+ static QJniObject fromString(const QString &string);
+ QString toString() const;
+
+ static bool isClassAvailable(const char *className);
+ bool isValid() const;
+
+ // This function takes ownership of the jobject and releases the local ref. before returning.
+ static QJniObject fromLocalRef(jobject lref);
+
+ template <typename T,
+ std::enable_if_t<std::is_convertible_v<T, jobject>, bool> = true>
+ QJniObject &operator=(T obj)
+ {
+ assign(static_cast<T>(obj));
+ return *this;
+ }
+
+protected:
+ QJniObject(Qt::Initialization) {}
+ JNIEnv *jniEnv() const noexcept;
+
+private:
+ static jclass loadClass(const QByteArray &className, JNIEnv *env);
+
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ // these need to stay in the ABI as they were used in inline methods before 6.7
+ static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded);
+ static QByteArray toBinaryEncClassName(const QByteArray &className);
+ void callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const;
+#endif
+
+ static jfieldID getCachedFieldID(JNIEnv *env, jclass clazz, const QByteArray &className,
+ const char *name, const char *signature,
+ bool isStatic = false);
+ jfieldID getCachedFieldID(JNIEnv *env, const char *name, const char *signature,
+ bool isStatic = false) const;
+ static jmethodID getCachedMethodID(JNIEnv *env, jclass clazz, const QByteArray &className,
+ const char *name, const char *signature,
+ bool isStatic = false);
+ jmethodID getCachedMethodID(JNIEnv *env, const char *name, const char *signature,
+ bool isStatic = false) const;
+
+ static jfieldID getFieldID(JNIEnv *env, jclass clazz, const char *name,
+ const char *signature, bool isStatic = false);
+ static jmethodID getMethodID(JNIEnv *env, jclass clazz, const char *name,
+ const char *signature, bool isStatic = false);
+
+ void callVoidMethodV(JNIEnv *env, jmethodID id, ...) const;
+
+ bool isSameObject(jobject obj) const;
+ bool isSameObject(const QJniObject &other) const;
+ void assign(jobject obj);
+ jobject javaObject() const;
+
+ friend bool operator==(const QJniObject &, const QJniObject &);
+ friend bool operator!=(const QJniObject&, const QJniObject&);
+
+ template<typename T>
+ static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, ...)
+ {
+ va_list args = {};
+ va_start(args, id);
+ QtJniTypes::Caller<T>::callMethodForType(env, res, obj, id, args);
+ va_end(args);
+ }
+
+ template<typename T>
+ static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz,
+ jmethodID id, ...)
+ {
+ if (!clazz || !id)
+ return;
+ va_list args = {};
+ va_start(args, id);
+ QtJniTypes::Caller<T>::callStaticMethodForType(env, res, clazz, id, args);
+ va_end(args);
+ }
+
+ static void callStaticMethodForVoid(JNIEnv *env, jclass clazz, jmethodID id, ...)
+ {
+ if (!clazz || !id)
+ return;
+ va_list args;
+ va_start(args, id);
+ env->CallStaticVoidMethodV(clazz, id, args);
+ va_end(args);
+ }
+
+
+ template<typename T>
+ static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj, jfieldID id)
+ {
+ QtJniTypes::Caller<T>::getFieldForType(env, res, obj, id);
+ }
+
+ template<typename T>
+ static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz, jfieldID id)
+ {
+ QtJniTypes::Caller<T>::getStaticFieldForType(env, res, clazz, id);
+ }
+
+ template<typename T>
+ static constexpr void setFieldForType(JNIEnv *env, jobject obj, jfieldID id, T value)
+ {
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ LocalFrame<T> frame(env);
+ env->SetObjectField(obj, id, static_cast<jobject>(frame.convertToJni(value)));
+ } else {
+ QtJniTypes::Caller<T>::setFieldForType(env, obj, id, value);
+ }
+ }
+
+ template<typename T>
+ static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz, jfieldID id, T value)
+ {
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ LocalFrame<T> frame(env);
+ env->SetStaticObjectField(clazz, id, static_cast<jobject>(frame.convertToJni(value)));
+ } else {
+ QtJniTypes::Caller<T>::setStaticFieldForType(env, clazz, id, value);
+ }
+ }
+
+ friend QJniObjectPrivate;
+ QSharedPointer<QJniObjectPrivate> d;
+};
+
+inline bool operator==(const QJniObject &obj1, const QJniObject &obj2)
+{
+ return obj1.isSameObject(obj2);
+}
+
+inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
+{
+ return !obj1.isSameObject(obj2);
+}
+
+namespace QtJniTypes {
+struct QT_TECH_PREVIEW_API JObjectBase
+{
+ operator QJniObject() const { return m_object; }
+
+ bool isValid() const { return m_object.isValid(); }
+ jclass objectClass() const { return m_object.objectClass(); }
+ QString toString() const { return m_object.toString(); }
+
+ template <typename T = jobject>
+ T object() const {
+ return m_object.object<T>();
+ }
+
+protected:
+ JObjectBase() = default;
+ ~JObjectBase() = default;
+
+ Q_IMPLICIT JObjectBase(jobject object) : m_object(object) {}
+ Q_IMPLICIT JObjectBase(const QJniObject &object) : m_object(object) {}
+ Q_IMPLICIT JObjectBase(QJniObject &&object) noexcept : m_object(std::move(object)) {}
+
+ QJniObject m_object;
+};
+
+template<typename Type>
+class QT_TECH_PREVIEW_API JObject : public JObjectBase
+{
+public:
+ using Class = Type;
+
+ JObject()
+ : JObjectBase{QJniObject(QtJniTypes::Traits<Class>::className())}
+ {}
+ Q_IMPLICIT JObject(jobject object) : JObjectBase(object) {}
+ Q_IMPLICIT JObject(const QJniObject &object) : JObjectBase(object) {}
+ Q_IMPLICIT JObject(QJniObject &&object) noexcept : JObjectBase(std::move(object)) {}
+
+ // base class destructor is protected, so need to provide all SMFs
+ JObject(const JObject &other) = default;
+ JObject(JObject &&other) noexcept = default;
+ JObject &operator=(const JObject &other) = default;
+ JObject &operator=(JObject &&other) noexcept = default;
+
+ ~JObject() = default;
+
+ template<typename Arg, typename ...Args
+ , std::enable_if_t<!std::is_same_v<Arg, JObject>, bool> = true
+ , IfValidSignatureTypes<Arg, Args...> = true
+ >
+ explicit JObject(Arg && arg, Args &&...args)
+ : JObjectBase{QJniObject(QtJniTypes::Traits<Class>::className(),
+ std::forward<Arg>(arg), std::forward<Args>(args)...)}
+ {}
+
+ // named constructors avoid ambiguities
+ static Type fromJObject(jobject object) { return Type(object); }
+ template <typename ...Args>
+ static Type construct(Args &&...args) { return Type(std::forward<Args>(args)...); }
+ static Type fromLocalRef(jobject lref) { return Type(QJniObject::fromLocalRef(lref)); }
+
+ static bool registerNativeMethods(std::initializer_list<JNINativeMethod> methods)
+ {
+ QJniEnvironment env;
+ return env.registerNativeMethods<Class>(methods);
+ }
+
+ // public API forwarding to QJniObject, with the implicit Class template parameter
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(const char *name, Args &&...args)
+ {
+ return QJniObject::callStaticMethod<Class, Ret, Args...>(name,
+ std::forward<Args>(args)...);
+ }
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(const char *field)
+ {
+ return QJniObject::getStaticField<Class, T>(field);
+ }
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(const char *field, T &&value)
+ {
+ QJniObject::setStaticField<Class, T>(field, std::forward<T>(value));
+ }
+
+ // keep only these overloads, the rest is made private
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ auto callMethod(const char *method, Args &&...args) const
+ {
+ return m_object.callMethod<Ret>(method, std::forward<Args>(args)...);
+ }
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ auto getField(const char *fieldName) const
+ {
+ return m_object.getField<T>(fieldName);
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ void setField(const char *fieldName, T &&value)
+ {
+ m_object.setField(fieldName, std::forward<T>(value));
+ }
+
+ QByteArray className() const {
+ return QtJniTypes::Traits<Class>::className().data();
+ }
+
+private:
+ friend bool comparesEqual(const JObject &lhs, const JObject &rhs) noexcept
+ { return lhs.m_object == rhs.m_object; }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(JObject);
+};
+}
+
+// This cannot be included earlier as QJniArray is a QJniObject subclass, but it
+// must be included so that we can implement QJniObject::LocalFrame conversion.
+QT_END_NAMESPACE
+#include <QtCore/qjniarray.h>
+QT_BEGIN_NAMESPACE
+
+template <typename ...Args>
+template <typename T>
+auto QJniObject::LocalFrame<Args...>::convertToJni(T &&value)
+{
+ using Type = q20::remove_cvref_t<T>;
+ if constexpr (std::is_same_v<Type, QString>) {
+ return newLocalRef<jstring>(QJniObject::fromString(value));
+ } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
+ return value.arrayObject();
+ } else if constexpr (QJniArrayBase::canConvert<T>) {
+ using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::forward<T>(value)));
+ using ArrayType = decltype(std::declval<QJniArrayType>().arrayObject());
+ return newLocalRef<ArrayType>(QJniArrayBase::fromContainer(std::forward<T>(value)).template object<jobject>());
+ } else if constexpr (std::is_base_of_v<QJniObject, Type>
+ || std::is_base_of_v<QtJniTypes::JObjectBase, Type>) {
+ return value.object();
+ } else {
+ return std::forward<T>(value);
+ }
+}
+
+template <typename ...Args>
+template <typename T>
+auto QJniObject::LocalFrame<Args...>::convertFromJni(QJniObject &&object)
+{
+ using Type = q20::remove_cvref_t<T>;
+ if constexpr (std::is_same_v<Type, QString>) {
+ return object.toString();
+ } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
+ return T(std::move(object));
+ } else if constexpr (QJniArrayBase::canConvert<Type>) {
+ // if we were to create a QJniArray from Type...
+ using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::declval<Type>()));
+ // then that QJniArray would have elements of type
+ using ElementType = typename QJniArrayType::Type;
+ // construct a QJniArray from a jobject pointer of that type
+ return QJniArray<ElementType>(object.template object<jarray>()).toContainer();
+ } else if constexpr (std::is_array_v<Type>) {
+ using ElementType = std::remove_extent_t<Type>;
+ return QJniArray<ElementType>(std::move(object));
+ } else if constexpr (std::is_base_of_v<QJniObject, Type>
+ && !std::is_same_v<QJniObject, Type>) {
+ return T{std::move(object)};
+ } else if constexpr (std::is_base_of_v<QtJniTypes::JObjectBase, Type>) {
+ return T{std::move(object)};
+ } else {
+ return std::move(object);
+ }
+}
+
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // QJNIOBJECT_H
diff --git a/src/corelib/kernel/qjnionload.cpp b/src/corelib/kernel/qjnionload.cpp
deleted file mode 100644
index 0550b86553..0000000000
--- a/src/corelib/kernel/qjnionload.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <jni.h>
-#include "qjnihelpers_p.h"
-#include <android/log.h>
-
-static const char logTag[] = "QtCore";
-
-
-Q_CORE_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
-{
- Q_UNUSED(reserved)
-
- static bool initialized = false;
- if (initialized)
- return JNI_VERSION_1_6;
- initialized = true;
-
- typedef union {
- JNIEnv *nenv;
- void *venv;
- } _JNIEnv;
-
- __android_log_print(ANDROID_LOG_INFO, logTag, "Start");
-
- _JNIEnv uenv;
- uenv.venv = nullptr;
-
- if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK)
- {
- __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed");
- return JNI_ERR;
- }
-
- JNIEnv *env = uenv.nenv;
- const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, env));
- if (ret != 0)
- {
- __android_log_print(ANDROID_LOG_FATAL, logTag, "initJNI failed");
- return ret;
- }
-
- return JNI_VERSION_1_6;
-}
diff --git a/src/corelib/kernel/qjnitypes.h b/src/corelib/kernel/qjnitypes.h
new file mode 100644
index 0000000000..e071a3f784
--- /dev/null
+++ b/src/corelib/kernel/qjnitypes.h
@@ -0,0 +1,223 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QJNITYPES_H
+#define QJNITYPES_H
+
+#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
+
+#include <QtCore/qjnitypes_impl.h>
+#include <QtCore/qjniobject.h>
+
+QT_BEGIN_NAMESPACE
+
+// QT_TECH_PREVIEW_API
+#define Q_DECLARE_JNI_TYPE_HELPER(Type) \
+namespace QtJniTypes { \
+struct Type : JObject<Type> \
+{ \
+ using JObject::JObject; \
+}; \
+} \
+
+// QT_TECH_PREVIEW_API
+#define Q_DECLARE_JNI_TYPE(Type, Signature) \
+Q_DECLARE_JNI_TYPE_HELPER(Type) \
+template<> \
+struct QtJniTypes::Traits<QtJniTypes::Type> { \
+ static constexpr auto signature() \
+ { \
+ static_assert((Signature[0] == 'L' \
+ || Signature[0] == '[') \
+ && Signature[sizeof(Signature) - 2] == ';', \
+ "Type signature needs to start with 'L' or" \
+ " '[' and end with ';'"); \
+ return QtJniTypes::CTString(Signature); \
+ } \
+}; \
+
+// QT_TECH_PREVIEW_API
+#define Q_DECLARE_JNI_CLASS(Type, Signature) \
+Q_DECLARE_JNI_TYPE_HELPER(Type) \
+template<> \
+struct QtJniTypes::Traits<QtJniTypes::Type> { \
+ static constexpr auto className() \
+ { \
+ return QtJniTypes::CTString(Signature); \
+ } \
+ static constexpr auto signature() \
+ { \
+ return QtJniTypes::CTString("L") \
+ + className() \
+ + QtJniTypes::CTString(";"); \
+ } \
+}; \
+
+// Macros for native methods
+
+namespace QtJniMethods {
+namespace Detail {
+// Various helpers to forward a call from a variadic argument function to
+// the real function with proper type conversion. This is needed because we
+// want to write functions that take QJniObjects (subclasses), while Java
+// can only call functions that take jobjects.
+
+// In Var-arg functions, any argument narrower than (unsigned) int or double
+// is promoted to (unsigned) int or double.
+template <typename Arg> struct PromotedType { using Type = Arg; };
+template <> struct PromotedType<bool> { using Type = int; };
+template <> struct PromotedType<char> { using Type = int; };
+template <> struct PromotedType<signed char> { using Type = int; };
+template <> struct PromotedType<unsigned char> { using Type = unsigned int; };
+template <> struct PromotedType<short> { using Type = int; };
+template <> struct PromotedType<unsigned short> { using Type = unsigned int; };
+template <> struct PromotedType<float> { using Type = double; };
+
+// Map any QJniObject type to jobject; that's what's on the va_list
+template <typename Arg>
+struct JNITypeForArgImpl
+{
+ using Type = std::conditional_t<std::disjunction_v<std::is_base_of<QJniObject, Arg>,
+ std::is_base_of<QtJniTypes::JObjectBase, Arg>>,
+ jobject, typename PromotedType<Arg>::Type>;
+ static Arg fromVarArg(Type t)
+ {
+ return static_cast<Arg>(t);
+ }
+};
+
+template <>
+struct JNITypeForArgImpl<QString>
+{
+ using Type = jstring;
+
+ static QString fromVarArg(Type t)
+ {
+ return QJniObject(t).toString();
+ }
+};
+
+template <typename T>
+struct JNITypeForArgImpl<QJniArray<T>>
+{
+ using Type = jobject;
+
+ static QJniArray<T> fromVarArg(Type t)
+ {
+ return QJniArray<T>(t);
+ }
+};
+
+template <typename T>
+struct JNITypeForArgImpl<QList<T>>
+{
+private:
+ using ArrayType = decltype(QJniArrayBase::fromContainer(std::declval<QList<T>>()));
+ using ArrayObjectType = decltype(std::declval<ArrayType>().arrayObject());
+ using ElementType = typename ArrayType::value_type;
+public:
+ using Type = ArrayObjectType;
+
+ static QList<T> fromVarArg(Type t)
+ {
+ return QJniArray<ElementType>(t).toContainer();
+ }
+};
+
+template <typename Arg>
+using JNITypeForArg = typename JNITypeForArgImpl<std::decay_t<Arg>>::Type;
+template <typename Arg, typename Type>
+static inline auto methodArgFromVarArg(Type t) // Type comes from a va_arg, so is always POD
+{
+ return JNITypeForArgImpl<std::decay_t<Arg>>::fromVarArg(t);
+}
+
+// Turn a va_list into a tuple of typed arguments
+template <typename ...Args>
+static constexpr auto makeTupleFromArgsHelper(va_list args)
+{
+ return std::tuple(methodArgFromVarArg<Args>(va_arg(args, JNITypeForArg<Args>))...);
+}
+
+template <typename Ret, typename ...Args>
+static constexpr auto makeTupleFromArgs(Ret (*)(JNIEnv *, jobject, Args...), va_list args)
+{
+ return makeTupleFromArgsHelper<Args...>(args);
+}
+template <typename Ret, typename ...Args>
+static constexpr auto makeTupleFromArgs(Ret (*)(JNIEnv *, jclass, Args...), va_list args)
+{
+ return makeTupleFromArgsHelper<Args...>(args);
+}
+
+// Get the return type of a function point
+template <typename Ret, typename ...Args>
+auto nativeFunctionReturnType(Ret(*function)(Args...))
+{
+ return function(std::declval<Args>()...);
+}
+
+} // namespace Detail
+} // namespace QtJniMethods
+
+// A va_ variadic arguments function that we register with JNI as a proxy
+// for the function we have. This function uses the helpers to unpack the
+// variadic arguments into a tuple of typed arguments, which we then call
+// the actual function with. This then takes care of implicit conversions,
+// e.g. a jobject becomes a QJniObject.
+#define Q_DECLARE_JNI_NATIVE_METHOD_HELPER(Method) \
+static decltype(QtJniMethods::Detail::nativeFunctionReturnType(Method)) \
+va_##Method(JNIEnv *env, jclass thiz, ...) \
+{ \
+ va_list args; \
+ va_start(args, thiz); \
+ auto va_cleanup = qScopeGuard([&args]{ va_end(args); }); \
+ auto argTuple = QtJniMethods::Detail::makeTupleFromArgs(Method, args); \
+ return std::apply([env, thiz](auto &&... args) { \
+ return Method(env, thiz, args...); \
+ }, argTuple); \
+} \
+
+// QT_TECH_PREVIEW_API
+#define Q_DECLARE_JNI_NATIVE_METHOD(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_JNI_NATIVE_METHOD, __VA_ARGS__) \
+
+#define QT_DECLARE_JNI_NATIVE_METHOD_2(Method, Name) \
+namespace QtJniMethods { \
+Q_DECLARE_JNI_NATIVE_METHOD_HELPER(Method) \
+static constexpr auto Method##_signature = \
+ QtJniTypes::nativeMethodSignature(Method); \
+static const JNINativeMethod Method##_method = { \
+ #Name, Method##_signature.data(), \
+ reinterpret_cast<void *>(va_##Method) \
+}; \
+} \
+
+#define QT_DECLARE_JNI_NATIVE_METHOD_1(Method) \
+ QT_DECLARE_JNI_NATIVE_METHOD_2(Method, Method) \
+
+// QT_TECH_PREVIEW_API
+#define Q_JNI_NATIVE_METHOD(Method) QtJniMethods::Method##_method
+
+// QT_TECH_PREVIEW_API
+#define Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE, __VA_ARGS__) \
+
+#define QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(Method, Name) \
+ Q_DECLARE_JNI_NATIVE_METHOD_HELPER(Method) \
+ static inline constexpr auto Method##_signature = QtJniTypes::nativeMethodSignature(Method); \
+ static inline const JNINativeMethod Method##_method = { \
+ #Name, Method##_signature.data(), reinterpret_cast<void *>(va_##Method) \
+ };
+
+#define QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_1(Method) \
+ QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(Method, Method) \
+
+// QT_TECH_PREVIEW_API
+#define Q_JNI_NATIVE_SCOPED_METHOD(Method, Scope) Scope::Method##_method
+
+QT_END_NAMESPACE
+
+#endif // defined(Q_QDOC) || defined(Q_OS_ANDROID)
+
+#endif // QJNITYPES_H
diff --git a/src/corelib/kernel/qjnitypes_impl.h b/src/corelib/kernel/qjnitypes_impl.h
new file mode 100644
index 0000000000..d963509023
--- /dev/null
+++ b/src/corelib/kernel/qjnitypes_impl.h
@@ -0,0 +1,373 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QJNITYPES_IMPL_H
+#define QJNITYPES_IMPL_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/q20type_traits.h>
+
+#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
+#include <jni.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtJniTypes
+{
+
+// a constexpr type for string literals of any character width, aware of the length
+// of the string.
+template<size_t N_WITH_NULL, typename BaseType = char>
+struct CTString
+{
+ BaseType m_data[N_WITH_NULL] = {};
+
+ constexpr CTString() noexcept {}
+ // Can be instantiated (only) with a string literal
+ constexpr explicit CTString(const BaseType (&data)[N_WITH_NULL]) noexcept
+ {
+ for (size_t i = 0; i < N_WITH_NULL - 1; ++i)
+ m_data[i] = data[i];
+ }
+
+ constexpr BaseType at(size_t i) const { return m_data[i]; }
+ constexpr BaseType operator[](size_t i) const { return at(i); }
+ static constexpr size_t size() noexcept { return N_WITH_NULL; }
+ constexpr operator const BaseType *() const noexcept { return m_data; }
+ constexpr const BaseType *data() const noexcept { return m_data; }
+ template<size_t N2_WITH_NULL>
+ constexpr bool startsWith(const BaseType (&lit)[N2_WITH_NULL]) const noexcept
+ {
+ if constexpr (N2_WITH_NULL > N_WITH_NULL) {
+ return false;
+ } else {
+ for (size_t i = 0; i < N2_WITH_NULL - 1; ++i) {
+ if (m_data[i] != lit[i])
+ return false;
+ }
+ }
+ return true;
+ }
+ constexpr bool startsWith(BaseType c) const noexcept
+ {
+ return N_WITH_NULL > 1 && m_data[0] == c;
+ }
+ template<size_t N2_WITH_NULL>
+ constexpr bool endsWith(const BaseType (&lit)[N2_WITH_NULL]) const noexcept
+ {
+ if constexpr (N2_WITH_NULL > N_WITH_NULL) {
+ return false;
+ } else {
+ for (size_t i = 0; i < N2_WITH_NULL; ++i) {
+ if (m_data[N_WITH_NULL - i - 1] != lit[N2_WITH_NULL - i - 1])
+ return false;
+ }
+ }
+ return true;
+ }
+ constexpr bool endsWith(BaseType c) const noexcept
+ {
+ return N_WITH_NULL > 1 && m_data[N_WITH_NULL - 2] == c;
+ }
+
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr bool operator==(const CTString<N_WITH_NULL> &lhs,
+ const CTString<N2_WITH_NULL> &rhs) noexcept
+ {
+ if constexpr (N_WITH_NULL != N2_WITH_NULL) {
+ return false;
+ } else {
+ for (size_t i = 0; i < N_WITH_NULL - 1; ++i) {
+ if (lhs.at(i) != rhs.at(i))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr bool operator!=(const CTString<N_WITH_NULL> &lhs,
+ const CTString<N2_WITH_NULL> &rhs) noexcept
+ {
+ return !operator==(lhs, rhs);
+ }
+
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr bool operator==(const CTString<N_WITH_NULL> &lhs,
+ const BaseType (&rhs)[N2_WITH_NULL]) noexcept
+ {
+ return operator==(lhs, CTString<N2_WITH_NULL>(rhs));
+ }
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr bool operator==(const BaseType (&lhs)[N2_WITH_NULL],
+ const CTString<N_WITH_NULL> &rhs) noexcept
+ {
+ return operator==(CTString<N2_WITH_NULL>(lhs), rhs);
+ }
+
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr bool operator!=(const CTString<N_WITH_NULL> &lhs,
+ const BaseType (&rhs)[N2_WITH_NULL]) noexcept
+ {
+ return operator!=(lhs, CTString<N2_WITH_NULL>(rhs));
+ }
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr bool operator!=(const BaseType (&lhs)[N2_WITH_NULL],
+ const CTString<N_WITH_NULL> &rhs) noexcept
+ {
+ return operator!=(CTString<N2_WITH_NULL>(lhs), rhs);
+ }
+
+ template<size_t N2_WITH_NULL>
+ friend inline constexpr auto operator+(const CTString<N_WITH_NULL> &lhs,
+ const CTString<N2_WITH_NULL> &rhs) noexcept
+ {
+ char data[N_WITH_NULL + N2_WITH_NULL - 1] = {};
+ for (size_t i = 0; i < N_WITH_NULL - 1; ++i)
+ data[i] = lhs[i];
+ for (size_t i = 0; i < N2_WITH_NULL - 1; ++i)
+ data[N_WITH_NULL - 1 + i] = rhs[i];
+ return CTString<N_WITH_NULL + N2_WITH_NULL - 1>(data);
+ }
+};
+
+// Helper types that allow us to disable variadic overloads that would conflict
+// with overloads that take a const char*.
+template<typename T, size_t N = 0> struct IsStringType : std::false_type {};
+template<> struct IsStringType<const char *, 0> : std::true_type {};
+template<> struct IsStringType<const char *&, 0> : std::true_type {};
+template<size_t N> struct IsStringType<CTString<N>> : std::true_type {};
+template<size_t N> struct IsStringType<const char[N]> : std::true_type {};
+template<size_t N> struct IsStringType<const char(&)[N]> : std::true_type {};
+template<size_t N> struct IsStringType<char[N]> : std::true_type {};
+
+template <typename T>
+struct Traits {
+ // The return type of className/signature becomes void for any type
+ // not handled here. This indicates that the Traits type is not specialized
+ // for the respective type, which we use to detect invalid types in the
+ // IfValidSignatureTypes and IfValidFieldType predicates below.
+
+ static constexpr auto className()
+ {
+ if constexpr (std::is_same_v<T, jstring>)
+ return CTString("java/lang/String");
+ else if constexpr (std::is_same_v<T, jobject>)
+ return CTString("java/lang/Object");
+ else if constexpr (std::is_same_v<T, jclass>)
+ return CTString("java/lang/Class");
+ else if constexpr (std::is_same_v<T, jthrowable>)
+ return CTString("java/lang/Throwable");
+ // else: return void -> not implemented
+ }
+
+ static constexpr auto signature()
+ {
+ if constexpr (!std::is_same_v<decltype(className()), void>) {
+ // the type signature of any object class is L<className>;
+ return CTString("L") + className() + CTString(";");
+ } else if constexpr (std::is_array_v<T>) {
+ using UnderlyingType = typename std::remove_extent_t<T>;
+ static_assert(!std::is_array_v<UnderlyingType>,
+ "Traits::signature() does not handle multi-dimensional arrays");
+ return CTString("[") + Traits<UnderlyingType>::signature();
+ } else if constexpr (std::is_same_v<T, jobjectArray>) {
+ return CTString("[Ljava/lang/Object;");
+ } else if constexpr (std::is_same_v<T, jbooleanArray>) {
+ return CTString("[Z");
+ } else if constexpr (std::is_same_v<T, jbyteArray>) {
+ return CTString("[B");
+ } else if constexpr (std::is_same_v<T, jshortArray>) {
+ return CTString("[S");
+ } else if constexpr (std::is_same_v<T, jintArray>) {
+ return CTString("[I");
+ } else if constexpr (std::is_same_v<T, jlongArray>) {
+ return CTString("[J");
+ } else if constexpr (std::is_same_v<T, jfloatArray>) {
+ return CTString("[F");
+ } else if constexpr (std::is_same_v<T, jdoubleArray>) {
+ return CTString("[D");
+ } else if constexpr (std::is_same_v<T, jcharArray>) {
+ return CTString("[C");
+ } else if constexpr (std::is_same_v<T, jboolean>) {
+ return CTString("Z");
+ } else if constexpr (std::is_same_v<T, bool>) {
+ return CTString("Z");
+ } else if constexpr (std::is_same_v<T, jbyte>) {
+ return CTString("B");
+ } else if constexpr (std::is_same_v<T, jchar>) {
+ return CTString("C");
+ } else if constexpr (std::is_same_v<T, char>) {
+ return CTString("C");
+ } else if constexpr (std::is_same_v<T, jshort>) {
+ return CTString("S");
+ } else if constexpr (std::is_same_v<T, short>) {
+ return CTString("S");
+ } else if constexpr (std::is_same_v<T, jint>) {
+ return CTString("I");
+ } else if constexpr (std::is_same_v<T, int>) {
+ return CTString("I");
+ } else if constexpr (std::is_same_v<T, uint>) {
+ return CTString("I");
+ } else if constexpr (std::is_same_v<T, jlong>) {
+ return CTString("J");
+ } else if constexpr (std::is_same_v<T, quint64>) {
+ return CTString("J");
+ } else if constexpr (std::is_same_v<T, jfloat>) {
+ return CTString("F");
+ } else if constexpr (std::is_same_v<T, float>) {
+ return CTString("F");
+ } else if constexpr (std::is_same_v<T, jdouble>) {
+ return CTString("D");
+ } else if constexpr (std::is_same_v<T, double>) {
+ return CTString("D");
+ } else if constexpr (std::is_same_v<T, void>) {
+ return CTString("V");
+ } else if constexpr (std::is_enum_v<T>) {
+ return Traits<std::underlying_type_t<T>>::signature();
+ } else if constexpr (std::is_same_v<T, QString>) {
+ return CTString("Ljava/lang/String;");
+ }
+ // else: return void -> not implemented
+ }
+};
+
+template <typename Have, typename Want>
+static constexpr bool sameTypeForJni = (QtJniTypes::Traits<Have>::signature()
+ == QtJniTypes::Traits<Want>::signature())
+ && (sizeof(Have) == sizeof(Want));
+
+template <typename, typename = void>
+struct Caller
+{};
+
+#define MAKE_CALLER(Type, Method) \
+template <typename T> \
+struct Caller<T, std::enable_if_t<sameTypeForJni<T, Type>>> \
+{ \
+ static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, va_list args) \
+ { \
+ res = T(env->Call##Method##MethodV(obj, id, args)); \
+ } \
+ static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz, jmethodID id, va_list args) \
+ { \
+ res = T(env->CallStatic##Method##MethodV(clazz, id, args)); \
+ } \
+ static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj, jfieldID id) \
+ { \
+ res = T(env->Get##Method##Field(obj, id)); \
+ } \
+ static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz, jfieldID id) \
+ { \
+ res = T(env->GetStatic##Method##Field(clazz, id)); \
+ } \
+ static constexpr void setFieldForType(JNIEnv *env, jobject obj, jfieldID id, T value) \
+ { \
+ env->Set##Method##Field(obj, id, static_cast<Type>(value)); \
+ } \
+ static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz, jfieldID id, T value) \
+ { \
+ env->SetStatic##Method##Field(clazz, id, static_cast<Type>(value)); \
+ } \
+}
+
+MAKE_CALLER(jboolean, Boolean);
+MAKE_CALLER(jbyte, Byte);
+MAKE_CALLER(jchar, Char);
+MAKE_CALLER(jshort, Short);
+MAKE_CALLER(jint, Int);
+MAKE_CALLER(jlong, Long);
+MAKE_CALLER(jfloat, Float);
+MAKE_CALLER(jdouble, Double);
+
+#undef MAKE_CALLER
+
+template<typename T>
+static constexpr bool isPrimitiveType()
+{
+ return Traits<T>::signature().size() == 2;
+}
+
+template<typename T>
+static constexpr bool isArrayType()
+{
+ constexpr auto signature = Traits<T>::signature();
+ return signature.startsWith('[') && signature.size() > 2;
+}
+
+template<typename T>
+static constexpr bool isObjectType()
+{
+ if constexpr (std::is_convertible_v<T, jobject>) {
+ return true;
+ } else {
+ constexpr auto signature = Traits<T>::signature();
+ return (signature.startsWith('L') && signature.endsWith(';')) || isArrayType<T>();
+ }
+}
+
+template<typename T>
+static constexpr void assertObjectType()
+{
+ static_assert(isObjectType<T>(),
+ "Type needs to be a JNI object type (convertible to jobject, or with "
+ "an object type signature registered)!");
+}
+
+// A set of types is valid if Traits::signature is implemented for all of them
+template<typename ...Types>
+constexpr bool ValidSignatureTypesDetail = !std::disjunction<std::is_same<
+ decltype(Traits<Types>::signature()),
+ void>...,
+ IsStringType<Types>...>::value;
+template<typename ...Types>
+using IfValidSignatureTypes = std::enable_if_t<
+ ValidSignatureTypesDetail<q20::remove_cvref_t<Types>...>, bool>;
+
+template<typename Type>
+constexpr bool ValidFieldTypeDetail = isObjectType<Type>() || isPrimitiveType<Type>();
+template<typename Type>
+using IfValidFieldType = std::enable_if_t<
+ ValidFieldTypeDetail<q20::remove_cvref_t<Type>>, bool>;
+
+
+template<typename R, typename ...Args, IfValidSignatureTypes<R, Args...> = true>
+static constexpr auto methodSignature()
+{
+ return (CTString("(") +
+ ... + Traits<q20::remove_cvref_t<Args>>::signature())
+ + CTString(")")
+ + Traits<R>::signature();
+}
+
+template<typename T, IfValidSignatureTypes<T> = true>
+static constexpr auto fieldSignature()
+{
+ return QtJniTypes::Traits<T>::signature();
+}
+
+template<typename ...Args, IfValidSignatureTypes<Args...> = true>
+static constexpr auto constructorSignature()
+{
+ return methodSignature<void, Args...>();
+}
+
+template<typename Ret, typename ...Args, IfValidSignatureTypes<Ret, Args...> = true>
+static constexpr auto nativeMethodSignature(Ret (*)(JNIEnv *, jobject, Args...))
+{
+ return methodSignature<Ret, Args...>();
+}
+
+template<typename Ret, typename ...Args, IfValidSignatureTypes<Ret, Args...> = true>
+static constexpr auto nativeMethodSignature(Ret (*)(JNIEnv *, jclass, Args...))
+{
+ return methodSignature<Ret, Args...>();
+}
+
+} // namespace QtJniTypes
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // QJNITYPES_IMPL_H
diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp
index 2778dc242d..8742a4bee5 100644
--- a/src/corelib/kernel/qmath.cpp
+++ b/src/corelib/kernel/qmath.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qmath.h>
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
index 57314901e8..72057ee16d 100644
--- a/src/corelib/kernel/qmath.h
+++ b/src/corelib/kernel/qmath.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMATH_H
#define QMATH_H
@@ -47,6 +11,10 @@
#include <QtCore/qglobal.h>
#include <QtCore/qalgorithms.h>
+#if __has_include(<bit>) && __cplusplus > 201703L
+#include <bit>
+#endif
+
#ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES
# define undef_USE_MATH_DEFINES
@@ -131,6 +99,72 @@ template <typename T> auto qSqrt(T v)
return sqrt(v);
}
+namespace QtPrivate {
+template <typename R, typename F> // For qfloat16 to specialize
+struct QHypotType { using type = decltype(std::hypot(R(1), F(1))); };
+
+// Implements hypot() without limiting number of arguments:
+template <typename T>
+class QHypotHelper
+{
+ T scale, total;
+ template <typename F> friend class QHypotHelper;
+ QHypotHelper(T first, T prior) : scale(first), total(prior) {}
+public:
+ QHypotHelper(T first) : scale(qAbs(first)), total(1) {}
+ T result() const
+ { return qIsFinite(scale) ? scale > 0 ? scale * T(qSqrt(total)) : T(0) : scale; }
+
+ template<typename F, typename ...Fs>
+ auto add(F first, Fs... rest) const
+ { return add(first).add(rest...); }
+
+ template<typename F, typename R = typename QHypotType<T, F>::type>
+ QHypotHelper<R> add(F next) const
+ {
+ if (qIsInf(scale) || (qIsNaN(scale) && !qIsInf(next)))
+ return QHypotHelper<R>(scale, R(1));
+ if (qIsNaN(next))
+ return QHypotHelper<R>(next, R(1));
+ const R val = qAbs(next);
+ if (!(scale > 0) || qIsInf(next))
+ return QHypotHelper<R>(val, R(1));
+ if (!(val > 0))
+ return QHypotHelper<R>(scale, total);
+ if (val > scale) {
+ const R ratio = scale / next;
+ return QHypotHelper<R>(val, total * ratio * ratio + R(1));
+ }
+ const R ratio = next / scale;
+ return QHypotHelper<R>(scale, total + ratio * ratio);
+ }
+};
+} // QtPrivate
+
+template<typename F, typename ...Fs>
+auto qHypot(F first, Fs... rest)
+{
+ return QtPrivate::QHypotHelper<F>(first).add(rest...).result();
+}
+
+// However, where possible, use the standard library implementations:
+template <typename Tx, typename Ty>
+auto qHypot(Tx x, Ty y)
+{
+ // C99 has hypot(), hence C++11 has std::hypot()
+ using std::hypot;
+ return hypot(x, y);
+}
+
+#if defined(__cpp_lib_hypot) && __cpp_lib_hypot >= 201603L // Expected to be true
+template <typename Tx, typename Ty, typename Tz>
+auto qHypot(Tx x, Ty y, Tz z)
+{
+ using std::hypot;
+ return hypot(x, y, z);
+}
+#endif // else: no need to over-ride the arbitrarily-many-arg form
+
template <typename T> auto qLn(T v)
{
using std::log;
@@ -223,28 +257,49 @@ inline qreal qFastCos(qreal x)
return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
}
-Q_DECL_CONSTEXPR inline float qDegreesToRadians(float degrees)
+constexpr inline float qDegreesToRadians(float degrees)
+{
+ return degrees * float(M_PI / 180);
+}
+
+constexpr inline double qDegreesToRadians(double degrees)
{
- return degrees * float(M_PI/180);
+ return degrees * (M_PI / 180);
}
-Q_DECL_CONSTEXPR inline double qDegreesToRadians(double degrees)
+constexpr inline long double qDegreesToRadians(long double degrees)
{
return degrees * (M_PI / 180);
}
-Q_DECL_CONSTEXPR inline float qRadiansToDegrees(float radians)
+template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
+constexpr inline double qDegreesToRadians(T degrees)
{
- return radians * float(180/M_PI);
+ return qDegreesToRadians(static_cast<double>(degrees));
}
-Q_DECL_CONSTEXPR inline double qRadiansToDegrees(double radians)
+constexpr inline float qRadiansToDegrees(float radians)
+{
+ return radians * float(180 / M_PI);
+}
+
+constexpr inline double qRadiansToDegrees(double radians)
{
return radians * (180 / M_PI);
}
+constexpr inline long double qRadiansToDegrees(long double radians)
+{
+ return radians * (180 / M_PI);
+}
+
+// A qRadiansToDegrees(Integral) overload isn't here; it's extremely
+// questionable that someone is manipulating quantities in radians
+// using integral datatypes...
+
namespace QtPrivate {
-constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v) {
+constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v)
+{
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
@@ -254,7 +309,8 @@ constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v) {
return v;
}
-constexpr inline quint64 qConstexprNextPowerOfTwo(quint64 v) {
+constexpr inline quint64 qConstexprNextPowerOfTwo(quint64 v)
+{
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
@@ -278,7 +334,10 @@ constexpr inline quint64 qConstexprNextPowerOfTwo(qint64 v)
constexpr inline quint32 qNextPowerOfTwo(quint32 v)
{
-#if defined(QT_HAS_BUILTIN_CLZ)
+ Q_ASSERT(static_cast<qint32>(v) >= 0); // There is a next power of two
+#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
+ return std::bit_ceil(v + 1);
+#elif defined(QT_HAS_BUILTIN_CLZ)
if (v == 0)
return 1;
return 2U << (31 ^ QAlgorithmsPrivate::qt_builtin_clz(v));
@@ -289,7 +348,10 @@ constexpr inline quint32 qNextPowerOfTwo(quint32 v)
constexpr inline quint64 qNextPowerOfTwo(quint64 v)
{
-#if defined(QT_HAS_BUILTIN_CLZLL)
+ Q_ASSERT(static_cast<qint64>(v) >= 0); // There is a next power of two
+#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
+ return std::bit_ceil(v + 1);
+#elif defined(QT_HAS_BUILTIN_CLZLL)
if (v == 0)
return 1;
return Q_UINT64_C(2) << (63 ^ QAlgorithmsPrivate::qt_builtin_clzll(v));
@@ -308,6 +370,16 @@ constexpr inline quint64 qNextPowerOfTwo(qint64 v)
return qNextPowerOfTwo(quint64(v));
}
+constexpr inline unsigned long qNextPowerOfTwo(unsigned long v)
+{
+ return qNextPowerOfTwo(QIntegerForSizeof<long>::Unsigned(v));
+}
+
+constexpr inline unsigned long qNextPowerOfTwo(long v)
+{
+ return qNextPowerOfTwo(QIntegerForSizeof<long>::Unsigned(v));
+}
+
QT_END_NAMESPACE
#endif // QMATH_H
diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc
index 82a4ae85a5..bc365f26fa 100644
--- a/src/corelib/kernel/qmath.qdoc
+++ b/src/corelib/kernel/qmath.qdoc
@@ -1,32 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\headerfile <QtMath>
+ \inmodule QtCore
\title Generic Math Functions
\ingroup funclists
@@ -54,8 +31,8 @@
*/
/*!
- \fn int qCeil(qreal v)
- Return the ceiling of the value \a v.
+ \fn template <typename T> int qCeil(T v)
+ Returns the ceiling of the value \a v.
The ceiling is the smallest integer that is not less than \a v.
For example, if \a v is 41.2, then the ceiling is 42.
@@ -65,8 +42,8 @@
*/
/*!
- \fn int qFloor(qreal v)
- Return the floor of the value \a v.
+ \fn template <typename T> int qFloor(T v)
+ Returns the floor of the value \a v.
The floor is the largest integer that is not greater than \a v.
For example, if \a v is 41.2, then the floor is 41.
@@ -139,7 +116,7 @@
This function will return the angle (argument) of that point.
\relates <QtMath>
- \sa qAtan()
+ \sa qAtan(), qHypot()
*/
/*!
@@ -148,7 +125,57 @@
This function returns a NaN if \a v is a negative number.
\relates <QtMath>
- \sa qPow()
+ \sa qPow(), qHypot()
+*/
+
+/*!
+ \since 6.1
+ \overload
+ \fn template <typename Tx, typename Ty> auto qHypot(Tx x, Ty y)
+ Returns the distance of a point (\a x, \a y) from the origin (0, 0).
+
+ This is qSqrt(x * x + y * y), optimized.
+ In particular, underflow and overflow may be avoided.
+
+ Accepts any mix of numeric types, returning the same
+ floating-point type as std::hypot(). If either parameter is
+ infinite, so is the result; otherwise, if either is a NaN, so is
+ the result.
+
+ \relates <QtMath>
+ \sa qSqrt(), qAtan2()
+*/
+
+/*!
+ \since 6.1
+ \overload
+ \fn template <typename Tx, typename Ty, typename Tz> auto qHypot(Tx x, Ty y, Tz z)
+ Returns the distance of a point (x, y, z) from the origin (0, 0, 0).
+
+ This is qSqrt(x * x + y * y + z * z), optimized where supported.
+ In particular, underflow and overflow may be avoided.
+
+ Accepts any mix of numeric types, returning the same
+ floating-point type as std::hypot(). If any parameter is infinite,
+ so is the result; otherwise, if any is NaN, so is the result.
+
+ \relates <QtMath>
+ \sa qSqrt()
+*/
+
+/*!
+ \since 6.1
+ \fn template<typename F, typename ...Fs> auto qHypot(F first, Fs... rest)
+ Returns the distance from origin in arbitrarily many dimensions
+
+ This is as for the two-argument and three-argument forms, supported by
+ std::hypot(), but with as many numeric parameters as you care to pass to
+ it. Uses \a first and each of the \a rest as coordinates, performing a
+ calculation equivalent to squaring each, summing and returning the square
+ root, save that underflow and overflow are avoided as far as possible.
+
+ \relates <QtMath>
+ \sa qSqrt()
*/
/*!
@@ -205,6 +232,30 @@
*/
/*!
+ \fn long double qDegreesToRadians(long double degrees)
+ \relates <QtMath>
+ \since 6.0
+
+ This function converts the \a degrees in double to radians.
+
+ \sa qRadiansToDegrees()
+*/
+
+/*!
+ \fn template <typename Integral> double qDegreesToRadians(Integral degrees)
+ \relates <QtMath>
+ \since 6.0
+
+ This function converts the \a degrees in double to radians;
+ the angle is casted to a double before the conversion.
+
+ This function participates in overload resolution if and only if
+ \c Integral is an integral type.
+
+ \sa qRadiansToDegrees()
+*/
+
+/*!
\fn float qRadiansToDegrees(float radians)
\relates <QtMath>
\since 5.1
@@ -233,11 +284,21 @@
*/
/*!
+ \fn long double qRadiansToDegrees(long double radians)
+ \relates <QtMath>
+ \since 6.0
+
+ This function converts the \a radians in double to degrees.
+
+ \sa qDegreesToRadians()
+*/
+
+/*!
\fn quint32 qNextPowerOfTwo(quint32 value)
\relates <QtMath>
\since 5.4
- This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^31 it returns 0.
+ This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^31 the result is undefined.
*/
/*!
@@ -246,7 +307,7 @@
\since 5.4
\overload
- This function returns the nearest power of two greater than \a value. For negative values it returns 0.
+ This function returns the nearest power of two greater than \a value. For negative values the result is undefined.
*/
/*!
@@ -254,7 +315,7 @@
\relates <QtMath>
\since 5.4
- This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^63 it returns 0.
+ This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^63 the result is undefined.
*/
/*!
@@ -263,5 +324,5 @@
\since 5.4
\overload
- This function returns the nearest power of two greater than \a value. For negative values it returns 0.
+ This function returns the nearest power of two greater than \a value. For negative values the result is undefined.
*/
diff --git a/src/corelib/kernel/qmetacontainer.cpp b/src/corelib/kernel/qmetacontainer.cpp
new file mode 100644
index 0000000000..5f68f8fe74
--- /dev/null
+++ b/src/corelib/kernel/qmetacontainer.cpp
@@ -0,0 +1,831 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qmetacontainer.h"
+#include "qmetatype.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMetaSequence
+ \inmodule QtCore
+ \since 6.0
+ \brief The QMetaSequence class allows type erased access to sequential containers.
+
+ \ingroup objectmodel
+
+ \compares equality
+
+ The class provides a number of primitive container operations, using void*
+ as operands. This way, you can manipulate a generic container retrieved from
+ a Variant without knowing its type.
+
+ The void* arguments to the various methods are typically created by using
+ a \l QVariant of the respective container or value type, and calling
+ its \l QVariant::data() or \l QVariant::constData() methods. However, you
+ can also pass plain pointers to objects of the container or value type.
+
+ Iterator invalidation follows the rules given by the underlying containers
+ and is not expressed in the API. Therefore, for a truly generic container,
+ any iterators should be considered invalid after any write operation.
+*/
+
+/*!
+ \fn template<typename C> QMetaSequence QMetaSequence::fromContainer()
+ \since 6.0
+
+ Returns the QMetaSequence corresponding to the type given as template parameter.
+*/
+
+/*!
+ Returns \c true if the underlying container provides at least an input
+ iterator as defined by std::input_iterator_tag, otherwise returns
+ \c false. Forward, Bi-directional, and random access iterators are
+ specializations of input iterators. This method will also return
+ \c true if the container provides one of those.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasInputIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::InputCapability);
+}
+
+/*!
+ Returns \c true if the underlying container provides at least a forward
+ iterator as defined by std::forward_iterator_tag, otherwise returns
+ \c false. Bi-directional iterators and random access iterators are
+ specializations of forward iterators. This method will also return
+ \c true if the container provides one of those.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasForwardIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::ForwardCapability);
+}
+
+/*!
+ Returns \c true if the underlying container provides a bi-directional
+ iterator or a random access iterator as defined by
+ std::bidirectional_iterator_tag and std::random_access_iterator_tag,
+ respectively. Otherwise returns \c false.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasBidirectionalIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::BiDirectionalCapability);
+}
+
+/*!
+ Returns \c true if the underlying container provides a random access
+ iterator as defined by std::random_access_iterator_tag, otherwise returns
+ \c false.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasRandomAccessIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::RandomAccessCapability);
+}
+
+/*!
+ Returns the meta type for values stored in the container.
+ */
+QMetaType QMetaSequence::valueMetaType() const
+{
+ if (auto iface = d())
+ return QMetaType(iface->valueMetaType);
+ return QMetaType();
+}
+
+/*!
+ Returns \c true if the underlying container is sortable, otherwise returns
+ \c false. A container is considered sortable if values added to it are
+ placed in a defined location. Inserting into or adding to a sortable
+ container will always succeed. Inserting into or adding to an unsortable
+ container may not succeed, for example if the container is a QSet that
+ already contains the value being inserted.
+
+ \sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
+ canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
+ */
+bool QMetaSequence::isSortable() const
+{
+ if (auto iface = d()) {
+ return (iface->addRemoveCapabilities
+ & (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
+ && (iface->addRemoveCapabilities
+ & (QtMetaContainerPrivate::CanRemoveAtBegin
+ | QtMetaContainerPrivate::CanRemoveAtEnd));
+ }
+ return false;
+}
+
+/*!
+ Returns \c true if values added using \l addValue() can be placed at the
+ beginning of the container, otherwise returns \c false.
+
+ \sa addValueAtBegin(), canAddValueAtEnd()
+ */
+bool QMetaSequence::canAddValueAtBegin() const
+{
+ if (auto iface = d()) {
+ return iface->addValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
+ }
+ return false;
+}
+
+/*!
+ Adds \a value to the beginning of \a container if possible. If
+ \l canAddValueAtBegin() returns \c false, the \a value is not added.
+
+ \sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
+ */
+void QMetaSequence::addValueAtBegin(void *container, const void *value) const
+{
+ if (canAddValueAtBegin())
+ d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+}
+
+/*!
+ Returns \c true if values can be removed from the beginning of the container
+ using \l removeValue() can be placed at the, otherwise returns \c false.
+
+ \sa removeValueAtBegin(), canRemoveValueAtEnd()
+ */
+bool QMetaSequence::canRemoveValueAtBegin() const
+{
+ if (auto iface = d()) {
+ return iface->removeValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
+ }
+ return false;
+}
+
+/*!
+ Removes a value from the beginning of \a container if possible. If
+ \l canRemoveValueAtBegin() returns \c false, the value is not removed.
+
+ \sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
+ */
+void QMetaSequence::removeValueAtBegin(void *container) const
+{
+ if (canRemoveValueAtBegin())
+ d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+}
+
+/*!
+ Returns \c true if values added using \l addValue() can be placed at the
+ end of the container, otherwise returns \c false.
+
+ \sa addValueAtEnd(), canAddValueAtBegin()
+ */
+bool QMetaSequence::canAddValueAtEnd() const
+{
+ if (auto iface = d()) {
+ return iface->addValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
+ }
+ return false;
+}
+
+/*!
+ Adds \a value to the end of \a container if possible. If
+ \l canAddValueAtEnd() returns \c false, the \a value is not added.
+
+ \sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
+ */
+void QMetaSequence::addValueAtEnd(void *container, const void *value) const
+{
+ if (canAddValueAtEnd())
+ d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+}
+
+/*!
+ Returns \c true if values can be removed from the end of the container
+ using \l removeValue() can be placed at the, otherwise returns \c false.
+
+ \sa removeValueAtEnd(), canRemoveValueAtBegin()
+ */
+bool QMetaSequence::canRemoveValueAtEnd() const
+{
+ if (auto iface = d()) {
+ return iface->removeValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
+ }
+ return false;
+}
+
+/*!
+ Removes a value from the end of \a container if possible. If
+ \l canRemoveValueAtEnd() returns \c false, the value is not removed.
+
+ \sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
+ */
+void QMetaSequence::removeValueAtEnd(void *container) const
+{
+ if (canRemoveValueAtEnd())
+ d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+}
+
+/*!
+ Returns \c true if the container can be queried for its size, \c false
+ otherwise.
+
+ \sa size()
+ */
+bool QMetaContainer::hasSize() const
+{
+ return d_ptr && d_ptr->sizeFn;
+}
+
+/*!
+ Returns the number of values in the given \a container if it can be
+ queried for its size. Otherwise returns \c -1.
+
+ \sa hasSize()
+ */
+qsizetype QMetaContainer::size(const void *container) const
+{
+ return hasSize() ? d_ptr->sizeFn(container) : -1;
+}
+
+/*!
+ Returns \c true if the container can be cleared, \c false otherwise.
+
+ \sa clear()
+ */
+bool QMetaContainer::canClear() const
+{
+ return d_ptr && d_ptr->clearFn;
+}
+
+/*!
+ Clears the given \a container if it can be cleared.
+
+ \sa canClear()
+ */
+void QMetaContainer::clear(void *container) const
+{
+ if (canClear())
+ d_ptr->clearFn(container);
+}
+
+/*!
+ Returns \c true if values can be retrieved from the container by index,
+ otherwise \c false.
+
+ \sa valueAtIndex()
+ */
+bool QMetaSequence::canGetValueAtIndex() const
+{
+ if (auto iface = d())
+ return iface->valueAtIndexFn;
+ return false;
+}
+
+/*!
+ Retrieves the value at \a index in the \a container and places it in the
+ memory location pointed to by \a result, if that is possible.
+
+ \sa canGetValueAtIndex()
+ */
+void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *result) const
+{
+ if (canGetValueAtIndex())
+ d()->valueAtIndexFn(container, index, result);
+}
+
+/*!
+ Returns \c true if an value can be written to the container by index,
+ otherwise \c false.
+
+ \sa setValueAtIndex()
+*/
+bool QMetaSequence::canSetValueAtIndex() const
+{
+ if (auto iface = d())
+ return iface->setValueAtIndexFn;
+ return false;
+}
+
+/*!
+ Overwrites the value at \a index in the \a container using the \a value
+ passed as parameter if that is possible.
+
+ \sa canSetValueAtIndex()
+ */
+void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void *value) const
+{
+ if (canSetValueAtIndex())
+ d()->setValueAtIndexFn(container, index, value);
+}
+
+/*!
+ Returns \c true if values can be added to the container, \c false
+ otherwise.
+
+ \sa addValue(), isSortable()
+ */
+bool QMetaSequence::canAddValue() const
+{
+ if (auto iface = d())
+ return iface->addValueFn;
+ return false;
+}
+
+/*!
+ Adds \a value to the \a container if possible. If \l canAddValue()
+ returns \c false, the \a value is not added. Else, if
+ \l canAddValueAtEnd() returns \c true, the \a value is added
+ to the end of the \a container. Else, if
+ \l canAddValueAtBegin() returns \c true, the \a value is added to
+ the beginning of the container. Else, the value is added in an unspecified
+ place or not at all. The latter is the case for adding values to an
+ unordered container, for example \l QSet.
+
+ \sa canAddValue(), canAddValueAtBegin(),
+ canAddValueAtEnd(), isSortable(), removeValue()
+ */
+void QMetaSequence::addValue(void *container, const void *value) const
+{
+ if (canAddValue()) {
+ d()->addValueFn(container, value,
+ QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
+ }
+}
+
+/*!
+ Returns \c true if values can be removed from the container, \c false
+ otherwise.
+
+ \sa removeValue(), isSortable()
+ */
+bool QMetaSequence::canRemoveValue() const
+{
+ if (auto iface = d())
+ return iface->removeValueFn;
+ return false;
+}
+
+/*!
+ Removes an value from the \a container if possible. If
+ \l canRemoveValue() returns \c false, no value is removed. Else, if
+ \l canRemoveValueAtEnd() returns \c true, the last value in
+ the \a container is removed. Else, if \l canRemoveValueAtBegin()
+ returns \c true, the first value in the \a container is removed. Else,
+ an unspecified value or nothing is removed.
+
+ \sa canRemoveValue(), canRemoveValueAtBegin(),
+ canRemoveValueAtEnd(), isSortable(), addValue()
+ */
+void QMetaSequence::removeValue(void *container) const
+{
+ if (canRemoveValue()) {
+ d()->removeValueFn(container,
+ QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
+ }
+}
+
+/*!
+ Returns \c true if the underlying container offers a non-const iterator,
+ \c false otherwise.
+
+ \sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
+ advanceIterator(), copyIterator()
+ */
+bool QMetaContainer::hasIterator() const
+{
+ if (!d_ptr || !d_ptr->createIteratorFn)
+ return false;
+ Q_ASSERT(d_ptr->destroyIteratorFn);
+ Q_ASSERT(d_ptr->compareIteratorFn);
+ Q_ASSERT(d_ptr->copyIteratorFn);
+ Q_ASSERT(d_ptr->advanceIteratorFn);
+ Q_ASSERT(d_ptr->diffIteratorFn);
+ return true;
+}
+
+/*!
+ Creates and returns a non-const iterator pointing to the beginning of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any non-const iterators.
+
+ \sa end(), constBegin(), constEnd(), destroyIterator()
+ */
+void *QMetaContainer::begin(void *container) const
+{
+ return hasIterator()
+ ? d_ptr->createIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
+ : nullptr;
+}
+
+/*!
+ Creates and returns a non-const iterator pointing to the end of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any non-const iterators.
+
+ \sa hasIterator(), end(), constBegin(), constEnd(), destroyIterator()
+ */
+void *QMetaContainer::end(void *container) const
+{
+ return hasIterator()
+ ? d_ptr->createIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
+ : nullptr;
+}
+
+/*!
+ Destroys a non-const \a iterator previously created using \l begin() or
+ \l end().
+
+ \sa begin(), end(), destroyConstIterator()
+ */
+void QMetaContainer::destroyIterator(const void *iterator) const
+{
+ if (hasIterator())
+ d_ptr->destroyIteratorFn(iterator);
+}
+
+/*!
+ Returns \c true if the non-const iterators \a i and \a j point to the same
+ value in the container they are iterating over, otherwise returns \c
+ false.
+
+ \sa begin(), end()
+ */
+bool QMetaContainer::compareIterator(const void *i, const void *j) const
+{
+ return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
+}
+
+/*!
+ Copies the non-const iterator \a source into the non-const iterator
+ \a target. Afterwards compareIterator(target, source) returns \c true.
+
+ \sa begin(), end()
+ */
+void QMetaContainer::copyIterator(void *target, const void *source) const
+{
+ if (hasIterator())
+ d_ptr->copyIteratorFn(target, source);
+}
+
+/*!
+ Advances the non-const \a iterator by \a step steps. If \a steps is negative
+ the \a iterator is moved backwards, towards the beginning of the container.
+ The behavior is unspecified for negative values of \a step if
+ \l hasBidirectionalIterator() returns false.
+
+ \sa begin(), end()
+ */
+void QMetaContainer::advanceIterator(void *iterator, qsizetype step) const
+{
+ if (hasIterator())
+ d_ptr->advanceIteratorFn(iterator, step);
+}
+
+/*!
+ Returns the distance between the non-const iterators \a i and \a j, the
+ equivalent of \a i \c - \a j. If \a j is closer to the end of the container
+ than \a i, the returned value is negative. The behavior is unspecified in
+ this case if \l hasBidirectionalIterator() returns false.
+
+ \sa begin(), end()
+ */
+qsizetype QMetaContainer::diffIterator(const void *i, const void *j) const
+{
+ return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
+}
+
+/*!
+ Returns \c true if the underlying container can retrieve the value pointed
+ to by a non-const iterator, \c false otherwise.
+
+ \sa hasIterator(), valueAtIterator()
+ */
+bool QMetaSequence::canGetValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->valueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Retrieves the value pointed to by the non-const \a iterator and stores it
+ in the memory location pointed to by \a result, if possible.
+
+ \sa canGetValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
+{
+ if (canGetValueAtIterator())
+ d()->valueAtIteratorFn(iterator, result);
+}
+
+/*!
+ Returns \c true if the underlying container can write to the value pointed
+ to by a non-const iterator, \c false otherwise.
+
+ \sa hasIterator(), setValueAtIterator()
+ */
+bool QMetaSequence::canSetValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->setValueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Writes \a value to the value pointed to by the non-const \a iterator, if
+ possible.
+
+ \sa canSetValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::setValueAtIterator(const void *iterator, const void *value) const
+{
+ if (canSetValueAtIterator())
+ d()->setValueAtIteratorFn(iterator, value);
+}
+
+/*!
+ Returns \c true if the underlying container can insert a new value, taking
+ the location pointed to by a non-const iterator into account.
+
+ \sa hasIterator(), insertValueAtIterator()
+ */
+bool QMetaSequence::canInsertValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->insertValueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Inserts \a value into the \a container, if possible, taking the non-const
+ \a iterator into account. If \l canInsertValueAtIterator() returns
+ \c false, the \a value is not inserted. Else if \l isSortable() returns
+ \c true, the value is inserted before the value pointed to by
+ \a iterator. Else, the \a value is inserted at an unspecified place or not
+ at all. In the latter case, the \a iterator is taken as a hint. If it points
+ to the correct place for the \a value, the operation may be faster than a
+ \l addValue() without iterator.
+
+ \sa canInsertValueAtIterator(), isSortable(), begin(), end()
+ */
+void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
+ const void *value) const
+{
+ if (canInsertValueAtIterator())
+ d()->insertValueAtIteratorFn(container, iterator, value);
+}
+
+/*!
+ Returns \c true if the value pointed to by a non-const iterator can be
+ erased, \c false otherwise.
+
+ \sa hasIterator(), eraseValueAtIterator()
+ */
+bool QMetaSequence::canEraseValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->eraseValueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Erases the value pointed to by the non-const \a iterator from the
+ \a container, if possible.
+
+ \sa canEraseValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator) const
+{
+ if (canEraseValueAtIterator())
+ d()->eraseValueAtIteratorFn(container, iterator);
+}
+
+/*!
+ Returns \c true if a range between two iterators can be erased from the
+ container, \c false otherwise.
+ */
+bool QMetaSequence::canEraseRangeAtIterator() const
+{
+ if (auto iface = d())
+ return iface->eraseRangeAtIteratorFn;
+ return false;
+}
+
+/*!
+ Erases the range of values between the iterators \a iterator1 and
+ \a iterator2 from the \a container, if possible.
+
+ \sa canEraseValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
+ const void *iterator2) const
+{
+ if (canEraseRangeAtIterator())
+ d()->eraseRangeAtIteratorFn(container, iterator1, iterator2);
+}
+
+/*!
+ Returns \c true if the underlying container offers a const iterator,
+ \c false otherwise.
+
+ \sa constBegin(), constEnd(), destroyConstIterator(),
+ compareConstIterator(), diffConstIterator(), advanceConstIterator(),
+ copyConstIterator()
+ */
+bool QMetaContainer::hasConstIterator() const
+{
+ if (!d_ptr || !d_ptr->createConstIteratorFn)
+ return false;
+ Q_ASSERT(d_ptr->destroyConstIteratorFn);
+ Q_ASSERT(d_ptr->compareConstIteratorFn);
+ Q_ASSERT(d_ptr->copyConstIteratorFn);
+ Q_ASSERT(d_ptr->advanceConstIteratorFn);
+ Q_ASSERT(d_ptr->diffConstIteratorFn);
+ return true;
+}
+
+/*!
+ Creates and returns a const iterator pointing to the beginning of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyConstIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any const iterators.
+
+ \sa constEnd(), begin(), end(), destroyConstIterator()
+ */
+void *QMetaContainer::constBegin(const void *container) const
+{
+ return hasConstIterator()
+ ? d_ptr->createConstIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
+ : nullptr;
+}
+
+/*!
+ Creates and returns a const iterator pointing to the end of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyConstIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any const iterators.
+
+ \sa constBegin(), begin(), end(), destroyConstIterator()
+ */
+void *QMetaContainer::constEnd(const void *container) const
+{
+ return hasConstIterator()
+ ? d_ptr->createConstIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
+ : nullptr;
+}
+
+/*!
+ Destroys a const \a iterator previously created using \l constBegin() or
+ \l constEnd().
+
+ \sa constBegin(), constEnd(), destroyIterator()
+ */
+void QMetaContainer::destroyConstIterator(const void *iterator) const
+{
+ if (hasConstIterator())
+ d_ptr->destroyConstIteratorFn(iterator);
+}
+
+/*!
+ Returns \c true if the const iterators \a i and \a j point to the same
+ value in the container they are iterating over, otherwise returns \c
+ false.
+
+ \sa constBegin(), constEnd()
+ */
+bool QMetaContainer::compareConstIterator(const void *i, const void *j) const
+{
+ return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
+}
+
+/*!
+ Copies the const iterator \a source into the const iterator
+ \a target. Afterwards compareConstIterator(target, source) returns \c true.
+
+ \sa constBegin(), constEnd()
+ */
+void QMetaContainer::copyConstIterator(void *target, const void *source) const
+{
+ if (hasConstIterator())
+ d_ptr->copyConstIteratorFn(target, source);
+}
+
+/*!
+ Advances the const \a iterator by \a step steps. If \a steps is negative
+ the \a iterator is moved backwards, towards the beginning of the container.
+ The behavior is unspecified for negative values of \a step if
+ \l hasBidirectionalIterator() returns false.
+
+ \sa constBegin(), constEnd()
+ */
+void QMetaContainer::advanceConstIterator(void *iterator, qsizetype step) const
+{
+ if (hasConstIterator())
+ d_ptr->advanceConstIteratorFn(iterator, step);
+}
+
+/*!
+ Returns the distance between the const iterators \a i and \a j, the
+ equivalent of \a i \c - \a j. If \a j is closer to the end of the container
+ than \a i, the returned value is negative. The behavior is unspecified in
+ this case if \l hasBidirectionalIterator() returns false.
+
+ \sa constBegin(), constEnd()
+ */
+qsizetype QMetaContainer::diffConstIterator(const void *i, const void *j) const
+{
+ return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
+}
+
+/*!
+ Returns \c true if the underlying container can retrieve the value pointed
+ to by a const iterator, \c false otherwise.
+
+ \sa hasConstIterator(), valueAtConstIterator()
+ */
+bool QMetaSequence::canGetValueAtConstIterator() const
+{
+ if (auto iface = d())
+ return iface->valueAtConstIteratorFn;
+ return false;
+}
+
+/*!
+ Retrieves the value pointed to by the const \a iterator and stores it
+ in the memory location pointed to by \a result, if possible.
+
+ \sa canGetValueAtConstIterator(), constBegin(), constEnd()
+ */
+void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) const
+{
+ if (canGetValueAtConstIterator())
+ d()->valueAtConstIteratorFn(iterator, result);
+}
+
+/*!
+ \fn bool QMetaSequence::operator==(const QMetaSequence &lhs, const QMetaSequence &rhs)
+ \since 6.0
+
+ Returns \c true if the QMetaSequence \a lhs represents the same container type
+ as the QMetaSequence \a rhs, otherwise returns \c false.
+*/
+
+/*!
+ \fn bool QMetaSequence::operator!=(const QMetaSequence &lhs, const QMetaSequence &rhs)
+ \since 6.0
+
+ Returns \c true if the QMetaSequence \a lhs represents a different container
+ type than the QMetaSequence \a rhs, otherwise returns \c false.
+*/
+
+
+/*!
+ Returns the meta type for keys in the container.
+ */
+QMetaType QMetaAssociation::keyMetaType() const
+{
+ if (auto iface = d())
+ return QMetaType(iface->keyMetaType);
+ return QMetaType();
+}
+
+/*!
+ Returns the meta type for mapped values in the container.
+ */
+QMetaType QMetaAssociation::mappedMetaType() const
+{
+ if (auto iface = d())
+ return QMetaType(iface->mappedMetaType);
+ return QMetaType();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h
new file mode 100644
index 0000000000..1bed7f9f7b
--- /dev/null
+++ b/src/corelib/kernel/qmetacontainer.h
@@ -0,0 +1,1197 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMETACONTAINER_H
+#define QMETACONTAINER_H
+
+#include <QtCore/qcontainerinfo.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qflags.h>
+#include <QtCore/qglobal.h>
+
+#include <iterator>
+
+QT_BEGIN_NAMESPACE
+
+class QMetaType;
+namespace QtPrivate {
+class QMetaTypeInterface;
+template<typename T>
+constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
+}
+
+namespace QtMetaContainerPrivate {
+
+enum IteratorCapability : quint8 {
+ InputCapability = 1 << 0,
+ ForwardCapability = 1 << 1,
+ BiDirectionalCapability = 1 << 2,
+ RandomAccessCapability = 1 << 3,
+};
+
+Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
+Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
+
+enum AddRemoveCapability : quint8 {
+ CanAddAtBegin = 1 << 0,
+ CanRemoveAtBegin = 1 << 1,
+ CanAddAtEnd = 1 << 2,
+ CanRemoveAtEnd = 1 << 3
+};
+Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
+Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
+
+class QMetaContainerInterface
+{
+public:
+ enum Position : quint8 { AtBegin, AtEnd, Unspecified };
+ ushort revision = 0;
+ IteratorCapabilities iteratorCapabilities;
+
+ using SizeFn = qsizetype(*)(const void *);
+ SizeFn sizeFn;
+ using ClearFn = void(*)(void *);
+ ClearFn clearFn;
+
+ using CreateIteratorFn = void *(*)(void *, Position);
+ CreateIteratorFn createIteratorFn;
+ using DestroyIteratorFn = void(*)(const void *);
+ DestroyIteratorFn destroyIteratorFn;
+ using CompareIteratorFn = bool(*)(const void *, const void *);
+ CompareIteratorFn compareIteratorFn;
+ using CopyIteratorFn = void(*)(void *, const void *);
+ CopyIteratorFn copyIteratorFn;
+ using AdvanceIteratorFn = void(*)(void *, qsizetype);
+ AdvanceIteratorFn advanceIteratorFn;
+ using DiffIteratorFn = qsizetype(*)(const void *, const void *);
+ DiffIteratorFn diffIteratorFn;
+
+ using CreateConstIteratorFn = void *(*)(const void *, Position);
+ CreateConstIteratorFn createConstIteratorFn;
+ DestroyIteratorFn destroyConstIteratorFn;
+ CompareIteratorFn compareConstIteratorFn;
+ CopyIteratorFn copyConstIteratorFn;
+ AdvanceIteratorFn advanceConstIteratorFn;
+ DiffIteratorFn diffConstIteratorFn;
+
+ QMetaContainerInterface() = default;
+
+ template<typename MetaContainer>
+ constexpr QMetaContainerInterface(const MetaContainer &)
+ : iteratorCapabilities(MetaContainer::getIteratorCapabilities())
+ , sizeFn(MetaContainer::getSizeFn())
+ , clearFn(MetaContainer::getClearFn())
+ , createIteratorFn(MetaContainer::getCreateIteratorFn())
+ , destroyIteratorFn(MetaContainer::getDestroyIteratorFn())
+ , compareIteratorFn(MetaContainer::getCompareIteratorFn())
+ , copyIteratorFn(MetaContainer::getCopyIteratorFn())
+ , advanceIteratorFn(MetaContainer::getAdvanceIteratorFn())
+ , diffIteratorFn(MetaContainer::getDiffIteratorFn())
+ , createConstIteratorFn(MetaContainer::getCreateConstIteratorFn())
+ , destroyConstIteratorFn(MetaContainer::getDestroyConstIteratorFn())
+ , compareConstIteratorFn(MetaContainer::getCompareConstIteratorFn())
+ , copyConstIteratorFn(MetaContainer::getCopyConstIteratorFn())
+ , advanceConstIteratorFn(MetaContainer::getAdvanceConstIteratorFn())
+ , diffConstIteratorFn(MetaContainer::getDiffConstIteratorFn())
+ {}
+};
+
+class QMetaSequenceInterface : public QMetaContainerInterface
+{
+public:
+ const QtPrivate::QMetaTypeInterface *valueMetaType;
+ AddRemoveCapabilities addRemoveCapabilities;
+
+ using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
+ ValueAtIndexFn valueAtIndexFn;
+ using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
+ SetValueAtIndexFn setValueAtIndexFn;
+
+ using AddValueFn = void(*)(void *, const void *, Position);
+ AddValueFn addValueFn;
+ using RemoveValueFn = void(*)(void *, Position);
+ RemoveValueFn removeValueFn;
+
+ using ValueAtIteratorFn = void(*)(const void *, void *);
+ ValueAtIteratorFn valueAtIteratorFn;
+ using SetValueAtIteratorFn = void(*)(const void *, const void *);
+ SetValueAtIteratorFn setValueAtIteratorFn;
+ using InsertValueAtIteratorFn = void(*)(void *, const void *, const void *);
+ InsertValueAtIteratorFn insertValueAtIteratorFn;
+
+ ValueAtIteratorFn valueAtConstIteratorFn;
+
+ using EraseValueAtIteratorFn = void(*)(void *, const void *);
+ EraseValueAtIteratorFn eraseValueAtIteratorFn;
+
+ using EraseRangeAtIteratorFn = void(*)(void *, const void *, const void *);
+ EraseRangeAtIteratorFn eraseRangeAtIteratorFn;
+
+ QMetaSequenceInterface() = default;
+
+ template<typename MetaSequence>
+ constexpr QMetaSequenceInterface(const MetaSequence &m)
+ : QMetaContainerInterface(m)
+ , valueMetaType(MetaSequence::getValueMetaType())
+ , addRemoveCapabilities(MetaSequence::getAddRemoveCapabilities())
+ , valueAtIndexFn(MetaSequence::getValueAtIndexFn())
+ , setValueAtIndexFn(MetaSequence::getSetValueAtIndexFn())
+ , addValueFn(MetaSequence::getAddValueFn())
+ , removeValueFn(MetaSequence::getRemoveValueFn())
+ , valueAtIteratorFn(MetaSequence::getValueAtIteratorFn())
+ , setValueAtIteratorFn(MetaSequence::getSetValueAtIteratorFn())
+ , insertValueAtIteratorFn(MetaSequence::getInsertValueAtIteratorFn())
+ , valueAtConstIteratorFn(MetaSequence::getValueAtConstIteratorFn())
+ , eraseValueAtIteratorFn(MetaSequence::getEraseValueAtIteratorFn())
+ , eraseRangeAtIteratorFn(MetaSequence::getEraseRangeAtIteratorFn())
+ {}
+};
+
+class QMetaAssociationInterface : public QMetaContainerInterface
+{
+public:
+ const QtPrivate::QMetaTypeInterface *keyMetaType;
+ const QtPrivate::QMetaTypeInterface *mappedMetaType;
+
+ using InsertKeyFn = void(*)(void *, const void *);
+ InsertKeyFn insertKeyFn;
+ using RemoveKeyFn = void(*)(void *, const void *);
+ RemoveKeyFn removeKeyFn;
+ using ContainsKeyFn = bool(*)(const void *, const void *);
+ ContainsKeyFn containsKeyFn;
+
+ using MappedAtKeyFn = void(*)(const void *, const void *, void *);
+ MappedAtKeyFn mappedAtKeyFn;
+ using SetMappedAtKeyFn = void(*)(void *, const void *, const void *);
+ SetMappedAtKeyFn setMappedAtKeyFn;
+
+ using CreateIteratorAtKeyFn = void *(*)(void *, const void *);
+ CreateIteratorAtKeyFn createIteratorAtKeyFn;
+ using CreateConstIteratorAtKeyFn = void *(*)(const void *, const void *);
+ CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn;
+
+ using KeyAtIteratorFn = void(*)(const void *, void *);
+ KeyAtIteratorFn keyAtIteratorFn;
+ KeyAtIteratorFn keyAtConstIteratorFn;
+
+ using MappedAtIteratorFn = void(*)(const void *, void *);
+ MappedAtIteratorFn mappedAtIteratorFn;
+ MappedAtIteratorFn mappedAtConstIteratorFn;
+
+ using SetMappedAtIteratorFn = void(*)(const void *, const void *);
+ SetMappedAtIteratorFn setMappedAtIteratorFn;
+
+ using EraseKeyAtIteratorFn = void(*)(void *, const void *);
+ EraseKeyAtIteratorFn eraseKeyAtIteratorFn;
+
+ QMetaAssociationInterface() = default;
+
+ template<typename MetaAssociation>
+ constexpr QMetaAssociationInterface(const MetaAssociation &m)
+ : QMetaContainerInterface(m)
+ , keyMetaType(MetaAssociation::getKeyMetaType())
+ , mappedMetaType(MetaAssociation::getMappedMetaType())
+ , insertKeyFn(MetaAssociation::getInsertKeyFn())
+ , removeKeyFn(MetaAssociation::getRemoveKeyFn())
+ , containsKeyFn(MetaAssociation::getContainsKeyFn())
+ , mappedAtKeyFn(MetaAssociation::getMappedAtKeyFn())
+ , setMappedAtKeyFn(MetaAssociation::getSetMappedAtKeyFn())
+ , createIteratorAtKeyFn(MetaAssociation::createIteratorAtKeyFn())
+ , createConstIteratorAtKeyFn(MetaAssociation::createConstIteratorAtKeyFn())
+ , keyAtIteratorFn(MetaAssociation::getKeyAtIteratorFn())
+ , keyAtConstIteratorFn(MetaAssociation::getKeyAtConstIteratorFn())
+ , mappedAtIteratorFn(MetaAssociation::getMappedAtIteratorFn())
+ , mappedAtConstIteratorFn(MetaAssociation::getMappedAtConstIteratorFn())
+ , setMappedAtIteratorFn(MetaAssociation::getSetMappedAtIteratorFn())
+ , eraseKeyAtIteratorFn(MetaAssociation::getEraseKeyAtIteratorFn())
+ {}
+};
+
+template<typename C>
+class QMetaContainerForContainer
+{
+ friend QMetaContainerInterface;
+
+ template <typename Iterator>
+ static constexpr IteratorCapabilities capabilitiesForIterator()
+ {
+ using Tag = typename std::iterator_traits<Iterator>::iterator_category;
+ IteratorCapabilities caps {};
+ if constexpr (std::is_base_of_v<std::input_iterator_tag, Tag>)
+ caps |= InputCapability;
+ if constexpr (std::is_base_of_v<std::forward_iterator_tag, Tag>)
+ caps |= ForwardCapability;
+ if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, Tag>)
+ caps |= BiDirectionalCapability;
+ if constexpr (std::is_base_of_v<std::random_access_iterator_tag, Tag>)
+ caps |= RandomAccessCapability;
+ return caps;
+ }
+
+ static constexpr IteratorCapabilities getIteratorCapabilities()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>)
+ return capabilitiesForIterator<QContainerInfo::iterator<C>>();
+ else if constexpr (QContainerInfo::has_const_iterator_v<C>)
+ return capabilitiesForIterator<QContainerInfo::const_iterator<C>>();
+ else
+ return {};
+ }
+
+ static constexpr QMetaContainerInterface::SizeFn getSizeFn()
+ {
+ if constexpr (QContainerInfo::has_size_v<C>) {
+ return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::ClearFn getClearFn()
+ {
+ if constexpr (QContainerInfo::has_clear_v<C>) {
+ return [](void *c) { return static_cast<C *>(c)->clear(); };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, QMetaContainerInterface::Position p) -> void* {
+ using Iterator = QContainerInfo::iterator<C>;
+ switch (p) {
+ case QMetaContainerInterface::Unspecified:
+ return new Iterator;
+ case QMetaContainerInterface::AtBegin:
+ return new Iterator(static_cast<C *>(c)->begin());
+ case QMetaContainerInterface::AtEnd:
+ return new Iterator(static_cast<C *>(c)->end());
+ }
+ return nullptr;
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i) {
+ using Iterator = QContainerInfo::iterator<C>;
+ delete static_cast<const Iterator *>(i);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *j) {
+ using Iterator = QContainerInfo::iterator<C>;
+ return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *i, const void *j) {
+ using Iterator = QContainerInfo::iterator<C>;
+ *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *i, qsizetype step) {
+ std::advance(*static_cast<QContainerInfo::iterator<C> *>(i), step);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *j) -> qsizetype {
+ return std::distance(*static_cast<const QContainerInfo::iterator<C> *>(j),
+ *static_cast<const QContainerInfo::iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
+ return [](const void *c, QMetaContainerInterface::Position p) -> void* {
+ using Iterator = QContainerInfo::const_iterator<C>;
+ switch (p) {
+ case QMetaContainerInterface::Unspecified:
+ return new Iterator;
+ case QMetaContainerInterface::AtBegin:
+ return new Iterator(static_cast<const C *>(c)->begin());
+ case QMetaContainerInterface::AtEnd:
+ return new Iterator(static_cast<const C *>(c)->end());
+ }
+ return nullptr;
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
+ return [](const void *i) {
+ using Iterator = QContainerInfo::const_iterator<C>;
+ delete static_cast<const Iterator *>(i);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
+ return [](const void *i, const void *j) {
+ using Iterator = QContainerInfo::const_iterator<C>;
+ return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
+ return [](void *i, const void *j) {
+ using Iterator = QContainerInfo::const_iterator<C>;
+ *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
+ return [](void *i, qsizetype step) {
+ std::advance(*static_cast<QContainerInfo::const_iterator<C> *>(i), step);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
+ return [](const void *i, const void *j) -> qsizetype {
+ return std::distance(*static_cast<const QContainerInfo::const_iterator<C> *>(j),
+ *static_cast<const QContainerInfo::const_iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+protected:
+
+ template<typename EraseFn>
+ static constexpr EraseFn getEraseAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C>
+ && QContainerInfo::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, const void *i) {
+ static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+};
+
+template<typename C>
+class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
+{
+ friend QMetaSequenceInterface;
+
+ static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType()
+ {
+ if constexpr (QContainerInfo::has_value_type_v<C>)
+ return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
+ else
+ return nullptr;
+ }
+
+ static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
+ {
+ AddRemoveCapabilities caps;
+ if constexpr (QContainerInfo::has_push_back_v<C>)
+ caps |= CanAddAtEnd;
+ if constexpr (QContainerInfo::has_pop_back_v<C>)
+ caps |= CanRemoveAtEnd;
+ if constexpr (QContainerInfo::has_push_front_v<C>)
+ caps |= CanAddAtBegin;
+ if constexpr (QContainerInfo::has_pop_front_v<C>)
+ caps |= CanRemoveAtBegin;
+ return caps;
+ }
+
+ static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn()
+ {
+ if constexpr (QContainerInfo::has_at_index_v<C>) {
+ return [](const void *c, qsizetype i, void *r) {
+ *static_cast<QContainerInfo::value_type<C> *>(r)
+ = static_cast<const C *>(c)->at(i);
+ };
+ } else if constexpr (QContainerInfo::can_get_at_index_v<C>) {
+ return [](const void *c, qsizetype i, void *r) {
+ *static_cast<QContainerInfo::value_type<C> *>(r)
+ = (*static_cast<const C *>(c))[i];
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::SetValueAtIndexFn getSetValueAtIndexFn()
+ {
+ if constexpr (QContainerInfo::can_set_at_index_v<C>) {
+ return [](void *c, qsizetype i, const void *e) {
+ (*static_cast<C *>(c))[i]
+ = *static_cast<const QContainerInfo::value_type<C> *>(e);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
+ {
+ if constexpr (QContainerInfo::has_push_back_v<C>) {
+ if constexpr (QContainerInfo::has_push_front_v<C>) {
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->push_front(value);
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ case QMetaSequenceInterface::Unspecified:
+ static_cast<C *>(c)->push_back(value);
+ break;
+ }
+ };
+ } else {
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ case QMetaSequenceInterface::Unspecified:
+ static_cast<C *>(c)->push_back(value);
+ break;
+ }
+ };
+ }
+ } else if constexpr (QContainerInfo::has_push_front_v<C>) {
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
+ switch (position) {
+ case QMetaSequenceInterface::Unspecified:
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->push_front(value);
+ case QMetaSequenceInterface::AtEnd:
+ break;
+ }
+ };
+ } else if constexpr (QContainerInfo::has_insert_v<C>) {
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ if (position == QMetaSequenceInterface::Unspecified) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerInfo::value_type<C> *>(v));
+ }
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
+ {
+ if constexpr (QContainerInfo::has_pop_back_v<C>) {
+ if constexpr (QContainerInfo::has_pop_front_v<C>) {
+ return [](void *c, QMetaSequenceInterface::Position position) {
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->pop_front();
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ case QMetaSequenceInterface::Unspecified:
+ static_cast<C *>(c)->pop_back();
+ break;
+ }
+ };
+ } else {
+ return [](void *c, QMetaSequenceInterface::Position position) {
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ break;
+ case QMetaSequenceInterface::Unspecified:
+ case QMetaSequenceInterface::AtEnd:
+ static_cast<C *>(c)->pop_back();
+ break;
+ }
+ };
+ }
+ } else if constexpr (QContainerInfo::has_pop_front_v<C>) {
+ return [](void *c, QMetaSequenceInterface::Position position) {
+ switch (position) {
+ case QMetaSequenceInterface::Unspecified:
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->pop_front();
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ break;
+ }
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C>
+ && QContainerInfo::iterator_dereferences_to_value_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, void *r) {
+ *static_cast<QContainerInfo::value_type<C> *>(r) =
+ *(*static_cast<const QContainerInfo::iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C>
+ && QContainerInfo::can_set_value_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *e) {
+ *(*static_cast<const QContainerInfo::iterator<C> *>(i))
+ = *static_cast<const QContainerInfo::value_type<C> *>(e);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C>
+ && QContainerInfo::can_insert_value_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, const void *i, const void *e) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerInfo::iterator<C> *>(i),
+ *static_cast<const QContainerInfo::value_type<C> *>(e));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_const_iterator_v<C>
+ && QContainerInfo::iterator_dereferences_to_value_v<C>) {
+ return [](const void *i, void *r) {
+ *static_cast<QContainerInfo::value_type<C> *>(r) =
+ *(*static_cast<const QContainerInfo::const_iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
+ {
+ return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
+ QMetaSequenceInterface::EraseValueAtIteratorFn>();
+ }
+
+ static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::has_iterator_v<C>
+ && QContainerInfo::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, const void *i, const void *j) {
+ static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i),
+ *static_cast<const QContainerInfo::iterator<C> *>(j));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+};
+
+template<typename C>
+class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
+{
+ friend QMetaAssociationInterface;
+
+ static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType()
+ {
+ if constexpr (QContainerInfo::has_key_type_v<C>)
+ return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
+ else
+ return nullptr;
+ }
+
+ static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType()
+ {
+ if constexpr (QContainerInfo::has_mapped_type_v<C>)
+ return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
+ else
+ return nullptr;
+ }
+
+ static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn()
+ {
+ if constexpr (QContainerInfo::can_insert_key_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerInfo::key_type<C> *>(k));
+ };
+ } else if constexpr (QContainerInfo::can_insert_pair_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->insert(
+ {*static_cast<const QContainerInfo::key_type<C> *>(k), {}});
+ };
+ } else if constexpr (QContainerInfo::can_insert_key_mapped_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerInfo::key_type<C> *>(k), {});
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn()
+ {
+ if constexpr (QContainerInfo::can_erase_at_key_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::key_type<C> *>(k));
+ };
+ } else if constexpr (QContainerInfo::can_remove_at_key_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->remove(*static_cast<const QContainerInfo::key_type<C> *>(k));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn()
+ {
+ if constexpr (QContainerInfo::has_contains_v<C>) {
+ return [](const void *c, const void *k) {
+ return static_cast<const C *>(c)->contains(
+ *static_cast<const QContainerInfo::key_type<C> *>(k));
+ };
+ } else if (QContainerInfo::has_find_v<C>) {
+ return [](const void *c, const void *k) {
+ const C *container = static_cast<const C *>(c);
+ return container->find(
+ *static_cast<const QContainerInfo::key_type<C> *>(k))
+ != container->end();
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn()
+ {
+ if constexpr (QContainerInfo::has_at_key_v<C>) {
+ return [](const void *c, const void *k, void *r) {
+ *static_cast<QContainerInfo::mapped_type<C> *>(r)
+ = static_cast<const C *>(c)->at(
+ *static_cast<const QContainerInfo::key_type<C> *>(k));
+ };
+ } else if constexpr (QContainerInfo::can_get_at_key_v<C>) {
+ return [](const void *c, const void *k, void *r) {
+ *static_cast<QContainerInfo::mapped_type<C> *>(r)
+ = (*static_cast<const C *>(c))[
+ *static_cast<const QContainerInfo::key_type<C> *>(k)];
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn()
+ {
+ if constexpr (QContainerInfo::can_set_at_key_v<C>) {
+ return [](void *c, const void *k, const void *m) {
+ (*static_cast<C *>(c))[*static_cast<const QContainerInfo::key_type<C> *>(k)] =
+ *static_cast<const QContainerInfo::mapped_type<C> *>(m);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn()
+ {
+ if constexpr (QContainerInfo::has_find_v<C>) {
+ return [](void *c, const void *k) -> void* {
+ using Iterator = QContainerInfo::iterator<C>;
+ return new Iterator(static_cast<C *>(c)->find(
+ *static_cast<const QContainerInfo::key_type<C> *>(k)));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn()
+ {
+ if constexpr (QContainerInfo::has_find_v<C>) {
+ return [](const void *c, const void *k) -> void* {
+ using Iterator = QContainerInfo::const_iterator<C>;
+ return new Iterator(static_cast<const C *>(c)->find(
+ *static_cast<const QContainerInfo::key_type<C> *>(k)));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ template<typename Iterator>
+ static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::iterator_has_key_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerInfo::key_type<C> *>(k)
+ = static_cast<const Iterator *>(i)->key();
+ };
+ } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
+ && QContainerInfo::value_type_has_first_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerInfo::key_type<C> *>(k)
+ = (*static_cast<const Iterator *>(i))->first;
+ };
+ } else if constexpr (QContainerInfo::iterator_dereferences_to_key_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerInfo::key_type<C> *>(k)
+ = *(*static_cast<const Iterator *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn()
+ {
+ return keyAtIteratorFn<QContainerInfo::iterator<C>>();
+ }
+
+ static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn()
+ {
+ return keyAtIteratorFn<QContainerInfo::const_iterator<C>>();
+ }
+
+ template<typename Iterator>
+ static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::iterator_has_value_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerInfo::mapped_type<C> *>(k)
+ = static_cast<const Iterator *>(i)->value();
+ };
+ } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
+ && QContainerInfo::value_type_has_second_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerInfo::mapped_type<C> *>(k)
+ = (*static_cast<const Iterator *>(i))->second;
+ };
+ } else if constexpr (QContainerInfo::iterator_dereferences_to_mapped_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerInfo::mapped_type<C> *>(k)
+ = *static_cast<const Iterator *>(i);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn()
+ {
+ return mappedAtIteratorFn<QContainerInfo::iterator<C>>();
+ }
+
+ static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn()
+ {
+ return mappedAtIteratorFn<QContainerInfo::const_iterator<C>>();
+ }
+
+ static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn()
+ {
+ if constexpr (QContainerInfo::can_set_mapped_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *m) {
+ *(*static_cast<const QContainerInfo::iterator<C> *>(i))
+ = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
+ };
+ } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
+ && QContainerInfo::value_type_has_second_v<C>) {
+ return [](const void *i, const void *m) {
+ (*static_cast<const QContainerInfo::iterator<C> *>(i))->second
+ = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn()
+ {
+ return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
+ QMetaAssociationInterface::EraseKeyAtIteratorFn>();
+ }
+};
+
+} // namespace QtMetaContainerPrivate
+
+class Q_CORE_EXPORT QMetaContainer
+{
+public:
+ QMetaContainer() = default;
+ explicit QMetaContainer(const QtMetaContainerPrivate::QMetaContainerInterface *d) : d_ptr(d) {}
+
+ bool hasInputIterator() const;
+ bool hasForwardIterator() const;
+ bool hasBidirectionalIterator() const;
+ bool hasRandomAccessIterator() const;
+
+ bool hasSize() const;
+ qsizetype size(const void *container) const;
+
+ bool canClear() const;
+ void clear(void *container) const;
+
+ bool hasIterator() const;
+ void *begin(void *container) const;
+ void *end(void *container) const;
+ void destroyIterator(const void *iterator) const;
+ bool compareIterator(const void *i, const void *j) const;
+ void copyIterator(void *target, const void *source) const;
+ void advanceIterator(void *iterator, qsizetype step) const;
+ qsizetype diffIterator(const void *i, const void *j) const;
+
+ bool hasConstIterator() const;
+ void *constBegin(const void *container) const;
+ void *constEnd(const void *container) const;
+ void destroyConstIterator(const void *iterator) const;
+ bool compareConstIterator(const void *i, const void *j) const;
+ void copyConstIterator(void *target, const void *source) const;
+ void advanceConstIterator(void *iterator, qsizetype step) const;
+ qsizetype diffConstIterator(const void *i, const void *j) const;
+
+protected:
+ const QtMetaContainerPrivate::QMetaContainerInterface *d_ptr = nullptr;
+};
+
+class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
+{
+public:
+ QMetaSequence() = default;
+ explicit QMetaSequence(const QtMetaContainerPrivate::QMetaSequenceInterface *d) : QMetaContainer(d) {}
+
+ template<typename T>
+ static constexpr QMetaSequence fromContainer()
+ {
+ return QMetaSequence(&MetaSequence<T>::value);
+ }
+
+ QMetaType valueMetaType() const;
+
+ bool isSortable() const;
+ bool canAddValueAtBegin() const;
+ void addValueAtBegin(void *container, const void *value) const;
+ bool canAddValueAtEnd() const;
+ void addValueAtEnd(void *container, const void *value) const;
+ bool canRemoveValueAtBegin() const;
+ void removeValueAtBegin(void *container) const;
+ bool canRemoveValueAtEnd() const;
+ void removeValueAtEnd(void *container) const;
+
+ bool canGetValueAtIndex() const;
+ void valueAtIndex(const void *container, qsizetype index, void *result) const;
+
+ bool canSetValueAtIndex() const;
+ void setValueAtIndex(void *container, qsizetype index, const void *value) const;
+
+ bool canAddValue() const;
+ void addValue(void *container, const void *value) const;
+
+ bool canRemoveValue() const;
+ void removeValue(void *container) const;
+
+ bool canGetValueAtIterator() const;
+ void valueAtIterator(const void *iterator, void *result) const;
+
+ bool canSetValueAtIterator() const;
+ void setValueAtIterator(const void *iterator, const void *value) const;
+
+ bool canInsertValueAtIterator() const;
+ void insertValueAtIterator(void *container, const void *iterator, const void *value) const;
+
+ bool canEraseValueAtIterator() const;
+ void eraseValueAtIterator(void *container, const void *iterator) const;
+
+ bool canEraseRangeAtIterator() const;
+ void eraseRangeAtIterator(void *container, const void *iterator1, const void *iterator2) const;
+
+ bool canGetValueAtConstIterator() const;
+ void valueAtConstIterator(const void *iterator, void *result) const;
+
+ const QtMetaContainerPrivate::QMetaSequenceInterface *iface() const { return d(); }
+
+private:
+ friend bool comparesEqual(const QMetaSequence &lhs, const QMetaSequence &rhs) noexcept
+ {
+ return lhs.d() == rhs.d();
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QMetaSequence)
+
+ template<typename T>
+ struct MetaSequence
+ {
+ static constexpr const QtMetaContainerPrivate::QMetaSequenceInterface value
+ = QtMetaContainerPrivate::QMetaSequenceInterface(
+ QtMetaContainerPrivate::QMetaSequenceForContainer<T>());
+ };
+
+ const QtMetaContainerPrivate::QMetaSequenceInterface *d() const
+ {
+ return static_cast<const QtMetaContainerPrivate::QMetaSequenceInterface *>(d_ptr);
+ }
+};
+
+class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
+{
+public:
+ QMetaAssociation() = default;
+ explicit QMetaAssociation(const QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {}
+
+ template<typename T>
+ static constexpr QMetaAssociation fromContainer()
+ {
+ return QMetaAssociation(&MetaAssociation<T>::value);
+ }
+
+ QMetaType keyMetaType() const;
+ QMetaType mappedMetaType() const;
+
+ bool canInsertKey() const
+ {
+ if (auto iface = d())
+ return iface->insertKeyFn;
+ return false;
+ }
+ void insertKey(void *container, const void *key) const
+ {
+ if (canInsertKey())
+ d()->insertKeyFn(container, key);
+ }
+
+ bool canRemoveKey() const
+ {
+ if (auto iface = d())
+ return iface->removeKeyFn;
+ return false;
+ }
+ void removeKey(void *container, const void *key) const
+ {
+ if (canRemoveKey())
+ d()->removeKeyFn(container, key);
+ }
+
+ bool canContainsKey() const
+ {
+ if (auto iface = d())
+ return iface->containsKeyFn;
+ return false;
+ }
+ bool containsKey(const void *container, const void *key) const
+ {
+ if (canContainsKey())
+ return d()->containsKeyFn(container, key);
+ return false;
+ }
+
+
+ bool canGetMappedAtKey() const
+ {
+ if (auto iface = d())
+ return iface->mappedAtKeyFn;
+ return false;
+ }
+ void mappedAtKey(const void *container, const void *key, void *mapped) const
+ {
+ if (canGetMappedAtKey())
+ d()->mappedAtKeyFn(container, key, mapped);
+ }
+
+ bool canSetMappedAtKey() const
+ {
+ if (auto iface = d())
+ return iface->setMappedAtKeyFn;
+ return false;
+ }
+ void setMappedAtKey(void *container, const void *key, const void *mapped) const
+ {
+ if (canSetMappedAtKey())
+ d()->setMappedAtKeyFn(container, key, mapped);
+ }
+
+ bool canGetKeyAtIterator() const
+ {
+ if (auto iface = d())
+ return iface->keyAtIteratorFn;
+ return false;
+ }
+
+ void keyAtIterator(const void *iterator, void *key) const
+ {
+ if (canGetKeyAtIterator())
+ d()->keyAtIteratorFn(iterator, key);
+ }
+
+ bool canGetKeyAtConstIterator() const
+ {
+ if (auto iface = d())
+ return iface->keyAtConstIteratorFn;
+ return false;
+ }
+
+ void keyAtConstIterator(const void *iterator, void *key) const
+ {
+ if (canGetKeyAtConstIterator())
+ d()->keyAtConstIteratorFn(iterator, key);
+ }
+
+ bool canGetMappedAtIterator() const
+ {
+ if (auto iface = d())
+ return iface->mappedAtIteratorFn;
+ return false;
+ }
+
+ void mappedAtIterator(const void *iterator, void *mapped) const
+ {
+ if (canGetMappedAtIterator())
+ d()->mappedAtIteratorFn(iterator, mapped);
+ }
+
+ bool canGetMappedAtConstIterator() const
+ {
+ if (auto iface = d())
+ return iface->mappedAtConstIteratorFn;
+ return false;
+ }
+
+ void mappedAtConstIterator(const void *iterator, void *mapped) const
+ {
+ if (canGetMappedAtConstIterator())
+ d()->mappedAtConstIteratorFn(iterator, mapped);
+ }
+
+ bool canSetMappedAtIterator() const
+ {
+ if (auto iface = d())
+ return iface->setMappedAtIteratorFn;
+ return false;
+ }
+
+ void setMappedAtIterator(const void *iterator, const void *mapped) const
+ {
+ if (canSetMappedAtIterator())
+ d()->setMappedAtIteratorFn(iterator, mapped);
+ }
+
+ bool canCreateIteratorAtKey() const
+ {
+ if (auto iface = d())
+ return iface->createIteratorAtKeyFn;
+ return false;
+ }
+
+ void *createIteratorAtKey(void *container, const void *key) const
+ {
+ if (canCreateIteratorAtKey())
+ return d()->createIteratorAtKeyFn(container, key);
+ return nullptr;
+ }
+
+ bool canCreateConstIteratorAtKey() const
+ {
+ if (auto iface = d())
+ return iface->createConstIteratorAtKeyFn;
+ return false;
+ }
+
+ void *createConstIteratorAtKey(const void *container, const void *key) const
+ {
+ if (canCreateConstIteratorAtKey())
+ return d()->createConstIteratorAtKeyFn(container, key);
+ return nullptr;
+ }
+
+ const QtMetaContainerPrivate::QMetaAssociationInterface *iface() const { return d(); }
+
+private:
+ friend bool comparesEqual(const QMetaAssociation &lhs, const QMetaAssociation &rhs) noexcept
+ {
+ return lhs.d() == rhs.d();
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QMetaAssociation)
+
+ template<typename T>
+ struct MetaAssociation
+ {
+ static constexpr const QtMetaContainerPrivate::QMetaAssociationInterface value
+ = QtMetaContainerPrivate::QMetaAssociationInterface(
+ QtMetaContainerPrivate::QMetaAssociationForContainer<T>());
+ };
+
+ const QtMetaContainerPrivate::QMetaAssociationInterface *d() const
+ {
+ return static_cast<const QtMetaContainerPrivate::QMetaAssociationInterface *>(d_ptr);
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QMETACONTAINER_H
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 6cb43cea72..05662b385a 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1,70 +1,35 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmetaobject.h"
+#include "qmetaobject_p.h"
#include "qmetatype.h"
+#include "qmetatype_p.h"
#include "qobject.h"
-#include "qmetaobject_p.h"
+#include "qobject_p.h"
#include <qcoreapplication.h>
-#include <qcoreevent.h>
-#include <qdatastream.h>
-#include <qstringlist.h>
-#include <qthread.h>
#include <qvariant.h>
-#include <qdebug.h>
+
+// qthread(_p).h uses QT_CONFIG(thread) internally and has a dummy
+// interface for the non-thread support case
+#include <qthread.h>
+#include "private/qthread_p.h"
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#endif
-#include "private/qobject_p.h"
-#include "private/qmetaobject_p.h"
-#include "private/qthread_p.h"
-
// for normalizeTypeInternal
#include "private/qmetaobject_moc_p.h"
#include <ctype.h>
+#include <memory>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QMetaObject
\inmodule QtCore
@@ -129,12 +94,17 @@ QT_BEGIN_NAMESPACE
\internal
- \value InvokeSlot
- \value EmitSignal
+ \value InvokeMetaMethod
\value ReadProperty
\value WriteProperty
\value ResetProperty
\value CreateInstance
+ \value IndexOfMethod
+ \value RegisterPropertyMetaType
+ \value RegisterMethodArgumentMetaType
+ \value BindableProperty
+ \value CustomCall
+ \value ConstructInPlace
*/
/*!
@@ -157,43 +127,51 @@ static inline const char *rawStringData(const QMetaObject *mo, int index)
return reinterpret_cast<const char *>(mo->d.stringdata) + offset;
}
-static inline const QByteArray stringData(const QMetaObject *mo, int index)
+static inline QByteArrayView stringDataView(const QMetaObject *mo, int index)
{
Q_ASSERT(priv(mo->d.data)->revision >= 7);
uint offset = mo->d.stringdata[2*index];
uint length = mo->d.stringdata[2*index + 1];
const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset;
- return QByteArray::fromRawData(string, length);
+ return {string, qsizetype(length)};
}
-static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
+static inline QByteArray stringData(const QMetaObject *mo, int index)
{
- if (typeInfo & IsUnresolvedType) {
- return rawStringData(mo, typeInfo & TypeNameIndexMask);
- } else {
- return QMetaType::typeName(typeInfo);
- }
+ const auto view = stringDataView(mo, index);
+ return QByteArray::fromRawData(view.data(), view.size());
}
-static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
+static inline QByteArrayView typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
{
- if (typeInfo & IsUnresolvedType) {
- return stringData(mo, typeInfo & TypeNameIndexMask);
- } else {
- // ### Use the QMetaType::typeName() that returns QByteArray
- const char *t = QMetaType::typeName(typeInfo);
- return QByteArray::fromRawData(t, qstrlen(t));
- }
+ if (typeInfo & IsUnresolvedType)
+ return stringDataView(mo, typeInfo & TypeNameIndexMask);
+ else
+ return QByteArrayView(QMetaType(typeInfo).name());
}
static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
{
if (!(typeInfo & IsUnresolvedType))
return typeInfo;
- return QMetaType::type(rawStringData(mo, typeInfo & TypeNameIndexMask));
+ return QMetaType::fromName(rawStringData(mo, typeInfo & TypeNameIndexMask)).id();
+}
+
+static auto parse_scope(QByteArrayView qualifiedKey) noexcept
+{
+ struct R {
+ std::optional<QByteArrayView> scope;
+ QByteArrayView key;
+ };
+ const auto scopePos = qualifiedKey.lastIndexOf("::"_L1);
+ if (scopePos < 0)
+ return R{std::nullopt, qualifiedKey};
+ else
+ return R{qualifiedKey.first(scopePos), qualifiedKey.sliced(scopePos + 2)};
}
-class QMetaMethodPrivate : public QMetaMethod
+namespace {
+class QMetaMethodPrivate : public QMetaMethodInvoker
{
public:
static const QMetaMethodPrivate *get(const QMetaMethod *q)
@@ -209,17 +187,27 @@ public:
inline uint parameterTypeInfo(int index) const;
inline int parameterType(int index) const;
inline void getParameterTypes(int *types) const;
+ inline const QtPrivate::QMetaTypeInterface *returnMetaTypeInterface() const;
+ inline const QtPrivate::QMetaTypeInterface *const *parameterMetaTypeInterfaces() const;
+ inline QByteArray parameterTypeName(int index) const;
inline QList<QByteArray> parameterTypes() const;
inline QList<QByteArray> parameterNames() const;
inline QByteArray tag() const;
inline int ownMethodIndex() const;
+ inline int ownConstructorMethodIndex() const;
private:
+ void checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface, int index) const;
QMetaMethodPrivate();
};
+} // unnamed namespace
+enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*!
\since 4.5
+ \obsolete [6.5] Please use the variadic overload of this function
Constructs a new instance of this class. You can pass up to ten arguments
(\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
@@ -242,54 +230,84 @@ QObject *QMetaObject::newInstance(QGenericArgument val0,
QGenericArgument val8,
QGenericArgument val9) const
{
- if (!inherits(&QObject::staticMetaObject))
- {
- qWarning("QMetaObject::newInstance: type %s does not inherit QObject", className());
- return nullptr;
- }
-
- QByteArray constructorName = className();
- {
- int idx = constructorName.lastIndexOf(':');
- if (idx != -1)
- constructorName.remove(0, idx+1); // remove qualified part
- }
- QVarLengthArray<char, 512> sig;
- sig.append(constructorName.constData(), constructorName.length());
- sig.append('(');
-
- enum { MaximumParamCount = 10 };
- const char *typeNames[] = {val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
- val5.name(), val6.name(), val7.name(), val8.name(), val9.name()};
+ const char *typeNames[] = {
+ nullptr,
+ val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
+ val5.name(), val6.name(), val7.name(), val8.name(), val9.name()
+ };
+ const void *parameters[] = {
+ nullptr,
+ val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
+ val5.data(), val6.data(), val7.data(), val8.data(), val9.data()
+ };
int paramCount;
- for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
- int len = qstrlen(typeNames[paramCount]);
+ for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
+ int len = int(qstrlen(typeNames[paramCount]));
if (len <= 0)
break;
- sig.append(typeNames[paramCount], len);
- sig.append(',');
}
- if (paramCount == 0)
- sig.append(')'); // no parameters
- else
- sig[sig.size() - 1] = ')';
- sig.append('\0');
- int idx = indexOfConstructor(sig.constData());
- if (idx < 0) {
- QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
- idx = indexOfConstructor(norm.constData());
- }
- if (idx < 0)
+ return newInstanceImpl(this, paramCount, parameters, typeNames, nullptr);
+}
+#endif
+
+/*!
+ \fn template <typename... Args> QObject *QMetaObject::newInstance(Args &&... arguments) const
+ \since 6.5
+
+ Constructs a new instance of this class and returns the new object, or
+ \nullptr if no suitable constructor is available. The types of the
+ arguments \a arguments will be used to find a matching constructor, and then
+ forwarded to it the same way signal-slot connections do.
+
+ Note that only constructors that are declared with the Q_INVOKABLE
+ modifier are made available through the meta-object system.
+
+ \sa constructor()
+*/
+
+QObject *QMetaObject::newInstanceImpl(const QMetaObject *mobj, qsizetype paramCount,
+ const void **parameters, const char **typeNames,
+ const QtPrivate::QMetaTypeInterface **metaTypes)
+{
+ if (!mobj->inherits(&QObject::staticMetaObject)) {
+ qWarning("QMetaObject::newInstance: type %s does not inherit QObject", mobj->className());
return nullptr;
+ }
+QT_WARNING_PUSH
+#if Q_CC_GNU >= 1200
+QT_WARNING_DISABLE_GCC("-Wdangling-pointer")
+#endif
+
+ // set the return type
QObject *returnValue = nullptr;
- void *param[] = {&returnValue, val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
- val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
+ QMetaType returnValueMetaType = QMetaType::fromType<decltype(returnValue)>();
+ parameters[0] = &returnValue;
+ typeNames[0] = returnValueMetaType.name();
+ if (metaTypes)
+ metaTypes[0] = returnValueMetaType.iface();
+
+QT_WARNING_POP
+
+ // find the constructor
+ auto priv = QMetaObjectPrivate::get(mobj);
+ for (int i = 0; i < priv->constructorCount; ++i) {
+ QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(mobj, i);
+ if (m.parameterCount() != (paramCount - 1))
+ continue;
+
+ // attempt to call
+ QMetaMethodPrivate::InvokeFailReason r =
+ QMetaMethodPrivate::invokeImpl(m, nullptr, Qt::DirectConnection, paramCount,
+ parameters, typeNames, metaTypes);
+ if (r == QMetaMethodPrivate::InvokeFailReason::None)
+ return returnValue;
+ if (int(r) < 0)
+ return nullptr;
+ }
- if (static_metacall(CreateInstance, idx, param) >= 0)
- return nullptr;
return returnValue;
}
@@ -316,9 +334,9 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
return object->qt_metacall(cl, idx, argv);
}
-static inline const char *objectClassName(const QMetaObject *m)
+static inline QByteArrayView objectClassName(const QMetaObject *m)
{
- return rawStringData(m, priv(m->d.data)->className);
+ return stringDataView(m, priv(m->d.data)->className);
}
/*!
@@ -328,7 +346,7 @@ static inline const char *objectClassName(const QMetaObject *m)
*/
const char *QMetaObject::className() const
{
- return objectClassName(this);
+ return objectClassName(this).constData();
}
/*!
@@ -359,16 +377,12 @@ bool QMetaObject::inherits(const QMetaObject *metaObject) const noexcept
}
/*!
+ \fn QObject *QMetaObject::cast(QObject *obj) const
\internal
Returns \a obj if object \a obj inherits from this
meta-object; otherwise returns \nullptr.
*/
-QObject *QMetaObject::cast(QObject *obj) const
-{
- // ### Qt 6: inline
- return const_cast<QObject*>(cast(const_cast<const QObject*>(obj)));
-}
/*!
\internal
@@ -387,11 +401,58 @@ const QObject *QMetaObject::cast(const QObject *obj) const
*/
QString QMetaObject::tr(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(objectClassName(this), s, c, n);
+ return QCoreApplication::translate(className(), s, c, n);
}
#endif // QT_NO_TRANSLATION
/*!
+ \since 6.2
+ Returns the metatype corresponding to this metaobject.
+ If the metaobject originates from a namespace, an invalid metatype is returned.
+ */
+QMetaType QMetaObject::metaType() const
+{
+
+ const QMetaObjectPrivate *d = priv(this->d.data);
+ if (d->revision < 10) {
+ // before revision 10, we did not store the metatype in the metatype array
+ return QMetaType::fromName(className());
+ } else {
+ /* in the metatype array, we store
+
+ | index | data |
+ |----------------------------------------------------------------------|
+ | 0 | QMetaType(property0) |
+ | ... | ... |
+ | propertyCount - 1 | QMetaType(propertyCount - 1) |
+ | propertyCount | QMetaType(enumerator0) |
+ | ... | ... |
+ | propertyCount + enumeratorCount - 1 | QMetaType(enumeratorCount - 1) |
+ | propertyCount + enumeratorCount | QMetaType(class) |
+
+ */
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ // Before revision 12 we only stored metatypes for enums if they showed
+ // up as types of properties or method arguments or return values.
+ // From revision 12 on, we always store them in a predictable place.
+ const qsizetype offset = d->revision < 12
+ ? d->propertyCount
+ : d->propertyCount + d->enumeratorCount;
+#else
+ const qsizetype offset = d->propertyCount + d->enumeratorCount;
+#endif
+
+ auto iface = this->d.metaTypes[offset];
+ if (iface && QtMetaTypePrivate::isInterfaceFor<void>(iface))
+ return QMetaType(); // return invalid meta-type for namespaces
+ if (iface)
+ return QMetaType(iface);
+ else // in case of a dynamic metaobject, we might have no metatype stored
+ return QMetaType::fromName(className()); // try lookup by name in that case
+ }
+}
+
+/*!
Returns the method offset for this class; i.e. the index position
of this class's first member function.
@@ -574,19 +635,25 @@ bool QMetaObjectPrivate::methodMatch(const QMetaObject *m, const QMetaMethod &me
const QArgumentType *types)
{
const QMetaMethod::Data &data = method.data;
- if (data.argc() != uint(argc))
+ auto priv = QMetaMethodPrivate::get(&method);
+ if (priv->parameterCount() != argc)
return false;
if (stringData(m, data.name()) != name)
return false;
+ const QtPrivate::QMetaTypeInterface * const *ifaces = priv->parameterMetaTypeInterfaces();
int paramsIndex = data.parameters() + 1;
for (int i = 0; i < argc; ++i) {
uint typeInfo = m->d.data[paramsIndex + i];
- if (types[i].type()) {
- if (types[i].type() != typeFromTypeInfo(m, typeInfo))
+ if (int id = types[i].type()) {
+ if (id == QMetaType(ifaces[i]).id())
+ continue;
+ if (id != typeFromTypeInfo(m, typeInfo))
return false;
} else {
+ if (types[i].name() == QMetaType(ifaces[i]).name())
+ continue;
if (types[i].name() != typeNameFromTypeInfo(m, typeInfo))
return false;
}
@@ -595,6 +662,24 @@ bool QMetaObjectPrivate::methodMatch(const QMetaObject *m, const QMetaMethod &me
return true;
}
+/*!
+ \internal
+ Returns the first method with name \a name found in \a baseObject
+ */
+QMetaMethod QMetaObjectPrivate::firstMethod(const QMetaObject *baseObject, QByteArrayView name)
+{
+ for (const QMetaObject *currentObject = baseObject; currentObject; currentObject = currentObject->superClass()) {
+ const int start = priv(currentObject->d.data)->methodCount - 1;
+ const int end = 0;
+ for (int i = start; i >= end; --i) {
+ auto candidate = QMetaMethod::fromRelativeMethodIndex(currentObject, i);
+ if (name == candidate.name())
+ return candidate;
+ }
+ }
+ return QMetaMethod{};
+}
+
/**
* \internal
* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
@@ -748,7 +833,7 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
QMetaMethod conflictMethod = m->d.superdata->method(conflict);
qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
conflictMethod.methodSignature().constData(),
- objectClassName(m->d.superdata), objectClassName(m));
+ m->d.superdata->className(), m->className());
}
}
#endif
@@ -933,8 +1018,8 @@ bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
uint targetTypeInfo = method->parameterTypeInfo(i);
if ((sourceTypeInfo & IsUnresolvedType)
|| (targetTypeInfo & IsUnresolvedType)) {
- QByteArray sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
- QByteArray targetName = typeNameFromTypeInfo(rmeta, targetTypeInfo);
+ QByteArrayView sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
+ QByteArrayView targetName = typeNameFromTypeInfo(rmeta, targetTypeInfo);
if (sourceName != targetName)
return false;
} else {
@@ -947,10 +1032,10 @@ bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
return true;
}
-static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
+static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, QByteArrayView name)
{
while (self) {
- if (strcmp(objectClassName(self), name) == 0)
+ if (objectClassName(self) == name)
return self;
if (self->d.relatedMetaObjects) {
Q_ASSERT(priv(self->d.data)->revision >= 2);
@@ -976,27 +1061,28 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co
*/
int QMetaObject::indexOfEnumerator(const char *name) const
{
- const QMetaObject *m = this;
- while (m) {
- const QMetaObjectPrivate *d = priv(m->d.data);
- for (int i = 0; i < d->enumeratorCount; ++i) {
- const QMetaEnum e(m, i);
- const char *prop = rawStringData(m, e.data.name());
- if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
- i += m->enumeratorOffset();
- return i;
- }
- }
- m = m->d.superdata;
+ return QMetaObjectPrivate::indexOfEnumerator(this, name);
+}
+
+int QMetaObjectPrivate::indexOfEnumerator(const QMetaObject *m, QByteArrayView name)
+{
+ using W = QMetaObjectPrivate::Which;
+ for (auto which : { W::Name, W::Alias }) {
+ if (int index = indexOfEnumerator(m, name, which); index != -1)
+ return index;
}
- // Check alias names:
- m = this;
+ return -1;
+}
+
+int QMetaObjectPrivate::indexOfEnumerator(const QMetaObject *m, QByteArrayView name, Which which)
+{
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
for (int i = 0; i < d->enumeratorCount; ++i) {
const QMetaEnum e(m, i);
- const char *prop = rawStringData(m, e.data.alias());
- if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ const quint32 id = which == Which::Name ? e.data.name() : e.data.alias();
+ QByteArrayView prop = stringDataView(m, id);
+ if (name == prop) {
i += m->enumeratorOffset();
return i;
}
@@ -1018,9 +1104,9 @@ int QMetaObject::indexOfProperty(const char *name) const
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
for (int i = 0; i < d->propertyCount; ++i) {
- const QMetaProperty p(m, i);
- const char *prop = rawStringData(m, p.data.name());
- if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ const QMetaProperty::Data data = QMetaProperty::getMetaPropertyData(m, i);
+ const char *prop = rawStringData(m, data.name());
+ if (strcmp(name, prop) == 0) {
i += m->propertyOffset();
return i;
}
@@ -1185,8 +1271,8 @@ bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
while (*s2++ != '(') { }
if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
return true; // exact match
- int s1len = qstrlen(s1);
- int s2len = qstrlen(s2);
+ const auto s1len = qstrlen(s1);
+ const auto s2len = qstrlen(s2);
if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
return true; // method has less args
return false;
@@ -1305,69 +1391,82 @@ QByteArray QMetaObject::normalizedSignature(const char *method)
return result;
}
-enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
-
-/*
- Returns the signatures of all methods whose name matches \a nonExistentMember,
- or an empty QByteArray if there are no matches.
-*/
-static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, const char *nonExistentMember)
+Q_DECL_COLD_FUNCTION static inline bool
+printMethodNotFoundWarning(const QMetaObject *meta, QByteArrayView name, qsizetype paramCount,
+ const char *const *names,
+ const QtPrivate::QMetaTypeInterface * const *metaTypes)
{
+ // now find the candidates we couldn't use
QByteArray candidateMessage;
- // Prevent full string comparison in every iteration.
- const QByteArray memberByteArray = nonExistentMember;
- for (int i = 0; i < metaObject->methodCount(); ++i) {
- const QMetaMethod method = metaObject->method(i);
- if (method.name() == memberByteArray)
+ for (int i = 0; i < meta->methodCount(); ++i) {
+ const QMetaMethod method = meta->method(i);
+ if (method.name() == name)
candidateMessage += " " + method.methodSignature() + '\n';
}
if (!candidateMessage.isEmpty()) {
candidateMessage.prepend("\nCandidates are:\n");
candidateMessage.chop(1);
}
- return candidateMessage;
+
+ QVarLengthArray<char, 512> sig;
+ for (qsizetype i = 1; i < paramCount; ++i) {
+ if (names[i])
+ sig.append(names[i], qstrlen(names[i]));
+ else
+ sig.append(metaTypes[i]->name, qstrlen(metaTypes[i]->name));
+ sig.append(',');
+ }
+ if (paramCount != 1)
+ sig.resize(sig.size() - 1);
+
+ qWarning("QMetaObject::invokeMethod: No such method %s::%.*s(%.*s)%.*s",
+ meta->className(), int(name.size()), name.constData(),
+ int(sig.size()), sig.constData(),
+ int(candidateMessage.size()), candidateMessage.constData());
+ return false;
}
/*!
+ \fn template <typename ReturnArg, typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... args)
+ \fn template <typename ReturnArg, typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... args)
+ \fn template <typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, Args &&... args)
+ \fn template <typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, Args &&... args)
+ \since 6.5
\threadsafe
Invokes the \a member (a signal or a slot name) on the object \a
obj. Returns \c true if the member could be invoked. Returns \c false
if there is no such member or the parameters did not match.
- The invocation can be either synchronous or asynchronous,
- depending on \a type:
+ For the overloads with a QTemplatedMetaMethodReturnArgument parameter, the
+ return value of the \a member function call is placed in \a ret. For the
+ overloads without such a member, the return value of the called function
+ (if any) will be discarded. QTemplatedMetaMethodReturnArgument is an
+ internal type you should not use directly. Instead, use the qReturnArg()
+ function.
+
+ The overloads with a Qt::ConnectionType \a type parameter allow explicitly
+ selecting whether the invocation will be synchronous or not:
\list
- \li If \a type is Qt::DirectConnection, the member will be invoked immediately.
+ \li If \a type is Qt::DirectConnection, the member will be invoked immediately
+ in the current thread.
- \li If \a type is Qt::QueuedConnection,
- a QEvent will be sent and the member is invoked as soon as the application
- enters the main event loop.
+ \li If \a type is Qt::QueuedConnection, a QEvent will be sent and the
+ member is invoked as soon as the application enters the event loop in the
+ thread that the \a obj was created in or was moved to.
\li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
the same way as for Qt::QueuedConnection, except that the current thread
will block until the event is delivered. Using this connection type to
communicate between objects in the same thread will lead to deadlocks.
- \li If \a type is Qt::AutoConnection, the member is invoked
- synchronously if \a obj lives in the same thread as the
- caller; otherwise it will invoke the member asynchronously.
+ \li If \a type is Qt::AutoConnection, the member is invoked synchronously
+ if \a obj lives in the same thread as the caller; otherwise it will invoke
+ the member asynchronously. This is the behavior of the overloads that do
+ not have the \a type parameter.
\endlist
- The return value of the \a member function call is placed in \a
- ret. If the invocation is asynchronous, the return value cannot
- be evaluated. You can pass up to ten arguments (\a val0, \a val1,
- \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
- and \a val9) to the \a member function.
-
- QGenericArgument and QGenericReturnArgument are internal
- helper classes. Because signals and slots can be dynamically
- invoked, you must enclose the arguments using the Q_ARG() and
- Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
- const reference of that type; Q_RETURN_ARG() takes a type name
- and a non-const reference.
-
You only need to pass the name of the signal or slot to this function,
not the entire signature. For example, to asynchronously invoke
the \l{QThread::quit()}{quit()} slot on a
@@ -1375,8 +1474,62 @@ static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, con
\snippet code/src_corelib_kernel_qmetaobject.cpp 2
+ With asynchronous method invocations, the parameters must be copyable
+ types, because Qt needs to copy the arguments to store them in an event
+ behind the scenes. Since Qt 6.5, this function automatically registers the
+ types being used; however, as a side-effect, it is not possible to make
+ calls using types that are only forward-declared. Additionally, it is not
+ possible to make asynchronous calls that use references to
+ non-const-qualified types as parameters either.
+
+ To synchronously invoke the \c compute(QString, int, double) slot on
+ some arbitrary object \c obj retrieve its return value:
+
+ \snippet code/src_corelib_kernel_qmetaobject.cpp invokemethod-no-macro
+
+ If the "compute" slot does not take exactly one \l QString, one \c int, and
+ one \c double in the specified order, the call will fail. Note how it was
+ necessary to be explicit about the type of the QString, as the character
+ literal is not exactly the right type to match. If the method instead took
+ a \l QStringView, a \l qsizetype, and a \c float, the call would need to be
+ written as:
+
+ \snippet code/src_corelib_kernel_qmetaobject.cpp invokemethod-no-macro-other-types
+
+ The same call can be executed using the Q_ARG() and Q_RETURN_ARG() macros,
+ as in:
+
+ \snippet code/src_corelib_kernel_qmetaobject.cpp 4
+
+ The macros are kept for compatibility with Qt 6.4 and earlier versions, and
+ can be freely mixed with parameters that do not use the macro. They may be
+ necessary in rare situations when calling a method that used a typedef to
+ forward-declared type as a parameter or the return type.
+
+ \sa Q_ARG(), Q_RETURN_ARG(), QMetaMethod::invoke()
+*/
+
+/*!
+ \threadsafe
+ \overload
+ \obsolete [6.5] Please use the variadic overload of this function
+
+ Invokes the \a member (a signal or a slot name) on the object \a
+ obj. Returns \c true if the member could be invoked. Returns \c false
+ if there is no such member or the parameters did not match.
+
+ See the variadic invokeMethod() function for more information. This
+ function should behave the same way as that one, with the following
+ limitations:
+
+ \list
+ \li The number of parameters is limited to 10.
+ \li Parameter names may need to be an exact string match.
+ \li Meta types are not automatically registered.
+ \endlist
+
With asynchronous method invocations, the parameters must be of
- types that are known to Qt's meta-object system, because Qt needs
+ types that are already known to Qt's meta-object system, because Qt needs
to copy the arguments to store them in an event behind the
scenes. If you try to use a queued connection and get the error
message
@@ -1386,14 +1539,6 @@ static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, con
call qRegisterMetaType() to register the data type before you
call invokeMethod().
- To synchronously invoke the \c compute(QString, int, double) slot on
- some arbitrary object \c obj retrieve its return value:
-
- \snippet code/src_corelib_kernel_qmetaobject.cpp 4
-
- If the "compute" slot does not take exactly one QString, one int
- and one double in the specified order, the call will fail.
-
\sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaMethod::invoke()
*/
bool QMetaObject::invokeMethod(QObject *obj,
@@ -1414,58 +1559,70 @@ bool QMetaObject::invokeMethod(QObject *obj,
if (!obj)
return false;
- QVarLengthArray<char, 512> sig;
- int len = qstrlen(member);
- if (len <= 0)
- return false;
- sig.append(member, len);
- sig.append('(');
-
const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
val9.name()};
-
+ const void *parameters[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(),
+ val4.data(), val5.data(), val6.data(), val7.data(), val8.data(),
+ val9.data()};
int paramCount;
for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
- len = qstrlen(typeNames[paramCount]);
- if (len <= 0)
+ if (qstrlen(typeNames[paramCount]) <= 0)
break;
- sig.append(typeNames[paramCount], len);
- sig.append(',');
}
- if (paramCount == 1)
- sig.append(')'); // no parameters
- else
- sig[sig.size() - 1] = ')';
- sig.append('\0');
+ return invokeMethodImpl(obj, member, type, paramCount, parameters, typeNames, nullptr);
+}
- const QMetaObject *meta = obj->metaObject();
- int idx = meta->indexOfMethod(sig.constData());
- if (idx < 0) {
- QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
- idx = meta->indexOfMethod(norm.constData());
- }
+bool QMetaObject::invokeMethodImpl(QObject *obj, const char *member, Qt::ConnectionType type,
+ qsizetype paramCount, const void * const *parameters,
+ const char * const *typeNames,
+ const QtPrivate::QMetaTypeInterface * const *metaTypes)
+{
+ if (!obj)
+ return false;
- if (idx < 0 || idx >= meta->methodCount()) {
- // This method doesn't belong to us; print out a nice warning with candidates.
- qWarning("QMetaObject::invokeMethod: No such method %s::%s%s",
- meta->className(), sig.constData(), findMethodCandidates(meta, member).constData());
+ Q_ASSERT(paramCount >= 1); // includes the return type
+ Q_ASSERT(parameters);
+ Q_ASSERT(typeNames);
+
+ // find the method
+ QByteArrayView name(member);
+ if (name.isEmpty())
return false;
+
+ const QMetaObject *meta = obj->metaObject();
+ for ( ; meta; meta = meta->superClass()) {
+ auto priv = QMetaObjectPrivate::get(meta);
+ for (int i = 0; i < priv->methodCount; ++i) {
+ QMetaMethod m = QMetaMethod::fromRelativeMethodIndex(meta, i);
+ if (m.parameterCount() != (paramCount - 1))
+ continue;
+ if (name != stringDataView(meta, m.data.name()))
+ continue;
+
+ // attempt to call
+ QMetaMethodPrivate::InvokeFailReason r =
+ QMetaMethodPrivate::invokeImpl(m, obj, type, paramCount, parameters,
+ typeNames, metaTypes);
+ if (int(r) <= 0)
+ return r == QMetaMethodPrivate::InvokeFailReason::None;
+ }
}
- QMetaMethod method = meta->method(idx);
- return method.invoke(obj, type, ret,
- val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+
+ // This method doesn't belong to us; print out a nice warning with candidates.
+ return printMethodNotFoundWarning(obj->metaObject(), name, paramCount, typeNames, metaTypes);
}
-bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret)
+bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ qsizetype parameterCount, const void *const *params, const char *const *names,
+ const QtPrivate::QMetaTypeInterface * const *metaTypes)
{
- struct Holder {
- QtPrivate::QSlotObjectBase *obj;
- ~Holder() { obj->destroyIfLastRef(); }
- } holder = { slot };
- Q_UNUSED(holder);
+ // We don't need this now but maybe we want it later, or we may be able to
+ // share more code between the two invokeMethodImpl() overloads:
+ Q_UNUSED(names);
+ auto slot = QtPrivate::SlotObjUniquePtr(slotObj);
- if (! object)
+ if (! object) // ### only if the slot requires the object + not queued?
return false;
Qt::HANDLE currentThreadId = QThread::currentThreadId();
@@ -1477,8 +1634,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
if (type == Qt::AutoConnection)
type = receiverInSameThread ? Qt::DirectConnection : Qt::QueuedConnection;
- void *argv[] = { ret };
-
+ void **argv = const_cast<void **>(params);
if (type == Qt::DirectConnection) {
slot->call(object, argv);
} else if (type == Qt::QueuedConnection) {
@@ -1487,15 +1643,23 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
"queued connections");
return false;
}
+ auto event = std::make_unique<QMetaCallEvent>(std::move(slot), nullptr, -1, parameterCount);
+ void **args = event->args();
+ QMetaType *types = event->types();
+
+ for (int i = 1; i < parameterCount; ++i) {
+ types[i] = QMetaType(metaTypes[i]);
+ args[i] = types[i].create(argv[i]);
+ }
- QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, 1));
+ QCoreApplication::postEvent(object, event.release());
} else if (type == Qt::BlockingQueuedConnection) {
#if QT_CONFIG(thread)
if (receiverInSameThread)
qWarning("QMetaObject::invokeMethod: Dead lock detected");
QSemaphore semaphore;
- QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, argv, &semaphore));
+ QCoreApplication::postEvent(object, new QMetaCallEvent(std::move(slot), nullptr, -1, argv, &semaphore));
semaphore.acquire();
#endif // QT_CONFIG(thread)
} else {
@@ -1518,6 +1682,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument());
\threadsafe
+ \obsolete [6.5] Please use the variadic overload of this function.
\overload invokeMethod()
This overload always invokes the member using the connection type Qt::AutoConnection.
@@ -1537,6 +1702,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
QGenericArgument val9 = QGenericArgument())
\threadsafe
+ \obsolete [6.5] Please use the variadic overload of this function.
\overload invokeMethod()
This overload can be used if the return value of the member is of no interest.
@@ -1556,6 +1722,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
QGenericArgument val9 = QGenericArgument())
\threadsafe
+ \obsolete [6.5] Please use the variadic overload of this function.
\overload invokeMethod()
This overload invokes the member using the connection type Qt::AutoConnection and
@@ -1563,31 +1730,44 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
*/
/*!
- \fn template<typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type, FunctorReturnType *ret)
+ \fn template<typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, FunctorReturnType *ret)
+ \fn template<typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
\since 5.10
-
\threadsafe
- \overload
Invokes the \a function in the event loop of \a context. \a function can be a functor
or a pointer to a member function. Returns \c true if the function could be invoked.
Returns \c false if there is no such function or the parameters did not match.
The return value of the function call is placed in \a ret.
+
+ If \a type is set, then the function is invoked using that connection type. Otherwise,
+ Qt::AutoConnection will be used.
*/
/*!
- \fn template<typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor function, FunctorReturnType *ret)
-
- \since 5.10
+ \fn template<typename Functor, typename FunctorReturnType, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments)
+ \fn template<typename Functor, typename FunctorReturnType, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments)
+ \fn template<typename Functor, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, Args &&...arguments)
+ \fn template<typename Functor, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Args &&...arguments)
+ \since 6.7
\threadsafe
- \overload
- Invokes the \a function in the event loop of \a context using the connection type Qt::AutoConnection.
- \a function can be a functor or a pointer to a member function. Returns \c true if the function could
- be invoked. Returns \c false if there is no such member or the parameters did not match.
- The return value of the function call is placed in \a ret.
+ Invokes the \a function with \a arguments in the event loop of \a context.
+ \a function can be a functor or a pointer to a member function. Returns
+ \c true if the function could be invoked. The return value of the
+ function call is placed in \a ret. The object used for the \a ret argument
+ should be obtained by passing your object to qReturnArg(). For example:
+
+ \badcode
+ MyClass *obj = ...;
+ int result = 0;
+ QMetaObject::invokeMethod(obj, &MyClass::myMethod, qReturnArg(result), parameter);
+ \endcode
+
+ If \a type is set, then the function is invoked using that connection type.
+ Otherwise, Qt::AutoConnection will be used.
*/
/*!
@@ -1603,6 +1783,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
*/
/*!
+ \fn QMetaObject::Connection::swap(Connection &other)
+ \since 5.15
+
+ Swaps this Connection instance with \a other. This operation is very fast
+ and never fails.
+*/
+
+/*!
\class QMetaMethod
\inmodule QtCore
@@ -1610,6 +1798,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
function.
\ingroup objectmodel
+ \compares equality
A QMetaMethod has a methodType(), a methodSignature(), a list of
parameterTypes() and parameterNames(), a return typeName(), a
@@ -1637,21 +1826,19 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
invoked), otherwise returns \c false.
*/
-/*! \fn bool operator==(const QMetaMethod &m1, const QMetaMethod &m2)
+/*! \fn bool QMetaMethod::operator==(const QMetaMethod &lhs, const QMetaMethod &rhs)
\since 5.0
- \relates QMetaMethod
\overload
- Returns \c true if method \a m1 is equal to method \a m2,
+ Returns \c true if method \a lhs is equal to method \a rhs,
otherwise returns \c false.
*/
-/*! \fn bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2)
+/*! \fn bool QMetaMethod::operator!=(const QMetaMethod &lhs, const QMetaMethod &rhs)
\since 5.0
- \relates QMetaMethod
\overload
- Returns \c true if method \a m1 is not equal to method \a m2,
+ Returns \c true if method \a lhs is not equal to method \a rhs,
otherwise returns \c false.
*/
@@ -1739,7 +1926,7 @@ const char *QMetaMethodPrivate::rawReturnTypeName() const
if (typeInfo & IsUnresolvedType)
return rawStringData(mobj, typeInfo & TypeNameIndexMask);
else
- return QMetaType::typeName(typeInfo);
+ return QMetaType(typeInfo).name();
}
int QMetaMethodPrivate::returnType() const
@@ -1753,6 +1940,35 @@ int QMetaMethodPrivate::parameterCount() const
return data.argc();
}
+inline void
+QMetaMethodPrivate::checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface,
+ int index) const
+{
+ uint typeInfo = parameterTypeInfo(index);
+ QMetaType mt(iface);
+ if (iface) {
+ if ((typeInfo & IsUnresolvedType) == 0)
+ Q_ASSERT(mt.id() == int(typeInfo & TypeNameIndexMask));
+ Q_ASSERT(mt.name());
+ } else {
+ // The iface can only be null for a parameter if that parameter is a
+ // const-ref to a forward-declared type. Since primitive types are
+ // never incomplete, we can assert it's not one of them.
+
+#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME) \
+ Q_ASSERT(typeInfo != QMetaType::TYPE);
+ QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ASSERT_NOT_PRIMITIVE_TYPE)
+#undef ASSERT_NOT_PRIMITIVE_TYPE
+ Q_ASSERT(typeInfo != QMetaType::QObjectStar);
+
+ // Prior to Qt 6.4 we failed to record void and void*
+ if (priv(mobj->d.data)->revision >= 11) {
+ Q_ASSERT(typeInfo != QMetaType::Void);
+ Q_ASSERT(typeInfo != QMetaType::VoidStar);
+ }
+ }
+}
+
int QMetaMethodPrivate::parametersDataIndex() const
{
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
@@ -1765,6 +1981,29 @@ uint QMetaMethodPrivate::parameterTypeInfo(int index) const
return mobj->d.data[parametersDataIndex() + index];
}
+const QtPrivate::QMetaTypeInterface *QMetaMethodPrivate::returnMetaTypeInterface() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ if (methodType() == QMetaMethod::Constructor)
+ return nullptr; // constructors don't have return types
+
+ const QtPrivate::QMetaTypeInterface *iface = mobj->d.metaTypes[data.metaTypeOffset()];
+ checkMethodMetaTypeConsistency(iface, -1);
+ return iface;
+}
+
+const QtPrivate::QMetaTypeInterface * const *QMetaMethodPrivate::parameterMetaTypeInterfaces() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ int offset = (methodType() == QMetaMethod::Constructor ? 0 : 1);
+ const auto ifaces = &mobj->d.metaTypes[data.metaTypeOffset() + offset];
+
+ for (int i = 0; i < parameterCount(); ++i)
+ checkMethodMetaTypeConsistency(ifaces[i], i);
+
+ return ifaces;
+}
+
int QMetaMethodPrivate::parameterType(int index) const
{
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
@@ -1782,6 +2021,12 @@ void QMetaMethodPrivate::getParameterTypes(int *types) const
}
}
+QByteArray QMetaMethodPrivate::parameterTypeName(int index) const
+{
+ int paramsIndex = parametersDataIndex();
+ return typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + index]).toByteArray();
+}
+
QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
{
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
@@ -1789,8 +2034,10 @@ QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
QList<QByteArray> list;
list.reserve(argc);
int paramsIndex = parametersDataIndex();
- for (int i = 0; i < argc; ++i)
- list += typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
+ for (int i = 0; i < argc; ++i) {
+ QByteArrayView name = typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
+ list.emplace_back(name.toByteArray());
+ }
return list;
}
@@ -1814,10 +2061,17 @@ QByteArray QMetaMethodPrivate::tag() const
int QMetaMethodPrivate::ownMethodIndex() const
{
- // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
+ // recompute the methodIndex by reversing the arithmetic in QMetaObject::method()
return ( data.d - mobj->d.data - priv(mobj->d.data)->methodData)/Data::Size;
}
+int QMetaMethodPrivate::ownConstructorMethodIndex() const
+{
+ // recompute the methodIndex by reversing the arithmetic in QMetaObject::constructor()
+ Q_ASSERT(methodType() == Constructor);
+ return ( data.d - mobj->d.data - priv(mobj->d.data)->constructorData)/Data::Size;
+}
+
/*!
\since 5.0
@@ -1963,6 +2217,20 @@ QList<QByteArray> QMetaMethod::parameterTypes() const
}
/*!
+ \since 6.0
+ Returns the name of the type at position \a index
+ If there is no parameter at \a index, returns an empty QByteArray
+
+ \sa parameterNames()
+ */
+QByteArray QMetaMethod::parameterTypeName(int index) const
+{
+ if (!mobj || index < 0 || index >= parameterCount())
+ return {};
+ return QMetaMethodPrivate::get(this)->parameterTypeName(index);
+}
+
+/*!
Returns a list of parameter names.
\sa parameterTypes(), methodSignature()
@@ -2007,10 +2275,9 @@ const char *QMetaMethod::typeName() const
differently, and treat them according to the specific needs of your
application.
- \note Since Qt 5.0, \c moc expands preprocessor macros, so it is necessary
+ \note \c moc expands preprocessor macros, so it is necessary
to surround the definition with \c #ifndef \c Q_MOC_RUN, as shown in the
- example above. This was not required in Qt 4. The code as shown above works
- with Qt 4 too.
+ example above.
*/
const char *QMetaMethod::tag() const
{
@@ -2074,6 +2341,23 @@ int QMetaMethod::revision() const
}
/*!
+ \since 6.2
+
+ Returns whether the method is const qualified.
+
+ \note This method might erroneously return \c false for a const method
+ if it belongs to a library compiled against an older version of Qt.
+ */
+bool QMetaMethod::isConst() const
+{
+ if (!mobj)
+ return false;
+ if (QMetaObjectPrivate::get(mobj)->revision < 10)
+ return false;
+ return data.flags() & MethodIsConst;
+}
+
+/*!
Returns the access specification of this method (private,
protected, or public).
@@ -2107,7 +2391,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const
\since 5.0
Returns the meta-method that corresponds to the given \a signal, or an
- invalid QMetaMethod if \a signal is not a signal of the class.
+ invalid QMetaMethod if \a signal is \c{nullptr} or not a signal of the class.
Example:
@@ -2135,36 +2419,43 @@ QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **si
}
/*!
+ \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invoke(QObject *obj, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
+ \fn template <typename... Args> bool QMetaMethod::invoke(QObject *obj, Qt::ConnectionType type, Args &&... arguments) const
+ \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invoke(QObject *obj, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
+ \fn template <typename... Args> bool QMetaMethod::invoke(QObject *obj, Args &&... arguments) const
+ \since 6.5
+
Invokes this method on the object \a object. Returns \c true if the member could be invoked.
Returns \c false if there is no such member or the parameters did not match.
- The invocation can be either synchronous or asynchronous, depending on the
- \a connectionType:
+ For the overloads with a QTemplatedMetaMethodReturnArgument parameter, the
+ return value of the \a member function call is placed in \a ret. For the
+ overloads without such a member, the return value of the called function
+ (if any) will be discarded. QTemplatedMetaMethodReturnArgument is an
+ internal type you should not use directly. Instead, use the qReturnArg()
+ function.
+
+ The overloads with a Qt::ConnectionType \a type parameter allow explicitly
+ selecting whether the invocation will be synchronous or not:
\list
- \li If \a connectionType is Qt::DirectConnection, the member will be invoked immediately.
-
- \li If \a connectionType is Qt::QueuedConnection,
- a QEvent will be posted and the member is invoked as soon as the application
- enters the main event loop.
+ \li If \a type is Qt::DirectConnection, the member will be invoked immediately
+ in the current thread.
- \li If \a connectionType is Qt::AutoConnection, the member is invoked
- synchronously if \a object lives in the same thread as the
- caller; otherwise it will invoke the member asynchronously.
- \endlist
+ \li If \a type is Qt::QueuedConnection, a QEvent will be sent and the
+ member is invoked as soon as the application enters the event loop in the
+ thread the \a obj was created in or was moved to.
- The return value of this method call is placed in \a
- returnValue. If the invocation is asynchronous, the return value cannot
- be evaluated. You can pass up to ten arguments (\a val0, \a val1,
- \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
- and \a val9) to this method call.
+ \li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
+ the same way as for Qt::QueuedConnection, except that the current thread
+ will block until the event is delivered. Using this connection type to
+ communicate between objects in the same thread will lead to deadlocks.
- QGenericArgument and QGenericReturnArgument are internal
- helper classes. Because signals and slots can be dynamically
- invoked, you must enclose the arguments using the Q_ARG() and
- Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
- const reference of that type; Q_RETURN_ARG() takes a type name
- and a non-const reference.
+ \li If \a type is Qt::AutoConnection, the member is invoked synchronously
+ if \a obj lives in the same thread as the caller; otherwise it will invoke
+ the member asynchronously. This is the behavior of the overloads that do
+ not have the \a type parameter.
+ \endlist
To asynchronously invoke the
\l{QPushButton::animateClick()}{animateClick()} slot on a
@@ -2172,6 +2463,56 @@ QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **si
\snippet code/src_corelib_kernel_qmetaobject.cpp 6
+ With asynchronous method invocations, the parameters must be copyable
+ types, because Qt needs to copy the arguments to store them in an event
+ behind the scenes. Since Qt 6.5, this function automatically registers the
+ types being used; however, as a side-effect, it is not possible to make
+ calls using types that are only forward-declared. Additionally, it is not
+ possible to make asynchronous calls that use references to
+ non-const-qualified types as parameters either.
+
+ To synchronously invoke the \c compute(QString, int, double) slot on
+ some arbitrary object \c obj retrieve its return value:
+
+ \snippet code/src_corelib_kernel_qmetaobject.cpp invoke-no-macro
+
+ If the "compute" slot does not take exactly one \l QString, one \c int, and
+ one \c double in the specified order, the call will fail. Note how it was
+ necessary to be explicit about the type of the QString, as the character
+ literal is not exactly the right type to match. If the method instead took
+ a \l QByteArray, a \l qint64, and a \c{long double}, the call would need to be
+ written as:
+
+ \snippet code/src_corelib_kernel_qmetaobject.cpp invoke-no-macro-other-types
+
+ The same call can be executed using the Q_ARG() and Q_RETURN_ARG() macros,
+ as in:
+
+ \snippet code/src_corelib_kernel_qmetaobject.cpp 8
+
+ \warning this method will not test the validity of the arguments: \a object
+ must be an instance of the class of the QMetaObject of which this QMetaMethod
+ has been constructed with.
+
+ \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
+*/
+
+/*!
+ \obsolete [6.5] Please use the variadic overload of this function
+
+ Invokes this method on the object \a object. Returns \c true if the member could be invoked.
+ Returns \c false if there is no such member or the parameters did not match.
+
+ See the variadic invokeMethod() function for more information. This
+ function should behave the same way as that one, with the following
+ limitations:
+
+ \list
+ \li The number of parameters is limited to 10.
+ \li Parameter names may need to be an exact string match.
+ \li Meta types are not automatically registered.
+ \endlist
+
With asynchronous method invocations, the parameters must be of
types that are known to Qt's meta-object system, because Qt needs
to copy the arguments to store them in an event behind the
@@ -2183,22 +2524,9 @@ QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **si
call qRegisterMetaType() to register the data type before you
call QMetaMethod::invoke().
- To synchronously invoke the \c compute(QString, int, double) slot on
- some arbitrary object \c obj retrieve its return value:
-
- \snippet code/src_corelib_kernel_qmetaobject.cpp 8
-
- QMetaObject::normalizedSignature() is used here to ensure that the format
- of the signature is what invoke() expects. E.g. extra whitespace is
- removed.
-
- If the "compute" slot does not take exactly one QString, one int
- and one double in the specified order, the call will fail.
-
- \warning this method will not test the validity of the arguments: \a object
- must be an instance of the class of the QMetaObject of which this QMetaMethod
- has been constructed with. The arguments must have the same type as the ones
- expected by the method, else, the behaviour is undefined.
+ \warning In addition to the limitations of the variadic invoke() overload,
+ the arguments must have the same type as the ones expected by the method,
+ else, the behavior is undefined.
\sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
*/
@@ -2219,23 +2547,6 @@ bool QMetaMethod::invoke(QObject *object,
if (!object || !mobj)
return false;
- Q_ASSERT(mobj->cast(object));
-
- // check return type
- if (returnValue.data()) {
- const char *retType = typeName();
- if (qstrcmp(returnValue.name(), retType) != 0) {
- // normalize the return value as well
- QByteArray normalized = QMetaObject::normalizedType(returnValue.name());
- if (qstrcmp(normalized.constData(), retType) != 0) {
- // String comparison failed, try compare the metatype.
- int t = returnType();
- if (t == QMetaType::UnknownType || t != QMetaType::type(normalized))
- return false;
- }
- }
- }
-
// check argument count (we don't allow invoking a method if given too few arguments)
const char *typeNames[] = {
returnValue.name(),
@@ -2250,27 +2561,184 @@ bool QMetaMethod::invoke(QObject *object,
val8.name(),
val9.name()
};
+ void *param[] = {
+ returnValue.data(),
+ val0.data(),
+ val1.data(),
+ val2.data(),
+ val3.data(),
+ val4.data(),
+ val5.data(),
+ val6.data(),
+ val7.data(),
+ val8.data(),
+ val9.data()
+ };
+
int paramCount;
for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
if (qstrlen(typeNames[paramCount]) <= 0)
break;
}
- if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount())
+ return invokeImpl(*this, object, connectionType, paramCount, param, typeNames, nullptr);
+}
+
+bool QMetaMethod::invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType connectionType,
+ qsizetype paramCount, const void *const *parameters,
+ const char *const *typeNames,
+ const QtPrivate::QMetaTypeInterface *const *metaTypes)
+{
+ if (!target || !self.mobj)
return false;
+ QMetaMethodPrivate::InvokeFailReason r =
+ QMetaMethodPrivate::invokeImpl(self, target, connectionType, paramCount, parameters,
+ typeNames, metaTypes);
+ if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
+ return true;
+
+ if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
+ int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
+ qWarning("QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
+ n, typeNames[n + 1] ? typeNames[n + 1] : metaTypes[n + 1]->name,
+ self.mobj->className(), self.methodSignature().constData());
+ }
+ if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
+ qWarning("QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
+ int(paramCount), self.mobj->className(), self.methodSignature().constData());
+ }
+ return false;
+}
- Qt::HANDLE currentThreadId = QThread::currentThreadId();
- QThread *objectThread = object->thread();
- bool receiverInSameThread = false;
- if (objectThread)
- receiverInSameThread = currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
+auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
+ Qt::ConnectionType connectionType,
+ qsizetype paramCount, const void *const *parameters,
+ const char *const *typeNames,
+ const QtPrivate::QMetaTypeInterface *const *metaTypes) -> InvokeFailReason
+{
+ auto object = static_cast<QObject *>(target);
+ auto priv = QMetaMethodPrivate::get(&self);
+ constexpr bool MetaTypesAreOptional = QT_VERSION < QT_VERSION_CHECK(7, 0, 0);
+ auto methodMetaTypes = priv->parameterMetaTypeInterfaces();
+ auto param = const_cast<void **>(parameters);
+
+ Q_ASSERT(priv->mobj);
+ Q_ASSERT(self.methodType() == Constructor || object);
+ Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
+ priv->mobj->cast(object));
+ Q_ASSERT(paramCount >= 1); // includes the return type
+ Q_ASSERT(parameters);
+ Q_ASSERT(typeNames);
+ Q_ASSERT(MetaTypesAreOptional || metaTypes);
+
+ if ((paramCount - 1) < qsizetype(priv->data.argc()))
+ return InvokeFailReason::TooFewArguments;
+
+ // 0 is the return type, 1 is the first formal parameter
+ auto checkTypesAreCompatible = [=](int idx) {
+ uint typeInfo = priv->parameterTypeInfo(idx - 1);
+ QByteArrayView userTypeName(typeNames[idx] ? typeNames[idx] : metaTypes[idx]->name);
+
+ if ((typeInfo & IsUnresolvedType) == 0) {
+ // this is a built-in type
+ if (MetaTypesAreOptional && !metaTypes)
+ return int(typeInfo) == QMetaType::fromName(userTypeName).id();
+ return int(typeInfo) == metaTypes[idx]->typeId;
+ }
- // check connection type
- if (connectionType == Qt::AutoConnection) {
- connectionType = receiverInSameThread
- ? Qt::DirectConnection
- : Qt::QueuedConnection;
+ QByteArrayView methodTypeName = stringDataView(priv->mobj, typeInfo & TypeNameIndexMask);
+ if ((MetaTypesAreOptional && !metaTypes) || !metaTypes[idx]) {
+ // compatibility call, compare strings
+ if (methodTypeName == userTypeName)
+ return true;
+
+ // maybe the user type needs normalization
+ QByteArray normalized = normalizeTypeInternal(userTypeName.begin(), userTypeName.end());
+ return methodTypeName == normalized;
+ }
+
+ QMetaType userType(metaTypes[idx]);
+ Q_ASSERT(userType.isValid());
+ if (QMetaType(methodMetaTypes[idx - 1]) == userType)
+ return true;
+
+ // if the parameter type was NOT only forward-declared, it MUST have
+ // matched
+ if (methodMetaTypes[idx - 1])
+ return false;
+
+ // resolve from the name moc stored for us
+ QMetaType resolved = QMetaType::fromName(methodTypeName);
+ return resolved == userType;
+ };
+
+ // force all types to be registered, just in case
+ for (qsizetype i = 0; metaTypes && i < paramCount; ++i)
+ QMetaType(metaTypes[i]).registerType();
+
+ // check formal parameters first (overload set)
+ for (qsizetype i = 1; i < paramCount; ++i) {
+ if (!checkTypesAreCompatible(i))
+ return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
+ }
+
+ // handle constructors first
+ if (self.methodType() == Constructor) {
+ if (object) {
+ qWarning("QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
+ self.methodSignature().constData(), object);
+ return InvokeFailReason::ConstructorCallOnObject;
+ }
+
+ if (!parameters[0]) {
+ qWarning("QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
+ self.methodSignature().constData());
+ return InvokeFailReason::ConstructorCallWithoutResult;
+ }
+
+ if (!MetaTypesAreOptional || metaTypes) {
+ if (metaTypes[0]->typeId != QMetaType::QObjectStar) {
+ qWarning("QMetaMethod::invokeMethod: cannot convert QObject* to %s on constructor call %s",
+ metaTypes[0]->name, self.methodSignature().constData());
+ return InvokeFailReason::ReturnTypeMismatch;
+ }
+ }
+
+ int idx = priv->ownConstructorMethodIndex();
+ if (priv->mobj->static_metacall(QMetaObject::CreateInstance, idx, param) >= 0)
+ return InvokeFailReason::ConstructorCallFailed;
+ return {};
+ }
+
+ // regular type - check return type
+ if (parameters[0]) {
+ if (!checkTypesAreCompatible(0)) {
+ const char *retType = typeNames[0] ? typeNames[0] : metaTypes[0]->name;
+ qWarning("QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
+ " cannot convert from %s to %s during invocation",
+ priv->mobj->className(), priv->methodSignature().constData(),
+ priv->rawReturnTypeName(), retType);
+ return InvokeFailReason::ReturnTypeMismatch;
+ }
}
+ Qt::HANDLE currentThreadId = nullptr;
+ QThread *objectThread = nullptr;
+ auto receiverInSameThread = [&]() {
+ if (!currentThreadId) {
+ currentThreadId = QThread::currentThreadId();
+ objectThread = object->thread();
+ }
+ if (objectThread)
+ return currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
+ return false;
+ };
+
+ // check connection type
+ if (connectionType == Qt::AutoConnection)
+ connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
+ else if (connectionType == Qt::ConnectionType(-1))
+ connectionType = Qt::DirectConnection;
+
#if !QT_CONFIG(thread)
if (connectionType == Qt::BlockingQueuedConnection) {
connectionType = Qt::DirectConnection;
@@ -2278,69 +2746,53 @@ bool QMetaMethod::invoke(QObject *object,
#endif
// invoke!
- void *param[] = {
- returnValue.data(),
- val0.data(),
- val1.data(),
- val2.data(),
- val3.data(),
- val4.data(),
- val5.data(),
- val6.data(),
- val7.data(),
- val8.data(),
- val9.data()
- };
- int idx_relative = QMetaMethodPrivate::get(this)->ownMethodIndex();
- int idx_offset = mobj->methodOffset();
- Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6);
- QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall;
+ int idx_relative = priv->ownMethodIndex();
+ int idx_offset = priv->mobj->methodOffset();
+ QObjectPrivate::StaticMetaCallFunction callFunction = priv->mobj->d.static_metacall;
if (connectionType == Qt::DirectConnection) {
- if (callFunction) {
+ if (callFunction)
callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
- return true;
- } else {
- return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) < 0;
- }
+ else if (QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) >= 0)
+ return InvokeFailReason::CallViaVirtualFailed;
} else if (connectionType == Qt::QueuedConnection) {
- if (returnValue.data()) {
+ if (parameters[0]) {
qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
"queued connections");
- return false;
+ return InvokeFailReason::CouldNotQueueParameter;
}
- QScopedPointer<QMetaCallEvent> event(new QMetaCallEvent(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount));
- int *types = event->types();
+ auto event = std::make_unique<QMetaCallEvent>(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount);
+ QMetaType *types = event->types();
void **args = event->args();
- int argIndex = 0;
+ // fill in the meta types first
for (int i = 1; i < paramCount; ++i) {
- types[i] = QMetaType::type(typeNames[i]);
- if (types[i] == QMetaType::UnknownType && param[i]) {
- // Try to register the type and try again before reporting an error.
- void *argv[] = { &types[i], &argIndex };
- QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType,
- idx_relative + idx_offset, argv);
- if (types[i] == -1) {
- qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
- typeNames[i]);
- return false;
- }
- }
- if (types[i] != QMetaType::UnknownType) {
- args[i] = QMetaType::create(types[i], param[i]);
- ++argIndex;
+ types[i] = QMetaType(methodMetaTypes[i - 1]);
+ if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
+ types[i] = QMetaType(metaTypes[i]);
+ if (!types[i].iface())
+ types[i] = priv->parameterMetaType(i - 1);
+ if (!types[i].iface() && typeNames[i])
+ types[i] = QMetaType::fromName(typeNames[i]);
+ if (!types[i].iface()) {
+ qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
+ typeNames[i]);
+ return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
}
}
- QCoreApplication::postEvent(object, event.take());
+ // now create copies of our parameters using those meta types
+ for (int i = 1; i < paramCount; ++i)
+ args[i] = types[i].create(parameters[i]);
+
+ QCoreApplication::postEvent(object, event.release());
} else { // blocking queued connection
#if QT_CONFIG(thread)
- if (receiverInSameThread) {
- qWarning("QMetaMethod::invoke: Dead lock detected in "
- "BlockingQueuedConnection: Receiver is %s(%p)",
- mobj->className(), object);
+ if (receiverInSameThread()) {
+ qWarning("QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
+ "Receiver is %s(%p)", priv->mobj->className(), object);
+ return InvokeFailReason::DeadLockDetected;
}
QSemaphore semaphore;
@@ -2349,7 +2801,7 @@ bool QMetaMethod::invoke(QObject *object,
semaphore.acquire();
#endif // QT_CONFIG(thread)
}
- return true;
+ return {};
}
/*! \fn bool QMetaMethod::invoke(QObject *object,
@@ -2364,6 +2816,7 @@ bool QMetaMethod::invoke(QObject *object,
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const
+ \obsolete [6.5] Please use the variadic overload of this function
\overload invoke()
This overload always invokes this method using the connection type Qt::AutoConnection.
@@ -2381,7 +2834,7 @@ bool QMetaMethod::invoke(QObject *object,
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const
-
+ \obsolete [6.5] Please use the variadic overload of this function
\overload invoke()
This overload can be used if the return value of the member is of no interest.
@@ -2399,7 +2852,7 @@ bool QMetaMethod::invoke(QObject *object,
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const
-
+ \obsolete [6.5] Please use the variadic overload of this function
\overload invoke()
This overload invokes this method using the
@@ -2407,7 +2860,9 @@ bool QMetaMethod::invoke(QObject *object,
*/
/*!
- \since 5.5
+ \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invokeOnGadget(void *gadget, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
+ \fn template <typename... Args> bool QMetaMethod::invokeOnGadget(void *gadget, Args &&... arguments) const
+ \since 6.5
Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
Returns \c false if there is no such member or the parameters did not match.
@@ -2416,15 +2871,39 @@ bool QMetaMethod::invoke(QObject *object,
The invocation is always synchronous.
- The return value of this method call is placed in \a
- returnValue. You can pass up to ten arguments (\a val0, \a val1,
- \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
- and \a val9) to this method call.
+ For the overload with a QTemplatedMetaMethodReturnArgument parameter, the
+ return value of the \a member function call is placed in \a ret. For the
+ overload without it, the return value of the called function (if any) will
+ be discarded. QTemplatedMetaMethodReturnArgument is an internal type you
+ should not use directly. Instead, use the qReturnArg() function.
\warning this method will not test the validity of the arguments: \a gadget
must be an instance of the class of the QMetaObject of which this QMetaMethod
- has been constructed with. The arguments must have the same type as the ones
- expected by the method, else, the behavior is undefined.
+ has been constructed with.
+
+ \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
+*/
+
+/*!
+ \since 5.5
+ \obsolete [6.5] Please use the variadic overload of this function
+
+ Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
+ Returns \c false if there is no such member or the parameters did not match.
+
+ See the variadic invokeMethod() function for more information. This
+ function should behave the same way as that one, with the following
+ limitations:
+
+ \list
+ \li The number of parameters is limited to 10.
+ \li Parameter names may need to be an exact string match.
+ \li Meta types are not automatically registered.
+ \endlist
+
+ \warning In addition to the limitations of the variadic invoke() overload,
+ the arguments must have the same type as the ones expected by the method,
+ else, the behavior is undefined.
\sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
*/
@@ -2453,7 +2932,7 @@ bool QMetaMethod::invokeOnGadget(void *gadget,
if (qstrcmp(normalized.constData(), retType) != 0) {
// String comparison failed, try compare the metatype.
int t = returnType();
- if (t == QMetaType::UnknownType || t != QMetaType::type(normalized))
+ if (t == QMetaType::UnknownType || t != QMetaType::fromName(normalized).id())
return false;
}
}
@@ -2518,6 +2997,7 @@ bool QMetaMethod::invokeOnGadget(void *gadget,
QGenericArgument val9 = QGenericArgument()) const
\overload
+ \obsolete [6.5] Please use the variadic overload of this function
\since 5.5
This overload invokes this method for a \a gadget and ignores return values.
@@ -2587,7 +3067,7 @@ const char *QMetaEnum::name() const
Returns the enum name of the flag (without the scope).
For example, the Qt::AlignmentFlag flag has \c
- AlignmentFlag as the enum name, but \c Alignment as as the type name.
+ AlignmentFlag as the enum name, but \c Alignment as the type name.
Non flag enums has the same type and enum names.
Enum names have the same scope as the type name.
@@ -2603,6 +3083,32 @@ const char *QMetaEnum::enumName() const
}
/*!
+ Returns the meta type of the enum.
+
+ If the QMetaObject that this enum is part of was generated with Qt 6.5 or
+ earlier, this will be an invalid meta type.
+
+ \note This is the meta type of the enum itself, not of its underlying
+ integral type. You can retrieve the meta type of the underlying type of the
+ enum using \l{QMetaType::underlyingType()}.
+
+ \since 6.6
+*/
+QMetaType QMetaEnum::metaType() const
+{
+ if (!mobj)
+ return {};
+
+ const QMetaObjectPrivate *p = priv(mobj->d.data);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ if (p->revision < 12)
+ QMetaType();
+#endif
+
+ return QMetaType(mobj->d.metaTypes[data.index(mobj) + p->propertyCount]);
+}
+
+/*!
Returns the number of keys.
\sa key()
@@ -2638,12 +3144,11 @@ int QMetaEnum::value(int index) const
{
if (!mobj)
return 0;
- if (index >= 0 && index < int(data.keyCount()))
- return mobj->d.data[data.data() + 2*index + 1];
+ if (index >= 0 && index < int(data.keyCount()))
+ return mobj->d.data[data.data() + 2 * index + 1];
return -1;
}
-
/*!
Returns \c true if this enumerator is used as a flag; otherwise returns
false.
@@ -2683,7 +3188,34 @@ bool QMetaEnum::isScoped() const
*/
const char *QMetaEnum::scope() const
{
- return mobj ? objectClassName(mobj) : nullptr;
+ return mobj ? mobj->className() : nullptr;
+}
+
+static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
+{
+ const QByteArrayView className = e->enclosingMetaObject()->className();
+
+ // Typical use-cases:
+ // a) Unscoped: namespace N { class C { enum E { F }; }; }; key == "N::C::F"
+ // b) Scoped: namespace N { class C { enum class E { F }; }; }; key == "N::C::E::F"
+ if (scope == className)
+ return true;
+
+ // Not using name() because if isFlag() is true, we want the actual name
+ // of the enum, e.g. "MyFlag", not "MyFlags", e.g.
+ // enum MyFlag { F1, F2 }; Q_DECLARE_FLAGS(MyFlags, MyFlag);
+ QByteArrayView name = e->enumName();
+
+ // Match fully qualified enumerator in unscoped enums, key == "N::C::E::F"
+ // equivalent to use-case "a" above
+ const auto sz = className.size();
+ if (scope.size() == sz + qsizetype(qstrlen("::")) + name.size()
+ && scope.startsWith(className)
+ && scope.sliced(sz, 2) == "::"
+ && scope.sliced(sz + 2) == name)
+ return true;
+
+ return false;
}
/*!
@@ -2703,22 +3235,14 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
*ok = false;
if (!mobj || !key)
return -1;
- uint scope = 0;
- const char *qualified_key = key;
- const char *s = key + qstrlen(key);
- while (s > key && *s != ':')
- --s;
- if (s > key && *(s-1)==':') {
- scope = s - key - 1;
- key += scope + 2;
- }
+
+ const auto [scope, enumKey] = parse_scope(QLatin1StringView(key));
for (int i = 0; i < int(data.keyCount()); ++i) {
- const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
- if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
- && strcmp(key, rawStringData(mobj, mobj->d.data[data.data() + 2*i])) == 0) {
+ if ((!scope || isScopeMatch(*scope, this))
+ && enumKey == stringDataView(mobj, mobj->d.data[data.data() + 2 * i])) {
if (ok != nullptr)
*ok = true;
- return mobj->d.data[data.data() + 2*i + 1];
+ return mobj->d.data[data.data() + 2 * i + 1];
}
}
return -1;
@@ -2732,16 +3256,61 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
\sa isFlag(), valueToKeys()
*/
-const char* QMetaEnum::valueToKey(int value) const
+const char *QMetaEnum::valueToKey(int value) const
{
if (!mobj)
return nullptr;
for (int i = 0; i < int(data.keyCount()); ++i)
- if (value == (int)mobj->d.data[data.data() + 2*i + 1])
- return rawStringData(mobj, mobj->d.data[data.data() + 2*i]);
+ if (value == (int)mobj->d.data[data.data() + 2 * i + 1])
+ return rawStringData(mobj, mobj->d.data[data.data() + 2 * i]);
return nullptr;
}
+static bool parseEnumFlags(QByteArrayView v, QVarLengthArray<QByteArrayView, 10> &list)
+{
+ v = v.trimmed();
+ if (v.empty()) {
+ qWarning("QMetaEnum::keysToValue: empty keys string.");
+ return false;
+ }
+
+ qsizetype sep = v.indexOf('|', 0);
+ if (sep == 0) {
+ qWarning("QMetaEnum::keysToValue: malformed keys string, starts with '|', \"%s\"",
+ v.constData());
+ return false;
+ }
+
+ if (sep == -1) { // One flag
+ list.push_back(v);
+ return true;
+ }
+
+ if (v.endsWith('|')) {
+ qWarning("QMetaEnum::keysToValue: malformed keys string, ends with '|', \"%s\"",
+ v.constData());
+ return false;
+ }
+
+ const auto begin = v.begin();
+ const auto end = v.end();
+ auto b = begin;
+ for (; b != end && sep != -1; sep = v.indexOf('|', sep)) {
+ list.push_back({b, begin + sep});
+ ++sep; // Skip over '|'
+ b = begin + sep;
+ if (*b == '|') {
+ qWarning("QMetaEnum::keysToValue: malformed keys string, has two consecutive '|': "
+ "\"%s\"", v.constData());
+ return false;
+ }
+ }
+
+ // The rest of the string
+ list.push_back({b, end});
+ return true;
+}
+
/*!
Returns the value derived from combining together the values of
the \a keys using the OR operator, or -1 if \a keys is not
@@ -2758,44 +3327,56 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
*ok = false;
if (!mobj || !keys)
return -1;
- if (ok != nullptr)
- *ok = true;
- const QString keysString = QString::fromLatin1(keys);
- const auto splitKeys = QStringView{keysString}.split(QLatin1Char('|'));
- if (splitKeys.isEmpty())
- return 0;
- // ### TODO write proper code: do not allocate memory, so we can go nothrow
- int value = 0;
- for (QStringView untrimmed : splitKeys) {
- const QStringView trimmed = untrimmed.trimmed();
- QByteArray qualified_key = trimmed.toLatin1();
- const char *key = qualified_key.constData();
- uint scope = 0;
- const char *s = key + qstrlen(key);
- while (s > key && *s != ':')
- --s;
- if (s > key && *(s-1)==':') {
- scope = s - key - 1;
- key += scope + 2;
- }
- int i;
- for (i = data.keyCount() - 1; i >= 0; --i) {
- const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
- if ((!scope || (className.size() == int(scope) && strncmp(qualified_key.constData(), className.constData(), scope) == 0))
- && strcmp(key, rawStringData(mobj, mobj->d.data[data.data() + 2*i])) == 0) {
- value |= mobj->d.data[data.data() + 2*i + 1];
- break;
- }
- }
- if (i < 0) {
- if (ok != nullptr)
- *ok = false;
- value |= -1;
+
+ auto lookup = [&] (QByteArrayView key) -> std::optional<int> {
+ for (int i = data.keyCount() - 1; i >= 0; --i) {
+ if (key == stringDataView(mobj, mobj->d.data[data.data() + 2*i]))
+ return mobj->d.data[data.data() + 2*i + 1];
}
+ return std::nullopt;
+ };
+
+ int value = 0;
+ QVarLengthArray<QByteArrayView, 10> list;
+ const bool r = parseEnumFlags(QByteArrayView{keys}, list);
+ if (!r)
+ return -1;
+ for (const auto &untrimmed : list) {
+ const auto parsed = parse_scope(untrimmed.trimmed());
+ if (parsed.scope && !isScopeMatch(*parsed.scope, this))
+ return -1; // wrong type name in qualified name
+ if (auto thisValue = lookup(parsed.key))
+ value |= *thisValue;
+ else
+ return -1; // no such enumerator
}
+ if (ok != nullptr)
+ *ok = true;
return value;
}
+namespace
+{
+template <typename String, typename Container, typename Separator>
+void join_reversed(String &s, const Container &c, Separator sep)
+{
+ if (c.empty())
+ return;
+ qsizetype len = qsizetype(c.size()) - 1; // N - 1 separators
+ for (auto &e : c)
+ len += qsizetype(e.size()); // N parts
+ s.reserve(len);
+ bool first = true;
+ for (auto rit = c.rbegin(), rend = c.rend(); rit != rend; ++rit) {
+ const auto &e = *rit;
+ if (!first)
+ s.append(sep);
+ first = false;
+ s.append(e.data(), e.size());
+ }
+}
+} // unnamed namespace
+
/*!
Returns a byte array of '|'-separated keys that represents the
given \a value.
@@ -2807,17 +3388,17 @@ QByteArray QMetaEnum::valueToKeys(int value) const
QByteArray keys;
if (!mobj)
return keys;
+ QVarLengthArray<QByteArrayView, sizeof(int) * CHAR_BIT> parts;
int v = value;
// reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
for (int i = data.keyCount() - 1; i >= 0; --i) {
- int k = mobj->d.data[data.data() + 2*i + 1];
- if ((k != 0 && (v & k) == k ) || (k == value)) {
+ int k = mobj->d.data[data.data() + 2 * i + 1];
+ if ((k != 0 && (v & k) == k) || (k == value)) {
v = v & ~k;
- if (!keys.isEmpty())
- keys.prepend('|');
- keys.prepend(stringData(mobj, mobj->d.data[data.data() + 2*i]));
+ parts.push_back(stringDataView(mobj, mobj->d.data[data.data() + 2 * i]));
}
}
+ join_reversed(keys, parts, '|');
return keys;
}
@@ -2830,15 +3411,19 @@ QMetaEnum::QMetaEnum(const QMetaObject *mobj, int index)
Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->enumeratorCount);
}
+int QMetaEnum::Data::index(const QMetaObject *mobj) const
+{
+ return (d - mobj->d.data - priv(mobj->d.data)->enumeratorData) / Size;
+}
+
/*!
- \fn QMetaEnum QMetaEnum::fromType()
+ \fn template<typename T> QMetaEnum QMetaEnum::fromType()
\since 5.5
Returns the QMetaEnum corresponding to the type in the template parameter.
The enum needs to be declared with Q_ENUM.
*/
-
/*!
\class QMetaProperty
\inmodule QtCore
@@ -2915,24 +3500,22 @@ const char *QMetaProperty::typeName() const
{
if (!mobj)
return nullptr;
- return rawTypeNameFromTypeInfo(mobj, data.type());
+ // TODO: can the metatype be invalid for dynamic metaobjects?
+ if (const auto mt = metaType(); mt.isValid())
+ return mt.name();
+ return typeNameFromTypeInfo(mobj, data.type()).constData();
}
-/*!
+/*! \fn QVariant::Type QMetaProperty::type() const
+ \deprecated
+
Returns this property's type. The return value is one
of the values of the QVariant::Type enumeration.
- \sa userType(), typeName(), name(), metaType()
+ \sa typeName(), name(), metaType()
*/
-QVariant::Type QMetaProperty::type() const
-{
- uint type = userType();
- if (type >= QMetaType::User)
- return QVariant::UserType;
- return QVariant::Type(type);
-}
-/*!
+/*! \fn int QMetaProperty::userType() const
\since 4.2
Returns this property's user type. The return value is one
@@ -2942,12 +3525,15 @@ QVariant::Type QMetaProperty::type() const
\sa type(), QMetaType, typeName(), metaType()
*/
-int QMetaProperty::userType() const
-{
- if (!mobj)
- return QMetaType::UnknownType;
- return QMetaType(mobj->d.metaTypes[data.index(mobj)]).id();
-}
+
+/*! \fn int QMetaProperty::typeId() const
+ \since 6.0
+
+ Returns the storage type of the property. This is
+ the same as metaType().id().
+
+ \sa QMetaType, typeName(), metaType()
+ */
/*!
\since 6.0
@@ -2965,7 +3551,7 @@ QMetaType QMetaProperty::metaType() const
int QMetaProperty::Data::index(const QMetaObject *mobj) const
{
- return (d - mobj->d.data - priv(mobj->d.data)->propertyData)/Size;
+ return (d - mobj->d.data - priv(mobj->d.data)->propertyData) / Size;
}
/*!
@@ -3050,57 +3636,60 @@ bool QMetaProperty::isAlias() const
return (data.flags() & Alias);
}
+#if QT_DEPRECATED_SINCE(6, 4)
/*!
\internal
+ Historically:
Executes metacall with QMetaObject::RegisterPropertyMetaType flag.
Returns id of registered type or QMetaType::UnknownType if a type
could not be registered for any reason.
+ Obsolete since Qt 6
*/
int QMetaProperty::registerPropertyType() const
{
- int registerResult = -1;
- void *argv[] = { &registerResult };
- mobj->static_metacall(QMetaObject::RegisterPropertyMetaType, data.index(mobj), argv);
- return registerResult == -1 ? QMetaType::UnknownType : registerResult;
+ return typeId();
}
+#endif
QMetaProperty::QMetaProperty(const QMetaObject *mobj, int index)
: mobj(mobj),
- data({ mobj->d.data + priv(mobj->d.data)->propertyData + index * Data::Size })
+ data(getMetaPropertyData(mobj, index))
{
Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->propertyCount);
+ // The code below here just resolves menum if the property is an enum type:
+ if (!(data.flags() & EnumOrFlag) || !metaType().flags().testFlag(QMetaType::IsEnumeration))
+ return;
+ QByteArrayView enum_name = typeNameFromTypeInfo(mobj, data.type());
+ menum = mobj->enumerator(QMetaObjectPrivate::indexOfEnumerator(mobj, enum_name));
+ if (menum.isValid())
+ return;
- if (data.flags() & EnumOrFlag) {
- const char *type = rawTypeNameFromTypeInfo(mobj, data.type());
- menum = mobj->enumerator(mobj->indexOfEnumerator(type));
- if (!menum.isValid()) {
- const char *enum_name = type;
- const char *scope_name = objectClassName(mobj);
- char *scope_buffer = nullptr;
-
- const char *colon = strrchr(enum_name, ':');
- // ':' will always appear in pairs
- Q_ASSERT(colon <= enum_name || *(colon-1) == ':');
- if (colon > enum_name) {
- int len = colon-enum_name-1;
- scope_buffer = (char *)malloc(len+1);
- memcpy(scope_buffer, enum_name, len);
- scope_buffer[len] = '\0';
- scope_name = scope_buffer;
- enum_name = colon+1;
- }
-
- const QMetaObject *scope = nullptr;
- if (qstrcmp(scope_name, "Qt") == 0)
- scope = &Qt::staticMetaObject;
- else
- scope = QMetaObject_findMetaObject(mobj, scope_name);
- if (scope)
- menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
- if (scope_buffer)
- free(scope_buffer);
- }
+ QByteArrayView scope_name;
+ const auto parsed = parse_scope(enum_name);
+ if (parsed.scope) {
+ scope_name = *parsed.scope;
+ enum_name = parsed.key;
+ } else {
+ scope_name = objectClassName(mobj);
}
+
+ const QMetaObject *scope = nullptr;
+ if (scope_name == "Qt")
+ scope = &Qt::staticMetaObject;
+ else
+ scope = QMetaObject_findMetaObject(mobj, QByteArrayView(scope_name));
+
+ if (scope)
+ menum = scope->enumerator(QMetaObjectPrivate::indexOfEnumerator(scope, enum_name));
+}
+
+/*!
+ \internal
+ Constructs the \c QMetaProperty::Data for the \a index th property of \a mobj
+ */
+QMetaProperty::Data QMetaProperty::getMetaPropertyData(const QMetaObject *mobj, int index)
+{
+ return { mobj->d.data + priv(mobj->d.data)->propertyData + index * Data::Size };
}
/*!
@@ -3159,35 +3748,47 @@ QVariant QMetaProperty::read(const QObject *object) const
Writes \a value as the property's value to the given \a object. Returns
true if the write succeeded; otherwise returns \c false.
- If \a value is not of the same type type as the property, a conversion
+ If \a value is not of the same type as the property, a conversion
is attempted. An empty QVariant() is equivalent to a call to reset()
- if this property is resetable, or setting a default-constructed object
+ if this property is resettable, or setting a default-constructed object
otherwise.
+ \note This function internally makes a copy of \a value. Prefer to use the
+ rvalue overload when possible.
+
\sa read(), reset(), isWritable()
*/
bool QMetaProperty::write(QObject *object, const QVariant &value) const
{
if (!object || !isWritable())
return false;
+ return write(object, QVariant(value));
+}
- QVariant v = value;
+/*!
+ \overload
+ \since 6.6
+*/
+bool QMetaProperty::write(QObject *object, QVariant &&v) const
+{
+ if (!object || !isWritable())
+ return false;
QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) {
- if (isEnumType() && !t.metaObject() && v.userType() == QMetaType::QString) {
+ if (isEnumType() && !t.metaObject() && v.metaType().id() == QMetaType::QString) {
// Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM)
bool ok;
if (isFlagType())
- v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
+ v = QVariant(menum.keysToValue(v.toByteArray(), &ok));
else
- v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
+ v = QVariant(menum.keyToValue(v.toByteArray(), &ok));
if (!ok)
return false;
- } else if (!value.isValid()) {
+ } else if (!v.isValid()) {
if (isResettable())
return reset(object);
v = QVariant(t, nullptr);
- } else if (!v.convert(t.id())) {
+ } else if (!v.convert(t)) {
return false;
}
}
@@ -3232,6 +3833,23 @@ bool QMetaProperty::reset(QObject *object) const
QMetaObject::metacall(object, QMetaObject::ResetProperty, data.index(mobj) + mobj->propertyOffset(), argv);
return true;
}
+
+/*!
+ \since 6.0
+ Returns the bindable interface for the property on a given \a object.
+
+ If the property doesn't support bindings, the returned interface will be
+ invalid.
+
+ \sa QObjectBindableProperty, QProperty, isBindable()
+*/
+QUntypedBindable QMetaProperty::bindable(QObject *object) const
+{
+ QUntypedBindable bindable;
+ void * argv[1] { &bindable };
+ mobj->metacall(object, QMetaObject::BindableProperty, data.index(mobj) + mobj->propertyOffset(), argv);
+ return bindable;
+}
/*!
\since 5.5
@@ -3261,6 +3879,16 @@ bool QMetaProperty::writeOnGadget(void *gadget, const QVariant &value) const
}
/*!
+ \overload
+ \since 6.6
+*/
+bool QMetaProperty::writeOnGadget(void *gadget, QVariant &&value) const
+{
+ Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
+ return write(reinterpret_cast<QObject*>(gadget), std::move(value));
+}
+
+/*!
\since 5.5
Resets the property for the given \a gadget with a reset method.
@@ -3344,20 +3972,23 @@ int QMetaProperty::notifySignalIndex() const
if (!mobj || data.notifyIndex() == std::numeric_limits<uint>::max())
return -1;
uint methodIndex = data.notifyIndex();
- if (methodIndex & IsUnresolvedSignal) {
- methodIndex &= ~IsUnresolvedSignal;
- const QByteArray signalName = stringData(mobj, methodIndex);
- const QMetaObject *m = mobj;
- const int idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(&m, signalName, 0, nullptr);
- if (idx >= 0) {
- return idx + m->methodOffset();
- } else {
- qWarning("QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
- signalName.constData(), objectClassName(mobj), name());
- return -1;
- }
- }
- return methodIndex + mobj->methodOffset();
+ if (!(methodIndex & IsUnresolvedSignal))
+ return methodIndex + mobj->methodOffset();
+ methodIndex &= ~IsUnresolvedSignal;
+ const QByteArray signalName = stringData(mobj, methodIndex);
+ const QMetaObject *m = mobj;
+ // try 0-arg signal
+ int idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(&m, signalName, 0, nullptr);
+ if (idx >= 0)
+ return idx + m->methodOffset();
+ // try 1-arg signal
+ QArgumentType argType(typeId());
+ idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(&m, signalName, 1, &argType);
+ if (idx >= 0)
+ return idx + m->methodOffset();
+ qWarning("QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
+ signalName.constData(), mobj->className(), name());
+ return -1;
}
// This method has been around for a while, but the documentation was marked \internal until 5.1
@@ -3387,14 +4018,9 @@ bool QMetaProperty::isWritable() const
return data.flags() & Writable;
}
-
/*!
- Returns \c true if this property is designable;
- otherwise returns \c false.
-
- If no \a object is given, the function returns \c false if the
- \c{Q_PROPERTY()}'s \c DESIGNABLE attribute is false; otherwise
- returns \c true.
+ Returns \c false if the \c{Q_PROPERTY()}'s \c DESIGNABLE attribute
+ is false; otherwise returns \c true.
\sa isScriptable(), isStored()
*/
@@ -3406,12 +4032,8 @@ bool QMetaProperty::isDesignable() const
}
/*!
- Returns \c true if the property is scriptable;
- otherwise returns \c false.
-
- If no \a object is given, the function returns \c false if the
- \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute is false; otherwise returns
- true.
+ Returns \c false if the \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute
+ is false; otherwise returns true.
\sa isDesignable(), isStored()
*/
@@ -3440,15 +4062,10 @@ bool QMetaProperty::isStored() const
}
/*!
- Returns \c true if this property is designated as the \c USER
- property, i.e., the one that the user can edit or
- that is significant in some other way. Otherwise it returns
- false. e.g., the \c text property is the \c USER editable property
- of a QLineEdit.
-
- If \a object is \nullptr, the function returns \c false if the \c
- {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
- true.
+ Returns \c false if the \c {Q_PROPERTY()}'s \c USER attribute is false.
+ Otherwise it returns true, indicating the property is designated as the
+ \c USER property, i.e., the one that the user can edit or
+ that is significant in some other way.
\sa QMetaObject::userProperty(), isDesignable(), isScriptable()
*/
@@ -3503,16 +4120,18 @@ bool QMetaProperty::isRequired() const
/*!
\since 6.0
- Returns \c true if the property is implemented using a QProperty member; otherwise returns \c false.
+ Returns \c true if the \c{Q_PROPERTY()} exposes binding functionality; otherwise returns false.
- This can be used to detect the availability of QProperty related meta-call types ahead of
- performing the call itself.
+ This implies that you can create bindings that use this property as a dependency or install QPropertyObserver
+ objects on this property. Unless the property is readonly, you can also set a binding on this property.
+
+ \sa QProperty, isWritable(), bindable()
*/
-bool QMetaProperty::isQProperty() const
+bool QMetaProperty::isBindable() const
{
if (!mobj)
return false;
- return data.flags() & IsQProperty;
+ return (data.flags() & Bindable);
}
/*!
@@ -3530,13 +4149,15 @@ bool QMetaProperty::isQProperty() const
\snippet code/src_corelib_kernel_qmetaobject.cpp 5
- This mechanism is free for you to use in your Qt applications. Qt
- doesn't use it for any of its classes.
+ This mechanism is free for you to use in your Qt applications.
+
+ \note It's also used by the \l[ActiveQt]{Active Qt},
+ \l[QtDBus]{Qt D-Bus}, \l[QtQml]{Qt Qml}, and \l{Qt Remote Objects}
+ modules. Some keys might be set when using these modules.
\sa QMetaObject
*/
-
/*!
\fn QMetaClassInfo::QMetaClassInfo()
\internal
@@ -3564,7 +4185,7 @@ const char *QMetaClassInfo::name() const
\sa name()
*/
-const char* QMetaClassInfo::value() const
+const char *QMetaClassInfo::value() const
{
if (!mobj)
return nullptr;
@@ -3585,25 +4206,25 @@ const char* QMetaClassInfo::value() const
our state machine and dbus.
*/
-
/*!
- \macro QGenericArgument Q_ARG(Type, const Type &value)
+ \macro QMetaMethodArgument Q_ARG(Type, const Type &value)
\relates QMetaObject
This macro takes a \a Type and a \a value of that type and
- returns a \l QGenericArgument object that can be passed to
- QMetaObject::invokeMethod().
+ returns a QMetaMethodArgument, which can be passed to the template
+ QMetaObject::invokeMethod() with the \c {Args &&...} arguments.
\sa Q_RETURN_ARG()
*/
/*!
- \macro QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)
+ \macro QMetaMethodReturnArgument Q_RETURN_ARG(Type, Type &value)
\relates QMetaObject
This macro takes a \a Type and a non-const reference to a \a
- value of that type and returns a QGenericReturnArgument object
- that can be passed to QMetaObject::invokeMethod().
+ value of that type and returns a QMetaMethodReturnArgument, which can be
+ passed to the template QMetaObject::invokeMethod() with the \c {Args &&...}
+ arguments.
\sa Q_ARG()
*/
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 20a5c67586..91f287a8d3 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -1,57 +1,24 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMETAOBJECT_H
#define QMETAOBJECT_H
#include <QtCore/qobjectdefs.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
+class QUntypedBindable;
+
#define Q_METAMETHOD_INVOKE_MAX_ARGS 10
class Q_CORE_EXPORT QMetaMethod
{
public:
- Q_DECL_CONSTEXPR inline QMetaMethod() : mobj(nullptr), data({ nullptr }) {}
+ constexpr inline QMetaMethod() : mobj(nullptr), data({ nullptr }) {}
QByteArray methodSignature() const;
QByteArray name() const;
@@ -63,6 +30,7 @@ public:
QMetaType parameterMetaType(int index) const;
void getParameterTypes(int *types) const;
QList<QByteArray> parameterTypes() const;
+ QByteArray parameterTypeName(int index) const;
QList<QByteArray> parameterNames() const;
const char *tag() const;
enum Access { Private, Protected, Public };
@@ -74,9 +42,11 @@ public:
int methodIndex() const;
int relativeMethodIndex() const;
int revision() const;
+ bool isConst() const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
bool invoke(QObject *object,
Qt::ConnectionType connectionType,
QGenericReturnArgument returnValue,
@@ -108,7 +78,7 @@ public:
}
inline bool invoke(QObject *object,
Qt::ConnectionType connectionType,
- QGenericArgument val0 = QGenericArgument(nullptr),
+ QGenericArgument val0,
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
@@ -123,7 +93,7 @@ public:
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
}
inline bool invoke(QObject *object,
- QGenericArgument val0 = QGenericArgument(nullptr),
+ QGenericArgument val0,
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
@@ -150,7 +120,7 @@ public:
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const;
inline bool invokeOnGadget(void *gadget,
- QGenericArgument val0 = QGenericArgument(nullptr),
+ QGenericArgument val0,
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
@@ -164,6 +134,78 @@ public:
return invokeOnGadget(gadget, QGenericReturnArgument(),
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
}
+#endif
+
+ template <typename ReturnArg, typename... Args>
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invoke(QObject *obj, Qt::ConnectionType c, QTemplatedMetaMethodReturnArgument<ReturnArg> r,
+ Args &&... arguments) const
+ {
+ auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
+ return invokeImpl(*this, obj, c, h.parameterCount(), h.parameters.data(),
+ h.typeNames.data(), h.metaTypes.data());
+ }
+
+ template <typename... Args>
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invoke(QObject *obj, Qt::ConnectionType c, Args &&... arguments) const
+ {
+ return invoke(obj, c, QTemplatedMetaMethodReturnArgument<void>{}, std::forward<Args>(arguments)...);
+ }
+
+ template <typename ReturnArg, typename... Args>
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invoke(QObject *obj, QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) const
+ {
+ return invoke(obj, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
+ }
+
+ template <typename... Args>
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invoke(QObject *obj, Args &&... arguments) const
+ {
+ return invoke(obj, Qt::AutoConnection, std::forward<Args>(arguments)...);
+ }
+
+ template <typename ReturnArg, typename... Args>
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invokeOnGadget(void *gadget, QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) const
+ {
+ auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
+ return invokeImpl(*this, gadget, Qt::ConnectionType(-1), h.parameterCount(),
+ h.parameters.data(), h.typeNames.data(), h.metaTypes.data());
+ }
+
+ template <typename... Args>
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invokeOnGadget(void *gadget, Args &&... arguments) const
+ {
+ return invokeOnGadget(gadget, QTemplatedMetaMethodReturnArgument<void>{}, std::forward<Args>(arguments)...);
+ }
inline bool isValid() const { return mobj != nullptr; }
@@ -172,16 +214,20 @@ public:
{
typedef QtPrivate::FunctionPointer<PointerToMemberFunction> SignalType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
- "No Q_OBJECT in the class with the signal");
+ "No Q_OBJECT in the class with the signal");
return fromSignalImpl(&SignalType::Object::staticMetaObject,
reinterpret_cast<void **>(&signal));
}
private:
+ static bool invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType, qsizetype paramCount,
+ const void *const *parameters, const char *const *typeNames,
+ const QtPrivate::QMetaTypeInterface *const *metaTypes);
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
static QMetaMethod fromRelativeMethodIndex(const QMetaObject *mobj, int index);
static QMetaMethod fromRelativeConstructorIndex(const QMetaObject *mobj, int index);
+protected:
struct Data {
enum { Size = 6 };
@@ -195,33 +241,34 @@ private:
const uint *d;
};
+private:
constexpr QMetaMethod(const QMetaObject *metaObject, const Data &data_)
: mobj(metaObject), data(data_)
{}
+protected:
const QMetaObject *mobj;
Data data;
- friend class QMetaMethodPrivate;
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
friend class QObject;
- friend bool operator==(const QMetaMethod &m1, const QMetaMethod &m2);
- friend bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2);
-};
-Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE);
-inline bool operator==(const QMetaMethod &m1, const QMetaMethod &m2)
-{ return m1.data == m2.data; }
-inline bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2)
-{ return !(m1 == m2); }
+private:
+ friend bool comparesEqual(const QMetaMethod &lhs, const QMetaMethod &rhs) noexcept
+ { return lhs.data == rhs.data; }
+ Q_DECLARE_EQUALITY_COMPARABLE(QMetaMethod)
+};
+Q_DECLARE_TYPEINFO(QMetaMethod, Q_RELOCATABLE_TYPE);
class Q_CORE_EXPORT QMetaEnum
{
public:
- Q_DECL_CONSTEXPR inline QMetaEnum() : mobj(nullptr), data({ nullptr }) {}
+ constexpr inline QMetaEnum() : mobj(nullptr), data({ nullptr }) {}
const char *name() const;
const char *enumName() const;
+ QMetaType metaType() const;
+
bool isFlag() const;
bool isScoped() const;
@@ -232,18 +279,20 @@ public:
const char *scope() const;
int keyToValue(const char *key, bool *ok = nullptr) const;
- const char* valueToKey(int value) const;
- int keysToValue(const char * keys, bool *ok = nullptr) const;
+ const char *valueToKey(int value) const;
+ int keysToValue(const char *keys, bool *ok = nullptr) const;
QByteArray valueToKeys(int value) const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
inline bool isValid() const { return name() != nullptr; }
- template<typename T> static QMetaEnum fromType() {
+ template<typename T>
+ static QMetaEnum fromType()
+ {
static_assert(QtPrivate::IsQEnumHelper<T>::Value,
- "QMetaEnum::fromType only works with enums declared as "
- "Q_ENUM, Q_ENUM_NS, Q_FLAG or Q_FLAG_NS");
+ "QMetaEnum::fromType only works with enums declared as "
+ "Q_ENUM, Q_ENUM_NS, Q_FLAG or Q_FLAG_NS");
const QMetaObject *metaObject = qt_getEnumMetaObject(T());
const char *name = qt_getEnumName(T());
return metaObject->enumerator(metaObject->indexOfEnumerator(name));
@@ -257,6 +306,7 @@ private:
quint32 flags() const { return d[2]; }
qint32 keyCount() const { return static_cast<qint32>(d[3]); }
quint32 data() const { return d[4]; }
+ int index(const QMetaObject *mobj) const;
const uint *d;
};
@@ -268,7 +318,7 @@ private:
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
};
-Q_DECLARE_TYPEINFO(QMetaEnum, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMetaEnum, Q_RELOCATABLE_TYPE);
class Q_CORE_EXPORT QMetaProperty
{
@@ -277,8 +327,16 @@ public:
const char *name() const;
const char *typeName() const;
- QVariant::Type type() const;
- int userType() const;
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
+ QT_DEPRECATED_VERSION_6_0
+ QVariant::Type type() const
+ { int t = userType(); return t >= QMetaType::User ? QVariant::UserType : QVariant::Type(t); }
+ QT_WARNING_POP
+#endif
+ int userType() const { return typeId(); }
+ int typeId() const { return metaType().id(); }
QMetaType metaType() const;
int propertyIndex() const;
int relativePropertyIndex() const;
@@ -293,7 +351,7 @@ public:
bool isConstant() const;
bool isFinal() const;
bool isRequired() const;
- bool isQProperty() const;
+ bool isBindable() const;
bool isFlagType() const;
bool isEnumType() const;
@@ -307,10 +365,14 @@ public:
QVariant read(const QObject *obj) const;
bool write(QObject *obj, const QVariant &value) const;
+ bool write(QObject *obj, QVariant &&value) const;
bool reset(QObject *obj) const;
+ QUntypedBindable bindable(QObject *object) const;
+
QVariant readOnGadget(const void *gadget) const;
bool writeOnGadget(void *gadget, const QVariant &value) const;
+ bool writeOnGadget(void *gadget, QVariant &&value) const;
bool resetOnGadget(void *gadget) const;
bool hasStdCppSet() const;
@@ -319,7 +381,10 @@ public:
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
private:
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("obsolete, simply returns typeId()")
int registerPropertyType() const;
+#endif
struct Data {
enum { Size = 5 };
@@ -336,6 +401,7 @@ private:
};
QMetaProperty(const QMetaObject *mobj, int index);
+ static Data getMetaPropertyData(const QMetaObject *mobj, int index);
const QMetaObject *mobj;
Data data;
@@ -347,10 +413,11 @@ private:
class Q_CORE_EXPORT QMetaClassInfo
{
public:
- Q_DECL_CONSTEXPR inline QMetaClassInfo() : mobj(nullptr), data({ nullptr }) {}
+ constexpr inline QMetaClassInfo() : mobj(nullptr), data({ nullptr }) {}
const char *name() const;
const char *value() const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
private:
struct Data {
enum { Size = 2 };
@@ -365,7 +432,7 @@ private:
Data data;
friend struct QMetaObject;
};
-Q_DECLARE_TYPEINFO(QMetaClassInfo, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMetaClassInfo, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h
index 9770d9c576..ad8c6f92d6 100644
--- a/src/corelib/kernel/qmetaobject_moc_p.h
+++ b/src/corelib/kernel/qmetaobject_moc_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#if !defined(QMETAOBJECT_P_H) && !defined(UTILS_H)
# error "Include qmetaobject_p.h (or moc's utils.h) before including this file."
@@ -53,6 +17,7 @@
//
#include <QtCore/qbytearray.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 02ede4d376..d5dc9a356a 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMETAOBJECT_P_H
#define QMETAOBJECT_P_H
@@ -59,20 +23,22 @@
#ifndef QT_NO_QOBJECT
#include <private/qobject_p.h> // For QObjectPrivate::Connection
#endif
+#include <private/qtools_p.h>
#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
-// ### TODO Qt6: add a proper namespace with Q_NAMESPACE and use scoped enums
-// A namespace and scoped are needed to avoid enum clashes
+// ### TODO - QTBUG-87869: wrap in a proper Q_NAMESPACE and use scoped enums, to avoid name clashes
-enum PropertyFlags {
+using namespace QtMiscUtils;
+
+enum PropertyFlags {
Invalid = 0x00000000,
Readable = 0x00000001,
Writable = 0x00000002,
Resettable = 0x00000004,
EnumOrFlag = 0x00000008,
Alias = 0x00000010,
- //Reserved for future usage = 0x00000020,
+ // Reserved for future usage = 0x00000020,
StdCppSet = 0x00000100,
Constant = 0x00000400,
Final = 0x00000800,
@@ -81,14 +47,14 @@ enum PropertyFlags {
Stored = 0x00010000,
User = 0x00100000,
Required = 0x01000000,
- IsQProperty = 0x02000000
+ Bindable = 0x02000000
};
-enum MethodFlags {
+enum MethodFlags {
AccessPrivate = 0x00,
AccessProtected = 0x01,
AccessPublic = 0x02,
- AccessMask = 0x03, //mask
+ AccessMask = 0x03, // mask
MethodMethod = 0x00,
MethodSignal = 0x04,
@@ -99,14 +65,18 @@ enum MethodFlags {
MethodCompatibility = 0x10,
MethodCloned = 0x20,
MethodScriptable = 0x40,
- MethodRevisioned = 0x80
+ MethodRevisioned = 0x80,
+
+ MethodIsConst = 0x100, // no use case for volatile so far
};
-enum MetaObjectFlags { // keep it in sync with QMetaObjectBuilder::MetaObjectFlag enum
+enum MetaObjectFlag {
DynamicMetaObject = 0x01,
RequiresVariantMetaObject = 0x02,
PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
};
+Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
+Q_DECLARE_OPERATORS_FOR_FLAGS(MetaObjectFlags)
enum MetaDataFlags {
IsUnresolvedType = 0x80000000,
@@ -119,7 +89,7 @@ enum EnumFlags {
EnumIsScoped = 0x2
};
-extern int qMetaTypeTypeInternal(const char *);
+Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *);
class QArgumentType
{
@@ -138,41 +108,72 @@ public:
QByteArray name() const
{
if (_type && _name.isEmpty())
- const_cast<QArgumentType *>(this)->_name = QMetaType::typeName(_type);
+ const_cast<QArgumentType *>(this)->_name = QMetaType(_type).name();
return _name;
}
- bool operator==(const QArgumentType &other) const
- {
- if (_type && other._type)
- return _type == other._type;
- else
- return name() == other.name();
- }
- bool operator!=(const QArgumentType &other) const
+
+private:
+ friend bool comparesEqual(const QArgumentType &lhs,
+ const QArgumentType &rhs) noexcept
{
- if (_type && other._type)
- return _type != other._type;
+ if (lhs._type && rhs._type)
+ return lhs._type == rhs._type;
else
- return name() != other.name();
+ return lhs.name() == rhs.name();
}
+ Q_DECLARE_EQUALITY_COMPARABLE(QArgumentType)
-private:
int _type;
QByteArray _name;
};
-Q_DECLARE_TYPEINFO(QArgumentType, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QArgumentType, Q_RELOCATABLE_TYPE);
typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray;
-class QMetaMethodPrivate;
+namespace { class QMetaMethodPrivate; }
+class QMetaMethodInvoker : public QMetaMethod
+{
+ QMetaMethodInvoker() = delete;
+
+public:
+ enum class InvokeFailReason : int {
+ // negative values mean a match was found but the invocation failed
+ // (and a warning has been printed)
+ ReturnTypeMismatch = -1,
+ DeadLockDetected = -2,
+ CallViaVirtualFailed = -3, // no warning
+ ConstructorCallOnObject = -4,
+ ConstructorCallWithoutResult = -5,
+ ConstructorCallFailed = -6, // no warning
+
+ CouldNotQueueParameter = -0x1000,
+
+ // zero is success
+ None = 0,
+
+ // positive values mean the parameters did not match
+ TooFewArguments,
+ FormalParameterMismatch = 0x1000,
+ };
+
+ // shadows the public function
+ static InvokeFailReason Q_CORE_EXPORT
+ invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType, qsizetype paramCount,
+ const void *const *parameters, const char *const *typeNames,
+ const QtPrivate::QMetaTypeInterface *const *metaTypes);
+};
struct QMetaObjectPrivate
{
// revision 7 is Qt 5.0 everything lower is not supported
// revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
// revision 9 is Qt 6.0: It adds the metatype of properties and methods
- enum { OutputRevision = 9 }; // Used by moc, qmetaobjectbuilder and qdbus
- enum { IntsPerMethod = QMetaMethod::Data::Size};
+ // revision 10 is Qt 6.2: The metatype of the metaobject is stored in the metatypes array
+ // and metamethods store a flag stating whether they are const
+ // revision 11 is Qt 6.5: The metatype for void is stored in the metatypes array
+ // revision 12 is Qt 6.6: It adds the metatype for enums
+ enum { OutputRevision = 12 }; // Used by moc, qmetaobjectbuilder and qdbus
+ enum { IntsPerMethod = QMetaMethod::Data::Size };
enum { IntsPerEnum = QMetaEnum::Data::Size };
enum { IntsPerProperty = QMetaProperty::Data::Size };
@@ -207,12 +208,18 @@ struct QMetaObjectPrivate
int argc, const QArgumentType *types);
static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
int argc, const QArgumentType *types);
+
+ enum class Which { Name, Alias };
+ static int indexOfEnumerator(const QMetaObject *m, QByteArrayView name, Which which);
+ static int indexOfEnumerator(const QMetaObject *m, QByteArrayView name);
+
Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject *m, int signal_index);
- static inline int signalOffset(const QMetaObject *m) {
+ static inline int signalOffset(const QMetaObject *m)
+ {
Q_ASSERT(m != nullptr);
int offset = 0;
for (m = m->d.superdata; m; m = m->d.superdata)
- offset += reinterpret_cast<const QMetaObjectPrivate*>(m->d.data)->signalCount;
+ offset += reinterpret_cast<const QMetaObjectPrivate *>(m->d.data)->signalCount;
return offset;
}
Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject *m);
@@ -225,7 +232,7 @@ struct QMetaObjectPrivate
static QList<QByteArray> parameterTypeNamesFromSignature(const char *signature);
#ifndef QT_NO_QOBJECT
- //defined in qobject.cpp
+ // defined in qobject.cpp
enum DisconnectType { DisconnectAll, DisconnectOne };
static void memberIndexes(const QObject *obj, const QMetaMethod &member,
int *signalIndex, int *methodIndex);
@@ -251,6 +258,7 @@ struct QMetaObjectPrivate
static bool methodMatch(const QMetaObject *m, const QMetaMethod &method,
const QByteArray &name, int argc,
const QArgumentType *types);
+ Q_CORE_EXPORT static QMetaMethod firstMethod(const QMetaObject *baseObject, QByteArrayView name);
};
@@ -262,11 +270,7 @@ enum { MetaObjectPrivateFieldCount = sizeof(QMetaObjectPrivate) / sizeof(int) };
// mirrored in moc's utils.h
static inline bool is_ident_char(char s)
{
- return ((s >= 'a' && s <= 'z')
- || (s >= 'A' && s <= 'Z')
- || (s >= '0' && s <= '9')
- || s == '_'
- );
+ return isAsciiLetterOrNumber(s) || s == '_';
}
static inline bool is_space(char s)
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index b418cd2dab..c2b44a4f00 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmetaobjectbuilder_p.h"
@@ -81,7 +45,7 @@ QT_BEGIN_NAMESPACE
namespace QtPrivate {
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type)
{
- int id = QMetaType::type(type);
+ int id = QMetaType::fromName(type).id();
if (!id && !type.isEmpty() && type != "void")
return false;
return (id < QMetaType::User);
@@ -89,7 +53,7 @@ Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type)
} // namespace QtPrivate
// copied from qmetaobject.cpp
-static inline Q_DECL_UNUSED const QMetaObjectPrivate *priv(const uint* data)
+[[maybe_unused]] static inline const QMetaObjectPrivate *qmobPriv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
class QMetaMethodBuilderPrivate
@@ -146,16 +110,17 @@ public:
return signature.left(qMax(signature.indexOf('('), 0));
}
};
-Q_DECLARE_TYPEINFO(QMetaMethodBuilderPrivate, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMetaMethodBuilderPrivate, Q_RELOCATABLE_TYPE);
class QMetaPropertyBuilderPrivate
{
public:
QMetaPropertyBuilderPrivate
- (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1,
+ (const QByteArray& _name, const QByteArray& _type, QMetaType _metaType, int notifierIdx=-1,
int _revision = 0)
: name(_name),
type(QMetaObject::normalizedType(_type.constData())),
+ metaType(_metaType),
flags(Readable | Writable | Scriptable), notifySignal(notifierIdx),
revision(_revision)
{
@@ -164,6 +129,7 @@ public:
QByteArray name;
QByteArray type;
+ QMetaType metaType;
int flags;
int notifySignal;
int revision;
@@ -181,24 +147,25 @@ public:
flags &= ~f;
}
};
-Q_DECLARE_TYPEINFO(QMetaPropertyBuilderPrivate, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMetaPropertyBuilderPrivate, Q_RELOCATABLE_TYPE);
class QMetaEnumBuilderPrivate
{
public:
- QMetaEnumBuilderPrivate(const QByteArray& _name)
+ QMetaEnumBuilderPrivate(const QByteArray &_name)
: name(_name), enumName(_name), isFlag(false), isScoped(false)
{
}
QByteArray name;
QByteArray enumName;
+ QMetaType metaType;
bool isFlag;
bool isScoped;
QList<QByteArray> keys;
QList<int> values;
};
-Q_DECLARE_TYPEINFO(QMetaEnumBuilderPrivate, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMetaEnumBuilderPrivate, Q_RELOCATABLE_TYPE);
class QMetaObjectBuilderPrivate
{
@@ -222,7 +189,7 @@ public:
QList<QByteArray> classInfoValues;
std::vector<QMetaEnumBuilderPrivate> enumerators;
QList<const QMetaObject *> relatedMetaObjects;
- int flags;
+ MetaObjectFlags flags;
};
bool QMetaObjectBuilderPrivate::hasRevisionedMethods() const
@@ -253,8 +220,8 @@ QMetaObjectBuilder::QMetaObjectBuilder()
\sa addMetaObject()
*/
-QMetaObjectBuilder::QMetaObjectBuilder
- (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+QMetaObjectBuilder::QMetaObjectBuilder(const QMetaObject *prototype,
+ QMetaObjectBuilder::AddMembers members)
{
d = new QMetaObjectBuilderPrivate();
addMetaObject(prototype, members);
@@ -285,7 +252,7 @@ QByteArray QMetaObjectBuilder::className() const
\sa className(), setSuperClass()
*/
-void QMetaObjectBuilder::setClassName(const QByteArray& name)
+void QMetaObjectBuilder::setClassName(const QByteArray &name)
{
d->className = name;
}
@@ -321,9 +288,9 @@ void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
\sa setFlags()
*/
-QMetaObjectBuilder::MetaObjectFlags QMetaObjectBuilder::flags() const
+MetaObjectFlags QMetaObjectBuilder::flags() const
{
- return (QMetaObjectBuilder::MetaObjectFlags)d->flags;
+ return d->flags;
}
/*!
@@ -418,7 +385,7 @@ int QMetaObjectBuilder::relatedMetaObjectCount() const
\sa method(), methodCount(), removeMethod(), indexOfMethod()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray &signature)
{
int index = int(d->methods.size());
d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
@@ -434,12 +401,11 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
\sa method(), methodCount(), removeMethod(), indexOfMethod()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addMethod
- (const QByteArray& signature, const QByteArray& returnType)
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray &signature,
+ const QByteArray &returnType)
{
int index = int(d->methods.size());
- d->methods.push_back(QMetaMethodBuilderPrivate
- (QMetaMethod::Method, signature, returnType));
+ d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature, returnType));
return QMetaMethodBuilder(this, index);
}
@@ -454,7 +420,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod
\sa method(), methodCount(), removeMethod(), indexOfMethod()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod &prototype)
{
QMetaMethodBuilder method;
if (prototype.methodType() == QMetaMethod::Method)
@@ -482,7 +448,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
\sa addMethod(), addSignal(), indexOfSlot()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray &signature)
{
int index = int(d->methods.size());
d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
@@ -497,11 +463,11 @@ QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
\sa addMethod(), addSlot(), indexOfSignal()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray &signature)
{
int index = int(d->methods.size());
- d->methods.push_back(QMetaMethodBuilderPrivate
- (QMetaMethod::Signal, signature, QByteArray("void"), QMetaMethod::Public));
+ d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Signal, signature,
+ QByteArray("void"), QMetaMethod::Public));
return QMetaMethodBuilder(this, index);
}
@@ -514,7 +480,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
\sa constructor(), constructorCount(), removeConstructor()
\sa indexOfConstructor()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray &signature)
{
int index = int(d->constructors.size());
d->constructors.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature,
@@ -533,7 +499,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signatur
\sa constructor(), constructorCount(), removeConstructor()
\sa indexOfConstructor()
*/
-QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod &prototype)
{
Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
QMetaMethodBuilder ctor = addConstructor(prototype.methodSignature());
@@ -554,11 +520,19 @@ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototy
\sa property(), propertyCount(), removeProperty(), indexOfProperty()
*/
-QMetaPropertyBuilder QMetaObjectBuilder::addProperty
- (const QByteArray& name, const QByteArray& type, int notifierId)
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QByteArray &name, const QByteArray &type,
+ int notifierId)
+{
+ return addProperty(name, type, QMetaType::fromName(type), notifierId);
+}
+
+/*!
+ \overload
+ */
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QByteArray &name, const QByteArray &type, QMetaType metaType, int notifierId)
{
int index = int(d->properties.size());
- d->properties.push_back(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ d->properties.push_back(QMetaPropertyBuilderPrivate(name, type, metaType, notifierId));
return QMetaPropertyBuilder(this, index);
}
@@ -570,9 +544,9 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty
\sa property(), propertyCount(), removeProperty(), indexOfProperty()
*/
-QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty &prototype)
{
- QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName(), prototype.metaType());
property.setReadable(prototype.isReadable());
property.setWritable(prototype.isWritable());
property.setResettable(prototype.isResettable());
@@ -604,7 +578,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot
\sa enumerator(), enumeratorCount(), removeEnumerator()
\sa indexOfEnumerator()
*/
-QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray &name)
{
int index = int(d->enumerators.size());
d->enumerators.push_back(QMetaEnumBuilderPrivate(name));
@@ -620,10 +594,11 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
\sa enumerator(), enumeratorCount(), removeEnumerator()
\sa indexOfEnumerator()
*/
-QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum &prototype)
{
QMetaEnumBuilder en = addEnumerator(prototype.name());
en.setEnumName(prototype.enumName());
+ en.setMetaType(prototype.metaType());
en.setIsFlag(prototype.isFlag());
en.setIsScoped(prototype.isScoped());
int count = prototype.keyCount();
@@ -639,7 +614,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
\sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
\sa indexOfClassInfo()
*/
-int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+int QMetaObjectBuilder::addClassInfo(const QByteArray &name, const QByteArray &value)
{
int index = d->classInfoNames.size();
d->classInfoNames += name;
@@ -673,8 +648,8 @@ int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
The \a members parameter indicates which members of \a prototype
should be added. The default is AllMembers.
*/
-void QMetaObjectBuilder::addMetaObject
- (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+void QMetaObjectBuilder::addMetaObject(const QMetaObject *prototype,
+ QMetaObjectBuilder::AddMembers members)
{
Q_ASSERT(prototype);
int index;
@@ -731,7 +706,7 @@ void QMetaObjectBuilder::addMetaObject
}
if ((members & RelatedMetaObjects) != 0) {
- Q_ASSERT(priv(prototype->d.data)->revision >= 2);
+ Q_ASSERT(qmobPriv(prototype->d.data)->revision >= 2);
const auto *objects = prototype->d.relatedMetaObjects;
if (objects) {
while (*objects != nullptr) {
@@ -742,7 +717,7 @@ void QMetaObjectBuilder::addMetaObject
}
if ((members & StaticMetacall) != 0) {
- Q_ASSERT(priv(prototype->d.data)->revision >= 6);
+ Q_ASSERT(qmobPriv(prototype->d.data)->revision >= 6);
if (prototype->d.static_metacall)
setStaticMetacallFunction(prototype->d.static_metacall);
}
@@ -948,7 +923,7 @@ void QMetaObjectBuilder::removeRelatedMetaObject(int index)
\sa method(), methodCount(), addMethod(), removeMethod()
*/
-int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+int QMetaObjectBuilder::indexOfMethod(const QByteArray &signature)
{
QByteArray sig = QMetaObject::normalizedSignature(signature);
for (const auto &method : d->methods) {
@@ -964,7 +939,7 @@ int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
\sa indexOfMethod(), indexOfSlot()
*/
-int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+int QMetaObjectBuilder::indexOfSignal(const QByteArray &signature)
{
QByteArray sig = QMetaObject::normalizedSignature(signature);
for (const auto &method : d->methods) {
@@ -980,7 +955,7 @@ int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
\sa indexOfMethod(), indexOfSignal()
*/
-int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+int QMetaObjectBuilder::indexOfSlot(const QByteArray &signature)
{
QByteArray sig = QMetaObject::normalizedSignature(signature);
for (const auto &method : d->methods) {
@@ -996,7 +971,7 @@ int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
\sa constructor(), constructorCount(), addConstructor(), removeConstructor()
*/
-int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray &signature)
{
QByteArray sig = QMetaObject::normalizedSignature(signature);
for (const auto &constructor : d->constructors) {
@@ -1012,7 +987,7 @@ int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
\sa property(), propertyCount(), addProperty(), removeProperty()
*/
-int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+int QMetaObjectBuilder::indexOfProperty(const QByteArray &name)
{
for (const auto &property : d->properties) {
if (name == property.name)
@@ -1027,7 +1002,7 @@ int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
\sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
*/
-int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray &name)
{
for (const auto &enumerator : d->enumerators) {
if (name == enumerator.name)
@@ -1043,7 +1018,7 @@ int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
\sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
\sa removeClassInfo()
*/
-int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray &name)
{
for (int index = 0; index < d->classInfoNames.size(); ++index) {
if (name == d->classInfoNames[index])
@@ -1053,6 +1028,9 @@ int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
}
// Align on a specific type boundary.
+#ifdef ALIGN
+# undef ALIGN
+#endif
#define ALIGN(size,type) \
(size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
@@ -1107,10 +1085,10 @@ static void writeString(char *out, int i, const QByteArray &str,
int offset = offsetOfStringdataMember + stringdataOffset;
uint offsetLen[2] = { uint(offset), uint(size) };
- memcpy(out + 2 * i * sizeof(uint), &offsetLen, 2*sizeof(uint));
+ memcpy(out + 2 * i * sizeof(uint), &offsetLen, 2 * sizeof(uint));
memcpy(out + offset, str.constData(), size);
- out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
+ out[offset + size] = '\0';
stringdataOffset += size + 1;
}
@@ -1121,13 +1099,13 @@ static void writeString(char *out, int i, const QByteArray &str,
// moc (see generator.cpp).
void QMetaStringTable::writeBlob(char *out) const
{
- Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1)));
+ Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment() - 1)));
int offsetOfStringdataMember = int(m_entries.size() * 2 * sizeof(uint));
int stringdataOffset = 0;
// qt_metacast expects the first string in the string table to be the class name.
- writeString(out, /*index*/0, m_className, offsetOfStringdataMember, stringdataOffset);
+ writeString(out, /*index*/ 0, m_className, offsetOfStringdataMember, stringdataOffset);
for (Entries::ConstIterator it = m_entries.constBegin(), end = m_entries.constEnd();
it != end; ++it) {
@@ -1151,31 +1129,32 @@ static int aggregateParameterCount(const std::vector<QMetaMethodBuilderPrivate>
return sum;
}
+enum Mode {
+ Prepare, // compute the size of the metaobject
+ Construct // construct metaobject in pre-allocated buffer
+};
// Build a QMetaObject in "buf" based on the information in "d".
-// If "buf" is null, then return the number of bytes needed to
-// build the QMetaObject. Returns -1 if the metaobject if
-// relocatable is set, but the metaobject contains relatedMetaObjects.
+// If the mode is prepare, then return the number of bytes needed to
+// build the QMetaObject.
+template<Mode mode>
static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
- int expectedSize, bool relocatable)
+ int expectedSize)
{
Q_UNUSED(expectedSize); // Avoid warning in release mode
- int size = 0;
+ Q_UNUSED(buf);
+ qsizetype size = 0;
int dataIndex;
int paramsIndex;
int enumIndex;
int index;
bool hasRevisionedMethods = d->hasRevisionedMethods();
- if (relocatable &&
- (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction))
- return -1;
-
// Create the main QMetaObject structure at the start of the buffer.
QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
size += sizeof(QMetaObject);
ALIGN(size, int);
- if (buf) {
- if (!relocatable) meta->d.superdata = d->superClass;
+ if constexpr (mode == Construct) {
+ meta->d.superdata = d->superClass;
meta->d.relatedMetaObjects = nullptr;
meta->d.extradata = nullptr;
meta->d.metaTypes = nullptr;
@@ -1183,19 +1162,19 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
// Populate the QMetaObjectPrivate structure.
- QMetaObjectPrivate *pmeta
- = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
- int pmetaSize = size;
+ QMetaObjectPrivate *pmeta = buf ? reinterpret_cast<QMetaObjectPrivate *>(buf + size)
+ : nullptr;
+ //int pmetaSize = size;
dataIndex = MetaObjectPrivateFieldCount;
int methodParametersDataSize =
((aggregateParameterCount(d->methods)
+ aggregateParameterCount(d->constructors)) * 2) // types and parameter names
- int(d->methods.size()) // return "parameters" don't have names
- int(d->constructors.size()); // "this" parameters don't have names
- if (buf) {
- static_assert(QMetaObjectPrivate::OutputRevision == 9, "QMetaObjectBuilder should generate the same version as moc");
+ if constexpr (mode == Construct) {
+ static_assert(QMetaObjectPrivate::OutputRevision == 12, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
- pmeta->flags = d->flags;
+ pmeta->flags = d->flags.toInt();
pmeta->className = 0; // Class name is always the first string.
//pmeta->signalCount is handled in the "output method loop" as an optimization.
@@ -1246,15 +1225,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
int *data = reinterpret_cast<int *>(pmeta);
size += dataIndex * sizeof(int);
ALIGN(size, void *);
- char *str = reinterpret_cast<char *>(buf + size);
- if (buf) {
- if (relocatable) {
- meta->d.stringdata = reinterpret_cast<const uint *>((quintptr)size);
- meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize);
- } else {
- meta->d.stringdata = reinterpret_cast<const uint *>(str);
- meta->d.data = reinterpret_cast<uint *>(data);
- }
+ [[maybe_unused]] char *str = reinterpret_cast<char *>(buf + size);
+ if constexpr (mode == Construct) {
+ meta->d.stringdata = reinterpret_cast<const uint *>(str);
+ meta->d.data = reinterpret_cast<uint *>(data);
}
// Reset the current data position to just past the QMetaObjectPrivate.
@@ -1265,9 +1239,9 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the class infos,
Q_ASSERT(!buf || dataIndex == pmeta->classInfoData);
for (index = 0; index < d->classInfoNames.size(); ++index) {
- int name = strings.enter(d->classInfoNames[index]);
- int value = strings.enter(d->classInfoValues[index]);
- if (buf) {
+ [[maybe_unused]] int name = strings.enter(d->classInfoNames[index]);
+ [[maybe_unused]] int value = strings.enter(d->classInfoValues[index]);
+ if constexpr (mode == Construct) {
data[dataIndex] = name;
data[dataIndex + 1] = value;
}
@@ -1276,13 +1250,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the methods in the class.
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
- int parameterMetaTypesIndex = d->properties.size();
+ // + 1 for metatype of this metaobject
+ int parameterMetaTypesIndex = int(d->properties.size()) + 1;
for (const auto &method : d->methods) {
- int name = strings.enter(method.name());
+ [[maybe_unused]] int name = strings.enter(method.name());
int argc = method.parameterCount();
- int tag = strings.enter(method.tag);
- int attrs = method.attributes;
- if (buf) {
+ [[maybe_unused]] int tag = strings.enter(method.tag);
+ [[maybe_unused]] int attrs = method.attributes;
+ if constexpr (mode == Construct) {
data[dataIndex] = name;
data[dataIndex + 1] = argc;
data[dataIndex + 2] = paramsIndex;
@@ -1298,7 +1273,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
if (hasRevisionedMethods) {
for (const auto &method : d->methods) {
- if (buf)
+ if constexpr (mode == Construct)
data[dataIndex] = method.revision;
++dataIndex;
}
@@ -1314,12 +1289,12 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
int paramCount = paramTypeNames.size();
for (int i = -1; i < paramCount; ++i) {
const QByteArray &typeName = (i < 0) ? method.returnType : paramTypeNames.at(i);
- int typeInfo;
+ [[maybe_unused]] int typeInfo;
if (QtPrivate::isBuiltinType(typeName))
- typeInfo = QMetaType::type(typeName);
+ typeInfo = QMetaType::fromName(typeName).id();
else
typeInfo = IsUnresolvedType | strings.enter(typeName);
- if (buf)
+ if constexpr (mode == Construct)
data[dataIndex] = typeInfo;
++dataIndex;
}
@@ -1328,8 +1303,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
while (paramNames.size() < paramCount)
paramNames.append(QByteArray());
for (int i = 0; i < paramCount; ++i) {
- int stringIndex = strings.enter(paramNames.at(i));
- if (buf)
+ [[maybe_unused]] int stringIndex = strings.enter(paramNames.at(i));
+ if constexpr (mode == Construct)
data[dataIndex] = stringIndex;
++dataIndex;
}
@@ -1338,21 +1313,22 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the properties in the class.
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
- for (const auto &prop : d->properties) {
- int name = strings.enter(prop.name);
+ for (QMetaPropertyBuilderPrivate &prop : d->properties) {
+ [[maybe_unused]] int name = strings.enter(prop.name);
- int typeInfo;
- if (QtPrivate::isBuiltinType(prop.type))
- typeInfo = QMetaType::type(prop.type);
- else
- typeInfo = IsUnresolvedType | strings.enter(prop.type);
+ // try to resolve the metatype again if it was unknown
+ if (!prop.metaType.isValid())
+ prop.metaType = QMetaType::fromName(prop.type);
+ [[maybe_unused]] const int typeInfo = prop.metaType.isValid()
+ ? prop.metaType.id()
+ : IsUnresolvedType | strings.enter(prop.type);
- int flags = prop.flags;
+ [[maybe_unused]] int flags = prop.flags;
if (!QtPrivate::isBuiltinType(prop.type))
flags |= EnumOrFlag;
- if (buf) {
+ if constexpr (mode == Construct) {
data[dataIndex] = name;
data[dataIndex + 1] = typeInfo;
data[dataIndex + 2] = flags;
@@ -1365,13 +1341,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the enumerators in the class.
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
for (const auto &enumerator : d->enumerators) {
- int name = strings.enter(enumerator.name);
- int enumName = strings.enter(enumerator.enumName);
- int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
- int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
+ [[maybe_unused]] int name = strings.enter(enumerator.name);
+ [[maybe_unused]] int enumName = strings.enter(enumerator.enumName);
+ [[maybe_unused]] int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
+ [[maybe_unused]] int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
int count = enumerator.keys.size();
int enumOffset = enumIndex;
- if (buf) {
+ if constexpr (mode == Construct) {
data[dataIndex] = name;
data[dataIndex + 1] = enumName;
data[dataIndex + 2] = isFlag | isScoped;
@@ -1379,8 +1355,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
data[dataIndex + 4] = enumOffset;
}
for (int key = 0; key < count; ++key) {
- int keyIndex = strings.enter(enumerator.keys[key]);
- if (buf) {
+ [[maybe_unused]] int keyIndex = strings.enter(enumerator.keys[key]);
+ if constexpr (mode == Construct) {
data[enumOffset++] = keyIndex;
data[enumOffset++] = enumerator.values[key];
}
@@ -1392,11 +1368,11 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the constructors in the class.
Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
for (const auto &ctor : d->constructors) {
- int name = strings.enter(ctor.name());
+ [[maybe_unused]] int name = strings.enter(ctor.name());
int argc = ctor.parameterCount();
- int tag = strings.enter(ctor.tag);
- int attrs = ctor.attributes;
- if (buf) {
+ [[maybe_unused]] int tag = strings.enter(ctor.tag);
+ [[maybe_unused]] int attrs = ctor.attributes;
+ if constexpr (mode == Construct) {
data[dataIndex] = name;
data[dataIndex + 1] = argc;
data[dataIndex + 2] = paramsIndex;
@@ -1411,11 +1387,11 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
size += strings.blobSize();
- if (buf)
+ if constexpr (mode == Construct)
strings.writeBlob(str);
// Output the zero terminator in the data array.
- if (buf)
+ if constexpr (mode == Construct)
data[enumIndex] = 0;
// Create the relatedMetaObjects block if we need one.
@@ -1423,7 +1399,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
using SuperData = QMetaObject::SuperData;
ALIGN(size, SuperData);
auto objects = reinterpret_cast<SuperData *>(buf + size);
- if (buf) {
+ if constexpr (mode == Construct) {
meta->d.relatedMetaObjects = objects;
for (index = 0; index < d->relatedMetaObjects.size(); ++index)
objects[index] = d->relatedMetaObjects[index];
@@ -1432,37 +1408,39 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1);
}
- if (d->properties.size() > 0 || d->methods.size() > 0 || d->constructors.size() > 0) {
- ALIGN(size, QtPrivate::QMetaTypeInterface *);
- auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size);
- if (buf) {
- meta->d.metaTypes = types;
- for (const auto &prop : d->properties) {
- QMetaType mt(QMetaType::type(prop.type));
+ ALIGN(size, QtPrivate::QMetaTypeInterface *);
+ auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size);
+ if constexpr (mode == Construct) {
+ meta->d.metaTypes = types;
+ for (const auto &prop : d->properties) {
+ QMetaType mt = prop.metaType;
+ *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
+ types++;
+ }
+ // add metatype interface for this metaobject - must be null
+ // as we can't know our metatype
+ *types = nullptr;
+ types++;
+ for (const auto &method: d->methods) {
+ QMetaType mt(QMetaType::fromName(method.returnType).id());
+ *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
+ types++;
+ for (const auto &parameterType: method.parameterTypes()) {
+ QMetaType mt = QMetaType::fromName(parameterType);
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
types++;
}
- for (const auto &method: d->methods) {
- QMetaType mt(QMetaType::type(method.returnType));
+ }
+ for (const auto &constructor : d->constructors) {
+ for (const auto &parameterType : constructor.parameterTypes()) {
+ QMetaType mt = QMetaType::fromName(parameterType);
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
types++;
- for (const auto &parameterType: method.parameterTypes()) {
- QMetaType mt(QMetaType::type(parameterType));
- *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
- types++;
- }
- }
- for (const auto &constructor: d->constructors) {
- for (const auto &parameterType: constructor.parameterTypes()) {
- QMetaType mt(QMetaType::type(parameterType));
- *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
- types++;
- }
}
}
- // parameterMetaTypesIndex is equal to the total number of metatypes
- size += static_cast<int>(sizeof(QMetaType) * parameterMetaTypesIndex);
}
+ // parameterMetaTypesIndex is equal to the total number of metatypes
+ size += sizeof(QMetaType) * parameterMetaTypesIndex;
// Align the final size and return it.
ALIGN(size, void *);
@@ -1482,72 +1460,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
*/
QMetaObject *QMetaObjectBuilder::toMetaObject() const
{
- int size = buildMetaObject(d, nullptr, 0, false);
+ int size = buildMetaObject<Prepare>(d, nullptr, 0);
char *buf = reinterpret_cast<char *>(malloc(size));
memset(buf, 0, size);
- buildMetaObject(d, buf, size, false);
+ buildMetaObject<Construct>(d, buf, size);
return reinterpret_cast<QMetaObject *>(buf);
}
-/*
- \internal
-
- Converts this meta object builder into relocatable data. This data can
- be stored, copied and later passed to fromRelocatableData() to create a
- concrete QMetaObject.
-
- The data is specific to the architecture on which it was created, but is not
- specific to the process that created it. Not all meta object builder's can
- be converted to data in this way. If \a ok is provided, it will be set to
- true if the conversion succeeds, and false otherwise. If a
- staticMetacallFunction() or any relatedMetaObject()'s are specified the
- conversion to relocatable data will fail.
-*/
-QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const
-{
- int size = buildMetaObject(d, nullptr, 0, true);
- if (size == -1) {
- if (ok) *ok = false;
- return QByteArray();
- }
-
- QByteArray data;
- data.resize(size);
- char *buf = data.data();
- memset(buf, 0, size);
- buildMetaObject(d, buf, size, true);
- if (ok) *ok = true;
- return data;
-}
-
-/*
- \internal
-
- Sets the \a data returned from toRelocatableData() onto a concrete
- QMetaObject instance, \a output. As the meta object's super class is not
- saved in the relocatable data, it must be passed as \a superClass.
-*/
-void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
- const QMetaObject *superclass,
- const QByteArray &data)
-{
- if (!output)
- return;
-
- const char *buf = data.constData();
- const QMetaObject *dataMo = reinterpret_cast<const QMetaObject *>(buf);
-
- quintptr stringdataOffset = (quintptr)dataMo->d.stringdata;
- quintptr dataOffset = (quintptr)dataMo->d.data;
-
- output->d.superdata = superclass;
- output->d.stringdata = reinterpret_cast<const uint *>(buf + stringdataOffset);
- output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
- output->d.extradata = nullptr;
- output->d.relatedMetaObjects = nullptr;
- output->d.static_metacall = nullptr;
-}
-
/*!
\typedef QMetaObjectBuilder::StaticMetacallFunction
@@ -1579,275 +1498,6 @@ void QMetaObjectBuilder::setStaticMetacallFunction
d->staticMetacallFunction = value;
}
-#ifndef QT_NO_DATASTREAM
-
-/*!
- Serializes the contents of the meta object builder onto \a stream.
-
- \sa deserialize()
-*/
-void QMetaObjectBuilder::serialize(QDataStream& stream) const
-{
- int index;
-
- // Write the class and super class names.
- stream << d->className;
- if (d->superClass)
- stream << QByteArray(d->superClass->className());
- else
- stream << QByteArray();
-
- // Write the counts for each type of class member.
- stream << d->classInfoNames.size();
- stream << int(d->methods.size());
- stream << int(d->properties.size());
- stream << int(d->enumerators.size());
- stream << int(d->constructors.size());
- stream << d->relatedMetaObjects.size();
-
- // Write the items of class information.
- for (index = 0; index < d->classInfoNames.size(); ++index) {
- stream << d->classInfoNames[index];
- stream << d->classInfoValues[index];
- }
-
- // Write the methods.
- for (const auto &method : d->methods) {
- stream << method.signature;
- stream << method.returnType;
- stream << method.parameterNames;
- stream << method.tag;
- stream << method.attributes;
- if (method.revision)
- stream << method.revision;
- }
-
- // Write the properties.
- for (const auto &property : d->properties) {
- stream << property.name;
- stream << property.type;
- stream << property.flags;
- stream << property.notifySignal;
- stream << property.revision;
- }
-
- // Write the enumerators.
- for (const auto &enumerator : d->enumerators) {
- stream << enumerator.name;
- stream << enumerator.isFlag;
- stream << enumerator.isScoped;
- stream << enumerator.keys;
- stream << enumerator.values;
- }
-
- // Write the constructors.
- for (const auto &ctor : d->constructors) {
- stream << ctor.signature;
- stream << ctor.returnType;
- stream << ctor.parameterNames;
- stream << ctor.tag;
- stream << ctor.attributes;
- }
-
- // Write the related meta objects.
- for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
- const QMetaObject *meta = d->relatedMetaObjects[index];
- stream << QByteArray(meta->className());
- }
-
- // Add an extra empty QByteArray for additional data in future versions.
- // This should help maintain backwards compatibility, allowing older
- // versions to read newer data.
- stream << QByteArray();
-}
-
-// Resolve a class name using the name reference map.
-static const QMetaObject *resolveClassName
- (const QMap<QByteArray, const QMetaObject *>& references,
- const QByteArray& name)
-{
- if (name == QByteArray("QObject"))
- return &QObject::staticMetaObject;
- else
- return references.value(name, 0);
-}
-
-/*!
- Deserializes a meta object builder from \a stream into
- this meta object builder.
-
- The \a references parameter specifies a mapping from class names
- to QMetaObject instances for resolving the super class name and
- related meta objects in the object that is deserialized.
- The meta object for QObject is implicitly added to \a references
- and does not need to be supplied.
-
- The QDataStream::status() value on \a stream will be set to
- QDataStream::ReadCorruptData if the input data is corrupt.
- The status will be set to QDataStream::ReadPastEnd if the
- input was exhausted before the full meta object was read.
-
- \sa serialize()
-*/
-void QMetaObjectBuilder::deserialize
- (QDataStream& stream,
- const QMap<QByteArray, const QMetaObject *>& references)
-{
- QByteArray name;
- const QMetaObject *cl;
- int index;
-
- // Clear all members in the builder to their default states.
- d->className.clear();
- d->superClass = &QObject::staticMetaObject;
- d->classInfoNames.clear();
- d->classInfoValues.clear();
- d->methods.clear();
- d->properties.clear();
- d->enumerators.clear();
- d->constructors.clear();
- d->relatedMetaObjects.clear();
- d->staticMetacallFunction = nullptr;
-
- // Read the class and super class names.
- stream >> d->className;
- stream >> name;
- if (name.isEmpty()) {
- d->superClass = nullptr;
- } else if ((cl = resolveClassName(references, name)) != nullptr) {
- d->superClass = cl;
- } else {
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
-
- // Read the counts for each type of class member.
- int classInfoCount, methodCount, propertyCount;
- int enumeratorCount, constructorCount, relatedMetaObjectCount;
- stream >> classInfoCount;
- stream >> methodCount;
- stream >> propertyCount;
- stream >> enumeratorCount;
- stream >> constructorCount;
- stream >> relatedMetaObjectCount;
- if (classInfoCount < 0 || methodCount < 0 ||
- propertyCount < 0 || enumeratorCount < 0 ||
- constructorCount < 0 || relatedMetaObjectCount < 0) {
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
-
- // Read the items of class information.
- for (index = 0; index < classInfoCount; ++index) {
- if (stream.status() != QDataStream::Ok)
- return;
- QByteArray value;
- stream >> name;
- stream >> value;
- addClassInfo(name, value);
- }
-
- // Read the member methods.
- for (index = 0; index < methodCount; ++index) {
- if (stream.status() != QDataStream::Ok)
- return;
- stream >> name;
- addMethod(name);
- QMetaMethodBuilderPrivate &method = d->methods[index];
- stream >> method.returnType;
- stream >> method.parameterNames;
- stream >> method.tag;
- stream >> method.attributes;
- if (method.attributes & MethodRevisioned)
- stream >> method.revision;
- if (method.methodType() == QMetaMethod::Constructor) {
- // Cannot add a constructor in this set of methods.
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
- }
-
- // Read the properties.
- for (index = 0; index < propertyCount; ++index) {
- if (stream.status() != QDataStream::Ok)
- return;
- QByteArray type;
- stream >> name;
- stream >> type;
- addProperty(name, type);
- QMetaPropertyBuilderPrivate &property = d->properties[index];
- stream >> property.flags;
- stream >> property.notifySignal;
- if (property.notifySignal < -1 ||
- property.notifySignal >= int(d->methods.size())) {
- // Notify signal method index is out of range.
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
- if (property.notifySignal >= 0 &&
- d->methods[property.notifySignal].methodType() != QMetaMethod::Signal) {
- // Notify signal method index does not refer to a signal.
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
- stream >> property.revision;
- }
-
- // Read the enumerators.
- for (index = 0; index < enumeratorCount; ++index) {
- if (stream.status() != QDataStream::Ok)
- return;
- stream >> name;
- addEnumerator(name);
- QMetaEnumBuilderPrivate &enumerator = d->enumerators[index];
- stream >> enumerator.isFlag;
- stream >> enumerator.isScoped;
- stream >> enumerator.keys;
- stream >> enumerator.values;
- if (enumerator.keys.size() != enumerator.values.size()) {
- // Mismatch between number of keys and number of values.
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
- }
-
- // Read the constructor methods.
- for (index = 0; index < constructorCount; ++index) {
- if (stream.status() != QDataStream::Ok)
- return;
- stream >> name;
- addConstructor(name);
- QMetaMethodBuilderPrivate &method = d->constructors[index];
- stream >> method.returnType;
- stream >> method.parameterNames;
- stream >> method.tag;
- stream >> method.attributes;
- if (method.methodType() != QMetaMethod::Constructor) {
- // The type must be Constructor.
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
- }
-
- // Read the related meta objects.
- for (index = 0; index < relatedMetaObjectCount; ++index) {
- if (stream.status() != QDataStream::Ok)
- return;
- stream >> name;
- cl = resolveClassName(references, name);
- if (!cl) {
- stream.setStatus(QDataStream::ReadCorruptData);
- return;
- }
- addRelatedMetaObject(cl);
- }
-
- // Read the extra data block, which is reserved for future use.
- stream >> name;
-}
-
-#endif // !QT_NO_DATASTREAM
-
/*!
\class QMetaMethodBuilder
\inmodule QtCore
@@ -1930,7 +1580,7 @@ QByteArray QMetaMethodBuilder::returnType() const
\sa returnType(), parameterTypes(), signature()
*/
-void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+void QMetaMethodBuilder::setReturnType(const QByteArray &value)
{
QMetaMethodBuilderPrivate *d = d_func();
if (d)
@@ -1970,7 +1620,7 @@ QList<QByteArray> QMetaMethodBuilder::parameterNames() const
\sa parameterNames()
*/
-void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray> &value)
{
QMetaMethodBuilderPrivate *d = d_func();
if (d)
@@ -1996,7 +1646,7 @@ QByteArray QMetaMethodBuilder::tag() const
\sa setTag()
*/
-void QMetaMethodBuilder::setTag(const QByteArray& value)
+void QMetaMethodBuilder::setTag(const QByteArray &value)
{
QMetaMethodBuilderPrivate *d = d_func();
if (d)
@@ -2060,6 +1710,28 @@ void QMetaMethodBuilder::setAttributes(int value)
}
/*!
+ Returns true if the method is const qualified.
+ */
+int QMetaMethodBuilder::isConst() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (!d)
+ return false;
+ return (d->attributes & MethodIsConst);
+}
+
+void QMetaMethodBuilder::setConst(bool methodIsConst)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (!d)
+ return;
+ if (methodIsConst)
+ d->attributes |= MethodIsConst;
+ else
+ d->attributes &= ~MethodIsConst;
+}
+
+/*!
Returns the revision of this method.
\sa setRevision()
@@ -2070,7 +1742,6 @@ int QMetaMethodBuilder::revision() const
if (d)
return d->revision;
return 0;
-
}
/*!
@@ -2177,7 +1848,7 @@ QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
\sa hasNotifySignal(), notifySignal(), removeNotifySignal()
*/
-void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder &value)
{
QMetaPropertyBuilderPrivate *d = d_func();
if (d) {
@@ -2381,6 +2052,18 @@ bool QMetaPropertyBuilder::isAlias() const
}
/*!
+ Returns \c true if the property is bindable
+ The default value is false
+ */
+bool QMetaPropertyBuilder::isBindable() const
+{
+ if (auto d = d_func())
+ return d->flag(Bindable);
+ else
+ return false;
+}
+
+/*!
Sets this property to readable if \a value is true.
\sa isReadable(), setWritable()
@@ -2526,6 +2209,15 @@ void QMetaPropertyBuilder::setAlias(bool value)
}
/*!
+ Sets the\c BINDABLE flag on this property to \a value
+ */
+void QMetaPropertyBuilder::setBindable(bool value)
+{
+ if (auto d = d_func())
+ d->setFlag(Bindable, value);
+}
+
+/*!
Returns the revision of this property.
\sa setRevision()
@@ -2536,7 +2228,6 @@ int QMetaPropertyBuilder::revision() const
if (d)
return d->revision;
return 0;
-
}
/*!
@@ -2551,7 +2242,6 @@ void QMetaPropertyBuilder::setRevision(int revision)
d->revision = revision;
}
-
/*!
\class QMetaEnumBuilder
\inmodule QtCore
@@ -2618,6 +2308,31 @@ void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
}
/*!
+ Returns the meta type of the enumerator.
+
+ \since 6.6
+*/
+QMetaType QMetaEnumBuilder::metaType() const
+{
+ if (QMetaEnumBuilderPrivate *d = d_func())
+ return d->metaType;
+ return QMetaType();
+}
+
+/*!
+ Sets this enumerator to have the given \c metaType.
+
+ \since 6.6
+ \sa metaType()
+*/
+void QMetaEnumBuilder::setMetaType(QMetaType metaType)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->metaType = metaType;
+}
+
+/*!
Returns \c true if this enumerator is used as a flag; otherwise returns
false.
@@ -2719,7 +2434,7 @@ int QMetaEnumBuilder::value(int index) const
\sa keyCount(), key(), value(), removeKey()
*/
-int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+int QMetaEnumBuilder::addKey(const QByteArray &name, int value)
{
QMetaEnumBuilderPrivate *d = d_func();
if (d) {
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index a473e68cec..b52487986c 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMETAOBJECTBUILDER_P_H
#define QMETAOBJECTBUILDER_P_H
@@ -58,6 +22,7 @@
#include <QtCore/qhash.h>
#include <QtCore/qmap.h>
+#include <private/qmetaobject_p.h>
QT_BEGIN_NAMESPACE
@@ -93,14 +58,6 @@ public:
};
Q_DECLARE_FLAGS(AddMembers, AddMember)
- // ### TODO Qt6: remove me and use the MetaObjectFlags enum from qmetaobject_p.h
- enum MetaObjectFlag { // keep it in sync with enum MetaObjectFlags from qmetaobject_p.h
- DynamicMetaObject = 0x01,
- RequiresVariantMetaObject = 0x02,
- PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
- };
- Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
-
QMetaObjectBuilder();
explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
virtual ~QMetaObjectBuilder();
@@ -132,6 +89,7 @@ public:
QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, QMetaType metaType, int notifierId=-1);
QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
QMetaEnumBuilder addEnumerator(const QByteArray& name);
@@ -173,15 +131,6 @@ public:
void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
QMetaObject *toMetaObject() const;
- QByteArray toRelocatableData(bool * = nullptr) const;
- static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &);
-
-#ifndef QT_NO_DATASTREAM
- void serialize(QDataStream& stream) const;
- void deserialize
- (QDataStream& stream,
- const QMap<QByteArray, const QMetaObject *>& references);
-#endif
private:
Q_DISABLE_COPY_MOVE(QMetaObjectBuilder)
@@ -219,6 +168,9 @@ public:
int attributes() const;
void setAttributes(int value);
+ int isConst() const;
+ void setConst(bool methodIsConst=true);
+
int revision() const;
void setRevision(int revision);
@@ -263,6 +215,7 @@ public:
bool isConstant() const;
bool isFinal() const;
bool isAlias() const;
+ bool isBindable() const;
void setReadable(bool value);
void setWritable(bool value);
@@ -276,6 +229,7 @@ public:
void setConstant(bool value);
void setFinal(bool value);
void setAlias(bool value);
+ void setBindable(bool value);
int revision() const;
void setRevision(int revision);
@@ -304,6 +258,9 @@ public:
QByteArray enumName() const;
void setEnumName(const QByteArray &alias);
+ QMetaType metaType() const;
+ void setMetaType(QMetaType metaType);
+
bool isFlag() const;
void setIsFlag(bool value);
@@ -331,6 +288,7 @@ private:
class Q_CORE_EXPORT QMetaStringTable
{
+ Q_DISABLE_COPY_MOVE(QMetaStringTable)
public:
explicit QMetaStringTable(const QByteArray &className);
@@ -348,7 +306,6 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 9841758c80..9a57f46cbf 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1,41 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmetatype.h"
#include "qmetatype_p.h"
@@ -43,23 +9,25 @@
#include "qdatetime.h"
#include "qbytearray.h"
#include "qreadwritelock.h"
+#include "qhash.h"
+#include "qmap.h"
#include "qstring.h"
#include "qstringlist.h"
#include "qlist.h"
#include "qlocale.h"
+#include "qdebug.h"
#if QT_CONFIG(easingcurve)
#include "qeasingcurve.h"
#endif
#include "quuid.h"
-#include "qvariant.h"
-#include "qdatastream.h"
-#include "qmetatypeswitcher_p.h"
#if QT_CONFIG(regularexpression)
# include "qregularexpression.h"
#endif
#ifndef QT_BOOTSTRAPPED
+# include "qdatastream.h"
+
# include "qbitarray.h"
# include "qurl.h"
# include "qvariant.h"
@@ -71,6 +39,10 @@
# include "qcborarray.h"
# include "qcbormap.h"
# include "qbytearraylist.h"
+# include "qmetaobject.h"
+# include "qsequentialiterable.h"
+# include "qassociativeiterable.h"
+# include "qobject.h"
#endif
#if QT_CONFIG(itemmodel)
@@ -84,52 +56,71 @@
# include "qline.h"
#endif
-#include <bitset>
#include <new>
+#include <cstring>
QT_BEGIN_NAMESPACE
#define NS(x) QT_PREPEND_NAMESPACE(x)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl)
+
+using QtMetaTypePrivate::isInterfaceFor;
namespace {
-struct DefinedTypesFilter {
- template<typename T>
- struct Acceptor {
- static const bool IsAccepted = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && QModulesPrivate::QTypeModuleInfo<T>::IsCore;
- };
+struct QMetaTypeDeleter
+{
+ const QtPrivate::QMetaTypeInterface *iface;
+ void operator()(void *data)
+ {
+ if (iface->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+ operator delete(data, std::align_val_t(iface->alignment));
+ } else {
+ operator delete(data);
+ }
+ }
};
struct QMetaTypeCustomRegistry
{
- QReadWriteLock lock;
- QList<QtPrivate::QMetaTypeInterface *> registry;
- QHash<QByteArray, QtPrivate::QMetaTypeInterface *> aliases;
-#ifndef QT_NO_DATASTREAM
- struct DataStreamOps
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QMetaTypeCustomRegistry()
{
- QMetaType::SaveOperator saveOp;
- QMetaType::LoadOperator loadOp;
- };
- QHash<int, DataStreamOps> dataStreamOp;
+ /* qfloat16 was neither a builtin, nor unconditionally registered
+ in QtCore in Qt <= 6.2.
+ Inserting it as an alias ensures that a QMetaType::id call
+ will get the correct built-in type-id (the interface pointers
+ might still not match, but we already deal with that case.
+ */
+ aliases.insert("qfloat16", QtPrivate::qMetaTypeInterfaceForType<qfloat16>());
+ }
#endif
+
+ QReadWriteLock lock;
+ QList<const QtPrivate::QMetaTypeInterface *> registry;
+ QHash<QByteArray, const QtPrivate::QMetaTypeInterface *> aliases;
// index of first empty (unregistered) type in registry, if any.
int firstEmpty = 0;
- int registerCustomType(QtPrivate::QMetaTypeInterface *ti)
+ int registerCustomType(const QtPrivate::QMetaTypeInterface *cti)
{
+ // we got here because cti->typeId is 0, so this is a custom meta type
+ // (not read-only)
+ auto ti = const_cast<QtPrivate::QMetaTypeInterface *>(cti);
{
QWriteLocker l(&lock);
- if (ti->typeId)
- return ti->typeId;
+ if (int id = ti->typeId.loadRelaxed())
+ return id;
QByteArray name =
#ifndef QT_NO_QOBJECT
QMetaObject::normalizedType
#endif
(ti->name);
if (auto ti2 = aliases.value(name)) {
- ti->typeId.storeRelaxed(ti2->typeId.loadRelaxed());
- return ti2->typeId;
+ const auto id = ti2->typeId.loadRelaxed();
+ ti->typeId.storeRelaxed(id);
+ return id;
}
aliases[name] = ti;
int size = registry.size();
@@ -142,11 +133,11 @@ struct QMetaTypeCustomRegistry
registry.append(ti);
firstEmpty = registry.size();
}
- ti->typeId = firstEmpty + QMetaType::User;
+ ti->typeId.storeRelaxed(firstEmpty + QMetaType::User);
}
if (ti->legacyRegisterOp)
ti->legacyRegisterOp();
- return ti->typeId;
+ return ti->typeId.loadRelaxed();
};
void unregisterDynamicType(int id)
@@ -159,20 +150,14 @@ struct QMetaTypeCustomRegistry
auto &ti = registry[idx];
// We must unregister all names.
- auto it = aliases.begin();
- while (it != aliases.end()) {
- if (it.value() == ti)
- it = aliases.erase(it);
- else
- ++it;
- }
+ aliases.removeIf([ti] (const auto &kv) { return kv.value() == ti; });
ti = nullptr;
firstEmpty = std::min(firstEmpty, idx);
}
- QtPrivate::QMetaTypeInterface *getCustomType(int id)
+ const QtPrivate::QMetaTypeInterface *getCustomType(int id)
{
QReadLocker l(&lock);
return registry.value(id - QMetaType::User - 1);
@@ -183,6 +168,44 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
} // namespace
+// used by QVariant::save(): returns the name used in the Q_DECLARE_METATYPE
+// macro (one of them, indetermine which one)
+const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d)
+{
+ const char *name = nullptr;
+ if (!customTypeRegistry.exists())
+ return name;
+ QMetaTypeCustomRegistry *r = &*customTypeRegistry;
+
+ QByteArrayView officialName(type_d->name);
+ QReadLocker l(&r->lock);
+ auto it = r->aliases.constBegin();
+ auto end = r->aliases.constEnd();
+ for ( ; it != end; ++it) {
+ if (it.value() != type_d)
+ continue;
+ if (it.key() == officialName)
+ continue; // skip the official name
+ name = it.key().constData();
+ ++it;
+ break;
+ }
+
+#ifndef QT_NO_DEBUG
+ QByteArrayList otherNames;
+ for ( ; it != end; ++it) {
+ if (it.value() == type_d && it.key() != officialName)
+ otherNames << it.key();
+ }
+ l.unlock();
+ if (!otherNames.isEmpty())
+ qWarning("QMetaType: type %s has more than one typedef alias: %s, %s",
+ type_d->name, name, otherNames.join(", ").constData());
+#endif
+
+ return name;
+}
+
/*!
\macro Q_DECLARE_OPAQUE_POINTER(PointerType)
\relates QMetaType
@@ -239,13 +262,23 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\li Pointers to classes derived from QObject
\li QList<T>, QQueue<T>, QStack<T> or QSet<T>
where T is a registered meta type
- \li QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are
+ \li QHash<T1, T2>, QMap<T1, T2> or std::pair<T1, T2> where T1 and T2 are
registered meta types
\li QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject
\li Enumerations registered with Q_ENUM or Q_FLAG
\li Classes that have a Q_GADGET macro
\endlist
+ \note This method also registers the stream and debug operators for the type if they
+ are visible at registration time. As this is done automatically in some places,
+ it is strongly recommended to declare the stream operators for a type directly
+ after the type itself. Because of the argument dependent lookup rules of C++, it is
+ also strongly recommended to declare the operators in the same namespace as the type itself.
+
+ The stream operators should have the following signatures:
+
+ \snippet code/src_corelib_kernel_qmetatype.cpp 6
+
\sa qRegisterMetaType()
*/
@@ -319,14 +352,20 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value LongLong LongLong
\value Short \c{short}
\value Char \c{char}
+ \value Char16 \c{char16_t}
+ \value Char32 \c{char32_t}
\value ULong \c{unsigned long}
\value ULongLong ULongLong
\value UShort \c{unsigned short}
\value SChar \c{signed char}
\value UChar \c{unsigned char}
\value Float \c float
+ \value Float16 qfloat16
+ \omitvalue Float128
+ \omitvalue BFloat16
+ \omitvalue Int128
+ \omitvalue UInt128
\value QObjectStar QObject *
- \value QVariant QVariant
\value QCursor QCursor
\value QDate QDate
@@ -344,6 +383,7 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value QStringList QStringList
\value QVariantMap QVariantMap
\value QVariantHash QVariantHash
+ \value QVariantPair QVariantPair
\value QIcon QIcon
\value QPen QPen
\value QLineF QLineF
@@ -384,13 +424,13 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5)
\value QUuid QUuid
\value QByteArrayList QByteArrayList
+ \value QVariant QVariant
\value User Base value for user types
\value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
- \omitvalue LastCoreType
- \omitvalue LastGuiType
- Additional types can be registered using Q_DECLARE_METATYPE().
+ Additional types can be registered using qRegisterMetaType() or by calling
+ registerType().
\sa type(), typeName()
*/
@@ -400,17 +440,31 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
The enum describes attributes of a type supported by QMetaType.
- \value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
- \value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects.
- \value MovableType An instance of a type having this attribute can be safely moved by memcpy.
+ \value NeedsConstruction This type has a default constructor. If the flag is not set, instances can be safely initialized with memset to 0.
+ \value NeedsCopyConstruction (since 6.5) This type has a non-trivial copy constructor. If the flag is not set, instances can be copied with memcpy.
+ \value NeedsMoveConstruction (since 6.5) This type has a non-trivial move constructor. If the flag is not set, instances can be moved with memcpy.
+ \value NeedsDestruction This type has a non-trivial destructor. If the flag is not set, calls to the destructor are not necessary before discarding objects.
+ \value RelocatableType An instance of a type having this attribute can be safely moved to a different memory location using memcpy.
+ \omitvalue MovableType
\omitvalue SharedPointerToQObject
- \value IsEnumeration This type is an enumeration
- \value PointerToQObject This type is a pointer to a derived of QObject
+ \value IsEnumeration This type is an enumeration.
+ \value IsUnsignedEnumeration If the type is an Enumeration, its underlying type is unsigned.
+ \value PointerToQObject This type is a pointer to a class derived from QObject.
+ \value IsPointer This type is a pointer to another type.
\omitvalue WeakPointerToQObject
\omitvalue TrackingPointerToQObject
- \omitvalue WasDeclaredAsMetaType
- \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit
+ \omitvalue IsGadget \omit (since Qt 5.5) This type is a Q_GADGET and its corresponding QMetaObject can be accessed with QMetaType::metaObject. \endomit
\omitvalue PointerToGadget
+ \omitvalue IsQmlList
+ \value IsConst Indicates that values of this type are immutable; for instance, because they are pointers to const objects.
+
+ \note Before Qt 6.5, both the NeedsConstruction and NeedsDestruction flags
+ were incorrectly set if the either copy construtor or destructor were
+ non-trivial (that is, if the type was not trivial).
+
+ Note that the Needs flags may be set but the meta type may not have a
+ publicly-accessible constructor of the relevant type or a
+ publicly-accessible destructor.
*/
/*!
@@ -420,21 +474,24 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\ingroup objectmodel
\threadsafe
+ \compares equality
The class is used as a helper to marshall types in QVariant and
in queued signals and slots connections. It associates a type
name to a type so that it can be created and destructed
- dynamically at run-time. Declare new types with Q_DECLARE_METATYPE()
- to make them available to QVariant and other template-based functions.
- Call qRegisterMetaType() to make types available to non-template based
- functions, such as the queued signal and slot connections.
+ dynamically at run-time.
- Any class or struct that has a public default
- constructor, a public copy constructor, and a public destructor
- can be registered.
+ Type names can be registered with QMetaType by using either
+ qRegisterMetaType() or registerType(). Registration is not required for
+ most operations; it's only required for operations that attempt to resolve
+ a type name in string form back to a QMetaType object or the type's ID.
+ Those include some old-style signal-slot connections using
+ QObject::connect(), reading user-types from \l QDataStream to \l QVariant,
+ or binding to other languages and IPC mechanisms, like QML, D-Bus,
+ JavaScript, etc.
- The following code allocates and destructs an instance of
- \c{MyClass}:
+ The following code allocates and destructs an instance of \c{MyClass} by
+ its name, which requires that \c{MyClass} have been previously registered:
\snippet code/src_corelib_kernel_qmetatype.cpp 3
@@ -452,6 +509,8 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
Returns \c true if this QMetaType object contains valid
information about a type, false otherwise.
+
+ \sa isRegistered()
*/
bool QMetaType::isValid() const
{
@@ -462,35 +521,49 @@ bool QMetaType::isValid() const
\fn bool QMetaType::isRegistered() const
\since 5.0
- Returns \c true if this QMetaType object contains valid
- information about a type, false otherwise.
+ Returns \c true if this QMetaType object has been registered with the Qt
+ global metatype registry. Registration allows the type to be found by its
+ name (using QMetaType::fromName()) or by its ID (using the constructor).
+
+ \sa qRegisterMetaType(), isValid()
*/
bool QMetaType::isRegistered() const
{
- return d_ptr;
+ return d_ptr && d_ptr->typeId.loadRelaxed();
}
/*!
\fn int QMetaType::id() const
\since 5.13
- Returns id type hold by this QMetatype instance.
+ Returns id type held by this QMetatype instance.
*/
-int QMetaType::id() const
+
+/*!
+ \fn void QMetaType::registerType() const
+ \since 6.5
+
+ Registers this QMetaType with the type registry so it can be found by name,
+ using QMetaType::fromName().
+
+ \sa qRegisterMetaType()
+ */
+/*!
+ \internal
+ Out-of-line path for registerType() and slow path id().
+ */
+int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
{
- if (d_ptr) {
- if (d_ptr->typeId)
- return d_ptr->typeId;
- auto reg = customTypeRegistry();
- if (reg) {
- return reg->registerCustomType(d_ptr);
- }
+ Q_ASSERT(iface);
+ auto reg = customTypeRegistry();
+ if (reg) {
+ return reg->registerCustomType(iface);
}
return 0;
}
/*!
- \fn bool QMetaType::sizeOf() const
+ \fn constexpr qsizetype QMetaType::sizeOf() const
\since 5.0
Returns the size of the type in bytes (i.e. sizeof(T),
@@ -500,57 +573,62 @@ int QMetaType::id() const
This function is typically used together with construct()
to perform low-level management of the memory used by a type.
- \sa QMetaType::construct(), QMetaType::sizeOf()
+ \sa QMetaType::construct(), QMetaType::sizeOf(), QMetaType::alignOf()
*/
-int QMetaType::sizeOf() const
-{
- if (d_ptr)
- return d_ptr->size;
- return 0;
-}
/*!
- \fn TypeFlags QMetaType::flags() const
+ \fn constexpr int QMetaType::alignOf() const
+ \since 6.0
+
+ Returns the alignment of the type in bytes (i.e. alignof(T),
+ where T is the actual type for which this QMetaType instance
+ was constructed for).
+
+ This function is typically used together with construct()
+ to perform low-level management of the memory used by a type.
+
+ \sa QMetaType::construct(), QMetaType::sizeOf()
+
+ */
+
+/*!
+ \fn constexpr TypeFlags QMetaType::flags() const
\since 5.0
- Returns flags of the type for which this QMetaType instance was constructed.
+ Returns flags of the type for which this QMetaType instance was
+ constructed. To inspect specific type traits, prefer using one of the "is-"
+ functions rather than the flags directly.
- \sa QMetaType::TypeFlags, QMetaType::typeFlags()
+ \sa QMetaType::TypeFlags, QMetaType::flags(), isDefaultConstructible(),
+ isCopyConstructible(), isMoveConstructible(), isDestructible(),
+ isEqualityComparable(), isOrdered()
*/
-QMetaType::TypeFlags QMetaType::flags() const
-{
- if (d_ptr)
- return TypeFlags(d_ptr->flags);
- return {};
-}
/*!
- \fn const QMetaObject *QMetaType::metaObject() const
+ \fn constexpr const QMetaObject *QMetaType::metaObject() const
\since 5.5
- return a QMetaObject relative to this type.
+ Returns a QMetaObject relative to this type.
If the type is a pointer type to a subclass of QObject, flags() contains
- QMetaType::PointerToQObject and this function returns the corresponding QMetaObject. This can
- be used to in combinaison with QMetaObject::construct to create QObject of this type.
+ QMetaType::PointerToQObject and this function returns the corresponding QMetaObject.
+ This can be used in combination with QMetaObject::newInstance() to create QObjects of this type.
- If the type is a Q_GADGET, flags() contains QMetaType::IsGadget, and this function returns its
- QMetaObject. This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
- pointer of this type. (given by QVariant::data for example)
+ If the type is a Q_GADGET, flags() contains QMetaType::IsGadget.
+ If the type is a pointer to a Q_GADGET, flags() contains QMetaType::PointerToGadget.
+ In both cases, this function returns its QMetaObject.
+ This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
+ pointer of this type for example, as given by QVariant::data().
- If the type is an enumeration, flags() contains QMetaType::IsEnumeration, and this function
- returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or
- \nullptr otherwise
+ If the type is an enumeration, flags() contains QMetaType::IsEnumeration.
+ In this case, this function returns the QMetaObject of the enclosing
+ object if the enum was registered as a Q_ENUM or \nullptr otherwise.
- \sa QMetaType::metaObjectForType(), QMetaType::flags()
+ \sa QMetaType::flags()
*/
-const QMetaObject *QMetaType::metaObject() const
-{
- return d_ptr ? d_ptr->metaObject : nullptr;
-}
/*!
- \fn void *QMetaType::create(const void *copy = 0) const
+ \fn void *QMetaType::create(const void *copy = nullptr) const
\since 5.0
Returns a copy of \a copy, assuming it is of the type that this
@@ -561,16 +639,17 @@ const QMetaObject *QMetaType::metaObject() const
*/
void *QMetaType::create(const void *copy) const
{
- if (d_ptr) {
- void *where =
-#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
- d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__ ?
- operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)) :
-#endif
- operator new(d_ptr->size);
- return construct(where, copy);
- }
- return nullptr;
+ if (copy ? !isCopyConstructible() : !isDefaultConstructible())
+ return nullptr;
+
+ std::unique_ptr<void, QMetaTypeDeleter> where(nullptr, {d_ptr});
+ if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ where.reset(operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)));
+ else
+ where.reset(operator new(d_ptr->size));
+
+ QtMetaTypePrivate::construct(d_ptr, where.get(), copy);
+ return where.release();
}
/*!
@@ -584,18 +663,14 @@ void *QMetaType::create(const void *copy) const
*/
void QMetaType::destroy(void *data) const
{
- if (d_ptr && d_ptr->dtor) {
- d_ptr->dtor(d_ptr, data);
- if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
- operator delete(data, std::align_val_t(d_ptr->alignment));
- } else {
- operator delete(data);
- }
+ if (data && isDestructible()) {
+ QtMetaTypePrivate::destruct(d_ptr, data);
+ QMetaTypeDeleter{d_ptr}(data);
}
}
/*!
- \fn void *QMetaType::construct(void *where, const void *copy = 0) const
+ \fn void *QMetaType::construct(void *where, const void *copy = nullptr) const
\since 5.0
Constructs a value of the type that this QMetaType instance
@@ -624,16 +699,11 @@ void *QMetaType::construct(void *where, const void *copy) const
{
if (!where)
return nullptr;
- if (d_ptr) {
- if (copy && d_ptr->copyCtr) {
- d_ptr->copyCtr(d_ptr, where, copy);
- return where;
- } else if (!copy && d_ptr->defaultCtr) {
- d_ptr->defaultCtr(d_ptr, where);
- return where;
- }
- }
- return nullptr;
+ if (copy ? !isCopyConstructible() : !isDefaultConstructible())
+ return nullptr;
+
+ QtMetaTypePrivate::construct(d_ptr, where, copy);
+ return where;
}
/*!
@@ -649,47 +719,204 @@ void *QMetaType::construct(void *where, const void *copy) const
*/
void QMetaType::destruct(void *data) const
{
- if (!data)
- return;
- if (d_ptr && d_ptr->dtor) {
- d_ptr->dtor(d_ptr, data);
- return;
+ if (data && isDestructible())
+ QtMetaTypePrivate::destruct(d_ptr, data);
+}
+
+static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
+{
+ std::less<const void *> less;
+ if (less(ptr1, ptr2))
+ return QPartialOrdering::Less;
+ if (less(ptr2, ptr1))
+ return QPartialOrdering::Greater;
+ return QPartialOrdering::Equivalent;
+}
+
+/*!
+ Compares the objects at \a lhs and \a rhs for ordering.
+
+ Returns QPartialOrdering::Unordered if comparison is not supported
+ or the values are unordered. Otherwise, returns
+ QPartialOrdering::Less, QPartialOrdering::Equivalent or
+ QPartialOrdering::Greater if \a lhs is less than, equivalent
+ to or greater than \a rhs, respectively.
+
+ Both objects must be of the type described by this metatype. If either \a lhs
+ or \a rhs is \nullptr, the values are unordered. Comparison is only supported
+ if the type's less than operator was visible to the metatype declaration.
+
+ If the type's equality operator was also visible, values will only compare equal if the
+ equality operator says they are. In the absence of an equality operator, when neither
+ value is less than the other, values are considered equal; if equality is also available
+ and two such values are not equal, they are considered unordered, just as NaN (not a
+ number) values of a floating point type lie outside its ordering.
+
+ \note If no less than operator was visible to the metatype declaration, values are
+ unordered even if an equality operator visible to the declaration considers them equal:
+ \c{compare() == 0} only agrees with equals() if the less than operator was visible.
+
+ \since 6.0
+ \sa equals(), isOrdered()
+*/
+QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
+{
+ if (!lhs || !rhs)
+ return QPartialOrdering::Unordered;
+ if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
+ return threeWayCompare(*reinterpret_cast<const void * const *>(lhs),
+ *reinterpret_cast<const void * const *>(rhs));
+ if (d_ptr && d_ptr->lessThan) {
+ if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
+ return QPartialOrdering::Equivalent;
+ if (d_ptr->lessThan(d_ptr, lhs, rhs))
+ return QPartialOrdering::Less;
+ if (d_ptr->lessThan(d_ptr, rhs, lhs))
+ return QPartialOrdering::Greater;
+ if (!d_ptr->equals)
+ return QPartialOrdering::Equivalent;
}
+ return QPartialOrdering::Unordered;
}
-void QtMetaTypePrivate::derefAndDestroy(NS(QtPrivate::QMetaTypeInterface) *d_ptr)
+/*!
+ Compares the objects at \a lhs and \a rhs for equality.
+
+ Both objects must be of the type described by this metatype. Can only compare the
+ two objects if a less than or equality operator for the type was visible to the
+ metatype declaration. Otherwise, the metatype never considers values equal. When
+ an equality operator was visible to the metatype declaration, it is authoritative;
+ otherwise, if less than is visible, when neither value is less than the other, the
+ two are considered equal. If values are unordered (see compare() for details) they
+ are not equal.
+
+ Returns true if the two objects compare equal, otherwise false.
+
+ \since 6.0
+ \sa isEqualityComparable(), compare()
+*/
+bool QMetaType::equals(const void *lhs, const void *rhs) const
{
- if (d_ptr && !d_ptr->ref.deref()) {
- if (auto reg = customTypeRegistry())
- reg->unregisterDynamicType(d_ptr->typeId.loadRelaxed());
- Q_ASSERT(d_ptr->deleteSelf);
- d_ptr->deleteSelf(d_ptr);
+ if (!lhs || !rhs)
+ return false;
+ if (d_ptr) {
+ if (d_ptr->flags & QMetaType::IsPointer)
+ return *reinterpret_cast<const void * const *>(lhs) == *reinterpret_cast<const void * const *>(rhs);
+
+ if (d_ptr->equals)
+ return d_ptr->equals(d_ptr, lhs, rhs);
+ if (d_ptr->lessThan && !d_ptr->lessThan(d_ptr, lhs, rhs) && !d_ptr->lessThan(d_ptr, rhs, lhs))
+ return true;
}
+ return false;
+}
+
+/*!
+ \fn bool QMetaType::isDefaultConstructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be default-constructed. If it can be, then
+ construct() and create() can be used with a \c{copy} parameter that is
+ null.
+
+ \sa flags(), isCopyConstructible(), isMoveConstructible(), isDestructible()
+ */
+
+/*!
+ \fn bool QMetaType::isCopyConstructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be copy-constructed. If it can be, then
+ construct() and create() can be used with a \c{copy} parameter that is
+ not null.
+
+ \sa flags(), isDefaultConstructible(), isMoveConstructible(), isDestructible()
+ */
+
+/*!
+ \fn bool QMetaType::isMoveConstructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be move-constructed. QMetaType currently does
+ not have an API to make use of this trait.
+
+ \sa flags(), isDefaultConstructible(), isCopyConstructible(), isDestructible()
+ */
+
+/*!
+ \fn bool QMetaType::isDestructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be destroyed. If it can be, then destroy()
+ and destruct() can be called.
+
+ \sa flags(), isDefaultConstructible(), isCopyConstructible(), isMoveConstructible()
+ */
+
+bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
+}
+
+bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
+}
+
+bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
+}
+
+bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface);
}
/*!
- \fn QMetaType::~QMetaType()
+ Returns \c true if a less than or equality operator for the type described by
+ this metatype was visible to the metatype declaration, otherwise \c false.
- Destructs this object.
+ \sa equals(), isOrdered()
*/
-QMetaType::~QMetaType()
+bool QMetaType::isEqualityComparable() const
{
- QtMetaTypePrivate::derefAndDestroy(d_ptr);
+ return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->equals != nullptr || d_ptr->lessThan != nullptr);
}
-QMetaType::QMetaType(QtPrivate::QMetaTypeInterface *d) : d_ptr(d)
+/*!
+ Returns \c true if a less than operator for the type described by this metatype
+ was visible to the metatype declaration, otherwise \c false.
+
+ \sa compare(), isEqualityComparable()
+*/
+bool QMetaType::isOrdered() const
{
- if (d_ptr)
- d_ptr->ref.ref();
+ return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->lessThan != nullptr);
}
-QMetaType &QMetaType::operator=(const QMetaType &other)
+
+/*!
+ \internal
+*/
+void QMetaType::unregisterMetaType(QMetaType type)
{
- if (d_ptr != other.d_ptr) {
- this->~QMetaType();
- new (this) QMetaType(other.d_ptr);
+ const QtPrivate::QMetaTypeInterface *d_ptr = type.d_ptr;
+ if (!d_ptr)
+ return;
+
+ const int typeId = d_ptr->typeId.loadRelaxed();
+ if (typeId < QMetaType::User)
+ return;
+
+ // this is a custom meta type (not read-only)
+
+ if (auto reg = customTypeRegistry()) {
+ Q_ASSERT(reg->getCustomType(typeId) == d_ptr);
+ reg->unregisterDynamicType(typeId);
}
- return *this;
+
+ const_cast<QtPrivate::QMetaTypeInterface *>(d_ptr)->typeId.storeRelease(0);
}
/*!
@@ -699,24 +926,28 @@ QMetaType &QMetaType::operator=(const QMetaType &other)
Returns the QMetaType corresponding to the type in the template parameter.
*/
-/*! \fn bool operator==(const QMetaType &a, const QMetaType &b)
+/*! \fn bool QMetaType::operator==(const QMetaType &lhs, const QMetaType &rhs)
\since 5.15
- \relates QMetaType
\overload
- Returns \c true if the QMetaType \a a represents the same type
- as the QMetaType \a b, otherwise returns \c false.
+ Returns \c true if the QMetaType \a lhs represents the same type
+ as the QMetaType \a rhs, otherwise returns \c false.
*/
-/*! \fn bool operator!=(const QMetaType &a, const QMetaType &b)
+/*! \fn bool QMetaType::operator!=(const QMetaType &lhs, const QMetaType &rhs)
\since 5.15
- \relates QMetaType
\overload
- Returns \c true if the QMetaType \a a represents a different type
- than the QMetaType \a b, otherwise returns \c false.
+ Returns \c true if the QMetaType \a lhs represents a different type
+ than the QMetaType \a rhs, otherwise returns \c false.
*/
+/*! \internal */
+bool QMetaTypeModuleHelper::convert(const void *, int, void *, int) const
+{
+ return false;
+}
+
#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
{ #RealName, sizeof(#RealName) - 1, MetaTypeId },
@@ -732,11 +963,709 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
{nullptr, 0, QMetaType::UnknownType}
};
-Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
-Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
+// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class
+static constexpr struct : QMetaTypeModuleHelper
+{
+ template<typename T, typename LiteralWrapper =
+ std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
+ static inline bool convertToBool(const T &source)
+ {
+ T str = source.toLower();
+ return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
+ }
+
+ const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ default:
+ return nullptr;
+ }
+ }
+
+ bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override
+ {
+ Q_ASSERT(fromTypeId != toTypeId);
+
+ // canConvert calls with two nullptr
+ bool onlyCheck = (from == nullptr && to == nullptr);
+
+ // other callers must provide two valid pointers
+ Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
+
+ using Char = char;
+ using SChar = signed char;
+ using UChar = unsigned char;
+ using Short = short;
+ using UShort = unsigned short;
+ using Int = int;
+ using UInt = unsigned int;
+ using Long = long;
+ using LongLong = qlonglong;
+ using ULong = unsigned long;
+ using ULongLong = qulonglong;
+ using Float = float;
+ using Double = double;
+ using Bool = bool;
+ using Nullptr = std::nullptr_t;
+ using Char16 = char16_t;
+ using Char32 = char32_t;
+
+#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From) \
+ QMETATYPE_CONVERTER(To, From, result = double(source); return true;)
+#define QMETATYPE_CONVERTER_ASSIGN_NUMBER(To, From) \
+ QMETATYPE_CONVERTER(To, From, result = To::number(source); return true;)
+#ifndef QT_BOOTSTRAPPED
+#define CONVERT_CBOR_AND_JSON(To) \
+ QMETATYPE_CONVERTER(To, QCborValue, \
+ if constexpr(std::is_same_v<To, Bool>) { \
+ if (!source.isBool()) \
+ return false; \
+ result = source.toBool(); \
+ } else { \
+ if (!source.isInteger() && !source.isDouble()) \
+ return false; \
+ if constexpr(std::is_integral_v<To>) \
+ result = source.toInteger(); \
+ else \
+ result = source.toDouble(); \
+ } \
+ return true; \
+ ); \
+ QMETATYPE_CONVERTER(To, QJsonValue, \
+ if constexpr(std::is_same_v<To, Bool>) { \
+ if (!source.isBool()) \
+ return false; \
+ result = source.toBool(); \
+ } else { \
+ if (!source.isDouble()) \
+ return false; \
+ if constexpr(std::is_integral_v<To>) \
+ result = source.toInteger(); \
+ else \
+ result = source.toDouble(); \
+ } \
+ return true; \
+ )
+#else
+#define CONVERT_CBOR_AND_JSON(To)
+#endif
+
+#define INTEGRAL_CONVERTER(To) \
+ QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Char); \
+ QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
+ QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Short); \
+ QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Int); \
+ QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Long); \
+ QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
+ QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
+ QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
+ QMETATYPE_CONVERTER(To, Float, result = qRound64(source); return true;); \
+ QMETATYPE_CONVERTER(To, Double, result = qRound64(source); return true;); \
+ QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;); \
+ QMETATYPE_CONVERTER(To, QString, \
+ bool ok = false; \
+ if constexpr(std::is_same_v<To, bool>) \
+ result = (ok = true, convertToBool(source)); \
+ else if constexpr(std::is_signed_v<To>) \
+ result = To(source.toLongLong(&ok)); \
+ else \
+ result = To(source.toULongLong(&ok)); \
+ return ok; \
+ ); \
+ QMETATYPE_CONVERTER(To, QByteArray, \
+ bool ok = false; \
+ if constexpr(std::is_same_v<To, bool>) \
+ result = (ok = true, convertToBool(source)); \
+ else if constexpr(std::is_signed_v<To>) \
+ result = To(source.toLongLong(&ok)); \
+ else \
+ result = To(source.toULongLong(&ok)); \
+ return ok; \
+ ); \
+ CONVERT_CBOR_AND_JSON(To)
+
+#define FLOAT_CONVERTER(To) \
+ QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Char); \
+ QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
+ QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Short); \
+ QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Int); \
+ QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Long); \
+ QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
+ QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
+ QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Float); \
+ QMETATYPE_CONVERTER_ASSIGN(To, Double); \
+ QMETATYPE_CONVERTER(To, QString, \
+ bool ok = false; \
+ result = source.toDouble(&ok); \
+ return ok; \
+ ); \
+ QMETATYPE_CONVERTER(To, QByteArray, \
+ bool ok = false; \
+ result = source.toDouble(&ok); \
+ return ok; \
+ ); \
+ CONVERT_CBOR_AND_JSON(To)
+
+ switch (makePair(toTypeId, fromTypeId)) {
+
+ // integral conversions
+ INTEGRAL_CONVERTER(Bool);
+ INTEGRAL_CONVERTER(Char);
+ INTEGRAL_CONVERTER(UChar);
+ INTEGRAL_CONVERTER(SChar);
+ INTEGRAL_CONVERTER(Short);
+ INTEGRAL_CONVERTER(UShort);
+ INTEGRAL_CONVERTER(Int);
+ INTEGRAL_CONVERTER(UInt);
+ INTEGRAL_CONVERTER(Long);
+ INTEGRAL_CONVERTER(ULong);
+ INTEGRAL_CONVERTER(LongLong);
+ INTEGRAL_CONVERTER(ULongLong);
+ FLOAT_CONVERTER(Float);
+ FLOAT_CONVERTER(Double);
+
+#ifndef QT_BOOTSTRAPPED
+ QMETATYPE_CONVERTER_ASSIGN(QUrl, QString);
+ QMETATYPE_CONVERTER(QUrl, QCborValue,
+ if (source.isUrl()) {
+ result = source.toUrl();
+ return true;
+ }
+ return false;
+ );
+#endif
+#if QT_CONFIG(itemmodel)
+ QMETATYPE_CONVERTER_ASSIGN(QModelIndex, QPersistentModelIndex);
+ QMETATYPE_CONVERTER_ASSIGN(QPersistentModelIndex, QModelIndex);
+#endif // QT_CONFIG(itemmodel)
+
+ // QChar methods
+#define QMETATYPE_CONVERTER_ASSIGN_QCHAR(From) \
+ QMETATYPE_CONVERTER(QChar, From, result = QChar::fromUcs2(source); return true;)
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Char);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(SChar);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Short);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Long);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Int);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(LongLong);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Float);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(UChar);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(UShort);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULong);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(UInt);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULongLong);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Char16);
+
+ QMETATYPE_CONVERTER(Char16, QChar, result = source.unicode(); return true;)
+
+ // conversions to QString
+ QMETATYPE_CONVERTER_ASSIGN(QString, QChar);
+ QMETATYPE_CONVERTER(QString, Bool,
+ result = source ? QStringLiteral("true") : QStringLiteral("false");
+ return true;
+ );
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Short);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Long);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Int);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, LongLong);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UShort);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULong);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UInt);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULongLong);
+ QMETATYPE_CONVERTER(QString, Float,
+ result = QString::number(source, 'g', QLocale::FloatingPointShortest);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, Double,
+ result = QString::number(source, 'g', QLocale::FloatingPointShortest);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, Char,
+ result = QString::fromLatin1(&source, 1);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, SChar,
+ char s = source;
+ result = QString::fromLatin1(&s, 1);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, UChar,
+ char s = source;
+ result = QString::fromLatin1(&s, 1);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, Char16,
+ result = QChar(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, Char32,
+ result = QChar::fromUcs4(source).operator QStringView().toString();
+ return true;
+ );
+#if QT_CONFIG(datestring)
+ QMETATYPE_CONVERTER(QString, QDate, result = source.toString(Qt::ISODate); return true;);
+ QMETATYPE_CONVERTER(QString, QTime, result = source.toString(Qt::ISODateWithMs); return true;);
+ QMETATYPE_CONVERTER(QString, QDateTime, result = source.toString(Qt::ISODateWithMs); return true;);
+#endif
+ QMETATYPE_CONVERTER(QString, QByteArray, result = QString::fromUtf8(source); return true;);
+ QMETATYPE_CONVERTER(QString, QStringList,
+ return (source.size() == 1) ? (result = source.at(0), true) : false;
+ );
+#ifndef QT_BOOTSTRAPPED
+ QMETATYPE_CONVERTER(QString, QUrl, result = source.toString(); return true;);
+ QMETATYPE_CONVERTER(QString, QJsonValue,
+ if (source.isString() || source.isNull()) {
+ result = source.toString();
+ return true;
+ }
+ return false;
+ );
+#endif
+ QMETATYPE_CONVERTER(QString, Nullptr, Q_UNUSED(source); result = QString(); return true;);
+
+ // QByteArray
+ QMETATYPE_CONVERTER(QByteArray, QString, result = source.toUtf8(); return true;);
+ QMETATYPE_CONVERTER(QByteArray, Bool,
+ result = source ? "true" : "false";
+ return true;
+ );
+ QMETATYPE_CONVERTER(QByteArray, Char, result = QByteArray(source, 1); return true;);
+ QMETATYPE_CONVERTER(QByteArray, SChar, result = QByteArray(source, 1); return true;);
+ QMETATYPE_CONVERTER(QByteArray, UChar, result = QByteArray(source, 1); return true;);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Short);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Long);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Int);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, LongLong);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UShort);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULong);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UInt);
+ QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULongLong);
+ QMETATYPE_CONVERTER(QByteArray, Float,
+ result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QByteArray, Double,
+ result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QByteArray, Nullptr, Q_UNUSED(source); result = QByteArray(); return true;);
+
+ QMETATYPE_CONVERTER(QString, QUuid, result = source.toString(); return true;);
+ QMETATYPE_CONVERTER(QUuid, QString, result = QUuid(source); return true;);
+ QMETATYPE_CONVERTER(QByteArray, QUuid, result = source.toByteArray(); return true;);
+ QMETATYPE_CONVERTER(QUuid, QByteArray, result = QUuid(source); return true;);
+
+#ifndef QT_NO_GEOM_VARIANT
+ QMETATYPE_CONVERTER(QSize, QSizeF, result = source.toSize(); return true;);
+ QMETATYPE_CONVERTER_ASSIGN(QSizeF, QSize);
+ QMETATYPE_CONVERTER(QLine, QLineF, result = source.toLine(); return true;);
+ QMETATYPE_CONVERTER_ASSIGN(QLineF, QLine);
+ QMETATYPE_CONVERTER(QRect, QRectF, result = source.toRect(); return true;);
+ QMETATYPE_CONVERTER_ASSIGN(QRectF, QRect);
+ QMETATYPE_CONVERTER(QPoint, QPointF, result = source.toPoint(); return true;);
+ QMETATYPE_CONVERTER_ASSIGN(QPointF, QPoint);
+#endif
+
+ QMETATYPE_CONVERTER(QStringList, QString, result = QStringList() << source; return true;);
+
+#ifndef QT_NO_VARIANT
+ QMETATYPE_CONVERTER(QByteArrayList, QVariantList,
+ result.reserve(source.size());
+ for (const auto &v: source)
+ result.append(v.toByteArray());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantList, QByteArrayList,
+ result.reserve(source.size());
+ for (const auto &v: source)
+ result.append(QVariant(v));
+ return true;
+ );
+
+ QMETATYPE_CONVERTER(QStringList, QVariantList,
+ result.reserve(source.size());
+ for (const auto &v: source)
+ result.append(v.toString());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantList, QStringList,
+ result.reserve(source.size());
+ for (const auto &v: source)
+ result.append(QVariant(v));
+ return true;
+ );
+
+ QMETATYPE_CONVERTER(QVariantHash, QVariantMap,
+ for (auto it = source.begin(); it != source.end(); ++it)
+ result.insert(it.key(), it.value());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantMap, QVariantHash,
+ for (auto it = source.begin(); it != source.end(); ++it)
+ result.insert(it.key(), it.value());
+ return true;
+ );
+#endif // !QT_NO_VARIANT
+#ifndef QT_BOOTSTRAPPED
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QString);
+ QMETATYPE_CONVERTER(QString, QCborValue,
+ if (source.isContainer() || source.isTag())
+ return false;
+ result = source.toVariant().toString();
+ return true;
+ );
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QByteArray);
+ QMETATYPE_CONVERTER(QByteArray, QCborValue,
+ if (source.isByteArray()) {
+ result = source.toByteArray();
+ return true;
+ }
+ return false;
+ );
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUuid);
+ QMETATYPE_CONVERTER(QUuid, QCborValue,
+ if (!source.isUuid())
+ return false;
+ result = source.toUuid();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QVariantList, result = QCborArray::fromVariantList(source); return true;);
+ QMETATYPE_CONVERTER(QVariantList, QCborValue,
+ if (!source.isArray())
+ return false;
+ result = source.toArray().toVariantList();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
+ QMETATYPE_CONVERTER(QVariantMap, QCborValue,
+ if (!source.isMap())
+ return false;
+ result = source.toMap().toVariantMap();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
+ QMETATYPE_CONVERTER(QVariantHash, QCborValue,
+ if (!source.isMap())
+ return false;
+ result = source.toMap().toVariantHash();
+ return true;
+ );
+#if QT_CONFIG(regularexpression)
+ QMETATYPE_CONVERTER(QCborValue, QRegularExpression, result = QCborValue(source); return true;);
+ QMETATYPE_CONVERTER(QRegularExpression, QCborValue,
+ if (!source.isRegularExpression())
+ return false;
+ result = source.toRegularExpression();
+ return true;
+ );
+#endif
+
+ QMETATYPE_CONVERTER(QCborValue, Nullptr,
+ Q_UNUSED(source);
+ result = QCborValue(QCborValue::Null);
+ return true;
+ );
+ QMETATYPE_CONVERTER(Nullptr, QCborValue,
+ result = nullptr;
+ return source.isNull();
+ );
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, Bool);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, Int);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, UInt);
+ QMETATYPE_CONVERTER(QCborValue, ULong, result = qlonglong(source); return true;);
+ QMETATYPE_CONVERTER(QCborValue, Long, result = qlonglong(source); return true;);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, LongLong);
+ QMETATYPE_CONVERTER(QCborValue, ULongLong, result = qlonglong(source); return true;);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, UShort);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, UChar);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, Char);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, SChar);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, Short);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, Double);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, Float);
+ QMETATYPE_CONVERTER(QCborValue, QStringList,
+ result = QCborArray::fromStringList(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QDate,
+ result = QCborValue(source.startOfDay());
+ return true;
+ );
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUrl);
+ QMETATYPE_CONVERTER(QCborValue, QJsonValue,
+ result = QCborValue::fromJsonValue(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QJsonObject,
+ result = QCborMap::fromJsonObject(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QJsonArray,
+ result = QCborArray::fromJsonArray(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborValue, QJsonDocument,
+ QJsonDocument doc = source;
+ if (doc.isArray())
+ result = QCborArray::fromJsonArray(doc.array());
+ else
+ result = QCborMap::fromJsonObject(doc.object());
+ return true;
+ );
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborMap);
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborArray);
+
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QDateTime);
+ QMETATYPE_CONVERTER(QDateTime, QCborValue,
+ if (source.isDateTime()) {
+ result = source.toDateTime();
+ return true;
+ }
+ return false;
+ );
+
+ QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborSimpleType);
+ QMETATYPE_CONVERTER(QCborSimpleType, QCborValue,
+ if (source.isSimpleType()) {
+ result = source.toSimpleType();
+ return true;
+ }
+ return false;
+ );
+
+ QMETATYPE_CONVERTER(QCborArray, QVariantList, result = QCborArray::fromVariantList(source); return true;);
+ QMETATYPE_CONVERTER(QVariantList, QCborArray, result = source.toVariantList(); return true;);
+ QMETATYPE_CONVERTER(QCborArray, QStringList, result = QCborArray::fromStringList(source); return true;);
+ QMETATYPE_CONVERTER(QCborMap, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
+ QMETATYPE_CONVERTER(QVariantMap, QCborMap, result = source.toVariantMap(); return true;);
+ QMETATYPE_CONVERTER(QCborMap, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
+ QMETATYPE_CONVERTER(QVariantHash, QCborMap, result = source.toVariantHash(); return true;);
+
+ QMETATYPE_CONVERTER(QCborArray, QCborValue,
+ if (!source.isArray())
+ return false;
+ result = source.toArray();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborArray, QJsonDocument,
+ if (!source.isArray())
+ return false;
+ result = QCborArray::fromJsonArray(source.array());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborArray, QJsonValue,
+ if (!source.isArray())
+ return false;
+ result = QCborArray::fromJsonArray(source.toArray());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborArray, QJsonArray,
+ result = QCborArray::fromJsonArray(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborMap, QCborValue,
+ if (!source.isMap())
+ return false;
+ result = source.toMap();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborMap, QJsonDocument,
+ if (source.isArray())
+ return false;
+ result = QCborMap::fromJsonObject(source.object());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborMap, QJsonValue,
+ if (!source.isObject())
+ return false;
+ result = QCborMap::fromJsonObject(source.toObject());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QCborMap, QJsonObject,
+ result = QCborMap::fromJsonObject(source);
+ return true;
+ );
+
+
+ QMETATYPE_CONVERTER(QVariantList, QJsonValue,
+ if (!source.isArray())
+ return false;
+ result = source.toArray().toVariantList();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantList, QJsonArray, result = source.toVariantList(); return true;);
+ QMETATYPE_CONVERTER(QVariantMap, QJsonValue,
+ if (!source.isObject())
+ return false;
+ result = source.toObject().toVariantMap();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantMap, QJsonObject, result = source.toVariantMap(); return true;);
+ QMETATYPE_CONVERTER(QVariantHash, QJsonValue,
+ if (!source.isObject())
+ return false;
+ result = source.toObject().toVariantHash();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantHash, QJsonObject, result = source.toVariantHash(); return true;);
+
+
+ QMETATYPE_CONVERTER(QJsonArray, QStringList, result = QJsonArray::fromStringList(source); return true;);
+ QMETATYPE_CONVERTER(QJsonArray, QVariantList, result = QJsonArray::fromVariantList(source); return true;);
+ QMETATYPE_CONVERTER(QJsonArray, QJsonValue,
+ if (!source.isArray())
+ return false;
+ result = source.toArray();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonArray, QJsonDocument,
+ if (!source.isArray())
+ return false;
+ result = source.array();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonArray, QCborValue,
+ if (!source.isArray())
+ return false;
+ result = source.toArray().toJsonArray();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonArray, QCborArray, result = source.toJsonArray(); return true;);
+ QMETATYPE_CONVERTER(QJsonObject, QVariantMap, result = QJsonObject::fromVariantMap(source); return true;);
+ QMETATYPE_CONVERTER(QJsonObject, QVariantHash, result = QJsonObject::fromVariantHash(source); return true;);
+ QMETATYPE_CONVERTER(QJsonObject, QJsonValue,
+ if (!source.isObject())
+ return false;
+ result = source.toObject();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonObject, QJsonDocument,
+ if (source.isArray())
+ return false;
+ result = source.object();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonObject, QCborValue,
+ if (!source.isMap())
+ return false;
+ result = source.toMap().toJsonObject();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonObject, QCborMap, result = source.toJsonObject(); return true; );
+
+ QMETATYPE_CONVERTER(QJsonValue, Nullptr,
+ Q_UNUSED(source);
+ result = QJsonValue(QJsonValue::Null);
+ return true;
+ );
+ QMETATYPE_CONVERTER(Nullptr, QJsonValue,
+ result = nullptr;
+ return source.isNull();
+ );
+ QMETATYPE_CONVERTER(QJsonValue, Bool,
+ result = QJsonValue(source);
+ return true;);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Int);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UInt);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Double);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULong);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Long);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, LongLong);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULongLong);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UShort);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UChar);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Char);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, SChar);
+ QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Short);
+ QMETATYPE_CONVERTER_ASSIGN(QJsonValue, QString);
+ QMETATYPE_CONVERTER(QJsonValue, QStringList,
+ result = QJsonValue(QJsonArray::fromStringList(source));
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QVariantList,
+ result = QJsonValue(QJsonArray::fromVariantList(source));
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QVariantMap,
+ result = QJsonValue(QJsonObject::fromVariantMap(source));
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QVariantHash,
+ result = QJsonValue(QJsonObject::fromVariantHash(source));
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QJsonObject,
+ result = source;
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QJsonArray,
+ result = source;
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QJsonDocument,
+ QJsonDocument doc = source;
+ result = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QCborValue,
+ result = source.toJsonValue();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QCborMap,
+ result = source.toJsonObject();
+ return true;
+ );
+ QMETATYPE_CONVERTER(QJsonValue, QCborArray,
+ result = source.toJsonArray();
+ return true;
+ );
+
+#endif
+
+ QMETATYPE_CONVERTER(QDate, QDateTime, result = source.date(); return true;);
+ QMETATYPE_CONVERTER(QTime, QDateTime, result = source.time(); return true;);
+ QMETATYPE_CONVERTER(QDateTime, QDate, result = source.startOfDay(); return true;);
+#if QT_CONFIG(datestring)
+ QMETATYPE_CONVERTER(QDate, QString,
+ result = QDate::fromString(source, Qt::ISODate);
+ return result.isValid();
+ );
+ QMETATYPE_CONVERTER(QTime, QString,
+ result = QTime::fromString(source, Qt::ISODate);
+ return result.isValid();
+ );
+ QMETATYPE_CONVERTER(QDateTime, QString,
+ result = QDateTime::fromString(source, Qt::ISODate);
+ return result.isValid();
+ );
+#endif
+
+ }
+ return false;
+ }
+} metatypeHelper = {};
+
+Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
+Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
static const QMetaTypeModuleHelper *qModuleHelperForType(int type)
{
+ if (type <= QMetaType::LastCoreType)
+ return &metatypeHelper;
if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
return qMetaTypeGuiHelper;
else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
@@ -760,20 +1689,22 @@ public:
return map.contains(k);
}
- bool insertIfNotContains(Key k, const T *f)
+ bool insertIfNotContains(Key k, const T &f)
{
const QWriteLocker locker(&lock);
- const T* &fun = map[k];
- if (fun)
+ const qsizetype oldSize = map.size();
+ auto &e = map[k];
+ if (map.size() == oldSize) // already present
return false;
- fun = f;
+ e = f;
return true;
}
const T *function(Key k) const
{
const QReadLocker locker(&lock);
- return map.value(k, nullptr);
+ auto it = map.find(k);
+ return it == map.end() ? nullptr : std::addressof(*it);
}
void remove(int from, int to)
@@ -784,88 +1715,107 @@ public:
}
private:
mutable QReadWriteLock lock;
- QHash<Key, const T *> map;
+ QHash<Key, T> map;
};
-typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
-QMetaTypeConverterRegistry;
-typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int>
-QMetaTypeComparatorRegistry;
-typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
-QMetaTypeDebugStreamRegistry;
+using QMetaTypeConverterRegistry
+ = QMetaTypeFunctionRegistry<QMetaType::ConverterFunction, std::pair<int,int>>;
Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
-Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry)
-Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
+
+using QMetaTypeMutableViewRegistry
+ = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, std::pair<int,int>>;
+Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
/*!
- \fn bool QMetaType::registerConverter()
+ \fn template<typename From, typename To> bool QMetaType::registerConverter()
\since 5.2
Registers the possibility of an implicit conversion from type From to type To in the meta
type system. Returns \c true if the registration succeeded, otherwise false.
+
+ \snippet qmetatype/registerConverters.cpp implicit
*/
/*!
- \fn template<typename MemberFunction, int> bool QMetaType::registerConverter(MemberFunction function)
+ \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)() const)
\since 5.2
\overload
Registers a method \a function like To From::function() const as converter from type From
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
+
+ \snippet qmetatype/registerConverters.cpp member
*/
/*!
- \fn template<typename MemberFunctionOk, char> bool QMetaType::registerConverter(MemberFunctionOk function)
+ \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)(bool*) const)
\since 5.2
\overload
Registers a method \a function like To From::function(bool *ok) const as converter from type From
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
+
+ The \c ok pointer can be used by the function to indicate whether the conversion succeeded.
+ \snippet qmetatype/registerConverters.cpp memberOk
+
*/
/*!
- \fn template<typename UnaryFunction> bool QMetaType::registerConverter(UnaryFunction function)
+ \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerConverter(UnaryFunction function)
\since 5.2
\overload
Registers a unary function object \a function as converter from type From
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
+
+ \a function must take an instance of type \c From and return an instance of \c To. It can be a function
+ pointer, a lambda or a functor object. Since Qt 6.5, the \a function can also return an instance of
+ \c std::optional<To> to be able to indicate failed conversions.
+ \snippet qmetatype/registerConverters.cpp unaryfunc
*/
/*!
- \fn bool QMetaType::registerComparators()
- \since 5.2
- Registers comparison operators for the user-registered type T. This requires T to have
- both an operator== and an operator<.
+ Registers function \a f as converter function from type id \a from to \a to.
+ If there's already a conversion registered, this does nothing but deleting \a f.
Returns \c true if the registration succeeded, otherwise false.
+ \since 5.2
+ \internal
*/
+bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to)
+{
+ if (!customTypesConversionRegistry()->insertIfNotContains({from.id(), to.id()}, f)) {
+ qWarning("Type conversion already registered from type %s to type %s",
+ from.name(), to.name());
+ return false;
+ }
+ return true;
+}
/*!
- \fn bool QMetaType::registerEqualsComparator()
- \since 5.5
- Registers equals operator for the user-registered type T. This requires T to have
- an operator==.
- Returns \c true if the registration succeeded, otherwise false.
+ \fn template<typename From, typename To> static bool QMetaType::registerMutableView(To(From::*function)())
+ \since 6.0
+ \overload
+ Registers a method \a function like \c {To From::function()} as mutable view of type \c {To} on
+ type \c {From} in the meta type system. Returns \c true if the registration succeeded, otherwise
+ \c false.
*/
-#ifndef QT_NO_DEBUG_STREAM
/*!
- \fn bool QMetaType::registerDebugStreamOperator()
- Registers the debug stream operator for the user-registered type T. This requires T to have
- an operator<<(QDebug dbg, T).
- Returns \c true if the registration succeeded, otherwise false.
+ \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerMutableView(UnaryFunction function)
+ \since 6.0
+ \overload
+ Registers a unary function object \a function as mutable view of type To on type From
+ in the meta type system. Returns \c true if the registration succeeded, otherwise \c false.
*/
-#endif
/*!
- Registers function \a f as converter function from type id \a from to \a to.
- If there's already a conversion registered, this does nothing but deleting \a f.
- Returns \c true if the registration succeeded, otherwise false.
- \since 5.2
+ Registers function \a f as mutable view of type id \a to on type id \a from.
+ Returns \c true if the registration succeeded, otherwise \c false.
+ \since 6.0
\internal
*/
-bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to)
+bool QMetaType::registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to)
{
- if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from, to), f)) {
- qWarning("Type conversion already registered from type %s to type %s",
- QMetaType::typeName(from), QMetaType::typeName(to));
+ if (!customTypesMutableViewRegistry()->insertIfNotContains({from.id(), to.id()}, f)) {
+ qWarning("Mutable view on type already registered from type %s to type %s",
+ from.name(), to.name());
return false;
}
return true;
@@ -873,280 +1823,872 @@ bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunc
/*!
\internal
-
- Invoked automatically when a converter function object is destroyed.
*/
-void QMetaType::unregisterConverterFunction(int from, int to)
+void QMetaType::unregisterMutableViewFunction(QMetaType from, QMetaType to)
{
- if (customTypesConversionRegistry.isDestroyed())
+ if (customTypesMutableViewRegistry.isDestroyed())
return;
- customTypesConversionRegistry()->remove(from, to);
+ customTypesMutableViewRegistry()->remove(from.id(), to.id());
}
-bool QMetaType::registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type)
+/*!
+ \internal
+
+ Invoked automatically when a converter function object is destroyed.
+ */
+void QMetaType::unregisterConverterFunction(QMetaType from, QMetaType to)
{
- if (!customTypesComparatorRegistry()->insertIfNotContains(type, f)) {
- qWarning("Comparators already registered for type %s", QMetaType::typeName(type));
- return false;
- }
- return true;
+ if (customTypesConversionRegistry.isDestroyed())
+ return;
+ customTypesConversionRegistry()->remove(from.id(), to.id());
}
-/*!
- \fn bool QMetaType::hasRegisteredComparators()
- Returns \c true, if the meta type system has registered comparators for type T.
- \since 5.2
- */
+#ifndef QT_NO_DEBUG_STREAM
/*!
- Returns \c true, if the meta type system has registered comparators for type id \a typeId.
- \since 5.2
- */
-bool QMetaType::hasRegisteredComparators(int typeId)
+ \fn QDebug QMetaType::operator<<(QDebug d, QMetaType m)
+ \since 6.5
+ Writes the QMetaType \a m to the stream \a d, and returns the stream.
+*/
+QDebug operator<<(QDebug d, QMetaType m)
{
- return customTypesComparatorRegistry()->contains(typeId);
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "QMetaType(" << m.name() << ")";
}
-#ifndef QT_NO_DEBUG_STREAM
-bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f,
- int type)
+/*!
+ Streams the object at \a rhs to the debug stream \a dbg. Returns \c true
+ on success, otherwise false.
+ \since 5.2
+*/
+bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
{
- if (!customTypesDebugStreamRegistry()->insertIfNotContains(type, f)) {
- qWarning("Debug stream operator already registered for type %s", QMetaType::typeName(type));
- return false;
+ if (d_ptr && d_ptr->flags & QMetaType::IsPointer) {
+ dbg << *reinterpret_cast<const void * const *>(rhs);
+ return true;
}
- return true;
+ if (d_ptr && d_ptr->debugStream) {
+ d_ptr->debugStream(d_ptr, dbg, rhs);
+ return true;
+ }
+ return false;
}
/*!
- \fn bool QMetaType::hasRegisteredDebugStreamOperator()
- Returns \c true, if the meta type system has a registered debug stream operator for type T.
+ \fn bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
+ \overload
+ \deprecated
+*/
+
+/*!
+ \fn template<typename T> bool QMetaType::hasRegisteredDebugStreamOperator()
+ \deprecated
\since 5.2
+
+ Returns \c true, if the meta type system has a registered debug stream operator for type T.
*/
/*!
+ \fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
+ \deprecated Use QMetaType::hasRegisteredDebugStreamOperator() instead.
+
Returns \c true, if the meta type system has a registered debug stream operator for type
id \a typeId.
\since 5.2
*/
-bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
+
+/*!
+ \since 6.0
+
+ Returns \c true, if the meta type system has a registered debug stream operator for this
+ meta type.
+*/
+bool QMetaType::hasRegisteredDebugStreamOperator() const
{
- return customTypesDebugStreamRegistry()->contains(typeId);
+ return d_ptr && d_ptr->debugStream != nullptr;
}
#endif
+#ifndef QT_NO_QOBJECT
/*!
- Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
- typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
- \since 5.2
+ \internal
+ returns a QMetaEnum for a given meta tape type id if possible
*/
-bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
+static QMetaEnum metaEnumFromType(QMetaType t)
{
- const QtPrivate::AbstractConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
- return f && f->convert(f, from, to);
+ if (t.flags() & QMetaType::IsEnumeration) {
+ if (const QMetaObject *metaObject = t.metaObject()) {
+ QByteArrayView qflagsNamePrefix = "QFlags<";
+ QByteArray enumName = t.name();
+ if (enumName.endsWith('>') && enumName.startsWith(qflagsNamePrefix)) {
+ // extract the template argument
+ enumName.chop(1);
+ enumName = enumName.sliced(qflagsNamePrefix.size());
+ }
+ if (qsizetype lastColon = enumName.lastIndexOf(':'); lastColon != -1)
+ enumName = enumName.sliced(lastColon + 1);
+ return metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
+ }
+ }
+ return QMetaEnum();
}
+#endif
-/*!
- Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
- \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
- or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
- \since 5.2
-*/
-bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
+static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
{
- const QtPrivate::AbstractComparatorFunction * const f =
- customTypesComparatorRegistry()->function(typeId);
- if (!f)
+ qlonglong ll;
+ if (fromType.flags() & QMetaType::IsUnsignedEnumeration) {
+ qulonglong ull;
+ switch (fromType.sizeOf()) {
+ case 1:
+ ull = *static_cast<const unsigned char *>(from);
+ break;
+ case 2:
+ ull = *static_cast<const unsigned short *>(from);
+ break;
+ case 4:
+ ull = *static_cast<const unsigned int *>(from);
+ break;
+ case 8:
+ ull = *static_cast<const quint64 *>(from);
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ if (toType.id() == QMetaType::ULongLong) {
+ *static_cast<qulonglong *>(to) = ull;
+ return true;
+ }
+ if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
+ return QMetaType::convert(QMetaType::fromType<qulonglong>(), &ull, toType, to);
+ ll = qlonglong(ull);
+ } else {
+ switch (fromType.sizeOf()) {
+ case 1:
+ ll = *static_cast<const signed char *>(from);
+ break;
+ case 2:
+ ll = *static_cast<const short *>(from);
+ break;
+ case 4:
+ ll = *static_cast<const int *>(from);
+ break;
+ case 8:
+ ll = *static_cast<const qint64 *>(from);
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ if (toType.id() == QMetaType::LongLong) {
+ *static_cast<qlonglong *>(to) = ll;
+ return true;
+ }
+ if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
+ return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
+ }
+#ifndef QT_NO_QOBJECT
+ QMetaEnum en = metaEnumFromType(fromType);
+ if (en.isValid()) {
+ if (en.isFlag()) {
+ const QByteArray keys = en.valueToKeys(static_cast<int>(ll));
+ if (toType.id() == QMetaType::QString)
+ *static_cast<QString *>(to) = QString::fromUtf8(keys);
+ else
+ *static_cast<QByteArray *>(to) = keys;
+ } else {
+ const char *key = en.valueToKey(static_cast<int>(ll));
+ if (toType.id() == QMetaType::QString)
+ *static_cast<QString *>(to) = QString::fromUtf8(key);
+ else
+ *static_cast<QByteArray *>(to) = key;
+ }
+ return true;
+ }
+#endif
+ if (toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray)
+ return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
+ return false;
+}
+
+static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
+{
+ int fromTypeId = fromType.id();
+ qlonglong value = -1;
+ bool ok = false;
+#ifndef QT_NO_QOBJECT
+ if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
+ QMetaEnum en = metaEnumFromType(toType);
+ if (en.isValid()) {
+ QByteArray keys = (fromTypeId == QMetaType::QString)
+ ? static_cast<const QString *>(from)->toUtf8()
+ : *static_cast<const QByteArray *>(from);
+ value = en.keysToValue(keys.constData(), &ok);
+ }
+ }
+#endif
+ if (!ok) {
+ if (fromTypeId == QMetaType::LongLong) {
+ value = *static_cast<const qlonglong *>(from);
+ ok = true;
+ } else {
+ ok = QMetaType::convert(fromType, from, QMetaType::fromType<qlonglong>(), &value);
+ }
+ }
+
+ if (!ok)
return false;
- if (f->equals(f, lhs, rhs))
- *result = 0;
- else if (f->lessThan)
- *result = f->lessThan(f, lhs, rhs) ? -1 : 1;
- else
+
+ switch (toType.sizeOf()) {
+ case 1:
+ *static_cast<signed char *>(to) = value;
+ return true;
+ case 2:
+ *static_cast<qint16 *>(to) = value;
+ return true;
+ case 4:
+ *static_cast<qint32 *>(to) = value;
+ return true;
+ case 8:
+ *static_cast<qint64 *>(to) = value;
+ return true;
+ default:
+ Q_UNREACHABLE_RETURN(false);
+ }
+}
+
+#ifndef QT_BOOTSTRAPPED
+static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
+{
+ QSequentialIterable list;
+ if (!QMetaType::convert(fromType, from, QMetaType::fromType<QSequentialIterable>(), &list))
return false;
+
+ QVariantList &l = *static_cast<QVariantList *>(to);
+ l.clear();
+ l.reserve(list.size());
+ auto end = list.end();
+ for (auto it = list.begin(); it != end; ++it)
+ l << *it;
return true;
}
-/*!
- Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
- \a result is set to zero, if \a lhs equals to rhs. Returns \c true, if the comparison
- succeeded, otherwise \c false.
- \since 5.5
-*/
-bool QMetaType::equals(const void *lhs, const void *rhs, int typeId, int *result)
+static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
{
- const QtPrivate::AbstractComparatorFunction * const f
- = customTypesComparatorRegistry()->function(typeId);
- if (!f)
+ QAssociativeIterable map;
+ if (!QMetaType::convert(fromType, from, QMetaType::fromType<QAssociativeIterable>(), &map))
return false;
- if (f->equals(f, lhs, rhs))
- *result = 0;
- else
- *result = -1;
+
+ QVariantMap &h = *static_cast<QVariantMap *>(to);
+ h.clear();
+ auto end = map.end();
+ for (auto it = map.begin(); it != end; ++it)
+ h.insert(it.key().toString(), it.value());
return true;
}
-/*!
- Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns \c true
- on success, otherwise false.
- \since 5.2
-*/
-bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
+static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
+{
+ QAssociativeIterable map;
+ if (!QMetaType::convert(fromType, from, QMetaType::fromType<QAssociativeIterable>(), &map))
+ return false;
+
+ QVariantHash &h = *static_cast<QVariantHash *>(to);
+ h.clear();
+ h.reserve(map.size());
+ auto end = map.end();
+ for (auto it = map.begin(); it != end; ++it)
+ h.insert(it.key().toString(), it.value());
+ return true;
+}
+
+static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
{
- const QtPrivate::AbstractDebugStreamFunction * const f = customTypesDebugStreamRegistry()->function(typeId);
+ const int targetId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ const auto f = customTypesConversionRegistry()->function({fromType.id(), targetId});
+
if (!f)
return false;
- f->stream(f, dbg, rhs);
+
+ QtMetaTypePrivate::QPairVariantInterfaceImpl pi;
+ (*f)(from, &pi);
+
+ QVariant v1(pi._metaType_first);
+ void *dataPtr;
+ if (pi._metaType_first == QMetaType::fromType<QVariant>())
+ dataPtr = &v1;
+ else
+ dataPtr = v1.data();
+ pi.first(dataPtr);
+
+ QVariant v2(pi._metaType_second);
+ if (pi._metaType_second == QMetaType::fromType<QVariant>())
+ dataPtr = &v2;
+ else
+ dataPtr = v2.data();
+ pi.second(dataPtr);
+
+ *static_cast<QVariantPair *>(to) = QVariantPair(v1, v2);
return true;
}
+static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
+{
+ using namespace QtMetaTypePrivate;
+ const int fromTypeId = fromType.id();
+
+ QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
+ switch (fromTypeId) {
+ case QMetaType::QVariantList:
+ i = QSequentialIterable(reinterpret_cast<const QVariantList *>(from));
+ return true;
+ case QMetaType::QStringList:
+ i = QSequentialIterable(reinterpret_cast<const QStringList *>(from));
+ return true;
+ case QMetaType::QByteArrayList:
+ i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
+ return true;
+ case QMetaType::QString:
+ i = QSequentialIterable(reinterpret_cast<const QString *>(from));
+ return true;
+ case QMetaType::QByteArray:
+ i = QSequentialIterable(reinterpret_cast<const QByteArray *>(from));
+ return true;
+ default: {
+ QSequentialIterable impl;
+ if (QMetaType::convert(
+ fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &impl)) {
+ i = std::move(impl);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool canConvertToSequentialIterable(QMetaType fromType)
+{
+ switch (fromType.id()) {
+ case QMetaType::QVariantList:
+ case QMetaType::QStringList:
+ case QMetaType::QByteArrayList:
+ case QMetaType::QString:
+ case QMetaType::QByteArray:
+ return true;
+ default:
+ return QMetaType::canConvert(fromType, QMetaType::fromType<QIterable<QMetaSequence>>());
+ }
+}
+
+static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
+{
+ switch (fromType.id()) {
+ case QMetaType::QVariantList:
+ case QMetaType::QStringList:
+ case QMetaType::QByteArrayList:
+ case QMetaType::QString:
+ case QMetaType::QByteArray:
+ return true;
+ default:
+ return QMetaType::canView(
+ fromType, QMetaType::fromType<QIterable<QMetaSequence>>());
+ }
+}
+
+static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
+{
+ using namespace QtMetaTypePrivate;
+ const int fromTypeId = fromType.id();
+
+ QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
+ switch (fromTypeId) {
+ case QMetaType::QVariantList:
+ i = QSequentialIterable(reinterpret_cast<QVariantList *>(from));
+ return true;
+ case QMetaType::QStringList:
+ i = QSequentialIterable(reinterpret_cast<QStringList *>(from));
+ return true;
+ case QMetaType::QByteArrayList:
+ i = QSequentialIterable(reinterpret_cast<QByteArrayList *>(from));
+ return true;
+ case QMetaType::QString:
+ i = QSequentialIterable(reinterpret_cast<QString *>(from));
+ return true;
+ case QMetaType::QByteArray:
+ i = QSequentialIterable(reinterpret_cast<QByteArray *>(from));
+ return true;
+ default: {
+ QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
+ if (QMetaType::view(
+ fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &j)) {
+ i = std::move(j);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool convertToAssociativeIterable(QMetaType fromType, const void *from, void *to)
+{
+ using namespace QtMetaTypePrivate;
+
+ QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
+ if (fromType.id() == QMetaType::QVariantMap) {
+ i = QAssociativeIterable(reinterpret_cast<const QVariantMap *>(from));
+ return true;
+ }
+ if (fromType.id() == QMetaType::QVariantHash) {
+ i = QAssociativeIterable(reinterpret_cast<const QVariantHash *>(from));
+ return true;
+ }
+
+ QAssociativeIterable impl;
+ if (QMetaType::convert(
+ fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &impl)) {
+ i = std::move(impl);
+ return true;
+ }
+
+ return false;
+}
+
+static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
+{
+ if ((fromType.flags() & QMetaType::IsPointer) != (toType.flags() & QMetaType::IsPointer))
+ return false; // Can not convert between pointer and value
+
+ const QMetaObject *f = fromType.metaObject();
+ const QMetaObject *t = toType.metaObject();
+ if (f && t) {
+ return f->inherits(t) || (t->inherits(f));
+ }
+ return false;
+}
+
+static bool canConvertToAssociativeIterable(QMetaType fromType)
+{
+ switch (fromType.id()) {
+ case QMetaType::QVariantMap:
+ case QMetaType::QVariantHash:
+ return true;
+ default:
+ return QMetaType::canConvert(fromType, QMetaType::fromType<QIterable<QMetaAssociation>>());
+ }
+}
+
+static bool canImplicitlyViewAsAssociativeIterable(QMetaType fromType)
+{
+ switch (fromType.id()) {
+ case QMetaType::QVariantMap:
+ case QMetaType::QVariantHash:
+ return true;
+ default:
+ return QMetaType::canView(
+ fromType, QMetaType::fromType<QIterable<QMetaAssociation>>());
+ }
+}
+
+static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
+{
+ using namespace QtMetaTypePrivate;
+ int fromTypeId = fromType.id();
+
+ QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
+ if (fromTypeId == QMetaType::QVariantMap) {
+ i = QAssociativeIterable(reinterpret_cast<QVariantMap *>(from));
+ return true;
+ }
+ if (fromTypeId == QMetaType::QVariantHash) {
+ i = QAssociativeIterable(reinterpret_cast<QVariantHash *>(from));
+ return true;
+ }
+
+ QIterable<QMetaAssociation> j(QMetaAssociation(), nullptr);
+ if (QMetaType::view(
+ fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &j)) {
+ i = std::move(j);
+ return true;
+ }
+
+ return false;
+}
+
+static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
+{
+ // handle QObject conversion
+ if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
+ QObject *fromObject = *static_cast<QObject * const *>(from);
+ // use dynamic metatype of from if possible
+ if (fromObject && fromObject->metaObject()->inherits(toType.metaObject())) {
+ *static_cast<QObject **>(to) = toType.metaObject()->cast(fromObject);
+ return true;
+ } else if (!fromObject && fromType.metaObject()) {
+ // if fromObject is null, use static fromType to check if conversion works
+ *static_cast<void **>(to) = nullptr;
+ return fromType.metaObject()->inherits(toType.metaObject());
+ }
+ } else if ((fromType.flags() & QMetaType::IsPointer) == (toType.flags() & QMetaType::IsPointer)) {
+ // fromType and toType are of same 'pointedness'
+ const QMetaObject *f = fromType.metaObject();
+ const QMetaObject *t = toType.metaObject();
+ if (f && t && f->inherits(t)) {
+ toType.destruct(to);
+ toType.construct(to, from);
+ return true;
+ }
+ }
+ return false;
+}
+#endif // !QT_BOOTSTRAPPED
+
/*!
- \fn bool QMetaType::hasRegisteredConverterFunction()
- Returns \c true, if the meta type system has a registered conversion from type From to type To.
+ \fn bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
+ \deprecated
+
+ Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
+ typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
+
+ Both \a from and \a to have to be valid pointers.
+
\since 5.2
- \overload
- */
+*/
/*!
- Returns \c true, if the meta type system has a registered conversion from meta type id \a fromTypeId
- to \a toTypeId
+ Converts the object at \a from from \a fromType to the preallocated space at \a to
+ typed \a toType. Returns \c true, if the conversion succeeded, otherwise false.
+
+ Both \a from and \a to have to be valid pointers.
+
\since 5.2
*/
-bool QMetaType::hasRegisteredConverterFunction(int fromTypeId, int toTypeId)
+bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
{
- return customTypesConversionRegistry()->contains(qMakePair(fromTypeId, toTypeId));
+ if (!fromType.isValid() || !toType.isValid())
+ return false;
+
+ if (fromType == toType) {
+ // just make a copy
+ fromType.destruct(to);
+ fromType.construct(to, from);
+ return true;
+ }
+
+ int fromTypeId = fromType.id();
+ int toTypeId = toType.id();
+
+ if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
+ if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
+ return true;
+ }
+ const auto f = customTypesConversionRegistry()->function({fromTypeId, toTypeId});
+ if (f)
+ return (*f)(from, to);
+
+ if (fromType.flags() & QMetaType::IsEnumeration)
+ return convertFromEnum(fromType, from, toType, to);
+ if (toType.flags() & QMetaType::IsEnumeration)
+ return convertToEnum(fromType, from, toType, to);
+ if (toTypeId == Nullptr) {
+ *static_cast<std::nullptr_t *>(to) = nullptr;
+ if (fromType.flags() & QMetaType::IsPointer) {
+ if (*static_cast<const void * const *>(from) == nullptr)
+ return true;
+ }
+ }
+
+#ifndef QT_BOOTSTRAPPED
+# ifndef QT_NO_VARIANT
+ if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
+ return true;
+
+ // handle iterables
+ if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
+ return true;
+
+ if (toTypeId == QVariantMap && convertIterableToVariantMap(fromType, from, to))
+ return true;
+
+ if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
+ return true;
+# endif
+
+ if (toTypeId == qMetaTypeId<QSequentialIterable>())
+ return convertToSequentialIterable(fromType, from, to);
+
+ if (toTypeId == qMetaTypeId<QAssociativeIterable>())
+ return convertToAssociativeIterable(fromType, from, to);
+
+ return convertMetaObject(fromType, from, toType, to);
+#else
+ return false;
+#endif
}
-#ifndef QT_NO_DATASTREAM
/*!
- \internal
+ Creates a mutable view on the object at \a from of \a fromType in the preallocated space at
+ \a to typed \a toType. Returns \c true if the conversion succeeded, otherwise false.
+ \since 6.0
*/
-void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
- LoadOperator loadOp)
+bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
{
- registerStreamOperators(type(typeName), saveOp, loadOp);
+ if (!fromType.isValid() || !toType.isValid())
+ return false;
+
+ int fromTypeId = fromType.id();
+ int toTypeId = toType.id();
+
+ const auto f = customTypesMutableViewRegistry()->function({fromTypeId, toTypeId});
+ if (f)
+ return (*f)(from, to);
+
+#ifndef QT_BOOTSTRAPPED
+ if (toTypeId == qMetaTypeId<QSequentialIterable>())
+ return viewAsSequentialIterable(fromType, from, to);
+
+ if (toTypeId == qMetaTypeId<QAssociativeIterable>())
+ return viewAsAssociativeIterable(fromType, from, to);
+
+ return convertMetaObject(fromType, from, toType, to);
+#else
+ return false;
+#endif
}
/*!
- \internal
+ Returns \c true if QMetaType::view can create a mutable view of type \a toType
+ on type \a fromType.
+
+ Converting between pointers of types derived from QObject will return true for this
+ function if a qobject_cast from the type described by \a fromType to the type described
+ by \a toType would succeed.
+
+ You can create a mutable view of type QSequentialIterable on any container registered with
+ Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE().
+
+ Similarly you can create a mutable view of type QAssociativeIterable on any container
+ registered with Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE().
+
+ \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(),
+ QAssociativeIterable, Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
*/
-void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
- LoadOperator loadOp)
+bool QMetaType::canView(QMetaType fromType, QMetaType toType)
{
- if (idx < User)
- return; //builtin types should not be registered;
+ int fromTypeId = fromType.id();
+ int toTypeId = toType.id();
- if (auto reg = customTypeRegistry()) {
- QWriteLocker locker(&reg->lock);
- reg->dataStreamOp[idx] = { saveOp, loadOp };
- }
-}
-#endif // QT_NO_DATASTREAM
-
-// We don't officially support constexpr in MSVC 2015, but the limited support it
-// has is enough for the code below.
+ if (fromTypeId == UnknownType || toTypeId == UnknownType)
+ return false;
-#define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \
- #RealName "\0"
-#define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \
- short(sizeof(#RealName)),
-#define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \
- TypeId,
+ const auto f = customTypesMutableViewRegistry()->function({fromTypeId, toTypeId});
+ if (f)
+ return true;
-namespace {
-// All type names in one long string.
-constexpr char metaTypeStrings[] = QT_FOR_EACH_STATIC_TYPE(STRINGIFY_TYPE_NAME);
+#ifndef QT_BOOTSTRAPPED
+ if (toTypeId == qMetaTypeId<QSequentialIterable>())
+ return canImplicitlyViewAsSequentialIterable(fromType);
-// The sizes of the strings in the metaTypeStrings string (including terminating null)
-constexpr short metaTypeNameSizes[] = {
- QT_FOR_EACH_STATIC_TYPE(CALCULATE_TYPE_LEN)
-};
+ if (toTypeId == qMetaTypeId<QAssociativeIterable>())
+ return canImplicitlyViewAsAssociativeIterable(fromType);
-// The type IDs, in the order of the metaTypeStrings data
-constexpr short metaTypeIds[] = {
- QT_FOR_EACH_STATIC_TYPE(MAP_TYPE_ID_TO_IDX)
-};
+ if (canConvertMetaObject(fromType, toType))
+ return true;
+#endif
-constexpr int MetaTypeNameCount = sizeof(metaTypeNameSizes) / sizeof(metaTypeNameSizes[0]);
+ return false;
+}
-template <typename IntegerSequence> struct MetaTypeOffsets;
-template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds...>>
+/*!
+ Returns \c true if QMetaType::convert can convert from \a fromType to
+ \a toType.
+
+ The following conversions are supported by Qt:
+
+ \table
+ \header \li Type \li Automatically Cast To
+ \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
+ \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
+ \l QMetaType::UInt, \l QMetaType::ULongLong
+ \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
+ \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
+ \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
+ \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
+ \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
+ \row \li \l QMetaType::QColor \li \l QMetaType::QString
+ \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
+ \l QMetaType::QString
+ \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
+ \l QMetaType::QString, \l QMetaType::QTime
+ \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
+ \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
+ \l QMetaType::ULongLong
+ \row \li \l QMetaType::QFont \li \l QMetaType::QString
+ \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
+ \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
+ \l QMetaType::UInt, \l QMetaType::ULongLong
+ \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
+ \l QMetaType::QString
+ \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
+ list's items can be converted to QStrings)
+ \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
+ \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
+ \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
+ \l QMetaType::ULongLong
+ \row \li \l QMetaType::QPoint \li QMetaType::QPointF
+ \row \li \l QMetaType::QRect \li QMetaType::QRectF
+ \row \li \l QMetaType::QString \li \l QMetaType::Bool,
+ \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
+ \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
+ \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
+ \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
+ \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
+ \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
+ \l QMetaType::QString (if the list contains exactly one item)
+ \row \li \l QMetaType::QTime \li \l QMetaType::QString
+ \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
+ \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
+ \l QMetaType::QString, \l QMetaType::ULongLong
+ \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
+ \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
+ \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
+ \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
+ \endtable
+
+ Casting between primitive type (int, float, bool etc.) is supported.
+
+ Converting between pointers of types derived from QObject will also return true for this
+ function if a qobject_cast from the type described by \a fromType to the type described
+ by \a toType would succeed.
+
+ A cast from a sequential container will also return true for this
+ function if the \a toType is QVariantList.
+
+ Similarly, a cast from an associative container will also return true for this
+ function the \a toType is QVariantHash or QVariantMap.
+
+ \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
+ Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
+*/
+bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
{
- // This would have been a lot easier if the meta types that the macro
- // QT_FOR_EACH_STATIC_TYPE declared were in sorted, ascending order, but
- // they're not (i.e., the first one declared is QMetaType::Void == 43,
- // followed by QMetaType::Bool == 1)... As a consequence, we need to use
- // the C++11 constexpr function calculateOffsetForTypeId below in order to
- // create the offset array.
+ int fromTypeId = fromType.id();
+ int toTypeId = toType.id();
- static constexpr int findTypeId(int typeId, int i = 0)
- {
- return i >= MetaTypeNameCount ? -1 :
- metaTypeIds[i] == typeId ? i : findTypeId(typeId, i + 1);
- }
+ if (fromTypeId == UnknownType || toTypeId == UnknownType)
+ return false;
- static constexpr short calculateOffsetForIdx(int i)
- {
- return i < 0 ? -1 :
- i == 0 ? 0 : metaTypeNameSizes[i - 1] + calculateOffsetForIdx(i - 1);
+ if (fromTypeId == toTypeId)
+ return true;
+
+ if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
+ if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
+ return true;
}
+ const ConverterFunction * const f =
+ customTypesConversionRegistry()->function(std::make_pair(fromTypeId, toTypeId));
+ if (f)
+ return true;
- static constexpr short calculateOffsetForTypeId(int typeId)
- {
- return calculateOffsetForIdx(findTypeId(typeId));
-#if 0
- // same as, but this is only valid in C++14:
- short offset = 0;
- for (int i = 0; i < MetaTypeNameCount; ++i) {
- if (metaTypeIds[i] == typeId)
- return offset;
- offset += metaTypeNameSizes[i];
- }
- return -1;
+#ifndef QT_BOOTSTRAPPED
+ if (toTypeId == qMetaTypeId<QSequentialIterable>())
+ return canConvertToSequentialIterable(fromType);
+
+ if (toTypeId == qMetaTypeId<QAssociativeIterable>())
+ return canConvertToAssociativeIterable(fromType);
#endif
+#ifndef QT_NO_VARIANT
+ if (toTypeId == QVariantList
+ && canConvert(fromType, QMetaType::fromType<QSequentialIterable>())) {
+ return true;
}
- short offsets[sizeof...(TypeIds)];
- constexpr MetaTypeOffsets() : offsets{calculateOffsetForTypeId(TypeIds)...} {}
+ if ((toTypeId == QVariantHash || toTypeId == QVariantMap)
+ && canConvert(fromType, QMetaType::fromType<QAssociativeIterable>())) {
+ return true;
+ }
- const char *operator[](int typeId) const noexcept
- {
- short o = offsets[typeId];
- return o < 0 ? nullptr : metaTypeStrings + o;
+ if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
+ fromType, QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
+ return true;
+#endif
+
+ if (fromType.flags() & IsEnumeration) {
+ if (toTypeId == QString || toTypeId == QByteArray)
+ return true;
+ return canConvert(QMetaType(LongLong), toType);
}
-};
-} // anonymous namespace
+ if (toType.flags() & IsEnumeration) {
+ if (fromTypeId == QString || fromTypeId == QByteArray)
+ return true;
+ return canConvert(fromType, QMetaType(LongLong));
+ }
+ if (toTypeId == Nullptr && fromType.flags() & IsPointer)
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ if (canConvertMetaObject(fromType, toType))
+ return true;
+#endif
-constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::Value> metaTypeNames {};
-#undef STRINGIFY_TYPE_NAME
-#undef CALCULATE_TYPE_LEN
-#undef MAP_TYPE_ID_TO_IDX
+ return false;
+}
+
+/*!
+ \fn bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
+ \deprecated Use the non-static compare method instead
+
+ Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
+ \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
+ or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
+*/
+
+/*!
+ \fn template<typename From, typename To> bool QMetaType::hasRegisteredConverterFunction()
+ Returns \c true, if the meta type system has a registered conversion from type From to type To.
+ \since 5.2
+ \overload
+ */
/*!
+ Returns \c true, if the meta type system has a registered conversion from meta type id \a fromType
+ to \a toType
+ \since 5.2
+*/
+bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType)
+{
+ return customTypesConversionRegistry()->contains({fromType.id(), toType.id()});
+}
+
+/*!
+ \fn template<typename From, typename To> bool QMetaType::hasRegisteredMutableViewFunction()
+ Returns \c true, if the meta type system has a registered mutable view on type From of type To.
+ \since 6.0
+ \overload
+*/
+
+/*!
+ Returns \c true, if the meta type system has a registered mutable view on meta type id
+ \a fromType of meta type id \a toType.
+ \since 5.2
+*/
+bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType)
+{
+ return customTypesMutableViewRegistry()->contains({fromType.id(), toType.id()});
+}
+
+/*!
+ \fn const char *QMetaType::typeName(int typeId)
+ \deprecated
+
Returns the type name associated with the given \a typeId, or a null
pointer if no matching type was found. The returned pointer must not be
deleted.
\sa type(), isRegistered(), Type, name()
*/
-const char *QMetaType::typeName(int typeId)
-{
- const uint type = typeId;
- if (Q_LIKELY(type <= QMetaType::HighestInternalId)) {
- return metaTypeNames[typeId];
- } else if (Q_UNLIKELY(type < QMetaType::User)) {
- return nullptr; // It can happen when someone cast int to QVariant::Type, we should not crash...
- }
-
- if (auto reg = customTypeRegistry()) {
- if (auto ti = reg->getCustomType(typeId))
- return ti->name;
- }
- return nullptr;
-}
/*!
+ \fn constexpr const char *QMetaType::name() const
\since 5.15
Returns the type name associated with this QMetaType, or a null
@@ -1155,10 +2697,6 @@ const char *QMetaType::typeName(int typeId)
\sa typeName()
*/
-QByteArray QMetaType::name() const
-{
- return d_ptr ? d_ptr->name : nullptr;
-}
/*
Similar to QMetaType::type(), but only looks in the static set of types.
@@ -1180,12 +2718,13 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
*/
static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
{
- if (auto reg = customTypeRegistry()) {
+ if (customTypeRegistry.exists()) {
+ auto reg = &*customTypeRegistry;
#if QT_CONFIG(thread)
Q_ASSERT(!reg->lock.tryLockForWrite());
#endif
- if (auto ti = reg->aliases.value(QByteArray(typeName, length), nullptr)) {
- return ti->typeId;
+ if (auto ti = reg->aliases.value(QByteArray::fromRawData(typeName, length), nullptr)) {
+ return ti->typeId.loadRelaxed();
}
}
return QMetaType::UnknownType;
@@ -1212,6 +2751,20 @@ void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeN
}
}
+
+static const QtPrivate::QMetaTypeInterface *interfaceForTypeNoWarning(int typeId)
+{
+ const QtPrivate::QMetaTypeInterface *iface = nullptr;
+ if (typeId >= QMetaType::User) {
+ if (customTypeRegistry.exists())
+ iface = customTypeRegistry->getCustomType(typeId);
+ } else {
+ if (auto moduleHelper = qModuleHelperForType(typeId))
+ iface = moduleHelper->interfaceForType(typeId);
+ }
+ return iface;
+}
+
/*!
Returns \c true if the datatype with ID \a type is registered;
otherwise returns \c false.
@@ -1220,7 +2773,7 @@ void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeN
*/
bool QMetaType::isRegistered(int type)
{
- return QMetaType(type).isRegistered();
+ return interfaceForTypeNoWarning(type) != nullptr;
}
template <bool tryNormalizedType>
@@ -1248,280 +2801,219 @@ static inline int qMetaTypeTypeImpl(const char *typeName, int length)
}
/*!
+ \fn int QMetaType::type(const char *typeName)
+ \deprecated
+
Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
no such type.
\sa isRegistered(), typeName(), Type
*/
-int QMetaType::type(const char *typeName)
-{
- return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName, qstrlen(typeName));
-}
/*!
- \a internal
+ \internal
Similar to QMetaType::type(); the only difference is that this function
doesn't attempt to normalize the type name (i.e., the lookup will fail
for type names in non-normalized form).
*/
-int qMetaTypeTypeInternal(const char *typeName)
+Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *typeName)
{
- return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, qstrlen(typeName));
+ return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, int(qstrlen(typeName)));
}
/*!
+ \fn int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
+
\since 5.5
\overload
+ \deprecated
Returns a handle to the type called \a typeName, or 0 if there is
no such type.
\sa isRegistered(), typeName()
*/
-int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
-{
- return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName.constData(), typeName.size());
-}
#ifndef QT_NO_DATASTREAM
-namespace
-{
-
-template<typename T>
-class HasStreamOperator
-{
- struct Yes { char unused[1]; };
- struct No { char unused[2]; };
- static_assert(sizeof(Yes) != sizeof(No));
-
- template<class C> static decltype(std::declval<QDataStream&>().operator>>(std::declval<C&>()), Yes()) load(int);
- template<class C> static decltype(operator>>(std::declval<QDataStream&>(), std::declval<C&>()), Yes()) load(int);
- template<class C> static No load(...);
- template<class C> static decltype(operator<<(std::declval<QDataStream&>(), std::declval<const C&>()), Yes()) saveFunction(int);
- template<class C> static decltype(std::declval<QDataStream&>().operator<<(std::declval<const C&>()), Yes()) saveMethod(int);
- template<class C> static No saveMethod(...);
- template<class C> static No saveFunction(...);
- static constexpr bool LoadValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && (sizeof(load<T>(0)) == sizeof(Yes));
- static constexpr bool SaveValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable &&
- ((sizeof(saveMethod<T>(0)) == sizeof(Yes)) || (sizeof(saveFunction<T>(0)) == sizeof(Yes)));
-public:
- static constexpr bool Value = LoadValue && SaveValue;
-};
-
-// Quick sanity checks
-static_assert(HasStreamOperator<NS(QJsonDocument)>::Value);
-static_assert(!HasStreamOperator<void*>::Value);
-static_assert(HasStreamOperator<qint8>::Value);
+/*!
+ Writes the object pointed to by \a data to the given \a stream.
+ Returns \c true if the object is saved successfully; otherwise
+ returns \c false.
-template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value>
-struct FilteredOperatorSwitch
-{
- static bool load(QDataStream &stream, T *data, int)
- {
- stream >> *data;
- return true;
- }
- static bool save(QDataStream &stream, const T *data, int)
- {
- stream << *data;
- return true;
- }
-};
+ Normally, you should not need to call this function directly.
+ Instead, use QVariant's \c operator<<(), which relies on save()
+ to stream custom types.
-template<typename T>
-struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false>
+ \sa load()
+*/
+bool QMetaType::save(QDataStream &stream, const void *data) const
{
- static const QMetaTypeModuleHelper *getMetaTypeInterface()
- {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return qMetaTypeGuiHelper;
- else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return qMetaTypeWidgetsHelper;
- return nullptr;
- }
- static bool save(QDataStream &stream, const T *data, int type)
- {
- if (auto interface = getMetaTypeInterface()) {
- return interface->save(stream, type, data);
- }
+ if (!data || !isValid())
return false;
- }
- static bool load(QDataStream &stream, T *data, int type)
- {
- if (auto interface = getMetaTypeInterface()) {
- return interface->load(stream, type, data);
- }
- return false;
- }
-};
-class SaveOperatorSwitch
-{
-public:
- QDataStream &stream;
- int m_type;
-
- template<typename T>
- bool delegate(const T *data)
- {
- return FilteredOperatorSwitch<T>::save(stream, data, m_type);
- }
- bool delegate(const char *data)
- {
- // force a char to be signed
- stream << qint8(*data);
- return true;
- }
- bool delegate(const long *data)
- {
- stream << qlonglong(*data);
+ // keep compatibility for long/ulong
+ if (id() == QMetaType::Long) {
+ stream << qlonglong(*(long *)data);
return true;
- }
- bool delegate(const unsigned long *data)
- {
- stream << qulonglong(*data);
+ } else if (id() == QMetaType::ULong) {
+ stream << qlonglong(*(unsigned long *)data);
return true;
}
- bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
- {
- auto ct = customTypeRegistry();
- if (!ct)
- return false;
- QMetaType::SaveOperator op = nullptr;
- {
- QReadLocker lock(&ct->lock);
- op = ct->dataStreamOp.value(m_type).saveOp;
- }
- if (!op)
- return false;
- op(stream, data);
- return true;
- }
- bool delegate(const void*) { return false; }
- bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
-};
-class LoadOperatorSwitch
-{
-public:
- QDataStream &stream;
- int m_type;
- template<typename T>
- bool delegate(const T *data)
- {
- return FilteredOperatorSwitch<T>::load(stream, const_cast<T*>(data), m_type);
- }
- bool delegate(const char *data)
- {
- // force a char to be signed
- qint8 c;
- stream >> c;
- *const_cast<char*>(data) = c;
- return true;
- }
- bool delegate(const long *data)
- {
- qlonglong l;
- stream >> l;
- *const_cast<long*>(data) = l;
- return true;
- }
- bool delegate(const unsigned long *data)
- {
- qlonglong l;
- stream >> l;
- *const_cast<unsigned long*>(data) = l;
- return true;
- }
- bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
- {
- auto ct = customTypeRegistry();
- if (!ct)
- return false;
- QMetaType::LoadOperator op = nullptr;
- {
- QReadLocker lock(&ct->lock);
- op = ct->dataStreamOp.value(m_type).loadOp;
- }
- if (!op)
- return false;
- op(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType *>(data));
- return true;
- }
- bool delegate(const void*) { return false; }
- bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
-};
-} // namespace
+ if (!d_ptr->dataStreamOut)
+ return false;
+
+ d_ptr->dataStreamOut(d_ptr, stream, data);
+ return true;
+}
/*!
- Writes the object pointed to by \a data with the ID \a type to
- the given \a stream. Returns \c true if the object is saved
- successfully; otherwise returns \c false.
+ \fn bool QMetaType::save(QDataStream &stream, int type, const void *data)
+ \overload
+ \deprecated
+*/
- The type must have been registered with qRegisterMetaType() and
- qRegisterMetaTypeStreamOperators() beforehand.
+/*!
+ Reads the object of this type from the given \a stream into \a data.
+ Returns \c true if the object is loaded successfully; otherwise
+ returns \c false.
Normally, you should not need to call this function directly.
- Instead, use QVariant's \c operator<<(), which relies on save()
+ Instead, use QVariant's \c operator>>(), which relies on load()
to stream custom types.
- \sa load(), qRegisterMetaTypeStreamOperators()
+ \sa save()
*/
-bool QMetaType::save(QDataStream &stream, int type, const void *data)
+bool QMetaType::load(QDataStream &stream, void *data) const
{
- if (!data)
+ if (!data || !isValid())
+ return false;
+
+ // keep compatibility for long/ulong
+ if (id() == QMetaType::Long) {
+ qlonglong ll;
+ stream >> ll;
+ *(long *)data = long(ll);
+ return true;
+ } else if (id() == QMetaType::ULong) {
+ qulonglong ull;
+ stream >> ull;
+ *(unsigned long *)data = (unsigned long)(ull);
+ return true;
+ }
+ if (!d_ptr->dataStreamIn)
return false;
- SaveOperatorSwitch saveOp{stream, type};
- return QMetaTypeSwitcher::switcher<bool>(saveOp, type, data);
+
+ d_ptr->dataStreamIn(d_ptr, stream, data);
+ return true;
}
/*!
- Reads the object of the specified \a type from the given \a
- stream into \a data. Returns \c true if the object is loaded
- successfully; otherwise returns \c false.
+ \since 6.1
- The type must have been registered with qRegisterMetaType() and
- qRegisterMetaTypeStreamOperators() beforehand.
+ Returns \c true, if the meta type system has registered data stream operators for this
+ meta type.
+*/
+bool QMetaType::hasRegisteredDataStreamOperators() const
+{
+ int type = id();
+ if (type == QMetaType::Long || type == QMetaType::ULong)
+ return true;
+ return d_ptr && d_ptr->dataStreamIn != nullptr && d_ptr->dataStreamOut != nullptr;
+}
- Normally, you should not need to call this function directly.
- Instead, use QVariant's \c operator>>(), which relies on load()
- to stream custom types.
+/*!
+ \since 6.6
- \sa save(), qRegisterMetaTypeStreamOperators()
-*/
-bool QMetaType::load(QDataStream &stream, int type, void *data)
+ If this metatype represents an enumeration, this method returns a
+ metatype of a numeric class of the same signedness and size as the
+ enums underlying type.
+ If it represents a QFlags type, it returns QMetaType::Int.
+ In all other cases an invalid QMetaType is returned.
+ */
+QMetaType QMetaType::underlyingType() const
{
- if (!data)
- return false;
- LoadOperatorSwitch loadOp{stream, type};
- return QMetaTypeSwitcher::switcher<bool>(loadOp, type, data);
+ if (!d_ptr || !(flags() & IsEnumeration))
+ return {};
+ /* QFlags has enumeration set so that's handled here (qint32
+ case), as QFlags uses int as the underlying type
+ Note that we do some approximation here, as we cannot
+ differentiate between different underlying types of the
+ same size and signedness (consider char <-> (un)signed char,
+ int <-> long <-> long long).
+
+ ### TODO PENDING: QTBUG-111926 - QFlags supporting >32 bit int
+ */
+ if (flags() & IsUnsignedEnumeration) {
+ switch (sizeOf()) {
+ case 1:
+ return QMetaType::fromType<quint8>();
+ case 2:
+ return QMetaType::fromType<quint16>();
+ case 4:
+ return QMetaType::fromType<quint32>();
+ case 8:
+ return QMetaType::fromType<quint64>();
+ default:
+ break;
+ }
+ } else {
+ switch (sizeOf()) {
+ case 1:
+ return QMetaType::fromType<qint8>();
+ case 2:
+ return QMetaType::fromType<qint16>();
+ case 4:
+ return QMetaType::fromType<qint32>();
+ case 8:
+ return QMetaType::fromType<qint64>();
+ default:
+ break;
+ }
+ }
+ // int128 can be handled above once we have qint128
+ return QMetaType();
}
+
+/*!
+ \fn bool QMetaType::load(QDataStream &stream, int type, void *data)
+ \overload
+ \deprecated
+*/
#endif // QT_NO_DATASTREAM
/*!
+ Returns a QMetaType matching \a typeName. The returned object is
+ not valid if the typeName is not known to QMetaType
+ */
+QMetaType QMetaType::fromName(QByteArrayView typeName)
+{
+ return QMetaType(qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName.data(), typeName.size()));
+}
+
+/*!
+ \fn void *QMetaType::create(int type, const void *copy)
+ \deprecated
+
Returns a copy of \a copy, assuming it is of type \a type. If \a
copy is zero, creates a default constructed instance.
\sa destroy(), isRegistered(), Type
*/
-void *QMetaType::create(int type, const void *copy)
-{
- return QMetaType(type).create(copy);
-}
/*!
+ \fn void QMetaType::destroy(int type, void *data)
+ \deprecated
Destroys the \a data, assuming it is of the \a type given.
\sa create(), isRegistered(), Type
*/
-void QMetaType::destroy(int type, void *data)
-{
- QMetaType(type).destroy(data);
-}
/*!
+ \fn void *QMetaType::construct(int type, void *where, const void *copy)
\since 5.0
+ \deprecated
Constructs a value of the given \a type in the existing memory
addressed by \a where, that is a copy of \a copy, and returns
@@ -1546,14 +3038,12 @@ void QMetaType::destroy(int type, void *data)
\sa destruct(), sizeOf()
*/
-void *QMetaType::construct(int type, void *where, const void *copy)
-{
- return QMetaType(type).construct(where, copy);
-}
/*!
+ \fn void QMetaType::destruct(int type, void *where)
\since 5.0
+ \deprecated
Destructs the value of the given \a type, located at \a where.
@@ -1562,13 +3052,11 @@ void *QMetaType::construct(int type, void *where, const void *copy)
\sa construct()
*/
-void QMetaType::destruct(int type, void *where)
-{
- return QMetaType(type).destruct(where);
-}
/*!
+ \fn int QMetaType::sizeOf(int type)
\since 5.0
+ \deprecated
Returns the size of the given \a type in bytes (i.e. sizeof(T),
where T is the actual type identified by the \a type argument).
@@ -1576,41 +3064,33 @@ void QMetaType::destruct(int type, void *where)
This function is typically used together with construct()
to perform low-level management of the memory used by a type.
- \sa construct()
+ \sa construct(), QMetaType::alignOf()
*/
-int QMetaType::sizeOf(int type)
-{
- return QMetaType(type).sizeOf();
-}
/*!
+ \fn QMetaType::TypeFlags QMetaType::typeFlags(int type)
\since 5.0
+ \deprecated
Returns flags of the given \a type.
\sa QMetaType::TypeFlags
*/
-QMetaType::TypeFlags QMetaType::typeFlags(int type)
-{
- return QMetaType(type).flags();
-}
-
/*!
+ \fn const QMetaObject *QMetaType::metaObjectForType(int type)
\since 5.0
+ \deprecated
returns QMetaType::metaObject for \a type
\sa metaObject()
*/
-const QMetaObject *QMetaType::metaObjectForType(int type)
-{
- return QMetaType(type).metaObject();
-}
/*!
- \fn int qRegisterMetaType(const char *typeName)
+ \fn template <typename T> int qRegisterMetaType(const char *typeName)
\relates QMetaType
+ \obsolete
\threadsafe
Registers the type name \a typeName for the type \c{T}. Returns
@@ -1638,67 +3118,67 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\warning This function is useful only for registering an alias (typedef)
for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
- \sa {QMetaType::}{qRegisterMetaTypeStreamOperators()}, {QMetaType::}{isRegistered()},
- Q_DECLARE_METATYPE()
+ \sa {QMetaType::}{isRegistered()}, Q_DECLARE_METATYPE()
*/
/*!
- \fn void qRegisterMetaTypeStreamOperators(const char *typeName)
+ \fn template <typename T> int qRegisterMetaType()
\relates QMetaType
\threadsafe
+ \since 4.2
- Registers the stream operators for the type \c{T} called \a
- typeName.
+ Call this function to register the type \c T. Returns the meta type Id.
- Afterward, the type can be streamed using QMetaType::load() and
- QMetaType::save(). These functions are used when streaming a
- QVariant.
+ Example:
- \snippet code/src_corelib_kernel_qmetatype.cpp 5
+ \snippet code/src_corelib_kernel_qmetatype.cpp 7
- The stream operators should have the following signatures:
+ This function requires that \c{T} is a fully defined type at the point
+ where the function is called. For pointer types, it also requires that the
+ pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
+ to register pointers to forward declared types.
- \snippet code/src_corelib_kernel_qmetatype.cpp 6
+ To use the type \c T in QMetaType, QVariant, or with the
+ QObject::property() API, registration is not necessary.
- \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
-*/
+ To use the type \c T in queued signal and slot connections,
+ \c{qRegisterMetaType<T>()} must be called before the first connection is
+ established. That is typically done in the constructor of the class that
+ uses \c T, or in the \c{main()} function.
+
+ After a type has been registered, it can be found by its name using
+ QMetaType::fromName().
+
+ \sa Q_DECLARE_METATYPE()
+ */
/*!
- \fn int qRegisterMetaType()
+ \fn int qRegisterMetaType(QMetaType meta)
\relates QMetaType
\threadsafe
- \since 4.2
+ \since 6.5
- Call this function to register the type \c T. \c T must be declared with
- Q_DECLARE_METATYPE(). Returns the meta type Id.
-
- Example:
-
- \snippet code/src_corelib_kernel_qmetatype.cpp 7
+ Registers the meta type \a meta and returns its type Id.
This function requires that \c{T} is a fully defined type at the point
where the function is called. For pointer types, it also requires that the
pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
to register pointers to forward declared types.
- After a type has been registered, you can create and destroy
- objects of that type dynamically at run-time.
-
- To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is
- sufficient. To use the type \c T in queued signal and slot connections,
- \c{qRegisterMetaType<T>()} must be called before the first connection
- is established.
+ To use the type \c T in QMetaType, QVariant, or with the
+ QObject::property() API, registration is not necessary.
- Also, to use type \c T with the QObject::property() API,
- \c{qRegisterMetaType<T>()} must be called before it is used, typically
- in the constructor of the class that uses \c T, or in the \c{main()}
- function.
+ To use the type \c T in queued signal and slot connections,
+ \c{qRegisterMetaType<T>()} must be called before the first connection is
+ established. That is typically done in the constructor of the class that
+ uses \c T, or in the \c{main()} function.
- \sa Q_DECLARE_METATYPE()
+ After a type has been registered, it can be found by its name using
+ QMetaType::fromName().
*/
/*!
- \fn int qMetaTypeId()
+ \fn template <typename T> int qMetaTypeId()
\relates QMetaType
\threadsafe
\since 4.1
@@ -1719,52 +3199,51 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
-static QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
+static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
{
- if (typeId >= QMetaType::User) {
- if (auto reg = customTypeRegistry())
- return reg->getCustomType(typeId);
- }
- if (auto moduleHelper = qModuleHelperForType(typeId))
- return moduleHelper->interfaceForType(typeId);
-
- switch (typeId) {
- QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
- QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
- QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
- QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
- QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_CONVERT_ID_TO_TYPE)
- default:
- if (typeId != QMetaType::UnknownType)
- qWarning("Trying to construct an instance of an invalid type, type id: %i", typeId);
- return nullptr;
- }
+ const QtPrivate::QMetaTypeInterface *iface = interfaceForTypeNoWarning(typeId);
+ if (!iface && typeId != QMetaType::UnknownType)
+ qWarning("Trying to construct an instance of an invalid type, type id: %i", typeId);
+
+ return iface;
}
/*!
- \fn QMetaType::QMetaType(const int typeId)
+ \fn QMetaType::QMetaType()
+ \since 6.0
+
+ Constructs a default, invalid, QMetaType object.
+*/
+
+/*!
+ \fn QMetaType::QMetaType(int typeId)
\since 5.0
Constructs a QMetaType object that contains all information about type \a typeId.
-
- \note The default parameter was added in Qt 5.15.
*/
QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
-namespace QtMetaTypePrivate {
-const bool VectorBoolElements::true_element = true;
-const bool VectorBoolElements::false_element = false;
-}
+
+/*! \fn size_t qHash(QMetaType type, size_t seed = 0)
+ \relates QMetaType
+ \since 6.4
+
+ Returns the hash value for the \a type, using \a seed to seed the calculation.
+*/
namespace QtPrivate {
-#ifndef QT_BOOTSTRAPPED
+#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
+
// Explicit instantiation definition
-#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) template class QMetaTypeForType<Name>;
-QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
+#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
+ template class QMetaTypeForType<Name>; \
+ template struct QMetaTypeInterfaceWrapper<Name>;
+QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
+
#undef QT_METATYPE_DECLARE_TEMPLATE_ITER
#endif
}
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index c7e754cb5c..80d10f5c9a 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMETATYPE_H
#define QMETATYPE_H
@@ -45,17 +9,24 @@
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtCore/qrefcount.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qfloat16.h>
+#include <QtCore/qhashfunctions.h>
+#include <QtCore/qiterable.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#endif
+#include <QtCore/qscopeguard.h>
#include <array>
#include <new>
#include <vector>
#include <list>
#include <map>
+#include <functional>
+#include <optional>
+#include <QtCore/q20type_traits.h>
#ifdef Bool
#error qmetatype.h must be included before any header file that defines Bool
@@ -70,12 +41,10 @@ template <typename T>
struct QMetaTypeId2;
template <typename T>
-inline Q_DECL_CONSTEXPR int qMetaTypeId();
+inline constexpr int qMetaTypeId();
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
-// ### Qt6: reorder the types to match the C++ integral type ranking
-#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
- F(Void, 43, void) \
+#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)\
F(Bool, 1, bool) \
F(Int, 2, int) \
F(UInt, 3, uint) \
@@ -95,7 +64,11 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(Nullptr, 51, std::nullptr_t) \
F(QCborSimpleType, 52, QCborSimpleType) \
-#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
+#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
+ QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F) \
+ F(Void, 43, void) \
+
+#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F) \
F(VoidStar, 31, void*) \
#if QT_CONFIG(easingcurve)
@@ -119,11 +92,16 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#else
# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
#endif
+#ifndef QT_NO_VARIANT
+# define QT_FOR_EACH_STATIC_QVARIANT(F) \
+ F(QVariant, 41, QVariant)
+#else
+# define QT_FOR_EACH_STATIC_QVARIANT(F)
+#endif
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
F(QChar, 7, QChar) \
F(QString, 10, QString) \
- F(QStringList, 11, QStringList) \
F(QByteArray, 12, QByteArray) \
F(QBitArray, 13, QBitArray) \
F(QDate, 14, QDate) \
@@ -141,7 +119,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QPointF, 26, QPointF) \
QT_FOR_EACH_STATIC_EASINGCURVE(F) \
F(QUuid, 30, QUuid) \
- F(QVariant, 41, QVariant) \
+ QT_FOR_EACH_STATIC_QVARIANT(F) \
QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
F(QJsonValue, 45, QJsonValue) \
F(QJsonObject, 46, QJsonObject) \
@@ -150,52 +128,62 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QCborValue, 53, QCborValue) \
F(QCborArray, 54, QCborArray) \
F(QCborMap, 55, QCborMap) \
+ F(Float16, 63, qfloat16) \
QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
F(QObjectStar, 39, QObject*)
-#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
+#ifndef QT_NO_VARIANT
+# define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
F(QVariantMap, 8, QVariantMap) \
F(QVariantList, 9, QVariantList) \
F(QVariantHash, 28, QVariantHash) \
+ F(QVariantPair, 58, QVariantPair) \
+ F(QByteArrayList, 49, QByteArrayList) \
+ F(QStringList, 11, QStringList) \
+ /**/
+#else
+# define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
F(QByteArrayList, 49, QByteArrayList) \
+ F(QStringList, 11, QStringList)
+#endif
#if QT_CONFIG(shortcut)
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
- F(QKeySequence, 75, QKeySequence)
+ F(QKeySequence, 0x100b, QKeySequence)
#else
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
#endif
#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
- F(QFont, 64, QFont) \
- F(QPixmap, 65, QPixmap) \
- F(QBrush, 66, QBrush) \
- F(QColor, 67, QColor) \
- F(QPalette, 68, QPalette) \
- F(QIcon, 69, QIcon) \
- F(QImage, 70, QImage) \
- F(QPolygon, 71, QPolygon) \
- F(QRegion, 72, QRegion) \
- F(QBitmap, 73, QBitmap) \
- F(QCursor, 74, QCursor) \
+ F(QFont, 0x1000, QFont) \
+ F(QPixmap, 0x1001, QPixmap) \
+ F(QBrush, 0x1002, QBrush) \
+ F(QColor, 0x1003, QColor) \
+ F(QPalette, 0x1004, QPalette) \
+ F(QIcon, 0x1005, QIcon) \
+ F(QImage, 0x1006, QImage) \
+ F(QPolygon, 0x1007, QPolygon) \
+ F(QRegion, 0x1008, QRegion) \
+ F(QBitmap, 0x1009, QBitmap) \
+ F(QCursor, 0x100a, QCursor) \
QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
- F(QPen, 76, QPen) \
- F(QTextLength, 77, QTextLength) \
- F(QTextFormat, 78, QTextFormat) \
- F(QTransform, 80, QTransform) \
- F(QMatrix4x4, 81, QMatrix4x4) \
- F(QVector2D, 82, QVector2D) \
- F(QVector3D, 83, QVector3D) \
- F(QVector4D, 84, QVector4D) \
- F(QQuaternion, 85, QQuaternion) \
- F(QPolygonF, 86, QPolygonF) \
- F(QColorSpace, 87, QColorSpace) \
+ F(QPen, 0x100c, QPen) \
+ F(QTextLength, 0x100d, QTextLength) \
+ F(QTextFormat, 0x100e, QTextFormat) \
+ F(QTransform, 0x1010, QTransform) \
+ F(QMatrix4x4, 0x1011, QMatrix4x4) \
+ F(QVector2D, 0x1012, QVector2D) \
+ F(QVector3D, 0x1013, QVector3D) \
+ F(QVector4D, 0x1014, QVector4D) \
+ F(QQuaternion, 0x1015, QQuaternion) \
+ F(QPolygonF, 0x1016, QPolygonF) \
+ F(QColorSpace, 0x1017, QColorSpace) \
#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
- F(QSizePolicy, 121, QSizePolicy) \
+ F(QSizePolicy, 0x2000, QSizePolicy) \
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
@@ -213,11 +201,20 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(UInt, -1, uint, "quint32") \
F(LongLong, -1, qlonglong, "qint64") \
F(ULongLong, -1, qulonglong, "quint64") \
- F(QVariantList, -1, QVariantList, "QVector<QVariant>") \
+ F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
+ F(QStringList, -1, QStringList, "QList<QString>") \
+ QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
+
+#ifndef QT_NO_VARIANT
+#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F) \
F(QVariantList, -1, QVariantList, "QList<QVariant>") \
F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
- F(QByteArrayList, -1, QByteArrayList, "QVector<QByteArray>") \
+ F(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>") \
+ /**/
+#else
+#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
+#endif
#define QT_FOR_EACH_STATIC_TYPE(F)\
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@@ -248,7 +245,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QPointer)
class QDataStream;
-class QMetaTypeInterface;
struct QMetaObject;
namespace QtPrivate
@@ -256,176 +252,75 @@ namespace QtPrivate
class QMetaTypeInterface;
-/*!
- This template is used for implicit conversion from type From to type To.
- \internal
-*/
-template<typename From, typename To>
-To convertImplicit(const From& from)
-{
- return from;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-struct AbstractDebugStreamFunction
-{
- typedef void (*Stream)(const AbstractDebugStreamFunction *, QDebug&, const void *);
- typedef void (*Destroy)(AbstractDebugStreamFunction *);
- explicit AbstractDebugStreamFunction(Stream s = nullptr, Destroy d = nullptr)
- : stream(s), destroy(d) {}
- Q_DISABLE_COPY(AbstractDebugStreamFunction)
- Stream stream;
- Destroy destroy;
-};
-
-template<typename T>
-struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction
-{
- BuiltInDebugStreamFunction()
- : AbstractDebugStreamFunction(stream, destroy) {}
- static void stream(const AbstractDebugStreamFunction *, QDebug& dbg, const void *r)
- {
- const T *rhs = static_cast<const T *>(r);
- operator<<(dbg, *rhs);
- }
-
- static void destroy(AbstractDebugStreamFunction *_this)
- {
- delete static_cast<BuiltInDebugStreamFunction *>(_this);
- }
-};
+// MSVC is the only supported compiler that includes the type of a variable in
+// its mangled form, so it's not binary-compatible to drop the const in
+// QMetaTypeInterfaceWrapper::metaType for it, which means we must keep the
+// mutable field until Qt 7.
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || !defined(Q_CC_MSVC)
+# define QMTI_MUTABLE
+using NonConstMetaTypeInterface = QMetaTypeInterface;
+#else
+# define QMTI_MUTABLE mutable
+using NonConstMetaTypeInterface = const QMetaTypeInterface;
#endif
-struct AbstractComparatorFunction
-{
- typedef bool (*LessThan)(const AbstractComparatorFunction *, const void *, const void *);
- typedef bool (*Equals)(const AbstractComparatorFunction *, const void *, const void *);
- typedef void (*Destroy)(AbstractComparatorFunction *);
- explicit AbstractComparatorFunction(LessThan lt = nullptr, Equals e = nullptr, Destroy d = nullptr)
- : lessThan(lt), equals(e), destroy(d) {}
- Q_DISABLE_COPY(AbstractComparatorFunction)
- LessThan lessThan;
- Equals equals;
- Destroy destroy;
-};
-
-template<typename T>
-struct BuiltInComparatorFunction : public AbstractComparatorFunction
+class QMetaTypeInterface
{
- BuiltInComparatorFunction()
- : AbstractComparatorFunction(lessThan, equals, destroy) {}
- static bool lessThan(const AbstractComparatorFunction *, const void *l, const void *r)
- {
- const T *lhs = static_cast<const T *>(l);
- const T *rhs = static_cast<const T *>(r);
- return *lhs < *rhs;
- }
-
- static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
- {
- const T *lhs = static_cast<const T *>(l);
- const T *rhs = static_cast<const T *>(r);
- return *lhs == *rhs;
- }
+public:
- static void destroy(AbstractComparatorFunction *_this)
- {
- delete static_cast<BuiltInComparatorFunction *>(_this);
- }
-};
+ /* Revision: Can increase if new field are added, or if semantics changes
+ 0: Initial Revision
+ 1: the meaning of the NeedsDestruction flag changed
+ */
+ static inline constexpr ushort CurrentRevision = 1;
-template<typename T>
-struct BuiltInEqualsComparatorFunction : public AbstractComparatorFunction
-{
- BuiltInEqualsComparatorFunction()
- : AbstractComparatorFunction(nullptr, equals, destroy) {}
- static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
- {
- const T *lhs = static_cast<const T *>(l);
- const T *rhs = static_cast<const T *>(r);
- return *lhs == *rhs;
- }
+ ushort revision;
+ ushort alignment;
+ uint size;
+ uint flags;
+ QMTI_MUTABLE QBasicAtomicInt typeId;
- static void destroy(AbstractComparatorFunction *_this)
- {
- delete static_cast<BuiltInEqualsComparatorFunction *>(_this);
- }
-};
+ using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
+ MetaObjectFn metaObjectFn;
-struct AbstractConverterFunction
-{
- typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
- explicit AbstractConverterFunction(Converter c = nullptr)
- : convert(c) {}
- Q_DISABLE_COPY(AbstractConverterFunction)
- Converter convert;
-};
+ const char *name;
-template<typename From, typename To>
-struct ConverterMemberFunction : public AbstractConverterFunction
-{
- explicit ConverterMemberFunction(To(From::*function)() const)
- : AbstractConverterFunction(convert),
- m_function(function) {}
- ~ConverterMemberFunction();
- static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
- {
- const From *f = static_cast<const From *>(in);
- To *t = static_cast<To *>(out);
- const ConverterMemberFunction *_typedThis =
- static_cast<const ConverterMemberFunction *>(_this);
- *t = (f->*_typedThis->m_function)();
- return true;
- }
+ using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
+ DefaultCtrFn defaultCtr;
+ using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
+ CopyCtrFn copyCtr;
+ using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
+ MoveCtrFn moveCtr;
+ using DtorFn = void (*)(const QMetaTypeInterface *, void *);
+ DtorFn dtor;
+ using EqualsFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
+ EqualsFn equals;
+ using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
+ LessThanFn lessThan;
+ using DebugStreamFn = void (*)(const QMetaTypeInterface *, QDebug &, const void *);
+ DebugStreamFn debugStream;
+ using DataStreamOutFn = void (*)(const QMetaTypeInterface *, QDataStream &, const void *);
+ DataStreamOutFn dataStreamOut;
+ using DataStreamInFn = void (*)(const QMetaTypeInterface *, QDataStream &, void *);
+ DataStreamInFn dataStreamIn;
- To(From::* const m_function)() const;
+ using LegacyRegisterOp = void (*)();
+ LegacyRegisterOp legacyRegisterOp;
};
+#undef QMTI_MUTABLE
+/*!
+ This template is used for implicit conversion from type From to type To.
+ \internal
+*/
template<typename From, typename To>
-struct ConverterMemberFunctionOk : public AbstractConverterFunction
-{
- explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const)
- : AbstractConverterFunction(convert),
- m_function(function) {}
- ~ConverterMemberFunctionOk();
- static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
- {
- const From *f = static_cast<const From *>(in);
- To *t = static_cast<To *>(out);
- bool ok = false;
- const ConverterMemberFunctionOk *_typedThis =
- static_cast<const ConverterMemberFunctionOk *>(_this);
- *t = (f->*_typedThis->m_function)(&ok);
- if (!ok)
- *t = To();
- return ok;
- }
-
- To(From::* const m_function)(bool*) const;
-};
-
-template<typename From, typename To, typename UnaryFunction>
-struct ConverterFunctor : public AbstractConverterFunction
+To convertImplicit(const From& from)
{
- explicit ConverterFunctor(UnaryFunction function)
- : AbstractConverterFunction(convert),
- m_function(function) {}
- ~ConverterFunctor();
- static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
- {
- const From *f = static_cast<const From *>(in);
- To *t = static_cast<To *>(out);
- const ConverterFunctor *_typedThis =
- static_cast<const ConverterFunctor *>(_this);
- *t = _typedThis->m_function(*f);
- return true;
- }
-
- UnaryFunction m_function;
-};
+ return from;
+}
template<typename T, bool>
- struct ValueTypeIsMetaType;
+ struct SequentialValueTypeIsMetaType;
template<typename T, bool>
struct AssociativeValueTypeIsMetaType;
template<typename T, bool>
@@ -445,14 +340,14 @@ struct ConverterFunctor : public AbstractConverterFunction
class Q_CORE_EXPORT QMetaType {
public:
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
// The code that actually gets compiled.
enum Type {
// these are merged with QVariant
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
FirstCoreType = Bool,
- LastCoreType = Char32,
+ LastCoreType = Float16,
FirstGuiType = QFont,
LastGuiType = QColorSpace,
FirstWidgetsType = QSizePolicy,
@@ -462,7 +357,7 @@ public:
QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
UnknownType = 0,
- User = 1024
+ User = 65536
};
#else
// If we are using QDoc it fakes the Type enum looks like this.
@@ -481,148 +376,188 @@ public:
QByteArrayList = 49, QObjectStar = 39, SChar = 40,
Void = 43,
Nullptr = 51,
- QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
+ QVariantMap = 8, QVariantList = 9, QVariantHash = 28, QVariantPair = 58,
QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
Char16 = 56, Char32 = 57,
+ Int128 = 59, UInt128 = 60, Float128 = 61, BFloat16 = 62, Float16 = 63,
// Gui types
- QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
- QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
- QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78,
- QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
- QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86, QColorSpace = 87,
+ QFont = 0x1000, QPixmap = 0x1001, QBrush = 0x1002, QColor = 0x1003, QPalette = 0x1004,
+ QIcon = 0x1005, QImage = 0x1006, QPolygon = 0x1007, QRegion = 0x1008, QBitmap = 0x1009,
+ QCursor = 0x100a, QKeySequence = 0x100b, QPen = 0x100c, QTextLength = 0x100d, QTextFormat = 0x100e,
+ QTransform = 0x1010, QMatrix4x4 = 0x1011, QVector2D = 0x1012,
+ QVector3D = 0x1013, QVector4D = 0x1014, QQuaternion = 0x1015, QPolygonF = 0x1016, QColorSpace = 0x1017,
// Widget types
- QSizePolicy = 121,
- LastCoreType = QCborMap,
- LastGuiType = QColorSpace,
- User = 1024
+ QSizePolicy = 0x2000,
+
+ // Start-point for client-code types:
+ User = 65536
};
#endif
enum TypeFlag {
NeedsConstruction = 0x1,
NeedsDestruction = 0x2,
- MovableType = 0x4,
+ RelocatableType = 0x4,
+#if QT_DEPRECATED_SINCE(6, 0)
+ MovableType Q_DECL_ENUMERATOR_DEPRECATED_X("Use RelocatableType instead.") = RelocatableType,
+#endif
PointerToQObject = 0x8,
IsEnumeration = 0x10,
SharedPointerToQObject = 0x20,
WeakPointerToQObject = 0x40,
TrackingPointerToQObject = 0x80,
- WasDeclaredAsMetaType = 0x100,
+ IsUnsignedEnumeration = 0x100,
IsGadget = 0x200,
PointerToGadget = 0x400,
IsPointer = 0x800,
+ IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T>
+ IsConst = 0x2000,
+ // since 6.5:
+ NeedsCopyConstruction = 0x4000,
+ NeedsMoveConstruction = 0x8000,
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
- typedef void (*SaveOperator)(QDataStream &, const void *);
- typedef void (*LoadOperator)(QDataStream &, void *);
-#ifndef QT_NO_DATASTREAM
- static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
- LoadOperator loadOp);
- static void registerStreamOperators(int type, SaveOperator saveOp,
- LoadOperator loadOp);
-#endif
static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
- static int type(const char *typeName);
-
- static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName);
- static const char *typeName(int type);
- static int sizeOf(int type);
- static TypeFlags typeFlags(int type);
- static const QMetaObject *metaObjectForType(int type);
- static bool isRegistered(int type);
- static void *create(int type, const void *copy = nullptr);
- static void destroy(int type, void *data);
- static void *construct(int type, void *where, const void *copy);
- static void destruct(int type, void *where);
-
-#ifndef QT_NO_DATASTREAM
- static bool save(QDataStream &stream, int type, const void *data);
- static bool load(QDataStream &stream, int type, void *data);
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static int type(const char *typeName)
+ { return QMetaType::fromName(typeName).id(); }
+ QT_DEPRECATED_VERSION_6_0
+ static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
+ { return QMetaType::fromName(typeName).id(); }
+ QT_DEPRECATED_VERSION_6_0
+ static const char *typeName(int type)
+ { return QMetaType(type).name(); }
+ QT_DEPRECATED_VERSION_6_0
+ static int sizeOf(int type)
+ { return int(QMetaType(type).sizeOf()); }
+ QT_DEPRECATED_VERSION_6_0
+ static TypeFlags typeFlags(int type)
+ { return QMetaType(type).flags(); }
+ QT_DEPRECATED_VERSION_6_0
+ static const QMetaObject *metaObjectForType(int type)
+ { return QMetaType(type).metaObject(); }
+ QT_DEPRECATED_VERSION_6_0
+ static void *create(int type, const void *copy = nullptr)
+ { return QMetaType(type).create(copy); }
+ QT_DEPRECATED_VERSION_6_0
+ static void destroy(int type, void *data)
+ { return QMetaType(type).destroy(data); }
+ QT_DEPRECATED_VERSION_6_0
+ static void *construct(int type, void *where, const void *copy)
+ { return QMetaType(type).construct(where, copy); }
+ QT_DEPRECATED_VERSION_6_0
+ static void destruct(int type, void *where)
+ { return QMetaType(type).destruct(where); }
#endif
+ static bool isRegistered(int type);
explicit QMetaType(int type);
- explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
- constexpr QMetaType() : d_ptr(nullptr) {}
- ~QMetaType();
- QMetaType(const QMetaType &other) : QMetaType(other.d_ptr) {}
- QMetaType &operator=(const QMetaType &);
- QMetaType(QMetaType &&other) : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
- QMetaType &operator=(QMetaType &&other)
- {
- qSwap(d_ptr, other.d_ptr);
- return *this;
- }
+ explicit constexpr QMetaType(const QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
+ constexpr QMetaType() = default;
bool isValid() const;
bool isRegistered() const;
+ void registerType() const
+ {
+ // "register" is a reserved keyword
+ registerHelper();
+ }
+#if QT_CORE_REMOVED_SINCE(6, 1) || defined(Q_QDOC)
int id() const;
- int sizeOf() const;
- TypeFlags flags() const;
- const QMetaObject *metaObject() const;
- QT_PREPEND_NAMESPACE(QByteArray) name() const;
+#else
+ // ### Qt 7: Remove traces of out of line version
+ // unused int parameter is used to avoid ODR violation
+ int id(int = 0) const
+ {
+ // keep in sync with the version in removed_api.cpp
+ return registerHelper();
+ }
+#endif
+ constexpr qsizetype sizeOf() const;
+ constexpr qsizetype alignOf() const;
+ constexpr TypeFlags flags() const;
+ constexpr const QMetaObject *metaObject() const;
+ constexpr const char *name() const;
void *create(const void *copy = nullptr) const;
void destroy(void *data) const;
void *construct(void *where, const void *copy = nullptr) const;
void destruct(void *data) const;
+ QPartialOrdering compare(const void *lhs, const void *rhs) const;
+ bool equals(const void *lhs, const void *rhs) const;
- template<typename T>
- static QMetaType fromType();
+ bool isDefaultConstructible() const noexcept { return d_ptr && isDefaultConstructible(d_ptr); }
+ bool isCopyConstructible() const noexcept { return d_ptr && isCopyConstructible(d_ptr); }
+ bool isMoveConstructible() const noexcept { return d_ptr && isMoveConstructible(d_ptr); }
+ bool isDestructible() const noexcept { return d_ptr && isDestructible(d_ptr); }
+ bool isEqualityComparable() const;
+ bool isOrdered() const;
- friend bool operator==(const QMetaType &a, const QMetaType &b) { return a.id() == b.id(); }
- friend bool operator!=(const QMetaType &a, const QMetaType &b) { return !(a == b); }
+#ifndef QT_NO_DATASTREAM
+ bool save(QDataStream &stream, const void *data) const;
+ bool load(QDataStream &stream, void *data) const;
+ bool hasRegisteredDataStreamOperators() const;
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static bool save(QDataStream &stream, int type, const void *data)
+ { return QMetaType(type).save(stream, data); }
+ QT_DEPRECATED_VERSION_6_0
+ static bool load(QDataStream &stream, int type, void *data)
+ { return QMetaType(type).load(stream, data); }
+#endif
+#endif
-public:
- template<typename T>
- static bool registerComparators()
- {
- static_assert((!QMetaTypeId2<T>::IsBuiltIn),
- "QMetaType::registerComparators: The type must be a custom type.");
+ QMetaType underlyingType() const;
- const int typeId = qMetaTypeId<T>();
- static const QtPrivate::BuiltInComparatorFunction<T> f;
- return registerComparatorFunction( &f, typeId);
- }
template<typename T>
- static bool registerEqualsComparator()
- {
- static_assert((!QMetaTypeId2<T>::IsBuiltIn),
- "QMetaType::registerEqualsComparator: The type must be a custom type.");
- const int typeId = qMetaTypeId<T>();
- static const QtPrivate::BuiltInEqualsComparatorFunction<T> f;
- return registerComparatorFunction( &f, typeId);
- }
-
- template<typename T>
- static bool hasRegisteredComparators()
+ constexpr static QMetaType fromType();
+ static QMetaType fromName(QByteArrayView name);
+private:
+ friend bool comparesEqual(const QMetaType &lhs,
+ const QMetaType &rhs) noexcept
{
- return hasRegisteredComparators(qMetaTypeId<T>());
- }
- static bool hasRegisteredComparators(int typeId);
-
-
+ if (lhs.d_ptr == rhs.d_ptr)
+ return true;
+ if (!lhs.d_ptr || !rhs.d_ptr)
+ return false; // one type is undefined, the other is defined
+ // avoid id call if we already have the id
+ const int aId = lhs.id();
+ const int bId = rhs.id();
+ return aId == bId;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QMetaType)
#ifndef QT_NO_DEBUG_STREAM
- template<typename T>
- static bool registerDebugStreamOperator()
- {
- static_assert((!QMetaTypeId2<T>::IsBuiltIn),
- "QMetaType::registerDebugStreamOperator: The type must be a custom type.");
+private:
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug d, QMetaType m);
+public:
+ bool debugStream(QDebug& dbg, const void *rhs);
+ bool hasRegisteredDebugStreamOperator() const;
- const int typeId = qMetaTypeId<T>();
- static const QtPrivate::BuiltInDebugStreamFunction<T> f;
- return registerDebugStreamOperatorFunction(&f, typeId);
- }
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
+ { return QMetaType(typeId).debugStream(dbg, rhs); }
template<typename T>
+ QT_DEPRECATED_VERSION_6_0
static bool hasRegisteredDebugStreamOperator()
- {
- return hasRegisteredDebugStreamOperator(qMetaTypeId<T>());
- }
- static bool hasRegisteredDebugStreamOperator(int typeId);
+ { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
+ QT_DEPRECATED_VERSION_6_0
+ static bool hasRegisteredDebugStreamOperator(int typeId)
+ { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
#endif
+#endif
+
+ // type erased converter function
+ using ConverterFunction = std::function<bool(const void *src, void *target)>;
+
+ // type erased mutable view, primarily for containers
+ using MutableViewFunction = std::function<bool(void *src, void *target)>;
// implicit conversion supported like double -> float
template<typename From, typename To>
@@ -631,14 +566,6 @@ public:
return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
}
-#ifdef Q_CLANG_QDOC
- template<typename MemberFunction, int>
- static bool registerConverter(MemberFunction function);
- template<typename MemberFunctionOk, char>
- static bool registerConverter(MemberFunctionOk function);
- template<typename UnaryFunction>
- static bool registerConverter(UnaryFunction function);
-#else
// member function as in "QString QFont::toString() const"
template<typename From, typename To>
static bool registerConverter(To(From::*function)() const)
@@ -646,10 +573,33 @@ public:
static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
"QMetaType::registerConverter: At least one of the types must be a custom type.");
- const int fromTypeId = qMetaTypeId<From>();
- const int toTypeId = qMetaTypeId<To>();
- static const QtPrivate::ConverterMemberFunction<From, To> f(function);
- return registerConverterFunction(&f, fromTypeId, toTypeId);
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto converter = [function](const void *from, void *to) -> bool {
+ const From *f = static_cast<const From *>(from);
+ To *t = static_cast<To *>(to);
+ *t = (f->*function)();
+ return true;
+ };
+ return registerConverterImpl<From, To>(converter, fromType, toType);
+ }
+
+ // member function
+ template<typename From, typename To>
+ static bool registerMutableView(To(From::*function)())
+ {
+ static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerMutableView: At least one of the types must be a custom type.");
+
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto view = [function](void *from, void *to) -> bool {
+ From *f = static_cast<From *>(from);
+ To *t = static_cast<To *>(to);
+ *t = (f->*function)();
+ return true;
+ };
+ return registerMutableViewImpl<From, To>(view, fromType, toType);
}
// member function as in "double QString::toDouble(bool *ok = nullptr) const"
@@ -659,10 +609,18 @@ public:
static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
"QMetaType::registerConverter: At least one of the types must be a custom type.");
- const int fromTypeId = qMetaTypeId<From>();
- const int toTypeId = qMetaTypeId<To>();
- static const QtPrivate::ConverterMemberFunctionOk<From, To> f(function);
- return registerConverterFunction(&f, fromTypeId, toTypeId);
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto converter = [function](const void *from, void *to) -> bool {
+ const From *f = static_cast<const From *>(from);
+ To *t = static_cast<To *>(to);
+ bool result = true;
+ *t = (f->*function)(&result);
+ if (!result)
+ *t = To();
+ return result;
+ };
+ return registerConverterImpl<From, To>(converter, fromType, toType);
}
// functor or function pointer
@@ -672,720 +630,225 @@ public:
static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
"QMetaType::registerConverter: At least one of the types must be a custom type.");
- const int fromTypeId = qMetaTypeId<From>();
- const int toTypeId = qMetaTypeId<To>();
- static const QtPrivate::ConverterFunctor<From, To, UnaryFunction> f(function);
- return registerConverterFunction(&f, fromTypeId, toTypeId);
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto converter = [function = std::move(function)](const void *from, void *to) -> bool {
+ const From *f = static_cast<const From *>(from);
+ To *t = static_cast<To *>(to);
+ auto &&r = function(*f);
+ if constexpr (std::is_same_v<q20::remove_cvref_t<decltype(r)>, std::optional<To>>) {
+ if (!r)
+ return false;
+ *t = *std::forward<decltype(r)>(r);
+ } else {
+ *t = std::forward<decltype(r)>(r);
+ }
+ return true;
+ };
+ return registerConverterImpl<From, To>(std::move(converter), fromType, toType);
}
-#endif
-
- static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
- static bool compare(const void *lhs, const void *rhs, int typeId, int* result);
- static bool equals(const void *lhs, const void *rhs, int typeId, int* result);
- static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
- template<typename From, typename To>
- static bool hasRegisteredConverterFunction()
+ // functor or function pointer
+ template<typename From, typename To, typename UnaryFunction>
+ static bool registerMutableView(UnaryFunction function)
{
- return hasRegisteredConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
+ static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerMutableView: At least one of the types must be a custom type.");
+
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto view = [function = std::move(function)](void *from, void *to) -> bool {
+ From *f = static_cast<From *>(from);
+ To *t = static_cast<To *>(to);
+ *t = function(*f);
+ return true;
+ };
+ return registerMutableViewImpl<From, To>(std::move(view), fromType, toType);
}
- static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
-
- static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
-#ifndef QT_NO_DEBUG_STREAM
- static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
-#endif
-
-#ifndef Q_CLANG_QDOC
- template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
- template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
- template<typename, typename> friend struct QtPrivate::ConverterMemberFunctionOk;
- template<typename, typename, typename> friend struct QtPrivate::ConverterFunctor;
- template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
- template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
- template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
-#endif
- static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
- static void unregisterConverterFunction(int from, int to);
private:
- friend class QVariant;
- QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
-};
-
-#undef QT_DEFINE_METATYPE_ID
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
-
-namespace QtPrivate {
-
-template<typename From, typename To>
-ConverterMemberFunction<From, To>::~ConverterMemberFunction()
-{
- QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
-}
-template<typename From, typename To>
-ConverterMemberFunctionOk<From, To>::~ConverterMemberFunctionOk()
-{
- QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
-}
-template<typename From, typename To, typename UnaryFunction>
-ConverterFunctor<From, To, UnaryFunction>::~ConverterFunctor()
-{
- QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
-}
-
-}
-
-#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
- } \
- Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
- namespace QtMetaTypePrivate {
-
-namespace QtMetaTypePrivate {
-template <typename T, bool Accepted = true>
-struct QMetaTypeFunctionHelper {
- static void Destruct(void *t)
- {
- Q_UNUSED(t) // Silence MSVC that warns for POD types.
- static_cast<T*>(t)->~T();
- }
-
- static void *Construct(void *where, const void *t)
- {
- if (t)
- return new (where) T(*static_cast<const T*>(t));
- return new (where) T;
- }
-#ifndef QT_NO_DATASTREAM
- static void Save(QDataStream &stream, const void *t)
- {
- stream << *static_cast<const T*>(t);
- }
-
- static void Load(QDataStream &stream, void *t)
+ template<typename From, typename To>
+ static bool registerConverterImpl(ConverterFunction converter, QMetaType fromType, QMetaType toType)
{
- stream >> *static_cast<T*>(t);
+ if (registerConverterFunction(std::move(converter), fromType, toType)) {
+ static const auto unregister = qScopeGuard([=] {
+ unregisterConverterFunction(fromType, toType);
+ });
+ return true;
+ } else {
+ return false;
+ }
}
-#endif // QT_NO_DATASTREAM
-};
-template <typename T>
-struct QMetaTypeFunctionHelper<T, /* Accepted */ false> {
- static void Destruct(void *) {}
- static void *Construct(void *, const void *) { return nullptr; }
-#ifndef QT_NO_DATASTREAM
- static void Save(QDataStream &, const void *) {}
- static void Load(QDataStream &, void *) {}
-#endif // QT_NO_DATASTREAM
-};
-template <>
-struct QMetaTypeFunctionHelper<void, /* Accepted */ true>
- : public QMetaTypeFunctionHelper<void, /* Accepted */ false>
-{};
-
-struct VariantData
-{
- VariantData(const int metaTypeId_,
- const void *data_,
- const uint flags_)
- : metaTypeId(metaTypeId_)
- , data(data_)
- , flags(flags_)
+ template<typename From, typename To>
+ static bool registerMutableViewImpl(MutableViewFunction view, QMetaType fromType, QMetaType toType)
{
+ if (registerMutableViewFunction(std::move(view), fromType, toType)) {
+ static const auto unregister = qScopeGuard([=] {
+ unregisterMutableViewFunction(fromType, toType);
+ });
+ return true;
+ } else {
+ return false;
+ }
}
- VariantData(const VariantData &other)
- : metaTypeId(other.metaTypeId), data(other.data), flags(other.flags){}
- const int metaTypeId;
- const void *data;
- const uint flags;
-private:
- // copy constructor allowed to be implicit to silence level 4 warning from MSVC
- VariantData &operator=(const VariantData &) = delete;
-};
+public:
-template<typename const_iterator>
-struct IteratorOwnerCommon
-{
- static void assign(void **ptr, const_iterator iterator)
- {
- *ptr = new const_iterator(iterator);
+ static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
+ static bool canConvert(QMetaType fromType, QMetaType toType);
+
+ static bool view(QMetaType fromType, void *from, QMetaType toType, void *to);
+ static bool canView(QMetaType fromType, QMetaType toType);
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
+ { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); }
+ QT_DEPRECATED_VERSION_6_0
+ static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
+ {
+ QMetaType t(typeId);
+ auto c = t.compare(lhs, rhs);
+ if (c == QPartialOrdering::Unordered) {
+ *result = 0;
+ return false;
+ } else if (c == QPartialOrdering::Less) {
+ *result = -1;
+ return true;
+ } else if (c == QPartialOrdering::Equivalent) {
+ *result = 0;
+ return true;
+ } else {
+ *result = 1;
+ return true;
+ }
}
- static void assign(void **ptr, void * const * src)
+ QT_DEPRECATED_VERSION_6_0
+ static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
{
- *ptr = new const_iterator(*static_cast<const_iterator*>(*src));
+ QMetaType t(typeId);
+ if (!t.isEqualityComparable())
+ return false;
+ *result = t.equals(lhs, rhs) ? 0 : -1;
+ return true;
}
+#endif
- static void advance(void **iterator, int step)
+ template<typename From, typename To>
+ static bool hasRegisteredConverterFunction()
{
- const_iterator &it = *static_cast<const_iterator*>(*iterator);
- std::advance(it, step);
+ return hasRegisteredConverterFunction(
+ QMetaType::fromType<From>(), QMetaType::fromType<To>());
}
- static void destroy(void **ptr)
- {
- delete static_cast<const_iterator*>(*ptr);
- }
+ static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType);
- static bool equal(void * const *it, void * const *other)
+ template<typename From, typename To>
+ static bool hasRegisteredMutableViewFunction()
{
- return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
+ return hasRegisteredMutableViewFunction(
+ QMetaType::fromType<From>(), QMetaType::fromType<To>());
}
-};
-template<typename const_iterator>
-struct IteratorOwner : IteratorOwnerCommon<const_iterator>
-{
- static const void *getData(void * const *iterator)
- {
- return &**static_cast<const_iterator*>(*iterator);
- }
+ static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType);
- static const void *getData(const_iterator it)
- {
- return &*it;
- }
-};
+#ifndef Q_QDOC
+ template<typename, bool> friend struct QtPrivate::SequentialValueTypeIsMetaType;
+ template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
+ template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
+ template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
+#endif
+ static bool registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to);
+ static void unregisterConverterFunction(QMetaType from, QMetaType to);
-struct Q_CORE_EXPORT VectorBoolElements
-{
- static const bool true_element;
- static const bool false_element;
-};
+ static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to);
+ static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
-template<>
-struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator>
-{
-public:
- static const void *getData(void * const *iterator)
- {
- return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ?
- &VectorBoolElements::true_element : &VectorBoolElements::false_element;
- }
+ static void unregisterMetaType(QMetaType type);
- static const void *getData(const std::vector<bool>::const_iterator& it)
- {
- return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element;
- }
-};
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
+#endif
+ const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
-template<typename value_type>
-struct IteratorOwner<const value_type*>
-{
private:
- // We need to disable typed overloads of assign() and getData() if the value_type
- // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
- // type as part of the overload signature.
- struct Dummy {};
- typedef typename std::conditional<std::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
-public:
- static void assign(void **ptr, const value_type_OR_Dummy *iterator )
- {
- *ptr = const_cast<value_type*>(iterator);
- }
- static void assign(void **ptr, void * const * src)
- {
- *ptr = static_cast<value_type*>(*src);
- }
-
- static void advance(void **iterator, int step)
- {
- value_type *it = static_cast<value_type*>(*iterator);
- std::advance(it, step);
- *iterator = it;
- }
-
- static void destroy(void **)
- {
- }
+ static bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
+ static bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
+ static bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
+ static bool isDestructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
- static const void *getData(void * const *iterator)
- {
- return *iterator;
- }
-
- static const void *getData(const value_type_OR_Dummy *it)
- {
- return it;
- }
-
- static bool equal(void * const *it, void * const *other)
- {
- return static_cast<value_type*>(*it) == static_cast<value_type*>(*other);
+#if QT_CORE_REMOVED_SINCE(6, 5)
+ int idHelper() const;
+#endif
+ static int registerHelper(const QtPrivate::QMetaTypeInterface *iface);
+ int registerHelper() const
+ {
+ // keep in sync with the QMetaType::id() version in removed_api.cpp
+ if (d_ptr) {
+ if (int id = d_ptr->typeId.loadRelaxed())
+ return id;
+ return registerHelper(d_ptr);
+ }
+ return 0;
}
-};
-enum IteratorCapability
-{
- ForwardCapability = 1,
- BiDirectionalCapability = 2,
- RandomAccessCapability = 4
-};
-
-enum ContainerCapability
-{
- ContainerIsAppendable = 1
-};
-
-template<typename Container, typename T = void>
-struct ContainerCapabilitiesImpl
-{
- enum {ContainerCapabilities = 0};
- using appendFunction = void(*)(const void *container, const void *newElement);
- static constexpr const appendFunction appendImpl = nullptr;
-};
+ friend int qRegisterMetaType(QMetaType meta);
-template<typename Container>
-struct ContainerCapabilitiesImpl<Container, decltype(std::declval<Container>().push_back(std::declval<typename Container::value_type>()))>
-{
- enum {ContainerCapabilities = ContainerIsAppendable};
-
- // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl
- // pointed to a const object to begin with
- static void appendImpl(const void *container, const void *value)
- { static_cast<Container *>(const_cast<void *>(container))->push_back(*static_cast<const typename Container::value_type *>(value)); }
-};
-
-namespace QtPrivate {
-namespace ContainerCapabilitiesMetaProgrammingHelper {
- template<typename... Ts>
- using void_t = void;
-}
-}
-
-template<typename Container>
-struct ContainerCapabilitiesImpl<Container, QtPrivate::ContainerCapabilitiesMetaProgrammingHelper::void_t<decltype(std::declval<Container>().insert(std::declval<typename Container::value_type>())), decltype(std::declval<typename Container::value_type>() == std::declval<typename Container::value_type>())>>
-{
- enum {ContainerCapabilities = ContainerIsAppendable};
-
- // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl
- // pointed to a const object to begin with
- static void appendImpl(const void *container, const void *value)
- { static_cast<Container *>(const_cast<void *>(container))->insert(*static_cast<const typename Container::value_type *>(value)); }
-};
-
-template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
-struct CapabilitiesImpl;
-
-template<typename T>
-struct CapabilitiesImpl<T, std::forward_iterator_tag>
-{ enum { IteratorCapabilities = ForwardCapability }; };
-template<typename T>
-struct CapabilitiesImpl<T, std::bidirectional_iterator_tag>
-{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; };
-template<typename T>
-struct CapabilitiesImpl<T, std::random_access_iterator_tag>
-{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; };
-
-template<typename T>
-struct ContainerAPI : CapabilitiesImpl<T>
-{
- static int size(const T *t) { return int(std::distance(t->begin(), t->end())); }
+ friend class QVariant;
+ const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
};
-template<typename T>
-struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
-{ static int size(const QVector<T> *t) { return t->size(); } };
-
-template<typename T>
-struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
-{ static int size(const std::vector<T> *t) { return int(t->size()); } };
-
-template<typename T>
-struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
-{ static int size(const std::list<T> *t) { return int(t->size()); } };
-
-/*
- revision 0: _iteratorCapabilities is simply a uint, where the bits at _revision were never set
- revision 1: _iteratorCapabilties is treated as a bitfield, the remaining bits are used to introduce
- _revision, _containerCapabilities and _unused. The latter contains 21 bits that are
- not used yet
-*/
-class QSequentialIterableImpl
-{
-public:
- const void * _iterable;
- void *_iterator;
- int _metaType_id;
- uint _metaType_flags;
- uint _iteratorCapabilities;
- // Iterator capabilities looks actually like
- // uint _iteratorCapabilities:4;
- // uint _revision:3;
- // uint _containerCapabilities:4;
- // uint _unused:21;
- typedef int(*sizeFunc)(const void *p);
- typedef const void * (*atFunc)(const void *p, int);
- typedef void (*moveIteratorFunc)(const void *p, void **);
- enum Position { ToBegin, ToEnd };
- typedef void (*moveIteratorFunc2)(const void *p, void **, Position position);
- typedef void (*advanceFunc)(void **p, int);
- typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
- typedef void (*destroyIterFunc)(void **p);
- typedef bool (*equalIterFunc)(void * const *p, void * const *other);
- typedef void (*copyIterFunc)(void **, void * const *);
- typedef void(*appendFunction)(const void *container, const void *newElement);
-
- IteratorCapability iteratorCapabilities() {return static_cast<IteratorCapability>(_iteratorCapabilities & 0xF);}
- uint revision() {return _iteratorCapabilities >> 4 & 0x7;}
- uint containerCapabilities() {return _iteratorCapabilities >> 7 & 0xF;}
-
- sizeFunc _size;
- atFunc _at;
- union {
- moveIteratorFunc _moveToBegin;
- moveIteratorFunc2 _moveTo;
- };
- union {
- moveIteratorFunc _moveToEnd;
- appendFunction _append;
- };
- advanceFunc _advance;
- getFunc _get;
- destroyIterFunc _destroyIter;
- equalIterFunc _equalIter;
- copyIterFunc _copyIter;
-
- template<class T>
- static int sizeImpl(const void *p)
- { return ContainerAPI<T>::size(static_cast<const T*>(p)); }
-
- template<class T>
- static const void* atImpl(const void *p, int idx)
- {
- typename T::const_iterator i = static_cast<const T*>(p)->begin();
- std::advance(i, idx);
- return IteratorOwner<typename T::const_iterator>::getData(i);
- }
-
- template<class T>
- static void moveToBeginImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
-
- template<class T>
- static void moveToEndImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
-
- template<class Container>
- static void moveToImpl(const void *container, void **iterator, Position position)
- {
- if (position == ToBegin)
- moveToBeginImpl<Container>(container, iterator);
- else
- moveToEndImpl<Container>(container, iterator);
- }
-
- template<class T>
- static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
-
-public:
- template<class T> QSequentialIterableImpl(const T*p)
- : _iterable(p)
- , _iterator(nullptr)
- , _metaType_id(qMetaTypeId<typename T::value_type>())
- , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer)
- , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities | (1 << 4) | (ContainerCapabilitiesImpl<T>::ContainerCapabilities << (4+3)))
- , _size(sizeImpl<T>)
- , _at(atImpl<T>)
- , _moveTo(moveToImpl<T>)
- , _append(ContainerCapabilitiesImpl<T>::appendImpl)
- , _advance(IteratorOwner<typename T::const_iterator>::advance)
- , _get(getImpl<T>)
- , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
- , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
- , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
- {
- }
-
- QSequentialIterableImpl()
- : _iterable(nullptr)
- , _iterator(nullptr)
- , _metaType_id(QMetaType::UnknownType)
- , _metaType_flags(0)
- , _iteratorCapabilities(0 | (1 << 4) ) // no iterator capabilities, revision 1
- , _size(nullptr)
- , _at(nullptr)
- , _moveToBegin(nullptr)
- , _moveToEnd(nullptr)
- , _advance(nullptr)
- , _get(nullptr)
- , _destroyIter(nullptr)
- , _equalIter(nullptr)
- , _copyIter(nullptr)
- {
- }
-
- inline void moveToBegin() {
- if (revision() == 0)
- _moveToBegin(_iterable, &_iterator);
- else
- _moveTo(_iterable, &_iterator, ToBegin);
- }
- inline void moveToEnd() {
- if (revision() == 0)
- _moveToEnd(_iterable, &_iterator);
- else
- _moveTo(_iterable, &_iterator, ToEnd);
- }
- inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
- inline QSequentialIterableImpl &advance(int i) {
- Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability);
- _advance(&_iterator, i);
- return *this;
- }
-
- inline void append(const void *newElement) {
- if (containerCapabilities() & ContainerIsAppendable)
- _append(_iterable, newElement);
- }
-
- inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); }
-
- VariantData at(int idx) const
- { return VariantData(_metaType_id, _at(_iterable, idx), _metaType_flags); }
-
- int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
+#undef QT_DEFINE_METATYPE_ID
- inline void destroyIter() { _destroyIter(&_iterator); }
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
- void copy(const QSequentialIterableImpl &other)
- {
- *this = other;
- _copyIter(&_iterator, &other._iterator);
- }
-};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QSequentialIterableImpl, Q_MOVABLE_TYPE)
+#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
+ } \
+ Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
+ namespace QtMetaTypePrivate {
-template<typename From>
-struct QSequentialIterableConvertFunctor
-{
- QSequentialIterableImpl operator()(const From &f) const
- {
- return QSequentialIterableImpl(&f);
- }
-};
-}
namespace QtMetaTypePrivate {
-template<typename T, bool = std::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
-struct AssociativeContainerAccessor
-{
- static const typename T::key_type& getKey(const typename T::const_iterator &it)
- {
- return it.key();
- }
-
- static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
- {
- return it.value();
- }
-};
-
-template<typename T, bool = std::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
-struct StlStyleAssociativeContainerAccessor;
-
-template<typename T>
-struct StlStyleAssociativeContainerAccessor<T, true>
-{
- static const typename T::key_type& getKey(const typename T::const_iterator &it)
- {
- return it->first;
- }
-
- static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
- {
- return it->second;
- }
-};
-
-template<typename T>
-struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
-{
-};
-
-class QAssociativeIterableImpl
-{
-public:
- const void *_iterable;
- void *_iterator;
- int _metaType_id_key;
- uint _metaType_flags_key;
- int _metaType_id_value;
- uint _metaType_flags_value;
- typedef int(*sizeFunc)(const void *p);
- typedef void (*findFunc)(const void *container, const void *p, void **iterator);
- typedef void (*beginFunc)(const void *p, void **);
- typedef void (*advanceFunc)(void **p, int);
- typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
- typedef void (*destroyIterFunc)(void **p);
- typedef bool (*equalIterFunc)(void * const *p, void * const *other);
- typedef void (*copyIterFunc)(void **, void * const *);
-
- sizeFunc _size;
- findFunc _find;
- beginFunc _begin;
- beginFunc _end;
- advanceFunc _advance;
- getFunc _getKey;
- getFunc _getValue;
- destroyIterFunc _destroyIter;
- equalIterFunc _equalIter;
- copyIterFunc _copyIter;
-
- template<class T>
- static int sizeImpl(const void *p)
- { return int(std::distance(static_cast<const T*>(p)->begin(),
- static_cast<const T*>(p)->end())); }
-
- template<class T>
- static void findImpl(const void *container, const void *p, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator,
- static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
-
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED // Hits on the deprecated QHash::iterator::operator--()
- template<class T>
- static void advanceImpl(void **p, int step)
- { std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
- QT_WARNING_POP
-
- template<class T>
- static void beginImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
-
- template<class T>
- static void endImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
-
- template<class T>
- static VariantData getKeyImpl(void * const *iterator, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
-
- template<class T>
- static VariantData getValueImpl(void * const *iterator, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
-
-public:
- template<class T> QAssociativeIterableImpl(const T*p)
- : _iterable(p)
- , _iterator(nullptr)
- , _metaType_id_key(qMetaTypeId<typename T::key_type>())
- , _metaType_flags_key(QTypeInfo<typename T::key_type>::isPointer)
- , _metaType_id_value(qMetaTypeId<typename T::mapped_type>())
- , _metaType_flags_value(QTypeInfo<typename T::mapped_type>::isPointer)
- , _size(sizeImpl<T>)
- , _find(findImpl<T>)
- , _begin(beginImpl<T>)
- , _end(endImpl<T>)
- , _advance(advanceImpl<T>)
- , _getKey(getKeyImpl<T>)
- , _getValue(getValueImpl<T>)
- , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
- , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
- , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
- {
- }
-
- QAssociativeIterableImpl()
- : _iterable(nullptr)
- , _iterator(nullptr)
- , _metaType_id_key(QMetaType::UnknownType)
- , _metaType_flags_key(0)
- , _metaType_id_value(QMetaType::UnknownType)
- , _metaType_flags_value(0)
- , _size(nullptr)
- , _find(nullptr)
- , _begin(nullptr)
- , _end(nullptr)
- , _advance(nullptr)
- , _getKey(nullptr)
- , _getValue(nullptr)
- , _destroyIter(nullptr)
- , _equalIter(nullptr)
- , _copyIter(nullptr)
- {
- }
-
- inline void begin() { _begin(_iterable, &_iterator); }
- inline void end() { _end(_iterable, &_iterator); }
- inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
- inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
-
- inline void destroyIter() { _destroyIter(&_iterator); }
-
- inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_key); }
- inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); }
-
- inline void find(const VariantData &key)
- { _find(_iterable, key.data, &_iterator); }
-
- int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
-
- void copy(const QAssociativeIterableImpl &other)
- {
- *this = other;
- _copyIter(&_iterator, &other._iterator);
- }
-};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QAssociativeIterableImpl, Q_MOVABLE_TYPE)
-
-template<typename From>
-struct QAssociativeIterableConvertFunctor
-{
- QAssociativeIterableImpl operator()(const From& f) const
- {
- return QAssociativeIterableImpl(&f);
- }
-};
class QPairVariantInterfaceImpl
{
+public:
const void *_pair;
- int _metaType_id_first;
- uint _metaType_flags_first;
- int _metaType_id_second;
- uint _metaType_flags_second;
+ QMetaType _metaType_first;
+ QMetaType _metaType_second;
- typedef VariantData (*getFunc)(const void * const *p, int metaTypeId, uint flags);
+ typedef void (*getFunc)(const void * const *p, void *);
getFunc _getFirst;
getFunc _getSecond;
template<class T>
- static VariantData getFirstImpl(const void * const *pair, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->first, flags); }
+ static void getFirstImpl(const void * const *pair, void *dataPtr)
+ { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; }
template<class T>
- static VariantData getSecondImpl(const void * const *pair, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->second, flags); }
+ static void getSecondImpl(const void * const *pair, void *dataPtr)
+ { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; }
public:
template<class T> QPairVariantInterfaceImpl(const T*p)
: _pair(p)
- , _metaType_id_first(qMetaTypeId<typename T::first_type>())
- , _metaType_flags_first(QTypeInfo<typename T::first_type>::isPointer)
- , _metaType_id_second(qMetaTypeId<typename T::second_type>())
- , _metaType_flags_second(QTypeInfo<typename T::second_type>::isPointer)
+ , _metaType_first(QMetaType::fromType<typename T::first_type>())
+ , _metaType_second(QMetaType::fromType<typename T::second_type>())
, _getFirst(getFirstImpl<T>)
, _getSecond(getSecondImpl<T>)
{
}
- QPairVariantInterfaceImpl()
+ constexpr QPairVariantInterfaceImpl()
: _pair(nullptr)
- , _metaType_id_first(QMetaType::UnknownType)
- , _metaType_flags_first(0)
- , _metaType_id_second(QMetaType::UnknownType)
- , _metaType_flags_second(0)
, _getFirst(nullptr)
, _getSecond(nullptr)
{
}
- inline VariantData first() const { return _getFirst(&_pair, _metaType_id_first, _metaType_flags_first); }
- inline VariantData second() const { return _getSecond(&_pair, _metaType_id_second, _metaType_flags_second); }
+ inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); }
+ inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); }
};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_MOVABLE_TYPE)
+QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_RELOCATABLE_TYPE)
template<typename From>
struct QPairVariantInterfaceConvertFunctor;
@@ -1402,7 +865,6 @@ struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
}
class QObject;
-class QWidget;
#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \
template <class T> class Name; \
@@ -1411,6 +873,34 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_T
namespace QtPrivate
{
+ namespace detail {
+ template<typename T, typename ODR_VIOLATION_PREVENTER>
+ struct is_complete_helper
+ {
+ template<typename U>
+ static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
+ static auto check(...) -> std::false_type;
+ using type = decltype(check(static_cast<T *>(nullptr)));
+ };
+ } // namespace detail
+
+ template <typename T, typename ODR_VIOLATION_PREVENTER>
+ struct is_complete : detail::is_complete_helper<std::remove_reference_t<T>, ODR_VIOLATION_PREVENTER>::type {};
+
+ template <typename T> struct MetatypeDecay { using type = T; };
+ template <typename T> struct MetatypeDecay<const T> { using type = T; };
+ template <typename T> struct MetatypeDecay<const T &> { using type = T; };
+
+ template <typename T> struct IsPointerDeclaredOpaque :
+ std::disjunction<std::is_member_pointer<T>,
+ std::is_function<std::remove_pointer_t<T>>>
+ {};
+ template <> struct IsPointerDeclaredOpaque<void *> : std::true_type {};
+ template <> struct IsPointerDeclaredOpaque<const void *> : std::true_type {};
+
+ // Note: this does not check that T = U* isn't pointing to a
+ // forward-declared type. You may want to combine with
+ // checkTypeIsSuitableForMetaType().
template<typename T>
struct IsPointerToTypeDerivedFromQObject
{
@@ -1442,9 +932,9 @@ namespace QtPrivate
#ifndef QT_NO_QOBJECT
static yes_type checkType(QObject* );
+ static yes_type checkType(const QObject* );
#endif
static no_type checkType(...);
- static_assert(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined");
enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
};
@@ -1463,6 +953,9 @@ namespace QtPrivate
};
};
+ template <typename T>
+ using IsRealGadget = std::bool_constant<IsGadgetHelper<T>::IsRealGadget>;
+
template<typename T, typename Enable = void>
struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
@@ -1496,36 +989,42 @@ namespace QtPrivate
template<typename T, typename Enable = void>
struct MetaObjectForType
{
- static constexpr inline const QMetaObject *value() { return nullptr; }
+ static constexpr const QMetaObject *value() { return nullptr; }
+ using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
+ static constexpr MetaObjectFn metaObjectFunction = nullptr;
};
#ifndef QT_NO_QOBJECT
- template<>
- struct MetaObjectForType<void>
- {
- static constexpr inline const QMetaObject *value() { return nullptr; }
- };
template<typename T>
struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
{
- static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
};
template<typename T>
- struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
- {
- static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
+ struct MetaObjectForType<T, std::enable_if_t<
+ std::disjunction_v<
+ std::bool_constant<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>,
+ std::is_base_of<QObject, T>
+ >
+ >>
+ {
+ static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
- static constexpr inline const QMetaObject *value()
+ static constexpr const QMetaObject *value()
{
return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject;
}
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
{
- static constexpr inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
+ static constexpr const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
};
#endif
@@ -1576,62 +1075,82 @@ namespace QtPrivate
};
template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
- struct SequentialContainerConverterHelper
+ struct SequentialContainerTransformationHelper
{
- static bool registerConverter(int)
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
{
return false;
}
};
template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
- struct ValueTypeIsMetaType
+ struct SequentialValueTypeIsMetaType
{
- static bool registerConverter(int)
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
{
return false;
}
};
template<typename T>
- struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T>
+ struct SequentialContainerTransformationHelper<T, true> : SequentialValueTypeIsMetaType<T>
{
};
template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
- struct AssociativeContainerConverterHelper
+ struct AssociativeContainerTransformationHelper
{
- static bool registerConverter(int)
+ static bool registerConverter()
{
return false;
}
- };
- template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
- struct AssociativeValueTypeIsMetaType
- {
- static bool registerConverter(int)
+ static bool registerMutableView()
{
return false;
}
};
template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
- struct KeyAndValueTypeIsMetaType
+ struct AssociativeKeyTypeIsMetaType
{
- static bool registerConverter(int)
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
{
return false;
}
};
- template<typename T>
- struct KeyAndValueTypeIsMetaType<T, true> : AssociativeValueTypeIsMetaType<T>
+ template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
+ struct AssociativeMappedTypeIsMetaType
{
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
+ {
+ return false;
+ }
};
template<typename T>
- struct AssociativeContainerConverterHelper<T, true> : KeyAndValueTypeIsMetaType<T>
+ struct AssociativeContainerTransformationHelper<T, true> : AssociativeKeyTypeIsMetaType<T>
{
};
@@ -1639,7 +1158,7 @@ namespace QtPrivate
&& QMetaTypeId2<typename T::second_type>::Defined>
struct IsMetaTypePair
{
- static bool registerConverter(int)
+ static bool registerConverter()
{
return false;
}
@@ -1648,13 +1167,13 @@ namespace QtPrivate
template<typename T>
struct IsMetaTypePair<T, true>
{
- inline static bool registerConverter(int id);
+ inline static bool registerConverter();
};
template<typename T>
struct IsPair
{
- static bool registerConverter(int)
+ static bool registerConverter()
{
return false;
}
@@ -1668,15 +1187,39 @@ namespace QtPrivate
template<typename T, typename = void>
struct MetaTypeSmartPointerHelper
{
- static bool registerConverter(int) { return false; }
+ static bool registerConverter() { return false; }
};
+#if QT_CONFIG(future)
+ template<typename T>
+ struct MetaTypeQFutureHelper
+ {
+ static bool registerConverter() { return false; }
+ };
+#endif
+
+ template <typename X> static constexpr bool checkTypeIsSuitableForMetaType()
+ {
+ using T = typename MetatypeDecay<X>::type;
+ static_assert(is_complete<T, void>::value || std::is_void_v<T>,
+ "Meta Types must be fully defined");
+ static_assert(!std::is_reference_v<T>,
+ "Meta Types cannot be non-const references or rvalue references.");
+ if constexpr (std::is_pointer_v<T> && !IsPointerDeclaredOpaque<T>::value) {
+ using Pointed = std::remove_pointer_t<T>;
+ static_assert(is_complete<Pointed, void>::value,
+ "Pointer Meta Types must either point to fully-defined types "
+ "or be declared with Q_DECLARE_OPAQUE_POINTER(T *)");
+ }
+ return true;
+ }
+
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
template <typename T, int =
QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
- QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget :
+ QtPrivate::IsRealGadget<T>::value ? QMetaType::IsGadget :
QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
struct QMetaTypeIdQObject
@@ -1694,24 +1237,30 @@ struct QMetaTypeId : public QMetaTypeIdQObject<T>
template <typename T>
struct QMetaTypeId2
{
+ using NameAsArrayType = void;
enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
- static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
+ static inline constexpr int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
};
template <typename T>
struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
template <typename T>
-struct QMetaTypeId2<T&> { enum {Defined = false }; };
+struct QMetaTypeId2<T&>
+{
+ using NameAsArrayType = void;
+ enum { Defined = false, IsBuiltIn = false };
+ static inline constexpr int qt_metatype_id() { return 0; }
+};
namespace QtPrivate {
template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
struct QMetaTypeIdHelper {
- static inline Q_DECL_CONSTEXPR int qt_metatype_id()
+ static inline constexpr int qt_metatype_id()
{ return QMetaTypeId2<T>::qt_metatype_id(); }
};
template <typename T> struct QMetaTypeIdHelper<T, false> {
- static inline Q_DECL_CONSTEXPR int qt_metatype_id()
+ static inline constexpr int qt_metatype_id()
{ return -1; }
};
@@ -1720,11 +1269,21 @@ namespace QtPrivate {
struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
template<typename T>
+ inline constexpr bool IsQmlListType = false;
+
+ template<typename T, bool = std::is_enum<T>::value>
+ constexpr bool IsUnsignedEnum = false;
+ template<typename T>
+ constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
+
+ template<typename T>
struct QMetaTypeTypeFlags
{
- enum { Flags = (QTypeInfoQuery<T>::isRelocatable ? QMetaType::MovableType : 0)
- | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
- | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
+ enum { Flags = (QTypeInfo<T>::isRelocatable ? QMetaType::RelocatableType : 0)
+ | ((!std::is_default_constructible_v<T> || !QTypeInfo<T>::isValueInitializationBitwiseZero) ? QMetaType::NeedsConstruction : 0)
+ | (!std::is_trivially_destructible_v<T> ? QMetaType::NeedsDestruction : 0)
+ | (!std::is_trivially_copy_constructible_v<T> ? QMetaType::NeedsCopyConstruction : 0)
+ | (!std::is_trivially_move_constructible_v<T> ? QMetaType::NeedsMoveConstruction : 0)
| (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
| (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
| (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
@@ -1732,7 +1291,10 @@ namespace QtPrivate {
| (IsEnumOrFlags<T>::value ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
| (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
- | (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0)
+ | (std::is_pointer_v<T> ? QMetaType::IsPointer : 0)
+ | (IsUnsignedEnum<T> ? QMetaType::IsUnsignedEnumeration : 0)
+ | (IsQmlListType<T> ? QMetaType::IsQmlList : 0)
+ | (std::is_const_v<std::remove_pointer_t<T>> ? QMetaType::IsConst : 0)
};
};
@@ -1767,65 +1329,85 @@ namespace QtPrivate {
}
template <typename T>
-int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
-#ifndef Q_CLANG_QDOC
- , T * = 0
- , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
-#endif
-)
+int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
{
#ifndef QT_NO_QOBJECT
- Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), "qRegisterNormalizedMetaType", "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
+ Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()),
+ "qRegisterNormalizedMetaType",
+ "qRegisterNormalizedMetaType was called with a not normalized type name, "
+ "please call qRegisterMetaType instead.");
#endif
const QMetaType metaType = QMetaType::fromType<T>();
const int id = metaType.id();
- if (id > 0) {
+ QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
+ QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
+ QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
+ QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
+ QtPrivate::MetaTypePairHelper<T>::registerConverter();
+ QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
+#if QT_CONFIG(future)
+ QtPrivate::MetaTypeQFutureHelper<T>::registerConverter();
+#endif
+
+ if (normalizedTypeName != metaType.name())
QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
- QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
- QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
- QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
- QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
- }
return id;
}
+// This primary template calls the -Implementation, like all other specialisations should.
+// But the split allows to
+// - in a header:
+// - define a specialization of this template calling an out-of-line function
+// (QT_DECL_METATYPE_EXTERN{,_TAGGED})
+// - in the .cpp file:
+// - define the out-of-line wrapper to call the -Implementation
+// (QT_IMPL_METATYPE_EXTERN{,_TAGGED})
+// The _TAGGED variants let you choose a tag (must be a C identifier) to disambiguate
+// the out-of-line function; the non-_TAGGED variants use the passed class name as tag.
template <typename T>
-int qRegisterMetaType(const char *typeName
-#ifndef Q_CLANG_QDOC
- , T * dummy = nullptr
- , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
-#endif
-)
+int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
+{
+ return qRegisterNormalizedMetaTypeImplementation<T>(normalizedTypeName);
+}
+
+#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT) \
+ QT_BEGIN_NAMESPACE \
+ EXPORT int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &); \
+ template <> inline int qRegisterNormalizedMetaType< TYPE >(const QByteArray &name) \
+ { return qRegisterNormalizedMetaType_ ## TAG (name); } \
+ QT_END_NAMESPACE \
+ Q_DECLARE_METATYPE(TYPE) \
+ /* end */
+#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG) \
+ int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &name) \
+ { return qRegisterNormalizedMetaTypeImplementation< TYPE >(name); } \
+ /* end */
+#define QT_DECL_METATYPE_EXTERN(TYPE, EXPORT) \
+ QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TYPE, EXPORT)
+#define QT_IMPL_METATYPE_EXTERN(TYPE) \
+ QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TYPE)
+
+template <typename T>
+int qRegisterMetaType(const char *typeName)
{
#ifdef QT_NO_QOBJECT
QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
#else
QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
#endif
- return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
-}
-
-#ifndef QT_NO_DATASTREAM
-template <typename T>
-void qRegisterMetaTypeStreamOperators(const char *typeName
-#ifndef Q_CLANG_QDOC
- , T * /* dummy */ = nullptr
-#endif
-)
-{
- qRegisterMetaType<T>(typeName);
- QMetaType::registerStreamOperators(typeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
+ return qRegisterNormalizedMetaType<T>(normalizedTypeName);
}
-#endif // QT_NO_DATASTREAM
template <typename T>
-inline Q_DECL_CONSTEXPR int qMetaTypeId()
+inline constexpr int qMetaTypeId()
{
if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
+ // this has the same result as the below code, but avoids asking the
+ // compiler to load a global variable whose value we know at compile
+ // time
return QMetaTypeId2<T>::MetaType;
} else {
return QMetaType::fromType<T>().id();
@@ -1833,22 +1415,16 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId()
}
template <typename T>
-inline Q_DECL_CONSTEXPR int qRegisterMetaType()
+inline constexpr int qRegisterMetaType()
{
- return qMetaTypeId<T>();
+ int id = qMetaTypeId<T>();
+ return id;
}
-#if QT_DEPRECATED_SINCE(5, 1) && !defined(Q_CLANG_QDOC)
-// There used to be a T *dummy = 0 argument in Qt 4.0 to support MSVC6
-template <typename T>
-QT_DEPRECATED inline Q_DECL_CONSTEXPR int qMetaTypeId(T *)
-{ return qMetaTypeId<T>(); }
-#ifndef Q_CC_SUN
-template <typename T>
-QT_DEPRECATED inline Q_DECL_CONSTEXPR int qRegisterMetaType(T *)
-{ return qRegisterMetaType<T>(); }
-#endif
-#endif
+inline int qRegisterMetaType(QMetaType meta)
+{
+ return meta.registerHelper();
+}
#ifndef QT_NO_QOBJECT
template <typename T>
@@ -1860,16 +1436,14 @@ struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
- const char * const cName = T::staticMetaObject.className();
+ const char *const cName = T::staticMetaObject.className();
QByteArray typeName;
- typeName.reserve(int(strlen(cName)) + 1);
+ typeName.reserve(strlen(cName) + 1);
typeName.append(cName).append('*');
- const int newId = qRegisterNormalizedMetaType<T*>(
- typeName,
- reinterpret_cast<T**>(quintptr(-1)));
+ const int newId = qRegisterNormalizedMetaType<T *>(typeName);
metatype_id.storeRelease(newId);
return newId;
}
@@ -1884,13 +1458,11 @@ struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
- const char * const cName = T::staticMetaObject.className();
- const int newId = qRegisterNormalizedMetaType<T>(
- cName,
- reinterpret_cast<T*>(quintptr(-1)));
+ const char *const cName = T::staticMetaObject.className();
+ const int newId = qRegisterNormalizedMetaType<T>(cName);
metatype_id.storeRelease(newId);
return newId;
}
@@ -1905,16 +1477,14 @@ struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
- const char * const cName = T::staticMetaObject.className();
+ const char *const cName = T::staticMetaObject.className();
QByteArray typeName;
- typeName.reserve(int(strlen(cName)) + 1);
+ typeName.reserve(strlen(cName) + 1);
typeName.append(cName).append('*');
- const int newId = qRegisterNormalizedMetaType<T*>(
- typeName,
- reinterpret_cast<T**>(quintptr(-1)));
+ const int newId = qRegisterNormalizedMetaType<T *>(typeName);
metatype_id.storeRelease(newId);
return newId;
}
@@ -1929,41 +1499,25 @@ struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
const char *eName = qt_getEnumName(T());
const char *cName = qt_getEnumMetaObject(T())->className();
QByteArray typeName;
- typeName.reserve(int(strlen(cName) + 2 + strlen(eName)));
+ typeName.reserve(strlen(cName) + 2 + strlen(eName));
typeName.append(cName).append("::").append(eName);
- const int newId = qRegisterNormalizedMetaType<T>(
- typeName,
- reinterpret_cast<T*>(quintptr(-1)));
+ const int newId = qRegisterNormalizedMetaType<T>(typeName);
metatype_id.storeRelease(newId);
return newId;
}
};
#endif
-#ifndef QT_NO_DATASTREAM
-template <typename T>
-inline int qRegisterMetaTypeStreamOperators()
-{
- int id = qMetaTypeId<T>();
- QMetaType::registerStreamOperators(id, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
- return id;
-}
-#endif
-
#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
QT_BEGIN_NAMESPACE namespace QtPrivate { \
- template <> \
- struct IsPointerToTypeDerivedFromQObject<POINTER > \
- { \
- enum { Value = false }; \
- }; \
+ template <> struct IsPointerDeclaredOpaque<POINTER> \
+ : std::true_type {}; \
} QT_END_NAMESPACE \
/**/
@@ -1975,13 +1529,20 @@ inline int qRegisterMetaTypeStreamOperators()
struct QMetaTypeId< TYPE > \
{ \
enum { Defined = 1 }; \
+ static_assert(QtPrivate::checkTypeIsSuitableForMetaType<TYPE>()); \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
- const int newId = qRegisterMetaType< TYPE >(#TYPE, \
- reinterpret_cast< TYPE *>(quintptr(-1))); \
+ constexpr auto arr = QtPrivate::typenameHelper<TYPE>(); \
+ auto name = arr.data(); \
+ if (QByteArrayView(name) == (#TYPE)) { \
+ const int id = qRegisterNormalizedMetaType<TYPE>(name); \
+ metatype_id.storeRelease(id); \
+ return id; \
+ } \
+ const int newId = qRegisterMetaType< TYPE >(#TYPE); \
metatype_id.storeRelease(newId); \
return newId; \
} \
@@ -1993,9 +1554,10 @@ inline int qRegisterMetaTypeStreamOperators()
QT_BEGIN_NAMESPACE \
template<> struct QMetaTypeId2<NAME> \
{ \
+ using NameAsArrayType = std::array<char, sizeof(#NAME)>; \
enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \
- static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \
- static constexpr const char * const name = #NAME; \
+ static inline constexpr int qt_metatype_id() { return METATYPEID; } \
+ static constexpr NameAsArrayType nameAsArray = { #NAME }; \
}; \
QT_END_NAMESPACE
@@ -2008,15 +1570,6 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
-typedef QList<QVariant> QVariantList;
-typedef QMap<QString, QVariant> QVariantMap;
-typedef QHash<QString, QVariant> QVariantHash;
-#ifdef Q_CLANG_QDOC
-class QByteArrayList;
-#else
-using QByteArrayList = QList<QByteArray>;
-#endif
-
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
QT_BEGIN_NAMESPACE \
template <typename T> \
@@ -2027,31 +1580,22 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
}; \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadRelaxed()) \
return id; \
- const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
+ const char *tName = QMetaType::fromType<T>().name(); \
Q_ASSERT(tName); \
- const int tNameLen = int(qstrlen(tName)); \
+ const size_t tNameLen = qstrlen(tName); \
QByteArray typeName; \
- typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \
+ typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1); \
typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
.append('<').append(tName, tNameLen); \
typeName.append('>'); \
- const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \
- typeName, \
- reinterpret_cast< SINGLE_ARG_TEMPLATE<T> *>(quintptr(-1))); \
+ const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName); \
metatype_id.storeRelease(newId); \
return newId; \
} \
}; \
-namespace QtPrivate { \
-template<typename T> \
-struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
-{ \
- enum { Value = true }; \
-}; \
-} \
QT_END_NAMESPACE
#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
@@ -2064,23 +1608,21 @@ struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
}; \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
- const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
- const char *uName = QMetaType::typeName(qMetaTypeId<U>()); \
+ const char *tName = QMetaType::fromType<T>().name(); \
+ const char *uName = QMetaType::fromType<U>().name(); \
Q_ASSERT(tName); \
Q_ASSERT(uName); \
- const int tNameLen = int(qstrlen(tName)); \
- const int uNameLen = int(qstrlen(uName)); \
+ const size_t tNameLen = qstrlen(tName); \
+ const size_t uNameLen = qstrlen(uName); \
QByteArray typeName; \
- typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
+ typeName.reserve(sizeof(#DOUBLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \
.append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \
typeName.append('>'); \
- const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(\
- typeName, \
- reinterpret_cast< DOUBLE_ARG_TEMPLATE<T, U> *>(quintptr(-1))); \
+ const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName); \
metatype_id.storeRelease(newId); \
return newId; \
} \
@@ -2114,34 +1656,29 @@ struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
}; \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
const char * const cName = T::staticMetaObject.className(); \
QByteArray typeName; \
- typeName.reserve(int(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1)); \
+ typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1); \
typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \
.append('<').append(cName).append('>'); \
- const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >( \
- typeName, \
- reinterpret_cast< SMART_POINTER<T> *>(quintptr(-1))); \
+ const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName); \
metatype_id.storeRelease(newId); \
return newId; \
} \
}; \
template<typename T> \
struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \
- typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> \
+ typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value && !std::is_const_v<T>>::type> \
{ \
- static bool registerConverter(int id) \
+ static bool registerConverter() \
{ \
- const int toId = QMetaType::QObjectStar; \
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { \
+ const QMetaType to = QMetaType(QMetaType::QObjectStar); \
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) { \
QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \
- static const QtPrivate::ConverterFunctor<SMART_POINTER<T>, \
- QObject*, \
- QSmartPointerConvertFunctor<SMART_POINTER<T> > > f(o); \
- return QMetaType::registerConverterFunction(&f, id, toId); \
+ return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o); \
} \
return true; \
} \
@@ -2155,11 +1692,20 @@ struct QMetaTypeId< SMART_POINTER<T> > \
};\
QT_END_NAMESPACE
-#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE) \
QT_BEGIN_NAMESPACE \
- template <class T> class TEMPLATENAME; \
+ namespace QtPrivate { \
+ template<typename T> \
+ struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
+ { \
+ enum { Value = true }; \
+ }; \
+ } \
QT_END_NAMESPACE \
- Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME)
+ Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE)
+
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
+ Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(TEMPLATENAME)
QT_END_NAMESPACE
@@ -2167,20 +1713,9 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
-#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
-
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
-#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
- QT_BEGIN_NAMESPACE \
- template <class T1, class T2> CPPTYPE TEMPLATENAME; \
- QT_END_NAMESPACE \
-
-QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
-
-#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
-
#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
QT_BEGIN_NAMESPACE \
namespace QtPrivate { \
@@ -2202,7 +1737,6 @@ Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
-
QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER)
QT_BEGIN_NAMESPACE
@@ -2211,95 +1745,108 @@ QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-
QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
QT_BEGIN_NAMESPACE
template <typename T>
-inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
+inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter()
{
- const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QPairVariantInterfaceImpl,
- QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
+ return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
}
return true;
}
namespace QtPrivate {
- template<typename T>
- struct ValueTypeIsMetaType<T, true>
+
+template<typename From>
+struct QSequentialIterableConvertFunctor
+{
+ QIterable<QMetaSequence> operator()(const From &f) const
{
- static bool registerConverter(int id)
- {
- const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QSequentialIterableImpl,
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
- }
- return true;
- }
- };
+ return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
+ }
+};
- template<typename T>
- struct AssociativeValueTypeIsMetaType<T, true>
+template<typename From>
+struct QSequentialIterableMutableViewFunctor
+{
+ QIterable<QMetaSequence> operator()(From &f) const
{
- static bool registerConverter(int id)
- {
- const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QAssociativeIterableImpl,
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
- }
- return true;
+ return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
+ }
+};
+
+template<typename T>
+struct SequentialValueTypeIsMetaType<T, true>
+{
+ static bool registerConverter()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ QSequentialIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
}
- };
-}
+ return true;
+ }
-namespace QtPrivate {
+ static bool registerMutableView()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
+ if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
+ QSequentialIterableMutableViewFunctor<T> o;
+ return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
+ }
+ return true;
+ }
+};
-class QMetaTypeInterface
+template<typename From>
+struct QAssociativeIterableConvertFunctor
{
-public:
- uint revision; // 0 in Qt 6.0. Can increase if new field are added
- uint size;
- uint alignment;
- uint flags;
- const QMetaObject *metaObject;
- const char *name;
-
- QBasicAtomicInt typeId;
- QtPrivate::RefCount ref;
+ QIterable<QMetaAssociation> operator()(const From &f) const
+ {
+ return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
+ }
+};
- // Called when the type is unregistered, to delete this
- using DeleteSelf = void (*)(QMetaTypeInterface *);
- DeleteSelf deleteSelf;
+template<typename From>
+struct QAssociativeIterableMutableViewFunctor
+{
+ QIterable<QMetaAssociation> operator()(From &f) const
+ {
+ return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
+ }
+};
- using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
- DefaultCtrFn defaultCtr;
- using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
- CopyCtrFn copyCtr;
- using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
- MoveCtrFn moveCtr;
- using DtorFn = void (*)(const QMetaTypeInterface *, void *);
- DtorFn dtor;
+// Mapped type can be omitted, for example in case of a set.
+// However, if it is available, we want to instantiate the metatype here.
+template<typename T>
+struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T>
+{
+ static bool registerConverter()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ QAssociativeIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
+ }
+ return true;
+ }
- using LegacyRegisterOp = void (*)();
- LegacyRegisterOp legacyRegisterOp;
+ static bool registerMutableView()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
+ if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
+ QAssociativeIterableMutableViewFunctor<T> o;
+ return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
+ }
+ return true;
+ }
};
struct QTypeNormalizer
@@ -2315,7 +1862,7 @@ private:
|| s == '_');
}
static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); }
- static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; };
+ static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; }
static constexpr bool starts_with_token(const char *b, const char *e, const char *token,
bool msvcKw = false)
{
@@ -2328,7 +1875,7 @@ private:
#ifdef Q_CC_MSVC
/// On MSVC, keywords like class or struct are not separated with spaces in constexpr
/// context
- if (msvcKw)
+ if (msvcKw && !is_ident_char(*b))
return true;
#endif
Q_UNUSED(msvcKw);
@@ -2360,7 +1907,7 @@ private:
if (x != e)
x++;
return x;
- };
+ }
static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
{
int scopeDepth = 0;
@@ -2401,7 +1948,7 @@ private:
x++;
}
return x;
- };
+ }
constexpr void append(char x)
{
@@ -2411,13 +1958,156 @@ private:
*output++ = x;
}
+ constexpr void replaceLast(char x)
+ {
+ last = x;
+ if (output)
+ *(output - 1) = x;
+ }
+
constexpr void appendStr(const char *x)
{
while (*x)
append(*x++);
- };
+ }
+
+ constexpr void normalizeIntegerTypes(const char *&begin, const char *end)
+ {
+ int numLong = 0;
+ int numSigned = 0;
+ int numUnsigned = 0;
+ int numInt = 0;
+ int numShort = 0;
+ int numChar = 0;
+ while (begin < end) {
+ if (skipToken(begin, end, "long")) {
+ numLong++;
+ continue;
+ }
+ if (skipToken(begin, end, "int")) {
+ numInt++;
+ continue;
+ }
+ if (skipToken(begin, end, "short")) {
+ numShort++;
+ continue;
+ }
+ if (skipToken(begin, end, "unsigned")) {
+ numUnsigned++;
+ continue;
+ }
+ if (skipToken(begin, end, "signed")) {
+ numSigned++;
+ continue;
+ }
+ if (skipToken(begin, end, "char")) {
+ numChar++;
+ continue;
+ }
+#ifdef Q_CC_MSVC
+ if (skipToken(begin, end, "__int64")) {
+ numLong = 2;
+ continue;
+ }
+#endif
+ break;
+ }
+ if (numLong == 2)
+ append('q'); // q(u)longlong
+ if (numSigned && numChar)
+ appendStr("signed ");
+ else if (numUnsigned)
+ appendStr("u");
+ if (numChar)
+ appendStr("char");
+ else if (numShort)
+ appendStr("short");
+ else if (numLong == 1)
+ appendStr("long");
+ else if (numLong == 2)
+ appendStr("longlong");
+ else if (numUnsigned || numSigned || numInt)
+ appendStr("int");
+ }
+
+ constexpr void skipStructClassOrEnum(const char *&begin, const char *end)
+ {
+ // discard 'struct', 'class', and 'enum'; they are optional
+ // and we don't want them in the normalized signature
+ skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
+ || skipToken(begin, end, "enum", true);
+ }
+
+ constexpr void skipQtNamespace(const char *&begin, const char *end)
+ {
+#ifdef QT_NAMESPACE
+ const char *nsbeg = begin;
+ if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
+ && nsbeg[1] == ':') {
+ begin = nsbeg + 2;
+ while (begin != end && is_space(*begin))
+ begin++;
+ }
+#else
+ Q_UNUSED(begin);
+ Q_UNUSED(end);
+#endif
+ }
public:
+#if defined(Q_CC_CLANG) || defined (Q_CC_GNU)
+ // this is much simpler than the full type normalization below
+ // the reason is that the signature returned by Q_FUNC_INFO is already
+ // normalized to the largest degree, and we need to do only small adjustments
+ constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
+ {
+ // bail out if there is an anonymous struct
+ std::string_view name(begin, end-begin);
+#if defined (Q_CC_CLANG)
+ if (name.find("anonymous ") != std::string_view::npos)
+ return normalizeType(begin, end);
+#endif
+ if (name.find("unnamed ") != std::string_view::npos)
+ return normalizeType(begin, end);
+ while (begin < end) {
+ if (*begin == ' ') {
+ if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
+ ++begin;
+ continue;
+ }
+ }
+ if (last == ' ') {
+ if (*begin == '*' || *begin == '&' || *begin == '(') {
+ replaceLast(*begin);
+ ++begin;
+ continue;
+ }
+ }
+ if (!is_ident_char(last)) {
+ skipStructClassOrEnum(begin, end);
+ if (begin == end)
+ break;
+
+ skipQtNamespace(begin, end);
+ if (begin == end)
+ break;
+
+ normalizeIntegerTypes(begin, end);
+ if (begin == end)
+ break;
+ }
+ append(*begin);
+ ++begin;
+ }
+ return len;
+ }
+#else
+ // MSVC needs the full normalization, as it puts the const in a different
+ // place than we expect
+ constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
+ { return normalizeType(begin, end); }
+#endif
+
constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
{
// Trim spaces
@@ -2500,20 +2190,8 @@ public:
}
}
- // discard 'struct', 'class', and 'enum'; they are optional
- // and we don't want them in the normalized signature
- skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
- || skipToken(begin, end, "enum", true);
-
-#ifdef QT_NAMESPACE
- const char *nsbeg = begin;
- if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
- && nsbeg[1] == ':') {
- begin = nsbeg + 2;
- while (begin != end && is_space(*begin))
- begin++;
- }
-#endif
+ skipStructClassOrEnum(begin, end);
+ skipQtNamespace(begin, end);
if (skipToken(begin, end, "QVector")) {
// Replace QVector by QList
@@ -2522,73 +2200,12 @@ public:
if (skipToken(begin, end, "QPair")) {
// replace QPair by std::pair
-#ifdef _LIBCPP_VERSION
- appendStr("std::" QT_STRINGIFY(_LIBCPP_ABI_NAMESPACE) "::pair");
-#else
appendStr("std::pair");
-#endif
}
- if (!hasMiddleConst) {
+ if (!hasMiddleConst)
// Normalize the integer types
- int numLong = 0;
- int numSigned = 0;
- int numUnsigned = 0;
- int numInt = 0;
- int numShort = 0;
- int numChar = 0;
- while (begin < end) {
- if (skipToken(begin, end, "long")) {
- numLong++;
- continue;
- }
- if (skipToken(begin, end, "int")) {
- numInt++;
- continue;
- }
- if (skipToken(begin, end, "short")) {
- numShort++;
- continue;
- }
- if (skipToken(begin, end, "unsigned")) {
- numUnsigned++;
- continue;
- }
- if (skipToken(begin, end, "signed")) {
- numSigned++;
- continue;
- }
- if (skipToken(begin, end, "char")) {
- numChar++;
- continue;
- }
- break;
- }
- if (numChar || numShort) {
- if (numSigned && numChar)
- appendStr("signed ");
- if (numUnsigned)
- appendStr("unsigned ");
- if (numChar)
- appendStr("char");
- else
- appendStr("short");
- } else if (numLong) {
- if (numLong == 1) {
- if (numUnsigned)
- append('u');
- appendStr("long");
- } else {
- if (numUnsigned)
- appendStr("unsigned ");
- appendStr("long long");
- }
- } else if (numUnsigned || numSigned || numInt) {
- if (numUnsigned)
- append('u');
- appendStr("int");
- }
- }
+ normalizeIntegerTypes(begin, end);
bool spaceSkiped = true;
while (begin != end) {
@@ -2631,43 +2248,92 @@ constexpr int qNormalizeType(const char *begin, const char *end, char *output)
}
template<typename T>
+struct is_std_pair : std::false_type {};
+
+template <typename T1_, typename T2_>
+struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
+ using T1 = T1_;
+ using T2 = T2_;
+};
+
+namespace TypeNameHelper {
+template<typename T>
constexpr auto typenameHelper()
{
- constexpr auto prefix = sizeof(
+ if constexpr (is_std_pair<T>::value) {
+ using T1 = typename is_std_pair<T>::T1;
+ using T2 = typename is_std_pair<T>::T2;
+ std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {};
+ std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {};
+ if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) {
+ t1Name = QMetaTypeId2<T1>::nameAsArray;
+ } else {
+ t1Name = typenameHelper<T1>();
+ }
+ if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) {
+ t2Name = QMetaTypeId2<T2>::nameAsArray;
+ } else {
+ t2Name = typenameHelper<T2>();
+ }
+ constexpr auto nonTypeDependentLen = sizeof("std::pair<,>");
+ constexpr auto t1Len = t1Name.size() - 1;
+ constexpr auto t2Len = t2Name.size() - 1;
+ constexpr auto length = nonTypeDependentLen + t1Len + t2Len;
+ std::array<char, length + 1> result {};
+ constexpr auto prefix = "std::pair<";
+ int currentLength = 0;
+ for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength)
+ result[currentLength] = prefix[currentLength];
+ for (int i = 0; i < int(t1Len); ++currentLength, ++i)
+ result[currentLength] = t1Name[i];
+ result[currentLength++] = ',';
+ for (int i = 0; i < int(t2Len); ++currentLength, ++i)
+ result[currentLength] = t2Name[i];
+ result[currentLength++] = '>';
+ result[currentLength++] = '\0';
+ return result;
+ } else {
+ constexpr auto prefix = sizeof(
#ifdef QT_NAMESPACE
- QT_STRINGIFY(QT_NAMESPACE) "::"
+ QT_STRINGIFY(QT_NAMESPACE) "::"
#endif
-#ifdef Q_CC_MSVC
- "auto __cdecl QtPrivate::typenameHelper<"
+#if defined(Q_CC_MSVC) && defined(Q_CC_CLANG)
+ "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper(void) [T = "
+#elif defined(Q_CC_MSVC)
+ "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper<"
#elif defined(Q_CC_CLANG)
- "auto QtPrivate::typenameHelper() [T = "
+ "auto QtPrivate::TypeNameHelper::typenameHelper() [T = "
+#elif defined(Q_CC_GHS)
+ "auto QtPrivate::TypeNameHelper::typenameHelper<T>()[with T="
#else
- "constexpr auto QtPrivate::typenameHelper() [with T = "
+ "constexpr auto QtPrivate::TypeNameHelper::typenameHelper() [with T = "
#endif
- ) - 1;
-#ifdef Q_CC_MSVC
- constexpr int suffix = sizeof(">(void)");
+ ) - 1;
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+ constexpr int suffix = sizeof(">(void)");
#else
- constexpr int suffix = sizeof("]");
+ constexpr int suffix = sizeof("]");
#endif
-#if !(defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG))
- constexpr auto func = Q_FUNC_INFO;
- constexpr const char *begin = func + prefix;
- constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
- constexpr int len = qNormalizeType(begin, end, nullptr);
-#else // GCC < 8.1 did not have Q_FUNC_INFO as constexpr, and GCC 9 has a precompiled header bug
- auto func = Q_FUNC_INFO;
- const char *begin = func + prefix;
- const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
- // This is an upper bound of the size since the normalized signature should always be smaller
- // (Unless there is a QList -> QVector change, but that should not happen)
- constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
+#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU_ONLY < 804
+ auto func = Q_FUNC_INFO;
+ const char *begin = func + prefix;
+ const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
+ // This is an upper bound of the size since the normalized signature should always be smaller
+ constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
+#else
+ constexpr auto func = Q_FUNC_INFO;
+ constexpr const char *begin = func + prefix;
+ constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
+ constexpr int len = QTypeNormalizer{ nullptr }.normalizeTypeFromSignature(begin, end);
#endif
- std::array<char, len + 1> result {};
- qNormalizeType(begin, end, result.data());
- return result;
+ std::array<char, len + 1> result {};
+ QTypeNormalizer{ result.data() }.normalizeTypeFromSignature(begin, end);
+ return result;
+ }
}
+} // namespace TypeNameHelper
+using TypeNameHelper::typenameHelper;
template<typename T, typename = void>
struct BuiltinMetaType : std::integral_constant<int, 0>
@@ -2679,164 +2345,237 @@ struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
{
};
+template<typename T, bool = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>)>
+struct QEqualityOperatorForType
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_FLOAT_COMPARE
+ static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
+ { return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
+QT_WARNING_POP
+};
+
+template<typename T>
+struct QEqualityOperatorForType <T, false>
+{
+ static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
+};
+
+template<typename T, bool = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>)>
+struct QLessThanOperatorForType
+{
+ static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
+ { return *reinterpret_cast<const T *>(a) < *reinterpret_cast<const T *>(b); }
+};
+
+template<typename T>
+struct QLessThanOperatorForType <T, false>
+{
+ static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
+};
+
+template<typename T, bool = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>)>
+struct QDebugStreamOperatorForType
+{
+ static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
+ { dbg << *reinterpret_cast<const T *>(a); }
+};
+
+template<typename T>
+struct QDebugStreamOperatorForType <T, false>
+{
+ static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
+};
+
+template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
+struct QDataStreamOperatorForType
+{
+ static constexpr QMetaTypeInterface::DataStreamOutFn dataStreamOut = nullptr;
+ static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr;
+};
+
+#ifndef QT_NO_DATASTREAM
+template<typename T>
+struct QDataStreamOperatorForType <T, true>
+{
+ static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
+ { ds << *reinterpret_cast<const T *>(a); }
+ static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
+ { ds >> *reinterpret_cast<T *>(a); }
+};
+#endif
+
+// Performance optimization:
+//
+// Don't add all these symbols to the dynamic symbol tables on ELF systems and
+// on Darwin. Each library is going to have a copy anyway and QMetaType already
+// copes with some of these being "hidden" (see QMetaType::idHelper()). We may
+// as well let the linker know it can always use the local copy.
+//
+// This is currently not enabled for GCC due to
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106023
+
+#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
+# pragma GCC visibility push(hidden)
+#endif
+
template<typename S>
class QMetaTypeForType
{
- static const decltype(typenameHelper<S>()) name;
+public:
+ static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
+ static constexpr unsigned Flags = QMetaTypeTypeFlags<S>::Flags;
- template<typename T>
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
{
- if constexpr (std::is_default_constructible_v<T>) {
- return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); };
- } else {
- return nullptr;
- }
+ if constexpr (std::is_default_constructible_v<S> && !QTypeInfo<S>::isValueInitializationBitwiseZero) {
+ return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
+ } else {
+ return nullptr;
+ }
}
- template<typename T>
static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
{
- if constexpr (std::is_copy_constructible_v<T>) {
- return [](const QMetaTypeInterface *, void *addr, const void *other) {
- new (addr) T(*reinterpret_cast<const T *>(other));
- };
- } else {
- return nullptr;
- }
+ if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
+ return [](const QMetaTypeInterface *, void *addr, const void *other) {
+ new (addr) S(*reinterpret_cast<const S *>(other));
+ };
+ } else {
+ return nullptr;
+ }
}
- template<typename T>
static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
{
- if constexpr (std::is_move_constructible_v<T>) {
- return [](const QMetaTypeInterface *, void *addr, void *other) {
- new (addr) T(std::move(*reinterpret_cast<T *>(other)));
- };
- } else {
- return nullptr;
- }
+ if constexpr (std::is_move_constructible_v<S> && !std::is_trivially_move_constructible_v<S>) {
+ return [](const QMetaTypeInterface *, void *addr, void *other) {
+ new (addr) S(std::move(*reinterpret_cast<S *>(other)));
+ };
+ } else {
+ return nullptr;
+ }
}
- template<typename T>
static constexpr QMetaTypeInterface::DtorFn getDtor()
{
- if constexpr (std::is_destructible_v<T>)
- return [](const QMetaTypeInterface *, void *addr) { reinterpret_cast<T *>(addr)->~T(); };
- else
- return nullptr;
+ if constexpr (std::is_destructible_v<S> && !std::is_trivially_destructible_v<S>)
+ return [](const QMetaTypeInterface *, void *addr) {
+ reinterpret_cast<S *>(addr)->~S();
+ };
+ else
+ return nullptr;
}
- template<typename T>
static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister()
{
- if constexpr (QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn) {
- return []() { QMetaTypeId2<T>::qt_metatype_id(); };
- } else {
- return nullptr;
- }
+ if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
+ return []() { QMetaTypeId2<S>::qt_metatype_id(); };
+ } else {
+ return nullptr;
+ }
}
static constexpr const char *getName()
{
if constexpr (bool(QMetaTypeId2<S>::IsBuiltIn)) {
- return QMetaTypeId2<S>::name;
+ return QMetaTypeId2<S>::nameAsArray.data();
} else {
return name.data();
}
}
-
-public:
- static QMetaTypeInterface metaType;
};
template<typename T>
-QMetaTypeInterface QMetaTypeForType<T>::metaType = {
- /*.revision=*/ 0,
- /*.size=*/ sizeof(T),
- /*.alignment=*/ alignof(T),
- /*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
- /*.metaObject=*/ MetaObjectForType<T>::value(),
- /*.name=*/ getName(),
- /*.typeId=*/ BuiltinMetaType<T>::value,
- /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
- /*.deleteSelf=*/ nullptr,
- /*.defaultCtr=*/ getDefaultCtr<T>(),
- /*.copyCtr=*/ getCopyCtr<T>(),
- /*.moveCtr=*/ getMoveCtr<T>(),
- /*.dtor=*/ getDtor<T>(),
- /*.legacyRegisterOp=*/ getLegacyRegister<T>()
+struct QMetaTypeInterfaceWrapper
+{
+ // if the type ID for T is known at compile-time, then we can declare
+ // the QMetaTypeInterface object const; otherwise, we declare it as
+ // non-const and the .typeId is updated by QMetaType::idHelper().
+ static constexpr bool IsConstMetaTypeInterface = !!BuiltinMetaType<T>::value;
+ using InterfaceType = std::conditional_t<IsConstMetaTypeInterface, const QMetaTypeInterface, NonConstMetaTypeInterface>;
+
+ static inline InterfaceType metaType = {
+ /*.revision=*/ QMetaTypeInterface::CurrentRevision,
+ /*.alignment=*/ alignof(T),
+ /*.size=*/ sizeof(T),
+ /*.flags=*/ QMetaTypeForType<T>::Flags,
+ /*.typeId=*/ BuiltinMetaType<T>::value,
+ /*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
+ /*.name=*/ QMetaTypeForType<T>::getName(),
+ /*.defaultCtr=*/ QMetaTypeForType<T>::getDefaultCtr(),
+ /*.copyCtr=*/ QMetaTypeForType<T>::getCopyCtr(),
+ /*.moveCtr=*/ QMetaTypeForType<T>::getMoveCtr(),
+ /*.dtor=*/ QMetaTypeForType<T>::getDtor(),
+ /*.equals=*/ QEqualityOperatorForType<T>::equals,
+ /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
+ /*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
+ /*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
+ /*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
+ /*.legacyRegisterOp=*/ QMetaTypeForType<T>::getLegacyRegister()
+ };
};
-template<typename T>
-constexpr const decltype(typenameHelper<T>()) QMetaTypeForType<T>::name = typenameHelper<T>();
+#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
+# pragma GCC visibility pop
+#endif
template<>
-class QMetaTypeForType<void>
+class QMetaTypeInterfaceWrapper<void>
{
- static const decltype(typenameHelper<void>()) name;
-
public:
- static inline QMetaTypeInterface metaType =
+ static constexpr QMetaTypeInterface metaType =
{
/*.revision=*/ 0,
- /*.size=*/ 0,
/*.alignment=*/ 0,
+ /*.size=*/ 0,
/*.flags=*/ 0,
- /*.metaObject=*/ nullptr,
- /*.name=*/ "void",
/*.typeId=*/ BuiltinMetaType<void>::value,
- /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
- /*.deleteSelf=*/ nullptr,
+ /*.metaObjectFn=*/ nullptr,
+ /*.name=*/ "void",
/*.defaultCtr=*/ nullptr,
/*.copyCtr=*/ nullptr,
/*.moveCtr=*/ nullptr,
/*.dtor=*/ nullptr,
+ /*.equals=*/ nullptr,
+ /*.lessThan=*/ nullptr,
+ /*.debugStream=*/ nullptr,
+ /*.dataStreamOut=*/ nullptr,
+ /*.dataStreamIn=*/ nullptr,
/*.legacyRegisterOp=*/ nullptr
};
};
-#undef QT_METATYPE_CONSTEXPRLAMDA
-#ifndef QT_BOOTSTRAPPED
-#define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
+/*
+ MSVC instantiates extern templates
+(https://developercommunity.visualstudio.com/t/c11-extern-templates-doesnt-work-for-class-templat/157868)
+
+ The INTEGRITY compiler apparently does too.
+
+ On Windows (with other compilers or whenever MSVC is fixed), we can't declare
+ QMetaTypeInterfaceWrapper with __declspec(dllimport) because taking its
+ address is not a core constant expression.
+ */
+#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
+
+#ifdef QT_NO_DATA_RELOCATION
+# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4910) // '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_GCC("-Wattributes") // false positive because of QMetaTypeForType<void>
-QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
-QT_WARNING_POP
+#else
+# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
+ extern template class Q_CORE_EXPORT QMetaTypeForType<Name>; \
+ extern template struct Q_CORE_EXPORT QMetaTypeInterfaceWrapper<Name>;
+#endif
+
+QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
-QT_WARNING_POP
#undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER
#endif
template<typename T>
-constexpr QMetaTypeInterface *qMetaTypeInterfaceForType()
-{
- using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
- return &QMetaTypeForType<Ty>::metaType;
-}
-
-namespace detail {
-
-template <typename T, typename ODR_VIOLATION_PREVENTER>
-struct is_complete_helper {
- template <typename U>
- static auto check(U*) -> std::integral_constant<bool, sizeof(U) != 0>;
- static auto check(...) -> std::false_type;
- using type = decltype(check(static_cast<T*>(nullptr)));
-};
-
-}
-
-template <typename T, typename ODR_VIOLATION_PREVENTER>
-struct is_complete : detail::is_complete_helper<T, ODR_VIOLATION_PREVENTER>::type {};
-
-template<typename T>
struct qRemovePointerLike
{
using type = std::remove_pointer_t<T>;
@@ -2854,36 +2593,106 @@ template<typename T>
using qRemovePointerLike_t = typename qRemovePointerLike<T>::type;
#undef Q_REMOVE_POINTER_LIKE_IMPL
-template<typename Unique, typename T>
-constexpr QMetaTypeInterface *qTryMetaTypeInterfaceForType()
+template<typename T, typename ForceComplete_>
+struct TypeAndForceComplete
{
- using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
+ using type = T;
+ using ForceComplete = ForceComplete_;
+};
+
+template<typename T>
+constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType()
+{
+ // don't check the type is suitable here
+ using Ty = typename MetatypeDecay<T>::type;
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
+}
+
+template<typename Unique, typename TypeCompletePair>
+constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType()
+{
+ using T = typename TypeCompletePair::type;
+ using ForceComplete = typename TypeCompletePair::ForceComplete;
+ using Ty = typename MetatypeDecay<T>::type;
using Tz = qRemovePointerLike_t<Ty>;
- if constexpr (!is_complete<Tz, Unique>::value) {
+
+ if constexpr (std::is_void_v<Tz>) {
+ // early out to avoid expanding the rest of the templates
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
+ } else if constexpr (ForceComplete::value) {
+ checkTypeIsSuitableForMetaType<Ty>();
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
+ } else if constexpr (std::is_reference_v<Tz>) {
+ return nullptr;
+ } else if constexpr (!is_complete<Tz, Unique>::value) {
return nullptr;
} else {
- return &QMetaTypeForType<Ty>::metaType;
+ // don't check the type is suitable here
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
}
}
} // namespace QtPrivate
template<typename T>
-QMetaType QMetaType::fromType()
+constexpr QMetaType QMetaType::fromType()
{
+ QtPrivate::checkTypeIsSuitableForMetaType<T>();
return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
}
+constexpr qsizetype QMetaType::sizeOf() const
+{
+ return d_ptr ? d_ptr->size : 0;
+}
+
+constexpr qsizetype QMetaType::alignOf() const
+{
+ return d_ptr ? d_ptr->alignment : 0;
+}
+
+constexpr QMetaType::TypeFlags QMetaType::flags() const
+{
+ return d_ptr ? TypeFlags(d_ptr->flags) : TypeFlags{};
+}
+
+constexpr const QMetaObject *QMetaType::metaObject() const
+{
+ return d_ptr && d_ptr->metaObjectFn ? d_ptr->metaObjectFn(d_ptr) : nullptr;
+}
+
template<typename... T>
-QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
- QtPrivate::qMetaTypeInterfaceForType<T>()...
+constexpr const QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
+ /*
+ Unique in qTryMetaTypeInterfaceForType does not have to be unique here
+ as we require _all_ types here to be actually complete.
+ We just want to have the additional type processing that exist in
+ QtPrivate::qTryMetaTypeInterfaceForType as opposed to the normal
+ QtPrivate::qMetaTypeInterfaceForType used in QMetaType::fromType
+ */
+ QtPrivate::qTryMetaTypeInterfaceForType<void, QtPrivate::TypeAndForceComplete<T, std::true_type>>()...
};
+constexpr const char *QMetaType::name() const
+{
+ return d_ptr ? d_ptr->name : nullptr;
+}
+
template<typename Unique,typename... T>
-QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
+constexpr const QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
QtPrivate::qTryMetaTypeInterfaceForType<Unique, T>()...
};
+inline size_t qHash(QMetaType type, size_t seed = 0)
+{
+ // We cannot use d_ptr here since the same type in different DLLs
+ // might result in different pointers!
+ return qHash(type.id(), seed);
+}
+
QT_END_NAMESPACE
+QT_DECL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl,
+ QPairVariantInterfaceImpl, Q_CORE_EXPORT)
+
#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index d8dba13770..7e0457771f 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMETATYPE_P_H
#define QMETATYPE_P_H
@@ -56,84 +20,48 @@
QT_BEGIN_NAMESPACE
-namespace QModulesPrivate {
-enum Names { Core, Gui, Widgets, Unknown, ModulesCount /* ModulesCount has to be at the end */ };
-
-static inline int moduleForType(const uint typeId)
-{
- if (typeId <= QMetaType::LastCoreType)
- return Core;
- if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType)
- return Gui;
- if (typeId >= QMetaType::FirstWidgetsType && typeId <= QMetaType::LastWidgetsType)
- return Widgets;
- return Unknown;
-}
-
-template <typename T>
-class QTypeModuleInfo
+#define QMETATYPE_CONVERTER(To, From, assign_and_return) \
+ case makePair(QMetaType::To, QMetaType::From): \
+ if (onlyCheck) \
+ return true; \
+ { \
+ const From &source = *static_cast<const From *>(from); \
+ To &result = *static_cast<To *>(to); \
+ assign_and_return \
+ }
+#define QMETATYPE_CONVERTER_ASSIGN(To, From) \
+ QMETATYPE_CONVERTER(To, From, result = To(source); return true;)
+
+#define QMETATYPE_CONVERTER_FUNCTION(To, assign_and_return) \
+ { \
+ To &result = *static_cast<To *>(r); \
+ assign_and_return \
+ }
+
+class Q_CORE_EXPORT QMetaTypeModuleHelper
{
+ Q_DISABLE_COPY_MOVE(QMetaTypeModuleHelper)
+protected:
+ QMetaTypeModuleHelper() = default;
+ ~QMetaTypeModuleHelper() = default;
public:
- enum Module : bool {
- IsCore = false,
- IsWidget = false,
- IsGui = false,
- IsUnknown = true
- };
-};
+ Q_WEAK_OVERLOAD // prevent it from entering the ABI and rendering constexpr useless
+ static constexpr auto makePair(int from, int to) -> quint64
+ {
+ return (quint64(from) << 32) + quint64(to);
+ }
-#define QT_ASSIGN_TYPE_TO_MODULE(TYPE, MODULE) \
-template<> \
-class QTypeModuleInfo<TYPE > \
-{ \
-public: \
- enum Module : bool { \
- IsCore = (((MODULE) == (QModulesPrivate::Core))), \
- IsWidget = (((MODULE) == (QModulesPrivate::Widgets))), \
- IsGui = (((MODULE) == (QModulesPrivate::Gui))), \
- IsUnknown = !(IsCore || IsWidget || IsGui) \
- }; \
- static inline int module() { return MODULE; } \
- static_assert((IsUnknown && !(IsCore || IsWidget || IsGui)) \
- || (IsCore && !(IsUnknown || IsWidget || IsGui)) \
- || (IsWidget && !(IsUnknown || IsCore || IsGui)) \
- || (IsGui && !(IsUnknown || IsCore || IsWidget))); \
+ virtual const QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
+ virtual bool convert(const void *, int, void *, int) const;
};
-
-#define QT_DECLARE_CORE_MODULE_TYPES_ITER(TypeName, TypeId, Name) \
- QT_ASSIGN_TYPE_TO_MODULE(Name, QModulesPrivate::Core);
-#define QT_DECLARE_GUI_MODULE_TYPES_ITER(TypeName, TypeId, Name) \
- QT_ASSIGN_TYPE_TO_MODULE(Name, QModulesPrivate::Gui);
-#define QT_DECLARE_WIDGETS_MODULE_TYPES_ITER(TypeName, TypeId, Name) \
- QT_ASSIGN_TYPE_TO_MODULE(Name, QModulesPrivate::Widgets);
-
-QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_DECLARE_CORE_MODULE_TYPES_ITER)
-QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_DECLARE_CORE_MODULE_TYPES_ITER)
-QT_FOR_EACH_STATIC_CORE_CLASS(QT_DECLARE_CORE_MODULE_TYPES_ITER)
-QT_FOR_EACH_STATIC_CORE_POINTER(QT_DECLARE_CORE_MODULE_TYPES_ITER)
-QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_DECLARE_CORE_MODULE_TYPES_ITER)
-QT_FOR_EACH_STATIC_GUI_CLASS(QT_DECLARE_GUI_MODULE_TYPES_ITER)
-QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_DECLARE_WIDGETS_MODULE_TYPES_ITER)
-} // namespace QModulesPrivate
-
-#undef QT_DECLARE_CORE_MODULE_TYPES_ITER
-#undef QT_DECLARE_GUI_MODULE_TYPES_ITER
-#undef QT_DECLARE_WIDGETS_MODULE_TYPES_ITER
-
-class QMetaTypeModuleHelper
-{
-public:
- virtual QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
-#ifndef QT_NO_DATASTREAM
- virtual bool save(QDataStream &stream, int type, const void *data) const = 0;
- virtual bool load(QDataStream &stream, int type, void *data) const = 0;
-#endif
-};
+extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper;
+extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper;
namespace QtMetaTypePrivate {
template<typename T>
-struct TypeDefinition {
+struct TypeDefinition
+{
static const bool IsAvailable = true;
};
@@ -189,11 +117,99 @@ template<> struct TypeDefinition<QQuaternion> { static const bool IsAvailable =
template<> struct TypeDefinition<QIcon> { static const bool IsAvailable = false; };
#endif
+template <typename T> inline bool isInterfaceFor(const QtPrivate::QMetaTypeInterface *iface)
+{
+ // typeId for built-in types are fixed and require no registration
+ static_assert(QMetaTypeId2<T>::IsBuiltIn, "This function only works for built-in types");
+ static constexpr int typeId = QtPrivate::BuiltinMetaType<T>::value;
+ return iface->typeId.loadRelaxed() == typeId;
+}
+
+template <typename FPointer>
+inline bool checkMetaTypeFlagOrPointer(const QtPrivate::QMetaTypeInterface *iface, FPointer ptr, QMetaType::TypeFlag Flag)
+{
+ // helper to the isXxxConstructible & isDestructible functions below: a
+ // meta type has the trait if the trait is trivial or we have the pointer
+ // to perform the operation
+ Q_ASSERT(!isInterfaceFor<void>(iface));
+ Q_ASSERT(iface->size);
+ return ptr != nullptr || (iface->flags & Flag) == 0;
+}
+
+inline bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return checkMetaTypeFlagOrPointer(iface, iface->defaultCtr, QMetaType::NeedsConstruction);
+}
+
+inline bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return checkMetaTypeFlagOrPointer(iface, iface->copyCtr, QMetaType::NeedsCopyConstruction);
+}
+
+inline bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return checkMetaTypeFlagOrPointer(iface, iface->moveCtr, QMetaType::NeedsMoveConstruction);
+}
+
+inline bool isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ /* For metatypes of revision 1, the NeedsDestruction was set even for trivially
+ destructible types, but their dtor pointer would be null.
+ For that reason, we need the additional check here.
+ */
+ return iface->revision < 1 ||
+ checkMetaTypeFlagOrPointer(iface, iface->dtor, QMetaType::NeedsDestruction);
+}
+
+inline void defaultConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
+{
+ Q_ASSERT(isDefaultConstructible(iface));
+ if (iface->defaultCtr)
+ iface->defaultCtr(iface, where);
+ else
+ memset(where, 0, iface->size);
+}
+
+inline void copyConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
+{
+ Q_ASSERT(isCopyConstructible(iface));
+ if (iface->copyCtr)
+ iface->copyCtr(iface, where, copy);
+ else
+ memcpy(where, copy, iface->size);
+}
+
+inline void moveConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, void *copy)
+{
+ Q_ASSERT(isMoveConstructible(iface));
+ if (iface->moveCtr)
+ iface->moveCtr(iface, where, copy);
+ else
+ memcpy(where, copy, iface->size);
+}
+
+inline void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
+{
+ if (copy)
+ copyConstruct(iface, where, copy);
+ else
+ defaultConstruct(iface, where);
+}
+
+inline void destruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
+{
+ Q_ASSERT(isDestructible(iface));
+ if (iface->dtor)
+ iface->dtor(iface, where);
+}
+
+const char *typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d);
+
template<typename T>
-static QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType()
+static const QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType()
{
if constexpr (QtMetaTypePrivate::TypeDefinition<T>::IsAvailable) {
- return &QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeForType)<T>::metaType;
+ return &QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterfaceWrapper)<T>::metaType;
}
return nullptr;
}
@@ -202,18 +218,6 @@ static QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType
case QMetaType::MetaTypeName: \
return QtMetaTypePrivate::getInterfaceFromType<RealName>();
-#define QT_METATYPE_DATASTREAM_SAVE(MetaTypeName, MetaTypeId, RealName) \
- case QMetaType::MetaTypeName: \
- QtMetaTypePrivate::QMetaTypeFunctionHelper<RealName, QtMetaTypePrivate::TypeDefinition<RealName>::IsAvailable>::Save(stream, data); \
- return true;
-
-#define QT_METATYPE_DATASTREAM_LOAD(MetaTypeName, MetaTypeId, RealName) \
- case QMetaType::MetaTypeName: \
- QtMetaTypePrivate::QMetaTypeFunctionHelper<RealName, QtMetaTypePrivate::TypeDefinition<RealName>::IsAvailable>::Load(stream, data); \
- return true;
-
-void derefAndDestroy(QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *d_ptr);
-
} //namespace QtMetaTypePrivate
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatypeswitcher_p.h b/src/corelib/kernel/qmetatypeswitcher_p.h
deleted file mode 100644
index dabc70f4b0..0000000000
--- a/src/corelib/kernel/qmetatypeswitcher_p.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMETATYPESWITCHER_P_H
-#define QMETATYPESWITCHER_P_H
-
-#include "qmetatype.h"
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_BEGIN_NAMESPACE
-
-class QMetaTypeSwitcher {
-public:
- class NotBuiltinType; // type is not a built-in type, but it may be a custom type or an unknown type
- class UnknownType; // type not known to QMetaType system
- template<class ReturnType, class DelegateObject>
- static ReturnType switcher(DelegateObject &logic, int type, const void *data = nullptr);
-};
-
-
-#define QT_METATYPE_SWICHER_CASE(TypeName, TypeId, Name)\
- case QMetaType::TypeName: return logic.delegate(static_cast<Name const *>(data));
-
-template<class ReturnType, class DelegateObject>
-ReturnType QMetaTypeSwitcher::switcher(DelegateObject &logic, int type, const void *data)
-{
- switch (QMetaType::Type(type)) {
- QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_SWICHER_CASE)
-
- case QMetaType::UnknownType:
- return logic.delegate(static_cast<UnknownType const *>(data));
- default:
- if (type < QMetaType::User)
- return logic.delegate(static_cast<UnknownType const *>(data));
- return logic.delegate(static_cast<NotBuiltinType const *>(data));
- }
-}
-
-#undef QT_METATYPE_SWICHER_CASE
-
-QT_END_NAMESPACE
-
-#endif // QMETATYPESWITCHER_P_H
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
index 21a1350fc5..2c0a89dbd7 100644
--- a/src/corelib/kernel/qmimedata.cpp
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmimedata.h"
@@ -46,19 +10,21 @@
QT_BEGIN_NAMESPACE
-static inline QString textUriListLiteral() { return QStringLiteral("text/uri-list"); }
-static inline QString textHtmlLiteral() { return QStringLiteral("text/html"); }
-static inline QString textPlainLiteral() { return QStringLiteral("text/plain"); }
-static inline QString textPlainUtf8Literal() { return QStringLiteral("text/plain;charset=utf-8"); }
-static inline QString applicationXColorLiteral() { return QStringLiteral("application/x-color"); }
-static inline QString applicationXQtImageLiteral() { return QStringLiteral("application/x-qt-image"); }
+using namespace Qt::StringLiterals;
+
+static inline QString textUriListLiteral() { return u"text/uri-list"_s; }
+static inline QString textHtmlLiteral() { return u"text/html"_s; }
+static inline QString textPlainLiteral() { return u"text/plain"_s; }
+static inline QString textPlainUtf8Literal() { return u"text/plain;charset=utf-8"_s; }
+static inline QString applicationXColorLiteral() { return u"application/x-color"_s; }
+static inline QString applicationXQtImageLiteral() { return u"application/x-qt-image"_s; }
struct QMimeDataStruct
{
QString format;
QVariant data;
};
-Q_DECLARE_TYPEINFO(QMimeDataStruct, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMimeDataStruct, Q_RELOCATABLE_TYPE);
class QMimeDataPrivate : public QObjectPrivate
{
@@ -68,7 +34,7 @@ public:
void setData(const QString &format, const QVariant &data);
QVariant getData(const QString &format) const;
- QVariant retrieveTypedData(const QString &format, QMetaType::Type type) const;
+ QVariant retrieveTypedData(const QString &format, QMetaType type) const;
std::vector<QMimeDataStruct>::iterator find(const QString &format) noexcept {
const auto formatEquals = [](const QString &format) {
@@ -110,24 +76,48 @@ QVariant QMimeDataPrivate::getData(const QString &format) const
return it->data;
}
-QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType::Type type) const
+static QList<QVariant> dataToUrls(QByteArrayView text)
+{
+ QList<QVariant> list;
+ qsizetype newLineIndex = -1;
+ qsizetype from = 0;
+ const char *begin = text.data();
+ while ((newLineIndex = text.indexOf('\n', from)) != -1) {
+ const auto bav = QByteArrayView(begin + from, begin + newLineIndex).trimmed();
+ if (!bav.isEmpty())
+ list.push_back(QUrl::fromEncoded(bav));
+ from = newLineIndex + 1;
+ if (from >= text.size())
+ break;
+ }
+ if (from != text.size()) {
+ const auto bav = QByteArrayView(begin + from, text.end()).trimmed();
+ if (!bav.isEmpty())
+ list.push_back(QUrl::fromEncoded(bav));
+ }
+ return list;
+}
+
+QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType type) const
{
Q_Q(const QMimeData);
+ int typeId = type.id();
- QVariant data = q->retrieveData(format, QVariant::Type(type));
+ QVariant data = q->retrieveData(format, type);
// Text data requested: fallback to URL data if available
- if (format == QLatin1String("text/plain") && !data.isValid()) {
- data = retrieveTypedData(textUriListLiteral(), QMetaType::QVariantList);
- if (data.userType() == QMetaType::QUrl) {
+ if (format == "text/plain"_L1 && !data.isValid()) {
+ data = retrieveTypedData(textUriListLiteral(), QMetaType(QMetaType::QVariantList));
+ if (data.metaType().id() == QMetaType::QUrl) {
data = QVariant(data.toUrl().toDisplayString());
- } else if (data.userType() == QMetaType::QVariantList) {
+ } else if (data.metaType().id() == QMetaType::QVariantList) {
QString text;
int numUrls = 0;
const QList<QVariant> list = data.toList();
- for (int i = 0; i < list.size(); ++i) {
- if (list.at(i).userType() == QMetaType::QUrl) {
- text += list.at(i).toUrl().toDisplayString() + QLatin1Char('\n');
+ for (const auto &element : list) {
+ if (element.metaType().id() == QMetaType::QUrl) {
+ text += element.toUrl().toDisplayString();
+ text += u'\n';
++numUrls;
}
}
@@ -137,31 +127,32 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType::T
}
}
- if (data.userType() == type || !data.isValid())
+ if (data.metaType() == type || !data.isValid())
return data;
- // provide more conversion possiblities than just what QVariant provides
+ // provide more conversion possibilities than just what QVariant provides
// URLs can be lists as well...
- if ((type == QMetaType::QUrl && data.userType() == QMetaType::QVariantList)
- || (type == QMetaType::QVariantList && data.userType() == QMetaType::QUrl))
+ if ((typeId == QMetaType::QUrl && data.metaType().id() == QMetaType::QVariantList)
+ || (typeId == QMetaType::QVariantList && data.metaType().id() == QMetaType::QUrl))
return data;
// images and pixmaps are interchangeable
- if ((type == QMetaType::QPixmap && data.userType() == QMetaType::QImage)
- || (type == QMetaType::QImage && data.userType() == QMetaType::QPixmap))
+ if ((typeId == QMetaType::QPixmap && data.metaType().id() == QMetaType::QImage)
+ || (typeId == QMetaType::QImage && data.metaType().id() == QMetaType::QPixmap))
return data;
- if (data.userType() == QMetaType::QByteArray) {
+ if (data.metaType().id() == QMetaType::QByteArray) {
// see if we can convert to the requested type
- switch(type) {
+ switch (typeId) {
case QMetaType::QString: {
const QByteArray ba = data.toByteArray();
- if (format == QLatin1String("text/html")) {
- auto encoding = QStringConverter::encodingForHtml(ba.constData(), ba.size());
- if (encoding) {
- QStringDecoder toUtf16(*encoding);
- return QString(toUtf16(ba));
+ if (ba.isNull())
+ return QVariant();
+ if (format == "text/html"_L1) {
+ QStringDecoder decoder = QStringDecoder::decoderForHtml(ba);
+ if (decoder.isValid()) {
+ return QString(decoder(ba));
}
// fall back to utf8
}
@@ -169,39 +160,31 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType::T
}
case QMetaType::QColor: {
QVariant newData = data;
- newData.convert(QMetaType::QColor);
+ newData.convert(QMetaType(QMetaType::QColor));
return newData;
}
case QMetaType::QVariantList: {
- if (format != QLatin1String("text/uri-list"))
+ if (format != "text/uri-list"_L1)
break;
Q_FALLTHROUGH();
}
case QMetaType::QUrl: {
- QByteArray ba = data.toByteArray();
+ auto bav = data.view<QByteArrayView>();
// Qt 3.x will send text/uri-list with a trailing
// null-terminator (that is *not* sent for any other
// text/* mime-type), so chop it off
- if (ba.endsWith('\0'))
- ba.chop(1);
-
- QList<QByteArray> urls = ba.split('\n');
- QList<QVariant> list;
- for (int i = 0; i < urls.size(); ++i) {
- QByteArray ba = urls.at(i).trimmed();
- if (!ba.isEmpty())
- list.append(QUrl::fromEncoded(ba));
- }
- return list;
+ if (bav.endsWith('\0'))
+ bav.chop(1);
+ return dataToUrls(bav);
}
default:
break;
}
- } else if (type == QMetaType::QByteArray) {
+ } else if (typeId == QMetaType::QByteArray) {
// try to convert to bytearray
- switch (data.userType()) {
+ switch (data.metaType().id()) {
case QMetaType::QByteArray:
case QMetaType::QColor:
return data.toByteArray();
@@ -212,10 +195,10 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType::T
case QMetaType::QVariantList: {
// has to be list of URLs
QByteArray result;
- QList<QVariant> list = data.toList();
- for (int i = 0; i < list.size(); ++i) {
- if (list.at(i).userType() == QMetaType::QUrl) {
- result += list.at(i).toUrl().toEncoded();
+ const QList<QVariant> list = data.toList();
+ for (const auto &element : list) {
+ if (element.metaType().id() == QMetaType::QUrl) {
+ result += element.toUrl().toEncoded();
result += "\r\n";
}
}
@@ -312,12 +295,12 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType::T
\snippet code/src_corelib_kernel_qmimedata.cpp 8
On Windows, the MIME format does not always map directly to the
- clipboard formats. Qt provides QWinMime to map clipboard
+ clipboard formats. Qt provides QWindowsMimeConverter to map clipboard
formats to open-standard MIME formats. Similarly, the
- QMacPasteboardMime maps MIME to Mac flavors.
+ QUtiMimeConverter maps MIME to Uniform Type Identifiers on macOS and iOS.
\sa QClipboard, QDragEnterEvent, QDragMoveEvent, QDropEvent, QDrag,
- QMacPasteboardMime, {Drag and Drop}
+ {Drag and Drop}
*/
/*!
@@ -345,15 +328,15 @@ QMimeData::~QMimeData()
QList<QUrl> QMimeData::urls() const
{
Q_D(const QMimeData);
- QVariant data = d->retrieveTypedData(textUriListLiteral(), QMetaType::QVariantList);
+ QVariant data = d->retrieveTypedData(textUriListLiteral(), QMetaType(QMetaType::QVariantList));
QList<QUrl> urls;
- if (data.userType() == QMetaType::QUrl)
+ if (data.metaType().id() == QMetaType::QUrl)
urls.append(data.toUrl());
- else if (data.userType() == QMetaType::QVariantList) {
- QList<QVariant> list = data.toList();
- for (int i = 0; i < list.size(); ++i) {
- if (list.at(i).userType() == QMetaType::QUrl)
- urls.append(list.at(i).toUrl());
+ else if (data.metaType().id() == QMetaType::QVariantList) {
+ const QList<QVariant> list = data.toList();
+ for (const auto &element : list) {
+ if (element.metaType().id() == QMetaType::QUrl)
+ urls.append(element.toUrl());
}
}
return urls;
@@ -373,13 +356,7 @@ QList<QUrl> QMimeData::urls() const
void QMimeData::setUrls(const QList<QUrl> &urls)
{
Q_D(QMimeData);
- QList<QVariant> list;
- const int numUrls = urls.size();
- list.reserve(numUrls);
- for (int i = 0; i < numUrls; ++i)
- list.append(urls.at(i));
-
- d->setData(textUriListLiteral(), list);
+ d->setData(textUriListLiteral(), QList<QVariant>(urls.cbegin(), urls.cend()));
}
/*!
@@ -405,11 +382,11 @@ bool QMimeData::hasUrls() const
QString QMimeData::text() const
{
Q_D(const QMimeData);
- QVariant utf8Text = d->retrieveTypedData(textPlainUtf8Literal(), QMetaType::QString);
+ QVariant utf8Text = d->retrieveTypedData(textPlainUtf8Literal(), QMetaType(QMetaType::QString));
if (!utf8Text.isNull())
return utf8Text.toString();
- QVariant data = d->retrieveTypedData(textPlainLiteral(), QMetaType::QString);
+ QVariant data = d->retrieveTypedData(textPlainLiteral(), QMetaType(QMetaType::QString));
return data.toString();
}
@@ -445,7 +422,7 @@ bool QMimeData::hasText() const
QString QMimeData::html() const
{
Q_D(const QMimeData);
- QVariant data = d->retrieveTypedData(textHtmlLiteral(), QMetaType::QString);
+ QVariant data = d->retrieveTypedData(textHtmlLiteral(), QMetaType(QMetaType::QString));
return data.toString();
}
@@ -487,7 +464,7 @@ bool QMimeData::hasHtml() const
QVariant QMimeData::imageData() const
{
Q_D(const QMimeData);
- return d->retrieveTypedData(applicationXQtImageLiteral(), QMetaType::QImage);
+ return d->retrieveTypedData(applicationXQtImageLiteral(), QMetaType(QMetaType::QImage));
}
/*!
@@ -534,7 +511,7 @@ bool QMimeData::hasImage() const
QVariant QMimeData::colorData() const
{
Q_D(const QMimeData);
- return d->retrieveTypedData(applicationXColorLiteral(), QMetaType::QColor);
+ return d->retrieveTypedData(applicationXColorLiteral(), QMetaType(QMetaType::QColor));
}
/*!
@@ -569,7 +546,7 @@ bool QMimeData::hasColor() const
QByteArray QMimeData::data(const QString &mimeType) const
{
Q_D(const QMimeData);
- QVariant data = d->retrieveTypedData(mimeType, QMetaType::QByteArray);
+ QVariant data = d->retrieveTypedData(mimeType, QMetaType(QMetaType::QByteArray));
return data.toByteArray();
}
@@ -583,28 +560,19 @@ QByteArray QMimeData::data(const QString &mimeType) const
Note that if you want to use a custom data type in an item view drag and drop
operation, you must register it as a Qt \l{QMetaType}{meta type}, using the
- Q_DECLARE_METATYPE() macro, and implement stream operators for it. The stream
- operators must then be registered with the qRegisterMetaTypeStreamOperators()
- function.
+ Q_DECLARE_METATYPE() macro, and implement stream operators for it.
- \sa hasFormat(), QMetaType, {QMetaType::}{qRegisterMetaTypeStreamOperators()}
+ \sa hasFormat(), QMetaType, {QMetaType::}{Q_DECLARE_METATYPE()}
*/
void QMimeData::setData(const QString &mimeType, const QByteArray &data)
{
Q_D(QMimeData);
- if (mimeType == QLatin1String("text/uri-list")) {
- QByteArray ba = data;
+ if (mimeType == "text/uri-list"_L1) {
+ auto ba = QByteArrayView(data);
if (ba.endsWith('\0'))
ba.chop(1);
- QList<QByteArray> urls = ba.split('\n');
- QList<QVariant> list;
- for (int i = 0; i < urls.size(); ++i) {
- QByteArray ba = urls.at(i).trimmed();
- if (!ba.isEmpty())
- list.append(QUrl::fromEncoded(ba));
- }
- d->setData(mimeType, list);
+ d->setData(mimeType, dataToUrls(ba));
} else {
d->setData(mimeType, QVariant(data));
}
@@ -661,7 +629,7 @@ QStringList QMimeData::formats() const
\sa data()
*/
-QVariant QMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
+QVariant QMimeData::retrieveData(const QString &mimeType, QMetaType type) const
{
Q_UNUSED(type);
Q_D(const QMimeData);
diff --git a/src/corelib/kernel/qmimedata.h b/src/corelib/kernel/qmimedata.h
index 64235832c2..0969a7315c 100644
--- a/src/corelib/kernel/qmimedata.h
+++ b/src/corelib/kernel/qmimedata.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEDATA_H
#define QMIMEDATA_H
@@ -45,7 +9,6 @@
QT_BEGIN_NAMESPACE
-
class QUrl;
class QMimeDataPrivate;
@@ -84,9 +47,10 @@ public:
virtual QStringList formats() const;
void clear();
+
protected:
- virtual QVariant retrieveData(const QString &mimetype,
- QVariant::Type preferredType) const;
+ virtual QVariant retrieveData(const QString &mimetype, QMetaType preferredType) const;
+
private:
Q_DISABLE_COPY(QMimeData)
Q_DECLARE_PRIVATE(QMimeData)
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 615bc63f1d..e1129c5d25 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1,52 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qobject.h"
#include "qobject_p.h"
+#include "qobject_p_p.h"
#include "qmetaobject_p.h"
#include "qabstracteventdispatcher.h"
#include "qabstracteventdispatcher_p.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
+#include "qcoreevent_p.h"
#include "qloggingcategory.h"
#include "qvariant.h"
#include "qmetaobject.h"
@@ -56,29 +22,41 @@
#include <qthread.h>
#include <private/qthread_p.h>
#include <qdebug.h>
-#include <qpair.h>
#include <qvarlengtharray.h>
#include <qscopeguard.h>
#include <qset.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#endif
-#include <qsharedpointer.h>
#include <private/qorderedmutexlocker_p.h>
#include <private/qhooks_p.h>
#include <qtcore_tracepoints_p.h>
#include <new>
+#include <mutex>
+#include <memory>
#include <ctype.h>
#include <limits.h>
QT_BEGIN_NAMESPACE
+Q_TRACE_POINT(qtcore, QObject_ctor, QObject *object);
+Q_TRACE_POINT(qtcore, QObject_dtor, QObject *object);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_entry, QObject *sender, int signalIndex);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_exit);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_slot_entry, QObject *receiver, int slotIndex);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_slot_exit);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_slot_functor_entry, void *slotObject);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_slot_functor_exit);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_declarative_signal_entry, QObject *sender, int signalIndex);
+Q_TRACE_POINT(qtcore, QMetaObject_activate_declarative_signal_exit);
+
static int DIRECT_CONNECTION_ONLY = 0;
-Q_LOGGING_CATEGORY(lcConnections, "qt.core.qmetaobject.connectslotsbyname")
+Q_LOGGING_CATEGORY(lcConnectSlotsByName, "qt.core.qmetaobject.connectslotsbyname")
+Q_LOGGING_CATEGORY(lcConnect, "qt.core.qobject.connect")
Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
@@ -95,33 +73,37 @@ QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject()
{
}
-static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
+static int *queuedConnectionTypes(const QMetaMethod &method)
{
- int *types = new int [typeNames.count() + 1];
- Q_CHECK_PTR(types);
- for (int i = 0; i < typeNames.count(); ++i) {
- const QByteArray typeName = typeNames.at(i);
- if (typeName.endsWith('*'))
- types[i] = QMetaType::VoidStar;
+ const auto parameterCount = method.parameterCount();
+ int *typeIds = new int[parameterCount + 1];
+ Q_CHECK_PTR(typeIds);
+ for (int i = 0; i < parameterCount; ++i) {
+ const QMetaType metaType = method.parameterMetaType(i);
+ if (metaType.flags() & QMetaType::IsPointer)
+ typeIds[i] = QMetaType::VoidStar;
else
- types[i] = QMetaType::type(typeName);
-
- if (!types[i]) {
- qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
- "(Make sure '%s' is registered using qRegisterMetaType().)",
- typeName.constData(), typeName.constData());
- delete [] types;
+ typeIds[i] = metaType.id();
+ if (!typeIds[i] && method.parameterTypeName(i).endsWith('*'))
+ typeIds[i] = QMetaType::VoidStar;
+ if (!typeIds[i]) {
+ const QByteArray typeName = method.parameterTypeName(i);
+ qCWarning(lcConnect,
+ "QObject::connect: Cannot queue arguments of type '%s'\n"
+ "(Make sure '%s' is registered using qRegisterMetaType().)",
+ typeName.constData(), typeName.constData());
+ delete[] typeIds;
return nullptr;
}
}
- types[typeNames.count()] = 0;
+ typeIds[parameterCount] = 0;
- return types;
+ return typeIds;
}
static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
{
- QScopedArrayPointer<int> types(new int [argc + 1]);
+ auto types = std::make_unique<int[]>(argc + 1);
for (int i = 0; i < argc; ++i) {
const QArgumentType &type = argumentTypes[i];
if (type.type())
@@ -129,21 +111,22 @@ static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
else if (type.name().endsWith('*'))
types[i] = QMetaType::VoidStar;
else
- types[i] = QMetaType::type(type.name());
+ types[i] = QMetaType::fromName(type.name()).id();
if (!types[i]) {
- qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
- "(Make sure '%s' is registered using qRegisterMetaType().)",
- type.name().constData(), type.name().constData());
+ qCWarning(lcConnect,
+ "QObject::connect: Cannot queue arguments of type '%s'\n"
+ "(Make sure '%s' is registered using qRegisterMetaType().)",
+ type.name().constData(), type.name().constData());
return nullptr;
}
}
types[argc] = 0;
- return types.take();
+ return types.release();
}
-static QBasicMutex _q_ObjectMutexPool[131];
+Q_CONSTINIT static QBasicMutex _q_ObjectMutexPool[131];
/**
* \internal
@@ -154,16 +137,7 @@ static inline QBasicMutex *signalSlotLock(const QObject *o)
return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)];
}
-#if QT_VERSION < 0x60000
-extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
-{}
-
-extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
-{}
-#endif
-
void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr;
-void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr;
void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr;
int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
@@ -201,6 +175,10 @@ QObjectPrivate::QObjectPrivate(int version)
metaObject = nullptr;
isWindow = false;
deleteLaterCalled = false;
+ isQuickItem = false;
+ willBeWidget = false;
+ wasWidget = false;
+ receiveParentEvents = false; // If object wants ParentAboutToChange and ParentChange
}
QObjectPrivate::~QObjectPrivate()
@@ -213,8 +191,8 @@ QObjectPrivate::~QObjectPrivate()
thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr);
// release the timer ids back to the pool
- for (int i = 0; i < extraData->runningTimers.size(); ++i)
- QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
+ for (auto id : std::as_const(extraData->runningTimers))
+ QAbstractEventDispatcherPrivate::releaseTimerId(id);
} else {
qWarning("QObject::~QObject: Timers cannot be stopped from another thread");
}
@@ -225,7 +203,8 @@ QObjectPrivate::~QObjectPrivate()
thisThreadData->deref();
- if (metaObject) metaObject->objectDestroyed(q_ptr);
+ if (metaObject)
+ metaObject->objectDestroyed(q_ptr);
delete extraData;
}
@@ -248,32 +227,11 @@ static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int
}
// Used by QAccessibleWidget
-bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
-{
- Q_Q(const QObject);
- int signal_index = signalIndex(signal);
- ConnectionData *cd = connections.loadRelaxed();
- if (signal_index < 0 || !cd)
- return false;
- QBasicMutexLocker locker(signalSlotLock(q));
- if (signal_index < cd->signalVectorCount()) {
- const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
-
- while (c) {
- if (c->receiver.loadRelaxed() == receiver)
- return true;
- c = c->nextConnectionList.loadRelaxed();
- }
- }
- return false;
-}
-
-// Used by QAccessibleWidget
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
QObjectList returnValue;
int signal_index = signalIndex(signal);
- ConnectionData *cd = connections.loadRelaxed();
+ ConnectionData *cd = connections.loadAcquire();
if (signal_index < 0 || !cd)
return returnValue;
if (signal_index < cd->signalVectorCount()) {
@@ -289,17 +247,17 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const
return returnValue;
}
-// Used by QAccessibleWidget
-QObjectList QObjectPrivate::senderList() const
+/*!
+ \internal
+ The signalSlotLock() of the sender must be locked while calling this function
+*/
+inline void QObjectPrivate::ensureConnectionData()
{
- QObjectList returnValue;
- ConnectionData *cd = connections.loadRelaxed();
- if (cd) {
- QBasicMutexLocker locker(signalSlotLock(q_func()));
- for (Connection *c = cd->senders; c; c = c->next)
- returnValue << c->sender;
- }
- return returnValue;
+ if (connections.loadRelaxed())
+ return;
+ ConnectionData *cd = new ConnectionData;
+ cd->ref.ref();
+ connections.storeRelease(cd);
}
/*!
@@ -312,7 +270,7 @@ QObjectList QObjectPrivate::senderList() const
Will also add the connection in the sender's list of the receiver.
*/
-void QObjectPrivate::addConnection(int signal, Connection *c)
+inline void QObjectPrivate::addConnection(int signal, Connection *c)
{
Q_ASSERT(c->sender == q_ptr);
ensureConnectionData();
@@ -382,10 +340,16 @@ void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection
c->prevConnectionList->nextConnectionList.storeRelaxed(n);
c->prevConnectionList = nullptr;
- Q_ASSERT(c != orphaned.loadRelaxed());
+ Q_ASSERT(c != static_cast<Connection *>(orphaned.load(std::memory_order_relaxed)));
// add c to orphanedConnections
- c->nextInOrphanList = orphaned.loadRelaxed();
- orphaned.storeRelaxed(c);
+ TaggedSignalVector o = nullptr;
+ /* No ABA issue here: When adding a node, we only care about the list head, it doesn't
+ * matter if the tail changes.
+ */
+ o = orphaned.load(std::memory_order_acquire);
+ do {
+ c->nextInOrphanList = o;
+ } while (!orphaned.compare_exchange_strong(o, TaggedSignalVector(c), std::memory_order_release));
#ifndef QT_NO_DEBUG
found = false;
@@ -400,28 +364,39 @@ void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection
}
-void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender)
+void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy)
{
- ConnectionOrSignalVector *c = nullptr;
+ QBasicMutex *senderMutex = signalSlotLock(sender);
+ TaggedSignalVector c = nullptr;
{
- QBasicMutexLocker l(signalSlotLock(sender));
+ std::unique_lock<QBasicMutex> lock(*senderMutex, std::defer_lock_t{});
+ if (lockPolicy == NeedToLock)
+ lock.lock();
if (ref.loadAcquire() > 1)
return;
// Since ref == 1, no activate() is in process since we locked the mutex. That implies,
// that nothing can reference the orphaned connection objects anymore and they can
// be safely deleted
- c = orphaned.loadRelaxed();
- orphaned.storeRelaxed(nullptr);
+ c = orphaned.exchange(nullptr, std::memory_order_relaxed);
+ }
+ if (c) {
+ // Deleting c might run arbitrary user code, so we must not hold the lock
+ if (lockPolicy == AlreadyLockedAndTemporarilyReleasingLock) {
+ senderMutex->unlock();
+ deleteOrphaned(c);
+ senderMutex->lock();
+ } else {
+ deleteOrphaned(c);
+ }
}
- deleteOrphaned(c);
}
-void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o)
+inline void QObjectPrivate::ConnectionData::deleteOrphaned(TaggedSignalVector o)
{
while (o) {
- QObjectPrivate::ConnectionOrSignalVector *next = nullptr;
- if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(o)) {
+ TaggedSignalVector next = nullptr;
+ if (SignalVector *v = static_cast<SignalVector *>(o)) {
next = v->nextInOrphanList;
free(v);
} else {
@@ -447,7 +422,7 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative)
if (checkDeclarative && isDeclarativeSignalConnected(signalIndex))
return true;
- ConnectionData *cd = connections.loadRelaxed();
+ ConnectionData *cd = connections.loadAcquire();
if (!cd)
return false;
SignalVector *signalVector = cd->signalVector.loadRelaxed();
@@ -470,7 +445,7 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative)
bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
{
- ConnectionData *cd = connections.loadRelaxed();
+ ConnectionData *cd = connections.loadAcquire();
if (!cd)
return false;
SignalVector *signalVector = cd->signalVector.loadRelaxed();
@@ -487,6 +462,13 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
return false;
}
+void QObjectPrivate::reinitBindingStorageAfterThreadMove()
+{
+ bindingStorage.reinitAfterThreadMove();
+ for (int i = 0; i < children.size(); ++i)
+ children[i]->d_func()->reinitBindingStorageAfterThreadMove();
+}
+
/*!
\internal
*/
@@ -506,7 +488,7 @@ inline void QMetaCallEvent::allocArgs()
if (!d.nargs_)
return;
- constexpr size_t each = sizeof(void*) + sizeof(int);
+ constexpr size_t each = sizeof(void*) + sizeof(QMetaType);
void *const memory = d.nargs_ * each > sizeof(prealloc_) ?
calloc(d.nargs_, each) : prealloc_;
@@ -540,7 +522,7 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
const QObject *sender, int signalId,
void **args, QSemaphore *semaphore)
: QAbstractMetaCallEvent(sender, signalId, semaphore),
- d({slotO, args, nullptr, 0, 0, ushort(-1)}),
+ d({QtPrivate::SlotObjUniquePtr{slotO}, args, nullptr, 0, 0, ushort(-1)}),
prealloc_()
{
if (d.slotObj_)
@@ -550,6 +532,21 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
/*!
\internal
+ Used for blocking queued connections, just passes \a args through without
+ allocating any memory.
+ */
+QMetaCallEvent::QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotO,
+ const QObject *sender, int signalId,
+ void **args, QSemaphore *semaphore)
+ : QAbstractMetaCallEvent(sender, signalId, semaphore),
+ d{std::move(slotO), args, nullptr, 0, 0, ushort(-1)},
+ prealloc_()
+{
+}
+
+/*!
+ \internal
+
Allocates memory for \a nargs; code creating an event needs to initialize
the void* and int arrays by accessing \a args() and \a types(), respectively.
*/
@@ -574,7 +571,7 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
const QObject *sender, int signalId,
int nargs)
: QAbstractMetaCallEvent(sender, signalId),
- d({slotO, nullptr, nullptr, nargs, 0, ushort(-1)}),
+ d({QtPrivate::SlotObjUniquePtr(slotO), nullptr, nullptr, nargs, 0, ushort(-1)}),
prealloc_()
{
if (d.slotObj_)
@@ -584,20 +581,34 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
/*!
\internal
+
+ Allocates memory for \a nargs; code creating an event needs to initialize
+ the void* and int arrays by accessing \a args() and \a types(), respectively.
+ */
+QMetaCallEvent::QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotO,
+ const QObject *sender, int signalId,
+ int nargs)
+ : QAbstractMetaCallEvent(sender, signalId),
+ d{std::move(slotO), nullptr, nullptr, nargs, 0, ushort(-1)},
+ prealloc_()
+{
+ allocArgs();
+}
+
+/*!
+ \internal
*/
QMetaCallEvent::~QMetaCallEvent()
{
if (d.nargs_) {
- int *typeIDs = types();
+ QMetaType *t = types();
for (int i = 0; i < d.nargs_; ++i) {
- if (typeIDs[i] && d.args_[i])
- QMetaType::destroy(typeIDs[i], d.args_[i]);
+ if (t[i].isValid() && d.args_[i])
+ t[i].destroy(d.args_[i]);
}
- if (reinterpret_cast<void*>(d.args_) != reinterpret_cast<void*>(prealloc_))
+ if (reinterpret_cast<void *>(d.args_) != reinterpret_cast<void *>(prealloc_))
free(d.args_);
}
- if (d.slotObj_)
- d.slotObj_->destroyIfLastRef();
}
/*!
@@ -615,6 +626,25 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
}
}
+QMetaCallEvent* QMetaCallEvent::create_impl(QtPrivate::SlotObjUniquePtr slotObj,
+ const QObject *sender, int signal_index,
+ size_t argc, const void* const argp[],
+ const QMetaType metaTypes[])
+{
+ auto metaCallEvent = std::make_unique<QMetaCallEvent>(std::move(slotObj), sender,
+ signal_index, int(argc));
+
+ void **args = metaCallEvent->args();
+ QMetaType *types = metaCallEvent->types();
+ for (size_t i = 0; i < argc; ++i) {
+ types[i] = metaTypes[i];
+ args[i] = types[i].create(argp[i]);
+ Q_CHECK_PTR(!i || args[i]);
+ }
+
+ return metaCallEvent.release();
+}
+
/*!
\class QSignalBlocker
\brief Exception-safe wrapper around QObject::blockSignals().
@@ -702,6 +732,14 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
*/
/*!
+ \fn void QSignalBlocker::dismiss()
+ \since 6.7
+ Dismisses the QSignalBlocker. It will no longer access the QObject
+ passed to its constructor. unblock(), reblock(), as well as
+ ~QSignalBlocker() will have no effect.
+*/
+
+/*!
\class QObject
\inmodule QtCore
\brief The QObject class is the base class of all Qt objects.
@@ -742,7 +780,7 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
to catch child events.
Last but not least, QObject provides the basic timer support in
- Qt; see QTimer for high-level support for timers.
+ Qt; see QChronoTimer for high-level support for timers.
Notice that the Q_OBJECT macro is mandatory for any object that
implements signals, slots or properties. You also need to run the
@@ -825,20 +863,20 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
\l uic generates code that invokes this function to enable
auto-connection to be performed between widgets on forms created
- with \e{Qt Designer}. More information about using auto-connection with \e{Qt Designer} is
+ with \e{\QD}. More information about using auto-connection with \e{\QD} is
given in the \l{Using a Designer UI File in Your Application} section of
- the \e{Qt Designer} manual.
+ the \l{Qt Widgets Designer Manual}{\QD} manual.
\section1 Dynamic Properties
- From Qt 4.2, dynamic properties can be added to and removed from QObject
+ Dynamic properties can be added to and removed from QObject
instances at run-time. Dynamic properties do not need to be declared at
compile-time, yet they provide the same advantages as static properties
and are manipulated using the same API - using property() to read them
and setProperty() to write them.
- From Qt 4.3, dynamic properties are supported by
- \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
+ Dynamic properties are supported by
+ \l{Qt Widgets Designer's Widget Editing Mode#The Property Editor}{\QD},
and both standard Qt widgets and user-created forms can be given dynamic
properties.
@@ -917,7 +955,7 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
QT_TRY {
if (!check_parent_thread(parent, parent ? parent->d_func()->threadData.loadRelaxed() : nullptr, threadData))
parent = nullptr;
- if (d->isWidget) {
+ if (d->willBeWidget) {
if (parent) {
d->parent = parent;
d->parent->d_func()->children.append(this);
@@ -931,14 +969,16 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
QT_RETHROW;
}
}
-#if QT_VERSION < 0x60000
- qt_addObject(this);
-#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
Q_TRACE(QObject_ctor, this);
}
+void QObjectPrivate::clearBindingStorage()
+{
+ bindingStorage.clear();
+}
+
/*!
Destroys the object, deleting all its child objects.
@@ -953,8 +993,8 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
outside the parent. If you still do, the destroyed() signal gives
you an opportunity to detect when an object is destroyed.
- \warning Deleting a QObject while pending events are waiting to
- be delivered can cause a crash. You must not delete the QObject
+ \warning Deleting a QObject while it is handling an event
+ delivered to it can cause a crash. You must not delete the QObject
directly if it exists in a different thread than the one currently
executing. Use deleteLater() instead, which will cause the event
loop to delete the object after all pending events have been
@@ -969,6 +1009,20 @@ QObject::~QObject()
d->wasDeleted = true;
d->blockSig = 0; // unblock signals so we always emit destroyed()
+ if (!d->bindingStorage.isValid()) {
+ // this might be the case after an incomplete thread-move
+ // remove this object from the pending list in that case
+ if (QThread *ownThread = thread()) {
+ auto *privThread = static_cast<QThreadPrivate *>(
+ QObjectPrivate::get(ownThread));
+ privThread->removeObjectWithPendingBindingStatusChange(this);
+ }
+ }
+
+ // If we reached this point, we need to clear the binding data
+ // as the corresponding properties are no longer useful
+ d->clearBindingStorage();
+
QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
if (sharedRefcount) {
if (sharedRefcount->strongref.loadRelaxed() > 0) {
@@ -982,14 +1036,14 @@ QObject::~QObject()
delete sharedRefcount;
}
- if (!d->isWidget && d->isSignalConnected(0)) {
+ if (!d->wasWidget && d->isSignalConnected(0)) {
emit destroyed(this);
}
- if (d->declarativeData && QAbstractDeclarativeData::destroyed)
+ if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::destroyed)
QAbstractDeclarativeData::destroyed(d->declarativeData, this);
- QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
+ QObjectPrivate::ConnectionData *cd = d->connections.loadAcquire();
if (cd) {
if (cd->currentSender) {
cd->currentSender->receiverDeleted();
@@ -997,7 +1051,7 @@ QObject::~QObject()
}
QBasicMutex *signalSlotMutex = signalSlotLock(this);
- QBasicMutexLocker locker(signalSlotMutex);
+ QMutexLocker locker(signalSlotMutex);
// disconnect all receivers
int receiverCount = cd->signalVectorCount();
@@ -1009,7 +1063,7 @@ QObject::~QObject()
QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed());
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
- if (c->receiver.loadAcquire()) {
+ if (c == connectionList.first.loadAcquire() && c->receiver.loadAcquire()) {
cd->removeConnection(c);
Q_ASSERT(connectionList.first.loadRelaxed() != c);
}
@@ -1047,14 +1101,29 @@ QObject::~QObject()
}
senderData->removeConnection(node);
+ /*
+ When we unlock, another thread has the chance to delete/modify sender data.
+ Thus we need to call cleanOrphanedConnections before unlocking. We use the
+ variant of the function which assumes that the lock is already held to avoid
+ a deadlock.
+ We need to hold m, the sender lock. Considering that we might execute arbitrary user
+ code, we should already release the signalSlotMutex here – unless they are the same.
+ */
+ const bool locksAreTheSame = signalSlotMutex == m;
+ if (!locksAreTheSame)
+ locker.unlock();
+ senderData->cleanOrphanedConnections(
+ sender,
+ QObjectPrivate::ConnectionData::AlreadyLockedAndTemporarilyReleasingLock
+ );
if (needToUnlock)
m->unlock();
- if (slotObj) {
+ if (locksAreTheSame) // otherwise already unlocked
locker.unlock();
+ if (slotObj)
slotObj->destroyIfLastRef();
- locker.relock();
- }
+ locker.relock();
}
// invalidate all connections on the object and make sure
@@ -1068,9 +1137,6 @@ QObject::~QObject()
if (!d->children.isEmpty())
d->deleteChildren();
-#if QT_VERSION < 0x60000
- qt_removeObject(this);
-#endif
if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
@@ -1080,12 +1146,12 @@ QObject::~QObject()
d->setParent_helper(nullptr);
}
-QObjectPrivate::Connection::~Connection()
+inline QObjectPrivate::Connection::~Connection()
{
if (ownArgumentTypes) {
const int *v = argumentTypes.loadRelaxed();
if (v != &DIRECT_CONNECTION_ONLY)
- delete [] v;
+ delete[] v;
}
if (isSlotObject)
slotObj->destroyIfLastRef();
@@ -1163,8 +1229,7 @@ QObjectPrivate::Connection::~Connection()
\c dynamic_cast(), with the advantages that it doesn't require
RTTI support and it works across dynamic library boundaries.
- qobject_cast() can also be used in conjunction with interfaces;
- see the \l{tools/plugandpaint/app}{Plug & Paint} example for details.
+ qobject_cast() can also be used in conjunction with interfaces.
\warning If T isn't declared with the Q_OBJECT macro, this
function's return value is undefined.
@@ -1210,24 +1275,63 @@ QObjectPrivate::Connection::~Connection()
QString QObject::objectName() const
{
Q_D(const QObject);
+#if QT_CONFIG(thread)
+ if (QThread::currentThreadId() != d->threadData.loadRelaxed()->threadId.loadRelaxed()) // Unsafe code path
+ return d->extraData ? d->extraData->objectName.valueBypassingBindings() : QString();
+#endif
+ if (!d->extraData && QtPrivate::isAnyBindingEvaluating()) {
+ QObjectPrivate *dd = const_cast<QObjectPrivate *>(d);
+ // extraData is mutable, so this should be safe
+ dd->extraData = new QObjectPrivate::ExtraData(dd);
+ }
return d->extraData ? d->extraData->objectName : QString();
}
-/*
+/*!
+ \fn void QObject::setObjectName(const QString &name)
Sets the object's name to \a name.
*/
-void QObject::setObjectName(const QString &name)
+void QObject::doSetObjectName(const QString &name)
+{
+ Q_D(QObject);
+
+ d->ensureExtraData();
+
+ d->extraData->objectName.removeBindingUnlessInWrapper();
+
+ if (d->extraData->objectName.valueBypassingBindings() != name) {
+ d->extraData->objectName.setValueBypassingBindings(name);
+ d->extraData->objectName.notify(); // also emits a signal
+ }
+}
+
+/*!
+ \overload
+ \since 6.4
+*/
+void QObject::setObjectName(QAnyStringView name)
{
Q_D(QObject);
- if (!d->extraData)
- d->extraData = new QObjectPrivate::ExtraData;
- if (d->extraData->objectName != name) {
- d->extraData->objectName = name;
- emit objectNameChanged(d->extraData->objectName, QPrivateSignal());
+ d->ensureExtraData();
+
+ d->extraData->objectName.removeBindingUnlessInWrapper();
+
+ if (d->extraData->objectName.valueBypassingBindings() != name) {
+ d->extraData->objectName.setValueBypassingBindings(name.toString());
+ d->extraData->objectName.notify(); // also emits a signal
}
}
+QBindable<QString> QObject::bindableObjectName()
+{
+ Q_D(QObject);
+
+ d->ensureExtraData();
+
+ return QBindable<QString>(&d->extraData->objectName);
+}
+
/*! \fn void QObject::objectNameChanged(const QString &objectName)
This signal is emitted after the object's name has been changed. The new object name is passed as \a objectName.
@@ -1254,6 +1358,17 @@ void QObject::setObjectName(const QString &name)
*/
/*!
+ \fn bool QObject::isQuickItemType() const
+
+ Returns \c true if the object is a QQuickItem; otherwise returns \c false.
+
+ Calling this function is equivalent to calling
+ \c{inherits("QQuickItem")}, except that it is much faster.
+
+ \since 6.4
+*/
+
+/*!
This virtual function receives events to an object and should
return true if the event \a e was recognized and processed.
@@ -1275,28 +1390,31 @@ bool QObject::event(QEvent *e)
{
switch (e->type()) {
case QEvent::Timer:
- timerEvent((QTimerEvent*)e);
+ timerEvent((QTimerEvent *)e);
break;
case QEvent::ChildAdded:
case QEvent::ChildPolished:
case QEvent::ChildRemoved:
- childEvent((QChildEvent*)e);
+ childEvent((QChildEvent *)e);
break;
case QEvent::DeferredDelete:
- qDeleteInEventHandler(this);
+ qCDebug(lcDeleteLater) << "Deferred deleting" << this;
+ delete this;
break;
case QEvent::MetaCall:
{
QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
- if (!d_func()->connections.loadRelaxed()) {
- QBasicMutexLocker locker(signalSlotLock(this));
+ QObjectPrivate::ConnectionData *connections = d_func()->connections.loadAcquire();
+ if (!connections) {
+ QMutexLocker locker(signalSlotLock(this));
d_func()->ensureConnectionData();
+ connections = d_func()->connections.loadRelaxed();
}
- QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
+ QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId(), connections);
mce->placeMetaCall(this);
break;
@@ -1307,12 +1425,20 @@ bool QObject::event(QEvent *e)
QThreadData *threadData = d->threadData.loadRelaxed();
QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
- QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
+ QList<QAbstractEventDispatcher::TimerInfoV2> timers = eventDispatcher->timersForObject(this);
if (!timers.isEmpty()) {
+ const bool res = eventDispatcher->unregisterTimers(this);
// do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).
- eventDispatcher->unregisterTimers(this);
- QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
- Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));
+ Q_ASSERT_X(res, Q_FUNC_INFO,
+ "QAbstractEventDispatcher::unregisterTimers() returned false,"
+ " but there are timers associated with this object.");
+ auto reRegisterTimers = [this, timers = std::move(timers)]() {
+ QAbstractEventDispatcher *eventDispatcher =
+ d_func()->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
+ for (const auto &ti : timers)
+ eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, this);
+ };
+ QMetaObject::invokeMethod(this, std::move(reRegisterTimers), Qt::QueuedConnection);
}
}
break;
@@ -1334,9 +1460,9 @@ bool QObject::event(QEvent *e)
This event handler can be reimplemented in a subclass to receive
timer events for the object.
- QTimer provides a higher-level interface to the timer
- functionality, and also more general information about timers. The
- timer event is passed in the \a event parameter.
+ QChronoTimer provides higher-level interfaces to the timer functionality,
+ and also more general information about timers. The timer event is passed
+ in the \a event parameter.
\sa startTimer(), killTimer(), event()
*/
@@ -1475,9 +1601,9 @@ QThread *QObject::thread() const
}
/*!
- Changes the thread affinity for this object and its children. The
- object cannot be moved if it has a parent. Event processing will
- continue in the \a targetThread.
+ Changes the thread affinity for this object and its children and
+ returns \c true on success. The object cannot be moved if it has a
+ parent. Event processing will continue in the \a targetThread.
To move an object to the main thread, use QApplication::instance()
to retrieve a pointer to the current application, and then use
@@ -1514,42 +1640,46 @@ QThread *QObject::thread() const
\sa thread()
*/
-void QObject::moveToThread(QThread *targetThread)
+bool QObject::moveToThread(QThread *targetThread QT6_IMPL_NEW_OVERLOAD_TAIL)
{
Q_D(QObject);
if (d->threadData.loadRelaxed()->thread.loadAcquire() == targetThread) {
// object is already in this thread
- return;
+ return true;
}
if (d->parent != nullptr) {
qWarning("QObject::moveToThread: Cannot move objects with a parent");
- return;
+ return false;
}
if (d->isWidget) {
qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
- return;
+ return false;
+ }
+ if (!d->bindingStorage.isEmpty()) {
+ qWarning("QObject::moveToThread: Can not move objects that contain bindings or are used in bindings to a new thread.");
+ return false;
}
QThreadData *currentData = QThreadData::current();
QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
- QThreadData *thisThreadData = d->threadData.loadRelaxed();
- if (!thisThreadData->thread.loadAcquire() && currentData == targetData) {
+ QThreadData *thisThreadData = d->threadData.loadAcquire();
+ if (!thisThreadData->thread.loadRelaxed() && currentData == targetData) {
// one exception to the rule: we allow moving objects with no thread affinity to the current thread
- currentData = d->threadData;
+ currentData = thisThreadData;
} else if (thisThreadData != currentData) {
qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
"Cannot move to target thread (%p)\n",
currentData->thread.loadRelaxed(), thisThreadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
qWarning("You might be loading two sets of Qt binaries into the same process. "
"Check that all plugins are compiled against the right Qt binaries. Export "
"DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
#endif
- return;
+ return false;
}
// prepare to move
@@ -1568,12 +1698,22 @@ void QObject::moveToThread(QThread *targetThread)
currentData->ref();
// move the object
- d_func()->setThreadData_helper(currentData, targetData);
+ auto threadPrivate = targetThread
+ ? static_cast<QThreadPrivate *>(QThreadPrivate::get(targetThread))
+ : nullptr;
+ QBindingStatus *bindingStatus = threadPrivate
+ ? threadPrivate->bindingStatus()
+ : nullptr;
+ if (threadPrivate && !bindingStatus) {
+ bindingStatus = threadPrivate->addObjectWithPendingBindingStatusChange(this);
+ }
+ d_func()->setThreadData_helper(currentData, targetData, bindingStatus);
locker.unlock();
// now currentData can commit suicide if it wants to
currentData->deref();
+ return true;
}
void QObjectPrivate::moveToThread_helper()
@@ -1581,16 +1721,22 @@ void QObjectPrivate::moveToThread_helper()
Q_Q(QObject);
QEvent e(QEvent::ThreadChange);
QCoreApplication::sendEvent(q, &e);
+ bindingStorage.clear();
for (int i = 0; i < children.size(); ++i) {
QObject *child = children.at(i);
child->d_func()->moveToThread_helper();
}
}
-void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
+void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status)
{
Q_Q(QObject);
+ if (status) {
+ // the new thread is already running
+ this->bindingStorage.bindingStatus = status;
+ }
+
// move posted events
int eventsMoved = 0;
for (int i = 0; i < currentData->postEventList.size(); ++i) {
@@ -1610,7 +1756,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
}
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
- ConnectionData *cd = connections.loadRelaxed();
+ ConnectionData *cd = connections.loadAcquire();
if (cd) {
if (cd->currentSender) {
cd->currentSender->receiverDeleted();
@@ -1645,23 +1791,10 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
for (int i = 0; i < children.size(); ++i) {
QObject *child = children.at(i);
- child->d_func()->setThreadData_helper(currentData, targetData);
- }
-}
-
-void QObjectPrivate::_q_reregisterTimers(void *pointer)
-{
- Q_Q(QObject);
- QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
- QAbstractEventDispatcher *eventDispatcher = threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
- for (int i = 0; i < timerList->size(); ++i) {
- const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
- eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
+ child->d_func()->setThreadData_helper(currentData, targetData, status);
}
- delete timerList;
}
-
//
// The timer flag hasTimer is set when startTimer is called.
// It is not reset when killing the timer because more than
@@ -1669,13 +1802,36 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
//
/*!
+ \fn int QObject::startTimer(int interval, Qt::TimerType timerType)
+
+ This is an overloaded function that will start a timer of type
+ \a timerType and a timeout of \a interval milliseconds. This is
+ equivalent to calling:
+ \code
+ startTimer(std::chrono::milliseconds{interval}, timerType);
+ \endcode
+
+ \sa timerEvent(), killTimer(), QChronoTimer::singleShot()
+*/
+
+int QObject::startTimer(int interval, Qt::TimerType timerType)
+{
+ // no overflow can happen here:
+ // 2^31 ms * 1,000,000 always fits a 64-bit signed integer type
+ return startTimer(std::chrono::milliseconds{interval}, timerType);
+}
+
+/*!
+ \since 5.9
+ \overload
+
Starts a timer and returns a timer identifier, or returns zero if
it could not start a timer.
- A timer event will occur every \a interval milliseconds until
- killTimer() is called. If \a interval is 0, then the timer event
- occurs once every time there are no more window system events to
- process.
+ A timer event will occur every \a interval until killTimer()
+ is called. If \a interval is equal to \c{std::chrono::duration::zero()},
+ then the timer event occurs once every time there are no more window
+ system events to process.
The virtual timerEvent() function is called with the QTimerEvent
event parameter class when a timer event occurs. Reimplement this
@@ -1688,26 +1844,41 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
\snippet code/src_corelib_kernel_qobject.cpp 8
- Note that QTimer's accuracy depends on the underlying operating system and
- hardware. The \a timerType argument allows you to customize the accuracy of
+ Note that the accuracy of QChronoTimer depends on the underlying operating
+ system and hardware.
+
+ The \a timerType argument allows you to customize the accuracy of
the timer. See Qt::TimerType for information on the different timer types.
Most platforms support an accuracy of 20 milliseconds; some provide more.
If Qt is unable to deliver the requested number of timer events, it will
silently discard some.
- The QTimer class provides a high-level programming interface with
- single-shot timers and timer signals instead of events. There is
- also a QBasicTimer class that is more lightweight than QTimer and
- less clumsy than using timer IDs directly.
+ The QTimer and QChronoTimer classes provide a high-level programming
+ interface with single-shot timers and timer signals instead of
+ events. There is also a QBasicTimer class that is more lightweight than
+ QChronoTimer but less clumsy than using timer IDs directly.
- \sa timerEvent(), killTimer(), QTimer::singleShot()
-*/
+ \sa timerEvent(), killTimer(), QChronoTimer::singleShot()
-int QObject::startTimer(int interval, Qt::TimerType timerType)
+ \note Starting from Qt 6.8 the type of \a interval
+ is \c std::chrono::nanoseconds, prior to that it was \c
+ std::chrono::milliseconds. This change is backwards compatible with
+ older releases of Qt.
+
+ \note In Qt 6.8, QObject was changed to use Qt::TimerId to represent timer
+ IDs. This method converts the TimerId to int for backwards compatibility
+ reasons, however you can use Qt::TimerId to check the value returned by
+ this method, for example:
+ \snippet code/src_corelib_kernel_qobject.cpp invalid-timer-id
+
+*/
+int QObject::startTimer(std::chrono::nanoseconds interval, Qt::TimerType timerType)
{
Q_D(QObject);
- if (Q_UNLIKELY(interval < 0)) {
+ using namespace std::chrono_literals;
+
+ if (Q_UNLIKELY(interval < 0ns)) {
qWarning("QObject::startTimer: Timers cannot have negative intervals");
return 0;
}
@@ -1721,53 +1892,15 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
qWarning("QObject::startTimer: Timers cannot be started from another thread");
return 0;
}
- int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this);
- if (!d->extraData)
- d->extraData = new QObjectPrivate::ExtraData;
+
+ auto dispatcher = thisThreadData->eventDispatcher.loadRelaxed();
+ Qt::TimerId timerId = dispatcher->registerTimer(interval, timerType, this);
+ d->ensureExtraData();
d->extraData->runningTimers.append(timerId);
- return timerId;
+ return int(timerId);
}
/*!
- \since 5.9
- \overload
- \fn int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType)
-
- Starts a timer and returns a timer identifier, or returns zero if
- it could not start a timer.
-
- A timer event will occur every \a time interval until killTimer()
- is called. If \a time is equal to \c{std::chrono::duration::zero()},
- then the timer event occurs once every time there are no more window
- system events to process.
-
- The virtual timerEvent() function is called with the QTimerEvent
- event parameter class when a timer event occurs. Reimplement this
- function to get timer events.
-
- If multiple timers are running, the QTimerEvent::timerId() can be
- used to find out which timer was activated.
-
- Example:
-
- \snippet code/src_corelib_kernel_qobject.cpp 8
-
- Note that QTimer's accuracy depends on the underlying operating system and
- hardware. The \a timerType argument allows you to customize the accuracy of
- the timer. See Qt::TimerType for information on the different timer types.
- Most platforms support an accuracy of 20 milliseconds; some provide more.
- If Qt is unable to deliver the requested number of timer events, it will
- silently discard some.
-
- The QTimer class provides a high-level programming interface with
- single-shot timers and timer signals instead of events. There is
- also a QBasicTimer class that is more lightweight than QTimer and
- less clumsy than using timer IDs directly.
-
- \sa timerEvent(), killTimer(), QTimer::singleShot()
-*/
-
-/*!
Kills the timer with timer identifier, \a id.
The timer identifier is returned by startTimer() when a timer
@@ -1778,17 +1911,26 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
void QObject::killTimer(int id)
{
+ killTimer(Qt::TimerId{id});
+}
+
+/*!
+ \since 6.8
+ \overload
+*/
+void QObject::killTimer(Qt::TimerId id)
+{
Q_D(QObject);
if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QObject::killTimer: Timers cannot be stopped from another thread");
return;
}
- if (id) {
+ if (id > Qt::TimerId::Invalid) {
int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
if (at == -1) {
// timer isn't owned by this object
qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
- id,
+ qToUnderlying(id),
this,
metaObject()->className(),
qUtf16Printable(objectName()));
@@ -1804,7 +1946,6 @@ void QObject::killTimer(int id)
}
}
-
/*!
\fn QObject *QObject::parent() const
@@ -1838,18 +1979,19 @@ void QObject::killTimer(int id)
/*!
- \fn template<typename T> T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const
+ \fn template<typename T> T *QObject::findChild(QAnyStringView name, Qt::FindChildOptions options) const
Returns the child of this object that can be cast into type T and
that is called \a name, or \nullptr if there is no such object.
- Omitting the \a name argument causes all object names to be matched.
+ A null \a name argument causes all objects to be matched. An empty,
+ non-null \a name matches only objects whose \l objectName is empty.
The search is performed recursively, unless \a options specifies the
option FindDirectChildrenOnly.
- If there is more than one child matching the search, the most
- direct ancestor is returned. If there are several direct
- ancestors, it is undefined which one will be returned. In that
- case, findChildren() should be used.
+ If there is more than one child matching the search, the most-direct
+ ancestor is returned. If there are several most-direct ancestors, the
+ first child in children() will be returned. In that case, it's better
+ to use findChildren() to get the complete list of all children.
This example returns a child \c{QPushButton} of \c{parentWidget}
named \c{"button1"}, even if the button isn't a direct child of
@@ -1871,15 +2013,37 @@ void QObject::killTimer(int id)
\snippet code/src_corelib_kernel_qobject.cpp 42
+ \note In Qt versions prior to 6.7, this function took \a name as
+ \c{QString}, not \c{QAnyStringView}.
+
\sa findChildren()
*/
/*!
- \fn template<typename T> QList<T> QObject::findChildren(const QString &name, Qt::FindChildOptions options) const
+ \fn template<typename T> T *QObject::findChild(Qt::FindChildOptions options) const
+ \overload
+ \since 6.7
+
+ Returns the child of this object that can be cast into type T, or
+ \nullptr if there is no such object.
+ The search is performed recursively, unless \a options specifies the
+ option FindDirectChildrenOnly.
+
+ If there is more than one child matching the search, the most-direct ancestor
+ is returned. If there are several most-direct ancestors, the first child in
+ children() will be returned. In that case, it's better to use findChildren()
+ to get the complete list of all children.
+
+ \sa findChildren()
+*/
+
+/*!
+ \fn template<typename T> QList<T> QObject::findChildren(QAnyStringView name, Qt::FindChildOptions options) const
Returns all children of this object with the given \a name that can be
cast to type T, or an empty list if there are no such objects.
- Omitting the \a name argument causes all object names to be matched.
+ A null \a name argument causes all objects to be matched, an empty one
+ only those whose objectName is empty.
The search is performed recursively, unless \a options specifies the
option FindDirectChildrenOnly.
@@ -1896,11 +2060,27 @@ void QObject::killTimer(int id)
\snippet code/src_corelib_kernel_qobject.cpp 43
+ \note In Qt versions prior to 6.7, this function took \a name as
+ \c{QString}, not \c{QAnyStringView}.
+
+ \sa findChild()
+*/
+
+/*!
+ \fn template<typename T> QList<T> QObject::findChildren(Qt::FindChildOptions options) const
+ \overload
+ \since 6.3
+
+ Returns all children of this object that can be cast to type T, or
+ an empty list if there are no such objects.
+ The search is performed recursively, unless \a options specifies the
+ option FindDirectChildrenOnly.
+
\sa findChild()
*/
/*!
- \fn QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const
+ \fn template<typename T> QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const
\overload findChildren()
\since 5.0
@@ -1916,7 +2096,7 @@ void QObject::killTimer(int id)
\fn template<typename T> T qFindChild(const QObject *obj, const QString &name)
\relates QObject
\overload qFindChildren()
- \obsolete
+ \deprecated
This function is equivalent to
\a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
@@ -1932,7 +2112,7 @@ void QObject::killTimer(int id)
\fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QString &name)
\relates QObject
\overload qFindChildren()
- \obsolete
+ \deprecated
This function is equivalent to
\a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
@@ -1944,22 +2124,24 @@ void QObject::killTimer(int id)
\sa QObject::findChildren()
*/
+static bool matches_objectName_non_null(QObject *obj, QAnyStringView name)
+{
+ if (auto ext = QObjectPrivate::get(obj)->extraData)
+ return ext ->objectName.valueBypassingBindings() == name;
+ return name.isEmpty();
+}
+
/*!
\internal
*/
-void qt_qFindChildren_helper(const QObject *parent, const QString &name,
+void qt_qFindChildren_helper(const QObject *parent, QAnyStringView name,
const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
{
- if (!parent || !list)
- return;
- const QObjectList &children = parent->children();
- QObject *obj;
- for (int i = 0; i < children.size(); ++i) {
- obj = children.at(i);
- if (mo.cast(obj)) {
- if (name.isNull() || obj->objectName() == name)
- list->append(obj);
- }
+ Q_ASSERT(parent);
+ Q_ASSERT(list);
+ for (QObject *obj : parent->children()) {
+ if (mo.cast(obj) && (name.isNull() || matches_objectName_non_null(obj, name)))
+ list->append(obj);
if (options & Qt::FindChildrenRecursively)
qt_qFindChildren_helper(obj, name, mo, list, options);
}
@@ -1972,12 +2154,9 @@ void qt_qFindChildren_helper(const QObject *parent, const QString &name,
void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
{
- if (!parent || !list)
- return;
- const QObjectList &children = parent->children();
- QObject *obj;
- for (int i = 0; i < children.size(); ++i) {
- obj = children.at(i);
+ Q_ASSERT(parent);
+ Q_ASSERT(list);
+ for (QObject *obj : parent->children()) {
if (mo.cast(obj)) {
QRegularExpressionMatch m = re.match(obj->objectName());
if (m.hasMatch())
@@ -1991,23 +2170,17 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re
/*!
\internal
- */
-QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options)
+*/
+QObject *qt_qFindChild_helper(const QObject *parent, QAnyStringView name, const QMetaObject &mo, Qt::FindChildOptions options)
{
- if (!parent)
- return nullptr;
- const QObjectList &children = parent->children();
- QObject *obj;
- int i;
- for (i = 0; i < children.size(); ++i) {
- obj = children.at(i);
- if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
- return obj;
+ Q_ASSERT(parent);
+ for (QObject *obj : parent->children()) {
+ if (mo.cast(obj) && (name.isNull() || matches_objectName_non_null(obj, name)))
+ return obj;
}
if (options & Qt::FindChildrenRecursively) {
- for (i = 0; i < children.size(); ++i) {
- obj = qt_qFindChild_helper(children.at(i), name, mo, options);
- if (obj)
+ for (QObject *child : parent->children()) {
+ if (QObject *obj = qt_qFindChild_helper(child, name, mo, options))
return obj;
}
}
@@ -2033,9 +2206,9 @@ void QObjectPrivate::deleteChildren()
// delete children objects
// don't use qDeleteAll as the destructor of the child might
// delete siblings
- for (int i = 0; i < children.count(); ++i) {
+ for (int i = 0; i < children.size(); ++i) {
currentChildBeingDeleted = children.at(i);
- children[i] = 0;
+ children[i] = nullptr;
delete currentChildBeingDeleted;
}
children.clear();
@@ -2076,7 +2249,7 @@ void QObjectPrivate::setParent_helper(QObject *o)
if (index < 0) {
// we're probably recursing into setParent() from a ChildRemoved event, don't do anything
} else if (parentD->isDeletingChildren) {
- parentD->children[index] = 0;
+ parentD->children[index] = nullptr;
} else {
parentD->children.removeAt(index);
if (sendChildEvents && parentD->receiveChildEvents) {
@@ -2086,24 +2259,36 @@ void QObjectPrivate::setParent_helper(QObject *o)
}
}
}
+
+ if (receiveParentEvents) {
+ Q_ASSERT(!isWidget); // Handled in QWidget
+ QEvent e(QEvent::ParentAboutToChange);
+ QCoreApplication::sendEvent(q, &e);
+ }
+
parent = o;
+
if (parent) {
// object hierarchies are constrained to a single thread
- if (threadData != parent->d_func()->threadData) {
+ if (threadData.loadRelaxed() != parent->d_func()->threadData.loadRelaxed()) {
qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
parent = nullptr;
return;
}
parent->d_func()->children.append(q);
- if(sendChildEvents && parent->d_func()->receiveChildEvents) {
+ if (sendChildEvents && parent->d_func()->receiveChildEvents) {
if (!isWidget) {
QChildEvent e(QEvent::ChildAdded, q);
QCoreApplication::sendEvent(parent, &e);
}
}
}
- if (!wasDeleted && !isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged)
- QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
+
+ if (receiveParentEvents) {
+ Q_ASSERT(!isWidget); // Handled in QWidget
+ QEvent e(QEvent::ParentChange);
+ QCoreApplication::sendEvent(q, &e);
+ }
}
/*!
@@ -2122,6 +2307,9 @@ void QObjectPrivate::setParent_helper(QObject *o)
If multiple event filters are installed on a single object, the
filter that was installed last is activated first.
+ If \a filterObj has already been installed for this object,
+ this function moves it so it acts as if it was installed last.
+
Here's a \c KeyPressEater class that eats the key presses of its
monitored objects:
@@ -2153,17 +2341,16 @@ void QObject::installEventFilter(QObject *obj)
Q_D(QObject);
if (!obj)
return;
- if (d->threadData != obj->d_func()->threadData) {
+ if (d->threadData.loadRelaxed() != obj->d_func()->threadData.loadRelaxed()) {
qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
return;
}
- if (!d->extraData)
- d->extraData = new QObjectPrivate::ExtraData;
+ d->ensureExtraData();
- // clean up unused items in the list
- d->extraData->eventFilters.removeAll((QObject*)nullptr);
- d->extraData->eventFilters.removeAll(obj);
+ // clean up unused items in the list along the way:
+ auto isNullOrEquals = [](auto obj) { return [obj](const auto &p) { return !p || p == obj; }; };
+ d->extraData->eventFilters.removeIf(isNullOrEquals(obj));
d->extraData->eventFilters.prepend(obj);
}
@@ -2184,14 +2371,15 @@ void QObject::removeEventFilter(QObject *obj)
{
Q_D(QObject);
if (d->extraData) {
- for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {
- if (d->extraData->eventFilters.at(i) == obj)
- d->extraData->eventFilters[i] = nullptr;
+ for (auto &filter : d->extraData->eventFilters) {
+ if (filter == obj) {
+ filter = nullptr;
+ break;
+ }
}
}
}
-
/*!
\fn void QObject::destroyed(QObject *obj)
@@ -2216,7 +2404,7 @@ void QObject::removeEventFilter(QObject *obj)
QCoreApplication::exec()), the object will be deleted once the
event loop is started. If deleteLater() is called after the main event loop
has stopped, the object will not be deleted.
- Since Qt 4.8, if deleteLater() is called on an object that lives in a
+ If deleteLater() is called on an object that lives in a
thread with no running event loop, the object will be destroyed when the
thread finishes.
@@ -2227,15 +2415,85 @@ void QObject::removeEventFilter(QObject *obj)
event loop was still running: the Qt event loop will delete those objects
as soon as the new nested event loop starts.
- \b{Note:} It is safe to call this function more than once; when the
- first deferred deletion event is delivered, any pending events for the
- object are removed from the event queue.
+ In situations where Qt is not driving the event dispatcher via e.g.
+ QCoreApplication::exec() or QEventLoop::exec(), deferred deletes
+ will not be processed automatically. To ensure deferred deletion in
+ this scenario, the following workaround can be used:
+
+ \code
+ const auto *eventDispatcher = QThread::currentThread()->eventDispatcher();
+ QObject::connect(eventDispatcher, &QAbstractEventDispatcher::aboutToBlock,
+ QThread::currentThread(), []{
+ if (QThread::currentThread()->loopLevel() == 0)
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ }
+ );
+ \endcode
\sa destroyed(), QPointer
*/
void QObject::deleteLater()
{
- QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
+#ifdef QT_DEBUG
+ if (qApp == this)
+ qWarning("You are deferring the delete of QCoreApplication, this may not work as expected.");
+#endif
+
+
+ // De-bounce QDeferredDeleteEvents. Use the post event list mutex
+ // to guard access to deleteLaterCalled, so we don't need a separate
+ // mutex in QObjectData.
+ auto eventListLocker = QCoreApplicationPrivate::lockThreadPostEventList(this);
+ if (!eventListLocker.threadData)
+ return;
+
+ // FIXME: The deleteLaterCalled flag is part of a bit field,
+ // so we likely have data races here, even with the mutex above,
+ // as long as we're not guarding every access to the bit field.
+
+ Q_D(QObject);
+ if (d->deleteLaterCalled) {
+ qCDebug(lcDeleteLater) << "Skipping deleteLater for already deferred object" << this;
+ return;
+ }
+
+ d->deleteLaterCalled = true;
+
+ int loopLevel = 0;
+ int scopeLevel = 0;
+
+ auto *objectThreadData = eventListLocker.threadData;
+ if (objectThreadData == QThreadData::current()) {
+ // Remember the current running eventloop for deleteLater
+ // calls in the object's own thread.
+
+ // Events sent by non-Qt event handlers (such as glib) may not
+ // have the scopeLevel set correctly. The scope level makes sure that
+ // code like this:
+ // foo->deleteLater();
+ // qApp->processEvents(); // without passing QEvent::DeferredDelete
+ // will not cause "foo" to be deleted before returning to the event loop.
+
+ loopLevel = objectThreadData->loopLevel;
+ scopeLevel = objectThreadData->scopeLevel;
+
+ // If the scope level is 0 while loopLevel != 0, we are called from a
+ // non-conformant code path, and our best guess is that the scope level
+ // should be 1. (Loop level 0 is special: it means that no event loops
+ // are running.)
+ if (scopeLevel == 0 && loopLevel != 0) {
+ qCDebug(lcDeleteLater) << "Delete later called with scope level 0"
+ << "but loop level is > 0. Assuming scope is 1";
+ scopeLevel = 1;
+ }
+ }
+
+ qCDebug(lcDeleteLater) << "Posting deferred delete for" << this
+ << "with loop level" << loopLevel << "and scope level" << scopeLevel;
+
+ eventListLocker.unlock();
+ QCoreApplication::postEvent(this,
+ new QDeferredDeleteEvent(loopLevel, scopeLevel));
}
/*!
@@ -2248,13 +2506,12 @@ void QObject::deleteLater()
translated string is available.
Example:
- \snippet ../widgets/mainwindows/sdi/mainwindow.cpp implicit tr context
+ \snippet ../widgets/itemviews/spreadsheet/spreadsheet.cpp implicit tr context
\dots
If the same \a sourceText is used in different roles within the
same context, an additional identifying string may be passed in
- \a disambiguation (\nullptr by default). In Qt 4.4 and earlier, this was
- the preferred way to pass comments to translators.
+ \a disambiguation (\nullptr by default).
Example:
@@ -2263,8 +2520,8 @@ void QObject::deleteLater()
See \l{Writing Source Code for Translation} for a detailed description of
Qt's translation mechanisms in general, and the
- \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
- section for information on disambiguation.
+ \l{Writing Source Code for Translation#Disambiguate Identical Text}
+ {Disambiguate Identical Text} section for information on disambiguation.
\warning This method is reentrant only if all translators are
installed \e before calling this method. Installing or removing
@@ -2274,43 +2531,31 @@ void QObject::deleteLater()
\sa QCoreApplication::translate(), {Internationalization with Qt}
*/
-/*!
- \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
- \reentrant
- \obsolete
-
- Returns a translated version of \a sourceText, or
- QString::fromUtf8(\a sourceText) if there is no appropriate
- version. It is otherwise identical to tr(\a sourceText, \a
- disambiguation, \a n).
-
- \warning This method is reentrant only if all translators are
- installed \e before calling this method. Installing or removing
- translators while performing translations is not supported. Doing
- so will probably result in crashes or other undesirable behavior.
-
- \warning For portability reasons, we recommend that you use
- escape sequences for specifying non-ASCII characters in string
- literals to trUtf8(). For example:
-
- \snippet code/src_corelib_kernel_qobject.cpp 20
-
- \sa tr(), QCoreApplication::translate(), {Internationalization with Qt}
-*/
-
-
-
-
/*****************************************************************************
Signals and slots
*****************************************************************************/
+namespace {
+// This class provides (per-thread) storage for qFlagLocation()
+class FlaggedDebugSignatures
+{
+ uint idx = 0;
+ std::array<const char *, 2> locations = {}; // one for the SIGNAL, one for the SLOT
+
+public:
+ void store(const char* method) noexcept
+ { locations[idx++ % locations.size()] = method; }
+
+ bool contains(const char *method) const noexcept
+ { return std::find(locations.begin(), locations.end(), method) != locations.end(); }
+};
+
+Q_CONSTINIT static thread_local FlaggedDebugSignatures flaggedSignatures = {};
+} // unnamed namespace
const char *qFlagLocation(const char *method)
{
- QThreadData *currentThreadData = QThreadData::current(false);
- if (currentThreadData != nullptr)
- currentThreadData->flaggedSignatures.store(method);
+ flaggedSignatures.store(method);
return method;
}
@@ -2320,9 +2565,9 @@ static int extract_code(const char *member)
return (((int)(*member) - '0') & 0x3);
}
-static const char * extract_location(const char *member)
+static const char *extract_location(const char *member)
{
- if (QThreadData::current()->flaggedSignatures.contains(member)) {
+ if (flaggedSignatures.contains(member)) {
// signature includes location information after the first null-terminator
const char *location = member + qstrlen(member) + 1;
if (*location != '\0')
@@ -2337,27 +2582,29 @@ static bool check_signal_macro(const QObject *sender, const char *signal,
int sigcode = extract_code(signal);
if (sigcode != QSIGNAL_CODE) {
if (sigcode == QSLOT_CODE)
- qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
- func, op, sender->metaObject()->className(), signal+1);
+ qCWarning(lcConnect, "QObject::%s: Attempt to %s non-signal %s::%s", func, op,
+ sender->metaObject()->className(), signal + 1);
else
- qWarning("QObject::%s: Use the SIGNAL macro to %s %s::%s",
- func, op, sender->metaObject()->className(), signal);
+ qCWarning(lcConnect, "QObject::%s: Use the SIGNAL macro to %s %s::%s", func, op,
+ sender->metaObject()->className(), signal);
return false;
}
return true;
}
-static bool check_method_code(int code, const QObject *object,
- const char *method, const char *func)
+static bool check_method_code(int code, const QObject *object, const char *method, const char *func)
{
if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
- qWarning("QObject::%s: Use the SLOT or SIGNAL macro to "
- "%s %s::%s", func, func, object->metaObject()->className(), method);
+ qCWarning(lcConnect,
+ "QObject::%s: Use the SLOT or SIGNAL macro to "
+ "%s %s::%s",
+ func, func, object->metaObject()->className(), method);
return false;
}
return true;
}
+Q_DECL_COLD_FUNCTION
static void err_method_notfound(const QObject *object,
const char *method, const char *func)
{
@@ -2367,28 +2614,23 @@ static void err_method_notfound(const QObject *object,
case QSIGNAL_CODE: type = "signal"; break;
}
const char *loc = extract_location(method);
- if (strchr(method,')') == nullptr) // common typing mistake
- qWarning("QObject::%s: Parentheses expected, %s %s::%s%s%s",
- func, type, object->metaObject()->className(), method+1,
- loc ? " in ": "", loc ? loc : "");
+ if (strchr(method, ')') == nullptr) // common typing mistake
+ qCWarning(lcConnect, "QObject::%s: Parentheses expected, %s %s::%s%s%s", func, type,
+ object->metaObject()->className(), method + 1, loc ? " in " : "", loc ? loc : "");
else
- qWarning("QObject::%s: No such %s %s::%s%s%s",
- func, type, object->metaObject()->className(), method+1,
- loc ? " in ": "", loc ? loc : "");
-
+ qCWarning(lcConnect, "QObject::%s: No such %s %s::%s%s%s", func, type,
+ object->metaObject()->className(), method + 1, loc ? " in " : "", loc ? loc : "");
}
-
-static void err_info_about_objects(const char * func,
- const QObject * sender,
- const QObject * receiver)
+Q_DECL_COLD_FUNCTION
+static void err_info_about_objects(const char *func, const QObject *sender, const QObject *receiver)
{
QString a = sender ? sender->objectName() : QString();
QString b = receiver ? receiver->objectName() : QString();
if (!a.isEmpty())
- qWarning("QObject::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
+ qCWarning(lcConnect, "QObject::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
if (!b.isEmpty())
- qWarning("QObject::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
+ qCWarning(lcConnect, "QObject::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
}
/*!
@@ -2417,7 +2659,7 @@ QObject *QObject::sender() const
{
Q_D(const QObject);
- QBasicMutexLocker locker(signalSlotLock(this));
+ QMutexLocker locker(signalSlotLock(this));
QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
if (!cd || !cd->currentSender)
return nullptr;
@@ -2459,7 +2701,7 @@ int QObject::senderSignalIndex() const
{
Q_D(const QObject);
- QBasicMutexLocker locker(signalSlotLock(this));
+ QMutexLocker locker(signalSlotLock(this));
QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
if (!cd || !cd->currentSender)
return -1;
@@ -2510,7 +2752,7 @@ int QObject::receivers(const char *signal) const
int signal_index = d->signalIndex(signal);
if (signal_index < 0) {
#ifndef QT_NO_DEBUG
- err_method_notfound(this, signal-1, "receivers");
+ err_method_notfound(this, signal - 1, "receivers");
#endif
return 0;
}
@@ -2518,13 +2760,13 @@ int QObject::receivers(const char *signal) const
if (!d->isSignalConnected(signal_index))
return receivers;
- if (d->declarativeData && QAbstractDeclarativeData::receivers) {
+ if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::receivers) {
receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
signal_index);
}
+ QMutexLocker locker(signalSlotLock(this));
QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
- QBasicMutexLocker locker(signalSlotLock(this));
if (cd && signal_index < cd->signalVectorCount()) {
const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
while (c) {
@@ -2546,13 +2788,15 @@ int QObject::receivers(const char *signal) const
\snippet code/src_corelib_kernel_qobject.cpp 49
- As the code snippet above illustrates, you can use this function
- to avoid emitting a signal that nobody listens to.
+ As the code snippet above illustrates, you can use this function to avoid
+ expensive initialization or emitting a signal that nobody listens to.
+ However, in a multithreaded application, connections might change after
+ this function returns and before the signal gets emitted.
\warning This function violates the object-oriented principle of
- modularity. However, it might be useful when you need to perform
- expensive initialization only if something is connected to a
- signal.
+ modularity. In particular, this function must not be called from an
+ override of connectNotify() or disconnectNotify(), as those might get
+ called from any thread.
*/
bool QObject::isSignalConnected(const QMetaMethod &signal) const
{
@@ -2569,7 +2813,7 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const
signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj);
- QBasicMutexLocker locker(signalSlotLock(this));
+ QMutexLocker locker(signalSlotLock(this));
return d->isSignalConnected(signalIndex, true);
}
@@ -2631,13 +2875,13 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
{
if (signal.attributes() & QMetaMethod::Compatibility) {
if (!(method.attributes() & QMetaMethod::Compatibility))
- qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
- sender->className(), signal.methodSignature().constData());
- } else if ((method.attributes() & QMetaMethod::Compatibility) &&
- method.methodType() == QMetaMethod::Signal) {
- qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
- sender->className(), signal.methodSignature().constData(),
- receiver->className(), method.methodSignature().constData());
+ qCWarning(lcConnect, "QObject::connect: Connecting from COMPAT signal (%s::%s)",
+ sender->className(), signal.methodSignature().constData());
+ } else if ((method.attributes() & QMetaMethod::Compatibility)
+ && method.methodType() == QMetaMethod::Signal) {
+ qCWarning(lcConnect, "QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
+ sender->className(), signal.methodSignature().constData(), receiver->className(),
+ method.methodSignature().constData());
}
}
#endif
@@ -2714,15 +2958,15 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
{Differences between String-Based and Functor-Based Connections}
*/
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
- const QObject *receiver, const char *method,
- Qt::ConnectionType type)
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
{
if (sender == nullptr || receiver == nullptr || signal == nullptr || method == nullptr) {
- qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
- sender ? sender->metaObject()->className() : "(nullptr)",
- (signal && *signal) ? signal+1 : "(nullptr)",
- receiver ? receiver->metaObject()->className() : "(nullptr)",
- (method && *method) ? method+1 : "(nullptr)");
+ qCWarning(lcConnect, "QObject::connect: Cannot connect %s::%s to %s::%s",
+ sender ? sender->metaObject()->className() : "(nullptr)",
+ (signal && *signal) ? signal + 1 : "(nullptr)",
+ receiver ? receiver->metaObject()->className() : "(nullptr)",
+ (method && *method) ? method + 1 : "(nullptr)");
return QMetaObject::Connection(nullptr);
}
QByteArray tmp_signal_name;
@@ -2731,7 +2975,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
return QMetaObject::Connection(nullptr);
const QMetaObject *smeta = sender->metaObject();
const char *signal_arg = signal;
- ++signal; //skip code
+ ++signal; // skip code
QArgumentTypeArray signalTypes;
Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
@@ -2808,10 +3052,11 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
if (!QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
methodTypes.size(), methodTypes.constData())) {
- qWarning("QObject::connect: Incompatible sender/receiver arguments"
- "\n %s::%s --> %s::%s",
- sender->metaObject()->className(), signal,
- receiver->metaObject()->className(), method);
+ qCWarning(lcConnect,
+ "QObject::connect: Incompatible sender/receiver arguments"
+ "\n %s::%s --> %s::%s",
+ sender->metaObject()->className(), signal, receiver->metaObject()->className(),
+ method);
return QMetaObject::Connection(nullptr);
}
@@ -2859,11 +3104,11 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
|| receiver == nullptr
|| signal.methodType() != QMetaMethod::Signal
|| method.methodType() == QMetaMethod::Constructor) {
- qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
- sender ? sender->metaObject()->className() : "(nullptr)",
- signal.methodSignature().constData(),
- receiver ? receiver->metaObject()->className() : "(nullptr)",
- method.methodSignature().constData() );
+ qCWarning(lcConnect, "QObject::connect: Cannot connect %s::%s to %s::%s",
+ sender ? sender->metaObject()->className() : "(nullptr)",
+ signal.methodSignature().constData(),
+ receiver ? receiver->metaObject()->className() : "(nullptr)",
+ method.methodSignature().constData());
return QMetaObject::Connection(nullptr);
}
@@ -2878,27 +3123,28 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
const QMetaObject *smeta = sender->metaObject();
const QMetaObject *rmeta = receiver->metaObject();
if (signal_index == -1) {
- qWarning("QObject::connect: Can't find signal %s on instance of class %s",
- signal.methodSignature().constData(), smeta->className());
+ qCWarning(lcConnect, "QObject::connect: Can't find signal %s on instance of class %s",
+ signal.methodSignature().constData(), smeta->className());
return QMetaObject::Connection(nullptr);
}
if (method_index == -1) {
- qWarning("QObject::connect: Can't find method %s on instance of class %s",
- method.methodSignature().constData(), rmeta->className());
+ qCWarning(lcConnect, "QObject::connect: Can't find method %s on instance of class %s",
+ method.methodSignature().constData(), rmeta->className());
return QMetaObject::Connection(nullptr);
}
- if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
- qWarning("QObject::connect: Incompatible sender/receiver arguments"
- "\n %s::%s --> %s::%s",
- smeta->className(), signal.methodSignature().constData(),
- rmeta->className(), method.methodSignature().constData());
+ if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(),
+ method.methodSignature().constData())) {
+ qCWarning(lcConnect,
+ "QObject::connect: Incompatible sender/receiver arguments"
+ "\n %s::%s --> %s::%s",
+ smeta->className(), signal.methodSignature().constData(), rmeta->className(),
+ method.methodSignature().constData());
return QMetaObject::Connection(nullptr);
}
int *types = nullptr;
- if ((type == Qt::QueuedConnection)
- && !(types = queuedConnectionTypes(signal.parameterTypes())))
+ if ((type == Qt::QueuedConnection) && !(types = queuedConnectionTypes(signal)))
return QMetaObject::Connection(nullptr);
#ifndef QT_NO_DEBUG
@@ -2983,13 +3229,15 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
if \a receiver is left out, so you cannot disconnect a
specifically-named slot on all objects.
+ \include includes/qobject.qdocinc disconnect-all
+
\sa connect()
*/
bool QObject::disconnect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method)
{
if (sender == nullptr || (receiver == nullptr && method != nullptr)) {
- qWarning("QObject::disconnect: Unexpected nullptr parameter");
+ qCWarning(lcConnect, "QObject::disconnect: Unexpected nullptr parameter");
return false;
}
@@ -3086,7 +3334,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
}
if (res) {
if (!signal)
- const_cast<QObject*>(sender)->disconnectNotify(QMetaMethod());
+ const_cast<QObject *>(sender)->disconnectNotify(QMetaMethod());
}
return res;
}
@@ -3118,39 +3366,33 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
In the same way \nullptr can be used for \a receiver in the meaning "any receiving object".
In this case method should also be QMetaMethod(). \a sender parameter should be never \nullptr.
+ \include includes/qobject.qdocinc disconnect-all
+
\sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
*/
bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method)
{
if (sender == nullptr || (receiver == nullptr && method.mobj != nullptr)) {
- qWarning("QObject::disconnect: Unexpected nullptr parameter");
+ qCWarning(lcConnect, "QObject::disconnect: Unexpected nullptr parameter");
return false;
}
if (signal.mobj) {
- if(signal.methodType() != QMetaMethod::Signal) {
- qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
+ if (signal.methodType() != QMetaMethod::Signal) {
+ qCWarning(lcConnect, "QObject::%s: Attempt to %s non-signal %s::%s",
"disconnect","unbind",
sender->metaObject()->className(), signal.methodSignature().constData());
return false;
}
}
if (method.mobj) {
- if(method.methodType() == QMetaMethod::Constructor) {
- qWarning("QObject::disconnect: cannot use constructor as argument %s::%s",
- receiver->metaObject()->className(), method.methodSignature().constData());
+ if (method.methodType() == QMetaMethod::Constructor) {
+ qCWarning(lcConnect, "QObject::disconnect: cannot use constructor as argument %s::%s",
+ receiver->metaObject()->className(), method.methodSignature().constData());
return false;
}
}
- // Reconstructing SIGNAL() macro result for signal.methodSignature() string
- QByteArray signalSignature;
- if (signal.mobj) {
- signalSignature.reserve(signal.methodSignature().size()+1);
- signalSignature.append((char)(QSIGNAL_CODE + '0'));
- signalSignature.append(signal.methodSignature());
- }
-
int signal_index;
int method_index;
{
@@ -3161,14 +3403,14 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
// If we are here sender is not nullptr. If signal is not nullptr while signal_index
// is -1 then this signal is not a member of sender.
if (signal.mobj && signal_index == -1) {
- qWarning("QObject::disconnect: signal %s not found on class %s",
- signal.methodSignature().constData(), sender->metaObject()->className());
+ qCWarning(lcConnect, "QObject::disconnect: signal %s not found on class %s",
+ signal.methodSignature().constData(), sender->metaObject()->className());
return false;
}
// If this condition is true then method is not a member of receiver.
if (receiver && method.mobj && method_index == -1) {
- qWarning("QObject::disconnect: method %s not found on class %s",
- method.methodSignature().constData(), receiver->metaObject()->className());
+ qCWarning(lcConnect, "QObject::disconnect: method %s not found on class %s",
+ method.methodSignature().constData(), receiver->metaObject()->className());
return false;
}
@@ -3180,7 +3422,7 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
// QMetaObjectPrivate::disconnect() doesn't call disconnectNotify()
// per connection in this case. Call it once now, with an invalid
// QMetaMethod as argument, as documented.
- const_cast<QObject*>(sender)->disconnectNotify(signal);
+ const_cast<QObject *>(sender)->disconnectNotify(signal);
}
return true;
}
@@ -3195,6 +3437,8 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
A signal-slot connection is removed when either of the objects
involved are destroyed.
+
+ \include includes/qobject.qdocinc disconnect-all
*/
/*!
@@ -3226,8 +3470,13 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
signal.
\warning This function is called from the thread which performs the
- connection, which may be a different thread from the thread in
- which this object lives.
+ connection, which may be a different thread from the thread in which
+ this object lives. This function may also be called with a QObject internal
+ mutex locked. It is therefore not allowed to re-enter any QObject
+ functions, including isSignalConnected(), from your reimplementation. If
+ you lock a mutex in your reimplementation, make sure that you don't call
+ QObject functions with that mutex held in other places or it will result in
+ a deadlock.
\sa connect(), disconnectNotify()
*/
@@ -3256,12 +3505,12 @@ void QObject::connectNotify(const QMetaMethod &signal)
expensive resources.
\warning This function is called from the thread which performs the
- disconnection, which may be a different thread from the thread in
- which this object lives. This function may also be called with a QObject
- internal mutex locked. It is therefore not allowed to re-enter any
- of any QObject functions from your reimplementation and if you lock
- a mutex in your reimplementation, make sure that you don't call QObject
- functions with that mutex held in other places or it will result in
+ disconnection, which may be a different thread from the thread in which
+ this object lives. This function may also be called with a QObject internal
+ mutex locked. It is therefore not allowed to re-enter any QObject
+ functions, including isSignalConnected(), from your reimplementation. If
+ you lock a mutex in your reimplementation, make sure that you don't call
+ QObject functions with that mutex held in other places or it will result in
a deadlock.
\sa disconnect(), connectNotify()
@@ -3305,7 +3554,8 @@ static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
from the sender to the receiver's slot
*/
QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index, int type, int *types)
+ const QObject *receiver, int method_index, int type,
+ int *types)
{
const QMetaObject *smeta = sender->metaObject();
signal_index = methodIndexToSignalIndex(&smeta, signal_index);
@@ -3351,14 +3601,20 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
c2 = c2->nextConnectionList.loadRelaxed();
}
}
- type &= Qt::UniqueConnection - 1;
}
+ type &= ~Qt::UniqueConnection;
+
+ const bool isSingleShot = type & Qt::SingleShotConnection;
+ type &= ~Qt::SingleShotConnection;
+
+ Q_ASSERT(type >= 0);
+ Q_ASSERT(type <= 3);
std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
c->sender = s;
c->signal_index = signal_index;
c->receiver.storeRelaxed(r);
- QThreadData *td = r->d_func()->threadData;
+ QThreadData *td = r->d_func()->threadData.loadAcquire();
td->ref();
c->receiverThreadData.storeRelaxed(td);
c->method_relative = method_index;
@@ -3367,6 +3623,7 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
c->isSlotObject = false;
c->argumentTypes.storeRelaxed(types);
c->callFunction = callFunction;
+ c->isSingleShot = isSingleShot;
QObjectPrivate::get(s)->addConnection(signal_index, c.get());
@@ -3462,9 +3719,9 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender,
QObject *s = const_cast<QObject *>(sender);
QBasicMutex *senderMutex = signalSlotLock(sender);
- QBasicMutexLocker locker(senderMutex);
+ QMutexLocker locker(senderMutex);
- QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
+ QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
if (!scd)
return false;
@@ -3554,7 +3811,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
const QMetaObject *mo = o->metaObject();
Q_ASSERT(mo);
const QObjectList list = // list of all objects to look for matching signals including...
- o->findChildren<QObject *>(QString()) // all children of 'o'...
+ o->findChildren<QObject *>() // all children of 'o'...
<< o; // and the object 'o' itself
// for each method/slot of o ...
@@ -3569,7 +3826,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
// ...we check each object in our list, ...
bool foundIt = false;
- for(int j = 0; j < list.count(); ++j) {
+ for (int j = 0; j < list.size(); ++j) {
const QObject *co = list.at(j);
const QByteArray coName = co->objectName().toLatin1();
@@ -3589,7 +3846,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
// chosen 'at random' (order of declaration in source file)
QList<QByteArray> compatibleSignals;
const QMetaObject *smo = co->metaObject();
- int sigLen = qstrlen(signal) - 1; // ignore the trailing ')'
+ int sigLen = int(qstrlen(signal)) - 1; // ignore the trailing ')'
for (int k = QMetaObjectPrivate::absoluteSignalCount(smo)-1; k >= 0; --k) {
const QMetaMethod method = QMetaObjectPrivate::signal(smo, k);
if (!qstrncmp(method.methodSignature().constData(), signal, sigLen)) {
@@ -3599,7 +3856,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
}
}
if (compatibleSignals.size() > 1)
- qWarning() << "QMetaObject::connectSlotsByName: Connecting slot" << slot
+ qCWarning(lcConnectSlotsByName) << "QMetaObject::connectSlotsByName: Connecting slot" << slot
<< "with the first of the following compatible signals:" << compatibleSignals;
}
@@ -3609,7 +3866,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
// we connect it...
if (Connection(QMetaObjectPrivate::connect(co, sigIndex, smeta, o, i))) {
foundIt = true;
- qCDebug(lcConnections, "%s",
+ qCDebug(lcConnectSlotsByName, "%s",
msgConnect(smeta, coName, QMetaObjectPrivate::signal(smeta, sigIndex), o, i).constData());
// ...and stop looking for further objects with the same name.
// Note: the Designer will make sure each object name is unique in the above
@@ -3621,18 +3878,47 @@ void QMetaObject::connectSlotsByName(QObject *o)
if (foundIt) {
// we found our slot, now skip all overloads
while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
- ++i;
+ ++i;
} else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
// check if the slot has the following signature: "on_..._...(..."
int iParen = slotSignature.indexOf('(');
- int iLastUnderscore = slotSignature.lastIndexOf('_', iParen-1);
+ int iLastUnderscore = slotSignature.lastIndexOf('_', iParen - 1);
if (iLastUnderscore > 3)
- qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
+ qCWarning(lcConnectSlotsByName,
+ "QMetaObject::connectSlotsByName: No matching signal for %s", slot);
}
}
}
/*!
+ \internal
+ A small RAII helper for QSlotObjectBase.
+ Calls ref on construction and destroyLastRef in its dtor.
+ Allows construction from a nullptr in which case it does nothing.
+ */
+struct SlotObjectGuard {
+ SlotObjectGuard() = default;
+ // move would be fine, but we do not need it currently
+ Q_DISABLE_COPY_MOVE(SlotObjectGuard)
+ Q_NODISCARD_CTOR explicit SlotObjectGuard(QtPrivate::QSlotObjectBase *slotObject)
+ : m_slotObject(slotObject)
+ {
+ if (m_slotObject)
+ m_slotObject->ref();
+ }
+
+ QtPrivate::QSlotObjectBase const *operator->() const
+ { return m_slotObject.get(); }
+
+ QtPrivate::QSlotObjectBase *operator->()
+ { return m_slotObject.get(); }
+
+ ~SlotObjectGuard() = default;
+private:
+ QtPrivate::SlotObjUniquePtr m_slotObject;
+};
+
+/*!
\internal
\a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
@@ -3642,28 +3928,29 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
const int *argumentTypes = c->argumentTypes.loadRelaxed();
if (!argumentTypes) {
QMetaMethod m = QMetaObjectPrivate::signal(sender->metaObject(), signal);
- argumentTypes = queuedConnectionTypes(m.parameterTypes());
+ argumentTypes = queuedConnectionTypes(m);
if (!argumentTypes) // cannot queue arguments
argumentTypes = &DIRECT_CONNECTION_ONLY;
if (!c->argumentTypes.testAndSetOrdered(nullptr, argumentTypes)) {
if (argumentTypes != &DIRECT_CONNECTION_ONLY)
- delete [] argumentTypes;
+ delete[] argumentTypes;
argumentTypes = c->argumentTypes.loadRelaxed();
}
}
if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
return;
int nargs = 1; // include return type
- while (argumentTypes[nargs-1])
+ while (argumentTypes[nargs - 1])
++nargs;
- QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed()));
- if (!c->receiver.loadRelaxed()) {
+ QMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed()));
+ QObject *receiver = c->receiver.loadRelaxed();
+ if (!receiver) {
// the connection has been disconnected before we got the lock
return;
}
- if (c->isSlotObject)
- c->slotObj->ref();
+
+ SlotObjectGuard slotObjectGuard { c->isSlotObject ? c->slotObj : nullptr };
locker.unlock();
QMetaCallEvent *ev = c->isSlotObject ?
@@ -3671,30 +3958,33 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);
void **args = ev->args();
- int *types = ev->types();
+ QMetaType *types = ev->types();
- types[0] = 0; // return type
+ types[0] = QMetaType(); // return type
args[0] = nullptr; // return value
if (nargs > 1) {
for (int n = 1; n < nargs; ++n)
- types[n] = argumentTypes[n-1];
+ types[n] = QMetaType(argumentTypes[n - 1]);
for (int n = 1; n < nargs; ++n)
- args[n] = QMetaType::create(types[n], argv[n]);
+ args[n] = types[n].create(argv[n]);
+ }
+
+ if (c->isSingleShot && !QObjectPrivate::removeConnection(c)) {
+ delete ev;
+ return;
}
locker.relock();
- if (c->isSlotObject)
- c->slotObj->destroyIfLastRef();
- if (!c->receiver.loadRelaxed()) {
+ if (!c->isSingleShot && !c->receiver.loadRelaxed()) {
// the connection has been disconnected while we were unlocked
locker.unlock();
delete ev;
return;
}
- QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev);
+ QCoreApplication::postEvent(receiver, ev);
}
template <bool callbacks_enabled>
@@ -3734,8 +4024,8 @@ void doActivate(QObject *sender, int signal_index, void **argv)
bool senderDeleted = false;
{
- Q_ASSERT(sp->connections.loadAcquire());
- QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
+ Q_ASSERT(sp->connections.loadRelaxed());
+ QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadAcquire());
QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
const QObjectPrivate::ConnectionList *list;
@@ -3788,10 +4078,14 @@ void doActivate(QObject *sender, int signal_index, void **argv)
sender->metaObject()->className(), sender,
receiver->metaObject()->className(), receiver);
}
+
+ if (c->isSingleShot && !QObjectPrivate::removeConnection(c))
+ continue;
+
QSemaphore semaphore;
{
- QBasicMutexLocker locker(signalSlotLock(sender));
- if (!c->receiver.loadAcquire())
+ QMutexLocker locker(signalSlotLock(receiver));
+ if (!c->isSingleShot && !c->receiver.loadAcquire())
continue;
QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :
@@ -3804,20 +4098,18 @@ void doActivate(QObject *sender, int signal_index, void **argv)
#endif
}
- QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index);
+ if (c->isSingleShot && !QObjectPrivate::removeConnection(c))
+ continue;
- if (c->isSlotObject) {
- c->slotObj->ref();
+ QObjectPrivate::Sender senderData(
+ receiverInSameThread ? receiver : nullptr, sender, signal_index,
+ receiverInSameThread ? QObjectPrivate::get(receiver)->connections.loadAcquire() : nullptr);
- struct Deleter {
- void operator()(QtPrivate::QSlotObjectBase *slot) const {
- if (slot) slot->destroyIfLastRef();
- }
- };
- const std::unique_ptr<QtPrivate::QSlotObjectBase, Deleter> obj{c->slotObj};
+ if (c->isSlotObject) {
+ SlotObjectGuard obj{c->slotObj};
{
- Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.get());
+ Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, c->slotObj);
obj->call(receiver, argv);
}
} else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
@@ -3860,7 +4152,7 @@ void doActivate(QObject *sender, int signal_index, void **argv)
senderDeleted = true;
}
if (!senderDeleted) {
- sp->connections.loadRelaxed()->cleanOrphanedConnections(sender);
+ sp->connections.loadAcquire()->cleanOrphanedConnections(sender);
if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
signal_spy_set->signal_end_callback(sender, signal_index);
@@ -3892,7 +4184,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
doActivate<true>(sender, signal_index, argv);
else
doActivate<false>(sender, signal_index, argv);
- }
+}
/*!
\internal
@@ -3937,9 +4229,9 @@ int QObjectPrivate::signalIndex(const char *signalName,
Properties
*****************************************************************************/
-#ifndef QT_NO_PROPERTIES
-
/*!
+ \fn bool QObject::setProperty(const char *name, const QVariant &value)
+
Sets the value of the object's \a name property to \a value.
If the property is defined in the class using Q_PROPERTY then
@@ -3960,17 +4252,24 @@ int QObjectPrivate::signalIndex(const char *signalName,
\sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write()
*/
-bool QObject::setProperty(const char *name, const QVariant &value)
+
+/*!
+ \fn bool QObject::setProperty(const char *name, QVariant &&value)
+ \since 6.6
+ \overload setProperty
+*/
+
+bool QObject::doSetProperty(const char *name, const QVariant *lvalue, QVariant *rvalue)
{
Q_D(QObject);
- const QMetaObject* meta = metaObject();
+ const auto &value =*lvalue;
+ const QMetaObject *meta = metaObject();
if (!name || !meta)
return false;
int id = meta->indexOfProperty(name);
if (id < 0) {
- if (!d->extraData)
- d->extraData = new QObjectPrivate::ExtraData;
+ d->ensureExtraData();
const int idx = d->extraData->propertyNames.indexOf(name);
@@ -3982,12 +4281,18 @@ bool QObject::setProperty(const char *name, const QVariant &value)
} else {
if (idx == -1) {
d->extraData->propertyNames.append(name);
- d->extraData->propertyValues.append(value);
+ if (rvalue)
+ d->extraData->propertyValues.append(std::move(*rvalue));
+ else
+ d->extraData->propertyValues.append(*lvalue);
} else {
if (value.userType() == d->extraData->propertyValues.at(idx).userType()
&& value == d->extraData->propertyValues.at(idx))
return false;
- d->extraData->propertyValues[idx] = value;
+ if (rvalue)
+ d->extraData->propertyValues[idx] = std::move(*rvalue);
+ else
+ d->extraData->propertyValues[idx] = *lvalue;
}
}
@@ -4002,7 +4307,7 @@ bool QObject::setProperty(const char *name, const QVariant &value)
qWarning("%s::setProperty: Property \"%s\" invalid,"
" read-only or does not exist", metaObject()->className(), name);
#endif
- return p.write(this, value);
+ return rvalue ? p.write(this, std::move(*rvalue)) : p.write(this, *lvalue);
}
/*!
@@ -4018,7 +4323,7 @@ bool QObject::setProperty(const char *name, const QVariant &value)
QVariant QObject::property(const char *name) const
{
Q_D(const QObject);
- const QMetaObject* meta = metaObject();
+ const QMetaObject *meta = metaObject();
if (!name || !meta)
return QVariant();
@@ -4052,65 +4357,32 @@ QList<QByteArray> QObject::dynamicPropertyNames() const
return QList<QByteArray>();
}
-#endif // QT_NO_PROPERTIES
-
-
/*****************************************************************************
QObject debugging output routines.
*****************************************************************************/
+std::string QObjectPrivate::flagsForDumping() const
+{
+ return {};
+}
+
static void dumpRecursive(int level, const QObject *object)
{
if (object) {
- QByteArray buf;
- buf.fill(' ', level / 2 * 8);
- if (level % 2)
- buf += " ";
- QString name = object->objectName();
- QString flags = QLatin1String("");
-#if 0
- if (qApp->focusWidget() == object)
- flags += 'F';
- if (object->isWidgetType()) {
- QWidget * w = (QWidget *)object;
- if (w->isVisible()) {
- QString t("<%1,%2,%3,%4>");
- flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
- } else {
- flags += 'I';
- }
- }
-#endif
- qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
- flags.toLatin1().data());
- QObjectList children = object->children();
- if (!children.isEmpty()) {
- for (int i = 0; i < children.size(); ++i)
- dumpRecursive(level+1, children.at(i));
- }
+ const int indent = level * 4;
+ qDebug("%*s%s::%ls %s", indent, "", object->metaObject()->className(),
+ qUtf16Printable(object->objectName()),
+ QObjectPrivate::get(object)->flagsForDumping().c_str());
+ for (auto child : object->children())
+ dumpRecursive(level + 1, child);
}
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- \overload
- \obsolete
-
- Dumps a tree of children to the debug output.
-
- \sa dumpObjectInfo()
-*/
-
-void QObject::dumpObjectTree()
-{
- const_cast<const QObject *>(this)->dumpObjectTree();
-}
-#endif
/*!
Dumps a tree of children to the debug output.
- \note before Qt 5.9, this function was not const.
+ \note Before Qt 5.9, this function was not const.
\sa dumpObjectInfo()
*/
@@ -4120,28 +4392,11 @@ void QObject::dumpObjectTree() const
dumpRecursive(0, this);
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- \overload
- \obsolete
-
- Dumps information about signal connections, etc. for this object
- to the debug output.
-
- \sa dumpObjectTree()
-*/
-
-void QObject::dumpObjectInfo()
-{
- const_cast<const QObject *>(this)->dumpObjectInfo();
-}
-#endif
-
/*!
Dumps information about signal connections, etc. for this object
to the debug output.
- \note before Qt 5.9, this function was not const.
+ \note Before Qt 5.9, this function was not const.
\sa dumpObjectTree()
*/
@@ -4152,13 +4407,13 @@ void QObject::dumpObjectInfo() const
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
Q_D(const QObject);
- QBasicMutexLocker locker(signalSlotLock(this));
+ QMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
qDebug(" SIGNALS OUT");
QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
- if (cd && cd->signalVectorCount()) {
+ if (cd && cd->signalVectorCount() > 0) {
QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.loadRelaxed();
@@ -4214,15 +4469,23 @@ void QObject::dumpObjectInfo() const
#ifndef QT_NO_DEBUG_STREAM
+void QObjectPrivate::writeToDebugStream(QDebug &dbg) const
+{
+ Q_Q(const QObject);
+ dbg.nospace() << q->metaObject()->className() << '(' << (const void *)q;
+ if (!q->objectName().isEmpty())
+ dbg << ", name = " << q->objectName();
+ dbg << ')';
+}
+
QDebug operator<<(QDebug dbg, const QObject *o)
{
QDebugStateSaver saver(dbg);
if (!o)
return dbg << "QObject(0x0)";
- dbg.nospace() << o->metaObject()->className() << '(' << (const void *)o;
- if (!o->objectName().isEmpty())
- dbg << ", name = " << o->objectName();
- dbg << ')';
+
+ const QObjectPrivate *d = QObjectPrivate::get(o);
+ d->writeToDebugStream(dbg);
return dbg;
}
#endif
@@ -4232,20 +4495,22 @@ QDebug operator<<(QDebug dbg, const QObject *o)
\relates QObject
This macro associates extra information to the class, which is available
- using QObject::metaObject(). Qt makes only limited use of this feature, in
- the \l{Active Qt}, \l{Qt D-Bus} and \l{Qt QML module}{Qt QML}.
-
- The extra information takes the form of a \a Name string and a \a Value
- literal string.
+ using QObject::metaObject(). The extra information takes the form of a
+ \a Name string and a \a Value literal string.
Example:
\snippet code/src_corelib_kernel_qobject.cpp 35
+ Qt makes use of the macro in \l{Qt D-Bus} and \l{Qt Qml} modules.
+ For instance, when defining \l{QML Object Types} in C++, you can
+ designate a property as the \e default one:
+
+ \snippet code/doc_src_properties.cpp 7
+
\sa QMetaObject::classInfo()
- \sa QAxFactory
\sa {Using Qt D-Bus Adaptors}
- \sa {Extending QML}
+ \sa {Defining QML Types from C++}
*/
/*!
@@ -4255,15 +4520,6 @@ QDebug operator<<(QDebug dbg, const QObject *o)
This macro tells Qt which interfaces the class implements. This
is used when implementing plugins.
- Example:
-
- \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 1
- \dots
- \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 3
-
- See the \l{tools/plugandpaint/plugins/basictools}{Plug & Paint
- Basic Tools} example for details.
-
\sa Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), {How to Create Qt Plugins}
*/
@@ -4297,7 +4553,7 @@ QDebug operator<<(QDebug dbg, const QObject *o)
/*!
\macro Q_ENUMS(...)
\relates QObject
- \obsolete
+ \deprecated
In new code, you should prefer the use of the Q_ENUM() macro, which makes the
type available also to the meta type system.
@@ -4317,7 +4573,7 @@ QDebug operator<<(QDebug dbg, const QObject *o)
/*!
\macro Q_FLAGS(...)
\relates QObject
- \obsolete
+ \deprecated
This macro registers one or several \l{QFlags}{flags types} with the
meta-object system. It is typically used in a class definition to declare
@@ -4340,8 +4596,8 @@ QDebug operator<<(QDebug dbg, const QObject *o)
\since 5.5
This macro registers an enum type with the meta-object system.
- It must be placed after the enum declaration in a class that has the Q_OBJECT or the
- Q_GADGET macro. For namespaces use \l Q_ENUM_NS() instead.
+ It must be placed after the enum declaration in a class that has the Q_OBJECT,
+ Q_GADGET or Q_GADGET_EXPORT macro. For namespaces use \l Q_ENUM_NS() instead.
For example:
@@ -4459,9 +4715,16 @@ QDebug operator<<(QDebug dbg, const QObject *o)
\snippet signalsandslots/signalsandslots.h 3
\note This macro requires the class to be a subclass of QObject. Use
- Q_GADGET instead of Q_OBJECT to enable the meta object system's support
+ Q_GADGET or Q_GADGET_EXPORT instead of Q_OBJECT to enable the meta object system's support
for enums in a class that is not a QObject subclass.
+//! [qobject-macros-private-access-specifier]
+ \note This macro expansion ends with a \c private: access specifier, which makes member
+ declarations immediately after the macro private, too. If you want add public (or protected)
+ members immediately after the macro, you need to use a \c public: (or \c protected:)
+ access specifier.
+//! [qobject-macros-private-access-specifier]
+
\sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
*/
@@ -4479,7 +4742,38 @@ QDebug operator<<(QDebug dbg, const QObject *o)
Q_GADGET makes a class member, \c{staticMetaObject}, available.
\c{staticMetaObject} is of type QMetaObject and provides access to the
- enums declared with Q_ENUMS.
+ enums declared with Q_ENUM.
+
+ \include qobject.cpp qobject-macros-private-access-specifier
+
+ \sa Q_GADGET_EXPORT
+*/
+
+/*!
+ \macro Q_GADGET_EXPORT(EXPORT_MACRO)
+ \relates QObject
+ \since 6.3
+
+ The Q_GADGET_EXPORT macro works exactly like the Q_GADGET macro.
+ However, the \c{staticMetaObject} variable that is made available (see
+ Q_GADGET) is declared with the supplied \a EXPORT_MACRO qualifier. This is
+ useful if the object needs to be exported from a dynamic library, but the
+ enclosing class as a whole should not be (e.g. because it consists of mostly
+ inline functions).
+
+ For example:
+
+ \code
+ class Point {
+ Q_GADGET_EXPORT(EXPORT_MACRO)
+ Q_PROPERTY(int x MEMBER x)
+ Q_PROPERTY(int y MEMBER y)
+ ~~~
+ \endcode
+
+ \include qobject.cpp qobject-macros-private-access-specifier
+
+ \sa Q_GADGET, {Creating Shared Libraries}
*/
/*!
@@ -4709,17 +5003,34 @@ QDebug operator<<(QDebug dbg, const QObject *o)
*/
/*!
+ \macro QT_NO_CONTEXTLESS_CONNECT
+ \relates QObject
+ \since 6.7
+
+ Defining this macro will disable the overload of QObject::connect() that
+ connects a signal to a functor, without also specifying a QObject
+ as a receiver/context object (that is, the 3-arguments overload
+ of QObject::connect()).
+
+ Using the context-less overload is error prone, because it is easy
+ to connect to functors that depend on some local state of the
+ receiving end. If such local state gets destroyed, the connection
+ does not get automatically disconnected.
+
+ Moreover, such connections are always direct connections, which may
+ cause issues in multithreaded scenarios (for instance, if the
+ signal is emitted from another thread).
+
+ \sa QObject::connect, Qt::ConnectionType
+*/
+
+/*!
\typedef QObjectList
\relates QObject
Synonym for QList<QObject *>.
*/
-void qDeleteInEventHandler(QObject *o)
-{
- delete o;
-}
-
/*!
\fn template<typename PointerToMemberFunction> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
\overload connect()
@@ -4796,9 +5107,8 @@ void qDeleteInEventHandler(QObject *o)
The signal must be a function declared as a signal in the header.
The slot function can be any function or functor that can be connected
to the signal.
- A function can be connected to a given signal if the signal has at
- least as many argument as the slot. A functor can be connected to a signal
- if they have exactly the same number of arguments. There must exist implicit
+ A slot function can be connected to a given signal if the signal has at
+ least as many arguments as the slot function. There must exist implicit
conversion between the types of the corresponding arguments in the
signal and the slot.
@@ -4814,6 +5124,11 @@ void qDeleteInEventHandler(QObject *o)
However, you should take care that any objects used within the functor
are still alive when the signal is emitted.
+ For this reason, it is recommended to use the overload of connect()
+ that also takes a QObject as a receiver/context. It is possible
+ to disable the usage of the context-less overload by defining the
+ \c{QT_NO_CONTEXTLESS_CONNECT} macro.
+
Overloaded functions can be resolved with help of \l qOverload.
*/
@@ -4836,9 +5151,8 @@ void qDeleteInEventHandler(QObject *o)
The signal must be a function declared as a signal in the header.
The slot function can be any function or functor that can be connected
to the signal.
- A function can be connected to a given signal if the signal has at
- least as many argument as the slot. A functor can be connected to a signal
- if they have exactly the same number of arguments. There must exist implicit
+ A slot function can be connected to a given signal if the signal has at
+ least as many arguments as the slot function. There must exist implicit
conversion between the types of the corresponding arguments in the
signal and the slot.
@@ -4880,13 +5194,12 @@ void qDeleteInEventHandler(QObject *o)
*/
QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
const QObject *receiver, void **slot,
- QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ QtPrivate::QSlotObjectBase *slotObjRaw, Qt::ConnectionType type,
const int *types, const QMetaObject *senderMetaObject)
{
+ QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
if (!signal) {
- qWarning("QObject::connect: invalid nullptr parameter");
- if (slotObj)
- slotObj->destroyIfLastRef();
+ qCWarning(lcConnect, "QObject::connect: invalid nullptr parameter");
return QMetaObject::Connection();
}
@@ -4898,12 +5211,24 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
break;
}
if (!senderMetaObject) {
- qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className());
- slotObj->destroyIfLastRef();
+ qCWarning(lcConnect, "QObject::connect: signal not found in %s", sender->metaObject()->className());
return QMetaObject::Connection(nullptr);
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
- return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
+ return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj.release(), type, types, senderMetaObject);
+}
+
+static void connectWarning(const QObject *sender,
+ const QMetaObject *senderMetaObject,
+ const QObject *receiver,
+ const char *message)
+{
+ const char *senderString = sender ? sender->metaObject()->className()
+ : senderMetaObject ? senderMetaObject->className()
+ : "Unknown";
+ const char *receiverString = receiver ? receiver->metaObject()->className()
+ : "Unknown";
+ qCWarning(lcConnect, "QObject::connect(%s, %s): %s", senderString, receiverString, message);
}
/*!
@@ -4915,18 +5240,18 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
*/
QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int signal_index,
const QObject *receiver, void **slot,
- QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ QtPrivate::QSlotObjectBase *slotObjRaw, int type,
const int *types, const QMetaObject *senderMetaObject)
{
+ QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
+
if (!sender || !receiver || !slotObj || !senderMetaObject) {
- const char *senderString = sender ? sender->metaObject()->className()
- : senderMetaObject ? senderMetaObject->className()
- : "Unknown";
- const char *receiverString = receiver ? receiver->metaObject()->className()
- : "Unknown";
- qWarning("QObject::connect(%s, %s): invalid nullptr parameter", senderString, receiverString);
- if (slotObj)
- slotObj->destroyIfLastRef();
+ connectWarning(sender, senderMetaObject, receiver, "invalid nullptr parameter");
+ return QMetaObject::Connection();
+ }
+
+ if (type & Qt::UniqueConnection && !slot) {
+ connectWarning(sender, senderMetaObject, receiver, "unique connections require a pointer to member function of a QObject subclass");
return QMetaObject::Connection();
}
@@ -4936,36 +5261,41 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
- if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) {
+ if (type & Qt::UniqueConnection && slot) {
QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
- if (connections->signalVectorCount() > signal_index) {
+ if (connections && connections->signalVectorCount() > signal_index) {
const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
while (c2) {
- if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
- slotObj->destroyIfLastRef();
+ if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot))
return QMetaObject::Connection();
- }
c2 = c2->nextConnectionList.loadRelaxed();
}
}
- type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
}
+ type &= ~Qt::UniqueConnection;
+
+ const bool isSingleShot = type & Qt::SingleShotConnection;
+ type &= ~Qt::SingleShotConnection;
+
+ Q_ASSERT(type >= 0);
+ Q_ASSERT(type <= 3);
std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
c->sender = s;
c->signal_index = signal_index;
- QThreadData *td = r->d_func()->threadData;
+ QThreadData *td = r->d_func()->threadData.loadAcquire();
td->ref();
c->receiverThreadData.storeRelaxed(td);
c->receiver.storeRelaxed(r);
- c->slotObj = slotObj;
c->connectionType = type;
c->isSlotObject = true;
+ c->slotObj = slotObj.release();
if (types) {
c->argumentTypes.storeRelaxed(types);
c->ownArgumentTypes = false;
}
+ c->isSingleShot = isSingleShot;
QObjectPrivate::get(s)->addConnection(signal_index, c.get());
QMetaObject::Connection ret(c.release());
@@ -4989,39 +5319,12 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
bool QObject::disconnect(const QMetaObject::Connection &connection)
{
QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
-
if (!c)
return false;
- QObject *receiver = c->receiver.loadRelaxed();
- if (!receiver)
- return false;
-
- QBasicMutex *senderMutex = signalSlotLock(c->sender);
- QBasicMutex *receiverMutex = signalSlotLock(receiver);
-
- QObjectPrivate::ConnectionData *connections;
- {
- QOrderedMutexLocker locker(senderMutex, receiverMutex);
-
- // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime
- receiver = c->receiver.loadRelaxed();
- if (!receiver)
- return false;
-
- connections = QObjectPrivate::get(c->sender)->connections.loadRelaxed();
- Q_ASSERT(connections);
- connections->removeConnection(c);
- }
-
- connections->cleanOrphanedConnections(c->sender);
-
- c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(),
- c->signal_index));
-
+ const bool disconnected = QObjectPrivate::removeConnection(c);
const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr;
c->deref(); // has been removed from the QMetaObject::Connection object
-
- return true;
+ return disconnected;
}
/*! \fn template<typename PointerToMemberFunction> bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
@@ -5067,8 +5370,9 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
any signal. If not, only the specified signal is disconnected.
If \a receiver is \nullptr, it disconnects anything connected to \a
- signal. If not, slots in objects other than \a receiver are not
- disconnected.
+ signal. If not, only slots in the specified receiver are disconnected.
+ disconnect() with a non-null \a receiver also disconnects slot functions
+ that were connected with \a receiver as their context object.
If \a method is \nullptr, it disconnects anything that is connected to \a
receiver. If not, only slots named \a method will be disconnected,
@@ -5087,7 +5391,7 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject)
{
if (sender == nullptr || (receiver == nullptr && slot != nullptr)) {
- qWarning("QObject::disconnect: Unexpected nullptr parameter");
+ qCWarning(lcConnect, "QObject::disconnect: Unexpected nullptr parameter");
return false;
}
@@ -5100,7 +5404,7 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject
break;
}
if (!senderMetaObject) {
- qWarning("QObject::disconnect: signal not found in %s", sender->metaObject()->className());
+ qCWarning(lcConnect, "QObject::disconnect: signal not found in %s", sender->metaObject()->className());
return false;
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
@@ -5111,22 +5415,43 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject
/*!
\internal
- Used by QML to connect a signal by index to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass).
+ Used by QML to connect a signal by index to a slot implemented in JavaScript
+ (wrapped in a custom QSlotObjectBase subclass).
+
+ This version of connect assumes that sender and receiver are the same object.
The signal_index is an index relative to the number of methods.
*/
QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type)
{
+ return QObjectPrivate::connect(sender, signal_index, sender, slotObj, type);
+}
+
+/*!
+ \internal
+ Used by QML to connect a signal by index to a slot implemented in JavaScript
+ (wrapped in a custom QSlotObjectBase subclass).
+
+ This is an overload that should be used when \a sender and \a receiver are
+ different objects.
+
+ The signal_index is an index relative to the number of methods.
+ */
+QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index,
+ const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObjRaw,
+ Qt::ConnectionType type)
+{
+ QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
if (!sender) {
- qWarning("QObject::connect: invalid nullptr parameter");
- if (slotObj)
- slotObj->destroyIfLastRef();
+ qCWarning(lcConnect, "QObject::connect: invalid nullptr parameter");
return QMetaObject::Connection();
}
const QMetaObject *senderMetaObject = sender->metaObject();
signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
- return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/nullptr, slotObj, type, /*types*/nullptr, senderMetaObject);
+ return connectImpl(sender, signal_index, receiver, /*slot*/ nullptr, slotObj.release(),
+ type, /*types*/ nullptr, senderMetaObject);
}
/*!
@@ -5134,13 +5459,104 @@ QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signa
Used by QML to disconnect a signal by index that's connected to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass)
In the QML case the slot is not a pointer to a pointer to the function to disconnect, but instead it is a pointer to an array of internal values
required for the disconnect.
+
+ This version of disconnect assumes that sender and receiver are the same object.
*/
bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void **slot)
{
+ return QObjectPrivate::disconnect(sender, signal_index, sender, slot);
+}
+
+/*!
+ \internal
+
+ Used by QML to disconnect a signal by index that's connected to a slot
+ implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass) In the
+ QML case the slot is not a pointer to a pointer to the function to disconnect,
+ but instead it is a pointer to an array of internal values required for the
+ disconnect.
+
+ This is an overload that should be used when \a sender and \a receiver are
+ different objects.
+ */
+bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, const QObject *receiver,
+ void **slot)
+{
const QMetaObject *senderMetaObject = sender->metaObject();
signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
- return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, sender, -1, slot);
+ return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, receiver, -1,
+ slot);
+}
+
+/*!
+ \internal
+ \threadsafe
+*/
+inline bool QObjectPrivate::removeConnection(QObjectPrivate::Connection *c)
+{
+ if (!c)
+ return false;
+ QObject *receiver = c->receiver.loadRelaxed();
+ if (!receiver)
+ return false;
+
+ QBasicMutex *senderMutex = signalSlotLock(c->sender);
+ QBasicMutex *receiverMutex = signalSlotLock(receiver);
+
+ QObjectPrivate::ConnectionData *connections;
+ {
+ QOrderedMutexLocker locker(senderMutex, receiverMutex);
+
+ // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime
+ receiver = c->receiver.loadRelaxed();
+ if (!receiver)
+ return false;
+
+ connections = QObjectPrivate::get(c->sender)->connections.loadRelaxed();
+ Q_ASSERT(connections);
+ connections->removeConnection(c);
+
+ c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(), c->signal_index));
+ // We must not hold the receiver mutex, else we risk dead-locking; we also only need the sender mutex
+ // It is however vital to hold the senderMutex before calling cleanOrphanedConnections, as otherwise
+ // another thread might modify/delete the connection
+ if (receiverMutex != senderMutex) {
+ receiverMutex->unlock();
+ }
+ connections->cleanOrphanedConnections(c->sender, ConnectionData::AlreadyLockedAndTemporarilyReleasingLock);
+ senderMutex->unlock(); // now both sender and receiver mutex have been manually unlocked
+ locker.dismiss(); // so we dismiss the QOrderedMutexLocker
+ }
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Used by QPropertyAdaptorSlotObject to get an existing instance for a property, if available
+ */
+QtPrivate::QPropertyAdaptorSlotObject *
+QObjectPrivate::getPropertyAdaptorSlotObject(const QMetaProperty &property)
+{
+ if (auto conns = connections.loadAcquire()) {
+ Q_Q(QObject);
+ const QMetaObject *metaObject = q->metaObject();
+ int signal_index = methodIndexToSignalIndex(&metaObject, property.notifySignalIndex());
+ if (signal_index >= conns->signalVectorCount())
+ return nullptr;
+ const auto &connectionList = conns->connectionsForSignal(signal_index);
+ for (auto c = connectionList.first.loadRelaxed(); c;
+ c = c->nextConnectionList.loadRelaxed()) {
+ if (c->isSlotObject) {
+ if (auto p = QtPrivate::QPropertyAdaptorSlotObject::cast(c->slotObj,
+ property.propertyIndex()))
+ return p;
+ }
+ }
+ }
+ return nullptr;
}
/*! \class QMetaObject::Connection
@@ -5167,7 +5583,7 @@ QMetaObject::Connection::Connection(const QMetaObject::Connection &other) : d_pt
/*!
Assigns \a other to this connection and returns a reference to this connection.
*/
-QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::Connection& other)
+QMetaObject::Connection &QMetaObject::Connection::operator=(const QMetaObject::Connection &other)
{
if (other.d_ptr != d_ptr) {
if (d_ptr)
@@ -5216,5 +5632,4 @@ bool QMetaObject::Connection::isConnected_helper() const
QT_END_NAMESPACE
-#include "moc_qnamespace.cpp"
#include "moc_qobject.cpp"
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index ea635ce6f1..06cfefd61b 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOBJECT_H
#define QOBJECT_H
@@ -54,14 +18,15 @@
#include <QtCore/qmetatype.h>
#include <QtCore/qobject_impl.h>
+#include <QtCore/qbindingstorage.h>
+#include <QtCore/qtcoreexports.h>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
+template <typename T> class QBindable;
class QEvent;
class QTimerEvent;
class QChildEvent;
@@ -79,13 +44,27 @@ struct QDynamicMetaObjectData;
typedef QList<QObject*> QObjectList;
+#if QT_CORE_REMOVED_SINCE(6, 7)
Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name,
const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
+#endif
+Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, QAnyStringView name,
+ const QMetaObject &mo, QList<void *> *list,
+ Qt::FindChildOptions options);
+#if QT_CORE_REMOVED_SINCE(6, 7)
+Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QMetaObject &mo,
+ QList<void *> *list, Qt::FindChildOptions options);
+#endif
Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
+#if QT_CORE_REMOVED_SINCE(6, 7)
Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options);
+#endif
+Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, QAnyStringView name,
+ const QMetaObject &mo, Qt::FindChildOptions options);
-class Q_CORE_EXPORT QObjectData {
+class Q_CORE_EXPORT QObjectData
+{
Q_DISABLE_COPY(QObjectData)
public:
QObjectData() = default;
@@ -100,11 +79,19 @@ public:
uint isDeletingChildren : 1;
uint sendChildEvents : 1;
uint receiveChildEvents : 1;
- uint isWindow : 1; //for QWindow
+ uint isWindow : 1; // for QWindow
uint deleteLaterCalled : 1;
- uint unused : 24;
- int postedEvents;
+ uint isQuickItem : 1;
+ uint willBeWidget : 1; // for handling widget-specific bits in QObject's ctor
+ uint wasWidget : 1; // for properly cleaning up in QObject's dtor
+ uint receiveParentEvents: 1;
+ uint unused : 20;
+ QAtomicInt postedEvents;
QDynamicMetaObjectData *metaObject;
+ QBindingStorage bindingStorage;
+
+ // ### Qt7: Make this return a const QMetaObject *. You should not mess with
+ // the metaobjects of existing objects.
QMetaObject *dynamicMetaObject() const;
#ifdef QT_DEBUG
@@ -112,74 +99,98 @@ public:
#endif
};
-
class Q_CORE_EXPORT QObject
{
Q_OBJECT
- Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
+ Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged
+ BINDABLE bindableObjectName)
Q_DECLARE_PRIVATE(QObject)
public:
- Q_INVOKABLE explicit QObject(QObject *parent=nullptr);
+ Q_INVOKABLE explicit QObject(QObject *parent = nullptr);
virtual ~QObject();
virtual bool event(QEvent *event);
virtual bool eventFilter(QObject *watched, QEvent *event);
-#if defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC)
+#if defined(QT_NO_TRANSLATION) || defined(Q_QDOC)
static QString tr(const char *sourceText, const char * = nullptr, int = -1)
{ return QString::fromUtf8(sourceText); }
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED static QString trUtf8(const char *sourceText, const char * = nullptr, int = -1)
- { return QString::fromUtf8(sourceText); }
-#endif
-#endif //QT_NO_TRANSLATION
+#endif // QT_NO_TRANSLATION
QString objectName() const;
+#if QT_CORE_REMOVED_SINCE(6, 4)
void setObjectName(const QString &name);
+#endif
+ Q_WEAK_OVERLOAD
+ void setObjectName(const QString &name) { doSetObjectName(name); }
+ void setObjectName(QAnyStringView name);
+ QBindable<QString> bindableObjectName();
inline bool isWidgetType() const { return d_ptr->isWidget; }
inline bool isWindowType() const { return d_ptr->isWindow; }
+ inline bool isQuickItemType() const { return d_ptr->isQuickItem; }
inline bool signalsBlocked() const noexcept { return d_ptr->blockSig; }
bool blockSignals(bool b) noexcept;
QThread *thread() const;
+#if QT_CORE_REMOVED_SINCE(6, 7)
void moveToThread(QThread *thread);
+#endif
+ bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL);
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
-#if __has_include(<chrono>)
- Q_ALWAYS_INLINE
- int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer)
- {
- return startTimer(int(time.count()), timerType);
- }
+
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer);
#endif
+ int startTimer(std::chrono::nanoseconds time, Qt::TimerType timerType = Qt::CoarseTimer);
+
void killTimer(int id);
+ void killTimer(Qt::TimerId id);
template<typename T>
- inline T findChild(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
+ T findChild(QAnyStringView aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
+ static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
+ "No Q_OBJECT in the class passed to QObject::findChild");
return static_cast<T>(qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options));
}
template<typename T>
- inline QList<T> findChildren(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
+ QList<T> findChildren(QAnyStringView aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
+ static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
+ "No Q_OBJECT in the class passed to QObject::findChildren");
QList<T> list;
qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject,
reinterpret_cast<QList<void *> *>(&list), options);
return list;
}
+ template<typename T>
+ T findChild(Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
+ {
+ return findChild<T>({}, options);
+ }
+
+ template<typename T>
+ QList<T> findChildren(Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
+ {
+ return findChildren<T>(QAnyStringView{}, options);
+ }
+
#if QT_CONFIG(regularexpression)
template<typename T>
inline QList<T> findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
+ static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
+ "No Q_OBJECT in the class passed to QObject::findChildren");
QList<T> list;
qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
reinterpret_cast<QList<void *> *>(&list), options);
@@ -203,7 +214,7 @@ public:
inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
const char *member, Qt::ConnectionType type = Qt::AutoConnection) const;
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
template<typename PointerToMemberFunction>
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);
template<typename PointerToMemberFunction, typename Functor>
@@ -211,54 +222,28 @@ public:
template<typename PointerToMemberFunction, typename Functor>
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection);
#else
- //Connect a signal to a pointer to qobject member function
+ //connect with context
template <typename Func1, typename Func2>
- static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
- const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
- Qt::ConnectionType type = Qt::AutoConnection)
+ static inline QMetaObject::Connection
+ connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
+ const typename QtPrivate::ContextTypeForFunctor<Func2>::ContextType *context, Func2 &&slot,
+ Qt::ConnectionType type = Qt::AutoConnection)
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
- typedef QtPrivate::FunctionPointer<Func2> SlotType;
-
- static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
- "No Q_OBJECT in the class with the signal");
-
- //compilation error if the arguments does not match.
- static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
- "The slot requires more arguments than the signal provides.");
- static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
- "Signal and slot arguments are not compatible.");
- static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
- "Return type of the slot is not compatible with the return type of the signal.");
-
- const int *types = nullptr;
- if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
- types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
+ typedef QtPrivate::FunctionPointer<std::decay_t<Func2>> SlotType;
- return connectImpl(sender, reinterpret_cast<void **>(&signal),
- receiver, reinterpret_cast<void **>(&slot),
- new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
- typename SignalType::ReturnType>(slot),
- type, types, &SignalType::Object::staticMetaObject);
- }
+ if constexpr (SlotType::ArgumentCount != -1) {
+ static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
+ "Return type of the slot is not compatible with the return type of the signal.");
+ } else {
+ constexpr int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<std::decay_t<Func2>, typename SignalType::Arguments>::Value;
+ [[maybe_unused]]
+ constexpr int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
+ typedef typename QtPrivate::FunctorReturnType<std::decay_t<Func2>, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;
- //connect to a function pointer (not a member)
- template <typename Func1, typename Func2>
- static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0, QMetaObject::Connection>::type
- connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
- {
- return connect(sender, signal, sender, slot, Qt::DirectConnection);
- }
-
- //connect to a function pointer (not a member)
- template <typename Func1, typename Func2>
- static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
- !QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction, QMetaObject::Connection>::type
- connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
- Qt::ConnectionType type = Qt::AutoConnection)
- {
- typedef QtPrivate::FunctionPointer<Func1> SignalType;
- typedef QtPrivate::FunctionPointer<Func2> SlotType;
+ static_assert((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
+ "Return type of the slot is not compatible with the return type of the signal.");
+ }
static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
@@ -266,61 +251,35 @@ public:
//compilation error if the arguments does not match.
static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
"The slot requires more arguments than the signal provides.");
- static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
- "Signal and slot arguments are not compatible.");
- static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
- "Return type of the slot is not compatible with the return type of the signal.");
const int *types = nullptr;
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
- return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
- new QtPrivate::QStaticSlotObject<Func2,
- typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
- typename SignalType::ReturnType>(slot),
+ void **pSlot = nullptr;
+ if constexpr (std::is_member_function_pointer_v<std::decay_t<Func2>>) {
+ pSlot = const_cast<void **>(reinterpret_cast<void *const *>(&slot));
+ } else {
+ Q_ASSERT_X((type & Qt::UniqueConnection) == 0, "",
+ "QObject::connect: Unique connection requires the slot to be a pointer to "
+ "a member function of a QObject subclass.");
+ }
+
+ return connectImpl(sender, reinterpret_cast<void **>(&signal), context, pSlot,
+ QtPrivate::makeCallableObject<Func1>(std::forward<Func2>(slot)),
type, types, &SignalType::Object::staticMetaObject);
}
- //connect to a functor
+#ifndef QT_NO_CONTEXTLESS_CONNECT
+ //connect without context
template <typename Func1, typename Func2>
- static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
- connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
+ static inline QMetaObject::Connection
+ connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 &&slot)
{
- return connect(sender, signal, sender, std::move(slot), Qt::DirectConnection);
- }
-
- //connect to a functor, with a "context" object defining in which event loop is going to be executed
- template <typename Func1, typename Func2>
- static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
- connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
- Qt::ConnectionType type = Qt::AutoConnection)
- {
- typedef QtPrivate::FunctionPointer<Func1> SignalType;
- const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;
-
- static_assert((FunctorArgumentCount >= 0),
- "Signal and slot arguments are not compatible.");
- const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
- typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;
-
- static_assert((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
- "Return type of the slot is not compatible with the return type of the signal.");
-
- static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
- "No Q_OBJECT in the class with the signal");
-
- const int *types = nullptr;
- if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
- types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
-
- return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
- new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
- typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
- typename SignalType::ReturnType>(std::move(slot)),
- type, types, &SignalType::Object::staticMetaObject);
+ return connect(sender, signal, sender, std::forward<Func2>(slot), Qt::DirectConnection);
}
-#endif //Q_CLANG_QDOC
+#endif // QT_NO_CONTEXTLESS_CONNECT
+#endif //Q_QDOC
static bool disconnect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member);
@@ -333,7 +292,7 @@ public:
{ return disconnect(this, nullptr, receiver, member); }
static bool disconnect(const QMetaObject::Connection &);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
template<typename PointerToMemberFunction>
static bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method);
#else
@@ -366,21 +325,18 @@ public:
return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero,
&SignalType::Object::staticMetaObject);
}
-#endif //Q_CLANG_QDOC
+#endif //Q_QDOC
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void dumpObjectTree(); // ### Qt 6: remove
- void dumpObjectInfo(); // ### Qt 6: remove
-#endif
void dumpObjectTree() const;
void dumpObjectInfo() const;
-#ifndef QT_NO_PROPERTIES
+ QT_CORE_INLINE_SINCE(6, 6)
bool setProperty(const char *name, const QVariant &value);
+ inline bool setProperty(const char *name, QVariant &&value);
QVariant property(const char *name) const;
QList<QByteArray> dynamicPropertyNames() const;
-#endif // QT_NO_PROPERTIES
+ QBindingStorage *bindingStorage() { return &d_ptr->bindingStorage; }
+ const QBindingStorage *bindingStorage() const { return &d_ptr->bindingStorage; }
Q_SIGNALS:
void destroyed(QObject * = nullptr);
@@ -390,7 +346,9 @@ public:
inline QObject *parent() const { return d_ptr->parent; }
inline bool inherits(const char *classname) const
- { return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr; }
+ {
+ return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr;
+ }
public Q_SLOTS:
void deleteLater();
@@ -398,7 +356,7 @@ public Q_SLOTS:
protected:
QObject *sender() const;
int senderSignalIndex() const;
- int receivers(const char* signal) const;
+ int receivers(const char *signal) const;
bool isSignalConnected(const QMetaMethod &signal) const;
virtual void timerEvent(QTimerEvent *event);
@@ -426,8 +384,10 @@ protected:
friend class QThreadData;
private:
+ void doSetObjectName(const QString &name);
+ bool doSetProperty(const char *name, const QVariant *lvalue, QVariant *rvalue);
+
Q_DISABLE_COPY(QObject)
- Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
private:
static QMetaObject::Connection connectImpl(const QObject *sender, void **signal,
@@ -444,22 +404,22 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch
const char *amember, Qt::ConnectionType atype) const
{ return connect(asender, asignal, this, amember, atype); }
-#if QT_DEPRECATED_SINCE(5, 0)
-template<typename T>
-inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString())
-{ return o->findChild<T>(name); }
-
-template<typename T>
-inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString())
+#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
+bool QObject::setProperty(const char *name, const QVariant &value)
{
- return o->findChildren<T>(name);
+ return doSetProperty(name, &value, nullptr);
+}
+#endif // inline since 6.6
+bool QObject::setProperty(const char *name, QVariant &&value)
+{
+ return doSetProperty(name, &value, &value);
}
-
-#endif //QT_DEPRECATED
template <class T>
inline T qobject_cast(QObject *object)
{
+ static_assert(std::is_pointer_v<T>,
+ "qobject_cast requires to cast towards a pointer type");
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
"qobject_cast requires the type to have a Q_OBJECT macro");
@@ -469,6 +429,10 @@ inline T qobject_cast(QObject *object)
template <class T>
inline T qobject_cast(const QObject *object)
{
+ static_assert(std::is_pointer_v<T>,
+ "qobject_cast requires to cast towards a pointer type");
+ static_assert(std::is_const_v<std::remove_pointer_t<T>>,
+ "qobject_cast cannot cast away constness (use const_cast)");
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
"qobject_cast requires the type to have a Q_OBJECT macro");
@@ -476,22 +440,41 @@ inline T qobject_cast(const QObject *object)
}
-template <class T> inline const char * qobject_interface_iid()
-{ return nullptr; }
-
+template <class T> constexpr const char * qobject_interface_iid() = delete;
+template <class T> inline T *
+qobject_iid_cast(QObject *object, const char *IId = qobject_interface_iid<T *>())
+{
+ return reinterpret_cast<T *>((object ? object->qt_metacast(IId) : nullptr));
+}
+template <class T> inline std::enable_if_t<std::is_const<T>::value, T *>
+qobject_iid_cast(const QObject *object)
+{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ QObject *o = const_cast<QObject *>(object);
+ return qobject_iid_cast<std::remove_cv_t<T>>(o);
+}
-#if defined(Q_CLANG_QDOC)
+#if defined(Q_QDOC)
# define Q_DECLARE_INTERFACE(IFace, IId)
#elif !defined(Q_MOC_RUN)
# define Q_DECLARE_INTERFACE(IFace, IId) \
- template <> inline const char *qobject_interface_iid<IFace *>() \
+ template <> constexpr const char *qobject_interface_iid<IFace *>() \
{ return IId; } \
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
- { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : nullptr)); } \
- template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
- { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : nullptr)); }
+ { return qobject_iid_cast<IFace>(object); } \
+ template <> inline const IFace *qobject_cast<const IFace *>(const QObject *object) \
+ { return qobject_iid_cast<const IFace>(object); }
#endif // Q_MOC_RUN
+inline const QBindingStorage *qGetBindingStorage(const QObject *o)
+{
+ return o->bindingStorage();
+}
+inline QBindingStorage *qGetBindingStorage(QObject *o)
+{
+ return o->bindingStorage();
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
#endif
@@ -499,18 +482,23 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
class QSignalBlocker
{
public:
+ Q_NODISCARD_CTOR
inline explicit QSignalBlocker(QObject *o) noexcept;
+ Q_NODISCARD_CTOR
inline explicit QSignalBlocker(QObject &o) noexcept;
inline ~QSignalBlocker();
+ Q_NODISCARD_CTOR
inline QSignalBlocker(QSignalBlocker &&other) noexcept;
inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept;
inline void reblock() noexcept;
inline void unblock() noexcept;
+ inline void dismiss() noexcept;
+
private:
Q_DISABLE_COPY(QSignalBlocker)
- QObject * m_o;
+ QObject *m_o;
bool m_blocked;
bool m_inhibited;
};
@@ -559,21 +547,28 @@ QSignalBlocker::~QSignalBlocker()
void QSignalBlocker::reblock() noexcept
{
- if (m_o) m_o->blockSignals(true);
+ if (m_o)
+ m_o->blockSignals(true);
m_inhibited = false;
}
void QSignalBlocker::unblock() noexcept
{
- if (m_o) m_o->blockSignals(m_blocked);
+ if (m_o)
+ m_o->blockSignals(m_blocked);
m_inhibited = true;
}
+void QSignalBlocker::dismiss() noexcept
+{
+ m_o = nullptr;
+}
+
namespace QtPrivate {
inline QObject & deref_for_methodcall(QObject &o) { return o; }
inline QObject & deref_for_methodcall(QObject *o) { return *o; }
}
-#define Q_SET_OBJECT_NAME(obj) QT_PREPEND_NAMESPACE(QtPrivate)::deref_for_methodcall(obj).setObjectName(QLatin1String(#obj))
+#define Q_SET_OBJECT_NAME(obj) QT_PREPEND_NAMESPACE(QtPrivate)::deref_for_methodcall(obj).setObjectName(QLatin1StringView(#obj))
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h
index 0c36417a24..b57d7e50cc 100644
--- a/src/corelib/kernel/qobject_impl.h
+++ b/src/corelib/kernel/qobject_impl.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef Q_QDOC
@@ -73,30 +37,6 @@ namespace QtPrivate {
{ static const int *types() { return nullptr; } };
template <typename... Args> struct ConnectionTypes<List<Args...>, true>
{ static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } };
-
- // implementation of QSlotObjectBase for which the slot is a static function
- // Args and R are the List of arguments and the return type of the signal to which the slot is connected.
- template<typename Func, typename Args, typename R> class QStaticSlotObject : public QSlotObjectBase
- {
- typedef QtPrivate::FunctionPointer<Func> FuncType;
- Func function;
- static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
- {
- switch (which) {
- case Destroy:
- delete static_cast<QStaticSlotObject*>(this_);
- break;
- case Call:
- FuncType::template call<Args, R>(static_cast<QStaticSlotObject*>(this_)->function, r, a);
- break;
- case Compare: // not implemented
- case NumOperations:
- Q_UNUSED(ret);
- }
- }
- public:
- explicit QStaticSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
- };
}
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index d3285b292f..0ab9bf02ed 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOBJECT_P_H
#define QOBJECT_P_H
@@ -54,15 +18,27 @@
#include <QtCore/private/qglobal_p.h>
#include "QtCore/qcoreevent.h"
+#include <QtCore/qfunctionaltools_impl.h>
#include "QtCore/qlist.h"
#include "QtCore/qobject.h"
#include "QtCore/qpointer.h"
-#include "QtCore/qreadwritelock.h"
-#include "QtCore/qsharedpointer.h"
#include "QtCore/qvariant.h"
+#include "QtCore/qproperty.h"
+#include <QtCore/qshareddata.h>
+#include "QtCore/private/qproperty_p.h"
+
+#include <string>
QT_BEGIN_NAMESPACE
+#ifdef Q_MOC_RUN
+#define QT_ANONYMOUS_PROPERTY(text) QT_ANONYMOUS_PROPERTY(text)
+#define QT_ANONYMOUS_PRIVATE_PROPERTY(d, text) QT_ANONYMOUS_PRIVATE_PROPERTY(d, text)
+#elif !defined QT_NO_META_MACROS
+#define QT_ANONYMOUS_PROPERTY(...) QT_ANNOTATE_CLASS(qt_anonymous_property, __VA_ARGS__)
+#define QT_ANONYMOUS_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_anonymous_private_property, d, text)
+#endif
+
class QVariant;
class QThreadData;
class QObjectConnectionListVector;
@@ -88,7 +64,6 @@ class Q_CORE_EXPORT QAbstractDeclarativeData
{
public:
static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
- static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **);
static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int);
static bool (*isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int);
@@ -97,137 +72,47 @@ public:
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
+public:
Q_DECLARE_PUBLIC(QObject)
-public:
struct ExtraData
{
- ExtraData() {}
- QList<QByteArray> propertyNames;
- QList<QVariant> propertyValues;
- QList<int> runningTimers;
- QList<QPointer<QObject> > eventFilters;
- QString objectName;
- };
-
- typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
- struct Connection;
- struct SignalVector;
+ ExtraData(QObjectPrivate *ptr) : parent(ptr) { }
- struct ConnectionOrSignalVector {
- union {
- // linked list of orphaned connections that need cleaning up
- ConnectionOrSignalVector *nextInOrphanList;
- // linked list of connections connected to slots in this object
- Connection *next;
- };
-
- static SignalVector *asSignalVector(ConnectionOrSignalVector *c) {
- if (reinterpret_cast<quintptr>(c) & 1)
- return reinterpret_cast<SignalVector *>(reinterpret_cast<quintptr>(c) & ~quintptr(1u));
- return nullptr;
- }
- static Connection *fromSignalVector(SignalVector *v) {
- return reinterpret_cast<Connection *>(reinterpret_cast<quintptr>(v) | quintptr(1u));
- }
- };
-
- struct Connection : public ConnectionOrSignalVector
- {
- // linked list of connections connected to slots in this object, next is in base class
- Connection **prev;
- // linked list of connections connected to signals in this object
- QAtomicPointer<Connection> nextConnectionList;
- Connection *prevConnectionList;
-
- QObject *sender;
- QAtomicPointer<QObject> receiver;
- QAtomicPointer<QThreadData> receiverThreadData;
- union {
- StaticMetaCallFunction callFunction;
- QtPrivate::QSlotObjectBase *slotObj;
- };
- QAtomicPointer<const int> argumentTypes;
- QAtomicInt ref_;
- uint id = 0;
- ushort method_offset;
- ushort method_relative;
- int signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
- ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
- ushort isSlotObject : 1;
- ushort ownArgumentTypes : 1;
- Connection() : ref_(2), ownArgumentTypes(true) {
- //ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
- }
- ~Connection();
- int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; }
- void ref() { ref_.ref(); }
- void freeSlotObject()
+ inline void setObjectNameForwarder(const QString &name)
{
- if (isSlotObject) {
- slotObj->destroyIfLastRef();
- isSlotObject = false;
- }
+ parent->q_func()->setObjectName(name);
}
- void deref() {
- if (!ref_.deref()) {
- Q_ASSERT(!receiver.loadRelaxed());
- Q_ASSERT(!isSlotObject);
- delete this;
- }
- }
- };
- // ConnectionList is a singly-linked list
- struct ConnectionList {
- QAtomicPointer<Connection> first;
- QAtomicPointer<Connection> last;
- };
- struct Sender
- {
- Sender(QObject *receiver, QObject *sender, int signal)
- : receiver(receiver), sender(sender), signal(signal)
+ inline void nameChangedForwarder(const QString &name)
{
- if (receiver) {
- ConnectionData *cd = receiver->d_func()->connections.loadRelaxed();
- previous = cd->currentSender;
- cd->currentSender = this;
- }
+ Q_EMIT parent->q_func()->objectNameChanged(name, QObject::QPrivateSignal());
}
- ~Sender()
- {
- if (receiver)
- receiver->d_func()->connections.loadRelaxed()->currentSender = previous;
- }
- void receiverDeleted()
- {
- Sender *s = this;
- while (s) {
- s->receiver = nullptr;
- s = s->previous;
- }
- }
- Sender *previous;
- QObject *receiver;
- QObject *sender;
- int signal;
- };
- struct SignalVector : public ConnectionOrSignalVector {
- quintptr allocated;
- // ConnectionList signals[]
- ConnectionList &at(int i)
- {
- return reinterpret_cast<ConnectionList *>(this + 1)[i + 1];
- }
- const ConnectionList &at(int i) const
- {
- return reinterpret_cast<const ConnectionList *>(this + 1)[i + 1];
- }
- int count() const { return static_cast<int>(allocated); }
+ QList<QByteArray> propertyNames;
+ QList<QVariant> propertyValues;
+ QList<Qt::TimerId> runningTimers;
+ QList<QPointer<QObject>> eventFilters;
+ Q_OBJECT_COMPAT_PROPERTY(QObjectPrivate::ExtraData, QString, objectName,
+ &QObjectPrivate::ExtraData::setObjectNameForwarder,
+ &QObjectPrivate::ExtraData::nameChangedForwarder)
+ QObjectPrivate *parent;
};
+ void ensureExtraData()
+ {
+ if (!extraData)
+ extraData = new ExtraData(this);
+ }
+ typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
+ struct Connection;
+ struct ConnectionData;
+ struct ConnectionList;
+ struct ConnectionOrSignalVector;
+ struct SignalVector;
+ struct Sender;
+ struct TaggedSignalVector;
/*
This contains the all connections from and to an object.
@@ -243,88 +128,26 @@ public:
to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this
linked list.
*/
- struct ConnectionData {
- // the id below is used to avoid activating new connections. When the object gets
- // deleted it's set to 0, so that signal emission stops
- QAtomicInteger<uint> currentConnectionId;
- QAtomicInt ref;
- QAtomicPointer<SignalVector> signalVector;
- Connection *senders = nullptr;
- Sender *currentSender = nullptr; // object currently activating the object
- QAtomicPointer<Connection> orphaned;
-
- ~ConnectionData()
- {
- deleteOrphaned(orphaned.loadRelaxed());
- SignalVector *v = signalVector.loadRelaxed();
- if (v)
- free(v);
- }
-
- // must be called on the senders connection data
- // assumes the senders and receivers lock are held
- void removeConnection(Connection *c);
- void cleanOrphanedConnections(QObject *sender)
- {
- if (orphaned.loadRelaxed() && ref.loadAcquire() == 1)
- cleanOrphanedConnectionsImpl(sender);
- }
- void cleanOrphanedConnectionsImpl(QObject *sender);
-
- ConnectionList &connectionsForSignal(int signal)
- {
- return signalVector.loadRelaxed()->at(signal);
- }
-
- void resizeSignalVector(uint size) {
- SignalVector *vector = this->signalVector.loadRelaxed();
- if (vector && vector->allocated > size)
- return;
- size = (size + 7) & ~7;
- SignalVector *newVector = reinterpret_cast<SignalVector *>(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList)));
- int start = -1;
- if (vector) {
- memcpy(newVector, vector, sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList));
- start = vector->count();
- }
- for (int i = start; i < int(size); ++i)
- newVector->at(i) = ConnectionList();
- newVector->next = nullptr;
- newVector->allocated = size;
-
- signalVector.storeRelaxed(newVector);
- if (vector) {
- vector->nextInOrphanList = orphaned.loadRelaxed();
- orphaned.storeRelaxed(ConnectionOrSignalVector::fromSignalVector(vector));
- }
- }
- int signalVectorCount() const {
- return signalVector.loadAcquire() ? signalVector.loadRelaxed()->count() : -1;
- }
-
- static void deleteOrphaned(ConnectionOrSignalVector *c);
- };
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
void deleteChildren();
+ // used to clear binding storage early in ~QObject
+ void clearBindingStorage();
inline void checkForIncompatibleLibraryVersion(int version) const;
void setParent_helper(QObject *);
void moveToThread_helper();
- void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
- void _q_reregisterTimers(void *pointer);
+ void setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status);
- bool isSender(const QObject *receiver, const char *signal) const;
QObjectList receiverList(const char *signal) const;
- QObjectList senderList() const;
- void addConnection(int signal, Connection *c);
+ inline void ensureConnectionData();
+ inline void addConnection(int signal, Connection *c);
+ static inline bool removeConnection(Connection *c);
- static QObjectPrivate *get(QObject *o) {
- return o->d_func();
- }
+ static QObjectPrivate *get(QObject *o) { return o->d_func(); }
static const QObjectPrivate *get(const QObject *o) { return o->d_func(); }
int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const;
@@ -337,6 +160,8 @@ public:
inline void connectNotify(const QMetaMethod &signal);
inline void disconnectNotify(const QMetaMethod &signal);
+ void reinitBindingStorageAfterThreadMove();
+
template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
@@ -348,21 +173,28 @@ public:
static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
const QObject *receiver, void **slot,
- QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ QtPrivate::QSlotObjectBase *slotObj, int type,
const int *types, const QMetaObject *senderMetaObject);
static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
+ static QMetaObject::Connection connect(const QObject *sender, int signal_index,
+ const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj,
+ Qt::ConnectionType type);
static bool disconnect(const QObject *sender, int signal_index, void **slot);
+ static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver,
+ void **slot);
+
+ virtual std::string flagsForDumping() const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ virtual void writeToDebugStream(QDebug &) const;
+#endif
+
+ QtPrivate::QPropertyAdaptorSlotObject *
+ getPropertyAdaptorSlotObject(const QMetaProperty &property);
- void ensureConnectionData()
- {
- if (connections.loadRelaxed())
- return;
- ConnectionData *cd = new ConnectionData;
- cd->ref.ref();
- connections.storeRelaxed(cd);
- }
public:
- ExtraData *extraData; // extra data set by the user
+ mutable ExtraData *extraData; // extra data set by the user
// This atomic requires acquire/release semantics in a few places,
// e.g. QObject::moveToThread must synchronize with QCoreApplication::postEvent,
// because postEvent is thread-safe.
@@ -383,8 +215,6 @@ public:
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};
-Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE);
-
/*
Catch mixing of incompatible library versions.
@@ -409,7 +239,7 @@ inline void QObjectPrivate::checkForIncompatibleLibraryVersion(int version) cons
inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
{
- return declarativeData && QAbstractDeclarativeData::isSignalConnected
+ return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
}
@@ -424,28 +254,44 @@ inline void QObjectPrivate::disconnectNotify(const QMetaMethod &signal)
}
namespace QtPrivate {
-template<typename Func, typename Args, typename R> class QPrivateSlotObject : public QSlotObjectBase
+inline const QObject *getQObject(const QObjectPrivate *d) { return d->q_func(); }
+
+template <typename Func>
+using FunctionStorage = QtPrivate::CompactStorage<Func>;
+
+template <typename ObjPrivate> inline void assertObjectType(QObjectPrivate *d)
+{
+ using Obj = std::remove_pointer_t<decltype(std::declval<ObjPrivate *>()->q_func())>;
+ assertObjectType<Obj>(d->q_ptr);
+}
+
+template<typename Func, typename Args, typename R>
+class QPrivateSlotObject : public QSlotObjectBase, private FunctionStorage<Func>
{
typedef QtPrivate::FunctionPointer<Func> FuncType;
- Func function;
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
+#else
+ static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret)
+#endif
{
+ const auto that = static_cast<QPrivateSlotObject*>(this_);
switch (which) {
case Destroy:
- delete static_cast<QPrivateSlotObject*>(this_);
+ delete that;
break;
case Call:
- FuncType::template call<Args, R>(static_cast<QPrivateSlotObject*>(this_)->function,
+ FuncType::template call<Args, R>(that->object(),
static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a);
break;
case Compare:
- *ret = *reinterpret_cast<Func *>(a) == static_cast<QPrivateSlotObject*>(this_)->function;
+ *ret = *reinterpret_cast<Func *>(a) == that->object();
break;
case NumOperations: ;
}
}
public:
- explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
+ explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), FunctionStorage<Func>{std::move(f)} {}
};
} //namespace QtPrivate
@@ -472,7 +318,7 @@ inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate:
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
return QObject::connectImpl(sender, reinterpret_cast<void **>(&signal),
- receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
+ QtPrivate::getQObject(receiverPrivate), reinterpret_cast<void **>(&slot),
new QtPrivate::QPrivateSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
type, types, &SignalType::Object::staticMetaObject);
@@ -494,9 +340,6 @@ bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1
&SignalType::Object::staticMetaObject);
}
-Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
-
class QSemaphore;
class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent
{
@@ -533,6 +376,9 @@ public:
QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
const QObject *sender, int signalId,
void **args, QSemaphore *semaphore);
+ QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
+ const QObject *sender, int signalId,
+ void **args, QSemaphore *semaphore);
// queued - args allocated by event, copied by caller
QMetaCallEvent(ushort method_offset, ushort method_relative,
@@ -542,22 +388,56 @@ public:
QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
const QObject *sender, int signalId,
int nargs);
+ QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
+ const QObject *sender, int signalId,
+ int nargs);
~QMetaCallEvent() override;
+ template<typename ...Args>
+ static QMetaCallEvent *create(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender,
+ int signal_index, const Args &...argv)
+ {
+ const void* const argp[] = { nullptr, std::addressof(argv)... };
+ const QMetaType metaTypes[] = { QMetaType::fromType<void>(), QMetaType::fromType<Args>()... };
+ constexpr auto argc = sizeof...(Args) + 1;
+ return create_impl(slotObj, sender, signal_index, argc, argp, metaTypes);
+ }
+ template<typename ...Args>
+ static QMetaCallEvent *create(QtPrivate::SlotObjUniquePtr slotObj, const QObject *sender,
+ int signal_index, const Args &...argv)
+ {
+ const void* const argp[] = { nullptr, std::addressof(argv)... };
+ const QMetaType metaTypes[] = { QMetaType::fromType<void>(), QMetaType::fromType<Args>()... };
+ constexpr auto argc = sizeof...(Args) + 1;
+ return create_impl(std::move(slotObj), sender, signal_index, argc, argp, metaTypes);
+ }
+
inline int id() const { return d.method_offset_ + d.method_relative_; }
inline const void * const* args() const { return d.args_; }
inline void ** args() { return d.args_; }
- inline const int *types() const { return reinterpret_cast<int*>(d.args_ + d.nargs_); }
- inline int *types() { return reinterpret_cast<int*>(d.args_ + d.nargs_); }
+ inline const QMetaType *types() const { return reinterpret_cast<QMetaType *>(d.args_ + d.nargs_); }
+ inline QMetaType *types() { return reinterpret_cast<QMetaType *>(d.args_ + d.nargs_); }
virtual void placeMetaCall(QObject *object) override;
private:
+ static QMetaCallEvent *create_impl(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender,
+ int signal_index, size_t argc, const void * const argp[],
+ const QMetaType metaTypes[])
+ {
+ if (slotObj)
+ slotObj->ref();
+ return create_impl(QtPrivate::SlotObjUniquePtr{slotObj}, sender,
+ signal_index, argc, argp, metaTypes);
+ }
+ static QMetaCallEvent *create_impl(QtPrivate::SlotObjUniquePtr slotObj, const QObject *sender,
+ int signal_index, size_t argc, const void * const argp[],
+ const QMetaType metaTypes[]);
inline void allocArgs();
struct Data {
- QtPrivate::QSlotObjectBase *slotObj_;
+ QtPrivate::SlotObjUniquePtr slotObj_;
void **args_;
QObjectPrivate::StaticMetaCallFunction callFunction_;
int nargs_;
@@ -565,29 +445,30 @@ private:
ushort method_relative_;
} d;
// preallocate enough space for three arguments
- char prealloc_[3*(sizeof(void*) + sizeof(int))];
+ alignas(void *) char prealloc_[3 * sizeof(void *) + 3 * sizeof(QMetaType)];
};
class QBoolBlocker
{
Q_DISABLE_COPY_MOVE(QBoolBlocker)
public:
- explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
- inline ~QBoolBlocker(){block = reset; }
+ Q_NODISCARD_CTOR explicit QBoolBlocker(bool &b, bool value = true)
+ : block(b), reset(b)
+ { block = value; }
+ inline ~QBoolBlocker() { block = reset; }
+
private:
bool &block;
bool reset;
};
-void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
-
struct QAbstractDynamicMetaObject;
struct Q_CORE_EXPORT QDynamicMetaObjectData
{
virtual ~QDynamicMetaObjectData();
virtual void objectDestroyed(QObject *) { delete this; }
- virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) = 0;
+ virtual QMetaObject *toDynamicMetaObject(QObject *) = 0;
virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0;
};
@@ -595,13 +476,30 @@ struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData,
{
~QAbstractDynamicMetaObject();
- QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override { return this; }
+ QMetaObject *toDynamicMetaObject(QObject *) override { return this; }
virtual int createProperty(const char *, const char *) { return -1; }
int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override
{ return metaCall(c, _id, a); }
virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload
};
+inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate *o)
+{
+ return &o->bindingStorage;
+}
+inline QBindingStorage *qGetBindingStorage(QObjectPrivate *o)
+{
+ return &o->bindingStorage;
+}
+inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate::ExtraData *ed)
+{
+ return &ed->parent->bindingStorage;
+}
+inline QBindingStorage *qGetBindingStorage(QObjectPrivate::ExtraData *ed)
+{
+ return &ed->parent->bindingStorage;
+}
+
QT_END_NAMESPACE
#endif // QOBJECT_P_H
diff --git a/src/corelib/kernel/qobject_p_p.h b/src/corelib/kernel/qobject_p_p.h
new file mode 100644
index 0000000000..2277af0497
--- /dev/null
+++ b/src/corelib/kernel/qobject_p_p.h
@@ -0,0 +1,257 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QOBJECT_P_P_H
+#define QOBJECT_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qobject.cpp. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Even though this file is only used by qobject.cpp, the only reason this
+// code lives here is that some special apps/libraries for e.g., QtJambi,
+// Gammaray need access to the structs in this file.
+
+#include <QtCore/qobject.h>
+#include <QtCore/private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// ConnectionList is a singly-linked list
+struct QObjectPrivate::ConnectionList
+{
+ QAtomicPointer<Connection> first;
+ QAtomicPointer<Connection> last;
+};
+static_assert(std::is_trivially_destructible_v<QObjectPrivate::ConnectionList>);
+Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_RELOCATABLE_TYPE);
+
+struct QObjectPrivate::TaggedSignalVector
+{
+ quintptr c;
+
+ TaggedSignalVector() = default;
+ TaggedSignalVector(std::nullptr_t) noexcept : c(0) {}
+ TaggedSignalVector(Connection *v) noexcept : c(reinterpret_cast<quintptr>(v)) { Q_ASSERT(v && (reinterpret_cast<quintptr>(v) & 0x1) == 0); }
+ TaggedSignalVector(SignalVector *v) noexcept : c(reinterpret_cast<quintptr>(v) | quintptr(1u)) { Q_ASSERT(v); }
+ explicit operator SignalVector *() const noexcept
+ {
+ if (c & 0x1)
+ return reinterpret_cast<SignalVector *>(c & ~quintptr(1u));
+ return nullptr;
+ }
+ explicit operator Connection *() const noexcept
+ {
+ return reinterpret_cast<Connection *>(c);
+ }
+ operator uintptr_t() const noexcept { return c; }
+};
+
+struct QObjectPrivate::ConnectionOrSignalVector
+{
+ union {
+ // linked list of orphaned connections that need cleaning up
+ TaggedSignalVector nextInOrphanList;
+ // linked list of connections connected to slots in this object
+ Connection *next;
+ };
+};
+static_assert(std::is_trivial_v<QObjectPrivate::ConnectionOrSignalVector>);
+
+struct QObjectPrivate::Connection : public ConnectionOrSignalVector
+{
+ // linked list of connections connected to slots in this object, next is in base class
+ Connection **prev;
+ // linked list of connections connected to signals in this object
+ QAtomicPointer<Connection> nextConnectionList;
+ Connection *prevConnectionList;
+
+ QObject *sender;
+ QAtomicPointer<QObject> receiver;
+ QAtomicPointer<QThreadData> receiverThreadData;
+ union {
+ StaticMetaCallFunction callFunction;
+ QtPrivate::QSlotObjectBase *slotObj;
+ };
+ QAtomicPointer<const int> argumentTypes;
+ QAtomicInt ref_{
+ 2
+ }; // ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
+ uint id = 0;
+ ushort method_offset;
+ ushort method_relative;
+ signed int signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
+ ushort connectionType : 2; // 0 == auto, 1 == direct, 2 == queued, 3 == blocking
+ ushort isSlotObject : 1;
+ ushort ownArgumentTypes : 1;
+ ushort isSingleShot : 1;
+ Connection() : ownArgumentTypes(true) { }
+ ~Connection();
+ int method() const
+ {
+ Q_ASSERT(!isSlotObject);
+ return method_offset + method_relative;
+ }
+ void ref() { ref_.ref(); }
+ void freeSlotObject()
+ {
+ if (isSlotObject) {
+ slotObj->destroyIfLastRef();
+ isSlotObject = false;
+ }
+ }
+ void deref()
+ {
+ if (!ref_.deref()) {
+ Q_ASSERT(!receiver.loadRelaxed());
+ Q_ASSERT(!isSlotObject);
+ delete this;
+ }
+ }
+};
+Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_RELOCATABLE_TYPE);
+
+struct QObjectPrivate::SignalVector : public ConnectionOrSignalVector
+{
+ quintptr allocated;
+ // ConnectionList signals[]
+ ConnectionList &at(int i) { return reinterpret_cast<ConnectionList *>(this + 1)[i + 1]; }
+ const ConnectionList &at(int i) const
+ {
+ return reinterpret_cast<const ConnectionList *>(this + 1)[i + 1];
+ }
+ int count() const { return static_cast<int>(allocated); }
+};
+static_assert(
+ std::is_trivial_v<QObjectPrivate::SignalVector>); // it doesn't need to be, but it helps
+
+struct QObjectPrivate::ConnectionData
+{
+ // the id below is used to avoid activating new connections. When the object gets
+ // deleted it's set to 0, so that signal emission stops
+ QAtomicInteger<uint> currentConnectionId;
+ QAtomicInt ref;
+ QAtomicPointer<SignalVector> signalVector;
+ Connection *senders = nullptr;
+ Sender *currentSender = nullptr; // object currently activating the object
+ std::atomic<TaggedSignalVector> orphaned = {};
+
+ ~ConnectionData()
+ {
+ Q_ASSERT(ref.loadRelaxed() == 0);
+ TaggedSignalVector c = orphaned.exchange(nullptr, std::memory_order_relaxed);
+ if (c)
+ deleteOrphaned(c);
+ SignalVector *v = signalVector.loadRelaxed();
+ if (v) {
+ v->~SignalVector();
+ free(v);
+ }
+ }
+
+ // must be called on the senders connection data
+ // assumes the senders and receivers lock are held
+ void removeConnection(Connection *c);
+ enum LockPolicy {
+ NeedToLock,
+ // Beware that we need to temporarily release the lock
+ // and thus calling code must carefully consider whether
+ // invariants still hold.
+ AlreadyLockedAndTemporarilyReleasingLock
+ };
+ void cleanOrphanedConnections(QObject *sender, LockPolicy lockPolicy = NeedToLock)
+ {
+ if (orphaned.load(std::memory_order_relaxed) && ref.loadAcquire() == 1)
+ cleanOrphanedConnectionsImpl(sender, lockPolicy);
+ }
+ void cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy);
+
+ ConnectionList &connectionsForSignal(int signal)
+ {
+ return signalVector.loadRelaxed()->at(signal);
+ }
+
+ void resizeSignalVector(uint size)
+ {
+ SignalVector *vector = this->signalVector.loadRelaxed();
+ if (vector && vector->allocated > size)
+ return;
+ size = (size + 7) & ~7;
+ void *ptr = malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList));
+ auto newVector = new (ptr) SignalVector;
+
+ int start = -1;
+ if (vector) {
+ // not (yet) existing trait:
+ // static_assert(std::is_relocatable_v<SignalVector>);
+ // static_assert(std::is_relocatable_v<ConnectionList>);
+ memcpy(newVector, vector,
+ sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList));
+ start = vector->count();
+ }
+ for (int i = start; i < int(size); ++i)
+ new (&newVector->at(i)) ConnectionList();
+ newVector->next = nullptr;
+ newVector->allocated = size;
+
+ signalVector.storeRelaxed(newVector);
+ if (vector) {
+ TaggedSignalVector o = nullptr;
+ /* No ABA issue here: When adding a node, we only care about the list head, it doesn't
+ * matter if the tail changes.
+ */
+ o = orphaned.load(std::memory_order_acquire);
+ do {
+ vector->nextInOrphanList = o;
+ } while (!orphaned.compare_exchange_strong(o, TaggedSignalVector(vector), std::memory_order_release));
+ }
+ }
+ int signalVectorCount() const
+ {
+ return signalVector.loadAcquire() ? signalVector.loadRelaxed()->count() : -1;
+ }
+
+ static void deleteOrphaned(TaggedSignalVector o);
+};
+
+struct QObjectPrivate::Sender
+{
+ Sender(QObject *receiver, QObject *sender, int signal, ConnectionData *receiverConnections)
+ : receiver(receiver), sender(sender), signal(signal)
+ {
+ if (receiverConnections) {
+ previous = receiverConnections->currentSender;
+ receiverConnections->currentSender = this;
+ }
+ }
+ ~Sender()
+ {
+ if (receiver)
+ receiver->d_func()->connections.loadAcquire()->currentSender = previous;
+ }
+ void receiverDeleted()
+ {
+ Sender *s = this;
+ while (s) {
+ s->receiver = nullptr;
+ s = s->previous;
+ }
+ }
+ Sender *previous = nullptr;
+ QObject *receiver;
+ QObject *sender;
+ int signal;
+};
+Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_RELOCATABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qobjectcleanuphandler.cpp b/src/corelib/kernel/qobjectcleanuphandler.cpp
index 8bf0e1fcab..f46afc2f07 100644
--- a/src/corelib/kernel/qobjectcleanuphandler.cpp
+++ b/src/corelib/kernel/qobjectcleanuphandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qobjectcleanuphandler.h"
@@ -91,7 +55,7 @@ QObjectCleanupHandler::~QObjectCleanupHandler()
\sa remove()
*/
-QObject *QObjectCleanupHandler::add(QObject* object)
+QObject *QObjectCleanupHandler::add(QObject *object)
{
if (!object)
return nullptr;
diff --git a/src/corelib/kernel/qobjectcleanuphandler.h b/src/corelib/kernel/qobjectcleanuphandler.h
index 26c0dc2f05..b01ed94d47 100644
--- a/src/corelib/kernel/qobjectcleanuphandler.h
+++ b/src/corelib/kernel/qobjectcleanuphandler.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOBJECTCLEANUPHANDLER_H
#define QOBJECTCLEANUPHANDLER_H
@@ -44,7 +8,6 @@
QT_BEGIN_NAMESPACE
-
class Q_CORE_EXPORT QObjectCleanupHandler : public QObject
{
Q_OBJECT
@@ -53,7 +16,7 @@ public:
QObjectCleanupHandler();
~QObjectCleanupHandler();
- QObject* add(QObject* object);
+ QObject *add(QObject *object);
void remove(QObject *object);
bool isEmpty() const;
void clear();
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index d47c311c18..190901d5d1 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOBJECTDEFS_H
#define QOBJECTDEFS_H
@@ -47,6 +11,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qobjectdefs_impl.h>
+#include <QtCore/qtcoreexports.h>
#include <QtCore/qtmetamacros.h>
QT_BEGIN_NAMESPACE
@@ -72,28 +37,31 @@ class QString;
Q_CORE_EXPORT const char *qFlagLocation(const char *method);
#ifndef QT_NO_META_MACROS
-#ifndef QT_NO_DEBUG
-# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
-# ifndef QT_NO_KEYWORDS
-# define METHOD(a) qFlagLocation("0"#a QLOCATION)
+# define QMETHOD_CODE 0 // member type codes
+# define QSLOT_CODE 1
+# define QSIGNAL_CODE 2
+# define QT_PREFIX_CODE(code, a) QT_STRINGIFY(code) #a
+# define QT_STRINGIFY_METHOD(a) QT_PREFIX_CODE(QMETHOD_CODE, a)
+# define QT_STRINGIFY_SLOT(a) QT_PREFIX_CODE(QSLOT_CODE, a)
+# define QT_STRINGIFY_SIGNAL(a) QT_PREFIX_CODE(QSIGNAL_CODE, a)
+# ifndef QT_NO_DEBUG
+# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
+# ifndef QT_NO_KEYWORDS
+# define METHOD(a) qFlagLocation(QT_STRINGIFY_METHOD(a) QLOCATION)
+# endif
+# define SLOT(a) qFlagLocation(QT_STRINGIFY_SLOT(a) QLOCATION)
+# define SIGNAL(a) qFlagLocation(QT_STRINGIFY_SIGNAL(a) QLOCATION)
+# else
+# ifndef QT_NO_KEYWORDS
+# define METHOD(a) QT_STRINGIFY_METHOD(a)
+# endif
+# define SLOT(a) QT_STRINGIFY_SLOT(a)
+# define SIGNAL(a) QT_STRINGIFY_SIGNAL(a)
# endif
-# define SLOT(a) qFlagLocation("1"#a QLOCATION)
-# define SIGNAL(a) qFlagLocation("2"#a QLOCATION)
-#else
-# ifndef QT_NO_KEYWORDS
-# define METHOD(a) "0"#a
-# endif
-# define SLOT(a) "1"#a
-# define SIGNAL(a) "2"#a
-#endif
-
-#define QMETHOD_CODE 0 // member type codes
-#define QSLOT_CODE 1
-#define QSIGNAL_CODE 2
#endif // QT_NO_META_MACROS
-#define Q_ARG(type, data) QArgument<type >(#type, data)
-#define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data)
+#define Q_ARG(Type, data) QtPrivate::Invoke::argument<Type>(QT_STRINGIFY(Type), data)
+#define Q_RETURN_ARG(Type, data) QtPrivate::Invoke::returnArgument<Type>(QT_STRINGIFY(Type), data)
class QObject;
class QMetaMethod;
@@ -103,6 +71,7 @@ class QMetaClassInfo;
namespace QtPrivate {
class QMetaTypeInterface;
+template<typename T> constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
}
struct QMethodRawArguments
@@ -110,6 +79,7 @@ struct QMethodRawArguments
void **arguments;
};
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
class Q_CORE_EXPORT QGenericArgument
{
public:
@@ -157,6 +127,108 @@ public:
: QGenericReturnArgument(aName, static_cast<void *>(&aData))
{}
};
+#endif
+
+struct QMetaMethodArgument
+{
+ const QtPrivate::QMetaTypeInterface *metaType;
+ const char *name;
+ const void *data;
+};
+
+struct QMetaMethodReturnArgument
+{
+ const QtPrivate::QMetaTypeInterface *metaType;
+ const char *name;
+ void *data;
+};
+
+template <typename T>
+struct QTemplatedMetaMethodReturnArgument : QMetaMethodReturnArgument
+{
+ using Type = T;
+};
+
+namespace QtPrivate {
+namespace Invoke {
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+template <typename... Args>
+using AreOldStyleArgs = std::disjunction<std::is_base_of<QGenericArgument, Args>...>;
+
+template <typename T, typename... Args> using IfNotOldStyleArgs =
+ std::enable_if_t<!AreOldStyleArgs<Args...>::value, T>;
+#else
+template <typename T, typename... Args> using IfNotOldStyleArgs = T;
+#endif
+
+template <typename T> inline QMetaMethodArgument argument(const char *name, const T &t)
+{
+ if constexpr ((std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>) ||
+ !std::is_reference_v<T>) {
+ return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) };
+ } else {
+ return { nullptr, name, std::addressof(t) };
+ }
+}
+
+template <typename T>
+inline QTemplatedMetaMethodReturnArgument<T> returnArgument(const char *name, T &t)
+{
+ return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) };
+}
+
+template <typename T> inline const char *typenameHelper(const T &)
+{
+ return nullptr;
+}
+template <typename T> inline const void *dataHelper(const T &t)
+{
+ return std::addressof(t);
+}
+template <typename T> inline const QMetaTypeInterface *metaTypeHelper(const T &)
+{
+ return qMetaTypeInterfaceForType<T>();
+}
+
+inline const char *typenameHelper(QMetaMethodArgument a)
+{ return a.name; }
+inline const void *dataHelper(QMetaMethodArgument a)
+{ return a.data; }
+inline const QMetaTypeInterface *metaTypeHelper(QMetaMethodArgument a)
+{ return a.metaType; }
+
+inline const char *typenameHelper(const char *) = delete;
+template <typename T> inline const void *dataHelper(const char *) = delete;
+inline const QMetaTypeInterface *metaTypeHelper(const char *) = delete;
+inline const char *typenameHelper(const char16_t *) = delete;
+template <typename T> inline const void *dataHelper(const char16_t *) = delete;
+inline const QMetaTypeInterface *metaTypeHelper(const char16_t *) = delete;
+
+} // namespace QtPrivate::Invoke
+
+template <typename... Args> inline auto invokeMethodHelper(QMetaMethodReturnArgument r, const Args &... arguments)
+{
+ std::array params = { const_cast<const void *>(r.data), Invoke::dataHelper(arguments)... };
+ std::array names = { r.name, Invoke::typenameHelper(arguments)... };
+ std::array types = { r.metaType, Invoke::metaTypeHelper(arguments)... };
+ static_assert(params.size() == types.size());
+ static_assert(params.size() == names.size());
+
+ struct R {
+ decltype(params) parameters;
+ decltype(names) typeNames;
+ decltype(types) metaTypes;
+ constexpr qsizetype parameterCount() const { return qsizetype(parameters.size()); }
+ };
+ return R { params, names, types };
+}
+} // namespace QtPrivate
+
+template <typename T> void qReturnArg(const T &&) = delete;
+template <typename T> inline QTemplatedMetaMethodReturnArgument<T> qReturnArg(T &data)
+{
+ return QtPrivate::Invoke::returnArgument(nullptr, data);
+}
struct Q_CORE_EXPORT QMetaObject
{
@@ -165,13 +237,16 @@ struct Q_CORE_EXPORT QMetaObject
const QMetaObject *superClass() const;
bool inherits(const QMetaObject *metaObject) const noexcept;
- QObject *cast(QObject *obj) const;
+ QObject *cast(QObject *obj) const
+ { return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); }
const QObject *cast(const QObject *obj) const;
-#if !defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC)
+#if !defined(QT_NO_TRANSLATION) || defined(Q_QDOC)
QString tr(const char *s, const char *c, int n = -1) const;
#endif // QT_NO_TRANSLATION
+ QMetaType metaType() const;
+
int methodOffset() const;
int enumeratorOffset() const;
int propertyOffset() const;
@@ -188,6 +263,7 @@ struct Q_CORE_EXPORT QMetaObject
int indexOfSignal(const char *signal) const;
int indexOfSlot(const char *slot) const;
int indexOfEnumerator(const char *name) const;
+
int indexOfProperty(const char *name) const;
int indexOfClassInfo(const char *name) const;
@@ -221,6 +297,7 @@ struct Q_CORE_EXPORT QMetaObject
static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv);
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
static bool invokeMethod(QObject *obj, const char *member,
Qt::ConnectionType,
QGenericReturnArgument ret,
@@ -254,7 +331,7 @@ struct Q_CORE_EXPORT QMetaObject
static inline bool invokeMethod(QObject *obj, const char *member,
Qt::ConnectionType type,
- QGenericArgument val0 = QGenericArgument(nullptr),
+ QGenericArgument val0,
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
@@ -270,7 +347,7 @@ struct Q_CORE_EXPORT QMetaObject
}
static inline bool invokeMethod(QObject *obj, const char *member,
- QGenericArgument val0 = QGenericArgument(nullptr),
+ QGenericArgument val0,
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
@@ -284,89 +361,162 @@ struct Q_CORE_EXPORT QMetaObject
return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
val1, val2, val3, val4, val5, val6, val7, val8, val9);
}
+#endif // Qt < 7.0
+
+ template <typename ReturnArg, typename... Args> static
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c,
+ QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments)
+ {
+ auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
+ return invokeMethodImpl(obj, member, c, h.parameterCount(), h.parameters.data(),
+ h.typeNames.data(), h.metaTypes.data());
+ }
+
+ template <typename... Args> static
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, Args &&... arguments)
+ {
+ QTemplatedMetaMethodReturnArgument<void> r = {};
+ return invokeMethod(obj, member, c, r, std::forward<Args>(arguments)...);
+ }
+
+ template <typename ReturnArg, typename... Args> static
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> r,
+ Args &&... arguments)
+ {
+ return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
+ }
+
+ template <typename... Args> static
+#ifdef Q_QDOC
+ bool
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
+#endif
+ invokeMethod(QObject *obj, const char *member, Args &&... arguments)
+ {
+ QTemplatedMetaMethodReturnArgument<void> r = {};
+ return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
+ }
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
template<typename Functor, typename FunctorReturnType>
- static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr);
+ static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr);
template<typename Functor, typename FunctorReturnType>
- static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret);
+ static bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret);
+
+ template<typename Functor, typename FunctorReturnType, typename... Args>
+ static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments);
+ template<typename Functor, typename FunctorReturnType, typename... Args>
+ static bool invokeMethod(QObject *context, Functor &&function, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments);
+ template<typename Functor, typename... Args>
+ static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, Args &&...arguments);
+ template<typename Functor, typename... Args>
+ static bool invokeMethod(QObject *context, Functor &&function, Args &&...arguments);
#else
-
- // invokeMethod() for member function pointer
template <typename Func>
- static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
- && !std::is_convertible<Func, const char*>::value
- && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
- invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object,
- Func function,
- Qt::ConnectionType type = Qt::AutoConnection,
- typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr)
+ static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ QtPrivate::Invoke::AreOldStyleArgs<Func>>,
+ bool>
+ invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function, Qt::ConnectionType type,
+ typename QtPrivate::Callable<Func>::ReturnType *ret)
{
- return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret);
+ using R = typename QtPrivate::Callable<Func>::ReturnType;
+ const auto getReturnArg = [ret]() -> QTemplatedMetaMethodReturnArgument<R> {
+ if constexpr (std::is_void_v<R>)
+ return {};
+ else
+ return ret ? qReturnArg(*ret) : QTemplatedMetaMethodReturnArgument<R>{};
+ };
+ return invokeMethod(object, std::forward<Func>(function), type, getReturnArg());
}
-
template <typename Func>
- static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
- && !std::is_convertible<Func, const char*>::value
- && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
- invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object,
- Func function,
- typename QtPrivate::FunctionPointer<Func>::ReturnType *ret)
+ static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ QtPrivate::Invoke::AreOldStyleArgs<Func>>,
+ bool>
+ invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function, typename QtPrivate::Callable<Func>::ReturnType *ret)
{
- return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret);
+ return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret);
}
- // invokeMethod() for function pointer (not member)
- template <typename Func>
- static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
- && !std::is_convertible<Func, const char*>::value
- && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
- invokeMethod(QObject *context, Func function,
- Qt::ConnectionType type = Qt::AutoConnection,
- typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr)
+ template <typename Func, typename... Args>
+ static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
+ bool>
+ invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function, Qt::ConnectionType type,
+ QTemplatedMetaMethodReturnArgument<
+ typename QtPrivate::Callable<Func, Args...>::ReturnType>
+ ret,
+ Args &&...args)
{
- return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret);
+ return invokeMethodCallableHelper(object, std::forward<Func>(function), type, ret,
+ std::forward<Args>(args)...);
}
- template <typename Func>
- static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
- && !std::is_convertible<Func, const char*>::value
- && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
- invokeMethod(QObject *context, Func function,
- typename QtPrivate::FunctionPointer<Func>::ReturnType *ret)
+ template <typename Func, typename... Args>
+ static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
+ bool>
+ invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function, Qt::ConnectionType type, Args &&...args)
{
- return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret);
+ using R = typename QtPrivate::Callable<Func, Args...>::ReturnType;
+ QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr,
+ nullptr };
+ return invokeMethod(object, std::forward<Func>(function), type, r,
+ std::forward<Args>(args)...);
}
- // invokeMethod() for Functor
- template <typename Func>
- static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
- && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
- && !std::is_convertible<Func, const char*>::value, bool>::type
- invokeMethod(QObject *context, Func function,
- Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
+ template <typename Func, typename... Args>
+ static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
+ bool>
+ invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function,
+ QTemplatedMetaMethodReturnArgument<
+ typename QtPrivate::Callable<Func, Args...>::ReturnType>
+ ret,
+ Args &&...args)
{
- return invokeMethodImpl(context,
- new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
- type,
- ret);
+ return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret,
+ std::forward<Args>(args)...);
}
- template <typename Func>
- static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
- && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
- && !std::is_convertible<Func, const char*>::value, bool>::type
- invokeMethod(QObject *context, Func function, decltype(function()) *ret)
+ template <typename Func, typename... Args>
+ static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
+ bool>
+ invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function, Args &&...args)
{
- return invokeMethodImpl(context,
- new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
- Qt::AutoConnection,
- ret);
+ using R = typename QtPrivate::Callable<Func, Args...>::ReturnType;
+ QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr,
+ nullptr };
+ return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, r,
+ std::forward<Args>(args)...);
}
#endif
- QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr),
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QObject *newInstance(QGenericArgument val0,
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
@@ -376,6 +526,20 @@ struct Q_CORE_EXPORT QMetaObject
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const;
+#endif
+
+ template <typename... Args>
+#ifdef Q_QDOC
+ QObject *
+#else
+ QtPrivate::Invoke::IfNotOldStyleArgs<QObject *, Args...>
+#endif
+ newInstance(Args &&... arguments) const
+ {
+ auto h = QtPrivate::invokeMethodHelper(QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...);
+ return newInstanceImpl(this, h.parameterCount(), h.parameters.data(),
+ h.typeNames.data(), h.metaTypes.data());
+ }
enum Call {
InvokeMetaMethod,
@@ -386,8 +550,9 @@ struct Q_CORE_EXPORT QMetaObject
IndexOfMethod,
RegisterPropertyMetaType,
RegisterMethodArgumentMetaType,
- RegisterQPropertyObserver,
- SetQPropertyBinding
+ BindableProperty,
+ CustomCall,
+ ConstructInPlace,
};
int static_metacall(Call, int, void **) const;
@@ -399,6 +564,7 @@ struct Q_CORE_EXPORT QMetaObject
}
struct SuperData {
+ using Getter = const QMetaObject *(*)();
const QMetaObject *direct;
SuperData() = default;
constexpr SuperData(std::nullptr_t) : direct(nullptr) {}
@@ -407,7 +573,6 @@ struct Q_CORE_EXPORT QMetaObject
constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); }
#ifdef QT_NO_DATA_RELOCATION
- using Getter = const QMetaObject *(*)();
Getter indirect = nullptr;
constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {}
constexpr operator const QMetaObject *() const
@@ -415,6 +580,7 @@ struct Q_CORE_EXPORT QMetaObject
template <const QMetaObject &MO> static constexpr SuperData link()
{ return SuperData(QMetaObject::staticMetaObject<MO>); }
#else
+ constexpr SuperData(Getter g) : direct(g()) {}
constexpr operator const QMetaObject *() const
{ return direct; }
template <const QMetaObject &MO> static constexpr SuperData link()
@@ -429,13 +595,51 @@ struct Q_CORE_EXPORT QMetaObject
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
StaticMetacallFunction static_metacall;
const SuperData *relatedMetaObjects;
- QtPrivate::QMetaTypeInterface *const *metaTypes;
+ const QtPrivate::QMetaTypeInterface *const *metaTypes;
void *extradata; //reserved for future use
} d;
private:
+ // Just need to have this here with a separate name so the other inline
+ // functions can call this without any ambiguity
+ template <typename Func, typename... Args>
+ static bool
+ invokeMethodCallableHelper(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
+ Func &&function, Qt::ConnectionType type, const QMetaMethodReturnArgument &ret,
+ Args &&...args)
+ {
+ using Callable = QtPrivate::Callable<Func, Args...>;
+ using ExpectedArguments = typename Callable::Arguments;
+ static_assert(sizeof...(Args) <= ExpectedArguments::size, "Too many arguments");
+ using ActualArguments = QtPrivate::List<Args...>;
+ static_assert(QtPrivate::CheckCompatibleArguments<ActualArguments,
+ ExpectedArguments>::value,
+ "Incompatible arguments");
+
+ auto h = QtPrivate::invokeMethodHelper(ret, std::forward<Args>(args)...);
+
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ auto callable = new QtPrivate::QCallableObject<std::decay_t<Func>, ActualArguments,
+ typename Callable::ReturnType>(std::forward<Func>(function));
+ return invokeMethodImpl(object, callable, type, h.parameterCount(), h.parameters.data(),
+ h.typeNames.data(), h.metaTypes.data());
+ }
+
+ static bool invokeMethodImpl(QObject *object, const char *member, Qt::ConnectionType type,
+ qsizetype parameterCount, const void *const *parameters, const char *const *names,
+ const QtPrivate::QMetaTypeInterface * const *metaTypes);
+ static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj,
+ Qt::ConnectionType type, qsizetype parameterCount,
+ const void *const *params, const char *const *names,
+ const QtPrivate::QMetaTypeInterface *const *metaTypes);
+#if QT_CORE_REMOVED_SINCE(6, 7)
static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
+#endif
+ static QObject *newInstanceImpl(const QMetaObject *mobj, qsizetype parameterCount,
+ const void **parameters, const char **typeNames,
+ const QtPrivate::QMetaTypeInterface **metaTypes);
friend class QTimer;
+ friend class QChronoTimer;
};
class Q_CORE_EXPORT QMetaObject::Connection {
@@ -453,20 +657,27 @@ public:
#ifdef Q_QDOC
operator bool() const;
#else
+ // still using the restricted bool trick here, in order to support
+ // code using copy-init (e.g. `bool ok = connect(...)`)
typedef void *Connection::*RestrictedBool;
operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; }
#endif
- Connection(Connection &&o) noexcept : d_ptr(o.d_ptr) { o.d_ptr = nullptr; }
- Connection &operator=(Connection &&other) noexcept
- { qSwap(d_ptr, other.d_ptr); return *this; }
+ Connection(Connection &&other) noexcept : d_ptr(std::exchange(other.d_ptr, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection)
+ void swap(Connection &other) noexcept { qt_ptr_swap(d_ptr, other.d_ptr); }
};
+inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept
+{
+ lhs.swap(rhs);
+}
+
inline const QMetaObject *QMetaObject::superClass() const
{ return d.superdata; }
namespace QtPrivate {
- /* Trait that tells is a the Object has a Q_OBJECT macro */
+ // Trait that tells if a QObject has a Q_OBJECT macro
template <typename Object> struct HasQ_OBJECT_Macro {
template <typename T>
static char test(int (T::*)(QMetaObject::Call, int, void **));
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index f3f7f3df72..1e953f29b6 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOBJECTDEFS_H
#error Do not include qobjectdefs_impl.h directly
@@ -48,8 +12,15 @@
#pragma qt_sync_stop_processing
#endif
+#include <QtCore/qfunctionaltools_impl.h>
+
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QObject;
+class QObjectPrivate;
+class QMetaMethod;
+class QByteArray;
namespace QtPrivate {
template <typename T> struct RemoveRef { typedef T Type; };
@@ -64,37 +35,43 @@ namespace QtPrivate {
the list composed of the first N element of the list
*/
// With variadic template, lists are represented using a variadic template argument instead of the lisp way
- template <typename...> struct List {};
- template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; };
+ template <typename... Ts> struct List { static constexpr size_t size = sizeof...(Ts); };
+ template<typename T> struct SizeOfList { static constexpr size_t value = 1; };
+ template<> struct SizeOfList<List<>> { static constexpr size_t value = 0; };
+ template<typename ...Ts> struct SizeOfList<List<Ts...>> { static constexpr size_t value = List<Ts...>::size; };
+ template <typename Head, typename... Tail> struct List<Head, Tail...> {
+ static constexpr size_t size = 1 + sizeof...(Tail);
+ typedef Head Car; typedef List<Tail...> Cdr;
+ };
template <typename, typename> struct List_Append;
template <typename... L1, typename...L2> struct List_Append<List<L1...>, List<L2...>> { typedef List<L1..., L2...> Value; };
template <typename L, int N> struct List_Left {
typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value;
};
template <typename L> struct List_Left<L, 0> { typedef List<> Value; };
- // List_Select<L,N> returns (via typedef Value) the Nth element of the list L
- template <typename L, int N> struct List_Select { typedef typename List_Select<typename L::Cdr, N - 1>::Value Value; };
- template <typename L> struct List_Select<L,0> { typedef typename L::Car Value; };
/*
- trick to set the return value of a slot that works even if the signal or the slot returns void
- to be used like function(), ApplyReturnValue<ReturnType>(&return_value)
- if function() returns a value, the operator,(T, ApplyReturnValue<ReturnType>) is called, but if it
- returns void, the builtin one is used without an error.
- */
- template <typename T>
- struct ApplyReturnValue {
- void *data;
- explicit ApplyReturnValue(void *data_) : data(data_) {}
+ This is used to store the return value from a slot, whether the caller
+ wants to store this value (QMetaObject::invokeMethod() with
+ qReturnArg() or non-void signal ) or not.
+ */
+ struct FunctorCallBase
+ {
+ template <typename R, typename Lambda>
+ static void call_internal(void **args, Lambda &&fn) noexcept(noexcept(fn()))
+ {
+ using SlotRet = decltype(fn());
+ if constexpr (std::is_void_v<R> || std::is_void_v<SlotRet>) {
+ Q_UNUSED(args);
+ } else {
+ if (args[0]) {
+ *reinterpret_cast<R *>(args[0]) = fn();
+ return;
+ }
+ }
+ fn();
+ }
};
- template<typename T, typename U>
- void operator,(T &&value, const ApplyReturnValue<U> &container) {
- if (container.data)
- *reinterpret_cast<U *>(container.data) = std::forward<T>(value);
- }
- template<typename T>
- void operator,(T, const ApplyReturnValue<void> &) {}
-
/*
The FunctionPointer<Func> struct is a type trait for function pointer.
@@ -110,7 +87,7 @@ namespace QtPrivate {
and args is the array of pointer to arguments, as used in qt_metacall
The Functor<Func,N> struct is the helper to call a functor of N argument.
- its call function is the same as the FunctionPointer::call function.
+ Its call function is the same as the FunctionPointer::call function.
*/
template<class T> using InvokeGenSeq = typename T::Type;
@@ -139,39 +116,77 @@ namespace QtPrivate {
template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
+ template<typename ObjPrivate> inline void assertObjectType(QObjectPrivate *d);
+ template<typename Obj> inline void assertObjectType(QObject *o)
+ {
+ // ensure all three compile
+ [[maybe_unused]] auto staticcast = [](QObject *obj) { return static_cast<Obj *>(obj); };
+ [[maybe_unused]] auto qobjcast = [](QObject *obj) { return Obj::staticMetaObject.cast(obj); };
+#ifdef __cpp_rtti
+ [[maybe_unused]] auto dyncast = [](QObject *obj) { return dynamic_cast<Obj *>(obj); };
+ auto cast = dyncast;
+#else
+ auto cast = qobjcast;
+#endif
+ Q_ASSERT_X(cast(o), Obj::staticMetaObject.className(),
+ "Called object is not of the correct type (class destructor may have already run)");
+ }
+
template <typename, typename, typename, typename> struct FunctorCall;
template <int... II, typename... SignalArgs, typename R, typename Function>
- struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> {
- static void call(Function &f, void **arg) {
- f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
+ struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> : FunctorCallBase
+ {
+ static void call(Function &f, void **arg)
+ {
+ call_internal<R>(arg, [&] {
+ return f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
+ });
}
};
template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
- struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> {
- static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg) {
- (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
+ struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> : FunctorCallBase
+ {
+ static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg)
+ {
+ assertObjectType<Obj>(o);
+ call_internal<R>(arg, [&] {
+ return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
+ });
}
};
template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
- struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> {
- static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg) {
- (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
+ struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> : FunctorCallBase
+ {
+ static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg)
+ {
+ assertObjectType<Obj>(o);
+ call_internal<R>(arg, [&] {
+ return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
+ });
}
};
-#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
- struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> {
- static void call(SlotRet (Obj::*f)(SlotArgs...) noexcept, Obj *o, void **arg) {
- (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
+ struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> : FunctorCallBase
+ {
+ static void call(SlotRet (Obj::*f)(SlotArgs...) noexcept, Obj *o, void **arg)
+ {
+ assertObjectType<Obj>(o);
+ call_internal<R>(arg, [&]() noexcept {
+ return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
+ });
}
};
template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
- struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> {
- static void call(SlotRet (Obj::*f)(SlotArgs...) const noexcept, Obj *o, void **arg) {
- (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
+ struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> : FunctorCallBase
+ {
+ static void call(SlotRet (Obj::*f)(SlotArgs...) const noexcept, Obj *o, void **arg)
+ {
+ assertObjectType<Obj>(o);
+ call_internal<R>(arg, [&]() noexcept {
+ return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
+ });
}
};
-#endif
template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...)>
{
@@ -210,7 +225,6 @@ namespace QtPrivate {
}
};
-#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) noexcept>
{
typedef Obj Object;
@@ -247,15 +261,6 @@ namespace QtPrivate {
FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg);
}
};
-#endif
-
- template<typename Function, int N> struct Functor
- {
- template <typename SignalArgs, typename R>
- static void call(Function &f, void *, void **arg) {
- FunctorCall<typename Indexes<N>::Value, SignalArgs, R, Function>::call(f, arg);
- }
- };
// Traits to detect if there is a conversion between two types,
// and that conversion does not include a narrowing conversion.
@@ -290,10 +295,9 @@ namespace QtPrivate {
static_assert(CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::value)
*/
template<typename A1, typename A2> struct AreArgumentsCompatible {
- static int test(const typename RemoveRef<A2>::Type&);
+ static int test(const std::remove_reference_t<A2>&);
static char test(...);
- static const typename RemoveRef<A1>::Type &dummy();
- enum { value = sizeof(test(dummy())) == sizeof(int) };
+ enum { value = sizeof(test(std::declval<std::remove_reference_t<A1>>())) == sizeof(int) };
#ifdef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
using AreArgumentsConvertibleWithoutNarrowing = AreArgumentsConvertibleWithoutNarrowingBase<std::decay_t<A1>, std::decay_t<A2>>;
static_assert(AreArgumentsConvertibleWithoutNarrowing::value, "Signal and slot arguments are not compatible (narrowing)");
@@ -332,11 +336,10 @@ namespace QtPrivate {
template <typename Functor, typename... ArgList> struct ComputeFunctorArgumentCount<Functor, List<ArgList...>>
{
- template <typename D> static D dummy();
- template <typename F> static auto test(F f) -> decltype(((f.operator()((dummy<ArgList>())...)), int()));
+ template <typename F> static auto test(F f) -> decltype(((f.operator()((std::declval<ArgList>())...)), int()));
static char test(...);
enum {
- Ok = sizeof(test(dummy<Functor>())) == sizeof(int),
+ Ok = sizeof(test(std::declval<Functor>())) == sizeof(int),
Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
};
};
@@ -344,19 +347,118 @@ namespace QtPrivate {
/* get the return type of a functor, given the signal argument list */
template <typename Functor, typename ArgList> struct FunctorReturnType;
template <typename Functor, typename ... ArgList> struct FunctorReturnType<Functor, List<ArgList...>> {
- template <typename D> static D dummy();
- typedef decltype(dummy<Functor>().operator()((dummy<ArgList>())...)) Value;
+ typedef decltype(std::declval<Functor>().operator()((std::declval<ArgList>())...)) Value;
+ };
+
+ template<typename Func, typename... Args>
+ struct FunctorCallable
+ {
+ using ReturnType = decltype(std::declval<Func>()(std::declval<Args>()...));
+ using Function = ReturnType(*)(Args...);
+ enum {ArgumentCount = sizeof...(Args)};
+ using Arguments = QtPrivate::List<Args...>;
+
+ template <typename SignalArgs, typename R>
+ static void call(Func &f, void *, void **arg) {
+ FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Func>::call(f, arg);
+ }
+ };
+
+ template <typename Functor, typename... Args>
+ struct HasCallOperatorAcceptingArgs
+ {
+ private:
+ template <typename F, typename = void>
+ struct Test : std::false_type
+ {
+ };
+ // We explicitly use .operator() to not return true for pointers to free/static function
+ template <typename F>
+ struct Test<F, std::void_t<decltype(std::declval<F>().operator()(std::declval<Args>()...))>>
+ : std::true_type
+ {
+ };
+
+ public:
+ using Type = Test<Functor>;
+ static constexpr bool value = Type::value;
+ };
+
+ template <typename Functor, typename... Args>
+ constexpr bool
+ HasCallOperatorAcceptingArgs_v = HasCallOperatorAcceptingArgs<Functor, Args...>::value;
+
+ template <typename Func, typename... Args>
+ struct CallableHelper
+ {
+ private:
+ // Could've been std::conditional_t, but that requires all branches to
+ // be valid
+ static auto Resolve(std::true_type CallOperator) -> FunctorCallable<Func, Args...>;
+ static auto Resolve(std::false_type CallOperator) -> FunctionPointer<std::decay_t<Func>>;
+
+ public:
+ using Type = decltype(Resolve(typename HasCallOperatorAcceptingArgs<std::decay_t<Func>,
+ Args...>::Type{}));
};
+ template<typename Func, typename... Args>
+ struct Callable : CallableHelper<Func, Args...>::Type
+ {};
+ template<typename Func, typename... Args>
+ struct Callable<Func, List<Args...>> : CallableHelper<Func, Args...>::Type
+ {};
+
+ /*
+ Wrapper around ComputeFunctorArgumentCount and CheckCompatibleArgument,
+ depending on whether \a Functor is a PMF or not. Returns -1 if \a Func is
+ not compatible with the \a ExpectedArguments, otherwise returns >= 0.
+ */
+ template<typename Prototype, typename Functor>
+ inline constexpr std::enable_if_t<!std::disjunction_v<std::is_convertible<Prototype, const char *>,
+ std::is_same<std::decay_t<Prototype>, QMetaMethod>,
+ std::is_convertible<Functor, const char *>,
+ std::is_same<std::decay_t<Functor>, QMetaMethod>
+ >,
+ int>
+ countMatchingArguments()
+ {
+ using ExpectedArguments = typename QtPrivate::FunctionPointer<Prototype>::Arguments;
+ using Actual = std::decay_t<Functor>;
+
+ if constexpr (QtPrivate::FunctionPointer<Actual>::IsPointerToMemberFunction
+ || QtPrivate::FunctionPointer<Actual>::ArgumentCount >= 0) {
+ // PMF or free function
+ using ActualArguments = typename QtPrivate::FunctionPointer<Actual>::Arguments;
+ if constexpr (QtPrivate::CheckCompatibleArguments<ExpectedArguments, ActualArguments>::value)
+ return QtPrivate::FunctionPointer<Actual>::ArgumentCount;
+ else
+ return -1;
+ } else {
+ // lambda or functor
+ return QtPrivate::ComputeFunctorArgumentCount<Actual, ExpectedArguments>::Value;
+ }
+ }
+
// internal base class (interface) containing functions required to call a slot managed by a pointer to function.
- class QSlotObjectBase {
- QAtomicInt m_ref;
- // don't use virtual functions here; we don't want the
+ class QSlotObjectBase
+ {
+ // Don't use virtual functions here; we don't want the
// compiler to create tons of per-polymorphic-class stuff that
- // we'll never need. We just use one function pointer.
+ // we'll never need. We just use one function pointer, and the
+ // Operations enum below to distinguish requests
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QAtomicInt m_ref = 1;
typedef void (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret);
const ImplFn m_impl;
+#else
+ using ImplFn = void (*)(QSlotObjectBase* this_, QObject *receiver, void **args, int which, bool *ret);
+ const ImplFn m_impl;
+ QAtomicInt m_ref = 1;
+#endif
protected:
+ // The operations that can be requested by calls to m_impl,
+ // see the member functions that call m_impl below for details
enum Operation {
Destroy,
Call,
@@ -365,80 +467,197 @@ namespace QtPrivate {
NumOperations
};
public:
- explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {}
+ explicit QSlotObjectBase(ImplFn fn) : m_impl(fn) {}
+
+ // A custom deleter compatible with std protocols (op()()) we well as
+ // the legacy QScopedPointer protocol (cleanup()).
+ struct Deleter {
+ void operator()(QSlotObjectBase *p) const noexcept
+ { if (p) p->destroyIfLastRef(); }
+ // for the non-standard QScopedPointer protocol:
+ static void cleanup(QSlotObjectBase *p) noexcept { Deleter{}(p); }
+ };
- inline int ref() noexcept { return m_ref.ref(); }
+ bool ref() noexcept { return m_ref.ref(); }
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
inline void destroyIfLastRef() noexcept
{ if (!m_ref.deref()) m_impl(Destroy, this, nullptr, nullptr, nullptr); }
inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, nullptr, a, &ret); return ret; }
- inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, nullptr); }
+ inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, nullptr); }
+#else
+ inline void destroyIfLastRef() noexcept
+ { if (!m_ref.deref()) m_impl(this, nullptr, nullptr, Destroy, nullptr); }
+
+ inline bool compare(void **a)
+ {
+ bool ret = false;
+ m_impl(this, nullptr, a, Compare, &ret);
+ return ret;
+ }
+ inline void call(QObject *r, void **a) { m_impl(this, r, a, Call, nullptr); }
+#endif
+ bool isImpl(ImplFn f) const { return m_impl == f; }
protected:
~QSlotObjectBase() {}
private:
Q_DISABLE_COPY_MOVE(QSlotObjectBase)
};
- // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject
- // Args and R are the List of arguments and the return type of the signal to which the slot is connected.
- template<typename Func, typename Args, typename R> class QSlotObject : public QSlotObjectBase
+ using SlotObjUniquePtr = std::unique_ptr<QSlotObjectBase,
+ QSlotObjectBase::Deleter>;
+ inline SlotObjUniquePtr copy(const SlotObjUniquePtr &other) noexcept
{
- typedef QtPrivate::FunctionPointer<Func> FuncType;
- Func function;
- static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
+ if (other)
+ other->ref();
+ return SlotObjUniquePtr{other.get()};
+ }
+
+ class SlotObjSharedPtr {
+ SlotObjUniquePtr obj;
+ public:
+ Q_NODISCARD_CTOR Q_IMPLICIT SlotObjSharedPtr() noexcept = default;
+ Q_NODISCARD_CTOR Q_IMPLICIT SlotObjSharedPtr(std::nullptr_t) noexcept : SlotObjSharedPtr() {}
+ Q_NODISCARD_CTOR explicit SlotObjSharedPtr(SlotObjUniquePtr o)
+ : obj(std::move(o))
{
- switch (which) {
- case Destroy:
- delete static_cast<QSlotObject*>(this_);
- break;
- case Call:
- FuncType::template call<Args, R>(static_cast<QSlotObject*>(this_)->function, static_cast<typename FuncType::Object *>(r), a);
- break;
- case Compare:
- *ret = *reinterpret_cast<Func *>(a) == static_cast<QSlotObject*>(this_)->function;
- break;
- case NumOperations: ;
- }
+ // does NOT ref() (takes unique_ptr by value)
+ // (that's why (QSlotObjectBase*) ctor doesn't exisit: don't know whether that one _should_)
}
- public:
- explicit QSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
+ Q_NODISCARD_CTOR SlotObjSharedPtr(const SlotObjSharedPtr &other) noexcept
+ : obj{copy(other.obj)} {}
+ SlotObjSharedPtr &operator=(const SlotObjSharedPtr &other) noexcept
+ { auto copy = other; swap(copy); return *this; }
+
+ Q_NODISCARD_CTOR SlotObjSharedPtr(SlotObjSharedPtr &&other) noexcept = default;
+ SlotObjSharedPtr &operator=(SlotObjSharedPtr &&other) noexcept = default;
+ ~SlotObjSharedPtr() = default;
+
+ void swap(SlotObjSharedPtr &other) noexcept { obj.swap(other.obj); }
+
+ auto get() const noexcept { return obj.get(); }
+ auto operator->() const noexcept { return get(); }
+
+ explicit operator bool() const noexcept { return bool(obj); }
};
- // implementation of QSlotObjectBase for which the slot is a functor (or lambda)
- // N is the number of arguments
+
+
+ // Implementation of QSlotObjectBase for which the slot is a callable (function, PMF, functor, or lambda).
// Args and R are the List of arguments and the return type of the signal to which the slot is connected.
- template<typename Func, int N, typename Args, typename R> class QFunctorSlotObject : public QSlotObjectBase
+ template <typename Func, typename Args, typename R>
+ class QCallableObject : public QSlotObjectBase,
+ private QtPrivate::CompactStorage<std::decay_t<Func>>
{
- typedef QtPrivate::Functor<Func, N> FuncType;
- Func function;
- static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
+ using FunctorValue = std::decay_t<Func>;
+ using Storage = QtPrivate::CompactStorage<FunctorValue>;
+ using FuncType = Callable<Func, Args>;
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ Q_DECL_HIDDEN static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
+#else
+ // Design note: the first three arguments match those for typical Call
+ // and Destroy uses. We return void to enable tail call optimization
+ // for those too.
+ Q_DECL_HIDDEN static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret)
+#endif
{
+ const auto that = static_cast<QCallableObject*>(this_);
switch (which) {
case Destroy:
- delete static_cast<QFunctorSlotObject*>(this_);
+ delete that;
break;
case Call:
- FuncType::template call<Args, R>(static_cast<QFunctorSlotObject*>(this_)->function, r, a);
+ if constexpr (std::is_member_function_pointer_v<FunctorValue>)
+ FuncType::template call<Args, R>(that->object(), static_cast<typename FuncType::Object *>(r), a);
+ else
+ FuncType::template call<Args, R>(that->object(), r, a);
break;
- case Compare: // not implemented
+ case Compare:
+ if constexpr (std::is_member_function_pointer_v<FunctorValue>) {
+ *ret = *reinterpret_cast<FunctorValue *>(a) == that->object();
+ break;
+ }
+ // not implemented otherwise
+ Q_FALLTHROUGH();
case NumOperations:
Q_UNUSED(ret);
}
}
public:
- explicit QFunctorSlotObject(Func f) : QSlotObjectBase(&impl), function(std::move(f)) {}
+ explicit QCallableObject(Func &&f) : QSlotObjectBase(&impl), Storage{std::move(f)} {}
+ explicit QCallableObject(const Func &f) : QSlotObjectBase(&impl), Storage{f} {}
};
- // typedefs for readability for when there are no parameters
+ // Helper to detect the context object type based on the functor type:
+ // QObject for free functions and lambdas; the callee for member function
+ // pointers. The default declaration doesn't have the ContextType typedef,
+ // and so non-functor APIs (like old-style string-based slots) are removed
+ // from the overload set.
+ template <typename Func, typename = void>
+ struct ContextTypeForFunctor {};
+
template <typename Func>
- using QSlotObjectWithNoArgs = QSlotObject<Func,
- QtPrivate::List<>,
- typename QtPrivate::FunctionPointer<Func>::ReturnType>;
+ struct ContextTypeForFunctor<Func,
+ std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
+ std::is_member_function_pointer<Func>
+ >
+ >
+ >
+ {
+ using ContextType = QObject;
+ };
+ template <typename Func>
+ struct ContextTypeForFunctor<Func,
+ std::enable_if_t<std::conjunction_v<std::negation<std::is_convertible<Func, const char *>>,
+ std::is_member_function_pointer<Func>,
+ std::is_convertible<typename QtPrivate::FunctionPointer<Func>::Object *, QObject *>
+ >
+ >
+ >
+ {
+ using ContextType = typename QtPrivate::FunctionPointer<Func>::Object;
+ };
- template <typename Func, typename R>
- using QFunctorSlotObjectWithNoArgs = QFunctorSlotObject<Func, 0, QtPrivate::List<>, R>;
+ /*
+ Returns a suitable QSlotObjectBase object that holds \a func, if possible.
- template <typename Func>
- using QFunctorSlotObjectWithNoArgsImplicitReturn = QFunctorSlotObjectWithNoArgs<Func, typename QtPrivate::FunctionPointer<Func>::ReturnType>;
+ Not available (and thus produces compile-time errors) if the Functor provided is
+ not compatible with the expected Prototype.
+ */
+ template <typename Prototype, typename Functor>
+ static constexpr std::enable_if_t<QtPrivate::countMatchingArguments<Prototype, Functor>() >= 0,
+ QtPrivate::QSlotObjectBase *>
+ makeCallableObject(Functor &&func)
+ {
+ using ExpectedSignature = QtPrivate::FunctionPointer<Prototype>;
+ using ExpectedReturnType = typename ExpectedSignature::ReturnType;
+ using ExpectedArguments = typename ExpectedSignature::Arguments;
+
+ using ActualSignature = QtPrivate::FunctionPointer<Functor>;
+ constexpr int MatchingArgumentCount = QtPrivate::countMatchingArguments<Prototype, Functor>();
+ using ActualArguments = typename QtPrivate::List_Left<ExpectedArguments, MatchingArgumentCount>::Value;
+
+ static_assert(int(ActualSignature::ArgumentCount) <= int(ExpectedSignature::ArgumentCount),
+ "Functor requires more arguments than what can be provided.");
+
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ return new QtPrivate::QCallableObject<std::decay_t<Functor>, ActualArguments, ExpectedReturnType>(std::forward<Functor>(func));
+ }
+
+ template<typename Prototype, typename Functor, typename = void>
+ struct AreFunctionsCompatible : std::false_type {};
+ template<typename Prototype, typename Functor>
+ struct AreFunctionsCompatible<Prototype, Functor, std::enable_if_t<
+ std::is_same_v<decltype(QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(std::declval<Functor>()))),
+ QtPrivate::QSlotObjectBase *>>
+ > : std::true_type {};
+
+ template<typename Prototype, typename Functor>
+ inline constexpr bool AssertCompatibleFunctions() {
+ static_assert(AreFunctionsCompatible<Prototype, Functor>::value,
+ "Functor is not compatible with expected prototype!");
+ return true;
+ }
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpermissions.cpp b/src/corelib/kernel/qpermissions.cpp
new file mode 100644
index 0000000000..d0d2d9eb10
--- /dev/null
+++ b/src/corelib/kernel/qpermissions.cpp
@@ -0,0 +1,693 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qpermissions.h"
+#include "qpermissions_p.h"
+#include "qhashfunctions.h"
+
+#include <QtCore/qshareddata.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg);
+
+/*!
+ \page permissions.html
+ \title Application Permissions
+ \brief Managing application permissions
+
+ Many features of today's devices and operating systems can have
+ significant privacy, security, and performance implications if
+ misused. It's therefore increasingly common for platforms to
+ require explicit consent from the user before accessing these
+ features.
+
+ The Qt permission APIs allow the application to check or request
+ permission for such features in a cross platform manner.
+
+ \section1 Usage
+
+ A feature that commonly requires user consent is access to the
+ microphone of the device. An application for recording voice
+ memos would perhaps look something like this initially:
+
+ \code
+ void VoiceMemoWidget::onRecordingInitiated()
+ {
+ m_microphone->startRecording();
+ }
+ \endcode
+
+ To ensure this application works well on platforms that
+ require user consent for microphone access we would extend
+ it like this:
+
+ \code
+ void VoiceMemoWidget::onRecordingInitiated()
+ {
+ QMicrophonePermission microphonePermission;
+ switch (qApp->checkPermission(microphonePermission)) {
+ case Qt::PermissionStatus::Undetermined:
+ qApp->requestPermission(microphonePermission, this,
+ &VoiceMemoWidget::onRecordingInitiated);
+ return;
+ case Qt::PermissionStatus::Denied:
+ m_permissionInstructionsDialog->show();
+ return;
+ case Qt::PermissionStatus::Granted:
+ m_microphone->startRecording();
+ }
+ }
+ \endcode
+
+ We first check if we already know the status of the microphone permission.
+ If we don't we initiate a permission request to determine the current
+ status, which will potentially ask the user for consent. We connect the
+ result of the request to the slot we're already in, so that we get another
+ chance at evaluating the permission status.
+
+ Once the permission status is known, either because we had been granted or
+ denied permission at an earlier time, or after getting the result back from
+ the request we just initiated, we redirect the user to a dialog explaining
+ why we can not record voice memos at this time (if the permission was denied),
+ or proceed to using the microphone (if permission was granted).
+
+ \note On \macOS and iOS permissions can currently only be requested for
+ GUI applications.
+
+ \section2 Declaring Permissions
+
+ Some platforms require that the permissions you request are declared
+ up front at build time.
+
+ \section3 Apple platforms
+ \target apple-usage-description
+
+ Each permission you request must be accompanied by a so called
+ \e {usage description} string in the application's \c Info.plist
+ file, describing why the application needs to access the given
+ permission. For example:
+
+ \badcode
+ <key>NSMicrophoneUsageDescription</key>
+ <string>The microphone is used to record voice memos.</string>
+ \endcode
+
+ The relevant usage description keys are described in the documentation
+ for each permission type.
+
+ \sa {Information Property List Files}.
+
+ \section3 Android
+ \target android-uses-permission
+
+ Each permission you request must be accompanied by a \c uses-permission
+ entry in the application's \c AndroidManifest.xml file. For example:
+
+ \badcode
+ <manifest ...>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ </manifest>
+ \endcode
+
+ The relevant permission names are described in the documentation
+ for each permission type.
+
+ \sa {Qt Creator: Editing Manifest Files}.
+
+ \section1 Available Permissions
+
+ The following permissions types are available:
+
+ \annotatedlist permissions
+
+ \section1 Best Practices
+
+ To ensure the best possible user experience for the end user we recommend
+ adopting the following best practices for managing application permissions:
+
+ \list
+
+ \li Request the minimal set of permissions needed. For example, if you only
+ need access to the microphone, do \e not request camera permission just in case.
+ Use the properties of individual permission types to limit the permission scope
+ even further, for example QContactsPermission::setReadOnly() to request read
+ only access.
+
+ \li Request permissions in response to specific actions by the user. For example,
+ defer requesting microphone permission until the user presses the button to record
+ audio. Associating the permission request to a specific action gives the user a clearer
+ context of why the permission is needed. Do \e not request all needed permission on
+ startup.
+
+ \li Present extra context and explanation if needed. Sometimes the action by the user
+ is not enough context. Consider presenting an explanation-dialog after the user has
+ initiated the action, but before requesting the permission, so the user is aware of
+ what's about to happen when the system permission dialog subsequently pops up.
+
+ \li Be transparent and explicit about why permissions are needed. In explanation
+ dialogs and usage descriptions, be transparent about why the particular permission
+ is needed for your application to provide a specific feature, so users can make
+ informed decisions.
+
+ \li Account for denied permissions. The permissions you request may be denied
+ for various reasons. You should always account for this situation, by gracefully
+ degrading the experience of your application, and presenting clear explanations
+ the user about the situation.
+
+ \li Never request permissions from a library. The request of permissions should
+ be done as close as possible to the user, where the information needed to make
+ good decisions on the points above is available. Libraries can check permissions,
+ to ensure they have the prerequisites for doing their work, but if the permission
+ is undetermined or denied this should be reflected through the library's API,
+ so that the application in turn can request the necessary permissions.
+
+ \endlist
+*/
+
+
+/*!
+ \class QPermission
+ \inmodule QtCore
+ \inheaderfile QPermissions
+ \since 6.5
+ \brief An opaque wrapper of a typed permission.
+
+ The QPermission class is an opaque wrapper of a \l{typed permission},
+ used when checking or requesting permissions. You do not need to construct
+ this type explicitly, as the type is automatically used when checking or
+ requesting permissions:
+
+ \code
+ qApp->checkPermission(QCameraPermission{});
+ \endcode
+
+ When requesting permissions, the given functor will
+ be passed an instance of a QPermission, which can be used
+ to check the result of the request:
+
+ \code
+ qApp->requestPermission(QCameraPermission{}, [](const QPermission &permission) {
+ if (permission.status() == Qt::PermissionStatus:Granted)
+ takePhoto();
+ });
+ \endcode
+
+ To inspect the properties of the original, typed permission,
+ use the \l {QPermission::}{value()} function:
+
+ \code
+ QLocationPermission locationPermission;
+ locationPermission.setAccuracy(QLocationPermission::Precise);
+ qApp->requestPermission(locationPermission, this, &LocationWidget::permissionUpdated);
+ \endcode
+
+ \code
+ void LocationWidget::permissionUpdated(const QPermission &permission)
+ {
+ if (permission.status() != Qt::PermissionStatus:Granted)
+ return;
+ auto locationPermission = permission.value<QLocationPermission>();
+ if (!locationPermission || locationPermission->accuracy() != QLocationPermission::Precise)
+ return;
+ updatePreciseLocation();
+ }
+ \endcode
+
+ \target typed permission
+ \section2 Typed Permissions
+
+ The following permissions are available:
+
+ \annotatedlist permissions
+
+ \sa {Application Permissions}
+*/
+
+/*!
+ \fn template <typename T, QPermission::if_permission<T>> QPermission::QPermission(const T &type)
+
+ Constructs a permission from the given \l{typed permission} \a type.
+
+ You do not need to construct this type explicitly, as the type is automatically
+ used when checking or requesting permissions.
+
+ This constructor participates in overload resolution only if \c T is one of
+ the \l{typed permission} classes:
+
+ \annotatedlist permissions
+*/
+
+/*!
+ \fn template <typename T, QPermission::if_permission<T>> std::optional<T> QPermission::value() const
+
+ Returns the \l{typed permission} of type \c T, or \c{std::nullopt} if this
+ QPermission object doesn't contain one.
+
+ Use type() for dynamically choosing which typed permission to request.
+
+ This function participates in overload resolution only if \c T is one of
+ the \l{typed permission} classes:
+
+ \annotatedlist permissions
+*/
+
+/*!
+ \fn Qt::PermissionStatus QPermission::status() const
+ Returns the status of the permission.
+*/
+
+/*!
+ \fn QMetaType QPermission::type() const
+ Returns the type of the permission.
+*/
+
+/*
+ \internal
+*/
+const void *QPermission::data(QMetaType requestedType) const
+{
+ const auto actualType = type();
+ if (requestedType != actualType)
+ return nullptr;
+ return m_data.data();
+}
+
+// check alignof(AlignmentCheck) instead of alignof(void*), in case
+// pointers have different alignment inside structs:
+struct AlignmentCheck { void *p; };
+
+#define QT_PERMISSION_IMPL_COMMON(ClassName) \
+ /* Class##Private is unused until we need it: */ \
+ static_assert(sizeof(ClassName) == sizeof(void*), \
+ "You have added too many members to " #ClassName "::ShortData. " \
+ "Decrease their size or switch to using a d-pointer."); \
+ static_assert(alignof(ClassName) == alignof(AlignmentCheck), \
+ "You have added members to " #ClassName "::ShortData that are overaligned. " \
+ "Decrease their alignment or switch to using a d-pointer."); \
+ ClassName::ClassName(const ClassName &other) noexcept = default; \
+ ClassName::~ClassName() = default; \
+ ClassName &ClassName::operator=(const ClassName &other) noexcept = default; \
+ ClassName::ClassName() \
+ /* impl supplied by caller */
+
+
+/*!
+ \class QCameraPermission
+ \brief Access the camera for taking pictures or videos.
+
+ \section1 Requirements
+
+ \include permissions.qdocinc begin-usage-declarations
+ \row
+ \li Apple
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSCameraUsageDescription
+ \row
+ \li Android
+ \li \l{android-uses-permission}{\c{uses-permission}}
+ \li \c android.permission.CAMERA
+ \include permissions.qdocinc end-usage-declarations
+
+ \include permissions.qdocinc permission-metadata
+*/
+
+QT_PERMISSION_IMPL_COMMON(QCameraPermission)
+ : u{} // stateless, atm
+{}
+
+/*!
+ \class QMicrophonePermission
+ \brief Access the microphone for monitoring or recording sound.
+
+ \section1 Requirements
+
+ \include permissions.qdocinc begin-usage-declarations
+ \row
+ \li Apple
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSMicrophoneUsageDescription
+ \row
+ \li Android
+ \li \l{android-uses-permission}{\c{uses-permission}}
+ \li \c android.permission.RECORD_AUDIO
+ \include permissions.qdocinc end-usage-declarations
+
+ \include permissions.qdocinc permission-metadata
+*/
+
+QT_PERMISSION_IMPL_COMMON(QMicrophonePermission)
+ : u{} // stateless, atm
+{}
+
+/*!
+ \class QBluetoothPermission
+ \brief Access Bluetooth peripherals.
+
+ \section1 Requirements
+
+ \include permissions.qdocinc begin-usage-declarations
+ \row
+ \li Apple
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSBluetoothAlwaysUsageDescription
+ \row
+ \li Android
+ \li \l{android-uses-permission}{\c{uses-permission}}
+ \li Up to Android 11 (API Level < 31):
+ \list
+ \li \c android.permission.BLUETOOTH
+ \li \c android.permission.ACCESS_FINE_LOCATION
+ \endlist
+
+ Starting from Android 12 (API Level >= 31):
+ \list
+ \li \c android.permission.BLUETOOTH_ADVERTISE
+ \li \c android.permission.BLUETOOTH_CONNECT
+ \li \c android.permission.BLUETOOTH_SCAN
+ \li \c android.permission.ACCESS_FINE_LOCATION
+ \endlist
+ \include permissions.qdocinc end-usage-declarations
+
+ \note Currently on Android the \c android.permission.ACCESS_FINE_LOCATION
+ permission is requested together with Bluetooth permissions. This is
+ required for Bluetooth to work properly, unless the application provides a
+ strong assertion in the application manifest that it does not use Bluetooth
+ to derive a physical location. This permission coupling may change in
+ future.
+
+ \include permissions.qdocinc permission-metadata
+*/
+
+QT_PERMISSION_IMPL_COMMON(QBluetoothPermission)
+ : u{ShortData{CommunicationMode::Default, {}}}
+{}
+
+/*!
+ \enum QBluetoothPermission::CommunicationMode
+ \since 6.6
+
+ This enum is used to control the allowed Bluetooth communication modes.
+
+ \value Access Allow this device to access other Bluetooth devices. This
+ includes scanning for nearby devices and connecting to them.
+ \value Advertise Allow other Bluetooth devices to discover this device.
+ \value Default This configuration is used by default.
+
+ \note The fine-grained permissions are currently supported only on
+ Android 12 and newer. On older Android versions, as well as on Apple
+ operating systems, any mode results in full Bluetooth access.
+
+ \note For now the \c Access mode on Android also requests the
+ \l {QLocationPermission::Precise}{precise location} permission.
+ This permission coupling may change in the future.
+*/
+
+/*!
+ \since 6.6
+
+ Sets the allowed Bluetooth communication modes to \a modes.
+
+ \note A default-constructed instance of \l {QBluetoothPermission::}
+ {CommunicationModes} has no sense, so an attempt to set such a mode will
+ raise a \c {qWarning()} and fall back to using the
+ \l {QBluetoothPermission::}{Default} mode.
+*/
+void QBluetoothPermission::setCommunicationModes(CommunicationModes modes)
+{
+ if (modes == CommunicationModes{}) {
+ qCWarning(lcPermissions, "QBluetoothPermission: trying to set an invalid empty mode. "
+ "Falling back to CommunicationMode::Default.");
+ u.data.mode = Default;
+ } else {
+ u.data.mode = static_cast<CommunicationMode>(modes.toInt());
+ }
+}
+
+/*!
+ \since 6.6
+
+ Returns the allowed Bluetooth communication modes.
+*/
+QBluetoothPermission::CommunicationModes QBluetoothPermission::communicationModes() const
+{
+ return u.data.mode;
+}
+
+/*!
+ \class QLocationPermission
+ \brief Access the user's location.
+
+ By default the request is for approximate accuracy,
+ and only while the application is in use. Use
+ setAccuracy() and/or setAvailability() to override
+ the default.
+
+ \section1 Requirements
+
+ \include permissions.qdocinc begin-usage-declarations
+ \row
+ \li \macos
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSLocationUsageDescription
+ \row
+ \li iOS
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSLocationWhenInUseUsageDescription, and
+ \c NSLocationAlwaysAndWhenInUseUsageDescription if requesting
+ QLocationPermission::Always
+ \row
+ \li Android
+ \li \l{android-uses-permission}{\c{uses-permission}}
+ \li \list
+ \li \c android.permission.ACCESS_FINE_LOCATION for QLocationPermission::Precise
+ \li \c android.permission.ACCESS_COARSE_LOCATION for QLocationPermission::Approximate
+ \li \c android.permission.ACCESS_BACKGROUND_LOCATION for QLocationPermission::Always
+ \endlist
+ \note QLocationPermission::Always \c uses-permission string has
+ to be combined with one or both of QLocationPermission::Precise
+ and QLocationPermission::Approximate strings.
+ \include permissions.qdocinc end-usage-declarations
+
+ \include permissions.qdocinc permission-metadata
+*/
+
+QT_PERMISSION_IMPL_COMMON(QLocationPermission)
+ : u{ShortData{Accuracy::Approximate, Availability::WhenInUse, {}}}
+{}
+
+/*!
+ \enum QLocationPermission::Accuracy
+
+ This enum is used to control the accuracy of the location data.
+
+ \value Approximate An approximate location is requested.
+ \value Precise A precise location is requested.
+*/
+
+/*!
+ \enum QLocationPermission::Availability
+
+ This enum is used to control the availability of the location data.
+
+ \value WhenInUse The location is only available only when the
+ application is in use.
+ \value Always The location is available at all times, including when
+ the application is in the background.
+*/
+
+/*!
+ Sets the desired \a accuracy of the request.
+*/
+void QLocationPermission::setAccuracy(Accuracy accuracy)
+{
+ u.data.accuracy = accuracy;
+}
+
+/*!
+ Returns the accuracy of the request.
+*/
+QLocationPermission::Accuracy QLocationPermission::accuracy() const
+{
+ return u.data.accuracy;
+}
+
+/*!
+ Sets the desired \a availability of the request.
+*/
+void QLocationPermission::setAvailability(Availability availability)
+{
+ u.data.availability = availability;
+}
+
+/*!
+ Returns the availability of the request.
+*/
+QLocationPermission::Availability QLocationPermission::availability() const
+{
+ return u.data.availability;
+}
+
+/*!
+ \class QContactsPermission
+ \brief Access the user's contacts.
+
+ By default the request is for read-only access.
+ Use setAccessMode() to override the default.
+
+ \section1 Requirements
+
+ \include permissions.qdocinc begin-usage-declarations
+ \row
+ \li Apple
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSContactsUsageDescription
+ \row
+ \li Android
+ \li \l{android-uses-permission}{\c{uses-permission}}
+ \li \c android.permission.READ_CONTACTS. \c android.permission.WRITE_CONTACTS if
+ QContactsPermission::accessMode() is set to AccessMode::ReadWrite.
+ \include permissions.qdocinc end-usage-declarations
+
+ \include permissions.qdocinc permission-metadata
+*/
+
+/*!
+ \enum QContactsPermission::AccessMode
+
+ This enum is used to control access to the contacts data.
+
+ \value ReadOnly Read-only access to the contacts data (the default).
+ \value ReadWrite Read and write access to the contacts data.
+
+ \sa setAccessMode, accessMode
+*/
+
+QT_PERMISSION_IMPL_COMMON(QContactsPermission)
+ : u{ShortData{AccessMode::ReadOnly, {}}}
+{}
+
+/*!
+ Sets whether the request is for read-write (\a mode == AccessMode::ReadOnly) or
+ read-only (\a mode == AccessMode::ReadOnly) access to the contacts.
+*/
+void QContactsPermission::setAccessMode(AccessMode mode)
+{
+ u.data.mode = mode;
+}
+
+/*!
+ Returns AccessMode::ReadWrite when the request is for read-write and
+ AccessMode::ReadOnly when it is for read-only access to the contacts.
+*/
+QContactsPermission::AccessMode QContactsPermission::accessMode() const
+{
+ return u.data.mode;
+}
+
+/*!
+ \class QCalendarPermission
+ \brief Access the user's calendar.
+
+ By default the request is for read-only access.
+ Use setAccessMode() to override the default.
+
+ \section1 Requirements
+
+ \include permissions.qdocinc begin-usage-declarations
+ \row
+ \li Apple
+ \li \l{apple-usage-description}{Usage description}
+ \li \c NSCalendarsUsageDescription
+ \row
+ \li Android
+ \li \l{android-uses-permission}{\c{uses-permission}}
+ \li \c android.permission.READ_CALENDAR. \c android.permission.WRITE_CALENDAR if
+ QCalendarPermission::accessMode() is set to AccessMode::ReadWrite.
+ \include permissions.qdocinc end-usage-declarations
+
+ \include permissions.qdocinc permission-metadata
+*/
+
+/*!
+ \enum QCalendarPermission::AccessMode
+
+ This enum is used to control access to the calendar data.
+
+ \value ReadOnly Read-only access to the calendar data (the default).
+ \value ReadWrite Read and write access to the calendar data.
+
+ \sa setAccessMode, accessMode
+*/
+
+QT_PERMISSION_IMPL_COMMON(QCalendarPermission)
+ : u{ShortData{AccessMode::ReadOnly, {}}}
+{}
+
+/*!
+ Sets whether the request is for read-write (\a mode == AccessMode::ReadOnly) or
+ read-only (\a mode == AccessMode::ReadOnly) access to the calendar.
+*/
+void QCalendarPermission::setAccessMode(AccessMode mode)
+{
+ u.data.mode = mode;
+}
+
+/*!
+ Returns AccessMode::ReadWrite when the request is for read-write and
+ AccessMode::ReadOnly when it is for read-only access to the calendar.
+*/
+QCalendarPermission::AccessMode QCalendarPermission::accessMode() const
+{
+ return u.data.mode;
+}
+
+/*!
+ * \internal
+*/
+
+QPermissionPlugin::~QPermissionPlugin() = default;
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QPermission &permission)
+{
+ const auto verbosity = debug.verbosity();
+ QDebugStateSaver saver(debug);
+ debug.nospace().setVerbosity(0);
+ if (verbosity >= QDebug::DefaultVerbosity)
+ debug << permission.type().name() << "(";
+ debug << permission.status();
+ if (verbosity >= QDebug::DefaultVerbosity)
+ debug << ")";
+ return debug;
+}
+#endif
+
+#undef QT_PERMISSION_IMPL_COMMON
+
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WASM)
+// Default backend for platforms without a permission implementation.
+// Always returns Granted, to match behavior when not using permission APIs
+// https://bugreports.qt.io/browse/QTBUG-90498?focusedCommentId=725085#comment-725085
+namespace QPermissions::Private
+{
+ Qt::PermissionStatus checkPermission(const QPermission &permission)
+ {
+ qCDebug(lcPermissions) << "No permission backend on this platform."
+ << "Optimistically returning Granted for" << permission;
+ return Qt::PermissionStatus::Granted;
+ }
+
+ void requestPermission(const QPermission &permission, const PermissionCallback &callback)
+ {
+ qCDebug(lcPermissions) << "No permission backend on this platform."
+ << "Optimistically returning Granted for" << permission;
+ callback(Qt::PermissionStatus::Granted);
+ }
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "moc_qpermissions.cpp"
diff --git a/src/corelib/kernel/qpermissions.h b/src/corelib/kernel/qpermissions.h
new file mode 100644
index 0000000000..9573e377e5
--- /dev/null
+++ b/src/corelib/kernel/qpermissions.h
@@ -0,0 +1,219 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPERMISSIONS_H
+#define QPERMISSIONS_H
+
+#if 0
+#pragma qt_class(QPermissions)
+#endif
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qtmetamacros.h>
+#include <QtCore/qvariant.h>
+
+#include <QtCore/qshareddata_impl.h>
+#include <QtCore/qtypeinfo.h>
+#include <QtCore/qmetatype.h>
+
+#include <optional>
+
+#if !defined(Q_QDOC)
+QT_REQUIRE_CONFIG(permissions);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+#endif
+
+struct QMetaObject;
+class QCoreApplication;
+
+class QPermission
+{
+ template <typename T, typename Enable = void>
+ static constexpr inline bool is_permission_v = false;
+
+ template <typename T>
+ using if_permission = std::enable_if_t<is_permission_v<T>, bool>;
+public:
+ explicit QPermission() = default;
+
+ template <typename T, if_permission<T> = true>
+ QPermission(const T &t) : m_data(QVariant::fromValue(t)) {}
+
+ Qt::PermissionStatus status() const { return m_status; }
+
+ QMetaType type() const { return m_data.metaType(); }
+
+ template <typename T, if_permission<T> = true>
+ std::optional<T> value() const
+ {
+ if (auto p = data(QMetaType::fromType<T>()))
+ return *static_cast<const T *>(p);
+ return std::nullopt;
+ }
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QPermission &);
+#endif
+
+private:
+ Q_CORE_EXPORT const void *data(QMetaType id) const;
+
+ Qt::PermissionStatus m_status = Qt::PermissionStatus::Undetermined;
+ QVariant m_data;
+
+ friend class QCoreApplication;
+};
+
+template <typename T>
+constexpr bool QPermission::is_permission_v<T, typename T::QtPermissionHelper> = true;
+
+#define QT_PERMISSION(ClassName) \
+ using QtPermissionHelper = void; \
+ friend class QPermission; \
+ union U { \
+ U() : d(nullptr) {} \
+ U(ShortData _data) : data(_data) {} \
+ U(ClassName##Private *_d) : d(_d) {} \
+ ShortData data; \
+ ClassName##Private *d; \
+ } u; \
+public: \
+ Q_CORE_EXPORT ClassName(); \
+ Q_CORE_EXPORT ClassName(const ClassName &other) noexcept; \
+ ClassName(ClassName &&other) noexcept \
+ : u{other.u} { other.u.d = nullptr; } \
+ Q_CORE_EXPORT ~ClassName(); \
+ Q_CORE_EXPORT ClassName &operator=(const ClassName &other) noexcept; \
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(ClassName) \
+ void swap(ClassName &other) noexcept { std::swap(u, other.u); } \
+private: \
+ /*end*/
+
+class QLocationPermissionPrivate;
+class QLocationPermission
+{
+ Q_GADGET_EXPORT(Q_CORE_EXPORT)
+public:
+ enum Accuracy : quint8 {
+ Approximate,
+ Precise,
+ };
+ Q_ENUM(Accuracy)
+
+ Q_CORE_EXPORT void setAccuracy(Accuracy accuracy);
+ Q_CORE_EXPORT Accuracy accuracy() const;
+
+ enum Availability : quint8 {
+ WhenInUse,
+ Always,
+ };
+ Q_ENUM(Availability)
+
+ Q_CORE_EXPORT void setAvailability(Availability availability);
+ Q_CORE_EXPORT Availability availability() const;
+
+private:
+ struct ShortData {
+ Accuracy accuracy;
+ Availability availability;
+ char reserved[sizeof(void*) - sizeof(accuracy) - sizeof(availability)];
+ };
+ QT_PERMISSION(QLocationPermission)
+};
+Q_DECLARE_SHARED(QLocationPermission)
+
+class QCalendarPermissionPrivate;
+class QCalendarPermission
+{
+ Q_GADGET_EXPORT(Q_CORE_EXPORT)
+public:
+ enum AccessMode : quint8 {
+ ReadOnly,
+ ReadWrite,
+ };
+ Q_ENUM(AccessMode)
+
+ Q_CORE_EXPORT void setAccessMode(AccessMode mode);
+ Q_CORE_EXPORT AccessMode accessMode() const;
+
+private:
+ struct ShortData {
+ AccessMode mode;
+ char reserved[sizeof(void*) - sizeof(mode)];
+ };
+ QT_PERMISSION(QCalendarPermission)
+};
+Q_DECLARE_SHARED(QCalendarPermission)
+
+class QContactsPermissionPrivate;
+class QContactsPermission
+{
+ Q_GADGET_EXPORT(Q_CORE_EXPORT)
+public:
+ enum AccessMode : quint8 {
+ ReadOnly,
+ ReadWrite,
+ };
+ Q_ENUM(AccessMode)
+
+ Q_CORE_EXPORT void setAccessMode(AccessMode mode);
+ Q_CORE_EXPORT AccessMode accessMode() const;
+
+private:
+ struct ShortData {
+ AccessMode mode;
+ char reserved[sizeof(void*) - sizeof(mode)];
+ };
+ QT_PERMISSION(QContactsPermission)
+};
+Q_DECLARE_SHARED(QContactsPermission)
+
+class QBluetoothPermissionPrivate;
+class QBluetoothPermission
+{
+ Q_GADGET_EXPORT(Q_CORE_EXPORT)
+public:
+ enum CommunicationMode : quint8 {
+ Access = 0x01,
+ Advertise = 0x02,
+ Default = Access | Advertise,
+ };
+ Q_DECLARE_FLAGS(CommunicationModes, CommunicationMode)
+ Q_FLAG(CommunicationModes)
+
+ Q_CORE_EXPORT void setCommunicationModes(CommunicationModes modes);
+ Q_CORE_EXPORT CommunicationModes communicationModes() const;
+
+private:
+ struct ShortData {
+ CommunicationMode mode;
+ char reserved[sizeof(void*) - sizeof(mode)];
+ };
+ QT_PERMISSION(QBluetoothPermission)
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothPermission::CommunicationModes)
+Q_DECLARE_SHARED(QBluetoothPermission)
+
+#define Q_DECLARE_MINIMAL_PERMISSION(ClassName) \
+ class ClassName##Private; \
+ class ClassName \
+ { \
+ struct ShortData { char reserved[sizeof(void*)]; }; \
+ QT_PERMISSION(ClassName) \
+ }; \
+ Q_DECLARE_SHARED(ClassName)
+
+Q_DECLARE_MINIMAL_PERMISSION(QCameraPermission)
+Q_DECLARE_MINIMAL_PERMISSION(QMicrophonePermission)
+
+#undef QT_PERMISSION
+#undef Q_DECLARE_MINIMAL_PERMISSION
+
+QT_END_NAMESPACE
+
+#endif // QPERMISSIONS_H
diff --git a/src/corelib/kernel/qpermissions_android.cpp b/src/corelib/kernel/qpermissions_android.cpp
new file mode 100644
index 0000000000..6c21ded72c
--- /dev/null
+++ b/src/corelib/kernel/qpermissions_android.cpp
@@ -0,0 +1,189 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qpermissions.h"
+#include "qpermissions_p.h"
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qfuture.h>
+#include <QtCore/qhash.h>
+
+#include "private/qandroidextras_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+static QStringList nativeLocationPermission(const QLocationPermission &permission)
+{
+ QStringList nativeLocationPermissionList;
+ const int sdkVersion = QtAndroidPrivate::androidSdkVersion();
+ static QString backgroundLocation = u"android.permission.ACCESS_BACKGROUND_LOCATION"_s;
+ static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
+ static QString coarseLocation = u"android.permission.ACCESS_COARSE_LOCATION"_s;
+
+ // Since Android API 30, background location cannot be requested along
+ // with fine or coarse location, but it should be requested separately after
+ // the latter have been granted, see
+ // https://developer.android.com/training/location/permissions
+ if (sdkVersion < 30 || permission.availability() == QLocationPermission::WhenInUse) {
+ if (permission.accuracy() == QLocationPermission::Approximate) {
+ nativeLocationPermissionList << coarseLocation;
+ } else {
+ nativeLocationPermissionList << fineLocation;
+ // Since Android API 31, if precise location is requested, it's advised
+ // to request both fine and coarse location permissions, see
+ // https://developer.android.com/training/location/permissions#approximate-request
+ if (sdkVersion >= 31)
+ nativeLocationPermissionList << coarseLocation;
+ }
+ }
+
+ // NOTE: before Android API 29, background permission doesn't exist yet.
+
+ // Keep the background permission in front to be able to use first()
+ // on the list in checkPermission() because it takes single permission.
+ if (sdkVersion >= 29 && permission.availability() == QLocationPermission::Always)
+ nativeLocationPermissionList.prepend(backgroundLocation);
+
+ return nativeLocationPermissionList;
+}
+
+static QStringList nativeBluetoothPermission(const QBluetoothPermission &permission)
+{
+ // See https://developer.android.com/guide/topics/connectivity/bluetooth/permissions
+ // for the details.
+
+ // API Level < 31
+ static QString bluetoothGeneral = u"android.permission.BLUETOOTH"_s;
+ // API Level >= 31
+ static QString bluetoothScan = u"android.permission.BLUETOOTH_SCAN"_s;
+ static QString bluetoothAdvertise = u"android.permission.BLUETOOTH_ADVERTISE"_s;
+ static QString bluetoothConnect = u"android.permission.BLUETOOTH_CONNECT"_s;
+ // Fine location is currently required for ALL API levels, but that is not
+ // strictly necessary for API Level >= 31. See QTBUG-112164.
+ static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
+
+ if (QtAndroidPrivate::androidSdkVersion() < 31) {
+ return {bluetoothGeneral, fineLocation};
+ } else {
+ const auto modes = permission.communicationModes();
+ QStringList permissionList;
+ if (modes & QBluetoothPermission::Advertise)
+ permissionList << bluetoothAdvertise;
+ if (modes & QBluetoothPermission::Access)
+ permissionList << bluetoothScan << bluetoothConnect << fineLocation;
+ return permissionList;
+ }
+}
+
+static QStringList nativeStringsFromPermission(const QPermission &permission)
+{
+ const auto id = permission.type().id();
+ if (id == qMetaTypeId<QLocationPermission>()) {
+ return nativeLocationPermission(*permission.value<QLocationPermission>());
+ } else if (id == qMetaTypeId<QCameraPermission>()) {
+ return { u"android.permission.CAMERA"_s };
+ } else if (id == qMetaTypeId<QMicrophonePermission>()) {
+ return { u"android.permission.RECORD_AUDIO"_s };
+ } else if (id == qMetaTypeId<QBluetoothPermission>()) {
+ return nativeBluetoothPermission(*permission.value<QBluetoothPermission>());
+ } else if (id == qMetaTypeId<QContactsPermission>()) {
+ const auto readContactsString = u"android.permission.READ_CONTACTS"_s;
+ switch (permission.value<QContactsPermission>()->accessMode()) {
+ case QContactsPermission::AccessMode::ReadOnly:
+ return { readContactsString };
+ case QContactsPermission::AccessMode::ReadWrite:
+ return { readContactsString, u"android.permission.WRITE_CONTACTS"_s };
+ }
+ Q_UNREACHABLE_RETURN({});
+ } else if (id == qMetaTypeId<QCalendarPermission>()) {
+ const auto readContactsString = u"android.permission.READ_CALENDAR"_s;
+ switch (permission.value<QCalendarPermission>()->accessMode()) {
+ case QCalendarPermission::AccessMode::ReadOnly:
+ return { readContactsString };
+ case QCalendarPermission::AccessMode::ReadWrite:
+ return { readContactsString, u"android.permission.WRITE_CALENDAR"_s };
+ }
+ Q_UNREACHABLE_RETURN({});
+ }
+
+ return {};
+}
+
+static Qt::PermissionStatus
+permissionStatusForAndroidResult(QtAndroidPrivate::PermissionResult result)
+{
+ switch (result) {
+ case QtAndroidPrivate::PermissionResult::Authorized: return Qt::PermissionStatus::Granted;
+ case QtAndroidPrivate::PermissionResult::Denied: return Qt::PermissionStatus::Denied;
+ default: return Qt::PermissionStatus::Undetermined;
+ }
+}
+
+using PermissionStatusHash = QHash<int, Qt::PermissionStatus>;
+Q_GLOBAL_STATIC_WITH_ARGS(PermissionStatusHash, g_permissionStatusHash, ({
+ { qMetaTypeId<QCameraPermission>(), Qt::PermissionStatus::Undetermined },
+ { qMetaTypeId<QMicrophonePermission>(), Qt::PermissionStatus::Undetermined },
+ { qMetaTypeId<QBluetoothPermission>(), Qt::PermissionStatus::Undetermined },
+ { qMetaTypeId<QContactsPermission>(), Qt::PermissionStatus::Undetermined },
+ { qMetaTypeId<QCalendarPermission>(), Qt::PermissionStatus::Undetermined },
+ { qMetaTypeId<QLocationPermission>(), Qt::PermissionStatus::Undetermined }
+}));
+
+static Qt::PermissionStatus
+getCombinedStatus(const QList<QtAndroidPrivate::PermissionResult> &androidResults)
+{
+ // Android returns only Denied or Granted
+ for (const auto &result : androidResults) {
+ const auto status = permissionStatusForAndroidResult(result);
+ if (status == Qt::PermissionStatus::Denied)
+ return status;
+ }
+ return Qt::PermissionStatus::Granted;
+}
+
+namespace QPermissions::Private
+{
+ Qt::PermissionStatus checkPermission(const QPermission &permission)
+ {
+ const auto nativePermissionList = nativeStringsFromPermission(permission);
+ if (nativePermissionList.isEmpty())
+ return Qt::PermissionStatus::Granted;
+
+ QList<QtAndroidPrivate::PermissionResult> androidResults;
+ androidResults.reserve(nativePermissionList.size());
+ for (const auto &nativePermission : nativePermissionList)
+ androidResults.push_back(QtAndroidPrivate::checkPermission(nativePermission).result());
+
+ const auto status = getCombinedStatus(androidResults);
+ const auto it = g_permissionStatusHash->constFind(permission.type().id());
+ const bool foundStatus = (it != g_permissionStatusHash->constEnd());
+ const bool itUndetermined = foundStatus && (*it) == Qt::PermissionStatus::Undetermined;
+ if (status == Qt::PermissionStatus::Denied && itUndetermined)
+ return Qt::PermissionStatus::Undetermined;
+ return status;
+ }
+
+ void requestPermission(const QPermission &permission,
+ const QPermissions::Private::PermissionCallback &callback)
+ {
+ const auto nativePermissionList = nativeStringsFromPermission(permission);
+ if (nativePermissionList.isEmpty()) {
+ callback(Qt::PermissionStatus::Granted);
+ return;
+ }
+
+ QtAndroidPrivate::requestPermissions(nativePermissionList).then(qApp,
+ [callback, permission](QFuture<QtAndroidPrivate::PermissionResult> future) {
+ const auto androidResults = future.isValid() ? future.results()
+ : QList{QtAndroidPrivate::Denied};
+ const auto status = getCombinedStatus(androidResults);
+ g_permissionStatusHash->insert(permission.type().id(), status);
+ callback(status);
+ }
+ );
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpermissions_darwin.mm b/src/corelib/kernel/qpermissions_darwin.mm
new file mode 100644
index 0000000000..ae2cb2c423
--- /dev/null
+++ b/src/corelib/kernel/qpermissions_darwin.mm
@@ -0,0 +1,88 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qpermissions.h"
+#include "qpermissions_p.h"
+
+#include <QtCore/private/qfactoryloader_p.h>
+#include <QtCore/private/qcoreapplication_p.h>
+#include <QtCore/qcborarray.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+namespace {
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, pluginLoader,
+ (QPermissionPluginInterface_iid, QLatin1String("/permissions"), Qt::CaseInsensitive))
+
+QPermissionPlugin *permissionPlugin(const QPermission &permission)
+{
+ static QMutex mutex;
+ QMutexLocker locker(&mutex);
+
+ const char *permissionType = permission.type().name();
+ qCDebug(lcPermissions, "Looking for permission plugin for %s", permissionType);
+
+ if (Q_UNLIKELY(!pluginLoader)) {
+ qCWarning(lcPermissions, "Cannot check or request permissions during application shutdown");
+ return nullptr;
+ }
+
+ auto metaDataList = pluginLoader()->metaData();
+ for (int i = 0; i < metaDataList.size(); ++i) {
+ auto metaData = metaDataList.at(i).value(QtPluginMetaDataKeys::MetaData).toMap();
+ auto permissions = metaData.value("Permissions"_L1).toArray();
+ if (permissions.contains(QString::fromUtf8(permissionType))) {
+ auto className = metaDataList.at(i).value(QtPluginMetaDataKeys::ClassName).toString();
+ qCDebug(lcPermissions) << "Found matching plugin" << qUtf8Printable(className);
+ auto *plugin = static_cast<QPermissionPlugin*>(pluginLoader()->instance(i));
+ if (!plugin->parent()) {
+ // We want to re-parent the plugin to the factory loader, so that it's
+ // cleaned up properly. To do so we first need to move the plugin to the
+ // same thread as the factory loader, as the plugin might be instantiated
+ // on a secondary thread if triggered from a checkPermission call (which
+ // is allowed on any thread).
+ plugin->moveToThread(pluginLoader->thread());
+
+ // Also, as setParent will involve sending a ChildAdded event to the parent,
+ // we need to make the call on the same thread as the parent lives, as events
+ // are not allowed to be sent to an object owned by another thread.
+ QMetaObject::invokeMethod(plugin, [=] {
+ plugin->setParent(pluginLoader);
+ });
+ }
+ return plugin;
+ }
+ }
+
+ qCWarning(lcPermissions).nospace() << "Could not find permission plugin for "
+ << permission.type().name() << ". Please make sure you have included the "
+ << "required usage description in your Info.plist";
+
+ return nullptr;
+}
+
+} // Unnamed namespace
+
+namespace QPermissions::Private
+{
+ Qt::PermissionStatus checkPermission(const QPermission &permission)
+ {
+ if (auto *plugin = permissionPlugin(permission))
+ return plugin->checkPermission(permission);
+ else
+ return Qt::PermissionStatus::Denied;
+ }
+
+ void requestPermission(const QPermission &permission, const QPermissions::Private::PermissionCallback &callback)
+ {
+ if (auto *plugin = permissionPlugin(permission))
+ plugin->requestPermission(permission, callback);
+ else
+ callback(Qt::PermissionStatus::Denied);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpermissions_p.h b/src/corelib/kernel/qpermissions_p.h
new file mode 100644
index 0000000000..36f497f198
--- /dev/null
+++ b/src/corelib/kernel/qpermissions_p.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPERMISSIONS_P_H
+#define QPERMISSIONS_P_H
+
+#include "qpermissions.h"
+
+#include <private/qglobal_p.h>
+#include <QtCore/qloggingcategory.h>
+
+#include <QtCore/QObject>
+
+#include <functional>
+
+QT_REQUIRE_CONFIG(permissions);
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcPermissions, Q_CORE_EXPORT)
+
+namespace QPermissions::Private
+{
+ using PermissionCallback = std::function<void(Qt::PermissionStatus)>;
+
+ Qt::PermissionStatus checkPermission(const QPermission &permission);
+ void requestPermission(const QPermission &permission, const PermissionCallback &callback);
+}
+
+#define QPermissionPluginInterface_iid "org.qt-project.QPermissionPluginInterface.6.5"
+
+class Q_CORE_EXPORT QPermissionPlugin : public QObject
+{
+public:
+ virtual ~QPermissionPlugin();
+
+ virtual Qt::PermissionStatus checkPermission(const QPermission &permission) = 0;
+ virtual void requestPermission(const QPermission &permission,
+ const QPermissions::Private::PermissionCallback &callback) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPERMISSIONS_P_H
diff --git a/src/corelib/kernel/qpermissions_wasm.cpp b/src/corelib/kernel/qpermissions_wasm.cpp
new file mode 100644
index 0000000000..846e62ccf7
--- /dev/null
+++ b/src/corelib/kernel/qpermissions_wasm.cpp
@@ -0,0 +1,275 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <private/qpermissions_p.h>
+#include <private/qstdweb_p.h>
+
+#include <qglobalstatic.h>
+#include <qpermissions.h>
+#include <qmetaobject.h>
+#include <qnamespace.h>
+#include <qmetatype.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qhash.h>
+
+#include <emscripten.h>
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
+
+#include <utility>
+#include <string>
+#include <queue>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPermissions::Private;
+using namespace emscripten;
+
+namespace
+{
+ constexpr const char *wapiGranted = "granted";
+ constexpr const char *wapiDenied = "denied";
+ constexpr const char *wapiPrompt = "prompt";
+ constexpr const char *wapiCamera = "camera";
+ constexpr const char *wapiVideoCapture = "video_capture"; // Alternative to "camera".
+ constexpr const char *wapiMicrophone = "microphone";
+ constexpr const char *wapiAudioCapture = "audio_capture"; // Alternative to "microphone".
+ constexpr const char *wapiGeolocation = "geolocation";
+
+ void updatePermission(const std::string &name, const std::string &state,
+ PermissionCallback callback);
+
+ void checkPermission(const std::string &permissionName)
+ {
+ val permissions = val::global("navigator")["permissions"];
+ if (permissions.isUndefined() || permissions.isNull())
+ return;
+
+ qstdweb::PromiseCallbacks callbacks;
+ callbacks.thenFunc = [permissionName](val permissionState)
+ {
+ updatePermission(permissionName, permissionState["state"].as<std::string>(), {});
+ };
+ callbacks.catchFunc = [permissionName](val)
+ {
+ updatePermission(permissionName, wapiDenied, {});
+ };
+
+ val query = val::object();
+ query.set("name", val(permissionName));
+
+ qstdweb::Promise::make(permissions, QStringLiteral("query"), callbacks, query);
+ }
+
+ void checkPermissions()
+ {
+ checkPermission(wapiCamera);
+ checkPermission(wapiMicrophone);
+ checkPermission(wapiGeolocation);
+ }
+
+ void bootstrapCheckPermissions()
+ {
+ QTimer::singleShot(0, []{checkPermissions();});
+ }
+
+ Q_CONSTRUCTOR_FUNCTION(bootstrapCheckPermissions);
+
+ int permissionTypeIdFromString(const std::string &permission)
+ {
+ if (permission == wapiCamera || permission == wapiVideoCapture)
+ return qMetaTypeId<QCameraPermission>();
+ if (permission == wapiMicrophone || permission == wapiAudioCapture)
+ return qMetaTypeId<QMicrophonePermission>();
+ if (permission == wapiGeolocation)
+ return qMetaTypeId<QLocationPermission>();
+
+ qCWarning(lcPermissions, "Unknown permission type '%s'", permission.c_str());
+
+ return -1;
+ }
+
+ Qt::PermissionStatus permissionStatusFromString(const std::string &state)
+ {
+ if (state == wapiGranted)
+ return Qt::PermissionStatus::Granted;
+ if (state == wapiDenied)
+ return Qt::PermissionStatus::Denied;
+ if (state == wapiPrompt)
+ return Qt::PermissionStatus::Undetermined;
+
+ qCWarning(lcPermissions, "Unknown permission state '%s'", state.c_str());
+
+ return Qt::PermissionStatus::Denied;
+ }
+
+ using PermissionHash = QHash<int, Qt::PermissionStatus>;
+ Q_GLOBAL_STATIC(PermissionHash, permissionStatuses);
+
+ void updatePermission(const std::string &name, const std::string &state, PermissionCallback callback)
+ {
+ qCDebug(lcPermissions) << "Updating" << name << "permission to" << state;
+
+ const int type = permissionTypeIdFromString(name);
+ if (type == -1)
+ return; // Unknown permission type
+
+ const auto status = permissionStatusFromString(state);
+ (*permissionStatuses)[type] = status;
+
+ if (callback)
+ callback(status);
+ }
+
+ void requestMediaDevicePermission(const std::string &device, const PermissionCallback &cb)
+ {
+ Q_ASSERT(cb);
+
+ val mediaDevices = val::global("navigator")["mediaDevices"];
+ if (mediaDevices.isUndefined())
+ return cb(Qt::PermissionStatus::Denied);
+
+ qstdweb::PromiseCallbacks queryCallbacks;
+ queryCallbacks.thenFunc = [device, cb](val)
+ {
+ updatePermission(device, wapiGranted, cb);
+ };
+ queryCallbacks.catchFunc = [device, cb](val error)
+ {
+ if (error["name"].as<std::string>() == "NotAllowedError")
+ return updatePermission(device, wapiDenied, cb);
+ updatePermission(device, wapiPrompt, cb);
+ };
+
+ val constraint = val::object();
+ if (device == wapiCamera)
+ constraint.set("video", true);
+ else
+ constraint.set("audio", true);
+
+ qstdweb::Promise::make(mediaDevices, QStringLiteral("getUserMedia"), queryCallbacks, constraint);
+ }
+
+ using GeoRequest = std::pair<QPermission, PermissionCallback>;
+ Q_GLOBAL_STATIC(std::deque<GeoRequest>, geolocationRequestQueue);
+
+ bool processingLocationRequest = false;
+
+ void processNextGeolocationRequest();
+
+ void geolocationSuccess(val position)
+ {
+ Q_UNUSED(position);
+ Q_ASSERT(geolocationRequestQueue->size());
+
+ processingLocationRequest = false;
+
+ auto cb = geolocationRequestQueue->front().second;
+ geolocationRequestQueue->pop_front();
+ updatePermission(wapiGeolocation, wapiGranted, cb);
+ processNextGeolocationRequest();
+ }
+
+ void geolocationError(val error)
+ {
+ Q_ASSERT(geolocationRequestQueue->size());
+
+ static int deniedError = []
+ {
+ val posErr = val::global("GeolocationPositionError");
+ if (posErr.isUndefined() || posErr.isNull())
+ return 1;
+ return posErr["PERMISSION_DENIED"].as<int>();
+ }();
+
+ processingLocationRequest = false;
+
+ auto cb = geolocationRequestQueue->front().second;
+ geolocationRequestQueue->pop_front();
+
+ const int errorCode = error["code"].as<int>();
+ updatePermission(wapiGeolocation, errorCode == deniedError ? wapiDenied : wapiPrompt, cb);
+ processNextGeolocationRequest();
+ }
+
+ EMSCRIPTEN_BINDINGS(qt_permissions) {
+ function("qtLocationSuccess", &geolocationSuccess);
+ function("qtLocationError", &geolocationError);
+ }
+
+ void processNextGeolocationRequest()
+ {
+ if (processingLocationRequest)
+ return;
+
+ if (geolocationRequestQueue->empty())
+ return;
+
+ processingLocationRequest = true;
+
+ val geolocation = val::global("navigator")["geolocation"];
+ Q_ASSERT(!geolocation.isUndefined());
+ Q_ASSERT(!geolocation.isNull());
+
+ const auto &permission = geolocationRequestQueue->front().first;
+ const auto locationPermission = *permission.value<QLocationPermission>();
+ const bool highAccuracy = locationPermission.accuracy() == QLocationPermission::Precise;
+
+ val options = val::object();
+ options.set("enableHighAccuracy", highAccuracy ? true : false);
+ geolocation.call<void>("getCurrentPosition", val::module_property("qtLocationSuccess"),
+ val::module_property("qtLocationError"), options);
+ }
+
+ void requestGeolocationPermission(const QPermission &permission, const PermissionCallback &cb)
+ {
+ Q_ASSERT(cb);
+ Q_UNUSED(permission);
+ Q_UNUSED(cb);
+
+ val geolocation = val::global("navigator")["geolocation"];
+ if (geolocation.isUndefined() || geolocation.isNull())
+ return cb(Qt::PermissionStatus::Denied);
+
+ if (processingLocationRequest)
+ qCWarning(lcPermissions, "Permission to access location requested, while another request is in progress");
+
+ geolocationRequestQueue->push_back(std::make_pair(permission, cb));
+ processNextGeolocationRequest();
+ }
+} // Unnamed namespace
+
+namespace QPermissions::Private
+{
+ Qt::PermissionStatus checkPermission(const QPermission &permission)
+ {
+ const auto it = permissionStatuses->find(permission.type().id());
+ return it != permissionStatuses->end() ? it.value() : Qt::PermissionStatus::Undetermined;
+ }
+
+ void requestPermission(const QPermission &permission, const PermissionCallback &callback)
+ {
+ Q_ASSERT(permission.type().isValid());
+ Q_ASSERT(callback);
+
+ const auto status = checkPermission(permission);
+ if (status != Qt::PermissionStatus::Undetermined)
+ return callback(status);
+
+ const int requestedTypeId = permission.type().id();
+ if (requestedTypeId == qMetaTypeId<QCameraPermission>())
+ return requestMediaDevicePermission(wapiCamera, callback);
+
+ if (requestedTypeId == qMetaTypeId<QMicrophonePermission>())
+ return requestMediaDevicePermission(wapiMicrophone, callback);
+
+ if (requestedTypeId == qMetaTypeId<QLocationPermission>())
+ return requestGeolocationPermission(permission, callback);
+
+ (*permissionStatuses)[requestedTypeId] = Qt::PermissionStatus::Denied;
+ callback(Qt::PermissionStatus::Denied);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h
index ebc06a0fb1..39e4ba3e0f 100644
--- a/src/corelib/kernel/qpointer.h
+++ b/src/corelib/kernel/qpointer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPOINTER_H
#define QPOINTER_H
@@ -54,15 +18,48 @@ class QPointer
{
static_assert(!std::is_pointer<T>::value, "QPointer's template type must not be a pointer type");
+ template <typename X>
+ using if_convertible = std::enable_if_t<std::is_convertible_v<X*, T*>, bool>;
+ template <typename X>
+ friend class QPointer;
+
using QObjectType =
typename std::conditional<std::is_const<T>::value, const QObject, QObject>::type;
QWeakPointer<QObjectType> wp;
public:
- QPointer() = default;
+ Q_NODISCARD_CTOR
+ QPointer() noexcept = default;
+ Q_NODISCARD_CTOR
+ constexpr QPointer(std::nullptr_t) noexcept : QPointer{} {}
+ Q_WEAK_OVERLOAD
+ Q_NODISCARD_CTOR
inline QPointer(T *p) : wp(p, true) { }
// compiler-generated copy/move ctor/assignment operators are fine!
// compiler-generated dtor is fine!
+ template <typename X, if_convertible<X> = true>
+ Q_NODISCARD_CTOR
+ QPointer(QPointer<X> &&other) noexcept
+ : wp(std::exchange(other.wp, nullptr).internalData(), true) {}
+ template <typename X, if_convertible<X> = true>
+ Q_NODISCARD_CTOR
+ QPointer(const QPointer<X> &other) noexcept
+ : wp(other.wp.internalData(), true) {}
+
+ template <typename X, if_convertible<X> = true>
+ QPointer &operator=(const QPointer<X> &other) noexcept
+ {
+ QPointer(other).swap(*this);
+ return *this;
+ }
+
+ template <typename X, if_convertible<X> = true>
+ QPointer &operator=(QPointer<X> &&other) noexcept
+ {
+ QPointer(std::move(other)).swap(*this);
+ return *this;
+ }
+
#ifdef Q_QDOC
// Stop qdoc from complaining about missing function
~QPointer();
@@ -73,64 +70,49 @@ public:
inline QPointer<T> &operator=(T* p)
{ wp.assign(static_cast<QObjectType*>(p)); return *this; }
- inline T* data() const
+ T* data() const noexcept
{ return static_cast<T*>(wp.internalData()); }
- inline T* get() const
+ T* get() const noexcept
{ return data(); }
- inline T* operator->() const
+ T* operator->() const noexcept
{ return data(); }
- inline T& operator*() const
+ T& operator*() const noexcept
{ return *data(); }
- inline operator T*() const
+ operator T*() const noexcept
{ return data(); }
- inline bool isNull() const
+ bool isNull() const noexcept
{ return wp.isNull(); }
- inline void clear()
+ void clear() noexcept
{ wp.clear(); }
-};
-template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_MOVABLE_TYPE);
-
-template <class T>
-inline bool operator==(const T *o, const QPointer<T> &p)
-{ return o == p.operator->(); }
-
-template<class T>
-inline bool operator==(const QPointer<T> &p, const T *o)
-{ return p.operator->() == o; }
-
-template <class T>
-inline bool operator==(T *o, const QPointer<T> &p)
-{ return o == p.operator->(); }
-
-template<class T>
-inline bool operator==(const QPointer<T> &p, T *o)
-{ return p.operator->() == o; }
-
-template<class T>
-inline bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
-{ return p1.operator->() == p2.operator->(); }
-template <class T>
-inline bool operator!=(const T *o, const QPointer<T> &p)
-{ return o != p.operator->(); }
-
-template<class T>
-inline bool operator!= (const QPointer<T> &p, const T *o)
-{ return p.operator->() != o; }
-
-template <class T>
-inline bool operator!=(T *o, const QPointer<T> &p)
-{ return o != p.operator->(); }
-
-template<class T>
-inline bool operator!= (const QPointer<T> &p, T *o)
-{ return p.operator->() != o; }
-
-template<class T>
-inline bool operator!= (const QPointer<T> &p1, const QPointer<T> &p2)
-{ return p1.operator->() != p2.operator->() ; }
+ friend void swap(QPointer &lhs, QPointer &rhs) noexcept
+ { lhs.swap(rhs); }
+
+#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; }
+
+#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \
+ template <typename X> \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ template <typename X> \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; }
+
+ DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), const QPointer<X> &p2, p2.data())
+ DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), X *ptr, ptr)
+ DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QPointer &p2, p2.data())
+ DECLARE_COMPARE_SET(const QPointer &p1, p1.data(), std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QPointer &p2, p2.data())
+#undef DECLARE_COMPARE_SET
+#undef DECLARE_TEMPLATE_COMPARE_SET
+};
+template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_RELOCATABLE_TYPE);
template<typename T>
QPointer<T>
@@ -140,10 +122,6 @@ qPointerFromVariant(const QVariant &variant)
return QPointer<T>{qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(wp))};
}
-template <class T>
-inline void swap(QPointer<T> &p1, QPointer<T> &p2) noexcept
-{ p1.swap(p2); }
-
QT_END_NAMESPACE
#endif // QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.qdoc
index 5f6826b269..9e4c9b2658 100644
--- a/src/corelib/kernel/qpointer.cpp
+++ b/src/corelib/kernel/qpointer.qdoc
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QPointer
@@ -112,6 +76,7 @@
/*!
\fn template <class T> QPointer<T>::QPointer()
+ \fn template <class T> QPointer<T>::QPointer(std::nullptr_t)
Constructs a guarded pointer with value \nullptr.
@@ -134,6 +99,42 @@
*/
/*!
+ \fn template <class T> template <typename X, QPointer<T>::if_convertible<X> = true> QPointer<T>::QPointer(QPointer<X> &&other)
+ \fn template <class T> template <typename X, QPointer<T>::if_convertible<X> = true> QPointer<T>::QPointer(const QPointer<X> &other)
+ \since 6.6
+
+ Conversion constructor. Constructs a new QPointer by moving or copying from
+ \a other.
+
+ The moved-from QPointer is reset to nullptr.
+
+ \note These constructors participate in overload resolution only if \c{X*}
+ is convertible to \c{T*}.
+*/
+
+/*!
+ \fn template <class T> template <typename X, QPointer<T>::if_convertible<X> = true> QPointer<T> &QPointer<T>::operator=(const QPointer<X> &other)
+ \since 6.6
+
+ Conversion assignment operator. Makes this guarded pointer guard the
+ same object guarded by \a other.
+
+ \note This operator participates in overload resolution only if \c{X*}
+ is convertible to \c{T*}.
+*/
+
+/*!
+ \fn template <class T> template <typename X, QPointer<T>::if_convertible<X> = true> &QPointer<T>::operator=(QPointer<X> &&other)
+ \since 6.6.1
+
+ Conversion move-assignment operator. Makes this guarded pointer guard the
+ same object guarded by \a other and resets \a other to nullptr.
+
+ \note This operator participates in overload resolution only if \c{X*}
+ is convertible to \c{T*}.
+*/
+
+/*!
\fn template <class T> void QPointer<T>::swap(QPointer &other)
\since 5.6
@@ -201,8 +202,7 @@
*/
/*!
- \fn template <class T> bool operator==(const T *o, const QPointer<T> &p)
- \relates QPointer
+ \fn template <typename T> template<typename X> bool QPointer<T>::operator==(X *o, const QPointer<T> &p)
Equality operator. Returns \c true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -210,8 +210,7 @@
*/
/*!
- \fn template <class T> bool operator==(const QPointer<T> &p, const T *o)
- \relates QPointer
+ \fn template <typename T> template<typename X> bool QPointer<T>::operator==(const QPointer<T> &p, X *o)
Equality operator. Returns \c true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -219,74 +218,64 @@
*/
/*!
- \fn template <class T> bool operator==(T *o, const QPointer<T> &p)
- \relates QPointer
+ \fn template <typename T> template<typename X> bool QPointer<T>::operator==(const QPointer<T> &p1, const QPointer<X> &p2)
- Equality operator. Returns \c true if \a o and the guarded
- pointer \a p are pointing to the same object, otherwise
+ Equality operator. Returns \c true if the guarded pointers \a p1 and \a p2
+ are pointing to the same object, otherwise
returns \c false.
*/
/*!
- \fn template <class T> bool operator==(const QPointer<T> &p, T *o)
- \relates QPointer
+ \fn template <typename T> bool QPointer<T>::operator==(std::nullptr_t, const QPointer<T> &rhs)
- Equality operator. Returns \c true if \a o and the guarded
- pointer \a p are pointing to the same object, otherwise
+ Equality operator. Returns \c true if the pointer guarded by \a rhs
+ is \nullptr, otherwise
returns \c false.
-
*/
/*!
- \fn template <class T> bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
- \relates QPointer
+ \fn template <typename T> bool QPointer<T>::operator==(const QPointer<T> &lhs, std::nullptr_t)
- Equality operator. Returns \c true if the guarded pointers \a p1 and \a p2
- are pointing to the same object, otherwise
+ Equality operator. Returns \c true if the pointer guarded by \a lhs
+ is \nullptr, otherwise
returns \c false.
-
*/
-
/*!
- \fn template <class T> bool operator!=(const T *o, const QPointer<T> &p)
- \relates QPointer
+ \fn template <typename T> template<typename X> bool QPointer<T>::operator!=(const QPointer<T> &p, X *o)
Inequality operator. Returns \c true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
returns \c false.
*/
/*!
- \fn template <class T> bool operator!=(const QPointer<T> &p, const T *o)
- \relates QPointer
+ \fn template <typename T> template<typename X> bool QPointer<T>::operator!=(X *o, const QPointer<T> &p)
Inequality operator. Returns \c true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
returns \c false.
*/
/*!
- \fn template <class T> bool operator!=(T *o, const QPointer<T> &p)
- \relates QPointer
+ \fn template <typename T> template<typename X> bool QPointer<T>::operator!=(const QPointer<T> &p1, const QPointer<X> &p2)
- Inequality operator. Returns \c true if \a o and the guarded
- pointer \a p are not pointing to the same object, otherwise
+ Inequality operator. Returns \c true if the guarded pointers \a p1 and
+ \a p2 are not pointing to the same object, otherwise
returns \c false.
*/
/*!
- \fn template <class T> bool operator!=(const QPointer<T> &p, T *o)
- \relates QPointer
+ \fn template <typename T> bool QPointer<T>::operator!=(std::nullptr_t, const QPointer<T> &rhs)
- Inequality operator. Returns \c true if \a o and the guarded
- pointer \a p are not pointing to the same object, otherwise
+ Inequality operator. Returns \c true if the pointer guarded by \a rhs is
+ a valid (ie not \nullptr) pointer, otherwise
returns \c false.
*/
/*!
- \fn template <class T> bool operator!=(const QPointer<T> &p1, const QPointer<T> &p2)
- \relates QPointer
+ \fn template <typename T> bool QPointer<T>::operator!=(const QPointer<T> &lhs, std::nullptr_t)
- Inequality operator. Returns \c true if the guarded pointers \a p1 and
- \a p2 are not pointing to the same object, otherwise
+ Inequality operator. Returns \c true if the pointer guarded by \a lhs is
+ a valid (ie not \nullptr) pointer, otherwise
returns \c false.
*/
+
/*!
\fn template <typename T> QPointer<T> qPointerFromVariant(const QVariant &variant)
diff --git a/src/corelib/kernel/qpoll.cpp b/src/corelib/kernel/qpoll.cpp
index 8b87bfe79d..58fb0234b4 100644
--- a/src/corelib/kernel/qpoll.cpp
+++ b/src/corelib/kernel/qpoll.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcore_unix_p.h"
@@ -90,7 +54,7 @@ static inline void qt_poll_examine_ready_read(struct pollfd &pfd)
int res;
char data;
- EINTR_LOOP(res, ::recv(pfd.fd, &data, sizeof(data), MSG_PEEK));
+ QT_EINTR_LOOP(res, ::recv(pfd.fd, &data, sizeof(data), MSG_PEEK));
const int error = (res < 0) ? errno : 0;
if (res == 0) {
@@ -145,7 +109,7 @@ static inline bool qt_poll_is_bad_fd(int fd)
#endif
int ret;
- EINTR_LOOP(ret, fcntl(fd, F_GETFD));
+ QT_EINTR_LOOP(ret, fcntl(fd, F_GETFD));
return (ret == -1 && errno == EBADF);
}
@@ -177,7 +141,7 @@ int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
}
fd_set read_fds, write_fds, except_fds;
- struct timeval tv, *ptv = 0;
+ struct timeval tv, *ptv = nullptr;
if (timeout_ts) {
tv = timespecToTimeval(*timeout_ts);
@@ -192,6 +156,11 @@ int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
if (fds[i].fd < 0)
continue;
+ if (fds[i].fd > FD_SETSIZE) {
+ errno = EINVAL;
+ return -1;
+ }
+
if (fds[i].events & QT_POLL_EVENTS_MASK)
continue;
diff --git a/src/corelib/kernel/qpoll_p.h b/src/corelib/kernel/qpoll_p.h
index cb6ad82ae7..7c7fa7a5a3 100644
--- a/src/corelib/kernel/qpoll_p.h
+++ b/src/corelib/kernel/qpoll_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPOLL_P_H
#define QPOLL_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp
deleted file mode 100644
index 166d590872..0000000000
--- a/src/corelib/kernel/qppsattribute.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qppsattribute_p.h"
-#include "qppsattributeprivate_p.h"
-
-#include <QDebug>
-#include <QVariant>
-
-QT_BEGIN_NAMESPACE
-
-///////////////////////////
-//
-// QPpsAttributePrivate
-//
-///////////////////////////
-
-QPpsAttributePrivate::QPpsAttributePrivate() : type(QPpsAttribute::None)
-{
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(int value, QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::Number;
- attribute.d->data = value;
- attribute.d->flags = flags;
- return attribute;
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(long long value, QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::Number;
- attribute.d->data = value;
- attribute.d->flags = flags;
- return attribute;
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(double value, QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::Number;
- attribute.d->data = value;
- attribute.d->flags = flags;
- return attribute;
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(bool value, QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::Bool;
- attribute.d->data = value;
- attribute.d->flags = flags;
- return attribute;
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QString &value,
- QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::String;
- attribute.d->data = value;
- attribute.d->flags = flags;
- return attribute;
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QPpsAttributeList &value,
- QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::Array;
- attribute.d->data = QVariant::fromValue(value);
- attribute.d->flags = flags;
- return attribute;
-}
-
-QPpsAttribute QPpsAttributePrivate::createPpsAttribute(const QPpsAttributeMap &value,
- QPpsAttribute::Flags flags)
-{
- QPpsAttribute attribute;
- attribute.d->type = QPpsAttribute::Object;
- attribute.d->data = QVariant::fromValue(value);
- attribute.d->flags = flags;
- return attribute;
-}
-
-///////////////////////////
-//
-// QPpsAttribute
-//
-///////////////////////////
-
-QPpsAttribute::QPpsAttribute() : d(new QPpsAttributePrivate())
-{
-}
-
-QPpsAttribute::~QPpsAttribute()
-{
-}
-
-QPpsAttribute::QPpsAttribute(const QPpsAttribute &other) : d(other.d)
-{
-}
-
-QPpsAttribute &QPpsAttribute::operator=(const QPpsAttribute &other)
-{
- d = other.d;
- return *this;
-}
-
-QPpsAttribute::QPpsAttribute(QPpsAttribute &&other) : d(other.d)
-{
- other.d->type = QPpsAttribute::None;
-}
-
-QPpsAttribute &QPpsAttribute::operator=(QPpsAttribute &&other)
-{
- qSwap(d, other.d);
- return *this;
-}
-
-bool QPpsAttribute::operator==(const QPpsAttribute &other) const
-{
- if (type() != other.type())
- return false;
- if (flags() != other.flags())
- return false;
-
- switch (type()) {
- case QPpsAttribute::Number:
- case QPpsAttribute::Bool:
- case QPpsAttribute::String:
- // QVariant can compare double, int, longlong, bool, and QString for us.
- return d->data == other.d->data;
- case QPpsAttribute::Array:
- // QVariant can't compare custom types (like QPpsAttributeList), always returning false.
- // So we pull the lists out manually and compare them.
- return toList() == other.toList();
- case QPpsAttribute::Object:
- // QVariant can't compare custom types (like QPpsAttributeMap), always returning false.
- // So we pull the maps out manually and compare them.
- return toMap() == other.toMap();
- case QPpsAttribute::None:
- // Both are "None" type, so the actual content doesn't matter.
- return true;
- }
- return d->data == other.d->data;
-}
-
-bool QPpsAttribute::isValid() const
-{
- return d->type != QPpsAttribute::None;
-}
-
-QPpsAttribute::Type QPpsAttribute::type() const
-{
- return d->type;
-}
-
-bool QPpsAttribute::isNumber() const
-{
- return type() == QPpsAttribute::Number;
-}
-
-bool QPpsAttribute::isBool() const
-{
- return type() == QPpsAttribute::Bool;
-}
-
-bool QPpsAttribute::isString() const
-{
- return type() == QPpsAttribute::String;
-}
-
-bool QPpsAttribute::isArray() const
-{
- return type() == QPpsAttribute::Array;
-}
-
-bool QPpsAttribute::isObject() const
-{
- return type() == QPpsAttribute::Object;
-}
-
-double QPpsAttribute::toDouble() const
-{
- return d->data.toDouble();
-}
-
-qlonglong QPpsAttribute::toLongLong() const
-{
- return d->data.toLongLong();
-}
-
-int QPpsAttribute::toInt() const
-{
- return d->data.toInt();
-}
-
-bool QPpsAttribute::toBool() const
-{
- return d->data.toBool();
-}
-
-QString QPpsAttribute::toString() const
-{
- return d->data.toString();
-}
-
-QPpsAttributeList QPpsAttribute::toList() const
-{
- return d->data.value< QPpsAttributeList >();
-}
-
-QPpsAttributeMap QPpsAttribute::toMap() const
-{
- return d->data.value< QPpsAttributeMap >();
-}
-
-QPpsAttribute::Flags QPpsAttribute::flags() const
-{
- return d->flags;
-}
-
-QVariant QPpsAttribute::toVariant() const
-{
- return d->data;
-}
-
-QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QPpsAttribute(";
-
- switch (attribute.type()) {
- case QPpsAttribute::Number:
- switch (attribute.toVariant().type()) {
- case QVariant::Int:
- dbg << "Number, " << attribute.flags() << ", " << attribute.toInt();
- break;
- case QVariant::LongLong:
- dbg << "Number, " << attribute.flags() << ", " << attribute.toLongLong();
- break;
- default:
- dbg << "Number, " << attribute.flags() << ", " << attribute.toDouble();
- break;
- }
- break;
- case QPpsAttribute::Bool:
- dbg << "Bool, " << attribute.flags() << ", " << attribute.toBool();
- break;
- case QPpsAttribute::String:
- dbg << "String, " << attribute.flags() << ", " << attribute.toString();
- break;
- case QPpsAttribute::Array:
- dbg << "Array, " << attribute.flags() << ", " << attribute.toList();
- break;
- case QPpsAttribute::Object:
- dbg << "Object, " << attribute.flags() << ", " << attribute.toMap();
- break;
- case QPpsAttribute::None:
- dbg << "None";
- break;
- }
-
- dbg << ')';
-
- return dbg;
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h
deleted file mode 100644
index d6611cb675..0000000000
--- a/src/corelib/kernel/qppsattribute_p.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QPPSATTRIBUTE_P_H
-#define QPPSATTRIBUTE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-#include <QList>
-#include <QMap>
-#include <QSharedDataPointer>
-#include <QVariant>
-
-QT_BEGIN_NAMESPACE
-
-class QPpsAttributePrivate;
-class QPpsAttribute;
-
-typedef QList<QPpsAttribute> QPpsAttributeList;
-typedef QMap<QString, QPpsAttribute> QPpsAttributeMap;
-
-class Q_CORE_EXPORT QPpsAttribute
-{
-public:
-
- enum Type {
- None = 0,
- Number = 1,
- Bool = 2,
- String = 3,
- Array = 4,
- Object = 5
- };
-
- enum Flag {
- Incomplete = 0x01,
- Deleted = 0x02,
- Created = 0x04,
- Truncated = 0x08,
- Purged = 0x10
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QPpsAttribute();
- QPpsAttribute(const QPpsAttribute &other);
- ~QPpsAttribute();
-
- QPpsAttribute &operator=(const QPpsAttribute &other);
- bool operator==(const QPpsAttribute &other) const;
- bool operator!=(const QPpsAttribute &other) const;
-
- QPpsAttribute(QPpsAttribute &&other);
- QPpsAttribute &operator=(QPpsAttribute &&other);
-
- bool isValid() const;
- Type type() const;
- QPpsAttribute::Flags flags() const;
-
- bool isNumber() const;
- bool isBool() const;
- bool isString() const;
- bool isArray() const;
- bool isObject() const;
-
- double toDouble() const;
- qlonglong toLongLong() const;
- int toInt() const;
- bool toBool() const;
- QString toString() const;
- QPpsAttributeList toList() const;
- QPpsAttributeMap toMap() const;
- QVariant toVariant() const;
-
-private:
- QSharedDataPointer<QPpsAttributePrivate> d;
- friend class QPpsAttributePrivate;
-};
-
-inline bool QPpsAttribute::operator!=(const QPpsAttribute &other) const
-{
- return !(*this == other);
-}
-
-Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QPpsAttributeList)
-Q_DECLARE_METATYPE(QPpsAttributeMap)
-
-#endif // QPPSATTRIBUTE_P_H
diff --git a/src/corelib/kernel/qppsattributeprivate_p.h b/src/corelib/kernel/qppsattributeprivate_p.h
deleted file mode 100644
index 78b7b3c4c2..0000000000
--- a/src/corelib/kernel/qppsattributeprivate_p.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPPSATTRIBUTEPRIVATE_P_H
-#define QPPSATTRIBUTEPRIVATE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qppsattribute_p.h"
-
-#include <QList>
-#include <QMap>
-#include <QSharedData>
-#include <QString>
-#include <QVariant>
-
-QT_BEGIN_NAMESPACE
-
-class QPpsAttributePrivate : public QSharedData
-{
-public:
- QPpsAttributePrivate();
-
- static QPpsAttribute createPpsAttribute(double value, QPpsAttribute::Flags flags);
- static QPpsAttribute createPpsAttribute(long long value, QPpsAttribute::Flags flags);
- static QPpsAttribute createPpsAttribute(int value, QPpsAttribute::Flags flags);
- static QPpsAttribute createPpsAttribute(bool value, QPpsAttribute::Flags flags);
- static QPpsAttribute createPpsAttribute(const QString &value, QPpsAttribute::Flags flags);
- static QPpsAttribute createPpsAttribute(const QPpsAttributeList &value,
- QPpsAttribute::Flags flags);
- static QPpsAttribute createPpsAttribute(const QPpsAttributeMap &value,
- QPpsAttribute::Flags flags);
-
-private:
- friend class QPpsAttribute;
-
- QVariant data;
- QPpsAttribute::Type type;
- QPpsAttribute::Flags flags;
-};
-
-QT_END_NAMESPACE
-
-#endif // QPPSATTRIBUTEPRIVATE_P_H
diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp
deleted file mode 100644
index f4001d3833..0000000000
--- a/src/corelib/kernel/qppsobject.cpp
+++ /dev/null
@@ -1,966 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qppsobject_p.h"
-
-#include "qppsobjectprivate_p.h"
-#include "qppsattribute_p.h"
-#include "qppsattributeprivate_p.h"
-#include "qcore_unix_p.h"
-
-#include <QObject>
-#include <QSocketNotifier>
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <confname.h>
-
-#include <sys/pps.h>
-
-QT_BEGIN_NAMESPACE
-
-///////////////////////////////////////////////////////////////////////////////
-static inline void safeAssign(bool *pointer, bool value)
-{
- if (pointer)
- *pointer = value;
-}
-
-class QPpsMaxSize
-{
-public:
- QPpsMaxSize()
- {
- int fd = qt_safe_open("/pps/.all", O_RDONLY);
- if (fd == -1) {
- qWarning("qppsobject.cpp: qt_safe_open failed");
- value = -1;
- }
-
- // This tells us the maximum transfer size across PPS
- value = ::fpathconf(fd, _PC_REC_MAX_XFER_SIZE);
-
- qt_safe_close(fd);
- }
-
- int value;
-};
-
-Q_GLOBAL_STATIC(QPpsMaxSize, ppsMaxSize)
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// QPpsObjectPrivate
-//
-///////////////////////////////////////////////////////////////////////////////
-
-QPpsObjectPrivate::QPpsObjectPrivate(const QString &path)
- : notifier(0),
- path(path),
- error(EOK),
- fd(-1),
- readyReadEnabled(true)
-{
-}
-
-QPpsAttributeMap QPpsObjectPrivate::decode(const QByteArray &rawData, bool *ok)
-{
- QPpsAttributeMap attributeMap;
- pps_decoder_t decoder;
-
- QByteArray mutableData(rawData);
- pps_decoder_error_t error = pps_decoder_initialize(&decoder, mutableData.data());
- if (error == PPS_DECODER_OK) {
- // no need to check ok in this case
- attributeMap = decodeObject(&decoder, ok);
- } else {
- qWarning("QPpsObjectPrivate::decode: pps_decoder_initialize failed");
- *ok = false;
- }
-
- pps_decoder_cleanup(&decoder);
- return attributeMap;
-}
-
-QVariantMap QPpsObjectPrivate::variantMapFromPpsAttributeMap(const QPpsAttributeMap &data)
-{
- QVariantMap variantMap;
-
- for (QPpsAttributeMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
- QVariant variant = variantFromPpsAttribute(it.value());
- if (!variant.isValid())
- return QVariantMap();
- variantMap[it.key()] = variant;
- }
-
- return variantMap;
-}
-
-QPpsAttribute::Flags QPpsObjectPrivate::readFlags(pps_decoder_t *decoder)
-{
- int rawFlags = pps_decoder_flags(decoder, 0);
-
- QPpsAttribute::Flags attributeFlags;
-
- if (rawFlags & PPS_INCOMPLETE)
- attributeFlags |= QPpsAttribute::Incomplete;
- if (rawFlags & PPS_DELETED)
- attributeFlags |= QPpsAttribute::Deleted;
- if (rawFlags & PPS_CREATED)
- attributeFlags |= QPpsAttribute::Created;
- if (rawFlags & PPS_TRUNCATED)
- attributeFlags |= QPpsAttribute::Truncated;
- if (rawFlags & PPS_PURGED)
- attributeFlags |= QPpsAttribute::Purged;
-
- return attributeFlags;
-}
-
-QPpsAttribute QPpsObjectPrivate::decodeString(pps_decoder_t *decoder)
-{
- const char *value = 0;
- pps_decoder_error_t error = pps_decoder_get_string(decoder, 0, &value);
-
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeString: PPS_DECODER_GET_STRING failed");
- return QPpsAttribute();
- }
-
- QPpsAttribute::Flags flags = readFlags(decoder);
- return QPpsAttributePrivate::createPpsAttribute(QString::fromUtf8(value), flags);
-}
-
-QPpsAttribute QPpsObjectPrivate::decodeNumber(pps_decoder_t *decoder)
-{
- // In order to support more number types, we have to do something stupid because the PPS
- // library won't let us work any other way. Basically, we have to probe the encoded type in
- // order to try to get exactly what we want.
- int64_t llValue;
- double dValue;
- int iValue;
- QPpsAttribute::Flags flags;
-
- if (pps_decoder_is_integer(decoder, 0)) {
- pps_decoder_error_t error = pps_decoder_get_int(decoder, 0, &iValue);
- switch (error) {
- case PPS_DECODER_OK:
- flags = readFlags(decoder);
- return QPpsAttributePrivate::createPpsAttribute(iValue, flags);
- case PPS_DECODER_CONVERSION_FAILED:
- error = pps_decoder_get_int64(decoder, 0, &llValue);
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeNumber: failed to decode integer");
- return QPpsAttribute();
- }
- flags = readFlags(decoder);
- return QPpsAttributePrivate::createPpsAttribute(static_cast<long long>(llValue), flags);
- default:
- qWarning("QPpsObjectPrivate::decodeNumber: pps_decoder_get_int failed");
- return QPpsAttribute();
- }
- } else {
- pps_decoder_error_t error = pps_decoder_get_double(decoder, 0, &dValue);
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeNumber: pps_decoder_get_double failed");
- return QPpsAttribute();
- }
- flags = readFlags(decoder);
- return QPpsAttributePrivate::createPpsAttribute(dValue, flags);
- }
-}
-
-QPpsAttribute QPpsObjectPrivate::decodeBool(pps_decoder_t *decoder)
-{
- bool value;
- pps_decoder_error_t error = pps_decoder_get_bool(decoder, 0, &value);
-
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeBool: pps_decoder_get_bool failed");
- return QPpsAttribute();
- }
-
- QPpsAttribute::Flags flags = readFlags(decoder);
- return QPpsAttributePrivate::createPpsAttribute(value, flags);
-}
-
-template<typename T>
-QPpsAttribute QPpsObjectPrivate::decodeNestedData(T (*decodeFunction)(pps_decoder_t *, bool *),
- pps_decoder_t *decoder)
-{
- // We must read the flags before we push into the object,
- // otherwise we'll get the flags for the first element in the object.
- QPpsAttribute::Flags flags = readFlags(decoder);
-
- if (!decoderPush(decoder))
- return QPpsAttribute();
-
- bool ok = false;
-
- T attributeContainer = decodeFunction(decoder, &ok);
-
- if (!ok)
- return QPpsAttribute();
-
- QPpsAttribute returnVal = QPpsAttributePrivate::createPpsAttribute(attributeContainer, flags);
-
- if (!decoderPop(decoder))
- return QPpsAttribute();
-
- return returnVal;
-}
-
-QPpsAttribute QPpsObjectPrivate::decodeData(pps_decoder_t *decoder)
-{
- pps_node_type_t nodeType = pps_decoder_type(decoder, 0);
- switch (nodeType) {
- case PPS_TYPE_BOOL:
- return decodeBool(decoder);
- case PPS_TYPE_NUMBER:
- return decodeNumber(decoder);
- case PPS_TYPE_STRING:
- return decodeString(decoder);
- case PPS_TYPE_ARRAY:
- return decodeNestedData(&QPpsObjectPrivate::decodeArray, decoder);
- case PPS_TYPE_OBJECT:
- return decodeNestedData(&QPpsObjectPrivate::decodeObject, decoder);
- case PPS_TYPE_DELETED: {
- // This should create an attribute with the flags set to PpsAttribute::Deleted.
- // However, we need to create a valid QPpsAttribute while doing so. To do this,
- // I'll create an empty map as a sentinel. Note that the readFlags() call with produce
- // the correct set of flags. While I suspect that there will never be any other flags
- // set in conjunction with this one, I'd rather not be surprised later.
- QPpsAttributeMap emptyMap;
- QPpsAttribute::Flags flags = readFlags(decoder);
- QPpsAttribute returnVal = QPpsAttributePrivate::createPpsAttribute(emptyMap, flags);
- return returnVal;
- }
- case PPS_TYPE_NULL:
- case PPS_TYPE_NONE:
- case PPS_TYPE_UNKNOWN:
- default:
- qWarning("QPpsObjectPrivate::decodeData: invalid pps_node_type");
- return QPpsAttribute();
- }
-}
-
-QPpsAttributeList QPpsObjectPrivate::decodeArray(pps_decoder_t *decoder, bool *ok)
-{
- QPpsAttributeList list;
-
- int length = pps_decoder_length(decoder);
- for (int i = 0; i < length; ++i) {
- // Force movement to a specific index.
- pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeArray: pps_decoder_goto_index failed");
- *ok = false;
- return QPpsAttributeList();
- }
-
- QPpsAttribute ppsAttribute = decodeData(decoder);
- if (!ppsAttribute.isValid()) {
- *ok = false;
- return QPpsAttributeList();
- }
-
- list << ppsAttribute;
- }
-
- *ok = true;
- return list;
-}
-
-QPpsAttributeMap QPpsObjectPrivate::decodeObject(pps_decoder_t *decoder, bool *ok)
-{
- QPpsAttributeMap map;
-
- int length = pps_decoder_length(decoder);
- for (int i = 0; i < length; ++i) {
- // Force movement to a specific index.
- pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeObject: pps_decoder_goto_index failed");
- *ok = false;
- return QPpsAttributeMap();
- }
- QString name = QString::fromUtf8(pps_decoder_name(decoder));
- QPpsAttribute ppsAttribute = decodeData(decoder);
- if (!ppsAttribute.isValid()) {
- *ok = false;
- return QPpsAttributeMap();
- }
- map[name] = ppsAttribute;
- }
-
- *ok = true;
- return map;
-}
-
-QVariant QPpsObjectPrivate::variantFromPpsAttribute(const QPpsAttribute &attribute)
-{
- switch (attribute.type()) {
- case QPpsAttribute::Number:
- switch (attribute.toVariant().type()) {
- case QVariant::Int:
- return attribute.toInt();
- case QVariant::LongLong:
- return attribute.toLongLong();
- default:
- return attribute.toDouble();
- }
- break;
- case QPpsAttribute::Bool:
- return attribute.toBool();
- case QPpsAttribute::String:
- return attribute.toString();
- case QPpsAttribute::Array: {
- QVariantList variantList;
- const auto attrs = attribute.toList();
- for (const QPpsAttribute &attr : attrs) {
- QVariant variant = variantFromPpsAttribute(attr);
- if (!variant.isValid())
- return QVariantList();
- variantList << variant;
- }
- return variantList;
- }
- case QPpsAttribute::Object:
- return variantMapFromPpsAttributeMap(attribute.toMap());
- case QPpsAttribute::None:
- default:
- qWarning("QPpsObjectPrivate::variantFromPpsAttribute: invalid attribute parameter");
- return QVariant();
- }
-}
-
-QByteArray QPpsObjectPrivate::encode(const QVariantMap &ppsData, bool *ok)
-{
- pps_encoder_t encoder;
- pps_encoder_initialize(&encoder, false);
-
- encodeObject(&encoder, ppsData, ok);
- const char *rawData = 0;
- if (*ok) {
- // rawData points to a memory owned by encoder.
- // The memory will be freed when pps_encoder_cleanup is called.
- rawData = pps_encoder_buffer(&encoder);
- if (!rawData) {
- qWarning("QPpsObjectPrivate::encode: pps_encoder_buffer failed");
- *ok = false;
- }
- }
-
- pps_encoder_cleanup(&encoder);
- return QByteArray(rawData);
-}
-
-void QPpsObjectPrivate::encodeData(pps_encoder_t *encoder, const char *name, const QVariant &data,
- bool *ok)
-{
- const char *errorFunction;
- pps_encoder_error_t error = PPS_ENCODER_OK;
- switch (data.type()) {
- case QVariant::Bool:
- error = pps_encoder_add_bool(encoder, name, data.toBool());
- errorFunction = "pps_encoder_add_bool";
- break;
- // We want to support encoding uint even though libpps doesn't support it directly.
- // We can't encode uint as an int since that will lose precision (e.g. 2^31+1 can't be
- // encoded that way). However, we can convert uint to double without losing precision.
- // QVariant.toDouble() conveniently takes care of the conversion for us.
- case QVariant::UInt:
- case QVariant::Double:
- error = pps_encoder_add_double(encoder, name, data.toDouble());
- errorFunction = "pps_encoder_add_double";
- break;
- case QVariant::Int:
- error = pps_encoder_add_int(encoder, name, data.toInt());
- errorFunction = "pps_encoder_add_int";
- break;
- case QVariant::LongLong:
- error = pps_encoder_add_int64(encoder, name, data.toLongLong());
- errorFunction = "pps_encoder_add_int64";
- break;
- case QVariant::String:
- error = pps_encoder_add_string(encoder, name, data.toString().toUtf8().constData());
- errorFunction = "pps_encoder_add_string";
- break;
- case QVariant::List:
- error = pps_encoder_start_array(encoder, name);
- errorFunction = "pps_encoder_start_array";
- if (error == PPS_ENCODER_OK) {
- encodeArray(encoder, data.toList(), ok);
- error = pps_encoder_end_array(encoder);
- errorFunction = "pps_encoder_end_array";
- }
- break;
- case QVariant::Map:
- error = pps_encoder_start_object(encoder, name);
- errorFunction = "pps_encoder_start_object";
- if (error == PPS_ENCODER_OK) {
- encodeObject(encoder, data.toMap(), ok);
- error = pps_encoder_end_object(encoder);
- errorFunction = "pps_encoder_end_object";
- }
- break;
- case QVariant::Invalid:
- error = pps_encoder_add_null(encoder, name);
- errorFunction = "pps_encoder_add_null";
- break;
- default:
- qWarning("QPpsObjectPrivate::encodeData: the type of the parameter data is invalid");
- *ok = false;
- return;
- }
-
- if (error != PPS_ENCODER_OK) {
- qWarning("QPpsObjectPrivate::encodeData: %s failed", errorFunction);
- *ok = false;
- } else {
- *ok = true;
- }
-}
-
-void QPpsObjectPrivate::encodeArray(pps_encoder_t *encoder, const QVariantList &data, bool *ok)
-{
- for (QVariantList::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
- encodeData(encoder, 0, *it, ok);
- if (!(*ok))
- return;
- }
- // if the passed data is empty, nothing went wrong and ok is set to true
- *ok = true;
-}
-
-void QPpsObjectPrivate::encodeObject(pps_encoder_t *encoder, const QVariantMap &data, bool *ok)
-{
- for (QVariantMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) {
- encodeData(encoder, it.key().toUtf8().constData(), it.value(), ok);
- if (!(*ok))
- return;
- }
- // if the passed data is empty, nothing went wrong and ok is set to true
- *ok = true;
-}
-
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// QPpsObjectPrivate
-//
-///////////////////////////////////////////////////////////////////////////////
-
-QPpsObject::QPpsObject(const QString &path, QObject *parent)
- : QObject(*new QPpsObjectPrivate(path), parent)
-{
-}
-
-QPpsObject::~QPpsObject()
-{
- // RAII - ensure file gets closed
- if (isOpen())
- close();
-}
-
-int QPpsObject::error() const
-{
- Q_D(const QPpsObject);
- return d->error;
-}
-
-QString QPpsObject::errorString() const
-{
- Q_D(const QPpsObject);
- return qt_error_string(d->error);
-}
-
-bool QPpsObject::isReadyReadEnabled() const
-{
- Q_D(const QPpsObject);
-
- // query state of read ready signal
- return d->readyReadEnabled;
-}
-
-void QPpsObject::setReadyReadEnabled(bool enable)
-{
- Q_D(QPpsObject);
-
- // toggle whether socket notifier will emit a signal on read ready
- d->readyReadEnabled = enable;
- if (isOpen())
- d->notifier->setEnabled(enable);
-}
-
-bool QPpsObject::isBlocking() const
-{
- Q_D(const QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // abort if file not open
- if (!isOpen()) {
- d->error = EBADF;
- return false;
- }
-
- // query file status flags
- int flags = fcntl(d->fd, F_GETFL);
- if (flags == -1) {
- d->error = errno;
- return false;
- }
- // check if non-blocking flag is unset
- return ((flags & O_NONBLOCK) != O_NONBLOCK);
-}
-
-bool QPpsObject::setBlocking(bool enable)
-{
- Q_D(QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // abort if file not open
- if (!isOpen()) {
- d->error = EBADF;
- return false;
- }
-
- // query file status flags
- int flags = fcntl(d->fd, F_GETFL);
- if (flags == -1) {
- d->error = errno;
- return false;
- }
-
- // configure non-blocking flag
- if (enable)
- flags &= ~O_NONBLOCK;
- else
- flags |= O_NONBLOCK;
-
- // update file status flags
- flags = fcntl(d->fd, F_SETFL, flags);
- if (flags == -1) {
- d->error = errno;
- return false;
- }
-
- return true;
-}
-
-bool QPpsObject::isOpen() const
-{
- Q_D(const QPpsObject);
- return (d->fd != -1);
-}
-
-bool QPpsObject::open(QPpsObject::OpenModes mode)
-{
- Q_D(QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // abort if file already open
- if (isOpen()) {
- d->error = EBUSY;
- return false;
- }
-
- // convert pps flags to open flags
- int oflags = 0;
- if ((mode & QPpsObject::Publish) && (mode & QPpsObject::Subscribe))
- oflags |= O_RDWR;
- else if (mode & QPpsObject::Publish)
- oflags |= O_WRONLY;
- else if (mode & QPpsObject::Subscribe)
- oflags |= O_RDONLY;
-
- if (mode & QPpsObject::Create)
- oflags |= O_CREAT | O_EXCL;
-
- if (mode & QPpsObject::DeleteContents)
- oflags |= O_TRUNC;
-
- // open pps file
- d->fd = qt_safe_open(d->path.toUtf8().data(), oflags, 0666);
- if (d->fd == -1) {
- d->error = errno;
- return false;
- }
- // wire up socket notifier to know when reads are ready
- d->notifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, this);
- d->notifier->setEnabled(d->readyReadEnabled);
- QObject::connect(d->notifier, &QSocketNotifier::activated, this, &QPpsObject::readyRead);
- return true;
-}
-
-bool QPpsObject::close()
-{
- Q_D(QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // abort if file not open
- if (!isOpen()) {
- d->error = EBADF;
- return false;
- }
-
- // shutdown socket notifier
- delete d->notifier;
- d->notifier = 0;
-
- // close pps file
- const int result = qt_safe_close(d->fd);
- d->fd = -1;
-
- // check success of operation
- if (result != 0) {
- d->error = errno;
- return false;
- }
- return true;
-}
-
-QByteArray QPpsObject::read(bool *ok)
-{
- Q_D(QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // abort if file not open
- if (!isOpen()) {
- d->error = EBADF;
- safeAssign(ok, false);
- return QByteArray();
- }
-
- const int maxSize = ppsMaxSize->value;
- if (maxSize == -1) {
- qWarning("QPpsObject::read: maxSize is equal to -1");
- safeAssign(ok, false);
- return QByteArray();
- }
-
- QByteArray byteArray;
- byteArray.resize(maxSize); // resize doesn't initialize the data
- const int result = qt_safe_read(d->fd, byteArray.data(), byteArray.size());
-
- if (result == -1) {
- d->error = errno;
- qWarning() << "QPpsObject::read failed to read pps data, error " << errorString();
- safeAssign(ok, false);
- return QByteArray(); // Specifically return a default-constructed QByteArray.
- }
- if (result == 0) {
- // normalize the behavior of read() when no data is ready so a pps object
- // put in non-blocking mode via opening w/o wait (read returns 0) looks
- // the same as a pps object put in non-blocking mode by setting O_NONBLOCK
- // (read returns EAGAIN)
- d->error = EAGAIN;
- safeAssign(ok, false);
- return QByteArray(); // Specifically return a default-constructed QByteArray.
- }
- // resize byte array to amount actually read
- byteArray.resize(result);
- safeAssign(ok, true);
- return byteArray;
-}
-
-bool QPpsObject::write(const QByteArray &byteArray)
-{
- Q_D(QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // abort if file not open
- if (!isOpen()) {
- d->error = EBADF;
- return false;
- }
-
- // write entire byte array to pps file
- const int result = qt_safe_write(d->fd, byteArray.data(), byteArray.size());
- if (result == -1)
- d->error = errno;
-
- return (result == byteArray.size());
-}
-
-int QPpsObject::writeMessage(const QString &msg, const QVariantMap &dat)
-{
- // Treat empty msg as an encoding error
- if (msg.isEmpty())
- return -1;
-
- bool ok;
- QByteArray byteArray = encodeMessage(msg, dat, &ok);
-
- if (!ok)
- return -1;
-
- ok = write(byteArray);
- if (!ok)
- return error();
-
- return EOK;
-}
-
-int QPpsObject::writeMessage(const QString &msg, const QString &id, const QVariantMap &dat)
-{
- // Treat empty msg or id as an encoding error
- if (msg.isEmpty() || id.isEmpty())
- return -1;
-
- bool ok;
- QByteArray byteArray = encodeMessage(msg, id, dat, &ok);
-
- if (!ok)
- return -1;
-
- ok = write(byteArray);
- if (!ok)
- return error();
-
- return EOK;
-}
-
-bool QPpsObject::remove()
-{
- Q_D(QPpsObject);
-
- // reset last error
- d->error = EOK;
-
- // delete pps file
- const int result = unlink(d->path.toUtf8().data());
-
- // check success of operation
- if (result != 0) {
- d->error = errno;
- return false;
- }
- return true;
-}
-
-// static
-QVariantMap QPpsObject::decode(const QByteArray &rawData, bool *ok)
-{
- QPpsAttributeMap mapData = decodeWithFlags(rawData, 0, ok);
-
- // If *ok is false, then mapData is empty, so the resulting QVariantMap
- // will also be empty, as desired.
- return QPpsObjectPrivate::variantMapFromPpsAttributeMap(mapData);
-}
-
-// static
-QPpsAttributeMap QPpsObject::decodeWithFlags(const QByteArray &rawData, bool *ok)
-{
- return QPpsObject::decodeWithFlags(rawData, 0, ok);
-}
-
-// static
-QPpsAttributeMap QPpsObject::decodeWithFlags(const QByteArray &rawData,
- QPpsAttribute *objectAttribute, bool *ok)
-{
- safeAssign(ok, true);
-
- bool success = false;
- QPpsAttributeMap mapData = QPpsObjectPrivate::decode(rawData, &success);
- if (!success) {
- safeAssign(ok, false);
- return QPpsAttributeMap();
- }
-
- // The object name is the key of the first element, and the flags of that attribute
- // give the status for the object as a whole.
- if (!mapData.isEmpty() && objectAttribute) {
- QString extractedName = mapData.begin().key();
- QPpsAttribute topmostAttribute = mapData.begin().value();
- QPpsAttribute::Flags topmostFlags = topmostAttribute.flags();
- QPpsAttribute toplevelAttribute =
- QPpsAttributePrivate::createPpsAttribute(extractedName, topmostFlags);
- *objectAttribute = toplevelAttribute;
- }
-
- return mapData;
-}
-
-
-// static
-QByteArray QPpsObject::encode(const QVariantMap &ppsData, bool *ok)
-{
- safeAssign(ok, true);
-
- bool success = false;
- QByteArray byteArray = QPpsObjectPrivate::encode(ppsData, &success);
- if (!success) {
- safeAssign(ok, false);
- return QByteArray();
- }
- return byteArray;
-}
-
-// static
-QByteArray QPpsObject::encodeMessage(const QString &msg, const QVariantMap &dat, bool *ok)
-{
- safeAssign(ok, true);
-
- // Treat empty msg as an encoding error
- if (msg.isEmpty()) {
- safeAssign(ok, false);
- return QByteArray();
- }
-
- QVariantMap ppsData;
- ppsData[QStringLiteral("msg")] = msg;
- ppsData[QStringLiteral("dat")] = dat;
-
- return QPpsObject::encode(ppsData, ok);
-}
-
-// static
-QByteArray QPpsObject::encodeMessage(const QString &msg, const QString &id, const QVariantMap &dat,
- bool *ok)
-{
- safeAssign(ok, true);
-
- // Treat empty msg or id as an encoding error
- if (msg.isEmpty() || id.isEmpty()) {
- safeAssign(ok, false);
- return QByteArray();
- }
-
- QVariantMap ppsData;
- ppsData[QStringLiteral("msg")] = msg;
- ppsData[QStringLiteral("id")] = id;
- ppsData[QStringLiteral("dat")] = dat;
-
- return QPpsObject::encode(ppsData, ok);
-}
-
-// static
-int QPpsObject::sendMessage(const QString &path, const QString &message)
-{
- QPpsObject pps(path);
-
- bool ok = pps.open(QPpsObject::Publish);
- if (!ok)
- return pps.error();
-
- ok = pps.write(message.toLocal8Bit());
- if (!ok)
- return pps.error();
-
- return EOK;
-}
-
-// static
-int QPpsObject::sendMessage(const QString &path, const QVariantMap &message)
-{
- QPpsObject pps(path);
-
- bool ok = pps.open(QPpsObject::Publish);
- if (!ok)
- return pps.error();
-
- QByteArray payload = QPpsObject::encode(message, &ok);
- if (!ok)
- return -1;
-
- ok = pps.write(payload);
- if (!ok)
- return pps.error();
-
- return EOK;
-}
-
-// static
-int QPpsObject::sendMessage(const QString &path, const QString &msg, const QVariantMap &dat)
-{
- // Treat empty msg as an encoding error
- if (msg.isEmpty())
- return -1;
-
- QPpsObject pps(path);
-
- bool ok = pps.open(QPpsObject::Publish);
- if (!ok)
- return pps.error();
-
- QByteArray payload = QPpsObject::encodeMessage(msg, dat, &ok);
- if (!ok)
- return -1;
-
- ok = pps.write(payload);
- if (!ok)
- return pps.error();
-
- return EOK;
-}
-
-// static
-int QPpsObject::sendMessage(const QString &path, const QByteArray &ppsData)
-{
- QPpsObject pps(path);
-
- bool ok = pps.open(QPpsObject::Publish);
- if (!ok)
- return pps.error();
-
- ok = pps.write(ppsData);
- if (!ok)
- return pps.error();
-
- return EOK;
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qppsobject_p.h b/src/corelib/kernel/qppsobject_p.h
deleted file mode 100644
index a3bf3a5bc1..0000000000
--- a/src/corelib/kernel/qppsobject_p.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPPSOBJECT_P_H
-#define QPPSOBJECT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qppsattribute_p.h"
-
-#include <QMap>
-#include <QObject>
-#include <QVariantMap>
-
-QT_BEGIN_NAMESPACE
-
-class QPpsObjectPrivate;
-
-class Q_CORE_EXPORT QPpsObject : public QObject
-{
- Q_OBJECT
-
-public:
- enum OpenMode {
- Publish = 1,
- Subscribe = 2,
- PublishSubscribe = Publish | Subscribe,
- Create = 4,
- DeleteContents = 8
- };
- Q_DECLARE_FLAGS(OpenModes, OpenMode)
-
- explicit QPpsObject(const QString &path, QObject *parent = 0);
- virtual ~QPpsObject();
-
- int error() const;
- QString errorString() const;
-
- bool isReadyReadEnabled() const;
- bool isBlocking() const;
- bool setBlocking(bool enable);
- bool isOpen() const;
-
- bool open(QPpsObject::OpenModes mode = QPpsObject::PublishSubscribe);
- bool close();
- bool remove();
-
- QByteArray read(bool *ok = 0);
- bool write(const QByteArray &byteArray);
-
- int writeMessage(const QString &msg, const QVariantMap &dat);
- int writeMessage(const QString &msg, const QString &id, const QVariantMap &dat);
-
- static QVariantMap decode(const QByteArray &rawData, bool *ok = 0);
- static QPpsAttributeMap decodeWithFlags(const QByteArray &rawData, bool *ok = 0);
- static QPpsAttributeMap decodeWithFlags(const QByteArray &rawData,
- QPpsAttribute *objectAttribute, bool *ok = 0);
-
- static QByteArray encode(const QVariantMap &ppsData, bool *ok = 0);
- static QByteArray encodeMessage(const QString &msg, const QVariantMap &dat, bool *ok = 0);
- static QByteArray encodeMessage(const QString &msg, const QString &id, const QVariantMap &dat,
- bool *ok = 0);
-
- static int sendMessage(const QString &path, const QString &message);
- static int sendMessage(const QString &path, const QVariantMap &message);
- static int sendMessage(const QString &path, const QString &msg, const QVariantMap &dat);
- static int sendMessage(const QString &path, const QByteArray &ppsData);
-
-public Q_SLOTS:
- void setReadyReadEnabled(bool enable);
-
-Q_SIGNALS:
- void readyRead();
-
-private:
- Q_DECLARE_PRIVATE(QPpsObject)
- Q_DISABLE_COPY_MOVE(QPpsObject)
-};
-
-QT_END_NAMESPACE
-
-#endif // QPPSOBJECT_P_H
diff --git a/src/corelib/kernel/qppsobjectprivate_p.h b/src/corelib/kernel/qppsobjectprivate_p.h
deleted file mode 100644
index d6b4640832..0000000000
--- a/src/corelib/kernel/qppsobjectprivate_p.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPPSOBJECTPRIVATE_P_H_
-#define QPPSOBJECTPRIVATE_P_H_
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qppsattribute_p.h"
-
-#include <QMap>
-#include <QDebug>
-
-#include <sys/pps.h>
-#include <private/qobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSocketNotifier;
-
-class QPpsObjectPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QPpsObject)
-public:
- explicit QPpsObjectPrivate(const QString &path);
-
- static QPpsAttributeMap decode(const QByteArray &rawData, bool *ok);
- static QByteArray encode(const QVariantMap &ppsData, bool *ok);
-
- static QVariantMap variantMapFromPpsAttributeMap(const QPpsAttributeMap &data);
-
- QSocketNotifier *notifier;
- QString path;
- mutable int error;
- int fd;
- bool readyReadEnabled;
-
-private:
- static QPpsAttribute::Flags readFlags(pps_decoder_t *decoder);
- static QPpsAttribute decodeString(pps_decoder_t *decoder);
- static QPpsAttribute decodeNumber(pps_decoder_t *decoder);
- static QPpsAttribute decodeBool(pps_decoder_t *decoder);
- static QPpsAttribute decodeData(pps_decoder_t *decoder);
- static QPpsAttributeList decodeArray(pps_decoder_t *decoder, bool *ok);
- static QPpsAttributeMap decodeObject(pps_decoder_t *decoder, bool *ok);
- static bool decoderPush(pps_decoder_t *decoder, const char *name = 0);
- static bool decoderPop(pps_decoder_t *decoder);
-
- template<typename T>
- static QPpsAttribute decodeNestedData(T (*decodeFunction)(pps_decoder_t *, bool *),
- pps_decoder_t *decoder);
-
- static void encodeData(pps_encoder_t *encoder, const char *name,
- const QVariant &data, bool *ok);
- static void encodeArray(pps_encoder_t *encoder, const QVariantList &data, bool *ok);
- static void encodeObject(pps_encoder_t *encoder, const QVariantMap &data, bool *ok);
-
- static QVariant variantFromPpsAttribute(const QPpsAttribute &attribute);
-};
-
-inline bool QPpsObjectPrivate::decoderPush(pps_decoder_t *decoder, const char *name)
-{
- pps_decoder_error_t error = pps_decoder_push(decoder, name);
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeData: pps_decoder_push failed");
- return false;
- }
- return true;
-}
-
-inline bool QPpsObjectPrivate::decoderPop(pps_decoder_t *decoder)
-{
- pps_decoder_error_t error = pps_decoder_pop(decoder);
- if (error != PPS_DECODER_OK) {
- qWarning("QPpsObjectPrivate::decodeData: pps_decoder_pop failed");
- return false;
- }
- return true;
-}
-
-QT_END_NAMESPACE
-
-#endif /* QPPSOBJECTPRIVATE_P_H_ */
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index b362319f22..caa9fce787 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -1,309 +1,728 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qproperty.h"
#include "qproperty_p.h"
-#include "qpropertybinding_p.h"
#include <qscopedvaluerollback.h>
+#include <QScopeGuard>
+#include <QtCore/qloggingcategory.h>
+#include <QThread>
+#include <QtCore/qmetaobject.h>
+
+#include "qobject_p.h"
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQPropertyBinding, "qt.qproperty.binding");
+
using namespace QtPrivate;
-QPropertyBase::QPropertyBase(QPropertyBase &&other, void *propertyDataPtr)
+void QPropertyBindingPrivatePtr::destroyAndFreeMemory()
{
- std::swap(d_ptr, other.d_ptr);
- QPropertyBasePointer d{this};
- d.setFirstObserver(nullptr);
- if (auto binding = d.bindingPtr())
- binding->setProperty(propertyDataPtr);
+ QPropertyBindingPrivate::destroyAndFreeMemory(static_cast<QPropertyBindingPrivate *>(d));
}
-void QPropertyBase::moveAssign(QPropertyBase &&other, void *propertyDataPtr)
+void QPropertyBindingPrivatePtr::reset(QtPrivate::RefCounted *ptr) noexcept
+{
+ if (ptr != d) {
+ if (ptr)
+ ptr->addRef();
+ auto *old = std::exchange(d, ptr);
+ if (old && !old->deref())
+ QPropertyBindingPrivate::destroyAndFreeMemory(static_cast<QPropertyBindingPrivate *>(d));
+ }
+}
+
+
+void QPropertyBindingDataPointer::addObserver(QPropertyObserver *observer)
{
- if (&other == this)
+ if (auto *b = binding()) {
+ observer->prev = &b->firstObserver.ptr;
+ observer->next = b->firstObserver.ptr;
+ if (observer->next)
+ observer->next->prev = &observer->next;
+ b->firstObserver.ptr = observer;
+ } else {
+ auto &d = ptr->d_ref();
+ Q_ASSERT(!(d & QPropertyBindingData::BindingBit));
+ auto firstObserver = reinterpret_cast<QPropertyObserver*>(d);
+ observer->prev = reinterpret_cast<QPropertyObserver**>(&d);
+ observer->next = firstObserver;
+ if (observer->next)
+ observer->next->prev = &observer->next;
+ d = reinterpret_cast<quintptr>(observer);
+ }
+}
+
+/*!
+ \internal
+
+ QPropertyDelayedNotifications is used to manage delayed notifications in grouped property updates.
+ It acts as a pool allocator for QPropertyProxyBindingData, and has methods to manage delayed
+ notifications.
+
+ \sa beginPropertyUpdateGroup, endPropertyUpdateGroup
+*/
+struct QPropertyDelayedNotifications
+{
+ // we can't access the dynamic page size as we need a constant value
+ // use 4096 as a sensible default
+ static constexpr inline auto PageSize = 4096;
+ int ref = 0;
+ QPropertyDelayedNotifications *next = nullptr; // in case we have more than size dirty properties...
+ qsizetype used = 0;
+ // Size chosen to avoid allocating more than one page of memory, while still ensuring
+ // that we can store many delayed properties without doing further allocations
+ static constexpr qsizetype size = (PageSize - 3*sizeof(void *))/sizeof(QPropertyProxyBindingData);
+ QPropertyProxyBindingData delayedProperties[size];
+
+ /*!
+ \internal
+ This method is called when a property attempts to notify its observers while inside of a
+ property update group. Instead of actually notifying, it replaces \a bindingData's d_ptr
+ with a QPropertyProxyBindingData.
+ \a bindingData and \a propertyData are the binding data and property data of the property
+ whose notify call gets delayed.
+ \sa QPropertyBindingData::notifyObservers
+ */
+ void addProperty(const QPropertyBindingData *bindingData, QUntypedPropertyData *propertyData) {
+ if (bindingData->isNotificationDelayed())
+ return;
+ auto *data = this;
+ while (data->used == size) {
+ if (!data->next)
+ // add a new page
+ data->next = new QPropertyDelayedNotifications;
+ data = data->next;
+ }
+ auto *delayed = data->delayedProperties + data->used;
+ *delayed = QPropertyProxyBindingData { bindingData->d_ptr, bindingData, propertyData };
+ ++data->used;
+ // preserve the binding bit for faster access
+ quintptr bindingBit = bindingData->d_ptr & QPropertyBindingData::BindingBit;
+ bindingData->d_ptr = reinterpret_cast<quintptr>(delayed) | QPropertyBindingData::DelayedNotificationBit | bindingBit;
+ Q_ASSERT(bindingData->d_ptr > 3);
+ if (!bindingBit) {
+ if (auto observer = reinterpret_cast<QPropertyObserver *>(delayed->d_ptr))
+ observer->prev = reinterpret_cast<QPropertyObserver **>(&delayed->d_ptr);
+ }
+ }
+
+ /*!
+ \internal
+ Called in Qt::endPropertyUpdateGroup. For the QPropertyProxyBindingData at position
+ \a index, it
+ \list
+ \li restores the original binding data that was modified in addProperty and
+ \li evaluates any bindings which depend on properties that were changed inside
+ the group.
+ \endlist
+ Change notifications are sent later with notify (following the logic of separating
+ binding updates and notifications used in non-deferred updates).
+ */
+ void evaluateBindings(PendingBindingObserverList &bindingObservers, qsizetype index, QBindingStatus *status) {
+ auto *delayed = delayedProperties + index;
+ auto *bindingData = delayed->originalBindingData;
+ if (!bindingData)
+ return;
+
+ bindingData->d_ptr = delayed->d_ptr;
+ Q_ASSERT(!(bindingData->d_ptr & QPropertyBindingData::DelayedNotificationBit));
+ if (!bindingData->hasBinding()) {
+ if (auto observer = reinterpret_cast<QPropertyObserver *>(bindingData->d_ptr))
+ observer->prev = reinterpret_cast<QPropertyObserver **>(&bindingData->d_ptr);
+ }
+
+ QPropertyBindingDataPointer bindingDataPointer{bindingData};
+ QPropertyObserverPointer observer = bindingDataPointer.firstObserver();
+ if (observer)
+ observer.evaluateBindings(bindingObservers, status);
+ }
+
+ /*!
+ \internal
+ Called in Qt::endPropertyUpdateGroup. For the QPropertyProxyBindingData at position
+ \a i, it
+ \list
+ \li resets the proxy binding data and
+ \li sends any pending notifications.
+ \endlist
+ */
+ void notify(qsizetype index) {
+ auto *delayed = delayedProperties + index;
+ if (delayed->d_ptr & QPropertyBindingData::BindingBit)
+ return; // already handled
+ if (!delayed->originalBindingData)
+ return;
+ delayed->originalBindingData = nullptr;
+
+ QPropertyObserverPointer observer { reinterpret_cast<QPropertyObserver *>(delayed->d_ptr & ~QPropertyBindingData::DelayedNotificationBit) };
+ delayed->d_ptr = 0;
+
+ if (observer)
+ observer.notify(delayed->propertyData);
+ }
+};
+
+Q_CONSTINIT static thread_local QBindingStatus bindingStatus;
+
+/*!
+ \since 6.2
+
+ \relates QProperty
+
+ Marks the beginning of a property update group. Inside this group,
+ changing a property does neither immediately update any dependent properties
+ nor does it trigger change notifications.
+ Those are instead deferred until the group is ended by a call to endPropertyUpdateGroup.
+
+ Groups can be nested. In that case, the deferral ends only after the outermost group has been
+ ended.
+
+ \note Change notifications are only send after all property values affected by the group have
+ been updated to their new values. This allows re-establishing a class invariant if multiple
+ properties need to be updated, preventing any external observer from noticing an inconsistent
+ state.
+
+ \sa Qt::endPropertyUpdateGroup, QScopedPropertyUpdateGroup
+*/
+void Qt::beginPropertyUpdateGroup()
+{
+ QPropertyDelayedNotifications *& groupUpdateData = bindingStatus.groupUpdateData;
+ if (!groupUpdateData)
+ groupUpdateData = new QPropertyDelayedNotifications;
+ ++groupUpdateData->ref;
+}
+
+/*!
+ \since 6.2
+ \relates QProperty
+
+ Ends a property update group. If the outermost group has been ended, and deferred
+ binding evaluations and notifications happen now.
+
+ \warning Calling endPropertyUpdateGroup without a preceding call to beginPropertyUpdateGroup
+ results in undefined behavior.
+
+ \sa Qt::beginPropertyUpdateGroup, QScopedPropertyUpdateGroup
+*/
+void Qt::endPropertyUpdateGroup()
+{
+ auto status = &bindingStatus;
+ QPropertyDelayedNotifications *& groupUpdateData = status->groupUpdateData;
+ auto *data = groupUpdateData;
+ Q_ASSERT(data->ref);
+ if (--data->ref)
return;
+ groupUpdateData = nullptr;
+ // ensures that bindings are kept alive until endPropertyUpdateGroup concludes
+ PendingBindingObserverList bindingObservers;
+ // update all delayed properties
+ auto start = data;
+ while (data) {
+ for (qsizetype i = 0; i < data->used; ++i)
+ data->evaluateBindings(bindingObservers, i, status);
+ data = data->next;
+ }
+ // notify all delayed notifications from binding evaluation
+ for (const QBindingObserverPtr &observer: bindingObservers) {
+ QPropertyBindingPrivate *binding = observer.binding();
+ binding->notifyNonRecursive();
+ }
+ // do the same for properties which only have observers
+ data = start;
+ while (data) {
+ for (qsizetype i = 0; i < data->used; ++i)
+ data->notify(i);
+ delete std::exchange(data, data->next);
+ }
+}
- QPropertyBasePointer d{this};
- auto observer = d.firstObserver();
- d.setFirstObserver(nullptr);
+/*!
+ \since 6.6
+ \class QScopedPropertyUpdateGroup
+ \inmodule QtCore
+ \ingroup tools
+ \brief RAII class around Qt::beginPropertyUpdateGroup()/Qt::endPropertyUpdateGroup().
- if (auto binding = d.bindingPtr()) {
- binding->unlinkAndDeref();
- d_ptr &= FlagMask;
+ This class calls Qt::beginPropertyUpdateGroup() in its constructor and
+ Qt::endPropertyUpdateGroup() in its destructor, making sure the latter
+ function is reliably called even in the presence of early returns or thrown
+ exceptions.
+
+ \note Qt::endPropertyUpdateGroup() may re-throw exceptions thrown by
+ binding evaluations. This means your application may crash
+ (\c{std::terminate()} called) if another exception is causing
+ QScopedPropertyUpdateGroup's destructor to be called during stack
+ unwinding. If you expect exceptions from binding evaluations, use manual
+ Qt::endPropertyUpdateGroup() calls and \c{try}/\c{catch} blocks.
+
+ \sa QProperty
+*/
+
+/*!
+ \fn QScopedPropertyUpdateGroup::QScopedPropertyUpdateGroup()
+
+ Calls Qt::beginPropertyUpdateGroup().
+*/
+
+/*!
+ \fn QScopedPropertyUpdateGroup::~QScopedPropertyUpdateGroup()
+
+ Calls Qt::endPropertyUpdateGroup().
+*/
+
+
+// check everything stored in QPropertyBindingPrivate's union is trivially destructible
+// (though the compiler would also complain if that weren't the case)
+static_assert(std::is_trivially_destructible_v<QPropertyBindingSourceLocation>);
+static_assert(std::is_trivially_destructible_v<std::byte[sizeof(QPropertyBindingSourceLocation)]>);
+
+QPropertyBindingPrivate::~QPropertyBindingPrivate()
+{
+ if (firstObserver)
+ firstObserver.unlink();
+ if (vtable->size)
+ vtable->destroy(reinterpret_cast<std::byte *>(this)
+ + QPropertyBindingPrivate::getSizeEnsuringAlignment());
+}
+
+void QPropertyBindingPrivate::clearDependencyObservers() {
+ for (size_t i = 0; i < qMin(dependencyObserverCount, inlineDependencyObservers.size()); ++i) {
+ QPropertyObserverPointer p{&inlineDependencyObservers[i]};
+ p.unlink_fast();
}
+ if (heapObservers)
+ heapObservers->clear();
+ dependencyObserverCount = 0;
+}
- std::swap(d_ptr, other.d_ptr);
+QPropertyObserverPointer QPropertyBindingPrivate::allocateDependencyObserver_slow()
+{
+ ++dependencyObserverCount;
+ if (!heapObservers)
+ heapObservers.reset(new std::vector<QPropertyObserver>());
+ return {&heapObservers->emplace_back()};
+}
- if (auto binding = d.bindingPtr())
- binding->setProperty(propertyDataPtr);
+void QPropertyBindingPrivate::unlinkAndDeref()
+{
+ clearDependencyObservers();
+ propertyDataPtr = nullptr;
+ if (!deref())
+ destroyAndFreeMemory(this);
+}
- d.setFirstObserver(observer.ptr);
+bool QPropertyBindingPrivate::evaluateRecursive(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
+{
+ if (!status)
+ status = &bindingStatus;
+ return evaluateRecursive_inline(bindingObservers, status);
+}
- // The caller will have to notify observers.
+void QPropertyBindingPrivate::notifyNonRecursive(const PendingBindingObserverList &bindingObservers)
+{
+ notifyNonRecursive();
+ for (auto &&bindingObserver: bindingObservers) {
+ bindingObserver.binding()->notifyNonRecursive();
+ }
}
-QPropertyBase::~QPropertyBase()
+QPropertyBindingPrivate::NotificationState QPropertyBindingPrivate::notifyNonRecursive()
{
- QPropertyBasePointer d{this};
+ if (!pendingNotify)
+ return Delayed;
+ pendingNotify = false;
+ Q_ASSERT(!updating);
+ updating = true;
+ if (firstObserver) {
+ firstObserver.noSelfDependencies(this);
+ firstObserver.notify(propertyDataPtr);
+ }
+ if (hasStaticObserver)
+ staticObserverCallback(propertyDataPtr);
+ updating = false;
+ return Sent;
+}
+
+/*!
+ Constructs a null QUntypedPropertyBinding.
+
+ \sa isNull()
+*/
+QUntypedPropertyBinding::QUntypedPropertyBinding() = default;
+
+/*!
+ \fn template<typename Functor>
+ QUntypedPropertyBinding(QMetaType metaType, Functor &&f, const QPropertyBindingSourceLocation &location)
+
+ \internal
+*/
+
+/*!
+ \internal
+
+ Constructs QUntypedPropertyBinding. Assumes that \a metaType, \a function and \a vtable match.
+ Unless a specialization of \c BindingFunctionVTable is used, this function should never be called
+ directly.
+*/
+QUntypedPropertyBinding::QUntypedPropertyBinding(QMetaType metaType, const BindingFunctionVTable *vtable, void *function,
+ const QPropertyBindingSourceLocation &location)
+{
+ std::byte *mem = new std::byte[QPropertyBindingPrivate::getSizeEnsuringAlignment() + vtable->size]();
+ d = new(mem) QPropertyBindingPrivate(metaType, vtable, std::move(location));
+ vtable->moveConstruct(mem + QPropertyBindingPrivate::getSizeEnsuringAlignment(), function);
+}
+
+/*!
+ Move-constructs a QUntypedPropertyBinding from \a other.
+
+ \a other is left in a null state.
+ \sa isNull()
+*/
+QUntypedPropertyBinding::QUntypedPropertyBinding(QUntypedPropertyBinding &&other)
+ : d(std::move(other.d))
+{
+}
+
+/*!
+ Copy-constructs a QUntypedPropertyBinding from \a other.
+*/
+QUntypedPropertyBinding::QUntypedPropertyBinding(const QUntypedPropertyBinding &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Copy-assigns \a other to this QUntypedPropertyBinding.
+*/
+QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(const QUntypedPropertyBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Move-assigns \a other to this QUntypedPropertyBinding.
+
+ \a other is left in a null state.
+ \sa isNull
+*/
+QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(QUntypedPropertyBinding &&other)
+{
+ d = std::move(other.d);
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QUntypedPropertyBinding::QUntypedPropertyBinding(QPropertyBindingPrivate *priv)
+ : d(priv)
+{
+}
+
+/*!
+ Destroys the QUntypedPropertyBinding.
+*/
+QUntypedPropertyBinding::~QUntypedPropertyBinding()
+{
+}
+
+/*!
+ Returns \c true if the \c QUntypedPropertyBinding is null.
+ This is only true for default-constructed and moved-from instances.
+
+ \sa isNull()
+*/
+bool QUntypedPropertyBinding::isNull() const
+{
+ return !d;
+}
+
+/*!
+ Returns the error state of the binding.
+
+ \sa QPropertyBindingError
+*/
+QPropertyBindingError QUntypedPropertyBinding::error() const
+{
+ if (!d)
+ return QPropertyBindingError();
+ return static_cast<QPropertyBindingPrivate *>(d.get())->bindingError();
+}
+
+/*!
+ Returns the meta-type of the binding.
+ If the QUntypedPropertyBinding is null, an invalid QMetaType is returned.
+*/
+QMetaType QUntypedPropertyBinding::valueMetaType() const
+{
+ if (!d)
+ return QMetaType();
+ return static_cast<QPropertyBindingPrivate *>(d.get())->valueMetaType();
+}
+
+QPropertyBindingData::~QPropertyBindingData()
+{
+ QPropertyBindingDataPointer d{this};
+ if (isNotificationDelayed())
+ proxyData()->originalBindingData = nullptr;
for (auto observer = d.firstObserver(); observer;) {
auto next = observer.nextObserver();
observer.unlink();
observer = next;
}
- if (auto binding = d.bindingPtr())
+ if (auto binding = d.binding())
binding->unlinkAndDeref();
}
-QUntypedPropertyBinding QPropertyBase::setBinding(const QUntypedPropertyBinding &binding,
- void *propertyDataPtr,
- void *staticObserver,
- void (*staticObserverCallback)(void*, void*),
- bool (*guardCallback)(void *, void*))
+QUntypedPropertyBinding QPropertyBindingData::setBinding(const QUntypedPropertyBinding &binding,
+ QUntypedPropertyData *propertyDataPtr,
+ QPropertyObserverCallback staticObserverCallback,
+ QtPrivate::QPropertyBindingWrapper guardCallback)
{
QPropertyBindingPrivatePtr oldBinding;
QPropertyBindingPrivatePtr newBinding = binding.d;
- QPropertyBasePointer d{this};
+ QPropertyBindingDataPointer d{this};
QPropertyObserverPointer observer;
- if (auto *existingBinding = d.bindingPtr()) {
+ auto &data = d_ref();
+ if (auto *existingBinding = d.binding()) {
if (existingBinding == newBinding.data())
- return QUntypedPropertyBinding(oldBinding.data());
+ return QUntypedPropertyBinding(static_cast<QPropertyBindingPrivate *>(oldBinding.data()));
+ if (existingBinding->isUpdating()) {
+ existingBinding->setError({QPropertyBindingError::BindingLoop, QStringLiteral("Binding set during binding evaluation!")});
+ return QUntypedPropertyBinding(static_cast<QPropertyBindingPrivate *>(oldBinding.data()));
+ }
oldBinding = QPropertyBindingPrivatePtr(existingBinding);
- observer = oldBinding->takeObservers();
- oldBinding->unlinkAndDeref();
- d_ptr &= FlagMask;
+ observer = static_cast<QPropertyBindingPrivate *>(oldBinding.data())->takeObservers();
+ static_cast<QPropertyBindingPrivate *>(oldBinding.data())->unlinkAndDeref();
+ data = 0;
} else {
observer = d.firstObserver();
}
if (newBinding) {
- newBinding.data()->ref.ref();
- d_ptr = (d_ptr & FlagMask) | reinterpret_cast<quintptr>(newBinding.data());
- d_ptr |= BindingBit;
- newBinding->setDirty(true);
- newBinding->setProperty(propertyDataPtr);
+ newBinding.data()->addRef();
+ data = reinterpret_cast<quintptr>(newBinding.data());
+ data |= BindingBit;
+ auto newBindingRaw = static_cast<QPropertyBindingPrivate *>(newBinding.data());
+ newBindingRaw->setProperty(propertyDataPtr);
if (observer)
- newBinding->prependObserver(observer);
- newBinding->setStaticObserver(staticObserver, staticObserverCallback, guardCallback);
+ newBindingRaw->prependObserver(observer);
+ newBindingRaw->setStaticObserver(staticObserverCallback, guardCallback);
+
+ PendingBindingObserverList bindingObservers;
+ newBindingRaw->evaluateRecursive(bindingObservers);
+ newBindingRaw->notifyNonRecursive(bindingObservers);
} else if (observer) {
d.setObservers(observer.ptr);
} else {
- d_ptr &= ~QPropertyBase::BindingBit;
+ data = 0;
}
- return QUntypedPropertyBinding(oldBinding.data());
+ if (oldBinding)
+ static_cast<QPropertyBindingPrivate *>(oldBinding.data())->detachFromProperty();
+
+ return QUntypedPropertyBinding(static_cast<QPropertyBindingPrivate *>(oldBinding.data()));
}
-QPropertyBindingPrivate *QPropertyBase::binding()
+QPropertyBindingData::QPropertyBindingData(QPropertyBindingData &&other) : d_ptr(std::exchange(other.d_ptr, 0))
{
- QPropertyBasePointer d{this};
- if (auto binding = d.bindingPtr())
- return binding;
- return nullptr;
+ QPropertyBindingDataPointer::fixupAfterMove(this);
}
-QPropertyBindingPrivate *QPropertyBasePointer::bindingPtr() const
+BindingEvaluationState::BindingEvaluationState(QPropertyBindingPrivate *binding, QBindingStatus *status)
+ : binding(binding)
{
- if (ptr->d_ptr & QPropertyBase::BindingBit)
- return reinterpret_cast<QPropertyBindingPrivate*>(ptr->d_ptr & ~QPropertyBase::FlagMask);
- return nullptr;
+ Q_ASSERT(status);
+ QBindingStatus *s = status;
+ // store a pointer to the currentBindingEvaluationState to avoid a TLS lookup in
+ // the destructor (as these come with a non zero cost)
+ currentState = &s->currentlyEvaluatingBinding;
+ previousState = *currentState;
+ *currentState = this;
+ binding->clearDependencyObservers();
}
-void QPropertyBasePointer::setObservers(QPropertyObserver *observer)
+CompatPropertySafePoint::CompatPropertySafePoint(QBindingStatus *status, QUntypedPropertyData *property)
+ : property(property)
{
- observer->prev = reinterpret_cast<QPropertyObserver**>(&(ptr->d_ptr));
- ptr->d_ptr = (reinterpret_cast<quintptr>(observer) & ~QPropertyBase::FlagMask);
+ // store a pointer to the currentBindingEvaluationState to avoid a TLS lookup in
+ // the destructor (as these come with a non zero cost)
+ currentState = &status->currentCompatProperty;
+ previousState = *currentState;
+ *currentState = this;
+
+ currentlyEvaluatingBindingList = &bindingStatus.currentlyEvaluatingBinding;
+ bindingState = *currentlyEvaluatingBindingList;
+ *currentlyEvaluatingBindingList = nullptr;
}
-void QPropertyBasePointer::addObserver(QPropertyObserver *observer)
+QPropertyBindingPrivate *QPropertyBindingPrivate::currentlyEvaluatingBinding()
{
- if (auto *binding = bindingPtr()) {
- observer->prev = &binding->firstObserver.ptr;
- observer->next = binding->firstObserver.ptr;
- if (observer->next)
- observer->next->prev = &observer->next;
- binding->firstObserver.ptr = observer;
- } else {
- auto firstObserver = reinterpret_cast<QPropertyObserver*>(ptr->d_ptr & ~QPropertyBase::FlagMask);
- observer->prev = reinterpret_cast<QPropertyObserver**>(&ptr->d_ptr);
- observer->next = firstObserver;
- if (observer->next)
- observer->next->prev = &observer->next;
- }
- setFirstObserver(observer);
+ auto currentState = bindingStatus.currentlyEvaluatingBinding ;
+ return currentState ? currentState->binding : nullptr;
}
-void QPropertyBasePointer::setFirstObserver(QPropertyObserver *observer)
+// ### Unused, kept for BC with 6.0
+void QPropertyBindingData::evaluateIfDirty(const QUntypedPropertyData *) const
{
- if (auto *binding = bindingPtr()) {
- binding->firstObserver.ptr = observer;
- return;
- }
- ptr->d_ptr = reinterpret_cast<quintptr>(observer) | (ptr->d_ptr & QPropertyBase::FlagMask);
}
-QPropertyObserverPointer QPropertyBasePointer::firstObserver() const
+void QPropertyBindingData::removeBinding_helper()
{
- if (auto *binding = bindingPtr())
- return binding->firstObserver;
- return {reinterpret_cast<QPropertyObserver*>(ptr->d_ptr & ~QPropertyBase::FlagMask)};
-}
+ QPropertyBindingDataPointer d{this};
-static thread_local BindingEvaluationState *currentBindingEvaluationState = nullptr;
+ auto *existingBinding = d.binding();
+ Q_ASSERT(existingBinding);
+ if (existingBinding->isSticky()) {
+ return;
+ }
-BindingEvaluationState::BindingEvaluationState(QPropertyBindingPrivate *binding)
- : binding(binding)
-{
- previousState = currentBindingEvaluationState;
- currentBindingEvaluationState = this;
- binding->clearDependencyObservers();
+ auto observer = existingBinding->takeObservers();
+ d_ref() = 0;
+ if (observer)
+ d.setObservers(observer.ptr);
+ existingBinding->unlinkAndDeref();
}
-BindingEvaluationState::~BindingEvaluationState()
+void QPropertyBindingData::registerWithCurrentlyEvaluatingBinding() const
{
- currentBindingEvaluationState = previousState;
+ auto currentState = bindingStatus.currentlyEvaluatingBinding;
+ if (!currentState)
+ return;
+ registerWithCurrentlyEvaluatingBinding_helper(currentState);
}
-void QPropertyBase::evaluateIfDirty()
+
+void QPropertyBindingData::registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentState) const
{
- QPropertyBasePointer d{this};
- QPropertyBindingPrivate *binding = d.bindingPtr();
- if (!binding)
+ QPropertyBindingDataPointer d{this};
+
+ if (currentState->alreadyCaptureProperties.contains(this))
return;
- binding->evaluateIfDirtyAndReturnTrueIfValueChanged();
+ else
+ currentState->alreadyCaptureProperties.push_back(this);
+
+ QPropertyObserverPointer dependencyObserver = currentState->binding->allocateDependencyObserver();
+ Q_ASSERT(QPropertyObserver::ObserverNotifiesBinding == 0);
+ dependencyObserver.setBindingToNotify_unsafe(currentState->binding);
+ d.addObserver(dependencyObserver.ptr);
}
-void QPropertyBase::removeBinding()
+void QPropertyBindingData::notifyObservers(QUntypedPropertyData *propertyDataPtr) const
{
- QPropertyBasePointer d{this};
-
- if (auto *existingBinding = d.bindingPtr()) {
- auto observer = existingBinding->takeObservers();
- existingBinding->unlinkAndDeref();
- d_ptr &= ExtraBit;
- if (observer)
- d.setObservers(observer.ptr);
- }
+ notifyObservers(propertyDataPtr, nullptr);
}
-void QPropertyBase::registerWithCurrentlyEvaluatingBinding() const
+void QPropertyBindingData::notifyObservers(QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage) const
{
- auto currentState = currentBindingEvaluationState;
- if (!currentState)
+ if (isNotificationDelayed())
return;
-
- QPropertyBasePointer d{this};
-
- QPropertyObserverPointer dependencyObserver = currentState->binding->allocateDependencyObserver();
- dependencyObserver.setBindingToMarkDirty(currentState->binding);
- dependencyObserver.observeProperty(d);
+ QPropertyBindingDataPointer d{this};
+
+ PendingBindingObserverList bindingObservers;
+ if (QPropertyObserverPointer observer = d.firstObserver()) {
+ if (notifyObserver_helper(propertyDataPtr, storage, observer, bindingObservers) == Evaluated) {
+ /* evaluateBindings() can trash the observers. We need to re-fetch here.
+ "this" might also no longer be valid in case we have a QObjectBindableProperty
+ and consequently d isn't either (this happens when binding evaluation has
+ caused the binding storage to resize.
+ If storage is nullptr, then there is no dynamically resizable storage,
+ and we cannot run into the issue.
+ */
+ if (storage)
+ d = QPropertyBindingDataPointer {storage->bindingData(propertyDataPtr)};
+ if (QPropertyObserverPointer observer = d.firstObserver())
+ observer.notify(propertyDataPtr);
+ for (auto &&bindingObserver: bindingObservers)
+ bindingObserver.binding()->notifyNonRecursive();
+ }
+ }
}
-void QPropertyBase::notifyObservers(void *propertyDataPtr)
+QPropertyBindingData::NotificationResult QPropertyBindingData::notifyObserver_helper
+(
+ QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage,
+ QPropertyObserverPointer observer,
+ PendingBindingObserverList &bindingObservers) const
{
- QPropertyBasePointer d{this};
- if (QPropertyObserverPointer observer = d.firstObserver())
- observer.notify(d.bindingPtr(), propertyDataPtr);
-}
+#ifdef QT_HAS_FAST_CURRENT_THREAD_ID
+ QBindingStatus *status = storage ? storage->bindingStatus : nullptr;
+ if (!status || status->threadId != QThread::currentThreadId())
+ status = &bindingStatus;
+#else
+ Q_UNUSED(storage);
+ QBindingStatus *status = &bindingStatus;
+#endif
+ if (QPropertyDelayedNotifications *delay = status->groupUpdateData) {
+ delay->addProperty(this, propertyDataPtr);
+ return Delayed;
+ }
-int QPropertyBasePointer::observerCount() const
-{
- int count = 0;
- for (auto observer = firstObserver(); observer; observer = observer.nextObserver())
- ++count;
- return count;
+ observer.evaluateBindings(bindingObservers, status);
+ return Evaluated;
}
-QPropertyObserver::QPropertyObserver(void (*callback)(QPropertyObserver *, void *))
+
+QPropertyObserver::QPropertyObserver(ChangeHandler changeHandler)
{
QPropertyObserverPointer d{this};
- d.setChangeHandler(callback);
+ d.setChangeHandler(changeHandler);
}
-QPropertyObserver::QPropertyObserver(void *aliasedPropertyPtr)
+#if QT_DEPRECATED_SINCE(6, 6)
+QPropertyObserver::QPropertyObserver(QUntypedPropertyData *data)
{
- QPropertyObserverPointer d{this};
- d.setAliasedProperty(aliasedPropertyPtr);
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ aliasData = data;
+ next.setTag(ObserverIsAlias);
+ QT_WARNING_POP
}
+#endif
-void QPropertyObserver::setSource(QPropertyBase &property)
+/*! \internal
+*/
+void QPropertyObserver::setSource(const QPropertyBindingData &property)
{
QPropertyObserverPointer d{this};
- QPropertyBasePointer propPrivate{&property};
+ QPropertyBindingDataPointer propPrivate{&property};
d.observeProperty(propPrivate);
}
-
QPropertyObserver::~QPropertyObserver()
{
QPropertyObserverPointer d{this};
d.unlink();
}
-QPropertyObserver::QPropertyObserver() = default;
-
-QPropertyObserver::QPropertyObserver(QPropertyObserver &&other)
+QPropertyObserver::QPropertyObserver(QPropertyObserver &&other) noexcept
{
- std::swap(bindingToMarkDirty, other.bindingToMarkDirty);
- std::swap(next, other.next);
- std::swap(prev, other.prev);
+ binding = std::exchange(other.binding, {});
+ next = std::exchange(other.next, {});
+ prev = std::exchange(other.prev, {});
if (next)
next->prev = &next;
if (prev)
prev.setPointer(this);
}
-QPropertyObserver &QPropertyObserver::operator=(QPropertyObserver &&other)
+QPropertyObserver &QPropertyObserver::operator=(QPropertyObserver &&other) noexcept
{
if (this == &other)
return *this;
QPropertyObserverPointer d{this};
d.unlink();
- bindingToMarkDirty = nullptr;
+ binding = nullptr;
- std::swap(bindingToMarkDirty, other.bindingToMarkDirty);
- std::swap(next, other.next);
- std::swap(prev, other.prev);
+ binding = std::exchange(other.binding, {});
+ next = std::exchange(other.next, {});
+ prev = std::exchange(other.prev, {});
if (next)
next->prev = &next;
if (prev)
@@ -312,111 +731,209 @@ QPropertyObserver &QPropertyObserver::operator=(QPropertyObserver &&other)
return *this;
}
-void QPropertyObserverPointer::unlink()
-{
- if (ptr->next.tag() & QPropertyObserver::ObserverNotifiesAlias)
- ptr->aliasedPropertyPtr = 0;
- if (ptr->next)
- ptr->next->prev = ptr->prev;
- if (ptr->prev)
- ptr->prev.setPointer(ptr->next.data());
- ptr->next = nullptr;
- ptr->prev.clear();
-}
+/*!
+ \fn QPropertyObserverPointer::unlink()
+ \internal
+ Unlinks
+ */
-void QPropertyObserverPointer::setChangeHandler(void (*changeHandler)(QPropertyObserver *, void *))
+
+/*!
+ \fn QPropertyObserverPointer::unlink_fast()
+ \internal
+ Like unlink, but does not handle ObserverIsAlias.
+ Must only be called in places where we know that we are not dealing
+ with such an observer.
+ */
+
+void QPropertyObserverPointer::setChangeHandler(QPropertyObserver::ChangeHandler changeHandler)
{
+ Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder);
ptr->changeHandler = changeHandler;
ptr->next.setTag(QPropertyObserver::ObserverNotifiesChangeHandler);
}
-void QPropertyObserverPointer::setAliasedProperty(void *propertyPtr)
+/*!
+ \internal
+ The same as setBindingToNotify, but assumes that the tag is already correct.
+ */
+void QPropertyObserverPointer::setBindingToNotify_unsafe(QPropertyBindingPrivate *binding)
{
- ptr->aliasedPropertyPtr = quintptr(propertyPtr);
- ptr->next.setTag(QPropertyObserver::ObserverNotifiesAlias);
+ Q_ASSERT(ptr->next.tag() == QPropertyObserver::ObserverNotifiesBinding);
+ ptr->binding = binding;
}
-void QPropertyObserverPointer::setBindingToMarkDirty(QPropertyBindingPrivate *binding)
-{
- ptr->bindingToMarkDirty = binding;
- ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding);
-}
+/*!
+ \class QPropertyObserverNodeProtector
+ \internal
+ QPropertyObserverNodeProtector is a RAII wrapper which takes care of the internal switching logic
+ for QPropertyObserverPointer::notify (described ibidem)
+*/
-void QPropertyObserverPointer::notify(QPropertyBindingPrivate *triggeringBinding, void *propertyDataPtr)
-{
- bool knownIfPropertyChanged = false;
- bool propertyChanged = true;
+/*!
+ \fn QPropertyObserverNodeProtector::notify(QUntypedPropertyData *propertyDataPtr)
+ \internal
+ \a propertyDataPtr is a pointer to the observed property's property data
+*/
+#ifndef QT_NO_DEBUG
+void QPropertyObserverPointer::noSelfDependencies(QPropertyBindingPrivate *binding)
+{
auto observer = const_cast<QPropertyObserver*>(ptr);
+ // See also comment in notify()
while (observer) {
- auto * const next = observer->next.data();
- switch (observer->next.tag()) {
- case QPropertyObserver::ObserverNotifiesChangeHandler:
- if (!knownIfPropertyChanged && triggeringBinding) {
- knownIfPropertyChanged = true;
-
- propertyChanged = triggeringBinding->evaluateIfDirtyAndReturnTrueIfValueChanged();
+ if (QPropertyObserver::ObserverTag(observer->next.tag()) == QPropertyObserver::ObserverNotifiesBinding)
+ if (observer->binding == binding) {
+ qCritical("Property depends on itself!");
+ break;
}
- if (!propertyChanged)
- return;
- if (auto handlerToCall = std::exchange(observer->changeHandler, nullptr)) {
- handlerToCall(observer, propertyDataPtr);
- observer->changeHandler = handlerToCall;
- }
- break;
- case QPropertyObserver::ObserverNotifiesBinding:
- if (observer->bindingToMarkDirty)
- observer->bindingToMarkDirty->markDirtyAndNotifyObservers();
- break;
- case QPropertyObserver::ObserverNotifiesAlias:
- break;
+ observer = observer->next.data();
+ }
+
+}
+#endif
+
+void QPropertyObserverPointer::evaluateBindings(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
+{
+ Q_ASSERT(status);
+ auto observer = const_cast<QPropertyObserver*>(ptr);
+ // See also comment in notify()
+ while (observer) {
+ QPropertyObserver *next = observer->next.data();
+
+ if (QPropertyObserver::ObserverTag(observer->next.tag()) == QPropertyObserver::ObserverNotifiesBinding) {
+ auto bindingToEvaluate = observer->binding;
+ QPropertyObserverNodeProtector protector(observer);
+ QBindingObserverPtr bindingObserver(observer); // binding must not be gone after evaluateRecursive_inline
+ if (bindingToEvaluate->evaluateRecursive_inline(bindingObservers, status))
+ bindingObservers.push_back(std::move(bindingObserver));
+ next = protector.next();
}
+
observer = next;
}
}
-void QPropertyObserverPointer::observeProperty(QPropertyBasePointer property)
+void QPropertyObserverPointer::observeProperty(QPropertyBindingDataPointer property)
{
if (ptr->prev)
unlink();
property.addObserver(ptr);
}
-QPropertyBindingError::QPropertyBindingError(Type type)
+/*!
+ \class QPropertyBindingError
+ \inmodule QtCore
+ \ingroup tools
+ \since 6.0
+
+ QPropertyBindingError is used by \l{The Property System}{the property
+ system} to report errors that occurred when a binding was evaluated. Use \l
+ type() to query which error occurred, and \l
+ description() to extract an error message which might contain
+ more details.
+ If there is no error, QPropertyBindingError has type
+ \c QPropertyBindingError::NoError and \c hasError() returns false.
+
+ \code
+ extern QProperty<int> prop;
+
+ QPropertyBindingError error = prop.binding().error();
+ if (error.hasError())
+ qDebug() << error.description();
+ \endcode
+*/
+
+/*!
+ \enum QPropertyBindingError::Type
+
+ This enum specifies which error occurred.
+
+ \value NoError
+ No error occurred while evaluating the binding.
+ \value BindingLoop
+ Binding evaluation was stopped because a property depended on its own
+ value.
+ \value EvaluationError
+ Binding evaluation was stopped for any other reason than a binding loop.
+ For example, this value is used in the QML engine when an exception occurs
+ while a binding is evaluated.
+ \value UnknownError
+ A generic error type used when neither of the other values is suitable.
+ Calling \l description() might provide details.
+*/
+
+/*!
+ Default constructs QPropertyBindingError.
+ hasError() will return false, type will return \c NoError and
+ \l description() will return an empty string.
+*/
+QPropertyBindingError::QPropertyBindingError()
+{
+}
+
+/*!
+ Constructs a QPropertyBindingError of type \a type with \a description as its
+ description.
+*/
+QPropertyBindingError::QPropertyBindingError(Type type, const QString &description)
{
if (type != NoError) {
d = new QPropertyBindingErrorPrivate;
d->type = type;
+ d->description = description;
}
}
+/*!
+ Copy-constructs QPropertyBindingError from \a other.
+*/
QPropertyBindingError::QPropertyBindingError(const QPropertyBindingError &other)
: d(other.d)
{
}
+/*!
+ Copies \a other to this QPropertyBindingError.
+*/
QPropertyBindingError &QPropertyBindingError::operator=(const QPropertyBindingError &other)
{
d = other.d;
return *this;
}
+/*!
+ Move-constructs QPropertyBindingError from \a other.
+ \a other will be left in its default state.
+*/
QPropertyBindingError::QPropertyBindingError(QPropertyBindingError &&other)
: d(std::move(other.d))
{
}
+/*!
+ Move-assigns \a other to this QPropertyBindingError.
+ \a other will be left in its default state.
+*/
QPropertyBindingError &QPropertyBindingError::operator=(QPropertyBindingError &&other)
{
d = std::move(other.d);
return *this;
}
+/*!
+ Destroys the QPropertyBindingError.
+*/
QPropertyBindingError::~QPropertyBindingError()
{
}
+/*!
+ Returns the type of the QPropertyBindingError.
+
+ \sa QPropertyBindingError::Type
+*/
QPropertyBindingError::Type QPropertyBindingError::type() const
{
if (!d)
@@ -424,13 +941,10 @@ QPropertyBindingError::Type QPropertyBindingError::type() const
return d->type;
}
-void QPropertyBindingError::setDescription(const QString &description)
-{
- if (!d)
- d = new QPropertyBindingErrorPrivate;
- d->description = description;
-}
-
+/*!
+ Returns a descriptive error message for the QPropertyBindingError if
+ it has been set.
+*/
QString QPropertyBindingError::description() const
{
if (!d)
@@ -438,195 +952,423 @@ QString QPropertyBindingError::description() const
return d->description;
}
-QPropertyBindingSourceLocation QPropertyBindingError::location() const
-{
- if (!d)
- return QPropertyBindingSourceLocation();
- return d->location;
-}
+/*!
+ \class QPropertyData
+ \inmodule QtCore
+ \brief The QPropertyData class is a helper class for properties with automatic property bindings.
+ \since 6.0
+
+ \ingroup tools
+
+ QPropertyData\<T\> is a common base class for classes that can hold properties with automatic
+ data bindings. It mainly wraps the stored data, and offers low level access to that data.
+
+ The low level access to the data provided by this class bypasses the binding mechanism, and should be
+ used with care, as updates to the values will not get propagated to any bindings that depend on this
+ property.
+
+ You should usually call value() and setValue() on QProperty<T> or QObjectBindableProperty<T>, not use
+ the low level mechanisms provided in this class.
+*/
+
+/*! \fn template <typename T> QPropertyData<T>::parameter_type QPropertyData<T>::valueBypassingBindings() const
+
+ Returns the data stored in this property.
+
+ \note As this will bypass any binding evaluation it might return an outdated value if a
+ binding is set on this property. Using this method will also not register the property
+ access with any currently executing binding.
+*/
+
+/*! \fn template <typename T> void QPropertyData<T>::setValueBypassingBindings(parameter_type v)
+
+ Sets the data value stored in this property to \a v.
+
+ \note Using this method will bypass any potential binding registered for this property.
+*/
+
+/*! \fn template <typename T> void QPropertyData<T>::setValueBypassingBindings(rvalue_ref v)
+ \overload
+
+ Sets the data value stored in this property to \a v.
+
+ \note Using this method will bypass any potential binding registered for this property.
+*/
/*!
- \class QProperty
+ \class QUntypedBindable
\inmodule QtCore
- \brief The QProperty class is a template class that enables automatic property bindings.
+ \brief QUntypedBindable is a uniform interface over bindable properties like \c QProperty\<T\>
+ and \c QObjectBindableProperty of any type \c T.
+ \since 6.0
\ingroup tools
- QProperty\<T\> is a generic container that holds an instance of T. You can assign
- a value to it and you can read it via the value() function or the T conversion
- operator. You can also tie the property to an expression that computes the value
- dynamically, the binding expression. It is represented as a C++ lambda and
- can be used to express relationships between different properties in your
- application.
+ QUntypedBindable is a fully type-erased generic interface to wrap bindable properties.
+ You can use it to interact with properties without knowing their type nor caring what
+ kind of bindable property they are (e.g. QProperty or QObjectBindableProperty).
+ For most use cases, using QBindable\<T\> (which is generic over the property implementation
+ but has a fixed type) should be preferred.
+*/
- The binding expression computes the value by reading other QProperty values.
- Behind the scenes this dependency is tracked. Whenever a change in any property's
- dependency is detected, the binding expression is re-evaluated and the new
- result is applied to the property. This happens lazily, by marking the binding
- as dirty and evaluating it only when the property's value is requested. For example:
+/*!
+ \fn QUntypedBindable::QUntypedBindable()
- \code
- QProperty<QString> firstname("John");
- QProperty<QString> lastname("Smith");
- QProperty<int> age(41);
+ Default-constructs a QUntypedBindable. It is in an invalid state.
+ \sa isValid()
+*/
- QProperty<QString> fullname;
- fullname.setBinding([&]() { return firstname.value() + " " + lastname.value() + " age:" + QString::number(age.value()); });
+/*!
+ \fn template<typename Property> QUntypedBindable::QUntypedBindable(Property *property)
- qDebug() << fullname.value(); // Prints "John Smith age: 41"
+ Constructs a QUntypedBindable from the property \a property. If Property is const,
+ the QUntypedBindable will be read only. If \a property is null, the QUntypedBindable
+ will be invalid.
- firstname = "Emma"; // Marks binding expression as dirty
+ \sa isValid(), isReadOnly()
+*/
- qDebug() << fullname.value(); // Re-evaluates the binding expression and prints "Emma Smith age: 41"
+/*!
+ \fn bool QUntypedBindable::isValid() const
- // Birthday is coming up
- age.setValue(age.value() + 1);
+ Returns true if the QUntypedBindable is valid. Methods called on an invalid
+ QUntypedBindable generally have no effect, unless otherwise noted.
+*/
- qDebug() << fullname.value(); // Re-evaluates the binding expression and prints "Emma Smith age: 42"
- \endcode
+/*!
+ \fn bool QUntypedBindable::isReadOnly() const
+ \since 6.1
- When a new value is assigned to the \c firstname property, the binding
- expression for \c fullname is marked as dirty. So when the last \c qDebug() statement
- tries to read the name value of the \c fullname property, the expression is
- evaluated again, \c firstname() will be called again and return the new value.
+ Returns true if the QUntypedBindable is read-only.
+*/
- Since bindings are C++ lambda expressions, they may do anything that's possible
- in C++. This includes calling other functions. If those functions access values
- held by QProperty, they automatically become dependencies to the binding.
+/*!
+ \fn bool QUntypedBindable::isBindable() const
+ \internal
- Binding expressions may use properties of any type, so in the above example the age
- is an integer and folded into the string value using conversion to integer, but
- the dependency is fully tracked.
+ Returns true if the underlying property's binding can be queried
+ with binding() and, if not read-only, changed with setBinding.
+ Only QObjectComputedProperty currently leads to this method returning
+ false.
- \section1 Tracking properties
+ \sa isReadOnly()
+*/
- Sometimes the relationships between properties cannot be expressed using
- bindings. Instead you may need to run custom code whenever the value of a property
- changes and instead of assigning the value to another property, pass it to
- other parts of your application. For example writing data into a network socket
- or printing debug output. QProperty provides two mechanisms for tracking.
+/*!
+ \fn QUntypedPropertyBinding QUntypedBindable::makeBinding(const QPropertyBindingSourceLocation &location) const
- You can register for a callback function to be called whenever the value of
- a property changes, by using onValueChanged(). If you want the callback to also
- be called for the current value of the property, register your callback using
- subscribe() instead.
+ Creates a binding returning the underlying properties' value, using a specified source \a location.
*/
/*!
- \fn template <typename T> QProperty<T>::QProperty()
+ \fn void QUntypedBindable::observe(QPropertyObserver *observer)
+ \internal
- Constructs a property with a default constructed instance of T.
+ Installs the observer on the underlying property.
*/
/*!
- \fn template <typename T> explicit QProperty<T>::QProperty(const T &initialValue)
+ \fn template<typename Functor> QPropertyChangeHandler<Functor> QUntypedBindable::onValueChanged(Functor f) const
- Constructs a property with the provided \a initialValue.
+ Installs \a f as a change handler. Whenever the underlying property changes, \a f will be called, as
+ long as the returned \c QPropertyChangeHandler and the property are kept alive.
+ On each value change, the handler is either called immediately, or deferred, depending on the context.
+
+ \sa onValueChanged(), subscribe()
*/
/*!
- \fn template <typename T> explicit QProperty<T>::QProperty(T &&initialValue)
+ \fn template<typename Functor> QPropertyChangeHandler<Functor> QUntypedBindable::subscribe(Functor f) const
- Move-Constructs a property with the provided \a initialValue.
+ Behaves like a call to \a f followed by \c onValueChanged(f),
+
+ \sa onValueChanged()
*/
/*!
- \fn template <typename T> QProperty<T>::QProperty(QProperty<T> &&other)
+ \fn template<typename Functor> QPropertyNotifier QUntypedBindable::addNotifier(Functor f)
- Move-constructs a QProperty instance, making it point at the same object that
- \a other was pointing to.
+ Installs \a f as a change handler. Whenever the underlying property changes, \a f will be called, as
+ long as the returned \c QPropertyNotifier and the property are kept alive.
+
+ This method is in some cases easier to use than onValueChanged(), as the returned object is not a template.
+ It can therefore more easily be stored, e.g. as a member in a class.
+
+ \sa onValueChanged(), subscribe()
*/
/*!
- \fn template <typename T> QProperty<T> &QProperty<T>::operator=(QProperty &&other)
+ \fn QUntypedPropertyBinding QUntypedBindable::binding() const
- Move-assigns \a other to this QProperty instance.
+ Returns the underlying property's binding if there is any, or a default
+ constructed QUntypedPropertyBinding otherwise.
+
+ \sa hasBinding()
*/
/*!
- \fn template <typename T> QProperty<T>::QProperty(const QPropertyBinding<T> &binding)
+ \fn QUntypedPropertyBinding QUntypedBindable::takeBinding()
+
+ Removes the currently set binding from the property and returns it.
+ Returns a default-constructed QUntypedPropertyBinding if no binding is set.
- Constructs a property that is tied to the provided \a binding expression. The
- first time the property value is read, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read.
+ \since 6.1
*/
/*!
- \fn template <typename T> template <typename Functor> QProperty<T>::QProperty(Functor &&f)
+ \fn bool QUntypedBindable::setBinding(const QUntypedPropertyBinding &binding)
+
+ Sets the underlying property's binding to \a binding. This does not have any effect
+ if the QUntypedBindable is read-only, null or if \a binding's type does match the
+ underlying property's type.
+
+ \return \c true when the binding was successfully set.
- Constructs a property that is tied to the provided binding expression \a f. The
- first time the property value is read, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read.
+ //! \sa QUntypedPropertyBinding::valueMetaType()
*/
/*!
- \fn template <typename T> QProperty<T>::~QProperty()
+ \fn bool QUntypedBindable::hasBinding() const
- Destroys the property.
+ Returns \c true if the underlying property has a binding.
*/
/*!
- \fn template <typename T> T QProperty<T>::value() const
+ \fn QMetaType QUntypedBindable::metaType() const
+ \since 6.2
- Returns the value of the property. This may evaluate a binding expression that
- is tied to this property, before returning the value.
+ Returns the metatype of the property from which the QUntypedBindable was created.
+ If the bindable is invalid, an invalid metatype will be returned.
+
+ \sa isValid()
+ //! \sa QUntypedPropertyBinding::valueMetaType()
*/
/*!
- \fn template <typename T> QProperty<T>::operator T() const
+ \class QBindable
+ \inmodule QtCore
+ \brief QBindable is a wrapper class around binding-enabled properties. It allows type-safe
+ operations while abstracting the differences between the various property classes away.
+ \inherits QUntypedBindable
- Returns the value of the property. This may evaluate a binding expression that
- is tied to this property, before returning the value.
+ \ingroup tools
+
+ QBindable\<T\> helps to integrate Qt's traditional Q_PROPERTY with
+ \l {Qt Bindable Properties}{binding-enabled} properties.
+ If a property is backed by a QProperty, QObjectBindableProperty or QObjectComputedProperty,
+ you can add \c BINDABLE bindablePropertyName to the Q_PROPERTY
+ declaration, where bindablePropertyName is a function returning an instance of QBindable
+ constructed from the QProperty. The returned QBindable allows users of the property to set
+ and query bindings of the property, without having to know the exact kind of binding-enabled
+ property used.
+
+ \snippet code/src_corelib_kernel_qproperty.cpp 0
+ \snippet code/src_corelib_kernel_qproperty.cpp 3
+
+ \sa QMetaProperty::isBindable, QProperty, QObjectBindableProperty,
+ QObjectComputedProperty, {Qt Bindable Properties}
*/
/*!
- \fn template <typename T> void QProperty<T>::setValue(const T &newValue)
+ \fn template<typename T> QBindable<T>::QBindable(QObject *obj, const char *property)
- Assigns \a newValue to this property and removes the property's associated
- binding, if present.
+ Constructs a QBindable for the \l Q_PROPERTY \a property on \a obj. The property must
+ have a notify signal but does not need to have \c BINDABLE in its \c Q_PROPERTY
+ definition, so even binding unaware \c {Q_PROPERTY}s can be bound or used in binding
+ expressions. You must use \c QBindable::value() in binding expressions instead of the
+ normal property \c READ function (or \c MEMBER) to enable dependency tracking if the
+ property is not \c BINDABLE. When binding using a lambda, you may prefer to capture the
+ QBindable by value to avoid the cost of calling this constructor in the binding
+ expression.
+ This constructor should not be used to implement \c BINDABLE for a Q_PROPERTY, as the
+ resulting Q_PROPERTY will not support dependency tracking. To make a property that is
+ usable directly without reading through a QBindable use \l QProperty or
+ \l QObjectBindableProperty.
+
+ \code
+ QProperty<QString> displayText;
+ QDateTimeEdit *dateTimeEdit = findDateTimeEdit();
+ QBindable<QDateTime> dateTimeBindable(dateTimeEdit, "dateTime");
+ displayText.setBinding([dateTimeBindable](){ return dateTimeBindable.value().toString(); });
+ \endcode
+
+ \sa QProperty, QObjectBindableProperty, {Qt Bindable Properties}
*/
/*!
- \fn template <typename T> void QProperty<T>::setValue(T &&newValue)
- \overload
+ \fn template<typename T> QBindable<T>::QBindable(QObject *obj, const QMetaProperty &property)
- Assigns \a newValue to this property and removes the property's associated
- binding, if present.
+ See \l QBindable::QBindable(QObject *obj, const char *property)
*/
/*!
- \fn template <typename T> QProperty<T> &QProperty<T>::operator=(const T &newValue)
+ \fn template<typename T> QPropertyBinding<T> QBindable<T>::makeBinding(const QPropertyBindingSourceLocation &location) const
- Assigns \a newValue to this property and returns a reference to this QProperty.
+ Constructs a binding evaluating to the underlying property's value, using a specified source
+ \a location.
+*/
+
+/*!
+ \fn template <typename T> QPropertyBinding<T> QBindable<T>::binding() const
+
+ Returns the currently set binding of the underlying property. If the property does not
+ have a binding, the returned \c QPropertyBinding<T> will be invalid.
+
+ \sa setBinding, hasBinding
+ //! \sa QPropertyBinding::isValid()
+*/
+
+/*!
+ \fn template <typename T> QPropertyBinding<T> QBindable<T>::takeBinding()
+
+ Removes the currently set binding of the underlying property and returns it.
+ If the property does not have a binding, the returned \c QPropertyBinding<T> will be invalid.
+
+ \sa binding, setBinding, hasBinding
+ //! \sa QPropertyBinding::isValid()
+*/
+
+
+/*!
+ \fn template <typename T> void QBindable<T>::setBinding(const QPropertyBinding<T> &binding)
+
+ Sets the underlying property's binding to \a binding. Does nothing if the QBindable is
+ read-only or invalid.
+
+ \sa binding, isReadOnly(), isValid()
+ //! \sa QPropertyBinding::isValid()
*/
/*!
- \fn template <typename T> QProperty<T> &QProperty<T>::operator=(T &&newValue)
+ \fn template <typename T> template <typename Functor> QPropertyBinding<T> QBindable<T>::setBinding(Functor f);
\overload
- Assigns \a newValue to this property and returns a reference to this QProperty.
+ Creates a \c QPropertyBinding<T> from \a f, and sets it as the underlying property's binding.
*/
/*!
- \fn template <typename T> QProperty<T> &QProperty<T>::operator=(const QPropertyBinding<T> &newBinding)
+ \fn template <typename T> T QBindable<T>::value() const
- Associates the value of this property with the provided \a newBinding
- expression and returns a reference to this property. The first time the
- property value is read, the binding is evaluated. Whenever a dependency of the
- binding changes, the binding will be re-evaluated the next time the value of
- this property is read.
+ Returns the underlying property's current value. If the QBindable is invalid,
+ a default constructed \c T is returned.
+
+ \sa isValid()
+*/
+
+/*!
+ \fn template <typename T> void QBindable<T>::setValue(const T &value)
+
+ Sets the underlying property's value to \a value. This removes any currenltly set
+ binding from it. This function has no effect if the QBindable is read-only or invalid.
+
+ \sa isValid(), isReadOnly(), setBinding()
+*/
+
+/*!
+ \class QProperty
+ \inmodule QtCore
+ \brief The QProperty class is a template class that enables automatic property bindings.
+ \since 6.0
+
+ \ingroup tools
+
+ QProperty\<T\> is one of the classes implementing \l {Qt Bindable Properties}.
+ It is a container that holds an instance of T. You can assign
+ a value to it and you can read it via the value() function or the T conversion
+ operator. You can also tie the property to an expression that computes the value
+ dynamically, the binding expression. It is represented as a C++ lambda and
+ can be used to express relationships between different properties in your
+ application.
+
+ \note For QML, it's important to expose the \l QProperty in \l Q_PROPERTY
+ with the BINDABLE keyword. As a result, the QML engine uses
+ it as the bindable interface to set up the property binding. In turn, the
+ binding can then be interacted with C++ via the normal API:
+ QProperty<T>::onValueChanged, QProperty::takeBinding and QBindable::hasBinding
+ If the property is BINDABLE, the engine will use the change-tracking
+ inherent to the C++ property system for getting notified about changes, and it
+ won't rely on signals being emitted.
+*/
+
+/*!
+ \fn template <typename T> QProperty<T>::QProperty()
+
+ Constructs a property with a default constructed instance of T.
+*/
+
+/*!
+ \fn template <typename T> explicit QProperty<T>::QProperty(const T &initialValue)
+
+ Constructs a property with the provided \a initialValue.
+*/
+
+/*!
+ \fn template <typename T> explicit QProperty<T>::QProperty(T &&initialValue)
+
+ Move-Constructs a property with the provided \a initialValue.
+*/
+
+/*!
+ \fn template <typename T> QProperty<T>::QProperty(QProperty<T> &&other)
+
+ Move-constructs a QProperty instance, making it point at the same object that
+ \a other was pointing to.
+*/
+
+/*!
+ \fn template <typename T> QProperty<T>::QProperty(const QPropertyBinding<T> &binding)
+
+ Constructs a property that is tied to the provided \a binding expression.
+ The property's value is set to the result of evaluating the new binding.
+ Whenever a dependency of the binding changes, the binding will be re-evaluated,
+ and the property's value gets updated accordingly.
+*/
+
+/*!
+ \fn template <typename T> template <typename Functor> QProperty<T>::QProperty(Functor &&f)
+
+ Constructs a property that is tied to the provided binding expression \a f.
+ The property's value is set to the result of evaluating the new binding.
+ Whenever a dependency of the binding changes, the binding will be re-evaluated,
+ and the property's value gets updated accordingly.
+ */
+
+/*!
+ \fn template <typename T> QProperty<T>::~QProperty()
+
+ Destroys the property.
+*/
+
+/*!
+ \fn template <typename T> T QProperty<T>::value() const
+
+ Returns the value of the property. This may evaluate a binding expression that
+ is tied to this property, before returning the value.
+*/
+
+/*!
+ \fn template <typename T> void QProperty<T>::setValue(rvalue_ref newValue)
+ \fn template <typename T> void QProperty<T>::setValue(parameter_type newValue)
+
+ Assigns \a newValue to this property and removes the property's associated
+ binding, if present.
+*/
+
+/*!
+ \fn template <typename T> QProperty<T> &QProperty<T>::operator=(rvalue_ref newValue)
+ \fn template <typename T> QProperty<T> &QProperty<T>::operator=(parameter_type newValue)
+
+ Assigns \a newValue to this property and returns a reference to this QProperty.
*/
/*!
\fn template <typename T> QPropertyBinding<T> QProperty<T>::setBinding(const QPropertyBinding<T> &newBinding)
Associates the value of this property with the provided \a newBinding
- expression and returns the previously associated binding. The first time the
- property value is read, the binding is evaluated. Whenever a dependency of the
- binding changes, the binding will be re-evaluated the next time the value of
- this property is read.
+ expression and returns the previously associated binding. The property's value
+ is set to the result of evaluating the new binding. Whenever a dependency of
+ the binding changes, the binding will be re-evaluated, and the property's
+ value gets updated accordingly.
*/
/*!
@@ -634,21 +1376,12 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
\overload
Associates the value of this property with the provided functor \a f and
- returns the previously associated binding. The first time the property value
- is read, the binding is evaluated by invoking the call operator () of \a f.
- Whenever a dependency of the binding changes, the binding will be re-evaluated
- the next time the value of this property is read.
-*/
-
-/*!
- \fn template <typename T> QPropertyBinding<T> QProperty<T>::setBinding(QPropertyBinding<T> &&newBinding)
- \overload
+ returns the previously associated binding. The property's value is set to the
+ result of evaluating the new binding. Whenever a dependency of the binding
+ changes, the binding will be re-evaluated, and the property's value gets
+ updated accordingly.
- Associates the value of this property with the provided \a newBinding
- expression and returns the previously associated binding. The first time the
- property value is read, the binding is evaluated. Whenever a dependency of the
- binding changes, the binding will be re-evaluated the next time the value of
- this property is read.
+ \sa {Formulating a Property Binding}
*/
/*!
@@ -656,9 +1389,10 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
\overload
Associates the value of this property with the provided \a newBinding
- expression. The first time the property value is read, the binding is evaluated.
- Whenever a dependency of the binding changes, the binding will be re-evaluated
- the next time the value of this property is read.
+ expression. The property's value is set to the result of evaluating the new
+ binding. Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
+
Returns true if the type of this property is the same as the type the binding
function returns; false otherwise.
@@ -684,139 +1418,357 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
\fn template <typename T> template <typename Functor> QPropertyChangeHandler<T, Functor> QProperty<T>::onValueChanged(Functor f)
Registers the given functor \a f as a callback that shall be called whenever
- the value of the property changes.
+ the value of the property changes. On each value change, the handler
+ is either called immediately, or deferred, depending on the context.
- The callback \a f is expected to be a type that has a plain call operator () without any
- parameters. This means that you can provide a C++ lambda expression, an std::function
- or even a custom struct with a call operator.
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
- The returned property change handler object keeps track of the registration. When it
- goes out of scope, the callback is de-registered.
+ The returned property change handler object keeps track of the registration.
+ When it goes out of scope, the callback is de-registered.
*/
/*!
\fn template <typename T> template <typename Functor> QPropertyChangeHandler<T, Functor> QProperty<T>::subscribe(Functor f)
- Subscribes the given functor \a f as a callback that is called immediately and whenever
- the value of the property changes in the future.
+ Subscribes the given functor \a f as a callback that is called immediately and
+ whenever the value of the property changes in the future. On each value
+ change, the handler is either called immediately, or deferred, depending on
+ the context.
+
+ The callback \a f is expected to be a type that can be copied and has a plain
+ call operator() without any parameters. This means that you can provide a C++
+ lambda expression, a std::function or even a custom struct with a call
+ operator.
- The callback \a f is expected to be a type that has a plain call operator () without any
- parameters. This means that you can provide a C++ lambda expression, an std::function
- or even a custom struct with a call operator.
+ The returned property change handler object keeps track of the subscription.
+ When it goes out of scope, the callback is unsubscribed.
+*/
+
+/*!
+ \fn template <typename T> template <typename Functor> QPropertyNotifier QProperty<T>::addNotifier(Functor f)
+
+ Subscribes the given functor \a f as a callback that is called whenever
+ the value of the property changes.
+
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
- The returned property change handler object keeps track of the subscription. When it
- goes out of scope, the callback is unsubscribed.
+ The returned property change handler object keeps track of the subscription.
+ When it goes out of scope, the callback is unsubscribed.
+
+ This method is in some cases easier to use than onValueChanged(), as the
+ returned object is not a template. It can therefore more easily be stored,
+ e.g. as a member in a class.
+
+ \sa onValueChanged(), subscribe()
+*/
+
+/*!
+ \fn template <typename T> QtPrivate::QPropertyBindingData &QProperty<T>::bindingData() const
+ \internal
*/
/*!
- \class QNotifiedProperty
+ \class QObjectBindableProperty
\inmodule QtCore
- \brief The QNotifiedProperty class is a template class that enables automatic property bindings
- and invokes a callback function on the surrounding class when the value changes.
+ \brief The QObjectBindableProperty class is a template class that enables
+ automatic property bindings for property data stored in QObject derived
+ classes.
+ \since 6.0
\ingroup tools
- QNotifiedProperty\<T, Callback\> is a generic container that holds an
- instance of T and behaves mostly like \l QProperty. The extra template
- parameter is used to identify the surrounding class and a member function of
- that class. The member function will be called whenever the value held by the
- property changes.
+ QObjectBindableProperty is a generic container that holds an
+ instance of T and behaves mostly like \l QProperty.
+ It is one of the classes implementing \l {Qt Bindable Properties}.
+ Unlike QProperty, it stores its management data structure in
+ the surrounding QObject.
+ The extra template parameters are used to identify the surrounding
+ class and a member function of that class acting as a change handler.
- You can use QNotifiedProperty to port code that uses Q_PROPERTY. The getter
- and setter are trivial to adapt for accessing a \l QProperty rather than the
- plain value. In order to invoke the change signal on property changes, use
- QNotifiedProperty and pass the change signal as callback.
+ You can use QObjectBindableProperty to add binding support to code that uses
+ Q_PROPERTY. The getter and setter methods must be adapted carefully according
+ to the rules described in \l {Bindable Property Getters and Setters}.
- \code
- class MyClass : public QObject
- {
- \Q_OBJECT
- // Replacing: Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged)
- public:
- int x() const { return xProp; }
- void setX(int x) { xProp = x; }
-
- signals:
- void xChanged();
-
- private:
- // Now you can set bindings on xProp and use it in other bindings.
- QNotifiedProperty<int, &MyClass::xChanged> xProp;
- };
- \endcode
+ In order to invoke the change signal on property changes, use
+ QObjectBindableProperty and pass the change signal as a callback.
+
+ A simple example is given in the following.
+
+ \snippet code/src_corelib_kernel_qproperty.cpp 4
+
+ QObjectBindableProperty is usually not used directly, instead an instance of
+ it is created by using the Q_OBJECT_BINDABLE_PROPERTY macro.
+
+ Use the Q_OBJECT_BINDABLE_PROPERTY macro in the class declaration to declare
+ the property as bindable.
+
+ \snippet code/src_corelib_kernel_qproperty.cpp 0
+
+ If you need to directly initialize the property with some non-default value,
+ you can use the Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS macro. It accepts a
+ value for the initialization as one of its parameters.
+
+ \snippet code/src_corelib_kernel_qproperty.cpp 1
+
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS does not support multiple arguments
+ directly. If your property requires multiple arguments for initialization,
+ please explicitly call the specific constructor.
+
+ \snippet code/src_corelib_kernel_qproperty.cpp 2
+
+ The change handler can optionally accept one argument, of the same type as the
+ property, in which case it is passed the new value of the property. Otherwise,
+ it should take no arguments.
+
+ If the property does not need a changed notification, you can leave out the
+ "NOTIFY xChanged" in the Q_PROPERTY macro as well as the last argument
+ of the Q_OBJECT_BINDABLE_PROPERTY and Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS
+ macros.
+
+ \sa Q_OBJECT_BINDABLE_PROPERTY, Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS,
+ QProperty, QObjectComputedProperty, {Qt's Property System}, {Qt Bindable
+ Properties}
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::QNotifiedProperty()
+ \macro Q_OBJECT_BINDABLE_PROPERTY(containingClass, type, name, signal)
+ \since 6.0
+ \relates QObjectBindableProperty
+ \brief Declares a \l QObjectBindableProperty inside \a containingClass of type
+ \a type with name \a name. If the optional argument \a signal is given, this
+ signal will be emitted when the property is marked dirty.
- Constructs a property with a default constructed instance of T.
+ \sa {Qt's Property System}, {Qt Bindable Properties}
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> explicit QNotifiedProperty<T, Callback>::QNotifiedProperty(const T &initialValue)
+ \macro Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(containingClass, type, name, initialvalue, signal)
+ \since 6.0
+ \relates QObjectBindableProperty
+ \brief Declares a \l QObjectBindableProperty inside \a containingClass
+ of type \a type with name \a name which is initialized to \a initialvalue.
+ If the optional argument \a signal is given, this signal will be emitted when
+ the property is marked dirty.
- Constructs a property with the provided \a initialValue.
+ \sa {Qt's Property System}, {Qt Bindable Properties}
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> explicit QNotifiedProperty<T, Callback>::QNotifiedProperty(T &&initialValue)
+ \class QObjectCompatProperty
+ \inmodule QtCore
+ \brief The QObjectCompatProperty class is a template class to help port old
+ properties to the bindable property system.
+ \since 6.0
+ \ingroup tools
+ \internal
- Move-Constructs a property with the provided \a initialValue.
+ QObjectCompatProperty is a generic container that holds an
+ instance of \c T and behaves mostly like QProperty, just like
+ QObjectBindableProperty. It's one of the Qt internal classes implementing
+ \l {Qt Bindable Properties}. Like QObjectBindableProperty,
+ QObjectCompatProperty stores its management data structure in the surrounding
+ QObject. The last template parameter specifies a method (of the owning
+ class) to be called when the property is changed through the binding.
+ This is usually a setter.
+
+ As explained in \l {Qt Bindable Properties}, getters and setters for bindable
+ properties have to be almost trivial to be correct. However, in legacy code,
+ there is often complex logic in the setter. QObjectCompatProperty is a helper
+ to port these properties to the bindable property system.
+
+ With QObjectCompatProperty, the same rules as described in
+ \l {Bindable Property Getters and Setters} hold for the getter.
+ For the setter, the rules are different. It remains that every possible code
+ path in the setter must write to the underlying QObjectCompatProperty,
+ otherwise calling the setter might not remove a pre-existing binding, as
+ it should. However, as QObjectCompatProperty will call the setter on every
+ change, the setter is allowed to contain code like updating class internals
+ or emitting signals. Every write to the QObjectCompatProperty has to
+ be analyzed carefully to comply with the rules given in
+ \l {Writing to a Bindable Property}.
+
+ \section2 Properties with Virtual Setters
+
+ Some of the pre-existing Qt classes (for example, \l QAbstractProxyModel)
+ have properties with virtual setters. Special care must be taken when
+ making such properties bindable.
+
+ For the binding to work properly, the property must be correctly handled in
+ all reimplemented methods of each derived class.
+
+ Unless the derived class has access to the underlying property object, the
+ base implementation \e must be called for the binding to work correctly.
+
+ If the derived class can directly access the property instance, there is no
+ need to explicitly call the base implementation, but the property's value
+ \e must be correctly updated.
+
+ Refer to \l {Bindable Properties with Virtual Setters and Getters} for more
+ details.
+
+ In both cases the expected behavior \e must be documented in the property's
+ documentation, so that users can correctly override the setter.
+
+ Properties for which these conditions cannot be met should not be made
+ bindable.
+
+ \sa Q_OBJECT_COMPAT_PROPERTY, QObjectBindableProperty, {Qt's Property System}, {Qt Bindable
+ Properties}
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::QNotifiedProperty(Class *owner, const QPropertyBinding<T> &binding)
+ \macro Q_OBJECT_COMPAT_PROPERTY(containingClass, type, name, callback)
+ \since 6.0
+ \relates QObjectCompatProperty
+ \internal
+ \brief Declares a \l QObjectCompatProperty inside \a containingClass
+ of type \a type with name \a name. The argument \a callback specifies
+ a setter function to be called when the property is changed through the binding.
- Constructs a property that is tied to the provided \a binding expression. The
- first time the property value is read, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read. When the property value changes \a
- owner is notified via the Callback function.
+ \sa QObjectBindableProperty, {Qt's Property System}, {Qt Bindable Properties}
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::QNotifiedProperty(Class *owner, QPropertyBinding<T> &&binding)
+ \macro Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(containingClass, type, name, callback, value)
+ \since 6.0
+ \relates QObjectCompatProperty
+ \internal
+ \brief Declares a \l QObjectCompatProperty inside of \a containingClass
+ of type \a type with name \a name. The argument \a callback specifies
+ a setter function to be called when the property is changed through the binding.
+ \a value specifies an initialization value.
+*/
- Constructs a property that is tied to the provided \a binding expression. The
- first time the property value is read, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read. When the property value changes \a
- owner is notified via the Callback function.
+/*!
+ \class QObjectComputedProperty
+ \inmodule QtCore
+ \brief The QObjectComputedProperty class is a template class to help port old
+ properties to the bindable property system.
+ \since 6.0
+ \ingroup tools
+
+ QObjectComputedProperty is a read-only property which is recomputed on each read.
+ It does not store the computed value.
+ It is one of the Qt internal classes implementing \l {Qt Bindable Properties}.
+ QObjectComputedProperty is usually not used directly, instead an instance of it is created by
+ using the Q_OBJECT_COMPUTED_PROPERTY macro.
+
+ See the following example.
+
+ \snippet code/src_corelib_kernel_qproperty.cpp 5
+
+ The rules for getters in \l {Bindable Property Getters and Setters}
+ also apply for QObjectComputedProperty. Especially, the getter
+ should be trivial and only return the value of the QObjectComputedProperty object.
+ The callback given to the QObjectComputedProperty should usually be a private
+ method which is only called by the QObjectComputedProperty.
+
+ No setter is required or allowed, as QObjectComputedProperty is read-only.
+
+ To correctly participate in dependency handling, QObjectComputedProperty
+ has to know when its value, the result of the callback given to it, might
+ have changed. Whenever a bindable property used in the callback changes,
+ this happens automatically. If the result of the callback might change
+ because of a change in a value which is not a bindable property,
+ it is the developer's responsibility to call \c notify
+ on the QObjectComputedProperty object.
+ This will inform dependent properties about the potential change.
+
+ Note that calling \c notify might trigger change handlers in dependent
+ properties, which might in turn use the object the QObjectComputedProperty
+ is a member of. So \c notify must not be called when in a transitional
+ or invalid state.
+
+ QObjectComputedProperty is not suitable for use with a computation that depends
+ on any input that might change without notice, such as the contents of a file.
+
+ \sa Q_OBJECT_COMPUTED_PROPERTY, QProperty, QObjectBindableProperty,
+ {Qt's Property System}, {Qt Bindable Properties}
+*/
+
+/*!
+ \macro Q_OBJECT_COMPUTED_PROPERTY(containingClass, type, name, callback)
+ \since 6.0
+ \relates QObjectComputedProperty
+ \brief Declares a \l QObjectComputedProperty inside \a containingClass
+ of type \a type with name \a name. The argument \a callback specifies
+ a GETTER function to be called when the property is evaluated.
+
+ \sa QObjectBindableProperty, {Qt's Property System}, {Qt Bindable Properties}
+*/
+
+/*!
+ \fn template <typename Class, typename T, auto offset, auto Callback> QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty()
+
+ Constructs a property with a default constructed instance of T.
+*/
+
+/*!
+ \fn template <typename Class, typename T, auto offset, auto Callback> explicit QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(const T &initialValue)
+
+ Constructs a property with the provided \a initialValue.
*/
+/*!
+ \fn template <typename Class, typename T, auto offset, auto Callback> explicit QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(T &&initialValue)
+
+ Move-Constructs a property with the provided \a initialValue.
+*/
+
+/*!
+ \fn template <typename Class, typename T, auto offset, auto Callback> QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(Class *owner, const QPropertyBinding<T> &binding)
+
+ Constructs a property that is tied to the provided \a binding expression.
+ The property's value is set to the result of evaluating the new binding.
+ Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
+
+ When the property value changes, \a owner is notified via the Callback
+ function.
+*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QNotifiedProperty<T, Callback>::QNotifiedProperty(Class *owner, Functor &&f)
+ \fn template <typename Class, typename T, auto offset, auto Callback> QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(Class *owner, QPropertyBinding<T> &&binding)
- Constructs a property that is tied to the provided binding expression \a f. The
- first time the property value is read, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read. When the property value changes \a
+ Constructs a property that is tied to the provided \a binding expression.
+ The property's value is set to the result of evaluating the new binding.
+ Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
+
+ When the property value changes, \a
owner is notified via the Callback function.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::~QNotifiedProperty()
+ \fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(Functor &&f)
+
+ Constructs a property that is tied to the provided binding expression \a f.
+ The property's value is set to the result of evaluating the new binding.
+ Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
- Destroys the property.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> T QNotifiedProperty<T, Callback>::value() const
+ \fn template <typename Class, typename T, auto offset, auto Callback> QObjectBindableProperty<Class, T, offset, Callback>::~QObjectBindableProperty()
- Returns the value of the property. This may evaluate a binding expression that
- is tied to this property, before returning the value.
+ Destroys the property.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::operator T() const
+ \fn template <typename Class, typename T, auto offset, auto Callback> T QObjectBindableProperty<Class, T, offset, Callback>::value() const
Returns the value of the property. This may evaluate a binding expression that
is tied to this property, before returning the value.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> void QNotifiedProperty<T, Callback>::setValue(Class *owner, const T &newValue)
+ \fn template <typename Class, typename T, auto offset, auto Callback> void QObjectBindableProperty<Class, T, offset, Callback>::setValue(parameter_type newValue)
+ \fn template <typename Class, typename T, auto offset, auto Callback> void QObjectBindableProperty<Class, T, offset, Callback>::setValue(rvalue_ref newValue)
Assigns \a newValue to this property and removes the property's associated
binding, if present. If the property value changes as a result, calls the
@@ -824,72 +1776,72 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> void QNotifiedProperty<T, Callback>::setValue(Class *owner, T &&newValue)
- \overload
+ \fn template <typename Class, typename T, auto offset, auto Callback> void QObjectBindableProperty<Class, T, offset, Callback>::notify()
- Assigns \a newValue to this property and removes the property's associated
- binding, if present. If the property value changes as a result, calls the
- Callback function on \a owner.
+ Programmatically signals a change of the property. Any binding which depend on
+ it will be notified, and if the property has a signal, it will be emitted.
+
+ This can be useful in combination with setValueBypassingBindings to defer
+ signalling the change until a class invariant has been restored.
+
+ \note If this property has a binding (i.e. hasBinding() returns true), that
+ binding is not reevaluated when notify() is called. Any binding depending on
+ this property is still reevaluated as usual.
+
+ \sa Qt::beginPropertyUpdateGroup(), setValueBypassingBindings()
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::setBinding(Class *owner, const QPropertyBinding<T> &newBinding)
+ \fn template <typename Class, typename T, auto offset, auto Callback> QPropertyBinding<T> QObjectBindableProperty<Class, T, offset, Callback>::setBinding(const QPropertyBinding<T> &newBinding)
Associates the value of this property with the provided \a newBinding
- expression and returns the previously associated binding. The first time the
- property value is read, the binding is evaluated. Whenever a dependency of the
- binding changes, the binding will be re-evaluated the next time the value of
- this property is read. When the property value changes \a owner is notified
- via the Callback function.
+ expression and returns the previously associated binding.
+ The property's value is set to the result of evaluating the new binding. Whenever a dependency of
+ the binding changes, the binding will be re-evaluated,
+ and the property's value gets updated accordingly.
+ When the property value changes, the owner
+ is notified via the Callback function.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QPropertyBinding<T> QNotifiedProperty<T, Callback>::setBinding(Class *owner, Functor f)
+ \fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QPropertyBinding<T> QObjectBindableProperty<Class, T, offset, Callback>::setBinding(Functor f)
\overload
Associates the value of this property with the provided functor \a f and
- returns the previously associated binding. The first time the property value
- is read, the binding is evaluated by invoking the call operator () of \a f.
- Whenever a dependency of the binding changes, the binding will be re-evaluated
- the next time the value of this property is read. When the property value
- changes \a owner is notified via the Callback function.
-*/
+ returns the previously associated binding. The property's value is set to the
+ result of evaluating the new binding by invoking the call operator \c{()} of \a
+ f. Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
-/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::setBinding(Class *owner, QPropertyBinding<T> &&newBinding)
- \overload
+ When the property value changes, the owner is notified via the Callback
+ function.
- Associates the value of this property with the provided \a newBinding
- expression and returns the previously associated binding. The first time the
- property value is read, the binding is evaluated. Whenever a dependency of the
- binding changes, the binding will be re-evaluated the next time the value of
- this property is read. When the property value changes \a owner is notified
- via the Callback function.
+ \sa {Formulating a Property Binding}
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> bool QNotifiedProperty<T, Callback>::setBinding(Class *owner, const QUntypedPropertyBinding &newBinding)
+ \fn template <typename Class, typename T, auto offset, auto Callback> QPropertyBinding<T> bool QObjectBindableProperty<Class, T, offset, Callback>::setBinding(const QUntypedPropertyBinding &newBinding)
\overload
Associates the value of this property with the provided \a newBinding
- expression. The first time the property value is read, the binding is evaluated.
- Whenever a dependency of the binding changes, the binding will be re-evaluated
- the next time the value of this property is read. When the property value
- changes \a owner is notified via the Callback function.
+ expression. The property's value is set to the result of evaluating the new
+ binding. Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
- Returns true if the type of this property is the same as the type the binding
- function returns; false otherwise.
+
+ Returns \c true if the type of this property is the same as the type the
+ binding function returns; \c false otherwise.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> bool QNotifiedProperty<T, Callback>::hasBinding() const
+ \fn template <typename Class, typename T, auto offset, auto Callback> bool QObjectBindableProperty<Class, T, offset, Callback>::hasBinding() const
Returns true if the property is associated with a binding; false otherwise.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::binding() const
+ \fn template <typename Class, typename T, auto offset, auto Callback> QPropertyBinding<T> QObjectBindableProperty<Class, T, offset, Callback>::binding() const
Returns the binding expression that is associated with this property. A
default constructed QPropertyBinding<T> will be returned if no such
@@ -897,7 +1849,7 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::takeBinding()
+ \fn template <typename Class, typename T, auto offset, auto Callback> QPropertyBinding<T> QObjectBindableProperty<Class, T, offset, Callback>::takeBinding()
Disassociates the binding expression from this property and returns it. After
calling this function, the value of the property will only change if you
@@ -905,43 +1857,87 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QPropertyChangeHandler<T, Functor> QNotifiedProperty<T, Callback>::onValueChanged(Functor f)
+ \fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QPropertyChangeHandler<T, Functor> QObjectBindableProperty<Class, T, offset, Callback>::onValueChanged(Functor f)
Registers the given functor \a f as a callback that shall be called whenever
- the value of the property changes.
+ the value of the property changes. On each value change, the handler is either
+ called immediately, or deferred, depending on the context.
- The callback \a f is expected to be a type that has a plain call operator () without any
- parameters. This means that you can provide a C++ lambda expression, an std::function
- or even a custom struct with a call operator.
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
- The returned property change handler object keeps track of the registration. When it
- goes out of scope, the callback is de-registered.
+ The returned property change handler object keeps track of the registration.
+ When it goes out of scope, the callback is de-registered.
+*/
+
+/*!
+ \fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QPropertyChangeHandler<T, Functor> QObjectBindableProperty<Class, T, offset, Callback>::subscribe(Functor f)
+
+ Subscribes the given functor \a f as a callback that is called immediately and
+ whenever the value of the property changes in the future. On each value
+ change, the handler is either called immediately, or deferred, depending on
+ the context.
+
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
+
+ The returned property change handler object keeps track of the subscription.
+ When it goes out of scope, the callback is unsubscribed.
*/
/*!
- \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QPropertyChangeHandler<T, Functor> QNotifiedProperty<T, Callback>::subscribe(Functor f)
+ \fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QPropertyNotifier QObjectBindableProperty<Class, T, offset, Callback>::addNotifier(Functor f)
+
+ Subscribes the given functor \a f as a callback that is called whenever the
+ value of the property changes.
- Subscribes the given functor \a f as a callback that is called immediately and whenever
- the value of the property changes in the future.
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
- The callback \a f is expected to be a type that has a plain call operator () without any
- parameters. This means that you can provide a C++ lambda expression, an std::function
- or even a custom struct with a call operator.
+ The returned property change handler object keeps track of the subscription.
+ When it goes out of scope, the callback is unsubscribed.
+
+ This method is in some cases easier to use than onValueChanged(), as the
+ returned object is not a template. It can therefore more easily be stored,
+ e.g. as a member in a class.
+
+ \sa onValueChanged(), subscribe()
+*/
- The returned property change handler object keeps track of the subscription. When it
- goes out of scope, the callback is unsubscribed.
+/*!
+ \fn template <typename T> QtPrivate::QPropertyBase &QObjectBindableProperty<Class, T, offset, Callback>::propertyBase() const
+ \internal
*/
/*!
\class QPropertyChangeHandler
\inmodule QtCore
- \brief The QPropertyChangeHandler class controls the lifecycle of change callback installed on a QProperty.
+ \brief The QPropertyChangeHandler class controls the lifecycle of change
+ callback installed on a QProperty.
+
+ \ingroup tools
+
+ QPropertyChangeHandler\<Functor\> is created when registering a callback on a
+ QProperty to listen to changes to the property's value, using
+ QProperty::onValueChanged and QProperty::subscribe. As long as the change
+ handler is alive, the callback remains installed.
+
+ A handler instance can be transferred between C++ scopes using move semantics.
+*/
+
+/*!
+ \class QPropertyNotifier
+ \inmodule QtCore
+ \brief The QPropertyNotifier class controls the lifecycle of change callback installed on a QProperty.
\ingroup tools
- QPropertyChangeHandler\<PropertyType, Functor\> is created when registering a
- callback on a QProperty to listen to changes to the property's value, using QProperty::onValueChanged
- and QProperty::subscribe. As long as the change handler is alive, the callback remains installed.
+ QPropertyNotifier is created when registering a callback on a QProperty to
+ listen to changes to the property's value, using QProperty::addNotifier. As
+ long as the change handler is alive, the callback remains installed.
A handler instance can be transferred between C++ scopes using move semantics.
*/
@@ -949,7 +1945,10 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
/*!
\class QPropertyAlias
\inmodule QtCore
- \brief The QPropertyAlias class is a safe alias for a QProperty with same template parameter.
+ \internal
+
+ \brief The QPropertyAlias class is a safe alias for a QProperty with same
+ template parameter.
\ingroup tools
@@ -964,10 +1963,10 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
QPropertyAlias<QString> nameAlias(name);
QPropertyAlias<int> ageAlias(&age);
- QPropertyAlias<QString> fullname;
- fullname.setBinding([&]() { return nameAlias.value() + " age:" + QString::number(ageAlias.value()); });
+ QProperty<QString> fullname;
+ fullname.setBinding([&]() { return nameAlias.value() + " age: " + QString::number(ageAlias.value()); });
- qDebug() << fullname.value(); // Prints "Smith age: 41"
+ qDebug() << fullname.value(); // Prints "John age: 41"
*name = "Emma"; // Marks binding expression as dirty
@@ -1020,14 +2019,6 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
*/
/*!
- \fn template <typename T> void QPropertyAlias<T>::setValue(T &&newValue)
- \overload
-
- Assigns \a newValue to the aliased property and removes the property's
- associated binding, if present.
-*/
-
-/*!
\fn template <typename T> QPropertyAlias<T> &QPropertyAlias<T>::operator=(const T &newValue)
Assigns \a newValue to the aliased property and returns a reference to this
@@ -1035,48 +2026,14 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
*/
/*!
- \fn template <typename T> QPropertyAlias<T> &QPropertyAlias<T>::operator=(T &&newValue)
- \overload
-
- Assigns \a newValue to the aliased property and returns a reference to this
- QPropertyAlias.
-*/
-
-/*!
- \fn template <typename T> QPropertyAlias<T> &QPropertyAlias<T>::operator=(const QPropertyBinding<T> &newBinding)
- \overload
-
- Associates the value of the aliased property with the provided \a newBinding
- expression and returns a reference to this alias. The first time the
- property value is read, either from the property itself or from any alias, the
- binding is evaluated. Whenever a dependency of the binding changes, the
- binding will be re-evaluated the next time the value of this property is read.
-*/
-
-/*!
\fn template <typename T> QPropertyBinding<T> QPropertyAlias<T>::setBinding(const QPropertyBinding<T> &newBinding)
Associates the value of the aliased property with the provided \a newBinding
expression and returns any previous binding the associated with the aliased
- property. The first time the property value is read, either from the property
- itself or from any alias, the binding is evaluated. Whenever a dependency of
- the binding changes, the binding will be re-evaluated the next time the value
- of this property is read.
-
- Returns any previous binding associated with the property, or a
- default-constructed QPropertyBinding<T>.
-*/
-
-/*!
- \fn template <typename T> QPropertyBinding<T> QPropertyAlias<T>::setBinding(QPropertyBinding<T> &&newBinding)
- \overload
+ property.The property's value is set to the result of evaluating the new
+ binding. Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
- Associates the value of the aliased property with the provided \a newBinding
- expression and returns any previous binding the associated with the aliased
- property. The first time the property value is read, either from the property
- itself or from any alias, the binding is evaluated. Whenever a dependency of
- the binding changes, the binding will be re-evaluated the next time the value
- of this property is read.
Returns any previous binding associated with the property, or a
default-constructed QPropertyBinding<T>.
@@ -1087,27 +2044,29 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
\overload
Associates the value of the aliased property with the provided \a newBinding
- expression. The first time the property value is read, either from the
- property itself or from any alias, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read.
+ expression. The property's value is set to the result of evaluating the new
+ binding. Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
+
Returns true if the type of this property is the same as the type the binding
function returns; false otherwise.
*/
/*!
- \fn template <typename T> template <typename Functor> QPropertyBinding<T> setBinding(Functor f)
+ \fn template <typename T> template <typename Functor> QPropertyBinding<T> QPropertyAlias<T>::setBinding(Functor f)
\overload
Associates the value of the aliased property with the provided functor \a f
- expression. The first time the property value is read, either from the
- property itself or from any alias, the binding is evaluated. Whenever a
- dependency of the binding changes, the binding will be re-evaluated the next
- time the value of this property is read.
+ expression. The property's value is set to the result of evaluating the new
+ binding. Whenever a dependency of the binding changes, the binding will be
+ re-evaluated, and the property's value gets updated accordingly.
+
Returns any previous binding associated with the property, or a
default-constructed QPropertyBinding<T>.
+
+ \sa {Formulating a Property Binding}
*/
/*!
@@ -1137,11 +2096,12 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
\fn template <typename T> template <typename Functor> QPropertyChangeHandler<T, Functor> QPropertyAlias<T>::onValueChanged(Functor f)
Registers the given functor \a f as a callback that shall be called whenever
- the value of the aliased property changes.
+ the value of the aliased property changes. On each value change, the handler
+ is either called immediately, or deferred, depending on the context.
- The callback \a f is expected to be a type that has a plain call operator () without any
- parameters. This means that you can provide a C++ lambda expression, an std::function
- or even a custom struct with a call operator.
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
The returned property change handler object keeps track of the registration. When it
goes out of scope, the callback is de-registered.
@@ -1150,15 +2110,37 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
/*!
\fn template <typename T> template <typename Functor> QPropertyChangeHandler<T, Functor> QPropertyAlias<T>::subscribe(Functor f)
- Subscribes the given functor \a f as a callback that is called immediately and whenever
- the value of the aliased property changes in the future.
+ Subscribes the given functor \a f as a callback that is called immediately and
+ whenever the value of the aliased property changes in the future. On each
+ value change, the handler is either called immediately, or deferred, depending
+ on the context.
+
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
+
+ The returned property change handler object keeps track of the subscription.
+ When it goes out of scope, the callback is unsubscribed.
+*/
+
+/*!
+ \fn template <typename T> template <typename Functor> QPropertyNotifier QPropertyAlias<T>::addNotifier(Functor f)
+
+ Subscribes the given functor \a f as a callback that is called whenever
+ the value of the aliased property changes.
- The callback \a f is expected to be a type that has a plain call operator () without any
- parameters. This means that you can provide a C++ lambda expression, an std::function
- or even a custom struct with a call operator.
+ The callback \a f is expected to be a type that has a plain call operator
+ \c{()} without any parameters. This means that you can provide a C++ lambda
+ expression, a std::function or even a custom struct with a call operator.
- The returned property change handler object keeps track of the subscription. When it
- goes out of scope, the callback is unsubscribed.
+ The returned property change handler object keeps track of the subscription.
+ When it goes out of scope, the callback is unsubscribed.
+
+ This method is in some cases easier to use than onValueChanged(), as the
+ returned object is not a template. It can therefore more easily be stored,
+ e.g. as a member in a class.
+
+ \sa onValueChanged(), subscribe()
*/
/*!
@@ -1169,4 +2151,429 @@ QPropertyBindingSourceLocation QPropertyBindingError::location() const
If the aliased property doesn't exist, all other method calls are ignored.
*/
+struct QBindingStorageData
+{
+ size_t size = 0;
+ size_t used = 0;
+ // Pair[] pairs;
+};
+
+struct QBindingStoragePrivate
+{
+ // This class basically implements a simple and fast hash map to store bindings for a QObject
+ // The reason that we're not using QHash is that QPropertyBindingData can not be copied, only
+ // moved. That doesn't work well together with an implicitly shared class.
+ struct Pair
+ {
+ QUntypedPropertyData *data;
+ QPropertyBindingData bindingData;
+ };
+ static_assert(alignof(Pair) == alignof(void *));
+ static_assert(alignof(size_t) == alignof(void *));
+
+ QBindingStorageData *&d;
+
+ static inline Pair *pairs(QBindingStorageData *dd)
+ {
+ Q_ASSERT(dd);
+ return reinterpret_cast<Pair *>(dd + 1);
+ }
+ void reallocate(size_t newSize)
+ {
+ Q_ASSERT(!d || newSize > d->size);
+ size_t allocSize = sizeof(QBindingStorageData) + newSize*sizeof(Pair);
+ void *nd = malloc(allocSize);
+ memset(nd, 0, allocSize);
+ QBindingStorageData *newData = new (nd) QBindingStorageData;
+ newData->size = newSize;
+ if (!d) {
+ d = newData;
+ return;
+ }
+ newData->used = d->used;
+ Pair *p = pairs(d);
+ for (size_t i = 0; i < d->size; ++i, ++p) {
+ if (p->data) {
+ Pair *pp = pairs(newData);
+ Q_ASSERT(newData->size && (newData->size & (newData->size - 1)) == 0); // size is a power of two
+ size_t index = qHash(p->data) & (newData->size - 1);
+ while (pp[index].data) {
+ ++index;
+ if (index == newData->size)
+ index = 0;
+ }
+ new (pp + index) Pair{p->data, QPropertyBindingData(std::move(p->bindingData))};
+ }
+ }
+ // data has been moved, no need to call destructors on old Pairs
+ free(d);
+ d = newData;
+ }
+
+ QBindingStoragePrivate(QBindingStorageData *&_d) : d(_d) {}
+
+ QPropertyBindingData *get(const QUntypedPropertyData *data)
+ {
+ Q_ASSERT(d);
+ Q_ASSERT(d->size && (d->size & (d->size - 1)) == 0); // size is a power of two
+ size_t index = qHash(data) & (d->size - 1);
+ Pair *p = pairs(d);
+ while (p[index].data) {
+ if (p[index].data == data)
+ return &p[index].bindingData;
+ ++index;
+ if (index == d->size)
+ index = 0;
+ }
+ return nullptr;
+ }
+ QPropertyBindingData *get(QUntypedPropertyData *data, bool create)
+ {
+ if (!d) {
+ if (!create)
+ return nullptr;
+ reallocate(8);
+ }
+ else if (d->used*2 >= d->size)
+ reallocate(d->size*2);
+ Q_ASSERT(d->size && (d->size & (d->size - 1)) == 0); // size is a power of two
+ size_t index = qHash(data) & (d->size - 1);
+ Pair *p = pairs(d);
+ while (p[index].data) {
+ if (p[index].data == data)
+ return &p[index].bindingData;
+ ++index;
+ if (index == d->size)
+ index = 0;
+ }
+ if (!create)
+ return nullptr;
+ ++d->used;
+ new (p + index) Pair{data, QPropertyBindingData()};
+ return &p[index].bindingData;
+ }
+
+ void destroy()
+ {
+ if (!d)
+ return;
+ Pair *p = pairs(d);
+ for (size_t i = 0; i < d->size; ++i) {
+ if (p->data)
+ p->~Pair();
+ ++p;
+ }
+ free(d);
+ }
+};
+
+/*!
+ \class QBindingStorage
+ \internal
+
+ QBindingStorage acts as a storage for property binding related data in QObject.
+ Any property in a QObject can be made bindable by using the Q_OBJECT_BINDABLE_PROPERTY
+ macro to declare it. A setter and a getter for the property and a declaration using
+ Q_PROPERTY have to be made as usual.
+ Binding related data will automatically be stored within the QBindingStorage
+ inside the QObject.
+*/
+
+QBindingStorage::QBindingStorage()
+{
+ bindingStatus = &QT_PREPEND_NAMESPACE(bindingStatus);
+ Q_ASSERT(bindingStatus);
+}
+
+QBindingStorage::~QBindingStorage()
+{
+ QBindingStoragePrivate(d).destroy();
+}
+
+void QBindingStorage::reinitAfterThreadMove()
+{
+ bindingStatus = &QT_PREPEND_NAMESPACE(bindingStatus);
+ Q_ASSERT(bindingStatus);
+}
+
+void QBindingStorage::clear()
+{
+ QBindingStoragePrivate(d).destroy();
+ d = nullptr;
+ bindingStatus = nullptr;
+}
+
+void QBindingStorage::registerDependency_helper(const QUntypedPropertyData *data) const
+{
+ Q_ASSERT(bindingStatus);
+ // Use ::bindingStatus to get the binding from TLS. This is required, so that reads from
+ // another thread do not register as dependencies
+ QtPrivate::BindingEvaluationState *currentBinding;
+#ifdef QT_HAS_FAST_CURRENT_THREAD_ID
+ const bool threadMatches = (QThread::currentThreadId() == bindingStatus->threadId);
+ if (Q_LIKELY(threadMatches))
+ currentBinding = bindingStatus->currentlyEvaluatingBinding;
+ else
+ currentBinding = QT_PREPEND_NAMESPACE(bindingStatus).currentlyEvaluatingBinding;
+#else
+ currentBinding = QT_PREPEND_NAMESPACE(bindingStatus).currentlyEvaluatingBinding;
+#endif
+ QUntypedPropertyData *dd = const_cast<QUntypedPropertyData *>(data);
+ if (!currentBinding)
+ return;
+ auto storage = QBindingStoragePrivate(d).get(dd, true);
+ if (!storage)
+ return;
+ storage->registerWithCurrentlyEvaluatingBinding(currentBinding);
+}
+
+
+QPropertyBindingData *QBindingStorage::bindingData_helper(const QUntypedPropertyData *data) const
+{
+ return QBindingStoragePrivate(d).get(data);
+}
+
+const QBindingStatus *QBindingStorage::status(QtPrivate::QBindingStatusAccessToken) const
+{
+ return bindingStatus;
+}
+
+QPropertyBindingData *QBindingStorage::bindingData_helper(QUntypedPropertyData *data, bool create)
+{
+ return QBindingStoragePrivate(d).get(data, create);
+}
+
+
+namespace QtPrivate {
+
+
+void initBindingStatusThreadId()
+{
+ bindingStatus.threadId = QThread::currentThreadId();
+}
+
+BindingEvaluationState *suspendCurrentBindingStatus()
+{
+ auto ret = bindingStatus.currentlyEvaluatingBinding;
+ bindingStatus.currentlyEvaluatingBinding = nullptr;
+ return ret;
+}
+
+void restoreBindingStatus(BindingEvaluationState *status)
+{
+ bindingStatus.currentlyEvaluatingBinding = status;
+}
+
+/*!
+ \internal
+ This function can be used to detect whether we are currently
+ evaluating a binding. This can e.g. be used to defer the allocation
+ of extra data for a QPropertyBindingStorage in a getter.
+ Note that this function accesses TLS storage, and is therefore soemwhat
+ costly to call.
+*/
+bool isAnyBindingEvaluating()
+{
+ return bindingStatus.currentlyEvaluatingBinding != nullptr;
+}
+
+bool isPropertyInBindingWrapper(const QUntypedPropertyData *property)
+{
+ // Accessing bindingStatus is expensive because it's thread-local. Do it only once.
+ if (const auto current = bindingStatus.currentCompatProperty)
+ return current->property == property;
+ return false;
+}
+
+namespace BindableWarnings {
+
+void printUnsuitableBindableWarning(QAnyStringView prefix, BindableWarnings::Reason reason)
+{
+ switch (reason) {
+ case QtPrivate::BindableWarnings::NonBindableInterface:
+ qCWarning(lcQPropertyBinding).noquote() << prefix.toString()
+ << "The QBindable does not allow interaction with the binding.";
+ break;
+ case QtPrivate::BindableWarnings::ReadOnlyInterface:
+ qCWarning(lcQPropertyBinding).noquote() << prefix.toString()
+ << "The QBindable is read-only.";
+ break;
+ default:
+ case QtPrivate::BindableWarnings::InvalidInterface:
+ qCWarning(lcQPropertyBinding).noquote() << prefix.toString()
+ << "The QBindable is invalid.";
+ break;
+ }
+}
+
+void printMetaTypeMismatch(QMetaType actual, QMetaType expected)
+{
+ qCWarning(lcQPropertyBinding) << "setBinding: Could not set binding as the property expects it to be of type"
+ << actual.name()
+ << "but got" << expected.name() << "instead.";
+}
+
+} // namespace BindableWarnings end
+
+/*!
+ \internal
+ Returns the binding statusof the current thread.
+ */
+QBindingStatus* getBindingStatus(QtPrivate::QBindingStatusAccessToken) { return &QT_PREPEND_NAMESPACE(bindingStatus); }
+
+namespace PropertyAdaptorSlotObjectHelpers {
+void getter(const QUntypedPropertyData *d, void *value)
+{
+ auto adaptor = static_cast<const QtPrivate::QPropertyAdaptorSlotObject *>(d);
+ adaptor->bindingData().registerWithCurrentlyEvaluatingBinding();
+ auto mt = adaptor->metaProperty().metaType();
+ mt.destruct(value);
+ mt.construct(value, adaptor->metaProperty().read(adaptor->object()).data());
+}
+
+void setter(QUntypedPropertyData *d, const void *value)
+{
+ auto adaptor = static_cast<QtPrivate::QPropertyAdaptorSlotObject *>(d);
+ adaptor->bindingData().removeBinding();
+ adaptor->metaProperty().write(adaptor->object(),
+ QVariant(adaptor->metaProperty().metaType(), value));
+}
+
+QUntypedPropertyBinding getBinding(const QUntypedPropertyData *d)
+{
+ auto adaptor = static_cast<const QtPrivate::QPropertyAdaptorSlotObject *>(d);
+ return QUntypedPropertyBinding(adaptor->bindingData().binding());
+}
+
+bool bindingWrapper(QMetaType type, QUntypedPropertyData *d,
+ QtPrivate::QPropertyBindingFunction binding, QUntypedPropertyData *temp,
+ void *value)
+{
+ auto adaptor = static_cast<const QtPrivate::QPropertyAdaptorSlotObject *>(d);
+ type.destruct(value);
+ type.construct(value, adaptor->metaProperty().read(adaptor->object()).data());
+ if (binding.vtable->call(type, temp, binding.functor)) {
+ adaptor->metaProperty().write(adaptor->object(), QVariant(type, value));
+ return true;
+ }
+ return false;
+}
+
+QUntypedPropertyBinding setBinding(QUntypedPropertyData *d, const QUntypedPropertyBinding &binding,
+ QPropertyBindingWrapper wrapper)
+{
+ auto adaptor = static_cast<QPropertyAdaptorSlotObject *>(d);
+ return adaptor->bindingData().setBinding(binding, d, nullptr, wrapper);
+}
+
+void setObserver(const QUntypedPropertyData *d, QPropertyObserver *observer)
+{
+ observer->setSource(static_cast<const QPropertyAdaptorSlotObject *>(d)->bindingData());
+}
+}
+
+QPropertyAdaptorSlotObject::QPropertyAdaptorSlotObject(QObject *o, const QMetaProperty &p)
+ : QSlotObjectBase(&impl), obj(o), metaProperty_(p)
+{
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+void QPropertyAdaptorSlotObject::impl(int which, QSlotObjectBase *this_, QObject *r, void **a,
+ bool *ret)
+#else
+void QPropertyAdaptorSlotObject::impl(QSlotObjectBase *this_, QObject *r, void **a, int which,
+ bool *ret)
+#endif
+{
+ auto self = static_cast<QPropertyAdaptorSlotObject *>(this_);
+ switch (which) {
+ case Destroy:
+ delete self;
+ break;
+ case Call:
+ if (!self->bindingData_.hasBinding())
+ self->bindingData_.notifyObservers(self);
+ break;
+ case Compare:
+ case NumOperations:
+ Q_UNUSED(r);
+ Q_UNUSED(a);
+ Q_UNUSED(ret);
+ break;
+ }
+}
+
+} // namespace QtPrivate end
+
+QUntypedBindable::QUntypedBindable(QObject *obj, const QMetaProperty &metaProperty,
+ const QtPrivate::QBindableInterface *i)
+ : iface(i)
+{
+ if (!obj)
+ return;
+
+ if (!metaProperty.isValid()) {
+ qCWarning(lcQPropertyBinding) << "QUntypedBindable: Property is not valid";
+ return;
+ }
+
+ if (metaProperty.isBindable()) {
+ *this = metaProperty.bindable(obj);
+ return;
+ }
+
+ if (!metaProperty.hasNotifySignal()) {
+ qCWarning(lcQPropertyBinding)
+ << "QUntypedBindable: Property" << metaProperty.name() << "has no notify signal";
+ return;
+ }
+
+ auto metatype = iface->metaType();
+ if (metaProperty.metaType() != metatype) {
+ qCWarning(lcQPropertyBinding) << "QUntypedBindable: Property" << metaProperty.name()
+ << "of type" << metaProperty.metaType().name()
+ << "does not match requested type" << metatype.name();
+ return;
+ }
+
+ // Test for name pointer equality proves it's exactly the same property
+ if (obj->metaObject()->property(metaProperty.propertyIndex()).name() != metaProperty.name()) {
+ qCWarning(lcQPropertyBinding) << "QUntypedBindable: Property" << metaProperty.name()
+ << "does not belong to this object";
+ return;
+ }
+
+ // Get existing binding data if it exists
+ auto adaptor = QObjectPrivate::get(obj)->getPropertyAdaptorSlotObject(metaProperty);
+
+ if (!adaptor) {
+ adaptor = new QPropertyAdaptorSlotObject(obj, metaProperty);
+
+ auto c = QObjectPrivate::connect(obj, metaProperty.notifySignalIndex(), obj, adaptor,
+ Qt::DirectConnection);
+ Q_ASSERT(c);
+ }
+
+ data = adaptor;
+}
+
+QUntypedBindable::QUntypedBindable(QObject *obj, const char *property,
+ const QtPrivate::QBindableInterface *i)
+ : QUntypedBindable(
+ obj,
+ [=]() -> QMetaProperty {
+ if (!obj)
+ return {};
+ auto propertyIndex = obj->metaObject()->indexOfProperty(property);
+ if (propertyIndex < 0) {
+ qCWarning(lcQPropertyBinding)
+ << "QUntypedBindable: No property named" << property;
+ return {};
+ }
+ return obj->metaObject()->property(propertyIndex);
+ }(),
+ i)
+{
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index de08a71349..0373867a66 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -1,69 +1,96 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROPERTY_H
#define QPROPERTY_H
#include <QtCore/qglobal.h>
-#include <QtCore/QSharedDataPointer>
-#include <QtCore/QString>
-#include <QtCore/qmetatype.h>
-#include <functional>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qbindingstorage.h>
+
#include <type_traits>
-#include <variant>
#include <QtCore/qpropertyprivate.h>
-#if __has_include(<source_location>) && __cplusplus >= 202002L && !defined(Q_CLANG_QDOC)
-#include <experimental/source_location>
+#if __has_include(<source_location>) && __cplusplus >= 202002L && !defined(Q_QDOC)
+#include <source_location>
+#if defined(__cpp_lib_source_location)
+#define QT_SOURCE_LOCATION_NAMESPACE std
#define QT_PROPERTY_COLLECT_BINDING_LOCATION
-#define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::source_location::current())
-#elif __has_include(<experimental/source_location>) && __cplusplus >= 201703L && !defined(Q_CLANG_QDOC)
+#if defined(Q_CC_MSVC)
+/* MSVC runs into an issue with constexpr with source location (error C7595)
+ so use the factory function as a workaround */
+# define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation::fromStdSourceLocation(std::source_location::current())
+#else
+/* some versions of gcc in turn run into
+ expression ‘std::source_location::current()’ is not a constant expression
+ so don't use the workaround there */
+# define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::source_location::current())
+#endif
+#endif
+#endif
+
+#if __has_include(<experimental/source_location>) && !defined(Q_QDOC)
#include <experimental/source_location>
+#if !defined(QT_PROPERTY_COLLECT_BINDING_LOCATION)
+#if defined(__cpp_lib_experimental_source_location)
+#define QT_SOURCE_LOCATION_NAMESPACE std::experimental
#define QT_PROPERTY_COLLECT_BINDING_LOCATION
#define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::experimental::source_location::current())
-#else
+#endif // defined(__cpp_lib_experimental_source_location)
+#endif
+#endif
+
+#if !defined(QT_PROPERTY_COLLECT_BINDING_LOCATION)
#define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation()
#endif
QT_BEGIN_NAMESPACE
+namespace Qt {
+Q_CORE_EXPORT void beginPropertyUpdateGroup();
+Q_CORE_EXPORT void endPropertyUpdateGroup();
+}
+
+class QScopedPropertyUpdateGroup
+{
+ Q_DISABLE_COPY_MOVE(QScopedPropertyUpdateGroup)
+public:
+ Q_NODISCARD_CTOR
+ QScopedPropertyUpdateGroup()
+ { Qt::beginPropertyUpdateGroup(); }
+ ~QScopedPropertyUpdateGroup() noexcept(false)
+ { Qt::endPropertyUpdateGroup(); }
+};
+
+template <typename T>
+class QPropertyData : public QUntypedPropertyData
+{
+protected:
+ mutable T val = T();
+private:
+ class DisableRValueRefs {};
+protected:
+ static constexpr bool UseReferences = !(std::is_arithmetic_v<T> || std::is_enum_v<T> || std::is_pointer_v<T>);
+public:
+ using value_type = T;
+ using parameter_type = std::conditional_t<UseReferences, const T &, T>;
+ using rvalue_ref = typename std::conditional_t<UseReferences, T &&, DisableRValueRefs>;
+ using arrow_operator_result = std::conditional_t<std::is_pointer_v<T>, const T &,
+ std::conditional_t<QTypeTraits::is_dereferenceable_v<T>, const T &, void>>;
+
+ QPropertyData() = default;
+ QPropertyData(parameter_type t) : val(t) {}
+ QPropertyData(rvalue_ref t) : val(std::move(t)) {}
+ ~QPropertyData() = default;
+
+ parameter_type valueBypassingBindings() const { return val; }
+ void setValueBypassingBindings(parameter_type v) { val = v; }
+ void setValueBypassingBindings(rvalue_ref v) { val = std::move(v); }
+};
+
+// ### Qt 7: un-export
struct Q_CORE_EXPORT QPropertyBindingSourceLocation
{
const char *fileName = nullptr;
@@ -71,8 +98,23 @@ struct Q_CORE_EXPORT QPropertyBindingSourceLocation
quint32 line = 0;
quint32 column = 0;
QPropertyBindingSourceLocation() = default;
-#ifdef QT_PROPERTY_COLLECT_BINDING_LOCATION
- QPropertyBindingSourceLocation(const std::experimental::source_location &cppLocation)
+#ifdef __cpp_lib_source_location
+ constexpr QPropertyBindingSourceLocation(const std::source_location &cppLocation)
+ {
+ fileName = cppLocation.file_name();
+ functionName = cppLocation.function_name();
+ line = cppLocation.line();
+ column = cppLocation.column();
+ }
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static consteval QPropertyBindingSourceLocation
+ fromStdSourceLocation(const std::source_location &cppLocation)
+ {
+ return cppLocation;
+ }
+#endif
+#ifdef __cpp_lib_experimental_source_location
+ constexpr QPropertyBindingSourceLocation(const std::experimental::source_location &cppLocation)
{
fileName = cppLocation.file_name();
functionName = cppLocation.function_name();
@@ -83,10 +125,6 @@ struct Q_CORE_EXPORT QPropertyBindingSourceLocation
};
template <typename Functor> class QPropertyChangeHandler;
-
-template <typename T> class QProperty;
-template <typename T, auto callbackMember, auto guardCallback> class QNotifiedProperty;
-
class QPropertyBindingErrorPrivate;
class Q_CORE_EXPORT QPropertyBindingError
@@ -99,17 +137,18 @@ public:
UnknownError
};
- QPropertyBindingError(Type type = NoError);
+ QPropertyBindingError();
+ QPropertyBindingError(Type type, const QString &description = QString());
+
QPropertyBindingError(const QPropertyBindingError &other);
QPropertyBindingError &operator=(const QPropertyBindingError &other);
QPropertyBindingError(QPropertyBindingError &&other);
QPropertyBindingError &operator=(QPropertyBindingError &&other);
~QPropertyBindingError();
+ bool hasError() const { return d.get() != nullptr; }
Type type() const;
- void setDescription(const QString &description);
QString description() const;
- QPropertyBindingSourceLocation location() const;
private:
QSharedDataPointer<QPropertyBindingErrorPrivate> d;
@@ -118,12 +157,17 @@ private:
class Q_CORE_EXPORT QUntypedPropertyBinding
{
public:
- using BindingEvaluationResult = QPropertyBindingError;
// writes binding result into dataPtr
- using BindingEvaluationFunction = std::function<BindingEvaluationResult(const QMetaType &metaType, void *dataPtr)>;
+ using BindingFunctionVTable = QtPrivate::BindingFunctionVTable;
QUntypedPropertyBinding();
- QUntypedPropertyBinding(const QMetaType &metaType, BindingEvaluationFunction function, const QPropertyBindingSourceLocation &location);
+ QUntypedPropertyBinding(QMetaType metaType, const BindingFunctionVTable *vtable, void *function, const QPropertyBindingSourceLocation &location);
+
+ template<typename Functor>
+ QUntypedPropertyBinding(QMetaType metaType, Functor &&f, const QPropertyBindingSourceLocation &location)
+ : QUntypedPropertyBinding(metaType, &QtPrivate::bindingFunctionVTable<std::remove_reference_t<Functor>>, &f, location)
+ {}
+
QUntypedPropertyBinding(QUntypedPropertyBinding &&other);
QUntypedPropertyBinding(const QUntypedPropertyBinding &other);
QUntypedPropertyBinding &operator=(const QUntypedPropertyBinding &other);
@@ -138,7 +182,7 @@ public:
explicit QUntypedPropertyBinding(QPropertyBindingPrivate *priv);
private:
- friend class QtPrivate::QPropertyBase;
+ friend class QtPrivate::QPropertyBindingData;
friend class QPropertyBindingPrivate;
template <typename> friend class QPropertyBinding;
QPropertyBindingPrivatePtr d;
@@ -147,42 +191,15 @@ private:
template <typename PropertyType>
class QPropertyBinding : public QUntypedPropertyBinding
{
- template <typename Functor>
- struct BindingAdaptor
- {
- Functor impl;
- QUntypedPropertyBinding::BindingEvaluationResult operator()(const QMetaType &/*metaType*/, void *dataPtr)
- {
- std::variant<PropertyType, QPropertyBindingError> result(impl());
- if (auto errorPtr = std::get_if<QPropertyBindingError>(&result))
- return *errorPtr;
-
- if (auto valuePtr = std::get_if<PropertyType>(&result)) {
- PropertyType *propertyPtr = reinterpret_cast<PropertyType *>(dataPtr);
- *propertyPtr = std::move(*valuePtr);
- return {};
- }
-
- return {};
- }
- };
public:
QPropertyBinding() = default;
template<typename Functor>
QPropertyBinding(Functor &&f, const QPropertyBindingSourceLocation &location)
- : QUntypedPropertyBinding(QMetaType::fromType<PropertyType>(), BindingAdaptor<Functor>{std::forward<Functor>(f)}, location)
- {}
-
- QPropertyBinding(const QProperty<PropertyType> &property)
- : QUntypedPropertyBinding(property.d.priv.binding())
+ : QUntypedPropertyBinding(QMetaType::fromType<PropertyType>(), &QtPrivate::bindingFunctionVTable<std::remove_reference_t<Functor>, PropertyType>, &f, location)
{}
- template<auto notifier, auto guard>
- QPropertyBinding(const QNotifiedProperty<PropertyType, notifier, guard> &property)
- : QUntypedPropertyBinding(property.d.priv.binding())
- {}
// Internal
explicit QPropertyBinding(const QUntypedPropertyBinding &binding)
@@ -190,51 +207,174 @@ public:
{}
};
-namespace QtPrivate {
- template<typename... Ts>
- constexpr auto is_variant_v = false;
- template<typename... Ts>
- constexpr auto is_variant_v<std::variant<Ts...>> = true;
-}
-
namespace Qt {
template <typename Functor>
auto makePropertyBinding(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
- std::enable_if_t<std::is_invocable_v<Functor>> * = 0)
+ std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
{
- if constexpr (QtPrivate::is_variant_v<std::invoke_result_t<Functor>>) {
- return QPropertyBinding<std::variant_alternative_t<0, std::invoke_result_t<Functor>>>(std::forward<Functor>(f), location);
- } else {
- return QPropertyBinding<std::invoke_result_t<Functor>>(std::forward<Functor>(f), location);
- }
- // Work around bogus warning
- Q_UNUSED(QtPrivate::is_variant_v<bool>)
+ return QPropertyBinding<std::invoke_result_t<Functor>>(std::forward<Functor>(f), location);
}
}
-struct QPropertyBasePointer;
+struct QPropertyObserverPrivate;
+struct QPropertyObserverPointer;
+class QPropertyObserver;
+
+class QPropertyObserverBase
+{
+public:
+ // Internal
+ enum ObserverTag {
+ ObserverNotifiesBinding, // observer was installed to notify bindings that obsverved property changed
+ ObserverNotifiesChangeHandler, // observer is a change handler, which runs on every change
+ ObserverIsPlaceholder, // the observer before this one is currently evaluated in QPropertyObserver::notifyObservers.
+#if QT_DEPRECATED_SINCE(6, 6)
+ ObserverIsAlias QT_DEPRECATED_VERSION_X_6_6("Use QProperty and add a binding to the target.")
+#endif
+ };
+protected:
+ using ChangeHandler = void (*)(QPropertyObserver*, QUntypedPropertyData *);
+
+private:
+ friend struct QPropertyDelayedNotifications;
+ friend struct QPropertyObserverNodeProtector;
+ friend class QPropertyObserver;
+ friend struct QPropertyObserverPointer;
+ friend struct QPropertyBindingDataPointer;
+ friend class QPropertyBindingPrivate;
+
+ QTaggedPointer<QPropertyObserver, ObserverTag> next;
+ // prev is a pointer to the "next" element within the previous node, or to the "firstObserverPtr" if it is the
+ // first node.
+ QtPrivate::QTagPreservingPointerToPointer<QPropertyObserver, ObserverTag> prev;
+
+ union {
+ QPropertyBindingPrivate *binding = nullptr;
+ ChangeHandler changeHandler;
+ QUntypedPropertyData *aliasData;
+ };
+};
+
+class Q_CORE_EXPORT QPropertyObserver : public QPropertyObserverBase
+{
+public:
+ constexpr QPropertyObserver() = default;
+ QPropertyObserver(QPropertyObserver &&other) noexcept;
+ QPropertyObserver &operator=(QPropertyObserver &&other) noexcept;
+ ~QPropertyObserver();
+
+ template <typename Property, QtPrivate::IsUntypedPropertyData<Property> = true>
+ void setSource(const Property &property)
+ { setSource(property.bindingData()); }
+ void setSource(const QtPrivate::QPropertyBindingData &property);
+
+protected:
+ QPropertyObserver(ChangeHandler changeHandler);
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("This constructor was only meant for internal use. Use QProperty and add a binding to the target.")
+ QPropertyObserver(QUntypedPropertyData *aliasedPropertyPtr);
+#endif
+
+ QUntypedPropertyData *aliasedProperty() const
+ {
+ return aliasData;
+ }
+
+private:
+
+ QPropertyObserver(const QPropertyObserver &) = delete;
+ QPropertyObserver &operator=(const QPropertyObserver &) = delete;
+
+};
+
+template <typename Functor>
+class QPropertyChangeHandler : public QPropertyObserver
+{
+ Functor m_handler;
+public:
+ Q_NODISCARD_CTOR
+ QPropertyChangeHandler(Functor handler)
+ : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) {
+ auto This = static_cast<QPropertyChangeHandler<Functor>*>(self);
+ This->m_handler();
+ })
+ , m_handler(handler)
+ {
+ }
+
+ template <typename Property, QtPrivate::IsUntypedPropertyData<Property> = true>
+ Q_NODISCARD_CTOR
+ QPropertyChangeHandler(const Property &property, Functor handler)
+ : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) {
+ auto This = static_cast<QPropertyChangeHandler<Functor>*>(self);
+ This->m_handler();
+ })
+ , m_handler(handler)
+ {
+ setSource(property);
+ }
+};
+
+class QPropertyNotifier : public QPropertyObserver
+{
+ std::function<void()> m_handler;
+public:
+ Q_NODISCARD_CTOR
+ QPropertyNotifier() = default;
+ template<typename Functor>
+ Q_NODISCARD_CTOR
+ QPropertyNotifier(Functor handler)
+ : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) {
+ auto This = static_cast<QPropertyNotifier *>(self);
+ This->m_handler();
+ })
+ , m_handler(handler)
+ {
+ }
+
+ template <typename Functor, typename Property,
+ QtPrivate::IsUntypedPropertyData<Property> = true>
+ Q_NODISCARD_CTOR
+ QPropertyNotifier(const Property &property, Functor handler)
+ : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) {
+ auto This = static_cast<QPropertyNotifier *>(self);
+ This->m_handler();
+ })
+ , m_handler(handler)
+ {
+ setSource(property);
+ }
+};
template <typename T>
-class QProperty
+class QProperty : public QPropertyData<T>
{
+ QtPrivate::QPropertyBindingData d;
+ bool is_equal(const T &v)
+ {
+ if constexpr (QTypeTraits::has_operator_equal_v<T>) {
+ if (v == this->val)
+ return true;
+ }
+ return false;
+ }
+
public:
- using value_type = T;
+ using value_type = typename QPropertyData<T>::value_type;
+ using parameter_type = typename QPropertyData<T>::parameter_type;
+ using rvalue_ref = typename QPropertyData<T>::rvalue_ref;
+ using arrow_operator_result = typename QPropertyData<T>::arrow_operator_result;
QProperty() = default;
- explicit QProperty(const T &initialValue) : d(initialValue) {}
- explicit QProperty(T &&initialValue) : d(std::move(initialValue)) {}
- QProperty(QProperty &&other) : d(std::move(other.d)) { notify(); }
- QProperty &operator=(QProperty &&other) { d = std::move(other.d); notify(); return *this; }
- QProperty(const QPropertyBinding<T> &binding)
+ explicit QProperty(parameter_type initialValue) : QPropertyData<T>(initialValue) {}
+ explicit QProperty(rvalue_ref initialValue) : QPropertyData<T>(std::move(initialValue)) {}
+ explicit QProperty(const QPropertyBinding<T> &binding)
: QProperty()
- { operator=(binding); }
- QProperty(QPropertyBinding<T> &&binding)
- : QProperty()
- { operator=(std::move(binding)); }
-#ifndef Q_CLANG_QDOC
+ { setBinding(binding); }
+#ifndef Q_QDOC
template <typename Functor>
explicit QProperty(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
- typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = 0)
+ typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = nullptr)
: QProperty(QPropertyBinding<T>(std::forward<Functor>(f), location))
{}
#else
@@ -243,82 +383,78 @@ public:
#endif
~QProperty() = default;
- T value() const
+ parameter_type value() const
{
- if (d.priv.hasBinding())
- d.priv.evaluateIfDirty();
- d.priv.registerWithCurrentlyEvaluatingBinding();
- return d.getValue();
+ d.registerWithCurrentlyEvaluatingBinding();
+ return this->val;
}
- operator T() const
+ arrow_operator_result operator->() const
{
- return value();
+ if constexpr (QTypeTraits::is_dereferenceable_v<T>) {
+ return value();
+ } else if constexpr (std::is_pointer_v<T>) {
+ value();
+ return this->val;
+ } else {
+ return;
+ }
}
- void setValue(T &&newValue)
+ parameter_type operator*() const
{
- d.priv.removeBinding();
- if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
- notify();
+ return value();
}
- void setValue(const T &newValue)
+ operator parameter_type() const
{
- d.priv.removeBinding();
- if (d.setValueAndReturnTrueIfChanged(newValue))
- notify();
+ return value();
}
- QProperty<T> &operator=(T &&newValue)
+ void setValue(rvalue_ref newValue)
{
- setValue(std::move(newValue));
- return *this;
+ d.removeBinding();
+ if (is_equal(newValue))
+ return;
+ this->val = std::move(newValue);
+ notify();
}
- QProperty<T> &operator=(const T &newValue)
+ void setValue(parameter_type newValue)
{
- setValue(newValue);
- return *this;
+ d.removeBinding();
+ if (is_equal(newValue))
+ return;
+ this->val = newValue;
+ notify();
}
- QProperty<T> &operator=(const QPropertyBinding<T> &newBinding)
+ QProperty<T> &operator=(rvalue_ref newValue)
{
- setBinding(newBinding);
+ setValue(std::move(newValue));
return *this;
}
- QProperty<T> &operator=(QPropertyBinding<T> &&newBinding)
+ QProperty<T> &operator=(parameter_type newValue)
{
- setBinding(std::move(newBinding));
+ setValue(newValue);
return *this;
}
QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding)
{
- QPropertyBinding<T> oldBinding(d.priv.setBinding(newBinding, &d));
- notify();
- return oldBinding;
- }
-
- QPropertyBinding<T> setBinding(QPropertyBinding<T> &&newBinding)
- {
- QPropertyBinding<T> b(std::move(newBinding));
- QPropertyBinding<T> oldBinding(d.priv.setBinding(b, &d));
- notify();
- return oldBinding;
+ return QPropertyBinding<T>(d.setBinding(newBinding, this));
}
bool setBinding(const QUntypedPropertyBinding &newBinding)
{
- if (newBinding.valueMetaType().id() != qMetaTypeId<T>())
+ if (!newBinding.isNull() && newBinding.valueMetaType().id() != qMetaTypeId<T>())
return false;
- d.priv.setBinding(newBinding, &d);
- notify();
+ setBinding(static_cast<const QPropertyBinding<T> &>(newBinding));
return true;
}
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
template <typename Functor>
QPropertyBinding<T> setBinding(Functor &&f,
const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
@@ -331,37 +467,48 @@ public:
QPropertyBinding<T> setBinding(Functor f);
#endif
- bool hasBinding() const { return d.priv.hasBinding(); }
+ bool hasBinding() const { return d.hasBinding(); }
QPropertyBinding<T> binding() const
{
- return QPropertyBinding<T>(*this);
+ return QPropertyBinding<T>(QUntypedPropertyBinding(d.binding()));
}
QPropertyBinding<T> takeBinding()
{
- return QPropertyBinding<T>(d.priv.setBinding(QUntypedPropertyBinding(), &d));
+ return QPropertyBinding<T>(d.setBinding(QUntypedPropertyBinding(), this));
}
template<typename Functor>
- QPropertyChangeHandler<Functor> onValueChanged(Functor f);
+ QPropertyChangeHandler<Functor> onValueChanged(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyChangeHandler<Functor>(*this, f);
+ }
+
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> subscribe(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ f();
+ return onValueChanged(f);
+ }
+
template<typename Functor>
- QPropertyChangeHandler<Functor> subscribe(Functor f);
+ QPropertyNotifier addNotifier(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyNotifier(*this, f);
+ }
+ const QtPrivate::QPropertyBindingData &bindingData() const { return d; }
private:
void notify()
{
- d.priv.notifyObservers(&d);
+ d.notifyObservers(this);
}
- Q_DISABLE_COPY(QProperty)
-
- friend struct QPropertyBasePointer;
- friend class QPropertyBinding<T>;
- friend class QPropertyObserver;
- // Mutable because querying for the value may require evalating the binding expression, calling
- // non-const functions on QPropertyBase.
- mutable QtPrivate::QPropertyValueStorage<T> d;
+ Q_DISABLE_COPY_MOVE(QProperty)
};
namespace Qt {
@@ -374,448 +521,635 @@ namespace Qt {
}
}
-namespace detail {
- template <typename F>
- struct ExtractClassFromFunctionPointer;
- template<typename T, typename C>
- struct ExtractClassFromFunctionPointer<T C::*> { using Class = C; };
-}
+namespace QtPrivate
+{
-template <typename T, auto Callback, auto ValueGuard=nullptr>
-class QNotifiedProperty
+struct QBindableInterface
{
+ using Getter = void (*)(const QUntypedPropertyData *d, void *value);
+ using Setter = void (*)(QUntypedPropertyData *d, const void *value);
+ using BindingGetter = QUntypedPropertyBinding (*)(const QUntypedPropertyData *d);
+ using BindingSetter = QUntypedPropertyBinding (*)(QUntypedPropertyData *d, const QUntypedPropertyBinding &binding);
+ using MakeBinding = QUntypedPropertyBinding (*)(const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location);
+ using SetObserver = void (*)(const QUntypedPropertyData *d, QPropertyObserver *observer);
+ using GetMetaType = QMetaType (*)();
+ Getter getter;
+ Setter setter;
+ BindingGetter getBinding;
+ BindingSetter setBinding;
+ MakeBinding makeBinding;
+ SetObserver setObserver;
+ GetMetaType metaType;
+
+ static constexpr quintptr MetaTypeAccessorFlag = 0x1;
+};
+
+template<typename Property, typename = void>
+class QBindableInterfaceForProperty
+{
+ using T = typename Property::value_type;
public:
- using value_type = T;
- using Class = typename detail::ExtractClassFromFunctionPointer<decltype(Callback)>::Class;
-private:
- static bool constexpr ValueGuardModifiesArgument = std::is_invocable_r_v<bool, decltype(ValueGuard), Class, T&>;
- static bool constexpr CallbackAcceptsOldValue = std::is_invocable_v<decltype(Callback), Class, T>;
- static bool constexpr HasValueGuard = !std::is_same_v<decltype(ValueGuard), std::nullptr_t>;
+ // interface for computed properties. Those do not have a binding()/setBinding() method, but one can
+ // install observers on them.
+ static constexpr QBindableInterface iface = {
+ [](const QUntypedPropertyData *d, void *value) -> void
+ { *static_cast<T*>(value) = static_cast<const Property *>(d)->value(); },
+ nullptr,
+ nullptr,
+ nullptr,
+ [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
+ { return Qt::makePropertyBinding([d]() -> T { return static_cast<const Property *>(d)->value(); }, location); },
+ [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
+ { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
+ []() { return QMetaType::fromType<T>(); }
+ };
+};
+
+template<typename Property>
+class QBindableInterfaceForProperty<const Property, std::void_t<decltype(std::declval<Property>().binding())>>
+{
+ using T = typename Property::value_type;
public:
- static_assert(CallbackAcceptsOldValue || std::is_invocable_v<decltype(Callback), Class>);
- static_assert(
- std::is_invocable_r_v<bool, decltype(ValueGuard), Class, T> ||
- ValueGuardModifiesArgument ||
- !HasValueGuard,
- "Guard has wrong signature");
-private:
- // type erased guard functions, casts its arguments to the correct types
- static constexpr bool (*GuardTEHelper)(void *, void*) = [](void *o, void *newValue){
- if constexpr (HasValueGuard) { // Guard->* is invalid if Guard == nullptr
- return (reinterpret_cast<Class *>(o)->*(ValueGuard))(*static_cast<T *>(newValue));
- } else {
- Q_UNUSED(o); // some compilers complain about unused variables
- Q_UNUSED(newValue);
- return true;
- }
+ // A bindable created from a const property results in a read-only interface, too.
+ static constexpr QBindableInterface iface = {
+
+ [](const QUntypedPropertyData *d, void *value) -> void
+ { *static_cast<T*>(value) = static_cast<const Property *>(d)->value(); },
+ /*setter=*/nullptr,
+ [](const QUntypedPropertyData *d) -> QUntypedPropertyBinding
+ { return static_cast<const Property *>(d)->binding(); },
+ /*setBinding=*/nullptr,
+ [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
+ { return Qt::makePropertyBinding([d]() -> T { return static_cast<const Property *>(d)->value(); }, location); },
+ [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
+ { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
+ []() { return QMetaType::fromType<T>(); }
};
- static constexpr bool(*GuardTE)(void *, void*) = HasValueGuard ? GuardTEHelper : nullptr;
+};
+
+template<typename Property>
+class QBindableInterfaceForProperty<Property, std::void_t<decltype(std::declval<Property>().binding())>>
+{
+ using T = typename Property::value_type;
public:
+ static constexpr QBindableInterface iface = {
+ [](const QUntypedPropertyData *d, void *value) -> void
+ { *static_cast<T*>(value) = static_cast<const Property *>(d)->value(); },
+ [](QUntypedPropertyData *d, const void *value) -> void
+ { static_cast<Property *>(d)->setValue(*static_cast<const T*>(value)); },
+ [](const QUntypedPropertyData *d) -> QUntypedPropertyBinding
+ { return static_cast<const Property *>(d)->binding(); },
+ [](QUntypedPropertyData *d, const QUntypedPropertyBinding &binding) -> QUntypedPropertyBinding
+ { return static_cast<Property *>(d)->setBinding(static_cast<const QPropertyBinding<T> &>(binding)); },
+ [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
+ { return Qt::makePropertyBinding([d]() -> T { return static_cast<const Property *>(d)->value(); }, location); },
+ [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
+ { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
+ []() { return QMetaType::fromType<T>(); }
+ };
+};
- QNotifiedProperty() = default;
+}
- explicit QNotifiedProperty(const T &initialValue) : d(initialValue) {}
- explicit QNotifiedProperty(T &&initialValue) : d(std::move(initialValue)) {}
+namespace QtPrivate {
+// used in Q(Untyped)Bindable to print warnings about various binding errors
+namespace BindableWarnings {
+enum Reason { InvalidInterface, NonBindableInterface, ReadOnlyInterface };
+Q_CORE_EXPORT void printUnsuitableBindableWarning(QAnyStringView prefix, Reason reason);
+Q_CORE_EXPORT void printMetaTypeMismatch(QMetaType actual, QMetaType expected);
+}
- QNotifiedProperty(Class *owner, const QPropertyBinding<T> &binding)
- : QNotifiedProperty()
- { setBinding(owner, binding); }
- QNotifiedProperty(Class *owner, QPropertyBinding<T> &&binding)
- : QNotifiedProperty()
- { setBinding(owner, std::move(binding)); }
+namespace PropertyAdaptorSlotObjectHelpers {
+Q_CORE_EXPORT void getter(const QUntypedPropertyData *d, void *value);
+Q_CORE_EXPORT void setter(QUntypedPropertyData *d, const void *value);
+Q_CORE_EXPORT QUntypedPropertyBinding getBinding(const QUntypedPropertyData *d);
+Q_CORE_EXPORT bool bindingWrapper(QMetaType type, QUntypedPropertyData *d,
+ QtPrivate::QPropertyBindingFunction binding,
+ QUntypedPropertyData *temp, void *value);
+Q_CORE_EXPORT QUntypedPropertyBinding setBinding(QUntypedPropertyData *d,
+ const QUntypedPropertyBinding &binding,
+ QPropertyBindingWrapper wrapper);
+Q_CORE_EXPORT void setObserver(const QUntypedPropertyData *d, QPropertyObserver *observer);
-#ifndef Q_CLANG_QDOC
- template <typename Functor>
- explicit QNotifiedProperty(Class *owner, Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
- typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = 0)
- : QNotifiedProperty(QPropertyBinding<T>(owner, std::forward<Functor>(f), location))
+template<typename T>
+bool bindingWrapper(QMetaType type, QUntypedPropertyData *d,
+ QtPrivate::QPropertyBindingFunction binding)
+{
+ struct Data : QPropertyData<T>
+ {
+ void *data() { return &this->val; }
+ } temp;
+ return bindingWrapper(type, d, binding, &temp, temp.data());
+}
+
+template<typename T>
+QUntypedPropertyBinding setBinding(QUntypedPropertyData *d, const QUntypedPropertyBinding &binding)
+{
+ return setBinding(d, binding, &bindingWrapper<T>);
+}
+
+template<typename T>
+QUntypedPropertyBinding makeBinding(const QUntypedPropertyData *d,
+ const QPropertyBindingSourceLocation &location)
+{
+ return Qt::makePropertyBinding(
+ [d]() -> T {
+ T r;
+ getter(d, &r);
+ return r;
+ },
+ location);
+}
+
+template<class T>
+inline constexpr QBindableInterface iface = {
+ &getter,
+ &setter,
+ &getBinding,
+ &setBinding<T>,
+ &makeBinding<T>,
+ &setObserver,
+ &QMetaType::fromType<T>,
+};
+}
+}
+
+class QUntypedBindable
+{
+ friend struct QUntypedBindablePrivate; // allows access to internal data
+protected:
+ QUntypedPropertyData *data = nullptr;
+ const QtPrivate::QBindableInterface *iface = nullptr;
+ constexpr QUntypedBindable(QUntypedPropertyData *d, const QtPrivate::QBindableInterface *i)
+ : data(d), iface(i)
{}
-#else
- template <typename Functor>
- explicit QProperty(Class *owner, Functor &&f);
-#endif
- ~QNotifiedProperty() = default;
+ Q_CORE_EXPORT explicit QUntypedBindable(QObject* obj, const QMetaProperty &property, const QtPrivate::QBindableInterface *i);
+ Q_CORE_EXPORT explicit QUntypedBindable(QObject* obj, const char* property, const QtPrivate::QBindableInterface *i);
- T value() const
+public:
+ constexpr QUntypedBindable() = default;
+ template<typename Property>
+ QUntypedBindable(Property *p)
+ : data(const_cast<std::remove_cv_t<Property> *>(p)),
+ iface(&QtPrivate::QBindableInterfaceForProperty<Property>::iface)
+ { Q_ASSERT(data && iface); }
+
+ bool isValid() const { return data != nullptr; }
+ bool isBindable() const { return iface && iface->getBinding; }
+ bool isReadOnly() const { return !(iface && iface->setBinding && iface->setObserver); }
+
+ QUntypedPropertyBinding makeBinding(const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION) const
{
- if (d.priv.hasBinding())
- d.priv.evaluateIfDirty();
- d.priv.registerWithCurrentlyEvaluatingBinding();
- return d.getValue();
+ return iface ? iface->makeBinding(data, location) : QUntypedPropertyBinding();
}
- operator T() const
+ QUntypedPropertyBinding takeBinding()
{
- return value();
+ if (!iface)
+ return QUntypedPropertyBinding {};
+ // We do not have a dedicated takeBinding function pointer in the interface
+ // therefore we synthesize takeBinding by retrieving the binding with binding
+ // and calling setBinding with a default constructed QUntypedPropertyBinding
+ // afterwards.
+ if (!(iface->getBinding && iface->setBinding))
+ return QUntypedPropertyBinding {};
+ QUntypedPropertyBinding binding = iface->getBinding(data);
+ iface->setBinding(data, QUntypedPropertyBinding{});
+ return binding;
}
- template<typename S>
- auto setValue(Class *owner, S &&newValue) -> std::enable_if_t<!ValueGuardModifiesArgument && std::is_same_v<S, T>, void>
+ void observe(QPropertyObserver *observer) const
{
- if constexpr (HasValueGuard) {
- if (!(owner->*ValueGuard)(newValue))
- return;
- }
- if constexpr (CallbackAcceptsOldValue) {
- T oldValue = value(); // TODO: kind of pointless if there was no change
- if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
- notify(owner, &oldValue);
- } else {
- if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
- notify(owner);
- }
- d.priv.removeBinding();
+ if (iface)
+ iface->setObserver(data, observer);
+#ifndef QT_NO_DEBUG
+ else
+ QtPrivate::BindableWarnings::printUnsuitableBindableWarning("observe:",
+ QtPrivate::BindableWarnings::InvalidInterface);
+#endif
}
- void setValue(Class *owner, std::conditional_t<ValueGuardModifiesArgument, T, const T &> newValue)
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> onValueChanged(Functor f) const
{
- if constexpr (HasValueGuard) {
- if (!(owner->*ValueGuard)(newValue))
- return;
- }
- if constexpr (CallbackAcceptsOldValue) {
- // When newValue is T, we move it, if it's const T& it stays const T& and won't get moved
- T oldValue = value();
- if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
- notify(owner, &oldValue);
- } else {
- if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
- notify(owner);
- }
- d.priv.removeBinding();
+ QPropertyChangeHandler<Functor> handler(f);
+ observe(&handler);
+ return handler;
}
- QPropertyBinding<T> setBinding(Class *owner, const QPropertyBinding<T> &newBinding)
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> subscribe(Functor f) const
{
- if constexpr (CallbackAcceptsOldValue) {
- T oldValue = value();
- QPropertyBinding<T> oldBinding(d.priv.setBinding(newBinding, &d, owner, [](void *o, void *oldVal) {
- (reinterpret_cast<Class *>(o)->*Callback)(*reinterpret_cast<T *>(oldVal));
- }, GuardTE));
- notify(owner, &oldValue);
- return oldBinding;
- } else {
- QPropertyBinding<T> oldBinding(d.priv.setBinding(newBinding, &d, owner, [](void *o, void *) {
- (reinterpret_cast<Class *>(o)->*Callback)();
- }, GuardTE));
- notify(owner);
- return oldBinding;
- }
+ f();
+ return onValueChanged(f);
}
- QPropertyBinding<T> setBinding(Class *owner, QPropertyBinding<T> &&newBinding)
+ template<typename Functor>
+ QPropertyNotifier addNotifier(Functor f)
{
- QPropertyBinding<T> b(std::move(newBinding));
- if constexpr (CallbackAcceptsOldValue) {
- T oldValue = value();
- QPropertyBinding<T> oldBinding(d.priv.setBinding(b, &d, owner, [](void *o, void *oldVal) {
- (reinterpret_cast<Class *>(o)->*Callback)(*reinterpret_cast<T *>(oldVal));
- }, GuardTE));
- notify(owner, &oldValue);
- return oldBinding;
- } else {
- QPropertyBinding<T> oldBinding(d.priv.setBinding(b, &d, owner, [](void *o, void *) {
- (reinterpret_cast<Class *>(o)->*Callback)();
- }, GuardTE));
- notify(owner);
- return oldBinding;
- }
+ QPropertyNotifier handler(f);
+ observe(&handler);
+ return handler;
}
- bool setBinding(Class *owner, const QUntypedPropertyBinding &newBinding)
+ QUntypedPropertyBinding binding() const
+ {
+ if (!isBindable()) {
+#ifndef QT_NO_DEBUG
+ QtPrivate::BindableWarnings::printUnsuitableBindableWarning("binding: ",
+ QtPrivate::BindableWarnings::NonBindableInterface);
+#endif
+ return QUntypedPropertyBinding();
+ }
+ return iface->getBinding(data);
+ }
+ bool setBinding(const QUntypedPropertyBinding &binding)
{
- if (newBinding.valueMetaType().id() != qMetaTypeId<T>())
+ if (isReadOnly()) {
+#ifndef QT_NO_DEBUG
+ const auto errorType = iface ? QtPrivate::BindableWarnings::ReadOnlyInterface :
+ QtPrivate::BindableWarnings::InvalidInterface;
+ QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding: Could not set binding via bindable interface.", errorType);
+#endif
+ return false;
+ }
+ if (!binding.isNull() && binding.valueMetaType() != metaType()) {
+#ifndef QT_NO_DEBUG
+ QtPrivate::BindableWarnings::printMetaTypeMismatch(metaType(), binding.valueMetaType());
+#endif
return false;
- if constexpr (CallbackAcceptsOldValue) {
- T oldValue = value();
- d.priv.setBinding(newBinding, &d, owner, [](void *o, void *oldVal) {
- (reinterpret_cast<Class *>(o)->*Callback)(*reinterpret_cast<T *>(oldVal));
- }, GuardTE);
- notify(owner, &oldValue);
- } else {
- d.priv.setBinding(newBinding, &d, owner, [](void *o, void *) {
- (reinterpret_cast<Class *>(o)->*Callback)();
- }, GuardTE);
- notify(owner);
}
+ iface->setBinding(data, binding);
return true;
}
+ bool hasBinding() const
+ {
+ return !binding().isNull();
+ }
-#ifndef Q_CLANG_QDOC
- template <typename Functor>
- QPropertyBinding<T> setBinding(Class *owner, Functor &&f,
- const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
- std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
+ QMetaType metaType() const
{
- return setBinding(owner, Qt::makePropertyBinding(std::forward<Functor>(f), location));
+ if (!(iface && data))
+ return QMetaType();
+ if (iface->metaType)
+ return iface->metaType();
+ // ### Qt 7: Change the metatype function to take data as its argument
+ // special casing for QML's proxy bindable: allow multiplexing in the getter
+ // function to retrieve the metatype from data
+ Q_ASSERT(iface->getter);
+ QMetaType result;
+ iface->getter(data, reinterpret_cast<void *>(quintptr(&result) | QtPrivate::QBindableInterface::MetaTypeAccessorFlag));
+ return result;
}
-#else
- template <typename Functor>
- QPropertyBinding<T> setBinding(Class *owner, Functor f);
-#endif
- bool hasBinding() const { return d.priv.hasBinding(); }
+};
+
+template<typename T>
+class QBindable : public QUntypedBindable
+{
+ template<typename U>
+ friend class QPropertyAlias;
+ constexpr QBindable(QUntypedPropertyData *d, const QtPrivate::QBindableInterface *i)
+ : QUntypedBindable(d, i)
+ {}
+public:
+ using QUntypedBindable::QUntypedBindable;
+ explicit QBindable(const QUntypedBindable &b) : QUntypedBindable(b)
+ {
+ if (iface && metaType() != QMetaType::fromType<T>()) {
+ data = nullptr;
+ iface = nullptr;
+ }
+ }
+
+ explicit QBindable(QObject *obj, const QMetaProperty &property)
+ : QUntypedBindable(obj, property, &QtPrivate::PropertyAdaptorSlotObjectHelpers::iface<T>) {}
+
+ explicit QBindable(QObject *obj, const char *property)
+ : QUntypedBindable(obj, property, &QtPrivate::PropertyAdaptorSlotObjectHelpers::iface<T>) {}
+ QPropertyBinding<T> makeBinding(const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION) const
+ {
+ return static_cast<QPropertyBinding<T> &&>(QUntypedBindable::makeBinding(location));
+ }
QPropertyBinding<T> binding() const
{
- return QPropertyBinding<T>(*this);
+ return static_cast<QPropertyBinding<T> &&>(QUntypedBindable::binding());
}
QPropertyBinding<T> takeBinding()
{
- return QPropertyBinding<T>(d.priv.setBinding(QUntypedPropertyBinding(), &d));
+ return static_cast<QPropertyBinding<T> &&>(QUntypedBindable::takeBinding());
}
- template<typename Functor>
- QPropertyChangeHandler<Functor> onValueChanged(Functor f);
- template<typename Functor>
- QPropertyChangeHandler<Functor> subscribe(Functor f);
+ using QUntypedBindable::setBinding;
+ QPropertyBinding<T> setBinding(const QPropertyBinding<T> &binding)
+ {
+ Q_ASSERT(!iface || binding.isNull() || binding.valueMetaType() == metaType());
+
+ if (iface && iface->setBinding)
+ return static_cast<QPropertyBinding<T> &&>(iface->setBinding(data, binding));
+#ifndef QT_NO_DEBUG
+ if (!iface)
+ QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding", QtPrivate::BindableWarnings::InvalidInterface);
+ else
+ QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding: Could not set binding via bindable interface.", QtPrivate::BindableWarnings::ReadOnlyInterface);
+#endif
+ return QPropertyBinding<T>();
+ }
+#ifndef Q_QDOC
+ template <typename Functor>
+ QPropertyBinding<T> setBinding(Functor &&f,
+ const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
+ std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
+ {
+ return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
+ }
+#else
+ template <typename Functor>
+ QPropertyBinding<T> setBinding(Functor f);
+#endif
-private:
- void notify(Class *owner, T *oldValue=nullptr)
+ T value() const
{
- d.priv.notifyObservers(&d);
- if constexpr (std::is_invocable_v<decltype(Callback), Class>) {
- Q_UNUSED(oldValue);
- (owner->*Callback)();
- } else {
- (owner->*Callback)(*oldValue);
+ if (iface) {
+ T result;
+ iface->getter(data, &result);
+ return result;
}
+ return T{};
}
- Q_DISABLE_COPY_MOVE(QNotifiedProperty)
-
- friend class QPropertyBinding<T>;
- friend class QPropertyObserver;
- // Mutable because querying for the value may require evalating the binding expression, calling
- // non-const functions on QPropertyBase.
- mutable QtPrivate::QPropertyValueStorage<T> d;
+ void setValue(const T &value)
+ {
+ if (iface && iface->setter)
+ iface->setter(data, &value);
+ }
};
-struct QPropertyObserverPrivate;
-struct QPropertyObserverPointer;
-
-class Q_CORE_EXPORT QPropertyObserver
+#if QT_DEPRECATED_SINCE(6, 6)
+template<typename T>
+class QT_DEPRECATED_VERSION_X_6_6("Class was only meant for internal use, use a QProperty and add a binding to the target")
+QPropertyAlias : public QPropertyObserver
{
-public:
- // Internal
- enum ObserverTag {
- ObserverNotifiesBinding,
- ObserverNotifiesChangeHandler,
- ObserverNotifiesAlias,
- };
+ Q_DISABLE_COPY_MOVE(QPropertyAlias)
+ const QtPrivate::QBindableInterface *iface = nullptr;
- QPropertyObserver();
- QPropertyObserver(QPropertyObserver &&other);
- QPropertyObserver &operator=(QPropertyObserver &&other);
- ~QPropertyObserver();
+public:
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ QPropertyAlias(QProperty<T> *property)
+ : QPropertyObserver(property),
+ iface(&QtPrivate::QBindableInterfaceForProperty<QProperty<T>>::iface)
+ {
+ if (iface)
+ iface->setObserver(aliasedProperty(), this);
+ }
- template <typename PropertyType>
- void setSource(const QProperty<PropertyType> &property)
- { setSource(property.d.priv); }
+ template <typename Property, QtPrivate::IsUntypedPropertyData<Property> = true>
+ QPropertyAlias(Property *property)
+ : QPropertyObserver(property),
+ iface(&QtPrivate::QBindableInterfaceForProperty<Property>::iface)
+ {
+ if (iface)
+ iface->setObserver(aliasedProperty(), this);
+ }
- template <typename PropertyType, auto notifier, auto guard>
- void setSource(const QNotifiedProperty<PropertyType, notifier, guard> &property)
- { setSource(property.d.priv); }
+ QPropertyAlias(QPropertyAlias<T> *alias)
+ : QPropertyObserver(alias->aliasedProperty()),
+ iface(alias->iface)
+ {
+ if (iface)
+ iface->setObserver(aliasedProperty(), this);
+ }
-protected:
- QPropertyObserver(void (*callback)(QPropertyObserver*, void *));
- QPropertyObserver(void *aliasedPropertyPtr);
+ QPropertyAlias(const QBindable<T> &property)
+ : QPropertyObserver(property.data),
+ iface(property.iface)
+ {
+ if (iface)
+ iface->setObserver(aliasedProperty(), this);
+ }
- template<typename PropertyType>
- QProperty<PropertyType> *aliasedProperty() const
+ T value() const
{
- return reinterpret_cast<QProperty<PropertyType> *>(aliasedPropertyPtr);
+ T t = T();
+ if (auto *p = aliasedProperty())
+ iface->getter(p, &t);
+ return t;
}
-private:
- void setSource(QtPrivate::QPropertyBase &property);
+ operator T() const { return value(); }
- QTaggedPointer<QPropertyObserver, ObserverTag> next;
- // prev is a pointer to the "next" element within the previous node, or to the "firstObserverPtr" if it is the
- // first node.
- QtPrivate::QTagPreservingPointerToPointer<QPropertyObserver, ObserverTag> prev;
+ void setValue(const T &newValue)
+ {
+ if (auto *p = aliasedProperty())
+ iface->setter(p, &newValue);
+ }
- union {
- QPropertyBindingPrivate *bindingToMarkDirty = nullptr;
- void (*changeHandler)(QPropertyObserver*, void *);
- quintptr aliasedPropertyPtr;
- };
+ QPropertyAlias<T> &operator=(const T &newValue)
+ {
+ setValue(newValue);
+ return *this;
+ }
- QPropertyObserver(const QPropertyObserver &) = delete;
- QPropertyObserver &operator=(const QPropertyObserver &) = delete;
+ QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding)
+ {
+ return QBindable<T>(aliasedProperty(), iface).setBinding(newBinding);
+ }
- friend struct QPropertyObserverPointer;
- friend struct QPropertyBasePointer;
- friend class QPropertyBindingPrivate;
-};
+ bool setBinding(const QUntypedPropertyBinding &newBinding)
+ {
+ return QBindable<T>(aliasedProperty(), iface).setBinding(newBinding);
+ }
-template <typename Functor>
-class QPropertyChangeHandler : public QPropertyObserver
-{
- Functor m_handler;
-public:
- QPropertyChangeHandler(Functor handler)
- : QPropertyObserver([](QPropertyObserver *self, void *) {
- auto This = static_cast<QPropertyChangeHandler<Functor>*>(self);
- This->m_handler();
- })
- , m_handler(handler)
+#ifndef Q_QDOC
+ template <typename Functor>
+ QPropertyBinding<T> setBinding(Functor &&f,
+ const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
+ std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
{
+ return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
}
+#else
+ template <typename Functor>
+ QPropertyBinding<T> setBinding(Functor f);
+#endif
- template <typename PropertyType>
- QPropertyChangeHandler(const QProperty<PropertyType> &property, Functor handler)
- : QPropertyObserver([](QPropertyObserver *self, void *) {
- auto This = static_cast<QPropertyChangeHandler<Functor>*>(self);
- This->m_handler();
- })
- , m_handler(handler)
+ bool hasBinding() const
{
- setSource(property);
+ return QBindable<T>(aliasedProperty(), iface).hasBinding();
}
- template <typename PropertyType, auto Callback, auto Guard>
- QPropertyChangeHandler(const QNotifiedProperty<PropertyType, Callback, Guard> &property, Functor handler)
- : QPropertyObserver([](QPropertyObserver *self, void *) {
- auto This = static_cast<QPropertyChangeHandler<Functor>*>(self);
- This->m_handler();
- })
- , m_handler(handler)
+ QPropertyBinding<T> binding() const
{
- setSource(property);
+ return QBindable<T>(aliasedProperty(), iface).binding();
}
-};
-template <typename T>
-template<typename Functor>
-QPropertyChangeHandler<Functor> QProperty<T>::onValueChanged(Functor f)
-{
-#if defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703L)
- static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
-#endif
- return QPropertyChangeHandler<Functor>(*this, f);
-}
+ QPropertyBinding<T> takeBinding()
+ {
+ return QBindable<T>(aliasedProperty(), iface).takeBinding();
+ }
-template <typename T>
-template<typename Functor>
-QPropertyChangeHandler<Functor> QProperty<T>::subscribe(Functor f)
-{
-#if defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703L)
- static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
-#endif
- f();
- return onValueChanged(f);
-}
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> onValueChanged(Functor f)
+ {
+ return QBindable<T>(aliasedProperty(), iface).onValueChanged(f);
+ }
-template <typename T, auto Callback, auto ValueGuard>
-template<typename Functor>
-QPropertyChangeHandler<Functor> QNotifiedProperty<T, Callback, ValueGuard>::onValueChanged(Functor f)
-{
-#if defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703L)
- static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
-#endif
- return QPropertyChangeHandler<Functor>(*this, f);
-}
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> subscribe(Functor f)
+ {
+ return QBindable<T>(aliasedProperty(), iface).subscribe(f);
+ }
-template <typename T, auto Callback, auto ValueGuard>
-template<typename Functor>
-QPropertyChangeHandler<Functor> QNotifiedProperty<T, Callback, ValueGuard>::subscribe(Functor f)
-{
-#if defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703L)
- static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
-#endif
- f();
- return onValueChanged(f);
-}
+ template<typename Functor>
+ QPropertyNotifier addNotifier(Functor f)
+ {
+ return QBindable<T>(aliasedProperty(), iface).addNotifier(f);
+ }
-template<typename T>
-class QPropertyAlias : public QPropertyObserver
-{
- Q_DISABLE_COPY_MOVE(QPropertyAlias)
-public:
- QPropertyAlias(QProperty<T> *property)
- : QPropertyObserver(property)
+ bool isValid() const
{
- if (property)
- setSource(*property);
+ return aliasedProperty() != nullptr;
}
+ QT_WARNING_POP
+};
+#endif // QT_DEPRECATED_SINCE(6, 6)
- QPropertyAlias(QPropertyAlias<T> *alias)
- : QPropertyAlias(alias->aliasedProperty<T>())
+template<typename Class, typename T, auto Offset, auto Signal = nullptr>
+class QObjectBindableProperty : public QPropertyData<T>
+{
+ using ThisType = QObjectBindableProperty<Class, T, Offset, Signal>;
+ static bool constexpr HasSignal = !std::is_same_v<decltype(Signal), std::nullptr_t>;
+ using SignalTakesValue = std::is_invocable<decltype(Signal), Class, T>;
+ Class *owner()
+ {
+ char *that = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
+ }
+ const Class *owner() const
+ {
+ char *that = const_cast<char *>(reinterpret_cast<const char *>(this));
+ return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
+ }
+ static void signalCallBack(QUntypedPropertyData *o)
+ {
+ QObjectBindableProperty *that = static_cast<QObjectBindableProperty *>(o);
+ if constexpr (HasSignal) {
+ if constexpr (SignalTakesValue::value)
+ (that->owner()->*Signal)(that->valueBypassingBindings());
+ else
+ (that->owner()->*Signal)();
+ }
+ }
+public:
+ using value_type = typename QPropertyData<T>::value_type;
+ using parameter_type = typename QPropertyData<T>::parameter_type;
+ using rvalue_ref = typename QPropertyData<T>::rvalue_ref;
+ using arrow_operator_result = typename QPropertyData<T>::arrow_operator_result;
+
+ QObjectBindableProperty() = default;
+ explicit QObjectBindableProperty(const T &initialValue) : QPropertyData<T>(initialValue) {}
+ explicit QObjectBindableProperty(T &&initialValue) : QPropertyData<T>(std::move(initialValue)) {}
+ explicit QObjectBindableProperty(const QPropertyBinding<T> &binding)
+ : QObjectBindableProperty()
+ { setBinding(binding); }
+#ifndef Q_QDOC
+ template <typename Functor>
+ explicit QObjectBindableProperty(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
+ typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = nullptr)
+ : QObjectBindableProperty(QPropertyBinding<T>(std::forward<Functor>(f), location))
{}
+#else
+ template <typename Functor>
+ explicit QObjectBindableProperty(Functor &&f);
+#endif
- T value() const
+ parameter_type value() const
{
- if (auto *p = aliasedProperty<T>())
- return p->value();
- return T();
+ qGetBindingStorage(owner())->registerDependency(this);
+ return this->val;
}
- operator T() const { return value(); }
-
- void setValue(T &&newValue)
+ arrow_operator_result operator->() const
{
- if (auto *p = aliasedProperty<T>())
- p->setValue(std::move(newValue));
+ if constexpr (QTypeTraits::is_dereferenceable_v<T>) {
+ return value();
+ } else if constexpr (std::is_pointer_v<T>) {
+ value();
+ return this->val;
+ } else {
+ return;
+ }
}
- void setValue(const T &newValue)
+ parameter_type operator*() const
{
- if (auto *p = aliasedProperty<T>())
- p->setValue(newValue);
+ return value();
}
- QPropertyAlias<T> &operator=(T &&newValue)
+ operator parameter_type() const
{
- if (auto *p = aliasedProperty<T>())
- *p = std::move(newValue);
- return *this;
+ return value();
}
- QPropertyAlias<T> &operator=(const T &newValue)
+ void setValue(parameter_type t)
{
- if (auto *p = aliasedProperty<T>())
- *p = newValue;
- return *this;
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ if (bd)
+ bd->removeBinding();
+ if (this->val == t)
+ return;
+ this->val = t;
+ notify(bd);
+ }
+
+ void notify() {
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ notify(bd);
}
- QPropertyAlias<T> &operator=(const QPropertyBinding<T> &newBinding)
+ void setValue(rvalue_ref t)
{
- setBinding(newBinding);
- return *this;
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ if (bd)
+ bd->removeBinding();
+ if (this->val == t)
+ return;
+ this->val = std::move(t);
+ notify(bd);
}
- QPropertyAlias<T> &operator=(QPropertyBinding<T> &&newBinding)
+ QObjectBindableProperty &operator=(rvalue_ref newValue)
{
- setBinding(std::move(newBinding));
+ setValue(std::move(newValue));
return *this;
}
- QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding)
+ QObjectBindableProperty &operator=(parameter_type newValue)
{
- if (auto *p = aliasedProperty<T>())
- return p->setBinding(newBinding);
- return QPropertyBinding<T>();
+ setValue(newValue);
+ return *this;
}
- QPropertyBinding<T> setBinding(QPropertyBinding<T> &&newBinding)
+ QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding)
{
- if (auto *p = aliasedProperty<T>())
- return p->setBinding(std::move(newBinding));
- return QPropertyBinding<T>();
+ QtPrivate::QPropertyBindingData *bd = qGetBindingStorage(owner())->bindingData(this, true);
+ QUntypedPropertyBinding oldBinding(bd->setBinding(newBinding, this, HasSignal ? &signalCallBack : nullptr));
+ return static_cast<QPropertyBinding<T> &>(oldBinding);
}
bool setBinding(const QUntypedPropertyBinding &newBinding)
{
- if (auto *p = aliasedProperty<T>())
- return p->setBinding(newBinding);
- return false;
+ if (!newBinding.isNull() && newBinding.valueMetaType().id() != qMetaTypeId<T>())
+ return false;
+ setBinding(static_cast<const QPropertyBinding<T> &>(newBinding));
+ return true;
}
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
template <typename Functor>
QPropertyBinding<T> setBinding(Functor &&f,
const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
@@ -830,46 +1164,204 @@ public:
bool hasBinding() const
{
- if (auto *p = aliasedProperty<T>())
- return p->hasBinding();
- return false;
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ return bd && bd->binding() != nullptr;
}
QPropertyBinding<T> binding() const
{
- if (auto *p = aliasedProperty<T>())
- return p->binding();
- return QPropertyBinding<T>();
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ return static_cast<QPropertyBinding<T> &&>(QUntypedPropertyBinding(bd ? bd->binding() : nullptr));
}
QPropertyBinding<T> takeBinding()
{
- if (auto *p = aliasedProperty<T>())
- return p->takeBinding();
- return QPropertyBinding<T>();
+ return setBinding(QPropertyBinding<T>());
}
template<typename Functor>
QPropertyChangeHandler<Functor> onValueChanged(Functor f)
{
- if (auto *p = aliasedProperty<T>())
- return p->onValueChanged(f);
- return QPropertyChangeHandler<Functor>(f);
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyChangeHandler<Functor>(*this, f);
}
template<typename Functor>
QPropertyChangeHandler<Functor> subscribe(Functor f)
{
- if (auto *p = aliasedProperty<T>())
- return p->subscribe(f);
- return QPropertyChangeHandler<Functor>(f);
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ f();
+ return onValueChanged(f);
}
- bool isValid() const
+ template<typename Functor>
+ QPropertyNotifier addNotifier(Functor f)
{
- return aliasedProperty<T>() != nullptr;
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyNotifier(*this, f);
+ }
+
+ const QtPrivate::QPropertyBindingData &bindingData() const
+ {
+ auto *storage = const_cast<QBindingStorage *>(qGetBindingStorage(owner()));
+ return *storage->bindingData(const_cast<ThisType *>(this), true);
+ }
+private:
+ void notify(const QtPrivate::QPropertyBindingData *binding)
+ {
+ if (binding)
+ binding->notifyObservers(this, qGetBindingStorage(owner()));
+ if constexpr (HasSignal) {
+ if constexpr (SignalTakesValue::value)
+ (owner()->*Signal)(this->valueBypassingBindings());
+ else
+ (owner()->*Signal)();
+ }
}
};
+
+#define QT_OBJECT_BINDABLE_PROPERTY_3(Class, Type, name) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr> name;
+
+#define QT_OBJECT_BINDABLE_PROPERTY_4(Class, Type, name, Signal) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal> name;
+
+#define Q_OBJECT_BINDABLE_PROPERTY(...) \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ QT_OVERLOADED_MACRO(QT_OBJECT_BINDABLE_PROPERTY, __VA_ARGS__) \
+ QT_WARNING_POP
+
+#define QT_OBJECT_BINDABLE_PROPERTY_WITH_ARGS_4(Class, Type, name, value) \
+ static constexpr size_t _qt_property_##name##_offset() \
+ { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr> name = \
+ QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr>( \
+ value);
+
+#define QT_OBJECT_BINDABLE_PROPERTY_WITH_ARGS_5(Class, Type, name, value, Signal) \
+ static constexpr size_t _qt_property_##name##_offset() \
+ { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal> name = \
+ QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal>( \
+ value);
+
+#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...) \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ QT_OVERLOADED_MACRO(QT_OBJECT_BINDABLE_PROPERTY_WITH_ARGS, __VA_ARGS__) \
+ QT_WARNING_POP
+
+template<typename Class, typename T, auto Offset, auto Getter>
+class QObjectComputedProperty : public QUntypedPropertyData
+{
+ Class *owner()
+ {
+ char *that = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
+ }
+ const Class *owner() const
+ {
+ char *that = const_cast<char *>(reinterpret_cast<const char *>(this));
+ return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
+ }
+
+public:
+ using value_type = T;
+ using parameter_type = T;
+
+ QObjectComputedProperty() = default;
+
+ parameter_type value() const
+ {
+ qGetBindingStorage(owner())->registerDependency(this);
+ return (owner()->*Getter)();
+ }
+
+ std::conditional_t<QTypeTraits::is_dereferenceable_v<T>, parameter_type, void>
+ operator->() const
+ {
+ if constexpr (QTypeTraits::is_dereferenceable_v<T>)
+ return value();
+ else
+ return;
+ }
+
+ parameter_type operator*() const
+ {
+ return value();
+ }
+
+ operator parameter_type() const
+ {
+ return value();
+ }
+
+ constexpr bool hasBinding() const { return false; }
+
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> onValueChanged(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyChangeHandler<Functor>(*this, f);
+ }
+
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> subscribe(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ f();
+ return onValueChanged(f);
+ }
+
+ template<typename Functor>
+ QPropertyNotifier addNotifier(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyNotifier(*this, f);
+ }
+
+ QtPrivate::QPropertyBindingData &bindingData() const
+ {
+ auto *storage = const_cast<QBindingStorage *>(qGetBindingStorage(owner()));
+ return *storage->bindingData(const_cast<QObjectComputedProperty *>(this), true);
+ }
+
+ void notify() {
+ // computed property can't store a binding, so there's nothing to mark
+ auto *storage = const_cast<QBindingStorage *>(qGetBindingStorage(owner()));
+ auto bd = storage->bindingData(const_cast<QObjectComputedProperty *>(this), false);
+ if (bd)
+ bd->notifyObservers(this, qGetBindingStorage(owner()));
+ }
+};
+
+#define Q_OBJECT_COMPUTED_PROPERTY(Class, Type, name, ...) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectComputedProperty<Class, Type, Class::_qt_property_##name##_offset, __VA_ARGS__> name;
+
+#undef QT_SOURCE_LOCATION_NAMESPACE
+
QT_END_NAMESPACE
#endif // QPROPERTY_H
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index e5365f36fc..8ae6664a2b 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROPERTY_P_H
#define QPROPERTY_P_H
@@ -45,57 +9,181 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
//
// We mean it.
//
-#include <qglobal.h>
-#include <qvarlengtharray.h>
+#include <private/qglobal_p.h>
+#include <qproperty.h>
-#include "qproperty.h"
+#include <qmetaobject.h>
+#include <qscopedpointer.h>
+#include <qscopedvaluerollback.h>
+#include <qvariant.h>
+#include <vector>
+#include <QtCore/QVarLengthArray>
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+ Q_CORE_EXPORT bool isAnyBindingEvaluating();
+ struct QBindingStatusAccessToken {};
+}
+
+
+/*!
+ \internal
+ Similar to \c QPropertyBindingPrivatePtr, but stores a
+ \c QPropertyObserver * linking to the QPropertyBindingPrivate*
+ instead of the QPropertyBindingPrivate* itself
+ */
+struct QBindingObserverPtr
+{
+private:
+ QPropertyObserver *d = nullptr;
+public:
+ QBindingObserverPtr() = default;
+ Q_DISABLE_COPY(QBindingObserverPtr);
+ void swap(QBindingObserverPtr &other) noexcept
+ { qt_ptr_swap(d, other.d); }
+ QBindingObserverPtr(QBindingObserverPtr &&other) noexcept : d(std::exchange(other.d, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QBindingObserverPtr);
+
+
+ inline QBindingObserverPtr(QPropertyObserver *observer) noexcept;
+ inline ~QBindingObserverPtr();
+ inline QPropertyBindingPrivate *binding() const noexcept;
+ inline QPropertyObserver *operator ->();
+};
+
+using PendingBindingObserverList = QVarLengthArray<QBindingObserverPtr>;
+
+// Keep all classes related to QProperty in one compilation unit. Performance of this code is crucial and
+// we need to allow the compiler to inline where it makes sense.
+
// This is a helper "namespace"
-struct Q_AUTOTEST_EXPORT QPropertyBasePointer
+struct QPropertyBindingDataPointer
{
- const QtPrivate::QPropertyBase *ptr = nullptr;
+ const QtPrivate::QPropertyBindingData *ptr = nullptr;
- QPropertyBindingPrivate *bindingPtr() const;
+ QPropertyBindingPrivate *binding() const
+ {
+ return ptr->binding();
+ }
- void setObservers(QPropertyObserver *observer);
- void addObserver(QPropertyObserver *observer);
- void setFirstObserver(QPropertyObserver *observer);
- QPropertyObserverPointer firstObserver() const;
+ void setObservers(QPropertyObserver *observer)
+ {
+ auto &d = ptr->d_ref();
+ observer->prev = reinterpret_cast<QPropertyObserver**>(&d);
+ d = reinterpret_cast<quintptr>(observer);
+ }
+ static void fixupAfterMove(QtPrivate::QPropertyBindingData *ptr);
+ void Q_ALWAYS_INLINE addObserver(QPropertyObserver *observer);
+ inline void setFirstObserver(QPropertyObserver *observer);
+ inline QPropertyObserverPointer firstObserver() const;
+ static QPropertyProxyBindingData *proxyData(QtPrivate::QPropertyBindingData *ptr);
- int observerCount() const;
+ inline int observerCount() const;
template <typename T>
- static QPropertyBasePointer get(QProperty<T> &property)
+ static QPropertyBindingDataPointer get(QProperty<T> &property)
{
- return QPropertyBasePointer{&property.d.priv};
+ return QPropertyBindingDataPointer{&property.bindingData()};
}
};
+struct QPropertyObserverNodeProtector
+{
+ Q_DISABLE_COPY_MOVE(QPropertyObserverNodeProtector)
+
+ QPropertyObserverBase m_placeHolder;
+ Q_NODISCARD_CTOR
+ QPropertyObserverNodeProtector(QPropertyObserver *observer)
+ {
+ // insert m_placeholder after observer into the linked list
+ QPropertyObserver *next = observer->next.data();
+ m_placeHolder.next = next;
+ observer->next = static_cast<QPropertyObserver *>(&m_placeHolder);
+ if (next)
+ next->prev = &m_placeHolder.next;
+ m_placeHolder.prev = &observer->next;
+ m_placeHolder.next.setTag(QPropertyObserver::ObserverIsPlaceholder);
+ }
+
+ QPropertyObserver *next() const { return m_placeHolder.next.data(); }
+
+ ~QPropertyObserverNodeProtector();
+};
+
// This is a helper "namespace"
struct QPropertyObserverPointer
{
QPropertyObserver *ptr = nullptr;
- void unlink();
+ void unlink()
+ {
+ unlink_common();
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ if (ptr->next.tag() == QPropertyObserver::ObserverIsAlias)
+ ptr->aliasData = nullptr;
+ QT_WARNING_POP
+#endif
+ }
+
+ void unlink_fast()
+ {
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsAlias);
+ QT_WARNING_POP
+#endif
+ unlink_common();
+ }
+
+ void setBindingToNotify(QPropertyBindingPrivate *binding)
+ {
+ Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder);
+ ptr->binding = binding;
+ ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding);
+ }
+
+ void setBindingToNotify_unsafe(QPropertyBindingPrivate *binding);
+ void setChangeHandler(QPropertyObserver::ChangeHandler changeHandler);
- void setBindingToMarkDirty(QPropertyBindingPrivate *binding);
- void setChangeHandler(void (*changeHandler)(QPropertyObserver *, void *));
- void setAliasedProperty(void *propertyPtr);
+ enum class Notify {Everything, OnlyChangeHandlers};
- void notify(QPropertyBindingPrivate *triggeringBinding, void *propertyDataPtr);
- void observeProperty(QPropertyBasePointer property);
+ void notify(QUntypedPropertyData *propertyDataPtr);
+#ifndef QT_NO_DEBUG
+ void noSelfDependencies(QPropertyBindingPrivate *binding);
+#else
+ void noSelfDependencies(QPropertyBindingPrivate *) {}
+#endif
+ void evaluateBindings(PendingBindingObserverList &bindingObservers, QBindingStatus *status);
+ void observeProperty(QPropertyBindingDataPointer property);
explicit operator bool() const { return ptr != nullptr; }
QPropertyObserverPointer nextObserver() const { return {ptr->next.data()}; }
+
+ QPropertyBindingPrivate *binding() const
+ {
+ Q_ASSERT(ptr->next.tag() == QPropertyObserver::ObserverNotifiesBinding);
+ return ptr->binding;
+ }
+
+private:
+ void unlink_common()
+ {
+ if (ptr->next)
+ ptr->next->prev = ptr->prev;
+ if (ptr->prev)
+ ptr->prev.setPointer(ptr->next.data());
+ ptr->next = nullptr;
+ ptr->prev.clear();
+ }
};
class QPropertyBindingErrorPrivate : public QSharedData
@@ -103,16 +191,810 @@ class QPropertyBindingErrorPrivate : public QSharedData
public:
QPropertyBindingError::Type type = QPropertyBindingError::NoError;
QString description;
- QPropertyBindingSourceLocation location;
};
+namespace QtPrivate {
+
struct BindingEvaluationState
{
- BindingEvaluationState(QPropertyBindingPrivate *binding);
- ~BindingEvaluationState();
+ BindingEvaluationState(QPropertyBindingPrivate *binding, QBindingStatus *status);
+ ~BindingEvaluationState()
+ {
+ *currentState = previousState;
+ }
+
QPropertyBindingPrivate *binding;
BindingEvaluationState *previousState = nullptr;
+ BindingEvaluationState **currentState = nullptr;
+ QVarLengthArray<const QPropertyBindingData *, 8> alreadyCaptureProperties;
+};
+
+/*!
+ * \internal
+ * CompatPropertySafePoint needs to be constructed before the setter of
+ * a QObjectCompatProperty runs. It prevents spurious binding dependencies
+ * caused by reads of properties inside the compat property setter.
+ * Moreover, it ensures that we don't destroy bindings when using operator=
+ */
+struct CompatPropertySafePoint
+{
+ Q_CORE_EXPORT CompatPropertySafePoint(QBindingStatus *status, QUntypedPropertyData *property);
+ ~CompatPropertySafePoint()
+ {
+ *currentState = previousState;
+ *currentlyEvaluatingBindingList = bindingState;
+ }
+ QUntypedPropertyData *property;
+ CompatPropertySafePoint *previousState = nullptr;
+ CompatPropertySafePoint **currentState = nullptr;
+ QtPrivate::BindingEvaluationState **currentlyEvaluatingBindingList = nullptr;
+ QtPrivate::BindingEvaluationState *bindingState = nullptr;
+};
+
+/*!
+ * \internal
+ * While the regular QProperty notification for a compat property runs we
+ * don't want to have any currentCompatProperty set. This would be a _different_
+ * one than the one we are current evaluating. Therefore it's misleading and
+ * prevents the registering of actual dependencies.
+ */
+struct CurrentCompatPropertyThief
+{
+ Q_DISABLE_COPY_MOVE(CurrentCompatPropertyThief)
+public:
+ CurrentCompatPropertyThief(QBindingStatus *status)
+ : status(&status->currentCompatProperty)
+ , stolen(std::exchange(status->currentCompatProperty, nullptr))
+ {
+ }
+
+ ~CurrentCompatPropertyThief()
+ {
+ *status = stolen;
+ }
+
+private:
+ CompatPropertySafePoint **status = nullptr;
+ CompatPropertySafePoint *stolen = nullptr;
+};
+
+}
+
+class Q_CORE_EXPORT QPropertyBindingPrivate : public QtPrivate::RefCounted
+{
+private:
+ friend struct QPropertyBindingDataPointer;
+ friend class QPropertyBindingPrivatePtr;
+
+ using ObserverArray = std::array<QPropertyObserver, 4>;
+
+private:
+
+ // used to detect binding loops for lazy evaluated properties
+ bool updating = false;
+ bool hasStaticObserver = false;
+ bool pendingNotify = false;
+ bool hasBindingWrapper:1;
+ // used to detect binding loops for eagerly evaluated properties
+ bool isQQmlPropertyBinding:1;
+ /* a sticky binding does not get removed in removeBinding
+ this is used to support QQmlPropertyData::DontRemoveBinding
+ in qtdeclarative
+ */
+ bool m_sticky:1;
+
+ const QtPrivate::BindingFunctionVTable *vtable;
+
+ union {
+ QtPrivate::QPropertyObserverCallback staticObserverCallback = nullptr;
+ QtPrivate::QPropertyBindingWrapper staticBindingWrapper;
+ };
+ ObserverArray inlineDependencyObservers; // for things we are observing
+
+ QPropertyObserverPointer firstObserver; // list of observers observing us
+ QScopedPointer<std::vector<QPropertyObserver>> heapObservers; // for things we are observing
+
+protected:
+ QUntypedPropertyData *propertyDataPtr = nullptr;
+
+ /* For bindings set up from C++, location stores where the binding was created in the C++ source
+ For QQmlPropertyBinding that information does not make sense, and the location in the QML file
+ is stored somewhere else. To make efficient use of the space, we instead provide a scratch space
+ for QQmlPropertyBinding (which stores further binding information there).
+ Anything stored in the union must be trivially destructible.
+ (checked in qproperty.cpp)
+ */
+ using DeclarativeErrorCallback = void(*)(QPropertyBindingPrivate *);
+ union {
+ QPropertyBindingSourceLocation location;
+ struct {
+ std::byte declarativeExtraData[sizeof(QPropertyBindingSourceLocation) - sizeof(DeclarativeErrorCallback)];
+ DeclarativeErrorCallback errorCallBack;
+ };
+ };
+private:
+ QPropertyBindingError error;
+
+ QMetaType metaType;
+
+public:
+ static constexpr size_t getSizeEnsuringAlignment() {
+ constexpr auto align = alignof (std::max_align_t) - 1;
+ constexpr size_t sizeEnsuringAlignment = (sizeof(QPropertyBindingPrivate) + align) & ~align;
+ static_assert (sizeEnsuringAlignment % alignof (std::max_align_t) == 0,
+ "Required for placement new'ing the function behind it.");
+ return sizeEnsuringAlignment;
+ }
+
+
+ // public because the auto-tests access it, too.
+ size_t dependencyObserverCount = 0;
+
+ bool isUpdating() {return updating;}
+ void setSticky(bool keep = true) {m_sticky = keep;}
+ bool isSticky() {return m_sticky;}
+ void scheduleNotify() {pendingNotify = true;}
+
+ QPropertyBindingPrivate(QMetaType metaType, const QtPrivate::BindingFunctionVTable *vtable,
+ const QPropertyBindingSourceLocation &location, bool isQQmlPropertyBinding=false)
+ : hasBindingWrapper(false)
+ , isQQmlPropertyBinding(isQQmlPropertyBinding)
+ , m_sticky(false)
+ , vtable(vtable)
+ , location(location)
+ , metaType(metaType)
+ {}
+ ~QPropertyBindingPrivate();
+
+
+ void setProperty(QUntypedPropertyData *propertyPtr) { propertyDataPtr = propertyPtr; }
+ void setStaticObserver(QtPrivate::QPropertyObserverCallback callback, QtPrivate::QPropertyBindingWrapper bindingWrapper)
+ {
+ Q_ASSERT(!(callback && bindingWrapper));
+ if (callback) {
+ hasStaticObserver = true;
+ hasBindingWrapper = false;
+ staticObserverCallback = callback;
+ } else if (bindingWrapper) {
+ hasStaticObserver = false;
+ hasBindingWrapper = true;
+ staticBindingWrapper = bindingWrapper;
+ } else {
+ hasStaticObserver = false;
+ hasBindingWrapper = false;
+ staticObserverCallback = nullptr;
+ }
+ }
+ void prependObserver(QPropertyObserverPointer observer)
+ {
+ observer.ptr->prev = const_cast<QPropertyObserver **>(&firstObserver.ptr);
+ firstObserver = observer;
+ }
+
+ QPropertyObserverPointer takeObservers()
+ {
+ auto observers = firstObserver;
+ firstObserver.ptr = nullptr;
+ return observers;
+ }
+
+ void clearDependencyObservers();
+
+ Q_ALWAYS_INLINE QPropertyObserverPointer allocateDependencyObserver() {
+ if (dependencyObserverCount < inlineDependencyObservers.size()) {
+ ++dependencyObserverCount;
+ return {&inlineDependencyObservers[dependencyObserverCount - 1]};
+ }
+ return allocateDependencyObserver_slow();
+ }
+
+ QPropertyObserverPointer allocateDependencyObserver_slow();
+
+ QPropertyBindingSourceLocation sourceLocation() const
+ {
+ if (!hasCustomVTable())
+ return this->location;
+ QPropertyBindingSourceLocation location;
+ constexpr auto msg = "Custom location";
+ location.fileName = msg;
+ return location;
+ }
+ QPropertyBindingError bindingError() const { return error; }
+ QMetaType valueMetaType() const { return metaType; }
+
+ void unlinkAndDeref();
+
+ bool evaluateRecursive(PendingBindingObserverList &bindingObservers, QBindingStatus *status = nullptr);
+
+ bool Q_ALWAYS_INLINE evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status);
+
+ void notifyNonRecursive(const PendingBindingObserverList &bindingObservers);
+ enum NotificationState : bool { Delayed, Sent };
+ NotificationState notifyNonRecursive();
+
+ static QPropertyBindingPrivate *get(const QUntypedPropertyBinding &binding)
+ { return static_cast<QPropertyBindingPrivate *>(binding.d.data()); }
+
+ void setError(QPropertyBindingError &&e)
+ { error = std::move(e); }
+
+ void detachFromProperty()
+ {
+ hasStaticObserver = false;
+ hasBindingWrapper = false;
+ propertyDataPtr = nullptr;
+ clearDependencyObservers();
+ }
+
+ static QPropertyBindingPrivate *currentlyEvaluatingBinding();
+
+ bool hasCustomVTable() const
+ {
+ return vtable->size == 0;
+ }
+
+ static void destroyAndFreeMemory(QPropertyBindingPrivate *priv) {
+ if (priv->hasCustomVTable()) {
+ // special hack for QQmlPropertyBinding which has a
+ // different memory layout than normal QPropertyBindings
+ priv->vtable->destroy(priv);
+ } else{
+ priv->~QPropertyBindingPrivate();
+ delete[] reinterpret_cast<std::byte *>(priv);
+ }
+ }
+};
+
+inline void QPropertyBindingDataPointer::setFirstObserver(QPropertyObserver *observer)
+{
+ if (auto *b = binding()) {
+ b->firstObserver.ptr = observer;
+ return;
+ }
+ auto &d = ptr->d_ref();
+ d = reinterpret_cast<quintptr>(observer);
+}
+
+inline void QPropertyBindingDataPointer::fixupAfterMove(QtPrivate::QPropertyBindingData *ptr)
+{
+ auto &d = ptr->d_ref();
+ if (ptr->isNotificationDelayed()) {
+ QPropertyProxyBindingData *proxy = ptr->proxyData();
+ Q_ASSERT(proxy);
+ proxy->originalBindingData = ptr;
+ }
+ // If QPropertyBindingData has been moved, and it has an observer
+ // we have to adjust the firstObserver's prev pointer to point to
+ // the moved to QPropertyBindingData's d_ptr
+ if (d & QtPrivate::QPropertyBindingData::BindingBit)
+ return; // nothing to do if the observer is stored in the binding
+ if (auto observer = reinterpret_cast<QPropertyObserver *>(d))
+ observer->prev = reinterpret_cast<QPropertyObserver **>(&d);
+}
+
+inline QPropertyObserverPointer QPropertyBindingDataPointer::firstObserver() const
+{
+ if (auto *b = binding())
+ return b->firstObserver;
+ return { reinterpret_cast<QPropertyObserver *>(ptr->d()) };
+}
+
+/*!
+ \internal
+ Returns the proxy data of \a ptr, or \c nullptr if \a ptr has no delayed notification
+ */
+inline QPropertyProxyBindingData *QPropertyBindingDataPointer::proxyData(QtPrivate::QPropertyBindingData *ptr)
+{
+ if (!ptr->isNotificationDelayed())
+ return nullptr;
+ return ptr->proxyData();
+}
+
+inline int QPropertyBindingDataPointer::observerCount() const
+{
+ int count = 0;
+ for (auto observer = firstObserver(); observer; observer = observer.nextObserver())
+ ++count;
+ return count;
+}
+
+namespace QtPrivate {
+ Q_CORE_EXPORT bool isPropertyInBindingWrapper(const QUntypedPropertyData *property);
+ void Q_CORE_EXPORT initBindingStatusThreadId();
+}
+
+template<typename Class, typename T, auto Offset, auto Setter, auto Signal = nullptr,
+ auto Getter = nullptr>
+class QObjectCompatProperty : public QPropertyData<T>
+{
+ template<typename Property, typename>
+ friend class QtPrivate::QBindableInterfaceForProperty;
+
+ using ThisType = QObjectCompatProperty<Class, T, Offset, Setter, Signal, Getter>;
+ using SignalTakesValue = std::is_invocable<decltype(Signal), Class, T>;
+ Class *owner()
+ {
+ char *that = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
+ }
+ const Class *owner() const
+ {
+ char *that = const_cast<char *>(reinterpret_cast<const char *>(this));
+ return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
+ }
+
+ static bool bindingWrapper(QMetaType type, QUntypedPropertyData *dataPtr, QtPrivate::QPropertyBindingFunction binding)
+ {
+ auto *thisData = static_cast<ThisType *>(dataPtr);
+ QBindingStorage *storage = qGetBindingStorage(thisData->owner());
+ QPropertyData<T> copy;
+ {
+ QtPrivate::CurrentCompatPropertyThief thief(storage->bindingStatus);
+ binding.vtable->call(type, &copy, binding.functor);
+ if constexpr (QTypeTraits::has_operator_equal_v<T>)
+ if (copy.valueBypassingBindings() == thisData->valueBypassingBindings())
+ return false;
+ }
+ // ensure value and setValue know we're currently evaluating our binding
+ QtPrivate::CompatPropertySafePoint guardThis(storage->bindingStatus, thisData);
+ (thisData->owner()->*Setter)(copy.valueBypassingBindings());
+ return true;
+ }
+ bool inBindingWrapper(const QBindingStorage *storage) const
+ {
+ return storage->bindingStatus && storage->bindingStatus->currentCompatProperty
+ && QtPrivate::isPropertyInBindingWrapper(this);
+ }
+
+ inline static T getPropertyValue(const QUntypedPropertyData *d) {
+ auto prop = static_cast<const ThisType *>(d);
+ if constexpr (std::is_null_pointer_v<decltype(Getter)>)
+ return prop->value();
+ else
+ return (prop->owner()->*Getter)();
+ }
+
+public:
+ using value_type = typename QPropertyData<T>::value_type;
+ using parameter_type = typename QPropertyData<T>::parameter_type;
+ using arrow_operator_result = typename QPropertyData<T>::arrow_operator_result;
+
+ QObjectCompatProperty() = default;
+ explicit QObjectCompatProperty(const T &initialValue) : QPropertyData<T>(initialValue) {}
+ explicit QObjectCompatProperty(T &&initialValue) : QPropertyData<T>(std::move(initialValue)) {}
+
+ parameter_type value() const
+ {
+ const QBindingStorage *storage = qGetBindingStorage(owner());
+ // make sure we don't register this binding as a dependency to itself
+ if (storage->bindingStatus && storage->bindingStatus->currentlyEvaluatingBinding && !inBindingWrapper(storage))
+ storage->registerDependency_helper(this);
+ return this->val;
+ }
+
+ arrow_operator_result operator->() const
+ {
+ if constexpr (QTypeTraits::is_dereferenceable_v<T>) {
+ return value();
+ } else if constexpr (std::is_pointer_v<T>) {
+ value();
+ return this->val;
+ } else {
+ return;
+ }
+ }
+
+ parameter_type operator*() const
+ {
+ return value();
+ }
+
+ operator parameter_type() const
+ {
+ return value();
+ }
+
+ void setValue(parameter_type t)
+ {
+ QBindingStorage *storage = qGetBindingStorage(owner());
+ if (auto *bd = storage->bindingData(this)) {
+ // make sure we don't remove the binding if called from the bindingWrapper
+ if (bd->hasBinding() && !inBindingWrapper(storage))
+ bd->removeBinding_helper();
+ }
+ this->val = t;
+ }
+
+ QObjectCompatProperty &operator=(parameter_type newValue)
+ {
+ setValue(newValue);
+ return *this;
+ }
+
+ QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding)
+ {
+ QtPrivate::QPropertyBindingData *bd = qGetBindingStorage(owner())->bindingData(this, true);
+ QUntypedPropertyBinding oldBinding(bd->setBinding(newBinding, this, nullptr, bindingWrapper));
+ // notification is already handled in QPropertyBindingData::setBinding
+ return static_cast<QPropertyBinding<T> &>(oldBinding);
+ }
+
+ bool setBinding(const QUntypedPropertyBinding &newBinding)
+ {
+ if (!newBinding.isNull() && newBinding.valueMetaType() != QMetaType::fromType<T>())
+ return false;
+ setBinding(static_cast<const QPropertyBinding<T> &>(newBinding));
+ return true;
+ }
+
+#ifndef Q_QDOC
+ template <typename Functor>
+ QPropertyBinding<T> setBinding(Functor &&f,
+ const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
+ std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
+ {
+ return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
+ }
+#else
+ template <typename Functor>
+ QPropertyBinding<T> setBinding(Functor f);
+#endif
+
+ bool hasBinding() const {
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ return bd && bd->binding() != nullptr;
+ }
+
+ void removeBindingUnlessInWrapper()
+ {
+ QBindingStorage *storage = qGetBindingStorage(owner());
+ if (auto *bd = storage->bindingData(this)) {
+ // make sure we don't remove the binding if called from the bindingWrapper
+ if (bd->hasBinding() && !inBindingWrapper(storage))
+ bd->removeBinding_helper();
+ }
+ }
+
+ void notify()
+ {
+ QBindingStorage *storage = qGetBindingStorage(owner());
+ if (auto bd = storage->bindingData(this, false)) {
+ // This partly duplicates QPropertyBindingData::notifyObservers because we want to
+ // check for inBindingWrapper() after checking for isNotificationDelayed() and
+ // firstObserver. This is because inBindingWrapper() is the most expensive check.
+ if (!bd->isNotificationDelayed()) {
+ QPropertyBindingDataPointer d{bd};
+ if (QPropertyObserverPointer observer = d.firstObserver()) {
+ if (!inBindingWrapper(storage)) {
+ PendingBindingObserverList bindingObservers;
+ if (bd->notifyObserver_helper(this, storage, observer, bindingObservers)
+ == QtPrivate::QPropertyBindingData::Evaluated) {
+ // evaluateBindings() can trash the observers. We need to re-fetch here.
+ if (QPropertyObserverPointer observer = d.firstObserver())
+ observer.notify(this);
+ for (auto&& bindingObserver: bindingObservers)
+ bindingObserver.binding()->notifyNonRecursive();
+ }
+ }
+ }
+ }
+ }
+ if constexpr (!std::is_null_pointer_v<decltype(Signal)>) {
+ if constexpr (SignalTakesValue::value)
+ (owner()->*Signal)(getPropertyValue(this));
+ else
+ (owner()->*Signal)();
+ }
+ }
+
+ QPropertyBinding<T> binding() const
+ {
+ auto *bd = qGetBindingStorage(owner())->bindingData(this);
+ return static_cast<QPropertyBinding<T> &&>(QUntypedPropertyBinding(bd ? bd->binding() : nullptr));
+ }
+
+ QPropertyBinding<T> takeBinding()
+ {
+ return setBinding(QPropertyBinding<T>());
+ }
+
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> onValueChanged(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyChangeHandler<Functor>(*this, f);
+ }
+
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> subscribe(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ f();
+ return onValueChanged(f);
+ }
+
+ template<typename Functor>
+ QPropertyNotifier addNotifier(Functor f)
+ {
+ static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters");
+ return QPropertyNotifier(*this, f);
+ }
+
+ QtPrivate::QPropertyBindingData &bindingData() const
+ {
+ auto *storage = const_cast<QBindingStorage *>(qGetBindingStorage(owner()));
+ return *storage->bindingData(const_cast<QObjectCompatProperty *>(this), true);
+ }
+};
+
+namespace QtPrivate {
+template<typename Class, typename Ty, auto Offset, auto Setter, auto Signal, auto Getter>
+class QBindableInterfaceForProperty<
+ QObjectCompatProperty<Class, Ty, Offset, Setter, Signal, Getter>, std::void_t<Class>>
+{
+ using Property = QObjectCompatProperty<Class, Ty, Offset, Setter, Signal, Getter>;
+ using T = typename Property::value_type;
+public:
+ static constexpr QBindableInterface iface = {
+ [](const QUntypedPropertyData *d, void *value) -> void
+ { *static_cast<T*>(value) = Property::getPropertyValue(d); },
+ [](QUntypedPropertyData *d, const void *value) -> void
+ {
+ (static_cast<Property *>(d)->owner()->*Setter)(*static_cast<const T*>(value));
+ },
+ [](const QUntypedPropertyData *d) -> QUntypedPropertyBinding
+ { return static_cast<const Property *>(d)->binding(); },
+ [](QUntypedPropertyData *d, const QUntypedPropertyBinding &binding) -> QUntypedPropertyBinding
+ { return static_cast<Property *>(d)->setBinding(static_cast<const QPropertyBinding<T> &>(binding)); },
+ [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
+ { return Qt::makePropertyBinding([d]() -> T { return Property::getPropertyValue(d); }, location); },
+ [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
+ { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
+ []() { return QMetaType::fromType<T>(); }
+ };
+};
+}
+
+#define QT_OBJECT_COMPAT_PROPERTY_4(Class, Type, name, setter) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name;
+
+#define QT_OBJECT_COMPAT_PROPERTY_5(Class, Type, name, setter, signal) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal> name;
+
+#define Q_OBJECT_COMPAT_PROPERTY(...) \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ QT_OVERLOADED_MACRO(QT_OBJECT_COMPAT_PROPERTY, __VA_ARGS__) \
+ QT_WARNING_POP
+
+#define QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS_5(Class, Type, name, setter, value) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name = \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter>( \
+ value);
+
+#define QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS_6(Class, Type, name, setter, signal, value) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal> name = \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, \
+ signal>(value);
+
+#define QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS_7(Class, Type, name, setter, signal, getter, value) \
+ static constexpr size_t _qt_property_##name##_offset() { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, name); \
+ QT_WARNING_POP \
+ } \
+ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal, getter>\
+ name = QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, \
+ signal, getter>(value);
+
+#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(...) \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ QT_OVERLOADED_MACRO(QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS, __VA_ARGS__) \
+ QT_WARNING_POP
+
+
+namespace QtPrivate {
+Q_CORE_EXPORT BindingEvaluationState *suspendCurrentBindingStatus();
+Q_CORE_EXPORT void restoreBindingStatus(BindingEvaluationState *status);
+}
+
+struct QUntypedBindablePrivate
+{
+ static QtPrivate::QBindableInterface const *getInterface(const QUntypedBindable &bindable)
+ {
+ return bindable.iface;
+ }
+
+ static QUntypedPropertyData *getPropertyData(const QUntypedBindable &bindable)
+ {
+ return bindable.data;
+ }
+};
+
+inline bool QPropertyBindingPrivate::evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
+{
+ if (updating) {
+ error = QPropertyBindingError(QPropertyBindingError::BindingLoop);
+ if (isQQmlPropertyBinding)
+ errorCallBack(this);
+ return false;
+ }
+
+ /*
+ * Evaluating the binding might lead to the binding being broken. This can
+ * cause ref to reach zero at the end of the function. However, the
+ * updateGuard's destructor will then still trigger, trying to set the
+ * updating bool to its old value
+ * To prevent this, we create a QPropertyBindingPrivatePtr which ensures
+ * that the object is still alive when updateGuard's dtor runs.
+ */
+ QPropertyBindingPrivatePtr keepAlive {this};
+
+ QScopedValueRollback<bool> updateGuard(updating, true);
+
+ QtPrivate::BindingEvaluationState evaluationFrame(this, status);
+
+ auto bindingFunctor = reinterpret_cast<std::byte *>(this) +
+ QPropertyBindingPrivate::getSizeEnsuringAlignment();
+ bool changed = false;
+ if (hasBindingWrapper) {
+ changed = staticBindingWrapper(metaType, propertyDataPtr,
+ {vtable, bindingFunctor});
+ } else {
+ changed = vtable->call(metaType, propertyDataPtr, bindingFunctor);
+ }
+ // If there was a change, we must set pendingNotify.
+ // If there was not, we must not clear it, as that only should happen in notifyRecursive
+ pendingNotify = pendingNotify || changed;
+ if (!changed || !firstObserver)
+ return changed;
+
+ firstObserver.noSelfDependencies(this);
+ firstObserver.evaluateBindings(bindingObservers, status);
+ return true;
+}
+
+/*!
+ \internal
+
+ Walks through the list of property observers, and calls any ChangeHandler
+ found there.
+ It doesn't do anything with bindings, which are only handled in
+ QPropertyBindingPrivate::evaluateRecursive.
+ */
+inline void QPropertyObserverPointer::notify(QUntypedPropertyData *propertyDataPtr)
+{
+ auto observer = const_cast<QPropertyObserver*>(ptr);
+ /*
+ * The basic idea of the loop is as follows: We iterate over all observers in the linked list,
+ * and execute the functionality corresponding to their tag.
+ * However, complication arise due to the fact that the triggered operations might modify the list,
+ * which includes deletion and move of the current and next nodes.
+ * Therefore, we take a few safety precautions:
+ * 1. Before executing any action which might modify the list, we insert a placeholder node after the current node.
+ * As that one is stack allocated and owned by us, we can rest assured that it is
+ * still there after the action has executed, and placeHolder->next points to the actual next node in the list.
+ * Note that taking next at the beginning of the loop does not work, as the executed action might either move
+ * or delete that node.
+ * 2. After the triggered action has finished, we can use the next pointer in the placeholder node as a safe way to
+ * retrieve the next node.
+ * 3. Some care needs to be taken to avoid infinite recursion with change handlers, so we add an extra test there, that
+ * checks whether we're already have the same change handler in our call stack. This can be done by checking whether
+ * the node after the current one is a placeholder node.
+ */
+ while (observer) {
+ QPropertyObserver *next = observer->next.data();
+ switch (QPropertyObserver::ObserverTag(observer->next.tag())) {
+ case QPropertyObserver::ObserverNotifiesChangeHandler:
+ {
+ auto handlerToCall = observer->changeHandler;
+ // prevent recursion
+ if (next && next->next.tag() == QPropertyObserver::ObserverIsPlaceholder) {
+ observer = next->next.data();
+ continue;
+ }
+ // handlerToCall might modify the list
+ QPropertyObserverNodeProtector protector(observer);
+ handlerToCall(observer, propertyDataPtr);
+ next = protector.next();
+ break;
+ }
+ case QPropertyObserver::ObserverNotifiesBinding:
+ break;
+ case QPropertyObserver::ObserverIsPlaceholder:
+ // recursion is already properly handled somewhere else
+ break;
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ case QPropertyObserver::ObserverIsAlias:
+ break;
+ QT_WARNING_POP
+#endif
+ default: Q_UNREACHABLE();
+ }
+ observer = next;
+ }
+}
+
+inline QPropertyObserverNodeProtector::~QPropertyObserverNodeProtector()
+{
+ QPropertyObserverPointer d{static_cast<QPropertyObserver *>(&m_placeHolder)};
+ d.unlink_fast();
+}
+
+QBindingObserverPtr::QBindingObserverPtr(QPropertyObserver *observer) noexcept : d(observer)
+{
+ Q_ASSERT(d);
+ QPropertyObserverPointer{d}.binding()->addRef();
+}
+
+QBindingObserverPtr::~QBindingObserverPtr()
+{
+ if (!d)
+ return;
+
+ QPropertyBindingPrivate *bindingPrivate = binding();
+ if (!bindingPrivate->deref())
+ QPropertyBindingPrivate::destroyAndFreeMemory(bindingPrivate);
+}
+
+QPropertyBindingPrivate *QBindingObserverPtr::binding() const noexcept { return QPropertyObserverPointer{d}.binding(); }
+
+QPropertyObserver *QBindingObserverPtr::operator->() { return d; }
+
+namespace QtPrivate {
+class QPropertyAdaptorSlotObject : public QUntypedPropertyData, public QSlotObjectBase
+{
+ QPropertyBindingData bindingData_;
+ QObject *obj;
+ QMetaProperty metaProperty_;
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret);
+#else
+ static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret);
+#endif
+
+ QPropertyAdaptorSlotObject(QObject *o, const QMetaProperty& p);
+
+public:
+ static QPropertyAdaptorSlotObject *cast(QSlotObjectBase *ptr, int propertyIndex)
+ {
+ if (ptr->isImpl(&QPropertyAdaptorSlotObject::impl)) {
+ auto p = static_cast<QPropertyAdaptorSlotObject *>(ptr);
+ if (p->metaProperty_.propertyIndex() == propertyIndex)
+ return p;
+ }
+ return nullptr;
+ }
+
+ inline const QPropertyBindingData &bindingData() const { return bindingData_; }
+ inline QPropertyBindingData &bindingData() { return bindingData_; }
+ inline QObject *object() const { return obj; }
+ inline const QMetaProperty &metaProperty() const { return metaProperty_; }
+
+ friend class QT_PREPEND_NAMESPACE(QUntypedBindable);
};
+}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpropertybinding.cpp b/src/corelib/kernel/qpropertybinding.cpp
deleted file mode 100644
index 8602ef957f..0000000000
--- a/src/corelib/kernel/qpropertybinding.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qpropertybinding_p.h"
-#include "qproperty_p.h"
-
-#include <QScopedValueRollback>
-#include <QVariant>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QtPrivate;
-
-QPropertyBindingPrivate::~QPropertyBindingPrivate()
-{
- if (firstObserver)
- firstObserver.unlink();
- if (!hasStaticObserver)
- inlineDependencyObservers.~ObserverArray(); // Explicit because of union.
-}
-
-void QPropertyBindingPrivate::unlinkAndDeref()
-{
- propertyDataPtr = nullptr;
- if (!ref.deref())
- delete this;
-}
-
-void QPropertyBindingPrivate::markDirtyAndNotifyObservers()
-{
- if (dirty)
- return;
- dirty = true;
- if (firstObserver)
- firstObserver.notify(this, propertyDataPtr);
- if (hasStaticObserver) {
- if (metaType == QMetaType::fromType<bool>()) {
- auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
- bool oldValue = propertyPtr->extraBit();
- staticObserverCallback(staticObserver, &oldValue);
- } else {
- staticObserverCallback(staticObserver, propertyDataPtr);
- }
- }
-}
-
-bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged()
-{
- if (!dirty)
- return false;
-
- if (updating) {
- error = QPropertyBindingError(QPropertyBindingError::BindingLoop);
- return false;
- }
-
- /*
- * Evaluating the binding might lead to the binding being broken. This can
- * cause ref to reach zero at the end of the function. However, the
- * updateGuard's destructor will then still trigger, trying to set the
- * updating bool to its old value
- * To prevent this, we create a QPropertyBindingPrivatePtr which ensures
- * that the object is still alive when updateGuard's dtor runs.
- */
- QPropertyBindingPrivatePtr keepAlive {this};
- QScopedValueRollback<bool> updateGuard(updating, true);
-
- BindingEvaluationState evaluationFrame(this);
-
- QPropertyBindingError evalError;
- QUntypedPropertyBinding::BindingEvaluationResult result;
- bool changed = false;
- if (metaType.id() == QMetaType::Bool) {
- auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
- bool newValue = false;
- evalError = evaluationFunction(metaType, &newValue);
- if (evalError.type() == QPropertyBindingError::NoError) {
- bool updateAllowed = true;
- if (hasStaticObserver && staticGuardCallback)
- updateAllowed = staticGuardCallback(staticObserver, &newValue);
- if (updateAllowed && propertyPtr->extraBit() != newValue) {
- propertyPtr->setExtraBit(newValue);
- changed = true;
- }
- }
- } else {
- QVariant resultVariant(metaType.id(), nullptr);
- evalError = evaluationFunction(metaType, resultVariant.data());
- if (evalError.type() == QPropertyBindingError::NoError) {
- int compareResult = 0;
- bool updateAllowed = true;
- if (hasStaticObserver && staticGuardCallback)
- updateAllowed = staticGuardCallback(staticObserver, resultVariant.data());
- if (updateAllowed && (!QMetaType::compare(propertyDataPtr, resultVariant.constData(), metaType.id(), &compareResult) || compareResult != 0)) {
- changed = true;
- metaType.destruct(propertyDataPtr);
- metaType.construct(propertyDataPtr, resultVariant.constData());
- }
- }
- }
-
- if (evalError.type() != QPropertyBindingError::NoError)
- error = evalError;
-
- dirty = false;
- return changed;
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding() = default;
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction function,
- const QPropertyBindingSourceLocation &location)
-{
- d = new QPropertyBindingPrivate(metaType, std::move(function), std::move(location));
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(QUntypedPropertyBinding &&other)
- : d(std::move(other.d))
-{
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(const QUntypedPropertyBinding &other)
- : d(other.d)
-{
-}
-
-QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(const QUntypedPropertyBinding &other)
-{
- d = other.d;
- return *this;
-}
-
-QUntypedPropertyBinding &QUntypedPropertyBinding::operator=(QUntypedPropertyBinding &&other)
-{
- d = std::move(other.d);
- return *this;
-}
-
-QUntypedPropertyBinding::QUntypedPropertyBinding(QPropertyBindingPrivate *priv)
- : d(priv)
-{
-}
-
-QUntypedPropertyBinding::~QUntypedPropertyBinding()
-{
-}
-
-bool QUntypedPropertyBinding::isNull() const
-{
- return !d;
-}
-
-QPropertyBindingError QUntypedPropertyBinding::error() const
-{
- if (!d)
- return QPropertyBindingError();
- return d->bindingError();
-}
-
-QMetaType QUntypedPropertyBinding::valueMetaType() const
-{
- if (!d)
- return QMetaType();
- return d->valueMetaType();
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qpropertybinding_p.h b/src/corelib/kernel/qpropertybinding_p.h
deleted file mode 100644
index 151f5543d5..0000000000
--- a/src/corelib/kernel/qpropertybinding_p.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPROPERTYBINDING_P_H
-#define QPROPERTYBINDING_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qshareddata.h>
-#include <QtCore/qscopedpointer.h>
-#include <vector>
-#include <functional>
-
-#include "qproperty_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class Q_CORE_EXPORT QPropertyBindingPrivate : public QSharedData
-{
-private:
- friend struct QPropertyBasePointer;
-
- using ObserverArray = std::array<QPropertyObserver, 4>;
-
- // QSharedData is 4 bytes. Use the padding for the bools as we need 8 byte alignment below.
- bool dirty = false;
- bool updating = false;
- bool hasStaticObserver = false;
-
- QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction;
-
- QPropertyObserverPointer firstObserver;
- union {
- ObserverArray inlineDependencyObservers;
- struct {
- void *staticObserver;
- void (*staticObserverCallback)(void*, void*);
- bool (*staticGuardCallback)(void*, void*);
- };
- };
- QScopedPointer<std::vector<QPropertyObserver>> heapObservers;
-
- void *propertyDataPtr = nullptr;
-
- QPropertyBindingSourceLocation location;
- QPropertyBindingError error;
-
- QMetaType metaType;
-
-public:
- // public because the auto-tests access it, too.
- size_t dependencyObserverCount = 0;
-
- QPropertyBindingPrivate(const QMetaType &metaType, QUntypedPropertyBinding::BindingEvaluationFunction evaluationFunction,
- const QPropertyBindingSourceLocation &location)
- : evaluationFunction(std::move(evaluationFunction))
- , inlineDependencyObservers() // Explicit initialization required because of union
- , location(location)
- , metaType(metaType)
- {}
- virtual ~QPropertyBindingPrivate();
-
- void setDirty(bool d) { dirty = d; }
- void setProperty(void *propertyPtr) { propertyDataPtr = propertyPtr; }
- void setStaticObserver(void *observer, void (*callback)(void*, void*), bool (*guardCallback)(void *, void*))
- {
- if (observer) {
- if (!hasStaticObserver) {
- if (dependencyObserverCount > 0) {
- if (!heapObservers)
- heapObservers.reset(new std::vector<QPropertyObserver>());
- for (int i = 0, end = qMin(dependencyObserverCount, inlineDependencyObservers.size()); i < end; ++i)
- heapObservers->push_back(std::move(inlineDependencyObservers[i]));
- }
- inlineDependencyObservers.~ObserverArray();
- }
-
- hasStaticObserver = true;
- staticObserver = observer;
- staticObserverCallback = callback;
- staticGuardCallback = guardCallback;
- } else if (hasStaticObserver) {
- hasStaticObserver = false;
- new (&inlineDependencyObservers) ObserverArray();
- for (int i = 0, end = qMin(dependencyObserverCount, inlineDependencyObservers.size()); i < end; ++i) {
- inlineDependencyObservers[i] = std::move(heapObservers->back());
- heapObservers->pop_back();
- }
- }
- }
- void prependObserver(QPropertyObserverPointer observer) {
- observer.ptr->prev = const_cast<QPropertyObserver **>(&firstObserver.ptr);
- firstObserver = observer;
- }
-
- QPropertyObserverPointer takeObservers()
- {
- auto observers = firstObserver;
- firstObserver.ptr = nullptr;
- return observers;
- }
-
- void clearDependencyObservers() {
- if (!hasStaticObserver) {
- for (size_t i = 0; i < inlineDependencyObservers.size(); ++i) {
- QPropertyObserver empty;
- qSwap(inlineDependencyObservers[i], empty);
- }
- }
- if (heapObservers)
- heapObservers->clear();
- dependencyObserverCount = 0;
- }
- QPropertyObserverPointer allocateDependencyObserver() {
- if (!hasStaticObserver && dependencyObserverCount < inlineDependencyObservers.size()) {
- ++dependencyObserverCount;
- return {&inlineDependencyObservers[dependencyObserverCount - 1]};
- }
- ++dependencyObserverCount;
- if (!heapObservers)
- heapObservers.reset(new std::vector<QPropertyObserver>());
- return {&heapObservers->emplace_back()};
- }
-
- QPropertyBindingSourceLocation sourceLocation() const { return location; }
- QPropertyBindingError bindingError() const { return error; }
- QMetaType valueMetaType() const { return metaType; }
-
- void unlinkAndDeref();
-
- void markDirtyAndNotifyObservers();
- bool evaluateIfDirtyAndReturnTrueIfValueChanged();
-
- static QPropertyBindingPrivate *get(const QUntypedPropertyBinding &binding)
- { return binding.d.data(); }
-};
-
-QT_END_NAMESPACE
-
-#endif // QPROPERTYBINDING_P_H
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index 145f2c66b9..a8456721d0 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROPERTYPRIVATE_H
#define QPROPERTYPRIVATE_H
@@ -44,132 +8,323 @@
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qglobal.h>
-#include <QtCore/QExplicitlySharedDataPointer>
#include <QtCore/qtaggedpointer.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qcontainerfwd.h>
+
+#include <functional>
QT_BEGIN_NAMESPACE
-class QUntypedPropertyBinding;
-class QPropertyBindingPrivate;
-using QPropertyBindingPrivatePtr = QExplicitlySharedDataPointer<QPropertyBindingPrivate>;
-struct QPropertyBasePointer;
+class QBindingStorage;
+
+template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
+class QObjectCompatProperty;
+
+struct QBindingObserverPtr;
+using PendingBindingObserverList = QVarLengthArray<QBindingObserverPtr>;
namespace QtPrivate {
+// QPropertyBindingPrivatePtr operates on a RefCountingMixin solely so that we can inline
+// the constructor and copy constructor
+struct RefCounted {
+
+ int refCount() const { return ref; }
+ void addRef() { ++ref; }
+ bool deref() { return --ref != 0; }
-class Q_CORE_EXPORT QPropertyBase
+private:
+ int ref = 0;
+};
+}
+
+class QQmlPropertyBinding;
+class QPropertyBindingPrivate;
+class QPropertyBindingPrivatePtr
{
- // Mutable because the address of the observer of the currently evaluating binding is stored here, for
- // notification later when the value changes.
- mutable quintptr d_ptr = 0;
- friend struct QT_PREPEND_NAMESPACE(QPropertyBasePointer);
public:
- QPropertyBase() = default;
- Q_DISABLE_COPY(QPropertyBase)
- QPropertyBase(QPropertyBase &&other) = delete;
- QPropertyBase(QPropertyBase &&other, void *propertyDataPtr);
- QPropertyBase &operator=(QPropertyBase &&other) = delete;
- ~QPropertyBase();
+ using T = QtPrivate::RefCounted;
+ T &operator*() const { return *d; }
+ T *operator->() noexcept { return d; }
+ T *operator->() const noexcept { return d; }
+ explicit operator T *() { return d; }
+ explicit operator const T *() const noexcept { return d; }
+ T *data() const noexcept { return d; }
+ T *get() const noexcept { return d; }
+ const T *constData() const noexcept { return d; }
+ T *take() noexcept { T *x = d; d = nullptr; return x; }
+
+ QPropertyBindingPrivatePtr() noexcept : d(nullptr) { }
+ ~QPropertyBindingPrivatePtr()
+ {
+ if (d && !d->deref())
+ destroyAndFreeMemory();
+ }
+ Q_CORE_EXPORT void destroyAndFreeMemory();
- void moveAssign(QPropertyBase &&other, void *propertyDataPtr);
+ explicit QPropertyBindingPrivatePtr(T *data) noexcept : d(data) { if (d) d->addRef(); }
+ QPropertyBindingPrivatePtr(const QPropertyBindingPrivatePtr &o) noexcept
+ : d(o.d) { if (d) d->addRef(); }
- bool hasBinding() const { return d_ptr & BindingBit; }
+ void reset(T *ptr = nullptr) noexcept;
- QUntypedPropertyBinding setBinding(const QUntypedPropertyBinding &newBinding,
- void *propertyDataPtr, void *staticObserver = nullptr,
- void (*staticObserverCallback)(void *, void *) = nullptr,
- bool (*guardCallback)(void *, void *) = nullptr);
- QPropertyBindingPrivate *binding();
+ QPropertyBindingPrivatePtr &operator=(const QPropertyBindingPrivatePtr &o) noexcept
+ {
+ reset(o.d);
+ return *this;
+ }
+ QPropertyBindingPrivatePtr &operator=(T *o) noexcept
+ {
+ reset(o);
+ return *this;
+ }
+ QPropertyBindingPrivatePtr(QPropertyBindingPrivatePtr &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPropertyBindingPrivatePtr)
- void evaluateIfDirty();
- void removeBinding();
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
- void registerWithCurrentlyEvaluatingBinding() const;
- void notifyObservers(void *propertyDataPtr);
+ void swap(QPropertyBindingPrivatePtr &other) noexcept
+ { qt_ptr_swap(d, other.d); }
- void setExtraBit(bool b)
- {
- if (b)
- d_ptr |= ExtraBit;
- else
- d_ptr &= ~ExtraBit;
- }
+private:
+ friend bool comparesEqual(const QPropertyBindingPrivatePtr &lhs,
+ const QPropertyBindingPrivatePtr &rhs) noexcept
+ { return lhs.d == rhs.d; }
+ Q_DECLARE_EQUALITY_COMPARABLE(QPropertyBindingPrivatePtr)
+ friend bool comparesEqual(const QPropertyBindingPrivatePtr &lhs,
+ const T *rhs) noexcept
+ { return lhs.d == rhs; }
+ Q_DECLARE_EQUALITY_COMPARABLE(QPropertyBindingPrivatePtr, T*)
+ friend bool comparesEqual(const QPropertyBindingPrivatePtr &lhs,
+ std::nullptr_t) noexcept
+ { return !lhs; }
+ Q_DECLARE_EQUALITY_COMPARABLE(QPropertyBindingPrivatePtr, std::nullptr_t)
+
+ QtPrivate::RefCounted *d;
+};
- bool extraBit() const { return d_ptr & ExtraBit; }
+class QUntypedPropertyBinding;
+class QPropertyBindingPrivate;
+struct QPropertyBindingDataPointer;
+class QPropertyObserver;
+struct QPropertyObserverPointer;
- static const quintptr ExtraBit = 0x1; // Used for QProperty<bool> specialization
- static const quintptr BindingBit = 0x2; // Is d_ptr pointing to a binding (1) or list of notifiers (0)?
- static const quintptr FlagMask = BindingBit | ExtraBit;
+class QUntypedPropertyData
+{
};
+namespace QtPrivate {
+template <typename T>
+using IsUntypedPropertyData = std::enable_if_t<std::is_base_of_v<QUntypedPropertyData, T>, bool>;
+}
+
template <typename T>
-struct QPropertyValueStorage
+class QPropertyData;
+
+// Used for grouped property evaluations
+namespace QtPrivate {
+class QPropertyBindingData;
+}
+struct QPropertyDelayedNotifications;
+struct QPropertyProxyBindingData
{
-private:
- T value;
-public:
- QPropertyBase priv;
+ // acts as QPropertyBindingData::d_ptr
+ quintptr d_ptr;
+ /*
+ The two members below store the original binding data and property
+ data pointer of the property which gets proxied.
+ They are set in QPropertyDelayedNotifications::addProperty
+ */
+ const QtPrivate::QPropertyBindingData *originalBindingData;
+ QUntypedPropertyData *propertyData;
+};
- QPropertyValueStorage() : value() {}
- Q_DISABLE_COPY(QPropertyValueStorage)
- explicit QPropertyValueStorage(const T &initialValue) : value(initialValue) {}
- QPropertyValueStorage &operator=(const T &newValue) { value = newValue; return *this; }
- explicit QPropertyValueStorage(T &&initialValue) : value(std::move(initialValue)) {}
- QPropertyValueStorage &operator=(T &&newValue) { value = std::move(newValue); return *this; }
- QPropertyValueStorage(QPropertyValueStorage &&other) : value(std::move(other.value)), priv(std::move(other.priv), this) {}
- QPropertyValueStorage &operator=(QPropertyValueStorage &&other) { value = std::move(other.value); priv.moveAssign(std::move(other.priv), &value); return *this; }
+namespace QtPrivate {
+struct BindingEvaluationState;
- T getValue() const { return value; }
- bool setValueAndReturnTrueIfChanged(T &&v)
- {
- if (v == value)
- return false;
- value = std::move(v);
- return true;
- }
- bool setValueAndReturnTrueIfChanged(const T &v)
+/* used in BindingFunctionVTable::createFor; on all other compilers, void would work, but on
+ MSVC this causes C2182 when compiling in C++20 mode. As we only need to provide some default
+ value which gets ignored, we introduce this dummy type.
+*/
+struct MSVCWorkAround {};
+
+struct BindingFunctionVTable
+{
+ using CallFn = bool(*)(QMetaType, QUntypedPropertyData *, void *);
+ using DtorFn = void(*)(void *);
+ using MoveCtrFn = void(*)(void *, void *);
+ const CallFn call;
+ const DtorFn destroy;
+ const MoveCtrFn moveConstruct;
+ const qsizetype size;
+
+ template<typename Callable, typename PropertyType=MSVCWorkAround>
+ static constexpr BindingFunctionVTable createFor()
{
- if (v == value)
- return false;
- value = v;
- return true;
+ static_assert (alignof(Callable) <= alignof(std::max_align_t), "Bindings do not support overaligned functors!");
+ return {
+ /*call=*/[](QMetaType metaType, QUntypedPropertyData *dataPtr, void *f){
+ if constexpr (!std::is_invocable_v<Callable>) {
+ // we got an untyped callable
+ static_assert (std::is_invocable_r_v<bool, Callable, QMetaType, QUntypedPropertyData *> );
+ auto untypedEvaluationFunction = static_cast<Callable *>(f);
+ return std::invoke(*untypedEvaluationFunction, metaType, dataPtr);
+ } else if constexpr (!std::is_same_v<PropertyType, MSVCWorkAround>) {
+ Q_UNUSED(metaType);
+ QPropertyData<PropertyType> *propertyPtr = static_cast<QPropertyData<PropertyType> *>(dataPtr);
+ // That is allowed by POSIX even if Callable is a function pointer
+ auto evaluationFunction = static_cast<Callable *>(f);
+ PropertyType newValue = std::invoke(*evaluationFunction);
+ if constexpr (QTypeTraits::has_operator_equal_v<PropertyType>) {
+ if (newValue == propertyPtr->valueBypassingBindings())
+ return false;
+ }
+ propertyPtr->setValueBypassingBindings(std::move(newValue));
+ return true;
+ } else {
+ // Our code will never instantiate this
+ Q_UNREACHABLE_RETURN(false);
+ }
+ },
+ /*destroy*/[](void *f){ static_cast<Callable *>(f)->~Callable(); },
+ /*moveConstruct*/[](void *addr, void *other){
+ new (addr) Callable(std::move(*static_cast<Callable *>(other)));
+ },
+ /*size*/sizeof(Callable)
+ };
}
};
-template<>
-struct QPropertyValueStorage<bool>
+template<typename Callable, typename PropertyType=MSVCWorkAround>
+inline constexpr BindingFunctionVTable bindingFunctionVTable = BindingFunctionVTable::createFor<Callable, PropertyType>();
+
+
+// writes binding result into dataPtr
+struct QPropertyBindingFunction {
+ const QtPrivate::BindingFunctionVTable *vtable;
+ void *functor;
+};
+
+using QPropertyObserverCallback = void (*)(QUntypedPropertyData *);
+using QPropertyBindingWrapper = bool(*)(QMetaType, QUntypedPropertyData *dataPtr, QPropertyBindingFunction);
+
+/*!
+ \internal
+ A property normally consists of the actual property value and metadata for the binding system.
+ QPropertyBindingData is the latter part. It stores a pointer to either
+ - a (potentially empty) linked list of notifiers, in case there is no binding set,
+ - an actual QUntypedPropertyBinding when the property has a binding,
+ - or a pointer to QPropertyProxyBindingData when notifications occur inside a grouped update.
+
+ \sa QPropertyDelayedNotifications, beginPropertyUpdateGroup
+ */
+class Q_CORE_EXPORT QPropertyBindingData
{
- QPropertyBase priv;
+ // Mutable because the address of the observer of the currently evaluating binding is stored here, for
+ // notification later when the value changes.
+ mutable quintptr d_ptr = 0;
+ friend struct QT_PREPEND_NAMESPACE(QPropertyBindingDataPointer);
+ friend class QT_PREPEND_NAMESPACE(QQmlPropertyBinding);
+ friend struct QT_PREPEND_NAMESPACE(QPropertyDelayedNotifications);
+
+ template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
+ friend class QT_PREPEND_NAMESPACE(QObjectCompatProperty);
+
+ Q_DISABLE_COPY(QPropertyBindingData)
+public:
+ QPropertyBindingData() = default;
+ QPropertyBindingData(QPropertyBindingData &&other);
+ QPropertyBindingData &operator=(QPropertyBindingData &&other) = delete;
+ ~QPropertyBindingData();
+
+ // Is d_ptr pointing to a binding (1) or list of notifiers (0)?
+ static inline constexpr quintptr BindingBit = 0x1;
+ // Is d_ptr pointing to QPropertyProxyBindingData (1) or to an actual binding/list of notifiers?
+ static inline constexpr quintptr DelayedNotificationBit = 0x2;
+
+ bool hasBinding() const { return d_ptr & BindingBit; }
+ bool isNotificationDelayed() const { return d_ptr & DelayedNotificationBit; }
+
+ QUntypedPropertyBinding setBinding(const QUntypedPropertyBinding &newBinding,
+ QUntypedPropertyData *propertyDataPtr,
+ QPropertyObserverCallback staticObserverCallback = nullptr,
+ QPropertyBindingWrapper bindingWrapper = nullptr);
- QPropertyValueStorage() = default;
- Q_DISABLE_COPY(QPropertyValueStorage)
- explicit QPropertyValueStorage(bool initialValue) { priv.setExtraBit(initialValue); }
- QPropertyValueStorage &operator=(bool newValue) { priv.setExtraBit(newValue); return *this; }
- QPropertyValueStorage(QPropertyValueStorage &&other) : priv(std::move(other.priv), this) {}
- QPropertyValueStorage &operator=(QPropertyValueStorage &&other) { priv.moveAssign(std::move(other.priv), this); return *this; }
+ QPropertyBindingPrivate *binding() const
+ {
+ quintptr dd = d();
+ if (dd & BindingBit)
+ return reinterpret_cast<QPropertyBindingPrivate*>(dd - BindingBit);
+ return nullptr;
+
+ }
+
+ void evaluateIfDirty(const QUntypedPropertyData *) const; // ### Kept for BC reasons, unused
+
+ void removeBinding()
+ {
+ if (hasBinding())
+ removeBinding_helper();
+ }
- bool getValue() const { return priv.extraBit(); }
- bool setValueAndReturnTrueIfChanged(bool v)
+ void registerWithCurrentlyEvaluatingBinding(QtPrivate::BindingEvaluationState *currentBinding) const
+ {
+ if (!currentBinding)
+ return;
+ registerWithCurrentlyEvaluatingBinding_helper(currentBinding);
+ }
+ void registerWithCurrentlyEvaluatingBinding() const;
+ void notifyObservers(QUntypedPropertyData *propertyDataPtr) const;
+ void notifyObservers(QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage) const;
+private:
+ /*!
+ \internal
+ Returns a reference to d_ptr, except when d_ptr points to a proxy.
+ In that case, a reference to proxy->d_ptr is returned instead.
+
+ To properly support proxying, direct access to d_ptr only occurs when
+ - a function actually deals with proxying (e.g.
+ QPropertyDelayedNotifications::addProperty),
+ - only the tag value is accessed (e.g. hasBinding) or
+ - inside a constructor.
+ */
+ quintptr &d_ref() const
+ {
+ quintptr &d = d_ptr;
+ if (isNotificationDelayed())
+ return proxyData()->d_ptr;
+ return d;
+ }
+ quintptr d() const { return d_ref(); }
+ QPropertyProxyBindingData *proxyData() const
{
- if (v == priv.extraBit())
- return false;
- priv.setExtraBit(v);
- return true;
+ Q_ASSERT(isNotificationDelayed());
+ return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit));
}
+ void registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentBinding) const;
+ void removeBinding_helper();
+
+ enum NotificationResult { Delayed, Evaluated };
+ NotificationResult notifyObserver_helper(
+ QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage,
+ QPropertyObserverPointer observer,
+ PendingBindingObserverList &bindingObservers) const;
};
template <typename T, typename Tag>
class QTagPreservingPointerToPointer
{
public:
- QTagPreservingPointerToPointer() = default;
+ constexpr QTagPreservingPointerToPointer() = default;
QTagPreservingPointerToPointer(T **ptr)
: d(reinterpret_cast<quintptr*>(ptr))
@@ -177,13 +332,13 @@ public:
QTagPreservingPointerToPointer<T, Tag> &operator=(T **ptr)
{
- d = reinterpret_cast<quintptr*>(ptr);
+ d = reinterpret_cast<quintptr *>(ptr);
return *this;
}
QTagPreservingPointerToPointer<T, Tag> &operator=(QTaggedPointer<T, Tag> *ptr)
{
- d = reinterpret_cast<quintptr*>(ptr);
+ d = reinterpret_cast<quintptr *>(ptr);
return *this;
}
@@ -194,7 +349,7 @@ public:
void setPointer(T *ptr)
{
- *d = (reinterpret_cast<quintptr>(ptr) & QTaggedPointer<T, Tag>::pointerMask()) | (*d & QTaggedPointer<T, Tag>::tagMask());
+ *d = reinterpret_cast<quintptr>(ptr) | (*d & QTaggedPointer<T, Tag>::tagMask());
}
T *get() const
@@ -211,6 +366,23 @@ private:
quintptr *d = nullptr;
};
+namespace detail {
+ template <typename F>
+ struct ExtractClassFromFunctionPointer;
+
+ template<typename T, typename C>
+ struct ExtractClassFromFunctionPointer<T C::*> { using Class = C; };
+
+ constexpr size_t getOffset(size_t o)
+ {
+ return o;
+ }
+ constexpr size_t getOffset(size_t (*offsetFn)())
+ {
+ return offsetFn();
+ }
+}
+
} // namespace QtPrivate
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsequentialiterable.cpp b/src/corelib/kernel/qsequentialiterable.cpp
new file mode 100644
index 0000000000..c331f1de63
--- /dev/null
+++ b/src/corelib/kernel/qsequentialiterable.cpp
@@ -0,0 +1,215 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qsequentialiterable.h>
+#include <QtCore/qvariant.h>
+
+#include <QtCore/private/qiterable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSequentialIterable
+ \since 5.2
+ \inmodule QtCore
+ \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
+
+ This class allows several methods of accessing the values of a container held within
+ a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
+ be converted to a QVariantList.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+
+ The container itself is not copied before iterating over it.
+
+ \sa QVariant
+*/
+
+/*!
+ \typedef QSequentialIterable::RandomAccessIterator
+ Exposes an iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::BidirectionalIterator
+ Exposes an iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::ForwardIterator
+ Exposes an iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::InputIterator
+ Exposes an iterator using std::input_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::RandomAccessConstIterator
+ Exposes a const_iterator using std::random_access_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::BidirectionalConstIterator
+ Exposes a const_iterator using std::bidirectional_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::ForwardConstIterator
+ Exposes a const_iterator using std::forward_iterator_tag.
+*/
+
+/*!
+ \typedef QSequentialIterable::InputConstIterator
+ Exposes a const_iterator using std::input_iterator_tag.
+*/
+
+/*!
+ Adds \a value to the container, at \a position, if possible.
+ */
+void QSequentialIterable::addValue(const QVariant &value, Position position)
+{
+ QtPrivate::QVariantTypeCoercer coercer;
+ const void *valuePtr = coercer.coerce(value, metaContainer().valueMetaType());
+
+ switch (position) {
+ case AtBegin:
+ if (metaContainer().canAddValueAtBegin())
+ metaContainer().addValueAtBegin(mutableIterable(), valuePtr);
+ break;
+ case AtEnd:
+ if (metaContainer().canAddValueAtEnd())
+ metaContainer().addValueAtEnd(mutableIterable(), valuePtr);
+ break;
+ case Unspecified:
+ if (metaContainer().canAddValue())
+ metaContainer().addValue(mutableIterable(), valuePtr);
+ break;
+ }
+}
+
+/*!
+ Removes a value from the container, at \a position, if possible.
+ */
+void QSequentialIterable::removeValue(Position position)
+{
+ switch (position) {
+ case AtBegin:
+ if (metaContainer().canRemoveValueAtBegin())
+ metaContainer().removeValueAtBegin(mutableIterable());
+ break;
+ case AtEnd:
+ if (metaContainer().canRemoveValueAtEnd())
+ metaContainer().removeValueAtEnd(mutableIterable());
+ break;
+ case Unspecified:
+ if (metaContainer().canRemoveValue())
+ metaContainer().removeValue(mutableIterable());
+ break;
+ }
+}
+
+QMetaType QSequentialIterable::valueMetaType() const
+{
+ return QMetaType(metaContainer().valueMetaType());
+}
+
+/*!
+ Returns the value at position \a idx in the container.
+*/
+QVariant QSequentialIterable::at(qsizetype idx) const
+{
+ QVariant v(valueMetaType());
+ void *dataPtr;
+ if (valueMetaType() == QMetaType::fromType<QVariant>())
+ dataPtr = &v;
+ else
+ dataPtr = v.data();
+
+ const QMetaSequence meta = metaContainer();
+ if (meta.canGetValueAtIndex()) {
+ meta.valueAtIndex(m_iterable.constPointer(), idx, dataPtr);
+ } else if (meta.canGetValueAtConstIterator()) {
+ void *iterator = meta.constBegin(m_iterable.constPointer());
+ meta.advanceConstIterator(iterator, idx);
+ meta.valueAtConstIterator(iterator, dataPtr);
+ meta.destroyConstIterator(iterator);
+ }
+
+ return v;
+}
+
+/*!
+ Sets the element at position \a idx in the container to \a value.
+*/
+void QSequentialIterable::set(qsizetype idx, const QVariant &value)
+{
+ QtPrivate::QVariantTypeCoercer coercer;
+ const void *dataPtr = coercer.coerce(value, metaContainer().valueMetaType());
+
+ const QMetaSequence meta = metaContainer();
+ if (meta.canSetValueAtIndex()) {
+ meta.setValueAtIndex(m_iterable.mutablePointer(), idx, dataPtr);
+ } else if (meta.canSetValueAtIterator()) {
+ void *iterator = meta.begin(m_iterable.mutablePointer());
+ meta.advanceIterator(iterator, idx);
+ meta.setValueAtIterator(iterator, dataPtr);
+ meta.destroyIterator(iterator);
+ }
+}
+
+/*!
+ \typealias QSequentialIterable::const_iterator
+ \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
+
+ A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+
+ \snippet code/src_corelib_kernel_qvariant.cpp 9
+*/
+
+/*!
+ \typealias QSequentialIterable::iterator
+ \since 6.0
+ \brief The QSequentialIterable::iterator allows iteration over a container in a QVariant.
+
+ A QSequentialIterable::iterator can only be created by a QSequentialIterable instance,
+ and can be used in a way similar to other stl-style iterators.
+*/
+
+/*!
+ Returns the current item, converted to a QVariantRef.
+*/
+QVariantRef<QSequentialIterator> QSequentialIterator::operator*() const
+{
+ return QVariantRef<QSequentialIterator>(this);
+}
+
+/*!
+ Returns the current item, converted to a QVariantPointer.
+*/
+QVariantPointer<QSequentialIterator> QSequentialIterator::operator->() const
+{
+ return QVariantPointer<QSequentialIterator>(this);
+}
+
+/*!
+ Returns the current item, converted to a QVariant.
+*/
+QVariant QSequentialConstIterator::operator*() const
+{
+ return QIterablePrivate::retrieveElement(metaContainer().valueMetaType(), [this](void *dataPtr) {
+ metaContainer().valueAtConstIterator(constIterator(), dataPtr);
+ });
+}
+
+/*!
+ Returns the current item, converted to a QVariantConstPointer.
+*/
+QVariantConstPointer QSequentialConstIterator::operator->() const
+{
+ return QVariantConstPointer(operator*());
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsequentialiterable.h b/src/corelib/kernel/qsequentialiterable.h
new file mode 100644
index 0000000000..dac146d2ad
--- /dev/null
+++ b/src/corelib/kernel/qsequentialiterable.h
@@ -0,0 +1,155 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSEQUENTIALITERABLE_H
+#define QSEQUENTIALITERABLE_H
+
+#include <QtCore/qiterable.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QSequentialIterator : public QIterator<QMetaSequence>
+{
+public:
+ using value_type = QVariant;
+ using reference = QVariantRef<QSequentialIterator>;
+ using pointer = QVariantPointer<QSequentialIterator>;
+
+ QSequentialIterator(QIterator &&it)
+ : QIterator(std::move(it))
+ {}
+
+ QVariantRef<QSequentialIterator> operator*() const;
+ QVariantPointer<QSequentialIterator> operator->() const;
+};
+
+class Q_CORE_EXPORT QSequentialConstIterator : public QConstIterator<QMetaSequence>
+{
+public:
+ using value_type = QVariant;
+ using reference = const QVariant &;
+ using pointer = QVariantConstPointer;
+
+ QSequentialConstIterator(QConstIterator &&it)
+ : QConstIterator(std::move(it))
+ {}
+
+ QVariant operator*() const;
+ QVariantConstPointer operator->() const;
+};
+
+class Q_CORE_EXPORT QSequentialIterable : public QIterable<QMetaSequence>
+{
+public:
+ using iterator = QTaggedIterator<QSequentialIterator, void>;
+ using const_iterator = QTaggedIterator<QSequentialConstIterator, void>;
+
+ using RandomAccessIterator = QTaggedIterator<iterator, std::random_access_iterator_tag>;
+ using BidirectionalIterator = QTaggedIterator<iterator, std::bidirectional_iterator_tag>;
+ using ForwardIterator = QTaggedIterator<iterator, std::forward_iterator_tag>;
+ using InputIterator = QTaggedIterator<iterator, std::input_iterator_tag>;
+
+ using RandomAccessConstIterator = QTaggedIterator<const_iterator, std::random_access_iterator_tag>;
+ using BidirectionalConstIterator = QTaggedIterator<const_iterator, std::bidirectional_iterator_tag>;
+ using ForwardConstIterator = QTaggedIterator<const_iterator, std::forward_iterator_tag>;
+ using InputConstIterator = QTaggedIterator<const_iterator, std::input_iterator_tag>;
+
+ template<class T>
+ QSequentialIterable(const T *p)
+ : QIterable(QMetaSequence::fromContainer<T>(), p)
+ {
+ Q_UNUSED(m_revision);
+ }
+
+ template<class T>
+ QSequentialIterable(T *p)
+ : QIterable(QMetaSequence::fromContainer<T>(), p)
+ {
+ }
+
+ QSequentialIterable()
+ : QIterable(QMetaSequence(), nullptr)
+ {
+ }
+
+ template<typename Pointer>
+ QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
+ : QIterable(metaSequence, iterable)
+ {
+ }
+
+ // ### Qt7: Pass QMetaType as value rather than const ref.
+ QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
+ void *iterable)
+ : QIterable(metaSequence, metaType.alignOf(), iterable)
+ {
+ }
+
+ // ### Qt7: Pass QMetaType as value rather than const ref.
+ QSequentialIterable(const QMetaSequence &metaSequence, const QMetaType &metaType,
+ const void *iterable)
+ : QIterable(metaSequence, metaType.alignOf(), iterable)
+ {
+ }
+
+ QSequentialIterable(QIterable<QMetaSequence> &&other) : QIterable(std::move(other)) {}
+
+ QSequentialIterable &operator=(QIterable<QMetaSequence> &&other)
+ {
+ QIterable::operator=(std::move(other));
+ return *this;
+ }
+
+ const_iterator begin() const { return constBegin(); }
+ const_iterator end() const { return constEnd(); }
+
+ const_iterator constBegin() const { return const_iterator(QIterable::constBegin()); }
+ const_iterator constEnd() const { return const_iterator(QIterable::constEnd()); }
+
+ iterator mutableBegin() { return iterator(QIterable::mutableBegin()); }
+ iterator mutableEnd() { return iterator(QIterable::mutableEnd()); }
+
+ QVariant at(qsizetype idx) const;
+ void set(qsizetype idx, const QVariant &value);
+
+ enum Position { Unspecified, AtBegin, AtEnd };
+ void addValue(const QVariant &value, Position position = Unspecified);
+ void removeValue(Position position = Unspecified);
+
+ QMetaType valueMetaType() const;
+};
+
+template<>
+inline QVariantRef<QSequentialIterator>::operator QVariant() const
+{
+ if (m_pointer == nullptr)
+ return QVariant();
+ const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
+ QVariant v(metaType);
+ void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
+ m_pointer->metaContainer().valueAtIterator(m_pointer->constIterator(), dataPtr);
+ return v;
+}
+
+template<>
+inline QVariantRef<QSequentialIterator> &QVariantRef<QSequentialIterator>::operator=(
+ const QVariant &value)
+{
+ if (m_pointer == nullptr)
+ return *this;
+
+ QtPrivate::QVariantTypeCoercer coercer;
+ m_pointer->metaContainer().setValueAtIterator(
+ m_pointer->constIterator(),
+ coercer.coerce(value, m_pointer->metaContainer().valueMetaType()));
+ return *this;
+}
+
+Q_DECLARE_TYPEINFO(QSequentialIterable, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSequentialIterable::iterator, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSequentialIterable::const_iterator, Q_RELOCATABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QSEQUENTIALITERABLE_H
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
deleted file mode 100644
index 2d65e0bbe4..0000000000
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ /dev/null
@@ -1,624 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsharedmemory.h"
-#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qdir.h>
-#include <qcryptographichash.h>
-#include <qdebug.h>
-#ifdef Q_OS_WIN
-# include <qt_windows.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
-/*!
- \internal
-
- Generate a string from the key which can be any unicode string into
- the subset that the win/unix kernel allows.
-
- On Unix this will be a file name
- */
-QString
-QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
- const QString &prefix)
-{
- if (key.isEmpty())
- return QString();
-
- QString result = prefix;
-
- for (QChar ch : key) {
- if ((ch >= QLatin1Char('a') && ch <= QLatin1Char('z')) ||
- (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z')))
- result += ch;
- }
-
- QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
- result.append(QLatin1String(hex));
-#ifdef Q_OS_WIN
- return result;
-#elif defined(QT_POSIX_IPC)
- return QLatin1Char('/') + result;
-#else
- return QDir::tempPath() + QLatin1Char('/') + result;
-#endif
-}
-#endif // QT_NO_SHAREDMEMORY && QT_NO_SHAREDMEMORY
-
-#ifndef QT_NO_SHAREDMEMORY
-
-/*!
- \class QSharedMemory
- \inmodule QtCore
- \since 4.4
-
- \brief The QSharedMemory class provides access to a shared memory segment.
-
- QSharedMemory provides access to a shared memory segment by multiple
- threads and processes. It also provides a way for a single thread or
- process to lock the memory for exclusive access.
-
- When using this class, be aware of the following platform
- differences:
-
- \list
-
- \li Windows: QSharedMemory does not "own" the shared memory segment.
- When all threads or processes that have an instance of QSharedMemory
- attached to a particular shared memory segment have either destroyed
- their instance of QSharedMemory or exited, the Windows kernel
- releases the shared memory segment automatically.
-
- \li Unix: QSharedMemory "owns" the shared memory segment. When the
- last thread or process that has an instance of QSharedMemory
- attached to a particular shared memory segment detaches from the
- segment by destroying its instance of QSharedMemory, the Unix kernel
- release the shared memory segment. But if that last thread or
- process crashes without running the QSharedMemory destructor, the
- shared memory segment survives the crash.
-
- \li HP-UX: Only one attach to a shared memory segment is allowed per
- process. This means that QSharedMemory should not be used across
- multiple threads in the same process in HP-UX.
-
- \endlist
-
- Remember to lock the shared memory with lock() before reading from
- or writing to the shared memory, and remember to release the lock
- with unlock() after you are done.
-
- QSharedMemory automatically destroys the shared memory segment when
- the last instance of QSharedMemory is detached from the segment, and
- no references to the segment remain.
-
- \warning QSharedMemory changes the key in a Qt-specific way, unless otherwise
- specified. Interoperation with non-Qt applications is achieved by first creating
- a default shared memory with QSharedMemory() and then setting a native key with
- setNativeKey(). When using native keys, shared memory is not protected against
- multiple accesses on it (for example, unable to lock()) and a user-defined mechanism
- should be used to achieve such protection.
- */
-
-/*!
- \overload QSharedMemory()
-
- Constructs a shared memory object with the given \a parent. The
- shared memory object's key is not set by the constructor, so the
- shared memory object does not have an underlying shared memory
- segment attached. The key must be set with setKey() or setNativeKey()
- before create() or attach() can be used.
-
- \sa setKey()
- */
-
-#ifndef QT_NO_QOBJECT
-QSharedMemory::QSharedMemory(QObject *parent)
- : QObject(*new QSharedMemoryPrivate, parent)
-{
-}
-#else
-QSharedMemory::QSharedMemory()
- : d_ptr(new QSharedMemoryPrivate)
-{
-}
-#endif
-/*!
- Constructs a shared memory object with the given \a parent and with
- its key set to \a key. Because its key is set, its create() and
- attach() functions can be called.
-
- \sa setKey(), create(), attach()
- */
-#ifndef QT_NO_QOBJECT
-QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
- : QObject(*new QSharedMemoryPrivate, parent)
-{
- setKey(key);
-}
-#else
-QSharedMemory::QSharedMemory(const QString &key)
- : d_ptr(new QSharedMemoryPrivate)
-{
- setKey(key);
-}
-#endif
-
-/*!
- The destructor clears the key, which forces the shared memory object
- to \l {detach()} {detach} from its underlying shared memory
- segment. If this shared memory object is the last one connected to
- the shared memory segment, the detach() operation destroys the
- shared memory segment.
-
- \sa detach(), isAttached()
- */
-QSharedMemory::~QSharedMemory()
-{
- setKey(QString());
-}
-
-/*!
- Sets the platform independent \a key for this shared memory object. If \a key
- is the same as the current key, the function returns without doing anything.
-
- You can call key() to retrieve the platform independent key. Internally,
- QSharedMemory converts this key into a platform specific key. If you instead
- call nativeKey(), you will get the platform specific, converted key.
-
- If the shared memory object is attached to an underlying shared memory
- segment, it will \l {detach()} {detach} from it before setting the new key.
- This function does not do an attach().
-
- \sa key(), nativeKey(), isAttached()
-*/
-void QSharedMemory::setKey(const QString &key)
-{
- Q_D(QSharedMemory);
- if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey)
- return;
-
- if (isAttached())
- detach();
- d->cleanHandle();
- d->key = key;
- d->nativeKey = d->makePlatformSafeKey(key);
-}
-
-/*!
- \since 4.8
-
- Sets the native, platform specific, \a key for this shared memory object. If
- \a key is the same as the current native key, the function returns without
- doing anything. If all you want is to assign a key to a segment, you should
- call setKey() instead.
-
- You can call nativeKey() to retrieve the native key. If a native key has been
- assigned, calling key() will return a null string.
-
- If the shared memory object is attached to an underlying shared memory
- segment, it will \l {detach()} {detach} from it before setting the new key.
- This function does not do an attach().
-
- The application will not be portable if you set a native key.
-
- \sa nativeKey(), key(), isAttached()
-*/
-void QSharedMemory::setNativeKey(const QString &key)
-{
- Q_D(QSharedMemory);
- if (key == d->nativeKey && d->key.isNull())
- return;
-
- if (isAttached())
- detach();
- d->cleanHandle();
- d->key = QString();
- d->nativeKey = key;
-}
-
-bool QSharedMemoryPrivate::initKey()
-{
- if (!cleanHandle())
- return false;
-#ifndef QT_NO_SYSTEMSEMAPHORE
- systemSemaphore.setKey(QString(), 1);
- systemSemaphore.setKey(key, 1);
- if (systemSemaphore.error() != QSystemSemaphore::NoError) {
- QString function = QLatin1String("QSharedMemoryPrivate::initKey");
- errorString = QSharedMemory::tr("%1: unable to set key on lock").arg(function);
- switch(systemSemaphore.error()) {
- case QSystemSemaphore::PermissionDenied:
- error = QSharedMemory::PermissionDenied;
- break;
- case QSystemSemaphore::KeyError:
- error = QSharedMemory::KeyError;
- break;
- case QSystemSemaphore::AlreadyExists:
- error = QSharedMemory::AlreadyExists;
- break;
- case QSystemSemaphore::NotFound:
- error = QSharedMemory::NotFound;
- break;
- case QSystemSemaphore::OutOfResources:
- error = QSharedMemory::OutOfResources;
- break;
- case QSystemSemaphore::UnknownError:
- default:
- error = QSharedMemory::UnknownError;
- break;
- }
- return false;
- }
-#endif
- errorString = QString();
- error = QSharedMemory::NoError;
- return true;
-}
-
-/*!
- Returns the key assigned with setKey() to this shared memory, or a null key
- if no key has been assigned, or if the segment is using a nativeKey(). The
- key is the identifier used by Qt applications to identify the shared memory
- segment.
-
- You can find the native, platform specific, key used by the operating system
- by calling nativeKey().
-
- \sa setKey(), setNativeKey()
- */
-QString QSharedMemory::key() const
-{
- Q_D(const QSharedMemory);
- return d->key;
-}
-
-/*!
- \since 4.8
-
- Returns the native, platform specific, key for this shared memory object. The
- native key is the identifier used by the operating system to identify the
- shared memory segment.
-
- You can use the native key to access shared memory segments that have not
- been created by Qt, or to grant shared memory access to non-Qt applications.
-
- \sa setKey(), setNativeKey()
-*/
-QString QSharedMemory::nativeKey() const
-{
- Q_D(const QSharedMemory);
- return d->nativeKey;
-}
-
-/*!
- Creates a shared memory segment of \a size bytes with the key passed to the
- constructor, set with setKey() or set with setNativeKey(), then attaches to
- the new shared memory segment with the given access \a mode and returns
- \tt true. If a shared memory segment identified by the key already exists,
- the attach operation is not performed and \tt false is returned. When the
- return value is \tt false, call error() to determine which error occurred.
-
- \sa error()
- */
-bool QSharedMemory::create(int size, AccessMode mode)
-{
- Q_D(QSharedMemory);
-
- if (!d->initKey())
- return false;
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-#ifndef Q_OS_WIN
- // Take ownership and force set initialValue because the semaphore
- // might have already existed from a previous crash.
- d->systemSemaphore.setKey(d->key, 1, QSystemSemaphore::Create);
-#endif
-#endif
-
- QString function = QLatin1String("QSharedMemory::create");
-#ifndef QT_NO_SYSTEMSEMAPHORE
- QSharedMemoryLocker lock(this);
- if (!d->key.isNull() && !d->tryLocker(&lock, function))
- return false;
-#endif
-
- if (size <= 0) {
- d->error = QSharedMemory::InvalidSize;
- d->errorString =
- QSharedMemory::tr("%1: create size is less then 0").arg(function);
- return false;
- }
-
- if (!d->create(size))
- return false;
-
- return d->attach(mode);
-}
-
-/*!
- Returns the size of the attached shared memory segment. If no shared
- memory segment is attached, 0 is returned.
-
- \note The size of the segment may be larger than the requested size that was
- passed to create().
-
- \sa create(), attach()
- */
-int QSharedMemory::size() const
-{
- Q_D(const QSharedMemory);
- return d->size;
-}
-
-/*!
- \enum QSharedMemory::AccessMode
-
- \value ReadOnly The shared memory segment is read-only. Writing to
- the shared memory segment is not allowed. An attempt to write to a
- shared memory segment created with ReadOnly causes the program to
- abort.
-
- \value ReadWrite Reading and writing the shared memory segment are
- both allowed.
-*/
-
-/*!
- Attempts to attach the process to the shared memory segment
- identified by the key that was passed to the constructor or to a
- call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::}
- {ReadWrite} by default. It can also be \l {QSharedMemory::}
- {ReadOnly}. Returns \c true if the attach operation is successful. If
- false is returned, call error() to determine which error occurred.
- After attaching the shared memory segment, a pointer to the shared
- memory can be obtained by calling data().
-
- \sa isAttached(), detach(), create()
- */
-bool QSharedMemory::attach(AccessMode mode)
-{
- Q_D(QSharedMemory);
-
- if (isAttached() || !d->initKey())
- return false;
-#ifndef QT_NO_SYSTEMSEMAPHORE
- QSharedMemoryLocker lock(this);
- if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach")))
- return false;
-#endif
-
- if (isAttached() || !d->handle())
- return false;
-
- return d->attach(mode);
-}
-
-/*!
- Returns \c true if this process is attached to the shared memory
- segment.
-
- \sa attach(), detach()
- */
-bool QSharedMemory::isAttached() const
-{
- Q_D(const QSharedMemory);
- return (nullptr != d->memory);
-}
-
-/*!
- Detaches the process from the shared memory segment. If this was the
- last process attached to the shared memory segment, then the shared
- memory segment is released by the system, i.e., the contents are
- destroyed. The function returns \c true if it detaches the shared
- memory segment. If it returns \c false, it usually means the segment
- either isn't attached, or it is locked by another process.
-
- \sa attach(), isAttached()
- */
-bool QSharedMemory::detach()
-{
- Q_D(QSharedMemory);
- if (!isAttached())
- return false;
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
- QSharedMemoryLocker lock(this);
- if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach")))
- return false;
-#endif
-
- return d->detach();
-}
-
-/*!
- Returns a pointer to the contents of the shared memory segment, if
- one is attached. Otherwise it returns null. Remember to lock the
- shared memory with lock() before reading from or writing to the
- shared memory, and remember to release the lock with unlock() after
- you are done.
-
- \sa attach()
- */
-void *QSharedMemory::data()
-{
- Q_D(QSharedMemory);
- return d->memory;
-}
-
-/*!
- Returns a const pointer to the contents of the shared memory
- segment, if one is attached. Otherwise it returns null. Remember to
- lock the shared memory with lock() before reading from or writing to
- the shared memory, and remember to release the lock with unlock()
- after you are done.
-
- \sa attach(), create()
- */
-const void* QSharedMemory::constData() const
-{
- Q_D(const QSharedMemory);
- return d->memory;
-}
-
-/*!
- \overload data()
- */
-const void *QSharedMemory::data() const
-{
- Q_D(const QSharedMemory);
- return d->memory;
-}
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-/*!
- This is a semaphore that locks the shared memory segment for access
- by this process and returns \c true. If another process has locked the
- segment, this function blocks until the lock is released. Then it
- acquires the lock and returns \c true. If this function returns \c false,
- it means that you have ignored a false return from create() or attach(),
- that you have set the key with setNativeKey() or that
- QSystemSemaphore::acquire() failed due to an unknown system error.
-
- \sa unlock(), data(), QSystemSemaphore::acquire()
- */
-bool QSharedMemory::lock()
-{
- Q_D(QSharedMemory);
- if (d->lockedByMe) {
- qWarning("QSharedMemory::lock: already locked");
- return true;
- }
- if (d->systemSemaphore.acquire()) {
- d->lockedByMe = true;
- return true;
- }
- QString function = QLatin1String("QSharedMemory::lock");
- d->errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
- d->error = QSharedMemory::LockError;
- return false;
-}
-
-/*!
- Releases the lock on the shared memory segment and returns \c true, if
- the lock is currently held by this process. If the segment is not
- locked, or if the lock is held by another process, nothing happens
- and false is returned.
-
- \sa lock()
- */
-bool QSharedMemory::unlock()
-{
- Q_D(QSharedMemory);
- if (!d->lockedByMe)
- return false;
- d->lockedByMe = false;
- if (d->systemSemaphore.release())
- return true;
- QString function = QLatin1String("QSharedMemory::unlock");
- d->errorString = QSharedMemory::tr("%1: unable to unlock").arg(function);
- d->error = QSharedMemory::LockError;
- return false;
-}
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-/*!
- \enum QSharedMemory::SharedMemoryError
-
- \value NoError No error occurred.
-
- \value PermissionDenied The operation failed because the caller
- didn't have the required permissions.
-
- \value InvalidSize A create operation failed because the requested
- size was invalid.
-
- \value KeyError The operation failed because of an invalid key.
-
- \value AlreadyExists A create() operation failed because a shared
- memory segment with the specified key already existed.
-
- \value NotFound An attach() failed because a shared memory segment
- with the specified key could not be found.
-
- \value LockError The attempt to lock() the shared memory segment
- failed because create() or attach() failed and returned false, or
- because a system error occurred in QSystemSemaphore::acquire().
-
- \value OutOfResources A create() operation failed because there was
- not enough memory available to fill the request.
-
- \value UnknownError Something else happened and it was bad.
-*/
-
-/*!
- Returns a value indicating whether an error occurred, and, if so,
- which error it was.
-
- \sa errorString()
- */
-QSharedMemory::SharedMemoryError QSharedMemory::error() const
-{
- Q_D(const QSharedMemory);
- return d->error;
-}
-
-/*!
- Returns a text description of the last error that occurred. If
- error() returns an \l {QSharedMemory::SharedMemoryError} {error
- value}, call this function to get a text string that describes the
- error.
-
- \sa error()
- */
-QString QSharedMemory::errorString() const
-{
- Q_D(const QSharedMemory);
- return d->errorString;
-}
-
-#endif // QT_NO_SHAREDMEMORY
-
-QT_END_NAMESPACE
-
-#ifndef QT_NO_QOBJECT
-#include "moc_qsharedmemory.cpp"
-#endif
diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h
deleted file mode 100644
index 6236c6aa4c..0000000000
--- a/src/corelib/kernel/qsharedmemory.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHAREDMEMORY_H
-#define QSHAREDMEMORY_H
-
-#include <QtCore/qglobal.h>
-#ifndef QT_NO_QOBJECT
-# include <QtCore/qobject.h>
-#else
-# include <QtCore/qobjectdefs.h>
-# include <QtCore/qscopedpointer.h>
-# include <QtCore/qstring.h>
-#endif
-QT_BEGIN_NAMESPACE
-
-
-#ifndef QT_NO_SHAREDMEMORY
-
-class QSharedMemoryPrivate;
-
-class Q_CORE_EXPORT QSharedMemory
-#ifndef QT_NO_QOBJECT
- : public QObject
-#endif
-{
-#ifndef QT_NO_QOBJECT
- Q_OBJECT
-#endif
- Q_DECLARE_PRIVATE(QSharedMemory)
-
-public:
- enum AccessMode
- {
- ReadOnly,
- ReadWrite
- };
-
- enum SharedMemoryError
- {
- NoError,
- PermissionDenied,
- InvalidSize,
- KeyError,
- AlreadyExists,
- NotFound,
- LockError,
- OutOfResources,
- UnknownError
- };
-
-#ifndef QT_NO_QOBJECT
- QSharedMemory(QObject *parent = nullptr);
- QSharedMemory(const QString &key, QObject *parent = nullptr);
-#else
- QSharedMemory();
- QSharedMemory(const QString &key);
- static QString tr(const char * str)
- {
- return QString::fromLatin1(str);
- }
-#endif
- ~QSharedMemory();
-
- void setKey(const QString &key);
- QString key() const;
- void setNativeKey(const QString &key);
- QString nativeKey() const;
-
- bool create(int size, AccessMode mode = ReadWrite);
- int size() const;
-
- bool attach(AccessMode mode = ReadWrite);
- bool isAttached() const;
- bool detach();
-
- void *data();
- const void* constData() const;
- const void *data() const;
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
- bool lock();
- bool unlock();
-#endif
-
- SharedMemoryError error() const;
- QString errorString() const;
-
-private:
- Q_DISABLE_COPY(QSharedMemory)
-#ifdef QT_NO_QOBJECT
- QScopedPointer<QSharedMemoryPrivate> d_ptr;
-#endif
-};
-
-#endif // QT_NO_SHAREDMEMORY
-
-QT_END_NAMESPACE
-
-#endif // QSHAREDMEMORY_H
-
diff --git a/src/corelib/kernel/qsharedmemory_android.cpp b/src/corelib/kernel/qsharedmemory_android.cpp
deleted file mode 100644
index 2661e39575..0000000000
--- a/src/corelib/kernel/qsharedmemory_android.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Collabora Ltd, author <robin.burchell@collabora.co.uk>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsharedmemory.h"
-#include "qsharedmemory_p.h"
-#include <qdebug.h>
-
-#ifndef QT_NO_SHAREDMEMORY
-QT_BEGIN_NAMESPACE
-
-QSharedMemoryPrivate::QSharedMemoryPrivate()
- : QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
-#ifndef QT_NO_SYSTEMSEMAPHORE
- systemSemaphore(QString()), lockedByMe(false),
-#endif
- unix_key(0)
-{
-}
-
-void QSharedMemoryPrivate::setErrorString(QLatin1String function)
-{
- Q_UNUSED(function);
- Q_UNIMPLEMENTED();
-}
-
-key_t QSharedMemoryPrivate::handle()
-{
- Q_UNIMPLEMENTED();
- return 0;
-}
-
-#endif // QT_NO_SHAREDMEMORY
-
-#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
-int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
-{
- Q_UNUSED(fileName);
- Q_UNIMPLEMENTED();
- return 0;
-}
-#endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE
-
-#ifndef QT_NO_SHAREDMEMORY
-
-bool QSharedMemoryPrivate::cleanHandle()
-{
- Q_UNIMPLEMENTED();
- return true;
-}
-
-bool QSharedMemoryPrivate::create(int size)
-{
- Q_UNUSED(size);
- Q_UNIMPLEMENTED();
- return false;
-}
-
-bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
-{
- Q_UNUSED(mode);
- Q_UNIMPLEMENTED();
- return false;
-}
-
-bool QSharedMemoryPrivate::detach()
-{
- Q_UNIMPLEMENTED();
- return false;
-}
-
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
deleted file mode 100644
index e6e989abda..0000000000
--- a/src/corelib/kernel/qsharedmemory_p.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHAREDMEMORY_P_H
-#define QSHAREDMEMORY_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qsharedmemory.h"
-
-#include <QtCore/qstring.h>
-
-#ifdef QT_NO_SHAREDMEMORY
-# ifndef QT_NO_SYSTEMSEMAPHORE
-namespace QSharedMemoryPrivate
-{
- int createUnixKeyFile(const QString &fileName);
- QString makePlatformSafeKey(const QString &key,
- const QString &prefix = QLatin1String("qipc_sharedmemory_"));
-}
-#endif
-#else
-
-#include "qsystemsemaphore.h"
-
-#ifndef QT_NO_QOBJECT
-# include "private/qobject_p.h"
-#endif
-
-#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_RTEMS)
-# include <sys/sem.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-/*!
- Helper class
- */
-class QSharedMemoryLocker
-{
-
-public:
- inline QSharedMemoryLocker(QSharedMemory *sharedMemory) : q_sm(sharedMemory)
- {
- Q_ASSERT(q_sm);
- }
-
- inline ~QSharedMemoryLocker()
- {
- if (q_sm)
- q_sm->unlock();
- }
-
- inline bool lock()
- {
- if (q_sm && q_sm->lock())
- return true;
- q_sm = nullptr;
- return false;
- }
-
-private:
- QSharedMemory *q_sm;
-};
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-class Q_AUTOTEST_EXPORT QSharedMemoryPrivate
-#ifndef QT_NO_QOBJECT
- : public QObjectPrivate
-#endif
-{
-#ifndef QT_NO_QOBJECT
- Q_DECLARE_PUBLIC(QSharedMemory)
-#endif
-
-public:
- QSharedMemoryPrivate();
-
- void *memory;
- int size;
- QString key;
- QString nativeKey;
- QSharedMemory::SharedMemoryError error;
- QString errorString;
-#ifndef QT_NO_SYSTEMSEMAPHORE
- QSystemSemaphore systemSemaphore;
- bool lockedByMe;
-#endif
-
- static int createUnixKeyFile(const QString &fileName);
- static QString makePlatformSafeKey(const QString &key,
- const QString &prefix = QLatin1String("qipc_sharedmemory_"));
-#ifdef Q_OS_WIN
- Qt::HANDLE handle();
-#elif defined(QT_POSIX_IPC)
- int handle();
-#else
- key_t handle();
-#endif
- bool initKey();
- bool cleanHandle();
- bool create(int size);
- bool attach(QSharedMemory::AccessMode mode);
- bool detach();
-
- void setErrorString(QLatin1String function);
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
- bool tryLocker(QSharedMemoryLocker *locker, const QString &function) {
- if (!locker->lock()) {
- errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
- error = QSharedMemory::LockError;
- return false;
- }
- return true;
- }
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-private:
-#ifdef Q_OS_WIN
- Qt::HANDLE hand;
-#elif defined(QT_POSIX_IPC)
- int hand;
-#else
- key_t unix_key;
-#endif
-};
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SHAREDMEMORY
-
-#endif // QSHAREDMEMORY_P_H
-
diff --git a/src/corelib/kernel/qsharedmemory_posix.cpp b/src/corelib/kernel/qsharedmemory_posix.cpp
deleted file mode 100644
index 80f9a35651..0000000000
--- a/src/corelib/kernel/qsharedmemory_posix.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Konstantin Ritt <ritt.ks@gmail.com>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-
-#include "qsharedmemory.h"
-#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qfile.h>
-
-#include <errno.h>
-
-#ifdef QT_POSIX_IPC
-
-#ifndef QT_NO_SHAREDMEMORY
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "private/qcore_unix_p.h"
-
-QT_BEGIN_NAMESPACE
-
-int QSharedMemoryPrivate::handle()
-{
- // don't allow making handles on empty keys
- const QString safeKey = makePlatformSafeKey(key);
- if (safeKey.isEmpty()) {
- errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle"));
- error = QSharedMemory::KeyError;
- return 0;
- }
-
- return 1;
-}
-
-bool QSharedMemoryPrivate::cleanHandle()
-{
- qt_safe_close(hand);
- hand = -1;
-
- return true;
-}
-
-bool QSharedMemoryPrivate::create(int size)
-{
- if (!handle())
- return false;
-
- const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
-
- int fd;
-#ifdef O_CLOEXEC
- // First try with O_CLOEXEC flag, if that fails, fall back to normal flags
- EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600));
- if (fd == -1)
- EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0600));
-#else
- EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0600));
-#endif
- if (fd == -1) {
- const int errorNumber = errno;
- const QLatin1String function("QSharedMemory::attach (shm_open)");
- switch (errorNumber) {
- case ENAMETOOLONG:
- case EINVAL:
- errorString = QSharedMemory::tr("%1: bad name").arg(function);
- error = QSharedMemory::KeyError;
- break;
- default:
- setErrorString(function);
- }
- return false;
- }
-
- // the size may only be set once
- int ret;
- EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
- if (ret == -1) {
- setErrorString(QLatin1String("QSharedMemory::create (ftruncate)"));
- qt_safe_close(fd);
- return false;
- }
-
- qt_safe_close(fd);
-
- return true;
-}
-
-bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
-{
- const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
-
- const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
- const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
-
-#ifdef O_CLOEXEC
- // First try with O_CLOEXEC flag, if that fails, fall back to normal flags
- EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag | O_CLOEXEC, omode));
- if (hand == -1)
- EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
-#else
- EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
-#endif
- if (hand == -1) {
- const int errorNumber = errno;
- const QLatin1String function("QSharedMemory::attach (shm_open)");
- switch (errorNumber) {
- case ENAMETOOLONG:
- case EINVAL:
- errorString = QSharedMemory::tr("%1: bad name").arg(function);
- error = QSharedMemory::KeyError;
- break;
- default:
- setErrorString(function);
- }
- hand = -1;
- return false;
- }
-
- // grab the size
- QT_STATBUF st;
- if (QT_FSTAT(hand, &st) == -1) {
- setErrorString(QLatin1String("QSharedMemory::attach (fstat)"));
- cleanHandle();
- return false;
- }
- size = st.st_size;
-
- // grab the memory
- const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
- memory = QT_MMAP(0, size, mprot, MAP_SHARED, hand, 0);
- if (memory == MAP_FAILED || !memory) {
- setErrorString(QLatin1String("QSharedMemory::attach (mmap)"));
- cleanHandle();
- memory = 0;
- size = 0;
- return false;
- }
-
-#ifdef F_ADD_SEALS
- // Make sure the shared memory region will not shrink
- // otherwise someone could cause SIGBUS on us.
- // (see http://lwn.net/Articles/594919/)
- fcntl(hand, F_ADD_SEALS, F_SEAL_SHRINK);
-#endif
-
- return true;
-}
-
-bool QSharedMemoryPrivate::detach()
-{
- // detach from the memory segment
- if (::munmap(memory, size) == -1) {
- setErrorString(QLatin1String("QSharedMemory::detach (munmap)"));
- return false;
- }
- memory = 0;
- size = 0;
-
-#ifdef Q_OS_QNX
- // On QNX the st_nlink field of struct stat contains the number of
- // active shm_open() connections to the shared memory file, so we
- // can use it to automatically clean up the file once the last
- // user has detached from it.
-
- // get the number of current attachments
- int shm_nattch = 0;
- QT_STATBUF st;
- if (QT_FSTAT(hand, &st) == 0) {
- // subtract 2 from linkcount: one for our own open and one for the dir entry
- shm_nattch = st.st_nlink - 2;
- }
-
- cleanHandle();
-
- // if there are no attachments then unlink the shared memory
- if (shm_nattch == 0) {
- const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
- if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
- setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)"));
- }
-#else
- // On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
- // so we'll simply leak the shared memory files.
- cleanHandle();
-#endif
-
- return true;
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SHAREDMEMORY
-
-#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsharedmemory_systemv.cpp b/src/corelib/kernel/qsharedmemory_systemv.cpp
deleted file mode 100644
index 0ba5f65641..0000000000
--- a/src/corelib/kernel/qsharedmemory_systemv.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-
-#include "qsharedmemory.h"
-#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qdir.h>
-#include <qdebug.h>
-
-#include <errno.h>
-
-#ifndef QT_POSIX_IPC
-
-#ifndef QT_NO_SHAREDMEMORY
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif //QT_NO_SHAREDMEMORY
-
-#include "private/qcore_unix_p.h"
-
-#ifndef QT_NO_SHAREDMEMORY
-QT_BEGIN_NAMESPACE
-
-/*!
- \internal
-
- If not already made create the handle used for accessing the shared memory.
-*/
-key_t QSharedMemoryPrivate::handle()
-{
- // already made
- if (unix_key)
- return unix_key;
-
- // don't allow making handles on empty keys
- if (nativeKey.isEmpty()) {
- errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::KeyError;
- return 0;
- }
-
- // ftok requires that an actual file exists somewhere
- if (!QFile::exists(nativeKey)) {
- errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::NotFound;
- return 0;
- }
-
- unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q');
- if (-1 == unix_key) {
- errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::KeyError;
- unix_key = 0;
- }
- return unix_key;
-}
-
-#endif // QT_NO_SHAREDMEMORY
-
-#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
-/*!
- \internal
- Creates the unix file if needed.
- returns \c true if the unix file was created.
-
- -1 error
- 0 already existed
- 1 created
- */
-int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
-{
- int fd = qt_safe_open(QFile::encodeName(fileName).constData(),
- O_EXCL | O_CREAT | O_RDWR, 0640);
- if (-1 == fd) {
- if (errno == EEXIST)
- return 0;
- return -1;
- } else {
- close(fd);
- }
- return 1;
-}
-#endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE
-
-#ifndef QT_NO_SHAREDMEMORY
-
-bool QSharedMemoryPrivate::cleanHandle()
-{
- unix_key = 0;
- return true;
-}
-
-bool QSharedMemoryPrivate::create(int size)
-{
- // build file if needed
- bool createdFile = false;
- int built = createUnixKeyFile(nativeKey);
- if (built == -1) {
- errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::KeyError;
- return false;
- }
- if (built == 1) {
- createdFile = true;
- }
-
- // get handle
- if (!handle()) {
- if (createdFile)
- QFile::remove(nativeKey);
- return false;
- }
-
- // create
- if (-1 == shmget(unix_key, size, 0600 | IPC_CREAT | IPC_EXCL)) {
- const QLatin1String function("QSharedMemory::create");
- switch (errno) {
- case EINVAL:
- errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg(QLatin1String("QSharedMemory::handle"));
- error = QSharedMemory::InvalidSize;
- break;
- default:
- setErrorString(function);
- }
- if (createdFile && error != QSharedMemory::AlreadyExists)
- QFile::remove(nativeKey);
- return false;
- }
-
- return true;
-}
-
-bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
-{
- // grab the shared memory segment id
- int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
- if (-1 == id) {
- setErrorString(QLatin1String("QSharedMemory::attach (shmget)"));
- return false;
- }
-
- // grab the memory
- memory = shmat(id, nullptr, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
- if ((void*) - 1 == memory) {
- memory = nullptr;
- setErrorString(QLatin1String("QSharedMemory::attach (shmat)"));
- return false;
- }
-
- // grab the size
- shmid_ds shmid_ds;
- if (!shmctl(id, IPC_STAT, &shmid_ds)) {
- size = (int)shmid_ds.shm_segsz;
- } else {
- setErrorString(QLatin1String("QSharedMemory::attach (shmctl)"));
- return false;
- }
-
- return true;
-}
-
-bool QSharedMemoryPrivate::detach()
-{
- // detach from the memory segment
- if (-1 == shmdt(memory)) {
- const QLatin1String function("QSharedMemory::detach");
- switch (errno) {
- case EINVAL:
- errorString = QSharedMemory::tr("%1: not attached").arg(function);
- error = QSharedMemory::NotFound;
- break;
- default:
- setErrorString(function);
- }
- return false;
- }
- memory = nullptr;
- size = 0;
-
- // Get the number of current attachments
- int id = shmget(unix_key, 0, 0400);
- cleanHandle();
-
- struct shmid_ds shmid_ds;
- if (0 != shmctl(id, IPC_STAT, &shmid_ds)) {
- switch (errno) {
- case EINVAL:
- return true;
- default:
- return false;
- }
- }
- // If there are no attachments then remove it.
- if (shmid_ds.shm_nattch == 0) {
- // mark for removal
- if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
- setErrorString(QLatin1String("QSharedMemory::remove"));
- switch (errno) {
- case EINVAL:
- return true;
- default:
- return false;
- }
- }
-
- // remove file
- if (!QFile::remove(nativeKey))
- return false;
- }
- return true;
-}
-
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SHAREDMEMORY
-
-#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
deleted file mode 100644
index bc0f3b03ca..0000000000
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-
-#include "qsharedmemory.h"
-#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qdebug.h>
-
-#include <errno.h>
-
-#ifndef QT_NO_SHAREDMEMORY
-#include <sys/types.h>
-#ifndef QT_POSIX_IPC
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#else
-#include <sys/mman.h>
-#endif
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif //QT_NO_SHAREDMEMORY
-
-#include "private/qcore_unix_p.h"
-
-#ifndef QT_NO_SHAREDMEMORY
-QT_BEGIN_NAMESPACE
-
-QSharedMemoryPrivate::QSharedMemoryPrivate() :
-#ifndef QT_NO_QOBJECT
- QObjectPrivate(),
-#endif
- memory(nullptr), size(0), error(QSharedMemory::NoError),
-#ifndef QT_NO_SYSTEMSEMAPHORE
- systemSemaphore(QString()), lockedByMe(false),
-#endif
-#ifndef QT_POSIX_IPC
- unix_key(0)
-#else
- hand(-1)
-#endif
-{
-}
-
-void QSharedMemoryPrivate::setErrorString(QLatin1String function)
-{
- // EINVAL is handled in functions so they can give better error strings
- switch (errno) {
- case EACCES:
- errorString = QSharedMemory::tr("%1: permission denied").arg(function);
- error = QSharedMemory::PermissionDenied;
- break;
- case EEXIST:
- errorString = QSharedMemory::tr("%1: already exists").arg(function);
- error = QSharedMemory::AlreadyExists;
- break;
- case ENOENT:
- errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
- error = QSharedMemory::NotFound;
- break;
- case EMFILE:
- case ENOMEM:
- case ENOSPC:
- errorString = QSharedMemory::tr("%1: out of resources").arg(function);
- error = QSharedMemory::OutOfResources;
- break;
- default:
- errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errno);
- error = QSharedMemory::UnknownError;
-#if defined QSHAREDMEMORY_DEBUG
- qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
-#endif
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
deleted file mode 100644
index cbf31bcb2f..0000000000
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsharedmemory.h"
-#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qdebug.h>
-#include <qt_windows.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_SHAREDMEMORY
-
-QSharedMemoryPrivate::QSharedMemoryPrivate() :
-#ifndef QT_NO_QOBJECT
- QObjectPrivate(),
-#endif
- memory(0), size(0), error(QSharedMemory::NoError),
- systemSemaphore(QString()), lockedByMe(false), hand(0)
-{
-}
-
-void QSharedMemoryPrivate::setErrorString(QLatin1String function)
-{
- DWORD windowsError = GetLastError();
- if (windowsError == 0)
- return;
- switch (windowsError) {
- case ERROR_ALREADY_EXISTS:
- error = QSharedMemory::AlreadyExists;
- errorString = QSharedMemory::tr("%1: already exists").arg(function);
- break;
- case ERROR_FILE_NOT_FOUND:
- error = QSharedMemory::NotFound;
- errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
- break;
- case ERROR_COMMITMENT_LIMIT:
- error = QSharedMemory::InvalidSize;
- errorString = QSharedMemory::tr("%1: invalid size").arg(function);
- break;
- case ERROR_NO_SYSTEM_RESOURCES:
- case ERROR_NOT_ENOUGH_MEMORY:
- error = QSharedMemory::OutOfResources;
- errorString = QSharedMemory::tr("%1: out of resources").arg(function);
- break;
- case ERROR_ACCESS_DENIED:
- error = QSharedMemory::PermissionDenied;
- errorString = QSharedMemory::tr("%1: permission denied").arg(function);
- break;
- default:
- errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(windowsError);
- error = QSharedMemory::UnknownError;
-#if defined QSHAREDMEMORY_DEBUG
- qDebug() << errorString << "key" << key;
-#endif
- }
-}
-
-HANDLE QSharedMemoryPrivate::handle()
-{
- if (!hand) {
- const QLatin1String function("QSharedMemory::handle");
- if (nativeKey.isEmpty()) {
- error = QSharedMemory::KeyError;
- errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
- return 0;
- }
- hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
- reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
- if (!hand) {
- setErrorString(function);
- return 0;
- }
- }
- return hand;
-}
-
-bool QSharedMemoryPrivate::cleanHandle()
-{
- if (hand != 0 && !CloseHandle(hand)) {
- hand = 0;
- setErrorString(QLatin1String("QSharedMemory::cleanHandle"));
- return false;
- }
- hand = 0;
- return true;
-}
-
-bool QSharedMemoryPrivate::create(int size)
-{
- const QLatin1String function("QSharedMemory::create");
- if (nativeKey.isEmpty()) {
- error = QSharedMemory::KeyError;
- errorString = QSharedMemory::tr("%1: key error").arg(function);
- return false;
- }
-
- // Create the file mapping.
- hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size,
- reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
- setErrorString(function);
-
- // hand is valid when it already exists unlike unix so explicitly check
- return error != QSharedMemory::AlreadyExists && hand;
-}
-
-bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
-{
- // Grab a pointer to the memory block
- int permissions = (mode == QSharedMemory::ReadOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
- memory = (void *)MapViewOfFile(handle(), permissions, 0, 0, 0);
- if (0 == memory) {
- setErrorString(QLatin1String("QSharedMemory::attach"));
- cleanHandle();
- return false;
- }
-
- // Grab the size of the memory we have been given (a multiple of 4K on windows)
- MEMORY_BASIC_INFORMATION info;
- if (!VirtualQuery(memory, &info, sizeof(info))) {
- // Windows doesn't set an error code on this one,
- // it should only be a kernel memory error.
- error = QSharedMemory::UnknownError;
- errorString = QSharedMemory::tr("%1: size query failed").arg(QLatin1String("QSharedMemory::attach: "));
- return false;
- }
- size = info.RegionSize;
-
- return true;
-}
-
-bool QSharedMemoryPrivate::detach()
-{
- // umap memory
- if (!UnmapViewOfFile(memory)) {
- setErrorString(QLatin1String("QSharedMemory::detach"));
- return false;
- }
- memory = 0;
- size = 0;
-
- // close handle
- return cleanHandle();
-}
-
-#endif //QT_NO_SHAREDMEMORY
-
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index 8e690d15ff..65d766db4a 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
@@ -49,10 +13,6 @@ class QSignalMapperPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSignalMapper)
public:
- void _q_senderDestroyed() {
- Q_Q(QSignalMapper);
- q->removeMappings(q->sender());
- }
template <class Signal, class Container>
void emitMappedValue(QObject *sender, Signal signal, const Container &mappedValues)
@@ -61,7 +21,7 @@ public:
auto it = mappedValues.find(sender);
if (it != mappedValues.end())
- Q_EMIT (q->*signal)(*it);
+ Q_EMIT(q->*signal)(*it);
}
void emitMappedValues(QObject *sender)
@@ -73,7 +33,7 @@ public:
QHash<QObject *, int> intHash;
QHash<QObject *, QString> stringHash;
- QHash<QObject *, QObject*> objectHash;
+ QHash<QObject *, QObject *> objectHash;
};
/*!
@@ -164,7 +124,7 @@ void QSignalMapper::setMapping(QObject *sender, int id)
{
Q_D(QSignalMapper);
d->intHash.insert(sender, id);
- connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+ connect(sender, &QObject::destroyed, this, &QSignalMapper::removeMappings);
}
/*!
@@ -177,7 +137,7 @@ void QSignalMapper::setMapping(QObject *sender, const QString &text)
{
Q_D(QSignalMapper);
d->stringHash.insert(sender, text);
- connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+ connect(sender, &QObject::destroyed, this, &QSignalMapper::removeMappings);
}
/*!
@@ -190,7 +150,7 @@ void QSignalMapper::setMapping(QObject *sender, QObject *object)
{
Q_D(QSignalMapper);
d->objectHash.insert(sender, object);
- connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+ connect(sender, &QObject::destroyed, this, &QSignalMapper::removeMappings);
}
/*!
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
index e92b275428..af0be52ee5 100644
--- a/src/corelib/kernel/qsignalmapper.h
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIGNALMAPPER_H
#define QSIGNALMAPPER_H
@@ -74,7 +38,6 @@ public Q_SLOTS:
private:
Q_DISABLE_COPY(QSignalMapper)
- Q_PRIVATE_SLOT(d_func(), void _q_senderDestroyed())
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsingleshottimer_p.h b/src/corelib/kernel/qsingleshottimer_p.h
new file mode 100644
index 0000000000..dd1402f63a
--- /dev/null
+++ b/src/corelib/kernel/qsingleshottimer_p.h
@@ -0,0 +1,141 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSINGLESHOTTIMER_P_H
+#define QSINGLESHOTTIMER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qmetaobject_p.h"
+#include "private/qnumeric_p.h"
+
+#include <chrono>
+
+QT_BEGIN_NAMESPACE
+
+class QSingleShotTimer : public QObject
+{
+ Q_OBJECT
+
+ Qt::TimerId timerId = Qt::TimerId::Invalid;
+
+public:
+ // use the same duration type
+ using Duration = QAbstractEventDispatcher::Duration;
+
+ inline ~QSingleShotTimer();
+ inline QSingleShotTimer(Duration interval, Qt::TimerType timerType,
+ const QObject *r, const char *member);
+ inline QSingleShotTimer(Duration interval, Qt::TimerType timerType,
+ const QObject *r, QtPrivate::QSlotObjectBase *slotObj);
+
+ inline void startTimerForReceiver(Duration interval, Qt::TimerType timerType,
+ const QObject *receiver);
+
+ static Duration fromMsecs(std::chrono::milliseconds ms)
+ {
+ using namespace std::chrono;
+ using ratio = std::ratio_divide<std::milli, Duration::period>;
+ static_assert(ratio::den == 1);
+
+ Duration::rep r;
+ if (qMulOverflow<ratio::num>(ms.count(), &r)) {
+ qWarning("QTimer::singleShot(std::chrono::milliseconds, ...): "
+ "interval argument overflowed when converted to nanoseconds.");
+ return Duration::max();
+ }
+ return Duration{r};
+ }
+Q_SIGNALS:
+ void timeout();
+
+private:
+ inline void timerEvent(QTimerEvent *) override;
+};
+
+QSingleShotTimer::QSingleShotTimer(Duration interval, Qt::TimerType timerType,
+ const QObject *r, const char *member)
+ : QObject(QAbstractEventDispatcher::instance())
+{
+ connect(this, SIGNAL(timeout()), r, member);
+ startTimerForReceiver(interval, timerType, r);
+}
+
+QSingleShotTimer::QSingleShotTimer(Duration interval, Qt::TimerType timerType,
+ const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
+ : QObject(QAbstractEventDispatcher::instance())
+{
+ int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject);
+ Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout");
+ QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj,
+ Qt::AutoConnection, nullptr, &staticMetaObject);
+
+ startTimerForReceiver(interval, timerType, r);
+}
+
+QSingleShotTimer::~QSingleShotTimer()
+{
+ if (timerId > Qt::TimerId::Invalid)
+ killTimer(timerId);
+}
+
+/*
+ Move the timer, and the dispatching and handling of the timer event, into
+ the same thread as where it will be handled, so that it fires reliably even
+ if the thread that set up the timer is busy.
+*/
+void QSingleShotTimer::startTimerForReceiver(Duration interval, Qt::TimerType timerType,
+ const QObject *receiver)
+{
+ if (receiver && receiver->thread() != thread()) {
+ // Avoid leaking the QSingleShotTimer instance in case the application exits before the
+ // timer fires
+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this,
+ &QObject::deleteLater);
+ setParent(nullptr);
+ moveToThread(receiver->thread());
+
+ QDeadlineTimer deadline(interval, timerType);
+ auto invokable = [this, deadline, timerType] {
+ if (deadline.hasExpired()) {
+ Q_EMIT timeout();
+ } else {
+ timerId = Qt::TimerId{startTimer(deadline.remainingTimeAsDuration(), timerType)};
+ }
+ };
+ QMetaObject::invokeMethod(this, invokable, Qt::QueuedConnection);
+ } else {
+ timerId = Qt::TimerId{startTimer(interval, timerType)};
+ }
+}
+
+void QSingleShotTimer::timerEvent(QTimerEvent *)
+{
+ // need to kill the timer _before_ we emit timeout() in case the
+ // slot connected to timeout calls processEvents()
+ if (timerId > Qt::TimerId::Invalid)
+ killTimer(std::exchange(timerId, Qt::TimerId::Invalid));
+
+ Q_EMIT timeout();
+
+ // we would like to use delete later here, but it feels like a
+ // waste to post a new event to handle this event, so we just unset the flag
+ // and explicitly delete...
+ delete this;
+}
+
+QT_END_NAMESPACE
+
+#endif // QSINGLESHOTTIMER_P_H
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index 6e1d2103bd..4e4cf3666b 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define BUILDING_QSOCKETNOTIFIER
#include "qsocketnotifier.h"
@@ -52,19 +16,23 @@
#include <private/qthread_p.h>
#include <QtCore/QLoggingCategory>
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcSocketNotifierDeprecation)
Q_LOGGING_CATEGORY(lcSocketNotifierDeprecation, "qt.core.socketnotifier_deprecation");
+QT_IMPL_METATYPE_EXTERN_TAGGED(QSocketNotifier::Type, QSocketNotifier_Type)
+QT_IMPL_METATYPE_EXTERN(QSocketDescriptor)
+
class QSocketNotifierPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSocketNotifier)
public:
QSocketDescriptor sockfd;
QSocketNotifier::Type sntype;
- bool snenabled;
+ bool snenabled = false;
};
/*!
@@ -85,11 +53,16 @@ public:
Once you have opened a device using a low-level (usually
platform-specific) API, you can create a socket notifier to
- monitor the file descriptor. The socket notifier is enabled by
- default, i.e. it emits the activated() signal whenever a socket
- event corresponding to its type occurs. Connect the activated()
- signal to the slot you want to be called when an event
- corresponding to your socket notifier's type occurs.
+ monitor the file descriptor. If the descriptor is passed to the
+ notifier's constructor, the socket notifier is enabled by default,
+ i.e. it emits the activated() signal whenever a socket event
+ corresponding to its type occurs. Connect the activated() signal
+ to the slot you want to be called when an event corresponding to
+ your socket notifier's type occurs.
+
+ You can create a socket notifier with no descriptor assigned. In
+ this case, you should call the setSocket() function after the
+ descriptor has been obtained.
There are three types of socket notifiers: read, write, and
exception. The type is described by the \l Type enum, and must be
@@ -136,6 +109,29 @@ public:
*/
/*!
+ \since 6.1
+
+ Constructs a socket notifier with the given \a type that has no
+ descriptor assigned. The \a parent argument is passed to QObject's
+ constructor.
+
+ Call the setSocket() function to set the descriptor for monitoring.
+
+ \sa setSocket(), isValid(), isEnabled()
+*/
+
+QSocketNotifier::QSocketNotifier(Type type, QObject *parent)
+ : QObject(*new QSocketNotifierPrivate, parent)
+{
+ Q_D(QSocketNotifier);
+
+ qRegisterMetaType<QSocketDescriptor>();
+ qRegisterMetaType<QSocketNotifier::Type>();
+
+ d->sntype = type;
+}
+
+/*!
Constructs a socket notifier with the given \a parent. It enables
the \a socket, and watches for events of the given \a type.
@@ -149,15 +145,11 @@ public:
*/
QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
- : QObject(*new QSocketNotifierPrivate, parent)
+ : QSocketNotifier(type, parent)
{
Q_D(QSocketNotifier);
- qRegisterMetaType<QSocketDescriptor>();
- qRegisterMetaType<QSocketNotifier::Type>();
-
d->sockfd = socket;
- d->sntype = type;
d->snenabled = true;
auto thisThreadData = d->threadData.loadRelaxed();
@@ -182,7 +174,7 @@ QSocketNotifier::~QSocketNotifier()
/*!
\fn void QSocketNotifier::activated(int socket)
- \obsolete To avoid unintended truncation of the descriptor, use
+ \deprecated To avoid unintended truncation of the descriptor, use
the QSocketDescriptor overload of this function. If you need
compatibility with versions older than 5.15 you need to change
the slot to accept qintptr if it currently accepts an int, and
@@ -208,11 +200,28 @@ QSocketNotifier::~QSocketNotifier()
\sa type(), socket()
*/
+/*!
+ \since 6.1
+
+ Assigns the \a socket to this notifier.
+
+ \note The notifier will be disabled as a side effect and needs
+ to be re-enabled.
+
+ \sa setEnabled(), isValid()
+*/
+void QSocketNotifier::setSocket(qintptr socket)
+{
+ Q_D(QSocketNotifier);
+
+ setEnabled(false);
+ d->sockfd = socket;
+}
/*!
- Returns the socket identifier specified to the constructor.
+ Returns the socket identifier assigned to this object.
- \sa type()
+ \sa isValid(), type()
*/
qintptr QSocketNotifier::socket() const
{
@@ -232,6 +241,20 @@ QSocketNotifier::Type QSocketNotifier::type() const
}
/*!
+ \since 6.1
+
+ Returns \c true if the notifier is valid (that is, it has
+ a descriptor assigned); otherwise returns \c false.
+
+ \sa setSocket()
+*/
+bool QSocketNotifier::isValid() const
+{
+ Q_D(const QSocketNotifier);
+ return d->sockfd.isValid();
+}
+
+/*!
Returns \c true if the notifier is enabled; otherwise returns \c false.
\sa setEnabled()
@@ -246,10 +269,10 @@ bool QSocketNotifier::isEnabled() const
If \a enable is true, the notifier is enabled; otherwise the notifier
is disabled.
- The notifier is enabled by default, i.e. it emits the activated()
- signal whenever a socket event corresponding to its
- \l{type()}{type} occurs. If it is disabled, it ignores socket
- events (the same effect as not creating the socket notifier).
+ When the notifier is enabled, it emits the activated() signal whenever
+ a socket event corresponding to its \l{type()}{type} occurs. When it is
+ disabled, it ignores socket events (the same effect as not creating
+ the socket notifier).
Write notifiers should normally be disabled immediately after the
activated() signal has been emitted
@@ -289,24 +312,28 @@ bool QSocketNotifier::event(QEvent *e)
Q_D(QSocketNotifier);
// Emits the activated() signal when a QEvent::SockAct or QEvent::SockClose is
// received.
- if (e->type() == QEvent::ThreadChange) {
+ switch (e->type()) {
+ case QEvent::ThreadChange:
if (d->snenabled) {
QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
Q_ARG(bool, d->snenabled));
setEnabled(false);
}
- }
- QObject::event(e); // will activate filters
- if ((e->type() == QEvent::SockAct) || (e->type() == QEvent::SockClose)) {
- QPointer<QSocketNotifier> alive(this);
- emit activated(d->sockfd, d->sntype, QPrivateSignal());
- // ### Qt7: Remove emission if the activated(int) signal is removed
- if (alive)
- emit activated(int(qintptr(d->sockfd)), QPrivateSignal());
-
+ break;
+ case QEvent::SockAct:
+ case QEvent::SockClose:
+ {
+ QPointer<QSocketNotifier> alive(this);
+ emit activated(d->sockfd, d->sntype, QPrivateSignal());
+ // ### Qt7: Remove emission if the activated(int) signal is removed
+ if (alive)
+ emit activated(int(qintptr(d->sockfd)), QPrivateSignal());
+ }
return true;
+ default:
+ break;
}
- return false;
+ return QObject::event(e);
}
/*!
diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h
index 528f58a1e1..ac9e577ebc 100644
--- a/src/corelib/kernel/qsocketnotifier.h
+++ b/src/corelib/kernel/qsocketnotifier.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSOCKETNOTIFIER_H
#define QSOCKETNOTIFIER_H
@@ -54,12 +18,15 @@ class Q_CORE_EXPORT QSocketNotifier : public QObject
public:
enum Type { Read, Write, Exception };
+ explicit QSocketNotifier(Type, QObject *parent = nullptr);
QSocketNotifier(qintptr socket, Type, QObject *parent = nullptr);
~QSocketNotifier();
+ void setSocket(qintptr socket);
qintptr socket() const;
Type type() const;
+ bool isValid() const;
bool isEnabled() const;
public Q_SLOTS:
@@ -81,7 +48,7 @@ Q_SIGNALS:
// This means the PMF-based connect(..) will automatically, on recompile, pick up the new
// version while the old-style connect(..) can query the metaobject system for this version.
#if defined(Q_MOC_RUN) || defined(BUILDING_QSOCKETNOTIFIER) || defined(Q_QDOC)
- void activated(int socket, QPrivateSignal);
+ QT_MOC_COMPAT void activated(int socket, QPrivateSignal);
#endif
protected:
@@ -102,39 +69,40 @@ public:
#define Q_DECL_CONSTEXPR_NOT_WIN Q_DECL_CONSTEXPR
#endif
- /* implicit */ Q_DECL_CONSTEXPR_NOT_WIN
+ Q_DECL_CONSTEXPR_NOT_WIN Q_IMPLICIT
QSocketDescriptor(DescriptorType descriptor = DescriptorType(-1)) noexcept : sockfd(descriptor)
{
}
#if defined(Q_OS_WIN) || defined(Q_QDOC)
- /* implicit */ QSocketDescriptor(qintptr desc) noexcept : sockfd(DescriptorType(desc)) {}
- operator qintptr() const noexcept { return qintptr(sockfd); }
+ Q_IMPLICIT QSocketDescriptor(qintptr desc) noexcept : sockfd(DescriptorType(desc)) {}
+ Q_IMPLICIT operator qintptr() const noexcept { return qintptr(sockfd); }
Q_DECL_CONSTEXPR Qt::HANDLE winHandle() const noexcept { return sockfd; }
#endif
Q_DECL_CONSTEXPR operator DescriptorType() const noexcept { return sockfd; }
Q_DECL_CONSTEXPR_NOT_WIN bool isValid() const noexcept { return *this != QSocketDescriptor(); }
- friend Q_DECL_CONSTEXPR_NOT_WIN bool operator==(QSocketDescriptor lhs,
- QSocketDescriptor rhs) noexcept
+private:
+ friend Q_DECL_CONSTEXPR_NOT_WIN bool comparesEqual(const QSocketDescriptor &lhs,
+ const QSocketDescriptor &rhs) noexcept
{
return lhs.sockfd == rhs.sockfd;
}
- friend Q_DECL_CONSTEXPR_NOT_WIN bool operator!=(QSocketDescriptor lhs,
- QSocketDescriptor rhs) noexcept
- {
- return lhs.sockfd != rhs.sockfd;
- }
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+ Q_DECLARE_EQUALITY_COMPARABLE(QSocketDescriptor)
+#else
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QSocketDescriptor)
+#endif
#undef Q_DECL_CONSTEXPR_NOT_WIN
-private:
DescriptorType sockfd;
};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QSocketNotifier::Type)
-Q_DECLARE_METATYPE(QSocketDescriptor)
+
+QT_DECL_METATYPE_EXTERN_TAGGED(QSocketNotifier::Type, QSocketNotifier_Type, Q_CORE_EXPORT)
+QT_DECL_METATYPE_EXTERN(QSocketDescriptor, Q_CORE_EXPORT)
#endif // QSOCKETNOTIFIER_H
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index 6a250f5f3a..428ce62984 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
#include "qsystemerror_p.h"
@@ -45,10 +9,16 @@
#endif
#ifdef Q_OS_WIN
# include <qt_windows.h>
+# include <comdef.h>
+#endif
+#ifndef QT_BOOTSTRAPPED
+# include <qcoreapplication.h>
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if !defined(Q_OS_WIN) && QT_CONFIG(thread) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
namespace {
@@ -61,11 +31,11 @@ namespace {
// version in portable code. However, it's impossible to do that if
// _GNU_SOURCE is defined so we use C++ overloading to decide what to do
// depending on the return type
- static inline Q_DECL_UNUSED QString fromstrerror_helper(int, const QByteArray &buf)
+ [[maybe_unused]] static inline QString fromstrerror_helper(int, const QByteArray &buf)
{
return QString::fromLocal8Bit(buf);
}
- static inline Q_DECL_UNUSED QString fromstrerror_helper(const char *str, const QByteArray &)
+ [[maybe_unused]] static inline QString fromstrerror_helper(const char *str, const QByteArray &)
{
return QString::fromLocal8Bit(str);
}
@@ -76,8 +46,8 @@ namespace {
static QString windowsErrorString(int errorCode)
{
QString ret;
- wchar_t *string = 0;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ wchar_t *string = nullptr;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
@@ -89,11 +59,11 @@ static QString windowsErrorString(int errorCode)
if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
ret = QString::fromLatin1("The specified module could not be found.");
- if (ret.endsWith(QLatin1String("\r\n")))
+ if (ret.endsWith("\r\n"_L1))
ret.chop(2);
if (ret.isEmpty())
ret = QString::fromLatin1("Unknown error 0x%1.")
- .arg(unsigned(errorCode), 8, 16, QLatin1Char('0'));
+ .arg(unsigned(errorCode), 8, 16, '0'_L1);
return ret;
}
#endif
@@ -127,18 +97,20 @@ static QString standardLibraryErrorString(int errorCode)
break; }
}
if (s) {
- // ######## this breaks moc build currently
- // ret = QCoreApplication::translate("QIODevice", s);
+#ifndef QT_BOOTSTRAPPED
+ ret = QCoreApplication::translate("QIODevice", s);
+#else
ret = QString::fromLatin1(s);
+#endif
}
return ret.trimmed();
}
QString QSystemError::string(ErrorScope errorScope, int errorCode)
{
- switch(errorScope) {
+ switch (errorScope) {
case NativeError:
-#if defined (Q_OS_WIN)
+#if defined(Q_OS_WIN)
return windowsErrorString(errorCode);
#endif // else unix: native and standard library are the same
case StandardLibraryError:
@@ -147,7 +119,7 @@ QString QSystemError::string(ErrorScope errorScope, int errorCode)
qWarning("invalid error scope");
Q_FALLTHROUGH();
case NoError:
- return QLatin1String("No error");
+ return u"No error"_s;
}
}
@@ -162,6 +134,15 @@ QString QSystemError::windowsString(int errorCode)
return windowsErrorString(errorCode == -1 ? GetLastError() : errorCode);
}
+QString QSystemError::windowsComString(HRESULT hr)
+{
+ const _com_error comError(hr);
+ QString result = "COM error 0x"_L1 + QString::number(ulong(hr), 16);
+ if (const wchar_t *msg = comError.ErrorMessage())
+ result += ": "_L1 + QString::fromWCharArray(msg);
+ return result;
+}
+
QString qt_error_string(int code)
{
return windowsErrorString(code == -1 ? GetLastError() : code);
diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h
index abc2f1efc1..72ced63dc5 100644
--- a/src/corelib/kernel/qsystemerror_p.h
+++ b/src/corelib/kernel/qsystemerror_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSYSTEMERROR_P_H
#define QSYSTEMERROR_P_H
@@ -66,23 +30,32 @@ public:
NativeError
};
- Q_DECL_CONSTEXPR explicit QSystemError(int error, ErrorScope scope)
+ constexpr explicit QSystemError(int error, ErrorScope scope)
: errorCode(error), errorScope(scope)
{
}
- Q_DECL_CONSTEXPR QSystemError() = default;
+ constexpr QSystemError() = default;
QString toString() const { return string(errorScope, errorCode); }
- Q_DECL_CONSTEXPR ErrorScope scope() const { return errorScope; }
- Q_DECL_CONSTEXPR int error() const { return errorCode; }
+ constexpr ErrorScope scope() const { return errorScope; }
+ constexpr int error() const { return errorCode; }
+
+ constexpr bool ok() const noexcept { return errorScope == NoError; }
+ static constexpr QSystemError stdError(int error)
+ { return QSystemError(error, StandardLibraryError); }
static Q_CORE_EXPORT QString string(ErrorScope errorScope, int errorCode);
static Q_CORE_EXPORT QString stdString(int errorCode = -1);
#ifdef Q_OS_WIN
static Q_CORE_EXPORT QString windowsString(int errorCode = -1);
+ using HRESULT = long;
+ static Q_CORE_EXPORT QString windowsComString(HRESULT hr);
+
+ static constexpr QSystemError nativeError(int error)
+ { return QSystemError(error, NativeError); }
#endif
- //data members
+ // data members
int errorCode = 0;
ErrorScope errorScope = NoError;
};
diff --git a/src/corelib/kernel/qsystemsemaphore.h b/src/corelib/kernel/qsystemsemaphore.h
deleted file mode 100644
index d6a4301df6..0000000000
--- a/src/corelib/kernel/qsystemsemaphore.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSYSTEMSEMAPHORE_H
-#define QSYSTEMSEMAPHORE_H
-
-#include <QtCore/qstring.h>
-#include <QtCore/qscopedpointer.h>
-
-QT_BEGIN_NAMESPACE
-
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-class QSystemSemaphorePrivate;
-
-class Q_CORE_EXPORT QSystemSemaphore
-{
-
-public:
- enum AccessMode
- {
- Open,
- Create
- };
-
- enum SystemSemaphoreError
- {
- NoError,
- PermissionDenied,
- KeyError,
- AlreadyExists,
- NotFound,
- OutOfResources,
- UnknownError
- };
-
- QSystemSemaphore(const QString &key, int initialValue = 0, AccessMode mode = Open);
- ~QSystemSemaphore();
-
- void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open);
- QString key() const;
-
- bool acquire();
- bool release(int n = 1);
-
- SystemSemaphoreError error() const;
- QString errorString() const;
-
-private:
- Q_DISABLE_COPY(QSystemSemaphore)
- QScopedPointer<QSystemSemaphorePrivate> d;
-};
-
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-QT_END_NAMESPACE
-
-#endif // QSYSTEMSEMAPHORE_H
-
diff --git a/src/corelib/kernel/qsystemsemaphore_android.cpp b/src/corelib/kernel/qsystemsemaphore_android.cpp
deleted file mode 100644
index 149215bc30..0000000000
--- a/src/corelib/kernel/qsystemsemaphore_android.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Collabora Ltd, author <robin.burchell@collabora.co.uk>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsystemsemaphore.h"
-#include "qsystemsemaphore_p.h"
-
-#include <qdebug.h>
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-QT_BEGIN_NAMESPACE
-
-QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
- unix_key(-1), semaphore(-1), createdFile(false),
- createdSemaphore(false), error(QSystemSemaphore::NoError)
-{
-}
-
-void QSystemSemaphorePrivate::setErrorString(const QString &function)
-{
- Q_UNUSED(function);
- Q_UNIMPLEMENTED();
-}
-
-key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
-{
- Q_UNUSED(mode);
- Q_UNIMPLEMENTED();
- return -1;
-}
-
-void QSystemSemaphorePrivate::cleanHandle()
-{
- Q_UNIMPLEMENTED();
-}
-
-bool QSystemSemaphorePrivate::modifySemaphore(int count)
-{
- Q_UNUSED(count);
- Q_UNIMPLEMENTED();
- return false;
-}
-
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h
deleted file mode 100644
index 3b55d80276..0000000000
--- a/src/corelib/kernel/qsystemsemaphore_p.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSYSTEMSEMAPHORE_P_H
-#define QSYSTEMSEMAPHORE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qsystemsemaphore.h"
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-#include "qsharedmemory_p.h"
-#include <sys/types.h>
-#ifdef QT_POSIX_IPC
-# include <semaphore.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-class QSystemSemaphorePrivate
-{
-
-public:
- QSystemSemaphorePrivate();
-
- QString makeKeyFileName()
- {
- return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemsem_"));
- }
-
- inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
- { error = e; errorString = message; }
- inline void clearError()
- { setError(QSystemSemaphore::NoError, QString()); }
-
-#ifdef Q_OS_WIN
- Qt::HANDLE handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
- void setErrorString(const QString &function);
-#elif defined(QT_POSIX_IPC)
- bool handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
- void setErrorString(const QString &function);
-#else
- key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
- void setErrorString(const QString &function);
-#endif
- void cleanHandle();
- bool modifySemaphore(int count);
-
- QString key;
- QString fileName;
- int initialValue;
-#ifdef Q_OS_WIN
- Qt::HANDLE semaphore;
- Qt::HANDLE semaphoreLock;
-#elif defined(QT_POSIX_IPC)
- sem_t *semaphore;
- bool createdSemaphore;
-#else
- key_t unix_key;
- int semaphore;
- bool createdFile;
- bool createdSemaphore;
-#endif
- QString errorString;
- QSystemSemaphore::SystemSemaphoreError error;
-};
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-#endif // QSYSTEMSEMAPHORE_P_H
-
diff --git a/src/corelib/kernel/qsystemsemaphore_posix.cpp b/src/corelib/kernel/qsystemsemaphore_posix.cpp
deleted file mode 100644
index 9fbf5779b8..0000000000
--- a/src/corelib/kernel/qsystemsemaphore_posix.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Konstantin Ritt <ritt.ks@gmail.com>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsystemsemaphore.h"
-#include "qsystemsemaphore_p.h"
-
-#include <qdebug.h>
-#include <qfile.h>
-#include <qcoreapplication.h>
-
-#ifdef QT_POSIX_IPC
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "private/qcore_unix_p.h"
-
-// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
-// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
-#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
-#define EIDRM EINVAL
-#endif
-
-QT_BEGIN_NAMESPACE
-
-bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
-{
- if (semaphore != SEM_FAILED)
- return true; // we already have a semaphore
-
- if (fileName.isEmpty()) {
- errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle"));
- error = QSystemSemaphore::KeyError;
- return false;
- }
-
- const QByteArray semName = QFile::encodeName(fileName);
-
- // Always try with O_EXCL so we know whether we created the semaphore.
- int oflag = O_CREAT | O_EXCL;
- for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) {
- do {
- semaphore = ::sem_open(semName.constData(), oflag, 0600, initialValue);
- } while (semaphore == SEM_FAILED && errno == EINTR);
- if (semaphore == SEM_FAILED && errno == EEXIST) {
- if (mode == QSystemSemaphore::Create) {
- if (::sem_unlink(semName.constData()) == -1 && errno != ENOENT) {
- setErrorString(QLatin1String("QSystemSemaphore::handle (sem_unlink)"));
- return false;
- }
- // Race condition: the semaphore might be recreated before
- // we call sem_open again, so we'll retry several times.
- maxTries = 3;
- } else {
- // Race condition: if it no longer exists at the next sem_open
- // call, we won't realize we created it, so we'll leak it later.
- oflag &= ~O_EXCL;
- maxTries = 2;
- }
- } else {
- break;
- }
- }
-
- if (semaphore == SEM_FAILED) {
- setErrorString(QLatin1String("QSystemSemaphore::handle"));
- return false;
- }
-
- createdSemaphore = (oflag & O_EXCL) != 0;
-
- return true;
-}
-
-void QSystemSemaphorePrivate::cleanHandle()
-{
- if (semaphore != SEM_FAILED) {
- if (::sem_close(semaphore) == -1) {
- setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::cleanHandle sem_close failed.");
-#endif
- }
- semaphore = SEM_FAILED;
- }
-
- if (createdSemaphore) {
- if (::sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) {
- setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_unlink)"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::cleanHandle sem_unlink failed.");
-#endif
- }
- createdSemaphore = false;
- }
-}
-
-bool QSystemSemaphorePrivate::modifySemaphore(int count)
-{
- if (!handle())
- return false;
-
- if (count > 0) {
- int cnt = count;
- do {
- if (::sem_post(semaphore) == -1) {
- setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::modify sem_post failed %d %d", count, errno);
-#endif
- // rollback changes to preserve the SysV semaphore behavior
- for ( ; cnt < count; ++cnt) {
- int res;
- EINTR_LOOP(res, ::sem_wait(semaphore));
- }
- return false;
- }
- --cnt;
- } while (cnt > 0);
- } else {
- int res;
- EINTR_LOOP(res, ::sem_wait(semaphore));
- if (res == -1) {
- // If the semaphore was removed be nice and create it and then modifySemaphore again
- if (errno == EINVAL || errno == EIDRM) {
- semaphore = SEM_FAILED;
- return modifySemaphore(count);
- }
- setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_wait)"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::modify sem_wait failed %d %d", count, errno);
-#endif
- return false;
- }
- }
-
- clearError();
- return true;
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
deleted file mode 100644
index 2c38d74d2d..0000000000
--- a/src/corelib/kernel/qsystemsemaphore_systemv.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsystemsemaphore.h"
-#include "qsystemsemaphore_p.h"
-
-#include <qdebug.h>
-#include <qfile.h>
-#include <qcoreapplication.h>
-
-#ifndef QT_POSIX_IPC
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "private/qcore_unix_p.h"
-
-// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
-// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
-#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
-#define EIDRM EINVAL
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \internal
-
- Setup unix_key
- */
-key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
-{
- if (key.isEmpty()){
- errorString =
-#if QT_CONFIG(translation)
- QCoreApplication::tr("%1: key is empty", "QSystemSemaphore")
-#else
- QLatin1String("%1: key is empty")
-#endif
- .arg(QLatin1String("QSystemSemaphore::handle:"));
- error = QSystemSemaphore::KeyError;
- return -1;
- }
-
- // ftok requires that an actual file exists somewhere
- if (-1 != unix_key)
- return unix_key;
-
- // Create the file needed for ftok
- int built = QSharedMemoryPrivate::createUnixKeyFile(fileName);
- if (-1 == built) {
- errorString =
-#if QT_CONFIG(translation)
- QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore")
-#else
- QLatin1String("%1: unable to make key")
-#endif
- .arg(QLatin1String("QSystemSemaphore::handle:"));
- error = QSystemSemaphore::KeyError;
- return -1;
- }
- createdFile = (1 == built);
-
-#if !defined(QT_NO_SHAREDMEMORY) && !defined(QT_POSIX_IPC) && !defined(Q_OS_ANDROID)
- // Get the unix key for the created file
- unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
-#endif
- if (-1 == unix_key) {
- errorString =
-#if QT_CONFIG(translation)
- QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore")
-#else
- QLatin1String("%1: ftok failed")
-#endif
- .arg(QLatin1String("QSystemSemaphore::handle:"));
- error = QSystemSemaphore::KeyError;
- return -1;
- }
-
- // Get semaphore
- semaphore = semget(unix_key, 1, 0600 | IPC_CREAT | IPC_EXCL);
- if (-1 == semaphore) {
- if (errno == EEXIST)
- semaphore = semget(unix_key, 1, 0600 | IPC_CREAT);
- if (-1 == semaphore) {
- setErrorString(QLatin1String("QSystemSemaphore::handle"));
- cleanHandle();
- return -1;
- }
- } else {
- createdSemaphore = true;
- // Force cleanup of file, it is possible that it can be left over from a crash
- createdFile = true;
- }
-
- if (mode == QSystemSemaphore::Create) {
- createdSemaphore = true;
- createdFile = true;
- }
-
- // Created semaphore so initialize its value.
- if (createdSemaphore && initialValue >= 0) {
- qt_semun init_op;
- init_op.val = initialValue;
- if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
- setErrorString(QLatin1String("QSystemSemaphore::handle"));
- cleanHandle();
- return -1;
- }
- }
-
- return unix_key;
-}
-
-/*!
- \internal
-
- Cleanup the unix_key
- */
-void QSystemSemaphorePrivate::cleanHandle()
-{
- unix_key = -1;
-
- // remove the file if we made it
- if (createdFile) {
- QFile::remove(fileName);
- createdFile = false;
- }
-
- if (createdSemaphore) {
- if (-1 != semaphore) {
- if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
- setErrorString(QLatin1String("QSystemSemaphore::cleanHandle"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::cleanHandle semctl failed.");
-#endif
- }
- semaphore = -1;
- }
- createdSemaphore = false;
- }
-}
-
-/*!
- \internal
- */
-bool QSystemSemaphorePrivate::modifySemaphore(int count)
-{
- if (-1 == handle())
- return false;
-
- struct sembuf operation;
- operation.sem_num = 0;
- operation.sem_op = count;
- operation.sem_flg = SEM_UNDO;
-
- int res;
- EINTR_LOOP(res, semop(semaphore, &operation, 1));
- if (-1 == res) {
- // If the semaphore was removed be nice and create it and then modifySemaphore again
- if (errno == EINVAL || errno == EIDRM) {
- semaphore = -1;
- cleanHandle();
- handle();
- return modifySemaphore(count);
- }
- setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::modify failed %d %d %d %d %d",
- count, int(semctl(semaphore, 0, GETVAL)), int(errno), int(EIDRM), int(EINVAL);
-#endif
- return false;
- }
-
- clearError();
- return true;
-}
-
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SYSTEMSEMAPHORE
-
-#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
deleted file mode 100644
index f12a808891..0000000000
--- a/src/corelib/kernel/qsystemsemaphore_unix.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsystemsemaphore.h"
-#include "qsystemsemaphore_p.h"
-
-#include <qdebug.h>
-#include <qcoreapplication.h>
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-#include <sys/types.h>
-#ifndef QT_POSIX_IPC
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#endif
-#include <fcntl.h>
-#include <errno.h>
-
-#include "private/qcore_unix_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
-#ifndef QT_POSIX_IPC
- unix_key(-1), semaphore(-1), createdFile(false),
-#else
- semaphore(SEM_FAILED),
-#endif // QT_POSIX_IPC
- createdSemaphore(false), error(QSystemSemaphore::NoError)
-{
-}
-
-void QSystemSemaphorePrivate::setErrorString(const QString &function)
-{
- // EINVAL is handled in functions so they can give better error strings
- switch (errno) {
- case EPERM:
- case EACCES:
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: permission denied").arg(function);
- error = QSystemSemaphore::PermissionDenied;
- break;
- case EEXIST:
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: already exists").arg(function);
- error = QSystemSemaphore::AlreadyExists;
- break;
- case ENOENT:
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: does not exist").arg(function);
- error = QSystemSemaphore::NotFound;
- break;
- case ERANGE:
- case ENOSPC:
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function);
- error = QSystemSemaphore::OutOfResources;
- break;
- default:
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(errno);
- error = QSystemSemaphore::UnknownError;
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
-#endif
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
deleted file mode 100644
index d19476db4a..0000000000
--- a/src/corelib/kernel/qsystemsemaphore_win.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsystemsemaphore.h"
-#include "qsystemsemaphore_p.h"
-#include "qcoreapplication.h"
-#include <qdebug.h>
-#include <qt_windows.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_SYSTEMSEMAPHORE
-
-QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
- semaphore(0), error(QSystemSemaphore::NoError)
-{
-}
-
-void QSystemSemaphorePrivate::setErrorString(const QString &function)
-{
- BOOL windowsError = GetLastError();
- if (windowsError == 0)
- return;
-
- switch (windowsError) {
- case ERROR_NO_SYSTEM_RESOURCES:
- case ERROR_NOT_ENOUGH_MEMORY:
- error = QSystemSemaphore::OutOfResources;
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function);
- break;
- case ERROR_ACCESS_DENIED:
- error = QSystemSemaphore::PermissionDenied;
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: permission denied").arg(function);
- break;
- default:
- errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(windowsError);
- error = QSystemSemaphore::UnknownError;
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << errorString << "key" << key;
-#endif
- }
-}
-
-HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
-{
- // don't allow making handles on empty keys
- if (key.isEmpty())
- return 0;
-
- // Create it if it doesn't already exists.
- if (semaphore == 0) {
- semaphore = CreateSemaphore(0, initialValue, MAXLONG,
- reinterpret_cast<const wchar_t*>(fileName.utf16()));
- if (semaphore == NULL)
- setErrorString(QLatin1String("QSystemSemaphore::handle"));
- }
-
- return semaphore;
-}
-
-void QSystemSemaphorePrivate::cleanHandle()
-{
- if (semaphore && !CloseHandle(semaphore)) {
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphorePrivate::CloseHandle: sem failed");
-#endif
- }
- semaphore = 0;
-}
-
-bool QSystemSemaphorePrivate::modifySemaphore(int count)
-{
- if (0 == handle())
- return false;
-
- if (count > 0) {
- if (0 == ReleaseSemaphore(semaphore, count, 0)) {
- setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
-#endif
- return false;
- }
- } else {
- if (WAIT_OBJECT_0 != WaitForSingleObjectEx(semaphore, INFINITE, FALSE)) {
- setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug("QSystemSemaphore::modifySemaphore WaitForSingleObject failed");
-#endif
- return false;
- }
- }
-
- clearError();
- return true;
-}
-
-#endif //QT_NO_SYSTEMSEMAPHORE
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qt_attribution.json b/src/corelib/kernel/qt_attribution.json
index 6d8f4f2abc..86ca3a2664 100644
--- a/src/corelib/kernel/qt_attribution.json
+++ b/src/corelib/kernel/qt_attribution.json
@@ -3,9 +3,9 @@
"Name": "QEventDispatcher on macOS",
"QDocModule": "qtcore",
"QtUsage": "Used in Qt Core on macOS.",
- "Path": "qeventdispatcher_cf_p.h",
+ "Files": "qeventdispatcher_cf_p.h",
- "Description": "Treat as final version; no upstream known",
+ "Comment": "Treat as final version; no upstream known",
"Description": "Implementation of QAbstractEventDispatcher for macOS.",
"License": "BSD 3-clause \"New\" or \"Revised\" License",
"LicenseId": "BSD-3-Clause",
diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp
index 928c8021bc..2ac44bb13d 100644
--- a/src/corelib/kernel/qtestsupport_core.cpp
+++ b/src/corelib/kernel/qtestsupport_core.cpp
@@ -1,82 +1,103 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtestsupport_core.h"
-#ifdef Q_OS_WIN
-#include <qt_windows.h>
-#endif
+#include <thread>
+
+using namespace std::chrono_literals;
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
+/*!
+ \overload
+
+ Sleeps for \a ms milliseconds, blocking execution of the test.
+
+ Equivalent to calling:
+ \code
+ QTest::qSleep(std::chrono::milliseconds{ms});
+ \endcode
+*/
+void QTest::qSleep(int ms)
{
- Q_ASSERT(ms > 0);
-
-#if defined(Q_OS_WIN)
- Sleep(uint(ms));
-#else
- struct timespec ts = { time_t(ms / 1000), (ms % 1000) * 1000 * 1000 };
- nanosleep(&ts, nullptr);
-#endif
+ QTest::qSleep(std::chrono::milliseconds{ms});
+}
+
+/*!
+ \since 6.7
+
+ Sleeps for \a msecs, blocking execution of the test.
+
+ This method will not do any event processing and will leave your test
+ unresponsive. Network communication might time out while sleeping.
+ Use \l {QTest::qWait()} to do non-blocking sleeping.
+
+ \a msecs must be greater than 0ms.
+
+ \note Starting from Qt 6.7, this function is implemented using
+ \c {std::this_thread::sleep_for}, so the accuracy of time spent depends
+ on the Standard Library implementation. Before Qt 6.7 this function called
+ either \c nanosleep() on Unix or \c Sleep() on Windows, so the accuracy of
+ time spent in this function depended on the operating system.
+
+ Example:
+ \snippet code/src_qtestlib_qtestcase.cpp 23
+
+ \sa {QTest::qWait()}
+*/
+void QTest::qSleep(std::chrono::milliseconds msecs)
+{
+ Q_ASSERT(msecs > 0ms);
+ std::this_thread::sleep_for(msecs);
}
/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
+ \since 5.10
+ \overload
+
Waits for \a timeout milliseconds or until the \a predicate returns true.
- Returns \c true if the \a predicate returned true at any point, otherwise returns \c false.
+ This is equivalent to calling:
+ \code
+ qWaitFor(predicate, QDeadlineTimer(timeout));
+ \endcode
+*/
+
+/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, QDeadlineTimer deadline)
+ \since 6.7
+
+ Waits until \a deadline has expired, or until \a predicate returns true, whichever
+ happens first.
+
+ Returns \c true if \a predicate returned true at any point, otherwise returns \c false.
Example:
- \snippet code/src_corelib_kernel_qtestsupport_core_snippet.cpp 0
+ \snippet code/src_corelib_kernel_qtestsupport_core.cpp 2
The code above will wait for the object to become ready, for a
maximum of three seconds.
-
- \since 5.10
*/
+/*!
+ \overload
+
+ Waits for \a msecs. Equivalent to calling:
+ \code
+ QTest::qWait(std::chrono::milliseconds{msecs});
+ \endcode
+*/
+Q_CORE_EXPORT void QTest::qWait(int msecs)
+{
+ qWait(std::chrono::milliseconds{msecs});
+}
-/*! \fn void QTest::qWait(int ms)
+/*!
+ \since 6.7
- Waits for \a ms milliseconds. While waiting, events will be processed and
+ Waits for \a msecs. While waiting, events will be processed and
your test will stay responsive to user interface events or network communication.
Example:
@@ -88,25 +109,34 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
\sa QTest::qSleep(), QSignalSpy::wait()
*/
-Q_CORE_EXPORT void QTest::qWait(int ms)
+Q_CORE_EXPORT void QTest::qWait(std::chrono::milliseconds msecs)
{
- // Ideally this method would be implemented in terms of qWaitFor, with
- // a predicate that always returns false, but due to a compiler bug in
- // GCC 6 we can't do that.
+ // Ideally this method would be implemented in terms of qWaitFor(), with a
+ // predicate that always returns false, but qWaitFor() uses the 1-arg overload
+ // of processEvents(), which doesn't handle events posted in this round of event
+ // processing, which, together with the 10ms qSleep() after every processEvents(),
+ // lead to a 10x slow-down in some webengine tests.
Q_ASSERT(QCoreApplication::instance());
- QDeadlineTimer timer(ms, Qt::PreciseTimer);
- int remaining = ms;
+ using namespace std::chrono;
+
+ QDeadlineTimer deadline(msecs, Qt::PreciseTimer);
+
do {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::processEvents(QEventLoop::AllEvents, deadline);
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- remaining = timer.remainingTime();
- if (remaining <= 0)
+
+ // If dealine is Forever, processEvents() has already looped forever
+ if (deadline.isForever())
+ break;
+
+ msecs = ceil<milliseconds>(deadline.remainingTimeAsDuration());
+ if (msecs == 0ms)
break;
- QTestPrivate::qSleep(qMin(10, remaining));
- remaining = timer.remainingTime();
- } while (remaining > 0);
+
+ QTest::qSleep(std::min(10ms, msecs));
+ } while (!deadline.hasExpired());
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtestsupport_core.h b/src/corelib/kernel/qtestsupport_core.h
index 24399dd7a9..27265903af 100644
--- a/src/corelib/kernel/qtestsupport_core.h
+++ b/src/corelib/kernel/qtestsupport_core.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTESTSUPPORT_CORE_H
#define QTESTSUPPORT_CORE_H
@@ -43,28 +7,26 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdeadlinetimer.h>
-QT_BEGIN_NAMESPACE
+#include <chrono>
-namespace QTestPrivate {
-Q_CORE_EXPORT void qSleep(int ms);
-}
+QT_BEGIN_NAMESPACE
namespace QTest {
+Q_CORE_EXPORT void qSleep(int ms);
+Q_CORE_EXPORT void qSleep(std::chrono::milliseconds msecs);
+
template <typename Functor>
-Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
+[[nodiscard]] bool
+qWaitFor(Functor predicate, QDeadlineTimer deadline = QDeadlineTimer(std::chrono::seconds{5}))
{
// We should not spin the event loop in case the predicate is already true,
// otherwise we might send new events that invalidate the predicate.
if (predicate())
return true;
- // qWait() is expected to spin the event loop, even when called with a small
- // timeout like 1ms, so we we can't use a simple while-loop here based on
- // the deadline timer not having timed out. Use do-while instead.
-
- int remaining = timeout;
- QDeadlineTimer deadline(remaining, Qt::PreciseTimer);
+ // qWait() is expected to spin the event loop at least once, even when
+ // called with a small timeout like 1ns.
do {
// We explicitly do not pass the remaining time to processEvents, as
@@ -76,21 +38,29 @@ Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
QCoreApplication::processEvents(QEventLoop::AllEvents);
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- remaining = int(deadline.remainingTime());
- if (remaining > 0)
- QTestPrivate::qSleep(qMin(10, remaining));
-
if (predicate())
return true;
- remaining = int(deadline.remainingTime());
- } while (remaining > 0);
+ using namespace std::chrono;
+
+ if (const auto remaining = deadline.remainingTimeAsDuration(); remaining > 0ns)
+ qSleep((std::min)(10ms, ceil<milliseconds>(remaining)));
+
+ } while (!deadline.hasExpired());
return predicate(); // Last chance
}
+template <typename Functor>
+[[nodiscard]] bool qWaitFor(Functor predicate, int timeout)
+{
+ return qWaitFor(predicate, QDeadlineTimer{timeout, Qt::PreciseTimer});
+}
+
Q_CORE_EXPORT void qWait(int ms);
+Q_CORE_EXPORT void qWait(std::chrono::milliseconds msecs);
+
} // namespace QTest
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 25ce0c032f..294369c1b3 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -1,49 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimer.h"
+#include "qtimer_p.h"
+#include "qsingleshottimer_p.h"
+
#include "qabstracteventdispatcher.h"
#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qdeadlinetimer.h"
+#include "qmetaobject_p.h"
#include "qobject_p.h"
+#include "qproperty_p.h"
#include "qthread.h"
-#include "qcoreapplication_p.h"
+
+using namespace std::chrono_literals;
QT_BEGIN_NAMESPACE
@@ -102,6 +74,13 @@ QT_BEGIN_NAMESPACE
more and more platforms, we expect that zero-millisecond
QTimer objects will gradually be replaced by \l{QThread}s.
+ \note Since Qt 6.7 this class is superseded by \l{QChronoTimer}.
+ The maximum interval QTimer supports is limited by the number of
+ milliseconds that would fit in an \c int (which is around 24 days);
+ whereas QChronoTimer stores its interval as \c std::chrono::nanoseconds
+ (which raises that limit to around 292 million years), that is, there is
+ less chance of integer overflow with QChronoTimer.
+
\section1 Accuracy and Timer Resolution
The accuracy of timers depends on the underlying operating system
@@ -138,19 +117,17 @@ QT_BEGIN_NAMESPACE
used; Qt tries to work around these limitations.
\sa QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers,
- {Analog Clock Example}, {Wiggly Example}
+ {Analog Clock}
*/
-static const int INV_TIMER = -1; // invalid timer id
-
/*!
Constructs a timer with the given \a parent.
*/
QTimer::QTimer(QObject *parent)
- : QObject(parent), id(INV_TIMER), inter(0), del(0), single(0), nulltimer(0), type(Qt::CoarseTimer)
+ : QObject(*new QTimerPrivate(this), parent)
{
- Q_UNUSED(del); // ### Qt 6: remove field
+ Q_ASSERT(d_func()->isQTimer);
}
@@ -160,7 +137,7 @@ QTimer::QTimer(QObject *parent)
QTimer::~QTimer()
{
- if (id != INV_TIMER) // stop running timer
+ if (d_func()->isActive()) // stop running timer
stop();
}
@@ -187,6 +164,15 @@ QTimer::~QTimer()
Returns \c true if the timer is running (pending); otherwise returns
false.
*/
+bool QTimer::isActive() const
+{
+ return d_func()->isActiveData.value();
+}
+
+QBindable<bool> QTimer::bindableActive()
+{
+ return QBindable<bool>(&d_func()->isActiveData);
+}
/*!
\fn int QTimer::timerId() const
@@ -194,7 +180,23 @@ QTimer::~QTimer()
Returns the ID of the timer if the timer is running; otherwise returns
-1.
*/
+int QTimer::timerId() const
+{
+ auto v = qToUnderlying(id());
+ return v == 0 ? -1 : v;
+}
+/*!
+ \since 6.8
+ Returns a Qt::TimerId representing the timer ID if the timer is running;
+ otherwise returns \c Qt::TimerId::Invalid.
+
+ \sa Qt::TimerId
+*/
+Qt::TimerId QTimer::id() const
+{
+ return d_func()->id;
+}
/*! \overload start()
@@ -207,10 +209,15 @@ QTimer::~QTimer()
*/
void QTimer::start()
{
- if (id != INV_TIMER) // stop running timer
+ Q_D(QTimer);
+ if (d->isActive()) // stop running timer
stop();
- nulltimer = (!inter && single);
- id = QObject::startTimer(inter, Qt::TimerType(type));
+
+ Qt::TimerId newId{ QObject::startTimer(d->inter * 1ms, d->type) }; // overflow impossible
+ if (newId > Qt::TimerId::Invalid) {
+ d->id = newId;
+ d->isActiveData.notify();
+ }
}
/*!
@@ -220,13 +227,33 @@ void QTimer::start()
If the timer is already running, it will be
\l{QTimer::stop()}{stopped} and restarted.
- If \l singleShot is true, the timer will be activated only once.
+ If \l singleShot is true, the timer will be activated only once. This is
+ equivalent to:
+ \code
+ timer.setInterval(msec);
+ timer.start();
+ \endcode
+
+ \note Keeping the event loop busy with a zero-timer is bound to
+ cause trouble and highly erratic behavior of the UI.
*/
void QTimer::start(int msec)
{
- inter = msec;
+ start(msec * 1ms);
+}
+
+void QTimer::start(std::chrono::milliseconds interval)
+{
+ Q_D(QTimer);
+ // This could be narrowing as the interval is stored in an `int` QProperty,
+ // and the type can't be changed in Qt6.
+ const int msec = interval.count();
+ const bool intervalChanged = msec != d->inter;
+ d->inter.setValue(msec);
start();
+ if (intervalChanged)
+ d->inter.notify();
}
@@ -239,9 +266,11 @@ void QTimer::start(int msec)
void QTimer::stop()
{
- if (id != INV_TIMER) {
- QObject::killTimer(id);
- id = INV_TIMER;
+ Q_D(QTimer);
+ if (d->isActive()) {
+ QObject::killTimer(d->id);
+ d->id = Qt::TimerId::Invalid;
+ d->isActiveData.notify();
}
}
@@ -251,84 +280,14 @@ void QTimer::stop()
*/
void QTimer::timerEvent(QTimerEvent *e)
{
- if (e->timerId() == id) {
- if (single)
+ Q_D(QTimer);
+ if (Qt::TimerId{e->timerId()} == d->id) {
+ if (d->single)
stop();
emit timeout(QPrivateSignal());
}
}
-class QSingleShotTimer : public QObject
-{
- Q_OBJECT
- int timerId;
- bool hasValidReceiver;
- QPointer<const QObject> receiver;
- QtPrivate::QSlotObjectBase *slotObj;
-public:
- ~QSingleShotTimer();
- QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char * m);
- QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj);
-
-Q_SIGNALS:
- void timeout();
-protected:
- void timerEvent(QTimerEvent *) override;
-};
-
-QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member)
- : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(true), slotObj(nullptr)
-{
- timerId = startTimer(msec, timerType);
- connect(this, SIGNAL(timeout()), r, member);
-}
-
-QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
- : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(r), receiver(r), slotObj(slotObj)
-{
- timerId = startTimer(msec, timerType);
- if (r && thread() != r->thread()) {
- // Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires
- connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
- setParent(nullptr);
- moveToThread(r->thread());
- }
-}
-
-QSingleShotTimer::~QSingleShotTimer()
-{
- if (timerId > 0)
- killTimer(timerId);
- if (slotObj)
- slotObj->destroyIfLastRef();
-}
-
-void QSingleShotTimer::timerEvent(QTimerEvent *)
-{
- // need to kill the timer _before_ we emit timeout() in case the
- // slot connected to timeout calls processEvents()
- if (timerId > 0)
- killTimer(timerId);
- timerId = -1;
-
- if (slotObj) {
- // If the receiver was destroyed, skip this part
- if (Q_LIKELY(!receiver.isNull() || !hasValidReceiver)) {
- // We allocate only the return type - we previously checked the function had
- // no arguments.
- void *args[1] = { nullptr };
- slotObj->call(const_cast<QObject*>(receiver.data()), args);
- }
- } else {
- emit timeout();
- }
-
- // we would like to use delete later here, but it feels like a
- // waste to post a new event to handle this event, so we just unset the flag
- // and explicitly delete...
- qDeleteInEventHandler(this);
-}
-
/*!
\internal
@@ -338,14 +297,13 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
\a timerType is the timer type
\a receiver is the receiver object, can be null. In such a case, it will be the same
as the final sender class.
- \a slot a pointer only used when using Qt::UniqueConnection
\a slotObj the slot object
- */
-void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
+*/
+void QTimer::singleShotImpl(std::chrono::milliseconds msec, Qt::TimerType timerType,
const QObject *receiver,
QtPrivate::QSlotObjectBase *slotObj)
{
- if (msec == 0) {
+ if (msec == 0ms) {
bool deleteReceiver = false;
// Optimize: set a receiver context when none is given, such that we can use
// QMetaObject::invokeMethod which is more efficient than going through a timer.
@@ -364,19 +322,23 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
deleteReceiver = true;
}
+ auto h = QtPrivate::invokeMethodHelper({});
QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
- Qt::QueuedConnection, nullptr);
+ Qt::QueuedConnection, h.parameterCount(), h.parameters.data(), h.typeNames.data(),
+ h.metaTypes.data());
if (deleteReceiver)
const_cast<QObject *>(receiver)->deleteLater();
return;
}
- new QSingleShotTimer(msec, timerType, receiver, slotObj);
+ new QSingleShotTimer(QSingleShotTimer::fromMsecs(msec), timerType, receiver, slotObj);
}
/*!
+ \fn void QTimer::singleShot(int msec, const QObject *receiver, const char *member)
\reentrant
+ \deprecated [6.8] Use the chrono overloads.
This static function calls a slot after a given time interval.
It is very convenient to use this function because you do not need
@@ -395,16 +357,11 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
\sa start()
*/
-void QTimer::singleShot(int msec, const QObject *receiver, const char *member)
-{
- // coarse timers are worst in their first firing
- // so we prefer a high precision timer for something that happens only once
- // unless the timeout is too big, in which case we go for coarse anyway
- singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, receiver, member);
-}
-
-/*! \overload
+/*!
+ \fn void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member)
+ \overload
\reentrant
+ \deprecated [6.8] Use the chrono overloads.
This static function calls a slot after a given time interval.
It is very convenient to use this function because you do not need
@@ -417,147 +374,54 @@ void QTimer::singleShot(int msec, const QObject *receiver, const char *member)
\sa start()
*/
-void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member)
+
+void QTimer::singleShot(std::chrono::milliseconds msec, Qt::TimerType timerType,
+ const QObject *receiver, const char *member)
{
- if (Q_UNLIKELY(msec < 0)) {
+ if (Q_UNLIKELY(msec < 0ms)) {
qWarning("QTimer::singleShot: Timers cannot have negative timeouts");
return;
}
if (receiver && member) {
- if (msec == 0) {
+ if (msec == 0ms) {
// special code shortpath for 0-timers
const char* bracketPosition = strchr(member, '(');
if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) {
qWarning("QTimer::singleShot: Invalid slot specification");
return;
}
- QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name
- QMetaObject::invokeMethod(const_cast<QObject *>(receiver), methodName.constData(), Qt::QueuedConnection);
+ const auto methodName = QByteArrayView(member + 1, // extract method name
+ bracketPosition - 1 - member).trimmed();
+ QMetaObject::invokeMethod(const_cast<QObject *>(receiver), methodName.toByteArray().constData(),
+ Qt::QueuedConnection);
return;
}
- (void) new QSingleShotTimer(msec, timerType, receiver, member);
+ (void) new QSingleShotTimer(QSingleShotTimer::fromMsecs(msec), timerType, receiver, member);
}
}
-/*! \fn template<typename PointerToMemberFunction> void QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method)
-
- \since 5.4
-
- \overload
- \reentrant
- This static function calls a member function of a QObject after a given time interval.
-
- It is very convenient to use this function because you do not need
- to bother with a \l{QObject::timerEvent()}{timerEvent} or
- create a local QTimer object.
-
- The \a receiver is the receiving object and the \a method is the member function. The
- time interval is \a msec milliseconds.
-
- If \a receiver is destroyed before the interval occurs, the method will not be called.
- The function will be run in the thread of \a receiver. The receiver's thread must have
- a running Qt event loop.
-
- \sa start()
-*/
-
-/*! \fn template<typename PointerToMemberFunction> void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method)
-
- \since 5.4
-
- \overload
- \reentrant
- This static function calls a member function of a QObject after a given time interval.
-
- It is very convenient to use this function because you do not need
- to bother with a \l{QObject::timerEvent()}{timerEvent} or
- create a local QTimer object.
-
- The \a receiver is the receiving object and the \a method is the member function. The
- time interval is \a msec milliseconds. The \a timerType affects the
- accuracy of the timer.
-
- If \a receiver is destroyed before the interval occurs, the method will not be called.
- The function will be run in the thread of \a receiver. The receiver's thread must have
- a running Qt event loop.
-
- \sa start()
-*/
-
-/*! \fn template<typename Functor> void QTimer::singleShot(int msec, Functor functor)
-
- \since 5.4
-
- \overload
- \reentrant
- This static function calls \a functor after a given time interval.
-
- It is very convenient to use this function because you do not need
- to bother with a \l{QObject::timerEvent()}{timerEvent} or
- create a local QTimer object.
-
- The time interval is \a msec milliseconds.
-
- \sa start()
-*/
-
-/*! \fn template<typename Functor> void QTimer::singleShot(int msec, Qt::TimerType timerType, Functor functor)
-
+/*! \fn template<typename Duration, typename Functor> void QTimer::singleShot(Duration msec, const QObject *context, Functor &&functor)
+ \fn template<typename Duration, typename Functor> void QTimer::singleShot(Duration msec, Qt::TimerType timerType, const QObject *context, Functor &&functor)
+ \fn template<typename Duration, typename Functor> void QTimer::singleShot(Duration msec, Functor &&functor)
+ \fn template<typename Duration, typename Functor> void QTimer::singleShot(Duration msec, Qt::TimerType timerType, Functor &&functor)
\since 5.4
- \overload
\reentrant
- This static function calls \a functor after a given time interval.
+ This static function calls \a functor after \a msec milliseconds.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
- The time interval is \a msec milliseconds. The \a timerType affects the
- accuracy of the timer.
-
- \sa start()
-*/
-
-/*! \fn template<typename Functor> void QTimer::singleShot(int msec, const QObject *context, Functor functor)
-
- \since 5.4
-
- \overload
- \reentrant
- This static function calls \a functor after a given time interval.
+ If \a context is specified, then the \a functor will be called only if the
+ \a context object has not been destroyed before the interval occurs. The functor
+ will then be run the thread of \a context. The context's thread must have a
+ running Qt event loop.
- It is very convenient to use this function because you do not need
- to bother with a \l{QObject::timerEvent()}{timerEvent} or
- create a local QTimer object.
+ If \a functor is a member
+ function of \a context, then the function will be called on the object.
- The time interval is \a msec milliseconds.
-
- If \a context is destroyed before the interval occurs, the method will not be called.
- The function will be run in the thread of \a context. The context's thread must have
- a running Qt event loop.
-
- \sa start()
-*/
-
-/*! \fn template<typename Functor> void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor)
-
- \since 5.4
-
- \overload
- \reentrant
- This static function calls \a functor after a given time interval.
-
- It is very convenient to use this function because you do not need
- to bother with a \l{QObject::timerEvent()}{timerEvent} or
- create a local QTimer object.
-
- The time interval is \a msec milliseconds. The \a timerType affects the
- accuracy of the timer.
-
- If \a context is destroyed before the interval occurs, the method will not be called.
- The function will be run in the thread of \a context. The context's thread must have
- a running Qt event loop.
+ The \a msec parameter can be an \c int or a \c std::chrono::milliseconds value.
\sa start()
*/
@@ -600,43 +464,35 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
*/
/*!
- \fn template <typename Functor> QMetaObject::Connection QTimer::callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \fn template <typename Functor> QMetaObject::Connection QTimer::callOnTimeout(Functor &&slot)
\since 5.12
- \overload
- Creates a connection of type \a connectionType from the timeout() signal
- to \a slot, and returns a handle to the connection.
+ Creates a connection from the timer's timeout() signal to \a slot.
+ Returns a handle to the connection.
- This method is provided for convenience.
- It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, slot, connectionType)}.
+ This method is provided for convenience. It's equivalent to calling:
+ \code
+ QObject::connect(timer, &QTimer::timeout, timer, slot, Qt::DirectConnection);
+ \endcode
+
+ \note This overload is not available when \c {QT_NO_CONTEXTLESS_CONNECT} is
+ defined, instead use the callOnTimeout() overload that takes a context object.
\sa QObject::connect(), timeout()
*/
/*!
- \fn template <typename Functor> QMetaObject::Connection QTimer::callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \fn template <typename Functor> QMetaObject::Connection QTimer::callOnTimeout(const QObject *context, Functor &&slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
\since 5.12
\overload callOnTimeout()
Creates a connection from the timeout() signal to \a slot to be placed in a specific
event loop of \a context, and returns a handle to the connection.
- This method is provided for convenience. It's equivalent to calling
- \c {QObject::connect(timer, &QTimer::timeout, context, slot, connectionType)}.
-
- \sa QObject::connect(), timeout()
-*/
-
-/*!
- \fn template <typename MemberFunction> QMetaObject::Connection QTimer::callOnTimeout(const QObject *receiver, MemberFunction *slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
- \since 5.12
- \overload callOnTimeout()
-
- Creates a connection from the timeout() signal to the \a slot in the \a receiver object. Returns
- a handle to the connection.
-
- This method is provided for convenience. It's equivalent to calling
- \c {QObject::connect(timer, &QTimer::timeout, receiver, slot, connectionType)}.
+ This method is provided for convenience. It's equivalent to calling:
+ \code
+ QObject::connect(timer, &QTimer::timeout, context, slot, connectionType);
+ \endcode
\sa QObject::connect(), timeout()
*/
@@ -651,7 +507,13 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
If the timer is already running, it will be
\l{QTimer::stop()}{stopped} and restarted.
- If \l singleShot is true, the timer will be activated only once.
+ If \l singleShot is true, the timer will be activated only once. This is
+ equivalent to:
+
+ \code
+ timer.setInterval(msec);
+ timer.start();
+ \endcode
*/
/*!
@@ -687,6 +549,20 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
\sa interval, singleShot()
*/
+void QTimer::setSingleShot(bool singleShot)
+{
+ d_func()->single = singleShot;
+}
+
+bool QTimer::isSingleShot() const
+{
+ return d_func()->single;
+}
+
+QBindable<bool> QTimer::bindableSingleShot()
+{
+ return QBindable<bool>(&d_func()->single);
+}
/*!
\property QTimer::interval
@@ -702,11 +578,43 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
*/
void QTimer::setInterval(int msec)
{
- inter = msec;
- if (id != INV_TIMER) { // create new timer
- QObject::killTimer(id); // restart timer
- id = QObject::startTimer(msec, Qt::TimerType(type));
+ setInterval(std::chrono::milliseconds{msec});
+}
+
+void QTimer::setInterval(std::chrono::milliseconds interval)
+{
+ Q_D(QTimer);
+ // This could be narrowing as the interval is stored in an `int` QProperty,
+ // and the type can't be changed in Qt6.
+ const int msec = interval.count();
+ d->inter.removeBindingUnlessInWrapper();
+ const bool intervalChanged = msec != d->inter.valueBypassingBindings();
+ d->inter.setValueBypassingBindings(msec);
+ if (d->isActive()) { // create new timer
+ QObject::killTimer(d->id); // restart timer
+ Qt::TimerId newId{ QObject::startTimer(msec * 1ms, d->type) }; // overflow impossible
+ if (newId > Qt::TimerId::Invalid) {
+ // Restarted successfully. No need to update the active state.
+ d->id = newId;
+ } else {
+ // Failed to start the timer.
+ // Need to notify about active state change.
+ d->id = Qt::TimerId::Invalid;
+ d->isActiveData.notify();
+ }
}
+ if (intervalChanged)
+ d->inter.notify();
+}
+
+int QTimer::interval() const
+{
+ return d_func()->inter;
+}
+
+QBindable<int> QTimer::bindableInterval()
+{
+ return QBindable<int>(&d_func()->inter);
}
/*!
@@ -722,8 +630,11 @@ void QTimer::setInterval(int msec)
*/
int QTimer::remainingTime() const
{
- if (id != INV_TIMER) {
- return QAbstractEventDispatcher::instance()->remainingTime(id);
+ Q_D(const QTimer);
+ if (d->isActive()) {
+ using namespace std::chrono;
+ auto remaining = QAbstractEventDispatcher::instance()->remainingTime(d->id);
+ return ceil<milliseconds>(remaining).count();
}
return -1;
@@ -737,8 +648,21 @@ int QTimer::remainingTime() const
\sa Qt::TimerType
*/
+void QTimer::setTimerType(Qt::TimerType atype)
+{
+ d_func()->type = atype;
+}
+
+Qt::TimerType QTimer::timerType() const
+{
+ return d_func()->type;
+}
+
+QBindable<Qt::TimerType> QTimer::bindableTimerType()
+{
+ return QBindable<Qt::TimerType>(&d_func()->type);
+}
QT_END_NAMESPACE
-#include "qtimer.moc"
#include "moc_qtimer.cpp"
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index c55fd8d6c3..854d9072f2 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTIMER_H
#define QTIMER_H
@@ -47,118 +11,92 @@
#include <QtCore/qbasictimer.h> // conceptual inheritance
#include <QtCore/qobject.h>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
-
+class QTimerPrivate;
class Q_CORE_EXPORT QTimer : public QObject
{
Q_OBJECT
- Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot)
- Q_PROPERTY(int interval READ interval WRITE setInterval)
+ Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot BINDABLE bindableSingleShot)
+ Q_PROPERTY(int interval READ interval WRITE setInterval BINDABLE bindableInterval)
Q_PROPERTY(int remainingTime READ remainingTime)
- Q_PROPERTY(Qt::TimerType timerType READ timerType WRITE setTimerType)
- Q_PROPERTY(bool active READ isActive)
+ Q_PROPERTY(Qt::TimerType timerType READ timerType WRITE setTimerType BINDABLE bindableTimerType)
+ Q_PROPERTY(bool active READ isActive STORED false BINDABLE bindableActive)
public:
explicit QTimer(QObject *parent = nullptr);
~QTimer();
- inline bool isActive() const { return id >= 0; }
- int timerId() const { return id; }
+ bool isActive() const;
+ QBindable<bool> bindableActive();
+ int timerId() const;
+ Qt::TimerId id() const;
void setInterval(int msec);
- int interval() const { return inter; }
+ int interval() const;
+ QBindable<int> bindableInterval();
int remainingTime() const;
- void setTimerType(Qt::TimerType atype) { this->type = atype; }
- Qt::TimerType timerType() const { return Qt::TimerType(type); }
+ void setTimerType(Qt::TimerType atype);
+ Qt::TimerType timerType() const;
+ QBindable<Qt::TimerType> bindableTimerType();
- inline void setSingleShot(bool singleShot);
- inline bool isSingleShot() const { return single; }
+ void setSingleShot(bool singleShot);
+ bool isSingleShot() const;
+ QBindable<bool> bindableSingleShot();
+ QT_CORE_INLINE_SINCE(6, 8)
static void singleShot(int msec, const QObject *receiver, const char *member);
+
+ QT_CORE_INLINE_SINCE(6, 8)
static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member);
-#ifdef Q_CLANG_QDOC
- template<typename PointerToMemberFunction>
- static void singleShot(int msec, const QObject *receiver, PointerToMemberFunction method);
- template<typename PointerToMemberFunction>
- static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method);
- template<typename Functor>
- static void singleShot(int msec, Functor functor);
- template<typename Functor>
- static void singleShot(int msec, Qt::TimerType timerType, Functor functor);
- template<typename Functor, int>
- static void singleShot(int msec, const QObject *context, Functor functor);
- template<typename Functor, int>
- static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
- template <typename Functor>
- QMetaObject::Connection callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
- template <typename Functor>
- QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
- template <typename MemberFunction>
- QMetaObject::Connection callOnTimeout(const QObject *receiver, MemberFunction *slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ // singleShot with context
+#ifdef Q_QDOC
+ template <typename Duration, typename Functor>
+ static inline void singleShot(Duration interval, const QObject *receiver, Functor &&slot);
+ template <typename Duration, typename Functor>
+ static inline void singleShot(Duration interval, Qt::TimerType timerType,
+ const QObject *receiver, Functor &&slot);
#else
- // singleShot to a QObject slot
- template <typename Duration, typename Func1>
- static inline void singleShot(Duration interval, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot)
+ template <typename Duration, typename Functor>
+ static inline void singleShot(Duration interval,
+ const typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType *receiver,
+ Functor &&slot)
{
- singleShot(interval, defaultTypeFor(interval), receiver, slot);
+ singleShot(interval, defaultTypeFor(interval), receiver, std::forward<Functor>(slot));
}
- template <typename Duration, typename Func1>
- static inline void singleShot(Duration interval, Qt::TimerType timerType, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver,
- Func1 slot)
+ template <typename Duration, typename Functor>
+ static inline void singleShot(Duration interval, Qt::TimerType timerType,
+ const typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType *receiver,
+ Functor &&slot)
{
- typedef QtPrivate::FunctionPointer<Func1> SlotType;
-
- //compilation error if the slot has arguments.
- static_assert(int(SlotType::ArgumentCount) == 0,
- "The slot must not have any arguments.");
-
+ using Prototype = void(*)();
singleShotImpl(interval, timerType, receiver,
- new QtPrivate::QSlotObject<Func1, typename SlotType::Arguments, void>(slot));
- }
- // singleShot to a functor or function pointer (without context)
- template <typename Duration, typename Func1>
- static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
- !std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, Func1 slot)
- {
- singleShot(interval, defaultTypeFor(interval), nullptr, std::move(slot));
- }
- template <typename Duration, typename Func1>
- static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
- !std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, Qt::TimerType timerType, Func1 slot)
- {
- singleShot(interval, timerType, nullptr, std::move(slot));
+ QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(slot)));
}
- // singleShot to a functor or function pointer (with context)
- template <typename Duration, typename Func1>
- static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
- !std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, const QObject *context, Func1 slot)
+#endif
+
+ // singleShot without context
+ template <typename Duration, typename Functor>
+ static inline void singleShot(Duration interval, Functor &&slot)
{
- singleShot(interval, defaultTypeFor(interval), context, std::move(slot));
+ singleShot(interval, defaultTypeFor(interval), nullptr, std::forward<Functor>(slot));
}
- template <typename Duration, typename Func1>
- static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
- !std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, Qt::TimerType timerType, const QObject *context, Func1 slot)
+ template <typename Duration, typename Functor>
+ static inline void singleShot(Duration interval, Qt::TimerType timerType, Functor &&slot)
{
- //compilation error if the slot has arguments.
- typedef QtPrivate::FunctionPointer<Func1> SlotType;
- static_assert(int(SlotType::ArgumentCount) <= 0, "The slot must not have any arguments.");
-
- singleShotImpl(interval, timerType, context,
- new QtPrivate::QFunctorSlotObject<Func1, 0,
- typename QtPrivate::List_Left<void, 0>::Value, void>(std::move(slot)));
+ singleShot(interval, timerType, nullptr, std::forward<Functor>(slot));
}
+#ifdef Q_QDOC
+ template <typename Functor>
+ QMetaObject::Connection callOnTimeout(Functor &&slot);
+ template <typename Functor>
+ QMetaObject::Connection callOnTimeout(const QObject *context, Functor &&slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+#else
template <typename ... Args>
QMetaObject::Connection callOnTimeout(Args && ...args)
{
@@ -177,11 +115,7 @@ Q_SIGNALS:
void timeout(QPrivateSignal);
public:
-#if __has_include(<chrono>) || defined(Q_QDOC)
- void setInterval(std::chrono::milliseconds value)
- {
- setInterval(int(value.count()));
- }
+ void setInterval(std::chrono::milliseconds value);
std::chrono::milliseconds intervalAsDuration() const
{
@@ -195,54 +129,57 @@ public:
static void singleShot(std::chrono::milliseconds value, const QObject *receiver, const char *member)
{
- singleShot(int(value.count()), receiver, member);
+ singleShot(value, defaultTypeFor(value), receiver, member);
}
+ static void singleShot(std::chrono::milliseconds interval, Qt::TimerType timerType,
+ const QObject *receiver, const char *member);
- static void singleShot(std::chrono::milliseconds value, Qt::TimerType timerType, const QObject *receiver, const char *member)
- {
- singleShot(int(value.count()), timerType, receiver, member);
- }
-
- void start(std::chrono::milliseconds value)
- {
- start(int(value.count()));
- }
-#endif
+ void start(std::chrono::milliseconds value);
protected:
void timerEvent(QTimerEvent *) override;
private:
Q_DISABLE_COPY(QTimer)
+ Q_DECLARE_PRIVATE(QTimer)
inline int startTimer(int){ return -1;}
inline void killTimer(int){}
- static Q_DECL_CONSTEXPR Qt::TimerType defaultTypeFor(int msecs) noexcept
- { return msecs >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer; }
- static void singleShotImpl(int msec, Qt::TimerType timerType,
- const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
-
-#if __has_include(<chrono>)
- static Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval)
- { return defaultTypeFor(int(interval.count())); }
+ static constexpr Qt::TimerType defaultTypeFor(int msecs) noexcept
+ { return defaultTypeFor(std::chrono::milliseconds{msecs}); }
- static void singleShotImpl(std::chrono::milliseconds interval, Qt::TimerType timerType,
- const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
+ static constexpr Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval) noexcept
{
- singleShotImpl(int(interval.count()),
- timerType, receiver, slotObj);
+ // coarse timers are worst in their first firing
+ // so we prefer a high precision timer for something that happens only once
+ // unless the timeout is too big, in which case we go for coarse anyway
+ using namespace std::chrono_literals;
+ return interval >= 2s ? Qt::CoarseTimer : Qt::PreciseTimer;
}
-#endif
- int id, inter, del;
- uint single : 1;
- uint nulltimer : 1;
- uint type : 2;
- // reserved : 28
+ QT_CORE_INLINE_SINCE(6, 8)
+ static void singleShotImpl(int msec, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
+
+ static void singleShotImpl(std::chrono::milliseconds interval, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
};
-inline void QTimer::setSingleShot(bool asingleShot) { single = asingleShot; }
+#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
+void QTimer::singleShot(int msec, const QObject *receiver, const char *member)
+{ singleShot(std::chrono::milliseconds{msec}, receiver, member); }
+
+void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver,
+ const char *member)
+{ singleShot(std::chrono::milliseconds{msec}, timerType, receiver, member); }
+
+void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
+{
+ singleShotImpl(std::chrono::milliseconds{msec}, timerType, receiver, slotObj);
+}
+#endif
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer_p.h b/src/corelib/kernel/qtimer_p.h
new file mode 100644
index 0000000000..9347f6c241
--- /dev/null
+++ b/src/corelib/kernel/qtimer_p.h
@@ -0,0 +1,73 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QTIMER_P_H
+#define QTIMER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Qt translation tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+#include "qtimer.h"
+#include "qchronotimer.h"
+
+#include "qobject_p.h"
+#include "qproperty_p.h"
+#include "qttypetraits.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTimerPrivate : public QObjectPrivate
+{
+public:
+ QTimerPrivate(QTimer *qq)
+ : q(qq),
+ isQTimer(true)
+ {}
+
+ QTimerPrivate(std::chrono::nanoseconds nsec, QChronoTimer *qq)
+ : intervalDuration(nsec),
+ q(qq)
+ {
+ intervalDuration.notify();
+ }
+
+ static constexpr int INV_TIMER = -1; // invalid timer id
+
+ void setIntervalDuration(std::chrono::nanoseconds nsec)
+ {
+ if (isQTimer) {
+ const auto msec = std::chrono::ceil<std::chrono::milliseconds>(nsec);
+ static_cast<QTimer *>(q)->setInterval(msec);
+ } else {
+ static_cast<QChronoTimer *>(q)->setInterval(nsec);
+ }
+ }
+
+ void setInterval(int msec)
+ {
+ Q_ASSERT(isQTimer);
+ static_cast<QTimer *>(q)->setInterval(msec);
+ }
+
+ bool isActive() const { return id > Qt::TimerId::Invalid; }
+
+ Qt::TimerId id = Qt::TimerId::Invalid;
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimerPrivate, int, inter, &QTimerPrivate::setInterval, 0)
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimerPrivate, std::chrono::nanoseconds, intervalDuration,
+ &QTimerPrivate::setIntervalDuration,
+ std::chrono::nanoseconds{0})
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimerPrivate, bool, single, false)
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimerPrivate, Qt::TimerType, type, Qt::CoarseTimer)
+ Q_OBJECT_COMPUTED_PROPERTY(QTimerPrivate, bool, isActiveData, &QTimerPrivate::isActive)
+
+ QObject *q;
+ const bool isQTimer = false; // true if q is a QTimer*
+};
+
+QT_END_NAMESPACE
+#endif // QTIMER_P_H
diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp
index b425ca3dcb..b83f0194c2 100644
--- a/src/corelib/kernel/qtimerinfo_unix.cpp
+++ b/src/corelib/kernel/qtimerinfo_unix.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qelapsedtimer.h>
#include <qcoreapplication.h>
@@ -46,13 +10,12 @@
#include "private/qobject_p.h"
#include "private/qabstracteventdispatcher_p.h"
-#ifdef QTIMERINFO_DEBUG
-# include <QDebug>
-# include <QThread>
-#endif
-
#include <sys/times.h>
+using namespace std::chrono;
+// Implied by "using namespace std::chrono", but be explicit about it, for grep-ability
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;
@@ -62,172 +25,75 @@ Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;
* timerBitVec array is used for keeping track of timer identifiers.
*/
-QTimerInfoList::QTimerInfoList()
-{
-#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL)
- if (!QElapsedTimer::isMonotonic()) {
- // not using monotonic timers, initialize the timeChanged() machinery
- previousTime = qt_gettime();
-
- tms unused;
- previousTicks = times(&unused);
-
- ticksPerSecond = sysconf(_SC_CLK_TCK);
- msPerTick = 1000/ticksPerSecond;
- } else {
- // detected monotonic timers
- previousTime.tv_sec = previousTime.tv_nsec = 0;
- previousTicks = 0;
- ticksPerSecond = 0;
- msPerTick = 0;
- }
-#endif
-
- firstTimerInfo = nullptr;
-}
-
-timespec QTimerInfoList::updateCurrentTime()
-{
- return (currentTime = qt_gettime());
-}
-
-#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED)
+QTimerInfoList::QTimerInfoList() = default;
-timespec qAbsTimespec(const timespec &t)
+steady_clock::time_point QTimerInfoList::updateCurrentTime() const
{
- timespec tmp = t;
- if (tmp.tv_sec < 0) {
- tmp.tv_sec = -tmp.tv_sec - 1;
- tmp.tv_nsec -= 1000000000;
- }
- if (tmp.tv_sec == 0 && tmp.tv_nsec < 0) {
- tmp.tv_nsec = -tmp.tv_nsec;
- }
- return normalizedTimespec(tmp);
+ currentTime = steady_clock::now();
+ return currentTime;
}
-/*
- Returns \c true if the real time clock has changed by more than 10%
- relative to the processor time since the last time this function was
- called. This presumably means that the system time has been changed.
-
- If /a delta is nonzero, delta is set to our best guess at how much the system clock was changed.
-*/
-bool QTimerInfoList::timeChanged(timespec *delta)
-{
-#ifdef Q_OS_NACL
- Q_UNUSED(delta)
- return false; // Calling "times" crashes.
-#endif
- struct tms unused;
- clock_t currentTicks = times(&unused);
-
- clock_t elapsedTicks = currentTicks - previousTicks;
- timespec elapsedTime = currentTime - previousTime;
-
- timespec elapsedTimeTicks;
- elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
- elapsedTimeTicks.tv_nsec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000 * 1000;
-
- timespec dummy;
- if (!delta)
- delta = &dummy;
- *delta = elapsedTime - elapsedTimeTicks;
-
- previousTicks = currentTicks;
- previousTime = currentTime;
-
- // If tick drift is more than 10% off compared to realtime, we assume that the clock has
- // been set. Of course, we have to allow for the tick granularity as well.
- timespec tickGranularity;
- tickGranularity.tv_sec = 0;
- tickGranularity.tv_nsec = msPerTick * 1000 * 1000;
- return elapsedTimeTicks < ((qAbsTimespec(*delta) - tickGranularity) * 10);
-}
+/*! \internal
+ Updates the currentTime member to the current time, and returns \c true if
+ the first timer's timeout is in the future (after currentTime).
-/*
- repair broken timer
+ The list is sorted by timeout, thus it's enough to check the first timer only.
*/
-void QTimerInfoList::timerRepair(const timespec &diff)
-{
- // repair all timers
- for (int i = 0; i < size(); ++i) {
- QTimerInfo *t = at(i);
- t->timeout = t->timeout + diff;
- }
-}
-
-void QTimerInfoList::repairTimersIfNeeded()
+bool QTimerInfoList::hasPendingTimers()
{
- if (QElapsedTimer::isMonotonic())
- return;
- timespec delta;
- if (timeChanged(&delta))
- timerRepair(delta);
+ if (timers.isEmpty())
+ return false;
+ return updateCurrentTime() < timers.at(0)->timeout;
}
-#else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
-
-void QTimerInfoList::repairTimersIfNeeded()
-{
-}
-
-#endif
+static bool byTimeout(const QTimerInfo *a, const QTimerInfo *b)
+{ return a->timeout < b->timeout; };
/*
insert timer info into list
*/
void QTimerInfoList::timerInsert(QTimerInfo *ti)
{
- int index = size();
- while (index--) {
- const QTimerInfo * const t = at(index);
- if (!(ti->timeout < t->timeout))
- break;
- }
- insert(index+1, ti);
-}
-
-inline timespec &operator+=(timespec &t1, int ms)
-{
- t1.tv_sec += ms / 1000;
- t1.tv_nsec += ms % 1000 * 1000 * 1000;
- return normalizedTimespec(t1);
-}
-
-inline timespec operator+(const timespec &t1, int ms)
-{
- timespec t2 = t1;
- return t2 += ms;
+ timers.insert(std::upper_bound(timers.cbegin(), timers.cend(), ti, byTimeout),
+ ti);
}
-static timespec roundToMillisecond(timespec val)
+static constexpr milliseconds roundToMillisecond(nanoseconds val)
{
// always round up
// worst case scenario is that the first trigger of a 1-ms timer is 0.999 ms late
-
- int ns = val.tv_nsec % (1000 * 1000);
- val.tv_nsec += 1000 * 1000 - ns;
- return normalizedTimespec(val);
+ return ceil<milliseconds>(val);
}
-#ifdef QTIMERINFO_DEBUG
-QDebug operator<<(QDebug s, timeval tv)
-{
- QDebugStateSaver saver(s);
- s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << Qt::reset;
- return s;
-}
-QDebug operator<<(QDebug s, Qt::TimerType t)
+static_assert(roundToMillisecond(0ns) == 0ms);
+static_assert(roundToMillisecond(1ns) == 1ms);
+static_assert(roundToMillisecond(999'999ns) == 1ms);
+static_assert(roundToMillisecond(1'000'000ns) == 1ms);
+static_assert(roundToMillisecond(999'000'000ns) == 999ms);
+static_assert(roundToMillisecond(999'000'001ns) == 1000ms);
+static_assert(roundToMillisecond(999'999'999ns) == 1000ms);
+static_assert(roundToMillisecond(1s) == 1s);
+
+static constexpr seconds roundToSecs(nanoseconds interval)
{
- QDebugStateSaver saver(s);
- s << (t == Qt::PreciseTimer ? "P" :
- t == Qt::CoarseTimer ? "C" : "VC");
- return s;
+ // The very coarse timer is based on full second precision, so we want to
+ // round the interval to the closest second, rounding 500ms up to 1s.
+ //
+ // std::chrono::round() wouldn't work with all multiples of 500 because for the
+ // middle point it would round to even:
+ // value round() wanted
+ // 500 0 1
+ // 1500 2 2
+ // 2500 2 3
+
+ auto secs = duration_cast<seconds>(interval);
+ const nanoseconds frac = interval - secs;
+ if (frac >= 500ms)
+ ++secs;
+ return secs;
}
-#endif
-static void calculateCoarseTimerTimeout(QTimerInfo *t, timespec currentTime)
+static void calculateCoarseTimerTimeout(QTimerInfo *t, steady_clock::time_point now)
{
// The coarse timer works like this:
// - interval under 40 ms: round to even
@@ -245,214 +111,186 @@ static void calculateCoarseTimerTimeout(QTimerInfo *t, timespec currentTime)
//
// The objective is to make most timers wake up at the same time, thereby reducing CPU wakeups.
- uint interval = uint(t->interval);
- uint msec = uint(t->timeout.tv_nsec) / 1000 / 1000;
- Q_ASSERT(interval >= 20);
+ Q_ASSERT(t->interval >= 20ms);
+
+ const auto timeoutInSecs = time_point_cast<seconds>(t->timeout);
+
+ auto recalculate = [&](const milliseconds frac) {
+ t->timeout = timeoutInSecs + frac;
+ if (t->timeout < now)
+ t->timeout += t->interval;
+ };
// Calculate how much we can round and still keep within 5% error
- uint absMaxRounding = interval / 20;
+ milliseconds interval = roundToMillisecond(t->interval);
+ const milliseconds absMaxRounding = interval / 20;
- if (interval < 100 && interval != 25 && interval != 50 && interval != 75) {
+ auto fracMsec = duration_cast<milliseconds>(t->timeout - timeoutInSecs);
+
+ if (interval < 100ms && interval != 25ms && interval != 50ms && interval != 75ms) {
+ auto fracCount = fracMsec.count();
// special mode for timers of less than 100 ms
- if (interval < 50) {
+ if (interval < 50ms) {
// round to even
// round towards multiples of 50 ms
- bool roundUp = (msec % 50) >= 25;
- msec >>= 1;
- msec |= uint(roundUp);
- msec <<= 1;
+ bool roundUp = (fracCount % 50) >= 25;
+ fracCount >>= 1;
+ fracCount |= roundUp;
+ fracCount <<= 1;
} else {
// round to multiple of 4
// round towards multiples of 100 ms
- bool roundUp = (msec % 100) >= 50;
- msec >>= 2;
- msec |= uint(roundUp);
- msec <<= 2;
- }
- } else {
- uint min = qMax<int>(0, msec - absMaxRounding);
- uint max = qMin(1000u, msec + absMaxRounding);
-
- // find the boundary that we want, according to the rules above
- // extra rules:
- // 1) whatever the interval, we'll take any round-to-the-second timeout
- if (min == 0) {
- msec = 0;
- goto recalculate;
- } else if (max == 1000) {
- msec = 1000;
- goto recalculate;
+ bool roundUp = (fracCount % 100) >= 50;
+ fracCount >>= 2;
+ fracCount |= roundUp;
+ fracCount <<= 2;
}
+ fracMsec = milliseconds{fracCount};
+ recalculate(fracMsec);
+ return;
+ }
- uint wantedBoundaryMultiple;
-
- // 2) if the interval is a multiple of 500 ms and > 5000 ms, we'll always round
- // towards a round-to-the-second
- // 3) if the interval is a multiple of 500 ms, we'll round towards the nearest
- // multiple of 500 ms
- if ((interval % 500) == 0) {
- if (interval >= 5000) {
- msec = msec >= 500 ? max : min;
- goto recalculate;
- } else {
- wantedBoundaryMultiple = 500;
- }
- } else if ((interval % 50) == 0) {
- // 4) same for multiples of 250, 200, 100, 50
- uint mult50 = interval / 50;
- if ((mult50 % 4) == 0) {
- // multiple of 200
- wantedBoundaryMultiple = 200;
- } else if ((mult50 % 2) == 0) {
- // multiple of 100
- wantedBoundaryMultiple = 100;
- } else if ((mult50 % 5) == 0) {
- // multiple of 250
- wantedBoundaryMultiple = 250;
- } else {
- // multiple of 50
- wantedBoundaryMultiple = 50;
- }
- } else {
- wantedBoundaryMultiple = 25;
- }
+ milliseconds min = std::max(0ms, fracMsec - absMaxRounding);
+ milliseconds max = std::min(1000ms, fracMsec + absMaxRounding);
- uint base = msec / wantedBoundaryMultiple * wantedBoundaryMultiple;
- uint middlepoint = base + wantedBoundaryMultiple / 2;
- if (msec < middlepoint)
- msec = qMax(base, min);
- else
- msec = qMin(base + wantedBoundaryMultiple, max);
+ // find the boundary that we want, according to the rules above
+ // extra rules:
+ // 1) whatever the interval, we'll take any round-to-the-second timeout
+ if (min == 0ms) {
+ fracMsec = 0ms;
+ recalculate(fracMsec);
+ return;
+ } else if (max == 1000ms) {
+ fracMsec = 1000ms;
+ recalculate(fracMsec);
+ return;
}
-recalculate:
- if (msec == 1000u) {
- ++t->timeout.tv_sec;
- t->timeout.tv_nsec = 0;
- } else {
- t->timeout.tv_nsec = msec * 1000 * 1000;
+ milliseconds wantedBoundaryMultiple{25};
+
+ // 2) if the interval is a multiple of 500 ms and > 5000 ms, we'll always round
+ // towards a round-to-the-second
+ // 3) if the interval is a multiple of 500 ms, we'll round towards the nearest
+ // multiple of 500 ms
+ if ((interval % 500) == 0ms) {
+ if (interval >= 5s) {
+ fracMsec = fracMsec >= 500ms ? max : min;
+ recalculate(fracMsec);
+ return;
+ } else {
+ wantedBoundaryMultiple = 500ms;
+ }
+ } else if ((interval % 50) == 0ms) {
+ // 4) same for multiples of 250, 200, 100, 50
+ milliseconds mult50 = interval / 50;
+ if ((mult50 % 4) == 0ms) {
+ // multiple of 200
+ wantedBoundaryMultiple = 200ms;
+ } else if ((mult50 % 2) == 0ms) {
+ // multiple of 100
+ wantedBoundaryMultiple = 100ms;
+ } else if ((mult50 % 5) == 0ms) {
+ // multiple of 250
+ wantedBoundaryMultiple = 250ms;
+ } else {
+ // multiple of 50
+ wantedBoundaryMultiple = 50ms;
+ }
}
- if (t->timeout < currentTime)
- t->timeout += interval;
+ milliseconds base = (fracMsec / wantedBoundaryMultiple) * wantedBoundaryMultiple;
+ milliseconds middlepoint = base + wantedBoundaryMultiple / 2;
+ if (fracMsec < middlepoint)
+ fracMsec = qMax(base, min);
+ else
+ fracMsec = qMin(base + wantedBoundaryMultiple, max);
+
+ recalculate(fracMsec);
}
-static void calculateNextTimeout(QTimerInfo *t, timespec currentTime)
+static void calculateNextTimeout(QTimerInfo *t, steady_clock::time_point now)
{
switch (t->timerType) {
case Qt::PreciseTimer:
case Qt::CoarseTimer:
t->timeout += t->interval;
- if (t->timeout < currentTime) {
- t->timeout = currentTime;
+ if (t->timeout < now) {
+ t->timeout = now;
t->timeout += t->interval;
}
-#ifdef QTIMERINFO_DEBUG
- t->expected += t->interval;
- if (t->expected < currentTime) {
- t->expected = currentTime;
- t->expected += t->interval;
- }
-#endif
if (t->timerType == Qt::CoarseTimer)
- calculateCoarseTimerTimeout(t, currentTime);
+ calculateCoarseTimerTimeout(t, now);
return;
case Qt::VeryCoarseTimer:
- // we don't need to take care of the microsecond component of t->interval
- t->timeout.tv_sec += t->interval;
- if (t->timeout.tv_sec <= currentTime.tv_sec)
- t->timeout.tv_sec = currentTime.tv_sec + t->interval;
-#ifdef QTIMERINFO_DEBUG
- t->expected.tv_sec += t->interval;
- if (t->expected.tv_sec <= currentTime.tv_sec)
- t->expected.tv_sec = currentTime.tv_sec + t->interval;
-#endif
- return;
+ // t->interval already rounded to full seconds in registerTimer()
+ t->timeout += t->interval;
+ if (t->timeout <= now)
+ t->timeout = time_point_cast<seconds>(now + t->interval);
+ break;
}
-
-#ifdef QTIMERINFO_DEBUG
- if (t->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << t->timerType << Qt::hex << t->id << Qt::dec << "interval" << t->interval
- << "originally expected at" << t->expected << "will fire at" << t->timeout
- << "or" << (t->timeout - t->expected) << "s late";
-#endif
}
/*
- Returns the time to wait for the next timer, or null if no timers
- are waiting.
-*/
-bool QTimerInfoList::timerWait(timespec &tm)
+ Returns the time to wait for the first timer that has not been activated yet,
+ otherwise returns std::nullopt.
+ */
+std::optional<QTimerInfoList::Duration> QTimerInfoList::timerWait()
{
- timespec currentTime = updateCurrentTime();
- repairTimersIfNeeded();
+ steady_clock::time_point now = updateCurrentTime();
+ auto isWaiting = [](QTimerInfo *tinfo) { return !tinfo->activateRef; };
// Find first waiting timer not already active
- QTimerInfo *t = nullptr;
- for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
- if (!(*it)->activateRef) {
- t = *it;
- break;
- }
- }
-
- if (!t)
- return false;
-
- if (currentTime < t->timeout) {
- // time to wait
- tm = roundToMillisecond(t->timeout - currentTime);
- } else {
- // no time to wait
- tm.tv_sec = 0;
- tm.tv_nsec = 0;
- }
-
- return true;
+ auto it = std::find_if(timers.cbegin(), timers.cend(), isWaiting);
+ if (it == timers.cend())
+ return std::nullopt;
+
+ Duration timeToWait = (*it)->timeout - now;
+ if (timeToWait > 0ns)
+ return roundToMillisecond(timeToWait);
+ return 0ms;
}
/*
- Returns the timer's remaining time in milliseconds with the given timerId, or
- null if there is nothing left. If the timer id is not found in the list, the
- returned value will be -1. If the timer is overdue, the returned value will be 0.
+ Returns the timer's remaining time in milliseconds with the given timerId.
+ If the timer id is not found in the list, the returned value will be \c{Duration::min()}.
+ If the timer is overdue, the returned value will be 0.
*/
-int QTimerInfoList::timerRemainingTime(int timerId)
+QTimerInfoList::Duration QTimerInfoList::remainingDuration(Qt::TimerId timerId) const
{
- timespec currentTime = updateCurrentTime();
- repairTimersIfNeeded();
- timespec tm = {0, 0};
-
- for (int i = 0; i < count(); ++i) {
- QTimerInfo *t = at(i);
- if (t->id == timerId) {
- if (currentTime < t->timeout) {
- // time to wait
- tm = roundToMillisecond(t->timeout - currentTime);
- return tm.tv_sec*1000 + tm.tv_nsec/1000/1000;
- } else {
- return 0;
- }
- }
- }
+ const steady_clock::time_point now = updateCurrentTime();
+ auto it = findTimerById(timerId);
+ if (it == timers.cend()) {
#ifndef QT_NO_DEBUG
- qWarning("QTimerInfoList::timerRemainingTime: timer id %i not found", timerId);
+ qWarning("QTimerInfoList::timerRemainingTime: timer id %i not found", int(timerId));
#endif
+ return Duration::min();
+ }
- return -1;
+ const QTimerInfo *t = *it;
+ if (now < t->timeout) // time to wait
+ return t->timeout - now;
+ return 0ms;
}
-void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+void QTimerInfoList::registerTimer(Qt::TimerId timerId, QTimerInfoList::Duration interval,
+ Qt::TimerType timerType, QObject *object)
{
- QTimerInfo *t = new QTimerInfo;
- t->id = timerId;
- t->interval = interval;
- t->timerType = timerType;
- t->obj = object;
- t->activateRef = nullptr;
+ // correct the timer type first
+ if (timerType == Qt::CoarseTimer) {
+ // this timer has up to 5% coarseness
+ // so our boundaries are 20 ms and 20 s
+ // below 20 ms, 5% inaccuracy is below 1 ms, so we convert to high precision
+ // above 20 s, 5% inaccuracy is above 1 s, so we convert to VeryCoarseTimer
+ if (interval >= 20s)
+ timerType = Qt::VeryCoarseTimer;
+ else if (interval <= 20ms)
+ timerType = Qt::PreciseTimer;
+ }
- timespec expected = updateCurrentTime() + interval;
+ QTimerInfo *t = new QTimerInfo(timerId, interval, timerType, object);
+ QTimerInfo::TimePoint expected = updateCurrentTime() + interval;
switch (timerType) {
case Qt::PreciseTimer:
@@ -462,102 +300,69 @@ void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType time
break;
case Qt::CoarseTimer:
- // this timer has up to 5% coarseness
- // so our boundaries are 20 ms and 20 s
- // below 20 ms, 5% inaccuracy is below 1 ms, so we convert to high precision
- // above 20 s, 5% inaccuracy is above 1 s, so we convert to VeryCoarseTimer
- if (interval >= 20000) {
- t->timerType = Qt::VeryCoarseTimer;
- } else {
- t->timeout = expected;
- if (interval <= 20) {
- t->timerType = Qt::PreciseTimer;
- // no adjustment is necessary
- } else if (interval <= 20000) {
- calculateCoarseTimerTimeout(t, currentTime);
- }
- break;
- }
- Q_FALLTHROUGH();
+ t->timeout = expected;
+ t->interval = roundToMillisecond(interval);
+ calculateCoarseTimerTimeout(t, currentTime);
+ break;
+
case Qt::VeryCoarseTimer:
- // the very coarse timer is based on full second precision,
- // so we keep the interval in seconds (round to closest second)
- t->interval /= 500;
- t->interval += 1;
- t->interval >>= 1;
- t->timeout.tv_sec = currentTime.tv_sec + t->interval;
- t->timeout.tv_nsec = 0;
-
- // if we're past the half-second mark, increase the timeout again
- if (currentTime.tv_nsec > 500*1000*1000)
- ++t->timeout.tv_sec;
+ t->interval = roundToSecs(t->interval);
+ const auto currentTimeInSecs = floor<seconds>(currentTime);
+ t->timeout = currentTimeInSecs + t->interval;
+ // If we're past the half-second mark, increase the timeout again
+ if (currentTime - currentTimeInSecs > 500ms)
+ t->timeout += 1s;
}
timerInsert(t);
-
-#ifdef QTIMERINFO_DEBUG
- t->expected = expected;
- t->cumulativeError = 0;
- t->count = 0;
- if (t->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << t->timerType << Qt::hex <<t->id << Qt::dec << "interval" << t->interval << "expected at"
- << t->expected << "will fire first at" << t->timeout;
-#endif
}
-bool QTimerInfoList::unregisterTimer(int timerId)
+bool QTimerInfoList::unregisterTimer(Qt::TimerId timerId)
{
+ auto it = findTimerById(timerId);
+ if (it == timers.cend())
+ return false; // id not found
+
// set timer inactive
- for (int i = 0; i < count(); ++i) {
- QTimerInfo *t = at(i);
- if (t->id == timerId) {
- // found it
- removeAt(i);
- if (t == firstTimerInfo)
- firstTimerInfo = nullptr;
- if (t->activateRef)
- *(t->activateRef) = nullptr;
- delete t;
- return true;
- }
- }
- // id not found
- return false;
+ QTimerInfo *t = *it;
+ if (t == firstTimerInfo)
+ firstTimerInfo = nullptr;
+ if (t->activateRef)
+ *(t->activateRef) = nullptr;
+ delete t;
+ timers.erase(it);
+ return true;
}
bool QTimerInfoList::unregisterTimers(QObject *object)
{
- if (isEmpty())
+ if (timers.isEmpty())
return false;
- for (int i = 0; i < count(); ++i) {
- QTimerInfo *t = at(i);
- if (t->obj == object) {
- // object found
- removeAt(i);
- if (t == firstTimerInfo)
- firstTimerInfo = nullptr;
- if (t->activateRef)
- *(t->activateRef) = nullptr;
- delete t;
- // move back one so that we don't skip the new current item
- --i;
- }
- }
- return true;
+
+ auto associatedWith = [this](QObject *o) {
+ return [this, o](auto &t) {
+ if (t->obj == o) {
+ if (t == firstTimerInfo)
+ firstTimerInfo = nullptr;
+ if (t->activateRef)
+ *(t->activateRef) = nullptr;
+ delete t;
+ return true;
+ }
+ return false;
+ };
+ };
+
+ qsizetype count = timers.removeIf(associatedWith(object));
+ return count > 0;
}
-QList<QAbstractEventDispatcher::TimerInfo> QTimerInfoList::registeredTimers(QObject *object) const
+auto QTimerInfoList::registeredTimers(QObject *object) const -> QList<TimerInfo>
{
- QList<QAbstractEventDispatcher::TimerInfo> list;
- for (int i = 0; i < count(); ++i) {
- const QTimerInfo * const t = at(i);
- if (t->obj == object) {
- list << QAbstractEventDispatcher::TimerInfo(t->id,
- (t->timerType == Qt::VeryCoarseTimer
- ? t->interval * 1000
- : t->interval),
- t->timerType);
- }
+ QList<TimerInfo> list;
+ for (const auto &t : timers) {
+ if (t->obj == object)
+ list.emplaceBack(TimerInfo{t->interval, t->id, t->timerType});
}
return list;
}
@@ -567,31 +372,27 @@ QList<QAbstractEventDispatcher::TimerInfo> QTimerInfoList::registeredTimers(QObj
*/
int QTimerInfoList::activateTimers()
{
- if (qt_disable_lowpriority_timers || isEmpty())
+ if (qt_disable_lowpriority_timers || timers.isEmpty())
return 0; // nothing to do
- int n_act = 0, maxCount = 0;
firstTimerInfo = nullptr;
- timespec currentTime = updateCurrentTime();
- // qDebug() << "Thread" << QThread::currentThreadId() << "woken up at" << currentTime;
- repairTimersIfNeeded();
-
-
+ const steady_clock::time_point now = updateCurrentTime();
+ // qDebug() << "Thread" << QThread::currentThreadId() << "woken up at" << now;
// Find out how many timer have expired
- for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
- if (currentTime < (*it)->timeout)
- break;
- maxCount++;
- }
+ auto stillActive = [&now](const QTimerInfo *t) { return now < t->timeout; };
+ // Find first one still active (list is sorted by timeout)
+ auto it = std::find_if(timers.cbegin(), timers.cend(), stillActive);
+ auto maxCount = it - timers.cbegin();
+ int n_act = 0;
//fire the timers.
while (maxCount--) {
- if (isEmpty())
+ if (timers.isEmpty())
break;
- QTimerInfo *currentTimerInfo = constFirst();
- if (currentTime < currentTimerInfo->timeout)
+ QTimerInfo *currentTimerInfo = timers.constFirst();
+ if (now < currentTimerInfo->timeout)
break; // no timer has expired
if (!firstTimerInfo) {
@@ -604,44 +405,29 @@ int QTimerInfoList::activateTimers()
firstTimerInfo = currentTimerInfo;
}
- // remove from list
- removeFirst();
-
-#ifdef QTIMERINFO_DEBUG
- float diff;
- if (currentTime < currentTimerInfo->expected) {
- // early
- timeval early = currentTimerInfo->expected - currentTime;
- diff = -(early.tv_sec + early.tv_usec / 1000000.0);
- } else {
- timeval late = currentTime - currentTimerInfo->expected;
- diff = late.tv_sec + late.tv_usec / 1000000.0;
- }
- currentTimerInfo->cumulativeError += diff;
- ++currentTimerInfo->count;
- if (currentTimerInfo->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << currentTimerInfo->timerType << Qt::hex << currentTimerInfo->id << Qt::dec << "interval"
- << currentTimerInfo->interval << "firing at" << currentTime
- << "(orig" << currentTimerInfo->expected << "scheduled at" << currentTimerInfo->timeout
- << ") off by" << diff << "activation" << currentTimerInfo->count
- << "avg error" << (currentTimerInfo->cumulativeError / currentTimerInfo->count);
-#endif
-
// determine next timeout time
- calculateNextTimeout(currentTimerInfo, currentTime);
+ calculateNextTimeout(currentTimerInfo, now);
+ if (timers.size() > 1) {
+ // Find where "currentTimerInfo" should be in the list so as
+ // to keep the list ordered by timeout
+ auto afterCurrentIt = timers.begin() + 1;
+ auto iter = std::upper_bound(afterCurrentIt, timers.end(), currentTimerInfo, byTimeout);
+ currentTimerInfo = *std::rotate(timers.begin(), afterCurrentIt, iter);
+ }
- // reinsert timer
- timerInsert(currentTimerInfo);
- if (currentTimerInfo->interval > 0)
+ if (currentTimerInfo->interval > 0ms)
n_act++;
+ // Send event, but don't allow it to recurse:
if (!currentTimerInfo->activateRef) {
- // send event, but don't allow it to recurse
currentTimerInfo->activateRef = &currentTimerInfo;
- QTimerEvent e(currentTimerInfo->id);
+ QTimerEvent e(qToUnderlying(currentTimerInfo->id));
QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
+ // Storing currentTimerInfo's address in its activateRef allows the
+ // handling of that event to clear this local variable on deletion
+ // of the object it points to - if it didn't, clear activateRef:
if (currentTimerInfo)
currentTimerInfo->activateRef = nullptr;
}
diff --git a/src/corelib/kernel/qtimerinfo_unix_p.h b/src/corelib/kernel/qtimerinfo_unix_p.h
index 7bd6f16ea1..293e9c4d4e 100644
--- a/src/corelib/kernel/qtimerinfo_unix_p.h
+++ b/src/corelib/kernel/qtimerinfo_unix_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTIMERINFO_UNIX_P_H
#define QTIMERINFO_UNIX_P_H
@@ -53,65 +17,76 @@
#include <QtCore/private/qglobal_p.h>
-// #define QTIMERINFO_DEBUG
-
#include "qabstracteventdispatcher.h"
-#include <sys/time.h> // struct timeval
+#include <sys/time.h> // struct timespec
+#include <chrono>
QT_BEGIN_NAMESPACE
// internal timer info
-struct QTimerInfo {
- int id; // - timer identifier
- int interval; // - timer interval in milliseconds
+struct QTimerInfo
+{
+ using Duration = QAbstractEventDispatcher::Duration;
+ using TimePoint = std::chrono::time_point<std::chrono::steady_clock, Duration>;
+ QTimerInfo(Qt::TimerId timerId, Duration interval, Qt::TimerType type, QObject *obj)
+ : interval(interval), id(timerId), timerType(type), obj(obj)
+ {
+ }
+
+ TimePoint timeout = {}; // - when to actually fire
+ Duration interval = Duration{-1}; // - timer interval
+ Qt::TimerId id = Qt::TimerId::Invalid; // - timer identifier
Qt::TimerType timerType; // - timer type
- timespec timeout; // - when to actually fire
- QObject *obj; // - object to receive event
- QTimerInfo **activateRef; // - ref from activateTimers
-
-#ifdef QTIMERINFO_DEBUG
- timeval expected; // when timer is expected to fire
- float cumulativeError;
- uint count;
-#endif
+ QObject *obj = nullptr; // - object to receive event
+ QTimerInfo **activateRef = nullptr; // - ref from activateTimers
};
-class Q_CORE_EXPORT QTimerInfoList : public QList<QTimerInfo*>
+class Q_CORE_EXPORT QTimerInfoList
{
-#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED)
- timespec previousTime;
- clock_t previousTicks;
- int ticksPerSecond;
- int msPerTick;
-
- bool timeChanged(timespec *delta);
- void timerRepair(const timespec &);
-#endif
-
- // state variables used by activateTimers()
- QTimerInfo *firstTimerInfo;
-
public:
+ using Duration = QAbstractEventDispatcher::Duration;
+ using TimerInfo = QAbstractEventDispatcher::TimerInfoV2;
QTimerInfoList();
- timespec currentTime;
- timespec updateCurrentTime();
-
- // must call updateCurrentTime() first!
- void repairTimersIfNeeded();
+ mutable std::chrono::steady_clock::time_point currentTime;
- bool timerWait(timespec &);
+ std::optional<Duration> timerWait();
void timerInsert(QTimerInfo *);
- int timerRemainingTime(int timerId);
+ Duration remainingDuration(Qt::TimerId timerId) const;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
- bool unregisterTimer(int timerId);
+ void registerTimer(Qt::TimerId timerId, Duration interval,
+ Qt::TimerType timerType, QObject *object);
+ bool unregisterTimer(Qt::TimerId timerId);
bool unregisterTimers(QObject *object);
- QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const;
+ QList<TimerInfo> registeredTimers(QObject *object) const;
int activateTimers();
+ bool hasPendingTimers();
+
+ void clearTimers()
+ {
+ qDeleteAll(timers);
+ timers.clear();
+ }
+
+ bool isEmpty() const { return timers.empty(); }
+
+ qsizetype size() const { return timers.size(); }
+
+ auto findTimerById(Qt::TimerId timerId) const
+ {
+ auto matchesId = [timerId](const auto &t) { return t->id == timerId; };
+ return std::find_if(timers.cbegin(), timers.cend(), matchesId);
+ }
+
+private:
+ std::chrono::steady_clock::time_point updateCurrentTime() const;
+
+ // state variables used by activateTimers()
+ QTimerInfo *firstTimerInfo = nullptr;
+ QList<QTimerInfo *> timers;
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h
index 68f74cafc3..ae68abcfee 100644
--- a/src/corelib/kernel/qtmetamacros.h
+++ b/src/corelib/kernel/qtmetamacros.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTMETAMACROS_H
#define QTMETAMACROS_H
@@ -91,41 +55,6 @@ QT_BEGIN_NAMESPACE
#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text)
-#define Q_PRIVATE_QPROPERTY(accessor, type, name, setter, ...) \
- struct _qt_property_api_##name { \
- type value() const; \
- type operator()() const { return value(); } \
- void setValue(type &&); \
- void setValue(type const &); \
- void operator=(type const &v) { setValue(v); } \
- void operator=(type &&v) { setValue(std::move(v)); } \
- QPropertyBinding<type> setBinding(const QPropertyBinding<type> &); \
- QPropertyBinding<type> setBinding(QPropertyBinding<type> &&); \
- QPropertyBinding<type> operator=(const QPropertyBinding<type> &b) { return setBinding(b); } \
- QPropertyBinding<type> operator=(QPropertyBinding<type> &&b) { return setBinding(std::move(b)); } \
- bool setBinding(const QUntypedPropertyBinding &); \
- template <typename Functor> \
- QPropertyBinding<type> setBinding(Functor f, \
- const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION) \
- { \
- return setBinding(Qt::makePropertyBinding(f, location)); \
- } \
- bool hasBinding() const; \
- QPropertyBinding<type> binding() const; \
- QPropertyBinding<type> takeBinding(); \
- }; \
- void setter(type const& value);
-#if __has_cpp_attribute(no_unique_address)
-#define Q_PRIVATE_QPROPERTIES_BEGIN
-#define QT_PRIVATE_QPROPERTY_PREFIX [[no_unique_address]]
-#define Q_PRIVATE_QPROPERTIES_END
-#else
-#define Q_PRIVATE_QPROPERTIES_BEGIN union {
-#define QT_PRIVATE_QPROPERTY_PREFIX
-#define Q_PRIVATE_QPROPERTIES_END };
-#endif
-#define Q_PRIVATE_QPROPERTY_IMPL(name) \
- QT_PRIVATE_QPROPERTY_PREFIX _qt_property_api_##name name;
#ifndef Q_REVISION
# define Q_REVISION(...)
#endif
@@ -134,13 +63,13 @@ QT_BEGIN_NAMESPACE
#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x)
#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x)
#define Q_ENUM_IMPL(ENUM) \
- friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
- friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
+ friend constexpr const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ friend constexpr const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x)
#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x)
#define Q_ENUM_NS_IMPL(ENUM) \
- inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
- inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
+ inline constexpr const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ inline constexpr const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x)
#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x)
#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable)
@@ -154,37 +83,33 @@ QT_BEGIN_NAMESPACE
// full set of tr functions
# define QT_TR_FUNCTIONS \
static inline QString tr(const char *s, const char *c = nullptr, int n = -1) \
- { return staticMetaObject.tr(s, c, n); } \
- QT_DEPRECATED static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) \
{ return staticMetaObject.tr(s, c, n); }
#else
// inherit the ones from QObject
# define QT_TR_FUNCTIONS
#endif
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
#define QT_TR_FUNCTIONS
#endif
-// ### Qt6: remove
-#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */
+#define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN
-#if defined(Q_CC_INTEL)
-// Cannot redefine the visibility of a method in an exported class
-# define Q_DECL_HIDDEN_STATIC_METACALL
-#else
-# define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN
-#endif
-
-#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
-# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override")
-#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 501
+#if defined(Q_CC_CLANG)
+# if Q_CC_CLANG >= 1100
+# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override") QT_WARNING_DISABLE_CLANG("-Wsuggest-override")
+# elif Q_CC_CLANG >= 306
+# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override")
+# endif
+#elif defined(Q_CC_GNU) && Q_CC_GNU >= 501
# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override")
+#elif defined(Q_CC_MSVC)
+# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_MSVC(26433)
#else
# define Q_OBJECT_NO_OVERRIDE_WARNING
#endif
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600
+#if defined(Q_CC_GNU) && Q_CC_GNU >= 600
# define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes")
#else
# define Q_OBJECT_NO_ATTRIBUTES_WARNING
@@ -204,17 +129,17 @@ private: \
Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
QT_WARNING_POP \
- struct QPrivateSignal {}; \
+ struct QPrivateSignal { explicit QPrivateSignal() = default; }; \
QT_ANNOTATE_CLASS(qt_qobject, "")
/* qmake ignore Q_OBJECT */
#define Q_OBJECT_FAKE Q_OBJECT QT_ANNOTATE_CLASS(qt_fake, "")
#ifndef QT_NO_META_MACROS
-/* qmake ignore Q_GADGET */
-#define Q_GADGET \
+/* qmake ignore Q_GADGET_EXPORT */
+#define Q_GADGET_EXPORT(...) \
public: \
- static const QMetaObject staticMetaObject; \
+ static __VA_ARGS__ const QMetaObject staticMetaObject; \
void qt_check_for_QGADGET_macro(); \
typedef void QtGadgetHelper; \
private: \
@@ -225,7 +150,10 @@ private: \
QT_ANNOTATE_CLASS(qt_qgadget, "") \
/*end*/
-/* qmake ignore Q_NAMESPACE_EXPORT */
+/* qmake ignore Q_GADGET */
+#define Q_GADGET Q_GADGET_EXPORT()
+
+ /* qmake ignore Q_NAMESPACE_EXPORT */
#define Q_NAMESPACE_EXPORT(...) \
extern __VA_ARGS__ const QMetaObject staticMetaObject; \
QT_ANNOTATE_CLASS(qt_qnamespace, "") \
diff --git a/src/corelib/kernel/qtmochelpers.h b/src/corelib/kernel/qtmochelpers.h
new file mode 100644
index 0000000000..9d75177645
--- /dev/null
+++ b/src/corelib/kernel/qtmochelpers.h
@@ -0,0 +1,86 @@
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTMOCHELPERS_H
+#define QTMOCHELPERS_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists to be used by the code that
+// moc generates. This file will not change quickly, but it over the long term,
+// it will likely change or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#include <algorithm> // std::min
+#include <limits>
+
+#if 0
+#pragma qt_no_master_include
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace QtMocHelpers {
+// The maximum Size of a string literal is 2 GB on 32-bit and 4 GB on 64-bit
+// (but the compiler is likely to give up before you get anywhere near that much)
+static constexpr size_t MaxStringSize =
+ (std::min)(size_t((std::numeric_limits<uint>::max)()),
+ size_t((std::numeric_limits<qsizetype>::max)()));
+
+template <uint... Nx> constexpr size_t stringDataSizeHelper(std::integer_sequence<uint, Nx...>)
+{
+ // same as:
+ // return (0 + ... + Nx);
+ // but not using the fold expression to avoid exceeding compiler limits
+ size_t total = 0;
+ uint sizes[] = { Nx... };
+ for (uint n : sizes)
+ total += n;
+ return total;
+}
+
+template <int Count, size_t StringSize> struct StringData
+{
+ static_assert(StringSize <= MaxStringSize, "Meta Object data is too big");
+ uint offsetsAndSizes[Count] = {};
+ char stringdata0[StringSize] = {};
+ constexpr StringData() = default;
+};
+
+template <uint... Nx> constexpr auto stringData(const char (&...strings)[Nx])
+{
+ constexpr size_t StringSize = stringDataSizeHelper<Nx...>({});
+ constexpr size_t Count = 2 * sizeof...(Nx);
+
+ StringData<Count, StringSize> result;
+ const char *inputs[] = { strings... };
+ uint sizes[] = { Nx... };
+
+ uint offset = 0;
+ char *output = result.stringdata0;
+ for (size_t i = 0; i < sizeof...(Nx); ++i) {
+ // copy the input string, including the terminating null
+ uint len = sizes[i];
+ for (uint j = 0; j < len; ++j)
+ output[offset + j] = inputs[i][j];
+ result.offsetsAndSizes[2 * i] = offset + sizeof(result.offsetsAndSizes);
+ result.offsetsAndSizes[2 * i + 1] = len - 1;
+ offset += len;
+ }
+
+ return result;
+}
+
+# define QT_MOC_HAS_STRINGDATA 1
+
+} // namespace QtMocHelpers
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#endif // QTMOCHELPERS_H
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index d9c10151e8..ec92404a15 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
@@ -58,7 +22,7 @@
#include "qendian.h"
#include "qresource.h"
-#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
# define QT_USE_MMAP
# include "private/qcore_unix_p.h"
// for mmap
@@ -75,8 +39,11 @@
QT_BEGIN_NAMESPACE
+namespace {
enum Tag { Tag_End = 1, Tag_SourceText16, Tag_Translation, Tag_Context16, Tag_Obsolete1,
Tag_SourceText, Tag_Context, Tag_Comment, Tag_Obsolete2 };
+}
+
/*
$ mcookie
3cb86418caef9c95cd211cbf60a1bddd
@@ -485,8 +452,8 @@ bool QTranslator::load(const QString & filename, const QString & directory,
QString prefix;
if (QFileInfo(filename).isRelative()) {
prefix = directory;
- if (prefix.length() && !prefix.endsWith(QLatin1Char('/')))
- prefix += QLatin1Char('/');
+ if (prefix.size() && !prefix.endsWith(u'/'))
+ prefix += u'/';
}
const QString suffixOrDotQM = suffix.isNull() ? dotQmLiteral() : suffix;
@@ -508,7 +475,7 @@ bool QTranslator::load(const QString & filename, const QString & directory,
break;
int rightmost = 0;
- for (int i = 0; i < (int)delims.length(); i++) {
+ for (int i = 0; i < (int)delims.size(); i++) {
int k = fname.lastIndexOf(delims[i]);
if (k > rightmost)
rightmost = k;
@@ -530,7 +497,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
QTranslatorPrivate *d = this;
bool ok = false;
- if (realname.startsWith(QLatin1Char(':'))) {
+ if (realname.startsWith(u':')) {
// If the translation is in a non-compressed resource file, the data is already in
// memory, so no need to use QFile to copy it again.
Q_ASSERT(!d->resource);
@@ -603,9 +570,14 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
}
}
- if (ok && d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength, directory)) {
- d->filePath = realname;
- return true;
+ if (ok) {
+ const QString base_dir =
+ !directory.isEmpty() ? directory : QFileInfo(realname).absolutePath();
+ if (d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength,
+ base_dir)) {
+ d->filePath = realname;
+ return true;
+ }
}
#if defined(QT_USE_MMAP)
@@ -640,54 +612,36 @@ static QString find_translation(const QLocale & locale,
QString path;
if (QFileInfo(filename).isRelative()) {
path = directory;
- if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
- path += QLatin1Char('/');
+ if (!path.isEmpty() && !path.endsWith(u'/'))
+ path += u'/';
}
const QString suffixOrDotQM = suffix.isNull() ? dotQmLiteral() : suffix;
QString realname;
realname += path + filename + prefix; // using += in the hope for some reserve capacity
const int realNameBaseSize = realname.size();
- QStringList fuzzyLocales;
// see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration
- QStringList languages = locale.uiLanguages();
-#if defined(Q_OS_UNIX)
+ // For each language_country returned by locale.uiLanguages(), add
+ // also a lowercase version to the list. Since these languages are
+ // used to create file names, this is important on case-sensitive
+ // file systems, where otherwise a file called something like
+ // "prefix_en_us.qm" won't be found under the "en_US" locale. Note
+ // that the Qt resource system is always case-sensitive, even on
+ // Windows (in other words: this codepath is *not* UNIX-only).
+ QStringList languages = locale.uiLanguages(QLocale::TagSeparator::Underscore);
for (int i = languages.size()-1; i >= 0; --i) {
QString lang = languages.at(i);
QString lowerLang = lang.toLower();
if (lang != lowerLang)
- languages.insert(i+1, lowerLang);
+ languages.insert(i + 1, lowerLang);
}
-#endif
-
- // try explicit locales names first
- for (QString localeName : qAsConst(languages)) {
- localeName.replace(QLatin1Char('-'), QLatin1Char('_'));
-
- realname += localeName + suffixOrDotQM;
- if (is_readable_file(realname))
- return realname;
-
- realname.truncate(realNameBaseSize + localeName.size());
- if (is_readable_file(realname))
- return realname;
- realname.truncate(realNameBaseSize);
- fuzzyLocales.append(localeName);
- }
-
- // start guessing
- for (const QString &fuzzyLocale : qAsConst(fuzzyLocales)) {
- QStringView localeName(fuzzyLocale);
+ for (QString localeName : std::as_const(languages)) {
+ // try the complete locale name first and progressively truncate from
+ // the end until a matching language tag is found (with or without suffix)
for (;;) {
- int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
- // no truncations? fail
- if (rightmost <= 0)
- break;
- localeName.truncate(rightmost);
-
realname += localeName + suffixOrDotQM;
if (is_readable_file(realname))
return realname;
@@ -697,6 +651,11 @@ static QString find_translation(const QLocale & locale,
return realname;
realname.truncate(realNameBaseSize);
+
+ int rightmost = localeName.lastIndexOf(u'_');
+ if (rightmost <= 0)
+ break; // no truncations anymore, break
+ localeName.truncate(rightmost);
}
}
@@ -755,10 +714,10 @@ static QString find_translation(const QLocale & locale,
\li \c /opt/foolib/foo.es
\li \c /opt/foolib/foo.fr_CA.qm
\li \c /opt/foolib/foo.fr_CA
- \li \c /opt/foolib/foo.de.qm
- \li \c /opt/foolib/foo.de
\li \c /opt/foolib/foo.fr.qm
\li \c /opt/foolib/foo.fr
+ \li \c /opt/foolib/foo.de.qm
+ \li \c /opt/foolib/foo.de
\li \c /opt/foolib/foo.qm
\li \c /opt/foolib/foo.
\li \c /opt/foolib/foo
@@ -837,7 +796,7 @@ bool QTranslatorPrivate::do_load(const uchar *data, qsizetype len, const QString
}
if (tag == QTranslatorPrivate::Language) {
- language = QString::fromUtf8((const char*)data, blockLen);
+ language = QString::fromUtf8((const char *)data, blockLen);
} else if (tag == QTranslatorPrivate::Contexts) {
contextArray = data;
contextLength = blockLen;
@@ -906,7 +865,7 @@ static QString getMessage(const uchar *m, const uchar *end, const char *context,
uchar tag = 0;
if (m < end)
tag = read8(m++);
- switch((Tag)tag) {
+ switch ((Tag)tag) {
case Tag_End:
goto end;
case Tag_Translation: {
@@ -956,7 +915,7 @@ end:
if (!tn)
return QString();
QString str(tn_length / 2, Qt::Uninitialized);
- qFromBigEndian<ushort>(tn, str.length(), str.data());
+ qFromBigEndian<char16_t>(tn, str.size(), str.data());
return str;
}
@@ -1015,7 +974,7 @@ QString QTranslatorPrivate::do_translate(const char *context, const char *source
elfHash_finish(h);
const uchar *start = offsetArray;
- const uchar *end = start + ((numItems-1) << 3);
+ const uchar *end = start + ((numItems - 1) << 3);
while (start <= end) {
const uchar *middle = start + (((end - start) >> 4) << 3);
uint hash = read32(middle);
@@ -1031,7 +990,7 @@ QString QTranslatorPrivate::do_translate(const char *context, const char *source
if (start <= end) {
// go back on equal key
- while (start != offsetArray && read32(start) == read32(start-8))
+ while (start != offsetArray && read32(start) == read32(start - 8))
start -= 8;
while (start < offsetArray + offsetLength) {
@@ -1116,7 +1075,7 @@ void QTranslatorPrivate::clear()
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").
- If you need to programatically insert translations into a
+ If you need to programmatically insert translations into a
QTranslator, this function can be reimplemented.
\sa load()
diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h
index 61a39c4089..95d99e8ca8 100644
--- a/src/corelib/kernel/qtranslator.h
+++ b/src/corelib/kernel/qtranslator.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRANSLATOR_H
#define QTRANSLATOR_H
@@ -66,16 +30,17 @@ public:
QString language() const;
QString filePath() const;
- bool load(const QString & filename,
- const QString & directory = QString(),
- const QString & search_delimiters = QString(),
- const QString & suffix = QString());
- bool load(const QLocale & locale,
- const QString & filename,
- const QString & prefix = QString(),
- const QString & directory = QString(),
- const QString & suffix = QString());
- bool load(const uchar *data, int len, const QString &directory = QString());
+ [[nodiscard]] bool load(const QString & filename,
+ const QString & directory = QString(),
+ const QString & search_delimiters = QString(),
+ const QString & suffix = QString());
+ [[nodiscard]] bool load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix = QString(),
+ const QString & directory = QString(),
+ const QString & suffix = QString());
+ [[nodiscard]] bool load(const uchar *data, int len,
+ const QString &directory = QString());
private:
Q_DISABLE_COPY(QTranslator)
diff --git a/src/corelib/kernel/qtranslator_p.h b/src/corelib/kernel/qtranslator_p.h
index e148637ac6..8b4b8b8c48 100644
--- a/src/corelib/kernel/qtranslator_p.h
+++ b/src/corelib/kernel/qtranslator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRANSLATOR_P_H
#define QTRANSLATOR_P_H
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 61a80eeae8..92a44c462b 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1,50 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qvariant.h"
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qvariant_p.h"
#include "qbitarray.h"
#include "qbytearray.h"
#include "qdatastream.h"
#include "qdebug.h"
#include "qmap.h"
+#include "qhash.h"
#include "qdatetime.h"
#if QT_CONFIG(easingcurve)
#include "qeasingcurve.h"
@@ -71,7 +36,6 @@
#include "qjsondocument.h"
#include "qbytearraylist.h"
#endif
-#include "private/qvariant_p.h"
#include "private/qlocale_p.h"
#include "qmetatype_p.h"
#include <qmetaobject.h>
@@ -83,129 +47,103 @@
#include "qline.h"
#endif
+#include <memory>
+
#include <cmath>
#include <float.h>
#include <cstring>
QT_BEGIN_NAMESPACE
-namespace {
-class HandlersManager
-{
- static const QVariant::Handler *Handlers[QModulesPrivate::ModulesCount];
-public:
- const QVariant::Handler *operator[] (const uint typeId) const
- {
- return Handlers[QModulesPrivate::moduleForType(typeId)];
- }
-
- void registerHandler(const QModulesPrivate::Names name, const QVariant::Handler *handler)
- {
- Handlers[name] = handler;
- }
-};
-} // namespace
-
-namespace {
-struct CoreTypesFilter {
- template<typename T>
- struct Acceptor {
- static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsCore && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable;
- };
-};
-} // annonymous
-
-namespace { // annonymous used to hide QVariant handlers
+using namespace Qt::StringLiterals;
-static bool isNull(const QVariant::Private *d)
-{
- QVariantIsNull<CoreTypesFilter> isNull(d);
- return QMetaTypeSwitcher::switcher<bool>(isNull, d->type().id());
-}
+namespace { // anonymous used to hide QVariant handlers
-/*!
- \internal
-
- Compares \a a to \a b. The caller guarantees that \a a and \a b
- are of the same type.
- */
-static bool compare(const QVariant::Private *a, const QVariant::Private *b)
+static qlonglong qMetaTypeNumberBySize(const QVariant::Private *d)
{
- QVariantComparator<CoreTypesFilter> comparator(a, b);
- return QMetaTypeSwitcher::switcher<bool>(comparator, a->type().id());
+ switch (d->typeInterface()->size) {
+ case 1:
+ return d->get<signed char>();
+ case 2:
+ return d->get<short>();
+ case 4:
+ return d->get<int>();
+ case 8:
+ return d->get<qlonglong>();
+ }
+ Q_UNREACHABLE_RETURN(0);
}
-/*!
- \internal
- */
static qlonglong qMetaTypeNumber(const QVariant::Private *d)
{
- switch (d->type().id()) {
+ switch (d->typeInterface()->typeId) {
case QMetaType::Int:
- return d->data.i;
case QMetaType::LongLong:
- return d->data.ll;
case QMetaType::Char:
- return qlonglong(d->data.c);
case QMetaType::SChar:
- return qlonglong(d->data.sc);
case QMetaType::Short:
- return qlonglong(d->data.s);
case QMetaType::Long:
- return qlonglong(d->data.l);
+ return qMetaTypeNumberBySize(d);
case QMetaType::Float:
- return qRound64(d->data.f);
+ return qRound64(d->get<float>());
case QMetaType::Double:
- return qRound64(d->data.d);
+ return qRound64(d->get<double>());
#ifndef QT_BOOTSTRAPPED
case QMetaType::QJsonValue:
- return v_cast<QJsonValue>(d)->toDouble();
+ return d->get<QJsonValue>().toDouble();
case QMetaType::QCborValue:
- return v_cast<QCborValue>(d)->toInteger();
+ return d->get<QCborValue>().toInteger();
#endif
}
- Q_ASSERT(false);
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
{
- switch (d->type().id()) {
- case QMetaType::UInt:
- return d->data.u;
- case QMetaType::ULongLong:
- return d->data.ull;
- case QMetaType::UChar:
- return d->data.uc;
- case QMetaType::UShort:
- return d->data.us;
- case QMetaType::ULong:
- return d->data.ul;
+ switch (d->typeInterface()->size) {
+ case 1:
+ return d->get<unsigned char>();
+ case 2:
+ return d->get<unsigned short>();
+ case 4:
+ return d->get<unsigned int>();
+ case 8:
+ return d->get<qulonglong>();
}
- Q_ASSERT(false);
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
-static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
+static std::optional<qlonglong> qConvertToNumber(const QVariant::Private *d, bool allowStringToBool = false)
{
- *ok = true;
-
- switch (uint(d->type().id())) {
- case QMetaType::QString:
- return v_cast<QString>(d)->toLongLong(ok);
+ bool ok;
+ switch (d->typeInterface()->typeId) {
+ case QMetaType::QString: {
+ const QString &s = d->get<QString>();
+ if (qlonglong l = s.toLongLong(&ok); ok)
+ return l;
+ if (allowStringToBool) {
+ if (s == "false"_L1 || s == "0"_L1)
+ return 0;
+ if (s == "true"_L1 || s == "1"_L1)
+ return 1;
+ }
+ return std::nullopt;
+ }
case QMetaType::QChar:
- return v_cast<QChar>(d)->unicode();
+ return d->get<QChar>().unicode();
case QMetaType::QByteArray:
- return v_cast<QByteArray>(d)->toLongLong(ok);
+ if (qlonglong l = d->get<QByteArray>().toLongLong(&ok); ok)
+ return l;
+ return std::nullopt;
case QMetaType::Bool:
- return qlonglong(d->data.b);
+ return qlonglong(d->get<bool>());
#ifndef QT_BOOTSTRAPPED
case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble())
+ if (!d->get<QCborValue>().isInteger() && !d->get<QCborValue>().isDouble())
break;
return qMetaTypeNumber(d);
case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isDouble())
+ if (!d->get<QJsonValue>().isDouble())
break;
Q_FALLTHROUGH();
#endif
@@ -221,1318 +159,162 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
case QMetaType::ULongLong:
case QMetaType::UInt:
case QMetaType::UChar:
+ case QMetaType::Char16:
+ case QMetaType::Char32:
case QMetaType::UShort:
case QMetaType::ULong:
-
return qlonglong(qMetaTypeUNumber(d));
}
- QMetaType typeInfo = d->type();
- if (typeInfo.flags() & QMetaType::IsEnumeration
- || d->type().id() == QMetaType::QCborSimpleType) {
- switch (typeInfo.sizeOf()) {
- case 1:
- return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc;
- case 2:
- return d->is_shared ? *reinterpret_cast<qint16 *>(d->data.shared->ptr) : d->data.s;
- case 4:
- return d->is_shared ? *reinterpret_cast<qint32 *>(d->data.shared->ptr) : d->data.i;
- case 8:
- return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ll;
- }
- }
+ if (d->typeInterface()->flags & QMetaType::IsEnumeration
+ || d->typeInterface()->typeId == QMetaType::QCborSimpleType)
+ return qMetaTypeNumberBySize(d);
- *ok = false;
- return Q_INT64_C(0);
+ return std::nullopt;
}
-static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
+static std::optional<double> qConvertToRealNumber(const QVariant::Private *d)
{
- *ok = true;
- switch (uint(d->type().id())) {
+ bool ok;
+ switch (d->typeInterface()->typeId) {
+ case QMetaType::QString:
+ if (double r = d->get<QString>().toDouble(&ok); ok)
+ return r;
+ return std::nullopt;
case QMetaType::Double:
- return qreal(d->data.d);
+ return d->get<double>();
case QMetaType::Float:
- return qreal(d->data.f);
+ return double(d->get<float>());
+ case QMetaType::Float16:
+ return double(d->get<qfloat16>());
case QMetaType::ULongLong:
case QMetaType::UInt:
case QMetaType::UChar:
+ case QMetaType::Char16:
+ case QMetaType::Char32:
case QMetaType::UShort:
case QMetaType::ULong:
- return qreal(qMetaTypeUNumber(d));
+ return double(qMetaTypeUNumber(d));
#ifndef QT_BOOTSTRAPPED
case QMetaType::QCborValue:
- return v_cast<QCborValue>(d)->toDouble();
+ return d->get<QCborValue>().toDouble();
case QMetaType::QJsonValue:
- return v_cast<QJsonValue>(d)->toDouble();
+ return d->get<QJsonValue>().toDouble();
#endif
default:
// includes enum conversion as well as invalid types
- return qreal(qConvertToNumber(d, ok));
- }
-}
-
-static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
-{
- *ok = true;
-
- switch (uint(d->type().id())) {
- case QMetaType::QString:
- return v_cast<QString>(d)->toULongLong(ok);
- case QMetaType::QChar:
- return v_cast<QChar>(d)->unicode();
- case QMetaType::QByteArray:
- return v_cast<QByteArray>(d)->toULongLong(ok);
- case QMetaType::Bool:
- return qulonglong(d->data.b);
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isDouble())
- return qulonglong(qConvertToRealNumber(d, ok));
- if (!v_cast<QCborValue>(d)->isInteger())
- return false;
- return qulonglong(qMetaTypeNumber(d));
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isDouble())
- break;
- Q_FALLTHROUGH();
-#endif
- case QMetaType::Double:
- case QMetaType::Int:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Float:
- case QMetaType::LongLong:
- return qulonglong(qMetaTypeNumber(d));
- case QMetaType::ULongLong:
- case QMetaType::UInt:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- return qMetaTypeUNumber(d);
- }
-
- QMetaType typeInfo = d->type();
- if (typeInfo.flags() & QMetaType::IsEnumeration) {
- switch (typeInfo.sizeOf()) {
- case 1:
- return d->is_shared ? *reinterpret_cast<uchar *>(d->data.shared->ptr) : d->data.uc;
- case 2:
- return d->is_shared ? *reinterpret_cast<quint16 *>(d->data.shared->ptr) : d->data.us;
- case 4:
- return d->is_shared ? *reinterpret_cast<quint32 *>(d->data.shared->ptr) : d->data.u;
- case 8:
- return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ull;
- }
- }
-
- *ok = false;
- return Q_UINT64_C(0);
-}
-
-template<typename TInput, typename LiteralWrapper>
-inline bool qt_convertToBool(const QVariant::Private *const d)
-{
- TInput str = v_cast<TInput>(d)->toLower();
- return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
-}
-
-/*!
- \internal
- Returns the internal data pointer from \a d.
- */
-
-static const void *constData(const QVariant::Private &d)
-{
- return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.c);
-}
-
-#ifndef QT_NO_QOBJECT
-/*!
- \internal
- returns a QMetaEnum for a given meta tape type id if possible
-*/
-static QMetaEnum metaEnumFromType(QMetaType t)
-{
- if (t.flags() & QMetaType::IsEnumeration) {
- if (const QMetaObject *metaObject = t.metaObject()) {
- const QByteArray enumName = t.name();
- const char *lastColon = std::strrchr(enumName, ':');
- return metaObject->enumerator(metaObject->indexOfEnumerator(
- lastColon ? lastColon + 1 : enumName.constData()));
- }
+ if (std::optional<qlonglong> l = qConvertToNumber(d))
+ return double(*l);
+ return std::nullopt;
}
- return QMetaEnum();
}
-#endif
-
-/*!
- \internal
- Converts \a d to type \a t, which is placed in \a result.
- */
-static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
+static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface, const void *copy)
{
- Q_ASSERT(d->type().id() != t);
- Q_ASSERT(result);
-
- if (d->type().id() >= QMetaType::User || t >= QMetaType::User) {
- const bool isOk = QMetaType::convert(constData(*d), d->type().id(), result, t);
- if (ok)
- *ok = isOk;
- if (isOk)
- return true;
- }
-
- bool dummy;
- if (!ok)
- ok = &dummy;
-
- switch (uint(t)) {
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QUrl:
- switch (d->type().id()) {
- case QMetaType::QString:
- *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
- break;
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isUrl()) {
- *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl();
- break;
- }
- return false;
- default:
- return false;
- }
- break;
-#endif // QT_BOOTSTRAPPED
-#if QT_CONFIG(itemmodel)
- case QMetaType::QModelIndex:
- switch (d->type().id()) {
- case QMetaType::QPersistentModelIndex:
- *static_cast<QModelIndex *>(result) = QModelIndex(*v_cast<QPersistentModelIndex>(d));
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QPersistentModelIndex:
- switch (d->type().id()) {
- case QMetaType::QModelIndex:
- *static_cast<QPersistentModelIndex *>(result) = QPersistentModelIndex(*v_cast<QModelIndex>(d));
- break;
- default:
- return false;
- }
- break;
-#endif // QT_CONFIG(itemmodel)
- case QMetaType::QString: {
- QString *str = static_cast<QString *>(result);
- switch (d->type().id()) {
- case QMetaType::QChar:
- *str = *v_cast<QChar>(d);
- break;
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- *str = QChar::fromLatin1(d->data.c);
- break;
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Int:
- case QMetaType::LongLong:
- *str = QString::number(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *str = QString::number(qMetaTypeUNumber(d));
- break;
- case QMetaType::Float:
- *str = QString::number(d->data.f, 'g', QLocale::FloatingPointShortest);
- break;
- case QMetaType::Double:
- *str = QString::number(d->data.d, 'g', QLocale::FloatingPointShortest);
- break;
-#if QT_CONFIG(datestring)
- case QMetaType::QDate:
- *str = v_cast<QDate>(d)->toString(Qt::ISODate);
- break;
- case QMetaType::QTime:
- *str = v_cast<QTime>(d)->toString(Qt::ISODateWithMs);
- break;
- case QMetaType::QDateTime:
- *str = v_cast<QDateTime>(d)->toString(Qt::ISODateWithMs);
- break;
-#endif
- case QMetaType::Bool:
- *str = d->data.b ? QStringLiteral("true") : QStringLiteral("false");
- break;
- case QMetaType::QByteArray:
- *str = QString::fromUtf8(v_cast<QByteArray>(d)->constData());
- break;
- case QMetaType::QStringList:
- if (v_cast<QStringList>(d)->count() == 1)
- *str = v_cast<QStringList>(d)->at(0);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QUrl:
- *str = v_cast<QUrl>(d)->toString();
- break;
- case QMetaType::QJsonValue:
- if (v_cast<QJsonValue>(d)->isString())
- *str = v_cast<QJsonValue>(d)->toString();
- else if (!v_cast<QJsonValue>(d)->isNull())
- return false;
- break;
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag())
- return false;
- *str = v_cast<QCborValue>(d)->toVariant().toString();
- break;
-#endif
- case QMetaType::QUuid:
- *str = v_cast<QUuid>(d)->toString();
- break;
- case QMetaType::Nullptr:
- *str = QString();
- break;
- default:
-#ifndef QT_NO_QOBJECT
- {
- QMetaEnum en = metaEnumFromType(d->type());
- if (en.isValid()) {
- *str = QString::fromUtf8(en.valueToKey(qConvertToNumber(d, ok)));
- return *ok;
- }
- }
-#endif
- return false;
- }
- break;
- }
- case QMetaType::QChar: {
- QChar *c = static_cast<QChar *>(result);
- switch (d->type().id()) {
- case QMetaType::Int:
- case QMetaType::LongLong:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Float:
- *c = QChar::fromUcs2(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *c = QChar::fromUcs2(qMetaTypeUNumber(d));
- break;
- default:
- return false;
- }
- break;
- }
-#ifndef QT_NO_GEOM_VARIANT
- case QMetaType::QSize: {
- QSize *s = static_cast<QSize *>(result);
- switch (d->type().id()) {
- case QMetaType::QSizeF:
- *s = v_cast<QSizeF>(d)->toSize();
- break;
- default:
- return false;
- }
- break;
- }
-
- case QMetaType::QSizeF: {
- QSizeF *s = static_cast<QSizeF *>(result);
- switch (d->type().id()) {
- case QMetaType::QSize:
- *s = QSizeF(*(v_cast<QSize>(d)));
- break;
- default:
- return false;
- }
- break;
- }
-
- case QMetaType::QLine: {
- QLine *s = static_cast<QLine *>(result);
- switch (d->type().id()) {
- case QMetaType::QLineF:
- *s = v_cast<QLineF>(d)->toLine();
- break;
- default:
- return false;
- }
- break;
- }
-
- case QMetaType::QLineF: {
- QLineF *s = static_cast<QLineF *>(result);
- switch (d->type().id()) {
- case QMetaType::QLine:
- *s = QLineF(*(v_cast<QLine>(d)));
- break;
- default:
- return false;
- }
- break;
- }
-#endif
- case QMetaType::QStringList:
- if (d->type().id() == QMetaType::QVariantList) {
- QStringList *slst = static_cast<QStringList *>(result);
- const QVariantList *list = v_cast<QVariantList >(d);
- const int size = list->size();
- slst->reserve(size);
- for (int i = 0; i < size; ++i)
- slst->append(list->at(i).toString());
- } else if (d->type().id() == QMetaType::QString) {
- QStringList *slst = static_cast<QStringList *>(result);
- *slst = QStringList(*v_cast<QString>(d));
- } else {
- return false;
- }
- break;
- case QMetaType::QDate: {
- QDate *dt = static_cast<QDate *>(result);
- if (d->type().id() == QMetaType::QDateTime)
- *dt = v_cast<QDateTime>(d)->date();
-#if QT_CONFIG(datestring)
- else if (d->type().id() == QMetaType::QString)
- *dt = QDate::fromString(*v_cast<QString>(d), Qt::ISODate);
-#endif
- else
- return false;
-
- return dt->isValid();
- }
- case QMetaType::QTime: {
- QTime *t = static_cast<QTime *>(result);
- switch (d->type().id()) {
- case QMetaType::QDateTime:
- *t = v_cast<QDateTime>(d)->time();
- break;
-#if QT_CONFIG(datestring)
- case QMetaType::QString:
- *t = QTime::fromString(*v_cast<QString>(d), Qt::ISODate);
- break;
-#endif
- default:
- return false;
- }
- return t->isValid();
- }
- case QMetaType::QDateTime: {
- QDateTime *dt = static_cast<QDateTime *>(result);
- switch (d->type().id()) {
-#if QT_CONFIG(datestring)
- case QMetaType::QString:
- *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate);
- break;
-# ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isDateTime())
- *dt = v_cast<QCborValue>(d)->toDateTime();
- else
- return false;
- break;
-# endif
-#endif
- case QMetaType::QDate:
- *dt = v_cast<QDate>(d)->startOfDay();
- break;
- default:
- return false;
- }
- return dt->isValid();
- }
- case QMetaType::QByteArray: {
- QByteArray *ba = static_cast<QByteArray *>(result);
- switch (d->type().id()) {
- case QMetaType::QString:
- *ba = v_cast<QString>(d)->toUtf8();
- break;
- case QMetaType::Double:
- *ba = QByteArray::number(d->data.d, 'g', QLocale::FloatingPointShortest);
- break;
- case QMetaType::Float:
- *ba = QByteArray::number(d->data.f, 'g', QLocale::FloatingPointShortest);
- break;
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- *ba = QByteArray(1, d->data.c);
- break;
- case QMetaType::Int:
- case QMetaType::LongLong:
- case QMetaType::Short:
- case QMetaType::Long:
- *ba = QByteArray::number(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *ba = QByteArray::number(qMetaTypeUNumber(d));
- break;
- case QMetaType::Bool:
- *ba = QByteArray(d->data.b ? "true" : "false");
- break;
- case QMetaType::QUuid:
- *ba = v_cast<QUuid>(d)->toByteArray();
- break;
- case QMetaType::Nullptr:
- *ba = QByteArray();
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isByteArray())
- *ba = v_cast<QCborValue>(d)->toByteArray();
- else
- return false;
- break;
-#endif
- default:
-#ifndef QT_NO_QOBJECT
- {
- QMetaEnum en = metaEnumFromType(d->type());
- if (en.isValid()) {
- *ba = en.valueToKey(qConvertToNumber(d, ok));
- return *ok;
- }
- }
-#endif
- return false;
- }
- }
- break;
- case QMetaType::Short:
- *static_cast<short *>(result) = short(qConvertToNumber(d, ok));
- return *ok;
- case QMetaType::Long:
- *static_cast<long *>(result) = long(qConvertToNumber(d, ok));
- return *ok;
- case QMetaType::UShort:
- *static_cast<ushort *>(result) = ushort(qConvertToUnsignedNumber(d, ok));
- return *ok;
- case QMetaType::ULong:
- *static_cast<ulong *>(result) = ulong(qConvertToUnsignedNumber(d, ok));
- return *ok;
- case QMetaType::Int:
- *static_cast<int *>(result) = int(qConvertToNumber(d, ok));
- return *ok;
- case QMetaType::UInt:
- *static_cast<uint *>(result) = uint(qConvertToUnsignedNumber(d, ok));
- return *ok;
- case QMetaType::LongLong:
- *static_cast<qlonglong *>(result) = qConvertToNumber(d, ok);
- return *ok;
- case QMetaType::ULongLong: {
- *static_cast<qulonglong *>(result) = qConvertToUnsignedNumber(d, ok);
- return *ok;
- }
- case QMetaType::SChar: {
- signed char s = qConvertToNumber(d, ok);
- *static_cast<signed char*>(result) = s;
- return *ok;
- }
- case QMetaType::UChar: {
- *static_cast<uchar *>(result) = qConvertToUnsignedNumber(d, ok);
- return *ok;
- }
- case QMetaType::Bool: {
- bool *b = static_cast<bool *>(result);
- switch (d->type().id()) {
- case QMetaType::QByteArray:
- *b = qt_convertToBool<QByteArray, const char*>(d);
- break;
- case QMetaType::QString:
- *b = qt_convertToBool<QString, QLatin1String>(d);
- break;
- case QMetaType::QChar:
- *b = !v_cast<QChar>(d)->isNull();
- break;
- case QMetaType::Double:
- case QMetaType::Int:
- case QMetaType::LongLong:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Float:
- *b = qMetaTypeNumber(d) != Q_INT64_C(0);
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- *b = v_cast<QCborValue>(d)->toBool();
- if (!v_cast<QCborValue>(d)->isBool())
- return false;
- break;
- case QMetaType::QJsonValue:
- *b = v_cast<QJsonValue>(d)->toBool(false);
- if (!v_cast<QJsonValue>(d)->isBool())
- return false;
- break;
-#endif
- default:
- *b = false;
- return false;
- }
- break;
- }
- case QMetaType::Double: {
- double *f = static_cast<double *>(result);
- switch (d->type().id()) {
- case QMetaType::QString:
- *f = v_cast<QString>(d)->toDouble(ok);
- break;
- case QMetaType::QByteArray:
- *f = v_cast<QByteArray>(d)->toDouble(ok);
- break;
- case QMetaType::Bool:
- *f = double(d->data.b);
- break;
- case QMetaType::Float:
- *f = double(d->data.f);
- break;
- case QMetaType::LongLong:
- case QMetaType::Int:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- *f = double(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *f = double(qMetaTypeUNumber(d));
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- *f = v_cast<QCborValue>(d)->toDouble();
- if (!v_cast<QCborValue>(d)->isDouble())
- return false;
- break;
- case QMetaType::QJsonValue:
- *f = v_cast<QJsonValue>(d)->toDouble(0.0);
- if (!v_cast<QJsonValue>(d)->isDouble())
- return false;
- break;
-#endif
- default:
- *f = 0.0;
- return false;
- }
- break;
- }
- case QMetaType::Float: {
- float *f = static_cast<float *>(result);
- switch (d->type().id()) {
- case QMetaType::QString:
- *f = v_cast<QString>(d)->toFloat(ok);
- break;
- case QMetaType::QByteArray:
- *f = v_cast<QByteArray>(d)->toFloat(ok);
- break;
- case QMetaType::Bool:
- *f = float(d->data.b);
- break;
- case QMetaType::Double:
- *f = float(d->data.d);
- break;
- case QMetaType::LongLong:
- case QMetaType::Int:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- *f = float(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *f = float(qMetaTypeUNumber(d));
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- *f = v_cast<QCborValue>(d)->toDouble();
- if (!v_cast<QCborValue>(d)->isDouble())
- return false;
- break;
- case QMetaType::QJsonValue:
- *f = v_cast<QJsonValue>(d)->toDouble(0.0);
- if (!v_cast<QJsonValue>(d)->isDouble())
- return false;
- break;
-#endif
- default:
- *f = 0.0f;
- return false;
- }
- break;
- }
- case QMetaType::QVariantList:
- if (d->type().id() == QMetaType::QStringList) {
- QVariantList *lst = static_cast<QVariantList *>(result);
- const QStringList *slist = v_cast<QStringList>(d);
- const int size = slist->size();
- lst->reserve(size);
- for (int i = 0; i < size; ++i)
- lst->append(QVariant(slist->at(i)));
-#ifndef QT_BOOTSTRAPPED
- } else if (d->type().id() == QMetaType::QCborValue) {
- if (!v_cast<QCborValue>(d)->isArray())
- return false;
- *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList();
- } else if (d->type().id() == QMetaType::QCborArray) {
- *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList();
- } else if (d->type().id() == QMetaType::QJsonValue) {
- if (!v_cast<QJsonValue>(d)->isArray())
- return false;
- *static_cast<QVariantList *>(result) = v_cast<QJsonValue>(d)->toArray().toVariantList();
- } else if (d->type().id() == QMetaType::QJsonArray) {
- *static_cast<QVariantList *>(result) = v_cast<QJsonArray>(d)->toVariantList();
-#endif
- } else {
- return false;
- }
- break;
- case QMetaType::QVariantMap:
- if (d->type().id() == QMetaType::QVariantHash) {
- QVariantMap *map = static_cast<QVariantMap *>(result);
- const QVariantHash *hash = v_cast<QVariantHash>(d);
- const auto end = hash->end();
- for (auto it = hash->begin(); it != end; ++it)
- static_cast<QMultiMap<QString, QVariant> *>(map)->insert(it.key(), it.value());
-#ifndef QT_BOOTSTRAPPED
- } else if (d->type().id() == QMetaType::QCborValue) {
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap();
- } else if (d->type().id() == QMetaType::QCborMap) {
- *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap();
- } else if (d->type().id() == QMetaType::QJsonValue) {
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QVariantMap *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantMap();
- } else if (d->type().id() == QMetaType::QJsonObject) {
- *static_cast<QVariantMap *>(result) = v_cast<QJsonObject>(d)->toVariantMap();
-#endif
- } else {
- return false;
- }
- break;
- case QMetaType::QVariantHash:
- if (d->type().id() == QMetaType::QVariantMap) {
- QVariantHash *hash = static_cast<QVariantHash *>(result);
- const QVariantMap *map = v_cast<QVariantMap>(d);
- const auto end = map->end();
- for (auto it = map->begin(); it != end; ++it)
- hash->insert(it.key(), it.value());
-#ifndef QT_BOOTSTRAPPED
- } else if (d->type().id() == QMetaType::QCborValue) {
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash();
- } else if (d->type().id() == QMetaType::QCborMap) {
- *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash();
- } else if (d->type().id() == QMetaType::QJsonValue) {
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QVariantHash *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantHash();
- } else if (d->type().id() == QMetaType::QJsonObject) {
- *static_cast<QVariantHash *>(result) = v_cast<QJsonObject>(d)->toVariantHash();
-#endif
- } else {
- return false;
- }
- break;
-#ifndef QT_NO_GEOM_VARIANT
- case QMetaType::QRect:
- if (d->type().id() == QMetaType::QRectF)
- *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect();
- else
- return false;
- break;
- case QMetaType::QRectF:
- if (d->type().id() == QMetaType::QRect)
- *static_cast<QRectF *>(result) = *v_cast<QRect>(d);
- else
- return false;
- break;
- case QMetaType::QPointF:
- if (d->type().id() == QMetaType::QPoint)
- *static_cast<QPointF *>(result) = *v_cast<QPoint>(d);
- else
- return false;
- break;
- case QMetaType::QPoint:
- if (d->type().id() == QMetaType::QPointF)
- *static_cast<QPoint *>(result) = (v_cast<QPointF>(d))->toPoint();
- else
- return false;
- break;
- case QMetaType::Char:
- {
- *static_cast<qint8 *>(result) = qint8(qConvertToNumber(d, ok));
- return *ok;
- }
-#endif
- case QMetaType::QUuid:
- switch (d->type().id()) {
- case QMetaType::QString:
- *static_cast<QUuid *>(result) = QUuid(*v_cast<QString>(d));
- break;
- case QMetaType::QByteArray:
- *static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d));
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isUuid())
- return false;
- *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid();
- break;
-#endif
- default:
- return false;
- }
- break;
- case QMetaType::Nullptr:
- *static_cast<std::nullptr_t *>(result) = nullptr;
- if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject)
- || d->type().id() == QMetaType::VoidStar) {
- if (v_cast<const void *>(d) == nullptr)
- break;
- }
-#ifndef QT_BOOTSTRAPPED
- if (d->type().id() == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull())
- break;
-#endif
+ using namespace QtMetaTypePrivate;
+ if (!iface || iface->size == 0)
return false;
-#ifndef QT_BOOTSTRAPPED
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
- if (d->type().id() != QMetaType::QCborValue
- || !v_cast<QCborValue>(d)->isRegularExpression())
- return false;
- *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression();
- break;
-#endif
- case QMetaType::QJsonValue:
- switch (d->type().id()) {
- case QMetaType::Nullptr:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Null);
- break;
- case QMetaType::Bool:
- *static_cast<QJsonValue *>(result) = QJsonValue(d->data.b);
- break;
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- *static_cast<QJsonValue *>(result) = QJsonValue(qConvertToRealNumber(d, ok));
- Q_ASSERT(ok);
- break;
- case QMetaType::QString:
- *static_cast<QJsonValue *>(result) = QJsonValue(*v_cast<QString>(d));
- break;
- case QMetaType::QStringList:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromStringList(*v_cast<QStringList>(d)));
- break;
- case QMetaType::QVariantList:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromVariantList(*v_cast<QVariantList>(d)));
- break;
- case QMetaType::QVariantMap:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d)));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d)));
- break;
- case QMetaType::QJsonObject:
- *static_cast<QJsonValue *>(result) = *v_cast<QJsonObject>(d);
- break;
- case QMetaType::QJsonArray:
- *static_cast<QJsonValue *>(result) = *v_cast<QJsonArray>(d);
- break;
- case QMetaType::QJsonDocument: {
- QJsonDocument doc = *v_cast<QJsonDocument>(d);
- *static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
- break;
- }
- case QMetaType::QCborValue:
- *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue();
- break;
- case QMetaType::QCborMap:
- *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject();
- break;
- case QMetaType::QCborArray:
- *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray();
- break;
- default:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined);
- return false;
- }
- break;
- case QMetaType::QJsonArray:
- switch (d->type().id()) {
- case QMetaType::QStringList:
- *static_cast<QJsonArray *>(result) = QJsonArray::fromStringList(*v_cast<QStringList>(d));
- break;
- case QMetaType::QVariantList:
- *static_cast<QJsonArray *>(result) = QJsonArray::fromVariantList(*v_cast<QVariantList>(d));
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isArray())
- return false;
- *static_cast<QJsonArray *>(result) = v_cast<QJsonValue>(d)->toArray();
- break;
- case QMetaType::QJsonDocument:
- if (!v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array();
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isArray())
- return false;
- *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray();
- break;
- case QMetaType::QCborArray:
- *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray();
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QJsonObject:
- switch (d->type().id()) {
- case QMetaType::QVariantMap:
- *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d));
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QJsonObject *>(result) = v_cast<QJsonValue>(d)->toObject();
- break;
- case QMetaType::QJsonDocument:
- if (v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object();
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject();
- break;
- case QMetaType::QCborMap:
- *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject();
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QCborSimpleType:
- if (d->type().id() == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) {
- *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType();
- break;
- }
+ Q_ASSERT(!isInterfaceFor<void>(iface)); // only void should have size 0
+ if (!isCopyConstructible(iface) || !isDestructible(iface)) {
+ // all meta types must be copyable (because QVariant is) and
+ // destructible (because QVariant owns it)
+ qWarning("QVariant: Provided metatype for '%s' does not support destruction and "
+ "copy construction", iface->name);
return false;
- case QMetaType::QCborValue:
- switch (d->type().id()) {
- case QMetaType::Nullptr:
- *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null);
- break;
- case QMetaType::Bool:
- *static_cast<QCborValue *>(result) = QCborValue(d->data.b);
- break;
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok));
- Q_ASSERT(ok);
- break;
- case QMetaType::Double:
- case QMetaType::Float:
- *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok));
- Q_ASSERT(ok);
- break;
- case QMetaType::QString:
- *static_cast<QCborValue *>(result) = *v_cast<QString>(d);
- break;
- case QMetaType::QStringList:
- *static_cast<QCborValue *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
- break;
- case QMetaType::QByteArray:
- *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d);
- break;
- case QMetaType::QDate:
- *static_cast<QCborValue *>(result) = QCborValue(v_cast<QDate>(d)->startOfDay());
- break;
- case QMetaType::QDateTime:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d));
- break;
- case QMetaType::QUrl:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d));
- break;
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d));
- break;
-#endif
- case QMetaType::QUuid:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d));
- break;
- case QMetaType::QVariantList:
- *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
- break;
- case QMetaType::QVariantMap:
- *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
- break;
- case QMetaType::QJsonValue:
- *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(*v_cast<QJsonValue>(d));
- break;
- case QMetaType::QJsonObject:
- *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
- break;
- case QMetaType::QJsonArray:
- *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
- break;
- case QMetaType::QJsonDocument: {
- QJsonDocument doc = *v_cast<QJsonDocument>(d);
- if (doc.isArray())
- *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(doc.array());
- else
- *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(doc.object());
- break;
- }
- case QMetaType::QCborSimpleType:
- *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d);
- break;
- case QMetaType::QCborMap:
- *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d);
- break;
- case QMetaType::QCborArray:
- *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d);
- break;
- default:
- *static_cast<QCborValue *>(result) = {};
- return false;
- }
- break;
- case QMetaType::QCborArray:
- switch (d->type().id()) {
- case QMetaType::QStringList:
- *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
- break;
- case QMetaType::QVariantList:
- *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isArray())
- return false;
- *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray();
- break;
- case QMetaType::QJsonDocument:
- if (!v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonDocument>(d)->array());
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isArray())
- return false;
- *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonValue>(d)->toArray());
- break;
- case QMetaType::QJsonArray:
- *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QCborMap:
- switch (d->type().id()) {
- case QMetaType::QVariantMap:
- *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap();
- break;
- case QMetaType::QJsonDocument:
- if (v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonDocument>(d)->object());
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonValue>(d)->toObject());
- break;
- case QMetaType::QJsonObject:
- *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
- break;
- default:
- return false;
- }
- break;
-#endif
-
- default:
-#ifndef QT_NO_QOBJECT
- if (d->type().id() == QMetaType::QString || d->type().id() == QMetaType::QByteArray) {
- QMetaEnum en = metaEnumFromType(QMetaType(t));
- if (en.isValid()) {
- QByteArray keys = (d->type().id() == QMetaType::QString)
- ? v_cast<QString>(d)->toUtf8()
- : *v_cast<QByteArray>(d);
- int value = en.keysToValue(keys.constData(), ok);
- if (*ok) {
- switch (QMetaType::sizeOf(t)) {
- case 1:
- *static_cast<signed char *>(result) = value;
- return true;
- case 2:
- *static_cast<qint16 *>(result) = value;
- return true;
- case 4:
- *static_cast<qint32 *>(result) = value;
- return true;
- case 8:
- *static_cast<qint64 *>(result) = value;
- return true;
- }
- }
- }
- }
-#endif
- if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration
- || d->type().id() == QMetaType::QCborSimpleType) {
- qlonglong value = qConvertToNumber(d, ok);
- if (*ok) {
- switch (QMetaType::sizeOf(t)) {
- case 1:
- *static_cast<signed char *>(result) = value;
- return true;
- case 2:
- *static_cast<qint16 *>(result) = value;
- return true;
- case 4:
- *static_cast<qint32 *>(result) = value;
- return true;
- case 8:
- *static_cast<qint64 *>(result) = value;
- return true;
- }
- }
- return *ok;
- }
+ }
+ if (!copy && !isDefaultConstructible(iface)) {
+ // non-default-constructible types are acceptable, but not if you're
+ // asking us to construct from nothing
+ qWarning("QVariant: Cannot create type '%s' without a default constructor", iface->name);
return false;
}
- return true;
-}
-#if !defined(QT_NO_DEBUG_STREAM)
-static void streamDebug(QDebug dbg, const QVariant &v)
-{
- QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
- QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
- QMetaTypeSwitcher::switcher<void>(stream, d->type().id());
+ return true;
}
-#endif
-const QVariant::Handler qt_kernel_variant_handler = {
- isNull,
- compare,
- convert,
-#if !defined(QT_NO_DEBUG_STREAM)
- streamDebug
-#else
- nullptr
-#endif
+enum CustomConstructMoveOptions {
+ UseCopy, // custom construct uses the copy ctor unconditionally
+ // future option: TryMove: uses move ctor if available, else copy ctor
+ ForceMove, // custom construct use the move ctor (which must exist)
};
-static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; }
-static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; }
-static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; }
-#if !defined(QT_NO_DEBUG_STREAM)
-static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); }
-#endif
-const QVariant::Handler qt_dummy_variant_handler = {
- dummyIsNull,
- dummyCompare,
- dummyConvert,
-#if !defined(QT_NO_DEBUG_STREAM)
- dummyStreamDebug
-#else
- nullptr
-#endif
+enum CustomConstructNullabilityOption {
+ MaybeNull, // copy might be null, might be non-null
+ NonNull, // copy is guarantueed to be non-null
+ // future option: AlwaysNull?
};
// the type of d has already been set, but other field are not set
-static void customConstruct(QVariant::Private *d, const void *copy)
-{
- const QMetaType type = d->type();
- const uint size = type.sizeOf();
- if (!size) {
- *d = QVariant::Private();
- return;
- }
-
- // this logic should match with QVariantIntegrator::CanUseInternalSpace
- if (size <= sizeof(QVariant::Private::Data)
- && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) {
- type.construct(&d->data, copy);
+template <CustomConstructMoveOptions moveOption = UseCopy, CustomConstructNullabilityOption nullability = MaybeNull>
+static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant::Private *d,
+ std::conditional_t<moveOption == ForceMove, void *, const void *> copy)
+{
+ using namespace QtMetaTypePrivate;
+ Q_ASSERT(iface);
+ Q_ASSERT(iface->size);
+ Q_ASSERT(!isInterfaceFor<void>(iface));
+ Q_ASSERT(isCopyConstructible(iface));
+ Q_ASSERT(isDestructible(iface));
+ Q_ASSERT(copy || isDefaultConstructible(iface));
+ if constexpr (moveOption == ForceMove)
+ Q_ASSERT(isMoveConstructible(iface));
+ if constexpr (nullability == NonNull)
+ Q_ASSERT(copy != nullptr);
+
+ // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses
+ // std::addressof(value) which in this case returns the address of the nullptr object.
+ // ### Qt 7: remove nullptr_t special casing
+ d->is_null = !copy QT6_ONLY(|| isInterfaceFor<std::nullptr_t>(iface));
+
+ if (QVariant::Private::canUseInternalSpace(iface)) {
d->is_shared = false;
+ if (!copy && !iface->defaultCtr)
+ return; // trivial default constructor and it's OK to build in 0-filled storage, which we've already done
+ if constexpr (moveOption == ForceMove && nullability == NonNull)
+ moveConstruct(iface, d->data.data, copy);
+ else
+ construct(iface, d->data.data, copy);
} else {
- // Private::Data contains long long, and long double is the biggest standard type.
- const size_t maxAlignment =
- qMax(alignof(QVariant::Private::Data), alignof(long double));
- const size_t s = sizeof(QVariant::PrivateShared);
- const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
- void *data = operator new(offset + size);
- void *ptr = static_cast<char *>(data) + offset;
- type.construct(ptr, copy);
+ d->data.shared = customConstructShared(iface->size, iface->alignment, [=](void *where) {
+ if constexpr (moveOption == ForceMove && nullability == NonNull)
+ moveConstruct(iface, where, copy);
+ else
+ construct(iface, where, copy);
+ });
d->is_shared = true;
- d->data.shared = new (data) QVariant::PrivateShared(ptr);
}
- d->is_null = !copy;
}
static void customClear(QVariant::Private *d)
{
+ const QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
+ if (!iface)
+ return;
if (!d->is_shared) {
- d->type().destruct(&d->data);
+ QtMetaTypePrivate::destruct(iface, d->data.data);
} else {
- d->type().destruct(d->data.shared->ptr);
- d->data.shared->~PrivateShared();
- operator delete(d->data.shared);
- }
-}
-
-static bool customIsNull(const QVariant::Private *d)
-{
- if (d->is_null)
- return true;
- if (d->type().flags() & QMetaType::IsPointer) {
- const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data);
- return *static_cast<void *const *>(d_ptr) == nullptr;
+ QtMetaTypePrivate::destruct(iface, d->data.shared->data());
+ QVariant::PrivateShared::free(d->data.shared);
}
- return false;
}
-static bool customCompare(const QVariant::Private *a, const QVariant::Private *b)
+static QVariant::Private clonePrivate(const QVariant::Private &other)
{
- const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data);
- const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data);
-
- if (a->is_null && b->is_null)
- return true;
-
- return !memcmp(a_ptr, b_ptr, a->type().sizeOf());
-}
+ QVariant::Private d = other;
+ if (d.is_shared) {
+ d.data.shared->ref.ref();
+ } else if (const QtPrivate::QMetaTypeInterface *iface = d.typeInterface()) {
+ Q_ASSERT(d.canUseInternalSpace(iface));
-static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok)
-{
- if (d->type().id() >= QMetaType::User || t >= QMetaType::User) {
- if (QMetaType::convert(constData(*d), d->type().id(), result, t)) {
- if (ok)
- *ok = true;
- return true;
- }
+ // if not trivially copyable, ask to copy
+ if (iface->copyCtr)
+ QtMetaTypePrivate::copyConstruct(iface, d.data.data, other.data.data);
}
- return convert(d, t, result, ok);
-}
-
-#if !defined(QT_NO_DEBUG_STREAM)
-static void customStreamDebug(QDebug dbg, const QVariant &variant) {
-#ifndef QT_BOOTSTRAPPED
- QMetaType::TypeFlags flags = QMetaType::typeFlags(variant.userType());
- if (flags & QMetaType::PointerToQObject)
- dbg.nospace() << qvariant_cast<QObject*>(variant);
-#else
- Q_UNUSED(dbg);
- Q_UNUSED(variant);
-#endif
-}
-#endif
-
-const QVariant::Handler qt_custom_variant_handler = {
- customIsNull,
- customCompare,
- customConvert,
-#if !defined(QT_NO_DEBUG_STREAM)
- customStreamDebug
-#else
- nullptr
-#endif
-};
-
-} // annonymous used to hide QVariant handlers
-
-static HandlersManager handlerManager;
-
-static_assert(!QModulesPrivate::Core, "Initialization assumes that ModulesNames::Core is 0");
-const QVariant::Handler *HandlersManager::Handlers[QModulesPrivate::ModulesCount]
- = { &qt_kernel_variant_handler, &qt_dummy_variant_handler,
- &qt_dummy_variant_handler, &qt_custom_variant_handler };
-
-Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler()
-{
- return &qt_kernel_variant_handler;
+ return d;
}
-Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names */name, const QVariant::Handler *handler)
-{
- handlerManager.registerHandler(static_cast<QModulesPrivate::Names>(name), handler);
-}
+} // anonymous used to hide QVariant handlers
/*!
\class QVariant
@@ -1542,17 +324,18 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
\ingroup objectmodel
\ingroup shared
+ \compares equality
Because C++ forbids unions from including types that have
non-default constructors or destructors, most interesting Qt
classes cannot be used in unions. Without QVariant, this would be
a problem for QObject::property() and for database work, etc.
- A QVariant object holds a single value of a single type() at a
- time. (Some type()s are multi-valued, for example a string list.)
+ A QVariant object holds a single value of a single typeId() at a
+ time. (Some types are multi-valued, for example a string list.)
You can find out what type, T, the variant holds, convert it to a
different type using convert(), get its value using one of the
- toT() functions (e.g., toSize()) and check whether the type can
+ toT() functions (e.g., toSize()), and check whether the type can
be converted to a particular type using canConvert().
The methods named toT() (e.g., toInt(), toString()) are const. If
@@ -1573,15 +356,14 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
and versatile, but may prove less memory and speed efficient than
storing specific types in standard data structures.
- QVariant also supports the notion of null values, where you can
- have a defined type with no value set. However, note that QVariant
- types can only be cast when they have had a value set.
+ QVariant also supports the notion of null values. A variant is null
+ if the variant contains no initialized value, or contains a null pointer.
\snippet code/src_corelib_kernel_qvariant.cpp 1
QVariant can be extended to support other types than those
- mentioned in the \l Type enum. See \l{Creating Custom Qt Types}{Creating Custom Qt Types}
- for details.
+ mentioned in the \l QMetaType::Type enum.
+ See \l{Creating Custom Qt Types}{Creating Custom Qt Types} for details.
\section1 A Note on GUI Types
@@ -1607,9 +389,9 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
QVariant to convert between types given suitable data; it is still
possible to supply data which cannot actually be converted.
- For example, canConvert(Int) would return true when called on a variant
- containing a string because, in principle, QVariant is able to convert
- strings of numbers to integers.
+ For example, \c{canConvert(QMetaType::fromType<int>())} would return true
+ when called on a variant containing a string because, in principle,
+ QVariant is able to convert strings of numbers to integers.
However, if the string contains non-numeric characters, it cannot be
converted to an integer, and any attempt to convert it will fail.
Hence, it is important to have both functions return true for a
@@ -1619,7 +401,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
*/
/*!
- \obsolete Use QMetaType::Type instead
+ \deprecated Use \l QMetaType::Type instead.
\enum QVariant::Type
This enum type defines the types of variable that a QVariant can
@@ -1640,7 +422,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
\value EasingCurve a QEasingCurve
\value Uuid a QUuid
\value ModelIndex a QModelIndex
- \value PersistentModelIndex a QPersistentModelIndex (since 5.5)
+ \value [since 5.5] PersistentModelIndex a QPersistentModelIndex
\value Font a QFont
\value Hash a QVariantHash
\value Icon a QIcon
@@ -1712,63 +494,41 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
Constructs an invalid variant.
*/
-
/*!
- \fn QVariant::QVariant(int typeId, const void *copy)
-
- Constructs variant of type \a typeId, and initializes with
- \a copy if \a copy is not \nullptr.
-
- Note that you have to pass the address of the variable you want stored.
-
- Usually, you never have to use this constructor, use QVariant::fromValue()
- instead to construct variants from the pointer types represented by
- \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
-
- \sa QVariant::fromValue(), QMetaType::Type
-*/
+ \fn QVariant::create(int type, const void *copy)
-/*!
- \fn QVariant::QVariant(Type type)
+ \internal
- Constructs an uninitialized variant of type \a type. This will create a
- variant in a special null state that if accessed will return a default
- constructed value of the \a type.
+ Constructs a variant private of type \a type, and initializes with \a copy if
+ \a copy is not \nullptr.
- \sa isNull()
*/
-
-
+//### Qt 7: Remove in favor of QMetaType overload
+void QVariant::create(int type, const void *copy)
+{
+ create(QMetaType(type), copy);
+}
/*!
\fn QVariant::create(int type, const void *copy)
\internal
-
- Constructs a variant private of type \a type, and initializes with \a copy if
- \a copy is not \nullptr.
+ \overload
*/
-
-void QVariant::create(int type, const void *copy)
+void QVariant::create(QMetaType type, const void *copy)
{
- d = Private(QMetaType(type));
- customConstruct(&d, copy);
+ *this = QVariant::fromMetaType(type, copy);
}
/*!
\fn QVariant::~QVariant()
Destroys the QVariant and the contained object.
-
- Note that subclasses that reimplement clear() should reimplement
- the destructor to call clear(). This destructor calls clear(), but
- because it is the destructor, QVariant::clear() is called rather
- than a subclass's clear().
*/
QVariant::~QVariant()
{
- if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared))
+ if (!d.is_shared || !d.data.shared->ref.deref())
customClear(&d);
}
@@ -1780,37 +540,121 @@ QVariant::~QVariant()
*/
QVariant::QVariant(const QVariant &p)
- : d(p.d)
+ : d(clonePrivate(p.d))
{
- if (d.is_shared) {
- d.data.shared->ref.ref();
- } else if (d.type().isValid()) {
- customConstruct(&d, p.constData());
- d.is_null = p.d.is_null;
- }
}
-#ifndef QT_NO_DATASTREAM
/*!
- Reads the variant from the data stream, \a s.
+ \fn template <typename T, typename... Args, QVariant::if_constructible<T, Args...> = true> QVariant::QVariant(std::in_place_type_t<T>, Args&&... args) noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
+
+ \since 6.6
+ Constructs a new variant containing a value of type \c T. The contained
+ value is is initialized with the arguments
+ \c{std::forward<Args>(args)...}.
+
+ This overload only participates in overload resolution if \c T can be
+ constructed from \a args.
+
+ This constructor is provided for STL/std::any compatibility.
+
+ \overload
+ */
+
+/*!
+
+ \fn template <typename T, typename U, typename... Args, QVariant::if_constructible<T, std::initializer_list<U> &, Args...> = true> explicit QVariant::QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args) noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, std::initializer_list<U> &, Args... >::value)
+
+ \since 6.6
+ \overload
+ This overload exists to support types with constructors taking an
+ \c initializer_list. It behaves otherwise equivalent to the
+ non-initializer list \c{in_place_type_t} overload.
+*/
+
+
+/*!
+ \fn template <typename T, typename... Args, QVariant::if_constructible<T, Args...> = true> QVariant::emplace(Args&&... args)
+
+ \since 6.6
+ Replaces the object currently held in \c{*this} with an object of
+ type \c{T}, constructed from \a{args}\c{...}. If \c{*this} was non-null,
+ the previously held object is destroyed first.
+ If possible, this method will reuse memory allocated by the QVariant.
+ Returns a reference to the newly-created object.
+ */
+
+/*!
+ \fn template <typename T, typename U, typename... Args, QVariant::if_constructible<T, std::initializer_list<U> &, Args...> = true> QVariant::emplace(std::initializer_list<U> list, Args&&... args)
+
+ \since 6.6
+ \overload
+ This overload exists to support types with constructors taking an
+ \c initializer_list. It behaves otherwise equivalent to the
+ non-initializer list overload.
*/
-QVariant::QVariant(QDataStream &s)
+
+QVariant::QVariant(std::in_place_t, QMetaType type) : d(type.iface())
{
- d.is_null = true;
- s >> *this;
+ // we query the metatype instead of detecting it at compile time
+ // so that we can change relocatability of internal types
+ if (!Private::canUseInternalSpace(type.iface())) {
+ d.data.shared = PrivateShared::create(type.sizeOf(), type.alignOf());
+ d.is_shared = true;
+ }
+}
+
+/*!
+ \internal
+ Returns a pointer to data suitable for placement new
+ of an object of type \a type
+ Changes the variant's metatype to \a type
+ */
+void *QVariant::prepareForEmplace(QMetaType type)
+{
+ /* There are two cases where we can reuse the existing storage
+ (1) The new type fits in QVariant's SBO storage
+ (2) We are using the externally allocated storage, the variant is
+ detached, and the new type fits into the existing storage.
+ In all other cases (3), we cannot reuse the storage.
+ */
+ auto typeFits = [&] {
+ auto newIface = type.iface();
+ auto oldIface = d.typeInterface();
+ auto newSize = PrivateShared::computeAllocationSize(newIface->size, newIface->alignment);
+ auto oldSize = PrivateShared::computeAllocationSize(oldIface->size, oldIface->alignment);
+ return newSize <= oldSize;
+ };
+ if (Private::canUseInternalSpace(type.iface())) { // (1)
+ clear();
+ d.packedType = quintptr(type.iface()) >> 2;
+ return d.data.data;
+ } else if (d.is_shared && isDetached() && typeFits()) { // (2)
+ QtMetaTypePrivate::destruct(d.typeInterface(), d.data.shared->data());
+ // compare QVariant::PrivateShared::create
+ const auto ps = d.data.shared;
+ const auto align = type.alignOf();
+ ps->offset = PrivateShared::computeOffset(ps, align);
+ d.packedType = quintptr(type.iface()) >> 2;
+ return ps->data();
+ }
+ // (3)
+ QVariant newVariant(std::in_place, type);
+ swap(newVariant);
+ // const cast is safe, we're in a non-const method
+ return const_cast<void *>(d.storage());
}
-#endif //QT_NO_DATASTREAM
/*!
- \fn QVariant::QVariant(const QString &val)
+ \fn QVariant::QVariant(const QString &val) noexcept
Constructs a new variant with a string value, \a val.
*/
/*!
- \fn QVariant::QVariant(QLatin1String val)
+ \fn QVariant::QVariant(QLatin1StringView val)
- Constructs a new variant with a string value, \a val.
+ Constructs a new variant with a QString value from the Latin-1
+ string viewed by \a val.
*/
/*!
@@ -1829,37 +673,37 @@ QVariant::QVariant(QDataStream &s)
*/
/*!
- \fn QVariant::QVariant(const QStringList &val)
+ \fn QVariant::QVariant(const QStringList &val) noexcept
Constructs a new variant with a string list value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QMap<QString, QVariant> &val)
+ \fn QVariant::QVariant(const QMap<QString, QVariant> &val) noexcept
Constructs a new variant with a map of \l {QVariant}s, \a val.
*/
/*!
- \fn QVariant::QVariant(const QHash<QString, QVariant> &val)
+ \fn QVariant::QVariant(const QHash<QString, QVariant> &val) noexcept
Constructs a new variant with a hash of \l {QVariant}s, \a val.
*/
/*!
- \fn QVariant::QVariant(QDate val)
+ \fn QVariant::QVariant(QDate val) noexcept
Constructs a new variant with a date value, \a val.
*/
/*!
- \fn QVariant::QVariant(QTime val)
+ \fn QVariant::QVariant(QTime val) noexcept
Constructs a new variant with a time value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QDateTime &val)
+ \fn QVariant::QVariant(const QDateTime &val) noexcept
Constructs a new variant with a date/time value, \a val.
*/
@@ -1873,14 +717,14 @@ QVariant::QVariant(QDataStream &s)
/*!
\since 5.0
- \fn QVariant::QVariant(const QUuid &val)
+ \fn QVariant::QVariant(QUuid val) noexcept
Constructs a new variant with an uuid value, \a val.
*/
/*!
\since 5.0
- \fn QVariant::QVariant(const QModelIndex &val)
+ \fn QVariant::QVariant(const QModelIndex &val) noexcept
Constructs a new variant with a QModelIndex value, \a val.
*/
@@ -1921,299 +765,247 @@ QVariant::QVariant(QDataStream &s)
*/
/*!
- \fn QVariant::QVariant(const QByteArray &val)
+ \fn QVariant::QVariant(const QByteArray &val) noexcept
Constructs a new variant with a bytearray value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QBitArray &val)
+ \fn QVariant::QVariant(const QBitArray &val) noexcept
Constructs a new variant with a bitarray value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QPoint &val)
+ \fn QVariant::QVariant(QPoint val) noexcept
Constructs a new variant with a point value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QPointF &val)
+ \fn QVariant::QVariant(QPointF val) noexcept
Constructs a new variant with a point value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QRectF &val)
+ \fn QVariant::QVariant(QRectF val)
Constructs a new variant with a rect value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QLineF &val)
+ \fn QVariant::QVariant(QLineF val) noexcept
Constructs a new variant with a line value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QLine &val)
+ \fn QVariant::QVariant(QLine val) noexcept
Constructs a new variant with a line value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QRect &val)
+ \fn QVariant::QVariant(QRect val) noexcept
Constructs a new variant with a rect value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QSize &val)
+ \fn QVariant::QVariant(QSize val) noexcept
Constructs a new variant with a size value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QSizeF &val)
+ \fn QVariant::QVariant(QSizeF val) noexcept
Constructs a new variant with a size value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QUrl &val)
+ \fn QVariant::QVariant(const QUrl &val) noexcept
Constructs a new variant with a url value of \a val.
*/
/*!
- \fn QVariant::QVariant(int val)
+ \fn QVariant::QVariant(int val) noexcept
Constructs a new variant with an integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(uint val)
+ \fn QVariant::QVariant(uint val) noexcept
Constructs a new variant with an unsigned integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(qlonglong val)
+ \fn QVariant::QVariant(qlonglong val) noexcept
Constructs a new variant with a long long integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(qulonglong val)
+ \fn QVariant::QVariant(qulonglong val) noexcept
Constructs a new variant with an unsigned long long integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(bool val)
+ \fn QVariant::QVariant(bool val) noexcept
Constructs a new variant with a boolean value, \a val.
*/
/*!
- \fn QVariant::QVariant(double val)
+ \fn QVariant::QVariant(double val) noexcept
Constructs a new variant with a floating point value, \a val.
*/
/*!
- \fn QVariant::QVariant(float val)
+ \fn QVariant::QVariant(float val) noexcept
Constructs a new variant with a floating point value, \a val.
\since 4.6
*/
/*!
- \fn QVariant::QVariant(const QList<QVariant> &val)
+ \fn QVariant::QVariant(const QList<QVariant> &val) noexcept
Constructs a new variant with a list value, \a val.
*/
/*!
- \fn QVariant::QVariant(QChar c)
+ \fn QVariant::QVariant(QChar c) noexcept
Constructs a new variant with a char value, \a c.
*/
/*!
- \fn QVariant::QVariant(const QLocale &l)
+ \fn QVariant::QVariant(const QLocale &l) noexcept
Constructs a new variant with a locale value, \a l.
*/
/*!
- \fn QVariant::QVariant(const QRegularExpression &re)
+ \fn QVariant::QVariant(const QRegularExpression &re) noexcept
\since 5.0
Constructs a new variant with the regular expression value \a re.
*/
-QVariant::QVariant(Type type)
-{ create(type, nullptr); }
+/*! \fn QVariant::QVariant(Type type)
+ \deprecated [6.0] Use the constructor taking a QMetaType instead.
-/*!
- \internal
- flags is true if it is a pointer type
- */
-QVariant::QVariant(int typeId, const void *copy, uint flags)
-{
- if (flags) { //type is a pointer type
- d = Private(QMetaType(typeId));
- d.data.ptr = *reinterpret_cast<void *const*>(copy);
- } else {
- create(typeId, copy);
- }
- d.is_null = false;
-}
+ Constructs an uninitialized variant of type \a type. This will create a
+ variant in a special null state that if accessed will return a default
+ constructed value of the \a type.
+
+ \sa isNull()
+*/
/*!
- \internal
- flags is true if it is a pointer type
- */
-QVariant::QVariant(QMetaType type, const void *copy) : d(type)
+ Constructs a variant of type \a type, and initializes it with
+ a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
+ must point to an object of type \a type).
+
+ Note that you have to pass the address of the object you want stored.
+
+ Usually, you never have to use this constructor, use QVariant::fromValue()
+ instead to construct variants from the pointer types represented by
+ \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
+
+ If \a type does not support copy construction and \a copy is not \nullptr,
+ the variant will be invalid. Similarly, if \a copy is \nullptr and
+ \a type does not support default construction, the variant will be
+ invalid.
+
+ \sa QVariant::fromMetaType, QVariant::fromValue(), QMetaType::Type
+*/
+QVariant::QVariant(QMetaType type, const void *copy)
+ : d()
{
- customConstruct(&d, copy);
- d.is_null = false;
+ *this = fromMetaType(type, copy);
}
-QVariant::QVariant(int val)
- : d(Int)
-{ d.data.i = val; }
-QVariant::QVariant(uint val)
- : d(UInt)
-{ d.data.u = val; }
-QVariant::QVariant(qlonglong val)
- : d(LongLong)
-{ d.data.ll = val; }
-QVariant::QVariant(qulonglong val)
- : d(ULongLong)
-{ d.data.ull = val; }
-QVariant::QVariant(bool val)
- : d(Bool)
-{ d.data.b = val; }
-QVariant::QVariant(double val)
- : d(Double)
-{ d.data.d = val; }
-QVariant::QVariant(float val)
- : d(QMetaType::Float)
-{ d.data.f = val; }
-
-QVariant::QVariant(const QByteArray &val)
- : d(ByteArray)
-{ v_construct<QByteArray>(&d, val); }
-QVariant::QVariant(const QBitArray &val)
- : d(BitArray)
-{ v_construct<QBitArray>(&d, val); }
-QVariant::QVariant(const QString &val)
- : d(String)
-{ v_construct<QString>(&d, val); }
-QVariant::QVariant(QChar val)
- : d(Char)
-{ v_construct<QChar>(&d, val); }
-QVariant::QVariant(QLatin1String val)
- : d(String)
-{ v_construct<QString>(&d, val); }
-QVariant::QVariant(const QStringList &val)
- : d(StringList)
-{ v_construct<QStringList>(&d, val); }
-
-QVariant::QVariant(QDate val)
- : d(Date)
-{ v_construct<QDate>(&d, val); }
-QVariant::QVariant(QTime val)
- : d(Time)
-{ v_construct<QTime>(&d, val); }
-QVariant::QVariant(const QDateTime &val)
- : d(DateTime)
-{ v_construct<QDateTime>(&d, val); }
+QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(uint val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(qlonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(qulonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(bool val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(double val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {}
+
+QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+#ifndef QT_BOOTSTRAPPED
+QVariant::QVariant(const QBitArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+#endif
+QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+
+QVariant::QVariant(QDate val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(QTime val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(const QDateTime &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+
+QVariant::QVariant(const QList<QVariant> &list) noexcept : d(std::piecewise_construct_t{}, list) {}
+QVariant::QVariant(const QMap<QString, QVariant> &map) noexcept : d(std::piecewise_construct_t{}, map) {}
+QVariant::QVariant(const QHash<QString, QVariant> &hash) noexcept : d(std::piecewise_construct_t{}, hash) {}
+
+QVariant::QVariant(QLatin1StringView val) : QVariant(QString(val)) {}
+
#if QT_CONFIG(easingcurve)
-QVariant::QVariant(const QEasingCurve &val)
- : d(EasingCurve)
-{ v_construct<QEasingCurve>(&d, val); }
+QVariant::QVariant(const QEasingCurve &val) : d(std::piecewise_construct_t{}, val) {}
#endif
-QVariant::QVariant(const QList<QVariant> &list)
- : d(List)
-{ v_construct<QVariantList>(&d, list); }
-QVariant::QVariant(const QMap<QString, QVariant> &map)
- : d(Map)
-{ v_construct<QVariantMap>(&d, map); }
-QVariant::QVariant(const QHash<QString, QVariant> &hash)
- : d(Hash)
-{ v_construct<QVariantHash>(&d, hash); }
#ifndef QT_NO_GEOM_VARIANT
-QVariant::QVariant(const QPoint &pt)
- : d(Point)
-{ v_construct<QPoint>(&d, pt); }
-QVariant::QVariant(const QPointF &pt)
- : d(PointF)
-{ v_construct<QPointF>(&d, pt); }
-QVariant::QVariant(const QRectF &r)
- : d(RectF)
-{ v_construct<QRectF>(&d, r); }
-QVariant::QVariant(const QLineF &l)
- : d(LineF)
-{ v_construct<QLineF>(&d, l); }
-QVariant::QVariant(const QLine &l)
- : d(Line)
-{ v_construct<QLine>(&d, l); }
-QVariant::QVariant(const QRect &r)
- : d(Rect)
-{ v_construct<QRect>(&d, r); }
-QVariant::QVariant(const QSize &s)
- : d(Size)
-{ v_construct<QSize>(&d, s); }
-QVariant::QVariant(const QSizeF &s)
- : d(SizeF)
-{ v_construct<QSizeF>(&d, s); }
+QVariant::QVariant(QPoint pt) noexcept
+ : d(std::piecewise_construct_t{}, pt) {}
+QVariant::QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
+ : d(std::piecewise_construct_t{}, pt) {}
+QVariant::QVariant(QRect r) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
+ : d(std::piecewise_construct_t{}, r) {}
+QVariant::QVariant(QRectF r) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
+ : d(std::piecewise_construct_t{}, r) {}
+QVariant::QVariant(QLine l) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
+ : d(std::piecewise_construct_t{}, l) {}
+QVariant::QVariant(QLineF l) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
+ : d(std::piecewise_construct_t{}, l) {}
+QVariant::QVariant(QSize s) noexcept
+ : d(std::piecewise_construct_t{}, s) {}
+QVariant::QVariant(QSizeF s) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
+ : d(std::piecewise_construct_t{}, s) {}
#endif
#ifndef QT_BOOTSTRAPPED
-QVariant::QVariant(const QUrl &u)
- : d(Url)
-{ v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
#endif
-QVariant::QVariant(const QLocale &l)
- : d(Locale)
-{ v_construct<QLocale>(&d, l); }
+QVariant::QVariant(const QLocale &l) noexcept : d(std::piecewise_construct_t{}, l) {}
#if QT_CONFIG(regularexpression)
-QVariant::QVariant(const QRegularExpression &re)
- : d(RegularExpression)
-{ v_construct<QRegularExpression>(&d, re); }
+QVariant::QVariant(const QRegularExpression &re) noexcept : d(std::piecewise_construct_t{}, re) {}
#endif // QT_CONFIG(regularexpression)
-QVariant::QVariant(const QUuid &uuid)
- : d(Uuid)
-{ v_construct<QUuid>(&d, uuid); }
+QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {}
#ifndef QT_BOOTSTRAPPED
-QVariant::QVariant(const QJsonValue &jsonValue)
- : d(QMetaType::QJsonValue)
-{ v_construct<QJsonValue>(&d, jsonValue); }
-QVariant::QVariant(const QJsonObject &jsonObject)
- : d(QMetaType::QJsonObject)
-{ v_construct<QJsonObject>(&d, jsonObject); }
-QVariant::QVariant(const QJsonArray &jsonArray)
- : d(QMetaType::QJsonArray)
-{ v_construct<QJsonArray>(&d, jsonArray); }
-QVariant::QVariant(const QJsonDocument &jsonDocument)
- : d(QMetaType::QJsonDocument)
-{ v_construct<QJsonDocument>(&d, jsonDocument); }
+QVariant::QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>)
+ : d(std::piecewise_construct_t{}, jsonValue)
+{ static_assert(sizeof(CborValueStandIn) == sizeof(QJsonValue)); }
+QVariant::QVariant(const QJsonObject &jsonObject) noexcept : d(std::piecewise_construct_t{}, jsonObject) {}
+QVariant::QVariant(const QJsonArray &jsonArray) noexcept : d(std::piecewise_construct_t{}, jsonArray) {}
+QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {}
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
-QVariant::QVariant(const QModelIndex &modelIndex)
- : d(ModelIndex)
-{ v_construct<QModelIndex>(&d, modelIndex); }
-QVariant::QVariant(const QPersistentModelIndex &modelIndex)
- : d(PersistentModelIndex)
-{ v_construct<QPersistentModelIndex>(&d, modelIndex); }
+QVariant::QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>)
+ : d(std::piecewise_construct_t{}, modelIndex) {}
+QVariant::QVariant(const QPersistentModelIndex &modelIndex) : d(std::piecewise_construct_t{}, modelIndex) {}
#endif
-/*!
+/*! \fn QVariant::Type QVariant::type() const
+ \deprecated [6.0] Use typeId() or metaType() instead.
+
Returns the storage type of the value stored in the variant.
Although this function is declared as returning QVariant::Type,
the return value should be interpreted as QMetaType::Type. In
@@ -2246,23 +1038,19 @@ QVariant::QVariant(const QPersistentModelIndex &modelIndex)
\sa userType(), metaType()
*/
-QVariant::Type QVariant::type() const
-{
- int type = d.type().id();
- return type >= QMetaType::User ? UserType : static_cast<Type>(type);
-}
-/*!
- Returns the storage type of the value stored in the variant. For
- non-user types, this is the same as type().
- \sa type(), metaType()
+/*! \fn int QVariant::userType() const
+ \fn int QVariant::typeId() const
+
+ Returns the storage type of the value stored in the variant. This is
+ the same as metaType().id().
+
+ \sa metaType()
*/
-int QVariant::userType() const
-{
- return d.type().id();
-}
/*!
+ \since 6.0
+
Returns the QMetaType of the value stored in the variant.
*/
QMetaType QVariant::metaType() const
@@ -2273,21 +1061,13 @@ QMetaType QVariant::metaType() const
/*!
Assigns the value of the variant \a variant to this variant.
*/
-QVariant& QVariant::operator=(const QVariant &variant)
+QVariant &QVariant::operator=(const QVariant &variant)
{
if (this == &variant)
return *this;
clear();
- if (variant.d.is_shared) {
- variant.d.data.shared->ref.ref();
- d = variant.d;
- } else {
- d = variant.d;
- customConstruct(&d, reinterpret_cast<const void *>(&variant.d.data));
- d.is_null = variant.d.is_null;
- }
-
+ d = clonePrivate(variant.d);
return *this;
}
@@ -2310,8 +1090,10 @@ void QVariant::detach()
if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
return;
- Private dd(d.type());
- customConstruct(&dd, constData());
+ Q_ASSERT(isValidMetaTypeForVariant(d.typeInterface(), constData()));
+ Private dd(d.typeInterface());
+ // null variant is never shared; anything else is NonNull
+ customConstruct<UseCopy, NonNull>(d.typeInterface(), &dd, constData());
if (!d.data.shared->ref.deref())
customClear(&d);
d.data.shared = dd.data.shared;
@@ -2331,8 +1113,7 @@ void QVariant::detach()
*/
const char *QVariant::typeName() const
{
- // Cannot use d.type().name because we must return a char*
- return QMetaType::typeName(d.type().id());
+ return d.type().name();
}
/*!
@@ -2341,35 +1122,31 @@ const char *QVariant::typeName() const
*/
void QVariant::clear()
{
- if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared))
+ if (!d.is_shared || !d.data.shared->ref.deref())
customClear(&d);
d = {};
}
/*!
+ \fn const char *QVariant::typeToName(int typeId)
+ \deprecated [6.0] Use \c QMetaType(typeId).name() instead.
+
Converts the int representation of the storage type, \a typeId, to
its string representation.
Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist.
*/
-const char *QVariant::typeToName(int typeId)
-{
- return QMetaType::typeName(typeId);
-}
-
/*!
+ \fn QVariant::Type QVariant::nameToType(const char *name)
+ \deprecated [6.0] Use \c QMetaType::fromName(name).id() instead
+
Converts the string representation of the storage type given in \a
name, to its enum representation.
If the string representation cannot be converted to any enum
representation, the variant is set to \c Invalid.
*/
-QVariant::Type QVariant::nameToType(const char *name)
-{
- int metaType = QMetaType::type(name);
- return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
-}
#ifndef QT_NO_DATASTREAM
enum { MapFromThreeCount = 36 };
@@ -2419,6 +1196,18 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
#endif
};
+// values needed to map Qt5 based type id's to Qt6 based ones
+constexpr int Qt5UserType = 1024;
+constexpr int Qt5LastCoreType = QMetaType::QCborMap;
+constexpr int Qt5FirstGuiType = 64;
+constexpr int Qt5LastGuiType = 87;
+constexpr int Qt5SizePolicy = 121;
+constexpr int Qt5RegExp = 27;
+constexpr int Qt5KeySequence = 75;
+constexpr int Qt5QQuaternion = 85;
+
+constexpr int Qt6ToQt5GuiTypeDelta = qToUnderlying(QMetaType::FirstGuiType) - Qt5FirstGuiType;
+
/*!
Internal function for loading a variant from stream \a s. Use the
stream operators instead.
@@ -2432,35 +1221,46 @@ void QVariant::load(QDataStream &s)
quint32 typeId;
s >> typeId;
if (s.version() < QDataStream::Qt_4_0) {
+ // map to Qt 5 ids
if (typeId >= MapFromThreeCount)
return;
typeId = mapIdFromQt3ToCurrent[typeId];
} else if (s.version() < QDataStream::Qt_5_0) {
+ // map to Qt 5 type ids
if (typeId == 127 /* QVariant::UserType */) {
- typeId = QMetaType::User;
- } else if (typeId >= 128 && typeId != QVariant::UserType) {
+ typeId = Qt5UserType;
+ } else if (typeId >= 128 && typeId != Qt5UserType) {
// In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
// by moving all ids down by 97.
typeId -= 97;
} else if (typeId == 75 /* QSizePolicy */) {
- typeId = QMetaType::QSizePolicy;
+ typeId = Qt5SizePolicy;
} else if (typeId > 75 && typeId <= 86) {
// and as a result these types received lower ids too
// QKeySequence QPen QTextLength QTextFormat QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
typeId -=1;
}
}
+ if (s.version() < QDataStream::Qt_6_0) {
+ // map from Qt 5 to Qt 6 values
+ if (typeId == Qt5UserType) {
+ typeId = QMetaType::User;
+ } else if (typeId >= Qt5FirstGuiType && typeId <= Qt5LastGuiType) {
+ typeId += Qt6ToQt5GuiTypeDelta;
+ } else if (typeId == Qt5SizePolicy) {
+ typeId = QMetaType::QSizePolicy;
+ } else if (typeId == Qt5RegExp) {
+ typeId = QMetaType::fromName("QRegExp").id();
+ }
+ }
qint8 is_null = false;
if (s.version() >= QDataStream::Qt_4_2)
s >> is_null;
- if (typeId == 27) {
- // used to be QRegExp in Qt 4/5
- typeId = QMetaType::type("QRegExp");
- } else if (typeId == QVariant::UserType) {
+ if (typeId == QMetaType::User) {
QByteArray name;
s >> name;
- typeId = QMetaType::type(name.constData());
+ typeId = QMetaType::fromName(name).id();
if (typeId == QMetaType::UnknownType) {
s.setStatus(QDataStream::ReadCorruptData);
qWarning("QVariant::load: unknown user type with name %s.", name.constData());
@@ -2472,7 +1272,7 @@ void QVariant::load(QDataStream &s)
if (!isValid()) {
if (s.version() < QDataStream::Qt_5_0) {
- // Since we wrote something, we should read something
+ // Since we wrote something, we should read something
QString x;
s >> x;
}
@@ -2481,7 +1281,8 @@ void QVariant::load(QDataStream &s)
}
// const cast is safe since we operate on a newly constructed variant
- if (!QMetaType::load(s, d.type().id(), const_cast<void *>(constData()))) {
+ void *data = const_cast<void *>(constData());
+ if (!d.type().load(s, data)) {
s.setStatus(QDataStream::ReadCorruptData);
qWarning("QVariant::load: unable to load type %d.", d.type().id());
}
@@ -2501,6 +1302,27 @@ void QVariant::save(QDataStream &s) const
typeId = QMetaType::User;
saveAsUserType = true;
}
+ if (s.version() < QDataStream::Qt_6_0) {
+ // map to Qt 5 values
+ if (typeId == QMetaType::User) {
+ typeId = Qt5UserType;
+ if (!strcmp(d.type().name(), "QRegExp")) {
+ typeId = 27; // QRegExp in Qt 4/5
+ }
+ } else if (typeId > Qt5LastCoreType && typeId <= QMetaType::LastCoreType) {
+ // the type didn't exist in Qt 5
+ typeId = Qt5UserType;
+ saveAsUserType = true;
+ } else if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType) {
+ typeId -= Qt6ToQt5GuiTypeDelta;
+ if (typeId > Qt5LastGuiType) {
+ typeId = Qt5UserType;
+ saveAsUserType = true;
+ }
+ } else if (typeId == QMetaType::QSizePolicy) {
+ typeId = Qt5SizePolicy;
+ }
+ }
if (s.version() < QDataStream::Qt_4_0) {
int i;
for (i = 0; i <= MapFromThreeCount - 1; ++i) {
@@ -2514,23 +1336,19 @@ void QVariant::save(QDataStream &s) const
return;
}
} else if (s.version() < QDataStream::Qt_5_0) {
- if (typeId == QMetaType::User) {
+ if (typeId == Qt5UserType) {
typeId = 127; // QVariant::UserType had this value in Qt4
saveAsUserType = true;
- } else if (typeId >= 128 - 97 && typeId <= LastCoreType) {
+ } else if (typeId >= 128 - 97 && typeId <= Qt5LastCoreType) {
// In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
// by moving all ids down by 97.
typeId += 97;
- } else if (typeId == QMetaType::QSizePolicy) {
+ } else if (typeId == Qt5SizePolicy) {
typeId = 75;
-#if QT_CONFIG(shortcut)
- } else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) {
-#else
- } else if (typeId >= QMetaType::QPen && typeId <= QMetaType::QQuaternion) {
-#endif
+ } else if (typeId >= Qt5KeySequence && typeId <= Qt5QQuaternion) {
// and as a result these types received lower ids too
- typeId +=1;
- } else if (typeId == QMetaType::QPolygonF || typeId == QMetaType::QUuid) {
+ typeId += 1;
+ } else if (typeId > Qt5QQuaternion || typeId == QMetaType::QUuid) {
// These existed in Qt 4 only as a custom type
typeId = 127;
saveAsUserType = true;
@@ -2538,17 +1356,16 @@ void QVariant::save(QDataStream &s) const
}
const char *typeName = nullptr;
if (saveAsUserType) {
- typeName = QMetaType::typeName(d.type().id());
- if (!strcmp(typeName, "QRegExp")) {
- typeId = 27; // QRegExp in Qt 4/5
- typeName = nullptr;
- }
+ if (s.version() < QDataStream::Qt_6_0)
+ typeName = QtMetaTypePrivate::typedefNameForType(d.type().d_ptr);
+ if (!typeName)
+ typeName = d.type().name();
}
s << typeId;
if (s.version() >= QDataStream::Qt_4_2)
s << qint8(d.is_null);
if (typeName)
- s << QMetaType::typeName(userType());
+ s << typeName;
if (!isValid()) {
if (s.version() < QDataStream::Qt_5_0)
@@ -2556,21 +1373,33 @@ void QVariant::save(QDataStream &s) const
return;
}
- if (!QMetaType::save(s, d.type().id(), constData())) {
+ if (!d.type().save(s, constData())) {
qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n",
- QMetaType::typeName(d.type().id()), d.type().id());
+ d.type().name(), d.type().id());
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
}
}
/*!
\since 4.4
+ \relates QVariant
Reads a variant \a p from the stream \a s.
+ \note If the stream contains types that aren't the built-in ones (see \l
+ QMetaType::Type), those types must be registered using qRegisterMetaType()
+ or QMetaType::registerType() before the variant can be properly loaded. If
+ an unregistered type is found, QVariant will set the corrupt flag in the
+ stream, stop processing and print a warning. For example, for QList<int>
+ it would print the following:
+
+ \quotation
+ QVariant::load: unknown user type with name QList<int>
+ \endquotation
+
\sa{Serializing Qt Data Types}{Format of the QDataStream operators}
*/
-QDataStream& operator>>(QDataStream &s, QVariant &p)
+QDataStream &operator>>(QDataStream &s, QVariant &p)
{
p.load(s);
return s;
@@ -2578,37 +1407,29 @@ QDataStream& operator>>(QDataStream &s, QVariant &p)
/*!
Writes a variant \a p to the stream \a s.
+ \relates QVariant
\sa{Serializing Qt Data Types}{Format of the QDataStream operators}
*/
-QDataStream& operator<<(QDataStream &s, const QVariant &p)
+QDataStream &operator<<(QDataStream &s, const QVariant &p)
{
p.save(s);
return s;
}
-/*!
+/*! \fn QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
+ \relates QVariant
+ \deprecated [6.0] Stream QMetaType::Type instead.
+
Reads a variant type \a p in enum representation from the stream \a s.
*/
-QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
-{
- quint32 u;
- s >> u;
- p = (QVariant::Type)u;
- return s;
-}
+/*! \fn QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
+ \relates QVariant
+ \deprecated [6.0] Stream QMetaType::Type instead.
-/*!
Writes a variant type \a p to the stream \a s.
*/
-QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
-{
- s << static_cast<quint32>(p);
-
- return s;
-}
-
#endif //QT_NO_DATASTREAM
/*!
@@ -2618,24 +1439,6 @@ QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
QMetaType::UnknownType; otherwise returns \c false.
*/
-template<typename T>
-inline T qVariantToHelper(const QVariant::Private &d)
-{
- QMetaType targetType = QMetaType::fromType<T>();
- if (d.type() == targetType)
- return *v_cast<T>(&d);
-
- T ret;
- if (d.type().id() >= QMetaType::User || targetType.id() >= QMetaType::User) {
- const void * const from = constData(d);
- if (QMetaType::convert(from, d.type().id(), &ret, targetType.id()))
- return ret;
- }
-
- handlerManager[d.type().id()]->convert(&d, targetType.id(), &ret, nullptr);
- return ret;
-}
-
/*!
\fn QStringList QVariant::toStringList() const
@@ -2644,11 +1447,11 @@ inline T qVariantToHelper(const QVariant::Private &d)
\l QMetaType::QVariantList of a type that can be converted to QString;
otherwise returns an empty list.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QStringList QVariant::toStringList() const
{
- return qVariantToHelper<QStringList>(d);
+ return qvariant_cast<QStringList>(*this);
}
/*!
@@ -2664,33 +1467,38 @@ QStringList QVariant::toStringList() const
Calling QVariant::toString() on an unsupported variant returns an empty
string.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QString QVariant::toString() const
{
- return qVariantToHelper<QString>(d);
+ return qvariant_cast<QString>(*this);
}
/*!
- Returns the variant as a QMap<QString, QVariant> if the variant
- has type() \l QMetaType::QVariantMap; otherwise returns an empty map.
+ Returns the variant as a QVariantMap if the variant has type() \l
+ QMetaType::QVariantMap. If it doesn't, QVariant will attempt to
+ convert the type to a map and then return it. This will succeed for
+ any type that has registered a converter to QVariantMap or which was
+ declared as a associative container using
+ \l{Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE}. If none of those
+ conditions are true, this function will return an empty map.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QVariantMap QVariant::toMap() const
{
- return qVariantToHelper<QVariantMap>(d);
+ return qvariant_cast<QVariantMap>(*this);
}
/*!
Returns the variant as a QHash<QString, QVariant> if the variant
has type() \l QMetaType::QVariantHash; otherwise returns an empty map.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QVariantHash QVariant::toHash() const
{
- return qVariantToHelper<QVariantHash>(d);
+ return qvariant_cast<QVariantHash>(*this);
}
/*!
@@ -2703,11 +1511,11 @@ QVariantHash QVariant::toHash() const
If the type() is \l QMetaType::QString, an invalid date will be returned if
the string cannot be parsed as a Qt::ISODate format date.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QDate QVariant::toDate() const
{
- return qVariantToHelper<QDate>(d);
+ return qvariant_cast<QDate>(*this);
}
/*!
@@ -2720,11 +1528,11 @@ QDate QVariant::toDate() const
If the type() is \l QMetaType::QString, an invalid time will be returned if
the string cannot be parsed as a Qt::ISODate format time.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QTime QVariant::toTime() const
{
- return qVariantToHelper<QTime>(d);
+ return qvariant_cast<QTime>(*this);
}
/*!
@@ -2737,11 +1545,11 @@ QTime QVariant::toTime() const
If the type() is \l QMetaType::QString, an invalid date/time will be
returned if the string cannot be parsed as a Qt::ISODate format date/time.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QDateTime QVariant::toDateTime() const
{
- return qVariantToHelper<QDateTime>(d);
+ return qvariant_cast<QDateTime>(*this);
}
/*!
@@ -2751,12 +1559,12 @@ QDateTime QVariant::toDateTime() const
Returns the variant as a QEasingCurve if the variant has userType()
\l QMetaType::QEasingCurve; otherwise returns a default easing curve.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
#if QT_CONFIG(easingcurve)
QEasingCurve QVariant::toEasingCurve() const
{
- return qVariantToHelper<QEasingCurve>(d);
+ return qvariant_cast<QEasingCurve>(*this);
}
#endif
@@ -2767,11 +1575,11 @@ QEasingCurve QVariant::toEasingCurve() const
\l QMetaType::QByteArray or \l QMetaType::QString (converted using
QString::fromUtf8()); otherwise returns an empty byte array.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QByteArray QVariant::toByteArray() const
{
- return qVariantToHelper<QByteArray>(d);
+ return qvariant_cast<QByteArray>(*this);
}
#ifndef QT_NO_GEOM_VARIANT
@@ -2782,11 +1590,11 @@ QByteArray QVariant::toByteArray() const
\l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
QPoint.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QPoint QVariant::toPoint() const
{
- return qVariantToHelper<QPoint>(d);
+ return qvariant_cast<QPoint>(*this);
}
/*!
@@ -2795,11 +1603,11 @@ QPoint QVariant::toPoint() const
Returns the variant as a QRect if the variant has userType()
\l QMetaType::QRect; otherwise returns an invalid QRect.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QRect QVariant::toRect() const
{
- return qVariantToHelper<QRect>(d);
+ return qvariant_cast<QRect>(*this);
}
/*!
@@ -2808,11 +1616,11 @@ QRect QVariant::toRect() const
Returns the variant as a QSize if the variant has userType()
\l QMetaType::QSize; otherwise returns an invalid QSize.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QSize QVariant::toSize() const
{
- return qVariantToHelper<QSize>(d);
+ return qvariant_cast<QSize>(*this);
}
/*!
@@ -2821,11 +1629,11 @@ QSize QVariant::toSize() const
Returns the variant as a QSizeF if the variant has userType() \l
QMetaType::QSizeF; otherwise returns an invalid QSizeF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QSizeF QVariant::toSizeF() const
{
- return qVariantToHelper<QSizeF>(d);
+ return qvariant_cast<QSizeF>(*this);
}
/*!
@@ -2835,11 +1643,11 @@ QSizeF QVariant::toSizeF() const
\l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid
QRectF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QRectF QVariant::toRectF() const
{
- return qVariantToHelper<QRectF>(d);
+ return qvariant_cast<QRectF>(*this);
}
/*!
@@ -2848,11 +1656,11 @@ QRectF QVariant::toRectF() const
Returns the variant as a QLineF if the variant has userType()
\l QMetaType::QLineF; otherwise returns an invalid QLineF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QLineF QVariant::toLineF() const
{
- return qVariantToHelper<QLineF>(d);
+ return qvariant_cast<QLineF>(*this);
}
/*!
@@ -2861,11 +1669,11 @@ QLineF QVariant::toLineF() const
Returns the variant as a QLine if the variant has userType()
\l QMetaType::QLine; otherwise returns an invalid QLine.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QLine QVariant::toLine() const
{
- return qVariantToHelper<QLine>(d);
+ return qvariant_cast<QLine>(*this);
}
/*!
@@ -2875,11 +1683,11 @@ QLine QVariant::toLine() const
QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
QPointF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QPointF QVariant::toPointF() const
{
- return qVariantToHelper<QPointF>(d);
+ return qvariant_cast<QPointF>(*this);
}
#endif // QT_NO_GEOM_VARIANT
@@ -2891,11 +1699,11 @@ QPointF QVariant::toPointF() const
Returns the variant as a QUrl if the variant has userType()
\l QMetaType::QUrl; otherwise returns an invalid QUrl.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QUrl QVariant::toUrl() const
{
- return qVariantToHelper<QUrl>(d);
+ return qvariant_cast<QUrl>(*this);
}
#endif
@@ -2905,11 +1713,11 @@ QUrl QVariant::toUrl() const
Returns the variant as a QLocale if the variant has userType()
\l QMetaType::QLocale; otherwise returns an invalid QLocale.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QLocale QVariant::toLocale() const
{
- return qVariantToHelper<QLocale>(d);
+ return qvariant_cast<QLocale>(*this);
}
#if QT_CONFIG(regularexpression)
@@ -2920,11 +1728,11 @@ QLocale QVariant::toLocale() const
Returns the variant as a QRegularExpression if the variant has userType() \l
QRegularExpression; otherwise returns an empty QRegularExpression.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QRegularExpression QVariant::toRegularExpression() const
{
- return qVariantToHelper<QRegularExpression>(d);
+ return qvariant_cast<QRegularExpression>(*this);
}
#endif // QT_CONFIG(regularexpression)
@@ -2935,11 +1743,11 @@ QRegularExpression QVariant::toRegularExpression() const
Returns the variant as a QModelIndex if the variant has userType() \l
QModelIndex; otherwise returns a default constructed QModelIndex.
- \sa canConvert(int targetTypeId), convert(), toPersistentModelIndex()
+ \sa canConvert(), convert(), toPersistentModelIndex()
*/
QModelIndex QVariant::toModelIndex() const
{
- return qVariantToHelper<QModelIndex>(d);
+ return qvariant_cast<QModelIndex>(*this);
}
/*!
@@ -2948,11 +1756,11 @@ QModelIndex QVariant::toModelIndex() const
Returns the variant as a QPersistentModelIndex if the variant has userType() \l
QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex.
- \sa canConvert(int targetTypeId), convert(), toModelIndex()
+ \sa canConvert(), convert(), toModelIndex()
*/
QPersistentModelIndex QVariant::toPersistentModelIndex() const
{
- return qVariantToHelper<QPersistentModelIndex>(d);
+ return qvariant_cast<QPersistentModelIndex>(*this);
}
#endif // QT_CONFIG(itemmodel)
@@ -2963,11 +1771,11 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const
\l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
otherwise returns a default-constructed QUuid.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QUuid QVariant::toUuid() const
{
- return qVariantToHelper<QUuid>(d);
+ return qvariant_cast<QUuid>(*this);
}
#ifndef QT_BOOTSTRAPPED
@@ -2977,11 +1785,11 @@ QUuid QVariant::toUuid() const
Returns the variant as a QJsonValue if the variant has userType() \l
QJsonValue; otherwise returns a default constructed QJsonValue.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonValue QVariant::toJsonValue() const
{
- return qVariantToHelper<QJsonValue>(d);
+ return qvariant_cast<QJsonValue>(*this);
}
/*!
@@ -2990,11 +1798,11 @@ QJsonValue QVariant::toJsonValue() const
Returns the variant as a QJsonObject if the variant has userType() \l
QJsonObject; otherwise returns a default constructed QJsonObject.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonObject QVariant::toJsonObject() const
{
- return qVariantToHelper<QJsonObject>(d);
+ return qvariant_cast<QJsonObject>(*this);
}
/*!
@@ -3003,11 +1811,11 @@ QJsonObject QVariant::toJsonObject() const
Returns the variant as a QJsonArray if the variant has userType() \l
QJsonArray; otherwise returns a default constructed QJsonArray.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonArray QVariant::toJsonArray() const
{
- return qVariantToHelper<QJsonArray>(d);
+ return qvariant_cast<QJsonArray>(*this);
}
/*!
@@ -3016,11 +1824,11 @@ QJsonArray QVariant::toJsonArray() const
Returns the variant as a QJsonDocument if the variant has userType() \l
QJsonDocument; otherwise returns a default constructed QJsonDocument.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonDocument QVariant::toJsonDocument() const
{
- return qVariantToHelper<QJsonDocument>(d);
+ return qvariant_cast<QJsonDocument>(*this);
}
#endif // QT_BOOTSTRAPPED
@@ -3031,42 +1839,40 @@ QJsonDocument QVariant::toJsonDocument() const
\l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise
returns an invalid QChar.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QChar QVariant::toChar() const
{
- return qVariantToHelper<QChar>(d);
+ return qvariant_cast<QChar>(*this);
}
+#ifndef QT_BOOTSTRAPPED
/*!
Returns the variant as a QBitArray if the variant has userType()
\l QMetaType::QBitArray; otherwise returns an empty bit array.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QBitArray QVariant::toBitArray() const
{
- return qVariantToHelper<QBitArray>(d);
+ return qvariant_cast<QBitArray>(*this);
}
+#endif // QT_BOOTSTRAPPED
template <typename T>
-inline T qNumVariantToHelper(const QVariant::Private &d,
- const HandlersManager &handlerManager, bool *ok, const T& val)
+inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok)
{
- const uint t = qMetaTypeId<T>();
+ QMetaType t = QMetaType::fromType<T>();
if (ok)
*ok = true;
- if (d.type().id() == t)
- return val;
+ if (d.type() == t)
+ return d.get<T>();
T ret = 0;
- if ((d.type().id() >= QMetaType::User || t >= QMetaType::User)
- && QMetaType::convert(constData(d), d.type().id(), &ret, t))
- return ret;
-
- if (!handlerManager[d.type().id()]->convert(&d, t, &ret, ok) && ok)
- *ok = false;
+ bool success = QMetaType::convert(d.type(), d.storage(), t, &ret);
+ if (ok)
+ *ok = success;
return ret;
}
@@ -3085,11 +1891,11 @@ inline T qNumVariantToHelper(const QVariant::Private &d,
will not be reflected in \a ok. A simple workaround is to use
QString::toInt().
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
int QVariant::toInt(bool *ok) const
{
- return qNumVariantToHelper<int>(d, handlerManager, ok, d.data.i);
+ return qNumVariantToHelper<int>(d, ok);
}
/*!
@@ -3107,11 +1913,11 @@ int QVariant::toInt(bool *ok) const
overflow will not be reflected in \a ok. A simple workaround is to use
QString::toUInt().
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
uint QVariant::toUInt(bool *ok) const
{
- return qNumVariantToHelper<uint>(d, handlerManager, ok, d.data.u);
+ return qNumVariantToHelper<uint>(d, ok);
}
/*!
@@ -3124,11 +1930,11 @@ uint QVariant::toUInt(bool *ok) const
If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
converted to an int; otherwise \c{*}\c{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
qlonglong QVariant::toLongLong(bool *ok) const
{
- return qNumVariantToHelper<qlonglong>(d, handlerManager, ok, d.data.ll);
+ return qNumVariantToHelper<qlonglong>(d, ok);
}
/*!
@@ -3141,11 +1947,11 @@ qlonglong QVariant::toLongLong(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to an int; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
qulonglong QVariant::toULongLong(bool *ok) const
{
- return qNumVariantToHelper<qulonglong>(d, handlerManager, ok, d.data.ull);
+ return qNumVariantToHelper<qulonglong>(d, ok);
}
/*!
@@ -3158,16 +1964,16 @@ qulonglong QVariant::toULongLong(bool *ok) const
\l QMetaType::QByteArray and its lower-case content is not one of the
following: empty, "0" or "false"; otherwise returns \c false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
bool QVariant::toBool() const
{
- if (d.type() == QMetaType::fromType<bool>())
- return d.data.b;
+ auto boolType = QMetaType::fromType<bool>();
+ if (d.type() == boolType)
+ return d.get<bool>();
bool res = false;
- handlerManager[d.type().id()]->convert(&d, Bool, &res, nullptr);
-
+ QMetaType::convert(d.type(), constData(), boolType, &res);
return res;
}
@@ -3181,11 +1987,11 @@ bool QVariant::toBool() const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
double QVariant::toDouble(bool *ok) const
{
- return qNumVariantToHelper<double>(d, handlerManager, ok, d.data.d);
+ return qNumVariantToHelper<double>(d, ok);
}
/*!
@@ -3200,11 +2006,11 @@ double QVariant::toDouble(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
float QVariant::toFloat(bool *ok) const
{
- return qNumVariantToHelper<float>(d, handlerManager, ok, d.data.f);
+ return qNumVariantToHelper<float>(d, ok);
}
/*!
@@ -3219,451 +2025,74 @@ float QVariant::toFloat(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
qreal QVariant::toReal(bool *ok) const
{
- return qNumVariantToHelper<qreal>(d, handlerManager, ok, d.data.real);
+ return qNumVariantToHelper<qreal>(d, ok);
}
/*!
- Returns the variant as a QVariantList if the variant has userType()
- \l QMetaType::QVariantList or \l QMetaType::QStringList; otherwise returns
- an empty list.
+ Returns the variant as a QVariantList if the variant has userType() \l
+ QMetaType::QVariantList. If it doesn't, QVariant will attempt to convert
+ the type to a list and then return it. This will succeed for any type that
+ has registered a converter to QVariantList or which was declared as a
+ sequential container using \l{Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE}. If
+ none of those conditions are true, this function will return an empty
+ list.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QVariantList QVariant::toList() const
{
- return qVariantToHelper<QVariantList>(d);
+ return qvariant_cast<QVariantList>(*this);
}
+/*!
+ \fn bool QVariant::canConvert(int targetTypeId) const
+ \overload
+ \deprecated [6.0] Use \c canConvert(QMetaType(targetTypeId)) instead.
-static const quint32 qCanConvertMatrix[QMetaType::LastCoreType + 1] =
-{
-/*Invalid*/ 0,
-
-/*Bool*/ 1 << QMetaType::Double | 1 << QMetaType::Int | 1 << QMetaType::UInt
- | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QByteArray
- | 1 << QMetaType::QString | 1 << QMetaType::QChar,
-
-/*Int*/ 1 << QMetaType::UInt | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray | 1 << QMetaType::Int,
-
-/*UInt*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*LLong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*ULlong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*double*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::ULongLong
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::QByteArray,
-
-/*QChar*/ 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::ULongLong,
-
-/*QMap*/ 0,
-
-/*QList*/ 1 << QMetaType::QStringList,
-
-/*QString*/ 1 << QMetaType::QStringList | 1 << QMetaType::QByteArray | 1 << QMetaType::Int
- | 1 << QMetaType::UInt | 1 << QMetaType::Bool | 1 << QMetaType::Double
- | 1 << QMetaType::QDate | 1 << QMetaType::QTime | 1 << QMetaType::QDateTime
- | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QChar
- | 1 << QMetaType::QUrl | 1 << QMetaType::QUuid,
-
-/*QStringList*/ 1 << QMetaType::QVariantList | 1 << QMetaType::QString,
-
-/*QByteArray*/ 1 << QMetaType::QString | 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::Bool
- | 1 << QMetaType::Double | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QUuid,
-
-/*QBitArray*/ 0,
-
-/*QDate*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
-
-/*QTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
-
-/*QDateTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDate,
-
-/*QUrl*/ 1 << QMetaType::QString,
-
-/*QLocale*/ 0,
-
-/*QRect*/ 1 << QMetaType::QRectF,
-
-/*QRectF*/ 1 << QMetaType::QRect,
-
-/*QSize*/ 1 << QMetaType::QSizeF,
-
-/*QSizeF*/ 1 << QMetaType::QSize,
-
-/*QLine*/ 1 << QMetaType::QLineF,
-
-/*QLineF*/ 1 << QMetaType::QLine,
-
-/*QPoint*/ 1 << QMetaType::QPointF,
-
-/*QPointF*/ 1 << QMetaType::QPoint,
-
-/*unused, was: QRegExp*/ 0,
-
-/*QHash*/ 0,
-
-/*QEasingCurve*/ 0,
-
-/*QUuid*/ 1 << QMetaType::QString | 1 << QMetaType::QByteArray,
-};
-static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix);
-
-#ifndef QT_BOOTSTRAPPED
-/*
- Returns \c true if from inherits to.
+ \sa QMetaType::canConvert()
*/
-static bool canConvertMetaObject(const QMetaObject *from, const QMetaObject *to)
-{
- if (from && to == &QObject::staticMetaObject)
- return true;
-
- while (from) {
- if (from == to)
- return true;
- from = from->superClass();
- }
-
- return false;
-}
-#endif
-
-static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
-{
-#ifndef QT_BOOTSTRAPPED
- QMetaType toType(toId);
- if ((QMetaType::typeFlags(fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
- if (!fromObject)
- return true;
- return canConvertMetaObject(fromObject->metaObject(), toType.metaObject());
- }
-#else
- Q_UNUSED(fromId);
- Q_UNUSED(toId);
- Q_UNUSED(fromObject);
-#endif
- return false;
-}
-
/*!
+ \fn bool QVariant::canConvert(QMetaType type) const
+ \since 6.0
+
Returns \c true if the variant's type can be cast to the requested
- type, \a targetTypeId. Such casting is done automatically when calling the
+ type, \a type. Such casting is done automatically when calling the
toInt(), toBool(), ... methods.
- The following casts are done automatically:
-
- \table
- \header \li Type \li Automatically Cast To
- \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong
- \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
- \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
- \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
- \row \li \l QMetaType::QColor \li \l QMetaType::QString
- \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
- \l QMetaType::QString
- \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
- \l QMetaType::QString, \l QMetaType::QTime
- \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
- \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
- \l QMetaType::ULongLong
- \row \li \l QMetaType::QFont \li \l QMetaType::QString
- \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
- \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong
- \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
- \l QMetaType::QString
- \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
- list's items can be converted to QStrings)
- \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
- \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
- \l QMetaType::ULongLong
- \row \li \l QMetaType::QPoint \li QMetaType::QPointF
- \row \li \l QMetaType::QRect \li QMetaType::QRectF
- \row \li \l QMetaType::QString \li \l QMetaType::Bool,
- \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
- \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
- \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
- \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
- \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
- \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
- \l QMetaType::QString (if the list contains exactly one item)
- \row \li \l QMetaType::QTime \li \l QMetaType::QString
- \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
- \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
- \l QMetaType::QString, \l QMetaType::ULongLong
- \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
- \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
- \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
- \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
- \endtable
-
- A QVariant containing a pointer to a type derived from QObject will also return true for this
- function if a qobject_cast to the type described by \a targetTypeId would succeed. Note that
- this only works for QObject subclasses which use the Q_OBJECT macro.
-
- A QVariant containing a sequential container will also return true for this
- function if the \a targetTypeId is QVariantList. It is possible to iterate over
- the contents of the container without extracting it as a (copied) QVariantList:
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- This requires that the value_type of the container is itself a metatype.
-
- Similarly, a QVariant containing a sequential container will also return true for this
- function the \a targetTypeId is QVariantHash or QVariantMap. It is possible to iterate over
- the contents of the container without extracting it as a (copied) QVariantHash or QVariantMap:
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
- Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
+ \sa QMetaType::canConvert()
*/
-bool QVariant::canConvert(int targetTypeId) const
-{
- if (d.type().id() == targetTypeId)
- return true;
-
-#if QT_CONFIG(itemmodel)
- if ((targetTypeId == QMetaType::QModelIndex
- && d.type().id() == QMetaType::QPersistentModelIndex)
- || (targetTypeId == QMetaType::QPersistentModelIndex
- && d.type().id() == QMetaType::QModelIndex))
- return true;
-#endif
- if (targetTypeId == QMetaType::QVariantList
- && (d.type().id() == QMetaType::QVariantList || d.type().id() == QMetaType::QStringList
- || d.type().id() == QMetaType::QByteArrayList
- || QMetaType::hasRegisteredConverterFunction(
- d.type().id(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) {
- return true;
- }
- if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap)
- && (d.type().id() == QMetaType::QVariantMap || d.type().id() == QMetaType::QVariantHash
- || QMetaType::hasRegisteredConverterFunction(
- d.type().id(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) {
- return true;
- }
-
- if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant>>()
- && QMetaType::hasRegisteredConverterFunction(
- d.type().id(), qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
- return true;
- }
+/*!
+ \fn bool QVariant::convert(int targetTypeId)
+ \deprecated [6.0] Use \c convert(QMetaType(targetTypeId)) instead.
- if ((d.type().id() >= QMetaType::User || targetTypeId >= QMetaType::User)
- && QMetaType::hasRegisteredConverterFunction(d.type().id(), targetTypeId)) {
- return true;
- }
+ Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
+ done, the variant is still changed to the requested type, but is left in a cleared
+ null state similar to that constructed by QVariant(Type).
- // TODO Reimplement this function, currently it works but it is a historical mess.
- uint currentType = d.type().id();
- if (currentType == QMetaType::SChar || currentType == QMetaType::Char)
- currentType = QMetaType::UInt;
- if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char)
- targetTypeId = QMetaType::UInt;
- if (currentType == QMetaType::Short || currentType == QMetaType::UShort)
- currentType = QMetaType::Int;
- if (targetTypeId == QMetaType::Short || currentType == QMetaType::UShort)
- targetTypeId = QMetaType::Int;
- if (currentType == QMetaType::Float)
- currentType = QMetaType::Double;
- if (targetTypeId == QMetaType::Float)
- targetTypeId = QMetaType::Double;
-
- if (currentType == uint(targetTypeId))
- return true;
+ Returns \c true if the current type of the variant was successfully cast;
+ otherwise returns \c false.
- if (targetTypeId < 0)
- return false;
- if (targetTypeId >= QMetaType::User) {
- if (QMetaType::typeFlags(targetTypeId) & QMetaType::IsEnumeration) {
- targetTypeId = QMetaType::Int;
- } else {
- return canConvertMetaObject(currentType, targetTypeId, d.data.o);
- }
- }
+ A QVariant containing a pointer to a type derived from QObject will also convert
+ and return true for this function if a qobject_cast to the type described
+ by \a targetTypeId would succeed. Note that this only works for QObject subclasses
+ which use the Q_OBJECT macro.
- if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) {
- switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) {
- case QMetaType::Nullptr:
- case QMetaType::QString:
- case QMetaType::Bool:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::QVariantList:
- case QMetaType::QVariantMap:
- case QMetaType::QVariantHash:
- case QMetaType::QCborValue:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- return true;
- default:
- return false;
- }
- }
- if (currentType == QMetaType::QJsonArray)
- return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
- || targetTypeId == QMetaType::QCborArray;
- if (currentType == QMetaType::QJsonObject)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
- || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap;
-
- if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) {
- switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) {
- case QMetaType::UnknownType:
- case QMetaType::Nullptr:
- case QMetaType::Bool:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::QString:
- case QMetaType::QByteArray:
- case QMetaType::QDateTime:
- case QMetaType::QUrl:
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
-#endif
- case QMetaType::QUuid:
- case QMetaType::QVariantList:
- case QMetaType::QVariantMap:
- case QMetaType::QVariantHash:
- case QMetaType::QJsonValue:
- case QMetaType::QJsonArray:
- case QMetaType::QJsonObject:
- case QMetaType::QJsonDocument:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- case QMetaType::QCborSimpleType:
- return true;
- default:
- return false;
- }
- }
- if (currentType == QMetaType::QCborArray)
- return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
- || targetTypeId == QMetaType::QJsonArray;
- if (currentType == QMetaType::QCborMap)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
- || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject;
-
- // FIXME It should be LastCoreType intead of Uuid
- if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
- switch (uint(targetTypeId)) {
- case QVariant::Int:
-#if QT_CONFIG(shortcut)
- if (currentType == QVariant::KeySequence)
- return true;
- Q_FALLTHROUGH();
-#endif
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- return currentType == QMetaType::ULong
- || currentType == QMetaType::Long
- || currentType == QMetaType::UShort
- || currentType == QMetaType::UChar
- || currentType == QMetaType::Char
- || currentType == QMetaType::SChar
- || currentType == QMetaType::Short
- || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
- case QVariant::Image:
- return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
- case QVariant::Pixmap:
- return currentType == QVariant::Image || currentType == QVariant::Bitmap
- || currentType == QVariant::Brush;
- case QVariant::Bitmap:
- return currentType == QVariant::Pixmap || currentType == QVariant::Image;
- case QVariant::ByteArray:
- return currentType == QVariant::Color || currentType == QMetaType::Nullptr
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
- case QVariant::String:
- return currentType == QVariant::Font
- || currentType == QVariant::Color || currentType == QMetaType::Nullptr
-#if QT_CONFIG(shortcut)
- || currentType == QVariant::KeySequence
-#endif
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
-#if QT_CONFIG(shortcut)
- case QVariant::KeySequence:
- return currentType == QVariant::String || currentType == QVariant::Int;
-#endif
- case QVariant::Font:
- return currentType == QVariant::String;
- case QVariant::Color:
- return currentType == QVariant::String || currentType == QVariant::ByteArray
- || currentType == QVariant::Brush;
- case QVariant::Brush:
- return currentType == QVariant::Color || currentType == QVariant::Pixmap;
- case QMetaType::Long:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- case QMetaType::ULong:
- case QMetaType::Short:
- case QMetaType::UShort:
- return currentType == QVariant::Int
- || (currentType < qCanConvertMatrixMaximumTargetType
- && qCanConvertMatrix[QVariant::Int] & (1U << currentType))
- || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
- case QMetaType::QObjectStar:
- return canConvertMetaObject(currentType, targetTypeId, d.data.o);
- default:
- return false;
- }
- }
+ \note converting QVariants that are null due to not being initialized or having
+ failed a previous conversion will always fail, changing the type, remaining null,
+ and returning \c false.
- if (targetTypeId == String && currentType == StringList)
- return v_cast<QStringList>(&d)->count() == 1;
- return currentType < qCanConvertMatrixMaximumTargetType
- && qCanConvertMatrix[targetTypeId] & (1U << currentType);
-}
+ \sa canConvert(), clear()
+*/
/*!
- Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
+ Casts the variant to the requested type, \a targetType. If the cast cannot be
done, the variant is still changed to the requested type, but is left in a cleared
null state similar to that constructed by QVariant(Type).
@@ -3672,122 +2101,115 @@ bool QVariant::canConvert(int targetTypeId) const
A QVariant containing a pointer to a type derived from QObject will also convert
and return true for this function if a qobject_cast to the type described
- by \a targetTypeId would succeed. Note that this only works for QObject subclasses
+ by \a targetType would succeed. Note that this only works for QObject subclasses
which use the Q_OBJECT macro.
\note converting QVariants that are null due to not being initialized or having
failed a previous conversion will always fail, changing the type, remaining null,
and returning \c false.
- \sa canConvert(int targetTypeId), clear()
+ \since 6.0
+
+ \sa canConvert(), clear()
*/
-bool QVariant::convert(int targetTypeId)
+bool QVariant::convert(QMetaType targetType)
{
- if (d.type().id() == targetTypeId)
- return true;
+ if (d.type() == targetType)
+ return targetType.isValid();
QVariant oldValue = *this;
clear();
- if (!oldValue.canConvert(targetTypeId))
+ create(targetType, nullptr);
+ if (!oldValue.canConvert(targetType))
return false;
- create(targetTypeId, nullptr);
// Fail if the value is not initialized or was forced null by a previous failed convert.
if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr)
return false;
- if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
- create(targetTypeId, &oldValue.d.data.o);
- return true;
- }
-
- bool isOk = true;
- int converterType = std::max(oldValue.userType(), targetTypeId);
- if (!handlerManager[converterType]->convert(&oldValue.d, targetTypeId, data(), &isOk))
- isOk = false;
- d.is_null = !isOk;
- return isOk;
+ bool ok = QMetaType::convert(oldValue.d.type(), oldValue.constData(), targetType, data());
+ d.is_null = !ok;
+ return ok;
}
/*!
- \fn bool QVariant::convert(const int type, void *ptr) const
+ \fn bool QVariant::convert(int type, void *ptr) const
\internal
Created for qvariant_cast() usage
*/
-bool QVariant::convert(const int type, void *ptr) const
+bool QVariant::convert(int type, void *ptr) const
{
- return handlerManager[type]->convert(&d, type, ptr, nullptr);
+ return QMetaType::convert(d.type(), constData(), QMetaType(type), ptr);
}
+/*!
+ \internal
+*/
+bool QVariant::view(int type, void *ptr)
+{
+ return QMetaType::view(d.type(), data(), QMetaType(type), ptr);
+}
/*!
- \fn bool operator==(const QVariant &v1, const QVariant &v2)
+ \fn bool QVariant::operator==(const QVariant &lhs, const QVariant &rhs)
- \relates QVariant
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
- Returns \c true if \a v1 and \a v2 are equal; otherwise returns \c false.
+ QVariant uses the equality operator of the type() contained to check for
+ equality.
- If \a v1 and \a v2 have the same \l{QVariant::}{type()}, the
- type's equality operator is used for comparison. If not, it is
- attempted to \l{QVariant::}{convert()} \a v2 to the same type as
- \a v1. See \l{QVariant::}{canConvert()} for a list of possible
- conversions.
+ Variants of different types will always compare as not equal with a few
+ exceptions:
+
+ \list
+ \li If both types are numeric types (integers and floatins point numbers)
+ Qt will compare those types using standard C++ type promotion rules.
+ \li If one type is numeric and the other one a QString, Qt will try to
+ convert the QString to a matching numeric type and if successful compare
+ those.
+ \li If both variants contain pointers to QObject derived types, QVariant
+ will check whether the types are related and point to the same object.
+ \endlist
The result of the function is not affected by the result of QVariant::isNull,
which means that two values can be equal even if one of them is null and
another is not.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
*/
-/*!
- \fn bool operator!=(const QVariant &v1, const QVariant &v2)
-
- \relates QVariant
-
- Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-*/
-
-/*! \fn bool QVariant::operator==(const QVariant &v) const
- Compares this QVariant with \a v and returns \c true if they are
- equal; otherwise returns \c false.
-
- QVariant uses the equality operator of the type() it contains to
- check for equality. QVariant will try to convert() \a v if its
- type is not the same as this variant's type. See canConvert() for
- a list of possible conversions.
+/*!
+ \fn bool QVariant::operator!=(const QVariant &lhs, const QVariant &rhs)
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-*/
+ Returns \c false if \a lhs and \a rhs are equal; otherwise returns \c true.
-/*!
- \fn bool QVariant::operator!=(const QVariant &v) const
+ QVariant uses the equality operator of the type() contained to check for
+ equality.
- Compares this QVariant with \a v and returns \c true if they are not
- equal; otherwise returns \c false.
+ Variants of different types will always compare as not equal with a few
+ exceptions:
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
+ \list
+ \li If both types are numeric types (integers and floatins point numbers)
+ Qt will compare those types using standard C++ type promotion rules.
+ \li If one type is numeric and the other one a QString, Qt will try to
+ convert the QString to a matching numeric type and if successful compare
+ those.
+ \li If both variants contain pointers to QObject derived types, QVariant
+ will check whether the types are related and point to the same object.
+ \endlist
*/
static bool qIsNumericType(uint tp)
{
static const qulonglong numericTypeBits =
+ Q_UINT64_C(1) << QMetaType::QString |
Q_UINT64_C(1) << QMetaType::Bool |
Q_UINT64_C(1) << QMetaType::Double |
Q_UINT64_C(1) << QMetaType::Float |
Q_UINT64_C(1) << QMetaType::Char |
+ Q_UINT64_C(1) << QMetaType::Char16 |
+ Q_UINT64_C(1) << QMetaType::Char32 |
Q_UINT64_C(1) << QMetaType::SChar |
Q_UINT64_C(1) << QMetaType::UChar |
Q_UINT64_C(1) << QMetaType::Short |
@@ -3803,33 +2225,56 @@ static bool qIsNumericType(uint tp)
static bool qIsFloatingPoint(uint tp)
{
- return tp == QMetaType::Double || tp == QMetaType::Float;
+ return tp == QMetaType::Double || tp == QMetaType::Float || tp == QMetaType::Float16;
}
-static int normalizeLowerRanks(uint tp)
+static bool canBeNumericallyCompared(const QtPrivate::QMetaTypeInterface *iface1,
+ const QtPrivate::QMetaTypeInterface *iface2)
{
- static const qulonglong numericTypeBits =
- Q_UINT64_C(1) << QMetaType::Bool |
- Q_UINT64_C(1) << QMetaType::Char |
- Q_UINT64_C(1) << QMetaType::SChar |
- Q_UINT64_C(1) << QMetaType::UChar |
- Q_UINT64_C(1) << QMetaType::Short |
- Q_UINT64_C(1) << QMetaType::UShort;
- return numericTypeBits & (Q_UINT64_C(1) << tp) ? uint(QMetaType::Int) : tp;
-}
+ if (!iface1 || !iface2)
+ return false;
-static int normalizeLong(uint tp)
-{
- const uint IntType = sizeof(long) == sizeof(int) ? QMetaType::Int : QMetaType::LongLong;
- const uint UIntType = sizeof(ulong) == sizeof(uint) ? QMetaType::UInt : QMetaType::ULongLong;
- return tp == QMetaType::Long ? IntType :
- tp == QMetaType::ULong ? UIntType : tp;
+ // We don't need QMetaType::id() here because the type Id is always stored
+ // directly for all built-in types.
+ bool isNumeric1 = qIsNumericType(iface1->typeId);
+ bool isNumeric2 = qIsNumericType(iface2->typeId);
+
+ // if they're both numeric (or QString), then they can be compared
+ if (isNumeric1 && isNumeric2)
+ return true;
+
+ bool isEnum1 = iface1->flags & QMetaType::IsEnumeration;
+ bool isEnum2 = iface2->flags & QMetaType::IsEnumeration;
+
+ // if both are enums, we can only compare if they are the same enum
+ // (the language does allow comparing two different enum types, but that's
+ // usually considered poor coding and produces a warning)
+ if (isEnum1 && isEnum2)
+ return QMetaType(iface1) == QMetaType(iface2);
+
+ // if one is an enum and the other is a numeric, we can compare too
+ if (isEnum1 && isNumeric2)
+ return true;
+ if (isNumeric1 && isEnum2)
+ return true;
+
+ // we need at least one enum and one numeric...
+ return false;
}
-static int numericTypePromotion(uint t1, uint t2)
+static int numericTypePromotion(const QtPrivate::QMetaTypeInterface *iface1,
+ const QtPrivate::QMetaTypeInterface *iface2)
{
- Q_ASSERT(qIsNumericType(t1));
- Q_ASSERT(qIsNumericType(t2));
+ Q_ASSERT(canBeNumericallyCompared(iface1, iface2));
+
+ // We don't need QMetaType::id() here because the type Id is always stored
+ // directly for the types we're comparing against below.
+ uint t1 = iface1->typeId;
+ uint t2 = iface2->typeId;
+
+ if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
+ (t2 == QMetaType::Bool && t1 == QMetaType::QString))
+ return QMetaType::Bool;
// C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
// bool < signed char < short < int < long < long long
@@ -3849,175 +2294,260 @@ static int numericTypePromotion(uint t1, uint t2)
if (qIsFloatingPoint(t1) || qIsFloatingPoint(t2))
return QMetaType::QReal;
+ auto isUnsigned = [](uint tp) {
+ // only types for which sizeof(T) >= sizeof(int); lesser ones promote to int
+ return tp == QMetaType::ULongLong || tp == QMetaType::ULong ||
+ tp == QMetaType::UInt || tp == QMetaType::Char32;
+ };
+ bool isUnsigned1 = isUnsigned(t1);
+ bool isUnsigned2 = isUnsigned(t2);
+
// integral rules:
- // for all platforms we support, int can always hold the values of lower-ranked types
- t1 = normalizeLowerRanks(t1);
- t2 = normalizeLowerRanks(t2);
-
- // normalize long / ulong: in all platforms we run, they're either the same as int or as long long
- t1 = normalizeLong(t1);
- t2 = normalizeLong(t2);
-
- // implement the other rules
- // the four possibilities are Int, UInt, LongLong and ULongLong
- // if any of the two is ULongLong, then it wins (highest rank, unsigned)
- // otherwise, if one of the two is LongLong, then the other is either LongLong too or lower-ranked
- // otherwise, if one of the two is UInt, then the other is either UInt too or Int
- if (t1 == QMetaType::ULongLong || t2 == QMetaType::ULongLong)
+ // 1) if either type is a 64-bit unsigned, compare as 64-bit unsigned
+ if (isUnsigned1 && iface1->size > sizeof(int))
return QMetaType::ULongLong;
- if (t1 == QMetaType::LongLong || t2 == QMetaType::LongLong)
+ if (isUnsigned2 && iface2->size > sizeof(int))
+ return QMetaType::ULongLong;
+
+ // 2) if either type is 64-bit, compare as 64-bit signed
+ if (iface1->size > sizeof(int) || iface2->size > sizeof(int))
return QMetaType::LongLong;
- if (t1 == QMetaType::UInt || t2 == QMetaType::UInt)
+
+ // 3) if either type is 32-bit unsigned, compare as 32-bit unsigned
+ if (isUnsigned1 || isUnsigned2)
return QMetaType::UInt;
+
+ // 4) otherwise, just do int promotion
return QMetaType::Int;
}
-static int integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
+template <typename Numeric> static QPartialOrdering spaceShip(Numeric lhs, Numeric rhs)
{
- // use toLongLong to retrieve the data, it gets us all the bits
- bool ok;
- qlonglong l1 = qConvertToNumber(d1, &ok);
- Q_ASSERT(ok);
+ if (lhs == rhs)
+ return QPartialOrdering::Equivalent;
+ if constexpr (std::numeric_limits<Numeric>::has_quiet_NaN) {
+ if (std::isnan(lhs) || std::isnan(rhs))
+ return QPartialOrdering::Unordered;
+ }
- qlonglong l2 = qConvertToNumber(d2, &ok);
- Q_ASSERT(ok);
+ bool smaller;
+ if constexpr (std::is_same_v<Numeric, QObject *>)
+ smaller = std::less<QObject *>()(lhs, rhs); // can't use less all the time because of bool
+ else
+ smaller = lhs < rhs;
+ return smaller ? QPartialOrdering::Less : QPartialOrdering::Greater;
+}
- if (promotedType == QMetaType::Int)
- return int(l1) < int(l2) ? -1 : int(l1) == int(l2) ? 0 : 1;
+static QPartialOrdering integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
+{
+ // use toLongLong to retrieve the data, it gets us all the bits
+ std::optional<qlonglong> l1 = qConvertToNumber(d1, promotedType == QMetaType::Bool);
+ std::optional<qlonglong> l2 = qConvertToNumber(d2, promotedType == QMetaType::Bool);
+ if (!l1 || !l2)
+ return QPartialOrdering::Unordered;
if (promotedType == QMetaType::UInt)
- return uint(l1) < uint(l2) ? -1 : uint(l1) == uint(l2) ? 0 : 1;
+ return spaceShip<uint>(*l1, *l2);
if (promotedType == QMetaType::LongLong)
- return l1 < l2 ? -1 : l1 == l2 ? 0 : 1;
+ return spaceShip<qlonglong>(*l1, *l2);
if (promotedType == QMetaType::ULongLong)
- return qulonglong(l1) < qulonglong(l2) ? -1 : qulonglong(l1) == qulonglong(l2) ? 0 : 1;
+ return spaceShip<qulonglong>(*l1, *l2);
- Q_UNREACHABLE();
- return 0;
+ return spaceShip<int>(*l1, *l2);
}
-static int numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
+static QPartialOrdering numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
{
- uint promotedType = numericTypePromotion(d1->type().id(), d2->type().id());
+ uint promotedType = numericTypePromotion(d1->typeInterface(), d2->typeInterface());
if (promotedType != QMetaType::QReal)
return integralCompare(promotedType, d1, d2);
- // qreal comparisons
- bool ok;
- qreal r1 = qConvertToRealNumber(d1, &ok);
- Q_ASSERT(ok);
- qreal r2 = qConvertToRealNumber(d2, &ok);
- Q_ASSERT(ok);
- if (r1 == r2)
- return 0;
-
- // only do fuzzy comparisons for finite, non-zero numbers
- int c1 = qFpClassify(r1);
- int c2 = qFpClassify(r2);
- if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
- if (qFuzzyCompare(r1, r2))
- return 0;
+ // floating point comparison
+ const auto r1 = qConvertToRealNumber(d1);
+ const auto r2 = qConvertToRealNumber(d2);
+ if (!r1 || !r2)
+ return QPartialOrdering::Unordered;
+ if (*r1 == *r2)
+ return QPartialOrdering::Equivalent;
+
+ return spaceShip(*r1, *r2);
+}
+
+#ifndef QT_BOOTSTRAPPED
+static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
+{
+ if ((fromType.flags() & QMetaType::PointerToQObject)
+ && (toType.flags() & QMetaType::PointerToQObject)) {
+ const QMetaObject *f = fromType.metaObject();
+ const QMetaObject *t = toType.metaObject();
+ return f && t && (f->inherits(t) || t->inherits(f));
}
+ return false;
+}
- return r1 < r2 ? -1 : 1;
+static QPartialOrdering pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
+{
+ return spaceShip<QObject *>(d1->get<QObject *>(), d2->get<QObject *>());
}
+#endif
/*!
\internal
*/
-bool QVariant::cmp(const QVariant &v) const
+bool QVariant::equals(const QVariant &v) const
{
- auto cmp_helper = [](const QVariant::Private &d1, const QVariant::Private &d2) {
- Q_ASSERT(d1.type() == d2.type());
- if (d1.type().id() >= QMetaType::User) {
- int result;
- if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)),
- QT_PREPEND_NAMESPACE(constData(d2)), d1.type().id(), &result))
- return result == 0;
- }
- return handlerManager[d1.type().id()]->compare(&d1, &d2);
- };
+ auto metatype = d.type();
- // try numerics first, with C++ type promotion rules (no conversion)
- if (qIsNumericType(d.type().id()) && qIsNumericType(v.d.type().id()))
- return numericCompare(&d, &v.d) == 0;
+ if (metatype != v.metaType()) {
+ // try numeric comparisons, with C++ type promotion rules (no conversion)
+ if (canBeNumericallyCompared(metatype.iface(), v.d.type().iface()))
+ return numericCompare(&d, &v.d) == QPartialOrdering::Equivalent;
+#ifndef QT_BOOTSTRAPPED
+ // if both types are related pointers to QObjects, check if they point to the same object
+ if (qvCanConvertMetaObject(metatype, v.metaType()))
+ return pointerCompare(&d, &v.d) == QPartialOrdering::Equivalent;
+#endif
+ return false;
+ }
- if (d.type() == v.d.type())
- return cmp_helper(d, v.d);
+ // For historical reasons: QVariant() == QVariant()
+ if (!metatype.isValid())
+ return true;
- QVariant v1 = *this;
- QVariant v2 = v;
- if (v2.canConvert(v1.d.type().id())) {
- if (!v2.convert(v1.d.type().id()))
- return false;
- } else {
- // try the opposite conversion, it might work
- qSwap(v1, v2);
- if (!v2.convert(v1.d.type().id()))
- return false;
- }
- return cmp_helper(v1.d, v2.d);
+ return metatype.equals(d.storage(), v.d.storage());
}
/*!
- \internal
- */
+ Compares the objects at \a lhs and \a rhs for ordering.
-const void *QVariant::constData() const
+ Returns QPartialOrdering::Unordered if comparison is not supported
+ or the values are unordered. Otherwise, returns
+ QPartialOrdering::Less, QPartialOrdering::Equivalent or
+ QPartialOrdering::Greater if \a lhs is less than, equivalent
+ to or greater than \a rhs, respectively.
+
+ If the variants contain data with a different metatype, the values are considered
+ unordered unless they are both of numeric or pointer types, where regular numeric or
+ pointer comparison rules will be used.
+ \note: If a numeric comparison is done and at least one value is NaN, QPartialOrdering::Unordered
+ is returned.
+
+ If both variants contain data of the same metatype, the method will use the
+ QMetaType::compare method to determine the ordering of the two variants, which can
+ also indicate that it can't establish an ordering between the two values.
+
+ \since 6.0
+ \sa QMetaType::compare(), QMetaType::isOrdered()
+*/
+QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
{
- return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data);
+ QMetaType t = lhs.d.type();
+ if (t != rhs.d.type()) {
+ // try numeric comparisons, with C++ type promotion rules (no conversion)
+ if (canBeNumericallyCompared(lhs.d.type().iface(), rhs.d.type().iface()))
+ return numericCompare(&lhs.d, &rhs.d);
+#ifndef QT_BOOTSTRAPPED
+ if (qvCanConvertMetaObject(lhs.metaType(), rhs.metaType()))
+ return pointerCompare(&lhs.d, &rhs.d);
+#endif
+ return QPartialOrdering::Unordered;
+ }
+ return t.compare(lhs.constData(), rhs.constData());
}
/*!
+ \fn const void *QVariant::constData() const
\fn const void* QVariant::data() const
- \internal
-*/
+ Returns a pointer to the contained object as a generic void* that cannot be
+ written to.
+
+ \sa get_if(), QMetaType
+ */
/*!
- \internal
+ Returns a pointer to the contained object as a generic void* that can be
+ written to.
+
+ This function detaches the QVariant. When called on a \l{isNull}{null-QVariant},
+ the QVariant will not be null after the call.
+
+ \sa get_if(), QMetaType
*/
-void* QVariant::data()
+void *QVariant::data()
{
detach();
+ // set is_null to false, as the caller is likely to write some data into this variant
+ d.is_null = false;
return const_cast<void *>(constData());
}
+/*!
+ \since 6.6
+ \fn template <typename T> const T* QVariant::get_if(const QVariant *v)
+ \fn template <typename T> T* QVariant::get_if(QVariant *v)
+
+ If \a v contains an object of type \c T, returns a pointer to the contained
+ object, otherwise returns \nullptr.
+
+ The overload taking a mutable \a v detaches \a v: When called on a
+ \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
+ after the call.
+
+ These functions are provided for compatibility with \c{std::variant}.
+
+ \sa data()
+*/
/*!
- Returns \c true if this is a null variant, false otherwise. A variant is
- considered null if it contains no initialized value, or the contained value
- is \nullptr or is an instance of a built-in type that has an isNull
- method, in which case the result would be the same as calling isNull on the
- wrapped object.
+ \since 6.6
+ \fn template <typename T> T &QVariant::get(QVariant &v)
+ \fn template <typename T> const T &QVariant::get(const QVariant &v)
+ \fn template <typename T> T &&QVariant::get(QVariant &&v)
+ \fn template <typename T> const T &&QVariant::get(const QVariant &&v)
- \warning Null variants is not a single state and two null variants may easily
- return \c false on the == operator if they do not contain similar null values.
+ If \a v contains an object of type \c T, returns a reference to the contained
+ object, otherwise the call has undefined behavior.
- \sa convert(int)
+ The overloads taking a mutable \a v detach \a v: When called on a
+ \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
+ after the call.
+
+ These functions are provided for compatibility with \c{std::variant}.
+
+ \sa get_if(), data()
+*/
+
+/*!
+ Returns \c true if this is a null variant, false otherwise.
+
+ A variant is considered null if it contains no initialized value or a null pointer.
+
+ \note This behavior has been changed from Qt 5, where isNull() would also
+ return true if the variant contained an object of a builtin type with an isNull()
+ method that returned true for that object.
+
+ \sa convert()
*/
bool QVariant::isNull() const
{
- return handlerManager[d.type().id()]->isNull(&d);
+ if (d.is_null || !metaType().isValid())
+ return true;
+ if (metaType().flags() & QMetaType::IsPointer)
+ return d.get<void *>() == nullptr;
+ return false;
}
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QVariant &v)
+QDebug QVariant::qdebugHelper(QDebug dbg) const
{
QDebugStateSaver saver(dbg);
- const uint typeId = v.d.type().id();
+ const uint typeId = d.type().id();
dbg.nospace() << "QVariant(";
if (typeId != QMetaType::UnknownType) {
- dbg << QMetaType::typeName(typeId) << ", ";
- bool userStream = false;
- bool canConvertToString = false;
- if (typeId >= QMetaType::User) {
- userStream = QMetaType::debugStream(dbg, constData(v.d), typeId);
- canConvertToString = v.canConvert<QString>();
- }
- if (!userStream && canConvertToString)
- dbg << v.toString();
- else if (!userStream)
- handlerManager[typeId]->debugStream(dbg, v);
+ dbg << d.type().name() << ", ";
+ bool streamed = d.type().debugStream(dbg, d.storage());
+ if (!streamed && canConvert<QString>())
+ dbg << toString();
} else {
dbg << "Invalid";
}
@@ -4025,19 +2555,42 @@ QDebug operator<<(QDebug dbg, const QVariant &v)
return dbg;
}
+QVariant QVariant::moveConstruct(QMetaType type, void *data)
+{
+ QVariant var;
+ var.d = QVariant::Private(type.d_ptr);
+ customConstruct<ForceMove, NonNull>(type.d_ptr, &var.d, data);
+ return var;
+}
+
+QVariant QVariant::copyConstruct(QMetaType type, const void *data)
+{
+ QVariant var;
+ var.d = QVariant::Private(type.d_ptr);
+ customConstruct<UseCopy, NonNull>(type.d_ptr, &var.d, data);
+ return var;
+}
+
+#if QT_DEPRECATED_SINCE(6, 0)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+
QDebug operator<<(QDebug dbg, const QVariant::Type p)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "QVariant::"
<< (int(p) != int(QMetaType::UnknownType)
- ? QMetaType::typeName(p)
+ ? QMetaType(p).name()
: "Invalid");
return dbg;
}
+
+QT_WARNING_POP
#endif
+#endif
-/*! \fn template<typename T> void QVariant::setValue(const T &value)
+/*! \fn template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> void QVariant::setValue(T &&value)
Stores a copy of \a value. If \c{T} is a type that QVariant
doesn't support, QMetaType is used to store the value. A compile
@@ -4050,7 +2603,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa value(), fromValue(), canConvert()
*/
-/*! \fn template<typename T> T QVariant::value() const
+/*! \fn void QVariant::setValue(const QVariant &value)
+
+ Copies \a value over this QVariant. It is equivalent to simply
+ assigning \a value to this QVariant.
+*/
+
+/*! \fn void QVariant::setValue(QVariant &&value)
+
+ Moves \a value over this QVariant. It is equivalent to simply
+ move assigning \a value to this QVariant.
+*/
+
+/*! \fn template<typename T> T QVariant::value() const &
Returns the stored value converted to the template type \c{T}.
Call canConvert() to find out whether a type can be converted.
@@ -4078,7 +2643,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa setValue(), fromValue(), canConvert(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
*/
-/*! \fn bool QVariant::canConvert() const
+/*! \fn template<typename T> T QVariant::view()
+
+ Returns a mutable view of template type \c{T} on the stored value.
+ Call canView() to find out whether such a view is supported.
+ If no such view can be created, returns the stored value converted to the
+ template type \c{T}. Call canConvert() to find out whether a type can be
+ converted. If the value can neither be viewed nor converted, a
+ \l{default-constructed value} will be returned.
+
+ \sa canView(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
+*/
+
+/*! \fn template<typename T> bool QVariant::canConvert() const
Returns \c true if the variant can be converted to the template type \c{T},
otherwise false.
@@ -4094,6 +2671,14 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa convert()
*/
+/*! \fn template<typename T> bool QVariant::canView() const
+
+ Returns \c true if a mutable view of the template type \c{T} can be created on this variant,
+ otherwise \c false.
+
+ \sa value()
+*/
+
/*! \fn template<typename T> static QVariant QVariant::fromValue(const T &value)
Returns a QVariant containing a copy of \a value. Behaves
@@ -4103,12 +2688,15 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\snippet code/src_corelib_kernel_qvariant.cpp 7
- \note If you are working with custom types, you should use
- the Q_DECLARE_METATYPE() macro to register your custom type.
-
\sa setValue(), value()
*/
+/*! \fn template<typename T, QVariant::if_rvalue<T> = true> static QVariant QVariant::fromValue(T &&value)
+
+ \since 6.6
+ \overload
+*/
+
/*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
\since 5.11
@@ -4122,45 +2710,46 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa fromValue()
*/
-#if QT_DEPRECATED_SINCE(5, 14)
/*!
- \fn template<typename T> QVariant qVariantFromValue(const T &value)
- \relates QVariant
- \obsolete
-
- Returns a variant containing a copy of the given \a value
- with template type \c{T}.
-
- This function is equivalent to QVariant::fromValue(\a value).
-
- \note This function was provided as a workaround for MSVC 6
- which did not support member template functions. It is advised
- to use the other form in new code.
+ \fn template<typename... Types> QVariant QVariant::fromStdVariant(std::variant<Types...> &&value)
+ \since 6.6
+ \overload
+*/
- For example, a QObject pointer can be stored in a variant with the
- following code:
- \snippet code/src_corelib_kernel_qvariant.cpp 8
+/*!
+ \since 6.7
- \sa QVariant::fromValue()
-*/
+ Creates a variant of type \a type, and initializes it with
+ a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
+ must point to an object of type \a type).
-/*! \fn template<typename T> void qVariantSetValue(QVariant &variant, const T &value)
- \relates QVariant
- \obsolete
+ Note that you have to pass the address of the object you want stored.
- Sets the contents of the given \a variant to a copy of the
- \a value with the specified template type \c{T}.
+ Usually, you never have to use this constructor, use QVariant::fromValue()
+ instead to construct variants from the pointer types represented by
+ \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
- This function is equivalent to QVariant::setValue(\a value).
+ If \a type does not support copy construction and \a copy is not \nullptr,
+ the variant will be invalid. Similarly, if \a copy is \nullptr and
+ \a type does not support default construction, the variant will be
+ invalid.
- \note This function was provided as a workaround for MSVC 6
- which did not support member template functions. It is advised
- to use the other form in new code.
+ Returns the QVariant created as described above.
- \sa QVariant::setValue()
+ \sa QVariant::fromValue(), QMetaType::Type
*/
-#endif
+QVariant QVariant::fromMetaType(QMetaType type, const void *copy)
+{
+ QVariant result;
+ type.registerType();
+ const auto iface = type.iface();
+ if (isValidMetaTypeForVariant(iface, copy)) {
+ result.d = Private(iface);
+ customConstruct(iface, &result.d, copy);
+ }
+ return result;
+}
/*!
\fn template<typename T> T qvariant_cast(const QVariant &value)
@@ -4173,9 +2762,17 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa QVariant::value()
*/
+/*!
+ \fn template<typename T> T QVariant::qvariant_cast(QVariant &&value)
+ \overload
+ \since 6.7
+
+ Returns the given \a value converted to the template type \c{T}.
+*/
+
/*! \fn template<typename T> T qVariantValue(const QVariant &value)
\relates QVariant
- \obsolete
+ \deprecated
Returns the given \a value converted to the template type \c{T}.
@@ -4191,7 +2788,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
/*! \fn bool qVariantCanConvert(const QVariant &value)
\relates QVariant
- \obsolete
+ \deprecated
Returns \c true if the given \a value can be converted to the
template type specified; otherwise returns \c false.
@@ -4278,655 +2875,157 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
*/
/*!
- \class QSequentialIterable
- \since 5.2
- \inmodule QtCore
- \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
-
- This class allows several methods of accessing the elements of a container held within
- a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
- be converted to a QVariantList.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- The container itself is not copied before iterating over it.
-
- \sa QVariant
-*/
-
-/*!
\internal
-*/
-QSequentialIterable::QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl)
- : m_impl(impl)
-{
-}
-
-QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_)
- : m_impl(iter.m_impl), ref(ref_)
-{
- ref->ref();
-}
-
-QSequentialIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_)
- : m_impl(impl), ref(ref_)
-{
- ref->ref();
-}
-
-void QSequentialIterable::const_iterator::begin()
-{
- m_impl.moveToBegin();
-}
-
-void QSequentialIterable::const_iterator::end()
-{
- m_impl.moveToEnd();
-}
-
-/*! \fn QSequentialIterable::const_iterator QSequentialIterable::begin() const
-
- Returns a QSequentialIterable::const_iterator for the beginning of the container. This
- can be used in stl-style iteration.
-
- \sa end()
-*/
-QSequentialIterable::const_iterator QSequentialIterable::begin() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.begin();
- return it;
-}
-
-/*!
- Returns a QSequentialIterable::const_iterator for the end of the container. This
- can be used in stl-style iteration.
-
- \sa begin()
-*/
-QSequentialIterable::const_iterator QSequentialIterable::end() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.end();
- return it;
-}
-
-static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) {
- QVariant v;
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- v = *reinterpret_cast<const QVariant*>(d.data);
- else
- v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData);
- if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData)
- QMetaType::destroy(d.metaTypeId, const_cast<void *>(d.data));
- return v;
-}
-
-/*!
- Returns the element at position \a idx in the container.
-*/
-QVariant QSequentialIterable::at(int idx) const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns the number of elements in the container.
-*/
-int QSequentialIterable::size() const
+ */
+const void *QtPrivate::QVariantTypeCoercer::convert(const QVariant &value, const QMetaType &type)
{
- return m_impl.size();
-}
+ if (type == QMetaType::fromType<QVariant>())
+ return &value;
-/*!
- Returns whether it is possible to iterate over the container in reverse. This
- corresponds to the std::bidirectional_iterator_tag iterator trait of the
- const_iterator of the container.
-*/
-bool QSequentialIterable::canReverseIterate() const
-{
- return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability;
-}
+ if (type == value.metaType())
+ return value.constData();
-/*!
- \class QSequentialIterable::const_iterator
- \since 5.2
- \inmodule QtCore
- \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
-
- A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
- and can be used in a way similar to other stl-style iterators.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- \sa QSequentialIterable
-*/
-
-
-/*!
- Destroys the QSequentialIterable::const_iterator.
-*/
-QSequentialIterable::const_iterator::~const_iterator() {
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
+ if (value.canConvert(type)) {
+ converted = value;
+ if (converted.convert(type))
+ return converted.constData();
}
-}
-/*!
- Creates a copy of \a other.
-*/
-QSequentialIterable::const_iterator::const_iterator(const const_iterator &other)
- : m_impl(other.m_impl), ref(other.ref)
-{
- ref->ref();
+ return nullptr;
}
/*!
- Assigns \a other to this.
-*/
-QSequentialIterable::const_iterator&
-QSequentialIterable::const_iterator::operator=(const const_iterator &other)
-{
- other.ref->ref();
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
- m_impl = other.m_impl;
- ref = other.ref;
- return *this;
-}
-
-/*!
- Returns the current item, converted to a QVariant.
-*/
-const QVariant QSequentialIterable::const_iterator::operator*() const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-bool QSequentialIterable::const_iterator::operator==(const const_iterator &other) const
-{
- return m_impl.equal(other.m_impl);
-}
-
-/*!
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other) const
+ \internal
+ */
+const void *QtPrivate::QVariantTypeCoercer::coerce(const QVariant &value, const QMetaType &type)
{
- return !m_impl.equal(other.m_impl);
-}
-
-/*!
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the container and returns an iterator to the new current
- item.
+ if (const void *result = convert(value, type))
+ return result;
- Calling this function on QSequentialIterable::end() leads to undefined results.
-
- \sa operator--()
-*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++()
-{
- m_impl.advance(1);
- return *this;
+ converted = QVariant(type);
+ return converted.constData();
}
/*!
- \overload
+ \class QVariantRef
+ \since 6.0
+ \inmodule QtCore
+ \brief The QVariantRef acts as a non-const reference to a QVariant.
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the container and returns an iterator to the previously
- current item.
+ As the generic iterators don't actually instantiate a QVariant on each
+ step, they cannot return a reference to one from operator*(). QVariantRef
+ provides the same functionality as an actual reference to a QVariant would,
+ but is backed by a pointer given as template parameter. The template is
+ implemented for pointers of type QSequentialIterator and
+ QAssociativeIterator.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int)
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(1);
- return const_iterator(impl, new QAtomicInt(0));
-}
/*!
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
+ \fn template<typename Pointer> QVariantRef<Pointer>::QVariantRef(const Pointer *pointer)
- Calling this function on QSequentialIterable::begin() leads to undefined results.
-
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
-
- \sa operator++(), canReverseIterate()
-*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--()
-{
- m_impl.advance(-1);
- return *this;
-}
+ Creates a QVariantRef from an \a pointer.
+ */
/*!
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
+ \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariant &value)
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
-
- \sa canReverseIterate()
-*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int)
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(-1);
- return const_iterator(impl, new QAtomicInt(0));
-}
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
+ */
/*!
- Advances the iterator by \a j items.
+ \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariantRef &value)
- \sa operator-=(), operator+()
-*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j)
-{
- m_impl.advance(j);
- return *this;
-}
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
+ */
/*!
- Makes the iterator go back by \a j items.
-
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
+ \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(QVariantRef &&value)
- \sa operator+=(), operator-(), canReverseIterate()
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j)
-{
- m_impl.advance(-j);
- return *this;
-}
/*!
- Returns an iterator to the item at \a j positions forward from
- this iterator.
+ \fn template<typename Pointer> QVariantRef<Pointer>::operator QVariant() const
- \sa operator-(), operator+=()
+ Resolves the QVariantRef to an actual QVariant.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(j);
- return const_iterator(impl, new QAtomicInt(0));
-}
/*!
- Returns an iterator to the item at \a j positions backward from
- this iterator.
+ \fn template<typename Pointer> void swap(QVariantRef<Pointer> a, QVariantRef<Pointer> b)
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
-
- \sa operator+(), operator-=(), canReverseIterate()
+ Swaps the values pointed to by the pointers the QVariantRefs
+ \a a and \a b refer to.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(-j);
- return const_iterator(impl, new QAtomicInt(0));
-}
/*!
- \class QAssociativeIterable
- \since 5.2
+ \class QVariantConstPointer
+ \since 6.0
\inmodule QtCore
- \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
-
- This class allows several methods of accessing the elements of an associative container held within
- a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
- be converted to a QVariantHash or QVariantMap.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- The container itself is not copied before iterating over it.
-
- \sa QVariant
-*/
-
-/*!
- \internal
-*/
-QAssociativeIterable::QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl)
- : m_impl(impl)
-{
-}
-
-QAssociativeIterable::const_iterator::const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_)
- : m_impl(iter.m_impl), ref(ref_)
-{
- ref->ref();
-}
-
-QAssociativeIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_)
- : m_impl(impl), ref(ref_)
-{
- ref->ref();
-}
-
-void QAssociativeIterable::const_iterator::begin()
-{
- m_impl.begin();
-}
-
-void QAssociativeIterable::const_iterator::end()
-{
- m_impl.end();
-}
-
-void QAssociativeIterable::const_iterator::find(const QVariant &key)
-{
- Q_ASSERT(key.userType() == m_impl._metaType_id_key);
- const QtMetaTypePrivate::VariantData dkey(key.userType(), key.constData(), 0 /*key.flags()*/);
- m_impl.find(dkey);
-}
-
-/*!
- Returns a QAssociativeIterable::const_iterator for the beginning of the container. This
- can be used in stl-style iteration.
+ \brief Emulated const pointer to QVariant based on a pointer.
- \sa end()
+ QVariantConstPointer wraps a QVariant and returns it from its operator*().
+ This makes it suitable as replacement for an actual const pointer. We cannot
+ return an actual const pointer from generic iterators as the iterators don't
+ hold an actual QVariant.
*/
-QAssociativeIterable::const_iterator QAssociativeIterable::begin() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.begin();
- return it;
-}
/*!
- Returns a QAssociativeIterable::const_iterator for the end of the container. This
- can be used in stl-style iteration.
-
- \sa begin()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::end() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.end();
- return it;
-}
-
-/*!
- \since 5.5
-
- Returns a QAssociativeIterable::const_iterator for the given key \a key
- in the container, if the types are convertible.
-
- If the key is not found, returns end().
-
- This can be used in stl-style iteration.
-
- \sa begin(), end(), value()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
+ Constructs a QVariantConstPointer from a \a variant.
+ */
+QVariantConstPointer::QVariantConstPointer(QVariant variant)
+ : m_variant(std::move(variant))
{
- const_iterator it(*this, new QAtomicInt(0));
- QVariant key_ = key;
- if (key_.canConvert(m_impl._metaType_id_key) && key_.convert(m_impl._metaType_id_key))
- it.find(key_);
- else
- it.end();
- return it;
}
/*!
- Returns the value for the given \a key in the container, if the types are convertible.
-
- \sa find()
-*/
-QVariant QAssociativeIterable::value(const QVariant &key) const
+ Dereferences the QVariantConstPointer to retrieve its internal QVariant.
+ */
+QVariant QVariantConstPointer::operator*() const
{
- const const_iterator it = find(key);
- if (it == end())
- return QVariant();
- return *it;
+ return m_variant;
}
/*!
- Returns the number of elements in the container.
-*/
-int QAssociativeIterable::size() const
+ Returns a const pointer to the QVariant, conforming to the
+ conventions for operator->().
+ */
+const QVariant *QVariantConstPointer::operator->() const
{
- return m_impl.size();
+ return &m_variant;
}
/*!
- \class QAssociativeIterable::const_iterator
- \since 5.2
+ \class QVariantPointer
+ \since 6.0
\inmodule QtCore
- \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
-
- A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
- and can be used in a way similar to other stl-style iterators.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- \sa QAssociativeIterable
-*/
-
+ \brief QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
-/*!
- Destroys the QAssociativeIterable::const_iterator.
+ QVariantConstPointer wraps a pointer and returns QVariantRef to it from its
+ operator*(). This makes it suitable as replacement for an actual pointer. We
+ cannot return an actual pointer from generic iterators as the iterators don't
+ hold an actual QVariant.
*/
-QAssociativeIterable::const_iterator::~const_iterator()
-{
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
-}
/*!
- Creates a copy of \a other.
-*/
-QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other)
- : m_impl(other.m_impl), ref(other.ref)
-{
- ref->ref();
-}
+ \fn template<typename Pointer> QVariantPointer<Pointer>::QVariantPointer(const Pointer *pointer)
-/*!
- Assigns \a other to this.
-*/
-QAssociativeIterable::const_iterator&
-QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
-{
- other.ref->ref();
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
- m_impl = other.m_impl;
- ref = other.ref;
- return *this;
-}
-
-/*!
- Returns the current value, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::operator*() const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns the current key, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::key() const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns the current value, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::value() const
-{
- return operator*();
-}
-
-/*!
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const
-{
- return m_impl.equal(other.m_impl);
-}
-
-/*!
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const
-{
- return !m_impl.equal(other.m_impl);
-}
-
-/*!
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the container and returns an iterator to the new current
- item.
-
- Calling this function on QAssociativeIterable::end() leads to undefined results.
-
- \sa operator--()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++()
-{
- m_impl.advance(1);
- return *this;
-}
-
-/*!
- \overload
-
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the container and returns an iterator to the previously
- current item.
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int)
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(1);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QAssociativeIterable::begin() leads to undefined results.
-
- \sa operator++()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--()
-{
- m_impl.advance(-1);
- return *this;
-}
-
-/*!
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int)
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(-1);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- Advances the iterator by \a j items.
-
- \sa operator-=(), operator+()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j)
-{
- m_impl.advance(j);
- return *this;
-}
-
-/*!
- Makes the iterator go back by \a j items.
-
- \sa operator+=(), operator-()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j)
-{
- m_impl.advance(-j);
- return *this;
-}
+ Constructs a QVariantPointer from the given \a pointer.
+ */
/*!
- Returns an iterator to the item at \a j positions forward from
- this iterator.
+ \fn template<typename Pointer> QVariantRef<Pointer> QVariantPointer<Pointer>::operator*() const
- \sa operator-(), operator+=()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(j);
- return const_iterator(impl, new QAtomicInt(0));
-}
+ Dereferences the QVariantPointer to a QVariantRef.
+ */
/*!
- Returns an iterator to the item at \a j positions backward from
- this iterator.
-
- \sa operator+(), operator-=()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(-j);
- return const_iterator(impl, new QAtomicInt(0));
-}
+ \fn template<typename Pointer> Pointer QVariantPointer<Pointer>::operator->() const
-QVariant::Private::~Private()
-{
- QtMetaTypePrivate::derefAndDestroy(
- reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2));
-}
+ Dereferences and returns the pointer. The pointer is expected to also
+ implement operator->().
+ */
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index a80321b7d4..d567bcbb7c 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -1,137 +1,147 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVARIANT_H
#define QVARIANT_H
#include <QtCore/qatomic.h>
-#include <QtCore/qbytearray.h>
-#include <QtCore/qlist.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qcontainerfwd.h>
#include <QtCore/qmetatype.h>
-#include <QtCore/qmap.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/qobject.h>
-#ifndef QT_BOOTSTRAPPED
-#include <QtCore/qbytearraylist.h>
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
#endif
#include <memory>
-
-#if __has_include(<variant>) && __cplusplus >= 201703L
+#include <QtCore/q20type_traits.h>
+#include <QtCore/q23utility.h>
#include <variant>
-#elif defined(Q_CLANG_QDOC)
-namespace std { template<typename...> struct variant; }
+
+#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
+# include <QtCore/qlist.h>
+# include <QtCore/qstringlist.h>
+# include <QtCore/qbytearraylist.h>
+# include <QtCore/qhash.h>
+# include <QtCore/qmap.h>
+# include <QtCore/qobject.h>
#endif
QT_BEGIN_NAMESPACE
+QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
+QT_ENABLE_P0846_SEMANTICS_FOR(get)
class QBitArray;
class QDataStream;
class QDate;
class QDateTime;
-#if QT_CONFIG(easingcurve)
class QEasingCurve;
-#endif
class QLine;
class QLineF;
class QLocale;
-class QTransform;
-class QStringList;
-class QTime;
+class QModelIndex;
+class QPersistentModelIndex;
class QPoint;
class QPointF;
-class QSize;
-class QSizeF;
class QRect;
class QRectF;
-#if QT_CONFIG(regularexpression)
class QRegularExpression;
-#endif // QT_CONFIG(regularexpression)
+class QSize;
+class QSizeF;
class QTextFormat;
class QTextLength;
+class QTime;
+class QTransform;
class QUrl;
class QVariant;
-class QVariantComparisonHelper;
template<typename T>
inline T qvariant_cast(const QVariant &);
namespace QtPrivate {
+template<> constexpr inline bool qIsRelocatable<QVariant> = true;
+}
+class Q_CORE_EXPORT QVariant
+{
+ template <typename T, typename... Args>
+ using if_constructible = std::enable_if_t<
+ std::conjunction_v<
+ std::is_copy_constructible<q20::remove_cvref_t<T>>,
+ std::is_destructible<q20::remove_cvref_t<T>>,
+ std::is_constructible<q20::remove_cvref_t<T>, Args...>
+ >,
+ bool>;
+
+ template <typename T>
+ using if_rvalue = std::enable_if_t<!std::is_reference_v<T>, bool>;
+
+ struct CborValueStandIn { qint64 n; void *c; int t; };
+public:
+ struct PrivateShared
+ {
+ private:
+ inline PrivateShared() : ref(1) { }
+ public:
+ static int computeOffset(PrivateShared *ps, size_t align);
+ static size_t computeAllocationSize(size_t size, size_t align);
+ static PrivateShared *create(size_t size, size_t align);
+ static void free(PrivateShared *p);
- template <typename Derived, typename Argument, typename ReturnType>
- struct ObjectInvoker
+ alignas(8) QAtomicInt ref;
+ int offset;
+
+ const void *data() const { return reinterpret_cast<const uchar *>(this) + offset; }
+ void *data() { return reinterpret_cast<uchar *>(this) + offset; }
+ };
+
+ struct Private
{
- static ReturnType invoke(Argument a)
+ static constexpr size_t MaxInternalSize = 3 * sizeof(void *);
+ template <size_t S> static constexpr bool FitsInInternalSize = S <= MaxInternalSize;
+ template<typename T> static constexpr bool CanUseInternalSpace =
+ (QTypeInfo<T>::isRelocatable && FitsInInternalSize<sizeof(T)> && alignof(T) <= alignof(double));
+ static constexpr bool canUseInternalSpace(const QtPrivate::QMetaTypeInterface *type)
{
- return Derived::object(a);
+ Q_ASSERT(type);
+ return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType &&
+ size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double);
}
- };
- template <typename Derived, typename Argument, typename ReturnType>
- struct MetaTypeInvoker
- {
- static ReturnType invoke(Argument a)
+ union
{
- return Derived::metaType(a);
+ uchar data[MaxInternalSize] = {};
+ PrivateShared *shared;
+ double _forAlignment; // we want an 8byte alignment on 32bit systems as well
+ } data;
+ quintptr is_shared : 1;
+ quintptr is_null : 1;
+ quintptr packedType : sizeof(QMetaType) * 8 - 2;
+
+ constexpr Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
+ explicit Private(const QtPrivate::QMetaTypeInterface *iface) noexcept;
+ template <typename T> explicit Private(std::piecewise_construct_t, const T &t);
+
+ const void *storage() const
+ { return is_shared ? data.shared->data() : &data.data; }
+
+ // determine internal storage at compile time
+ template<typename T> const T &get() const
+ { return *static_cast<const T *>(CanUseInternalSpace<T> ? &data.data : data.shared->data()); }
+
+ inline const QtPrivate::QMetaTypeInterface *typeInterface() const
+ {
+ return reinterpret_cast<const QtPrivate::QMetaTypeInterface *>(packedType << 2);
}
- };
- template <typename Derived, typename T, typename Argument, typename ReturnType, bool = IsPointerToTypeDerivedFromQObject<T>::Value>
- struct TreatAsQObjectBeforeMetaType : ObjectInvoker<Derived, Argument, ReturnType>
- {
+ inline QMetaType type() const
+ {
+ return QMetaType(typeInterface());
+ }
};
- template <typename Derived, typename T, typename Argument, typename ReturnType>
- struct TreatAsQObjectBeforeMetaType<Derived, T, Argument, ReturnType, false> : MetaTypeInvoker<Derived, Argument, ReturnType>
+#if QT_DEPRECATED_SINCE(6, 0)
+ enum QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") Type
{
- };
-
- template<typename T> struct QVariantValueHelper;
-}
-
-class Q_CORE_EXPORT QVariant
-{
- public:
- enum Type {
Invalid = QMetaType::UnknownType,
Bool = QMetaType::Bool,
Int = QMetaType::Int,
@@ -204,44 +214,110 @@ class Q_CORE_EXPORT QVariant
UserType = QMetaType::User,
LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
};
-
+#endif
QVariant() noexcept : d() {}
~QVariant();
- QVariant(Type type);
- QVariant(int typeId, const void *copy, uint flags = 0); // ### Qt6 TODO deprecate
- explicit QVariant(QMetaType type, const void *copy);
+ explicit QVariant(QMetaType type, const void *copy = nullptr);
QVariant(const QVariant &other);
-#ifndef QT_NO_DATASTREAM
- QVariant(QDataStream &s);
+private:
+ template <typename T, typename ...Args>
+ using is_noexcept_constructible = std::conjunction<
+ std::bool_constant<Private::CanUseInternalSpace<T>>,
+ std::is_nothrow_constructible<T, Args...>
+ >;
+
+public:
+ template <typename T, typename... Args,
+ if_constructible<T, Args...> = true>
+ explicit QVariant(std::in_place_type_t<T>, Args&&... args)
+ noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
+ : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>() )
+ {
+ void *data = const_cast<void *>(constData());
+ new (data) T(std::forward<Args>(args)...);
+ }
+
+ template <typename T, typename U, typename... Args,
+ if_constructible<T, std::initializer_list<U> &, Args...> = true>
+ explicit QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args)
+ noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>,
+ std::initializer_list<U> &,
+ Args...
+ >::value)
+ : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>())
+ {
+ char *data = static_cast<char *>(const_cast<void *>(constData()));
+ new (data) T(il, std::forward<Args>(args)...);
+ }
+
+ // primitives
+ QVariant(int i) noexcept;
+ QVariant(uint ui) noexcept;
+ QVariant(qlonglong ll) noexcept;
+ QVariant(qulonglong ull) noexcept;
+ QVariant(bool b) noexcept;
+ QVariant(double d) noexcept;
+ QVariant(float f) noexcept;
+
+ // trivial, trivially-copyable or COW
+ QVariant(QChar qchar) noexcept;
+ QVariant(QDate date) noexcept;
+ QVariant(QTime time) noexcept;
+#ifndef QT_BOOTSTRAPPED
+ QVariant(const QBitArray &bitarray) noexcept;
+#endif
+ QVariant(const QByteArray &bytearray) noexcept;
+ QVariant(const QDateTime &datetime) noexcept;
+ QVariant(const QHash<QString, QVariant> &hash) noexcept;
+ QVariant(const QJsonArray &jsonArray) noexcept;
+ QVariant(const QJsonObject &jsonObject) noexcept;
+ QVariant(const QList<QVariant> &list) noexcept;
+ QVariant(const QLocale &locale) noexcept;
+ QVariant(const QMap<QString, QVariant> &map) noexcept;
+ QVariant(const QRegularExpression &re) noexcept;
+ QVariant(const QString &string) noexcept;
+ QVariant(const QStringList &stringlist) noexcept;
+ QVariant(const QUrl &url) noexcept;
+
+ // conditionally noexcept trivial or trivially-copyable
+ // (most of these are noexcept on 64-bit)
+ QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>);
+ QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>);
+ QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>);
+#ifndef QT_NO_GEOM_VARIANT
+ QVariant(QSize size) noexcept;
+ QVariant(QSizeF size) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
+ QVariant(QPoint pt) noexcept;
+ QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
+ QVariant(QLine line) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
+ QVariant(QLineF line) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
+ QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
+ QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
#endif
- QVariant(int i);
- QVariant(uint ui);
- QVariant(qlonglong ll);
- QVariant(qulonglong ull);
- QVariant(bool b);
- QVariant(double d);
- QVariant(float f);
+ // not noexcept
+ QVariant(const QEasingCurve &easing) noexcept(false);
+ QVariant(const QJsonDocument &jsonDocument) noexcept(false);
+ QVariant(const QPersistentModelIndex &modelIndex) noexcept(false);
+
#ifndef QT_NO_CAST_FROM_ASCII
- QT_ASCII_CAST_WARN QVariant(const char *str)
+ QT_ASCII_CAST_WARN QVariant(const char *str) noexcept(false)
: QVariant(QString::fromUtf8(str))
{}
#endif
+ QVariant(QLatin1StringView string) noexcept(false); // converts to QString
- QVariant(const QByteArray &bytearray);
- QVariant(const QBitArray &bitarray);
- QVariant(const QString &string);
- QVariant(QLatin1String string);
- QVariant(const QStringList &stringlist);
- QVariant(QChar qchar);
- QVariant(QDate date);
- QVariant(QTime time);
- QVariant(const QDateTime &datetime);
- QVariant(const QList<QVariant> &list);
- QVariant(const QMap<QString,QVariant> &map);
- QVariant(const QHash<QString,QVariant> &hash);
-#ifndef QT_NO_GEOM_VARIANT
+#if !defined(Q_CC_GHS)
+ // GHS has an ICE with this code; use the simplified version below
+ template <typename T,
+ std::enable_if_t<std::disjunction_v<std::is_pointer<T>, std::is_member_pointer<T>>, bool> = false>
+ QVariant(T) = delete;
+#else
+ QVariant(const volatile void *) = delete;
+#endif
+
+#if QT_CORE_REMOVED_SINCE(6, 5)
QVariant(const QSize &size);
QVariant(const QSizeF &size);
QVariant(const QPoint &pt);
@@ -250,42 +326,37 @@ class Q_CORE_EXPORT QVariant
QVariant(const QLineF &line);
QVariant(const QRect &rect);
QVariant(const QRectF &rect);
-#endif
- QVariant(const QLocale &locale);
-#if QT_CONFIG(regularexpression)
- QVariant(const QRegularExpression &re);
-#endif // QT_CONFIG(regularexpression)
-#if QT_CONFIG(easingcurve)
- QVariant(const QEasingCurve &easing);
-#endif
QVariant(const QUuid &uuid);
-#ifndef QT_BOOTSTRAPPED
- QVariant(const QUrl &url);
- QVariant(const QJsonValue &jsonValue);
- QVariant(const QJsonObject &jsonObject);
- QVariant(const QJsonArray &jsonArray);
- QVariant(const QJsonDocument &jsonDocument);
-#endif // QT_BOOTSTRAPPED
-#if QT_CONFIG(itemmodel)
- QVariant(const QModelIndex &modelIndex);
- QVariant(const QPersistentModelIndex &modelIndex);
#endif
QVariant& operator=(const QVariant &other);
inline QVariant(QVariant &&other) noexcept : d(other.d)
{ other.d = Private(); }
- inline QVariant &operator=(QVariant &&other) noexcept
- { QVariant moved(std::move(other)); swap(moved); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant)
+
+ inline void swap(QVariant &other) noexcept { std::swap(d, other.d); }
- inline void swap(QVariant &other) noexcept { qSwap(d, other.d); }
+ int userType() const { return typeId(); }
+ int typeId() const { return metaType().id(); }
- Type type() const;
- int userType() const;
const char *typeName() const;
QMetaType metaType() const;
- bool canConvert(int targetTypeId) const;
- bool convert(int targetTypeId);
+ bool canConvert(QMetaType targetType) const
+ { return QMetaType::canConvert(d.type(), targetType); }
+ bool convert(QMetaType type);
+
+ bool canView(QMetaType targetType) const
+ { return QMetaType::canView(d.type(), targetType); }
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ bool canConvert(int targetTypeId) const
+ { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); }
+ QT_DEPRECATED_VERSION_6_0
+ bool convert(int targetTypeId)
+ { return convert(QMetaType(targetTypeId)); }
+#endif
inline bool isValid() const;
bool isNull() const;
@@ -304,7 +375,9 @@ class Q_CORE_EXPORT QVariant
float toFloat(bool *ok = nullptr) const;
qreal toReal(bool *ok = nullptr) const;
QByteArray toByteArray() const;
+#ifndef QT_BOOTSTRAPPED
QBitArray toBitArray() const;
+#endif
QString toString() const;
QStringList toStringList() const;
QChar toChar() const;
@@ -349,140 +422,259 @@ class Q_CORE_EXPORT QVariant
void load(QDataStream &ds);
void save(QDataStream &ds) const;
#endif
- static const char *typeToName(int typeId);
- static Type nameToType(const char *name);
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
+ QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.")
+ explicit QVariant(Type type)
+ : QVariant(QMetaType(int(type)))
+ {}
+ QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().")
+ Type type() const
+ {
+ int type = d.type().id();
+ return type >= QMetaType::User ? UserType : static_cast<Type>(type);
+ }
+ QT_DEPRECATED_VERSION_6_0
+ static const char *typeToName(int typeId)
+ { return QMetaType(typeId).name(); }
+ QT_DEPRECATED_VERSION_6_0
+ static Type nameToType(const char *name)
+ {
+ int metaType = QMetaType::fromName(name).id();
+ return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
+ }
+ QT_WARNING_POP
+#endif
void *data();
- const void *constData() const;
+ const void *constData() const
+ { return d.storage(); }
inline const void *data() const { return constData(); }
- template<typename T>
- inline void setValue(const T &value);
+private:
+ template <typename T>
+ void verifySuitableForEmplace()
+ {
+ static_assert(!std::is_reference_v<T>,
+ "QVariant does not support reference types");
+ static_assert(!std::is_const_v<T>,
+ "QVariant does not support const types");
+ static_assert(std::is_copy_constructible_v<T>,
+ "QVariant requires that the type is copyable");
+ static_assert(std::is_destructible_v<T>,
+ "QVariant requires that the type is destructible");
+ }
+
+ template <typename T, typename... Args>
+ T &emplaceImpl(Args&&... args)
+ {
+ verifySuitableForEmplace<T>();
+ auto data = static_cast<T *>(prepareForEmplace(QMetaType::fromType<T>()));
+ return *q20::construct_at(data, std::forward<Args>(args)...);
+ }
+
+public:
+ template <typename T, typename... Args,
+ if_constructible<T, Args...> = true>
+ T &emplace(Args&&... args)
+ {
+ return emplaceImpl<T>(std::forward<Args>(args)...);
+ }
+
+ template <typename T, typename U, typename... Args,
+ if_constructible<T, std::initializer_list<U> &, Args...> = true>
+ T &emplace(std::initializer_list<U> list, Args&&... args)
+ {
+ return emplaceImpl<T>(list, std::forward<Args>(args)...);
+ }
+
+ template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>>
+ void setValue(T &&avalue)
+ {
+ using VT = std::decay_t<T>;
+ QMetaType metaType = QMetaType::fromType<VT>();
+ // If possible we reuse the current QVariant private.
+ if (isDetached() && d.type() == metaType) {
+ *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
+ } else {
+ *this = QVariant::fromValue<VT>(std::forward<T>(avalue));
+ }
+ }
+
+ void setValue(const QVariant &avalue)
+ {
+ *this = avalue;
+ }
+
+ void setValue(QVariant &&avalue)
+ {
+ *this = std::move(avalue);
+ }
template<typename T>
- inline T value() const
+ inline T value() const &
{ return qvariant_cast<T>(*this); }
template<typename T>
+ inline T view()
+ {
+ T t{};
+ QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t);
+ return t;
+ }
+
+ template<typename T>
+ inline T value() &&
+ { return qvariant_cast<T>(std::move(*this)); }
+
+ template<typename T, if_rvalue<T> = true>
+#ifndef Q_QDOC
+ /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works
+ (but copy_constructible implies move_constructble, so don't bother checking)
+ */
+ static inline auto fromValue(T &&value)
+ noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
+ -> std::enable_if_t<std::conjunction_v<std::is_copy_constructible<T>,
+ std::is_destructible<T>>, QVariant>
+#else
+ static inline QVariant fromValue(T &&value)
+#endif
+ {
+ // handle special cases
+ using Type = std::remove_cv_t<T>;
+ if constexpr (std::is_null_pointer_v<Type>)
+ return QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>());
+ else if constexpr (std::is_same_v<Type, QVariant>)
+ return std::forward<T>(value);
+ else if constexpr (std::is_same_v<Type, std::monostate>)
+ return QVariant();
+ QMetaType mt = QMetaType::fromType<Type>();
+ mt.registerType(); // we want the type stored in QVariant to always be registered
+ // T is a forwarding reference, so if T satifies the enable-ifery,
+ // we get this overload even if T is an lvalue reference and thus must check here
+ // Moreover, we only try to move if the type is actually moveable and not if T is const
+ // as in const int i; QVariant::fromValue(std::move(i));
+ if constexpr (std::conjunction_v<std::is_move_constructible<Type>, std::negation<std::is_const<T>>>)
+ return moveConstruct(QMetaType::fromType<Type>(), std::addressof(value));
+ else
+ return copyConstruct(mt, std::addressof(value));
+ }
+
+ template<typename T>
+#ifndef Q_QDOC
+ static inline auto fromValue(const T &value)
+ noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
+ -> std::enable_if_t<std::is_copy_constructible_v<T> && std::is_destructible_v<T>, QVariant>
+#else
static inline QVariant fromValue(const T &value)
+#endif
{
+ if constexpr (std::is_null_pointer_v<T>)
+ return QVariant(QMetaType::fromType<std::nullptr_t>());
+ else if constexpr (std::is_same_v<T, QVariant>)
+ return value;
+ else if constexpr (std::is_same_v<T, std::monostate>)
+ return QVariant();
return QVariant(QMetaType::fromType<T>(), std::addressof(value));
}
-#if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC)
template<typename... Types>
static inline QVariant fromStdVariant(const std::variant<Types...> &value)
{
- if (value.valueless_by_exception())
- return QVariant();
- return std::visit([](const auto &arg) { return fromValue(arg); }, value);
+ return fromStdVariantImpl(value);
}
-#endif
+
+ template<typename... Types>
+ static QVariant fromStdVariant(std::variant<Types...> &&value)
+ {
+ return fromStdVariantImpl(std::move(value));
+ }
+
+ static QVariant fromMetaType(QMetaType type, const void *copy = nullptr);
template<typename T>
bool canConvert() const
- { return canConvert(qMetaTypeId<T>()); }
+ { return canConvert(QMetaType::fromType<T>()); }
- public:
- struct PrivateShared
- {
- inline PrivateShared(void *v) : ptr(v), ref(1) { }
- void *ptr;
- QAtomicInt ref;
- };
- struct Private
- {
- Private() noexcept : packedType(0), is_shared(false), is_null(true) {}
- explicit Private(const QMetaType &type) noexcept : is_shared(false), is_null(false)
- {
- if (type.d_ptr)
- type.d_ptr->ref.ref();
- quintptr mt = quintptr(type.d_ptr);
- Q_ASSERT((mt & 0x3) == 0);
- packedType = mt >> 2;
- }
- explicit Private(int type) noexcept : Private(QMetaType(type)) {}
- Private(const Private &other) : Private(other.type())
- {
- data = other.data;
- is_shared = other.is_shared;
- is_null = other.is_null;
- }
- Private &operator=(const Private &other)
- {
- if (&other != this) {
- this->~Private();
- new (this) Private(other);
- }
- return *this;
- }
- Q_CORE_EXPORT ~Private();
+ template<typename T>
+ bool canView() const
+ { return canView(QMetaType::fromType<T>()); }
- union Data
- {
- void *threeptr[3] = { nullptr, nullptr, nullptr };
- char c;
- uchar uc;
- short s;
- signed char sc;
- ushort us;
- int i;
- uint u;
- long l;
- ulong ul;
- bool b;
- double d;
- float f;
- qreal real;
- qlonglong ll;
- qulonglong ull;
- QObject *o;
- void *ptr;
- PrivateShared *shared;
- } data;
- quintptr packedType : sizeof(QMetaType) * 8 - 2;
- quintptr is_shared : 1;
- quintptr is_null : 1;
- inline QMetaType type() const
- {
- return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2));
- }
- };
- public:
- typedef bool (*f_null)(const Private *);
- typedef bool (*f_compare)(const Private *, const Private *);
- typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *);
- typedef void (*f_debugStream)(QDebug, const QVariant &);
- struct Handler {
- f_null isNull;
- f_compare compare;
- f_convert convert;
- f_debugStream debugStream;
- };
+ static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs);
- inline bool operator==(const QVariant &v) const
- { return cmp(v); }
- inline bool operator!=(const QVariant &v) const
- { return !cmp(v); }
+private:
+ template <typename StdVariant>
+ static QVariant fromStdVariantImpl(StdVariant &&v)
+ {
+ if (Q_UNLIKELY(v.valueless_by_exception()))
+ return QVariant();
+ auto visitor = [](auto &&arg) {
+ return QVariant::fromValue(q23::forward_like<StdVariant>(arg));
+ };
+ return std::visit(visitor, std::forward<StdVariant>(v));
+ }
+
+ friend bool comparesEqual(const QVariant &a, const QVariant &b)
+ { return a.equals(b); }
+ Q_DECLARE_EQUALITY_COMPARABLE(QVariant)
-protected:
- friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
#ifndef QT_NO_DEBUG_STREAM
- friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
+ template <typename T>
+ friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> {
+ return variant.qdebugHelper(debug);
+ }
+ QDebug qdebugHelper(QDebug) const;
#endif
-// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC for QTBUG-41810 .
-#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
+
+ template <typename T>
+ friend T *get_if(QVariant *v) noexcept
+ {
+ // data() will detach from is_null, returning non-nullptr
+ if (!v || v->d.type() != QMetaType::fromType<T>())
+ return nullptr;
+ return static_cast<T*>(v->data());
+ }
+ template <typename T>
+ friend const T *get_if(const QVariant *v) noexcept
+ {
+ // (const) data() will not detach from is_null, return nullptr
+ if (!v || v->d.is_null || v->d.type() != QMetaType::fromType<T>())
+ return nullptr;
+ return static_cast<const T*>(v->data());
+ }
+
+#define Q_MK_GET(cvref) \
+ template <typename T> \
+ friend T cvref get(QVariant cvref v) \
+ { \
+ if constexpr (std::is_const_v<T cvref>) \
+ Q_ASSERT(!v.d.is_null); \
+ Q_ASSERT(v.d.type() == QMetaType::fromType<q20::remove_cvref_t<T>>()); \
+ return static_cast<T cvref>(*get_if<T>(&v)); \
+ } \
+ /* end */
+ Q_MK_GET(&)
+ Q_MK_GET(const &)
+ Q_MK_GET(&&)
+ Q_MK_GET(const &&)
+#undef Q_MK_GET
+
+ static QVariant moveConstruct(QMetaType type, void *data);
+ static QVariant copyConstruct(QMetaType type, const void *data);
+
template<typename T>
friend inline T qvariant_cast(const QVariant &);
- template<typename T> friend struct QtPrivate::QVariantValueHelper;
+ template<typename T>
+ friend inline T qvariant_cast(QVariant &&);
+
protected:
-#else
-public:
-#endif
Private d;
void create(int type, const void *copy);
- bool cmp(const QVariant &other) const;
- bool convert(const int t, void *ptr) const; // ### Qt6: drop const
+ void create(QMetaType type, const void *copy);
+ bool equals(const QVariant &other) const;
+ bool convert(int type, void *ptr) const;
+ bool view(int type, void *ptr);
private:
// force compile error, prevent QVariant(bool) to be called
@@ -495,7 +687,12 @@ private:
// int variant, so delete this constructor:
QVariant(QMetaType::Type) = delete;
- // These constructors don't create QVariants of the type associcated
+ // used to setup the QVariant internals for the "real" inplace ctor
+ QVariant(std::in_place_t, QMetaType type);
+ // helper for emplace
+ void *prepareForEmplace(QMetaType type);
+
+ // These constructors don't create QVariants of the type associated
// with the enum, as expected, but they would create a QVariant of
// type int with the value of the enum value.
// Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
@@ -514,348 +711,173 @@ public:
inline const DataPtr &data_ptr() const { return d; }
};
-template<>
-inline QVariant QVariant::fromValue(const QVariant &value)
-{
- return value;
-}
-
-#if __has_include(<variant>) && __cplusplus >= 201703L
-template<>
-inline QVariant QVariant::fromValue(const std::monostate &)
-{
- return QVariant();
-}
-#endif
-
inline bool QVariant::isValid() const
{
return d.type().isValid();
}
-template<typename T>
-inline void QVariant::setValue(const T &avalue)
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p);
+
+#if QT_DEPRECATED_SINCE(6, 0)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+QT_DEPRECATED_VERSION_6_0
+inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p)
{
- QMetaType metaType = QMetaType::fromType<T>();
- // If possible we reuse the current QVariant private.
- if (isDetached() && d.type() == metaType) {
- *reinterpret_cast<T *>(data()) = avalue;
- } else {
- *this = QVariant::fromValue<T>(avalue);
- }
+ quint32 u;
+ s >> u;
+ p = static_cast<QVariant::Type>(u);
+ return s;
}
-
-template<>
-inline void QVariant::setValue(const QVariant &avalue)
+QT_DEPRECATED_VERSION_6_0
+inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p)
{
- *this = avalue;
+ s << static_cast<quint32>(p);
+ return s;
}
+QT_WARNING_POP
+#endif
-#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p);
-Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p);
-Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p);
-Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
#endif
inline bool QVariant::isDetached() const
{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
+inline void swap(QVariant &value1, QVariant &value2) noexcept
+{ value1.swap(value2); }
-#ifdef Q_QDOC
- inline bool operator==(const QVariant &v1, const QVariant &v2);
- inline bool operator!=(const QVariant &v1, const QVariant &v2);
-#else
+#ifndef QT_MOC
-/* Helper class to add one more level of indirection to prevent
- implicit casts.
-*/
-class QVariantComparisonHelper
+template<typename T> inline T qvariant_cast(const QVariant &v)
{
-public:
- inline QVariantComparisonHelper(const QVariant &var)
- : v(&var) {}
-private:
- friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
- const QVariant *v;
-};
+ QMetaType targetType = QMetaType::fromType<T>();
+ if (v.d.type() == targetType)
+ return v.d.get<T>();
+ if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
+ using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
+ QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
+ if (v.d.type() == nonConstTargetType)
+ return v.d.get<nonConstT>();
+ }
-inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2)
-{
- return v1.cmp(*v2.v);
+ T t{};
+ QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
+ return t;
}
-inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
+template<typename T> inline T qvariant_cast(QVariant &&v)
{
- return !operator==(v1, v2);
+ QMetaType targetType = QMetaType::fromType<T>();
+ if (v.d.type() == targetType) {
+ if constexpr (QVariant::Private::CanUseInternalSpace<T>) {
+ return std::move(*reinterpret_cast<T *>(v.d.data.data));
+ } else {
+ if (v.d.data.shared->ref.loadRelaxed() == 1)
+ return std::move(*reinterpret_cast<T *>(v.d.data.shared->data()));
+ else
+ return v.d.get<T>();
+ }
+ }
+ if constexpr (std::is_same_v<T, QVariant>) {
+ // if the metatype doesn't match, but we want a QVariant, just return the current variant
+ return v;
+ } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
+ // moving a pointer is pointless, just do the same as the const & overload
+ using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
+ QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
+ if (v.d.type() == nonConstTargetType)
+ return v.d.get<nonConstT>();
+ }
+
+ T t{};
+ QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
+ return t;
}
-#endif
-Q_DECLARE_SHARED(QVariant)
-class Q_CORE_EXPORT QSequentialIterable
+# ifndef QT_NO_VARIANT
+template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
{
- QtMetaTypePrivate::QSequentialIterableImpl m_impl;
-public:
- struct Q_CORE_EXPORT const_iterator
- {
- private:
- QtMetaTypePrivate::QSequentialIterableImpl m_impl;
- QAtomicInt *ref;
- friend class QSequentialIterable;
- explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_);
-
- explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_);
-
- void begin();
- void end();
- public:
- ~const_iterator();
-
- const_iterator(const const_iterator &other);
-
- const_iterator& operator=(const const_iterator &other);
-
- const QVariant operator*() const;
- bool operator==(const const_iterator &o) const;
- bool operator!=(const const_iterator &o) const;
- const_iterator &operator++();
- const_iterator operator++(int);
- const_iterator &operator--();
- const_iterator operator--(int);
- const_iterator &operator+=(int j);
- const_iterator &operator-=(int j);
- const_iterator operator+(int j) const;
- const_iterator operator-(int j) const;
- friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
- };
-
- friend struct const_iterator;
-
- explicit QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl);
-
- const_iterator begin() const;
- const_iterator end() const;
+ if (v.metaType().id() == QMetaType::QVariant)
+ return *reinterpret_cast<const QVariant *>(v.constData());
+ return v;
+}
+# endif
- QVariant at(int idx) const;
- int size() const;
+#endif // QT_MOC
- bool canReverseIterate() const;
-};
+#ifndef QT_NO_DEBUG_STREAM
+#if QT_DEPRECATED_SINCE(6, 0)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+QT_DEPRECATED_VERSION_6_0
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
+QT_WARNING_POP
+#endif
+#endif
-class Q_CORE_EXPORT QAssociativeIterable
+namespace QtPrivate {
+class Q_CORE_EXPORT QVariantTypeCoercer
{
- QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
public:
- struct Q_CORE_EXPORT const_iterator
- {
- private:
- QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
- QAtomicInt *ref;
- friend class QAssociativeIterable;
- explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_);
-
- explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_);
-
- void begin();
- void end();
- void find(const QVariant &key);
- public:
- ~const_iterator();
- const_iterator(const const_iterator &other);
-
- const_iterator& operator=(const const_iterator &other);
-
- const QVariant key() const;
-
- const QVariant value() const;
-
- const QVariant operator*() const;
- bool operator==(const const_iterator &o) const;
- bool operator!=(const const_iterator &o) const;
- const_iterator &operator++();
- const_iterator operator++(int);
- const_iterator &operator--();
- const_iterator operator--(int);
- const_iterator &operator+=(int j);
- const_iterator &operator-=(int j);
- const_iterator operator+(int j) const;
- const_iterator operator-(int j) const;
- friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
- };
-
- friend struct const_iterator;
+ // ### Qt7: Pass QMetaType as value rather than const ref.
+ const void *convert(const QVariant &value, const QMetaType &type);
+ const void *coerce(const QVariant &value, const QMetaType &type);
- explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl);
+private:
+ QVariant converted;
+};
+}
- const_iterator begin() const;
- const_iterator end() const;
- const_iterator find(const QVariant &key) const;
+template<typename Pointer>
+class QVariantRef
+{
+private:
+ const Pointer *m_pointer = nullptr;
- QVariant value(const QVariant &key) const;
+public:
+ explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {}
+ QVariantRef(const QVariantRef &) = default;
+ QVariantRef(QVariantRef &&) = default;
+ ~QVariantRef() = default;
- int size() const;
-};
+ operator QVariant() const;
+ QVariantRef &operator=(const QVariant &value);
+ QVariantRef &operator=(const QVariantRef &value) { return operator=(QVariant(value)); }
+ QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); }
-#ifndef QT_MOC
-namespace QtPrivate {
- template<typename T>
- struct QVariantValueHelper : TreatAsQObjectBeforeMetaType<QVariantValueHelper<T>, T, const QVariant &, T>
+ friend void swap(QVariantRef a, QVariantRef b)
{
- static T metaType(const QVariant &v)
- {
- const int vid = qMetaTypeId<T>();
- if (vid == v.userType())
- return *reinterpret_cast<const T *>(v.constData());
- T t;
- if (v.convert(vid, &t))
- return t;
- return T();
- }
-#ifndef QT_NO_QOBJECT
- static T object(const QVariant &v)
- {
- return qobject_cast<T>(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject
- ? v.d.data.o
- : QVariantValueHelper::metaType(v));
- }
-#endif
- };
+ QVariant tmp = a;
+ a = b;
+ b = std::move(tmp);
+ }
+};
- template<typename T>
- struct QVariantValueHelperInterface : QVariantValueHelper<T>
- {
- };
+class Q_CORE_EXPORT QVariantConstPointer
+{
+private:
+ QVariant m_variant;
- template<>
- struct QVariantValueHelperInterface<QSequentialIterable>
- {
- static QSequentialIterable invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantList>()) {
- return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QVariantList*>(v.constData())));
- }
- if (typeId == qMetaTypeId<QStringList>()) {
- return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QStringList*>(v.constData())));
- }
-#ifndef QT_BOOTSTRAPPED
- if (typeId == qMetaTypeId<QByteArrayList>()) {
- return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QByteArrayList*>(v.constData())));
- }
-#endif
- return QSequentialIterable(qvariant_cast<QtMetaTypePrivate::QSequentialIterableImpl>(v));
- }
- };
- template<>
- struct QVariantValueHelperInterface<QAssociativeIterable>
- {
- static QAssociativeIterable invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantMap>()) {
- return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantMap*>(v.constData())));
- }
- if (typeId == qMetaTypeId<QVariantHash>()) {
- return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData())));
- }
- return QAssociativeIterable(qvariant_cast<QtMetaTypePrivate::QAssociativeIterableImpl>(v));
- }
- };
- template<>
- struct QVariantValueHelperInterface<QVariantList>
- {
- static QVariantList invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() ||
- (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantList>()))) {
- QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
- QVariantList l;
- l.reserve(iter.size());
- for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l << *it;
- return l;
- }
- return QVariantValueHelper<QVariantList>::invoke(v);
- }
- };
- template<>
- struct QVariantValueHelperInterface<QVariantHash>
- {
- static QVariantHash invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantMap>() || ((QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantHash>()))) {
- QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
- QVariantHash l;
- l.reserve(iter.size());
- for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
- return l;
- }
- return QVariantValueHelper<QVariantHash>::invoke(v);
- }
- };
- template<>
- struct QVariantValueHelperInterface<QVariantMap>
- {
- static QVariantMap invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantHash>() || (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantMap>()))) {
- QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
- QVariantMap l;
- for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- static_cast<QMultiMap<QString, QVariant> &>(l).insert(it.key().toString(), it.value());
- return l;
- }
- return QVariantValueHelper<QVariantMap>::invoke(v);
- }
- };
- template<>
- struct QVariantValueHelperInterface<QPair<QVariant, QVariant> >
- {
- static QPair<QVariant, QVariant> invoke(const QVariant &v)
- {
- const int typeId = v.userType();
-
- if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()) && !(typeId == qMetaTypeId<QPair<QVariant, QVariant> >())) {
- QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
- const QtMetaTypePrivate::VariantData d1 = pi.first();
- QVariant v1(d1.metaTypeId, d1.data, d1.flags);
- if (d1.metaTypeId == qMetaTypeId<QVariant>())
- v1 = *reinterpret_cast<const QVariant*>(d1.data);
-
- const QtMetaTypePrivate::VariantData d2 = pi.second();
- QVariant v2(d2.metaTypeId, d2.data, d2.flags);
- if (d2.metaTypeId == qMetaTypeId<QVariant>())
- v2 = *reinterpret_cast<const QVariant*>(d2.data);
-
- return QPair<QVariant, QVariant>(v1, v2);
- }
- return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
- }
- };
-}
+public:
+ explicit QVariantConstPointer(QVariant variant);
-template<typename T> inline T qvariant_cast(const QVariant &v)
-{
- return QtPrivate::QVariantValueHelperInterface<T>::invoke(v);
-}
+ QVariant operator*() const;
+ const QVariant *operator->() const;
+};
-template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
+template<typename Pointer>
+class QVariantPointer
{
- if (v.userType() == QMetaType::QVariant)
- return *reinterpret_cast<const QVariant *>(v.constData());
- return v;
-}
-
-#endif
+private:
+ const Pointer *m_pointer = nullptr;
-#ifndef QT_NO_DEBUG_STREAM
-Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
-Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
-#endif
+public:
+ explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {}
+ QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); }
+ Pointer operator->() const { return *m_pointer; }
+};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 8739cb5173..d2a7390938 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -1,42 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVARIANT_P_H
#define QVARIANT_P_H
@@ -52,353 +15,95 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/private/qmetatype_p.h>
-#include <QtCore/qdebug.h>
-
-#include "qmetatypeswitcher_p.h"
+#include "qvariant.h"
QT_BEGIN_NAMESPACE
-template<typename T>
-struct QVariantIntegrator
-{
- static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data)
- && ((QTypeInfoQuery<T>::isRelocatable) || std::is_enum<T>::value);
- typedef std::integral_constant<bool, CanUseInternalSpace> CanUseInternalSpace_t;
-};
-static_assert(QVariantIntegrator<double>::CanUseInternalSpace);
-static_assert(QVariantIntegrator<long int>::CanUseInternalSpace);
-static_assert(QVariantIntegrator<qulonglong>::CanUseInternalSpace);
-
-#ifdef Q_CC_SUN // Sun CC picks the wrong overload, so introduce awful hack
-
-// takes a type, returns the internal void* pointer cast
-// to a pointer of the input type
-template <typename T>
-inline T *v_cast(const QVariant::Private *nd, T * = 0)
+inline auto customConstructSharedImpl(size_t size, size_t align)
{
- QVariant::Private *d = const_cast<QVariant::Private *>(nd);
- return !QVariantIntegrator<T>::CanUseInternalSpace
- ? static_cast<T *>(d->data.shared->ptr)
- : static_cast<T *>(static_cast<void *>(&d->data.c));
-}
-
-#else // every other compiler in this world
+ struct Deleter {
+ void operator()(QVariant::PrivateShared *p) const
+ { QVariant::PrivateShared::free(p); }
+ };
-template <typename T>
-inline const T *v_cast(const QVariant::Private *d, T * = nullptr)
-{
- return !QVariantIntegrator<T>::CanUseInternalSpace
- ? static_cast<const T *>(d->data.shared->ptr)
- : static_cast<const T *>(static_cast<const void *>(&d->data.c));
+ // this is exception-safe
+ std::unique_ptr<QVariant::PrivateShared, Deleter> ptr;
+ ptr.reset(QVariant::PrivateShared::create(size, align));
+ return ptr;
}
-template <typename T>
-inline T *v_cast(QVariant::Private *d, T * = nullptr)
+template <typename F> static QVariant::PrivateShared *
+customConstructShared(size_t size, size_t align, F &&construct)
{
- return !QVariantIntegrator<T>::CanUseInternalSpace
- ? static_cast<T *>(d->data.shared->ptr)
- : static_cast<T *>(static_cast<void *>(&d->data.c));
+ auto ptr = customConstructSharedImpl(size, align);
+ construct(ptr->data());
+ return ptr.release();
}
-#endif
-
-enum QVariantConstructionFlags : uint {
- Default = 0x0,
- PointerType = 0x1,
- ShouldDeleteVariantData = 0x2 // only used in Q*Iterable
-};
-
-//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
-template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
-{
-public:
- QVariantPrivateSharedEx() : QVariant::PrivateShared(&m_t), m_t() { }
- QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { }
-
-private:
- T m_t;
-};
-
-template <class T>
-inline void v_construct_helper(QVariant::Private *x, const T &t, std::true_type)
+inline int QVariant::PrivateShared::computeOffset(PrivateShared *ps, size_t align)
{
- new (&x->data) T(t);
- x->is_shared = false;
+ return int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps));
}
-template <class T>
-inline void v_construct_helper(QVariant::Private *x, const T &t, std::false_type)
+inline size_t QVariant::PrivateShared::computeAllocationSize(size_t size, size_t align)
{
- x->data.shared = new QVariantPrivateSharedEx<T>(t);
- x->is_shared = true;
+ size += sizeof(PrivateShared);
+ if (align > sizeof(PrivateShared)) {
+ // The alignment is larger than the alignment we can guarantee for the pointer
+ // directly following PrivateShared, so we need to allocate some additional
+ // memory to be able to fit the object into the available memory with suitable
+ // alignment.
+ size += align - sizeof(PrivateShared);
+ }
+ return size;
}
-template <class T>
-inline void v_construct_helper(QVariant::Private *x, std::true_type)
+inline QVariant::PrivateShared *QVariant::PrivateShared::create(size_t size, size_t align)
{
- new (&x->data) T();
- x->is_shared = false;
+ size = computeAllocationSize(size, align);
+ void *data = operator new(size);
+ auto *ps = new (data) QVariant::PrivateShared();
+ ps->offset = computeOffset(ps, align);
+ return ps;
}
-template <class T>
-inline void v_construct_helper(QVariant::Private *x, std::false_type)
+inline void QVariant::PrivateShared::free(PrivateShared *p)
{
- x->data.shared = new QVariantPrivateSharedEx<T>;
- x->is_shared = true;
+ p->~PrivateShared();
+ operator delete(p);
}
-template <class T>
-inline void v_construct(QVariant::Private *x, const T &t)
+inline QVariant::Private::Private(const QtPrivate::QMetaTypeInterface *iface) noexcept
+ : is_shared(false), is_null(false), packedType(quintptr(iface) >> 2)
{
- // dispatch
- v_construct_helper(x, t, typename QVariantIntegrator<T>::CanUseInternalSpace_t());
+ Q_ASSERT((quintptr(iface) & 0x3) == 0);
}
-// constructs a new variant if copy is 0, otherwise copy-constructs
-template <class T>
-inline void v_construct(QVariant::Private *x, const void *copy, T * = nullptr)
+template <typename T> inline
+QVariant::Private::Private(std::piecewise_construct_t, const T &t)
+ : is_shared(!CanUseInternalSpace<T>), is_null(std::is_same_v<T, std::nullptr_t>)
{
- if (copy)
- v_construct<T>(x, *static_cast<const T *>(copy));
- else
- v_construct_helper<T>(x, typename QVariantIntegrator<T>::CanUseInternalSpace_t());
-}
+ // confirm noexceptness
+ static constexpr bool isNothrowQVariantConstructible = noexcept(QVariant(t));
+ static constexpr bool isNothrowCopyConstructible = std::is_nothrow_copy_constructible_v<T>;
+ static constexpr bool isNothrowCopyAssignable = std::is_nothrow_copy_assignable_v<T>;
-// deletes the internal structures
-template <class T>
-inline void v_clear(QVariant::Private *d, T* = nullptr)
-{
+ const QtPrivate::QMetaTypeInterface *iface = QtPrivate::qMetaTypeInterfaceForType<T>();
+ Q_ASSERT((quintptr(iface) & 0x3) == 0);
+ packedType = quintptr(iface) >> 2;
- if (!QVariantIntegrator<T>::CanUseInternalSpace) {
- //now we need to cast
- //because QVariant::PrivateShared doesn't have a virtual destructor
- delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared);
+ if constexpr (CanUseInternalSpace<T>) {
+ static_assert(isNothrowQVariantConstructible == isNothrowCopyConstructible);
+ static_assert(isNothrowQVariantConstructible == isNothrowCopyAssignable);
+ new (data.data) T(t);
} else {
- v_cast<T>(d)->~T();
- }
-
-}
-
-template <typename T>
-struct PrimitiveIsNull
-{
-public:
- static bool isNull(const QVariant::Private *d)
- {
- return d->is_null;
- }
-};
-
-template <typename T>
-struct PrimitiveIsNull<T*>
-{
-public:
- static bool isNull(const QVariant::Private *d)
- {
- return d->is_null || d->data.ptr == nullptr;
- }
-};
-
-template <>
-struct PrimitiveIsNull<std::nullptr_t>
-{
-public:
- static bool isNull(const QVariant::Private *)
- {
- return true;
- }
-};
-
-template<class Filter>
-class QVariantComparator {
- template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted>
- struct FilteredComparator {
- static bool compare(const QVariant::Private *a, const QVariant::Private *b)
- {
- return *v_cast<T>(a) == *v_cast<T>(b);
- }
- };
- template<typename T>
- struct FilteredComparator<T, /* IsAcceptedType = */ false> {
- static bool compare(const QVariant::Private *, const QVariant::Private *)
- {
- // It is not possible to construct a QVariant containing not fully defined type
- Q_ASSERT(false);
- return false;
- }
- };
-public:
- QVariantComparator(const QVariant::Private *a, const QVariant::Private *b)
- : m_a(a), m_b(b)
- {
- Q_ASSERT(a->type() == b->type());
+ static_assert(!isNothrowQVariantConstructible); // we allocate memory, even if T doesn't
+ data.shared = customConstructShared(sizeof(T), alignof(T), [=](void *where) {
+ new (where) T(t);
+ });
}
-
- template<typename T>
- bool delegate(const T*)
- {
- return FilteredComparator<T>::compare(m_a, m_b);
- }
-
- bool delegate(const void*) { Q_ASSERT(false); return true; }
- bool delegate(const QMetaTypeSwitcher::UnknownType*)
- {
- return true; // for historical reason invalid variant == invalid variant
- }
- bool delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return false; }
-protected:
- const QVariant::Private *m_a;
- const QVariant::Private *m_b;
-};
-
-
-Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
-
-template<class Filter>
-class QVariantIsNull
-{
- /// \internal
- /// This class checks if a type T has method called isNull. Result is kept in the Value property
- /// TODO Can we somehow generalize it? A macro version?
- template<typename T>
- class HasIsNullMethod {
- struct Yes { char unused[1]; };
- struct No { char unused[2]; };
- static_assert(sizeof(Yes) != sizeof(No));
-
- template<class C> static decltype(static_cast<const C*>(nullptr)->isNull(), Yes()) test(int);
- template<class C> static No test(...);
- public:
- static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes));
- };
-
- // TODO This part should go to autotests during HasIsNullMethod generalization.
- static_assert(!HasIsNullMethod<bool>::Value);
- struct SelfTest1 { bool isNull() const; };
- static_assert(HasIsNullMethod<SelfTest1>::Value);
- struct SelfTest2 {};
- static_assert(!HasIsNullMethod<SelfTest2>::Value);
- struct SelfTest3 : public SelfTest1 {};
- static_assert(HasIsNullMethod<SelfTest3>::Value);
- struct SelfTestFinal1 final { bool isNull() const; };
- static_assert(HasIsNullMethod<SelfTestFinal1>::Value);
- struct SelfTestFinal2 final {};
- static_assert(!HasIsNullMethod<SelfTestFinal2>::Value);
- struct SelfTestFinal3 final : public SelfTest1 {};
- static_assert(HasIsNullMethod<SelfTestFinal3>::Value);
-
- template<typename T, bool HasIsNull = HasIsNullMethod<T>::Value>
- struct CallFilteredIsNull
- {
- static bool isNull(const QVariant::Private *d)
- {
- return v_cast<T>(d)->isNull();
- }
- };
- template<typename T>
- struct CallFilteredIsNull<T, /* HasIsNull = */ false>
- {
- static bool isNull(const QVariant::Private *d)
- {
- return PrimitiveIsNull<T>::isNull(d);
- }
- };
-
- template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted>
- struct CallIsNull
- {
- static bool isNull(const QVariant::Private *d)
- {
- return CallFilteredIsNull<T>::isNull(d);
- }
- };
- template<typename T>
- struct CallIsNull<T, /* IsAcceptedType = */ false>
- {
- static bool isNull(const QVariant::Private *d)
- {
- return CallFilteredIsNull<T, false>::isNull(d);
- }
- };
-
-public:
- QVariantIsNull(const QVariant::Private *d)
- : m_d(d)
- {}
- template<typename T>
- bool delegate(const T*)
- {
- return CallIsNull<T>::isNull(m_d);
- }
- // we need that as sizof(void) is undefined and it is needed in HasIsNullMethod
- bool delegate(const void *) { Q_ASSERT(false); return m_d->is_null; }
- bool delegate(const QMetaTypeSwitcher::UnknownType *) { return m_d->is_null; }
- bool delegate(const QMetaTypeSwitcher::NotBuiltinType *)
- {
- // QVariantIsNull is used only for built-in types
- Q_ASSERT(false);
- return m_d->is_null;
- }
-protected:
- const QVariant::Private *m_d;
-};
-
-namespace QVariantPrivate {
-Q_CORE_EXPORT void registerHandler(const int /* Modules::Names */ name, const QVariant::Handler *handler);
}
-#if !defined(QT_NO_DEBUG_STREAM)
-template<class Filter>
-class QVariantDebugStream
-{
- template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted>
- struct Filtered {
- Filtered(QDebug dbg, QVariant::Private *d)
- {
- dbg.nospace() << *v_cast<T>(d);
- }
- };
- template<typename T>
- struct Filtered<T, /* IsAcceptedType = */ false> {
- Filtered(QDebug /* dbg */, QVariant::Private *)
- {
- // It is not possible to construct not acccepted type, QVariantConstructor creates an invalid variant for them
- Q_ASSERT(false);
- }
- };
-
-public:
- QVariantDebugStream(QDebug dbg, QVariant::Private *d)
- : m_debugStream(dbg)
- , m_d(d)
- {}
-
- template<typename T>
- void delegate(const T*)
- {
- Filtered<T> streamIt(m_debugStream, m_d);
- Q_UNUSED(streamIt);
- }
-
- void delegate(const QMetaTypeSwitcher::NotBuiltinType*)
- {
- // QVariantDebugStream class is used only for a built-in type
- Q_ASSERT(false);
- }
- void delegate(const QMetaTypeSwitcher::UnknownType*)
- {
- m_debugStream.nospace() << "QVariant::Invalid";
- }
- void delegate(const void*) { Q_ASSERT(false); }
-private:
- QDebug m_debugStream;
- QVariant::Private *m_d;
-};
-#endif
-
QT_END_NAMESPACE
#endif // QVARIANT_P_H
diff --git a/src/corelib/kernel/qvarianthash.h b/src/corelib/kernel/qvarianthash.h
new file mode 100644
index 0000000000..a36efc6e9a
--- /dev/null
+++ b/src/corelib/kernel/qvarianthash.h
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QVARIANTHASH_H
+#define QVARIANTHASH_H
+
+#if 0
+#pragma qt_class(QVariantHash)
+#endif
+
+#include <QtCore/qglobal.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QVariant>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qvariantlist.h b/src/corelib/kernel/qvariantlist.h
new file mode 100644
index 0000000000..5a567854e8
--- /dev/null
+++ b/src/corelib/kernel/qvariantlist.h
@@ -0,0 +1,19 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QVARIANTLIST_H
+#define QVARIANTLIST_H
+
+#if 0
+#pragma qt_class(QVariantList)
+#endif
+
+#include <QtCore/qglobal.h>
+
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qvariantmap.h b/src/corelib/kernel/qvariantmap.h
new file mode 100644
index 0000000000..22cb975b5c
--- /dev/null
+++ b/src/corelib/kernel/qvariantmap.h
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QVARIANTMAP_H
+#define QVARIANTMAP_H
+
+#if 0
+#pragma qt_class(QVariantMap)
+#endif
+
+#include <QtCore/qglobal.h>
+
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index b306e3aba1..afbf4227dc 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwineventnotifier_p.h"
-#include "qeventdispatcher_win_p.h"
#include "qcoreapplication.h"
-
-#include <private/qthread_p.h>
+#include "qthread.h"
+#include <QPointer>
QT_BEGIN_NAMESPACE
@@ -119,14 +82,7 @@ QWinEventNotifier::QWinEventNotifier(QObject *parent)
QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
: QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
{
- Q_D(QWinEventNotifier);
- QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
- if (Q_UNLIKELY(!eventDispatcher)) {
- qWarning("QWinEventNotifier: Can only be used with threads started with QThread");
- return;
- }
- eventDispatcher->registerEventNotifier(this);
- d->enabled = true;
+ setEnabled(true);
}
/*!
@@ -193,19 +149,31 @@ void QWinEventNotifier::setEnabled(bool enable)
return;
d->enabled = enable;
- QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
- if (!eventDispatcher) // perhaps application is shutting down
- return;
if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
return;
}
if (enable) {
- d->signaledCount = 0;
- eventDispatcher->registerEventNotifier(this);
- } else {
- eventDispatcher->unregisterEventNotifier(this);
+ // It is possible that the notifier was disabled after an event was already
+ // posted. In that case we set a state that indicates that such an obsolete
+ // event shall be ignored.
+ d->winEventActPosted.testAndSetRelaxed(QWinEventNotifierPrivate::Posted,
+ QWinEventNotifierPrivate::IgnorePosted);
+ // The notifier can't be registered, if 'enabled' flag was false.
+ // The code in the else branch ensures that.
+ Q_ASSERT(!d->registered);
+ SetThreadpoolWait(d->waitObject, d->handleToEvent, NULL);
+ d->registered = true;
+ } else if (d->registered) {
+ // Stop waiting for an event. However, there may be a callback queued
+ // already after the call.
+ SetThreadpoolWait(d->waitObject, NULL, NULL);
+ // So, to avoid a race condition after a possible call to
+ // setEnabled(true), wait for a possibly outstanding callback
+ // to complete.
+ WaitForThreadpoolWaitCallbacks(d->waitObject, TRUE);
+ d->registered = false;
}
}
@@ -216,56 +184,69 @@ void QWinEventNotifier::setEnabled(bool enable)
bool QWinEventNotifier::event(QEvent * e)
{
Q_D(QWinEventNotifier);
- if (e->type() == QEvent::ThreadChange) {
+
+ switch (e->type()) {
+ case QEvent::ThreadChange:
if (d->enabled) {
QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
Q_ARG(bool, true));
setEnabled(false);
}
- }
- QObject::event(e); // will activate filters
- if (e->type() == QEvent::WinEventAct) {
- emit activated(d->handleToEvent, QPrivateSignal());
+ break;
+ case QEvent::WinEventAct:
+ // Emit notification, but only if the event has not been invalidated
+ // since by the notifier being disabled, even if it was re-enabled
+ // again.
+ if (d->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::NotPosted)
+ == QWinEventNotifierPrivate::Posted && d->enabled) {
+ // Clear the flag, as the wait object is implicitly unregistered
+ // when the callback is queued.
+ d->registered = false;
+
+ QPointer<QWinEventNotifier> alive(this);
+ emit activated(d->handleToEvent, QPrivateSignal());
+
+ if (alive && d->enabled && !d->registered) {
+ SetThreadpoolWait(d->waitObject, d->handleToEvent, NULL);
+ d->registered = true;
+ }
+ }
return true;
+ default:
+ break;
}
- return false;
+ return QObject::event(e);
}
-static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/)
+QWinEventNotifierPrivate::QWinEventNotifierPrivate(HANDLE h, bool e)
+ : handleToEvent(h), enabled(e), registered(false)
{
- QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context);
- QAbstractEventDispatcher *eventDispatcher = nd->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
-
- // Happens when Q(Core)Application is destroyed before QWinEventNotifier.
- // https://bugreports.qt.io/browse/QTBUG-70214
- if (!eventDispatcher) { // perhaps application is shutting down
- qWarning("QWinEventNotifier: no event dispatcher, application shutting down? Cannot deliver event.");
- return;
- }
-
- QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get(
- static_cast<QEventDispatcherWin32 *>(eventDispatcher));
- ++nd->signaledCount;
- SetEvent(edp->winEventNotifierActivatedEvent);
+ waitObject = CreateThreadpoolWait(waitCallback, this, NULL);
+ if (waitObject == NULL)
+ qErrnoWarning("QWinEventNotifier:: CreateThreadpollWait failed.");
}
-bool QWinEventNotifierPrivate::registerWaitObject()
+QWinEventNotifierPrivate::~QWinEventNotifierPrivate()
{
- if (RegisterWaitForSingleObject(&waitHandle, handleToEvent, wfsoCallback, this,
- INFINITE, WT_EXECUTEONLYONCE) == 0) {
- qErrnoWarning("QWinEventNotifier: RegisterWaitForSingleObject failed.");
- return false;
- }
- return true;
+ CloseThreadpoolWait(waitObject);
}
-void QWinEventNotifierPrivate::unregisterWaitObject()
+void QWinEventNotifierPrivate::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult)
{
- // Unregister the wait handle and wait for pending callbacks to finish.
- if (UnregisterWaitEx(waitHandle, INVALID_HANDLE_VALUE))
- waitHandle = NULL;
- else
- qErrnoWarning("QWinEventNotifier: UnregisterWaitEx failed.");
+ Q_UNUSED(instance);
+ Q_UNUSED(wait);
+ Q_UNUSED(waitResult);
+ QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context);
+
+ // Do not post an event, if an event is already in the message queue. Note
+ // that an event that was previously invalidated will be reactivated.
+ if (nd->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::Posted)
+ == QWinEventNotifierPrivate::NotPosted) {
+ QCoreApplication::postEvent(nd->q_func(), new QEvent(QEvent::WinEventAct));
+ }
}
QT_END_NAMESPACE
+
+#include "moc_qwineventnotifier.cpp"
diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h
index 71a1d29057..bd0ece1f5b 100644
--- a/src/corelib/kernel/qwineventnotifier.h
+++ b/src/corelib/kernel/qwineventnotifier.h
@@ -1,48 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINEVENTNOTIFIER_H
#define QWINEVENTNOTIFIER_H
#include "QtCore/qobject.h"
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h
index 8bb2c3159a..3f78f55e61 100644
--- a/src/corelib/kernel/qwineventnotifier_p.h
+++ b/src/corelib/kernel/qwineventnotifier_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINEVENTNOTIFIER_P_H
#define QWINEVENTNOTIFIER_P_H
@@ -63,19 +27,20 @@ class QWinEventNotifierPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QWinEventNotifier)
public:
- QWinEventNotifierPrivate()
- : handleToEvent(0), enabled(false) {}
- QWinEventNotifierPrivate(HANDLE h, bool e)
- : handleToEvent(h), enabled(e) {}
+ QWinEventNotifierPrivate() : QWinEventNotifierPrivate(0, false) {}
+ QWinEventNotifierPrivate(HANDLE h, bool e);
+ virtual ~QWinEventNotifierPrivate();
- static QWinEventNotifierPrivate *get(QWinEventNotifier *q) { return q->d_func(); }
- bool registerWaitObject();
- void unregisterWaitObject();
+ static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult);
HANDLE handleToEvent;
- HANDLE waitHandle = NULL;
- QAtomicInt signaledCount;
+ PTP_WAIT waitObject = NULL;
+
+ enum PostingState { NotPosted = 0, Posted, IgnorePosted };
+ QAtomicInt winEventActPosted;
bool enabled;
+ bool registered;
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwinregistry.cpp b/src/corelib/kernel/qwinregistry.cpp
index ac3b2ec370..d237316577 100644
--- a/src/corelib/kernel/qwinregistry.cpp
+++ b/src/corelib/kernel/qwinregistry.cpp
@@ -1,52 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwinregistry_p.h"
-
#include <QtCore/qvarlengtharray.h>
-
-#include <algorithm>
+#include <QtCore/qendian.h>
+#include <QtCore/qlist.h>
QT_BEGIN_NAMESPACE
-QWinRegistryKey::QWinRegistryKey() :
- m_key(nullptr)
+QWinRegistryKey::QWinRegistryKey()
{
}
@@ -55,8 +17,8 @@ QWinRegistryKey::QWinRegistryKey() :
QWinRegistryKey::QWinRegistryKey(HKEY parentHandle, QStringView subKey,
REGSAM permissions, REGSAM access)
{
- if (RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(subKey.utf16()),
- 0, permissions | access, &m_key) != ERROR_SUCCESS) {
+ if (RegOpenKeyExW(parentHandle, reinterpret_cast<const wchar_t *>(subKey.utf16()),
+ 0, permissions | access, &m_key) != ERROR_SUCCESS) {
m_key = nullptr;
}
}
@@ -74,45 +36,99 @@ void QWinRegistryKey::close()
}
}
-QString QWinRegistryKey::stringValue(QStringView subKey) const
+QVariant QWinRegistryKey::value(QStringView subKey) const
{
- QString result;
+ // NOTE: Empty value name is allowed in Windows registry, it means the default
+ // or unnamed value of a key, you can read/write/delete such value normally.
+
if (!isValid())
- return result;
- DWORD type;
- DWORD size;
- auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
- if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, nullptr, &size) != ERROR_SUCCESS
- || (type != REG_SZ && type != REG_EXPAND_SZ) || size <= 2) {
- return result;
+ return {};
+
+ // Use nullptr when we need to access the default value.
+ const auto subKeyC = subKey.isEmpty() ? nullptr : reinterpret_cast<const wchar_t *>(subKey.utf16());
+
+ // Get the size and type of the value.
+ DWORD dataType = REG_NONE;
+ DWORD dataSize = 0;
+ LONG ret = RegQueryValueExW(m_key, subKeyC, nullptr, &dataType, nullptr, &dataSize);
+ if (ret != ERROR_SUCCESS)
+ return {};
+
+ // Workaround for rare cases where the trailing '\0' is missing.
+ if (dataType == REG_SZ || dataType == REG_EXPAND_SZ)
+ dataSize += 2;
+ else if (dataType == REG_MULTI_SZ)
+ dataSize += 4;
+
+ // Get the value.
+ QVarLengthArray<unsigned char> data(dataSize);
+ std::fill(data.data(), data.data() + dataSize, 0u);
+
+ ret = RegQueryValueExW(m_key, subKeyC, nullptr, nullptr, data.data(), &dataSize);
+ if (ret != ERROR_SUCCESS)
+ return {};
+
+ switch (dataType) {
+ case REG_SZ:
+ case REG_EXPAND_SZ: {
+ if (dataSize > 0) {
+ return QString::fromWCharArray(
+ reinterpret_cast<const wchar_t *>(data.constData()));
+ }
+ return QString();
+ }
+
+ case REG_MULTI_SZ: {
+ if (dataSize > 0) {
+ QStringList list = {};
+ int i = 0;
+ while (true) {
+ const QString str = QString::fromWCharArray(
+ reinterpret_cast<const wchar_t *>(data.constData()) + i);
+ i += str.length() + 1;
+ if (str.isEmpty())
+ break;
+ list.append(str);
+ }
+ return list;
+ }
+ return QStringList();
+ }
+
+ case REG_NONE: // No specific type, treat as binary data.
+ case REG_BINARY: {
+ if (dataSize > 0) {
+ return QString::fromWCharArray(
+ reinterpret_cast<const wchar_t *>(data.constData()), data.size() / 2);
+ }
+ return QString();
+ }
+
+ case REG_DWORD: // Same as REG_DWORD_LITTLE_ENDIAN
+ return qFromLittleEndian<quint32>(data.constData());
+
+ case REG_DWORD_BIG_ENDIAN:
+ return qFromBigEndian<quint32>(data.constData());
+
+ case REG_QWORD: // Same as REG_QWORD_LITTLE_ENDIAN
+ return qFromLittleEndian<quint64>(data.constData());
+
+ default:
+ break;
}
- // Reserve more for rare cases where trailing '\0' are missing in registry.
- // Rely on 0-termination since strings of size 256 padded with 0 have been
- // observed (QTBUG-84455).
- size += 2;
- QVarLengthArray<unsigned char> buffer(static_cast<int>(size));
- std::fill(buffer.data(), buffer.data() + size, 0u);
- if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, buffer.data(), &size) == ERROR_SUCCESS)
- result = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buffer.constData()));
- return result;
+
+ return {};
}
-QPair<DWORD, bool> QWinRegistryKey::dwordValue(QStringView subKey) const
+QString QWinRegistryKey::stringValue(QStringView subKey) const
{
- if (!isValid())
- return qMakePair(0, false);
- DWORD type;
- auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
- if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, nullptr, nullptr) != ERROR_SUCCESS
- || type != REG_DWORD) {
- return qMakePair(0, false);
- }
- DWORD value = 0;
- DWORD size = sizeof(value);
- const bool ok =
- RegQueryValueEx(m_key, subKeyC, nullptr, nullptr,
- reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS;
- return qMakePair(value, ok);
+ return value<QString>(subKey).value_or(QString());
+}
+
+std::pair<DWORD, bool> QWinRegistryKey::dwordValue(QStringView subKey) const
+{
+ const std::optional<DWORD> val = value<DWORD>(subKey);
+ return {val.value_or(0), val.has_value()};
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwinregistry_p.h b/src/corelib/kernel/qwinregistry_p.h
index d249a97988..20b2d10dd7 100644
--- a/src/corelib/kernel/qwinregistry_p.h
+++ b/src/corelib/kernel/qwinregistry_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINREGISTRY_H
#define QWINREGISTRY_H
@@ -55,33 +19,49 @@
#include <QtCore/qstring.h>
#include <QtCore/qstringview.h>
#include <QtCore/qt_windows.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QWinRegistryKey
{
-public:
Q_DISABLE_COPY(QWinRegistryKey)
+public:
QWinRegistryKey();
explicit QWinRegistryKey(HKEY parentHandle, QStringView subKey,
REGSAM permissions = KEY_READ, REGSAM access = 0);
~QWinRegistryKey();
- QWinRegistryKey(QWinRegistryKey &&other) noexcept { swap(other); }
- QWinRegistryKey &operator=(QWinRegistryKey &&other) noexcept { swap(other); return *this; }
-
+ QWinRegistryKey(QWinRegistryKey &&other) noexcept
+ : m_key(std::exchange(other.m_key, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWinRegistryKey)
void swap(QWinRegistryKey &other) noexcept { qSwap(m_key, other.m_key); }
- bool isValid() const { return m_key != nullptr; }
- operator HKEY() const { return m_key; }
+ [[nodiscard]] bool isValid() const { return m_key != nullptr; }
+
+ [[nodiscard]] HKEY handle() const { return m_key; }
+
+ operator HKEY() const { return handle(); }
+
void close();
+ [[nodiscard]] QVariant value(QStringView subKey) const;
+ template<typename T>
+ [[nodiscard]] std::optional<T> value(QStringView subKey) const
+ {
+ const QVariant var = value(subKey);
+ if (var.isValid())
+ return qvariant_cast<T>(var);
+ return std::nullopt;
+ }
+
+ // ### TODO: Remove once all usages are migrated to new interface.
QString stringValue(QStringView subKey) const;
- QPair<DWORD, bool> dwordValue(QStringView subKey) const;
+ std::pair<DWORD, bool> dwordValue(QStringView subKey) const;
private:
- HKEY m_key;
+ HKEY m_key = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/mime/generate.bat b/src/corelib/mimetypes/mime/generate.bat
deleted file mode 100644
index f63fc63693..0000000000
--- a/src/corelib/mimetypes/mime/generate.bat
+++ /dev/null
@@ -1,73 +0,0 @@
-:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-::
-:: Copyright (C) 2019 Intel Corporation.
-:: Contact: https://www.qt.io/licensing/
-::
-:: This file is part of the tools applications of the Qt Toolkit.
-::
-:: $QT_BEGIN_LICENSE:GPL-EXCEPT$
-:: Commercial License Usage
-:: Licensees holding valid commercial Qt licenses may use this file in
-:: accordance with the commercial license agreement provided with the
-:: Software or, alternatively, in accordance with the terms contained in
-:: a written agreement between you and The Qt Company. For licensing terms
-:: and conditions see https://www.qt.io/terms-conditions. For further
-:: information use the contact form at https://www.qt.io/contact-us.
-::
-:: GNU General Public License Usage
-:: Alternatively, this file may be used under the terms of the GNU
-:: General Public License version 3 as published by the Free Software
-:: Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-:: included in the packaging of this file. Please review the following
-:: information to ensure the GNU General Public License requirements will
-:: be met: https://www.gnu.org/licenses/gpl-3.0.html.
-::
-:: $QT_END_LICENSE$
-::
-:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
-@echo off
-setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
-set me=%~dp0
-
-:: Check if certain tools are in PATH
-for %%C in (gzip.exe zstd.exe perl.exe) do set %%C=%%~$PATH:C
-
-:: If perl is in PATH, just let it do everything
-if not "%perl.exe%" == "" goto PuntToPerl
-
-set COMPRESS=
-set MACRO=MIME_DATABASE_IS_UNCOMPRESSED
-if not "%gzip.exe%" == "" (
- set COMPRESS=gzip -9
- set MACRO=MIME_DATABASE_IS_GZIP
-)
-
-:: Check if zstd support was enabled
-if /i "%~1" == "--zstd" (
- shift
- if not "%zstd.exe%" == "" (
- set COMPRESS=zstd -19
- set MACRO=MIME_DATABASE_IS_ZSTD
- )
-)
-
-if not "%COMPRESS%" == "" goto CompressedCommon
-
-:: No Compression and no Perl
-:: Just hex-dump with Powershell
-powershell -ExecutionPolicy Bypass %me%hexdump.ps1 %1 %1
-exit /b %errorlevel%
-
-:CompressedCommon
-:: Compress to a temporary file, then hex-dump using Powershell
-echo #define %MACRO%
-set tempfile=generate%RANDOM%.tmp
-%COMPRESS% < %1 > %tempfile%
-powershell -ExecutionPolicy Bypass %me%hexdump.ps1 %tempfile% %1
-del %tempfile%
-exit /b %errorlevel%
-
-:PuntToPerl
-perl %me%generate.pl %*
-exit /b %errorlevel%
diff --git a/src/corelib/mimetypes/mime/generate.pl b/src/corelib/mimetypes/mime/generate.pl
deleted file mode 100644
index 1427658e59..0000000000
--- a/src/corelib/mimetypes/mime/generate.pl
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/perl
-#############################################################################
-##
-## Copyright (C) 2019 Intel Corporation.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-use strict;
-use warnings;
-use Config;
-local $/; # Enable "slurp" mode
-
-sub checkCommand($) {
- use File::Spec::Functions;
- my $cmd = $_[0] . $Config{_exe};
- for my $path (path()) {
- return 1 if -x catfile($path, $cmd);
- }
- return 0;
-}
-
-my $data;
-my $compress;
-my $macro;
-my $zlib = eval 'use Compress::Zlib; use IO::Compress::Gzip; return 1;';
-my $fname = shift @ARGV;
-
-if ($zlib) {
- # Prefer internal zlib support (useful on Windows where gzip.exe isn't
- # always presnet)
- $macro = "MIME_DATABASE_IS_GZIP";
-} elsif (checkCommand("gzip")) {
- # No builtin support for compression (old Perl?)
- $compress = "gzip -c9";
- $macro = "MIME_DATABASE_IS_GZIP";
-}
-
-# Check if Qt is being built with zstd support
-if ($fname eq "--zstd") {
- $fname = shift @ARGV;
- if (checkCommand("zstd")) {
- $compress = "zstd -cq19 -T1";
- $macro = "MIME_DATABASE_IS_ZSTD";
- }
-}
-
-# Check if xml (from xmlstarlet) is in $PATH
-my $cmd;
-if (checkCommand("xmlstarlet")) {
- # Minify the data before compressing
- $cmd = "xmlstarlet sel -D -B -t -c / $fname";
- $cmd .= "| $compress" if $compress;
-} elsif ($compress) {
- $cmd = "$compress < $fname"
-}
-if ($cmd) {
- # Run the command and read everything
- open CMD, "$cmd |";
- $data = <CMD>;
- close CMD;
- die("Failed to run $cmd") if ($? >> 8);
-} else {
- # No command, just read the file
- open F, "<$fname";
- $data = <F>;
- close F;
-}
-
-# Do we need to compress with zlib?
-if (!$compress && $zlib) {
- $data = eval q{
- use Compress::Zlib;
- use IO::Compress::Gzip qw(gzip);
- my $compressed;
- gzip \$data => \$compressed,
- Minimal => 1,
- Level => Z_BEST_COMPRESSION;
- return $compressed;
- };
-}
-
-# Now print as hex
-printf "#define %s\n", $macro if $macro;
-printf "static const unsigned char mimetype_database[] = {";
-my $i = 0;
-map {
- printf "\n " if $i++ % 12 == 0;
- printf "0x%02x, ", ord $_
-} split //, $data;
-printf "\n};\n";
-printf "static constexpr size_t MimeTypeDatabaseOriginalSize = %d;\n",
- (stat $fname)[7];
diff --git a/src/corelib/mimetypes/mime/hexdump.ps1 b/src/corelib/mimetypes/mime/hexdump.ps1
index 25ce8138fa..26fb9dd6e6 100644
--- a/src/corelib/mimetypes/mime/hexdump.ps1
+++ b/src/corelib/mimetypes/mime/hexdump.ps1
@@ -1,30 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2019 Intel Corporation.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2019 Intel Corporation.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
param([String]$path, [String]$orig)
diff --git a/src/corelib/mimetypes/mime/packages/freedesktop.org.xml b/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
index d384ffb2d5..b7aa6a1995 100644
--- a/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
+++ b/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
@@ -1,446 +1,491 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mime-info [
- <!ELEMENT mime-info (mime-type)+>
- <!ATTLIST mime-info xmlns CDATA #FIXED "http://www.freedesktop.org/standards/shared-mime-info">
-
- <!ELEMENT mime-type (comment+, (acronym,expanded-acronym)? , (icon? | generic-icon? | glob | magic | treemagic | root-XML | alias | sub-class-of)*)>
- <!ATTLIST mime-type type CDATA #REQUIRED>
-
- <!-- a comment describing a document with the respective MIME type. Example: "WMV video" -->
- <!ELEMENT comment (#PCDATA)>
- <!ATTLIST comment xml:lang CDATA #IMPLIED>
-
- <!-- a comment describing the respective unexpanded MIME type acronym. Example: "WMV" -->
- <!ELEMENT acronym (#PCDATA)>
- <!ATTLIST acronym xml:lang CDATA #IMPLIED>
-
- <!-- a comment describing the respective expanded MIME type acronym. Example: "Windows Media Video" -->
- <!ELEMENT expanded-acronym (#PCDATA)>
- <!ATTLIST expanded-acronym xml:lang CDATA #IMPLIED>
-
- <!ELEMENT icon EMPTY>
- <!ATTLIST icon name CDATA #REQUIRED>
-
- <!-- a generic icon name as per the Icon Naming Specification, only required if computing
- it from the mime-type would not work, See "generic-icon" in the Shared Mime Specification -->
- <!ELEMENT generic-icon EMPTY>
- <!ATTLIST generic-icon name (application-x-executable|audio-x-generic|folder|font-x-generic|image-x-generic|package-x-generic|text-html|text-x-generic|text-x-generic-template|text-x-script|video-x-generic|x-office-address-book|x-office-calendar|x-office-document|x-office-presentation|x-office-spreadsheet) #REQUIRED>
-
- <!ELEMENT glob EMPTY>
- <!ATTLIST glob pattern CDATA #REQUIRED>
- <!ATTLIST glob weight CDATA "50">
- <!ATTLIST glob case-sensitive CDATA #IMPLIED>
-
- <!ELEMENT magic (match)+>
- <!ATTLIST magic priority CDATA "50">
-
- <!ELEMENT match (match)*>
- <!ATTLIST match offset CDATA #REQUIRED>
- <!ATTLIST match type (string|big16|big32|little16|little32|host16|host32|byte) #REQUIRED>
- <!ATTLIST match value CDATA #REQUIRED>
- <!ATTLIST match mask CDATA #IMPLIED>
-
- <!ELEMENT treemagic (treematch)+>
- <!ATTLIST treemagic priority CDATA "50">
+<!ELEMENT mime-info (mime-type)+>
+<!ATTLIST mime-info xmlns CDATA #FIXED "http://www.freedesktop.org/standards/shared-mime-info">
+<!ELEMENT mime-type (comment+ , (acronym , expanded-acronym)? , (icon | generic-icon | glob | magic | treemagic | root-XML | alias | sub-class-of)*)>
+<!ATTLIST mime-type type CDATA #REQUIRED>
+<!-- a comment describing a document with the respective MIME type. Example: "WMV video" --><!ELEMENT comment (#PCDATA)>
+<!ATTLIST comment xml:lang CDATA #IMPLIED>
+<!-- a comment describing the respective unexpanded MIME type acronym. Example: "WMV" --><!ELEMENT acronym (#PCDATA)>
+<!-- a comment describing the respective expanded MIME type acronym. Example: "Windows Media Video" --><!ELEMENT expanded-acronym (#PCDATA)>
+<!ELEMENT icon EMPTY>
+<!ATTLIST icon name CDATA #REQUIRED>
+<!-- a generic icon name as per the Icon Naming Specification, only required if computing
+ it from the mime-type would not work, See "generic-icon" in the Shared Mime Specification --><!ELEMENT generic-icon EMPTY>
+<!ATTLIST generic-icon name (application-x-executable | audio-x-generic | emblem-symbolic-link | folder | font-x-generic | image-x-generic | media-floppy | media-optical | package-x-generic | text-html | text-x-generic | text-x-generic-template | text-x-script | video-x-generic | x-office-address-book | x-office-calendar | x-office-document | x-office-presentation | x-office-spreadsheet) #REQUIRED>
+<!ELEMENT glob EMPTY>
+<!ATTLIST glob pattern CDATA #REQUIRED>
+<!ATTLIST glob weight CDATA "50">
+<!ATTLIST glob case-sensitive CDATA #IMPLIED>
+<!ELEMENT magic (match)+>
+<!ATTLIST magic priority CDATA "50">
+<!ELEMENT match (match)*>
+<!ATTLIST match offset CDATA #REQUIRED>
+<!ATTLIST match type (string | big16 | big32 | little16 | little32 | host16 | host32 | byte) #REQUIRED>
+<!ATTLIST match value CDATA #REQUIRED>
+<!ATTLIST match mask CDATA #IMPLIED>
+<!ELEMENT treemagic (treematch)+>
+<!ATTLIST treemagic priority CDATA "50">
+<!ELEMENT treematch (treematch)*>
+<!ATTLIST treematch path CDATA #REQUIRED>
+<!ATTLIST treematch type (file | directory | link) #IMPLIED>
+<!ATTLIST treematch match-case (true | false) #IMPLIED>
+<!ATTLIST treematch executable (true | false) #IMPLIED>
+<!ATTLIST treematch non-empty (true | false) #IMPLIED>
+<!ATTLIST treematch mimetype CDATA #IMPLIED>
+<!ELEMENT root-XML EMPTY>
+<!ATTLIST root-XML namespaceURI CDATA #REQUIRED>
+<!ATTLIST root-XML localName CDATA #REQUIRED>
+<!ELEMENT alias EMPTY>
+<!ATTLIST alias type CDATA #REQUIRED>
+<!ELEMENT sub-class-of EMPTY>
+<!ATTLIST sub-class-of type CDATA #REQUIRED>
+]>
+<!--
+The freedesktop.org shared MIME database (this file) was created by merging
+several existing MIME databases (all released under the GNU GPL).
- <!ELEMENT treematch (treematch)*>
- <!ATTLIST treematch path CDATA #REQUIRED>
- <!ATTLIST treematch type (file|directory|link) #IMPLIED>
- <!ATTLIST treematch match-case (true|false) #IMPLIED>
- <!ATTLIST treematch executable (true|false) #IMPLIED>
- <!ATTLIST treematch non-empty (true|false) #IMPLIED>
- <!ATTLIST treematch mimetype CDATA #IMPLIED>
+It comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law. You may
+redistribute copies of freedesktop.org.xml under the terms of the GNU General
+Public License version 2 or later. For more information about these matters,
+see the file named COPYING.
- <!ELEMENT root-XML EMPTY>
- <!ATTLIST root-XML namespaceURI CDATA #REQUIRED>
- <!ATTLIST root-XML localName CDATA #REQUIRED>
+The latest version is available from:
- <!ELEMENT alias EMPTY>
- <!ATTLIST alias type CDATA #REQUIRED>
+ http://www.freedesktop.org/wiki/Software/shared-mime-info/
- <!ELEMENT sub-class-of EMPTY>
- <!ATTLIST sub-class-of type CDATA #REQUIRED>
-]>
+To extend this database, users and applications should create additional
+XML files in the 'packages' directory and run the update-mime-database
+command to generate the output files.
+-->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-atari-2600-rom">
- <comment>Atari 2600</comment>
- <comment xml:lang="ast">Atari 2600</comment>
- <comment xml:lang="ca">Atari 2600</comment>
- <comment xml:lang="cs">Atari 2600</comment>
- <comment xml:lang="da">Atari 2600</comment>
- <comment xml:lang="de">Atari 2600</comment>
- <comment xml:lang="en_GB">Atari 2600</comment>
- <comment xml:lang="es">Atari 2600</comment>
- <comment xml:lang="eu">Atari 2600</comment>
- <comment xml:lang="fi">Atari 2600</comment>
- <comment xml:lang="fr">Atari 2600</comment>
- <comment xml:lang="ga">Atari 2600</comment>
- <comment xml:lang="he">אטארי 2600</comment>
- <comment xml:lang="hr">Atari 2600</comment>
- <comment xml:lang="hu">Atari 2600</comment>
- <comment xml:lang="id">Atari 2600</comment>
- <comment xml:lang="it">Atari 2600</comment>
- <comment xml:lang="kk">Atari 2600</comment>
- <comment xml:lang="ko">Atari 2600</comment>
- <comment xml:lang="oc">Atari 2600</comment>
- <comment xml:lang="pl">Atari 2600</comment>
- <comment xml:lang="pt_BR">Atari 2600</comment>
- <comment xml:lang="ru">Atari 2600</comment>
- <comment xml:lang="sk">Atari 2600</comment>
- <comment xml:lang="sr">Атари 2600</comment>
- <comment xml:lang="sv">Atari 2600</comment>
- <comment xml:lang="tr">Atari 2600</comment>
- <comment xml:lang="uk">Atari 2600</comment>
- <comment xml:lang="zh_CN">雅达利 2600</comment>
- <comment xml:lang="zh_TW">Atari 2600</comment>
+ <comment>Atari 2600 ROM</comment>
+ <comment xml:lang="zh_TW">雅達利 2600 ROM</comment>
+ <comment xml:lang="zh_CN">雅达利 2600 ROM</comment>
+ <comment xml:lang="uk">Atari 2600 ROM</comment>
+ <comment xml:lang="tr">Atari 2600 ROM</comment>
+ <comment xml:lang="sv">Atari 2600-rom</comment>
+ <comment xml:lang="sr">Атари 2600 РОМ</comment>
+ <comment xml:lang="sq">ROM Atari 2600</comment>
+ <comment xml:lang="sl">Atari 2600 ROM</comment>
+ <comment xml:lang="si">Atari 2600 ROM</comment>
+ <comment xml:lang="ru">Atari 2600 ROM</comment>
+ <comment xml:lang="pt_BR">ROM do Atari 2600</comment>
+ <comment xml:lang="pt">ROM Atari 2600</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Atari 2600</comment>
+ <comment xml:lang="nl">Atari 2600-ROM</comment>
+ <comment xml:lang="ko">아타리 2600 롬</comment>
+ <comment xml:lang="kk">Atari 2600 ROM</comment>
+ <comment xml:lang="ka">Atari 2600 ROM</comment>
+ <comment xml:lang="ja">Atari 2600 ROM</comment>
+ <comment xml:lang="it">ROM Atari 2600</comment>
+ <comment xml:lang="is">Atari 2600 ROM</comment>
+ <comment xml:lang="id">Atari 2600 ROM</comment>
+ <comment xml:lang="hu">Atari 2600 ROM</comment>
+ <comment xml:lang="hr">Atari 2600 ROM</comment>
+ <comment xml:lang="he">Atari 2600 ROM</comment>
+ <comment xml:lang="gl">ROM de Atari 2600</comment>
+ <comment xml:lang="fur">ROM Atari 2600</comment>
+ <comment xml:lang="fr">ROM Atari 2600</comment>
+ <comment xml:lang="fi">Atari 2600 -ROM</comment>
+ <comment xml:lang="eu">Atari 2600 ROMa</comment>
+ <comment xml:lang="es">ROM de Atari 2600</comment>
+ <comment xml:lang="en_GB">Atari 2600 ROM</comment>
+ <comment xml:lang="de">Atari-2600-ROM</comment>
+ <comment xml:lang="da">Atari 2600-ROM</comment>
+ <comment xml:lang="ca">ROM d'Atari 2600</comment>
+ <comment xml:lang="bg">ROM — Atari 2600</comment>
+ <comment xml:lang="be">Atari 2600 ROM</comment>
+ <comment xml:lang="ar">روم Atari 2600</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.a26"/>
</mime-type>
<mime-type type="application/x-atari-7800-rom">
- <comment>Atari 7800</comment>
- <comment xml:lang="ast">Atari 7800</comment>
- <comment xml:lang="ca">Atari 7800</comment>
- <comment xml:lang="cs">Atari 7800</comment>
- <comment xml:lang="da">Atari 7800</comment>
- <comment xml:lang="de">Atari 7800</comment>
- <comment xml:lang="en_GB">Atari 7800</comment>
- <comment xml:lang="es">Atari 7800</comment>
- <comment xml:lang="eu">Atari 7800</comment>
- <comment xml:lang="fi">Atari 7800</comment>
- <comment xml:lang="fr">Atari 7800</comment>
- <comment xml:lang="ga">Atari 7800</comment>
- <comment xml:lang="he">אטארי 7800</comment>
- <comment xml:lang="hr">Atari 7800</comment>
- <comment xml:lang="hu">Atari 7800</comment>
- <comment xml:lang="id">Atari 7800</comment>
- <comment xml:lang="it">Atari 7800</comment>
- <comment xml:lang="kk">Atari 7800</comment>
- <comment xml:lang="ko">Atari 7800</comment>
- <comment xml:lang="oc">Atari 7800</comment>
- <comment xml:lang="pl">Atari 7800</comment>
- <comment xml:lang="pt_BR">Atari 7800</comment>
- <comment xml:lang="ru">Atari 7800</comment>
- <comment xml:lang="sk">Atari 7800</comment>
- <comment xml:lang="sr">Атари 7800</comment>
- <comment xml:lang="sv">Atari 7800</comment>
- <comment xml:lang="tr">Atari 7800</comment>
- <comment xml:lang="uk">Atari 7800</comment>
- <comment xml:lang="zh_CN">雅达利 7800</comment>
- <comment xml:lang="zh_TW">Atari 7800</comment>
+ <comment>Atari 7800 ROM</comment>
+ <comment xml:lang="zh_TW">雅達利 7800 ROM</comment>
+ <comment xml:lang="zh_CN">雅达利 7800 ROM</comment>
+ <comment xml:lang="uk">Atari 7800 ROM</comment>
+ <comment xml:lang="tr">Atari 7800 ROM</comment>
+ <comment xml:lang="sv">Atari 7800-rom</comment>
+ <comment xml:lang="sr">Атари 7800 РОМ</comment>
+ <comment xml:lang="sq">ROM Atari 7800</comment>
+ <comment xml:lang="sl">Atari 7800 ROM</comment>
+ <comment xml:lang="si">Atari 7800 ROM</comment>
+ <comment xml:lang="ru">Atari 7800 ROM</comment>
+ <comment xml:lang="pt_BR">ROM do Atari 7800</comment>
+ <comment xml:lang="pt">ROM Atari 7800</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Atari 7800</comment>
+ <comment xml:lang="nl">Atari 7800-ROM</comment>
+ <comment xml:lang="ko">아타리 7800 롬</comment>
+ <comment xml:lang="kk">Atari 7800 ROM</comment>
+ <comment xml:lang="ka">Atari 7800 ROM</comment>
+ <comment xml:lang="ja">Atari 7800 ROM</comment>
+ <comment xml:lang="it">ROM Atari 7800</comment>
+ <comment xml:lang="is">Atari 7800 ROM</comment>
+ <comment xml:lang="id">Atari 7800 ROM</comment>
+ <comment xml:lang="hu">Atari 7800 ROM</comment>
+ <comment xml:lang="hr">Atari 7800 ROM</comment>
+ <comment xml:lang="he">Atari 7800 ROM</comment>
+ <comment xml:lang="gl">ROM de Atari 7800</comment>
+ <comment xml:lang="fur">ROM Atari 7800</comment>
+ <comment xml:lang="fr">ROM Atari 7800</comment>
+ <comment xml:lang="fi">Atari 7800 -ROM</comment>
+ <comment xml:lang="eu">Atari 7800 ROMa</comment>
+ <comment xml:lang="es">ROM de Atari 7800</comment>
+ <comment xml:lang="en_GB">Atari 7800 ROM</comment>
+ <comment xml:lang="de">Atari-7800-ROM</comment>
+ <comment xml:lang="da">Atari 7800-ROM</comment>
+ <comment xml:lang="ca">ROM d'Atari 7800</comment>
+ <comment xml:lang="bg">ROM — Atari 7800</comment>
+ <comment xml:lang="be">Atari 7800 ROM</comment>
+ <comment xml:lang="ar">روم Atari 7800</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.a78"/>
<magic>
- <match value="ATARI7800" type="string" offset="1"/>
+ <match type="string" value="ATARI7800" offset="1"/>
</magic>
</mime-type>
<mime-type type="application/x-atari-lynx-rom">
- <comment>Atari Lynx</comment>
- <comment xml:lang="ast">Atari Lynx</comment>
- <comment xml:lang="ca">Atari Lynx</comment>
- <comment xml:lang="cs">Atari Lynx</comment>
- <comment xml:lang="de">Atari Lynx</comment>
- <comment xml:lang="en_GB">Atari Lynx</comment>
- <comment xml:lang="es">Atari Lynx</comment>
- <comment xml:lang="fi">Atari Lynx</comment>
- <comment xml:lang="hr">Atari Lynx</comment>
- <comment xml:lang="hu">Atari Lynx</comment>
- <comment xml:lang="id">Atari Lynx</comment>
- <comment xml:lang="it">Atari Lynx</comment>
- <comment xml:lang="kk">Atari Lynx</comment>
- <comment xml:lang="ko">Atari Lynx</comment>
- <comment xml:lang="pl">Atari Lynx</comment>
- <comment xml:lang="pt_BR">Atari Lynx</comment>
- <comment xml:lang="ru">Atari Lynx</comment>
- <comment xml:lang="sk">Atari Lynx</comment>
- <comment xml:lang="sv">Atari Lynx</comment>
- <comment xml:lang="uk">Atari Lynx</comment>
- <comment xml:lang="zh_CN">雅达利 Lynx</comment>
- <comment xml:lang="zh_TW">Atari Lynx</comment>
+ <comment>Atari Lynx ROM</comment>
+ <comment xml:lang="zh_TW">雅達利 Lynx ROM</comment>
+ <comment xml:lang="zh_CN">雅达利 Lynx ROM</comment>
+ <comment xml:lang="uk">Atari Lynx ROM</comment>
+ <comment xml:lang="tr">Atari Lynx ROM</comment>
+ <comment xml:lang="sv">Atari Lynx-rom</comment>
+ <comment xml:lang="sr">Атари Линкс РОМ</comment>
+ <comment xml:lang="sq">ROM Atari Lynx</comment>
+ <comment xml:lang="sl">Atari Lynx ROM</comment>
+ <comment xml:lang="si">Atari Lynx ROM</comment>
+ <comment xml:lang="ru">Atari Lynx ROM</comment>
+ <comment xml:lang="pt_BR">ROM do Atari Lynx</comment>
+ <comment xml:lang="pt">ROM Atari Lynx</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Atari Lynx</comment>
+ <comment xml:lang="nl">Atari Lynx-ROM</comment>
+ <comment xml:lang="ko">아타리 링스 롬</comment>
+ <comment xml:lang="kk">Atari Lynx ROM</comment>
+ <comment xml:lang="ka">Atari Lynx ROM</comment>
+ <comment xml:lang="ja">Atari Lynx ROM</comment>
+ <comment xml:lang="it">ROM Atari Lynx</comment>
+ <comment xml:lang="is">Atari Lynx ROM</comment>
+ <comment xml:lang="id">Atari Lynx ROM</comment>
+ <comment xml:lang="hu">Atari Lynx ROM</comment>
+ <comment xml:lang="hr">Atari Lynx ROM</comment>
+ <comment xml:lang="he">Atari Lynx ROM</comment>
+ <comment xml:lang="gl">ROM de Atari Lynx</comment>
+ <comment xml:lang="fur">ROM Atari Lynx</comment>
+ <comment xml:lang="fr">ROM Atari Lynx</comment>
+ <comment xml:lang="fi">Atari Lynx -ROM</comment>
+ <comment xml:lang="eu">Atari Lynx ROMa</comment>
+ <comment xml:lang="es">ROM de Atari Lynx</comment>
+ <comment xml:lang="en_GB">Atari Lynx ROM</comment>
+ <comment xml:lang="de">Atari-Lynx-ROM</comment>
+ <comment xml:lang="da">Atari Lynx-ROM</comment>
+ <comment xml:lang="ca">ROM d'Atari Lynx</comment>
+ <comment xml:lang="bg">ROM — Atari Lynx</comment>
+ <comment xml:lang="be">Atari Lynx ROM</comment>
+ <comment xml:lang="ar">روم Atari Lynx</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.lnx"/>
<magic>
- <match value="LYNX" type="string" offset="0"/>
+ <match type="string" value="LYNX" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/andrew-inset">
<comment>ATK inset</comment>
- <comment xml:lang="ar">شكل ATK</comment>
- <comment xml:lang="be@latin">Ustaŭka ATK</comment>
- <comment xml:lang="bg">Сбор — ATK</comment>
- <comment xml:lang="ca">ATK inset</comment>
- <comment xml:lang="cs">vložka ATK</comment>
- <comment xml:lang="da">ATK-indsættelse</comment>
- <comment xml:lang="de">ATK-Inset</comment>
- <comment xml:lang="el">Ένθετο ATK</comment>
- <comment xml:lang="en_GB">ATK inset</comment>
- <comment xml:lang="es">inserción ATK</comment>
- <comment xml:lang="eu">ATK sartzapena</comment>
- <comment xml:lang="fi">ATK-osio</comment>
- <comment xml:lang="fo">ATK innskot</comment>
- <comment xml:lang="fr">encart ATK</comment>
- <comment xml:lang="ga">intlis ATK</comment>
- <comment xml:lang="gl">conxunto ATK</comment>
- <comment xml:lang="he">תוספת ATK</comment>
- <comment xml:lang="hr">ATK umetak</comment>
- <comment xml:lang="hu">ATK betét</comment>
- <comment xml:lang="ia">Folio intercalari ATK</comment>
- <comment xml:lang="id">Inset ATK</comment>
- <comment xml:lang="it">Inset ATK</comment>
- <comment xml:lang="ja">ATK インセット</comment>
- <comment xml:lang="kk">ATK беті</comment>
- <comment xml:lang="ko">ATK inset</comment>
- <comment xml:lang="lt">ATK inset</comment>
- <comment xml:lang="lv">ATK ielaidums</comment>
- <comment xml:lang="nb">ATK-innsats</comment>
- <comment xml:lang="nl">ATK-invoegsel</comment>
- <comment xml:lang="nn">ATK-innskot</comment>
- <comment xml:lang="oc">encart ATK</comment>
- <comment xml:lang="pl">Wstawka ATK</comment>
- <comment xml:lang="pt">Suplemento ATK</comment>
- <comment xml:lang="pt_BR">Conjunto de entrada do ATK</comment>
- <comment xml:lang="ro">Inset ATK</comment>
- <comment xml:lang="ru">Вкладка ATK</comment>
- <comment xml:lang="sk">Vložka ATK</comment>
- <comment xml:lang="sl">Vložka ATK</comment>
- <comment xml:lang="sq">Inset ATK</comment>
- <comment xml:lang="sr">АТК уметак</comment>
- <comment xml:lang="sv">ATK-inlägg</comment>
- <comment xml:lang="tr">ATK iç metni</comment>
- <comment xml:lang="uk">вкладка ATK</comment>
- <comment xml:lang="vi">Bộ dát ATK</comment>
- <comment xml:lang="zh_CN">ATK 嵌入对象</comment>
<comment xml:lang="zh_TW">ATK 內嵌</comment>
+ <comment xml:lang="zh_CN">ATK 嵌入对象</comment>
+ <comment xml:lang="vi">Bộ dát ATK</comment>
+ <comment xml:lang="uk">вкладка ATK</comment>
+ <comment xml:lang="tr">ATK iç metni</comment>
+ <comment xml:lang="sv">ATK-inlägg</comment>
+ <comment xml:lang="sr">АТК уметак</comment>
+ <comment xml:lang="sl">Vložka ATK</comment>
+ <comment xml:lang="si">ATK ඇතුළු කිරීම</comment>
+ <comment xml:lang="sk">Vložka ATK</comment>
+ <comment xml:lang="ru">Вкладка ATK</comment>
+ <comment xml:lang="ro">Inset ATK</comment>
+ <comment xml:lang="pt_BR">Conjunto de entrada do ATK</comment>
+ <comment xml:lang="pt">Suplemento ATK</comment>
+ <comment xml:lang="pl">Wstawka ATK</comment>
+ <comment xml:lang="oc">encart ATK</comment>
+ <comment xml:lang="nn">ATK-innskot</comment>
+ <comment xml:lang="nl">ATK-invoegsel</comment>
+ <comment xml:lang="nb">ATK-innsats</comment>
+ <comment xml:lang="lv">ATK ielaidums</comment>
+ <comment xml:lang="lt">ATK inset</comment>
+ <comment xml:lang="ko">ATK 인세트</comment>
+ <comment xml:lang="kk">ATK беті</comment>
+ <comment xml:lang="ja">ATK インセット</comment>
+ <comment xml:lang="it">Inset ATK</comment>
+ <comment xml:lang="is">ATK innfelling</comment>
+ <comment xml:lang="id">Inset ATK</comment>
+ <comment xml:lang="ia">Folio intercalari ATK</comment>
+ <comment xml:lang="hu">ATK betét</comment>
+ <comment xml:lang="hr">ATK umetak</comment>
+ <comment xml:lang="he">תוספת ATK</comment>
+ <comment xml:lang="gl">conxunto ATK</comment>
+ <comment xml:lang="ga">intlis ATK</comment>
+ <comment xml:lang="fur">inset ATK</comment>
+ <comment xml:lang="fr">encart ATK</comment>
+ <comment xml:lang="fo">ATK innskot</comment>
+ <comment xml:lang="fi">ATK-osio</comment>
+ <comment xml:lang="eu">ATK sartzapena</comment>
+ <comment xml:lang="es">inserción ATK</comment>
+ <comment xml:lang="en_GB">ATK inset</comment>
+ <comment xml:lang="el">Ένθετο ATK</comment>
+ <comment xml:lang="de">ATK-Inset</comment>
+ <comment xml:lang="da">ATK-indsættelse</comment>
+ <comment xml:lang="cs">vložka ATK</comment>
+ <comment xml:lang="ca">ATK inset</comment>
+ <comment xml:lang="bg">Притурка — ATK</comment>
+ <comment xml:lang="be@latin">Ustaŭka ATK</comment>
+ <comment xml:lang="be">устаўка ATK</comment>
+ <comment xml:lang="ar">شكل ATK</comment>
<acronym>ATK</acronym>
<expanded-acronym>Andrew Toolkit</expanded-acronym>
<generic-icon name="x-office-document"/>
<glob pattern="*.ez"/>
</mime-type>
<mime-type type="application/epub+zip">
- <comment>electronic book document</comment>
- <comment xml:lang="ar">مستند كتاب إلكتروني</comment>
- <comment xml:lang="ast">documentu de llibru electrónicu</comment>
- <comment xml:lang="be@latin">elektronnaja kniha</comment>
- <comment xml:lang="bg">Документ — електронна книга</comment>
- <comment xml:lang="ca">document de llibre electrònic</comment>
- <comment xml:lang="cs">dokument elektronické knihy</comment>
- <comment xml:lang="da">elektronisk bogdokument</comment>
- <comment xml:lang="de">Elektronisches Buch</comment>
- <comment xml:lang="el">Έγγραφο ηλεκτρονικού βιβλίου</comment>
- <comment xml:lang="en_GB">electronic book document</comment>
- <comment xml:lang="es">documento de libro electrónico</comment>
- <comment xml:lang="eu">liburu elektronikoaren dokumentua</comment>
- <comment xml:lang="fi">elektroninen kirja</comment>
- <comment xml:lang="fo">elektroniskbóka skjal</comment>
- <comment xml:lang="fr">document livre électronique</comment>
- <comment xml:lang="ga">leabhar leictreonach</comment>
- <comment xml:lang="gl">documento de libro electrónico</comment>
- <comment xml:lang="he">מסמך מסוג ספר אלקטרוני</comment>
- <comment xml:lang="hr">Dokument elektroničke knjige</comment>
- <comment xml:lang="hu">elektronikus könyvdokumentum</comment>
- <comment xml:lang="ia">Documento de libro electronic</comment>
- <comment xml:lang="id">dokumen buku elektronik</comment>
- <comment xml:lang="it">Documento libro elettronico</comment>
- <comment xml:lang="ja">電子ブックドキュメント</comment>
- <comment xml:lang="kk">электронды кітабы</comment>
- <comment xml:lang="ko">전자책 문서</comment>
- <comment xml:lang="lt">elektroninės knygos dokumentas</comment>
- <comment xml:lang="lv">elektroniskās grāmatas dokuments</comment>
- <comment xml:lang="nl">elektronisch boek</comment>
- <comment xml:lang="nn">elektronisk bok-dokument</comment>
- <comment xml:lang="oc">document libre electronic</comment>
- <comment xml:lang="pl">Dokument książki elektronicznej</comment>
- <comment xml:lang="pt">documento de livro eletrónico</comment>
- <comment xml:lang="pt_BR">Documento de livro eletrônico</comment>
- <comment xml:lang="ro">document carte electronică</comment>
- <comment xml:lang="ru">Электронная книга</comment>
- <comment xml:lang="sk">Dokument elektronickej knihy</comment>
- <comment xml:lang="sl">dokument elektronske knjige</comment>
- <comment xml:lang="sq">Dokument libri elektronik</comment>
- <comment xml:lang="sr">документ електронске књиге</comment>
- <comment xml:lang="sv">elektroniskt bokdokument</comment>
- <comment xml:lang="tr">elektronik kitap belgesi</comment>
- <comment xml:lang="uk">документ електронної книги</comment>
- <comment xml:lang="vi">tài liệu cuốn sách điện tử</comment>
- <comment xml:lang="zh_CN">电子书文档</comment>
+ <comment>Electronic book document</comment>
<comment xml:lang="zh_TW">電子書文件</comment>
+ <comment xml:lang="uk">документ електронної книги</comment>
+ <comment xml:lang="sv">Elektroniskt bokdokument</comment>
+ <comment xml:lang="sq">Dokument libri elektronik</comment>
+ <comment xml:lang="ru">Документ электронной книги</comment>
+ <comment xml:lang="pt_BR">Documento de livro eletrônico</comment>
+ <comment xml:lang="pl">Dokument książki elektronicznej</comment>
+ <comment xml:lang="ja">電子書籍</comment>
+ <comment xml:lang="it">Documento libro elettronico</comment>
+ <comment xml:lang="gl">Documento de libro electrónico</comment>
+ <comment xml:lang="eu">Liburu elektronikoa</comment>
+ <comment xml:lang="es">documento de libro electrónico</comment>
+ <comment xml:lang="de">E-Book</comment>
+ <comment xml:lang="be">электроннай кніга</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/epub+zip" type="string" offset="38"/>
- <match value="application/epub+zip" type="string" offset="43"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/epub+zip" offset="38"/>
+ <match type="string" value="application/epub+zip" offset="43"/>
</match>
</match>
</magic>
<glob pattern="*.epub"/>
</mime-type>
+ <mime-type type="application/vnd.amazon.mobi8-ebook">
+ <comment>Kindle book document</comment>
+ <comment xml:lang="zh_TW">Kindle 書文件</comment>
+ <comment xml:lang="zh_CN">Kindle 电子书文档</comment>
+ <comment xml:lang="uk">документ книги Kindle</comment>
+ <comment xml:lang="tr">Kindle kitap belgesi</comment>
+ <comment xml:lang="sv">Kindle-bokdokument</comment>
+ <comment xml:lang="sr">Документ Киндл књиге</comment>
+ <comment xml:lang="sq">dokument libri Kindle</comment>
+ <comment xml:lang="sl">Dokument knjige Kindle</comment>
+ <comment xml:lang="si">Kindle පොත් ලේඛනය</comment>
+ <comment xml:lang="ru">Документ электронной книги Kindle</comment>
+ <comment xml:lang="pt_BR">Documento livro do Kindle</comment>
+ <comment xml:lang="pt">documento de livro eletrónico do Kindle</comment>
+ <comment xml:lang="pl">Dokument książki Kindle</comment>
+ <comment xml:lang="oc">document libre Kindle</comment>
+ <comment xml:lang="nl">Kindle-boekdocument</comment>
+ <comment xml:lang="lt">Kindle knygos dokumentas</comment>
+ <comment xml:lang="ko">Kindle 책 문서</comment>
+ <comment xml:lang="kk">Kindle кітап құжаты</comment>
+ <comment xml:lang="ja">キンドルブックドキュメント</comment>
+ <comment xml:lang="it">Documento libro Kindle</comment>
+ <comment xml:lang="is">Kindle rafbókarskjal</comment>
+ <comment xml:lang="id">Dokumen buku Kindle</comment>
+ <comment xml:lang="hu">Kindle könyvdokumentum</comment>
+ <comment xml:lang="hr">Dokument Kindle knjige</comment>
+ <comment xml:lang="he">מסמך ספר Kindle</comment>
+ <comment xml:lang="gl">Documento de libro de Kindle</comment>
+ <comment xml:lang="fr">document livre Kindle</comment>
+ <comment xml:lang="fi">Kindle book -asiakirja</comment>
+ <comment xml:lang="eu">Kindle liburu-dokumentua</comment>
+ <comment xml:lang="es">documento de libro de Kindle</comment>
+ <comment xml:lang="en_GB">Kindle book document</comment>
+ <comment xml:lang="de">Kindle E-Book</comment>
+ <comment xml:lang="da">Kindle-bogdokument</comment>
+ <comment xml:lang="ca">document de llibre Kindle</comment>
+ <comment xml:lang="be">дакумент кнігі Kindle</comment>
+ <comment xml:lang="ar">مستند كتاب كندل</comment>
+ <sub-class-of type="application/x-mobipocket-ebook"/>
+ <glob pattern="*.azw3"/>
+ <glob pattern="*.kfx"/>
+ <alias type="application/x-mobi8-ebook"/>
+ </mime-type>
<mime-type type="application/illustrator">
<comment>Adobe Illustrator document</comment>
- <comment xml:lang="ar">مستند أدوبي المصور</comment>
- <comment xml:lang="ast">Documentu d'Adobe Illustrator</comment>
- <comment xml:lang="be@latin">Dakument Adobe Illustrator</comment>
- <comment xml:lang="bg">Документ — Adobe Illustrator</comment>
- <comment xml:lang="ca">document d'Adobe Illustrator</comment>
- <comment xml:lang="cs">dokument Adobe Illustrator</comment>
- <comment xml:lang="da">Adobe Illustrator-dokument</comment>
- <comment xml:lang="de">Adobe-Illustrator-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Adobe Illustrator</comment>
- <comment xml:lang="en_GB">Adobe Illustrator document</comment>
- <comment xml:lang="eo">dokumento de Adobe Illustrator</comment>
- <comment xml:lang="es">documento de Adobe Illustrator</comment>
- <comment xml:lang="eu">Adobe Illustrator dokumentua</comment>
- <comment xml:lang="fi">Adobe Illustrator -asiakirja</comment>
- <comment xml:lang="fo">Adobe Illustrator skjal</comment>
- <comment xml:lang="fr">document Adobe Illustrator</comment>
- <comment xml:lang="ga">cáipéis Adobe Illustrator</comment>
- <comment xml:lang="gl">documento de Adobe Ilustrator</comment>
- <comment xml:lang="he">מסמך Adobe Ill</comment>
- <comment xml:lang="hr">Adobe Illustrator dokument</comment>
- <comment xml:lang="hu">Adobe Illustrator-dokumentum</comment>
- <comment xml:lang="ia">Documento Adobe Illustrator</comment>
- <comment xml:lang="id">dokumen Adobe Illustrator</comment>
- <comment xml:lang="it">Documento Adobe Illustrator</comment>
- <comment xml:lang="ja">Adobe Illustrator ドキュメント</comment>
- <comment xml:lang="ka">Adobe Illustrator-ის დოკუმენტი</comment>
- <comment xml:lang="kk">Adobe Illustrator құжаты</comment>
- <comment xml:lang="ko">Adobe Illustrator 문서</comment>
- <comment xml:lang="lt">Adobe Illustrator dokumentas</comment>
- <comment xml:lang="lv">Adobe Illustrator dokuments</comment>
- <comment xml:lang="ms">Dokumen Adobe Illustrator</comment>
- <comment xml:lang="nb">Adobe Illustrator-dokument</comment>
- <comment xml:lang="nl">Adobe Illustrator-document</comment>
- <comment xml:lang="nn">Adobe Illustrator-dokument</comment>
- <comment xml:lang="oc">document Adobe Illustrator</comment>
- <comment xml:lang="pl">Dokument Adobe Illustrator</comment>
- <comment xml:lang="pt">documento Adobe Illustrator</comment>
- <comment xml:lang="pt_BR">Documento do Adobe Illustrator</comment>
- <comment xml:lang="ro">Document Adobe Illustrator</comment>
- <comment xml:lang="ru">Документ Adobe Illustrator</comment>
- <comment xml:lang="sk">Dokument Adobe Illustrator</comment>
- <comment xml:lang="sl">Dokument Adobe Illustrator</comment>
- <comment xml:lang="sq">Dokument Adobe Illustrator</comment>
- <comment xml:lang="sr">документ Адобе илустратора</comment>
- <comment xml:lang="sv">Adobe Illustrator-dokument</comment>
- <comment xml:lang="tr">Adobe Illustrator belgesi</comment>
- <comment xml:lang="uk">документ Adobe Illustrator</comment>
- <comment xml:lang="vi">Tài liệu Adobe Illustrator</comment>
- <comment xml:lang="zh_CN">Adobe Illustrator 文档</comment>
<comment xml:lang="zh_TW">Adobe Illustrator 文件</comment>
+ <comment xml:lang="zh_CN">Adobe Illustrator 文档</comment>
+ <comment xml:lang="vi">Tài liệu Adobe Illustrator</comment>
+ <comment xml:lang="uk">документ Adobe Illustrator</comment>
+ <comment xml:lang="tr">Adobe Illustrator belgesi</comment>
+ <comment xml:lang="sv">Adobe Illustrator-dokument</comment>
+ <comment xml:lang="sr">документ Адобе илустратора</comment>
+ <comment xml:lang="sq">dokument Adobe Illustrator</comment>
+ <comment xml:lang="sl">Dokument Adobe Illustrator</comment>
+ <comment xml:lang="si">Adobe Illustrator ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Adobe Illustrator</comment>
+ <comment xml:lang="ru">Документ Adobe Illustrator</comment>
+ <comment xml:lang="ro">Document Adobe Illustrator</comment>
+ <comment xml:lang="pt_BR">Documento do Adobe Illustrator</comment>
+ <comment xml:lang="pt">documento Adobe Illustrator</comment>
+ <comment xml:lang="pl">Dokument Adobe Illustrator</comment>
+ <comment xml:lang="oc">document Adobe Illustrator</comment>
+ <comment xml:lang="nn">Adobe Illustrator-dokument</comment>
+ <comment xml:lang="nl">Adobe Illustrator-document</comment>
+ <comment xml:lang="nb">Adobe Illustrator-dokument</comment>
+ <comment xml:lang="ms">Dokumen Adobe Illustrator</comment>
+ <comment xml:lang="lv">Adobe Illustrator dokuments</comment>
+ <comment xml:lang="lt">Adobe Illustrator dokumentas</comment>
+ <comment xml:lang="ko">Adobe Illustrator 문서</comment>
+ <comment xml:lang="kk">Adobe Illustrator құжаты</comment>
+ <comment xml:lang="ka">Adobe Illustrator-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Adobe Illustrator ドキュメント</comment>
+ <comment xml:lang="it">Documento Adobe Illustrator</comment>
+ <comment xml:lang="is">Adobe Illustrator skjal</comment>
+ <comment xml:lang="id">Dokumen Adobe Illustrator</comment>
+ <comment xml:lang="ia">Documento Adobe Illustrator</comment>
+ <comment xml:lang="hu">Adobe Illustrator-dokumentum</comment>
+ <comment xml:lang="hr">Adobe Illustrator dokument</comment>
+ <comment xml:lang="he">מסמך Adobe Ill</comment>
+ <comment xml:lang="gl">documento de Adobe Ilustrator</comment>
+ <comment xml:lang="ga">cáipéis Adobe Illustrator</comment>
+ <comment xml:lang="fur">document Adobe Illustrator</comment>
+ <comment xml:lang="fr">document Adobe Illustrator</comment>
+ <comment xml:lang="fo">Adobe Illustrator skjal</comment>
+ <comment xml:lang="fi">Adobe Illustrator -asiakirja</comment>
+ <comment xml:lang="eu">Adobe Illustrator dokumentua</comment>
+ <comment xml:lang="es">documento de Adobe Illustrator</comment>
+ <comment xml:lang="eo">dokumento de Adobe Illustrator</comment>
+ <comment xml:lang="en_GB">Adobe Illustrator document</comment>
+ <comment xml:lang="el">Έγγραφο Adobe Illustrator</comment>
+ <comment xml:lang="de">Adobe-Illustrator-Dokument</comment>
+ <comment xml:lang="da">Adobe Illustrator-dokument</comment>
+ <comment xml:lang="cs">dokument Adobe Illustrator</comment>
+ <comment xml:lang="ca">document d'Adobe Illustrator</comment>
+ <comment xml:lang="bg">Документ — Adobe Illustrator</comment>
+ <comment xml:lang="be@latin">Dakument Adobe Illustrator</comment>
+ <comment xml:lang="be">дакумент Adobe Illustrator</comment>
+ <comment xml:lang="ast">Documentu d'Adobe Illustrator</comment>
+ <comment xml:lang="ar">مستند أدوبي إليستريتور</comment>
+ <comment xml:lang="af">Adobe Illustrator-dokument</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.ai"/>
<alias type="application/vnd.adobe.illustrator"/>
</mime-type>
<mime-type type="application/mac-binhex40">
<comment>Macintosh BinHex-encoded file</comment>
- <comment xml:lang="ar">ملف Macintosh BinHex مشفر</comment>
- <comment xml:lang="ast">Ficheru codificáu en BinHex de Machintosh</comment>
- <comment xml:lang="az">Macintosh BinHex-kodlanmış fayl</comment>
- <comment xml:lang="be@latin">Fajł Macintosh, BinHex-zakadavany</comment>
- <comment xml:lang="bg">Файл — кодиран във формат BinHex за Macintosh</comment>
- <comment xml:lang="ca">fitxer amb codificació BinHex de Macintosh</comment>
- <comment xml:lang="cs">soubor kódovaný pomocí Macintosh BinHex</comment>
- <comment xml:lang="cy">Ffeil BinHex-amgodwyd Macintosh</comment>
- <comment xml:lang="da">Macintosh BinHex-kodet fil</comment>
- <comment xml:lang="de">Macintosh-Datei (BinHex-kodiert)</comment>
- <comment xml:lang="el">Αρχείο Macintosh κωδικοποίησης BinHex</comment>
- <comment xml:lang="en_GB">Macintosh BinHex-encoded file</comment>
- <comment xml:lang="eo">dosiero kodigita laŭ Macintosh BinHex</comment>
- <comment xml:lang="es">archivo Macintosh codificado con BinHex</comment>
- <comment xml:lang="eu">Macintosh BinHex-ekin kodetutako fitxategia</comment>
- <comment xml:lang="fi">Macintosh BinHex -koodattu tiedosto</comment>
- <comment xml:lang="fo">Macintosh BinHex-bronglað fíla</comment>
- <comment xml:lang="fr">fichier codé Macintosh BinHex</comment>
- <comment xml:lang="ga">comhad ionchódaithe le Macintosh BinHex</comment>
- <comment xml:lang="gl">ficheiro de Macintosh codificado con BinHex</comment>
- <comment xml:lang="he">קובץ בקידוד Macintosh BinHex</comment>
- <comment xml:lang="hr">Macintosh BinHex-kôdirana datoteka</comment>
- <comment xml:lang="hu">Macintosh BinHex kódolású fájl</comment>
- <comment xml:lang="ia">File codificate in BinHex de Macintosh</comment>
- <comment xml:lang="id">berkas tersandi Macintosh BinHex</comment>
- <comment xml:lang="it">File Macintosh codificato BinHex</comment>
- <comment xml:lang="ja">Macintosh BinHex エンコードファイル</comment>
- <comment xml:lang="kk">Macintosh BinHex кодталған файлы</comment>
- <comment xml:lang="ko">매킨토시 BinHex 인코딩된 압축 파일</comment>
- <comment xml:lang="lt">Macintosh BinHex-encoded failas</comment>
- <comment xml:lang="lv">Macintosh BinHex-kodēts datne</comment>
- <comment xml:lang="ms">Fail terenkod-BinHex Macintosh</comment>
- <comment xml:lang="nb">Macintosh BinHe-kodet arkiv</comment>
- <comment xml:lang="nl">Macintosh BinHex-gecodeerd bestand</comment>
- <comment xml:lang="nn">Macintosh BinHex-koda fil</comment>
- <comment xml:lang="oc">fichièr encodat Macintosh BinHex</comment>
- <comment xml:lang="pl">Zakodowany w BinHex plik Macintosh</comment>
- <comment xml:lang="pt">ficheiro codificado em BinHex de Macintosh</comment>
- <comment xml:lang="pt_BR">Arquivo do Macintosh codificado com BinHex</comment>
- <comment xml:lang="ro">Fișier codat Macintosh BinHex</comment>
- <comment xml:lang="ru">Файл (закодированный Macintosh BinHex)</comment>
- <comment xml:lang="sk">Súbor kódovaný pomocou Macintosh BinHex</comment>
- <comment xml:lang="sl">Kodirana datoteka Macintosh (BinHex)</comment>
- <comment xml:lang="sq">File Macintosh i kodifikuar BinHex</comment>
- <comment xml:lang="sr">Мекинтошова БинХекс-кодирана датотека</comment>
- <comment xml:lang="sv">Macintosh BinHex-kodad fil</comment>
- <comment xml:lang="tr">Macintosh BinHex-şifreli dosya</comment>
- <comment xml:lang="uk">файл закодований Macintosh BinHex</comment>
- <comment xml:lang="vi">Tập tin đã mã hoá BinHex của Macintosh</comment>
- <comment xml:lang="zh_CN">Macintosh BinHex 编码的文件</comment>
<comment xml:lang="zh_TW">Macintosh BinHex 編碼檔</comment>
+ <comment xml:lang="zh_CN">Macintosh BinHex 编码的文件</comment>
+ <comment xml:lang="vi">Tập tin đã mã hoá BinHex của Macintosh</comment>
+ <comment xml:lang="uk">файл закодований Macintosh BinHex</comment>
+ <comment xml:lang="tr">Macintosh BinHex-şifreli dosya</comment>
+ <comment xml:lang="sv">Macintosh BinHex-kodad fil</comment>
+ <comment xml:lang="sr">Мекинтошова БинХекс-кодирана датотека</comment>
+ <comment xml:lang="sq">kartelë Macintosh koduar me BinHex</comment>
+ <comment xml:lang="sl">Kodirana datoteka Macintosh (BinHex)</comment>
+ <comment xml:lang="si">Macintosh BinHex-කේතනය කළ ගොනුව</comment>
+ <comment xml:lang="sk">Súbor kódovaný pomocou Macintosh BinHex</comment>
+ <comment xml:lang="ru">Файл Macintosh закодированный BinHex</comment>
+ <comment xml:lang="ro">Fișier codat Macintosh BinHex</comment>
+ <comment xml:lang="pt_BR">Arquivo do Macintosh codificado com BinHex</comment>
+ <comment xml:lang="pt">ficheiro codificado em BinHex de Macintosh</comment>
+ <comment xml:lang="pl">Zakodowany w BinHex plik Macintosh</comment>
+ <comment xml:lang="oc">fichièr encodat Macintosh BinHex</comment>
+ <comment xml:lang="nn">Macintosh BinHex-koda fil</comment>
+ <comment xml:lang="nl">Macintosh BinHex-gecodeerd bestand</comment>
+ <comment xml:lang="nb">Macintosh BinHe-kodet arkiv</comment>
+ <comment xml:lang="ms">Fail terenkod-BinHex Macintosh</comment>
+ <comment xml:lang="lv">Macintosh BinHex-kodēts datne</comment>
+ <comment xml:lang="lt">Macintosh BinHex-encoded failas</comment>
+ <comment xml:lang="ko">매킨토시 BinHex 인코딩된 압축 파일</comment>
+ <comment xml:lang="kk">Macintosh BinHex кодталған файлы</comment>
+ <comment xml:lang="ja">Macintosh BinHex エンコードファイル</comment>
+ <comment xml:lang="it">File Macintosh codificato BinHex</comment>
+ <comment xml:lang="is">Macintosh BinHex-kóðuð skrá</comment>
+ <comment xml:lang="id">Berkas tersandi Macintosh BinHex</comment>
+ <comment xml:lang="ia">File codificate in BinHex de Macintosh</comment>
+ <comment xml:lang="hu">Macintosh BinHex kódolású fájl</comment>
+ <comment xml:lang="hr">Macintosh BinHex-kôdirana datoteka</comment>
+ <comment xml:lang="he">קובץ בקידוד Macintosh BinHex</comment>
+ <comment xml:lang="gl">ficheiro de Macintosh codificado con BinHex</comment>
+ <comment xml:lang="ga">comhad ionchódaithe le Macintosh BinHex</comment>
+ <comment xml:lang="fur">file di Macintosh codificât BinHex</comment>
+ <comment xml:lang="fr">fichier codé Macintosh BinHex</comment>
+ <comment xml:lang="fo">Macintosh BinHex-bronglað fíla</comment>
+ <comment xml:lang="fi">Macintosh BinHex -koodattu tiedosto</comment>
+ <comment xml:lang="eu">Macintosh BinHex-ekin kodetutako fitxategia</comment>
+ <comment xml:lang="es">archivo Macintosh codificado con BinHex</comment>
+ <comment xml:lang="eo">dosiero kodigita laŭ Macintosh BinHex</comment>
+ <comment xml:lang="en_GB">Macintosh BinHex-encoded file</comment>
+ <comment xml:lang="el">Αρχείο Macintosh κωδικοποίησης BinHex</comment>
+ <comment xml:lang="de">Macintosh-Datei (BinHex-verschlüsselt)</comment>
+ <comment xml:lang="da">Macintosh BinHex-kodet fil</comment>
+ <comment xml:lang="cy">Ffeil BinHex-amgodwyd Macintosh</comment>
+ <comment xml:lang="cs">soubor kódovaný pomocí Macintosh BinHex</comment>
+ <comment xml:lang="ca">fitxer amb codificació BinHex de Macintosh</comment>
+ <comment xml:lang="bg">Файл — кодиран във формат BinHex за Macintosh</comment>
+ <comment xml:lang="be@latin">Fajł Macintosh, BinHex-zakadavany</comment>
+ <comment xml:lang="be">файл з кадаваннем Macintosh BinHex</comment>
+ <comment xml:lang="az">Macintosh BinHex-kodlanmış fayl</comment>
+ <comment xml:lang="ast">Ficheru codificáu en BinHex de Machintosh</comment>
+ <comment xml:lang="ar">ملف Macintosh BinHex مشفر</comment>
+ <comment xml:lang="af">Macintosh BinHex-geënkodeerde lêer</comment>
+ <sub-class-of type="text/plain"/>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="must be converted with BinHex" type="string" offset="11"/>
+ <magic>
+ <match type="string" value="(This file must be converted with BinHex 4.0)" offset="0"/>
+ <match type="string" value="(This file must be converted; you knew that already.)" offset="0"/>
</magic>
+ <glob pattern="*.hqx"/>
</mime-type>
<mime-type type="application/mathematica">
- <comment>Mathematica Notebook</comment>
- <comment xml:lang="ar">مذكرة رياضيات</comment>
- <comment xml:lang="be@latin">Natatnik Mathematica</comment>
- <comment xml:lang="bg">Тетрадка — Mathematica</comment>
- <comment xml:lang="ca">llibreta de notes de Mathematica</comment>
- <comment xml:lang="cs">sešit Mathematica</comment>
- <comment xml:lang="da">Mathematica Notebook</comment>
- <comment xml:lang="de">Mathematica-Dokument</comment>
- <comment xml:lang="el">Σημειωματάριο Mathematica</comment>
- <comment xml:lang="en_GB">Mathematica Notebook</comment>
- <comment xml:lang="es">libreta de Mathematica</comment>
- <comment xml:lang="eu">Mathematica Notebook</comment>
- <comment xml:lang="fi">Mathematica-muistilehtiö</comment>
- <comment xml:lang="fo">Mathematica skriviblokkur</comment>
- <comment xml:lang="fr">carnet de notes Mathematica</comment>
- <comment xml:lang="ga">leabhar nótaí Mathematica</comment>
- <comment xml:lang="gl">notebook de Mathematica</comment>
- <comment xml:lang="he">מחברת מתמטיקה</comment>
- <comment xml:lang="hr">Matematička bilježnica</comment>
- <comment xml:lang="hu">Mathematica notesz</comment>
- <comment xml:lang="ia">Carnet de notas Mathematica</comment>
- <comment xml:lang="id">Mathematica Notebook</comment>
- <comment xml:lang="it">Notebook Mathematica</comment>
- <comment xml:lang="ja">Mathematica ノートブック</comment>
- <comment xml:lang="kk">Mathematica Notebook</comment>
- <comment xml:lang="ko">Mathematica 노트북</comment>
- <comment xml:lang="lt">Mathematica užrašinė</comment>
- <comment xml:lang="lv">Mathematica bloknots</comment>
- <comment xml:lang="nb">Mathematica notisblokk</comment>
- <comment xml:lang="nl">Mathematica-notitieboek</comment>
- <comment xml:lang="nn">Mathematica-notatbok</comment>
- <comment xml:lang="oc">quasernet de nòtas Mathematica</comment>
- <comment xml:lang="pl">Notatnik Mathematica</comment>
- <comment xml:lang="pt">Bloco notas Mathematica</comment>
- <comment xml:lang="pt_BR">Caderno do Mathematica</comment>
- <comment xml:lang="ro">Carnețel Mathematica</comment>
- <comment xml:lang="ru">Mathematica Notebook</comment>
- <comment xml:lang="sk">Zošit programu Mathematica</comment>
- <comment xml:lang="sl">Datoteka dokumenta Mathematica</comment>
- <comment xml:lang="sq">Notebook matematike</comment>
- <comment xml:lang="sr">бележница Математике</comment>
- <comment xml:lang="sv">Mathematica Notebook-dokument</comment>
- <comment xml:lang="tr">Mathematica Defteri</comment>
- <comment xml:lang="uk">математичний записник</comment>
- <comment xml:lang="vi">Cuốn vở Mathematica</comment>
- <comment xml:lang="zh_CN">Mathematica 笔记本</comment>
- <comment xml:lang="zh_TW">Mathematica Notebook</comment>
+ <comment>Mathematica Notebook file</comment>
+ <comment xml:lang="zh_TW">Mathematica 筆記本檔案</comment>
+ <comment xml:lang="zh_CN">Mathematica 笔记本文件</comment>
+ <comment xml:lang="uk">файл нотатника Mathematica</comment>
+ <comment xml:lang="tr">Mathematica Notebook dosyası</comment>
+ <comment xml:lang="sv">Mathematica-anteckningsboksfil</comment>
+ <comment xml:lang="sq">kartelë Mathematica Notebook</comment>
+ <comment xml:lang="sl">Datoteka Mathematica Notebook</comment>
+ <comment xml:lang="si">Mathematica Notebook ගොනුව</comment>
+ <comment xml:lang="ru">Файл Mathematica Notebook</comment>
+ <comment xml:lang="pt_BR">Arquivo Notebook do Mathematica</comment>
+ <comment xml:lang="pt">ficheiro de Mathematica Notebook do Wolfram</comment>
+ <comment xml:lang="pl">Plik notatnika Mathematica</comment>
+ <comment xml:lang="nl">Mathematica Notebook-bestand</comment>
+ <comment xml:lang="ko">Mathematica 기록장 파일</comment>
+ <comment xml:lang="kk">Mathematica блокнот файлы</comment>
+ <comment xml:lang="ka">Mathematica Notebook-ის ფაილი</comment>
+ <comment xml:lang="ja">Mathematica ノートブックファイル</comment>
+ <comment xml:lang="it">File Mathematica Notebook</comment>
+ <comment xml:lang="is">Mathematica Notebook skrá</comment>
+ <comment xml:lang="id">Berkas Mathematica Notebook</comment>
+ <comment xml:lang="hu">Mathematica munkafüzetfájl</comment>
+ <comment xml:lang="hr">Mathematica Notebook datoteka</comment>
+ <comment xml:lang="he">קובץ מחברת של Mathematica</comment>
+ <comment xml:lang="gl">Ficheiro de caderno de Mathematica</comment>
+ <comment xml:lang="fr">fichier carnet Mathematica</comment>
+ <comment xml:lang="fi">Mathematica Notebook -tiedosto</comment>
+ <comment xml:lang="eu">Mathematica Notebook fitxategia</comment>
+ <comment xml:lang="es">archivo de Mathematica Notebook</comment>
+ <comment xml:lang="en_GB">Mathematica Notebook file</comment>
+ <comment xml:lang="de">Mathematica-Notebook-Datei</comment>
+ <comment xml:lang="da">Mathematica Notebook-fil</comment>
+ <comment xml:lang="ca">llibreta de Mathematica Notebook</comment>
+ <comment xml:lang="bg">Скицник — Mathematica</comment>
+ <comment xml:lang="be">файл Mathematica Notebook</comment>
+ <comment xml:lang="ar">ملف دفتر ماثماتيكا</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.nb"/>
- <magic priority="50">
+ <magic>
<match value="(************** Content-type: application/mathematica" type="string" offset="0"/>
<match value="This notebook can be used on any computer system with Mathematica" type="string" offset="100:256"/>
<match value="This is a Mathematica Notebook file. It contains ASCII text" type="string" offset="10:256"/>
@@ -449,58 +494,63 @@
</mime-type>
<mime-type type="application/mathml+xml">
<comment>MathML document</comment>
- <comment xml:lang="ar">مستند MathML</comment>
- <comment xml:lang="ast">Documentu MathML</comment>
- <comment xml:lang="az">MathML sənədi</comment>
- <comment xml:lang="be@latin">Dakument MathML</comment>
- <comment xml:lang="bg">Документ — MathML</comment>
- <comment xml:lang="ca">document MathML</comment>
- <comment xml:lang="cs">dokument MathML</comment>
- <comment xml:lang="cy">Dogfen MathML</comment>
- <comment xml:lang="da">MathML-dokument</comment>
- <comment xml:lang="de">MathML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο MathML</comment>
- <comment xml:lang="en_GB">MathML document</comment>
- <comment xml:lang="eo">MathML-dokumento</comment>
- <comment xml:lang="es">documento MathML</comment>
- <comment xml:lang="eu">MathML dokumentua</comment>
- <comment xml:lang="fi">MathML-asiakirja</comment>
- <comment xml:lang="fo">MathML skjal</comment>
- <comment xml:lang="fr">document MathML</comment>
- <comment xml:lang="ga">cáipéis MathML</comment>
- <comment xml:lang="gl">documento de MathML</comment>
- <comment xml:lang="he">מסמך MathML</comment>
- <comment xml:lang="hr">MathML dokument</comment>
- <comment xml:lang="hu">MathML-dokumentum</comment>
- <comment xml:lang="ia">Documento MathML</comment>
- <comment xml:lang="id">dokumen MathML</comment>
- <comment xml:lang="it">Documento MathML</comment>
- <comment xml:lang="ja">MathML ドキュメント</comment>
- <comment xml:lang="ka">MathML-ის დოკუმენტი</comment>
- <comment xml:lang="kk">MathML құжаты</comment>
- <comment xml:lang="ko">MathML 문서</comment>
- <comment xml:lang="lt">MathML dokumentas</comment>
- <comment xml:lang="lv">MathML dokuments</comment>
- <comment xml:lang="ms">Dokumen MathML</comment>
- <comment xml:lang="nb">MathML-dokument</comment>
- <comment xml:lang="nl">MathML-document</comment>
- <comment xml:lang="nn">MathML-dokument</comment>
- <comment xml:lang="oc">document MathML</comment>
- <comment xml:lang="pl">Dokument MathML</comment>
- <comment xml:lang="pt">documento MathML</comment>
- <comment xml:lang="pt_BR">Documento do MathML</comment>
- <comment xml:lang="ro">Document MathML</comment>
- <comment xml:lang="ru">Документ MathML</comment>
- <comment xml:lang="sk">Dokument MathML</comment>
- <comment xml:lang="sl">Dokument MathML</comment>
- <comment xml:lang="sq">Dokument MathML</comment>
- <comment xml:lang="sr">МатМЛ документ</comment>
- <comment xml:lang="sv">MathML-dokument</comment>
- <comment xml:lang="tr">MathML belgesi</comment>
- <comment xml:lang="uk">документ MathML</comment>
- <comment xml:lang="vi">Tài liệu MathML</comment>
- <comment xml:lang="zh_CN">MathML 文档</comment>
<comment xml:lang="zh_TW">MathML 文件</comment>
+ <comment xml:lang="zh_CN">MathML 文档</comment>
+ <comment xml:lang="vi">Tài liệu MathML</comment>
+ <comment xml:lang="uk">документ MathML</comment>
+ <comment xml:lang="tr">MathML belgesi</comment>
+ <comment xml:lang="sv">MathML-dokument</comment>
+ <comment xml:lang="sr">МатМЛ документ</comment>
+ <comment xml:lang="sq">dokument MathML</comment>
+ <comment xml:lang="sl">Dokument MathML</comment>
+ <comment xml:lang="si">MathML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument MathML</comment>
+ <comment xml:lang="ru">Документ MathML</comment>
+ <comment xml:lang="ro">Document MathML</comment>
+ <comment xml:lang="pt_BR">Documento do MathML</comment>
+ <comment xml:lang="pt">documento MathML</comment>
+ <comment xml:lang="pl">Dokument MathML</comment>
+ <comment xml:lang="oc">document MathML</comment>
+ <comment xml:lang="nn">MathML-dokument</comment>
+ <comment xml:lang="nl">MathML-document</comment>
+ <comment xml:lang="nb">MathML-dokument</comment>
+ <comment xml:lang="ms">Dokumen MathML</comment>
+ <comment xml:lang="lv">MathML dokuments</comment>
+ <comment xml:lang="lt">MathML dokumentas</comment>
+ <comment xml:lang="ko">MathML 문서</comment>
+ <comment xml:lang="kk">MathML құжаты</comment>
+ <comment xml:lang="ka">MathML-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">MathML ドキュメント</comment>
+ <comment xml:lang="it">Documento MathML</comment>
+ <comment xml:lang="is">MathML skjal</comment>
+ <comment xml:lang="id">Dokumen MathML</comment>
+ <comment xml:lang="ia">Documento MathML</comment>
+ <comment xml:lang="hu">MathML-dokumentum</comment>
+ <comment xml:lang="hr">MathML dokument</comment>
+ <comment xml:lang="he">מסמך MathML</comment>
+ <comment xml:lang="gl">documento de MathML</comment>
+ <comment xml:lang="ga">cáipéis MathML</comment>
+ <comment xml:lang="fur">document MathML</comment>
+ <comment xml:lang="fr">document MathML</comment>
+ <comment xml:lang="fo">MathML skjal</comment>
+ <comment xml:lang="fi">MathML-asiakirja</comment>
+ <comment xml:lang="eu">MathML dokumentua</comment>
+ <comment xml:lang="es">documento MathML</comment>
+ <comment xml:lang="eo">MathML-dokumento</comment>
+ <comment xml:lang="en_GB">MathML document</comment>
+ <comment xml:lang="el">Έγγραφο MathML</comment>
+ <comment xml:lang="de">MathML-Dokument</comment>
+ <comment xml:lang="da">MathML-dokument</comment>
+ <comment xml:lang="cy">Dogfen MathML</comment>
+ <comment xml:lang="cs">dokument MathML</comment>
+ <comment xml:lang="ca">document MathML</comment>
+ <comment xml:lang="bg">Документ — MathML</comment>
+ <comment xml:lang="be@latin">Dakument MathML</comment>
+ <comment xml:lang="be">дакумент MathML</comment>
+ <comment xml:lang="az">MathML sənədi</comment>
+ <comment xml:lang="ast">Documentu MathML</comment>
+ <comment xml:lang="ar">مستند MathML</comment>
+ <comment xml:lang="af">MathML-dokument</comment>
<acronym>MathML</acronym>
<expanded-acronym>Mathematical Markup Language</expanded-acronym>
<alias type="text/mathml"/>
@@ -509,253 +559,210 @@
<root-XML namespaceURI="http://www.w3.org/1998/Math/MathML" localName="math"/>
</mime-type>
<mime-type type="application/mbox">
- <comment>mailbox file</comment>
- <comment xml:lang="ar">ملف صندوق البريد</comment>
- <comment xml:lang="be@latin">fajł paštovaj skryni</comment>
- <comment xml:lang="bg">Файл — Mailbox</comment>
- <comment xml:lang="ca">fitxer mailbox</comment>
- <comment xml:lang="cs">soubor mailbox</comment>
- <comment xml:lang="da">postkassefil</comment>
- <comment xml:lang="de">Mailbox-Datei</comment>
- <comment xml:lang="el">Αρχείο mailbox</comment>
- <comment xml:lang="en_GB">mailbox file</comment>
- <comment xml:lang="es">archivo de buzón de correo</comment>
- <comment xml:lang="eu">mailbox fitxategia</comment>
- <comment xml:lang="fi">mailbox-tiedosto</comment>
- <comment xml:lang="fo">postkassafíla</comment>
- <comment xml:lang="fr">fichier boîte aux lettres</comment>
- <comment xml:lang="ga">comhad bhosca poist</comment>
- <comment xml:lang="gl">ficheiro de caixa de correo</comment>
- <comment xml:lang="he">קובץ תיבת-דואר</comment>
- <comment xml:lang="hr">Datoteka poštanskog sandučića</comment>
- <comment xml:lang="hu">mailbox fájl</comment>
- <comment xml:lang="ia">File de cassa postal</comment>
- <comment xml:lang="id">berkas kotak surat</comment>
- <comment xml:lang="it">File mailbox</comment>
- <comment xml:lang="ja">メールボックスファイル</comment>
- <comment xml:lang="kk">пошта жәшігінің файлы</comment>
- <comment xml:lang="ko">메일함 파일</comment>
- <comment xml:lang="lt">pašto dėžutės failas</comment>
- <comment xml:lang="lv">pastkastītes datne</comment>
- <comment xml:lang="nb">postboksfil</comment>
- <comment xml:lang="nl">mailbox-bestand</comment>
- <comment xml:lang="nn">mailbox-fil</comment>
- <comment xml:lang="oc">fichièr bóstia de letras</comment>
- <comment xml:lang="pl">Plik poczty (Mailbox)</comment>
- <comment xml:lang="pt">ficheiro de caixa de correio</comment>
- <comment xml:lang="pt_BR">Arquivo de caixa de correio</comment>
- <comment xml:lang="ro">fișier căsuță poștală</comment>
- <comment xml:lang="ru">Файл почтового ящика</comment>
- <comment xml:lang="sk">Súbor mailbox</comment>
- <comment xml:lang="sl">datoteka poštnega predala</comment>
- <comment xml:lang="sq">File mailbox</comment>
- <comment xml:lang="sr">датотека поштанског сандучета</comment>
- <comment xml:lang="sv">brevlådefil</comment>
- <comment xml:lang="tr">posta kutusu dosyası</comment>
+ <comment>Mailbox file</comment>
<comment xml:lang="uk">файл поштової скриньки</comment>
- <comment xml:lang="vi">tập tin hộp thư</comment>
- <comment xml:lang="zh_CN">邮箱文件</comment>
- <comment xml:lang="zh_TW">郵箱檔</comment>
+ <comment xml:lang="sv">Brevlådefil</comment>
+ <comment xml:lang="sq">Kartelë kutie email-esh</comment>
+ <comment xml:lang="ru">Файл почтового ящика</comment>
+ <comment xml:lang="pt_BR">Arquivo de caixa de correio</comment>
+ <comment xml:lang="pl">Plik poczty (Mailbox)</comment>
+ <comment xml:lang="ja">電子郵便</comment>
+ <comment xml:lang="it">File mailbox</comment>
+ <comment xml:lang="gl">Ficheiro Mailbox</comment>
+ <comment xml:lang="eu">Mailbox fitxategia</comment>
+ <comment xml:lang="es">archivo de buzón de correo</comment>
+ <comment xml:lang="de">Mailbox-Datei</comment>
+ <comment xml:lang="be">файл паштовай скрынкі</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
<magic priority="20">
- <match value="From " type="string" offset="0"/>
+ <match type="string" value="From " offset="0"/>
</magic>
<glob pattern="*.mbox"/>
</mime-type>
<mime-type type="application/metalink+xml">
<comment>Metalink file</comment>
- <comment xml:lang="ar">ملف ميتالنك</comment>
- <comment xml:lang="ast">Ficheru d'enllaz meta</comment>
- <comment xml:lang="bg">Изтегляне — Metalink</comment>
- <comment xml:lang="ca">fitxer Metalink</comment>
- <comment xml:lang="cs">soubor metalink</comment>
- <comment xml:lang="da">Metahenvisningsfil</comment>
- <comment xml:lang="de">Metalink-Datei</comment>
- <comment xml:lang="el">Αρχείο Metalink</comment>
- <comment xml:lang="en_GB">Metalink file</comment>
- <comment xml:lang="eo">Metalink-dosiero</comment>
- <comment xml:lang="es">archivo de Metalink</comment>
- <comment xml:lang="eu">Metaestekaren fitxategia</comment>
- <comment xml:lang="fi">Metalink-tiedosto</comment>
- <comment xml:lang="fo">Metalink fíla</comment>
- <comment xml:lang="fr">fichier metalink</comment>
- <comment xml:lang="ga">comhad Metalink</comment>
- <comment xml:lang="gl">ficheiro Metalink</comment>
- <comment xml:lang="he">קובץ Metalink</comment>
- <comment xml:lang="hr">Datoteka meta poveznice</comment>
- <comment xml:lang="hu">Metalink fájl</comment>
- <comment xml:lang="ia">File Metalink</comment>
- <comment xml:lang="id">berkas Metalink</comment>
- <comment xml:lang="it">File Metalink</comment>
- <comment xml:lang="ja">Metalink ファイル</comment>
- <comment xml:lang="kk">Metalink файлы</comment>
- <comment xml:lang="ko">Metalink 파일</comment>
- <comment xml:lang="lt">Metalink failas</comment>
- <comment xml:lang="lv">Metalink datne</comment>
- <comment xml:lang="nl">Metalink bestand</comment>
- <comment xml:lang="oc">fichièr metalink</comment>
- <comment xml:lang="pl">Plik Metalink</comment>
- <comment xml:lang="pt">ficheiro Metalink</comment>
- <comment xml:lang="pt_BR">Arquivo Metalink</comment>
- <comment xml:lang="ro">Fișier Metalink</comment>
- <comment xml:lang="ru">Файл Metalink</comment>
- <comment xml:lang="sk">Súbor Metalink</comment>
- <comment xml:lang="sl">Datoteka povezave Metalink</comment>
- <comment xml:lang="sr">датотека метавезе</comment>
- <comment xml:lang="sv">Metalink-fil</comment>
- <comment xml:lang="tr">Metalink dosyası</comment>
- <comment xml:lang="uk">файл метапосилання</comment>
- <comment xml:lang="zh_CN">Metalink 文件</comment>
<comment xml:lang="zh_TW">Metalink 檔案</comment>
+ <comment xml:lang="zh_CN">Metalink 文件</comment>
+ <comment xml:lang="uk">файл метапосилання</comment>
+ <comment xml:lang="tr">Metalink dosyası</comment>
+ <comment xml:lang="sv">Metalink-fil</comment>
+ <comment xml:lang="sr">датотека метавезе</comment>
+ <comment xml:lang="sq">kartelë Metalink</comment>
+ <comment xml:lang="sl">Datoteka povezave Metalink</comment>
+ <comment xml:lang="si">Metalink ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Metalink</comment>
+ <comment xml:lang="ru">Файл Metalink</comment>
+ <comment xml:lang="ro">Fișier Metalink</comment>
+ <comment xml:lang="pt_BR">Arquivo Metalink</comment>
+ <comment xml:lang="pt">ficheiro Metalink</comment>
+ <comment xml:lang="pl">Plik Metalink</comment>
+ <comment xml:lang="oc">fichièr metalink</comment>
+ <comment xml:lang="nl">Metalink-bestand</comment>
+ <comment xml:lang="lv">Metalink datne</comment>
+ <comment xml:lang="lt">Metalink failas</comment>
+ <comment xml:lang="ko">Metalink 파일</comment>
+ <comment xml:lang="kk">Metalink файлы</comment>
+ <comment xml:lang="ka">მეტაბმულის ფაილი</comment>
+ <comment xml:lang="ja">Metalink ファイル</comment>
+ <comment xml:lang="it">File Metalink</comment>
+ <comment xml:lang="is">Metalink skrá</comment>
+ <comment xml:lang="id">Berkas Metalink</comment>
+ <comment xml:lang="ia">File Metalink</comment>
+ <comment xml:lang="hu">Metalink fájl</comment>
+ <comment xml:lang="hr">Datoteka meta poveznice</comment>
+ <comment xml:lang="he">קובץ Metalink</comment>
+ <comment xml:lang="gl">ficheiro Metalink</comment>
+ <comment xml:lang="ga">comhad Metalink</comment>
+ <comment xml:lang="fur">file Metalink</comment>
+ <comment xml:lang="fr">fichier metalink</comment>
+ <comment xml:lang="fo">Metalink fíla</comment>
+ <comment xml:lang="fi">Metalink-tiedosto</comment>
+ <comment xml:lang="eu">Metaestekaren fitxategia</comment>
+ <comment xml:lang="es">archivo de Metalink</comment>
+ <comment xml:lang="eo">Metalink-dosiero</comment>
+ <comment xml:lang="en_GB">Metalink file</comment>
+ <comment xml:lang="el">Αρχείο Metalink</comment>
+ <comment xml:lang="de">Metalink-Datei</comment>
+ <comment xml:lang="da">Metahenvisningsfil</comment>
+ <comment xml:lang="cs">soubor metalink</comment>
+ <comment xml:lang="ca">fitxer Metalink</comment>
+ <comment xml:lang="bg">Изтегляне — Metalink</comment>
+ <comment xml:lang="be">файл Metalink</comment>
+ <comment xml:lang="ast">Ficheru d'enllaz meta</comment>
+ <comment xml:lang="ar">ملف ميتالنك</comment>
+ <comment xml:lang="af">Metalink-lêer</comment>
<sub-class-of type="application/xml"/>
- <magic priority="50">
- <match value="&lt;metalink version=&quot;3.0&quot;" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;metalink version=&quot;3.0&quot;" offset="0:256"/>
</magic>
<glob pattern="*.metalink"/>
<root-XML namespaceURI="http://www.metalinker.org/" localName="metalink"/>
</mime-type>
<mime-type type="application/metalink4+xml">
<comment>Metalink file</comment>
- <comment xml:lang="ar">ملف ميتالنك</comment>
- <comment xml:lang="ast">Ficheru d'enllaz meta</comment>
- <comment xml:lang="bg">Изтегляне — Metalink</comment>
- <comment xml:lang="ca">fitxer Metalink</comment>
- <comment xml:lang="cs">soubor metalink</comment>
- <comment xml:lang="da">Metahenvisningsfil</comment>
- <comment xml:lang="de">Metalink-Datei</comment>
- <comment xml:lang="el">Αρχείο Metalink</comment>
- <comment xml:lang="en_GB">Metalink file</comment>
- <comment xml:lang="eo">Metalink-dosiero</comment>
- <comment xml:lang="es">archivo de Metalink</comment>
- <comment xml:lang="eu">Metaestekaren fitxategia</comment>
- <comment xml:lang="fi">Metalink-tiedosto</comment>
- <comment xml:lang="fo">Metalink fíla</comment>
- <comment xml:lang="fr">fichier metalink</comment>
- <comment xml:lang="ga">comhad Metalink</comment>
- <comment xml:lang="gl">ficheiro Metalink</comment>
- <comment xml:lang="he">קובץ Metalink</comment>
- <comment xml:lang="hr">Datoteka meta poveznice</comment>
- <comment xml:lang="hu">Metalink fájl</comment>
- <comment xml:lang="ia">File Metalink</comment>
- <comment xml:lang="id">berkas Metalink</comment>
- <comment xml:lang="it">File Metalink</comment>
- <comment xml:lang="ja">Metalink ファイル</comment>
- <comment xml:lang="kk">Metalink файлы</comment>
- <comment xml:lang="ko">Metalink 파일</comment>
- <comment xml:lang="lt">Metalink failas</comment>
- <comment xml:lang="lv">Metalink datne</comment>
- <comment xml:lang="nl">Metalink bestand</comment>
- <comment xml:lang="oc">fichièr metalink</comment>
- <comment xml:lang="pl">Plik Metalink</comment>
- <comment xml:lang="pt">ficheiro Metalink</comment>
- <comment xml:lang="pt_BR">Arquivo Metalink</comment>
- <comment xml:lang="ro">Fișier Metalink</comment>
- <comment xml:lang="ru">Файл Metalink</comment>
- <comment xml:lang="sk">Súbor Metalink</comment>
- <comment xml:lang="sl">Datoteka povezave Metalink</comment>
- <comment xml:lang="sr">датотека метавезе</comment>
- <comment xml:lang="sv">Metalink-fil</comment>
- <comment xml:lang="tr">Metalink dosyası</comment>
- <comment xml:lang="uk">файл метапосилання</comment>
- <comment xml:lang="zh_CN">Metalink 文件</comment>
<comment xml:lang="zh_TW">Metalink 檔案</comment>
+ <comment xml:lang="zh_CN">Metalink 文件</comment>
+ <comment xml:lang="uk">файл метапосилання</comment>
+ <comment xml:lang="tr">Metalink dosyası</comment>
+ <comment xml:lang="sv">Metalink-fil</comment>
+ <comment xml:lang="sr">датотека метавезе</comment>
+ <comment xml:lang="sq">kartelë Metalink</comment>
+ <comment xml:lang="sl">Datoteka povezave Metalink</comment>
+ <comment xml:lang="si">Metalink ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Metalink</comment>
+ <comment xml:lang="ru">Файл Metalink</comment>
+ <comment xml:lang="ro">Fișier Metalink</comment>
+ <comment xml:lang="pt_BR">Arquivo Metalink</comment>
+ <comment xml:lang="pt">ficheiro Metalink</comment>
+ <comment xml:lang="pl">Plik Metalink</comment>
+ <comment xml:lang="oc">fichièr metalink</comment>
+ <comment xml:lang="nl">Metalink-bestand</comment>
+ <comment xml:lang="lv">Metalink datne</comment>
+ <comment xml:lang="lt">Metalink failas</comment>
+ <comment xml:lang="ko">Metalink 파일</comment>
+ <comment xml:lang="kk">Metalink файлы</comment>
+ <comment xml:lang="ka">მეტაბმულის ფაილი</comment>
+ <comment xml:lang="ja">Metalink ファイル</comment>
+ <comment xml:lang="it">File Metalink</comment>
+ <comment xml:lang="is">Metalink skrá</comment>
+ <comment xml:lang="id">Berkas Metalink</comment>
+ <comment xml:lang="ia">File Metalink</comment>
+ <comment xml:lang="hu">Metalink fájl</comment>
+ <comment xml:lang="hr">Datoteka meta poveznice</comment>
+ <comment xml:lang="he">קובץ Metalink</comment>
+ <comment xml:lang="gl">ficheiro Metalink</comment>
+ <comment xml:lang="ga">comhad Metalink</comment>
+ <comment xml:lang="fur">file Metalink</comment>
+ <comment xml:lang="fr">fichier metalink</comment>
+ <comment xml:lang="fo">Metalink fíla</comment>
+ <comment xml:lang="fi">Metalink-tiedosto</comment>
+ <comment xml:lang="eu">Metaestekaren fitxategia</comment>
+ <comment xml:lang="es">archivo de Metalink</comment>
+ <comment xml:lang="eo">Metalink-dosiero</comment>
+ <comment xml:lang="en_GB">Metalink file</comment>
+ <comment xml:lang="el">Αρχείο Metalink</comment>
+ <comment xml:lang="de">Metalink-Datei</comment>
+ <comment xml:lang="da">Metahenvisningsfil</comment>
+ <comment xml:lang="cs">soubor metalink</comment>
+ <comment xml:lang="ca">fitxer Metalink</comment>
+ <comment xml:lang="bg">Изтегляне — Metalink</comment>
+ <comment xml:lang="be">файл Metalink</comment>
+ <comment xml:lang="ast">Ficheru d'enllaz meta</comment>
+ <comment xml:lang="ar">ملف ميتالنك</comment>
+ <comment xml:lang="af">Metalink-lêer</comment>
<sub-class-of type="application/xml"/>
- <magic priority="50">
- <match value="&lt;metalink xmlns=&quot;urn" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;metalink xmlns=&quot;urn" offset="0:256"/>
</magic>
<glob pattern="*.meta4"/>
<root-XML namespaceURI="urn:ietf:params:xml:ns:metalink" localName="metalink"/>
</mime-type>
<mime-type type="application/octet-stream">
- <comment>unknown</comment>
- <comment xml:lang="ar">مجهول</comment>
- <comment xml:lang="ast">desconozse</comment>
- <comment xml:lang="be@latin">nieviadomy</comment>
- <comment xml:lang="bg">Неизвестен тип</comment>
- <comment xml:lang="ca">desconegut</comment>
- <comment xml:lang="cs">neznámý</comment>
- <comment xml:lang="da">ukendt</comment>
- <comment xml:lang="de">unbekannt</comment>
- <comment xml:lang="el">Άγνωστο</comment>
- <comment xml:lang="en_GB">unknown</comment>
- <comment xml:lang="eo">nekonate</comment>
- <comment xml:lang="es">desconocido</comment>
- <comment xml:lang="eu">ezezaguna</comment>
- <comment xml:lang="fi">tuntematon</comment>
- <comment xml:lang="fo">ókent</comment>
- <comment xml:lang="fr">inconnu</comment>
- <comment xml:lang="ga">anaithnid</comment>
- <comment xml:lang="gl">descoñecido</comment>
- <comment xml:lang="he">לא ידוע</comment>
- <comment xml:lang="hr">Nepoznato</comment>
- <comment xml:lang="hu">ismeretlen</comment>
- <comment xml:lang="ia">incognite</comment>
- <comment xml:lang="id">tak diketahui</comment>
- <comment xml:lang="it">Sconosciuto</comment>
- <comment xml:lang="ja">不明</comment>
- <comment xml:lang="ka">უცნობი</comment>
- <comment xml:lang="kk">белгісіз</comment>
- <comment xml:lang="ko">알 수 없음</comment>
- <comment xml:lang="lt">nežinoma</comment>
- <comment xml:lang="lv">nezināms</comment>
- <comment xml:lang="ms">Entah</comment>
- <comment xml:lang="nb">ukjent</comment>
- <comment xml:lang="nl">onbekend</comment>
- <comment xml:lang="nn">ukjend</comment>
- <comment xml:lang="oc">desconegut</comment>
- <comment xml:lang="pl">Nieznany typ</comment>
- <comment xml:lang="pt">desconhecido</comment>
- <comment xml:lang="pt_BR">Desconhecido</comment>
- <comment xml:lang="ro">necunoscut</comment>
+ <comment>Unknown</comment>
+ <comment xml:lang="zh_TW">未知</comment>
+ <comment xml:lang="uk">невідомий</comment>
+ <comment xml:lang="sv">Okänd</comment>
+ <comment xml:lang="sq">I panjohur</comment>
<comment xml:lang="ru">Неизвестно</comment>
- <comment xml:lang="sk">Neznámy</comment>
- <comment xml:lang="sl">neznano</comment>
- <comment xml:lang="sq">Nuk njihet</comment>
- <comment xml:lang="sr">непознато</comment>
- <comment xml:lang="sv">okänd</comment>
- <comment xml:lang="tr">bilinmeyen</comment>
- <comment xml:lang="uk">невідомо</comment>
- <comment xml:lang="vi">không rõ</comment>
- <comment xml:lang="zh_CN">未知</comment>
- <comment xml:lang="zh_TW">不明</comment>
+ <comment xml:lang="pt_BR">Desconhecido</comment>
+ <comment xml:lang="pl">Nieznany typ</comment>
+ <comment xml:lang="ja">不明</comment>
+ <comment xml:lang="it">Sconosciuto</comment>
+ <comment xml:lang="gl">Descoñecido</comment>
+ <comment xml:lang="eu">Ezezaguna</comment>
+ <comment xml:lang="es">desconocido</comment>
+ <comment xml:lang="de">Unbekannt</comment>
+ <comment xml:lang="be">невядома</comment>
</mime-type>
<mime-type type="application/x-partial-download">
<comment>Partially downloaded file</comment>
- <comment xml:lang="ast">Ficheru baxáu parcialmente</comment>
- <comment xml:lang="ca">fitxer baixat parcialment</comment>
- <comment xml:lang="cs">částečně stažený soubor</comment>
- <comment xml:lang="da">Delvist hentet fil</comment>
- <comment xml:lang="de">Teilweise heruntergeladene Datei</comment>
- <comment xml:lang="el">Μερικώς ληφθέντο αρχείο</comment>
- <comment xml:lang="en_GB">Partially downloaded file</comment>
- <comment xml:lang="es">archivo descargado parcialmente</comment>
- <comment xml:lang="eu">Partzialki deskargatutako fitxategia</comment>
- <comment xml:lang="fi">Osittain ladattu tiedosto</comment>
- <comment xml:lang="fr">fichier partiellement téléchargé</comment>
- <comment xml:lang="ga">Comhad leath-íoslódáilte</comment>
- <comment xml:lang="gl">Ficheiro descargado parcialmente</comment>
- <comment xml:lang="he">קובץ שהתקבל חלקית</comment>
- <comment xml:lang="hr">Djelomično preuzeta datoteka</comment>
- <comment xml:lang="hu">Részben letöltött fájl</comment>
- <comment xml:lang="ia">File partialmente discargate</comment>
- <comment xml:lang="id">Berkas yang terunduh sebagian</comment>
- <comment xml:lang="it">File parzialmente scaricato</comment>
- <comment xml:lang="kk">Жартылай жүктелген файл</comment>
- <comment xml:lang="ko">일부 다운로드한 파일</comment>
- <comment xml:lang="oc">fichièr parcialament telecargat</comment>
- <comment xml:lang="pl">Częściowo pobrany plik</comment>
- <comment xml:lang="pt">Ficheiro parcialmente transferido</comment>
- <comment xml:lang="pt_BR">Arquivo baixado parcialmente</comment>
- <comment xml:lang="ru">Частично загруженный файл</comment>
- <comment xml:lang="sk">Čiastočne stiahnutý súbor</comment>
- <comment xml:lang="sl">Delno prenesena datoteka</comment>
- <comment xml:lang="sr">делимично преузета датотека</comment>
- <comment xml:lang="sv">Delvis hämtad fil</comment>
- <comment xml:lang="tr">Kısmen indirilmiş dosya</comment>
- <comment xml:lang="uk">частково отриманий файл</comment>
- <comment xml:lang="zh_CN">部分下载的文件</comment>
<comment xml:lang="zh_TW">已部份下載的檔案</comment>
+ <comment xml:lang="zh_CN">部分下载的文件</comment>
+ <comment xml:lang="uk">частково отриманий файл</comment>
+ <comment xml:lang="tr">Kısmen indirilmiş dosya</comment>
+ <comment xml:lang="sv">Delvis hämtad fil</comment>
+ <comment xml:lang="sr">делимично преузета датотека</comment>
+ <comment xml:lang="sq">Kartelë e shkarkuar pjesërisht</comment>
+ <comment xml:lang="sl">Delno prenesena datoteka</comment>
+ <comment xml:lang="si">අර්ධ වශයෙන් බාගත කළ ගොනුව</comment>
+ <comment xml:lang="sk">Čiastočne stiahnutý súbor</comment>
+ <comment xml:lang="ru">Частично загруженный файл</comment>
+ <comment xml:lang="pt_BR">Arquivo baixado parcialmente</comment>
+ <comment xml:lang="pt">ficheiro descarregado parcialmente</comment>
+ <comment xml:lang="pl">Częściowo pobrany plik</comment>
+ <comment xml:lang="oc">fichièr parcialament telecargat</comment>
+ <comment xml:lang="nl">Gedeeltelijk gedownload bestand</comment>
+ <comment xml:lang="lt">Dalinai atsiųstas failas</comment>
+ <comment xml:lang="ko">일부 다운로드한 파일</comment>
+ <comment xml:lang="kk">Жартылай жүктелген файл</comment>
+ <comment xml:lang="ka">ნაწილობრივ გადმოწერილი ფაილი</comment>
+ <comment xml:lang="ja">部分的にダウンロードされたファイル</comment>
+ <comment xml:lang="it">File parzialmente scaricato</comment>
+ <comment xml:lang="is">skrá sótt að hluta</comment>
+ <comment xml:lang="id">Berkas yang terunduh sebagian</comment>
+ <comment xml:lang="ia">File partialmente discargate</comment>
+ <comment xml:lang="hu">Részben letöltött fájl</comment>
+ <comment xml:lang="hr">Djelomično preuzeta datoteka</comment>
+ <comment xml:lang="he">קובץ שהתקבל חלקית</comment>
+ <comment xml:lang="gl">Ficheiro descargado parcialmente</comment>
+ <comment xml:lang="ga">Comhad leath-íoslódáilte</comment>
+ <comment xml:lang="fur">file no discjariât dal dut</comment>
+ <comment xml:lang="fr">fichier partiellement téléchargé</comment>
+ <comment xml:lang="fi">Osittain ladattu tiedosto</comment>
+ <comment xml:lang="eu">Partzialki deskargatutako fitxategia</comment>
+ <comment xml:lang="es">archivo descargado parcialmente</comment>
+ <comment xml:lang="en_GB">Partially downloaded file</comment>
+ <comment xml:lang="el">Μερικώς ληφθέντο αρχείο</comment>
+ <comment xml:lang="de">Teilweise heruntergeladene Datei</comment>
+ <comment xml:lang="da">Delvist downloadet fil</comment>
+ <comment xml:lang="cs">částečně stažený soubor</comment>
+ <comment xml:lang="ca">fitxer baixat parcialment</comment>
+ <comment xml:lang="bg">Частично изтеглен файл</comment>
+ <comment xml:lang="be">часткова спампаваны файл</comment>
+ <comment xml:lang="ast">Ficheru baxáu parcialmente</comment>
+ <comment xml:lang="ar">ملف منزل جزئياً</comment>
+ <comment xml:lang="af">Gedeeltelik afgelaaide lêer</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.wkdownload"/>
<glob pattern="*.crdownload"/>
@@ -763,58 +770,63 @@
</mime-type>
<mime-type type="application/oda">
<comment>ODA document</comment>
- <comment xml:lang="ar">مستند ODA</comment>
- <comment xml:lang="ast">Documentu ODA</comment>
- <comment xml:lang="az">ODA sənədi</comment>
- <comment xml:lang="be@latin">Dakument ODA</comment>
- <comment xml:lang="bg">Документ — ODA</comment>
- <comment xml:lang="ca">document ODA</comment>
- <comment xml:lang="cs">dokument ODA</comment>
- <comment xml:lang="cy">Dogfen ODA</comment>
- <comment xml:lang="da">ODA-dokument</comment>
- <comment xml:lang="de">ODA-Dokument</comment>
- <comment xml:lang="el">Έγγραφο ODA</comment>
- <comment xml:lang="en_GB">ODA document</comment>
- <comment xml:lang="eo">ODA-dokumento</comment>
- <comment xml:lang="es">documento ODA</comment>
- <comment xml:lang="eu">ODA dokumentua</comment>
- <comment xml:lang="fi">ODA-asiakirja</comment>
- <comment xml:lang="fo">ODA skjal</comment>
- <comment xml:lang="fr">document ODA</comment>
- <comment xml:lang="ga">cáipéis ODA</comment>
- <comment xml:lang="gl">documento ODA</comment>
- <comment xml:lang="he">מסמך ODA</comment>
- <comment xml:lang="hr">ODA dokument</comment>
- <comment xml:lang="hu">ODA-dokumentum</comment>
- <comment xml:lang="ia">Documento ODA</comment>
- <comment xml:lang="id">Dokumen ODA</comment>
- <comment xml:lang="it">Documento ODA</comment>
- <comment xml:lang="ja">ODA ドキュメント</comment>
- <comment xml:lang="ka">ODA დოკუმენტი</comment>
- <comment xml:lang="kk">ODA құжаты</comment>
- <comment xml:lang="ko">ODA 문서</comment>
- <comment xml:lang="lt">ODA dokumentas</comment>
- <comment xml:lang="lv">ODA dokuments</comment>
- <comment xml:lang="ms">Dokumen ODA</comment>
- <comment xml:lang="nb">ODA-dokument</comment>
- <comment xml:lang="nl">ODA-document</comment>
- <comment xml:lang="nn">ODA-dokument</comment>
- <comment xml:lang="oc">document ODA</comment>
- <comment xml:lang="pl">Dokument ODA</comment>
- <comment xml:lang="pt">documento ODA</comment>
- <comment xml:lang="pt_BR">Documento ODA</comment>
- <comment xml:lang="ro">Document ODA</comment>
- <comment xml:lang="ru">Документ ODA</comment>
- <comment xml:lang="sk">Dokument ODA</comment>
- <comment xml:lang="sl">Dokument ODA</comment>
- <comment xml:lang="sq">Dokument ODA</comment>
- <comment xml:lang="sr">ОДА документ</comment>
- <comment xml:lang="sv">ODA-dokument</comment>
- <comment xml:lang="tr">ODA belgesi</comment>
- <comment xml:lang="uk">документ ODA</comment>
- <comment xml:lang="vi">Tài liệu ODA</comment>
- <comment xml:lang="zh_CN">ODA 文档</comment>
<comment xml:lang="zh_TW">ODA 文件</comment>
+ <comment xml:lang="zh_CN">ODA 文档</comment>
+ <comment xml:lang="vi">Tài liệu ODA</comment>
+ <comment xml:lang="uk">документ ODA</comment>
+ <comment xml:lang="tr">ODA belgesi</comment>
+ <comment xml:lang="sv">ODA-dokument</comment>
+ <comment xml:lang="sr">ОДА документ</comment>
+ <comment xml:lang="sq">dokument ODA</comment>
+ <comment xml:lang="sl">Dokument ODA</comment>
+ <comment xml:lang="si">ODA ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument ODA</comment>
+ <comment xml:lang="ru">Документ ODA</comment>
+ <comment xml:lang="ro">Document ODA</comment>
+ <comment xml:lang="pt_BR">Documento ODA</comment>
+ <comment xml:lang="pt">documento ODA</comment>
+ <comment xml:lang="pl">Dokument ODA</comment>
+ <comment xml:lang="oc">document ODA</comment>
+ <comment xml:lang="nn">ODA-dokument</comment>
+ <comment xml:lang="nl">ODA-document</comment>
+ <comment xml:lang="nb">ODA-dokument</comment>
+ <comment xml:lang="ms">Dokumen ODA</comment>
+ <comment xml:lang="lv">ODA dokuments</comment>
+ <comment xml:lang="lt">ODA dokumentas</comment>
+ <comment xml:lang="ko">ODA 문서</comment>
+ <comment xml:lang="kk">ODA құжаты</comment>
+ <comment xml:lang="ka">ODA დოკუმენტი</comment>
+ <comment xml:lang="ja">ODA ドキュメント</comment>
+ <comment xml:lang="it">Documento ODA</comment>
+ <comment xml:lang="is">ODA skjal</comment>
+ <comment xml:lang="id">Dokumen ODA</comment>
+ <comment xml:lang="ia">Documento ODA</comment>
+ <comment xml:lang="hu">ODA-dokumentum</comment>
+ <comment xml:lang="hr">ODA dokument</comment>
+ <comment xml:lang="he">מסמך ODA</comment>
+ <comment xml:lang="gl">documento ODA</comment>
+ <comment xml:lang="ga">cáipéis ODA</comment>
+ <comment xml:lang="fur">document ODA</comment>
+ <comment xml:lang="fr">document ODA</comment>
+ <comment xml:lang="fo">ODA skjal</comment>
+ <comment xml:lang="fi">ODA-asiakirja</comment>
+ <comment xml:lang="eu">ODA dokumentua</comment>
+ <comment xml:lang="es">documento ODA</comment>
+ <comment xml:lang="eo">ODA-dokumento</comment>
+ <comment xml:lang="en_GB">ODA document</comment>
+ <comment xml:lang="el">Έγγραφο ODA</comment>
+ <comment xml:lang="de">ODA-Dokument</comment>
+ <comment xml:lang="da">ODA-dokument</comment>
+ <comment xml:lang="cy">Dogfen ODA</comment>
+ <comment xml:lang="cs">dokument ODA</comment>
+ <comment xml:lang="ca">document ODA</comment>
+ <comment xml:lang="bg">Документ — ODA</comment>
+ <comment xml:lang="be@latin">Dakument ODA</comment>
+ <comment xml:lang="be">дакумент ODA</comment>
+ <comment xml:lang="az">ODA sənədi</comment>
+ <comment xml:lang="ast">Documentu ODA</comment>
+ <comment xml:lang="ar">مستند ODA</comment>
+ <comment xml:lang="af">ODA-dokument</comment>
<acronym>ODA</acronym>
<expanded-acronym>Office Document Architecture</expanded-acronym>
<generic-icon name="x-office-document"/>
@@ -822,46 +834,54 @@
</mime-type>
<mime-type type="application/x-wwf">
<comment>WWF document</comment>
- <comment xml:lang="ast">Documentu WWF</comment>
- <comment xml:lang="bg">Документ — WWF</comment>
- <comment xml:lang="ca">document WWF</comment>
- <comment xml:lang="cs">dokument WWF</comment>
- <comment xml:lang="da">WWF-dokument</comment>
- <comment xml:lang="de">WWF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο WWF</comment>
- <comment xml:lang="en_GB">WWF document</comment>
- <comment xml:lang="eo">WWF-dokumento</comment>
- <comment xml:lang="es">documento WWF</comment>
- <comment xml:lang="eu">WWF dokumentua</comment>
- <comment xml:lang="fi">WWF-asiakirja</comment>
- <comment xml:lang="fr">document WWF</comment>
- <comment xml:lang="ga">cáipéis WWF</comment>
- <comment xml:lang="gl">documento de WWF</comment>
- <comment xml:lang="he">מסמך WWF</comment>
- <comment xml:lang="hr">WWF dokument</comment>
- <comment xml:lang="hu">WWF-dokumentum</comment>
- <comment xml:lang="ia">Documento WWF</comment>
- <comment xml:lang="id">Dokumen WWF</comment>
- <comment xml:lang="it">Documento WWF</comment>
- <comment xml:lang="ja">WWF 文書</comment>
- <comment xml:lang="ka">WWF დოკუმენტი</comment>
- <comment xml:lang="kk">WWF құжаты</comment>
- <comment xml:lang="ko">WWF 문서</comment>
- <comment xml:lang="lv">WWF dokuments</comment>
- <comment xml:lang="nl">WWF document</comment>
- <comment xml:lang="oc">document WWF</comment>
- <comment xml:lang="pl">Dokument WWF</comment>
- <comment xml:lang="pt">documento WWF</comment>
- <comment xml:lang="pt_BR">Documento WWF</comment>
- <comment xml:lang="ru">Документ WWF</comment>
- <comment xml:lang="sk">Dokument WWF</comment>
- <comment xml:lang="sl">Dokument WWF</comment>
- <comment xml:lang="sr">ВВФ документ</comment>
- <comment xml:lang="sv">WWF-dokument</comment>
- <comment xml:lang="tr">WWF belgesi</comment>
- <comment xml:lang="uk">документ WWF</comment>
- <comment xml:lang="zh_CN">WWF</comment>
<comment xml:lang="zh_TW">WWF 文件</comment>
+ <comment xml:lang="zh_CN">WWF</comment>
+ <comment xml:lang="uk">документ WWF</comment>
+ <comment xml:lang="tr">WWF belgesi</comment>
+ <comment xml:lang="sv">WWF-dokument</comment>
+ <comment xml:lang="sr">ВВФ документ</comment>
+ <comment xml:lang="sq">dokument WWF</comment>
+ <comment xml:lang="sl">Dokument WWF</comment>
+ <comment xml:lang="si">WWF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument WWF</comment>
+ <comment xml:lang="ru">Документ WWF</comment>
+ <comment xml:lang="pt_BR">Documento WWF</comment>
+ <comment xml:lang="pt">documento WWF</comment>
+ <comment xml:lang="pl">Dokument WWF</comment>
+ <comment xml:lang="oc">document WWF</comment>
+ <comment xml:lang="nl">WWF-document</comment>
+ <comment xml:lang="lv">WWF dokuments</comment>
+ <comment xml:lang="lt">WWF dokumentas</comment>
+ <comment xml:lang="ko">WWF 문서</comment>
+ <comment xml:lang="kk">WWF құжаты</comment>
+ <comment xml:lang="ka">WWF დოკუმენტი</comment>
+ <comment xml:lang="ja">WWF ドキュメント</comment>
+ <comment xml:lang="it">Documento WWF</comment>
+ <comment xml:lang="is">WWF skjal</comment>
+ <comment xml:lang="id">Dokumen WWF</comment>
+ <comment xml:lang="ia">Documento WWF</comment>
+ <comment xml:lang="hu">WWF-dokumentum</comment>
+ <comment xml:lang="hr">WWF dokument</comment>
+ <comment xml:lang="he">מסמך WWF</comment>
+ <comment xml:lang="gl">documento de WWF</comment>
+ <comment xml:lang="ga">cáipéis WWF</comment>
+ <comment xml:lang="fur">document WWF</comment>
+ <comment xml:lang="fr">document WWF</comment>
+ <comment xml:lang="fi">WWF-asiakirja</comment>
+ <comment xml:lang="eu">WWF dokumentua</comment>
+ <comment xml:lang="es">documento WWF</comment>
+ <comment xml:lang="eo">WWF-dokumento</comment>
+ <comment xml:lang="en_GB">WWF document</comment>
+ <comment xml:lang="el">Έγγραφο WWF</comment>
+ <comment xml:lang="de">WWF-Dokument</comment>
+ <comment xml:lang="da">WWF-dokument</comment>
+ <comment xml:lang="cs">dokument WWF</comment>
+ <comment xml:lang="ca">document WWF</comment>
+ <comment xml:lang="bg">Документ — WWF</comment>
+ <comment xml:lang="be">дакумент WWF</comment>
+ <comment xml:lang="ast">Documentu WWF</comment>
+ <comment xml:lang="ar">مستند WWF</comment>
+ <comment xml:lang="af">WWF-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.wwf"/>
<sub-class-of type="application/pdf"/>
@@ -869,61 +889,67 @@
</mime-type>
<mime-type type="application/pdf">
<comment>PDF document</comment>
- <comment xml:lang="ar">مستند PDF</comment>
- <comment xml:lang="ast">Documentu PDF</comment>
- <comment xml:lang="be@latin">Dakument PDF</comment>
- <comment xml:lang="bg">Документ — PDF</comment>
- <comment xml:lang="ca">document PDF</comment>
- <comment xml:lang="cs">dokument PDF</comment>
- <comment xml:lang="cy">Dogfen PDF</comment>
- <comment xml:lang="da">PDF-dokument</comment>
- <comment xml:lang="de">PDF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο PDF</comment>
- <comment xml:lang="en_GB">PDF document</comment>
- <comment xml:lang="eo">PDF-dokumento</comment>
- <comment xml:lang="es">documento PDF</comment>
- <comment xml:lang="eu">PDF dokumentua</comment>
- <comment xml:lang="fi">PDF-asiakirja</comment>
- <comment xml:lang="fo">PDF skjal</comment>
- <comment xml:lang="fr">document PDF</comment>
- <comment xml:lang="ga">cáipéis PDF</comment>
- <comment xml:lang="gl">documento PDF</comment>
- <comment xml:lang="he">מסמך PDF</comment>
- <comment xml:lang="hr">PDF dokument</comment>
- <comment xml:lang="hu">PDF-dokumentum</comment>
- <comment xml:lang="ia">Documento PDF</comment>
- <comment xml:lang="id">Dokumen PDF</comment>
- <comment xml:lang="it">Documento PDF</comment>
- <comment xml:lang="ja">PDF ドキュメント</comment>
- <comment xml:lang="kk">PDF құжаты</comment>
- <comment xml:lang="ko">PDF 문서</comment>
- <comment xml:lang="lt">PDF dokumentas</comment>
- <comment xml:lang="lv">PDF dokuments</comment>
- <comment xml:lang="ms">Dokumen PDF</comment>
- <comment xml:lang="nb">PDF-dokument</comment>
- <comment xml:lang="nl">PDF-document</comment>
- <comment xml:lang="nn">PDF-dokument</comment>
- <comment xml:lang="oc">document PDF</comment>
- <comment xml:lang="pl">Dokument PDF</comment>
- <comment xml:lang="pt">documento PDF</comment>
- <comment xml:lang="pt_BR">Documento PDF</comment>
- <comment xml:lang="ro">Document PDF</comment>
- <comment xml:lang="ru">Документ PDF</comment>
- <comment xml:lang="sk">Dokument PDF</comment>
- <comment xml:lang="sl">Dokument PDF</comment>
- <comment xml:lang="sq">Dokument PDF</comment>
- <comment xml:lang="sr">ПДФ документ</comment>
- <comment xml:lang="sv">PDF-dokument</comment>
- <comment xml:lang="tr">PDF belgesi</comment>
- <comment xml:lang="uk">документ PDF</comment>
- <comment xml:lang="vi">Tài liệu PDF</comment>
- <comment xml:lang="zh_CN">PDF 文档</comment>
<comment xml:lang="zh_TW">PDF 文件</comment>
+ <comment xml:lang="zh_CN">PDF 文档</comment>
+ <comment xml:lang="vi">Tài liệu PDF</comment>
+ <comment xml:lang="uk">документ PDF</comment>
+ <comment xml:lang="tr">PDF belgesi</comment>
+ <comment xml:lang="sv">PDF-dokument</comment>
+ <comment xml:lang="sr">ПДФ документ</comment>
+ <comment xml:lang="sq">dokument PDF</comment>
+ <comment xml:lang="sl">Dokument PDF</comment>
+ <comment xml:lang="si">PDF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument PDF</comment>
+ <comment xml:lang="ru">Документ PDF</comment>
+ <comment xml:lang="ro">Document PDF</comment>
+ <comment xml:lang="pt_BR">Documento PDF</comment>
+ <comment xml:lang="pt">documento PDF</comment>
+ <comment xml:lang="pl">Dokument PDF</comment>
+ <comment xml:lang="oc">document PDF</comment>
+ <comment xml:lang="nn">PDF-dokument</comment>
+ <comment xml:lang="nl">PDF-document</comment>
+ <comment xml:lang="nb">PDF-dokument</comment>
+ <comment xml:lang="ms">Dokumen PDF</comment>
+ <comment xml:lang="lv">PDF dokuments</comment>
+ <comment xml:lang="lt">PDF dokumentas</comment>
+ <comment xml:lang="ko">PDF 문서</comment>
+ <comment xml:lang="kk">PDF құжаты</comment>
+ <comment xml:lang="ka">PDF დოკუმენტი</comment>
+ <comment xml:lang="ja">PDF ドキュメント</comment>
+ <comment xml:lang="it">Documento PDF</comment>
+ <comment xml:lang="is">PDF skjal</comment>
+ <comment xml:lang="id">Dokumen PDF</comment>
+ <comment xml:lang="ia">Documento PDF</comment>
+ <comment xml:lang="hu">PDF-dokumentum</comment>
+ <comment xml:lang="hr">PDF dokument</comment>
+ <comment xml:lang="he">מסמך PDF</comment>
+ <comment xml:lang="gl">documento PDF</comment>
+ <comment xml:lang="ga">cáipéis PDF</comment>
+ <comment xml:lang="fur">document PDF</comment>
+ <comment xml:lang="fr">document PDF</comment>
+ <comment xml:lang="fo">PDF skjal</comment>
+ <comment xml:lang="fi">PDF-asiakirja</comment>
+ <comment xml:lang="eu">PDF dokumentua</comment>
+ <comment xml:lang="es">documento PDF</comment>
+ <comment xml:lang="eo">PDF-dokumento</comment>
+ <comment xml:lang="en_GB">PDF document</comment>
+ <comment xml:lang="el">Έγγραφο PDF</comment>
+ <comment xml:lang="de">PDF-Dokument</comment>
+ <comment xml:lang="da">PDF-dokument</comment>
+ <comment xml:lang="cy">Dogfen PDF</comment>
+ <comment xml:lang="cs">dokument PDF</comment>
+ <comment xml:lang="ca">document PDF</comment>
+ <comment xml:lang="bg">Документ — PDF</comment>
+ <comment xml:lang="be@latin">Dakument PDF</comment>
+ <comment xml:lang="be">дакумент PDF</comment>
+ <comment xml:lang="ast">Documentu PDF</comment>
+ <comment xml:lang="ar">مستند PDF</comment>
+ <comment xml:lang="af">PDF-dokument</comment>
<acronym>PDF</acronym>
<expanded-acronym>Portable Document Format</expanded-acronym>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="%PDF-" type="string" offset="0:1024"/>
+ <magic>
+ <match type="string" value="%PDF-" offset="0:1024"/>
</magic>
<glob pattern="*.pdf"/>
<alias type="application/x-pdf"/>
@@ -933,61 +959,67 @@
</mime-type>
<mime-type type="application/xspf+xml">
<comment>XSPF playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل XSPF</comment>
- <comment xml:lang="ast">Llista de reproducción XSPF</comment>
- <comment xml:lang="be@latin">Śpis piesień XSPF</comment>
- <comment xml:lang="bg">Списък за изпълнение — XSPF</comment>
- <comment xml:lang="ca">llista de reproducció XSPF</comment>
- <comment xml:lang="cs">seznam k přehrání XSPF</comment>
- <comment xml:lang="da">XSPF-afspilningsliste</comment>
- <comment xml:lang="de">XSPF-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής XSPF</comment>
- <comment xml:lang="en_GB">XSPF playlist</comment>
- <comment xml:lang="eo">XSPF-ludlisto</comment>
- <comment xml:lang="es">lista de reproducción XSPF</comment>
- <comment xml:lang="eu">XSPF erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">XSPF-soittolista</comment>
- <comment xml:lang="fo">XSPF avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture XSPF</comment>
- <comment xml:lang="ga">seinmliosta XSPF</comment>
- <comment xml:lang="gl">lista de reprodución XSPF</comment>
- <comment xml:lang="he">רשימת נגינה XSPF</comment>
- <comment xml:lang="hr">XSPF popis izvođenja</comment>
- <comment xml:lang="hu">XSPF-lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection XSPF</comment>
- <comment xml:lang="id">Senarai pular XSPF</comment>
- <comment xml:lang="it">Playlist XSPF</comment>
- <comment xml:lang="ja">XSPF 再生リスト</comment>
- <comment xml:lang="kk">XSPF ойнау тізімі</comment>
- <comment xml:lang="ko">XSPF 재생 목록</comment>
- <comment xml:lang="lt">XSPF grojaraštis</comment>
- <comment xml:lang="lv">XSPF repertuārs</comment>
- <comment xml:lang="nb">XSPF-spilleliste</comment>
- <comment xml:lang="nl">XSPF-afspeellijst</comment>
- <comment xml:lang="nn">XSPF-speleliste</comment>
- <comment xml:lang="oc">lista de lectura XSPF</comment>
- <comment xml:lang="pl">Lista odtwarzania XSPF</comment>
- <comment xml:lang="pt">lista de reprodução XSPF</comment>
- <comment xml:lang="pt_BR">Lista de reprodução XSPF</comment>
- <comment xml:lang="ro">Listă XSPF</comment>
- <comment xml:lang="ru">Список воспроизведения XSPF</comment>
- <comment xml:lang="sk">Zoznam skladieb XSPF</comment>
- <comment xml:lang="sl">Seznam predvajanja XSPF</comment>
- <comment xml:lang="sq">Listë titujsh XSPF</comment>
- <comment xml:lang="sr">ИксСПФ списак нумера</comment>
- <comment xml:lang="sv">XSPF-spellista</comment>
- <comment xml:lang="tr">XSPF çalma listesi</comment>
- <comment xml:lang="uk">список програвання XSPF</comment>
- <comment xml:lang="vi">Danh mục nhạc XSPF</comment>
- <comment xml:lang="zh_CN">XSPF 播放列表</comment>
<comment xml:lang="zh_TW">XSPF 播放清單</comment>
+ <comment xml:lang="zh_CN">XSPF 播放列表</comment>
+ <comment xml:lang="vi">Danh mục nhạc XSPF</comment>
+ <comment xml:lang="uk">список програвання XSPF</comment>
+ <comment xml:lang="tr">XSPF çalma listesi</comment>
+ <comment xml:lang="sv">XSPF-spellista</comment>
+ <comment xml:lang="sr">ИксСПФ списак нумера</comment>
+ <comment xml:lang="sq">luajlistë XSPF</comment>
+ <comment xml:lang="sl">Seznam predvajanja XSPF</comment>
+ <comment xml:lang="si">XSPF ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb XSPF</comment>
+ <comment xml:lang="ru">Список воспроизведения XSPF</comment>
+ <comment xml:lang="ro">Listă XSPF</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução XSPF</comment>
+ <comment xml:lang="pt">lista de reprodução XSPF</comment>
+ <comment xml:lang="pl">Lista odtwarzania XSPF</comment>
+ <comment xml:lang="oc">lista de lectura XSPF</comment>
+ <comment xml:lang="nn">XSPF-speleliste</comment>
+ <comment xml:lang="nl">XSPF-afspeellijst</comment>
+ <comment xml:lang="nb">XSPF-spilleliste</comment>
+ <comment xml:lang="lv">XSPF repertuārs</comment>
+ <comment xml:lang="lt">XSPF grojaraštis</comment>
+ <comment xml:lang="ko">XSPF 재생 목록</comment>
+ <comment xml:lang="kk">XSPF ойнау тізімі</comment>
+ <comment xml:lang="ka">XSPF დასაკრავი სია</comment>
+ <comment xml:lang="ja">XSPF プレイリスト</comment>
+ <comment xml:lang="it">Playlist XSPF</comment>
+ <comment xml:lang="is">XSPF spilunarlisti</comment>
+ <comment xml:lang="id">Senarai pular XSPF</comment>
+ <comment xml:lang="ia">Lista de selection XSPF</comment>
+ <comment xml:lang="hu">XSPF-lejátszólista</comment>
+ <comment xml:lang="hr">XSPF popis izvođenja</comment>
+ <comment xml:lang="he">רשימת נגינה XSPF</comment>
+ <comment xml:lang="gl">lista de reprodución XSPF</comment>
+ <comment xml:lang="ga">seinmliosta XSPF</comment>
+ <comment xml:lang="fur">liste di riproduzion XSPF</comment>
+ <comment xml:lang="fr">liste de lecture XSPF</comment>
+ <comment xml:lang="fo">XSPF avspælingarlisti</comment>
+ <comment xml:lang="fi">XSPF-soittolista</comment>
+ <comment xml:lang="eu">XSPF erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción XSPF</comment>
+ <comment xml:lang="eo">XSPF-ludlisto</comment>
+ <comment xml:lang="en_GB">XSPF playlist</comment>
+ <comment xml:lang="el">Λίστα αναπαραγωγής XSPF</comment>
+ <comment xml:lang="de">XSPF-Wiedergabeliste</comment>
+ <comment xml:lang="da">XSPF-afspilningsliste</comment>
+ <comment xml:lang="cs">seznam k přehrání XSPF</comment>
+ <comment xml:lang="ca">llista de reproducció XSPF</comment>
+ <comment xml:lang="bg">Списък за изпълнение — XSPF</comment>
+ <comment xml:lang="be@latin">Śpis piesień XSPF</comment>
+ <comment xml:lang="be">плэй-ліст XSPF</comment>
+ <comment xml:lang="ast">Llista de reproducción XSPF</comment>
+ <comment xml:lang="ar">قائمة تشغيل XSPF</comment>
+ <comment xml:lang="af">XSPF-speellys</comment>
<acronym>XSPF</acronym>
<expanded-acronym>XML Shareable Playlist Format</expanded-acronym>
<sub-class-of type="application/xml"/>
<generic-icon name="audio-x-generic"/>
- <magic priority="50">
- <match value="&lt;playlist version=&quot;1" type="string" offset="0:64"/>
- <match value="&lt;playlist version='1" type="string" offset="0:64"/>
+ <magic>
+ <match type="string" value="&lt;playlist version=&quot;1" offset="0:64"/>
+ <match type="string" value="&lt;playlist version='1" offset="0:64"/>
</magic>
<glob pattern="*.xspf"/>
<root-XML namespaceURI="http://xspf.org/ns/0/" localName="playlist"/>
@@ -995,428 +1027,413 @@
</mime-type>
<mime-type type="application/x-windows-themepack">
<comment>Microsoft Windows theme pack</comment>
- <comment xml:lang="ar">حزمة سمات Microsoft Works</comment>
- <comment xml:lang="ast">Paquete de temes de Microsoft Windows</comment>
- <comment xml:lang="bg">Пакет с тема — Microsoft Windows</comment>
- <comment xml:lang="ca">paquet de temes de Microsoft Windows</comment>
- <comment xml:lang="cs">balík motivů Microsoft Windows</comment>
- <comment xml:lang="da">Microsoft Windows-temapakke</comment>
- <comment xml:lang="de">Microsoft-Windows-Themenpaket</comment>
- <comment xml:lang="el">Πακέτο θέματος Microsoft Windows</comment>
- <comment xml:lang="en_GB">Microsoft Windows theme pack</comment>
- <comment xml:lang="es">paquete de tema para Microsoft Windows</comment>
- <comment xml:lang="eu">Microsoft Windows-en gaiaren paketea</comment>
- <comment xml:lang="fi">Microsoft Windows -teemapaketti</comment>
- <comment xml:lang="fo">Microsoft Windows tema pakki</comment>
- <comment xml:lang="fr">paquet de thèmes Microsoft Windows</comment>
- <comment xml:lang="ga">paca téamaí Microsoft Windows</comment>
- <comment xml:lang="gl">paquete de tema de Microsoft Windows</comment>
- <comment xml:lang="he">חבילת ערכות נושא של Microsoft Windows</comment>
- <comment xml:lang="hr">Microsoft Windows paket tema</comment>
- <comment xml:lang="hu">Microsoft Windows témacsomag</comment>
- <comment xml:lang="ia">Pacchetto de themas Microsoft Windows</comment>
- <comment xml:lang="id">Pak tema Microsoft Windows</comment>
- <comment xml:lang="it">Pacchetto temi Microsoft Windows</comment>
- <comment xml:lang="ja">Microsoft Windows テーマパック</comment>
- <comment xml:lang="ka">Microsoft Windows-ის თემის შეკვრა</comment>
- <comment xml:lang="kk">Microsoft Windows тема дестесі</comment>
- <comment xml:lang="ko">Microsoft Windows 테마 패키지</comment>
- <comment xml:lang="lt">Microsoft Windows temų paketas</comment>
- <comment xml:lang="lv">Microsoft Windows motīvu paka</comment>
- <comment xml:lang="nl">Microsoft Windows thema pack</comment>
- <comment xml:lang="oc">paquet de tèmas Microsoft Windows</comment>
- <comment xml:lang="pl">Pakiet motywu Microsoft Windows</comment>
- <comment xml:lang="pt">pacote de tema Microsoft Windows</comment>
- <comment xml:lang="pt_BR">Pacote de temas do Microsoft Windows</comment>
- <comment xml:lang="ro">Pachet de teme Microsoft Windows</comment>
- <comment xml:lang="ru">Пакет темы Microsoft Windows</comment>
- <comment xml:lang="sk">Balík tém Microsoft Windows</comment>
- <comment xml:lang="sl">Datoteka teme Microsoft Windows</comment>
- <comment xml:lang="sr">пакет теме Мајкрософт Виндоуза</comment>
- <comment xml:lang="sv">Microsoft Windows-temapaket</comment>
- <comment xml:lang="tr">Microsoft Windows tema paketi</comment>
- <comment xml:lang="uk">пакунок з темою Microsoft Windows</comment>
- <comment xml:lang="zh_CN">Microsoft Windows 主题包</comment>
<comment xml:lang="zh_TW">微軟視窗佈景主題包</comment>
+ <comment xml:lang="zh_CN">Microsoft Windows 主题包</comment>
+ <comment xml:lang="uk">пакунок з темою Microsoft Windows</comment>
+ <comment xml:lang="tr">Microsoft Windows tema paketi</comment>
+ <comment xml:lang="sv">Microsoft Windows-temapaket</comment>
+ <comment xml:lang="sr">пакет теме Мајкрософт Виндоуза</comment>
+ <comment xml:lang="sq">paketë temash Microsoft Windows</comment>
+ <comment xml:lang="sl">Datoteka teme Microsoft Windows</comment>
+ <comment xml:lang="si">Microsoft Windows තේමා ඇසුරුම</comment>
+ <comment xml:lang="sk">Balík tém Microsoft Windows</comment>
+ <comment xml:lang="ru">Пакет темы Microsoft Windows</comment>
+ <comment xml:lang="ro">Pachet de teme Microsoft Windows</comment>
+ <comment xml:lang="pt_BR">Pacote de temas do Microsoft Windows</comment>
+ <comment xml:lang="pt">pacote de tema Microsoft Windows</comment>
+ <comment xml:lang="pl">Pakiet motywu Microsoft Windows</comment>
+ <comment xml:lang="oc">paquet de tèmas Microsoft Windows</comment>
+ <comment xml:lang="nl">Microsoft Windows-themapakket</comment>
+ <comment xml:lang="lv">Microsoft Windows motīvu paka</comment>
+ <comment xml:lang="lt">Microsoft Windows temų paketas</comment>
+ <comment xml:lang="ko">Microsoft Windows 테마 패키지</comment>
+ <comment xml:lang="kk">Microsoft Windows тема дестесі</comment>
+ <comment xml:lang="ka">Microsoft Windows-ის თემის შეკვრა</comment>
+ <comment xml:lang="ja">Microsoft Windows テーマパック</comment>
+ <comment xml:lang="it">Pacchetto temi Microsoft Windows</comment>
+ <comment xml:lang="is">Microsoft Windows þemapakki</comment>
+ <comment xml:lang="id">Pak tema Microsoft Windows</comment>
+ <comment xml:lang="ia">Pacchetto de themas Microsoft Windows</comment>
+ <comment xml:lang="hu">Microsoft Windows témacsomag</comment>
+ <comment xml:lang="hr">Microsoft Windows paket tema</comment>
+ <comment xml:lang="he">חבילת ערכות נושא של Microsoft Windows</comment>
+ <comment xml:lang="gl">paquete de tema de Microsoft Windows</comment>
+ <comment xml:lang="ga">paca téamaí Microsoft Windows</comment>
+ <comment xml:lang="fur">pachet temis di Microsoft Windows</comment>
+ <comment xml:lang="fr">paquet de thèmes Microsoft Windows</comment>
+ <comment xml:lang="fo">Microsoft Windows tema pakki</comment>
+ <comment xml:lang="fi">Microsoft Windows -teemapaketti</comment>
+ <comment xml:lang="eu">Microsoft Windows-en gaiaren paketea</comment>
+ <comment xml:lang="es">paquete de tema para Microsoft Windows</comment>
+ <comment xml:lang="en_GB">Microsoft Windows theme pack</comment>
+ <comment xml:lang="el">Πακέτο θέματος Microsoft Windows</comment>
+ <comment xml:lang="de">Microsoft-Windows-Themenpaket</comment>
+ <comment xml:lang="da">Microsoft Windows-temapakke</comment>
+ <comment xml:lang="cs">balík motivů Microsoft Windows</comment>
+ <comment xml:lang="ca">paquet de temes de Microsoft Windows</comment>
+ <comment xml:lang="bg">Пакет с тема — Microsoft Windows</comment>
+ <comment xml:lang="be">пакет тэмы Microsoft Windows</comment>
+ <comment xml:lang="ast">Paquete de temes de Microsoft Windows</comment>
+ <comment xml:lang="ar">حزمة سمات Microsoft Works</comment>
+ <comment xml:lang="af">Microsoft Windows-temapak</comment>
<sub-class-of type="application/vnd.ms-cab-compressed"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.themepack"/>
</mime-type>
<mime-type type="audio/x-amzxml">
<comment>AmazonMP3 download file</comment>
- <comment xml:lang="ast">Ficheru de descarga AmazonMP3</comment>
- <comment xml:lang="ca">fitxer baixat d'AmazonMP3</comment>
- <comment xml:lang="cs">soubor stahování AmazonMP3</comment>
- <comment xml:lang="da">AmazonMP3-downloadfil</comment>
- <comment xml:lang="de">AmazonMP3-Herunterladedatei</comment>
- <comment xml:lang="el">Αρχείο λήψης AmazonMP3</comment>
- <comment xml:lang="en_GB">AmazonMP3 download file</comment>
- <comment xml:lang="es">archivo de descarga de AmazonMP3</comment>
- <comment xml:lang="eu">AmazonMP3 deskarga fitxategia</comment>
- <comment xml:lang="fr">fichier téléchargé AmazonMP3</comment>
- <comment xml:lang="ga">comhad íoslódáilte AmazonMP3</comment>
- <comment xml:lang="gl">Ficheiro de descarga de AmazonMP3</comment>
- <comment xml:lang="he">קובץ הורדת AmazonMP3</comment>
- <comment xml:lang="hr">AmazonMP3 preuzeta datoteka</comment>
- <comment xml:lang="hu">AmazonMP3 letöltésfájl</comment>
- <comment xml:lang="ia">File de discargamento AmazonMP3</comment>
- <comment xml:lang="id">Berkas unduh AmazonMP3</comment>
- <comment xml:lang="it">File scaricamento AmazonMP3</comment>
- <comment xml:lang="ja">AmazonMP3 ダウンロードファイル</comment>
- <comment xml:lang="kk">AmazonMP3 жүктеме файлы</comment>
- <comment xml:lang="ko">AmazonMP3 다운로드 파일</comment>
- <comment xml:lang="lv">AmazonMP3 lejupielādes datne</comment>
- <comment xml:lang="oc">fichièr telecargat AmazonMP3</comment>
- <comment xml:lang="pl">Pobrany plik AmazonMP3</comment>
- <comment xml:lang="pt">ficheiro transferido AmazonMP3</comment>
- <comment xml:lang="pt_BR">Arquivo de download AmazonMP3</comment>
- <comment xml:lang="ru">Файл загрузки AmazonMP3</comment>
- <comment xml:lang="sk">Stiahnutý súbor AmazonMP3 </comment>
- <comment xml:lang="sl">Datoteka prenosa AmazonMP3</comment>
- <comment xml:lang="sr">датотека преузимања АмазонаМП3</comment>
- <comment xml:lang="sv">AmazonMP3-hämtningsfil</comment>
- <comment xml:lang="tr">AmazonMP3 indirme dosyası</comment>
- <comment xml:lang="uk">файл завантаження AmazonMP3</comment>
- <comment xml:lang="zh_CN">AmazonMP3 下载文件</comment>
<comment xml:lang="zh_TW">AmazonMP3 下載檔</comment>
+ <comment xml:lang="zh_CN">AmazonMP3 下载文件</comment>
+ <comment xml:lang="uk">файл завантаження AmazonMP3</comment>
+ <comment xml:lang="tr">AmazonMP3 indirme dosyası</comment>
+ <comment xml:lang="sv">AmazonMP3-hämtningsfil</comment>
+ <comment xml:lang="sr">датотека преузимања АмазонаМП3</comment>
+ <comment xml:lang="sq">kartelë shkarkimi AmazonMP3</comment>
+ <comment xml:lang="sl">Datoteka prenosa AmazonMP3</comment>
+ <comment xml:lang="si">AmazonMP3 බාගත කිරීමේ ගොනුව</comment>
+ <comment xml:lang="sk">Stiahnutý súbor AmazonMP3 </comment>
+ <comment xml:lang="ru">Файл загрузки AmazonMP3</comment>
+ <comment xml:lang="pt_BR">Arquivo de download AmazonMP3</comment>
+ <comment xml:lang="pt">ficheiro transferido AmazonMP3</comment>
+ <comment xml:lang="pl">Pobrany plik AmazonMP3</comment>
+ <comment xml:lang="oc">fichièr telecargat AmazonMP3</comment>
+ <comment xml:lang="nl">AmazonMP3-downloadbestand</comment>
+ <comment xml:lang="lv">AmazonMP3 lejupielādes datne</comment>
+ <comment xml:lang="ko">AmazonMP3 다운로드 파일</comment>
+ <comment xml:lang="kk">AmazonMP3 жүктеме файлы</comment>
+ <comment xml:lang="ka">AmazonMP3 გადმოწერის ფაილი</comment>
+ <comment xml:lang="ja">AmazonMP3 ダウンロードファイル</comment>
+ <comment xml:lang="it">File scaricamento AmazonMP3</comment>
+ <comment xml:lang="is">AmazonMP3 niðurhalsskrá</comment>
+ <comment xml:lang="id">Berkas unduh AmazonMP3</comment>
+ <comment xml:lang="ia">File de discargamento AmazonMP3</comment>
+ <comment xml:lang="hu">AmazonMP3 letöltésfájl</comment>
+ <comment xml:lang="hr">AmazonMP3 preuzeta datoteka</comment>
+ <comment xml:lang="he">קובץ הורדת AmazonMP3</comment>
+ <comment xml:lang="gl">Ficheiro de descarga de AmazonMP3</comment>
+ <comment xml:lang="ga">comhad íoslódáilte AmazonMP3</comment>
+ <comment xml:lang="fur">file discjariât AmazonMP3</comment>
+ <comment xml:lang="fr">fichier téléchargé AmazonMP3</comment>
+ <comment xml:lang="fi">AmazonMP3-lataustiedosto</comment>
+ <comment xml:lang="eu">AmazonMP3 deskarga fitxategia</comment>
+ <comment xml:lang="es">archivo de descarga de AmazonMP3</comment>
+ <comment xml:lang="en_GB">AmazonMP3 download file</comment>
+ <comment xml:lang="el">Αρχείο λήψης AmazonMP3</comment>
+ <comment xml:lang="de">Amazon MP3-Download-Datei</comment>
+ <comment xml:lang="da">AmazonMP3-downloadfil</comment>
+ <comment xml:lang="cs">soubor stahování AmazonMP3</comment>
+ <comment xml:lang="ca">fitxer baixat d'AmazonMP3</comment>
+ <comment xml:lang="bg">Файл за изтегляне — AmazonMP3</comment>
+ <comment xml:lang="be">файл спампоўвання AmazonMP3</comment>
+ <comment xml:lang="ast">Ficheru de descarga AmazonMP3</comment>
+ <comment xml:lang="ar">ملف تنزيل AmazonMP3 </comment>
+ <comment xml:lang="af">AmazonMP3-aflaailêer</comment>
<glob pattern="*.amz"/>
</mime-type>
<mime-type type="audio/x-gsm">
<comment>GSM 06.10 audio</comment>
- <comment xml:lang="ar">GSM 06.10 سمعي</comment>
- <comment xml:lang="ast">Audiu GSM 6.10</comment>
- <comment xml:lang="bg">Аудио — GSM 06.10</comment>
- <comment xml:lang="ca">àudio de GSM 06.10</comment>
- <comment xml:lang="cs">zvuk GSM 06.10</comment>
- <comment xml:lang="da">GSM 06.10-lyd</comment>
- <comment xml:lang="de">GSM-06.10-Audio</comment>
- <comment xml:lang="el">Ήχος GSM 06.10</comment>
- <comment xml:lang="en_GB">GSM 06.10 audio</comment>
- <comment xml:lang="es">sonido GSM 06.10</comment>
- <comment xml:lang="eu">GSM 06.10 audioa</comment>
- <comment xml:lang="fi">GSM 06.10 -ääni</comment>
- <comment xml:lang="fo">GSM 06.10 ljóður</comment>
- <comment xml:lang="fr">audio GSM 06.10</comment>
- <comment xml:lang="ga">fuaim GSM 06.10</comment>
- <comment xml:lang="gl">son de GSM 06.10</comment>
- <comment xml:lang="he">שמע GSM 06.10</comment>
- <comment xml:lang="hr">GSM 06.10 zvučni zapis</comment>
- <comment xml:lang="hu">GSM 06.10 hang</comment>
- <comment xml:lang="ia">Audio GSM 06.10</comment>
- <comment xml:lang="id">Audio GSM 06.10</comment>
- <comment xml:lang="it">Audio GSM 06.10</comment>
- <comment xml:lang="ja">GSM 06.10 オーディオ</comment>
- <comment xml:lang="ka">GSM 06.10 აუდიო</comment>
- <comment xml:lang="kk">GSM 06.10 аудиосы</comment>
- <comment xml:lang="ko">GSM 06.10 오디오</comment>
- <comment xml:lang="lt">GSM 06.10 garso įrašas</comment>
- <comment xml:lang="lv">GSM 06.10 audio</comment>
- <comment xml:lang="nl">GSM 06.10 audio</comment>
- <comment xml:lang="oc">àudio GSM 06.10</comment>
- <comment xml:lang="pl">Plik dźwiękowy GSM 06.10</comment>
- <comment xml:lang="pt">áudio GSM 06.10</comment>
- <comment xml:lang="pt_BR">Áudio GSM 06.10</comment>
- <comment xml:lang="ro">GSM 06.10 audio</comment>
- <comment xml:lang="ru">Аудио GSM 06.10</comment>
- <comment xml:lang="sk">Zvuk GSM 06.10</comment>
- <comment xml:lang="sl">Zvočna datoteka GSM 06.10</comment>
- <comment xml:lang="sr">ГСМ 06.10 звук</comment>
- <comment xml:lang="sv">GSM 06.10-ljud</comment>
- <comment xml:lang="tr">GSM 06.10 ses dosyası</comment>
- <comment xml:lang="uk">звук GSM 06.10</comment>
- <comment xml:lang="vi">Âm thanh GSM 06.10</comment>
- <comment xml:lang="zh_CN">GSM 06.10 音频</comment>
<comment xml:lang="zh_TW">GSM 06.10 音訊</comment>
+ <comment xml:lang="zh_CN">GSM 06.10 音频</comment>
+ <comment xml:lang="vi">Âm thanh GSM 06.10</comment>
+ <comment xml:lang="uk">звук GSM 06.10</comment>
+ <comment xml:lang="tr">GSM 06.10 ses dosyası</comment>
+ <comment xml:lang="sv">GSM 06.10-ljud</comment>
+ <comment xml:lang="sr">ГСМ 06.10 звук</comment>
+ <comment xml:lang="sq">audio GSM 06.10</comment>
+ <comment xml:lang="sl">Zvočna datoteka GSM 06.10</comment>
+ <comment xml:lang="si">GSM 06.10 ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk GSM 06.10</comment>
+ <comment xml:lang="ru">Аудио GSM 06.10</comment>
+ <comment xml:lang="ro">GSM 06.10 audio</comment>
+ <comment xml:lang="pt_BR">Áudio GSM 06.10</comment>
+ <comment xml:lang="pt">áudio GSM 06.10</comment>
+ <comment xml:lang="pl">Plik dźwiękowy GSM 06.10</comment>
+ <comment xml:lang="oc">àudio GSM 06.10</comment>
+ <comment xml:lang="nl">GSM 06.10 audio</comment>
+ <comment xml:lang="lv">GSM 06.10 audio</comment>
+ <comment xml:lang="lt">GSM 06.10 garso įrašas</comment>
+ <comment xml:lang="ko">GSM 06.10 오디오</comment>
+ <comment xml:lang="kk">GSM 06.10 аудиосы</comment>
+ <comment xml:lang="ka">GSM 06.10 აუდიო</comment>
+ <comment xml:lang="ja">GSM 06.10 オーディオ</comment>
+ <comment xml:lang="it">Audio GSM 06.10</comment>
+ <comment xml:lang="is">GSM 06.10 hljóð</comment>
+ <comment xml:lang="id">Audio GSM 06.10</comment>
+ <comment xml:lang="ia">Audio GSM 06.10</comment>
+ <comment xml:lang="hu">GSM 06.10 hang</comment>
+ <comment xml:lang="hr">GSM 06.10 zvučni zapis</comment>
+ <comment xml:lang="he">שמע GSM 06.10</comment>
+ <comment xml:lang="gl">son de GSM 06.10</comment>
+ <comment xml:lang="ga">fuaim GSM 06.10</comment>
+ <comment xml:lang="fur">audio GSM 06.10</comment>
+ <comment xml:lang="fr">audio GSM 06.10</comment>
+ <comment xml:lang="fo">GSM 06.10 ljóður</comment>
+ <comment xml:lang="fi">GSM 06.10 -ääni</comment>
+ <comment xml:lang="eu">GSM 06.10 audioa</comment>
+ <comment xml:lang="es">sonido GSM 06.10</comment>
+ <comment xml:lang="en_GB">GSM 06.10 audio</comment>
+ <comment xml:lang="el">Ήχος GSM 06.10</comment>
+ <comment xml:lang="de">GSM-06.10-Audio</comment>
+ <comment xml:lang="da">GSM 06.10-lyd</comment>
+ <comment xml:lang="cs">zvuk GSM 06.10</comment>
+ <comment xml:lang="ca">àudio de GSM 06.10</comment>
+ <comment xml:lang="bg">Аудио — GSM 06.10</comment>
+ <comment xml:lang="be">аўдыя GSM 06.10</comment>
+ <comment xml:lang="ast">Audiu GSM 6.10</comment>
+ <comment xml:lang="ar">صوت GSM 06.10</comment>
+ <comment xml:lang="af">GSM 06.10-oudio</comment>
<acronym>GSM</acronym>
<expanded-acronym>Global System for Mobile communications</expanded-acronym>
<glob pattern="*.gsm"/>
</mime-type>
<mime-type type="audio/x-iriver-pla">
- <comment>iRiver Playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل iRiver</comment>
- <comment xml:lang="ast">Llista de reproducción iRiver</comment>
- <comment xml:lang="be@latin">Śpis piesień iRiver</comment>
- <comment xml:lang="bg">Списък за изпълнение — iRiver</comment>
- <comment xml:lang="ca">llista de reproducció iRiver</comment>
- <comment xml:lang="cs">seznam k přehrání iRiver</comment>
- <comment xml:lang="da">iRiver-afspilningsliste</comment>
- <comment xml:lang="de">iRiver-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής iRiver</comment>
- <comment xml:lang="en_GB">iRiver Playlist</comment>
- <comment xml:lang="eo">iRiver-ludlisto</comment>
- <comment xml:lang="es">lista de reproducción de iRiver</comment>
- <comment xml:lang="eu">iRiver erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">iRiver-soittolista</comment>
- <comment xml:lang="fo">iRiver avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture iRiver</comment>
- <comment xml:lang="ga">seinmliosta iRiver</comment>
- <comment xml:lang="gl">lista de reprodución de iRiver</comment>
- <comment xml:lang="he">רשימת נגינה של iRiver</comment>
- <comment xml:lang="hr">iRiver popis izvođenja</comment>
- <comment xml:lang="hu">iRiver lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection iRiver</comment>
- <comment xml:lang="id">iRiver Playlist</comment>
- <comment xml:lang="it">Playlist iRiver</comment>
- <comment xml:lang="ja">iRiver 再生リスト</comment>
- <comment xml:lang="kk">iRiver ойнау тізімі</comment>
- <comment xml:lang="ko">iRiver 재생 목록</comment>
- <comment xml:lang="lt">iRiver grojaraštis</comment>
- <comment xml:lang="lv">iRiver repertuārs</comment>
- <comment xml:lang="nb">iRiver-spilleliste</comment>
- <comment xml:lang="nl">iRiver-afspeellijst</comment>
- <comment xml:lang="nn">iRiver speleliste</comment>
- <comment xml:lang="oc">lista de lectura iRiver</comment>
- <comment xml:lang="pl">Lista odtwarzania iRiver</comment>
- <comment xml:lang="pt">lista de reprodução iRiver</comment>
- <comment xml:lang="pt_BR">Lista de reprodução do iRiver</comment>
- <comment xml:lang="ro">Listă iRiver</comment>
- <comment xml:lang="ru">Список воспроизведения iRiver</comment>
- <comment xml:lang="sk">Zoznam skladieb iRiver</comment>
- <comment xml:lang="sl">Seznam predvajanja iRiver</comment>
- <comment xml:lang="sq">Listë titujsh iRiver</comment>
- <comment xml:lang="sr">иРивер списак нумера</comment>
- <comment xml:lang="sv">iRiver-spellista</comment>
- <comment xml:lang="tr">iRiver Çalma Listesini</comment>
- <comment xml:lang="uk">список програвання iRiver</comment>
- <comment xml:lang="vi">danh mục nhạc iRiver</comment>
- <comment xml:lang="zh_CN">iRiver 播放列表</comment>
+ <comment>iRiver playlist</comment>
<comment xml:lang="zh_TW">iRiver 播放清單</comment>
- <magic priority="50">
- <match value="iriver UMS PLA" type="string" offset="4"/>
+ <comment xml:lang="zh_CN">iRiver 播放列表</comment>
+ <comment xml:lang="uk">список відтворення iRiver</comment>
+ <comment xml:lang="tr">iRiver çalma listesi</comment>
+ <comment xml:lang="sv">iRiver-spellista</comment>
+ <comment xml:lang="sq">luajlistë iRiver</comment>
+ <comment xml:lang="sl">Seznam predvajanja iRiver</comment>
+ <comment xml:lang="si">iRiver ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb iRiver</comment>
+ <comment xml:lang="ru">Список воспроизведения iRiver</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução do iRiver</comment>
+ <comment xml:lang="pt">lista de reprodução do iRiver</comment>
+ <comment xml:lang="pl">Lista odtwarzania iRiver</comment>
+ <comment xml:lang="oc">lista de lectura iRiver</comment>
+ <comment xml:lang="nl">iRiver-playlist</comment>
+ <comment xml:lang="lt">iRiver grojaraštis</comment>
+ <comment xml:lang="ko">아이리버 재생 목록</comment>
+ <comment xml:lang="kk">iRiver ойнау тізімі</comment>
+ <comment xml:lang="ka">iRiver დასაკრავი სია</comment>
+ <comment xml:lang="ja">iRiver プレイリスト</comment>
+ <comment xml:lang="it">Playlist iRiver</comment>
+ <comment xml:lang="is">iRiver spilunarlisti</comment>
+ <comment xml:lang="id">daftar putar iRiver</comment>
+ <comment xml:lang="hu">iRiver lejátszólista</comment>
+ <comment xml:lang="hr">iRiver popis izvođenja</comment>
+ <comment xml:lang="he">רשימת נגינה של iRiver</comment>
+ <comment xml:lang="gl">Lista de reprodución de iRiver</comment>
+ <comment xml:lang="fr">liste de lecture iRiver</comment>
+ <comment xml:lang="fi">iRiver-soittolista</comment>
+ <comment xml:lang="eu">iRiver erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción de iRiver</comment>
+ <comment xml:lang="en_GB">iRiver playlist</comment>
+ <comment xml:lang="de">iRiver-Wiedergabeliste</comment>
+ <comment xml:lang="da">iRiver-afspilningsliste</comment>
+ <comment xml:lang="ca">llista de reproducció iRiver</comment>
+ <comment xml:lang="bg">Списък за изпълнение — iRiver</comment>
+ <comment xml:lang="be">плэй-ліст iRiver</comment>
+ <comment xml:lang="ar">قائمة تشغيل iRiver</comment>
+ <magic>
+ <match type="string" value="iriver UMS PLA" offset="4"/>
</magic>
<glob pattern="*.pla"/>
</mime-type>
<mime-type type="application/pgp-encrypted">
<comment>PGP/MIME-encrypted message header</comment>
- <comment xml:lang="ar">ترويسة رسالة PGP/MIME-مشفرة</comment>
- <comment xml:lang="ast">Testera de mensaxe cifrada en PGP/MIME</comment>
- <comment xml:lang="be@latin">Zahałovak paviedamleńnia, zašyfravany ŭ PGP/MIME</comment>
- <comment xml:lang="bg">Заглавна част на шифрирано съобщение — PGP/MIME</comment>
- <comment xml:lang="ca">capçalera de missatge amb xifrat PGP/MIME</comment>
- <comment xml:lang="cs">záhlaví zprávy zašifrované pomocí PGP/MIME</comment>
- <comment xml:lang="da">PGP-/MIME-krypteret meddelelseshoved</comment>
- <comment xml:lang="de">PGP/MIME-verschlüsselter Nachrichtenkopf</comment>
- <comment xml:lang="el">Κεφαλίδα μηνύματος κρυπτογραφημένου κατά PGP/MIME</comment>
- <comment xml:lang="en_GB">PGP/MIME-encrypted message header</comment>
- <comment xml:lang="eo">PGP/MIME-ĉifrita ĉapo de mesaĝo</comment>
- <comment xml:lang="es">cabecera de mensaje cifrado PGP/MIME</comment>
- <comment xml:lang="eu">PGP/MIME enkriptatutako mezu-goiburua</comment>
- <comment xml:lang="fi">PGP/MIME-salattu viestiotsikko</comment>
- <comment xml:lang="fo">PGP/MIME-encrypted boð tekshøvd</comment>
- <comment xml:lang="fr">en-tête de message codé PGP/MIME</comment>
- <comment xml:lang="ga">ceanntásc teachtaireachta ionchódaithe le PGP/MIME</comment>
- <comment xml:lang="gl">cabeceira de mensaxe cifrado PGP/MIME</comment>
- <comment xml:lang="he">כותר של קובץ מוצפן מסוג PGP/MIME</comment>
- <comment xml:lang="hr">PGP/MIME-šrifrirano zaglavlje poruke</comment>
- <comment xml:lang="hu">PGP/MIME titkosított üzenetfejléc</comment>
- <comment xml:lang="ia">Capite de message cryptate con PGP/MIME</comment>
- <comment xml:lang="id">Tajuk pesan terenkripsi PGP/MIME</comment>
- <comment xml:lang="it">Intestazione messaggio PGP/MIME-encrypted</comment>
- <comment xml:lang="ja">PGP/MIME 暗号化メッセージヘッダー</comment>
- <comment xml:lang="kk">PGP/MIME-шифрленген мәлімдеме тақырыптамасы</comment>
- <comment xml:lang="ko">PGP/MIME으로 암호화된 메시지 헤더</comment>
- <comment xml:lang="lt">PGP/MIME užšifruota žinutės antraštė</comment>
- <comment xml:lang="lv">PGP/MIME-šifrēta ziņas galvene</comment>
- <comment xml:lang="ms">Pengepala mesej terenkripsi PGP/MIME</comment>
- <comment xml:lang="nb">PGP/MIME-kryptert meldingshode</comment>
- <comment xml:lang="nl">PGP/MIME-versleutelde berichtkopregels</comment>
- <comment xml:lang="nn">PGP/MIME-kryptert meldingshovud</comment>
- <comment xml:lang="oc">entèsta de messatge encodat PGP/MIME</comment>
- <comment xml:lang="pl">Nagłówek listu zaszyfrowanego PGP/MIME</comment>
- <comment xml:lang="pt">cabeçalho de mensagem encriptada com PGP/MIME</comment>
- <comment xml:lang="pt_BR">Cabeçalho de mensagem criptografada PGP/MIME</comment>
- <comment xml:lang="ro">Antet de mesaj encriptat PGP/MIME</comment>
- <comment xml:lang="ru">Заголовок сообщения, зашифрованный PGP/MIME</comment>
- <comment xml:lang="sk">Hlavičke správy zašifrovaná pomocou PGP/MIME</comment>
- <comment xml:lang="sl">Datoteka glave šifriranega sporočila PGP/MIME</comment>
- <comment xml:lang="sq">Header mesazhi të kriptuar PGP/MIME</comment>
- <comment xml:lang="sr">ПГП/МИМЕ шифровано заглавље поруке</comment>
- <comment xml:lang="sv">PGP/MIME-krypterat meddelandehuvud</comment>
- <comment xml:lang="tr">PGP/MIME-şifreli ileti başlığı</comment>
- <comment xml:lang="uk">заголовок шифрованого PGP/MIME повідомлення</comment>
- <comment xml:lang="vi">Phần đầu thông điệp đã mật mã bằng PGP/MIME</comment>
- <comment xml:lang="zh_CN">PGP/MIME 加密的信件头</comment>
<comment xml:lang="zh_TW">PGP/MIME 加密訊息標頭</comment>
- <sub-class-of type="text/plain"/>
- <generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="-----BEGIN PGP MESSAGE-----" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">PGP/MIME 加密的信件头</comment>
+ <comment xml:lang="vi">Phần đầu thông điệp đã mật mã bằng PGP/MIME</comment>
+ <comment xml:lang="uk">заголовок шифрованого PGP/MIME повідомлення</comment>
+ <comment xml:lang="tr">PGP/MIME-şifreli ileti başlığı</comment>
+ <comment xml:lang="sv">PGP/MIME-krypterat meddelandehuvud</comment>
+ <comment xml:lang="sr">ПГП/МИМЕ шифровано заглавље поруке</comment>
+ <comment xml:lang="sq">krye mesazhi fshehtëzuar me PGP/MIME</comment>
+ <comment xml:lang="sl">Datoteka glave šifriranega sporočila PGP/MIME</comment>
+ <comment xml:lang="si">PGP/MIME-සංකේතනය කළ පණිවිඩ ශීර්ෂකය</comment>
+ <comment xml:lang="sk">Hlavičke správy zašifrovaná pomocou PGP/MIME</comment>
+ <comment xml:lang="ru">Заголовок сообщения, зашифрованный PGP/MIME</comment>
+ <comment xml:lang="ro">Antet de mesaj encriptat PGP/MIME</comment>
+ <comment xml:lang="pt_BR">Cabeçalho de mensagem criptografada PGP/MIME</comment>
+ <comment xml:lang="pt">cabeçalho de mensagem encriptada com PGP/MIME</comment>
+ <comment xml:lang="pl">Nagłówek listu zaszyfrowanego PGP/MIME</comment>
+ <comment xml:lang="oc">entèsta de messatge encodat PGP/MIME</comment>
+ <comment xml:lang="nn">PGP/MIME-kryptert meldingshovud</comment>
+ <comment xml:lang="nl">PGP/MIME-versleutelde berichtkopregels</comment>
+ <comment xml:lang="nb">PGP/MIME-kryptert meldingshode</comment>
+ <comment xml:lang="ms">Pengepala mesej terenkripsi PGP/MIME</comment>
+ <comment xml:lang="lv">PGP/MIME-šifrēta ziņas galvene</comment>
+ <comment xml:lang="lt">PGP/MIME užšifruota žinutės antraštė</comment>
+ <comment xml:lang="ko">PGP/MIME으로 암호화된 메시지 헤더</comment>
+ <comment xml:lang="kk">PGP/MIME-шифрленген мәлімдеме тақырыптамасы</comment>
+ <comment xml:lang="ja">PGP/MIME 暗号化メッセージヘッダー</comment>
+ <comment xml:lang="it">Intestazione messaggio PGP/MIME-encrypted</comment>
+ <comment xml:lang="is">PGP-dulritaður skilaboðahaus</comment>
+ <comment xml:lang="id">Tajuk pesan terenkripsi PGP/MIME</comment>
+ <comment xml:lang="ia">Capite de message cryptate con PGP/MIME</comment>
+ <comment xml:lang="hu">PGP/MIME titkosított üzenetfejléc</comment>
+ <comment xml:lang="hr">PGP/MIME-šrifrirano zaglavlje poruke</comment>
+ <comment xml:lang="he">כותר של קובץ מוצפן מסוג PGP/MIME</comment>
+ <comment xml:lang="gl">cabeceira de mensaxe cifrado PGP/MIME</comment>
+ <comment xml:lang="ga">ceanntásc teachtaireachta ionchódaithe le PGP/MIME</comment>
+ <comment xml:lang="fur">intestazion messaç cifrât in PGP/MIME</comment>
+ <comment xml:lang="fr">en-tête de message codé PGP/MIME</comment>
+ <comment xml:lang="fo">PGP/MIME-encrypted boð tekshøvd</comment>
+ <comment xml:lang="fi">PGP/MIME-salattu viestiotsake</comment>
+ <comment xml:lang="eu">PGP/MIME zifratutako mezu-goiburua</comment>
+ <comment xml:lang="es">cabecera de mensaje cifrado PGP/MIME</comment>
+ <comment xml:lang="eo">PGP/MIME-ĉifrita ĉapo de mesaĝo</comment>
+ <comment xml:lang="en_GB">PGP/MIME-encrypted message header</comment>
+ <comment xml:lang="el">Κεφαλίδα μηνύματος κρυπτογραφημένου κατά PGP/MIME</comment>
+ <comment xml:lang="de">PGP/MIME-verschlüsselter Nachrichtenkopf</comment>
+ <comment xml:lang="da">PGP-/MIME-krypteret meddelelseshoved</comment>
+ <comment xml:lang="cs">záhlaví zprávy zašifrované pomocí PGP/MIME</comment>
+ <comment xml:lang="ca">capçalera de missatge amb xifrat PGP/MIME</comment>
+ <comment xml:lang="bg">Заглавна част на шифрирано съобщение — PGP/MIME</comment>
+ <comment xml:lang="be@latin">Zahałovak paviedamleńnia, zašyfravany ŭ PGP/MIME</comment>
+ <comment xml:lang="be">загаловак паведамлення з шыфраваннем PGP/MIME</comment>
+ <comment xml:lang="ast">Testera de mensaxe cifrada en PGP/MIME</comment>
+ <comment xml:lang="ar">ترويسة رسالة PGP/MIME-مشفرة</comment>
+ <comment xml:lang="af">Kop van PGP/MIME-geënkripteerde boodskap</comment>
+ <magic>
+ <match type="string" value="-----BEGIN PGP MESSAGE-----" offset="0"/>
</magic>
<glob pattern="*.pgp"/>
<glob pattern="*.gpg"/>
- <glob weight="10" pattern="*.asc"/>
+ <glob pattern="*.asc" weight="10"/>
<alias type="application/pgp"/>
</mime-type>
<mime-type type="application/pgp-keys">
<comment>PGP keys</comment>
- <comment xml:lang="ar">مفاتيح PGP</comment>
- <comment xml:lang="ast">Claves PGP</comment>
- <comment xml:lang="az">PGP açarları</comment>
- <comment xml:lang="be@latin">Klučy PGP</comment>
- <comment xml:lang="bg">Ключове — PGP</comment>
- <comment xml:lang="ca">claus PGP</comment>
- <comment xml:lang="cs">klíče PGP</comment>
- <comment xml:lang="cy">Allweddi PGP</comment>
- <comment xml:lang="da">PGP-nøgler</comment>
- <comment xml:lang="de">PGP-Schlüssel</comment>
- <comment xml:lang="el">Κλειδιά PGP</comment>
- <comment xml:lang="en_GB">PGP keys</comment>
- <comment xml:lang="eo">PGP-ŝlosiloj</comment>
- <comment xml:lang="es">claves PGP</comment>
- <comment xml:lang="eu">PGP giltzak</comment>
- <comment xml:lang="fi">PGP-avainrengas</comment>
- <comment xml:lang="fo">PGP lyklar</comment>
- <comment xml:lang="fr">clés PGP</comment>
- <comment xml:lang="ga">eochracha PGP</comment>
- <comment xml:lang="gl">Chaves PGP</comment>
- <comment xml:lang="he">מפתחות PGP</comment>
- <comment xml:lang="hr">PGP ključevi</comment>
- <comment xml:lang="hu">PGP-kulcs</comment>
- <comment xml:lang="ia">Claves PGP</comment>
- <comment xml:lang="id">Kunci PGP</comment>
- <comment xml:lang="it">Chiavi PGP</comment>
- <comment xml:lang="ja">PGP 鍵</comment>
- <comment xml:lang="kk">PGP кілттері</comment>
- <comment xml:lang="ko">PGP 키</comment>
- <comment xml:lang="lt">PGP raktai</comment>
- <comment xml:lang="lv">PGP atslēgas</comment>
- <comment xml:lang="ms">Kekunci PGP</comment>
- <comment xml:lang="nb">PGP-nøkler</comment>
- <comment xml:lang="nl">PGP-sleutels</comment>
- <comment xml:lang="nn">PGP-nøkler</comment>
- <comment xml:lang="oc">claus PGP</comment>
- <comment xml:lang="pl">Klucze PGP</comment>
- <comment xml:lang="pt">chaves PGP</comment>
- <comment xml:lang="pt_BR">Chaves PGP</comment>
- <comment xml:lang="ro">Chei PGP</comment>
- <comment xml:lang="ru">Ключи PGP</comment>
- <comment xml:lang="sk">Kľúče PGP</comment>
- <comment xml:lang="sl">Datoteka ključa PGP</comment>
- <comment xml:lang="sq">Kyçe PGP</comment>
- <comment xml:lang="sr">ПГП кључеви</comment>
- <comment xml:lang="sv">PGP-nycklar</comment>
- <comment xml:lang="tr">PGP anahtarları</comment>
- <comment xml:lang="uk">ключі PGP</comment>
- <comment xml:lang="vi">Khoá PGP</comment>
+ <comment xml:lang="zh_TW">PGP 金鑰</comment>
<comment xml:lang="zh_CN">PGP 密钥</comment>
- <comment xml:lang="zh_TW">PGP 鑰匙</comment>
+ <comment xml:lang="vi">Khoá PGP</comment>
+ <comment xml:lang="uk">ключі PGP</comment>
+ <comment xml:lang="tr">PGP anahtarları</comment>
+ <comment xml:lang="sv">PGP-nycklar</comment>
+ <comment xml:lang="sr">ПГП кључеви</comment>
+ <comment xml:lang="sq">kyçe PGP</comment>
+ <comment xml:lang="sl">Datoteka ključa PGP</comment>
+ <comment xml:lang="si">PGP යතුරු</comment>
+ <comment xml:lang="sk">Kľúče PGP</comment>
+ <comment xml:lang="ru">Ключи PGP</comment>
+ <comment xml:lang="ro">Chei PGP</comment>
+ <comment xml:lang="pt_BR">Chaves PGP</comment>
+ <comment xml:lang="pt">chaves PGP</comment>
+ <comment xml:lang="pl">Klucze PGP</comment>
+ <comment xml:lang="oc">claus PGP</comment>
+ <comment xml:lang="nn">PGP-nøkler</comment>
+ <comment xml:lang="nl">PGP-sleutels</comment>
+ <comment xml:lang="nb">PGP-nøkler</comment>
+ <comment xml:lang="ms">Kekunci PGP</comment>
+ <comment xml:lang="lv">PGP atslēgas</comment>
+ <comment xml:lang="lt">PGP raktai</comment>
+ <comment xml:lang="ko">PGP 키</comment>
+ <comment xml:lang="kk">PGP кілттері</comment>
+ <comment xml:lang="ka">PGP გასაღები</comment>
+ <comment xml:lang="ja">PGP 鍵</comment>
+ <comment xml:lang="it">Chiavi PGP</comment>
+ <comment xml:lang="is">PGP-lyklar</comment>
+ <comment xml:lang="id">Kunci PGP</comment>
+ <comment xml:lang="ia">Claves PGP</comment>
+ <comment xml:lang="hu">PGP-kulcs</comment>
+ <comment xml:lang="hr">PGP ključevi</comment>
+ <comment xml:lang="he">מפתחות PGP</comment>
+ <comment xml:lang="gl">Chaves PGP</comment>
+ <comment xml:lang="ga">eochracha PGP</comment>
+ <comment xml:lang="fur">clâfs PGP</comment>
+ <comment xml:lang="fr">clés PGP</comment>
+ <comment xml:lang="fo">PGP lyklar</comment>
+ <comment xml:lang="fi">PGP-avainrengas</comment>
+ <comment xml:lang="eu">PGP giltzak</comment>
+ <comment xml:lang="es">claves PGP</comment>
+ <comment xml:lang="eo">PGP-ŝlosiloj</comment>
+ <comment xml:lang="en_GB">PGP keys</comment>
+ <comment xml:lang="el">Κλειδιά PGP</comment>
+ <comment xml:lang="de">PGP-Schlüssel</comment>
+ <comment xml:lang="da">PGP-nøgler</comment>
+ <comment xml:lang="cy">Allweddi PGP</comment>
+ <comment xml:lang="cs">klíče PGP</comment>
+ <comment xml:lang="ca">claus PGP</comment>
+ <comment xml:lang="bg">Ключове — PGP</comment>
+ <comment xml:lang="be@latin">Klučy PGP</comment>
+ <comment xml:lang="be">ключы PGP</comment>
+ <comment xml:lang="az">PGP açarları</comment>
+ <comment xml:lang="ast">Claves PGP</comment>
+ <comment xml:lang="ar">مفاتيح PGP</comment>
+ <comment xml:lang="af">PGP-sleutels</comment>
<acronym>PGP</acronym>
<expanded-acronym>Pretty Good Privacy</expanded-acronym>
- <sub-class-of type="text/plain"/>
- <generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="-----BEGIN PGP PUBLIC KEY BLOCK-----" type="string" offset="0"/>
- <match value="-----BEGIN PGP PRIVATE KEY BLOCK-----" type="string" offset="0"/>
- <match value="0x9501" type="big16" offset="0"/>
- <match value="0x9500" type="big16" offset="0"/>
- <match value="0x9900" type="big16" offset="0"/>
- <match value="0x9901" type="big16" offset="0"/>
+ <magic>
+ <match type="string" value="-----BEGIN PGP PUBLIC KEY BLOCK-----" offset="0"/>
+ <match type="string" value="-----BEGIN PGP PRIVATE KEY BLOCK-----" offset="0"/>
+ <match type="big16" value="0x9501" offset="0"/>
+ <match type="big16" value="0x9500" offset="0"/>
+ <match type="big16" value="0x9900" offset="0"/>
+ <match type="big16" value="0x9901" offset="0"/>
</magic>
<glob pattern="*.skr"/>
<glob pattern="*.pkr"/>
- <glob weight="10" pattern="*.asc"/>
+ <glob pattern="*.asc" weight="10"/>
<glob pattern="*.pgp"/>
<glob pattern="*.gpg"/>
+ <glob pattern="*.key"/>
</mime-type>
<mime-type type="application/pgp-signature">
- <comment>detached OpenPGP signature</comment>
- <comment xml:lang="ar">إمضاء OpenPGP مفصول</comment>
- <comment xml:lang="be@latin">adłučany podpis OpenPGP</comment>
- <comment xml:lang="bg">Отделен подпис — OpenPGP</comment>
- <comment xml:lang="ca">signatura OpenPGP abstreta</comment>
- <comment xml:lang="cs">oddělený podpis OpenPGP</comment>
- <comment xml:lang="da">frigjort OpenPGP-signatur</comment>
- <comment xml:lang="de">isolierte OpenPGP-Signatur</comment>
- <comment xml:lang="el">Αποκομμένη υπογραφή OpenPGP</comment>
- <comment xml:lang="en_GB">detached OpenPGP signature</comment>
- <comment xml:lang="eo">dekroĉa OpenPGP-subskribo</comment>
- <comment xml:lang="es">firma OpenPGP separada</comment>
- <comment xml:lang="eu">desuzturtako OpenPGP sinadura</comment>
- <comment xml:lang="fi">erillinen OpenPGP-allekirjoitus</comment>
- <comment xml:lang="fo">skild OpenPGP undirskrift</comment>
- <comment xml:lang="fr">signature OpenPGP détachée</comment>
- <comment xml:lang="ga">síniú OpenPGP scartha</comment>
- <comment xml:lang="gl">sinatura de OpenPGP independente</comment>
- <comment xml:lang="he">חתימת OpenPGP מנותקת</comment>
- <comment xml:lang="hr">Odvojen OpenPGP potpis</comment>
- <comment xml:lang="hu">leválasztott OpenPGP-aláírás</comment>
- <comment xml:lang="ia">Signatura OpenPGP distachate</comment>
- <comment xml:lang="id">tanda tangan OpenPGP yang terlepas</comment>
- <comment xml:lang="it">Firma staccata OpenPGP</comment>
- <comment xml:lang="ja">分離 OpenPGP 署名</comment>
- <comment xml:lang="kk">бөлінген OpenPGP қолтаңбасы</comment>
- <comment xml:lang="ko">분리된 OpenPGP 서명</comment>
- <comment xml:lang="lt">neprisegtas OpenPGP parašas</comment>
- <comment xml:lang="lv">atvienots OpenPGP paraksts</comment>
- <comment xml:lang="ms">Tandatangan OpenPGP terlerai</comment>
- <comment xml:lang="nb">frakoblet OpenPGP-signatur</comment>
- <comment xml:lang="nl">losse OpenPGP-ondertekening</comment>
- <comment xml:lang="nn">fråkopla OpenPGP-signatur</comment>
- <comment xml:lang="oc">signatura OpenPGP destacada</comment>
- <comment xml:lang="pl">Oddzielony podpis OpenPGP</comment>
- <comment xml:lang="pt">assinatura OpenPGP solta</comment>
- <comment xml:lang="pt_BR">Assinatura OpenPGP destacada</comment>
- <comment xml:lang="ro">semnătură OpenPGP detașată</comment>
+ <comment>Detached OpenPGP signature</comment>
+ <comment xml:lang="zh_TW">卸離的 OpenGPG 簽章</comment>
+ <comment xml:lang="uk">відокремлений підпис OpenPGP</comment>
+ <comment xml:lang="sv">Frikopplad OpenPGP-signatur</comment>
<comment xml:lang="ru">Отсоединённая подпись OpenPGP</comment>
- <comment xml:lang="sk">Oddelený podpis OpenPGP</comment>
- <comment xml:lang="sl">odpet podpis OpenPGP</comment>
- <comment xml:lang="sq">Firmë e shkëputur OpenPGP</comment>
- <comment xml:lang="sr">одвојени ОпенПГП потпис</comment>
- <comment xml:lang="sv">frikopplad OpenPGP-signatur</comment>
- <comment xml:lang="tr">müstakil OpenPGP imzası</comment>
- <comment xml:lang="uk">відокремлений OpenPGP підпис</comment>
- <comment xml:lang="vi">chữ ký OpenPGP tách rời</comment>
- <comment xml:lang="zh_CN">分离的 OpenPGP 签名</comment>
- <comment xml:lang="zh_TW">分離的 OpenPGP 簽章</comment>
- <sub-class-of type="text/plain"/>
- <generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="-----BEGIN PGP SIGNATURE-----" type="string" offset="0"/>
+ <comment xml:lang="pt_BR">Assinatura OpenPGP destacada</comment>
+ <comment xml:lang="pl">Oddzielony podpis OpenPGP</comment>
+ <comment xml:lang="it">Firma staccata OpenPGP</comment>
+ <comment xml:lang="gl">Sinatura OpenPGP desancorada</comment>
+ <comment xml:lang="eu">OpenPGP sinadura askea</comment>
+ <comment xml:lang="es">firma OpenGPG separada</comment>
+ <comment xml:lang="de">Isolierte OpenPGP-Signatur</comment>
+ <comment xml:lang="be">адлучаны подпіс OpenPGP</comment>
+ <magic>
+ <match type="string" value="-----BEGIN PGP SIGNATURE-----" offset="0"/>
</magic>
- <glob weight="10" pattern="*.asc"/>
+ <glob pattern="*.asc" weight="10"/>
<glob pattern="*.sig"/>
<glob pattern="*.pgp"/>
<glob pattern="*.gpg"/>
</mime-type>
-
+ <!-- defined in RFC 2311 -->
<mime-type type="application/pkcs7-mime">
- <comment>PKCS#7 Message or Certificate</comment>
- <comment xml:lang="ast">Mensaxe o certificáu PKCS#7</comment>
- <comment xml:lang="ca">missatge o certificat PKCS#7</comment>
- <comment xml:lang="cs">zpráva nebo certifikát PKCS#7</comment>
- <comment xml:lang="da">PKCS#7-besked eller certifikat</comment>
- <comment xml:lang="de">PKCS#7 Nachricht oder Zertifikat</comment>
- <comment xml:lang="el">Μήνυμα ή πιστοποιητικό PKCS#7</comment>
- <comment xml:lang="en_GB">PKCS#7 Message or Certificate</comment>
- <comment xml:lang="es">mensaje o certificado PKCS#7</comment>
- <comment xml:lang="eu">PKCS#7 mezu edo zertifikazioa</comment>
- <comment xml:lang="fi">PKCS#7-viesti tai -varmenne</comment>
- <comment xml:lang="fr">Message ou certificat PKCS#7</comment>
- <comment xml:lang="ga">Teachtaireacht nó Teastas PKCS#7</comment>
- <comment xml:lang="gl">Mensaxe ou certificado PKCS#7</comment>
- <comment xml:lang="he">הודעה או אישור מסוג PKCS#7</comment>
- <comment xml:lang="hr">PKCS#7 poruka ili vjerodajnica</comment>
- <comment xml:lang="hu">PKCS#7 üzenet vagy tanúsítvány</comment>
- <comment xml:lang="ia">Message o certificato PKCS#7</comment>
- <comment xml:lang="id">Sertifikat atau Pesan PKCS#7</comment>
- <comment xml:lang="it">Messaggio o certificato PKCS#7</comment>
- <comment xml:lang="ja">PKCS#7 メッセージまたは証明書</comment>
- <comment xml:lang="kk">PKCS#7 хабарламасы не сертификаты</comment>
- <comment xml:lang="ko">PKCS#7 메시지 또는 인증서</comment>
- <comment xml:lang="lv">PKCS#7 ziņojums vai sertifikāts</comment>
- <comment xml:lang="oc">Messatge o certificat PKCS#7</comment>
- <comment xml:lang="pl">Wiadomość lub certyfikat PKCS#7</comment>
- <comment xml:lang="pt">Mensagem ou certificado PKCS#7</comment>
- <comment xml:lang="pt_BR">Certificado ou Mensagem PKCS#7</comment>
- <comment xml:lang="ru">Сообщение или сертификат PKCS#7</comment>
- <comment xml:lang="sk">Správa alebo certifikát PKCS#7</comment>
- <comment xml:lang="sl">Sporočilo ali dovoljenje PKCS#7</comment>
- <comment xml:lang="sr">ПКЦС#7 порука или уверење</comment>
- <comment xml:lang="sv">PKCS#7-meddelande eller -certifikat</comment>
- <comment xml:lang="tr">PKCS#7 İletisi veya Sertifikası</comment>
- <comment xml:lang="uk">повідомлення або сертифікат PKCS#7</comment>
- <comment xml:lang="zh_CN">PKCS#7 消息或证书</comment>
- <comment xml:lang="zh_TW">PKCS#7 訊息或憑證</comment>
+ <comment>PKCS#7 file</comment>
+ <comment xml:lang="zh_TW">PKCS#7 檔案</comment>
+ <comment xml:lang="zh_CN">PKCS#7 文件</comment>
+ <comment xml:lang="uk">файл PKCS#7</comment>
+ <comment xml:lang="tr">PKCS#7 dosyası</comment>
+ <comment xml:lang="sv">PKCS#7-fil</comment>
+ <comment xml:lang="sq">kartelë PKCS#7</comment>
+ <comment xml:lang="sl">Datoteka PKCS#7</comment>
+ <comment xml:lang="si">PKCS#7 ගොනුව</comment>
+ <comment xml:lang="sk">Súbor PKCS#7</comment>
+ <comment xml:lang="ru">Файл PKCS#7</comment>
+ <comment xml:lang="pt_BR">Arquivo PKCS#7</comment>
+ <comment xml:lang="pt">ficheiro PKCS#7</comment>
+ <comment xml:lang="pl">Plik PKCS#7</comment>
+ <comment xml:lang="oc">fichièr PKCS#7</comment>
+ <comment xml:lang="nl">PKCS#7-bestand</comment>
+ <comment xml:lang="lt">PKCS#7 failas</comment>
+ <comment xml:lang="ko">PKCS#7 파일</comment>
+ <comment xml:lang="kk">PKCS#7 файлы</comment>
+ <comment xml:lang="ka">PKCS#7 ფაილი</comment>
+ <comment xml:lang="ja">PKCS#7 ファイル</comment>
+ <comment xml:lang="it">File PKCS#7</comment>
+ <comment xml:lang="is">PKCS#7 skrá</comment>
+ <comment xml:lang="id">Berkas PKCS#7</comment>
+ <comment xml:lang="hu">PKCS#7 fájl</comment>
+ <comment xml:lang="hr">PKCS#7 datoteka</comment>
+ <comment xml:lang="he">קובץ PKCS#7</comment>
+ <comment xml:lang="gl">Ficheiro PKCS#7</comment>
+ <comment xml:lang="fr">fichier PKCS#7</comment>
+ <comment xml:lang="fi">PKCS#7-tiedosto</comment>
+ <comment xml:lang="eu">PKCS#7 fitxategia</comment>
+ <comment xml:lang="es">archivo PKCS#7</comment>
+ <comment xml:lang="en_GB">PKCS#7 file</comment>
+ <comment xml:lang="de">PKCS#7-Datei</comment>
+ <comment xml:lang="da">PKCS#7-fil</comment>
+ <comment xml:lang="ca">fitxer PKCS#7</comment>
+ <comment xml:lang="bg">Файл за PKCS#7</comment>
+ <comment xml:lang="be">файл PKCS#7</comment>
+ <comment xml:lang="ar">ملف PKCS#7</comment>
<acronym>PKCS</acronym>
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<generic-icon name="text-x-generic"/>
@@ -1424,55 +1441,19 @@
<glob pattern="*.p7m"/>
</mime-type>
<mime-type type="application/pkcs7-signature">
- <comment>detached S/MIME signature</comment>
- <comment xml:lang="ar">إمضاء S/MIME مفصول</comment>
- <comment xml:lang="be@latin">adłučany podpis S/MIME</comment>
- <comment xml:lang="bg">Отделен подпис — S/MIME</comment>
- <comment xml:lang="ca">signatura S/MIME abstreta</comment>
- <comment xml:lang="cs">oddělený podpis S/MIME</comment>
- <comment xml:lang="da">frigjort S/MIME-signatur</comment>
- <comment xml:lang="de">isolierte S/MIME-Signatur</comment>
- <comment xml:lang="el">Αποκομμένη υπογραφή S/MIME</comment>
- <comment xml:lang="en_GB">detached S/MIME signature</comment>
- <comment xml:lang="eo">dekroĉa S/MIME-subskribo</comment>
- <comment xml:lang="es">firma S/MIME separada</comment>
- <comment xml:lang="eu">desuzturtako S/MIME sinadura</comment>
- <comment xml:lang="fi">erillinen S/MIME-allekirjoitus</comment>
- <comment xml:lang="fo">skild S/MIME undirskrift</comment>
- <comment xml:lang="fr">signature S/MIME détachée</comment>
- <comment xml:lang="ga">síniú S/MIME scartha</comment>
- <comment xml:lang="gl">sinatura S/MIME independente</comment>
- <comment xml:lang="he">חתימת S/MIME מנותקת</comment>
- <comment xml:lang="hr">Odvojen S/MIME potpis</comment>
- <comment xml:lang="hu">leválasztott S/MIME-aláírás</comment>
- <comment xml:lang="ia">Signatura S/MIME distachate</comment>
- <comment xml:lang="id">tanda tangan S/MIME yang terlepas</comment>
- <comment xml:lang="it">Firma staccata S/MIME</comment>
- <comment xml:lang="ja">分離 S/MIME 署名</comment>
- <comment xml:lang="kk">бөлінген S/MIME қолтаңбасы</comment>
- <comment xml:lang="ko">분리된 S/MIME 서명</comment>
- <comment xml:lang="lt">neprisegtas S/MIME parašas</comment>
- <comment xml:lang="lv">atvienots S/MIME paraksts</comment>
- <comment xml:lang="ms">Tandatangan S/MIME terlerai</comment>
- <comment xml:lang="nb">frakoblet S/MIME-signatur</comment>
- <comment xml:lang="nl">losse S/MIME-ondertekening</comment>
- <comment xml:lang="nn">fråkopla S/MIME-signatur</comment>
- <comment xml:lang="oc">signatura S/MIME destacada</comment>
- <comment xml:lang="pl">Oddzielony podpis S/MIME</comment>
- <comment xml:lang="pt">assinatura S/MIME solta</comment>
- <comment xml:lang="pt_BR">Assinatura S/MIME destacada</comment>
- <comment xml:lang="ro">semnătură S/MIME detașată</comment>
+ <comment>Detached S/MIME signature</comment>
+ <comment xml:lang="zh_TW">卸離的 S/MIME 簽章</comment>
+ <comment xml:lang="uk">відокремлений підпис S/MIME</comment>
+ <comment xml:lang="sv">Frikopplad S/MIME-signatur</comment>
<comment xml:lang="ru">Отсоединённая подпись S/MIME</comment>
- <comment xml:lang="sk">Oddelený podpis S/MIME</comment>
- <comment xml:lang="sl">odpet podpis S/MIME</comment>
- <comment xml:lang="sq">Firmë e shkëputur S/MIME</comment>
- <comment xml:lang="sr">одвојени С/МИМЕ потпис</comment>
- <comment xml:lang="sv">frikopplad S/MIME-signatur</comment>
- <comment xml:lang="tr">müstakil S/MIME imzası</comment>
- <comment xml:lang="uk">відокремлений S/MIME підпис</comment>
- <comment xml:lang="vi">chữ ký S/MIME tách rời</comment>
- <comment xml:lang="zh_CN">分离的 S/MIME 签名</comment>
- <comment xml:lang="zh_TW">分離的 S/MIME 簽章</comment>
+ <comment xml:lang="pt_BR">Assinatura S/MIME destacada</comment>
+ <comment xml:lang="pl">Oddzielony podpis S/MIME</comment>
+ <comment xml:lang="it">Firma staccata S/MIME</comment>
+ <comment xml:lang="gl">Sinatura S/MIME desancorada</comment>
+ <comment xml:lang="eu">S/MIME sinadura askea</comment>
+ <comment xml:lang="es">firma S/MIME separada</comment>
+ <comment xml:lang="de">Isolierte S/MIME-Signatur</comment>
+ <comment xml:lang="be">адлучаны подпіс S/MIME</comment>
<acronym>S/MIME</acronym>
<expanded-acronym>Secure/Multipurpose Internet Mail Extensions</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -1481,105 +1462,155 @@
</mime-type>
<mime-type type="application/pkcs8">
<comment>PKCS#8 private key</comment>
- <comment xml:lang="ar">رزمة الشهادة PKCS#8</comment>
- <comment xml:lang="bg">Ключ, частен — PKCS#8</comment>
- <comment xml:lang="ca">clau privada PKCS#8</comment>
- <comment xml:lang="cs">soukromý klíč PKCS#8</comment>
- <comment xml:lang="da">PKCS#8-privat nøgle</comment>
- <comment xml:lang="de">PKCS#8 Geheimer Schlüssel</comment>
- <comment xml:lang="el">Ιδιωτικό κλειδί PKCS#8</comment>
- <comment xml:lang="en_GB">PKCS#8 private key</comment>
- <comment xml:lang="es">clave privada PCKS#8</comment>
- <comment xml:lang="eu">PKCS#8 gako pribatua</comment>
- <comment xml:lang="fi">PKCS#8 yksityinen avain</comment>
- <comment xml:lang="fo">PKCS#8 privatur lykil</comment>
- <comment xml:lang="fr">clé privée PKCS#8</comment>
- <comment xml:lang="ga">eochair phríobháideach PKCS#8</comment>
- <comment xml:lang="gl">Chave privada PKCS#8</comment>
- <comment xml:lang="he">מפתח פרטי של PKCS#8</comment>
- <comment xml:lang="hr">PKCS#8 privatni ključ</comment>
- <comment xml:lang="hu">PKCS#8 személyes kulcs</comment>
- <comment xml:lang="ia">Clave private PKCS#8</comment>
- <comment xml:lang="id">Kunci privat PKCS#8</comment>
- <comment xml:lang="it">Chiave privata PKCS#8</comment>
- <comment xml:lang="ja">PKCS#8 秘密鍵</comment>
- <comment xml:lang="kk">PKCS#8 меншік кілті</comment>
- <comment xml:lang="ko">PKCS#8 개인 키</comment>
- <comment xml:lang="lt">PKCS#8 asmeninis raktas</comment>
- <comment xml:lang="lv">PKCS#8 privātā atslēga</comment>
- <comment xml:lang="nl">PKCS#8 private sleutel</comment>
- <comment xml:lang="oc">clau privada PKCS#8</comment>
- <comment xml:lang="pl">Klucz prywatny PKCS#8</comment>
- <comment xml:lang="pt">chave privada PKCS#8</comment>
- <comment xml:lang="pt_BR">Chave privada PKCS#8</comment>
- <comment xml:lang="ro">Cheie privată PKCS#8</comment>
- <comment xml:lang="ru">Личный ключ PKCS#8</comment>
- <comment xml:lang="sk">Súkromný kľúč PKCS#8</comment>
- <comment xml:lang="sl">Datoteka osebnega ključa PKCS#8</comment>
- <comment xml:lang="sr">ПКЦС#8 лични кључ</comment>
- <comment xml:lang="sv">Privat PKCS#8-nyckel</comment>
- <comment xml:lang="tr">PKCS#8 özel anahtarı</comment>
- <comment xml:lang="uk">закритий ключ PKCS#8</comment>
- <comment xml:lang="zh_CN">PKCS#8 私钥</comment>
<comment xml:lang="zh_TW">PKCS#8 私人金鑰</comment>
+ <comment xml:lang="zh_CN">PKCS#8 私钥</comment>
+ <comment xml:lang="uk">закритий ключ PKCS#8</comment>
+ <comment xml:lang="tr">PKCS#8 özel anahtarı</comment>
+ <comment xml:lang="sv">Privat PKCS#8-nyckel</comment>
+ <comment xml:lang="sr">ПКЦС#8 лични кључ</comment>
+ <comment xml:lang="sq">kyç privat PKCS#8</comment>
+ <comment xml:lang="sl">Datoteka osebnega ključa PKCS#8</comment>
+ <comment xml:lang="si">PKCS#8 පුද්ගලික යතුර</comment>
+ <comment xml:lang="sk">Súkromný kľúč PKCS#8</comment>
+ <comment xml:lang="ru">Личный ключ PKCS#8</comment>
+ <comment xml:lang="ro">Cheie privată PKCS#8</comment>
+ <comment xml:lang="pt_BR">Chave privada PKCS#8</comment>
+ <comment xml:lang="pt">chave privada PKCS#8</comment>
+ <comment xml:lang="pl">Klucz prywatny PKCS#8</comment>
+ <comment xml:lang="oc">clau privada PKCS#8</comment>
+ <comment xml:lang="nl">PKCS#8-privésleutel</comment>
+ <comment xml:lang="lv">PKCS#8 privātā atslēga</comment>
+ <comment xml:lang="lt">PKCS#8 asmeninis raktas</comment>
+ <comment xml:lang="ko">PKCS#8 개인 키</comment>
+ <comment xml:lang="kk">PKCS#8 меншік кілті</comment>
+ <comment xml:lang="ja">PKCS#8 秘密鍵</comment>
+ <comment xml:lang="it">Chiave privata PKCS#8</comment>
+ <comment xml:lang="is">PKCS#8 einkalykill</comment>
+ <comment xml:lang="id">Kunci privat PKCS#8</comment>
+ <comment xml:lang="ia">Clave private PKCS#8</comment>
+ <comment xml:lang="hu">PKCS#8 személyes kulcs</comment>
+ <comment xml:lang="hr">PKCS#8 privatni ključ</comment>
+ <comment xml:lang="he">מפתח פרטי של PKCS#8</comment>
+ <comment xml:lang="gl">Chave privada PKCS#8</comment>
+ <comment xml:lang="ga">eochair phríobháideach PKCS#8</comment>
+ <comment xml:lang="fur">clâf privade PKCS#8</comment>
+ <comment xml:lang="fr">clé privée PKCS#8</comment>
+ <comment xml:lang="fo">PKCS#8 privatur lykil</comment>
+ <comment xml:lang="fi">PKCS#8 yksityinen avain</comment>
+ <comment xml:lang="eu">PKCS#8 gako pribatua</comment>
+ <comment xml:lang="es">clave privada PCKS#8</comment>
+ <comment xml:lang="en_GB">PKCS#8 private key</comment>
+ <comment xml:lang="el">Ιδιωτικό κλειδί PKCS#8</comment>
+ <comment xml:lang="de">Privater PKCS#8-Schlüssel</comment>
+ <comment xml:lang="da">PKCS#8-privat nøgle</comment>
+ <comment xml:lang="cs">soukromý klíč PKCS#8</comment>
+ <comment xml:lang="ca">clau privada PKCS#8</comment>
+ <comment xml:lang="bg">Ключ — PKCS#8, частен</comment>
+ <comment xml:lang="be">закрыты ключ PKCS#8</comment>
+ <comment xml:lang="ar">رزمة شهادة PKCS#8</comment>
+ <comment xml:lang="af">PKCS#8- private sleutel</comment>
<acronym>PKCS</acronym>
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<glob pattern="*.p8"/>
</mime-type>
<mime-type type="application/pkcs8-encrypted">
<comment>PKCS#8 private key (encrypted)</comment>
+ <comment xml:lang="zh_TW">PKCS#8 私人金鑰 (加密)</comment>
+ <comment xml:lang="zh_CN">PKCS#8 私钥(已加密)</comment>
+ <comment xml:lang="uk">закритий ключ PKCS#8 (зашифрований)</comment>
+ <comment xml:lang="tr">PKCS#8 özel anahtar (şifrelenmiş)</comment>
+ <comment xml:lang="sv">Privat PKCS#8-nyckel (krypterad)</comment>
+ <comment xml:lang="sq">ky privat PKCS#8 (i fshehtëzuar)</comment>
+ <comment xml:lang="sl">Zasebni ključ PKCS#8 (širfirano)</comment>
+ <comment xml:lang="si">PKCS#8 පුද්ගලික යතුර (සංකේතනය කළ)</comment>
+ <comment xml:lang="sk">Súkromný kľúč PKCS#8 (šifrovaný)</comment>
+ <comment xml:lang="ru">Личный ключ PKCS#8 (зашифрованный)</comment>
+ <comment xml:lang="pt_BR">Chave privada PKCS#8 (criptografada)</comment>
+ <comment xml:lang="pt">chave privada PKCS#8 (encriptada)</comment>
+ <comment xml:lang="pl">Klucz prywatny PKCS#8 (zaszyfrowany)</comment>
+ <comment xml:lang="nl">PKCS#8-privésleutel (versleuteld)</comment>
+ <comment xml:lang="ko">PKCS#8 개인 키(암호화됨)</comment>
+ <comment xml:lang="kk">PKCS#8 жеке кілті (шифрленген)</comment>
+ <comment xml:lang="ja">PKCS#8 プライベートキー (暗号化)</comment>
+ <comment xml:lang="it">Chiave privata PKCS#8 (cifrata)</comment>
+ <comment xml:lang="is">PKCS#8 einkalykill (dulritaður)</comment>
+ <comment xml:lang="id">Kunci privat PKCS#8 (terenkripsi)</comment>
+ <comment xml:lang="hu">PKCS#8 személyes kulcs (titkosított)</comment>
+ <comment xml:lang="hr">PKCS#8 privatni ključ (šifriran)</comment>
+ <comment xml:lang="he">מפתח פרטי מסוג PKCS#8 (מוצפן)</comment>
+ <comment xml:lang="gl">Chave privada PKCS#8 (cifrada)</comment>
+ <comment xml:lang="ga">eochair phríobháideach PKCS#8 (criptithe)</comment>
+ <comment xml:lang="fur">clâf privade PKCS#8 (cifrade)</comment>
+ <comment xml:lang="fr">clé privée PKCS#8 (chiffrée)</comment>
+ <comment xml:lang="fi">PKCS#8 yksityinen avain (salattu)</comment>
+ <comment xml:lang="eu">PKCS#8 gako pribatua (zifratua)</comment>
+ <comment xml:lang="es">clave privada PKCS#8 (cifrada)</comment>
+ <comment xml:lang="en_GB">PKCS#8 private key (encrypted)</comment>
+ <comment xml:lang="de">Privater PKCS#8-Schlüssel (verschlüsselt)</comment>
+ <comment xml:lang="da">PKCS#8-privat nøgle (krypteret)</comment>
+ <comment xml:lang="cs">soukromý klíč PKCS#8 (zašifrovaný)</comment>
+ <comment xml:lang="ca">clau privada PKCS#8 (xifrada)</comment>
+ <comment xml:lang="bg">Ключ — PKCS#8, частен, шифриран</comment>
+ <comment xml:lang="be">закрыты ключ PKCS#8 (зашыфраваны)</comment>
+ <comment xml:lang="ar">مفتاح خاص PKCS#8 (مشفر)</comment>
+ <comment xml:lang="af">PKCS#8- private sleutel (geënkripteer)</comment>
<acronym>PKCS</acronym>
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<glob pattern="*.p8e"/>
</mime-type>
<mime-type type="application/pkcs10">
<comment>PKCS#10 certification request</comment>
- <comment xml:lang="ar">طلب شهادة PKCS#10</comment>
- <comment xml:lang="be@latin">Zapyt sertyfikacyi PKCS#10</comment>
- <comment xml:lang="bg">Заявка за сертификат — PKCS#10</comment>
- <comment xml:lang="ca">sol·licitud de certificació PKCS#10</comment>
- <comment xml:lang="cs">žádost o certifikát PKCS#10</comment>
- <comment xml:lang="da">PKCS#10-certifikatanmodning</comment>
- <comment xml:lang="de">PKCS#10-Zertifikatanfrage</comment>
- <comment xml:lang="el">Αίτηση πιστοποίησης PKCS#10</comment>
- <comment xml:lang="en_GB">PKCS#10 certification request</comment>
- <comment xml:lang="es">petición de certificados PKCS#10</comment>
- <comment xml:lang="eu">PKCS#10 ziurtagirien eskaera</comment>
- <comment xml:lang="fi">PKCS#10-varmennepyyntö</comment>
- <comment xml:lang="fo">PKCS#10 váttanarumbøn</comment>
- <comment xml:lang="fr">requête de certification PKCS#10</comment>
- <comment xml:lang="ga">iarratas dheimhniúchán PKCS#10</comment>
- <comment xml:lang="gl">Solicitude de certificado PKCS#10</comment>
- <comment xml:lang="he">בקשה מוסמכת PLCS#10</comment>
- <comment xml:lang="hr">PKCS#10 zahtjev vjerodajnice</comment>
- <comment xml:lang="hu">PKCS#10-tanúsítványkérés</comment>
- <comment xml:lang="ia">Requesta de certification PKCS#10</comment>
- <comment xml:lang="id">Permintaan sertifikasi PKCS#10</comment>
- <comment xml:lang="it">Richiesta certificazione PKCS#10</comment>
- <comment xml:lang="ja">PKCS#10 証明書署名要求</comment>
- <comment xml:lang="kk">PKCS#10 сертификацияға сұранымы</comment>
- <comment xml:lang="ko">PKCS#10 인증서 요청</comment>
- <comment xml:lang="lt">PKCS#10 liudijimų užklausa</comment>
- <comment xml:lang="lv">PKCS#10 sertifikācijas pieprasījums</comment>
- <comment xml:lang="nb">PKCS#10-sertifikatforespørsel</comment>
- <comment xml:lang="nl">PKCS#10-certificatieverzoek</comment>
- <comment xml:lang="nn">PKCS#10-sertifiseringsførespurnad</comment>
- <comment xml:lang="oc">requèsta de certificacion PKCS#10</comment>
- <comment xml:lang="pl">Żądanie certyfikatu PKCS#10</comment>
- <comment xml:lang="pt">pedido de certificação PKCS#10</comment>
- <comment xml:lang="pt_BR">Pedido de certificação PKCS#12</comment>
- <comment xml:lang="ro">Cerere de certificat PKCS#10</comment>
- <comment xml:lang="ru">Запрос сертификации PKCS#10</comment>
- <comment xml:lang="sk">Požiadavka na certifikát PKCS#10</comment>
- <comment xml:lang="sl">Datoteka potrdila PKCS#10</comment>
- <comment xml:lang="sq">Kërkesë çertifikimi PKCS#10</comment>
- <comment xml:lang="sr">ПКЦС#10 зхатев уверења</comment>
- <comment xml:lang="sv">PKCS#10-certifikatbegäran</comment>
- <comment xml:lang="tr">PKCS#10 sertifika isteği</comment>
- <comment xml:lang="uk">комплект сертифікатів PKCS#10</comment>
- <comment xml:lang="vi">Yêu cầu chứng nhận PKCS#10</comment>
- <comment xml:lang="zh_CN">PKCS#10 认证请求</comment>
<comment xml:lang="zh_TW">PKCS#10 憑證請求</comment>
+ <comment xml:lang="zh_CN">PKCS#10 认证请求</comment>
+ <comment xml:lang="vi">Yêu cầu chứng nhận PKCS#10</comment>
+ <comment xml:lang="uk">комплект сертифікатів PKCS#10</comment>
+ <comment xml:lang="tr">PKCS#10 sertifika isteği</comment>
+ <comment xml:lang="sv">PKCS#10-certifikatbegäran</comment>
+ <comment xml:lang="sr">ПКЦС#10 зхатев уверења</comment>
+ <comment xml:lang="sq">kërkesë certifikimi PKCS#10</comment>
+ <comment xml:lang="sl">Datoteka potrdila PKCS#10</comment>
+ <comment xml:lang="si">PKCS#10 සහතික කිරීමේ ඉල්ලීම</comment>
+ <comment xml:lang="sk">Požiadavka na certifikát PKCS#10</comment>
+ <comment xml:lang="ru">Запрос сертификации PKCS#10</comment>
+ <comment xml:lang="ro">Cerere de certificat PKCS#10</comment>
+ <comment xml:lang="pt_BR">Pedido de certificação PKCS#12</comment>
+ <comment xml:lang="pt">pedido de certificação PKCS#10</comment>
+ <comment xml:lang="pl">Żądanie certyfikatu PKCS#10</comment>
+ <comment xml:lang="oc">requèsta de certificacion PKCS#10</comment>
+ <comment xml:lang="nn">PKCS#10-sertifiseringsførespurnad</comment>
+ <comment xml:lang="nl">PKCS#10-certificatieverzoek</comment>
+ <comment xml:lang="nb">PKCS#10-sertifikatforespørsel</comment>
+ <comment xml:lang="lv">PKCS#10 sertifikācijas pieprasījums</comment>
+ <comment xml:lang="lt">PKCS#10 liudijimų užklausa</comment>
+ <comment xml:lang="ko">PKCS#10 인증서 요청</comment>
+ <comment xml:lang="kk">PKCS#10 сертификацияға сұранымы</comment>
+ <comment xml:lang="ja">PKCS#10 証明書署名要求</comment>
+ <comment xml:lang="it">Richiesta certificazione PKCS#10</comment>
+ <comment xml:lang="is">PKCS#10 skilríkisbeiðni</comment>
+ <comment xml:lang="id">Permintaan sertifikasi PKCS#10</comment>
+ <comment xml:lang="ia">Requesta de certification PKCS#10</comment>
+ <comment xml:lang="hu">PKCS#10-tanúsítványkérés</comment>
+ <comment xml:lang="hr">PKCS#10 zahtjev vjerodajnice</comment>
+ <comment xml:lang="he">בקשה מוסמכת PLCS#10</comment>
+ <comment xml:lang="gl">Solicitude de certificado PKCS#10</comment>
+ <comment xml:lang="ga">iarratas dheimhniúchán PKCS#10</comment>
+ <comment xml:lang="fur">richieste certificazion PKCS#10</comment>
+ <comment xml:lang="fr">requête de certification PKCS#10</comment>
+ <comment xml:lang="fo">PKCS#10 váttanarumbøn</comment>
+ <comment xml:lang="fi">PKCS#10-varmennepyyntö</comment>
+ <comment xml:lang="eu">PKCS#10 ziurtagirien eskaera</comment>
+ <comment xml:lang="es">petición de certificados PKCS#10</comment>
+ <comment xml:lang="en_GB">PKCS#10 certification request</comment>
+ <comment xml:lang="el">Αίτηση πιστοποίησης PKCS#10</comment>
+ <comment xml:lang="de">PKCS#10-Zertifikatanfrage</comment>
+ <comment xml:lang="da">PKCS#10-certifikatanmodning</comment>
+ <comment xml:lang="cs">žádost o certifikát PKCS#10</comment>
+ <comment xml:lang="ca">sol·licitud de certificació PKCS#10</comment>
+ <comment xml:lang="bg">Заявка за сертификат — PKCS#10</comment>
+ <comment xml:lang="be@latin">Zapyt sertyfikacyi PKCS#10</comment>
+ <comment xml:lang="be">запыт сертыфікацыі PKCS#10</comment>
+ <comment xml:lang="ar">طلب شهادة PKCS#10</comment>
+ <comment xml:lang="af">PKCS#10-sertifiseringsversoek</comment>
<acronym>PKCS</acronym>
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<generic-icon name="text-x-generic"/>
@@ -1587,339 +1618,342 @@
</mime-type>
<mime-type type="application/pkix-cert">
<comment>X.509 certificate</comment>
- <comment xml:lang="ar">شهادة X.509</comment>
- <comment xml:lang="ast">Certificáu X.509</comment>
- <comment xml:lang="bg">Сертификат — X.509</comment>
- <comment xml:lang="ca">certificat X.509</comment>
- <comment xml:lang="cs">certifikát X.509</comment>
- <comment xml:lang="da">X.509-certifikat</comment>
- <comment xml:lang="de">X.509-Zertifikat</comment>
- <comment xml:lang="el">Πιστοποιητικό X.509</comment>
- <comment xml:lang="en_GB">X.509 certificate</comment>
- <comment xml:lang="es">certificado X.509</comment>
- <comment xml:lang="eu">X.509 ziurtagiria</comment>
- <comment xml:lang="fi">X.509-varmenne</comment>
- <comment xml:lang="fo">X.509 prógv</comment>
- <comment xml:lang="fr">certificat X.509</comment>
- <comment xml:lang="ga">teastas X.509</comment>
- <comment xml:lang="gl">Certificado X.509</comment>
- <comment xml:lang="he">אישור X.509</comment>
- <comment xml:lang="hr">X.509 vjerodajnica</comment>
- <comment xml:lang="hu">X.509 tanúsítvány</comment>
- <comment xml:lang="ia">Certificato X.509</comment>
- <comment xml:lang="id">Sertifikat X.509</comment>
- <comment xml:lang="it">Certificato X.509</comment>
- <comment xml:lang="ja">X.509 証明書</comment>
- <comment xml:lang="kk">X.509 сертификаты</comment>
- <comment xml:lang="ko">X.509 인증서</comment>
- <comment xml:lang="lt">X.509 liudijimas</comment>
- <comment xml:lang="lv">X.509 sertifikāts</comment>
- <comment xml:lang="nl">X.509 certificaat</comment>
- <comment xml:lang="oc">certificat X.509</comment>
- <comment xml:lang="pl">Certyfikat X.509</comment>
- <comment xml:lang="pt">certificado X.509</comment>
- <comment xml:lang="pt_BR">Certificado X.509</comment>
- <comment xml:lang="ro">Certificat X.509</comment>
- <comment xml:lang="ru">Сертификат X.509</comment>
- <comment xml:lang="sk">Certifikát X.509</comment>
- <comment xml:lang="sl">Datoteka potrdila X.509</comment>
- <comment xml:lang="sr">Икс.509 уверење</comment>
- <comment xml:lang="sv">X.509-certifikat</comment>
- <comment xml:lang="tr">X.509 sertifikası</comment>
- <comment xml:lang="uk">сертифікат X.509</comment>
- <comment xml:lang="zh_CN">X.509 证书</comment>
<comment xml:lang="zh_TW">X.509 憑證</comment>
+ <comment xml:lang="zh_CN">X.509 证书</comment>
+ <comment xml:lang="uk">сертифікат X.509</comment>
+ <comment xml:lang="tr">X.509 sertifikası</comment>
+ <comment xml:lang="sv">X.509-certifikat</comment>
+ <comment xml:lang="sr">Икс.509 уверење</comment>
+ <comment xml:lang="sq">dëshmi X.509</comment>
+ <comment xml:lang="sl">Datoteka potrdila X.509</comment>
+ <comment xml:lang="si">X.509 සහතිකය</comment>
+ <comment xml:lang="sk">Certifikát X.509</comment>
+ <comment xml:lang="ru">Сертификат X.509</comment>
+ <comment xml:lang="ro">Certificat X.509</comment>
+ <comment xml:lang="pt_BR">Certificado X.509</comment>
+ <comment xml:lang="pt">certificado X.509</comment>
+ <comment xml:lang="pl">Certyfikat X.509</comment>
+ <comment xml:lang="oc">certificat X.509</comment>
+ <comment xml:lang="nl">X.509-certificaat</comment>
+ <comment xml:lang="lv">X.509 sertifikāts</comment>
+ <comment xml:lang="lt">X.509 liudijimas</comment>
+ <comment xml:lang="ko">X.509 인증서</comment>
+ <comment xml:lang="kk">X.509 сертификаты</comment>
+ <comment xml:lang="ka">X.509 სერტიფიკატი</comment>
+ <comment xml:lang="ja">X.509 証明書</comment>
+ <comment xml:lang="it">Certificato X.509</comment>
+ <comment xml:lang="is">X.509 skilríki</comment>
+ <comment xml:lang="id">Sertifikat X.509</comment>
+ <comment xml:lang="ia">Certificato X.509</comment>
+ <comment xml:lang="hu">X.509 tanúsítvány</comment>
+ <comment xml:lang="hr">X.509 vjerodajnica</comment>
+ <comment xml:lang="he">אישור X.509</comment>
+ <comment xml:lang="gl">Certificado X.509</comment>
+ <comment xml:lang="ga">teastas X.509</comment>
+ <comment xml:lang="fur">certificât X.509</comment>
+ <comment xml:lang="fr">certificat X.509</comment>
+ <comment xml:lang="fo">X.509 prógv</comment>
+ <comment xml:lang="fi">X.509-varmenne</comment>
+ <comment xml:lang="eu">X.509 ziurtagiria</comment>
+ <comment xml:lang="es">certificado X.509</comment>
+ <comment xml:lang="en_GB">X.509 certificate</comment>
+ <comment xml:lang="el">Πιστοποιητικό X.509</comment>
+ <comment xml:lang="de">X.509-Zertifikat</comment>
+ <comment xml:lang="da">X.509-certifikat</comment>
+ <comment xml:lang="cs">certifikát X.509</comment>
+ <comment xml:lang="ca">certificat X.509</comment>
+ <comment xml:lang="bg">Сертификат — X.509</comment>
+ <comment xml:lang="be">сертыфікат X.509</comment>
+ <comment xml:lang="ast">Certificáu X.509</comment>
+ <comment xml:lang="ar">شهادة X.509</comment>
+ <comment xml:lang="af">X.509-sertifikaat</comment>
+ <magic>
+ <match type="string" value="-----BEGIN CERTIFICATE-----" offset="0"/>
+ <match type="string" value="-----BEGIN X509 CERTIFICATE-----" offset="0"/>
+ </magic>
<glob pattern="*.cer"/>
</mime-type>
<mime-type type="application/pkix-crl">
<comment>Certificate revocation list</comment>
- <comment xml:lang="ar">قائمة إبطال الشهادات</comment>
- <comment xml:lang="ast">Llistáu de revocación de certificaos</comment>
- <comment xml:lang="bg">Списък с отхвърлени сертификати</comment>
- <comment xml:lang="ca">llista de revocació de certificats</comment>
- <comment xml:lang="cs">seznam odvolaných certifikátů</comment>
- <comment xml:lang="da">Certifikattilbagekaldelsesliste</comment>
- <comment xml:lang="de">Liste widerrufener Zertifikate</comment>
- <comment xml:lang="el">Λίστα ανάκλησης πιστοποιητικού</comment>
- <comment xml:lang="en_GB">Certificate revocation list</comment>
- <comment xml:lang="es">lista de revocación de certificados</comment>
- <comment xml:lang="eu">Ziurtagiri-errebokatzeen zerrenda</comment>
- <comment xml:lang="fi">Varmenteiden sulkulista</comment>
- <comment xml:lang="fo">Prógv afturtøkulisti</comment>
- <comment xml:lang="fr">liste de révocation de certificat</comment>
- <comment xml:lang="ga">Liosta teastas cúlghairmthe</comment>
- <comment xml:lang="gl">lista de certificados de revogación</comment>
- <comment xml:lang="he">רשימת אישורים מבוטלים</comment>
- <comment xml:lang="hr">Popis opozvanih vjerodajnica</comment>
- <comment xml:lang="hu">Tanúsítvány-visszavonási lista</comment>
- <comment xml:lang="ia">Lista de revocation de certificatos</comment>
- <comment xml:lang="id">Daftar pencabutan sertificat (CRL)</comment>
- <comment xml:lang="it">Elenco certificati di revoca</comment>
- <comment xml:lang="ja">証明書失効リスト</comment>
- <comment xml:lang="kk">Сертификатты қайта шақыру тізімі</comment>
- <comment xml:lang="ko">인증서 철회 목록</comment>
- <comment xml:lang="lt">Panaikintų liudijimų sąrašas</comment>
- <comment xml:lang="lv">Sertifikātu atsaukšanu saraksts</comment>
- <comment xml:lang="nl">Certificaat revocation lijst</comment>
- <comment xml:lang="oc">lista de revocacion de certificat</comment>
- <comment xml:lang="pl">Lista unieważnień certyfikatów</comment>
- <comment xml:lang="pt">lista de revogação de certificados</comment>
- <comment xml:lang="pt_BR">Lista de revogação de certificado</comment>
- <comment xml:lang="ro">Listă de revocare a certificatelor</comment>
- <comment xml:lang="ru">Список аннулирования сертификатов</comment>
- <comment xml:lang="sk">Zoznam zrušených certifikátov</comment>
- <comment xml:lang="sl">Datoteka seznama preklica potrdil</comment>
- <comment xml:lang="sr">списак повлачења уверења</comment>
- <comment xml:lang="sv">Spärrlista för certifikat</comment>
- <comment xml:lang="tr">Sertifika iptal listesi</comment>
<comment xml:lang="uk">список відкликання сертифікатів</comment>
- <comment xml:lang="zh_CN">证书吊销列表</comment>
- <comment xml:lang="zh_TW">憑證撤銷清單</comment>
+ <comment xml:lang="sv">Certifikatåterkallningslista</comment>
+ <comment xml:lang="sq">listë shfuqizimi dëshmish</comment>
+ <comment xml:lang="ru">Список отзыва сертификатов</comment>
+ <comment xml:lang="pt_BR">Lista de revogação de certificado</comment>
+ <comment xml:lang="pl">Lista unieważnień certyfikatów</comment>
+ <comment xml:lang="it">Elenco certificati di revoca</comment>
+ <comment xml:lang="gl">Lista de revogación de certificados</comment>
+ <comment xml:lang="es">lista de revocación de certificados</comment>
+ <comment xml:lang="de">Zertifikat-Widerrufliste</comment>
+ <comment xml:lang="be">спіс адкліканых сертыфікатаў</comment>
+ <magic>
+ <match type="string" value="-----BEGIN X509 CRL-----" offset="0"/>
+ </magic>
<glob pattern="*.crl"/>
</mime-type>
<mime-type type="application/pkix-pkipath">
<comment>PkiPath certification path</comment>
- <comment xml:lang="ar">مسار شهادة PkiPath</comment>
- <comment xml:lang="ast">Camín de certificación PkiPath</comment>
- <comment xml:lang="bg">Сертификационна верига — PkiPath</comment>
- <comment xml:lang="ca">camí cap a la certificació PkiPath</comment>
- <comment xml:lang="cs">cesta k certifikátu PkiPath</comment>
- <comment xml:lang="da">PkiPath-certifikationssti</comment>
- <comment xml:lang="de">PkiPath-Zertifikatspfad</comment>
- <comment xml:lang="el">Διαδρομή πιστοποιητικού PkiPath</comment>
- <comment xml:lang="en_GB">PkiPath certification path</comment>
- <comment xml:lang="es">ruta de certificación PkiPath</comment>
- <comment xml:lang="eu">PkiPath ziurtagirien bide-izena</comment>
- <comment xml:lang="fi">PkiPath-varmennepolku</comment>
- <comment xml:lang="fo">PkiPath váttanleið</comment>
- <comment xml:lang="fr">chemin de certification PkiPath</comment>
- <comment xml:lang="ga">conair dheimhniúcháin PkiPath</comment>
- <comment xml:lang="gl">Ruta de certificación PkiPath</comment>
- <comment xml:lang="he">נתיב מאושר של PkiPath</comment>
- <comment xml:lang="hr">PkiPath putanja vjerodajnice</comment>
- <comment xml:lang="hu">PkiPath tanúsítványútvonal</comment>
- <comment xml:lang="ia">Cammino de certification PkiPath</comment>
- <comment xml:lang="id">Alamat sertifikasi PkiPath</comment>
- <comment xml:lang="it">Percorso certificazione PkiPath</comment>
- <comment xml:lang="ja">PkiPath 証明書パス</comment>
- <comment xml:lang="kk">PkiPath сертификаттау жолы</comment>
- <comment xml:lang="ko">PkiPath 인증서 요청</comment>
- <comment xml:lang="lt">PkiPath liudijimų maršrutas</comment>
- <comment xml:lang="lv">PkiPath sertifikāta ceļš</comment>
- <comment xml:lang="nl">PkiPath-certificatiepad</comment>
- <comment xml:lang="oc">camin de certificacion PkiPath</comment>
- <comment xml:lang="pl">Ścieżka certyfikacji PkiPath</comment>
- <comment xml:lang="pt">caminho de certificação PkiPath</comment>
- <comment xml:lang="pt_BR">Pedido de certificação PkiPath</comment>
- <comment xml:lang="ro">Cale certificare PkiPath</comment>
- <comment xml:lang="ru">Путь сертификации PkiPath</comment>
- <comment xml:lang="sk">Cesta k certifikátu PkiPath</comment>
- <comment xml:lang="sl">Datoteka poti potrdila PkiPath</comment>
- <comment xml:lang="sr">путања уверења ПкиПат-а</comment>
- <comment xml:lang="sv">PkiPath-certifikatsekvens</comment>
- <comment xml:lang="tr">PkiPath sertifika yolu</comment>
- <comment xml:lang="uk">шлях сертифікації PkiPath</comment>
- <comment xml:lang="vi">Đường dẫn cấp chứng nhận PkiPath</comment>
- <comment xml:lang="zh_CN">PkiPath 证书目录</comment>
<comment xml:lang="zh_TW">PkiPath 憑證路徑</comment>
+ <comment xml:lang="zh_CN">PkiPath 证书目录</comment>
+ <comment xml:lang="vi">Đường dẫn cấp chứng nhận PkiPath</comment>
+ <comment xml:lang="uk">шлях сертифікації PkiPath</comment>
+ <comment xml:lang="tr">PkiPath sertifika yolu</comment>
+ <comment xml:lang="sv">PkiPath-certifikatsekvens</comment>
+ <comment xml:lang="sr">путања уверења ПкиПат-а</comment>
+ <comment xml:lang="sq">shteg dëshmish PkiPath</comment>
+ <comment xml:lang="sl">Datoteka poti potrdila PkiPath</comment>
+ <comment xml:lang="si">PkiPath සහතික කිරීමේ මාර්ගය</comment>
+ <comment xml:lang="sk">Cesta k certifikátu PkiPath</comment>
+ <comment xml:lang="ru">Путь сертификации PkiPath</comment>
+ <comment xml:lang="ro">Cale certificare PkiPath</comment>
+ <comment xml:lang="pt_BR">Pedido de certificação PkiPath</comment>
+ <comment xml:lang="pt">caminho de certificação PkiPath</comment>
+ <comment xml:lang="pl">Ścieżka certyfikacji PkiPath</comment>
+ <comment xml:lang="oc">camin de certificacion PkiPath</comment>
+ <comment xml:lang="nl">PkiPath-certificatiepad</comment>
+ <comment xml:lang="lv">PkiPath sertifikāta ceļš</comment>
+ <comment xml:lang="lt">PkiPath liudijimų maršrutas</comment>
+ <comment xml:lang="ko">PkiPath 인증서 요청</comment>
+ <comment xml:lang="kk">PkiPath сертификаттау жолы</comment>
+ <comment xml:lang="ja">PkiPath 証明書パス</comment>
+ <comment xml:lang="it">Percorso certificazione PkiPath</comment>
+ <comment xml:lang="is">PkiPath vottunarslóð</comment>
+ <comment xml:lang="id">Alamat sertifikasi PkiPath</comment>
+ <comment xml:lang="ia">Cammino de certification PkiPath</comment>
+ <comment xml:lang="hu">PkiPath tanúsítványútvonal</comment>
+ <comment xml:lang="hr">PkiPath putanja vjerodajnice</comment>
+ <comment xml:lang="he">נתיב מאושר של PkiPath</comment>
+ <comment xml:lang="gl">Ruta de certificación PkiPath</comment>
+ <comment xml:lang="ga">conair dheimhniúcháin PkiPath</comment>
+ <comment xml:lang="fur">percors di certificazion PkiPath</comment>
+ <comment xml:lang="fr">chemin de certification PkiPath</comment>
+ <comment xml:lang="fo">PkiPath váttanleið</comment>
+ <comment xml:lang="fi">PkiPath-varmennepolku</comment>
+ <comment xml:lang="eu">PkiPath ziurtagirien bide-izena</comment>
+ <comment xml:lang="es">ruta de certificación PkiPath</comment>
+ <comment xml:lang="en_GB">PkiPath certification path</comment>
+ <comment xml:lang="el">Διαδρομή πιστοποιητικού PkiPath</comment>
+ <comment xml:lang="de">PkiPath-Zertifikatspfad</comment>
+ <comment xml:lang="da">PkiPath-certifikationssti</comment>
+ <comment xml:lang="cs">cesta k certifikátu PkiPath</comment>
+ <comment xml:lang="ca">camí cap a la certificació PkiPath</comment>
+ <comment xml:lang="bg">Сертификационна верига — PkiPath</comment>
+ <comment xml:lang="be">шлях сертыфікацыі PkiPath</comment>
+ <comment xml:lang="ast">Camín de certificación PkiPath</comment>
+ <comment xml:lang="ar">مسار شهادة PkiPath</comment>
+ <comment xml:lang="af">PkiPath-sertifiseringspad</comment>
<glob pattern="*.pkipath"/>
</mime-type>
<mime-type type="application/postscript">
- <comment>PS document</comment>
- <comment xml:lang="ar">مستند PS</comment>
- <comment xml:lang="ast">Documentu PS</comment>
- <comment xml:lang="be@latin">Dakument PS</comment>
- <comment xml:lang="bg">Документ — PS</comment>
- <comment xml:lang="ca">document PS</comment>
- <comment xml:lang="cs">dokument PS</comment>
- <comment xml:lang="da">PS-dokument</comment>
- <comment xml:lang="de">PS-Dokument</comment>
- <comment xml:lang="el">Έγγραφο PS</comment>
- <comment xml:lang="en_GB">PS document</comment>
- <comment xml:lang="eo">PS-dokumento</comment>
- <comment xml:lang="es">documento PS</comment>
- <comment xml:lang="eu">PS dokumentua</comment>
- <comment xml:lang="fi">PS-asiakirja</comment>
- <comment xml:lang="fo">PS skjal</comment>
- <comment xml:lang="fr">document PS</comment>
- <comment xml:lang="ga">cáipéis PS</comment>
- <comment xml:lang="gl">documento PS</comment>
- <comment xml:lang="he">מסמך PS</comment>
- <comment xml:lang="hr">PS dokument</comment>
- <comment xml:lang="hu">PS dokumentum</comment>
- <comment xml:lang="ia">Documento PS</comment>
- <comment xml:lang="id">Dokumen PS</comment>
- <comment xml:lang="it">Documento PS</comment>
- <comment xml:lang="ja">PS ドキュメント</comment>
- <comment xml:lang="kk">PS құжаты</comment>
- <comment xml:lang="ko">PS 문서</comment>
- <comment xml:lang="lt">PS dokumentas</comment>
- <comment xml:lang="lv">PS dokuments</comment>
- <comment xml:lang="nb">PS-dokument</comment>
- <comment xml:lang="nl">PS-document</comment>
- <comment xml:lang="nn">PS-dokument</comment>
- <comment xml:lang="oc">document PS</comment>
- <comment xml:lang="pl">Dokument PS</comment>
- <comment xml:lang="pt">documento PS</comment>
- <comment xml:lang="pt_BR">Documento PS</comment>
- <comment xml:lang="ro">Document PS</comment>
- <comment xml:lang="ru">Документ PS</comment>
- <comment xml:lang="sk">Dokument PS</comment>
- <comment xml:lang="sl">Dokument PS</comment>
- <comment xml:lang="sq">Dokument PS</comment>
- <comment xml:lang="sr">ПС документ</comment>
- <comment xml:lang="sv">PS-dokument</comment>
- <comment xml:lang="tr">PS belgesi</comment>
- <comment xml:lang="uk">документ PS</comment>
- <comment xml:lang="vi">Tài liệu PS</comment>
- <comment xml:lang="zh_CN">PS 文档</comment>
- <comment xml:lang="zh_TW">Ps 文件</comment>
- <acronym>PS</acronym>
- <expanded-acronym>PostScript</expanded-acronym>
+ <comment>PostScript document</comment>
+ <comment xml:lang="zh_TW">PostScript 文件</comment>
+ <comment xml:lang="zh_CN">PostScript 文档</comment>
+ <comment xml:lang="uk">документ PostScript</comment>
+ <comment xml:lang="tr">PostScript belgesi</comment>
+ <comment xml:lang="sv">Postscript-dokument</comment>
+ <comment xml:lang="sq">dokument PostScript</comment>
+ <comment xml:lang="sl">Dokument PostScript</comment>
+ <comment xml:lang="si">PostScript ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument PostScript</comment>
+ <comment xml:lang="ru">Документ PostScript</comment>
+ <comment xml:lang="pt_BR">Documento PostScript</comment>
+ <comment xml:lang="pt">documento PostScript</comment>
+ <comment xml:lang="pl">Dokument PostScript</comment>
+ <comment xml:lang="oc">document PostScript</comment>
+ <comment xml:lang="nl">PostScript-document</comment>
+ <comment xml:lang="lt">PostScript dokumentas</comment>
+ <comment xml:lang="ko">포스트스크립트 문서</comment>
+ <comment xml:lang="kk">PostScript құжаты</comment>
+ <comment xml:lang="ka">PostScript-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">PostScript ドキュメント</comment>
+ <comment xml:lang="it">Documento PostScript</comment>
+ <comment xml:lang="is">PostScript skjal</comment>
+ <comment xml:lang="id">Dokumen PostScript</comment>
+ <comment xml:lang="hu">PostScript dokumentum</comment>
+ <comment xml:lang="hr">PostScript dokument</comment>
+ <comment xml:lang="he">מסמך PostScript</comment>
+ <comment xml:lang="gl">Documento de PostScript</comment>
+ <comment xml:lang="fr">document PostScript</comment>
+ <comment xml:lang="fi">PostScript-asiakirja</comment>
+ <comment xml:lang="eu">PostScript dokumentua</comment>
+ <comment xml:lang="es">documento PostScript</comment>
+ <comment xml:lang="en_GB">PostScript document</comment>
+ <comment xml:lang="de">PostScript-Dokument</comment>
+ <comment xml:lang="da">PostScript-dokument</comment>
+ <comment xml:lang="ca">document PostScript</comment>
+ <comment xml:lang="bg">Документ — PostScrip</comment>
+ <comment xml:lang="be">дакумент PostScript</comment>
+ <comment xml:lang="ar">مستند بوست سكربت</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="\004%!" type="string" offset="0"/>
- <match value="%!" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\004%!" offset="0"/>
+ <match type="string" value="%!" offset="0"/>
</magic>
<glob pattern="*.ps"/>
</mime-type>
<mime-type type="application/prs.plucker">
<comment>Plucker document</comment>
- <comment xml:lang="ar">مستند Plucker</comment>
- <comment xml:lang="ast">Documentu Plucker</comment>
- <comment xml:lang="be@latin">Dakument Plucker</comment>
- <comment xml:lang="bg">Документ — Plucker</comment>
- <comment xml:lang="ca">document Plucker</comment>
- <comment xml:lang="cs">dokument Plucker</comment>
- <comment xml:lang="da">Pluckerdokument</comment>
- <comment xml:lang="de">Plucker-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Plucker</comment>
- <comment xml:lang="en_GB">Plucker document</comment>
- <comment xml:lang="eo">Plucker-dokumento</comment>
- <comment xml:lang="es">documento de Plucker</comment>
- <comment xml:lang="eu">Plucker dokumentua</comment>
- <comment xml:lang="fi">Plucker-asiakirja</comment>
- <comment xml:lang="fo">Plucker skjal</comment>
- <comment xml:lang="fr">document Plucker</comment>
- <comment xml:lang="ga">cáipéis Plucker</comment>
- <comment xml:lang="gl">documento de Plucker</comment>
- <comment xml:lang="he">מסמך של Plucker</comment>
- <comment xml:lang="hr">Plucker dokument</comment>
- <comment xml:lang="hu">Plucker dokumentum</comment>
- <comment xml:lang="ia">Documento Plucker</comment>
- <comment xml:lang="id">Dokumen Plucker</comment>
- <comment xml:lang="it">Documento Plucker</comment>
- <comment xml:lang="ja">Plucker ドキュメント</comment>
- <comment xml:lang="kk">Plucker құжаты</comment>
- <comment xml:lang="ko">Plucker 문서</comment>
- <comment xml:lang="lt">Plucker dokumentas</comment>
- <comment xml:lang="lv">Plucker dokuments</comment>
- <comment xml:lang="nb">Plucker-dokument</comment>
- <comment xml:lang="nl">Plucker-document</comment>
- <comment xml:lang="nn">Plucker-dokument</comment>
- <comment xml:lang="oc">document Plucker</comment>
- <comment xml:lang="pl">Dokument Plucker</comment>
- <comment xml:lang="pt">documento Plucker</comment>
- <comment xml:lang="pt_BR">Documento do Plucker</comment>
- <comment xml:lang="ro">Document Plucker</comment>
- <comment xml:lang="ru">Документ Plucker</comment>
- <comment xml:lang="sk">Dokument Plucker</comment>
- <comment xml:lang="sl">Dokument Plucker</comment>
- <comment xml:lang="sq">Dokument Plucker</comment>
- <comment xml:lang="sr">Плакер документ</comment>
- <comment xml:lang="sv">Plucker-dokument</comment>
- <comment xml:lang="tr">Plucker belgesi</comment>
- <comment xml:lang="uk">документ Plucker</comment>
- <comment xml:lang="vi">Tài liệu Plucker</comment>
- <comment xml:lang="zh_CN">Plucker 文档</comment>
<comment xml:lang="zh_TW">Plucker 文件</comment>
+ <comment xml:lang="zh_CN">Plucker 文档</comment>
+ <comment xml:lang="vi">Tài liệu Plucker</comment>
+ <comment xml:lang="uk">документ Plucker</comment>
+ <comment xml:lang="tr">Plucker belgesi</comment>
+ <comment xml:lang="sv">Plucker-dokument</comment>
+ <comment xml:lang="sr">Плакер документ</comment>
+ <comment xml:lang="sq">dokument Plucker</comment>
+ <comment xml:lang="sl">Dokument Plucker</comment>
+ <comment xml:lang="si">ප්ලකර් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Plucker</comment>
+ <comment xml:lang="ru">Документ Plucker</comment>
+ <comment xml:lang="ro">Document Plucker</comment>
+ <comment xml:lang="pt_BR">Documento do Plucker</comment>
+ <comment xml:lang="pt">documento Plucker</comment>
+ <comment xml:lang="pl">Dokument Plucker</comment>
+ <comment xml:lang="oc">document Plucker</comment>
+ <comment xml:lang="nn">Plucker-dokument</comment>
+ <comment xml:lang="nl">Plucker-document</comment>
+ <comment xml:lang="nb">Plucker-dokument</comment>
+ <comment xml:lang="lv">Plucker dokuments</comment>
+ <comment xml:lang="lt">Plucker dokumentas</comment>
+ <comment xml:lang="ko">Plucker 문서</comment>
+ <comment xml:lang="kk">Plucker құжаты</comment>
+ <comment xml:lang="ka">Plucker-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Plucker ドキュメント</comment>
+ <comment xml:lang="it">Documento Plucker</comment>
+ <comment xml:lang="is">Plucker skjal</comment>
+ <comment xml:lang="id">Dokumen Plucker</comment>
+ <comment xml:lang="ia">Documento Plucker</comment>
+ <comment xml:lang="hu">Plucker dokumentum</comment>
+ <comment xml:lang="hr">Plucker dokument</comment>
+ <comment xml:lang="he">מסמך של Plucker</comment>
+ <comment xml:lang="gl">documento de Plucker</comment>
+ <comment xml:lang="ga">cáipéis Plucker</comment>
+ <comment xml:lang="fur">document Plucker</comment>
+ <comment xml:lang="fr">document Plucker</comment>
+ <comment xml:lang="fo">Plucker skjal</comment>
+ <comment xml:lang="fi">Plucker-asiakirja</comment>
+ <comment xml:lang="eu">Plucker dokumentua</comment>
+ <comment xml:lang="es">documento de Plucker</comment>
+ <comment xml:lang="eo">Plucker-dokumento</comment>
+ <comment xml:lang="en_GB">Plucker document</comment>
+ <comment xml:lang="el">Έγγραφο Plucker</comment>
+ <comment xml:lang="de">Plucker-Dokument</comment>
+ <comment xml:lang="da">Pluckerdokument</comment>
+ <comment xml:lang="cs">dokument Plucker</comment>
+ <comment xml:lang="ca">document Plucker</comment>
+ <comment xml:lang="bg">Документ — Plucker</comment>
+ <comment xml:lang="be@latin">Dakument Plucker</comment>
+ <comment xml:lang="be">дакумент Plucker</comment>
+ <comment xml:lang="ast">Documentu Plucker</comment>
+ <comment xml:lang="ar">مستند Plucker</comment>
+ <comment xml:lang="af">Plucker-dokument</comment>
<generic-icon name="x-office-document"/>
<magic priority="80">
- <match value="DataPlkr" type="string" offset="60"/>
+ <match type="string" value="DataPlkr" offset="60"/>
</magic>
</mime-type>
<mime-type type="application/raml+yaml">
<comment>RAML document</comment>
- <comment xml:lang="ast">Documentu RAML</comment>
- <comment xml:lang="ca">document RAML</comment>
- <comment xml:lang="cs">dokument RAML</comment>
- <comment xml:lang="da">RAML-dokument</comment>
- <comment xml:lang="de">RAML-Dokument</comment>
- <comment xml:lang="en_GB">RAML document</comment>
- <comment xml:lang="es">documento RAML</comment>
- <comment xml:lang="eu">RAML dokumentua</comment>
- <comment xml:lang="fi">RAML-asiakirja</comment>
- <comment xml:lang="fr">document RAML</comment>
- <comment xml:lang="ga">cáipéis RAML</comment>
- <comment xml:lang="he">מסמך RAML</comment>
- <comment xml:lang="hr">RAML dokument</comment>
- <comment xml:lang="hu">RAML dokumentum</comment>
- <comment xml:lang="id">dokumen RAML</comment>
- <comment xml:lang="it">Documento RAML</comment>
- <comment xml:lang="kk">RAML құжаты</comment>
- <comment xml:lang="ko">RAML 문서</comment>
- <comment xml:lang="oc">Document RAML</comment>
- <comment xml:lang="pl">Dokument RAML</comment>
- <comment xml:lang="pt_BR">Documento RAML</comment>
- <comment xml:lang="ru">Документ RAML</comment>
- <comment xml:lang="sk">Dokument RAML</comment>
- <comment xml:lang="sr">РАМЛ документ</comment>
- <comment xml:lang="sv">RAML-dokument</comment>
- <comment xml:lang="tr">RAML belgesi</comment>
- <comment xml:lang="uk">документ RAML</comment>
- <comment xml:lang="zh_CN">RAML 文档</comment>
<comment xml:lang="zh_TW">RAML 文件</comment>
+ <comment xml:lang="zh_CN">RAML 文档</comment>
+ <comment xml:lang="uk">документ RAML</comment>
+ <comment xml:lang="tr">RAML belgesi</comment>
+ <comment xml:lang="sv">RAML-dokument</comment>
+ <comment xml:lang="sr">РАМЛ документ</comment>
+ <comment xml:lang="sq">dokument RAML</comment>
+ <comment xml:lang="sl">Dokument RAML</comment>
+ <comment xml:lang="si">RAML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RAML</comment>
+ <comment xml:lang="ru">Документ RAML</comment>
+ <comment xml:lang="pt_BR">Documento RAML</comment>
+ <comment xml:lang="pt">documento RAML</comment>
+ <comment xml:lang="pl">Dokument RAML</comment>
+ <comment xml:lang="oc">Document RAML</comment>
+ <comment xml:lang="nl">RAML-document</comment>
+ <comment xml:lang="lt">RAML dokumentas</comment>
+ <comment xml:lang="ko">RAML 문서</comment>
+ <comment xml:lang="kk">RAML құжаты</comment>
+ <comment xml:lang="ka">RAML-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">RAML ドキュメント</comment>
+ <comment xml:lang="it">Documento RAML</comment>
+ <comment xml:lang="is">RAML skjal</comment>
+ <comment xml:lang="id">Dokumen RAML</comment>
+ <comment xml:lang="hu">RAML dokumentum</comment>
+ <comment xml:lang="hr">RAML dokument</comment>
+ <comment xml:lang="he">מסמך RAML</comment>
+ <comment xml:lang="gl">Documento RAML</comment>
+ <comment xml:lang="ga">cáipéis RAML</comment>
+ <comment xml:lang="fur">document RAML</comment>
+ <comment xml:lang="fr">document RAML</comment>
+ <comment xml:lang="fi">RAML-asiakirja</comment>
+ <comment xml:lang="eu">RAML dokumentua</comment>
+ <comment xml:lang="es">documento RAML</comment>
+ <comment xml:lang="en_GB">RAML document</comment>
+ <comment xml:lang="de">RAML-Dokument</comment>
+ <comment xml:lang="da">RAML-dokument</comment>
+ <comment xml:lang="cs">dokument RAML</comment>
+ <comment xml:lang="ca">document RAML</comment>
+ <comment xml:lang="bg">Документ — RAML</comment>
+ <comment xml:lang="be">дакумент RAML</comment>
+ <comment xml:lang="ast">Documentu RAML</comment>
+ <comment xml:lang="ar">مستند RAML</comment>
+ <comment xml:lang="af">RAML-dokument</comment>
<acronym>RAML</acronym>
<expanded-acronym>RESTful API Modeling Language</expanded-acronym>
- <sub-class-of type="application/x-yaml"/>
+ <sub-class-of type="application/yaml"/>
<magic>
- <match value="#%RAML " type="string" offset="0"/>
+ <match type="string" value="#%RAML " offset="0"/>
</magic>
<glob pattern="*.raml"/>
</mime-type>
<mime-type type="application/relax-ng-compact-syntax">
<comment>RELAX NG XML schema</comment>
- <comment xml:lang="ar">مخطط RELAX NG XML</comment>
- <comment xml:lang="bg">Схема за XML — RELAX NG</comment>
- <comment xml:lang="ca">esquema XML en RELAX NG</comment>
- <comment xml:lang="cs">schéma RELAX NG XML</comment>
- <comment xml:lang="da">RELAX NG XML-skema</comment>
- <comment xml:lang="de">RELAX NG XML-Schema</comment>
- <comment xml:lang="el">Σχήμα RELAX NG XML</comment>
- <comment xml:lang="en_GB">RELAX NG XML schema</comment>
- <comment xml:lang="es">esquema XML RELAX NG</comment>
- <comment xml:lang="eu">RELAX NG XML eskema</comment>
- <comment xml:lang="fi">RELAX NG XML-skeema</comment>
- <comment xml:lang="fr">schéma XML RELAX NG</comment>
- <comment xml:lang="ga">scéimre XML RELAX NG</comment>
- <comment xml:lang="gl">Esquema XML RELAX NG</comment>
- <comment xml:lang="he">סכנת RELAX NG XML</comment>
- <comment xml:lang="hr">RELAX NG XML shema</comment>
- <comment xml:lang="hu">RELAX NG XML-séma</comment>
- <comment xml:lang="ia">Schema XML RELAX NG</comment>
- <comment xml:lang="id">Skema XML RELAX NG</comment>
- <comment xml:lang="it">Schema XML RELAX NG</comment>
- <comment xml:lang="ja">RELAX NG XML スキーマ</comment>
- <comment xml:lang="kk">RELAX NG XML сұлбасы</comment>
- <comment xml:lang="ko">RELAX NG XML 스키마</comment>
- <comment xml:lang="lt">RELAX NG XML schema</comment>
- <comment xml:lang="lv">RELAX NG XML shēma</comment>
- <comment xml:lang="nl">RELAX NG XML schema</comment>
- <comment xml:lang="oc">esquèma XML RELAX NG</comment>
- <comment xml:lang="pl">Schemat XML RELAX NG</comment>
- <comment xml:lang="pt">Esquema RELAX NG XML</comment>
- <comment xml:lang="pt_BR">Esquema XML de RELAX NG</comment>
- <comment xml:lang="ro">Schemă RELAX NG XML</comment>
- <comment xml:lang="ru">XML-схема RELAX NG</comment>
- <comment xml:lang="sk">XML schéma RELAX NG</comment>
- <comment xml:lang="sl">Datoteka shema RELAX NG XML</comment>
- <comment xml:lang="sr">РЕЛАКС НГ ИксМЛ шема</comment>
- <comment xml:lang="sv">RELAX NG XML-schema</comment>
- <comment xml:lang="tr">RELAX NG XML şeması</comment>
- <comment xml:lang="uk">XML-схема RELAX NG</comment>
+ <comment xml:lang="zh_TW">RELAX NG XML 綱要</comment>
<comment xml:lang="zh_CN">RELAX NG XML 模式</comment>
- <comment xml:lang="zh_TW">RELAX NG XML schema</comment>
+ <comment xml:lang="uk">XML-схема RELAX NG</comment>
+ <comment xml:lang="tr">RELAX NG XML şeması</comment>
+ <comment xml:lang="sv">RELAX NG XML-schema</comment>
+ <comment xml:lang="sr">РЕЛАКС НГ ИксМЛ шема</comment>
+ <comment xml:lang="sl">Datoteka shema RELAX NG XML</comment>
+ <comment xml:lang="si">RELAX NG XML ක්‍රමය</comment>
+ <comment xml:lang="sk">XML schéma RELAX NG</comment>
+ <comment xml:lang="ru">XML-схема RELAX NG</comment>
+ <comment xml:lang="ro">Schemă RELAX NG XML</comment>
+ <comment xml:lang="pt_BR">Esquema XML de RELAX NG</comment>
+ <comment xml:lang="pt">Esquema RELAX NG XML</comment>
+ <comment xml:lang="pl">Schemat XML RELAX NG</comment>
+ <comment xml:lang="oc">esquèma XML RELAX NG</comment>
+ <comment xml:lang="nl">RELAX NG XML-schema</comment>
+ <comment xml:lang="lv">RELAX NG XML shēma</comment>
+ <comment xml:lang="lt">RELAX NG XML schema</comment>
+ <comment xml:lang="ko">RELAX NG XML 스키마</comment>
+ <comment xml:lang="kk">RELAX NG XML сұлбасы</comment>
+ <comment xml:lang="ja">RELAX NG XML スキーマ</comment>
+ <comment xml:lang="it">Schema XML RELAX NG</comment>
+ <comment xml:lang="is">RELAX NG XML skema</comment>
+ <comment xml:lang="id">Skema XML RELAX NG</comment>
+ <comment xml:lang="ia">Schema XML RELAX NG</comment>
+ <comment xml:lang="hu">RELAX NG XML-séma</comment>
+ <comment xml:lang="hr">RELAX NG XML shema</comment>
+ <comment xml:lang="he">סכנת RELAX NG XML</comment>
+ <comment xml:lang="gl">Esquema XML RELAX NG</comment>
+ <comment xml:lang="ga">scéimre XML RELAX NG</comment>
+ <comment xml:lang="fur">scheme XML RELAX NG</comment>
+ <comment xml:lang="fr">schéma XML RELAX NG</comment>
+ <comment xml:lang="fi">RELAX NG XML-skeema</comment>
+ <comment xml:lang="eu">RELAX NG XML eskema</comment>
+ <comment xml:lang="es">esquema XML RELAX NG</comment>
+ <comment xml:lang="en_GB">RELAX NG XML schema</comment>
+ <comment xml:lang="el">Σχήμα RELAX NG XML</comment>
+ <comment xml:lang="de">RELAX NG XML-Schema</comment>
+ <comment xml:lang="da">RELAX NG XML-skema</comment>
+ <comment xml:lang="cs">schéma RELAX NG XML</comment>
+ <comment xml:lang="ca">esquema XML en RELAX NG</comment>
+ <comment xml:lang="bg">Схема за XML — RELAX NG</comment>
+ <comment xml:lang="be">XML-схема RELAX NG</comment>
+ <comment xml:lang="ar">مخطط RELAX NG XML</comment>
+ <comment xml:lang="af">RELAX NG XML-skema</comment>
<acronym>RELAX NG</acronym>
<expanded-acronym>REgular LAnguage for XML Next Generation</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -1929,165 +1963,182 @@
</mime-type>
<mime-type type="application/rtf">
<comment>RTF document</comment>
- <comment xml:lang="ar">مستند RTF</comment>
- <comment xml:lang="ast">Documentu RTF</comment>
- <comment xml:lang="be@latin">Dakument RTF</comment>
- <comment xml:lang="bg">Документ — RTF</comment>
- <comment xml:lang="ca">document RTF</comment>
- <comment xml:lang="cs">dokument RTF</comment>
- <comment xml:lang="da">RTF-dokument</comment>
- <comment xml:lang="de">RTF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο RTF</comment>
- <comment xml:lang="en_GB">RTF document</comment>
- <comment xml:lang="eo">RTF-dokumento</comment>
- <comment xml:lang="es">documento RTF</comment>
- <comment xml:lang="eu">RTF dokumentua</comment>
- <comment xml:lang="fi">RTF-asiakirja</comment>
- <comment xml:lang="fo">RTF skjal</comment>
- <comment xml:lang="fr">document RTF</comment>
- <comment xml:lang="ga">cáipéis RTF</comment>
- <comment xml:lang="gl">documento RTF</comment>
- <comment xml:lang="he">מסמך RTF</comment>
- <comment xml:lang="hr">RTF dokument</comment>
- <comment xml:lang="hu">RTF dokumentum</comment>
- <comment xml:lang="ia">Documento RTF</comment>
- <comment xml:lang="id">Dokumen RTF</comment>
- <comment xml:lang="it">Documento RTF</comment>
- <comment xml:lang="ja">RTF ドキュメント</comment>
- <comment xml:lang="kk">RTF құжаты</comment>
- <comment xml:lang="ko">RTF 문서</comment>
- <comment xml:lang="lt">RTF dokumentas</comment>
- <comment xml:lang="lv">RTF dokuments</comment>
- <comment xml:lang="nb">RTF-dokument</comment>
- <comment xml:lang="nl">RTF-document</comment>
- <comment xml:lang="nn">TRF-dokument</comment>
- <comment xml:lang="oc">document RTF</comment>
- <comment xml:lang="pl">Dokument RTF</comment>
- <comment xml:lang="pt">documento RTF</comment>
- <comment xml:lang="pt_BR">Documento RTF</comment>
- <comment xml:lang="ro">Document RTF</comment>
- <comment xml:lang="ru">Документ RTF</comment>
- <comment xml:lang="sk">Dokument RTF</comment>
- <comment xml:lang="sl">Dokument RTF</comment>
- <comment xml:lang="sq">Dokument RTF</comment>
- <comment xml:lang="sr">РТФ документ</comment>
- <comment xml:lang="sv">RTF-dokument</comment>
- <comment xml:lang="tr">RTF belgesi</comment>
- <comment xml:lang="uk">документ RTF</comment>
- <comment xml:lang="vi">Tài liệu RTF</comment>
- <comment xml:lang="zh_CN">RTF 文档</comment>
<comment xml:lang="zh_TW">RTF 文件</comment>
+ <comment xml:lang="zh_CN">RTF 文档</comment>
+ <comment xml:lang="vi">Tài liệu RTF</comment>
+ <comment xml:lang="uk">документ RTF</comment>
+ <comment xml:lang="tr">RTF belgesi</comment>
+ <comment xml:lang="sv">RTF-dokument</comment>
+ <comment xml:lang="sr">РТФ документ</comment>
+ <comment xml:lang="sq">dokument RTF</comment>
+ <comment xml:lang="sl">Dokument RTF</comment>
+ <comment xml:lang="si">RTF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RTF</comment>
+ <comment xml:lang="ru">Документ RTF</comment>
+ <comment xml:lang="ro">Document RTF</comment>
+ <comment xml:lang="pt_BR">Documento RTF</comment>
+ <comment xml:lang="pt">documento RTF</comment>
+ <comment xml:lang="pl">Dokument RTF</comment>
+ <comment xml:lang="oc">document RTF</comment>
+ <comment xml:lang="nn">TRF-dokument</comment>
+ <comment xml:lang="nl">RTF-document</comment>
+ <comment xml:lang="nb">RTF-dokument</comment>
+ <comment xml:lang="lv">RTF dokuments</comment>
+ <comment xml:lang="lt">RTF dokumentas</comment>
+ <comment xml:lang="ko">RTF 문서</comment>
+ <comment xml:lang="kk">RTF құжаты</comment>
+ <comment xml:lang="ka">RTF დოკუმენტი</comment>
+ <comment xml:lang="ja">RTF ドキュメント</comment>
+ <comment xml:lang="it">Documento RTF</comment>
+ <comment xml:lang="is">RTF skjal</comment>
+ <comment xml:lang="id">Dokumen RTF</comment>
+ <comment xml:lang="ia">Documento RTF</comment>
+ <comment xml:lang="hu">RTF dokumentum</comment>
+ <comment xml:lang="hr">RTF dokument</comment>
+ <comment xml:lang="he">מסמך RTF</comment>
+ <comment xml:lang="gl">documento RTF</comment>
+ <comment xml:lang="ga">cáipéis RTF</comment>
+ <comment xml:lang="fur">document RTF</comment>
+ <comment xml:lang="fr">document RTF</comment>
+ <comment xml:lang="fo">RTF skjal</comment>
+ <comment xml:lang="fi">RTF-asiakirja</comment>
+ <comment xml:lang="eu">RTF dokumentua</comment>
+ <comment xml:lang="es">documento RTF</comment>
+ <comment xml:lang="eo">RTF-dokumento</comment>
+ <comment xml:lang="en_GB">RTF document</comment>
+ <comment xml:lang="el">Έγγραφο RTF</comment>
+ <comment xml:lang="de">RTF-Dokument</comment>
+ <comment xml:lang="da">RTF-dokument</comment>
+ <comment xml:lang="cs">dokument RTF</comment>
+ <comment xml:lang="ca">document RTF</comment>
+ <comment xml:lang="bg">Документ — RTF</comment>
+ <comment xml:lang="be@latin">Dakument RTF</comment>
+ <comment xml:lang="be">дакумент RTF</comment>
+ <comment xml:lang="ast">Documentu RTF</comment>
+ <comment xml:lang="ar">مستند RTF</comment>
+ <comment xml:lang="af">RTF-dokument</comment>
<acronym>RTF</acronym>
<expanded-acronym>Rich Text Format</expanded-acronym>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="{\\rtf" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="{\\rtf" offset="0"/>
</magic>
<glob pattern="*.rtf"/>
<alias type="text/rtf"/>
</mime-type>
<mime-type type="application/sieve">
<comment>Sieve mail filter script</comment>
- <comment xml:lang="ar">سكربت مرشح بريد Sieve</comment>
- <comment xml:lang="be@latin">Skrypt filtravańnia pošty Sieve</comment>
- <comment xml:lang="bg">Скрипт-филтър за пресяване на поща</comment>
- <comment xml:lang="ca">script de filtre de correu Sieve</comment>
- <comment xml:lang="cs">skript poštovního filtru Sieve</comment>
- <comment xml:lang="da">Sieve e-post-filterprogram</comment>
- <comment xml:lang="de">Sieve-E-Mail-Filterskript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών φιλτραρίσματος αλληλογραφίας Sieve</comment>
- <comment xml:lang="en_GB">Sieve mail filter script</comment>
- <comment xml:lang="es">secuencia de órdenes de filtro en Sieve</comment>
- <comment xml:lang="eu">Sieve posta-iragazki script-a</comment>
- <comment xml:lang="fi">Sieve-postinsuodatuskomentotiedosto</comment>
- <comment xml:lang="fr">script de filtrage de courriel Sieve</comment>
- <comment xml:lang="ga">script scagaire r-phost Sieve</comment>
- <comment xml:lang="gl">Script de filtro de correo Sieve</comment>
- <comment xml:lang="he">תסריט סינון דואר של Sieve</comment>
- <comment xml:lang="hr">Sieve skripta filtriranja pošte</comment>
- <comment xml:lang="hu">Sieve levélszűrő parancsfájl</comment>
- <comment xml:lang="ia">Script de filtration de e-mail Sieve</comment>
- <comment xml:lang="id">Skrip filter surat Sieve</comment>
- <comment xml:lang="it">Script filtro posta Sieve</comment>
- <comment xml:lang="ja">Sieve メールフィルタスクリプト</comment>
- <comment xml:lang="kk">Sieve пошталық фильтр сценарийі</comment>
- <comment xml:lang="ko">Sieve 메일 필터 스크립트</comment>
- <comment xml:lang="lt">Sieve pašto filtro scenarijus</comment>
- <comment xml:lang="lv">Sieve pasta filtra skripts</comment>
- <comment xml:lang="nb">Sieve e-postfilter skript</comment>
- <comment xml:lang="nl">Sieve mailfilter-script</comment>
- <comment xml:lang="nn">Sieve e-postfilterskript</comment>
- <comment xml:lang="oc">escript de filtratge de corrièr electronic Sieve</comment>
- <comment xml:lang="pl">Skrypt filtra poczty Sieve</comment>
- <comment xml:lang="pt">Script de filtragem de correio Sieve</comment>
- <comment xml:lang="pt_BR">Script de filtro de mensagens do Sieve</comment>
- <comment xml:lang="ro">Script filtrare email Sieve</comment>
- <comment xml:lang="ru">Сценарий почтового фильтра Sieve</comment>
- <comment xml:lang="sk">Skript poštového filtra Sieve</comment>
- <comment xml:lang="sl">Skriptna datoteka Sieve poštnega filtra</comment>
- <comment xml:lang="sq">Script filtrim poste Sieve</comment>
- <comment xml:lang="sr">Сјев скрипта пропусника поште</comment>
- <comment xml:lang="sv">Sieve-epostfilterskript</comment>
- <comment xml:lang="tr">Sieve posta filtre betiği</comment>
- <comment xml:lang="uk">скрипт поштового фільтру Sieve</comment>
- <comment xml:lang="vi">Văn lệnh lọc thư Sieve</comment>
+ <comment xml:lang="zh_TW">Sieve 郵件篩選指令稿</comment>
<comment xml:lang="zh_CN">Sieve 邮件过滤脚本</comment>
- <comment xml:lang="zh_TW">Sieve 郵件過濾指令稿</comment>
- <sub-class-of type="application/xml"/>
+ <comment xml:lang="vi">Văn lệnh lọc thư Sieve</comment>
+ <comment xml:lang="uk">скрипт поштового фільтру Sieve</comment>
+ <comment xml:lang="tr">Sieve posta süzgeç betiği</comment>
+ <comment xml:lang="sv">Sieve-epostfilterskript</comment>
+ <comment xml:lang="sr">Сјев скрипта пропусника поште</comment>
+ <comment xml:lang="sq">programth filtrimi poste Sieve</comment>
+ <comment xml:lang="sl">Skriptna datoteka Sieve poštnega filtra</comment>
+ <comment xml:lang="si">තැපැල් පෙරහන් ස්ක්‍රිප්ට් පෙරා ගන්න</comment>
+ <comment xml:lang="sk">Skript poštového filtra Sieve</comment>
+ <comment xml:lang="ru">Сценарий почтового фильтра Sieve</comment>
+ <comment xml:lang="ro">Script filtrare email Sieve</comment>
+ <comment xml:lang="pt_BR">Script de filtro de mensagens do Sieve</comment>
+ <comment xml:lang="pt">Script de filtragem de correio Sieve</comment>
+ <comment xml:lang="pl">Skrypt filtra poczty Sieve</comment>
+ <comment xml:lang="oc">escript de filtratge de corrièr electronic Sieve</comment>
+ <comment xml:lang="nn">Sieve e-postfilterskript</comment>
+ <comment xml:lang="nl">Sieve mailfilter-script</comment>
+ <comment xml:lang="nb">Sieve e-postfilter skript</comment>
+ <comment xml:lang="lv">Sieve pasta filtra skripts</comment>
+ <comment xml:lang="lt">Sieve pašto filtro scenarijus</comment>
+ <comment xml:lang="ko">Sieve 메일 필터 스크립트</comment>
+ <comment xml:lang="kk">Sieve пошталық фильтр сценарийі</comment>
+ <comment xml:lang="ja">Sieve メールフィルタスクリプト</comment>
+ <comment xml:lang="it">Script filtro posta Sieve</comment>
+ <comment xml:lang="is">Sieve póstsíuskrifta</comment>
+ <comment xml:lang="id">Skrip filter surat Sieve</comment>
+ <comment xml:lang="ia">Script de filtration de e-mail Sieve</comment>
+ <comment xml:lang="hu">Sieve levélszűrő parancsfájl</comment>
+ <comment xml:lang="hr">Sieve skripta filtriranja pošte</comment>
+ <comment xml:lang="he">תסריט סינון דואר של Sieve</comment>
+ <comment xml:lang="gl">Script de filtro de correo Sieve</comment>
+ <comment xml:lang="ga">script scagaire r-phost Sieve</comment>
+ <comment xml:lang="fur">script filtri pueste Sieve</comment>
+ <comment xml:lang="fr">script de filtrage de courriel Sieve</comment>
+ <comment xml:lang="fi">Sieve-postinsuodatuskomentotiedosto</comment>
+ <comment xml:lang="eu">Sieve posta-iragazki script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes de filtro en Sieve</comment>
+ <comment xml:lang="en_GB">Sieve mail filter script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών φιλτραρίσματος αλληλογραφίας Sieve</comment>
+ <comment xml:lang="de">Sieve E-Mail-Filterskript</comment>
+ <comment xml:lang="da">Sieve e-post-filterprogram</comment>
+ <comment xml:lang="cs">skript poštovního filtru Sieve</comment>
+ <comment xml:lang="ca">script de filtre de correu Sieve</comment>
+ <comment xml:lang="bg">Скрипт-филтър за пресяване на поща</comment>
+ <comment xml:lang="be@latin">Skrypt filtravańnia pošty Sieve</comment>
+ <comment xml:lang="be">скрыпт паштовага фільтра Sieve</comment>
+ <comment xml:lang="ar">سكربت مرشح بريد Sieve</comment>
+ <comment xml:lang="af">Sieve-posfiltreerskrip</comment>
<generic-icon name="text-x-script"/>
<glob pattern="*.siv"/>
+ <glob pattern="*.sieve"/>
</mime-type>
<mime-type type="application/smil+xml">
<comment>SMIL document</comment>
- <comment xml:lang="ar">مستند SMIL</comment>
- <comment xml:lang="ast">Documentu SMIL</comment>
- <comment xml:lang="be@latin">Dakument SMIL</comment>
- <comment xml:lang="bg">Документ — SMIL</comment>
- <comment xml:lang="ca">document SMIL</comment>
- <comment xml:lang="cs">dokument SMIL</comment>
- <comment xml:lang="da">SMIL-dokument</comment>
- <comment xml:lang="de">SMIL-Dokument</comment>
- <comment xml:lang="el">Έγγραφο SMIL</comment>
- <comment xml:lang="en_GB">SMIL document</comment>
- <comment xml:lang="eo">SMIL-dokumento</comment>
- <comment xml:lang="es">documento SMIL</comment>
- <comment xml:lang="eu">SMIL dokumentua</comment>
- <comment xml:lang="fi">SMIL-asiakirja</comment>
- <comment xml:lang="fo">SMIL skjal</comment>
- <comment xml:lang="fr">document SMIL</comment>
- <comment xml:lang="ga">cáipéis SMIL</comment>
- <comment xml:lang="gl">documento SMIL</comment>
- <comment xml:lang="he">מסמך SMIL</comment>
- <comment xml:lang="hr">SMIL dokument</comment>
- <comment xml:lang="hu">SMIL dokumentum</comment>
- <comment xml:lang="ia">Documento SMIL</comment>
- <comment xml:lang="id">Dokumen SMIL</comment>
- <comment xml:lang="it">Documento SMIL</comment>
- <comment xml:lang="ja">SMIL ドキュメント</comment>
- <comment xml:lang="kk">SMIL құжаты</comment>
- <comment xml:lang="ko">SMIL 문서</comment>
- <comment xml:lang="lt">SMIL dokumentas</comment>
- <comment xml:lang="lv">SMIL dokuments</comment>
- <comment xml:lang="nb">SMIL-dokument</comment>
- <comment xml:lang="nl">SMIL-document</comment>
- <comment xml:lang="nn">SMIL-dokument</comment>
- <comment xml:lang="oc">document SMIL</comment>
- <comment xml:lang="pl">Dokument SMIL</comment>
- <comment xml:lang="pt">documento SMIL</comment>
- <comment xml:lang="pt_BR">Documento SMIL</comment>
- <comment xml:lang="ro">Document SMIL</comment>
- <comment xml:lang="ru">Документ SMIL</comment>
- <comment xml:lang="sk">Dokument SMIL</comment>
- <comment xml:lang="sl">Dokument SMIL</comment>
- <comment xml:lang="sq">Dokument SMIL</comment>
- <comment xml:lang="sr">СМИЛ документ</comment>
- <comment xml:lang="sv">SMIL-dokument</comment>
- <comment xml:lang="tr">SMIL belgesi</comment>
- <comment xml:lang="uk">документ SMIL</comment>
- <comment xml:lang="vi">Tài liệu SMIL</comment>
- <comment xml:lang="zh_CN">SMIL 文档</comment>
<comment xml:lang="zh_TW">SMIL 文件</comment>
+ <comment xml:lang="zh_CN">SMIL 文档</comment>
+ <comment xml:lang="vi">Tài liệu SMIL</comment>
+ <comment xml:lang="uk">документ SMIL</comment>
+ <comment xml:lang="tr">SMIL belgesi</comment>
+ <comment xml:lang="sv">SMIL-dokument</comment>
+ <comment xml:lang="sr">СМИЛ документ</comment>
+ <comment xml:lang="sq">dokument SMIL</comment>
+ <comment xml:lang="sl">Dokument SMIL</comment>
+ <comment xml:lang="si">SMIL ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument SMIL</comment>
+ <comment xml:lang="ru">Документ SMIL</comment>
+ <comment xml:lang="ro">Document SMIL</comment>
+ <comment xml:lang="pt_BR">Documento SMIL</comment>
+ <comment xml:lang="pt">documento SMIL</comment>
+ <comment xml:lang="pl">Dokument SMIL</comment>
+ <comment xml:lang="oc">document SMIL</comment>
+ <comment xml:lang="nn">SMIL-dokument</comment>
+ <comment xml:lang="nl">SMIL-document</comment>
+ <comment xml:lang="nb">SMIL-dokument</comment>
+ <comment xml:lang="lv">SMIL dokuments</comment>
+ <comment xml:lang="lt">SMIL dokumentas</comment>
+ <comment xml:lang="ko">SMIL 문서</comment>
+ <comment xml:lang="kk">SMIL құжаты</comment>
+ <comment xml:lang="ka">SMIL-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">SMIL ドキュメント</comment>
+ <comment xml:lang="it">Documento SMIL</comment>
+ <comment xml:lang="is">SMIL skjal</comment>
+ <comment xml:lang="id">Dokumen SMIL</comment>
+ <comment xml:lang="ia">Documento SMIL</comment>
+ <comment xml:lang="hu">SMIL dokumentum</comment>
+ <comment xml:lang="hr">SMIL dokument</comment>
+ <comment xml:lang="he">מסמך SMIL</comment>
+ <comment xml:lang="gl">documento SMIL</comment>
+ <comment xml:lang="ga">cáipéis SMIL</comment>
+ <comment xml:lang="fur">document SMIL</comment>
+ <comment xml:lang="fr">document SMIL</comment>
+ <comment xml:lang="fo">SMIL skjal</comment>
+ <comment xml:lang="fi">SMIL-asiakirja</comment>
+ <comment xml:lang="eu">SMIL dokumentua</comment>
+ <comment xml:lang="es">documento SMIL</comment>
+ <comment xml:lang="eo">SMIL-dokumento</comment>
+ <comment xml:lang="en_GB">SMIL document</comment>
+ <comment xml:lang="el">Έγγραφο SMIL</comment>
+ <comment xml:lang="de">SMIL-Dokument</comment>
+ <comment xml:lang="da">SMIL-dokument</comment>
+ <comment xml:lang="cs">dokument SMIL</comment>
+ <comment xml:lang="ca">document SMIL</comment>
+ <comment xml:lang="bg">Документ — SMIL</comment>
+ <comment xml:lang="be@latin">Dakument SMIL</comment>
+ <comment xml:lang="be">дакумент SMIL</comment>
+ <comment xml:lang="ast">Documentu SMIL</comment>
+ <comment xml:lang="ar">مستند SMIL</comment>
+ <comment xml:lang="af">SMIL-dokument</comment>
<acronym>SMIL</acronym>
<expanded-acronym>Synchronized Multimedia Integration Language</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -2098,7 +2149,7 @@
<glob pattern="*.sml"/>
<glob pattern="*.kino"/>
<magic priority="55">
- <match value="&lt;smil" type="string" offset="0:256"/>
+ <match type="string" value="&lt;smil" offset="0:256"/>
</magic>
<root-XML namespaceURI="http://www.w3.org/2001/SMIL20/Language" localName="smil"/>
<root-XML namespaceURI="http://www.w3.org/2005/SMIL21/Language" localName="smil"/>
@@ -2106,279 +2157,350 @@
</mime-type>
<mime-type type="application/vnd.ms-wpl">
<comment>WPL playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل WPL</comment>
- <comment xml:lang="bg">Списък за изпълнение — WPL</comment>
- <comment xml:lang="ca">llista de reproducció WPL</comment>
- <comment xml:lang="cs">seznam k přehrání WPL</comment>
- <comment xml:lang="da">WPL-afspilningsliste</comment>
- <comment xml:lang="de">WPL-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής WPL</comment>
- <comment xml:lang="en_GB">WPL playlist</comment>
- <comment xml:lang="eo">WPL-ludlisto</comment>
- <comment xml:lang="es">lista de reproducción WPL</comment>
- <comment xml:lang="eu">WPL erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">WPL-soittolista</comment>
- <comment xml:lang="fo">WPL avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture WPL</comment>
- <comment xml:lang="ga">seinmliosta WPL</comment>
- <comment xml:lang="gl">lista de reprodución WPL</comment>
- <comment xml:lang="he">רשימת נגינה WPL</comment>
- <comment xml:lang="hr">WPL popis izvođenja</comment>
- <comment xml:lang="hu">WPL-lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection WPL</comment>
- <comment xml:lang="id">Senarai putar WPL</comment>
- <comment xml:lang="it">Playlist WPL</comment>
- <comment xml:lang="ja">WPL 再生リスト</comment>
- <comment xml:lang="kk">WPL ойнау тізімі</comment>
- <comment xml:lang="ko">WPL 재생 목록</comment>
- <comment xml:lang="lt">WPL grojaraštis</comment>
- <comment xml:lang="lv">WPL repertuārs</comment>
- <comment xml:lang="nl">WPL-afspeellijst</comment>
- <comment xml:lang="oc">lista de lectura WPL</comment>
- <comment xml:lang="pl">Lista odtwarzania WPL</comment>
- <comment xml:lang="pt">lista de reprodução WPL</comment>
- <comment xml:lang="pt_BR">Lista de reprodução do WPL</comment>
- <comment xml:lang="ro">Listă redare WPL</comment>
- <comment xml:lang="ru">Список воспроизведения WPL</comment>
- <comment xml:lang="sk">Zoznam skladieb WPL</comment>
- <comment xml:lang="sl">Seznam predvajanja WPL</comment>
- <comment xml:lang="sr">ВПЛ списак нумера</comment>
- <comment xml:lang="sv">WPL-spellista</comment>
- <comment xml:lang="tr">WPL çalma listesi</comment>
- <comment xml:lang="uk">список відтворення WPL</comment>
- <comment xml:lang="vi">Danh mục nhạc WPL</comment>
- <comment xml:lang="zh_CN">WPL 播放列表</comment>
<comment xml:lang="zh_TW">WPL 播放清單</comment>
+ <comment xml:lang="zh_CN">WPL 播放列表</comment>
+ <comment xml:lang="vi">Danh mục nhạc WPL</comment>
+ <comment xml:lang="uk">список відтворення WPL</comment>
+ <comment xml:lang="tr">WPL çalma listesi</comment>
+ <comment xml:lang="sv">WPL-spellista</comment>
+ <comment xml:lang="sr">ВПЛ списак нумера</comment>
+ <comment xml:lang="sq">luajlistë WPL</comment>
+ <comment xml:lang="sl">Seznam predvajanja WPL</comment>
+ <comment xml:lang="si">WPL ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb WPL</comment>
+ <comment xml:lang="ru">Список воспроизведения WPL</comment>
+ <comment xml:lang="ro">Listă redare WPL</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução do WPL</comment>
+ <comment xml:lang="pt">lista de reprodução WPL</comment>
+ <comment xml:lang="pl">Lista odtwarzania WPL</comment>
+ <comment xml:lang="oc">lista de lectura WPL</comment>
+ <comment xml:lang="nl">WPL-afspeellijst</comment>
+ <comment xml:lang="lv">WPL repertuārs</comment>
+ <comment xml:lang="lt">WPL grojaraštis</comment>
+ <comment xml:lang="ko">WPL 재생 목록</comment>
+ <comment xml:lang="kk">WPL ойнау тізімі</comment>
+ <comment xml:lang="ka">WPL დასაკრავი სია</comment>
+ <comment xml:lang="ja">WPL プレイリスト</comment>
+ <comment xml:lang="it">Playlist WPL</comment>
+ <comment xml:lang="is">WPL spilunarlisti</comment>
+ <comment xml:lang="id">Senarai putar WPL</comment>
+ <comment xml:lang="ia">Lista de selection WPL</comment>
+ <comment xml:lang="hu">WPL-lejátszólista</comment>
+ <comment xml:lang="hr">WPL popis izvođenja</comment>
+ <comment xml:lang="he">רשימת נגינה WPL</comment>
+ <comment xml:lang="gl">lista de reprodución WPL</comment>
+ <comment xml:lang="ga">seinmliosta WPL</comment>
+ <comment xml:lang="fur">liste di riproduzion WPL</comment>
+ <comment xml:lang="fr">liste de lecture WPL</comment>
+ <comment xml:lang="fo">WPL avspælingarlisti</comment>
+ <comment xml:lang="fi">WPL-soittolista</comment>
+ <comment xml:lang="eu">WPL erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción WPL</comment>
+ <comment xml:lang="eo">WPL-ludlisto</comment>
+ <comment xml:lang="en_GB">WPL playlist</comment>
+ <comment xml:lang="el">Λίστα αναπαραγωγής WPL</comment>
+ <comment xml:lang="de">WPL-Wiedergabeliste</comment>
+ <comment xml:lang="da">WPL-afspilningsliste</comment>
+ <comment xml:lang="cs">seznam k přehrání WPL</comment>
+ <comment xml:lang="ca">llista de reproducció WPL</comment>
+ <comment xml:lang="bg">Списък за изпълнение — WPL</comment>
+ <comment xml:lang="be">плэй-ліст WPL</comment>
+ <comment xml:lang="ar">قائمة تشغيل WPL</comment>
+ <comment xml:lang="af">WPL-speellys</comment>
<acronym>WPL</acronym>
<expanded-acronym>Windows Media Player Playlist</expanded-acronym>
<generic-icon name="video-x-generic"/>
<glob pattern="*.wpl"/>
<magic priority="60">
- <match value="&lt;?wpl" type="string" offset="0:256"/>
+ <match type="string" value="&lt;?wpl" offset="0:256"/>
</magic>
</mime-type>
<mime-type type="application/x-sqlite2">
<comment>SQLite2 database</comment>
- <comment xml:lang="ar">قاعدة بيانات SQLite2</comment>
- <comment xml:lang="be@latin">Baza źviestak SQLite2</comment>
- <comment xml:lang="bg">База от данни — SQLite2</comment>
- <comment xml:lang="ca">base de dades SQLite2</comment>
- <comment xml:lang="cs">databáze SQLite2</comment>
- <comment xml:lang="da">SQLite2-database</comment>
- <comment xml:lang="de">SQLite2-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων SQLite2</comment>
- <comment xml:lang="en_GB">SQLite2 database</comment>
- <comment xml:lang="eo">SQLite2-datumbazo</comment>
- <comment xml:lang="es">base de datos SQLite2</comment>
- <comment xml:lang="eu">SQLite2 datu-basea</comment>
- <comment xml:lang="fi">SQLite2-tietokanta</comment>
- <comment xml:lang="fo">SQLite2 dátustovnur</comment>
- <comment xml:lang="fr">base de données SQLite2</comment>
- <comment xml:lang="ga">bunachar sonraí SQLite2</comment>
- <comment xml:lang="gl">base de datos SQLite2</comment>
- <comment xml:lang="he">מסד נתונים מסוג SQLite2</comment>
- <comment xml:lang="hr">SQLite2 baza podataka</comment>
- <comment xml:lang="hu">SQLite2 adatbázis</comment>
- <comment xml:lang="ia">Base de datos SQLite2</comment>
- <comment xml:lang="id">Basis data SQLite2</comment>
- <comment xml:lang="it">Database SQLite2</comment>
- <comment xml:lang="ja">SQLite2 データベース</comment>
- <comment xml:lang="kk">SQLite2 дерекқоры</comment>
- <comment xml:lang="ko">SQLite2 데이터베이스</comment>
- <comment xml:lang="lt">SQLite2 duomenų bazė</comment>
- <comment xml:lang="lv">SQLite2 datubāze</comment>
- <comment xml:lang="nb">SQLite2-database</comment>
- <comment xml:lang="nl">SQLite2-gegevensbank</comment>
- <comment xml:lang="nn">SQLite2-database</comment>
- <comment xml:lang="oc">banca de donadas SQLite2</comment>
- <comment xml:lang="pl">Baza danych SQLite2</comment>
- <comment xml:lang="pt">base de dados SQLite2</comment>
- <comment xml:lang="pt_BR">Banco de dados SQLite2</comment>
- <comment xml:lang="ro">Bază de date SQLite2</comment>
- <comment xml:lang="ru">База данных SQLite2</comment>
- <comment xml:lang="sk">Databáza SQLite2</comment>
- <comment xml:lang="sl">Podatkovna zbirka SQLite2</comment>
- <comment xml:lang="sq">Bazë me të dhëna SQLite2</comment>
- <comment xml:lang="sr">СКуЛајт2 база података</comment>
- <comment xml:lang="sv">SQLite2-databas</comment>
- <comment xml:lang="tr">SQLite2 veritabanı</comment>
- <comment xml:lang="uk">База даних SQLite2</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu SQLite2</comment>
- <comment xml:lang="zh_CN">SQLite2 数据库</comment>
<comment xml:lang="zh_TW">SQLite2 資料庫</comment>
+ <comment xml:lang="zh_CN">SQLite2 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu SQLite2</comment>
+ <comment xml:lang="uk">База даних SQLite2</comment>
+ <comment xml:lang="tr">SQLite2 veri tabanı</comment>
+ <comment xml:lang="sv">SQLite2-databas</comment>
+ <comment xml:lang="sr">СКуЛајт2 база података</comment>
+ <comment xml:lang="sq">bazë të dhënash SQLite2</comment>
+ <comment xml:lang="sl">Podatkovna zbirka SQLite2</comment>
+ <comment xml:lang="si">SQLite2 දත්ත සමුදාය</comment>
+ <comment xml:lang="sk">Databáza SQLite2</comment>
+ <comment xml:lang="ru">База данных SQLite2</comment>
+ <comment xml:lang="ro">Bază de date SQLite2</comment>
+ <comment xml:lang="pt_BR">Banco de dados SQLite2</comment>
+ <comment xml:lang="pt">base de dados SQLite2</comment>
+ <comment xml:lang="pl">Baza danych SQLite2</comment>
+ <comment xml:lang="oc">banca de donadas SQLite2</comment>
+ <comment xml:lang="nn">SQLite2-database</comment>
+ <comment xml:lang="nl">SQLite2-gegevensbank</comment>
+ <comment xml:lang="nb">SQLite2-database</comment>
+ <comment xml:lang="lv">SQLite2 datubāze</comment>
+ <comment xml:lang="lt">SQLite2 duomenų bazė</comment>
+ <comment xml:lang="ko">SQLite2 데이터베이스</comment>
+ <comment xml:lang="kk">SQLite2 дерекқоры</comment>
+ <comment xml:lang="ja">SQLite2 データベース</comment>
+ <comment xml:lang="it">Database SQLite2</comment>
+ <comment xml:lang="is">SQLite2 gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data SQLite2</comment>
+ <comment xml:lang="ia">Base de datos SQLite2</comment>
+ <comment xml:lang="hu">SQLite2 adatbázis</comment>
+ <comment xml:lang="hr">SQLite2 baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים מסוג SQLite2</comment>
+ <comment xml:lang="gl">base de datos SQLite2</comment>
+ <comment xml:lang="ga">bunachar sonraí SQLite2</comment>
+ <comment xml:lang="fur">base di dâts SQLite2</comment>
+ <comment xml:lang="fr">base de données SQLite2</comment>
+ <comment xml:lang="fo">SQLite2 dátustovnur</comment>
+ <comment xml:lang="fi">SQLite2-tietokanta</comment>
+ <comment xml:lang="eu">SQLite2 datu-basea</comment>
+ <comment xml:lang="es">base de datos SQLite2</comment>
+ <comment xml:lang="eo">SQLite2-datumbazo</comment>
+ <comment xml:lang="en_GB">SQLite2 database</comment>
+ <comment xml:lang="el">Βάση δεδομένων SQLite2</comment>
+ <comment xml:lang="de">SQLite2-Datenbank</comment>
+ <comment xml:lang="da">SQLite2-database</comment>
+ <comment xml:lang="cs">databáze SQLite2</comment>
+ <comment xml:lang="ca">base de dades SQLite2</comment>
+ <comment xml:lang="bg">База от данни — SQLite2</comment>
+ <comment xml:lang="be@latin">Baza źviestak SQLite2</comment>
+ <comment xml:lang="be">база даных SQLite2</comment>
+ <comment xml:lang="ar">قاعدة بيانات SQLite2</comment>
+ <comment xml:lang="af">SQLite2-databasis</comment>
<glob pattern="*.sqlite2"/>
<magic>
- <match value="** This file contains an SQLite" type="string" offset="0"/>
+ <match type="string" value="** This file contains an SQLite" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/vnd.sqlite3">
<comment>SQLite3 database</comment>
- <comment xml:lang="ar">قاعدة بيانات SQLite3</comment>
- <comment xml:lang="be@latin">Baza źviestak SQLite3</comment>
- <comment xml:lang="bg">База от данни — SQLite3</comment>
- <comment xml:lang="ca">base de dades SQLite3</comment>
- <comment xml:lang="cs">databáze SQLite3</comment>
- <comment xml:lang="da">SQLite3-database</comment>
- <comment xml:lang="de">SQLite3-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων SQLite3</comment>
- <comment xml:lang="en_GB">SQLite3 database</comment>
- <comment xml:lang="eo">SQLite3-datumbazo</comment>
- <comment xml:lang="es">base de datos SQLite3</comment>
- <comment xml:lang="eu">SQLite3 datu-basea</comment>
- <comment xml:lang="fi">SQLite3-tietokanta</comment>
- <comment xml:lang="fo">SQLite3 dátustovnur</comment>
- <comment xml:lang="fr">base de données SQLite3</comment>
- <comment xml:lang="ga">bunachar sonraí SQLite3</comment>
- <comment xml:lang="gl">base de datos SQLite3</comment>
- <comment xml:lang="he">מסד נתונים מסוג SQLite3</comment>
- <comment xml:lang="hr">SQLite3 baza podataka</comment>
- <comment xml:lang="hu">SQLite3 adatbázis</comment>
- <comment xml:lang="ia">Base de datos SQLite3</comment>
- <comment xml:lang="id">Basis data SQLite3</comment>
- <comment xml:lang="it">Database SQLite3</comment>
- <comment xml:lang="ja">SQLite3 データベース</comment>
- <comment xml:lang="kk">SQLite3 дерекқоры</comment>
- <comment xml:lang="ko">SQLite3 데이터베이스</comment>
- <comment xml:lang="lt">SQLite3 duomenų bazė</comment>
- <comment xml:lang="lv">SQLite3 datubāze</comment>
- <comment xml:lang="nb">SQLite3-database</comment>
- <comment xml:lang="nl">SQLite3-gegevensbank</comment>
- <comment xml:lang="nn">SQLite3-database</comment>
- <comment xml:lang="oc">banca de donadas SQLite3</comment>
- <comment xml:lang="pl">Baza danych SQLite3</comment>
- <comment xml:lang="pt">base de dados SQLite3</comment>
- <comment xml:lang="pt_BR">Banco de dados SQLite3</comment>
- <comment xml:lang="ro">Bază de date SQLite3</comment>
- <comment xml:lang="ru">База данных SQLite3</comment>
- <comment xml:lang="sk">Databáza SQLite3</comment>
- <comment xml:lang="sl">Podatkovna zbirka SQLite3</comment>
- <comment xml:lang="sq">Bazë me të dhëna SQLite3</comment>
- <comment xml:lang="sr">СКуЛајт3 база података</comment>
- <comment xml:lang="sv">SQLite3-databas</comment>
- <comment xml:lang="tr">SQLite3 veritabanı</comment>
- <comment xml:lang="uk">база даних SQLite3</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu SQLite3</comment>
- <comment xml:lang="zh_CN">SQLite3 数据库</comment>
<comment xml:lang="zh_TW">SQLite3 資料庫</comment>
+ <comment xml:lang="zh_CN">SQLite3 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu SQLite3</comment>
+ <comment xml:lang="uk">база даних SQLite3</comment>
+ <comment xml:lang="tr">SQLite3 veri tabanı</comment>
+ <comment xml:lang="sv">SQLite3-databas</comment>
+ <comment xml:lang="sr">СКуЛајт3 база података</comment>
+ <comment xml:lang="sq">bazë të dhënash SQLite3</comment>
+ <comment xml:lang="sl">Podatkovna zbirka SQLite3</comment>
+ <comment xml:lang="si">SQLite3 දත්ත සමුදාය</comment>
+ <comment xml:lang="sk">Databáza SQLite3</comment>
+ <comment xml:lang="ru">База данных SQLite3</comment>
+ <comment xml:lang="ro">Bază de date SQLite3</comment>
+ <comment xml:lang="pt_BR">Banco de dados SQLite3</comment>
+ <comment xml:lang="pt">base de dados SQLite3</comment>
+ <comment xml:lang="pl">Baza danych SQLite3</comment>
+ <comment xml:lang="oc">banca de donadas SQLite3</comment>
+ <comment xml:lang="nn">SQLite3-database</comment>
+ <comment xml:lang="nl">SQLite3-gegevensbank</comment>
+ <comment xml:lang="nb">SQLite3-database</comment>
+ <comment xml:lang="lv">SQLite3 datubāze</comment>
+ <comment xml:lang="lt">SQLite3 duomenų bazė</comment>
+ <comment xml:lang="ko">SQLite3 데이터베이스</comment>
+ <comment xml:lang="kk">SQLite3 дерекқоры</comment>
+ <comment xml:lang="ja">SQLite3 データベース</comment>
+ <comment xml:lang="it">Database SQLite3</comment>
+ <comment xml:lang="is">SQLite3 gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data SQLite3</comment>
+ <comment xml:lang="ia">Base de datos SQLite3</comment>
+ <comment xml:lang="hu">SQLite3 adatbázis</comment>
+ <comment xml:lang="hr">SQLite3 baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים מסוג SQLite3</comment>
+ <comment xml:lang="gl">base de datos SQLite3</comment>
+ <comment xml:lang="ga">bunachar sonraí SQLite3</comment>
+ <comment xml:lang="fur">base di dâts SQLite3</comment>
+ <comment xml:lang="fr">base de données SQLite3</comment>
+ <comment xml:lang="fo">SQLite3 dátustovnur</comment>
+ <comment xml:lang="fi">SQLite3-tietokanta</comment>
+ <comment xml:lang="eu">SQLite3 datu-basea</comment>
+ <comment xml:lang="es">base de datos SQLite3</comment>
+ <comment xml:lang="eo">SQLite3-datumbazo</comment>
+ <comment xml:lang="en_GB">SQLite3 database</comment>
+ <comment xml:lang="el">Βάση δεδομένων SQLite3</comment>
+ <comment xml:lang="de">SQLite3-Datenbank</comment>
+ <comment xml:lang="da">SQLite3-database</comment>
+ <comment xml:lang="cs">databáze SQLite3</comment>
+ <comment xml:lang="ca">base de dades SQLite3</comment>
+ <comment xml:lang="bg">База от данни — SQLite3</comment>
+ <comment xml:lang="be@latin">Baza źviestak SQLite3</comment>
+ <comment xml:lang="be">база даных SQLite3</comment>
+ <comment xml:lang="ar">قاعدة بيانات SQLite3</comment>
+ <comment xml:lang="af">SQLite3-databasis</comment>
<glob pattern="*.sqlite3"/>
<magic>
- <match value="SQLite format 3" type="string" offset="0"/>
+ <match type="string" value="SQLite format 3" offset="0"/>
</magic>
<alias type="application/x-sqlite3"/>
</mime-type>
- <mime-type type="application/x-gedcom">
+ <mime-type type="application/x-apple-systemprofiler+xml">
+ <comment>Apple System Profiler</comment>
+ <comment xml:lang="zh_CN">Apple 系统概述</comment>
+ <comment xml:lang="uk">засіб профілювання системи Apple</comment>
+ <comment xml:lang="tr">Apple Sistem Profilcisi</comment>
+ <comment xml:lang="sv">Apple Systeminformation</comment>
+ <comment xml:lang="sq">Apple System Profiler</comment>
+ <comment xml:lang="si">ඇපල් පද්ධති පැතිකඩ</comment>
+ <comment xml:lang="ru">Apple System Profiler</comment>
+ <comment xml:lang="pt_BR">Apple System Profiler</comment>
+ <comment xml:lang="pt">Perfilador do sistema Apple</comment>
+ <comment xml:lang="pl">Profiler komputera Apple</comment>
+ <comment xml:lang="nl">Apple System Profiler</comment>
+ <comment xml:lang="ko">Apple 시스템 프로파일러</comment>
+ <comment xml:lang="kk">Apple жүйелік профильдеуші</comment>
+ <comment xml:lang="ja">Apple システムプロファイラー</comment>
+ <comment xml:lang="it">Profiler di sistema Apple</comment>
+ <comment xml:lang="is">Apple System Profiler</comment>
+ <comment xml:lang="id">Profiler Sistem Apple</comment>
+ <comment xml:lang="hu">Apple rendszerprofilozó</comment>
+ <comment xml:lang="hr">Apple profiler sustava</comment>
+ <comment xml:lang="he">מאפיין מערכת של Apple</comment>
+ <comment xml:lang="gl">Perfilador de sistema de Appl</comment>
+ <comment xml:lang="fr">Profileur système Apple</comment>
+ <comment xml:lang="fi">Applen järjestelmän profiloija</comment>
+ <comment xml:lang="eu">Apple sistemaren profilatzailea</comment>
+ <comment xml:lang="es">perfil del sistema de Apple</comment>
+ <comment xml:lang="en_GB">Apple System Profiler</comment>
+ <comment xml:lang="de">Apple-Systeminformationen</comment>
+ <comment xml:lang="da">Apple System Profiler</comment>
+ <comment xml:lang="ca">System Profiler d'Apple</comment>
+ <comment xml:lang="be">Apple System Profiler</comment>
+ <comment xml:lang="ar">محلل نظام أبل</comment>
+ <sub-class-of type="application/xml"/>
+ <magic>
+ <match type="string" value="&lt;plist version=&quot;1.0&quot;" offset="0:256">
+ <match type="string" value="&lt;key&gt;_SPCommandLineArguments&lt;/key&gt;" offset="34:384"/>
+ </match>
+ </magic>
+ <glob pattern="*.spx" weight="40"/>
+ <root-XML namespaceURI="http://www.apple.com/DTDs/PropertyList-1.0.dtd" localName="plist"/>
+ </mime-type>
+ <mime-type type="text/vnd.familysearch.gedcom">
<comment>GEDCOM family history</comment>
- <comment xml:lang="ar">تاريخ عائلة GEDCOM</comment>
- <comment xml:lang="be@latin">Siamiejnaja historyja GEDCOM</comment>
- <comment xml:lang="bg">Родословно дърво — GEDCOM</comment>
- <comment xml:lang="ca">antecedents familiars GEDCOM</comment>
- <comment xml:lang="cs">rodokmen GEDCOM</comment>
- <comment xml:lang="da">GEDCOM-familiehistorie</comment>
- <comment xml:lang="de">GEDCOM-Stammbaum</comment>
- <comment xml:lang="el">Οικογενειακό ιστορικό GEDCOM</comment>
- <comment xml:lang="en_GB">GEDCOM family history</comment>
- <comment xml:lang="es">historial familiar de GEDCOM</comment>
- <comment xml:lang="eu">GEDCOM famili historia</comment>
- <comment xml:lang="fi">GEDCOM-sukuhistoria</comment>
- <comment xml:lang="fo">GEDCOM familjusøga</comment>
- <comment xml:lang="fr">généalogie GEDCOM</comment>
- <comment xml:lang="ga">stair theaghlach GEDCOM</comment>
- <comment xml:lang="gl">historial de familia GEDCOM</comment>
- <comment xml:lang="he">היסטוריה משפחתית של GEDCOM</comment>
- <comment xml:lang="hr">GEDCOM obiteljska povijest</comment>
- <comment xml:lang="hu">GEDCOM családtörténet</comment>
- <comment xml:lang="ia">Genealogia GEDCOM</comment>
- <comment xml:lang="id">Sejarah keluarga GEDCOM</comment>
- <comment xml:lang="it">Cronologia famiglia GEDCOM</comment>
- <comment xml:lang="ja">GEDCOM 家系図データ</comment>
- <comment xml:lang="ka">GEDCOM ოჯახის ისტორია</comment>
- <comment xml:lang="kk">GEDCOM отбасы тарихы</comment>
- <comment xml:lang="ko">GEDCOM 패밀리 기록</comment>
- <comment xml:lang="lt">GEDCOM šeimos istorija</comment>
- <comment xml:lang="lv">GEDCOM ģimenes vēsture</comment>
- <comment xml:lang="nb">GEDCOM-familiehistorikk</comment>
- <comment xml:lang="nl">GEDCOM-stamboom</comment>
- <comment xml:lang="nn">GEDCOM-familehistorie</comment>
- <comment xml:lang="oc">genealogia GEDCOM</comment>
- <comment xml:lang="pl">Plik historii rodziny GEDCOM</comment>
- <comment xml:lang="pt">história familiar GEDCOM</comment>
- <comment xml:lang="pt_BR">Histórico familiar do GEDCOM</comment>
- <comment xml:lang="ro">Tablou genealogic GEDCOM</comment>
- <comment xml:lang="ru">История семьи GEDCOM</comment>
- <comment xml:lang="sk">Rodokmeň GEDCOM</comment>
- <comment xml:lang="sl">Datoteka družinske zgodovine GEDCOM</comment>
- <comment xml:lang="sq">Kronollogji familje GEDCOM</comment>
- <comment xml:lang="sr">ГЕДКОМ историјат породице</comment>
- <comment xml:lang="sv">GEDCOM-släktträd</comment>
- <comment xml:lang="tr">GEDCOM aile geçmişi</comment>
- <comment xml:lang="uk">історія родини GEDCOM</comment>
- <comment xml:lang="vi">Lịch sử gia đình GEDCOM</comment>
+ <comment xml:lang="zh_TW">GEDCOM 族譜</comment>
<comment xml:lang="zh_CN">GEDCOM 家谱</comment>
- <comment xml:lang="zh_TW">GEDCOM 家族史</comment>
+ <comment xml:lang="vi">Lịch sử gia đình GEDCOM</comment>
+ <comment xml:lang="uk">історія родини GEDCOM</comment>
+ <comment xml:lang="tr">GEDCOM aile geçmişi</comment>
+ <comment xml:lang="sv">GEDCOM-släktträd</comment>
+ <comment xml:lang="sr">ГЕДКОМ историјат породице</comment>
+ <comment xml:lang="sq">historik familjeje GEDCOM</comment>
+ <comment xml:lang="sl">Datoteka družinske zgodovine GEDCOM</comment>
+ <comment xml:lang="si">GEDCOM පවුලේ ඉතිහාසය</comment>
+ <comment xml:lang="sk">Rodokmeň GEDCOM</comment>
+ <comment xml:lang="ru">История семьи GEDCOM</comment>
+ <comment xml:lang="ro">Tablou genealogic GEDCOM</comment>
+ <comment xml:lang="pt_BR">Histórico familiar do GEDCOM</comment>
+ <comment xml:lang="pt">história familiar GEDCOM</comment>
+ <comment xml:lang="pl">Plik historii rodziny GEDCOM</comment>
+ <comment xml:lang="oc">genealogia GEDCOM</comment>
+ <comment xml:lang="nn">GEDCOM-familehistorie</comment>
+ <comment xml:lang="nl">GEDCOM-stamboom</comment>
+ <comment xml:lang="nb">GEDCOM-familiehistorikk</comment>
+ <comment xml:lang="lv">GEDCOM ģimenes vēsture</comment>
+ <comment xml:lang="lt">GEDCOM šeimos istorija</comment>
+ <comment xml:lang="ko">GEDCOM 가족 내력</comment>
+ <comment xml:lang="kk">GEDCOM отбасы тарихы</comment>
+ <comment xml:lang="ka">GEDCOM ოჯახის ისტორია</comment>
+ <comment xml:lang="ja">GEDCOM 家系図データ</comment>
+ <comment xml:lang="it">Cronologia famiglia GEDCOM</comment>
+ <comment xml:lang="is">GEDCOM ættartré</comment>
+ <comment xml:lang="id">Sejarah keluarga GEDCOM</comment>
+ <comment xml:lang="ia">Genealogia GEDCOM</comment>
+ <comment xml:lang="hu">GEDCOM családtörténet</comment>
+ <comment xml:lang="hr">GEDCOM obiteljska povijest</comment>
+ <comment xml:lang="he">היסטוריה משפחתית של GEDCOM</comment>
+ <comment xml:lang="gl">historial de familia GEDCOM</comment>
+ <comment xml:lang="ga">stair theaghlach GEDCOM</comment>
+ <comment xml:lang="fur">gjenealogjie GEDCOM</comment>
+ <comment xml:lang="fr">généalogie GEDCOM</comment>
+ <comment xml:lang="fo">GEDCOM familjusøga</comment>
+ <comment xml:lang="fi">GEDCOM-sukuhistoria</comment>
+ <comment xml:lang="eu">GEDCOM famili historia</comment>
+ <comment xml:lang="es">historial familiar de GEDCOM</comment>
+ <comment xml:lang="en_GB">GEDCOM family history</comment>
+ <comment xml:lang="el">Οικογενειακό ιστορικό GEDCOM</comment>
+ <comment xml:lang="de">GEDCOM-Stammbaum</comment>
+ <comment xml:lang="da">GEDCOM-familiehistorie</comment>
+ <comment xml:lang="cs">rodokmen GEDCOM</comment>
+ <comment xml:lang="ca">antecedents familiars GEDCOM</comment>
+ <comment xml:lang="bg">Родословно дърво — GEDCOM</comment>
+ <comment xml:lang="be@latin">Siamiejnaja historyja GEDCOM</comment>
+ <comment xml:lang="be">гісторыя сям'і GEDCOM</comment>
+ <comment xml:lang="ar">تاريخ عائلة GEDCOM</comment>
+ <comment xml:lang="af">GEDCOM-familiegeskiedenis</comment>
<acronym>GEDCOM</acronym>
<expanded-acronym>GEnealogical Data COMmunication</expanded-acronym>
+ <sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="0 HEAD" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="0 HEAD" offset="0"/>
</magic>
<glob pattern="*.ged"/>
<glob pattern="*.gedcom"/>
+ <alias type="application/x-gedcom"/>
<alias type="text/gedcom"/>
</mime-type>
<mime-type type="video/x-flv">
<comment>Flash video</comment>
- <comment xml:lang="ar">Flash مرئي</comment>
- <comment xml:lang="ast">Videu en Flash</comment>
- <comment xml:lang="be@latin">Videa Flash</comment>
- <comment xml:lang="bg">Видео — Flash</comment>
- <comment xml:lang="ca">vídeo de Flash</comment>
- <comment xml:lang="cs">video Flash</comment>
- <comment xml:lang="da">Flashvideo</comment>
- <comment xml:lang="de">Flash-Video</comment>
- <comment xml:lang="el">Βίντεο Flash</comment>
- <comment xml:lang="en_GB">Flash video</comment>
- <comment xml:lang="eo">Flash-video</comment>
- <comment xml:lang="es">vídeo Flash</comment>
- <comment xml:lang="eu">Flash bideoa</comment>
- <comment xml:lang="fi">Flash-video</comment>
- <comment xml:lang="fo">Flash video</comment>
- <comment xml:lang="fr">vidéo Flash</comment>
- <comment xml:lang="ga">físeán Flash</comment>
- <comment xml:lang="gl">vídeo Flash</comment>
- <comment xml:lang="he">וידאו של פלאש</comment>
- <comment xml:lang="hr">Flash video snimka</comment>
- <comment xml:lang="hu">Flash videó</comment>
- <comment xml:lang="ia">Video Flash</comment>
- <comment xml:lang="id">Video Flash</comment>
- <comment xml:lang="it">Video Flash</comment>
- <comment xml:lang="ja">Flash 動画</comment>
- <comment xml:lang="ka">Flash-ის ვიდეო</comment>
- <comment xml:lang="kk">Flash видеосы</comment>
- <comment xml:lang="ko">Flash 동영상</comment>
- <comment xml:lang="lt">Flash vaizdo įrašas</comment>
- <comment xml:lang="lv">Flash video</comment>
- <comment xml:lang="nb">Flash-film</comment>
- <comment xml:lang="nl">Flash-video</comment>
- <comment xml:lang="nn">Flash-video</comment>
- <comment xml:lang="oc">vidèo Flash</comment>
- <comment xml:lang="pl">Plik wideo Flash</comment>
- <comment xml:lang="pt">vídeo Flash</comment>
- <comment xml:lang="pt_BR">Vídeo Flash</comment>
- <comment xml:lang="ro">Video Flash</comment>
- <comment xml:lang="ru">Видео Flash</comment>
- <comment xml:lang="sk">Video Flash</comment>
- <comment xml:lang="sl">Video datoteka Flash</comment>
- <comment xml:lang="sq">Video Flash</comment>
- <comment xml:lang="sr">Флеш видео</comment>
- <comment xml:lang="sv">Flash-video</comment>
- <comment xml:lang="tr">Flash video</comment>
- <comment xml:lang="uk">відеокліп Flash</comment>
- <comment xml:lang="vi">Ảnh động Flash</comment>
- <comment xml:lang="zh_CN">Flash 视频</comment>
<comment xml:lang="zh_TW">Flash 視訊</comment>
+ <comment xml:lang="zh_CN">Flash 视频</comment>
+ <comment xml:lang="vi">Ảnh động Flash</comment>
+ <comment xml:lang="uk">відеокліп Flash</comment>
+ <comment xml:lang="tr">Flash video</comment>
+ <comment xml:lang="sv">Flash-video</comment>
+ <comment xml:lang="sr">Флеш видео</comment>
+ <comment xml:lang="sq">video Flash</comment>
+ <comment xml:lang="sl">Video datoteka Flash</comment>
+ <comment xml:lang="si">ෆ්ලෑෂ් වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Flash</comment>
+ <comment xml:lang="ru">Видео Flash</comment>
+ <comment xml:lang="ro">Video Flash</comment>
+ <comment xml:lang="pt_BR">Vídeo Flash</comment>
+ <comment xml:lang="pt">vídeo Flash</comment>
+ <comment xml:lang="pl">Plik wideo Flash</comment>
+ <comment xml:lang="oc">vidèo Flash</comment>
+ <comment xml:lang="nn">Flash-video</comment>
+ <comment xml:lang="nl">Flash-video</comment>
+ <comment xml:lang="nb">Flash-film</comment>
+ <comment xml:lang="lv">Flash video</comment>
+ <comment xml:lang="lt">Flash vaizdo įrašas</comment>
+ <comment xml:lang="ko">Flash 동영상</comment>
+ <comment xml:lang="kk">Flash видеосы</comment>
+ <comment xml:lang="ka">Flash-ის ვიდეო</comment>
+ <comment xml:lang="ja">Flash 動画</comment>
+ <comment xml:lang="it">Video Flash</comment>
+ <comment xml:lang="is">Flash myndskeið</comment>
+ <comment xml:lang="id">Video Flash</comment>
+ <comment xml:lang="ia">Video Flash</comment>
+ <comment xml:lang="hu">Flash videó</comment>
+ <comment xml:lang="hr">Flash video snimka</comment>
+ <comment xml:lang="he">וידאו Flash</comment>
+ <comment xml:lang="gl">vídeo Flash</comment>
+ <comment xml:lang="ga">físeán Flash</comment>
+ <comment xml:lang="fur">video Flash</comment>
+ <comment xml:lang="fr">vidéo Flash</comment>
+ <comment xml:lang="fo">Flash video</comment>
+ <comment xml:lang="fi">Flash-video</comment>
+ <comment xml:lang="eu">Flash bideoa</comment>
+ <comment xml:lang="es">vídeo Flash</comment>
+ <comment xml:lang="eo">Flash-video</comment>
+ <comment xml:lang="en_GB">Flash video</comment>
+ <comment xml:lang="el">Βίντεο Flash</comment>
+ <comment xml:lang="de">Flash-Video</comment>
+ <comment xml:lang="da">Flashvideo</comment>
+ <comment xml:lang="cs">video Flash</comment>
+ <comment xml:lang="ca">vídeo de Flash</comment>
+ <comment xml:lang="bg">Видео — Flash</comment>
+ <comment xml:lang="be@latin">Videa Flash</comment>
+ <comment xml:lang="be">відэа Flash</comment>
+ <comment xml:lang="ast">Videu en Flash</comment>
+ <comment xml:lang="ar">فيديو فلاش</comment>
+ <comment xml:lang="af">Flash-video</comment>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
- <match value="FLV" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="FLV" offset="0"/>
</magic>
<glob pattern="*.flv"/>
<alias type="application/x-flash-video"/>
@@ -2387,162 +2509,361 @@
</mime-type>
<mime-type type="video/x-javafx">
<comment>JavaFX video</comment>
- <comment xml:lang="ast">Videu en JavaFX</comment>
- <comment xml:lang="bg">Видео — JavaFX</comment>
- <comment xml:lang="ca">vídeo de JavaFX</comment>
- <comment xml:lang="cs">video JavaFX</comment>
- <comment xml:lang="da">JavaFX-video</comment>
- <comment xml:lang="de">JavaFX-Video</comment>
- <comment xml:lang="el">Βίντεο JavaFX</comment>
- <comment xml:lang="en_GB">JavaFX video</comment>
- <comment xml:lang="eo">JavaFX-video</comment>
- <comment xml:lang="es">vídeo JavaFX</comment>
- <comment xml:lang="eu">JavaFX bideoa</comment>
- <comment xml:lang="fi">JavaFX-video</comment>
- <comment xml:lang="fo">JavaFX video</comment>
- <comment xml:lang="fr">vidéo JavaFX</comment>
- <comment xml:lang="ga">físeán JavaFX</comment>
- <comment xml:lang="gl">vídeo JavaFX</comment>
- <comment xml:lang="he">וידאו JavaFX</comment>
- <comment xml:lang="hr">JavaFX video snimka</comment>
- <comment xml:lang="hu">JavaFX videó</comment>
- <comment xml:lang="ia">Video JavaFX</comment>
- <comment xml:lang="id">Video JavaFX</comment>
- <comment xml:lang="it">Video JavaFX</comment>
- <comment xml:lang="ja">JavaFX 動画</comment>
- <comment xml:lang="kk">JavaFX аудиосы</comment>
- <comment xml:lang="ko">JavaFX 동영상</comment>
- <comment xml:lang="lv">JavaFX video</comment>
- <comment xml:lang="nl">JavaFX video</comment>
- <comment xml:lang="oc">vidèo JavaFX</comment>
- <comment xml:lang="pl">Plik wideo JavaFX</comment>
- <comment xml:lang="pt">vídeo JavaFX</comment>
- <comment xml:lang="pt_BR">Vídeo JavaFX</comment>
- <comment xml:lang="ro">Video JavaFX</comment>
- <comment xml:lang="ru">Видео JavaFX</comment>
- <comment xml:lang="sk">Video JavaFX</comment>
- <comment xml:lang="sl">Video JavaFX</comment>
- <comment xml:lang="sr">ЈаваФИкс видео</comment>
- <comment xml:lang="sv">JavaFX-video</comment>
- <comment xml:lang="tr">JavaFX video</comment>
- <comment xml:lang="uk">відеокліп JavaFX</comment>
- <comment xml:lang="zh_CN">JavaFX 视频</comment>
<comment xml:lang="zh_TW">JavaFX 視訊</comment>
+ <comment xml:lang="zh_CN">JavaFX 视频</comment>
+ <comment xml:lang="uk">відеокліп JavaFX</comment>
+ <comment xml:lang="tr">JavaFX video</comment>
+ <comment xml:lang="sv">JavaFX-video</comment>
+ <comment xml:lang="sr">ЈаваФИкс видео</comment>
+ <comment xml:lang="sq">video JavaFX</comment>
+ <comment xml:lang="sl">Video JavaFX</comment>
+ <comment xml:lang="si">JavaFX වීඩියෝව</comment>
+ <comment xml:lang="sk">Video JavaFX</comment>
+ <comment xml:lang="ru">Видео JavaFX</comment>
+ <comment xml:lang="ro">Video JavaFX</comment>
+ <comment xml:lang="pt_BR">Vídeo JavaFX</comment>
+ <comment xml:lang="pt">vídeo JavaFX</comment>
+ <comment xml:lang="pl">Plik wideo JavaFX</comment>
+ <comment xml:lang="oc">vidèo JavaFX</comment>
+ <comment xml:lang="nl">JavaFX video</comment>
+ <comment xml:lang="lv">JavaFX video</comment>
+ <comment xml:lang="lt">JavaFX vaizdo įrašas</comment>
+ <comment xml:lang="ko">JavaFX 동영상</comment>
+ <comment xml:lang="kk">JavaFX аудиосы</comment>
+ <comment xml:lang="ja">JavaFX 動画</comment>
+ <comment xml:lang="it">Video JavaFX</comment>
+ <comment xml:lang="is">JavaFX myndskeið</comment>
+ <comment xml:lang="id">Video JavaFX</comment>
+ <comment xml:lang="ia">Video JavaFX</comment>
+ <comment xml:lang="hu">JavaFX videó</comment>
+ <comment xml:lang="hr">JavaFX video snimka</comment>
+ <comment xml:lang="he">וידאו JavaFX</comment>
+ <comment xml:lang="gl">vídeo JavaFX</comment>
+ <comment xml:lang="ga">físeán JavaFX</comment>
+ <comment xml:lang="fur">video JavaFX</comment>
+ <comment xml:lang="fr">vidéo JavaFX</comment>
+ <comment xml:lang="fo">JavaFX video</comment>
+ <comment xml:lang="fi">JavaFX-video</comment>
+ <comment xml:lang="eu">JavaFX bideoa</comment>
+ <comment xml:lang="es">vídeo JavaFX</comment>
+ <comment xml:lang="eo">JavaFX-video</comment>
+ <comment xml:lang="en_GB">JavaFX video</comment>
+ <comment xml:lang="el">Βίντεο JavaFX</comment>
+ <comment xml:lang="de">JavaFX-Video</comment>
+ <comment xml:lang="da">JavaFX-video</comment>
+ <comment xml:lang="cs">video JavaFX</comment>
+ <comment xml:lang="ca">vídeo de JavaFX</comment>
+ <comment xml:lang="bg">Видео — JavaFX</comment>
+ <comment xml:lang="be">відэа JavaFX</comment>
+ <comment xml:lang="ast">Videu en JavaFX</comment>
+ <comment xml:lang="ar">فيديو JavaFX</comment>
+ <comment xml:lang="af">JavaFX-video</comment>
<generic-icon name="video-x-generic"/>
<magic priority="40">
- <match value="FLV" type="string" offset="0"/>
+ <match type="string" value="FLV" offset="0"/>
</magic>
<glob pattern="*.fxm"/>
<sub-class-of type="video/x-flv"/>
</mime-type>
<mime-type type="application/x-go-sgf">
-
+ <!-- translators: a record is in this context a description of a board game
+ that has been played, and that can be played back again:
+ http://www.red-bean.com/sgf/ -->
<comment>SGF record</comment>
- <comment xml:lang="ar">تسجيلة SGF</comment>
- <comment xml:lang="be@latin">Zapisanaja hulnia SGF</comment>
- <comment xml:lang="bg">Запис — SGF</comment>
- <comment xml:lang="ca">registre SGF</comment>
- <comment xml:lang="cs">nahrávka SGF</comment>
- <comment xml:lang="da">SGF-optagelse</comment>
- <comment xml:lang="de">SGF-Aufzeichnung</comment>
- <comment xml:lang="el">Εγγραφή SGF</comment>
- <comment xml:lang="en_GB">SGF record</comment>
- <comment xml:lang="es">grabación SGF</comment>
- <comment xml:lang="eu">SGF erregistroa</comment>
- <comment xml:lang="fi">SGF-nauhoitus</comment>
- <comment xml:lang="fo">SGF met</comment>
- <comment xml:lang="fr">partie SGF</comment>
- <comment xml:lang="ga">taifead SGF</comment>
- <comment xml:lang="gl">Grabación SGF</comment>
- <comment xml:lang="he">הקלטת SGF</comment>
- <comment xml:lang="hr">SGF zapis</comment>
- <comment xml:lang="hu">SGF pontszám</comment>
- <comment xml:lang="ia">Partita SGF</comment>
- <comment xml:lang="id">Catatan SGF</comment>
- <comment xml:lang="it">Registrazione SGF</comment>
- <comment xml:lang="ja">SGF レコード</comment>
- <comment xml:lang="kk">SGF жазбасы</comment>
- <comment xml:lang="ko">SGF 기록 파일</comment>
- <comment xml:lang="lt">SGF įrašas</comment>
- <comment xml:lang="lv">SGF ieraksts</comment>
- <comment xml:lang="nb">SGF-oppføring</comment>
- <comment xml:lang="nl">SGF-record</comment>
- <comment xml:lang="nn">SGF-logg</comment>
- <comment xml:lang="oc">partida SGF</comment>
- <comment xml:lang="pl">Zapis gry SGF</comment>
- <comment xml:lang="pt">gravação SGF</comment>
- <comment xml:lang="pt_BR">Gravação SGF</comment>
- <comment xml:lang="ro">Înregistrare SGF</comment>
- <comment xml:lang="ru">Запись SGF</comment>
- <comment xml:lang="sk">Záznam SGF</comment>
- <comment xml:lang="sl">Datoteka shranjene igre SGF</comment>
- <comment xml:lang="sq">Regjistrim SGF</comment>
- <comment xml:lang="sr">СГФ запис</comment>
- <comment xml:lang="sv">SGF-protokoll</comment>
- <comment xml:lang="tr">SGF kaydı</comment>
- <comment xml:lang="uk">запис SGF</comment>
- <comment xml:lang="vi">Mục ghi SGF</comment>
- <comment xml:lang="zh_CN">SGF 记录</comment>
<comment xml:lang="zh_TW">SGF 紀錄</comment>
+ <comment xml:lang="zh_CN">SGF 记录</comment>
+ <comment xml:lang="vi">Mục ghi SGF</comment>
+ <comment xml:lang="uk">запис SGF</comment>
+ <comment xml:lang="tr">SGF kaydı</comment>
+ <comment xml:lang="sv">SGF-protokoll</comment>
+ <comment xml:lang="sr">СГФ запис</comment>
+ <comment xml:lang="sq">regjistrim SGF</comment>
+ <comment xml:lang="sl">Datoteka shranjene igre SGF</comment>
+ <comment xml:lang="si">SGF වාර්තාව</comment>
+ <comment xml:lang="sk">Záznam SGF</comment>
+ <comment xml:lang="ru">Запись SGF</comment>
+ <comment xml:lang="ro">Înregistrare SGF</comment>
+ <comment xml:lang="pt_BR">Gravação SGF</comment>
+ <comment xml:lang="pt">gravação SGF</comment>
+ <comment xml:lang="pl">Zapis gry SGF</comment>
+ <comment xml:lang="oc">partida SGF</comment>
+ <comment xml:lang="nn">SGF-logg</comment>
+ <comment xml:lang="nl">SGF-record</comment>
+ <comment xml:lang="nb">SGF-oppføring</comment>
+ <comment xml:lang="lv">SGF ieraksts</comment>
+ <comment xml:lang="lt">SGF įrašas</comment>
+ <comment xml:lang="ko">SGF 기록 파일</comment>
+ <comment xml:lang="kk">SGF жазбасы</comment>
+ <comment xml:lang="ja">SGF レコード</comment>
+ <comment xml:lang="it">Registrazione SGF</comment>
+ <comment xml:lang="is">SGF færsla</comment>
+ <comment xml:lang="id">Catatan SGF</comment>
+ <comment xml:lang="ia">Partita SGF</comment>
+ <comment xml:lang="hu">SGF pontszám</comment>
+ <comment xml:lang="hr">SGF zapis</comment>
+ <comment xml:lang="he">הקלטת SGF</comment>
+ <comment xml:lang="gl">Grabación SGF</comment>
+ <comment xml:lang="ga">taifead SGF</comment>
+ <comment xml:lang="fur">regjistrazion SGF</comment>
+ <comment xml:lang="fr">partie SGF</comment>
+ <comment xml:lang="fo">SGF met</comment>
+ <comment xml:lang="fi">SGF-tallenne</comment>
+ <comment xml:lang="eu">SGF erregistroa</comment>
+ <comment xml:lang="es">grabación SGF</comment>
+ <comment xml:lang="en_GB">SGF record</comment>
+ <comment xml:lang="el">Εγγραφή SGF</comment>
+ <comment xml:lang="de">SGF-Aufzeichnung</comment>
+ <comment xml:lang="da">SGF-optagelse</comment>
+ <comment xml:lang="cs">nahrávka SGF</comment>
+ <comment xml:lang="ca">registre SGF</comment>
+ <comment xml:lang="bg">Запис — SGF</comment>
+ <comment xml:lang="be@latin">Zapisanaja hulnia SGF</comment>
+ <comment xml:lang="be">запіс SGF</comment>
+ <comment xml:lang="ar">تسجيلة SGF</comment>
+ <comment xml:lang="af">SGF-rekord</comment>
<acronym>SGF</acronym>
<expanded-acronym>Smart Game Format</expanded-acronym>
<generic-icon name="text-x-generic"/>
<glob pattern="*.sgf"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="(;FF[3]" type="string" offset="0"/>
- <match value="(;FF[4]" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="(;FF[3]" offset="0"/>
+ <match type="string" value="(;FF[4]" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-godot-project">
+ <comment>Godot Engine project</comment>
+ <comment xml:lang="zh_TW">Godot Engine 專案</comment>
+ <comment xml:lang="zh_CN">Godot Engine 项目</comment>
+ <comment xml:lang="uk">проєкт Godot Engine</comment>
+ <comment xml:lang="tr">Godot Engine projesi</comment>
+ <comment xml:lang="sv">Godot Engine-projekt</comment>
+ <comment xml:lang="sl">Projekt Godot Engine</comment>
+ <comment xml:lang="si">ගොඩොට් එන්ජින් ව්යාපෘතිය</comment>
+ <comment xml:lang="ru">Проект Godot Engine</comment>
+ <comment xml:lang="pt_BR">Projeto do Godot Engine</comment>
+ <comment xml:lang="pt">projeto Godot Engine</comment>
+ <comment xml:lang="pl">Projekt Godot Engine</comment>
+ <comment xml:lang="nl">Godot Engine-project</comment>
+ <comment xml:lang="ko">Godot 엔진 프로젝트</comment>
+ <comment xml:lang="kk">Godot Engine жобасы</comment>
+ <comment xml:lang="ja">Godot Engine プロジェクト</comment>
+ <comment xml:lang="it">Progetto Godot Engine</comment>
+ <comment xml:lang="hr">Godot Engine projekt</comment>
+ <comment xml:lang="he">מיזם של מנוע גודו</comment>
+ <comment xml:lang="gl">Proxecto do motor Godot</comment>
+ <comment xml:lang="fi">Godot Engine -projekti</comment>
+ <comment xml:lang="eu">Godot Engine proiektua</comment>
+ <comment xml:lang="es">proyecto de motor Godot</comment>
+ <comment xml:lang="en_GB">Godot Engine project</comment>
+ <comment xml:lang="de">Godot-Engine-Projekt</comment>
+ <comment xml:lang="be">праект Godot Engine</comment>
+ <comment xml:lang="ar">مشروع محرك جودو</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="project.godot"/>
+ </mime-type>
+ <mime-type type="application/x-godot-resource">
+ <comment>Godot Engine resource</comment>
+ <comment xml:lang="zh_CN">Godot Engine 资源</comment>
+ <comment xml:lang="uk">ресурс Godot Engine</comment>
+ <comment xml:lang="tr">Godot Engine kaynağı</comment>
+ <comment xml:lang="sv">Godot Engine-resurs</comment>
+ <comment xml:lang="sl">Vir Godot Engine</comment>
+ <comment xml:lang="si">ගොඩොට් එන්ජින් සම්පත</comment>
+ <comment xml:lang="ru">Ресурс Godot Engine</comment>
+ <comment xml:lang="pt_BR">Recurso do Godot Engine</comment>
+ <comment xml:lang="pt">recurso do Motor Godot</comment>
+ <comment xml:lang="pl">Zasób Godot Engine</comment>
+ <comment xml:lang="nl">Godot Engine-bron</comment>
+ <comment xml:lang="ko">Godot 엔진 자원</comment>
+ <comment xml:lang="kk">Godot Engine ресурсы</comment>
+ <comment xml:lang="ja">Godot Engine リソース</comment>
+ <comment xml:lang="it">Risorsa Godot Engine</comment>
+ <comment xml:lang="hr">Godot Engine resurs</comment>
+ <comment xml:lang="he">משאב של מנוע גודו</comment>
+ <comment xml:lang="gl">Recurso do motor Godot</comment>
+ <comment xml:lang="fi">Godot Engine -resurssi</comment>
+ <comment xml:lang="eu">Godot Engine baliabidea</comment>
+ <comment xml:lang="es">recurso de motor Godot</comment>
+ <comment xml:lang="en_GB">Godot Engine resource</comment>
+ <comment xml:lang="de">Godot-Engine-Ressource</comment>
+ <comment xml:lang="be">рэсурс Godot Engine</comment>
+ <comment xml:lang="ar">مورد محرك جودو</comment>
+ <glob pattern="*.res"/>
+ <glob pattern="*.tres"/>
+ <magic>
+ <match type="string" value="[gd_resource " offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-godot-scene">
+ <comment>Godot Engine scene</comment>
+ <comment xml:lang="zh_TW">Godot Engine 場景</comment>
+ <comment xml:lang="zh_CN">Godot Engine 场景</comment>
+ <comment xml:lang="uk">сцена Godot Engine</comment>
+ <comment xml:lang="tr">Godot Engine sahnesi</comment>
+ <comment xml:lang="sv">Godot Engine-scen</comment>
+ <comment xml:lang="sl">Prizor Godot Engine</comment>
+ <comment xml:lang="si">ගොඩෝ එන්ජින් දර්ශනය</comment>
+ <comment xml:lang="ru">Сцена Godot Engine</comment>
+ <comment xml:lang="pt_BR">Cena do Godot Engine</comment>
+ <comment xml:lang="pt">cena do Godot Engine</comment>
+ <comment xml:lang="pl">Scena Godot Engine</comment>
+ <comment xml:lang="nl">Godot Engine-scène</comment>
+ <comment xml:lang="ko">Godot 엔진 장면</comment>
+ <comment xml:lang="kk">Godot Engine сахнасы</comment>
+ <comment xml:lang="ja">Godot Engine シーン</comment>
+ <comment xml:lang="it">Scena Godot Engine</comment>
+ <comment xml:lang="hr">Godot Engine scena</comment>
+ <comment xml:lang="he">סצנה של מנוע גודו</comment>
+ <comment xml:lang="gl">Escena do motor Godot</comment>
+ <comment xml:lang="fi">Godot Engine -näkymä</comment>
+ <comment xml:lang="eu">Godot Engine eszena</comment>
+ <comment xml:lang="es">escena de motor Godot</comment>
+ <comment xml:lang="en_GB">Godot Engine scene</comment>
+ <comment xml:lang="de">Godot-Engine-Szene</comment>
+ <comment xml:lang="be">сцэна Godot Engine</comment>
+ <comment xml:lang="ar">مشهد محرك جودو</comment>
+ <glob pattern="*.scn"/>
+ <glob pattern="*.tscn"/>
+ <glob pattern="*.escn"/>
+ <magic>
+ <match type="string" value="[gd_scene " offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-godot-shader">
+ <comment>Godot Engine shader</comment>
+ <comment xml:lang="zh_CN">Godot Engine 着色器</comment>
+ <comment xml:lang="uk">шейдер Godot Engine</comment>
+ <comment xml:lang="tr">Godot Engine gölgelendiricisi</comment>
+ <comment xml:lang="sv">Godot Engine-shader</comment>
+ <comment xml:lang="sl">Senčilnik Godot Engine</comment>
+ <comment xml:lang="si">ගොඩොට් එන්ජින් සෙවන</comment>
+ <comment xml:lang="ru">Шейдер Godot Engine</comment>
+ <comment xml:lang="pt_BR">Sombra do Godot Engine</comment>
+ <comment xml:lang="pt">sombra do Godot Engine</comment>
+ <comment xml:lang="pl">Program cieniujący Godot Engine</comment>
+ <comment xml:lang="nl">Godot Engine-shader</comment>
+ <comment xml:lang="ko">Godot 엔진 셰이더</comment>
+ <comment xml:lang="kk">Godot Engine шейдері</comment>
+ <comment xml:lang="ja">Godot Engine シェーダー</comment>
+ <comment xml:lang="it">Shader Godot Engine</comment>
+ <comment xml:lang="hr">Godot Engine shader</comment>
+ <comment xml:lang="he">הצללה של מנוע גודו</comment>
+ <comment xml:lang="gl">Sombreador do motor Godot</comment>
+ <comment xml:lang="fi">Godot Engine -varjostin</comment>
+ <comment xml:lang="eu">Godot Engine itzalgilea</comment>
+ <comment xml:lang="es">sombreador de Godot Engine</comment>
+ <comment xml:lang="en_GB">Godot Engine shader</comment>
+ <comment xml:lang="de">Godot-Engine-Shader</comment>
+ <comment xml:lang="be">шэйдар Godot Engine</comment>
+ <comment xml:lang="ar">مظلل محرك جودو</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.gdshader"/>
+ </mime-type>
+ <mime-type type="application/x-gdscript">
+ <comment>GDScript script</comment>
+ <comment xml:lang="zh_TW">GDScript 指令稿</comment>
+ <comment xml:lang="zh_CN">GDScript 脚本</comment>
+ <comment xml:lang="uk">скрипт GDScript</comment>
+ <comment xml:lang="tr">GDScript betiği</comment>
+ <comment xml:lang="sv">GDScript-skript</comment>
+ <comment xml:lang="sl">Skript GDScript</comment>
+ <comment xml:lang="si">GDScript පිටපත</comment>
+ <comment xml:lang="ru">Сценарий GDScript</comment>
+ <comment xml:lang="pt_BR">Script GDScript</comment>
+ <comment xml:lang="pl">Skrypt GDScript</comment>
+ <comment xml:lang="nl">GDScript-script</comment>
+ <comment xml:lang="ko">GDScript 스크립트</comment>
+ <comment xml:lang="kk">GDScript скрипті</comment>
+ <comment xml:lang="ka">GDScript-ის სკრიპტი</comment>
+ <comment xml:lang="ja">GDScript スクリプト</comment>
+ <comment xml:lang="it">Script GDScript</comment>
+ <comment xml:lang="hr">GDScript skripta</comment>
+ <comment xml:lang="he">סקריפט GDScript</comment>
+ <comment xml:lang="gl">Script de GDScript</comment>
+ <comment xml:lang="fi">GDScript-skripti</comment>
+ <comment xml:lang="eu">GDScript scripta</comment>
+ <comment xml:lang="es">secuencia de órdenes en GDScript</comment>
+ <comment xml:lang="en_GB">GDScript script</comment>
+ <comment xml:lang="de">GDScript-Skript</comment>
+ <comment xml:lang="be">скрыпт GDScript</comment>
+ <comment xml:lang="ar">سكربت GDScript</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.gd"/>
+ </mime-type>
+ <mime-type type="application/its+xml">
+ <comment>ITS translation file</comment>
+ <comment xml:lang="uk">файл перекладу ITS</comment>
+ <comment xml:lang="sv">ITS-översättningsfil</comment>
+ <comment xml:lang="ru">Файл перевода ITS</comment>
+ <comment xml:lang="pl">Plik tłumaczenia ITS</comment>
+ <comment xml:lang="es">archivo de traducción ITS</comment>
+ <comment xml:lang="de">ITS-Übersetzungsdatei</comment>
+ <acronym>ITS</acronym>
+ <expanded-acronym>Internationalization Tag Set</expanded-acronym>
+ <sub-class-of type="application/xml"/>
+ <generic-icon name="text-x-generic"/>
+ <glob pattern="*.its"/>
+ <magic>
+ <match type="string" value="&lt;its" offset="0:256"/>
</magic>
+ <root-XML namespaceURI="http://www.w3.org/2005/11/its" localName="its"/>
</mime-type>
<mime-type type="application/xliff+xml">
<comment>XLIFF translation file</comment>
- <comment xml:lang="ar">ملف ترجمة XLIFF</comment>
- <comment xml:lang="ast">Ficheru de traducciones XLIFF</comment>
- <comment xml:lang="be@latin">Fajł pierakładu XLIFF</comment>
- <comment xml:lang="bg">Превод — XLIFF</comment>
- <comment xml:lang="ca">fitxer de traducció XLIFF</comment>
- <comment xml:lang="cs">soubor překladu XLIFF</comment>
- <comment xml:lang="da">XLIFF-oversættelsesfil</comment>
- <comment xml:lang="de">XLIFF-Übersetzung</comment>
- <comment xml:lang="el">Αρχείο μετάφρασης XLIFF</comment>
- <comment xml:lang="en_GB">XLIFF translation file</comment>
- <comment xml:lang="es">archivo de traducción XLIFF</comment>
- <comment xml:lang="eu">XLIFF itzulpen-fitxategia</comment>
- <comment xml:lang="fi">XLIFF-käännöstiedosto</comment>
- <comment xml:lang="fo">XLIFF týðingarfíla</comment>
- <comment xml:lang="fr">fichier de traduction XLIFF</comment>
- <comment xml:lang="ga">comhad aistriúcháin XLIFF</comment>
- <comment xml:lang="gl">ficheiro de tradución XLIFF</comment>
- <comment xml:lang="he">קובץ תרגום CLIFF</comment>
- <comment xml:lang="hr">XLIFF datoteka prijevoda</comment>
- <comment xml:lang="hu">XLIFF fordítási fájl</comment>
- <comment xml:lang="ia">File de traduction XLIFF</comment>
- <comment xml:lang="id">Berkas terjemahan XLIFF</comment>
- <comment xml:lang="it">File traduzione XLIFF</comment>
- <comment xml:lang="ja">XLIFF 翻訳ファイル</comment>
- <comment xml:lang="kk">XLIFF аударма файлы</comment>
- <comment xml:lang="ko">XLIFF 번역 파일</comment>
- <comment xml:lang="lt">XLIFF vertimo failas</comment>
- <comment xml:lang="lv">XLIFF tulkošanas datne</comment>
- <comment xml:lang="nb">XLIFF-oversettelsesfil</comment>
- <comment xml:lang="nl">XLIFF-vertalingsbestand</comment>
- <comment xml:lang="nn">XLIFF-omsetjingsfil</comment>
- <comment xml:lang="oc">fichièr de traduccion XLIFF</comment>
- <comment xml:lang="pl">Plik tłumaczenia XLIFF</comment>
- <comment xml:lang="pt">ficheiro de tradução XLIFF</comment>
- <comment xml:lang="pt_BR">Arquivo de tradução XLIFF</comment>
- <comment xml:lang="ro">Fișier de traducere XLIFF</comment>
- <comment xml:lang="ru">Файл перевода XLIFF</comment>
- <comment xml:lang="sk">Súbor prekladu XLIFF</comment>
- <comment xml:lang="sl">Datoteka prevoda XLIFF</comment>
- <comment xml:lang="sq">File përkthimesh XLIFF</comment>
- <comment xml:lang="sr">ИксЛИФФ датотека превода</comment>
- <comment xml:lang="sv">XLIFF-översättningsfil</comment>
- <comment xml:lang="tr">XLIFF çeviri dosyası</comment>
- <comment xml:lang="uk">файл перекладу XLIFF</comment>
- <comment xml:lang="vi">Tập tin dịch XLIFF</comment>
- <comment xml:lang="zh_CN">XLIFF 翻译文件</comment>
<comment xml:lang="zh_TW">XLIFF 翻譯檔</comment>
+ <comment xml:lang="zh_CN">XLIFF 翻译文件</comment>
+ <comment xml:lang="vi">Tập tin dịch XLIFF</comment>
+ <comment xml:lang="uk">файл перекладу XLIFF</comment>
+ <comment xml:lang="tr">XLIFF çeviri dosyası</comment>
+ <comment xml:lang="sv">XLIFF-översättningsfil</comment>
+ <comment xml:lang="sr">ИксЛИФФ датотека превода</comment>
+ <comment xml:lang="sq">kartelë përkthimesh XLIFF</comment>
+ <comment xml:lang="sl">Datoteka prevoda XLIFF</comment>
+ <comment xml:lang="si">XLIFF පරිවර්තන ගොනුව</comment>
+ <comment xml:lang="sk">Súbor prekladu XLIFF</comment>
+ <comment xml:lang="ru">Файл перевода XLIFF</comment>
+ <comment xml:lang="ro">Fișier de traducere XLIFF</comment>
+ <comment xml:lang="pt_BR">Arquivo de tradução XLIFF</comment>
+ <comment xml:lang="pt">ficheiro de tradução XLIFF</comment>
+ <comment xml:lang="pl">Plik tłumaczenia XLIFF</comment>
+ <comment xml:lang="oc">fichièr de traduccion XLIFF</comment>
+ <comment xml:lang="nn">XLIFF-omsetjingsfil</comment>
+ <comment xml:lang="nl">XLIFF-vertalingsbestand</comment>
+ <comment xml:lang="nb">XLIFF-oversettelsesfil</comment>
+ <comment xml:lang="lv">XLIFF tulkošanas datne</comment>
+ <comment xml:lang="lt">XLIFF vertimo failas</comment>
+ <comment xml:lang="ko">XLIFF 번역 파일</comment>
+ <comment xml:lang="kk">XLIFF аударма файлы</comment>
+ <comment xml:lang="ka">XLIFF თარგმნის ფაილი</comment>
+ <comment xml:lang="ja">XLIFF 翻訳ファイル</comment>
+ <comment xml:lang="it">File traduzione XLIFF</comment>
+ <comment xml:lang="is">XLIFF-þýðingaskrá</comment>
+ <comment xml:lang="id">Berkas terjemahan XLIFF</comment>
+ <comment xml:lang="ia">File de traduction XLIFF</comment>
+ <comment xml:lang="hu">XLIFF fordítási fájl</comment>
+ <comment xml:lang="hr">XLIFF datoteka prijevoda</comment>
+ <comment xml:lang="he">קובץ תרגום CLIFF</comment>
+ <comment xml:lang="gl">ficheiro de tradución XLIFF</comment>
+ <comment xml:lang="ga">comhad aistriúcháin XLIFF</comment>
+ <comment xml:lang="fur">file di traduzion XLIFF</comment>
+ <comment xml:lang="fr">fichier de traduction XLIFF</comment>
+ <comment xml:lang="fo">XLIFF týðingarfíla</comment>
+ <comment xml:lang="fi">XLIFF-käännöstiedosto</comment>
+ <comment xml:lang="eu">XLIFF itzulpen-fitxategia</comment>
+ <comment xml:lang="es">archivo de traducción XLIFF</comment>
+ <comment xml:lang="en_GB">XLIFF translation file</comment>
+ <comment xml:lang="el">Αρχείο μετάφρασης XLIFF</comment>
+ <comment xml:lang="de">XLIFF-Übersetzungsdatei</comment>
+ <comment xml:lang="da">XLIFF-oversættelsesfil</comment>
+ <comment xml:lang="cs">soubor překladu XLIFF</comment>
+ <comment xml:lang="ca">fitxer de traducció XLIFF</comment>
+ <comment xml:lang="bg">Превод — XLIFF</comment>
+ <comment xml:lang="be@latin">Fajł pierakładu XLIFF</comment>
+ <comment xml:lang="be">файл перакладу XLIFF</comment>
+ <comment xml:lang="ast">Ficheru de traducciones XLIFF</comment>
+ <comment xml:lang="ar">ملف ترجمة XLIFF</comment>
+ <comment xml:lang="af">XLIFF-vertaallêer</comment>
<acronym>XLIFF</acronym>
<expanded-acronym>XML Localization Interchange File Format</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -2550,125 +2871,173 @@
<glob pattern="*.xlf"/>
<glob pattern="*.xliff"/>
<magic priority="80">
- <match value="&lt;xliff" type="string" offset="0:256"/>
+ <match type="string" value="&lt;xliff" offset="0:256"/>
</magic>
- <root-XML namespaceURI='urn:oasis:names:tc:xliff:document:1.1' localName='xliff'/>
+ <root-XML namespaceURI="urn:oasis:names:tc:xliff:document:1.1" localName="xliff"/>
<alias type="application/x-xliff"/>
</mime-type>
- <mime-type type="application/x-yaml">
+ <mime-type type="application/toml">
+ <comment>TOML document</comment>
+ <comment xml:lang="zh_CN">TOML 文档</comment>
+ <comment xml:lang="uk">документ TOML</comment>
+ <comment xml:lang="tr">TOML belgesi</comment>
+ <comment xml:lang="sv">TOML-dokument</comment>
+ <comment xml:lang="sq">dokument TOML</comment>
+ <comment xml:lang="sl">Dokument TOML</comment>
+ <comment xml:lang="si">TOML ලේඛනය</comment>
+ <comment xml:lang="ru">Документ TOML</comment>
+ <comment xml:lang="pt_BR">Documento TOML</comment>
+ <comment xml:lang="pl">Dokument TOML</comment>
+ <comment xml:lang="oc">document TOML</comment>
+ <comment xml:lang="nl">TOML-document</comment>
+ <comment xml:lang="ko">TOML 문서</comment>
+ <comment xml:lang="kk">TOML құжаты</comment>
+ <comment xml:lang="ka">TOML დოკუმენტი</comment>
+ <comment xml:lang="ja">TOML ドキュメント</comment>
+ <comment xml:lang="it">Documento TOML</comment>
+ <comment xml:lang="hr">TOML dokument</comment>
+ <comment xml:lang="he">מסמך TOML</comment>
+ <comment xml:lang="gl">Documento TOML</comment>
+ <comment xml:lang="fi">TOML-asiakirja</comment>
+ <comment xml:lang="eu">TOML dokumentua</comment>
+ <comment xml:lang="es">documento TOML</comment>
+ <comment xml:lang="en_GB">TOML document</comment>
+ <comment xml:lang="de">TOML-Dokument</comment>
+ <comment xml:lang="be">дакумент TOML</comment>
+ <comment xml:lang="ar">مستند TOML</comment>
+ <acronym>TOML</acronym>
+ <expanded-acronym>Tom's Obvious Minimal Language</expanded-acronym>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-generic"/>
+ <glob pattern="*.toml"/>
+ </mime-type>
+ <mime-type type="application/yaml">
<comment>YAML document</comment>
- <comment xml:lang="ar">مستند YAML</comment>
- <comment xml:lang="ast">Documentu YAML</comment>
- <comment xml:lang="bg">Документ — YAML</comment>
- <comment xml:lang="ca">document YAML</comment>
- <comment xml:lang="cs">dokument YAML</comment>
- <comment xml:lang="da">YAML-dokument</comment>
- <comment xml:lang="de">YAML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο YAML</comment>
- <comment xml:lang="en_GB">YAML document</comment>
- <comment xml:lang="eo">YAML-dokumento</comment>
- <comment xml:lang="es">documento YAML</comment>
- <comment xml:lang="eu">YAML dokumentua</comment>
- <comment xml:lang="fi">YAML-asiakirja</comment>
- <comment xml:lang="fo">YAML skjal</comment>
- <comment xml:lang="fr">document YAML</comment>
- <comment xml:lang="ga">cáipéis YAML</comment>
- <comment xml:lang="gl">documento YAML</comment>
- <comment xml:lang="he">מסמך YAML</comment>
- <comment xml:lang="hr">YAML dokument</comment>
- <comment xml:lang="hu">YAML-dokumentum</comment>
- <comment xml:lang="ia">Documento YAML</comment>
- <comment xml:lang="id">Dokumen YAML</comment>
- <comment xml:lang="it">Documento YAML</comment>
- <comment xml:lang="ja">YAML ドキュメント</comment>
- <comment xml:lang="kk">YAML құжаты</comment>
- <comment xml:lang="ko">YAML 문서</comment>
- <comment xml:lang="lt">YAML dokumentas</comment>
- <comment xml:lang="lv">YAML dokuments</comment>
- <comment xml:lang="nl">YAML document</comment>
- <comment xml:lang="oc">document YAML</comment>
- <comment xml:lang="pl">Dokument YAML</comment>
- <comment xml:lang="pt">documento YAML</comment>
- <comment xml:lang="pt_BR">Documento YAML</comment>
- <comment xml:lang="ro">Document YAML</comment>
- <comment xml:lang="ru">Документ YAML</comment>
- <comment xml:lang="sk">Dokument YAML</comment>
- <comment xml:lang="sl">Dokument YAML</comment>
- <comment xml:lang="sr">ЈАМЛ документ</comment>
- <comment xml:lang="sv">YAML-dokument</comment>
- <comment xml:lang="tr">YAML belgesi</comment>
- <comment xml:lang="uk">документ YAML</comment>
- <comment xml:lang="zh_CN">YAML 文档</comment>
<comment xml:lang="zh_TW">YAML 文件</comment>
+ <comment xml:lang="zh_CN">YAML 文档</comment>
+ <comment xml:lang="uk">документ YAML</comment>
+ <comment xml:lang="tr">YAML belgesi</comment>
+ <comment xml:lang="sv">YAML-dokument</comment>
+ <comment xml:lang="sr">ЈАМЛ документ</comment>
+ <comment xml:lang="sq">dokument YAML</comment>
+ <comment xml:lang="sl">Dokument YAML</comment>
+ <comment xml:lang="si">YAML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument YAML</comment>
+ <comment xml:lang="ru">Документ YAML</comment>
+ <comment xml:lang="ro">Document YAML</comment>
+ <comment xml:lang="pt_BR">Documento YAML</comment>
+ <comment xml:lang="pt">documento YAML</comment>
+ <comment xml:lang="pl">Dokument YAML</comment>
+ <comment xml:lang="oc">document YAML</comment>
+ <comment xml:lang="nl">YAML-document</comment>
+ <comment xml:lang="lv">YAML dokuments</comment>
+ <comment xml:lang="lt">YAML dokumentas</comment>
+ <comment xml:lang="ko">YAML 문서</comment>
+ <comment xml:lang="kk">YAML құжаты</comment>
+ <comment xml:lang="ka">YAML დოკუმენტი</comment>
+ <comment xml:lang="ja">YAML ドキュメント</comment>
+ <comment xml:lang="it">Documento YAML</comment>
+ <comment xml:lang="is">YAML skjal</comment>
+ <comment xml:lang="id">Dokumen YAML</comment>
+ <comment xml:lang="ia">Documento YAML</comment>
+ <comment xml:lang="hu">YAML-dokumentum</comment>
+ <comment xml:lang="hr">YAML dokument</comment>
+ <comment xml:lang="he">מסמך YAML</comment>
+ <comment xml:lang="gl">documento YAML</comment>
+ <comment xml:lang="ga">cáipéis YAML</comment>
+ <comment xml:lang="fur">document YAML</comment>
+ <comment xml:lang="fr">document YAML</comment>
+ <comment xml:lang="fo">YAML skjal</comment>
+ <comment xml:lang="fi">YAML-asiakirja</comment>
+ <comment xml:lang="eu">YAML dokumentua</comment>
+ <comment xml:lang="es">documento YAML</comment>
+ <comment xml:lang="eo">YAML-dokumento</comment>
+ <comment xml:lang="en_GB">YAML document</comment>
+ <comment xml:lang="el">Έγγραφο YAML</comment>
+ <comment xml:lang="de">YAML-Dokument</comment>
+ <comment xml:lang="da">YAML-dokument</comment>
+ <comment xml:lang="cs">dokument YAML</comment>
+ <comment xml:lang="ca">document YAML</comment>
+ <comment xml:lang="bg">Документ — YAML</comment>
+ <comment xml:lang="be">дакумент YAML</comment>
+ <comment xml:lang="ast">Documentu YAML</comment>
+ <comment xml:lang="ar">مستند YAML</comment>
+ <comment xml:lang="af">YAML-dokument</comment>
<acronym>YAML</acronym>
<expanded-acronym>YAML Ain't Markup Language</expanded-acronym>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<magic>
- <match value="%YAML" type="string" offset="0"/>
+ <match type="string" value="%YAML" offset="0"/>
</magic>
<glob pattern="*.yaml"/>
<glob pattern="*.yml"/>
+ <alias type="application/x-yaml"/>
<alias type="text/yaml"/>
<alias type="text/x-yaml"/>
</mime-type>
<mime-type type="application/vnd.corel-draw">
<comment>Corel Draw drawing</comment>
- <comment xml:lang="ar">تصميم Corel Draw</comment>
- <comment xml:lang="ast">Dibuxu de Corel Draw</comment>
- <comment xml:lang="az">Corel Draw çəkimi</comment>
- <comment xml:lang="be@latin">Rysunak Corel Draw</comment>
- <comment xml:lang="bg">Чертеж — Corel Draw</comment>
- <comment xml:lang="ca">dibuix de Corel Draw</comment>
- <comment xml:lang="cs">kresba Corel Draw</comment>
- <comment xml:lang="cy">Darlun Corel Draw</comment>
- <comment xml:lang="da">Corel Draw-tegning</comment>
- <comment xml:lang="de">Corel-Draw-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Corel Draw </comment>
- <comment xml:lang="en_GB">Corel Draw drawing</comment>
- <comment xml:lang="eo">grafikaĵo de Corel Draw</comment>
- <comment xml:lang="es">dibujo de Corel Draw</comment>
- <comment xml:lang="eu">Corel Draw-eko marrazkia</comment>
- <comment xml:lang="fi">Corel Draw -piirros</comment>
- <comment xml:lang="fo">Corel Draw tekning</comment>
- <comment xml:lang="fr">dessin Corel Draw</comment>
- <comment xml:lang="ga">líníocht Corel Draw</comment>
- <comment xml:lang="gl">debuxo de Corel Draw</comment>
- <comment xml:lang="he">ציור של Corel Draw</comment>
- <comment xml:lang="hr">Corel Draw crtež</comment>
- <comment xml:lang="hu">Corel Draw-rajz</comment>
- <comment xml:lang="ia">Designo Corel Draw</comment>
- <comment xml:lang="id">Gambar Corel Draw</comment>
- <comment xml:lang="it">Disegno Corel Draw</comment>
- <comment xml:lang="ja">Corel Draw ドロー</comment>
- <comment xml:lang="ka">Corel Draw-ის ნახაზი</comment>
- <comment xml:lang="kk">Corel Draw суреті</comment>
- <comment xml:lang="ko">코렐 드로우 드로잉</comment>
- <comment xml:lang="lt">Corel Draw piešinys</comment>
- <comment xml:lang="lv">Corel Draw zīmējums</comment>
- <comment xml:lang="ms">Lukisan Corel Draw</comment>
- <comment xml:lang="nb">Corel Draw-tegning</comment>
- <comment xml:lang="nl">Corel Draw-tekening</comment>
- <comment xml:lang="nn">Corel Draw-teikning</comment>
- <comment xml:lang="oc">dessenh Corel Draw</comment>
- <comment xml:lang="pl">Rysunek Corel Draw</comment>
- <comment xml:lang="pt">desenho Corel Drawdesenho Corel Draw</comment>
- <comment xml:lang="pt_BR">Desenho do Corel Draw</comment>
- <comment xml:lang="ro">Desen Corel Draw</comment>
- <comment xml:lang="ru">Рисунок Corel Draw</comment>
- <comment xml:lang="sk">Kresba Corel Draw</comment>
- <comment xml:lang="sl">Datoteka risbe Corel Draw</comment>
- <comment xml:lang="sq">Vizatim Corel Draw</comment>
- <comment xml:lang="sr">Корелов цртеж</comment>
- <comment xml:lang="sv">Corel Draw-teckning</comment>
- <comment xml:lang="tr">Corel Draw çizimi</comment>
- <comment xml:lang="uk">малюнок Corel Draw</comment>
- <comment xml:lang="vi">Bản vẽ Corel Draw</comment>
- <comment xml:lang="zh_CN">Corel Draw 绘图</comment>
<comment xml:lang="zh_TW">Corel Draw 繪圖</comment>
+ <comment xml:lang="zh_CN">Corel Draw 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ Corel Draw</comment>
+ <comment xml:lang="uk">малюнок Corel Draw</comment>
+ <comment xml:lang="tr">Corel Draw çizimi</comment>
+ <comment xml:lang="sv">Corel Draw-teckning</comment>
+ <comment xml:lang="sr">Корелов цртеж</comment>
+ <comment xml:lang="sq">vizatim Corel Draw</comment>
+ <comment xml:lang="sl">Datoteka risbe Corel Draw</comment>
+ <comment xml:lang="si">Corel Draw ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba Corel Draw</comment>
+ <comment xml:lang="ru">Рисунок Corel Draw</comment>
+ <comment xml:lang="ro">Desen Corel Draw</comment>
+ <comment xml:lang="pt_BR">Desenho do Corel Draw</comment>
+ <comment xml:lang="pt">desenho Corel Drawdesenho Corel Draw</comment>
+ <comment xml:lang="pl">Rysunek Corel Draw</comment>
+ <comment xml:lang="oc">dessenh Corel Draw</comment>
+ <comment xml:lang="nn">Corel Draw-teikning</comment>
+ <comment xml:lang="nl">Corel Draw-tekening</comment>
+ <comment xml:lang="nb">Corel Draw-tegning</comment>
+ <comment xml:lang="ms">Lukisan Corel Draw</comment>
+ <comment xml:lang="lv">Corel Draw zīmējums</comment>
+ <comment xml:lang="lt">Corel Draw piešinys</comment>
+ <comment xml:lang="ko">Corel Draw 드로잉</comment>
+ <comment xml:lang="kk">Corel Draw суреті</comment>
+ <comment xml:lang="ka">Corel Draw-ის ნახაზი</comment>
+ <comment xml:lang="ja">Corel Draw ドロー</comment>
+ <comment xml:lang="it">Disegno Corel Draw</comment>
+ <comment xml:lang="is">Corel Draw teikning</comment>
+ <comment xml:lang="id">Gambar Corel Draw</comment>
+ <comment xml:lang="ia">Designo Corel Draw</comment>
+ <comment xml:lang="hu">Corel Draw-rajz</comment>
+ <comment xml:lang="hr">Corel Draw crtež</comment>
+ <comment xml:lang="he">ציור Corel Draw</comment>
+ <comment xml:lang="gl">debuxo de Corel Draw</comment>
+ <comment xml:lang="ga">líníocht Corel Draw</comment>
+ <comment xml:lang="fur">dissen Corel Draw</comment>
+ <comment xml:lang="fr">dessin Corel Draw</comment>
+ <comment xml:lang="fo">Corel Draw tekning</comment>
+ <comment xml:lang="fi">Corel Draw -piirros</comment>
+ <comment xml:lang="eu">Corel Draw-eko marrazkia</comment>
+ <comment xml:lang="es">dibujo de Corel Draw</comment>
+ <comment xml:lang="eo">grafikaĵo de Corel Draw</comment>
+ <comment xml:lang="en_GB">Corel Draw drawing</comment>
+ <comment xml:lang="el">Σχέδιο Corel Draw </comment>
+ <comment xml:lang="de">Corel-Draw-Zeichnung</comment>
+ <comment xml:lang="da">Corel Draw-tegning</comment>
+ <comment xml:lang="cy">Darlun Corel Draw</comment>
+ <comment xml:lang="cs">kresba Corel Draw</comment>
+ <comment xml:lang="ca">dibuix de Corel Draw</comment>
+ <comment xml:lang="bg">Чертеж — Corel Draw</comment>
+ <comment xml:lang="be@latin">Rysunak Corel Draw</comment>
+ <comment xml:lang="be">рысунак Corel Draw</comment>
+ <comment xml:lang="az">Corel Draw çəkimi</comment>
+ <comment xml:lang="ast">Dibuxu de Corel Draw</comment>
+ <comment xml:lang="ar">تصميم Corel Draw</comment>
+ <comment xml:lang="af">Corel Draw-tekening</comment>
<generic-icon name="image-x-generic"/>
<magic priority="80">
- <match value="CDRXvrsn" type="string" offset="8" mask="0xffffff00ffffffff"/>
+ <match type="string" value="CDRXvrsn" mask="0xffffff00ffffffff" offset="8"/>
</magic>
<glob pattern="*.cdr"/>
<alias type="application/cdr"/>
@@ -2681,54 +3050,60 @@
</mime-type>
<mime-type type="application/vnd.hp-hpgl">
<comment>HPGL file</comment>
- <comment xml:lang="ar">ملف HPGL</comment>
- <comment xml:lang="ast">Ficheru HPGL</comment>
- <comment xml:lang="be@latin">Fajł HPGL</comment>
- <comment xml:lang="bg">Файл — HPGL</comment>
- <comment xml:lang="ca">fitxer HPGL</comment>
- <comment xml:lang="cs">soubor HPGL</comment>
- <comment xml:lang="da">HPGL-fil</comment>
- <comment xml:lang="de">HPGL-Datei</comment>
- <comment xml:lang="el">Αρχείο HPGL</comment>
- <comment xml:lang="en_GB">HPGL file</comment>
- <comment xml:lang="eo">HPGL-dosiero</comment>
- <comment xml:lang="es">archivo HPGL</comment>
- <comment xml:lang="eu">HPGL fitxategia</comment>
- <comment xml:lang="fi">HPGL-tiedosto</comment>
- <comment xml:lang="fo">HPGL fíla</comment>
- <comment xml:lang="fr">fichier HPGL</comment>
- <comment xml:lang="ga">comhad HPGL</comment>
- <comment xml:lang="gl">ficheiro HPGL</comment>
- <comment xml:lang="he">קובץ HGPL</comment>
- <comment xml:lang="hr">HPGL datoteka</comment>
- <comment xml:lang="hu">HPGL fájl</comment>
- <comment xml:lang="ia">File HPGL</comment>
- <comment xml:lang="id">Berkas HPGL</comment>
- <comment xml:lang="it">File HPGL</comment>
- <comment xml:lang="ja">HPGL ファイル</comment>
- <comment xml:lang="kk">HPGL файлы</comment>
- <comment xml:lang="ko">HPGL 파일</comment>
- <comment xml:lang="lt">HPGL failas</comment>
- <comment xml:lang="lv">HPGL datne</comment>
- <comment xml:lang="nb">HPGL-fil</comment>
- <comment xml:lang="nl">HPGL-bestand</comment>
- <comment xml:lang="nn">HPGL-fil</comment>
- <comment xml:lang="oc">fichièr HPGL</comment>
- <comment xml:lang="pl">Plik HPGL</comment>
- <comment xml:lang="pt">ficheiro HPGL</comment>
- <comment xml:lang="pt_BR">Arquivo HPGL</comment>
- <comment xml:lang="ro">Fișier HPGL</comment>
- <comment xml:lang="ru">Файл HPGL</comment>
- <comment xml:lang="sk">Súbor HPGL</comment>
- <comment xml:lang="sl">Datoteka HPGL</comment>
- <comment xml:lang="sq">File HPGL</comment>
- <comment xml:lang="sr">ХПГЛ датотека</comment>
- <comment xml:lang="sv">HPGL-fil</comment>
- <comment xml:lang="tr">HPGL dosyası</comment>
- <comment xml:lang="uk">файл HPGL</comment>
- <comment xml:lang="vi">Tập tin HPGL</comment>
- <comment xml:lang="zh_CN">HPGL 文件</comment>
<comment xml:lang="zh_TW">HPGL 檔案</comment>
+ <comment xml:lang="zh_CN">HPGL 文件</comment>
+ <comment xml:lang="vi">Tập tin HPGL</comment>
+ <comment xml:lang="uk">файл HPGL</comment>
+ <comment xml:lang="tr">HPGL dosyası</comment>
+ <comment xml:lang="sv">HPGL-fil</comment>
+ <comment xml:lang="sr">ХПГЛ датотека</comment>
+ <comment xml:lang="sq">kartelë HPGL</comment>
+ <comment xml:lang="sl">Datoteka HPGL</comment>
+ <comment xml:lang="si">HPGL ගොනුව</comment>
+ <comment xml:lang="sk">Súbor HPGL</comment>
+ <comment xml:lang="ru">Файл HPGL</comment>
+ <comment xml:lang="ro">Fișier HPGL</comment>
+ <comment xml:lang="pt_BR">Arquivo HPGL</comment>
+ <comment xml:lang="pt">ficheiro HPGL</comment>
+ <comment xml:lang="pl">Plik HPGL</comment>
+ <comment xml:lang="oc">fichièr HPGL</comment>
+ <comment xml:lang="nn">HPGL-fil</comment>
+ <comment xml:lang="nl">HPGL-bestand</comment>
+ <comment xml:lang="nb">HPGL-fil</comment>
+ <comment xml:lang="lv">HPGL datne</comment>
+ <comment xml:lang="lt">HPGL failas</comment>
+ <comment xml:lang="ko">HPGL 파일</comment>
+ <comment xml:lang="kk">HPGL файлы</comment>
+ <comment xml:lang="ka">HPGL ფაილი</comment>
+ <comment xml:lang="ja">HPGL ファイル</comment>
+ <comment xml:lang="it">File HPGL</comment>
+ <comment xml:lang="is">HPGL skrá</comment>
+ <comment xml:lang="id">Berkas HPGL</comment>
+ <comment xml:lang="ia">File HPGL</comment>
+ <comment xml:lang="hu">HPGL fájl</comment>
+ <comment xml:lang="hr">HPGL datoteka</comment>
+ <comment xml:lang="he">קובץ HGPL</comment>
+ <comment xml:lang="gl">ficheiro HPGL</comment>
+ <comment xml:lang="ga">comhad HPGL</comment>
+ <comment xml:lang="fur">file HPGL</comment>
+ <comment xml:lang="fr">fichier HPGL</comment>
+ <comment xml:lang="fo">HPGL fíla</comment>
+ <comment xml:lang="fi">HPGL-tiedosto</comment>
+ <comment xml:lang="eu">HPGL fitxategia</comment>
+ <comment xml:lang="es">archivo HPGL</comment>
+ <comment xml:lang="eo">HPGL-dosiero</comment>
+ <comment xml:lang="en_GB">HPGL file</comment>
+ <comment xml:lang="el">Αρχείο HPGL</comment>
+ <comment xml:lang="de">HPGL-Datei</comment>
+ <comment xml:lang="da">HPGL-fil</comment>
+ <comment xml:lang="cs">soubor HPGL</comment>
+ <comment xml:lang="ca">fitxer HPGL</comment>
+ <comment xml:lang="bg">Файл — HPGL</comment>
+ <comment xml:lang="be@latin">Fajł HPGL</comment>
+ <comment xml:lang="be">файл HPGL</comment>
+ <comment xml:lang="ast">Ficheru HPGL</comment>
+ <comment xml:lang="ar">ملف HPGL</comment>
+ <comment xml:lang="af">HPGL-lêer</comment>
<acronym>HPGL</acronym>
<expanded-acronym>HP Graphics Language</expanded-acronym>
<generic-icon name="image-x-generic"/>
@@ -2736,115 +3111,141 @@
</mime-type>
<mime-type type="application/vnd.hp-pcl">
<comment>PCL file</comment>
- <comment xml:lang="ar">ملف PCL</comment>
- <comment xml:lang="ast">FIcheru PCL</comment>
- <comment xml:lang="be@latin">Fajł PCL</comment>
- <comment xml:lang="bg">Файл — PCL</comment>
- <comment xml:lang="ca">fitxer PCL</comment>
- <comment xml:lang="cs">soubor PCL</comment>
- <comment xml:lang="da">PCL-fil</comment>
- <comment xml:lang="de">PCL-Datei</comment>
- <comment xml:lang="el">Αρχείο PCL</comment>
- <comment xml:lang="en_GB">PCL file</comment>
- <comment xml:lang="eo">PCL-dosiero</comment>
- <comment xml:lang="es">archivo PCL</comment>
- <comment xml:lang="eu">PCL fitxategia</comment>
- <comment xml:lang="fi">PCL-tiedosto</comment>
- <comment xml:lang="fo">PCL fíla</comment>
- <comment xml:lang="fr">fichier PCL</comment>
- <comment xml:lang="ga">comhad PCL</comment>
- <comment xml:lang="gl">ficheiro PCL</comment>
- <comment xml:lang="he">קובץ PCL</comment>
- <comment xml:lang="hr">PCL datoteka</comment>
- <comment xml:lang="hu">PCL fájl</comment>
- <comment xml:lang="ia">File PCL</comment>
- <comment xml:lang="id">Berkas PCL</comment>
- <comment xml:lang="it">File PCL</comment>
- <comment xml:lang="ja">PCL ファイル</comment>
- <comment xml:lang="kk">PCL файлы</comment>
- <comment xml:lang="ko">PCL 파일</comment>
- <comment xml:lang="lt">PCL failas</comment>
- <comment xml:lang="lv">PCL datne</comment>
- <comment xml:lang="nb">PCL-fil</comment>
- <comment xml:lang="nl">PCL-bestand</comment>
- <comment xml:lang="nn">PCL-fil</comment>
- <comment xml:lang="oc">fichièr PCL</comment>
- <comment xml:lang="pl">Plik PCL</comment>
- <comment xml:lang="pt">ficheiro PCL</comment>
- <comment xml:lang="pt_BR">Arquivo PCL</comment>
- <comment xml:lang="ro">Fișier PCL</comment>
- <comment xml:lang="ru">Файл PCL</comment>
- <comment xml:lang="sk">Súbor PCL</comment>
- <comment xml:lang="sl">Datoteka PCL</comment>
- <comment xml:lang="sq">File PCL</comment>
- <comment xml:lang="sr">ПЦЛ датотека</comment>
- <comment xml:lang="sv">PCL-fil</comment>
- <comment xml:lang="tr">PCL dosyası</comment>
- <comment xml:lang="uk">файл PCL</comment>
- <comment xml:lang="vi">Tập tin PCL</comment>
- <comment xml:lang="zh_CN">PCL 文件</comment>
<comment xml:lang="zh_TW">PCL 檔</comment>
+ <comment xml:lang="zh_CN">PCL 文件</comment>
+ <comment xml:lang="vi">Tập tin PCL</comment>
+ <comment xml:lang="uk">файл PCL</comment>
+ <comment xml:lang="tr">PCL dosyası</comment>
+ <comment xml:lang="sv">PCL-fil</comment>
+ <comment xml:lang="sr">ПЦЛ датотека</comment>
+ <comment xml:lang="sq">kartelë PCL</comment>
+ <comment xml:lang="sl">Datoteka PCL</comment>
+ <comment xml:lang="si">PCL ගොනුව</comment>
+ <comment xml:lang="sk">Súbor PCL</comment>
+ <comment xml:lang="ru">Файл PCL</comment>
+ <comment xml:lang="ro">Fișier PCL</comment>
+ <comment xml:lang="pt_BR">Arquivo PCL</comment>
+ <comment xml:lang="pt">ficheiro PCL</comment>
+ <comment xml:lang="pl">Plik PCL</comment>
+ <comment xml:lang="oc">fichièr PCL</comment>
+ <comment xml:lang="nn">PCL-fil</comment>
+ <comment xml:lang="nl">PCL-bestand</comment>
+ <comment xml:lang="nb">PCL-fil</comment>
+ <comment xml:lang="lv">PCL datne</comment>
+ <comment xml:lang="lt">PCL failas</comment>
+ <comment xml:lang="ko">PCL 파일</comment>
+ <comment xml:lang="kk">PCL файлы</comment>
+ <comment xml:lang="ka">PCL ფაილი</comment>
+ <comment xml:lang="ja">PCL ファイル</comment>
+ <comment xml:lang="it">File PCL</comment>
+ <comment xml:lang="is">PCL skrá</comment>
+ <comment xml:lang="id">Berkas PCL</comment>
+ <comment xml:lang="ia">File PCL</comment>
+ <comment xml:lang="hu">PCL fájl</comment>
+ <comment xml:lang="hr">PCL datoteka</comment>
+ <comment xml:lang="he">קובץ PCL</comment>
+ <comment xml:lang="gl">ficheiro PCL</comment>
+ <comment xml:lang="ga">comhad PCL</comment>
+ <comment xml:lang="fur">file PCL</comment>
+ <comment xml:lang="fr">fichier PCL</comment>
+ <comment xml:lang="fo">PCL fíla</comment>
+ <comment xml:lang="fi">PCL-tiedosto</comment>
+ <comment xml:lang="eu">PCL fitxategia</comment>
+ <comment xml:lang="es">archivo PCL</comment>
+ <comment xml:lang="eo">PCL-dosiero</comment>
+ <comment xml:lang="en_GB">PCL file</comment>
+ <comment xml:lang="el">Αρχείο PCL</comment>
+ <comment xml:lang="de">PCL-Datei</comment>
+ <comment xml:lang="da">PCL-fil</comment>
+ <comment xml:lang="cs">soubor PCL</comment>
+ <comment xml:lang="ca">fitxer PCL</comment>
+ <comment xml:lang="bg">Файл — PCL</comment>
+ <comment xml:lang="be@latin">Fajł PCL</comment>
+ <comment xml:lang="be">файл PCL</comment>
+ <comment xml:lang="ast">FIcheru PCL</comment>
+ <comment xml:lang="ar">ملف PCL</comment>
+ <comment xml:lang="af">PCL-lêer</comment>
<acronym>PCL</acronym>
<expanded-acronym>HP Printer Control Language</expanded-acronym>
<generic-icon name="image-x-generic"/>
<glob pattern="*.pcl"/>
</mime-type>
+ <mime-type type="application/vnd.cups-ppd">
+ <comment>PostScript printer description</comment>
+ <comment xml:lang="uk">опис принтера PostScript</comment>
+ <comment xml:lang="sv">Postscript-skrivarbeskrivning</comment>
+ <comment xml:lang="ru">Описание принтера PostScript</comment>
+ <comment xml:lang="pt_BR">Descrição de impressora PostScript</comment>
+ <comment xml:lang="pl">Opis drukarki PostScript</comment>
+ <comment xml:lang="es">descripción de impresora PostScript</comment>
+ <comment xml:lang="de">PostScript-Druckerbeschreibung</comment>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="*PPD-Adobe:" offset="0"/>
+ </magic>
+ <glob pattern="*.ppd"/>
+ </mime-type>
<mime-type type="application/vnd.lotus-1-2-3">
<comment>Lotus 1-2-3 spreadsheet</comment>
- <comment xml:lang="ar">جدول Lotus 1-2-3</comment>
- <comment xml:lang="ast">Fueya de cálculu de Lotus 1-2-3</comment>
- <comment xml:lang="az">Lotus 1-2-3 hesab cədvəli</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš Lotus 1-2-3</comment>
- <comment xml:lang="bg">Таблица — Lotus 1-2-3</comment>
- <comment xml:lang="ca">full de càlcul de Lotus 1-2-3</comment>
- <comment xml:lang="cs">sešit Lotus 1-2-3</comment>
- <comment xml:lang="cy">Taenlen Lotus 1-2-3</comment>
- <comment xml:lang="da">Lotus 1-2-3-regneark</comment>
- <comment xml:lang="de">Lotus-1-2-3-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Lotus 1-2-3</comment>
- <comment xml:lang="en_GB">Lotus 1-2-3 spreadsheet</comment>
- <comment xml:lang="eo">Kalkultabelo de Lotus 1-2-3</comment>
- <comment xml:lang="es">hoja de cálculo de Lotus 1-2-3</comment>
- <comment xml:lang="eu">Lotus 1-2-3 kalkulu-orria</comment>
- <comment xml:lang="fi">Lotus 1-2-3 -taulukko</comment>
- <comment xml:lang="fo">Lotus 1-2-3 rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Lotus 1-2-3</comment>
- <comment xml:lang="ga">scarbhileog Lotus 1-2-3</comment>
- <comment xml:lang="gl">folla de cálculo de Lotus 1-2-3</comment>
- <comment xml:lang="he">גיליון נתונים של Lotus 1-2-3</comment>
- <comment xml:lang="hr">Lotus 1-2-3 proračunska tablica</comment>
- <comment xml:lang="hu">Lotus 1-2-3-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo Lotus 1-2-3</comment>
- <comment xml:lang="id">Lembar sebar Lotus 1-2-3</comment>
- <comment xml:lang="it">Foglio di calcolo Lotus 1-2-3</comment>
- <comment xml:lang="ja">Lotus 1-2-3 スプレッドシート</comment>
- <comment xml:lang="kk">Lotus 1-2-3 электрондық кестесі</comment>
- <comment xml:lang="ko">Lotus 1-2-3 스프레드시트</comment>
- <comment xml:lang="lt">Lotus 1-2-3 skaičialentė</comment>
- <comment xml:lang="lv">Lotus 1-2-3 izklājlapa</comment>
- <comment xml:lang="ms">Hamparan Lotus 1-2-3</comment>
- <comment xml:lang="nb">Lotus 1-2-3 regneark</comment>
- <comment xml:lang="nl">Lotus 1-2-3-rekenblad</comment>
- <comment xml:lang="nn">Lotus 1-2-3 rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul Lotus 1-2-3</comment>
- <comment xml:lang="pl">Arkusz Lotus 1-2-3</comment>
- <comment xml:lang="pt">folha de cálculo Lotus 1-2-3</comment>
- <comment xml:lang="pt_BR">Planilha do Lotus 1-2-3</comment>
- <comment xml:lang="ro">Foaie de calcul Lotus 1-2-3</comment>
- <comment xml:lang="ru">Электронная таблица Lotus 1-2-3</comment>
- <comment xml:lang="sk">Zošit Lotus 1-2-3</comment>
- <comment xml:lang="sl">Preglednica Lotus 1-2-3</comment>
- <comment xml:lang="sq">Fletë llogaritjesh Lotus 1-2-3</comment>
- <comment xml:lang="sr">Лотусова 1-2-3 табела</comment>
- <comment xml:lang="sv">Lotus 1-2-3-kalkylblad</comment>
- <comment xml:lang="tr">Lotus 1-2-3 hesap tablosu</comment>
- <comment xml:lang="uk">ел. таблиця Lotus 1-2-3</comment>
- <comment xml:lang="vi">Bảng tính Lotus 1-2-3</comment>
- <comment xml:lang="zh_CN">Lotus 1-2-3 电子表格</comment>
<comment xml:lang="zh_TW">Lotus 1-2-3 試算表</comment>
+ <comment xml:lang="zh_CN">Lotus 1-2-3 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Lotus 1-2-3</comment>
+ <comment xml:lang="uk">електронна таблиця Lotus 1-2-3</comment>
+ <comment xml:lang="tr">Lotus 1-2-3 hesap çizelgesi</comment>
+ <comment xml:lang="sv">Lotus 1-2-3-kalkylblad</comment>
+ <comment xml:lang="sr">Лотусова 1-2-3 табела</comment>
+ <comment xml:lang="sq">fletëllogaritje Lotus 1-2-3</comment>
+ <comment xml:lang="sl">Preglednica Lotus 1-2-3</comment>
+ <comment xml:lang="si">නෙළුම් 1-2-3 පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Lotus 1-2-3</comment>
+ <comment xml:lang="ru">Электронная таблица Lotus 1-2-3</comment>
+ <comment xml:lang="ro">Foaie de calcul Lotus 1-2-3</comment>
+ <comment xml:lang="pt_BR">Planilha do Lotus 1-2-3</comment>
+ <comment xml:lang="pt">folha de cálculo Lotus 1-2-3</comment>
+ <comment xml:lang="pl">Arkusz Lotus 1-2-3</comment>
+ <comment xml:lang="oc">fuèlh de calcul Lotus 1-2-3</comment>
+ <comment xml:lang="nn">Lotus 1-2-3 rekneark</comment>
+ <comment xml:lang="nl">Lotus 1-2-3-rekenblad</comment>
+ <comment xml:lang="nb">Lotus 1-2-3 regneark</comment>
+ <comment xml:lang="ms">Hamparan Lotus 1-2-3</comment>
+ <comment xml:lang="lv">Lotus 1-2-3 izklājlapa</comment>
+ <comment xml:lang="lt">Lotus 1-2-3 skaičialentė</comment>
+ <comment xml:lang="ko">Lotus 1-2-3 스프레드시트</comment>
+ <comment xml:lang="kk">Lotus 1-2-3 электрондық кестесі</comment>
+ <comment xml:lang="ja">Lotus 1-2-3 スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Lotus 1-2-3</comment>
+ <comment xml:lang="is">Lotus 1-2-3 töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Lotus 1-2-3</comment>
+ <comment xml:lang="ia">Folio de calculo Lotus 1-2-3</comment>
+ <comment xml:lang="hu">Lotus 1-2-3-munkafüzet</comment>
+ <comment xml:lang="hr">Lotus 1-2-3 proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Lotus 1-2-3</comment>
+ <comment xml:lang="gl">folla de cálculo de Lotus 1-2-3</comment>
+ <comment xml:lang="ga">scarbhileog Lotus 1-2-3</comment>
+ <comment xml:lang="fur">sfuei di calcul Lotus 1-2-3</comment>
+ <comment xml:lang="fr">feuille de calcul Lotus 1-2-3</comment>
+ <comment xml:lang="fo">Lotus 1-2-3 rokniark</comment>
+ <comment xml:lang="fi">Lotus 1-2-3 -taulukko</comment>
+ <comment xml:lang="eu">Lotus 1-2-3 kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Lotus 1-2-3</comment>
+ <comment xml:lang="eo">Kalkultabelo de Lotus 1-2-3</comment>
+ <comment xml:lang="en_GB">Lotus 1-2-3 spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Lotus 1-2-3</comment>
+ <comment xml:lang="de">Lotus-1-2-3-Tabelle</comment>
+ <comment xml:lang="da">Lotus 1-2-3-regneark</comment>
+ <comment xml:lang="cy">Taenlen Lotus 1-2-3</comment>
+ <comment xml:lang="cs">sešit Lotus 1-2-3</comment>
+ <comment xml:lang="ca">full de càlcul de Lotus 1-2-3</comment>
+ <comment xml:lang="bg">Таблица — Lotus 1-2-3</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš Lotus 1-2-3</comment>
+ <comment xml:lang="be">электронная табліца Lotus 1-2-3</comment>
+ <comment xml:lang="az">Lotus 1-2-3 hesab cədvəli</comment>
+ <comment xml:lang="ast">Fueya de cálculu de Lotus 1-2-3</comment>
+ <comment xml:lang="ar">جدول Lotus 1-2-3</comment>
+ <comment xml:lang="af">Lotus 1-2-3 sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="\x00\x00\x02\x00\x06\x04\x06\x00\x08\x00\x00\x00\x00\x00" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\x00\x00\x02\x00\x06\x04\x06\x00\x08\x00\x00\x00\x00\x00" offset="0"/>
</magic>
<glob pattern="*.123"/>
<glob pattern="*.wk1"/>
@@ -2858,107 +3259,134 @@
<alias type="zz-application/zz-winassoc-123"/>
</mime-type>
<mime-type type="application/vnd.lotus-wordpro">
- <comment>Lotus Word Pro</comment>
- <comment xml:lang="ast">Lotus Word Pro</comment>
- <comment xml:lang="ca">Lotus Word Pro</comment>
- <comment xml:lang="cs">Lotus Word Pro</comment>
- <comment xml:lang="da">Lotus Word Pro</comment>
- <comment xml:lang="de">Lotus Word Pro</comment>
- <comment xml:lang="el">Lotus Word Pro</comment>
- <comment xml:lang="en_GB">Lotus Word Pro</comment>
- <comment xml:lang="es">Lotus Word Pro</comment>
- <comment xml:lang="eu">Lotus Word Pro</comment>
- <comment xml:lang="fi">Lotus Word Pro</comment>
- <comment xml:lang="fr">Lotus Word Pro</comment>
- <comment xml:lang="ga">Lotus Word Pro</comment>
- <comment xml:lang="gl">Lotus Word Pro</comment>
- <comment xml:lang="he">Lotus Word Pro</comment>
- <comment xml:lang="hr">Lotus Word Pro</comment>
- <comment xml:lang="hu">Lotus Word Pro</comment>
- <comment xml:lang="ia">Lotus Word Pro</comment>
- <comment xml:lang="id">Lotus Word Pro</comment>
- <comment xml:lang="it">Lotus Word Pro</comment>
- <comment xml:lang="ja">Lotus Word Pro</comment>
- <comment xml:lang="kk">Lotus Word Pro</comment>
- <comment xml:lang="ko">Lotus Word Pro</comment>
- <comment xml:lang="lv">Lotus Word Pro</comment>
- <comment xml:lang="oc">Lotus Word Pro</comment>
- <comment xml:lang="pl">Lotus Word Pro</comment>
- <comment xml:lang="pt">Lotus Word Pro</comment>
- <comment xml:lang="pt_BR">Lotus Word Pro</comment>
- <comment xml:lang="ru">Lotus Word Pro</comment>
- <comment xml:lang="sk">Lotus Word Pro</comment>
- <comment xml:lang="sl">Lotus Word Pro</comment>
- <comment xml:lang="sr">Лотусов Писац Про</comment>
- <comment xml:lang="sv">Lotus Word Pro</comment>
- <comment xml:lang="tr">Lotus Word Pro</comment>
- <comment xml:lang="uk">Lotus Word Pro</comment>
- <comment xml:lang="zh_CN">Lotus Word Pro</comment>
- <comment xml:lang="zh_TW">Lotus Word Pro</comment>
+ <comment>Lotus Word Pro document</comment>
+ <comment xml:lang="zh_TW">Lotus Word Pro 文件</comment>
+ <comment xml:lang="zh_CN">Lotus Word Pro 文档</comment>
+ <comment xml:lang="uk">документ Lotus Word Pro</comment>
+ <comment xml:lang="tr">Lotus Word Pro belgesi</comment>
+ <comment xml:lang="sv">Lotus Word Pro-dokument</comment>
+ <comment xml:lang="sq">dokument Lotus Word Pro</comment>
+ <comment xml:lang="sl">Dokument Lotus Word Pro</comment>
+ <comment xml:lang="si">Lotus Word Pro ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Lotus Word Pro</comment>
+ <comment xml:lang="ru">Документ Lotus Word Pro</comment>
+ <comment xml:lang="pt_BR">Documento do Lotus Word Pro</comment>
+ <comment xml:lang="pt">documento Lotus Word Pro</comment>
+ <comment xml:lang="pl">Dokument Lotus Word Pro</comment>
+ <comment xml:lang="oc">document Lotus Word Pro</comment>
+ <comment xml:lang="nl">Lotus Word Pro-document</comment>
+ <comment xml:lang="ko">Lotus 워드 프로 문서</comment>
+ <comment xml:lang="kk">Lotus Word Pro құжаты</comment>
+ <comment xml:lang="ja">Lotus Word Pro ドキュメント</comment>
+ <comment xml:lang="it">Documento Lotus Word Pro</comment>
+ <comment xml:lang="is">Lotus Word Pro skjal</comment>
+ <comment xml:lang="id">Dokumen Lotus Word Pro</comment>
+ <comment xml:lang="hu">Lotus Word Pro dokumentum</comment>
+ <comment xml:lang="hr">Lotus Word Pro dokument</comment>
+ <comment xml:lang="he">מסמך Lotus Word Pro</comment>
+ <comment xml:lang="gl">Documento de Lotus Word Pro</comment>
+ <comment xml:lang="fr">document Lotus Word Pro</comment>
+ <comment xml:lang="fi">Lotus Word Pro -asiakirja</comment>
+ <comment xml:lang="eu">Lotus Word Pro dokumentua</comment>
+ <comment xml:lang="es">documento de Lotus Word Pro</comment>
+ <comment xml:lang="en_GB">Lotus Word Pro document</comment>
+ <comment xml:lang="de">Lotus-Word-Pro-Dokument</comment>
+ <comment xml:lang="da">Lotus Word Pro-dokument</comment>
+ <comment xml:lang="ca">document de Lotus Word Pro</comment>
+ <comment xml:lang="bg">Документ — Lotus Word Pro</comment>
+ <comment xml:lang="be">дакумент Lotus Word Pro</comment>
+ <comment xml:lang="ar">مستند لوتس ورد برو</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="WordPro" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="WordPro" offset="0"/>
</magic>
<glob pattern="*.lwp"/>
</mime-type>
+ <mime-type type="application/x-lmdb">
+ <comment>LMDB database</comment>
+ <comment xml:lang="uk">база даних LMDB</comment>
+ <comment xml:lang="sv">LMDB-databas</comment>
+ <comment xml:lang="sq">bazë të dhënash LMDB</comment>
+ <comment xml:lang="ru">База данных LMDB</comment>
+ <comment xml:lang="pt_BR">Banco de dados LMDB</comment>
+ <comment xml:lang="pl">Baza danych LMDB</comment>
+ <comment xml:lang="it">Database LMDB</comment>
+ <comment xml:lang="gl">Base de datos LMDB</comment>
+ <comment xml:lang="eu">LMDB datu-basea</comment>
+ <comment xml:lang="es">base de datos LMDB</comment>
+ <comment xml:lang="de">LMDB-Datenbank</comment>
+ <comment xml:lang="be">база даных LMDB</comment>
+ <acronym>LMDB</acronym>
+ <expanded-acronym>Lightning Memory-Mapped Database</expanded-acronym>
+ <generic-icon name="x-office-document"/>
+ <magic>
+ <match offset="16" type="little32" value="0xBEEFC0DE"/>
+ </magic>
+ <glob pattern="*.mdb"/>
+ <glob pattern="*.lmdb"/>
+ </mime-type>
<mime-type type="application/vnd.ms-access">
<comment>JET database</comment>
- <comment xml:lang="ar">قاعدة بيانات JET</comment>
- <comment xml:lang="ast">Base de datos JETº</comment>
- <comment xml:lang="be@latin">Baza źviestak JET</comment>
- <comment xml:lang="bg">База от данни — JET</comment>
- <comment xml:lang="ca">base de dades JET</comment>
- <comment xml:lang="cs">databáze JET</comment>
- <comment xml:lang="da">JET-database</comment>
- <comment xml:lang="de">JET-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων JET</comment>
- <comment xml:lang="en_GB">JET database</comment>
- <comment xml:lang="eo">JET-datumbazo</comment>
- <comment xml:lang="es">base de datos JET</comment>
- <comment xml:lang="eu">JET datu-basea</comment>
- <comment xml:lang="fi">JET-tietokanta</comment>
- <comment xml:lang="fo">JET dátustovnur</comment>
- <comment xml:lang="fr">base de données JET</comment>
- <comment xml:lang="ga">bunachar sonraí JET</comment>
- <comment xml:lang="gl">base de datos JET</comment>
- <comment xml:lang="he">מסד נתונים מסוג JET</comment>
- <comment xml:lang="hr">JET baza podataka</comment>
- <comment xml:lang="hu">JET adatbázis</comment>
- <comment xml:lang="ia">Base de datos JET</comment>
- <comment xml:lang="id">Basis data JET</comment>
- <comment xml:lang="it">Database JET</comment>
- <comment xml:lang="ja">JET データベース</comment>
- <comment xml:lang="kk">JET дерекқоры</comment>
- <comment xml:lang="ko">JET 데이터베이스</comment>
- <comment xml:lang="lt">JET duomenų bazė</comment>
- <comment xml:lang="lv">JET datubāze</comment>
- <comment xml:lang="nb">JET-database</comment>
- <comment xml:lang="nl">JET-gegevensbank</comment>
- <comment xml:lang="nn">JET-database</comment>
- <comment xml:lang="oc">banca de donadas JET</comment>
- <comment xml:lang="pl">Baza Danych JET</comment>
- <comment xml:lang="pt">base de dados JET</comment>
- <comment xml:lang="pt_BR">Banco de dados JET</comment>
- <comment xml:lang="ro">Bază de date JET</comment>
- <comment xml:lang="ru">База данных JET</comment>
- <comment xml:lang="sk">Databáza JET</comment>
- <comment xml:lang="sl">Podatkovna zbirka JET</comment>
- <comment xml:lang="sq">Bazë me të dhëna JET</comment>
- <comment xml:lang="sr">ЈЕТ база података</comment>
- <comment xml:lang="sv">JET-databas</comment>
- <comment xml:lang="tr">JET veritabanı</comment>
- <comment xml:lang="uk">База даних JET</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu JET</comment>
- <comment xml:lang="zh_CN">JET 数据库</comment>
<comment xml:lang="zh_TW">JET 資料庫</comment>
+ <comment xml:lang="zh_CN">JET 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu JET</comment>
+ <comment xml:lang="uk">База даних JET</comment>
+ <comment xml:lang="tr">JET veri tabanı</comment>
+ <comment xml:lang="sv">JET-databas</comment>
+ <comment xml:lang="sr">ЈЕТ база података</comment>
+ <comment xml:lang="sq">bazë të dhënash JET</comment>
+ <comment xml:lang="sl">Podatkovna zbirka JET</comment>
+ <comment xml:lang="si">JET දත්ත සමුදාය</comment>
+ <comment xml:lang="sk">Databáza JET</comment>
+ <comment xml:lang="ru">База данных JET</comment>
+ <comment xml:lang="ro">Bază de date JET</comment>
+ <comment xml:lang="pt_BR">Banco de dados JET</comment>
+ <comment xml:lang="pt">base de dados JET</comment>
+ <comment xml:lang="pl">Baza Danych JET</comment>
+ <comment xml:lang="oc">banca de donadas JET</comment>
+ <comment xml:lang="nn">JET-database</comment>
+ <comment xml:lang="nl">JET-gegevensbank</comment>
+ <comment xml:lang="nb">JET-database</comment>
+ <comment xml:lang="lv">JET datubāze</comment>
+ <comment xml:lang="lt">JET duomenų bazė</comment>
+ <comment xml:lang="ko">JET 데이터베이스</comment>
+ <comment xml:lang="kk">JET дерекқоры</comment>
+ <comment xml:lang="ja">JET データベース</comment>
+ <comment xml:lang="it">Database JET</comment>
+ <comment xml:lang="is">JET gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data JET</comment>
+ <comment xml:lang="ia">Base de datos JET</comment>
+ <comment xml:lang="hu">JET adatbázis</comment>
+ <comment xml:lang="hr">JET baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים מסוג JET</comment>
+ <comment xml:lang="gl">base de datos JET</comment>
+ <comment xml:lang="ga">bunachar sonraí JET</comment>
+ <comment xml:lang="fur">base di dâts JET</comment>
+ <comment xml:lang="fr">base de données JET</comment>
+ <comment xml:lang="fo">JET dátustovnur</comment>
+ <comment xml:lang="fi">JET-tietokanta</comment>
+ <comment xml:lang="eu">JET datu-basea</comment>
+ <comment xml:lang="es">base de datos JET</comment>
+ <comment xml:lang="eo">JET-datumbazo</comment>
+ <comment xml:lang="en_GB">JET database</comment>
+ <comment xml:lang="el">Βάση δεδομένων JET</comment>
+ <comment xml:lang="de">JET-Datenbank</comment>
+ <comment xml:lang="da">JET-database</comment>
+ <comment xml:lang="cs">databáze JET</comment>
+ <comment xml:lang="ca">base de dades JET</comment>
+ <comment xml:lang="bg">База от данни — JET</comment>
+ <comment xml:lang="be@latin">Baza źviestak JET</comment>
+ <comment xml:lang="be">база даных JET</comment>
+ <comment xml:lang="ast">Base de datos JETº</comment>
+ <comment xml:lang="ar">قاعدة بيانات JET</comment>
+ <comment xml:lang="af">JET-databasis</comment>
<acronym>JET</acronym>
<expanded-acronym>Joint Engine Technology</expanded-acronym>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="\x00\x01\x00\x00Standard Jet DB" type="string" offset="0"/>
+ <magic>
+ <match offset="0" type="string" value="\x00\x01\x00\x00Standard Jet DB"/>
</magic>
- <glob pattern="*.mdb"/>
- <alias type="application/x-msaccess"/>
+ <glob pattern="*.mdb" weight="60"/>
<alias type="application/msaccess"/>
<alias type="application/vnd.msaccess"/>
<alias type="application/x-msaccess"/>
@@ -2968,109 +3396,121 @@
</mime-type>
<mime-type type="application/vnd.ms-cab-compressed">
<comment>Microsoft Cabinet archive</comment>
- <comment xml:lang="ar">أرشيف Microsoft Cabinet</comment>
- <comment xml:lang="bg">Архив — Microsoft Cabinet</comment>
- <comment xml:lang="ca">arxiu de Microsoft Cabinet</comment>
- <comment xml:lang="cs">archiv Microsoft Cabinet</comment>
- <comment xml:lang="da">Microsoft Cabinet-arkiv</comment>
- <comment xml:lang="de">Microsoft-Cabinet-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Microsoft Cabinet</comment>
- <comment xml:lang="en_GB">Microsoft Cabinet archive</comment>
- <comment xml:lang="es">archivador Cabinet de Microsoft</comment>
- <comment xml:lang="eu">Microsoft Cabinet artxiboa</comment>
- <comment xml:lang="fi">Microsoft Cabinet -arkisto</comment>
- <comment xml:lang="fo">Microsoft Cabinet skjalasavn</comment>
- <comment xml:lang="fr">archive Cab Microsoft</comment>
- <comment xml:lang="ga">cartlann Microsoft Cabinet</comment>
- <comment xml:lang="gl">arquivo de Microsoft Cabinet</comment>
- <comment xml:lang="he">ארכיון CAB (מיקרוסופט)</comment>
- <comment xml:lang="hr">Microsoft Cabinet arhiva</comment>
- <comment xml:lang="hu">Microsoft Cabinet archívum</comment>
- <comment xml:lang="ia">Archivo Microsoft Cabinet</comment>
- <comment xml:lang="id">Arsip Microsoft Cabinet</comment>
- <comment xml:lang="it">Archivio Microsoft Cabinet</comment>
- <comment xml:lang="ja">Microsoft Cabinet アーカイブ</comment>
- <comment xml:lang="ka">Microsoft-ის Cabinet არქივი</comment>
- <comment xml:lang="kk">Microsoft Cabinet архиві</comment>
- <comment xml:lang="ko">Microsoft Cabinte 압축 파일</comment>
- <comment xml:lang="lt">Microsoft Cabinet archyvas</comment>
- <comment xml:lang="lv">Microsoft kabineta arhīvs</comment>
- <comment xml:lang="nl">Microsoft Cabinet-archief</comment>
- <comment xml:lang="oc">archiu Cab Microsoft</comment>
- <comment xml:lang="pl">Archiwum Microsoft Cabinet</comment>
- <comment xml:lang="pt">arquivo Microsoft Cabinet</comment>
- <comment xml:lang="pt_BR">Pacote Cabinet da Microsoft</comment>
- <comment xml:lang="ro">Arhivă Microsoft Cabinet</comment>
- <comment xml:lang="ru">Архив Microsoft Cabinet</comment>
- <comment xml:lang="sk">Archív Microsoft Cabinet</comment>
- <comment xml:lang="sl">Datoteka arhiva Microsoft Cabinet</comment>
- <comment xml:lang="sr">Мајкрософтова кабинет архива</comment>
- <comment xml:lang="sv">Microsoft Cabinet-arkiv</comment>
- <comment xml:lang="tr">Microsoft Cabinet arşivi</comment>
- <comment xml:lang="uk">архів Cabinet Microsoft</comment>
- <comment xml:lang="vi">Kho lưu Cabinet Microsoft</comment>
- <comment xml:lang="zh_CN">Microsoft Cabinet 归档文件</comment>
<comment xml:lang="zh_TW">微軟 Cabinet 封存檔</comment>
+ <comment xml:lang="zh_CN">Microsoft Cabinet 归档文件</comment>
+ <comment xml:lang="vi">Kho lưu Cabinet Microsoft</comment>
+ <comment xml:lang="uk">архів Cabinet Microsoft</comment>
+ <comment xml:lang="tr">Microsoft Cabinet arşivi</comment>
+ <comment xml:lang="sv">Microsoft Cabinet-arkiv</comment>
+ <comment xml:lang="sr">Мајкрософтова кабинет архива</comment>
+ <comment xml:lang="sq">arkiv Microsoft Cabinet</comment>
+ <comment xml:lang="sl">Datoteka arhiva Microsoft Cabinet</comment>
+ <comment xml:lang="si">Microsoft කැබිනට් සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Microsoft Cabinet</comment>
+ <comment xml:lang="ru">Архив Microsoft Cabinet</comment>
+ <comment xml:lang="ro">Arhivă Microsoft Cabinet</comment>
+ <comment xml:lang="pt_BR">Pacote Cabinet da Microsoft</comment>
+ <comment xml:lang="pt">arquivo Microsoft Cabinet</comment>
+ <comment xml:lang="pl">Archiwum Microsoft Cabinet</comment>
+ <comment xml:lang="oc">archiu Cab Microsoft</comment>
+ <comment xml:lang="nl">Microsoft Cabinet-archief</comment>
+ <comment xml:lang="lv">Microsoft kabineta arhīvs</comment>
+ <comment xml:lang="lt">Microsoft Cabinet archyvas</comment>
+ <comment xml:lang="ko">Microsoft Cabinet 압축 파일</comment>
+ <comment xml:lang="kk">Microsoft Cabinet архиві</comment>
+ <comment xml:lang="ka">Microsoft-ის Cabinet არქივი</comment>
+ <comment xml:lang="ja">Microsoft Cabinet アーカイブ</comment>
+ <comment xml:lang="it">Archivio Microsoft Cabinet</comment>
+ <comment xml:lang="is">Microsoft Cabinet safnskrá</comment>
+ <comment xml:lang="id">Arsip Microsoft Cabinet</comment>
+ <comment xml:lang="ia">Archivo Microsoft Cabinet</comment>
+ <comment xml:lang="hu">Microsoft Cabinet archívum</comment>
+ <comment xml:lang="hr">Microsoft Cabinet arhiva</comment>
+ <comment xml:lang="he">ארכיון CAB (מיקרוסופט)</comment>
+ <comment xml:lang="gl">arquivo de Microsoft Cabinet</comment>
+ <comment xml:lang="ga">cartlann Microsoft Cabinet</comment>
+ <comment xml:lang="fur">archivi Cabinet Microsoft</comment>
+ <comment xml:lang="fr">archive Cab Microsoft</comment>
+ <comment xml:lang="fo">Microsoft Cabinet skjalasavn</comment>
+ <comment xml:lang="fi">Microsoft Cabinet -arkisto</comment>
+ <comment xml:lang="eu">Microsoft Cabinet artxiboa</comment>
+ <comment xml:lang="es">archivador Cabinet de Microsoft</comment>
+ <comment xml:lang="en_GB">Microsoft Cabinet archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Microsoft Cabinet</comment>
+ <comment xml:lang="de">Microsoft-Cabinet-Archiv</comment>
+ <comment xml:lang="da">Microsoft Cabinet-arkiv</comment>
+ <comment xml:lang="cs">archiv Microsoft Cabinet</comment>
+ <comment xml:lang="ca">arxiu de Microsoft Cabinet</comment>
+ <comment xml:lang="bg">Архив — Microsoft Cabinet</comment>
+ <comment xml:lang="be">архіў Microsoft Cabinet</comment>
+ <comment xml:lang="ar">أرشيف Microsoft Cabinet</comment>
+ <comment xml:lang="af">Microsoft Cabinet-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="MSCF\0\0\0\0" type="string" offset="0"/>
+ <match offset="0" type="string" value="MSCF\0\0\0\0"/>
</magic>
<glob pattern="*.cab"/>
<alias type="zz-application/zz-winassoc-cab"/>
</mime-type>
<mime-type type="application/vnd.ms-excel">
<comment>Excel spreadsheet</comment>
- <comment xml:lang="ar">جدول Excel</comment>
- <comment xml:lang="be@latin">Raźlikovy akruš Excel</comment>
- <comment xml:lang="bg">Таблица — Excel</comment>
- <comment xml:lang="ca">full de càlcul d'Excel</comment>
- <comment xml:lang="cs">sešit Excel</comment>
- <comment xml:lang="da">Excelregneark</comment>
- <comment xml:lang="de">Excel-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Excel</comment>
- <comment xml:lang="en_GB">Excel spreadsheet</comment>
- <comment xml:lang="eo">Excel-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo de Excel</comment>
- <comment xml:lang="eu">Excel kalkulu-orria</comment>
- <comment xml:lang="fi">Excel-taulukko</comment>
- <comment xml:lang="fo">Excel rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Excel</comment>
- <comment xml:lang="ga">scarbhileog Excel</comment>
- <comment xml:lang="gl">folla de cálculo de Excel</comment>
- <comment xml:lang="he">גליון נתונים של Excel</comment>
- <comment xml:lang="hr">Excel proračunska tablica</comment>
- <comment xml:lang="hu">Excel táblázat</comment>
- <comment xml:lang="ia">Folio de calculo Excel</comment>
- <comment xml:lang="id">Lembar sebar Excel</comment>
- <comment xml:lang="it">Foglio di calcolo Excel</comment>
- <comment xml:lang="ja">Excel スプレッドシート</comment>
- <comment xml:lang="ka">Excel-ის ცხრილი</comment>
- <comment xml:lang="kk">Excel электрондық кестесі</comment>
- <comment xml:lang="ko">Excel 스프레드시트</comment>
- <comment xml:lang="lt">Excel skaičialentė</comment>
- <comment xml:lang="lv">Excel izklājlapa</comment>
- <comment xml:lang="nb">Excel regneark</comment>
- <comment xml:lang="nl">Excel-rekenblad</comment>
- <comment xml:lang="nn">Excel-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul Excel</comment>
- <comment xml:lang="pl">Arkusz Excel</comment>
- <comment xml:lang="pt">folha de cálculo Excel</comment>
- <comment xml:lang="pt_BR">Planilha do Excel</comment>
- <comment xml:lang="ro">Foaie de calcul Excel</comment>
- <comment xml:lang="ru">Электронная таблица Excel</comment>
- <comment xml:lang="sk">Zošit Excel</comment>
- <comment xml:lang="sl">Razpredelnica Microsoft Excel</comment>
- <comment xml:lang="sq">Fletë llogaritje Excel</comment>
- <comment xml:lang="sr">Екселова табела</comment>
- <comment xml:lang="sv">Excel-kalkylblad</comment>
- <comment xml:lang="tr">Excel çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Excel</comment>
- <comment xml:lang="vi">Bảng tính Excel</comment>
- <comment xml:lang="zh_CN">Excel 电子表格</comment>
<comment xml:lang="zh_TW">Excel 試算表</comment>
+ <comment xml:lang="zh_CN">Excel 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Excel</comment>
+ <comment xml:lang="uk">електронна таблиця Excel</comment>
+ <comment xml:lang="tr">Excel hesap çizelgesi</comment>
+ <comment xml:lang="sv">Excel-kalkylblad</comment>
+ <comment xml:lang="sr">Екселова табела</comment>
+ <comment xml:lang="sq">fletëllogaritje Excel</comment>
+ <comment xml:lang="sl">Razpredelnica Microsoft Excel</comment>
+ <comment xml:lang="si">එක්සෙල් පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Excel</comment>
+ <comment xml:lang="ru">Электронная таблица Excel</comment>
+ <comment xml:lang="ro">Foaie de calcul Excel</comment>
+ <comment xml:lang="pt_BR">Planilha do Excel</comment>
+ <comment xml:lang="pt">folha de cálculo Excel</comment>
+ <comment xml:lang="pl">Arkusz Excel</comment>
+ <comment xml:lang="oc">fuèlh de calcul Excel</comment>
+ <comment xml:lang="nn">Excel-rekneark</comment>
+ <comment xml:lang="nl">Excel-rekenblad</comment>
+ <comment xml:lang="nb">Excel regneark</comment>
+ <comment xml:lang="lv">Excel izklājlapa</comment>
+ <comment xml:lang="lt">Excel skaičialentė</comment>
+ <comment xml:lang="ko">Excel 스프레드시트</comment>
+ <comment xml:lang="kk">Excel электрондық кестесі</comment>
+ <comment xml:lang="ka">Excel-ის ცხრილი</comment>
+ <comment xml:lang="ja">Excel スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Excel</comment>
+ <comment xml:lang="is">Excel töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Excel</comment>
+ <comment xml:lang="ia">Folio de calculo Excel</comment>
+ <comment xml:lang="hu">Excel táblázat</comment>
+ <comment xml:lang="hr">Excel proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Excel</comment>
+ <comment xml:lang="gl">folla de cálculo de Excel</comment>
+ <comment xml:lang="ga">scarbhileog Excel</comment>
+ <comment xml:lang="fur">sfuei di calcul Excel</comment>
+ <comment xml:lang="fr">feuille de calcul Excel</comment>
+ <comment xml:lang="fo">Excel rokniark</comment>
+ <comment xml:lang="fi">Excel-taulukko</comment>
+ <comment xml:lang="eu">Excel kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Excel</comment>
+ <comment xml:lang="eo">Excel-kalkultabelo</comment>
+ <comment xml:lang="en_GB">Excel spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Excel</comment>
+ <comment xml:lang="de">Excel-Tabelle</comment>
+ <comment xml:lang="da">Excelregneark</comment>
+ <comment xml:lang="cs">sešit Excel</comment>
+ <comment xml:lang="ca">full de càlcul d'Excel</comment>
+ <comment xml:lang="bg">Таблица — Excel</comment>
+ <comment xml:lang="be@latin">Raźlikovy akruš Excel</comment>
+ <comment xml:lang="be">электронная табліца Excel</comment>
+ <comment xml:lang="ar">جدول اكسل</comment>
+ <comment xml:lang="af">Excel-sigblad</comment>
+ <sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="Microsoft Excel 5.0 Worksheet" type="string" offset="2080"/>
+ <magic>
+ <match type="string" value="Microsoft Excel 5.0 Worksheet" offset="2080"/>
</magic>
<glob pattern="*.xls"/>
<glob pattern="*.xlc"/>
@@ -3086,232 +3526,269 @@
</mime-type>
<mime-type type="application/vnd.ms-excel.addin.macroEnabled.12">
<comment>Excel add-in</comment>
- <comment xml:lang="bg">Приставка — Excel</comment>
- <comment xml:lang="ca">complement d'Excel</comment>
- <comment xml:lang="cs">doplněk aplikace Excel</comment>
- <comment xml:lang="da">Excel-tilføjelse</comment>
- <comment xml:lang="de">Excel Add-in</comment>
- <comment xml:lang="el">Πρόσθετο Excel</comment>
- <comment xml:lang="en_GB">Excel add-in</comment>
- <comment xml:lang="es">complemento de Excel</comment>
- <comment xml:lang="eu">Excel gehigarria</comment>
- <comment xml:lang="fi">Excel-lisäosa</comment>
- <comment xml:lang="fr">complément Excel</comment>
- <comment xml:lang="ga">breiseán Excel</comment>
- <comment xml:lang="gl">complemento de Excel</comment>
- <comment xml:lang="he">תוסף של Excel</comment>
- <comment xml:lang="hr">Excel dodatak</comment>
- <comment xml:lang="hu">Excel bővítmény</comment>
- <comment xml:lang="ia">Add-in Excel</comment>
- <comment xml:lang="id">Add-in Excel</comment>
- <comment xml:lang="it">Add-in Excel</comment>
- <comment xml:lang="ja">Excel アドイン</comment>
- <comment xml:lang="ka">Excel-ის დამატება</comment>
- <comment xml:lang="kk">Excel қосымшасы</comment>
- <comment xml:lang="ko">Excel 추가 기능</comment>
- <comment xml:lang="lv">Excel pievienojumprogramma</comment>
- <comment xml:lang="nl">Excel add-in</comment>
- <comment xml:lang="oc">complement Excel</comment>
- <comment xml:lang="pl">Dodatek Excel</comment>
- <comment xml:lang="pt">Extensão Excel</comment>
- <comment xml:lang="pt_BR">Suplemento do Excel</comment>
- <comment xml:lang="ru">Дополнение Excel</comment>
- <comment xml:lang="sk">Doplnok aplikácie Excel</comment>
- <comment xml:lang="sl">Vstavek Excel</comment>
- <comment xml:lang="sr">Екселов додатак</comment>
- <comment xml:lang="sv">Excel-tillägg</comment>
- <comment xml:lang="tr">Excel eklentisi</comment>
- <comment xml:lang="uk">додаток Excel</comment>
- <comment xml:lang="zh_CN">Excel 外接程序</comment>
<comment xml:lang="zh_TW">Excel 增益集</comment>
+ <comment xml:lang="zh_CN">Excel 外接程序</comment>
+ <comment xml:lang="uk">додаток Excel</comment>
+ <comment xml:lang="tr">Excel eklentisi</comment>
+ <comment xml:lang="sv">Excel-tillägg</comment>
+ <comment xml:lang="sr">Екселов додатак</comment>
+ <comment xml:lang="sq">shtojcë Excel</comment>
+ <comment xml:lang="sl">Vstavek Excel</comment>
+ <comment xml:lang="si">එක්සෙල් ඇඩෝනය</comment>
+ <comment xml:lang="sk">Doplnok aplikácie Excel</comment>
+ <comment xml:lang="ru">Дополнение Excel</comment>
+ <comment xml:lang="pt_BR">Suplemento do Excel</comment>
+ <comment xml:lang="pt">Extensão Excel</comment>
+ <comment xml:lang="pl">Dodatek Excel</comment>
+ <comment xml:lang="oc">complement Excel</comment>
+ <comment xml:lang="nl">Excel-add-in</comment>
+ <comment xml:lang="lv">Excel pievienojumprogramma</comment>
+ <comment xml:lang="ko">Excel 추가 기능</comment>
+ <comment xml:lang="kk">Excel қосымшасы</comment>
+ <comment xml:lang="ka">Excel-ის დამატება</comment>
+ <comment xml:lang="ja">Excel アドイン</comment>
+ <comment xml:lang="it">Add-in Excel</comment>
+ <comment xml:lang="is">Excel viðbót</comment>
+ <comment xml:lang="id">Add-in Excel</comment>
+ <comment xml:lang="ia">Add-in Excel</comment>
+ <comment xml:lang="hu">Excel bővítmény</comment>
+ <comment xml:lang="hr">Excel dodatak</comment>
+ <comment xml:lang="he">תוסף של Excel</comment>
+ <comment xml:lang="gl">complemento de Excel</comment>
+ <comment xml:lang="ga">breiseán Excel</comment>
+ <comment xml:lang="fur">zonte Excel</comment>
+ <comment xml:lang="fr">complément Excel</comment>
+ <comment xml:lang="fi">Excel-lisäosa</comment>
+ <comment xml:lang="eu">Excel gehigarria</comment>
+ <comment xml:lang="es">complemento de Excel</comment>
+ <comment xml:lang="en_GB">Excel add-in</comment>
+ <comment xml:lang="el">Πρόσθετο Excel</comment>
+ <comment xml:lang="de">Excel-Add-in</comment>
+ <comment xml:lang="da">Excel-tilføjelse</comment>
+ <comment xml:lang="cs">doplněk aplikace Excel</comment>
+ <comment xml:lang="ca">complement d'Excel</comment>
+ <comment xml:lang="bg">Приставка — Excel</comment>
+ <comment xml:lang="be">надбудова Excel</comment>
+ <comment xml:lang="ar">إضافة اكسل</comment>
+ <comment xml:lang="af">Excel-byvoeging</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xlam"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/>
</mime-type>
<mime-type type="application/vnd.ms-excel.sheet.binary.macroEnabled.12">
<comment>Excel 2007 binary spreadsheet</comment>
- <comment xml:lang="bg">Таблица — Excel 2007, двоична</comment>
- <comment xml:lang="ca">full de càlcul binari d'Excel 2007</comment>
- <comment xml:lang="cs">binární formát sešitu Excel 2007</comment>
- <comment xml:lang="da">Binært Excel 2007-regneark</comment>
- <comment xml:lang="de">Excel-2007-Tabelle (binär)</comment>
- <comment xml:lang="el">Δυαδικό λογιστικό φύλλο Excel 2007</comment>
- <comment xml:lang="en_GB">Excel 2007 binary spreadsheet</comment>
- <comment xml:lang="es">hoja de cálculo binaria de Excel 2007</comment>
- <comment xml:lang="eu">Excel 2007 kalkulu-orri binarioa</comment>
- <comment xml:lang="fi">Excel 2007:n binaarinen taulukko</comment>
- <comment xml:lang="fr">feuille de calcul binaire Excel 2007</comment>
- <comment xml:lang="ga">scarbhileog dhénártha Excel 2007</comment>
- <comment xml:lang="gl">ficheiro binario de folla de cálculo Excel 2007</comment>
- <comment xml:lang="he">גיליון נתונים בינרי של Excel 2007</comment>
- <comment xml:lang="hr">Excel 2007 binarna proračunska tablica</comment>
- <comment xml:lang="hu">Excel 2007 bináris táblázat</comment>
- <comment xml:lang="ia">Folio de calculo binari Excel 2007</comment>
- <comment xml:lang="id">Lembar kerja biner Excel 2007</comment>
- <comment xml:lang="it">Foglio di calcolo binario Excel 2007</comment>
- <comment xml:lang="ja">Excel 2007 バイナリスプレッドシート</comment>
- <comment xml:lang="ka">Excel 2007-ის ბინარული ცხრილი</comment>
- <comment xml:lang="kk">Excel 2007 бинарды кестесі</comment>
- <comment xml:lang="ko">Excel 2007 바이너리 스프레드시트</comment>
- <comment xml:lang="lv">Excel 2007 binārā izklājlapa</comment>
- <comment xml:lang="nl">Excel 2007 binary spreadsheet</comment>
- <comment xml:lang="oc">fuèlh de calcul binaire Excel 2007</comment>
- <comment xml:lang="pl">Binarny arkusz Excel 2007</comment>
- <comment xml:lang="pt">folha de cálculo binária Excel 2007</comment>
- <comment xml:lang="pt_BR">Planilha binária do Excel 2007</comment>
- <comment xml:lang="ru">Двоичная электронная таблица Excel 2007</comment>
- <comment xml:lang="sk">Binárny zošit Excel 2007</comment>
- <comment xml:lang="sl">Binarna preglednica Excel 2007</comment>
- <comment xml:lang="sr">Ексел 2007 бинарна табела</comment>
- <comment xml:lang="sv">Binärt Excel 2007-kalkylblad</comment>
- <comment xml:lang="tr">Excel 2007 ikilik çalışma sayfası</comment>
- <comment xml:lang="uk">бінарна електронна таблиця Excel 2007</comment>
- <comment xml:lang="zh_CN">Excel 2007 二进制电子表格</comment>
<comment xml:lang="zh_TW">Excel 2007 二進位試算表</comment>
+ <comment xml:lang="zh_CN">Excel 2007 二进制电子表格</comment>
+ <comment xml:lang="uk">бінарна електронна таблиця Excel 2007</comment>
+ <comment xml:lang="tr">Excel 2007 ikilik hesap çizelgesi</comment>
+ <comment xml:lang="sv">Binärt Excel 2007-kalkylblad</comment>
+ <comment xml:lang="sr">Ексел 2007 бинарна табела</comment>
+ <comment xml:lang="sq">fletëllogaritje dyore Excel 2007</comment>
+ <comment xml:lang="sl">Binarna preglednica Excel 2007</comment>
+ <comment xml:lang="si">Excel 2007 ද්විමය පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Binárny zošit Excel 2007</comment>
+ <comment xml:lang="ru">Двоичная электронная таблица Excel 2007</comment>
+ <comment xml:lang="pt_BR">Planilha binária do Excel 2007</comment>
+ <comment xml:lang="pt">folha de cálculo binária Excel 2007</comment>
+ <comment xml:lang="pl">Binarny arkusz Excel 2007</comment>
+ <comment xml:lang="oc">fuèlh de calcul binaire Excel 2007</comment>
+ <comment xml:lang="nl">Excel 2007 binair rekenblad</comment>
+ <comment xml:lang="lv">Excel 2007 binārā izklājlapa</comment>
+ <comment xml:lang="ko">Excel 2007 바이너리 스프레드시트</comment>
+ <comment xml:lang="kk">Excel 2007 бинарды кестесі</comment>
+ <comment xml:lang="ka">Excel 2007-ის ბინარული ცხრილი</comment>
+ <comment xml:lang="ja">Excel 2007 バイナリスプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo binario Excel 2007</comment>
+ <comment xml:lang="is">Excel tvíunddarkerfis töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar kerja biner Excel 2007</comment>
+ <comment xml:lang="ia">Folio de calculo binari Excel 2007</comment>
+ <comment xml:lang="hu">Excel 2007 bináris táblázat</comment>
+ <comment xml:lang="hr">Excel 2007 binarna proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים בינרי של Excel 2007</comment>
+ <comment xml:lang="gl">ficheiro binario de folla de cálculo Excel 2007</comment>
+ <comment xml:lang="ga">scarbhileog dhénártha Excel 2007</comment>
+ <comment xml:lang="fur">sfuei di calcul binari Excel 2007</comment>
+ <comment xml:lang="fr">feuille de calcul binaire Excel 2007</comment>
+ <comment xml:lang="fi">Excel 2007 binäärinen taulukko</comment>
+ <comment xml:lang="eu">Excel 2007 kalkulu-orri binarioa</comment>
+ <comment xml:lang="es">hoja de cálculo binaria de Excel 2007</comment>
+ <comment xml:lang="en_GB">Excel 2007 binary spreadsheet</comment>
+ <comment xml:lang="el">Δυαδικό λογιστικό φύλλο Excel 2007</comment>
+ <comment xml:lang="de">Excel-2007-Tabelle (binär)</comment>
+ <comment xml:lang="da">Binært Excel 2007-regneark</comment>
+ <comment xml:lang="cs">binární formát sešitu Excel 2007</comment>
+ <comment xml:lang="ca">full de càlcul binari d'Excel 2007</comment>
+ <comment xml:lang="bg">Таблица — Excel 2007, двоична</comment>
+ <comment xml:lang="be">двайковая электронная табліца Excel 2007</comment>
+ <comment xml:lang="ar">مستند اكسل 2007 ثنائي</comment>
+ <comment xml:lang="af">Excel 2007 binêre sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xlsb"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/>
</mime-type>
<mime-type type="application/vnd.ms-excel.sheet.macroEnabled.12">
<comment>Excel spreadsheet</comment>
- <comment xml:lang="ar">جدول Excel</comment>
- <comment xml:lang="be@latin">Raźlikovy akruš Excel</comment>
- <comment xml:lang="bg">Таблица — Excel</comment>
- <comment xml:lang="ca">full de càlcul d'Excel</comment>
- <comment xml:lang="cs">sešit Excel</comment>
- <comment xml:lang="da">Excelregneark</comment>
- <comment xml:lang="de">Excel-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Excel</comment>
- <comment xml:lang="en_GB">Excel spreadsheet</comment>
- <comment xml:lang="eo">Excel-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo de Excel</comment>
- <comment xml:lang="eu">Excel kalkulu-orria</comment>
- <comment xml:lang="fi">Excel-taulukko</comment>
- <comment xml:lang="fo">Excel rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Excel</comment>
- <comment xml:lang="ga">scarbhileog Excel</comment>
- <comment xml:lang="gl">folla de cálculo de Excel</comment>
- <comment xml:lang="he">גליון נתונים של Excel</comment>
- <comment xml:lang="hr">Excel proračunska tablica</comment>
- <comment xml:lang="hu">Excel táblázat</comment>
- <comment xml:lang="ia">Folio de calculo Excel</comment>
- <comment xml:lang="id">Lembar sebar Excel</comment>
- <comment xml:lang="it">Foglio di calcolo Excel</comment>
- <comment xml:lang="ja">Excel スプレッドシート</comment>
- <comment xml:lang="ka">Excel-ის ცხრილი</comment>
- <comment xml:lang="kk">Excel электрондық кестесі</comment>
- <comment xml:lang="ko">Excel 스프레드시트</comment>
- <comment xml:lang="lt">Excel skaičialentė</comment>
- <comment xml:lang="lv">Excel izklājlapa</comment>
- <comment xml:lang="nb">Excel regneark</comment>
- <comment xml:lang="nl">Excel-rekenblad</comment>
- <comment xml:lang="nn">Excel-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul Excel</comment>
- <comment xml:lang="pl">Arkusz Excel</comment>
- <comment xml:lang="pt">folha de cálculo Excel</comment>
- <comment xml:lang="pt_BR">Planilha do Excel</comment>
- <comment xml:lang="ro">Foaie de calcul Excel</comment>
- <comment xml:lang="ru">Электронная таблица Excel</comment>
- <comment xml:lang="sk">Zošit Excel</comment>
- <comment xml:lang="sl">Razpredelnica Microsoft Excel</comment>
- <comment xml:lang="sq">Fletë llogaritje Excel</comment>
- <comment xml:lang="sr">Екселова табела</comment>
- <comment xml:lang="sv">Excel-kalkylblad</comment>
- <comment xml:lang="tr">Excel çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Excel</comment>
- <comment xml:lang="vi">Bảng tính Excel</comment>
- <comment xml:lang="zh_CN">Excel 电子表格</comment>
<comment xml:lang="zh_TW">Excel 試算表</comment>
+ <comment xml:lang="zh_CN">Excel 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Excel</comment>
+ <comment xml:lang="uk">електронна таблиця Excel</comment>
+ <comment xml:lang="tr">Excel hesap çizelgesi</comment>
+ <comment xml:lang="sv">Excel-kalkylblad</comment>
+ <comment xml:lang="sr">Екселова табела</comment>
+ <comment xml:lang="sq">fletëllogaritje Excel</comment>
+ <comment xml:lang="sl">Razpredelnica Microsoft Excel</comment>
+ <comment xml:lang="si">එක්සෙල් පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Excel</comment>
+ <comment xml:lang="ru">Электронная таблица Excel</comment>
+ <comment xml:lang="ro">Foaie de calcul Excel</comment>
+ <comment xml:lang="pt_BR">Planilha do Excel</comment>
+ <comment xml:lang="pt">folha de cálculo Excel</comment>
+ <comment xml:lang="pl">Arkusz Excel</comment>
+ <comment xml:lang="oc">fuèlh de calcul Excel</comment>
+ <comment xml:lang="nn">Excel-rekneark</comment>
+ <comment xml:lang="nl">Excel-rekenblad</comment>
+ <comment xml:lang="nb">Excel regneark</comment>
+ <comment xml:lang="lv">Excel izklājlapa</comment>
+ <comment xml:lang="lt">Excel skaičialentė</comment>
+ <comment xml:lang="ko">Excel 스프레드시트</comment>
+ <comment xml:lang="kk">Excel электрондық кестесі</comment>
+ <comment xml:lang="ka">Excel-ის ცხრილი</comment>
+ <comment xml:lang="ja">Excel スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Excel</comment>
+ <comment xml:lang="is">Excel töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Excel</comment>
+ <comment xml:lang="ia">Folio de calculo Excel</comment>
+ <comment xml:lang="hu">Excel táblázat</comment>
+ <comment xml:lang="hr">Excel proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Excel</comment>
+ <comment xml:lang="gl">folla de cálculo de Excel</comment>
+ <comment xml:lang="ga">scarbhileog Excel</comment>
+ <comment xml:lang="fur">sfuei di calcul Excel</comment>
+ <comment xml:lang="fr">feuille de calcul Excel</comment>
+ <comment xml:lang="fo">Excel rokniark</comment>
+ <comment xml:lang="fi">Excel-taulukko</comment>
+ <comment xml:lang="eu">Excel kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Excel</comment>
+ <comment xml:lang="eo">Excel-kalkultabelo</comment>
+ <comment xml:lang="en_GB">Excel spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Excel</comment>
+ <comment xml:lang="de">Excel-Tabelle</comment>
+ <comment xml:lang="da">Excelregneark</comment>
+ <comment xml:lang="cs">sešit Excel</comment>
+ <comment xml:lang="ca">full de càlcul d'Excel</comment>
+ <comment xml:lang="bg">Таблица — Excel</comment>
+ <comment xml:lang="be@latin">Raźlikovy akruš Excel</comment>
+ <comment xml:lang="be">электронная табліца Excel</comment>
+ <comment xml:lang="ar">جدول اكسل</comment>
+ <comment xml:lang="af">Excel-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xlsm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/>
</mime-type>
<mime-type type="application/vnd.ms-excel.template.macroEnabled.12">
<comment>Excel spreadsheet template</comment>
- <comment xml:lang="ca">plantilla de full de càlcul d'Excel</comment>
- <comment xml:lang="cs">šablona tabulky Excel</comment>
- <comment xml:lang="da">Excel-regnearksskabelon</comment>
- <comment xml:lang="de">Excel-Tabellenvorlage</comment>
- <comment xml:lang="el">Πρότυπο λογιστικού φύλλου Excel</comment>
- <comment xml:lang="en_GB">Excel spreadsheet template</comment>
- <comment xml:lang="es">plantilla de libro de Excel</comment>
- <comment xml:lang="eu">Excel kalkulu-orri txantiloia</comment>
- <comment xml:lang="fi">Excel-taulukkomalli</comment>
- <comment xml:lang="fr">modèle de feuille de calcul Excel</comment>
- <comment xml:lang="ga">teimpléad scarbhileoige Excel</comment>
- <comment xml:lang="he">תבנית גיליון נתונים של Excel</comment>
- <comment xml:lang="hr">Predložak Excel proračunske tablice</comment>
- <comment xml:lang="hu">Excel munkafüzetsablon</comment>
- <comment xml:lang="ia">Patrono de folio de calculo Excel</comment>
- <comment xml:lang="id">Templat lembar kerja Excel</comment>
- <comment xml:lang="it">Modello foglio di calcolo Excel</comment>
- <comment xml:lang="kk">Excel кестесінің үлгісі</comment>
- <comment xml:lang="ko">Excel 스프레드시트 서식</comment>
- <comment xml:lang="oc">Modèl de fuèlh de calcul Excel</comment>
- <comment xml:lang="pl">Szablon arkusza Excel</comment>
- <comment xml:lang="pt">modelo de folha de cálculo Excel</comment>
- <comment xml:lang="pt_BR">Modelo de planilha do Excel</comment>
- <comment xml:lang="ru">Шаблон таблицы Excel</comment>
- <comment xml:lang="sk">Šablóna tabuľky aplikácie Excel</comment>
- <comment xml:lang="sr">Екселов шаблон табеле</comment>
- <comment xml:lang="sv">Excel-kalkylarksmall</comment>
- <comment xml:lang="tr">Excel hesap tablosu şablonu</comment>
- <comment xml:lang="uk">шаблон електронної таблиці Excel</comment>
- <comment xml:lang="zh_CN">Excel 电子表格模板</comment>
<comment xml:lang="zh_TW">Excel 試算表範本</comment>
+ <comment xml:lang="zh_CN">Excel 电子表格模板</comment>
+ <comment xml:lang="uk">шаблон електронної таблиці Excel</comment>
+ <comment xml:lang="tr">Excel hesap çizelgesi şablonu</comment>
+ <comment xml:lang="sv">Excel-kalkylarksmall</comment>
+ <comment xml:lang="sr">Екселов шаблон табеле</comment>
+ <comment xml:lang="sq">gjedhe fletëllogaritjesh Excel</comment>
+ <comment xml:lang="sl">Predloga preglednice Excel</comment>
+ <comment xml:lang="si">එක්සෙල් පැතුරුම්පත් අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna tabuľky aplikácie Excel</comment>
+ <comment xml:lang="ru">Шаблон таблицы Excel</comment>
+ <comment xml:lang="pt_BR">Modelo de planilha do Excel</comment>
+ <comment xml:lang="pt">predefinição da folha de cálculo Excel</comment>
+ <comment xml:lang="pl">Szablon arkusza Excel</comment>
+ <comment xml:lang="oc">Modèl de fuèlh de calcul Excel</comment>
+ <comment xml:lang="nl">Excel-rekenbladsjabloon</comment>
+ <comment xml:lang="ko">Excel 스프레드시트 서식</comment>
+ <comment xml:lang="kk">Excel кестесінің үлгісі</comment>
+ <comment xml:lang="ja">Excel スプレッドシートテンプレート</comment>
+ <comment xml:lang="it">Modello foglio di calcolo Excel</comment>
+ <comment xml:lang="is">Excel töflureiknisniðmát</comment>
+ <comment xml:lang="id">Templat lembar kerja Excel</comment>
+ <comment xml:lang="ia">Patrono de folio de calculo Excel</comment>
+ <comment xml:lang="hu">Excel munkafüzetsablon</comment>
+ <comment xml:lang="hr">Predložak Excel proračunske tablice</comment>
+ <comment xml:lang="he">תבנית גיליון נתונים של Excel</comment>
+ <comment xml:lang="gl">Modelo de folla de cálculo de Excel</comment>
+ <comment xml:lang="ga">teimpléad scarbhileoige Excel</comment>
+ <comment xml:lang="fur">model sfuei di calcul Excel</comment>
+ <comment xml:lang="fr">modèle de feuille de calcul Excel</comment>
+ <comment xml:lang="fi">Excel-taulukkomalli</comment>
+ <comment xml:lang="eu">Excel kalkulu-orri txantiloia</comment>
+ <comment xml:lang="es">plantilla de hoja de cálculo de Excel</comment>
+ <comment xml:lang="en_GB">Excel spreadsheet template</comment>
+ <comment xml:lang="el">Πρότυπο λογιστικού φύλλου Excel</comment>
+ <comment xml:lang="de">Excel-Tabellenvorlage</comment>
+ <comment xml:lang="da">Excel-regnearksskabelon</comment>
+ <comment xml:lang="cs">šablona tabulky Excel</comment>
+ <comment xml:lang="ca">plantilla de full de càlcul d'Excel</comment>
+ <comment xml:lang="bg">Шаблон за таблица — Excel</comment>
+ <comment xml:lang="be">шаблон электроннай табліцы Excel</comment>
+ <comment xml:lang="ar">قالب جدول اكسل</comment>
+ <comment xml:lang="af">Excel-sigbladsjabloon</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xltm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.spreadsheetml.template"/>
</mime-type>
<mime-type type="application/vnd.ms-powerpoint">
<comment>PowerPoint presentation</comment>
- <comment xml:lang="ar">عرض تقديمي PowerPoint</comment>
- <comment xml:lang="be@latin">Prezentacyja PowerPoint</comment>
- <comment xml:lang="bg">Презентация — PowerPoint</comment>
- <comment xml:lang="ca">presentació de PowerPoint</comment>
- <comment xml:lang="cs">prezentace PowerPoint</comment>
- <comment xml:lang="da">PowerPoint-præsentation</comment>
- <comment xml:lang="de">PowerPoint-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση PowerPoint</comment>
- <comment xml:lang="en_GB">PowerPoint presentation</comment>
- <comment xml:lang="eo">PowerPoint-prezentaĵo</comment>
- <comment xml:lang="es">presentación de PowerPoint</comment>
- <comment xml:lang="eu">PowerPoint aurkezpena</comment>
- <comment xml:lang="fi">PowerPoint-esitys</comment>
- <comment xml:lang="fo">PowerPoint framløga</comment>
- <comment xml:lang="fr">présentation PowerPoint</comment>
- <comment xml:lang="ga">láithreoireacht PowerPoint</comment>
- <comment xml:lang="gl">presentación de PowerPoint</comment>
- <comment xml:lang="he">מצגת PowerPoint</comment>
- <comment xml:lang="hr">PowerPoint prezentacija</comment>
- <comment xml:lang="hu">PowerPoint prezentáció</comment>
- <comment xml:lang="ia">Presentation PowerPoint</comment>
- <comment xml:lang="id">Presentasi PowerPoint</comment>
- <comment xml:lang="it">Presentazione PowerPoint</comment>
- <comment xml:lang="ja">PowerPoint プレゼンテーション</comment>
- <comment xml:lang="kk">PowerPoint презентациясы</comment>
- <comment xml:lang="ko">PowerPoint 프레젠테이션</comment>
- <comment xml:lang="lt">PowerPoint pateiktis</comment>
- <comment xml:lang="lv">PowerPoint prezentācija</comment>
- <comment xml:lang="nb">PowerPoint-presentasjon</comment>
- <comment xml:lang="nl">PowerPoint-presentatie</comment>
- <comment xml:lang="nn">PowerPoint-presentasjon</comment>
- <comment xml:lang="oc">presentacion PowerPoint</comment>
- <comment xml:lang="pl">Prezentacja PowerPoint</comment>
- <comment xml:lang="pt">apresentação PowerPoint</comment>
- <comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
- <comment xml:lang="ro">Prezentare PowerPoint</comment>
- <comment xml:lang="ru">Презентация PowerPoint</comment>
- <comment xml:lang="sk">Prezentácia PowerPoint</comment>
- <comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
- <comment xml:lang="sq">Prezantim PowerPoint</comment>
- <comment xml:lang="sr">Пауер поинт презентација</comment>
- <comment xml:lang="sv">PowerPoint-presentation</comment>
- <comment xml:lang="tr">PowerPoint sunumu</comment>
- <comment xml:lang="uk">презентація PowerPoint</comment>
- <comment xml:lang="vi">Trình diễn PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint 簡報</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
+ <comment xml:lang="vi">Trình diễn PowerPoint</comment>
+ <comment xml:lang="uk">презентація PowerPoint</comment>
+ <comment xml:lang="tr">PowerPoint sunumu</comment>
+ <comment xml:lang="sv">PowerPoint-presentation</comment>
+ <comment xml:lang="sr">Пауер поинт презентација</comment>
+ <comment xml:lang="sq">paraqitje PowerPoint</comment>
+ <comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
+ <comment xml:lang="si">PowerPoint ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia PowerPoint</comment>
+ <comment xml:lang="ru">Презентация PowerPoint</comment>
+ <comment xml:lang="ro">Prezentare PowerPoint</comment>
+ <comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
+ <comment xml:lang="pt">apresentação PowerPoint</comment>
+ <comment xml:lang="pl">Prezentacja PowerPoint</comment>
+ <comment xml:lang="oc">presentacion PowerPoint</comment>
+ <comment xml:lang="nn">PowerPoint-presentasjon</comment>
+ <comment xml:lang="nl">PowerPoint-presentatie</comment>
+ <comment xml:lang="nb">PowerPoint-presentasjon</comment>
+ <comment xml:lang="lv">PowerPoint prezentācija</comment>
+ <comment xml:lang="lt">PowerPoint pateiktis</comment>
+ <comment xml:lang="ko">PowerPoint 프레젠테이션</comment>
+ <comment xml:lang="kk">PowerPoint презентациясы</comment>
+ <comment xml:lang="ja">PowerPoint プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione PowerPoint</comment>
+ <comment xml:lang="is">PowerPoint kynning</comment>
+ <comment xml:lang="id">Presentasi PowerPoint</comment>
+ <comment xml:lang="ia">Presentation PowerPoint</comment>
+ <comment xml:lang="hu">PowerPoint prezentáció</comment>
+ <comment xml:lang="hr">PowerPoint prezentacija</comment>
+ <comment xml:lang="he">מצגת PowerPoint</comment>
+ <comment xml:lang="gl">presentación de PowerPoint</comment>
+ <comment xml:lang="ga">láithreoireacht PowerPoint</comment>
+ <comment xml:lang="fur">presentazion PowerPoint</comment>
+ <comment xml:lang="fr">présentation PowerPoint</comment>
+ <comment xml:lang="fo">PowerPoint framløga</comment>
+ <comment xml:lang="fi">PowerPoint-esitys</comment>
+ <comment xml:lang="eu">PowerPoint aurkezpena</comment>
+ <comment xml:lang="es">presentación de PowerPoint</comment>
+ <comment xml:lang="eo">PowerPoint-prezentaĵo</comment>
+ <comment xml:lang="en_GB">PowerPoint presentation</comment>
+ <comment xml:lang="el">Παρουσίαση PowerPoint</comment>
+ <comment xml:lang="de">PowerPoint-Präsentation</comment>
+ <comment xml:lang="da">PowerPoint-præsentation</comment>
+ <comment xml:lang="cs">prezentace PowerPoint</comment>
+ <comment xml:lang="ca">presentació de PowerPoint</comment>
+ <comment xml:lang="bg">Презентация — PowerPoint</comment>
+ <comment xml:lang="be@latin">Prezentacyja PowerPoint</comment>
+ <comment xml:lang="be">прэзентацыя PowerPoint</comment>
+ <comment xml:lang="ar">عرض تقديمي بوربوينت</comment>
+ <comment xml:lang="af">PowerPoint-voorlegging</comment>
+ <sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.ppz"/>
<glob pattern="*.ppt"/>
@@ -3323,644 +3800,781 @@
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.addin.macroEnabled.12">
<comment>PowerPoint add-in</comment>
- <comment xml:lang="bg">Приставка — PowerPoint</comment>
- <comment xml:lang="ca">complement de PowerPoint</comment>
- <comment xml:lang="cs">doplněk PowerPoint</comment>
- <comment xml:lang="da">PowerPoint-tilføjelse</comment>
- <comment xml:lang="de">PowerPoint Add-in</comment>
- <comment xml:lang="el">Πρόσθετο PowerPoint</comment>
- <comment xml:lang="en_GB">PowerPoint add-in</comment>
- <comment xml:lang="es">complemento de PowerPoint</comment>
- <comment xml:lang="eu">PowerPoint gehigarria</comment>
- <comment xml:lang="fi">PowerPoint-lisäosa</comment>
- <comment xml:lang="fr">complément PowerPoint</comment>
- <comment xml:lang="ga">breiseán PowerPoint</comment>
- <comment xml:lang="gl">complemento de PowerPoint</comment>
- <comment xml:lang="he">תוסף של PowerPoint</comment>
- <comment xml:lang="hr">PowerPoint dodatak</comment>
- <comment xml:lang="hu">PowerPoint bővítmény</comment>
- <comment xml:lang="ia">Add-in PowerPoint</comment>
- <comment xml:lang="id">Add-in PowerPoint</comment>
- <comment xml:lang="it">Add-in PowerPoint</comment>
- <comment xml:lang="ja">PowerPoint アドイン</comment>
- <comment xml:lang="ka">PowerPoint-ის დამატება</comment>
- <comment xml:lang="kk">PowerPoint қосымшасы</comment>
- <comment xml:lang="ko">PowerPoint 추가 기능</comment>
- <comment xml:lang="lv">PowerPoint pievienojumprogramma</comment>
- <comment xml:lang="nl">PowerPoint add-in</comment>
- <comment xml:lang="oc">complement PowerPoint</comment>
- <comment xml:lang="pl">Dodatek PowerPoint</comment>
- <comment xml:lang="pt">extensão PowerPoint</comment>
- <comment xml:lang="pt_BR">Suplemento do PowerPoint</comment>
- <comment xml:lang="ru">Дополнение PowerPoint</comment>
- <comment xml:lang="sk">Doplnok aplikácie PowerPoint </comment>
- <comment xml:lang="sl">Vstavek PowerPoint</comment>
- <comment xml:lang="sr">Пауер поинт додатак</comment>
- <comment xml:lang="sv">PowerPoint-tillägg</comment>
- <comment xml:lang="tr">PowerPoint eklentisi</comment>
- <comment xml:lang="uk">додаток PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 外接程序</comment>
<comment xml:lang="zh_TW">PowerPoint 增益集</comment>
+ <comment xml:lang="zh_CN">PowerPoint 外接程序</comment>
+ <comment xml:lang="uk">додаток PowerPoint</comment>
+ <comment xml:lang="tr">PowerPoint eklentisi</comment>
+ <comment xml:lang="sv">PowerPoint-tillägg</comment>
+ <comment xml:lang="sr">Пауер поинт додатак</comment>
+ <comment xml:lang="sq">shtojcë PowerPoint</comment>
+ <comment xml:lang="sl">Vstavek PowerPoint</comment>
+ <comment xml:lang="si">PowerPoint ඇඩෝනය</comment>
+ <comment xml:lang="sk">Doplnok aplikácie PowerPoint </comment>
+ <comment xml:lang="ru">Дополнение PowerPoint</comment>
+ <comment xml:lang="pt_BR">Suplemento do PowerPoint</comment>
+ <comment xml:lang="pt">extensão PowerPoint</comment>
+ <comment xml:lang="pl">Dodatek PowerPoint</comment>
+ <comment xml:lang="oc">complement PowerPoint</comment>
+ <comment xml:lang="nl">PowerPoint-add-in</comment>
+ <comment xml:lang="lv">PowerPoint pievienojumprogramma</comment>
+ <comment xml:lang="ko">PowerPoint 추가 기능</comment>
+ <comment xml:lang="kk">PowerPoint қосымшасы</comment>
+ <comment xml:lang="ka">PowerPoint-ის დამატება</comment>
+ <comment xml:lang="ja">PowerPoint アドイン</comment>
+ <comment xml:lang="it">Add-in PowerPoint</comment>
+ <comment xml:lang="is">PowerPoint viðbót</comment>
+ <comment xml:lang="id">Add-in PowerPoint</comment>
+ <comment xml:lang="ia">Add-in PowerPoint</comment>
+ <comment xml:lang="hu">PowerPoint bővítmény</comment>
+ <comment xml:lang="hr">PowerPoint dodatak</comment>
+ <comment xml:lang="he">תוסף של PowerPoint</comment>
+ <comment xml:lang="gl">complemento de PowerPoint</comment>
+ <comment xml:lang="ga">breiseán PowerPoint</comment>
+ <comment xml:lang="fur">zonte PowerPoint</comment>
+ <comment xml:lang="fr">complément PowerPoint</comment>
+ <comment xml:lang="fi">PowerPoint-lisäosa</comment>
+ <comment xml:lang="eu">PowerPoint gehigarria</comment>
+ <comment xml:lang="es">complemento de PowerPoint</comment>
+ <comment xml:lang="en_GB">PowerPoint add-in</comment>
+ <comment xml:lang="el">Πρόσθετο PowerPoint</comment>
+ <comment xml:lang="de">PowerPoint-Add-in</comment>
+ <comment xml:lang="da">PowerPoint-tilføjelse</comment>
+ <comment xml:lang="cs">doplněk PowerPoint</comment>
+ <comment xml:lang="ca">complement de PowerPoint</comment>
+ <comment xml:lang="bg">Приставка — PowerPoint</comment>
+ <comment xml:lang="be">надбудова PowerPoint</comment>
+ <comment xml:lang="ar">إضافة بوربوينت</comment>
+ <comment xml:lang="af">PowerPoint-byvoeging</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.ppam"/>
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.presentation.macroEnabled.12">
<comment>PowerPoint presentation</comment>
- <comment xml:lang="ar">عرض تقديمي PowerPoint</comment>
- <comment xml:lang="be@latin">Prezentacyja PowerPoint</comment>
- <comment xml:lang="bg">Презентация — PowerPoint</comment>
- <comment xml:lang="ca">presentació de PowerPoint</comment>
- <comment xml:lang="cs">prezentace PowerPoint</comment>
- <comment xml:lang="da">PowerPoint-præsentation</comment>
- <comment xml:lang="de">PowerPoint-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση PowerPoint</comment>
- <comment xml:lang="en_GB">PowerPoint presentation</comment>
- <comment xml:lang="eo">PowerPoint-prezentaĵo</comment>
- <comment xml:lang="es">presentación de PowerPoint</comment>
- <comment xml:lang="eu">PowerPoint aurkezpena</comment>
- <comment xml:lang="fi">PowerPoint-esitys</comment>
- <comment xml:lang="fo">PowerPoint framløga</comment>
- <comment xml:lang="fr">présentation PowerPoint</comment>
- <comment xml:lang="ga">láithreoireacht PowerPoint</comment>
- <comment xml:lang="gl">presentación de PowerPoint</comment>
- <comment xml:lang="he">מצגת PowerPoint</comment>
- <comment xml:lang="hr">PowerPoint prezentacija</comment>
- <comment xml:lang="hu">PowerPoint prezentáció</comment>
- <comment xml:lang="ia">Presentation PowerPoint</comment>
- <comment xml:lang="id">Presentasi PowerPoint</comment>
- <comment xml:lang="it">Presentazione PowerPoint</comment>
- <comment xml:lang="ja">PowerPoint プレゼンテーション</comment>
- <comment xml:lang="kk">PowerPoint презентациясы</comment>
- <comment xml:lang="ko">PowerPoint 프레젠테이션</comment>
- <comment xml:lang="lt">PowerPoint pateiktis</comment>
- <comment xml:lang="lv">PowerPoint prezentācija</comment>
- <comment xml:lang="nb">PowerPoint-presentasjon</comment>
- <comment xml:lang="nl">PowerPoint-presentatie</comment>
- <comment xml:lang="nn">PowerPoint-presentasjon</comment>
- <comment xml:lang="oc">presentacion PowerPoint</comment>
- <comment xml:lang="pl">Prezentacja PowerPoint</comment>
- <comment xml:lang="pt">apresentação PowerPoint</comment>
- <comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
- <comment xml:lang="ro">Prezentare PowerPoint</comment>
- <comment xml:lang="ru">Презентация PowerPoint</comment>
- <comment xml:lang="sk">Prezentácia PowerPoint</comment>
- <comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
- <comment xml:lang="sq">Prezantim PowerPoint</comment>
- <comment xml:lang="sr">Пауер поинт презентација</comment>
- <comment xml:lang="sv">PowerPoint-presentation</comment>
- <comment xml:lang="tr">PowerPoint sunumu</comment>
- <comment xml:lang="uk">презентація PowerPoint</comment>
- <comment xml:lang="vi">Trình diễn PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint 簡報</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
+ <comment xml:lang="vi">Trình diễn PowerPoint</comment>
+ <comment xml:lang="uk">презентація PowerPoint</comment>
+ <comment xml:lang="tr">PowerPoint sunumu</comment>
+ <comment xml:lang="sv">PowerPoint-presentation</comment>
+ <comment xml:lang="sr">Пауер поинт презентација</comment>
+ <comment xml:lang="sq">paraqitje PowerPoint</comment>
+ <comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
+ <comment xml:lang="si">PowerPoint ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia PowerPoint</comment>
+ <comment xml:lang="ru">Презентация PowerPoint</comment>
+ <comment xml:lang="ro">Prezentare PowerPoint</comment>
+ <comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
+ <comment xml:lang="pt">apresentação PowerPoint</comment>
+ <comment xml:lang="pl">Prezentacja PowerPoint</comment>
+ <comment xml:lang="oc">presentacion PowerPoint</comment>
+ <comment xml:lang="nn">PowerPoint-presentasjon</comment>
+ <comment xml:lang="nl">PowerPoint-presentatie</comment>
+ <comment xml:lang="nb">PowerPoint-presentasjon</comment>
+ <comment xml:lang="lv">PowerPoint prezentācija</comment>
+ <comment xml:lang="lt">PowerPoint pateiktis</comment>
+ <comment xml:lang="ko">PowerPoint 프레젠테이션</comment>
+ <comment xml:lang="kk">PowerPoint презентациясы</comment>
+ <comment xml:lang="ja">PowerPoint プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione PowerPoint</comment>
+ <comment xml:lang="is">PowerPoint kynning</comment>
+ <comment xml:lang="id">Presentasi PowerPoint</comment>
+ <comment xml:lang="ia">Presentation PowerPoint</comment>
+ <comment xml:lang="hu">PowerPoint prezentáció</comment>
+ <comment xml:lang="hr">PowerPoint prezentacija</comment>
+ <comment xml:lang="he">מצגת PowerPoint</comment>
+ <comment xml:lang="gl">presentación de PowerPoint</comment>
+ <comment xml:lang="ga">láithreoireacht PowerPoint</comment>
+ <comment xml:lang="fur">presentazion PowerPoint</comment>
+ <comment xml:lang="fr">présentation PowerPoint</comment>
+ <comment xml:lang="fo">PowerPoint framløga</comment>
+ <comment xml:lang="fi">PowerPoint-esitys</comment>
+ <comment xml:lang="eu">PowerPoint aurkezpena</comment>
+ <comment xml:lang="es">presentación de PowerPoint</comment>
+ <comment xml:lang="eo">PowerPoint-prezentaĵo</comment>
+ <comment xml:lang="en_GB">PowerPoint presentation</comment>
+ <comment xml:lang="el">Παρουσίαση PowerPoint</comment>
+ <comment xml:lang="de">PowerPoint-Präsentation</comment>
+ <comment xml:lang="da">PowerPoint-præsentation</comment>
+ <comment xml:lang="cs">prezentace PowerPoint</comment>
+ <comment xml:lang="ca">presentació de PowerPoint</comment>
+ <comment xml:lang="bg">Презентация — PowerPoint</comment>
+ <comment xml:lang="be@latin">Prezentacyja PowerPoint</comment>
+ <comment xml:lang="be">прэзентацыя PowerPoint</comment>
+ <comment xml:lang="ar">عرض تقديمي بوربوينت</comment>
+ <comment xml:lang="af">PowerPoint-voorlegging</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.pptm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.presentationml.presentation"/>
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.slide.macroEnabled.12">
<comment>PowerPoint slide</comment>
- <comment xml:lang="ast">Diapositiva de PowerPoint</comment>
- <comment xml:lang="ca">dispositiva de PowerPoint</comment>
- <comment xml:lang="cs">promítání PowerPoint</comment>
- <comment xml:lang="da">PowerPoint-dias</comment>
- <comment xml:lang="de">PowerPoint-Folie</comment>
- <comment xml:lang="el">Διαφάνεια PowerPoint</comment>
- <comment xml:lang="en_GB">PowerPoint slide</comment>
- <comment xml:lang="es">diapositiva de PowerPoint</comment>
- <comment xml:lang="eu">PowerPoint diapositiba</comment>
- <comment xml:lang="fi">PowerPoint-dia</comment>
- <comment xml:lang="fr">diapositive PowerPoint</comment>
- <comment xml:lang="ga">sleamhnán PowerPoint</comment>
- <comment xml:lang="he">שקופית של PowerPoint</comment>
- <comment xml:lang="hr">PowerPoint prezentacija</comment>
- <comment xml:lang="hu">PowerPoint dia</comment>
- <comment xml:lang="ia">Diapositiva PowerPoint</comment>
- <comment xml:lang="id">Salindia PowerPoint</comment>
- <comment xml:lang="it">Diapositiva PowerPoint</comment>
- <comment xml:lang="kk">PowerPoint слайды</comment>
- <comment xml:lang="ko">파워포인트 슬라이드</comment>
- <comment xml:lang="oc">Diapositiva PowerPoint</comment>
- <comment xml:lang="pl">Slajd PowerPoint</comment>
- <comment xml:lang="pt">diapositivo PowerPoint</comment>
- <comment xml:lang="pt_BR">Slide do PowerPoint</comment>
- <comment xml:lang="ru">Слайд PowerPoint</comment>
- <comment xml:lang="sk">Snímka aplikácie PowerPoint</comment>
- <comment xml:lang="sr">Пауер поинт слајд</comment>
- <comment xml:lang="sv">PowerPoint-bildspel</comment>
- <comment xml:lang="tr">PowerPoint sunusu</comment>
- <comment xml:lang="uk">слайд PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 幻灯片</comment>
<comment xml:lang="zh_TW">PowerPoint 投影片</comment>
+ <comment xml:lang="zh_CN">PowerPoint 幻灯片</comment>
+ <comment xml:lang="uk">слайд PowerPoint</comment>
+ <comment xml:lang="tr">PowerPoint sunusu</comment>
+ <comment xml:lang="sv">PowerPoint-bildspel</comment>
+ <comment xml:lang="sr">Пауер поинт слајд</comment>
+ <comment xml:lang="sq">diapozitiv PowerPoint</comment>
+ <comment xml:lang="sl">Prosojnica PowerPoint</comment>
+ <comment xml:lang="si">PowerPoint ස්ලයිඩය</comment>
+ <comment xml:lang="sk">Snímka aplikácie PowerPoint</comment>
+ <comment xml:lang="ru">Слайд PowerPoint</comment>
+ <comment xml:lang="pt_BR">Slide do PowerPoint</comment>
+ <comment xml:lang="pt">diapositivo PowerPoint</comment>
+ <comment xml:lang="pl">Slajd PowerPoint</comment>
+ <comment xml:lang="oc">Diapositiva PowerPoint</comment>
+ <comment xml:lang="nl">PowerPoint-dia</comment>
+ <comment xml:lang="ko">PowerPoint 슬라이드</comment>
+ <comment xml:lang="kk">PowerPoint слайды</comment>
+ <comment xml:lang="ja">PowerPoint スライド</comment>
+ <comment xml:lang="it">Diapositiva PowerPoint</comment>
+ <comment xml:lang="is">PowerPoint skyggna</comment>
+ <comment xml:lang="id">Salindia PowerPoint</comment>
+ <comment xml:lang="ia">Diapositiva PowerPoint</comment>
+ <comment xml:lang="hu">PowerPoint dia</comment>
+ <comment xml:lang="hr">PowerPoint prezentacija</comment>
+ <comment xml:lang="he">שקופית של PowerPoint</comment>
+ <comment xml:lang="gl">Diapositiva de PowerPoint</comment>
+ <comment xml:lang="ga">sleamhnán PowerPoint</comment>
+ <comment xml:lang="fur">diapositive PowerPoint</comment>
+ <comment xml:lang="fr">diapositive PowerPoint</comment>
+ <comment xml:lang="fi">PowerPoint-dia</comment>
+ <comment xml:lang="eu">PowerPoint diapositiba</comment>
+ <comment xml:lang="es">diapositiva de PowerPoint</comment>
+ <comment xml:lang="en_GB">PowerPoint slide</comment>
+ <comment xml:lang="el">Διαφάνεια PowerPoint</comment>
+ <comment xml:lang="de">PowerPoint-Folie</comment>
+ <comment xml:lang="da">PowerPoint-dias</comment>
+ <comment xml:lang="cs">promítání PowerPoint</comment>
+ <comment xml:lang="ca">dispositiva de PowerPoint</comment>
+ <comment xml:lang="bg">Кадър — PowerPoint</comment>
+ <comment xml:lang="be">слайд PowerPoint</comment>
+ <comment xml:lang="ast">Diapositiva de PowerPoint</comment>
+ <comment xml:lang="ar">شريحة بوربوينت</comment>
+ <comment xml:lang="af">PowerPoint-skyfie</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.sldm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.presentationml.slide"/>
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.slideshow.macroEnabled.12">
<comment>PowerPoint presentation</comment>
- <comment xml:lang="ar">عرض تقديمي PowerPoint</comment>
- <comment xml:lang="be@latin">Prezentacyja PowerPoint</comment>
- <comment xml:lang="bg">Презентация — PowerPoint</comment>
- <comment xml:lang="ca">presentació de PowerPoint</comment>
- <comment xml:lang="cs">prezentace PowerPoint</comment>
- <comment xml:lang="da">PowerPoint-præsentation</comment>
- <comment xml:lang="de">PowerPoint-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση PowerPoint</comment>
- <comment xml:lang="en_GB">PowerPoint presentation</comment>
- <comment xml:lang="eo">PowerPoint-prezentaĵo</comment>
- <comment xml:lang="es">presentación de PowerPoint</comment>
- <comment xml:lang="eu">PowerPoint aurkezpena</comment>
- <comment xml:lang="fi">PowerPoint-esitys</comment>
- <comment xml:lang="fo">PowerPoint framløga</comment>
- <comment xml:lang="fr">présentation PowerPoint</comment>
- <comment xml:lang="ga">láithreoireacht PowerPoint</comment>
- <comment xml:lang="gl">presentación de PowerPoint</comment>
- <comment xml:lang="he">מצגת PowerPoint</comment>
- <comment xml:lang="hr">PowerPoint prezentacija</comment>
- <comment xml:lang="hu">PowerPoint prezentáció</comment>
- <comment xml:lang="ia">Presentation PowerPoint</comment>
- <comment xml:lang="id">Presentasi PowerPoint</comment>
- <comment xml:lang="it">Presentazione PowerPoint</comment>
- <comment xml:lang="ja">PowerPoint プレゼンテーション</comment>
- <comment xml:lang="kk">PowerPoint презентациясы</comment>
- <comment xml:lang="ko">PowerPoint 프레젠테이션</comment>
- <comment xml:lang="lt">PowerPoint pateiktis</comment>
- <comment xml:lang="lv">PowerPoint prezentācija</comment>
- <comment xml:lang="nb">PowerPoint-presentasjon</comment>
- <comment xml:lang="nl">PowerPoint-presentatie</comment>
- <comment xml:lang="nn">PowerPoint-presentasjon</comment>
- <comment xml:lang="oc">presentacion PowerPoint</comment>
- <comment xml:lang="pl">Prezentacja PowerPoint</comment>
- <comment xml:lang="pt">apresentação PowerPoint</comment>
- <comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
- <comment xml:lang="ro">Prezentare PowerPoint</comment>
- <comment xml:lang="ru">Презентация PowerPoint</comment>
- <comment xml:lang="sk">Prezentácia PowerPoint</comment>
- <comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
- <comment xml:lang="sq">Prezantim PowerPoint</comment>
- <comment xml:lang="sr">Пауер поинт презентација</comment>
- <comment xml:lang="sv">PowerPoint-presentation</comment>
- <comment xml:lang="tr">PowerPoint sunumu</comment>
- <comment xml:lang="uk">презентація PowerPoint</comment>
- <comment xml:lang="vi">Trình diễn PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint 簡報</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
+ <comment xml:lang="vi">Trình diễn PowerPoint</comment>
+ <comment xml:lang="uk">презентація PowerPoint</comment>
+ <comment xml:lang="tr">PowerPoint sunumu</comment>
+ <comment xml:lang="sv">PowerPoint-presentation</comment>
+ <comment xml:lang="sr">Пауер поинт презентација</comment>
+ <comment xml:lang="sq">paraqitje PowerPoint</comment>
+ <comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
+ <comment xml:lang="si">PowerPoint ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia PowerPoint</comment>
+ <comment xml:lang="ru">Презентация PowerPoint</comment>
+ <comment xml:lang="ro">Prezentare PowerPoint</comment>
+ <comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
+ <comment xml:lang="pt">apresentação PowerPoint</comment>
+ <comment xml:lang="pl">Prezentacja PowerPoint</comment>
+ <comment xml:lang="oc">presentacion PowerPoint</comment>
+ <comment xml:lang="nn">PowerPoint-presentasjon</comment>
+ <comment xml:lang="nl">PowerPoint-presentatie</comment>
+ <comment xml:lang="nb">PowerPoint-presentasjon</comment>
+ <comment xml:lang="lv">PowerPoint prezentācija</comment>
+ <comment xml:lang="lt">PowerPoint pateiktis</comment>
+ <comment xml:lang="ko">PowerPoint 프레젠테이션</comment>
+ <comment xml:lang="kk">PowerPoint презентациясы</comment>
+ <comment xml:lang="ja">PowerPoint プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione PowerPoint</comment>
+ <comment xml:lang="is">PowerPoint kynning</comment>
+ <comment xml:lang="id">Presentasi PowerPoint</comment>
+ <comment xml:lang="ia">Presentation PowerPoint</comment>
+ <comment xml:lang="hu">PowerPoint prezentáció</comment>
+ <comment xml:lang="hr">PowerPoint prezentacija</comment>
+ <comment xml:lang="he">מצגת PowerPoint</comment>
+ <comment xml:lang="gl">presentación de PowerPoint</comment>
+ <comment xml:lang="ga">láithreoireacht PowerPoint</comment>
+ <comment xml:lang="fur">presentazion PowerPoint</comment>
+ <comment xml:lang="fr">présentation PowerPoint</comment>
+ <comment xml:lang="fo">PowerPoint framløga</comment>
+ <comment xml:lang="fi">PowerPoint-esitys</comment>
+ <comment xml:lang="eu">PowerPoint aurkezpena</comment>
+ <comment xml:lang="es">presentación de PowerPoint</comment>
+ <comment xml:lang="eo">PowerPoint-prezentaĵo</comment>
+ <comment xml:lang="en_GB">PowerPoint presentation</comment>
+ <comment xml:lang="el">Παρουσίαση PowerPoint</comment>
+ <comment xml:lang="de">PowerPoint-Präsentation</comment>
+ <comment xml:lang="da">PowerPoint-præsentation</comment>
+ <comment xml:lang="cs">prezentace PowerPoint</comment>
+ <comment xml:lang="ca">presentació de PowerPoint</comment>
+ <comment xml:lang="bg">Презентация — PowerPoint</comment>
+ <comment xml:lang="be@latin">Prezentacyja PowerPoint</comment>
+ <comment xml:lang="be">прэзентацыя PowerPoint</comment>
+ <comment xml:lang="ar">عرض تقديمي بوربوينت</comment>
+ <comment xml:lang="af">PowerPoint-voorlegging</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.ppsm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.presentationml.slideshow"/>
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.template.macroEnabled.12">
<comment>PowerPoint presentation template</comment>
- <comment xml:lang="ast">Plantía de presentaciones de PowerPoint</comment>
- <comment xml:lang="ca">plantilla de presentació de PowerPoint</comment>
- <comment xml:lang="cs">šablona prezentace PowerPoint</comment>
- <comment xml:lang="da">PowerPoint-præsentationsskabelon</comment>
- <comment xml:lang="de">PowerPoint-Präsentationsvorlage</comment>
- <comment xml:lang="el">Πρότυπο παρουσίασης PowerPoint</comment>
- <comment xml:lang="en_GB">PowerPoint presentation template</comment>
- <comment xml:lang="es">plantilla de presentación de PowerPoint</comment>
- <comment xml:lang="eu">PowerPoint aurkezpen txantiloia</comment>
- <comment xml:lang="fi">PowerPoint-esitysmalli</comment>
- <comment xml:lang="fr">modèle de présentation PowerPoint</comment>
- <comment xml:lang="ga">teimpléad láithreoireachta PowerPoint</comment>
- <comment xml:lang="he">תבנית מצגת PowerPoint</comment>
- <comment xml:lang="hr">Predložak PowerPoint prezentacije</comment>
- <comment xml:lang="hu">PowerPoint bemutatósablon</comment>
- <comment xml:lang="ia">Patrono de presentation PowerPoint</comment>
- <comment xml:lang="id">Templat presentasi PowerPoint</comment>
- <comment xml:lang="it">Modello presentazione PowerPoint</comment>
- <comment xml:lang="kk">PowerPoint презентация үлгісі</comment>
- <comment xml:lang="ko">PowerPoint 프리젠테이션 서식</comment>
- <comment xml:lang="oc">Modèl de presentacion PowerPoint</comment>
- <comment xml:lang="pl">Szablon prezentacji PowerPoint</comment>
- <comment xml:lang="pt">modelo de apresentação PowerPoint</comment>
- <comment xml:lang="pt_BR">Modelo de apresentação do PowerPoint</comment>
- <comment xml:lang="ru">Шаблон презентации PowerPoint</comment>
- <comment xml:lang="sk">Šablóna prezentácie aplikácie PowerPoint</comment>
- <comment xml:lang="sr">Шаблон презентације Пауер поинта</comment>
- <comment xml:lang="sv">PowerPoint-presentationsmall</comment>
- <comment xml:lang="tr">PowerPoint sunum şablonu</comment>
- <comment xml:lang="uk">шаблон презентації PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 演示文稿模板</comment>
<comment xml:lang="zh_TW">PowerPoint 簡報範本</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿模板</comment>
+ <comment xml:lang="uk">шаблон презентації PowerPoint</comment>
+ <comment xml:lang="tr">PowerPoint sunum şablonu</comment>
+ <comment xml:lang="sv">PowerPoint-presentationsmall</comment>
+ <comment xml:lang="sr">Шаблон презентације Пауер поинта</comment>
+ <comment xml:lang="sq">gjedhe paraqitjeje PowerPoint</comment>
+ <comment xml:lang="sl">Predloga predstavitve PowerPoint</comment>
+ <comment xml:lang="si">PowerPoint ඉදිරිපත් කිරීමේ අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna prezentácie aplikácie PowerPoint</comment>
+ <comment xml:lang="ru">Шаблон презентации PowerPoint</comment>
+ <comment xml:lang="pt_BR">Modelo de apresentação do PowerPoint</comment>
+ <comment xml:lang="pt">predefinição de apresentação PowerPoint</comment>
+ <comment xml:lang="pl">Szablon prezentacji PowerPoint</comment>
+ <comment xml:lang="oc">Modèl de presentacion PowerPoint</comment>
+ <comment xml:lang="nl">PowerPoint-presentatiesjabloon</comment>
+ <comment xml:lang="ko">PowerPoint 프레젠테이션 서식</comment>
+ <comment xml:lang="kk">PowerPoint презентация үлгісі</comment>
+ <comment xml:lang="ja">PowerPoint プレゼンテーションテンプレート</comment>
+ <comment xml:lang="it">Modello presentazione PowerPoint</comment>
+ <comment xml:lang="is">PowerPoint sniðmát fyrir glærukynningu</comment>
+ <comment xml:lang="id">Templat presentasi PowerPoint</comment>
+ <comment xml:lang="ia">Patrono de presentation PowerPoint</comment>
+ <comment xml:lang="hu">PowerPoint bemutatósablon</comment>
+ <comment xml:lang="hr">Predložak PowerPoint prezentacije</comment>
+ <comment xml:lang="he">תבנית מצגת PowerPoint</comment>
+ <comment xml:lang="gl">Modelo de presentación de PowerPoint</comment>
+ <comment xml:lang="ga">teimpléad láithreoireachta PowerPoint</comment>
+ <comment xml:lang="fur">model di presentazion PowerPoint</comment>
+ <comment xml:lang="fr">modèle de présentation PowerPoint</comment>
+ <comment xml:lang="fi">PowerPoint-esitysmalli</comment>
+ <comment xml:lang="eu">PowerPoint aurkezpen txantiloia</comment>
+ <comment xml:lang="es">plantilla de presentación de PowerPoint</comment>
+ <comment xml:lang="en_GB">PowerPoint presentation template</comment>
+ <comment xml:lang="el">Πρότυπο παρουσίασης PowerPoint</comment>
+ <comment xml:lang="de">PowerPoint-Präsentationsvorlage</comment>
+ <comment xml:lang="da">PowerPoint-præsentationsskabelon</comment>
+ <comment xml:lang="cs">šablona prezentace PowerPoint</comment>
+ <comment xml:lang="ca">plantilla de presentació de PowerPoint</comment>
+ <comment xml:lang="bg">Шаблон за презентация — PowerPoint</comment>
+ <comment xml:lang="be">шаблон прэзентацыі PowerPoint</comment>
+ <comment xml:lang="ast">Plantía de presentaciones de PowerPoint</comment>
+ <comment xml:lang="ar">قالب عرض بوربوينت</comment>
+ <comment xml:lang="af">PowerPoint-voorleggingsjabloon</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.potm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.presentationml.template"/>
</mime-type>
- <mime-type type="application/vnd.ms-visio.drawing.main+xml">
- <comment>Office Open XML Visio Drawing</comment>
- <comment xml:lang="ca">dibuix en Office Open XML de Visio</comment>
- <comment xml:lang="cs">kresba Office Open XML Visio</comment>
- <comment xml:lang="da">Office Open XML Visio-tegning</comment>
- <comment xml:lang="de">Office-Open-XML-Visio-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Office Open XML Visio</comment>
- <comment xml:lang="en_GB">Office Open XML Visio Drawing</comment>
- <comment xml:lang="es">dibujo en OOXML de Visio</comment>
- <comment xml:lang="eu">Office Open XML Visio marrazkia</comment>
- <comment xml:lang="fi">Office Open XML Visio -piirros</comment>
- <comment xml:lang="fr">dessin Visio Office Open XML</comment>
- <comment xml:lang="ga">Líníocht Office Open XML Visio</comment>
- <comment xml:lang="he">ציור Visio ב־Open XML מבית Office</comment>
- <comment xml:lang="hr">Office Open XML Visio crtež</comment>
- <comment xml:lang="hu">Office Open XML Visio rajz</comment>
- <comment xml:lang="ia">Designo Office Open XML Visio</comment>
- <comment xml:lang="id">Gambar Visio Office Open XML</comment>
- <comment xml:lang="it">Disegno Visio Office Open XML</comment>
- <comment xml:lang="kk">Office Open XML Visio суреті</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 드로잉</comment>
- <comment xml:lang="pl">Rysunek Office Open XML Visio</comment>
- <comment xml:lang="pt">desenho Office Open XML Visio</comment>
- <comment xml:lang="pt_BR">Desenho do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Рисунок Visio формата Office Open XML</comment>
- <comment xml:lang="sk">Kresba aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">Офисов отворени ИксМЛ Визио цртеж</comment>
- <comment xml:lang="sv">Office Open XML Visio-teckning</comment>
- <comment xml:lang="tr">Office Open XML Visio Çizimi</comment>
- <comment xml:lang="uk">схема VIisio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">Office Open XML Visio 绘图</comment>
+ <mime-type type="application/vnd.ms-visio.drawing.main+xml">
+ <comment>Office Open XML Visio drawing</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 繪圖</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 绘图</comment>
+ <comment xml:lang="uk">малюнок Visio Office Open у XML</comment>
+ <comment xml:lang="tr">Office Open XML Visio çizimi</comment>
+ <comment xml:lang="sv">Office Open XML Visio-ritning</comment>
+ <comment xml:lang="sq">vizatim Office Open XML Visio</comment>
+ <comment xml:lang="sl">Risba Office Open XML Visio</comment>
+ <comment xml:lang="si">කාර්යාල විවෘත XML Visio ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba aplikácie Office Open XML Visio</comment>
+ <comment xml:lang="ru">Рисунок Visio формата Office Open XML</comment>
+ <comment xml:lang="pt_BR">Desenho do Office Open XML Visio</comment>
+ <comment xml:lang="pt">desenho Visio do Open Office XML</comment>
+ <comment xml:lang="pl">Rysunek Office Open XML Visio</comment>
+ <comment xml:lang="nl">Office Open XML Visio-tekening</comment>
+ <comment xml:lang="ko">오피스 오픈 XML Visio 드로잉</comment>
+ <comment xml:lang="kk">Office Open XML Visio суреті</comment>
+ <comment xml:lang="ja">Office Open XML Visio ドロー</comment>
+ <comment xml:lang="it">Disegno Visio Office Open XML</comment>
+ <comment xml:lang="is">Office Open XML Visio teikning</comment>
+ <comment xml:lang="id">Gambar Office Open XML Visio</comment>
+ <comment xml:lang="hu">Office Open XML Visio rajz</comment>
+ <comment xml:lang="hr">Office Open XML Visio crtež</comment>
+ <comment xml:lang="he">ציור Office Open XML Visio</comment>
+ <comment xml:lang="gl">Debuxo de Office Open XML Visio</comment>
+ <comment xml:lang="fr">dessin Visio Office Open XML</comment>
+ <comment xml:lang="fi">Office Open XML Visio -piirros</comment>
+ <comment xml:lang="eu">Office Open XML Visio marrazkia</comment>
+ <comment xml:lang="es">dibujo Office Open XML de Visio</comment>
+ <comment xml:lang="en_GB">Office Open XML Visio drawing</comment>
+ <comment xml:lang="de">Office-Open-XML-Visio-Zeichnung</comment>
+ <comment xml:lang="da">Office Open XML Visio-tegning</comment>
+ <comment xml:lang="ca">dibuix en Office Open XML de Visio</comment>
+ <comment xml:lang="bg">Чертеж — Office Open XML Visio</comment>
+ <comment xml:lang="be">рысунак Office Open XML Visio</comment>
+ <comment xml:lang="ar">رسم فيزيو Open XML</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vsdx"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/vnd.ms-visio.template.main+xml">
- <comment>Office Open XML Visio Template</comment>
- <comment xml:lang="ca">plantilla en Office Open XML de Visio</comment>
- <comment xml:lang="cs">šablona Office Open XML Visio</comment>
- <comment xml:lang="da">Office Open XML Visio-skabelon</comment>
- <comment xml:lang="de">Office-Open-XML-Visio-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο Office Open XML Visio</comment>
- <comment xml:lang="en_GB">Office Open XML Visio Template</comment>
- <comment xml:lang="es">plantilla en OOXML de Visio</comment>
- <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
- <comment xml:lang="fi">Office Open XML Visio -malli</comment>
- <comment xml:lang="fr">modèle Visio Office Open XML</comment>
- <comment xml:lang="ga">Teimpléad Office Open XML Visio</comment>
- <comment xml:lang="he">תבנית Visio ב־Open XML מבית Office</comment>
- <comment xml:lang="hr">Predložak Office Open XML Visio</comment>
- <comment xml:lang="hu">Office Open XML Visio sablon</comment>
- <comment xml:lang="ia">Patrono Office Open XML Visio</comment>
- <comment xml:lang="id">Templat Visio Office Open XML</comment>
- <comment xml:lang="it">Modello Visio Office Open XML</comment>
- <comment xml:lang="kk">Office Open XML Visio үлгісі</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 서식</comment>
- <comment xml:lang="pl">Szablon Office Open XML Visio</comment>
- <comment xml:lang="pt">modelo Office Open XML Visio</comment>
- <comment xml:lang="pt_BR">Modelo do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Шаблон Visio формата Office Open XML</comment>
- <comment xml:lang="sk">Šablóna aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">Офисов отворени ИксМЛ Визио шаблон</comment>
- <comment xml:lang="sv">Office Open XML Visio-mall</comment>
- <comment xml:lang="tr">Office Open XML Visio Şablonu</comment>
- <comment xml:lang="uk">шаблон Visio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">Office Open XML Visio 模板</comment>
+ <comment>Office Open XML Visio template</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 範本</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 模板</comment>
+ <comment xml:lang="uk">шаблон Visio Office Open у XML</comment>
+ <comment xml:lang="tr">Office Open XML Visio şablonu</comment>
+ <comment xml:lang="sv">Office Open XML Visio-mall</comment>
+ <comment xml:lang="sq">gjedhe Office Open XML Visio</comment>
+ <comment xml:lang="sl">Predloga Office Open XML Visio</comment>
+ <comment xml:lang="si">Office Open XML Visio අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna aplikácie Office Open XML Visio</comment>
+ <comment xml:lang="ru">Шаблон Visio формата Office Open XML</comment>
+ <comment xml:lang="pt_BR">Modelo Office Open XML Visio</comment>
+ <comment xml:lang="pt">predefinição Visio do Open Office XML</comment>
+ <comment xml:lang="pl">Szablon Office Open XML Visio</comment>
+ <comment xml:lang="nl">Office Open XML Visio-sjabloon</comment>
+ <comment xml:lang="ko">오피스 오픈 XML Visio 양식</comment>
+ <comment xml:lang="kk">Office Open XML Visio үлгісі</comment>
+ <comment xml:lang="ja">Office Open XML Visio テンプレート</comment>
+ <comment xml:lang="it">Modello Visio Office Open XML</comment>
+ <comment xml:lang="is">Office Open XML Visio sniðmát</comment>
+ <comment xml:lang="id">Templat Office Open XML Visio</comment>
+ <comment xml:lang="hu">Office Open XML Visio sablon</comment>
+ <comment xml:lang="hr">Office Open XML Visio predložak</comment>
+ <comment xml:lang="he">תבנית Office Open XML Visio</comment>
+ <comment xml:lang="gl">Modelo de Office Open XML Visio</comment>
+ <comment xml:lang="fr">modèle Visio Office Open XML</comment>
+ <comment xml:lang="fi">Office Open XML Visio -malli</comment>
+ <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
+ <comment xml:lang="es">plantilla Office Open XML de Visio</comment>
+ <comment xml:lang="en_GB">Office Open XML Visio template</comment>
+ <comment xml:lang="de">Office-Open-XML-Visio-Vorlage</comment>
+ <comment xml:lang="da">Office Open XML Visio-skabelon</comment>
+ <comment xml:lang="ca">plantilla en Office Open XML de Visio</comment>
+ <comment xml:lang="bg">Шаблон за чертеж — Office Open XML Visio</comment>
+ <comment xml:lang="be">шаблон Office Open XML Visio</comment>
+ <comment xml:lang="ar">قالب فيزيو Open XML</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vstx"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/vnd.ms-visio.stencil.main+xml">
- <comment>Office Open XML Visio Stencil</comment>
- <comment xml:lang="ca">patró en Office Open XML de Visio</comment>
- <comment xml:lang="cs">objekty Office Open XML Visio</comment>
- <comment xml:lang="da">Office Open XML Visio-stencil</comment>
- <comment xml:lang="de">Office-Open-XML-Visio-Schablone</comment>
- <comment xml:lang="en_GB">Office Open XML Visio Stencil</comment>
- <comment xml:lang="es">esténcil en OOXML de Visio</comment>
- <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
- <comment xml:lang="fi">Office Open XML Visio -kaavio</comment>
- <comment xml:lang="fr">stencil Visio Office Open XML</comment>
- <comment xml:lang="ga">Stionsal Office Open XML Visio</comment>
- <comment xml:lang="he">דגם ל־Visio ב־Open XML מבית Office</comment>
- <comment xml:lang="hr">Office Open XML Visio šablona</comment>
- <comment xml:lang="hu">Office Open XML Visio stencil</comment>
- <comment xml:lang="ia">Stencil Office Open XML Visio</comment>
- <comment xml:lang="id">Stensil Visio Office Open XML</comment>
- <comment xml:lang="it">Stencil Visio Office Open XML</comment>
- <comment xml:lang="kk">Office Open XML пішімінің Visio трафареті</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 스텐실</comment>
- <comment xml:lang="pl">Wzór Office Open XML Visio</comment>
- <comment xml:lang="pt">Stencil Office Open XML Visio</comment>
- <comment xml:lang="pt_BR">Estêncil do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Трафарет Visio формата Office Open XML</comment>
- <comment xml:lang="sk">Objekt aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">Офисов отворени ИксМЛ Визио шаблон</comment>
- <comment xml:lang="sv">Office Open XML Visio-stencil</comment>
- <comment xml:lang="tr">Office Open XML Visio Kalıbı</comment>
- <comment xml:lang="uk">трафарет Visio у форматі Office Open XML</comment>
+ <comment>Office Open XML Visio stencil</comment>
<comment xml:lang="zh_CN">Office Open XML Visio 模具</comment>
- <comment xml:lang="zh_TW">Office Open XML Visio 圖形樣本</comment>
+ <comment xml:lang="uk">трафарет Visio Office Open у XML</comment>
+ <comment xml:lang="tr">Office Open XML Visio kalıbı</comment>
+ <comment xml:lang="sv">Office Open XML Visio-stencil</comment>
+ <comment xml:lang="sq">model Office Open XML Visio</comment>
+ <comment xml:lang="si">කාර්යාල විවෘත XML Visio ස්ටෙන්සිල්</comment>
+ <comment xml:lang="ru">Трафарет Visio формата Office Open XML</comment>
+ <comment xml:lang="pt_BR">Estêncil do Office Open XML Visio</comment>
+ <comment xml:lang="pt">estêncil Visio do Open Office XML</comment>
+ <comment xml:lang="pl">Wzór Office Open XML Visio</comment>
+ <comment xml:lang="nl">Office Open XML Visio-stencil</comment>
+ <comment xml:lang="ko">오피스 오픈 XML Visio 스텐실</comment>
+ <comment xml:lang="kk">Office Open XML Visio трафареті</comment>
+ <comment xml:lang="ja">Office Open XML Visio ステンシル</comment>
+ <comment xml:lang="it">Stencil Visio Office Open XML</comment>
+ <comment xml:lang="is">Office Open XML Visio stensill</comment>
+ <comment xml:lang="id">Stensil Office Open XML Visio</comment>
+ <comment xml:lang="hu">Office Open XML Visio stencil</comment>
+ <comment xml:lang="hr">Office Open XML Visio šablona</comment>
+ <comment xml:lang="he">סטנסיל ל־Visio ב־Open XML מבית Office</comment>
+ <comment xml:lang="gl">Pincel de de Office Open XML Visio</comment>
+ <comment xml:lang="fr">stencil Visio Office Open XML</comment>
+ <comment xml:lang="fi">Office Open XML Visio -malli</comment>
+ <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
+ <comment xml:lang="es">galería de símbolos Office Open XML de Visio</comment>
+ <comment xml:lang="en_GB">Office Open XML Visio stencil</comment>
+ <comment xml:lang="de">Office-Open-XML-Visio-Schablone</comment>
+ <comment xml:lang="da">Office Open XML Visio-stencil</comment>
+ <comment xml:lang="ca">patró en Office Open XML de Visio</comment>
+ <comment xml:lang="bg">Образци — Office Open XML Visio</comment>
+ <comment xml:lang="be">трафарэт Office Open XML Visio</comment>
+ <comment xml:lang="ar">شكل فيزيو Open XML</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vssx"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/vnd.ms-visio.drawing.macroEnabled.main+xml">
- <comment>Office Open XML Visio Drawing</comment>
- <comment xml:lang="ca">dibuix en Office Open XML de Visio</comment>
- <comment xml:lang="cs">kresba Office Open XML Visio</comment>
- <comment xml:lang="da">Office Open XML Visio-tegning</comment>
- <comment xml:lang="de">Office-Open-XML-Visio-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Office Open XML Visio</comment>
- <comment xml:lang="en_GB">Office Open XML Visio Drawing</comment>
- <comment xml:lang="es">dibujo en OOXML de Visio</comment>
- <comment xml:lang="eu">Office Open XML Visio marrazkia</comment>
- <comment xml:lang="fi">Office Open XML Visio -piirros</comment>
- <comment xml:lang="fr">dessin Visio Office Open XML</comment>
- <comment xml:lang="ga">Líníocht Office Open XML Visio</comment>
- <comment xml:lang="he">ציור Visio ב־Open XML מבית Office</comment>
- <comment xml:lang="hr">Office Open XML Visio crtež</comment>
- <comment xml:lang="hu">Office Open XML Visio rajz</comment>
- <comment xml:lang="ia">Designo Office Open XML Visio</comment>
- <comment xml:lang="id">Gambar Visio Office Open XML</comment>
- <comment xml:lang="it">Disegno Visio Office Open XML</comment>
- <comment xml:lang="kk">Office Open XML Visio суреті</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 드로잉</comment>
- <comment xml:lang="pl">Rysunek Office Open XML Visio</comment>
- <comment xml:lang="pt">desenho Office Open XML Visio</comment>
- <comment xml:lang="pt_BR">Desenho do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Рисунок Visio формата Office Open XML</comment>
- <comment xml:lang="sk">Kresba aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">Офисов отворени ИксМЛ Визио цртеж</comment>
- <comment xml:lang="sv">Office Open XML Visio-teckning</comment>
- <comment xml:lang="tr">Office Open XML Visio Çizimi</comment>
- <comment xml:lang="uk">схема VIisio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">Office Open XML Visio 绘图</comment>
+ <comment>Office Open XML Visio drawing</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 繪圖</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 绘图</comment>
+ <comment xml:lang="uk">малюнок Visio Office Open у XML</comment>
+ <comment xml:lang="tr">Office Open XML Visio çizimi</comment>
+ <comment xml:lang="sv">Office Open XML Visio-ritning</comment>
+ <comment xml:lang="sq">vizatim Office Open XML Visio</comment>
+ <comment xml:lang="sl">Risba Office Open XML Visio</comment>
+ <comment xml:lang="si">කාර්යාල විවෘත XML Visio ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba aplikácie Office Open XML Visio</comment>
+ <comment xml:lang="ru">Рисунок Visio формата Office Open XML</comment>
+ <comment xml:lang="pt_BR">Desenho do Office Open XML Visio</comment>
+ <comment xml:lang="pt">desenho Visio do Open Office XML</comment>
+ <comment xml:lang="pl">Rysunek Office Open XML Visio</comment>
+ <comment xml:lang="nl">Office Open XML Visio-tekening</comment>
+ <comment xml:lang="ko">오피스 오픈 XML Visio 드로잉</comment>
+ <comment xml:lang="kk">Office Open XML Visio суреті</comment>
+ <comment xml:lang="ja">Office Open XML Visio ドロー</comment>
+ <comment xml:lang="it">Disegno Visio Office Open XML</comment>
+ <comment xml:lang="is">Office Open XML Visio teikning</comment>
+ <comment xml:lang="id">Gambar Office Open XML Visio</comment>
+ <comment xml:lang="hu">Office Open XML Visio rajz</comment>
+ <comment xml:lang="hr">Office Open XML Visio crtež</comment>
+ <comment xml:lang="he">ציור Office Open XML Visio</comment>
+ <comment xml:lang="gl">Debuxo de Office Open XML Visio</comment>
+ <comment xml:lang="fr">dessin Visio Office Open XML</comment>
+ <comment xml:lang="fi">Office Open XML Visio -piirros</comment>
+ <comment xml:lang="eu">Office Open XML Visio marrazkia</comment>
+ <comment xml:lang="es">dibujo Office Open XML de Visio</comment>
+ <comment xml:lang="en_GB">Office Open XML Visio drawing</comment>
+ <comment xml:lang="de">Office-Open-XML-Visio-Zeichnung</comment>
+ <comment xml:lang="da">Office Open XML Visio-tegning</comment>
+ <comment xml:lang="ca">dibuix en Office Open XML de Visio</comment>
+ <comment xml:lang="bg">Чертеж — Office Open XML Visio</comment>
+ <comment xml:lang="be">рысунак Office Open XML Visio</comment>
+ <comment xml:lang="ar">رسم فيزيو Open XML</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vsdm"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/vnd.ms-visio.template.macroEnabled.main+xml">
- <comment>Office Open XML Visio Template</comment>
- <comment xml:lang="ca">plantilla en Office Open XML de Visio</comment>
- <comment xml:lang="cs">šablona Office Open XML Visio</comment>
- <comment xml:lang="da">Office Open XML Visio-skabelon</comment>
- <comment xml:lang="de">Office-Open-XML-Visio-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο Office Open XML Visio</comment>
- <comment xml:lang="en_GB">Office Open XML Visio Template</comment>
- <comment xml:lang="es">plantilla en OOXML de Visio</comment>
- <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
- <comment xml:lang="fi">Office Open XML Visio -malli</comment>
- <comment xml:lang="fr">modèle Visio Office Open XML</comment>
- <comment xml:lang="ga">Teimpléad Office Open XML Visio</comment>
- <comment xml:lang="he">תבנית Visio ב־Open XML מבית Office</comment>
- <comment xml:lang="hr">Predložak Office Open XML Visio</comment>
- <comment xml:lang="hu">Office Open XML Visio sablon</comment>
- <comment xml:lang="ia">Patrono Office Open XML Visio</comment>
- <comment xml:lang="id">Templat Visio Office Open XML</comment>
- <comment xml:lang="it">Modello Visio Office Open XML</comment>
- <comment xml:lang="kk">Office Open XML Visio үлгісі</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 서식</comment>
- <comment xml:lang="pl">Szablon Office Open XML Visio</comment>
- <comment xml:lang="pt">modelo Office Open XML Visio</comment>
- <comment xml:lang="pt_BR">Modelo do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Шаблон Visio формата Office Open XML</comment>
- <comment xml:lang="sk">Šablóna aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">Офисов отворени ИксМЛ Визио шаблон</comment>
- <comment xml:lang="sv">Office Open XML Visio-mall</comment>
- <comment xml:lang="tr">Office Open XML Visio Şablonu</comment>
- <comment xml:lang="uk">шаблон Visio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">Office Open XML Visio 模板</comment>
+ <comment>Office Open XML Visio template</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 範本</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 模板</comment>
+ <comment xml:lang="uk">шаблон Visio Office Open у XML</comment>
+ <comment xml:lang="tr">Office Open XML Visio şablonu</comment>
+ <comment xml:lang="sv">Office Open XML Visio-mall</comment>
+ <comment xml:lang="sq">gjedhe Office Open XML Visio</comment>
+ <comment xml:lang="sl">Predloga Office Open XML Visio</comment>
+ <comment xml:lang="si">Office Open XML Visio අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna aplikácie Office Open XML Visio</comment>
+ <comment xml:lang="ru">Шаблон Visio формата Office Open XML</comment>
+ <comment xml:lang="pt_BR">Modelo Office Open XML Visio</comment>
+ <comment xml:lang="pt">predefinição Visio do Open Office XML</comment>
+ <comment xml:lang="pl">Szablon Office Open XML Visio</comment>
+ <comment xml:lang="nl">Office Open XML Visio-sjabloon</comment>
+ <comment xml:lang="ko">오피스 오픈 XML Visio 양식</comment>
+ <comment xml:lang="kk">Office Open XML Visio үлгісі</comment>
+ <comment xml:lang="ja">Office Open XML Visio テンプレート</comment>
+ <comment xml:lang="it">Modello Visio Office Open XML</comment>
+ <comment xml:lang="is">Office Open XML Visio sniðmát</comment>
+ <comment xml:lang="id">Templat Office Open XML Visio</comment>
+ <comment xml:lang="hu">Office Open XML Visio sablon</comment>
+ <comment xml:lang="hr">Office Open XML Visio predložak</comment>
+ <comment xml:lang="he">תבנית Office Open XML Visio</comment>
+ <comment xml:lang="gl">Modelo de Office Open XML Visio</comment>
+ <comment xml:lang="fr">modèle Visio Office Open XML</comment>
+ <comment xml:lang="fi">Office Open XML Visio -malli</comment>
+ <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
+ <comment xml:lang="es">plantilla Office Open XML de Visio</comment>
+ <comment xml:lang="en_GB">Office Open XML Visio template</comment>
+ <comment xml:lang="de">Office-Open-XML-Visio-Vorlage</comment>
+ <comment xml:lang="da">Office Open XML Visio-skabelon</comment>
+ <comment xml:lang="ca">plantilla en Office Open XML de Visio</comment>
+ <comment xml:lang="bg">Шаблон за чертеж — Office Open XML Visio</comment>
+ <comment xml:lang="be">шаблон Office Open XML Visio</comment>
+ <comment xml:lang="ar">قالب فيزيو Open XML</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vstm"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/vnd.ms-visio.stencil.macroEnabled.main+xml">
- <comment>Office Open XML Visio Stencil</comment>
- <comment xml:lang="ca">patró en Office Open XML de Visio</comment>
- <comment xml:lang="cs">objekty Office Open XML Visio</comment>
- <comment xml:lang="da">Office Open XML Visio-stencil</comment>
- <comment xml:lang="de">Office-Open-XML-Visio-Schablone</comment>
- <comment xml:lang="en_GB">Office Open XML Visio Stencil</comment>
- <comment xml:lang="es">esténcil en OOXML de Visio</comment>
- <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
- <comment xml:lang="fi">Office Open XML Visio -kaavio</comment>
- <comment xml:lang="fr">stencil Visio Office Open XML</comment>
- <comment xml:lang="ga">Stionsal Office Open XML Visio</comment>
- <comment xml:lang="he">דגם ל־Visio ב־Open XML מבית Office</comment>
- <comment xml:lang="hr">Office Open XML Visio šablona</comment>
- <comment xml:lang="hu">Office Open XML Visio stencil</comment>
- <comment xml:lang="ia">Stencil Office Open XML Visio</comment>
- <comment xml:lang="id">Stensil Visio Office Open XML</comment>
- <comment xml:lang="it">Stencil Visio Office Open XML</comment>
- <comment xml:lang="kk">Office Open XML пішімінің Visio трафареті</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 스텐실</comment>
- <comment xml:lang="pl">Wzór Office Open XML Visio</comment>
- <comment xml:lang="pt">Stencil Office Open XML Visio</comment>
- <comment xml:lang="pt_BR">Estêncil do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Трафарет Visio формата Office Open XML</comment>
- <comment xml:lang="sk">Objekt aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">Офисов отворени ИксМЛ Визио шаблон</comment>
- <comment xml:lang="sv">Office Open XML Visio-stencil</comment>
- <comment xml:lang="tr">Office Open XML Visio Kalıbı</comment>
- <comment xml:lang="uk">трафарет Visio у форматі Office Open XML</comment>
+ <comment>Office Open XML Visio stencil</comment>
<comment xml:lang="zh_CN">Office Open XML Visio 模具</comment>
- <comment xml:lang="zh_TW">Office Open XML Visio 圖形樣本</comment>
+ <comment xml:lang="uk">трафарет Visio Office Open у XML</comment>
+ <comment xml:lang="tr">Office Open XML Visio kalıbı</comment>
+ <comment xml:lang="sv">Office Open XML Visio-stencil</comment>
+ <comment xml:lang="sq">model Office Open XML Visio</comment>
+ <comment xml:lang="si">කාර්යාල විවෘත XML Visio ස්ටෙන්සිල්</comment>
+ <comment xml:lang="ru">Трафарет Visio формата Office Open XML</comment>
+ <comment xml:lang="pt_BR">Estêncil do Office Open XML Visio</comment>
+ <comment xml:lang="pt">estêncil Visio do Open Office XML</comment>
+ <comment xml:lang="pl">Wzór Office Open XML Visio</comment>
+ <comment xml:lang="nl">Office Open XML Visio-stencil</comment>
+ <comment xml:lang="ko">오피스 오픈 XML Visio 스텐실</comment>
+ <comment xml:lang="kk">Office Open XML Visio трафареті</comment>
+ <comment xml:lang="ja">Office Open XML Visio ステンシル</comment>
+ <comment xml:lang="it">Stencil Visio Office Open XML</comment>
+ <comment xml:lang="is">Office Open XML Visio stensill</comment>
+ <comment xml:lang="id">Stensil Office Open XML Visio</comment>
+ <comment xml:lang="hu">Office Open XML Visio stencil</comment>
+ <comment xml:lang="hr">Office Open XML Visio šablona</comment>
+ <comment xml:lang="he">סטנסיל ל־Visio ב־Open XML מבית Office</comment>
+ <comment xml:lang="gl">Pincel de de Office Open XML Visio</comment>
+ <comment xml:lang="fr">stencil Visio Office Open XML</comment>
+ <comment xml:lang="fi">Office Open XML Visio -malli</comment>
+ <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
+ <comment xml:lang="es">galería de símbolos Office Open XML de Visio</comment>
+ <comment xml:lang="en_GB">Office Open XML Visio stencil</comment>
+ <comment xml:lang="de">Office-Open-XML-Visio-Schablone</comment>
+ <comment xml:lang="da">Office Open XML Visio-stencil</comment>
+ <comment xml:lang="ca">patró en Office Open XML de Visio</comment>
+ <comment xml:lang="bg">Образци — Office Open XML Visio</comment>
+ <comment xml:lang="be">трафарэт Office Open XML Visio</comment>
+ <comment xml:lang="ar">شكل فيزيو Open XML</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vssm"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/vnd.ms-word.document.macroEnabled.12">
<comment>Word document</comment>
- <comment xml:lang="ar">مستند Word</comment>
- <comment xml:lang="ast">Documentu de Word</comment>
- <comment xml:lang="be@latin">Dakument Word</comment>
- <comment xml:lang="bg">Документ — Word</comment>
- <comment xml:lang="ca">document Word</comment>
- <comment xml:lang="cs">dokument Word</comment>
- <comment xml:lang="da">Worddokument</comment>
- <comment xml:lang="de">Word-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Word</comment>
- <comment xml:lang="en_GB">Word document</comment>
- <comment xml:lang="eo">Word-dokumento</comment>
- <comment xml:lang="es">documento de Word</comment>
- <comment xml:lang="eu">Word dokumentua</comment>
- <comment xml:lang="fi">Word-asiakirja</comment>
- <comment xml:lang="fo">Word skjal</comment>
- <comment xml:lang="fr">document Word</comment>
- <comment xml:lang="ga">cáipéis Word</comment>
- <comment xml:lang="gl">documento de Word</comment>
- <comment xml:lang="he">מסמך Word</comment>
- <comment xml:lang="hr">Word dokument</comment>
- <comment xml:lang="hu">Word dokumentum</comment>
- <comment xml:lang="ia">Documento Word</comment>
- <comment xml:lang="id">Dokumen Word</comment>
- <comment xml:lang="it">Documento Word</comment>
- <comment xml:lang="ja">Word ドキュメント</comment>
- <comment xml:lang="kk">Word құжаты</comment>
- <comment xml:lang="ko">Word 문서</comment>
- <comment xml:lang="lt">Word dokumentas</comment>
- <comment xml:lang="lv">Word dokuments</comment>
- <comment xml:lang="nb">Word-dokument</comment>
- <comment xml:lang="nl">Word-document</comment>
- <comment xml:lang="nn">Word-dokument</comment>
- <comment xml:lang="oc">document Word</comment>
- <comment xml:lang="pl">Dokument Word</comment>
- <comment xml:lang="pt">documento Word</comment>
- <comment xml:lang="pt_BR">Documento do Word</comment>
- <comment xml:lang="ro">Document Word</comment>
- <comment xml:lang="ru">Документ Word</comment>
- <comment xml:lang="sk">Dokument Word</comment>
- <comment xml:lang="sl">Dokument Word</comment>
- <comment xml:lang="sq">Dokument Word</comment>
- <comment xml:lang="sr">Ворд документ</comment>
- <comment xml:lang="sv">Word-dokument</comment>
- <comment xml:lang="tr">Word belgesi</comment>
- <comment xml:lang="uk">документ Word</comment>
- <comment xml:lang="vi">Tài liệu Word</comment>
- <comment xml:lang="zh_CN">Word 文档</comment>
<comment xml:lang="zh_TW">Word 文件</comment>
+ <comment xml:lang="zh_CN">Word 文档</comment>
+ <comment xml:lang="vi">Tài liệu Word</comment>
+ <comment xml:lang="uk">документ Word</comment>
+ <comment xml:lang="tr">Word belgesi</comment>
+ <comment xml:lang="sv">Word-dokument</comment>
+ <comment xml:lang="sr">Ворд документ</comment>
+ <comment xml:lang="sq">dokument Word</comment>
+ <comment xml:lang="sl">Dokument Word</comment>
+ <comment xml:lang="si">වචන ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Word</comment>
+ <comment xml:lang="ru">Документ Word</comment>
+ <comment xml:lang="ro">Document Word</comment>
+ <comment xml:lang="pt_BR">Documento do Word</comment>
+ <comment xml:lang="pt">documento Word</comment>
+ <comment xml:lang="pl">Dokument Word</comment>
+ <comment xml:lang="oc">document Word</comment>
+ <comment xml:lang="nn">Word-dokument</comment>
+ <comment xml:lang="nl">Word-document</comment>
+ <comment xml:lang="nb">Word-dokument</comment>
+ <comment xml:lang="lv">Word dokuments</comment>
+ <comment xml:lang="lt">Word dokumentas</comment>
+ <comment xml:lang="ko">Word 문서</comment>
+ <comment xml:lang="kk">Word құжаты</comment>
+ <comment xml:lang="ka">Word -ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Word ドキュメント</comment>
+ <comment xml:lang="it">Documento Word</comment>
+ <comment xml:lang="is">Word skjal</comment>
+ <comment xml:lang="id">Dokumen Word</comment>
+ <comment xml:lang="ia">Documento Word</comment>
+ <comment xml:lang="hu">Word dokumentum</comment>
+ <comment xml:lang="hr">Word dokument</comment>
+ <comment xml:lang="he">מסמך Word</comment>
+ <comment xml:lang="gl">documento de Word</comment>
+ <comment xml:lang="ga">cáipéis Word</comment>
+ <comment xml:lang="fur">document Word</comment>
+ <comment xml:lang="fr">document Word</comment>
+ <comment xml:lang="fo">Word skjal</comment>
+ <comment xml:lang="fi">Word-asiakirja</comment>
+ <comment xml:lang="eu">Word dokumentua</comment>
+ <comment xml:lang="es">documento de Word</comment>
+ <comment xml:lang="eo">Word-dokumento</comment>
+ <comment xml:lang="en_GB">Word document</comment>
+ <comment xml:lang="el">Έγγραφο Word</comment>
+ <comment xml:lang="de">Word-Dokument</comment>
+ <comment xml:lang="da">Worddokument</comment>
+ <comment xml:lang="cs">dokument Word</comment>
+ <comment xml:lang="ca">document Word</comment>
+ <comment xml:lang="bg">Документ — Word</comment>
+ <comment xml:lang="be@latin">Dakument Word</comment>
+ <comment xml:lang="be">дакумент Word</comment>
+ <comment xml:lang="ast">Documentu de Word</comment>
+ <comment xml:lang="ar">مستند ورد</comment>
+ <comment xml:lang="af">Word-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.docm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.wordprocessingml.document"/>
</mime-type>
<mime-type type="application/vnd.ms-word.template.macroEnabled.12">
<comment>Word document template</comment>
- <comment xml:lang="ast">Plantía de documentu de Word</comment>
- <comment xml:lang="ca">plantilla de document Word</comment>
- <comment xml:lang="cs">šablona dokumentu Word</comment>
- <comment xml:lang="da">Word-dokumentskabelon</comment>
- <comment xml:lang="de">Word-Dokumentvorlage</comment>
- <comment xml:lang="el">Πρότυπο έγγραφο Word</comment>
- <comment xml:lang="en_GB">Word document template</comment>
- <comment xml:lang="es">plantilla de documento de Word</comment>
- <comment xml:lang="eu">Word dokumentuaren txantiloia</comment>
- <comment xml:lang="fi">Word-asiakirjamalli</comment>
- <comment xml:lang="fr">modèle de document Word</comment>
- <comment xml:lang="ga">teimpléad Word</comment>
- <comment xml:lang="he">תבנית מסמך Word</comment>
- <comment xml:lang="hr">Predložak Word dokumenta</comment>
- <comment xml:lang="hu">Word dokumentumsablon</comment>
- <comment xml:lang="ia">Patrono de documento Word</comment>
- <comment xml:lang="id">Templat dokumen Word</comment>
- <comment xml:lang="it">Modello documento Word</comment>
- <comment xml:lang="kk">Word құжатының үлгісі</comment>
- <comment xml:lang="ko">Word 문서 서식</comment>
- <comment xml:lang="oc">modèl de document Word</comment>
- <comment xml:lang="pl">Szablon dokumentu Word</comment>
- <comment xml:lang="pt">modelo de documento Word</comment>
- <comment xml:lang="pt_BR">Modelo de documento do Word</comment>
- <comment xml:lang="ru">Шаблон документа Word</comment>
- <comment xml:lang="sk">Šablóna dokumentu aplikácie Word</comment>
- <comment xml:lang="sr">Шаблон Ворд документа</comment>
- <comment xml:lang="sv">Word-dokumentmall</comment>
- <comment xml:lang="tr">Word belgesi şablonu</comment>
- <comment xml:lang="uk">шаблон документа Word</comment>
- <comment xml:lang="zh_CN">Word 文档模板</comment>
<comment xml:lang="zh_TW">Word 文件範本</comment>
+ <comment xml:lang="zh_CN">Word 文档模板</comment>
+ <comment xml:lang="uk">шаблон документа Word</comment>
+ <comment xml:lang="tr">Word belgesi şablonu</comment>
+ <comment xml:lang="sv">Word-dokumentmall</comment>
+ <comment xml:lang="sr">Шаблон Ворд документа</comment>
+ <comment xml:lang="sq">gjedhe dokumenti Word</comment>
+ <comment xml:lang="sl">Predloga dokumenta Word</comment>
+ <comment xml:lang="si">වචන ලේඛන ආකෘතිය</comment>
+ <comment xml:lang="sk">Šablóna dokumentu aplikácie Word</comment>
+ <comment xml:lang="ru">Шаблон документа Word</comment>
+ <comment xml:lang="pt_BR">Modelo de documento do Word</comment>
+ <comment xml:lang="pt">modelo de documento Word</comment>
+ <comment xml:lang="pl">Szablon dokumentu Word</comment>
+ <comment xml:lang="oc">modèl de document Word</comment>
+ <comment xml:lang="nl">Word-documentsjabloon</comment>
+ <comment xml:lang="ko">Word 문서 서식</comment>
+ <comment xml:lang="kk">Word құжатының үлгісі</comment>
+ <comment xml:lang="ja">Word ドキュメントテンプレート</comment>
+ <comment xml:lang="it">Modello documento Word</comment>
+ <comment xml:lang="is">Word sniðmát fyrir textaskjal</comment>
+ <comment xml:lang="id">Templat dokumen Word</comment>
+ <comment xml:lang="ia">Patrono de documento Word</comment>
+ <comment xml:lang="hu">Word dokumentumsablon</comment>
+ <comment xml:lang="hr">Predložak Word dokumenta</comment>
+ <comment xml:lang="he">תבנית מסמך Word</comment>
+ <comment xml:lang="gl">Modelo de documento Word</comment>
+ <comment xml:lang="ga">teimpléad Word</comment>
+ <comment xml:lang="fur">model di document Word</comment>
+ <comment xml:lang="fr">modèle de document Word</comment>
+ <comment xml:lang="fi">Word-asiakirjamalli</comment>
+ <comment xml:lang="eu">Word dokumentuaren txantiloia</comment>
+ <comment xml:lang="es">plantilla de documento de Word</comment>
+ <comment xml:lang="en_GB">Word document template</comment>
+ <comment xml:lang="el">Πρότυπο έγγραφο Word</comment>
+ <comment xml:lang="de">Word-Dokumentvorlage</comment>
+ <comment xml:lang="da">Word-dokumentskabelon</comment>
+ <comment xml:lang="cs">šablona dokumentu Word</comment>
+ <comment xml:lang="ca">plantilla de document Word</comment>
+ <comment xml:lang="bg">Шаблон за документ — Word</comment>
+ <comment xml:lang="be">шаблон дакумента Word</comment>
+ <comment xml:lang="ast">Plantía de documentu de Word</comment>
+ <comment xml:lang="ar">قالب مستند ورد</comment>
+ <comment xml:lang="af">Word-dokumentsjabloon</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.dotm"/>
<sub-class-of type="application/vnd.openxmlformats-officedocument.wordprocessingml.template"/>
</mime-type>
<mime-type type="application/oxps">
+ <comment>OpenXPS document</comment>
+ <comment xml:lang="zh_TW">OpenXPS 文件</comment>
+ <comment xml:lang="zh_CN">OpenXPS 文档</comment>
+ <comment xml:lang="uk">документ OpenXPS</comment>
+ <comment xml:lang="tr">OpenXPS belgesi</comment>
+ <comment xml:lang="sv">OpenXPS-dokument</comment>
+ <comment xml:lang="sl">Dokument OpenXPS</comment>
+ <comment xml:lang="si">OpenXPS ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument OpenXPS</comment>
+ <comment xml:lang="ru">Документ OpenXPS</comment>
+ <comment xml:lang="pt_BR">Documento OpenXPS</comment>
+ <comment xml:lang="pt">documento OpenXPS</comment>
+ <comment xml:lang="pl">Dokument OpenXPS</comment>
+ <comment xml:lang="oc">document OpenXPS</comment>
+ <comment xml:lang="nl">OpenXPS-document</comment>
+ <comment xml:lang="ko">OpenXPS 문서</comment>
+ <comment xml:lang="kk">OpenXPS құжаты</comment>
+ <comment xml:lang="ka">OpenXPS -ის დოკუმენტი</comment>
+ <comment xml:lang="ja">OpenXPS ドキュメント</comment>
+ <comment xml:lang="it">Documento OpenXPS</comment>
+ <comment xml:lang="is">OpenXPS skjal</comment>
+ <comment xml:lang="id">Dokumen OpenXPS</comment>
+ <comment xml:lang="hu">OpenXPS-dokumentum</comment>
+ <comment xml:lang="hr">OpenXPS dokument</comment>
+ <comment xml:lang="he">מסמך OpenXPS</comment>
+ <comment xml:lang="gl">Documento de OpenXPS</comment>
+ <comment xml:lang="fr">Document OpenXPS</comment>
+ <comment xml:lang="fi">OpenXPS-asiakirja</comment>
+ <comment xml:lang="eu">OpenXPS dokumentua</comment>
+ <comment xml:lang="es">documento OpenXPS</comment>
+ <comment xml:lang="en_GB">OpenXPS document</comment>
+ <comment xml:lang="de">OpenXPS-Dokument</comment>
+ <comment xml:lang="da">OpenXPS-dokument</comment>
+ <comment xml:lang="ca">document OpenXPS</comment>
+ <comment xml:lang="be">дакумент OpenXPS</comment>
+ <comment xml:lang="ar">مستند OpenXPS</comment>
+ <acronym>OpenXPS</acronym>
+ <expanded-acronym>Open XML Paper Specification</expanded-acronym>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="x-office-document"/>
+ <glob pattern="*.oxps"/>
+ </mime-type>
+ <mime-type type="application/vnd.ms-xpsdocument">
<comment>XPS document</comment>
- <comment xml:lang="ar">مستند XPS</comment>
- <comment xml:lang="ast">Documentu XPS</comment>
- <comment xml:lang="be@latin">Dakument XPS</comment>
- <comment xml:lang="bg">Документ — XPS</comment>
- <comment xml:lang="ca">document XPS</comment>
- <comment xml:lang="cs">dokument XPS</comment>
- <comment xml:lang="da">XPS-dokument</comment>
- <comment xml:lang="de">XPS-Dokument</comment>
- <comment xml:lang="el">Έγγραφο XPS</comment>
- <comment xml:lang="en_GB">XPS document</comment>
- <comment xml:lang="eo">XPS-dokumento</comment>
- <comment xml:lang="es">documento XPS</comment>
- <comment xml:lang="eu">XPS dokumentua</comment>
- <comment xml:lang="fi">XPS-asiakirja</comment>
- <comment xml:lang="fo">XPS skjal</comment>
- <comment xml:lang="fr">document XPS</comment>
- <comment xml:lang="ga">cáipéis XPS</comment>
- <comment xml:lang="gl">documento XPS</comment>
- <comment xml:lang="he">מסמך XPS</comment>
- <comment xml:lang="hr">XPS dokument</comment>
- <comment xml:lang="hu">XPS dokumentum</comment>
- <comment xml:lang="ia">Documento XPS</comment>
- <comment xml:lang="id">Dokumen XPS</comment>
- <comment xml:lang="it">Documento XPS</comment>
- <comment xml:lang="ja">XPS ドキュメント</comment>
- <comment xml:lang="kk">XPS құжаты</comment>
- <comment xml:lang="ko">XPS 문서</comment>
- <comment xml:lang="lt">XPS dokumentas</comment>
- <comment xml:lang="lv">XPS dokuments</comment>
- <comment xml:lang="nb">XPS-dokument</comment>
- <comment xml:lang="nl">XPS-document</comment>
- <comment xml:lang="nn">XPS-dokument</comment>
- <comment xml:lang="oc">document XPS</comment>
- <comment xml:lang="pl">Dokument XPS</comment>
- <comment xml:lang="pt">documento XPS</comment>
- <comment xml:lang="pt_BR">Documento XPS</comment>
- <comment xml:lang="ro">Document XPS</comment>
- <comment xml:lang="ru">Документ XPS</comment>
- <comment xml:lang="sk">Dokument XPS</comment>
- <comment xml:lang="sl">Dokument XPS</comment>
- <comment xml:lang="sq">Dokument XPS</comment>
- <comment xml:lang="sr">ИксПС документ</comment>
- <comment xml:lang="sv">XPS-dokument</comment>
- <comment xml:lang="tr">XPS belgesi</comment>
- <comment xml:lang="uk">документ XPS</comment>
- <comment xml:lang="vi">Tài liệu XPS</comment>
- <comment xml:lang="zh_CN">XPS 文档</comment>
<comment xml:lang="zh_TW">XPS 文件</comment>
+ <comment xml:lang="zh_CN">XPS 文档</comment>
+ <comment xml:lang="vi">Tài liệu XPS</comment>
+ <comment xml:lang="uk">документ XPS</comment>
+ <comment xml:lang="tr">XPS belgesi</comment>
+ <comment xml:lang="sv">XPS-dokument</comment>
+ <comment xml:lang="sr">ИксПС документ</comment>
+ <comment xml:lang="sq">dokument XPS</comment>
+ <comment xml:lang="sl">Dokument XPS</comment>
+ <comment xml:lang="si">XPS ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument XPS</comment>
+ <comment xml:lang="ru">Документ XPS</comment>
+ <comment xml:lang="ro">Document XPS</comment>
+ <comment xml:lang="pt_BR">Documento XPS</comment>
+ <comment xml:lang="pt">documento XPS</comment>
+ <comment xml:lang="pl">Dokument XPS</comment>
+ <comment xml:lang="oc">document XPS</comment>
+ <comment xml:lang="nn">XPS-dokument</comment>
+ <comment xml:lang="nl">XPS-document</comment>
+ <comment xml:lang="nb">XPS-dokument</comment>
+ <comment xml:lang="lv">XPS dokuments</comment>
+ <comment xml:lang="lt">XPS dokumentas</comment>
+ <comment xml:lang="ko">XPS 문서</comment>
+ <comment xml:lang="kk">XPS құжаты</comment>
+ <comment xml:lang="ka">XPS -ის დოკუმენტი</comment>
+ <comment xml:lang="ja">XPS ドキュメント</comment>
+ <comment xml:lang="it">Documento XPS</comment>
+ <comment xml:lang="is">XPS skjal</comment>
+ <comment xml:lang="id">Dokumen XPS</comment>
+ <comment xml:lang="ia">Documento XPS</comment>
+ <comment xml:lang="hu">XPS dokumentum</comment>
+ <comment xml:lang="hr">XPS dokument</comment>
+ <comment xml:lang="he">מסמך XPS</comment>
+ <comment xml:lang="gl">documento XPS</comment>
+ <comment xml:lang="ga">cáipéis XPS</comment>
+ <comment xml:lang="fur">document XPS</comment>
+ <comment xml:lang="fr">document XPS</comment>
+ <comment xml:lang="fo">XPS skjal</comment>
+ <comment xml:lang="fi">XPS-asiakirja</comment>
+ <comment xml:lang="eu">XPS dokumentua</comment>
+ <comment xml:lang="es">documento XPS</comment>
+ <comment xml:lang="eo">XPS-dokumento</comment>
+ <comment xml:lang="en_GB">XPS document</comment>
+ <comment xml:lang="el">Έγγραφο XPS</comment>
+ <comment xml:lang="de">XPS-Dokument</comment>
+ <comment xml:lang="da">XPS-dokument</comment>
+ <comment xml:lang="cs">dokument XPS</comment>
+ <comment xml:lang="ca">document XPS</comment>
+ <comment xml:lang="bg">Документ — XPS</comment>
+ <comment xml:lang="be@latin">Dakument XPS</comment>
+ <comment xml:lang="be">дакумент XPS</comment>
+ <comment xml:lang="ast">Documentu XPS</comment>
+ <comment xml:lang="ar">مستند XPS</comment>
+ <comment xml:lang="af">XPS-dokument</comment>
<acronym>XPS</acronym>
- <expanded-acronym>Open XML Paper Specification</expanded-acronym>
+ <expanded-acronym>XML Paper Specification</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
- <glob pattern="*.oxps"/>
<glob pattern="*.xps"/>
- <alias type="application/vnd.ms-xpsdocument"/>
<alias type="application/xps"/>
</mime-type>
<mime-type type="application/vnd.ms-works">
<comment>Microsoft Works document</comment>
- <comment xml:lang="ar">مستند Microsoft Works</comment>
- <comment xml:lang="ast">Documentu de Microsoft Works</comment>
- <comment xml:lang="be@latin">Dakument Microsoft Works</comment>
- <comment xml:lang="bg">Документ — Microsoft Works</comment>
- <comment xml:lang="ca">document de Microsoft Works</comment>
- <comment xml:lang="cs">dokument Microsoft Works</comment>
- <comment xml:lang="da">Microsoft Works-dokument</comment>
- <comment xml:lang="de">Microsoft-Works-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Microsoft Works</comment>
- <comment xml:lang="en_GB">Microsoft Works document</comment>
- <comment xml:lang="es">documento de Microsoft Works</comment>
- <comment xml:lang="eu">Microsoft Works dokumentua</comment>
- <comment xml:lang="fi">Microsoft Works -asiakirja</comment>
- <comment xml:lang="fo">Microsoft Works skjal</comment>
- <comment xml:lang="fr">document Microsoft Works</comment>
- <comment xml:lang="ga">cáipéis Microsoft Works</comment>
- <comment xml:lang="gl">documento de Microsoft Works</comment>
- <comment xml:lang="he">מסמך Microsoft Works</comment>
- <comment xml:lang="hr">Microsoft Works dokument</comment>
- <comment xml:lang="hu">Microsoft Works dokumentum</comment>
- <comment xml:lang="ia">Documento Microsoft Works</comment>
- <comment xml:lang="id">Dokumen Microsoft Works</comment>
- <comment xml:lang="it">Documento Microsoft Works</comment>
- <comment xml:lang="ja">Microsoft Works ドキュメント</comment>
- <comment xml:lang="ka">Microsoft Works-ის დოკუმენტი</comment>
- <comment xml:lang="kk">Microsoft Works құжаты</comment>
- <comment xml:lang="ko">Microsoft Works 문서</comment>
- <comment xml:lang="lt">Microsoft Works dokumentas</comment>
- <comment xml:lang="lv">Microsoft Works dokuments</comment>
- <comment xml:lang="nb">Microsoft Works-dokument</comment>
- <comment xml:lang="nl">Microsoft Works-document</comment>
- <comment xml:lang="nn">Microsoft Works-dokument</comment>
- <comment xml:lang="oc">document Microsoft Works</comment>
- <comment xml:lang="pl">Dokument Microsoft Works</comment>
- <comment xml:lang="pt">documento Microsoft Works</comment>
- <comment xml:lang="pt_BR">Documento do Microsoft Works</comment>
- <comment xml:lang="ro">Document Microsoft Works</comment>
- <comment xml:lang="ru">Документ Microsoft Works</comment>
- <comment xml:lang="sk">Dokument Microsoft Works</comment>
- <comment xml:lang="sl">Dokument Microsoft Works</comment>
- <comment xml:lang="sq">Dokument Microsoft Works</comment>
- <comment xml:lang="sr">документ Мајкрософт Воркса</comment>
- <comment xml:lang="sv">Microsoft Works-dokument</comment>
- <comment xml:lang="tr">Microsoft Works belgesi</comment>
- <comment xml:lang="uk">документ Microsoft Works</comment>
- <comment xml:lang="vi">Tài liệu Microsoft Works</comment>
- <comment xml:lang="zh_CN">Microsoft Works 文档</comment>
<comment xml:lang="zh_TW">微軟 Works 文件</comment>
+ <comment xml:lang="zh_CN">Microsoft Works 文档</comment>
+ <comment xml:lang="vi">Tài liệu Microsoft Works</comment>
+ <comment xml:lang="uk">документ Microsoft Works</comment>
+ <comment xml:lang="tr">Microsoft Works belgesi</comment>
+ <comment xml:lang="sv">Microsoft Works-dokument</comment>
+ <comment xml:lang="sr">документ Мајкрософт Воркса</comment>
+ <comment xml:lang="sq">dokument Microsoft Works</comment>
+ <comment xml:lang="sl">Dokument Microsoft Works</comment>
+ <comment xml:lang="si">Microsoft Works ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Microsoft Works</comment>
+ <comment xml:lang="ru">Документ Microsoft Works</comment>
+ <comment xml:lang="ro">Document Microsoft Works</comment>
+ <comment xml:lang="pt_BR">Documento do Microsoft Works</comment>
+ <comment xml:lang="pt">documento Microsoft Works</comment>
+ <comment xml:lang="pl">Dokument Microsoft Works</comment>
+ <comment xml:lang="oc">document Microsoft Works</comment>
+ <comment xml:lang="nn">Microsoft Works-dokument</comment>
+ <comment xml:lang="nl">Microsoft Works-document</comment>
+ <comment xml:lang="nb">Microsoft Works-dokument</comment>
+ <comment xml:lang="lv">Microsoft Works dokuments</comment>
+ <comment xml:lang="lt">Microsoft Works dokumentas</comment>
+ <comment xml:lang="ko">Microsoft Works 문서</comment>
+ <comment xml:lang="kk">Microsoft Works құжаты</comment>
+ <comment xml:lang="ka">Microsoft Works-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Microsoft Works ドキュメント</comment>
+ <comment xml:lang="it">Documento Microsoft Works</comment>
+ <comment xml:lang="is">Microsoft Works skjal</comment>
+ <comment xml:lang="id">Dokumen Microsoft Works</comment>
+ <comment xml:lang="ia">Documento Microsoft Works</comment>
+ <comment xml:lang="hu">Microsoft Works dokumentum</comment>
+ <comment xml:lang="hr">Microsoft Works dokument</comment>
+ <comment xml:lang="he">מסמך Microsoft Works</comment>
+ <comment xml:lang="gl">documento de Microsoft Works</comment>
+ <comment xml:lang="ga">cáipéis Microsoft Works</comment>
+ <comment xml:lang="fur">document Microsoft Works</comment>
+ <comment xml:lang="fr">document Microsoft Works</comment>
+ <comment xml:lang="fo">Microsoft Works skjal</comment>
+ <comment xml:lang="fi">Microsoft Works -asiakirja</comment>
+ <comment xml:lang="eu">Microsoft Works dokumentua</comment>
+ <comment xml:lang="es">documento de Microsoft Works</comment>
+ <comment xml:lang="en_GB">Microsoft Works document</comment>
+ <comment xml:lang="el">Έγγραφο Microsoft Works</comment>
+ <comment xml:lang="de">Microsoft-Works-Dokument</comment>
+ <comment xml:lang="da">Microsoft Works-dokument</comment>
+ <comment xml:lang="cs">dokument Microsoft Works</comment>
+ <comment xml:lang="ca">document de Microsoft Works</comment>
+ <comment xml:lang="bg">Документ — Microsoft Works</comment>
+ <comment xml:lang="be@latin">Dakument Microsoft Works</comment>
+ <comment xml:lang="be">дакумент Microsoft Works</comment>
+ <comment xml:lang="ast">Documentu de Microsoft Works</comment>
+ <comment xml:lang="ar">مستند Microsoft Works</comment>
+ <comment xml:lang="af">Microsoft Works-dokument</comment>
<sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.wcm"/>
@@ -3971,45 +4585,52 @@
</mime-type>
<mime-type type="application/vnd.visio">
<comment>Microsoft Visio document</comment>
- <comment xml:lang="ast">Documentu de Microsoft Visio</comment>
- <comment xml:lang="bg">Документ — Microsoft Visio</comment>
- <comment xml:lang="ca">document de Microsoft Visio</comment>
- <comment xml:lang="cs">dokument Microsoft Visio</comment>
- <comment xml:lang="da">Microsoft Visio-dokument</comment>
- <comment xml:lang="de">Microsoft-Visio-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Microsoft Visio</comment>
- <comment xml:lang="en_GB">Microsoft Visio document</comment>
- <comment xml:lang="es">documento de Microsoft Visio</comment>
- <comment xml:lang="eu">Microsoft Visio dokumentua</comment>
- <comment xml:lang="fi">Microsoft Visio -asiakirja</comment>
- <comment xml:lang="fr">document Microsoft Visio</comment>
- <comment xml:lang="ga">cáipéis Microsoft Visio</comment>
- <comment xml:lang="gl">Documento de Microsoft Visio</comment>
- <comment xml:lang="he">מסמך </comment>
- <comment xml:lang="hr">Microsoft Visio dokument</comment>
- <comment xml:lang="hu">Microsoft Visio dokumentum</comment>
- <comment xml:lang="ia">Documento Microsoft Visio</comment>
- <comment xml:lang="id">Dokumen Microsoft Visio</comment>
- <comment xml:lang="it">Documento Microsoft Visio</comment>
- <comment xml:lang="ja">Microsoft Visio ドキュメント</comment>
- <comment xml:lang="ka">Microsoft Visio-ის დოკუმენტი</comment>
- <comment xml:lang="kk">Microsoft Visio құжаты</comment>
- <comment xml:lang="ko">Microsoft Visio 문서</comment>
- <comment xml:lang="lv">Microsoft Visio dokuments</comment>
- <comment xml:lang="nl">Microsoft Visio document</comment>
- <comment xml:lang="oc">document Microsoft Visio</comment>
- <comment xml:lang="pl">Dokument Microsoft Visio</comment>
- <comment xml:lang="pt">documento Microsoft Visio</comment>
- <comment xml:lang="pt_BR">Documento do Microsoft Visio</comment>
- <comment xml:lang="ru">Документ Microsoft Visio</comment>
- <comment xml:lang="sk">Dokument Microsoft Visio</comment>
- <comment xml:lang="sl">Dokument Microsoft Visio</comment>
- <comment xml:lang="sr">документ Мајкрософт Визиа</comment>
- <comment xml:lang="sv">Microsoft Visio-dokument</comment>
- <comment xml:lang="tr">Microsoft Visio belgesi</comment>
- <comment xml:lang="uk">документ Microsoft Visio</comment>
+ <comment xml:lang="zh_TW">微軟 Visio 文件</comment>
<comment xml:lang="zh_CN">Microsoft Visio 文档</comment>
- <comment xml:lang="zh_TW">Microsoft Visio文件</comment>
+ <comment xml:lang="uk">документ Microsoft Visio</comment>
+ <comment xml:lang="tr">Microsoft Visio belgesi</comment>
+ <comment xml:lang="sv">Microsoft Visio-dokument</comment>
+ <comment xml:lang="sr">документ Мајкрософт Визиа</comment>
+ <comment xml:lang="sq">dokument Microsoft Visio</comment>
+ <comment xml:lang="sl">Dokument Microsoft Visio</comment>
+ <comment xml:lang="si">Microsoft Visio ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Microsoft Visio</comment>
+ <comment xml:lang="ru">Документ Microsoft Visio</comment>
+ <comment xml:lang="pt_BR">Documento do Microsoft Visio</comment>
+ <comment xml:lang="pt">documento Microsoft Visio</comment>
+ <comment xml:lang="pl">Dokument Microsoft Visio</comment>
+ <comment xml:lang="oc">document Microsoft Visio</comment>
+ <comment xml:lang="nl">Microsoft Visio document</comment>
+ <comment xml:lang="lv">Microsoft Visio dokuments</comment>
+ <comment xml:lang="ko">Microsoft Visio 문서</comment>
+ <comment xml:lang="kk">Microsoft Visio құжаты</comment>
+ <comment xml:lang="ka">Microsoft Visio-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Microsoft Visio ドキュメント</comment>
+ <comment xml:lang="it">Documento Microsoft Visio</comment>
+ <comment xml:lang="is">Microsoft Visio skjal</comment>
+ <comment xml:lang="id">Dokumen Microsoft Visio</comment>
+ <comment xml:lang="ia">Documento Microsoft Visio</comment>
+ <comment xml:lang="hu">Microsoft Visio dokumentum</comment>
+ <comment xml:lang="hr">Microsoft Visio dokument</comment>
+ <comment xml:lang="he">מסמך Microsoft Visio</comment>
+ <comment xml:lang="gl">Documento de Microsoft Visio</comment>
+ <comment xml:lang="ga">cáipéis Microsoft Visio</comment>
+ <comment xml:lang="fur">document Microsoft Visio</comment>
+ <comment xml:lang="fr">document Microsoft Visio</comment>
+ <comment xml:lang="fi">Microsoft Visio -asiakirja</comment>
+ <comment xml:lang="eu">Microsoft Visio dokumentua</comment>
+ <comment xml:lang="es">documento de Microsoft Visio</comment>
+ <comment xml:lang="en_GB">Microsoft Visio document</comment>
+ <comment xml:lang="el">Έγγραφο Microsoft Visio</comment>
+ <comment xml:lang="de">Microsoft-Visio-Dokument</comment>
+ <comment xml:lang="da">Microsoft Visio-dokument</comment>
+ <comment xml:lang="cs">dokument Microsoft Visio</comment>
+ <comment xml:lang="ca">document de Microsoft Visio</comment>
+ <comment xml:lang="bg">Документ — Microsoft Visio</comment>
+ <comment xml:lang="be">дакумент Microsoft Visio</comment>
+ <comment xml:lang="ast">Documentu de Microsoft Visio</comment>
+ <comment xml:lang="ar">مستند مايكروسوفت فيزو</comment>
+ <comment xml:lang="af">Microsoft Visio-dokument</comment>
<sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.vsd"/>
@@ -4019,66 +4640,72 @@
</mime-type>
<mime-type type="application/msword">
<comment>Word document</comment>
- <comment xml:lang="ar">مستند Word</comment>
- <comment xml:lang="ast">Documentu de Word</comment>
- <comment xml:lang="be@latin">Dakument Word</comment>
- <comment xml:lang="bg">Документ — Word</comment>
- <comment xml:lang="ca">document Word</comment>
- <comment xml:lang="cs">dokument Word</comment>
- <comment xml:lang="da">Worddokument</comment>
- <comment xml:lang="de">Word-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Word</comment>
- <comment xml:lang="en_GB">Word document</comment>
- <comment xml:lang="eo">Word-dokumento</comment>
- <comment xml:lang="es">documento de Word</comment>
- <comment xml:lang="eu">Word dokumentua</comment>
- <comment xml:lang="fi">Word-asiakirja</comment>
- <comment xml:lang="fo">Word skjal</comment>
- <comment xml:lang="fr">document Word</comment>
- <comment xml:lang="ga">cáipéis Word</comment>
- <comment xml:lang="gl">documento de Word</comment>
- <comment xml:lang="he">מסמך Word</comment>
- <comment xml:lang="hr">Word dokument</comment>
- <comment xml:lang="hu">Word dokumentum</comment>
- <comment xml:lang="ia">Documento Word</comment>
- <comment xml:lang="id">Dokumen Word</comment>
- <comment xml:lang="it">Documento Word</comment>
- <comment xml:lang="ja">Word ドキュメント</comment>
- <comment xml:lang="kk">Word құжаты</comment>
- <comment xml:lang="ko">Word 문서</comment>
- <comment xml:lang="lt">Word dokumentas</comment>
- <comment xml:lang="lv">Word dokuments</comment>
- <comment xml:lang="nb">Word-dokument</comment>
- <comment xml:lang="nl">Word-document</comment>
- <comment xml:lang="nn">Word-dokument</comment>
- <comment xml:lang="oc">document Word</comment>
- <comment xml:lang="pl">Dokument Word</comment>
- <comment xml:lang="pt">documento Word</comment>
- <comment xml:lang="pt_BR">Documento do Word</comment>
- <comment xml:lang="ro">Document Word</comment>
- <comment xml:lang="ru">Документ Word</comment>
- <comment xml:lang="sk">Dokument Word</comment>
- <comment xml:lang="sl">Dokument Word</comment>
- <comment xml:lang="sq">Dokument Word</comment>
- <comment xml:lang="sr">Ворд документ</comment>
- <comment xml:lang="sv">Word-dokument</comment>
- <comment xml:lang="tr">Word belgesi</comment>
- <comment xml:lang="uk">документ Word</comment>
- <comment xml:lang="vi">Tài liệu Word</comment>
- <comment xml:lang="zh_CN">Word 文档</comment>
<comment xml:lang="zh_TW">Word 文件</comment>
+ <comment xml:lang="zh_CN">Word 文档</comment>
+ <comment xml:lang="vi">Tài liệu Word</comment>
+ <comment xml:lang="uk">документ Word</comment>
+ <comment xml:lang="tr">Word belgesi</comment>
+ <comment xml:lang="sv">Word-dokument</comment>
+ <comment xml:lang="sr">Ворд документ</comment>
+ <comment xml:lang="sq">dokument Word</comment>
+ <comment xml:lang="sl">Dokument Word</comment>
+ <comment xml:lang="si">වචන ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Word</comment>
+ <comment xml:lang="ru">Документ Word</comment>
+ <comment xml:lang="ro">Document Word</comment>
+ <comment xml:lang="pt_BR">Documento do Word</comment>
+ <comment xml:lang="pt">documento Word</comment>
+ <comment xml:lang="pl">Dokument Word</comment>
+ <comment xml:lang="oc">document Word</comment>
+ <comment xml:lang="nn">Word-dokument</comment>
+ <comment xml:lang="nl">Word-document</comment>
+ <comment xml:lang="nb">Word-dokument</comment>
+ <comment xml:lang="lv">Word dokuments</comment>
+ <comment xml:lang="lt">Word dokumentas</comment>
+ <comment xml:lang="ko">Word 문서</comment>
+ <comment xml:lang="kk">Word құжаты</comment>
+ <comment xml:lang="ka">Word -ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Word ドキュメント</comment>
+ <comment xml:lang="it">Documento Word</comment>
+ <comment xml:lang="is">Word skjal</comment>
+ <comment xml:lang="id">Dokumen Word</comment>
+ <comment xml:lang="ia">Documento Word</comment>
+ <comment xml:lang="hu">Word dokumentum</comment>
+ <comment xml:lang="hr">Word dokument</comment>
+ <comment xml:lang="he">מסמך Word</comment>
+ <comment xml:lang="gl">documento de Word</comment>
+ <comment xml:lang="ga">cáipéis Word</comment>
+ <comment xml:lang="fur">document Word</comment>
+ <comment xml:lang="fr">document Word</comment>
+ <comment xml:lang="fo">Word skjal</comment>
+ <comment xml:lang="fi">Word-asiakirja</comment>
+ <comment xml:lang="eu">Word dokumentua</comment>
+ <comment xml:lang="es">documento de Word</comment>
+ <comment xml:lang="eo">Word-dokumento</comment>
+ <comment xml:lang="en_GB">Word document</comment>
+ <comment xml:lang="el">Έγγραφο Word</comment>
+ <comment xml:lang="de">Word-Dokument</comment>
+ <comment xml:lang="da">Worddokument</comment>
+ <comment xml:lang="cs">dokument Word</comment>
+ <comment xml:lang="ca">document Word</comment>
+ <comment xml:lang="bg">Документ — Word</comment>
+ <comment xml:lang="be@latin">Dakument Word</comment>
+ <comment xml:lang="be">дакумент Word</comment>
+ <comment xml:lang="ast">Documentu de Word</comment>
+ <comment xml:lang="ar">مستند ورد</comment>
+ <comment xml:lang="af">Word-dokument</comment>
<sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-document"/>
<magic priority="60">
- <match value="\x31\xbe\x00\x00" type="string" offset="0"/>
- <match value="PO^Q`" type="string" offset="0"/>
- <match value="\376\067\0\043" type="string" offset="0"/>
- <match value="\333\245-\0\0\0" type="string" offset="0"/>
- <match value="MSWordDoc" type="string" offset="2112"/>
- <match value="MSWordDoc" type="string" offset="2108"/>
- <match value="Microsoft Word document data" type="string" offset="2112"/>
- <match value="bjbj" type="string" offset="546"/>
- <match value="jbjb" type="string" offset="546"/>
+ <match type="string" value="\x31\xbe\x00\x00" offset="0"/>
+ <match type="string" value="PO^Q`" offset="0"/>
+ <match type="string" value="\376\067\0\043" offset="0"/>
+ <match type="string" value="\333\245-\0\0\0" offset="0"/>
+ <match type="string" value="MSWordDoc" offset="2112"/>
+ <match type="string" value="MSWordDoc" offset="2108"/>
+ <match type="string" value="Microsoft Word document data" offset="2112"/>
+ <match type="string" value="bjbj" offset="546"/>
+ <match type="string" value="jbjb" offset="546"/>
</magic>
<glob pattern="*.doc"/>
<alias type="application/vnd.ms-word"/>
@@ -4087,96 +4714,112 @@
</mime-type>
<mime-type type="application/msword-template">
<comment>Word template</comment>
- <comment xml:lang="ar">قالب Word</comment>
- <comment xml:lang="ast">Plantía de Word</comment>
- <comment xml:lang="be@latin">Šablon Word</comment>
- <comment xml:lang="bg">Шаблон за документи — Word</comment>
- <comment xml:lang="ca">plantilla de Word</comment>
- <comment xml:lang="cs">šablona Word</comment>
- <comment xml:lang="da">Wordskabelon</comment>
- <comment xml:lang="de">Word-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο έγγραφο Word</comment>
- <comment xml:lang="en_GB">Word template</comment>
- <comment xml:lang="eo">Word-ŝablono</comment>
- <comment xml:lang="es">plantilla de Word</comment>
- <comment xml:lang="eu">Word txantiloia</comment>
- <comment xml:lang="fi">Word-malli</comment>
- <comment xml:lang="fo">Word formur</comment>
- <comment xml:lang="fr">modèle Word</comment>
- <comment xml:lang="ga">teimpléad Word</comment>
- <comment xml:lang="gl">Plantilla de Word</comment>
- <comment xml:lang="he">תבנית Word</comment>
- <comment xml:lang="hr">Word predložak</comment>
- <comment xml:lang="hu">Word sablon</comment>
- <comment xml:lang="ia">Patrono Word</comment>
- <comment xml:lang="id">Templat Word</comment>
- <comment xml:lang="it">Modello Word</comment>
- <comment xml:lang="ja">Word テンプレート</comment>
- <comment xml:lang="kk">Word үлгісі</comment>
- <comment xml:lang="ko">Word 서식</comment>
- <comment xml:lang="lt">Word šablonas</comment>
- <comment xml:lang="lv">Word veidne</comment>
- <comment xml:lang="nb">Word-mal</comment>
- <comment xml:lang="nl">Word-sjabloon</comment>
- <comment xml:lang="nn">Word-mal</comment>
- <comment xml:lang="oc">modèl Word</comment>
- <comment xml:lang="pl">Szablon Word</comment>
- <comment xml:lang="pt">modelo Word</comment>
- <comment xml:lang="pt_BR">Modelo do Word</comment>
- <comment xml:lang="ro">Șablon Word</comment>
- <comment xml:lang="ru">Шаблон Word</comment>
- <comment xml:lang="sk">Šablóna Word</comment>
- <comment xml:lang="sl">Predloga dokumenta Microsoft Word</comment>
- <comment xml:lang="sq">Model Word</comment>
- <comment xml:lang="sr">Ворд шаблон</comment>
- <comment xml:lang="sv">Word-mall</comment>
- <comment xml:lang="tr">Word şablonu</comment>
- <comment xml:lang="uk">шаблон Word</comment>
- <comment xml:lang="vi">Mẫu Word</comment>
- <comment xml:lang="zh_CN">Word 模板</comment>
<comment xml:lang="zh_TW">Word 範本</comment>
+ <comment xml:lang="zh_CN">Word 模板</comment>
+ <comment xml:lang="vi">Mẫu Word</comment>
+ <comment xml:lang="uk">шаблон Word</comment>
+ <comment xml:lang="tr">Word şablonu</comment>
+ <comment xml:lang="sv">Word-mall</comment>
+ <comment xml:lang="sr">Ворд шаблон</comment>
+ <comment xml:lang="sq">gjedhe Word</comment>
+ <comment xml:lang="sl">Predloga dokumenta Microsoft Word</comment>
+ <comment xml:lang="si">වචන සැකිල්ල</comment>
+ <comment xml:lang="sk">Šablóna Word</comment>
+ <comment xml:lang="ru">Шаблон Word</comment>
+ <comment xml:lang="ro">Șablon Word</comment>
+ <comment xml:lang="pt_BR">Modelo do Word</comment>
+ <comment xml:lang="pt">modelo Word</comment>
+ <comment xml:lang="pl">Szablon Word</comment>
+ <comment xml:lang="oc">modèl Word</comment>
+ <comment xml:lang="nn">Word-mal</comment>
+ <comment xml:lang="nl">Word-sjabloon</comment>
+ <comment xml:lang="nb">Word-mal</comment>
+ <comment xml:lang="lv">Word veidne</comment>
+ <comment xml:lang="lt">Word šablonas</comment>
+ <comment xml:lang="ko">Word 서식</comment>
+ <comment xml:lang="kk">Word үлгісі</comment>
+ <comment xml:lang="ja">Word テンプレート</comment>
+ <comment xml:lang="it">Modello Word</comment>
+ <comment xml:lang="is">Word sniðmát</comment>
+ <comment xml:lang="id">Templat Word</comment>
+ <comment xml:lang="ia">Patrono Word</comment>
+ <comment xml:lang="hu">Word sablon</comment>
+ <comment xml:lang="hr">Word predložak</comment>
+ <comment xml:lang="he">תבנית Word</comment>
+ <comment xml:lang="gl">Plantilla de Word</comment>
+ <comment xml:lang="ga">teimpléad Word</comment>
+ <comment xml:lang="fur">model Word</comment>
+ <comment xml:lang="fr">modèle Word</comment>
+ <comment xml:lang="fo">Word formur</comment>
+ <comment xml:lang="fi">Word-malli</comment>
+ <comment xml:lang="eu">Word txantiloia</comment>
+ <comment xml:lang="es">plantilla de Word</comment>
+ <comment xml:lang="eo">Word-ŝablono</comment>
+ <comment xml:lang="en_GB">Word template</comment>
+ <comment xml:lang="el">Πρότυπο έγγραφο Word</comment>
+ <comment xml:lang="de">Word-Vorlage</comment>
+ <comment xml:lang="da">Wordskabelon</comment>
+ <comment xml:lang="cs">šablona Word</comment>
+ <comment xml:lang="ca">plantilla de Word</comment>
+ <comment xml:lang="bg">Шаблон за документи — Word</comment>
+ <comment xml:lang="be@latin">Šablon Word</comment>
+ <comment xml:lang="be">шаблон Word</comment>
+ <comment xml:lang="ast">Plantía de Word</comment>
+ <comment xml:lang="ar">قالب ورد</comment>
+ <comment xml:lang="af">Word-sjabloon</comment>
<sub-class-of type="application/msword"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.dot"/>
</mime-type>
<mime-type type="application/gml+xml">
<comment>GML document</comment>
- <comment xml:lang="ast">Documentu GML</comment>
- <comment xml:lang="ca">document GML</comment>
- <comment xml:lang="cs">dokument GML</comment>
- <comment xml:lang="da">GML-dokument</comment>
- <comment xml:lang="de">GML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο GML</comment>
- <comment xml:lang="en_GB">GML document</comment>
- <comment xml:lang="es">documento GML</comment>
- <comment xml:lang="eu">GML dokumentua</comment>
- <comment xml:lang="fi">GML-asiakirja</comment>
- <comment xml:lang="fr">document GML</comment>
- <comment xml:lang="ga">cáipéis GML</comment>
- <comment xml:lang="gl">Documento GML</comment>
- <comment xml:lang="he">מסמך GML</comment>
- <comment xml:lang="hr">GML dokument</comment>
- <comment xml:lang="hu">GML dokumentum</comment>
- <comment xml:lang="ia">Documento GML</comment>
- <comment xml:lang="id">Dokumen GML</comment>
- <comment xml:lang="it">Documento GML</comment>
- <comment xml:lang="ja">GML ドキュメント</comment>
- <comment xml:lang="kk">GML құжаты</comment>
- <comment xml:lang="ko">GML 문서</comment>
- <comment xml:lang="lv">GML dokuments</comment>
- <comment xml:lang="oc">document GML</comment>
- <comment xml:lang="pl">Dokument GML</comment>
- <comment xml:lang="pt">documento GML</comment>
- <comment xml:lang="pt_BR">Documento GML</comment>
- <comment xml:lang="ru">Документ GML</comment>
- <comment xml:lang="sk">Dokument GML</comment>
- <comment xml:lang="sl">Dokument GML</comment>
- <comment xml:lang="sr">ГМЛ документ</comment>
- <comment xml:lang="sv">GML-dokument</comment>
- <comment xml:lang="tr">GML belgesi</comment>
- <comment xml:lang="uk">документ GML</comment>
- <comment xml:lang="zh_CN">GML 文档</comment>
<comment xml:lang="zh_TW">GML 文件</comment>
+ <comment xml:lang="zh_CN">GML 文档</comment>
+ <comment xml:lang="uk">документ GML</comment>
+ <comment xml:lang="tr">GML belgesi</comment>
+ <comment xml:lang="sv">GML-dokument</comment>
+ <comment xml:lang="sr">ГМЛ документ</comment>
+ <comment xml:lang="sq">dokument GML</comment>
+ <comment xml:lang="sl">Dokument GML</comment>
+ <comment xml:lang="si">GML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument GML</comment>
+ <comment xml:lang="ru">Документ GML</comment>
+ <comment xml:lang="pt_BR">Documento GML</comment>
+ <comment xml:lang="pt">documento GML</comment>
+ <comment xml:lang="pl">Dokument GML</comment>
+ <comment xml:lang="oc">document GML</comment>
+ <comment xml:lang="nl">GML-document</comment>
+ <comment xml:lang="lv">GML dokuments</comment>
+ <comment xml:lang="lt">GML dokumentas</comment>
+ <comment xml:lang="ko">GML 문서</comment>
+ <comment xml:lang="kk">GML құжаты</comment>
+ <comment xml:lang="ka">GML -ის დოკუმენტი</comment>
+ <comment xml:lang="ja">GML ドキュメント</comment>
+ <comment xml:lang="it">Documento GML</comment>
+ <comment xml:lang="is">GML skjal</comment>
+ <comment xml:lang="id">Dokumen GML</comment>
+ <comment xml:lang="ia">Documento GML</comment>
+ <comment xml:lang="hu">GML dokumentum</comment>
+ <comment xml:lang="hr">GML dokument</comment>
+ <comment xml:lang="he">מסמך GML</comment>
+ <comment xml:lang="gl">Documento GML</comment>
+ <comment xml:lang="ga">cáipéis GML</comment>
+ <comment xml:lang="fur">document GML</comment>
+ <comment xml:lang="fr">document GML</comment>
+ <comment xml:lang="fi">GML-asiakirja</comment>
+ <comment xml:lang="eu">GML dokumentua</comment>
+ <comment xml:lang="es">documento GML</comment>
+ <comment xml:lang="en_GB">GML document</comment>
+ <comment xml:lang="el">Έγγραφο GML</comment>
+ <comment xml:lang="de">GML-Dokument</comment>
+ <comment xml:lang="da">GML-dokument</comment>
+ <comment xml:lang="cs">dokument GML</comment>
+ <comment xml:lang="ca">document GML</comment>
+ <comment xml:lang="bg">Документ — GML</comment>
+ <comment xml:lang="be">дакумент GML</comment>
+ <comment xml:lang="ast">Documentu GML</comment>
+ <comment xml:lang="ar">مستند GML</comment>
+ <comment xml:lang="af">GML-dokument</comment>
<acronym>GML</acronym>
<expanded-acronym>Geography Markup Language</expanded-acronym>
<glob pattern="*.gml"/>
@@ -4185,111 +4828,121 @@
</mime-type>
<mime-type type="application/gnunet-directory">
<comment>GNUnet search file</comment>
- <comment xml:lang="ar">ملف بحث GNUnet</comment>
- <comment xml:lang="be@latin">fajł pošuku GNUnet</comment>
- <comment xml:lang="bg">Указател за търсене — GNUnet</comment>
- <comment xml:lang="ca">fitxer de cerca GNUnet</comment>
- <comment xml:lang="cs">vyhledávací soubor GNUnet</comment>
- <comment xml:lang="da">GNunet-søgefil</comment>
- <comment xml:lang="de">GNUnet-Suchdatei</comment>
- <comment xml:lang="el">Αρχείο αναζήτησης GNUnet</comment>
- <comment xml:lang="en_GB">GNUnet search file</comment>
- <comment xml:lang="es">archivo de búsqueda GNUnet</comment>
- <comment xml:lang="eu">GNUnet bilaketako fitxategia</comment>
- <comment xml:lang="fi">GNUnet-hakutiedosto</comment>
- <comment xml:lang="fo">GNUnet leitifíla</comment>
- <comment xml:lang="fr">fichier de recherche GNUnet</comment>
- <comment xml:lang="ga">comhad cuardaigh GNUnet</comment>
- <comment xml:lang="gl">ficheiro de busca de GNUnet</comment>
- <comment xml:lang="he">קובץ חיפוש של GNUnet</comment>
- <comment xml:lang="hr">GNUnet datoteka pretrage</comment>
- <comment xml:lang="hu">GNUnet keresési fájl</comment>
- <comment xml:lang="ia">File de recerca GNUnet</comment>
- <comment xml:lang="id">Berkas telusur GNUnet</comment>
- <comment xml:lang="it">File ricerca GNUnet</comment>
- <comment xml:lang="ja">GNUnet 検索ファイル</comment>
- <comment xml:lang="ka">GNUnet ძებნის ფაილი</comment>
- <comment xml:lang="kk">GNUnet іздеу файлы</comment>
- <comment xml:lang="ko">GNUnet 검색 파일</comment>
- <comment xml:lang="lt">GNUnet paieškos failas</comment>
- <comment xml:lang="lv">GNUnet meklēšanas datne</comment>
- <comment xml:lang="nb">GNUnet søkefil</comment>
- <comment xml:lang="nl">GNUnet-zoekbestand</comment>
- <comment xml:lang="nn">GNUnet-søkjefil</comment>
- <comment xml:lang="oc">fichièr de recèrca GNUnet</comment>
- <comment xml:lang="pl">Plik wyszukiwania GNUnet</comment>
- <comment xml:lang="pt">ficheiro de procura GNUnet</comment>
- <comment xml:lang="pt_BR">Arquivo de pesquisa do GNUnet</comment>
- <comment xml:lang="ro">Fișier căutare GNUnet</comment>
- <comment xml:lang="ru">Файл поиска GNUnet</comment>
- <comment xml:lang="sk">Vyhľadávací súbor GNUnet</comment>
- <comment xml:lang="sl">Iskalna datoteka GNUnet</comment>
- <comment xml:lang="sq">File kërkimi GNUnet</comment>
- <comment xml:lang="sr">ГНУнет датотека претраге</comment>
- <comment xml:lang="sv">GNUnet-sökfil</comment>
- <comment xml:lang="tr">GNUnet arama dosyası</comment>
- <comment xml:lang="uk">файл пошуку GNUnet</comment>
- <comment xml:lang="vi">Tập tin tìm kiếm GNUnet</comment>
- <comment xml:lang="zh_CN">GNUnet 搜索文件</comment>
<comment xml:lang="zh_TW">GNUnet 搜尋檔案</comment>
- <magic priority="50">
- <match value="\211GND\r\n\032\n" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">GNUnet 搜索文件</comment>
+ <comment xml:lang="vi">Tập tin tìm kiếm GNUnet</comment>
+ <comment xml:lang="uk">файл пошуку GNUnet</comment>
+ <comment xml:lang="tr">GNUnet arama dosyası</comment>
+ <comment xml:lang="sv">GNUnet-sökfil</comment>
+ <comment xml:lang="sr">ГНУнет датотека претраге</comment>
+ <comment xml:lang="sq">kartelë kërkimi GNUnet</comment>
+ <comment xml:lang="sl">Iskalna datoteka GNUnet</comment>
+ <comment xml:lang="si">GNUnet සෙවුම් ගොනුව</comment>
+ <comment xml:lang="sk">Vyhľadávací súbor GNUnet</comment>
+ <comment xml:lang="ru">Файл поиска GNUnet</comment>
+ <comment xml:lang="ro">Fișier căutare GNUnet</comment>
+ <comment xml:lang="pt_BR">Arquivo de pesquisa do GNUnet</comment>
+ <comment xml:lang="pt">ficheiro de procura GNUnet</comment>
+ <comment xml:lang="pl">Plik wyszukiwania GNUnet</comment>
+ <comment xml:lang="oc">fichièr de recèrca GNUnet</comment>
+ <comment xml:lang="nn">GNUnet-søkjefil</comment>
+ <comment xml:lang="nl">GNUnet-zoekbestand</comment>
+ <comment xml:lang="nb">GNUnet søkefil</comment>
+ <comment xml:lang="lv">GNUnet meklēšanas datne</comment>
+ <comment xml:lang="lt">GNUnet paieškos failas</comment>
+ <comment xml:lang="ko">GNUnet 검색 파일</comment>
+ <comment xml:lang="kk">GNUnet іздеу файлы</comment>
+ <comment xml:lang="ka">GNUnet ძებნის ფაილი</comment>
+ <comment xml:lang="ja">GNUnet 検索ファイル</comment>
+ <comment xml:lang="it">File ricerca GNUnet</comment>
+ <comment xml:lang="is">GNUnet leitarskrá</comment>
+ <comment xml:lang="id">Berkas telusur GNUnet</comment>
+ <comment xml:lang="ia">File de recerca GNUnet</comment>
+ <comment xml:lang="hu">GNUnet keresési fájl</comment>
+ <comment xml:lang="hr">GNUnet datoteka pretrage</comment>
+ <comment xml:lang="he">קובץ חיפוש של GNUnet</comment>
+ <comment xml:lang="gl">ficheiro de busca de GNUnet</comment>
+ <comment xml:lang="ga">comhad cuardaigh GNUnet</comment>
+ <comment xml:lang="fur">file di ricercje GNUnet</comment>
+ <comment xml:lang="fr">fichier de recherche GNUnet</comment>
+ <comment xml:lang="fo">GNUnet leitifíla</comment>
+ <comment xml:lang="fi">GNUnet-hakutiedosto</comment>
+ <comment xml:lang="eu">GNUnet bilaketako fitxategia</comment>
+ <comment xml:lang="es">archivo de búsqueda GNUnet</comment>
+ <comment xml:lang="en_GB">GNUnet search file</comment>
+ <comment xml:lang="el">Αρχείο αναζήτησης GNUnet</comment>
+ <comment xml:lang="de">GNUnet-Suchdatei</comment>
+ <comment xml:lang="da">GNunet-søgefil</comment>
+ <comment xml:lang="cs">vyhledávací soubor GNUnet</comment>
+ <comment xml:lang="ca">fitxer de cerca GNUnet</comment>
+ <comment xml:lang="bg">Указател за търсене — GNUnet</comment>
+ <comment xml:lang="be@latin">fajł pošuku GNUnet</comment>
+ <comment xml:lang="be">файл пошуку GNUnet</comment>
+ <comment xml:lang="ar">ملف بحث GNUnet</comment>
+ <comment xml:lang="af">GNUnet-soeklêer</comment>
+ <magic>
+ <match type="string" value="\211GND\r\n\032\n" offset="0"/>
</magic>
<glob pattern="*.gnd"/>
</mime-type>
<mime-type type="application/vnd.ms-tnef">
<comment>TNEF message</comment>
- <comment xml:lang="ar">رسالة TNEF</comment>
- <comment xml:lang="ast">Mensaxe TNEF</comment>
- <comment xml:lang="be@latin">List TNEF</comment>
- <comment xml:lang="bg">Съобщение — TNEF</comment>
- <comment xml:lang="ca">missatge TNEF</comment>
- <comment xml:lang="cs">zpráva TNEF</comment>
- <comment xml:lang="da">TNEF-meddelelse</comment>
- <comment xml:lang="de">TNEF-Nachricht</comment>
- <comment xml:lang="el">Μήνυμα TNEF</comment>
- <comment xml:lang="en_GB">TNEF message</comment>
- <comment xml:lang="es">mensaje TNEF</comment>
- <comment xml:lang="eu">TNEF mezua</comment>
- <comment xml:lang="fi">TNEF-viesti</comment>
- <comment xml:lang="fo">TNEF boð</comment>
- <comment xml:lang="fr">message TNEF</comment>
- <comment xml:lang="ga">teachtaireacht TNEF</comment>
- <comment xml:lang="gl">mensaxe TNEF</comment>
- <comment xml:lang="he">הודעת TNEF</comment>
- <comment xml:lang="hr">TNEF poruka</comment>
- <comment xml:lang="hu">TNEF üzenet</comment>
- <comment xml:lang="ia">Message TNEF</comment>
- <comment xml:lang="id">Pesan TNEF</comment>
- <comment xml:lang="it">Messaggio TNEF</comment>
- <comment xml:lang="ja">TNEF メッセージ</comment>
- <comment xml:lang="kk">TNEF мәлімдемесі</comment>
- <comment xml:lang="ko">TNEF 메시지</comment>
- <comment xml:lang="lt">TNEF žinutė</comment>
- <comment xml:lang="lv">TNEF ziņojums</comment>
- <comment xml:lang="nb">TNEF-melding</comment>
- <comment xml:lang="nl">TNEF-bericht</comment>
- <comment xml:lang="nn">TNEF-melding</comment>
- <comment xml:lang="oc">messatge TNEF</comment>
- <comment xml:lang="pl">Wiadomość TNEF</comment>
- <comment xml:lang="pt">mensagem TNEF</comment>
- <comment xml:lang="pt_BR">Mensagem TNEF</comment>
- <comment xml:lang="ro">Mesaj TNEF</comment>
- <comment xml:lang="ru">Сообщение TNEF</comment>
- <comment xml:lang="sk">Správa TNEF</comment>
- <comment xml:lang="sl">Datoteka sporočila TNEF</comment>
- <comment xml:lang="sq">Mesazh TNEF</comment>
- <comment xml:lang="sr">ТНЕФ порука</comment>
- <comment xml:lang="sv">TNEF-meddelande</comment>
- <comment xml:lang="tr">TNEF iletisi</comment>
- <comment xml:lang="uk">повідомлення TNEF</comment>
- <comment xml:lang="vi">Thông điệp TNEF</comment>
- <comment xml:lang="zh_CN">TNEF 信件</comment>
<comment xml:lang="zh_TW">TNEF 訊息</comment>
+ <comment xml:lang="zh_CN">TNEF 信件</comment>
+ <comment xml:lang="vi">Thông điệp TNEF</comment>
+ <comment xml:lang="uk">повідомлення TNEF</comment>
+ <comment xml:lang="tr">TNEF iletisi</comment>
+ <comment xml:lang="sv">TNEF-meddelande</comment>
+ <comment xml:lang="sr">ТНЕФ порука</comment>
+ <comment xml:lang="sq">mesazh TNEF</comment>
+ <comment xml:lang="sl">Datoteka sporočila TNEF</comment>
+ <comment xml:lang="si">TNEF පණිවිඩය</comment>
+ <comment xml:lang="sk">Správa TNEF</comment>
+ <comment xml:lang="ru">Сообщение TNEF</comment>
+ <comment xml:lang="ro">Mesaj TNEF</comment>
+ <comment xml:lang="pt_BR">Mensagem TNEF</comment>
+ <comment xml:lang="pt">mensagem TNEF</comment>
+ <comment xml:lang="pl">Wiadomość TNEF</comment>
+ <comment xml:lang="oc">messatge TNEF</comment>
+ <comment xml:lang="nn">TNEF-melding</comment>
+ <comment xml:lang="nl">TNEF-bericht</comment>
+ <comment xml:lang="nb">TNEF-melding</comment>
+ <comment xml:lang="lv">TNEF ziņojums</comment>
+ <comment xml:lang="lt">TNEF žinutė</comment>
+ <comment xml:lang="ko">TNEF 메시지</comment>
+ <comment xml:lang="kk">TNEF мәлімдемесі</comment>
+ <comment xml:lang="ja">TNEF メッセージ</comment>
+ <comment xml:lang="it">Messaggio TNEF</comment>
+ <comment xml:lang="is">TNEF skilaboð</comment>
+ <comment xml:lang="id">Pesan TNEF</comment>
+ <comment xml:lang="ia">Message TNEF</comment>
+ <comment xml:lang="hu">TNEF üzenet</comment>
+ <comment xml:lang="hr">TNEF poruka</comment>
+ <comment xml:lang="he">הודעת TNEF</comment>
+ <comment xml:lang="gl">mensaxe TNEF</comment>
+ <comment xml:lang="ga">teachtaireacht TNEF</comment>
+ <comment xml:lang="fur">messaç TNEF</comment>
+ <comment xml:lang="fr">message TNEF</comment>
+ <comment xml:lang="fo">TNEF boð</comment>
+ <comment xml:lang="fi">TNEF-viesti</comment>
+ <comment xml:lang="eu">TNEF mezua</comment>
+ <comment xml:lang="es">mensaje TNEF</comment>
+ <comment xml:lang="en_GB">TNEF message</comment>
+ <comment xml:lang="el">Μήνυμα TNEF</comment>
+ <comment xml:lang="de">TNEF-Nachricht</comment>
+ <comment xml:lang="da">TNEF-meddelelse</comment>
+ <comment xml:lang="cs">zpráva TNEF</comment>
+ <comment xml:lang="ca">missatge TNEF</comment>
+ <comment xml:lang="bg">Съобщение — TNEF</comment>
+ <comment xml:lang="be@latin">List TNEF</comment>
+ <comment xml:lang="be">паведамленне TNEF</comment>
+ <comment xml:lang="ast">Mensaxe TNEF</comment>
+ <comment xml:lang="ar">رسالة TNEF</comment>
+ <comment xml:lang="af">TNEF-boodskap</comment>
<acronym>TNEF</acronym>
<expanded-acronym>Transport Neutral Encapsulation Format</expanded-acronym>
- <magic priority="50">
- <match value="0x223e9f78" type="little32" offset="0"/>
+ <magic>
+ <match type="little32" value="0x223e9f78" offset="0"/>
</magic>
<glob pattern="*.tnef"/>
<glob pattern="*.tnf"/>
@@ -4298,998 +4951,662 @@
</mime-type>
<mime-type type="application/vnd.stardivision.calc">
<comment>StarCalc spreadsheet</comment>
- <comment xml:lang="ar">جدول StarCalc</comment>
- <comment xml:lang="az">StarCalc hesab cədvəli</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš StarCalc</comment>
- <comment xml:lang="bg">Таблица — StarCalc</comment>
- <comment xml:lang="ca">full de càlcul de StarCalc</comment>
- <comment xml:lang="cs">sešit StarCalc</comment>
- <comment xml:lang="cy">Taenlen StarCalc</comment>
- <comment xml:lang="da">StarCalc-regneark</comment>
- <comment xml:lang="de">StarCalc-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο StarCalc</comment>
- <comment xml:lang="en_GB">StarCalc spreadsheet</comment>
- <comment xml:lang="eo">StarCalc-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo de StarCalc</comment>
- <comment xml:lang="eu">StarCalc kalkulu-orria</comment>
- <comment xml:lang="fi">StarCalc-taulukko</comment>
- <comment xml:lang="fo">StarCalc rokniark</comment>
- <comment xml:lang="fr">feuille de calcul StarCalc</comment>
- <comment xml:lang="ga">scarbhileog StarCalc</comment>
- <comment xml:lang="gl">folla de cálculo de StarCalc</comment>
- <comment xml:lang="he">גליון נתונים של StarCalc</comment>
- <comment xml:lang="hr">StarCalc proračunska tablica</comment>
- <comment xml:lang="hu">StarCalc-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo StarCalc</comment>
- <comment xml:lang="id">Lembar sebar StarCalc</comment>
- <comment xml:lang="it">Foglio di calcolo StarCalc</comment>
- <comment xml:lang="ja">StarCalc スプレッドシート</comment>
- <comment xml:lang="kk">StarCalc электрондық кестесі</comment>
- <comment xml:lang="ko">StarCalc 스프레드시트</comment>
- <comment xml:lang="lt">StarCalc skaičialentė</comment>
- <comment xml:lang="lv">StarCalc izklājlapa</comment>
- <comment xml:lang="ms">Hamparan StarCalc</comment>
- <comment xml:lang="nb">StarCalc-regneark</comment>
- <comment xml:lang="nl">StarCalc-rekenblad</comment>
- <comment xml:lang="nn">StarCalc-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul StarCalc</comment>
- <comment xml:lang="pl">Arkusz StarCalc</comment>
- <comment xml:lang="pt">folha de cálculo do StarCalc</comment>
- <comment xml:lang="pt_BR">Planilha do StarCalc</comment>
- <comment xml:lang="ro">Foaie de calcul StarCalc</comment>
- <comment xml:lang="ru">Электронная таблица StarCalc</comment>
- <comment xml:lang="sk">Zošit StarCalc</comment>
- <comment xml:lang="sl">Preglednica StarCalc</comment>
- <comment xml:lang="sq">Fletë llogaritjesh StarCalc</comment>
- <comment xml:lang="sr">Стар калк табела</comment>
- <comment xml:lang="sv">StarCalc-kalkylblad</comment>
- <comment xml:lang="tr">StarCalc çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця StarCalc</comment>
- <comment xml:lang="vi">Bảng tính StarCalc</comment>
- <comment xml:lang="zh_CN">StarCalc 电子表格</comment>
<comment xml:lang="zh_TW">StarCalc 試算表</comment>
+ <comment xml:lang="zh_CN">StarCalc 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính StarCalc</comment>
+ <comment xml:lang="uk">електронна таблиця StarCalc</comment>
+ <comment xml:lang="tr">StarCalc hesap çizelgesi</comment>
+ <comment xml:lang="sv">StarCalc-kalkylblad</comment>
+ <comment xml:lang="sr">Стар калк табела</comment>
+ <comment xml:lang="sq">fletëllogaritje StarCalc</comment>
+ <comment xml:lang="sl">Preglednica StarCalc</comment>
+ <comment xml:lang="si">StarCalc පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit StarCalc</comment>
+ <comment xml:lang="ru">Электронная таблица StarCalc</comment>
+ <comment xml:lang="ro">Foaie de calcul StarCalc</comment>
+ <comment xml:lang="pt_BR">Planilha do StarCalc</comment>
+ <comment xml:lang="pt">folha de cálculo do StarCalc</comment>
+ <comment xml:lang="pl">Arkusz StarCalc</comment>
+ <comment xml:lang="oc">fuèlh de calcul StarCalc</comment>
+ <comment xml:lang="nn">StarCalc-rekneark</comment>
+ <comment xml:lang="nl">StarCalc-rekenblad</comment>
+ <comment xml:lang="nb">StarCalc-regneark</comment>
+ <comment xml:lang="ms">Hamparan StarCalc</comment>
+ <comment xml:lang="lv">StarCalc izklājlapa</comment>
+ <comment xml:lang="lt">StarCalc skaičialentė</comment>
+ <comment xml:lang="ko">StarCalc 스프레드시트</comment>
+ <comment xml:lang="kk">StarCalc электрондық кестесі</comment>
+ <comment xml:lang="ja">StarCalc スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo StarCalc</comment>
+ <comment xml:lang="is">StarCalc töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar StarCalc</comment>
+ <comment xml:lang="ia">Folio de calculo StarCalc</comment>
+ <comment xml:lang="hu">StarCalc-munkafüzet</comment>
+ <comment xml:lang="hr">StarCalc proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של StarCalc</comment>
+ <comment xml:lang="gl">folla de cálculo de StarCalc</comment>
+ <comment xml:lang="ga">scarbhileog StarCalc</comment>
+ <comment xml:lang="fur">sfuei di calcul StarCalc</comment>
+ <comment xml:lang="fr">feuille de calcul StarCalc</comment>
+ <comment xml:lang="fo">StarCalc rokniark</comment>
+ <comment xml:lang="fi">StarCalc-taulukko</comment>
+ <comment xml:lang="eu">StarCalc kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de StarCalc</comment>
+ <comment xml:lang="eo">StarCalc-kalkultabelo</comment>
+ <comment xml:lang="en_GB">StarCalc spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο StarCalc</comment>
+ <comment xml:lang="de">StarCalc-Tabelle</comment>
+ <comment xml:lang="da">StarCalc-regneark</comment>
+ <comment xml:lang="cy">Taenlen StarCalc</comment>
+ <comment xml:lang="cs">sešit StarCalc</comment>
+ <comment xml:lang="ca">full de càlcul de StarCalc</comment>
+ <comment xml:lang="bg">Таблица — StarCalc</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš StarCalc</comment>
+ <comment xml:lang="be">электронная табліца StarCalc</comment>
+ <comment xml:lang="az">StarCalc hesab cədvəli</comment>
+ <comment xml:lang="ar">جدول StarCalc</comment>
+ <comment xml:lang="af">StarCalc-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.sdc"/>
</mime-type>
<mime-type type="application/vnd.stardivision.chart">
<comment>StarChart chart</comment>
- <comment xml:lang="ar">مخطط StarChart</comment>
- <comment xml:lang="az">StarChart cədvəli</comment>
- <comment xml:lang="be@latin">Dyjahrama StarChart</comment>
- <comment xml:lang="bg">Диаграма — StarChart</comment>
- <comment xml:lang="ca">diagrama de StarChart</comment>
- <comment xml:lang="cs">graf StarChart</comment>
- <comment xml:lang="cy">Siart StarChart</comment>
- <comment xml:lang="da">StarChart-diagram</comment>
- <comment xml:lang="de">StarChart-Diagramm</comment>
- <comment xml:lang="el">Γράφημα StarChart</comment>
- <comment xml:lang="en_GB">StarChart chart</comment>
- <comment xml:lang="eo">StarChart-diagramo</comment>
- <comment xml:lang="es">gráfico de StarChart</comment>
- <comment xml:lang="eu">StarChart diagrama</comment>
- <comment xml:lang="fi">StarChart-kaavio</comment>
- <comment xml:lang="fo">StarChart strikumynd</comment>
- <comment xml:lang="fr">graphique StarChart</comment>
- <comment xml:lang="ga">cairt StarChart</comment>
- <comment xml:lang="gl">gráfica de StarChart</comment>
- <comment xml:lang="he">טבלה של StarChart</comment>
- <comment xml:lang="hr">StarChart grafikon</comment>
- <comment xml:lang="hu">StarChart-grafikon</comment>
- <comment xml:lang="ia">Graphico StarChart</comment>
- <comment xml:lang="id">Bagan StarChart</comment>
- <comment xml:lang="it">Grafico StarChart</comment>
- <comment xml:lang="ja">StarChart チャート</comment>
- <comment xml:lang="kk">StarChart диаграммасы</comment>
- <comment xml:lang="ko">StarCalc 표</comment>
- <comment xml:lang="lt">StarChart diagrama</comment>
- <comment xml:lang="lv">StarChart diagramma</comment>
- <comment xml:lang="ms">Carta StarChart</comment>
- <comment xml:lang="nb">StarChart graf</comment>
- <comment xml:lang="nl">StarChart-kaart</comment>
- <comment xml:lang="nn">StarChart-graf</comment>
- <comment xml:lang="oc">grafic StarChart</comment>
- <comment xml:lang="pl">Wykres StarChart</comment>
- <comment xml:lang="pt">gráfico do StarChart</comment>
- <comment xml:lang="pt_BR">Gráfico do StarChart</comment>
- <comment xml:lang="ro">Diagramă StarChart</comment>
- <comment xml:lang="ru">Диаграмма StarChart</comment>
- <comment xml:lang="sk">Graf StarChart</comment>
- <comment xml:lang="sl">Datoteka grafikona StarChart</comment>
- <comment xml:lang="sq">Grafik StarChart</comment>
- <comment xml:lang="sr">График Стар Графика</comment>
- <comment xml:lang="sv">StarChart-diagram</comment>
- <comment xml:lang="tr">StarChart çizgelgesi</comment>
- <comment xml:lang="uk">діаграма StarChart</comment>
- <comment xml:lang="vi">Đồ thị StarChart</comment>
- <comment xml:lang="zh_CN">StarCalc 图表</comment>
<comment xml:lang="zh_TW">StarChart 圖表</comment>
+ <comment xml:lang="zh_CN">StarCalc 图表</comment>
+ <comment xml:lang="vi">Đồ thị StarChart</comment>
+ <comment xml:lang="uk">діаграма StarChart</comment>
+ <comment xml:lang="tr">StarChart çizgesi</comment>
+ <comment xml:lang="sv">StarChart-diagram</comment>
+ <comment xml:lang="sr">График Стар Графика</comment>
+ <comment xml:lang="sq">grafik StarChart</comment>
+ <comment xml:lang="sl">Datoteka grafikona StarChart</comment>
+ <comment xml:lang="si">StarChart සටහන</comment>
+ <comment xml:lang="sk">Graf StarChart</comment>
+ <comment xml:lang="ru">Диаграмма StarChart</comment>
+ <comment xml:lang="ro">Diagramă StarChart</comment>
+ <comment xml:lang="pt_BR">Gráfico do StarChart</comment>
+ <comment xml:lang="pt">gráfico do StarChart</comment>
+ <comment xml:lang="pl">Wykres StarChart</comment>
+ <comment xml:lang="oc">grafic StarChart</comment>
+ <comment xml:lang="nn">StarChart-graf</comment>
+ <comment xml:lang="nl">StarChart-kaart</comment>
+ <comment xml:lang="nb">StarChart graf</comment>
+ <comment xml:lang="ms">Carta StarChart</comment>
+ <comment xml:lang="lv">StarChart diagramma</comment>
+ <comment xml:lang="lt">StarChart diagrama</comment>
+ <comment xml:lang="ko">StarCalc 표</comment>
+ <comment xml:lang="kk">StarChart диаграммасы</comment>
+ <comment xml:lang="ja">StarChart チャート</comment>
+ <comment xml:lang="it">Grafico StarChart</comment>
+ <comment xml:lang="is">StarChart kort</comment>
+ <comment xml:lang="id">Bagan StarChart</comment>
+ <comment xml:lang="ia">Graphico StarChart</comment>
+ <comment xml:lang="hu">StarChart-grafikon</comment>
+ <comment xml:lang="hr">StarChart grafikon</comment>
+ <comment xml:lang="he">טבלת StarChart</comment>
+ <comment xml:lang="gl">gráfica de StarChart</comment>
+ <comment xml:lang="ga">cairt StarChart</comment>
+ <comment xml:lang="fur">grafic StarChart</comment>
+ <comment xml:lang="fr">graphique StarChart</comment>
+ <comment xml:lang="fo">StarChart strikumynd</comment>
+ <comment xml:lang="fi">StarChart-kaavio</comment>
+ <comment xml:lang="eu">StarChart diagrama</comment>
+ <comment xml:lang="es">gráfico de StarChart</comment>
+ <comment xml:lang="eo">StarChart-diagramo</comment>
+ <comment xml:lang="en_GB">StarChart chart</comment>
+ <comment xml:lang="el">Γράφημα StarChart</comment>
+ <comment xml:lang="de">StarChart-Diagramm</comment>
+ <comment xml:lang="da">StarChart-diagram</comment>
+ <comment xml:lang="cy">Siart StarChart</comment>
+ <comment xml:lang="cs">graf StarChart</comment>
+ <comment xml:lang="ca">diagrama de StarChart</comment>
+ <comment xml:lang="bg">Диаграма — StarChart</comment>
+ <comment xml:lang="be@latin">Dyjahrama StarChart</comment>
+ <comment xml:lang="be">дыяграма StarChart</comment>
+ <comment xml:lang="az">StarChart cədvəli</comment>
+ <comment xml:lang="ar">مخطط StarChart</comment>
+ <comment xml:lang="af">StarChart-grafiek</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.sds"/>
</mime-type>
<mime-type type="application/vnd.stardivision.draw">
<comment>StarDraw drawing</comment>
- <comment xml:lang="ar">تصميم StarDraw</comment>
- <comment xml:lang="az">StarDraw çəkimi</comment>
- <comment xml:lang="be@latin">Rysunak StarDraw</comment>
- <comment xml:lang="bg">Чертеж — StarDraw</comment>
- <comment xml:lang="ca">dibuix de StarDraw</comment>
- <comment xml:lang="cs">kresba StarDraw</comment>
- <comment xml:lang="cy">Darlun StarDraw</comment>
- <comment xml:lang="da">StarDraw-tegning</comment>
- <comment xml:lang="de">StarDraw-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο StarDraw</comment>
- <comment xml:lang="en_GB">StarDraw drawing</comment>
- <comment xml:lang="eo">StarDraw-grafikaĵo</comment>
- <comment xml:lang="es">dibujo de StarDraw</comment>
- <comment xml:lang="eu">StarDraw marrazkia</comment>
- <comment xml:lang="fi">StarDraw-piirros</comment>
- <comment xml:lang="fo">StarDraw tekning</comment>
- <comment xml:lang="fr">dessin StarDraw</comment>
- <comment xml:lang="ga">líníocht StarDraw</comment>
- <comment xml:lang="gl">debuxo de StarDraw</comment>
- <comment xml:lang="he">ציור של StarDrawing</comment>
- <comment xml:lang="hr">StarDraw crtež</comment>
- <comment xml:lang="hu">StarDraw-rajz</comment>
- <comment xml:lang="ia">Designo StarDraw</comment>
- <comment xml:lang="id">Gambar StarDraw</comment>
- <comment xml:lang="it">Disegno StarDraw</comment>
- <comment xml:lang="ja">StarDraw ドロー</comment>
- <comment xml:lang="kk">StarDraw суреті</comment>
- <comment xml:lang="ko">StarCalc 드로잉</comment>
- <comment xml:lang="lt">StarDraw piešinys</comment>
- <comment xml:lang="lv">StarDraw zīmējums</comment>
- <comment xml:lang="ms">Lukisan StarDraw</comment>
- <comment xml:lang="nb">StarDraw tegning</comment>
- <comment xml:lang="nl">StarDraw-tekening</comment>
- <comment xml:lang="nn">StarDraw-teikning</comment>
- <comment xml:lang="oc">dessenh StarDraw</comment>
- <comment xml:lang="pl">Rysunek StarDraw</comment>
- <comment xml:lang="pt">desenho do StarDraw</comment>
- <comment xml:lang="pt_BR">Desenho do StarDraw</comment>
- <comment xml:lang="ro">Desen StarDraw</comment>
- <comment xml:lang="ru">Рисунок StarDraw</comment>
- <comment xml:lang="sk">Kresba StarDraw</comment>
- <comment xml:lang="sl">Datoteka risbe StarDraw</comment>
- <comment xml:lang="sq">Vizatim StarDraw</comment>
- <comment xml:lang="sr">Цртеж Стар Цртежа</comment>
- <comment xml:lang="sv">StarDraw-teckning</comment>
- <comment xml:lang="tr">StarDraw çizimi</comment>
- <comment xml:lang="uk">малюнок StarDraw</comment>
- <comment xml:lang="vi">Bản vẽ StarDraw</comment>
- <comment xml:lang="zh_CN">StarDraw 绘图</comment>
<comment xml:lang="zh_TW">StarDraw 繪圖</comment>
+ <comment xml:lang="zh_CN">StarDraw 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ StarDraw</comment>
+ <comment xml:lang="uk">малюнок StarDraw</comment>
+ <comment xml:lang="tr">StarDraw çizimi</comment>
+ <comment xml:lang="sv">StarDraw-teckning</comment>
+ <comment xml:lang="sr">Цртеж Стар Цртежа</comment>
+ <comment xml:lang="sq">vizatim StarDraw</comment>
+ <comment xml:lang="sl">Datoteka risbe StarDraw</comment>
+ <comment xml:lang="si">StarDraw ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba StarDraw</comment>
+ <comment xml:lang="ru">Рисунок StarDraw</comment>
+ <comment xml:lang="ro">Desen StarDraw</comment>
+ <comment xml:lang="pt_BR">Desenho do StarDraw</comment>
+ <comment xml:lang="pt">desenho do StarDraw</comment>
+ <comment xml:lang="pl">Rysunek StarDraw</comment>
+ <comment xml:lang="oc">dessenh StarDraw</comment>
+ <comment xml:lang="nn">StarDraw-teikning</comment>
+ <comment xml:lang="nl">StarDraw-tekening</comment>
+ <comment xml:lang="nb">StarDraw tegning</comment>
+ <comment xml:lang="ms">Lukisan StarDraw</comment>
+ <comment xml:lang="lv">StarDraw zīmējums</comment>
+ <comment xml:lang="lt">StarDraw piešinys</comment>
+ <comment xml:lang="ko">StarCalc 드로잉</comment>
+ <comment xml:lang="kk">StarDraw суреті</comment>
+ <comment xml:lang="ja">StarDraw ドロー</comment>
+ <comment xml:lang="it">Disegno StarDraw</comment>
+ <comment xml:lang="is">StarDraw teikning</comment>
+ <comment xml:lang="id">Gambar StarDraw</comment>
+ <comment xml:lang="ia">Designo StarDraw</comment>
+ <comment xml:lang="hu">StarDraw-rajz</comment>
+ <comment xml:lang="hr">StarDraw crtež</comment>
+ <comment xml:lang="he">ציור StarDrawing</comment>
+ <comment xml:lang="gl">debuxo de StarDraw</comment>
+ <comment xml:lang="ga">líníocht StarDraw</comment>
+ <comment xml:lang="fur">dissen StarDraw</comment>
+ <comment xml:lang="fr">dessin StarDraw</comment>
+ <comment xml:lang="fo">StarDraw tekning</comment>
+ <comment xml:lang="fi">StarDraw-piirros</comment>
+ <comment xml:lang="eu">StarDraw marrazkia</comment>
+ <comment xml:lang="es">dibujo de StarDraw</comment>
+ <comment xml:lang="eo">StarDraw-grafikaĵo</comment>
+ <comment xml:lang="en_GB">StarDraw drawing</comment>
+ <comment xml:lang="el">Σχέδιο StarDraw</comment>
+ <comment xml:lang="de">StarDraw-Zeichnung</comment>
+ <comment xml:lang="da">StarDraw-tegning</comment>
+ <comment xml:lang="cy">Darlun StarDraw</comment>
+ <comment xml:lang="cs">kresba StarDraw</comment>
+ <comment xml:lang="ca">dibuix de StarDraw</comment>
+ <comment xml:lang="bg">Чертеж — StarDraw</comment>
+ <comment xml:lang="be@latin">Rysunak StarDraw</comment>
+ <comment xml:lang="be">рысунак StarDraw</comment>
+ <comment xml:lang="az">StarDraw çəkimi</comment>
+ <comment xml:lang="ar">تصميم StarDraw</comment>
+ <comment xml:lang="af">StarDraw-tekening</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.sda"/>
</mime-type>
<mime-type type="application/vnd.stardivision.impress">
<comment>StarImpress presentation</comment>
- <comment xml:lang="ar">عرض تقديمي StarImpress</comment>
- <comment xml:lang="az">StarImpress təqdimatı</comment>
- <comment xml:lang="be@latin">Prezentacyja StarImpress</comment>
- <comment xml:lang="bg">Презентация — StarImpress</comment>
- <comment xml:lang="ca">presentació de StarImpress</comment>
- <comment xml:lang="cs">prezentace StarImpress</comment>
- <comment xml:lang="cy">Cyflwyniad StarImpress</comment>
- <comment xml:lang="da">StarImpress-præsentation</comment>
- <comment xml:lang="de">StarImpress-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση StarImpress</comment>
- <comment xml:lang="en_GB">StarImpress presentation</comment>
- <comment xml:lang="eo">StarImpress-prezentaĵo</comment>
- <comment xml:lang="es">presentación de StarImpress</comment>
- <comment xml:lang="eu">StarImpress aurkezpena</comment>
- <comment xml:lang="fi">StarImpress-esitys</comment>
- <comment xml:lang="fo">StarImpress framløga</comment>
- <comment xml:lang="fr">présentation StarImpress</comment>
- <comment xml:lang="ga">láithreoireacht StarImpress</comment>
- <comment xml:lang="gl">presentación de StarImpress</comment>
- <comment xml:lang="he">מצגת של StarImpress</comment>
- <comment xml:lang="hr">StarImpress prezentacija</comment>
- <comment xml:lang="hu">StarImpress-bemutató</comment>
- <comment xml:lang="ia">Presentation StarImpress</comment>
- <comment xml:lang="id">Presentasi StarImpress</comment>
- <comment xml:lang="it">Presentazione StarImpress</comment>
- <comment xml:lang="ja">StarImpress プレゼンテーション</comment>
- <comment xml:lang="kk">StarImpress презентациясы</comment>
- <comment xml:lang="ko">StarImpress 프레젠테이션</comment>
- <comment xml:lang="lt">StarImpress pateiktis</comment>
- <comment xml:lang="lv">StarImpress prezentācija</comment>
- <comment xml:lang="ms">Persembahan StarImpress</comment>
- <comment xml:lang="nb">StarImpress-presentasjon</comment>
- <comment xml:lang="nl">StarImpress-presentatie</comment>
- <comment xml:lang="nn">StarImpress-presentasjon</comment>
- <comment xml:lang="oc">presentacion StarImpress</comment>
- <comment xml:lang="pl">Prezentacja StarImpress</comment>
- <comment xml:lang="pt">apresentação do StarImpress</comment>
- <comment xml:lang="pt_BR">Apresentação do StarImpress</comment>
- <comment xml:lang="ro">Prezentare StarImpress</comment>
- <comment xml:lang="ru">Презентация StarImpress</comment>
- <comment xml:lang="sk">Prezentácia StarImpress</comment>
- <comment xml:lang="sl">Predstavitev StarImpress</comment>
- <comment xml:lang="sq">Prezantim StarImpress</comment>
- <comment xml:lang="sr">Презентација Стар Импреса</comment>
- <comment xml:lang="sv">StarImpress-presentation</comment>
- <comment xml:lang="tr">StarImpress sunumu</comment>
- <comment xml:lang="uk">презентація StarImpress</comment>
- <comment xml:lang="vi">Trình diễn StarImpress</comment>
+ <comment xml:lang="zh_TW">StarImpress 簡報</comment>
<comment xml:lang="zh_CN">StarImpress 演示文稿</comment>
- <comment xml:lang="zh_TW">StarImpress 簡報檔</comment>
+ <comment xml:lang="vi">Trình diễn StarImpress</comment>
+ <comment xml:lang="uk">презентація StarImpress</comment>
+ <comment xml:lang="tr">StarImpress sunumu</comment>
+ <comment xml:lang="sv">StarImpress-presentation</comment>
+ <comment xml:lang="sr">Презентација Стар Импреса</comment>
+ <comment xml:lang="sq">paraqitje StarImpress</comment>
+ <comment xml:lang="sl">Predstavitev StarImpress</comment>
+ <comment xml:lang="si">StarImpress ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia StarImpress</comment>
+ <comment xml:lang="ru">Презентация StarImpress</comment>
+ <comment xml:lang="ro">Prezentare StarImpress</comment>
+ <comment xml:lang="pt_BR">Apresentação do StarImpress</comment>
+ <comment xml:lang="pt">apresentação do StarImpress</comment>
+ <comment xml:lang="pl">Prezentacja StarImpress</comment>
+ <comment xml:lang="oc">presentacion StarImpress</comment>
+ <comment xml:lang="nn">StarImpress-presentasjon</comment>
+ <comment xml:lang="nl">StarImpress-presentatie</comment>
+ <comment xml:lang="nb">StarImpress-presentasjon</comment>
+ <comment xml:lang="ms">Persembahan StarImpress</comment>
+ <comment xml:lang="lv">StarImpress prezentācija</comment>
+ <comment xml:lang="lt">StarImpress pateiktis</comment>
+ <comment xml:lang="ko">StarImpress 프레젠테이션</comment>
+ <comment xml:lang="kk">StarImpress презентациясы</comment>
+ <comment xml:lang="ja">StarImpress プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione StarImpress</comment>
+ <comment xml:lang="is">StarImpress framsetning</comment>
+ <comment xml:lang="id">Presentasi StarImpress</comment>
+ <comment xml:lang="ia">Presentation StarImpress</comment>
+ <comment xml:lang="hu">StarImpress-bemutató</comment>
+ <comment xml:lang="hr">StarImpress prezentacija</comment>
+ <comment xml:lang="he">מצגת StarImpress</comment>
+ <comment xml:lang="gl">presentación de StarImpress</comment>
+ <comment xml:lang="ga">láithreoireacht StarImpress</comment>
+ <comment xml:lang="fur">presentazion StarImpress</comment>
+ <comment xml:lang="fr">présentation StarImpress</comment>
+ <comment xml:lang="fo">StarImpress framløga</comment>
+ <comment xml:lang="fi">StarImpress-esitys</comment>
+ <comment xml:lang="eu">StarImpress aurkezpena</comment>
+ <comment xml:lang="es">presentación de StarImpress</comment>
+ <comment xml:lang="eo">StarImpress-prezentaĵo</comment>
+ <comment xml:lang="en_GB">StarImpress presentation</comment>
+ <comment xml:lang="el">Παρουσίαση StarImpress</comment>
+ <comment xml:lang="de">StarImpress-Präsentation</comment>
+ <comment xml:lang="da">StarImpress-præsentation</comment>
+ <comment xml:lang="cy">Cyflwyniad StarImpress</comment>
+ <comment xml:lang="cs">prezentace StarImpress</comment>
+ <comment xml:lang="ca">presentació de StarImpress</comment>
+ <comment xml:lang="bg">Презентация — StarImpress</comment>
+ <comment xml:lang="be@latin">Prezentacyja StarImpress</comment>
+ <comment xml:lang="be">прэзентацыя StarImpress</comment>
+ <comment xml:lang="az">StarImpress təqdimatı</comment>
+ <comment xml:lang="ar">عرض تقديمي StarImpress</comment>
+ <comment xml:lang="af">StarImpress-voorlegging</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.sdd"/>
<glob pattern="*.sdp"/>
</mime-type>
<mime-type type="application/vnd.stardivision.mail">
<comment>StarMail email</comment>
- <comment xml:lang="ar">بريد StarMail الإلكتروني</comment>
- <comment xml:lang="be@latin">Email StarMail</comment>
- <comment xml:lang="bg">Електронно писмо — StarMail</comment>
- <comment xml:lang="ca">correu electrònic de StarMail</comment>
- <comment xml:lang="cs">e-mail StarMail</comment>
- <comment xml:lang="da">StarMail-e-brev</comment>
- <comment xml:lang="de">StarMail-E-Mail</comment>
- <comment xml:lang="el">Ηλ. μήνυμα StarMail</comment>
- <comment xml:lang="en_GB">StarMail email</comment>
- <comment xml:lang="eo">StarMail-retpoŝto</comment>
- <comment xml:lang="es">correo electrónico de StarMail</comment>
- <comment xml:lang="eu">StarMail helb.el.</comment>
- <comment xml:lang="fi">StarMail-sähköposti</comment>
- <comment xml:lang="fo">StarMail t-postur</comment>
- <comment xml:lang="fr">courriel StarMail</comment>
- <comment xml:lang="ga">ríomhphost StarMail</comment>
- <comment xml:lang="gl">Correo electrónico de StarMail</comment>
- <comment xml:lang="he">דוא״ל של StarMail</comment>
- <comment xml:lang="hr">StarMail e-pošta</comment>
- <comment xml:lang="hu">StarMail e-mail</comment>
- <comment xml:lang="ia">Message electronic StarMail</comment>
- <comment xml:lang="id">Email StarMail</comment>
- <comment xml:lang="it">Email StarMail</comment>
- <comment xml:lang="ja">StarMail メール</comment>
- <comment xml:lang="kk">StarMail электрондық хаты</comment>
- <comment xml:lang="ko">StarMail 전자우편</comment>
- <comment xml:lang="lt">StarMail el. laiškas</comment>
- <comment xml:lang="lv">StarMail epasts</comment>
- <comment xml:lang="ms">Emel StarMail</comment>
- <comment xml:lang="nb">StarMail-melding</comment>
- <comment xml:lang="nl">StarMail-e-mail</comment>
- <comment xml:lang="nn">StarMail-fil</comment>
- <comment xml:lang="oc">corrièr electronic StarMail</comment>
- <comment xml:lang="pl">E-Mail StarMail</comment>
- <comment xml:lang="pt">email do StarMail</comment>
- <comment xml:lang="pt_BR">E-mail do StarMail</comment>
- <comment xml:lang="ro">Email StarEmail</comment>
- <comment xml:lang="ru">Электронное письмо StarMail</comment>
- <comment xml:lang="sk">E-mail StarMail</comment>
- <comment xml:lang="sl">Datoteka pošte StarMail</comment>
- <comment xml:lang="sq">Mesazh StarMail</comment>
- <comment xml:lang="sr">Ел. пошта Стар Поште</comment>
- <comment xml:lang="sv">StarMail-e-post</comment>
- <comment xml:lang="tr">StarMail epostası</comment>
- <comment xml:lang="uk">поштове повідомлення StarMail</comment>
- <comment xml:lang="vi">Thư điện tử StarMail</comment>
- <comment xml:lang="zh_CN">StarMail 电子邮件</comment>
<comment xml:lang="zh_TW">StarMail 郵件</comment>
+ <comment xml:lang="zh_CN">StarMail 电子邮件</comment>
+ <comment xml:lang="vi">Thư điện tử StarMail</comment>
+ <comment xml:lang="uk">поштове повідомлення StarMail</comment>
+ <comment xml:lang="tr">StarMail epostası</comment>
+ <comment xml:lang="sv">StarMail-e-post</comment>
+ <comment xml:lang="sr">Ел. пошта Стар Поште</comment>
+ <comment xml:lang="sq">email StarMail</comment>
+ <comment xml:lang="sl">Datoteka pošte StarMail</comment>
+ <comment xml:lang="si">StarMail ඊමේල්</comment>
+ <comment xml:lang="sk">E-mail StarMail</comment>
+ <comment xml:lang="ru">Электронное письмо StarMail</comment>
+ <comment xml:lang="ro">Email StarEmail</comment>
+ <comment xml:lang="pt_BR">E-mail do StarMail</comment>
+ <comment xml:lang="pt">email do StarMail</comment>
+ <comment xml:lang="pl">E-Mail StarMail</comment>
+ <comment xml:lang="oc">corrièr electronic StarMail</comment>
+ <comment xml:lang="nn">StarMail-fil</comment>
+ <comment xml:lang="nl">StarMail-e-mail</comment>
+ <comment xml:lang="nb">StarMail-melding</comment>
+ <comment xml:lang="ms">Emel StarMail</comment>
+ <comment xml:lang="lv">StarMail epasts</comment>
+ <comment xml:lang="lt">StarMail el. laiškas</comment>
+ <comment xml:lang="ko">StarMail 전자우편</comment>
+ <comment xml:lang="kk">StarMail электрондық хаты</comment>
+ <comment xml:lang="ja">StarMail メール</comment>
+ <comment xml:lang="it">Email StarMail</comment>
+ <comment xml:lang="is">StarMail tölvupóstur</comment>
+ <comment xml:lang="id">Email StarMail</comment>
+ <comment xml:lang="ia">Message electronic StarMail</comment>
+ <comment xml:lang="hu">StarMail e-mail</comment>
+ <comment xml:lang="hr">StarMail e-pošta</comment>
+ <comment xml:lang="he">דוא״ל של StarMail</comment>
+ <comment xml:lang="gl">Correo electrónico de StarMail</comment>
+ <comment xml:lang="ga">ríomhphost StarMail</comment>
+ <comment xml:lang="fur">e-mail StarMail</comment>
+ <comment xml:lang="fr">courriel StarMail</comment>
+ <comment xml:lang="fo">StarMail t-postur</comment>
+ <comment xml:lang="fi">StarMail-sähköposti</comment>
+ <comment xml:lang="eu">StarMail helb.el.</comment>
+ <comment xml:lang="es">correo electrónico de StarMail</comment>
+ <comment xml:lang="eo">StarMail-retpoŝto</comment>
+ <comment xml:lang="en_GB">StarMail e-mail</comment>
+ <comment xml:lang="el">Ηλ. μήνυμα StarMail</comment>
+ <comment xml:lang="de">StarMail-E-Mail</comment>
+ <comment xml:lang="da">StarMail-e-brev</comment>
+ <comment xml:lang="cs">e-mail StarMail</comment>
+ <comment xml:lang="ca">correu electrònic de StarMail</comment>
+ <comment xml:lang="bg">Електронно писмо — StarMail</comment>
+ <comment xml:lang="be@latin">Email StarMail</comment>
+ <comment xml:lang="be">Email StarMail</comment>
+ <comment xml:lang="ar">بريد إلكتروني StarMail</comment>
+ <comment xml:lang="af">StarMail-e-pos</comment>
<glob pattern="*.smd"/>
</mime-type>
<mime-type type="application/vnd.stardivision.math">
<comment>StarMath formula</comment>
- <comment xml:lang="ar">صيغة StarMath</comment>
- <comment xml:lang="be@latin">Formuła StarMath</comment>
- <comment xml:lang="bg">Формула — StarMath</comment>
- <comment xml:lang="ca">fórmula de StarMath</comment>
- <comment xml:lang="cs">vzorec StarMath</comment>
- <comment xml:lang="da">StarMath-formel</comment>
- <comment xml:lang="de">StarMath-Formel</comment>
- <comment xml:lang="el">Μαθηματικός τύπος StarMath</comment>
- <comment xml:lang="en_GB">StarMath formula</comment>
- <comment xml:lang="eo">StarMath-formulo</comment>
- <comment xml:lang="es">fórmula de StarMath</comment>
- <comment xml:lang="eu">StarMath formula</comment>
- <comment xml:lang="fi">StarMath-kaava</comment>
- <comment xml:lang="fo">StarMath frymil</comment>
- <comment xml:lang="fr">formule StarMath</comment>
- <comment xml:lang="ga">foirmle StarMath</comment>
- <comment xml:lang="gl">fórmula de StarMath</comment>
- <comment xml:lang="he">נוסחה של StarMath</comment>
- <comment xml:lang="hr">StarMath formula</comment>
- <comment xml:lang="hu">StarMath-képlet</comment>
- <comment xml:lang="ia">Formula StarMath</comment>
- <comment xml:lang="id">Formula StarMath</comment>
- <comment xml:lang="it">Formula StarMath</comment>
- <comment xml:lang="ja">StarMath 計算式</comment>
- <comment xml:lang="kk">StarMath формуласы</comment>
- <comment xml:lang="ko">StarMath 수식</comment>
- <comment xml:lang="lt">StarMath formulė</comment>
- <comment xml:lang="lv">StarMath formula</comment>
- <comment xml:lang="ms">Formula StarMath</comment>
- <comment xml:lang="nb">StarMath-formel</comment>
- <comment xml:lang="nl">StarMath-formule</comment>
- <comment xml:lang="nn">StarMath-formel</comment>
- <comment xml:lang="oc">formula StarMath</comment>
- <comment xml:lang="pl">Formuła StarMath</comment>
- <comment xml:lang="pt">fórmula do StarMath</comment>
- <comment xml:lang="pt_BR">Fórmula do StarMath</comment>
- <comment xml:lang="ro">Formulă StarMath</comment>
- <comment xml:lang="ru">Формула StarMath</comment>
- <comment xml:lang="sk">Vzorec StarMath</comment>
- <comment xml:lang="sl">Datoteka formule StarMath</comment>
- <comment xml:lang="sq">Formulë StarMath</comment>
- <comment xml:lang="sr">Формула Стар Математике</comment>
- <comment xml:lang="sv">StarMath-formel</comment>
- <comment xml:lang="tr">StarMath formülü</comment>
- <comment xml:lang="uk">формула StarMath</comment>
- <comment xml:lang="vi">Công thức StarMath</comment>
- <comment xml:lang="zh_CN">StarMath 公式</comment>
<comment xml:lang="zh_TW">StarMath 公式</comment>
+ <comment xml:lang="zh_CN">StarMath 公式</comment>
+ <comment xml:lang="vi">Công thức StarMath</comment>
+ <comment xml:lang="uk">формула StarMath</comment>
+ <comment xml:lang="tr">StarMath formülü</comment>
+ <comment xml:lang="sv">StarMath-formel</comment>
+ <comment xml:lang="sr">Формула Стар Математике</comment>
+ <comment xml:lang="sq">formulë StarMath</comment>
+ <comment xml:lang="sl">Datoteka formule StarMath</comment>
+ <comment xml:lang="si">StarMath සූත්‍රය</comment>
+ <comment xml:lang="sk">Vzorec StarMath</comment>
+ <comment xml:lang="ru">Формула StarMath</comment>
+ <comment xml:lang="ro">Formulă StarMath</comment>
+ <comment xml:lang="pt_BR">Fórmula do StarMath</comment>
+ <comment xml:lang="pt">fórmula do StarMath</comment>
+ <comment xml:lang="pl">Formuła StarMath</comment>
+ <comment xml:lang="oc">formula StarMath</comment>
+ <comment xml:lang="nn">StarMath-formel</comment>
+ <comment xml:lang="nl">StarMath-formule</comment>
+ <comment xml:lang="nb">StarMath-formel</comment>
+ <comment xml:lang="ms">Formula StarMath</comment>
+ <comment xml:lang="lv">StarMath formula</comment>
+ <comment xml:lang="lt">StarMath formulė</comment>
+ <comment xml:lang="ko">StarMath 수식</comment>
+ <comment xml:lang="kk">StarMath формуласы</comment>
+ <comment xml:lang="ja">StarMath 計算式</comment>
+ <comment xml:lang="it">Formula StarMath</comment>
+ <comment xml:lang="is">StarMath formúla</comment>
+ <comment xml:lang="id">Formula StarMath</comment>
+ <comment xml:lang="ia">Formula StarMath</comment>
+ <comment xml:lang="hu">StarMath-képlet</comment>
+ <comment xml:lang="hr">StarMath formula</comment>
+ <comment xml:lang="he">נוסחה של StarMath</comment>
+ <comment xml:lang="gl">fórmula de StarMath</comment>
+ <comment xml:lang="ga">foirmle StarMath</comment>
+ <comment xml:lang="fur">formule StarMath</comment>
+ <comment xml:lang="fr">formule StarMath</comment>
+ <comment xml:lang="fo">StarMath frymil</comment>
+ <comment xml:lang="fi">StarMath-kaava</comment>
+ <comment xml:lang="eu">StarMath formula</comment>
+ <comment xml:lang="es">fórmula de StarMath</comment>
+ <comment xml:lang="eo">StarMath-formulo</comment>
+ <comment xml:lang="en_GB">StarMath formula</comment>
+ <comment xml:lang="el">Μαθηματικός τύπος StarMath</comment>
+ <comment xml:lang="de">StarMath-Formel</comment>
+ <comment xml:lang="da">StarMath-formel</comment>
+ <comment xml:lang="cs">vzorec StarMath</comment>
+ <comment xml:lang="ca">fórmula de StarMath</comment>
+ <comment xml:lang="bg">Формула — StarMath</comment>
+ <comment xml:lang="be@latin">Formuła StarMath</comment>
+ <comment xml:lang="be">формула StarMath</comment>
+ <comment xml:lang="ar">صيغة StarMath</comment>
+ <comment xml:lang="af">StarMath-formule</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.smf"/>
</mime-type>
<mime-type type="application/vnd.stardivision.writer">
<comment>StarWriter document</comment>
- <comment xml:lang="ar">مستند StarWriter</comment>
- <comment xml:lang="ast">Documentu de StarWriter</comment>
- <comment xml:lang="az">StarWriter sənədi</comment>
- <comment xml:lang="be@latin">Dakument StarWriter</comment>
- <comment xml:lang="bg">Документ — StarWriter</comment>
- <comment xml:lang="ca">document StarWriter</comment>
- <comment xml:lang="cs">dokument StarWriter</comment>
- <comment xml:lang="cy">Dogfen StarWriter</comment>
- <comment xml:lang="da">StarWriter-dokument</comment>
- <comment xml:lang="de">StarWriter-Dokument</comment>
- <comment xml:lang="el">Έγγραφο StarWriter</comment>
- <comment xml:lang="en_GB">StarWriter document</comment>
- <comment xml:lang="eo">StarWriter-dokumento</comment>
- <comment xml:lang="es">documento de StarWriter</comment>
- <comment xml:lang="eu">StarWriter dokumentua</comment>
- <comment xml:lang="fi">StarWriter-asiakirja</comment>
- <comment xml:lang="fo">StarWriter skjal</comment>
- <comment xml:lang="fr">document StarWriter</comment>
- <comment xml:lang="ga">cáipéis StarWriter</comment>
- <comment xml:lang="gl">documento de StarWriter</comment>
- <comment xml:lang="he">מסמך של StarWriter</comment>
- <comment xml:lang="hr">StarWriter dokument</comment>
- <comment xml:lang="hu">StarWriter-dokumentum</comment>
- <comment xml:lang="ia">Documento StarWriter</comment>
- <comment xml:lang="id">Dokumen StarWriter</comment>
- <comment xml:lang="it">Documento StrarWriter</comment>
- <comment xml:lang="ja">StarWriter ドキュメント</comment>
- <comment xml:lang="kk">StarWriter құжаты</comment>
- <comment xml:lang="ko">StarWriter 문서</comment>
- <comment xml:lang="lt">StarWriter dokumentas</comment>
- <comment xml:lang="lv">StarWriter dokuments</comment>
- <comment xml:lang="ms">Dokumen StarWriter</comment>
- <comment xml:lang="nb">StarWriter-dokument</comment>
- <comment xml:lang="nl">StarWriter-document</comment>
- <comment xml:lang="nn">StarWriter document</comment>
- <comment xml:lang="oc">document StarWriter</comment>
- <comment xml:lang="pl">Dokument StarWriter</comment>
- <comment xml:lang="pt">documento do StarWriter</comment>
- <comment xml:lang="pt_BR">Documento do StarWriter</comment>
- <comment xml:lang="ro">Document StarWriter</comment>
- <comment xml:lang="ru">Документ StarWriter</comment>
- <comment xml:lang="sk">Dokument StarWriter</comment>
- <comment xml:lang="sl">Dokument StarWriter</comment>
- <comment xml:lang="sq">Dokument StarWriter</comment>
- <comment xml:lang="sr">Документ Стар Писца</comment>
- <comment xml:lang="sv">StarWriter-dokument</comment>
- <comment xml:lang="tr">StarWriter belgesi</comment>
- <comment xml:lang="uk">документ StarWriter</comment>
- <comment xml:lang="vi">Tài liệu StarWriter</comment>
- <comment xml:lang="zh_CN">StarWriter 文档</comment>
<comment xml:lang="zh_TW">StarWriter 文件</comment>
+ <comment xml:lang="zh_CN">StarWriter 文档</comment>
+ <comment xml:lang="vi">Tài liệu StarWriter</comment>
+ <comment xml:lang="uk">документ StarWriter</comment>
+ <comment xml:lang="tr">StarWriter belgesi</comment>
+ <comment xml:lang="sv">StarWriter-dokument</comment>
+ <comment xml:lang="sr">Документ Стар Писца</comment>
+ <comment xml:lang="sq">dokument StarWriter</comment>
+ <comment xml:lang="sl">Dokument StarWriter</comment>
+ <comment xml:lang="si">StarWriter ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument StarWriter</comment>
+ <comment xml:lang="ru">Документ StarWriter</comment>
+ <comment xml:lang="ro">Document StarWriter</comment>
+ <comment xml:lang="pt_BR">Documento do StarWriter</comment>
+ <comment xml:lang="pt">documento do StarWriter</comment>
+ <comment xml:lang="pl">Dokument StarWriter</comment>
+ <comment xml:lang="oc">document StarWriter</comment>
+ <comment xml:lang="nn">StarWriter document</comment>
+ <comment xml:lang="nl">StarWriter-document</comment>
+ <comment xml:lang="nb">StarWriter-dokument</comment>
+ <comment xml:lang="ms">Dokumen StarWriter</comment>
+ <comment xml:lang="lv">StarWriter dokuments</comment>
+ <comment xml:lang="lt">StarWriter dokumentas</comment>
+ <comment xml:lang="ko">StarWriter 문서</comment>
+ <comment xml:lang="kk">StarWriter құжаты</comment>
+ <comment xml:lang="ja">StarWriter ドキュメント</comment>
+ <comment xml:lang="it">Documento StrarWriter</comment>
+ <comment xml:lang="is">StarWriter skjal</comment>
+ <comment xml:lang="id">Dokumen StarWriter</comment>
+ <comment xml:lang="ia">Documento StarWriter</comment>
+ <comment xml:lang="hu">StarWriter-dokumentum</comment>
+ <comment xml:lang="hr">StarWriter dokument</comment>
+ <comment xml:lang="he">מסמך StarWriter</comment>
+ <comment xml:lang="gl">documento de StarWriter</comment>
+ <comment xml:lang="ga">cáipéis StarWriter</comment>
+ <comment xml:lang="fur">document StarWriter</comment>
+ <comment xml:lang="fr">document StarWriter</comment>
+ <comment xml:lang="fo">StarWriter skjal</comment>
+ <comment xml:lang="fi">StarWriter-asiakirja</comment>
+ <comment xml:lang="eu">StarWriter dokumentua</comment>
+ <comment xml:lang="es">documento de StarWriter</comment>
+ <comment xml:lang="eo">StarWriter-dokumento</comment>
+ <comment xml:lang="en_GB">StarWriter document</comment>
+ <comment xml:lang="el">Έγγραφο StarWriter</comment>
+ <comment xml:lang="de">StarWriter-Dokument</comment>
+ <comment xml:lang="da">StarWriter-dokument</comment>
+ <comment xml:lang="cy">Dogfen StarWriter</comment>
+ <comment xml:lang="cs">dokument StarWriter</comment>
+ <comment xml:lang="ca">document StarWriter</comment>
+ <comment xml:lang="bg">Документ — StarWriter</comment>
+ <comment xml:lang="be@latin">Dakument StarWriter</comment>
+ <comment xml:lang="be">дакумент StarWriter</comment>
+ <comment xml:lang="az">StarWriter sənədi</comment>
+ <comment xml:lang="ast">Documentu de StarWriter</comment>
+ <comment xml:lang="ar">مستند StarWriter</comment>
+ <comment xml:lang="af">StarWriter-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.sdw"/>
<glob pattern="*.vor"/>
<glob pattern="*.sgl"/>
<magic priority="90">
- <match value="StarWriter" type="string" offset="2089"/>
+ <match type="string" value="StarWriter" offset="2089"/>
</magic>
<alias type="application/vnd.stardivision.writer-global"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.calc">
- <comment>OpenOffice Calc spreadsheet</comment>
- <comment xml:lang="ar">جدول Calc المكتب المفتوح</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš OpenOffice Calc</comment>
- <comment xml:lang="bg">Таблица — OpenOffice Calc</comment>
- <comment xml:lang="ca">full de càlcul d'OpenOffice Calc</comment>
- <comment xml:lang="cs">sešit OpenOffice Calc</comment>
- <comment xml:lang="da">OpenOffice Calc-regneark</comment>
- <comment xml:lang="de">OpenOffice-Calc-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο OpenOffice Calc</comment>
- <comment xml:lang="en_GB">OpenOffice Calc spreadsheet</comment>
- <comment xml:lang="es">hoja de cálculo de OpenOffice Calc</comment>
- <comment xml:lang="eu">OpenOffice.org Calc kalkulu-orria</comment>
- <comment xml:lang="fi">OpenOffice Calc -taulukko</comment>
- <comment xml:lang="fo">OpenOffice Calc rokniark</comment>
- <comment xml:lang="fr">feuille de calcul OpenOffice Calc</comment>
- <comment xml:lang="ga">scarbhileog OpenOffice Calc</comment>
- <comment xml:lang="gl">folla de cálculo de OpenOffice Calc</comment>
- <comment xml:lang="he">גליון נתונים של OpenOffice Calc</comment>
- <comment xml:lang="hr">OpenOffice Calc proračunska tablica</comment>
- <comment xml:lang="hu">OpenOffice Calc táblázat</comment>
- <comment xml:lang="ia">Folio de calculo OpenOffice Calc</comment>
- <comment xml:lang="id">Lembar sebar OpenOffice Calc</comment>
- <comment xml:lang="it">Foglio di calcolo OpenOffice Calc</comment>
- <comment xml:lang="ja">OpenOffice Calc スプレッドシート</comment>
- <comment xml:lang="ka">OpenOffice Calc-ის ცხრილი</comment>
- <comment xml:lang="kk">OpenOffice Calc электрондық кестесі</comment>
- <comment xml:lang="ko">OpenOffice Calc 스프레드시트</comment>
- <comment xml:lang="lt">OpenOffice Calc skaičialentė</comment>
- <comment xml:lang="lv">OpenOffice Calc izklājlapa</comment>
- <comment xml:lang="nb">OpenOffice Calc-regneark</comment>
- <comment xml:lang="nl">OpenOffice.org Calc-rekenblad</comment>
- <comment xml:lang="nn">OpenOffice Calc-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul OpenOffice Calc</comment>
- <comment xml:lang="pl">Arkusz kalkulacyjny OpenOffice.org Calc</comment>
- <comment xml:lang="pt">folha de cálculo OpenOffice Calc</comment>
- <comment xml:lang="pt_BR">Planilha do OpenOffice Calc</comment>
- <comment xml:lang="ro">Foaie de calcul OpenOffice Calc</comment>
- <comment xml:lang="ru">Электронная таблица OpenOffice Calc</comment>
- <comment xml:lang="sk">Zošit OpenOffice Calc</comment>
- <comment xml:lang="sl">Razpredelnica OpenOffice.org Calc</comment>
- <comment xml:lang="sq">Fletë llogaritjesh OpenOffice Calc</comment>
- <comment xml:lang="sr">Табела Опен Офис Рачуна</comment>
- <comment xml:lang="sv">OpenOffice Calc-kalkylblad</comment>
- <comment xml:lang="tr">OpenOffice Calc çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця OpenOffice Calc</comment>
- <comment xml:lang="vi">Bảng tính Calc của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Calc 电子表格</comment>
- <comment xml:lang="zh_TW">OpenOffice Calc 試算表</comment>
+ <comment>LibreOffice Calc spreadsheet</comment>
+ <comment xml:lang="uk">електронна таблиця LibreOffice Calc</comment>
+ <comment xml:lang="sv">LibreOffice Calc-kalkylblad</comment>
+ <comment xml:lang="ru">Электронная таблица LibreOffice Calc</comment>
+ <comment xml:lang="pt_BR">Planilha do LibreOffice Calc</comment>
+ <comment xml:lang="pl">Arkusz LibreOffice Calc</comment>
+ <comment xml:lang="it">Foglio di calcolo LibreOffice Calc</comment>
+ <comment xml:lang="gl">Folla de cálculo de LibreOffice Calc</comment>
+ <comment xml:lang="eu">LibreOffice Calc kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de LibreOffice Calc</comment>
+ <comment xml:lang="de">LibreOffice Calc-Tabelle</comment>
+ <comment xml:lang="be">электронная табліца LibreOffice Calc</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.calc" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.calc"/>
</match>
</match>
</magic>
<glob pattern="*.sxc"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.calc.template">
- <comment>OpenOffice Calc template</comment>
- <comment xml:lang="ar">قالب Calc المكتب المفتوح</comment>
- <comment xml:lang="be@latin">Šablon OpenOffice Calc</comment>
- <comment xml:lang="bg">Шаблон за таблици — OpenOffice Calc</comment>
- <comment xml:lang="ca">plantilla d'OpenOffice Calc</comment>
- <comment xml:lang="cs">šablona OpenOffice Calc</comment>
- <comment xml:lang="da">OpenOffice Calc-skabelon</comment>
- <comment xml:lang="de">OpenOffice-Calc-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο OpenOffice Calc</comment>
- <comment xml:lang="en_GB">OpenOffice Calc template</comment>
- <comment xml:lang="es">plantilla de OpenOffice Calc</comment>
- <comment xml:lang="eu">OpenOffice Calc txantiloia</comment>
- <comment xml:lang="fi">OpenOffice Calc -malli</comment>
- <comment xml:lang="fo">OpenOffice Calc formur</comment>
- <comment xml:lang="fr">modèle OpenOffice Calc</comment>
- <comment xml:lang="ga">teimpléad OpenOffice Calc</comment>
- <comment xml:lang="gl">modelo de OpenOffice Calc</comment>
- <comment xml:lang="he">תבנית של OpenOffice Calc</comment>
- <comment xml:lang="hr">OpenOffice Calc predložak</comment>
- <comment xml:lang="hu">OpenOffice Calc sablon</comment>
- <comment xml:lang="ia">Patrono OpenOffice Calc</comment>
- <comment xml:lang="id">Templat OpenOffice Calc</comment>
- <comment xml:lang="it">Modello OpenOffice Calc</comment>
- <comment xml:lang="ja">OpenOffice Calc テンプレート</comment>
- <comment xml:lang="ka">OpenOffice Calc-ის შაბლონი</comment>
- <comment xml:lang="kk">OpenOffice Calc үлгісі</comment>
- <comment xml:lang="ko">OpenOffice Calc 스프레드시트 문서 서식</comment>
- <comment xml:lang="lt">OpenOffice Calc šablonas</comment>
- <comment xml:lang="lv">OpenOffice Calc veidne</comment>
- <comment xml:lang="nb">OpenOffice Calc-mal</comment>
- <comment xml:lang="nl">OpenOffice.org Calc-sjabloon</comment>
- <comment xml:lang="nn">OpenOffice Calc-mal</comment>
- <comment xml:lang="oc">modèl OpenOffice Calc</comment>
- <comment xml:lang="pl">Szablon arkusza OpenOffice.org Calc</comment>
- <comment xml:lang="pt">modelo OpenOffice Calc</comment>
- <comment xml:lang="pt_BR">Modelo do OpenOffice Calc</comment>
- <comment xml:lang="ro">Șablon OpenOffice Calc</comment>
- <comment xml:lang="ru">Шаблон OpenOffice Calc</comment>
- <comment xml:lang="sk">Šablóna OpenOffice Calc</comment>
- <comment xml:lang="sl">Predloga OpenOffice.org Calc</comment>
- <comment xml:lang="sq">Model OpenOffice Calc</comment>
- <comment xml:lang="sr">Шаблон Опен Офис Рачуна</comment>
- <comment xml:lang="sv">OpenOffice Calc-mall</comment>
- <comment xml:lang="tr">OpenOffice Calc şablonu</comment>
- <comment xml:lang="uk">шаблон ел.таблиці OpenOffice Calc</comment>
- <comment xml:lang="vi">Mẫu bảng tính Calc của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Calc 模板</comment>
- <comment xml:lang="zh_TW">OpenOffice Calc 範本</comment>
+ <comment>LibreOffice Calc template</comment>
+ <comment xml:lang="uk">шаблон LibreOffice Calc</comment>
+ <comment xml:lang="sv">LibreOffice Calc-mall</comment>
+ <comment xml:lang="ru">Шаблон LibreOffice Calc</comment>
+ <comment xml:lang="pt_BR">Modelo do LibreOffice Calc</comment>
+ <comment xml:lang="pl">Szablon arkusza LibreOffice Calc</comment>
+ <comment xml:lang="it">Modello LibreOffice Calc</comment>
+ <comment xml:lang="gl">Modelo de LibreOffice Calc</comment>
+ <comment xml:lang="eu">LibreOffice Calc txantiloia</comment>
+ <comment xml:lang="es">plantilla de LibreOffice Calc</comment>
+ <comment xml:lang="de">LibreOffice Calc-Vorlage</comment>
+ <comment xml:lang="be">шаблон LibreOffice Calc</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.calc" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.calc"/>
</match>
</match>
</magic>
<glob pattern="*.stc"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.draw">
- <comment>OpenOffice Draw drawing</comment>
- <comment xml:lang="ar">تصميم Draw المكتب المفتوح</comment>
- <comment xml:lang="be@latin">Rysunak OpenOffice Draw</comment>
- <comment xml:lang="bg">Чертеж — OpenOffice Draw</comment>
- <comment xml:lang="ca">dibuix d'OpenOffice Draw</comment>
- <comment xml:lang="cs">kresba OpenOffice Draw</comment>
- <comment xml:lang="da">OpenOffice Draw-tegning</comment>
- <comment xml:lang="de">OpenOffice-Draw-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο OpenOffice Draw</comment>
- <comment xml:lang="en_GB">OpenOffice Draw drawing</comment>
- <comment xml:lang="es">dibujo de OpenOffice Draw</comment>
- <comment xml:lang="eu">OpenOffice.org Draw marrazkia</comment>
- <comment xml:lang="fi">OpenOffice Draw -piirros</comment>
- <comment xml:lang="fo">OpenOffice Draw tekning</comment>
- <comment xml:lang="fr">dessin OpenOffice Draw</comment>
- <comment xml:lang="ga">líníocht OpenOffice Draw</comment>
- <comment xml:lang="gl">debuxo de OpenOffice Draw</comment>
- <comment xml:lang="he">ציור של OpenOffice Draw</comment>
- <comment xml:lang="hr">OpenOffice Draw crtež</comment>
- <comment xml:lang="hu">OpenOffice Draw rajz</comment>
- <comment xml:lang="ia">Designo OpenOffice Draw</comment>
- <comment xml:lang="id">Gambar OpenOffice Draw</comment>
- <comment xml:lang="it">Disegno OpenOffice Draw</comment>
- <comment xml:lang="ja">OpenOffice Draw ドロー</comment>
- <comment xml:lang="ka">OpenOffice Draw-ის ნახაზი</comment>
- <comment xml:lang="kk">OpenOffice Draw суреті</comment>
- <comment xml:lang="ko">OpenOffice Draw 그림</comment>
- <comment xml:lang="lt">OpenOffice Draw piešinys</comment>
- <comment xml:lang="lv">OpenOffice Draw zīmējums</comment>
- <comment xml:lang="nb">OpenOffice Draw-tegning</comment>
- <comment xml:lang="nl">OpenOffice.org Draw-tekening</comment>
- <comment xml:lang="nn">OpenOffice Draw-teikning</comment>
- <comment xml:lang="oc">dessenh OpenOffice Draw</comment>
- <comment xml:lang="pl">Rysunek OpenOffice.org Draw</comment>
- <comment xml:lang="pt">desenho OpenOffice Draw</comment>
- <comment xml:lang="pt_BR">Desenho do OpenOffice Draw</comment>
- <comment xml:lang="ro">Desen OpenOffice Draw</comment>
- <comment xml:lang="ru">Рисунок OpenOffice Draw</comment>
- <comment xml:lang="sk">Kresba OpenOffice Draw</comment>
- <comment xml:lang="sl">Datoteka risbe OpenOffice.org Draw</comment>
- <comment xml:lang="sq">Vizatim OpenOffice Draw</comment>
- <comment xml:lang="sr">Цртеж Опен Офис Цртежа</comment>
- <comment xml:lang="sv">OpenOffice Draw-teckning</comment>
- <comment xml:lang="tr">OpenOffice Draw çizimi</comment>
- <comment xml:lang="uk">малюнок OpenOffice Draw</comment>
- <comment xml:lang="vi">Bản vẽ Draw của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Draw 绘图</comment>
- <comment xml:lang="zh_TW">OpenOffice Draw 繪圖</comment>
+ <comment>LibreOffice Draw drawing</comment>
+ <comment xml:lang="uk">рисунок LibreOffice Draw</comment>
+ <comment xml:lang="sv">LibreOffice Draw-teckning</comment>
+ <comment xml:lang="ru">Рисунок LibreOffice Draw</comment>
+ <comment xml:lang="pt_BR">Desenho do LibreOffice Draw</comment>
+ <comment xml:lang="pl">Rysunek LibreOffice Draw</comment>
+ <comment xml:lang="it">Disegno LibreOffice Draw</comment>
+ <comment xml:lang="gl">Debuxo de LibreOffice Draw</comment>
+ <comment xml:lang="eu">LibreOffice Draw marrazkia</comment>
+ <comment xml:lang="es">dibujo de LibreOffice Draw</comment>
+ <comment xml:lang="de">LibreOffice Draw-Zeichnung</comment>
+ <comment xml:lang="be">рысунак LibreOffice Draw</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.draw" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.draw"/>
</match>
</match>
</magic>
<glob pattern="*.sxd"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.draw.template">
- <comment>OpenOffice Draw template</comment>
- <comment xml:lang="ar">قالب Draw المكتب المفتوح</comment>
- <comment xml:lang="be@latin">Šablon OpenOffice Draw</comment>
- <comment xml:lang="bg">Шаблон за чертежи — OpenOffice Draw</comment>
- <comment xml:lang="ca">plantilla d'OpenOffice Draw</comment>
- <comment xml:lang="cs">šablona OpenOffice Draw</comment>
- <comment xml:lang="da">OpenOffice Draw-skabelon</comment>
- <comment xml:lang="de">OpenOffice-Draw-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο OpenOffice Draw</comment>
- <comment xml:lang="en_GB">OpenOffice Draw template</comment>
- <comment xml:lang="es">plantilla de OpenOffice Draw</comment>
- <comment xml:lang="eu">OpenOffice Draw txantiloia</comment>
- <comment xml:lang="fi">OpenOffice Draw -malli</comment>
- <comment xml:lang="fo">OpenOffice Draw formur</comment>
- <comment xml:lang="fr">modèle OpenOffice Draw</comment>
- <comment xml:lang="ga">teimpléad OpenOffice Draw</comment>
- <comment xml:lang="gl">modelo de OpenOffice Draw</comment>
- <comment xml:lang="he">תבנית של OpenOffice Draw</comment>
- <comment xml:lang="hr">Predložak OpenOffice Drawa</comment>
- <comment xml:lang="hu">OpenOffice Draw sablon</comment>
- <comment xml:lang="ia">Patrono OpenOffice Draw</comment>
- <comment xml:lang="id">Templat OpenOffice Draw</comment>
- <comment xml:lang="it">Modello OpenOffice Draw</comment>
- <comment xml:lang="ja">OpenOffice Draw テンプレート</comment>
- <comment xml:lang="ka">OpenOffice Draw-ის შაბლონი</comment>
- <comment xml:lang="kk">OpenOffice Draw үлгісі</comment>
- <comment xml:lang="ko">OpenOffice Draw 그림 문서 서식</comment>
- <comment xml:lang="lt">OpenOffice Draw šablonas</comment>
- <comment xml:lang="lv">OpenOffice Draw veidne</comment>
- <comment xml:lang="nb">OpenOffice Draw-mal</comment>
- <comment xml:lang="nl">OpenOffice.org Draw-sjabloon</comment>
- <comment xml:lang="nn">OpenOffice Draw-mal</comment>
- <comment xml:lang="oc">modèl OpenOffice Draw</comment>
- <comment xml:lang="pl">Szablon rysunku OpenOffice.org Draw</comment>
- <comment xml:lang="pt">modelo OpenOffice Draw</comment>
- <comment xml:lang="pt_BR">Modelo do OpenOffice Draw</comment>
- <comment xml:lang="ro">Șablon OpenOffice Draw</comment>
- <comment xml:lang="ru">Шаблон OpenOffice Draw</comment>
- <comment xml:lang="sk">Šablóna OpenOffice Draw</comment>
- <comment xml:lang="sl">Predloga OpenOffice.org Draw</comment>
- <comment xml:lang="sq">Model OpenOffice Draw</comment>
- <comment xml:lang="sr">Шаблон Опен Офис Цртежа</comment>
- <comment xml:lang="sv">OpenOffice Draw-mall</comment>
- <comment xml:lang="tr">OpenOffice Draw şablonu</comment>
- <comment xml:lang="uk">шаблон малюнку OpenOffice Draw</comment>
- <comment xml:lang="vi">Mẫu bản vẽ Draw của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Draw 模板</comment>
- <comment xml:lang="zh_TW">OpenOffice Draw 範本</comment>
+ <comment>LibreOffice Draw template</comment>
+ <comment xml:lang="uk">шаблон LibreOffice Draw</comment>
+ <comment xml:lang="sv">LibreOffice Draw-mall</comment>
+ <comment xml:lang="ru">Шаблон LibreOffice Draw</comment>
+ <comment xml:lang="pt_BR">Modelo do LibreOffice Draw</comment>
+ <comment xml:lang="pl">Szablon rysunku LibreOffice Draw</comment>
+ <comment xml:lang="it">Modello LibreOffice Draw</comment>
+ <comment xml:lang="gl">Modelo de LibreOffice Draw</comment>
+ <comment xml:lang="eu">LibreOffice Draw txantiloia</comment>
+ <comment xml:lang="es">plantilla de LibreOffice Draw</comment>
+ <comment xml:lang="de">LibreOffice Draw-Vorlage</comment>
+ <comment xml:lang="be">шаблон LibreOffice Draw</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.draw" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.draw"/>
</match>
</match>
</magic>
<glob pattern="*.std"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.impress">
- <comment>OpenOffice Impress presentation</comment>
- <comment xml:lang="ar">عرض تقديمي Impress المكتب المفتوح</comment>
- <comment xml:lang="az">OpenOffice Impress sənədi</comment>
- <comment xml:lang="be@latin">Prezentacyja OpenOffice Impress</comment>
- <comment xml:lang="bg">Презентация — OpenOffice Impress</comment>
- <comment xml:lang="ca">presentació d'OpenOffice Impress</comment>
- <comment xml:lang="cs">prezentace OpenOffice Impress</comment>
- <comment xml:lang="cy">Cyflwyniad OpenOffice (Impress)</comment>
- <comment xml:lang="da">OpenOffice Impress-præsentation</comment>
- <comment xml:lang="de">OpenOffice-Impress-Vorlage</comment>
- <comment xml:lang="el">Παρουσίαση OpenOffice Impress</comment>
- <comment xml:lang="en_GB">OpenOffice Impress presentation</comment>
- <comment xml:lang="es">presentación de OpenOffice Impress</comment>
- <comment xml:lang="eu">OpenOffice.org Impress aurkezpena</comment>
- <comment xml:lang="fi">OpenOffice Impress -esitys</comment>
- <comment xml:lang="fo">OpenOffice Impress framløga</comment>
- <comment xml:lang="fr">présentation OpenOffice Impress</comment>
- <comment xml:lang="ga">láithreoireacht OpenOffice Impress</comment>
- <comment xml:lang="gl">presentación de de OpenOffice Impress</comment>
- <comment xml:lang="he">מצגת של OpenOffice Impress</comment>
- <comment xml:lang="hr">OpenOffice Impress prezentacija</comment>
- <comment xml:lang="hu">OpenOffice Impress bemutató</comment>
- <comment xml:lang="ia">Presentation OpenOffice Impress</comment>
- <comment xml:lang="id">Presentasi OpenOffice Impress</comment>
- <comment xml:lang="it">Presentazione OpenOffice Impress</comment>
- <comment xml:lang="ja">OpenOffice Impress プレゼンテーション</comment>
- <comment xml:lang="ka">OpenOffice Impress-ის პრეზენტაცია</comment>
- <comment xml:lang="kk">OpenOffice Impress презентациясы</comment>
- <comment xml:lang="ko">OpenOffice Impress 프레젠테이션</comment>
- <comment xml:lang="lt">OpenOffice Impress pateiktis</comment>
- <comment xml:lang="lv">OpenOffice Impress prezentācija</comment>
- <comment xml:lang="nb">OpenOffice Impress-presentasjon</comment>
- <comment xml:lang="nl">OpenOffice.org Impress-presentatie</comment>
- <comment xml:lang="nn">OpenOffice Impress-presentasjon</comment>
- <comment xml:lang="oc">presentacion OpenOffice Impress</comment>
- <comment xml:lang="pl">Prezentacja OpenOffice.org Impress</comment>
- <comment xml:lang="pt">apresentação OpenOffice Impress</comment>
- <comment xml:lang="pt_BR">Apresentação do OpenOffice Impress</comment>
- <comment xml:lang="ro">Prezentare OpenOffice Impress</comment>
- <comment xml:lang="ru">Презентация OpenOffice Impress</comment>
- <comment xml:lang="sk">Prezentácia OpenOffice Impress</comment>
- <comment xml:lang="sl">Predstavitev OpenOffice.org Impress</comment>
- <comment xml:lang="sq">Prezantim OpenOffice Impress</comment>
- <comment xml:lang="sr">Презентација Опен Офис Импреса</comment>
- <comment xml:lang="sv">OpenOffice Impress-presentation</comment>
- <comment xml:lang="tr">OpenOffice Impress sunumu</comment>
- <comment xml:lang="uk">презентація OpenOffice Impress</comment>
- <comment xml:lang="vi">Trình diễn Impress của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Impress 演示文稿</comment>
- <comment xml:lang="zh_TW">OpenOffice Impress 簡報</comment>
+ <comment>LibreOffice Impress presentation</comment>
+ <comment xml:lang="uk">презентація LibreOffice Impress</comment>
+ <comment xml:lang="sv">LibreOffice Impress-presentation</comment>
+ <comment xml:lang="ru">Презентация LibreOffice Impress</comment>
+ <comment xml:lang="pt_BR">Apresentação do LibreOffice Impress</comment>
+ <comment xml:lang="pl">Prezentacja LibreOffice Impress</comment>
+ <comment xml:lang="it">Presentazione LibreOffice Impress</comment>
+ <comment xml:lang="gl">Presentación de LibreOffice Impress</comment>
+ <comment xml:lang="eu">LibreOffice Impress aurkezpena</comment>
+ <comment xml:lang="es">presentación de LibreOffice Impress</comment>
+ <comment xml:lang="de">LibreOffice Impress-Präsentation</comment>
+ <comment xml:lang="be">прэзентацыя LibreOffice Impress</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.impress" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.impress"/>
</match>
</match>
</magic>
<glob pattern="*.sxi"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.impress.template">
- <comment>OpenOffice Impress template</comment>
- <comment xml:lang="ar">قالب Impress المكتب المفتوح</comment>
- <comment xml:lang="be@latin">Šablon OpenOffice Impress</comment>
- <comment xml:lang="bg">Шаблон за презентации — OpenOffice Impress</comment>
- <comment xml:lang="ca">plantilla d'OpenOffice Impress</comment>
- <comment xml:lang="cs">šablona OpenOffice Impress</comment>
- <comment xml:lang="da">OpenOffice Impress-skabelon</comment>
- <comment xml:lang="de">OpenOffice-Impress-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο OpenOffice Impress</comment>
- <comment xml:lang="en_GB">OpenOffice Impress template</comment>
- <comment xml:lang="es">plantilla de OpenOffice Impress</comment>
- <comment xml:lang="eu">OpenOffice Impress txantiloia</comment>
- <comment xml:lang="fi">OpenOffice Impress -malli</comment>
- <comment xml:lang="fo">OpenOffice Impress formur</comment>
- <comment xml:lang="fr">modèle OpenOffice Impress</comment>
- <comment xml:lang="ga">teimpléad OpenOffice Impress</comment>
- <comment xml:lang="gl">modelo de OpenOffice Impress</comment>
- <comment xml:lang="he">תבנית של OpenOffice Impress</comment>
- <comment xml:lang="hr">Predložak OpenOffice Impressa</comment>
- <comment xml:lang="hu">OpenOffice Impress sablon</comment>
- <comment xml:lang="ia">Patrono OpenOffice Impress</comment>
- <comment xml:lang="id">Templat OpenOffice Impress</comment>
- <comment xml:lang="it">Modello OpenOffice Impress</comment>
- <comment xml:lang="ja">OpenOffice Impress テンプレート</comment>
- <comment xml:lang="ka">OpenOffice Impress-ის შაბლონი</comment>
- <comment xml:lang="kk">OpenOffice Impress үлгісі</comment>
- <comment xml:lang="ko">OpenOffice Impress 프레젠테이션 문서 서식</comment>
- <comment xml:lang="lt">OpenOffice Impress šablonas</comment>
- <comment xml:lang="lv">OpenOffice Impress veidne</comment>
- <comment xml:lang="nb">OpenOffice Impress-mal</comment>
- <comment xml:lang="nl">OpenOffice.org Impress-sjabloon</comment>
- <comment xml:lang="nn">OpenOffice Impress-mal</comment>
- <comment xml:lang="oc">modèl OpenOffice Impress</comment>
- <comment xml:lang="pl">Szablon prezentacji OpenOffice.org Impress</comment>
- <comment xml:lang="pt">modelo OpenOffice Impress</comment>
- <comment xml:lang="pt_BR">Modelo do OpenOffice Impress</comment>
- <comment xml:lang="ro">Șablon OpenOffice Impress</comment>
- <comment xml:lang="ru">Шаблон OpenOffice Impress</comment>
- <comment xml:lang="sk">Šablóna OpenOffice Impress</comment>
- <comment xml:lang="sl">Predloga OpenOffice.org Impress</comment>
- <comment xml:lang="sq">Model OpenOffice Impress</comment>
- <comment xml:lang="sr">Шаблон Опен Офис Импреса</comment>
- <comment xml:lang="sv">OpenOffice Impress-mall</comment>
- <comment xml:lang="tr">OpenOffice Impress şablonu</comment>
- <comment xml:lang="uk">шаблон презентації OpenOffice Impress</comment>
- <comment xml:lang="vi">Mẫu trình diễn Impress của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Impress 模板</comment>
- <comment xml:lang="zh_TW">OpenOffice Impress 範本</comment>
+ <comment>LibreOffice Impress template</comment>
+ <comment xml:lang="uk">шаблон LibreOffice Impress</comment>
+ <comment xml:lang="sv">LibreOffice Impress-mall</comment>
+ <comment xml:lang="ru">Шаблон LibreOffice Impress</comment>
+ <comment xml:lang="pt_BR">Documento do LibreOffice Impress</comment>
+ <comment xml:lang="pl">Szablon prezentacji LibreOffice Impress</comment>
+ <comment xml:lang="it">Modello LibreOffice Impress</comment>
+ <comment xml:lang="gl">Modelo de LibreOffice Impress</comment>
+ <comment xml:lang="eu">LibreOffice Impress txantiloia</comment>
+ <comment xml:lang="es">plantilla de LibreOffice Impress</comment>
+ <comment xml:lang="de">LibreOffice Impress-Vorlage</comment>
+ <comment xml:lang="be">шаблон LibreOffice Impress</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.impress" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.impress"/>
</match>
</match>
</magic>
<glob pattern="*.sti"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.math">
- <comment>OpenOffice Math formula</comment>
- <comment xml:lang="ar">صيغة Math المكتب المفتوح</comment>
- <comment xml:lang="be@latin">Formuła OpenOffice Math</comment>
- <comment xml:lang="bg">Формула — OpenOffice Math</comment>
- <comment xml:lang="ca">fórmula d'OpenOffice Math</comment>
- <comment xml:lang="cs">vzorec OpenOffice Math</comment>
- <comment xml:lang="da">OpenOffice Math-formel</comment>
- <comment xml:lang="de">OpenOffice-Math-Formel</comment>
- <comment xml:lang="el">Μαθηματικός τύπος OpenOffice Math</comment>
- <comment xml:lang="en_GB">OpenOffice Math formula</comment>
- <comment xml:lang="es">fórmula de OpenOffice Math</comment>
- <comment xml:lang="eu">OpenOffice.org Math formula</comment>
- <comment xml:lang="fi">OpenOffice Math -kaava</comment>
- <comment xml:lang="fo">OpenOffice Math frymil</comment>
- <comment xml:lang="fr">formule OpenOffice Math</comment>
- <comment xml:lang="ga">foirmle OpenOffice Math</comment>
- <comment xml:lang="gl">fórmula de OpenOffice Math</comment>
- <comment xml:lang="he">נוסחה של OpenOffice Math</comment>
- <comment xml:lang="hr">OpenOffice Math formula</comment>
- <comment xml:lang="hu">OpenOffice Math képlet</comment>
- <comment xml:lang="ia">Formula OpenOffice Math</comment>
- <comment xml:lang="id">Formula OpenOffice Math</comment>
- <comment xml:lang="it">Formula OpenOffice Math</comment>
- <comment xml:lang="ja">OpenOffice Math 計算式</comment>
- <comment xml:lang="ka">OpenOffice Math-ის ფორმულა</comment>
- <comment xml:lang="kk">OpenOffice Math формуласы</comment>
- <comment xml:lang="ko">OpenOffice Math 수식</comment>
- <comment xml:lang="lt">OpenOffice Math formulė</comment>
- <comment xml:lang="lv">OpenOffice Math formula</comment>
- <comment xml:lang="nb">OpenOffice Math-formel</comment>
- <comment xml:lang="nl">OpenOffice.org Math-formule</comment>
- <comment xml:lang="nn">OpenOffice Math-formel</comment>
- <comment xml:lang="oc">formula OpenOffice Math</comment>
- <comment xml:lang="pl">Formuła OpenOffice.org Math</comment>
- <comment xml:lang="pt">fórmula OpenOffice Math</comment>
- <comment xml:lang="pt_BR">Fórmula do OpenOffice Math</comment>
- <comment xml:lang="ro">Formulă OpenOffice Math</comment>
- <comment xml:lang="ru">Формула OpenOffice Math</comment>
- <comment xml:lang="sk">Vzorec OpenOffice Math</comment>
- <comment xml:lang="sl">Dokument formule OpenOffice.org Math</comment>
- <comment xml:lang="sq">Formulë OpenOffice Math</comment>
- <comment xml:lang="sr">Формула Опен Офис Математике</comment>
- <comment xml:lang="sv">OpenOffice Math-formel</comment>
- <comment xml:lang="tr">OpenOffice Math formülü</comment>
- <comment xml:lang="uk">формула OpenOffice Math</comment>
- <comment xml:lang="vi">Công thức Math của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Math 公式</comment>
- <comment xml:lang="zh_TW">OpenOffice Math 公式</comment>
+ <comment>LibreOffice Math formula</comment>
+ <comment xml:lang="uk">формула LibreOffice Math</comment>
+ <comment xml:lang="sv">LibreOffice Math-formel</comment>
+ <comment xml:lang="ru">Формула LibreOffice Math</comment>
+ <comment xml:lang="pt_BR">Fórmula do LibreOffice Math</comment>
+ <comment xml:lang="pl">Formuła LibreOffice Math</comment>
+ <comment xml:lang="it">Formula LibreOffice Math</comment>
+ <comment xml:lang="gl">Fórmula de LibreOffice Math</comment>
+ <comment xml:lang="eu">LibreOffice Math formula</comment>
+ <comment xml:lang="es">fórmula de LibreOffice Math</comment>
+ <comment xml:lang="de">LibreOffice Math-Formel</comment>
+ <comment xml:lang="be">формула LibreOffice Math</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.math" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.math"/>
</match>
</match>
</magic>
<glob pattern="*.sxm"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.writer">
- <comment>OpenOffice Writer document</comment>
- <comment xml:lang="ar">مستند Writer المكتب المفتوح</comment>
- <comment xml:lang="ast">Documentu d'OpenOffice Writer</comment>
- <comment xml:lang="az">OpenOffice Writer sənədi</comment>
- <comment xml:lang="be@latin">Dakument OpenOffice Writer</comment>
- <comment xml:lang="bg">Документ — OpenOffice Writer</comment>
- <comment xml:lang="ca">document d'OpenOffice Writer</comment>
- <comment xml:lang="cs">dokument OpenOffice Writer</comment>
- <comment xml:lang="cy">Dogfen OpenOffice (Writer)</comment>
- <comment xml:lang="da">OpenOffice Writer-dokument</comment>
- <comment xml:lang="de">OpenOffice-Writer-Dokument</comment>
- <comment xml:lang="el">Έγγραφο OpenOffice Writer</comment>
- <comment xml:lang="en_GB">OpenOffice Writer document</comment>
- <comment xml:lang="es">documento de OpenOffice Writer</comment>
- <comment xml:lang="eu">OpenOffice.org Writer dokumentua</comment>
- <comment xml:lang="fi">OpenOffice Writer -asiakirja</comment>
- <comment xml:lang="fo">OpenOffice Writer skjal</comment>
- <comment xml:lang="fr">document OpenOffice Writer</comment>
- <comment xml:lang="ga">cáipéis OpenOffice Writer</comment>
- <comment xml:lang="gl">documento de OpenOffice Writer</comment>
- <comment xml:lang="he">מסמך של OpenOffice Writer</comment>
- <comment xml:lang="hr">OpenOffice Writer dokument</comment>
- <comment xml:lang="hu">OpenOffice Writer dokumentum</comment>
- <comment xml:lang="ia">Documento OpenOffice Writer</comment>
- <comment xml:lang="id">Dokumen OpenOffice Writer</comment>
- <comment xml:lang="it">Documento OpenOffice Writer</comment>
- <comment xml:lang="ja">OpenOffice Writer ドキュメント</comment>
- <comment xml:lang="ka">OpenOffice Writer-ის დოკუმენტი</comment>
- <comment xml:lang="kk">OpenOffice Writer құжаты</comment>
- <comment xml:lang="ko">OpenOffice Writer 문서</comment>
- <comment xml:lang="lt">OpenOffice Writer dokumentas</comment>
- <comment xml:lang="lv">OpenOffice Writer dokuments</comment>
- <comment xml:lang="nb">OpenOffice Writer-dokument</comment>
- <comment xml:lang="nl">OpenOffice.org Writer-document</comment>
- <comment xml:lang="nn">OpenOffice Writer-dokument</comment>
- <comment xml:lang="oc">document OpenOffice Writer</comment>
- <comment xml:lang="pl">Dokument OpenOffice.org Writer</comment>
- <comment xml:lang="pt">documento OpenOffice Writer</comment>
- <comment xml:lang="pt_BR">Documento do OpenOffice Writer</comment>
- <comment xml:lang="ro">Document OpenOffice Writer</comment>
- <comment xml:lang="ru">Документ OpenOffice Writer</comment>
- <comment xml:lang="sk">Dokument OpenOffice Writer</comment>
- <comment xml:lang="sl">Dokument OpenOffice.org Writer</comment>
- <comment xml:lang="sq">Dokument OpenOffice Writer</comment>
- <comment xml:lang="sr">Документ Опен Офис Писца</comment>
- <comment xml:lang="sv">OpenOffice Writer-dokument</comment>
- <comment xml:lang="tr">OpenOffice Writer belgesi</comment>
- <comment xml:lang="uk">документ OpenOffice Writer</comment>
- <comment xml:lang="vi">Tài liệu Writer của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Writer 文档</comment>
- <comment xml:lang="zh_TW">OpenOffice Writer 文件</comment>
+ <comment>LibreOffice Writer document</comment>
+ <comment xml:lang="uk">документ LibreOffice Writer</comment>
+ <comment xml:lang="sv">LibreOffice Writer-dokument</comment>
+ <comment xml:lang="ru">Документ LibreOffice Writer</comment>
+ <comment xml:lang="pt_BR">Documento do LibreOffice Writer</comment>
+ <comment xml:lang="pl">Dokument LibreOffice Writer</comment>
+ <comment xml:lang="it">Documento LibreOffice Writer</comment>
+ <comment xml:lang="gl">Documento de LibreOffice Writer</comment>
+ <comment xml:lang="eu">LibreOffice Writer dokumentua</comment>
+ <comment xml:lang="es">documento de LibreOffice Writer</comment>
+ <comment xml:lang="de">LibreOffice Writer-Dokument</comment>
+ <comment xml:lang="be">дакумент LibreOffice Writer</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.writer" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.writer"/>
</match>
</match>
</magic>
<glob pattern="*.sxw"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.writer.global">
- <comment>OpenOffice Writer global document</comment>
- <comment xml:lang="ar">مستند المكتب المفتوح Writer العالمي</comment>
- <comment xml:lang="ast">Documentu global d'OpenOffice Writer</comment>
- <comment xml:lang="az">OpenOffice Writer qlobal sənədi</comment>
- <comment xml:lang="be@latin">Hlabalny dakument OpenOffice Writer</comment>
- <comment xml:lang="bg">Документ - глобален — OpenOffice Writer</comment>
- <comment xml:lang="ca">document global d'OpenOffice Writer</comment>
- <comment xml:lang="cs">globální dokument OpenOffice Writer</comment>
- <comment xml:lang="cy">Dogfen eang OpenOffice (Writer)</comment>
- <comment xml:lang="da">OpenOffice Writer-globalt dokument</comment>
- <comment xml:lang="de">OpenOffice-Writer-Globaldokument</comment>
- <comment xml:lang="el">Καθολικό έγγραφο OpenOffice Writer</comment>
- <comment xml:lang="en_GB">OpenOffice Writer global document</comment>
- <comment xml:lang="es">documento global de OpenOffice Writer</comment>
- <comment xml:lang="eu">OpenOffice.org Writer dokumentu globala</comment>
- <comment xml:lang="fi">OpenOffice Writer - yleinen asiakirja</comment>
- <comment xml:lang="fo">OpenOffice Writer heiltøkt skjal</comment>
- <comment xml:lang="fr">document global OpenOffice Writer</comment>
- <comment xml:lang="ga">cáipéis chomhchoiteann OpenOffice Writer</comment>
- <comment xml:lang="gl">documento global de OpenOffice Writer</comment>
- <comment xml:lang="he">מסמך גלובלי של OpenOffice Writer</comment>
- <comment xml:lang="hr">OpenOffice Writer globalni dokument</comment>
- <comment xml:lang="hu">OpenOffice Writer globális dokumentum</comment>
- <comment xml:lang="ia">Documento global OpenOffice Writer</comment>
- <comment xml:lang="id">Dokumen global OpenOffice Writer</comment>
- <comment xml:lang="it">Documento globale OpenOffice Writer</comment>
- <comment xml:lang="ja">OpenOffice Writer グローバルドキュメント</comment>
- <comment xml:lang="ka">OpenOffice Writer-ის გლობალური დოკუმენტი</comment>
- <comment xml:lang="kk">OpenOffice Writer негізгі құжаты</comment>
- <comment xml:lang="ko">OpenOffice Writer 글로벌 문서</comment>
- <comment xml:lang="lt">OpenOffice Writer bendrinis dokumentas</comment>
- <comment xml:lang="lv">OpenOffice Writer globālais dokuments</comment>
- <comment xml:lang="nb">Global OpenOffice Writer globalt dokument</comment>
- <comment xml:lang="nl">OpenOffice.org Writer-globaal-document</comment>
- <comment xml:lang="nn">OpenOffice Writer globalt dokument</comment>
- <comment xml:lang="oc">document global OpenOffice Writer</comment>
- <comment xml:lang="pl">Globalny dokument OpenOffice.org Writer</comment>
- <comment xml:lang="pt">documento global OpenOffice Writer</comment>
- <comment xml:lang="pt_BR">Documento global do OpenOffice Writer</comment>
- <comment xml:lang="ro">Document global OpenOffice Writer</comment>
- <comment xml:lang="ru">Основной документ OpenOffice Writer</comment>
- <comment xml:lang="sk">Globálny dokument OpenOffice Writer</comment>
- <comment xml:lang="sl">Splošni dokument OpenOffice.org Writer</comment>
- <comment xml:lang="sq">Dokument i përgjithshëm OpenOffice Writer</comment>
- <comment xml:lang="sr">Општи документ Опен Офис Писца</comment>
- <comment xml:lang="sv">OpenOffice Writer-globaldokument</comment>
- <comment xml:lang="tr">OpenOffice Writer global belgesi</comment>
- <comment xml:lang="uk">загальний документ OpenOffice Writer</comment>
- <comment xml:lang="vi">Tài liệu toàn cục Writer của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Writer 全局文档</comment>
- <comment xml:lang="zh_TW">OpenOffice Writer 主控文件</comment>
+ <comment>LibreOffice Writer global document</comment>
+ <comment xml:lang="uk">загальний документ LibreOffice Writer</comment>
+ <comment xml:lang="sv">LibreOffice Writer-globaldokument</comment>
+ <comment xml:lang="ru">Основной документ LibreOffice Writer</comment>
+ <comment xml:lang="pt_BR">Documento global do LibreOffice Writer</comment>
+ <comment xml:lang="pl">Globalny dokument LibreOffice Writer</comment>
+ <comment xml:lang="it">Documento globale LibreOffice Writer</comment>
+ <comment xml:lang="gl">Documento global de LibreOffice Writer</comment>
+ <comment xml:lang="eu">LibreOffice Writer dokumentu globala</comment>
+ <comment xml:lang="es">documento global de LibreOffice Writer</comment>
+ <comment xml:lang="de">LibreOffice Writer-Globaldokument</comment>
+ <comment xml:lang="be">глабальны дакумент LibreOffice Writer</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.writer" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.writer"/>
</match>
</match>
</magic>
<glob pattern="*.sxg"/>
</mime-type>
<mime-type type="application/vnd.sun.xml.writer.template">
- <comment>OpenOffice Writer template</comment>
- <comment xml:lang="ar">قالب Writer المكتب المفتوح</comment>
- <comment xml:lang="az">OpenOffice Writer şablonu</comment>
- <comment xml:lang="be@latin">Šablon OpenOffice Writer</comment>
- <comment xml:lang="bg">Шаблон за документи — OpenOffice Writer</comment>
- <comment xml:lang="ca">plantilla d'OpenOffice Writer</comment>
- <comment xml:lang="cs">šablona OpenOffice Writer</comment>
- <comment xml:lang="cy">Templed OpenOffice (Writer)</comment>
- <comment xml:lang="da">OpenOffice Writer-skabelon</comment>
- <comment xml:lang="de">OpenOffice-Writer-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο OpenOffice Writer</comment>
- <comment xml:lang="en_GB">OpenOffice Writer template</comment>
- <comment xml:lang="es">plantilla de OpenOffice Writer</comment>
- <comment xml:lang="eu">OpenOffice Writer txantiloia</comment>
- <comment xml:lang="fi">OpenOffice Writer -malli</comment>
- <comment xml:lang="fo">OpenOffice Writer formur</comment>
- <comment xml:lang="fr">modèle OpenOffice Writer</comment>
- <comment xml:lang="ga">teimpléad OpenOffice Writer</comment>
- <comment xml:lang="gl">modelo de OpenOffice Writer</comment>
- <comment xml:lang="he">תסנית של OpenOffice Writer</comment>
- <comment xml:lang="hr">OpenOffice Writer predložak</comment>
- <comment xml:lang="hu">OpenOffice Writer sablon</comment>
- <comment xml:lang="ia">Patrono OpenOffice Writer</comment>
- <comment xml:lang="id">Templat OpenOffice Writer</comment>
- <comment xml:lang="it">Modello OpenOffice Writer</comment>
- <comment xml:lang="ja">OpenOffice Writer ドキュメントテンプレート</comment>
- <comment xml:lang="ka">OpenOffice Writer-ის შაბლონი</comment>
- <comment xml:lang="kk">OpenOffice Writer үлгісі</comment>
- <comment xml:lang="ko">OpenOffice Writer 문서 서식</comment>
- <comment xml:lang="lt">OpenOffice Writer šablonas</comment>
- <comment xml:lang="lv">OpenOffice Writer veidne</comment>
- <comment xml:lang="ms">Templat OpenOffice Writer</comment>
- <comment xml:lang="nb">OpenOffice Writer-mal</comment>
- <comment xml:lang="nl">OpenOffice.org Writer-sjabloon</comment>
- <comment xml:lang="nn">OpenOffice Writer-mal</comment>
- <comment xml:lang="oc">modèl OpenOffice Writer</comment>
- <comment xml:lang="pl">Szablon dokumentu OpenOffice.org Writer</comment>
- <comment xml:lang="pt">modelo OpenOffice Writer</comment>
- <comment xml:lang="pt_BR">Modelo do OpenOffice Writer</comment>
- <comment xml:lang="ro">Șablon OpenOffice Writer</comment>
- <comment xml:lang="ru">Шаблон OpenOffice Writer</comment>
- <comment xml:lang="sk">Šablóna OpenOffice Writer</comment>
- <comment xml:lang="sl">Predloga OpenOffice.org Writer</comment>
- <comment xml:lang="sq">Model OpenOffice Writer</comment>
- <comment xml:lang="sr">Шаблон Опен Офис Писца</comment>
- <comment xml:lang="sv">OpenOffice Writer-mall</comment>
- <comment xml:lang="tr">OpenOffice Writer şablonu</comment>
- <comment xml:lang="uk">шаблон документа OpenOffice Writer</comment>
- <comment xml:lang="vi">Mẫu tài liệu Writer của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice Writer 模板</comment>
- <comment xml:lang="zh_TW">OpenOffice Writer 範本</comment>
+ <comment>LibreOffice Writer template</comment>
+ <comment xml:lang="uk">шаблон LibreOffice Writer</comment>
+ <comment xml:lang="sv">LibreOffice Writer-mall</comment>
+ <comment xml:lang="ru">Шаблон LibreOffice Writer</comment>
+ <comment xml:lang="pt_BR">Modelo do LibreOffice Writer</comment>
+ <comment xml:lang="pl">Szablon dokumentu LibreOffice Writer</comment>
+ <comment xml:lang="it">Modello LibreOffice Writer</comment>
+ <comment xml:lang="gl">Modelo de LibreOffice Writer</comment>
+ <comment xml:lang="eu">LibreOffice Writer txantiloia</comment>
+ <comment xml:lang="es">plantilla de LibreOffice Writer</comment>
+ <comment xml:lang="de">LibreOffice Writer-Vorlage</comment>
+ <comment xml:lang="be">шаблон LibreOffice Writer</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.sun.xml.writer" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" offset="38" value="application/vnd.sun.xml.writer"/>
</match>
</match>
</magic>
@@ -5297,63 +5614,68 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.text">
<comment>ODT document</comment>
- <comment xml:lang="ar">مستند ODT</comment>
- <comment xml:lang="ast">Documentu ODT</comment>
- <comment xml:lang="be@latin">Dakument ODT</comment>
- <comment xml:lang="bg">Документ — ODT</comment>
- <comment xml:lang="ca">document ODT</comment>
- <comment xml:lang="cs">dokument ODT</comment>
- <comment xml:lang="da">ODT-dokument</comment>
- <comment xml:lang="de">ODT-Dokument</comment>
- <comment xml:lang="el">Έγγραφο ODT</comment>
- <comment xml:lang="en_GB">ODT document</comment>
- <comment xml:lang="eo">ODT-dokumento</comment>
- <comment xml:lang="es">documento ODT</comment>
- <comment xml:lang="eu">ODT dokumentua</comment>
- <comment xml:lang="fi">ODT-asiakirja</comment>
- <comment xml:lang="fo">ODT skjal</comment>
- <comment xml:lang="fr">document ODT</comment>
- <comment xml:lang="ga">cáipéis ODT</comment>
- <comment xml:lang="gl">documento ODT</comment>
- <comment xml:lang="he">מסמך ODT</comment>
- <comment xml:lang="hr">ODT dokument</comment>
- <comment xml:lang="hu">ODT-dokumentum</comment>
- <comment xml:lang="ia">Documento ODT</comment>
- <comment xml:lang="id">Dokumen ODT</comment>
- <comment xml:lang="it">Documento ODT</comment>
- <comment xml:lang="ja">ODT ドキュメント</comment>
- <comment xml:lang="ka">ODT დოკუმენტი</comment>
- <comment xml:lang="kk">ODT құжаты</comment>
- <comment xml:lang="ko">ODT 문서</comment>
- <comment xml:lang="lt">ODT dokumentas</comment>
- <comment xml:lang="lv">ODT dokuments</comment>
- <comment xml:lang="nb">ODT-dokument</comment>
- <comment xml:lang="nl">ODT-document</comment>
- <comment xml:lang="nn">ODT-dokument</comment>
- <comment xml:lang="oc">document ODT</comment>
- <comment xml:lang="pl">Dokument ODT</comment>
- <comment xml:lang="pt">documento ODT</comment>
- <comment xml:lang="pt_BR">Documento ODT</comment>
- <comment xml:lang="ro">Document ODT</comment>
- <comment xml:lang="ru">Документ ODT</comment>
- <comment xml:lang="sk">Dokument ODT</comment>
- <comment xml:lang="sl">Dokument ODT</comment>
- <comment xml:lang="sq">Dokument ODT</comment>
- <comment xml:lang="sr">ОДТ документ</comment>
- <comment xml:lang="sv">ODT-dokument</comment>
- <comment xml:lang="tr">ODT belgesi</comment>
- <comment xml:lang="uk">документ ODT</comment>
- <comment xml:lang="vi">Tài liệu ODT</comment>
- <comment xml:lang="zh_CN">ODT 文档</comment>
<comment xml:lang="zh_TW">ODT 文件</comment>
+ <comment xml:lang="zh_CN">ODT 文档</comment>
+ <comment xml:lang="vi">Tài liệu ODT</comment>
+ <comment xml:lang="uk">документ ODT</comment>
+ <comment xml:lang="tr">ODT belgesi</comment>
+ <comment xml:lang="sv">ODT-dokument</comment>
+ <comment xml:lang="sr">ОДТ документ</comment>
+ <comment xml:lang="sq">dokument ODT</comment>
+ <comment xml:lang="sl">Dokument ODT</comment>
+ <comment xml:lang="si">ODT ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument ODT</comment>
+ <comment xml:lang="ru">Документ ODT</comment>
+ <comment xml:lang="ro">Document ODT</comment>
+ <comment xml:lang="pt_BR">Documento ODT</comment>
+ <comment xml:lang="pt">documento ODT</comment>
+ <comment xml:lang="pl">Dokument ODT</comment>
+ <comment xml:lang="oc">document ODT</comment>
+ <comment xml:lang="nn">ODT-dokument</comment>
+ <comment xml:lang="nl">ODT-document</comment>
+ <comment xml:lang="nb">ODT-dokument</comment>
+ <comment xml:lang="lv">ODT dokuments</comment>
+ <comment xml:lang="lt">ODT dokumentas</comment>
+ <comment xml:lang="ko">ODT 문서</comment>
+ <comment xml:lang="kk">ODT құжаты</comment>
+ <comment xml:lang="ka">ODT დოკუმენტი</comment>
+ <comment xml:lang="ja">ODT ドキュメント</comment>
+ <comment xml:lang="it">Documento ODT</comment>
+ <comment xml:lang="is">ODT skjal</comment>
+ <comment xml:lang="id">Dokumen ODT</comment>
+ <comment xml:lang="ia">Documento ODT</comment>
+ <comment xml:lang="hu">ODT-dokumentum</comment>
+ <comment xml:lang="hr">ODT dokument</comment>
+ <comment xml:lang="he">מסמך ODT</comment>
+ <comment xml:lang="gl">documento ODT</comment>
+ <comment xml:lang="ga">cáipéis ODT</comment>
+ <comment xml:lang="fur">document ODT</comment>
+ <comment xml:lang="fr">document ODT</comment>
+ <comment xml:lang="fo">ODT skjal</comment>
+ <comment xml:lang="fi">ODT-asiakirja</comment>
+ <comment xml:lang="eu">ODT dokumentua</comment>
+ <comment xml:lang="es">documento ODT</comment>
+ <comment xml:lang="eo">ODT-dokumento</comment>
+ <comment xml:lang="en_GB">ODT document</comment>
+ <comment xml:lang="el">Έγγραφο ODT</comment>
+ <comment xml:lang="de">ODT-Dokument</comment>
+ <comment xml:lang="da">ODT-dokument</comment>
+ <comment xml:lang="cs">dokument ODT</comment>
+ <comment xml:lang="ca">document ODT</comment>
+ <comment xml:lang="bg">Документ — ODT</comment>
+ <comment xml:lang="be@latin">Dakument ODT</comment>
+ <comment xml:lang="be">дакумент ODT</comment>
+ <comment xml:lang="ast">Documentu ODT</comment>
+ <comment xml:lang="ar">مستند ODT</comment>
+ <comment xml:lang="af">ODT-dokument</comment>
<acronym>ODT</acronym>
<expanded-acronym>OpenDocument Text</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.text" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.text" offset="38"/>
</match>
</match>
</magic>
@@ -5361,49 +5683,55 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.text-flat-xml">
<comment>ODT document (Flat XML)</comment>
- <comment xml:lang="ar">مستند ODT (Flat XML)</comment>
- <comment xml:lang="ast">Documentu ODT (XML planu)</comment>
- <comment xml:lang="bg">Документ — ODT (само XML)</comment>
- <comment xml:lang="ca">document ODT (XML pla)</comment>
- <comment xml:lang="cs">dokument ODT (Flat XML)</comment>
- <comment xml:lang="da">ODT-dokument (flad XML)</comment>
- <comment xml:lang="de">ODT-Dokument (Unkomprimiertes XML)</comment>
- <comment xml:lang="el">Έγγραφο ODT (Flat XML)</comment>
- <comment xml:lang="en_GB">ODT document (Flat XML)</comment>
- <comment xml:lang="es">documento ODT (XML plano)</comment>
- <comment xml:lang="eu">ODT dokumentua (XML soila)</comment>
- <comment xml:lang="fi">ODT-asiakirja (Flat XML)</comment>
- <comment xml:lang="fo">ODT skjal (Flat XML)</comment>
- <comment xml:lang="fr">document ODT (XML plat)</comment>
- <comment xml:lang="ga">cáipéis ODT (XML cothrom)</comment>
- <comment xml:lang="gl">documento ODT (XML plano)</comment>
- <comment xml:lang="he">מסמך ODT‏ (Flat XML)</comment>
- <comment xml:lang="hr">ODT dokument (Flat XML)</comment>
- <comment xml:lang="hu">ODT-dokumentum (egyszerű XML)</comment>
- <comment xml:lang="ia">Documento ODT (XML platte)</comment>
- <comment xml:lang="id">Dokumen ODT (Flat XML)</comment>
- <comment xml:lang="it">Documento ODT (XML semplice)</comment>
- <comment xml:lang="ja">ODT ドキュメント (Flat XML)</comment>
- <comment xml:lang="ka">ODT დოკუმენტი (Flat XML)</comment>
- <comment xml:lang="kk">ODT құжаты (Тек XML)</comment>
- <comment xml:lang="ko">ODT 문서(단일 XML)</comment>
- <comment xml:lang="lt">ODT dokumentas (Flat XML)</comment>
- <comment xml:lang="lv">ODT dokuments (plakans XML)</comment>
- <comment xml:lang="nl">ODT document (Flat XML)</comment>
- <comment xml:lang="oc">document ODT (XML plat)</comment>
- <comment xml:lang="pl">Dokument ODT (prosty XML)</comment>
- <comment xml:lang="pt">documento ODT (XML plano)</comment>
- <comment xml:lang="pt_BR">Documento ODT (Flat XML)</comment>
- <comment xml:lang="ro">Document ODT (XML simplu)</comment>
- <comment xml:lang="ru">Документ ODT (простой XML)</comment>
- <comment xml:lang="sk">Dokument ODT (čisté XML)</comment>
- <comment xml:lang="sl">Datoteka dokumenta ODT (nepovezan XML)</comment>
- <comment xml:lang="sr">ОДТ документ (Обични ИксМЛ)</comment>
- <comment xml:lang="sv">ODT-dokument (platt XML)</comment>
- <comment xml:lang="tr">ODT belgesi (Düz XML)</comment>
- <comment xml:lang="uk">документ ODT (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODT 文档(Flat XML)</comment>
<comment xml:lang="zh_TW">ODT 文件 (Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODT 文档(Flat XML)</comment>
+ <comment xml:lang="uk">документ ODT (Flat XML)</comment>
+ <comment xml:lang="tr">ODT belgesi (Düz XML)</comment>
+ <comment xml:lang="sv">ODT-dokument (platt XML)</comment>
+ <comment xml:lang="sr">ОДТ документ (Обични ИксМЛ)</comment>
+ <comment xml:lang="sq">dokument ODT (Flat XML)</comment>
+ <comment xml:lang="sl">Datoteka dokumenta ODT (nepovezan XML)</comment>
+ <comment xml:lang="si">ODT ලේඛනය (පැතලි XML)</comment>
+ <comment xml:lang="sk">Dokument ODT (čisté XML)</comment>
+ <comment xml:lang="ru">Документ ODT (простой XML)</comment>
+ <comment xml:lang="ro">Document ODT (XML simplu)</comment>
+ <comment xml:lang="pt_BR">Documento ODT (Flat XML)</comment>
+ <comment xml:lang="pt">documento ODT (XML plano)</comment>
+ <comment xml:lang="pl">Dokument ODT (prosty XML)</comment>
+ <comment xml:lang="oc">document ODT (XML plat)</comment>
+ <comment xml:lang="nl">ODT document (Flat XML)</comment>
+ <comment xml:lang="lv">ODT dokuments (plakans XML)</comment>
+ <comment xml:lang="lt">ODT dokumentas (Flat XML)</comment>
+ <comment xml:lang="ko">ODT 문서(단일 XML)</comment>
+ <comment xml:lang="kk">ODT құжаты (Тек XML)</comment>
+ <comment xml:lang="ka">ODT დოკუმენტი (Flat XML)</comment>
+ <comment xml:lang="ja">ODT ドキュメント (Flat XML)</comment>
+ <comment xml:lang="it">Documento ODT (XML semplice)</comment>
+ <comment xml:lang="is">ODT skjal (flatt XML)</comment>
+ <comment xml:lang="id">Dokumen ODT (Flat XML)</comment>
+ <comment xml:lang="ia">Documento ODT (XML platte)</comment>
+ <comment xml:lang="hu">ODT-dokumentum (egyszerű XML)</comment>
+ <comment xml:lang="hr">ODT dokument (Flat XML)</comment>
+ <comment xml:lang="he">מסמך ODT‏ (Flat XML)</comment>
+ <comment xml:lang="gl">documento ODT (XML plano)</comment>
+ <comment xml:lang="ga">cáipéis ODT (XML cothrom)</comment>
+ <comment xml:lang="fur">document ODT (XML sempliç)</comment>
+ <comment xml:lang="fr">document ODT (XML plat)</comment>
+ <comment xml:lang="fo">ODT skjal (Flat XML)</comment>
+ <comment xml:lang="fi">ODT-asiakirja (Flat XML)</comment>
+ <comment xml:lang="eu">ODT dokumentua (XML soila)</comment>
+ <comment xml:lang="es">documento ODT (XML plano)</comment>
+ <comment xml:lang="en_GB">ODT document (Flat XML)</comment>
+ <comment xml:lang="el">Έγγραφο ODT (Flat XML)</comment>
+ <comment xml:lang="de">ODT-Dokument (einfaches XML)</comment>
+ <comment xml:lang="da">ODT-dokument (flad XML)</comment>
+ <comment xml:lang="cs">dokument ODT (Flat XML)</comment>
+ <comment xml:lang="ca">document ODT (XML pla)</comment>
+ <comment xml:lang="bg">Документ — ODT (само XML)</comment>
+ <comment xml:lang="be">дакумент ODT (плоскі XML)</comment>
+ <comment xml:lang="ast">Documentu ODT (XML planu)</comment>
+ <comment xml:lang="ar">مستند ODT (Flat XML)</comment>
+ <comment xml:lang="af">ODT-dokument (plat XML)</comment>
<acronym>FODT</acronym>
<expanded-acronym>OpenDocument Text (Flat XML)</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -5412,62 +5740,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.text-template">
<comment>ODT template</comment>
- <comment xml:lang="ar">قالب ODT</comment>
- <comment xml:lang="be@latin">Šablon ODT</comment>
- <comment xml:lang="bg">Шаблон за документи — ODT</comment>
- <comment xml:lang="ca">plantilla ODT</comment>
- <comment xml:lang="cs">šablona ODT</comment>
- <comment xml:lang="da">ODT-skabelon</comment>
- <comment xml:lang="de">ODT-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο ODT</comment>
- <comment xml:lang="en_GB">ODT template</comment>
- <comment xml:lang="eo">ODT-ŝablono</comment>
- <comment xml:lang="es">plantilla ODT</comment>
- <comment xml:lang="eu">ODT txantiloia</comment>
- <comment xml:lang="fi">ODT-malli</comment>
- <comment xml:lang="fo">ODT formur</comment>
- <comment xml:lang="fr">modèle ODT</comment>
- <comment xml:lang="ga">teimpléad ODT</comment>
- <comment xml:lang="gl">modelo ODT</comment>
- <comment xml:lang="he">תבנית ODT</comment>
- <comment xml:lang="hr">ODT predložak</comment>
- <comment xml:lang="hu">ODT-sablon</comment>
- <comment xml:lang="ia">Patrono ODT</comment>
- <comment xml:lang="id">Templat ODT</comment>
- <comment xml:lang="it">Modello ODT</comment>
- <comment xml:lang="ja">ODT テンプレート</comment>
- <comment xml:lang="ka">ODT დოკუმენტი</comment>
- <comment xml:lang="kk">ODT үлгісі</comment>
- <comment xml:lang="ko">ODT 문서 서식</comment>
- <comment xml:lang="lt">ODT šablonas</comment>
- <comment xml:lang="lv">ODT veidne</comment>
- <comment xml:lang="nb">ODT-mal</comment>
- <comment xml:lang="nl">ODT-sjabloon</comment>
- <comment xml:lang="nn">ODT-mal</comment>
- <comment xml:lang="oc">modèl ODT</comment>
- <comment xml:lang="pl">Szablon ODT</comment>
- <comment xml:lang="pt">modelo ODT</comment>
- <comment xml:lang="pt_BR">Modelo ODT</comment>
- <comment xml:lang="ro">Șablon ODT</comment>
- <comment xml:lang="ru">Шаблон ODT</comment>
- <comment xml:lang="sk">Šablóna ODT</comment>
- <comment xml:lang="sl">Predloga dokumenta ODT</comment>
- <comment xml:lang="sq">Model ODT</comment>
- <comment xml:lang="sr">ОДТ шаблон</comment>
- <comment xml:lang="sv">ODT-mall</comment>
- <comment xml:lang="tr">ODT şablonu</comment>
- <comment xml:lang="uk">шаблон ODT</comment>
- <comment xml:lang="vi">Mẫu ODT</comment>
- <comment xml:lang="zh_CN">ODT 模板</comment>
<comment xml:lang="zh_TW">ODT 範本</comment>
+ <comment xml:lang="zh_CN">ODT 模板</comment>
+ <comment xml:lang="vi">Mẫu ODT</comment>
+ <comment xml:lang="uk">шаблон ODT</comment>
+ <comment xml:lang="tr">ODT şablonu</comment>
+ <comment xml:lang="sv">ODT-mall</comment>
+ <comment xml:lang="sr">ОДТ шаблон</comment>
+ <comment xml:lang="sq">gjedhe ODT</comment>
+ <comment xml:lang="sl">Predloga dokumenta ODT</comment>
+ <comment xml:lang="si">ODT අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna ODT</comment>
+ <comment xml:lang="ru">Шаблон ODT</comment>
+ <comment xml:lang="ro">Șablon ODT</comment>
+ <comment xml:lang="pt_BR">Modelo ODT</comment>
+ <comment xml:lang="pt">modelo ODT</comment>
+ <comment xml:lang="pl">Szablon ODT</comment>
+ <comment xml:lang="oc">modèl ODT</comment>
+ <comment xml:lang="nn">ODT-mal</comment>
+ <comment xml:lang="nl">ODT-sjabloon</comment>
+ <comment xml:lang="nb">ODT-mal</comment>
+ <comment xml:lang="lv">ODT veidne</comment>
+ <comment xml:lang="lt">ODT šablonas</comment>
+ <comment xml:lang="ko">ODT 문서 서식</comment>
+ <comment xml:lang="kk">ODT үлгісі</comment>
+ <comment xml:lang="ka">ODT დოკუმენტი</comment>
+ <comment xml:lang="ja">ODT テンプレート</comment>
+ <comment xml:lang="it">Modello ODT</comment>
+ <comment xml:lang="is">ODT sniðmát</comment>
+ <comment xml:lang="id">Templat ODT</comment>
+ <comment xml:lang="ia">Patrono ODT</comment>
+ <comment xml:lang="hu">ODT-sablon</comment>
+ <comment xml:lang="hr">ODT predložak</comment>
+ <comment xml:lang="he">תבנית ODT</comment>
+ <comment xml:lang="gl">modelo ODT</comment>
+ <comment xml:lang="ga">teimpléad ODT</comment>
+ <comment xml:lang="fur">model ODT</comment>
+ <comment xml:lang="fr">modèle ODT</comment>
+ <comment xml:lang="fo">ODT formur</comment>
+ <comment xml:lang="fi">ODT-malli</comment>
+ <comment xml:lang="eu">ODT txantiloia</comment>
+ <comment xml:lang="es">plantilla ODT</comment>
+ <comment xml:lang="eo">ODT-ŝablono</comment>
+ <comment xml:lang="en_GB">ODT template</comment>
+ <comment xml:lang="el">Πρότυπο ODT</comment>
+ <comment xml:lang="de">ODT-Vorlage</comment>
+ <comment xml:lang="da">ODT-skabelon</comment>
+ <comment xml:lang="cs">šablona ODT</comment>
+ <comment xml:lang="ca">plantilla ODT</comment>
+ <comment xml:lang="bg">Шаблон за документи — ODT</comment>
+ <comment xml:lang="be@latin">Šablon ODT</comment>
+ <comment xml:lang="be">шаблон ODT</comment>
+ <comment xml:lang="ar">قالب ODT</comment>
+ <comment xml:lang="af">ODT-sjabloon</comment>
<acronym>ODT</acronym>
<expanded-acronym>OpenDocument Text</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.text-template" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.text-template" offset="38"/>
</match>
</match>
</magic>
@@ -5475,62 +5808,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.text-web">
<comment>OTH template</comment>
- <comment xml:lang="ar">قالب OTH</comment>
- <comment xml:lang="be@latin">Šablon OTH</comment>
- <comment xml:lang="bg">Шаблон за страници — OTH</comment>
- <comment xml:lang="ca">plantilla OTH</comment>
- <comment xml:lang="cs">šablona OTH</comment>
- <comment xml:lang="da">OTH-skabelon</comment>
- <comment xml:lang="de">OTH-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο OTH</comment>
- <comment xml:lang="en_GB">OTH template</comment>
- <comment xml:lang="eo">OTH-ŝablono</comment>
- <comment xml:lang="es">plantilla OTH</comment>
- <comment xml:lang="eu">OTH txantiloia</comment>
- <comment xml:lang="fi">OTH-malli</comment>
- <comment xml:lang="fo">OTH formur</comment>
- <comment xml:lang="fr">modèle OTH</comment>
- <comment xml:lang="ga">teimpléad OTH</comment>
- <comment xml:lang="gl">modelo OTH</comment>
- <comment xml:lang="he">תבנית OTH</comment>
- <comment xml:lang="hr">OTH predložak</comment>
- <comment xml:lang="hu">OTH-sablon</comment>
- <comment xml:lang="ia">Patrono OTH</comment>
- <comment xml:lang="id">Templat OTH</comment>
- <comment xml:lang="it">Modello OTH</comment>
- <comment xml:lang="ja">OTH テンプレート</comment>
- <comment xml:lang="ka">OTH შაბლონი</comment>
- <comment xml:lang="kk">OTH үлгісі</comment>
- <comment xml:lang="ko">OTH 문서 서식</comment>
- <comment xml:lang="lt">OTH šablonas</comment>
- <comment xml:lang="lv">OTH veidne</comment>
- <comment xml:lang="nb">OTH-mal</comment>
- <comment xml:lang="nl">OTH-sjabloon</comment>
- <comment xml:lang="nn">OTH-mal</comment>
- <comment xml:lang="oc">modèl OTH</comment>
- <comment xml:lang="pl">Szablon OTH</comment>
- <comment xml:lang="pt">modelo OTH</comment>
- <comment xml:lang="pt_BR">Modelo OTH</comment>
- <comment xml:lang="ro">Șablon OTH</comment>
- <comment xml:lang="ru">Шаблон OTH</comment>
- <comment xml:lang="sk">Šablóna OTH</comment>
- <comment xml:lang="sl">Predloga OTH</comment>
- <comment xml:lang="sq">Model OTH</comment>
- <comment xml:lang="sr">ОТХ шаблон</comment>
- <comment xml:lang="sv">OTH-mall</comment>
- <comment xml:lang="tr">OTH şablonu</comment>
- <comment xml:lang="uk">шаблон OTH</comment>
- <comment xml:lang="vi">Mẫu ODH</comment>
- <comment xml:lang="zh_CN">OTH 模板</comment>
<comment xml:lang="zh_TW">OTH 範本</comment>
+ <comment xml:lang="zh_CN">OTH 模板</comment>
+ <comment xml:lang="vi">Mẫu ODH</comment>
+ <comment xml:lang="uk">шаблон OTH</comment>
+ <comment xml:lang="tr">OTH şablonu</comment>
+ <comment xml:lang="sv">OTH-mall</comment>
+ <comment xml:lang="sr">ОТХ шаблон</comment>
+ <comment xml:lang="sq">gjedhe OTH</comment>
+ <comment xml:lang="sl">Predloga OTH</comment>
+ <comment xml:lang="si">OTH අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna OTH</comment>
+ <comment xml:lang="ru">Шаблон OTH</comment>
+ <comment xml:lang="ro">Șablon OTH</comment>
+ <comment xml:lang="pt_BR">Modelo OTH</comment>
+ <comment xml:lang="pt">modelo OTH</comment>
+ <comment xml:lang="pl">Szablon OTH</comment>
+ <comment xml:lang="oc">modèl OTH</comment>
+ <comment xml:lang="nn">OTH-mal</comment>
+ <comment xml:lang="nl">OTH-sjabloon</comment>
+ <comment xml:lang="nb">OTH-mal</comment>
+ <comment xml:lang="lv">OTH veidne</comment>
+ <comment xml:lang="lt">OTH šablonas</comment>
+ <comment xml:lang="ko">OTH 문서 서식</comment>
+ <comment xml:lang="kk">OTH үлгісі</comment>
+ <comment xml:lang="ka">OTH შაბლონი</comment>
+ <comment xml:lang="ja">OTH テンプレート</comment>
+ <comment xml:lang="it">Modello OTH</comment>
+ <comment xml:lang="is">OTH sniðmát</comment>
+ <comment xml:lang="id">Templat OTH</comment>
+ <comment xml:lang="ia">Patrono OTH</comment>
+ <comment xml:lang="hu">OTH-sablon</comment>
+ <comment xml:lang="hr">OTH predložak</comment>
+ <comment xml:lang="he">תבנית OTH</comment>
+ <comment xml:lang="gl">modelo OTH</comment>
+ <comment xml:lang="ga">teimpléad OTH</comment>
+ <comment xml:lang="fur">model OTH</comment>
+ <comment xml:lang="fr">modèle OTH</comment>
+ <comment xml:lang="fo">OTH formur</comment>
+ <comment xml:lang="fi">OTH-malli</comment>
+ <comment xml:lang="eu">OTH txantiloia</comment>
+ <comment xml:lang="es">plantilla OTH</comment>
+ <comment xml:lang="eo">OTH-ŝablono</comment>
+ <comment xml:lang="en_GB">OTH template</comment>
+ <comment xml:lang="el">Πρότυπο OTH</comment>
+ <comment xml:lang="de">OTH-Vorlage</comment>
+ <comment xml:lang="da">OTH-skabelon</comment>
+ <comment xml:lang="cs">šablona OTH</comment>
+ <comment xml:lang="ca">plantilla OTH</comment>
+ <comment xml:lang="bg">Шаблон за страници — OTH</comment>
+ <comment xml:lang="be@latin">Šablon OTH</comment>
+ <comment xml:lang="be">шаблон OTH</comment>
+ <comment xml:lang="ar">قالب OTH</comment>
+ <comment xml:lang="af">OTH-sjabloon</comment>
<acronym>OTH</acronym>
<expanded-acronym>OpenDocument HTML</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="text-html"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.text-web" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.text-web" offset="38"/>
</match>
</match>
</magic>
@@ -5538,63 +5876,68 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.text-master">
<comment>ODM document</comment>
- <comment xml:lang="ar">مستند ODM</comment>
- <comment xml:lang="ast">Documentu ODM</comment>
- <comment xml:lang="be@latin">Dakument ODM</comment>
- <comment xml:lang="bg">Документ — ODM</comment>
- <comment xml:lang="ca">document ODM</comment>
- <comment xml:lang="cs">dokument ODM</comment>
- <comment xml:lang="da">ODM-dokument</comment>
- <comment xml:lang="de">ODM-Dokument</comment>
- <comment xml:lang="el">Έγγραφο ODM</comment>
- <comment xml:lang="en_GB">ODM document</comment>
- <comment xml:lang="eo">ODM-dokumento</comment>
- <comment xml:lang="es">documento ODM</comment>
- <comment xml:lang="eu">ODM dokumentua</comment>
- <comment xml:lang="fi">ODM-asiakirja</comment>
- <comment xml:lang="fo">ODM skjal</comment>
- <comment xml:lang="fr">document ODM</comment>
- <comment xml:lang="ga">cáipéis ODM</comment>
- <comment xml:lang="gl">documento ODM</comment>
- <comment xml:lang="he">מסמך ODM</comment>
- <comment xml:lang="hr">ODM dokument</comment>
- <comment xml:lang="hu">ODM-dokumentum</comment>
- <comment xml:lang="ia">Documento ODM</comment>
- <comment xml:lang="id">Dokumen ODM</comment>
- <comment xml:lang="it">Documento ODM</comment>
- <comment xml:lang="ja">ODM ドキュメント</comment>
- <comment xml:lang="ka">ODM დოკუმენტი</comment>
- <comment xml:lang="kk">ODM құжаты</comment>
- <comment xml:lang="ko">ODM 문서</comment>
- <comment xml:lang="lt">ODM dokumentas</comment>
- <comment xml:lang="lv">ODM dokuments</comment>
- <comment xml:lang="nb">ODM-dokument</comment>
- <comment xml:lang="nl">ODM-document</comment>
- <comment xml:lang="nn">ODM-dokument</comment>
- <comment xml:lang="oc">document ODM</comment>
- <comment xml:lang="pl">Dokument ODM</comment>
- <comment xml:lang="pt">documento ODM</comment>
- <comment xml:lang="pt_BR">Documento ODM</comment>
- <comment xml:lang="ro">Document ODM</comment>
- <comment xml:lang="ru">Документ ODM</comment>
- <comment xml:lang="sk">Dokument ODM</comment>
- <comment xml:lang="sl">Dokument ODM</comment>
- <comment xml:lang="sq">Dokument ODM</comment>
- <comment xml:lang="sr">ОДМ документ</comment>
- <comment xml:lang="sv">ODM-dokument</comment>
- <comment xml:lang="tr">ODM belgesi</comment>
- <comment xml:lang="uk">документ ODM</comment>
- <comment xml:lang="vi">Tài liệu ODM</comment>
- <comment xml:lang="zh_CN">ODM 文档</comment>
<comment xml:lang="zh_TW">ODM 文件</comment>
+ <comment xml:lang="zh_CN">ODM 文档</comment>
+ <comment xml:lang="vi">Tài liệu ODM</comment>
+ <comment xml:lang="uk">документ ODM</comment>
+ <comment xml:lang="tr">ODM belgesi</comment>
+ <comment xml:lang="sv">ODM-dokument</comment>
+ <comment xml:lang="sr">ОДМ документ</comment>
+ <comment xml:lang="sq">dokument ODM</comment>
+ <comment xml:lang="sl">Dokument ODM</comment>
+ <comment xml:lang="si">ODM ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument ODM</comment>
+ <comment xml:lang="ru">Документ ODM</comment>
+ <comment xml:lang="ro">Document ODM</comment>
+ <comment xml:lang="pt_BR">Documento ODM</comment>
+ <comment xml:lang="pt">documento ODM</comment>
+ <comment xml:lang="pl">Dokument ODM</comment>
+ <comment xml:lang="oc">document ODM</comment>
+ <comment xml:lang="nn">ODM-dokument</comment>
+ <comment xml:lang="nl">ODM-document</comment>
+ <comment xml:lang="nb">ODM-dokument</comment>
+ <comment xml:lang="lv">ODM dokuments</comment>
+ <comment xml:lang="lt">ODM dokumentas</comment>
+ <comment xml:lang="ko">ODM 문서</comment>
+ <comment xml:lang="kk">ODM құжаты</comment>
+ <comment xml:lang="ka">ODM დოკუმენტი</comment>
+ <comment xml:lang="ja">ODM ドキュメント</comment>
+ <comment xml:lang="it">Documento ODM</comment>
+ <comment xml:lang="is">ODM skjal</comment>
+ <comment xml:lang="id">Dokumen ODM</comment>
+ <comment xml:lang="ia">Documento ODM</comment>
+ <comment xml:lang="hu">ODM-dokumentum</comment>
+ <comment xml:lang="hr">ODM dokument</comment>
+ <comment xml:lang="he">מסמך ODM</comment>
+ <comment xml:lang="gl">documento ODM</comment>
+ <comment xml:lang="ga">cáipéis ODM</comment>
+ <comment xml:lang="fur">document ODM</comment>
+ <comment xml:lang="fr">document ODM</comment>
+ <comment xml:lang="fo">ODM skjal</comment>
+ <comment xml:lang="fi">ODM-asiakirja</comment>
+ <comment xml:lang="eu">ODM dokumentua</comment>
+ <comment xml:lang="es">documento ODM</comment>
+ <comment xml:lang="eo">ODM-dokumento</comment>
+ <comment xml:lang="en_GB">ODM document</comment>
+ <comment xml:lang="el">Έγγραφο ODM</comment>
+ <comment xml:lang="de">ODM-Dokument</comment>
+ <comment xml:lang="da">ODM-dokument</comment>
+ <comment xml:lang="cs">dokument ODM</comment>
+ <comment xml:lang="ca">document ODM</comment>
+ <comment xml:lang="bg">Документ — ODM</comment>
+ <comment xml:lang="be@latin">Dakument ODM</comment>
+ <comment xml:lang="be">дакумент ODM</comment>
+ <comment xml:lang="ast">Documentu ODM</comment>
+ <comment xml:lang="ar">مستند ODM</comment>
+ <comment xml:lang="af">ODM-dokument</comment>
<acronym>ODM</acronym>
<expanded-acronym>OpenDocument Master</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.text-master" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.text-master" offset="38"/>
</match>
</match>
</magic>
@@ -5602,62 +5945,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.graphics">
<comment>ODG drawing</comment>
- <comment xml:lang="ar">تصميم ODG</comment>
- <comment xml:lang="be@latin">Rysunak ODG</comment>
- <comment xml:lang="bg">Чертеж — ODG</comment>
- <comment xml:lang="ca">dibuix ODG</comment>
- <comment xml:lang="cs">kresba ODG</comment>
- <comment xml:lang="da">ODG-tegning</comment>
- <comment xml:lang="de">ODG-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο ODG</comment>
- <comment xml:lang="en_GB">ODG drawing</comment>
- <comment xml:lang="eo">ODG-desegnaĵo</comment>
- <comment xml:lang="es">dibujo ODG</comment>
- <comment xml:lang="eu">ODG marrazkia</comment>
- <comment xml:lang="fi">ODG-piirros</comment>
- <comment xml:lang="fo">ODG tekning</comment>
- <comment xml:lang="fr">dessin ODG</comment>
- <comment xml:lang="ga">líníocht ODG</comment>
- <comment xml:lang="gl">debuxo ODG</comment>
- <comment xml:lang="he">ציור ODG</comment>
- <comment xml:lang="hr">ODG crtež</comment>
- <comment xml:lang="hu">ODG-rajz</comment>
- <comment xml:lang="ia">Designo ODG</comment>
- <comment xml:lang="id">Gambar ODG</comment>
- <comment xml:lang="it">Disegno ODG</comment>
- <comment xml:lang="ja">ODG ドロー</comment>
- <comment xml:lang="ka">ODG-ის ნახაზი</comment>
- <comment xml:lang="kk">ODG суреті</comment>
- <comment xml:lang="ko">ODG 드로잉</comment>
- <comment xml:lang="lt">ODG piešinys</comment>
- <comment xml:lang="lv">ODG zīmējums</comment>
- <comment xml:lang="nb">ODG-tegning</comment>
- <comment xml:lang="nl">ODG-tekening</comment>
- <comment xml:lang="nn">ODG-teikning</comment>
- <comment xml:lang="oc">dessenh ODG</comment>
- <comment xml:lang="pl">Rysunek ODG</comment>
- <comment xml:lang="pt">desenho ODG</comment>
- <comment xml:lang="pt_BR">Desenho ODG</comment>
- <comment xml:lang="ro">Desen ODG</comment>
- <comment xml:lang="ru">Рисунок ODG</comment>
- <comment xml:lang="sk">Kresba ODG</comment>
- <comment xml:lang="sl">Datoteka risbe ODG</comment>
- <comment xml:lang="sq">Vizatim ODG</comment>
- <comment xml:lang="sr">ОДГ цртеж</comment>
- <comment xml:lang="sv">ODG-teckning</comment>
- <comment xml:lang="tr">ODG çizimi</comment>
- <comment xml:lang="uk">малюнок ODG</comment>
- <comment xml:lang="vi">Bản vẽ ODG</comment>
- <comment xml:lang="zh_CN">ODG 绘图</comment>
<comment xml:lang="zh_TW">ODG 繪圖</comment>
+ <comment xml:lang="zh_CN">ODG 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ ODG</comment>
+ <comment xml:lang="uk">малюнок ODG</comment>
+ <comment xml:lang="tr">ODG çizimi</comment>
+ <comment xml:lang="sv">ODG-teckning</comment>
+ <comment xml:lang="sr">ОДГ цртеж</comment>
+ <comment xml:lang="sq">vizatim ODG</comment>
+ <comment xml:lang="sl">Datoteka risbe ODG</comment>
+ <comment xml:lang="si">ODG ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba ODG</comment>
+ <comment xml:lang="ru">Рисунок ODG</comment>
+ <comment xml:lang="ro">Desen ODG</comment>
+ <comment xml:lang="pt_BR">Desenho ODG</comment>
+ <comment xml:lang="pt">desenho ODG</comment>
+ <comment xml:lang="pl">Rysunek ODG</comment>
+ <comment xml:lang="oc">dessenh ODG</comment>
+ <comment xml:lang="nn">ODG-teikning</comment>
+ <comment xml:lang="nl">ODG-tekening</comment>
+ <comment xml:lang="nb">ODG-tegning</comment>
+ <comment xml:lang="lv">ODG zīmējums</comment>
+ <comment xml:lang="lt">ODG piešinys</comment>
+ <comment xml:lang="ko">ODG 드로잉</comment>
+ <comment xml:lang="kk">ODG суреті</comment>
+ <comment xml:lang="ka">ODG-ის ნახაზი</comment>
+ <comment xml:lang="ja">ODG ドロー</comment>
+ <comment xml:lang="it">Disegno ODG</comment>
+ <comment xml:lang="is">ODG teikning</comment>
+ <comment xml:lang="id">Gambar ODG</comment>
+ <comment xml:lang="ia">Designo ODG</comment>
+ <comment xml:lang="hu">ODG-rajz</comment>
+ <comment xml:lang="hr">ODG crtež</comment>
+ <comment xml:lang="he">ציור ODG</comment>
+ <comment xml:lang="gl">debuxo ODG</comment>
+ <comment xml:lang="ga">líníocht ODG</comment>
+ <comment xml:lang="fur">dissen ODG</comment>
+ <comment xml:lang="fr">dessin ODG</comment>
+ <comment xml:lang="fo">ODG tekning</comment>
+ <comment xml:lang="fi">ODG-piirros</comment>
+ <comment xml:lang="eu">ODG marrazkia</comment>
+ <comment xml:lang="es">dibujo ODG</comment>
+ <comment xml:lang="eo">ODG-desegnaĵo</comment>
+ <comment xml:lang="en_GB">ODG drawing</comment>
+ <comment xml:lang="el">Σχέδιο ODG</comment>
+ <comment xml:lang="de">ODG-Zeichnung</comment>
+ <comment xml:lang="da">ODG-tegning</comment>
+ <comment xml:lang="cs">kresba ODG</comment>
+ <comment xml:lang="ca">dibuix ODG</comment>
+ <comment xml:lang="bg">Чертеж — ODG</comment>
+ <comment xml:lang="be@latin">Rysunak ODG</comment>
+ <comment xml:lang="be">рысунак ODG</comment>
+ <comment xml:lang="ar">تصميم ODG</comment>
+ <comment xml:lang="af">ODG-tekening</comment>
<acronym>ODG</acronym>
<expanded-acronym>OpenDocument Drawing</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.graphics" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.graphics" offset="38"/>
</match>
</match>
</magic>
@@ -5665,48 +6013,54 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.graphics-flat-xml">
<comment>ODG drawing (Flat XML)</comment>
- <comment xml:lang="ar">رسمة ODG (Flat XML)</comment>
- <comment xml:lang="bg">Чертеж — ODG (само XML)</comment>
- <comment xml:lang="ca">dibuix ODG (XML pla) </comment>
- <comment xml:lang="cs">kresba ODG (Flat XML)</comment>
- <comment xml:lang="da">ODG-tegning (flad XML)</comment>
- <comment xml:lang="de">ODG-Zeichnung (Unkomprimiertes XML)</comment>
- <comment xml:lang="el">Σχέδιο ODG (Flat XML)</comment>
- <comment xml:lang="en_GB">ODG drawing (Flat XML)</comment>
- <comment xml:lang="es">dibujo ODG (XML plano)</comment>
- <comment xml:lang="eu">ODG marrazkia (XML soila)</comment>
- <comment xml:lang="fi">ODG-piirros (Flat XML)</comment>
- <comment xml:lang="fo">ODG tekning (Flat XML)</comment>
- <comment xml:lang="fr">dessin ODG (XML plat)</comment>
- <comment xml:lang="ga">líníocht ODG (XML cothrom)</comment>
- <comment xml:lang="gl">debuxo ODB (XML plano)</comment>
- <comment xml:lang="he">ציור ODG (Flat XML(</comment>
- <comment xml:lang="hr">ODG crtež (Flat XML)</comment>
- <comment xml:lang="hu">ODG-rajz (egyszerű XML)</comment>
- <comment xml:lang="ia">Designo ODG (XML platte)</comment>
- <comment xml:lang="id">Gambar ODG (FLAT XML)</comment>
- <comment xml:lang="it">Disegno ODG (XML semplice)</comment>
- <comment xml:lang="ja">ODG ドロー (Flat XML)</comment>
- <comment xml:lang="ka">ODG-ის ნახაზი (Flat XML)</comment>
- <comment xml:lang="kk">ODG сызбасы (Тек XML)</comment>
- <comment xml:lang="ko">ODG 드로잉(단일 XML)</comment>
- <comment xml:lang="lt">ODG piešinys (Flat XML)</comment>
- <comment xml:lang="lv">ODG zīmējums (plakans XML)</comment>
- <comment xml:lang="nl">ODG-tekening (Flat XML)</comment>
- <comment xml:lang="oc">dessenh ODG (XML plat)</comment>
- <comment xml:lang="pl">Rysunek ODG (prosty XML)</comment>
- <comment xml:lang="pt">desenho ODG (XML plano)</comment>
- <comment xml:lang="pt_BR">Desenho ODG (Flat XML)</comment>
- <comment xml:lang="ro">Desen ODG (XML simplu)</comment>
- <comment xml:lang="ru">Рисунок ODG (простой XML)</comment>
- <comment xml:lang="sk">Kresba ODG (čisté XML)</comment>
- <comment xml:lang="sl">Datoteka risbe ODG (nepovezan XML)</comment>
- <comment xml:lang="sr">ОДГ цртеж (Обичан ИксМЛ)</comment>
- <comment xml:lang="sv">ODG-teckning (platt XML)</comment>
- <comment xml:lang="tr">ODG çizimi (Düz XML)</comment>
- <comment xml:lang="uk">малюнок ODG (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODG 绘图(Flat XML)</comment>
<comment xml:lang="zh_TW">ODG 繪圖 (Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODG 绘图(Flat XML)</comment>
+ <comment xml:lang="uk">малюнок ODG (простий XML)</comment>
+ <comment xml:lang="tr">ODG çizimi (Düz XML)</comment>
+ <comment xml:lang="sv">ODG-teckning (platt XML)</comment>
+ <comment xml:lang="sr">ОДГ цртеж (Обичан ИксМЛ)</comment>
+ <comment xml:lang="sq">vizatim ODF (Flat XML)</comment>
+ <comment xml:lang="sl">Datoteka risbe ODG (nepovezan XML)</comment>
+ <comment xml:lang="si">ODG ඇඳීම (පැතලි XML)</comment>
+ <comment xml:lang="sk">Kresba ODG (čisté XML)</comment>
+ <comment xml:lang="ru">Рисунок ODG (простой XML)</comment>
+ <comment xml:lang="ro">Desen ODG (XML simplu)</comment>
+ <comment xml:lang="pt_BR">Desenho ODG (Flat XML)</comment>
+ <comment xml:lang="pt">desenho ODG (XML plano)</comment>
+ <comment xml:lang="pl">Rysunek ODG (prosty XML)</comment>
+ <comment xml:lang="oc">dessenh ODG (XML plat)</comment>
+ <comment xml:lang="nl">ODG-tekening (Flat XML)</comment>
+ <comment xml:lang="lv">ODG zīmējums (plakans XML)</comment>
+ <comment xml:lang="lt">ODG piešinys (Flat XML)</comment>
+ <comment xml:lang="ko">ODG 드로잉(단일 XML)</comment>
+ <comment xml:lang="kk">ODG сызбасы (Тек XML)</comment>
+ <comment xml:lang="ka">ODG-ის ნახაზი (Flat XML)</comment>
+ <comment xml:lang="ja">ODG ドロー (Flat XML)</comment>
+ <comment xml:lang="it">Disegno ODG (XML semplice)</comment>
+ <comment xml:lang="is">ODG teikning (flatt XML)</comment>
+ <comment xml:lang="id">Gambar ODG (FLAT XML)</comment>
+ <comment xml:lang="ia">Designo ODG (XML platte)</comment>
+ <comment xml:lang="hu">ODG-rajz (egyszerű XML)</comment>
+ <comment xml:lang="hr">ODG crtež (Flat XML)</comment>
+ <comment xml:lang="he">ציור ODG ‏(Flat XML)</comment>
+ <comment xml:lang="gl">debuxo ODB (XML plano)</comment>
+ <comment xml:lang="ga">líníocht ODG (XML cothrom)</comment>
+ <comment xml:lang="fur">dissen ODG (XML sempliç)</comment>
+ <comment xml:lang="fr">dessin ODG (XML plat)</comment>
+ <comment xml:lang="fo">ODG tekning (Flat XML)</comment>
+ <comment xml:lang="fi">ODG-piirros (Flat XML)</comment>
+ <comment xml:lang="eu">ODG marrazkia (XML soila)</comment>
+ <comment xml:lang="es">dibujo ODG (XML plano)</comment>
+ <comment xml:lang="en_GB">ODG drawing (Flat XML)</comment>
+ <comment xml:lang="el">Σχέδιο ODG (Flat XML)</comment>
+ <comment xml:lang="de">ODG-Zeichnung (einfaches XML)</comment>
+ <comment xml:lang="da">ODG-tegning (flad XML)</comment>
+ <comment xml:lang="cs">kresba ODG (Flat XML)</comment>
+ <comment xml:lang="ca">dibuix ODG (XML pla) </comment>
+ <comment xml:lang="bg">Чертеж — ODG (само XML)</comment>
+ <comment xml:lang="be">рысунак ODG (плоскі XML)</comment>
+ <comment xml:lang="ar">رسمة ODG (Flat XML)</comment>
+ <comment xml:lang="af">ODG-tekening (plat XML)</comment>
<acronym>FODG</acronym>
<expanded-acronym>OpenDocument Drawing (Flat XML)</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -5715,62 +6069,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.graphics-template">
<comment>ODG template</comment>
- <comment xml:lang="ar">قالب ODG</comment>
- <comment xml:lang="be@latin">Šablon ODG</comment>
- <comment xml:lang="bg">Шаблон за чертежи — ODG</comment>
- <comment xml:lang="ca">plantilla ODG</comment>
- <comment xml:lang="cs">šablona ODG</comment>
- <comment xml:lang="da">ODG-skabelon</comment>
- <comment xml:lang="de">ODG-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο ODG</comment>
- <comment xml:lang="en_GB">ODG template</comment>
- <comment xml:lang="eo">ODG-ŝablono</comment>
- <comment xml:lang="es">plantilla ODG</comment>
- <comment xml:lang="eu">ODG txantiloia</comment>
- <comment xml:lang="fi">ODG-malli</comment>
- <comment xml:lang="fo">ODG formur</comment>
- <comment xml:lang="fr">modèle ODG</comment>
- <comment xml:lang="ga">teimpléad ODG</comment>
- <comment xml:lang="gl">modelo ODG</comment>
- <comment xml:lang="he">תבנית ODG</comment>
- <comment xml:lang="hr">ODG predložak</comment>
- <comment xml:lang="hu">ODG-sablon</comment>
- <comment xml:lang="ia">Patrono ODG</comment>
- <comment xml:lang="id">Templat ODG</comment>
- <comment xml:lang="it">Modello ODG</comment>
- <comment xml:lang="ja">ODG テンプレート</comment>
- <comment xml:lang="ka">ODG-ის შაბლონი</comment>
- <comment xml:lang="kk">ODG үлгісі</comment>
- <comment xml:lang="ko">ODG 문서 서식</comment>
- <comment xml:lang="lt">ODG šablonas</comment>
- <comment xml:lang="lv">ODG veidne</comment>
- <comment xml:lang="nb">ODG-mal</comment>
- <comment xml:lang="nl">ODG-sjabloon</comment>
- <comment xml:lang="nn">ODG-mal</comment>
- <comment xml:lang="oc">modèl ODG</comment>
- <comment xml:lang="pl">Szablon ODG</comment>
- <comment xml:lang="pt">modelo ODG</comment>
- <comment xml:lang="pt_BR">Modelo ODG</comment>
- <comment xml:lang="ro">Șablon ODG</comment>
- <comment xml:lang="ru">Шаблон ODG</comment>
- <comment xml:lang="sk">Šablóna ODG</comment>
- <comment xml:lang="sl">Predloga dokumenta ODG</comment>
- <comment xml:lang="sq">Model ODG</comment>
- <comment xml:lang="sr">ОДГ шаблон</comment>
- <comment xml:lang="sv">ODG-mall</comment>
- <comment xml:lang="tr">ODG şablonu</comment>
- <comment xml:lang="uk">шаблон ODG</comment>
- <comment xml:lang="vi">Mẫu ODG</comment>
- <comment xml:lang="zh_CN">ODG 模板</comment>
<comment xml:lang="zh_TW">ODG 範本</comment>
+ <comment xml:lang="zh_CN">ODG 模板</comment>
+ <comment xml:lang="vi">Mẫu ODG</comment>
+ <comment xml:lang="uk">шаблон ODG</comment>
+ <comment xml:lang="tr">ODG şablonu</comment>
+ <comment xml:lang="sv">ODG-mall</comment>
+ <comment xml:lang="sr">ОДГ шаблон</comment>
+ <comment xml:lang="sq">gjedhe ODG</comment>
+ <comment xml:lang="sl">Predloga dokumenta ODG</comment>
+ <comment xml:lang="si">ODG අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna ODG</comment>
+ <comment xml:lang="ru">Шаблон ODG</comment>
+ <comment xml:lang="ro">Șablon ODG</comment>
+ <comment xml:lang="pt_BR">Modelo ODG</comment>
+ <comment xml:lang="pt">modelo ODG</comment>
+ <comment xml:lang="pl">Szablon ODG</comment>
+ <comment xml:lang="oc">modèl ODG</comment>
+ <comment xml:lang="nn">ODG-mal</comment>
+ <comment xml:lang="nl">ODG-sjabloon</comment>
+ <comment xml:lang="nb">ODG-mal</comment>
+ <comment xml:lang="lv">ODG veidne</comment>
+ <comment xml:lang="lt">ODG šablonas</comment>
+ <comment xml:lang="ko">ODG 문서 서식</comment>
+ <comment xml:lang="kk">ODG үлгісі</comment>
+ <comment xml:lang="ka">ODG-ის შაბლონი</comment>
+ <comment xml:lang="ja">ODG テンプレート</comment>
+ <comment xml:lang="it">Modello ODG</comment>
+ <comment xml:lang="is">ODG sniðmát</comment>
+ <comment xml:lang="id">Templat ODG</comment>
+ <comment xml:lang="ia">Patrono ODG</comment>
+ <comment xml:lang="hu">ODG-sablon</comment>
+ <comment xml:lang="hr">ODG predložak</comment>
+ <comment xml:lang="he">תבנית ODG</comment>
+ <comment xml:lang="gl">modelo ODG</comment>
+ <comment xml:lang="ga">teimpléad ODG</comment>
+ <comment xml:lang="fur">model ODG</comment>
+ <comment xml:lang="fr">modèle ODG</comment>
+ <comment xml:lang="fo">ODG formur</comment>
+ <comment xml:lang="fi">ODG-malli</comment>
+ <comment xml:lang="eu">ODG txantiloia</comment>
+ <comment xml:lang="es">plantilla ODG</comment>
+ <comment xml:lang="eo">ODG-ŝablono</comment>
+ <comment xml:lang="en_GB">ODG template</comment>
+ <comment xml:lang="el">Πρότυπο ODG</comment>
+ <comment xml:lang="de">ODG-Vorlage</comment>
+ <comment xml:lang="da">ODG-skabelon</comment>
+ <comment xml:lang="cs">šablona ODG</comment>
+ <comment xml:lang="ca">plantilla ODG</comment>
+ <comment xml:lang="bg">Шаблон за чертежи — ODG</comment>
+ <comment xml:lang="be@latin">Šablon ODG</comment>
+ <comment xml:lang="be">шаблон ODG</comment>
+ <comment xml:lang="ar">قالب ODG</comment>
+ <comment xml:lang="af">ODG-sjabloon</comment>
<acronym>ODG</acronym>
<expanded-acronym>OpenDocument Drawing</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.graphics-template" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.graphics-template" offset="38"/>
</match>
</match>
</magic>
@@ -5778,62 +6137,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.presentation">
<comment>ODP presentation</comment>
- <comment xml:lang="ar">عرض تقديمي ODP</comment>
- <comment xml:lang="be@latin">Prezentacyja ODP</comment>
- <comment xml:lang="bg">Презентация — ODP</comment>
- <comment xml:lang="ca">presentació ODP</comment>
- <comment xml:lang="cs">prezentace ODP</comment>
- <comment xml:lang="da">ODP-præsentation</comment>
- <comment xml:lang="de">ODP-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση ODP</comment>
- <comment xml:lang="en_GB">ODP presentation</comment>
- <comment xml:lang="eo">ODP-prezentaĵo</comment>
- <comment xml:lang="es">presentación ODP</comment>
- <comment xml:lang="eu">ODP aurkezpena</comment>
- <comment xml:lang="fi">ODP-esitys</comment>
- <comment xml:lang="fo">ODP framløga</comment>
- <comment xml:lang="fr">présentation ODP</comment>
- <comment xml:lang="ga">láithreoireacht ODP</comment>
- <comment xml:lang="gl">presentación ODP</comment>
- <comment xml:lang="he">מצגת ODP</comment>
- <comment xml:lang="hr">ODP prezentacija</comment>
- <comment xml:lang="hu">ODP-prezentáció</comment>
- <comment xml:lang="ia">Presentation ODP</comment>
- <comment xml:lang="id">Presentasi ODP</comment>
- <comment xml:lang="it">Presentazione ODP</comment>
- <comment xml:lang="ja">ODP プレゼンテーション</comment>
- <comment xml:lang="ka">ODP პრეზენტაცია</comment>
- <comment xml:lang="kk">ODP презентациясы</comment>
- <comment xml:lang="ko">ODP 프레젠테이션</comment>
- <comment xml:lang="lt">ODP pateiktis</comment>
- <comment xml:lang="lv">ODP prezentācija</comment>
- <comment xml:lang="nb">ODP-presentasjon</comment>
- <comment xml:lang="nl">ODP-presentatie</comment>
- <comment xml:lang="nn">ODP-presentasjon</comment>
- <comment xml:lang="oc">presentacion ODP</comment>
- <comment xml:lang="pl">Prezentacja ODP</comment>
- <comment xml:lang="pt">apresentação ODP</comment>
- <comment xml:lang="pt_BR">Apresentação ODP</comment>
- <comment xml:lang="ro">Prezentare ODP</comment>
- <comment xml:lang="ru">Презентация ODP</comment>
- <comment xml:lang="sk">Prezentácia ODP</comment>
- <comment xml:lang="sl">Predstavitev ODP</comment>
- <comment xml:lang="sq">Prezantim ODP</comment>
- <comment xml:lang="sr">ОДП презентација</comment>
- <comment xml:lang="sv">ODP-presentation</comment>
- <comment xml:lang="tr">ODP sunumu</comment>
- <comment xml:lang="uk">презентація ODP</comment>
- <comment xml:lang="vi">Trình diễn ODM</comment>
- <comment xml:lang="zh_CN">ODP 演示文稿</comment>
<comment xml:lang="zh_TW">ODP 簡報</comment>
+ <comment xml:lang="zh_CN">ODP 演示文稿</comment>
+ <comment xml:lang="vi">Trình diễn ODM</comment>
+ <comment xml:lang="uk">презентація ODP</comment>
+ <comment xml:lang="tr">ODP sunumu</comment>
+ <comment xml:lang="sv">ODP-presentation</comment>
+ <comment xml:lang="sr">ОДП презентација</comment>
+ <comment xml:lang="sq">paraqitje ODP</comment>
+ <comment xml:lang="sl">Predstavitev ODP</comment>
+ <comment xml:lang="si">ODP ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia ODP</comment>
+ <comment xml:lang="ru">Презентация ODP</comment>
+ <comment xml:lang="ro">Prezentare ODP</comment>
+ <comment xml:lang="pt_BR">Apresentação ODP</comment>
+ <comment xml:lang="pt">apresentação ODP</comment>
+ <comment xml:lang="pl">Prezentacja ODP</comment>
+ <comment xml:lang="oc">presentacion ODP</comment>
+ <comment xml:lang="nn">ODP-presentasjon</comment>
+ <comment xml:lang="nl">ODP-presentatie</comment>
+ <comment xml:lang="nb">ODP-presentasjon</comment>
+ <comment xml:lang="lv">ODP prezentācija</comment>
+ <comment xml:lang="lt">ODP pateiktis</comment>
+ <comment xml:lang="ko">ODP 프레젠테이션</comment>
+ <comment xml:lang="kk">ODP презентациясы</comment>
+ <comment xml:lang="ka">ODP პრეზენტაცია</comment>
+ <comment xml:lang="ja">ODP プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione ODP</comment>
+ <comment xml:lang="is">ODP kynning</comment>
+ <comment xml:lang="id">Presentasi ODP</comment>
+ <comment xml:lang="ia">Presentation ODP</comment>
+ <comment xml:lang="hu">ODP-prezentáció</comment>
+ <comment xml:lang="hr">ODP prezentacija</comment>
+ <comment xml:lang="he">מצגת ODP</comment>
+ <comment xml:lang="gl">presentación ODP</comment>
+ <comment xml:lang="ga">láithreoireacht ODP</comment>
+ <comment xml:lang="fur">presentazion ODP</comment>
+ <comment xml:lang="fr">présentation ODP</comment>
+ <comment xml:lang="fo">ODP framløga</comment>
+ <comment xml:lang="fi">ODP-esitys</comment>
+ <comment xml:lang="eu">ODP aurkezpena</comment>
+ <comment xml:lang="es">presentación ODP</comment>
+ <comment xml:lang="eo">ODP-prezentaĵo</comment>
+ <comment xml:lang="en_GB">ODP presentation</comment>
+ <comment xml:lang="el">Παρουσίαση ODP</comment>
+ <comment xml:lang="de">ODP-Präsentation</comment>
+ <comment xml:lang="da">ODP-præsentation</comment>
+ <comment xml:lang="cs">prezentace ODP</comment>
+ <comment xml:lang="ca">presentació ODP</comment>
+ <comment xml:lang="bg">Презентация — ODP</comment>
+ <comment xml:lang="be@latin">Prezentacyja ODP</comment>
+ <comment xml:lang="be">прэзентацыя ODP</comment>
+ <comment xml:lang="ar">عرض تقديمي ODP</comment>
+ <comment xml:lang="af">ODP-voorlegging</comment>
<acronym>ODP</acronym>
<expanded-acronym>OpenDocument Presentation</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.presentation" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.presentation" offset="38"/>
</match>
</match>
</magic>
@@ -5841,48 +6205,54 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.presentation-flat-xml">
<comment>ODP presentation (Flat XML)</comment>
- <comment xml:lang="ar">عرض ODP (Flat XML)</comment>
- <comment xml:lang="bg">Презентация — ODP (само XML)</comment>
- <comment xml:lang="ca">presentació ODP (XML pla)</comment>
- <comment xml:lang="cs">prezentace ODP (Flat XML)</comment>
- <comment xml:lang="da">ODP-præsentation (flad XML)</comment>
- <comment xml:lang="de">ODP-Präsentation (Unkomprimiertes XML)</comment>
- <comment xml:lang="el">Παρουσίαση ODP (Flat XML)</comment>
- <comment xml:lang="en_GB">ODP presentation (Flat XML)</comment>
- <comment xml:lang="es">presentación ODP (XML plano)</comment>
- <comment xml:lang="eu">ODP aurkezpena (XML soila)</comment>
- <comment xml:lang="fi">ODP-esitys (Flat XML)</comment>
- <comment xml:lang="fo">ODP framløga (Flat XML)</comment>
- <comment xml:lang="fr">présentation ODP (XML plat)</comment>
- <comment xml:lang="ga">láithreoireacht ODP (XML cothrom)</comment>
- <comment xml:lang="gl">presentación ODP (XML plano)</comment>
- <comment xml:lang="he">מצגת ODP‏ (Flat XML)</comment>
- <comment xml:lang="hr">ODP prezentacija (Flat XML)</comment>
- <comment xml:lang="hu">ODP-prezentáció (egyszerű XML)</comment>
- <comment xml:lang="ia">Presentation ODP (XML platte)</comment>
- <comment xml:lang="id">Presentasi ODP (Flat XML)</comment>
- <comment xml:lang="it">Presentazione ODP (XML semplice)</comment>
- <comment xml:lang="ja">ODP プレゼンテーション (Flat XML)</comment>
- <comment xml:lang="ka">ODP პრეზენტაცია (Flat XML)</comment>
- <comment xml:lang="kk">ODP презентациясы (Тек XML)</comment>
- <comment xml:lang="ko">ODP 프레젠테이션(단일 XML)</comment>
- <comment xml:lang="lt">ODP pateiktis (Flat XML)</comment>
- <comment xml:lang="lv">ODP prezentācija (plakans XML)</comment>
- <comment xml:lang="nl">ODP presentatie (Flat XML)</comment>
- <comment xml:lang="oc">presentacion ODP (XML plat)</comment>
- <comment xml:lang="pl">Prezentacja ODP (prosty XML)</comment>
- <comment xml:lang="pt">apresentação ODP (XML plano)</comment>
- <comment xml:lang="pt_BR">Apresentação ODP (Flat XML)</comment>
- <comment xml:lang="ro">Prezentare ODP (XML simplu)</comment>
- <comment xml:lang="ru">Презентация ODP (простой XML)</comment>
- <comment xml:lang="sk">Prezentácia ODP (čisté XML)</comment>
- <comment xml:lang="sl">Predstavitev ODP (nepovezan XML)</comment>
- <comment xml:lang="sr">ОДП презентација (Обични ИксМЛ)</comment>
- <comment xml:lang="sv">ODP-presentation (platt XML)</comment>
- <comment xml:lang="tr">ODP sunumu (Düz XML)</comment>
- <comment xml:lang="uk">презентація ODP (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODP 演示文稿(Flat XML)</comment>
<comment xml:lang="zh_TW">ODP 範本 (Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODP 演示文稿(Flat XML)</comment>
+ <comment xml:lang="uk">презентація ODP (Flat XML)</comment>
+ <comment xml:lang="tr">ODP sunumu (Düz XML)</comment>
+ <comment xml:lang="sv">ODP-presentation (platt XML)</comment>
+ <comment xml:lang="sr">ОДП презентација (Обични ИксМЛ)</comment>
+ <comment xml:lang="sq">paraqitje ODF (Flat XML)</comment>
+ <comment xml:lang="sl">Predstavitev ODP (nepovezan XML)</comment>
+ <comment xml:lang="si">ODP ඉදිරිපත් කිරීම (පැතලි XML)</comment>
+ <comment xml:lang="sk">Prezentácia ODP (čisté XML)</comment>
+ <comment xml:lang="ru">Презентация ODP (простой XML)</comment>
+ <comment xml:lang="ro">Prezentare ODP (XML simplu)</comment>
+ <comment xml:lang="pt_BR">Apresentação ODP (Flat XML)</comment>
+ <comment xml:lang="pt">apresentação ODP (XML plano)</comment>
+ <comment xml:lang="pl">Prezentacja ODP (prosty XML)</comment>
+ <comment xml:lang="oc">presentacion ODP (XML plat)</comment>
+ <comment xml:lang="nl">ODP presentatie (Flat XML)</comment>
+ <comment xml:lang="lv">ODP prezentācija (plakans XML)</comment>
+ <comment xml:lang="lt">ODP pateiktis (Flat XML)</comment>
+ <comment xml:lang="ko">ODP 프레젠테이션(단일 XML)</comment>
+ <comment xml:lang="kk">ODP презентациясы (Тек XML)</comment>
+ <comment xml:lang="ka">ODP პრეზენტაცია (Flat XML)</comment>
+ <comment xml:lang="ja">ODP プレゼンテーション (Flat XML)</comment>
+ <comment xml:lang="it">Presentazione ODP (XML semplice)</comment>
+ <comment xml:lang="is">ODP glærukynning (flatt XML)</comment>
+ <comment xml:lang="id">Presentasi ODP (Flat XML)</comment>
+ <comment xml:lang="ia">Presentation ODP (XML platte)</comment>
+ <comment xml:lang="hu">ODP-prezentáció (egyszerű XML)</comment>
+ <comment xml:lang="hr">ODP prezentacija (Flat XML)</comment>
+ <comment xml:lang="he">מצגת ODP‏ (Flat XML)</comment>
+ <comment xml:lang="gl">presentación ODP (XML plano)</comment>
+ <comment xml:lang="ga">láithreoireacht ODP (XML cothrom)</comment>
+ <comment xml:lang="fur">presentazion ODP (XML sempliç)</comment>
+ <comment xml:lang="fr">présentation ODP (XML plat)</comment>
+ <comment xml:lang="fo">ODP framløga (Flat XML)</comment>
+ <comment xml:lang="fi">ODP-esitys (Flat XML)</comment>
+ <comment xml:lang="eu">ODP aurkezpena (XML soila)</comment>
+ <comment xml:lang="es">presentación ODP (XML plano)</comment>
+ <comment xml:lang="en_GB">ODP presentation (Flat XML)</comment>
+ <comment xml:lang="el">Παρουσίαση ODP (Flat XML)</comment>
+ <comment xml:lang="de">ODP-Präsentation (einfaches XML)</comment>
+ <comment xml:lang="da">ODP-præsentation (flad XML)</comment>
+ <comment xml:lang="cs">prezentace ODP (Flat XML)</comment>
+ <comment xml:lang="ca">presentació ODP (XML pla)</comment>
+ <comment xml:lang="bg">Презентация — ODP (само XML)</comment>
+ <comment xml:lang="be">прэзентацыя ODP (плоскі XML)</comment>
+ <comment xml:lang="ar">عرض ODP (Flat XML)</comment>
+ <comment xml:lang="af">ODP-voorlegging (plat XML)</comment>
<acronym>FODP</acronym>
<expanded-acronym>OpenDocument Presentation (Flat XML)</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -5891,62 +6261,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.presentation-template">
<comment>ODP template</comment>
- <comment xml:lang="ar">قالب ODP</comment>
- <comment xml:lang="be@latin">Šablon ODP</comment>
- <comment xml:lang="bg">Шаблон за презентации — ODP</comment>
- <comment xml:lang="ca">plantilla ODP</comment>
- <comment xml:lang="cs">šablona ODP</comment>
- <comment xml:lang="da">ODP-skabelon</comment>
- <comment xml:lang="de">ODP-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο ODP</comment>
- <comment xml:lang="en_GB">ODP template</comment>
- <comment xml:lang="eo">ODP-ŝablono</comment>
- <comment xml:lang="es">plantilla ODP</comment>
- <comment xml:lang="eu">ODP txantiloia</comment>
- <comment xml:lang="fi">ODP-malli</comment>
- <comment xml:lang="fo">ODP formur</comment>
- <comment xml:lang="fr">modèle ODP</comment>
- <comment xml:lang="ga">teimpléad ODP</comment>
- <comment xml:lang="gl">modelo ODP</comment>
- <comment xml:lang="he">תבנית ODP</comment>
- <comment xml:lang="hr">ODP predložak</comment>
- <comment xml:lang="hu">ODP-sablon</comment>
- <comment xml:lang="ia">Patrono ODP</comment>
- <comment xml:lang="id">Templat ODP</comment>
- <comment xml:lang="it">Modello ODP</comment>
- <comment xml:lang="ja">ODP テンプレート</comment>
- <comment xml:lang="ka">ODP შაბლონი</comment>
- <comment xml:lang="kk">ODP үлгісі</comment>
- <comment xml:lang="ko">ODP 문서 서식</comment>
- <comment xml:lang="lt">ODP šablonas</comment>
- <comment xml:lang="lv">ODP veidne</comment>
- <comment xml:lang="nb">ODP-mal</comment>
- <comment xml:lang="nl">ODP-sjabloon</comment>
- <comment xml:lang="nn">ODP-mal</comment>
- <comment xml:lang="oc">modèl ODP</comment>
- <comment xml:lang="pl">Szablon ODP</comment>
- <comment xml:lang="pt">modelo ODP</comment>
- <comment xml:lang="pt_BR">Modelo ODP</comment>
- <comment xml:lang="ro">Șablon ODP</comment>
- <comment xml:lang="ru">Шаблон ODP</comment>
- <comment xml:lang="sk">Šablóna ODP</comment>
- <comment xml:lang="sl">Predloga dokumenta ODP</comment>
- <comment xml:lang="sq">Model ODP</comment>
- <comment xml:lang="sr">ОДП шаблон</comment>
- <comment xml:lang="sv">ODP-mall</comment>
- <comment xml:lang="tr">ODP şablonu</comment>
- <comment xml:lang="uk">шаблон ODP</comment>
- <comment xml:lang="vi">Mẫu ODP</comment>
- <comment xml:lang="zh_CN">ODP 模板</comment>
<comment xml:lang="zh_TW">ODP 範本</comment>
+ <comment xml:lang="zh_CN">ODP 模板</comment>
+ <comment xml:lang="vi">Mẫu ODP</comment>
+ <comment xml:lang="uk">шаблон ODP</comment>
+ <comment xml:lang="tr">ODP şablonu</comment>
+ <comment xml:lang="sv">ODP-mall</comment>
+ <comment xml:lang="sr">ОДП шаблон</comment>
+ <comment xml:lang="sq">gjedhe ODP</comment>
+ <comment xml:lang="sl">Predloga dokumenta ODP</comment>
+ <comment xml:lang="si">ODP අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna ODP</comment>
+ <comment xml:lang="ru">Шаблон ODP</comment>
+ <comment xml:lang="ro">Șablon ODP</comment>
+ <comment xml:lang="pt_BR">Modelo ODP</comment>
+ <comment xml:lang="pt">modelo ODP</comment>
+ <comment xml:lang="pl">Szablon ODP</comment>
+ <comment xml:lang="oc">modèl ODP</comment>
+ <comment xml:lang="nn">ODP-mal</comment>
+ <comment xml:lang="nl">ODP-sjabloon</comment>
+ <comment xml:lang="nb">ODP-mal</comment>
+ <comment xml:lang="lv">ODP veidne</comment>
+ <comment xml:lang="lt">ODP šablonas</comment>
+ <comment xml:lang="ko">ODP 문서 서식</comment>
+ <comment xml:lang="kk">ODP үлгісі</comment>
+ <comment xml:lang="ka">ODP შაბლონი</comment>
+ <comment xml:lang="ja">ODP テンプレート</comment>
+ <comment xml:lang="it">Modello ODP</comment>
+ <comment xml:lang="is">ODP sniðmát</comment>
+ <comment xml:lang="id">Templat ODP</comment>
+ <comment xml:lang="ia">Patrono ODP</comment>
+ <comment xml:lang="hu">ODP-sablon</comment>
+ <comment xml:lang="hr">ODP predložak</comment>
+ <comment xml:lang="he">תבנית ODP</comment>
+ <comment xml:lang="gl">modelo ODP</comment>
+ <comment xml:lang="ga">teimpléad ODP</comment>
+ <comment xml:lang="fur">model ODP</comment>
+ <comment xml:lang="fr">modèle ODP</comment>
+ <comment xml:lang="fo">ODP formur</comment>
+ <comment xml:lang="fi">ODP-malli</comment>
+ <comment xml:lang="eu">ODP txantiloia</comment>
+ <comment xml:lang="es">plantilla ODP</comment>
+ <comment xml:lang="eo">ODP-ŝablono</comment>
+ <comment xml:lang="en_GB">ODP template</comment>
+ <comment xml:lang="el">Πρότυπο ODP</comment>
+ <comment xml:lang="de">ODP-Vorlage</comment>
+ <comment xml:lang="da">ODP-skabelon</comment>
+ <comment xml:lang="cs">šablona ODP</comment>
+ <comment xml:lang="ca">plantilla ODP</comment>
+ <comment xml:lang="bg">Шаблон за презентации — ODP</comment>
+ <comment xml:lang="be@latin">Šablon ODP</comment>
+ <comment xml:lang="be">шаблон ODP</comment>
+ <comment xml:lang="ar">قالب ODP</comment>
+ <comment xml:lang="af">ODP-sjabloon</comment>
<acronym>ODP</acronym>
<expanded-acronym>OpenDocument Presentation</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.presentation-template" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.presentation-template" offset="38"/>
</match>
</match>
</magic>
@@ -5954,62 +6329,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.spreadsheet">
<comment>ODS spreadsheet</comment>
- <comment xml:lang="ar">جدول ODS</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš ODS</comment>
- <comment xml:lang="bg">Таблица — ODS</comment>
- <comment xml:lang="ca">full de càlcul ODS</comment>
- <comment xml:lang="cs">sešit ODS</comment>
- <comment xml:lang="da">ODS-regneark</comment>
- <comment xml:lang="de">ODS-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο ODS</comment>
- <comment xml:lang="en_GB">ODS spreadsheet</comment>
- <comment xml:lang="eo">ODS-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo ODS</comment>
- <comment xml:lang="eu">ODS kalkulu-orria</comment>
- <comment xml:lang="fi">ODS-taulukko</comment>
- <comment xml:lang="fo">ODS rokniark</comment>
- <comment xml:lang="fr">feuille de calcul ODS</comment>
- <comment xml:lang="ga">scarbhileog ODS</comment>
- <comment xml:lang="gl">folla de cálculo ODS</comment>
- <comment xml:lang="he">גליון נתונים ODS</comment>
- <comment xml:lang="hr">ODS proračunska tablica</comment>
- <comment xml:lang="hu">ODS-táblázat</comment>
- <comment xml:lang="ia">Folio de calculo ODS</comment>
- <comment xml:lang="id">Lembar sebar ODS</comment>
- <comment xml:lang="it">Foglio di calcolo ODS</comment>
- <comment xml:lang="ja">ODS スプレッドシート</comment>
- <comment xml:lang="ka">ODS ცხრილი</comment>
- <comment xml:lang="kk">ODS электрондық кестесі</comment>
- <comment xml:lang="ko">ODS 스프레드시트</comment>
- <comment xml:lang="lt">ODS skaičialentė</comment>
- <comment xml:lang="lv">ODS izklājlapa</comment>
- <comment xml:lang="nb">ODS-regneark</comment>
- <comment xml:lang="nl">ODS-rekenblad</comment>
- <comment xml:lang="nn">ODS-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul ODS</comment>
- <comment xml:lang="pl">Arkusz ODS</comment>
- <comment xml:lang="pt">folha de cálculo ODS</comment>
- <comment xml:lang="pt_BR">Planilha ODS</comment>
- <comment xml:lang="ro">Foaie de calcul ODS</comment>
- <comment xml:lang="ru">Электронная таблица ODS</comment>
- <comment xml:lang="sk">Zošit ODS</comment>
- <comment xml:lang="sl">Preglednica ODS</comment>
- <comment xml:lang="sq">Fletë llogaritjesh ODS</comment>
- <comment xml:lang="sr">ОДС табела</comment>
- <comment xml:lang="sv">ODS-kalkylblad</comment>
- <comment xml:lang="tr">ODS çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця ODS</comment>
- <comment xml:lang="vi">Bảng tính ODS</comment>
- <comment xml:lang="zh_CN">ODS 电子表格</comment>
<comment xml:lang="zh_TW">ODS 試算表</comment>
+ <comment xml:lang="zh_CN">ODS 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính ODS</comment>
+ <comment xml:lang="uk">електронна таблиця ODS</comment>
+ <comment xml:lang="tr">ODS hesap çizelgesi</comment>
+ <comment xml:lang="sv">ODS-kalkylblad</comment>
+ <comment xml:lang="sr">ОДС табела</comment>
+ <comment xml:lang="sq">fletëllogaritje ODS</comment>
+ <comment xml:lang="sl">Preglednica ODS</comment>
+ <comment xml:lang="si">ODS පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit ODS</comment>
+ <comment xml:lang="ru">Электронная таблица ODS</comment>
+ <comment xml:lang="ro">Foaie de calcul ODS</comment>
+ <comment xml:lang="pt_BR">Planilha ODS</comment>
+ <comment xml:lang="pt">folha de cálculo ODS</comment>
+ <comment xml:lang="pl">Arkusz ODS</comment>
+ <comment xml:lang="oc">fuèlh de calcul ODS</comment>
+ <comment xml:lang="nn">ODS-rekneark</comment>
+ <comment xml:lang="nl">ODS-rekenblad</comment>
+ <comment xml:lang="nb">ODS-regneark</comment>
+ <comment xml:lang="lv">ODS izklājlapa</comment>
+ <comment xml:lang="lt">ODS skaičialentė</comment>
+ <comment xml:lang="ko">ODS 스프레드시트</comment>
+ <comment xml:lang="kk">ODS электрондық кестесі</comment>
+ <comment xml:lang="ka">ODS ცხრილი</comment>
+ <comment xml:lang="ja">ODS スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo ODS</comment>
+ <comment xml:lang="is">ODS töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar ODS</comment>
+ <comment xml:lang="ia">Folio de calculo ODS</comment>
+ <comment xml:lang="hu">ODS-táblázat</comment>
+ <comment xml:lang="hr">ODS proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים ODS</comment>
+ <comment xml:lang="gl">folla de cálculo ODS</comment>
+ <comment xml:lang="ga">scarbhileog ODS</comment>
+ <comment xml:lang="fur">sfuei di calcul ODS</comment>
+ <comment xml:lang="fr">feuille de calcul ODS</comment>
+ <comment xml:lang="fo">ODS rokniark</comment>
+ <comment xml:lang="fi">ODS-taulukko</comment>
+ <comment xml:lang="eu">ODS kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo ODS</comment>
+ <comment xml:lang="eo">ODS-kalkultabelo</comment>
+ <comment xml:lang="en_GB">ODS spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο ODS</comment>
+ <comment xml:lang="de">ODS-Tabelle</comment>
+ <comment xml:lang="da">ODS-regneark</comment>
+ <comment xml:lang="cs">sešit ODS</comment>
+ <comment xml:lang="ca">full de càlcul ODS</comment>
+ <comment xml:lang="bg">Таблица — ODS</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš ODS</comment>
+ <comment xml:lang="be">электронная табліца ODS</comment>
+ <comment xml:lang="ar">جدول ODS</comment>
+ <comment xml:lang="af">ODS-sigblad</comment>
<acronym>ODS</acronym>
<expanded-acronym>OpenDocument Spreadsheet</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.spreadsheet" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.spreadsheet" offset="38"/>
</match>
</match>
</magic>
@@ -6017,48 +6397,54 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.spreadsheet-flat-xml">
<comment>ODS spreadsheet (Flat XML)</comment>
- <comment xml:lang="ar">جدول ODS (Flat XML)</comment>
- <comment xml:lang="bg">Таблица — ODS (само XML)</comment>
- <comment xml:lang="ca">full de càlcul ODS (XML pla)</comment>
- <comment xml:lang="cs">sešit ODS (Flat XML)</comment>
- <comment xml:lang="da">ODS-regneark (flad XML)</comment>
- <comment xml:lang="de">ODS-Tabelle (Unkomprimiertes XML)</comment>
- <comment xml:lang="el">Λογιστικό φύλλο ODS (Flat XML)</comment>
- <comment xml:lang="en_GB">ODS spreadsheet (Flat XML)</comment>
- <comment xml:lang="es">hoja de cálculo ODS (XML plano)</comment>
- <comment xml:lang="eu">ODS kalkulu-orria (XML soila)</comment>
- <comment xml:lang="fi">ODS-laskentataulukko (Flat XML)</comment>
- <comment xml:lang="fo">ODS rokniark (Flat XML)</comment>
- <comment xml:lang="fr">feuille de calcul ODS (XML plat)</comment>
- <comment xml:lang="ga">scarbhileog ODS (XML cothrom)</comment>
- <comment xml:lang="gl">folla de cálculo ODS (XML plano)</comment>
- <comment xml:lang="he">גליון נתונים ODS‏ (XML פשוט)</comment>
- <comment xml:lang="hr">ODS proračunska tablica (Flat XML)</comment>
- <comment xml:lang="hu">ODS-táblázat (egyszerű XML)</comment>
- <comment xml:lang="ia">Folio de calculo ODS (XML platte)</comment>
- <comment xml:lang="id">Lembar sebar ODS (Flat XML)</comment>
- <comment xml:lang="it">Foglio di calcolo ODS (XML semplice)</comment>
- <comment xml:lang="ja">ODS スプレッドシート (Flat XML)</comment>
- <comment xml:lang="ka">ODS ცხრილი (Flat XML)</comment>
- <comment xml:lang="kk">ODS электрондық кестесі (Тек XML)</comment>
- <comment xml:lang="ko">ODS 스프레드시트(단일 XML)</comment>
- <comment xml:lang="lt">ODS skaičialentė (Flat XML)</comment>
- <comment xml:lang="lv">ODS izklājlapa (plakans XML)</comment>
- <comment xml:lang="nl">ODS spreadsheet (Flat XML)</comment>
- <comment xml:lang="oc">fuèlh de calcul ODS (XML plat)</comment>
- <comment xml:lang="pl">Arkusz ODS (prosty XML)</comment>
- <comment xml:lang="pt">folha de cálculo ODS (XML plano)</comment>
- <comment xml:lang="pt_BR">Planilha ODS (Flat XML)</comment>
- <comment xml:lang="ro">Foaie de calcul ODS (XML simplu)</comment>
- <comment xml:lang="ru">Электронная таблица ODS (простой XML)</comment>
- <comment xml:lang="sk">Zošit ODS (čisté XML)</comment>
- <comment xml:lang="sl">Preglednica ODS (nepovezan XML)</comment>
- <comment xml:lang="sr">ОДС табела (обични ИксМЛ)</comment>
- <comment xml:lang="sv">ODS-kalkylblad (platt XML)</comment>
- <comment xml:lang="tr">ODS sunumu (Düz XML)</comment>
- <comment xml:lang="uk">ел. таблиця ODS (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODS 电子表格 (Flat XML)</comment>
<comment xml:lang="zh_TW">ODS 試算表 (Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODS 电子表格 (Flat XML)</comment>
+ <comment xml:lang="uk">електронна таблиця ODS (Flat XML)</comment>
+ <comment xml:lang="tr">ODS hesap çizelgesi (Düz XML)</comment>
+ <comment xml:lang="sv">ODS-kalkylblad (platt XML)</comment>
+ <comment xml:lang="sr">ОДС табела (обични ИксМЛ)</comment>
+ <comment xml:lang="sq">fletëllogaritje ODF (Flat XML)</comment>
+ <comment xml:lang="sl">Preglednica ODS (nepovezan XML)</comment>
+ <comment xml:lang="si">ODS පැතුරුම්පත (පැතලි XML)</comment>
+ <comment xml:lang="sk">Zošit ODS (čisté XML)</comment>
+ <comment xml:lang="ru">Электронная таблица ODS (простой XML)</comment>
+ <comment xml:lang="ro">Foaie de calcul ODS (XML simplu)</comment>
+ <comment xml:lang="pt_BR">Planilha ODS (Flat XML)</comment>
+ <comment xml:lang="pt">folha de cálculo ODS (XML plano)</comment>
+ <comment xml:lang="pl">Arkusz ODS (prosty XML)</comment>
+ <comment xml:lang="oc">fuèlh de calcul ODS (XML plat)</comment>
+ <comment xml:lang="nl">ODS spreadsheet (Flat XML)</comment>
+ <comment xml:lang="lv">ODS izklājlapa (plakans XML)</comment>
+ <comment xml:lang="lt">ODS skaičialentė (Flat XML)</comment>
+ <comment xml:lang="ko">ODS 스프레드시트(단일 XML)</comment>
+ <comment xml:lang="kk">ODS электрондық кестесі (Тек XML)</comment>
+ <comment xml:lang="ka">ODS ცხრილი (Flat XML)</comment>
+ <comment xml:lang="ja">ODS スプレッドシート (Flat XML)</comment>
+ <comment xml:lang="it">Foglio di calcolo ODS (XML semplice)</comment>
+ <comment xml:lang="is">ODS töflureikniskjal (flatt XML)</comment>
+ <comment xml:lang="id">Lembar sebar ODS (Flat XML)</comment>
+ <comment xml:lang="ia">Folio de calculo ODS (XML platte)</comment>
+ <comment xml:lang="hu">ODS-táblázat (egyszerű XML)</comment>
+ <comment xml:lang="hr">ODS proračunska tablica (Flat XML)</comment>
+ <comment xml:lang="he">גיליון נתונים ODS‏ (XML פשוט)</comment>
+ <comment xml:lang="gl">folla de cálculo ODS (XML plano)</comment>
+ <comment xml:lang="ga">scarbhileog ODS (XML cothrom)</comment>
+ <comment xml:lang="fur">sfuei di calcul ODS (XML sempliç)</comment>
+ <comment xml:lang="fr">feuille de calcul ODS (XML plat)</comment>
+ <comment xml:lang="fo">ODS rokniark (Flat XML)</comment>
+ <comment xml:lang="fi">ODS-laskentataulukko (Flat XML)</comment>
+ <comment xml:lang="eu">ODS kalkulu-orria (XML soila)</comment>
+ <comment xml:lang="es">hoja de cálculo ODS (XML plano)</comment>
+ <comment xml:lang="en_GB">ODS spreadsheet (Flat XML)</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο ODS (Flat XML)</comment>
+ <comment xml:lang="de">ODS-Tabelle (einfaches XML)</comment>
+ <comment xml:lang="da">ODS-regneark (flad XML)</comment>
+ <comment xml:lang="cs">sešit ODS (Flat XML)</comment>
+ <comment xml:lang="ca">full de càlcul ODS (XML pla)</comment>
+ <comment xml:lang="bg">Таблица — ODS (само XML)</comment>
+ <comment xml:lang="be">электронная табліца ODS (плоскі XML)</comment>
+ <comment xml:lang="ar">جدول ODS (Flat XML)</comment>
+ <comment xml:lang="af">ODS-sigblad (plat XML)</comment>
<acronym>FODS</acronym>
<expanded-acronym>OpenDocument Spreadsheet (Flat XML)</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -6067,62 +6453,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.spreadsheet-template">
<comment>ODS template</comment>
- <comment xml:lang="ar">قالب ODS</comment>
- <comment xml:lang="be@latin">Šablon ODS</comment>
- <comment xml:lang="bg">Шаблон за таблици — ODS</comment>
- <comment xml:lang="ca">plantilla ODS</comment>
- <comment xml:lang="cs">šablona ODS</comment>
- <comment xml:lang="da">ODS-skabelon</comment>
- <comment xml:lang="de">ODS-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο ODS</comment>
- <comment xml:lang="en_GB">ODS template</comment>
- <comment xml:lang="eo">ODS-ŝablono</comment>
- <comment xml:lang="es">plantilla ODS</comment>
- <comment xml:lang="eu">ODS txantiloia</comment>
- <comment xml:lang="fi">ODS-malli</comment>
- <comment xml:lang="fo">ODS formur</comment>
- <comment xml:lang="fr">modèle ODS</comment>
- <comment xml:lang="ga">teimpléad ODS</comment>
- <comment xml:lang="gl">modelo ODS</comment>
- <comment xml:lang="he">תבנית ODS</comment>
- <comment xml:lang="hr">ODS predložak</comment>
- <comment xml:lang="hu">ODS-sablon</comment>
- <comment xml:lang="ia">Patrono ODS</comment>
- <comment xml:lang="id">Templat ODS</comment>
- <comment xml:lang="it">Modello ODS</comment>
- <comment xml:lang="ja">ODS テンプレート</comment>
- <comment xml:lang="ka">ODS-ის შაბლონი</comment>
- <comment xml:lang="kk">ODS үлгісі</comment>
- <comment xml:lang="ko">ODS 문서 서식</comment>
- <comment xml:lang="lt">ODS šablonas</comment>
- <comment xml:lang="lv">ODS veidne</comment>
- <comment xml:lang="nb">ODS-mal</comment>
- <comment xml:lang="nl">ODS-sjabloon</comment>
- <comment xml:lang="nn">ODS-mal</comment>
- <comment xml:lang="oc">modèl ODS</comment>
- <comment xml:lang="pl">Szablon ODS</comment>
- <comment xml:lang="pt">modelo ODS</comment>
- <comment xml:lang="pt_BR">Modelo ODS</comment>
- <comment xml:lang="ro">Șablon ODS</comment>
- <comment xml:lang="ru">Шаблон ODS</comment>
- <comment xml:lang="sk">Šablóna ODS</comment>
- <comment xml:lang="sl">Predloga dokumenta ODS</comment>
- <comment xml:lang="sq">Model ODS</comment>
- <comment xml:lang="sr">ОДС шаблон</comment>
- <comment xml:lang="sv">ODS-mall</comment>
- <comment xml:lang="tr">ODS şablonu</comment>
- <comment xml:lang="uk">шаблон ODS</comment>
- <comment xml:lang="vi">Mẫu ODS</comment>
- <comment xml:lang="zh_CN">ODS 模板</comment>
<comment xml:lang="zh_TW">ODS 範本</comment>
+ <comment xml:lang="zh_CN">ODS 模板</comment>
+ <comment xml:lang="vi">Mẫu ODS</comment>
+ <comment xml:lang="uk">шаблон ODS</comment>
+ <comment xml:lang="tr">ODS şablonu</comment>
+ <comment xml:lang="sv">ODS-mall</comment>
+ <comment xml:lang="sr">ОДС шаблон</comment>
+ <comment xml:lang="sq">gjedhe ODS</comment>
+ <comment xml:lang="sl">Predloga dokumenta ODS</comment>
+ <comment xml:lang="si">ODS ආකෘතිය</comment>
+ <comment xml:lang="sk">Šablóna ODS</comment>
+ <comment xml:lang="ru">Шаблон ODS</comment>
+ <comment xml:lang="ro">Șablon ODS</comment>
+ <comment xml:lang="pt_BR">Modelo ODS</comment>
+ <comment xml:lang="pt">modelo ODS</comment>
+ <comment xml:lang="pl">Szablon ODS</comment>
+ <comment xml:lang="oc">modèl ODS</comment>
+ <comment xml:lang="nn">ODS-mal</comment>
+ <comment xml:lang="nl">ODS-sjabloon</comment>
+ <comment xml:lang="nb">ODS-mal</comment>
+ <comment xml:lang="lv">ODS veidne</comment>
+ <comment xml:lang="lt">ODS šablonas</comment>
+ <comment xml:lang="ko">ODS 문서 서식</comment>
+ <comment xml:lang="kk">ODS үлгісі</comment>
+ <comment xml:lang="ka">ODS-ის შაბლონი</comment>
+ <comment xml:lang="ja">ODS テンプレート</comment>
+ <comment xml:lang="it">Modello ODS</comment>
+ <comment xml:lang="is">ODS sniðmát</comment>
+ <comment xml:lang="id">Templat ODS</comment>
+ <comment xml:lang="ia">Patrono ODS</comment>
+ <comment xml:lang="hu">ODS-sablon</comment>
+ <comment xml:lang="hr">ODS predložak</comment>
+ <comment xml:lang="he">תבנית ODS</comment>
+ <comment xml:lang="gl">modelo ODS</comment>
+ <comment xml:lang="ga">teimpléad ODS</comment>
+ <comment xml:lang="fur">model ODS</comment>
+ <comment xml:lang="fr">modèle ODS</comment>
+ <comment xml:lang="fo">ODS formur</comment>
+ <comment xml:lang="fi">ODS-malli</comment>
+ <comment xml:lang="eu">ODS txantiloia</comment>
+ <comment xml:lang="es">plantilla ODS</comment>
+ <comment xml:lang="eo">ODS-ŝablono</comment>
+ <comment xml:lang="en_GB">ODS template</comment>
+ <comment xml:lang="el">Πρότυπο ODS</comment>
+ <comment xml:lang="de">ODS-Vorlage</comment>
+ <comment xml:lang="da">ODS-skabelon</comment>
+ <comment xml:lang="cs">šablona ODS</comment>
+ <comment xml:lang="ca">plantilla ODS</comment>
+ <comment xml:lang="bg">Шаблон за таблици — ODS</comment>
+ <comment xml:lang="be@latin">Šablon ODS</comment>
+ <comment xml:lang="be">шаблон ODS</comment>
+ <comment xml:lang="ar">قالب ODS</comment>
+ <comment xml:lang="af">ODS-sjabloon</comment>
<acronym>ODS</acronym>
<expanded-acronym>OpenDocument Spreadsheet</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.spreadsheet-template" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.spreadsheet-template" offset="38"/>
</match>
</match>
</magic>
@@ -6130,61 +6521,66 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.chart">
<comment>ODC chart</comment>
- <comment xml:lang="ar">مخطط ODC</comment>
- <comment xml:lang="be@latin">Dyjahrama ODC</comment>
- <comment xml:lang="bg">Диаграма — ODC</comment>
- <comment xml:lang="ca">diagrama ODC</comment>
- <comment xml:lang="cs">graf ODC</comment>
- <comment xml:lang="da">ODC-diagram</comment>
- <comment xml:lang="de">ODC-Diagramm</comment>
- <comment xml:lang="el">Διάγραμμα ODC</comment>
- <comment xml:lang="en_GB">ODC chart</comment>
- <comment xml:lang="eo">ODC-diagramo</comment>
- <comment xml:lang="es">gráfico ODC</comment>
- <comment xml:lang="eu">ODC diagrama</comment>
- <comment xml:lang="fi">ODC-kaavio</comment>
- <comment xml:lang="fo">ODC strikumynd</comment>
- <comment xml:lang="fr">graphique ODC</comment>
- <comment xml:lang="ga">cairt ODC</comment>
- <comment xml:lang="gl">gráfica ODC</comment>
- <comment xml:lang="he">תו ODC</comment>
- <comment xml:lang="hr">ODC grafikon</comment>
- <comment xml:lang="hu">ODC-táblázat</comment>
- <comment xml:lang="ia">Graphico ODC</comment>
- <comment xml:lang="id">Bagan ODC</comment>
- <comment xml:lang="it">Grafico ODC</comment>
- <comment xml:lang="ja">ODC チャート</comment>
- <comment xml:lang="kk">ODC диаграммасы</comment>
- <comment xml:lang="ko">ODC 차트</comment>
- <comment xml:lang="lt">ODC diagrama</comment>
- <comment xml:lang="lv">ODC diagramma</comment>
- <comment xml:lang="nb">ODC-graf</comment>
- <comment xml:lang="nl">ODC-grafiek</comment>
- <comment xml:lang="nn">ODC-diagram</comment>
- <comment xml:lang="oc">grafic ODC</comment>
- <comment xml:lang="pl">Wykres ODC</comment>
- <comment xml:lang="pt">gráfico ODC</comment>
- <comment xml:lang="pt_BR">Gráfico ODC</comment>
- <comment xml:lang="ro">Diagramă ODC</comment>
- <comment xml:lang="ru">Диаграмма ODC</comment>
- <comment xml:lang="sk">Graf ODC</comment>
- <comment xml:lang="sl">Datoteka grafikona ODC</comment>
- <comment xml:lang="sq">Grafik ODC</comment>
- <comment xml:lang="sr">ОДЦ график</comment>
- <comment xml:lang="sv">ODC-diagram</comment>
- <comment xml:lang="tr">ODC çizelgesi</comment>
- <comment xml:lang="uk">діаграма ODC</comment>
- <comment xml:lang="vi">Sơ đồ ODC</comment>
- <comment xml:lang="zh_CN">ODC 图表</comment>
<comment xml:lang="zh_TW">ODC 圖表</comment>
+ <comment xml:lang="zh_CN">ODC 图表</comment>
+ <comment xml:lang="vi">Sơ đồ ODC</comment>
+ <comment xml:lang="uk">діаграма ODC</comment>
+ <comment xml:lang="tr">ODC çizgesi</comment>
+ <comment xml:lang="sv">ODC-diagram</comment>
+ <comment xml:lang="sr">ОДЦ график</comment>
+ <comment xml:lang="sq">grafik ODC</comment>
+ <comment xml:lang="sl">Datoteka grafikona ODC</comment>
+ <comment xml:lang="si">ODC ප්‍රස්ථාරය</comment>
+ <comment xml:lang="sk">Graf ODC</comment>
+ <comment xml:lang="ru">Диаграмма ODC</comment>
+ <comment xml:lang="ro">Diagramă ODC</comment>
+ <comment xml:lang="pt_BR">Gráfico ODC</comment>
+ <comment xml:lang="pt">gráfico ODC</comment>
+ <comment xml:lang="pl">Wykres ODC</comment>
+ <comment xml:lang="oc">grafic ODC</comment>
+ <comment xml:lang="nn">ODC-diagram</comment>
+ <comment xml:lang="nl">ODC-grafiek</comment>
+ <comment xml:lang="nb">ODC-graf</comment>
+ <comment xml:lang="lv">ODC diagramma</comment>
+ <comment xml:lang="lt">ODC diagrama</comment>
+ <comment xml:lang="ko">ODC 차트</comment>
+ <comment xml:lang="kk">ODC диаграммасы</comment>
+ <comment xml:lang="ja">ODC チャート</comment>
+ <comment xml:lang="it">Grafico ODC</comment>
+ <comment xml:lang="is">ODC graf</comment>
+ <comment xml:lang="id">Bagan ODC</comment>
+ <comment xml:lang="ia">Graphico ODC</comment>
+ <comment xml:lang="hu">ODC-táblázat</comment>
+ <comment xml:lang="hr">ODC grafikon</comment>
+ <comment xml:lang="he">תו ODC</comment>
+ <comment xml:lang="gl">gráfica ODC</comment>
+ <comment xml:lang="ga">cairt ODC</comment>
+ <comment xml:lang="fur">grafic ODC</comment>
+ <comment xml:lang="fr">graphique ODC</comment>
+ <comment xml:lang="fo">ODC strikumynd</comment>
+ <comment xml:lang="fi">ODC-kaavio</comment>
+ <comment xml:lang="eu">ODC diagrama</comment>
+ <comment xml:lang="es">gráfico ODC</comment>
+ <comment xml:lang="eo">ODC-diagramo</comment>
+ <comment xml:lang="en_GB">ODC chart</comment>
+ <comment xml:lang="el">Διάγραμμα ODC</comment>
+ <comment xml:lang="de">ODC-Diagramm</comment>
+ <comment xml:lang="da">ODC-diagram</comment>
+ <comment xml:lang="cs">graf ODC</comment>
+ <comment xml:lang="ca">diagrama ODC</comment>
+ <comment xml:lang="bg">Диаграма — ODC</comment>
+ <comment xml:lang="be@latin">Dyjahrama ODC</comment>
+ <comment xml:lang="be">дыяграма ODC</comment>
+ <comment xml:lang="ar">مخطط ODC</comment>
+ <comment xml:lang="af">ODC-grafiek</comment>
<acronym>ODC</acronym>
<expanded-acronym>OpenDocument Chart</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.chart" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.chart" offset="38"/>
</match>
</match>
</magic>
@@ -6192,58 +6588,64 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.chart-template">
<comment>ODC template</comment>
- <comment xml:lang="ar">قالب ODC</comment>
- <comment xml:lang="bg">Шаблон за диаграми — ODC</comment>
- <comment xml:lang="ca">plantilla ODC</comment>
- <comment xml:lang="cs">šablona ODC</comment>
- <comment xml:lang="da">ODC-skabelon</comment>
- <comment xml:lang="de">ODC-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο ODC</comment>
- <comment xml:lang="en_GB">ODC template</comment>
- <comment xml:lang="eo">ODC-ŝablono</comment>
- <comment xml:lang="es">plantilla ODC</comment>
- <comment xml:lang="eu">ODC txantiloia</comment>
- <comment xml:lang="fi">ODC-malli</comment>
- <comment xml:lang="fo">ODC formur</comment>
- <comment xml:lang="fr">modèle ODC</comment>
- <comment xml:lang="ga">teimpléad ODC</comment>
- <comment xml:lang="gl">modelo ODC</comment>
- <comment xml:lang="he">תבנית ODC</comment>
- <comment xml:lang="hr">ODC predložak</comment>
- <comment xml:lang="hu">ODC-sablon</comment>
- <comment xml:lang="ia">Patrono ODC</comment>
- <comment xml:lang="id">Templat ODC</comment>
- <comment xml:lang="it">Modello ODC</comment>
- <comment xml:lang="ja">ODC テンプレート</comment>
- <comment xml:lang="ka">ODC შაბლონი</comment>
- <comment xml:lang="kk">ODC үлгісі</comment>
- <comment xml:lang="ko">ODC 문서 서식</comment>
- <comment xml:lang="lt">ODC šablonas</comment>
- <comment xml:lang="lv">ODC veidne</comment>
- <comment xml:lang="nl">ODC-sjabloon</comment>
- <comment xml:lang="oc">modèl ODC</comment>
- <comment xml:lang="pl">Szablon ODC</comment>
- <comment xml:lang="pt">modelo ODC</comment>
- <comment xml:lang="pt_BR">Modelo ODC</comment>
- <comment xml:lang="ro">Șablon ODC</comment>
- <comment xml:lang="ru">Шаблон ODC</comment>
- <comment xml:lang="sk">Šablóna ODC</comment>
- <comment xml:lang="sl">Predloga ODC</comment>
- <comment xml:lang="sr">ОДЦ шаблон</comment>
- <comment xml:lang="sv">ODC-mall</comment>
- <comment xml:lang="tr">ODC şablonu</comment>
- <comment xml:lang="uk">шаблон ODC</comment>
- <comment xml:lang="vi">Mẫu ODC</comment>
- <comment xml:lang="zh_CN">ODC 模板</comment>
<comment xml:lang="zh_TW">ODC 範本</comment>
+ <comment xml:lang="zh_CN">ODC 模板</comment>
+ <comment xml:lang="vi">Mẫu ODC</comment>
+ <comment xml:lang="uk">шаблон ODC</comment>
+ <comment xml:lang="tr">ODC şablonu</comment>
+ <comment xml:lang="sv">ODC-mall</comment>
+ <comment xml:lang="sr">ОДЦ шаблон</comment>
+ <comment xml:lang="sq">gjedhe ODC</comment>
+ <comment xml:lang="sl">Predloga ODC</comment>
+ <comment xml:lang="si">ODC අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna ODC</comment>
+ <comment xml:lang="ru">Шаблон ODC</comment>
+ <comment xml:lang="ro">Șablon ODC</comment>
+ <comment xml:lang="pt_BR">Modelo ODC</comment>
+ <comment xml:lang="pt">modelo ODC</comment>
+ <comment xml:lang="pl">Szablon ODC</comment>
+ <comment xml:lang="oc">modèl ODC</comment>
+ <comment xml:lang="nl">ODC-sjabloon</comment>
+ <comment xml:lang="lv">ODC veidne</comment>
+ <comment xml:lang="lt">ODC šablonas</comment>
+ <comment xml:lang="ko">ODC 문서 서식</comment>
+ <comment xml:lang="kk">ODC үлгісі</comment>
+ <comment xml:lang="ka">ODC შაბლონი</comment>
+ <comment xml:lang="ja">ODC テンプレート</comment>
+ <comment xml:lang="it">Modello ODC</comment>
+ <comment xml:lang="is">ODC sniðmát</comment>
+ <comment xml:lang="id">Templat ODC</comment>
+ <comment xml:lang="ia">Patrono ODC</comment>
+ <comment xml:lang="hu">ODC-sablon</comment>
+ <comment xml:lang="hr">ODC predložak</comment>
+ <comment xml:lang="he">תבנית ODC</comment>
+ <comment xml:lang="gl">modelo ODC</comment>
+ <comment xml:lang="ga">teimpléad ODC</comment>
+ <comment xml:lang="fur">model ODC</comment>
+ <comment xml:lang="fr">modèle ODC</comment>
+ <comment xml:lang="fo">ODC formur</comment>
+ <comment xml:lang="fi">ODC-malli</comment>
+ <comment xml:lang="eu">ODC txantiloia</comment>
+ <comment xml:lang="es">plantilla ODC</comment>
+ <comment xml:lang="eo">ODC-ŝablono</comment>
+ <comment xml:lang="en_GB">ODC template</comment>
+ <comment xml:lang="el">Πρότυπο ODC</comment>
+ <comment xml:lang="de">ODC-Vorlage</comment>
+ <comment xml:lang="da">ODC-skabelon</comment>
+ <comment xml:lang="cs">šablona ODC</comment>
+ <comment xml:lang="ca">plantilla ODC</comment>
+ <comment xml:lang="bg">Шаблон за диаграми — ODC</comment>
+ <comment xml:lang="be">шаблон ODC</comment>
+ <comment xml:lang="ar">قالب ODC</comment>
+ <comment xml:lang="af">ODC-sjabloon</comment>
<acronym>ODC</acronym>
<expanded-acronym>OpenDocument Chart</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.chart-template" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.chart-template" offset="38"/>
</match>
</match>
</magic>
@@ -6251,62 +6653,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.formula">
<comment>ODF formula</comment>
- <comment xml:lang="ar">صيغة ODF</comment>
- <comment xml:lang="be@latin">Formuła ODF</comment>
- <comment xml:lang="bg">Формула — ODF</comment>
- <comment xml:lang="ca">fórmula ODF</comment>
- <comment xml:lang="cs">vzorec ODF</comment>
- <comment xml:lang="da">ODF-formel</comment>
- <comment xml:lang="de">ODF-Formel</comment>
- <comment xml:lang="el">Μαθηματικός τύπος ODF</comment>
- <comment xml:lang="en_GB">ODF formula</comment>
- <comment xml:lang="eo">ODF-formulo</comment>
- <comment xml:lang="es">fórmula ODF</comment>
- <comment xml:lang="eu">ODF formula</comment>
- <comment xml:lang="fi">ODF-kaava</comment>
- <comment xml:lang="fo">ODF frymil</comment>
- <comment xml:lang="fr">formule ODF</comment>
- <comment xml:lang="ga">foirmle ODF</comment>
- <comment xml:lang="gl">Fórula ODF</comment>
- <comment xml:lang="he">נוסחת ODF</comment>
- <comment xml:lang="hr">ODF formula</comment>
- <comment xml:lang="hu">ODF-képlet</comment>
- <comment xml:lang="ia">Formula ODF</comment>
- <comment xml:lang="id">Formula ODF</comment>
- <comment xml:lang="it">Formula ODF</comment>
- <comment xml:lang="ja">ODF 計算式</comment>
- <comment xml:lang="ka">ODF-ის ფორმულა</comment>
- <comment xml:lang="kk">ODF формуласы</comment>
- <comment xml:lang="ko">ODF 수식</comment>
- <comment xml:lang="lt">ODF formulė</comment>
- <comment xml:lang="lv">ODF formula</comment>
- <comment xml:lang="nb">ODF-formel</comment>
- <comment xml:lang="nl">ODF-formule</comment>
- <comment xml:lang="nn">ODF-formel</comment>
- <comment xml:lang="oc">formula ODF</comment>
- <comment xml:lang="pl">Formuła ODF</comment>
- <comment xml:lang="pt">fórmula ODF</comment>
- <comment xml:lang="pt_BR">Fórmula ODF</comment>
- <comment xml:lang="ro">Formulă ODF</comment>
- <comment xml:lang="ru">Формула ODF</comment>
- <comment xml:lang="sk">Vzorec ODF</comment>
- <comment xml:lang="sl">Dokument formule ODF</comment>
- <comment xml:lang="sq">Formulë ODF</comment>
- <comment xml:lang="sr">ОДФ формула</comment>
- <comment xml:lang="sv">ODF-formel</comment>
- <comment xml:lang="tr">ODF formülü</comment>
- <comment xml:lang="uk">формула ODF</comment>
- <comment xml:lang="vi">Công thức ODF</comment>
- <comment xml:lang="zh_CN">ODF 公式</comment>
<comment xml:lang="zh_TW">ODF 公式</comment>
+ <comment xml:lang="zh_CN">ODF 公式</comment>
+ <comment xml:lang="vi">Công thức ODF</comment>
+ <comment xml:lang="uk">формула ODF</comment>
+ <comment xml:lang="tr">ODF formülü</comment>
+ <comment xml:lang="sv">ODF-formel</comment>
+ <comment xml:lang="sr">ОДФ формула</comment>
+ <comment xml:lang="sq">formulë ODF</comment>
+ <comment xml:lang="sl">Dokument formule ODF</comment>
+ <comment xml:lang="si">ODF සූත්‍රය</comment>
+ <comment xml:lang="sk">Vzorec ODF</comment>
+ <comment xml:lang="ru">Формула ODF</comment>
+ <comment xml:lang="ro">Formulă ODF</comment>
+ <comment xml:lang="pt_BR">Fórmula ODF</comment>
+ <comment xml:lang="pt">fórmula ODF</comment>
+ <comment xml:lang="pl">Formuła ODF</comment>
+ <comment xml:lang="oc">formula ODF</comment>
+ <comment xml:lang="nn">ODF-formel</comment>
+ <comment xml:lang="nl">ODF-formule</comment>
+ <comment xml:lang="nb">ODF-formel</comment>
+ <comment xml:lang="lv">ODF formula</comment>
+ <comment xml:lang="lt">ODF formulė</comment>
+ <comment xml:lang="ko">ODF 수식</comment>
+ <comment xml:lang="kk">ODF формуласы</comment>
+ <comment xml:lang="ka">ODF-ის ფორმულა</comment>
+ <comment xml:lang="ja">ODF 計算式</comment>
+ <comment xml:lang="it">Formula ODF</comment>
+ <comment xml:lang="is">ODF formúla</comment>
+ <comment xml:lang="id">Formula ODF</comment>
+ <comment xml:lang="ia">Formula ODF</comment>
+ <comment xml:lang="hu">ODF-képlet</comment>
+ <comment xml:lang="hr">ODF formula</comment>
+ <comment xml:lang="he">נוסחת ODF</comment>
+ <comment xml:lang="gl">Fórula ODF</comment>
+ <comment xml:lang="ga">foirmle ODF</comment>
+ <comment xml:lang="fur">formule ODF</comment>
+ <comment xml:lang="fr">formule ODF</comment>
+ <comment xml:lang="fo">ODF frymil</comment>
+ <comment xml:lang="fi">ODF-kaava</comment>
+ <comment xml:lang="eu">ODF formula</comment>
+ <comment xml:lang="es">fórmula ODF</comment>
+ <comment xml:lang="eo">ODF-formulo</comment>
+ <comment xml:lang="en_GB">ODF formula</comment>
+ <comment xml:lang="el">Μαθηματικός τύπος ODF</comment>
+ <comment xml:lang="de">ODF-Formel</comment>
+ <comment xml:lang="da">ODF-formel</comment>
+ <comment xml:lang="cs">vzorec ODF</comment>
+ <comment xml:lang="ca">fórmula ODF</comment>
+ <comment xml:lang="bg">Формула — ODF</comment>
+ <comment xml:lang="be@latin">Formuła ODF</comment>
+ <comment xml:lang="be">формула ODF</comment>
+ <comment xml:lang="ar">صيغة ODF</comment>
+ <comment xml:lang="af">ODF-formule</comment>
<acronym>ODF</acronym>
<expanded-acronym>OpenDocument Formula</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.formula" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.formula" offset="38"/>
</match>
</match>
</magic>
@@ -6314,58 +6721,64 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.formula-template">
<comment>ODF template</comment>
- <comment xml:lang="ar">قالب ODF</comment>
- <comment xml:lang="bg">Шаблон за формули — ODF</comment>
- <comment xml:lang="ca">plantilla ODF</comment>
- <comment xml:lang="cs">šablona ODF</comment>
- <comment xml:lang="da">ODF-skabelon</comment>
- <comment xml:lang="de">ODF-Vorlage</comment>
- <comment xml:lang="el">Πρότυπο ODF</comment>
- <comment xml:lang="en_GB">ODF template</comment>
- <comment xml:lang="eo">ODF-ŝablono</comment>
- <comment xml:lang="es">plantilla ODF</comment>
- <comment xml:lang="eu">ODF txantiloia</comment>
- <comment xml:lang="fi">ODF-malli</comment>
- <comment xml:lang="fo">ODF formur</comment>
- <comment xml:lang="fr">modèle ODF</comment>
- <comment xml:lang="ga">teimpléad ODF</comment>
- <comment xml:lang="gl">modelo ODF</comment>
- <comment xml:lang="he">תבנית ODF</comment>
- <comment xml:lang="hr">ODF predložak</comment>
- <comment xml:lang="hu">ODG-sablon</comment>
- <comment xml:lang="ia">Patrono ODF</comment>
- <comment xml:lang="id">Templat ODF</comment>
- <comment xml:lang="it">Modello ODF</comment>
- <comment xml:lang="ja">ODF テンプレート</comment>
- <comment xml:lang="ka">ODF-ის შაბლონი</comment>
- <comment xml:lang="kk">ODF үлгісі</comment>
- <comment xml:lang="ko">ODF 문서 서식</comment>
- <comment xml:lang="lt">ODF šablonas</comment>
- <comment xml:lang="lv">ODF veidne</comment>
- <comment xml:lang="nl">ODF-sjabloon</comment>
- <comment xml:lang="oc">modèl ODF</comment>
- <comment xml:lang="pl">Szablon ODF</comment>
- <comment xml:lang="pt">modelo ODF</comment>
- <comment xml:lang="pt_BR">Modelo ODF</comment>
- <comment xml:lang="ro">Șablon ODF</comment>
- <comment xml:lang="ru">Шаблон ODF</comment>
- <comment xml:lang="sk">Šablóna ODF</comment>
- <comment xml:lang="sl">Predloga dokumenta ODF</comment>
- <comment xml:lang="sr">ОДФ шаблон</comment>
- <comment xml:lang="sv">ODF-mall</comment>
- <comment xml:lang="tr">ODF şablonu</comment>
- <comment xml:lang="uk">шаблон ODF</comment>
- <comment xml:lang="vi">Mẫu ODF</comment>
- <comment xml:lang="zh_CN">ODF 模板</comment>
<comment xml:lang="zh_TW">ODF 範本</comment>
+ <comment xml:lang="zh_CN">ODF 模板</comment>
+ <comment xml:lang="vi">Mẫu ODF</comment>
+ <comment xml:lang="uk">шаблон ODF</comment>
+ <comment xml:lang="tr">ODF şablonu</comment>
+ <comment xml:lang="sv">ODF-mall</comment>
+ <comment xml:lang="sr">ОДФ шаблон</comment>
+ <comment xml:lang="sq">gjedhe ODF</comment>
+ <comment xml:lang="sl">Predloga dokumenta ODF</comment>
+ <comment xml:lang="si">ODF ආකෘතිය</comment>
+ <comment xml:lang="sk">Šablóna ODF</comment>
+ <comment xml:lang="ru">Шаблон ODF</comment>
+ <comment xml:lang="ro">Șablon ODF</comment>
+ <comment xml:lang="pt_BR">Modelo ODF</comment>
+ <comment xml:lang="pt">modelo ODF</comment>
+ <comment xml:lang="pl">Szablon ODF</comment>
+ <comment xml:lang="oc">modèl ODF</comment>
+ <comment xml:lang="nl">ODF-sjabloon</comment>
+ <comment xml:lang="lv">ODF veidne</comment>
+ <comment xml:lang="lt">ODF šablonas</comment>
+ <comment xml:lang="ko">ODF 문서 서식</comment>
+ <comment xml:lang="kk">ODF үлгісі</comment>
+ <comment xml:lang="ka">ODF-ის შაბლონი</comment>
+ <comment xml:lang="ja">ODF テンプレート</comment>
+ <comment xml:lang="it">Modello ODF</comment>
+ <comment xml:lang="is">ODF sniðmát</comment>
+ <comment xml:lang="id">Templat ODF</comment>
+ <comment xml:lang="ia">Patrono ODF</comment>
+ <comment xml:lang="hu">ODG-sablon</comment>
+ <comment xml:lang="hr">ODF predložak</comment>
+ <comment xml:lang="he">תבנית ODF</comment>
+ <comment xml:lang="gl">modelo ODF</comment>
+ <comment xml:lang="ga">teimpléad ODF</comment>
+ <comment xml:lang="fur">model ODF</comment>
+ <comment xml:lang="fr">modèle ODF</comment>
+ <comment xml:lang="fo">ODF formur</comment>
+ <comment xml:lang="fi">ODF-malli</comment>
+ <comment xml:lang="eu">ODF txantiloia</comment>
+ <comment xml:lang="es">plantilla ODF</comment>
+ <comment xml:lang="eo">ODF-ŝablono</comment>
+ <comment xml:lang="en_GB">ODF template</comment>
+ <comment xml:lang="el">Πρότυπο ODF</comment>
+ <comment xml:lang="de">ODF-Vorlage</comment>
+ <comment xml:lang="da">ODF-skabelon</comment>
+ <comment xml:lang="cs">šablona ODF</comment>
+ <comment xml:lang="ca">plantilla ODF</comment>
+ <comment xml:lang="bg">Шаблон за формули — ODF</comment>
+ <comment xml:lang="be">шаблон ODF</comment>
+ <comment xml:lang="ar">قالب ODF</comment>
+ <comment xml:lang="af">ODF-sjabloon</comment>
<acronym>ODF</acronym>
<expanded-acronym>OpenDocument Formula</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.formula-template" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.formula-template" offset="38"/>
</match>
</match>
</magic>
@@ -6373,62 +6786,67 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.database">
<comment>ODB database</comment>
- <comment xml:lang="ar">قاعدة بيانات ODB</comment>
- <comment xml:lang="be@latin">Baza źviestak ODB</comment>
- <comment xml:lang="bg">База от данни — ODB</comment>
- <comment xml:lang="ca">base de dades ODB</comment>
- <comment xml:lang="cs">databáze ODB</comment>
- <comment xml:lang="da">ODB-database</comment>
- <comment xml:lang="de">ODB-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων ODB</comment>
- <comment xml:lang="en_GB">ODB database</comment>
- <comment xml:lang="eo">ODB-datumbazo</comment>
- <comment xml:lang="es">base de datos ODB</comment>
- <comment xml:lang="eu">ODB datu-basea</comment>
- <comment xml:lang="fi">ODB-tietokanta</comment>
- <comment xml:lang="fo">ODB dátustovnur</comment>
- <comment xml:lang="fr">base de données ODB</comment>
- <comment xml:lang="ga">bunachar sonraí ODB</comment>
- <comment xml:lang="gl">base de datos ODB</comment>
- <comment xml:lang="he">מסד נתונים ODB</comment>
- <comment xml:lang="hr">ODB baza podataka</comment>
- <comment xml:lang="hu">ODB-adatbázis</comment>
- <comment xml:lang="ia">Base de datos ODB</comment>
- <comment xml:lang="id">Basis data ODB</comment>
- <comment xml:lang="it">Database ODB</comment>
- <comment xml:lang="ja">ODB データベース</comment>
- <comment xml:lang="ka">ODB-ის მონაცემთა ბაზა</comment>
- <comment xml:lang="kk">ODB дерекқоры</comment>
- <comment xml:lang="ko">ODB 데이터베이스</comment>
- <comment xml:lang="lt">ODB duomenų bazė</comment>
- <comment xml:lang="lv">ODB datubāze</comment>
- <comment xml:lang="nb">ODB-database</comment>
- <comment xml:lang="nl">ODB-gegevensbank</comment>
- <comment xml:lang="nn">ODB-database</comment>
- <comment xml:lang="oc">banca de donadas ODB</comment>
- <comment xml:lang="pl">Baza danych ODB</comment>
- <comment xml:lang="pt">base de dados ODB</comment>
- <comment xml:lang="pt_BR">Banco de dados ODB</comment>
- <comment xml:lang="ro">Bază de date ODB</comment>
- <comment xml:lang="ru">База данных ODB</comment>
- <comment xml:lang="sk">Databáza ODB</comment>
- <comment xml:lang="sl">Podatkovna zbirka ODB</comment>
- <comment xml:lang="sq">Bazë me të dhëna ODB</comment>
- <comment xml:lang="sr">ОДБ база података</comment>
- <comment xml:lang="sv">ODB-databas</comment>
- <comment xml:lang="tr">ODB veritabanı</comment>
- <comment xml:lang="uk">база даних ODB</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu ODB</comment>
- <comment xml:lang="zh_CN">ODB 数据库</comment>
<comment xml:lang="zh_TW">ODB 資料庫</comment>
+ <comment xml:lang="zh_CN">ODB 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu ODB</comment>
+ <comment xml:lang="uk">база даних ODB</comment>
+ <comment xml:lang="tr">ODB veri tabanı</comment>
+ <comment xml:lang="sv">ODB-databas</comment>
+ <comment xml:lang="sr">ОДБ база података</comment>
+ <comment xml:lang="sq">bazë të dhënash ODB</comment>
+ <comment xml:lang="sl">Podatkovna zbirka ODB</comment>
+ <comment xml:lang="si">ODB දත්ත සමුදාය</comment>
+ <comment xml:lang="sk">Databáza ODB</comment>
+ <comment xml:lang="ru">База данных ODB</comment>
+ <comment xml:lang="ro">Bază de date ODB</comment>
+ <comment xml:lang="pt_BR">Banco de dados ODB</comment>
+ <comment xml:lang="pt">base de dados ODB</comment>
+ <comment xml:lang="pl">Baza danych ODB</comment>
+ <comment xml:lang="oc">banca de donadas ODB</comment>
+ <comment xml:lang="nn">ODB-database</comment>
+ <comment xml:lang="nl">ODB-gegevensbank</comment>
+ <comment xml:lang="nb">ODB-database</comment>
+ <comment xml:lang="lv">ODB datubāze</comment>
+ <comment xml:lang="lt">ODB duomenų bazė</comment>
+ <comment xml:lang="ko">ODB 데이터베이스</comment>
+ <comment xml:lang="kk">ODB дерекқоры</comment>
+ <comment xml:lang="ka">ODB-ის მონაცემთა ბაზა</comment>
+ <comment xml:lang="ja">ODB データベース</comment>
+ <comment xml:lang="it">Database ODB</comment>
+ <comment xml:lang="is">ODB gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data ODB</comment>
+ <comment xml:lang="ia">Base de datos ODB</comment>
+ <comment xml:lang="hu">ODB-adatbázis</comment>
+ <comment xml:lang="hr">ODB baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים ODB</comment>
+ <comment xml:lang="gl">base de datos ODB</comment>
+ <comment xml:lang="ga">bunachar sonraí ODB</comment>
+ <comment xml:lang="fur">base di dâts ODB</comment>
+ <comment xml:lang="fr">base de données ODB</comment>
+ <comment xml:lang="fo">ODB dátustovnur</comment>
+ <comment xml:lang="fi">ODB-tietokanta</comment>
+ <comment xml:lang="eu">ODB datu-basea</comment>
+ <comment xml:lang="es">base de datos ODB</comment>
+ <comment xml:lang="eo">ODB-datumbazo</comment>
+ <comment xml:lang="en_GB">ODB database</comment>
+ <comment xml:lang="el">Βάση δεδομένων ODB</comment>
+ <comment xml:lang="de">ODB-Datenbank</comment>
+ <comment xml:lang="da">ODB-database</comment>
+ <comment xml:lang="cs">databáze ODB</comment>
+ <comment xml:lang="ca">base de dades ODB</comment>
+ <comment xml:lang="bg">База от данни — ODB</comment>
+ <comment xml:lang="be@latin">Baza źviestak ODB</comment>
+ <comment xml:lang="be">база даных ODB</comment>
+ <comment xml:lang="ar">قاعدة بيانات ODB</comment>
+ <comment xml:lang="af">ODB-databasis</comment>
<acronym>ODB</acronym>
<expanded-acronym>OpenDocument Database</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.base" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.base" offset="38"/>
</match>
</match>
</magic>
@@ -6437,63 +6855,68 @@
</mime-type>
<mime-type type="application/vnd.oasis.opendocument.image">
<comment>ODI image</comment>
- <comment xml:lang="ar">صورة ODI</comment>
- <comment xml:lang="ast">Imaxe ODI</comment>
- <comment xml:lang="be@latin">Vyjava ODI</comment>
- <comment xml:lang="bg">Изображение — ODI</comment>
- <comment xml:lang="ca">imatge ODI</comment>
- <comment xml:lang="cs">obrázek ODI</comment>
- <comment xml:lang="da">ODI-billede</comment>
- <comment xml:lang="de">ODI-Bild</comment>
- <comment xml:lang="el">Εικόνα ODI</comment>
- <comment xml:lang="en_GB">ODI image</comment>
- <comment xml:lang="eo">ODI-bildo</comment>
- <comment xml:lang="es">imagen ODI</comment>
- <comment xml:lang="eu">ODI irudia</comment>
- <comment xml:lang="fi">ODI-kuva</comment>
- <comment xml:lang="fo">ODI mynd</comment>
- <comment xml:lang="fr">image ODI</comment>
- <comment xml:lang="ga">íomhá ODI</comment>
- <comment xml:lang="gl">imaxe ODI</comment>
- <comment xml:lang="he">תמונת ODI</comment>
- <comment xml:lang="hr">ODI slika</comment>
- <comment xml:lang="hu">ODI-kép</comment>
- <comment xml:lang="ia">Imagine ODI</comment>
- <comment xml:lang="id">Citra ODI</comment>
- <comment xml:lang="it">Immagine ODI</comment>
- <comment xml:lang="ja">ODI 画像</comment>
- <comment xml:lang="ka">ODI გამოსახულება</comment>
- <comment xml:lang="kk">ODI суреті</comment>
- <comment xml:lang="ko">ODI 그림</comment>
- <comment xml:lang="lt">ODI paveikslėlis</comment>
- <comment xml:lang="lv">ODI attēls</comment>
- <comment xml:lang="nb">ODI-bilde</comment>
- <comment xml:lang="nl">ODI-afbeelding</comment>
- <comment xml:lang="nn">ODI-bilete</comment>
- <comment xml:lang="oc">imatge ODI</comment>
- <comment xml:lang="pl">Obraz ODI</comment>
- <comment xml:lang="pt">imagem ODI</comment>
- <comment xml:lang="pt_BR">Imagem ODI</comment>
- <comment xml:lang="ro">Imagine ODI</comment>
- <comment xml:lang="ru">Изображение ODI</comment>
- <comment xml:lang="sk">Obrázok ODI</comment>
- <comment xml:lang="sl">Slikovna datoteka ODI</comment>
- <comment xml:lang="sq">Figurë ODI</comment>
- <comment xml:lang="sr">ОДИ слика</comment>
- <comment xml:lang="sv">ODI-bild</comment>
- <comment xml:lang="tr">ODI görüntüsü</comment>
- <comment xml:lang="uk">зображення ODI</comment>
- <comment xml:lang="vi">Ảnh ODI</comment>
- <comment xml:lang="zh_CN">ODI 图像</comment>
<comment xml:lang="zh_TW">ODI 影像</comment>
+ <comment xml:lang="zh_CN">ODI 图像</comment>
+ <comment xml:lang="vi">Ảnh ODI</comment>
+ <comment xml:lang="uk">зображення ODI</comment>
+ <comment xml:lang="tr">ODI görüntüsü</comment>
+ <comment xml:lang="sv">ODI-bild</comment>
+ <comment xml:lang="sr">ОДИ слика</comment>
+ <comment xml:lang="sq">figurë ODI</comment>
+ <comment xml:lang="sl">Slikovna datoteka ODI</comment>
+ <comment xml:lang="si">ODI රූපය</comment>
+ <comment xml:lang="sk">Obrázok ODI</comment>
+ <comment xml:lang="ru">Изображение ODI</comment>
+ <comment xml:lang="ro">Imagine ODI</comment>
+ <comment xml:lang="pt_BR">Imagem ODI</comment>
+ <comment xml:lang="pt">imagem ODI</comment>
+ <comment xml:lang="pl">Obraz ODI</comment>
+ <comment xml:lang="oc">imatge ODI</comment>
+ <comment xml:lang="nn">ODI-bilete</comment>
+ <comment xml:lang="nl">ODI-afbeelding</comment>
+ <comment xml:lang="nb">ODI-bilde</comment>
+ <comment xml:lang="lv">ODI attēls</comment>
+ <comment xml:lang="lt">ODI paveikslėlis</comment>
+ <comment xml:lang="ko">ODI 그림</comment>
+ <comment xml:lang="kk">ODI суреті</comment>
+ <comment xml:lang="ka">ODI გამოსახულება</comment>
+ <comment xml:lang="ja">ODI 画像</comment>
+ <comment xml:lang="it">Immagine ODI</comment>
+ <comment xml:lang="is">ODI mynd</comment>
+ <comment xml:lang="id">Citra ODI</comment>
+ <comment xml:lang="ia">Imagine ODI</comment>
+ <comment xml:lang="hu">ODI-kép</comment>
+ <comment xml:lang="hr">ODI slika</comment>
+ <comment xml:lang="he">תמונת ODI</comment>
+ <comment xml:lang="gl">imaxe ODI</comment>
+ <comment xml:lang="ga">íomhá ODI</comment>
+ <comment xml:lang="fur">imagjin ODI</comment>
+ <comment xml:lang="fr">image ODI</comment>
+ <comment xml:lang="fo">ODI mynd</comment>
+ <comment xml:lang="fi">ODI-kuva</comment>
+ <comment xml:lang="eu">ODI irudia</comment>
+ <comment xml:lang="es">imagen ODI</comment>
+ <comment xml:lang="eo">ODI-bildo</comment>
+ <comment xml:lang="en_GB">ODI image</comment>
+ <comment xml:lang="el">Εικόνα ODI</comment>
+ <comment xml:lang="de">ODI-Bild</comment>
+ <comment xml:lang="da">ODI-billede</comment>
+ <comment xml:lang="cs">obrázek ODI</comment>
+ <comment xml:lang="ca">imatge ODI</comment>
+ <comment xml:lang="bg">Изображение — ODI</comment>
+ <comment xml:lang="be@latin">Vyjava ODI</comment>
+ <comment xml:lang="be">выява ODI</comment>
+ <comment xml:lang="ast">Imaxe ODI</comment>
+ <comment xml:lang="ar">صورة ODI</comment>
+ <comment xml:lang="af">ODI-beeld</comment>
<acronym>ODI</acronym>
<expanded-acronym>OpenDocument Image</expanded-acronym>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/vnd.oasis.opendocument.image" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/vnd.oasis.opendocument.image" offset="38"/>
</match>
</match>
</magic>
@@ -6501,261 +6924,256 @@
</mime-type>
<mime-type type="application/vnd.openofficeorg.extension">
<comment>OpenOffice.org extension</comment>
- <comment xml:lang="ar">امتداد OpenOffice.org</comment>
- <comment xml:lang="ast">Estensión d'OpenOffice.org</comment>
- <comment xml:lang="be@latin">Pašyreńnie OpenOffice.org</comment>
- <comment xml:lang="bg">Разширение — OpenOffice</comment>
- <comment xml:lang="ca">extensió d'OpenOffice.org</comment>
- <comment xml:lang="cs">rozšíření OpenOffice.org</comment>
- <comment xml:lang="da">OpenOffice.org-udvidelse</comment>
- <comment xml:lang="de">OpenOffice.org-Erweiterung</comment>
- <comment xml:lang="el">Επέκταση OpenOffice.org</comment>
- <comment xml:lang="en_GB">OpenOffice.org extension</comment>
- <comment xml:lang="es">extensión de LibreOffice</comment>
- <comment xml:lang="eu">OpenOffice.org luzapena</comment>
- <comment xml:lang="fi">OpenOffice.org-laajennus</comment>
- <comment xml:lang="fo">OpenOffice.org víðkan</comment>
- <comment xml:lang="fr">extension OpenOffice.org</comment>
- <comment xml:lang="ga">eisínteacht OpenOffice.org</comment>
- <comment xml:lang="gl">Extensión de OpenOffice.org</comment>
- <comment xml:lang="he">הרחבה של OpenOffice.org</comment>
- <comment xml:lang="hr">OpenOffice.org proširenje</comment>
- <comment xml:lang="hu">OpenOffice.org kiterjesztés</comment>
- <comment xml:lang="ia">Extension OpenOffice.org</comment>
- <comment xml:lang="id">Ekstensi OpenOffice.org</comment>
- <comment xml:lang="it">Estensione OpenOffice.org</comment>
- <comment xml:lang="ja">OpenOffice.org 拡張機能</comment>
- <comment xml:lang="ka">OpenOffice.org-ის გაფართოება</comment>
- <comment xml:lang="kk">OpenOffice.org кеңейтуі</comment>
- <comment xml:lang="ko">OpenOffice.org 확장</comment>
- <comment xml:lang="lt">OpenOffice.org plėtinys</comment>
- <comment xml:lang="lv">OpenOffice.org paplašinājums</comment>
- <comment xml:lang="nl">OpenOffice.org-uitbreiding</comment>
- <comment xml:lang="nn">OpenOffice Writer-utviding</comment>
- <comment xml:lang="oc">extension OpenOffice.org</comment>
- <comment xml:lang="pl">Rozszerzenie OpenOffice.org</comment>
- <comment xml:lang="pt">extensão OpenOffice.org</comment>
- <comment xml:lang="pt_BR">Extensão do OpenOffice</comment>
- <comment xml:lang="ro">Extensie OpenOffice.org</comment>
- <comment xml:lang="ru">Расширение OpenOffice.org</comment>
- <comment xml:lang="sk">Rozšírenie OpenOffice.org</comment>
- <comment xml:lang="sl">Razširitev OpenOffice.org</comment>
- <comment xml:lang="sq">Shtojcë për OpenOffice.org</comment>
- <comment xml:lang="sr">проширење ОпенОфис.орг-а</comment>
- <comment xml:lang="sv">OpenOffice.org-tillägg</comment>
- <comment xml:lang="tr">OpenOffice.org eklentisi</comment>
- <comment xml:lang="uk">розширення OpenOffice.org</comment>
- <comment xml:lang="vi">Phần mở rộng của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org 扩展</comment>
<comment xml:lang="zh_TW">OpenOffice.org 擴充套件</comment>
+ <comment xml:lang="zh_CN">OpenOffice.org 扩展</comment>
+ <comment xml:lang="vi">Phần mở rộng của OpenOffice.org</comment>
+ <comment xml:lang="uk">розширення OpenOffice.org</comment>
+ <comment xml:lang="tr">OpenOffice.org eklentisi</comment>
+ <comment xml:lang="sv">OpenOffice.org-tillägg</comment>
+ <comment xml:lang="sr">проширење ОпенОфис.орг-а</comment>
+ <comment xml:lang="sq">zgjerim OpenOffice.org</comment>
+ <comment xml:lang="sl">Razširitev OpenOffice.org</comment>
+ <comment xml:lang="si">OpenOffice.org දිගුව</comment>
+ <comment xml:lang="sk">Rozšírenie OpenOffice.org</comment>
+ <comment xml:lang="ru">Расширение OpenOffice.org</comment>
+ <comment xml:lang="ro">Extensie OpenOffice.org</comment>
+ <comment xml:lang="pt_BR">Extensão do OpenOffice</comment>
+ <comment xml:lang="pt">extensão OpenOffice.org</comment>
+ <comment xml:lang="pl">Rozszerzenie OpenOffice.org</comment>
+ <comment xml:lang="oc">extension OpenOffice.org</comment>
+ <comment xml:lang="nn">OpenOffice Writer-utviding</comment>
+ <comment xml:lang="nl">OpenOffice.org-uitbreiding</comment>
+ <comment xml:lang="lv">OpenOffice.org paplašinājums</comment>
+ <comment xml:lang="lt">OpenOffice.org plėtinys</comment>
+ <comment xml:lang="ko">OpenOffice.org 확장</comment>
+ <comment xml:lang="kk">OpenOffice.org кеңейтуі</comment>
+ <comment xml:lang="ka">OpenOffice.org-ის გაფართოება</comment>
+ <comment xml:lang="ja">OpenOffice.org 拡張機能</comment>
+ <comment xml:lang="it">Estensione OpenOffice.org</comment>
+ <comment xml:lang="is">OpenOffice.org viðauki</comment>
+ <comment xml:lang="id">Ekstensi OpenOffice.org</comment>
+ <comment xml:lang="ia">Extension OpenOffice.org</comment>
+ <comment xml:lang="hu">OpenOffice.org kiterjesztés</comment>
+ <comment xml:lang="hr">OpenOffice.org proširenje</comment>
+ <comment xml:lang="he">הרחבה של OpenOffice.org</comment>
+ <comment xml:lang="gl">Extensión de OpenOffice.org</comment>
+ <comment xml:lang="ga">eisínteacht OpenOffice.org</comment>
+ <comment xml:lang="fur">estension OpenOffice.org</comment>
+ <comment xml:lang="fr">extension OpenOffice.org</comment>
+ <comment xml:lang="fo">OpenOffice.org víðkan</comment>
+ <comment xml:lang="fi">OpenOffice.org-laajennus</comment>
+ <comment xml:lang="eu">OpenOffice.org luzapena</comment>
+ <comment xml:lang="es">extensión de LibreOffice</comment>
+ <comment xml:lang="en_GB">OpenOffice.org extension</comment>
+ <comment xml:lang="el">Επέκταση OpenOffice.org</comment>
+ <comment xml:lang="de">OpenOffice.org-Erweiterung</comment>
+ <comment xml:lang="da">OpenOffice.org-udvidelse</comment>
+ <comment xml:lang="cs">rozšíření OpenOffice.org</comment>
+ <comment xml:lang="ca">extensió d'OpenOffice.org</comment>
+ <comment xml:lang="bg">Приставка — OpenOffice</comment>
+ <comment xml:lang="be@latin">Pašyreńnie OpenOffice.org</comment>
+ <comment xml:lang="be">пашырэнне OpenOffice.org</comment>
+ <comment xml:lang="ast">Estensión d'OpenOffice.org</comment>
+ <comment xml:lang="ar">امتداد OpenOffice.org</comment>
+ <comment xml:lang="af">OpenOffice.org-uitbreiding</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.oxt"/>
</mime-type>
<mime-type type="application/vnd.android.package-archive">
<comment>Android package</comment>
- <comment xml:lang="ast">Paquete d'Android</comment>
- <comment xml:lang="bg">Пакет — Android</comment>
- <comment xml:lang="ca">paquet d'Android</comment>
- <comment xml:lang="cs">balíčky systému Android</comment>
- <comment xml:lang="da">Android-pakke</comment>
- <comment xml:lang="de">Android-Paket</comment>
- <comment xml:lang="el">Πακέτο Android</comment>
- <comment xml:lang="en_GB">Android package</comment>
- <comment xml:lang="eo">Android-pakaĵo</comment>
- <comment xml:lang="es">paquete de Android</comment>
- <comment xml:lang="eu">Android paketea</comment>
- <comment xml:lang="fi">Android-paketti</comment>
- <comment xml:lang="fr">paquet Android</comment>
- <comment xml:lang="ga">pacáiste Android</comment>
- <comment xml:lang="gl">paquete de Android</comment>
- <comment xml:lang="he">חבילת אנדרויד</comment>
- <comment xml:lang="hr">Android paket</comment>
- <comment xml:lang="hu">Android csomag</comment>
- <comment xml:lang="ia">Pacchetto Android</comment>
- <comment xml:lang="id">Paket Android</comment>
- <comment xml:lang="it">Pacchetto Android</comment>
- <comment xml:lang="ja">Android パッケージ</comment>
- <comment xml:lang="ka">Android-ის პაკეტი</comment>
- <comment xml:lang="kk">Android дестесі</comment>
- <comment xml:lang="ko">Android 패키지</comment>
- <comment xml:lang="lv">Android pakotne</comment>
- <comment xml:lang="nl">Android pakket</comment>
- <comment xml:lang="oc">paquet Android</comment>
- <comment xml:lang="pl">Pakiet Androida</comment>
- <comment xml:lang="pt">pacote Android</comment>
- <comment xml:lang="pt_BR">Pacote do Android</comment>
- <comment xml:lang="ru">Пакет Android</comment>
- <comment xml:lang="sk">Balík Android</comment>
- <comment xml:lang="sl">Paket Android</comment>
- <comment xml:lang="sr">Андроидов пакет</comment>
- <comment xml:lang="sv">Android-paket</comment>
- <comment xml:lang="tr">Android paketi</comment>
- <comment xml:lang="uk">пакунок Android</comment>
- <comment xml:lang="zh_CN">Android 应用包</comment>
<comment xml:lang="zh_TW">Android 軟體包</comment>
- <sub-class-of type="application/x-java-archive"/>
+ <comment xml:lang="zh_CN">Android 应用包</comment>
+ <comment xml:lang="uk">пакунок Android</comment>
+ <comment xml:lang="tr">Android paketi</comment>
+ <comment xml:lang="sv">Android-paket</comment>
+ <comment xml:lang="sr">Андроидов пакет</comment>
+ <comment xml:lang="sq">pakete Android</comment>
+ <comment xml:lang="sl">Paket Android</comment>
+ <comment xml:lang="si">Android පැකේජය</comment>
+ <comment xml:lang="sk">Balík Android</comment>
+ <comment xml:lang="ru">Пакет Android</comment>
+ <comment xml:lang="pt_BR">Pacote do Android</comment>
+ <comment xml:lang="pt">pacote Android</comment>
+ <comment xml:lang="pl">Pakiet Androida</comment>
+ <comment xml:lang="oc">paquet Android</comment>
+ <comment xml:lang="nl">Android-pakket</comment>
+ <comment xml:lang="lv">Android pakotne</comment>
+ <comment xml:lang="lt">Android paketas</comment>
+ <comment xml:lang="ko">Android 패키지</comment>
+ <comment xml:lang="kk">Android дестесі</comment>
+ <comment xml:lang="ka">Android-ის პაკეტი</comment>
+ <comment xml:lang="ja">Android パッケージ</comment>
+ <comment xml:lang="it">Pacchetto Android</comment>
+ <comment xml:lang="is">Android pakki</comment>
+ <comment xml:lang="id">Paket Android</comment>
+ <comment xml:lang="ia">Pacchetto Android</comment>
+ <comment xml:lang="hu">Android csomag</comment>
+ <comment xml:lang="hr">Android paket</comment>
+ <comment xml:lang="he">חבילת Android</comment>
+ <comment xml:lang="gl">paquete de Android</comment>
+ <comment xml:lang="ga">pacáiste Android</comment>
+ <comment xml:lang="fur">pachet Android</comment>
+ <comment xml:lang="fr">paquet Android</comment>
+ <comment xml:lang="fi">Android-paketti</comment>
+ <comment xml:lang="eu">Android paketea</comment>
+ <comment xml:lang="es">paquete de Android</comment>
+ <comment xml:lang="eo">Android-pakaĵo</comment>
+ <comment xml:lang="en_GB">Android package</comment>
+ <comment xml:lang="el">Πακέτο Android</comment>
+ <comment xml:lang="de">Android-Paket</comment>
+ <comment xml:lang="da">Android-pakke</comment>
+ <comment xml:lang="cs">balíčky systému Android</comment>
+ <comment xml:lang="ca">paquet d'Android</comment>
+ <comment xml:lang="bg">Пакет — Android</comment>
+ <comment xml:lang="be">пакет Android</comment>
+ <comment xml:lang="ast">Paquete d'Android</comment>
+ <comment xml:lang="ar">حزمة أندرويد</comment>
+ <comment xml:lang="af">Android-pakket</comment>
+ <sub-class-of type="application/java-archive"/>
<glob pattern="*.apk"/>
</mime-type>
<mime-type type="application/vnd.symbian.install">
<comment>SIS package</comment>
- <comment xml:lang="ar">حزمة SIS</comment>
- <comment xml:lang="ast">Paquete SIS</comment>
- <comment xml:lang="be@latin">Pakunak SIS</comment>
- <comment xml:lang="bg">Пакет — SIS</comment>
- <comment xml:lang="ca">paquet SIS</comment>
- <comment xml:lang="cs">balíček SIS</comment>
- <comment xml:lang="da">SIS-pakke</comment>
- <comment xml:lang="de">SIS-Paket</comment>
- <comment xml:lang="el">Πακέτο SIS</comment>
- <comment xml:lang="en_GB">SIS package</comment>
- <comment xml:lang="eo">SIS-pakaĵo</comment>
- <comment xml:lang="es">paquete SIS</comment>
- <comment xml:lang="eu">SIS paketea</comment>
- <comment xml:lang="fi">SIS-paketti</comment>
- <comment xml:lang="fo">SIS pakki</comment>
- <comment xml:lang="fr">paquet SIS</comment>
- <comment xml:lang="ga">pacáiste SIS</comment>
- <comment xml:lang="gl">paquete SIS</comment>
- <comment xml:lang="he">חבילת SIS</comment>
- <comment xml:lang="hr">SIS paket</comment>
- <comment xml:lang="hu">SIS csomag</comment>
- <comment xml:lang="ia">Pacchetto SIS</comment>
- <comment xml:lang="id">Paket SIS</comment>
- <comment xml:lang="it">Pacchetto SIS</comment>
- <comment xml:lang="ja">SIS パッケージ</comment>
- <comment xml:lang="kk">SIS дестесі</comment>
- <comment xml:lang="ko">SIS 패키지</comment>
- <comment xml:lang="lt">SIS paketas</comment>
- <comment xml:lang="lv">SIS pakotne</comment>
- <comment xml:lang="nb">SIS-pakke</comment>
- <comment xml:lang="nl">SIS-pakket</comment>
- <comment xml:lang="nn">SIS-pakke</comment>
- <comment xml:lang="oc">paquet SIS</comment>
- <comment xml:lang="pl">Pakiet SIS</comment>
- <comment xml:lang="pt">pacote SIS</comment>
- <comment xml:lang="pt_BR">Pacote SIS</comment>
- <comment xml:lang="ro">Pachet SIS</comment>
- <comment xml:lang="ru">Пакет SIS</comment>
- <comment xml:lang="sk">Balíček SIS</comment>
- <comment xml:lang="sl">Datoteka paketa SIS</comment>
- <comment xml:lang="sq">Paketë SIS</comment>
- <comment xml:lang="sr">СИС пакет</comment>
- <comment xml:lang="sv">SIS-paket</comment>
- <comment xml:lang="tr">SIS paketi</comment>
- <comment xml:lang="uk">пакунок SIS</comment>
- <comment xml:lang="vi">Gói SIS</comment>
- <comment xml:lang="zh_CN">SIS 软件包</comment>
<comment xml:lang="zh_TW">SIS 軟體包</comment>
+ <comment xml:lang="zh_CN">SIS 软件包</comment>
+ <comment xml:lang="vi">Gói SIS</comment>
+ <comment xml:lang="uk">пакунок SIS</comment>
+ <comment xml:lang="tr">SIS paketi</comment>
+ <comment xml:lang="sv">SIS-paket</comment>
+ <comment xml:lang="sr">СИС пакет</comment>
+ <comment xml:lang="sq">paketë SIS</comment>
+ <comment xml:lang="sl">Datoteka paketa SIS</comment>
+ <comment xml:lang="si">SIS පැකේජය</comment>
+ <comment xml:lang="sk">Balíček SIS</comment>
+ <comment xml:lang="ru">Пакет SIS</comment>
+ <comment xml:lang="ro">Pachet SIS</comment>
+ <comment xml:lang="pt_BR">Pacote SIS</comment>
+ <comment xml:lang="pt">pacote SIS</comment>
+ <comment xml:lang="pl">Pakiet SIS</comment>
+ <comment xml:lang="oc">paquet SIS</comment>
+ <comment xml:lang="nn">SIS-pakke</comment>
+ <comment xml:lang="nl">SIS-pakket</comment>
+ <comment xml:lang="nb">SIS-pakke</comment>
+ <comment xml:lang="lv">SIS pakotne</comment>
+ <comment xml:lang="lt">SIS paketas</comment>
+ <comment xml:lang="ko">SIS 패키지</comment>
+ <comment xml:lang="kk">SIS дестесі</comment>
+ <comment xml:lang="ja">SIS パッケージ</comment>
+ <comment xml:lang="it">Pacchetto SIS</comment>
+ <comment xml:lang="is">SIS pakki</comment>
+ <comment xml:lang="id">Paket SIS</comment>
+ <comment xml:lang="ia">Pacchetto SIS</comment>
+ <comment xml:lang="hu">SIS csomag</comment>
+ <comment xml:lang="hr">SIS paket</comment>
+ <comment xml:lang="he">חבילת SIS</comment>
+ <comment xml:lang="gl">paquete SIS</comment>
+ <comment xml:lang="ga">pacáiste SIS</comment>
+ <comment xml:lang="fur">pachet SIS</comment>
+ <comment xml:lang="fr">paquet SIS</comment>
+ <comment xml:lang="fo">SIS pakki</comment>
+ <comment xml:lang="fi">SIS-paketti</comment>
+ <comment xml:lang="eu">SIS paketea</comment>
+ <comment xml:lang="es">paquete SIS</comment>
+ <comment xml:lang="eo">SIS-pakaĵo</comment>
+ <comment xml:lang="en_GB">SIS package</comment>
+ <comment xml:lang="el">Πακέτο SIS</comment>
+ <comment xml:lang="de">SIS-Paket</comment>
+ <comment xml:lang="da">SIS-pakke</comment>
+ <comment xml:lang="cs">balíček SIS</comment>
+ <comment xml:lang="ca">paquet SIS</comment>
+ <comment xml:lang="bg">Пакет — SIS</comment>
+ <comment xml:lang="be@latin">Pakunak SIS</comment>
+ <comment xml:lang="be">пакет SIS</comment>
+ <comment xml:lang="ast">Paquete SIS</comment>
+ <comment xml:lang="ar">حزمة SIS</comment>
+ <comment xml:lang="af">SIS-pakket</comment>
<acronym>SIS</acronym>
<expanded-acronym>Symbian Installation File</expanded-acronym>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="0x10000419" type="little32" offset="8"/>
+ <magic>
+ <match type="little32" value="0x10000419" offset="8"/>
</magic>
<glob pattern="*.sis"/>
</mime-type>
<mime-type type="x-epoc/x-sisx-app">
<comment>SISX package</comment>
- <comment xml:lang="ar">حزمة SISX</comment>
- <comment xml:lang="ast">Paquete SISX</comment>
- <comment xml:lang="be@latin">Pakunak SISX</comment>
- <comment xml:lang="bg">Пакет — SISX</comment>
- <comment xml:lang="ca">paquet SISX</comment>
- <comment xml:lang="cs">balíček SISX</comment>
- <comment xml:lang="da">SISX-pakke</comment>
- <comment xml:lang="de">SISX-Paket</comment>
- <comment xml:lang="el">Πακέτο SISX</comment>
- <comment xml:lang="en_GB">SISX package</comment>
- <comment xml:lang="eo">SISX-pakaĵo</comment>
- <comment xml:lang="es">paquete SISX</comment>
- <comment xml:lang="eu">SISX paketea</comment>
- <comment xml:lang="fi">SISX-paketti</comment>
- <comment xml:lang="fo">SISX pakki</comment>
- <comment xml:lang="fr">paquet SISX</comment>
- <comment xml:lang="ga">pacáiste SISX</comment>
- <comment xml:lang="gl">paquete SISX</comment>
- <comment xml:lang="he">חבילת SISX</comment>
- <comment xml:lang="hr">SISX paket</comment>
- <comment xml:lang="hu">SISX csomag</comment>
- <comment xml:lang="ia">Pacchetto SISX</comment>
- <comment xml:lang="id">Paket SISX</comment>
- <comment xml:lang="it">Pacchetto SISX</comment>
- <comment xml:lang="ja">SISX パッケージ</comment>
- <comment xml:lang="kk">SISX дестесі</comment>
- <comment xml:lang="ko">SISX 패키지</comment>
- <comment xml:lang="lt">SISX paketas</comment>
- <comment xml:lang="lv">SISX pakotne</comment>
- <comment xml:lang="nb">SISX-pakke</comment>
- <comment xml:lang="nl">SISX-pakket</comment>
- <comment xml:lang="nn">SISX-pakke</comment>
- <comment xml:lang="oc">paquet SISX</comment>
- <comment xml:lang="pl">Pakiet SISX</comment>
- <comment xml:lang="pt">pacote SISX</comment>
- <comment xml:lang="pt_BR">Pacote SISX</comment>
- <comment xml:lang="ro">Pachet SISX</comment>
- <comment xml:lang="ru">Пакет SISX</comment>
- <comment xml:lang="sk">Balíček SISX</comment>
- <comment xml:lang="sl">Datoteka paketa SISX</comment>
- <comment xml:lang="sq">Paketë SISX</comment>
- <comment xml:lang="sr">СИСИкс пакет</comment>
- <comment xml:lang="sv">SISX-paket</comment>
- <comment xml:lang="tr">SISX paketi</comment>
- <comment xml:lang="uk">пакунок SISX</comment>
- <comment xml:lang="vi">Gói SISX</comment>
- <comment xml:lang="zh_CN">SISX 软件包</comment>
<comment xml:lang="zh_TW">SISX 軟體包</comment>
+ <comment xml:lang="zh_CN">SISX 软件包</comment>
+ <comment xml:lang="vi">Gói SISX</comment>
+ <comment xml:lang="uk">пакунок SISX</comment>
+ <comment xml:lang="tr">SISX paketi</comment>
+ <comment xml:lang="sv">SISX-paket</comment>
+ <comment xml:lang="sr">СИСИкс пакет</comment>
+ <comment xml:lang="sq">paketë SISX</comment>
+ <comment xml:lang="sl">Datoteka paketa SISX</comment>
+ <comment xml:lang="si">SISX පැකේජය</comment>
+ <comment xml:lang="sk">Balíček SISX</comment>
+ <comment xml:lang="ru">Пакет SISX</comment>
+ <comment xml:lang="ro">Pachet SISX</comment>
+ <comment xml:lang="pt_BR">Pacote SISX</comment>
+ <comment xml:lang="pt">pacote SISX</comment>
+ <comment xml:lang="pl">Pakiet SISX</comment>
+ <comment xml:lang="oc">paquet SISX</comment>
+ <comment xml:lang="nn">SISX-pakke</comment>
+ <comment xml:lang="nl">SISX-pakket</comment>
+ <comment xml:lang="nb">SISX-pakke</comment>
+ <comment xml:lang="lv">SISX pakotne</comment>
+ <comment xml:lang="lt">SISX paketas</comment>
+ <comment xml:lang="ko">SISX 패키지</comment>
+ <comment xml:lang="kk">SISX дестесі</comment>
+ <comment xml:lang="ja">SISX パッケージ</comment>
+ <comment xml:lang="it">Pacchetto SISX</comment>
+ <comment xml:lang="is">SISX pakki</comment>
+ <comment xml:lang="id">Paket SISX</comment>
+ <comment xml:lang="ia">Pacchetto SISX</comment>
+ <comment xml:lang="hu">SISX csomag</comment>
+ <comment xml:lang="hr">SISX paket</comment>
+ <comment xml:lang="he">חבילת SISX</comment>
+ <comment xml:lang="gl">paquete SISX</comment>
+ <comment xml:lang="ga">pacáiste SISX</comment>
+ <comment xml:lang="fur">pachet SISX</comment>
+ <comment xml:lang="fr">paquet SISX</comment>
+ <comment xml:lang="fo">SISX pakki</comment>
+ <comment xml:lang="fi">SISX-paketti</comment>
+ <comment xml:lang="eu">SISX paketea</comment>
+ <comment xml:lang="es">paquete SISX</comment>
+ <comment xml:lang="eo">SISX-pakaĵo</comment>
+ <comment xml:lang="en_GB">SISX package</comment>
+ <comment xml:lang="el">Πακέτο SISX</comment>
+ <comment xml:lang="de">SISX-Paket</comment>
+ <comment xml:lang="da">SISX-pakke</comment>
+ <comment xml:lang="cs">balíček SISX</comment>
+ <comment xml:lang="ca">paquet SISX</comment>
+ <comment xml:lang="bg">Пакет — SISX</comment>
+ <comment xml:lang="be@latin">Pakunak SISX</comment>
+ <comment xml:lang="be">пакет SISX</comment>
+ <comment xml:lang="ast">Paquete SISX</comment>
+ <comment xml:lang="ar">حزمة SISX</comment>
+ <comment xml:lang="af">SISX-pakket</comment>
<acronym>SIS</acronym>
<expanded-acronym>Symbian Installation File</expanded-acronym>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="0x10201a7a" type="little32" offset="0"/>
+ <magic>
+ <match type="little32" value="0x10201a7a" offset="0"/>
</magic>
<glob pattern="*.sisx"/>
</mime-type>
<mime-type type="application/vnd.tcpdump.pcap">
- <comment>Network Packet Capture</comment>
- <comment xml:lang="bg">Прихванати пакети по мрежата</comment>
- <comment xml:lang="ca">captura de paquets de xarxa</comment>
- <comment xml:lang="cs">Network Packet Capture</comment>
- <comment xml:lang="da">Netværkspakkeoptegnelse</comment>
- <comment xml:lang="de">Netzwerk-Paketmitschnitt</comment>
- <comment xml:lang="el">Σύλληψη πακέτων δικτύου</comment>
- <comment xml:lang="en_GB">Network Packet Capture</comment>
- <comment xml:lang="es">captura de paquete de red</comment>
- <comment xml:lang="eu">Sareko pakete kaptura</comment>
- <comment xml:lang="fi">Verkkopakettien kaappaus</comment>
- <comment xml:lang="fr">capture de paquet réseau</comment>
- <comment xml:lang="ga">Gabháltas Paicéid Líonra</comment>
- <comment xml:lang="gl">Captura de Network Packet</comment>
- <comment xml:lang="he">לכידה של מנות נתונים ברשת</comment>
- <comment xml:lang="hr">Mrežno hvatanje paketa</comment>
- <comment xml:lang="hu">Hálózati csomagelfogás</comment>
- <comment xml:lang="ia">Captura de pacchettos de rete</comment>
- <comment xml:lang="id">Tangkapan Paket Jaringan</comment>
- <comment xml:lang="it">Cattura pacchetti rete</comment>
- <comment xml:lang="ja">ネットワークパケットキャプチャー</comment>
- <comment xml:lang="ka">ქსელური პაკეტის ანაბეჭდი</comment>
- <comment xml:lang="kk">ұсталған желілік пакеттер</comment>
- <comment xml:lang="ko">네트워크 패킷 캡처</comment>
- <comment xml:lang="lv">Network Packet Capture</comment>
- <comment xml:lang="nl">Network Packet Capture</comment>
- <comment xml:lang="oc">captura de paquet ret</comment>
- <comment xml:lang="pl">Przechwycenie pakietu sieciowego</comment>
- <comment xml:lang="pt">captura Network Packet</comment>
- <comment xml:lang="pt_BR">Pacote de captura de rede</comment>
+ <comment>Network packet capture</comment>
+ <comment xml:lang="uk">перехоплення пакетів мережі</comment>
+ <comment xml:lang="sv">Nätverkspaketsspårning</comment>
<comment xml:lang="ru">Захваченные сетевые пакеты</comment>
- <comment xml:lang="sk">Zachytené sieťové pakety</comment>
- <comment xml:lang="sl">Zajem omrežnih paketov</comment>
- <comment xml:lang="sr">Снимање мрежног пакета</comment>
- <comment xml:lang="sv">Fångst av nätverkspaket</comment>
- <comment xml:lang="tr">Ağ Paket Yakalaması</comment>
- <comment xml:lang="uk">перехоплені дані мережевих пакетів</comment>
- <comment xml:lang="zh_CN">网络包抓取</comment>
- <comment xml:lang="zh_TW">網路封包捕捉</comment>
- <magic priority="50">
- <match value="0xa1b2c3d4" type="host32" offset="0"/>
- <match value="0xd4c3b2a1" type="host32" offset="0"/>
+ <comment xml:lang="pt_BR">Captura de pacotes de rede</comment>
+ <comment xml:lang="pl">Przechwycenie pakietu sieciowego</comment>
+ <comment xml:lang="it">Cattura pacchetti di rete</comment>
+ <comment xml:lang="gl">Captura de paquetes de red</comment>
+ <comment xml:lang="es">captura de paquetes de red</comment>
+ <comment xml:lang="de">Netzwerkpaket-Aufzeichnung</comment>
+ <comment xml:lang="be">захопленыя сеткавыя пакеты</comment>
+ <magic>
+ <match type="host32" value="0xa1b2c3d4" offset="0"/>
+ <match type="host32" value="0xd4c3b2a1" offset="0"/>
</magic>
<glob pattern="*.pcap"/>
<glob pattern="*.cap"/>
@@ -6765,63 +7183,69 @@
</mime-type>
<mime-type type="application/vnd.wordperfect">
<comment>WordPerfect document</comment>
- <comment xml:lang="ar">مستند WordPerfect</comment>
- <comment xml:lang="ast">Documentu de WordPerfect</comment>
- <comment xml:lang="az">WordPerfect sənədi</comment>
- <comment xml:lang="be@latin">Dakument WordPerfect</comment>
- <comment xml:lang="bg">Документ — WordPerfect</comment>
- <comment xml:lang="ca">document WordPerfect</comment>
- <comment xml:lang="cs">dokument WordPerfect</comment>
- <comment xml:lang="cy">Dogfen WordPerfect</comment>
- <comment xml:lang="da">WordPerfect-dokument</comment>
- <comment xml:lang="de">WordPerfect-Dokument</comment>
- <comment xml:lang="el">Έγγραφο WordPerfect</comment>
- <comment xml:lang="en_GB">WordPerfect document</comment>
- <comment xml:lang="eo">WordPerfect-dokumento</comment>
- <comment xml:lang="es">documento de WordPerfect</comment>
- <comment xml:lang="eu">WordPerfect dokumentua</comment>
- <comment xml:lang="fi">WordPerfect-asiakirja</comment>
- <comment xml:lang="fo">WordPerfect skjal</comment>
- <comment xml:lang="fr">document WordPerfect</comment>
- <comment xml:lang="ga">cáipéis WordPerfect</comment>
- <comment xml:lang="gl">documento de WordPerfect</comment>
- <comment xml:lang="he">מסמך WordPerfect</comment>
- <comment xml:lang="hr">WordPerfect dokument</comment>
- <comment xml:lang="hu">WordPerfect-dokumentum</comment>
- <comment xml:lang="ia">Documento WordPerfect</comment>
- <comment xml:lang="id">Dokumen WordPerfect</comment>
- <comment xml:lang="it">Documento WordPerfect</comment>
- <comment xml:lang="ja">WordPerfect ドキュメント</comment>
- <comment xml:lang="kk">WordPerfect құжаты</comment>
- <comment xml:lang="ko">WordPerfect 문서</comment>
- <comment xml:lang="lt">WordPerfect dokumentas</comment>
- <comment xml:lang="lv">WordPerfect dokuments</comment>
- <comment xml:lang="ms">Dokumen WordPerfect</comment>
- <comment xml:lang="nb">WordPerfect-dokument</comment>
- <comment xml:lang="nl">WordPerfect-document</comment>
- <comment xml:lang="nn">WordPerfect-dokument</comment>
- <comment xml:lang="oc">document WordPerfect</comment>
- <comment xml:lang="pl">Dokument WordPerfect</comment>
- <comment xml:lang="pt">documento WordPerfect</comment>
- <comment xml:lang="pt_BR">Documento do WordPerfect</comment>
- <comment xml:lang="ro">Document WordPerfect</comment>
- <comment xml:lang="ru">Документ WordPerfect</comment>
- <comment xml:lang="sk">Dokument WordPerfect</comment>
- <comment xml:lang="sl">Dokument WordPerfect</comment>
- <comment xml:lang="sq">Dokument WordPerfect</comment>
- <comment xml:lang="sr">документ Ворд перфекта</comment>
- <comment xml:lang="sv">WordPerfect-dokument</comment>
- <comment xml:lang="tr">WordPerfect belgesi</comment>
- <comment xml:lang="uk">документ WordPerfect</comment>
- <comment xml:lang="vi">Tài liệu WordPerfect</comment>
- <comment xml:lang="zh_CN">WordPerfect 文档</comment>
<comment xml:lang="zh_TW">WordPerfect 文件</comment>
+ <comment xml:lang="zh_CN">WordPerfect 文档</comment>
+ <comment xml:lang="vi">Tài liệu WordPerfect</comment>
+ <comment xml:lang="uk">документ WordPerfect</comment>
+ <comment xml:lang="tr">WordPerfect belgesi</comment>
+ <comment xml:lang="sv">WordPerfect-dokument</comment>
+ <comment xml:lang="sr">документ Ворд перфекта</comment>
+ <comment xml:lang="sq">dokument WordPerfect</comment>
+ <comment xml:lang="sl">Dokument WordPerfect</comment>
+ <comment xml:lang="si">WordPerfect ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument WordPerfect</comment>
+ <comment xml:lang="ru">Документ WordPerfect</comment>
+ <comment xml:lang="ro">Document WordPerfect</comment>
+ <comment xml:lang="pt_BR">Documento do WordPerfect</comment>
+ <comment xml:lang="pt">documento WordPerfect</comment>
+ <comment xml:lang="pl">Dokument WordPerfect</comment>
+ <comment xml:lang="oc">document WordPerfect</comment>
+ <comment xml:lang="nn">WordPerfect-dokument</comment>
+ <comment xml:lang="nl">WordPerfect-document</comment>
+ <comment xml:lang="nb">WordPerfect-dokument</comment>
+ <comment xml:lang="ms">Dokumen WordPerfect</comment>
+ <comment xml:lang="lv">WordPerfect dokuments</comment>
+ <comment xml:lang="lt">WordPerfect dokumentas</comment>
+ <comment xml:lang="ko">WordPerfect 문서</comment>
+ <comment xml:lang="kk">WordPerfect құжаты</comment>
+ <comment xml:lang="ka">WordPerfect -ის დოკუმენტი</comment>
+ <comment xml:lang="ja">WordPerfect ドキュメント</comment>
+ <comment xml:lang="it">Documento WordPerfect</comment>
+ <comment xml:lang="is">WordPerfect skjal</comment>
+ <comment xml:lang="id">Dokumen WordPerfect</comment>
+ <comment xml:lang="ia">Documento WordPerfect</comment>
+ <comment xml:lang="hu">WordPerfect-dokumentum</comment>
+ <comment xml:lang="hr">WordPerfect dokument</comment>
+ <comment xml:lang="he">מסמך WordPerfect</comment>
+ <comment xml:lang="gl">documento de WordPerfect</comment>
+ <comment xml:lang="ga">cáipéis WordPerfect</comment>
+ <comment xml:lang="fur">document WordPerfect</comment>
+ <comment xml:lang="fr">document WordPerfect</comment>
+ <comment xml:lang="fo">WordPerfect skjal</comment>
+ <comment xml:lang="fi">WordPerfect-asiakirja</comment>
+ <comment xml:lang="eu">WordPerfect dokumentua</comment>
+ <comment xml:lang="es">documento de WordPerfect</comment>
+ <comment xml:lang="eo">WordPerfect-dokumento</comment>
+ <comment xml:lang="en_GB">WordPerfect document</comment>
+ <comment xml:lang="el">Έγγραφο WordPerfect</comment>
+ <comment xml:lang="de">WordPerfect-Dokument</comment>
+ <comment xml:lang="da">WordPerfect-dokument</comment>
+ <comment xml:lang="cy">Dogfen WordPerfect</comment>
+ <comment xml:lang="cs">dokument WordPerfect</comment>
+ <comment xml:lang="ca">document WordPerfect</comment>
+ <comment xml:lang="bg">Документ — WordPerfect</comment>
+ <comment xml:lang="be@latin">Dakument WordPerfect</comment>
+ <comment xml:lang="be">дакумент WordPerfect</comment>
+ <comment xml:lang="az">WordPerfect sənədi</comment>
+ <comment xml:lang="ast">Documentu de WordPerfect</comment>
+ <comment xml:lang="ar">مستند WordPerfect</comment>
+ <comment xml:lang="af">WordPerfect-dokument</comment>
<alias type="application/x-wordperfect"/>
<alias type="application/wordperfect"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="WPC" type="string" offset="1"/>
-
+ <magic>
+ <match type="string" value="WPC" offset="1"/>
+ <!-- <match type="big32" value="0xff575053c405" offset="0"/> -->
</magic>
<glob pattern="*.wp"/>
<glob pattern="*.wp4"/>
@@ -6830,283 +7254,332 @@
<glob pattern="*.wpd"/>
<glob pattern="*.wpp"/>
</mime-type>
- <mime-type type="application/vnd.youtube.yt">
- <comment>YouTube Media Archive</comment>
+ <mime-type type="video/vnd.youtube.yt">
+ <comment>YouTube media archive</comment>
+ <comment xml:lang="zh_CN">YouTube 媒体存档</comment>
+ <comment xml:lang="uk">мультимедійний архів YouTube</comment>
+ <comment xml:lang="tr">YouTube ortam arşivi</comment>
+ <comment xml:lang="sv">YouTube-mediaarkiv</comment>
+ <comment xml:lang="sq">arkiv media YouTube</comment>
+ <comment xml:lang="sl">Medijski arhiv YouTube</comment>
+ <comment xml:lang="si">YouTube මාධ්‍ය සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív médií YouTube</comment>
+ <comment xml:lang="ru">Медиа-архив YouTube</comment>
+ <comment xml:lang="pt_BR">Arquivo de mídia do Youtube</comment>
+ <comment xml:lang="pt">arquivo multimédia do YouTube</comment>
+ <comment xml:lang="pl">Archiwum multimediów YouTube</comment>
+ <comment xml:lang="oc">archiu mèdia YouTube</comment>
+ <comment xml:lang="nl">YouTube-media-archief</comment>
+ <comment xml:lang="ko">유튜브 미디어 저장 파일</comment>
+ <comment xml:lang="kk">YouTube медиа архиві</comment>
+ <comment xml:lang="ja">YouTube メディアアーカイブ</comment>
+ <comment xml:lang="it">Archivio multimediale YouTube</comment>
+ <comment xml:lang="is">YouTube margmiðlunarsafnskrá</comment>
+ <comment xml:lang="id">Arsip media YouTube</comment>
+ <comment xml:lang="hu">YouTube médiaarchívum</comment>
+ <comment xml:lang="hr">YouTube medijska arhiva</comment>
+ <comment xml:lang="he">ארכיון מדיה של YouTube</comment>
+ <comment xml:lang="gl">Arquivo multimedia de Youtube</comment>
+ <comment xml:lang="fr">archive média YouTube</comment>
+ <comment xml:lang="fi">YouTube-media-arkisto</comment>
+ <comment xml:lang="eu">YouTube media fitxategia</comment>
+ <comment xml:lang="es">archivador multimedia de YouTube</comment>
+ <comment xml:lang="en_GB">YouTube media archive</comment>
+ <comment xml:lang="de">YouTube-Medienarchiv</comment>
+ <comment xml:lang="da">YouTube-mediearkiv</comment>
+ <comment xml:lang="ca">arxiu de mitjans de YouTube</comment>
+ <comment xml:lang="bg">Медиен архив — YouTube</comment>
+ <comment xml:lang="be">архіў мультымедыя YouTube</comment>
+ <comment xml:lang="ar">أرشيف وسائط يوتيوب</comment>
+ <alias type="application/vnd.youtube.yt"/>
<generic-icon name="video-x-generic"/>
+ <magic>
+ <match type="string" value="ftypyt4 " offset="4"/>
+ </magic>
<glob pattern="*.yt"/>
<sub-class-of type="application/zip"/>
</mime-type>
<mime-type type="application/x-spss-por">
- <comment>SPSS Portable Data File</comment>
- <comment xml:lang="ar">ملف بيانات SPSS متنقلة</comment>
- <comment xml:lang="bg">Данни — SPSS, преносими</comment>
- <comment xml:lang="ca">fitxer de dades portables SPSS</comment>
- <comment xml:lang="cs">soubor přenositelných dat SPSS</comment>
- <comment xml:lang="da">Portabel SPSS-datafil</comment>
- <comment xml:lang="de">SPSS portable Datendatei</comment>
- <comment xml:lang="el">Φορητό αρχείο δεδομένων SPSS</comment>
- <comment xml:lang="en_GB">SPSS Portable Data File</comment>
- <comment xml:lang="es">archivo de datos portátil de SPSS</comment>
- <comment xml:lang="eu">SPSS datuen fitxategi eramangarria</comment>
- <comment xml:lang="fo">SPSS flytifør dátufíla</comment>
- <comment xml:lang="fr">fichier portable de données SPSS</comment>
- <comment xml:lang="ga">comhad iniompartha sonraí SPSS</comment>
- <comment xml:lang="gl">ficheiro de datos portábel SPSS</comment>
- <comment xml:lang="he">קובץ מידע נייד SPSS</comment>
- <comment xml:lang="hr">SPSS prenosiva podatkovna datoteka</comment>
- <comment xml:lang="hu">SPSS hordozható adatfájl</comment>
- <comment xml:lang="ia">File portabile de datos SPSS</comment>
- <comment xml:lang="id">Berkas Data Portabel SPSS</comment>
- <comment xml:lang="it">File dati SPSS Portable</comment>
- <comment xml:lang="ja">SPSS ポータブルデータファイル</comment>
- <comment xml:lang="kk">SPSS тасымалы ақпарат файлы</comment>
- <comment xml:lang="ko">SPSS 이동식 데이터 파일</comment>
- <comment xml:lang="lt">SPSS perkeliamų duomenų failas</comment>
- <comment xml:lang="lv">SPSS pārvietojamu datu datne</comment>
- <comment xml:lang="nl">SPSS Portable Databestand</comment>
- <comment xml:lang="oc">fichièr portable de donadas SPSS</comment>
- <comment xml:lang="pl">Plik przenośnych danych SPSS</comment>
- <comment xml:lang="pt">ficheiro de dados portátil SPSS</comment>
- <comment xml:lang="pt_BR">Arquivo de Dados Portáteis SPSS</comment>
- <comment xml:lang="ro">Fișier portabil de date SPSS</comment>
- <comment xml:lang="ru">Файл переносимых данных SPSS</comment>
- <comment xml:lang="sk">Súbor prenosných dát SPSS</comment>
- <comment xml:lang="sl">Prenosna podatkovna datoteka SPSS</comment>
- <comment xml:lang="sr">СПСС датотека преносних података</comment>
- <comment xml:lang="sv">Portabel SPSS-datafil</comment>
- <comment xml:lang="tr">SPSS Taşınabilir Veri Dosyası</comment>
- <comment xml:lang="uk">файл даних SPSS Portable</comment>
+ <comment>SPSS portable data file</comment>
+ <comment xml:lang="zh_TW">SPSS 可攜資料檔</comment>
<comment xml:lang="zh_CN">SPSS 便携式数据文件</comment>
- <comment xml:lang="zh_TW">SPSS 可攜式資料檔</comment>
- <magic priority="50">
- <match value="ASCII SPSS PORT FILE" type="string" offset="40"/>
+ <comment xml:lang="uk">портативний файл даних SPSS</comment>
+ <comment xml:lang="tr">SPSS taşınabilir veri dosyası</comment>
+ <comment xml:lang="sv">SPSS portabel datafil</comment>
+ <comment xml:lang="sq">kartelë të dhënash të bartshme SPSS</comment>
+ <comment xml:lang="sl">Prenosna podatkovna datoteka SPSS</comment>
+ <comment xml:lang="si">SPSS අතේ ගෙන යා හැකි දත්ත ගොනුව</comment>
+ <comment xml:lang="sk">Súbor prenosných údajov SPSS</comment>
+ <comment xml:lang="ru">Файл переносимых данных SPSS</comment>
+ <comment xml:lang="pt_BR">Arquivo de dados portáteis SPSS</comment>
+ <comment xml:lang="pt">ficheiro de dados portátil SPSS</comment>
+ <comment xml:lang="pl">Plik przenośnych danych SPSS</comment>
+ <comment xml:lang="nl">SPSS-portable-gegevensbestand</comment>
+ <comment xml:lang="ko">SPSS 휴대 데이터 파일</comment>
+ <comment xml:lang="kk">SPSS тасымалы деректер файлы</comment>
+ <comment xml:lang="ka">SPSS გადატანადი მონაცემების ფაილი</comment>
+ <comment xml:lang="ja">SPSS ポータブルデータファイル</comment>
+ <comment xml:lang="it">File dati SPSS Portable</comment>
+ <comment xml:lang="is">yfirfæranleg SPSS gagnaskrá</comment>
+ <comment xml:lang="id">Berkas data portabel SPSS</comment>
+ <comment xml:lang="hu">SPSS hordozható adatfájl</comment>
+ <comment xml:lang="hr">SPSS prenosiva podatkovna datoteka</comment>
+ <comment xml:lang="he">קובץ נתונים נייד של SPSS</comment>
+ <comment xml:lang="gl">Ficheiro de datos portábel de SPSS</comment>
+ <comment xml:lang="fr">fichier portable de données SPSS</comment>
+ <comment xml:lang="fi">Siirrettävä SPSS-tiedosto</comment>
+ <comment xml:lang="eu">SPSS datu fitxategi eramangarria</comment>
+ <comment xml:lang="es">archivo de datos portátiles de SPSS</comment>
+ <comment xml:lang="en_GB">SPSS portable data file</comment>
+ <comment xml:lang="de">Portierbare SPSS-Datendatei</comment>
+ <comment xml:lang="da">SPSS portable data-fil</comment>
+ <comment xml:lang="ca">fitxer de dades portables SPSS</comment>
+ <comment xml:lang="bg">Данни — SPSS, преносими</comment>
+ <comment xml:lang="be">файл пераносу даных SPSS</comment>
+ <comment xml:lang="ar">ملف بيانات SPSS متنقل</comment>
+ <acronym>SPSS</acronym>
+ <expanded-acronym>Statistical Package for the Social Sciences</expanded-acronym>
+ <magic>
+ <match type="string" offset="40" value="ASCII SPSS PORT FILE"/>
</magic>
<glob pattern="*.por"/>
</mime-type>
<mime-type type="application/x-spss-sav">
- <comment>SPSS Data File</comment>
- <comment xml:lang="ar">ملف بيانات SPSS</comment>
- <comment xml:lang="bg">Данни — SPSS</comment>
- <comment xml:lang="ca">fitxer de dades SPSS</comment>
- <comment xml:lang="cs">datový soubor SPSS</comment>
- <comment xml:lang="da">SPSS-datafil</comment>
- <comment xml:lang="de">SPSS-Datendatei</comment>
- <comment xml:lang="el">Αρχείο δεδομένων SPSS</comment>
- <comment xml:lang="en_GB">SPSS Data File</comment>
- <comment xml:lang="es">archivo de datos SPSS</comment>
- <comment xml:lang="eu">SPSS datuen fitxategia</comment>
- <comment xml:lang="fi">SPSS-datatiedosto</comment>
- <comment xml:lang="fo">SPSS dátufíla</comment>
- <comment xml:lang="fr">fichier de données SPSS</comment>
- <comment xml:lang="ga">comhad sonraí SPSS</comment>
- <comment xml:lang="gl">ficheiro de datos SPSS</comment>
- <comment xml:lang="he">קובץ מידע SPSS</comment>
- <comment xml:lang="hr">SPSS podatkovna datoteka</comment>
- <comment xml:lang="hu">SPSS adatfájl</comment>
- <comment xml:lang="ia">File de datos SPSS</comment>
- <comment xml:lang="id">Berkas Data SPSS</comment>
- <comment xml:lang="it">File dati SPSS</comment>
- <comment xml:lang="ja">SPSS データファイル</comment>
- <comment xml:lang="kk">SPSS ақпарат файлы</comment>
- <comment xml:lang="ko">SPSS 데이터 파일</comment>
- <comment xml:lang="lt">SPSS duomenų failas</comment>
- <comment xml:lang="lv">SPSS datu datne</comment>
- <comment xml:lang="nl">SPSS Databstand</comment>
- <comment xml:lang="oc">fichièr de donadas SPSS</comment>
- <comment xml:lang="pl">Plik danych SPSS</comment>
- <comment xml:lang="pt">ficheiro de dados SPSS</comment>
- <comment xml:lang="pt_BR">Arquivo de dados SPSS</comment>
- <comment xml:lang="ro">Fișier date SPSS</comment>
- <comment xml:lang="ru">Файл данных SPSS</comment>
- <comment xml:lang="sk">Dátový súbor SPSS</comment>
- <comment xml:lang="sl">Podatkovna datoteka SPSS</comment>
- <comment xml:lang="sr">СПСС датотека података</comment>
- <comment xml:lang="sv">SPSS-datafil</comment>
- <comment xml:lang="tr">SPSS Veri Dosyası</comment>
- <comment xml:lang="uk">файл даних SPSS</comment>
- <comment xml:lang="zh_CN">SPSS 数据文件</comment>
+ <comment>SPSS data file</comment>
<comment xml:lang="zh_TW">SPSS 資料檔</comment>
+ <comment xml:lang="zh_CN">SPSS 数据文件</comment>
+ <comment xml:lang="uk">файл даних SPSS</comment>
+ <comment xml:lang="tr">SPSS veri dosyası</comment>
+ <comment xml:lang="sv">SPSS-datafil</comment>
+ <comment xml:lang="sq">kartelë të dhënash SPSS</comment>
+ <comment xml:lang="sl">Podatkovna datoteka SPSS</comment>
+ <comment xml:lang="si">SPSS දත්ත ගොනුව</comment>
+ <comment xml:lang="sk">Súbor údajov SPSS</comment>
+ <comment xml:lang="ru">Файл данных SPSS</comment>
+ <comment xml:lang="pt_BR">Arquivo de dados SPSS</comment>
+ <comment xml:lang="pt">ficheiro de dados SPSS</comment>
+ <comment xml:lang="pl">Plik danych SPSS</comment>
+ <comment xml:lang="nl">SPSS-gegevensbestand</comment>
+ <comment xml:lang="ko">SPSS 데이터 파일</comment>
+ <comment xml:lang="kk">SPSS деректер файлы</comment>
+ <comment xml:lang="ja">SPSS データファイル</comment>
+ <comment xml:lang="it">File dati SPSS</comment>
+ <comment xml:lang="is">SPSS gagnaskrá</comment>
+ <comment xml:lang="id">Berkas data SPSS</comment>
+ <comment xml:lang="hu">SPSS adatfájl</comment>
+ <comment xml:lang="hr">SPSS podatkovna datoteka</comment>
+ <comment xml:lang="he">קובץ נתונים של SPSS</comment>
+ <comment xml:lang="gl">Ficheiro de datos SPSS</comment>
+ <comment xml:lang="fr">fichier de données SPSS</comment>
+ <comment xml:lang="fi">SPSS-datatiedosto</comment>
+ <comment xml:lang="eu">SPSS datu fitxategia</comment>
+ <comment xml:lang="es">archivo de datos de SPSS</comment>
+ <comment xml:lang="en_GB">SPSS data file</comment>
+ <comment xml:lang="de">SPSS-Datendatei</comment>
+ <comment xml:lang="da">SPSS data-fil</comment>
+ <comment xml:lang="ca">fitxer de dades SPSS</comment>
+ <comment xml:lang="bg">Данни — SPSS</comment>
+ <comment xml:lang="be">файл даных SPSS</comment>
+ <comment xml:lang="ar">ملف بيانات SPSS</comment>
+ <acronym>SPSS</acronym>
+ <expanded-acronym>Statistical Package for the Social Sciences</expanded-acronym>
<alias type="application/x-spss-savefile"/>
- <magic priority="50">
- <match value="$FL2" type="string" offset="0"/>
- <match value="$FL3" type="string" offset="0"/>
+ <magic>
+ <match type="string" offset="0" value="$FL2"/>
+ <match type="string" offset="0" value="$FL3"/>
</magic>
<glob pattern="*.sav"/>
<glob pattern="*.zsav"/>
</mime-type>
<mime-type type="application/x-xbel">
<comment>XBEL bookmarks</comment>
- <comment xml:lang="ar">علامات XBEL</comment>
- <comment xml:lang="be@latin">Zakładki XBEL</comment>
- <comment xml:lang="bg">Отметки — XBEL</comment>
- <comment xml:lang="ca">llista d'adreces d'interès XBEL</comment>
- <comment xml:lang="cs">záložky XBEL</comment>
- <comment xml:lang="da">XBEL-bogmærker</comment>
- <comment xml:lang="de">XBEL-Lesezeichen</comment>
- <comment xml:lang="el">Σελιδοδείκτες XBEL</comment>
- <comment xml:lang="en_GB">XBEL bookmarks</comment>
- <comment xml:lang="eo">XBEL-legosignoj</comment>
- <comment xml:lang="es">marcadores XBEL</comment>
- <comment xml:lang="eu">XBEL laster-markak</comment>
- <comment xml:lang="fi">XBEL-kirjanmerkit</comment>
- <comment xml:lang="fo">XBEL bókamerki</comment>
- <comment xml:lang="fr">marque-pages XBEL</comment>
- <comment xml:lang="ga">leabharmharcanna XBEL</comment>
- <comment xml:lang="gl">Marcadores XBEL</comment>
- <comment xml:lang="he">סימניית XBEL</comment>
- <comment xml:lang="hr">XBEL zabilješka</comment>
- <comment xml:lang="hu">XBEL-könyvjelzők</comment>
- <comment xml:lang="ia">Marcapaginas XBEL</comment>
- <comment xml:lang="id">Bookmark XBEL</comment>
- <comment xml:lang="it">Segnalibri XBEL</comment>
- <comment xml:lang="ja">XBEL ブックマーク</comment>
- <comment xml:lang="kk">XBEL бетбелгілері</comment>
- <comment xml:lang="ko">XBEL 책갈피</comment>
- <comment xml:lang="lt">XBEL žymelės</comment>
- <comment xml:lang="lv">XBEL grāmatzīmes</comment>
- <comment xml:lang="ms">Tandabuku XBEL</comment>
- <comment xml:lang="nb">XBEL-bokmerker</comment>
- <comment xml:lang="nl">XBEL-bladwijzers</comment>
- <comment xml:lang="nn">XBEL-bokmerker</comment>
- <comment xml:lang="oc">marcapaginas XBEL</comment>
- <comment xml:lang="pl">Zakładki XBEL</comment>
- <comment xml:lang="pt">marcadores XBEL</comment>
- <comment xml:lang="pt_BR">Marcadores do XBEL</comment>
- <comment xml:lang="ro">Semne de carte XBEL</comment>
- <comment xml:lang="ru">Закладки XBEL</comment>
- <comment xml:lang="sk">Záložky XBEL</comment>
- <comment xml:lang="sl">Datoteka zaznamkov XBEL</comment>
- <comment xml:lang="sq">Libërshënues XBEL</comment>
- <comment xml:lang="sr">ИксБЕЛ обележивачи</comment>
- <comment xml:lang="sv">XBEL-bokmärken</comment>
- <comment xml:lang="tr">XBEL yer imleri</comment>
- <comment xml:lang="uk">закладки XBEL</comment>
- <comment xml:lang="vi">Liên kết đã lưu XBEL</comment>
- <comment xml:lang="zh_CN">XBEL 书签</comment>
<comment xml:lang="zh_TW">XBEL 格式書籤</comment>
+ <comment xml:lang="zh_CN">XBEL 书签</comment>
+ <comment xml:lang="vi">Liên kết đã lưu XBEL</comment>
+ <comment xml:lang="uk">закладки XBEL</comment>
+ <comment xml:lang="tr">XBEL yer imleri</comment>
+ <comment xml:lang="sv">XBEL-bokmärken</comment>
+ <comment xml:lang="sr">ИксБЕЛ обележивачи</comment>
+ <comment xml:lang="sq">faqerojtës XBEL</comment>
+ <comment xml:lang="sl">Datoteka zaznamkov XBEL</comment>
+ <comment xml:lang="si">XBEL පිටුසන්</comment>
+ <comment xml:lang="sk">Záložky XBEL</comment>
+ <comment xml:lang="ru">Закладки XBEL</comment>
+ <comment xml:lang="ro">Semne de carte XBEL</comment>
+ <comment xml:lang="pt_BR">Marcadores do XBEL</comment>
+ <comment xml:lang="pt">marcadores XBEL</comment>
+ <comment xml:lang="pl">Zakładki XBEL</comment>
+ <comment xml:lang="oc">marcapaginas XBEL</comment>
+ <comment xml:lang="nn">XBEL-bokmerker</comment>
+ <comment xml:lang="nl">XBEL-bladwijzers</comment>
+ <comment xml:lang="nb">XBEL-bokmerker</comment>
+ <comment xml:lang="ms">Tandabuku XBEL</comment>
+ <comment xml:lang="lv">XBEL grāmatzīmes</comment>
+ <comment xml:lang="lt">XBEL žymelės</comment>
+ <comment xml:lang="ko">XBEL 책갈피</comment>
+ <comment xml:lang="kk">XBEL бетбелгілері</comment>
+ <comment xml:lang="ja">XBEL ブックマーク</comment>
+ <comment xml:lang="it">Segnalibri XBEL</comment>
+ <comment xml:lang="is">XBEL bókamerki</comment>
+ <comment xml:lang="id">Bookmark XBEL</comment>
+ <comment xml:lang="ia">Marcapaginas XBEL</comment>
+ <comment xml:lang="hu">XBEL-könyvjelzők</comment>
+ <comment xml:lang="hr">XBEL zabilješka</comment>
+ <comment xml:lang="he">סימניית XBEL</comment>
+ <comment xml:lang="gl">Marcadores XBEL</comment>
+ <comment xml:lang="ga">leabharmharcanna XBEL</comment>
+ <comment xml:lang="fur">segnelibris XBEL</comment>
+ <comment xml:lang="fr">marque-pages XBEL</comment>
+ <comment xml:lang="fo">XBEL bókamerki</comment>
+ <comment xml:lang="fi">XBEL-kirjanmerkit</comment>
+ <comment xml:lang="eu">XBEL laster-markak</comment>
+ <comment xml:lang="es">marcadores XBEL</comment>
+ <comment xml:lang="eo">XBEL-legosignoj</comment>
+ <comment xml:lang="en_GB">XBEL bookmarks</comment>
+ <comment xml:lang="el">Σελιδοδείκτες XBEL</comment>
+ <comment xml:lang="de">XBEL-Lesezeichen</comment>
+ <comment xml:lang="da">XBEL-bogmærker</comment>
+ <comment xml:lang="cs">záložky XBEL</comment>
+ <comment xml:lang="ca">llista d'adreces d'interès XBEL</comment>
+ <comment xml:lang="bg">Отметки — XBEL</comment>
+ <comment xml:lang="be@latin">Zakładki XBEL</comment>
+ <comment xml:lang="be">закладкі XBEL</comment>
+ <comment xml:lang="ar">علامات XBEL</comment>
+ <comment xml:lang="af">XBEL-boekmerke</comment>
<acronym>XBEL</acronym>
<expanded-acronym>XML Bookmark Exchange Language</expanded-acronym>
<sub-class-of type="application/xml"/>
<generic-icon name="text-html"/>
- <magic priority="50">
- <match value="&lt;!DOCTYPE\ xbel" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;!DOCTYPE\ xbel" offset="0:256"/>
</magic>
<glob pattern="*.xbel"/>
</mime-type>
<mime-type type="application/x-7z-compressed">
<comment>7-zip archive</comment>
- <comment xml:lang="ar">أرشيف 7-zip</comment>
- <comment xml:lang="ast">Archivu 7-zip</comment>
- <comment xml:lang="be@latin">Archiŭ 7-zip</comment>
- <comment xml:lang="bg">Архив — 7-zip</comment>
- <comment xml:lang="ca">arxiu 7-zip</comment>
- <comment xml:lang="cs">archiv 7-zip</comment>
- <comment xml:lang="da">7-zip-arkiv</comment>
- <comment xml:lang="de">7zip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο 7-zip</comment>
- <comment xml:lang="en_GB">7-zip archive</comment>
- <comment xml:lang="eo">7z-arkivo</comment>
- <comment xml:lang="es">archivador 7-zip</comment>
- <comment xml:lang="eu">7-zip artxiboa</comment>
- <comment xml:lang="fi">7-zip-arkisto</comment>
- <comment xml:lang="fo">7-zip skjalasavn</comment>
- <comment xml:lang="fr">archive 7-zip</comment>
- <comment xml:lang="ga">cartlann 7-zip</comment>
- <comment xml:lang="gl">arquivo 7-zip</comment>
- <comment xml:lang="he">ארכיון 7-zip</comment>
- <comment xml:lang="hr">7-zip arhiva</comment>
- <comment xml:lang="hu">7-zip archívum</comment>
- <comment xml:lang="ia">Archivo 7-zip</comment>
- <comment xml:lang="id">Arsip 7-zip</comment>
- <comment xml:lang="it">Archivio 7-zip</comment>
- <comment xml:lang="ja">7-zip アーカイブ</comment>
- <comment xml:lang="ka">7-zip არქივი</comment>
- <comment xml:lang="kk">7-zip архиві</comment>
- <comment xml:lang="ko">7-ZIP 압축 파일</comment>
- <comment xml:lang="lt">7-zip archyvas</comment>
- <comment xml:lang="lv">7-zip arhīvs</comment>
- <comment xml:lang="nb">7-zip-arkiv</comment>
- <comment xml:lang="nl">7-zip-archief</comment>
- <comment xml:lang="nn">7-zip-arkiv</comment>
- <comment xml:lang="oc">archiu 7-zip</comment>
- <comment xml:lang="pl">Archiwum 7-zip</comment>
- <comment xml:lang="pt">arquivo 7-zip</comment>
- <comment xml:lang="pt_BR">Pacote 7-Zip</comment>
- <comment xml:lang="ro">Arhivă 7-zip</comment>
- <comment xml:lang="ru">Архив 7-zip</comment>
- <comment xml:lang="sk">Archív 7-zip</comment>
- <comment xml:lang="sl">Datoteka arhiva 7-zip</comment>
- <comment xml:lang="sq">Arkiv 7-zip</comment>
- <comment xml:lang="sr">7-зип архива</comment>
- <comment xml:lang="sv">7-zip-arkiv</comment>
- <comment xml:lang="tr">7-Zip arşivi</comment>
- <comment xml:lang="uk">архів 7-zip</comment>
- <comment xml:lang="vi">Kho nén 7-zip</comment>
- <comment xml:lang="zh_CN">7-zip 归档文件</comment>
<comment xml:lang="zh_TW">7-zip 封存檔</comment>
+ <comment xml:lang="zh_CN">7-zip 归档文件</comment>
+ <comment xml:lang="vi">Kho nén 7-zip</comment>
+ <comment xml:lang="uk">архів 7-zip</comment>
+ <comment xml:lang="tr">7-Zip arşivi</comment>
+ <comment xml:lang="sv">7-zip-arkiv</comment>
+ <comment xml:lang="sr">7-зип архива</comment>
+ <comment xml:lang="sq">arkiv 7-zip</comment>
+ <comment xml:lang="sl">Datoteka arhiva 7-zip</comment>
+ <comment xml:lang="si">7-zip සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív 7-zip</comment>
+ <comment xml:lang="ru">Архив 7-zip</comment>
+ <comment xml:lang="ro">Arhivă 7-zip</comment>
+ <comment xml:lang="pt_BR">Pacote 7-Zip</comment>
+ <comment xml:lang="pt">arquivo 7-zip</comment>
+ <comment xml:lang="pl">Archiwum 7-zip</comment>
+ <comment xml:lang="oc">archiu 7-zip</comment>
+ <comment xml:lang="nn">7-zip-arkiv</comment>
+ <comment xml:lang="nl">7-zip-archief</comment>
+ <comment xml:lang="nb">7-zip-arkiv</comment>
+ <comment xml:lang="lv">7-zip arhīvs</comment>
+ <comment xml:lang="lt">7-zip archyvas</comment>
+ <comment xml:lang="ko">7-ZIP 압축 파일</comment>
+ <comment xml:lang="kk">7-zip архиві</comment>
+ <comment xml:lang="ka">7-zip არქივი</comment>
+ <comment xml:lang="ja">7-zip アーカイブ</comment>
+ <comment xml:lang="it">Archivio 7-zip</comment>
+ <comment xml:lang="is">7-zip safnskrá</comment>
+ <comment xml:lang="id">Arsip 7-zip</comment>
+ <comment xml:lang="ia">Archivo 7-zip</comment>
+ <comment xml:lang="hu">7-zip archívum</comment>
+ <comment xml:lang="hr">7-zip arhiva</comment>
+ <comment xml:lang="he">ארכיון 7-zip</comment>
+ <comment xml:lang="gl">arquivo 7-zip</comment>
+ <comment xml:lang="ga">cartlann 7-zip</comment>
+ <comment xml:lang="fur">archivi 7-zip</comment>
+ <comment xml:lang="fr">archive 7-zip</comment>
+ <comment xml:lang="fo">7-zip skjalasavn</comment>
+ <comment xml:lang="fi">7-zip-arkisto</comment>
+ <comment xml:lang="eu">7-zip artxiboa</comment>
+ <comment xml:lang="es">archivador 7-zip</comment>
+ <comment xml:lang="eo">7z-arkivo</comment>
+ <comment xml:lang="en_GB">7-zip archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο 7-zip</comment>
+ <comment xml:lang="de">7-Zip-Archiv</comment>
+ <comment xml:lang="da">7-zip-arkiv</comment>
+ <comment xml:lang="cs">archiv 7-zip</comment>
+ <comment xml:lang="ca">arxiu 7-zip</comment>
+ <comment xml:lang="bg">Архив — 7-zip</comment>
+ <comment xml:lang="be@latin">Archiŭ 7-zip</comment>
+ <comment xml:lang="be">архіў 7-zip</comment>
+ <comment xml:lang="ast">Archivu 7-zip</comment>
+ <comment xml:lang="ar">أرشيف 7-zip</comment>
+ <comment xml:lang="af">7-zip-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="7z\274\257\047\034" type="string" offset="0"/>
+ <match type="string" value="7z\274\257\047\034" offset="0"/>
</magic>
<glob pattern="*.7z"/>
+ <glob pattern="*.7z.001"/>
</mime-type>
<mime-type type="application/x-abiword">
<comment>AbiWord document</comment>
- <comment xml:lang="ar">مستند آبي وورد</comment>
- <comment xml:lang="ast">Documentu d'AbiWord</comment>
- <comment xml:lang="be@latin">Dakument AbiWord</comment>
- <comment xml:lang="bg">Документ — AbiWord</comment>
- <comment xml:lang="ca">document AbiWord</comment>
- <comment xml:lang="cs">dokument AbiWord</comment>
- <comment xml:lang="da">AbiWord-dokument</comment>
- <comment xml:lang="de">AbiWord-Dokument</comment>
- <comment xml:lang="el">Έγγραφο AbiWord</comment>
- <comment xml:lang="en_GB">AbiWord document</comment>
- <comment xml:lang="eo">AbiWord-dokumento</comment>
- <comment xml:lang="es">documento de Abiword</comment>
- <comment xml:lang="eu">AbiWord dokumentua</comment>
- <comment xml:lang="fi">AbiWord-asiakirja</comment>
- <comment xml:lang="fo">AbiWord skjal</comment>
- <comment xml:lang="fr">document AbiWord</comment>
- <comment xml:lang="ga">cáipéis AbiWord</comment>
- <comment xml:lang="gl">documento de AbiWord</comment>
- <comment xml:lang="he">מסמך AbiWord</comment>
- <comment xml:lang="hr">AbiWord dokument</comment>
- <comment xml:lang="hu">AbiWord-dokumentum</comment>
- <comment xml:lang="ia">Documento AbiWord</comment>
- <comment xml:lang="id">Dokumen AbiWord</comment>
- <comment xml:lang="it">Documento AbiWord</comment>
- <comment xml:lang="ja">AbiWord ドキュメント</comment>
- <comment xml:lang="ka">AbiWord-ის დოკუმენტი</comment>
- <comment xml:lang="kk">AbiWord құжаты</comment>
- <comment xml:lang="ko">AbiWord 문서</comment>
- <comment xml:lang="lt">AbiWord dokumentas</comment>
- <comment xml:lang="lv">AbiWord dokuments</comment>
- <comment xml:lang="ms">Dokumen AbiWord</comment>
- <comment xml:lang="nb">AbiWord-dokument</comment>
- <comment xml:lang="nl">AbiWord-document</comment>
- <comment xml:lang="nn">AbiWord-dokument</comment>
- <comment xml:lang="oc">document AbiWord</comment>
- <comment xml:lang="pl">Dokument AbiWord</comment>
- <comment xml:lang="pt">documento AbiWord</comment>
- <comment xml:lang="pt_BR">Documento do AbiWord</comment>
- <comment xml:lang="ro">Document AbiWord</comment>
- <comment xml:lang="ru">Документ AbiWord</comment>
- <comment xml:lang="sk">Dokument AbiWord</comment>
- <comment xml:lang="sl">Dokument AbiWord</comment>
- <comment xml:lang="sq">Dokument AbiWord</comment>
- <comment xml:lang="sr">Абиворд документ</comment>
- <comment xml:lang="sv">AbiWord-dokument</comment>
- <comment xml:lang="tr">AbiWord belgesi</comment>
- <comment xml:lang="uk">документ AbiWord</comment>
- <comment xml:lang="vi">Tài liệu AbiWord</comment>
- <comment xml:lang="zh_CN">AbiWord 文档</comment>
<comment xml:lang="zh_TW">AbiWord 文件</comment>
+ <comment xml:lang="zh_CN">AbiWord 文档</comment>
+ <comment xml:lang="vi">Tài liệu AbiWord</comment>
+ <comment xml:lang="uk">документ AbiWord</comment>
+ <comment xml:lang="tr">AbiWord belgesi</comment>
+ <comment xml:lang="sv">AbiWord-dokument</comment>
+ <comment xml:lang="sr">Абиворд документ</comment>
+ <comment xml:lang="sq">dokument AbiWord</comment>
+ <comment xml:lang="sl">Dokument AbiWord</comment>
+ <comment xml:lang="si">AbiWord ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument AbiWord</comment>
+ <comment xml:lang="ru">Документ AbiWord</comment>
+ <comment xml:lang="ro">Document AbiWord</comment>
+ <comment xml:lang="pt_BR">Documento do AbiWord</comment>
+ <comment xml:lang="pt">documento AbiWord</comment>
+ <comment xml:lang="pl">Dokument AbiWord</comment>
+ <comment xml:lang="oc">document AbiWord</comment>
+ <comment xml:lang="nn">AbiWord-dokument</comment>
+ <comment xml:lang="nl">AbiWord-document</comment>
+ <comment xml:lang="nb">AbiWord-dokument</comment>
+ <comment xml:lang="ms">Dokumen AbiWord</comment>
+ <comment xml:lang="lv">AbiWord dokuments</comment>
+ <comment xml:lang="lt">AbiWord dokumentas</comment>
+ <comment xml:lang="ko">AbiWord 문서</comment>
+ <comment xml:lang="kk">AbiWord құжаты</comment>
+ <comment xml:lang="ka">AbiWord-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">AbiWord ドキュメント</comment>
+ <comment xml:lang="it">Documento AbiWord</comment>
+ <comment xml:lang="is">AbiWord skjal</comment>
+ <comment xml:lang="id">Dokumen AbiWord</comment>
+ <comment xml:lang="ia">Documento AbiWord</comment>
+ <comment xml:lang="hu">AbiWord-dokumentum</comment>
+ <comment xml:lang="hr">AbiWord dokument</comment>
+ <comment xml:lang="he">מסמך AbiWord</comment>
+ <comment xml:lang="gl">documento de AbiWord</comment>
+ <comment xml:lang="ga">cáipéis AbiWord</comment>
+ <comment xml:lang="fur">document AbiWord</comment>
+ <comment xml:lang="fr">document AbiWord</comment>
+ <comment xml:lang="fo">AbiWord skjal</comment>
+ <comment xml:lang="fi">AbiWord-asiakirja</comment>
+ <comment xml:lang="eu">AbiWord dokumentua</comment>
+ <comment xml:lang="es">documento de AbiWord</comment>
+ <comment xml:lang="eo">AbiWord-dokumento</comment>
+ <comment xml:lang="en_GB">AbiWord document</comment>
+ <comment xml:lang="el">Έγγραφο AbiWord</comment>
+ <comment xml:lang="de">AbiWord-Dokument</comment>
+ <comment xml:lang="da">AbiWord-dokument</comment>
+ <comment xml:lang="cs">dokument AbiWord</comment>
+ <comment xml:lang="ca">document AbiWord</comment>
+ <comment xml:lang="bg">Документ — AbiWord</comment>
+ <comment xml:lang="be@latin">Dakument AbiWord</comment>
+ <comment xml:lang="be">дакумент AbiWord</comment>
+ <comment xml:lang="ast">Documentu d'AbiWord</comment>
+ <comment xml:lang="ar">مستند آبي وورد</comment>
+ <comment xml:lang="af">AbiWord-dokument</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="&lt;abiword" type="string" offset="0:256"/>
- <match value="&lt;!DOCTYPE abiword" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;abiword" offset="0:256"/>
+ <match type="string" value="&lt;!DOCTYPE abiword" offset="0:256"/>
</magic>
<glob pattern="*.abw"/>
<glob pattern="*.abw.CRASHED"/>
@@ -7116,520 +7589,614 @@
</mime-type>
<mime-type type="application/x-cue">
<comment>CD image cuesheet</comment>
- <comment xml:lang="ar">صفيحة صورة الـCD جديلة</comment>
- <comment xml:lang="be@latin">Infarmacyjny arkuš vyjavy CD</comment>
- <comment xml:lang="bg">Описание на изображение на CD</comment>
- <comment xml:lang="ca">«cuesheet» d'imatge de CD</comment>
- <comment xml:lang="cs">rozvržení stop obrazu CD</comment>
- <comment xml:lang="da">Cd-aftrykscuesheet</comment>
- <comment xml:lang="de">CD-Abbild-Cuesheet</comment>
- <comment xml:lang="el">Φύλλο cue εικόνας CD</comment>
- <comment xml:lang="en_GB">CD image cuesheet</comment>
- <comment xml:lang="es">hoja CUE de imagen de CD</comment>
- <comment xml:lang="eu">CD irudiaren CUE orria</comment>
- <comment xml:lang="fi">CD-vedos cuesheet</comment>
- <comment xml:lang="fr">index de pistes de CD</comment>
- <comment xml:lang="ga">bileog chiúála íomhá CD</comment>
- <comment xml:lang="gl">cue sheet dunha imaxe de CD</comment>
- <comment xml:lang="he">גליון נתונים לתמונת דיסק</comment>
- <comment xml:lang="hr">CD slika s meta podacima</comment>
- <comment xml:lang="hu">CD kép cuesheet</comment>
- <comment xml:lang="ia">Indice de pistas de CD</comment>
- <comment xml:lang="id">Citra cuesheet CD</comment>
- <comment xml:lang="it">Cuesheet immagine CD</comment>
- <comment xml:lang="ja">CD イメージキューシート</comment>
- <comment xml:lang="kk">CD бейнесінің құрама кестесі</comment>
- <comment xml:lang="ko">CD 이미지 큐시트</comment>
- <comment xml:lang="lt">CD atvaizdžio aprašas</comment>
- <comment xml:lang="lv">CD attēla rindulapa</comment>
- <comment xml:lang="nb">Filliste for CD-avtrykk</comment>
- <comment xml:lang="nl">CD-inhoudsopgave</comment>
- <comment xml:lang="nn">CD-bilete-indeksfil</comment>
- <comment xml:lang="oc">indèx de pistas de CD</comment>
- <comment xml:lang="pl">Obraz cuesheet płyty CD</comment>
- <comment xml:lang="pt">índice de CD de imagem</comment>
- <comment xml:lang="pt_BR">Índice de Imagem de CD</comment>
- <comment xml:lang="ro">Imagine CD cuesheet</comment>
- <comment xml:lang="ru">Таблица содержания образа CD</comment>
- <comment xml:lang="sk">Rozvrhnutie stôp obrazu CD</comment>
- <comment xml:lang="sl">Datoteka razpredelnice odtisa CD cue</comment>
- <comment xml:lang="sq">Cuesheet imazhi CD</comment>
- <comment xml:lang="sr">Кју лист ЦД одраза</comment>
- <comment xml:lang="sv">Indexblad för cd-avbild</comment>
- <comment xml:lang="tr">CD görüntüsü belgesi</comment>
- <comment xml:lang="uk">таблиця CUE образу CD</comment>
- <comment xml:lang="vi">Tờ tín hiệu báo ảnh CD</comment>
- <comment xml:lang="zh_CN">CD 映像标记文件</comment>
<comment xml:lang="zh_TW">CD 映像指示表</comment>
+ <comment xml:lang="zh_CN">CD 映像标记文件</comment>
+ <comment xml:lang="vi">Tờ tín hiệu báo ảnh CD</comment>
+ <comment xml:lang="uk">таблиця CUE образу CD</comment>
+ <comment xml:lang="tr">CD görüntüsü çizelgesi</comment>
+ <comment xml:lang="sv">Indexblad för cd-avbild</comment>
+ <comment xml:lang="sr">Кју лист ЦД одраза</comment>
+ <comment xml:lang="sl">Datoteka razpredelnice odtisa CD cue</comment>
+ <comment xml:lang="si">සීඩී රූප කුට්ටිය</comment>
+ <comment xml:lang="sk">Rozvrhnutie stôp obrazu CD</comment>
+ <comment xml:lang="ru">Таблица содержания образа CD</comment>
+ <comment xml:lang="ro">Imagine CD cuesheet</comment>
+ <comment xml:lang="pt_BR">Índice de Imagem de CD</comment>
+ <comment xml:lang="pt">índice de imagem do CD</comment>
+ <comment xml:lang="pl">Obraz cuesheet płyty CD</comment>
+ <comment xml:lang="oc">indèx de pistas de CD</comment>
+ <comment xml:lang="nn">CD-bilete-indeksfil</comment>
+ <comment xml:lang="nl">CD-inhoudsopgave</comment>
+ <comment xml:lang="nb">Filliste for CD-avtrykk</comment>
+ <comment xml:lang="lv">CD attēla rindulapa</comment>
+ <comment xml:lang="lt">CD atvaizdžio aprašas</comment>
+ <comment xml:lang="ko">CD 이미지 큐시트</comment>
+ <comment xml:lang="kk">CD бейнесінің құрама кестесі</comment>
+ <comment xml:lang="ja">CD イメージキューシート</comment>
+ <comment xml:lang="it">Cuesheet immagine CD</comment>
+ <comment xml:lang="is">cuesheet CD diskmyndar</comment>
+ <comment xml:lang="id">Citra cuesheet CD</comment>
+ <comment xml:lang="ia">Indice de pistas de CD</comment>
+ <comment xml:lang="hu">CD lemezkép-jelölőlap</comment>
+ <comment xml:lang="hr">CD slika s meta podacima</comment>
+ <comment xml:lang="he">גיליון נתונים לדמות תקליטור</comment>
+ <comment xml:lang="gl">cue sheet dunha imaxe de CD</comment>
+ <comment xml:lang="ga">bileog chiúála íomhá CD</comment>
+ <comment xml:lang="fur">sfuei-brivade CUE de imagjin CD</comment>
+ <comment xml:lang="fr">index de pistes de CD</comment>
+ <comment xml:lang="fi">CD-levykuvan taulukko</comment>
+ <comment xml:lang="eu">CD irudiaren CUE orria</comment>
+ <comment xml:lang="es">hoja CUE de imagen de CD</comment>
+ <comment xml:lang="en_GB">CD image cuesheet</comment>
+ <comment xml:lang="el">Φύλλο cue εικόνας CD</comment>
+ <comment xml:lang="de">CD-Abbild-Cuesheet</comment>
+ <comment xml:lang="da">Cd-aftrykscuesheet</comment>
+ <comment xml:lang="cs">rozvržení stop obrazu CD</comment>
+ <comment xml:lang="ca">«cuesheet» d'imatge de CD</comment>
+ <comment xml:lang="bg">Съдържание на CD</comment>
+ <comment xml:lang="be@latin">Infarmacyjny arkuš vyjavy CD</comment>
+ <comment xml:lang="be">табліца разметкі вобраза CD</comment>
+ <comment xml:lang="ar">صفيحة صورة CD جديلة</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<glob pattern="*.cue"/>
</mime-type>
<mime-type type="application/x-amipro">
<comment>Lotus AmiPro document</comment>
- <comment xml:lang="ar">مستند Lotus AmiPro</comment>
- <comment xml:lang="ast">Documentu de Lotus AmiPro</comment>
- <comment xml:lang="az">Lotus AmiPro sənədi</comment>
- <comment xml:lang="be@latin">Dakument Lotus AmiPro</comment>
- <comment xml:lang="bg">Документ — Lotus AmiPro</comment>
- <comment xml:lang="ca">document de Lotus AmiPro</comment>
- <comment xml:lang="cs">dokument Lotus AmiPro</comment>
- <comment xml:lang="cy">Dogfen Lotus AmiPro</comment>
- <comment xml:lang="da">Lotus AmiPro-dokument</comment>
- <comment xml:lang="de">Lotus-AmiPro-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Lotus AmiPro</comment>
- <comment xml:lang="en_GB">Lotus AmiPro document</comment>
- <comment xml:lang="eo">dokumento de Lotus AmiPro</comment>
- <comment xml:lang="es">documento de Lotus AmiPro</comment>
- <comment xml:lang="eu">Lotus AmiPro dokumentua</comment>
- <comment xml:lang="fi">Lotus AmiPro -asiakirja</comment>
- <comment xml:lang="fo">Lotus AmiPro skjal</comment>
- <comment xml:lang="fr">document Lotus AmiPro</comment>
- <comment xml:lang="ga">cáipéis Lotus AmiPro</comment>
- <comment xml:lang="gl">documento de Lotus AmiPro</comment>
- <comment xml:lang="he">מסמך של Lotus AmiPro</comment>
- <comment xml:lang="hr">Lotus AmiPro dokument</comment>
- <comment xml:lang="hu">Lotus AmiPro-dokumentum</comment>
- <comment xml:lang="ia">Documento Lotus AmiPro</comment>
- <comment xml:lang="id">Dokumen Lotus AmiPro</comment>
- <comment xml:lang="it">Documento Lotus AmiPro</comment>
- <comment xml:lang="ja">Lotus AmiPro ドキュメント</comment>
- <comment xml:lang="kk">Lotus AmiPro құжаты</comment>
- <comment xml:lang="ko">Lotus AmiPro 문서</comment>
- <comment xml:lang="lt">Lotus AmiPro dokumentas</comment>
- <comment xml:lang="lv">Lotus AmiPro dokuments</comment>
- <comment xml:lang="ms">Dokumen Lotus AmiPro</comment>
- <comment xml:lang="nb">Lotus AmiPro-dokument</comment>
- <comment xml:lang="nl">Lotus AmiPro-document</comment>
- <comment xml:lang="nn">Lotus AmiPro-dokument</comment>
- <comment xml:lang="oc">document Lotus AmiPro</comment>
- <comment xml:lang="pl">Dokument Lotus AmiPro</comment>
- <comment xml:lang="pt">documento Lotus AmiPro</comment>
- <comment xml:lang="pt_BR">Documento do Lotus AmiPro</comment>
- <comment xml:lang="ro">Document Lotus AmiPro</comment>
- <comment xml:lang="ru">Документ Lotus AmiPro</comment>
- <comment xml:lang="sk">Dokument Lotus AmiPro</comment>
- <comment xml:lang="sl">Dokument Lotus AmiPro</comment>
- <comment xml:lang="sq">Dokument Lotus AmiPro</comment>
- <comment xml:lang="sr">Лотусов Ами Про документ</comment>
- <comment xml:lang="sv">Lotus AmiPro-dokument</comment>
- <comment xml:lang="tr">Lotus AmiPro belgesi</comment>
- <comment xml:lang="uk">документ Lotus AmiPro</comment>
- <comment xml:lang="vi">Tài liệu Lotus AmiPro</comment>
- <comment xml:lang="zh_CN">Lotus AmiPro 文档</comment>
<comment xml:lang="zh_TW">Lotus AmiPro 文件</comment>
+ <comment xml:lang="zh_CN">Lotus AmiPro 文档</comment>
+ <comment xml:lang="vi">Tài liệu Lotus AmiPro</comment>
+ <comment xml:lang="uk">документ Lotus AmiPro</comment>
+ <comment xml:lang="tr">Lotus AmiPro belgesi</comment>
+ <comment xml:lang="sv">Lotus AmiPro-dokument</comment>
+ <comment xml:lang="sr">Лотусов Ами Про документ</comment>
+ <comment xml:lang="sq">dokument Lotus AmiPro</comment>
+ <comment xml:lang="sl">Dokument Lotus AmiPro</comment>
+ <comment xml:lang="si">Lotus AmiPro ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Lotus AmiPro</comment>
+ <comment xml:lang="ru">Документ Lotus AmiPro</comment>
+ <comment xml:lang="ro">Document Lotus AmiPro</comment>
+ <comment xml:lang="pt_BR">Documento do Lotus AmiPro</comment>
+ <comment xml:lang="pt">documento Lotus AmiPro</comment>
+ <comment xml:lang="pl">Dokument Lotus AmiPro</comment>
+ <comment xml:lang="oc">document Lotus AmiPro</comment>
+ <comment xml:lang="nn">Lotus AmiPro-dokument</comment>
+ <comment xml:lang="nl">Lotus AmiPro-document</comment>
+ <comment xml:lang="nb">Lotus AmiPro-dokument</comment>
+ <comment xml:lang="ms">Dokumen Lotus AmiPro</comment>
+ <comment xml:lang="lv">Lotus AmiPro dokuments</comment>
+ <comment xml:lang="lt">Lotus AmiPro dokumentas</comment>
+ <comment xml:lang="ko">Lotus AmiPro 문서</comment>
+ <comment xml:lang="kk">Lotus AmiPro құжаты</comment>
+ <comment xml:lang="ja">Lotus AmiPro ドキュメント</comment>
+ <comment xml:lang="it">Documento Lotus AmiPro</comment>
+ <comment xml:lang="is">Lotus AmiPro skjal</comment>
+ <comment xml:lang="id">Dokumen Lotus AmiPro</comment>
+ <comment xml:lang="ia">Documento Lotus AmiPro</comment>
+ <comment xml:lang="hu">Lotus AmiPro-dokumentum</comment>
+ <comment xml:lang="hr">Lotus AmiPro dokument</comment>
+ <comment xml:lang="he">מסמך של Lotus AmiPro</comment>
+ <comment xml:lang="gl">documento de Lotus AmiPro</comment>
+ <comment xml:lang="ga">cáipéis Lotus AmiPro</comment>
+ <comment xml:lang="fur">document Lotus AmiPro</comment>
+ <comment xml:lang="fr">document Lotus AmiPro</comment>
+ <comment xml:lang="fo">Lotus AmiPro skjal</comment>
+ <comment xml:lang="fi">Lotus AmiPro -asiakirja</comment>
+ <comment xml:lang="eu">Lotus AmiPro dokumentua</comment>
+ <comment xml:lang="es">documento de Lotus AmiPro</comment>
+ <comment xml:lang="eo">dokumento de Lotus AmiPro</comment>
+ <comment xml:lang="en_GB">Lotus AmiPro document</comment>
+ <comment xml:lang="el">Έγγραφο Lotus AmiPro</comment>
+ <comment xml:lang="de">Lotus-AmiPro-Dokument</comment>
+ <comment xml:lang="da">Lotus AmiPro-dokument</comment>
+ <comment xml:lang="cy">Dogfen Lotus AmiPro</comment>
+ <comment xml:lang="cs">dokument Lotus AmiPro</comment>
+ <comment xml:lang="ca">document de Lotus AmiPro</comment>
+ <comment xml:lang="bg">Документ — Lotus AmiPro</comment>
+ <comment xml:lang="be@latin">Dakument Lotus AmiPro</comment>
+ <comment xml:lang="be">дакумент Lotus AmiPro</comment>
+ <comment xml:lang="az">Lotus AmiPro sənədi</comment>
+ <comment xml:lang="ast">Documentu de Lotus AmiPro</comment>
+ <comment xml:lang="ar">مستند Lotus AmiPro</comment>
+ <comment xml:lang="af">Lotus AmiPro-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.sam"/>
</mime-type>
<mime-type type="application/x-aportisdoc">
<comment>AportisDoc document</comment>
- <comment xml:lang="ar">مستند AportisDoc</comment>
- <comment xml:lang="ast">Documentu d'AportisDoc</comment>
- <comment xml:lang="bg">Документ — AportisDoc</comment>
- <comment xml:lang="ca">document AportisDoc</comment>
- <comment xml:lang="cs">dokument AportisDoc</comment>
- <comment xml:lang="da">AportisDoc-dokument</comment>
- <comment xml:lang="de">AportisDoc-Dokument</comment>
- <comment xml:lang="el">Έγγραφο AportisDoc</comment>
- <comment xml:lang="en_GB">AportisDoc document</comment>
- <comment xml:lang="eo">AportisDoc-dokumento</comment>
- <comment xml:lang="es">documento de AportisDoc</comment>
- <comment xml:lang="eu">AportisDoc dokumentua</comment>
- <comment xml:lang="fi">AportisDoc-asiakirja</comment>
- <comment xml:lang="fo">AportisDoc skjal</comment>
- <comment xml:lang="fr">document AportisDoc</comment>
- <comment xml:lang="ga">cáipéis AportisDoc</comment>
- <comment xml:lang="gl">documento de AportiDoc</comment>
- <comment xml:lang="he">מסמך AportisDoc</comment>
- <comment xml:lang="hr">AportisDoc dokument</comment>
- <comment xml:lang="hu">AportisDoc-dokumentum</comment>
- <comment xml:lang="ia">Documento AportisDoc</comment>
- <comment xml:lang="id">Dokumen AportisDoc</comment>
- <comment xml:lang="it">Documento AportisDoc</comment>
- <comment xml:lang="ja">AportisDoc ドキュメント</comment>
- <comment xml:lang="ka">AportisDoc-ის დოკუმენტი</comment>
- <comment xml:lang="kk">AportisDoc құжаты</comment>
- <comment xml:lang="ko">AportisDoc 문서</comment>
- <comment xml:lang="lt">AportisDoc dokumentas</comment>
- <comment xml:lang="lv">AportisDoc dokuments</comment>
- <comment xml:lang="nl">AportisDoc-document</comment>
- <comment xml:lang="oc">document AportisDoc</comment>
- <comment xml:lang="pl">Dokument AportisDoc</comment>
- <comment xml:lang="pt">documento AportisDoc</comment>
- <comment xml:lang="pt_BR">Documento do AportisDoc</comment>
- <comment xml:lang="ro">Document AportisDoc</comment>
- <comment xml:lang="ru">Документ AportisDoc</comment>
- <comment xml:lang="sk">Dokument AportisDoc</comment>
- <comment xml:lang="sl">Dokument AportisDoc</comment>
- <comment xml:lang="sr">Апортис Док документ</comment>
- <comment xml:lang="sv">AportisDoc-dokument</comment>
- <comment xml:lang="tr">AportisDoc belgesi</comment>
- <comment xml:lang="uk">документ AportisDoc</comment>
- <comment xml:lang="vi">Tài liệu AportisDoc</comment>
- <comment xml:lang="zh_CN">AportisDoc 文档</comment>
<comment xml:lang="zh_TW">AportisDoc 文件</comment>
+ <comment xml:lang="zh_CN">AportisDoc 文档</comment>
+ <comment xml:lang="vi">Tài liệu AportisDoc</comment>
+ <comment xml:lang="uk">документ AportisDoc</comment>
+ <comment xml:lang="tr">AportisDoc belgesi</comment>
+ <comment xml:lang="sv">AportisDoc-dokument</comment>
+ <comment xml:lang="sr">Апортис Док документ</comment>
+ <comment xml:lang="sq">dokument AportisDoc</comment>
+ <comment xml:lang="sl">Dokument AportisDoc</comment>
+ <comment xml:lang="si">AportisDoc ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument AportisDoc</comment>
+ <comment xml:lang="ru">Документ AportisDoc</comment>
+ <comment xml:lang="ro">Document AportisDoc</comment>
+ <comment xml:lang="pt_BR">Documento do AportisDoc</comment>
+ <comment xml:lang="pt">documento AportisDoc</comment>
+ <comment xml:lang="pl">Dokument AportisDoc</comment>
+ <comment xml:lang="oc">document AportisDoc</comment>
+ <comment xml:lang="nl">AportisDoc-document</comment>
+ <comment xml:lang="lv">AportisDoc dokuments</comment>
+ <comment xml:lang="lt">AportisDoc dokumentas</comment>
+ <comment xml:lang="ko">AportisDoc 문서</comment>
+ <comment xml:lang="kk">AportisDoc құжаты</comment>
+ <comment xml:lang="ka">AportisDoc-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">AportisDoc ドキュメント</comment>
+ <comment xml:lang="it">Documento AportisDoc</comment>
+ <comment xml:lang="is">AportisDoc skjal</comment>
+ <comment xml:lang="id">Dokumen AportisDoc</comment>
+ <comment xml:lang="ia">Documento AportisDoc</comment>
+ <comment xml:lang="hu">AportisDoc-dokumentum</comment>
+ <comment xml:lang="hr">AportisDoc dokument</comment>
+ <comment xml:lang="he">מסמך AportisDoc</comment>
+ <comment xml:lang="gl">documento de AportiDoc</comment>
+ <comment xml:lang="ga">cáipéis AportisDoc</comment>
+ <comment xml:lang="fur">document AportisDoc</comment>
+ <comment xml:lang="fr">document AportisDoc</comment>
+ <comment xml:lang="fo">AportisDoc skjal</comment>
+ <comment xml:lang="fi">AportisDoc-asiakirja</comment>
+ <comment xml:lang="eu">AportisDoc dokumentua</comment>
+ <comment xml:lang="es">documento de AportisDoc</comment>
+ <comment xml:lang="eo">AportisDoc-dokumento</comment>
+ <comment xml:lang="en_GB">AportisDoc document</comment>
+ <comment xml:lang="el">Έγγραφο AportisDoc</comment>
+ <comment xml:lang="de">AportisDoc-Dokument</comment>
+ <comment xml:lang="da">AportisDoc-dokument</comment>
+ <comment xml:lang="cs">dokument AportisDoc</comment>
+ <comment xml:lang="ca">document AportisDoc</comment>
+ <comment xml:lang="bg">Документ — AportisDoc</comment>
+ <comment xml:lang="be">дакумент AportisDoc</comment>
+ <comment xml:lang="ast">Documentu d'AportisDoc</comment>
+ <comment xml:lang="ar">مستند AportisDoc</comment>
+ <comment xml:lang="af">AportisDoc-dokument</comment>
<sub-class-of type="application/vnd.palm"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="TEXtREAd" type="string" offset="60"/>
- <match value="TEXtTlDc" type="string" offset="60"/>
+ <magic>
+ <match type="string" value="TEXtREAd" offset="60"/>
+ <match type="string" value="TEXtTlDc" offset="60"/>
</magic>
- <glob pattern="*.pdb"/>
+ <glob pattern="*.pdb" weight="30"/>
<glob pattern="*.pdc"/>
</mime-type>
+ <mime-type type="chemical/x-pdb">
+ <comment>Protein Data Bank file</comment>
+ <comment xml:lang="uk">файл банку даних протеїнів</comment>
+ <comment xml:lang="sv">Protein Data Bank-fil</comment>
+ <comment xml:lang="ru">Файл Protein Data Bank</comment>
+ <comment xml:lang="pl">Plik Protein Data Bank</comment>
+ <comment xml:lang="de">Protein-Datenbank-Datei</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-generic"/>
+ <magic priority="40">
+ <match type="string" value="HEADER " offset="0"/>
+ </magic>
+ <glob pattern="*.pdb"/>
+ <glob pattern="*.brk"/>
+ </mime-type>
<mime-type type="application/x-applix-spreadsheet">
<comment>Applix Spreadsheets spreadsheet</comment>
- <comment xml:lang="ar">جداول بيانات Applix</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš Applix Spreadsheets</comment>
- <comment xml:lang="bg">Таблица — Applix Spreadsheets</comment>
- <comment xml:lang="ca">full de càlcul d'Applix Spreadsheets</comment>
- <comment xml:lang="cs">sešit Applix Spreadsheets</comment>
- <comment xml:lang="da">Applix Spreadsheets-regneark</comment>
- <comment xml:lang="de">Applix-Spreadsheets-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Applix Spreadsheets</comment>
- <comment xml:lang="en_GB">Applix Spreadsheets spreadsheet</comment>
- <comment xml:lang="eo">sterntabelo de Applix Spreadsheets</comment>
- <comment xml:lang="es">hoja de cálculo de Applix Spreadsheets</comment>
- <comment xml:lang="eu">Applix Spreadsheets kalkulu-orria</comment>
- <comment xml:lang="fi">Applix Spreadsheets -taulukko</comment>
- <comment xml:lang="fo">Applix Spreadsheets rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Applix</comment>
- <comment xml:lang="ga">scarbhileog Applix Spreadsheets</comment>
- <comment xml:lang="gl">folla de cálculo de Applix</comment>
- <comment xml:lang="he">גליון נתונים של Applix Spreadsheets</comment>
- <comment xml:lang="hr">Applix Spreadsheets proračunska tablica</comment>
- <comment xml:lang="hu">Applix Spreadsheets-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo Applix Spreadsheets</comment>
- <comment xml:lang="id">Lembar sebar Applix Spreadsheets</comment>
- <comment xml:lang="it">Foglio di calcolo Applix Spreadsheets</comment>
- <comment xml:lang="ja">Applix Spreadsheets スプレッドシート</comment>
- <comment xml:lang="ka">Applix Spreadsheets-ის ცხრილი</comment>
- <comment xml:lang="kk">Applix Spreadsheets электрондық кестесі</comment>
- <comment xml:lang="ko">Applix 스프레드시트</comment>
- <comment xml:lang="lt">Applix Spreadsheets skaičialentė</comment>
- <comment xml:lang="lv">Applix Spreadsheets izklājlapa</comment>
- <comment xml:lang="ms">Hamparan Applix Spreadsheets</comment>
- <comment xml:lang="nb">Applix Spreadsheets-regneark</comment>
- <comment xml:lang="nl">Applix Spreadsheets-rekenblad</comment>
- <comment xml:lang="nn">Applix Spreadsheets-dokument</comment>
- <comment xml:lang="oc">fuèlh de calcul Applix</comment>
- <comment xml:lang="pl">Arkusz Applix Spreadsheets</comment>
- <comment xml:lang="pt">folha de cálculo Applix Spreadsheets</comment>
- <comment xml:lang="pt_BR">Planilha do Applix Spreadsheets</comment>
- <comment xml:lang="ro">Foaie de calcul Applix</comment>
- <comment xml:lang="ru">Электронная таблица Applix Spreadsheets</comment>
- <comment xml:lang="sk">Zošit Applix Spreadsheets</comment>
- <comment xml:lang="sl">Razpredelnica Applix Spreadsheets</comment>
- <comment xml:lang="sq">Fletë llogaritjesh Applix Spreadsheets</comment>
- <comment xml:lang="sr">документ Апликсове Табеле</comment>
- <comment xml:lang="sv">Applix Spreadsheets-kalkylblad</comment>
- <comment xml:lang="tr">Applix Spreadsheets çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Applix Spreadsheets</comment>
- <comment xml:lang="vi">Bảng tính Applix Spreadsheets</comment>
- <comment xml:lang="zh_CN">Applix Spreadsheets 电子表格</comment>
<comment xml:lang="zh_TW">Applix Spreadsheets 試算表</comment>
+ <comment xml:lang="zh_CN">Applix Spreadsheets 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Applix Spreadsheets</comment>
+ <comment xml:lang="uk">електронна таблиця Applix Spreadsheets</comment>
+ <comment xml:lang="tr">Applix Spreadsheets hesap çizelgesi</comment>
+ <comment xml:lang="sv">Applix Spreadsheets-kalkylblad</comment>
+ <comment xml:lang="sr">документ Апликсове Табеле</comment>
+ <comment xml:lang="sq">fletëllogaritje Applix Spreadsheets</comment>
+ <comment xml:lang="sl">Razpredelnica Applix Spreadsheets</comment>
+ <comment xml:lang="si">Applix පැතුරුම්පත් පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Applix Spreadsheets</comment>
+ <comment xml:lang="ru">Электронная таблица Applix Spreadsheets</comment>
+ <comment xml:lang="ro">Foaie de calcul Applix</comment>
+ <comment xml:lang="pt_BR">Planilha do Applix Spreadsheets</comment>
+ <comment xml:lang="pt">folha de cálculo Applix Spreadsheets</comment>
+ <comment xml:lang="pl">Arkusz Applix Spreadsheets</comment>
+ <comment xml:lang="oc">fuèlh de calcul Applix</comment>
+ <comment xml:lang="nn">Applix Spreadsheets-dokument</comment>
+ <comment xml:lang="nl">Applix Spreadsheets-rekenblad</comment>
+ <comment xml:lang="nb">Applix Spreadsheets-regneark</comment>
+ <comment xml:lang="ms">Hamparan Applix Spreadsheets</comment>
+ <comment xml:lang="lv">Applix Spreadsheets izklājlapa</comment>
+ <comment xml:lang="lt">Applix Spreadsheets skaičialentė</comment>
+ <comment xml:lang="ko">Applix 스프레드시트</comment>
+ <comment xml:lang="kk">Applix Spreadsheets электрондық кестесі</comment>
+ <comment xml:lang="ka">Applix Spreadsheets-ის ცხრილი</comment>
+ <comment xml:lang="ja">Applix Spreadsheets スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Applix Spreadsheets</comment>
+ <comment xml:lang="is">Applix Spreadsheets töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Applix Spreadsheets</comment>
+ <comment xml:lang="ia">Folio de calculo Applix Spreadsheets</comment>
+ <comment xml:lang="hu">Applix Spreadsheets-munkafüzet</comment>
+ <comment xml:lang="hr">Applix Spreadsheets proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Applix Spreadsheets</comment>
+ <comment xml:lang="gl">folla de cálculo de Applix</comment>
+ <comment xml:lang="ga">scarbhileog Applix Spreadsheets</comment>
+ <comment xml:lang="fur">sfuei di calcul Applix Spreadsheets</comment>
+ <comment xml:lang="fr">feuille de calcul Applix</comment>
+ <comment xml:lang="fo">Applix Spreadsheets rokniark</comment>
+ <comment xml:lang="fi">Applix Spreadsheets -taulukko</comment>
+ <comment xml:lang="eu">Applix Spreadsheets kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Applix Spreadsheets</comment>
+ <comment xml:lang="eo">sterntabelo de Applix Spreadsheets</comment>
+ <comment xml:lang="en_GB">Applix Spreadsheets spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Applix Spreadsheets</comment>
+ <comment xml:lang="de">Applix-Spreadsheets-Tabelle</comment>
+ <comment xml:lang="da">Applix Spreadsheets-regneark</comment>
+ <comment xml:lang="cs">sešit Applix Spreadsheets</comment>
+ <comment xml:lang="ca">full de càlcul d'Applix Spreadsheets</comment>
+ <comment xml:lang="bg">Таблица — Applix Spreadsheets</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš Applix Spreadsheets</comment>
+ <comment xml:lang="be">электронная табліца Applix Spreadsheets</comment>
+ <comment xml:lang="ar">جداول بيانات Applix</comment>
+ <comment xml:lang="af">Applix Spreadsheets-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="*BEGIN SPREADSHEETS" type="string" offset="0"/>
- <match value="*BEGIN" type="string" offset="0">
- <match value="SPREADSHEETS" type="string" offset="7"/>
+ <magic>
+ <match type="string" value="*BEGIN SPREADSHEETS" offset="0"/>
+ <match type="string" value="*BEGIN" offset="0">
+ <match type="string" value="SPREADSHEETS" offset="7"/>
</match>
</magic>
<glob pattern="*.as"/>
</mime-type>
<mime-type type="application/x-applix-word">
<comment>Applix Words document</comment>
- <comment xml:lang="ar">مستند كلمات Applix</comment>
- <comment xml:lang="ast">Documentu d'Applix Words</comment>
- <comment xml:lang="az">Applix Words sənədi</comment>
- <comment xml:lang="be@latin">Dakument Applix Words</comment>
- <comment xml:lang="bg">Документ — Applix Words</comment>
- <comment xml:lang="ca">document d'Applix Words</comment>
- <comment xml:lang="cs">dokument Applix Words</comment>
- <comment xml:lang="cy">Dogfen Applix Words</comment>
- <comment xml:lang="da">Applix Words-dokument</comment>
- <comment xml:lang="de">Applix-Words-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Applix Words</comment>
- <comment xml:lang="en_GB">Applix Words document</comment>
- <comment xml:lang="eo">dokumento de Applix Words</comment>
- <comment xml:lang="es">documento de Applix Words</comment>
- <comment xml:lang="eu">Applix Words dokumentua</comment>
- <comment xml:lang="fi">Applix Words -asiakirja</comment>
- <comment xml:lang="fo">Applix Words skjal</comment>
- <comment xml:lang="fr">document Applix Words</comment>
- <comment xml:lang="ga">cáipéis Applix Words</comment>
- <comment xml:lang="gl">documento de Applix Words</comment>
- <comment xml:lang="he">מסמך של Applix Words</comment>
- <comment xml:lang="hr">Applix Words dokument</comment>
- <comment xml:lang="hu">Applix Words-dokumentum</comment>
- <comment xml:lang="ia">Documento Applix Words</comment>
- <comment xml:lang="id">Dokumen Applix Words</comment>
- <comment xml:lang="it">Documento Applix Words</comment>
- <comment xml:lang="ja">Applix Words ドキュメント</comment>
- <comment xml:lang="ka">Applix Words-ის დოკუმენტი</comment>
- <comment xml:lang="kk">Applix Words құжаты</comment>
- <comment xml:lang="ko">Applix Words 문서</comment>
- <comment xml:lang="lt">Applix Words dokumentas</comment>
- <comment xml:lang="lv">Applix Words dokuments</comment>
- <comment xml:lang="ms">Dokumen Perkataan Applix</comment>
- <comment xml:lang="nb">Applix Words-dokument</comment>
- <comment xml:lang="nl">Applix Words-document</comment>
- <comment xml:lang="nn">Applix Words dokument</comment>
- <comment xml:lang="oc">document Applix Words</comment>
- <comment xml:lang="pl">Dokument Applix Words</comment>
- <comment xml:lang="pt">documento Applix Words</comment>
- <comment xml:lang="pt_BR">Documento do Applix Words</comment>
- <comment xml:lang="ro">Document Applix Words</comment>
- <comment xml:lang="ru">Документ Applix Words</comment>
- <comment xml:lang="sk">Dokument Applix Words</comment>
- <comment xml:lang="sl">Dokument Applix Words</comment>
- <comment xml:lang="sq">Dokument Applix Words</comment>
- <comment xml:lang="sr">документ Апликсових Речи</comment>
- <comment xml:lang="sv">Applix Words-dokument</comment>
- <comment xml:lang="tr">Applix Words belgesi</comment>
- <comment xml:lang="uk">документ Applix Words</comment>
- <comment xml:lang="vi">Tài liệu Applix Words</comment>
- <comment xml:lang="zh_CN">Applix Words 文档</comment>
<comment xml:lang="zh_TW">Applix Words 文件</comment>
+ <comment xml:lang="zh_CN">Applix Words 文档</comment>
+ <comment xml:lang="vi">Tài liệu Applix Words</comment>
+ <comment xml:lang="uk">документ Applix Words</comment>
+ <comment xml:lang="tr">Applix Words belgesi</comment>
+ <comment xml:lang="sv">Applix Words-dokument</comment>
+ <comment xml:lang="sr">документ Апликсових Речи</comment>
+ <comment xml:lang="sq">dokument Applix Words</comment>
+ <comment xml:lang="sl">Dokument Applix Words</comment>
+ <comment xml:lang="si">Applix Words ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Applix Words</comment>
+ <comment xml:lang="ru">Документ Applix Words</comment>
+ <comment xml:lang="ro">Document Applix Words</comment>
+ <comment xml:lang="pt_BR">Documento do Applix Words</comment>
+ <comment xml:lang="pt">documento Applix Words</comment>
+ <comment xml:lang="pl">Dokument Applix Words</comment>
+ <comment xml:lang="oc">document Applix Words</comment>
+ <comment xml:lang="nn">Applix Words dokument</comment>
+ <comment xml:lang="nl">Applix Words-document</comment>
+ <comment xml:lang="nb">Applix Words-dokument</comment>
+ <comment xml:lang="ms">Dokumen Perkataan Applix</comment>
+ <comment xml:lang="lv">Applix Words dokuments</comment>
+ <comment xml:lang="lt">Applix Words dokumentas</comment>
+ <comment xml:lang="ko">Applix Words 문서</comment>
+ <comment xml:lang="kk">Applix Words құжаты</comment>
+ <comment xml:lang="ka">Applix Words-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Applix Words ドキュメント</comment>
+ <comment xml:lang="it">Documento Applix Words</comment>
+ <comment xml:lang="is">Applix Words skjal</comment>
+ <comment xml:lang="id">Dokumen Applix Words</comment>
+ <comment xml:lang="ia">Documento Applix Words</comment>
+ <comment xml:lang="hu">Applix Words-dokumentum</comment>
+ <comment xml:lang="hr">Applix Words dokument</comment>
+ <comment xml:lang="he">מסמך של Applix Words</comment>
+ <comment xml:lang="gl">documento de Applix Words</comment>
+ <comment xml:lang="ga">cáipéis Applix Words</comment>
+ <comment xml:lang="fur">document Applix Words</comment>
+ <comment xml:lang="fr">document Applix Words</comment>
+ <comment xml:lang="fo">Applix Words skjal</comment>
+ <comment xml:lang="fi">Applix Words -asiakirja</comment>
+ <comment xml:lang="eu">Applix Words dokumentua</comment>
+ <comment xml:lang="es">documento de Applix Words</comment>
+ <comment xml:lang="eo">dokumento de Applix Words</comment>
+ <comment xml:lang="en_GB">Applix Words document</comment>
+ <comment xml:lang="el">Έγγραφο Applix Words</comment>
+ <comment xml:lang="de">Applix-Words-Dokument</comment>
+ <comment xml:lang="da">Applix Words-dokument</comment>
+ <comment xml:lang="cy">Dogfen Applix Words</comment>
+ <comment xml:lang="cs">dokument Applix Words</comment>
+ <comment xml:lang="ca">document d'Applix Words</comment>
+ <comment xml:lang="bg">Документ — Applix Words</comment>
+ <comment xml:lang="be@latin">Dakument Applix Words</comment>
+ <comment xml:lang="be">дакумент Applix Words</comment>
+ <comment xml:lang="az">Applix Words sənədi</comment>
+ <comment xml:lang="ast">Documentu d'Applix Words</comment>
+ <comment xml:lang="ar">مستند كلمات Applix</comment>
+ <comment xml:lang="af">Applix Words-dokument</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="*BEGIN" type="string" offset="0">
- <match value="WORDS" type="string" offset="7"/>
+ <magic>
+ <match type="string" value="*BEGIN" offset="0">
+ <match type="string" value="WORDS" offset="7"/>
</match>
</magic>
<glob pattern="*.aw"/>
</mime-type>
<mime-type type="application/x-arc">
<comment>ARC archive</comment>
- <comment xml:lang="ar">أرشيف ARC</comment>
- <comment xml:lang="be@latin">Archiŭ ARC</comment>
- <comment xml:lang="bg">Архив — ARC</comment>
- <comment xml:lang="ca">arxiu ARC</comment>
- <comment xml:lang="cs">archiv ARC</comment>
- <comment xml:lang="da">ARC-arkiv</comment>
- <comment xml:lang="de">ARC-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο ARC</comment>
- <comment xml:lang="en_GB">ARC archive</comment>
- <comment xml:lang="eo">ARC-arkivo</comment>
- <comment xml:lang="es">archivador ARC</comment>
- <comment xml:lang="eu">ARC artxiboa</comment>
- <comment xml:lang="fi">ARC-arkisto</comment>
- <comment xml:lang="fo">ARC skjalasavn</comment>
- <comment xml:lang="fr">archive ARC</comment>
- <comment xml:lang="ga">cartlann ARC</comment>
- <comment xml:lang="gl">arquivo ARC</comment>
- <comment xml:lang="he">ארכיון ARC</comment>
- <comment xml:lang="hr">ARC arhiva</comment>
- <comment xml:lang="hu">ARC-archívum</comment>
- <comment xml:lang="ia">Archivo ARC</comment>
- <comment xml:lang="id">Arsip ARC</comment>
- <comment xml:lang="it">Archivio ARC</comment>
- <comment xml:lang="ja">ARC アーカイブ</comment>
- <comment xml:lang="ka">ARC არქივი</comment>
- <comment xml:lang="kk">ARC архиві</comment>
- <comment xml:lang="ko">ARC 압축 파일</comment>
- <comment xml:lang="lt">ARC archyvas</comment>
- <comment xml:lang="lv">ARC arhīvs</comment>
- <comment xml:lang="nb">ARC-arkiv</comment>
- <comment xml:lang="nl">ARC-archief</comment>
- <comment xml:lang="nn">ARC-arkiv</comment>
- <comment xml:lang="oc">archiu ARC</comment>
- <comment xml:lang="pl">Archiwum ARC</comment>
- <comment xml:lang="pt">arquivo ARC</comment>
- <comment xml:lang="pt_BR">Pacote ARC</comment>
- <comment xml:lang="ro">Arhivă ARC</comment>
- <comment xml:lang="ru">Архив ARC</comment>
- <comment xml:lang="sk">Archív ARC</comment>
- <comment xml:lang="sl">Datoteka arhiva ARC</comment>
- <comment xml:lang="sq">Arkiv ARC</comment>
- <comment xml:lang="sr">АРЦ архива</comment>
- <comment xml:lang="sv">ARC-arkiv</comment>
- <comment xml:lang="tr">ARC arşivi</comment>
- <comment xml:lang="uk">архів ARC</comment>
- <comment xml:lang="vi">Kho nén ARC</comment>
- <comment xml:lang="zh_CN">ARC 归档文件</comment>
<comment xml:lang="zh_TW">ARC 封存檔</comment>
+ <comment xml:lang="zh_CN">ARC 归档文件</comment>
+ <comment xml:lang="vi">Kho nén ARC</comment>
+ <comment xml:lang="uk">архів ARC</comment>
+ <comment xml:lang="tr">ARC arşivi</comment>
+ <comment xml:lang="sv">ARC-arkiv</comment>
+ <comment xml:lang="sr">АРЦ архива</comment>
+ <comment xml:lang="sq">arkiv ARC</comment>
+ <comment xml:lang="sl">Datoteka arhiva ARC</comment>
+ <comment xml:lang="si">ARC ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív ARC</comment>
+ <comment xml:lang="ru">Архив ARC</comment>
+ <comment xml:lang="ro">Arhivă ARC</comment>
+ <comment xml:lang="pt_BR">Pacote ARC</comment>
+ <comment xml:lang="pt">arquivo ARC</comment>
+ <comment xml:lang="pl">Archiwum ARC</comment>
+ <comment xml:lang="oc">archiu ARC</comment>
+ <comment xml:lang="nn">ARC-arkiv</comment>
+ <comment xml:lang="nl">ARC-archief</comment>
+ <comment xml:lang="nb">ARC-arkiv</comment>
+ <comment xml:lang="lv">ARC arhīvs</comment>
+ <comment xml:lang="lt">ARC archyvas</comment>
+ <comment xml:lang="ko">ARC 압축 파일</comment>
+ <comment xml:lang="kk">ARC архиві</comment>
+ <comment xml:lang="ka">ARC არქივი</comment>
+ <comment xml:lang="ja">ARC アーカイブ</comment>
+ <comment xml:lang="it">Archivio ARC</comment>
+ <comment xml:lang="is">ARC safnskrá</comment>
+ <comment xml:lang="id">Arsip ARC</comment>
+ <comment xml:lang="ia">Archivo ARC</comment>
+ <comment xml:lang="hu">ARC-archívum</comment>
+ <comment xml:lang="hr">ARC arhiva</comment>
+ <comment xml:lang="he">ארכיון ARC</comment>
+ <comment xml:lang="gl">arquivo ARC</comment>
+ <comment xml:lang="ga">cartlann ARC</comment>
+ <comment xml:lang="fur">archivi ARC</comment>
+ <comment xml:lang="fr">archive ARC</comment>
+ <comment xml:lang="fo">ARC skjalasavn</comment>
+ <comment xml:lang="fi">ARC-arkisto</comment>
+ <comment xml:lang="eu">ARC artxiboa</comment>
+ <comment xml:lang="es">archivador ARC</comment>
+ <comment xml:lang="eo">ARC-arkivo</comment>
+ <comment xml:lang="en_GB">ARC archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο ARC</comment>
+ <comment xml:lang="de">ARC-Archiv</comment>
+ <comment xml:lang="da">ARC-arkiv</comment>
+ <comment xml:lang="cs">archiv ARC</comment>
+ <comment xml:lang="ca">arxiu ARC</comment>
+ <comment xml:lang="bg">Архив — ARC</comment>
+ <comment xml:lang="be@latin">Archiŭ ARC</comment>
+ <comment xml:lang="be">архіў ARC</comment>
+ <comment xml:lang="ar">أرشيف ARC</comment>
+ <comment xml:lang="af">ARC-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="0x0000081a" type="little32" offset="0" mask="0x8080ffff"/>
- <match value="0x0000091a" type="little32" offset="0" mask="0x8080ffff"/>
- <match value="0x0000021a" type="little32" offset="0" mask="0x8080ffff"/>
- <match value="0x0000031a" type="little32" offset="0" mask="0x8080ffff"/>
- <match value="0x0000041a" type="little32" offset="0" mask="0x8080ffff"/>
- <match value="0x0000061a" type="little32" offset="0" mask="0x8080ffff"/>
+ <match type="little32" mask="0x8080ffff" value="0x0000081a" offset="0"/>
+ <match type="little32" mask="0x8080ffff" value="0x0000091a" offset="0"/>
+ <match type="little32" mask="0x8080ffff" value="0x0000021a" offset="0"/>
+ <match type="little32" mask="0x8080ffff" value="0x0000031a" offset="0"/>
+ <match type="little32" mask="0x8080ffff" value="0x0000041a" offset="0"/>
+ <match type="little32" mask="0x8080ffff" value="0x0000061a" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-archive">
<comment>AR archive</comment>
- <comment xml:lang="ar">أرشيف AR</comment>
- <comment xml:lang="be@latin">Archiŭ AR</comment>
- <comment xml:lang="bg">Архив — AR</comment>
- <comment xml:lang="ca">arxiu AR</comment>
- <comment xml:lang="cs">archiv AR</comment>
- <comment xml:lang="da">AR-arkiv</comment>
- <comment xml:lang="de">AR-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο AR</comment>
- <comment xml:lang="en_GB">AR archive</comment>
- <comment xml:lang="eo">AR-arkivo</comment>
- <comment xml:lang="es">archivador AR</comment>
- <comment xml:lang="eu">AR artxiboa</comment>
- <comment xml:lang="fi">AR-arkisto</comment>
- <comment xml:lang="fo">AR skjalasavn</comment>
- <comment xml:lang="fr">archive AR</comment>
- <comment xml:lang="ga">cartlann AR</comment>
- <comment xml:lang="gl">arquivo AR</comment>
- <comment xml:lang="he">ארכיון AR</comment>
- <comment xml:lang="hr">AR arhiva</comment>
- <comment xml:lang="hu">AR-archívum</comment>
- <comment xml:lang="ia">Archivo AR</comment>
- <comment xml:lang="id">Arsip AR</comment>
- <comment xml:lang="it">Archivio AR</comment>
- <comment xml:lang="ja">AR アーカイブ</comment>
- <comment xml:lang="ka">AR არქივი</comment>
- <comment xml:lang="kk">AR архиві</comment>
- <comment xml:lang="ko">AR 묶음 파일</comment>
- <comment xml:lang="lt">AR archyvas</comment>
- <comment xml:lang="lv">AR arhīvs</comment>
- <comment xml:lang="ms">Arkib AR</comment>
- <comment xml:lang="nb">AR-arkiv</comment>
- <comment xml:lang="nl">AR-archief</comment>
- <comment xml:lang="nn">AR-arkiv</comment>
- <comment xml:lang="oc">archiu AR</comment>
- <comment xml:lang="pl">Archiwum AR</comment>
- <comment xml:lang="pt">arquivo AR</comment>
- <comment xml:lang="pt_BR">Pacote AR</comment>
- <comment xml:lang="ro">Arhivă AR</comment>
- <comment xml:lang="ru">Архив AR</comment>
- <comment xml:lang="sk">Archív AR</comment>
- <comment xml:lang="sl">Datoteka arhiva AR</comment>
- <comment xml:lang="sq">Arkiv AR</comment>
- <comment xml:lang="sr">АР архива</comment>
- <comment xml:lang="sv">AR-arkiv</comment>
- <comment xml:lang="tr">AR arşivi</comment>
- <comment xml:lang="uk">архів AR</comment>
- <comment xml:lang="vi">Kho nén AR</comment>
- <comment xml:lang="zh_CN">AR 归档文件</comment>
<comment xml:lang="zh_TW">AR 封存檔</comment>
+ <comment xml:lang="zh_CN">AR 归档文件</comment>
+ <comment xml:lang="vi">Kho nén AR</comment>
+ <comment xml:lang="uk">архів AR</comment>
+ <comment xml:lang="tr">AR arşivi</comment>
+ <comment xml:lang="sv">AR-arkiv</comment>
+ <comment xml:lang="sr">АР архива</comment>
+ <comment xml:lang="sq">arkiv AR</comment>
+ <comment xml:lang="sl">Datoteka arhiva AR</comment>
+ <comment xml:lang="si">AR ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív AR</comment>
+ <comment xml:lang="ru">Архив AR</comment>
+ <comment xml:lang="ro">Arhivă AR</comment>
+ <comment xml:lang="pt_BR">Pacote AR</comment>
+ <comment xml:lang="pt">arquivo AR</comment>
+ <comment xml:lang="pl">Archiwum AR</comment>
+ <comment xml:lang="oc">archiu AR</comment>
+ <comment xml:lang="nn">AR-arkiv</comment>
+ <comment xml:lang="nl">AR-archief</comment>
+ <comment xml:lang="nb">AR-arkiv</comment>
+ <comment xml:lang="ms">Arkib AR</comment>
+ <comment xml:lang="lv">AR arhīvs</comment>
+ <comment xml:lang="lt">AR archyvas</comment>
+ <comment xml:lang="ko">AR 묶음 파일</comment>
+ <comment xml:lang="kk">AR архиві</comment>
+ <comment xml:lang="ka">AR არქივი</comment>
+ <comment xml:lang="ja">AR アーカイブ</comment>
+ <comment xml:lang="it">Archivio AR</comment>
+ <comment xml:lang="is">AR safnskrá</comment>
+ <comment xml:lang="id">Arsip AR</comment>
+ <comment xml:lang="ia">Archivo AR</comment>
+ <comment xml:lang="hu">AR-archívum</comment>
+ <comment xml:lang="hr">AR arhiva</comment>
+ <comment xml:lang="he">ארכיון AR</comment>
+ <comment xml:lang="gl">arquivo AR</comment>
+ <comment xml:lang="ga">cartlann AR</comment>
+ <comment xml:lang="fur">archivi AR</comment>
+ <comment xml:lang="fr">archive AR</comment>
+ <comment xml:lang="fo">AR skjalasavn</comment>
+ <comment xml:lang="fi">AR-arkisto</comment>
+ <comment xml:lang="eu">AR artxiboa</comment>
+ <comment xml:lang="es">archivador AR</comment>
+ <comment xml:lang="eo">AR-arkivo</comment>
+ <comment xml:lang="en_GB">AR archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο AR</comment>
+ <comment xml:lang="de">AR-Archiv</comment>
+ <comment xml:lang="da">AR-arkiv</comment>
+ <comment xml:lang="cs">archiv AR</comment>
+ <comment xml:lang="ca">arxiu AR</comment>
+ <comment xml:lang="bg">Архив — AR</comment>
+ <comment xml:lang="be@latin">Archiŭ AR</comment>
+ <comment xml:lang="be">архіў AR</comment>
+ <comment xml:lang="ar">أرشيف AR</comment>
+ <comment xml:lang="af">AR-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="45">
- <match value="&lt;ar&gt;" type="string" offset="0"/>
- <match value="!&lt;arch&gt;" type="string" offset="0"/>
+ <match type="string" value="&lt;ar&gt;" offset="0"/>
+ <match type="string" value="!&lt;arch&gt;" offset="0"/>
</magic>
<glob pattern="*.a"/>
<glob pattern="*.ar"/>
</mime-type>
<mime-type type="application/x-arj">
<comment>ARJ archive</comment>
- <comment xml:lang="ar">أرشيف ARJ</comment>
- <comment xml:lang="az">ARJ arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ ARJ</comment>
- <comment xml:lang="bg">Архив — ARJ</comment>
- <comment xml:lang="ca">arxiu ARJ</comment>
- <comment xml:lang="cs">archiv ARJ</comment>
- <comment xml:lang="cy">Archif ARJ</comment>
- <comment xml:lang="da">ARJ-arkiv</comment>
- <comment xml:lang="de">ARJ-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο ARJ</comment>
- <comment xml:lang="en_GB">ARJ archive</comment>
- <comment xml:lang="eo">ARJ-arkivo</comment>
- <comment xml:lang="es">archivador ARJ</comment>
- <comment xml:lang="eu">ARJ artxiboa</comment>
- <comment xml:lang="fi">ARJ-arkisto</comment>
- <comment xml:lang="fo">ARJ skjalasavn</comment>
- <comment xml:lang="fr">archive ARJ</comment>
- <comment xml:lang="ga">cartlann ARJ</comment>
- <comment xml:lang="gl">arquivo ARJ</comment>
- <comment xml:lang="he">ארכיון ARJ</comment>
- <comment xml:lang="hr">ARJ arhiva</comment>
- <comment xml:lang="hu">ARJ-archívum</comment>
- <comment xml:lang="ia">Archivo ARJ</comment>
- <comment xml:lang="id">Arsip ARJ</comment>
- <comment xml:lang="it">Archivio ARJ</comment>
- <comment xml:lang="ja">ARJ アーカイブ</comment>
- <comment xml:lang="ka">ARJ არქივი</comment>
- <comment xml:lang="kk">ARJ архиві</comment>
- <comment xml:lang="ko">ARJ 압축 파일</comment>
- <comment xml:lang="lt">ARJ archyvas</comment>
- <comment xml:lang="lv">ARJ arhīvs</comment>
- <comment xml:lang="ms">Arkib ARJ</comment>
- <comment xml:lang="nb">ARJ-arkiv</comment>
- <comment xml:lang="nl">ARJ-archief</comment>
- <comment xml:lang="nn">ARJ-arkiv</comment>
- <comment xml:lang="oc">archiu ARJ</comment>
- <comment xml:lang="pl">Archiwum ARJ</comment>
- <comment xml:lang="pt">arquivo ARJ</comment>
- <comment xml:lang="pt_BR">Pacote ARJ</comment>
- <comment xml:lang="ro">Arhivă ARJ</comment>
- <comment xml:lang="ru">Архив ARJ</comment>
- <comment xml:lang="sk">Archív ARJ</comment>
- <comment xml:lang="sl">Datoteka arhiva ARJ</comment>
- <comment xml:lang="sq">Arkiv ARJ</comment>
- <comment xml:lang="sr">АРЈ архива</comment>
- <comment xml:lang="sv">ARJ-arkiv</comment>
- <comment xml:lang="tr">ARJ arşivi</comment>
- <comment xml:lang="uk">архів ARJ</comment>
- <comment xml:lang="vi">Kho nén ARJ</comment>
- <comment xml:lang="zh_CN">ARJ 归档文件</comment>
<comment xml:lang="zh_TW">ARJ 封存檔</comment>
+ <comment xml:lang="zh_CN">ARJ 归档文件</comment>
+ <comment xml:lang="vi">Kho nén ARJ</comment>
+ <comment xml:lang="uk">архів ARJ</comment>
+ <comment xml:lang="tr">ARJ arşivi</comment>
+ <comment xml:lang="sv">ARJ-arkiv</comment>
+ <comment xml:lang="sr">АРЈ архива</comment>
+ <comment xml:lang="sq">arkiv ARJ</comment>
+ <comment xml:lang="sl">Datoteka arhiva ARJ</comment>
+ <comment xml:lang="si">ARJ ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív ARJ</comment>
+ <comment xml:lang="ru">Архив ARJ</comment>
+ <comment xml:lang="ro">Arhivă ARJ</comment>
+ <comment xml:lang="pt_BR">Pacote ARJ</comment>
+ <comment xml:lang="pt">arquivo ARJ</comment>
+ <comment xml:lang="pl">Archiwum ARJ</comment>
+ <comment xml:lang="oc">archiu ARJ</comment>
+ <comment xml:lang="nn">ARJ-arkiv</comment>
+ <comment xml:lang="nl">ARJ-archief</comment>
+ <comment xml:lang="nb">ARJ-arkiv</comment>
+ <comment xml:lang="ms">Arkib ARJ</comment>
+ <comment xml:lang="lv">ARJ arhīvs</comment>
+ <comment xml:lang="lt">ARJ archyvas</comment>
+ <comment xml:lang="ko">ARJ 압축 파일</comment>
+ <comment xml:lang="kk">ARJ архиві</comment>
+ <comment xml:lang="ka">ARJ არქივი</comment>
+ <comment xml:lang="ja">ARJ アーカイブ</comment>
+ <comment xml:lang="it">Archivio ARJ</comment>
+ <comment xml:lang="is">ARJ safnskrá</comment>
+ <comment xml:lang="id">Arsip ARJ</comment>
+ <comment xml:lang="ia">Archivo ARJ</comment>
+ <comment xml:lang="hu">ARJ-archívum</comment>
+ <comment xml:lang="hr">ARJ arhiva</comment>
+ <comment xml:lang="he">ארכיון ARJ</comment>
+ <comment xml:lang="gl">arquivo ARJ</comment>
+ <comment xml:lang="ga">cartlann ARJ</comment>
+ <comment xml:lang="fur">archivi ARJ</comment>
+ <comment xml:lang="fr">archive ARJ</comment>
+ <comment xml:lang="fo">ARJ skjalasavn</comment>
+ <comment xml:lang="fi">ARJ-arkisto</comment>
+ <comment xml:lang="eu">ARJ artxiboa</comment>
+ <comment xml:lang="es">archivador ARJ</comment>
+ <comment xml:lang="eo">ARJ-arkivo</comment>
+ <comment xml:lang="en_GB">ARJ archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο ARJ</comment>
+ <comment xml:lang="de">ARJ-Archiv</comment>
+ <comment xml:lang="da">ARJ-arkiv</comment>
+ <comment xml:lang="cy">Archif ARJ</comment>
+ <comment xml:lang="cs">archiv ARJ</comment>
+ <comment xml:lang="ca">arxiu ARJ</comment>
+ <comment xml:lang="bg">Архив — ARJ</comment>
+ <comment xml:lang="be@latin">Archiŭ ARJ</comment>
+ <comment xml:lang="be">архіў ARJ</comment>
+ <comment xml:lang="az">ARJ arxivi</comment>
+ <comment xml:lang="ar">أرشيف ARJ</comment>
+ <comment xml:lang="af">ARJ-argief</comment>
<acronym>ARJ</acronym>
<expanded-acronym>Archived by Robert Jung</expanded-acronym>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="0xea60" type="little16" offset="0"/>
+ <magic>
+ <match type="little16" value="0xea60" offset="0"/>
</magic>
<glob pattern="*.arj"/>
</mime-type>
+ <mime-type type="application/x-asar">
+ <comment>Electron Archive (ASAR)</comment>
+ <comment xml:lang="zh_CN">Electron 归档 (ASAR)</comment>
+ <comment xml:lang="uk">архів Electron (ASAR)</comment>
+ <comment xml:lang="tr">Electron Arşivi (ASAR)</comment>
+ <comment xml:lang="sv">Electron-arkiv (ASAR)</comment>
+ <comment xml:lang="sl">Arhiv Electron (ASAR)</comment>
+ <comment xml:lang="si">ඉලෙක්ට්‍රෝන ලේඛනාගාරය (ASAR)</comment>
+ <comment xml:lang="ru">Electron Archive (ASAR)</comment>
+ <comment xml:lang="pt_BR">Arquivo do Electron (ASAR)</comment>
+ <comment xml:lang="pl">Archiwum Electron (ASAR)</comment>
+ <comment xml:lang="nl">Electron Archive (ASAR)</comment>
+ <comment xml:lang="ko">일렉트론 묶음 파일 (ASAR)</comment>
+ <comment xml:lang="kk">Electron архиві (ASAR)</comment>
+ <comment xml:lang="ja">Electron アーカイブ (ASAR)</comment>
+ <comment xml:lang="it">Archivio Electron (ASAR)</comment>
+ <comment xml:lang="hr">Electron arhiva (ASAR)</comment>
+ <comment xml:lang="he">ארכיון Electron‏ (ASAR)</comment>
+ <comment xml:lang="gl">Arquivo Electron (ASAR)</comment>
+ <comment xml:lang="fi">Electron Archive (ASAR)</comment>
+ <comment xml:lang="eu">Electron artxiboa (ASAR)</comment>
+ <comment xml:lang="es">archivador Electron (ASARP)</comment>
+ <comment xml:lang="en_GB">Electron Archive (ASAR)</comment>
+ <comment xml:lang="de">Electron-Archiv (ASAR)</comment>
+ <comment xml:lang="be">архіў Electron (ASAR)</comment>
+ <comment xml:lang="ar">أرشيف إليكترون (ASAR)</comment>
+ <acronym>ASAR</acronym>
+ <expanded-acronym>Atom Shell Archive Format</expanded-acronym>
+ <magic>
+ <match type="string" value="\004\000\000\000" offset="0">
+ <match type="string" value="{&quot;files&quot;:" offset="16"/>
+ </match>
+ </magic>
+ <glob pattern="*.asar"/>
+ </mime-type>
<mime-type type="application/x-asp">
<comment>ASP page</comment>
- <comment xml:lang="ar">صفحة ASP</comment>
- <comment xml:lang="ast">Páxina ASP</comment>
- <comment xml:lang="be@latin">Staronka ASP</comment>
- <comment xml:lang="bg">Страница — ASP</comment>
- <comment xml:lang="ca">pàgina ASP</comment>
- <comment xml:lang="cs">stránka ASP</comment>
- <comment xml:lang="da">ASP-side</comment>
- <comment xml:lang="de">ASP-Seite</comment>
- <comment xml:lang="el">Σελίδα ASP</comment>
- <comment xml:lang="en_GB">ASP page</comment>
- <comment xml:lang="eo">ASP-paĝo</comment>
- <comment xml:lang="es">página ASP</comment>
- <comment xml:lang="eu">ASP orria</comment>
- <comment xml:lang="fi">ASP-sivu</comment>
- <comment xml:lang="fo">ASP síða</comment>
- <comment xml:lang="fr">page ASP</comment>
- <comment xml:lang="ga">leathanach ASP</comment>
- <comment xml:lang="gl">páxina ASP</comment>
- <comment xml:lang="he">עמוד ASP</comment>
- <comment xml:lang="hr">ASP stranica</comment>
- <comment xml:lang="hu">ASP oldal</comment>
- <comment xml:lang="ia">Pagina ASP</comment>
- <comment xml:lang="id">Halaman ASP</comment>
- <comment xml:lang="it">Pagina ASP</comment>
- <comment xml:lang="ja">ASP ページ</comment>
- <comment xml:lang="ka">ASP გვერდი</comment>
- <comment xml:lang="kk">ASP парағы</comment>
- <comment xml:lang="ko">ASP 페이지</comment>
- <comment xml:lang="lt">ASP puslapis</comment>
- <comment xml:lang="lv">ASP lapa</comment>
- <comment xml:lang="nb">ASP-side</comment>
- <comment xml:lang="nl">ASP-pagina</comment>
- <comment xml:lang="nn">ASP-side</comment>
- <comment xml:lang="oc">pagina ASP</comment>
- <comment xml:lang="pl">Strona ASP</comment>
- <comment xml:lang="pt">página ASP</comment>
- <comment xml:lang="pt_BR">Página ASP</comment>
- <comment xml:lang="ro">Pagină ASP</comment>
- <comment xml:lang="ru">Страница ASP</comment>
- <comment xml:lang="sk">Stránka ASP</comment>
- <comment xml:lang="sl">Datoteka spletne strani ASP</comment>
- <comment xml:lang="sq">Faqe ASP</comment>
- <comment xml:lang="sr">АСП страница</comment>
- <comment xml:lang="sv">ASP-sida</comment>
- <comment xml:lang="tr">ASP sayfası</comment>
- <comment xml:lang="uk">сторінка ASP</comment>
- <comment xml:lang="vi">Trang ASP</comment>
- <comment xml:lang="zh_CN">ASP 页面</comment>
<comment xml:lang="zh_TW">ASP 頁面</comment>
+ <comment xml:lang="zh_CN">ASP 页面</comment>
+ <comment xml:lang="vi">Trang ASP</comment>
+ <comment xml:lang="uk">сторінка ASP</comment>
+ <comment xml:lang="tr">ASP sayfası</comment>
+ <comment xml:lang="sv">ASP-sida</comment>
+ <comment xml:lang="sr">АСП страница</comment>
+ <comment xml:lang="sq">faqe ASP</comment>
+ <comment xml:lang="sl">Datoteka spletne strani ASP</comment>
+ <comment xml:lang="si">ASP පිටුව</comment>
+ <comment xml:lang="sk">Stránka ASP</comment>
+ <comment xml:lang="ru">Страница ASP</comment>
+ <comment xml:lang="ro">Pagină ASP</comment>
+ <comment xml:lang="pt_BR">Página ASP</comment>
+ <comment xml:lang="pt">página ASP</comment>
+ <comment xml:lang="pl">Strona ASP</comment>
+ <comment xml:lang="oc">pagina ASP</comment>
+ <comment xml:lang="nn">ASP-side</comment>
+ <comment xml:lang="nl">ASP-pagina</comment>
+ <comment xml:lang="nb">ASP-side</comment>
+ <comment xml:lang="lv">ASP lapa</comment>
+ <comment xml:lang="lt">ASP puslapis</comment>
+ <comment xml:lang="ko">ASP 페이지</comment>
+ <comment xml:lang="kk">ASP парағы</comment>
+ <comment xml:lang="ka">ASP გვერდი</comment>
+ <comment xml:lang="ja">ASP ページ</comment>
+ <comment xml:lang="it">Pagina ASP</comment>
+ <comment xml:lang="is">ASP síða</comment>
+ <comment xml:lang="id">Halaman ASP</comment>
+ <comment xml:lang="ia">Pagina ASP</comment>
+ <comment xml:lang="hu">ASP oldal</comment>
+ <comment xml:lang="hr">ASP stranica</comment>
+ <comment xml:lang="he">עמוד ASP</comment>
+ <comment xml:lang="gl">páxina ASP</comment>
+ <comment xml:lang="ga">leathanach ASP</comment>
+ <comment xml:lang="fur">pagjine ASP</comment>
+ <comment xml:lang="fr">page ASP</comment>
+ <comment xml:lang="fo">ASP síða</comment>
+ <comment xml:lang="fi">ASP-sivu</comment>
+ <comment xml:lang="eu">ASP orria</comment>
+ <comment xml:lang="es">página ASP</comment>
+ <comment xml:lang="eo">ASP-paĝo</comment>
+ <comment xml:lang="en_GB">ASP page</comment>
+ <comment xml:lang="el">Σελίδα ASP</comment>
+ <comment xml:lang="de">ASP-Seite</comment>
+ <comment xml:lang="da">ASP-side</comment>
+ <comment xml:lang="cs">stránka ASP</comment>
+ <comment xml:lang="ca">pàgina ASP</comment>
+ <comment xml:lang="bg">Страница — ASP</comment>
+ <comment xml:lang="be@latin">Staronka ASP</comment>
+ <comment xml:lang="be">старонка ASP</comment>
+ <comment xml:lang="ast">Páxina ASP</comment>
+ <comment xml:lang="ar">صفحة ASP</comment>
+ <comment xml:lang="af">ASP-bladsy</comment>
<acronym>ASP</acronym>
<expanded-acronym>Active Server Page</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -7638,129 +8205,108 @@
</mime-type>
<mime-type type="application/x-awk">
<comment>AWK script</comment>
- <comment xml:lang="ar">سكربت AWK</comment>
- <comment xml:lang="ast">Script AWK</comment>
- <comment xml:lang="az">AWK skripti</comment>
- <comment xml:lang="be@latin">Skrypt AWK</comment>
- <comment xml:lang="bg">Скрипт — AWK</comment>
- <comment xml:lang="ca">script AWK</comment>
- <comment xml:lang="cs">skript AWK</comment>
- <comment xml:lang="cy">Sgript AWK</comment>
- <comment xml:lang="da">AWK-program</comment>
- <comment xml:lang="de">AWK-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών AWK</comment>
- <comment xml:lang="en_GB">AWK script</comment>
- <comment xml:lang="eo">AWK-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en AWK</comment>
- <comment xml:lang="eu">AWK script-a</comment>
- <comment xml:lang="fi">AWK-komentotiedosto</comment>
- <comment xml:lang="fo">AWK boðrøð</comment>
- <comment xml:lang="fr">script AWK</comment>
- <comment xml:lang="ga">script AWK</comment>
- <comment xml:lang="gl">script de AWK</comment>
- <comment xml:lang="he">תסריט AWK</comment>
- <comment xml:lang="hr">AWK skripta</comment>
- <comment xml:lang="hu">AWK-parancsfájl</comment>
- <comment xml:lang="ia">Script AWK</comment>
- <comment xml:lang="id">Skrip AWK</comment>
- <comment xml:lang="it">Script AWK</comment>
- <comment xml:lang="ja">AWK スクリプト</comment>
- <comment xml:lang="ka">AWK სცენარი</comment>
- <comment xml:lang="kk">AWK сценарийі</comment>
- <comment xml:lang="ko">AWK 스크립트</comment>
- <comment xml:lang="lt">AWK scenarijus</comment>
- <comment xml:lang="lv">AWK skripts</comment>
- <comment xml:lang="ms">Skrip AWK</comment>
- <comment xml:lang="nb">AWK-skript</comment>
- <comment xml:lang="nl">AWK-script</comment>
- <comment xml:lang="nn">WAK-skript</comment>
- <comment xml:lang="oc">escript AWK</comment>
- <comment xml:lang="pl">Skrypt AWK</comment>
- <comment xml:lang="pt">script AWK</comment>
- <comment xml:lang="pt_BR">Script AWK</comment>
- <comment xml:lang="ro">Script AWK</comment>
- <comment xml:lang="ru">Сценарий AWK</comment>
- <comment xml:lang="sk">Skript AWK</comment>
- <comment xml:lang="sl">Skriptna datoteka AWK</comment>
- <comment xml:lang="sq">Script AWK</comment>
- <comment xml:lang="sr">АВК скрипта</comment>
- <comment xml:lang="sv">AWK-skript</comment>
- <comment xml:lang="tr">AWK betiği</comment>
- <comment xml:lang="uk">скрипт AWK</comment>
- <comment xml:lang="vi">Văn lệnh AWK</comment>
- <comment xml:lang="zh_CN">AWK 脚本</comment>
<comment xml:lang="zh_TW">AWK 指令稿</comment>
+ <comment xml:lang="zh_CN">AWK 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh AWK</comment>
+ <comment xml:lang="uk">скрипт AWK</comment>
+ <comment xml:lang="tr">AWK betiği</comment>
+ <comment xml:lang="sv">AWK-skript</comment>
+ <comment xml:lang="sr">АВК скрипта</comment>
+ <comment xml:lang="sq">programth AWK</comment>
+ <comment xml:lang="sl">Skriptna datoteka AWK</comment>
+ <comment xml:lang="si">AWK පිටපත</comment>
+ <comment xml:lang="sk">Skript AWK</comment>
+ <comment xml:lang="ru">Сценарий AWK</comment>
+ <comment xml:lang="ro">Script AWK</comment>
+ <comment xml:lang="pt_BR">Script AWK</comment>
+ <comment xml:lang="pt">script AWK</comment>
+ <comment xml:lang="pl">Skrypt AWK</comment>
+ <comment xml:lang="oc">escript AWK</comment>
+ <comment xml:lang="nn">WAK-skript</comment>
+ <comment xml:lang="nl">AWK-script</comment>
+ <comment xml:lang="nb">AWK-skript</comment>
+ <comment xml:lang="ms">Skrip AWK</comment>
+ <comment xml:lang="lv">AWK skripts</comment>
+ <comment xml:lang="lt">AWK scenarijus</comment>
+ <comment xml:lang="ko">AWK 스크립트</comment>
+ <comment xml:lang="kk">AWK сценарийі</comment>
+ <comment xml:lang="ka">AWK სცენარი</comment>
+ <comment xml:lang="ja">AWK スクリプト</comment>
+ <comment xml:lang="it">Script AWK</comment>
+ <comment xml:lang="is">AWK skrifta</comment>
+ <comment xml:lang="id">Skrip AWK</comment>
+ <comment xml:lang="ia">Script AWK</comment>
+ <comment xml:lang="hu">AWK-parancsfájl</comment>
+ <comment xml:lang="hr">AWK skripta</comment>
+ <comment xml:lang="he">תסריט AWK</comment>
+ <comment xml:lang="gl">script de AWK</comment>
+ <comment xml:lang="ga">script AWK</comment>
+ <comment xml:lang="fur">script AWK</comment>
+ <comment xml:lang="fr">script AWK</comment>
+ <comment xml:lang="fo">AWK boðrøð</comment>
+ <comment xml:lang="fi">AWK-komentotiedosto</comment>
+ <comment xml:lang="eu">AWK script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en AWK</comment>
+ <comment xml:lang="eo">AWK-skripto</comment>
+ <comment xml:lang="en_GB">AWK script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών AWK</comment>
+ <comment xml:lang="de">AWK-Skript</comment>
+ <comment xml:lang="da">AWK-program</comment>
+ <comment xml:lang="cy">Sgript AWK</comment>
+ <comment xml:lang="cs">skript AWK</comment>
+ <comment xml:lang="ca">script AWK</comment>
+ <comment xml:lang="bg">Скрипт — AWK</comment>
+ <comment xml:lang="be@latin">Skrypt AWK</comment>
+ <comment xml:lang="be">скрыпт AWK</comment>
+ <comment xml:lang="az">AWK skripti</comment>
+ <comment xml:lang="ast">Script AWK</comment>
+ <comment xml:lang="ar">سكربت AWK</comment>
+ <comment xml:lang="af">AWK-skrip</comment>
<sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
- <magic priority="50">
- <match value="#!/bin/gawk" type="string" offset="0"/>
- <match value="#! /bin/gawk" type="string" offset="0"/>
- <match value="#!/usr/bin/gawk" type="string" offset="0"/>
- <match value="#! /usr/bin/gawk" type="string" offset="0"/>
- <match value="#!/usr/local/bin/gawk" type="string" offset="0"/>
- <match value="#! /usr/local/bin/gawk" type="string" offset="0"/>
- <match value="#!/bin/awk" type="string" offset="0"/>
- <match value="#! /bin/awk" type="string" offset="0"/>
- <match value="#!/usr/bin/awk" type="string" offset="0"/>
- <match value="#! /usr/bin/awk" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#!/bin/gawk" offset="0"/>
+ <match type="string" value="#! /bin/gawk" offset="0"/>
+ <match type="string" value="#!/usr/bin/gawk" offset="0"/>
+ <match type="string" value="#! /usr/bin/gawk" offset="0"/>
+ <match type="string" value="#!/usr/local/bin/gawk" offset="0"/>
+ <match type="string" value="#! /usr/local/bin/gawk" offset="0"/>
+ <match type="string" value="#!/bin/awk" offset="0"/>
+ <match type="string" value="#! /bin/awk" offset="0"/>
+ <match type="string" value="#!/usr/bin/awk" offset="0"/>
+ <match type="string" value="#! /usr/bin/awk" offset="0"/>
</magic>
<glob pattern="*.awk"/>
</mime-type>
<mime-type type="application/x-bcpio">
- <comment>BCPIO document</comment>
- <comment xml:lang="ar">مستند BCPIO</comment>
- <comment xml:lang="ast">Documentu BCPIO</comment>
- <comment xml:lang="az">BCPIO sənədi</comment>
- <comment xml:lang="be@latin">Dakument BCPIO</comment>
- <comment xml:lang="bg">Документ — BCPIO</comment>
- <comment xml:lang="ca">document BCPIO</comment>
- <comment xml:lang="cs">dokument BCPIO</comment>
- <comment xml:lang="cy">Dogfen BCPIO</comment>
- <comment xml:lang="da">BCPIO-dokument</comment>
- <comment xml:lang="de">BCPIO-Dokument</comment>
- <comment xml:lang="el">Έγγραφο BCPIO</comment>
- <comment xml:lang="en_GB">BCPIO document</comment>
- <comment xml:lang="eo">BCPIO-dokumento</comment>
- <comment xml:lang="es">documento BCPIO</comment>
- <comment xml:lang="eu">BCPIO dokumentua</comment>
- <comment xml:lang="fi">BCPIO-asiakirja</comment>
- <comment xml:lang="fo">BCPIO skjal</comment>
- <comment xml:lang="fr">document BCPIO</comment>
- <comment xml:lang="ga">cáipéis BCPIO</comment>
- <comment xml:lang="gl">documento BCPIO</comment>
- <comment xml:lang="he">מסמך של BCPO</comment>
- <comment xml:lang="hr">BCPIO dokument</comment>
- <comment xml:lang="hu">BCPIO-dokumentum</comment>
- <comment xml:lang="ia">Documento BCPIO</comment>
- <comment xml:lang="id">Dokumen BCPIO</comment>
- <comment xml:lang="it">Documento BCPIO</comment>
- <comment xml:lang="ja">BCPIO ドキュメント</comment>
- <comment xml:lang="ka">BCPIO-ის დოკუმენტი</comment>
- <comment xml:lang="kk">BCPIO құжаты</comment>
- <comment xml:lang="ko">BCPIO 문서</comment>
- <comment xml:lang="lt">BCPIO dokumentas</comment>
- <comment xml:lang="lv">BCPIO dokuments</comment>
- <comment xml:lang="ms">Dokumen BCPIO</comment>
- <comment xml:lang="nb">BCPIO-dokument</comment>
- <comment xml:lang="nl">BCPIO-document</comment>
- <comment xml:lang="nn">BCPIO-dokument</comment>
- <comment xml:lang="oc">document BCPIO</comment>
- <comment xml:lang="pl">Dokument BCPIO</comment>
- <comment xml:lang="pt">documento BCPIO</comment>
- <comment xml:lang="pt_BR">Documento BCPIO</comment>
- <comment xml:lang="ro">Document BCPIO</comment>
- <comment xml:lang="ru">Документ BCPIO</comment>
- <comment xml:lang="sk">Dokument BCPIO</comment>
- <comment xml:lang="sl">Dokument BCPIO</comment>
- <comment xml:lang="sq">Dokument BCPIO</comment>
- <comment xml:lang="sr">БЦПИО документ</comment>
- <comment xml:lang="sv">BCPIO-dokument</comment>
- <comment xml:lang="tr">BCPIO belgesi</comment>
- <comment xml:lang="uk">документ BCPIO</comment>
- <comment xml:lang="vi">Tài liệu BCPIO</comment>
- <comment xml:lang="zh_CN">BCPIO 文档</comment>
- <comment xml:lang="zh_TW">BCPIO 文件</comment>
+ <comment>BCPIO archive</comment>
+ <comment xml:lang="zh_CN">BCPIO 归档</comment>
+ <comment xml:lang="uk">архів BCPIO</comment>
+ <comment xml:lang="tr">BCPIO arşivi</comment>
+ <comment xml:lang="sv">BCPIO-arkiv</comment>
+ <comment xml:lang="sl">Arhiv BCPIO</comment>
+ <comment xml:lang="si">BCPIO ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív BCPIO</comment>
+ <comment xml:lang="ru">Архив BCPIO</comment>
+ <comment xml:lang="pt_BR">Arquivo BCPIO</comment>
+ <comment xml:lang="pl">Archiwum BCPIO</comment>
+ <comment xml:lang="oc">archiu BCPIO</comment>
+ <comment xml:lang="nl">BCPIO-archief</comment>
+ <comment xml:lang="ko">BCPIO 묶음 파일</comment>
+ <comment xml:lang="kk">BCPIO архиві</comment>
+ <comment xml:lang="ja">BCPIO アーカイブ</comment>
+ <comment xml:lang="it">Archivio BCPIO</comment>
+ <comment xml:lang="hr">BCPIO arhiva</comment>
+ <comment xml:lang="he">ארכיון BCPIO</comment>
+ <comment xml:lang="gl">Arquivo BCPIO</comment>
+ <comment xml:lang="fi">BCPIO-arkisto</comment>
+ <comment xml:lang="eu">BCPIO artxiboa</comment>
+ <comment xml:lang="es">archivador BCPIO</comment>
+ <comment xml:lang="en_GB">BCPIO archive</comment>
+ <comment xml:lang="de">BCPIO-Archiv</comment>
+ <comment xml:lang="be">архіў BCPIO</comment>
+ <comment xml:lang="ar">أرشيف BCPIO</comment>
<acronym>BCPIO</acronym>
<expanded-acronym>Binary CPIO</expanded-acronym>
<generic-icon name="package-x-generic"/>
@@ -7768,601 +8314,323 @@
</mime-type>
<mime-type type="application/x-bittorrent">
<comment>BitTorrent seed file</comment>
- <comment xml:lang="ar">ملف باذر البت تورنت</comment>
- <comment xml:lang="az">BitTorrent seed faylı</comment>
- <comment xml:lang="be@latin">Fajł krynicy BitTorrent</comment>
- <comment xml:lang="bg">Файл-източник — BitTorrent</comment>
- <comment xml:lang="ca">fitxer de llavor BitTorrent</comment>
- <comment xml:lang="cs">soubor BitTorrent</comment>
- <comment xml:lang="cy">Ffeil hadu BitTorrent</comment>
- <comment xml:lang="da">BitTorrent-frøfil</comment>
- <comment xml:lang="de">BitTorrent-Seed-Datei</comment>
- <comment xml:lang="el">Αρχείο BitTorrent seed</comment>
- <comment xml:lang="en_GB">BitTorrent seed file</comment>
- <comment xml:lang="eo">BitTorrent-semdosiero</comment>
- <comment xml:lang="es">archivo semilla de BitTorrent</comment>
- <comment xml:lang="eu">BitTorrent hazi-fitxategia</comment>
- <comment xml:lang="fi">BitTorrent-siementiedosto</comment>
- <comment xml:lang="fo">BitTorrent seed fíla</comment>
- <comment xml:lang="fr">fichier graine BitTorrent</comment>
- <comment xml:lang="ga">comhad síl BitTorrent</comment>
- <comment xml:lang="gl">ficheiro de orixe BitTorrent</comment>
- <comment xml:lang="he">קובץ זריעה של BitTorrent</comment>
- <comment xml:lang="hr">BitTorrent datoteka</comment>
- <comment xml:lang="hu">BitTorrent-magfájl</comment>
- <comment xml:lang="ia">File seminal de BitTorrent</comment>
- <comment xml:lang="id">Berkas benih BitTorrent</comment>
- <comment xml:lang="it">File seed BitTorrent</comment>
- <comment xml:lang="ja">BitTorrent シードファイル</comment>
- <comment xml:lang="kk">BitTorrent көз файлы</comment>
- <comment xml:lang="ko">비트토렌트 시드 파일</comment>
- <comment xml:lang="lt">BitTorrent šaltinio failas</comment>
- <comment xml:lang="lv">BitTorrent avota datne</comment>
- <comment xml:lang="ms">Fail seed BitTorrent</comment>
- <comment xml:lang="nb">Fil med utgangsverdi for BitTorrent</comment>
- <comment xml:lang="nl">BitTorrent-bestand</comment>
- <comment xml:lang="nn">Nedlastingsfil for BitTorrent</comment>
- <comment xml:lang="oc">fichièr grana BitTorrent</comment>
- <comment xml:lang="pl">Plik ziarna BitTorrent</comment>
- <comment xml:lang="pt">ficheiro de semente BitTorrent</comment>
- <comment xml:lang="pt_BR">Arquivo semente BitTorrent</comment>
- <comment xml:lang="ro">Fișier sursă-completă BitTorrent</comment>
- <comment xml:lang="ru">Файл источника BitTorrent</comment>
- <comment xml:lang="sk">Súbor BitTorrent</comment>
- <comment xml:lang="sl">Datoteka sejanja BitTorrent</comment>
- <comment xml:lang="sq">File bazë BitTorrent</comment>
- <comment xml:lang="sr">датотека сејача Бит Торента</comment>
- <comment xml:lang="sv">BitTorrent-distributionsfil</comment>
- <comment xml:lang="tr">BitTorrent tohum dosyası</comment>
- <comment xml:lang="uk">файл поширення BitTorrent</comment>
- <comment xml:lang="vi">Tải tập hạt BitTorrent</comment>
- <comment xml:lang="zh_CN">BitTorrent 种子文件</comment>
<comment xml:lang="zh_TW">BitTorrent 種子檔</comment>
- <magic priority="50">
- <match value="d8:announce" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">BitTorrent 种子文件</comment>
+ <comment xml:lang="vi">Tải tập hạt BitTorrent</comment>
+ <comment xml:lang="uk">файл поширення BitTorrent</comment>
+ <comment xml:lang="tr">BitTorrent tohum dosyası</comment>
+ <comment xml:lang="sv">BitTorrent-distributionsfil</comment>
+ <comment xml:lang="sr">датотека сејача Бит Торента</comment>
+ <comment xml:lang="sq">kartelë seed BitTorrent</comment>
+ <comment xml:lang="sl">Datoteka sejanja BitTorrent</comment>
+ <comment xml:lang="si">BitTorrent බීජ ගොනුව</comment>
+ <comment xml:lang="sk">Súbor BitTorrent</comment>
+ <comment xml:lang="ru">Файл источника BitTorrent</comment>
+ <comment xml:lang="ro">Fișier sursă-completă BitTorrent</comment>
+ <comment xml:lang="pt_BR">Arquivo semente BitTorrent</comment>
+ <comment xml:lang="pt">ficheiro de semente BitTorrent</comment>
+ <comment xml:lang="pl">Plik ziarna BitTorrent</comment>
+ <comment xml:lang="oc">fichièr grana BitTorrent</comment>
+ <comment xml:lang="nn">Nedlastingsfil for BitTorrent</comment>
+ <comment xml:lang="nl">BitTorrent-bestand</comment>
+ <comment xml:lang="nb">Fil med utgangsverdi for BitTorrent</comment>
+ <comment xml:lang="ms">Fail seed BitTorrent</comment>
+ <comment xml:lang="lv">BitTorrent avota datne</comment>
+ <comment xml:lang="lt">BitTorrent šaltinio failas</comment>
+ <comment xml:lang="ko">비트토렌트 시드 파일</comment>
+ <comment xml:lang="kk">BitTorrent көз файлы</comment>
+ <comment xml:lang="ja">BitTorrent シードファイル</comment>
+ <comment xml:lang="it">File seed BitTorrent</comment>
+ <comment xml:lang="is">BitTorrent sáningarskrá</comment>
+ <comment xml:lang="id">Berkas benih BitTorrent</comment>
+ <comment xml:lang="ia">File seminal de BitTorrent</comment>
+ <comment xml:lang="hu">BitTorrent-magfájl</comment>
+ <comment xml:lang="hr">BitTorrent datoteka</comment>
+ <comment xml:lang="he">קובץ זריעה של BitTorrent</comment>
+ <comment xml:lang="gl">ficheiro de orixe BitTorrent</comment>
+ <comment xml:lang="ga">comhad síl BitTorrent</comment>
+ <comment xml:lang="fur">file semence di BitTorrent</comment>
+ <comment xml:lang="fr">fichier graine BitTorrent</comment>
+ <comment xml:lang="fo">BitTorrent seed fíla</comment>
+ <comment xml:lang="fi">BitTorrent-siementiedosto</comment>
+ <comment xml:lang="eu">BitTorrent hazi-fitxategia</comment>
+ <comment xml:lang="es">archivo semilla de BitTorrent</comment>
+ <comment xml:lang="eo">BitTorrent-semdosiero</comment>
+ <comment xml:lang="en_GB">BitTorrent seed file</comment>
+ <comment xml:lang="el">Αρχείο BitTorrent seed</comment>
+ <comment xml:lang="de">BitTorrent-Startdatei</comment>
+ <comment xml:lang="da">BitTorrent-frøfil</comment>
+ <comment xml:lang="cy">Ffeil hadu BitTorrent</comment>
+ <comment xml:lang="cs">soubor BitTorrent</comment>
+ <comment xml:lang="ca">fitxer de llavor BitTorrent</comment>
+ <comment xml:lang="bg">Файл-източник — BitTorrent</comment>
+ <comment xml:lang="be@latin">Fajł krynicy BitTorrent</comment>
+ <comment xml:lang="be">файл раздачы BitTorrent</comment>
+ <comment xml:lang="az">BitTorrent seed faylı</comment>
+ <comment xml:lang="ar">ملف باذر بت تورنت</comment>
+ <comment xml:lang="af">BitTorrent-saadlêer</comment>
+ <magic>
+ <match type="string" value="d8:announce" offset="0"/>
</magic>
<glob pattern="*.torrent"/>
</mime-type>
<mime-type type="application/x-blender">
<comment>Blender scene</comment>
- <comment xml:lang="ar">مشهد بلندر</comment>
- <comment xml:lang="ast">Escena de Blender</comment>
- <comment xml:lang="be@latin">Scena Blender</comment>
- <comment xml:lang="bg">Сцена — Blender</comment>
- <comment xml:lang="ca">escena de Blender</comment>
- <comment xml:lang="cs">scéna Blender</comment>
- <comment xml:lang="da">Blenderscene</comment>
- <comment xml:lang="de">Blender-Szene</comment>
- <comment xml:lang="el">Σκηνή Blender</comment>
- <comment xml:lang="en_GB">Blender scene</comment>
- <comment xml:lang="eo">Blender-sceno</comment>
- <comment xml:lang="es">escena de Blender</comment>
- <comment xml:lang="eu">Blender-eko fitxategia</comment>
- <comment xml:lang="fi">Blender-näkymä</comment>
- <comment xml:lang="fo">Blender leikmynd</comment>
- <comment xml:lang="fr">scène Blender</comment>
- <comment xml:lang="ga">radharc Blender</comment>
- <comment xml:lang="gl">escena de Blender</comment>
- <comment xml:lang="he">סצנת Blender</comment>
- <comment xml:lang="hr">Blender scena</comment>
- <comment xml:lang="hu">Blender-jelenet</comment>
- <comment xml:lang="ia">Scena Blender</comment>
- <comment xml:lang="id">Scene Blender</comment>
- <comment xml:lang="it">Scena Blender</comment>
- <comment xml:lang="ja">Blender シーン</comment>
- <comment xml:lang="ka">Blender-ის სცენა</comment>
- <comment xml:lang="kk">Blender сахнасы</comment>
- <comment xml:lang="ko">Blender 장면</comment>
- <comment xml:lang="lt">Blender scena</comment>
- <comment xml:lang="lv">Blender aina</comment>
- <comment xml:lang="ms">Babak Blender</comment>
- <comment xml:lang="nb">Blender-scene</comment>
- <comment xml:lang="nl">Blender-scène</comment>
- <comment xml:lang="nn">Blender-scene</comment>
- <comment xml:lang="oc">scèna Blender</comment>
- <comment xml:lang="pl">Scena programu Blender</comment>
- <comment xml:lang="pt">cenário Blender</comment>
- <comment xml:lang="pt_BR">Cena do Blender</comment>
- <comment xml:lang="ro">Scenă Blender</comment>
- <comment xml:lang="ru">Сцена Blender</comment>
- <comment xml:lang="sk">Scéna Blender</comment>
- <comment xml:lang="sl">Datoteka scene Blender</comment>
- <comment xml:lang="sq">Skenë Blender</comment>
- <comment xml:lang="sr">Блендерова сцена</comment>
- <comment xml:lang="sv">Blender-scen</comment>
- <comment xml:lang="tr">Blender sahnesi</comment>
- <comment xml:lang="uk">сцена Blender</comment>
- <comment xml:lang="vi">Cảnh Blender</comment>
- <comment xml:lang="zh_CN">Blender 场景</comment>
<comment xml:lang="zh_TW">Blender 場景</comment>
+ <comment xml:lang="zh_CN">Blender 场景</comment>
+ <comment xml:lang="vi">Cảnh Blender</comment>
+ <comment xml:lang="uk">сцена Blender</comment>
+ <comment xml:lang="tr">Blender sahnesi</comment>
+ <comment xml:lang="sv">Blender-scen</comment>
+ <comment xml:lang="sr">Блендерова сцена</comment>
+ <comment xml:lang="sq">skenë Blender</comment>
+ <comment xml:lang="sl">Datoteka scene Blender</comment>
+ <comment xml:lang="si">බ්ලෙන්ඩර් දර්ශනය</comment>
+ <comment xml:lang="sk">Scéna Blender</comment>
+ <comment xml:lang="ru">Сцена Blender</comment>
+ <comment xml:lang="ro">Scenă Blender</comment>
+ <comment xml:lang="pt_BR">Cena do Blender</comment>
+ <comment xml:lang="pt">cenário Blender</comment>
+ <comment xml:lang="pl">Scena programu Blender</comment>
+ <comment xml:lang="oc">scèna Blender</comment>
+ <comment xml:lang="nn">Blender-scene</comment>
+ <comment xml:lang="nl">Blender-scène</comment>
+ <comment xml:lang="nb">Blender-scene</comment>
+ <comment xml:lang="ms">Babak Blender</comment>
+ <comment xml:lang="lv">Blender aina</comment>
+ <comment xml:lang="lt">Blender scena</comment>
+ <comment xml:lang="ko">Blender 장면</comment>
+ <comment xml:lang="kk">Blender сахнасы</comment>
+ <comment xml:lang="ka">Blender-ის სცენა</comment>
+ <comment xml:lang="ja">Blender シーン</comment>
+ <comment xml:lang="it">Scena Blender</comment>
+ <comment xml:lang="is">Blender sviðsmynd</comment>
+ <comment xml:lang="id">Scene Blender</comment>
+ <comment xml:lang="ia">Scena Blender</comment>
+ <comment xml:lang="hu">Blender-jelenet</comment>
+ <comment xml:lang="hr">Blender scena</comment>
+ <comment xml:lang="he">סצנת Blender</comment>
+ <comment xml:lang="gl">escena de Blender</comment>
+ <comment xml:lang="ga">radharc Blender</comment>
+ <comment xml:lang="fur">sene Blender</comment>
+ <comment xml:lang="fr">scène Blender</comment>
+ <comment xml:lang="fo">Blender leikmynd</comment>
+ <comment xml:lang="fi">Blender-näkymä</comment>
+ <comment xml:lang="eu">Blender-eko fitxategia</comment>
+ <comment xml:lang="es">escena de Blender</comment>
+ <comment xml:lang="eo">Blender-sceno</comment>
+ <comment xml:lang="en_GB">Blender scene</comment>
+ <comment xml:lang="el">Σκηνή Blender</comment>
+ <comment xml:lang="de">Blender-Szene</comment>
+ <comment xml:lang="da">Blenderscene</comment>
+ <comment xml:lang="cs">scéna Blender</comment>
+ <comment xml:lang="ca">escena de Blender</comment>
+ <comment xml:lang="bg">Сцена — Blender</comment>
+ <comment xml:lang="be@latin">Scena Blender</comment>
+ <comment xml:lang="be">сцэна Blender</comment>
+ <comment xml:lang="ast">Escena de Blender</comment>
+ <comment xml:lang="ar">مشهد بلندر</comment>
+ <comment xml:lang="af">Blender-toneel</comment>
<generic-icon name="image-x-generic"/>
- <glob pattern="*.blender"/>
<glob pattern="*.blend"/>
<glob pattern="*.BLEND"/>
- <magic priority="50">
- <match value="BLENDER" type="string" offset="0"/>
+ <glob pattern="*.blender"/>
+ <magic>
+ <match type="string" value="BLENDER" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-bzdvi">
- <comment>TeX DVI document (bzip-compressed)</comment>
- <comment xml:lang="ar">مستند TeX DVI (مضغوط-bzip)</comment>
- <comment xml:lang="ast">Documentu Tex DVI (comprimíu en bzip)</comment>
- <comment xml:lang="be@latin">Dakument TeX DVI (bzip-skampresavany)</comment>
- <comment xml:lang="bg">Документ — TeX DVI, компресиран с bzip</comment>
- <comment xml:lang="ca">document de TeX DVI (amb compressió bzip)</comment>
- <comment xml:lang="cs">dokument TeX DVI (komprimovaný pomocí bzip)</comment>
- <comment xml:lang="da">TeX DVI-dokument (bzip-komprimeret)</comment>
- <comment xml:lang="de">TeX-DVI-Dokument (bzip-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο TeX DVI (συμπιεσμένο με bzip)</comment>
- <comment xml:lang="en_GB">TeX DVI document (bzip-compressed)</comment>
- <comment xml:lang="es">documento DVI de TeX (comprimido con bzip)</comment>
- <comment xml:lang="eu">TeX DVI dokumentua (bzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">TeX DVI -asiakirja (bzip-pakattu)</comment>
- <comment xml:lang="fo">TeX DVI skjal (bzip-stappað)</comment>
- <comment xml:lang="fr">document DVI TeX (compressé bzip)</comment>
- <comment xml:lang="ga">cáipéis DVI TeX (comhbhrúite le bzip)</comment>
- <comment xml:lang="gl">documento DVI de TeX (comprimido con bzip)</comment>
- <comment xml:lang="he">מסמך מסוג TeX DVI (מכווץ ע״י bzip)</comment>
- <comment xml:lang="hr">TeX DVI dokument (bzip sažeto)</comment>
- <comment xml:lang="hu">TeX DVI dokumentum (bzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Documento TeX DVI (comprimite con bzip)</comment>
- <comment xml:lang="id">Dokumen TeX DVI (terkompresi bzip)</comment>
- <comment xml:lang="it">Documento TeX DVI (compresso con bzip)</comment>
- <comment xml:lang="ja">Tex DVI ドキュメント (bzip 圧縮)</comment>
- <comment xml:lang="kk">TeX DVI құжаты (bzip-пен сығылған)</comment>
- <comment xml:lang="ko">TeX DVI 문서(BZIP 압축)</comment>
- <comment xml:lang="lt">TeX DVI dokumentas (suglaudintas su bzip)</comment>
- <comment xml:lang="lv">TeX DVI dokuments (saspiests ar bzip)</comment>
- <comment xml:lang="nb">TeX DVI-dokument (bzip-komprimert)</comment>
- <comment xml:lang="nl">TeX DVI-document (ingepakt met bzip)</comment>
- <comment xml:lang="nn">TeX DVI-dokument (pakka med bzip)</comment>
- <comment xml:lang="oc">document DVI TeX (compressat bzip)</comment>
- <comment xml:lang="pl">Dokument TeX DVI (kompresja bzip)</comment>
- <comment xml:lang="pt">documento TeX DVI (compressão bzip)</comment>
- <comment xml:lang="pt_BR">Documento DVI TeX (compactado com bzip)</comment>
- <comment xml:lang="ro">Document TeX DVI (comprimat bzip)</comment>
- <comment xml:lang="ru">Документ TeX DVI (сжатый bzip)</comment>
- <comment xml:lang="sk">Dokument TeX DVI (komprimovaný pomocou bzip)</comment>
- <comment xml:lang="sl">Dokument TeX DVI (stisnjen z bzip)</comment>
- <comment xml:lang="sq">Dokument Tex DVI (i kompresuar me bzip)</comment>
- <comment xml:lang="sr">ТеКс ДВИ документ (запакована бзипом)</comment>
- <comment xml:lang="sv">TeX DVI-dokument (bzip-komprimerat)</comment>
- <comment xml:lang="tr">TeX DVI belgesi (bzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ TeX DVI (стиснений bzip)</comment>
- <comment xml:lang="vi">Tài liệu DVI TeX (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">TeX DVI 文档(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">TeX DVI 文件 (bzip 格式壓縮)</comment>
- <sub-class-of type="application/x-bzip"/>
+ <comment>TeX DVI document (bzip2-compressed)</comment>
+ <comment xml:lang="uk">документ DVI TeX (стиснений bzip2)</comment>
+ <comment xml:lang="sv">TeX DVI-dokument (bzip2-komprimerat)</comment>
+ <comment xml:lang="ru">Документ DVI издательской системы TeX (сжатый bzip2)</comment>
+ <comment xml:lang="pt_BR">Documento DVI TeX (compactado com bzip2)</comment>
+ <comment xml:lang="pl">Dokument TeX DVI (kompresja bzip2)</comment>
+ <comment xml:lang="es">documento DVI de TeX (comprimido con BZIP2)</comment>
+ <comment xml:lang="de">TeX-DVI-Dokument (bzip2-komprimiert)</comment>
+ <sub-class-of type="application/x-bzip2"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.dvi.bz2"/>
</mime-type>
- <mime-type type="application/x-bzip">
- <comment>Bzip archive</comment>
- <comment xml:lang="ar">أرشيف Bzip</comment>
- <comment xml:lang="ast">Archivu Bzip</comment>
- <comment xml:lang="be@latin">Archiŭ bzip</comment>
- <comment xml:lang="bg">Архив — bzip</comment>
- <comment xml:lang="ca">arxiu bzip</comment>
- <comment xml:lang="cs">archiv bzip</comment>
- <comment xml:lang="da">Bzip-arkiv</comment>
- <comment xml:lang="de">Bzip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Bzip</comment>
- <comment xml:lang="en_GB">Bzip archive</comment>
- <comment xml:lang="eo">Bzip-arkivo</comment>
- <comment xml:lang="es">archivador Bzip</comment>
- <comment xml:lang="eu">Bzip artxiboa</comment>
- <comment xml:lang="fi">Bzip-arkisto</comment>
- <comment xml:lang="fo">Bzip skjalasavn</comment>
- <comment xml:lang="fr">archive bzip</comment>
- <comment xml:lang="ga">cartlann Bzip</comment>
- <comment xml:lang="gl">arquivo Bzip</comment>
- <comment xml:lang="he">ארכיון Bzip</comment>
- <comment xml:lang="hr">Bzip arhiva</comment>
- <comment xml:lang="hu">Bzip archívum</comment>
- <comment xml:lang="ia">Archivo Bzip</comment>
- <comment xml:lang="id">Arsip Bzip</comment>
- <comment xml:lang="it">Archivio bzip</comment>
- <comment xml:lang="ja">Bzip アーカイブ</comment>
- <comment xml:lang="ka">Bzip არქივი</comment>
- <comment xml:lang="kk">Bzip архиві</comment>
- <comment xml:lang="ko">BZIP 압축 파일</comment>
- <comment xml:lang="lt">Bzip archyvas</comment>
- <comment xml:lang="lv">Bzip arhīvs</comment>
- <comment xml:lang="nb">Bzip-arkiv</comment>
- <comment xml:lang="nl">Bzip-archief</comment>
- <comment xml:lang="nn">Bzip-arkiv</comment>
- <comment xml:lang="oc">archiu bzip</comment>
- <comment xml:lang="pl">Archiwum bzip</comment>
- <comment xml:lang="pt">arquivo Bzip</comment>
- <comment xml:lang="pt_BR">Pacote Bzip</comment>
- <comment xml:lang="ro">Arhivă Bzip</comment>
- <comment xml:lang="ru">Архив BZIP</comment>
- <comment xml:lang="sk">Archív bzip</comment>
- <comment xml:lang="sl">Datoteka arhiva Bzip</comment>
- <comment xml:lang="sq">Arkiv bzip</comment>
- <comment xml:lang="sr">Бзип архива</comment>
- <comment xml:lang="sv">Bzip-arkiv</comment>
- <comment xml:lang="tr">Bzip arşivi</comment>
- <comment xml:lang="uk">архів bzip</comment>
- <comment xml:lang="vi">Kho nén bzip</comment>
- <comment xml:lang="zh_CN">Bzip 归档文件</comment>
- <comment xml:lang="zh_TW">Bzip 封存檔</comment>
+ <mime-type type="application/x-bzip1">
+ <comment>Bzip1 archive</comment>
+ <comment xml:lang="uk">архів bzip1</comment>
+ <comment xml:lang="sv">Bzip1-arkiv</comment>
+ <comment xml:lang="ru">Архив Bzip1</comment>
+ <comment xml:lang="pl">Archiwum bzip1</comment>
+ <comment xml:lang="es">archivador BZIP1</comment>
+ <comment xml:lang="de">Bzip1-Archiv</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="BZh" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="BZ0" offset="0"/>
</magic>
- <glob pattern="*.bz2"/>
<glob pattern="*.bz"/>
- <alias type="application/x-bzip2"/>
- </mime-type>
- <mime-type type="application/x-bzip-compressed-tar">
- <comment>Tar archive (bzip-compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط-bzip)</comment>
- <comment xml:lang="ast">Archivu Tar (comprimíu en bzip)</comment>
- <comment xml:lang="be@latin">Archiŭ tar (bzip-skampresavany)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран с bzip</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió bzip)</comment>
- <comment xml:lang="cs">archiv Tar (komprimovaný pomocí bzip)</comment>
- <comment xml:lang="da">Tar-arkiv (bzip-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (bzip-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με bzip)</comment>
- <comment xml:lang="en_GB">Tar archive (bzip-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con bzip)</comment>
- <comment xml:lang="eu">Tar artxiboa (bzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (bzip-pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn (bzip-stappað)</comment>
- <comment xml:lang="fr">archive tar (compressée bzip)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le bzip)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido con bzip)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י bzip)</comment>
- <comment xml:lang="hr">Tar arhiva (bzip sažeto)</comment>
- <comment xml:lang="hu">Tar archívum (bzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite con bzip)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi bzip)</comment>
- <comment xml:lang="it">Archivio tar (compresso con bzip)</comment>
- <comment xml:lang="ja">Tar アーカイブ (bzip 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (bzip-пен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(BZIP 압축)</comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas su bzip)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests ar bzip)</comment>
- <comment xml:lang="nb">Tar-arkiv (bzip-komprimert)</comment>
- <comment xml:lang="nl">Tar-archief (ingepakt met bzip)</comment>
- <comment xml:lang="nn">Tar-arkiv (pakka med bzip)</comment>
- <comment xml:lang="oc">archiu tar (compressat bzip)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja bzip)</comment>
- <comment xml:lang="pt">arquivo Tar (compressão bzip)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado com bzip)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată bzip)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый bzip)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou bzip)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z bzip)</comment>
- <comment xml:lang="sq">Arkiv tar (i kompresuar me bzip)</comment>
- <comment xml:lang="sr">Тар архива (запакована бзипом)</comment>
- <comment xml:lang="sv">Tar-arkiv (bzip-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (bzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений bzip)</comment>
- <comment xml:lang="vi">Kho nén tar (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(bzip 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (bzip 格式壓縮)</comment>
+ </mime-type>
+ <mime-type type="application/x-bzip1-compressed-tar">
+ <comment>Tar archive (bzip1-compressed)</comment>
+ <comment xml:lang="uk">архів tar (стиснений bzip1)</comment>
+ <comment xml:lang="sv">Tar-arkiv (bzip1-komprimerat)</comment>
+ <comment xml:lang="ru">Архив Tar (сжатый bzip1)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja bzip1)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con BZIP1)</comment>
+ <comment xml:lang="de">Tar-Archiv (bzip1-komprimiert)</comment>
<generic-icon name="package-x-generic"/>
- <sub-class-of type="application/x-bzip"/>
- <glob pattern="*.tar.bz2"/>
+ <sub-class-of type="application/x-bzip1"/>
<glob pattern="*.tar.bz"/>
- <glob pattern="*.tbz2"/>
<glob pattern="*.tbz"/>
+ </mime-type>
+ <mime-type type="application/x-bzip2">
+ <comment>Bzip2 archive</comment>
+ <comment xml:lang="uk">архів bzip2</comment>
+ <comment xml:lang="sv">Bzip2-arkiv</comment>
+ <comment xml:lang="ru">Архив Bzip2</comment>
+ <comment xml:lang="pt_BR">Pacote Bzip2</comment>
+ <comment xml:lang="pl">Archiwum bzip2</comment>
+ <comment xml:lang="it">Archivio bzip2</comment>
+ <comment xml:lang="gl">Arquivo Bzip2</comment>
+ <comment xml:lang="eu">Bzip2 artxiboa</comment>
+ <comment xml:lang="es">archivador BZIP2</comment>
+ <comment xml:lang="de">Bzip2-Archiv</comment>
+ <comment xml:lang="be">архіў bzip2</comment>
+ <generic-icon name="package-x-generic"/>
+ <magic>
+ <match type="string" value="BZh" offset="0"/>
+ </magic>
+ <glob pattern="*.bz2"/>
+ <alias type="application/bzip2"/>
+ <alias type="application/x-bzip"/>
+ </mime-type>
+ <mime-type type="application/x-bzip2-compressed-tar">
+ <comment>Tar archive (bzip2-compressed)</comment>
+ <comment xml:lang="uk">архів tar (стиснений bzip2)</comment>
+ <comment xml:lang="sv">Tar-arkiv (bzip2-komprimerat)</comment>
+ <comment xml:lang="ru">Архив Tar (сжатый bzip2)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja bzip2)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con BZIP2)</comment>
+ <comment xml:lang="de">Tar-Archiv (bzip2-komprimiert)</comment>
+ <generic-icon name="package-x-generic"/>
+ <sub-class-of type="application/x-bzip2"/>
+ <glob pattern="*.tar.bz2"/>
+ <glob pattern="*.tbz2"/>
<glob pattern="*.tb2"/>
+ <alias type="application/x-bzip-compressed-tar"/>
+ </mime-type>
+ <mime-type type="application/x-bzip3">
+ <comment>Bzip3 archive</comment>
+ <comment xml:lang="uk">архів bzip3</comment>
+ <comment xml:lang="sv">Bzip3-arkiv</comment>
+ <comment xml:lang="ru">Архив Bzip3</comment>
+ <comment xml:lang="pl">Archiwum bzip3</comment>
+ <comment xml:lang="it">Archivio bzip3</comment>
+ <comment xml:lang="gl">Arquivo Bzip3</comment>
+ <comment xml:lang="eu">Bzip3 artxiboa</comment>
+ <comment xml:lang="es">archivador BZIP3</comment>
+ <comment xml:lang="de">Bzip3-Archiv</comment>
+ <comment xml:lang="be">архіў bzip3</comment>
+ <generic-icon name="package-x-generic"/>
+ <magic>
+ <match type="string" value="BZ3v1" offset="0"/>
+ </magic>
+ <glob pattern="*.bz3"/>
+ </mime-type>
+ <mime-type type="application/x-bzip3-compressed-tar">
+ <comment>Tar archive (bzip3-compressed)</comment>
+ <comment xml:lang="uk">архів tar (стиснений bzip3)</comment>
+ <comment xml:lang="sv">Tar-arkiv (bzip3-komprimerat)</comment>
+ <comment xml:lang="ru">TAR Архив (сжатый bzip3)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja bzip3)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con bzip3)</comment>
+ <comment xml:lang="gl">Arquivo Tar (comprimido con bzip3)</comment>
+ <comment xml:lang="eu">Tar artxiboa (bzip3-compressed)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con BZIP3)</comment>
+ <comment xml:lang="de">Tar-Archiv (bzip3-komprimiert)</comment>
+ <comment xml:lang="be">архіў tar (сцісканне bzip3)</comment>
+ <generic-icon name="package-x-generic"/>
+ <sub-class-of type="application/x-bzip3"/>
+ <glob pattern="*.tar.bz3"/>
+ <glob pattern="*.tbz3"/>
</mime-type>
<mime-type type="application/x-bzpdf">
- <comment>PDF document (bzip-compressed)</comment>
- <comment xml:lang="ar">مستند PDF (مضغوط-bzip)</comment>
- <comment xml:lang="ast">Documentu PDF (comprimíu en bzip)</comment>
- <comment xml:lang="be@latin">Dakument PDF (bzip-skampresavany)</comment>
- <comment xml:lang="bg">Документ — PDF, компресиран с bzip</comment>
- <comment xml:lang="ca">document PDF (amb compressió bzip)</comment>
- <comment xml:lang="cs">dokument PDF (komprimovaný pomocí bzip)</comment>
- <comment xml:lang="da">PDF-dokument (bzip-komprimeret)</comment>
- <comment xml:lang="de">PDF-Dokument (bzip-komprimiert)</comment>
- <comment xml:lang="el">Έγγραφο PDF (συμπιεσμένο με bzip)</comment>
- <comment xml:lang="en_GB">PDF document (bzip-compressed)</comment>
- <comment xml:lang="es">documento PDF (comprimido con bzip)</comment>
- <comment xml:lang="eu">PostScript dokumentua (bzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">PDF-asiakirja (bzip-pakattu)</comment>
- <comment xml:lang="fo">PDF skjal (bzip-stappað)</comment>
- <comment xml:lang="fr">document PDF (compressé bzip)</comment>
- <comment xml:lang="ga">cáipéis PDF (comhbhrúite le bzip)</comment>
- <comment xml:lang="gl">documento PDF (comprimido en bzip)</comment>
- <comment xml:lang="he">מסמך PDF (מכווץ ע״י bzip)</comment>
- <comment xml:lang="hr">PDF dokument (bzip sažet)</comment>
- <comment xml:lang="hu">PDF dokumentum (bzip-tömörítésű)</comment>
- <comment xml:lang="ia">Documento PDF (comprimite con bzip)</comment>
- <comment xml:lang="id">Dokumen PDF (terkompresi bzip)</comment>
- <comment xml:lang="it">Documento PDF (compresso con bzip)</comment>
- <comment xml:lang="ja">PDF ドキュメント (bzip 圧縮)</comment>
- <comment xml:lang="kk">PDF құжаты (bzip-пен сығылған)</comment>
- <comment xml:lang="ko">PDF 문서(BZIP 압축)</comment>
- <comment xml:lang="lt">PDF dokumentas (suglaudintas su bzip)</comment>
- <comment xml:lang="lv">PDF dokuments (saspiests ar bzip)</comment>
- <comment xml:lang="nb">PDF-dokument (bzip-komprimert)</comment>
- <comment xml:lang="nl">PDF-document (ingepakt met bzip)</comment>
- <comment xml:lang="nn">PDF-dokument (pakka med bzip)</comment>
- <comment xml:lang="oc">document PDF (compressat bzip)</comment>
- <comment xml:lang="pl">Dokument PDF (kompresja bzip)</comment>
- <comment xml:lang="pt">documento PDF (compressão bzip)</comment>
- <comment xml:lang="pt_BR">Documento PDF (compactado com bzip)</comment>
- <comment xml:lang="ro">Document PDF (comprimat bzip)</comment>
- <comment xml:lang="ru">Документ PDF (сжатый bzip)</comment>
- <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou bzip)</comment>
- <comment xml:lang="sl">Dokument PDF (stisnjen z bzip)</comment>
- <comment xml:lang="sq">Dokument PDF (i kompresuar me bzip)</comment>
- <comment xml:lang="sr">ПДФ документ (запакован бзипом)</comment>
- <comment xml:lang="sv">PDF-dokument (bzip-komprimerat)</comment>
- <comment xml:lang="tr">PDF belgesi (bzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ PDF (стиснений bzip)</comment>
- <comment xml:lang="vi">Tài liệu PDF (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">PDF 文档(bzip 压缩)</comment>
- <comment xml:lang="zh_TW">PDF 文件 (bzip 格式壓縮)</comment>
- <sub-class-of type="application/x-bzip"/>
+ <comment>PDF document (bzip2-compressed)</comment>
+ <comment xml:lang="uk">документ PDF (стиснений bzip2)</comment>
+ <comment xml:lang="sv">PDF-dokument (bzip2-komprimerat)</comment>
+ <comment xml:lang="ru">Документ PDF (сжатый bzip2)</comment>
+ <comment xml:lang="pl">Dokument PDF (kompresja bzip2)</comment>
+ <comment xml:lang="es">documento PDF (comprimido con BZIP2)</comment>
+ <comment xml:lang="de">PDF-Dokument (bzip2-komprimiert)</comment>
+ <sub-class-of type="application/x-bzip2"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.pdf.bz2"/>
</mime-type>
<mime-type type="application/x-bzpostscript">
- <comment>PostScript document (bzip-compressed)</comment>
- <comment xml:lang="ar">مستند PostScript (مضغوط-bzip)</comment>
- <comment xml:lang="ast">Documentu PostScript (comprimíu en bzip)</comment>
- <comment xml:lang="be@latin">Dakument PostScript (bzip-skampresavany)</comment>
- <comment xml:lang="bg">Документ — PostScript, компресиран с bzip</comment>
- <comment xml:lang="ca">document PostScript (amb compressió bzip)</comment>
- <comment xml:lang="cs">dokument PostScript (komprimovaný pomocí bzip)</comment>
- <comment xml:lang="da">PostScript-dokument (bzip-komprimeret)</comment>
- <comment xml:lang="de">PostScript-Dokument (bzip-komprimiert)</comment>
- <comment xml:lang="el">Έγγραφο PostScript (συμπιεσμένο με bzip)</comment>
- <comment xml:lang="en_GB">PostScript document (bzip-compressed)</comment>
- <comment xml:lang="es">documento PostScript (comprimido con bzip)</comment>
- <comment xml:lang="eu">PostScript dokumentua (bzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">PostScript-asiakirja (bzip-pakattu)</comment>
- <comment xml:lang="fo">PostScript skjal (bzip-stappað)</comment>
- <comment xml:lang="fr">document PostScript (compressé bzip)</comment>
- <comment xml:lang="ga">cáipéis PostScript (comhbhrúite le bzip)</comment>
- <comment xml:lang="gl">documento PostScript (comprimido con bzip)</comment>
- <comment xml:lang="he">מסמך PostDcript (מכווץ ע״י bzip)</comment>
- <comment xml:lang="hr">PostScript dokument (bzip sažet)</comment>
- <comment xml:lang="hu">PostScript dokumentum (bzip-tömörítésű)</comment>
- <comment xml:lang="ia">Documento PostScript (comprimite con bzip)</comment>
- <comment xml:lang="id">Dokumen PostScript (terkompresi bzip)</comment>
- <comment xml:lang="it">Documento PostScript (compresso con bzip)</comment>
- <comment xml:lang="ja">PostScript ドキュメント (bzip 圧縮)</comment>
- <comment xml:lang="kk">PostScript құжаты (bzip-пен сығылған)</comment>
- <comment xml:lang="ko">PostScript 문서(BZIP 압축)</comment>
- <comment xml:lang="lt">PostScript dokumentas (suglaudintas su bzip)</comment>
- <comment xml:lang="lv">PostScript dokuments (saspiests ar bzip)</comment>
- <comment xml:lang="nb">PostScript-dokument (bzip-komprimert)</comment>
- <comment xml:lang="nl">PostScript-document (ingepakt met bzip)</comment>
- <comment xml:lang="nn">PostScript-dokument (pakka med bzip)</comment>
- <comment xml:lang="oc">document PostEscript (compressat bzip)</comment>
- <comment xml:lang="pl">Dokument Postscript (kompresja bzip)</comment>
- <comment xml:lang="pt">documento PostScript (compressão bzip)</comment>
- <comment xml:lang="pt_BR">Documento PostScript (compactado com bzip)</comment>
- <comment xml:lang="ro">Document PostScript (comprimat bzip)</comment>
- <comment xml:lang="ru">Документ PostScript (сжатый bzip)</comment>
- <comment xml:lang="sk">Dokument PostScript (komprimovaný pomocou bzip)</comment>
- <comment xml:lang="sl">Dokument PostScript (stisnjen z bzip)</comment>
- <comment xml:lang="sq">Dokument PostScript (i kompresuar me bzip)</comment>
- <comment xml:lang="sr">Постскрипт документ (запакован бзипом)</comment>
- <comment xml:lang="sv">Postscript-dokument (bzip-komprimerat)</comment>
- <comment xml:lang="tr">PostScript belgesi (bzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ PostScript (стиснене bzip)</comment>
- <comment xml:lang="vi">Tài liệu PostScript (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">PostScript 文档(bzip 压缩)</comment>
- <comment xml:lang="zh_TW">PostScript 文件 (bzip 格式壓縮)</comment>
- <sub-class-of type="application/x-bzip"/>
+ <comment>PostScript document (bzip2-compressed)</comment>
+ <comment xml:lang="uk">документ PostScript (стиснений bzip2)</comment>
+ <comment xml:lang="sv">Postscript-dokument (bzip2-komprimerat)</comment>
+ <comment xml:lang="ru">Документ PostScript (сжатый bzip2)</comment>
+ <comment xml:lang="pl">Dokument PostScript (kompresja bzip2)</comment>
+ <comment xml:lang="es">documento PostScript (comprimido con BZIP2)</comment>
+ <comment xml:lang="de">PostScript-Dokument (bzip2-komprimiert)</comment>
+ <sub-class-of type="application/x-bzip2"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.ps.bz2"/>
</mime-type>
<mime-type type="application/vnd.comicbook-rar">
- <comment>comic book archive</comment>
- <comment xml:lang="ar">أرشيف comic book</comment>
- <comment xml:lang="be@latin">archiŭ komiksaŭ</comment>
- <comment xml:lang="bg">Архив — комикси</comment>
- <comment xml:lang="ca">arxiu comic book</comment>
- <comment xml:lang="cs">archiv knihy komiksů</comment>
- <comment xml:lang="da">comic book-arkiv</comment>
- <comment xml:lang="de">Comic-Book-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο κόμικ</comment>
- <comment xml:lang="en_GB">comic book archive</comment>
- <comment xml:lang="es">archivador de libro de cómic</comment>
- <comment xml:lang="eu">komiki artxiboa</comment>
- <comment xml:lang="fi">sarjakuva-arkisto</comment>
- <comment xml:lang="fo">teknisøgubóka skjalasavn</comment>
- <comment xml:lang="fr">archive Comic Book</comment>
- <comment xml:lang="ga">cartlann chartúin</comment>
- <comment xml:lang="gl">ficheiro de libro de banda deseñada</comment>
- <comment xml:lang="he">ארכיון ספר קומי</comment>
- <comment xml:lang="hr">Strip arhiva</comment>
- <comment xml:lang="hu">képregényarchívum</comment>
- <comment xml:lang="ia">Archivo Comic Book</comment>
- <comment xml:lang="id">arsip buku komik</comment>
- <comment xml:lang="it">Archivio comic book</comment>
- <comment xml:lang="ja">コミックブックアーカイブ</comment>
- <comment xml:lang="kk">комикстар архиві</comment>
- <comment xml:lang="ko">만화책 압축 파일</comment>
- <comment xml:lang="lt">komiksų knygos archyvas</comment>
- <comment xml:lang="lv">komiksu grāmatas arhīvs</comment>
- <comment xml:lang="nb">Tegneseriearkiv</comment>
- <comment xml:lang="nl">stripboek-archief</comment>
- <comment xml:lang="nn">teikneseriearkiv</comment>
- <comment xml:lang="oc">archiu Comic Book</comment>
- <comment xml:lang="pl">Archiwum komiksu</comment>
- <comment xml:lang="pt">arquivo de banda desenhada</comment>
- <comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
- <comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">Архив комиксов</comment>
- <comment xml:lang="sk">Archív knihy komiksov</comment>
- <comment xml:lang="sl">Datoteka arhiva stripov</comment>
- <comment xml:lang="sq">Arkiv comic book</comment>
- <comment xml:lang="sr">архива стрипа</comment>
- <comment xml:lang="sv">serietidningsarkiv</comment>
- <comment xml:lang="tr">çizgi roman arşivi</comment>
- <comment xml:lang="uk">архів коміксів</comment>
- <comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">漫画书归档文件</comment>
- <comment xml:lang="zh_TW">漫畫書封存檔</comment>
+ <comment>Comic book archive (rar container)</comment>
+ <comment xml:lang="uk">архів коміксів (контейнер rar)</comment>
+ <comment xml:lang="sv">Serietidningsarkiv (rar-behållare)</comment>
+ <comment xml:lang="ru">Архив комиксов (rar-контейнер)</comment>
+ <comment xml:lang="pl">Archiwum komiksu (kontener RAR)</comment>
+ <comment xml:lang="it">Archivio comic book (contenitore rar)</comment>
+ <comment xml:lang="gl">Arquivo de libro de banda deseñada (contedor rar)</comment>
+ <comment xml:lang="es">archivador de libro de historietas (contenedor RAR)</comment>
+ <comment xml:lang="de">Comic-Book-Archiv (rar-Container)</comment>
+ <comment xml:lang="be">архіў comic book (кантэйнер rar)</comment>
<sub-class-of type="application/vnd.rar"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.cbr"/>
<alias type="application/x-cbr"/>
</mime-type>
<mime-type type="application/x-cb7">
- <comment>comic book archive</comment>
- <comment xml:lang="ar">أرشيف comic book</comment>
- <comment xml:lang="be@latin">archiŭ komiksaŭ</comment>
- <comment xml:lang="bg">Архив — комикси</comment>
- <comment xml:lang="ca">arxiu comic book</comment>
- <comment xml:lang="cs">archiv knihy komiksů</comment>
- <comment xml:lang="da">comic book-arkiv</comment>
- <comment xml:lang="de">Comic-Book-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο κόμικ</comment>
- <comment xml:lang="en_GB">comic book archive</comment>
- <comment xml:lang="es">archivador de libro de cómic</comment>
- <comment xml:lang="eu">komiki artxiboa</comment>
- <comment xml:lang="fi">sarjakuva-arkisto</comment>
- <comment xml:lang="fo">teknisøgubóka skjalasavn</comment>
- <comment xml:lang="fr">archive Comic Book</comment>
- <comment xml:lang="ga">cartlann chartúin</comment>
- <comment xml:lang="gl">ficheiro de libro de banda deseñada</comment>
- <comment xml:lang="he">ארכיון ספר קומי</comment>
- <comment xml:lang="hr">Strip arhiva</comment>
- <comment xml:lang="hu">képregényarchívum</comment>
- <comment xml:lang="ia">Archivo Comic Book</comment>
- <comment xml:lang="id">arsip buku komik</comment>
- <comment xml:lang="it">Archivio comic book</comment>
- <comment xml:lang="ja">コミックブックアーカイブ</comment>
- <comment xml:lang="kk">комикстар архиві</comment>
- <comment xml:lang="ko">만화책 압축 파일</comment>
- <comment xml:lang="lt">komiksų knygos archyvas</comment>
- <comment xml:lang="lv">komiksu grāmatas arhīvs</comment>
- <comment xml:lang="nb">Tegneseriearkiv</comment>
- <comment xml:lang="nl">stripboek-archief</comment>
- <comment xml:lang="nn">teikneseriearkiv</comment>
- <comment xml:lang="oc">archiu Comic Book</comment>
- <comment xml:lang="pl">Archiwum komiksu</comment>
- <comment xml:lang="pt">arquivo de banda desenhada</comment>
- <comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
- <comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">Архив комиксов</comment>
- <comment xml:lang="sk">Archív knihy komiksov</comment>
- <comment xml:lang="sl">Datoteka arhiva stripov</comment>
- <comment xml:lang="sq">Arkiv comic book</comment>
- <comment xml:lang="sr">архива стрипа</comment>
- <comment xml:lang="sv">serietidningsarkiv</comment>
- <comment xml:lang="tr">çizgi roman arşivi</comment>
- <comment xml:lang="uk">архів коміксів</comment>
- <comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">漫画书归档文件</comment>
- <comment xml:lang="zh_TW">漫畫書封存檔</comment>
+ <comment>Comic book archive (7z container)</comment>
+ <comment xml:lang="uk">архів коміксів (контейнер 7z)</comment>
+ <comment xml:lang="sv">Serietidningsarkiv (7z-behållare)</comment>
+ <comment xml:lang="ru">Архив комиксов (7z-контейнер)</comment>
+ <comment xml:lang="pl">Archiwum komiksu (kontener 7z)</comment>
+ <comment xml:lang="it">Archivio comic book (contenitore 7z)</comment>
+ <comment xml:lang="gl">Arquivo de libro de banda deseñada (contedor 7z)</comment>
+ <comment xml:lang="es">archivador de libro de historietas (contenedor 7Z)</comment>
+ <comment xml:lang="de">Comic-Book-Archiv (7z-Container)</comment>
+ <comment xml:lang="be">архіў comic book (кантэйнер 7z)</comment>
<sub-class-of type="application/x-7z-compressed"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.cb7"/>
</mime-type>
<mime-type type="application/x-cbt">
- <comment>comic book archive</comment>
- <comment xml:lang="ar">أرشيف comic book</comment>
- <comment xml:lang="be@latin">archiŭ komiksaŭ</comment>
- <comment xml:lang="bg">Архив — комикси</comment>
- <comment xml:lang="ca">arxiu comic book</comment>
- <comment xml:lang="cs">archiv knihy komiksů</comment>
- <comment xml:lang="da">comic book-arkiv</comment>
- <comment xml:lang="de">Comic-Book-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο κόμικ</comment>
- <comment xml:lang="en_GB">comic book archive</comment>
- <comment xml:lang="es">archivador de libro de cómic</comment>
- <comment xml:lang="eu">komiki artxiboa</comment>
- <comment xml:lang="fi">sarjakuva-arkisto</comment>
- <comment xml:lang="fo">teknisøgubóka skjalasavn</comment>
- <comment xml:lang="fr">archive Comic Book</comment>
- <comment xml:lang="ga">cartlann chartúin</comment>
- <comment xml:lang="gl">ficheiro de libro de banda deseñada</comment>
- <comment xml:lang="he">ארכיון ספר קומי</comment>
- <comment xml:lang="hr">Strip arhiva</comment>
- <comment xml:lang="hu">képregényarchívum</comment>
- <comment xml:lang="ia">Archivo Comic Book</comment>
- <comment xml:lang="id">arsip buku komik</comment>
- <comment xml:lang="it">Archivio comic book</comment>
- <comment xml:lang="ja">コミックブックアーカイブ</comment>
- <comment xml:lang="kk">комикстар архиві</comment>
- <comment xml:lang="ko">만화책 압축 파일</comment>
- <comment xml:lang="lt">komiksų knygos archyvas</comment>
- <comment xml:lang="lv">komiksu grāmatas arhīvs</comment>
- <comment xml:lang="nb">Tegneseriearkiv</comment>
- <comment xml:lang="nl">stripboek-archief</comment>
- <comment xml:lang="nn">teikneseriearkiv</comment>
- <comment xml:lang="oc">archiu Comic Book</comment>
- <comment xml:lang="pl">Archiwum komiksu</comment>
- <comment xml:lang="pt">arquivo de banda desenhada</comment>
- <comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
- <comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">Архив комиксов</comment>
- <comment xml:lang="sk">Archív knihy komiksov</comment>
- <comment xml:lang="sl">Datoteka arhiva stripov</comment>
- <comment xml:lang="sq">Arkiv comic book</comment>
- <comment xml:lang="sr">архива стрипа</comment>
- <comment xml:lang="sv">serietidningsarkiv</comment>
- <comment xml:lang="tr">çizgi roman arşivi</comment>
- <comment xml:lang="uk">архів коміксів</comment>
- <comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">漫画书归档文件</comment>
- <comment xml:lang="zh_TW">漫畫書封存檔</comment>
+ <comment>Comic book archive (tar container)</comment>
+ <comment xml:lang="uk">архів коміксів (контейнер tar)</comment>
+ <comment xml:lang="sv">Serietidningsarkiv (tar-behållare)</comment>
+ <comment xml:lang="ru">Архив комиксов (tar-контейнер)</comment>
+ <comment xml:lang="pl">Archiwum komiksu (kontener tar)</comment>
+ <comment xml:lang="it">Archivio comic book (contenitore tar)</comment>
+ <comment xml:lang="gl">Arquivo de libro de banda deseñada (contedor tar)</comment>
+ <comment xml:lang="es">archivador de libro de historietas (contenedor TAR)</comment>
+ <comment xml:lang="de">Comic-Book-Archiv (tar-Container)</comment>
+ <comment xml:lang="be">архіў comic book (кантэйнер tar)</comment>
<sub-class-of type="application/x-tar"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.cbt"/>
</mime-type>
<mime-type type="application/vnd.comicbook+zip">
- <comment>comic book archive</comment>
- <comment xml:lang="ar">أرشيف comic book</comment>
- <comment xml:lang="be@latin">archiŭ komiksaŭ</comment>
- <comment xml:lang="bg">Архив — комикси</comment>
- <comment xml:lang="ca">arxiu comic book</comment>
- <comment xml:lang="cs">archiv knihy komiksů</comment>
- <comment xml:lang="da">comic book-arkiv</comment>
- <comment xml:lang="de">Comic-Book-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο κόμικ</comment>
- <comment xml:lang="en_GB">comic book archive</comment>
- <comment xml:lang="es">archivador de libro de cómic</comment>
- <comment xml:lang="eu">komiki artxiboa</comment>
- <comment xml:lang="fi">sarjakuva-arkisto</comment>
- <comment xml:lang="fo">teknisøgubóka skjalasavn</comment>
- <comment xml:lang="fr">archive Comic Book</comment>
- <comment xml:lang="ga">cartlann chartúin</comment>
- <comment xml:lang="gl">ficheiro de libro de banda deseñada</comment>
- <comment xml:lang="he">ארכיון ספר קומי</comment>
- <comment xml:lang="hr">Strip arhiva</comment>
- <comment xml:lang="hu">képregényarchívum</comment>
- <comment xml:lang="ia">Archivo Comic Book</comment>
- <comment xml:lang="id">arsip buku komik</comment>
- <comment xml:lang="it">Archivio comic book</comment>
- <comment xml:lang="ja">コミックブックアーカイブ</comment>
- <comment xml:lang="kk">комикстар архиві</comment>
- <comment xml:lang="ko">만화책 압축 파일</comment>
- <comment xml:lang="lt">komiksų knygos archyvas</comment>
- <comment xml:lang="lv">komiksu grāmatas arhīvs</comment>
- <comment xml:lang="nb">Tegneseriearkiv</comment>
- <comment xml:lang="nl">stripboek-archief</comment>
- <comment xml:lang="nn">teikneseriearkiv</comment>
- <comment xml:lang="oc">archiu Comic Book</comment>
- <comment xml:lang="pl">Archiwum komiksu</comment>
- <comment xml:lang="pt">arquivo de banda desenhada</comment>
- <comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
- <comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">Архив комиксов</comment>
- <comment xml:lang="sk">Archív knihy komiksov</comment>
- <comment xml:lang="sl">Datoteka arhiva stripov</comment>
- <comment xml:lang="sq">Arkiv comic book</comment>
- <comment xml:lang="sr">архива стрипа</comment>
- <comment xml:lang="sv">serietidningsarkiv</comment>
- <comment xml:lang="tr">çizgi roman arşivi</comment>
- <comment xml:lang="uk">архів коміксів</comment>
- <comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">漫画书归档文件</comment>
- <comment xml:lang="zh_TW">漫畫書封存檔</comment>
+ <comment>Comic book archive (zip container)</comment>
+ <comment xml:lang="uk">архів коміксів (контейнер zip)</comment>
+ <comment xml:lang="sv">Serietidningsarkiv (zip-behållare)</comment>
+ <comment xml:lang="ru">Архив комиксов (zip-контейнер)</comment>
+ <comment xml:lang="pl">Archiwum komiksu (kontener ZIP)</comment>
+ <comment xml:lang="it">Archivio comic book (contenitore zip)</comment>
+ <comment xml:lang="gl">Arquivo de libro de banda deseñada (contedor zip)</comment>
+ <comment xml:lang="es">archivador de libro de historietas (contenedor ZIP)</comment>
+ <comment xml:lang="de">Comic-Book-Archiv (zip-Container)</comment>
+ <comment xml:lang="be">архіў comic book (кантэйнер zip)</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.cbz"/>
@@ -8370,97 +8638,111 @@
</mime-type>
<mime-type type="application/x-lrzip">
<comment>Lrzip archive</comment>
- <comment xml:lang="ar">أرشيف Lrzip</comment>
- <comment xml:lang="bg">Архив — lrzip</comment>
- <comment xml:lang="ca">arxiu lrzip</comment>
- <comment xml:lang="cs">archiv Lrzip</comment>
- <comment xml:lang="da">Lrzip-arkiv</comment>
- <comment xml:lang="de">Lrzip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Lrzip</comment>
- <comment xml:lang="en_GB">Lrzip archive</comment>
- <comment xml:lang="eo">Lrzip-arkivo</comment>
- <comment xml:lang="es">archivador Lrzip</comment>
- <comment xml:lang="eu">Lrzip artxiboa</comment>
- <comment xml:lang="fi">Lrzip-arkisto</comment>
- <comment xml:lang="fo">Lrzip skjalasavn</comment>
- <comment xml:lang="fr">archive lrzip</comment>
- <comment xml:lang="ga">cartlann Lrzip</comment>
- <comment xml:lang="gl">arquivo Lrzip</comment>
- <comment xml:lang="he">ארכיון Lrzip</comment>
- <comment xml:lang="hr">Lrzip arhiva</comment>
- <comment xml:lang="hu">Lrzip archívum</comment>
- <comment xml:lang="ia">Archivo Lrzip</comment>
- <comment xml:lang="id">Arsip Lrzip</comment>
- <comment xml:lang="it">Archivio Lrzip</comment>
- <comment xml:lang="ja">Lrzip アーカイブ</comment>
- <comment xml:lang="kk">Lrzip архиві</comment>
- <comment xml:lang="ko">LRZIP 압축 파일</comment>
- <comment xml:lang="lt">Lrzip archyvas</comment>
- <comment xml:lang="lv">Lrzip arhīvs</comment>
- <comment xml:lang="nl">Lrzip archief</comment>
- <comment xml:lang="oc">archiu lrzip</comment>
- <comment xml:lang="pl">Archiwum lrzip</comment>
- <comment xml:lang="pt">arquivo Lrzip</comment>
- <comment xml:lang="pt_BR">Pacote Lrzip</comment>
- <comment xml:lang="ro">Arhivă Lrzip</comment>
- <comment xml:lang="ru">Архив LRZIP</comment>
- <comment xml:lang="sk">Archív Lrzip</comment>
- <comment xml:lang="sl">Datoteka arhiva Lrzip</comment>
- <comment xml:lang="sr">Лрзип архива</comment>
- <comment xml:lang="sv">Lrzip-arkiv</comment>
- <comment xml:lang="tr">Lrzip arşivi</comment>
- <comment xml:lang="uk">архів lrzip</comment>
- <comment xml:lang="zh_CN">Lrzip 归档文件</comment>
<comment xml:lang="zh_TW">Lrzip 封存檔</comment>
+ <comment xml:lang="zh_CN">Lrzip 归档文件</comment>
+ <comment xml:lang="uk">архів lrzip</comment>
+ <comment xml:lang="tr">Lrzip arşivi</comment>
+ <comment xml:lang="sv">Lrzip-arkiv</comment>
+ <comment xml:lang="sr">Лрзип архива</comment>
+ <comment xml:lang="sq">arkiv Lrzip</comment>
+ <comment xml:lang="sl">Datoteka arhiva Lrzip</comment>
+ <comment xml:lang="si">Lrzip සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Lrzip</comment>
+ <comment xml:lang="ru">Архив LRZIP</comment>
+ <comment xml:lang="ro">Arhivă Lrzip</comment>
+ <comment xml:lang="pt_BR">Pacote Lrzip</comment>
+ <comment xml:lang="pt">arquivo Lrzip</comment>
+ <comment xml:lang="pl">Archiwum lrzip</comment>
+ <comment xml:lang="oc">archiu lrzip</comment>
+ <comment xml:lang="nl">Lrzip-archief</comment>
+ <comment xml:lang="lv">Lrzip arhīvs</comment>
+ <comment xml:lang="lt">Lrzip archyvas</comment>
+ <comment xml:lang="ko">LRZIP 압축 파일</comment>
+ <comment xml:lang="kk">Lrzip архиві</comment>
+ <comment xml:lang="ja">Lrzip アーカイブ</comment>
+ <comment xml:lang="it">Archivio Lrzip</comment>
+ <comment xml:lang="is">Lrzip safnskrá</comment>
+ <comment xml:lang="id">Arsip Lrzip</comment>
+ <comment xml:lang="ia">Archivo Lrzip</comment>
+ <comment xml:lang="hu">Lrzip archívum</comment>
+ <comment xml:lang="hr">Lrzip arhiva</comment>
+ <comment xml:lang="he">ארכיון Lrzip</comment>
+ <comment xml:lang="gl">arquivo Lrzip</comment>
+ <comment xml:lang="ga">cartlann Lrzip</comment>
+ <comment xml:lang="fur">archivi Lrzip</comment>
+ <comment xml:lang="fr">archive lrzip</comment>
+ <comment xml:lang="fo">Lrzip skjalasavn</comment>
+ <comment xml:lang="fi">Lrzip-arkisto</comment>
+ <comment xml:lang="eu">Lrzip artxiboa</comment>
+ <comment xml:lang="es">archivador LRZIP</comment>
+ <comment xml:lang="eo">Lrzip-arkivo</comment>
+ <comment xml:lang="en_GB">Lrzip archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Lrzip</comment>
+ <comment xml:lang="de">Lrzip-Archiv</comment>
+ <comment xml:lang="da">Lrzip-arkiv</comment>
+ <comment xml:lang="cs">archiv Lrzip</comment>
+ <comment xml:lang="ca">arxiu lrzip</comment>
+ <comment xml:lang="bg">Архив — lrzip</comment>
+ <comment xml:lang="be">архіў Lrzip</comment>
+ <comment xml:lang="ar">أرشيف Lrzip</comment>
+ <comment xml:lang="af">Lrzip-argief</comment>
+ <acronym>Lrzip</acronym>
+ <expanded-acronym>Long Range Zip</expanded-acronym>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="LRZI" type="string" offset="0"/>
+ <match type="string" value="LRZI" offset="0"/>
</magic>
<glob pattern="*.lrz"/>
</mime-type>
<mime-type type="application/x-lrzip-compressed-tar">
<comment>Tar archive (lrzip-compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط-lrzip)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран с lrzip</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió lrzip)</comment>
- <comment xml:lang="cs">archiv Tar (komprimovaný pomocí lrzip)</comment>
- <comment xml:lang="da">Tar-arkiv (lrzip-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (lrzip-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με lrzip)</comment>
- <comment xml:lang="en_GB">Tar archive (lrzip-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con lrzip)</comment>
- <comment xml:lang="eu">Tar artxiboa (lrzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (lrzip-pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn (lrzip-stappað)</comment>
- <comment xml:lang="fr">archive tar (compressée lrzip)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le lrzip)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido con lrzip)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י lrzip)</comment>
- <comment xml:lang="hr">Tar arhiva (lrzip sažeta)</comment>
- <comment xml:lang="hu">Tar archívum (lrzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite con lrzip)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi lrzip)</comment>
- <comment xml:lang="it">Archivio tar (compresso con lrzip)</comment>
- <comment xml:lang="ja">Tar アーカイブ (lrzip 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (lrzip-пен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(LRZIP 압축)</comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas su lrzip)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests ar lrzip)</comment>
- <comment xml:lang="nl">Tar archief (lrzip-compressed)</comment>
- <comment xml:lang="oc">archiu tar (compressat lrzip)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja lrzip)</comment>
- <comment xml:lang="pt">arquivo Tar (compressão Lrzip)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado com lrzip)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată lrzip)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый lrzip)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou lrzip)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z lrzip)</comment>
- <comment xml:lang="sr">Тар архива (запакована лрзипом)</comment>
- <comment xml:lang="sv">Tar-arkiv (lrzip-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (lrzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений lrzip)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(lrzip 压缩)</comment>
<comment xml:lang="zh_TW">Tar 封存檔 (lrzip 格式壓縮)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(lrzip 压缩)</comment>
+ <comment xml:lang="uk">архів tar (стиснений lrzip)</comment>
+ <comment xml:lang="tr">Tar arşivi (lrzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (lrzip-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована лрзипом)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me lrzip)</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z lrzip)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (lrzip-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou lrzip)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый lrzip)</comment>
+ <comment xml:lang="ro">Arhivă Tar (comprimată lrzip)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado com lrzip)</comment>
+ <comment xml:lang="pt">arquivo Tar (compressão Lrzip)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja lrzip)</comment>
+ <comment xml:lang="oc">archiu tar (compressat lrzip)</comment>
+ <comment xml:lang="nl">Tar-archief (gecomprimeerd met lrzip)</comment>
+ <comment xml:lang="lv">Tar arhīvs (saspiests ar lrzip)</comment>
+ <comment xml:lang="lt">Tar archyvas (suglaudintas su lrzip)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(LRZIP 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (lrzip-пен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (lrzip 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con lrzip)</comment>
+ <comment xml:lang="is">Tar safnskrá (lrzip-þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi lrzip)</comment>
+ <comment xml:lang="ia">Archivo Tar (comprimite con lrzip)</comment>
+ <comment xml:lang="hu">Tar archívum (lrzip tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (lrzip sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י lrzip)</comment>
+ <comment xml:lang="gl">arquivo Tar (comprimido con lrzip)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le lrzip)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun lrzip)</comment>
+ <comment xml:lang="fr">archive tar (compressée lrzip)</comment>
+ <comment xml:lang="fo">Tar skjalasavn (lrzip-stappað)</comment>
+ <comment xml:lang="fi">Tar-arkisto (lrzip-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (lrzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con LRZIP)</comment>
+ <comment xml:lang="en_GB">Tar archive (lrzip-compressed)</comment>
+ <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με lrzip)</comment>
+ <comment xml:lang="de">Tar-Archiv (lrzip-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (lrzip-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimovaný pomocí lrzip)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió lrzip)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с lrzip</comment>
+ <comment xml:lang="be">архіў tar (сцісканне lrzip)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-lrzip)</comment>
+ <comment xml:lang="af">Tar-argief (lrzip-saamgepers)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-lrzip"/>
<glob pattern="*.tar.lrz"/>
@@ -8468,223 +8750,309 @@
</mime-type>
<mime-type type="application/x-apple-diskimage">
<comment>Apple disk image</comment>
- <comment xml:lang="ast">Imaxe de discu d'Apple</comment>
- <comment xml:lang="bg">Диск — Apple</comment>
- <comment xml:lang="ca">imatge de disc d'Apple</comment>
- <comment xml:lang="cs">obraz disku Apple</comment>
- <comment xml:lang="da">Apple-diskaftryk</comment>
- <comment xml:lang="de">Apple-Datenträgerabbild</comment>
- <comment xml:lang="el">Εικόνα δίσκου Apple</comment>
- <comment xml:lang="en_GB">Apple disk image</comment>
- <comment xml:lang="es">imagen de disco de Apple</comment>
- <comment xml:lang="eu">Apple disko irudia</comment>
- <comment xml:lang="fi">Apple-levytiedosto</comment>
- <comment xml:lang="fr">image disque Apple</comment>
- <comment xml:lang="ga">íomhá diosca Apple</comment>
- <comment xml:lang="gl">imaxe de disco de Appl</comment>
- <comment xml:lang="he">תמונת כונן Apple</comment>
- <comment xml:lang="hr">Apple slika diska</comment>
- <comment xml:lang="hu">Apple lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco Apple</comment>
- <comment xml:lang="id">Image disk Apple</comment>
- <comment xml:lang="it">Immagine disco Apple</comment>
- <comment xml:lang="ja">Apple ディスクイメージ</comment>
- <comment xml:lang="ka">Apple-ის სადისკო გამოსახულება</comment>
- <comment xml:lang="kk">Apple диск бейнесі</comment>
- <comment xml:lang="ko">Apple 디스크 이미지</comment>
- <comment xml:lang="lv">Apple diska attēls</comment>
- <comment xml:lang="nl">Apple disk image</comment>
- <comment xml:lang="oc">imatge disc Apple</comment>
- <comment xml:lang="pl">Obraz dysku Apple</comment>
- <comment xml:lang="pt">imagem de disco Apple</comment>
- <comment xml:lang="pt_BR">Imagem de disco Apple</comment>
- <comment xml:lang="ru">Образ диска Apple Mac OS X</comment>
- <comment xml:lang="sk">Obraz disku Apple</comment>
- <comment xml:lang="sl">Odtis diska Apple</comment>
- <comment xml:lang="sr">Еплов одраз диска</comment>
- <comment xml:lang="sv">Apple-diskavbild</comment>
- <comment xml:lang="tr">Apple disk görüntüsü</comment>
- <comment xml:lang="uk">образ диска Apple</comment>
- <comment xml:lang="zh_CN">Apple 磁盘映像</comment>
<comment xml:lang="zh_TW">Apple 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">Apple 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска Apple</comment>
+ <comment xml:lang="tr">Apple disk görüntüsü</comment>
+ <comment xml:lang="sv">Apple-diskavbild</comment>
+ <comment xml:lang="sr">Еплов одраз диска</comment>
+ <comment xml:lang="sq">pamje disku Apple</comment>
+ <comment xml:lang="sl">Odtis diska Apple</comment>
+ <comment xml:lang="si">ඇපල් තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku Apple</comment>
+ <comment xml:lang="ru">Образ диска Apple Mac OS X</comment>
+ <comment xml:lang="pt_BR">Imagem de disco Apple</comment>
+ <comment xml:lang="pt">imagem de disco Apple</comment>
+ <comment xml:lang="pl">Obraz dysku Apple</comment>
+ <comment xml:lang="oc">imatge disc Apple</comment>
+ <comment xml:lang="nl">Apple-schijfkopiebestand</comment>
+ <comment xml:lang="lv">Apple diska attēls</comment>
+ <comment xml:lang="ko">Apple 디스크 이미지</comment>
+ <comment xml:lang="kk">Apple диск бейнесі</comment>
+ <comment xml:lang="ka">Apple-ის სადისკო გამოსახულება</comment>
+ <comment xml:lang="ja">Apple ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco Apple</comment>
+ <comment xml:lang="is">Apple diskmynd</comment>
+ <comment xml:lang="id">Image disk Apple</comment>
+ <comment xml:lang="ia">Imagine de disco Apple</comment>
+ <comment xml:lang="hu">Apple lemezkép</comment>
+ <comment xml:lang="hr">Apple slika diska</comment>
+ <comment xml:lang="he">תמונת כונן Apple</comment>
+ <comment xml:lang="gl">imaxe de disco de Appl</comment>
+ <comment xml:lang="ga">íomhá diosca Apple</comment>
+ <comment xml:lang="fur">imagjin disc Apple</comment>
+ <comment xml:lang="fr">image disque Apple</comment>
+ <comment xml:lang="fi">Apple-levykuva</comment>
+ <comment xml:lang="eu">Apple disko irudia</comment>
+ <comment xml:lang="es">imagen de disco de Apple</comment>
+ <comment xml:lang="en_GB">Apple disk image</comment>
+ <comment xml:lang="el">Εικόνα δίσκου Apple</comment>
+ <comment xml:lang="de">Apple-Datenträgerabbild</comment>
+ <comment xml:lang="da">Apple-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku Apple</comment>
+ <comment xml:lang="ca">imatge de disc d'Apple</comment>
+ <comment xml:lang="bg">Диск — Apple</comment>
+ <comment xml:lang="be">вобраз дыска Apple</comment>
+ <comment xml:lang="ast">Imaxe de discu d'Apple</comment>
+ <comment xml:lang="ar">صورة قرص أبل</comment>
+ <comment xml:lang="af">Apple-skyfbeeldlêer</comment>
<glob pattern="*.dmg"/>
</mime-type>
- <mime-type type="application/x-raw-disk-image">
+ <mime-type type="application/vnd.efi.img">
<comment>Raw disk image</comment>
- <comment xml:lang="ast">Imaxe de discu en bruto</comment>
- <comment xml:lang="ca">imatge de disc RAW</comment>
- <comment xml:lang="cs">surový obraz disku</comment>
- <comment xml:lang="da">Rå diskaftryk</comment>
- <comment xml:lang="de">Rohes Datenträgerabbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα δίσκου</comment>
- <comment xml:lang="en_GB">Raw disk image</comment>
- <comment xml:lang="es">imagen de disco en bruto</comment>
- <comment xml:lang="eu">Disko gordinaren irudia</comment>
- <comment xml:lang="fi">Raaka levytiedosto</comment>
- <comment xml:lang="fr">image disque Raw</comment>
- <comment xml:lang="ga">Amhíomha diosca</comment>
- <comment xml:lang="gl">Imaxe de disco en bruto</comment>
- <comment xml:lang="he">דמות גולמית של כונן</comment>
- <comment xml:lang="hr">Osnovna slika diska</comment>
- <comment xml:lang="hu">Nyers lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco crude</comment>
- <comment xml:lang="id">Image disk mentah</comment>
- <comment xml:lang="it">Immagine disco raw</comment>
- <comment xml:lang="kk">Шикі диск бейнесі</comment>
- <comment xml:lang="ko">RAW 디스크 이미지</comment>
- <comment xml:lang="oc">imatge disc Raw</comment>
- <comment xml:lang="pl">Surowy obraz dysku</comment>
- <comment xml:lang="pt">imagem de disco Raw</comment>
- <comment xml:lang="pt_BR">Imagem bruta de disco</comment>
- <comment xml:lang="ru">Необработанный образ диска</comment>
- <comment xml:lang="sk">Obraz disku</comment>
- <comment xml:lang="sl">Surovi odtis diska</comment>
- <comment xml:lang="sr">сиров одраз диска</comment>
- <comment xml:lang="sv">Rå diskavbild</comment>
- <comment xml:lang="tr">İşlem görmemiş disk imajı</comment>
- <comment xml:lang="uk">простий образ диска</comment>
+ <comment xml:lang="zh_TW">原始磁碟映像檔</comment>
<comment xml:lang="zh_CN">原始磁盘映像</comment>
- <comment xml:lang="zh_TW">原生磁碟映像檔</comment>
+ <comment xml:lang="uk">простий образ диска</comment>
+ <comment xml:lang="tr">Ham disk görüntüsü</comment>
+ <comment xml:lang="sv">Rå diskavbild</comment>
+ <comment xml:lang="sr">сиров одраз диска</comment>
+ <comment xml:lang="sq">pamje disku e papërpunuar</comment>
+ <comment xml:lang="sl">Surovi odtis diska</comment>
+ <comment xml:lang="si">අමු තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku</comment>
+ <comment xml:lang="ru">Необработанный образ диска</comment>
+ <comment xml:lang="pt_BR">Imagem bruta de disco</comment>
+ <comment xml:lang="pt">imagem de disco Raw</comment>
+ <comment xml:lang="pl">Surowy obraz dysku</comment>
+ <comment xml:lang="oc">imatge disc Raw</comment>
+ <comment xml:lang="nl">Onbewerkt schijfkopiebestand</comment>
+ <comment xml:lang="ko">RAW 디스크 이미지</comment>
+ <comment xml:lang="kk">Шикі диск бейнесі</comment>
+ <comment xml:lang="ja">Raw ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco raw</comment>
+ <comment xml:lang="is">Hrá diskmynd</comment>
+ <comment xml:lang="id">Image disk mentah</comment>
+ <comment xml:lang="ia">Imagine de disco crude</comment>
+ <comment xml:lang="hu">Nyers lemezkép</comment>
+ <comment xml:lang="hr">Osnovna slika diska</comment>
+ <comment xml:lang="he">דמות גולמית של כונן</comment>
+ <comment xml:lang="gl">Imaxe de disco en bruto</comment>
+ <comment xml:lang="ga">Amhíomha diosca</comment>
+ <comment xml:lang="fur">imagjin disc grese</comment>
+ <comment xml:lang="fr">image disque Raw</comment>
+ <comment xml:lang="fi">Raaka levykuva</comment>
+ <comment xml:lang="eu">Disko gordinaren irudia</comment>
+ <comment xml:lang="es">imagen de disco en bruto</comment>
+ <comment xml:lang="en_GB">Raw disk image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα δίσκου</comment>
+ <comment xml:lang="de">Rohes Datenträgerabbild</comment>
+ <comment xml:lang="da">Raw-diskaftryk</comment>
+ <comment xml:lang="cs">surový obraz disku</comment>
+ <comment xml:lang="ca">imatge de disc RAW</comment>
+ <comment xml:lang="bg">Диск — raw</comment>
+ <comment xml:lang="be">неапрацаваны вобраз дыска</comment>
+ <comment xml:lang="ast">Imaxe de discu en bruto</comment>
+ <comment xml:lang="ar">صورة قرص خام</comment>
+ <comment xml:lang="af">Rou skyfbeeldlêer</comment>
+ <alias type="application/x-raw-disk-image"/>
<glob pattern="*.raw-disk-image"/>
<glob pattern="*.img"/>
</mime-type>
<mime-type type="application/x-raw-floppy-disk-image">
<comment>Floppy disk image</comment>
- <sub-class-of type="application/x-raw-disk-image"/>
+ <comment xml:lang="zh_TW">Floppy 軟碟映像檔</comment>
+ <comment xml:lang="zh_CN">软盘映像</comment>
+ <comment xml:lang="uk">образ дискети</comment>
+ <comment xml:lang="tr">Disket görüntüsü</comment>
+ <comment xml:lang="sv">Diskettavbild</comment>
+ <comment xml:lang="sr">одраз флопи диска</comment>
+ <comment xml:lang="sq">pamje diskete</comment>
+ <comment xml:lang="sl">Slika diskete</comment>
+ <comment xml:lang="si">නම්ය තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz pružného disku</comment>
+ <comment xml:lang="ru">Образ дискеты</comment>
+ <comment xml:lang="pt_BR">Imagem de disco flexível</comment>
+ <comment xml:lang="pt">imagem da disquete</comment>
+ <comment xml:lang="pl">Obraz dyskietki</comment>
+ <comment xml:lang="oc">imatge disc disqueta</comment>
+ <comment xml:lang="nl">Diskette-schijfkopiebestand</comment>
+ <comment xml:lang="ko">플로피 디스크 이미지</comment>
+ <comment xml:lang="kk">Иілгіш диск бейнесі</comment>
+ <comment xml:lang="ja">Floppy ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco floppy</comment>
+ <comment xml:lang="is">Disklingsmynd</comment>
+ <comment xml:lang="id">Image disk floppy</comment>
+ <comment xml:lang="hu">Flopi lemezkép</comment>
+ <comment xml:lang="hr">Slika diskete</comment>
+ <comment xml:lang="he">דמות תקליטון</comment>
+ <comment xml:lang="gl">Imaxe de disco de Disquete</comment>
+ <comment xml:lang="ga">íomhá diosca fhlapaigh</comment>
+ <comment xml:lang="fur">imagjin disc floppy</comment>
+ <comment xml:lang="fr">image disquette</comment>
+ <comment xml:lang="fi">Levykkeen levykuva</comment>
+ <comment xml:lang="eu">Diskete disko irudia</comment>
+ <comment xml:lang="es">imagen de disquete</comment>
+ <comment xml:lang="en_GB">Floppy disk image</comment>
+ <comment xml:lang="de">Diskettenabbild</comment>
+ <comment xml:lang="da">Floppy-diskaftryk</comment>
+ <comment xml:lang="cs">obraz diskety</comment>
+ <comment xml:lang="ca">imatge de disquet</comment>
+ <comment xml:lang="bg">Диск — флопи</comment>
+ <comment xml:lang="be">вобраз гнуткага дыска</comment>
+ <comment xml:lang="ar">صورة قرص مرن</comment>
+ <comment xml:lang="af">Disket-skyfbeeldlêer</comment>
+ <sub-class-of type="application/vnd.efi.img"/>
+ <generic-icon name="media-floppy"/>
<alias type="application/x-fd-file"/>
<glob pattern="*.fd"/>
<glob pattern="*.qd"/>
</mime-type>
<mime-type type="application/x-raw-disk-image-xz-compressed">
<comment>Raw disk image (XZ-compressed)</comment>
- <comment xml:lang="ast">Imaxe de discu en bruto (comprimida en XZ)</comment>
- <comment xml:lang="ca">imatge de disc RAW (amb compressió XZ)</comment>
- <comment xml:lang="cs">surový obraz disku (komprimovaný pomocí XZ)</comment>
- <comment xml:lang="da">Rå diskaftryk (XZ-komprimeret)</comment>
- <comment xml:lang="de">Rohes Datenträgerabbild (XZ-komprimiert)</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα δίσκου (συμπιεσμένη XZ)</comment>
- <comment xml:lang="en_GB">Raw disk image (XZ-compressed)</comment>
- <comment xml:lang="es">imagen de disco en bruto (comprimida con XZ)</comment>
- <comment xml:lang="eu">Disko gordinaren irudia (XZ-rekin konprimitua)</comment>
- <comment xml:lang="fi">Raaka levytiedosto (XZ-pakattu)</comment>
- <comment xml:lang="fr">image disque Raw (compression XZ)</comment>
- <comment xml:lang="ga">Amhíomhá (comhbhrúite le XZ)</comment>
- <comment xml:lang="gl">Imaxe de disco en bruto (comprimida en XZ)</comment>
- <comment xml:lang="he">דמות גולמית של כונן (בדחיסת XZ)</comment>
- <comment xml:lang="hr">Osnovna slika diska (XZ sažeta)</comment>
- <comment xml:lang="hu">Nyers lemezkép (XZ-vel tömörítve)</comment>
- <comment xml:lang="ia">Imagine de disco crude (comprimite con XZ)</comment>
- <comment xml:lang="id">Image disk mentah (terkompresi XZ)</comment>
- <comment xml:lang="it">Immagine disco raw (compressa XZ)</comment>
- <comment xml:lang="kk">Шикі диск бейнесі (XZ-мен сығылған)</comment>
- <comment xml:lang="ko">RAW 디스크 이미지(XZ 압축)</comment>
- <comment xml:lang="oc">imatge disc Raw (compression XZ)</comment>
- <comment xml:lang="pl">Surowy obraz dysku (kompresja XZ)</comment>
- <comment xml:lang="pt">imagem de disco Raw (compressão XZ)</comment>
- <comment xml:lang="pt_BR">Imagem bruta de disco (compactada com XZ)</comment>
- <comment xml:lang="ru">Необработанный образ диска (сжатый xz)</comment>
- <comment xml:lang="sk">Obraz disku (komprimovaný pomocou XZ)</comment>
- <comment xml:lang="sl">Surovi odtis diska (stisnjeno z XZ)</comment>
- <comment xml:lang="sr">сиров одраз диска (запакована ИксЗ-ом)</comment>
- <comment xml:lang="sv">Rå diskavbild (XZ-komprimerad)</comment>
- <comment xml:lang="tr">İşlem görmemiş disk imajı (XZ ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">простий образ диска (стиснений XZ)</comment>
+ <comment xml:lang="zh_TW">原始磁碟映像檔 (XZ 壓縮)</comment>
<comment xml:lang="zh_CN">原始磁盘映像(XZ 压缩)</comment>
- <comment xml:lang="zh_TW">原生磁碟映像 (XZ 格式壓縮)</comment>
+ <comment xml:lang="uk">простий образ диска (стиснений XZ)</comment>
+ <comment xml:lang="tr">Ham disk görüntüsü (XZ ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Rå diskavbild (XZ-komprimerad)</comment>
+ <comment xml:lang="sr">сиров одраз диска (запакована ИксЗ-ом)</comment>
+ <comment xml:lang="sq">pamje disku e papërpunuar (ngjeshur me XZ)</comment>
+ <comment xml:lang="sl">Surovi odtis diska (stisnjeno z XZ)</comment>
+ <comment xml:lang="si">අමු තැටි රූපය (XZ-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Obraz disku (komprimovaný pomocou XZ)</comment>
+ <comment xml:lang="ru">Необработанный образ диска (сжатый XZ)</comment>
+ <comment xml:lang="pt_BR">Imagem bruta de disco (compactada com XZ)</comment>
+ <comment xml:lang="pt">imagem de disco Raw (compressão XZ)</comment>
+ <comment xml:lang="pl">Surowy obraz dysku (kompresja XZ)</comment>
+ <comment xml:lang="oc">imatge disc Raw (compression XZ)</comment>
+ <comment xml:lang="nl">Onbewerkt schijfkopiebestand (gecomprimeerd met XZ)</comment>
+ <comment xml:lang="ko">RAW 디스크 이미지(XZ 압축)</comment>
+ <comment xml:lang="kk">Шикі диск бейнесі (XZ-мен сығылған)</comment>
+ <comment xml:lang="ja">Raw ディスクイメージ (XZ 圧縮)</comment>
+ <comment xml:lang="it">Immagine disco raw (compressa XZ)</comment>
+ <comment xml:lang="is">Hrá diskmynd (XZ-þjöppuð)</comment>
+ <comment xml:lang="id">Image disk mentah (terkompresi XZ)</comment>
+ <comment xml:lang="ia">Imagine de disco crude (comprimite con XZ)</comment>
+ <comment xml:lang="hu">Nyers lemezkép (XZ tömörítésű)</comment>
+ <comment xml:lang="hr">Osnovna slika diska (XZ sažeta)</comment>
+ <comment xml:lang="he">דמות גולמית של כונן (בדחיסת XZ)</comment>
+ <comment xml:lang="gl">Imaxe de disco en bruto (comprimida en XZ)</comment>
+ <comment xml:lang="ga">Amhíomhá (comhbhrúite le XZ)</comment>
+ <comment xml:lang="fur">imagjin disc grese (comprimude cun XZ)</comment>
+ <comment xml:lang="fr">image disque Raw (compression XZ)</comment>
+ <comment xml:lang="fi">Raaka levykuva (XZ-pakattu)</comment>
+ <comment xml:lang="eu">Disko gordinaren irudia (XZ-rekin konprimitua)</comment>
+ <comment xml:lang="es">imagen de disco en bruto (comprimida con XZ)</comment>
+ <comment xml:lang="en_GB">Raw disk image (XZ-compressed)</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα δίσκου (συμπιεσμένη XZ)</comment>
+ <comment xml:lang="de">Rohes Datenträgerabbild (XZ-komprimiert)</comment>
+ <comment xml:lang="da">Raw-diskaftryk (XZ-komprimeret)</comment>
+ <comment xml:lang="cs">surový obraz disku (komprimovaný pomocí XZ)</comment>
+ <comment xml:lang="ca">imatge de disc RAW (amb compressió XZ)</comment>
+ <comment xml:lang="bg">Диск — raw, компресиран с xz</comment>
+ <comment xml:lang="be">неапрацаваны вобраз дыска (сцісканне XZ)</comment>
+ <comment xml:lang="ast">Imaxe de discu en bruto (comprimida en XZ)</comment>
+ <comment xml:lang="ar">صورة قرص خام (مضغوطة-ZX)</comment>
+ <comment xml:lang="af">Rou skyfbeeldlêer (XZ-saamgepers)</comment>
<sub-class-of type="application/x-xz"/>
<glob pattern="*.raw-disk-image.xz"/>
<glob pattern="*.img.xz"/>
</mime-type>
- <mime-type type="application/x-cd-image">
- <comment>raw CD image</comment>
- <comment xml:lang="ar">صورة CD خامة</comment>
- <comment xml:lang="ast">imaxe de CD en bruto</comment>
- <comment xml:lang="be@latin">suvoraja vyjava CD</comment>
- <comment xml:lang="bg">Изображение — raw CD</comment>
- <comment xml:lang="ca">imatge de CD en cru</comment>
- <comment xml:lang="cs">surový obraz CD</comment>
- <comment xml:lang="da">rå cd-aftryk</comment>
- <comment xml:lang="de">CD-Roh-Abbild</comment>
- <comment xml:lang="el">Εικόνα περιεχομένου ψηφιακού δίσκου</comment>
- <comment xml:lang="en_GB">raw CD image</comment>
- <comment xml:lang="eo">kruda lumdiskbildo</comment>
- <comment xml:lang="es">imagen de CD en bruto</comment>
- <comment xml:lang="eu">CD gordinaren irudia </comment>
- <comment xml:lang="fi">raaka CD-vedos</comment>
- <comment xml:lang="fo">rá CD mynd</comment>
- <comment xml:lang="fr">image CD brute</comment>
- <comment xml:lang="ga">amhíomhá dhlúthdhiosca</comment>
- <comment xml:lang="gl">imaxe de CD en bruto</comment>
- <comment xml:lang="he">תמונת דיסק גולמית</comment>
- <comment xml:lang="hr">Osnovna CD slika</comment>
- <comment xml:lang="hu">nyers CD-lemezkép</comment>
- <comment xml:lang="ia">Imagine CD brute</comment>
- <comment xml:lang="id">citra CD mentah</comment>
- <comment xml:lang="it">Immagine raw CD</comment>
- <comment xml:lang="ja">生 CD イメージ</comment>
- <comment xml:lang="kk">өңделмеген CD бейнесі</comment>
- <comment xml:lang="ko">CD 이미지</comment>
- <comment xml:lang="lt">raw CD atvaizdis</comment>
- <comment xml:lang="lv">CD jēlattēls</comment>
- <comment xml:lang="ms">Imej CD mentah</comment>
- <comment xml:lang="nb">rått CD-bilde</comment>
- <comment xml:lang="nl">ruw CD-beeldbestand</comment>
- <comment xml:lang="nn">rått CD-bilete</comment>
- <comment xml:lang="oc">imatge CD brut</comment>
- <comment xml:lang="pl">Surowy obraz CD</comment>
- <comment xml:lang="pt">imagem em bruto de CD</comment>
- <comment xml:lang="pt_BR">Imagem bruta de CD</comment>
- <comment xml:lang="ro">imagine de CD brută</comment>
+ <mime-type type="application/vnd.efi.iso">
+ <comment>Raw CD image</comment>
+ <comment xml:lang="uk">простий образ CD</comment>
+ <comment xml:lang="sv">Rå cd-avbild</comment>
<comment xml:lang="ru">Необработанный образ компакт-диска</comment>
- <comment xml:lang="sk">Surový obraz CD</comment>
- <comment xml:lang="sl">surovi CD odtis</comment>
- <comment xml:lang="sq">Imazh raw CD</comment>
- <comment xml:lang="sr">сиров одраз ЦД-а</comment>
- <comment xml:lang="sv">rå cd-avbild</comment>
- <comment xml:lang="tr">Ham CD görüntüsü</comment>
- <comment xml:lang="uk">образ raw CD</comment>
- <comment xml:lang="vi">ảnh đĩa CD thô</comment>
- <comment xml:lang="zh_CN">原始 CD 映像</comment>
- <comment xml:lang="zh_TW">原生 CD 映像檔</comment>
- <sub-class-of type="application/x-raw-disk-image"/>
+ <comment xml:lang="pl">Surowy obraz CD</comment>
+ <comment xml:lang="it">Immagine raw CD</comment>
+ <comment xml:lang="gl">Imaxe de CD en bruto</comment>
+ <comment xml:lang="eu">CD irudi gordina</comment>
+ <comment xml:lang="es">imagen de CD en bruto</comment>
+ <comment xml:lang="de">CD-Roh-Abbild</comment>
+ <comment xml:lang="be">Неапрацаваны вобраз CD</comment>
+ <sub-class-of type="application/vnd.efi.img"/>
+ <generic-icon name="media-optical"/>
+ <alias type="application/x-cd-image"/>
<alias type="application/x-iso9660-image"/>
-
- <glob weight="80" pattern="*.iso"/>
+ <!-- No magic, see https://bugs.freedesktop.org/show_bug.cgi?id=10049 -->
+ <glob pattern="*.iso" weight="80"/>
<glob pattern="*.iso9660"/>
</mime-type>
+ <mime-type type="application/x-compressed-iso">
+ <comment>Compressed CD image</comment>
+ <comment xml:lang="zh_CN">压缩的 CD 映像</comment>
+ <comment xml:lang="uk">стиснений образ CD</comment>
+ <comment xml:lang="tr">Sıkıştırılmış CD görüntüsü</comment>
+ <comment xml:lang="sv">Komprimerad cd-avbild</comment>
+ <comment xml:lang="sr">компресовани ЦД одраз</comment>
+ <comment xml:lang="sl">Stisnjena slika CD</comment>
+ <comment xml:lang="si">සම්පීඩිත CD රූපය</comment>
+ <comment xml:lang="ru">Сжатый образ компакт-диска</comment>
+ <comment xml:lang="pt_BR">Imagem de CD compactada</comment>
+ <comment xml:lang="pt">Imagem de CD comprimida</comment>
+ <comment xml:lang="pl">Skompresowany obraz płyty CD</comment>
+ <comment xml:lang="oc">imatge CD compressat</comment>
+ <comment xml:lang="nl">Gecomprimeerd CD-schijfkopiebestand</comment>
+ <comment xml:lang="ko">압축된 CD 이미지</comment>
+ <comment xml:lang="kk">Сығылған CD бейнесі</comment>
+ <comment xml:lang="ja">圧縮 CD イメージ</comment>
+ <comment xml:lang="it">Immagine CD compressa</comment>
+ <comment xml:lang="is">Þjöppuð CD diskmynd</comment>
+ <comment xml:lang="id">Image CD terkompresi</comment>
+ <comment xml:lang="hu">Tömörített CD lemezkép</comment>
+ <comment xml:lang="hr">Sažeta CD slika</comment>
+ <comment xml:lang="he">דמות תקליטור דחוסה</comment>
+ <comment xml:lang="gl">Imaxe de CD comprimido</comment>
+ <comment xml:lang="fr">Image CD compressée</comment>
+ <comment xml:lang="fi">Pakattu CD-levykuva</comment>
+ <comment xml:lang="eu">Konprimatutako CD irudia</comment>
+ <comment xml:lang="es">imagen comprimida de CD</comment>
+ <comment xml:lang="en_GB">Compressed CD image</comment>
+ <comment xml:lang="de">Komprimiertes CD-Abbild</comment>
+ <comment xml:lang="da">Komprimeret CD-aftryk</comment>
+ <comment xml:lang="ca">imatge de CD amb compressió</comment>
+ <comment xml:lang="be">сціснуты вобраз CD</comment>
+ <comment xml:lang="ar">صورة سي دي مضغوطة</comment>
+ <generic-icon name="media-optical"/>
+ <magic>
+ <match value="CISO" type="string" offset="0"/>
+ </magic>
+ <glob pattern="*.cso"/>
+ </mime-type>
<mime-type type="application/x-iso9660-appimage">
<comment>AppImage application bundle</comment>
- <comment xml:lang="ca">paquet d'aplicació AppImage</comment>
- <comment xml:lang="cs">balíček AppImage s aplikací</comment>
- <comment xml:lang="da">Applmage-programsamling</comment>
- <comment xml:lang="de">AppImage-Anwendungspaket</comment>
- <comment xml:lang="en_GB">AppImage application bundle</comment>
- <comment xml:lang="es">paquete de aplicación AppImage</comment>
- <comment xml:lang="eu">AppImage aplikazio bilduma</comment>
- <comment xml:lang="fi">AppImage-sovelluspaketti</comment>
- <comment xml:lang="fr">lot applicatif AppImage</comment>
- <comment xml:lang="ga">burla feidhmchláir AppImage</comment>
- <comment xml:lang="he">חבילת יישומי AppImage</comment>
- <comment xml:lang="hr">AppImage paket aplikacije</comment>
- <comment xml:lang="hu">AppImage alkalmazáscsomag</comment>
- <comment xml:lang="id">bundel aplikasi AppImage</comment>
- <comment xml:lang="it">Bundle applicazione AppImage</comment>
- <comment xml:lang="kk">AppImage қолданбалар дестесі</comment>
- <comment xml:lang="ko">AppImage 프로그램 번들</comment>
- <comment xml:lang="pl">Pakiet programu AppImage</comment>
- <comment xml:lang="pt_BR">Pacote de aplicativo AppImage</comment>
- <comment xml:lang="ru">Пакет приложения AppImage</comment>
- <comment xml:lang="sk">Balík aplikácií AppImage</comment>
- <comment xml:lang="sr">скуп програма Ап-слике</comment>
- <comment xml:lang="sv">AppImage-programbunt</comment>
- <comment xml:lang="tr">AppImage uygulama paketi</comment>
- <comment xml:lang="uk">пакунок із програмами AppImage</comment>
- <comment xml:lang="zh_CN">AppImage 应用组合包</comment>
<comment xml:lang="zh_TW">AppImage 應用程式套組</comment>
+ <comment xml:lang="zh_CN">AppImage 应用组合包</comment>
+ <comment xml:lang="uk">пакунок із програмами AppImage</comment>
+ <comment xml:lang="tr">AppImage uygulama paketi</comment>
+ <comment xml:lang="sv">AppImage-programbunt</comment>
+ <comment xml:lang="sr">скуп програма Ап-слике</comment>
+ <comment xml:lang="sq">paketë aplikacioni AppImage</comment>
+ <comment xml:lang="si">AppImage යෙදුම් මිටියක්</comment>
+ <comment xml:lang="sk">Balík aplikácií AppImage</comment>
+ <comment xml:lang="ru">Пакет приложения AppImage</comment>
+ <comment xml:lang="pt_BR">Pacote de aplicativo AppImage</comment>
+ <comment xml:lang="pt">pacote de aplicação AppImage</comment>
+ <comment xml:lang="pl">Pakiet programu AppImage</comment>
+ <comment xml:lang="nl">AppImage-toepassingsbundel</comment>
+ <comment xml:lang="ko">AppImage 프로그램 번들</comment>
+ <comment xml:lang="kk">AppImage қолданбалар дестесі</comment>
+ <comment xml:lang="ja">AppImage アプリケーションバンドル</comment>
+ <comment xml:lang="it">Bundle applicazione AppImage</comment>
+ <comment xml:lang="is">AppImage forritavöndull</comment>
+ <comment xml:lang="id">Bundel aplikasi AppImage</comment>
+ <comment xml:lang="hu">AppImage alkalmazáscsomag</comment>
+ <comment xml:lang="hr">AppImage paket aplikacije</comment>
+ <comment xml:lang="he">חבילת יישומי AppImage</comment>
+ <comment xml:lang="gl">Paquete de aplicación de AppImage</comment>
+ <comment xml:lang="ga">burla feidhmchláir AppImage</comment>
+ <comment xml:lang="fur">côl di aplicazions AppImage</comment>
+ <comment xml:lang="fr">lot applicatif AppImage</comment>
+ <comment xml:lang="fi">AppImage-sovelluspaketti</comment>
+ <comment xml:lang="eu">AppImage aplikazio bilduma</comment>
+ <comment xml:lang="es">paquete de aplicación AppImage</comment>
+ <comment xml:lang="en_GB">AppImage application bundle</comment>
+ <comment xml:lang="de">AppImage-Anwendungspaket</comment>
+ <comment xml:lang="da">AppImage-programsamling</comment>
+ <comment xml:lang="cs">balíček AppImage s aplikací</comment>
+ <comment xml:lang="ca">paquet d'aplicació AppImage</comment>
+ <comment xml:lang="bg">Програмен пакет — AppImage</comment>
+ <comment xml:lang="be">пакет праграмы AppImage</comment>
+ <comment xml:lang="ar">حزمة تطبيق AppImage</comment>
+ <comment xml:lang="af">AppImage-toepassingsbundel</comment>
<sub-class-of type="application/x-executable"/>
- <sub-class-of type="application/x-iso9660-image"/>
+ <sub-class-of type="application/vnd.efi.iso"/>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
+ <magic>
<match value="ELF" type="string" offset="1">
<match value="0x41" type="byte" offset="8">
<match value="0x49" type="byte" offset="9">
@@ -8697,174 +9065,258 @@
</mime-type>
<mime-type type="application/x-cdrdao-toc">
<comment>CD Table Of Contents</comment>
- <comment xml:lang="ar">جدول محتويات الـ CD</comment>
- <comment xml:lang="be@latin">Źmieściva CD</comment>
- <comment xml:lang="bg">Съдържание на CD</comment>
- <comment xml:lang="ca">taula de continguts de CD</comment>
- <comment xml:lang="cs">obsah CD</comment>
- <comment xml:lang="da">Cd-indholdsfotegnelse</comment>
- <comment xml:lang="de">CD-Inhaltsverzeichnis</comment>
- <comment xml:lang="el">Πίνακας περιεχομένων CD</comment>
- <comment xml:lang="en_GB">CD Table Of Contents</comment>
- <comment xml:lang="es">índice de contenido de CD</comment>
- <comment xml:lang="eu">CDaren edukien aurkibidea</comment>
- <comment xml:lang="fi">CD-sisällysluettelo</comment>
- <comment xml:lang="fo">CD innihaldsyvurlit</comment>
- <comment xml:lang="fr">table des matières de CD</comment>
- <comment xml:lang="ga">clár ábhar dlúthdhiosca</comment>
- <comment xml:lang="gl">táboa de contidos de CD</comment>
- <comment xml:lang="he">תוכן עניינים של דיסק</comment>
- <comment xml:lang="hr">CD sadržaj</comment>
- <comment xml:lang="hu">CD tartalomjegyzék</comment>
- <comment xml:lang="ia">Tabula de contento de CD</comment>
- <comment xml:lang="id">Tabel Isi CD</comment>
- <comment xml:lang="it">Indice CD</comment>
- <comment xml:lang="ja">CD Table Of Contents</comment>
- <comment xml:lang="kk">CD құрама кестесі</comment>
- <comment xml:lang="ko">CD 내용 목록</comment>
- <comment xml:lang="lt">CD turinys</comment>
- <comment xml:lang="lv">CD satura rādītājs</comment>
- <comment xml:lang="nb">Innholdsfortegnelse for CD</comment>
- <comment xml:lang="nl">CD-inhoudsopgave</comment>
- <comment xml:lang="nn">CD innhaldsliste</comment>
- <comment xml:lang="oc">ensenhador de CD</comment>
- <comment xml:lang="pl">Plik zawartości płyty CD</comment>
- <comment xml:lang="pt">Tabela de conteúdos de CD</comment>
- <comment xml:lang="pt_BR">Sumário de CD</comment>
- <comment xml:lang="ro">Tabel conținut CD</comment>
- <comment xml:lang="ru">Таблица содержания CD</comment>
- <comment xml:lang="sk">Obsah CD</comment>
- <comment xml:lang="sl">Kazalo vsebine CD nosilca</comment>
- <comment xml:lang="sq">Tregues CD</comment>
- <comment xml:lang="sr">табела садржаја ЦД-а</comment>
- <comment xml:lang="sv">Cd-innehållsförteckning</comment>
- <comment xml:lang="tr">CD İçindekiler Tablosu</comment>
- <comment xml:lang="uk">зміст CD</comment>
- <comment xml:lang="vi">Mục Lục của đĩa CD</comment>
- <comment xml:lang="zh_CN">CD 索引</comment>
<comment xml:lang="zh_TW">CD 內容目錄</comment>
+ <comment xml:lang="zh_CN">CD 索引</comment>
+ <comment xml:lang="vi">Mục Lục của đĩa CD</comment>
+ <comment xml:lang="uk">зміст CD</comment>
+ <comment xml:lang="tr">CD İçindekiler Tablosu</comment>
+ <comment xml:lang="sv">Cd-innehållsförteckning</comment>
+ <comment xml:lang="sr">табела садржаја ЦД-а</comment>
+ <comment xml:lang="sq">Tryezë Lënde CD</comment>
+ <comment xml:lang="sl">Kazalo vsebine CD nosilca</comment>
+ <comment xml:lang="si">CD පටුන</comment>
+ <comment xml:lang="sk">Obsah CD</comment>
+ <comment xml:lang="ru">Содержание компакт-диска</comment>
+ <comment xml:lang="ro">Tabel conținut CD</comment>
+ <comment xml:lang="pt_BR">Sumário de CD</comment>
+ <comment xml:lang="pt">Tabela de conteúdos de CD</comment>
+ <comment xml:lang="pl">Plik zawartości płyty CD</comment>
+ <comment xml:lang="oc">ensenhador de CD</comment>
+ <comment xml:lang="nn">CD innhaldsliste</comment>
+ <comment xml:lang="nl">CD-inhoudsopgave</comment>
+ <comment xml:lang="nb">Innholdsfortegnelse for CD</comment>
+ <comment xml:lang="lv">CD satura rādītājs</comment>
+ <comment xml:lang="lt">CD turinys</comment>
+ <comment xml:lang="ko">CD 내용 목록</comment>
+ <comment xml:lang="kk">CD құрама кестесі</comment>
+ <comment xml:lang="ja">CD Table Of Contents</comment>
+ <comment xml:lang="it">Indice CD</comment>
+ <comment xml:lang="is">Efnisyfirlit CD-disks</comment>
+ <comment xml:lang="id">Tabel Isi CD</comment>
+ <comment xml:lang="ia">Tabula de contento de CD</comment>
+ <comment xml:lang="hu">CD tartalomjegyzék</comment>
+ <comment xml:lang="hr">CD sadržaj</comment>
+ <comment xml:lang="he">תוכן עניינים של דיסק</comment>
+ <comment xml:lang="gl">táboa de contidos de CD</comment>
+ <comment xml:lang="ga">clár ábhar dlúthdhiosca</comment>
+ <comment xml:lang="fur">tabele dai contignûts di CD</comment>
+ <comment xml:lang="fr">table des matières de CD</comment>
+ <comment xml:lang="fo">CD innihaldsyvurlit</comment>
+ <comment xml:lang="fi">CD-sisällysluettelo</comment>
+ <comment xml:lang="eu">CDaren edukien aurkibidea</comment>
+ <comment xml:lang="es">índice de contenido de CD</comment>
+ <comment xml:lang="en_GB">CD Table Of Contents</comment>
+ <comment xml:lang="el">Πίνακας περιεχομένων CD</comment>
+ <comment xml:lang="de">CD-Inhaltsverzeichnis</comment>
+ <comment xml:lang="da">Cd-indholdsfortegnelse</comment>
+ <comment xml:lang="cs">obsah CD</comment>
+ <comment xml:lang="ca">taula de continguts de CD</comment>
+ <comment xml:lang="bg">Съдържание на CD</comment>
+ <comment xml:lang="be@latin">Źmieściva CD</comment>
+ <comment xml:lang="be">табліца змесціва CD</comment>
+ <comment xml:lang="ar">جدول محتويات CD</comment>
+ <comment xml:lang="af">CD-inhoudsopgawe</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="CD_ROM\n" type="string" offset="0"/>
- <match value="CD_DA\n" type="string" offset="0"/>
- <match value="CD_ROM_XA\n" type="string" offset="0"/>
- <match value="CD_TEXT " type="string" offset="0"/>
- <match value="CATALOG &quot;" type="string" offset="0">
- <match value="&quot;" type="string" offset="22"/>
+ <magic>
+ <match type="string" value="CD_ROM\n" offset="0"/>
+ <match type="string" value="CD_DA\n" offset="0"/>
+ <match type="string" value="CD_ROM_XA\n" offset="0"/>
+ <match type="string" value="CD_TEXT " offset="0"/>
+ <match type="string" value="CATALOG &quot;" offset="0">
+ <match type="string" value="&quot;" offset="22"/>
</match>
</magic>
<glob pattern="*.toc"/>
</mime-type>
+ <mime-type type="application/x-gd-rom-cue">
+ <comment>GD-ROM image cuesheet</comment>
+ <comment xml:lang="uk">таблиця CUE образу GD-ROM</comment>
+ <comment xml:lang="tr">GD-ROM görüntüsü çizelgesi</comment>
+ <comment xml:lang="sv">GD-ROM Indexblad för cd-avbild</comment>
+ <comment xml:lang="si">GD-ROM රූප කුට්ටිය</comment>
+ <comment xml:lang="ru">Файл разметки образа GD-ROM</comment>
+ <comment xml:lang="pt_BR">Índice de Imagem de GD-ROM</comment>
+ <comment xml:lang="pl">Obraz cuesheet płyty GD-ROM</comment>
+ <comment xml:lang="nl">GD-ROM-schijfkopiebestand-cue-sheet</comment>
+ <comment xml:lang="ko">GD-ROM 이미지 큐시트</comment>
+ <comment xml:lang="kk">GD-ROM бейнесінің құрама кестесі</comment>
+ <comment xml:lang="ja">GD-ROM イメージキューシート</comment>
+ <comment xml:lang="it">Cuesheet immagine GD-ROM</comment>
+ <comment xml:lang="is">cuesheet CD-ROM diskmyndar</comment>
+ <comment xml:lang="id">cuesheet image GD-ROM</comment>
+ <comment xml:lang="hu">GD-ROM lemezkép-jelölőlap</comment>
+ <comment xml:lang="hr">GD-ROM popis slika</comment>
+ <comment xml:lang="he">גיליון cue של דמות GD-ROM</comment>
+ <comment xml:lang="fr">Index de pistes GD-ROM</comment>
+ <comment xml:lang="fi">GD-ROM levykuvan taulukko</comment>
+ <comment xml:lang="es">hoja CUE de imagen GD-ROM</comment>
+ <comment xml:lang="en_GB">GD-ROM image cuesheet</comment>
+ <comment xml:lang="de">GD-ROM-Abbild-Cuesheet</comment>
+ <comment xml:lang="da">GD-ROM-aftrykscuesheet</comment>
+ <comment xml:lang="ca">«cuesheet» d'imatge de GD-ROM</comment>
+ <comment xml:lang="be">табліца разметкі вобраза GD-ROM</comment>
+ <comment xml:lang="ar">صفيحة صورة الـGD-ROM جديلة</comment>
+ <!-- It is a non-standard cuesheet used only for Dreamcast GD-ROM images, it
+ is typically surrounded by the .bin and .raw files it lists, each one
+ matching a disc track.
+ The first file should have the application/x-dreamcast-rom type. -->
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-generic"/>
+ <glob pattern="*.gdi"/>
+ </mime-type>
+ <mime-type type="application/x-discjuggler-cd-image">
+ <comment>Padus DiscJuggler CD image</comment>
+ <comment xml:lang="zh_CN">Padus DiscJuggler CD 映像</comment>
+ <comment xml:lang="uk">образ CD Padus DiscJuggler</comment>
+ <comment xml:lang="tr">Padus DiscJuggler CD görüntüsü</comment>
+ <comment xml:lang="sv">Padus DiscJuggler cd-avbild</comment>
+ <comment xml:lang="si">Padus DiscJuggler CD රූපය</comment>
+ <comment xml:lang="ru">Образ диска Padus DiscJuggler CD</comment>
+ <comment xml:lang="pt_BR">Imagem de CD do Padus DiscJuggler</comment>
+ <comment xml:lang="pl">Obraz płyty CD programu Padus DiscJuggler</comment>
+ <comment xml:lang="nl">Padus DiscJuggler CD-schijfkopiebestand</comment>
+ <comment xml:lang="ko">Padus DiscJuggler CD 이미지</comment>
+ <comment xml:lang="kk">Padus DiscJuggler CD бейнесі</comment>
+ <comment xml:lang="ja">Padus DiscJuggler CD イメージ</comment>
+ <comment xml:lang="it">Immagine CD DiscJuggler Padus</comment>
+ <comment xml:lang="is">Padus DiscJuggler CD diskmynd</comment>
+ <comment xml:lang="id">image CD Padus DiscJuggler</comment>
+ <comment xml:lang="hu">Padus DiscJuggler CD lemezkép</comment>
+ <comment xml:lang="hr">Padus DiscJuggler CD slika</comment>
+ <comment xml:lang="he">תמונת תקליטור Padus DiscJuggler</comment>
+ <comment xml:lang="gl">Imaxe de CD Padus DiscJuggler</comment>
+ <comment xml:lang="fr">Image CD Padus DiscJuggler</comment>
+ <comment xml:lang="fi">Padus DiscJuggler CD-levykuva</comment>
+ <comment xml:lang="es">imagen de CD de Padus DiscJuggler</comment>
+ <comment xml:lang="en_GB">Padus DiscJuggler CD image</comment>
+ <comment xml:lang="de">Padus-DiscJuggler-CD-Abbild</comment>
+ <comment xml:lang="da">Padus DiscJuggler CD-aftryk</comment>
+ <comment xml:lang="ca">imatge de CD de Padus DiscJuggler</comment>
+ <comment xml:lang="be">вобраз CD Padus DiscJuggler</comment>
+ <comment xml:lang="ar">صورة سي دي Padus DiscJuggler</comment>
+ <generic-icon name="media-optical"/>
+ <glob pattern="*.cdi"/>
+ </mime-type>
<mime-type type="application/vnd.chess-pgn">
<comment>PGN chess game notation</comment>
- <comment xml:lang="ar">تدوينة لعبة الشطرنج PGN</comment>
- <comment xml:lang="be@latin">Zaciem ab šachmatnaj partyi PGN</comment>
- <comment xml:lang="bg">Игра шах — PGN</comment>
- <comment xml:lang="ca">notació de joc d'escacs PGN</comment>
- <comment xml:lang="cs">šachová notace PGN</comment>
- <comment xml:lang="da">PGN-skakspilsnotation</comment>
- <comment xml:lang="de">PGN-Schachspielnotation</comment>
- <comment xml:lang="el">Σημειογραφία παιχνιδιού σκακιού PGN</comment>
- <comment xml:lang="en_GB">PGN chess game notation</comment>
- <comment xml:lang="es">notación para juegos de ajedrez PGN</comment>
- <comment xml:lang="eu">PGN xake jokoaren notazioa</comment>
- <comment xml:lang="fi">PGN-šakkipelinotaatio</comment>
- <comment xml:lang="fo">PGN talv teknskipan</comment>
- <comment xml:lang="fr">notation de jeu d'échecs PGN</comment>
- <comment xml:lang="ga">nodaireacht chluiche ficheall PGN</comment>
- <comment xml:lang="gl">Notación de xogo de xadrez PGN</comment>
- <comment xml:lang="he">סימון משחק שח PGN</comment>
- <comment xml:lang="hr">PGN zapis šahovske igre</comment>
- <comment xml:lang="hu">PGN sakkfeljegyzés</comment>
- <comment xml:lang="ia">Notation de joco de chacos PGN</comment>
- <comment xml:lang="id">Notasi permainan catur PGN</comment>
- <comment xml:lang="it">Notazione partita a scacchi PGN</comment>
- <comment xml:lang="ja">PGN チェスゲーム記録</comment>
- <comment xml:lang="kk">PGN шахмат ойыны</comment>
- <comment xml:lang="ko">PGN 체스 게임 기보</comment>
- <comment xml:lang="lt">PGN šachmatų žaidimo žymėjimas</comment>
- <comment xml:lang="lv">PGN šaha spēles notācija</comment>
- <comment xml:lang="nb">PGN sjakkspillnotasjon</comment>
- <comment xml:lang="nl">PGN-schaakspelnotatie</comment>
- <comment xml:lang="nn">PGN-sjakkspelnotasjon</comment>
- <comment xml:lang="oc">notacion de jòc d'escacs PGN</comment>
- <comment xml:lang="pl">Plik PGN notacji gry w szachy</comment>
- <comment xml:lang="pt">notação de jogo de xadrez PGN</comment>
- <comment xml:lang="pt_BR">Notação de jogo de xadrez PGN</comment>
- <comment xml:lang="ro">Notație joc șah PGN</comment>
- <comment xml:lang="ru">Шахматная партия PGN</comment>
- <comment xml:lang="sk">Šachová notácia PGN</comment>
- <comment xml:lang="sl">Datoteka opomb šahovske igre PGN</comment>
- <comment xml:lang="sq">Njoftim loje shahu PGN</comment>
- <comment xml:lang="sr">ПГН забелешка шаховске игре</comment>
- <comment xml:lang="sv">PGN-schackpartinotation</comment>
- <comment xml:lang="tr">PGN satranç oyun gösterimi</comment>
- <comment xml:lang="uk">запис гри у шахи PGN</comment>
- <comment xml:lang="vi">Cách ghi lượt chơi cờ PGN</comment>
- <comment xml:lang="zh_CN">PGN 象棋游戏注记</comment>
<comment xml:lang="zh_TW">PGN 國際象棋棋譜</comment>
+ <comment xml:lang="zh_CN">PGN 象棋游戏注记</comment>
+ <comment xml:lang="vi">Cách ghi lượt chơi cờ PGN</comment>
+ <comment xml:lang="uk">запис гри у шахи PGN</comment>
+ <comment xml:lang="tr">PGN satranç oyun gösterimi</comment>
+ <comment xml:lang="sv">PGN-schackpartinotation</comment>
+ <comment xml:lang="sr">ПГН забелешка шаховске игре</comment>
+ <comment xml:lang="sq">sistem zbardhjeje loje shahu PGN</comment>
+ <comment xml:lang="sl">Datoteka opomb šahovske igre PGN</comment>
+ <comment xml:lang="si">PGN චෙස් ක්‍රීඩා අංකනය</comment>
+ <comment xml:lang="sk">Šachová notácia PGN</comment>
+ <comment xml:lang="ru">Шахматная партия PGN</comment>
+ <comment xml:lang="ro">Notație joc șah PGN</comment>
+ <comment xml:lang="pt_BR">Notação de jogo de xadrez PGN</comment>
+ <comment xml:lang="pt">notação de jogo de xadrez PGN</comment>
+ <comment xml:lang="pl">Plik PGN notacji gry w szachy</comment>
+ <comment xml:lang="oc">notacion de jòc d'escacs PGN</comment>
+ <comment xml:lang="nn">PGN-sjakkspelnotasjon</comment>
+ <comment xml:lang="nl">PGN-schaakspelnotatie</comment>
+ <comment xml:lang="nb">PGN sjakkspillnotasjon</comment>
+ <comment xml:lang="lv">PGN šaha spēles notācija</comment>
+ <comment xml:lang="lt">PGN šachmatų žaidimo žymėjimas</comment>
+ <comment xml:lang="ko">PGN 체스 게임 기보</comment>
+ <comment xml:lang="kk">PGN шахмат ойыны</comment>
+ <comment xml:lang="ja">PGN チェスゲーム記録</comment>
+ <comment xml:lang="it">Notazione partita a scacchi PGN</comment>
+ <comment xml:lang="is">færsla PGN skákleiks</comment>
+ <comment xml:lang="id">Notasi permainan catur PGN</comment>
+ <comment xml:lang="ia">Notation de joco de chacos PGN</comment>
+ <comment xml:lang="hu">PGN sakkfeljegyzés</comment>
+ <comment xml:lang="hr">PGN zapis šahovske igre</comment>
+ <comment xml:lang="he">סימון משחק שח PGN</comment>
+ <comment xml:lang="gl">Notación de xogo de xadrez PGN</comment>
+ <comment xml:lang="ga">nodaireacht chluiche ficheall PGN</comment>
+ <comment xml:lang="fur">notazion par zûc di scacs PGN</comment>
+ <comment xml:lang="fr">notation de jeu d'échecs PGN</comment>
+ <comment xml:lang="fo">PGN talv teknskipan</comment>
+ <comment xml:lang="fi">PGN-šakkipelinotaatio</comment>
+ <comment xml:lang="eu">PGN xake jokoaren notazioa</comment>
+ <comment xml:lang="es">notación para juegos de ajedrez PGN</comment>
+ <comment xml:lang="en_GB">PGN chess game notation</comment>
+ <comment xml:lang="el">Σημειογραφία παιχνιδιού σκακιού PGN</comment>
+ <comment xml:lang="de">PGN-Schachspielnotation</comment>
+ <comment xml:lang="da">PGN-skakspilsnotation</comment>
+ <comment xml:lang="cs">šachová notace PGN</comment>
+ <comment xml:lang="ca">notació de joc d'escacs PGN</comment>
+ <comment xml:lang="bg">Игра шах — PGN</comment>
+ <comment xml:lang="be@latin">Zaciem ab šachmatnaj partyi PGN</comment>
+ <comment xml:lang="be">запіс шахматнай партыі PGN</comment>
+ <comment xml:lang="ar">تدوينة لعبة شطرنج PGN</comment>
+ <comment xml:lang="af">PGN-skaakspelnotasie</comment>
<acronym>PGN</acronym>
<expanded-acronym>Portable Game Notation</expanded-acronym>
<generic-icon name="text-x-generic"/>
<glob pattern="*.pgn"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="[Event " type="string" offset="0"/>
+ <magic>
+ <match type="string" value="[Event " offset="0"/>
</magic>
<alias type="application/x-chess-pgn"/>
</mime-type>
<mime-type type="application/vnd.ms-htmlhelp">
<comment>CHM document</comment>
- <comment xml:lang="ar">مستند CHM</comment>
- <comment xml:lang="ast">Documentu CHM</comment>
- <comment xml:lang="be@latin">Dakument CHM</comment>
- <comment xml:lang="bg">Документ — CHM</comment>
- <comment xml:lang="ca">document CHM</comment>
- <comment xml:lang="cs">dokument CHM</comment>
- <comment xml:lang="da">CHM-dokument</comment>
- <comment xml:lang="de">CHM-Dokument</comment>
- <comment xml:lang="el">Έγγραφο CHM</comment>
- <comment xml:lang="en_GB">CHM document</comment>
- <comment xml:lang="eo">CHM-dokumento</comment>
- <comment xml:lang="es">documento CHM</comment>
- <comment xml:lang="eu">CHM dokumentua</comment>
- <comment xml:lang="fi">CHM-asiakirja</comment>
- <comment xml:lang="fo">CHM skjal</comment>
- <comment xml:lang="fr">document CHM</comment>
- <comment xml:lang="ga">cáipéis CHM</comment>
- <comment xml:lang="gl">documento CHM</comment>
- <comment xml:lang="he">מסמך CHM</comment>
- <comment xml:lang="hr">CHM dokument</comment>
- <comment xml:lang="hu">CHM dokumentum</comment>
- <comment xml:lang="ia">Documento CHM</comment>
- <comment xml:lang="id">Dokumen CHM</comment>
- <comment xml:lang="it">Documento CHM</comment>
- <comment xml:lang="ja">CHM ドキュメント</comment>
- <comment xml:lang="ka">CHM დოკუმენტი</comment>
- <comment xml:lang="kk">CHM құжаты</comment>
- <comment xml:lang="ko">CHM 문서</comment>
- <comment xml:lang="lt">CHM dokumentas</comment>
- <comment xml:lang="lv">CHM dokuments</comment>
- <comment xml:lang="nb">CHM-dokument</comment>
- <comment xml:lang="nl">CHM-document</comment>
- <comment xml:lang="nn">CHM-dokument</comment>
- <comment xml:lang="oc">document CHM</comment>
- <comment xml:lang="pl">Dokument CHM</comment>
- <comment xml:lang="pt">documento CHM</comment>
- <comment xml:lang="pt_BR">Documento CHM</comment>
- <comment xml:lang="ro">Document CHM</comment>
- <comment xml:lang="ru">Документ CHM</comment>
- <comment xml:lang="sk">Dokument CHM</comment>
- <comment xml:lang="sl">Dokument CHM</comment>
- <comment xml:lang="sq">Dokument CHM</comment>
- <comment xml:lang="sr">ЦХМ документ</comment>
- <comment xml:lang="sv">CHM-dokument</comment>
- <comment xml:lang="tr">CHM belgesi</comment>
- <comment xml:lang="uk">документ CHM</comment>
- <comment xml:lang="vi">Tài liệu CHM</comment>
- <comment xml:lang="zh_CN">CHM 文档</comment>
<comment xml:lang="zh_TW">CHM 文件</comment>
+ <comment xml:lang="zh_CN">CHM 文档</comment>
+ <comment xml:lang="vi">Tài liệu CHM</comment>
+ <comment xml:lang="uk">документ CHM</comment>
+ <comment xml:lang="tr">CHM belgesi</comment>
+ <comment xml:lang="sv">CHM-dokument</comment>
+ <comment xml:lang="sr">ЦХМ документ</comment>
+ <comment xml:lang="sq">dokument CHM</comment>
+ <comment xml:lang="sl">Dokument CHM</comment>
+ <comment xml:lang="si">CHM ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument CHM</comment>
+ <comment xml:lang="ru">Документ CHM</comment>
+ <comment xml:lang="ro">Document CHM</comment>
+ <comment xml:lang="pt_BR">Documento CHM</comment>
+ <comment xml:lang="pt">documento CHM</comment>
+ <comment xml:lang="pl">Dokument CHM</comment>
+ <comment xml:lang="oc">document CHM</comment>
+ <comment xml:lang="nn">CHM-dokument</comment>
+ <comment xml:lang="nl">CHM-document</comment>
+ <comment xml:lang="nb">CHM-dokument</comment>
+ <comment xml:lang="lv">CHM dokuments</comment>
+ <comment xml:lang="lt">CHM dokumentas</comment>
+ <comment xml:lang="ko">CHM 문서</comment>
+ <comment xml:lang="kk">CHM құжаты</comment>
+ <comment xml:lang="ka">CHM დოკუმენტი</comment>
+ <comment xml:lang="ja">CHM ドキュメント</comment>
+ <comment xml:lang="it">Documento CHM</comment>
+ <comment xml:lang="is">CHM skjal</comment>
+ <comment xml:lang="id">Dokumen CHM</comment>
+ <comment xml:lang="ia">Documento CHM</comment>
+ <comment xml:lang="hu">CHM dokumentum</comment>
+ <comment xml:lang="hr">CHM dokument</comment>
+ <comment xml:lang="he">מסמך CHM</comment>
+ <comment xml:lang="gl">documento CHM</comment>
+ <comment xml:lang="ga">cáipéis CHM</comment>
+ <comment xml:lang="fur">document CHM</comment>
+ <comment xml:lang="fr">document CHM</comment>
+ <comment xml:lang="fo">CHM skjal</comment>
+ <comment xml:lang="fi">CHM-asiakirja</comment>
+ <comment xml:lang="eu">CHM dokumentua</comment>
+ <comment xml:lang="es">documento CHM</comment>
+ <comment xml:lang="eo">CHM-dokumento</comment>
+ <comment xml:lang="en_GB">CHM document</comment>
+ <comment xml:lang="el">Έγγραφο CHM</comment>
+ <comment xml:lang="de">CHM-Dokument</comment>
+ <comment xml:lang="da">CHM-dokument</comment>
+ <comment xml:lang="cs">dokument CHM</comment>
+ <comment xml:lang="ca">document CHM</comment>
+ <comment xml:lang="bg">Документ — CHM</comment>
+ <comment xml:lang="be@latin">Dakument CHM</comment>
+ <comment xml:lang="be">дакумент CHM</comment>
+ <comment xml:lang="ast">Documentu CHM</comment>
+ <comment xml:lang="ar">مستند CHM</comment>
+ <comment xml:lang="af">CHM-dokument</comment>
<acronym>CHM</acronym>
<expanded-acronym>Compiled Help Modules</expanded-acronym>
<generic-icon name="x-office-document"/>
@@ -8873,1194 +9325,1507 @@
</mime-type>
<mime-type type="application/x-class-file">
<comment>Java byte code</comment>
- <comment xml:lang="ar">رمز بايت الـJava</comment>
- <comment xml:lang="az">Java bayt kodu</comment>
- <comment xml:lang="be@latin">Bajtavy kod Java</comment>
- <comment xml:lang="bg">Байт код за Java</comment>
- <comment xml:lang="ca">Bytecode de Java</comment>
- <comment xml:lang="cs">bajtový kód Java</comment>
- <comment xml:lang="cy">Côd beit Java</comment>
- <comment xml:lang="da">Javabytekode</comment>
- <comment xml:lang="de">Java-Bytecode</comment>
- <comment xml:lang="el">Συμβολοκώδικας Java</comment>
- <comment xml:lang="en_GB">Java byte code</comment>
- <comment xml:lang="eo">Java-bajtkodo</comment>
- <comment xml:lang="es">bytecode de Java</comment>
- <comment xml:lang="eu">Java byte-kodea</comment>
- <comment xml:lang="fi">Java-tavukoodi</comment>
- <comment xml:lang="fo">Java býtkota</comment>
- <comment xml:lang="fr">code Java binaire</comment>
- <comment xml:lang="ga">beartchód Java</comment>
- <comment xml:lang="gl">byte code de Java</comment>
- <comment xml:lang="he">קוד Java byte</comment>
- <comment xml:lang="hr">Java bajt kôd</comment>
- <comment xml:lang="hu">Java-bájtkód</comment>
- <comment xml:lang="ia">Codice intermediari de Java</comment>
- <comment xml:lang="id">Kode bita Java</comment>
- <comment xml:lang="it">Bytecode Java</comment>
- <comment xml:lang="ja">Java バイトコード</comment>
- <comment xml:lang="kk">Java байт коды</comment>
- <comment xml:lang="ko">Java 바이트 코드</comment>
- <comment xml:lang="lt">Java baitinis kodas</comment>
- <comment xml:lang="lv">Java bitu kods</comment>
- <comment xml:lang="ms">Kod bait Java</comment>
- <comment xml:lang="nb">Java-bytekode</comment>
- <comment xml:lang="nl">Java-bytecode</comment>
- <comment xml:lang="nn">Jave byte-kode</comment>
- <comment xml:lang="oc">còde Java binari</comment>
- <comment xml:lang="pl">Kod bajtowy Java</comment>
- <comment xml:lang="pt">byte-code Java</comment>
- <comment xml:lang="pt_BR">Código compilado Java</comment>
- <comment xml:lang="ro">Bytecode Java</comment>
- <comment xml:lang="ru">Байт-код Java</comment>
- <comment xml:lang="sk">Bajtový kód Java</comment>
- <comment xml:lang="sl">Datoteka bitne kode Java</comment>
- <comment xml:lang="sq">Byte code Java</comment>
- <comment xml:lang="sr">бајтни ко̂д Јаве</comment>
- <comment xml:lang="sv">Java-bytekod</comment>
- <comment xml:lang="tr">Java derlenmiş kodu</comment>
- <comment xml:lang="uk">Байт-код Java</comment>
- <comment xml:lang="vi">Mã byte Java</comment>
- <comment xml:lang="zh_CN">Java 字节码</comment>
<comment xml:lang="zh_TW">Java 位元組碼</comment>
+ <comment xml:lang="zh_CN">Java 字节码</comment>
+ <comment xml:lang="vi">Mã byte Java</comment>
+ <comment xml:lang="uk">Байт-код Java</comment>
+ <comment xml:lang="tr">Java derlenmiş kodu</comment>
+ <comment xml:lang="sv">Java-bytekod</comment>
+ <comment xml:lang="sr">бајтни ко̂д Јаве</comment>
+ <comment xml:lang="sl">Datoteka bitne kode Java</comment>
+ <comment xml:lang="si">ජාවා බයිට් කේතය</comment>
+ <comment xml:lang="sk">Bajtový kód Java</comment>
+ <comment xml:lang="ru">Байт-код Java</comment>
+ <comment xml:lang="ro">Bytecode Java</comment>
+ <comment xml:lang="pt_BR">Código compilado Java</comment>
+ <comment xml:lang="pt">byte-code Java</comment>
+ <comment xml:lang="pl">Kod bajtowy Java</comment>
+ <comment xml:lang="oc">còde Java binari</comment>
+ <comment xml:lang="nn">Jave byte-kode</comment>
+ <comment xml:lang="nl">Java-bytecode</comment>
+ <comment xml:lang="nb">Java-bytekode</comment>
+ <comment xml:lang="ms">Kod bait Java</comment>
+ <comment xml:lang="lv">Java bitu kods</comment>
+ <comment xml:lang="lt">Java baitinis kodas</comment>
+ <comment xml:lang="ko">Java 바이트 코드</comment>
+ <comment xml:lang="kk">Java байт коды</comment>
+ <comment xml:lang="ja">Java バイトコード</comment>
+ <comment xml:lang="it">Bytecode Java</comment>
+ <comment xml:lang="is">Java bætkóði</comment>
+ <comment xml:lang="id">Kode bita Java</comment>
+ <comment xml:lang="ia">Codice intermediari de Java</comment>
+ <comment xml:lang="hu">Java-bájtkód</comment>
+ <comment xml:lang="hr">Java bajt kôd</comment>
+ <comment xml:lang="he">קוד Java byte</comment>
+ <comment xml:lang="gl">byte code de Java</comment>
+ <comment xml:lang="ga">beartchód Java</comment>
+ <comment xml:lang="fur">bytecode di Java</comment>
+ <comment xml:lang="fr">code Java binaire</comment>
+ <comment xml:lang="fo">Java býtkota</comment>
+ <comment xml:lang="fi">Java-tavukoodi</comment>
+ <comment xml:lang="eu">Java byte-kodea</comment>
+ <comment xml:lang="es">bytecode de Java</comment>
+ <comment xml:lang="eo">Java-bajtkodo</comment>
+ <comment xml:lang="en_GB">Java byte code</comment>
+ <comment xml:lang="el">Συμβολοκώδικας Java</comment>
+ <comment xml:lang="de">Java-Bytecode</comment>
+ <comment xml:lang="da">Java-bytekode</comment>
+ <comment xml:lang="cy">Côd beit Java</comment>
+ <comment xml:lang="cs">bajtový kód Java</comment>
+ <comment xml:lang="ca">bytecode de Java</comment>
+ <comment xml:lang="bg">Байт код за Java</comment>
+ <comment xml:lang="be@latin">Bajtavy kod Java</comment>
+ <comment xml:lang="be">байт-код Java</comment>
+ <comment xml:lang="az">Java bayt kodu</comment>
+ <comment xml:lang="ar">رمز بايت Java</comment>
+ <comment xml:lang="af">Java binêre kode</comment>
</mime-type>
<mime-type type="application/x-compress">
<comment>UNIX-compressed file</comment>
- <comment xml:lang="ar">ملف يونكس-مضغوط</comment>
- <comment xml:lang="be@latin">Skampresavany UNIX-fajł</comment>
- <comment xml:lang="bg">Файл — компресиран за UNIX</comment>
- <comment xml:lang="ca">fitxer amb compressió UNIX</comment>
- <comment xml:lang="cs">soubor komprimovaný v Unixu</comment>
- <comment xml:lang="da">UNIX-komprimeret fil</comment>
- <comment xml:lang="de">UNIX-komprimierte Datei</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο UNIX</comment>
- <comment xml:lang="en_GB">UNIX-compressed file</comment>
- <comment xml:lang="eo">UNIX-kunpremita dosiero</comment>
- <comment xml:lang="es">archivo comprimido de Unix</comment>
- <comment xml:lang="eu">UNIX-en konprimitutako fitxategia</comment>
- <comment xml:lang="fi">UNIX-pakattu tiedosto</comment>
- <comment xml:lang="fo">UNIX-stappað fíla</comment>
- <comment xml:lang="fr">fichier compressé UNIX</comment>
- <comment xml:lang="ga">comhad UNIX-comhbhrúite</comment>
- <comment xml:lang="gl">ficheiro comprimido de UNIX</comment>
- <comment xml:lang="he">קובץ בכיווץ UNIX</comment>
- <comment xml:lang="hr">UNIX sažeta datoteka</comment>
- <comment xml:lang="hu">Tömörített UNIX-fájl</comment>
- <comment xml:lang="ia">File comprimite de UNIX</comment>
- <comment xml:lang="id">Berkas terkompresi UNIX</comment>
- <comment xml:lang="it">File compresso-UNIX</comment>
- <comment xml:lang="ja">UNIX-compress ファイル</comment>
- <comment xml:lang="kk">файл (UNIX-сығылған)</comment>
- <comment xml:lang="ko">UNIX 압축 파일</comment>
- <comment xml:lang="lt">UNIX suglaudintas failas</comment>
- <comment xml:lang="lv">UNIX saspiesta datne</comment>
- <comment xml:lang="ms">Fail termampat-UNIX</comment>
- <comment xml:lang="nb">UNIX-komprimert fil</comment>
- <comment xml:lang="nl">UNIX-ingepakt bestand</comment>
- <comment xml:lang="nn">UNIX-komprimert fil</comment>
- <comment xml:lang="oc">fichièr compressat UNIX</comment>
- <comment xml:lang="pl">Skompresowany plik systemu UNIX</comment>
- <comment xml:lang="pt">ficheiro comprimido UNIX</comment>
- <comment xml:lang="pt_BR">Arquivo compactado do UNIX</comment>
- <comment xml:lang="ro">Fișier comprimat UNIX</comment>
- <comment xml:lang="ru">Файл (UNIX-сжатый)</comment>
- <comment xml:lang="sk">Súbor komprimovaný v Unixe</comment>
- <comment xml:lang="sl">Skrčena Unix datoteka</comment>
- <comment xml:lang="sq">File i kompresuar UNIX</comment>
- <comment xml:lang="sr">датотека запакована ЈУНИКС-ом</comment>
- <comment xml:lang="sv">UNIX-komprimerad fil</comment>
- <comment xml:lang="tr">UNIX-sıkıştırılmış dosyası</comment>
- <comment xml:lang="uk">стиснений файл UNIX</comment>
- <comment xml:lang="vi">Tập tin đã nén UNIX</comment>
+ <comment xml:lang="zh_TW">UNIX 壓縮檔</comment>
<comment xml:lang="zh_CN">UNIX 压缩文件</comment>
- <comment xml:lang="zh_TW">UNIX 格式壓縮檔</comment>
+ <comment xml:lang="vi">Tập tin đã nén UNIX</comment>
+ <comment xml:lang="uk">стиснений файл UNIX</comment>
+ <comment xml:lang="tr">UNIX-sıkıştırılmış dosyası</comment>
+ <comment xml:lang="sv">UNIX-komprimerad fil</comment>
+ <comment xml:lang="sr">датотека запакована ЈУНИКС-ом</comment>
+ <comment xml:lang="sq">kartelë e ngjeshur me Unix</comment>
+ <comment xml:lang="sl">Skrčena Unix datoteka</comment>
+ <comment xml:lang="si">UNIX සම්පීඩිත ගොනුව</comment>
+ <comment xml:lang="sk">Súbor komprimovaný v Unixe</comment>
+ <comment xml:lang="ru">Сжатый файл UNIX</comment>
+ <comment xml:lang="ro">Fișier comprimat UNIX</comment>
+ <comment xml:lang="pt_BR">Arquivo compactado do UNIX</comment>
+ <comment xml:lang="pt">ficheiro comprimido UNIX</comment>
+ <comment xml:lang="pl">Skompresowany plik systemu UNIX</comment>
+ <comment xml:lang="oc">fichièr compressat UNIX</comment>
+ <comment xml:lang="nn">UNIX-komprimert fil</comment>
+ <comment xml:lang="nl">UNIX-ingepakt bestand</comment>
+ <comment xml:lang="nb">UNIX-komprimert fil</comment>
+ <comment xml:lang="ms">Fail termampat-UNIX</comment>
+ <comment xml:lang="lv">UNIX saspiesta datne</comment>
+ <comment xml:lang="lt">UNIX suglaudintas failas</comment>
+ <comment xml:lang="ko">UNIX 압축 파일</comment>
+ <comment xml:lang="kk">файл (UNIX-сығылған)</comment>
+ <comment xml:lang="ja">UNIX-compress ファイル</comment>
+ <comment xml:lang="it">File compresso-UNIX</comment>
+ <comment xml:lang="is">UNIX-þjöppuð skrá</comment>
+ <comment xml:lang="id">Berkas terkompresi UNIX</comment>
+ <comment xml:lang="ia">File comprimite de UNIX</comment>
+ <comment xml:lang="hu">UNIX tömörítésű fájl</comment>
+ <comment xml:lang="hr">UNIX sažeta datoteka</comment>
+ <comment xml:lang="he">קובץ בכיווץ UNIX</comment>
+ <comment xml:lang="gl">ficheiro comprimido de UNIX</comment>
+ <comment xml:lang="ga">comhad UNIX-comhbhrúite</comment>
+ <comment xml:lang="fur">file comprimût di UNIX</comment>
+ <comment xml:lang="fr">fichier compressé UNIX</comment>
+ <comment xml:lang="fo">UNIX-stappað fíla</comment>
+ <comment xml:lang="fi">UNIX-pakattu tiedosto</comment>
+ <comment xml:lang="eu">UNIX-en konprimitutako fitxategia</comment>
+ <comment xml:lang="es">archivo comprimido de Unix</comment>
+ <comment xml:lang="eo">UNIX-kunpremita dosiero</comment>
+ <comment xml:lang="en_GB">UNIX-compressed file</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο UNIX</comment>
+ <comment xml:lang="de">UNIX-komprimierte Datei</comment>
+ <comment xml:lang="da">UNIX-komprimeret fil</comment>
+ <comment xml:lang="cs">soubor komprimovaný v Unixu</comment>
+ <comment xml:lang="ca">fitxer amb compressió UNIX</comment>
+ <comment xml:lang="bg">Файл — компресиран за UNIX</comment>
+ <comment xml:lang="be@latin">Skampresavany UNIX-fajł</comment>
+ <comment xml:lang="be">файл сціснуты UNIX</comment>
+ <comment xml:lang="ar">ملف يونكس-مضغوط</comment>
+ <comment xml:lang="af">UNIX-saamgepersde lêer</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="\037\235" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\037\235" offset="0"/>
</magic>
<glob pattern="*.Z"/>
</mime-type>
<mime-type type="application/x-compressed-tar">
<comment>Tar archive (gzip-compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط-gzip)</comment>
- <comment xml:lang="be@latin">Archiŭ tar (gzip-skampresavany)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран с gzip</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió gzip)</comment>
- <comment xml:lang="cs">archiv tar (komprimovaný pomocí gzip)</comment>
- <comment xml:lang="da">Tar-arkiv (gzip-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (gzip-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με gzip)</comment>
- <comment xml:lang="en_GB">Tar archive (gzip-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con gzip)</comment>
- <comment xml:lang="eu">Tar artxiboa (gzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (gzip-pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn (gzip-stappað)</comment>
- <comment xml:lang="fr">archive tar (compressée gzip)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido con gzip)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">Tar arhiva (gzip sažeta)</comment>
- <comment xml:lang="hu">Tar archívum (gzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite con gzip)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi gzip)</comment>
- <comment xml:lang="it">Archivio tar (compresso con gzip)</comment>
- <comment xml:lang="ja">Tar アーカイブ (gzip 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(GZIP 압축)</comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests ar gzip)</comment>
- <comment xml:lang="nb">Tar-arkiv (gzip-komprimert)</comment>
- <comment xml:lang="nl">Tar-archief (ingepakt met gzip)</comment>
- <comment xml:lang="nn">Tar-arkiv (pakka med gzip)</comment>
- <comment xml:lang="oc">archiu tar (compressat gzip)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja gzip)</comment>
- <comment xml:lang="pt">arquivo Tar (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado com gzip)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată gzip)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый gzip)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou gzip)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z gzip)</comment>
- <comment xml:lang="sq">Arkiv tar (i kompresuar me gzip)</comment>
- <comment xml:lang="sr">Тар архива (запакована гзипом)</comment>
- <comment xml:lang="sv">Tar-arkiv (gzip-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений gzip)</comment>
- <comment xml:lang="vi">Kho nén tar (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Kho nén tar (đã nén gzip)</comment>
+ <comment xml:lang="uk">архів tar (стиснений gzip)</comment>
+ <comment xml:lang="tr">Tar arşivi (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (gzip-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована гзипом)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z gzip)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (gzip-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou gzip)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый gzip)</comment>
+ <comment xml:lang="ro">Arhivă Tar (comprimată gzip)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado com gzip)</comment>
+ <comment xml:lang="pt">arquivo Tar (compressão gzip)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja gzip)</comment>
+ <comment xml:lang="oc">archiu tar (compressat gzip)</comment>
+ <comment xml:lang="nn">Tar-arkiv (pakka med gzip)</comment>
+ <comment xml:lang="nl">Tar-archief (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">Tar-arkiv (gzip-komprimert)</comment>
+ <comment xml:lang="lv">Tar arhīvs (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">Tar archyvas (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(GZIP 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (gzip-пен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (gzip 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con gzip)</comment>
+ <comment xml:lang="is">Tar safnskrá (Gzip þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Archivo Tar (comprimite con gzip)</comment>
+ <comment xml:lang="hu">Tar archívum (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (gzip sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י gzip)</comment>
+ <comment xml:lang="gl">arquivo Tar (comprimido con gzip)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun gzip)</comment>
+ <comment xml:lang="fr">archive tar (compressée gzip)</comment>
+ <comment xml:lang="fo">Tar skjalasavn (gzip-stappað)</comment>
+ <comment xml:lang="fi">Tar-arkisto (gzip-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (gzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con GZIP)</comment>
+ <comment xml:lang="en_GB">Tar archive (gzip-compressed)</comment>
+ <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με gzip)</comment>
+ <comment xml:lang="de">Tar-Archiv (gzip-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (gzip-komprimeret)</comment>
+ <comment xml:lang="cs">archiv tar (komprimovaný pomocí gzip)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с gzip</comment>
+ <comment xml:lang="be@latin">Archiŭ tar (gzip-skampresavany)</comment>
+ <comment xml:lang="be">архіў tar (сцісканне gzip)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-gzip)</comment>
+ <comment xml:lang="af">Tar-argief (gzip-saamgepers)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.tar.gz"/>
<glob pattern="*.tgz"/>
</mime-type>
<mime-type type="application/x-core">
- <comment>program crash data</comment>
- <comment xml:lang="ar">معلومات انهيار البرنامج</comment>
- <comment xml:lang="be@latin">źviestki złamanaj prahramy</comment>
- <comment xml:lang="bg">Данни от забиване на програма</comment>
- <comment xml:lang="ca">dades de fallada de programa</comment>
- <comment xml:lang="cs">data o pádu programu</comment>
- <comment xml:lang="da">programnedbrudsdata</comment>
- <comment xml:lang="de">Daten zu Programmabsturz</comment>
- <comment xml:lang="el">δεδομένα από την κατάρρευση προγράμματος</comment>
- <comment xml:lang="en_GB">program crash data</comment>
- <comment xml:lang="eo">datumo pri kraŝo de programo</comment>
- <comment xml:lang="es">datos de cuelgue de programa</comment>
- <comment xml:lang="eu">programaren kraskaduraren datuak</comment>
- <comment xml:lang="fi">ohjelman kaatumistiedot</comment>
- <comment xml:lang="fo">forrits sordáta</comment>
- <comment xml:lang="fr">données de plantage de programme</comment>
- <comment xml:lang="ga">sonraí tuairte ríomhchláir</comment>
- <comment xml:lang="gl">datos de colgue do programa</comment>
- <comment xml:lang="he">מידע מקריסת תכנית</comment>
- <comment xml:lang="hr">podaci o rušenju programa</comment>
- <comment xml:lang="hu">összeomlott program adatai</comment>
- <comment xml:lang="ia">Datos de fallimento de programma</comment>
- <comment xml:lang="id">data program macet</comment>
- <comment xml:lang="it">Dati crash di applicazione</comment>
- <comment xml:lang="ja">プログラムクラッシュデータ</comment>
- <comment xml:lang="kk">апатты аяқтаудың мәліметтері</comment>
- <comment xml:lang="ko">프로그램 비정상 종료 데이터</comment>
- <comment xml:lang="lt">programos nulūžimo duomenys</comment>
- <comment xml:lang="lv">programmas avārijas dati</comment>
- <comment xml:lang="ms">Data program musnah</comment>
- <comment xml:lang="nb">krasjdata fra program</comment>
- <comment xml:lang="nl">programma-crashgegevens</comment>
- <comment xml:lang="nn">data om programkrasj</comment>
- <comment xml:lang="oc">donadas de plantage de programa</comment>
- <comment xml:lang="pl">Dane awarii programu</comment>
- <comment xml:lang="pt">dados de rebentamento de aplicação</comment>
- <comment xml:lang="pt_BR">Dados de travamento de programa</comment>
- <comment xml:lang="ro">date eroare program</comment>
+ <comment>Program crash data</comment>
+ <comment xml:lang="uk">дані щодо аварії програми</comment>
+ <comment xml:lang="sv">Programkraschdata</comment>
<comment xml:lang="ru">Данные аварийного завершения программы</comment>
- <comment xml:lang="sk">Údaje o páde programu</comment>
- <comment xml:lang="sl">podatki sesutja programa</comment>
- <comment xml:lang="sq">Të dhëna nga programi i bllokuar</comment>
- <comment xml:lang="sr">подаци о падовима програма</comment>
- <comment xml:lang="sv">programkraschdata</comment>
- <comment xml:lang="tr">program çökme verisi</comment>
- <comment xml:lang="uk">аварійні дані про програму</comment>
- <comment xml:lang="vi">dữ liệu sụp đổ chương trình</comment>
- <comment xml:lang="zh_CN">程序崩溃数据</comment>
- <comment xml:lang="zh_TW">程式當掉資料</comment>
- <magic priority="50">
- <match value="\177ELF \004" type="string" offset="0" mask="0xffffffff000000000000000000000000ff"/>
- <match value="\177ELF" type="string" offset="0">
- <match value="1" type="byte" offset="5">
- <match value="4" type="little16" offset="16"/>
+ <comment xml:lang="pl">Dane awarii programu</comment>
+ <comment xml:lang="it">Dati crash di applicazione</comment>
+ <comment xml:lang="es">datos de cierre inesperado de programa</comment>
+ <comment xml:lang="de">Programmabsturz-Daten</comment>
+ <comment xml:lang="be">даныя пра збой праграмы</comment>
+ <magic>
+ <match type="string" mask="0xffffffff000000000000000000000000ff" value="\177ELF \004" offset="0"/>
+ <match type="string" value="\177ELF" offset="0">
+ <match type="byte" value="1" offset="5">
+ <match type="little16" value="4" offset="16"/>
</match>
</match>
- <match value="\177ELF" type="string" offset="0">
- <match value="2" type="byte" offset="5">
- <match value="4" type="big16" offset="16"/>
+ <match type="string" value="\177ELF" offset="0">
+ <match type="byte" value="2" offset="5">
+ <match type="big16" value="4" offset="16"/>
</match>
</match>
- <match value="Core\001" type="string" offset="0"/>
- <match value="Core\002" type="string" offset="0"/>
+ <match type="string" value="Core\001" offset="0"/>
+ <match type="string" value="Core\002" offset="0"/>
</magic>
<glob pattern="core" case-sensitive="true"/>
</mime-type>
<mime-type type="application/x-cpio">
<comment>CPIO archive</comment>
- <comment xml:lang="ar">أرشيف CPIO</comment>
- <comment xml:lang="ast">Archivu CPIO</comment>
- <comment xml:lang="az">CPIO arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ CPIO</comment>
- <comment xml:lang="bg">Архив — CPIO</comment>
- <comment xml:lang="ca">arxiu CPIO</comment>
- <comment xml:lang="cs">archiv CPIO</comment>
- <comment xml:lang="cy">Archif CPIO</comment>
- <comment xml:lang="da">CPIO-arkiv</comment>
- <comment xml:lang="de">CPIO-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο CPIO</comment>
- <comment xml:lang="en_GB">CPIO archive</comment>
- <comment xml:lang="eo">CPIO-arkivo</comment>
- <comment xml:lang="es">archivador CPIO</comment>
- <comment xml:lang="eu">CPIO artxiboa</comment>
- <comment xml:lang="fi">CPIO-arkisto</comment>
- <comment xml:lang="fo">CPIO skjalasavn</comment>
- <comment xml:lang="fr">archive CPIO</comment>
- <comment xml:lang="ga">cartlann CPIO</comment>
- <comment xml:lang="gl">arquivo CPIO</comment>
- <comment xml:lang="he">ארכיון CPIO</comment>
- <comment xml:lang="hr">CPIO arhiva</comment>
- <comment xml:lang="hu">CPIO-archívum</comment>
- <comment xml:lang="ia">Archivo CPIO</comment>
- <comment xml:lang="id">Arsip CPIO</comment>
- <comment xml:lang="it">Archivio CPIO</comment>
- <comment xml:lang="ja">CPIO アーカイブ</comment>
- <comment xml:lang="ka">CPIO არქივი</comment>
- <comment xml:lang="kk">CPIO архиві</comment>
- <comment xml:lang="ko">CPIO 묶음 파일</comment>
- <comment xml:lang="lt">CPIO archyvas</comment>
- <comment xml:lang="lv">CPIO arhīvs</comment>
- <comment xml:lang="ms">Arkib CPIO</comment>
- <comment xml:lang="nb">CPIO-arkiv</comment>
- <comment xml:lang="nl">CPIO-archief</comment>
- <comment xml:lang="nn">CPIO-arkiv</comment>
- <comment xml:lang="oc">archiu CPIO</comment>
- <comment xml:lang="pl">Archiwum CPIO</comment>
- <comment xml:lang="pt">arquivo CPIO</comment>
- <comment xml:lang="pt_BR">Pacote CPIO</comment>
- <comment xml:lang="ro">Arhivă CPIO</comment>
- <comment xml:lang="ru">Архив CPIO</comment>
- <comment xml:lang="sk">Archív CPIO</comment>
- <comment xml:lang="sl">Datoteka arhiva CPIO</comment>
- <comment xml:lang="sq">Arkiv CPIO</comment>
- <comment xml:lang="sr">ЦПИО архива</comment>
- <comment xml:lang="sv">CPIO-arkiv</comment>
- <comment xml:lang="tr">CPIO arşivi</comment>
- <comment xml:lang="uk">архів CPIO</comment>
- <comment xml:lang="vi">Kho nén CPIO</comment>
- <comment xml:lang="zh_CN">CPIO 归档文件</comment>
<comment xml:lang="zh_TW">CPIO 封存檔</comment>
+ <comment xml:lang="zh_CN">CPIO 归档文件</comment>
+ <comment xml:lang="vi">Kho nén CPIO</comment>
+ <comment xml:lang="uk">архів CPIO</comment>
+ <comment xml:lang="tr">CPIO arşivi</comment>
+ <comment xml:lang="sv">CPIO-arkiv</comment>
+ <comment xml:lang="sr">ЦПИО архива</comment>
+ <comment xml:lang="sq">arkiv CPIO</comment>
+ <comment xml:lang="sl">Datoteka arhiva CPIO</comment>
+ <comment xml:lang="si">CPIO ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív CPIO</comment>
+ <comment xml:lang="ru">Архив CPIO</comment>
+ <comment xml:lang="ro">Arhivă CPIO</comment>
+ <comment xml:lang="pt_BR">Pacote CPIO</comment>
+ <comment xml:lang="pt">arquivo CPIO</comment>
+ <comment xml:lang="pl">Archiwum CPIO</comment>
+ <comment xml:lang="oc">archiu CPIO</comment>
+ <comment xml:lang="nn">CPIO-arkiv</comment>
+ <comment xml:lang="nl">CPIO-archief</comment>
+ <comment xml:lang="nb">CPIO-arkiv</comment>
+ <comment xml:lang="ms">Arkib CPIO</comment>
+ <comment xml:lang="lv">CPIO arhīvs</comment>
+ <comment xml:lang="lt">CPIO archyvas</comment>
+ <comment xml:lang="ko">CPIO 묶음 파일</comment>
+ <comment xml:lang="kk">CPIO архиві</comment>
+ <comment xml:lang="ka">CPIO არქივი</comment>
+ <comment xml:lang="ja">CPIO アーカイブ</comment>
+ <comment xml:lang="it">Archivio CPIO</comment>
+ <comment xml:lang="is">CPIO safnskrá</comment>
+ <comment xml:lang="id">Arsip CPIO</comment>
+ <comment xml:lang="ia">Archivo CPIO</comment>
+ <comment xml:lang="hu">CPIO-archívum</comment>
+ <comment xml:lang="hr">CPIO arhiva</comment>
+ <comment xml:lang="he">ארכיון CPIO</comment>
+ <comment xml:lang="gl">arquivo CPIO</comment>
+ <comment xml:lang="ga">cartlann CPIO</comment>
+ <comment xml:lang="fur">archivi CPIO</comment>
+ <comment xml:lang="fr">archive CPIO</comment>
+ <comment xml:lang="fo">CPIO skjalasavn</comment>
+ <comment xml:lang="fi">CPIO-arkisto</comment>
+ <comment xml:lang="eu">CPIO artxiboa</comment>
+ <comment xml:lang="es">archivador CPIO</comment>
+ <comment xml:lang="eo">CPIO-arkivo</comment>
+ <comment xml:lang="en_GB">CPIO archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο CPIO</comment>
+ <comment xml:lang="de">CPIO-Archiv</comment>
+ <comment xml:lang="da">CPIO-arkiv</comment>
+ <comment xml:lang="cy">Archif CPIO</comment>
+ <comment xml:lang="cs">archiv CPIO</comment>
+ <comment xml:lang="ca">arxiu CPIO</comment>
+ <comment xml:lang="bg">Архив — CPIO</comment>
+ <comment xml:lang="be@latin">Archiŭ CPIO</comment>
+ <comment xml:lang="be">архіў CPIO</comment>
+ <comment xml:lang="az">CPIO arxivi</comment>
+ <comment xml:lang="ast">Archivu CPIO</comment>
+ <comment xml:lang="ar">أرشيف CPIO</comment>
+ <comment xml:lang="af">CPIO-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="070707" type="host16" offset="0"/>
- <match value="070701" type="string" offset="0"/>
- <match value="070702" type="string" offset="0"/>
- <match value="0143561" type="host16" offset="0"/>
+ <match type="host16" value="070707" offset="0"/>
+ <match type="string" value="070701" offset="0"/>
+ <match type="string" value="070702" offset="0"/>
+ <match type="host16" value="0143561" offset="0"/>
</magic>
<glob pattern="*.cpio"/>
</mime-type>
<mime-type type="application/x-cpio-compressed">
<comment>CPIO archive (gzip-compressed)</comment>
- <comment xml:lang="ar">أرشيف CPIO (مضغوط-gzip)</comment>
- <comment xml:lang="az">CPIO arxivi (gzip ilə sıxışdırılmış)</comment>
- <comment xml:lang="be@latin">Archiŭ CPIO (gzip-skampresavany)</comment>
- <comment xml:lang="bg">Архив — CPIO, компресиран с gzip</comment>
- <comment xml:lang="ca">arxiu CPIO (amb compressió gzip)</comment>
- <comment xml:lang="cs">archiv CPIO (komprimovaný pomocí gzip)</comment>
- <comment xml:lang="cy">Archif CPIO (gywasgwyd drwy gzip)</comment>
- <comment xml:lang="da">CPIO-arkiv (gzip-komprimeret)</comment>
- <comment xml:lang="de">CPIO-Archiv (gzip-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο CPIO (συμπιεσμένο με gzip)</comment>
- <comment xml:lang="en_GB">CPIO archive (gzip-compressed)</comment>
- <comment xml:lang="eo">CPIO-arkivo (kunpremita per gzip)</comment>
- <comment xml:lang="es">archivador CPIO (comprimido con gzip)</comment>
- <comment xml:lang="eu">CPIO artxiboa (gzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">CPIO-arkisto (gzip-pakattu)</comment>
- <comment xml:lang="fo">CPIO skjalasavn (gzip-stappað)</comment>
- <comment xml:lang="fr">archive CPIO (compressé gzip)</comment>
- <comment xml:lang="ga">cartlann CPIO (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">arquivo CPIO (comprimido con gzip)</comment>
- <comment xml:lang="he">ארכיון CPIO (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">CPIO arhiva (gzip sažeta)</comment>
- <comment xml:lang="hu">CPIO-archívum (gzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Archivo CPIO (comprimite con gzip)</comment>
- <comment xml:lang="id">Arsip CPIO (terkompresi gzip)</comment>
- <comment xml:lang="it">Archivio CPIO (compresso con gzip)</comment>
- <comment xml:lang="ja">CPIO (gzip 圧縮) アーカイブ</comment>
- <comment xml:lang="ka">CPIO არქივი (gzip-ით შეკუმშული)</comment>
- <comment xml:lang="kk">CPIO архиві (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">CPIO 묶음 파일(GZIP 압축)</comment>
- <comment xml:lang="lt">CPIO archyvas (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">CPIO arhīvs (saspiests ar gzip)</comment>
- <comment xml:lang="ms">Arkib CPIO (dimampatkan-gzip)</comment>
- <comment xml:lang="nb">CPIO-arkiv (gzip-komprimert)</comment>
- <comment xml:lang="nl">CPIO-archief (ingepakt met gzip)</comment>
- <comment xml:lang="nn">CPIO-arkiv (gzip-pakka)</comment>
- <comment xml:lang="oc">archiu CPIO (compressat gzip)</comment>
- <comment xml:lang="pl">Archiwum CPIO (kompresja gzip)</comment>
- <comment xml:lang="pt">arquivo CPIO (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Pacote CPIO (compactado com gzip)</comment>
- <comment xml:lang="ro">Arhivă CPIO (compresie gzip)</comment>
- <comment xml:lang="ru">Архив CPIO (сжатый gzip)</comment>
- <comment xml:lang="sk">Archív CPIO (komprimovaný pomocou gzip)</comment>
- <comment xml:lang="sl">Datoteka arhiva CPIO (skrčena z gzip)</comment>
- <comment xml:lang="sq">Arkiv CPIO (kompresuar me gzip)</comment>
- <comment xml:lang="sr">ЦПИО архива (компресована гзип-ом)</comment>
- <comment xml:lang="sv">CPIO-arkiv (gzip-komprimerat)</comment>
- <comment xml:lang="tr">CPIO arşivi (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів CPIO (стиснений gzip)</comment>
- <comment xml:lang="vi">Kho nén CPIO (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">CPIO 封存檔 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">CPIO 归档文件(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">CPIO 封存檔 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Kho nén CPIO (đã nén gzip)</comment>
+ <comment xml:lang="uk">архів CPIO (стиснений gzip)</comment>
+ <comment xml:lang="tr">CPIO arşivi (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">CPIO-arkiv (gzip-komprimerat)</comment>
+ <comment xml:lang="sr">ЦПИО архива (компресована гзип-ом)</comment>
+ <comment xml:lang="sq">arkiv CPIO (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Datoteka arhiva CPIO (skrčena z gzip)</comment>
+ <comment xml:lang="si">CPIO සංරක්ෂිතය (gzip-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív CPIO (komprimovaný pomocou gzip)</comment>
+ <comment xml:lang="ru">Архив CPIO (сжатый gzip)</comment>
+ <comment xml:lang="ro">Arhivă CPIO (compresie gzip)</comment>
+ <comment xml:lang="pt_BR">Pacote CPIO (compactado com gzip)</comment>
+ <comment xml:lang="pt">arquivo CPIO (compressão gzip)</comment>
+ <comment xml:lang="pl">Archiwum CPIO (kompresja gzip)</comment>
+ <comment xml:lang="oc">archiu CPIO (compressat gzip)</comment>
+ <comment xml:lang="nn">CPIO-arkiv (gzip-pakka)</comment>
+ <comment xml:lang="nl">CPIO-archief (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">CPIO-arkiv (gzip-komprimert)</comment>
+ <comment xml:lang="ms">Arkib CPIO (dimampatkan-gzip)</comment>
+ <comment xml:lang="lv">CPIO arhīvs (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">CPIO archyvas (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">CPIO 묶음 파일(GZIP 압축)</comment>
+ <comment xml:lang="kk">CPIO архиві (gzip-пен сығылған)</comment>
+ <comment xml:lang="ka">CPIO არქივი (gzip-ით შეკუმშული)</comment>
+ <comment xml:lang="ja">CPIO (gzip 圧縮) アーカイブ</comment>
+ <comment xml:lang="it">Archivio CPIO (compresso con gzip)</comment>
+ <comment xml:lang="is">CPIO safnskrá (Gzip þjappað)</comment>
+ <comment xml:lang="id">Arsip CPIO (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Archivo CPIO (comprimite con gzip)</comment>
+ <comment xml:lang="hu">CPIO archívum (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">CPIO arhiva (gzip sažeta)</comment>
+ <comment xml:lang="he">ארכיון CPIO (מכווץ ע״י gzip)</comment>
+ <comment xml:lang="gl">arquivo CPIO (comprimido con gzip)</comment>
+ <comment xml:lang="ga">cartlann CPIO (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">archivi CPIO (comprimût cun gzip)</comment>
+ <comment xml:lang="fr">archive CPIO (compressé gzip)</comment>
+ <comment xml:lang="fo">CPIO skjalasavn (gzip-stappað)</comment>
+ <comment xml:lang="fi">CPIO-arkisto (gzip-pakattu)</comment>
+ <comment xml:lang="eu">CPIO artxiboa (gzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">archivador CPIO (comprimido con GZIP)</comment>
+ <comment xml:lang="eo">CPIO-arkivo (kunpremita per gzip)</comment>
+ <comment xml:lang="en_GB">CPIO archive (gzip-compressed)</comment>
+ <comment xml:lang="el">Αρχείο CPIO (συμπιεσμένο με gzip)</comment>
+ <comment xml:lang="de">CPIO-Archiv (gzip-komprimiert)</comment>
+ <comment xml:lang="da">CPIO-arkiv (gzip-komprimeret)</comment>
+ <comment xml:lang="cy">Archif CPIO (gywasgwyd drwy gzip)</comment>
+ <comment xml:lang="cs">archiv CPIO (komprimovaný pomocí gzip)</comment>
+ <comment xml:lang="ca">arxiu CPIO (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Архив — CPIO, компресиран с gzip</comment>
+ <comment xml:lang="be@latin">Archiŭ CPIO (gzip-skampresavany)</comment>
+ <comment xml:lang="be">архіў CPIO (сцісканне gzip)</comment>
+ <comment xml:lang="az">CPIO arxivi (gzip ilə sıxışdırılmış)</comment>
+ <comment xml:lang="ar">أرشيف CPIO (مضغوط-gzip)</comment>
+ <comment xml:lang="af">CPIO-argief (gzip-saamgepers)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.cpio.gz"/>
</mime-type>
+ <mime-type type="application/x-perf-data">
+ <comment>Perf data</comment>
+ <comment xml:lang="uk">дані Perf</comment>
+ <comment xml:lang="sv">Perf-data</comment>
+ <comment xml:lang="ru">Данные Perf</comment>
+ <comment xml:lang="pl">Dane wydajności</comment>
+ <comment xml:lang="it">Dati perf</comment>
+ <comment xml:lang="gl">Datos de Perf</comment>
+ <comment xml:lang="es">datos de rendimiento</comment>
+ <comment xml:lang="de">Leistungsdaten</comment>
+ <glob pattern="perf.data" case-sensitive="true"/>
+ <magic priority="50">
+ <match type="string" value="PERFILE2" offset="0"/>
+ </magic>
+ </mime-type>
<mime-type type="application/x-csh">
<comment>C shell script</comment>
- <comment xml:lang="ar">سكربت شِل سي</comment>
- <comment xml:lang="az">C qabıq skripti</comment>
- <comment xml:lang="be@latin">Skrypt abałonki C</comment>
- <comment xml:lang="bg">Скрипт — обвивка C</comment>
- <comment xml:lang="ca">script C shell</comment>
- <comment xml:lang="cs">skript shellu C</comment>
- <comment xml:lang="cy">Sgript plisgyn C</comment>
- <comment xml:lang="da">C-skalprogram</comment>
- <comment xml:lang="de">C-Shell-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών κελύφους C</comment>
- <comment xml:lang="en_GB">C shell script</comment>
- <comment xml:lang="eo">skripto de C-ŝelo</comment>
- <comment xml:lang="es">secuencia de órdenes de consola en C</comment>
- <comment xml:lang="eu">C shell script-a</comment>
- <comment xml:lang="fi">Csh-komentotiedosto</comment>
- <comment xml:lang="fo">C skel boðrøð</comment>
- <comment xml:lang="fr">script C shell</comment>
- <comment xml:lang="ga">script bhlaoisce C</comment>
- <comment xml:lang="gl">script de C shell</comment>
- <comment xml:lang="he">תסריט מעטפת C</comment>
- <comment xml:lang="hr">C skripta ljuske</comment>
- <comment xml:lang="hu">C héj-parancsfájl</comment>
- <comment xml:lang="ia">Script C-shell</comment>
- <comment xml:lang="id">Skrip shell C</comment>
- <comment xml:lang="it">Script C shell</comment>
- <comment xml:lang="ja">C シェルスクリプト</comment>
- <comment xml:lang="kk">C shell сценарийі</comment>
- <comment xml:lang="ko">C 셸 스크립트</comment>
- <comment xml:lang="lt">C shell scenarijus</comment>
- <comment xml:lang="lv">C čaulas skripts</comment>
- <comment xml:lang="ms">Skrip shell C</comment>
- <comment xml:lang="nb">C-skallskript</comment>
- <comment xml:lang="nl">C-shellscript</comment>
- <comment xml:lang="nn">C-skalskript</comment>
- <comment xml:lang="oc">escript C shell</comment>
- <comment xml:lang="pl">Skrypt powłoki C</comment>
- <comment xml:lang="pt">script de terminal C</comment>
- <comment xml:lang="pt_BR">Script de shell C</comment>
- <comment xml:lang="ro">Script C shell</comment>
- <comment xml:lang="ru">Сценарий C shell</comment>
- <comment xml:lang="sk">Skript shellu C</comment>
- <comment xml:lang="sl">Skriptna datoteka lupine C</comment>
- <comment xml:lang="sq">Script shell C</comment>
- <comment xml:lang="sr">скрипта Ц шкољке</comment>
- <comment xml:lang="sv">Skalskript (csh)</comment>
- <comment xml:lang="tr">C kabuk betiği</comment>
- <comment xml:lang="uk">скрипт оболонки C</comment>
- <comment xml:lang="vi">Văn lệnh trình bao C</comment>
- <comment xml:lang="zh_CN">C shell 脚本</comment>
<comment xml:lang="zh_TW">C shell 指令稿</comment>
+ <comment xml:lang="zh_CN">C shell 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh trình bao C</comment>
+ <comment xml:lang="uk">скрипт оболонки C</comment>
+ <comment xml:lang="tr">C kabuk betiği</comment>
+ <comment xml:lang="sv">Skalskript (csh)</comment>
+ <comment xml:lang="sr">скрипта Ц шкољке</comment>
+ <comment xml:lang="sq">programth C shell</comment>
+ <comment xml:lang="sl">Skriptna datoteka lupine C</comment>
+ <comment xml:lang="si">C shell පිටපත</comment>
+ <comment xml:lang="sk">Skript shellu C</comment>
+ <comment xml:lang="ru">Сценарий C shell</comment>
+ <comment xml:lang="ro">Script C shell</comment>
+ <comment xml:lang="pt_BR">Script de shell C</comment>
+ <comment xml:lang="pt">script de terminal C</comment>
+ <comment xml:lang="pl">Skrypt powłoki C</comment>
+ <comment xml:lang="oc">escript C shell</comment>
+ <comment xml:lang="nn">C-skalskript</comment>
+ <comment xml:lang="nl">C-shellscript</comment>
+ <comment xml:lang="nb">C-skallskript</comment>
+ <comment xml:lang="ms">Skrip shell C</comment>
+ <comment xml:lang="lv">C čaulas skripts</comment>
+ <comment xml:lang="lt">C shell scenarijus</comment>
+ <comment xml:lang="ko">C 셸 스크립트</comment>
+ <comment xml:lang="kk">C shell сценарийі</comment>
+ <comment xml:lang="ja">C シェルスクリプト</comment>
+ <comment xml:lang="it">Script C shell</comment>
+ <comment xml:lang="is">C skjeljarskrifta</comment>
+ <comment xml:lang="id">Skrip shell C</comment>
+ <comment xml:lang="ia">Script C-shell</comment>
+ <comment xml:lang="hu">C héj-parancsfájl</comment>
+ <comment xml:lang="hr">C skripta ljuske</comment>
+ <comment xml:lang="he">תסריט מעטפת C</comment>
+ <comment xml:lang="gl">script de C shell</comment>
+ <comment xml:lang="ga">script bhlaoisce C</comment>
+ <comment xml:lang="fur">script di shell in C</comment>
+ <comment xml:lang="fr">script C shell</comment>
+ <comment xml:lang="fo">C skel boðrøð</comment>
+ <comment xml:lang="fi">C shell -komentotiedosto</comment>
+ <comment xml:lang="eu">C shell script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes de consola en C</comment>
+ <comment xml:lang="eo">skripto de C-ŝelo</comment>
+ <comment xml:lang="en_GB">C shell script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών κελύφους C</comment>
+ <comment xml:lang="de">C-Shell-Skript</comment>
+ <comment xml:lang="da">C-skalprogram</comment>
+ <comment xml:lang="cy">Sgript plisgyn C</comment>
+ <comment xml:lang="cs">skript shellu C</comment>
+ <comment xml:lang="ca">script C shell</comment>
+ <comment xml:lang="bg">Скрипт — обвивка C</comment>
+ <comment xml:lang="be@latin">Skrypt abałonki C</comment>
+ <comment xml:lang="be">скрыпт C shell</comment>
+ <comment xml:lang="az">C qabıq skripti</comment>
+ <comment xml:lang="ar">سكربت شِل سي</comment>
+ <comment xml:lang="af">C shell-skrip</comment>
<sub-class-of type="application/x-shellscript"/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<magic>
- <match value="/bin/tcsh" type="string" offset="2:16"/>
- <match value="/bin/csh" type="string" offset="2:16"/>
- <match value="/bin/env csh" type="string" offset="2:16"/>
- <match value="/bin/env tcsh" type="string" offset="2:16"/>
+ <match type="string" value="/bin/tcsh" offset="2:16"/>
+ <match type="string" value="/bin/csh" offset="2:16"/>
+ <match type="string" value="/bin/env csh" offset="2:16"/>
+ <match type="string" value="/bin/env tcsh" offset="2:16"/>
</magic>
<glob pattern="*.csh"/>
</mime-type>
- <mime-type type="application/x-dbf">
+ <mime-type type="application/vnd.dbf">
<comment>Xbase document</comment>
- <comment xml:lang="ar">مستند Xbase</comment>
- <comment xml:lang="ast">Documentu Xbase</comment>
- <comment xml:lang="be@latin">Dakument Xbase</comment>
- <comment xml:lang="bg">Документ — Xbase</comment>
- <comment xml:lang="ca">document Xbase</comment>
- <comment xml:lang="cs">dokument Xbase</comment>
- <comment xml:lang="da">Xbasedokument</comment>
- <comment xml:lang="de">Xbase-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Xbase</comment>
- <comment xml:lang="en_GB">Xbase document</comment>
- <comment xml:lang="eo">Xbase-dokumento</comment>
- <comment xml:lang="es">documento Xbase</comment>
- <comment xml:lang="eu">Xbase dokumentua</comment>
- <comment xml:lang="fi">Xbase-asiakirja</comment>
- <comment xml:lang="fo">Xbase skjal</comment>
- <comment xml:lang="fr">document Xbase</comment>
- <comment xml:lang="ga">cáipéis Xbase</comment>
- <comment xml:lang="gl">documento Xbase</comment>
- <comment xml:lang="he">מסמך Xbase</comment>
- <comment xml:lang="hr">Xbase dokumenet</comment>
- <comment xml:lang="hu">Xbase dokumentum</comment>
- <comment xml:lang="ia">Documento Xbase</comment>
- <comment xml:lang="id">Dokumen Xbase</comment>
- <comment xml:lang="it">Documento Xbase</comment>
- <comment xml:lang="ja">Xbase ドキュメント</comment>
- <comment xml:lang="kk">Xbase құжаты</comment>
- <comment xml:lang="ko">Xbase 문서</comment>
- <comment xml:lang="lt">Xbase dokumentas</comment>
- <comment xml:lang="lv">Xbase dokuments</comment>
- <comment xml:lang="nb">Xbase-dokument</comment>
- <comment xml:lang="nl">Xbase-document</comment>
- <comment xml:lang="nn">Xbase-dokument</comment>
- <comment xml:lang="oc">document Xbase</comment>
- <comment xml:lang="pl">Dokument Xbase</comment>
- <comment xml:lang="pt">documento Xbase</comment>
- <comment xml:lang="pt_BR">Documento do Xbase</comment>
- <comment xml:lang="ro">Document Xbase</comment>
- <comment xml:lang="ru">Документ Xbase</comment>
- <comment xml:lang="sk">Dokument Xbase</comment>
- <comment xml:lang="sl">Dokument Xbase</comment>
- <comment xml:lang="sq">Dokument Xbase</comment>
- <comment xml:lang="sr">документ Иксбазе</comment>
- <comment xml:lang="sv">Xbase-dokument</comment>
- <comment xml:lang="tr">Xbase belgesi</comment>
- <comment xml:lang="uk">документ Xbase</comment>
- <comment xml:lang="vi">Tài liệu Xbase</comment>
- <comment xml:lang="zh_CN">Xbase 文档</comment>
<comment xml:lang="zh_TW">Xbase 文件</comment>
+ <comment xml:lang="zh_CN">Xbase 文档</comment>
+ <comment xml:lang="vi">Tài liệu Xbase</comment>
+ <comment xml:lang="uk">документ Xbase</comment>
+ <comment xml:lang="tr">Xbase belgesi</comment>
+ <comment xml:lang="sv">Xbase-dokument</comment>
+ <comment xml:lang="sr">документ Иксбазе</comment>
+ <comment xml:lang="sq">dokument Xbase</comment>
+ <comment xml:lang="sl">Dokument Xbase</comment>
+ <comment xml:lang="si">Xbase ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Xbase</comment>
+ <comment xml:lang="ru">Документ Xbase</comment>
+ <comment xml:lang="ro">Document Xbase</comment>
+ <comment xml:lang="pt_BR">Documento do Xbase</comment>
+ <comment xml:lang="pt">documento Xbase</comment>
+ <comment xml:lang="pl">Dokument Xbase</comment>
+ <comment xml:lang="oc">document Xbase</comment>
+ <comment xml:lang="nn">Xbase-dokument</comment>
+ <comment xml:lang="nl">Xbase-document</comment>
+ <comment xml:lang="nb">Xbase-dokument</comment>
+ <comment xml:lang="lv">Xbase dokuments</comment>
+ <comment xml:lang="lt">Xbase dokumentas</comment>
+ <comment xml:lang="ko">Xbase 문서</comment>
+ <comment xml:lang="kk">Xbase құжаты</comment>
+ <comment xml:lang="ja">Xbase ドキュメント</comment>
+ <comment xml:lang="it">Documento Xbase</comment>
+ <comment xml:lang="is">Xbase skjal</comment>
+ <comment xml:lang="id">Dokumen Xbase</comment>
+ <comment xml:lang="ia">Documento Xbase</comment>
+ <comment xml:lang="hu">Xbase dokumentum</comment>
+ <comment xml:lang="hr">Xbase dokumenet</comment>
+ <comment xml:lang="he">מסמך Xbase</comment>
+ <comment xml:lang="gl">documento Xbase</comment>
+ <comment xml:lang="ga">cáipéis Xbase</comment>
+ <comment xml:lang="fur">document Xbase</comment>
+ <comment xml:lang="fr">document Xbase</comment>
+ <comment xml:lang="fo">Xbase skjal</comment>
+ <comment xml:lang="fi">Xbase-asiakirja</comment>
+ <comment xml:lang="eu">Xbase dokumentua</comment>
+ <comment xml:lang="es">documento Xbase</comment>
+ <comment xml:lang="eo">Xbase-dokumento</comment>
+ <comment xml:lang="en_GB">Xbase document</comment>
+ <comment xml:lang="el">Έγγραφο Xbase</comment>
+ <comment xml:lang="de">Xbase-Dokument</comment>
+ <comment xml:lang="da">Xbasedokument</comment>
+ <comment xml:lang="cs">dokument Xbase</comment>
+ <comment xml:lang="ca">document Xbase</comment>
+ <comment xml:lang="bg">Документ — Xbase</comment>
+ <comment xml:lang="be@latin">Dakument Xbase</comment>
+ <comment xml:lang="be">дакумент Xbase</comment>
+ <comment xml:lang="ast">Documentu Xbase</comment>
+ <comment xml:lang="ar">مستند Xbase</comment>
+ <comment xml:lang="af">Xbase-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.dbf"/>
- <alias type="application/x-dbase"/>
- <alias type="application/dbf"/>
<alias type="application/dbase"/>
+ <alias type="application/dbf"/>
+ <alias type="application/x-dbase"/>
+ <alias type="application/x-dbf"/>
</mime-type>
<mime-type type="application/ecmascript">
<comment>ECMAScript program</comment>
- <comment xml:lang="ar">برنامج ECMAScript</comment>
- <comment xml:lang="be@latin">Prahrama ECMAScript</comment>
- <comment xml:lang="bg">Програма — ECMAScript</comment>
- <comment xml:lang="ca">programa ECMAScript</comment>
- <comment xml:lang="cs">program v jazyce ECMAScript</comment>
- <comment xml:lang="da">ECMA-program</comment>
- <comment xml:lang="de">ECMAScript-Programm</comment>
- <comment xml:lang="el">Πρόγραμμα ECMAScript</comment>
- <comment xml:lang="en_GB">ECMAScript program</comment>
- <comment xml:lang="es">programa en ECMAScript</comment>
- <comment xml:lang="eu">ECMAScript programa</comment>
- <comment xml:lang="fi">ECMAScript-ohjelma</comment>
- <comment xml:lang="fo">ECMAScript forrit</comment>
- <comment xml:lang="fr">programme ECMAScript</comment>
- <comment xml:lang="ga">ríomhchlár ECMAScript</comment>
- <comment xml:lang="gl">programa en ECMAScript</comment>
- <comment xml:lang="he">תכנית EMCAScript</comment>
- <comment xml:lang="hr">ECMAScript program</comment>
- <comment xml:lang="hu">ECMAScript program</comment>
- <comment xml:lang="ia">Programma ECMAScript</comment>
- <comment xml:lang="id">Program ECMAScript</comment>
- <comment xml:lang="it">Programma ECMAScript</comment>
- <comment xml:lang="ja">ECMAScript プログラム</comment>
- <comment xml:lang="ka">ECMAScript პროგრამა</comment>
- <comment xml:lang="kk">ECMAScript программасы</comment>
- <comment xml:lang="ko">ECMAScript 프로그램</comment>
- <comment xml:lang="lt">ECMAScript programa</comment>
- <comment xml:lang="lv">ECMAScript programma</comment>
- <comment xml:lang="nb">ECMAScript-program</comment>
- <comment xml:lang="nl">ECMAScript-programma</comment>
- <comment xml:lang="nn">ECMAScript-program</comment>
- <comment xml:lang="oc">programa ECMAEscript</comment>
- <comment xml:lang="pl">Pogram ECMAScript</comment>
- <comment xml:lang="pt">programa ECMAScript</comment>
- <comment xml:lang="pt_BR">Programa ECMAScript</comment>
- <comment xml:lang="ro">Program ECMAScript</comment>
- <comment xml:lang="ru">Программа ECMAScript</comment>
- <comment xml:lang="sk">Program ECMAScript</comment>
- <comment xml:lang="sl">Programska datoteka ECMAScript</comment>
- <comment xml:lang="sq">Program ECMAScript</comment>
- <comment xml:lang="sr">програм ЕЦМАСкрипте</comment>
- <comment xml:lang="sv">ECMAScript-program</comment>
- <comment xml:lang="tr">ECMAScript programı</comment>
- <comment xml:lang="uk">програма мовою ECMAScript</comment>
- <comment xml:lang="vi">Chương trình ECMAScript</comment>
- <comment xml:lang="zh_CN">ECMAScript 程序</comment>
<comment xml:lang="zh_TW">ECMAScript 程式</comment>
+ <comment xml:lang="zh_CN">ECMAScript 程序</comment>
+ <comment xml:lang="vi">Chương trình ECMAScript</comment>
+ <comment xml:lang="uk">програма мовою ECMAScript</comment>
+ <comment xml:lang="tr">ECMAScript programı</comment>
+ <comment xml:lang="sv">ECMAScript-program</comment>
+ <comment xml:lang="sr">програм ЕЦМАСкрипте</comment>
+ <comment xml:lang="sq">program ECMAScript</comment>
+ <comment xml:lang="sl">Programska datoteka ECMAScript</comment>
+ <comment xml:lang="si">ECMAScript වැඩසටහන</comment>
+ <comment xml:lang="sk">Program ECMAScript</comment>
+ <comment xml:lang="ru">Программа ECMAScript</comment>
+ <comment xml:lang="ro">Program ECMAScript</comment>
+ <comment xml:lang="pt_BR">Programa ECMAScript</comment>
+ <comment xml:lang="pt">programa ECMAScript</comment>
+ <comment xml:lang="pl">Pogram ECMAScript</comment>
+ <comment xml:lang="oc">programa ECMAEscript</comment>
+ <comment xml:lang="nn">ECMAScript-program</comment>
+ <comment xml:lang="nl">ECMAScript-programma</comment>
+ <comment xml:lang="nb">ECMAScript-program</comment>
+ <comment xml:lang="lv">ECMAScript programma</comment>
+ <comment xml:lang="lt">ECMAScript programa</comment>
+ <comment xml:lang="ko">ECMAScript 프로그램</comment>
+ <comment xml:lang="kk">ECMAScript программасы</comment>
+ <comment xml:lang="ka">ECMAScript პროგრამა</comment>
+ <comment xml:lang="ja">ECMAScript プログラム</comment>
+ <comment xml:lang="it">Programma ECMAScript</comment>
+ <comment xml:lang="is">ECMAScript forrit</comment>
+ <comment xml:lang="id">Program ECMAScript</comment>
+ <comment xml:lang="ia">Programma ECMAScript</comment>
+ <comment xml:lang="hu">ECMAScript program</comment>
+ <comment xml:lang="hr">ECMAScript program</comment>
+ <comment xml:lang="he">תכנית EMCAScript</comment>
+ <comment xml:lang="gl">programa en ECMAScript</comment>
+ <comment xml:lang="ga">ríomhchlár ECMAScript</comment>
+ <comment xml:lang="fur">program ECMAScript</comment>
+ <comment xml:lang="fr">programme ECMAScript</comment>
+ <comment xml:lang="fo">ECMAScript forrit</comment>
+ <comment xml:lang="fi">ECMAScript-ohjelma</comment>
+ <comment xml:lang="eu">ECMAScript programa</comment>
+ <comment xml:lang="es">programa en ECMAScript</comment>
+ <comment xml:lang="en_GB">ECMAScript program</comment>
+ <comment xml:lang="el">Πρόγραμμα ECMAScript</comment>
+ <comment xml:lang="de">ECMAScript-Programm</comment>
+ <comment xml:lang="da">ECMAScript-program</comment>
+ <comment xml:lang="cs">program v jazyce ECMAScript</comment>
+ <comment xml:lang="ca">programa ECMAScript</comment>
+ <comment xml:lang="bg">Програма — ECMAScript</comment>
+ <comment xml:lang="be@latin">Prahrama ECMAScript</comment>
+ <comment xml:lang="be">праграма ECMAScript</comment>
+ <comment xml:lang="ar">برنامج ECMAScript</comment>
+ <comment xml:lang="af">ECMAScript-program</comment>
<alias type="text/ecmascript"/>
- <sub-class-of type='application/x-executable'/>
- <sub-class-of type="text/plain"/>
+ <sub-class-of type="text/javascript"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.es"/>
</mime-type>
+ <mime-type type="application/x-mame-chd">
+ <comment>MAME compressed hard disk image</comment>
+ <comment xml:lang="uk">стиснений образ жорсткого диска MAME</comment>
+ <comment xml:lang="tr">MAME sıkıştırılmış sabit disk görüntüsü</comment>
+ <comment xml:lang="sv">MAME komprimerad hårddiskavbild</comment>
+ <comment xml:lang="sr">МАМЕ компресовани одраз диска</comment>
+ <comment xml:lang="si">MAME සම්පීඩිත දෘඪ තැටි රූපය</comment>
+ <comment xml:lang="ru">Сжатый образ жесткого диска MAME</comment>
+ <comment xml:lang="pt_BR">Imagem de disco rígido compactado do MAME</comment>
+ <comment xml:lang="pl">Skompresowany obraz dysku twardego MAME</comment>
+ <comment xml:lang="nl">met MAME gecomprimeerd harde-schijfkopiebestand</comment>
+ <comment xml:lang="ko">MAME 압축된 하드 디스크 이미지</comment>
+ <comment xml:lang="kk">MAME сығылған қатты диск бейнесі</comment>
+ <comment xml:lang="ja">MAME 圧縮ハーディディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco MAME compressa</comment>
+ <comment xml:lang="is">Þjöppuð MAME diskmynd</comment>
+ <comment xml:lang="id">image hard disk MAME terkompresi</comment>
+ <comment xml:lang="hu">MAME tömörített merevlemezkép</comment>
+ <comment xml:lang="hr">MAME komprimirane slike tvrdog diska</comment>
+ <comment xml:lang="he">דמות כונן קשיח בדחיסת MAME</comment>
+ <comment xml:lang="gl">Imaxe de disco duro comprimido MAME</comment>
+ <comment xml:lang="fr">Image de disque dur compressé MAME</comment>
+ <comment xml:lang="fi">MAME pakatun kiintolevyn levykuva</comment>
+ <comment xml:lang="es">imagen comprimida de disco duro de MAME</comment>
+ <comment xml:lang="en_GB">MAME compressed hard disk image</comment>
+ <comment xml:lang="de">MAME-komprimiertes Festplattenabbild</comment>
+ <comment xml:lang="da">MAME-komprimeret harddiskaftryk</comment>
+ <comment xml:lang="ca">imatge de disc dur MAME amb compressió</comment>
+ <comment xml:lang="be">сціснуты вобраз цвёрдага дыска MAME</comment>
+ <comment xml:lang="ar">صورة قرص صلب MAME مضغوطة</comment>
+ <generic-icon name="application-x-executable"/>
+ <magic>
+ <match type="string" value="MComprHD" offset="0"/>
+ </magic>
+ <glob pattern="*.chd"/>
+ </mime-type>
<mime-type type="application/x-sega-cd-rom">
-
+ <!-- Translate this to Mega-CD if the console was known as such in your locale
+ Should be Mega-CD in all but en_US, Mexico, Canada and Brazil: https://en.wikipedia.org/wiki/Sega_CD -->
<comment>Sega CD disc image</comment>
- <comment xml:lang="ast">Imaxe de discu de Sega CD</comment>
- <comment xml:lang="ca">imatge de disc de Sega CD</comment>
- <comment xml:lang="cs">obraz disku CD pro Sega</comment>
- <comment xml:lang="da">Sega CD-diskaftryk</comment>
- <comment xml:lang="de">Sega-CD-Datenträgerabbild</comment>
- <comment xml:lang="en_GB">Sega CD disc image</comment>
- <comment xml:lang="es">imagen de disco CD de Sega</comment>
- <comment xml:lang="eu">Sega CD disko irudia</comment>
- <comment xml:lang="fi">Sega CD -levykuva</comment>
- <comment xml:lang="fr">image disque Sega CD</comment>
- <comment xml:lang="ga">íomhá dlúthdhiosca Sega</comment>
- <comment xml:lang="he">דמות כונן Sega CD</comment>
- <comment xml:lang="hr">Sega CD slika diska</comment>
- <comment xml:lang="hu">Sega CD-lemezkép</comment>
- <comment xml:lang="id">image cakram CD Sega</comment>
- <comment xml:lang="it">Immagine disco Sega Mega CD</comment>
- <comment xml:lang="kk">Sega CD диск бейнесі</comment>
- <comment xml:lang="ko">세가 CD 디스크 이미지</comment>
- <comment xml:lang="pl">Obraz płyty konsoli Mega-CD</comment>
- <comment xml:lang="pt_BR">Imagem de disco Sega CD</comment>
- <comment xml:lang="ru">Образ диска CD Sega</comment>
- <comment xml:lang="sk">Obraz disku CD Sega</comment>
- <comment xml:lang="sr">одраз диска Сега ЦД-а</comment>
- <comment xml:lang="sv">Mega-CD-skivavbild</comment>
- <comment xml:lang="tr">Sega CD disk kalıbı</comment>
- <comment xml:lang="uk">образ диска Sega CD</comment>
- <comment xml:lang="zh_CN">Sega CD 光盘映像</comment>
<comment xml:lang="zh_TW">Sega CD 光碟映像檔</comment>
+ <comment xml:lang="zh_CN">Sega CD 光盘映像</comment>
+ <comment xml:lang="uk">образ диска Sega CD</comment>
+ <comment xml:lang="tr">Sega CD disk görüntüsü</comment>
+ <comment xml:lang="sv">Mega-CD-skivavbild</comment>
+ <comment xml:lang="sr">одраз диска Сега ЦД-а</comment>
+ <comment xml:lang="sq">pamje disku CD Sega</comment>
+ <comment xml:lang="sl">Slika diska CD Sega</comment>
+ <comment xml:lang="si">Sega CD තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku CD Sega</comment>
+ <comment xml:lang="ru">Образ диска CD Sega</comment>
+ <comment xml:lang="pt_BR">Imagem de disco Sega CD</comment>
+ <comment xml:lang="pt">imagem de disco Mega-CD</comment>
+ <comment xml:lang="pl">Obraz płyty konsoli Mega-CD</comment>
+ <comment xml:lang="oc">imatge disc Sega CD</comment>
+ <comment xml:lang="nl">Sega CD-schijfkopiebestand</comment>
+ <comment xml:lang="ko">세가 CD 디스크 이미지</comment>
+ <comment xml:lang="kk">Sega CD диск бейнесі</comment>
+ <comment xml:lang="ja">Sega CD ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco Sega Mega CD</comment>
+ <comment xml:lang="is">Sega CD diskmynd</comment>
+ <comment xml:lang="id">Image cakram CD Sega</comment>
+ <comment xml:lang="hu">Sega CD-lemezkép</comment>
+ <comment xml:lang="hr">Sega CD slika diska</comment>
+ <comment xml:lang="he">דמות כונן Sega CD</comment>
+ <comment xml:lang="gl">Imaxe de disco de Sega CD</comment>
+ <comment xml:lang="ga">íomhá dlúthdhiosca Sega</comment>
+ <comment xml:lang="fur">imagjin disc CD Sega</comment>
+ <comment xml:lang="fr">image disque Sega CD</comment>
+ <comment xml:lang="fi">Sega CD -levykuva</comment>
+ <comment xml:lang="eu">Sega CD disko irudia</comment>
+ <comment xml:lang="es">imagen de disco CD de Sega</comment>
+ <comment xml:lang="en_GB">Sega CD disc image</comment>
+ <comment xml:lang="de">Sega-CD-Datenträgerabbild</comment>
+ <comment xml:lang="da">Sega CD-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku CD pro Sega</comment>
+ <comment xml:lang="ca">imatge de disc de Sega CD</comment>
+ <comment xml:lang="bg">Диск — Mega-CD (Sega)</comment>
+ <comment xml:lang="be">вобраз CD-дыска Sega</comment>
+ <comment xml:lang="ast">Imaxe de discu de Sega CD</comment>
+ <comment xml:lang="ar">صورة قرص ميجا سي دي</comment>
+ <comment xml:lang="af">Mega CD-skyfbeeldlêer</comment>
<generic-icon name="application-x-executable"/>
-
+ <!-- Also matches the application/x-genesis-rom magic values, hence the higher priority -->
<magic priority="60">
- <match value="SEGADISCSYSTEM" type="string" offset="0">
- <match value="SEGA" type="string" offset="256"/>
+ <match type="string" value="SEGADISCSYSTEM" offset="0">
+ <match type="string" value="SEGA" offset="256"/>
</match>
- <match value="SEGADISCSYSTEM" type="string" offset="16">
- <match value="SEGA" type="string" offset="272"/>
+ <match type="string" value="SEGADISCSYSTEM" offset="16">
+ <match type="string" value="SEGA" offset="272"/>
</match>
</magic>
- <glob pattern="*.bin"/>
<glob pattern="*.iso"/>
</mime-type>
<mime-type type="application/x-sega-pico-rom">
-
+ <!-- Translate this to Kids Computer Pico if the console was known as such in your locale
+ Should be Sega Pico in all but Japan: https://en.wikipedia.org/wiki/Sega_Pico -->
<comment>Sega Pico ROM</comment>
- <comment xml:lang="ast">ROM de Sega Pico</comment>
- <comment xml:lang="ca">ROM de Sega Pico</comment>
- <comment xml:lang="cs">ROM pro Sega Pico</comment>
- <comment xml:lang="de">Sega Pico ROM</comment>
- <comment xml:lang="en_GB">Sega Pico ROM</comment>
- <comment xml:lang="es">ROM de Sega Pico</comment>
- <comment xml:lang="eu">Sega Pico ROM</comment>
- <comment xml:lang="fi">Sega Pico ROM</comment>
- <comment xml:lang="fr">ROM Sega Pico</comment>
- <comment xml:lang="ga">ROM Sega Pico</comment>
- <comment xml:lang="hr">Sega Pico ROM</comment>
- <comment xml:lang="hu">Sega Pico ROM</comment>
- <comment xml:lang="id">ROM Sega Pico</comment>
- <comment xml:lang="it">ROM Sega Pico</comment>
- <comment xml:lang="kk">Sega Pico ROM</comment>
- <comment xml:lang="ko">세카 피코 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Sega Pico</comment>
- <comment xml:lang="pt_BR">ROM de Sega Pico</comment>
- <comment xml:lang="ru">Sega Pico ROM</comment>
- <comment xml:lang="sk">ROM pre Sega Pico</comment>
- <comment xml:lang="sr">Сега Пико РОМ</comment>
- <comment xml:lang="sv">Sega Pico-rom</comment>
- <comment xml:lang="tr">Sega Pico ROM</comment>
- <comment xml:lang="uk">ППП Sega Pico</comment>
- <comment xml:lang="zh_CN">Sega Pico ROM</comment>
<comment xml:lang="zh_TW">Sega Pico ROM</comment>
+ <comment xml:lang="zh_CN">Sega Pico ROM</comment>
+ <comment xml:lang="uk">ППП Sega Pico</comment>
+ <comment xml:lang="tr">Sega Pico ROM</comment>
+ <comment xml:lang="sv">Sega Pico-rom</comment>
+ <comment xml:lang="sr">Сега Пико РОМ</comment>
+ <comment xml:lang="sq">ROM Sega Pico</comment>
+ <comment xml:lang="sl">Sega Pico ROM</comment>
+ <comment xml:lang="si">Sega Pico ROM</comment>
+ <comment xml:lang="sk">ROM pre Sega Pico</comment>
+ <comment xml:lang="ru">Sega Pico ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Sega Pico</comment>
+ <comment xml:lang="pt">ROM Sega Pico</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Sega Pico</comment>
+ <comment xml:lang="oc">ROM Sega Pico</comment>
+ <comment xml:lang="nl">Sega Pico-ROM</comment>
+ <comment xml:lang="ko">세가 피코 롬</comment>
+ <comment xml:lang="kk">Sega Pico ROM</comment>
+ <comment xml:lang="ja">キッズコンピュータ・ピコ ROM</comment>
+ <comment xml:lang="it">ROM Sega Pico</comment>
+ <comment xml:lang="is">Sega Pico ROM</comment>
+ <comment xml:lang="id">ROM Sega Pico</comment>
+ <comment xml:lang="hu">Sega Pico ROM</comment>
+ <comment xml:lang="hr">Sega Pico ROM</comment>
+ <comment xml:lang="he">ROM של Sega Pico</comment>
+ <comment xml:lang="gl">ROM de Sega Pico</comment>
+ <comment xml:lang="ga">ROM Sega Pico</comment>
+ <comment xml:lang="fur">ROM Sega Pico</comment>
+ <comment xml:lang="fr">ROM Sega Pico</comment>
+ <comment xml:lang="fi">Sega Pico ROM</comment>
+ <comment xml:lang="eu">Sega Pico ROM</comment>
+ <comment xml:lang="es">ROM de Sega Pico</comment>
+ <comment xml:lang="en_GB">Sega Pico ROM</comment>
+ <comment xml:lang="de">Sega-Pico-ROM</comment>
+ <comment xml:lang="da">Sega Pico-ROM</comment>
+ <comment xml:lang="cs">ROM pro Sega Pico</comment>
+ <comment xml:lang="ca">ROM de Sega Pico</comment>
+ <comment xml:lang="bg">ROM — Sega Pico</comment>
+ <comment xml:lang="be">Sega Pico ROM</comment>
+ <comment xml:lang="ast">ROM de Sega Pico</comment>
+ <comment xml:lang="ar">روم سيجا بيك</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="SEGA PICO" type="string" offset="256"/>
+ <magic>
+ <match type="string" value="SEGA PICO" offset="256"/>
</magic>
+ <glob pattern="*.iso"/>
</mime-type>
<mime-type type="application/x-saturn-rom">
<comment>Sega Saturn disc image</comment>
- <comment xml:lang="ast">Imaxe de discu de Sega Saturn</comment>
- <comment xml:lang="ca">imatge de disc de Sega Saturn</comment>
- <comment xml:lang="cs">obraz disku pro Sega Saturn</comment>
- <comment xml:lang="da">Sega Saturn-diskaftryk</comment>
- <comment xml:lang="de">Sega-Saturn-Datenträgerabbild</comment>
- <comment xml:lang="el">Εικόνα δίσκου Sega Saturn</comment>
- <comment xml:lang="en_GB">Sega Saturn disc image</comment>
- <comment xml:lang="es">imagen de disco de Sega Saturn</comment>
- <comment xml:lang="eu">Sega Saturn disko irudia</comment>
- <comment xml:lang="fi">Sega Saturn -levykuva</comment>
- <comment xml:lang="fr">image disque Sega Saturn</comment>
- <comment xml:lang="ga">íomhá diosca Sega Saturn</comment>
- <comment xml:lang="he">דמות כונן Sega Saturn</comment>
- <comment xml:lang="hr">Sega Saturn slika diska</comment>
- <comment xml:lang="hu">Sega Saturn lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco Sega Saturn</comment>
- <comment xml:lang="id">Image cakram Sega Saturn</comment>
- <comment xml:lang="it">Immagine disco Sega Saturn</comment>
- <comment xml:lang="kk">Sega Saturn диск бейнесі</comment>
- <comment xml:lang="ko">세가 새턴 디스크 이미지</comment>
- <comment xml:lang="oc">imatge disc Sega Saturn</comment>
- <comment xml:lang="pl">Obraz płyty konsoli Sega Saturn</comment>
- <comment xml:lang="pt">imagem de disco Sega Saturn</comment>
- <comment xml:lang="pt_BR">Imagem de disco do Sega Saturn</comment>
- <comment xml:lang="ru">Образ диска Sega Saturn</comment>
- <comment xml:lang="sk">Obraz disku Sega Saturn</comment>
- <comment xml:lang="sr">одраз диска Сега Сатурна</comment>
- <comment xml:lang="sv">Sega Saturn-skivavbild</comment>
- <comment xml:lang="tr">Sega Saturn disk kalıbı</comment>
- <comment xml:lang="uk">образ диска Sega Saturn</comment>
- <comment xml:lang="zh_CN">Sega Saturn 光盘映像</comment>
<comment xml:lang="zh_TW">Sega Saturn 光碟映像檔</comment>
+ <comment xml:lang="zh_CN">Sega Saturn 光盘映像</comment>
+ <comment xml:lang="uk">образ диска Sega Saturn</comment>
+ <comment xml:lang="tr">Sega Saturn disk görüntüsü</comment>
+ <comment xml:lang="sv">Sega Saturn-skivavbild</comment>
+ <comment xml:lang="sr">одраз диска Сега Сатурна</comment>
+ <comment xml:lang="sq">pamje disku Sega Saturn</comment>
+ <comment xml:lang="sl">Slika diska Sega Saturn</comment>
+ <comment xml:lang="si">සේගා සෙනසුරු තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku Sega Saturn</comment>
+ <comment xml:lang="ru">Образ диска Sega Saturn</comment>
+ <comment xml:lang="pt_BR">Imagem de disco do Sega Saturn</comment>
+ <comment xml:lang="pt">imagem de disco Sega Saturn</comment>
+ <comment xml:lang="pl">Obraz płyty konsoli Sega Saturn</comment>
+ <comment xml:lang="oc">imatge disc Sega Saturn</comment>
+ <comment xml:lang="nl">Sega Saturn-schijfkopiebestand</comment>
+ <comment xml:lang="ko">세가 새턴 디스크 이미지</comment>
+ <comment xml:lang="kk">Sega Saturn диск бейнесі</comment>
+ <comment xml:lang="ja">Sega Saturn ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco Sega Saturn</comment>
+ <comment xml:lang="is">Sega Saturn diskmynd</comment>
+ <comment xml:lang="id">Image cakram Sega Saturn</comment>
+ <comment xml:lang="ia">Imagine de disco Sega Saturn</comment>
+ <comment xml:lang="hu">Sega Saturn lemezkép</comment>
+ <comment xml:lang="hr">Sega Saturn slika diska</comment>
+ <comment xml:lang="he">דמות כונן Sega Saturn</comment>
+ <comment xml:lang="gl">Imaxe de disco de Sega Saturn</comment>
+ <comment xml:lang="ga">íomhá diosca Sega Saturn</comment>
+ <comment xml:lang="fur">imagjin disc Sega Saturn</comment>
+ <comment xml:lang="fr">image disque Sega Saturn</comment>
+ <comment xml:lang="fi">Sega Saturn -levykuva</comment>
+ <comment xml:lang="eu">Sega Saturn disko irudia</comment>
+ <comment xml:lang="es">imagen de disco de Sega Saturn</comment>
+ <comment xml:lang="en_GB">Sega Saturn disc image</comment>
+ <comment xml:lang="el">Εικόνα δίσκου Sega Saturn</comment>
+ <comment xml:lang="de">Sega-Saturn-Datenträgerabbild</comment>
+ <comment xml:lang="da">Sega Saturn-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku pro Sega Saturn</comment>
+ <comment xml:lang="ca">imatge de disc de Sega Saturn</comment>
+ <comment xml:lang="bg">Диск — Sega Saturn</comment>
+ <comment xml:lang="be">вобраз дыска Sega Saturn</comment>
+ <comment xml:lang="ast">Imaxe de discu de Sega Saturn</comment>
+ <comment xml:lang="ar">صورة قرص ميجا ساتورن</comment>
+ <comment xml:lang="af">Sega Saturn-skyfbeeldlêer</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="SEGA SEGASATURN" type="string" offset="0"/>
- <match value="SEGA SEGASATURN" type="string" offset="16"/>
+ <magic>
+ <match type="string" value="SEGA SEGASATURN" offset="0"/>
+ <match type="string" value="SEGA SEGASATURN" offset="16"/>
</magic>
- <glob pattern="*.bin"/>
<glob pattern="*.iso"/>
</mime-type>
- <mime-type type="application/x-dc-rom">
- <comment>Dreamcast GD-ROM</comment>
- <comment xml:lang="ast">GD-ROM de Dreamcast</comment>
- <comment xml:lang="ca">GD-ROM de Dreamcast</comment>
- <comment xml:lang="cs">GD-ROM pro Dreamcast</comment>
- <comment xml:lang="da">Dreamcast GD-ROM</comment>
- <comment xml:lang="de">Dreamcast GD-ROM</comment>
- <comment xml:lang="el">Dreamcast GD-ROM</comment>
- <comment xml:lang="en_GB">Dreamcast GD-ROM</comment>
- <comment xml:lang="es">GD-ROM de Dreamcast</comment>
- <comment xml:lang="eu">Dreamcast GD-ROM</comment>
- <comment xml:lang="fr">GD-ROM Dreamcast</comment>
- <comment xml:lang="ga">GD-ROM Dreamcast</comment>
- <comment xml:lang="he">Dreamcast GD-ROM</comment>
- <comment xml:lang="hr">Dreamcast GD-ROM</comment>
- <comment xml:lang="hu">Dreamcast GD-ROM</comment>
- <comment xml:lang="ia">GD-ROM Dreamcast</comment>
- <comment xml:lang="id">GD-ROM Dreamcast</comment>
- <comment xml:lang="it">GD-ROM Dreamcast</comment>
- <comment xml:lang="kk">Dreamcast GD-ROM</comment>
- <comment xml:lang="ko">드림캐스트 GD-ROM</comment>
- <comment xml:lang="oc">GD-ROM Dreamcast</comment>
- <comment xml:lang="pl">Plik GD-ROM konsoli Dreamcast</comment>
- <comment xml:lang="pt">GD-ROM Dreamcast</comment>
- <comment xml:lang="pt_BR">GD-ROM de Dreamcast</comment>
- <comment xml:lang="ru">Dreamcast GD-ROM</comment>
- <comment xml:lang="sk">Dreamcast GD-ROM</comment>
- <comment xml:lang="sr">Дримкаст ГД-РОМ</comment>
- <comment xml:lang="sv">Dreamcast-gd-rom</comment>
- <comment xml:lang="tr">Dreamcast GD-ROM</comment>
- <comment xml:lang="uk">GD-ROM Dreamcast</comment>
- <comment xml:lang="zh_CN">Dreamcast CD-ROM</comment>
- <comment xml:lang="zh_TW">Dreamcast GD-ROM</comment>
+ <mime-type type="application/x-dreamcast-rom">
+ <comment>Dreamcast disc image</comment>
+ <comment xml:lang="zh_TW">Dreamcast 光碟映像檔</comment>
+ <comment xml:lang="zh_CN">Dreamcast 光盘映像</comment>
+ <comment xml:lang="uk">образ диска Dreamcast</comment>
+ <comment xml:lang="tr">Dreamcast disk görüntüsü</comment>
+ <comment xml:lang="sv">Dreamcast-skivavbild</comment>
+ <comment xml:lang="sq">pamje disku Dreamcast</comment>
+ <comment xml:lang="sl">Slika diska Dreamcast</comment>
+ <comment xml:lang="si">Dreamcast තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku Dreamcast</comment>
+ <comment xml:lang="ru">Образ диска Dreamcast</comment>
+ <comment xml:lang="pt_BR">Imagem de disco do Dreamcast</comment>
+ <comment xml:lang="pt">imagem de disco Dreamcast</comment>
+ <comment xml:lang="pl">Obraz płyty konsoli Dreamcast</comment>
+ <comment xml:lang="oc">imatge disc Dreamcast</comment>
+ <comment xml:lang="nl">Dreamcast-schijfkopiebestand</comment>
+ <comment xml:lang="ko">드림캐스트 디스크 이미지</comment>
+ <comment xml:lang="kk">Dreamcast диск бейнесі</comment>
+ <comment xml:lang="ja">Dreamcast ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco Dreamcast</comment>
+ <comment xml:lang="is">Dreamcast diskmynd</comment>
+ <comment xml:lang="id">Image cakram Dreamcast</comment>
+ <comment xml:lang="hu">Dreamcast lemezkép</comment>
+ <comment xml:lang="hr">Dreamcast slika disa</comment>
+ <comment xml:lang="he">דמות כונן Dreamcast</comment>
+ <comment xml:lang="gl">Imaxe de disco de Dreamcast</comment>
+ <comment xml:lang="fr">image disque Dreamcast</comment>
+ <comment xml:lang="fi">Dreamcast-levykuva</comment>
+ <comment xml:lang="eu">Dreamcast disko irudia</comment>
+ <comment xml:lang="es">imagen de disco de Dreamcast</comment>
+ <comment xml:lang="en_GB">Dreamcast disc image</comment>
+ <comment xml:lang="de">Dreamcast-Datenträgerabbild</comment>
+ <comment xml:lang="da">Dreamcast-diskaftryk</comment>
+ <comment xml:lang="ca">imatge de disc de Dreamcast</comment>
+ <comment xml:lang="bg">Диск — Dreamcast</comment>
+ <comment xml:lang="be">вобраз дыска Dreamcast</comment>
+ <comment xml:lang="ar">صورة قرص Dreamcast</comment>
<generic-icon name="application-x-executable"/>
- <glob pattern="*.dc"/>
+ <magic>
+ <match type="string" value="SEGA SEGAKATANA" offset="16"/>
+ </magic>
+ <glob pattern="*.iso"/>
</mime-type>
<mime-type type="application/x-nintendo-ds-rom">
<comment>Nintendo DS ROM</comment>
- <comment xml:lang="ar">Nintendo DS ROM</comment>
- <comment xml:lang="ast">ROM de Nintendo DS</comment>
- <comment xml:lang="be@latin">Nintendo DS ROM</comment>
- <comment xml:lang="bg">ROM — Nintendo DS</comment>
- <comment xml:lang="ca">ROM de Nintendo DS</comment>
- <comment xml:lang="cs">ROM pro Nintendo DS</comment>
- <comment xml:lang="da">Nintendo DS-rom</comment>
- <comment xml:lang="de">Nintendo DS ROM</comment>
- <comment xml:lang="el">Nintendo DS ROM</comment>
- <comment xml:lang="en_GB">Nintendo DS ROM</comment>
- <comment xml:lang="es">ROM de Nintendo DS</comment>
- <comment xml:lang="eu">Nintendo DS-ko ROMa</comment>
- <comment xml:lang="fi">Nintendo DS-ROM</comment>
- <comment xml:lang="fo">Nintendo DS ROM</comment>
- <comment xml:lang="fr">ROM Nintendo DS</comment>
- <comment xml:lang="ga">ROM Nintendo DS</comment>
- <comment xml:lang="gl">ROM de Nintendo DS</comment>
- <comment xml:lang="he">ROM של Nintendo</comment>
- <comment xml:lang="hr">Nintendo DS ROM</comment>
- <comment xml:lang="hu">Nintendo DS ROM</comment>
- <comment xml:lang="ia">ROM pro Nintendo DS</comment>
- <comment xml:lang="id">Memori baca-saja Nintendo DS</comment>
- <comment xml:lang="it">ROM Nintendo DS</comment>
- <comment xml:lang="ja">Nintendo DS ROM</comment>
- <comment xml:lang="kk">Nintendo DS ROM</comment>
- <comment xml:lang="ko">닌텐도 DS 롬</comment>
- <comment xml:lang="lt">Nintendo DS ROM</comment>
- <comment xml:lang="lv">Nintendo DS ROM</comment>
- <comment xml:lang="nb">Nintendo DS-ROM</comment>
- <comment xml:lang="nl">Nintendo-DS-ROM</comment>
- <comment xml:lang="nn">Nintendo DS-ROM</comment>
- <comment xml:lang="oc">ROM Nintendo DS</comment>
- <comment xml:lang="pl">Plik ROM konsoli Nintendo DS</comment>
- <comment xml:lang="pt">ROM Nintendo DS</comment>
- <comment xml:lang="pt_BR">ROM de Nintendo DS</comment>
- <comment xml:lang="ro">ROM Nintendo DS</comment>
- <comment xml:lang="ru">Nintendo DS ROM</comment>
- <comment xml:lang="sk">ROM pre Nintendo DS</comment>
- <comment xml:lang="sl">Bralni pomnilnik Nintendo DS</comment>
- <comment xml:lang="sq">ROM Nintendo DS</comment>
- <comment xml:lang="sr">Нинтендо ДС РОМ</comment>
- <comment xml:lang="sv">Nintendo DS-rom</comment>
- <comment xml:lang="tr">Nintendo DS ROM</comment>
- <comment xml:lang="uk">ППП Nintendo</comment>
- <comment xml:lang="vi">ROM DS Nintendo</comment>
- <comment xml:lang="zh_CN">任天堂 DS ROM</comment>
<comment xml:lang="zh_TW">任天堂 DS ROM</comment>
+ <comment xml:lang="zh_CN">任天堂 DS ROM</comment>
+ <comment xml:lang="vi">ROM DS Nintendo</comment>
+ <comment xml:lang="uk">ППП Nintendo</comment>
+ <comment xml:lang="tr">Nintendo DS ROM</comment>
+ <comment xml:lang="sv">Nintendo DS-rom</comment>
+ <comment xml:lang="sr">Нинтендо ДС РОМ</comment>
+ <comment xml:lang="sq">ROM Nintendo DS</comment>
+ <comment xml:lang="sl">Bralni pomnilnik Nintendo DS</comment>
+ <comment xml:lang="si">Nintendo DS ROM</comment>
+ <comment xml:lang="sk">ROM pre Nintendo DS</comment>
+ <comment xml:lang="ru">Nintendo DS ROM</comment>
+ <comment xml:lang="ro">ROM Nintendo DS</comment>
+ <comment xml:lang="pt_BR">ROM de Nintendo DS</comment>
+ <comment xml:lang="pt">ROM Nintendo DS</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Nintendo DS</comment>
+ <comment xml:lang="oc">ROM Nintendo DS</comment>
+ <comment xml:lang="nn">Nintendo DS-ROM</comment>
+ <comment xml:lang="nl">Nintendo DS-ROM</comment>
+ <comment xml:lang="nb">Nintendo DS-ROM</comment>
+ <comment xml:lang="lv">Nintendo DS ROM</comment>
+ <comment xml:lang="lt">Nintendo DS ROM</comment>
+ <comment xml:lang="ko">닌텐도 DS 롬</comment>
+ <comment xml:lang="kk">Nintendo DS ROM</comment>
+ <comment xml:lang="ja">ニンテンドーDS ROM</comment>
+ <comment xml:lang="it">ROM Nintendo DS</comment>
+ <comment xml:lang="is">Nintendo DS ROM</comment>
+ <comment xml:lang="id">Memori baca-saja Nintendo DS</comment>
+ <comment xml:lang="ia">ROM pro Nintendo DS</comment>
+ <comment xml:lang="hu">Nintendo DS ROM</comment>
+ <comment xml:lang="hr">Nintendo DS ROM</comment>
+ <comment xml:lang="he">ROM של Nintendo</comment>
+ <comment xml:lang="gl">ROM de Nintendo DS</comment>
+ <comment xml:lang="ga">ROM Nintendo DS</comment>
+ <comment xml:lang="fur">ROM Nintendo DS</comment>
+ <comment xml:lang="fr">ROM Nintendo DS</comment>
+ <comment xml:lang="fo">Nintendo DS ROM</comment>
+ <comment xml:lang="fi">Nintendo DS-ROM</comment>
+ <comment xml:lang="eu">Nintendo DS-ko ROMa</comment>
+ <comment xml:lang="es">ROM de Nintendo DS</comment>
+ <comment xml:lang="en_GB">Nintendo DS ROM</comment>
+ <comment xml:lang="el">Nintendo DS ROM</comment>
+ <comment xml:lang="de">Nintendo-DS-ROM</comment>
+ <comment xml:lang="da">Nintendo DS-ROM</comment>
+ <comment xml:lang="cs">ROM pro Nintendo DS</comment>
+ <comment xml:lang="ca">ROM de Nintendo DS</comment>
+ <comment xml:lang="bg">ROM — Nintendo DS</comment>
+ <comment xml:lang="be@latin">Nintendo DS ROM</comment>
+ <comment xml:lang="be">Nintendo DS ROM</comment>
+ <comment xml:lang="ast">ROM de Nintendo DS</comment>
+ <comment xml:lang="ar">روم نينتندو دي</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.nds"/>
</mime-type>
+ <mime-type type="application/x-nintendo-3ds-rom">
+ <comment>Nintendo 3DS ROM</comment>
+ <comment xml:lang="uk">ППП Nintendo 3DS</comment>
+ <comment xml:lang="tr">Nintendo 3DS ROM</comment>
+ <comment xml:lang="sv">Nintendo 3DS-rom</comment>
+ <comment xml:lang="sl">Nintendo 3DS ROM</comment>
+ <comment xml:lang="si">Nintendo 3DS ROM</comment>
+ <comment xml:lang="ru">Nintendo 3DS ROM</comment>
+ <comment xml:lang="pt_BR">ROM do Nintendo 3DS</comment>
+ <comment xml:lang="pt">ROM Nintendo 3DS</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Nintendo 3DS</comment>
+ <comment xml:lang="oc">ROM Nintendo 3DS</comment>
+ <comment xml:lang="nl">Nintendo 3DS-ROM</comment>
+ <comment xml:lang="ko">닌텐도 3DS 롬</comment>
+ <comment xml:lang="kk">Nintendo 3DS ROM</comment>
+ <comment xml:lang="ja">ニンテンドー3DS ROM</comment>
+ <comment xml:lang="it">ROM Nintendo 3DS</comment>
+ <comment xml:lang="is">Nintendo 3DS ROM</comment>
+ <comment xml:lang="id">ROM Nintendo 3DS</comment>
+ <comment xml:lang="hu">Nintendo 3DS ROM</comment>
+ <comment xml:lang="hr">Nintendo 3DS ROM</comment>
+ <comment xml:lang="he">ROM של Nintendo 3DS</comment>
+ <comment xml:lang="gl">ROM de Nintendo 3DS</comment>
+ <comment xml:lang="fr">ROM Nintendo 3DS</comment>
+ <comment xml:lang="fi">Nintendo 3DS ROM</comment>
+ <comment xml:lang="eu">Nintendo 3DS ROMa</comment>
+ <comment xml:lang="es">ROM de Nintendo 3DS</comment>
+ <comment xml:lang="en_GB">Nintendo 3DS ROM</comment>
+ <comment xml:lang="de">Nintendo-3DS-ROM</comment>
+ <comment xml:lang="da">Nintendo 3DS-ROM</comment>
+ <comment xml:lang="ca">ROM de Nintendo 3DS</comment>
+ <comment xml:lang="be">Nintendo 3DS ROM</comment>
+ <comment xml:lang="ar">روم نينتندو 3دي</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.3ds"/>
+ <glob pattern="*.cci"/>
+ <magic>
+ <match offset="256" type="string" value="NCSD"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-nintendo-3ds-executable">
+ <comment>Nintendo 3DS Executable</comment>
+ <comment xml:lang="uk">виконуваний файл Nintendo 3DS</comment>
+ <comment xml:lang="tr">Nintendo 3DS Executable</comment>
+ <comment xml:lang="sv">Körbar Nintendo 3DS-fil</comment>
+ <comment xml:lang="si">Nintendo 3DS Executable</comment>
+ <comment xml:lang="ru">Nintendo 3DS Executable</comment>
+ <comment xml:lang="pt_BR">Executável do Nintendo 3DS</comment>
+ <comment xml:lang="pt">Executável da Nintendo 3DS</comment>
+ <comment xml:lang="pl">Plik wykonywalny konsoli Nintendo 3DS</comment>
+ <comment xml:lang="oc">Executable Nintendo 3DS</comment>
+ <comment xml:lang="nl">Nintendo 3DS-programmabestand</comment>
+ <comment xml:lang="ko">닌텐도 3DS 실행 파일</comment>
+ <comment xml:lang="kk">Nintendo 3DS орындалатын файлы</comment>
+ <comment xml:lang="ja">Nintendo 3DS 実行ファイル</comment>
+ <comment xml:lang="it">Eseguibile Nintendo 3DS</comment>
+ <comment xml:lang="is">Nintendo 3DS keyrsluskrá</comment>
+ <comment xml:lang="id">Executable Nintendo 3DS</comment>
+ <comment xml:lang="hu">Nintendo 3DS végrehajtható fájl</comment>
+ <comment xml:lang="hr">Nintendo 3DS izvršna datoteka</comment>
+ <comment xml:lang="he">קובץ הפעלה של Nintendo 3DS</comment>
+ <comment xml:lang="gl">Executábel de Nintendo 3DS</comment>
+ <comment xml:lang="fr">Exécutable Nintendo 3DS</comment>
+ <comment xml:lang="fi">Nintendo 3DS -ohjelma</comment>
+ <comment xml:lang="eu">Nintendo 3DS exekutagarria</comment>
+ <comment xml:lang="es">ejecutable de Nintendo 3DS</comment>
+ <comment xml:lang="en_GB">Nintendo 3DS Executable</comment>
+ <comment xml:lang="de">Nintendo-3DS-Programmdatei</comment>
+ <comment xml:lang="da">Nintendo 3DS-kørbar</comment>
+ <comment xml:lang="ca">executable de Nintendo 3DS</comment>
+ <comment xml:lang="be">выконвальны файл Nintendo 3DS</comment>
+ <comment xml:lang="ar">تنفيذي نينتندو 3دي إس</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.3dsx"/>
+ <magic priority="40">
+ <match offset="0" type="string" value="3DSX"/>
+ </magic>
+ </mime-type>
<mime-type type="application/x-pc-engine-rom">
<comment>PC Engine ROM</comment>
- <comment xml:lang="ast">ROM de PC Engine</comment>
- <comment xml:lang="ca">ROM de PC Engine</comment>
- <comment xml:lang="cs">ROM pro PC Engine</comment>
- <comment xml:lang="da">PC Engine ROM</comment>
- <comment xml:lang="de">PC Engine ROM</comment>
- <comment xml:lang="el">PC Engine ROM</comment>
- <comment xml:lang="en_GB">PC Engine ROM</comment>
- <comment xml:lang="es">ROM de PC Engine</comment>
- <comment xml:lang="eu">PC Engine ROM</comment>
- <comment xml:lang="fi">PC Engine ROM</comment>
- <comment xml:lang="fr">ROM PC Engine</comment>
- <comment xml:lang="ga">ROM PC Engine</comment>
- <comment xml:lang="gl">ROM de máquina de PC</comment>
- <comment xml:lang="he">ROM של PC Engine</comment>
- <comment xml:lang="hr">PC Engine ROM</comment>
- <comment xml:lang="hu">PC Engine ROM</comment>
- <comment xml:lang="ia">ROM PC Engine</comment>
- <comment xml:lang="id">ROM PC Engine</comment>
- <comment xml:lang="it">ROM PC Engine</comment>
- <comment xml:lang="kk">PC Engine ROM</comment>
- <comment xml:lang="ko">PC 엔진 롬</comment>
- <comment xml:lang="oc">ROM PC Engine</comment>
- <comment xml:lang="pl">Plik ROM konsoli PC Engine</comment>
- <comment xml:lang="pt">ROM PC Engine</comment>
- <comment xml:lang="pt_BR">ROM de PC Engine</comment>
- <comment xml:lang="ru">PC Engine ROM</comment>
- <comment xml:lang="sk">PC Engine ROM</comment>
- <comment xml:lang="sl">Pomnilnik PC Engine ROM</comment>
- <comment xml:lang="sr">ПЦ Енџин РОМ</comment>
- <comment xml:lang="sv">PC Engine-rom</comment>
- <comment xml:lang="tr">PC Engine ROM</comment>
- <comment xml:lang="uk">ROM для рушія на ПК</comment>
- <comment xml:lang="zh_CN">PC Engine ROM</comment>
<comment xml:lang="zh_TW">PC Engine ROM</comment>
+ <comment xml:lang="zh_CN">PC Engine ROM</comment>
+ <comment xml:lang="uk">ROM для рушія на ПК</comment>
+ <comment xml:lang="tr">PC Engine ROM</comment>
+ <comment xml:lang="sv">PC Engine-rom</comment>
+ <comment xml:lang="sr">ПЦ Енџин РОМ</comment>
+ <comment xml:lang="sl">Pomnilnik PC Engine ROM</comment>
+ <comment xml:lang="si">PC Engine ROM</comment>
+ <comment xml:lang="sk">PC Engine ROM</comment>
+ <comment xml:lang="ru">PC Engine ROM</comment>
+ <comment xml:lang="pt_BR">ROM de PC Engine</comment>
+ <comment xml:lang="pt">ROM PC Engine</comment>
+ <comment xml:lang="pl">Plik ROM konsoli PC Engine</comment>
+ <comment xml:lang="oc">ROM PC Engine</comment>
+ <comment xml:lang="nl">PC Engine-ROM</comment>
+ <comment xml:lang="ko">PC 엔진 롬</comment>
+ <comment xml:lang="kk">PC Engine ROM</comment>
+ <comment xml:lang="ja">PCエンジン ROM</comment>
+ <comment xml:lang="it">ROM PC Engine</comment>
+ <comment xml:lang="is">PC Engine ROM</comment>
+ <comment xml:lang="id">ROM PC Engine</comment>
+ <comment xml:lang="ia">ROM PC Engine</comment>
+ <comment xml:lang="hu">PC Engine ROM</comment>
+ <comment xml:lang="hr">PC Engine ROM</comment>
+ <comment xml:lang="he">ROM של PC Engine</comment>
+ <comment xml:lang="gl">ROM de máquina de PC</comment>
+ <comment xml:lang="ga">ROM PC Engine</comment>
+ <comment xml:lang="fur">ROM PC Engine</comment>
+ <comment xml:lang="fr">ROM PC Engine</comment>
+ <comment xml:lang="fi">PC Engine -ROM</comment>
+ <comment xml:lang="eu">PC Engine ROM</comment>
+ <comment xml:lang="es">ROM de PC Engine</comment>
+ <comment xml:lang="en_GB">PC Engine ROM</comment>
+ <comment xml:lang="el">PC Engine ROM</comment>
+ <comment xml:lang="de">PC-Engine ROM</comment>
+ <comment xml:lang="da">PC Engine-ROM</comment>
+ <comment xml:lang="cs">ROM pro PC Engine</comment>
+ <comment xml:lang="ca">ROM de PC Engine</comment>
+ <comment xml:lang="bg">ROM — PC Engine</comment>
+ <comment xml:lang="be">PC Engine ROM</comment>
+ <comment xml:lang="ast">ROM de PC Engine</comment>
+ <comment xml:lang="ar">روم محرك PC</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.pce"/>
</mime-type>
<mime-type type="application/x-wii-rom">
<comment>Wii disc image</comment>
- <comment xml:lang="ast">Imaxe de discu de Wii</comment>
- <comment xml:lang="ca">imatge de disc de Wii</comment>
- <comment xml:lang="cs">obraz disku pro Wii</comment>
- <comment xml:lang="da">Wii-diskaftryk</comment>
- <comment xml:lang="de">Wii-Datenträgerabbild</comment>
- <comment xml:lang="el">Εικόνα δίσκου Wii</comment>
- <comment xml:lang="en_GB">Wii disc image</comment>
- <comment xml:lang="es">imagen de disco de Wii</comment>
- <comment xml:lang="eu">Wii disko irudia</comment>
- <comment xml:lang="fi">Wii-levykuva</comment>
- <comment xml:lang="fr">image disque Wii</comment>
- <comment xml:lang="ga">íomhá diosca Wii</comment>
- <comment xml:lang="gl">Imaxe de disco de Wii</comment>
- <comment xml:lang="he">דמות כונן Wii</comment>
- <comment xml:lang="hr">Wii slika diska</comment>
- <comment xml:lang="hu">Wii lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco Wii</comment>
- <comment xml:lang="id">Image disk Wii</comment>
- <comment xml:lang="it">Immagine disco Wii</comment>
- <comment xml:lang="kk">Wii диск бейнесі</comment>
- <comment xml:lang="ko">Wii 디스크 이미지</comment>
- <comment xml:lang="oc">imatge disc Wii</comment>
- <comment xml:lang="pl">Obraz płyty konsoli Wii</comment>
- <comment xml:lang="pt">imagem de disco Wii</comment>
- <comment xml:lang="pt_BR">Imagem de disco Wii</comment>
- <comment xml:lang="ru">Образ диска Wii</comment>
- <comment xml:lang="sk">Obraz disku Wii</comment>
- <comment xml:lang="sl">Odtis diska Wii</comment>
- <comment xml:lang="sr">одраз диска Вии-ја</comment>
- <comment xml:lang="sv">Wii-skivavbild</comment>
- <comment xml:lang="tr">Wii disk görüntüsü</comment>
- <comment xml:lang="uk">образ диска Wii</comment>
- <comment xml:lang="zh_CN">Wii 光盘映像</comment>
<comment xml:lang="zh_TW">Wii 光碟映像檔</comment>
+ <comment xml:lang="zh_CN">Wii 光盘映像</comment>
+ <comment xml:lang="uk">образ диска Wii</comment>
+ <comment xml:lang="tr">Wii disk görüntüsü</comment>
+ <comment xml:lang="sv">Wii-skivavbild</comment>
+ <comment xml:lang="sr">одраз диска Вии-ја</comment>
+ <comment xml:lang="sq">pamje disku Wii</comment>
+ <comment xml:lang="sl">Odtis diska Wii</comment>
+ <comment xml:lang="si">Wii තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku Wii</comment>
+ <comment xml:lang="ru">Образ диска Wii</comment>
+ <comment xml:lang="pt_BR">Imagem de disco Wii</comment>
+ <comment xml:lang="pt">imagem de disco Wii</comment>
+ <comment xml:lang="pl">Obraz płyty konsoli Wii</comment>
+ <comment xml:lang="oc">imatge disc Wii</comment>
+ <comment xml:lang="nl">Wii-schijfkopiebestand</comment>
+ <comment xml:lang="ko">Wii 디스크 이미지</comment>
+ <comment xml:lang="kk">Wii диск бейнесі</comment>
+ <comment xml:lang="ja">Wii ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco Wii</comment>
+ <comment xml:lang="is">Wii diskmynd</comment>
+ <comment xml:lang="id">Image disk Wii</comment>
+ <comment xml:lang="ia">Imagine de disco Wii</comment>
+ <comment xml:lang="hu">Wii lemezkép</comment>
+ <comment xml:lang="hr">Wii slika diska</comment>
+ <comment xml:lang="he">דמות כונן Wii</comment>
+ <comment xml:lang="gl">Imaxe de disco de Wii</comment>
+ <comment xml:lang="ga">íomhá diosca Wii</comment>
+ <comment xml:lang="fur">imagjin disc Wii</comment>
+ <comment xml:lang="fr">image disque Wii</comment>
+ <comment xml:lang="fi">Wii-levykuva</comment>
+ <comment xml:lang="eu">Wii disko irudia</comment>
+ <comment xml:lang="es">imagen de disco de Wii</comment>
+ <comment xml:lang="en_GB">Wii disc image</comment>
+ <comment xml:lang="el">Εικόνα δίσκου Wii</comment>
+ <comment xml:lang="de">Wii-Datenträgerabbild</comment>
+ <comment xml:lang="da">Wii-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku pro Wii</comment>
+ <comment xml:lang="ca">imatge de disc de Wii</comment>
+ <comment xml:lang="bg">Диск — Wii</comment>
+ <comment xml:lang="be">вобраз дыска Wii</comment>
+ <comment xml:lang="ast">Imaxe de discu de Wii</comment>
+ <comment xml:lang="ar">صورة قرص وي</comment>
+ <comment xml:lang="af">Wii-skyfbeeldlêer</comment>
<alias type="application/x-wii-iso-image"/>
<alias type="application/x-wbfs"/>
<alias type="application/x-wia"/>
<generic-icon name="application-x-executable"/>
<glob pattern="*.iso"/>
- <magic priority="50">
- <match value="0x5d1c9ea3" type="big32" offset="24"/>
- <match value="WBFS" type="string" offset="0"/>
- <match value="WII\001DISC" type="string" offset="0"/>
+ <magic>
+ <match offset="24" type="big32" value="0x5d1c9ea3"/>
+ <match offset="0" type="string" value="WBFS"/>
+ <match offset="0" type="string" value="WII\001DISC"/>
</magic>
</mime-type>
<mime-type type="application/x-wii-wad">
<comment>WiiWare bundle</comment>
- <comment xml:lang="ca">paquet de WiiWare</comment>
- <comment xml:lang="cs">balíček pro WiiWare</comment>
- <comment xml:lang="da">WiiWare-samling</comment>
- <comment xml:lang="de">WiiWare-Paket</comment>
- <comment xml:lang="en_GB">WiiWare bundle</comment>
- <comment xml:lang="es">conjunto de WiiWare</comment>
- <comment xml:lang="eu">WiiWare bilduma</comment>
- <comment xml:lang="fr">lot WiiWare</comment>
- <comment xml:lang="ga">burla WiiWare</comment>
- <comment xml:lang="he">מאגד WiiWare</comment>
- <comment xml:lang="hr">WiiWare paket</comment>
- <comment xml:lang="hu">WiiWare csomag</comment>
- <comment xml:lang="ia">Pacchetto WiiWare</comment>
- <comment xml:lang="id">Bundel WiiWare</comment>
- <comment xml:lang="it">Bundle WiiWare</comment>
- <comment xml:lang="kk">WiiWare дестесі</comment>
- <comment xml:lang="ko">위-웨어 번들</comment>
- <comment xml:lang="oc">lòt WiiWare</comment>
- <comment xml:lang="pl">Pakiet WiiWare</comment>
- <comment xml:lang="pt">pacote WiiWare</comment>
- <comment xml:lang="pt_BR">Pacote WiiWare</comment>
- <comment xml:lang="ru">Пакет WiiWare</comment>
- <comment xml:lang="sk">Balík WiiWare</comment>
- <comment xml:lang="sr">ВииВер комплет</comment>
- <comment xml:lang="sv">WiiWare-paket</comment>
- <comment xml:lang="tr">WiiWare paketi</comment>
- <comment xml:lang="uk">пакет WiiWare</comment>
- <comment xml:lang="zh_CN">WiiWare 捆绑包</comment>
<comment xml:lang="zh_TW">WiiWare 綁包</comment>
+ <comment xml:lang="zh_CN">WiiWare 捆绑包</comment>
+ <comment xml:lang="uk">пакет WiiWare</comment>
+ <comment xml:lang="tr">WiiWare paketi</comment>
+ <comment xml:lang="sv">WiiWare-paket</comment>
+ <comment xml:lang="sr">ВииВер комплет</comment>
+ <comment xml:lang="sq">paketë WiiWare</comment>
+ <comment xml:lang="si">WiiWare බණ්ඩලය</comment>
+ <comment xml:lang="sk">Balík WiiWare</comment>
+ <comment xml:lang="ru">Пакет WiiWare</comment>
+ <comment xml:lang="pt_BR">Pacote WiiWare</comment>
+ <comment xml:lang="pt">pacote WiiWare</comment>
+ <comment xml:lang="pl">Pakiet WiiWare</comment>
+ <comment xml:lang="oc">lòt WiiWare</comment>
+ <comment xml:lang="nl">WiiWare-bundel</comment>
+ <comment xml:lang="ko">WiiWare 번들</comment>
+ <comment xml:lang="kk">WiiWare дестесі</comment>
+ <comment xml:lang="ja">WiiWare バンドル</comment>
+ <comment xml:lang="it">Bundle WiiWare</comment>
+ <comment xml:lang="is">WiiWare vöndull</comment>
+ <comment xml:lang="id">Bundel WiiWare</comment>
+ <comment xml:lang="ia">Pacchetto WiiWare</comment>
+ <comment xml:lang="hu">WiiWare csomag</comment>
+ <comment xml:lang="hr">WiiWare paket</comment>
+ <comment xml:lang="he">מאגד WiiWare</comment>
+ <comment xml:lang="gl">Empaquetado WiiWare</comment>
+ <comment xml:lang="ga">burla WiiWare</comment>
+ <comment xml:lang="fur">côl WiiWare</comment>
+ <comment xml:lang="fr">lot WiiWare</comment>
+ <comment xml:lang="fi">WiiWare-lisäpaketti</comment>
+ <comment xml:lang="eu">WiiWare bilduma</comment>
+ <comment xml:lang="es">conjunto de WiiWare</comment>
+ <comment xml:lang="en_GB">WiiWare bundle</comment>
+ <comment xml:lang="de">WiiWare-Paket</comment>
+ <comment xml:lang="da">WiiWare-samling</comment>
+ <comment xml:lang="cs">balíček pro WiiWare</comment>
+ <comment xml:lang="ca">paquet de WiiWare</comment>
+ <comment xml:lang="bg">Програмен пакет — WiiWare</comment>
+ <comment xml:lang="be">пакет WiiWare</comment>
+ <comment xml:lang="ar">حزمة وي واير</comment>
+ <comment xml:lang="af">WiiWare-bundel</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="Is\0\0" type="string" offset="4"/>
- <match value="ib\0\0" type="string" offset="4"/>
- <match value="Bk\0\0" type="string" offset="4"/>
+ <magic>
+ <match type="string" value="Is\0\0" offset="4"/>
+ <match type="string" value="ib\0\0" offset="4"/>
+ <match type="string" value="Bk\0\0" offset="4"/>
</magic>
<glob pattern="*.wad"/>
</mime-type>
<mime-type type="application/x-gamecube-rom">
<comment>GameCube disc image</comment>
- <comment xml:lang="ca">imatge de disc de GameCube</comment>
- <comment xml:lang="cs">obraz disku pro GameCube</comment>
- <comment xml:lang="da">GameCube-diskaftryk</comment>
- <comment xml:lang="de">GameCube-Datenträgerabbild</comment>
- <comment xml:lang="el">Εικόνα δίσκου GameCube</comment>
- <comment xml:lang="en_GB">GameCube disc image</comment>
- <comment xml:lang="es">imagen de disco de GameCube</comment>
- <comment xml:lang="eu">GameCube disko irudia</comment>
- <comment xml:lang="fi">GameCube-levykuva</comment>
- <comment xml:lang="fr">image disque GameCube</comment>
- <comment xml:lang="ga">íomhá diosca GameCube</comment>
- <comment xml:lang="gl">Imae de disco de GameCube</comment>
- <comment xml:lang="he">דמות כונן GameCube</comment>
- <comment xml:lang="hr">GameCube slika diska</comment>
- <comment xml:lang="hu">GameCube lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco GameCube</comment>
- <comment xml:lang="id">Image disk GameCube</comment>
- <comment xml:lang="it">Immagine disco GameCube</comment>
- <comment xml:lang="kk">GameCube диск бейнесі</comment>
- <comment xml:lang="ko">게임큐브 디스크 이미지</comment>
- <comment xml:lang="oc">imatge disc GameCube</comment>
- <comment xml:lang="pl">Obraz płyty konsoli GameCube</comment>
- <comment xml:lang="pt">imagem de disco GameCube</comment>
- <comment xml:lang="pt_BR">Imagem de disco GameCube</comment>
- <comment xml:lang="ru">Образ диска GameCube</comment>
- <comment xml:lang="sk">Obraz disku GameCube</comment>
- <comment xml:lang="sl">Odtis diska GameCube</comment>
- <comment xml:lang="sr">одраз диска Гејм Коцке</comment>
- <comment xml:lang="sv">GameCube-skivavbild</comment>
- <comment xml:lang="tr">GameCube disk görüntüsü</comment>
- <comment xml:lang="uk">образ диска GameCube</comment>
- <comment xml:lang="zh_CN">GameCube 光盘映像</comment>
<comment xml:lang="zh_TW">GameCube 光碟映像檔</comment>
+ <comment xml:lang="zh_CN">GameCube 光盘映像</comment>
+ <comment xml:lang="uk">образ диска GameCube</comment>
+ <comment xml:lang="tr">GameCube disk görüntüsü</comment>
+ <comment xml:lang="sv">GameCube-skivavbild</comment>
+ <comment xml:lang="sr">одраз диска Гејм Коцке</comment>
+ <comment xml:lang="sq">pamje disku GameCube</comment>
+ <comment xml:lang="sl">Odtis diska GameCube</comment>
+ <comment xml:lang="si">GameCube තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku GameCube</comment>
+ <comment xml:lang="ru">Образ диска GameCube</comment>
+ <comment xml:lang="pt_BR">Imagem de disco GameCube</comment>
+ <comment xml:lang="pt">imagem de disco GameCube</comment>
+ <comment xml:lang="pl">Obraz płyty konsoli GameCube</comment>
+ <comment xml:lang="oc">imatge disc GameCube</comment>
+ <comment xml:lang="nl">GameCube-schijfkopiebestand</comment>
+ <comment xml:lang="ko">게임큐브 디스크 이미지</comment>
+ <comment xml:lang="kk">GameCube диск бейнесі</comment>
+ <comment xml:lang="ja">GameCube ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco GameCube</comment>
+ <comment xml:lang="is">GameCube diskmynd</comment>
+ <comment xml:lang="id">Image disk GameCube</comment>
+ <comment xml:lang="ia">Imagine de disco GameCube</comment>
+ <comment xml:lang="hu">GameCube lemezkép</comment>
+ <comment xml:lang="hr">GameCube slika diska</comment>
+ <comment xml:lang="he">דמות כונן GameCube</comment>
+ <comment xml:lang="gl">Imae de disco de GameCube</comment>
+ <comment xml:lang="ga">íomhá diosca GameCube</comment>
+ <comment xml:lang="fur">imagjin disc GameCube</comment>
+ <comment xml:lang="fr">image disque GameCube</comment>
+ <comment xml:lang="fi">GameCube-levykuva</comment>
+ <comment xml:lang="eu">GameCube disko irudia</comment>
+ <comment xml:lang="es">imagen de disco de GameCube</comment>
+ <comment xml:lang="en_GB">GameCube disc image</comment>
+ <comment xml:lang="el">Εικόνα δίσκου GameCube</comment>
+ <comment xml:lang="de">GameCube-Datenträgerabbild</comment>
+ <comment xml:lang="da">GameCube-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku pro GameCube</comment>
+ <comment xml:lang="ca">imatge de disc de GameCube</comment>
+ <comment xml:lang="bg">Диск — GameCube</comment>
+ <comment xml:lang="be">вобраз дыска GameCube</comment>
+ <comment xml:lang="ar">صورة قرص GameCube</comment>
+ <comment xml:lang="af">GameCube-skyfbeeldlêer</comment>
<generic-icon name="application-x-executable"/>
<alias type="application/x-gamecube-iso-image"/>
<glob pattern="*.iso"/>
- <magic priority="50">
- <match value="0xc2339f3d" type="big32" offset="28"/>
+ <magic>
+ <match offset="28" type="big32" value="0xc2339f3d"/>
</magic>
</mime-type>
<mime-type type="application/x-thomson-cartridge-memo7">
<comment>Thomson Mémo7 cartridge</comment>
- <comment xml:lang="ca">cartutx Thomson Mémo7</comment>
- <comment xml:lang="cs">Kazeta Thomson Mémo7</comment>
- <comment xml:lang="de">Thomson-Mémo7-Steckmodul</comment>
- <comment xml:lang="en_GB">Thomson Mémo7 cartridge</comment>
- <comment xml:lang="es">cartucho Mémo7 de Thomson</comment>
- <comment xml:lang="fr">cartouche Thomson Mémo7</comment>
- <comment xml:lang="ga">cartús Thomson Mémo7</comment>
- <comment xml:lang="hr">Thomson Mémo7 uložak</comment>
- <comment xml:lang="hu">Thomson Mémo7 kazetta</comment>
- <comment xml:lang="id">cartridge Thomson Mémo7</comment>
- <comment xml:lang="it">Cartuccia Thomson Mémo7</comment>
- <comment xml:lang="kk">Thomson Mémo7 картриджі</comment>
- <comment xml:lang="ko">톰슨 메모7 카트릿지</comment>
- <comment xml:lang="pl">Kartridż Thomson Mémo7</comment>
- <comment xml:lang="pt_BR">Cartucho Thomson Mémo7</comment>
- <comment xml:lang="ru">Картридж Thomson Mémo7</comment>
- <comment xml:lang="sk">Kazeta Thomson Mémo7</comment>
- <comment xml:lang="sr">Томсон Мемо7 кертриџ</comment>
- <comment xml:lang="sv">Thomson Mémo7-spelkassett</comment>
- <comment xml:lang="tr">Thomson Mémo7 kartuşu</comment>
- <comment xml:lang="uk">картридж Thomson Mémo7</comment>
- <comment xml:lang="zh_CN">Thomson Mémo7 卡带</comment>
<comment xml:lang="zh_TW">Thomson Mémo7 卡匣</comment>
+ <comment xml:lang="zh_CN">Thomson Mémo7 卡带</comment>
+ <comment xml:lang="uk">картридж Thomson Mémo7</comment>
+ <comment xml:lang="tr">Thomson Mémo7 kartuşu</comment>
+ <comment xml:lang="sv">Thomson Mémo7-spelkassett</comment>
+ <comment xml:lang="sr">Томсон Мемо7 кертриџ</comment>
+ <comment xml:lang="sq">bobinë Thomson Mémo7</comment>
+ <comment xml:lang="si">Thomson Mémo7 කාට්රිජ්</comment>
+ <comment xml:lang="sk">Kazeta Thomson Mémo7</comment>
+ <comment xml:lang="ru">Картридж Thomson Mémo7</comment>
+ <comment xml:lang="pt_BR">Cartucho Thomson Mémo7</comment>
+ <comment xml:lang="pt">cartucho Thomson Mémo7</comment>
+ <comment xml:lang="pl">Kartridż Thomson Mémo7</comment>
+ <comment xml:lang="nl">Thomson Mémo7-casette</comment>
+ <comment xml:lang="ko">톰슨 Mémo7 카트리지</comment>
+ <comment xml:lang="kk">Thomson Mémo7 картриджі</comment>
+ <comment xml:lang="ja">Thomson Mémo7 カートリッジ</comment>
+ <comment xml:lang="it">Cartuccia Thomson Mémo7</comment>
+ <comment xml:lang="is">Thomson Mémo7 hylki</comment>
+ <comment xml:lang="id">Cartridge Thomson Mémo7</comment>
+ <comment xml:lang="hu">Thomson Mémo7 kazetta</comment>
+ <comment xml:lang="hr">Thomson Mémo7 uložak</comment>
+ <comment xml:lang="he">קלטת Thomson Mémo7</comment>
+ <comment xml:lang="gl">Cartucho de Thomson Mémo7</comment>
+ <comment xml:lang="ga">cartús Thomson Mémo7</comment>
+ <comment xml:lang="fur">cartucje Mémo7 Thomson</comment>
+ <comment xml:lang="fr">cartouche Thomson Mémo7</comment>
+ <comment xml:lang="fi">Thomson Mémo7 -patruuna</comment>
+ <comment xml:lang="eu">Thomson Mémo7 kartutxoa</comment>
+ <comment xml:lang="es">cartucho Mémo7 de Thomson</comment>
+ <comment xml:lang="en_GB">Thomson Mémo7 cartridge</comment>
+ <comment xml:lang="de">Thomson-Mémo7-Steckmodul</comment>
+ <comment xml:lang="da">Thomson Mémo7-kassette</comment>
+ <comment xml:lang="cs">Kazeta Thomson Mémo7</comment>
+ <comment xml:lang="ca">cartutx Thomson Mémo7</comment>
+ <comment xml:lang="bg">Касета — Thomson Mémo7</comment>
+ <comment xml:lang="be">картрыдж Thomson Mémo7</comment>
+ <comment xml:lang="ar">خرطوشة Thomson Mémo7</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.m7"/>
</mime-type>
<mime-type type="application/x-thomson-cassette">
<comment>Thomson cassette</comment>
- <comment xml:lang="ca">cinta de casset Thomson</comment>
- <comment xml:lang="cs">Kazeta Thomson</comment>
- <comment xml:lang="de">Thomson-Kassette</comment>
- <comment xml:lang="en_GB">Thomson cassette</comment>
- <comment xml:lang="es">casete de Thomson</comment>
- <comment xml:lang="fr">cassette Thomson</comment>
- <comment xml:lang="ga">caiséad Thomson</comment>
- <comment xml:lang="hr">Thomson kaseta</comment>
- <comment xml:lang="hu">Thomson kazetta</comment>
- <comment xml:lang="id">kaset Thomson</comment>
- <comment xml:lang="it">Cassetta Thomson</comment>
- <comment xml:lang="kk">Thomson кассетасы</comment>
- <comment xml:lang="ko">톰슨 카셋트</comment>
- <comment xml:lang="pl">Kaseta Thomson</comment>
- <comment xml:lang="pt_BR">Cassete Thomson</comment>
- <comment xml:lang="ru">Кассета Thomson</comment>
- <comment xml:lang="sk">Kazeta Thomson</comment>
- <comment xml:lang="sr">Томсон касете</comment>
- <comment xml:lang="sv">Thomson-kassett</comment>
- <comment xml:lang="tr">Thomson kaset</comment>
- <comment xml:lang="uk">касета Thomson</comment>
- <comment xml:lang="zh_CN">Thomson 磁带</comment>
<comment xml:lang="zh_TW">Thomson 卡匣</comment>
+ <comment xml:lang="zh_CN">Thomson 磁带</comment>
+ <comment xml:lang="uk">касета Thomson</comment>
+ <comment xml:lang="tr">Thomson kaset</comment>
+ <comment xml:lang="sv">Thomson-kassett</comment>
+ <comment xml:lang="sr">Томсон касете</comment>
+ <comment xml:lang="sq">kasetë Thomson</comment>
+ <comment xml:lang="sl">Kaseta Thomson</comment>
+ <comment xml:lang="si">තොම්සන් කැසට් පටය</comment>
+ <comment xml:lang="sk">Kazeta Thomson</comment>
+ <comment xml:lang="ru">Кассета Thomson</comment>
+ <comment xml:lang="pt_BR">Cassete Thomson</comment>
+ <comment xml:lang="pt">cassete Thomson</comment>
+ <comment xml:lang="pl">Kaseta Thomson</comment>
+ <comment xml:lang="nl">Thomson-cassette</comment>
+ <comment xml:lang="ko">톰슨 카세트</comment>
+ <comment xml:lang="kk">Thomson кассетасы</comment>
+ <comment xml:lang="ja">Thomson カセット</comment>
+ <comment xml:lang="it">Cassetta Thomson</comment>
+ <comment xml:lang="is">Thomson snælda</comment>
+ <comment xml:lang="id">Kaset Thomson</comment>
+ <comment xml:lang="hu">Thomson kazetta</comment>
+ <comment xml:lang="hr">Thomson kaseta</comment>
+ <comment xml:lang="he">קלטת Thomson</comment>
+ <comment xml:lang="ga">caiséad Thomson</comment>
+ <comment xml:lang="fur">cassete Thomson</comment>
+ <comment xml:lang="fr">cassette Thomson</comment>
+ <comment xml:lang="fi">Thomson-kasetti</comment>
+ <comment xml:lang="eu">Thomson kasetea</comment>
+ <comment xml:lang="es">casete de Thomson</comment>
+ <comment xml:lang="en_GB">Thomson cassette</comment>
+ <comment xml:lang="de">Thomson-Kassette</comment>
+ <comment xml:lang="da">Thomson-kassette</comment>
+ <comment xml:lang="cs">Kazeta Thomson</comment>
+ <comment xml:lang="ca">cinta de casset Thomson</comment>
+ <comment xml:lang="bg">Касета — Thomson</comment>
+ <comment xml:lang="be">касета Thomson</comment>
+ <comment xml:lang="ar">شريط Thomson</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.k7"/>
</mime-type>
<mime-type type="application/x-hfe-floppy-image">
<comment>HFE floppy disk image</comment>
- <comment xml:lang="ca">imatge de disquet HFE</comment>
- <comment xml:lang="cs">Obraz diskety HFE</comment>
- <comment xml:lang="de">HFE-Diskettenabbild</comment>
- <comment xml:lang="en_GB">HFE floppy disk image</comment>
- <comment xml:lang="es">imagen de disquete HFE</comment>
- <comment xml:lang="fr">image disquette HFE</comment>
- <comment xml:lang="ga">íomhá diosca fhlapaigh HFE</comment>
- <comment xml:lang="hr">HFE slika diskete</comment>
- <comment xml:lang="hu">HFE flopi lemezkép</comment>
- <comment xml:lang="id">image disk floppy HFE</comment>
- <comment xml:lang="it">Immagine disco floppy HFE</comment>
- <comment xml:lang="kk">HFE иілгіш диск бейнесі</comment>
- <comment xml:lang="ko">HFE 플로피 디스크 이미지</comment>
- <comment xml:lang="pl">Obraz dyskietki HFE</comment>
- <comment xml:lang="pt_BR">Imagem de disco flexível HFE</comment>
- <comment xml:lang="ru">Образ гибкого диска HFE</comment>
- <comment xml:lang="sk">Obraz pružného disku HFE</comment>
- <comment xml:lang="sr">ХФЕ слика флопи диска</comment>
- <comment xml:lang="sv">HFE-diskavbild</comment>
- <comment xml:lang="tr">HFE disket kalıbı</comment>
- <comment xml:lang="uk">образ дискети HFE</comment>
- <comment xml:lang="zh_CN">HFE 软盘映像</comment>
<comment xml:lang="zh_TW">HFE 軟碟映像檔</comment>
+ <comment xml:lang="zh_CN">HFE 软盘映像</comment>
+ <comment xml:lang="uk">образ дискети HFE</comment>
+ <comment xml:lang="tr">HFE disket görüntüsü</comment>
+ <comment xml:lang="sv">HFE-diskavbild</comment>
+ <comment xml:lang="sr">ХФЕ слика флопи диска</comment>
+ <comment xml:lang="sq">pamje diskete HFE</comment>
+ <comment xml:lang="sl">Slika diskete HFE</comment>
+ <comment xml:lang="si">HFE නම්ය තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz pružného disku HFE</comment>
+ <comment xml:lang="ru">Образ гибкого диска HFE</comment>
+ <comment xml:lang="pt_BR">Imagem de disco flexível HFE</comment>
+ <comment xml:lang="pt">imagem de disquete HFE</comment>
+ <comment xml:lang="pl">Obraz dyskietki HFE</comment>
+ <comment xml:lang="nl">HFE-diskette-schijfkopiebestand</comment>
+ <comment xml:lang="ko">HFE 플로피 디스크 이미지</comment>
+ <comment xml:lang="kk">HFE иілгіш диск бейнесі</comment>
+ <comment xml:lang="ja">HFE フロッピーディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco floppy HFE</comment>
+ <comment xml:lang="is">HFE disklingsmynd</comment>
+ <comment xml:lang="id">Image disk floppy HFE</comment>
+ <comment xml:lang="hu">HFE flopi lemezkép</comment>
+ <comment xml:lang="hr">HFE slika diskete</comment>
+ <comment xml:lang="he">דמות כונן תקליטון מסוג HPE</comment>
+ <comment xml:lang="gl">Imaxe de disquete HHFE</comment>
+ <comment xml:lang="ga">íomhá diosca fhlapaigh HFE</comment>
+ <comment xml:lang="fur">imagjin disc floppy HFE</comment>
+ <comment xml:lang="fr">image disquette HFE</comment>
+ <comment xml:lang="fi">HFE-levykekuva</comment>
+ <comment xml:lang="eu">HFE diskete disko irudia</comment>
+ <comment xml:lang="es">imagen de disquete HFE</comment>
+ <comment xml:lang="en_GB">HFE floppy disk image</comment>
+ <comment xml:lang="de">HFE-Diskettenabbild</comment>
+ <comment xml:lang="da">HFE-floppydiskaftryk</comment>
+ <comment xml:lang="cs">Obraz diskety HFE</comment>
+ <comment xml:lang="ca">imatge de disquet HFE</comment>
+ <comment xml:lang="bg">Диск — флопи, HFE</comment>
+ <comment xml:lang="be">вобраз гнуткага дыска HFE</comment>
+ <comment xml:lang="ar">صورة قرص مرن HFE</comment>
<acronym>HFE</acronym>
<expanded-acronym>HxC Floppy Emulator</expanded-acronym>
<generic-icon name="application-x-executable"/>
<glob pattern="*.hfe"/>
<magic>
- <match value="HXCPICFE" type="string" offset="0"/>
+ <match offset="0" type="string" value="HXCPICFE"/>
</magic>
<alias type="application/x-hfe-file"/>
</mime-type>
<mime-type type="application/x-thomson-sap-image">
<comment>SAP Thomson floppy disk image</comment>
- <comment xml:lang="ca">imatge de disquet SAP Thomson</comment>
- <comment xml:lang="cs">Obraz diskety SAP Thomson</comment>
- <comment xml:lang="de">SAP-Thomson-Diskettenabbild</comment>
- <comment xml:lang="en_GB">SAP Thomson floppy disk image</comment>
- <comment xml:lang="es">imagen de disquete SAP de Thomson</comment>
- <comment xml:lang="fr">image disquette SAP Thomson</comment>
- <comment xml:lang="ga">íomhá diosca fhlapaigh SAP Thomson</comment>
- <comment xml:lang="hr">SAP Thomson slika diskete</comment>
- <comment xml:lang="hu">SAP Thomson flopi lemezkép</comment>
- <comment xml:lang="id">image disk floppy SAP Thomson</comment>
- <comment xml:lang="it">Immagine disco floppy Thomson SAP</comment>
- <comment xml:lang="kk">SAP Thomson иілгіш диск бейнесі</comment>
- <comment xml:lang="ko">SAP 톰슨 플로피 디스크 이미지</comment>
- <comment xml:lang="pl">Obraz dyskietki SAP Thomson</comment>
- <comment xml:lang="pt_BR">Imagem de disco flexível SAP Thomson</comment>
- <comment xml:lang="ru">Образ гибкого диска SAP Thomson</comment>
- <comment xml:lang="sk">Obraz pružného disku SAP Thomson</comment>
- <comment xml:lang="sr">САП Томсон слика флопи диска</comment>
- <comment xml:lang="sv">SAP Thomson-diskavbild</comment>
- <comment xml:lang="tr">SAP Thomson disket kalıbı</comment>
- <comment xml:lang="uk">образ дискети Thomson SAP</comment>
- <comment xml:lang="zh_CN">SAP Thomson 软盘映像</comment>
<comment xml:lang="zh_TW">SAP Thomson 軟碟映像檔</comment>
+ <comment xml:lang="zh_CN">SAP Thomson 软盘映像</comment>
+ <comment xml:lang="uk">образ дискети Thomson SAP</comment>
+ <comment xml:lang="tr">SAP Thomson disket görüntüsü</comment>
+ <comment xml:lang="sv">SAP Thomson-diskavbild</comment>
+ <comment xml:lang="sr">САП Томсон слика флопи диска</comment>
+ <comment xml:lang="sq">pamje diskete SAP Thomson</comment>
+ <comment xml:lang="sl">Slika diskete SAP Thomson</comment>
+ <comment xml:lang="si">SAP තොම්සන් නම්ය තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz pružného disku SAP Thomson</comment>
+ <comment xml:lang="ru">Образ гибкого диска SAP Thomson</comment>
+ <comment xml:lang="pt_BR">Imagem de disco flexível SAP Thomson</comment>
+ <comment xml:lang="pt">imagem de disquete SAP Thomson</comment>
+ <comment xml:lang="pl">Obraz dyskietki SAP Thomson</comment>
+ <comment xml:lang="nl">SAP Thomson diskette-schijfkopiebestand</comment>
+ <comment xml:lang="ko">SAP 톰슨 플로피 디스크 이미지</comment>
+ <comment xml:lang="kk">SAP Thomson иілгіш диск бейнесі</comment>
+ <comment xml:lang="ja">SAP Thomson フロッピーディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco floppy Thomson SAP</comment>
+ <comment xml:lang="is">SAP Thomson disklingsmynd</comment>
+ <comment xml:lang="id">Image disk floppy SAP Thomson</comment>
+ <comment xml:lang="hu">SAP Thomson flopi lemezkép</comment>
+ <comment xml:lang="hr">SAP Thomson slika diskete</comment>
+ <comment xml:lang="he">דמות כונן תקליטון מסוג SAP Thomson</comment>
+ <comment xml:lang="gl">Imaxe de disquete SAP Thomson</comment>
+ <comment xml:lang="ga">íomhá diosca fhlapaigh SAP Thomson</comment>
+ <comment xml:lang="fur">imagjin disc floppy SAP Thomson</comment>
+ <comment xml:lang="fr">image disquette SAP Thomson</comment>
+ <comment xml:lang="fi">SAP Thomson -levykekuva</comment>
+ <comment xml:lang="eu">SAP Thomson diskete disko irudia</comment>
+ <comment xml:lang="es">imagen de disquete SAP de Thomson</comment>
+ <comment xml:lang="en_GB">SAP Thomson floppy disk image</comment>
+ <comment xml:lang="de">SAP-Thomson-Diskettenabbild</comment>
+ <comment xml:lang="da">SAP Thomson-floppydiskaftryk</comment>
+ <comment xml:lang="cs">Obraz diskety SAP Thomson</comment>
+ <comment xml:lang="ca">imatge de disquet SAP Thomson</comment>
+ <comment xml:lang="bg">Диск — флопи, SAP Thomson</comment>
+ <comment xml:lang="be">вобраз гнуткага дыска SAP Thomson</comment>
+ <comment xml:lang="ar">صورة قرص مرن SAP Thomson</comment>
<acronym>SAP</acronym>
<expanded-acronym>Système d'Archivage Pukall</expanded-acronym>
<generic-icon name="application-x-executable"/>
<glob pattern="*.sap"/>
<magic>
- <match value="SYSTEME D'ARCHIVAGE PUKALL S.A.P. (c) Alexandre PUKALL Avril 1998" type="string" offset="1"/>
+ <match offset="1" type="string" value="SYSTEME D'ARCHIVAGE PUKALL S.A.P. (c) Alexandre PUKALL Avril 1998"/>
</magic>
<alias type="application/x-sap-file"/>
</mime-type>
<mime-type type="application/vnd.debian.binary-package">
<comment>Debian package</comment>
- <comment xml:lang="ar">حزمة ديبيان</comment>
- <comment xml:lang="az">Debian paketi</comment>
- <comment xml:lang="be@latin">Pakunak Debian</comment>
- <comment xml:lang="bg">Пакет — Debian</comment>
- <comment xml:lang="ca">paquet Debian</comment>
- <comment xml:lang="cs">balíček Debianu</comment>
- <comment xml:lang="cy">Pecyn Debian</comment>
- <comment xml:lang="da">Debianpakke</comment>
- <comment xml:lang="de">Debian-Paket</comment>
- <comment xml:lang="el">Πακέτο Debian</comment>
- <comment xml:lang="en_GB">Debian package</comment>
- <comment xml:lang="eo">Debian-pakaĵo</comment>
- <comment xml:lang="es">paquete de Debian</comment>
- <comment xml:lang="eu">Debian paketea</comment>
- <comment xml:lang="fi">Debian-paketti</comment>
- <comment xml:lang="fo">Debian pakki</comment>
- <comment xml:lang="fr">paquet Debian</comment>
- <comment xml:lang="ga">pacáiste Debian</comment>
- <comment xml:lang="gl">paquete de Debian</comment>
- <comment xml:lang="he">חבילת דביאן</comment>
- <comment xml:lang="hr">Debian paket</comment>
- <comment xml:lang="hu">Debian-csomag</comment>
- <comment xml:lang="ia">Pacchetto Debian</comment>
- <comment xml:lang="id">Paket Debian</comment>
- <comment xml:lang="it">Pacchetto Debian</comment>
- <comment xml:lang="ja">Debian パッケージ</comment>
- <comment xml:lang="ka">Debian-ის პაკეტი</comment>
- <comment xml:lang="kk">Debian дестесі</comment>
- <comment xml:lang="ko">데비안 패키지</comment>
- <comment xml:lang="lt">Debian paketas</comment>
- <comment xml:lang="lv">Debian pakotne</comment>
- <comment xml:lang="ms">Pakej Debian</comment>
- <comment xml:lang="nb">Debian pakke</comment>
- <comment xml:lang="nl">Debian-pakket</comment>
- <comment xml:lang="nn">Debian pakke</comment>
- <comment xml:lang="oc">paquet Debian</comment>
- <comment xml:lang="pl">Pakiet Debiana</comment>
- <comment xml:lang="pt">pacote Debian</comment>
- <comment xml:lang="pt_BR">Pacote Debian</comment>
- <comment xml:lang="ro">Pachet Debian</comment>
- <comment xml:lang="ru">Пакет Debian</comment>
- <comment xml:lang="sk">Balíček Debianu</comment>
- <comment xml:lang="sl">Datoteka paketa Debian</comment>
- <comment xml:lang="sq">Paketë Debian</comment>
- <comment xml:lang="sr">Дебијанов пакет</comment>
- <comment xml:lang="sv">Debianpaket</comment>
- <comment xml:lang="tr">Debian paketi</comment>
- <comment xml:lang="uk">пакунок Debian</comment>
- <comment xml:lang="vi">Gói Debian</comment>
- <comment xml:lang="zh_CN">Debian 软件包</comment>
<comment xml:lang="zh_TW">Debian 軟體包</comment>
+ <comment xml:lang="zh_CN">Debian 软件包</comment>
+ <comment xml:lang="vi">Gói Debian</comment>
+ <comment xml:lang="uk">пакунок Debian</comment>
+ <comment xml:lang="tr">Debian paketi</comment>
+ <comment xml:lang="sv">Debianpaket</comment>
+ <comment xml:lang="sr">Дебијанов пакет</comment>
+ <comment xml:lang="sq">Paketë Debian</comment>
+ <comment xml:lang="sl">Datoteka paketa Debian</comment>
+ <comment xml:lang="si">ඩේබියන් පැකේජය</comment>
+ <comment xml:lang="sk">Balíček Debianu</comment>
+ <comment xml:lang="ru">Пакет Debian</comment>
+ <comment xml:lang="ro">Pachet Debian</comment>
+ <comment xml:lang="pt_BR">Pacote Debian</comment>
+ <comment xml:lang="pt">pacote Debian</comment>
+ <comment xml:lang="pl">Pakiet Debiana</comment>
+ <comment xml:lang="oc">paquet Debian</comment>
+ <comment xml:lang="nn">Debian pakke</comment>
+ <comment xml:lang="nl">Debian-pakket</comment>
+ <comment xml:lang="nb">Debian pakke</comment>
+ <comment xml:lang="ms">Pakej Debian</comment>
+ <comment xml:lang="lv">Debian pakotne</comment>
+ <comment xml:lang="lt">Debian paketas</comment>
+ <comment xml:lang="ko">데비안 패키지</comment>
+ <comment xml:lang="kk">Debian дестесі</comment>
+ <comment xml:lang="ka">Debian-ის პაკეტი</comment>
+ <comment xml:lang="ja">Debian パッケージ</comment>
+ <comment xml:lang="it">Pacchetto Debian</comment>
+ <comment xml:lang="is">Debian pakki</comment>
+ <comment xml:lang="id">Paket Debian</comment>
+ <comment xml:lang="ia">Pacchetto Debian</comment>
+ <comment xml:lang="hu">Debian-csomag</comment>
+ <comment xml:lang="hr">Debian paket</comment>
+ <comment xml:lang="he">חבילת Debian</comment>
+ <comment xml:lang="gl">paquete de Debian</comment>
+ <comment xml:lang="ga">pacáiste Debian</comment>
+ <comment xml:lang="fur">pachet Debian</comment>
+ <comment xml:lang="fr">paquet Debian</comment>
+ <comment xml:lang="fo">Debian pakki</comment>
+ <comment xml:lang="fi">Debian-paketti</comment>
+ <comment xml:lang="eu">Debian paketea</comment>
+ <comment xml:lang="es">paquete de Debian</comment>
+ <comment xml:lang="eo">Debian-pakaĵo</comment>
+ <comment xml:lang="en_GB">Debian package</comment>
+ <comment xml:lang="el">Πακέτο Debian</comment>
+ <comment xml:lang="de">Debian-Paket</comment>
+ <comment xml:lang="da">Debianpakke</comment>
+ <comment xml:lang="cy">Pecyn Debian</comment>
+ <comment xml:lang="cs">balíček Debianu</comment>
+ <comment xml:lang="ca">paquet Debian</comment>
+ <comment xml:lang="bg">Пакет — Debian</comment>
+ <comment xml:lang="be@latin">Pakunak Debian</comment>
+ <comment xml:lang="be">пакет Debian</comment>
+ <comment xml:lang="az">Debian paketi</comment>
+ <comment xml:lang="ar">حزمة ديبيان</comment>
+ <comment xml:lang="af">Debian-pakket</comment>
<alias type="application/x-deb"/>
<alias type="application/x-debian-package"/>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="!&lt;arch&gt;" type="string" offset="0">
- <match value="debian" type="string" offset="8"/>
+ <magic>
+ <match type="string" value="!&lt;arch&gt;" offset="0">
+ <match type="string" value="debian" offset="8"/>
</match>
</magic>
<glob pattern="*.deb"/>
<glob pattern="*.udeb"/>
</mime-type>
<mime-type type="application/x-designer">
- <comment>Qt Designer file</comment>
- <comment xml:lang="ar">ملف Qt Designer</comment>
- <comment xml:lang="be@latin">Fajł Qt Designer</comment>
- <comment xml:lang="bg">Файл — Qt Designer</comment>
- <comment xml:lang="ca">fitxer de Qt Designer</comment>
- <comment xml:lang="cs">soubor Qt Designer</comment>
- <comment xml:lang="da">Qt Designer-fil</comment>
- <comment xml:lang="de">Qt-Designer-Datei</comment>
- <comment xml:lang="el">Αρχείο Qt Designer</comment>
- <comment xml:lang="en_GB">Qt Designer file</comment>
- <comment xml:lang="eo">dosiero de Qt Designer</comment>
- <comment xml:lang="es">archivo de Qt Designer</comment>
- <comment xml:lang="eu">Qt Designer Fitxategia</comment>
- <comment xml:lang="fi">Qt Designer -tiedosto</comment>
- <comment xml:lang="fo">Qt Designer fíla</comment>
- <comment xml:lang="fr">fichier Qt Designer</comment>
- <comment xml:lang="ga">comhad Qt Designer</comment>
- <comment xml:lang="gl">ficheiro de Qt Designer</comment>
- <comment xml:lang="he">קובץ של Qt Designer</comment>
- <comment xml:lang="hr">Qt Designer datoteka</comment>
- <comment xml:lang="hu">Qt Designer-fájl</comment>
- <comment xml:lang="ia">File Qt Designer</comment>
- <comment xml:lang="id">Berkas Qt Designer</comment>
- <comment xml:lang="it">File Qt Designer</comment>
- <comment xml:lang="ja">Qt Designer ファイル</comment>
- <comment xml:lang="kk">Qt Designer файлы</comment>
- <comment xml:lang="ko">Qt 디자이너 파일</comment>
- <comment xml:lang="lt">Qt Designer failas</comment>
- <comment xml:lang="lv">Qt Designer datne</comment>
- <comment xml:lang="ms">Fail Qt Designer</comment>
- <comment xml:lang="nb">Qt Designer-fil</comment>
- <comment xml:lang="nl">Qt Designer-bestand</comment>
- <comment xml:lang="nn">Qt Designer-fil</comment>
- <comment xml:lang="oc">fichièr Qt Designer</comment>
- <comment xml:lang="pl">Plik Qt Designer</comment>
- <comment xml:lang="pt">ficheiro do Qt Designer</comment>
- <comment xml:lang="pt_BR">Arquivo do Qt Designer</comment>
- <comment xml:lang="ro">Fișier Qt Designer</comment>
- <comment xml:lang="ru">Файл Qt Designer</comment>
- <comment xml:lang="sk">Súbor Qt Designer</comment>
- <comment xml:lang="sl">Datoteka Qt Designer</comment>
- <comment xml:lang="sq">File Qt Designer</comment>
- <comment xml:lang="sr">датотека Кут дизајнера</comment>
- <comment xml:lang="sv">Qt Designer-fil</comment>
- <comment xml:lang="tr">Qt Tasarımcı dosyası</comment>
- <comment xml:lang="uk">файл програми Qt-дизайнер</comment>
- <comment xml:lang="vi">Tập tin thiết kế Qt Designer</comment>
- <comment xml:lang="zh_CN">Qt Designer 文件</comment>
- <comment xml:lang="zh_TW">Qt Designer 檔案</comment>
+ <comment>Qt Designer interface document</comment>
+ <comment xml:lang="zh_TW">Qt Designer 介面文件</comment>
+ <comment xml:lang="zh_CN">Qt Designer 界面文档</comment>
+ <comment xml:lang="uk">документ інтерфейсу Qt Designer</comment>
+ <comment xml:lang="tr">Qt Designer arayüz belgesi</comment>
+ <comment xml:lang="sv">Qt Designer-gränssnittsdokument</comment>
+ <comment xml:lang="sq">dokument ndërfaqesh Qt Designer</comment>
+ <comment xml:lang="sl">Dokument vmesnika Qt Designer</comment>
+ <comment xml:lang="si">Qt Designer අතුරුමුහුණත් ලේඛනය</comment>
+ <comment xml:lang="ru">Документ интерфейса Qt Designer</comment>
+ <comment xml:lang="pt_BR">Documento de interface do Qt Designer</comment>
+ <comment xml:lang="pt">documento de interface Qt Designer</comment>
+ <comment xml:lang="pl">Dokument interfejsu Qt Designer</comment>
+ <comment xml:lang="nl">Qt Designer-interfacedocument</comment>
+ <comment xml:lang="ko">Qt 디자이너 인터페이스 문서</comment>
+ <comment xml:lang="kk">Qt Designer интерфейс құжаты</comment>
+ <comment xml:lang="ja">Qt Designer インターフェイスドキュメント</comment>
+ <comment xml:lang="it">Documento interfaccia Qt Designer</comment>
+ <comment xml:lang="is">Qt Designer viðmótsskjal</comment>
+ <comment xml:lang="id">Dokumen antarmuka Qt Designer</comment>
+ <comment xml:lang="hu">Qt Designer felületleíró dokumentum</comment>
+ <comment xml:lang="hr">Qt Designer dokument sučelja</comment>
+ <comment xml:lang="he">מסמך מנשק של Qt Designer</comment>
+ <comment xml:lang="fr">document d'interface Qt Designer</comment>
+ <comment xml:lang="fi">Qt Designer -käyttöliittymän asiakirja</comment>
+ <comment xml:lang="eu">Qt Designer interfaze dokumentua</comment>
+ <comment xml:lang="es">documento de interfaz de Qt Designer</comment>
+ <comment xml:lang="en_GB">Qt Designer interface document</comment>
+ <comment xml:lang="de">Qt-Designer-Oberflächendokument</comment>
+ <comment xml:lang="da">Qt Designer-brugerflade-dokument</comment>
+ <comment xml:lang="ca">document d'interfície Qt Designer</comment>
+ <comment xml:lang="bg">Документ — интерфейс, Qt Designer</comment>
+ <comment xml:lang="be">дакумент інтэрфейсу Qt Designer</comment>
+ <comment xml:lang="ar">مستند واجهة مصمم كيوت</comment>
<generic-icon name="x-office-document"/>
<sub-class-of type="application/xml"/>
<magic>
- <match value="&lt;ui " type="string" offset="0:256"/>
- <match value="&lt;UI " type="string" offset="0:256"/>
+ <match type="string" value="&lt;ui " offset="0:256"/>
+ <match type="string" value="&lt;UI " offset="0:256"/>
</magic>
<glob pattern="*.ui"/>
</mime-type>
+ <mime-type type="text/x-kaitai-struct">
+ <comment>Kaitai Struct definition file</comment>
+ <comment xml:lang="uk">файл визначень Kaitai Struct</comment>
+ <comment xml:lang="tr">Kaitai Struct tanım dosyası</comment>
+ <comment xml:lang="sv">Kaitai Struct-definitionsfil</comment>
+ <comment xml:lang="si">Kaitai Struct නිර්වචන ගොනුව</comment>
+ <comment xml:lang="ru">Файл Kaitai Struct definition</comment>
+ <comment xml:lang="pt_BR">Arquivo de definição da Kaitai Struct</comment>
+ <comment xml:lang="pl">Plik definicji Kaitai Struct</comment>
+ <comment xml:lang="nl">Kaitai Struct-definitiebestand</comment>
+ <comment xml:lang="ko">Kaitai 구조체 정의 파일</comment>
+ <comment xml:lang="kk">Kaitai Struct сипаттама файлы</comment>
+ <comment xml:lang="ja">Kaitai Struct 定義ファイル</comment>
+ <comment xml:lang="it">File definizione Kaitai Struct</comment>
+ <comment xml:lang="is">Kaitai Struct skilgreiningarskrá</comment>
+ <comment xml:lang="id">berkas definisi Kaitai Struct</comment>
+ <comment xml:lang="hu">Kaitai szerkezetdefiníciós fájl</comment>
+ <comment xml:lang="hr">Kaitai Struct datoteka definicije</comment>
+ <comment xml:lang="he">קובץ הגדרת Kaitai Struct</comment>
+ <comment xml:lang="fr">Fichier de définition Kaitai Struct</comment>
+ <comment xml:lang="fi">Kaitai Struct -määritystiedosto</comment>
+ <comment xml:lang="es">archivo de definición de Kaitai Struct</comment>
+ <comment xml:lang="en_GB">Kaitai Struct definition file</comment>
+ <comment xml:lang="de">Kaitai Struct-Definitionsdatei</comment>
+ <comment xml:lang="da">Kaitai Struct-definitionsfil</comment>
+ <comment xml:lang="ca">fitxer de definicions Kaitai Struct</comment>
+ <comment xml:lang="be">файл азначэння Kaitai Struct</comment>
+ <comment xml:lang="ar">ملف تعريف Kaitai Struct</comment>
+ <sub-class-of type="application/yaml"/>
+ <glob pattern="*.ksy"/>
+ </mime-type>
<mime-type type="text/x-qml">
<comment>Qt Markup Language file</comment>
- <comment xml:lang="bg">Файл — Qt Markup</comment>
- <comment xml:lang="ca">fitxer de llenguatge de marcadors Qt</comment>
- <comment xml:lang="cs">soubor Qt Markup Language</comment>
- <comment xml:lang="da">Qt Markup Language-fil</comment>
- <comment xml:lang="de">Qt-Auszeichnungssprachendatei</comment>
- <comment xml:lang="el">Αρχείο Qt Markup Language</comment>
- <comment xml:lang="en_GB">Qt Markup Language file</comment>
- <comment xml:lang="es">archivo de lenguaje de marcado Qt</comment>
- <comment xml:lang="eu">Qt Markup lengoai fitxategia</comment>
- <comment xml:lang="fi">QML-tiedosto</comment>
- <comment xml:lang="fr">fichier Qt Markup Language</comment>
- <comment xml:lang="ga">comhad teanga mharcála Qt</comment>
- <comment xml:lang="gl">ficheiro de linguaxe de marcado Qt</comment>
- <comment xml:lang="he">קובץ שפת סימון של Qt</comment>
- <comment xml:lang="hr">Qt Markup Language datoteka</comment>
- <comment xml:lang="hu">Qt jelölőnyelvű fájl</comment>
- <comment xml:lang="ia">File de linguage de marcation Qt</comment>
- <comment xml:lang="id">Berkas Bahasa Markup Qt</comment>
- <comment xml:lang="it">File Qt Markup Language</comment>
- <comment xml:lang="ja">Qt マークアップ言語ファイル</comment>
- <comment xml:lang="kk">Qt Markup Language файлы</comment>
- <comment xml:lang="ko">Qt 마크업 언어 파일</comment>
- <comment xml:lang="lv">Qt marķēšanas valodas datne</comment>
- <comment xml:lang="nl">Qt Markup Tallbestand</comment>
- <comment xml:lang="oc">fichièr Qt Markup Language</comment>
- <comment xml:lang="pl">Plik języka znaczników Qt</comment>
- <comment xml:lang="pt">ficheiro de linguagem Qt Markup</comment>
- <comment xml:lang="pt_BR">Arquivo de Qt Markup Language</comment>
- <comment xml:lang="ru">Файл Qt Markup Language</comment>
- <comment xml:lang="sk">Súbor značkovacieho jazyka Qt</comment>
- <comment xml:lang="sl">Datoteka označevalnega jezika Qt</comment>
- <comment xml:lang="sr">датотека КуТ-овог језика означавања</comment>
- <comment xml:lang="sv">Qt-märkspråksfil</comment>
- <comment xml:lang="tr">Qt İşaretleme Dili dosyası</comment>
- <comment xml:lang="uk">файл мови розмітки Qt</comment>
- <comment xml:lang="zh_CN">Qt Markup Language 文件</comment>
<comment xml:lang="zh_TW">Qt 標記語言檔</comment>
- <magic priority="80">
- <match value="/bin/env qml" type="string" offset="2:16"/>
- <match value="import Qt" type="string" offset="0:3000">
- <match value="{" type="string" offset="9:3009"/>
+ <comment xml:lang="zh_CN">Qt Markup Language 文件</comment>
+ <comment xml:lang="uk">файл мови розмітки Qt</comment>
+ <comment xml:lang="tr">Qt İşaretleme Dili dosyası</comment>
+ <comment xml:lang="sv">Qt-märkspråksfil</comment>
+ <comment xml:lang="sr">датотека КуТ-овог језика означавања</comment>
+ <comment xml:lang="sq">kartelë Qt Markup Language</comment>
+ <comment xml:lang="sl">Datoteka označevalnega jezika Qt</comment>
+ <comment xml:lang="si">Qt Markup භාෂා ගොනුව</comment>
+ <comment xml:lang="sk">Súbor značkovacieho jazyka Qt</comment>
+ <comment xml:lang="ru">Файл Qt Markup Language</comment>
+ <comment xml:lang="pt_BR">Arquivo de Qt Markup Language</comment>
+ <comment xml:lang="pt">ficheiro de linguagem Qt Markup</comment>
+ <comment xml:lang="pl">Plik języka znaczników Qt</comment>
+ <comment xml:lang="oc">fichièr Qt Markup Language</comment>
+ <comment xml:lang="nl">Qt Markup Tallbestand</comment>
+ <comment xml:lang="lv">Qt marķēšanas valodas datne</comment>
+ <comment xml:lang="ko">Qt 마크업 언어 파일</comment>
+ <comment xml:lang="kk">Qt Markup Language файлы</comment>
+ <comment xml:lang="ja">Qt マークアップ言語ファイル</comment>
+ <comment xml:lang="it">File Qt Markup Language</comment>
+ <comment xml:lang="is">Qt Markup Language skrá</comment>
+ <comment xml:lang="id">Berkas Bahasa Markup Qt</comment>
+ <comment xml:lang="ia">File de linguage de marcation Qt</comment>
+ <comment xml:lang="hu">Qt jelölőnyelvű fájl</comment>
+ <comment xml:lang="hr">Qt Markup Language datoteka</comment>
+ <comment xml:lang="he">קובץ שפת סימון של Qt</comment>
+ <comment xml:lang="gl">ficheiro de linguaxe de marcado Qt</comment>
+ <comment xml:lang="ga">comhad teanga mharcála Qt</comment>
+ <comment xml:lang="fur">file Qt Markup Language</comment>
+ <comment xml:lang="fr">fichier Qt Markup Language</comment>
+ <comment xml:lang="fi">QML-tiedosto</comment>
+ <comment xml:lang="eu">Qt Markup lengoai fitxategia</comment>
+ <comment xml:lang="es">archivo de lenguaje de marcado Qt</comment>
+ <comment xml:lang="en_GB">Qt Markup Language file</comment>
+ <comment xml:lang="el">Αρχείο Qt Markup Language</comment>
+ <comment xml:lang="de">Qt-Auszeichnungssprachendatei</comment>
+ <comment xml:lang="da">Qt Markup Language-fil</comment>
+ <comment xml:lang="cs">soubor Qt Markup Language</comment>
+ <comment xml:lang="ca">fitxer de llenguatge de marcadors Qt</comment>
+ <comment xml:lang="bg">Интерфейс — Qt Markup</comment>
+ <comment xml:lang="be">файл Qt Markup Language</comment>
+ <comment xml:lang="ar">ملف لغة وصف Qt</comment>
+ <comment xml:lang="af">Qt Markup Language-lêer</comment>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="/bin/env qml" offset="2:16"/>
+ <match type="string" value="import Qt" offset="0:3000">
+ <match type="string" value="{" offset="9:3009"/>
</match>
- <match value="import Qml" type="string" offset="0:3000">
- <match value="{" type="string" offset="9:3009"/>
+ <match type="string" value="import Qml" offset="0:3000">
+ <match type="string" value="{" offset="9:3009"/>
</match>
</magic>
<glob pattern="*.qml"/>
@@ -10068,63 +10833,25 @@
<glob pattern="*.qmlproject"/>
</mime-type>
<mime-type type="application/x-desktop">
- <comment>desktop configuration file</comment>
- <comment xml:lang="ar">ملف تضبيط سطح المكتب</comment>
- <comment xml:lang="be@latin">kanfihuracyjny fajł asiarodździa</comment>
- <comment xml:lang="bg">Файл с информация за работния плот</comment>
- <comment xml:lang="ca">fitxer de configuració d'escriptori</comment>
- <comment xml:lang="cs">soubor nastavení pracovní plochy</comment>
- <comment xml:lang="da">skrivebordskonfigurationsfil</comment>
- <comment xml:lang="de">Desktop-Konfigurationsdatei</comment>
- <comment xml:lang="el">Αρχείο ρυθμίσεων επιφάνειας εργασίας</comment>
- <comment xml:lang="en_GB">desktop configuration file</comment>
- <comment xml:lang="eo">dosiero de agordoj de labortablo</comment>
- <comment xml:lang="es">archivo de configuración del escritorio</comment>
- <comment xml:lang="eu">Mahaigainaren konfigurazio-fitxategia</comment>
- <comment xml:lang="fi">työpöydän asetustiedosto</comment>
- <comment xml:lang="fo">skriviborðssamansetingarfíla</comment>
- <comment xml:lang="fr">fichier de configuration desktop</comment>
- <comment xml:lang="ga">comhad cumraíochta deisce</comment>
- <comment xml:lang="gl">ficheiro de configuración de escritorio</comment>
- <comment xml:lang="he">קובץ הגדרות שולחן עבודה</comment>
- <comment xml:lang="hr">Datoteka prečaca radne površine</comment>
- <comment xml:lang="hu">asztalbeállító fájl</comment>
- <comment xml:lang="ia">File de configuration de scriptorio</comment>
- <comment xml:lang="id">berkas konfigurasi destop</comment>
- <comment xml:lang="it">File configurazione desktop</comment>
- <comment xml:lang="ja">デスクトップ設定ファイル</comment>
- <comment xml:lang="kk">жұмыс үстел баптаулар файлы</comment>
- <comment xml:lang="ko">데스크톱 설정 파일</comment>
- <comment xml:lang="lt">darbastalio konfigūracijos failas</comment>
- <comment xml:lang="lv">darbvirsmas konfigurācijas datne</comment>
- <comment xml:lang="ms">Fail konfigurasi desktop</comment>
- <comment xml:lang="nb">konfigurasjonsfil for skrivebordet</comment>
- <comment xml:lang="nl">bureaublad-configuratiebestand</comment>
- <comment xml:lang="nn">skrivebordsoppsettfil</comment>
- <comment xml:lang="oc">fichièr de configuracion desktop</comment>
- <comment xml:lang="pl">Plik konfiguracji środowiska</comment>
- <comment xml:lang="pt">ficheiro de configuração de área de trabalho</comment>
- <comment xml:lang="pt_BR">Arquivo de configuração desktop</comment>
- <comment xml:lang="ro">fișier de configurare al desktopului</comment>
- <comment xml:lang="ru">Файл настроек рабочего стола</comment>
- <comment xml:lang="sk">Súbor nastavení pracovnej plochy</comment>
- <comment xml:lang="sl">nastavitvena datoteka namizja</comment>
- <comment xml:lang="sq">File konfigurimi desktop</comment>
- <comment xml:lang="sr">датотека подешавања радне површи</comment>
- <comment xml:lang="sv">skrivbordskonfigurationsfil</comment>
- <comment xml:lang="tr">masa üstü yapılandırma dosyası</comment>
- <comment xml:lang="uk">файл конфігурації стільниці</comment>
- <comment xml:lang="vi">tập tin cấu hình môi trường</comment>
- <comment xml:lang="zh_CN">桌面配置文件</comment>
- <comment xml:lang="zh_TW">桌面組態檔</comment>
+ <comment>Desktop entry</comment>
+ <comment xml:lang="uk">стільничний запис</comment>
+ <comment xml:lang="sv">Skrivbordspost</comment>
+ <comment xml:lang="ru">Запись рабочего стола</comment>
+ <comment xml:lang="pl">Wpis środowiska</comment>
+ <comment xml:lang="it">Elemento desktop</comment>
+ <comment xml:lang="gl">Entrada de escritorio</comment>
+ <comment xml:lang="eu">Mahaigaineko sarrera</comment>
+ <comment xml:lang="es">entrada de escritorio</comment>
+ <comment xml:lang="de">Desktop-Eintrag</comment>
+ <comment xml:lang="be">запіс desktop</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="[Desktop Entry]" type="string" offset="0:32"/>
- <match value="[Desktop Action" type="string" offset="0"/>
- <match value="[KDE Desktop Entry]" type="string" offset="0"/>
- <match value="# Config File" type="string" offset="0"/>
- <match value="# KDE Config File" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="[Desktop Entry]" offset="0:32"/>
+ <match type="string" value="[Desktop Action" offset="0"/>
+ <match type="string" value="[KDE Desktop Entry]" offset="0"/>
+ <match type="string" value="# Config File" offset="0"/>
+ <match type="string" value="# KDE Config File" offset="0"/>
</magic>
<glob pattern="*.desktop"/>
<glob pattern="*.kdelnk"/>
@@ -10132,624 +10859,676 @@
</mime-type>
<mime-type type="application/x-fictionbook+xml">
<comment>FictionBook document</comment>
- <comment xml:lang="ar">مستند FictionBook</comment>
- <comment xml:lang="ast">Documentu de FictionBook</comment>
- <comment xml:lang="bg">Документ — FictionBook</comment>
- <comment xml:lang="ca">document FictionBook</comment>
- <comment xml:lang="cs">dokument FictionBook</comment>
- <comment xml:lang="da">FictionBook-dokument</comment>
- <comment xml:lang="de">FictionBook-Dokument</comment>
- <comment xml:lang="el">Έγγραφο FictionBook</comment>
- <comment xml:lang="en_GB">FictionBook document</comment>
- <comment xml:lang="eo">FictionBook-dokumento</comment>
- <comment xml:lang="es">documento FictionBook</comment>
- <comment xml:lang="eu">FictionBook dokumentua</comment>
- <comment xml:lang="fi">FictionBook-asiakirja</comment>
- <comment xml:lang="fo">FictionBook skjal</comment>
- <comment xml:lang="fr">document FictionBook</comment>
- <comment xml:lang="ga">cáipéis FictionBook</comment>
- <comment xml:lang="gl">documento de FictionBook</comment>
- <comment xml:lang="he">מסמך FictionBook</comment>
- <comment xml:lang="hr">FictionBook dokument</comment>
- <comment xml:lang="hu">FictionBook-dokumentum</comment>
- <comment xml:lang="ia">Documento FictionBook</comment>
- <comment xml:lang="id">Dokumen FictionBook</comment>
- <comment xml:lang="it">Documento FictionBook</comment>
- <comment xml:lang="ja">FictionBook ドキュメント</comment>
- <comment xml:lang="ka">FictionBook-ის დოკუმენტი</comment>
- <comment xml:lang="kk">FictionBook құжаты</comment>
- <comment xml:lang="ko">FictionBook 문서</comment>
- <comment xml:lang="lt">FictionBook dokumentas</comment>
- <comment xml:lang="lv">FictionBook dokuments</comment>
- <comment xml:lang="nl">FictionBook-document</comment>
- <comment xml:lang="oc">document FictionBook</comment>
- <comment xml:lang="pl">Dokument FictionBook</comment>
- <comment xml:lang="pt">documento FictionBook</comment>
- <comment xml:lang="pt_BR">Documento FictionBook</comment>
- <comment xml:lang="ro">Document FictionBook</comment>
- <comment xml:lang="ru">Документ FictionBook</comment>
- <comment xml:lang="sk">Dokument FictionBook</comment>
- <comment xml:lang="sl">Dokument FictionBook</comment>
- <comment xml:lang="sr">документ Фикшон Књиге</comment>
- <comment xml:lang="sv">FictionBook-dokument</comment>
- <comment xml:lang="tr">FictionBook belgesi</comment>
- <comment xml:lang="uk">документ FictionBook</comment>
- <comment xml:lang="vi">Tài liệu FictionBook</comment>
- <comment xml:lang="zh_CN">FictionBook 文档</comment>
<comment xml:lang="zh_TW">FictionBook 文件</comment>
+ <comment xml:lang="zh_CN">FictionBook 文档</comment>
+ <comment xml:lang="vi">Tài liệu FictionBook</comment>
+ <comment xml:lang="uk">документ FictionBook</comment>
+ <comment xml:lang="tr">FictionBook belgesi</comment>
+ <comment xml:lang="sv">FictionBook-dokument</comment>
+ <comment xml:lang="sr">документ Фикшон Књиге</comment>
+ <comment xml:lang="sq">dokument FictionBook</comment>
+ <comment xml:lang="sl">Dokument FictionBook</comment>
+ <comment xml:lang="si">ප්‍රබන්ධ පොත් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument FictionBook</comment>
+ <comment xml:lang="ru">Документ FictionBook</comment>
+ <comment xml:lang="ro">Document FictionBook</comment>
+ <comment xml:lang="pt_BR">Documento FictionBook</comment>
+ <comment xml:lang="pt">documento FictionBook</comment>
+ <comment xml:lang="pl">Dokument FictionBook</comment>
+ <comment xml:lang="oc">document FictionBook</comment>
+ <comment xml:lang="nl">FictionBook-document</comment>
+ <comment xml:lang="lv">FictionBook dokuments</comment>
+ <comment xml:lang="lt">FictionBook dokumentas</comment>
+ <comment xml:lang="ko">FictionBook 문서</comment>
+ <comment xml:lang="kk">FictionBook құжаты</comment>
+ <comment xml:lang="ka">FictionBook-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">FictionBook ドキュメント</comment>
+ <comment xml:lang="it">Documento FictionBook</comment>
+ <comment xml:lang="is">FictionBook skjal</comment>
+ <comment xml:lang="id">Dokumen FictionBook</comment>
+ <comment xml:lang="ia">Documento FictionBook</comment>
+ <comment xml:lang="hu">FictionBook-dokumentum</comment>
+ <comment xml:lang="hr">FictionBook dokument</comment>
+ <comment xml:lang="he">מסמך FictionBook</comment>
+ <comment xml:lang="gl">documento de FictionBook</comment>
+ <comment xml:lang="ga">cáipéis FictionBook</comment>
+ <comment xml:lang="fur">document FictionBook</comment>
+ <comment xml:lang="fr">document FictionBook</comment>
+ <comment xml:lang="fo">FictionBook skjal</comment>
+ <comment xml:lang="fi">FictionBook-asiakirja</comment>
+ <comment xml:lang="eu">FictionBook dokumentua</comment>
+ <comment xml:lang="es">documento FictionBook</comment>
+ <comment xml:lang="eo">FictionBook-dokumento</comment>
+ <comment xml:lang="en_GB">FictionBook document</comment>
+ <comment xml:lang="el">Έγγραφο FictionBook</comment>
+ <comment xml:lang="de">FictionBook-Dokument</comment>
+ <comment xml:lang="da">FictionBook-dokument</comment>
+ <comment xml:lang="cs">dokument FictionBook</comment>
+ <comment xml:lang="ca">document FictionBook</comment>
+ <comment xml:lang="bg">Документ — FictionBook</comment>
+ <comment xml:lang="be">дакумент FictionBook</comment>
+ <comment xml:lang="ast">Documentu de FictionBook</comment>
+ <comment xml:lang="ar">مستند FictionBook</comment>
+ <comment xml:lang="af">FictionBook-dokument</comment>
<sub-class-of type="application/xml"/>
<glob pattern="*.fb2"/>
<magic priority="80">
- <match value="&lt;FictionBook" type="string" offset="0:256"/>
+ <match type="string" value="&lt;FictionBook" offset="0:256"/>
</magic>
<alias type="application/x-fictionbook"/>
<root-XML namespaceURI="http://www.gribuser.ru/xml/fictionbook/2.0" localName="FictionBook"/>
</mime-type>
<mime-type type="application/x-zip-compressed-fb2">
<comment>Compressed FictionBook document</comment>
- <comment xml:lang="ast">Documentu comprimíu de FictionBook</comment>
- <comment xml:lang="ca">document FictionBook amb compressió</comment>
- <comment xml:lang="cs">komprimovaný dokument FictionBook</comment>
- <comment xml:lang="da">Komprimeret FictionBook-dokument</comment>
- <comment xml:lang="de">Komprimiertes FictionBook-Dokument</comment>
- <comment xml:lang="el">Συμπιεσμένο έγγραφο FictionBook</comment>
- <comment xml:lang="en_GB">Compressed FictionBook document</comment>
- <comment xml:lang="es">documento comprimido de FictionBook</comment>
- <comment xml:lang="eu">Konprimitutako FictionBook dokumentua</comment>
- <comment xml:lang="fi">Pakattu FictionBook-asiakirja</comment>
- <comment xml:lang="fr">document FictionBook compressé</comment>
- <comment xml:lang="ga">cáipéis chomhbhrúite FictionBook</comment>
- <comment xml:lang="gl">Documento de FictionBook comprimida</comment>
- <comment xml:lang="he">מסמך FictionBook מכווץ</comment>
- <comment xml:lang="hr">Sažet FictionBook dokument</comment>
- <comment xml:lang="hu">Tömörített FictionBook dokumentum</comment>
- <comment xml:lang="ia">Documento FictionBook comprimite</comment>
- <comment xml:lang="id">Dokumen FictionBook terkompresi</comment>
- <comment xml:lang="it">Documento FictionBook compresso</comment>
- <comment xml:lang="kk">Сығылған FictionBook құжаты</comment>
- <comment xml:lang="ko">압축한 FictionBook 문서</comment>
- <comment xml:lang="oc">document FictionBook compressat</comment>
- <comment xml:lang="pl">Skompresowany dokument FictionBook</comment>
- <comment xml:lang="pt">documento comprimido FictionBook</comment>
- <comment xml:lang="pt_BR">Documento FictionBook comprimido</comment>
- <comment xml:lang="ru">Сжатый документ FictionBook</comment>
- <comment xml:lang="sk">Komprimovaný dokument FictionBook</comment>
- <comment xml:lang="sl">Stisnjeni dokument FictionBook</comment>
- <comment xml:lang="sr">запаковани документ Фикшон Књиге</comment>
- <comment xml:lang="sv">Komprimerat FictionBook-dokument</comment>
- <comment xml:lang="tr">Sıkıştırılmış KurguKitap belgesi</comment>
- <comment xml:lang="uk">стиснений документ FictionBook</comment>
- <comment xml:lang="zh_CN">压缩的 FictionBook 文档</comment>
<comment xml:lang="zh_TW">壓縮版 FictionBook 文件</comment>
+ <comment xml:lang="zh_CN">压缩的 FictionBook 文档</comment>
+ <comment xml:lang="uk">стиснений документ FictionBook</comment>
+ <comment xml:lang="tr">Sıkıştırılmış FictionBook belgesi</comment>
+ <comment xml:lang="sv">Komprimerat FictionBook-dokument</comment>
+ <comment xml:lang="sr">запаковани документ Фикшон Књиге</comment>
+ <comment xml:lang="sq">dokument FictionBook i ngjeshur</comment>
+ <comment xml:lang="sl">Stisnjeni dokument FictionBook</comment>
+ <comment xml:lang="si">සම්පීඩිත FictionBook ලේඛනය</comment>
+ <comment xml:lang="sk">Komprimovaný dokument FictionBook</comment>
+ <comment xml:lang="ru">Сжатый документ FictionBook</comment>
+ <comment xml:lang="pt_BR">Documento FictionBook comprimido</comment>
+ <comment xml:lang="pt">documento comprimido FictionBook</comment>
+ <comment xml:lang="pl">Skompresowany dokument FictionBook</comment>
+ <comment xml:lang="oc">document FictionBook compressat</comment>
+ <comment xml:lang="nl">Gecomprimeerd FictionBook-document</comment>
+ <comment xml:lang="ko">압축한 FictionBook 문서</comment>
+ <comment xml:lang="kk">Сығылған FictionBook құжаты</comment>
+ <comment xml:lang="ja">圧縮 FictionBook ドキュメント</comment>
+ <comment xml:lang="it">Documento FictionBook compresso</comment>
+ <comment xml:lang="is">Þjappað FictionBook skjal</comment>
+ <comment xml:lang="id">Dokumen FictionBook terkompresi</comment>
+ <comment xml:lang="ia">Documento FictionBook comprimite</comment>
+ <comment xml:lang="hu">Tömörített FictionBook dokumentum</comment>
+ <comment xml:lang="hr">Sažet FictionBook dokument</comment>
+ <comment xml:lang="he">מסמך FictionBook מכווץ</comment>
+ <comment xml:lang="gl">Documento de FictionBook comprimida</comment>
+ <comment xml:lang="ga">cáipéis chomhbhrúite FictionBook</comment>
+ <comment xml:lang="fur">document FictionBook comprimût</comment>
+ <comment xml:lang="fr">document FictionBook compressé</comment>
+ <comment xml:lang="fi">Pakattu FictionBook-asiakirja</comment>
+ <comment xml:lang="eu">Konprimitutako FictionBook dokumentua</comment>
+ <comment xml:lang="es">documento comprimido de FictionBook</comment>
+ <comment xml:lang="en_GB">Compressed FictionBook document</comment>
+ <comment xml:lang="el">Συμπιεσμένο έγγραφο FictionBook</comment>
+ <comment xml:lang="de">Komprimiertes FictionBook-Dokument</comment>
+ <comment xml:lang="da">Komprimeret FictionBook-dokument</comment>
+ <comment xml:lang="cs">komprimovaný dokument FictionBook</comment>
+ <comment xml:lang="ca">document FictionBook amb compressió</comment>
+ <comment xml:lang="bg">Документ — FictionBook, компресиран</comment>
+ <comment xml:lang="be">сціснуты дакумент FictionBook</comment>
+ <comment xml:lang="ast">Documentu comprimíu de FictionBook</comment>
+ <comment xml:lang="ar">مستند FictionBook مضغوط</comment>
+ <comment xml:lang="af">Saamgepersde FictionBook-dokument</comment>
<sub-class-of type="application/zip"/>
<glob pattern="*.fb2.zip"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
-
- <match value=".fb2" type="string" offset="30:256"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <!-- Okay, this is not ideal, but it should be good enough for normal cases -->
+ <match type="string" value=".fb2" offset="30:256"/>
</match>
</magic>
</mime-type>
<mime-type type="application/x-dia-diagram">
<comment>Dia diagram</comment>
- <comment xml:lang="ar">خطاطة Dia</comment>
- <comment xml:lang="az">Dia diaqramı</comment>
- <comment xml:lang="be@latin">Dyjahrama Dia</comment>
- <comment xml:lang="bg">Диаграма — Dia</comment>
- <comment xml:lang="ca">diagrama de Dia</comment>
- <comment xml:lang="cs">diagram Dia</comment>
- <comment xml:lang="cy">Diagram Dia</comment>
- <comment xml:lang="da">Dia-diagram</comment>
- <comment xml:lang="de">Dia-Diagramm</comment>
- <comment xml:lang="el">Διάγραμμα Dia</comment>
- <comment xml:lang="en_GB">Dia diagram</comment>
- <comment xml:lang="eo">Dia-diagramo</comment>
- <comment xml:lang="es">diagrama de Dia</comment>
- <comment xml:lang="eu">Dia diagrama</comment>
- <comment xml:lang="fi">Dia-kaavio</comment>
- <comment xml:lang="fo">Dia ritmynd</comment>
- <comment xml:lang="fr">diagramme Dia</comment>
- <comment xml:lang="ga">léaráid Dia</comment>
- <comment xml:lang="gl">diagrama de Dia</comment>
- <comment xml:lang="he">גרף של Dia</comment>
- <comment xml:lang="hr">Dia dijagram</comment>
- <comment xml:lang="hu">Dia-diagram</comment>
- <comment xml:lang="ia">Diagramma Dia</comment>
- <comment xml:lang="id">Diagram Dia</comment>
- <comment xml:lang="it">Diagramma Dia</comment>
- <comment xml:lang="ja">Dia ダイアグラム</comment>
- <comment xml:lang="ka">Dia-ის დიაგრამა</comment>
- <comment xml:lang="kk">Dia диаграммасы</comment>
- <comment xml:lang="ko">Dia 다이어그램</comment>
- <comment xml:lang="lt">Dia diagrama</comment>
- <comment xml:lang="lv">Dia diagramma</comment>
- <comment xml:lang="ms">Diagram Dia</comment>
- <comment xml:lang="nb">Dia-diagram</comment>
- <comment xml:lang="nl">Dia-diagram</comment>
- <comment xml:lang="nn">Dia diagram</comment>
- <comment xml:lang="oc">diagrama Dia</comment>
- <comment xml:lang="pl">Diagram Dia</comment>
- <comment xml:lang="pt">diagrama Dia</comment>
- <comment xml:lang="pt_BR">Diagrama do Dia</comment>
- <comment xml:lang="ro">Diagramă Dia</comment>
- <comment xml:lang="ru">Диаграмма Dia</comment>
- <comment xml:lang="sk">Diagram Dia</comment>
- <comment xml:lang="sl">Datoteka diagrama Dia</comment>
- <comment xml:lang="sq">Diagramë Dia</comment>
- <comment xml:lang="sr">дијаграм Дие</comment>
- <comment xml:lang="sv">Dia-diagram</comment>
- <comment xml:lang="tr">Dia çizimi</comment>
- <comment xml:lang="uk">діаграма Dia</comment>
- <comment xml:lang="vi">Biểu đồ Dia</comment>
- <comment xml:lang="zh_CN">Dia 图表</comment>
<comment xml:lang="zh_TW">Dia 圖表</comment>
+ <comment xml:lang="zh_CN">Dia 图表</comment>
+ <comment xml:lang="vi">Biểu đồ Dia</comment>
+ <comment xml:lang="uk">діаграма Dia</comment>
+ <comment xml:lang="tr">Dia çizimi</comment>
+ <comment xml:lang="sv">Dia-diagram</comment>
+ <comment xml:lang="sr">дијаграм Дие</comment>
+ <comment xml:lang="sq">diagram Dia</comment>
+ <comment xml:lang="sl">Datoteka diagrama Dia</comment>
+ <comment xml:lang="si">Dia රූප සටහන</comment>
+ <comment xml:lang="sk">Diagram Dia</comment>
+ <comment xml:lang="ru">Диаграмма Dia</comment>
+ <comment xml:lang="ro">Diagramă Dia</comment>
+ <comment xml:lang="pt_BR">Diagrama do Dia</comment>
+ <comment xml:lang="pt">diagrama Dia</comment>
+ <comment xml:lang="pl">Diagram Dia</comment>
+ <comment xml:lang="oc">diagrama Dia</comment>
+ <comment xml:lang="nn">Dia diagram</comment>
+ <comment xml:lang="nl">Dia-diagram</comment>
+ <comment xml:lang="nb">Dia-diagram</comment>
+ <comment xml:lang="ms">Diagram Dia</comment>
+ <comment xml:lang="lv">Dia diagramma</comment>
+ <comment xml:lang="lt">Dia diagrama</comment>
+ <comment xml:lang="ko">Dia 다이어그램</comment>
+ <comment xml:lang="kk">Dia диаграммасы</comment>
+ <comment xml:lang="ka">Dia-ის დიაგრამა</comment>
+ <comment xml:lang="ja">Dia ダイアグラム</comment>
+ <comment xml:lang="it">Diagramma Dia</comment>
+ <comment xml:lang="is">Dia teikning</comment>
+ <comment xml:lang="id">Diagram Dia</comment>
+ <comment xml:lang="ia">Diagramma Dia</comment>
+ <comment xml:lang="hu">Dia-diagram</comment>
+ <comment xml:lang="hr">Dia dijagram</comment>
+ <comment xml:lang="he">גרף של Dia</comment>
+ <comment xml:lang="gl">diagrama de Dia</comment>
+ <comment xml:lang="ga">léaráid Dia</comment>
+ <comment xml:lang="fur">diagram Dia</comment>
+ <comment xml:lang="fr">diagramme Dia</comment>
+ <comment xml:lang="fo">Dia ritmynd</comment>
+ <comment xml:lang="fi">Dia-kaavio</comment>
+ <comment xml:lang="eu">Dia diagrama</comment>
+ <comment xml:lang="es">diagrama de Dia</comment>
+ <comment xml:lang="eo">Dia-diagramo</comment>
+ <comment xml:lang="en_GB">Dia diagram</comment>
+ <comment xml:lang="el">Διάγραμμα Dia</comment>
+ <comment xml:lang="de">Dia-Diagramm</comment>
+ <comment xml:lang="da">Dia-diagram</comment>
+ <comment xml:lang="cy">Diagram Dia</comment>
+ <comment xml:lang="cs">diagram Dia</comment>
+ <comment xml:lang="ca">diagrama de Dia</comment>
+ <comment xml:lang="bg">Диаграма — Dia</comment>
+ <comment xml:lang="be@latin">Dyjahrama Dia</comment>
+ <comment xml:lang="be">дыяграма Dia</comment>
+ <comment xml:lang="az">Dia diaqramı</comment>
+ <comment xml:lang="ar">خطاطة Dia</comment>
+ <comment xml:lang="af">Dia-diagram</comment>
<generic-icon name="image-x-generic"/>
<sub-class-of type="application/xml"/>
<glob pattern="*.dia"/>
- <magic priority="50">
- <match value="&lt;dia:" type="string" offset="5:100"/>
+ <magic>
+ <match offset="5:100" type="string" value="&lt;dia:"/>
</magic>
<root-XML namespaceURI="http://www.lysator.liu.se/~alla/dia/" localName="diagram"/>
</mime-type>
<mime-type type="application/x-dia-shape">
<comment>Dia shape</comment>
- <comment xml:lang="ar">شكل Dia</comment>
- <comment xml:lang="bg">Фигура — Dia</comment>
- <comment xml:lang="ca">forma de Dia</comment>
- <comment xml:lang="cs">symboly Dia</comment>
- <comment xml:lang="da">Dia-figur</comment>
- <comment xml:lang="de">Dia-Form</comment>
- <comment xml:lang="el">Σχήμα Dia</comment>
- <comment xml:lang="en_GB">Dia shape</comment>
- <comment xml:lang="es">forma de Dia</comment>
- <comment xml:lang="eu">Dia-ren forma</comment>
- <comment xml:lang="fi">Dia-muoto</comment>
- <comment xml:lang="fo">Dia skapur</comment>
- <comment xml:lang="fr">forme Dia</comment>
- <comment xml:lang="ga">cruth Dia</comment>
- <comment xml:lang="gl">forma de Dia</comment>
- <comment xml:lang="he">צורה של Dia</comment>
- <comment xml:lang="hr">Dia oblik</comment>
- <comment xml:lang="hu">Dia alakzat</comment>
- <comment xml:lang="ia">Forma Dia</comment>
- <comment xml:lang="id">Shape Dia</comment>
- <comment xml:lang="it">Sagoma Dia</comment>
- <comment xml:lang="ja">Dia 図形</comment>
- <comment xml:lang="kk">Dia сызбасы</comment>
- <comment xml:lang="ko">Dia 그림</comment>
- <comment xml:lang="lt">Dia forma</comment>
- <comment xml:lang="lv">Dia forma</comment>
- <comment xml:lang="nl">Diavorm</comment>
- <comment xml:lang="oc">forma Dia</comment>
- <comment xml:lang="pl">Kształt Dia</comment>
- <comment xml:lang="pt">forma Dia</comment>
- <comment xml:lang="pt_BR">Formato Dia</comment>
- <comment xml:lang="ro">Figură Dia</comment>
- <comment xml:lang="ru">Фигура Dia</comment>
- <comment xml:lang="sk">Tvar Dia</comment>
- <comment xml:lang="sl">Datoteka oblik Dia</comment>
- <comment xml:lang="sr">облик Дие</comment>
- <comment xml:lang="sv">Dia-figur</comment>
- <comment xml:lang="tr">Dia şekli</comment>
- <comment xml:lang="uk">форма Dia</comment>
- <comment xml:lang="zh_CN">Dia 形状</comment>
<comment xml:lang="zh_TW">Dia 形狀</comment>
+ <comment xml:lang="zh_CN">Dia 形状</comment>
+ <comment xml:lang="uk">форма Dia</comment>
+ <comment xml:lang="tr">Dia şekli</comment>
+ <comment xml:lang="sv">Dia-figur</comment>
+ <comment xml:lang="sr">облик Дие</comment>
+ <comment xml:lang="sq">formë Dia</comment>
+ <comment xml:lang="sl">Datoteka oblik Dia</comment>
+ <comment xml:lang="si">Dia හැඩය</comment>
+ <comment xml:lang="sk">Tvar Dia</comment>
+ <comment xml:lang="ru">Фигура Dia</comment>
+ <comment xml:lang="ro">Figură Dia</comment>
+ <comment xml:lang="pt_BR">Formato Dia</comment>
+ <comment xml:lang="pt">forma Dia</comment>
+ <comment xml:lang="pl">Kształt Dia</comment>
+ <comment xml:lang="oc">forma Dia</comment>
+ <comment xml:lang="nl">Diavorm</comment>
+ <comment xml:lang="lv">Dia forma</comment>
+ <comment xml:lang="lt">Dia forma</comment>
+ <comment xml:lang="ko">Dia 그림</comment>
+ <comment xml:lang="kk">Dia сызбасы</comment>
+ <comment xml:lang="ja">Dia 図形</comment>
+ <comment xml:lang="it">Sagoma Dia</comment>
+ <comment xml:lang="is">Dia lögun</comment>
+ <comment xml:lang="id">Shape Dia</comment>
+ <comment xml:lang="ia">Forma Dia</comment>
+ <comment xml:lang="hu">Dia alakzat</comment>
+ <comment xml:lang="hr">Dia oblik</comment>
+ <comment xml:lang="he">צורה של Dia</comment>
+ <comment xml:lang="gl">forma de Dia</comment>
+ <comment xml:lang="ga">cruth Dia</comment>
+ <comment xml:lang="fur">sagome Dia</comment>
+ <comment xml:lang="fr">forme Dia</comment>
+ <comment xml:lang="fo">Dia skapur</comment>
+ <comment xml:lang="fi">Dia-muoto</comment>
+ <comment xml:lang="eu">Dia-ren forma</comment>
+ <comment xml:lang="es">forma de Dia</comment>
+ <comment xml:lang="en_GB">Dia shape</comment>
+ <comment xml:lang="el">Σχήμα Dia</comment>
+ <comment xml:lang="de">Dia-Form</comment>
+ <comment xml:lang="da">Dia-figur</comment>
+ <comment xml:lang="cs">symboly Dia</comment>
+ <comment xml:lang="ca">forma de Dia</comment>
+ <comment xml:lang="bg">Фигура — Dia</comment>
+ <comment xml:lang="be">фігура Dia</comment>
+ <comment xml:lang="ar">شكل Dia</comment>
+ <comment xml:lang="af">Dia-vorm</comment>
<generic-icon name="image-x-generic"/>
<sub-class-of type="application/xml"/>
<glob pattern="*.shape"/>
- <magic priority="50">
- <match value="&lt;shape" type="string" offset="5:100"/>
+ <magic>
+ <match offset="5:100" type="string" value="&lt;shape"/>
</magic>
<root-XML namespaceURI="http://www.daa.com.au/~james/dia-shape-ns" localName="shape"/>
</mime-type>
<mime-type type="application/x-dvi">
<comment>TeX DVI document</comment>
- <comment xml:lang="ar">مستند TeX DVI</comment>
- <comment xml:lang="ast">Documentu Tex DVI</comment>
- <comment xml:lang="be@latin">Dakument TeX DVI</comment>
- <comment xml:lang="bg">Документ — TeX DVI</comment>
- <comment xml:lang="ca">document DVI de TeX</comment>
- <comment xml:lang="cs">dokument TeX DVI</comment>
- <comment xml:lang="da">TeX DVI-dokument</comment>
- <comment xml:lang="de">TeX-DVI-Dokument</comment>
- <comment xml:lang="el">Έγγραφο TeX DVI</comment>
- <comment xml:lang="en_GB">TeX DVI document</comment>
- <comment xml:lang="eo">DVI-dokumento de TeX</comment>
- <comment xml:lang="es">documento TeX DVI</comment>
- <comment xml:lang="eu">TeX DVI dokumentua</comment>
- <comment xml:lang="fi">TeX DVI -asiakirja</comment>
- <comment xml:lang="fo">TeX DVI skjal</comment>
- <comment xml:lang="fr">document TeX DVI</comment>
- <comment xml:lang="ga">cáipéis DVI TeX</comment>
- <comment xml:lang="gl">documento TeX DVI</comment>
- <comment xml:lang="he">מסמך מסוג TeX DVI</comment>
- <comment xml:lang="hr">TeX DVI dokument</comment>
- <comment xml:lang="hu">TeX DVI-dokumentum</comment>
- <comment xml:lang="ia">Documento TeX DVI</comment>
- <comment xml:lang="id">Dokumen TeX DVI</comment>
- <comment xml:lang="it">Documento TeX DVI</comment>
- <comment xml:lang="ja">TeX DVI ドキュメント</comment>
- <comment xml:lang="kk">TeX DVI құжаты</comment>
- <comment xml:lang="ko">TeX DVI 문서</comment>
- <comment xml:lang="lt">TeX DVI dokumentas</comment>
- <comment xml:lang="lv">TeX DVI dokuments</comment>
- <comment xml:lang="ms">Dokumen TeX DVI</comment>
- <comment xml:lang="nb">TeX DVI-dokument</comment>
- <comment xml:lang="nl">TeX DVI-document</comment>
- <comment xml:lang="nn">TeX DVI-dokument</comment>
- <comment xml:lang="oc">document TeX DVI</comment>
- <comment xml:lang="pl">Dokument TeX DVI</comment>
- <comment xml:lang="pt">documento TeX DVI</comment>
- <comment xml:lang="pt_BR">Documento DVI TeX</comment>
- <comment xml:lang="ro">Document Tex DVI</comment>
- <comment xml:lang="ru">Документ TeX DVI</comment>
- <comment xml:lang="sk">Dokument TeX DVI</comment>
- <comment xml:lang="sl">Dokument TeX DVI</comment>
- <comment xml:lang="sq">Dokument TeX DVI</comment>
- <comment xml:lang="sr">ТеКс ДВИ документ</comment>
- <comment xml:lang="sv">TeX DVI-dokument</comment>
- <comment xml:lang="tr">TeX DVI belgesi</comment>
- <comment xml:lang="uk">документ TeX DVI</comment>
- <comment xml:lang="vi">Tài liệu DVI Tex</comment>
- <comment xml:lang="zh_CN">TeX DVI 文档</comment>
<comment xml:lang="zh_TW">TeX DVI 文件</comment>
+ <comment xml:lang="zh_CN">TeX DVI 文档</comment>
+ <comment xml:lang="vi">Tài liệu DVI Tex</comment>
+ <comment xml:lang="uk">документ TeX DVI</comment>
+ <comment xml:lang="tr">TeX DVI belgesi</comment>
+ <comment xml:lang="sv">TeX DVI-dokument</comment>
+ <comment xml:lang="sr">ТеКс ДВИ документ</comment>
+ <comment xml:lang="sq">dokument TeX DVI</comment>
+ <comment xml:lang="sl">Dokument TeX DVI</comment>
+ <comment xml:lang="si">TeX DVI ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument TeX DVI</comment>
+ <comment xml:lang="ru">Документ DVI издательской системы TeX</comment>
+ <comment xml:lang="ro">Document Tex DVI</comment>
+ <comment xml:lang="pt_BR">Documento DVI TeX</comment>
+ <comment xml:lang="pt">documento TeX DVI</comment>
+ <comment xml:lang="pl">Dokument TeX DVI</comment>
+ <comment xml:lang="oc">document TeX DVI</comment>
+ <comment xml:lang="nn">TeX DVI-dokument</comment>
+ <comment xml:lang="nl">TeX DVI-document</comment>
+ <comment xml:lang="nb">TeX DVI-dokument</comment>
+ <comment xml:lang="ms">Dokumen TeX DVI</comment>
+ <comment xml:lang="lv">TeX DVI dokuments</comment>
+ <comment xml:lang="lt">TeX DVI dokumentas</comment>
+ <comment xml:lang="ko">TeX DVI 문서</comment>
+ <comment xml:lang="kk">TeX DVI құжаты</comment>
+ <comment xml:lang="ja">TeX DVI ドキュメント</comment>
+ <comment xml:lang="it">Documento TeX DVI</comment>
+ <comment xml:lang="is">TeX DVI skjal</comment>
+ <comment xml:lang="id">Dokumen TeX DVI</comment>
+ <comment xml:lang="ia">Documento TeX DVI</comment>
+ <comment xml:lang="hu">TeX DVI-dokumentum</comment>
+ <comment xml:lang="hr">TeX DVI dokument</comment>
+ <comment xml:lang="he">מסמך מסוג TeX DVI</comment>
+ <comment xml:lang="gl">documento TeX DVI</comment>
+ <comment xml:lang="ga">cáipéis DVI TeX</comment>
+ <comment xml:lang="fur">document DVI TeX</comment>
+ <comment xml:lang="fr">document TeX DVI</comment>
+ <comment xml:lang="fo">TeX DVI skjal</comment>
+ <comment xml:lang="fi">TeX DVI -asiakirja</comment>
+ <comment xml:lang="eu">TeX DVI dokumentua</comment>
+ <comment xml:lang="es">documento TeX DVI</comment>
+ <comment xml:lang="eo">DVI-dokumento de TeX</comment>
+ <comment xml:lang="en_GB">TeX DVI document</comment>
+ <comment xml:lang="el">Έγγραφο TeX DVI</comment>
+ <comment xml:lang="de">TeX-DVI-Dokument</comment>
+ <comment xml:lang="da">TeX DVI-dokument</comment>
+ <comment xml:lang="cs">dokument TeX DVI</comment>
+ <comment xml:lang="ca">document DVI de TeX</comment>
+ <comment xml:lang="bg">Документ — TeX DVI</comment>
+ <comment xml:lang="be@latin">Dakument TeX DVI</comment>
+ <comment xml:lang="be">дакумент TeX DVI</comment>
+ <comment xml:lang="ast">Documentu Tex DVI</comment>
+ <comment xml:lang="ar">مستند TeX DVI</comment>
+ <comment xml:lang="af">TeX DVI-dokument</comment>
<acronym>DVI</acronym>
<expanded-acronym>Device independent file format</expanded-acronym>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="0x02f7" type="little16" offset="0"/>
+ <magic>
+ <match type="little16" value="0x02f7" offset="0"/>
</magic>
<glob pattern="*.dvi"/>
</mime-type>
<mime-type type="application/x-e-theme">
<comment>Enlightenment theme</comment>
- <comment xml:lang="ar">سمة Enlightenment</comment>
- <comment xml:lang="az">Enlightenment örtüyü</comment>
- <comment xml:lang="be@latin">Matyŭ Enlightenment</comment>
- <comment xml:lang="bg">Тема — Enlightenment</comment>
- <comment xml:lang="ca">tema d'Enlightenment</comment>
- <comment xml:lang="cs">motiv Enlightenment</comment>
- <comment xml:lang="cy">Thema Enlightenment</comment>
- <comment xml:lang="da">Enlightenmenttema</comment>
- <comment xml:lang="de">Enlightenment-Thema</comment>
- <comment xml:lang="el">Θέμα Enlightenment</comment>
- <comment xml:lang="en_GB">Enlightenment theme</comment>
- <comment xml:lang="eo">etoso de Enlightenment</comment>
- <comment xml:lang="es">tema de Enlightenment</comment>
- <comment xml:lang="eu">Enlightenment gaia</comment>
- <comment xml:lang="fi">Enlightenment-teema</comment>
- <comment xml:lang="fo">Enlightenment tema</comment>
- <comment xml:lang="fr">thème Enlightenment</comment>
- <comment xml:lang="ga">téama Enlightenment</comment>
- <comment xml:lang="gl">tema de Enlightenment</comment>
- <comment xml:lang="he">ערכת נושא של Enlightenment</comment>
- <comment xml:lang="hr">Enlightenment tema</comment>
- <comment xml:lang="hu">Enlightenment-téma</comment>
- <comment xml:lang="ia">Thema de Enlightenment</comment>
- <comment xml:lang="id">Tema Enlightenment</comment>
- <comment xml:lang="it">Tema Enlightenment</comment>
- <comment xml:lang="ja">Enlightenment テーマ</comment>
- <comment xml:lang="ka">Enlightenment-ის თემა</comment>
- <comment xml:lang="kk">Enlightenment темасы</comment>
- <comment xml:lang="ko">인라이튼먼트 테마</comment>
- <comment xml:lang="lt">Enlightenment tema</comment>
- <comment xml:lang="lv">Enlightenment motīvs</comment>
- <comment xml:lang="ms">Tema Enlightenment</comment>
- <comment xml:lang="nb">Enlightenment tema</comment>
- <comment xml:lang="nl">Enlightenment-thema</comment>
- <comment xml:lang="nn">Enlightenment-tema</comment>
- <comment xml:lang="oc">tèma Enlightenment</comment>
- <comment xml:lang="pl">Motyw Enlightenment</comment>
- <comment xml:lang="pt">tema Enlightenment</comment>
- <comment xml:lang="pt_BR">Tema do Enlightenment</comment>
- <comment xml:lang="ro">Temă Enlightenment</comment>
- <comment xml:lang="ru">Тема Enlightenment</comment>
- <comment xml:lang="sk">Motív Enlightenment</comment>
- <comment xml:lang="sl">Datoteka teme Enlightenment</comment>
- <comment xml:lang="sq">Tema Enlightenment</comment>
- <comment xml:lang="sr">тема за Енлајтмент</comment>
- <comment xml:lang="sv">Enlightenment-tema</comment>
- <comment xml:lang="tr">Enlightenment teması</comment>
- <comment xml:lang="uk">тема Enlightenment</comment>
- <comment xml:lang="vi">Sắc thái Enlightenment</comment>
- <comment xml:lang="zh_CN">Enlightenment 主题</comment>
<comment xml:lang="zh_TW">Enlightenment 佈景主題</comment>
+ <comment xml:lang="zh_CN">Enlightenment 主题</comment>
+ <comment xml:lang="vi">Sắc thái Enlightenment</comment>
+ <comment xml:lang="uk">тема Enlightenment</comment>
+ <comment xml:lang="tr">Enlightenment teması</comment>
+ <comment xml:lang="sv">Enlightenment-tema</comment>
+ <comment xml:lang="sr">тема за Енлајтмент</comment>
+ <comment xml:lang="sq">temë Enlightenment</comment>
+ <comment xml:lang="sl">Datoteka teme Enlightenment</comment>
+ <comment xml:lang="si">බුද්ධත්වයේ තේමාව</comment>
+ <comment xml:lang="sk">Motív Enlightenment</comment>
+ <comment xml:lang="ru">Тема Enlightenment</comment>
+ <comment xml:lang="ro">Temă Enlightenment</comment>
+ <comment xml:lang="pt_BR">Tema do Enlightenment</comment>
+ <comment xml:lang="pt">tema Enlightenment</comment>
+ <comment xml:lang="pl">Motyw Enlightenment</comment>
+ <comment xml:lang="oc">tèma Enlightenment</comment>
+ <comment xml:lang="nn">Enlightenment-tema</comment>
+ <comment xml:lang="nl">Enlightenment-thema</comment>
+ <comment xml:lang="nb">Enlightenment tema</comment>
+ <comment xml:lang="ms">Tema Enlightenment</comment>
+ <comment xml:lang="lv">Enlightenment motīvs</comment>
+ <comment xml:lang="lt">Enlightenment tema</comment>
+ <comment xml:lang="ko">인라이튼먼트 테마</comment>
+ <comment xml:lang="kk">Enlightenment темасы</comment>
+ <comment xml:lang="ka">Enlightenment-ის თემა</comment>
+ <comment xml:lang="ja">Enlightenment テーマ</comment>
+ <comment xml:lang="it">Tema Enlightenment</comment>
+ <comment xml:lang="is">Enlightenment þema</comment>
+ <comment xml:lang="id">Tema Enlightenment</comment>
+ <comment xml:lang="ia">Thema de Enlightenment</comment>
+ <comment xml:lang="hu">Enlightenment-téma</comment>
+ <comment xml:lang="hr">Enlightenment tema</comment>
+ <comment xml:lang="he">ערכת נושא של Enlightenment</comment>
+ <comment xml:lang="gl">tema de Enlightenment</comment>
+ <comment xml:lang="ga">téama Enlightenment</comment>
+ <comment xml:lang="fur">teme di Enlightenment</comment>
+ <comment xml:lang="fr">thème Enlightenment</comment>
+ <comment xml:lang="fo">Enlightenment tema</comment>
+ <comment xml:lang="fi">Enlightenment-teema</comment>
+ <comment xml:lang="eu">Enlightenment gaia</comment>
+ <comment xml:lang="es">tema de Enlightenment</comment>
+ <comment xml:lang="eo">etoso de Enlightenment</comment>
+ <comment xml:lang="en_GB">Enlightenment theme</comment>
+ <comment xml:lang="el">Θέμα Enlightenment</comment>
+ <comment xml:lang="de">Enlightenment-Thema</comment>
+ <comment xml:lang="da">Enlightenmenttema</comment>
+ <comment xml:lang="cy">Thema Enlightenment</comment>
+ <comment xml:lang="cs">motiv Enlightenment</comment>
+ <comment xml:lang="ca">tema d'Enlightenment</comment>
+ <comment xml:lang="bg">Тема — Enlightenment</comment>
+ <comment xml:lang="be@latin">Matyŭ Enlightenment</comment>
+ <comment xml:lang="be">тэма Enlightenment</comment>
+ <comment xml:lang="az">Enlightenment örtüyü</comment>
+ <comment xml:lang="ar">سمة Enlightenment</comment>
+ <comment xml:lang="af">Enlightenment-tema</comment>
<glob pattern="*.etheme"/>
</mime-type>
<mime-type type="application/x-egon">
<comment>Egon Animator animation</comment>
- <comment xml:lang="ar">تحريكة محرك Egon</comment>
- <comment xml:lang="be@latin">Animacyja Egon Animator</comment>
- <comment xml:lang="bg">Анимация — Egon Animator</comment>
- <comment xml:lang="ca">animació d'Egon Animator</comment>
- <comment xml:lang="cs">animace Egon Animator</comment>
- <comment xml:lang="da">Egon Animator-animation</comment>
- <comment xml:lang="de">Egon-Animator-Animation</comment>
- <comment xml:lang="el">Κινούμενο σχέδιο Egon Animator</comment>
- <comment xml:lang="en_GB">Egon Animator animation</comment>
- <comment xml:lang="eo">animacio de Egon Animator</comment>
- <comment xml:lang="es">animación de Egon Animator</comment>
- <comment xml:lang="eu">Egon Animator-eko animazioa</comment>
- <comment xml:lang="fi">Egon Animator -animaatio</comment>
- <comment xml:lang="fo">Egon Animator teknimyndagerð</comment>
- <comment xml:lang="fr">animation Egon Animator</comment>
- <comment xml:lang="ga">beochan Egon Animator</comment>
- <comment xml:lang="gl">animación de Egon Animator</comment>
- <comment xml:lang="he">אנימצייה של Egon Animator</comment>
- <comment xml:lang="hr">Egon Animator animacija</comment>
- <comment xml:lang="hu">Egon Animator-animáció</comment>
- <comment xml:lang="ia">Imagine Egon Animator</comment>
- <comment xml:lang="id">Animasi Egon Animator</comment>
- <comment xml:lang="it">Animazione Egon Animator</comment>
- <comment xml:lang="ja">Egon Animator アニメーション</comment>
- <comment xml:lang="ka">Egon Animator-ის ანიმაცია</comment>
- <comment xml:lang="kk">Egon Animator анимациясы</comment>
- <comment xml:lang="ko">Egon 애니메이터 애니메이션</comment>
- <comment xml:lang="lt">Egon Animator animacija</comment>
- <comment xml:lang="lv">Egon Animator animācija</comment>
- <comment xml:lang="ms">Animasi Egon Animator</comment>
- <comment xml:lang="nb">Egon animator-animasjon</comment>
- <comment xml:lang="nl">Egon Animator-animatie</comment>
- <comment xml:lang="nn">Egon Animator-animasjon</comment>
- <comment xml:lang="oc">animacion Egon Animator</comment>
- <comment xml:lang="pl">Animacja Egon Animator</comment>
- <comment xml:lang="pt">animação Egon Animator</comment>
- <comment xml:lang="pt_BR">Animação do Egon Animator</comment>
- <comment xml:lang="ro">Animație Egon Animator</comment>
- <comment xml:lang="ru">Анимация Egon Animator</comment>
- <comment xml:lang="sk">Animácia Egon Animator</comment>
- <comment xml:lang="sl">Datoteka animacije Egon Animator</comment>
- <comment xml:lang="sq">Animim Egon Animator</comment>
- <comment xml:lang="sr">анимација Егон аниматора</comment>
- <comment xml:lang="sv">Egon Animator-animering</comment>
- <comment xml:lang="tr">Egon Animator canlandırması</comment>
- <comment xml:lang="uk">анімація Egon Animator</comment>
- <comment xml:lang="vi">Hoạt ảnh Egon Animator</comment>
- <comment xml:lang="zh_CN">Egon Animator 动画</comment>
<comment xml:lang="zh_TW">Egon Animator 動畫</comment>
+ <comment xml:lang="zh_CN">Egon Animator 动画</comment>
+ <comment xml:lang="vi">Hoạt ảnh Egon Animator</comment>
+ <comment xml:lang="uk">анімація Egon Animator</comment>
+ <comment xml:lang="tr">Egon Animator canlandırması</comment>
+ <comment xml:lang="sv">Egon Animator-animering</comment>
+ <comment xml:lang="sr">анимација Егон аниматора</comment>
+ <comment xml:lang="sq">animacion Egon Animator</comment>
+ <comment xml:lang="sl">Datoteka animacije Egon Animator</comment>
+ <comment xml:lang="si">Egon Animator සජීවිකරණය</comment>
+ <comment xml:lang="sk">Animácia Egon Animator</comment>
+ <comment xml:lang="ru">Анимация Egon Animator</comment>
+ <comment xml:lang="ro">Animație Egon Animator</comment>
+ <comment xml:lang="pt_BR">Animação do Egon Animator</comment>
+ <comment xml:lang="pt">animação Egon Animator</comment>
+ <comment xml:lang="pl">Animacja Egon Animator</comment>
+ <comment xml:lang="oc">animacion Egon Animator</comment>
+ <comment xml:lang="nn">Egon Animator-animasjon</comment>
+ <comment xml:lang="nl">Egon Animator-animatie</comment>
+ <comment xml:lang="nb">Egon animator-animasjon</comment>
+ <comment xml:lang="ms">Animasi Egon Animator</comment>
+ <comment xml:lang="lv">Egon Animator animācija</comment>
+ <comment xml:lang="lt">Egon Animator animacija</comment>
+ <comment xml:lang="ko">Egon 애니메이터 애니메이션</comment>
+ <comment xml:lang="kk">Egon Animator анимациясы</comment>
+ <comment xml:lang="ka">Egon Animator-ის ანიმაცია</comment>
+ <comment xml:lang="ja">Egon Animator アニメーション</comment>
+ <comment xml:lang="it">Animazione Egon Animator</comment>
+ <comment xml:lang="is">Egon Animator hreyfimynd</comment>
+ <comment xml:lang="id">Animasi Egon Animator</comment>
+ <comment xml:lang="ia">Imagine Egon Animator</comment>
+ <comment xml:lang="hu">Egon Animator-animáció</comment>
+ <comment xml:lang="hr">Egon Animator animacija</comment>
+ <comment xml:lang="he">אנימצייה של Egon Animator</comment>
+ <comment xml:lang="gl">animación de Egon Animator</comment>
+ <comment xml:lang="ga">beochan Egon Animator</comment>
+ <comment xml:lang="fur">animazion Egon Animator</comment>
+ <comment xml:lang="fr">animation Egon Animator</comment>
+ <comment xml:lang="fo">Egon Animator teknimyndagerð</comment>
+ <comment xml:lang="fi">Egon Animator -animaatio</comment>
+ <comment xml:lang="eu">Egon Animator-eko animazioa</comment>
+ <comment xml:lang="es">animación de Egon Animator</comment>
+ <comment xml:lang="eo">animacio de Egon Animator</comment>
+ <comment xml:lang="en_GB">Egon Animator animation</comment>
+ <comment xml:lang="el">Κινούμενο σχέδιο Egon Animator</comment>
+ <comment xml:lang="de">Egon-Animator-Animation</comment>
+ <comment xml:lang="da">Egon Animator-animation</comment>
+ <comment xml:lang="cs">animace Egon Animator</comment>
+ <comment xml:lang="ca">animació d'Egon Animator</comment>
+ <comment xml:lang="bg">Анимация — Egon Animator</comment>
+ <comment xml:lang="be@latin">Animacyja Egon Animator</comment>
+ <comment xml:lang="be">анімацыя Egon Animator</comment>
+ <comment xml:lang="ar">تحريكة محرك Egon</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.egon"/>
</mime-type>
<mime-type type="application/x-executable">
- <comment>executable</comment>
- <comment xml:lang="ar">تنفيذي</comment>
- <comment xml:lang="be@latin">vykonvalny fajł</comment>
- <comment xml:lang="bg">Изпълним файл</comment>
- <comment xml:lang="ca">executable</comment>
- <comment xml:lang="cs">spustitelný soubor</comment>
- <comment xml:lang="da">kørbar</comment>
- <comment xml:lang="de">Programm</comment>
- <comment xml:lang="el">Εκτελέσιμο</comment>
- <comment xml:lang="en_GB">executable</comment>
- <comment xml:lang="eo">plenumebla</comment>
- <comment xml:lang="es">ejecutable</comment>
- <comment xml:lang="eu">exekutagarria</comment>
- <comment xml:lang="fi">suoritettava ohjelma</comment>
- <comment xml:lang="fo">inningarfør</comment>
- <comment xml:lang="fr">exécutable</comment>
- <comment xml:lang="ga">comhad inrite</comment>
- <comment xml:lang="gl">executábel</comment>
- <comment xml:lang="he">קובץ הרצה</comment>
- <comment xml:lang="hr">Izvršna datoteka</comment>
- <comment xml:lang="hu">futtatható</comment>
- <comment xml:lang="ia">Executabile</comment>
- <comment xml:lang="id">dapat dieksekusi</comment>
- <comment xml:lang="it">Eseguibile</comment>
- <comment xml:lang="ja">実行ファイル</comment>
- <comment xml:lang="kk">орындалатын</comment>
- <comment xml:lang="ko">실행 파일</comment>
- <comment xml:lang="lt">vykdomasis failas</comment>
- <comment xml:lang="lv">izpildāmais</comment>
- <comment xml:lang="ms">Bolehlaksana</comment>
- <comment xml:lang="nb">kjørbar</comment>
- <comment xml:lang="nl">uitvoerbaar bestand</comment>
- <comment xml:lang="nn">køyrbar</comment>
- <comment xml:lang="oc">executable</comment>
- <comment xml:lang="pl">Program</comment>
- <comment xml:lang="pt">executável</comment>
- <comment xml:lang="pt_BR">Executável</comment>
- <comment xml:lang="ro">executabil</comment>
- <comment xml:lang="ru">Исполняемый</comment>
- <comment xml:lang="sk">Spustiteľný súbor</comment>
- <comment xml:lang="sl">izvedljiva datoteka</comment>
- <comment xml:lang="sq">I ekzekutueshëm</comment>
- <comment xml:lang="sr">извршна</comment>
- <comment xml:lang="sv">körbar fil</comment>
- <comment xml:lang="tr">çalıştırılabilir</comment>
+ <comment>Executable</comment>
<comment xml:lang="uk">виконуваний файл</comment>
- <comment xml:lang="vi">thực hiện được</comment>
- <comment xml:lang="zh_CN">可执行文件</comment>
- <comment xml:lang="zh_TW">可執行檔</comment>
+ <comment xml:lang="sv">Körbar fil</comment>
+ <comment xml:lang="ru">Исполняемый</comment>
+ <comment xml:lang="pt_BR">Executável</comment>
+ <comment xml:lang="pl">Program</comment>
+ <comment xml:lang="it">Eseguibile</comment>
+ <comment xml:lang="gl">Executábel</comment>
+ <comment xml:lang="eu">Exekutagarria</comment>
+ <comment xml:lang="es">ejecutable</comment>
+ <comment xml:lang="de">Ausführbare Datei</comment>
+ <comment xml:lang="be">выконвальны файл</comment>
<generic-icon name="application-x-executable"/>
<magic priority="40">
- <match value="\177ELF" type="string" offset="0">
- <match value="1" type="byte" offset="5">
- <match value="2" type="little16" offset="16"/>
- </match>
+ <match type="string" value="\177ELF" offset="0">
+ <match type="byte" value="1" offset="5"/>
</match>
- <match value="\177ELF" type="string" offset="0">
- <match value="2" type="byte" offset="5">
- <match value="2" type="big16" offset="16"/>
- </match>
+ <match type="string" value="\177ELF" offset="0">
+ <match type="byte" value="2" offset="5"/>
</match>
- <match value="MZ" type="string" offset="0"/>
- <match value="0x521c" type="little16" offset="0"/>
- <match value="0420" type="host16" offset="0"/>
- <match value="0421" type="host16" offset="0"/>
- <match value="0603" type="little16" offset="0"/>
+ <match type="string" value="MZ" offset="0"/>
+ <match type="little16" value="0x521c" offset="0"/>
+ <match type="host16" value="0420" offset="0"/>
+ <match type="host16" value="0421" offset="0"/>
+ <match type="little16" value="0603" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-fluid">
<comment>FLTK Fluid file</comment>
- <comment xml:lang="ar">ملف FLTK Fluid</comment>
- <comment xml:lang="be@latin">Fajł FLTK Fluid</comment>
- <comment xml:lang="bg">Интерфейс — FLTK Fluid</comment>
- <comment xml:lang="ca">fitxer FLTK Fluid</comment>
- <comment xml:lang="cs">soubor FLTK Fluid</comment>
- <comment xml:lang="da">FLTK Fluid-fil</comment>
- <comment xml:lang="de">FLTK-Fluid-Datei</comment>
- <comment xml:lang="el">Αρχείο FLTK Fluid</comment>
- <comment xml:lang="en_GB">FLTK Fluid file</comment>
- <comment xml:lang="es">archivo FLTK Fluid</comment>
- <comment xml:lang="eu">FLTK Fluid fitxategia</comment>
- <comment xml:lang="fi">FLTK Fluid -tiedosto</comment>
- <comment xml:lang="fo">FLTK Fluid fíla</comment>
- <comment xml:lang="fr">fichier Fluid FLTK</comment>
- <comment xml:lang="ga">comhad FLTK Fluid</comment>
- <comment xml:lang="gl">ficheiro FLTK Fluid</comment>
- <comment xml:lang="he">קובץ FLTK Fluid</comment>
- <comment xml:lang="hr">FLTK Fluid datoteka</comment>
- <comment xml:lang="hu">FLTK Fluid fájl</comment>
- <comment xml:lang="ia">File Fluid de FLTK</comment>
- <comment xml:lang="id">Berkas FLTK Fluid</comment>
- <comment xml:lang="it">File FLTK Fluid</comment>
- <comment xml:lang="ja">FLTK Fluid ファイル</comment>
- <comment xml:lang="ka">FLTK Fluid-ის ფაილი</comment>
- <comment xml:lang="kk">FLTK Fluid файлы</comment>
- <comment xml:lang="ko">FLTK Fluid 파일</comment>
- <comment xml:lang="lt">FLTK Fluid failas</comment>
- <comment xml:lang="lv">FLTK Fluid datne</comment>
- <comment xml:lang="nb">FLTK Fluid-fil</comment>
- <comment xml:lang="nl">FLTK FLUID-bestand</comment>
- <comment xml:lang="nn">FLTK Fluid-fil</comment>
- <comment xml:lang="oc">fichièr Fluid FLTK</comment>
- <comment xml:lang="pl">Plik Fluid FLTK</comment>
- <comment xml:lang="pt">ficheiro FLTK Fluid</comment>
- <comment xml:lang="pt_BR">Arquivo Fluid do FLTK</comment>
- <comment xml:lang="ro">Fișier FLTK Fluid</comment>
- <comment xml:lang="ru">Файл FLTK Fluid</comment>
- <comment xml:lang="sk">Súbor FLTK Fluid</comment>
- <comment xml:lang="sl">Datoteka FLTK Fluid</comment>
- <comment xml:lang="sq">File FLTK Fluid</comment>
- <comment xml:lang="sr">датотека ФЛТК Флуида</comment>
- <comment xml:lang="sv">FLTK Fluid-fil</comment>
- <comment xml:lang="tr">FLTK Fluid dosyası</comment>
- <comment xml:lang="uk">файл FLTK Fluid</comment>
- <comment xml:lang="vi">Tập tin Fluid FLTK</comment>
- <comment xml:lang="zh_CN">FLTK 流体文档</comment>
<comment xml:lang="zh_TW">FLTK Fluid 檔</comment>
+ <comment xml:lang="zh_CN">FLTK 流体文档</comment>
+ <comment xml:lang="vi">Tập tin Fluid FLTK</comment>
+ <comment xml:lang="uk">файл FLTK Fluid</comment>
+ <comment xml:lang="tr">FLTK Fluid dosyası</comment>
+ <comment xml:lang="sv">FLTK Fluid-fil</comment>
+ <comment xml:lang="sr">датотека ФЛТК Флуида</comment>
+ <comment xml:lang="sq">kartelë FLTK Fluid</comment>
+ <comment xml:lang="sl">Datoteka FLTK Fluid</comment>
+ <comment xml:lang="si">FLTK තරල ගොනුව</comment>
+ <comment xml:lang="sk">Súbor FLTK Fluid</comment>
+ <comment xml:lang="ru">Файл FLTK Fluid</comment>
+ <comment xml:lang="ro">Fișier FLTK Fluid</comment>
+ <comment xml:lang="pt_BR">Arquivo Fluid do FLTK</comment>
+ <comment xml:lang="pt">ficheiro FLTK Fluid</comment>
+ <comment xml:lang="pl">Plik Fluid FLTK</comment>
+ <comment xml:lang="oc">fichièr Fluid FLTK</comment>
+ <comment xml:lang="nn">FLTK Fluid-fil</comment>
+ <comment xml:lang="nl">FLTK FLUID-bestand</comment>
+ <comment xml:lang="nb">FLTK Fluid-fil</comment>
+ <comment xml:lang="lv">FLTK Fluid datne</comment>
+ <comment xml:lang="lt">FLTK Fluid failas</comment>
+ <comment xml:lang="ko">FLTK Fluid 파일</comment>
+ <comment xml:lang="kk">FLTK Fluid файлы</comment>
+ <comment xml:lang="ka">FLTK Fluid-ის ფაილი</comment>
+ <comment xml:lang="ja">FLTK Fluid ファイル</comment>
+ <comment xml:lang="it">File FLTK Fluid</comment>
+ <comment xml:lang="is">FLTK Fluid skrá</comment>
+ <comment xml:lang="id">Berkas FLTK Fluid</comment>
+ <comment xml:lang="ia">File Fluid de FLTK</comment>
+ <comment xml:lang="hu">FLTK Fluid fájl</comment>
+ <comment xml:lang="hr">FLTK Fluid datoteka</comment>
+ <comment xml:lang="he">קובץ FLTK Fluid</comment>
+ <comment xml:lang="gl">ficheiro FLTK Fluid</comment>
+ <comment xml:lang="ga">comhad FLTK Fluid</comment>
+ <comment xml:lang="fur">file FLTK Fluid</comment>
+ <comment xml:lang="fr">fichier Fluid FLTK</comment>
+ <comment xml:lang="fo">FLTK Fluid fíla</comment>
+ <comment xml:lang="fi">FLTK Fluid -tiedosto</comment>
+ <comment xml:lang="eu">FLTK Fluid fitxategia</comment>
+ <comment xml:lang="es">archivo FLTK Fluid</comment>
+ <comment xml:lang="en_GB">FLTK Fluid file</comment>
+ <comment xml:lang="el">Αρχείο FLTK Fluid</comment>
+ <comment xml:lang="de">FLTK-Fluid-Datei</comment>
+ <comment xml:lang="da">FLTK Fluid-fil</comment>
+ <comment xml:lang="cs">soubor FLTK Fluid</comment>
+ <comment xml:lang="ca">fitxer FLTK Fluid</comment>
+ <comment xml:lang="bg">Интерфейс — FLTK Fluid</comment>
+ <comment xml:lang="be@latin">Fajł FLTK Fluid</comment>
+ <comment xml:lang="be">файл FLTK Fluid</comment>
+ <comment xml:lang="ar">ملف FLTK Fluid</comment>
+ <comment xml:lang="af">FLTK Fluit-lêer</comment>
<acronym>FLTK</acronym>
<expanded-acronym>Fast Light Toolkit</expanded-acronym>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="# data file for the Fltk" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="# data file for the Fltk" offset="0"/>
</magic>
<glob pattern="*.fl"/>
</mime-type>
<mime-type type="font/woff">
<comment>WOFF font</comment>
- <comment xml:lang="ast">Fonte WOFF</comment>
- <comment xml:lang="ca">lletra WOFF</comment>
- <comment xml:lang="cs">font WOFF</comment>
- <comment xml:lang="da">WOFF-skrifttype</comment>
- <comment xml:lang="de">WOFF-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά WOFF</comment>
- <comment xml:lang="en_GB">WOFF font</comment>
- <comment xml:lang="es">tipo de letra WOFF</comment>
- <comment xml:lang="eu">WOFF letra-tipoa</comment>
- <comment xml:lang="fi">WOFF-fontti</comment>
- <comment xml:lang="fr">police WOFF</comment>
- <comment xml:lang="ga">cló WOFF</comment>
- <comment xml:lang="gl">Tipo de letra WOFF</comment>
- <comment xml:lang="he">גופן WOFF</comment>
- <comment xml:lang="hr">WOFF slovo</comment>
- <comment xml:lang="hu">WOFF-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras WOFF</comment>
- <comment xml:lang="id">Fonta WOFF</comment>
- <comment xml:lang="it">Carattere WOFF</comment>
- <comment xml:lang="ja">WOFF フォント</comment>
- <comment xml:lang="kk">WOFF қарібі</comment>
- <comment xml:lang="ko">WOFF 글꼴</comment>
- <comment xml:lang="lv">WOFF fonts</comment>
- <comment xml:lang="oc">poliça WOFF</comment>
- <comment xml:lang="pl">Czcionka WOFF</comment>
- <comment xml:lang="pt">letra WOFF</comment>
- <comment xml:lang="pt_BR">Fonte WOFF</comment>
- <comment xml:lang="ru">Шрифт WOFF</comment>
- <comment xml:lang="sk">Písmo WOFF</comment>
- <comment xml:lang="sl">Pisava WOFF</comment>
- <comment xml:lang="sr">ВОФФ слова</comment>
- <comment xml:lang="sv">WOFF-typsnitt</comment>
- <comment xml:lang="tr">WOFF yazı tipi</comment>
- <comment xml:lang="uk">шрифт WOFF</comment>
- <comment xml:lang="zh_CN">WOFF 字体</comment>
<comment xml:lang="zh_TW">WOFF 字型</comment>
+ <comment xml:lang="zh_CN">WOFF 字体</comment>
+ <comment xml:lang="uk">шрифт WOFF</comment>
+ <comment xml:lang="tr">WOFF yazı tipi</comment>
+ <comment xml:lang="sv">WOFF-typsnitt</comment>
+ <comment xml:lang="sr">ВОФФ слова</comment>
+ <comment xml:lang="sq">shkronja WOFF</comment>
+ <comment xml:lang="sl">Pisava WOFF</comment>
+ <comment xml:lang="si">WOFF අකුරු</comment>
+ <comment xml:lang="sk">Písmo WOFF</comment>
+ <comment xml:lang="ru">Шрифт WOFF</comment>
+ <comment xml:lang="pt_BR">Fonte WOFF</comment>
+ <comment xml:lang="pt">letra WOFF</comment>
+ <comment xml:lang="pl">Czcionka WOFF</comment>
+ <comment xml:lang="oc">poliça WOFF</comment>
+ <comment xml:lang="nl">WOFF-lettertype</comment>
+ <comment xml:lang="lv">WOFF fonts</comment>
+ <comment xml:lang="lt">WOFF šriftas</comment>
+ <comment xml:lang="ko">WOFF 글꼴</comment>
+ <comment xml:lang="kk">WOFF қарібі</comment>
+ <comment xml:lang="ja">WOFF フォント</comment>
+ <comment xml:lang="it">Carattere WOFF</comment>
+ <comment xml:lang="is">WOFF letur</comment>
+ <comment xml:lang="id">Fonta WOFF</comment>
+ <comment xml:lang="ia">Typo de litteras WOFF</comment>
+ <comment xml:lang="hu">WOFF-betűkészlet</comment>
+ <comment xml:lang="hr">WOFF font</comment>
+ <comment xml:lang="he">גופן WOFF</comment>
+ <comment xml:lang="gl">Tipo de letra WOFF</comment>
+ <comment xml:lang="ga">cló WOFF</comment>
+ <comment xml:lang="fur">caratar WOFF</comment>
+ <comment xml:lang="fr">police WOFF</comment>
+ <comment xml:lang="fi">WOFF-fontti</comment>
+ <comment xml:lang="eu">WOFF letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra WOFF</comment>
+ <comment xml:lang="en_GB">WOFF font</comment>
+ <comment xml:lang="el">Γραμματοσειρά WOFF</comment>
+ <comment xml:lang="de">WOFF-Schrift</comment>
+ <comment xml:lang="da">WOFF-skrifttype</comment>
+ <comment xml:lang="cs">font WOFF</comment>
+ <comment xml:lang="ca">lletra WOFF</comment>
+ <comment xml:lang="bg">Шрифт — WOFF</comment>
+ <comment xml:lang="be">шрыфт WOFF</comment>
+ <comment xml:lang="ast">Fonte WOFF</comment>
+ <comment xml:lang="ar">خط WOFF</comment>
+ <comment xml:lang="af">WOFF-skriftipe</comment>
<acronym>WOFF</acronym>
<expanded-acronym>Web Open Font Format</expanded-acronym>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="0x774f4646" type="big32" offset="0"/>
+ <magic>
+ <match type="big32" value="0x774f4646" offset="0"/>
</magic>
<glob pattern="*.woff"/>
<alias type="application/font-woff"/>
</mime-type>
- <mime-type type="font/woff">
+ <mime-type type="font/woff2">
<comment>WOFF2 font</comment>
- <comment xml:lang="ast">Fonte WOFF2</comment>
- <comment xml:lang="ca">lletra WOFF2</comment>
- <comment xml:lang="cs">font WOFF2</comment>
- <comment xml:lang="de">WOFF2-Schrift</comment>
- <comment xml:lang="en_GB">WOFF2 font</comment>
- <comment xml:lang="es">tipo de letra WOFF2</comment>
- <comment xml:lang="fi">WOFF2-fontti</comment>
- <comment xml:lang="hr">WOFF2 slovo</comment>
- <comment xml:lang="hu">WOFF2 betűkészlet</comment>
- <comment xml:lang="id">Fonta WOFF2</comment>
- <comment xml:lang="it">Carattere WOFF2</comment>
- <comment xml:lang="kk">WOFF2 қарібі</comment>
- <comment xml:lang="ko">WOFF2 글꼴</comment>
- <comment xml:lang="pl">Czcionka WOFF2</comment>
- <comment xml:lang="pt_BR">Fonte WOFF2</comment>
- <comment xml:lang="ru">Шрифт WOFF2</comment>
- <comment xml:lang="sk">Písmo WOFF2</comment>
- <comment xml:lang="sv">WOFF2-typsnitt</comment>
- <comment xml:lang="uk">шрифт WOFF2</comment>
- <comment xml:lang="zh_CN">WOFF2 字体</comment>
<comment xml:lang="zh_TW">WOFF2 字型</comment>
+ <comment xml:lang="zh_CN">WOFF2 字体</comment>
+ <comment xml:lang="uk">шрифт WOFF2</comment>
+ <comment xml:lang="tr">WOFF2 yazı tipi</comment>
+ <comment xml:lang="sv">WOFF2-typsnitt</comment>
+ <comment xml:lang="sq">shkronja WOFF2</comment>
+ <comment xml:lang="sl">Pisava WOFF2</comment>
+ <comment xml:lang="si">WOFF2 අකුරු</comment>
+ <comment xml:lang="sk">Písmo WOFF2</comment>
+ <comment xml:lang="ru">Шрифт WOFF2</comment>
+ <comment xml:lang="pt_BR">Fonte WOFF2</comment>
+ <comment xml:lang="pt">letra WOFF2</comment>
+ <comment xml:lang="pl">Czcionka WOFF2</comment>
+ <comment xml:lang="oc">poliça WOFF2</comment>
+ <comment xml:lang="nl">WOFF2-lettertype</comment>
+ <comment xml:lang="lt">WOFF2 šriftas</comment>
+ <comment xml:lang="ko">WOFF2 글꼴</comment>
+ <comment xml:lang="kk">WOFF2 қарібі</comment>
+ <comment xml:lang="ja">WOFF2 フォント</comment>
+ <comment xml:lang="it">Carattere WOFF2</comment>
+ <comment xml:lang="is">WOFF2 letur</comment>
+ <comment xml:lang="id">Fonta WOFF2</comment>
+ <comment xml:lang="hu">WOFF2 betűkészlet</comment>
+ <comment xml:lang="hr">WOFF2 font</comment>
+ <comment xml:lang="he">גופן WOFF2</comment>
+ <comment xml:lang="gl">Tipo de letra WOFF2</comment>
+ <comment xml:lang="ga">cló WOFF2</comment>
+ <comment xml:lang="fur">caratar WOFF2</comment>
+ <comment xml:lang="fr">police WOFF2</comment>
+ <comment xml:lang="fi">WOFF2-fontti</comment>
+ <comment xml:lang="eu">WOFF2 letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra WOFF2</comment>
+ <comment xml:lang="en_GB">WOFF2 font</comment>
+ <comment xml:lang="de">WOFF2-Schrift</comment>
+ <comment xml:lang="da">WOFF2-skrifttype</comment>
+ <comment xml:lang="cs">font WOFF2</comment>
+ <comment xml:lang="ca">lletra WOFF2</comment>
+ <comment xml:lang="bg">Шрифт — WOFF2</comment>
+ <comment xml:lang="be">шрыфт WOFF 2</comment>
+ <comment xml:lang="ast">Fonte WOFF2</comment>
+ <comment xml:lang="ar">خط WOFF2</comment>
+ <comment xml:lang="af">WOFF2-skriftipe</comment>
<acronym>WOFF2</acronym>
<expanded-acronym>Web Open Font Format 2.0</expanded-acronym>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="0x774f4632" type="big32" offset="0"/>
+ <magic>
+ <match type="big32" value="0x774f4632" offset="0"/>
</magic>
<glob pattern="*.woff2"/>
</mime-type>
<mime-type type="application/x-font-type1">
<comment>PostScript type-1 font</comment>
- <comment xml:lang="ca">lletra type-1 de PostScript</comment>
- <comment xml:lang="cs">font PostScript type-1</comment>
- <comment xml:lang="de">PostScript-Typ-1-Schrift</comment>
- <comment xml:lang="en_GB">PostScript type-1 font</comment>
- <comment xml:lang="es">tipo de letra PostScript Type-1</comment>
- <comment xml:lang="eu">PostScript type-1 letra-tipoa</comment>
- <comment xml:lang="fr">police PostScript Type 1</comment>
- <comment xml:lang="ga">cló PostScript type-1</comment>
- <comment xml:lang="hr">PostScript type-1 slovo</comment>
- <comment xml:lang="hu">PostScript type-1 betűkészlet</comment>
- <comment xml:lang="id">fonta PostScript type-1</comment>
- <comment xml:lang="it">Carattere PostScript type-1</comment>
- <comment xml:lang="kk">PostScript type-1 қарібі</comment>
- <comment xml:lang="ko">PostScript Type-1 글꼴</comment>
- <comment xml:lang="pl">Czcionka PostScript Type-1</comment>
- <comment xml:lang="pt_BR">Fonte PostScript tipo-1</comment>
- <comment xml:lang="ru">Шрифт PostScript Type-1</comment>
- <comment xml:lang="sk">Písmo PostScript typu 1</comment>
- <comment xml:lang="sr">слова Постскрипта врсте-1</comment>
- <comment xml:lang="sv">PostScript type-1-typsnitt</comment>
- <comment xml:lang="tr">PostScript tip-1 yazı tipi</comment>
- <comment xml:lang="uk">шрифт type-1 PostScript</comment>
- <comment xml:lang="zh_CN">PostScript type-1 字体</comment>
<comment xml:lang="zh_TW">PostScript type-1 字型</comment>
+ <comment xml:lang="zh_CN">PostScript type-1 字体</comment>
+ <comment xml:lang="uk">шрифт type-1 PostScript</comment>
+ <comment xml:lang="tr">PostScript tip-1 yazı tipi</comment>
+ <comment xml:lang="sv">PostScript type-1-typsnitt</comment>
+ <comment xml:lang="sr">слова Постскрипта врсте-1</comment>
+ <comment xml:lang="sq">shkronja PostScript type-1</comment>
+ <comment xml:lang="sl">Datoteka pisave PostScript vrsta-1</comment>
+ <comment xml:lang="si">PostScript වර්ගය-1 අකුරු</comment>
+ <comment xml:lang="sk">Písmo PostScript typu 1</comment>
+ <comment xml:lang="ru">Шрифт PostScript Type-1</comment>
+ <comment xml:lang="pt_BR">Fonte PostScript tipo-1</comment>
+ <comment xml:lang="pt">letra PostScript Tipo 1</comment>
+ <comment xml:lang="pl">Czcionka PostScript Type-1</comment>
+ <comment xml:lang="nl">PostScript type-1-lettertype</comment>
+ <comment xml:lang="ko">PostScript Type-1 글꼴</comment>
+ <comment xml:lang="kk">PostScript type-1 қарібі</comment>
+ <comment xml:lang="ja">PostScript type-1 フォント</comment>
+ <comment xml:lang="it">Carattere PostScript type-1</comment>
+ <comment xml:lang="is">PostScript type-1 letur</comment>
+ <comment xml:lang="id">Fonta PostScript type-1</comment>
+ <comment xml:lang="hu">PostScript type-1 betűkészlet</comment>
+ <comment xml:lang="hr">PostScript type-1 font</comment>
+ <comment xml:lang="he">גופן PostScript type-1</comment>
+ <comment xml:lang="gl">Tipo de letra PostScript tipo 1</comment>
+ <comment xml:lang="ga">cló PostScript type-1</comment>
+ <comment xml:lang="fur">caratar PostScript type-1</comment>
+ <comment xml:lang="fr">police PostScript Type 1</comment>
+ <comment xml:lang="fi">PostScript type-1 -fontti</comment>
+ <comment xml:lang="eu">PostScript type-1 letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra PostScript Type-1</comment>
+ <comment xml:lang="en_GB">PostScript type-1 font</comment>
+ <comment xml:lang="de">PostScript-Typ-1-Schrift</comment>
+ <comment xml:lang="da">PostScript type-1-skrifttype</comment>
+ <comment xml:lang="cs">font PostScript type-1</comment>
+ <comment xml:lang="ca">lletra type-1 de PostScript</comment>
+ <comment xml:lang="bg">Шрифт — PostScript type-1</comment>
+ <comment xml:lang="be">шрыфт PostScript type-1</comment>
+ <comment xml:lang="ar">خط بوستسكربت النوع ١</comment>
+ <comment xml:lang="af">PostScript tipe 1-skriftipe</comment>
<sub-class-of type="application/postscript"/>
<generic-icon name="font-x-generic"/>
<magic priority="60">
- <match value="LWFN" type="string" offset="0"/>
- <match value="LWFN" type="string" offset="65"/>
- <match value="%!PS-AdobeFont-1." type="string" offset="0"/>
- <match value="%!PS-AdobeFont-1." type="string" offset="6"/>
- <match value="%!FontType1-1." type="string" offset="0"/>
- <match value="%!FontType1-1." type="string" offset="6"/>
+ <match type="string" value="LWFN" offset="0"/>
+ <match type="string" value="LWFN" offset="65"/>
+ <match type="string" value="%!PS-AdobeFont-1." offset="0"/>
+ <match type="string" value="%!PS-AdobeFont-1." offset="6"/>
+ <match type="string" value="%!FontType1-1." offset="0"/>
+ <match type="string" value="%!FontType1-1." offset="6"/>
</magic>
<glob pattern="*.pfa"/>
<glob pattern="*.pfb"/>
@@ -10757,454 +11536,500 @@
</mime-type>
<mime-type type="application/x-font-afm">
<comment>Adobe font metrics</comment>
- <comment xml:lang="ar">مقاييس خط أدوبي</comment>
- <comment xml:lang="az">Adobe yazı növü metrikləri</comment>
- <comment xml:lang="be@latin">Metryka šryftu Adobe</comment>
- <comment xml:lang="bg">Шрифтова метрика — Adobe</comment>
- <comment xml:lang="ca">mètrica de lletra d'Adobe</comment>
- <comment xml:lang="cs">metrika fontu Adobe</comment>
- <comment xml:lang="cy">Metrigau Ffont Adobe</comment>
- <comment xml:lang="da">Adobe skrifttypefil</comment>
- <comment xml:lang="de">Adobe-Schriftmetriken</comment>
- <comment xml:lang="el">Μετρικά γραμματοσειράς Adobe</comment>
- <comment xml:lang="en_GB">Adobe font metrics</comment>
- <comment xml:lang="eo">metrikoj de Adobe-tiparo</comment>
- <comment xml:lang="es">métricas tipográficas de Adobe</comment>
- <comment xml:lang="eu">Adobe letra-tipoen neurriak</comment>
- <comment xml:lang="fi">Adobe-fonttimitat</comment>
- <comment xml:lang="fr">métriques de police Adobe</comment>
- <comment xml:lang="ga">meadarachtaí cló Adobe</comment>
- <comment xml:lang="gl">métricas de fonte de Adobe</comment>
- <comment xml:lang="he">מדדי גופן של Adobe</comment>
- <comment xml:lang="hr">Adobe mjere slova</comment>
- <comment xml:lang="hu">Adobe-betűmetrika</comment>
- <comment xml:lang="ia">Metricas de typo de litteras Adobe</comment>
- <comment xml:lang="id">Metrik fonta Adobe</comment>
- <comment xml:lang="it">Metriche tipo carattere Adobe</comment>
- <comment xml:lang="ja">Adobe フォントメトリック</comment>
- <comment xml:lang="kk">Adobe қаріп метрикалары</comment>
- <comment xml:lang="ko">Adobe 글꼴 메트릭</comment>
- <comment xml:lang="lt">Adobe šriftų metrika</comment>
- <comment xml:lang="lv">Adobe fonta metrika</comment>
- <comment xml:lang="ms">Metrik font Adobe</comment>
- <comment xml:lang="nb">Adobe skrifttypefil</comment>
- <comment xml:lang="nl">Adobe-lettertype-metrieken</comment>
- <comment xml:lang="nn">Adobe skrifttypemetrikk</comment>
- <comment xml:lang="oc">metricas de poliça Adobe</comment>
- <comment xml:lang="pl">Metryka czcionki Adobe</comment>
- <comment xml:lang="pt">métrica de letras Adobe</comment>
- <comment xml:lang="pt_BR">Métricas de fonte Adobe</comment>
- <comment xml:lang="ro">Dimensiuni font Adobe</comment>
- <comment xml:lang="ru">Метрика шрифта Adobe</comment>
- <comment xml:lang="sk">Metrika písma Adobe</comment>
- <comment xml:lang="sl">Matrika pisave Adobe</comment>
- <comment xml:lang="sq">Metrik lloj gërmash Adobe</comment>
- <comment xml:lang="sr">метрика Адобе слова</comment>
- <comment xml:lang="sv">Adobe-typsnittsmetrik</comment>
- <comment xml:lang="tr">Adobe yazıtipi ölçüleri</comment>
- <comment xml:lang="uk">метрики шрифту Adobe</comment>
- <comment xml:lang="vi">Cách đo phông chữ Adobe</comment>
- <comment xml:lang="zh_CN">Adobe 字体规格</comment>
<comment xml:lang="zh_TW">Adobe 字型描述檔</comment>
+ <comment xml:lang="zh_CN">Adobe 字体规格</comment>
+ <comment xml:lang="vi">Cách đo phông chữ Adobe</comment>
+ <comment xml:lang="uk">метрики шрифту Adobe</comment>
+ <comment xml:lang="tr">Adobe yazı tipi ölçüleri</comment>
+ <comment xml:lang="sv">Adobe-typsnittsmetrik</comment>
+ <comment xml:lang="sr">метрика Адобе слова</comment>
+ <comment xml:lang="sq">vlera shkronjash Adobe</comment>
+ <comment xml:lang="sl">Matrika pisave Adobe</comment>
+ <comment xml:lang="si">Adobe අකුරු මිතික</comment>
+ <comment xml:lang="sk">Metrika písma Adobe</comment>
+ <comment xml:lang="ru">Метрика шрифта Adobe</comment>
+ <comment xml:lang="ro">Dimensiuni font Adobe</comment>
+ <comment xml:lang="pt_BR">Métricas de fonte Adobe</comment>
+ <comment xml:lang="pt">métrica de letras Adobe</comment>
+ <comment xml:lang="pl">Metryka czcionki Adobe</comment>
+ <comment xml:lang="oc">metricas de poliça Adobe</comment>
+ <comment xml:lang="nn">Adobe skrifttypemetrikk</comment>
+ <comment xml:lang="nl">Adobe lettertype-metrieken</comment>
+ <comment xml:lang="nb">Adobe skrifttypefil</comment>
+ <comment xml:lang="ms">Metrik font Adobe</comment>
+ <comment xml:lang="lv">Adobe fonta metrika</comment>
+ <comment xml:lang="lt">Adobe šriftų metrika</comment>
+ <comment xml:lang="ko">Adobe 글꼴 메트릭</comment>
+ <comment xml:lang="kk">Adobe қаріп метрикалары</comment>
+ <comment xml:lang="ja">Adobe フォントメトリック</comment>
+ <comment xml:lang="it">Metriche tipo carattere Adobe</comment>
+ <comment xml:lang="is">Adobe leturupplýsingar</comment>
+ <comment xml:lang="id">Metrik fonta Adobe</comment>
+ <comment xml:lang="ia">Metricas de typo de litteras Adobe</comment>
+ <comment xml:lang="hu">Adobe-betűmetrika</comment>
+ <comment xml:lang="hr">Metrika Adobe fonta</comment>
+ <comment xml:lang="he">מדדי גופן של Adobe</comment>
+ <comment xml:lang="gl">métricas de fonte de Adobe</comment>
+ <comment xml:lang="ga">meadarachtaí cló Adobe</comment>
+ <comment xml:lang="fur">metrichis caratar Adobe</comment>
+ <comment xml:lang="fr">métriques de police Adobe</comment>
+ <comment xml:lang="fi">Adobe-fonttimitat</comment>
+ <comment xml:lang="eu">Adobe letra-tipoen neurriak</comment>
+ <comment xml:lang="es">métricas tipográficas de Adobe</comment>
+ <comment xml:lang="eo">metrikoj de Adobe-tiparo</comment>
+ <comment xml:lang="en_GB">Adobe font metrics</comment>
+ <comment xml:lang="el">Μετρικά γραμματοσειράς Adobe</comment>
+ <comment xml:lang="de">Adobe-Schriftmetriken</comment>
+ <comment xml:lang="da">Adobe skrifttypefil</comment>
+ <comment xml:lang="cy">Metrigau Ffont Adobe</comment>
+ <comment xml:lang="cs">metrika fontu Adobe</comment>
+ <comment xml:lang="ca">mètrica de lletra d'Adobe</comment>
+ <comment xml:lang="bg">Шрифтова метрика — Adobe</comment>
+ <comment xml:lang="be@latin">Metryka šryftu Adobe</comment>
+ <comment xml:lang="be">метрыкі шрыфту Adobe</comment>
+ <comment xml:lang="az">Adobe yazı növü metrikləri</comment>
+ <comment xml:lang="ar">مقاييس خط أدوبي</comment>
+ <comment xml:lang="af">Adobe skriftipe-afmetings</comment>
<generic-icon name="font-x-generic"/>
<glob pattern="*.afm"/>
</mime-type>
<mime-type type="application/x-font-bdf">
<comment>BDF font</comment>
- <comment xml:lang="ar">خط BDF</comment>
- <comment xml:lang="az">BDF yazı növü</comment>
- <comment xml:lang="be@latin">Šryft BDF</comment>
- <comment xml:lang="bg">Шрифт — BDF</comment>
- <comment xml:lang="ca">lletra BDF</comment>
- <comment xml:lang="cs">font BDF</comment>
- <comment xml:lang="cy">Ffont BDF</comment>
- <comment xml:lang="da">BDF-skrifttype</comment>
- <comment xml:lang="de">BDF-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά BDF</comment>
- <comment xml:lang="en_GB">BDF font</comment>
- <comment xml:lang="eo">BDF-tiparo</comment>
- <comment xml:lang="es">tipo de letra BDF</comment>
- <comment xml:lang="eu">BDF letra-tipoa</comment>
- <comment xml:lang="fi">BDF-fontti</comment>
- <comment xml:lang="fo">BDF stavasnið</comment>
- <comment xml:lang="fr">police BDF</comment>
- <comment xml:lang="ga">cló BDF</comment>
- <comment xml:lang="gl">tipo de fonte BDF</comment>
- <comment xml:lang="he">גופן BDF</comment>
- <comment xml:lang="hr">BDF slovo</comment>
- <comment xml:lang="hu">BDF-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras BDF</comment>
- <comment xml:lang="id">Fonta BDF</comment>
- <comment xml:lang="it">Carattere BDF</comment>
- <comment xml:lang="ja">BDF フォント</comment>
- <comment xml:lang="kk">BDF қарібі</comment>
- <comment xml:lang="ko">BDF 글꼴</comment>
- <comment xml:lang="lt">BDF šriftas</comment>
- <comment xml:lang="lv">BDF fonts</comment>
- <comment xml:lang="ms">Font BDF</comment>
- <comment xml:lang="nb">BDF-skrifttype</comment>
- <comment xml:lang="nl">BDF-lettertype</comment>
- <comment xml:lang="nn">BDF-skrifttype</comment>
- <comment xml:lang="oc">poliça BDF</comment>
- <comment xml:lang="pl">Czcionka BDF</comment>
- <comment xml:lang="pt">letra BDF</comment>
- <comment xml:lang="pt_BR">Fonte BDF</comment>
- <comment xml:lang="ro">Font BDF</comment>
- <comment xml:lang="ru">Шрифт BDF</comment>
- <comment xml:lang="sk">Písmo BDF</comment>
- <comment xml:lang="sl">Datoteka pisave BDF</comment>
- <comment xml:lang="sq">Lloj gërme BDF</comment>
- <comment xml:lang="sr">БДФ слова</comment>
- <comment xml:lang="sv">BDF-typsnitt</comment>
- <comment xml:lang="tr">BDF fontu</comment>
- <comment xml:lang="uk">шрифт BDF</comment>
- <comment xml:lang="vi">Phông chữ BDF</comment>
- <comment xml:lang="zh_CN">BDF 字体</comment>
<comment xml:lang="zh_TW">BDF 字型</comment>
+ <comment xml:lang="zh_CN">BDF 字体</comment>
+ <comment xml:lang="vi">Phông chữ BDF</comment>
+ <comment xml:lang="uk">шрифт BDF</comment>
+ <comment xml:lang="tr">BDF yazı tipi</comment>
+ <comment xml:lang="sv">BDF-typsnitt</comment>
+ <comment xml:lang="sr">БДФ слова</comment>
+ <comment xml:lang="sq">shkronja BDF</comment>
+ <comment xml:lang="sl">Datoteka pisave BDF</comment>
+ <comment xml:lang="si">BDF අකුරු</comment>
+ <comment xml:lang="sk">Písmo BDF</comment>
+ <comment xml:lang="ru">Шрифт BDF</comment>
+ <comment xml:lang="ro">Font BDF</comment>
+ <comment xml:lang="pt_BR">Fonte BDF</comment>
+ <comment xml:lang="pt">letra BDF</comment>
+ <comment xml:lang="pl">Czcionka BDF</comment>
+ <comment xml:lang="oc">poliça BDF</comment>
+ <comment xml:lang="nn">BDF-skrifttype</comment>
+ <comment xml:lang="nl">BDF-lettertype</comment>
+ <comment xml:lang="nb">BDF-skrifttype</comment>
+ <comment xml:lang="ms">Font BDF</comment>
+ <comment xml:lang="lv">BDF fonts</comment>
+ <comment xml:lang="lt">BDF šriftas</comment>
+ <comment xml:lang="ko">BDF 글꼴</comment>
+ <comment xml:lang="kk">BDF қарібі</comment>
+ <comment xml:lang="ja">BDF フォント</comment>
+ <comment xml:lang="it">Carattere BDF</comment>
+ <comment xml:lang="is">BDF letur</comment>
+ <comment xml:lang="id">Fonta BDF</comment>
+ <comment xml:lang="ia">Typo de litteras BDF</comment>
+ <comment xml:lang="hu">BDF-betűkészlet</comment>
+ <comment xml:lang="hr">BDF font</comment>
+ <comment xml:lang="he">גופן BDF</comment>
+ <comment xml:lang="gl">tipo de fonte BDF</comment>
+ <comment xml:lang="ga">cló BDF</comment>
+ <comment xml:lang="fur">caratar BDF</comment>
+ <comment xml:lang="fr">police BDF</comment>
+ <comment xml:lang="fo">BDF stavasnið</comment>
+ <comment xml:lang="fi">BDF-fontti</comment>
+ <comment xml:lang="eu">BDF letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra BDF</comment>
+ <comment xml:lang="eo">BDF-tiparo</comment>
+ <comment xml:lang="en_GB">BDF font</comment>
+ <comment xml:lang="el">Γραμματοσειρά BDF</comment>
+ <comment xml:lang="de">BDF-Schrift</comment>
+ <comment xml:lang="da">BDF-skrifttype</comment>
+ <comment xml:lang="cy">Ffont BDF</comment>
+ <comment xml:lang="cs">font BDF</comment>
+ <comment xml:lang="ca">lletra BDF</comment>
+ <comment xml:lang="bg">Шрифт — BDF</comment>
+ <comment xml:lang="be@latin">Šryft BDF</comment>
+ <comment xml:lang="be">шрыфт BDF</comment>
+ <comment xml:lang="az">BDF yazı növü</comment>
+ <comment xml:lang="ar">خط BDF</comment>
+ <comment xml:lang="af">BDF-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="STARTFONT\040" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="STARTFONT\040" offset="0"/>
</magic>
<glob pattern="*.bdf"/>
</mime-type>
<mime-type type="application/x-font-dos">
<comment>DOS font</comment>
- <comment xml:lang="ar">خط DOS</comment>
- <comment xml:lang="az">DOS yazı növü</comment>
- <comment xml:lang="be@latin">Šryft DOS</comment>
- <comment xml:lang="bg">Шрифт — DOS</comment>
- <comment xml:lang="ca">lletra DOS</comment>
- <comment xml:lang="cs">font pro DOS</comment>
- <comment xml:lang="cy">Ffont DOS</comment>
- <comment xml:lang="da">DOS-skrifttype</comment>
- <comment xml:lang="de">DOS-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά DOS</comment>
- <comment xml:lang="en_GB">DOS font</comment>
- <comment xml:lang="eo">DOS-tiparo</comment>
- <comment xml:lang="es">tipo de letra de DOS</comment>
- <comment xml:lang="eu">DOS letra-tipoa</comment>
- <comment xml:lang="fi">DOS-fontti</comment>
- <comment xml:lang="fo">DOS stavasnið</comment>
- <comment xml:lang="fr">police DOS</comment>
- <comment xml:lang="ga">cló DOS</comment>
- <comment xml:lang="gl">tipo de fonte de DOS</comment>
- <comment xml:lang="he">גופן DOS</comment>
- <comment xml:lang="hr">DOS slovo</comment>
- <comment xml:lang="hu">DOS-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras DOS</comment>
- <comment xml:lang="id">Fonta DOS</comment>
- <comment xml:lang="it">Carattere DOS</comment>
- <comment xml:lang="ja">DOS フォント</comment>
- <comment xml:lang="kk">DOS қарібі</comment>
- <comment xml:lang="ko">DOS 글꼴</comment>
- <comment xml:lang="lt">DOS šriftas</comment>
- <comment xml:lang="lv">DOS fonts</comment>
- <comment xml:lang="ms">Font DOS</comment>
- <comment xml:lang="nb">DOS-skrifttype</comment>
- <comment xml:lang="nl">DOS-lettertype</comment>
- <comment xml:lang="nn">DOS-skrifttype</comment>
- <comment xml:lang="oc">poliça DOS</comment>
- <comment xml:lang="pl">Czcionka DOS</comment>
- <comment xml:lang="pt">letra DOS</comment>
- <comment xml:lang="pt_BR">Fonte do DOS</comment>
- <comment xml:lang="ro">Font DOS</comment>
- <comment xml:lang="ru">Шрифт DOS</comment>
- <comment xml:lang="sk">Písmo pre DOS</comment>
- <comment xml:lang="sl">Datoteka pisave DOS</comment>
- <comment xml:lang="sq">Gërmë DOS</comment>
- <comment xml:lang="sr">ДОС слова</comment>
- <comment xml:lang="sv">DOS-typsnitt</comment>
- <comment xml:lang="tr">DOS fontu</comment>
- <comment xml:lang="uk">шрифт DOS</comment>
- <comment xml:lang="vi">Phông chữ DOS</comment>
- <comment xml:lang="zh_CN">DOS 字体</comment>
<comment xml:lang="zh_TW">DOS 字型</comment>
+ <comment xml:lang="zh_CN">DOS 字体</comment>
+ <comment xml:lang="vi">Phông chữ DOS</comment>
+ <comment xml:lang="uk">шрифт DOS</comment>
+ <comment xml:lang="tr">DOS yazı tipi</comment>
+ <comment xml:lang="sv">DOS-typsnitt</comment>
+ <comment xml:lang="sr">ДОС слова</comment>
+ <comment xml:lang="sq">shkronja DOS</comment>
+ <comment xml:lang="sl">Datoteka pisave DOS</comment>
+ <comment xml:lang="si">DOS අකුරු</comment>
+ <comment xml:lang="sk">Písmo pre DOS</comment>
+ <comment xml:lang="ru">Шрифт DOS</comment>
+ <comment xml:lang="ro">Font DOS</comment>
+ <comment xml:lang="pt_BR">Fonte do DOS</comment>
+ <comment xml:lang="pt">letra DOS</comment>
+ <comment xml:lang="pl">Czcionka DOS</comment>
+ <comment xml:lang="oc">poliça DOS</comment>
+ <comment xml:lang="nn">DOS-skrifttype</comment>
+ <comment xml:lang="nl">DOS-lettertype</comment>
+ <comment xml:lang="nb">DOS-skrifttype</comment>
+ <comment xml:lang="ms">Font DOS</comment>
+ <comment xml:lang="lv">DOS fonts</comment>
+ <comment xml:lang="lt">DOS šriftas</comment>
+ <comment xml:lang="ko">DOS 글꼴</comment>
+ <comment xml:lang="kk">DOS қарібі</comment>
+ <comment xml:lang="ja">DOS フォント</comment>
+ <comment xml:lang="it">Carattere DOS</comment>
+ <comment xml:lang="is">DOS letur</comment>
+ <comment xml:lang="id">Fonta DOS</comment>
+ <comment xml:lang="ia">Typo de litteras DOS</comment>
+ <comment xml:lang="hu">DOS-betűkészlet</comment>
+ <comment xml:lang="hr">DOS font</comment>
+ <comment xml:lang="he">גופן DOS</comment>
+ <comment xml:lang="gl">tipo de fonte de DOS</comment>
+ <comment xml:lang="ga">cló DOS</comment>
+ <comment xml:lang="fur">caratar DOS</comment>
+ <comment xml:lang="fr">police DOS</comment>
+ <comment xml:lang="fo">DOS stavasnið</comment>
+ <comment xml:lang="fi">DOS-fontti</comment>
+ <comment xml:lang="eu">DOS letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra de DOS</comment>
+ <comment xml:lang="eo">DOS-tiparo</comment>
+ <comment xml:lang="en_GB">DOS font</comment>
+ <comment xml:lang="el">Γραμματοσειρά DOS</comment>
+ <comment xml:lang="de">DOS-Schrift</comment>
+ <comment xml:lang="da">DOS-skrifttype</comment>
+ <comment xml:lang="cy">Ffont DOS</comment>
+ <comment xml:lang="cs">font pro DOS</comment>
+ <comment xml:lang="ca">lletra DOS</comment>
+ <comment xml:lang="bg">Шрифт — DOS</comment>
+ <comment xml:lang="be@latin">Šryft DOS</comment>
+ <comment xml:lang="be">шрыфт DOS</comment>
+ <comment xml:lang="az">DOS yazı növü</comment>
+ <comment xml:lang="ar">خط DOS</comment>
+ <comment xml:lang="af">DOS-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="\xff\x46\x4f\x4e" type="string" offset="0"/>
- <match value="\x00\x45\x47\x41" type="string" offset="7"/>
- <match value="\x00\x56\x49\x44" type="string" offset="7"/>
+ <magic>
+ <match type="string" value="\xff\x46\x4f\x4e" offset="0"/>
+ <match type="string" value="\x00\x45\x47\x41" offset="7"/>
+ <match type="string" value="\x00\x56\x49\x44" offset="7"/>
</magic>
</mime-type>
<mime-type type="application/x-font-framemaker">
<comment>Adobe FrameMaker font</comment>
- <comment xml:lang="ar">خط أدوبي الصانع للإطارات</comment>
- <comment xml:lang="az">Adobe FrameMaker yazı növü</comment>
- <comment xml:lang="be@latin">Šryft Adobe FrameMaker</comment>
- <comment xml:lang="bg">Шрифт — Adobe FrameMaker</comment>
- <comment xml:lang="ca">lletra d'Adobe FrameMaker</comment>
- <comment xml:lang="cs">font Adobe FrameMaker</comment>
- <comment xml:lang="cy">Ffont Adobe FrameMaker</comment>
- <comment xml:lang="da">Adobe FrameMaker-skrifttype</comment>
- <comment xml:lang="de">Adobe-FrameMaker-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά Adobe FrameMaker</comment>
- <comment xml:lang="en_GB">Adobe FrameMaker font</comment>
- <comment xml:lang="eo">Tiparo de Adobe FrameMaker</comment>
- <comment xml:lang="es">tipo de letra de Adobe FrameMaker</comment>
- <comment xml:lang="eu">Adobe FrameMaker-en letra-tipoa</comment>
- <comment xml:lang="fi">Adobe FrameMaker -fontti</comment>
- <comment xml:lang="fo">Adobe FrameMaker stavasnið</comment>
- <comment xml:lang="fr">police Adobe FrameMaker</comment>
- <comment xml:lang="ga">cló Adobe FrameMaker</comment>
- <comment xml:lang="gl">tipo de fonte de Adobe FrameMaker</comment>
- <comment xml:lang="he">גופן של Adobe FrameMaker</comment>
- <comment xml:lang="hr">Adobe FrameMaker slovo</comment>
- <comment xml:lang="hu">Adobe FrameMaker-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras pro Adobe FrameMaker</comment>
- <comment xml:lang="id">Fonta Adobe FrameMaker</comment>
- <comment xml:lang="it">Carattere Adobe FrameMaker</comment>
- <comment xml:lang="ja">Adobe FrameMaker フォント</comment>
- <comment xml:lang="kk">Adobe FrameMaker қарібі</comment>
- <comment xml:lang="ko">Adobe 프레임메이커 글꼴</comment>
- <comment xml:lang="lt">Adobe FrameMaker šriftas</comment>
- <comment xml:lang="lv">Adobe FrameMaker fonts</comment>
- <comment xml:lang="ms">Font Adobe FrameMaker</comment>
- <comment xml:lang="nb">Adobe FrameMaker skrifttype</comment>
- <comment xml:lang="nl">Adobe FrameMaker-lettertype</comment>
- <comment xml:lang="nn">Adobe FrameMaker-skrifttype</comment>
- <comment xml:lang="oc">poliça Adobe FrameMaker</comment>
- <comment xml:lang="pl">Czcionka Adobe FrameMaker</comment>
- <comment xml:lang="pt">letra Adobe FrameMaker</comment>
- <comment xml:lang="pt_BR">Fonte do Adobe FrameMaker</comment>
- <comment xml:lang="ro">Font Adobe FrameMaker</comment>
- <comment xml:lang="ru">Шрифт Adobe FrameMaker</comment>
- <comment xml:lang="sk">Písmo Adobe FrameMaker</comment>
- <comment xml:lang="sl">Datoteka pisave Adobe FrameMaker</comment>
- <comment xml:lang="sq">Gërma Adobe FrameMaker</comment>
- <comment xml:lang="sr">слова Адобе Фрејм Мејкера</comment>
- <comment xml:lang="sv">Adobe FrameMaker-typsnitt</comment>
- <comment xml:lang="tr">Adobe FrameMaker yazı tipi</comment>
- <comment xml:lang="uk">шрифт Adobe FrameMaker</comment>
- <comment xml:lang="vi">Phông chữ Adobe FrameMaker</comment>
- <comment xml:lang="zh_CN">Adobe FrameMaker 字体</comment>
<comment xml:lang="zh_TW">Adobe FrameMaker 字型</comment>
+ <comment xml:lang="zh_CN">Adobe FrameMaker 字体</comment>
+ <comment xml:lang="vi">Phông chữ Adobe FrameMaker</comment>
+ <comment xml:lang="uk">шрифт Adobe FrameMaker</comment>
+ <comment xml:lang="tr">Adobe FrameMaker yazı tipi</comment>
+ <comment xml:lang="sv">Adobe FrameMaker-typsnitt</comment>
+ <comment xml:lang="sr">слова Адобе Фрејм Мејкера</comment>
+ <comment xml:lang="sq">shkronja Adobe FrameMaker</comment>
+ <comment xml:lang="sl">Datoteka pisave Adobe FrameMaker</comment>
+ <comment xml:lang="si">Adobe FrameMaker අකුරු</comment>
+ <comment xml:lang="sk">Písmo Adobe FrameMaker</comment>
+ <comment xml:lang="ru">Шрифт Adobe FrameMaker</comment>
+ <comment xml:lang="ro">Font Adobe FrameMaker</comment>
+ <comment xml:lang="pt_BR">Fonte do Adobe FrameMaker</comment>
+ <comment xml:lang="pt">letra Adobe FrameMaker</comment>
+ <comment xml:lang="pl">Czcionka Adobe FrameMaker</comment>
+ <comment xml:lang="oc">poliça Adobe FrameMaker</comment>
+ <comment xml:lang="nn">Adobe FrameMaker-skrifttype</comment>
+ <comment xml:lang="nl">Adobe FrameMaker-lettertype</comment>
+ <comment xml:lang="nb">Adobe FrameMaker skrifttype</comment>
+ <comment xml:lang="ms">Font Adobe FrameMaker</comment>
+ <comment xml:lang="lv">Adobe FrameMaker fonts</comment>
+ <comment xml:lang="lt">Adobe FrameMaker šriftas</comment>
+ <comment xml:lang="ko">Adobe 프레임메이커 글꼴</comment>
+ <comment xml:lang="kk">Adobe FrameMaker қарібі</comment>
+ <comment xml:lang="ja">Adobe FrameMaker フォント</comment>
+ <comment xml:lang="it">Carattere Adobe FrameMaker</comment>
+ <comment xml:lang="is">Adobe FrameMaker letur</comment>
+ <comment xml:lang="id">Fonta Adobe FrameMaker</comment>
+ <comment xml:lang="ia">Typo de litteras pro Adobe FrameMaker</comment>
+ <comment xml:lang="hu">Adobe FrameMaker-betűkészlet</comment>
+ <comment xml:lang="hr">Adobe FrameMaker font</comment>
+ <comment xml:lang="he">גופן של Adobe FrameMaker</comment>
+ <comment xml:lang="gl">tipo de fonte de Adobe FrameMaker</comment>
+ <comment xml:lang="ga">cló Adobe FrameMaker</comment>
+ <comment xml:lang="fur">caratar Adobe FrameMaker</comment>
+ <comment xml:lang="fr">police Adobe FrameMaker</comment>
+ <comment xml:lang="fo">Adobe FrameMaker stavasnið</comment>
+ <comment xml:lang="fi">Adobe FrameMaker -fontti</comment>
+ <comment xml:lang="eu">Adobe FrameMaker-en letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra de Adobe FrameMaker</comment>
+ <comment xml:lang="eo">Tiparo de Adobe FrameMaker</comment>
+ <comment xml:lang="en_GB">Adobe FrameMaker font</comment>
+ <comment xml:lang="el">Γραμματοσειρά Adobe FrameMaker</comment>
+ <comment xml:lang="de">Adobe-FrameMaker-Schrift</comment>
+ <comment xml:lang="da">Adobe FrameMaker-skrifttype</comment>
+ <comment xml:lang="cy">Ffont Adobe FrameMaker</comment>
+ <comment xml:lang="cs">font Adobe FrameMaker</comment>
+ <comment xml:lang="ca">lletra d'Adobe FrameMaker</comment>
+ <comment xml:lang="bg">Шрифт — Adobe FrameMaker</comment>
+ <comment xml:lang="be@latin">Šryft Adobe FrameMaker</comment>
+ <comment xml:lang="be">шрыфт Adobe FrameMaker</comment>
+ <comment xml:lang="az">Adobe FrameMaker yazı növü</comment>
+ <comment xml:lang="ar">خط أدوبي FrameMaker</comment>
+ <comment xml:lang="af">Adobe FrameMaker-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="&lt;MakerScreenFont" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="&lt;MakerScreenFont" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-font-libgrx">
<comment>LIBGRX font</comment>
- <comment xml:lang="ar">خط LIBGRX</comment>
- <comment xml:lang="az">LIBGRX yazı növü</comment>
- <comment xml:lang="be@latin">Šryft LIBGRX</comment>
- <comment xml:lang="bg">Шрифт — LIBGRX</comment>
- <comment xml:lang="ca">lletra LIBGRX</comment>
- <comment xml:lang="cs">font LIBGRX</comment>
- <comment xml:lang="cy">Ffont LIBGRX</comment>
- <comment xml:lang="da">LIBGRX-skrifttype</comment>
- <comment xml:lang="de">LIBGRX-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά LIBGRX</comment>
- <comment xml:lang="en_GB">LIBGRX font</comment>
- <comment xml:lang="eo">LIBGRX-tiparo</comment>
- <comment xml:lang="es">tipo de letra LIBGRX</comment>
- <comment xml:lang="eu">LIBGRX letra-tipoa</comment>
- <comment xml:lang="fi">LIBGRX-fontti</comment>
- <comment xml:lang="fo">LIBGRX stavasnið</comment>
- <comment xml:lang="fr">police LIBGRX</comment>
- <comment xml:lang="ga">cló LIBGRX</comment>
- <comment xml:lang="gl">tipo de fonte en LIBGRX</comment>
- <comment xml:lang="he">גופן LIBGRX</comment>
- <comment xml:lang="hr">LIBGRX slovo</comment>
- <comment xml:lang="hu">LIBGRX-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras LIBGRX</comment>
- <comment xml:lang="id">Fonta LIBGRX</comment>
- <comment xml:lang="it">Carattere LIBGRX</comment>
- <comment xml:lang="ja">LIBGRX フォーマット</comment>
- <comment xml:lang="kk">LIBGRX қарібі</comment>
- <comment xml:lang="ko">LIBGRX 글꼴</comment>
- <comment xml:lang="lt">LIBGRX šriftas</comment>
- <comment xml:lang="lv">LIBGRX fonts</comment>
- <comment xml:lang="ms">Font LIBGRX</comment>
- <comment xml:lang="nb">LIBGRX-skrifttype</comment>
- <comment xml:lang="nl">LIBGRX-lettertype</comment>
- <comment xml:lang="nn">LIBGRX skrifttype</comment>
- <comment xml:lang="oc">poliça LIBGRX</comment>
- <comment xml:lang="pl">Czcionka LIBGRX</comment>
- <comment xml:lang="pt">letra LIBGRX</comment>
- <comment xml:lang="pt_BR">Fonte LIBGRX</comment>
- <comment xml:lang="ro">Font LIBGRX</comment>
- <comment xml:lang="ru">Шрифт LIBGRX</comment>
- <comment xml:lang="sk">Písmo LIBGRX</comment>
- <comment xml:lang="sl">Datoteka pisave LIBGRX</comment>
- <comment xml:lang="sq">Lloj gërme LIBGRX</comment>
- <comment xml:lang="sr">ЛИБГРИкс слова</comment>
- <comment xml:lang="sv">LIBGRX-typsnitt</comment>
- <comment xml:lang="tr">LIBGRX fontu</comment>
- <comment xml:lang="uk">шрифт LIBGRX</comment>
- <comment xml:lang="vi">Phông chữ LIBGRX</comment>
- <comment xml:lang="zh_CN">LIBGRX 字体</comment>
<comment xml:lang="zh_TW">LIBGRX 字型</comment>
+ <comment xml:lang="zh_CN">LIBGRX 字体</comment>
+ <comment xml:lang="vi">Phông chữ LIBGRX</comment>
+ <comment xml:lang="uk">шрифт LIBGRX</comment>
+ <comment xml:lang="tr">LIBGRX yazı tipi</comment>
+ <comment xml:lang="sv">LIBGRX-typsnitt</comment>
+ <comment xml:lang="sr">ЛИБГРИкс слова</comment>
+ <comment xml:lang="sq">shkronja LIBGRX</comment>
+ <comment xml:lang="sl">Datoteka pisave LIBGRX</comment>
+ <comment xml:lang="si">LIBGRX අකුරු</comment>
+ <comment xml:lang="sk">Písmo LIBGRX</comment>
+ <comment xml:lang="ru">Шрифт LIBGRX</comment>
+ <comment xml:lang="ro">Font LIBGRX</comment>
+ <comment xml:lang="pt_BR">Fonte LIBGRX</comment>
+ <comment xml:lang="pt">letra LIBGRX</comment>
+ <comment xml:lang="pl">Czcionka LIBGRX</comment>
+ <comment xml:lang="oc">poliça LIBGRX</comment>
+ <comment xml:lang="nn">LIBGRX skrifttype</comment>
+ <comment xml:lang="nl">LIBGRX-lettertype</comment>
+ <comment xml:lang="nb">LIBGRX-skrifttype</comment>
+ <comment xml:lang="ms">Font LIBGRX</comment>
+ <comment xml:lang="lv">LIBGRX fonts</comment>
+ <comment xml:lang="lt">LIBGRX šriftas</comment>
+ <comment xml:lang="ko">LIBGRX 글꼴</comment>
+ <comment xml:lang="kk">LIBGRX қарібі</comment>
+ <comment xml:lang="ja">LIBGRX フォーマット</comment>
+ <comment xml:lang="it">Carattere LIBGRX</comment>
+ <comment xml:lang="is">LIBGRX letur</comment>
+ <comment xml:lang="id">Fonta LIBGRX</comment>
+ <comment xml:lang="ia">Typo de litteras LIBGRX</comment>
+ <comment xml:lang="hu">LIBGRX-betűkészlet</comment>
+ <comment xml:lang="hr">LIBGRX font</comment>
+ <comment xml:lang="he">גופן LIBGRX</comment>
+ <comment xml:lang="gl">tipo de fonte en LIBGRX</comment>
+ <comment xml:lang="ga">cló LIBGRX</comment>
+ <comment xml:lang="fur">caratar LIBGRX</comment>
+ <comment xml:lang="fr">police LIBGRX</comment>
+ <comment xml:lang="fo">LIBGRX stavasnið</comment>
+ <comment xml:lang="fi">LIBGRX-fontti</comment>
+ <comment xml:lang="eu">LIBGRX letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra LIBGRX</comment>
+ <comment xml:lang="eo">LIBGRX-tiparo</comment>
+ <comment xml:lang="en_GB">LIBGRX font</comment>
+ <comment xml:lang="el">Γραμματοσειρά LIBGRX</comment>
+ <comment xml:lang="de">LIBGRX-Schrift</comment>
+ <comment xml:lang="da">LIBGRX-skrifttype</comment>
+ <comment xml:lang="cy">Ffont LIBGRX</comment>
+ <comment xml:lang="cs">font LIBGRX</comment>
+ <comment xml:lang="ca">lletra LIBGRX</comment>
+ <comment xml:lang="bg">Шрифт — LIBGRX</comment>
+ <comment xml:lang="be@latin">Šryft LIBGRX</comment>
+ <comment xml:lang="be">шрыфт LIBGRX</comment>
+ <comment xml:lang="az">LIBGRX yazı növü</comment>
+ <comment xml:lang="ar">خط LIBGRX</comment>
+ <comment xml:lang="af">LIBGRX-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="\x14\x02\x59\x19" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\x14\x02\x59\x19" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-font-linux-psf">
<comment>Linux PSF console font</comment>
- <comment xml:lang="ar">خط كونسول PSF لينكس</comment>
- <comment xml:lang="az">Linux PSF konsol yazı növü</comment>
- <comment xml:lang="be@latin">Kansolny šryft PSF dla Linuksa</comment>
- <comment xml:lang="bg">Шрифт — PSF, за конзолата на Линукс</comment>
- <comment xml:lang="ca">lletra de consola PSF de Linux</comment>
- <comment xml:lang="cs">font PSF pro konzolu Linuxu</comment>
- <comment xml:lang="cy">Ffont Linux PSF</comment>
- <comment xml:lang="da">Linux PSF-konsolskrifttype</comment>
- <comment xml:lang="de">Linux-PSF-Konsolenschrift</comment>
- <comment xml:lang="el">Γραμματοσειρά κονσόλας PSF Linux</comment>
- <comment xml:lang="en_GB">Linux PSF console font</comment>
- <comment xml:lang="eo">PSF-tiparo de Linux-konzolo</comment>
- <comment xml:lang="es">tipo de letra de consola Linux PSF</comment>
- <comment xml:lang="eu">Linux PSF kontsolako letra-tipoa</comment>
- <comment xml:lang="fi">Linux PSF -konsolifontti</comment>
- <comment xml:lang="fo">Linux PSF stýristøðs stavasnið</comment>
- <comment xml:lang="fr">police console Linux PSF</comment>
- <comment xml:lang="ga">cló consóil Linux PSF</comment>
- <comment xml:lang="gl">tipo de fonte de consola Linux PSF</comment>
- <comment xml:lang="he">גופן לקונסול מסוג Linux PSF</comment>
- <comment xml:lang="hr">Linux PSF konzolno slovo</comment>
- <comment xml:lang="hu">Linux PSF konzolos betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras console Linux PSF</comment>
- <comment xml:lang="id">Fonta konsol Linux PSF</comment>
- <comment xml:lang="it">Carattere console Linux PSF</comment>
- <comment xml:lang="ja">Linux PSF コンソールフォント</comment>
- <comment xml:lang="kk">Linux PSF консольдік қарібі</comment>
- <comment xml:lang="ko">리눅스 PSF 콘솔 글꼴</comment>
- <comment xml:lang="lt">Linux PSF konsolės šriftas</comment>
- <comment xml:lang="lv">Linux PSF konsoles fonts</comment>
- <comment xml:lang="ms">Font konsol PSF Linux</comment>
- <comment xml:lang="nb">Linux PSF konsollskrifttype</comment>
- <comment xml:lang="nl">Linux PSF-console-lettertype</comment>
- <comment xml:lang="nn">Linux PSF konsoll-skrifttype</comment>
- <comment xml:lang="oc">poliça consòla Linux PSF</comment>
- <comment xml:lang="pl">Czcionka konsoli PSF Linux</comment>
- <comment xml:lang="pt">letra de consola Linux PSF</comment>
- <comment xml:lang="pt_BR">Fonte de console Linux PSF</comment>
- <comment xml:lang="ro">Font consolă Linux PSF</comment>
- <comment xml:lang="ru">Консольный шрифт Linux PSF</comment>
- <comment xml:lang="sk">Písmo PSF pre konzolu Linuxu</comment>
- <comment xml:lang="sl">Datoteka pisave konzole Linux PSF</comment>
- <comment xml:lang="sq">Lloj gërme për konsolë Linux PSF</comment>
- <comment xml:lang="sr">слова Линуксове ПСФ конзоле</comment>
- <comment xml:lang="sv">Linux PSF-konsoltypsnitt</comment>
- <comment xml:lang="tr">Linux PSF konsol fontu</comment>
- <comment xml:lang="uk">консольний шрифт Linux PSF</comment>
- <comment xml:lang="vi">Phông chữ bàn giao tiếp PSF Linux</comment>
- <comment xml:lang="zh_CN">Linux PSF 控制台字体</comment>
<comment xml:lang="zh_TW">Linux PSF console 字型</comment>
+ <comment xml:lang="zh_CN">Linux PSF 控制台字体</comment>
+ <comment xml:lang="vi">Phông chữ bàn giao tiếp PSF Linux</comment>
+ <comment xml:lang="uk">консольний шрифт Linux PSF</comment>
+ <comment xml:lang="tr">Linux PSF konsol yazı tipi</comment>
+ <comment xml:lang="sv">Linux PSF-konsoltypsnitt</comment>
+ <comment xml:lang="sr">слова Линуксове ПСФ конзоле</comment>
+ <comment xml:lang="sq">shkronja konsole Linux PSF</comment>
+ <comment xml:lang="sl">Datoteka pisave konzole Linux PSF</comment>
+ <comment xml:lang="si">Linux PSF කොන්සෝල අකුරු</comment>
+ <comment xml:lang="sk">Písmo PSF pre konzolu Linuxu</comment>
+ <comment xml:lang="ru">Консольный шрифт Linux PSF</comment>
+ <comment xml:lang="ro">Font consolă Linux PSF</comment>
+ <comment xml:lang="pt_BR">Fonte de console Linux PSF</comment>
+ <comment xml:lang="pt">letra de consola Linux PSF</comment>
+ <comment xml:lang="pl">Czcionka konsoli PSF Linux</comment>
+ <comment xml:lang="oc">poliça consòla Linux PSF</comment>
+ <comment xml:lang="nn">Linux PSF konsoll-skrifttype</comment>
+ <comment xml:lang="nl">Linux PSF-console-lettertype</comment>
+ <comment xml:lang="nb">Linux PSF konsollskrifttype</comment>
+ <comment xml:lang="ms">Font konsol PSF Linux</comment>
+ <comment xml:lang="lv">Linux PSF konsoles fonts</comment>
+ <comment xml:lang="lt">Linux PSF konsolės šriftas</comment>
+ <comment xml:lang="ko">리눅스 PSF 콘솔 글꼴</comment>
+ <comment xml:lang="kk">Linux PSF консольдік қарібі</comment>
+ <comment xml:lang="ja">Linux PSF コンソールフォント</comment>
+ <comment xml:lang="it">Carattere console Linux PSF</comment>
+ <comment xml:lang="is">Linux PSF stjórnskjáaletur</comment>
+ <comment xml:lang="id">Fonta konsol Linux PSF</comment>
+ <comment xml:lang="ia">Typo de litteras console Linux PSF</comment>
+ <comment xml:lang="hu">Linux PSF konzolos betűkészlet</comment>
+ <comment xml:lang="hr">Linux PSF font konzole</comment>
+ <comment xml:lang="he">גופן לקונסול מסוג Linux PSF</comment>
+ <comment xml:lang="gl">tipo de fonte de consola Linux PSF</comment>
+ <comment xml:lang="ga">cló consóil Linux PSF</comment>
+ <comment xml:lang="fur">caratar console Linux PSF</comment>
+ <comment xml:lang="fr">police console Linux PSF</comment>
+ <comment xml:lang="fo">Linux PSF stýristøðs stavasnið</comment>
+ <comment xml:lang="fi">Linux PSF -konsolifontti</comment>
+ <comment xml:lang="eu">Linux PSF kontsolako letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra de consola Linux PSF</comment>
+ <comment xml:lang="eo">PSF-tiparo de Linux-konzolo</comment>
+ <comment xml:lang="en_GB">Linux PSF console font</comment>
+ <comment xml:lang="el">Γραμματοσειρά κονσόλας PSF Linux</comment>
+ <comment xml:lang="de">Linux-PSF-Konsolenschrift</comment>
+ <comment xml:lang="da">Linux PSF-konsolskrifttype</comment>
+ <comment xml:lang="cy">Ffont Linux PSF</comment>
+ <comment xml:lang="cs">font PSF pro konzolu Linuxu</comment>
+ <comment xml:lang="ca">lletra de consola PSF de Linux</comment>
+ <comment xml:lang="bg">Шрифт — PSF, за конзолата на Линукс</comment>
+ <comment xml:lang="be@latin">Kansolny šryft PSF dla Linuksa</comment>
+ <comment xml:lang="be">шрыфт кансолі PSF для Linux</comment>
+ <comment xml:lang="az">Linux PSF konsol yazı növü</comment>
+ <comment xml:lang="ar">خط كونسول PSF لينكس</comment>
+ <comment xml:lang="af">Linux PSF-konsoleskriftipe</comment>
+ <acronym>PSF</acronym>
+ <expanded-acronym>PC Screen Font</expanded-acronym>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="\x36\x04" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\x36\x04" offset="0"/>
</magic>
<glob pattern="*.psf"/>
</mime-type>
<mime-type type="application/x-gz-font-linux-psf">
<comment>Linux PSF console font (gzip-compressed)</comment>
- <comment xml:lang="ar">خط كونسول PSF لينكس (مضغوط-gzip)</comment>
- <comment xml:lang="be@latin">Kansolny šryft PSF dla Linuksa (gzip-skampresavany)</comment>
- <comment xml:lang="bg">Шрифт — Linux PSF, компресиран с gzip</comment>
- <comment xml:lang="ca">lletra de consola PSF de Linux (amb compressió gzip)</comment>
- <comment xml:lang="cs">font PSF pro konzolu Linuxu (komprimace gzip)</comment>
- <comment xml:lang="da">Linux PSF-konsolskrifttype (gzip-komprimeret)</comment>
- <comment xml:lang="de">Linux-PSF-Konsolenschrift (gzip-komprimiert)</comment>
- <comment xml:lang="el">Γραμματοσειρά κονσόλας PSF Linux (συμπιεσμένη με gzip)</comment>
- <comment xml:lang="en_GB">Linux PSF console font (gzip-compressed)</comment>
- <comment xml:lang="es">tipo de letra de consola Linux PSF (comprimido con gzip)</comment>
- <comment xml:lang="eu">Linux PSF kontsolako letra-tipoa (gzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">Linux PSF -konsolifontti (gzip-pakattu)</comment>
- <comment xml:lang="fo">Linux PSF stýristøðs stavasnið (gzip-stappað)</comment>
- <comment xml:lang="fr">police console Linux PSF (compressée gzip)</comment>
- <comment xml:lang="ga">cló consóil Linux PSF (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">tipo de fonte de consola Linux PSF (comprimida con gzip)</comment>
- <comment xml:lang="he">גופן למסוף מסוג Linux PSF (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">Linux PSF konzolno slovo (gzip sažeto)</comment>
- <comment xml:lang="hu">Linux PSF konzolos betűkészlet (gzip-tömörítésű)</comment>
- <comment xml:lang="ia">Typo de litteras console Linux PSF (comprimite con gzip)</comment>
- <comment xml:lang="id">Fonta konsol Linux PSF (terkompresi gzip)</comment>
- <comment xml:lang="it">Carattere console Linux PSF (compresso con gzip)</comment>
- <comment xml:lang="ja">Linux PSF コンソールフォント (gzip 圧縮)</comment>
- <comment xml:lang="kk">Linux PSF консольдік қарібі (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">리눅스 PSF 콘솔 글꼴(GZIP 압축)</comment>
- <comment xml:lang="lt">Linux PSF konsolės šriftas (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">Linux PSF konsoles fonts (saspiests ar gzip)</comment>
- <comment xml:lang="nb">Linux PSF konsollskrifttype (gzip-komprimert)</comment>
- <comment xml:lang="nl">Linux PSF-console-lettertype (ingepakt met gzip)</comment>
- <comment xml:lang="nn">Linux PSF konsoll-skrifttype (gzip-pakka)</comment>
- <comment xml:lang="oc">poliça consòla Linux PSF (compressat gzip)</comment>
- <comment xml:lang="pl">Czcionka konsoli PSF Linux (kompresja gzip)</comment>
- <comment xml:lang="pt">letra de consola Linux PSF (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Fonte de console Linux PSF (compactada com gzip)</comment>
- <comment xml:lang="ro">Font consolă Linux PSF (compresie gzip)</comment>
- <comment xml:lang="ru">Консольный шрифт Linux PSF (сжатый gzip)</comment>
- <comment xml:lang="sk">Písmo PSF pre konzolu Linuxu (komprimované pomocou gzip)</comment>
- <comment xml:lang="sl">Datoteka pisave konzole Linux PSF (skrčena z gzip)</comment>
- <comment xml:lang="sq">Lloj gërme për konsolë Linux PSF (komresuar me gzip)</comment>
- <comment xml:lang="sr">слова Линуксове ПСФ конзоле (запакована гзип-ом)</comment>
- <comment xml:lang="sv">Linux PSF-konsoltypsnitt (gzip-komprimerat)</comment>
- <comment xml:lang="tr">Linux PSF konsol fontu (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">консольний шрифт Linux PSF (стиснений gzip)</comment>
- <comment xml:lang="vi">Phông chữ bàn giao tiếp PSF Linux (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">Linux PSF console 字型 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">Linux PSF 控制台字体(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">Linux PSF console 字型 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Phông chữ bàn giao tiếp PSF Linux (đã nén gzip)</comment>
+ <comment xml:lang="uk">консольний шрифт Linux PSF (стиснений gzip)</comment>
+ <comment xml:lang="tr">Linux PSF konsol yazı tipi (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Linux PSF-konsoltypsnitt (gzip-komprimerat)</comment>
+ <comment xml:lang="sr">слова Линуксове ПСФ конзоле (запакована гзип-ом)</comment>
+ <comment xml:lang="sq">shkronja konsole Linux PSF (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Datoteka pisave konzole Linux PSF (skrčena z gzip)</comment>
+ <comment xml:lang="si">Linux PSF කොන්සෝල අකුරු (gzip-compressed)</comment>
+ <comment xml:lang="sk">Písmo PSF pre konzolu Linuxu (komprimované pomocou gzip)</comment>
+ <comment xml:lang="ru">Консольный шрифт Linux PSF (сжатый gzip)</comment>
+ <comment xml:lang="ro">Font consolă Linux PSF (compresie gzip)</comment>
+ <comment xml:lang="pt_BR">Fonte de console Linux PSF (compactada com gzip)</comment>
+ <comment xml:lang="pt">letra de consola Linux PSF (compressão gzip)</comment>
+ <comment xml:lang="pl">Czcionka konsoli PSF Linux (kompresja gzip)</comment>
+ <comment xml:lang="oc">poliça consòla Linux PSF (compressat gzip)</comment>
+ <comment xml:lang="nn">Linux PSF konsoll-skrifttype (gzip-pakka)</comment>
+ <comment xml:lang="nl">Linux PSF-console-lettertype (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">Linux PSF konsollskrifttype (gzip-komprimert)</comment>
+ <comment xml:lang="lv">Linux PSF konsoles fonts (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">Linux PSF konsolės šriftas (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">리눅스 PSF 콘솔 글꼴(GZIP 압축)</comment>
+ <comment xml:lang="kk">Linux PSF консольдік қарібі (gzip-пен сығылған)</comment>
+ <comment xml:lang="ja">Linux PSF コンソールフォント (gzip 圧縮)</comment>
+ <comment xml:lang="it">Carattere console Linux PSF (compresso con gzip)</comment>
+ <comment xml:lang="is">Linux PSF stjórnskjáaletur (gzip-þjöppað)</comment>
+ <comment xml:lang="id">Fonta konsol Linux PSF (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Typo de litteras console Linux PSF (comprimite con gzip)</comment>
+ <comment xml:lang="hu">Linux PSF konzolos betűkészlet (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">Linux PSF font konzolne (gzip komprimirano)</comment>
+ <comment xml:lang="he">גופן למסוף מסוג Linux PSF (מכווץ ע״י gzip)</comment>
+ <comment xml:lang="gl">tipo de fonte de consola Linux PSF (comprimida con gzip)</comment>
+ <comment xml:lang="ga">cló consóil Linux PSF (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">caratar console Linux PSF (comprimût cun gzip)</comment>
+ <comment xml:lang="fr">police console Linux PSF (compressée gzip)</comment>
+ <comment xml:lang="fo">Linux PSF stýristøðs stavasnið (gzip-stappað)</comment>
+ <comment xml:lang="fi">Linux PSF -konsolifontti (gzip-pakattu)</comment>
+ <comment xml:lang="eu">Linux PSF kontsolako letra-tipoa (gzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">tipo de letra de consola Linux PSF (comprimido con GZIP)</comment>
+ <comment xml:lang="en_GB">Linux PSF console font (gzip-compressed)</comment>
+ <comment xml:lang="el">Γραμματοσειρά κονσόλας PSF Linux (συμπιεσμένη με gzip)</comment>
+ <comment xml:lang="de">Linux-PSF-Konsolenschrift (gzip-komprimiert)</comment>
+ <comment xml:lang="da">Linux PSF-konsolskrifttype (gzip-komprimeret)</comment>
+ <comment xml:lang="cs">font PSF pro konzolu Linuxu (komprimace gzip)</comment>
+ <comment xml:lang="ca">lletra de consola PSF de Linux (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Шрифт — Linux PSF, компресиран с gzip</comment>
+ <comment xml:lang="be@latin">Kansolny šryft PSF dla Linuksa (gzip-skampresavany)</comment>
+ <comment xml:lang="be">шрыфт кансолі PSF для Linux (сцісканне gzip)</comment>
+ <comment xml:lang="ar">خط كونسول PSF لينكس (مضغوط-gzip)</comment>
+ <comment xml:lang="af">Linux PSF-konsoleskriftipe (gzip-saamgepers)</comment>
+ <acronym>PSF</acronym>
+ <expanded-acronym>PC Screen Font</expanded-acronym>
<sub-class-of type="application/gzip"/>
<generic-icon name="font-x-generic"/>
<glob pattern="*.psf.gz"/>
</mime-type>
<mime-type type="application/x-font-pcf">
<comment>PCF font</comment>
- <comment xml:lang="ar">خط PCF</comment>
- <comment xml:lang="az">PCF yazı növü</comment>
- <comment xml:lang="be@latin">Šryft PCF</comment>
- <comment xml:lang="bg">Шрифт — PCF</comment>
- <comment xml:lang="ca">lletra PCF</comment>
- <comment xml:lang="cs">font PCF</comment>
- <comment xml:lang="cy">Ffont PCF</comment>
- <comment xml:lang="da">PCF-skrifttype</comment>
- <comment xml:lang="de">PCF-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά PCF</comment>
- <comment xml:lang="en_GB">PCF font</comment>
- <comment xml:lang="eo">PCF-tiparo</comment>
- <comment xml:lang="es">tipo de letra PCF</comment>
- <comment xml:lang="eu">PCF letra-tipoa</comment>
- <comment xml:lang="fi">PCF-fontti</comment>
- <comment xml:lang="fo">PCF stavasnið</comment>
- <comment xml:lang="fr">police PCF</comment>
- <comment xml:lang="ga">cló PCF</comment>
- <comment xml:lang="gl">tipo de letra PCF</comment>
- <comment xml:lang="he">גופן PCF</comment>
- <comment xml:lang="hr">PCF slovo</comment>
- <comment xml:lang="hu">PCF-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras PCF</comment>
- <comment xml:lang="id">Fonta PCF</comment>
- <comment xml:lang="it">Carattere PCF</comment>
- <comment xml:lang="ja">PCF フォント</comment>
- <comment xml:lang="kk">PCF қарібі</comment>
- <comment xml:lang="ko">PCF 글꼴</comment>
- <comment xml:lang="lt">PCF šriftas</comment>
- <comment xml:lang="lv">PCF fonts</comment>
- <comment xml:lang="ms">Font PCF</comment>
- <comment xml:lang="nb">PCF-skrifttype</comment>
- <comment xml:lang="nl">PCF-lettertype</comment>
- <comment xml:lang="nn">PCF-skrifttype</comment>
- <comment xml:lang="oc">poliça PCF</comment>
- <comment xml:lang="pl">Czcionka PCF</comment>
- <comment xml:lang="pt">letra PCF</comment>
- <comment xml:lang="pt_BR">Fonte PCF</comment>
- <comment xml:lang="ro">Font PCF</comment>
- <comment xml:lang="ru">Шрифт PCF</comment>
- <comment xml:lang="sk">Písmo PCF</comment>
- <comment xml:lang="sl">Datoteka pisave PCF</comment>
- <comment xml:lang="sq">Gërma PCF</comment>
- <comment xml:lang="sr">ПЦФ слова</comment>
- <comment xml:lang="sv">PCF-typsnitt</comment>
- <comment xml:lang="tr">PCF fontu</comment>
- <comment xml:lang="uk">шрифт PCF</comment>
- <comment xml:lang="vi">Phông chữ PCF</comment>
- <comment xml:lang="zh_CN">PCF 字体</comment>
<comment xml:lang="zh_TW">PCF 字型</comment>
+ <comment xml:lang="zh_CN">PCF 字体</comment>
+ <comment xml:lang="vi">Phông chữ PCF</comment>
+ <comment xml:lang="uk">шрифт PCF</comment>
+ <comment xml:lang="tr">PCF yazı tipi</comment>
+ <comment xml:lang="sv">PCF-typsnitt</comment>
+ <comment xml:lang="sr">ПЦФ слова</comment>
+ <comment xml:lang="sq">shkronja PCF</comment>
+ <comment xml:lang="sl">Datoteka pisave PCF</comment>
+ <comment xml:lang="si">PCF අකුරු</comment>
+ <comment xml:lang="sk">Písmo PCF</comment>
+ <comment xml:lang="ru">Шрифт PCF</comment>
+ <comment xml:lang="ro">Font PCF</comment>
+ <comment xml:lang="pt_BR">Fonte PCF</comment>
+ <comment xml:lang="pt">letra PCF</comment>
+ <comment xml:lang="pl">Czcionka PCF</comment>
+ <comment xml:lang="oc">poliça PCF</comment>
+ <comment xml:lang="nn">PCF-skrifttype</comment>
+ <comment xml:lang="nl">PCF-lettertype</comment>
+ <comment xml:lang="nb">PCF-skrifttype</comment>
+ <comment xml:lang="ms">Font PCF</comment>
+ <comment xml:lang="lv">PCF fonts</comment>
+ <comment xml:lang="lt">PCF šriftas</comment>
+ <comment xml:lang="ko">PCF 글꼴</comment>
+ <comment xml:lang="kk">PCF қарібі</comment>
+ <comment xml:lang="ja">PCF フォント</comment>
+ <comment xml:lang="it">Carattere PCF</comment>
+ <comment xml:lang="is">PCF letur</comment>
+ <comment xml:lang="id">Fonta PCF</comment>
+ <comment xml:lang="ia">Typo de litteras PCF</comment>
+ <comment xml:lang="hu">PCF-betűkészlet</comment>
+ <comment xml:lang="hr">PCF font</comment>
+ <comment xml:lang="he">גופן PCF</comment>
+ <comment xml:lang="gl">tipo de letra PCF</comment>
+ <comment xml:lang="ga">cló PCF</comment>
+ <comment xml:lang="fur">caratar PCF</comment>
+ <comment xml:lang="fr">police PCF</comment>
+ <comment xml:lang="fo">PCF stavasnið</comment>
+ <comment xml:lang="fi">PCF-fontti</comment>
+ <comment xml:lang="eu">PCF letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra PCF</comment>
+ <comment xml:lang="eo">PCF-tiparo</comment>
+ <comment xml:lang="en_GB">PCF font</comment>
+ <comment xml:lang="el">Γραμματοσειρά PCF</comment>
+ <comment xml:lang="de">PCF-Schrift</comment>
+ <comment xml:lang="da">PCF-skrifttype</comment>
+ <comment xml:lang="cy">Ffont PCF</comment>
+ <comment xml:lang="cs">font PCF</comment>
+ <comment xml:lang="ca">lletra PCF</comment>
+ <comment xml:lang="bg">Шрифт — PCF</comment>
+ <comment xml:lang="be@latin">Šryft PCF</comment>
+ <comment xml:lang="be">шрыфт PCF</comment>
+ <comment xml:lang="az">PCF yazı növü</comment>
+ <comment xml:lang="ar">خط PCF</comment>
+ <comment xml:lang="af">PCF-skriftipe</comment>
+ <acronym>PCF</acronym>
+ <expanded-acronym>Portable Compiled Format</expanded-acronym>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="\001fcp" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\001fcp" offset="0"/>
</magic>
<glob pattern="*.pcf"/>
<glob pattern="*.pcf.Z"/>
@@ -11212,612 +12037,703 @@
</mime-type>
<mime-type type="font/otf">
<comment>OpenType font</comment>
- <comment xml:lang="ar">خط OpenType</comment>
- <comment xml:lang="az">OpenType yazı növü</comment>
- <comment xml:lang="be@latin">Šryft OpenType</comment>
- <comment xml:lang="bg">Шрифт — OpenType</comment>
- <comment xml:lang="ca">lletra OpenType</comment>
- <comment xml:lang="cs">font OpenType</comment>
- <comment xml:lang="cy">Ffont OpenType</comment>
- <comment xml:lang="da">OpenType-skrifttype</comment>
- <comment xml:lang="de">OpenType-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά OpenType </comment>
- <comment xml:lang="en_GB">OpenType font</comment>
- <comment xml:lang="eo">OpenType-tiparo</comment>
- <comment xml:lang="es">tipo de letra OpenType</comment>
- <comment xml:lang="eu">OpenType letra-tipoa</comment>
- <comment xml:lang="fi">OpenType-fontti</comment>
- <comment xml:lang="fo">OpenType stavasnið</comment>
- <comment xml:lang="fr">police OpenType</comment>
- <comment xml:lang="ga">cló OpenType</comment>
- <comment xml:lang="gl">tipo de fonte OpenType</comment>
- <comment xml:lang="he">גופן של OpenType</comment>
- <comment xml:lang="hr">OpenType slovo</comment>
- <comment xml:lang="hu">OpenType-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras OpenType</comment>
- <comment xml:lang="id">Fonta OpenType</comment>
- <comment xml:lang="it">Carattere OpenType</comment>
- <comment xml:lang="ja">OpenType フォント</comment>
- <comment xml:lang="kk">OpenType қарібі</comment>
- <comment xml:lang="ko">오픈타입 글꼴</comment>
- <comment xml:lang="lt">OpenType šriftas</comment>
- <comment xml:lang="lv">OpenType fonts</comment>
- <comment xml:lang="ms">Font OpenType</comment>
- <comment xml:lang="nb">OpenType-skrifttype</comment>
- <comment xml:lang="nl">OpenType-lettertype</comment>
- <comment xml:lang="nn">OpenType-skrifttype</comment>
- <comment xml:lang="oc">poliça OpenType</comment>
- <comment xml:lang="pl">Czcionka OpenType</comment>
- <comment xml:lang="pt">letra OpenType</comment>
- <comment xml:lang="pt_BR">Fonte OpenType</comment>
- <comment xml:lang="ro">Font OpenType</comment>
- <comment xml:lang="ru">Шрифт OpenType</comment>
- <comment xml:lang="sk">Písmo OpenType</comment>
- <comment xml:lang="sl">Datoteka pisave OpenType</comment>
- <comment xml:lang="sq">Gërma OpenType</comment>
- <comment xml:lang="sr">слова Отворене Врсте</comment>
- <comment xml:lang="sv">OpenType-typsnitt</comment>
- <comment xml:lang="tr">OpenType fontu</comment>
- <comment xml:lang="uk">шрифт OpenType</comment>
- <comment xml:lang="vi">Phông chữ OpenType</comment>
- <comment xml:lang="zh_CN">OpenType 字体</comment>
<comment xml:lang="zh_TW">OpenType 字型</comment>
+ <comment xml:lang="zh_CN">OpenType 字体</comment>
+ <comment xml:lang="vi">Phông chữ OpenType</comment>
+ <comment xml:lang="uk">шрифт OpenType</comment>
+ <comment xml:lang="tr">OpenType yazı tipi</comment>
+ <comment xml:lang="sv">OpenType-typsnitt</comment>
+ <comment xml:lang="sr">слова Отворене Врсте</comment>
+ <comment xml:lang="sq">shkronja OpenType</comment>
+ <comment xml:lang="sl">Datoteka pisave OpenType</comment>
+ <comment xml:lang="si">OpenType අකුරු</comment>
+ <comment xml:lang="sk">Písmo OpenType</comment>
+ <comment xml:lang="ru">Шрифт OpenType</comment>
+ <comment xml:lang="ro">Font OpenType</comment>
+ <comment xml:lang="pt_BR">Fonte OpenType</comment>
+ <comment xml:lang="pt">letra OpenType</comment>
+ <comment xml:lang="pl">Czcionka OpenType</comment>
+ <comment xml:lang="oc">poliça OpenType</comment>
+ <comment xml:lang="nn">OpenType-skrifttype</comment>
+ <comment xml:lang="nl">OpenType-lettertype</comment>
+ <comment xml:lang="nb">OpenType-skrifttype</comment>
+ <comment xml:lang="ms">Font OpenType</comment>
+ <comment xml:lang="lv">OpenType fonts</comment>
+ <comment xml:lang="lt">OpenType šriftas</comment>
+ <comment xml:lang="ko">오픈타입 글꼴</comment>
+ <comment xml:lang="kk">OpenType қарібі</comment>
+ <comment xml:lang="ja">OpenType フォント</comment>
+ <comment xml:lang="it">Carattere OpenType</comment>
+ <comment xml:lang="is">Open Type letur</comment>
+ <comment xml:lang="id">Fonta OpenType</comment>
+ <comment xml:lang="ia">Typo de litteras OpenType</comment>
+ <comment xml:lang="hu">OpenType-betűkészlet</comment>
+ <comment xml:lang="hr">OpenType font</comment>
+ <comment xml:lang="he">גופן של OpenType</comment>
+ <comment xml:lang="gl">tipo de fonte OpenType</comment>
+ <comment xml:lang="ga">cló OpenType</comment>
+ <comment xml:lang="fur">caratar OpenType</comment>
+ <comment xml:lang="fr">police OpenType</comment>
+ <comment xml:lang="fo">OpenType stavasnið</comment>
+ <comment xml:lang="fi">OpenType-fontti</comment>
+ <comment xml:lang="eu">OpenType letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra OpenType</comment>
+ <comment xml:lang="eo">OpenType-tiparo</comment>
+ <comment xml:lang="en_GB">OpenType font</comment>
+ <comment xml:lang="el">Γραμματοσειρά OpenType </comment>
+ <comment xml:lang="de">OpenType-Schrift</comment>
+ <comment xml:lang="da">OpenType-skrifttype</comment>
+ <comment xml:lang="cy">Ffont OpenType</comment>
+ <comment xml:lang="cs">font OpenType</comment>
+ <comment xml:lang="ca">lletra OpenType</comment>
+ <comment xml:lang="bg">Шрифт — OpenType</comment>
+ <comment xml:lang="be@latin">Šryft OpenType</comment>
+ <comment xml:lang="be">шрыфт OpenType</comment>
+ <comment xml:lang="az">OpenType yazı növü</comment>
+ <comment xml:lang="ar">خط OpenType</comment>
+ <comment xml:lang="af">OpenType-skriftipe</comment>
<sub-class-of type="font/ttf"/>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="OTTO" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="OTTO" offset="0"/>
</magic>
<glob pattern="*.otf"/>
<alias type="application/x-font-otf"/>
</mime-type>
<mime-type type="application/x-font-speedo">
<comment>Speedo font</comment>
- <comment xml:lang="ar">خط Speedo</comment>
- <comment xml:lang="az">Speedo yazı növü</comment>
- <comment xml:lang="be@latin">Šryft Speedo</comment>
- <comment xml:lang="bg">Шрифт — Speedo</comment>
- <comment xml:lang="ca">lletra Speedo</comment>
- <comment xml:lang="cs">font Speedo</comment>
- <comment xml:lang="cy">Ffont Speedo</comment>
- <comment xml:lang="da">Speedoskrifttype</comment>
- <comment xml:lang="de">Speedo-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά Speedo</comment>
- <comment xml:lang="en_GB">Speedo font</comment>
- <comment xml:lang="eo">Speedo-tiparo</comment>
- <comment xml:lang="es">tipo de letra de Speedo</comment>
- <comment xml:lang="eu">Speedo letra-tipoa</comment>
- <comment xml:lang="fi">Speedo-fontti</comment>
- <comment xml:lang="fo">Speedo stavasnið</comment>
- <comment xml:lang="fr">police Speedo</comment>
- <comment xml:lang="ga">cló Speedo</comment>
- <comment xml:lang="gl">tipo de letra Speedo</comment>
- <comment xml:lang="he">גופן של Speedo</comment>
- <comment xml:lang="hr">Speedo slovo</comment>
- <comment xml:lang="hu">Speedo-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras Speedo</comment>
- <comment xml:lang="id">Fonta Speedo</comment>
- <comment xml:lang="it">Carattere Speedo</comment>
- <comment xml:lang="ja">Speedo フォント</comment>
- <comment xml:lang="kk">Speedo қарібі</comment>
- <comment xml:lang="ko">Speedo 글꼴</comment>
- <comment xml:lang="lt">Speedo šriftas</comment>
- <comment xml:lang="lv">Speedo fonts</comment>
- <comment xml:lang="ms">Font Speedo</comment>
- <comment xml:lang="nb">Speedo-skrifttype</comment>
- <comment xml:lang="nl">Speedo-lettertype</comment>
- <comment xml:lang="nn">Speedo-skrifttype</comment>
- <comment xml:lang="oc">poliça Speedo</comment>
- <comment xml:lang="pl">Czcionka Speedo</comment>
- <comment xml:lang="pt">letra Speedo</comment>
- <comment xml:lang="pt_BR">Fonte Speedo</comment>
- <comment xml:lang="ro">Font Speedo</comment>
- <comment xml:lang="ru">Шрифт Speedo</comment>
- <comment xml:lang="sk">Písmo Speedo</comment>
- <comment xml:lang="sl">Datoteka pisave Speedo</comment>
- <comment xml:lang="sq">Gërma Speedo</comment>
- <comment xml:lang="sr">Спидо слова</comment>
- <comment xml:lang="sv">Speedo-typsnitt</comment>
- <comment xml:lang="tr">Speedo fontu</comment>
- <comment xml:lang="uk">шрифт Speedo</comment>
- <comment xml:lang="vi">Phông chữ Speedo</comment>
- <comment xml:lang="zh_CN">Speedo 字体</comment>
<comment xml:lang="zh_TW">Speedo 字型</comment>
+ <comment xml:lang="zh_CN">Speedo 字体</comment>
+ <comment xml:lang="vi">Phông chữ Speedo</comment>
+ <comment xml:lang="uk">шрифт Speedo</comment>
+ <comment xml:lang="tr">Speedo yazı tipi</comment>
+ <comment xml:lang="sv">Speedo-typsnitt</comment>
+ <comment xml:lang="sr">Спидо слова</comment>
+ <comment xml:lang="sq">shkronja Speedo</comment>
+ <comment xml:lang="sl">Datoteka pisave Speedo</comment>
+ <comment xml:lang="si">ස්පීඩෝ අකුරු</comment>
+ <comment xml:lang="sk">Písmo Speedo</comment>
+ <comment xml:lang="ru">Шрифт Speedo</comment>
+ <comment xml:lang="ro">Font Speedo</comment>
+ <comment xml:lang="pt_BR">Fonte Speedo</comment>
+ <comment xml:lang="pt">letra Speedo</comment>
+ <comment xml:lang="pl">Czcionka Speedo</comment>
+ <comment xml:lang="oc">poliça Speedo</comment>
+ <comment xml:lang="nn">Speedo-skrifttype</comment>
+ <comment xml:lang="nl">Speedo-lettertype</comment>
+ <comment xml:lang="nb">Speedo-skrifttype</comment>
+ <comment xml:lang="ms">Font Speedo</comment>
+ <comment xml:lang="lv">Speedo fonts</comment>
+ <comment xml:lang="lt">Speedo šriftas</comment>
+ <comment xml:lang="ko">Speedo 글꼴</comment>
+ <comment xml:lang="kk">Speedo қарібі</comment>
+ <comment xml:lang="ja">Speedo フォント</comment>
+ <comment xml:lang="it">Carattere Speedo</comment>
+ <comment xml:lang="is">Speedo letur</comment>
+ <comment xml:lang="id">Fonta Speedo</comment>
+ <comment xml:lang="ia">Typo de litteras Speedo</comment>
+ <comment xml:lang="hu">Speedo-betűkészlet</comment>
+ <comment xml:lang="hr">Speedo font</comment>
+ <comment xml:lang="he">גופן של Speedo</comment>
+ <comment xml:lang="gl">tipo de letra Speedo</comment>
+ <comment xml:lang="ga">cló Speedo</comment>
+ <comment xml:lang="fur">caratar Speedo</comment>
+ <comment xml:lang="fr">police Speedo</comment>
+ <comment xml:lang="fo">Speedo stavasnið</comment>
+ <comment xml:lang="fi">Speedo-fontti</comment>
+ <comment xml:lang="eu">Speedo letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra de Speedo</comment>
+ <comment xml:lang="eo">Speedo-tiparo</comment>
+ <comment xml:lang="en_GB">Speedo font</comment>
+ <comment xml:lang="el">Γραμματοσειρά Speedo</comment>
+ <comment xml:lang="de">Speedo-Schrift</comment>
+ <comment xml:lang="da">Speedoskrifttype</comment>
+ <comment xml:lang="cy">Ffont Speedo</comment>
+ <comment xml:lang="cs">font Speedo</comment>
+ <comment xml:lang="ca">lletra Speedo</comment>
+ <comment xml:lang="bg">Шрифт — Speedo</comment>
+ <comment xml:lang="be@latin">Šryft Speedo</comment>
+ <comment xml:lang="be">шрыфт Speedo</comment>
+ <comment xml:lang="az">Speedo yazı növü</comment>
+ <comment xml:lang="ar">خط Speedo</comment>
+ <comment xml:lang="af">Speedo-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="D1.0\015" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="D1.0\015" offset="0"/>
</magic>
<glob pattern="*.spd"/>
</mime-type>
<mime-type type="application/x-font-sunos-news">
<comment>SunOS News font</comment>
- <comment xml:lang="ar">خط SunOS News</comment>
- <comment xml:lang="az">SunOS News yazı növü</comment>
- <comment xml:lang="be@latin">Šryft SunOS News</comment>
- <comment xml:lang="bg">Шрифт — SunOS News</comment>
- <comment xml:lang="ca">lletra News de SunOS</comment>
- <comment xml:lang="cs">font SunOS News</comment>
- <comment xml:lang="cy">Ffont SunOS News</comment>
- <comment xml:lang="da">SunOS News-skrifttype</comment>
- <comment xml:lang="de">SunOS-News-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά SunOS News</comment>
- <comment xml:lang="en_GB">SunOS News font</comment>
- <comment xml:lang="eo">tiparo de SunOS News</comment>
- <comment xml:lang="es">tipo de letra para NeWS de SunOS</comment>
- <comment xml:lang="eu">SunOs News letra-tipoa</comment>
- <comment xml:lang="fi">SunOS News -fontti</comment>
- <comment xml:lang="fo">SunOS News stavasnið</comment>
- <comment xml:lang="fr">police SunOS News</comment>
- <comment xml:lang="ga">cló SunOS News</comment>
- <comment xml:lang="gl">tipo de letra SunOS News</comment>
- <comment xml:lang="he">גופן של SunOS News</comment>
- <comment xml:lang="hr">SunOS News slovo</comment>
- <comment xml:lang="hu">SunOS News-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras SunOS News</comment>
- <comment xml:lang="id">Fonta SunOS News</comment>
- <comment xml:lang="it">Carattere SunOS News</comment>
- <comment xml:lang="ja">SunOS News フォント</comment>
- <comment xml:lang="kk">SunOS News қарібі</comment>
- <comment xml:lang="ko">SunOS News 글꼴</comment>
- <comment xml:lang="lt">SunOS News šriftas</comment>
- <comment xml:lang="lv">SunOS News fonts</comment>
- <comment xml:lang="ms">Font News SunOS</comment>
- <comment xml:lang="nb">SunOS News-skrifttype</comment>
- <comment xml:lang="nl">SunOS News-lettertype</comment>
- <comment xml:lang="nn">SunOS NEWS-skrifttype</comment>
- <comment xml:lang="oc">poliça SunOS News</comment>
- <comment xml:lang="pl">Czcionka SunOS News</comment>
- <comment xml:lang="pt">letra SunOS News</comment>
- <comment xml:lang="pt_BR">Fonte SunOS News</comment>
- <comment xml:lang="ro">Font SunOS News</comment>
- <comment xml:lang="ru">Шрифт SunOS News</comment>
- <comment xml:lang="sk">Písmo SunOS News</comment>
- <comment xml:lang="sl">Datoteka pisave SunOS News</comment>
- <comment xml:lang="sq">Gërma SunOS News</comment>
- <comment xml:lang="sr">слова СанОС Њуза</comment>
- <comment xml:lang="sv">SunOS News-typsnitt</comment>
- <comment xml:lang="tr">SunOS News yazı tipi</comment>
- <comment xml:lang="uk">шрифт SunOS News</comment>
- <comment xml:lang="vi">Phông chữ SunOS News</comment>
- <comment xml:lang="zh_CN">SunOS News 字体</comment>
<comment xml:lang="zh_TW">SunOS News 字型</comment>
+ <comment xml:lang="zh_CN">SunOS News 字体</comment>
+ <comment xml:lang="vi">Phông chữ SunOS News</comment>
+ <comment xml:lang="uk">шрифт SunOS News</comment>
+ <comment xml:lang="tr">SunOS News yazı tipi</comment>
+ <comment xml:lang="sv">SunOS News-typsnitt</comment>
+ <comment xml:lang="sr">слова СанОС Њуза</comment>
+ <comment xml:lang="sq">shkronja SunOS News</comment>
+ <comment xml:lang="sl">Datoteka pisave SunOS News</comment>
+ <comment xml:lang="si">SunOS News අකුරු</comment>
+ <comment xml:lang="sk">Písmo SunOS News</comment>
+ <comment xml:lang="ru">Шрифт SunOS News</comment>
+ <comment xml:lang="ro">Font SunOS News</comment>
+ <comment xml:lang="pt_BR">Fonte SunOS News</comment>
+ <comment xml:lang="pt">letra SunOS News</comment>
+ <comment xml:lang="pl">Czcionka SunOS News</comment>
+ <comment xml:lang="oc">poliça SunOS News</comment>
+ <comment xml:lang="nn">SunOS NEWS-skrifttype</comment>
+ <comment xml:lang="nl">SunOS News-lettertype</comment>
+ <comment xml:lang="nb">SunOS News-skrifttype</comment>
+ <comment xml:lang="ms">Font News SunOS</comment>
+ <comment xml:lang="lv">SunOS News fonts</comment>
+ <comment xml:lang="lt">SunOS News šriftas</comment>
+ <comment xml:lang="ko">SunOS News 글꼴</comment>
+ <comment xml:lang="kk">SunOS News қарібі</comment>
+ <comment xml:lang="ja">SunOS News フォント</comment>
+ <comment xml:lang="it">Carattere SunOS News</comment>
+ <comment xml:lang="is">SunOS News letur</comment>
+ <comment xml:lang="id">Fonta SunOS News</comment>
+ <comment xml:lang="ia">Typo de litteras SunOS News</comment>
+ <comment xml:lang="hu">SunOS News-betűkészlet</comment>
+ <comment xml:lang="hr">SunOS News font</comment>
+ <comment xml:lang="he">גופן של SunOS News</comment>
+ <comment xml:lang="gl">tipo de letra SunOS News</comment>
+ <comment xml:lang="ga">cló SunOS News</comment>
+ <comment xml:lang="fur">caratar SunOS News</comment>
+ <comment xml:lang="fr">police SunOS News</comment>
+ <comment xml:lang="fo">SunOS News stavasnið</comment>
+ <comment xml:lang="fi">SunOS News -fontti</comment>
+ <comment xml:lang="eu">SunOs News letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra para NeWS de SunOS</comment>
+ <comment xml:lang="eo">tiparo de SunOS News</comment>
+ <comment xml:lang="en_GB">SunOS News font</comment>
+ <comment xml:lang="el">Γραμματοσειρά SunOS News</comment>
+ <comment xml:lang="de">SunOS-NeWS-Schrift</comment>
+ <comment xml:lang="da">SunOS News-skrifttype</comment>
+ <comment xml:lang="cy">Ffont SunOS News</comment>
+ <comment xml:lang="cs">font SunOS News</comment>
+ <comment xml:lang="ca">lletra News de SunOS</comment>
+ <comment xml:lang="bg">Шрифт — SunOS News</comment>
+ <comment xml:lang="be@latin">Šryft SunOS News</comment>
+ <comment xml:lang="be">шрыфт SunOS News</comment>
+ <comment xml:lang="az">SunOS News yazı növü</comment>
+ <comment xml:lang="ar">خط SunOS News</comment>
+ <comment xml:lang="af">SunOS News-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="StartFont" type="string" offset="0"/>
- <match value="\x13\x7A\x29" type="string" offset="0"/>
- <match value="\x13\x7A\x2B" type="string" offset="8"/>
+ <magic>
+ <match type="string" value="StartFont" offset="0"/>
+ <match type="string" value="\x13\x7A\x29" offset="0"/>
+ <match type="string" value="\x13\x7A\x2B" offset="8"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/font-tdpfr">
+ <comment>TDPFR font</comment>
+ <comment xml:lang="uk">шрифт TDPFR</comment>
+ <comment xml:lang="sv">TDPFR-typsnitt</comment>
+ <comment xml:lang="ru">Шрифт TDPFR</comment>
+ <comment xml:lang="pt_BR">Fonte TDPFR</comment>
+ <comment xml:lang="pl">Czcionka TDPFR</comment>
+ <comment xml:lang="it">Carattere TDPFR</comment>
+ <comment xml:lang="gl">Tipo de letra TDPFR</comment>
+ <comment xml:lang="eu">TDPFR letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra TDPFR</comment>
+ <comment xml:lang="de">TDPFR-Schrift</comment>
+ <comment xml:lang="be">шрыфт TDPFR</comment>
+ <acronym>TDPFR</acronym>
+ <expanded-acronym>TrueDoc Portable Font Resource</expanded-acronym>
+ <generic-icon name="font-x-generic"/>
+ <magic>
+ <match type="big32" value="0x50465230" offset="0"/>
+ <match type="big32" value="0x50465231" offset="0"/>
</magic>
+ <glob pattern="*.pfr"/>
+ <alias type="application/vnd.truedoc"/>
</mime-type>
<mime-type type="application/x-font-tex">
<comment>TeX font</comment>
- <comment xml:lang="ar">خط TeX</comment>
- <comment xml:lang="az">TeX yazı növü</comment>
- <comment xml:lang="be@latin">Šryft TeX</comment>
- <comment xml:lang="bg">Шрифт — TeX</comment>
- <comment xml:lang="ca">lletra TeX</comment>
- <comment xml:lang="cs">font TeX</comment>
- <comment xml:lang="cy">Ffont TeX</comment>
- <comment xml:lang="da">TeX-skrifttype</comment>
- <comment xml:lang="de">TeX-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά TeX</comment>
- <comment xml:lang="en_GB">TeX font</comment>
- <comment xml:lang="eo">TeX-tiparo</comment>
- <comment xml:lang="es">tipo de letra de TeX</comment>
- <comment xml:lang="eu">TeX letra-tipoa</comment>
- <comment xml:lang="fi">TeX-fontti</comment>
- <comment xml:lang="fo">TeX stavasnið</comment>
- <comment xml:lang="fr">police TeX</comment>
- <comment xml:lang="ga">cló TeX</comment>
- <comment xml:lang="gl">tipo de letra de TeX</comment>
- <comment xml:lang="he">גופן TeX</comment>
- <comment xml:lang="hr">TeX slovo</comment>
- <comment xml:lang="hu">TeX-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras TeX</comment>
- <comment xml:lang="id">Fonta TeX</comment>
- <comment xml:lang="it">Carattere TeX</comment>
- <comment xml:lang="ja">TeX フォント</comment>
- <comment xml:lang="kk">TeX қарібі</comment>
- <comment xml:lang="ko">TeX 글꼴</comment>
- <comment xml:lang="lt">TeX šriftas</comment>
- <comment xml:lang="lv">TeX fonts</comment>
- <comment xml:lang="ms">Font TeX</comment>
- <comment xml:lang="nb">TeX-skrift</comment>
- <comment xml:lang="nl">TeX-lettertype</comment>
- <comment xml:lang="nn">TeX-skrifttype</comment>
- <comment xml:lang="oc">poliça TeX</comment>
- <comment xml:lang="pl">Czcionka TeX</comment>
- <comment xml:lang="pt">letra TeX</comment>
- <comment xml:lang="pt_BR">Fonte TeX</comment>
- <comment xml:lang="ro">Font TeX</comment>
- <comment xml:lang="ru">Шрифт TeX</comment>
- <comment xml:lang="sk">Písmo TeX</comment>
- <comment xml:lang="sl">Datoteka pisave TeX</comment>
- <comment xml:lang="sq">Gërma TeX</comment>
- <comment xml:lang="sr">ТеКс слова</comment>
- <comment xml:lang="sv">TeX-typsnitt</comment>
- <comment xml:lang="tr">TeX fontu</comment>
- <comment xml:lang="uk">шрифт TeX</comment>
- <comment xml:lang="vi">Phông chữ TeX</comment>
- <comment xml:lang="zh_CN">TeX 字体</comment>
<comment xml:lang="zh_TW">TeX 字型</comment>
+ <comment xml:lang="zh_CN">TeX 字体</comment>
+ <comment xml:lang="vi">Phông chữ TeX</comment>
+ <comment xml:lang="uk">шрифт TeX</comment>
+ <comment xml:lang="tr">TeX yazı tipi</comment>
+ <comment xml:lang="sv">TeX-typsnitt</comment>
+ <comment xml:lang="sr">ТеКс слова</comment>
+ <comment xml:lang="sq">shkronja TeX</comment>
+ <comment xml:lang="sl">Datoteka pisave TeX</comment>
+ <comment xml:lang="si">TeX අකුරු</comment>
+ <comment xml:lang="sk">Písmo TeX</comment>
+ <comment xml:lang="ru">Шрифт TeX</comment>
+ <comment xml:lang="ro">Font TeX</comment>
+ <comment xml:lang="pt_BR">Fonte TeX</comment>
+ <comment xml:lang="pt">letra TeX</comment>
+ <comment xml:lang="pl">Czcionka TeX</comment>
+ <comment xml:lang="oc">poliça TeX</comment>
+ <comment xml:lang="nn">TeX-skrifttype</comment>
+ <comment xml:lang="nl">TeX-lettertype</comment>
+ <comment xml:lang="nb">TeX-skrift</comment>
+ <comment xml:lang="ms">Font TeX</comment>
+ <comment xml:lang="lv">TeX fonts</comment>
+ <comment xml:lang="lt">TeX šriftas</comment>
+ <comment xml:lang="ko">TeX 글꼴</comment>
+ <comment xml:lang="kk">TeX қарібі</comment>
+ <comment xml:lang="ja">TeX フォント</comment>
+ <comment xml:lang="it">Carattere TeX</comment>
+ <comment xml:lang="is">TeX letur</comment>
+ <comment xml:lang="id">Fonta TeX</comment>
+ <comment xml:lang="ia">Typo de litteras TeX</comment>
+ <comment xml:lang="hu">TeX-betűkészlet</comment>
+ <comment xml:lang="hr">TeX font</comment>
+ <comment xml:lang="he">גופן TeX</comment>
+ <comment xml:lang="gl">tipo de letra de TeX</comment>
+ <comment xml:lang="ga">cló TeX</comment>
+ <comment xml:lang="fur">caratar TeX</comment>
+ <comment xml:lang="fr">police TeX</comment>
+ <comment xml:lang="fo">TeX stavasnið</comment>
+ <comment xml:lang="fi">TeX-fontti</comment>
+ <comment xml:lang="eu">TeX letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra de TeX</comment>
+ <comment xml:lang="eo">TeX-tiparo</comment>
+ <comment xml:lang="en_GB">TeX font</comment>
+ <comment xml:lang="el">Γραμματοσειρά TeX</comment>
+ <comment xml:lang="de">TeX-Schrift</comment>
+ <comment xml:lang="da">TeX-skrifttype</comment>
+ <comment xml:lang="cy">Ffont TeX</comment>
+ <comment xml:lang="cs">font TeX</comment>
+ <comment xml:lang="ca">lletra TeX</comment>
+ <comment xml:lang="bg">Шрифт — TeX</comment>
+ <comment xml:lang="be@latin">Šryft TeX</comment>
+ <comment xml:lang="be">шрыфт TeX</comment>
+ <comment xml:lang="az">TeX yazı növü</comment>
+ <comment xml:lang="ar">خط TeX</comment>
+ <comment xml:lang="af">TeX-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="\367\203" type="string" offset="0"/>
- <match value="\367\131" type="string" offset="0"/>
- <match value="\367\312" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\367\203" offset="0"/>
+ <match type="string" value="\367\131" offset="0"/>
+ <match type="string" value="\367\312" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-font-tex-tfm">
<comment>TeX font metrics</comment>
- <comment xml:lang="ar">مقاييس خط TeX</comment>
- <comment xml:lang="az">TeX yazı növü metrikləri</comment>
- <comment xml:lang="be@latin">Metryka šryftu TeX</comment>
- <comment xml:lang="bg">Шрифтова метрика — TeX</comment>
- <comment xml:lang="ca">mètrica de lletra de TeX</comment>
- <comment xml:lang="cs">metrika fontu TeX</comment>
- <comment xml:lang="cy">Metrigau Ffont TeX</comment>
- <comment xml:lang="da">TeX-skrifttypeinformation</comment>
- <comment xml:lang="de">TeX-Schriftmetriken</comment>
- <comment xml:lang="el">Μετρικά γραμματοσειράς TeX</comment>
- <comment xml:lang="en_GB">TeX font metrics</comment>
- <comment xml:lang="eo">metrikoj de TeX-tiparo</comment>
- <comment xml:lang="es">métricas tipográficas de TeX</comment>
- <comment xml:lang="eu">TeX letra-tipoen neurriak</comment>
- <comment xml:lang="fi">TeX-fonttimitat</comment>
- <comment xml:lang="fr">métriques de police TeX</comment>
- <comment xml:lang="ga">meadarachtaí cló TeX</comment>
- <comment xml:lang="gl">Métricas de tipo de letra de TeX</comment>
- <comment xml:lang="he">ממדי גופן של TeX</comment>
- <comment xml:lang="hr">TeX mjere slova</comment>
- <comment xml:lang="hu">TeX-betűmetrika</comment>
- <comment xml:lang="ia">Metricas de typo de litteras TeX</comment>
- <comment xml:lang="id">Fonta metrik TeX</comment>
- <comment xml:lang="it">Metriche tipo carattere TeX</comment>
- <comment xml:lang="ja">TeX フォントメトリック</comment>
- <comment xml:lang="kk">TeX қаріп метрикалары</comment>
- <comment xml:lang="ko">TeX 글꼴 메트릭</comment>
- <comment xml:lang="lt">TeX šriftų metrika</comment>
- <comment xml:lang="lv">TeX fonta metrikas</comment>
- <comment xml:lang="ms">Metrik font TeX</comment>
- <comment xml:lang="nb">TeX skrifttypemetrikk</comment>
- <comment xml:lang="nl">TeX-lettertype-metrieken</comment>
- <comment xml:lang="nn">TeX skrifttypemetrikk</comment>
- <comment xml:lang="oc">metricas de poliça TeX</comment>
- <comment xml:lang="pl">Metryki czcionki TeX</comment>
- <comment xml:lang="pt">métricas de letra TeX</comment>
- <comment xml:lang="pt_BR">Métrica de fonte TeX</comment>
- <comment xml:lang="ro">Dimensiuni font TeX</comment>
- <comment xml:lang="ru">Метрика шрифта TeX</comment>
- <comment xml:lang="sk">Metrika písma TeX</comment>
- <comment xml:lang="sl">Matrika pisave Tex</comment>
- <comment xml:lang="sq">Gërma TeX metrics</comment>
- <comment xml:lang="sr">метрика слова ТеКс-а</comment>
- <comment xml:lang="sv">TeX-typsnittsmetrik</comment>
- <comment xml:lang="tr">TeX yazı tipi ölçüleri</comment>
- <comment xml:lang="uk">метрики шрифту TeX</comment>
- <comment xml:lang="vi">Cách đo phông chữ TeX</comment>
- <comment xml:lang="zh_CN">TeX 字体规格</comment>
<comment xml:lang="zh_TW">TeX 字型描述檔</comment>
+ <comment xml:lang="zh_CN">TeX 字体规格</comment>
+ <comment xml:lang="vi">Cách đo phông chữ TeX</comment>
+ <comment xml:lang="uk">метрики шрифту TeX</comment>
+ <comment xml:lang="tr">TeX yazı tipi ölçüleri</comment>
+ <comment xml:lang="sv">TeX-typsnittsmetrik</comment>
+ <comment xml:lang="sr">метрика слова ТеКс-а</comment>
+ <comment xml:lang="sq">vlera shkronjash TeX</comment>
+ <comment xml:lang="sl">Matrika pisave Tex</comment>
+ <comment xml:lang="si">TeX අකුරු ප්‍රමිතික</comment>
+ <comment xml:lang="sk">Metrika písma TeX</comment>
+ <comment xml:lang="ru">Метрика шрифта TeX</comment>
+ <comment xml:lang="ro">Dimensiuni font TeX</comment>
+ <comment xml:lang="pt_BR">Métrica de fonte TeX</comment>
+ <comment xml:lang="pt">métricas de letra TeX</comment>
+ <comment xml:lang="pl">Metryki czcionki TeX</comment>
+ <comment xml:lang="oc">metricas de poliça TeX</comment>
+ <comment xml:lang="nn">TeX skrifttypemetrikk</comment>
+ <comment xml:lang="nl">TeX-lettertype-metrieken</comment>
+ <comment xml:lang="nb">TeX skrifttypemetrikk</comment>
+ <comment xml:lang="ms">Metrik font TeX</comment>
+ <comment xml:lang="lv">TeX fonta metrikas</comment>
+ <comment xml:lang="lt">TeX šriftų metrika</comment>
+ <comment xml:lang="ko">TeX 글꼴 메트릭</comment>
+ <comment xml:lang="kk">TeX қаріп метрикалары</comment>
+ <comment xml:lang="ja">TeX フォントメトリック</comment>
+ <comment xml:lang="it">Metriche tipo carattere TeX</comment>
+ <comment xml:lang="is">TeX leturupplýsingar</comment>
+ <comment xml:lang="id">Fonta metrik TeX</comment>
+ <comment xml:lang="ia">Metricas de typo de litteras TeX</comment>
+ <comment xml:lang="hu">TeX-betűmetrika</comment>
+ <comment xml:lang="hr">Metrika TeX fonta</comment>
+ <comment xml:lang="he">ממדי גופן של TeX</comment>
+ <comment xml:lang="gl">Métricas de tipo de letra de TeX</comment>
+ <comment xml:lang="ga">meadarachtaí cló TeX</comment>
+ <comment xml:lang="fur">metrichis caratar TeX</comment>
+ <comment xml:lang="fr">métriques de police TeX</comment>
+ <comment xml:lang="fi">TeX-fonttimitat</comment>
+ <comment xml:lang="eu">TeX letra-tipoen neurriak</comment>
+ <comment xml:lang="es">métricas tipográficas de TeX</comment>
+ <comment xml:lang="eo">metrikoj de TeX-tiparo</comment>
+ <comment xml:lang="en_GB">TeX font metrics</comment>
+ <comment xml:lang="el">Μετρικά γραμματοσειράς TeX</comment>
+ <comment xml:lang="de">TeX-Schriftmetriken</comment>
+ <comment xml:lang="da">TeX-skrifttypeinformation</comment>
+ <comment xml:lang="cy">Metrigau Ffont TeX</comment>
+ <comment xml:lang="cs">metrika fontu TeX</comment>
+ <comment xml:lang="ca">mètrica de lletra de TeX</comment>
+ <comment xml:lang="bg">Шрифтова метрика — TeX</comment>
+ <comment xml:lang="be@latin">Metryka šryftu TeX</comment>
+ <comment xml:lang="be">метрыкі шрыфту TeX</comment>
+ <comment xml:lang="az">TeX yazı növü metrikləri</comment>
+ <comment xml:lang="ar">مقاييس خط TeX</comment>
+ <comment xml:lang="af">TeX-skriftipeafmetings</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="\000\021" type="string" offset="2"/>
- <match value="\000\022" type="string" offset="2"/>
+ <magic>
+ <match type="string" value="\000\021" offset="2"/>
+ <match type="string" value="\000\022" offset="2"/>
</magic>
</mime-type>
<mime-type type="font/ttf">
<comment>TrueType font</comment>
- <comment xml:lang="ar">خط TrueType</comment>
- <comment xml:lang="be@latin">Šryft TrueType</comment>
- <comment xml:lang="bg">Шрифт — TrueType</comment>
- <comment xml:lang="ca">lletra TrueType</comment>
- <comment xml:lang="cs">font TrueType</comment>
- <comment xml:lang="da">TrueType-skrifttype</comment>
- <comment xml:lang="de">TrueType-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά TrueType</comment>
- <comment xml:lang="en_GB">TrueType font</comment>
- <comment xml:lang="eo">TrueType-tiparo</comment>
- <comment xml:lang="es">tipo de letra TrueType</comment>
- <comment xml:lang="eu">TrueType letra-tipoa</comment>
- <comment xml:lang="fi">TrueType-fontti</comment>
- <comment xml:lang="fo">TrueType stavasnið</comment>
- <comment xml:lang="fr">police Truetype</comment>
- <comment xml:lang="ga">cló TrueType</comment>
- <comment xml:lang="gl">tipo de letra TrueType</comment>
- <comment xml:lang="he">גופן מסוג TrueType</comment>
- <comment xml:lang="hr">TrueType slovo</comment>
- <comment xml:lang="hu">TrueType-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras TrueType</comment>
- <comment xml:lang="id">Fonta TrueType</comment>
- <comment xml:lang="it">Carattere TrueType</comment>
- <comment xml:lang="ja">TrueType フォント</comment>
- <comment xml:lang="kk">TrueType қарібі</comment>
- <comment xml:lang="ko">트루타입 글꼴</comment>
- <comment xml:lang="lt">TrueType šriftas</comment>
- <comment xml:lang="lv">TrueType fonts</comment>
- <comment xml:lang="ms">Font TrueType</comment>
- <comment xml:lang="nb">TrueType-skrift</comment>
- <comment xml:lang="nl">TrueType-lettertype</comment>
- <comment xml:lang="nn">TrueType-skrifttype</comment>
- <comment xml:lang="oc">poliça Truetype</comment>
- <comment xml:lang="pl">Czcionka TrueType</comment>
- <comment xml:lang="pt">letra TrueType</comment>
- <comment xml:lang="pt_BR">Fonte TrueType</comment>
- <comment xml:lang="ro">Font TrueType</comment>
- <comment xml:lang="ru">Шрифт TrueType</comment>
- <comment xml:lang="sk">Písmo TrueType</comment>
- <comment xml:lang="sl">Datoteka pisave TrueType</comment>
- <comment xml:lang="sq">Lloj gërme TrueType</comment>
- <comment xml:lang="sr">Трутајп слова</comment>
- <comment xml:lang="sv">Truetype-typsnitt</comment>
- <comment xml:lang="tr">TrueType fontu</comment>
- <comment xml:lang="uk">шрифт TrueType</comment>
- <comment xml:lang="vi">Phông chữ TrueType</comment>
- <comment xml:lang="zh_CN">TrueType 字体</comment>
<comment xml:lang="zh_TW">TrueType 字型</comment>
+ <comment xml:lang="zh_CN">TrueType 字体</comment>
+ <comment xml:lang="vi">Phông chữ TrueType</comment>
+ <comment xml:lang="uk">шрифт TrueType</comment>
+ <comment xml:lang="tr">TrueType yazı tipi</comment>
+ <comment xml:lang="sv">Truetype-typsnitt</comment>
+ <comment xml:lang="sr">Трутајп слова</comment>
+ <comment xml:lang="sq">shkronja TrueType</comment>
+ <comment xml:lang="sl">Datoteka pisave TrueType</comment>
+ <comment xml:lang="si">TrueType අකුරු</comment>
+ <comment xml:lang="sk">Písmo TrueType</comment>
+ <comment xml:lang="ru">Шрифт TrueType</comment>
+ <comment xml:lang="ro">Font TrueType</comment>
+ <comment xml:lang="pt_BR">Fonte TrueType</comment>
+ <comment xml:lang="pt">letra TrueType</comment>
+ <comment xml:lang="pl">Czcionka TrueType</comment>
+ <comment xml:lang="oc">poliça Truetype</comment>
+ <comment xml:lang="nn">TrueType-skrifttype</comment>
+ <comment xml:lang="nl">TrueType-lettertype</comment>
+ <comment xml:lang="nb">TrueType-skrift</comment>
+ <comment xml:lang="ms">Font TrueType</comment>
+ <comment xml:lang="lv">TrueType fonts</comment>
+ <comment xml:lang="lt">TrueType šriftas</comment>
+ <comment xml:lang="ko">트루타입 글꼴</comment>
+ <comment xml:lang="kk">TrueType қарібі</comment>
+ <comment xml:lang="ja">TrueType フォント</comment>
+ <comment xml:lang="it">Carattere TrueType</comment>
+ <comment xml:lang="is">TrueType letur</comment>
+ <comment xml:lang="id">Fonta TrueType</comment>
+ <comment xml:lang="ia">Typo de litteras TrueType</comment>
+ <comment xml:lang="hu">TrueType-betűkészlet</comment>
+ <comment xml:lang="hr">TrueType font</comment>
+ <comment xml:lang="he">גופן מסוג TrueType</comment>
+ <comment xml:lang="gl">tipo de letra TrueType</comment>
+ <comment xml:lang="ga">cló TrueType</comment>
+ <comment xml:lang="fur">caratar TrueType</comment>
+ <comment xml:lang="fr">police Truetype</comment>
+ <comment xml:lang="fo">TrueType stavasnið</comment>
+ <comment xml:lang="fi">TrueType-fontti</comment>
+ <comment xml:lang="eu">TrueType letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra TrueType</comment>
+ <comment xml:lang="eo">TrueType-tiparo</comment>
+ <comment xml:lang="en_GB">TrueType font</comment>
+ <comment xml:lang="el">Γραμματοσειρά TrueType</comment>
+ <comment xml:lang="de">TrueType-Schrift</comment>
+ <comment xml:lang="da">TrueType-skrifttype</comment>
+ <comment xml:lang="cs">font TrueType</comment>
+ <comment xml:lang="ca">lletra TrueType</comment>
+ <comment xml:lang="bg">Шрифт — TrueType</comment>
+ <comment xml:lang="be@latin">Šryft TrueType</comment>
+ <comment xml:lang="be">шрыфт TrueType</comment>
+ <comment xml:lang="ar">خط TrueType</comment>
+ <comment xml:lang="af">TrueType-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="FFIL" type="string" offset="0"/>
- <match value="FFIL" type="string" offset="65"/>
- <match value="\000\001\000\000\000" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="FFIL" offset="0"/>
+ <match type="string" value="FFIL" offset="65"/>
+ <match type="string" value="\000\001\000\000\000" offset="0"/>
</magic>
<glob pattern="*.ttf"/>
<alias type="application/x-font-ttf"/>
</mime-type>
<mime-type type="font/collection">
<comment>Font collection</comment>
- <comment xml:lang="ca">ccol·lecció de lletres</comment>
- <comment xml:lang="cs">kolekce fontů</comment>
- <comment xml:lang="de">Schriftsammlung</comment>
- <comment xml:lang="en_GB">Font collection</comment>
- <comment xml:lang="es">colección tipográfica</comment>
- <comment xml:lang="fi">Fonttikokoelma</comment>
- <comment xml:lang="hr">Kolekcija slova</comment>
- <comment xml:lang="hu">Betűkészlet-gyűjtemény</comment>
- <comment xml:lang="id">Koleksi fonta</comment>
- <comment xml:lang="it">Raccolta di caratteri</comment>
- <comment xml:lang="kk">Қаріптер жинағы</comment>
- <comment xml:lang="ko">글꼴 모음</comment>
- <comment xml:lang="pl">Kolekcja czcionek</comment>
- <comment xml:lang="pt_BR">coleção de fontes</comment>
- <comment xml:lang="ru">Коллекция шрифтов</comment>
- <comment xml:lang="sk">Zbierka písiem</comment>
- <comment xml:lang="sv">Typsnittssamling</comment>
- <comment xml:lang="uk">збірка шрифтів</comment>
- <comment xml:lang="zh_CN">字体集</comment>
<comment xml:lang="zh_TW">字型集</comment>
+ <comment xml:lang="zh_CN">字体集</comment>
+ <comment xml:lang="uk">збірка шрифтів</comment>
+ <comment xml:lang="tr">Yazı tipi derlemi</comment>
+ <comment xml:lang="sv">Typsnittssamling</comment>
+ <comment xml:lang="sq">koleksion shkronjash</comment>
+ <comment xml:lang="sl">Zbirka pisav</comment>
+ <comment xml:lang="si">අකුරු එකතුව</comment>
+ <comment xml:lang="sk">Zbierka písiem</comment>
+ <comment xml:lang="ru">Коллекция шрифтов</comment>
+ <comment xml:lang="pt_BR">Coleção de fontes</comment>
+ <comment xml:lang="pt">coleção de letras</comment>
+ <comment xml:lang="pl">Kolekcja czcionek</comment>
+ <comment xml:lang="nl">Lettertypeverzameling</comment>
+ <comment xml:lang="ko">글꼴 모음</comment>
+ <comment xml:lang="kk">Қаріптер жинағы</comment>
+ <comment xml:lang="ja">フォントコレクション</comment>
+ <comment xml:lang="it">Raccolta di caratteri</comment>
+ <comment xml:lang="is">Letursafn</comment>
+ <comment xml:lang="id">Koleksi fonta</comment>
+ <comment xml:lang="hu">Betűkészlet-gyűjtemény</comment>
+ <comment xml:lang="hr">Zbirka fontova</comment>
+ <comment xml:lang="he">אוסף גופנים</comment>
+ <comment xml:lang="gl">Colección de tipo de letra</comment>
+ <comment xml:lang="ga">bailiúchán clónna</comment>
+ <comment xml:lang="fur">colezion di caratars</comment>
+ <comment xml:lang="fr">Collection de polices</comment>
+ <comment xml:lang="fi">Fonttikokoelma</comment>
+ <comment xml:lang="eu">Letra-tipo bilduma</comment>
+ <comment xml:lang="es">colección tipográfica</comment>
+ <comment xml:lang="en_GB">Font collection</comment>
+ <comment xml:lang="de">Schriftsammlung</comment>
+ <comment xml:lang="da">Skrifttypesamling</comment>
+ <comment xml:lang="cs">kolekce fontů</comment>
+ <comment xml:lang="ca">ccol·lecció de lletres</comment>
+ <comment xml:lang="bg">Шрифтова колекция</comment>
+ <comment xml:lang="be">калекцыя шрыфтоў</comment>
+ <comment xml:lang="ar">تجميعة خط</comment>
+ <comment xml:lang="af">Skriftipeversameling</comment>
<generic-icon name="font-x-generic"/>
<glob pattern="*.ttc"/>
</mime-type>
<mime-type type="application/x-font-ttx">
<comment>TrueType XML font</comment>
- <comment xml:lang="ar">خط TrueType XML</comment>
- <comment xml:lang="be@latin">Šryft TrueType XML</comment>
- <comment xml:lang="bg">Шрифт — TrueType XML</comment>
- <comment xml:lang="ca">lletra XML de TrueType</comment>
- <comment xml:lang="cs">font TrueType XML</comment>
- <comment xml:lang="da">TrueType XML-skrifttype</comment>
- <comment xml:lang="de">TrueType-XML-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά XML TrueType</comment>
- <comment xml:lang="en_GB">TrueType XML font</comment>
- <comment xml:lang="es">tipo de letra TrueType XML</comment>
- <comment xml:lang="eu">TrueType XML letra-tipoa</comment>
- <comment xml:lang="fi">TrueType-XML-fontti</comment>
- <comment xml:lang="fo">TrueType XML stavasnið</comment>
- <comment xml:lang="fr">police Truetype XML</comment>
- <comment xml:lang="ga">cló XML TrueType</comment>
- <comment xml:lang="gl">tipo de letra TrueType XML</comment>
- <comment xml:lang="he">גופן XML מסוג TrueType</comment>
- <comment xml:lang="hr">TrueType XML slovo</comment>
- <comment xml:lang="hu">TrueType XML betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras TrueType XML</comment>
- <comment xml:lang="id">Fonta TrueType XML</comment>
- <comment xml:lang="it">Carattere TrueType XML</comment>
- <comment xml:lang="ja">TrueType XML フォント</comment>
- <comment xml:lang="kk">TrueType XML қарібі</comment>
- <comment xml:lang="ko">트루타입 XML 글꼴</comment>
- <comment xml:lang="lt">TrueType XML šriftas</comment>
- <comment xml:lang="lv">TrueType XML fonts</comment>
- <comment xml:lang="nb">TrueType XML-skrift</comment>
- <comment xml:lang="nl">TrueType XML-lettertype</comment>
- <comment xml:lang="nn">TrueType XML-skrifttype</comment>
- <comment xml:lang="oc">poliça Truetype XML</comment>
- <comment xml:lang="pl">Czcionka TrueType XML</comment>
- <comment xml:lang="pt">letra TrueType XML</comment>
- <comment xml:lang="pt_BR">Fonte TrueType XML</comment>
- <comment xml:lang="ro">Font XML TrueType</comment>
- <comment xml:lang="ru">Шрифт TrueType XML</comment>
- <comment xml:lang="sk">Písmo TrueType XML</comment>
- <comment xml:lang="sl">Datoteka pisave TrueType XML</comment>
- <comment xml:lang="sq">Lloj gërme TrueType XML</comment>
- <comment xml:lang="sr">Трутајп ИксМЛ слова</comment>
- <comment xml:lang="sv">Truetype XML-typsnitt</comment>
- <comment xml:lang="tr">TrueType XML fontu</comment>
- <comment xml:lang="uk">шрифт TrueType XML</comment>
- <comment xml:lang="vi">Phông chữ XML TrueType</comment>
- <comment xml:lang="zh_CN">TrueType XML 字体</comment>
<comment xml:lang="zh_TW">TrueType XML 字型</comment>
+ <comment xml:lang="zh_CN">TrueType XML 字体</comment>
+ <comment xml:lang="vi">Phông chữ XML TrueType</comment>
+ <comment xml:lang="uk">шрифт TrueType XML</comment>
+ <comment xml:lang="tr">TrueType XML yazı tipi</comment>
+ <comment xml:lang="sv">Truetype XML-typsnitt</comment>
+ <comment xml:lang="sr">Трутајп ИксМЛ слова</comment>
+ <comment xml:lang="sq">shkronja TrueType XML</comment>
+ <comment xml:lang="sl">Datoteka pisave TrueType XML</comment>
+ <comment xml:lang="si">TrueType XML අකුරු</comment>
+ <comment xml:lang="sk">Písmo TrueType XML</comment>
+ <comment xml:lang="ru">Шрифт TrueType XML</comment>
+ <comment xml:lang="ro">Font XML TrueType</comment>
+ <comment xml:lang="pt_BR">Fonte TrueType XML</comment>
+ <comment xml:lang="pt">letra TrueType XML</comment>
+ <comment xml:lang="pl">Czcionka TrueType XML</comment>
+ <comment xml:lang="oc">poliça Truetype XML</comment>
+ <comment xml:lang="nn">TrueType XML-skrifttype</comment>
+ <comment xml:lang="nl">TrueType XML-lettertype</comment>
+ <comment xml:lang="nb">TrueType XML-skrift</comment>
+ <comment xml:lang="lv">TrueType XML fonts</comment>
+ <comment xml:lang="lt">TrueType XML šriftas</comment>
+ <comment xml:lang="ko">트루타입 XML 글꼴</comment>
+ <comment xml:lang="kk">TrueType XML қарібі</comment>
+ <comment xml:lang="ja">TrueType XML フォント</comment>
+ <comment xml:lang="it">Carattere TrueType XML</comment>
+ <comment xml:lang="is">TrueType XML letur</comment>
+ <comment xml:lang="id">Fonta TrueType XML</comment>
+ <comment xml:lang="ia">Typo de litteras TrueType XML</comment>
+ <comment xml:lang="hu">TrueType XML betűkészlet</comment>
+ <comment xml:lang="hr">TrueType XML font</comment>
+ <comment xml:lang="he">גופן XML מסוג TrueType</comment>
+ <comment xml:lang="gl">tipo de letra TrueType XML</comment>
+ <comment xml:lang="ga">cló XML TrueType</comment>
+ <comment xml:lang="fur">caratar TrueType XML</comment>
+ <comment xml:lang="fr">police Truetype XML</comment>
+ <comment xml:lang="fo">TrueType XML stavasnið</comment>
+ <comment xml:lang="fi">TrueType-XML-fontti</comment>
+ <comment xml:lang="eu">TrueType XML letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra TrueType XML</comment>
+ <comment xml:lang="en_GB">TrueType XML font</comment>
+ <comment xml:lang="el">Γραμματοσειρά XML TrueType</comment>
+ <comment xml:lang="de">TrueType-XML-Schrift</comment>
+ <comment xml:lang="da">TrueType XML-skrifttype</comment>
+ <comment xml:lang="cs">font TrueType XML</comment>
+ <comment xml:lang="ca">lletra XML de TrueType</comment>
+ <comment xml:lang="bg">Шрифт — TrueType XML</comment>
+ <comment xml:lang="be@latin">Šryft TrueType XML</comment>
+ <comment xml:lang="be">шрыфт TrueType XML</comment>
+ <comment xml:lang="ar">خط TrueType XML</comment>
+ <comment xml:lang="af">TrueType XML-skriftipe</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="&lt;ttFont sfntVersion=&quot;\\x00\\x01\\x00\\x00&quot; ttLibVersion=&quot;" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;ttFont sfntVersion=&quot;\\x00\\x01\\x00\\x00&quot; ttLibVersion=&quot;" offset="0:256"/>
</magic>
<glob pattern="*.ttx"/>
</mime-type>
<mime-type type="application/x-font-vfont">
<comment>V font</comment>
- <comment xml:lang="ar">خط V</comment>
- <comment xml:lang="az">V yazı növü</comment>
- <comment xml:lang="be@latin">Šryft V</comment>
- <comment xml:lang="bg">Шрифт — V</comment>
- <comment xml:lang="ca">lletra V</comment>
- <comment xml:lang="cs">font V</comment>
- <comment xml:lang="cy">Ffont V</comment>
- <comment xml:lang="da">V-skrifttype</comment>
- <comment xml:lang="de">V-Schrift</comment>
- <comment xml:lang="el">Γραμματοσειρά V</comment>
- <comment xml:lang="en_GB">V font</comment>
- <comment xml:lang="eo">V-tiparo</comment>
- <comment xml:lang="es">tipo de letra V</comment>
- <comment xml:lang="eu">V letra-tipoa</comment>
- <comment xml:lang="fi">V-fontti</comment>
- <comment xml:lang="fo">V stavasnið</comment>
- <comment xml:lang="fr">police V</comment>
- <comment xml:lang="ga">cló V</comment>
- <comment xml:lang="gl">tipo de letra V</comment>
- <comment xml:lang="he">גופן של V</comment>
- <comment xml:lang="hr">V slovo</comment>
- <comment xml:lang="hu">V-betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras V</comment>
- <comment xml:lang="id">Fonta V</comment>
- <comment xml:lang="it">Carattere V</comment>
- <comment xml:lang="ja">V フォント</comment>
- <comment xml:lang="kk">V font қарібі</comment>
- <comment xml:lang="ko">V 글꼴</comment>
- <comment xml:lang="lt">V šriftas</comment>
- <comment xml:lang="lv">V fonts</comment>
- <comment xml:lang="ms">Font V</comment>
- <comment xml:lang="nb">V-skrift</comment>
- <comment xml:lang="nl">V-lettertype</comment>
- <comment xml:lang="nn">V-skrifttype</comment>
- <comment xml:lang="oc">poliça V</comment>
- <comment xml:lang="pl">Czcionka V</comment>
- <comment xml:lang="pt">letra V</comment>
- <comment xml:lang="pt_BR">Fonte V</comment>
- <comment xml:lang="ro">Font V</comment>
- <comment xml:lang="ru">Шрифт V font</comment>
- <comment xml:lang="sk">Písmo V</comment>
- <comment xml:lang="sl">Datoteka pisave V</comment>
- <comment xml:lang="sq">Gërmë V</comment>
- <comment xml:lang="sr">В слова</comment>
- <comment xml:lang="sv">V-typsnitt</comment>
- <comment xml:lang="tr">V fontu</comment>
- <comment xml:lang="uk">V-шрифт</comment>
- <comment xml:lang="vi">Phông chữ V</comment>
- <comment xml:lang="zh_CN">V 字体</comment>
<comment xml:lang="zh_TW">V 字型</comment>
+ <comment xml:lang="zh_CN">V 字体</comment>
+ <comment xml:lang="vi">Phông chữ V</comment>
+ <comment xml:lang="uk">V-шрифт</comment>
+ <comment xml:lang="tr">V yazı tipi</comment>
+ <comment xml:lang="sv">V-typsnitt</comment>
+ <comment xml:lang="sr">В слова</comment>
+ <comment xml:lang="sq">shkronja V</comment>
+ <comment xml:lang="sl">Datoteka pisave V</comment>
+ <comment xml:lang="si">V අකුරු</comment>
+ <comment xml:lang="sk">Písmo V</comment>
+ <comment xml:lang="ru">V-шрифт</comment>
+ <comment xml:lang="ro">Font V</comment>
+ <comment xml:lang="pt_BR">Fonte V</comment>
+ <comment xml:lang="pt">letra V</comment>
+ <comment xml:lang="pl">Czcionka V</comment>
+ <comment xml:lang="oc">poliça V</comment>
+ <comment xml:lang="nn">V-skrifttype</comment>
+ <comment xml:lang="nl">V-lettertype</comment>
+ <comment xml:lang="nb">V-skrift</comment>
+ <comment xml:lang="ms">Font V</comment>
+ <comment xml:lang="lv">V fonts</comment>
+ <comment xml:lang="lt">V šriftas</comment>
+ <comment xml:lang="ko">V 글꼴</comment>
+ <comment xml:lang="kk">V font қарібі</comment>
+ <comment xml:lang="ja">V フォント</comment>
+ <comment xml:lang="it">Carattere V</comment>
+ <comment xml:lang="is">V letur</comment>
+ <comment xml:lang="id">Fonta V</comment>
+ <comment xml:lang="ia">Typo de litteras V</comment>
+ <comment xml:lang="hu">V-betűkészlet</comment>
+ <comment xml:lang="hr">V font</comment>
+ <comment xml:lang="he">גופן של V</comment>
+ <comment xml:lang="gl">tipo de letra V</comment>
+ <comment xml:lang="ga">cló V</comment>
+ <comment xml:lang="fur">caratar V</comment>
+ <comment xml:lang="fr">police V</comment>
+ <comment xml:lang="fo">V stavasnið</comment>
+ <comment xml:lang="fi">V-fontti</comment>
+ <comment xml:lang="eu">V letra-tipoa</comment>
+ <comment xml:lang="es">tipo de letra V</comment>
+ <comment xml:lang="eo">V-tiparo</comment>
+ <comment xml:lang="en_GB">V font</comment>
+ <comment xml:lang="el">Γραμματοσειρά V</comment>
+ <comment xml:lang="de">V-Schrift</comment>
+ <comment xml:lang="da">V-skrifttype</comment>
+ <comment xml:lang="cy">Ffont V</comment>
+ <comment xml:lang="cs">font V</comment>
+ <comment xml:lang="ca">lletra V</comment>
+ <comment xml:lang="bg">Шрифт — V</comment>
+ <comment xml:lang="be@latin">Šryft V</comment>
+ <comment xml:lang="be">шрыфт V</comment>
+ <comment xml:lang="az">V yazı növü</comment>
+ <comment xml:lang="ar">خط V</comment>
+ <comment xml:lang="af">V-skriftipe</comment>
<generic-icon name="font-x-generic"/>
- <magic priority="50">
- <match value="FONT" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="FONT" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/vnd.framemaker">
<comment>Adobe FrameMaker document</comment>
- <comment xml:lang="ar">مستند أدوبي الصانع للإطارات</comment>
- <comment xml:lang="ast">Documentu d'Adobe FrameMaker</comment>
- <comment xml:lang="be@latin">Dakument Adobe FrameMaker</comment>
- <comment xml:lang="bg">Документ — Adobe FrameMaker</comment>
- <comment xml:lang="ca">document d'Adobe FrameMaker</comment>
- <comment xml:lang="cs">dokument Adobe FrameMaker</comment>
- <comment xml:lang="da">Adobe FrameMaker-dokument</comment>
- <comment xml:lang="de">Adobe-FrameMaker-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Adobe FrameMaker</comment>
- <comment xml:lang="en_GB">Adobe FrameMaker document</comment>
- <comment xml:lang="eo">Dokumento de Adobe FrameMaker</comment>
- <comment xml:lang="es">documento de Adobe FrameMaker</comment>
- <comment xml:lang="eu">Adobe FrameMaker-en dokumentua</comment>
- <comment xml:lang="fi">Adobe FrameMaker -asiakirja</comment>
- <comment xml:lang="fo">Adobe FrameMaker skjal</comment>
- <comment xml:lang="fr">document Adobe FrameMaker</comment>
- <comment xml:lang="ga">cáipéis Adobe FrameMaker</comment>
- <comment xml:lang="gl">documento de Adobe FrameMaker</comment>
- <comment xml:lang="he">מסמך Adobe FrameMaker</comment>
- <comment xml:lang="hr">Adobe FrameMaker dokument</comment>
- <comment xml:lang="hu">Adobe FrameMaker-dokumentum</comment>
- <comment xml:lang="ia">Documento Adobe FrameMaker</comment>
- <comment xml:lang="id">Dokumen Adobe FrameMaker</comment>
- <comment xml:lang="it">Documento Adobe FrameMaker</comment>
- <comment xml:lang="ja">Adobe FrameMaker ドキュメント</comment>
- <comment xml:lang="ka">Adobe FrameMaker-ის დოკუმენტი</comment>
- <comment xml:lang="kk">Adobe FrameMaker құжаты</comment>
- <comment xml:lang="ko">Adobe 프레임메이커 문서</comment>
- <comment xml:lang="lt">Adobe FrameMaker dokumentas</comment>
- <comment xml:lang="lv">Adobe FrameMaker dokuments</comment>
- <comment xml:lang="nb">Adobe FrameMaker-dokument</comment>
- <comment xml:lang="nl">Adobe FrameMaker-document</comment>
- <comment xml:lang="nn">Adobe FrameMaker-dokument</comment>
- <comment xml:lang="oc">document Adobe FrameMaker</comment>
- <comment xml:lang="pl">Dokument Adobe FrameMaker</comment>
- <comment xml:lang="pt">documento Adobe FrameMaker</comment>
- <comment xml:lang="pt_BR">Documento do Adobe FrameMaker</comment>
- <comment xml:lang="ro">Document Adobe FrameMaker</comment>
- <comment xml:lang="ru">Документ Adobe FrameMaker</comment>
- <comment xml:lang="sk">Dokument Adobe FrameMaker</comment>
- <comment xml:lang="sl">Dokument Adobe FrameMaker</comment>
- <comment xml:lang="sq">Dokument Adobe FrameMaker</comment>
- <comment xml:lang="sr">документ Адобе Фреј Мејкера</comment>
- <comment xml:lang="sv">Adobe FrameMaker-dokument</comment>
- <comment xml:lang="tr">Adobe FrameMaker belgesi</comment>
- <comment xml:lang="uk">документ Adobe FrameMaker</comment>
- <comment xml:lang="vi">Tài liệu Adobe FrameMaker</comment>
- <comment xml:lang="zh_CN">Adobe FrameMaker 文档</comment>
<comment xml:lang="zh_TW">Adobe FrameMaker 文件</comment>
+ <comment xml:lang="zh_CN">Adobe FrameMaker 文档</comment>
+ <comment xml:lang="vi">Tài liệu Adobe FrameMaker</comment>
+ <comment xml:lang="uk">документ Adobe FrameMaker</comment>
+ <comment xml:lang="tr">Adobe FrameMaker belgesi</comment>
+ <comment xml:lang="sv">Adobe FrameMaker-dokument</comment>
+ <comment xml:lang="sr">документ Адобе Фреј Мејкера</comment>
+ <comment xml:lang="sq">dokument Adobe FrameMaker</comment>
+ <comment xml:lang="sl">Dokument Adobe FrameMaker</comment>
+ <comment xml:lang="si">Adobe FrameMaker ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Adobe FrameMaker</comment>
+ <comment xml:lang="ru">Документ Adobe FrameMaker</comment>
+ <comment xml:lang="ro">Document Adobe FrameMaker</comment>
+ <comment xml:lang="pt_BR">Documento do Adobe FrameMaker</comment>
+ <comment xml:lang="pt">documento Adobe FrameMaker</comment>
+ <comment xml:lang="pl">Dokument Adobe FrameMaker</comment>
+ <comment xml:lang="oc">document Adobe FrameMaker</comment>
+ <comment xml:lang="nn">Adobe FrameMaker-dokument</comment>
+ <comment xml:lang="nl">Adobe FrameMaker-document</comment>
+ <comment xml:lang="nb">Adobe FrameMaker-dokument</comment>
+ <comment xml:lang="lv">Adobe FrameMaker dokuments</comment>
+ <comment xml:lang="lt">Adobe FrameMaker dokumentas</comment>
+ <comment xml:lang="ko">Adobe 프레임메이커 문서</comment>
+ <comment xml:lang="kk">Adobe FrameMaker құжаты</comment>
+ <comment xml:lang="ka">Adobe FrameMaker-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">Adobe FrameMaker ドキュメント</comment>
+ <comment xml:lang="it">Documento Adobe FrameMaker</comment>
+ <comment xml:lang="is">Adobe FrameMaker skjal</comment>
+ <comment xml:lang="id">Dokumen Adobe FrameMaker</comment>
+ <comment xml:lang="ia">Documento Adobe FrameMaker</comment>
+ <comment xml:lang="hu">Adobe FrameMaker-dokumentum</comment>
+ <comment xml:lang="hr">Adobe FrameMaker dokument</comment>
+ <comment xml:lang="he">מסמך Adobe FrameMaker</comment>
+ <comment xml:lang="gl">documento de Adobe FrameMaker</comment>
+ <comment xml:lang="ga">cáipéis Adobe FrameMaker</comment>
+ <comment xml:lang="fur">document Adobe FrameMaker</comment>
+ <comment xml:lang="fr">document Adobe FrameMaker</comment>
+ <comment xml:lang="fo">Adobe FrameMaker skjal</comment>
+ <comment xml:lang="fi">Adobe FrameMaker -asiakirja</comment>
+ <comment xml:lang="eu">Adobe FrameMaker-en dokumentua</comment>
+ <comment xml:lang="es">documento de Adobe FrameMaker</comment>
+ <comment xml:lang="eo">Dokumento de Adobe FrameMaker</comment>
+ <comment xml:lang="en_GB">Adobe FrameMaker document</comment>
+ <comment xml:lang="el">Έγγραφο Adobe FrameMaker</comment>
+ <comment xml:lang="de">Adobe-FrameMaker-Dokument</comment>
+ <comment xml:lang="da">Adobe FrameMaker-dokument</comment>
+ <comment xml:lang="cs">dokument Adobe FrameMaker</comment>
+ <comment xml:lang="ca">document d'Adobe FrameMaker</comment>
+ <comment xml:lang="bg">Документ — Adobe FrameMaker</comment>
+ <comment xml:lang="be@latin">Dakument Adobe FrameMaker</comment>
+ <comment xml:lang="be">дакумент Adobe FrameMaker</comment>
+ <comment xml:lang="ast">Documentu d'Adobe FrameMaker</comment>
+ <comment xml:lang="ar">مستند أدوبي FrameMaker</comment>
+ <comment xml:lang="af">Adobe FrameMaker-dokument</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="&lt;MakerFile" type="string" offset="0"/>
- <match value="&lt;MIFFile" type="string" offset="0"/>
- <match value="&lt;MakerDictionary" type="string" offset="0"/>
- <match value="&lt;MakerScreenFon" type="string" offset="0"/>
- <match value="&lt;MML" type="string" offset="0"/>
- <match value="&lt;Book" type="string" offset="0"/>
- <match value="&lt;Maker" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="&lt;MakerFile" offset="0"/>
+ <match type="string" value="&lt;MIFFile" offset="0"/>
+ <match type="string" value="&lt;MakerDictionary" offset="0"/>
+ <match type="string" value="&lt;MakerScreenFon" offset="0"/>
+ <match type="string" value="&lt;MML" offset="0"/>
+ <match type="string" value="&lt;Book" offset="0"/>
+ <match type="string" value="&lt;Maker" offset="0"/>
</magic>
<glob pattern="*.fm"/>
<alias type="application/x-frame"/>
</mime-type>
<mime-type type="application/x-gameboy-rom">
<comment>Game Boy ROM</comment>
- <comment xml:lang="ar">Game Boy ROM</comment>
- <comment xml:lang="be@latin">Game Boy ROM</comment>
- <comment xml:lang="bg">ROM — Game Boy</comment>
- <comment xml:lang="ca">ROM de Game Boy</comment>
- <comment xml:lang="cs">ROM pro Game Boy</comment>
- <comment xml:lang="da">Game Boy-rom</comment>
- <comment xml:lang="de">Game Boy ROM</comment>
- <comment xml:lang="el">Game Boy ROM</comment>
- <comment xml:lang="en_GB">Game Boy ROM</comment>
- <comment xml:lang="eo">NLM de Game Boy</comment>
- <comment xml:lang="es">ROM de Game Boy</comment>
- <comment xml:lang="eu">Game Boy-eko ROMa</comment>
- <comment xml:lang="fi">Game Boy -ROM</comment>
- <comment xml:lang="fo">Game Boy ROM</comment>
- <comment xml:lang="fr">ROM Game Boy</comment>
- <comment xml:lang="ga">ROM Game Boy</comment>
- <comment xml:lang="gl">ROM de Game Boy</comment>
- <comment xml:lang="he">ROM של Game Boy</comment>
- <comment xml:lang="hr">Game Boy ROM</comment>
- <comment xml:lang="hu">Game Boy ROM</comment>
- <comment xml:lang="ia">ROM de Game Boy</comment>
- <comment xml:lang="id">Memori baca-saja Game Boy</comment>
- <comment xml:lang="it">ROM Game Boy</comment>
- <comment xml:lang="ja">ゲームボーイ ROM</comment>
- <comment xml:lang="ka">Game Boy-ის ROM</comment>
- <comment xml:lang="kk">Game Boy ROM</comment>
- <comment xml:lang="ko">게임보이 롬</comment>
- <comment xml:lang="lt">Game Boy ROM</comment>
- <comment xml:lang="lv">Game Boy ROM</comment>
- <comment xml:lang="ms">ROM Game Boy</comment>
- <comment xml:lang="nb">Game Boy-ROM</comment>
- <comment xml:lang="nl">Game Boy-ROM</comment>
- <comment xml:lang="nn">Game Boy-ROM</comment>
- <comment xml:lang="oc">ROM Game Boy</comment>
- <comment xml:lang="pl">Plik ROM konsoli Game Boy</comment>
- <comment xml:lang="pt">ROM Game Boy</comment>
- <comment xml:lang="pt_BR">ROM de Game Boy</comment>
- <comment xml:lang="ro">ROM Game Boy</comment>
- <comment xml:lang="ru">Game Boy ROM</comment>
- <comment xml:lang="sk">ROM pre Game Boy</comment>
- <comment xml:lang="sl">Bralni pomnilnik Game Boy</comment>
- <comment xml:lang="sq">ROM Game Boy</comment>
- <comment xml:lang="sr">Гејм Бој РОМ</comment>
- <comment xml:lang="sv">Game Boy-rom</comment>
- <comment xml:lang="tr">Game Boy ROM</comment>
- <comment xml:lang="uk">ППП Game Boy</comment>
- <comment xml:lang="vi">ROM Game Boy</comment>
- <comment xml:lang="zh_CN">Game Boy ROM</comment>
<comment xml:lang="zh_TW">Game Boy ROM</comment>
+ <comment xml:lang="zh_CN">Game Boy ROM</comment>
+ <comment xml:lang="vi">ROM Game Boy</comment>
+ <comment xml:lang="uk">ППП Game Boy</comment>
+ <comment xml:lang="tr">Game Boy ROM</comment>
+ <comment xml:lang="sv">Game Boy-rom</comment>
+ <comment xml:lang="sr">Гејм Бој РОМ</comment>
+ <comment xml:lang="sq">ROM Game Boy</comment>
+ <comment xml:lang="sl">Bralni pomnilnik Game Boy</comment>
+ <comment xml:lang="si">Game Boy ROM</comment>
+ <comment xml:lang="sk">ROM pre Game Boy</comment>
+ <comment xml:lang="ru">Game Boy ROM</comment>
+ <comment xml:lang="ro">ROM Game Boy</comment>
+ <comment xml:lang="pt_BR">ROM de Game Boy</comment>
+ <comment xml:lang="pt">ROM Game Boy</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Game Boy</comment>
+ <comment xml:lang="oc">ROM Game Boy</comment>
+ <comment xml:lang="nn">Game Boy-ROM</comment>
+ <comment xml:lang="nl">Game Boy-ROM</comment>
+ <comment xml:lang="nb">Game Boy-ROM</comment>
+ <comment xml:lang="ms">ROM Game Boy</comment>
+ <comment xml:lang="lv">Game Boy ROM</comment>
+ <comment xml:lang="lt">Game Boy ROM</comment>
+ <comment xml:lang="ko">게임보이 롬</comment>
+ <comment xml:lang="kk">Game Boy ROM</comment>
+ <comment xml:lang="ka">Game Boy-ის ROM</comment>
+ <comment xml:lang="ja">ゲームボーイ ROM</comment>
+ <comment xml:lang="it">ROM Game Boy</comment>
+ <comment xml:lang="is">Game Boy ROM</comment>
+ <comment xml:lang="id">Memori baca-saja Game Boy</comment>
+ <comment xml:lang="ia">ROM de Game Boy</comment>
+ <comment xml:lang="hu">Game Boy ROM</comment>
+ <comment xml:lang="hr">Game Boy ROM</comment>
+ <comment xml:lang="he">ROM של Game Boy</comment>
+ <comment xml:lang="gl">ROM de Game Boy</comment>
+ <comment xml:lang="ga">ROM Game Boy</comment>
+ <comment xml:lang="fur">ROM Game Boy</comment>
+ <comment xml:lang="fr">ROM Game Boy</comment>
+ <comment xml:lang="fo">Game Boy ROM</comment>
+ <comment xml:lang="fi">Game Boy -ROM</comment>
+ <comment xml:lang="eu">Game Boy-eko ROMa</comment>
+ <comment xml:lang="es">ROM de Game Boy</comment>
+ <comment xml:lang="eo">NLM de Game Boy</comment>
+ <comment xml:lang="en_GB">Game Boy ROM</comment>
+ <comment xml:lang="el">Game Boy ROM</comment>
+ <comment xml:lang="de">Game-Boy-ROM</comment>
+ <comment xml:lang="da">Game Boy-ROM</comment>
+ <comment xml:lang="cs">ROM pro Game Boy</comment>
+ <comment xml:lang="ca">ROM de Game Boy</comment>
+ <comment xml:lang="bg">ROM — Game Boy</comment>
+ <comment xml:lang="be@latin">Game Boy ROM</comment>
+ <comment xml:lang="be">Game Boy ROM</comment>
+ <comment xml:lang="ar">Game Boy ROM</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="\xce\xed\x66\x66\xcc\x0d\x00\x0b\x03\x73\x00\x83\x00\x0c\x00\x0d\x00\x08\x11\x1f\x88\x89\x00\x0e" type="string" offset="260">
- <match value="0x0" type="byte" offset="323" mask="0x80"/>
+ <magic>
+ <match type="string" value="\xce\xed\x66\x66\xcc\x0d\x00\x0b\x03\x73\x00\x83\x00\x0c\x00\x0d\x00\x08\x11\x1f\x88\x89\x00\x0e" offset="260">
+ <match type="byte" value="0x0" mask="0x80" offset="323"/>
</match>
</magic>
<glob pattern="*.gb"/>
@@ -11825,37 +12741,49 @@
</mime-type>
<mime-type type="application/x-gameboy-color-rom">
<comment>Game Boy Color ROM</comment>
- <comment xml:lang="ca">ROM de Game Boy Color</comment>
- <comment xml:lang="cs">ROM pro Game Boy Color</comment>
- <comment xml:lang="da">Game Boy Color ROM</comment>
- <comment xml:lang="de">Game Boy Color ROM</comment>
- <comment xml:lang="en_GB">Game Boy Colour ROM</comment>
- <comment xml:lang="es">ROM de Game Boy Color</comment>
- <comment xml:lang="eu">Game Boy Color ROM</comment>
- <comment xml:lang="fi">Game Boy Color -ROM</comment>
- <comment xml:lang="fr">ROM Game Boy Color</comment>
- <comment xml:lang="ga">ROM Game Boy Color</comment>
- <comment xml:lang="he">ROM של Game Boy Color</comment>
- <comment xml:lang="hr">Game Boy Color ROM</comment>
- <comment xml:lang="hu">Game Boy Color ROM</comment>
- <comment xml:lang="id">ROM Game Boy Color</comment>
- <comment xml:lang="it">ROM Game Boy Color</comment>
- <comment xml:lang="kk">Game Boy Color ROM</comment>
- <comment xml:lang="ko">게임보이 컬러 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Game Boy Color</comment>
- <comment xml:lang="pt_BR">ROM de Game Boy Color</comment>
- <comment xml:lang="ru">Game Boy Color ROM</comment>
- <comment xml:lang="sk">ROM pre Game Boy Color</comment>
- <comment xml:lang="sr">Гејм Бој РОМ боје</comment>
- <comment xml:lang="sv">Game Boy Color-rom</comment>
- <comment xml:lang="tr">Game Boy Color ROM</comment>
- <comment xml:lang="uk">ППП Game Boy Color</comment>
- <comment xml:lang="zh_CN">Game Boy Color ROM</comment>
<comment xml:lang="zh_TW">Game Boy Color ROM</comment>
+ <comment xml:lang="zh_CN">Game Boy Color ROM</comment>
+ <comment xml:lang="uk">ППП Game Boy Color</comment>
+ <comment xml:lang="tr">Game Boy Color ROM</comment>
+ <comment xml:lang="sv">Game Boy Color-rom</comment>
+ <comment xml:lang="sr">Гејм Бој РОМ боје</comment>
+ <comment xml:lang="sq">ROM Game Boy Color</comment>
+ <comment xml:lang="sl">Game Boy Color ROM</comment>
+ <comment xml:lang="si">Game Boy Color ROM</comment>
+ <comment xml:lang="sk">ROM pre Game Boy Color</comment>
+ <comment xml:lang="ru">Game Boy Color ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Game Boy Color</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Game Boy Color</comment>
+ <comment xml:lang="oc">ROM Game Boy Color</comment>
+ <comment xml:lang="nl">Game Boy Color-ROM</comment>
+ <comment xml:lang="ko">게임보이 컬러 롬</comment>
+ <comment xml:lang="kk">Game Boy Color ROM</comment>
+ <comment xml:lang="ja">ゲームボーイカラー ROM</comment>
+ <comment xml:lang="it">ROM Game Boy Color</comment>
+ <comment xml:lang="is">Game Boy Color ROM</comment>
+ <comment xml:lang="id">ROM Game Boy Color</comment>
+ <comment xml:lang="hu">Game Boy Color ROM</comment>
+ <comment xml:lang="hr">Game Boy Color ROM</comment>
+ <comment xml:lang="he">ROM של Game Boy Color</comment>
+ <comment xml:lang="gl">ROM de Game Boy Color</comment>
+ <comment xml:lang="ga">ROM Game Boy Color</comment>
+ <comment xml:lang="fur">ROM Game Boy Color</comment>
+ <comment xml:lang="fr">ROM Game Boy Color</comment>
+ <comment xml:lang="fi">Game Boy Color -ROM</comment>
+ <comment xml:lang="eu">Game Boy Color ROM</comment>
+ <comment xml:lang="es">ROM de Game Boy Color</comment>
+ <comment xml:lang="en_GB">Game Boy Colour ROM</comment>
+ <comment xml:lang="de">Game-Boy-Color-ROM</comment>
+ <comment xml:lang="da">Game Boy Color-ROM</comment>
+ <comment xml:lang="cs">ROM pro Game Boy Color</comment>
+ <comment xml:lang="ca">ROM de Game Boy Color</comment>
+ <comment xml:lang="bg">ROM — Game Boy Color</comment>
+ <comment xml:lang="be">Game Boy Color ROM</comment>
+ <comment xml:lang="ar">روم جيم بوي كولر</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="\xce\xed\x66\x66\xcc\x0d\x00\x0b\x03\x73\x00\x83\x00\x0c\x00\x0d\x00\x08" type="string" offset="260">
- <match value="0x80" type="byte" offset="323" mask="0x80"/>
+ <magic>
+ <match type="string" value="\xce\xed\x66\x66\xcc\x0d\x00\x0b\x03\x73\x00\x83\x00\x0c\x00\x0d\x00\x08" offset="260">
+ <match type="byte" value="0x80" mask="0x80" offset="323"/>
</match>
</magic>
<glob pattern="*.gbc"/>
@@ -11863,442 +12791,460 @@
</mime-type>
<mime-type type="application/x-gba-rom">
<comment>Game Boy Advance ROM</comment>
- <comment xml:lang="ar">Game Boy Advance ROM</comment>
- <comment xml:lang="be@latin">Game Boy Advance ROM</comment>
- <comment xml:lang="bg">ROM — Game Boy Advance</comment>
- <comment xml:lang="ca">ROM de Game Boy Advance</comment>
- <comment xml:lang="cs">ROM pro Game Boy Advance</comment>
- <comment xml:lang="da">Game Boy Advance-rom</comment>
- <comment xml:lang="de">Game Boy Advance ROM</comment>
- <comment xml:lang="el">Game Boy Advance ROM</comment>
- <comment xml:lang="en_GB">Game Boy Advance ROM</comment>
- <comment xml:lang="es">ROM de Game Boy Advance</comment>
- <comment xml:lang="eu">Game Boy Advance-ko ROMa</comment>
- <comment xml:lang="fi">Game Boy Advance -ROM</comment>
- <comment xml:lang="fo">Game Boy Advance ROM</comment>
- <comment xml:lang="fr">ROM Game Boy Advance</comment>
- <comment xml:lang="ga">ROM Game Boy Advance</comment>
- <comment xml:lang="gl">ROM de Game Boy Advance</comment>
- <comment xml:lang="he">ROM של Game Boy Advance</comment>
- <comment xml:lang="hr">Game Boy Advance ROM</comment>
- <comment xml:lang="hu">Game Boy Advance ROM</comment>
- <comment xml:lang="ia">ROM de Game Boy Advance</comment>
- <comment xml:lang="id">Memori baca-saja Game Boy Advance</comment>
- <comment xml:lang="it">ROM Game Boy Advance</comment>
- <comment xml:lang="ja">ゲームボーイアドバンス ROM</comment>
- <comment xml:lang="ka">Game Boy Advance-ის ROM</comment>
- <comment xml:lang="kk">Game Boy Advance ROM</comment>
- <comment xml:lang="ko">게임보이 어드밴스 롬</comment>
- <comment xml:lang="lt">Game Boy Advance ROM</comment>
- <comment xml:lang="lv">Game Boy Advance ROM</comment>
- <comment xml:lang="nb">Game Boy Advance-ROM</comment>
- <comment xml:lang="nl">Game Boy Advance-ROM</comment>
- <comment xml:lang="nn">Game Boy Advance-ROM</comment>
- <comment xml:lang="oc">ROM Game Boy Advance</comment>
- <comment xml:lang="pl">Plik ROM konsoli Game Boy Advance</comment>
- <comment xml:lang="pt">ROM Game Boy Advance</comment>
- <comment xml:lang="pt_BR">ROM de Game Boy Advance</comment>
- <comment xml:lang="ro">ROM Game Boy Advance</comment>
- <comment xml:lang="ru">Game Boy Advance ROM</comment>
- <comment xml:lang="sk">ROM pre Game Boy Advance</comment>
- <comment xml:lang="sl">Bralni pomnilnik Game Boy Advance</comment>
- <comment xml:lang="sq">ROM Game Boy Advance</comment>
- <comment xml:lang="sr">Гејм Бој Адванс РОМ</comment>
- <comment xml:lang="sv">Game Boy Advance-rom</comment>
- <comment xml:lang="tr">Game Boy Gelişmiş ROM</comment>
- <comment xml:lang="uk">розширений ППП Game Boy</comment>
- <comment xml:lang="vi">ROM Game Boy Advance</comment>
- <comment xml:lang="zh_CN">Game Boy Advance ROM</comment>
<comment xml:lang="zh_TW">Game Boy Advance ROM</comment>
+ <comment xml:lang="zh_CN">Game Boy Advance ROM</comment>
+ <comment xml:lang="vi">ROM Game Boy Advance</comment>
+ <comment xml:lang="uk">розширений ППП Game Boy</comment>
+ <comment xml:lang="tr">Game Boy Gelişmiş ROM</comment>
+ <comment xml:lang="sv">Game Boy Advance-rom</comment>
+ <comment xml:lang="sr">Гејм Бој Адванс РОМ</comment>
+ <comment xml:lang="sq">ROM Game Boy Advance</comment>
+ <comment xml:lang="sl">Bralni pomnilnik Game Boy Advance</comment>
+ <comment xml:lang="si">Game Boy Advance ROM</comment>
+ <comment xml:lang="sk">ROM pre Game Boy Advance</comment>
+ <comment xml:lang="ru">Game Boy Advance ROM</comment>
+ <comment xml:lang="ro">ROM Game Boy Advance</comment>
+ <comment xml:lang="pt_BR">ROM de Game Boy Advance</comment>
+ <comment xml:lang="pt">ROM Game Boy Advance</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Game Boy Advance</comment>
+ <comment xml:lang="oc">ROM Game Boy Advance</comment>
+ <comment xml:lang="nn">Game Boy Advance-ROM</comment>
+ <comment xml:lang="nl">Game Boy Advance-ROM</comment>
+ <comment xml:lang="nb">Game Boy Advance-ROM</comment>
+ <comment xml:lang="lv">Game Boy Advance ROM</comment>
+ <comment xml:lang="lt">Game Boy Advance ROM</comment>
+ <comment xml:lang="ko">게임보이 어드밴스 롬</comment>
+ <comment xml:lang="kk">Game Boy Advance ROM</comment>
+ <comment xml:lang="ka">Game Boy Advance-ის ROM</comment>
+ <comment xml:lang="ja">ゲームボーイアドバンス ROM</comment>
+ <comment xml:lang="it">ROM Game Boy Advance</comment>
+ <comment xml:lang="is">Game Boy Advance ROM</comment>
+ <comment xml:lang="id">Memori baca-saja Game Boy Advance</comment>
+ <comment xml:lang="ia">ROM de Game Boy Advance</comment>
+ <comment xml:lang="hu">Game Boy Advance ROM</comment>
+ <comment xml:lang="hr">Game Boy Advance ROM</comment>
+ <comment xml:lang="he">ROM של Game Boy Advance</comment>
+ <comment xml:lang="gl">ROM de Game Boy Advance</comment>
+ <comment xml:lang="ga">ROM Game Boy Advance</comment>
+ <comment xml:lang="fur">ROM Game Boy Advance</comment>
+ <comment xml:lang="fr">ROM Game Boy Advance</comment>
+ <comment xml:lang="fo">Game Boy Advance ROM</comment>
+ <comment xml:lang="fi">Game Boy Advance -ROM</comment>
+ <comment xml:lang="eu">Game Boy Advance-ko ROMa</comment>
+ <comment xml:lang="es">ROM de Game Boy Advance</comment>
+ <comment xml:lang="en_GB">Game Boy Advance ROM</comment>
+ <comment xml:lang="el">Game Boy Advance ROM</comment>
+ <comment xml:lang="de">Game-Boy-Advance-ROM</comment>
+ <comment xml:lang="da">Game Boy Advance-ROM</comment>
+ <comment xml:lang="cs">ROM pro Game Boy Advance</comment>
+ <comment xml:lang="ca">ROM de Game Boy Advance</comment>
+ <comment xml:lang="bg">ROM — Game Boy Advance</comment>
+ <comment xml:lang="be@latin">Game Boy Advance ROM</comment>
+ <comment xml:lang="be">Game Boy Advance ROM</comment>
+ <comment xml:lang="ar">Game Boy Advance ROM</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.gba"/>
<glob pattern="*.agb"/>
</mime-type>
<mime-type type="application/x-virtual-boy-rom">
<comment>Virtual Boy ROM</comment>
- <comment xml:lang="ca">ROM de Virtual Boy</comment>
- <comment xml:lang="cs">ROM pro Virtual Boy</comment>
- <comment xml:lang="de">Virtual Boy ROM</comment>
- <comment xml:lang="en_GB">Virtual Boy ROM</comment>
- <comment xml:lang="es">ROM de Virtual Boy</comment>
- <comment xml:lang="hr">Virtual Boy ROM</comment>
- <comment xml:lang="hu">Virtual Boy ROM</comment>
- <comment xml:lang="id">ROM Virtual Boy</comment>
- <comment xml:lang="it">ROM Virtual Boy</comment>
- <comment xml:lang="kk">Virtual Boy ROM</comment>
- <comment xml:lang="ko">버추얼보이 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Virtual Boy</comment>
- <comment xml:lang="pt_BR">ROM de Virtual Boy</comment>
- <comment xml:lang="ru">Virtual Boy ROM</comment>
- <comment xml:lang="sk">ROM pre Virtual Boy</comment>
- <comment xml:lang="sv">Virtual Boy-rom</comment>
- <comment xml:lang="uk">ROM Virtual Boy</comment>
- <comment xml:lang="zh_CN">Virtual Boy ROM</comment>
<comment xml:lang="zh_TW">Virtual Boy ROM</comment>
+ <comment xml:lang="zh_CN">Virtual Boy ROM</comment>
+ <comment xml:lang="uk">ROM Virtual Boy</comment>
+ <comment xml:lang="tr">Virtual Boy ROM</comment>
+ <comment xml:lang="sv">Virtual Boy-rom</comment>
+ <comment xml:lang="sq">ROM Virtual Boy</comment>
+ <comment xml:lang="sl">Virtual Boy ROM</comment>
+ <comment xml:lang="si">Virtual Boy ROM</comment>
+ <comment xml:lang="sk">ROM pre Virtual Boy</comment>
+ <comment xml:lang="ru">Virtual Boy ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Virtual Boy</comment>
+ <comment xml:lang="pt">ROM Virtua Boy</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Virtual Boy</comment>
+ <comment xml:lang="nl">Virtual Boy-ROM</comment>
+ <comment xml:lang="ko">버추얼 보이 롬</comment>
+ <comment xml:lang="kk">Virtual Boy ROM</comment>
+ <comment xml:lang="ja">バーチャルボーイ ROM</comment>
+ <comment xml:lang="it">ROM Virtual Boy</comment>
+ <comment xml:lang="is">Virtual Boy ROM</comment>
+ <comment xml:lang="id">ROM Virtual Boy</comment>
+ <comment xml:lang="hu">Virtual Boy ROM</comment>
+ <comment xml:lang="hr">Virtual Boy ROM</comment>
+ <comment xml:lang="he">ROM של Virtual Boy</comment>
+ <comment xml:lang="gl">ROM de Virtual Boy</comment>
+ <comment xml:lang="ga">ROM Virtual Boy</comment>
+ <comment xml:lang="fur">ROM Virtual Boy</comment>
+ <comment xml:lang="fr">ROM Virtual Boy</comment>
+ <comment xml:lang="fi">Virtual Boy -ROM</comment>
+ <comment xml:lang="eu">Virtual Boy ROM</comment>
+ <comment xml:lang="es">ROM de Virtual Boy</comment>
+ <comment xml:lang="en_GB">Virtual Boy ROM</comment>
+ <comment xml:lang="de">Virtual-Boy-ROM</comment>
+ <comment xml:lang="da">Virtual Boy-ROM</comment>
+ <comment xml:lang="cs">ROM pro Virtual Boy</comment>
+ <comment xml:lang="ca">ROM de Virtual Boy</comment>
+ <comment xml:lang="bg">ROM — Virtual Boy</comment>
+ <comment xml:lang="be">Virtual Boy ROM</comment>
+ <comment xml:lang="ar">روم بوي الافتراضي</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.vb"/>
</mime-type>
<mime-type type="application/x-gdbm">
<comment>GDBM database</comment>
- <comment xml:lang="ar">قاعدة بيانات GDBM</comment>
- <comment xml:lang="be@latin">Baza źviestak GDBM</comment>
- <comment xml:lang="bg">База от данни — GDBM</comment>
- <comment xml:lang="ca">base de dades GDBM</comment>
- <comment xml:lang="cs">databáze GDBM</comment>
- <comment xml:lang="da">GDBM-database</comment>
- <comment xml:lang="de">GDBM-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων GDBM</comment>
- <comment xml:lang="en_GB">GDBM database</comment>
- <comment xml:lang="eo">GDBM-datumbazo</comment>
- <comment xml:lang="es">base de datos GDBM</comment>
- <comment xml:lang="eu">GDBM datu-basea</comment>
- <comment xml:lang="fi">GDBM-tietokanta</comment>
- <comment xml:lang="fo">GDBM dátustovnur</comment>
- <comment xml:lang="fr">base de données GDBM</comment>
- <comment xml:lang="ga">bunachar sonraí GDBM</comment>
- <comment xml:lang="gl">base de datos GDBM</comment>
- <comment xml:lang="he">מסד נתונים GDBM</comment>
- <comment xml:lang="hr">GDBM baza podataka</comment>
- <comment xml:lang="hu">GDBM adatbázis</comment>
- <comment xml:lang="ia">Base de datos GDBM</comment>
- <comment xml:lang="id">Basis data GDBM</comment>
- <comment xml:lang="it">Database GDBM</comment>
- <comment xml:lang="ja">GDBM データベース</comment>
- <comment xml:lang="ka">GDBM მონაცემთა ბაზა</comment>
- <comment xml:lang="kk">GDBM дерекқоры</comment>
- <comment xml:lang="ko">GDBM 데이터베이스</comment>
- <comment xml:lang="lt">GDBM duomenų bazė</comment>
- <comment xml:lang="lv">GDBM datubāze</comment>
- <comment xml:lang="nb">GDBM-database</comment>
- <comment xml:lang="nl">GDBM-gegevensbank</comment>
- <comment xml:lang="nn">GDBM-database</comment>
- <comment xml:lang="oc">banca de donadas GDBM</comment>
- <comment xml:lang="pl">Baza danych GDBM</comment>
- <comment xml:lang="pt">base de dados GDMB</comment>
- <comment xml:lang="pt_BR">Banco de dados GDBM</comment>
- <comment xml:lang="ro">Bază de date GDBM</comment>
- <comment xml:lang="ru">База данных GDBM</comment>
- <comment xml:lang="sk">Databáza GDBM</comment>
- <comment xml:lang="sl">Podatkovna zbirka GDBM</comment>
- <comment xml:lang="sq">Bazë me të dhëna GDBM</comment>
- <comment xml:lang="sr">ГДБМ база података</comment>
- <comment xml:lang="sv">GDBM-databas</comment>
- <comment xml:lang="tr">GDBM veritabanı</comment>
- <comment xml:lang="uk">база даних GDBM</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu GDBM</comment>
- <comment xml:lang="zh_CN">GDBM 数据库</comment>
<comment xml:lang="zh_TW">GDBM 資料庫</comment>
+ <comment xml:lang="zh_CN">GDBM 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu GDBM</comment>
+ <comment xml:lang="uk">база даних GDBM</comment>
+ <comment xml:lang="tr">GDBM veri tabanı</comment>
+ <comment xml:lang="sv">GDBM-databas</comment>
+ <comment xml:lang="sr">ГДБМ база података</comment>
+ <comment xml:lang="sq">bazë të dhënash GDBM</comment>
+ <comment xml:lang="sl">Podatkovna zbirka GDBM</comment>
+ <comment xml:lang="si">GDBM දත්ත සමුදාය</comment>
+ <comment xml:lang="sk">Databáza GDBM</comment>
+ <comment xml:lang="ru">База данных GDBM</comment>
+ <comment xml:lang="ro">Bază de date GDBM</comment>
+ <comment xml:lang="pt_BR">Banco de dados GDBM</comment>
+ <comment xml:lang="pt">base de dados GDMB</comment>
+ <comment xml:lang="pl">Baza danych GDBM</comment>
+ <comment xml:lang="oc">banca de donadas GDBM</comment>
+ <comment xml:lang="nn">GDBM-database</comment>
+ <comment xml:lang="nl">GDBM-database</comment>
+ <comment xml:lang="nb">GDBM-database</comment>
+ <comment xml:lang="lv">GDBM datubāze</comment>
+ <comment xml:lang="lt">GDBM duomenų bazė</comment>
+ <comment xml:lang="ko">GDBM 데이터베이스</comment>
+ <comment xml:lang="kk">GDBM дерекқоры</comment>
+ <comment xml:lang="ka">GDBM მონაცემთა ბაზა</comment>
+ <comment xml:lang="ja">GDBM データベース</comment>
+ <comment xml:lang="it">Database GDBM</comment>
+ <comment xml:lang="is">GDBM gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data GDBM</comment>
+ <comment xml:lang="ia">Base de datos GDBM</comment>
+ <comment xml:lang="hu">GDBM adatbázis</comment>
+ <comment xml:lang="hr">GDBM baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים GDBM</comment>
+ <comment xml:lang="gl">base de datos GDBM</comment>
+ <comment xml:lang="ga">bunachar sonraí GDBM</comment>
+ <comment xml:lang="fur">base di dâts GDBM</comment>
+ <comment xml:lang="fr">base de données GDBM</comment>
+ <comment xml:lang="fo">GDBM dátustovnur</comment>
+ <comment xml:lang="fi">GDBM-tietokanta</comment>
+ <comment xml:lang="eu">GDBM datu-basea</comment>
+ <comment xml:lang="es">base de datos GDBM</comment>
+ <comment xml:lang="eo">GDBM-datumbazo</comment>
+ <comment xml:lang="en_GB">GDBM database</comment>
+ <comment xml:lang="el">Βάση δεδομένων GDBM</comment>
+ <comment xml:lang="de">GDBM-Datenbank</comment>
+ <comment xml:lang="da">GDBM-database</comment>
+ <comment xml:lang="cs">databáze GDBM</comment>
+ <comment xml:lang="ca">base de dades GDBM</comment>
+ <comment xml:lang="bg">База от данни — GDBM</comment>
+ <comment xml:lang="be@latin">Baza źviestak GDBM</comment>
+ <comment xml:lang="be">база даных GDBM</comment>
+ <comment xml:lang="ar">قاعدة بيانات GDBM</comment>
+ <comment xml:lang="af">GDBM-databasis</comment>
<acronym>GDBM</acronym>
<expanded-acronym>GNU Database Manager</expanded-acronym>
- <magic priority="50">
- <match value="0x13579ace" type="big32" offset="0"/>
- <match value="0x13579ace" type="little32" offset="0"/>
- <match value="GDBM" type="string" offset="0"/>
+ <magic>
+ <match type="big32" value="0x13579ace" offset="0"/>
+ <match type="little32" value="0x13579ace" offset="0"/>
+ <match type="string" value="GDBM" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-genesis-rom">
-
+ <!-- Translate this to Mega Drive if the console was known as such in your locale
+ Should be Mega Drive in all but en_US, Mexico and Canada: https://en.wikipedia.org/wiki/Sega_Genesis#History -->
<comment>Genesis ROM</comment>
- <comment xml:lang="ar">Genesis ROM</comment>
- <comment xml:lang="be@latin">Genesis ROM</comment>
- <comment xml:lang="bg">ROM — Genesis</comment>
- <comment xml:lang="ca">ROM de Genesis</comment>
- <comment xml:lang="cs">ROM pro Genesis</comment>
- <comment xml:lang="da">Genesis-rom</comment>
- <comment xml:lang="de">Genesis ROM</comment>
- <comment xml:lang="el">Genesis ROM</comment>
- <comment xml:lang="en_GB">Genesis ROM</comment>
- <comment xml:lang="eo">Genesis-NLM</comment>
- <comment xml:lang="es">ROM de Genesis (Mega Drive)</comment>
- <comment xml:lang="eu">Genesis-eko ROMa</comment>
- <comment xml:lang="fi">Genesis-ROM</comment>
- <comment xml:lang="fo">Genesis ROM</comment>
- <comment xml:lang="fr">ROM Mega Drive/Genesis</comment>
- <comment xml:lang="ga">ROM Genesis</comment>
- <comment xml:lang="gl">ROM xenérica</comment>
- <comment xml:lang="he">ROM מסוג Genesis</comment>
- <comment xml:lang="hr">Genesis ROM</comment>
- <comment xml:lang="hu">Genesis ROM</comment>
- <comment xml:lang="ia">ROM de Mega Drive/Genesis</comment>
- <comment xml:lang="id">Memori baca-saja Genesis</comment>
- <comment xml:lang="it">ROM Megadrive</comment>
- <comment xml:lang="ja">メガドライブ ROM</comment>
- <comment xml:lang="kk">Genesis ROM</comment>
- <comment xml:lang="ko">제네시스 롬</comment>
- <comment xml:lang="lt">Genesis ROM</comment>
- <comment xml:lang="lv">Genesis ROM</comment>
- <comment xml:lang="ms">ROM Genesis</comment>
- <comment xml:lang="nb">Genesis-ROM</comment>
- <comment xml:lang="nl">Mega Drive</comment>
- <comment xml:lang="nn">Genesis-ROM</comment>
- <comment xml:lang="oc">ROM Mega Drive/Genesis</comment>
- <comment xml:lang="pl">Plik ROM konsoli Mega Drive</comment>
- <comment xml:lang="pt">ROM Mega Drive</comment>
- <comment xml:lang="pt_BR">ROM de Genesis (Mega Drive)</comment>
- <comment xml:lang="ro">ROM Genesis</comment>
- <comment xml:lang="ru">Genesis ROM</comment>
- <comment xml:lang="sk">ROM pre Megadrive</comment>
- <comment xml:lang="sl">Bralni pomnilnik Genesis</comment>
- <comment xml:lang="sq">ROM Genesis</comment>
- <comment xml:lang="sr">Мегадрајв РОМ</comment>
- <comment xml:lang="sv">Mega Drive-rom</comment>
- <comment xml:lang="tr">Genesis ROM</comment>
- <comment xml:lang="uk">ППП Genesis</comment>
- <comment xml:lang="vi">ROM Genesis</comment>
- <comment xml:lang="zh_CN">Genesis ROM</comment>
<comment xml:lang="zh_TW">Genesis ROM</comment>
+ <comment xml:lang="zh_CN">Genesis ROM</comment>
+ <comment xml:lang="vi">ROM Genesis</comment>
+ <comment xml:lang="uk">ППП Genesis</comment>
+ <comment xml:lang="tr">Genesis ROM</comment>
+ <comment xml:lang="sv">Mega Drive-rom</comment>
+ <comment xml:lang="sr">Мегадрајв РОМ</comment>
+ <comment xml:lang="sq">ROM Genesis</comment>
+ <comment xml:lang="sl">Bralni pomnilnik Genesis</comment>
+ <comment xml:lang="si">උත්පත්ති ROM</comment>
+ <comment xml:lang="sk">ROM pre Megadrive</comment>
+ <comment xml:lang="ru">Genesis ROM</comment>
+ <comment xml:lang="ro">ROM Genesis</comment>
+ <comment xml:lang="pt_BR">ROM de Genesis (Mega Drive)</comment>
+ <comment xml:lang="pt">ROM Mega Drive</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Mega Drive</comment>
+ <comment xml:lang="oc">ROM Mega Drive/Genesis</comment>
+ <comment xml:lang="nn">Genesis-ROM</comment>
+ <comment xml:lang="nl">Mega Drive-ROM</comment>
+ <comment xml:lang="nb">Genesis-ROM</comment>
+ <comment xml:lang="ms">ROM Genesis</comment>
+ <comment xml:lang="lv">Genesis ROM</comment>
+ <comment xml:lang="lt">Genesis ROM</comment>
+ <comment xml:lang="ko">제네시스 롬</comment>
+ <comment xml:lang="kk">Genesis ROM</comment>
+ <comment xml:lang="ja">メガドライブ ROM</comment>
+ <comment xml:lang="it">ROM Megadrive</comment>
+ <comment xml:lang="is">Genesis ROM</comment>
+ <comment xml:lang="id">Memori baca-saja Genesis</comment>
+ <comment xml:lang="ia">ROM de Mega Drive/Genesis</comment>
+ <comment xml:lang="hu">Genesis ROM</comment>
+ <comment xml:lang="hr">Genesis ROM</comment>
+ <comment xml:lang="he">ROM מסוג Genesis</comment>
+ <comment xml:lang="gl">ROM xenérica</comment>
+ <comment xml:lang="ga">ROM Genesis</comment>
+ <comment xml:lang="fur">ROM Sega Mega Drive</comment>
+ <comment xml:lang="fr">ROM Mega Drive/Genesis</comment>
+ <comment xml:lang="fo">Genesis ROM</comment>
+ <comment xml:lang="fi">Genesis-ROM</comment>
+ <comment xml:lang="eu">Genesis-eko ROMa</comment>
+ <comment xml:lang="es">ROM de Genesis (Mega Drive)</comment>
+ <comment xml:lang="eo">Genesis-NLM</comment>
+ <comment xml:lang="en_GB">Genesis ROM</comment>
+ <comment xml:lang="el">Genesis ROM</comment>
+ <comment xml:lang="de">Mega-Drive-ROM</comment>
+ <comment xml:lang="da">Genesis-ROM</comment>
+ <comment xml:lang="cs">ROM pro Genesis</comment>
+ <comment xml:lang="ca">ROM de Genesis</comment>
+ <comment xml:lang="bg">ROM — Genesis</comment>
+ <comment xml:lang="be@latin">Genesis ROM</comment>
+ <comment xml:lang="be">Genesis ROM</comment>
+ <comment xml:lang="ar">روم Genesis</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="SEGA GENESIS" type="string" offset="256"/>
- <match value="SEGA MEGA DRIVE" type="string" offset="256"/>
- <match value="EAGN" type="string" offset="640"/>
- <match value="EAMG" type="string" offset="640"/>
+ <magic>
+ <match type="string" value="SEGA GENESIS" offset="256"/>
+ <match type="string" value="SEGA MEGA DRIVE" offset="256"/>
+ <match type="string" value="SEGA_MEGA_DRIVE" offset="256"/>
+ <match type="string" value="EAGN" offset="640"/>
+ <match type="string" value="EAMG" offset="640"/>
</magic>
<glob pattern="*.gen"/>
<glob pattern="*.smd"/>
+ <glob pattern="*.sgd"/>
</mime-type>
<mime-type type="application/x-genesis-32x-rom">
-
+ <!-- Translate this to Super 32X, Mega Drive 32X or Mega 32X if the system was known as such in your locale
+ Should be Super 32X in Japan, Mega Drive 32X in PAL region and Mega 32X in Brazil: https://en.wikipedia.org/wiki/32X -->
<comment>Genesis 32X ROM</comment>
- <comment xml:lang="ca">ROM de Genesis 32X</comment>
- <comment xml:lang="cs">ROM pro Genesis 32X</comment>
- <comment xml:lang="da">Genesis 32X ROM</comment>
- <comment xml:lang="de">Genesis 32X ROM</comment>
- <comment xml:lang="en_GB">Genesis 32X ROM</comment>
- <comment xml:lang="es">ROM de Genesis 32X</comment>
- <comment xml:lang="eu">Genesis 32X ROM</comment>
- <comment xml:lang="fi">Genesis 32X -ROM</comment>
- <comment xml:lang="fr">ROM Genesis 32X</comment>
- <comment xml:lang="ga">ROM Genesis 32X</comment>
- <comment xml:lang="he">ROM מסוג Genesis 32X</comment>
- <comment xml:lang="hr">Genesis 32X ROM</comment>
- <comment xml:lang="hu">Genesis 32X ROM</comment>
- <comment xml:lang="id">ROM Genesis 32X</comment>
- <comment xml:lang="it">ROM Sega Mega Drive 32X</comment>
- <comment xml:lang="kk">Genesis 32X ROM</comment>
- <comment xml:lang="ko">제네시스 32X 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Mega Drive 32X</comment>
- <comment xml:lang="pt_BR">ROM de Genesis 32X</comment>
- <comment xml:lang="ru">Genesis 32X ROM</comment>
- <comment xml:lang="sk">ROM pre Genesis 32X</comment>
- <comment xml:lang="sr">Џенезис 32X РОМ</comment>
- <comment xml:lang="sv">Mega Drive 32X-rom</comment>
- <comment xml:lang="tr">Genesis 32X ROM</comment>
- <comment xml:lang="uk">ППП Genesis 32X</comment>
- <comment xml:lang="zh_CN">Genesis 32X ROM</comment>
<comment xml:lang="zh_TW">Genesis 32X ROM</comment>
+ <comment xml:lang="zh_CN">Genesis 32X ROM</comment>
+ <comment xml:lang="uk">ППП Genesis 32X</comment>
+ <comment xml:lang="tr">Genesis 32X ROM</comment>
+ <comment xml:lang="sv">Mega Drive 32X-rom</comment>
+ <comment xml:lang="sr">Џенезис 32X РОМ</comment>
+ <comment xml:lang="sq">ROM Genesis 32X</comment>
+ <comment xml:lang="sl">Genesis 32X ROM</comment>
+ <comment xml:lang="si">උත්පත්ති 32X ROM</comment>
+ <comment xml:lang="sk">ROM pre Genesis 32X</comment>
+ <comment xml:lang="ru">Genesis 32X ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Genesis 32X</comment>
+ <comment xml:lang="pt">ROM Genesis 32X</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Mega Drive 32X</comment>
+ <comment xml:lang="nl">Mega Drive 32X-ROM</comment>
+ <comment xml:lang="ko">제네시스 32X 롬</comment>
+ <comment xml:lang="kk">Genesis 32X ROM</comment>
+ <comment xml:lang="ja">メガドライブ 32X ROM</comment>
+ <comment xml:lang="it">ROM Sega Mega Drive 32X</comment>
+ <comment xml:lang="is">Genesis 32X ROM</comment>
+ <comment xml:lang="id">ROM Genesis 32X</comment>
+ <comment xml:lang="hu">Genesis 32X ROM</comment>
+ <comment xml:lang="hr">Genesis 32X ROM</comment>
+ <comment xml:lang="he">ROM מסוג Genesis 32X</comment>
+ <comment xml:lang="gl">ROM Genesis 32X</comment>
+ <comment xml:lang="ga">ROM Genesis 32X</comment>
+ <comment xml:lang="fur">ROM Sega Mega Drive 32X</comment>
+ <comment xml:lang="fr">ROM Genesis 32X</comment>
+ <comment xml:lang="fi">Genesis 32X -ROM</comment>
+ <comment xml:lang="eu">Genesis 32X ROM</comment>
+ <comment xml:lang="es">ROM de Genesis 32X</comment>
+ <comment xml:lang="en_GB">Genesis 32X ROM</comment>
+ <comment xml:lang="de">Mega-32X-ROM</comment>
+ <comment xml:lang="da">Genesis 32X-ROM</comment>
+ <comment xml:lang="cs">ROM pro Genesis 32X</comment>
+ <comment xml:lang="ca">ROM de Genesis 32X</comment>
+ <comment xml:lang="bg">ROM — Genesis 32X</comment>
+ <comment xml:lang="be">Genesis 32X ROM</comment>
+ <comment xml:lang="ar">روم Genesis 32X</comment>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="SEGA 32X" type="string" offset="256"/>
+ <magic>
+ <match type="string" value="SEGA 32X" offset="256"/>
</magic>
<glob pattern="*.32x"/>
<glob pattern="*.mdx"/>
</mime-type>
<mime-type type="application/x-gettext-translation">
- <comment>translated messages (machine-readable)</comment>
- <comment xml:lang="ar">رسائل مترجمة (مقروءة آليا)</comment>
- <comment xml:lang="be@latin">pierakładzienyja paviedamleńni (dla čytańnia kamputaram)</comment>
- <comment xml:lang="bg">Преведени съобщения — машинен формат</comment>
- <comment xml:lang="ca">missatges traduïts (llegible per màquina)</comment>
- <comment xml:lang="cs">přeložené zprávy (strojově čitelné)</comment>
- <comment xml:lang="da">oversatte meddelelser (maskinlæsbare)</comment>
- <comment xml:lang="de">Übersetzte Meldungen (maschinenlesbar)</comment>
- <comment xml:lang="el">Μεταφρασμένα μηνύματα (για μηχανική ανάγνωση)</comment>
- <comment xml:lang="en_GB">translated messages (machine-readable)</comment>
- <comment xml:lang="eo">tradukitaj mesaĝoj (maŝinlegebla)</comment>
- <comment xml:lang="es">mensajes traducidos (legibles por máquinas)</comment>
- <comment xml:lang="eu">itzulitako mezuak (ordenagailuek irakurtzeko)</comment>
- <comment xml:lang="fi">käännetyt viestit (koneluettava)</comment>
- <comment xml:lang="fo">týdd boð (maskin-lesifør)</comment>
- <comment xml:lang="fr">messages traduits (lisibles par machine)</comment>
- <comment xml:lang="ga">teachtaireachtaí aistrithe (inléite ag meaisín)</comment>
- <comment xml:lang="gl">mensaxes traducidos (lexíbeis por máquinas)</comment>
- <comment xml:lang="he">הודעות מתורגמות (מובן ע״י מכונה)</comment>
- <comment xml:lang="hr">Prevedene poruke (strojno čitljive)</comment>
- <comment xml:lang="hu">lefordított üzenetek (gépi kód)</comment>
- <comment xml:lang="ia">messages traducite (legibile pro machinas)</comment>
- <comment xml:lang="id">pesan diterjemahkan (dapat dibaca mesin)</comment>
- <comment xml:lang="it">Messaggi tradotti (leggibili da macchina)</comment>
- <comment xml:lang="ja">翻訳メッセージ (マシン用)</comment>
- <comment xml:lang="ka">ნათარგმნი შეტყობინებები (მანქანისთვის განკუთვნილი)</comment>
- <comment xml:lang="kk">аударылған хабарламалар (машиналық түрде)</comment>
- <comment xml:lang="ko">번역 메시지(컴퓨터 사용 형식)</comment>
- <comment xml:lang="lt">išversti užrašai (kompiuteriniu formatu)</comment>
- <comment xml:lang="lv">pārtulkotie ziņojumi (mašīnlasāms)</comment>
- <comment xml:lang="ms">Mesej diterjemah (bolehdibaca-mesin)</comment>
- <comment xml:lang="nb">oversatte meldinger (maskinlesbar)</comment>
- <comment xml:lang="nl">vertaalde berichten (machine-leesbaar)</comment>
- <comment xml:lang="nn">oversette meldingar (maskinlesbare)</comment>
- <comment xml:lang="oc">messatges tradusits (legibles per maquina)</comment>
- <comment xml:lang="pl">Przetłumaczone komunikaty (czytelne dla komputera)</comment>
- <comment xml:lang="pt">mensagens traduzidas (leitura pelo computador)</comment>
- <comment xml:lang="pt_BR">Mensagens traduzidas (legível pelo computador)</comment>
- <comment xml:lang="ro">mesaje traduse (citite de calculator)</comment>
- <comment xml:lang="ru">Переводы сообщений (откомпилированые)</comment>
- <comment xml:lang="sk">Preložené správy (strojovo čitateľné)</comment>
- <comment xml:lang="sl">prevedena sporočila (strojni zapis)</comment>
- <comment xml:lang="sq">Mesazhe të përkthyer (të lexueshëm nga makina)</comment>
- <comment xml:lang="sr">преведене поруке (машинама читљиве)</comment>
- <comment xml:lang="sv">översatta meddelanden (maskinläsbara)</comment>
- <comment xml:lang="tr">çevrilmiş iletiler (makine tarafından okunabilir)</comment>
+ <comment>Translated messages (machine-readable)</comment>
<comment xml:lang="uk">перекладені повідомлення (у машинній формі)</comment>
- <comment xml:lang="vi">thông điệp đã dịch (máy đọc được)</comment>
- <comment xml:lang="zh_CN">已翻译消息(机读)</comment>
- <comment xml:lang="zh_TW">翻譯訊息 (程式讀取格式)</comment>
- <magic priority="50">
- <match value="\336\22\4\225" type="string" offset="0"/>
- <match value="\225\4\22\336" type="string" offset="0"/>
+ <comment xml:lang="sv">Översatta meddelanden (maskinläsbara)</comment>
+ <comment xml:lang="ru">Переводы сообщений (откомпилированые)</comment>
+ <comment xml:lang="pl">Przetłumaczone komunikaty (czytelne dla komputera)</comment>
+ <comment xml:lang="it">Messaggi tradotti (leggibili da macchina)</comment>
+ <comment xml:lang="gl">Mensaxes traducidos (lexíbel pola máquina)</comment>
+ <comment xml:lang="eu">Itzulitako mezuak (makinak irakurtzeko modukoak)</comment>
+ <comment xml:lang="es">mensajes traducidos (legibles por máquinas)</comment>
+ <comment xml:lang="de">Übersetzte Meldungen (maschinenlesbar)</comment>
+ <comment xml:lang="be">перакладзеныя паведамленні (для чытання камп'ютарам)</comment>
+ <magic>
+ <match type="string" value="\336\22\4\225" offset="0"/>
+ <match type="string" value="\225\4\22\336" offset="0"/>
</magic>
<glob pattern="*.gmo"/>
<glob pattern="*.mo"/>
</mime-type>
<mime-type type="application/x-gtk-builder">
- <comment>GTK+ Builder</comment>
- <comment xml:lang="ca">constructor de GTK+</comment>
- <comment xml:lang="cs">GTK+ Builder</comment>
- <comment xml:lang="da">GTK+ Builder</comment>
- <comment xml:lang="de">GTK+ Builder</comment>
- <comment xml:lang="el">Δομητής GTK+</comment>
- <comment xml:lang="en_GB">GTK+ Builder</comment>
- <comment xml:lang="es">GTK+ Builder</comment>
- <comment xml:lang="eu">GTK+ Builder</comment>
- <comment xml:lang="fi">GTK+ Builder</comment>
- <comment xml:lang="fr">GTK+ Builder</comment>
- <comment xml:lang="ga">Tógálaí GTK+</comment>
- <comment xml:lang="gl">Construtor de GTK+</comment>
- <comment xml:lang="he">בנייה של GTK+‎</comment>
- <comment xml:lang="hr">GTK+ Builder</comment>
- <comment xml:lang="hu">GTK+ Builder</comment>
- <comment xml:lang="ia">GTK+ Builder</comment>
- <comment xml:lang="id">GTK+ Builder</comment>
- <comment xml:lang="it">GTK+ Builder</comment>
- <comment xml:lang="ja">GTK+ Builder</comment>
- <comment xml:lang="kk">GTK+ Builder</comment>
- <comment xml:lang="ko">GTK+ 빌더</comment>
- <comment xml:lang="lv">GTK+ būvētājs</comment>
- <comment xml:lang="oc">GTK+ Builder</comment>
- <comment xml:lang="pl">GTK+ Builder</comment>
- <comment xml:lang="pt">Construtor GTK+</comment>
- <comment xml:lang="pt_BR">GTK+ Builder</comment>
- <comment xml:lang="ru">GTK+ Builder</comment>
- <comment xml:lang="sk">GTK+ Builder</comment>
- <comment xml:lang="sl">GTK+ Builder</comment>
- <comment xml:lang="sr">ГТК+ Градитељ</comment>
- <comment xml:lang="sv">GTK+ Builder</comment>
- <comment xml:lang="tr">GTK+ İnşa Edici</comment>
- <comment xml:lang="uk">GTK+ Builder</comment>
- <comment xml:lang="zh_CN">GTK+ Builder</comment>
- <comment xml:lang="zh_TW">GTK+ Builder</comment>
+ <comment>GTK+ Builder interface document</comment>
+ <comment xml:lang="zh_TW">GTK+ Builder 介面文件</comment>
+ <comment xml:lang="zh_CN">GTK+ Builder 界面文档</comment>
+ <comment xml:lang="uk">документ інтерфейсу GTK+ Builder</comment>
+ <comment xml:lang="tr">GTK+ Builder arayüz belgesi</comment>
+ <comment xml:lang="sv">GTK+-Builder-gränssnittsdokument</comment>
+ <comment xml:lang="sq">dokument ndërfaqesh GTK+ Builder</comment>
+ <comment xml:lang="sl">Dokument vmesnika GTK+ Builder</comment>
+ <comment xml:lang="si">GTK+ Builder අතුරුමුහුණත් ලේඛනය</comment>
+ <comment xml:lang="ru">Документ интерфейса GTK+ Builder</comment>
+ <comment xml:lang="pt_BR">Documento de interface do GTK+ Builder</comment>
+ <comment xml:lang="pl">Dokument interfejsu GTK Builder</comment>
+ <comment xml:lang="nl">GTK-Builder-interfacedocument</comment>
+ <comment xml:lang="ko">GTK+ 빌더 인터페이스 문서</comment>
+ <comment xml:lang="kk">GTK+ Builder интерфейс құжаты</comment>
+ <comment xml:lang="ja">GTK+ Builder インターフェイスドキュメント</comment>
+ <comment xml:lang="it">Documento interfaccia GTK+ Builder</comment>
+ <comment xml:lang="is">GTK+ Builder viðmótsskjal</comment>
+ <comment xml:lang="id">Dokumen antarmuka GTK+ Builder</comment>
+ <comment xml:lang="hu">GTK+ Builder felületleíró dokumentum</comment>
+ <comment xml:lang="hr">GTK+ Graditelj dokument sučelja</comment>
+ <comment xml:lang="he">מסמך מנשק של GTK+ Builder</comment>
+ <comment xml:lang="gl">Documento de interface do Construtor de GTK+ </comment>
+ <comment xml:lang="fr">document d'interface GTK+ Builder</comment>
+ <comment xml:lang="fi">GTK+ Builder -käyttöliittymän asiakirja</comment>
+ <comment xml:lang="eu">GTK+ Builder interfaze dokumentua</comment>
+ <comment xml:lang="es">documento de interfaz de GTK Builder</comment>
+ <comment xml:lang="en_GB">GTK+ Builder interface document</comment>
+ <comment xml:lang="de">GTK+-Builder-Oberflächendokument</comment>
+ <comment xml:lang="da">GTK+ Builder-brugerflade-dokument</comment>
+ <comment xml:lang="ca">document d'interfície GTK+ Builder</comment>
+ <comment xml:lang="bg">Интерфейс — GTK+ Builder</comment>
+ <comment xml:lang="be">дакумент інтэрфейсу GTK+ Builder</comment>
+ <comment xml:lang="ar">مستند واجهة باني جي تي كي بلس</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.ui"/>
- <magic priority="50">
- <match value="&lt;interface" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;interface" offset="0:256"/>
</magic>
</mime-type>
<mime-type type="application/x-glade">
<comment>Glade project</comment>
- <comment xml:lang="ar">مشروع Glade</comment>
- <comment xml:lang="az">Glade layihəsi</comment>
- <comment xml:lang="be@latin">Prajekt Glade</comment>
- <comment xml:lang="bg">Проект — Glade</comment>
- <comment xml:lang="ca">projecte de Glade</comment>
- <comment xml:lang="cs">projekt Glade</comment>
- <comment xml:lang="cy">Prosiect Glade</comment>
- <comment xml:lang="da">Gladeprojekt</comment>
- <comment xml:lang="de">Glade-Projekt</comment>
- <comment xml:lang="el">Έργο Glade</comment>
- <comment xml:lang="en_GB">Glade project</comment>
- <comment xml:lang="eo">Glade-projekto</comment>
- <comment xml:lang="es">proyecto de Glade</comment>
- <comment xml:lang="eu">Glade proiektua</comment>
- <comment xml:lang="fi">Glade-projekti</comment>
- <comment xml:lang="fo">Glade verkætlan</comment>
- <comment xml:lang="fr">projet Glade</comment>
- <comment xml:lang="ga">tionscadal Glade</comment>
- <comment xml:lang="gl">proxecto de Glade</comment>
- <comment xml:lang="he">מיזם Glade</comment>
- <comment xml:lang="hr">Glade projekt</comment>
- <comment xml:lang="hu">Glade-projekt</comment>
- <comment xml:lang="ia">Projecto Glade</comment>
- <comment xml:lang="id">Proyek Glade</comment>
- <comment xml:lang="it">Progetto Glade</comment>
- <comment xml:lang="ja">Glade プロジェクト</comment>
- <comment xml:lang="kk">Glade жобасы</comment>
- <comment xml:lang="ko">Glade 프로젝트</comment>
- <comment xml:lang="lt">Glade projektas</comment>
- <comment xml:lang="lv">Glade projekts</comment>
- <comment xml:lang="ms">Projek Glade</comment>
- <comment xml:lang="nb">Glade prosjekt</comment>
- <comment xml:lang="nl">Glade-project</comment>
- <comment xml:lang="nn">Glade prosjekt</comment>
- <comment xml:lang="oc">projècte Glade</comment>
- <comment xml:lang="pl">Projekt Glade</comment>
- <comment xml:lang="pt">projecto Glade</comment>
- <comment xml:lang="pt_BR">Projeto do Glade</comment>
- <comment xml:lang="ro">Proiect Glade</comment>
- <comment xml:lang="ru">Проект Glade</comment>
- <comment xml:lang="sk">Projekt Glade</comment>
- <comment xml:lang="sl">Datoteka projekta Glade</comment>
- <comment xml:lang="sq">Projekt Glade</comment>
- <comment xml:lang="sr">Глејдов пројекат</comment>
- <comment xml:lang="sv">Glade-projekt</comment>
- <comment xml:lang="tr">Glade projesi</comment>
- <comment xml:lang="uk">проект Glade</comment>
- <comment xml:lang="vi">Dự án Glade</comment>
- <comment xml:lang="zh_CN">Glade 工程</comment>
<comment xml:lang="zh_TW">Glade 專案</comment>
+ <comment xml:lang="zh_CN">Glade 工程</comment>
+ <comment xml:lang="vi">Dự án Glade</comment>
+ <comment xml:lang="uk">проєкт Glade</comment>
+ <comment xml:lang="tr">Glade projesi</comment>
+ <comment xml:lang="sv">Glade-projekt</comment>
+ <comment xml:lang="sr">Глејдов пројекат</comment>
+ <comment xml:lang="sq">projekt Glade</comment>
+ <comment xml:lang="sl">Datoteka projekta Glade</comment>
+ <comment xml:lang="si">ග්ලේඩ් ව්යාපෘතිය</comment>
+ <comment xml:lang="sk">Projekt Glade</comment>
+ <comment xml:lang="ru">Проект Glade</comment>
+ <comment xml:lang="ro">Proiect Glade</comment>
+ <comment xml:lang="pt_BR">Projeto do Glade</comment>
+ <comment xml:lang="pt">projecto Glade</comment>
+ <comment xml:lang="pl">Projekt Glade</comment>
+ <comment xml:lang="oc">projècte Glade</comment>
+ <comment xml:lang="nn">Glade prosjekt</comment>
+ <comment xml:lang="nl">Glade-project</comment>
+ <comment xml:lang="nb">Glade prosjekt</comment>
+ <comment xml:lang="ms">Projek Glade</comment>
+ <comment xml:lang="lv">Glade projekts</comment>
+ <comment xml:lang="lt">Glade projektas</comment>
+ <comment xml:lang="ko">Glade 프로젝트</comment>
+ <comment xml:lang="kk">Glade жобасы</comment>
+ <comment xml:lang="ja">Glade プロジェクト</comment>
+ <comment xml:lang="it">Progetto Glade</comment>
+ <comment xml:lang="is">Glade verkefni</comment>
+ <comment xml:lang="id">Proyek Glade</comment>
+ <comment xml:lang="ia">Projecto Glade</comment>
+ <comment xml:lang="hu">Glade-projekt</comment>
+ <comment xml:lang="hr">Glade projekt</comment>
+ <comment xml:lang="he">מיזם Glade</comment>
+ <comment xml:lang="gl">proxecto de Glade</comment>
+ <comment xml:lang="ga">tionscadal Glade</comment>
+ <comment xml:lang="fur">progjet Glade</comment>
+ <comment xml:lang="fr">projet Glade</comment>
+ <comment xml:lang="fo">Glade verkætlan</comment>
+ <comment xml:lang="fi">Glade-projekti</comment>
+ <comment xml:lang="eu">Glade proiektua</comment>
+ <comment xml:lang="es">proyecto de Glade</comment>
+ <comment xml:lang="eo">Glade-projekto</comment>
+ <comment xml:lang="en_GB">Glade project</comment>
+ <comment xml:lang="el">Έργο Glade</comment>
+ <comment xml:lang="de">Glade-Projekt</comment>
+ <comment xml:lang="da">Gladeprojekt</comment>
+ <comment xml:lang="cy">Prosiect Glade</comment>
+ <comment xml:lang="cs">projekt Glade</comment>
+ <comment xml:lang="ca">projecte de Glade</comment>
+ <comment xml:lang="bg">Проект — Glade</comment>
+ <comment xml:lang="be@latin">Prajekt Glade</comment>
+ <comment xml:lang="be">праект Glade</comment>
+ <comment xml:lang="az">Glade layihəsi</comment>
+ <comment xml:lang="ar">مشروع Glade</comment>
+ <comment xml:lang="af">Glade-projek</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.glade"/>
- <magic priority="50">
- <match value="&lt;glade-interface" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;glade-interface" offset="0:256"/>
</magic>
</mime-type>
<mime-type type="application/x-gnucash">
<comment>GnuCash financial data</comment>
- <comment xml:lang="ar">معلومات GnuCash المالية</comment>
- <comment xml:lang="bg">Финансови данни — GnuCash</comment>
- <comment xml:lang="ca">dades financeres de GnuCash</comment>
- <comment xml:lang="cs">finanční data GnuCash</comment>
- <comment xml:lang="da">Finansielle data til GnuCash</comment>
- <comment xml:lang="de">GnuCash-Finanzdaten</comment>
- <comment xml:lang="el">Οικονομικά στοιχεία GnuCash</comment>
- <comment xml:lang="en_GB">GnuCash financial data</comment>
- <comment xml:lang="es">datos financieros de GnuCash</comment>
- <comment xml:lang="eu">GnuCash finantzako datuak</comment>
- <comment xml:lang="fi">GnuCash-taloustiedot</comment>
- <comment xml:lang="fo">GnuCash fíggjarligar dátur</comment>
- <comment xml:lang="fr">données financières GnuCash</comment>
- <comment xml:lang="ga">sonraí airgeadúla GnuCash</comment>
- <comment xml:lang="gl">datos financeiros de GNUCash</comment>
- <comment xml:lang="he">מידע כלכלי של GnuCash</comment>
- <comment xml:lang="hr">GnuCash financijski podaci</comment>
- <comment xml:lang="hu">GnuCash pénzügyi adatok</comment>
- <comment xml:lang="ia">Datos financiari GnuCash</comment>
- <comment xml:lang="id">Data keuangan GnuCash</comment>
- <comment xml:lang="it">Dati finanziari GnuCash</comment>
- <comment xml:lang="ja">GnuCash 会計データ</comment>
- <comment xml:lang="kk">GnuCash қаржы ақпараты</comment>
- <comment xml:lang="ko">GnuCash 재정 자료</comment>
- <comment xml:lang="lt">GnuCash finansiniai duomenys</comment>
- <comment xml:lang="lv">GnuCash finanšu dati</comment>
- <comment xml:lang="nl">GnuCash financiële gegevens</comment>
- <comment xml:lang="oc">donadas financières GnuCash</comment>
- <comment xml:lang="pl">Dane finansowe GnuCash</comment>
- <comment xml:lang="pt">dados financeiros GnuCash</comment>
- <comment xml:lang="pt_BR">Dados financeiros do GnuCash</comment>
- <comment xml:lang="ro">Date financiare GnuCash</comment>
- <comment xml:lang="ru">Финансовые данные GnuCash</comment>
- <comment xml:lang="sk">Finančné údaje GnuCash</comment>
- <comment xml:lang="sl">Datoteka finančnih podatkov GnuCash</comment>
- <comment xml:lang="sr">финансијски подаци Гнуовог новца</comment>
- <comment xml:lang="sv">GnuCash-finansdata</comment>
- <comment xml:lang="tr">GnuCash mali verisi</comment>
- <comment xml:lang="uk">фінансові дані GnuCash</comment>
- <comment xml:lang="vi">Dữ liệu tài chính GnuCash</comment>
- <comment xml:lang="zh_CN">GnuCash 财务数据</comment>
<comment xml:lang="zh_TW">GnuCash 財務資料</comment>
+ <comment xml:lang="zh_CN">GnuCash 财务数据</comment>
+ <comment xml:lang="vi">Dữ liệu tài chính GnuCash</comment>
+ <comment xml:lang="uk">фінансові дані GnuCash</comment>
+ <comment xml:lang="tr">GnuCash mali verisi</comment>
+ <comment xml:lang="sv">GnuCash-finansdata</comment>
+ <comment xml:lang="sr">финансијски подаци Гнуовог новца</comment>
+ <comment xml:lang="sq">të dhëna financiare GnuCash</comment>
+ <comment xml:lang="sl">Datoteka finančnih podatkov GnuCash</comment>
+ <comment xml:lang="si">GnuCash මූල්ය දත්ත</comment>
+ <comment xml:lang="sk">Finančné údaje GnuCash</comment>
+ <comment xml:lang="ru">Финансовые данные GnuCash</comment>
+ <comment xml:lang="ro">Date financiare GnuCash</comment>
+ <comment xml:lang="pt_BR">Dados financeiros do GnuCash</comment>
+ <comment xml:lang="pt">dados financeiros GnuCash</comment>
+ <comment xml:lang="pl">Dane finansowe GnuCash</comment>
+ <comment xml:lang="oc">donadas financières GnuCash</comment>
+ <comment xml:lang="nl">GnuCash financiële gegevens</comment>
+ <comment xml:lang="lv">GnuCash finanšu dati</comment>
+ <comment xml:lang="lt">GnuCash finansiniai duomenys</comment>
+ <comment xml:lang="ko">GnuCash 재정 자료</comment>
+ <comment xml:lang="kk">GnuCash қаржы ақпараты</comment>
+ <comment xml:lang="ja">GnuCash 会計データ</comment>
+ <comment xml:lang="it">Dati finanziari GnuCash</comment>
+ <comment xml:lang="is">GnuCash fjárhagsgögn</comment>
+ <comment xml:lang="id">Data keuangan GnuCash</comment>
+ <comment xml:lang="ia">Datos financiari GnuCash</comment>
+ <comment xml:lang="hu">GnuCash pénzügyi adatok</comment>
+ <comment xml:lang="hr">GnuCash financijski podaci</comment>
+ <comment xml:lang="he">מידע כלכלי של GnuCash</comment>
+ <comment xml:lang="gl">datos financeiros de GNUCash</comment>
+ <comment xml:lang="ga">sonraí airgeadúla GnuCash</comment>
+ <comment xml:lang="fur">dâts finanziaris GnuCash</comment>
+ <comment xml:lang="fr">données financières GnuCash</comment>
+ <comment xml:lang="fo">GnuCash fíggjarligar dátur</comment>
+ <comment xml:lang="fi">GnuCash-taloustiedot</comment>
+ <comment xml:lang="eu">GnuCash finantzako datuak</comment>
+ <comment xml:lang="es">datos financieros de GnuCash</comment>
+ <comment xml:lang="en_GB">GnuCash financial data</comment>
+ <comment xml:lang="el">Οικονομικά στοιχεία GnuCash</comment>
+ <comment xml:lang="de">GnuCash-Finanzdaten</comment>
+ <comment xml:lang="da">Finansielle data til GnuCash</comment>
+ <comment xml:lang="cs">finanční data GnuCash</comment>
+ <comment xml:lang="ca">dades financeres de GnuCash</comment>
+ <comment xml:lang="bg">Финансови данни — GnuCash</comment>
+ <comment xml:lang="be">фінансавыя даныя GnuCash</comment>
+ <comment xml:lang="ar">بيانات مالية GnuCash</comment>
+ <comment xml:lang="af">GnuCash finansiële data</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.gnucash"/>
<glob pattern="*.gnc"/>
@@ -12306,111 +13252,121 @@
</mime-type>
<mime-type type="application/x-gnumeric">
<comment>Gnumeric spreadsheet</comment>
- <comment xml:lang="ar">جدول Gnumeric</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš Gnumeric</comment>
- <comment xml:lang="bg">Таблица — Gnumeric</comment>
- <comment xml:lang="ca">full de càlcul de Gnumeric</comment>
- <comment xml:lang="cs">sešit Gnumeric</comment>
- <comment xml:lang="da">Gnumeric-regneark</comment>
- <comment xml:lang="de">Gnumeric-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Gnumeric</comment>
- <comment xml:lang="en_GB">Gnumeric spreadsheet</comment>
- <comment xml:lang="eo">Gnumeric-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo de Gnumeric</comment>
- <comment xml:lang="eu">Gnumeric kalkulu-orria</comment>
- <comment xml:lang="fi">Gnumeric-taulukko</comment>
- <comment xml:lang="fo">Gnumeric rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Gnumeric</comment>
- <comment xml:lang="ga">scarbhileog Gnumeric</comment>
- <comment xml:lang="gl">folla de cálculo de Gnumeric</comment>
- <comment xml:lang="he">גליון עבודה Gnumeric</comment>
- <comment xml:lang="hr">Gnumeric proračunska tablica</comment>
- <comment xml:lang="hu">Gnumeric-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo Gnumeric</comment>
- <comment xml:lang="id">Lembar sebar Gnumeric</comment>
- <comment xml:lang="it">Foglio di calcolo Gnumeric</comment>
- <comment xml:lang="ja">Gnumeric スプレッドシート</comment>
- <comment xml:lang="kk">Gnumeric электрондық кестесі</comment>
- <comment xml:lang="ko">Gnumeric 스프레드시트</comment>
- <comment xml:lang="lt">Gnumeric skaičialentė</comment>
- <comment xml:lang="lv">Gnumeric izklājlapa</comment>
- <comment xml:lang="ms">Hamparan Gnumeric</comment>
- <comment xml:lang="nb">Gnumeric-regneark</comment>
- <comment xml:lang="nl">Gnumeric-rekenblad</comment>
- <comment xml:lang="nn">Gnumeric-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul Gnumeric</comment>
- <comment xml:lang="pl">Arkusz Gnumeric</comment>
- <comment xml:lang="pt">folha de cálculo Gnumeric</comment>
- <comment xml:lang="pt_BR">Planilha do Gnumeric</comment>
- <comment xml:lang="ro">Foaie de calcul Gnumeric</comment>
- <comment xml:lang="ru">Электронная таблица Gnumeric</comment>
- <comment xml:lang="sk">Zošit Gnumeric</comment>
- <comment xml:lang="sl">Razpredelnica Gnumeric</comment>
- <comment xml:lang="sq">Fletë llogaritjesh Gnumeric</comment>
- <comment xml:lang="sr">табела Гномовог бројевника</comment>
- <comment xml:lang="sv">Gnumeric-kalkylblad</comment>
- <comment xml:lang="tr">Gnumeric çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Gnumeric</comment>
- <comment xml:lang="vi">Bảng tính Gnumeric.</comment>
- <comment xml:lang="zh_CN">Gnumeric 电子表格</comment>
<comment xml:lang="zh_TW">Gnumeric 試算表</comment>
+ <comment xml:lang="zh_CN">Gnumeric 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Gnumeric.</comment>
+ <comment xml:lang="uk">електронна таблиця Gnumeric</comment>
+ <comment xml:lang="tr">Gnumeric hesap çizelgesi</comment>
+ <comment xml:lang="sv">Gnumeric-kalkylblad</comment>
+ <comment xml:lang="sr">табела Гномовог бројевника</comment>
+ <comment xml:lang="sq">fletëllogaritjesh Gnumeric</comment>
+ <comment xml:lang="sl">Razpredelnica Gnumeric</comment>
+ <comment xml:lang="si">Gnumeric පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Gnumeric</comment>
+ <comment xml:lang="ru">Электронная таблица Gnumeric</comment>
+ <comment xml:lang="ro">Foaie de calcul Gnumeric</comment>
+ <comment xml:lang="pt_BR">Planilha do Gnumeric</comment>
+ <comment xml:lang="pt">folha de cálculo Gnumeric</comment>
+ <comment xml:lang="pl">Arkusz Gnumeric</comment>
+ <comment xml:lang="oc">fuèlh de calcul Gnumeric</comment>
+ <comment xml:lang="nn">Gnumeric-rekneark</comment>
+ <comment xml:lang="nl">Gnumeric-rekenblad</comment>
+ <comment xml:lang="nb">Gnumeric-regneark</comment>
+ <comment xml:lang="ms">Hamparan Gnumeric</comment>
+ <comment xml:lang="lv">Gnumeric izklājlapa</comment>
+ <comment xml:lang="lt">Gnumeric skaičialentė</comment>
+ <comment xml:lang="ko">Gnumeric 스프레드시트</comment>
+ <comment xml:lang="kk">Gnumeric электрондық кестесі</comment>
+ <comment xml:lang="ja">Gnumeric スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Gnumeric</comment>
+ <comment xml:lang="is">Gnumeric töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Gnumeric</comment>
+ <comment xml:lang="ia">Folio de calculo Gnumeric</comment>
+ <comment xml:lang="hu">Gnumeric-munkafüzet</comment>
+ <comment xml:lang="hr">Gnumeric proračunska tablica</comment>
+ <comment xml:lang="he">גיליון עבודה של Gnumeric</comment>
+ <comment xml:lang="gl">folla de cálculo de Gnumeric</comment>
+ <comment xml:lang="ga">scarbhileog Gnumeric</comment>
+ <comment xml:lang="fur">sfuei di calcul Gnumeric</comment>
+ <comment xml:lang="fr">feuille de calcul Gnumeric</comment>
+ <comment xml:lang="fo">Gnumeric rokniark</comment>
+ <comment xml:lang="fi">Gnumeric-taulukko</comment>
+ <comment xml:lang="eu">Gnumeric kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Gnumeric</comment>
+ <comment xml:lang="eo">Gnumeric-kalkultabelo</comment>
+ <comment xml:lang="en_GB">Gnumeric spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Gnumeric</comment>
+ <comment xml:lang="de">Gnumeric-Tabelle</comment>
+ <comment xml:lang="da">Gnumeric-regneark</comment>
+ <comment xml:lang="cs">sešit Gnumeric</comment>
+ <comment xml:lang="ca">full de càlcul de Gnumeric</comment>
+ <comment xml:lang="bg">Таблица — Gnumeric</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš Gnumeric</comment>
+ <comment xml:lang="be">электронная табліца Gnumeric</comment>
+ <comment xml:lang="ar">جدول Gnumeric</comment>
+ <comment xml:lang="af">Gnumeric-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="gmr:Workbook" type="string" offset="0:64"/>
- <match value="gnm:Workbook" type="string" offset="0:64"/>
+ <magic>
+ <match type="string" value="gmr:Workbook" offset="0:64"/>
+ <match type="string" value="gnm:Workbook" offset="0:64"/>
</magic>
<glob pattern="*.gnumeric"/>
</mime-type>
<mime-type type="application/x-gnuplot">
<comment>Gnuplot document</comment>
- <comment xml:lang="ar">مستند Gnuplot</comment>
- <comment xml:lang="ast">Documentu de Gnuplot</comment>
- <comment xml:lang="be@latin">Dakument Gnuplot</comment>
- <comment xml:lang="bg">Документ — Gnuplot</comment>
- <comment xml:lang="ca">document gnuplot</comment>
- <comment xml:lang="cs">dokument Gnuplot</comment>
- <comment xml:lang="da">Gnuplotdokument</comment>
- <comment xml:lang="de">Gnuplot-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Gnuplot</comment>
- <comment xml:lang="en_GB">Gnuplot document</comment>
- <comment xml:lang="eo">Gnuplot-dokumento</comment>
- <comment xml:lang="es">documento de Gnuplot</comment>
- <comment xml:lang="eu">Gnuplot dokumentua</comment>
- <comment xml:lang="fi">Gnuplot-asiakirja</comment>
- <comment xml:lang="fo">Gnuplot skjal</comment>
- <comment xml:lang="fr">document Gnuplot</comment>
- <comment xml:lang="ga">cáipéis Gnuplot</comment>
- <comment xml:lang="gl">documento de Gnuplot</comment>
- <comment xml:lang="he">מסמך Gnuplot</comment>
- <comment xml:lang="hr">Gnuplot dokument</comment>
- <comment xml:lang="hu">Gnuplot dokumentum</comment>
- <comment xml:lang="ia">Documento Gnuplot</comment>
- <comment xml:lang="id">Dokumen Gnuplot</comment>
- <comment xml:lang="it">Documento Gnuplot</comment>
- <comment xml:lang="ja">Gnuplot ドキュメント</comment>
- <comment xml:lang="kk">Gnuplot құжаты</comment>
- <comment xml:lang="ko">Gnuplot 문서</comment>
- <comment xml:lang="lt">Gnuplot dokumentas</comment>
- <comment xml:lang="lv">Gnuplot dokuments</comment>
- <comment xml:lang="nb">Gnuplot-dokument</comment>
- <comment xml:lang="nl">Gnuplot-document</comment>
- <comment xml:lang="nn">Gnuplot-dokument</comment>
- <comment xml:lang="oc">document Gnuplot</comment>
- <comment xml:lang="pl">Dokument Gnuplot</comment>
- <comment xml:lang="pt">documento Gnuplot</comment>
- <comment xml:lang="pt_BR">Documento do Gnuplot</comment>
- <comment xml:lang="ro">Document Gnuplot</comment>
- <comment xml:lang="ru">Документ Gnuplot</comment>
- <comment xml:lang="sk">Dokument Gnuplot</comment>
- <comment xml:lang="sl">Dokument Gnuplot</comment>
- <comment xml:lang="sq">Dokument Gnuplot</comment>
- <comment xml:lang="sr">документ Гнуплота</comment>
- <comment xml:lang="sv">Gnuplot-dokument</comment>
- <comment xml:lang="tr">Gnuplot belgesi</comment>
- <comment xml:lang="uk">документ Gnuplot</comment>
- <comment xml:lang="vi">Tài liệu Gnuplot</comment>
- <comment xml:lang="zh_CN">Gnuplot 文档</comment>
<comment xml:lang="zh_TW">Gnuplot 文件</comment>
+ <comment xml:lang="zh_CN">Gnuplot 文档</comment>
+ <comment xml:lang="vi">Tài liệu Gnuplot</comment>
+ <comment xml:lang="uk">документ Gnuplot</comment>
+ <comment xml:lang="tr">Gnuplot belgesi</comment>
+ <comment xml:lang="sv">Gnuplot-dokument</comment>
+ <comment xml:lang="sr">документ Гнуплота</comment>
+ <comment xml:lang="sq">dokument Gnuplot</comment>
+ <comment xml:lang="sl">Dokument Gnuplot</comment>
+ <comment xml:lang="si">Gnuplot ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Gnuplot</comment>
+ <comment xml:lang="ru">Документ Gnuplot</comment>
+ <comment xml:lang="ro">Document Gnuplot</comment>
+ <comment xml:lang="pt_BR">Documento do Gnuplot</comment>
+ <comment xml:lang="pt">documento Gnuplot</comment>
+ <comment xml:lang="pl">Dokument Gnuplot</comment>
+ <comment xml:lang="oc">document Gnuplot</comment>
+ <comment xml:lang="nn">Gnuplot-dokument</comment>
+ <comment xml:lang="nl">Gnuplot-document</comment>
+ <comment xml:lang="nb">Gnuplot-dokument</comment>
+ <comment xml:lang="lv">Gnuplot dokuments</comment>
+ <comment xml:lang="lt">Gnuplot dokumentas</comment>
+ <comment xml:lang="ko">Gnuplot 문서</comment>
+ <comment xml:lang="kk">Gnuplot құжаты</comment>
+ <comment xml:lang="ja">Gnuplot ドキュメント</comment>
+ <comment xml:lang="it">Documento Gnuplot</comment>
+ <comment xml:lang="is">Gnuplot skjal</comment>
+ <comment xml:lang="id">Dokumen Gnuplot</comment>
+ <comment xml:lang="ia">Documento Gnuplot</comment>
+ <comment xml:lang="hu">Gnuplot dokumentum</comment>
+ <comment xml:lang="hr">Gnuplot dokument</comment>
+ <comment xml:lang="he">מסמך Gnuplot</comment>
+ <comment xml:lang="gl">documento de Gnuplot</comment>
+ <comment xml:lang="ga">cáipéis Gnuplot</comment>
+ <comment xml:lang="fur">document Gnuplot</comment>
+ <comment xml:lang="fr">document Gnuplot</comment>
+ <comment xml:lang="fo">Gnuplot skjal</comment>
+ <comment xml:lang="fi">Gnuplot-asiakirja</comment>
+ <comment xml:lang="eu">Gnuplot dokumentua</comment>
+ <comment xml:lang="es">documento de Gnuplot</comment>
+ <comment xml:lang="eo">Gnuplot-dokumento</comment>
+ <comment xml:lang="en_GB">Gnuplot document</comment>
+ <comment xml:lang="el">Έγγραφο Gnuplot</comment>
+ <comment xml:lang="de">Gnuplot-Dokument</comment>
+ <comment xml:lang="da">Gnuplot-dokument</comment>
+ <comment xml:lang="cs">dokument Gnuplot</comment>
+ <comment xml:lang="ca">document gnuplot</comment>
+ <comment xml:lang="bg">Документ — Gnuplot</comment>
+ <comment xml:lang="be@latin">Dakument Gnuplot</comment>
+ <comment xml:lang="be">дакумент Gnuplot</comment>
+ <comment xml:lang="ast">Documentu de Gnuplot</comment>
+ <comment xml:lang="ar">مستند Gnuplot</comment>
+ <comment xml:lang="af">Gnuplot-dokument</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.gp"/>
@@ -12419,389 +13375,422 @@
</mime-type>
<mime-type type="application/x-graphite">
<comment>Graphite scientific graph</comment>
- <comment xml:lang="ar">مبيان الجرافيت العلمي</comment>
- <comment xml:lang="be@latin">Navukovy hrafik Graphite</comment>
- <comment xml:lang="bg">Графика — Graphite</comment>
- <comment xml:lang="ca">gràfic científic Graphite</comment>
- <comment xml:lang="cs">vědecký graf Graphite</comment>
- <comment xml:lang="da">Graphite videnskabelig graf</comment>
- <comment xml:lang="de">Wissenschaftlicher Graphite-Graph</comment>
- <comment xml:lang="el">Επιστημονικό γράφημα Graphite</comment>
- <comment xml:lang="en_GB">Graphite scientific graph</comment>
- <comment xml:lang="eo">scienca grafikaĵo de Graphite</comment>
- <comment xml:lang="es">gráfico científico de Graphite</comment>
- <comment xml:lang="eu">Graphite - grafiko zientifikoak</comment>
- <comment xml:lang="fi">Graphite- tieteellinen graafi</comment>
- <comment xml:lang="fo">Grapite vísindarlig ritmynd</comment>
- <comment xml:lang="fr">graphe Graphite scientific</comment>
- <comment xml:lang="ga">graf eolaíochta Graphite</comment>
- <comment xml:lang="gl">gráfica científica de Graphite</comment>
- <comment xml:lang="he">תרשים מדעי של Graphite</comment>
- <comment xml:lang="hr">Graphite znanstveni grafikon</comment>
- <comment xml:lang="hu">Graphite tudományos grafikon</comment>
- <comment xml:lang="ia">Graphico scientific Graphite</comment>
- <comment xml:lang="id">Grafik sains Graphite</comment>
- <comment xml:lang="it">Grafico scientifico Graphite</comment>
- <comment xml:lang="ja">Graphite scientific グラフ</comment>
- <comment xml:lang="kk">Graphite ғылыми кескіні</comment>
- <comment xml:lang="ko">Graphite 과학 그래프</comment>
- <comment xml:lang="lt">Graphite mokslinė diagrama</comment>
- <comment xml:lang="lv">Graphite zinātniskais grafiks</comment>
- <comment xml:lang="ms">Graf saintifik Graphite</comment>
- <comment xml:lang="nb">Vitenskapelig graf fra Graphite</comment>
- <comment xml:lang="nl">Graphite wetenschappelijke grafiek</comment>
- <comment xml:lang="nn">Graphite vitskaplege graf</comment>
- <comment xml:lang="oc">graphe Graphite scientific</comment>
- <comment xml:lang="pl">Wykres naukowy Graphite</comment>
- <comment xml:lang="pt">gráfico científico Graphite</comment>
- <comment xml:lang="pt_BR">Gráfico científico do Graphite</comment>
- <comment xml:lang="ro">Grafic științific Graphite</comment>
- <comment xml:lang="ru">Научная диаграмма Graphite</comment>
- <comment xml:lang="sk">Vedecký graf Graphite</comment>
- <comment xml:lang="sl">Datoteka znanstvenega grafa Graphite</comment>
- <comment xml:lang="sq">Grafik shkencor Graphite </comment>
- <comment xml:lang="sr">Графитов научни графикони</comment>
- <comment xml:lang="sv">Vetenskaplig Graphite-grafer</comment>
- <comment xml:lang="tr">Graphite bilimsel grafiği</comment>
- <comment xml:lang="uk">наукова графіка Graphite</comment>
- <comment xml:lang="vi">Biểu đồ khoa học Graphite</comment>
- <comment xml:lang="zh_CN">Graphite 科学图形</comment>
<comment xml:lang="zh_TW">Graphite 科學圖表</comment>
+ <comment xml:lang="zh_CN">Graphite 科学图形</comment>
+ <comment xml:lang="vi">Biểu đồ khoa học Graphite</comment>
+ <comment xml:lang="uk">наукова графіка Graphite</comment>
+ <comment xml:lang="tr">Graphite bilimsel grafiği</comment>
+ <comment xml:lang="sv">Vetenskaplig Graphite-grafer</comment>
+ <comment xml:lang="sr">Графитов научни графикони</comment>
+ <comment xml:lang="sq">grafik shkencor Graphite</comment>
+ <comment xml:lang="sl">Datoteka znanstvenega grafa Graphite</comment>
+ <comment xml:lang="si">ග්රැෆයිට් විද්යාත්මක ප්රස්ථාරය</comment>
+ <comment xml:lang="sk">Vedecký graf Graphite</comment>
+ <comment xml:lang="ru">Научная диаграмма Graphite</comment>
+ <comment xml:lang="ro">Grafic științific Graphite</comment>
+ <comment xml:lang="pt_BR">Gráfico científico do Graphite</comment>
+ <comment xml:lang="pt">gráfico científico Graphite</comment>
+ <comment xml:lang="pl">Wykres naukowy Graphite</comment>
+ <comment xml:lang="oc">graphe Graphite scientific</comment>
+ <comment xml:lang="nn">Graphite vitskaplege graf</comment>
+ <comment xml:lang="nl">Graphite wetenschappelijke grafiek</comment>
+ <comment xml:lang="nb">Vitenskapelig graf fra Graphite</comment>
+ <comment xml:lang="ms">Graf saintifik Graphite</comment>
+ <comment xml:lang="lv">Graphite zinātniskais grafiks</comment>
+ <comment xml:lang="lt">Graphite mokslinė diagrama</comment>
+ <comment xml:lang="ko">Graphite 과학 그래프</comment>
+ <comment xml:lang="kk">Graphite ғылыми кескіні</comment>
+ <comment xml:lang="ja">Graphite scientific グラフ</comment>
+ <comment xml:lang="it">Grafico scientifico Graphite</comment>
+ <comment xml:lang="is">Graphite vísindalegt graf</comment>
+ <comment xml:lang="id">Grafik sains Graphite</comment>
+ <comment xml:lang="ia">Graphico scientific Graphite</comment>
+ <comment xml:lang="hu">Graphite tudományos grafikon</comment>
+ <comment xml:lang="hr">Graphite znanstveni grafikon</comment>
+ <comment xml:lang="he">תרשים מדעי של Graphite</comment>
+ <comment xml:lang="gl">gráfica científica de Graphite</comment>
+ <comment xml:lang="ga">graf eolaíochta Graphite</comment>
+ <comment xml:lang="fur">grafic sientific Graphite</comment>
+ <comment xml:lang="fr">graphe Graphite scientific</comment>
+ <comment xml:lang="fo">Grapite vísindarlig ritmynd</comment>
+ <comment xml:lang="fi">Graphite- tieteellinen graafi</comment>
+ <comment xml:lang="eu">Graphite - grafiko zientifikoak</comment>
+ <comment xml:lang="es">gráfico científico de Graphite</comment>
+ <comment xml:lang="eo">scienca grafikaĵo de Graphite</comment>
+ <comment xml:lang="en_GB">Graphite scientific graph</comment>
+ <comment xml:lang="el">Επιστημονικό γράφημα Graphite</comment>
+ <comment xml:lang="de">Wissenschaftlicher Graphite-Graph</comment>
+ <comment xml:lang="da">Graphite videnskabelig graf</comment>
+ <comment xml:lang="cs">vědecký graf Graphite</comment>
+ <comment xml:lang="ca">gràfic científic Graphite</comment>
+ <comment xml:lang="bg">Графика — Graphite</comment>
+ <comment xml:lang="be@latin">Navukovy hrafik Graphite</comment>
+ <comment xml:lang="be">навуковы граф Graphite</comment>
+ <comment xml:lang="ar">مبيان جرافيت علمي</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.gra"/>
</mime-type>
<mime-type type="application/x-gtktalog">
<comment>GTKtalog catalog</comment>
- <comment xml:lang="ar">كتالوج GTKtalog</comment>
- <comment xml:lang="be@latin">Kataloh GTKtalog</comment>
- <comment xml:lang="bg">Каталог — Gtktalog</comment>
- <comment xml:lang="ca">catàleg de GTKtalog</comment>
- <comment xml:lang="cs">katalog GTKtalog</comment>
- <comment xml:lang="da">GTKtalog-katalog</comment>
- <comment xml:lang="de">GTKtalog-Katalog</comment>
- <comment xml:lang="el">Κατάλογος GTKtalog</comment>
- <comment xml:lang="en_GB">GTKtalog catalogue</comment>
- <comment xml:lang="eo">katalogo de GTKtalog</comment>
- <comment xml:lang="es">catálogo de GTKtalog</comment>
- <comment xml:lang="eu">Gtktalog katalogoa</comment>
- <comment xml:lang="fi">GTKtalog-luettelo</comment>
- <comment xml:lang="fo">GTKtalog skrá</comment>
- <comment xml:lang="fr">catalogue Gtktalog</comment>
- <comment xml:lang="ga">catalóg GTKtalog</comment>
- <comment xml:lang="gl">catálogo de GTKtalog</comment>
- <comment xml:lang="he">קטלוג GTKtalog</comment>
- <comment xml:lang="hr">GTKtalog katalog</comment>
- <comment xml:lang="hu">GTKtalog-katalógus</comment>
- <comment xml:lang="ia">Catalogo GTKtalog</comment>
- <comment xml:lang="id">Katalog GTKtalog</comment>
- <comment xml:lang="it">Catalogo GTKtalog</comment>
- <comment xml:lang="ja">GTKtalog カタログ</comment>
- <comment xml:lang="ka">GTKtalog-ის კატალოგი</comment>
- <comment xml:lang="kk">GTKtalog каталогы</comment>
- <comment xml:lang="ko">GTKtalog 카탈로그</comment>
- <comment xml:lang="lt">GTKtalog katalogas</comment>
- <comment xml:lang="lv">GTKtalog katalogs</comment>
- <comment xml:lang="ms">Katalog GTKtalog</comment>
- <comment xml:lang="nb">GTKtalog-katalog</comment>
- <comment xml:lang="nl">GTKtalog-catalogus</comment>
- <comment xml:lang="nn">GTKtalog-katalog</comment>
- <comment xml:lang="oc">catalòg Gtktalog</comment>
- <comment xml:lang="pl">Katalog programu GTKtalog</comment>
- <comment xml:lang="pt">catálogo GTKtalog</comment>
- <comment xml:lang="pt_BR">Catálogo GTKtalog</comment>
- <comment xml:lang="ro">Catalog GTKalog</comment>
- <comment xml:lang="ru">Каталог GTKtalog</comment>
- <comment xml:lang="sk">Katalóg GTKtalog</comment>
- <comment xml:lang="sl">Datoteka kataloga GTKtalog</comment>
- <comment xml:lang="sq">Katallog GTKtalog</comment>
- <comment xml:lang="sr">каталог ГТКталога</comment>
- <comment xml:lang="sv">GTKtalog-katalog</comment>
- <comment xml:lang="tr">Gtktalog kataloğu</comment>
- <comment xml:lang="uk">каталог GTKtalog</comment>
- <comment xml:lang="vi">Phân loại GTKtalog</comment>
- <comment xml:lang="zh_CN">GTKtalog 目录</comment>
<comment xml:lang="zh_TW">GTKtalog 光碟目錄</comment>
+ <comment xml:lang="zh_CN">GTKtalog 目录</comment>
+ <comment xml:lang="vi">Phân loại GTKtalog</comment>
+ <comment xml:lang="uk">каталог GTKtalog</comment>
+ <comment xml:lang="tr">GTKtalog kataloğu</comment>
+ <comment xml:lang="sv">GTKtalog-katalog</comment>
+ <comment xml:lang="sr">каталог ГТКталога</comment>
+ <comment xml:lang="sq">katalog GTKtalog</comment>
+ <comment xml:lang="sl">Datoteka kataloga GTKtalog</comment>
+ <comment xml:lang="si">GTKtalog නාමාවලිය</comment>
+ <comment xml:lang="sk">Katalóg GTKtalog</comment>
+ <comment xml:lang="ru">Каталог GTKtalog</comment>
+ <comment xml:lang="ro">Catalog GTKalog</comment>
+ <comment xml:lang="pt_BR">Catálogo GTKtalog</comment>
+ <comment xml:lang="pt">catálogo GTKtalog</comment>
+ <comment xml:lang="pl">Katalog programu GTKtalog</comment>
+ <comment xml:lang="oc">catalòg Gtktalog</comment>
+ <comment xml:lang="nn">GTKtalog-katalog</comment>
+ <comment xml:lang="nl">GTKtalog-catalogus</comment>
+ <comment xml:lang="nb">GTKtalog-katalog</comment>
+ <comment xml:lang="ms">Katalog GTKtalog</comment>
+ <comment xml:lang="lv">GTKtalog katalogs</comment>
+ <comment xml:lang="lt">GTKtalog katalogas</comment>
+ <comment xml:lang="ko">GTKtalog 카탈로그</comment>
+ <comment xml:lang="kk">GTKtalog каталогы</comment>
+ <comment xml:lang="ka">GTKtalog-ის კატალოგი</comment>
+ <comment xml:lang="ja">GTKtalog カタログ</comment>
+ <comment xml:lang="it">Catalogo GTKtalog</comment>
+ <comment xml:lang="is">GTKtalog efnisskrá</comment>
+ <comment xml:lang="id">Katalog GTKtalog</comment>
+ <comment xml:lang="ia">Catalogo GTKtalog</comment>
+ <comment xml:lang="hu">GTKtalog-katalógus</comment>
+ <comment xml:lang="hr">GTKtalog katalog</comment>
+ <comment xml:lang="he">קטלוג GTKtalog</comment>
+ <comment xml:lang="gl">catálogo de GTKtalog</comment>
+ <comment xml:lang="ga">catalóg GTKtalog</comment>
+ <comment xml:lang="fur">catalic GTKtalog</comment>
+ <comment xml:lang="fr">catalogue Gtktalog</comment>
+ <comment xml:lang="fo">GTKtalog skrá</comment>
+ <comment xml:lang="fi">GTKtalog-luettelo</comment>
+ <comment xml:lang="eu">Gtktalog katalogoa</comment>
+ <comment xml:lang="es">catálogo de GTKtalog</comment>
+ <comment xml:lang="eo">katalogo de GTKtalog</comment>
+ <comment xml:lang="en_GB">GTKtalog catalogue</comment>
+ <comment xml:lang="el">Κατάλογος GTKtalog</comment>
+ <comment xml:lang="de">GTKtalog-Katalog</comment>
+ <comment xml:lang="da">GTKtalog-katalog</comment>
+ <comment xml:lang="cs">katalog GTKtalog</comment>
+ <comment xml:lang="ca">catàleg de GTKtalog</comment>
+ <comment xml:lang="bg">Каталог — Gtktalog</comment>
+ <comment xml:lang="be@latin">Kataloh GTKtalog</comment>
+ <comment xml:lang="be">каталог GTKtalog</comment>
+ <comment xml:lang="ar">كتالوج GTKtalog</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="gtktalog " type="string" offset="4"/>
+ <magic>
+ <match type="string" value="gtktalog " offset="4"/>
</magic>
</mime-type>
<mime-type type="application/x-gzdvi">
<comment>TeX DVI document (gzip-compressed)</comment>
- <comment xml:lang="ar">مستند TeX DVI (مضغوط-gzip)</comment>
- <comment xml:lang="ast">Documentu Tex DVI (comprimíu en gzip)</comment>
- <comment xml:lang="be@latin">Dakument TeX DVI (gzip-skampresavany)</comment>
- <comment xml:lang="bg">Документ — TeX DVI, компресиран с gzip</comment>
- <comment xml:lang="ca">document DVI de TeX (amb compressió gzip)</comment>
- <comment xml:lang="cs">dokument TeX DVI (komprimovaný pomocí gzip)</comment>
- <comment xml:lang="da">TeX DVI-dokument (gzip-komprimeret)</comment>
- <comment xml:lang="de">TeX-DVI-Dokument (gzip-komprimiert)</comment>
- <comment xml:lang="el">Έγγραφο TeX DVI (συμπιεσμένο με gzip)</comment>
- <comment xml:lang="en_GB">TeX DVI document (gzip-compressed)</comment>
- <comment xml:lang="es">documento DVI de TeX (comprimido con gzip)</comment>
- <comment xml:lang="eu">TeX DVI dokumentua (gzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">TeX DVI -asiakirja (gzip-pakattu)</comment>
- <comment xml:lang="fo">TeX DVI skjal (gzip-stappað)</comment>
- <comment xml:lang="fr">document DVI TeX (compressé gzip)</comment>
- <comment xml:lang="ga">cáipéis DVI TeX (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">documento DVI de TeX (comprimido con gzip)</comment>
- <comment xml:lang="he">מסמך מסוג TeX DVI (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">TeX DVI dokument (gzip sažet)</comment>
- <comment xml:lang="hu">TeX DVI dokumentum (gzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Documento TeX DVI (comprimite con gzip)</comment>
- <comment xml:lang="id">Dokumen TeX DVI (terkompresi gzip)</comment>
- <comment xml:lang="it">Documento Tex DVI (compresso con gzip)</comment>
- <comment xml:lang="ja">Tex DVI ドキュメント (gzip 圧縮)</comment>
- <comment xml:lang="kk">TeX DVI құжаты (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">TeX DVI 문서(GZIP 압축)</comment>
- <comment xml:lang="lt">TeX DVI dokumentas (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">TeX DVI dokuments (saspiests ar gzip)</comment>
- <comment xml:lang="nb">TeX DVI-dokument (gzip-komprimert)</comment>
- <comment xml:lang="nl">TeX DVI-document (ingepakt met gzip)</comment>
- <comment xml:lang="nn">TeX DVI-dokument (pakka med gzip)</comment>
- <comment xml:lang="oc">document DVI TeX (compressat gzip)</comment>
- <comment xml:lang="pl">Dokument TeX DVI (kompresja gzip)</comment>
- <comment xml:lang="pt">documento TeX DVI (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Documento DVI TeX (compactado com gzip)</comment>
- <comment xml:lang="ro">Document TeX DVI (comprimat gzip)</comment>
- <comment xml:lang="ru">Документ TeX DVI (сжатый gzip)</comment>
- <comment xml:lang="sk">Dokument TeX DVI (komprimovaný pomocou gzip)</comment>
- <comment xml:lang="sl">Dokument TeX DVI (stisnjen z gzip)</comment>
- <comment xml:lang="sq">Dokument TeX DVI (i kompresuar me gzip)</comment>
- <comment xml:lang="sr">ТеКс ДВИ документ (запакован гзип-ом)</comment>
- <comment xml:lang="sv">TeX DVI-dokument (gzip-komprimerat)</comment>
- <comment xml:lang="tr">TeX DVI belgesi (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ TeX DVI (стиснений gzip)</comment>
- <comment xml:lang="vi">Tài liệu DVI TeX (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">TeX DVI 文件 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">TeX DVI 文档(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">TeX DVI 文件 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Tài liệu DVI TeX (đã nén gzip)</comment>
+ <comment xml:lang="uk">документ TeX DVI (стиснений gzip)</comment>
+ <comment xml:lang="tr">TeX DVI belgesi (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">TeX DVI-dokument (gzip-komprimerat)</comment>
+ <comment xml:lang="sr">ТеКс ДВИ документ (запакован гзип-ом)</comment>
+ <comment xml:lang="sq">dokument TeX DVI (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Dokument TeX DVI (stisnjen z gzip)</comment>
+ <comment xml:lang="si">TeX DVI ලේඛනය (gzip-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Dokument TeX DVI (komprimovaný pomocou gzip)</comment>
+ <comment xml:lang="ru">Документ DVI издательской системы TeX (сжатый gzip)</comment>
+ <comment xml:lang="ro">Document TeX DVI (comprimat gzip)</comment>
+ <comment xml:lang="pt_BR">Documento DVI TeX (compactado com gzip)</comment>
+ <comment xml:lang="pt">documento TeX DVI (compressão gzip)</comment>
+ <comment xml:lang="pl">Dokument TeX DVI (kompresja gzip)</comment>
+ <comment xml:lang="oc">document DVI TeX (compressat gzip)</comment>
+ <comment xml:lang="nn">TeX DVI-dokument (pakka med gzip)</comment>
+ <comment xml:lang="nl">TeX DVI-document (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">TeX DVI-dokument (gzip-komprimert)</comment>
+ <comment xml:lang="lv">TeX DVI dokuments (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">TeX DVI dokumentas (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">TeX DVI 문서(GZIP 압축)</comment>
+ <comment xml:lang="kk">TeX DVI құжаты (gzip-пен сығылған)</comment>
+ <comment xml:lang="ja">Tex DVI ドキュメント (gzip 圧縮)</comment>
+ <comment xml:lang="it">Documento Tex DVI (compresso con gzip)</comment>
+ <comment xml:lang="is">TeX DVI skjal (gzip-þjappað)</comment>
+ <comment xml:lang="id">Dokumen TeX DVI (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Documento TeX DVI (comprimite con gzip)</comment>
+ <comment xml:lang="hu">TeX DVI dokumentum (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">TeX DVI dokument (gzip sažet)</comment>
+ <comment xml:lang="he">מסמך מסוג TeX DVI (מכווץ ע״י gzip)</comment>
+ <comment xml:lang="gl">documento DVI de TeX (comprimido con gzip)</comment>
+ <comment xml:lang="ga">cáipéis DVI TeX (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">document DVI TeX (comprimût cun gzip)</comment>
+ <comment xml:lang="fr">document DVI TeX (compressé gzip)</comment>
+ <comment xml:lang="fo">TeX DVI skjal (gzip-stappað)</comment>
+ <comment xml:lang="fi">TeX DVI -asiakirja (gzip-pakattu)</comment>
+ <comment xml:lang="eu">TeX DVI dokumentua (gzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">documento DVI de TeX (comprimido con GZIP)</comment>
+ <comment xml:lang="en_GB">TeX DVI document (gzip-compressed)</comment>
+ <comment xml:lang="el">Έγγραφο TeX DVI (συμπιεσμένο με gzip)</comment>
+ <comment xml:lang="de">TeX-DVI-Dokument (gzip-komprimiert)</comment>
+ <comment xml:lang="da">TeX DVI-dokument (gzip-komprimeret)</comment>
+ <comment xml:lang="cs">dokument TeX DVI (komprimovaný pomocí gzip)</comment>
+ <comment xml:lang="ca">document DVI de TeX (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Документ — TeX DVI, компресиран с gzip</comment>
+ <comment xml:lang="be@latin">Dakument TeX DVI (gzip-skampresavany)</comment>
+ <comment xml:lang="be">дакумент TeX DVI (сцісканне gzip)</comment>
+ <comment xml:lang="ast">Documentu Tex DVI (comprimíu en gzip)</comment>
+ <comment xml:lang="ar">مستند TeX DVI (مضغوط-gzip)</comment>
+ <comment xml:lang="af">TeX DVI-dokument (gzip-saamgepers)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.dvi.gz"/>
</mime-type>
<mime-type type="application/gzip">
<comment>Gzip archive</comment>
- <comment xml:lang="ar">أرشيف Gzip</comment>
- <comment xml:lang="be@latin">Archiŭ gzip</comment>
- <comment xml:lang="bg">Архив — gzip</comment>
- <comment xml:lang="ca">arxiu gzip</comment>
- <comment xml:lang="cs">archiv gzip</comment>
- <comment xml:lang="da">Gzip-arkiv</comment>
- <comment xml:lang="de">Gzip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Gzip</comment>
- <comment xml:lang="en_GB">Gzip archive</comment>
- <comment xml:lang="eo">Gzip-arkivo</comment>
- <comment xml:lang="es">archivador Gzip</comment>
- <comment xml:lang="eu">Gzip artxiboa</comment>
- <comment xml:lang="fi">Gzip-arkisto</comment>
- <comment xml:lang="fo">Gzip skjalasavn</comment>
- <comment xml:lang="fr">archive gzip</comment>
- <comment xml:lang="ga">cartlann Gzip</comment>
- <comment xml:lang="gl">arquivo Gzip</comment>
- <comment xml:lang="he">ארכיון Gzip</comment>
- <comment xml:lang="hr">Gzip arhiva</comment>
- <comment xml:lang="hu">Gzip archívum</comment>
- <comment xml:lang="ia">Archivo Gzip</comment>
- <comment xml:lang="id">Arsip Gzip</comment>
- <comment xml:lang="it">Archivio gzip</comment>
- <comment xml:lang="ja">Gzip アーカイブ</comment>
- <comment xml:lang="kk">Gzip архиві</comment>
- <comment xml:lang="ko">GZIP 압축 파일</comment>
- <comment xml:lang="lt">Gzip archyvas</comment>
- <comment xml:lang="lv">Gzip arhīvs</comment>
- <comment xml:lang="nb">Gzip-arkiv</comment>
- <comment xml:lang="nl">Gzip-archief</comment>
- <comment xml:lang="nn">Gzip-arkiv</comment>
- <comment xml:lang="oc">archiu gzip</comment>
- <comment xml:lang="pl">Archiwum gzip</comment>
- <comment xml:lang="pt">arquivo Gzip</comment>
- <comment xml:lang="pt_BR">Pacote Gzip</comment>
- <comment xml:lang="ro">Arhivă Gzip</comment>
- <comment xml:lang="ru">Архив GZIP</comment>
- <comment xml:lang="sk">Archív gzip</comment>
- <comment xml:lang="sl">Datoteka arhiva Gzip</comment>
- <comment xml:lang="sq">Arkiv gzip</comment>
- <comment xml:lang="sr">Гзип архива</comment>
- <comment xml:lang="sv">Gzip-arkiv</comment>
- <comment xml:lang="tr">Gzip arşivi</comment>
- <comment xml:lang="uk">архів gzip</comment>
- <comment xml:lang="vi">Kho nén gzip</comment>
- <comment xml:lang="zh_CN">Gzip 归档文件</comment>
<comment xml:lang="zh_TW">Gzip 封存檔</comment>
+ <comment xml:lang="zh_CN">Gzip 归档文件</comment>
+ <comment xml:lang="vi">Kho nén gzip</comment>
+ <comment xml:lang="uk">архів gzip</comment>
+ <comment xml:lang="tr">Gzip arşivi</comment>
+ <comment xml:lang="sv">Gzip-arkiv</comment>
+ <comment xml:lang="sr">Гзип архива</comment>
+ <comment xml:lang="sq">arkiv gzip</comment>
+ <comment xml:lang="sl">Datoteka arhiva Gzip</comment>
+ <comment xml:lang="si">Gzip සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Gzip</comment>
+ <comment xml:lang="ru">Архив GZIP</comment>
+ <comment xml:lang="ro">Arhivă Gzip</comment>
+ <comment xml:lang="pt_BR">Pacote Gzip</comment>
+ <comment xml:lang="pt">arquivo Gzip</comment>
+ <comment xml:lang="pl">Archiwum gzip</comment>
+ <comment xml:lang="oc">archiu gzip</comment>
+ <comment xml:lang="nn">Gzip-arkiv</comment>
+ <comment xml:lang="nl">Gzip-archief</comment>
+ <comment xml:lang="nb">Gzip-arkiv</comment>
+ <comment xml:lang="lv">Gzip arhīvs</comment>
+ <comment xml:lang="lt">Gzip archyvas</comment>
+ <comment xml:lang="ko">GZIP 압축 파일</comment>
+ <comment xml:lang="kk">Gzip архиві</comment>
+ <comment xml:lang="ja">Gzip アーカイブ</comment>
+ <comment xml:lang="it">Archivio gzip</comment>
+ <comment xml:lang="is">gzip safnskrá</comment>
+ <comment xml:lang="id">Arsip Gzip</comment>
+ <comment xml:lang="ia">Archivo Gzip</comment>
+ <comment xml:lang="hu">Gzip archívum</comment>
+ <comment xml:lang="hr">Gzip arhiva</comment>
+ <comment xml:lang="he">ארכיון Gzip</comment>
+ <comment xml:lang="gl">arquivo Gzip</comment>
+ <comment xml:lang="ga">cartlann Gzip</comment>
+ <comment xml:lang="fur">archivi Gzip</comment>
+ <comment xml:lang="fr">archive gzip</comment>
+ <comment xml:lang="fo">Gzip skjalasavn</comment>
+ <comment xml:lang="fi">Gzip-arkisto</comment>
+ <comment xml:lang="eu">Gzip artxiboa</comment>
+ <comment xml:lang="es">archivador GZIP</comment>
+ <comment xml:lang="eo">Gzip-arkivo</comment>
+ <comment xml:lang="en_GB">Gzip archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Gzip</comment>
+ <comment xml:lang="de">Gzip-Archiv</comment>
+ <comment xml:lang="da">Gzip-arkiv</comment>
+ <comment xml:lang="cs">archiv gzip</comment>
+ <comment xml:lang="ca">arxiu gzip</comment>
+ <comment xml:lang="bg">Архив — gzip</comment>
+ <comment xml:lang="be@latin">Archiŭ gzip</comment>
+ <comment xml:lang="be">архіў gzip</comment>
+ <comment xml:lang="ar">أرشيف Gzip</comment>
+ <comment xml:lang="af">Gzip-argief</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="\037\213" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\037\213" offset="0"/>
</magic>
<glob pattern="*.gz"/>
<alias type="application/x-gzip"/>
</mime-type>
<mime-type type="application/x-gzpdf">
<comment>PDF document (gzip-compressed)</comment>
- <comment xml:lang="ar">مستند PDF (مضغوط-gzip)</comment>
- <comment xml:lang="ast">Documentu PDF (comprimíu en gzip)</comment>
- <comment xml:lang="be@latin">Dakument PDF (gzip-skampresavany)</comment>
- <comment xml:lang="bg">Документ — PDF, компресиран с gzip</comment>
- <comment xml:lang="ca">document PDF (amb compressió gzip)</comment>
- <comment xml:lang="cs">dokument PDF (komprimovaný pomocí gzip)</comment>
- <comment xml:lang="da">PDF-dokument (gzip-komprimeret)</comment>
- <comment xml:lang="de">PDF-Dokument (gzip-komprimiert)</comment>
- <comment xml:lang="el">Έγγραφο PDF (συμπιεσμένο με gzip)</comment>
- <comment xml:lang="en_GB">PDF document (gzip-compressed)</comment>
- <comment xml:lang="es">documento PDF (comprimido con gzip)</comment>
- <comment xml:lang="eu">PDF dokumentua (gzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">PDF-asiakirja (gzip-pakattu)</comment>
- <comment xml:lang="fo">PDF skjal (gzip-stappað)</comment>
- <comment xml:lang="fr">document PDF (compressé gzip)</comment>
- <comment xml:lang="ga">cáipéis PDF (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">documento PDF (comprimido en gzip)</comment>
- <comment xml:lang="he">מסמך PDF (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">PDF dokument (gzip sažet)</comment>
- <comment xml:lang="hu">PDF dokumentum (gzip-tömörítésű)</comment>
- <comment xml:lang="ia">Documento PDF (comprimite con gzip)</comment>
- <comment xml:lang="id">Dokumen PDF (terkompresi gzip)</comment>
- <comment xml:lang="it">Documento PDF (compresso con gzip)</comment>
- <comment xml:lang="ja">PDF ドキュメント (gzip 圧縮)</comment>
- <comment xml:lang="kk">PDF құжаты (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">PDF 문서(GZIP 압축)</comment>
- <comment xml:lang="lt">PDF dokumentas (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">PDF dokuments (saspiests ar gzip)</comment>
- <comment xml:lang="nb">PDF-dokument (gzip-komprimert)</comment>
- <comment xml:lang="nl">PDF-document (ingepakt met gzip)</comment>
- <comment xml:lang="nn">PDF-dokument (pakka med gzip)</comment>
- <comment xml:lang="oc">document PDF (compressat gzip)</comment>
- <comment xml:lang="pl">Dokument PDF (kompresja gzip)</comment>
- <comment xml:lang="pt">documento PDF (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Documento PDF (compactado com gzip)</comment>
- <comment xml:lang="ro">Document PDF (comprimat gzip)</comment>
- <comment xml:lang="ru">Документ PDF (сжатый gzip)</comment>
- <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou gzip)</comment>
- <comment xml:lang="sl">Dokument PDF (stisnjen z gzip)</comment>
- <comment xml:lang="sq">Dokument PDF (i kompresuar me gzip)</comment>
- <comment xml:lang="sr">ПДФ документ (запакован гзип-ом)</comment>
- <comment xml:lang="sv">PDF-dokument (gzip-komprimerat)</comment>
- <comment xml:lang="tr">PDF belgesi (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ PDF (стиснений gzip)</comment>
- <comment xml:lang="vi">Tài liệu PDF (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">PDF 文件 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">PDF 文档(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">PDF 文件 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Tài liệu PDF (đã nén gzip)</comment>
+ <comment xml:lang="uk">документ PDF (стиснений gzip)</comment>
+ <comment xml:lang="tr">PDF belgesi (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">PDF-dokument (gzip-komprimerat)</comment>
+ <comment xml:lang="sr">ПДФ документ (запакован гзип-ом)</comment>
+ <comment xml:lang="sq">dokument PDF (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Dokument PDF (stisnjen z gzip)</comment>
+ <comment xml:lang="si">PDF ලේඛනය (gzip-compressed)</comment>
+ <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou gzip)</comment>
+ <comment xml:lang="ru">Документ PDF (сжатый gzip)</comment>
+ <comment xml:lang="ro">Document PDF (comprimat gzip)</comment>
+ <comment xml:lang="pt_BR">Documento PDF (compactado com gzip)</comment>
+ <comment xml:lang="pt">documento PDF (compressão gzip)</comment>
+ <comment xml:lang="pl">Dokument PDF (kompresja gzip)</comment>
+ <comment xml:lang="oc">document PDF (compressat gzip)</comment>
+ <comment xml:lang="nn">PDF-dokument (pakka med gzip)</comment>
+ <comment xml:lang="nl">PDF-document (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">PDF-dokument (gzip-komprimert)</comment>
+ <comment xml:lang="lv">PDF dokuments (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">PDF dokumentas (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">PDF 문서(GZIP 압축)</comment>
+ <comment xml:lang="kk">PDF құжаты (gzip-пен сығылған)</comment>
+ <comment xml:lang="ja">PDF ドキュメント (gzip 圧縮)</comment>
+ <comment xml:lang="it">Documento PDF (compresso con gzip)</comment>
+ <comment xml:lang="is">PDF skjal (gzip-þjappað)</comment>
+ <comment xml:lang="id">Dokumen PDF (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Documento PDF (comprimite con gzip)</comment>
+ <comment xml:lang="hu">PDF dokumentum (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">PDF dokument (gzip sažet)</comment>
+ <comment xml:lang="he">מסמך PDF (מכווץ ע״י gzip)</comment>
+ <comment xml:lang="gl">documento PDF (comprimido en gzip)</comment>
+ <comment xml:lang="ga">cáipéis PDF (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">document PDF (comprimût cun gzip)</comment>
+ <comment xml:lang="fr">document PDF (compressé gzip)</comment>
+ <comment xml:lang="fo">PDF skjal (gzip-stappað)</comment>
+ <comment xml:lang="fi">PDF-asiakirja (gzip-pakattu)</comment>
+ <comment xml:lang="eu">PDF dokumentua (gzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">documento PDF (comprimido con GZIP)</comment>
+ <comment xml:lang="en_GB">PDF document (gzip-compressed)</comment>
+ <comment xml:lang="el">Έγγραφο PDF (συμπιεσμένο με gzip)</comment>
+ <comment xml:lang="de">PDF-Dokument (gzip-komprimiert)</comment>
+ <comment xml:lang="da">PDF-dokument (gzip-komprimeret)</comment>
+ <comment xml:lang="cs">dokument PDF (komprimovaný pomocí gzip)</comment>
+ <comment xml:lang="ca">document PDF (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Документ — PDF, компресиран с gzip</comment>
+ <comment xml:lang="be@latin">Dakument PDF (gzip-skampresavany)</comment>
+ <comment xml:lang="be">дакумент PDF (сцісканне gzip)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en gzip)</comment>
+ <comment xml:lang="ar">مستند PDF (مضغوط-gzip)</comment>
+ <comment xml:lang="af">PDF-dokument (gzip-saamgepers)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.pdf.gz"/>
</mime-type>
<mime-type type="application/x-gzpostscript">
<comment>PostScript document (gzip-compressed)</comment>
- <comment xml:lang="ar">مستند PostScript (مضغوط-gzip)</comment>
- <comment xml:lang="ast">Documentu PostScript (comprimíu en gzip)</comment>
- <comment xml:lang="be@latin">Dakument PostScript (gzip-skampresavany)</comment>
- <comment xml:lang="bg">Документ — PostScript, компресиран с gzip</comment>
- <comment xml:lang="ca">document PostScript (amb compressió gzip)</comment>
- <comment xml:lang="cs">dokument PostScript (komprimovaný pomocí gzip)</comment>
- <comment xml:lang="da">PostScript-dokument (gzip-komprimeret)</comment>
- <comment xml:lang="de">PostScript-Dokument (gzip-komprimiert)</comment>
- <comment xml:lang="el">Έγγραφο PostScript (συμπιεσμένο με gzip)</comment>
- <comment xml:lang="en_GB">PostScript document (gzip-compressed)</comment>
- <comment xml:lang="eo">PostScript-dokumento (kunpremita per gzip)</comment>
- <comment xml:lang="es">documento PostScript (comprimido con gzip)</comment>
- <comment xml:lang="eu">PostScript dokumentua (gzip-konprimitua)</comment>
- <comment xml:lang="fi">PostScript-asiakirja (gzip-pakattu)</comment>
- <comment xml:lang="fo">PostScript skjal (gzip-stappað)</comment>
- <comment xml:lang="fr">document PostScript (compressé gzip)</comment>
- <comment xml:lang="ga">cáipéis PostScript (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">documento PostScript (comprimido con gzip)</comment>
- <comment xml:lang="he">מסמך PostScript (מכוות ע״י gzip)</comment>
- <comment xml:lang="hr">PostScript dokument (gzip sažet)</comment>
- <comment xml:lang="hu">PostScript-dokumentum (gzip-pel tömörítve)</comment>
- <comment xml:lang="ia">Documento PostScript (comprimite con gzip)</comment>
- <comment xml:lang="id">Dokumen PostScript (terkompresi gzip)</comment>
- <comment xml:lang="it">Documento PostScript (compresso con gzip)</comment>
- <comment xml:lang="ja">PostScript ドキュメント (gzip 圧縮)</comment>
- <comment xml:lang="kk">PostScript құжаты (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">PostScript 문서(GZIP 압축)</comment>
- <comment xml:lang="lt">PostScript dokumentas (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">PostScript dokuments (saspiests ar gzip)</comment>
- <comment xml:lang="ms">Dokumen PostScript (dimampatkan-gzip)</comment>
- <comment xml:lang="nb">PostScript-dokument (gzip-komprimert)</comment>
- <comment xml:lang="nl">PostScript-document (ingepakt met gzip)</comment>
- <comment xml:lang="nn">PostScript-dokument (pakka med gzip)</comment>
- <comment xml:lang="oc">document PostEscript (compressat gzip)</comment>
- <comment xml:lang="pl">Dokument Postscript (kompresja gzip)</comment>
- <comment xml:lang="pt">documento PostScript (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Documento PostScript (compactado com gzip)</comment>
- <comment xml:lang="ro">Document PostScript (comprimat gzip)</comment>
- <comment xml:lang="ru">Документ PostScript (сжатый gzip)</comment>
- <comment xml:lang="sk">Dokument PostScript (komprimovaný pomocou gzip)</comment>
- <comment xml:lang="sl">Dokument PostScript (stisnjen z gzip)</comment>
- <comment xml:lang="sq">Dokument PostScript (i kompresuar me gzip)</comment>
- <comment xml:lang="sr">Постскрипт документ (запакован гзип-ом)</comment>
- <comment xml:lang="sv">Postscript-dokument (gzip-komprimerat)</comment>
- <comment xml:lang="tr">PostScript belgesi (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ PostScript (стиснене gzip)</comment>
- <comment xml:lang="vi">Tài liệu PostScript (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">PostScript 文件 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">PostScript 文档(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">PostScript 文件 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Tài liệu PostScript (đã nén gzip)</comment>
+ <comment xml:lang="uk">документ PostScript (стиснене gzip)</comment>
+ <comment xml:lang="tr">PostScript belgesi (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Postscript-dokument (gzip-komprimerat)</comment>
+ <comment xml:lang="sr">Постскрипт документ (запакован гзип-ом)</comment>
+ <comment xml:lang="sq">dokument PostScript (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Dokument PostScript (stisnjen z gzip)</comment>
+ <comment xml:lang="si">PostScript ලේඛනය (gzip-compressed)</comment>
+ <comment xml:lang="sk">Dokument PostScript (komprimovaný pomocou gzip)</comment>
+ <comment xml:lang="ru">Документ PostScript (сжатый gzip)</comment>
+ <comment xml:lang="ro">Document PostScript (comprimat gzip)</comment>
+ <comment xml:lang="pt_BR">Documento PostScript (compactado com gzip)</comment>
+ <comment xml:lang="pt">documento PostScript (compressão gzip)</comment>
+ <comment xml:lang="pl">Dokument PostScript (kompresja gzip)</comment>
+ <comment xml:lang="oc">document PostEscript (compressat gzip)</comment>
+ <comment xml:lang="nn">PostScript-dokument (pakka med gzip)</comment>
+ <comment xml:lang="nl">PostScript-document (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">PostScript-dokument (gzip-komprimert)</comment>
+ <comment xml:lang="ms">Dokumen PostScript (dimampatkan-gzip)</comment>
+ <comment xml:lang="lv">PostScript dokuments (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">PostScript dokumentas (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">PostScript 문서(GZIP 압축)</comment>
+ <comment xml:lang="kk">PostScript құжаты (gzip-пен сығылған)</comment>
+ <comment xml:lang="ja">PostScript ドキュメント (gzip 圧縮)</comment>
+ <comment xml:lang="it">Documento PostScript (compresso con gzip)</comment>
+ <comment xml:lang="is">PostScript skjal (gzip-þjappað)</comment>
+ <comment xml:lang="id">Dokumen PostScript (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Documento PostScript (comprimite con gzip)</comment>
+ <comment xml:lang="hu">PostScript-dokumentum (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">PostScript dokument (gzip sažet)</comment>
+ <comment xml:lang="he">מסמך PostScript (מכוות ע״י gzip)</comment>
+ <comment xml:lang="gl">documento PostScript (comprimido con gzip)</comment>
+ <comment xml:lang="ga">cáipéis PostScript (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">document PostScript (comprimût cun gzip)</comment>
+ <comment xml:lang="fr">document PostScript (compressé gzip)</comment>
+ <comment xml:lang="fo">PostScript skjal (gzip-stappað)</comment>
+ <comment xml:lang="fi">PostScript-asiakirja (gzip-pakattu)</comment>
+ <comment xml:lang="eu">PostScript dokumentua (gzip-konprimitua)</comment>
+ <comment xml:lang="es">documento PostScript (comprimido con GZIP)</comment>
+ <comment xml:lang="eo">PostScript-dokumento (kunpremita per gzip)</comment>
+ <comment xml:lang="en_GB">PostScript document (gzip-compressed)</comment>
+ <comment xml:lang="el">Έγγραφο PostScript (συμπιεσμένο με gzip)</comment>
+ <comment xml:lang="de">PostScript-Dokument (gzip-komprimiert)</comment>
+ <comment xml:lang="da">PostScript-dokument (gzip-komprimeret)</comment>
+ <comment xml:lang="cs">dokument PostScript (komprimovaný pomocí gzip)</comment>
+ <comment xml:lang="ca">document PostScript (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Документ — PostScript, компресиран с gzip</comment>
+ <comment xml:lang="be@latin">Dakument PostScript (gzip-skampresavany)</comment>
+ <comment xml:lang="be">дакумент PostScript (сцісканне gzip)</comment>
+ <comment xml:lang="ast">Documentu PostScript (comprimíu en gzip)</comment>
+ <comment xml:lang="ar">مستند PostScript (مضغوط-gzip)</comment>
+ <comment xml:lang="af">PostScript-dokument (gzip-saamgepers)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.ps.gz"/>
</mime-type>
<mime-type type="application/x-hdf">
<comment>HDF document</comment>
- <comment xml:lang="ar">مستند HDF</comment>
- <comment xml:lang="ast">Documentu HDF</comment>
- <comment xml:lang="az">HDF sənədi</comment>
- <comment xml:lang="be@latin">Dakument HDF</comment>
- <comment xml:lang="bg">Документ — HDF</comment>
- <comment xml:lang="ca">document HDF</comment>
- <comment xml:lang="cs">dokument HDF</comment>
- <comment xml:lang="cy">Dogfen HDF</comment>
- <comment xml:lang="da">HDF-dokument</comment>
- <comment xml:lang="de">HDF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο HDF</comment>
- <comment xml:lang="en_GB">HDF document</comment>
- <comment xml:lang="eo">HDF-dokumento</comment>
- <comment xml:lang="es">documento HDF</comment>
- <comment xml:lang="eu">HDF dokumentua</comment>
- <comment xml:lang="fi">HDF-asiakirja</comment>
- <comment xml:lang="fo">HDF skjal</comment>
- <comment xml:lang="fr">document HDF</comment>
- <comment xml:lang="ga">cáipéis HDF</comment>
- <comment xml:lang="gl">documento HDF</comment>
- <comment xml:lang="he">מסמך HDF</comment>
- <comment xml:lang="hr">HDF dokument</comment>
- <comment xml:lang="hu">HDF-dokumentum</comment>
- <comment xml:lang="ia">Documento HDF</comment>
- <comment xml:lang="id">Dokumen HDF</comment>
- <comment xml:lang="it">Documento HDF</comment>
- <comment xml:lang="ja">HDF ドキュメント</comment>
- <comment xml:lang="kk">HDF құжаты</comment>
- <comment xml:lang="ko">HDF 문서</comment>
- <comment xml:lang="lt">HDF dokumentas</comment>
- <comment xml:lang="lv">HDF dokuments</comment>
- <comment xml:lang="ms">Dokumen HDF</comment>
- <comment xml:lang="nb">HDF-dokument</comment>
- <comment xml:lang="nl">HDF-document</comment>
- <comment xml:lang="nn">HDF-dokument</comment>
- <comment xml:lang="oc">document HDF</comment>
- <comment xml:lang="pl">Dokument HDF</comment>
- <comment xml:lang="pt">documento HDF</comment>
- <comment xml:lang="pt_BR">Documento HDF</comment>
- <comment xml:lang="ro">Document HDF</comment>
- <comment xml:lang="ru">Документ HDF</comment>
- <comment xml:lang="sk">Dokument HDF</comment>
- <comment xml:lang="sl">Dokument HDF</comment>
- <comment xml:lang="sq">Dokument HDF</comment>
- <comment xml:lang="sr">ХДФ документ</comment>
- <comment xml:lang="sv">HDF-dokument</comment>
- <comment xml:lang="tr">HDF belgesi</comment>
- <comment xml:lang="uk">документ HDF</comment>
- <comment xml:lang="vi">Tài liệu HDF</comment>
- <comment xml:lang="zh_CN">HDF 文档</comment>
<comment xml:lang="zh_TW">HDF 文件</comment>
+ <comment xml:lang="zh_CN">HDF 文档</comment>
+ <comment xml:lang="vi">Tài liệu HDF</comment>
+ <comment xml:lang="uk">документ HDF</comment>
+ <comment xml:lang="tr">HDF belgesi</comment>
+ <comment xml:lang="sv">HDF-dokument</comment>
+ <comment xml:lang="sr">ХДФ документ</comment>
+ <comment xml:lang="sq">dokument HDF</comment>
+ <comment xml:lang="sl">Dokument HDF</comment>
+ <comment xml:lang="si">HDF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument HDF</comment>
+ <comment xml:lang="ru">Документ HDF</comment>
+ <comment xml:lang="ro">Document HDF</comment>
+ <comment xml:lang="pt_BR">Documento HDF</comment>
+ <comment xml:lang="pt">documento HDF</comment>
+ <comment xml:lang="pl">Dokument HDF</comment>
+ <comment xml:lang="oc">document HDF</comment>
+ <comment xml:lang="nn">HDF-dokument</comment>
+ <comment xml:lang="nl">HDF-document</comment>
+ <comment xml:lang="nb">HDF-dokument</comment>
+ <comment xml:lang="ms">Dokumen HDF</comment>
+ <comment xml:lang="lv">HDF dokuments</comment>
+ <comment xml:lang="lt">HDF dokumentas</comment>
+ <comment xml:lang="ko">HDF 문서</comment>
+ <comment xml:lang="kk">HDF құжаты</comment>
+ <comment xml:lang="ja">HDF ドキュメント</comment>
+ <comment xml:lang="it">Documento HDF</comment>
+ <comment xml:lang="is">HDF skjal</comment>
+ <comment xml:lang="id">Dokumen HDF</comment>
+ <comment xml:lang="ia">Documento HDF</comment>
+ <comment xml:lang="hu">HDF-dokumentum</comment>
+ <comment xml:lang="hr">HDF dokument</comment>
+ <comment xml:lang="he">מסמך HDF</comment>
+ <comment xml:lang="gl">documento HDF</comment>
+ <comment xml:lang="ga">cáipéis HDF</comment>
+ <comment xml:lang="fur">document HDF</comment>
+ <comment xml:lang="fr">document HDF</comment>
+ <comment xml:lang="fo">HDF skjal</comment>
+ <comment xml:lang="fi">HDF-asiakirja</comment>
+ <comment xml:lang="eu">HDF dokumentua</comment>
+ <comment xml:lang="es">documento HDF</comment>
+ <comment xml:lang="eo">HDF-dokumento</comment>
+ <comment xml:lang="en_GB">HDF document</comment>
+ <comment xml:lang="el">Έγγραφο HDF</comment>
+ <comment xml:lang="de">HDF-Dokument</comment>
+ <comment xml:lang="da">HDF-dokument</comment>
+ <comment xml:lang="cy">Dogfen HDF</comment>
+ <comment xml:lang="cs">dokument HDF</comment>
+ <comment xml:lang="ca">document HDF</comment>
+ <comment xml:lang="bg">Документ — HDF</comment>
+ <comment xml:lang="be@latin">Dakument HDF</comment>
+ <comment xml:lang="be">дакумент HDF</comment>
+ <comment xml:lang="az">HDF sənədi</comment>
+ <comment xml:lang="ast">Documentu HDF</comment>
+ <comment xml:lang="ar">مستند HDF</comment>
+ <comment xml:lang="af">HDF-dokument</comment>
<acronym>HDF</acronym>
<expanded-acronym>Hierarchical Data Format</expanded-acronym>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="\211HDF\r\n\032\n" type="string" offset="0"/>
- <match value="\016\003\023\001" type="string" offset="0"/>
+ <magic>
+ <match type="string" offset="0" value="\211HDF\r\n\032\n"/>
+ <match type="string" offset="0" value="\016\003\023\001"/>
</magic>
<glob pattern="*.hdf"/>
<glob pattern="*.hdf4"/>
@@ -12811,209 +13800,232 @@
</mime-type>
<mime-type type="application/x-iff">
<comment>IFF file</comment>
- <comment xml:lang="ca">fitxer IFF</comment>
- <comment xml:lang="cs">soubor IFF</comment>
- <comment xml:lang="da">IFF-fil</comment>
- <comment xml:lang="de">IFF-Datei</comment>
- <comment xml:lang="el">Αρχείο IFF</comment>
- <comment xml:lang="en_GB">IFF file</comment>
- <comment xml:lang="es">archivo IFF</comment>
- <comment xml:lang="eu">IFF fitxtegia</comment>
- <comment xml:lang="fi">IFF-tiedosto</comment>
- <comment xml:lang="fr">fichier IFF</comment>
- <comment xml:lang="ga">comhad IFF</comment>
- <comment xml:lang="gl">Ficheiro IFF</comment>
- <comment xml:lang="he">קובץ IFF</comment>
- <comment xml:lang="hr">IFF datoteka</comment>
- <comment xml:lang="hu">IFF fájl</comment>
- <comment xml:lang="ia">File IFF</comment>
- <comment xml:lang="id">Berkas IFF</comment>
- <comment xml:lang="it">File IFF</comment>
- <comment xml:lang="ja">IFF ファイル</comment>
- <comment xml:lang="kk">IFF файлы</comment>
- <comment xml:lang="ko">IFF 파일</comment>
- <comment xml:lang="lv">IFF datne</comment>
- <comment xml:lang="oc">fichièr IFF</comment>
- <comment xml:lang="pl">Plik IFF</comment>
- <comment xml:lang="pt">ficheiro IFF</comment>
- <comment xml:lang="pt_BR">Arquivo IFF</comment>
- <comment xml:lang="ru">Файл IFF</comment>
- <comment xml:lang="sk">Súbor IFF</comment>
- <comment xml:lang="sl">Datoteka IFF</comment>
- <comment xml:lang="sr">ИФФ датотека</comment>
- <comment xml:lang="sv">IFF-fil</comment>
- <comment xml:lang="tr">IFF dosyası</comment>
- <comment xml:lang="uk">файл IFF</comment>
- <comment xml:lang="zh_CN">IFF 文件</comment>
<comment xml:lang="zh_TW">IFF 檔案</comment>
+ <comment xml:lang="zh_CN">IFF 文件</comment>
+ <comment xml:lang="uk">файл IFF</comment>
+ <comment xml:lang="tr">IFF dosyası</comment>
+ <comment xml:lang="sv">IFF-fil</comment>
+ <comment xml:lang="sr">ИФФ датотека</comment>
+ <comment xml:lang="sq">kartelë IFF</comment>
+ <comment xml:lang="sl">Datoteka IFF</comment>
+ <comment xml:lang="si">IFF ගොනුව</comment>
+ <comment xml:lang="sk">Súbor IFF</comment>
+ <comment xml:lang="ru">Файл IFF</comment>
+ <comment xml:lang="pt_BR">Arquivo IFF</comment>
+ <comment xml:lang="pt">ficheiro IFF</comment>
+ <comment xml:lang="pl">Plik IFF</comment>
+ <comment xml:lang="oc">fichièr IFF</comment>
+ <comment xml:lang="nl">IFF-bestand</comment>
+ <comment xml:lang="lv">IFF datne</comment>
+ <comment xml:lang="ko">IFF 파일</comment>
+ <comment xml:lang="kk">IFF файлы</comment>
+ <comment xml:lang="ja">IFF ファイル</comment>
+ <comment xml:lang="it">File IFF</comment>
+ <comment xml:lang="is">IFF skrá</comment>
+ <comment xml:lang="id">Berkas IFF</comment>
+ <comment xml:lang="ia">File IFF</comment>
+ <comment xml:lang="hu">IFF fájl</comment>
+ <comment xml:lang="hr">IFF datoteka</comment>
+ <comment xml:lang="he">קובץ IFF</comment>
+ <comment xml:lang="gl">Ficheiro IFF</comment>
+ <comment xml:lang="ga">comhad IFF</comment>
+ <comment xml:lang="fur">file IFF</comment>
+ <comment xml:lang="fr">fichier IFF</comment>
+ <comment xml:lang="fi">IFF-tiedosto</comment>
+ <comment xml:lang="eu">IFF fitxtegia</comment>
+ <comment xml:lang="es">archivo IFF</comment>
+ <comment xml:lang="en_GB">IFF file</comment>
+ <comment xml:lang="el">Αρχείο IFF</comment>
+ <comment xml:lang="de">IFF-Datei</comment>
+ <comment xml:lang="da">IFF-fil</comment>
+ <comment xml:lang="cs">soubor IFF</comment>
+ <comment xml:lang="ca">fitxer IFF</comment>
+ <comment xml:lang="bg">Пакет — IFF</comment>
+ <comment xml:lang="be">файл IFF</comment>
+ <comment xml:lang="ar">ملف IFF</comment>
+ <comment xml:lang="af">IFF-lêer</comment>
<acronym>IFF</acronym>
<expanded-acronym>Interchange File Format</expanded-acronym>
<magic priority="40">
- <match value="FORM" type="string" offset="0"/>
+ <match type="string" value="FORM" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-ipod-firmware">
<comment>iPod firmware</comment>
- <comment xml:lang="ar">برنامج عتاد الـiPod</comment>
- <comment xml:lang="be@latin">Firmware iPod</comment>
- <comment xml:lang="bg">Фърмуер за iPod</comment>
- <comment xml:lang="ca">microprogramari d'iPod</comment>
- <comment xml:lang="cs">firmware iPod</comment>
- <comment xml:lang="da">iPod-styreprogram</comment>
- <comment xml:lang="de">iPod-Firmware</comment>
- <comment xml:lang="el">Υλικολογισμικό iPod</comment>
- <comment xml:lang="en_GB">iPod firmware</comment>
- <comment xml:lang="eo">iPod-mikroprogramaro</comment>
- <comment xml:lang="es">firmware de iPod</comment>
- <comment xml:lang="eu">iPod firmwarea</comment>
- <comment xml:lang="fi">iPod-laiteohjelmisto</comment>
- <comment xml:lang="fo">iPod fastbúnaður</comment>
- <comment xml:lang="fr">firmware iPod</comment>
- <comment xml:lang="ga">dochtearraí iPod</comment>
- <comment xml:lang="gl">firmware de iPod</comment>
- <comment xml:lang="he">קושחת ipod</comment>
- <comment xml:lang="hr">iPod firmver</comment>
- <comment xml:lang="hu">iPod-firmware</comment>
- <comment xml:lang="ia">Firmware iPod</comment>
- <comment xml:lang="id">peranti tegar iPod</comment>
- <comment xml:lang="it">Firmware iPod</comment>
- <comment xml:lang="ja">iPod ファームウェア</comment>
- <comment xml:lang="kk">iPod микробағдарламасы</comment>
- <comment xml:lang="ko">iPod 펌웨어</comment>
- <comment xml:lang="lt">iPod programinė įranga</comment>
- <comment xml:lang="lv">iPod aparātprogrammatūra</comment>
- <comment xml:lang="ms">Firmware iPod</comment>
- <comment xml:lang="nb">iPod-firmware</comment>
- <comment xml:lang="nl">iPod-firmware</comment>
- <comment xml:lang="nn">iPod-firmvare</comment>
- <comment xml:lang="oc">firmware iPod</comment>
- <comment xml:lang="pl">Oprogramowanie wewnętrzne iPod</comment>
- <comment xml:lang="pt">firmware iPod</comment>
- <comment xml:lang="pt_BR">Firmware do iPod</comment>
- <comment xml:lang="ro">Firmware iPod</comment>
- <comment xml:lang="ru">Микропрограмма iPod</comment>
- <comment xml:lang="sk">Firmware iPod</comment>
- <comment xml:lang="sl">Programska strojna oprema iPod</comment>
- <comment xml:lang="sq">Firmware iPod</comment>
- <comment xml:lang="sr">ајПод-ов уграђени</comment>
- <comment xml:lang="sv">fast iPod-program</comment>
- <comment xml:lang="tr">iPod üretici yazılımı</comment>
- <comment xml:lang="uk">мікропрограма iPod</comment>
- <comment xml:lang="vi">phần vững iPod</comment>
- <comment xml:lang="zh_CN">iPod 固件</comment>
<comment xml:lang="zh_TW">iPod 韌體</comment>
- <magic priority="50">
- <match value="S T O P" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">iPod 固件</comment>
+ <comment xml:lang="vi">phần vững iPod</comment>
+ <comment xml:lang="uk">мікропрограма iPod</comment>
+ <comment xml:lang="tr">iPod donanım yazılımı</comment>
+ <comment xml:lang="sv">fast iPod-program</comment>
+ <comment xml:lang="sr">ајПод-ов уграђени</comment>
+ <comment xml:lang="sq">firmware iPod</comment>
+ <comment xml:lang="sl">Programska strojna oprema iPod</comment>
+ <comment xml:lang="si">iPod ස්ථිරාංග</comment>
+ <comment xml:lang="sk">Firmware iPod</comment>
+ <comment xml:lang="ru">Микропрограмма iPod</comment>
+ <comment xml:lang="ro">Firmware iPod</comment>
+ <comment xml:lang="pt_BR">Firmware do iPod</comment>
+ <comment xml:lang="pt">firmware iPod</comment>
+ <comment xml:lang="pl">Oprogramowanie wewnętrzne iPod</comment>
+ <comment xml:lang="oc">firmware iPod</comment>
+ <comment xml:lang="nn">iPod-firmvare</comment>
+ <comment xml:lang="nl">iPod-firmware</comment>
+ <comment xml:lang="nb">iPod-firmware</comment>
+ <comment xml:lang="ms">Firmware iPod</comment>
+ <comment xml:lang="lv">iPod aparātprogrammatūra</comment>
+ <comment xml:lang="lt">iPod programinė įranga</comment>
+ <comment xml:lang="ko">iPod 펌웨어</comment>
+ <comment xml:lang="kk">iPod микробағдарламасы</comment>
+ <comment xml:lang="ja">iPod ファームウェア</comment>
+ <comment xml:lang="it">Firmware iPod</comment>
+ <comment xml:lang="is">iPod grunnhugbúnaður</comment>
+ <comment xml:lang="id">peranti tegar iPod</comment>
+ <comment xml:lang="ia">Firmware iPod</comment>
+ <comment xml:lang="hu">iPod-firmware</comment>
+ <comment xml:lang="hr">iPod firmver</comment>
+ <comment xml:lang="he">קושחת ipod</comment>
+ <comment xml:lang="gl">firmware de iPod</comment>
+ <comment xml:lang="ga">dochtearraí iPod</comment>
+ <comment xml:lang="fur">firmware iPod</comment>
+ <comment xml:lang="fr">firmware iPod</comment>
+ <comment xml:lang="fo">iPod fastbúnaður</comment>
+ <comment xml:lang="fi">iPod-laiteohjelmisto</comment>
+ <comment xml:lang="eu">iPod firmwarea</comment>
+ <comment xml:lang="es">firmware de iPod</comment>
+ <comment xml:lang="eo">iPod-mikroprogramaro</comment>
+ <comment xml:lang="en_GB">iPod firmware</comment>
+ <comment xml:lang="el">Υλικολογισμικό iPod</comment>
+ <comment xml:lang="de">iPod-Firmware</comment>
+ <comment xml:lang="da">iPod-styreprogram</comment>
+ <comment xml:lang="cs">firmware iPod</comment>
+ <comment xml:lang="ca">microprogramari d'iPod</comment>
+ <comment xml:lang="bg">Фърмуер — iPod</comment>
+ <comment xml:lang="be@latin">Firmware iPod</comment>
+ <comment xml:lang="be">убудаванае ПЗ iPod</comment>
+ <comment xml:lang="ar">برنامج عتاد الـiPod</comment>
+ <magic>
+ <match type="string" value="S T O P" offset="0"/>
</magic>
</mime-type>
- <mime-type type="application/x-java-archive">
+ <mime-type type="application/java-archive">
<comment>Java archive</comment>
- <comment xml:lang="ar">أرشيف Java</comment>
- <comment xml:lang="be@latin">Archiŭ Java</comment>
- <comment xml:lang="bg">Архив — Java</comment>
- <comment xml:lang="ca">arxiu de Java</comment>
- <comment xml:lang="cs">archiv Java</comment>
- <comment xml:lang="da">Javaarkiv</comment>
- <comment xml:lang="de">Java-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Java</comment>
- <comment xml:lang="en_GB">Java archive</comment>
- <comment xml:lang="eo">Java-arkivo</comment>
- <comment xml:lang="es">archivador Java</comment>
- <comment xml:lang="eu">Java artxiboa</comment>
- <comment xml:lang="fi">Java-arkisto</comment>
- <comment xml:lang="fo">Java skjalasavn</comment>
- <comment xml:lang="fr">archive Java</comment>
- <comment xml:lang="ga">cartlann Java</comment>
- <comment xml:lang="gl">arquivo Java</comment>
- <comment xml:lang="he">ארכיון Java</comment>
- <comment xml:lang="hr">Java arhiva</comment>
- <comment xml:lang="hu">Java-archívum</comment>
- <comment xml:lang="ia">Archivo Java</comment>
- <comment xml:lang="id">Arsip Java</comment>
- <comment xml:lang="it">Archivio Java</comment>
- <comment xml:lang="ja">Java アーカイブ</comment>
- <comment xml:lang="kk">Java архиві</comment>
- <comment xml:lang="ko">Java 묶음 파일</comment>
- <comment xml:lang="lt">Java archyvas</comment>
- <comment xml:lang="lv">Java arhīvs</comment>
- <comment xml:lang="ms">Arkib Java</comment>
- <comment xml:lang="nb">Java-arkiv</comment>
- <comment xml:lang="nl">Java-archief</comment>
- <comment xml:lang="nn">Java-arkiv</comment>
- <comment xml:lang="oc">archiu Java</comment>
- <comment xml:lang="pl">Archiwum Java</comment>
- <comment xml:lang="pt">arquivo Java</comment>
- <comment xml:lang="pt_BR">Pacote Java</comment>
- <comment xml:lang="ro">Arhivă Java</comment>
- <comment xml:lang="ru">Архив Java</comment>
- <comment xml:lang="sk">Archív Java</comment>
- <comment xml:lang="sl">Datoteka arhiva Java</comment>
- <comment xml:lang="sq">Arkiv Java</comment>
- <comment xml:lang="sr">архива Јаве</comment>
- <comment xml:lang="sv">Java-arkiv</comment>
- <comment xml:lang="tr">Java arşivi</comment>
- <comment xml:lang="uk">архів Java</comment>
- <comment xml:lang="vi">Kho nén Java</comment>
- <comment xml:lang="zh_CN">Java 归档文件</comment>
<comment xml:lang="zh_TW">Java 封存檔</comment>
+ <comment xml:lang="zh_CN">Java 归档文件</comment>
+ <comment xml:lang="vi">Kho nén Java</comment>
+ <comment xml:lang="uk">архів Java</comment>
+ <comment xml:lang="tr">Java arşivi</comment>
+ <comment xml:lang="sv">Java-arkiv</comment>
+ <comment xml:lang="sr">архива Јаве</comment>
+ <comment xml:lang="sq">arkiv Java</comment>
+ <comment xml:lang="sl">Datoteka arhiva Java</comment>
+ <comment xml:lang="si">ජාවා ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Java</comment>
+ <comment xml:lang="ru">Архив Java</comment>
+ <comment xml:lang="ro">Arhivă Java</comment>
+ <comment xml:lang="pt_BR">Pacote Java</comment>
+ <comment xml:lang="pt">arquivo Java</comment>
+ <comment xml:lang="pl">Archiwum Java</comment>
+ <comment xml:lang="oc">archiu Java</comment>
+ <comment xml:lang="nn">Java-arkiv</comment>
+ <comment xml:lang="nl">Java-archief</comment>
+ <comment xml:lang="nb">Java-arkiv</comment>
+ <comment xml:lang="ms">Arkib Java</comment>
+ <comment xml:lang="lv">Java arhīvs</comment>
+ <comment xml:lang="lt">Java archyvas</comment>
+ <comment xml:lang="ko">Java 묶음 파일</comment>
+ <comment xml:lang="kk">Java архиві</comment>
+ <comment xml:lang="ja">Java アーカイブ</comment>
+ <comment xml:lang="it">Archivio Java</comment>
+ <comment xml:lang="is">Java safnskrá</comment>
+ <comment xml:lang="id">Arsip Java</comment>
+ <comment xml:lang="ia">Archivo Java</comment>
+ <comment xml:lang="hu">Java-archívum</comment>
+ <comment xml:lang="hr">Java arhiva</comment>
+ <comment xml:lang="he">ארכיון Java</comment>
+ <comment xml:lang="gl">arquivo Java</comment>
+ <comment xml:lang="ga">cartlann Java</comment>
+ <comment xml:lang="fur">archivi Java</comment>
+ <comment xml:lang="fr">archive Java</comment>
+ <comment xml:lang="fo">Java skjalasavn</comment>
+ <comment xml:lang="fi">Java-arkisto</comment>
+ <comment xml:lang="eu">Java artxiboa</comment>
+ <comment xml:lang="es">archivador de Java</comment>
+ <comment xml:lang="eo">Java-arkivo</comment>
+ <comment xml:lang="en_GB">Java archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Java</comment>
+ <comment xml:lang="de">Java-Archiv</comment>
+ <comment xml:lang="da">Java-arkiv</comment>
+ <comment xml:lang="cs">archiv Java</comment>
+ <comment xml:lang="ca">arxiu de Java</comment>
+ <comment xml:lang="bg">Архив — Java</comment>
+ <comment xml:lang="be@latin">Archiŭ Java</comment>
+ <comment xml:lang="be">архіў Java</comment>
+ <comment xml:lang="ar">أرشيف Java</comment>
+ <comment xml:lang="af">Java-argief</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="package-x-generic"/>
<alias type="application/x-jar"/>
- <alias type="application/java-archive"/>
+ <alias type="application/x-java-archive"/>
<glob pattern="*.jar"/>
</mime-type>
<mime-type type="application/x-java">
<comment>Java class</comment>
- <comment xml:lang="ar">صنف java</comment>
- <comment xml:lang="be@latin">Klasa Java</comment>
- <comment xml:lang="bg">Клас на Java</comment>
- <comment xml:lang="ca">classe de Java</comment>
- <comment xml:lang="cs">třída Java</comment>
- <comment xml:lang="da">Javaklasse</comment>
- <comment xml:lang="de">Java-Klasse</comment>
- <comment xml:lang="el">Κλάση Java</comment>
- <comment xml:lang="en_GB">Java class</comment>
- <comment xml:lang="eo">Java-klaso</comment>
- <comment xml:lang="es">clase de Java</comment>
- <comment xml:lang="eu">Java-ko klasea</comment>
- <comment xml:lang="fi">Java-luokka</comment>
- <comment xml:lang="fo">Java flokkur</comment>
- <comment xml:lang="fr">classe Java</comment>
- <comment xml:lang="ga">aicme Java</comment>
- <comment xml:lang="gl">clase de Java</comment>
- <comment xml:lang="he">מחלקת Java</comment>
- <comment xml:lang="hr">Java klasa</comment>
- <comment xml:lang="hu">Java-osztály</comment>
- <comment xml:lang="ia">Classe Java</comment>
- <comment xml:lang="id">Kelas Java</comment>
- <comment xml:lang="it">Classe Java</comment>
- <comment xml:lang="ja">Java クラス</comment>
- <comment xml:lang="kk">Java класы</comment>
- <comment xml:lang="ko">Java 클래스</comment>
- <comment xml:lang="lt">Java klasė</comment>
- <comment xml:lang="lv">Java klase</comment>
- <comment xml:lang="ms">Kelas Java</comment>
- <comment xml:lang="nb">Java-klasse</comment>
- <comment xml:lang="nl">Java-klasse</comment>
- <comment xml:lang="nn">Java-klasse</comment>
- <comment xml:lang="oc">classa Java</comment>
- <comment xml:lang="pl">Klasa Java</comment>
- <comment xml:lang="pt">classe Java</comment>
- <comment xml:lang="pt_BR">Classe Java</comment>
- <comment xml:lang="ro">Clasă Java</comment>
- <comment xml:lang="ru">Класс Java</comment>
- <comment xml:lang="sk">Trieda Java</comment>
- <comment xml:lang="sl">Datoteka razreda Java</comment>
- <comment xml:lang="sq">Klasë Java</comment>
- <comment xml:lang="sr">разред Јаве</comment>
- <comment xml:lang="sv">Java-klass</comment>
- <comment xml:lang="tr">Java sınıfı</comment>
- <comment xml:lang="uk">клас Java</comment>
- <comment xml:lang="vi">Hạng Java</comment>
- <comment xml:lang="zh_CN">Java 类</comment>
<comment xml:lang="zh_TW">Java class</comment>
- <magic priority="50">
- <match value="0xcafebabe" type="big32" offset="0"/>
+ <comment xml:lang="zh_CN">Java 类</comment>
+ <comment xml:lang="vi">Hạng Java</comment>
+ <comment xml:lang="uk">клас Java</comment>
+ <comment xml:lang="tr">Java sınıfı</comment>
+ <comment xml:lang="sv">Java-klass</comment>
+ <comment xml:lang="sr">разред Јаве</comment>
+ <comment xml:lang="sq">klasë Java</comment>
+ <comment xml:lang="sl">Datoteka razreda Java</comment>
+ <comment xml:lang="si">ජාවා පන්තිය</comment>
+ <comment xml:lang="sk">Trieda Java</comment>
+ <comment xml:lang="ru">Класс Java</comment>
+ <comment xml:lang="ro">Clasă Java</comment>
+ <comment xml:lang="pt_BR">Classe Java</comment>
+ <comment xml:lang="pt">classe Java</comment>
+ <comment xml:lang="pl">Klasa Java</comment>
+ <comment xml:lang="oc">classa Java</comment>
+ <comment xml:lang="nn">Java-klasse</comment>
+ <comment xml:lang="nl">Java-klasse</comment>
+ <comment xml:lang="nb">Java-klasse</comment>
+ <comment xml:lang="ms">Kelas Java</comment>
+ <comment xml:lang="lv">Java klase</comment>
+ <comment xml:lang="lt">Java klasė</comment>
+ <comment xml:lang="ko">Java 클래스</comment>
+ <comment xml:lang="kk">Java класы</comment>
+ <comment xml:lang="ja">Java クラス</comment>
+ <comment xml:lang="it">Classe Java</comment>
+ <comment xml:lang="is">Java klassi</comment>
+ <comment xml:lang="id">Kelas Java</comment>
+ <comment xml:lang="ia">Classe Java</comment>
+ <comment xml:lang="hu">Java-osztály</comment>
+ <comment xml:lang="hr">Java klasa</comment>
+ <comment xml:lang="he">מחלקת Java</comment>
+ <comment xml:lang="gl">clase de Java</comment>
+ <comment xml:lang="ga">aicme Java</comment>
+ <comment xml:lang="fur">classe Java</comment>
+ <comment xml:lang="fr">classe Java</comment>
+ <comment xml:lang="fo">Java flokkur</comment>
+ <comment xml:lang="fi">Java-luokka</comment>
+ <comment xml:lang="eu">Java-ko klasea</comment>
+ <comment xml:lang="es">clase de Java</comment>
+ <comment xml:lang="eo">Java-klaso</comment>
+ <comment xml:lang="en_GB">Java class</comment>
+ <comment xml:lang="el">Κλάση Java</comment>
+ <comment xml:lang="de">Java-Klasse</comment>
+ <comment xml:lang="da">Java-klasse</comment>
+ <comment xml:lang="cs">třída Java</comment>
+ <comment xml:lang="ca">classe de Java</comment>
+ <comment xml:lang="bg">Клас — Java</comment>
+ <comment xml:lang="be@latin">Klasa Java</comment>
+ <comment xml:lang="be">клас Java</comment>
+ <comment xml:lang="ar">صنف java</comment>
+ <comment xml:lang="af">Java-klas</comment>
+ <magic>
+ <match type="big32" value="0xcafebabe" offset="0"/>
</magic>
<alias type="application/java"/>
<alias type="application/java-byte-code"/>
@@ -13022,109 +14034,190 @@
<alias type="application/x-java-vm"/>
<glob pattern="*.class"/>
</mime-type>
+ <mime-type type="text/x-groovy">
+ <comment>Groovy source code</comment>
+ <comment xml:lang="zh_TW">Groovy 原始碼</comment>
+ <comment xml:lang="zh_CN">Groovy 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Groovy</comment>
+ <comment xml:lang="tr">Groovy kaynak kodu</comment>
+ <comment xml:lang="sv">Groovy-källkod</comment>
+ <comment xml:lang="sq">kod burim Groovy</comment>
+ <comment xml:lang="sl">Izvorna koda Groovy</comment>
+ <comment xml:lang="si">Groovy මූල කේතය</comment>
+ <comment xml:lang="ru">Исходный код Groovy</comment>
+ <comment xml:lang="pt_BR">Código-fonte Groovy</comment>
+ <comment xml:lang="pl">Kod źródłowy Groovy</comment>
+ <comment xml:lang="oc">còdi font Groovy</comment>
+ <comment xml:lang="nl">Groovy-broncode</comment>
+ <comment xml:lang="ko">그루비 소스 코드</comment>
+ <comment xml:lang="kk">Groovy бастапқы коды</comment>
+ <comment xml:lang="ja">Groovy ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Groovy</comment>
+ <comment xml:lang="is">Groovy frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Groovy</comment>
+ <comment xml:lang="hu">Groovy forráskód</comment>
+ <comment xml:lang="hr">Groovy izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור ב־Groovy</comment>
+ <comment xml:lang="gl">Código fonte en Groovy</comment>
+ <comment xml:lang="fr">code source Groovy</comment>
+ <comment xml:lang="fi">Groovy-lähdekoodi</comment>
+ <comment xml:lang="eu">Groovy iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Groovy</comment>
+ <comment xml:lang="en_GB">Groovy source code</comment>
+ <comment xml:lang="de">Groovy-Quelltext</comment>
+ <comment xml:lang="da">Groovy-kildekode</comment>
+ <comment xml:lang="ca">codi font en Groovy</comment>
+ <comment xml:lang="bg">Изходен код — Groovy</comment>
+ <comment xml:lang="be">зыходны код Groovy</comment>
+ <comment xml:lang="ar">شفرة مصدر Groovy</comment>
+ <sub-class-of type="text/x-csrc"/>
+ <generic-icon name="text-x-script"/>
+ <glob pattern="*.groovy"/>
+ <glob pattern="*.gvy"/>
+ <glob pattern="*.gy"/>
+ <glob pattern="*.gsh"/>
+ </mime-type>
+ <mime-type type="text/x-gradle">
+ <comment>Gradle script</comment>
+ <comment xml:lang="zh_TW">Gradle 指令稿</comment>
+ <comment xml:lang="zh_CN">Gradle 脚本</comment>
+ <comment xml:lang="uk">скрипт Gradle</comment>
+ <comment xml:lang="tr">Gradle betiği</comment>
+ <comment xml:lang="sv">Gradle-skript</comment>
+ <comment xml:lang="sl">Skript Gradle</comment>
+ <comment xml:lang="si">Gradle පිටපත</comment>
+ <comment xml:lang="ru">Сценарий Gradle</comment>
+ <comment xml:lang="pt_BR">Script Gradle</comment>
+ <comment xml:lang="pl">Skrypt Gradle</comment>
+ <comment xml:lang="nl">Gradle-script</comment>
+ <comment xml:lang="ko">Gradle 스크립트</comment>
+ <comment xml:lang="kk">Gradle сценарийі</comment>
+ <comment xml:lang="ja">Gradle スクリプト</comment>
+ <comment xml:lang="it">Script Gradle</comment>
+ <comment xml:lang="hr">Gradle skripta</comment>
+ <comment xml:lang="gl">Script de Gradle</comment>
+ <comment xml:lang="fi">Gradle-skripti</comment>
+ <comment xml:lang="eu">Gradle script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes de Gradle</comment>
+ <comment xml:lang="en_GB">Gradle script</comment>
+ <comment xml:lang="de">Gradle-Skript</comment>
+ <comment xml:lang="be">скрыпт Gradle</comment>
+ <comment xml:lang="ar">سكربت Gradle</comment>
+ <sub-class-of type="text/x-groovy"/>
+ <glob pattern="*.gradle"/>
+ </mime-type>
<mime-type type="application/x-java-jnlp-file">
<comment>JNLP file</comment>
- <comment xml:lang="ar">ملف JNLP</comment>
- <comment xml:lang="be@latin">Fajł JNLP</comment>
- <comment xml:lang="bg">Файл — JNLP</comment>
- <comment xml:lang="ca">fitxer JNLP</comment>
- <comment xml:lang="cs">soubor JNLP</comment>
- <comment xml:lang="da">JNPL-fil</comment>
- <comment xml:lang="de">JNLP-Datei</comment>
- <comment xml:lang="el">Αρχείο JNLP</comment>
- <comment xml:lang="en_GB">JNLP file</comment>
- <comment xml:lang="eo">JNLP-dosiero</comment>
- <comment xml:lang="es">archivo JNPL</comment>
- <comment xml:lang="eu">JNLP fitxategia</comment>
- <comment xml:lang="fi">JNLP-tiedosto</comment>
- <comment xml:lang="fo">JNLP fíla</comment>
- <comment xml:lang="fr">fichier JNLP</comment>
- <comment xml:lang="ga">comhad JNLP</comment>
- <comment xml:lang="gl">ficheiro JNLP</comment>
- <comment xml:lang="he">קובץ JNLP</comment>
- <comment xml:lang="hr">JNLP datoteka</comment>
- <comment xml:lang="hu">JNLP fájl</comment>
- <comment xml:lang="ia">File JNLP</comment>
- <comment xml:lang="id">Berkas JNLP</comment>
- <comment xml:lang="it">File JNPL</comment>
- <comment xml:lang="ja">JNLP ファイル</comment>
- <comment xml:lang="kk">JNLP файлы</comment>
- <comment xml:lang="ko">JNLP 파일</comment>
- <comment xml:lang="lt">JNLP failas</comment>
- <comment xml:lang="lv">JNLP datne</comment>
- <comment xml:lang="nb">JNLP-fil</comment>
- <comment xml:lang="nl">JNLP-bestand</comment>
- <comment xml:lang="nn">JNLP-fil</comment>
- <comment xml:lang="oc">fichièr JNLP</comment>
- <comment xml:lang="pl">Plik JNLP</comment>
- <comment xml:lang="pt">ficheiro JNLP</comment>
- <comment xml:lang="pt_BR">Arquivo JNLP</comment>
- <comment xml:lang="ro">Fișier JNLP</comment>
- <comment xml:lang="ru">Файл JNLP</comment>
- <comment xml:lang="sk">Súbor JNLP</comment>
- <comment xml:lang="sl">Datoteka JNLP</comment>
- <comment xml:lang="sq">File JNLP</comment>
- <comment xml:lang="sr">ЈНЛП датотека</comment>
- <comment xml:lang="sv">JNLP-fil</comment>
- <comment xml:lang="tr">JNLP dosyası</comment>
- <comment xml:lang="uk">файл JNLP</comment>
- <comment xml:lang="vi">Tập tin JNLP</comment>
- <comment xml:lang="zh_CN">JNLP 文件</comment>
<comment xml:lang="zh_TW">JNLP 檔案</comment>
+ <comment xml:lang="zh_CN">JNLP 文件</comment>
+ <comment xml:lang="vi">Tập tin JNLP</comment>
+ <comment xml:lang="uk">файл JNLP</comment>
+ <comment xml:lang="tr">JNLP dosyası</comment>
+ <comment xml:lang="sv">JNLP-fil</comment>
+ <comment xml:lang="sr">ЈНЛП датотека</comment>
+ <comment xml:lang="sq">kartelë JNLP</comment>
+ <comment xml:lang="sl">Datoteka JNLP</comment>
+ <comment xml:lang="si">JNLP ගොනුව</comment>
+ <comment xml:lang="sk">Súbor JNLP</comment>
+ <comment xml:lang="ru">Файл JNLP</comment>
+ <comment xml:lang="ro">Fișier JNLP</comment>
+ <comment xml:lang="pt_BR">Arquivo JNLP</comment>
+ <comment xml:lang="pt">ficheiro JNLP</comment>
+ <comment xml:lang="pl">Plik JNLP</comment>
+ <comment xml:lang="oc">fichièr JNLP</comment>
+ <comment xml:lang="nn">JNLP-fil</comment>
+ <comment xml:lang="nl">JNLP-bestand</comment>
+ <comment xml:lang="nb">JNLP-fil</comment>
+ <comment xml:lang="lv">JNLP datne</comment>
+ <comment xml:lang="lt">JNLP failas</comment>
+ <comment xml:lang="ko">JNLP 파일</comment>
+ <comment xml:lang="kk">JNLP файлы</comment>
+ <comment xml:lang="ja">JNLP ファイル</comment>
+ <comment xml:lang="it">File JNPL</comment>
+ <comment xml:lang="is">JNLP skrá</comment>
+ <comment xml:lang="id">Berkas JNLP</comment>
+ <comment xml:lang="ia">File JNLP</comment>
+ <comment xml:lang="hu">JNLP fájl</comment>
+ <comment xml:lang="hr">JNLP datoteka</comment>
+ <comment xml:lang="he">קובץ JNLP</comment>
+ <comment xml:lang="gl">ficheiro JNLP</comment>
+ <comment xml:lang="ga">comhad JNLP</comment>
+ <comment xml:lang="fur">file JNLP</comment>
+ <comment xml:lang="fr">fichier JNLP</comment>
+ <comment xml:lang="fo">JNLP fíla</comment>
+ <comment xml:lang="fi">JNLP-tiedosto</comment>
+ <comment xml:lang="eu">JNLP fitxategia</comment>
+ <comment xml:lang="es">archivo JNPL</comment>
+ <comment xml:lang="eo">JNLP-dosiero</comment>
+ <comment xml:lang="en_GB">JNLP file</comment>
+ <comment xml:lang="el">Αρχείο JNLP</comment>
+ <comment xml:lang="de">JNLP-Datei</comment>
+ <comment xml:lang="da">JNPL-fil</comment>
+ <comment xml:lang="cs">soubor JNLP</comment>
+ <comment xml:lang="ca">fitxer JNLP</comment>
+ <comment xml:lang="bg">Стартер — JNLP</comment>
+ <comment xml:lang="be@latin">Fajł JNLP</comment>
+ <comment xml:lang="be">файл JNLP</comment>
+ <comment xml:lang="ar">ملف JNLP</comment>
+ <comment xml:lang="af">JNLP-lêer</comment>
<acronym>JNLP</acronym>
<expanded-acronym>Java Network Launching Protocol</expanded-acronym>
<sub-class-of type="application/xml"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.jnlp"/>
- <magic priority="50">
- <match value="&lt;jnlp" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;jnlp" offset="0:256"/>
</magic>
</mime-type>
<mime-type type="application/x-java-keystore">
<comment>Java keystore</comment>
- <comment xml:lang="ar">مخزن مفاتيح جافا</comment>
- <comment xml:lang="bg">Ключодържател — Java</comment>
- <comment xml:lang="ca">magatzem de claus de Java</comment>
- <comment xml:lang="cs">úložiště klíčů Java</comment>
- <comment xml:lang="da">Javanøglelager</comment>
- <comment xml:lang="de">Java-Schlüsselbund</comment>
- <comment xml:lang="el">Χώρος αποθήκευσης κλειδιών Java</comment>
- <comment xml:lang="en_GB">Java keystore</comment>
- <comment xml:lang="es">almacén de claves de Java</comment>
- <comment xml:lang="eu">Java-ren gako-biltegia</comment>
- <comment xml:lang="fi">Java-avainvarasto</comment>
- <comment xml:lang="fo">Java lyklagoymsla</comment>
- <comment xml:lang="fr">stockage de clés Java</comment>
- <comment xml:lang="ga">eochairstór Java</comment>
- <comment xml:lang="gl">almacén de chaves de Java</comment>
- <comment xml:lang="he">אחסון מפתחות של Java</comment>
- <comment xml:lang="hr">Java baza ključeva</comment>
- <comment xml:lang="hu">Java kulcstároló</comment>
- <comment xml:lang="ia">Magazin de claves Java</comment>
- <comment xml:lang="id">Penyimpanan kunci Java</comment>
- <comment xml:lang="it">Keystore Java</comment>
- <comment xml:lang="ja">Java キーストア</comment>
- <comment xml:lang="kk">Java сақталымы</comment>
- <comment xml:lang="ko">Java 키 저장소</comment>
- <comment xml:lang="lt">Java raktų saugykla</comment>
- <comment xml:lang="lv">Java keystore</comment>
- <comment xml:lang="nl">Java keystore</comment>
- <comment xml:lang="oc">emmagazinatge de claus Java</comment>
- <comment xml:lang="pl">Baza kluczy Java</comment>
- <comment xml:lang="pt">armazém de chaves Java</comment>
- <comment xml:lang="pt_BR">Keystore de Java</comment>
- <comment xml:lang="ro">Stocare chei Java</comment>
- <comment xml:lang="ru">Хранилище ключей Java</comment>
- <comment xml:lang="sk">Úložisko kľúčov Java</comment>
- <comment xml:lang="sl">Datoteka tipkovne razporeditve Java</comment>
- <comment xml:lang="sr">смештај кључа Јаве</comment>
- <comment xml:lang="sv">Java-nyckellager</comment>
- <comment xml:lang="tr">Java deposu</comment>
- <comment xml:lang="uk">сховище ключів Java</comment>
- <comment xml:lang="zh_CN">Java 密钥库</comment>
<comment xml:lang="zh_TW">Java 金鑰儲存</comment>
- <magic priority="50">
- <match value="0xfeedfeed" type="big32" offset="0"/>
+ <comment xml:lang="zh_CN">Java 密钥库</comment>
+ <comment xml:lang="uk">сховище ключів Java</comment>
+ <comment xml:lang="tr">Java anahtar deposu</comment>
+ <comment xml:lang="sv">Java-nyckellager</comment>
+ <comment xml:lang="sr">смештај кључа Јаве</comment>
+ <comment xml:lang="sl">Datoteka tipkovne razporeditve Java</comment>
+ <comment xml:lang="si">ජාවා යතුරු ගබඩාව</comment>
+ <comment xml:lang="sk">Úložisko kľúčov Java</comment>
+ <comment xml:lang="ru">Хранилище ключей Java</comment>
+ <comment xml:lang="ro">Stocare chei Java</comment>
+ <comment xml:lang="pt_BR">Keystore de Java</comment>
+ <comment xml:lang="pt">armazém de chaves Java</comment>
+ <comment xml:lang="pl">Baza kluczy Java</comment>
+ <comment xml:lang="oc">emmagazinatge de claus Java</comment>
+ <comment xml:lang="nl">Java-keystore</comment>
+ <comment xml:lang="lv">Java keystore</comment>
+ <comment xml:lang="lt">Java raktų saugykla</comment>
+ <comment xml:lang="ko">Java 키 저장소</comment>
+ <comment xml:lang="kk">Java сақталымы</comment>
+ <comment xml:lang="ja">Java キーストア</comment>
+ <comment xml:lang="it">Keystore Java</comment>
+ <comment xml:lang="is">Java lyklageymsla</comment>
+ <comment xml:lang="id">Penyimpanan kunci Java</comment>
+ <comment xml:lang="ia">Magazin de claves Java</comment>
+ <comment xml:lang="hu">Java kulcstároló</comment>
+ <comment xml:lang="hr">Java baza ključeva</comment>
+ <comment xml:lang="he">אחסון מפתחות של Java</comment>
+ <comment xml:lang="gl">almacén de chaves de Java</comment>
+ <comment xml:lang="ga">eochairstór Java</comment>
+ <comment xml:lang="fur">archivi di clâfs Java</comment>
+ <comment xml:lang="fr">stockage de clés Java</comment>
+ <comment xml:lang="fo">Java lyklagoymsla</comment>
+ <comment xml:lang="fi">Java-avainvarasto</comment>
+ <comment xml:lang="eu">Java-ren gako-biltegia</comment>
+ <comment xml:lang="es">almacén de claves de Java</comment>
+ <comment xml:lang="en_GB">Java keystore</comment>
+ <comment xml:lang="el">Χώρος αποθήκευσης κλειδιών Java</comment>
+ <comment xml:lang="de">Java-Schlüsselbund</comment>
+ <comment xml:lang="da">Java-nøglelager</comment>
+ <comment xml:lang="cs">úložiště klíčů Java</comment>
+ <comment xml:lang="ca">magatzem de claus de Java</comment>
+ <comment xml:lang="bg">Ключодържател — Java</comment>
+ <comment xml:lang="be">сховішча ключоў Java</comment>
+ <comment xml:lang="ar">مخزن مفاتيح جافا</comment>
+ <magic>
+ <match type="big32" value="0xfeedfeed" offset="0"/>
</magic>
<glob pattern="*.jks"/>
<glob pattern="*.ks"/>
@@ -13132,254 +14225,320 @@
</mime-type>
<mime-type type="application/x-java-jce-keystore">
<comment>Java JCE keystore</comment>
- <comment xml:lang="ar">مخزن مفاتيح Java JCE</comment>
- <comment xml:lang="bg">Ключодържател — Java JCE</comment>
- <comment xml:lang="ca">magatzem de claus JCE de Java</comment>
- <comment xml:lang="cs">úložiště klíčů Java JCE</comment>
- <comment xml:lang="da">Java JCE-nøglelager</comment>
- <comment xml:lang="de">Java JCE-Schlüsselbund</comment>
- <comment xml:lang="el">Αποθήκη κλειδιών Java JCE</comment>
- <comment xml:lang="en_GB">Java JCE keystore</comment>
- <comment xml:lang="es">almacén de claves JCE de Java</comment>
- <comment xml:lang="eu">Java JCE-ren gako-biltegia</comment>
- <comment xml:lang="fi">Java JCE -avainvarasto</comment>
- <comment xml:lang="fo">Java JCE lyklagoymsla</comment>
- <comment xml:lang="fr">stockage de clés Java JCE</comment>
- <comment xml:lang="ga">eochairstór Java JCE</comment>
- <comment xml:lang="gl">almacén de chves JCE de Java</comment>
- <comment xml:lang="he">אחסון מפתחות של Java JCE</comment>
- <comment xml:lang="hr">Java JCE baza ključeva</comment>
- <comment xml:lang="hu">Java JCE kulcstároló</comment>
- <comment xml:lang="ia">Magazin de claves Java JCE</comment>
- <comment xml:lang="id">Penyimpanan kunci Java JCE</comment>
- <comment xml:lang="it">Keystore Java JCE</comment>
- <comment xml:lang="ja">Java JCE キーストア</comment>
- <comment xml:lang="kk">Java JCE сақталымы</comment>
- <comment xml:lang="ko">Java JCE 키 저장소</comment>
- <comment xml:lang="lt">Java JCE raktų saugykla</comment>
- <comment xml:lang="lv">Java JCE keystore</comment>
- <comment xml:lang="nl">Java JCE keystore</comment>
- <comment xml:lang="oc">emmagazinatge de claus Java JCE</comment>
- <comment xml:lang="pl">Baza kluczy Java JCE</comment>
- <comment xml:lang="pt">armazém de chaves JavaJCE</comment>
- <comment xml:lang="pt_BR">Keystore JCE do Java</comment>
- <comment xml:lang="ro">Stocare chei Java JCE</comment>
- <comment xml:lang="ru">Хранилище ключей Java JCE</comment>
- <comment xml:lang="sk">Úložisko kľúčov Java JCE</comment>
- <comment xml:lang="sl">Datoteka tipkovne razporeditve Java JCE</comment>
- <comment xml:lang="sr">смештај ЈЦЕ кључа Јаве</comment>
- <comment xml:lang="sv">Java JCE-nyckellager</comment>
- <comment xml:lang="tr">Java JCE deposu</comment>
- <comment xml:lang="uk">сховище ключів JCE Java</comment>
- <comment xml:lang="zh_CN">Java JCE 密钥库</comment>
<comment xml:lang="zh_TW">Java JCE 金鑰儲存</comment>
+ <comment xml:lang="zh_CN">Java JCE 密钥库</comment>
+ <comment xml:lang="uk">сховище ключів JCE Java</comment>
+ <comment xml:lang="tr">Java JCE anahtar deposu</comment>
+ <comment xml:lang="sv">Java JCE-nyckellager</comment>
+ <comment xml:lang="sr">смештај ЈЦЕ кључа Јаве</comment>
+ <comment xml:lang="sl">Datoteka tipkovne razporeditve Java JCE</comment>
+ <comment xml:lang="si">ජාවා JCE යතුරු ගබඩාව</comment>
+ <comment xml:lang="sk">Úložisko kľúčov Java JCE</comment>
+ <comment xml:lang="ru">Хранилище ключей Java JCE</comment>
+ <comment xml:lang="ro">Stocare chei Java JCE</comment>
+ <comment xml:lang="pt_BR">Keystore JCE do Java</comment>
+ <comment xml:lang="pt">armazém de chaves JavaJCE</comment>
+ <comment xml:lang="pl">Baza kluczy Java JCE</comment>
+ <comment xml:lang="oc">emmagazinatge de claus Java JCE</comment>
+ <comment xml:lang="nl">Java JCE-keystore</comment>
+ <comment xml:lang="lv">Java JCE keystore</comment>
+ <comment xml:lang="lt">Java JCE raktų saugykla</comment>
+ <comment xml:lang="ko">Java JCE 키 저장소</comment>
+ <comment xml:lang="kk">Java JCE сақталымы</comment>
+ <comment xml:lang="ja">Java JCE キーストア</comment>
+ <comment xml:lang="it">Keystore Java JCE</comment>
+ <comment xml:lang="is">Java JCE lyklageymsla</comment>
+ <comment xml:lang="id">Penyimpanan kunci Java JCE</comment>
+ <comment xml:lang="ia">Magazin de claves Java JCE</comment>
+ <comment xml:lang="hu">Java JCE kulcstároló</comment>
+ <comment xml:lang="hr">Java JCE baza ključeva</comment>
+ <comment xml:lang="he">אחסון מפתחות של Java JCE</comment>
+ <comment xml:lang="gl">almacén de chves JCE de Java</comment>
+ <comment xml:lang="ga">eochairstór Java JCE</comment>
+ <comment xml:lang="fur">archivi di clâfs JCE Java</comment>
+ <comment xml:lang="fr">stockage de clés Java JCE</comment>
+ <comment xml:lang="fo">Java JCE lyklagoymsla</comment>
+ <comment xml:lang="fi">Java JCE -avainvarasto</comment>
+ <comment xml:lang="eu">Java JCE-ren gako-biltegia</comment>
+ <comment xml:lang="es">almacén de claves JCE de Java</comment>
+ <comment xml:lang="en_GB">Java JCE keystore</comment>
+ <comment xml:lang="el">Αποθήκη κλειδιών Java JCE</comment>
+ <comment xml:lang="de">Java JCE-Schlüsselbund</comment>
+ <comment xml:lang="da">Java JCE-nøglelager</comment>
+ <comment xml:lang="cs">úložiště klíčů Java JCE</comment>
+ <comment xml:lang="ca">magatzem de claus JCE de Java</comment>
+ <comment xml:lang="bg">Ключодържател — Java JCE</comment>
+ <comment xml:lang="be">сховішча ключоў Java JCE</comment>
+ <comment xml:lang="ar">مخزن مفاتيح Java JCE</comment>
<acronym>JCE</acronym>
<expanded-acronym>Java Cryptography Extension</expanded-acronym>
- <magic priority="50">
- <match value="0xcececece" type="host32" offset="0"/>
+ <magic>
+ <match type="host32" value="0xcececece" offset="0"/>
</magic>
<glob pattern="*.jceks"/>
</mime-type>
<mime-type type="application/x-java-pack200">
<comment>Pack200 Java archive</comment>
- <comment xml:lang="ar">أرشيف Pack200 Java</comment>
- <comment xml:lang="be@latin">Archiŭ Pack200 Java</comment>
- <comment xml:lang="bg">Архив — Java Pack200</comment>
- <comment xml:lang="ca">arxiu de Java en Pack200</comment>
- <comment xml:lang="cs">archiv Java Pack200</comment>
- <comment xml:lang="da">Pack200 Java-arkiv</comment>
- <comment xml:lang="de">Pack200-Java-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Java Pack200</comment>
- <comment xml:lang="en_GB">Pack200 Java archive</comment>
- <comment xml:lang="es">archivador Pack200 Java</comment>
- <comment xml:lang="eu">Pack2000 Java artxiboa</comment>
- <comment xml:lang="fi">Pack200-Java-arkisto</comment>
- <comment xml:lang="fo">Pack200 Java skjalasavn</comment>
- <comment xml:lang="fr">archive Java Pack200</comment>
- <comment xml:lang="ga">cartlann Java Pack200</comment>
- <comment xml:lang="gl">arquivo Pack200 Java</comment>
- <comment xml:lang="he">ארכיון מסוג Pack200 Java</comment>
- <comment xml:lang="hr">Pack200 Java arhiva</comment>
- <comment xml:lang="hu">Pack200 Java-archívum</comment>
- <comment xml:lang="ia">Archivo Java Pack200</comment>
- <comment xml:lang="id">Arsip Pack200 Java</comment>
- <comment xml:lang="it">Archivio Pack200 Java</comment>
- <comment xml:lang="ja">Pack200 Java アーカイブ</comment>
- <comment xml:lang="kk">Pack200 Java архиві</comment>
- <comment xml:lang="ko">Pack200 Java 압축 파일</comment>
- <comment xml:lang="lt">Pack200 Java archyvas</comment>
- <comment xml:lang="lv">Pack200 Java arhīvs</comment>
- <comment xml:lang="nb">Pack200 Java-arkiv</comment>
- <comment xml:lang="nl">Pack200 Java-archief</comment>
- <comment xml:lang="nn">Pack200 Java-arkiv</comment>
- <comment xml:lang="oc">archiu Java Pack200</comment>
- <comment xml:lang="pl">Archiwum Java Pack200</comment>
- <comment xml:lang="pt">arquivo Java Pack200</comment>
- <comment xml:lang="pt_BR">Pacote Java Pack200</comment>
- <comment xml:lang="ro">Arhivă Java Pack2000</comment>
- <comment xml:lang="ru">Архив Java Pack200</comment>
- <comment xml:lang="sk">Archív Java Pack200</comment>
- <comment xml:lang="sl">Datoteka arhiva Pack200 Java</comment>
- <comment xml:lang="sq">Arkiv Java Pack200</comment>
- <comment xml:lang="sr">архива Јаве Пак200</comment>
- <comment xml:lang="sv">Pack200 Java-arkiv</comment>
- <comment xml:lang="tr">Pack200 Java arşivi</comment>
- <comment xml:lang="uk">архів Java Pack200</comment>
- <comment xml:lang="vi">Kho nén Java Pack200</comment>
- <comment xml:lang="zh_CN">Pack200 Java 归档文件</comment>
<comment xml:lang="zh_TW">Pack200 Java 封存檔</comment>
+ <comment xml:lang="zh_CN">Pack200 Java 归档文件</comment>
+ <comment xml:lang="vi">Kho nén Java Pack200</comment>
+ <comment xml:lang="uk">архів Java Pack200</comment>
+ <comment xml:lang="tr">Pack200 Java arşivi</comment>
+ <comment xml:lang="sv">Pack200 Java-arkiv</comment>
+ <comment xml:lang="sr">архива Јаве Пак200</comment>
+ <comment xml:lang="sq">arkiv Java Pack200</comment>
+ <comment xml:lang="sl">Datoteka arhiva Pack200 Java</comment>
+ <comment xml:lang="si">Pack200 Java සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Java Pack200</comment>
+ <comment xml:lang="ru">Архив Java Pack200</comment>
+ <comment xml:lang="ro">Arhivă Java Pack2000</comment>
+ <comment xml:lang="pt_BR">Pacote Java Pack200</comment>
+ <comment xml:lang="pt">arquivo Java Pack200</comment>
+ <comment xml:lang="pl">Archiwum Java Pack200</comment>
+ <comment xml:lang="oc">archiu Java Pack200</comment>
+ <comment xml:lang="nn">Pack200 Java-arkiv</comment>
+ <comment xml:lang="nl">Pack200 Java-archief</comment>
+ <comment xml:lang="nb">Pack200 Java-arkiv</comment>
+ <comment xml:lang="lv">Pack200 Java arhīvs</comment>
+ <comment xml:lang="lt">Pack200 Java archyvas</comment>
+ <comment xml:lang="ko">Pack200 Java 압축 파일</comment>
+ <comment xml:lang="kk">Pack200 Java архиві</comment>
+ <comment xml:lang="ja">Pack200 Java アーカイブ</comment>
+ <comment xml:lang="it">Archivio Pack200 Java</comment>
+ <comment xml:lang="is">Pack200 Java safnskrá</comment>
+ <comment xml:lang="id">Arsip Pack200 Java</comment>
+ <comment xml:lang="ia">Archivo Java Pack200</comment>
+ <comment xml:lang="hu">Pack200 Java-archívum</comment>
+ <comment xml:lang="hr">Pack200 Java arhiva</comment>
+ <comment xml:lang="he">ארכיון מסוג Pack200 Java</comment>
+ <comment xml:lang="gl">arquivo Pack200 Java</comment>
+ <comment xml:lang="ga">cartlann Java Pack200</comment>
+ <comment xml:lang="fur">archivi Java Pack200</comment>
+ <comment xml:lang="fr">archive Java Pack200</comment>
+ <comment xml:lang="fo">Pack200 Java skjalasavn</comment>
+ <comment xml:lang="fi">Pack200-Java-arkisto</comment>
+ <comment xml:lang="eu">Pack2000 Java artxiboa</comment>
+ <comment xml:lang="es">archivador Pack200 Java</comment>
+ <comment xml:lang="en_GB">Pack200 Java archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Java Pack200</comment>
+ <comment xml:lang="de">Pack200-Java-Archiv</comment>
+ <comment xml:lang="da">Pack200 Java-arkiv</comment>
+ <comment xml:lang="cs">archiv Java Pack200</comment>
+ <comment xml:lang="ca">arxiu de Java en Pack200</comment>
+ <comment xml:lang="bg">Архив — Java Pack200</comment>
+ <comment xml:lang="be@latin">Archiŭ Pack200 Java</comment>
+ <comment xml:lang="be">архіў Pack200 Java</comment>
+ <comment xml:lang="ar">أرشيف Pack200 Java</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="0xcafed00d" type="big32" offset="0"/>
+ <match type="big32" value="0xcafed00d" offset="0"/>
</magic>
<glob pattern="*.pack"/>
</mime-type>
- <mime-type type="application/javascript">
+ <mime-type type="text/javascript">
<comment>JavaScript program</comment>
- <comment xml:lang="ar">برنامج جافاسكربت</comment>
- <comment xml:lang="be@latin">Prahrama JavaScript</comment>
- <comment xml:lang="bg">Програма на JavaScript</comment>
- <comment xml:lang="ca">programa JavaScript</comment>
- <comment xml:lang="cs">program v JavaScriptu</comment>
- <comment xml:lang="da">JavaScript-program</comment>
- <comment xml:lang="de">JavaScript-Programm</comment>
- <comment xml:lang="el">Πρόγραμμα JavaScript</comment>
- <comment xml:lang="en_GB">JavaScript program</comment>
- <comment xml:lang="eo">JavaScript-programo</comment>
- <comment xml:lang="es">programa en JavaScript</comment>
- <comment xml:lang="eu">JavaScript programa</comment>
- <comment xml:lang="fi">JavaScript-ohjelma</comment>
- <comment xml:lang="fo">JavaScript forrit</comment>
- <comment xml:lang="fr">programme JavaScript</comment>
- <comment xml:lang="ga">ríomhchlár JavaScript</comment>
- <comment xml:lang="gl">programa JavaScript</comment>
- <comment xml:lang="he">תכנית JavaScript</comment>
- <comment xml:lang="hr">JavaScript program</comment>
- <comment xml:lang="hu">JavaScript-program</comment>
- <comment xml:lang="ia">Programma JavaScript</comment>
- <comment xml:lang="id">Program JavaScript</comment>
- <comment xml:lang="it">Programma JavaScript</comment>
- <comment xml:lang="ja">JavaScript プログラム</comment>
- <comment xml:lang="kk">JavaScript бағдарламасы</comment>
- <comment xml:lang="ko">JavaScript 프로그램</comment>
- <comment xml:lang="lt">JavaScript programa</comment>
- <comment xml:lang="lv">JavaScript programma</comment>
- <comment xml:lang="ms">Program JavaScript</comment>
- <comment xml:lang="nb">JavaScript-program</comment>
- <comment xml:lang="nl">JavaScript-programma</comment>
- <comment xml:lang="nn">JavaScript-program</comment>
- <comment xml:lang="oc">programa JavaEscript</comment>
- <comment xml:lang="pl">Pogram JavaScript</comment>
- <comment xml:lang="pt">programa JavaScript</comment>
- <comment xml:lang="pt_BR">Programa JavaScript</comment>
- <comment xml:lang="ro">Program JavaScript</comment>
- <comment xml:lang="ru">Программа JavaScript</comment>
- <comment xml:lang="sk">Program jazyka JavaScript</comment>
- <comment xml:lang="sl">Programska datoteka JavaScript</comment>
- <comment xml:lang="sq">Program JavaScript</comment>
- <comment xml:lang="sr">програм Јава скрипте</comment>
- <comment xml:lang="sv">JavaScript-program</comment>
- <comment xml:lang="tr">JavaScript programı</comment>
- <comment xml:lang="uk">програма мовою JavaScript</comment>
- <comment xml:lang="vi">Chương trình JavaScript</comment>
- <comment xml:lang="zh_CN">JavaScript 程序</comment>
<comment xml:lang="zh_TW">JavaScript 程式</comment>
+ <comment xml:lang="zh_CN">JavaScript 程序</comment>
+ <comment xml:lang="vi">Chương trình JavaScript</comment>
+ <comment xml:lang="uk">програма мовою JavaScript</comment>
+ <comment xml:lang="tr">JavaScript programı</comment>
+ <comment xml:lang="sv">JavaScript-program</comment>
+ <comment xml:lang="sr">програм Јава скрипте</comment>
+ <comment xml:lang="sq">program JavaScript</comment>
+ <comment xml:lang="sl">Programska datoteka JavaScript</comment>
+ <comment xml:lang="si">JavaScript වැඩසටහන</comment>
+ <comment xml:lang="sk">Program jazyka JavaScript</comment>
+ <comment xml:lang="ru">Программа JavaScript</comment>
+ <comment xml:lang="ro">Program JavaScript</comment>
+ <comment xml:lang="pt_BR">Programa JavaScript</comment>
+ <comment xml:lang="pt">programa JavaScript</comment>
+ <comment xml:lang="pl">Pogram JavaScript</comment>
+ <comment xml:lang="oc">programa JavaEscript</comment>
+ <comment xml:lang="nn">JavaScript-program</comment>
+ <comment xml:lang="nl">JavaScript-programma</comment>
+ <comment xml:lang="nb">JavaScript-program</comment>
+ <comment xml:lang="ms">Program JavaScript</comment>
+ <comment xml:lang="lv">JavaScript programma</comment>
+ <comment xml:lang="lt">JavaScript programa</comment>
+ <comment xml:lang="ko">JavaScript 프로그램</comment>
+ <comment xml:lang="kk">JavaScript бағдарламасы</comment>
+ <comment xml:lang="ja">JavaScript プログラム</comment>
+ <comment xml:lang="it">Programma JavaScript</comment>
+ <comment xml:lang="is">JavaScript forrit</comment>
+ <comment xml:lang="id">Program JavaScript</comment>
+ <comment xml:lang="ia">Programma JavaScript</comment>
+ <comment xml:lang="hu">JavaScript-program</comment>
+ <comment xml:lang="hr">JavaScript program</comment>
+ <comment xml:lang="he">תכנית JavaScript</comment>
+ <comment xml:lang="gl">programa JavaScript</comment>
+ <comment xml:lang="ga">ríomhchlár JavaScript</comment>
+ <comment xml:lang="fur">program JavaScript</comment>
+ <comment xml:lang="fr">programme JavaScript</comment>
+ <comment xml:lang="fo">JavaScript forrit</comment>
+ <comment xml:lang="fi">JavaScript-ohjelma</comment>
+ <comment xml:lang="eu">JavaScript programa</comment>
+ <comment xml:lang="es">programa en JavaScript</comment>
+ <comment xml:lang="eo">JavaScript-programo</comment>
+ <comment xml:lang="en_GB">JavaScript program</comment>
+ <comment xml:lang="el">Πρόγραμμα JavaScript</comment>
+ <comment xml:lang="de">JavaScript-Programm</comment>
+ <comment xml:lang="da">JavaScript-program</comment>
+ <comment xml:lang="cs">program v JavaScriptu</comment>
+ <comment xml:lang="ca">programa JavaScript</comment>
+ <comment xml:lang="bg">Програма на JavaScript</comment>
+ <comment xml:lang="be@latin">Prahrama JavaScript</comment>
+ <comment xml:lang="be">праграма JavaScript</comment>
+ <comment xml:lang="ar">برنامج جافاسكربت</comment>
+ <comment xml:lang="af">JavaScript-program</comment>
<alias type="application/x-javascript"/>
- <alias type="text/javascript"/>
- <sub-class-of type="application/ecmascript"/>
+ <alias type="application/javascript"/>
+ <alias type="text/jscript"/>
+ <sub-class-of type="application/x-executable"/>
+ <sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
- <magic priority="50">
- <match value="#!/bin/gjs" type="string" offset="0"/>
- <match value="#! /bin/gjs" type="string" offset="0"/>
- <match value='eval \"exec /bin/gjs' type="string" offset="0"/>
- <match value="#!/usr/bin/gjs" type="string" offset="0"/>
- <match value="#! /usr/bin/gjs" type="string" offset="0"/>
- <match value='eval \"exec /usr/bin/gjs' type="string" offset="0"/>
- <match value="#!/usr/local/bin/gjs" type="string" offset="0"/>
- <match value="#! /usr/local/bin/gjs" type="string" offset="0"/>
- <match value='eval \"exec /usr/local/bin/gjs' type="string" offset="0"/>
- <match value='/bin/env gjs' type="string" offset="2:16"/>
+ <magic>
+ <match type="string" value="#!/bin/gjs" offset="0"/>
+ <match type="string" value="#! /bin/gjs" offset="0"/>
+ <match type="string" value="eval \&quot;exec /bin/gjs" offset="0"/>
+ <match type="string" value="#!/usr/bin/gjs" offset="0"/>
+ <match type="string" value="#! /usr/bin/gjs" offset="0"/>
+ <match type="string" value="eval \&quot;exec /usr/bin/gjs" offset="0"/>
+ <match type="string" value="#!/usr/local/bin/gjs" offset="0"/>
+ <match type="string" value="#! /usr/local/bin/gjs" offset="0"/>
+ <match type="string" value="eval \&quot;exec /usr/local/bin/gjs" offset="0"/>
+ <match type="string" value="/bin/env gjs" offset="2:16"/>
</magic>
<glob pattern="*.js"/>
<glob pattern="*.jsm"/>
<glob pattern="*.mjs"/>
</mime-type>
+ <mime-type type="text/jscript.encode">
+ <comment>Encoded JScript program</comment>
+ <comment xml:lang="uk">кодована програма JScript</comment>
+ <comment xml:lang="sv">Kodat JScript-program</comment>
+ <comment xml:lang="ru">Зашифрованная программа на JScript</comment>
+ <comment xml:lang="pl">Zakodowany program JScript</comment>
+ <comment xml:lang="es">programa en JScript codificado</comment>
+ <comment xml:lang="de">Verschlüsseltes JScript-Programm</comment>
+ <sub-class-of type="application/x-executable"/>
+ <generic-icon name="text-x-script"/>
+ <magic>
+ <match type="string" value="#@~^" offset="0"/>
+ </magic>
+ <glob pattern="*.jse"/>
+ </mime-type>
<mime-type type="application/json">
<comment>JSON document</comment>
- <comment xml:lang="ast">Documentu JSON</comment>
- <comment xml:lang="ca">document JSON</comment>
- <comment xml:lang="cs">dokument JSON</comment>
- <comment xml:lang="da">JSON-dokument</comment>
- <comment xml:lang="de">JSON-Dokument</comment>
- <comment xml:lang="el">Έγγραφο JSON</comment>
- <comment xml:lang="en_GB">JSON document</comment>
- <comment xml:lang="es">documento JSON</comment>
- <comment xml:lang="eu">JSON dokumentua</comment>
- <comment xml:lang="fi">JSON-asiakirja</comment>
- <comment xml:lang="fr">document JSON</comment>
- <comment xml:lang="ga">cáipéis JSON</comment>
- <comment xml:lang="gl">Documento JSON</comment>
- <comment xml:lang="he">מסמך JSON</comment>
- <comment xml:lang="hr">JSON dokument</comment>
- <comment xml:lang="hu">JSON dokumentum</comment>
- <comment xml:lang="ia">Documento JSON</comment>
- <comment xml:lang="id">Dokumen JSON</comment>
- <comment xml:lang="it">Documento JSON</comment>
- <comment xml:lang="kk">JSON құжаты</comment>
- <comment xml:lang="ko">JSON 문서</comment>
- <comment xml:lang="oc">document JSON</comment>
- <comment xml:lang="pl">Dokument JSON</comment>
- <comment xml:lang="pt">documento JSON</comment>
- <comment xml:lang="pt_BR">Documento JSON</comment>
- <comment xml:lang="ru">Документ JSON</comment>
- <comment xml:lang="sk">Dokument JSON</comment>
- <comment xml:lang="sl">Dokument JSON</comment>
- <comment xml:lang="sr">ЈСОН документ</comment>
- <comment xml:lang="sv">JSON-dokument</comment>
- <comment xml:lang="tr">JSON belgesi</comment>
- <comment xml:lang="uk">документ JSON</comment>
- <comment xml:lang="zh_CN">JSON 文档</comment>
<comment xml:lang="zh_TW">JSON 文件</comment>
+ <comment xml:lang="zh_CN">JSON 文档</comment>
+ <comment xml:lang="uk">документ JSON</comment>
+ <comment xml:lang="tr">JSON belgesi</comment>
+ <comment xml:lang="sv">JSON-dokument</comment>
+ <comment xml:lang="sr">ЈСОН документ</comment>
+ <comment xml:lang="sq">dokument JSON</comment>
+ <comment xml:lang="sl">Dokument JSON</comment>
+ <comment xml:lang="si">JSON ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument JSON</comment>
+ <comment xml:lang="ru">Документ JSON</comment>
+ <comment xml:lang="pt_BR">Documento JSON</comment>
+ <comment xml:lang="pt">documento JSON</comment>
+ <comment xml:lang="pl">Dokument JSON</comment>
+ <comment xml:lang="oc">document JSON</comment>
+ <comment xml:lang="nl">JSON-document</comment>
+ <comment xml:lang="ko">JSON 문서</comment>
+ <comment xml:lang="kk">JSON құжаты</comment>
+ <comment xml:lang="ja">JSON ドキュメント</comment>
+ <comment xml:lang="it">Documento JSON</comment>
+ <comment xml:lang="is">JSON skjal</comment>
+ <comment xml:lang="id">Dokumen JSON</comment>
+ <comment xml:lang="ia">Documento JSON</comment>
+ <comment xml:lang="hu">JSON dokumentum</comment>
+ <comment xml:lang="hr">JSON dokument</comment>
+ <comment xml:lang="he">מסמך JSON</comment>
+ <comment xml:lang="gl">Documento JSON</comment>
+ <comment xml:lang="ga">cáipéis JSON</comment>
+ <comment xml:lang="fur">document JSON</comment>
+ <comment xml:lang="fr">document JSON</comment>
+ <comment xml:lang="fi">JSON-asiakirja</comment>
+ <comment xml:lang="eu">JSON dokumentua</comment>
+ <comment xml:lang="es">documento JSON</comment>
+ <comment xml:lang="en_GB">JSON document</comment>
+ <comment xml:lang="el">Έγγραφο JSON</comment>
+ <comment xml:lang="de">JSON-Dokument</comment>
+ <comment xml:lang="da">JSON-dokument</comment>
+ <comment xml:lang="cs">dokument JSON</comment>
+ <comment xml:lang="ca">document JSON</comment>
+ <comment xml:lang="bg">Документ — JSON</comment>
+ <comment xml:lang="be">дакумент JSON</comment>
+ <comment xml:lang="ast">Documentu JSON</comment>
+ <comment xml:lang="ar">مستند JSON</comment>
+ <comment xml:lang="af">JSON-dokument</comment>
<acronym>JSON</acronym>
<expanded-acronym>JavaScript Object Notation</expanded-acronym>
- <sub-class-of type="application/javascript"/>
+ <sub-class-of type="application/json5"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.json"/>
</mime-type>
+ <mime-type type="application/json5">
+ <comment>JSON5 document</comment>
+ <comment xml:lang="uk">документ JSON5</comment>
+ <comment xml:lang="sv">JSON5-dokument</comment>
+ <comment xml:lang="ru">Документ JSON5</comment>
+ <comment xml:lang="pl">Dokument JSON5</comment>
+ <comment xml:lang="es">documento JSON5</comment>
+ <comment xml:lang="de">JSON5-Dokument</comment>
+ <acronym>JSON5</acronym>
+ <expanded-acronym>JavaScript Object Notation 5</expanded-acronym>
+ <sub-class-of type="text/javascript"/>
+ <generic-icon name="text-x-script"/>
+ <glob pattern="*.json5"/>
+ </mime-type>
<mime-type type="application/jrd+json">
<comment>JRD document</comment>
- <comment xml:lang="ast">Documentu JRD</comment>
- <comment xml:lang="ca">document JRD</comment>
- <comment xml:lang="cs">dokument JRD</comment>
- <comment xml:lang="da">JRD-dokument</comment>
- <comment xml:lang="de">JRD-Dokument</comment>
- <comment xml:lang="el">Έγγραφο JRD</comment>
- <comment xml:lang="en_GB">JRD document</comment>
- <comment xml:lang="es">documento JRD</comment>
- <comment xml:lang="eu">JRD dokumentua</comment>
- <comment xml:lang="fi">JRD-asiakirja</comment>
- <comment xml:lang="fr">document JRD</comment>
- <comment xml:lang="ga">cáipéis JRD</comment>
- <comment xml:lang="he">מסמך JRD</comment>
- <comment xml:lang="hr">JRD dokument</comment>
- <comment xml:lang="hu">JRD dokumentum</comment>
- <comment xml:lang="ia">Documento JRD</comment>
- <comment xml:lang="id">Dokumen JRD</comment>
- <comment xml:lang="it">Documento JRD</comment>
- <comment xml:lang="kk">JRD құжаты</comment>
- <comment xml:lang="ko">JRD 문서</comment>
- <comment xml:lang="oc">document JRD</comment>
- <comment xml:lang="pl">Dokument JRD</comment>
- <comment xml:lang="pt">doxumento JRD</comment>
- <comment xml:lang="pt_BR">Documento JRD</comment>
- <comment xml:lang="ru">Документ JRD</comment>
- <comment xml:lang="sk">Dokument JRD</comment>
- <comment xml:lang="sr">ЈРД документ</comment>
- <comment xml:lang="sv">JRD-dokument</comment>
- <comment xml:lang="tr">JRD belgesi</comment>
- <comment xml:lang="uk">документ JRD</comment>
- <comment xml:lang="zh_CN">JRD 文档</comment>
<comment xml:lang="zh_TW">JRD 文件</comment>
+ <comment xml:lang="zh_CN">JRD 文档</comment>
+ <comment xml:lang="uk">документ JRD</comment>
+ <comment xml:lang="tr">JRD belgesi</comment>
+ <comment xml:lang="sv">JRD-dokument</comment>
+ <comment xml:lang="sr">ЈРД документ</comment>
+ <comment xml:lang="sq">dokument JRD</comment>
+ <comment xml:lang="sl">Dokument JRD</comment>
+ <comment xml:lang="si">JRD ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument JRD</comment>
+ <comment xml:lang="ru">Документ JRD</comment>
+ <comment xml:lang="pt_BR">Documento JRD</comment>
+ <comment xml:lang="pt">doxumento JRD</comment>
+ <comment xml:lang="pl">Dokument JRD</comment>
+ <comment xml:lang="oc">document JRD</comment>
+ <comment xml:lang="nl">JRD-document</comment>
+ <comment xml:lang="ko">JRD 문서</comment>
+ <comment xml:lang="kk">JRD құжаты</comment>
+ <comment xml:lang="ja">JRD ドキュメント</comment>
+ <comment xml:lang="it">Documento JRD</comment>
+ <comment xml:lang="is">JRD skjal</comment>
+ <comment xml:lang="id">Dokumen JRD</comment>
+ <comment xml:lang="ia">Documento JRD</comment>
+ <comment xml:lang="hu">JRD dokumentum</comment>
+ <comment xml:lang="hr">JRD dokument</comment>
+ <comment xml:lang="he">מסמך JRD</comment>
+ <comment xml:lang="gl">Documento JRD</comment>
+ <comment xml:lang="ga">cáipéis JRD</comment>
+ <comment xml:lang="fur">document JRD</comment>
+ <comment xml:lang="fr">document JRD</comment>
+ <comment xml:lang="fi">JRD-asiakirja</comment>
+ <comment xml:lang="eu">JRD dokumentua</comment>
+ <comment xml:lang="es">documento JRD</comment>
+ <comment xml:lang="en_GB">JRD document</comment>
+ <comment xml:lang="el">Έγγραφο JRD</comment>
+ <comment xml:lang="de">JRD-Dokument</comment>
+ <comment xml:lang="da">JRD-dokument</comment>
+ <comment xml:lang="cs">dokument JRD</comment>
+ <comment xml:lang="ca">document JRD</comment>
+ <comment xml:lang="bg">Документ — JRD</comment>
+ <comment xml:lang="be">дакумент JRD</comment>
+ <comment xml:lang="ast">Documentu JRD</comment>
+ <comment xml:lang="ar">مستند JRD</comment>
+ <comment xml:lang="af">JRD-dokument</comment>
<acronym>JRD</acronym>
<expanded-acronym>JSON Resource Descriptor</expanded-acronym>
<sub-class-of type="application/json"/>
@@ -13388,35 +14547,47 @@
</mime-type>
<mime-type type="application/json-patch+json">
<comment>JSON patch</comment>
- <comment xml:lang="ca">pedaç de JSON</comment>
- <comment xml:lang="cs">cesta JSON</comment>
- <comment xml:lang="da">JSON-rettelse</comment>
- <comment xml:lang="de">JSON-Patch</comment>
- <comment xml:lang="en_GB">JSON patch</comment>
- <comment xml:lang="es">parche en JSON</comment>
- <comment xml:lang="eu">JSON adabakia</comment>
- <comment xml:lang="fr">correctif JSON</comment>
- <comment xml:lang="ga">paiste JSON</comment>
- <comment xml:lang="he">טלאי JSON</comment>
- <comment xml:lang="hr">JSON zakrpa</comment>
- <comment xml:lang="hu">JSON javítócsomag</comment>
- <comment xml:lang="ia">Patch JSON</comment>
- <comment xml:lang="id">Patch JSON</comment>
- <comment xml:lang="it">Patch JSON</comment>
- <comment xml:lang="kk">JSON өзгерісі</comment>
- <comment xml:lang="ko">JSON 패치</comment>
- <comment xml:lang="oc">correctiu JSON</comment>
- <comment xml:lang="pl">Łata JSON</comment>
- <comment xml:lang="pt">patch JSON</comment>
- <comment xml:lang="pt_BR">Patch JSON</comment>
- <comment xml:lang="ru">Патч JSON</comment>
- <comment xml:lang="sk">Záplata JSON</comment>
- <comment xml:lang="sr">ЈСОН закрпа</comment>
- <comment xml:lang="sv">JSON patch</comment>
- <comment xml:lang="tr">JSON yaması</comment>
- <comment xml:lang="uk">латка JSON</comment>
- <comment xml:lang="zh_CN">JSON 补丁</comment>
<comment xml:lang="zh_TW">JSON 修補檔</comment>
+ <comment xml:lang="zh_CN">JSON 补丁</comment>
+ <comment xml:lang="uk">латка JSON</comment>
+ <comment xml:lang="tr">JSON yaması</comment>
+ <comment xml:lang="sv">JSON patch</comment>
+ <comment xml:lang="sr">ЈСОН закрпа</comment>
+ <comment xml:lang="sq">arnë JSON</comment>
+ <comment xml:lang="sl">Popravek JSON</comment>
+ <comment xml:lang="si">JSON පැච්</comment>
+ <comment xml:lang="sk">Záplata JSON</comment>
+ <comment xml:lang="ru">Патч JSON</comment>
+ <comment xml:lang="pt_BR">Patch JSON</comment>
+ <comment xml:lang="pt">patch JSON</comment>
+ <comment xml:lang="pl">Łata JSON</comment>
+ <comment xml:lang="oc">correctiu JSON</comment>
+ <comment xml:lang="nl">JSON-patch</comment>
+ <comment xml:lang="ko">JSON 패치</comment>
+ <comment xml:lang="kk">JSON өзгерісі</comment>
+ <comment xml:lang="ja">JSON パッチ</comment>
+ <comment xml:lang="it">Patch JSON</comment>
+ <comment xml:lang="is">JSON kóðabót</comment>
+ <comment xml:lang="id">Patch JSON</comment>
+ <comment xml:lang="ia">Patch JSON</comment>
+ <comment xml:lang="hu">JSON javítócsomag</comment>
+ <comment xml:lang="hr">JSON zakrpa</comment>
+ <comment xml:lang="he">טלאי JSON</comment>
+ <comment xml:lang="gl">Parche JSON</comment>
+ <comment xml:lang="ga">paiste JSON</comment>
+ <comment xml:lang="fur">blec JSON</comment>
+ <comment xml:lang="fr">correctif JSON</comment>
+ <comment xml:lang="fi">JSON-paikkatiedosto</comment>
+ <comment xml:lang="eu">JSON adabakia</comment>
+ <comment xml:lang="es">parche en JSON</comment>
+ <comment xml:lang="en_GB">JSON patch</comment>
+ <comment xml:lang="de">JSON-Patch</comment>
+ <comment xml:lang="da">JSON-rettelse</comment>
+ <comment xml:lang="cs">cesta JSON</comment>
+ <comment xml:lang="ca">pedaç de JSON</comment>
+ <comment xml:lang="bg">Кръпка — JSON</comment>
+ <comment xml:lang="be">патч JSON</comment>
+ <comment xml:lang="ar">رقعة JSON</comment>
<acronym>JSON</acronym>
<expanded-acronym>JavaScript Object Notation</expanded-acronym>
<sub-class-of type="application/json"/>
@@ -13425,233 +14596,306 @@
</mime-type>
<mime-type type="application/ld+json">
<comment>JSON-LD document</comment>
- <comment xml:lang="ast">Documentu JSON-LD</comment>
- <comment xml:lang="ca">document JSON-LD</comment>
- <comment xml:lang="cs">dokument JSON-LD</comment>
- <comment xml:lang="da">JSON-LD-dokument</comment>
- <comment xml:lang="de">JSON-LD-Dokument</comment>
- <comment xml:lang="el">Έγγραφο JSON-LD</comment>
- <comment xml:lang="en_GB">JSON-LD document</comment>
- <comment xml:lang="es">documento JSON-LD</comment>
- <comment xml:lang="eu">JSON-LD dokumentua</comment>
- <comment xml:lang="fi">JSON-LD-asiakirja</comment>
- <comment xml:lang="fr">document JSON-LD</comment>
- <comment xml:lang="ga">cáipéis JSON-LD</comment>
- <comment xml:lang="he">מסמך JSON-LD</comment>
- <comment xml:lang="hr">JSON-LD dokument</comment>
- <comment xml:lang="hu">JSON-LD dokumentum</comment>
- <comment xml:lang="ia">Documento JSON-LD</comment>
- <comment xml:lang="id">Dokumen JSON-LD</comment>
- <comment xml:lang="it">Documento JSON-LD</comment>
- <comment xml:lang="kk">JSON-LD құжаты</comment>
- <comment xml:lang="ko">JSON-LD 문서</comment>
- <comment xml:lang="oc">Document JSON-LD</comment>
- <comment xml:lang="pl">Dokument JSON-LD</comment>
- <comment xml:lang="pt">documento JSON-LD</comment>
- <comment xml:lang="pt_BR">Documento JSON-LD</comment>
- <comment xml:lang="ru">Документ JSON-LD</comment>
- <comment xml:lang="sk">Dokument JSON-LD</comment>
- <comment xml:lang="sr">ЈСОН-ЛД документ</comment>
- <comment xml:lang="sv">JSON-LD-dokument</comment>
- <comment xml:lang="tr">JSON-LD belgesi</comment>
- <comment xml:lang="uk">документ JSON-LD</comment>
- <comment xml:lang="zh_CN">JSON-LD 文档</comment>
<comment xml:lang="zh_TW">JSON-LD 文件</comment>
+ <comment xml:lang="zh_CN">JSON-LD 文档</comment>
+ <comment xml:lang="uk">документ JSON-LD</comment>
+ <comment xml:lang="tr">JSON-LD belgesi</comment>
+ <comment xml:lang="sv">JSON-LD-dokument</comment>
+ <comment xml:lang="sr">ЈСОН-ЛД документ</comment>
+ <comment xml:lang="sq">dokument JSON-LD</comment>
+ <comment xml:lang="sl">Dokument JSON-LD</comment>
+ <comment xml:lang="si">JSON-LD ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument JSON-LD</comment>
+ <comment xml:lang="ru">Документ JSON-LD</comment>
+ <comment xml:lang="pt_BR">Documento JSON-LD</comment>
+ <comment xml:lang="pt">documento JSON-LD</comment>
+ <comment xml:lang="pl">Dokument JSON-LD</comment>
+ <comment xml:lang="oc">Document JSON-LD</comment>
+ <comment xml:lang="nl">JSON-LD-document</comment>
+ <comment xml:lang="ko">JSON-LD 문서</comment>
+ <comment xml:lang="kk">JSON-LD құжаты</comment>
+ <comment xml:lang="ja">JSON-LD ドキュメント</comment>
+ <comment xml:lang="it">Documento JSON-LD</comment>
+ <comment xml:lang="is">JSON-LD skjal</comment>
+ <comment xml:lang="id">Dokumen JSON-LD</comment>
+ <comment xml:lang="ia">Documento JSON-LD</comment>
+ <comment xml:lang="hu">JSON-LD dokumentum</comment>
+ <comment xml:lang="hr">JSON-LD dokument</comment>
+ <comment xml:lang="he">מסמך JSON-LD</comment>
+ <comment xml:lang="gl">Documento de JSON-LD</comment>
+ <comment xml:lang="ga">cáipéis JSON-LD</comment>
+ <comment xml:lang="fur">document JSON-LD</comment>
+ <comment xml:lang="fr">document JSON-LD</comment>
+ <comment xml:lang="fi">JSON-LD-asiakirja</comment>
+ <comment xml:lang="eu">JSON-LD dokumentua</comment>
+ <comment xml:lang="es">documento JSON-LD</comment>
+ <comment xml:lang="en_GB">JSON-LD document</comment>
+ <comment xml:lang="el">Έγγραφο JSON-LD</comment>
+ <comment xml:lang="de">JSON-LD-Dokument</comment>
+ <comment xml:lang="da">JSON-LD-dokument</comment>
+ <comment xml:lang="cs">dokument JSON-LD</comment>
+ <comment xml:lang="ca">document JSON-LD</comment>
+ <comment xml:lang="bg">Документ — JSON-LD</comment>
+ <comment xml:lang="be">дакумент JSON-LD</comment>
+ <comment xml:lang="ast">Documentu JSON-LD</comment>
+ <comment xml:lang="ar">مستند JSON-LD</comment>
<acronym>JSON-LD</acronym>
<expanded-acronym>JavaScript Object Notation for Linked Data</expanded-acronym>
<sub-class-of type="application/json"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.jsonld"/>
</mime-type>
+ <mime-type type="application/schema+json">
+ <comment>JSON schema</comment>
+ <comment xml:lang="uk">схема JSON</comment>
+ <comment xml:lang="tr">JSON şeması</comment>
+ <comment xml:lang="sv">JSON-schema</comment>
+ <comment xml:lang="sl">Shema JSON</comment>
+ <comment xml:lang="si">JSON යෝජනා ක්රමය</comment>
+ <comment xml:lang="ru">Схема JSON</comment>
+ <comment xml:lang="pl">Schemat JSON</comment>
+ <comment xml:lang="oc">esquèma JSON</comment>
+ <comment xml:lang="nl">JSON-schema</comment>
+ <comment xml:lang="ko">JSON 스키마</comment>
+ <comment xml:lang="kk">JSON сұлбасы</comment>
+ <comment xml:lang="ja">JSON スキーマ</comment>
+ <comment xml:lang="it">Schema JSON</comment>
+ <comment xml:lang="hr">JSON shema</comment>
+ <comment xml:lang="he">סכמת JSON</comment>
+ <comment xml:lang="gl">Esquema de JSON</comment>
+ <comment xml:lang="fi">JSON-skeema</comment>
+ <comment xml:lang="eu">JSON eskema</comment>
+ <comment xml:lang="es">esquema JSON</comment>
+ <comment xml:lang="en_GB">JSON schema</comment>
+ <comment xml:lang="de">JSON-Schema</comment>
+ <comment xml:lang="be">схема JSON</comment>
+ <comment xml:lang="ar">مخطط JSON</comment>
+ <sub-class-of type="application/json"/>
+ <generic-icon name="text-x-script"/>
+ <magic priority="80">
+ <match type="string" value="{" offset="0">
+ <match type="string" value="&quot;$schema&quot;:" offset="1:256"/>
+ </match>
+ </magic>
+ <glob pattern="*.json"/>
+ </mime-type>
<mime-type type="application/x-ipynb+json">
- <comment>Jupyter Notebook</comment>
- <comment xml:lang="ca">llibreta de notes de Jupyter</comment>
- <comment xml:lang="cs">sešit Jupyter</comment>
- <comment xml:lang="da">Jupyter Notebook</comment>
- <comment xml:lang="de">Jupyter-Dokument</comment>
- <comment xml:lang="en_GB">Jupyter Notebook</comment>
- <comment xml:lang="es">libreta de Jupyter</comment>
- <comment xml:lang="eu">Jupyter Notebook</comment>
+ <comment>Jupyter notebook document</comment>
+ <comment xml:lang="zh_TW">Jupyter 記事本文件</comment>
+ <comment xml:lang="zh_CN">Jupyter 笔记本文档</comment>
+ <comment xml:lang="uk">документ нотатника Jupyter</comment>
+ <comment xml:lang="tr">Jupyter notebook belgesi</comment>
+ <comment xml:lang="sv">Jupyter-anteckningsboksdokument</comment>
+ <comment xml:lang="sq">dokument ditari Jupyter</comment>
+ <comment xml:lang="si">Jupyter සටහන් පොත් ලේඛනය</comment>
+ <comment xml:lang="ru">Документ Jupyter notebook</comment>
+ <comment xml:lang="pt_BR">Documento Jupyter Notebook</comment>
+ <comment xml:lang="pl">Dokument notatnika Jupyter</comment>
+ <comment xml:lang="nl">Jupyter notebook-document</comment>
+ <comment xml:lang="ko">주피터 노트북 문서</comment>
+ <comment xml:lang="kk">Jupyter блокнот құжаты</comment>
+ <comment xml:lang="ja">Jupyter notebook ドキュメント</comment>
+ <comment xml:lang="it">Documento notebook Jupyter</comment>
+ <comment xml:lang="is">Jupyter skrifblokkarskjal</comment>
+ <comment xml:lang="id">Dokumen Jupyter notebook</comment>
+ <comment xml:lang="hu">Jupyter munkafüzet dokumentum</comment>
+ <comment xml:lang="hr">Jupyter notebook dokument</comment>
+ <comment xml:lang="he">מסמך מחברת של Jupyter</comment>
+ <comment xml:lang="gl">Documento de caderno de Jupyter</comment>
<comment xml:lang="fr">carnet de notes Jupyter</comment>
- <comment xml:lang="ga">Leabhar nótaí Jupyter</comment>
- <comment xml:lang="he">מחברת Jupyter</comment>
- <comment xml:lang="hr">Jupyter bilježnica</comment>
- <comment xml:lang="hu">Jupyter notesz</comment>
- <comment xml:lang="id">Notebook Jupyter</comment>
- <comment xml:lang="it">Notebook Jupyter</comment>
- <comment xml:lang="kk">Jupyter Notebook</comment>
- <comment xml:lang="ko">Jupyter 노트북</comment>
- <comment xml:lang="pl">Notatnik Jupyter</comment>
- <comment xml:lang="pt_BR">Bloco de Notas Jupyter</comment>
- <comment xml:lang="ru">Jupyter Notebook</comment>
- <comment xml:lang="sk">Zošit programu Jupyter</comment>
- <comment xml:lang="sr">Џупитер бележница</comment>
- <comment xml:lang="sv">Jupyter Notebook-dokument</comment>
- <comment xml:lang="tr">Jupyter Notebook</comment>
- <comment xml:lang="uk">записник Jupyter</comment>
- <comment xml:lang="zh_CN">Jupyter 笔记本</comment>
- <comment xml:lang="zh_TW">Jupyter 記事本</comment>
+ <comment xml:lang="fi">Jupyter notebook -asiakirja</comment>
+ <comment xml:lang="eu">Jupyter notebook dokumentua</comment>
+ <comment xml:lang="es">documento de cuaderno de Jupyter</comment>
+ <comment xml:lang="en_GB">Jupyter notebook document</comment>
+ <comment xml:lang="de">Jupyter-Notebook-Dokument</comment>
+ <comment xml:lang="da">Jupyter notebook-dokument</comment>
+ <comment xml:lang="ca">document de llibreta de notes de Jupyter</comment>
+ <comment xml:lang="bg">Скицник — Jupyter</comment>
+ <comment xml:lang="be">дакумент Jupyter notebook</comment>
+ <comment xml:lang="ar">مستند دفتر Jupyter</comment>
<sub-class-of type="application/json"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="{" type="string" offset="0">
- <match value='"cells":' type="string" offset="1:256"/>
+ <magic>
+ <match type="string" value="{" offset="0">
+ <match type="string" value="&quot;cells&quot;:" offset="1:256"/>
</match>
</magic>
<glob pattern="*.ipynb"/>
</mime-type>
<mime-type type="application/vnd.coffeescript">
<comment>CoffeeScript document</comment>
- <comment xml:lang="ast">Documentu de CoffeScript</comment>
- <comment xml:lang="ca">document CoffeeScript</comment>
- <comment xml:lang="cs">dokument CoffeeScript</comment>
- <comment xml:lang="da">CoffeeScript-dokument</comment>
- <comment xml:lang="de">CoffeeScript-Dokument</comment>
- <comment xml:lang="el">Έγγραφο CoffeeScript</comment>
- <comment xml:lang="en_GB">CoffeeScript document</comment>
- <comment xml:lang="es">documento en CoffeeScript</comment>
- <comment xml:lang="eu">CoffeeScript dokumentua</comment>
- <comment xml:lang="fi">CoffeeScript-asiakirja</comment>
- <comment xml:lang="fr">document CoffeeScript</comment>
- <comment xml:lang="ga">cáipéis CoffeeScript</comment>
- <comment xml:lang="he">מסמך CoffeeScript</comment>
- <comment xml:lang="hr">CoffeeScript dokument</comment>
- <comment xml:lang="hu">CoffeeScript dokumentum</comment>
- <comment xml:lang="ia">Documento CoffeeScript</comment>
- <comment xml:lang="id">Dokumen CoffeeScript</comment>
- <comment xml:lang="it">Documento CoffeeScript</comment>
- <comment xml:lang="kk">CoffeeScript құжаты</comment>
- <comment xml:lang="ko">CoffeeScript 문서</comment>
- <comment xml:lang="oc">Document CoffeScript</comment>
- <comment xml:lang="pl">Dokument CoffeeScript</comment>
- <comment xml:lang="pt">documento CoffeeScript</comment>
- <comment xml:lang="pt_BR">Documento CoffeeScript</comment>
- <comment xml:lang="ru">Документ CoffeeScript</comment>
- <comment xml:lang="sk">Dokument CoffeeScript</comment>
- <comment xml:lang="sr">Кофи скрипт документ</comment>
- <comment xml:lang="sv">CoffeeScript-dokument</comment>
- <comment xml:lang="tr">CoffeeScript belgesi</comment>
- <comment xml:lang="uk">документ CoffeeScript</comment>
- <comment xml:lang="zh_CN">CoffeeScript 文档</comment>
<comment xml:lang="zh_TW">CoffeeScript 文件</comment>
+ <comment xml:lang="zh_CN">CoffeeScript 文档</comment>
+ <comment xml:lang="uk">документ CoffeeScript</comment>
+ <comment xml:lang="tr">CoffeeScript belgesi</comment>
+ <comment xml:lang="sv">CoffeeScript-dokument</comment>
+ <comment xml:lang="sr">Кофи скрипт документ</comment>
+ <comment xml:lang="sq">dokument CoffeeScript</comment>
+ <comment xml:lang="sl">Dokument CoffeeScript</comment>
+ <comment xml:lang="si">CoffeeScript ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument CoffeeScript</comment>
+ <comment xml:lang="ru">Документ CoffeeScript</comment>
+ <comment xml:lang="pt_BR">Documento CoffeeScript</comment>
+ <comment xml:lang="pt">documento CoffeeScript</comment>
+ <comment xml:lang="pl">Dokument CoffeeScript</comment>
+ <comment xml:lang="oc">Document CoffeScript</comment>
+ <comment xml:lang="nl">CoffeeScript-document</comment>
+ <comment xml:lang="ko">CoffeeScript 문서</comment>
+ <comment xml:lang="kk">CoffeeScript құжаты</comment>
+ <comment xml:lang="ja">CoffeeScript ドキュメント</comment>
+ <comment xml:lang="it">Documento CoffeeScript</comment>
+ <comment xml:lang="is">CoffeeScript skjal</comment>
+ <comment xml:lang="id">Dokumen CoffeeScript</comment>
+ <comment xml:lang="ia">Documento CoffeeScript</comment>
+ <comment xml:lang="hu">CoffeeScript dokumentum</comment>
+ <comment xml:lang="hr">CoffeeScript dokument</comment>
+ <comment xml:lang="he">מסמך CoffeeScript</comment>
+ <comment xml:lang="gl">Documento CoffeeScript</comment>
+ <comment xml:lang="ga">cáipéis CoffeeScript</comment>
+ <comment xml:lang="fur">document CoffeeScript</comment>
+ <comment xml:lang="fr">document CoffeeScript</comment>
+ <comment xml:lang="fi">CoffeeScript-asiakirja</comment>
+ <comment xml:lang="eu">CoffeeScript dokumentua</comment>
+ <comment xml:lang="es">documento en CoffeeScript</comment>
+ <comment xml:lang="en_GB">CoffeeScript document</comment>
+ <comment xml:lang="el">Έγγραφο CoffeeScript</comment>
+ <comment xml:lang="de">CoffeeScript-Dokument</comment>
+ <comment xml:lang="da">CoffeeScript-dokument</comment>
+ <comment xml:lang="cs">dokument CoffeeScript</comment>
+ <comment xml:lang="ca">document CoffeeScript</comment>
+ <comment xml:lang="bg">Документ — CoffeeScript</comment>
+ <comment xml:lang="be">дакумент CoffeeScript</comment>
+ <comment xml:lang="ast">Documentu de CoffeScript</comment>
+ <comment xml:lang="ar">مستند CoffeeScript</comment>
+ <comment xml:lang="af">CoffeeScript-dokument</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.coffee"/>
</mime-type>
<mime-type type="application/x-jbuilder-project">
<comment>JBuilder project</comment>
- <comment xml:lang="ar">مشروع JBuilder</comment>
- <comment xml:lang="be@latin">Prajekt JBuilder</comment>
- <comment xml:lang="bg">Проект — JBuilder</comment>
- <comment xml:lang="ca">projecte de JBuilder</comment>
- <comment xml:lang="cs">projekt JBuilder</comment>
- <comment xml:lang="da">JBuilder-projekt</comment>
- <comment xml:lang="de">JBuilder-Projekt</comment>
- <comment xml:lang="el">Εργο JBuilder</comment>
- <comment xml:lang="en_GB">JBuilder project</comment>
- <comment xml:lang="eo">JBuilder-projekto</comment>
- <comment xml:lang="es">proyecto de JBuilder</comment>
- <comment xml:lang="eu">JBuilder proiektua</comment>
- <comment xml:lang="fi">JBuilder-projekti</comment>
- <comment xml:lang="fo">JBuilder verkætlan</comment>
- <comment xml:lang="fr">projet JBuilder</comment>
- <comment xml:lang="ga">tionscadal JBuilder</comment>
- <comment xml:lang="gl">proxecto de JBuilder</comment>
- <comment xml:lang="he">מיזם JBuilder</comment>
- <comment xml:lang="hr">JBuilder projekt</comment>
- <comment xml:lang="hu">JBuilder-projekt</comment>
- <comment xml:lang="ia">Projecto JBuilder</comment>
- <comment xml:lang="id">Proyek JBuilder</comment>
- <comment xml:lang="it">Progetto JBuilder</comment>
- <comment xml:lang="ja">JBuilder プロジェクト</comment>
- <comment xml:lang="kk">JBuilder жобасы</comment>
- <comment xml:lang="ko">JBuilder 프로젝트</comment>
- <comment xml:lang="lt">JBuilder projektas</comment>
- <comment xml:lang="lv">JBuilder projekts</comment>
- <comment xml:lang="ms">Projek JBuilder</comment>
- <comment xml:lang="nb">JBuilder-prosjekt</comment>
- <comment xml:lang="nl">JBuilder-project</comment>
- <comment xml:lang="nn">JBuilder-prosjekt</comment>
- <comment xml:lang="oc">projècte JBuilder</comment>
- <comment xml:lang="pl">Projekt JBuilder</comment>
- <comment xml:lang="pt">projecto JBuilder</comment>
- <comment xml:lang="pt_BR">Projeto do JBuilder</comment>
- <comment xml:lang="ro">Proiect JBuilder</comment>
- <comment xml:lang="ru">Проект JBuilder</comment>
- <comment xml:lang="sk">Projekt JBuilder</comment>
- <comment xml:lang="sl">Datoteka projekta JBuilder</comment>
- <comment xml:lang="sq">Projekt JBuilder</comment>
- <comment xml:lang="sr">пројекат ЈГрадитеља</comment>
- <comment xml:lang="sv">JBuilder-projekt</comment>
- <comment xml:lang="tr">JBuilder projesi</comment>
- <comment xml:lang="uk">проект JBuilder</comment>
- <comment xml:lang="vi">Dự án JBuilder</comment>
- <comment xml:lang="zh_CN">JBuilder 工程</comment>
<comment xml:lang="zh_TW">JBuilder 專案</comment>
+ <comment xml:lang="zh_CN">JBuilder 工程</comment>
+ <comment xml:lang="vi">Dự án JBuilder</comment>
+ <comment xml:lang="uk">проєкт JBuilder</comment>
+ <comment xml:lang="tr">JBuilder projesi</comment>
+ <comment xml:lang="sv">JBuilder-projekt</comment>
+ <comment xml:lang="sr">пројекат ЈГрадитеља</comment>
+ <comment xml:lang="sq">projekt JBuilder</comment>
+ <comment xml:lang="sl">Datoteka projekta JBuilder</comment>
+ <comment xml:lang="si">JBuilder ව්යාපෘතිය</comment>
+ <comment xml:lang="sk">Projekt JBuilder</comment>
+ <comment xml:lang="ru">Проект JBuilder</comment>
+ <comment xml:lang="ro">Proiect JBuilder</comment>
+ <comment xml:lang="pt_BR">Projeto do JBuilder</comment>
+ <comment xml:lang="pt">projecto JBuilder</comment>
+ <comment xml:lang="pl">Projekt JBuilder</comment>
+ <comment xml:lang="oc">projècte JBuilder</comment>
+ <comment xml:lang="nn">JBuilder-prosjekt</comment>
+ <comment xml:lang="nl">JBuilder-project</comment>
+ <comment xml:lang="nb">JBuilder-prosjekt</comment>
+ <comment xml:lang="ms">Projek JBuilder</comment>
+ <comment xml:lang="lv">JBuilder projekts</comment>
+ <comment xml:lang="lt">JBuilder projektas</comment>
+ <comment xml:lang="ko">JBuilder 프로젝트</comment>
+ <comment xml:lang="kk">JBuilder жобасы</comment>
+ <comment xml:lang="ja">JBuilder プロジェクト</comment>
+ <comment xml:lang="it">Progetto JBuilder</comment>
+ <comment xml:lang="is">JBuilder verkefni</comment>
+ <comment xml:lang="id">Proyek JBuilder</comment>
+ <comment xml:lang="ia">Projecto JBuilder</comment>
+ <comment xml:lang="hu">JBuilder-projekt</comment>
+ <comment xml:lang="hr">JBuilder projekt</comment>
+ <comment xml:lang="he">מיזם JBuilder</comment>
+ <comment xml:lang="gl">proxecto de JBuilder</comment>
+ <comment xml:lang="ga">tionscadal JBuilder</comment>
+ <comment xml:lang="fur">progjet JBuilder</comment>
+ <comment xml:lang="fr">projet JBuilder</comment>
+ <comment xml:lang="fo">JBuilder verkætlan</comment>
+ <comment xml:lang="fi">JBuilder-projekti</comment>
+ <comment xml:lang="eu">JBuilder proiektua</comment>
+ <comment xml:lang="es">proyecto de JBuilder</comment>
+ <comment xml:lang="eo">JBuilder-projekto</comment>
+ <comment xml:lang="en_GB">JBuilder project</comment>
+ <comment xml:lang="el">Εργο JBuilder</comment>
+ <comment xml:lang="de">JBuilder-Projekt</comment>
+ <comment xml:lang="da">JBuilder-projekt</comment>
+ <comment xml:lang="cs">projekt JBuilder</comment>
+ <comment xml:lang="ca">projecte de JBuilder</comment>
+ <comment xml:lang="bg">Проект — JBuilder</comment>
+ <comment xml:lang="be@latin">Prajekt JBuilder</comment>
+ <comment xml:lang="be">праект JBuilder</comment>
+ <comment xml:lang="ar">مشروع JBuilder</comment>
+ <comment xml:lang="af">JBuilder-projek</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.jpr"/>
<glob pattern="*.jpx"/>
</mime-type>
<mime-type type="application/x-karbon">
<comment>Karbon14 drawing</comment>
- <comment xml:lang="ar">تصميم Karbon14</comment>
- <comment xml:lang="be@latin">Rysunak Karbon14</comment>
- <comment xml:lang="bg">Чертеж — Karbon14</comment>
- <comment xml:lang="ca">dibuix de Karbon14</comment>
- <comment xml:lang="cs">kresba Karbon14</comment>
- <comment xml:lang="da">Karbon14-tegning</comment>
- <comment xml:lang="de">Karbon14-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Karbon14</comment>
- <comment xml:lang="en_GB">Karbon14 drawing</comment>
- <comment xml:lang="eo">Karbon14-grafikaĵo</comment>
- <comment xml:lang="es">dibujo de Karbon14</comment>
- <comment xml:lang="eu">Karbon14 marrazkia</comment>
- <comment xml:lang="fi">Karbon14-piirros</comment>
- <comment xml:lang="fo">Karbon14 tekning</comment>
- <comment xml:lang="fr">dessin Karbon14</comment>
- <comment xml:lang="ga">líníocht Karbon14</comment>
- <comment xml:lang="gl">debuxo de Karbon14</comment>
- <comment xml:lang="he">ציור Karbon14</comment>
- <comment xml:lang="hr">Karbon14 crtež</comment>
- <comment xml:lang="hu">Karbon14-rajz</comment>
- <comment xml:lang="ia">Designo Karbon14</comment>
- <comment xml:lang="id">Gambar Karbon14</comment>
- <comment xml:lang="it">Disegno Karbon14</comment>
- <comment xml:lang="ja">Karbon14 ドロー</comment>
- <comment xml:lang="kk">Karbon14 суреті</comment>
- <comment xml:lang="ko">Karbon14 그림</comment>
- <comment xml:lang="lt">Karbon14 piešinys</comment>
- <comment xml:lang="lv">Karbon14 zīmējums</comment>
- <comment xml:lang="ms">Lukisan Karbon14</comment>
- <comment xml:lang="nb">Karbon14-tegning</comment>
- <comment xml:lang="nl">Karbon14-tekening</comment>
- <comment xml:lang="nn">Karbon14-teikning</comment>
- <comment xml:lang="oc">dessenh Karbon14</comment>
- <comment xml:lang="pl">Rysunek Karbon14</comment>
- <comment xml:lang="pt">desenho Karbon14</comment>
- <comment xml:lang="pt_BR">Desenho do Karbon14</comment>
- <comment xml:lang="ro">Desen Karbon14</comment>
- <comment xml:lang="ru">Рисунок Karbon14</comment>
- <comment xml:lang="sk">Kresba Karbon14</comment>
- <comment xml:lang="sl">Datoteka risbe Karbon14</comment>
- <comment xml:lang="sq">Vizatim Karbon14</comment>
- <comment xml:lang="sr">цртеж Карбона14</comment>
- <comment xml:lang="sv">Karbon14-teckning</comment>
- <comment xml:lang="tr">Karbon14 çizimi</comment>
- <comment xml:lang="uk">малюнок Karbon14</comment>
- <comment xml:lang="vi">Bản vẽ Karbon14</comment>
- <comment xml:lang="zh_CN">Karbon14 绘图</comment>
<comment xml:lang="zh_TW">Karbon14 繪圖</comment>
+ <comment xml:lang="zh_CN">Karbon14 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ Karbon14</comment>
+ <comment xml:lang="uk">малюнок Karbon14</comment>
+ <comment xml:lang="tr">Karbon14 çizimi</comment>
+ <comment xml:lang="sv">Karbon14-teckning</comment>
+ <comment xml:lang="sr">цртеж Карбона14</comment>
+ <comment xml:lang="sq">vizatim Karbon14</comment>
+ <comment xml:lang="sl">Datoteka risbe Karbon14</comment>
+ <comment xml:lang="si">Karbon14 ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba Karbon14</comment>
+ <comment xml:lang="ru">Рисунок Karbon14</comment>
+ <comment xml:lang="ro">Desen Karbon14</comment>
+ <comment xml:lang="pt_BR">Desenho do Karbon14</comment>
+ <comment xml:lang="pt">desenho Karbon14</comment>
+ <comment xml:lang="pl">Rysunek Karbon14</comment>
+ <comment xml:lang="oc">dessenh Karbon14</comment>
+ <comment xml:lang="nn">Karbon14-teikning</comment>
+ <comment xml:lang="nl">Karbon14-tekening</comment>
+ <comment xml:lang="nb">Karbon14-tegning</comment>
+ <comment xml:lang="ms">Lukisan Karbon14</comment>
+ <comment xml:lang="lv">Karbon14 zīmējums</comment>
+ <comment xml:lang="lt">Karbon14 piešinys</comment>
+ <comment xml:lang="ko">Karbon14 그림</comment>
+ <comment xml:lang="kk">Karbon14 суреті</comment>
+ <comment xml:lang="ja">Karbon14 ドロー</comment>
+ <comment xml:lang="it">Disegno Karbon14</comment>
+ <comment xml:lang="is">Karbon14 Tteikning</comment>
+ <comment xml:lang="id">Gambar Karbon14</comment>
+ <comment xml:lang="ia">Designo Karbon14</comment>
+ <comment xml:lang="hu">Karbon14-rajz</comment>
+ <comment xml:lang="hr">Karbon14 crtež</comment>
+ <comment xml:lang="he">ציור Karbon14</comment>
+ <comment xml:lang="gl">debuxo de Karbon14</comment>
+ <comment xml:lang="ga">líníocht Karbon14</comment>
+ <comment xml:lang="fur">dissen Karbon14</comment>
+ <comment xml:lang="fr">dessin Karbon14</comment>
+ <comment xml:lang="fo">Karbon14 tekning</comment>
+ <comment xml:lang="fi">Karbon14-piirros</comment>
+ <comment xml:lang="eu">Karbon14 marrazkia</comment>
+ <comment xml:lang="es">dibujo de Karbon14</comment>
+ <comment xml:lang="eo">Karbon14-grafikaĵo</comment>
+ <comment xml:lang="en_GB">Karbon14 drawing</comment>
+ <comment xml:lang="el">Σχέδιο Karbon14</comment>
+ <comment xml:lang="de">Karbon14-Zeichnung</comment>
+ <comment xml:lang="da">Karbon14-tegning</comment>
+ <comment xml:lang="cs">kresba Karbon14</comment>
+ <comment xml:lang="ca">dibuix de Karbon14</comment>
+ <comment xml:lang="bg">Чертеж — Karbon14</comment>
+ <comment xml:lang="be@latin">Rysunak Karbon14</comment>
+ <comment xml:lang="be">рысунак Karbon14</comment>
+ <comment xml:lang="ar">تصميم Karbon14</comment>
+ <comment xml:lang="af">Karbon14-tekening</comment>
<generic-icon name="image-x-generic"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-karbon\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-karbon\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-karbon" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-karbon" offset="38"/>
</match>
</match>
</magic>
@@ -13659,313 +14903,296 @@
</mime-type>
<mime-type type="application/x-kchart">
<comment>KChart chart</comment>
- <comment xml:lang="ar">رسم بياني KChart</comment>
- <comment xml:lang="be@latin">Hrafik KChart</comment>
- <comment xml:lang="bg">Диаграма — KChart</comment>
- <comment xml:lang="ca">diagrama de KChart</comment>
- <comment xml:lang="cs">graf Chart</comment>
- <comment xml:lang="da">KChart-diagram</comment>
- <comment xml:lang="de">KChart-Diagramm</comment>
- <comment xml:lang="el">Γράφημα KChart</comment>
- <comment xml:lang="en_GB">KChart chart</comment>
- <comment xml:lang="eo">KChart-diagramo</comment>
- <comment xml:lang="es">gráfico de KChart</comment>
- <comment xml:lang="eu">KChart diagrama</comment>
- <comment xml:lang="fi">KChart-kaavio</comment>
- <comment xml:lang="fo">KChart strikumynd</comment>
- <comment xml:lang="fr">graphique KChart</comment>
- <comment xml:lang="ga">cairt KChart</comment>
- <comment xml:lang="gl">gráfica de KChart</comment>
- <comment xml:lang="he">תרשים KChart</comment>
- <comment xml:lang="hr">KChart grafikon</comment>
- <comment xml:lang="hu">KChart-grafikon</comment>
- <comment xml:lang="ia">Graphico KChart</comment>
- <comment xml:lang="id">Bagan KChart</comment>
- <comment xml:lang="it">Grafico KChart</comment>
- <comment xml:lang="ja">KChart チャート</comment>
- <comment xml:lang="kk">KChart диаграммасы</comment>
- <comment xml:lang="ko">KChart 차트</comment>
- <comment xml:lang="lt">KChart diagrama</comment>
- <comment xml:lang="lv">KChart diagramma</comment>
- <comment xml:lang="ms">Carta KChart</comment>
- <comment xml:lang="nb">KChart-graf</comment>
- <comment xml:lang="nl">KChart-grafiek</comment>
- <comment xml:lang="nn">KChart-diagram</comment>
- <comment xml:lang="oc">grafic KChart</comment>
- <comment xml:lang="pl">Wykres KChart</comment>
- <comment xml:lang="pt">gráfico KChart</comment>
- <comment xml:lang="pt_BR">Gráfico do KChart</comment>
- <comment xml:lang="ro">Diagramă KChart</comment>
- <comment xml:lang="ru">Диаграмма KChart</comment>
- <comment xml:lang="sk">Graf KChart</comment>
- <comment xml:lang="sl">Datoteka grafikona KChart</comment>
- <comment xml:lang="sq">Grafik KChart</comment>
- <comment xml:lang="sr">графикон К-графика</comment>
- <comment xml:lang="sv">KChart-diagram</comment>
- <comment xml:lang="tr">KChart çizgesi</comment>
- <comment xml:lang="uk">діаграма KChart</comment>
- <comment xml:lang="vi">Sơ đồ KChart</comment>
- <comment xml:lang="zh_CN">KChart 图表</comment>
<comment xml:lang="zh_TW">KChart 圖表</comment>
+ <comment xml:lang="zh_CN">KChart 图表</comment>
+ <comment xml:lang="vi">Sơ đồ KChart</comment>
+ <comment xml:lang="uk">діаграма KChart</comment>
+ <comment xml:lang="tr">KChart çizgesi</comment>
+ <comment xml:lang="sv">KChart-diagram</comment>
+ <comment xml:lang="sr">графикон К-графика</comment>
+ <comment xml:lang="sq">grafik KChart</comment>
+ <comment xml:lang="sl">Datoteka grafikona KChart</comment>
+ <comment xml:lang="si">KChart ප්‍රස්ථාරය</comment>
+ <comment xml:lang="sk">Graf KChart</comment>
+ <comment xml:lang="ru">Диаграмма KChart</comment>
+ <comment xml:lang="ro">Diagramă KChart</comment>
+ <comment xml:lang="pt_BR">Gráfico do KChart</comment>
+ <comment xml:lang="pt">gráfico KChart</comment>
+ <comment xml:lang="pl">Wykres KChart</comment>
+ <comment xml:lang="oc">grafic KChart</comment>
+ <comment xml:lang="nn">KChart-diagram</comment>
+ <comment xml:lang="nl">KChart-grafiek</comment>
+ <comment xml:lang="nb">KChart-graf</comment>
+ <comment xml:lang="ms">Carta KChart</comment>
+ <comment xml:lang="lv">KChart diagramma</comment>
+ <comment xml:lang="lt">KChart diagrama</comment>
+ <comment xml:lang="ko">KChart 차트</comment>
+ <comment xml:lang="kk">KChart диаграммасы</comment>
+ <comment xml:lang="ja">KChart チャート</comment>
+ <comment xml:lang="it">Grafico KChart</comment>
+ <comment xml:lang="is">KChart línurit</comment>
+ <comment xml:lang="id">Bagan KChart</comment>
+ <comment xml:lang="ia">Graphico KChart</comment>
+ <comment xml:lang="hu">KChart-grafikon</comment>
+ <comment xml:lang="hr">KChart grafikon</comment>
+ <comment xml:lang="he">תרשים KChart</comment>
+ <comment xml:lang="gl">gráfica de KChart</comment>
+ <comment xml:lang="ga">cairt KChart</comment>
+ <comment xml:lang="fur">grafic KChart</comment>
+ <comment xml:lang="fr">graphique KChart</comment>
+ <comment xml:lang="fo">KChart strikumynd</comment>
+ <comment xml:lang="fi">KChart-kaavio</comment>
+ <comment xml:lang="eu">KChart diagrama</comment>
+ <comment xml:lang="es">gráfico de KChart</comment>
+ <comment xml:lang="eo">KChart-diagramo</comment>
+ <comment xml:lang="en_GB">KChart chart</comment>
+ <comment xml:lang="el">Γράφημα KChart</comment>
+ <comment xml:lang="de">KChart-Diagramm</comment>
+ <comment xml:lang="da">KChart-diagram</comment>
+ <comment xml:lang="cs">graf Chart</comment>
+ <comment xml:lang="ca">diagrama de KChart</comment>
+ <comment xml:lang="bg">Диаграма — KChart</comment>
+ <comment xml:lang="be@latin">Hrafik KChart</comment>
+ <comment xml:lang="be">графік KChart</comment>
+ <comment xml:lang="ar">رسم بياني KChart</comment>
+ <comment xml:lang="af">KChart-grafiek</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kchart\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kchart\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kchart" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kchart" offset="38"/>
</match>
</match>
</magic>
<glob pattern="*.chrt"/>
</mime-type>
<mime-type type="application/x-kexi-connectiondata">
- <comment>Kexi settings for database server connection</comment>
- <comment xml:lang="ar">إعدادات Kexi للإتصال بخادم قاعدة البيانات</comment>
- <comment xml:lang="bg">Връзка към база от данни — Kexi</comment>
- <comment xml:lang="ca">ajusts de Kexi per a la connexió al servidor de bases de dades</comment>
- <comment xml:lang="cs">nastavení Kexi ke spojení s databázovým serverem</comment>
- <comment xml:lang="da">Kexiopsætning til forbindelsen for databaseserveren</comment>
- <comment xml:lang="de">Kexi-Einstellungen für Verbindung zum Datenbankserver</comment>
- <comment xml:lang="el">Ρυθμίσεις Kexi για σύνδεση με εξυπηρετητή βάσεων δεδομένων</comment>
- <comment xml:lang="en_GB">Kexi settings for database server connection</comment>
- <comment xml:lang="es">configuración de Kexi para conectar con un servidor de bases de datos</comment>
- <comment xml:lang="eu">Kexi-ren ezarpenak datu-basearen zerbitzariarekin konektatzeko</comment>
- <comment xml:lang="fi">Kexi-tietokantayhteysasetukset</comment>
- <comment xml:lang="fo">Kexi stillingar fyri dátustovnsambætara sambinding</comment>
- <comment xml:lang="fr">paramètres Kexi pour connexion au serveur de base de données</comment>
- <comment xml:lang="ga">socruithe Kexi do cheangal le freastalaí bunachair sonraí</comment>
- <comment xml:lang="gl">configuración de Kexi para conexión con servidor de base de datos </comment>
- <comment xml:lang="he">הגדרות של Kexi עבור חיבור שרת למסד נתונים</comment>
- <comment xml:lang="hr">Kexi postavke za povezeivanje baza podataka poslužitelja</comment>
- <comment xml:lang="hu">Kexi beállítások adatbáziskiszolgáló-kapcsolathoz</comment>
- <comment xml:lang="ia">Configuration Kexi pro connexion al servitor de base de datos</comment>
- <comment xml:lang="id">Tatanan Kexi bagi koneksi server basis data</comment>
- <comment xml:lang="it">Impostazioni Kexi per connessione a server di database</comment>
- <comment xml:lang="ja">データベースサーバ接続用の Kexi 設定</comment>
- <comment xml:lang="kk">Дерекқор серверге байланыс Kexi баптаулары</comment>
- <comment xml:lang="ko">Kexi 데이터베이스 서버 연결 설정</comment>
- <comment xml:lang="lt">Kexi duomenų bazės ryšio su serveriu parametrai</comment>
- <comment xml:lang="lv">Kexi iestatījumi datubāzes servera savienojumam</comment>
- <comment xml:lang="nl">Kexi instellingen voor database server connectie</comment>
- <comment xml:lang="oc">paramètres Kexi per connexion al servidor de banca de donadas</comment>
- <comment xml:lang="pl">Ustawienia Kexi dla połączenia serwera bazy danych</comment>
- <comment xml:lang="pt">definições Kexi para ligação de servidor de base de dados</comment>
- <comment xml:lang="pt_BR">Configurações do Kexi para conexão a servidor de banco de dados</comment>
- <comment xml:lang="ro">Configurări Kexi pentru conexiunea la serverul de baze de date</comment>
- <comment xml:lang="ru">Параметры Kexi для подключения к серверу БД</comment>
- <comment xml:lang="sk">Nastavenia Kexi pre pripojenie k databázovému serveru</comment>
- <comment xml:lang="sl">Strežniška povezava do nastavitvene datoteke Kexi.</comment>
- <comment xml:lang="sr">подешавања Кексија за везу са сервером базе података</comment>
- <comment xml:lang="sv">Kexi-inställningar för anslutning till databasserver</comment>
- <comment xml:lang="tr">Veritabanı sunucu bağlantısı için Kexi ayarları</comment>
- <comment xml:lang="uk">параметри Kexi для встановлення з’єднання з сервером бази даних</comment>
- <comment xml:lang="zh_CN">Kexi 数据库服务器连接设置</comment>
- <comment xml:lang="zh_TW">Kexi 設定值 (資料庫伺服器連線用)</comment>
+ <comment>Kexi settings</comment>
+ <comment xml:lang="zh_TW">Kexi 設定</comment>
+ <comment xml:lang="zh_CN">Kexi 设置</comment>
+ <comment xml:lang="uk">параметри Kexi</comment>
+ <comment xml:lang="tr">Kexi ayarları</comment>
+ <comment xml:lang="sv">Kexi-inställningar</comment>
+ <comment xml:lang="sq">rregullime Kexi</comment>
+ <comment xml:lang="sl">Nastavitve Kexi</comment>
+ <comment xml:lang="si">Kexi සැකසුම්</comment>
+ <comment xml:lang="sk">Nastavenia Kexi</comment>
+ <comment xml:lang="ru">Файл настроек Kexi</comment>
+ <comment xml:lang="pt_BR">Configurações do Kexi</comment>
+ <comment xml:lang="pl">Ustawienia Kexi</comment>
+ <comment xml:lang="oc">paramètres Kexi</comment>
+ <comment xml:lang="nl">Kexi-instellingen</comment>
+ <comment xml:lang="ko">Kexi 설정</comment>
+ <comment xml:lang="kk">Kexi баптаулары</comment>
+ <comment xml:lang="ja">Kexi 設定</comment>
+ <comment xml:lang="it">Impostazioni Kexi</comment>
+ <comment xml:lang="is">Kexi stillingar</comment>
+ <comment xml:lang="id">Pengaturan Kexi</comment>
+ <comment xml:lang="hu">Kexi beállítások</comment>
+ <comment xml:lang="hr">Kexi postavke</comment>
+ <comment xml:lang="he">הגדרות Kexi</comment>
+ <comment xml:lang="gl">Preferencias de Kexi</comment>
+ <comment xml:lang="fr">réglages Kexi</comment>
+ <comment xml:lang="fi">Kexi-asetukset</comment>
+ <comment xml:lang="eu">Kexi ezarpenak</comment>
+ <comment xml:lang="es">configuración de Kexi</comment>
+ <comment xml:lang="en_GB">Kexi settings</comment>
+ <comment xml:lang="de">Kexi-Einstellungen</comment>
+ <comment xml:lang="da">Kexi-indstillinger</comment>
+ <comment xml:lang="ca">ajusts de Kexi</comment>
+ <comment xml:lang="bg">Настройки — Kexi</comment>
+ <comment xml:lang="be">налады Kexi</comment>
+ <comment xml:lang="ar">إعدادات Kexi</comment>
<glob pattern="*.kexic"/>
</mime-type>
<mime-type type="application/x-kexiproject-shortcut">
- <comment>shortcut to Kexi project on database server</comment>
- <comment xml:lang="ar">اختصار لمشروع Kexi على خادم قاعدة بيانات</comment>
- <comment xml:lang="bg">Връзка към проект — Kexi</comment>
- <comment xml:lang="ca">drecera al projecte de Kexi en un servidor de base de dades</comment>
- <comment xml:lang="cs">zástupce projektu Kexi na databázovém serveru</comment>
- <comment xml:lang="da">genvej til Kexiprojekt på databaseserver</comment>
- <comment xml:lang="de">Schnellzugriff zum Kexi-Projekt auf dem Datenbankserver</comment>
- <comment xml:lang="el">Συντόμευση σε έργο Kexi στον εξυπηρετητή βάσης δεδομένων</comment>
- <comment xml:lang="en_GB">shortcut to Kexi project on database server</comment>
- <comment xml:lang="es">acceso directo a proyecto Kexi en el servidor de bases de datos</comment>
- <comment xml:lang="eu">lasterbidea datu-basearen zerbitzariko Kexi proiekturako</comment>
- <comment xml:lang="fi">pikakuvake tietokantapalvelimella olevaan Kexi-projektiin</comment>
- <comment xml:lang="fo">snarvegur til Kexi verkætlan á dátustovnsambætara</comment>
- <comment xml:lang="fr">raccourci vers projet Kexi sur serveur de base de données</comment>
- <comment xml:lang="ga">aicearra go tionscadal Kexi ar fhreastalaí bunachair sonraí</comment>
- <comment xml:lang="gl">acceso directo a proxecto Kexi no servidor de bases de datos</comment>
- <comment xml:lang="he">קיצור דרך לפרוירט Kexi בשרת נתונים</comment>
- <comment xml:lang="hr">Prečac do Kexi projekta na poslužitelju baze podataka</comment>
- <comment xml:lang="hu">indítóikon adatbázis-kiszolgálón lévő Kexi projektre</comment>
- <comment xml:lang="ia">Ligamine a projecto Kexi in servitor de base de datos</comment>
- <comment xml:lang="id">pintasan ke projek Kexi pada server basis data</comment>
- <comment xml:lang="it">Scorciatoia a progetto Kexi su server di database</comment>
- <comment xml:lang="ja">データベースサーバの Kexi プロジェクトへのショートカット</comment>
- <comment xml:lang="kk">дерекқор серверіндегі Kexi жобасына сілтеме</comment>
- <comment xml:lang="ko">데이터베이스 서버의 Kexi 프로젝트 바로 가기</comment>
- <comment xml:lang="lt">nuoroda į Kexi projektą duomenų bazės serveryje</comment>
- <comment xml:lang="lv">īsceļš uz Kexi projektu datubāzes serverī</comment>
- <comment xml:lang="nl">shortcut naar Kexi project op database server</comment>
- <comment xml:lang="oc">acorchi cap a projècte Kexi sus servidor de banca de donadas</comment>
- <comment xml:lang="pl">Skrót do projektu Kexi na serwerze bazy danych</comment>
- <comment xml:lang="pt">atalho para projeto Kexi em servidor de base de dados</comment>
- <comment xml:lang="pt_BR">Atalho para projeto Kexi no servidor de banco de dados</comment>
- <comment xml:lang="ro">scurtătură către un proiect Kexi pe un server de baze de date</comment>
- <comment xml:lang="ru">Ссылка на проект Kexi на сервере БД</comment>
- <comment xml:lang="sk">Zástupca projektu Kexi na databázovom serveri</comment>
- <comment xml:lang="sl">bližnjica do Kexi projekta na podatkovnem strežniku</comment>
- <comment xml:lang="sr">пречица до пројекта Кексија на серверу базе података</comment>
- <comment xml:lang="sv">genväg till Kexi-projekt på databasserver</comment>
- <comment xml:lang="tr">veritabanı üzerindeki Kexi projesine kısayol</comment>
- <comment xml:lang="uk">скорочення для проекту Kexi на сервері бази даних</comment>
- <comment xml:lang="zh_CN">数据库服务器上 Kexi 项目的快捷方式</comment>
- <comment xml:lang="zh_TW">資料庫伺服器上 Kexi 專案的捷徑</comment>
+ <comment>Kexi shortcut</comment>
+ <comment xml:lang="zh_TW">Kexi 捷徑</comment>
+ <comment xml:lang="zh_CN">Kexi 快捷方式</comment>
+ <comment xml:lang="uk">скорочення Kexi</comment>
+ <comment xml:lang="tr">Kexi kısayolu</comment>
+ <comment xml:lang="sv">Kexi-genväg</comment>
+ <comment xml:lang="sq">shkurtore Kexi</comment>
+ <comment xml:lang="sl">Bližnjica Kexi</comment>
+ <comment xml:lang="si">Kexi කෙටිමඟ</comment>
+ <comment xml:lang="sk">Odkaz Kexi</comment>
+ <comment xml:lang="ru">Ссылка Kexi</comment>
+ <comment xml:lang="pt_BR">Atalho do Kexi</comment>
+ <comment xml:lang="pl">Skrót Kexi</comment>
+ <comment xml:lang="nl">Kexi-snelkoppeling</comment>
+ <comment xml:lang="ko">Kexi 바로 가기</comment>
+ <comment xml:lang="kk">Kexi жарлығы</comment>
+ <comment xml:lang="ja">Kexi ショートカット</comment>
+ <comment xml:lang="it">Scorciatoia Kexi</comment>
+ <comment xml:lang="is">Kexi fýtileið</comment>
+ <comment xml:lang="id">Pintasan Kexi</comment>
+ <comment xml:lang="hu">Kexi parancsiko</comment>
+ <comment xml:lang="hr">Kexi prečac</comment>
+ <comment xml:lang="he">קיצור דרך של Kexi</comment>
+ <comment xml:lang="gl">Atallo de Kexi</comment>
+ <comment xml:lang="fr">raccourci Kexi</comment>
+ <comment xml:lang="fi">Kexi-pikakuvake</comment>
+ <comment xml:lang="eu">Kexi lasterbidea</comment>
+ <comment xml:lang="es">atajo de Kexi</comment>
+ <comment xml:lang="en_GB">Kexi shortcut</comment>
+ <comment xml:lang="de">Kexi-Verweis</comment>
+ <comment xml:lang="da">Kexi-genvej</comment>
+ <comment xml:lang="ca">drecera de Kexi</comment>
+ <comment xml:lang="bg">Ускорител — Kexi</comment>
+ <comment xml:lang="be">ярлык Kexi</comment>
+ <comment xml:lang="ar">اختصار Kexi</comment>
<glob pattern="*.kexis"/>
</mime-type>
<mime-type type="application/x-kexiproject-sqlite2">
- <comment>Kexi database file-based project</comment>
- <comment xml:lang="ar">مشروع قاعدة بيانات Kexi يعتمد على ملفات</comment>
- <comment xml:lang="bg">Проект с база от данни — Kexi</comment>
- <comment xml:lang="ca">projecte basat en fitxer de base de dades de Kexi</comment>
- <comment xml:lang="cs">projekt založený na souboru databáze Kexi</comment>
- <comment xml:lang="da">Filbaseret projekt for Kexidatabase</comment>
- <comment xml:lang="de">Dateibasiertes Kexi-Datenbankprojekt</comment>
- <comment xml:lang="el">Έργο βάσης δεδομένων Kexi βασισμένο σε αρχεία </comment>
- <comment xml:lang="en_GB">Kexi database file-based project</comment>
- <comment xml:lang="es">proyecto de base de datos basada en archivos de Kexi</comment>
- <comment xml:lang="eu">Kexi datu-baseko fitxategian oinarritutako proiektua</comment>
- <comment xml:lang="fi">Kexin tiedostoperustainen tietokantaprojekti</comment>
- <comment xml:lang="fo">Kexi dátustovns fílugrundað verkætlan</comment>
- <comment xml:lang="fr">projet de base de données Kexi en mode fichier</comment>
- <comment xml:lang="ga">tionscadal bunachair sonraí Kexi bunaithe ar chomhaid</comment>
- <comment xml:lang="gl">proxecto baseado no ficheiro-base de datos Kexi</comment>
- <comment xml:lang="he">מיזם מסד נתונים מבוסס-קובץ של Kexi</comment>
- <comment xml:lang="hr">Kexi baza podataka datotekom temeljen projekt</comment>
- <comment xml:lang="hu">Kexi adatbázisfájl-alapú projekt</comment>
- <comment xml:lang="ia">Projecto de base de datos Kexi in modo file</comment>
- <comment xml:lang="id">Projek berbasis berkas basis data Kexi</comment>
- <comment xml:lang="it">Progetto su file di database Kexi</comment>
- <comment xml:lang="ja">Kexi データベース ファイルベースプロジェクト</comment>
- <comment xml:lang="kk">Файл негізінде жоба үшін Kexi дерекқоры</comment>
- <comment xml:lang="ko">Kexi 데이터베이스 파일 기반 프로젝트</comment>
- <comment xml:lang="lt">Kexi duomenų bazės failo tipo projektas</comment>
- <comment xml:lang="lv">Kexi datubāzes datnes balstīts projekts</comment>
- <comment xml:lang="nl">Kexi database bestandgebaseerd project</comment>
- <comment xml:lang="oc">projècte de banca de donadas Kexi en mòde fichièr</comment>
- <comment xml:lang="pl">Projekt bazy danych Kexi na podstawie plików</comment>
- <comment xml:lang="pt">projeto Kexi em base de dados baseada em ficheiros</comment>
- <comment xml:lang="pt_BR">Projeto de banco de dados baseado em arquivo do Kexi</comment>
- <comment xml:lang="ro">Proiect bazat pe fișiere al bazei de date Kexi</comment>
- <comment xml:lang="ru">Файловый проект базы данных Kexi</comment>
- <comment xml:lang="sk">Projekt databázy Kexi s úložiskom typu súbor</comment>
- <comment xml:lang="sl">Datoteka projekta podatkovne zbirke Kexi</comment>
- <comment xml:lang="sr">пројекат Кексијеве базе података на основу датотеке</comment>
- <comment xml:lang="sv">Kexi-databas för filbaserat projekt</comment>
- <comment xml:lang="tr">Dosya temelli Kexi veritabanı projesi</comment>
- <comment xml:lang="uk">проект файлової бази даних Kexi</comment>
- <comment xml:lang="zh_CN">Kexi 基于文件的数据库项目</comment>
- <comment xml:lang="zh_TW">Kexi 資料庫檔案基礎專案</comment>
+ <comment>Kexi database file</comment>
+ <comment xml:lang="zh_TW">Kexi 資料庫檔案</comment>
+ <comment xml:lang="zh_CN">Kexi 数据库文件</comment>
+ <comment xml:lang="uk">файл бази даних Kexi</comment>
+ <comment xml:lang="tr">Kexi veri tabanı dosyası</comment>
+ <comment xml:lang="sv">Kexi-databasfil</comment>
+ <comment xml:lang="sq">kartelë baze të dhënash Kexi</comment>
+ <comment xml:lang="sl">Datoteka zbirke podatkov Kexi</comment>
+ <comment xml:lang="si">Kexi දත්ත සමුදා ගොනුව</comment>
+ <comment xml:lang="sk">Súbor databázy Kexi</comment>
+ <comment xml:lang="ru">Файл базы данных Kexi</comment>
+ <comment xml:lang="pt_BR">Arquivo de banco de dados do Kexi</comment>
+ <comment xml:lang="pl">Plik bazy danych Kexi</comment>
+ <comment xml:lang="nl">Kexi-databasebestand</comment>
+ <comment xml:lang="ko">Kexi 데이터베이스 파일</comment>
+ <comment xml:lang="kk">Kexi дерекқор файлы</comment>
+ <comment xml:lang="ja">Kexi データベースファイル</comment>
+ <comment xml:lang="it">File database Kexi</comment>
+ <comment xml:lang="is">Kexi gagnagrunnsskrá</comment>
+ <comment xml:lang="id">Berkas basis data Kexi</comment>
+ <comment xml:lang="hu">Kexi adatbázisfájl</comment>
+ <comment xml:lang="hr">Kexi datoteka baze podataka</comment>
+ <comment xml:lang="he">קובץ מסד נתונים של Kexi</comment>
+ <comment xml:lang="gl">Ficheiro de base de datos Kexi</comment>
+ <comment xml:lang="fr">fichier de base de données Kexi</comment>
+ <comment xml:lang="fi">Kexi-tietokanta</comment>
+ <comment xml:lang="eu">Kexi datu-base fitxategia</comment>
+ <comment xml:lang="es">archivo de base de datos de Kexi</comment>
+ <comment xml:lang="en_GB">Kexi database file</comment>
+ <comment xml:lang="de">Kexi-Datenbankdatei</comment>
+ <comment xml:lang="da">Kexi database-fil</comment>
+ <comment xml:lang="ca">fitxer de base de dades de Kexi</comment>
+ <comment xml:lang="bg">База от данни — Kexi</comment>
+ <comment xml:lang="be">база даных Kexi</comment>
+ <comment xml:lang="ar">ملف قاعدة Kexi</comment>
<sub-class-of type="application/x-sqlite2"/>
<glob pattern="*.kexi"/>
</mime-type>
<mime-type type="application/x-kexiproject-sqlite3">
- <comment>Kexi database file-based project</comment>
- <comment xml:lang="ar">مشروع قاعدة بيانات Kexi يعتمد على ملفات</comment>
- <comment xml:lang="bg">Проект с база от данни — Kexi</comment>
- <comment xml:lang="ca">projecte basat en fitxer de base de dades de Kexi</comment>
- <comment xml:lang="cs">projekt založený na souboru databáze Kexi</comment>
- <comment xml:lang="da">Filbaseret projekt for Kexidatabase</comment>
- <comment xml:lang="de">Dateibasiertes Kexi-Datenbankprojekt</comment>
- <comment xml:lang="el">Έργο βάσης δεδομένων Kexi βασισμένο σε αρχεία </comment>
- <comment xml:lang="en_GB">Kexi database file-based project</comment>
- <comment xml:lang="es">proyecto de base de datos basada en archivos de Kexi</comment>
- <comment xml:lang="eu">Kexi datu-baseko fitxategian oinarritutako proiektua</comment>
- <comment xml:lang="fi">Kexin tiedostoperustainen tietokantaprojekti</comment>
- <comment xml:lang="fo">Kexi dátustovns fílugrundað verkætlan</comment>
- <comment xml:lang="fr">projet de base de données Kexi en mode fichier</comment>
- <comment xml:lang="ga">tionscadal bunachair sonraí Kexi bunaithe ar chomhaid</comment>
- <comment xml:lang="gl">proxecto baseado no ficheiro-base de datos Kexi</comment>
- <comment xml:lang="he">מיזם מסד נתונים מבוסס-קובץ של Kexi</comment>
- <comment xml:lang="hr">Kexi baza podataka datotekom temeljen projekt</comment>
- <comment xml:lang="hu">Kexi adatbázisfájl-alapú projekt</comment>
- <comment xml:lang="ia">Projecto de base de datos Kexi in modo file</comment>
- <comment xml:lang="id">Projek berbasis berkas basis data Kexi</comment>
- <comment xml:lang="it">Progetto su file di database Kexi</comment>
- <comment xml:lang="ja">Kexi データベース ファイルベースプロジェクト</comment>
- <comment xml:lang="kk">Файл негізінде жоба үшін Kexi дерекқоры</comment>
- <comment xml:lang="ko">Kexi 데이터베이스 파일 기반 프로젝트</comment>
- <comment xml:lang="lt">Kexi duomenų bazės failo tipo projektas</comment>
- <comment xml:lang="lv">Kexi datubāzes datnes balstīts projekts</comment>
- <comment xml:lang="nl">Kexi database bestandgebaseerd project</comment>
- <comment xml:lang="oc">projècte de banca de donadas Kexi en mòde fichièr</comment>
- <comment xml:lang="pl">Projekt bazy danych Kexi na podstawie plików</comment>
- <comment xml:lang="pt">projeto Kexi em base de dados baseada em ficheiros</comment>
- <comment xml:lang="pt_BR">Projeto de banco de dados baseado em arquivo do Kexi</comment>
- <comment xml:lang="ro">Proiect bazat pe fișiere al bazei de date Kexi</comment>
- <comment xml:lang="ru">Файловый проект базы данных Kexi</comment>
- <comment xml:lang="sk">Projekt databázy Kexi s úložiskom typu súbor</comment>
- <comment xml:lang="sl">Datoteka projekta podatkovne zbirke Kexi</comment>
- <comment xml:lang="sr">пројекат Кексијеве базе података на основу датотеке</comment>
- <comment xml:lang="sv">Kexi-databas för filbaserat projekt</comment>
- <comment xml:lang="tr">Dosya temelli Kexi veritabanı projesi</comment>
- <comment xml:lang="uk">проект файлової бази даних Kexi</comment>
- <comment xml:lang="zh_CN">Kexi 基于文件的数据库项目</comment>
- <comment xml:lang="zh_TW">Kexi 資料庫檔案基礎專案</comment>
- <sub-class-of type="application/x-sqlite3"/>
+ <comment>Kexi database file</comment>
+ <comment xml:lang="zh_TW">Kexi 資料庫檔案</comment>
+ <comment xml:lang="zh_CN">Kexi 数据库文件</comment>
+ <comment xml:lang="uk">файл бази даних Kexi</comment>
+ <comment xml:lang="tr">Kexi veri tabanı dosyası</comment>
+ <comment xml:lang="sv">Kexi-databasfil</comment>
+ <comment xml:lang="sq">kartelë baze të dhënash Kexi</comment>
+ <comment xml:lang="sl">Datoteka zbirke podatkov Kexi</comment>
+ <comment xml:lang="si">Kexi දත්ත සමුදා ගොනුව</comment>
+ <comment xml:lang="sk">Súbor databázy Kexi</comment>
+ <comment xml:lang="ru">Файл базы данных Kexi</comment>
+ <comment xml:lang="pt_BR">Arquivo de banco de dados do Kexi</comment>
+ <comment xml:lang="pl">Plik bazy danych Kexi</comment>
+ <comment xml:lang="nl">Kexi-databasebestand</comment>
+ <comment xml:lang="ko">Kexi 데이터베이스 파일</comment>
+ <comment xml:lang="kk">Kexi дерекқор файлы</comment>
+ <comment xml:lang="ja">Kexi データベースファイル</comment>
+ <comment xml:lang="it">File database Kexi</comment>
+ <comment xml:lang="is">Kexi gagnagrunnsskrá</comment>
+ <comment xml:lang="id">Berkas basis data Kexi</comment>
+ <comment xml:lang="hu">Kexi adatbázisfájl</comment>
+ <comment xml:lang="hr">Kexi datoteka baze podataka</comment>
+ <comment xml:lang="he">קובץ מסד נתונים של Kexi</comment>
+ <comment xml:lang="gl">Ficheiro de base de datos Kexi</comment>
+ <comment xml:lang="fr">fichier de base de données Kexi</comment>
+ <comment xml:lang="fi">Kexi-tietokanta</comment>
+ <comment xml:lang="eu">Kexi datu-base fitxategia</comment>
+ <comment xml:lang="es">archivo de base de datos de Kexi</comment>
+ <comment xml:lang="en_GB">Kexi database file</comment>
+ <comment xml:lang="de">Kexi-Datenbankdatei</comment>
+ <comment xml:lang="da">Kexi database-fil</comment>
+ <comment xml:lang="ca">fitxer de base de dades de Kexi</comment>
+ <comment xml:lang="bg">База от данни — Kexi</comment>
+ <comment xml:lang="be">база даных Kexi</comment>
+ <comment xml:lang="ar">ملف قاعدة Kexi</comment>
+ <sub-class-of type="application/vnd.sqlite3"/>
<glob pattern="*.kexi"/>
<alias type="application/x-vnd.kde.kexi"/>
<alias type="application/x-kexiproject-sqlite"/>
</mime-type>
<mime-type type="application/x-kformula">
<comment>KFormula formula</comment>
- <comment xml:lang="ar">صيغة KFormula</comment>
- <comment xml:lang="be@latin">Formuła KFormula</comment>
- <comment xml:lang="bg">Формула — KFormula</comment>
- <comment xml:lang="ca">fórmula de KFormula</comment>
- <comment xml:lang="cs">vzorec KFormula</comment>
- <comment xml:lang="da">KFormula-formel</comment>
- <comment xml:lang="de">KFormula-Formel</comment>
- <comment xml:lang="el">Μαθηματικός τύπος KFormula</comment>
- <comment xml:lang="en_GB">KFormula formula</comment>
- <comment xml:lang="eo">KFormula-formulo</comment>
- <comment xml:lang="es">fórmula de KFormula</comment>
- <comment xml:lang="eu">KFormula formula</comment>
- <comment xml:lang="fi">KFormula-kaava</comment>
- <comment xml:lang="fo">KFormula frymil</comment>
- <comment xml:lang="fr">formule KFormula</comment>
- <comment xml:lang="ga">foirmle KFormula</comment>
- <comment xml:lang="gl">fórmula de KFormula</comment>
- <comment xml:lang="he">נוסחת KFormula</comment>
- <comment xml:lang="hr">KFormula formula</comment>
- <comment xml:lang="hu">KFormula-képlet</comment>
- <comment xml:lang="ia">Formula KFormula</comment>
- <comment xml:lang="id">Formula KFormula</comment>
- <comment xml:lang="it">Formula KFormula</comment>
- <comment xml:lang="ja">KFormula 計算式</comment>
- <comment xml:lang="kk">KFormula формуласы</comment>
- <comment xml:lang="ko">KFormula 수식</comment>
- <comment xml:lang="lt">KFormula formulė</comment>
- <comment xml:lang="lv">KFormula formula</comment>
- <comment xml:lang="ms">Formula KFormula</comment>
- <comment xml:lang="nb">KFormula-formel</comment>
- <comment xml:lang="nl">KFormula-formule</comment>
- <comment xml:lang="nn">KFormula-formel</comment>
- <comment xml:lang="oc">formula KFormula</comment>
- <comment xml:lang="pl">Formuła KFormula</comment>
- <comment xml:lang="pt">fórmula KFormula</comment>
- <comment xml:lang="pt_BR">Fórmula do KFormula</comment>
- <comment xml:lang="ro">Formulă KFormula</comment>
- <comment xml:lang="ru">Формула KFormula</comment>
- <comment xml:lang="sk">Vzorec KFormula</comment>
- <comment xml:lang="sl">Datoteka formule KFormula</comment>
- <comment xml:lang="sq">Formulë KFormula</comment>
- <comment xml:lang="sr">формула К-формуле</comment>
- <comment xml:lang="sv">KFormula-formel</comment>
- <comment xml:lang="tr">KFormula formülü</comment>
- <comment xml:lang="uk">формула KFormula</comment>
- <comment xml:lang="vi">Công thức KFormula</comment>
- <comment xml:lang="zh_CN">KFormula 公式</comment>
<comment xml:lang="zh_TW">KFormula 公式</comment>
+ <comment xml:lang="zh_CN">KFormula 公式</comment>
+ <comment xml:lang="vi">Công thức KFormula</comment>
+ <comment xml:lang="uk">формула KFormula</comment>
+ <comment xml:lang="tr">KFormula formülü</comment>
+ <comment xml:lang="sv">KFormula-formel</comment>
+ <comment xml:lang="sr">формула К-формуле</comment>
+ <comment xml:lang="sq">formulë KFormula</comment>
+ <comment xml:lang="sl">Datoteka formule KFormula</comment>
+ <comment xml:lang="si">KFormula සූත්‍රය</comment>
+ <comment xml:lang="sk">Vzorec KFormula</comment>
+ <comment xml:lang="ru">Формула KFormula</comment>
+ <comment xml:lang="ro">Formulă KFormula</comment>
+ <comment xml:lang="pt_BR">Fórmula do KFormula</comment>
+ <comment xml:lang="pt">fórmula KFormula</comment>
+ <comment xml:lang="pl">Formuła KFormula</comment>
+ <comment xml:lang="oc">formula KFormula</comment>
+ <comment xml:lang="nn">KFormula-formel</comment>
+ <comment xml:lang="nl">KFormula-formule</comment>
+ <comment xml:lang="nb">KFormula-formel</comment>
+ <comment xml:lang="ms">Formula KFormula</comment>
+ <comment xml:lang="lv">KFormula formula</comment>
+ <comment xml:lang="lt">KFormula formulė</comment>
+ <comment xml:lang="ko">KFormula 수식</comment>
+ <comment xml:lang="kk">KFormula формуласы</comment>
+ <comment xml:lang="ja">KFormula 計算式</comment>
+ <comment xml:lang="it">Formula KFormula</comment>
+ <comment xml:lang="is">KFormula formúla</comment>
+ <comment xml:lang="id">Formula KFormula</comment>
+ <comment xml:lang="ia">Formula KFormula</comment>
+ <comment xml:lang="hu">KFormula-képlet</comment>
+ <comment xml:lang="hr">KFormula formula</comment>
+ <comment xml:lang="he">נוסחת KFormula</comment>
+ <comment xml:lang="gl">fórmula de KFormula</comment>
+ <comment xml:lang="ga">foirmle KFormula</comment>
+ <comment xml:lang="fur">formule KFormula</comment>
+ <comment xml:lang="fr">formule KFormula</comment>
+ <comment xml:lang="fo">KFormula frymil</comment>
+ <comment xml:lang="fi">KFormula-kaava</comment>
+ <comment xml:lang="eu">KFormula formula</comment>
+ <comment xml:lang="es">fórmula de KFormula</comment>
+ <comment xml:lang="eo">KFormula-formulo</comment>
+ <comment xml:lang="en_GB">KFormula formula</comment>
+ <comment xml:lang="el">Μαθηματικός τύπος KFormula</comment>
+ <comment xml:lang="de">KFormula-Formel</comment>
+ <comment xml:lang="da">KFormula-formel</comment>
+ <comment xml:lang="cs">vzorec KFormula</comment>
+ <comment xml:lang="ca">fórmula de KFormula</comment>
+ <comment xml:lang="bg">Формула — KFormula</comment>
+ <comment xml:lang="be@latin">Formuła KFormula</comment>
+ <comment xml:lang="be">формула KFormula</comment>
+ <comment xml:lang="ar">صيغة KFormula</comment>
+ <comment xml:lang="af">KFormula-formule</comment>
<generic-icon name="x-office-document"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kformula\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kformula\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kformula" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kformula" offset="38"/>
</match>
</match>
</magic>
@@ -13973,59 +15200,64 @@
</mime-type>
<mime-type type="application/x-killustrator">
<comment>KIllustrator drawing</comment>
- <comment xml:lang="ar">تصميم KIllustrator</comment>
- <comment xml:lang="be@latin">Rysunak KIllustrator</comment>
- <comment xml:lang="bg">Чертеж — KIllustrator</comment>
- <comment xml:lang="ca">dibuix de KIllustrator</comment>
- <comment xml:lang="cs">kresba KIllustrator</comment>
- <comment xml:lang="da">KIllustrator-tegning</comment>
- <comment xml:lang="de">KIllustrator-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο KIllustrator</comment>
- <comment xml:lang="en_GB">KIllustrator drawing</comment>
- <comment xml:lang="eo">KIllustrator-grafikaĵo</comment>
- <comment xml:lang="es">dibujo de KIllustrator</comment>
- <comment xml:lang="eu">KIllustrator marrazkia</comment>
- <comment xml:lang="fi">KIllustrator-piirros</comment>
- <comment xml:lang="fo">KIllustrator tekning</comment>
- <comment xml:lang="fr">dessin KIllustrator</comment>
- <comment xml:lang="ga">líníocht KIllustrator</comment>
- <comment xml:lang="gl">debuxo de KIllustrator</comment>
- <comment xml:lang="he">ציור KIllustrator</comment>
- <comment xml:lang="hr">KIllustrator crtež</comment>
- <comment xml:lang="hu">KIllustrator-rajz</comment>
- <comment xml:lang="ia">Designo KIllustrator</comment>
- <comment xml:lang="id">Gambar KIllustrator</comment>
- <comment xml:lang="it">Disegno KIllustrator</comment>
- <comment xml:lang="ja">KIllustrator ドロー</comment>
- <comment xml:lang="kk">KIllustrator суреті</comment>
- <comment xml:lang="ko">KIllustrator 그림</comment>
- <comment xml:lang="lt">KIllustrator piešinys</comment>
- <comment xml:lang="lv">KIllustrator zīmējums</comment>
- <comment xml:lang="ms">Lukisan KIllustrator</comment>
- <comment xml:lang="nb">KIllustrator-tegning</comment>
- <comment xml:lang="nl">KIllustrator-tekening</comment>
- <comment xml:lang="nn">KIllustrator-teikning</comment>
- <comment xml:lang="oc">dessenh KIllustrator</comment>
- <comment xml:lang="pl">Rysunek KIllustrator</comment>
- <comment xml:lang="pt">desenho KIllustrator</comment>
- <comment xml:lang="pt_BR">Desenho do KIllustrator</comment>
- <comment xml:lang="ro">Desen KIllustrator</comment>
- <comment xml:lang="ru">Рисунок KIllustrator</comment>
- <comment xml:lang="sk">Kresba KIllustrator</comment>
- <comment xml:lang="sl">Datoteka risbe KIllustrator</comment>
- <comment xml:lang="sq">Vizatim KIllustrator</comment>
- <comment xml:lang="sr">цртеж К-илустратора</comment>
- <comment xml:lang="sv">KIllustrator-teckning</comment>
- <comment xml:lang="tr">KIllustrator çizimi</comment>
- <comment xml:lang="uk">малюнок KIllustrator</comment>
- <comment xml:lang="vi">Bản vẽ KIllustrator</comment>
- <comment xml:lang="zh_CN">KIllustrator 绘图</comment>
<comment xml:lang="zh_TW">KIllustrator 繪圖</comment>
+ <comment xml:lang="zh_CN">KIllustrator 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ KIllustrator</comment>
+ <comment xml:lang="uk">малюнок KIllustrator</comment>
+ <comment xml:lang="tr">KIllustrator çizimi</comment>
+ <comment xml:lang="sv">KIllustrator-teckning</comment>
+ <comment xml:lang="sr">цртеж К-илустратора</comment>
+ <comment xml:lang="sq">vizatim KIllustrator</comment>
+ <comment xml:lang="sl">Datoteka risbe KIllustrator</comment>
+ <comment xml:lang="si">කිලිස්ට්රේටර් ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba KIllustrator</comment>
+ <comment xml:lang="ru">Рисунок KIllustrator</comment>
+ <comment xml:lang="ro">Desen KIllustrator</comment>
+ <comment xml:lang="pt_BR">Desenho do KIllustrator</comment>
+ <comment xml:lang="pt">desenho KIllustrator</comment>
+ <comment xml:lang="pl">Rysunek KIllustrator</comment>
+ <comment xml:lang="oc">dessenh KIllustrator</comment>
+ <comment xml:lang="nn">KIllustrator-teikning</comment>
+ <comment xml:lang="nl">KIllustrator-tekening</comment>
+ <comment xml:lang="nb">KIllustrator-tegning</comment>
+ <comment xml:lang="ms">Lukisan KIllustrator</comment>
+ <comment xml:lang="lv">KIllustrator zīmējums</comment>
+ <comment xml:lang="lt">KIllustrator piešinys</comment>
+ <comment xml:lang="ko">KIllustrator 그림</comment>
+ <comment xml:lang="kk">KIllustrator суреті</comment>
+ <comment xml:lang="ja">KIllustrator ドロー</comment>
+ <comment xml:lang="it">Disegno KIllustrator</comment>
+ <comment xml:lang="is">KIllustrator teikning</comment>
+ <comment xml:lang="id">Gambar KIllustrator</comment>
+ <comment xml:lang="ia">Designo KIllustrator</comment>
+ <comment xml:lang="hu">KIllustrator-rajz</comment>
+ <comment xml:lang="hr">KIllustrator crtež</comment>
+ <comment xml:lang="he">ציור KIllustrator</comment>
+ <comment xml:lang="gl">debuxo de KIllustrator</comment>
+ <comment xml:lang="ga">líníocht KIllustrator</comment>
+ <comment xml:lang="fur">dissen KIllustrator</comment>
+ <comment xml:lang="fr">dessin KIllustrator</comment>
+ <comment xml:lang="fo">KIllustrator tekning</comment>
+ <comment xml:lang="fi">KIllustrator-piirros</comment>
+ <comment xml:lang="eu">KIllustrator marrazkia</comment>
+ <comment xml:lang="es">dibujo de KIllustrator</comment>
+ <comment xml:lang="eo">KIllustrator-grafikaĵo</comment>
+ <comment xml:lang="en_GB">KIllustrator drawing</comment>
+ <comment xml:lang="el">Σχέδιο KIllustrator</comment>
+ <comment xml:lang="de">KIllustrator-Zeichnung</comment>
+ <comment xml:lang="da">KIllustrator-tegning</comment>
+ <comment xml:lang="cs">kresba KIllustrator</comment>
+ <comment xml:lang="ca">dibuix de KIllustrator</comment>
+ <comment xml:lang="bg">Чертеж — KIllustrator</comment>
+ <comment xml:lang="be@latin">Rysunak KIllustrator</comment>
+ <comment xml:lang="be">рысунак KIllustrator</comment>
+ <comment xml:lang="ar">تصميم KIllustrator</comment>
+ <comment xml:lang="af">KIllustrator-tekening</comment>
<generic-icon name="image-x-generic"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-killustrator\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-killustrator\004\006" offset="18"/>
</match>
</match>
</magic>
@@ -14033,64 +15265,69 @@
</mime-type>
<mime-type type="application/x-kivio">
<comment>Kivio flowchart</comment>
- <comment xml:lang="ar">قائمة تدفق Kivio</comment>
- <comment xml:lang="be@latin">Blok-schiema Kivio</comment>
- <comment xml:lang="bg">Диаграма — Kivio</comment>
- <comment xml:lang="ca">diagrama de flux de Kivio</comment>
- <comment xml:lang="cs">vývojový diagram Kivio</comment>
- <comment xml:lang="da">Kiviorutediagram</comment>
- <comment xml:lang="de">Kivio-Flussdiagramm</comment>
- <comment xml:lang="el">Διάγραμμα ροής Kivio</comment>
- <comment xml:lang="en_GB">Kivio flowchart</comment>
- <comment xml:lang="eo">Kivo-fluskemo</comment>
- <comment xml:lang="es">diagrama de flujo de Kivio</comment>
- <comment xml:lang="eu">Kivio diagrama</comment>
- <comment xml:lang="fi">Kivio-vuokaavio</comment>
- <comment xml:lang="fo">Kivio leiðarit</comment>
- <comment xml:lang="fr">diagramme de flux Kivio</comment>
- <comment xml:lang="ga">sreabhchairt Kivio</comment>
- <comment xml:lang="gl">gráfica de fluxo de Kivio</comment>
- <comment xml:lang="he">תרשים זרימה של Kivio</comment>
- <comment xml:lang="hr">Kivio dijagram toka</comment>
- <comment xml:lang="hu">Kivio-folyamatábra</comment>
- <comment xml:lang="ia">Diagramma de fluxo Kivio</comment>
- <comment xml:lang="id">Bagan Kivio</comment>
- <comment xml:lang="it">Diagramma di flusso Kivio</comment>
- <comment xml:lang="ja">Kivio フローチャート</comment>
- <comment xml:lang="kk">Kivio диаграммасы</comment>
- <comment xml:lang="ko">Kivio 순서도</comment>
- <comment xml:lang="lt">Kivio eigos diagrama</comment>
- <comment xml:lang="lv">Kivio blokshēma</comment>
- <comment xml:lang="ms">Cartalir Kivio</comment>
- <comment xml:lang="nb">Kivio-flytdiagram</comment>
- <comment xml:lang="nl">Kivio-stroomschema</comment>
- <comment xml:lang="nn">Kivio-flytdiagram</comment>
- <comment xml:lang="oc">diagrama de flux Kivio</comment>
- <comment xml:lang="pl">Diagram przepływów Kivio</comment>
- <comment xml:lang="pt">gráfico de fluxo Kivio</comment>
- <comment xml:lang="pt_BR">Fluxograma do Kivio</comment>
- <comment xml:lang="ro">Diagramă Kivio</comment>
- <comment xml:lang="ru">Диаграмма Kivio</comment>
- <comment xml:lang="sk">Vývojový diagram Kivio</comment>
- <comment xml:lang="sl">Datoteka grafikona Kivio</comment>
- <comment xml:lang="sq">Diagramë fluksi Kivio</comment>
- <comment xml:lang="sr">Кивиов дијаграм тока</comment>
- <comment xml:lang="sv">Kivio-flödesschema</comment>
- <comment xml:lang="tr">Kivio akış şeması</comment>
- <comment xml:lang="uk">блок-схема Kivio</comment>
- <comment xml:lang="vi">Lược đồ Kivio</comment>
+ <comment xml:lang="zh_TW">Kivio 流程圖</comment>
<comment xml:lang="zh_CN">Kivio 流程图</comment>
- <comment xml:lang="zh_TW">Kivio 圖表</comment>
+ <comment xml:lang="vi">Lược đồ Kivio</comment>
+ <comment xml:lang="uk">блок-схема Kivio</comment>
+ <comment xml:lang="tr">Kivio akış çizgesi</comment>
+ <comment xml:lang="sv">Kivio-flödesschema</comment>
+ <comment xml:lang="sr">Кивиов дијаграм тока</comment>
+ <comment xml:lang="sq">diagram hapash Kivio</comment>
+ <comment xml:lang="sl">Datoteka grafikona Kivio</comment>
+ <comment xml:lang="si">කිවියෝ ගැලීම් සටහන</comment>
+ <comment xml:lang="sk">Vývojový diagram Kivio</comment>
+ <comment xml:lang="ru">Диаграмма Kivio</comment>
+ <comment xml:lang="ro">Diagramă Kivio</comment>
+ <comment xml:lang="pt_BR">Fluxograma do Kivio</comment>
+ <comment xml:lang="pt">gráfico de fluxo Kivio</comment>
+ <comment xml:lang="pl">Diagram przepływów Kivio</comment>
+ <comment xml:lang="oc">diagrama de flux Kivio</comment>
+ <comment xml:lang="nn">Kivio-flytdiagram</comment>
+ <comment xml:lang="nl">Kivio-stroomschema</comment>
+ <comment xml:lang="nb">Kivio-flytdiagram</comment>
+ <comment xml:lang="ms">Cartalir Kivio</comment>
+ <comment xml:lang="lv">Kivio blokshēma</comment>
+ <comment xml:lang="lt">Kivio eigos diagrama</comment>
+ <comment xml:lang="ko">Kivio 순서도</comment>
+ <comment xml:lang="kk">Kivio диаграммасы</comment>
+ <comment xml:lang="ja">Kivio フローチャート</comment>
+ <comment xml:lang="it">Diagramma di flusso Kivio</comment>
+ <comment xml:lang="is">Kivio flæðirit</comment>
+ <comment xml:lang="id">Bagan Kivio</comment>
+ <comment xml:lang="ia">Diagramma de fluxo Kivio</comment>
+ <comment xml:lang="hu">Kivio-folyamatábra</comment>
+ <comment xml:lang="hr">Kivio dijagram toka</comment>
+ <comment xml:lang="he">תרשים זרימה של Kivio</comment>
+ <comment xml:lang="gl">gráfica de fluxo de Kivio</comment>
+ <comment xml:lang="ga">sreabhchairt Kivio</comment>
+ <comment xml:lang="fur">diagram di flus Kivio</comment>
+ <comment xml:lang="fr">diagramme de flux Kivio</comment>
+ <comment xml:lang="fo">Kivio leiðarit</comment>
+ <comment xml:lang="fi">Kivio-vuokaavio</comment>
+ <comment xml:lang="eu">Kivio diagrama</comment>
+ <comment xml:lang="es">diagrama de flujo de Kivio</comment>
+ <comment xml:lang="eo">Kivo-fluskemo</comment>
+ <comment xml:lang="en_GB">Kivio flowchart</comment>
+ <comment xml:lang="el">Διάγραμμα ροής Kivio</comment>
+ <comment xml:lang="de">Kivio-Flussdiagramm</comment>
+ <comment xml:lang="da">Kiviorutediagram</comment>
+ <comment xml:lang="cs">vývojový diagram Kivio</comment>
+ <comment xml:lang="ca">diagrama de flux de Kivio</comment>
+ <comment xml:lang="bg">Диаграма — Kivio</comment>
+ <comment xml:lang="be@latin">Blok-schiema Kivio</comment>
+ <comment xml:lang="be">блок-схема Kivio</comment>
+ <comment xml:lang="ar">قائمة تدفق Kivio</comment>
+ <comment xml:lang="af">Kivio-vloeidiagram</comment>
<generic-icon name="x-office-document"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kivio\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kivio\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kivio" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kivio" offset="38"/>
</match>
</match>
</magic>
@@ -14098,64 +15335,69 @@
</mime-type>
<mime-type type="application/x-kontour">
<comment>Kontour drawing</comment>
- <comment xml:lang="ar">تصميم Kontour</comment>
- <comment xml:lang="be@latin">Rysunak Kontour</comment>
- <comment xml:lang="bg">Чертеж — Kontour</comment>
- <comment xml:lang="ca">dibuix de Kontour</comment>
- <comment xml:lang="cs">kresba Kontour</comment>
- <comment xml:lang="da">Kontourtegning</comment>
- <comment xml:lang="de">Kontour-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Kontour</comment>
- <comment xml:lang="en_GB">Kontour drawing</comment>
- <comment xml:lang="eo">Kontour-grafikaĵo</comment>
- <comment xml:lang="es">dibujo de Kontour</comment>
- <comment xml:lang="eu">Kontour marrazkia</comment>
- <comment xml:lang="fi">Kontour-piirros</comment>
- <comment xml:lang="fo">Kontour tekning</comment>
- <comment xml:lang="fr">dessin Kontour</comment>
- <comment xml:lang="ga">líníocht Kontour</comment>
- <comment xml:lang="gl">debuxo de Kontour</comment>
- <comment xml:lang="he">ציור Kontour</comment>
- <comment xml:lang="hr">Kontour crtež</comment>
- <comment xml:lang="hu">Kontour-rajz</comment>
- <comment xml:lang="ia">Designo Kontour</comment>
- <comment xml:lang="id">Gambar Kontour</comment>
- <comment xml:lang="it">Disegno Kontour</comment>
- <comment xml:lang="ja">Kontour ドロー</comment>
- <comment xml:lang="kk">Kontour суреті</comment>
- <comment xml:lang="ko">Kontour 그림</comment>
- <comment xml:lang="lt">Kontour piešinys</comment>
- <comment xml:lang="lv">Kontour zīmējums</comment>
- <comment xml:lang="ms">Lukisan Kontour</comment>
- <comment xml:lang="nb">Kontour-tegning</comment>
- <comment xml:lang="nl">Kontour-tekening</comment>
- <comment xml:lang="nn">Kontour-teikning</comment>
- <comment xml:lang="oc">dessenh Kontour</comment>
- <comment xml:lang="pl">Rysunek Kontour</comment>
- <comment xml:lang="pt">desenho Kontour</comment>
- <comment xml:lang="pt_BR">Desenho do Kontour</comment>
- <comment xml:lang="ro">Desen Kontour</comment>
- <comment xml:lang="ru">Рисунок Kontour</comment>
- <comment xml:lang="sk">Kresba Kontour</comment>
- <comment xml:lang="sl">Datoteka risbe Kontour</comment>
- <comment xml:lang="sq">Vizatim Kontour</comment>
- <comment xml:lang="sr">Контуров цртеж</comment>
- <comment xml:lang="sv">Kontour-teckning</comment>
- <comment xml:lang="tr">Kontour çizimi</comment>
- <comment xml:lang="uk">малюнок Kontour</comment>
- <comment xml:lang="vi">Bản vẽ Kontour</comment>
- <comment xml:lang="zh_CN">Kontour 绘图</comment>
<comment xml:lang="zh_TW">Kontour 繪圖</comment>
+ <comment xml:lang="zh_CN">Kontour 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ Kontour</comment>
+ <comment xml:lang="uk">малюнок Kontour</comment>
+ <comment xml:lang="tr">Kontour çizimi</comment>
+ <comment xml:lang="sv">Kontour-teckning</comment>
+ <comment xml:lang="sr">Контуров цртеж</comment>
+ <comment xml:lang="sq">vizatim Kontour</comment>
+ <comment xml:lang="sl">Datoteka risbe Kontour</comment>
+ <comment xml:lang="si">කොන්ටූර් ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba Kontour</comment>
+ <comment xml:lang="ru">Рисунок Kontour</comment>
+ <comment xml:lang="ro">Desen Kontour</comment>
+ <comment xml:lang="pt_BR">Desenho do Kontour</comment>
+ <comment xml:lang="pt">desenho Kontour</comment>
+ <comment xml:lang="pl">Rysunek Kontour</comment>
+ <comment xml:lang="oc">dessenh Kontour</comment>
+ <comment xml:lang="nn">Kontour-teikning</comment>
+ <comment xml:lang="nl">Kontour-tekening</comment>
+ <comment xml:lang="nb">Kontour-tegning</comment>
+ <comment xml:lang="ms">Lukisan Kontour</comment>
+ <comment xml:lang="lv">Kontour zīmējums</comment>
+ <comment xml:lang="lt">Kontour piešinys</comment>
+ <comment xml:lang="ko">Kontour 그림</comment>
+ <comment xml:lang="kk">Kontour суреті</comment>
+ <comment xml:lang="ja">Kontour ドロー</comment>
+ <comment xml:lang="it">Disegno Kontour</comment>
+ <comment xml:lang="is">Kontour teikning</comment>
+ <comment xml:lang="id">Gambar Kontour</comment>
+ <comment xml:lang="ia">Designo Kontour</comment>
+ <comment xml:lang="hu">Kontour-rajz</comment>
+ <comment xml:lang="hr">Kontour crtež</comment>
+ <comment xml:lang="he">ציור Kontour</comment>
+ <comment xml:lang="gl">debuxo de Kontour</comment>
+ <comment xml:lang="ga">líníocht Kontour</comment>
+ <comment xml:lang="fur">dissen Kontour</comment>
+ <comment xml:lang="fr">dessin Kontour</comment>
+ <comment xml:lang="fo">Kontour tekning</comment>
+ <comment xml:lang="fi">Kontour-piirros</comment>
+ <comment xml:lang="eu">Kontour marrazkia</comment>
+ <comment xml:lang="es">dibujo de Kontour</comment>
+ <comment xml:lang="eo">Kontour-grafikaĵo</comment>
+ <comment xml:lang="en_GB">Kontour drawing</comment>
+ <comment xml:lang="el">Σχέδιο Kontour</comment>
+ <comment xml:lang="de">Kontour-Zeichnung</comment>
+ <comment xml:lang="da">Kontourtegning</comment>
+ <comment xml:lang="cs">kresba Kontour</comment>
+ <comment xml:lang="ca">dibuix de Kontour</comment>
+ <comment xml:lang="bg">Чертеж — Kontour</comment>
+ <comment xml:lang="be@latin">Rysunak Kontour</comment>
+ <comment xml:lang="be">рысунак Kontour</comment>
+ <comment xml:lang="ar">تصميم Kontour</comment>
+ <comment xml:lang="af">Kontour-tekening</comment>
<generic-icon name="image-x-generic"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kontour\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kontour\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kontour" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kontour" offset="38"/>
</match>
</match>
</magic>
@@ -14163,117 +15405,127 @@
</mime-type>
<mime-type type="application/x-kpovmodeler">
<comment>KPovModeler scene</comment>
- <comment xml:lang="ar">مشهد KPovModeler</comment>
- <comment xml:lang="be@latin">Scena KPovModeler</comment>
- <comment xml:lang="bg">Сцена — KPovModeler</comment>
- <comment xml:lang="ca">escena de KPovModeler</comment>
- <comment xml:lang="cs">scéna KPovModeler</comment>
- <comment xml:lang="da">KPovModeler-scene</comment>
- <comment xml:lang="de">KPovModeler-Szene</comment>
- <comment xml:lang="el">Σκηνή KPovModeler</comment>
- <comment xml:lang="en_GB">KPovModeler scene</comment>
- <comment xml:lang="eo">KPovModeler-sceno</comment>
- <comment xml:lang="es">escena de KPovModeler</comment>
- <comment xml:lang="eu">KPovModeler eszena</comment>
- <comment xml:lang="fi">KPovModeler-näkymä</comment>
- <comment xml:lang="fo">KPovModeler leikmynd</comment>
- <comment xml:lang="fr">scène KPovModeler</comment>
- <comment xml:lang="ga">radharc KPovModeler</comment>
- <comment xml:lang="gl">escena de KPovModeler</comment>
- <comment xml:lang="he">סצנת KPovModeler</comment>
- <comment xml:lang="hr">KPovModeler scena</comment>
- <comment xml:lang="hu">KPovModeler-jelenet</comment>
- <comment xml:lang="ia">Scena KPovModeler</comment>
- <comment xml:lang="id">Scene KPovModeler</comment>
- <comment xml:lang="it">Scena KPovModeler</comment>
- <comment xml:lang="ja">KPovModeler シーン</comment>
- <comment xml:lang="kk">KPovModeler сахнасы</comment>
- <comment xml:lang="ko">KPovModeler 장면</comment>
- <comment xml:lang="lt">KPovModeler scena</comment>
- <comment xml:lang="lv">KPovModeler aina</comment>
- <comment xml:lang="ms">Babak KPovModeler</comment>
- <comment xml:lang="nb">KPovModeler-scene</comment>
- <comment xml:lang="nl">KPovModeler-scène</comment>
- <comment xml:lang="nn">KPovModeler-scene</comment>
- <comment xml:lang="oc">scène KPovModeler</comment>
- <comment xml:lang="pl">Scena KPovModeler</comment>
- <comment xml:lang="pt">cenário KPovModeler</comment>
- <comment xml:lang="pt_BR">Cena do KPovModeler</comment>
- <comment xml:lang="ro">Scenă KPovModeler</comment>
- <comment xml:lang="ru">Сцена KPovModeler</comment>
- <comment xml:lang="sk">Scéna KPovModeler</comment>
- <comment xml:lang="sl">Datoteka scene KPovModeler</comment>
- <comment xml:lang="sq">Skenë KPovModeler</comment>
- <comment xml:lang="sr">сцена КПов Моделера</comment>
- <comment xml:lang="sv">KPovModeler-scen</comment>
- <comment xml:lang="tr">KPovModeler sahnesi</comment>
- <comment xml:lang="uk">сцена KPovModeler</comment>
- <comment xml:lang="vi">Cảnh KPovModeler</comment>
- <comment xml:lang="zh_CN">KPovModeler 场景</comment>
<comment xml:lang="zh_TW">KPovModeler 場景</comment>
+ <comment xml:lang="zh_CN">KPovModeler 场景</comment>
+ <comment xml:lang="vi">Cảnh KPovModeler</comment>
+ <comment xml:lang="uk">сцена KPovModeler</comment>
+ <comment xml:lang="tr">KPovModeler sahnesi</comment>
+ <comment xml:lang="sv">KPovModeler-scen</comment>
+ <comment xml:lang="sr">сцена КПов Моделера</comment>
+ <comment xml:lang="sq">skenë KPovModeler</comment>
+ <comment xml:lang="sl">Datoteka scene KPovModeler</comment>
+ <comment xml:lang="si">KPovModeler දර්ශනය</comment>
+ <comment xml:lang="sk">Scéna KPovModeler</comment>
+ <comment xml:lang="ru">Сцена KPovModeler</comment>
+ <comment xml:lang="ro">Scenă KPovModeler</comment>
+ <comment xml:lang="pt_BR">Cena do KPovModeler</comment>
+ <comment xml:lang="pt">cenário KPovModeler</comment>
+ <comment xml:lang="pl">Scena KPovModeler</comment>
+ <comment xml:lang="oc">scène KPovModeler</comment>
+ <comment xml:lang="nn">KPovModeler-scene</comment>
+ <comment xml:lang="nl">KPovModeler-scène</comment>
+ <comment xml:lang="nb">KPovModeler-scene</comment>
+ <comment xml:lang="ms">Babak KPovModeler</comment>
+ <comment xml:lang="lv">KPovModeler aina</comment>
+ <comment xml:lang="lt">KPovModeler scena</comment>
+ <comment xml:lang="ko">KPovModeler 장면</comment>
+ <comment xml:lang="kk">KPovModeler сахнасы</comment>
+ <comment xml:lang="ja">KPovModeler シーン</comment>
+ <comment xml:lang="it">Scena KPovModeler</comment>
+ <comment xml:lang="is">KPovModeler sviðsmynd</comment>
+ <comment xml:lang="id">Scene KPovModeler</comment>
+ <comment xml:lang="ia">Scena KPovModeler</comment>
+ <comment xml:lang="hu">KPovModeler-jelenet</comment>
+ <comment xml:lang="hr">KPovModeler scena</comment>
+ <comment xml:lang="he">סצנת KPovModeler</comment>
+ <comment xml:lang="gl">escena de KPovModeler</comment>
+ <comment xml:lang="ga">radharc KPovModeler</comment>
+ <comment xml:lang="fur">sene KPovModeler</comment>
+ <comment xml:lang="fr">scène KPovModeler</comment>
+ <comment xml:lang="fo">KPovModeler leikmynd</comment>
+ <comment xml:lang="fi">KPovModeler-näkymä</comment>
+ <comment xml:lang="eu">KPovModeler eszena</comment>
+ <comment xml:lang="es">escena de KPovModeler</comment>
+ <comment xml:lang="eo">KPovModeler-sceno</comment>
+ <comment xml:lang="en_GB">KPovModeler scene</comment>
+ <comment xml:lang="el">Σκηνή KPovModeler</comment>
+ <comment xml:lang="de">KPovModeler-Szene</comment>
+ <comment xml:lang="da">KPovModeler-scene</comment>
+ <comment xml:lang="cs">scéna KPovModeler</comment>
+ <comment xml:lang="ca">escena de KPovModeler</comment>
+ <comment xml:lang="bg">Сцена — KPovModeler</comment>
+ <comment xml:lang="be@latin">Scena KPovModeler</comment>
+ <comment xml:lang="be">сцэна KPovModeler</comment>
+ <comment xml:lang="ar">مشهد KPovModeler</comment>
+ <comment xml:lang="af">KPovModeler-toneel</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.kpm"/>
</mime-type>
<mime-type type="application/x-kpresenter">
<comment>KPresenter presentation</comment>
- <comment xml:lang="ar">عرض تقديمي KPresenter</comment>
- <comment xml:lang="be@latin">Prezentacyja KPresenter</comment>
- <comment xml:lang="bg">Презентация — KPresenter</comment>
- <comment xml:lang="ca">presentació de KPresenter</comment>
- <comment xml:lang="cs">prezentace KPresenter</comment>
- <comment xml:lang="da">KPresenter-præsentation</comment>
- <comment xml:lang="de">KPresenter-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση KPresenter</comment>
- <comment xml:lang="en_GB">KPresenter presentation</comment>
- <comment xml:lang="eo">KPresenter-prezentaĵo</comment>
- <comment xml:lang="es">presentación de KPresenter</comment>
- <comment xml:lang="eu">Kpresenter aurkezpena</comment>
- <comment xml:lang="fi">KPresenter-esitys</comment>
- <comment xml:lang="fo">KPresenter framløga</comment>
- <comment xml:lang="fr">présentation KPresenter</comment>
- <comment xml:lang="ga">láithreoireacht KPresenter</comment>
- <comment xml:lang="gl">presentación de KPresenter</comment>
- <comment xml:lang="he">מצגת KPresenter</comment>
- <comment xml:lang="hr">KPresenter prezentacija</comment>
- <comment xml:lang="hu">KPresenter-bemutató</comment>
- <comment xml:lang="ia">Presentation KPresenter</comment>
- <comment xml:lang="id">Presentasi KPresenter</comment>
- <comment xml:lang="it">Presentazione KPresenter</comment>
- <comment xml:lang="ja">KPresenter プレゼンテーション</comment>
- <comment xml:lang="kk">KPresenter презентациясы</comment>
- <comment xml:lang="ko">KPresenter 프레젠테이션</comment>
- <comment xml:lang="lt">KPresenter pateiktis</comment>
- <comment xml:lang="lv">KPresenter prezentācija</comment>
- <comment xml:lang="ms">Persembahan Kpresenter</comment>
- <comment xml:lang="nb">KPresenter-presentasjon</comment>
- <comment xml:lang="nl">KPresenter-presentatie</comment>
- <comment xml:lang="nn">KPresenter-presentasjon</comment>
- <comment xml:lang="oc">presentacion KPresenter</comment>
- <comment xml:lang="pl">Prezentacja KPresenter</comment>
- <comment xml:lang="pt">apresentação KPresenter</comment>
- <comment xml:lang="pt_BR">Apresentação do KPresenter</comment>
- <comment xml:lang="ro">Prezentare KPresenter</comment>
- <comment xml:lang="ru">Презентация KPresenter</comment>
- <comment xml:lang="sk">Prezentácia KPresenter</comment>
- <comment xml:lang="sl">Predstavitev KPresenter</comment>
- <comment xml:lang="sq">Prezantim i KPresenter</comment>
- <comment xml:lang="sr">презентација К-представљача</comment>
- <comment xml:lang="sv">KPresenter-presentation</comment>
- <comment xml:lang="tr">KPresenter sunum dosyası</comment>
- <comment xml:lang="uk">презентація KPresenter</comment>
- <comment xml:lang="vi">Trình diễn KPresenter</comment>
+ <comment xml:lang="zh_TW">KPresenter 簡報</comment>
<comment xml:lang="zh_CN">KPresenter 演示文稿</comment>
- <comment xml:lang="zh_TW">KPresenter 簡報檔</comment>
+ <comment xml:lang="vi">Trình diễn KPresenter</comment>
+ <comment xml:lang="uk">презентація KPresenter</comment>
+ <comment xml:lang="tr">KPresenter sunum dosyası</comment>
+ <comment xml:lang="sv">KPresenter-presentation</comment>
+ <comment xml:lang="sr">презентација К-представљача</comment>
+ <comment xml:lang="sq">paraqitje KPresenter</comment>
+ <comment xml:lang="sl">Predstavitev KPresenter</comment>
+ <comment xml:lang="si">KPresenter ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia KPresenter</comment>
+ <comment xml:lang="ru">Презентация KPresenter</comment>
+ <comment xml:lang="ro">Prezentare KPresenter</comment>
+ <comment xml:lang="pt_BR">Apresentação do KPresenter</comment>
+ <comment xml:lang="pt">apresentação KPresenter</comment>
+ <comment xml:lang="pl">Prezentacja KPresenter</comment>
+ <comment xml:lang="oc">presentacion KPresenter</comment>
+ <comment xml:lang="nn">KPresenter-presentasjon</comment>
+ <comment xml:lang="nl">KPresenter-presentatie</comment>
+ <comment xml:lang="nb">KPresenter-presentasjon</comment>
+ <comment xml:lang="ms">Persembahan Kpresenter</comment>
+ <comment xml:lang="lv">KPresenter prezentācija</comment>
+ <comment xml:lang="lt">KPresenter pateiktis</comment>
+ <comment xml:lang="ko">KPresenter 프레젠테이션</comment>
+ <comment xml:lang="kk">KPresenter презентациясы</comment>
+ <comment xml:lang="ja">KPresenter プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione KPresenter</comment>
+ <comment xml:lang="is">KPresenter framsetning</comment>
+ <comment xml:lang="id">Presentasi KPresenter</comment>
+ <comment xml:lang="ia">Presentation KPresenter</comment>
+ <comment xml:lang="hu">KPresenter-bemutató</comment>
+ <comment xml:lang="hr">KPresenter prezentacija</comment>
+ <comment xml:lang="he">מצגת KPresenter</comment>
+ <comment xml:lang="gl">presentación de KPresenter</comment>
+ <comment xml:lang="ga">láithreoireacht KPresenter</comment>
+ <comment xml:lang="fur">presentazion KPresenter</comment>
+ <comment xml:lang="fr">présentation KPresenter</comment>
+ <comment xml:lang="fo">KPresenter framløga</comment>
+ <comment xml:lang="fi">KPresenter-esitys</comment>
+ <comment xml:lang="eu">Kpresenter aurkezpena</comment>
+ <comment xml:lang="es">presentación de KPresenter</comment>
+ <comment xml:lang="eo">KPresenter-prezentaĵo</comment>
+ <comment xml:lang="en_GB">KPresenter presentation</comment>
+ <comment xml:lang="el">Παρουσίαση KPresenter</comment>
+ <comment xml:lang="de">KPresenter-Präsentation</comment>
+ <comment xml:lang="da">KPresenter-præsentation</comment>
+ <comment xml:lang="cs">prezentace KPresenter</comment>
+ <comment xml:lang="ca">presentació de KPresenter</comment>
+ <comment xml:lang="bg">Презентация — KPresenter</comment>
+ <comment xml:lang="be@latin">Prezentacyja KPresenter</comment>
+ <comment xml:lang="be">прэзентацыя KPresenter</comment>
+ <comment xml:lang="ar">عرض تقديمي KPresenter</comment>
+ <comment xml:lang="af">KPresenter-voorlegging</comment>
<generic-icon name="x-office-presentation"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kpresenter\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kpresenter\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kpresenter" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kpresenter" offset="38"/>
</match>
</match>
</magic>
@@ -14282,130 +15534,144 @@
</mime-type>
<mime-type type="application/x-krita">
<comment>Krita document</comment>
- <comment xml:lang="ar">مستند Krita</comment>
- <comment xml:lang="ast">Documentu de Krita</comment>
- <comment xml:lang="be@latin">Dakument Krita</comment>
- <comment xml:lang="bg">Документ — Krita</comment>
- <comment xml:lang="ca">document Krita</comment>
- <comment xml:lang="cs">dokument Krita</comment>
- <comment xml:lang="da">Kritadokument</comment>
- <comment xml:lang="de">Krita-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Krita</comment>
- <comment xml:lang="en_GB">Krita document</comment>
- <comment xml:lang="eo">Krita-dokumento</comment>
- <comment xml:lang="es">documento de Krita</comment>
- <comment xml:lang="eu">Krita dokumentua</comment>
- <comment xml:lang="fi">Krita-asiakirja</comment>
- <comment xml:lang="fo">Krita skjal</comment>
- <comment xml:lang="fr">document Krita</comment>
- <comment xml:lang="ga">cáipéis Krita</comment>
- <comment xml:lang="gl">documento de Krita</comment>
- <comment xml:lang="he">מסמך Krita</comment>
- <comment xml:lang="hr">Krita dokument</comment>
- <comment xml:lang="hu">Krita-dokumentum</comment>
- <comment xml:lang="ia">Documento Krita</comment>
- <comment xml:lang="id">Dokumen Krita</comment>
- <comment xml:lang="it">Documento Krita</comment>
- <comment xml:lang="ja">Krita ドキュメント</comment>
- <comment xml:lang="kk">Krita құжаты</comment>
- <comment xml:lang="ko">Krita 문서</comment>
- <comment xml:lang="lt">Krita dokumentas</comment>
- <comment xml:lang="lv">Krita dokuments</comment>
- <comment xml:lang="ms">Dokumen Krita</comment>
- <comment xml:lang="nb">Krita-dokument</comment>
- <comment xml:lang="nl">Krita-document</comment>
- <comment xml:lang="nn">Krita-dokument</comment>
- <comment xml:lang="oc">document Krita</comment>
- <comment xml:lang="pl">Dokument Krita</comment>
- <comment xml:lang="pt">documento Krita</comment>
- <comment xml:lang="pt_BR">Documento do Krita</comment>
- <comment xml:lang="ro">Document Krita</comment>
- <comment xml:lang="ru">Документ Krita</comment>
- <comment xml:lang="sk">Dokument Krita</comment>
- <comment xml:lang="sl">Dokument Krita</comment>
- <comment xml:lang="sq">Dokument Krita</comment>
- <comment xml:lang="sr">документ Крите</comment>
- <comment xml:lang="sv">Krita-dokument</comment>
- <comment xml:lang="tr">Krita belgesi</comment>
- <comment xml:lang="uk">документ Krita</comment>
- <comment xml:lang="vi">Tài liệu Krita</comment>
- <comment xml:lang="zh_CN">Krita 文档</comment>
<comment xml:lang="zh_TW">Krita 文件</comment>
+ <comment xml:lang="zh_CN">Krita 文档</comment>
+ <comment xml:lang="vi">Tài liệu Krita</comment>
+ <comment xml:lang="uk">документ Krita</comment>
+ <comment xml:lang="tr">Krita belgesi</comment>
+ <comment xml:lang="sv">Krita-dokument</comment>
+ <comment xml:lang="sr">документ Крите</comment>
+ <comment xml:lang="sq">dokument Krita</comment>
+ <comment xml:lang="sl">Dokument Krita</comment>
+ <comment xml:lang="si">ක්‍රිටා ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Krita</comment>
+ <comment xml:lang="ru">Документ Krita</comment>
+ <comment xml:lang="ro">Document Krita</comment>
+ <comment xml:lang="pt_BR">Documento do Krita</comment>
+ <comment xml:lang="pt">documento Krita</comment>
+ <comment xml:lang="pl">Dokument Krita</comment>
+ <comment xml:lang="oc">document Krita</comment>
+ <comment xml:lang="nn">Krita-dokument</comment>
+ <comment xml:lang="nl">Krita-document</comment>
+ <comment xml:lang="nb">Krita-dokument</comment>
+ <comment xml:lang="ms">Dokumen Krita</comment>
+ <comment xml:lang="lv">Krita dokuments</comment>
+ <comment xml:lang="lt">Krita dokumentas</comment>
+ <comment xml:lang="ko">Krita 문서</comment>
+ <comment xml:lang="kk">Krita құжаты</comment>
+ <comment xml:lang="ja">Krita ドキュメント</comment>
+ <comment xml:lang="it">Documento Krita</comment>
+ <comment xml:lang="is">Krita skjal</comment>
+ <comment xml:lang="id">Dokumen Krita</comment>
+ <comment xml:lang="ia">Documento Krita</comment>
+ <comment xml:lang="hu">Krita-dokumentum</comment>
+ <comment xml:lang="hr">Krita dokument</comment>
+ <comment xml:lang="he">מסמך Krita</comment>
+ <comment xml:lang="gl">documento de Krita</comment>
+ <comment xml:lang="ga">cáipéis Krita</comment>
+ <comment xml:lang="fur">document Krita</comment>
+ <comment xml:lang="fr">document Krita</comment>
+ <comment xml:lang="fo">Krita skjal</comment>
+ <comment xml:lang="fi">Krita-asiakirja</comment>
+ <comment xml:lang="eu">Krita dokumentua</comment>
+ <comment xml:lang="es">documento de Krita</comment>
+ <comment xml:lang="eo">Krita-dokumento</comment>
+ <comment xml:lang="en_GB">Krita document</comment>
+ <comment xml:lang="el">Έγγραφο Krita</comment>
+ <comment xml:lang="de">Krita-Dokument</comment>
+ <comment xml:lang="da">Kritadokument</comment>
+ <comment xml:lang="cs">dokument Krita</comment>
+ <comment xml:lang="ca">document de Krita</comment>
+ <comment xml:lang="bg">Документ — Krita</comment>
+ <comment xml:lang="be@latin">Dakument Krita</comment>
+ <comment xml:lang="be">дакумент Krita</comment>
+ <comment xml:lang="ast">Documentu de Krita</comment>
+ <comment xml:lang="ar">مستند Krita</comment>
+ <comment xml:lang="af">Krita-dokument</comment>
<generic-icon name="x-office-document"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-krita\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-krita\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-krita" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <!-- Depending on the zip library and whether a 32 or 64 bits zip file is used, the offset is different. -->
+ <match type="string" value="application/x-krita" offset="38"/>
+ <match type="string" value="application/x-krita" offset="42"/>
+ <match type="string" value="application/x-krita" offset="63"/>
</match>
</match>
</magic>
<glob pattern="*.kra"/>
+ <glob pattern="*.krz"/>
</mime-type>
<mime-type type="application/x-kspread">
<comment>KSpread spreadsheet</comment>
- <comment xml:lang="ar">جدول KSpread</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš KSpread</comment>
- <comment xml:lang="bg">Таблица — KSpread</comment>
- <comment xml:lang="ca">full de càlcul de KSpread</comment>
- <comment xml:lang="cs">sešit KSpread</comment>
- <comment xml:lang="da">KSpread-regneark</comment>
- <comment xml:lang="de">KSpread-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο KSpread</comment>
- <comment xml:lang="en_GB">KSpread spreadsheet</comment>
- <comment xml:lang="eo">KSpread-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo de KSpread</comment>
- <comment xml:lang="eu">KSpread kalkulu-orria</comment>
- <comment xml:lang="fi">KSpread-taulukko</comment>
- <comment xml:lang="fo">KSpread rokniark</comment>
- <comment xml:lang="fr">feuille de calcul KSpread</comment>
- <comment xml:lang="ga">scarbhileog KSpread</comment>
- <comment xml:lang="gl">folla de cálculo de KSpread</comment>
- <comment xml:lang="he">גליון נתונים של Kspread</comment>
- <comment xml:lang="hr">KSpread proračunska tablica</comment>
- <comment xml:lang="hu">KSpread-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo KSpread</comment>
- <comment xml:lang="id">Lembar sebar KSpread</comment>
- <comment xml:lang="it">Foglio di calcolo KSpread</comment>
- <comment xml:lang="ja">KSpread スプレッドシート</comment>
- <comment xml:lang="kk">KSpread электрондық кестесі</comment>
- <comment xml:lang="ko">KSpread 스프레드시트</comment>
- <comment xml:lang="lt">KSpread skaičialentė</comment>
- <comment xml:lang="lv">KSpread izklājlapa</comment>
- <comment xml:lang="ms">Hamparan KSpread</comment>
- <comment xml:lang="nb">KSpread-regneark</comment>
- <comment xml:lang="nl">KSpread-rekenblad</comment>
- <comment xml:lang="nn">KSpread-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul KSpread</comment>
- <comment xml:lang="pl">Arkusz KSpread</comment>
- <comment xml:lang="pt">folha de cálculo KSpread</comment>
- <comment xml:lang="pt_BR">Planilha do KSpread</comment>
- <comment xml:lang="ro">Foaie de calcul KSpread</comment>
- <comment xml:lang="ru">Электронная таблица KSpread</comment>
- <comment xml:lang="sk">Zošit KSpread</comment>
- <comment xml:lang="sl">Preglednica KSpread</comment>
- <comment xml:lang="sq">Fletë llogaritjesh KSpread</comment>
- <comment xml:lang="sr">табела К-табеле</comment>
- <comment xml:lang="sv">KSpread-kalkylblad</comment>
- <comment xml:lang="tr">KSpread çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця KSpread</comment>
- <comment xml:lang="vi">Bảng tính KSpread</comment>
- <comment xml:lang="zh_CN">KSpread 电子表格</comment>
<comment xml:lang="zh_TW">KSpread 試算表</comment>
+ <comment xml:lang="zh_CN">KSpread 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính KSpread</comment>
+ <comment xml:lang="uk">електронна таблиця KSpread</comment>
+ <comment xml:lang="tr">KSpread hesap çizelgesi</comment>
+ <comment xml:lang="sv">KSpread-kalkylblad</comment>
+ <comment xml:lang="sr">табела К-табеле</comment>
+ <comment xml:lang="sq">fletëllogaritje KSpread</comment>
+ <comment xml:lang="sl">Preglednica KSpread</comment>
+ <comment xml:lang="si">KSpread පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit KSpread</comment>
+ <comment xml:lang="ru">Электронная таблица KSpread</comment>
+ <comment xml:lang="ro">Foaie de calcul KSpread</comment>
+ <comment xml:lang="pt_BR">Planilha do KSpread</comment>
+ <comment xml:lang="pt">folha de cálculo KSpread</comment>
+ <comment xml:lang="pl">Arkusz KSpread</comment>
+ <comment xml:lang="oc">fuèlh de calcul KSpread</comment>
+ <comment xml:lang="nn">KSpread-rekneark</comment>
+ <comment xml:lang="nl">KSpread-rekenblad</comment>
+ <comment xml:lang="nb">KSpread-regneark</comment>
+ <comment xml:lang="ms">Hamparan KSpread</comment>
+ <comment xml:lang="lv">KSpread izklājlapa</comment>
+ <comment xml:lang="lt">KSpread skaičialentė</comment>
+ <comment xml:lang="ko">KSpread 스프레드시트</comment>
+ <comment xml:lang="kk">KSpread электрондық кестесі</comment>
+ <comment xml:lang="ja">KSpread スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo KSpread</comment>
+ <comment xml:lang="is">KSpread töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar KSpread</comment>
+ <comment xml:lang="ia">Folio de calculo KSpread</comment>
+ <comment xml:lang="hu">KSpread-munkafüzet</comment>
+ <comment xml:lang="hr">KSpread proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Kspread</comment>
+ <comment xml:lang="gl">folla de cálculo de KSpread</comment>
+ <comment xml:lang="ga">scarbhileog KSpread</comment>
+ <comment xml:lang="fur">sfuei di calcul KSpread</comment>
+ <comment xml:lang="fr">feuille de calcul KSpread</comment>
+ <comment xml:lang="fo">KSpread rokniark</comment>
+ <comment xml:lang="fi">KSpread-taulukko</comment>
+ <comment xml:lang="eu">KSpread kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de KSpread</comment>
+ <comment xml:lang="eo">KSpread-kalkultabelo</comment>
+ <comment xml:lang="en_GB">KSpread spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο KSpread</comment>
+ <comment xml:lang="de">KSpread-Tabelle</comment>
+ <comment xml:lang="da">KSpread-regneark</comment>
+ <comment xml:lang="cs">sešit KSpread</comment>
+ <comment xml:lang="ca">full de càlcul de KSpread</comment>
+ <comment xml:lang="bg">Таблица — KSpread</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš KSpread</comment>
+ <comment xml:lang="be">электронная табліца KSpread</comment>
+ <comment xml:lang="ar">جدول KSpread</comment>
+ <comment xml:lang="af">KSpread-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kspread\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kspread\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kspread" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kspread" offset="38"/>
</match>
</match>
</magic>
@@ -14413,230 +15679,249 @@
</mime-type>
<mime-type type="application/x-kspread-crypt">
<comment>KSpread spreadsheet (encrypted)</comment>
- <comment xml:lang="ar">جدول KSpread (مشفر)</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš KSpread (zašyfravany)</comment>
- <comment xml:lang="bg">Таблица — KSpread, шифрирана</comment>
- <comment xml:lang="ca">full de càlcul de KSpread (xifrat)</comment>
- <comment xml:lang="cs">sešit KSpread (šifrovaný)</comment>
- <comment xml:lang="da">KSpread-regneark (krypteret)</comment>
- <comment xml:lang="de">KSpread-Tabelle (verschlüsselt)</comment>
- <comment xml:lang="el">Λογιστικό φύλλο KSpread (κρυπτογραφημένο)</comment>
- <comment xml:lang="en_GB">KSpread spreadsheet (encrypted)</comment>
- <comment xml:lang="eo">KSpread-kalkultabelo (ĉifrita)</comment>
- <comment xml:lang="es">hoja de cálculo de KSpread (cifrada)</comment>
- <comment xml:lang="eu">KSpread kalkulu-orria (enkriptatua)</comment>
- <comment xml:lang="fi">KSpread-taulukko (salattu)</comment>
- <comment xml:lang="fo">KSpread rokniark (bronglað)</comment>
- <comment xml:lang="fr">feuille de calcul KSpread (chiffrée)</comment>
- <comment xml:lang="ga">scarbhileog KSpread (criptithe)</comment>
- <comment xml:lang="gl">folla de cálculo de KSpread (cifrada)</comment>
- <comment xml:lang="he">גליון נתונים של KSpread (מוצפן)</comment>
- <comment xml:lang="hr">KSpread proračunska tablica (šifrirana)</comment>
- <comment xml:lang="hu">KSpread-munkafüzet (titkosított)</comment>
- <comment xml:lang="ia">Folio de calculo KSpread (cryptate)</comment>
- <comment xml:lang="id">Lembar sebar KSpread (terenkripsi)</comment>
- <comment xml:lang="it">Foglio di calcolo KSpread (cifrato)</comment>
- <comment xml:lang="ja">KSpread (暗号化) スプレッドシート</comment>
- <comment xml:lang="kk">KSpread электрондық кестесі (шифрленген)</comment>
- <comment xml:lang="ko">암호화된 KSpread 스프레드시트</comment>
- <comment xml:lang="lt">KSpread skaičialentė (užšifruota)</comment>
- <comment xml:lang="lv">KSpread izklājlapa (šifrēta)</comment>
- <comment xml:lang="ms">Hampatan KSpread (terenkripsi)</comment>
- <comment xml:lang="nb">KSpread-regneark (kryptert)</comment>
- <comment xml:lang="nl">KSpread-rekenblad (versleuteld)</comment>
- <comment xml:lang="nn">Kryptert KSpread-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul KSpread (chifrada)</comment>
- <comment xml:lang="pl">Arkusz KSpread (zaszyfrowany)</comment>
- <comment xml:lang="pt">folha de cálculo KSpread (encriptada)</comment>
- <comment xml:lang="pt_BR">Planilha do KSpread (criptografada)</comment>
- <comment xml:lang="ro">Foaie de calcul KSpread (criptat)</comment>
- <comment xml:lang="ru">Электронная таблица KSpread (зашифрованная)</comment>
- <comment xml:lang="sk">Zošit KSpread (šifrovaný)</comment>
- <comment xml:lang="sl">Preglednica KSpread (šifrirana)</comment>
- <comment xml:lang="sq">Fletë llogaritjesh KSpread (e kriptuar)</comment>
- <comment xml:lang="sr">табела К-табеле (шифрована)</comment>
- <comment xml:lang="sv">KSpread-kalkylblad (krypterat)</comment>
- <comment xml:lang="tr">KSpread çalışma sayfası (şifreli)</comment>
- <comment xml:lang="uk">ел. таблиця KSpread (зашифрована)</comment>
- <comment xml:lang="vi">Bảng tính KSpread (đã mật mã)</comment>
+ <comment xml:lang="zh_TW">KSpread 試算表 (加密)</comment>
<comment xml:lang="zh_CN">KSpread 电子表格(加密)</comment>
- <comment xml:lang="zh_TW">KSpread 試算表 (已加密)</comment>
+ <comment xml:lang="vi">Bảng tính KSpread (đã mật mã)</comment>
+ <comment xml:lang="uk">електронна таблиця KSpread (зашифрована)</comment>
+ <comment xml:lang="tr">KSpread hesap çizelgesi (şifreli)</comment>
+ <comment xml:lang="sv">KSpread-kalkylblad (krypterat)</comment>
+ <comment xml:lang="sr">табела К-табеле (шифрована)</comment>
+ <comment xml:lang="sq">fletëllogaritje KSpread (e fshehtëzuar)</comment>
+ <comment xml:lang="sl">Preglednica KSpread (šifrirana)</comment>
+ <comment xml:lang="si">KSpread පැතුරුම්පත (සංකේතනය කළ)</comment>
+ <comment xml:lang="sk">Zošit KSpread (šifrovaný)</comment>
+ <comment xml:lang="ru">Электронная таблица KSpread (зашифрованная)</comment>
+ <comment xml:lang="ro">Foaie de calcul KSpread (criptat)</comment>
+ <comment xml:lang="pt_BR">Planilha do KSpread (criptografada)</comment>
+ <comment xml:lang="pt">folha de cálculo KSpread (encriptada)</comment>
+ <comment xml:lang="pl">Arkusz KSpread (zaszyfrowany)</comment>
+ <comment xml:lang="oc">fuèlh de calcul KSpread (chifrada)</comment>
+ <comment xml:lang="nn">Kryptert KSpread-rekneark</comment>
+ <comment xml:lang="nl">KSpread-rekenblad (versleuteld)</comment>
+ <comment xml:lang="nb">KSpread-regneark (kryptert)</comment>
+ <comment xml:lang="ms">Hampatan KSpread (terenkripsi)</comment>
+ <comment xml:lang="lv">KSpread izklājlapa (šifrēta)</comment>
+ <comment xml:lang="lt">KSpread skaičialentė (užšifruota)</comment>
+ <comment xml:lang="ko">암호화된 KSpread 스프레드시트</comment>
+ <comment xml:lang="kk">KSpread электрондық кестесі (шифрленген)</comment>
+ <comment xml:lang="ja">KSpread (暗号化) スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo KSpread (cifrato)</comment>
+ <comment xml:lang="is">KSpread töflureikniskjal (dulritað)</comment>
+ <comment xml:lang="id">Lembar sebar KSpread (terenkripsi)</comment>
+ <comment xml:lang="ia">Folio de calculo KSpread (cryptate)</comment>
+ <comment xml:lang="hu">KSpread-munkafüzet (titkosított)</comment>
+ <comment xml:lang="hr">KSpread proračunska tablica (šifrirana)</comment>
+ <comment xml:lang="he">גיליון נתונים של KSpread (מוצפן)</comment>
+ <comment xml:lang="gl">folla de cálculo de KSpread (cifrada)</comment>
+ <comment xml:lang="ga">scarbhileog KSpread (criptithe)</comment>
+ <comment xml:lang="fur">sfuei di calcul KSpread (cifrât)</comment>
+ <comment xml:lang="fr">feuille de calcul KSpread (chiffrée)</comment>
+ <comment xml:lang="fo">KSpread rokniark (bronglað)</comment>
+ <comment xml:lang="fi">KSpread-taulukko (salattu)</comment>
+ <comment xml:lang="eu">KSpread kalkulu-orria (zifratuta)</comment>
+ <comment xml:lang="es">hoja de cálculo de KSpread (cifrada)</comment>
+ <comment xml:lang="eo">KSpread-kalkultabelo (ĉifrita)</comment>
+ <comment xml:lang="en_GB">KSpread spreadsheet (encrypted)</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο KSpread (κρυπτογραφημένο)</comment>
+ <comment xml:lang="de">KSpread-Tabelle (verschlüsselt)</comment>
+ <comment xml:lang="da">KSpread-regneark (krypteret)</comment>
+ <comment xml:lang="cs">sešit KSpread (šifrovaný)</comment>
+ <comment xml:lang="ca">full de càlcul de KSpread (xifrat)</comment>
+ <comment xml:lang="bg">Таблица — KSpread, шифрирана</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš KSpread (zašyfravany)</comment>
+ <comment xml:lang="be">электронная табліца KSpread (зашыфравана)</comment>
+ <comment xml:lang="ar">جدول KSpread (مشفر)</comment>
+ <comment xml:lang="af">KSpread-sigblad (geënkripteer)</comment>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="0x0d1a2702" type="big32" offset="0"/>
+ <magic>
+ <match type="big32" value="0x0d1a2702" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-ksysv-package">
<comment>KSysV init package</comment>
- <comment xml:lang="ar">حزمة KSysV init</comment>
- <comment xml:lang="be@latin">Inicyjalny pakunak KSysV</comment>
- <comment xml:lang="bg">Пакет — KSysV init</comment>
- <comment xml:lang="ca">paquet d'inici KSysV</comment>
- <comment xml:lang="cs">balíček init KSysV</comment>
- <comment xml:lang="da">KSsV init-pakke</comment>
- <comment xml:lang="de">KSysV-Init-Paket</comment>
- <comment xml:lang="el">Αρχικό πακέτο KSysV</comment>
- <comment xml:lang="en_GB">KSysV init package</comment>
- <comment xml:lang="es">paquete de configuración de init para KSysV</comment>
- <comment xml:lang="eu">KSysV hasieratzeko paketea</comment>
- <comment xml:lang="fi">KSysV init -paketti</comment>
- <comment xml:lang="fo">KSysV init pakki</comment>
- <comment xml:lang="fr">paquet d'initialisation KSysV</comment>
- <comment xml:lang="ga">pacáiste túsaithe KSysV</comment>
- <comment xml:lang="gl">paquete de KsysV init</comment>
- <comment xml:lang="he">חבילת KSysV init</comment>
- <comment xml:lang="hr">KSysV init paket</comment>
- <comment xml:lang="hu">KSysV init csomag</comment>
- <comment xml:lang="ia">Pacchetto de initialisation KSysV</comment>
- <comment xml:lang="id">Paket init KSysV</comment>
- <comment xml:lang="it">Pacchetto init KSysV</comment>
- <comment xml:lang="ja">KSysV init パッケージ</comment>
- <comment xml:lang="kk">KSysV инициализация дестесі</comment>
- <comment xml:lang="ko">KSysV init 패키지</comment>
- <comment xml:lang="lt">KSysV init paketas</comment>
- <comment xml:lang="lv">KSysV inicializācijas pakotne</comment>
- <comment xml:lang="nb">KSysV init-pakke</comment>
- <comment xml:lang="nl">KSysV-init-pakket</comment>
- <comment xml:lang="nn">KSysV init-pakke</comment>
- <comment xml:lang="oc">paquet d'initializacion KSysV</comment>
- <comment xml:lang="pl">Pakiet KSysV init</comment>
- <comment xml:lang="pt">pacote inicial KSysV</comment>
- <comment xml:lang="pt_BR">Pacote init do KSysV</comment>
- <comment xml:lang="ro">Pachet KSysV init</comment>
- <comment xml:lang="ru">Пакет инициализации KSysV</comment>
- <comment xml:lang="sk">Balíček KSysV init</comment>
- <comment xml:lang="sl">Datoteka paketa KSysV init</comment>
- <comment xml:lang="sq">Paketë init KSysV</comment>
- <comment xml:lang="sr">КСисВ побудни пакет</comment>
- <comment xml:lang="sv">KSysV init-paket</comment>
- <comment xml:lang="tr">KSysV init paketi</comment>
- <comment xml:lang="uk">пакунок KSysV init</comment>
- <comment xml:lang="vi">Gói sở khởi KSysV</comment>
- <comment xml:lang="zh_CN">KSysV init 软件包</comment>
<comment xml:lang="zh_TW">KSysV init 軟體包</comment>
+ <comment xml:lang="zh_CN">KSysV init 软件包</comment>
+ <comment xml:lang="vi">Gói sở khởi KSysV</comment>
+ <comment xml:lang="uk">пакунок KSysV init</comment>
+ <comment xml:lang="tr">KSysV init paketi</comment>
+ <comment xml:lang="sv">KSysV init-paket</comment>
+ <comment xml:lang="sr">КСисВ побудни пакет</comment>
+ <comment xml:lang="sq">paketë init KSysV</comment>
+ <comment xml:lang="sl">Datoteka paketa KSysV init</comment>
+ <comment xml:lang="si">KSysV init පැකේජය</comment>
+ <comment xml:lang="sk">Balíček KSysV init</comment>
+ <comment xml:lang="ru">Пакет инициализации KSysV</comment>
+ <comment xml:lang="ro">Pachet KSysV init</comment>
+ <comment xml:lang="pt_BR">Pacote init do KSysV</comment>
+ <comment xml:lang="pt">pacote inicial KSysV</comment>
+ <comment xml:lang="pl">Pakiet KSysV init</comment>
+ <comment xml:lang="oc">paquet d'initializacion KSysV</comment>
+ <comment xml:lang="nn">KSysV init-pakke</comment>
+ <comment xml:lang="nl">KSysV-init-pakket</comment>
+ <comment xml:lang="nb">KSysV init-pakke</comment>
+ <comment xml:lang="lv">KSysV inicializācijas pakotne</comment>
+ <comment xml:lang="lt">KSysV init paketas</comment>
+ <comment xml:lang="ko">KSysV init 패키지</comment>
+ <comment xml:lang="kk">KSysV инициализация дестесі</comment>
+ <comment xml:lang="ja">KSysV init パッケージ</comment>
+ <comment xml:lang="it">Pacchetto init KSysV</comment>
+ <comment xml:lang="is">KSysV init-pakki</comment>
+ <comment xml:lang="id">Paket init KSysV</comment>
+ <comment xml:lang="ia">Pacchetto de initialisation KSysV</comment>
+ <comment xml:lang="hu">KSysV init csomag</comment>
+ <comment xml:lang="hr">KSysV init paket</comment>
+ <comment xml:lang="he">חבילת KSysV init</comment>
+ <comment xml:lang="gl">paquete de KsysV init</comment>
+ <comment xml:lang="ga">pacáiste túsaithe KSysV</comment>
+ <comment xml:lang="fur">pachet init KSysV</comment>
+ <comment xml:lang="fr">paquet d'initialisation KSysV</comment>
+ <comment xml:lang="fo">KSysV init pakki</comment>
+ <comment xml:lang="fi">KSysV init -paketti</comment>
+ <comment xml:lang="eu">KSysV hasieratzeko paketea</comment>
+ <comment xml:lang="es">paquete de configuración de init para KSysV</comment>
+ <comment xml:lang="en_GB">KSysV init package</comment>
+ <comment xml:lang="el">Αρχικό πακέτο KSysV</comment>
+ <comment xml:lang="de">KSysV-Init-Paket</comment>
+ <comment xml:lang="da">KSsV init-pakke</comment>
+ <comment xml:lang="cs">balíček init KSysV</comment>
+ <comment xml:lang="ca">paquet de KSysV init</comment>
+ <comment xml:lang="bg">Пакет — KSysV init</comment>
+ <comment xml:lang="be@latin">Inicyjalny pakunak KSysV</comment>
+ <comment xml:lang="be">пакет ініцыялізацыі KSysV</comment>
+ <comment xml:lang="ar">حزمة KSysV init</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="KSysV" type="string" offset="4">
- <match value="1" type="byte" offset="15"/>
+ <magic>
+ <match type="string" value="KSysV" offset="4">
+ <match type="byte" value="1" offset="15"/>
</match>
</magic>
</mime-type>
<mime-type type="application/x-kugar">
<comment>Kugar document</comment>
- <comment xml:lang="ar">مستند Kugar</comment>
- <comment xml:lang="ast">Documentu de Kugar</comment>
- <comment xml:lang="be@latin">Dakument Kugar</comment>
- <comment xml:lang="bg">Документ — Kugar</comment>
- <comment xml:lang="ca">document Kugar</comment>
- <comment xml:lang="cs">dokument Kugar</comment>
- <comment xml:lang="da">Kugardokument</comment>
- <comment xml:lang="de">Kugar-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Kugar</comment>
- <comment xml:lang="en_GB">Kugar document</comment>
- <comment xml:lang="eo">Kugar-dokumento</comment>
- <comment xml:lang="es">documento de Kugar</comment>
- <comment xml:lang="eu">Kugar dokumentua</comment>
- <comment xml:lang="fi">Kugar-asiakirja</comment>
- <comment xml:lang="fo">Kugar skjal</comment>
- <comment xml:lang="fr">document Kugar</comment>
- <comment xml:lang="ga">cáipéis Kugar</comment>
- <comment xml:lang="gl">documento de Kugar</comment>
- <comment xml:lang="he">מסמך Kugar</comment>
- <comment xml:lang="hr">Kugar dokument</comment>
- <comment xml:lang="hu">Kugar-dokumentum</comment>
- <comment xml:lang="ia">Documento Kugar</comment>
- <comment xml:lang="id">Dokumen Kugar</comment>
- <comment xml:lang="it">Documento Kugar</comment>
- <comment xml:lang="ja">Kugar ドキュメント</comment>
- <comment xml:lang="kk">Kugar құжаты</comment>
- <comment xml:lang="ko">Kugar 문서</comment>
- <comment xml:lang="lt">Kugar dokumentas</comment>
- <comment xml:lang="lv">Kugar dokuments</comment>
- <comment xml:lang="ms">Dokumen Kugar</comment>
- <comment xml:lang="nb">Kugar-dokument</comment>
- <comment xml:lang="nl">Kugar-document</comment>
- <comment xml:lang="nn">Kugar-dokument</comment>
- <comment xml:lang="oc">document Kugar</comment>
- <comment xml:lang="pl">Dokument Kuguar</comment>
- <comment xml:lang="pt">documento Kugar</comment>
- <comment xml:lang="pt_BR">Documento do Kugar</comment>
- <comment xml:lang="ro">Document Kugar</comment>
- <comment xml:lang="ru">Документ Kugar</comment>
- <comment xml:lang="sk">Dokument Kugar</comment>
- <comment xml:lang="sl">Dokument Kugar</comment>
- <comment xml:lang="sq">Dokument Kugar</comment>
- <comment xml:lang="sr">документ Кугара</comment>
- <comment xml:lang="sv">Kugar-dokument</comment>
- <comment xml:lang="tr">Kugar belgesi</comment>
- <comment xml:lang="uk">документ Kugar</comment>
- <comment xml:lang="vi">Tài liệu Kugar</comment>
- <comment xml:lang="zh_CN">Kugar 文档</comment>
<comment xml:lang="zh_TW">Kugar 文件</comment>
+ <comment xml:lang="zh_CN">Kugar 文档</comment>
+ <comment xml:lang="vi">Tài liệu Kugar</comment>
+ <comment xml:lang="uk">документ Kugar</comment>
+ <comment xml:lang="tr">Kugar belgesi</comment>
+ <comment xml:lang="sv">Kugar-dokument</comment>
+ <comment xml:lang="sr">документ Кугара</comment>
+ <comment xml:lang="sq">dokument Kugar</comment>
+ <comment xml:lang="sl">Dokument Kugar</comment>
+ <comment xml:lang="si">කුගර් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Kugar</comment>
+ <comment xml:lang="ru">Документ Kugar</comment>
+ <comment xml:lang="ro">Document Kugar</comment>
+ <comment xml:lang="pt_BR">Documento do Kugar</comment>
+ <comment xml:lang="pt">documento Kugar</comment>
+ <comment xml:lang="pl">Dokument Kuguar</comment>
+ <comment xml:lang="oc">document Kugar</comment>
+ <comment xml:lang="nn">Kugar-dokument</comment>
+ <comment xml:lang="nl">Kugar-document</comment>
+ <comment xml:lang="nb">Kugar-dokument</comment>
+ <comment xml:lang="ms">Dokumen Kugar</comment>
+ <comment xml:lang="lv">Kugar dokuments</comment>
+ <comment xml:lang="lt">Kugar dokumentas</comment>
+ <comment xml:lang="ko">Kugar 문서</comment>
+ <comment xml:lang="kk">Kugar құжаты</comment>
+ <comment xml:lang="ja">Kugar ドキュメント</comment>
+ <comment xml:lang="it">Documento Kugar</comment>
+ <comment xml:lang="is">Kugar skjal</comment>
+ <comment xml:lang="id">Dokumen Kugar</comment>
+ <comment xml:lang="ia">Documento Kugar</comment>
+ <comment xml:lang="hu">Kugar-dokumentum</comment>
+ <comment xml:lang="hr">Kugar dokument</comment>
+ <comment xml:lang="he">מסמך Kugar</comment>
+ <comment xml:lang="gl">documento de Kugar</comment>
+ <comment xml:lang="ga">cáipéis Kugar</comment>
+ <comment xml:lang="fur">document Kugar</comment>
+ <comment xml:lang="fr">document Kugar</comment>
+ <comment xml:lang="fo">Kugar skjal</comment>
+ <comment xml:lang="fi">Kugar-asiakirja</comment>
+ <comment xml:lang="eu">Kugar dokumentua</comment>
+ <comment xml:lang="es">documento de Kugar</comment>
+ <comment xml:lang="eo">Kugar-dokumento</comment>
+ <comment xml:lang="en_GB">Kugar document</comment>
+ <comment xml:lang="el">Έγγραφο Kugar</comment>
+ <comment xml:lang="de">Kugar-Dokument</comment>
+ <comment xml:lang="da">Kugardokument</comment>
+ <comment xml:lang="cs">dokument Kugar</comment>
+ <comment xml:lang="ca">document Kugar</comment>
+ <comment xml:lang="bg">Документ — Kugar</comment>
+ <comment xml:lang="be@latin">Dakument Kugar</comment>
+ <comment xml:lang="be">дакумент Kugar</comment>
+ <comment xml:lang="ast">Documentu de Kugar</comment>
+ <comment xml:lang="ar">مستند Kugar</comment>
+ <comment xml:lang="af">Kugar-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.kud"/>
</mime-type>
<mime-type type="application/x-kword">
<comment>KWord document</comment>
- <comment xml:lang="ar">مستند KWord</comment>
- <comment xml:lang="ast">Documentu de Kword</comment>
- <comment xml:lang="be@latin">Dakument KWord</comment>
- <comment xml:lang="bg">Документ — KWord</comment>
- <comment xml:lang="ca">document KWord</comment>
- <comment xml:lang="cs">dokument KWord</comment>
- <comment xml:lang="cy">Dogfen KWord</comment>
- <comment xml:lang="da">KWord-dokument</comment>
- <comment xml:lang="de">KWord-Dokument</comment>
- <comment xml:lang="el">Έγγραφο KWord</comment>
- <comment xml:lang="en_GB">KWord document</comment>
- <comment xml:lang="eo">KWord-dokumento</comment>
- <comment xml:lang="es">documento de KWord</comment>
- <comment xml:lang="eu">KWord dokumentua</comment>
- <comment xml:lang="fi">KWord-asiakirja</comment>
- <comment xml:lang="fo">KWord skjal</comment>
- <comment xml:lang="fr">document KWord</comment>
- <comment xml:lang="ga">cáipéis KWord</comment>
- <comment xml:lang="gl">documento de KWord</comment>
- <comment xml:lang="he">מסמך KWord</comment>
- <comment xml:lang="hr">KWord dokument</comment>
- <comment xml:lang="hu">KWord-dokumentum</comment>
- <comment xml:lang="ia">Documento KWord</comment>
- <comment xml:lang="id">Dokumen KWord</comment>
- <comment xml:lang="it">Documento KWord</comment>
- <comment xml:lang="ja">KWord ドキュメント</comment>
- <comment xml:lang="kk">KWord құжаты</comment>
- <comment xml:lang="ko">KWord 문서</comment>
- <comment xml:lang="lt">KWord dokumentas</comment>
- <comment xml:lang="lv">KWord dokuments</comment>
- <comment xml:lang="ms">Dokumen KWord</comment>
- <comment xml:lang="nb">KWord-dokument</comment>
- <comment xml:lang="nl">KWord-document</comment>
- <comment xml:lang="nn">KWord-dokument</comment>
- <comment xml:lang="oc">document KWord</comment>
- <comment xml:lang="pl">Dokument KWord</comment>
- <comment xml:lang="pt">documento KWord</comment>
- <comment xml:lang="pt_BR">Documento do KWord</comment>
- <comment xml:lang="ro">Document KWord</comment>
- <comment xml:lang="ru">Документ KWord</comment>
- <comment xml:lang="sk">Dokument KWord</comment>
- <comment xml:lang="sl">Dokument KWord</comment>
- <comment xml:lang="sq">Dokument KWord</comment>
- <comment xml:lang="sr">документ К-речи</comment>
- <comment xml:lang="sv">KWord-dokument</comment>
- <comment xml:lang="tr">KWord belgesi</comment>
- <comment xml:lang="uk">документ KWord</comment>
- <comment xml:lang="vi">Tài liệu KWord</comment>
- <comment xml:lang="zh_CN">KWord 文档</comment>
<comment xml:lang="zh_TW">KWord 文件</comment>
+ <comment xml:lang="zh_CN">KWord 文档</comment>
+ <comment xml:lang="vi">Tài liệu KWord</comment>
+ <comment xml:lang="uk">документ KWord</comment>
+ <comment xml:lang="tr">KWord belgesi</comment>
+ <comment xml:lang="sv">KWord-dokument</comment>
+ <comment xml:lang="sr">документ К-речи</comment>
+ <comment xml:lang="sq">dokument KWord</comment>
+ <comment xml:lang="sl">Dokument KWord</comment>
+ <comment xml:lang="si">KWord ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument KWord</comment>
+ <comment xml:lang="ru">Документ KWord</comment>
+ <comment xml:lang="ro">Document KWord</comment>
+ <comment xml:lang="pt_BR">Documento do KWord</comment>
+ <comment xml:lang="pt">documento KWord</comment>
+ <comment xml:lang="pl">Dokument KWord</comment>
+ <comment xml:lang="oc">document KWord</comment>
+ <comment xml:lang="nn">KWord-dokument</comment>
+ <comment xml:lang="nl">KWord-document</comment>
+ <comment xml:lang="nb">KWord-dokument</comment>
+ <comment xml:lang="ms">Dokumen KWord</comment>
+ <comment xml:lang="lv">KWord dokuments</comment>
+ <comment xml:lang="lt">KWord dokumentas</comment>
+ <comment xml:lang="ko">KWord 문서</comment>
+ <comment xml:lang="kk">KWord құжаты</comment>
+ <comment xml:lang="ja">KWord ドキュメント</comment>
+ <comment xml:lang="it">Documento KWord</comment>
+ <comment xml:lang="is">KWord skjal</comment>
+ <comment xml:lang="id">Dokumen KWord</comment>
+ <comment xml:lang="ia">Documento KWord</comment>
+ <comment xml:lang="hu">KWord-dokumentum</comment>
+ <comment xml:lang="hr">KWord dokument</comment>
+ <comment xml:lang="he">מסמך KWord</comment>
+ <comment xml:lang="gl">documento de KWord</comment>
+ <comment xml:lang="ga">cáipéis KWord</comment>
+ <comment xml:lang="fur">document KWord</comment>
+ <comment xml:lang="fr">document KWord</comment>
+ <comment xml:lang="fo">KWord skjal</comment>
+ <comment xml:lang="fi">KWord-asiakirja</comment>
+ <comment xml:lang="eu">KWord dokumentua</comment>
+ <comment xml:lang="es">documento de KWord</comment>
+ <comment xml:lang="eo">KWord-dokumento</comment>
+ <comment xml:lang="en_GB">KWord document</comment>
+ <comment xml:lang="el">Έγγραφο KWord</comment>
+ <comment xml:lang="de">KWord-Dokument</comment>
+ <comment xml:lang="da">KWord-dokument</comment>
+ <comment xml:lang="cy">Dogfen KWord</comment>
+ <comment xml:lang="cs">dokument KWord</comment>
+ <comment xml:lang="ca">document KWord</comment>
+ <comment xml:lang="bg">Документ — KWord</comment>
+ <comment xml:lang="be@latin">Dakument KWord</comment>
+ <comment xml:lang="be">дакумент KWord</comment>
+ <comment xml:lang="ast">Documentu de Kword</comment>
+ <comment xml:lang="ar">مستند KWord</comment>
+ <comment xml:lang="af">KWord-dokument</comment>
<generic-icon name="x-office-document"/>
<magic priority="60">
- <match value="\037\213" type="string" offset="0">
- <match value="KOffice" type="string" offset="10">
- <match value="application/x-kword\004\006" type="string" offset="18"/>
+ <match type="string" value="\037\213" offset="0">
+ <match type="string" value="KOffice" offset="10">
+ <match type="string" value="application/x-kword\004\006" offset="18"/>
</match>
</match>
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="application/x-kword" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="application/x-kword" offset="38"/>
</match>
</match>
</magic>
@@ -14645,126 +15930,136 @@
</mime-type>
<mime-type type="application/x-kword-crypt">
<comment>KWord document (encrypted)</comment>
- <comment xml:lang="ar">مستند KWord (مشفر)</comment>
- <comment xml:lang="ast">Documentu de Kword (cifráu)</comment>
- <comment xml:lang="be@latin">Dakument KWord (zašyfravany)</comment>
- <comment xml:lang="bg">Документ — KWord, шифриран</comment>
- <comment xml:lang="ca">document KWord (xifrat)</comment>
- <comment xml:lang="cs">dokument KWord (šifrovaný)</comment>
- <comment xml:lang="da">KWord-dokument (krypteret)</comment>
- <comment xml:lang="de">KWord-Dokument (verschlüsselt)</comment>
- <comment xml:lang="el">Έγγραφο KWord (κρυπτογραφημένο)</comment>
- <comment xml:lang="en_GB">KWord document (encrypted)</comment>
- <comment xml:lang="eo">KWord-dokumento (ĉifrita)</comment>
- <comment xml:lang="es">documento de KWord (cifrado)</comment>
- <comment xml:lang="eu">KWord dokumentua (enkriptatua)</comment>
- <comment xml:lang="fi">KWord-asiakirja (salattu)</comment>
- <comment xml:lang="fo">KWord skjal (bronglað)</comment>
- <comment xml:lang="fr">document KWord (chiffré)</comment>
- <comment xml:lang="ga">cáipéis KWord (criptithe)</comment>
- <comment xml:lang="gl">documento de KWord (cifrado)</comment>
- <comment xml:lang="he">מסמך KWord (מוצפן)</comment>
- <comment xml:lang="hr">KWord dokument (šifriran)</comment>
- <comment xml:lang="hu">KWord-dokumentum (titkosított)</comment>
- <comment xml:lang="ia">Documento KWord (cryptate)</comment>
- <comment xml:lang="id">Dokumen KWord (terenkripsi)</comment>
- <comment xml:lang="it">Documento KWord (cifrato)</comment>
- <comment xml:lang="ja">KWord (暗号化) ドキュメント</comment>
- <comment xml:lang="kk">KWord құжаты (шифрленген)</comment>
- <comment xml:lang="ko">암호화된 KWord 문서</comment>
- <comment xml:lang="lt">KWord dokumentas (užšifruotas)</comment>
- <comment xml:lang="lv">KWord dokuments (šifrēts)</comment>
- <comment xml:lang="ms">Dokumen Kword (terenkripsi)</comment>
- <comment xml:lang="nb">KWord-dokument (kryptert)</comment>
- <comment xml:lang="nl">KWord-document (versleuteld)</comment>
- <comment xml:lang="nn">Kryptert KWord-dokument</comment>
- <comment xml:lang="oc">document KWord (chifrat)</comment>
- <comment xml:lang="pl">Dokument KWord (zaszyfrowany)</comment>
- <comment xml:lang="pt">documento KWord (encriptado)</comment>
- <comment xml:lang="pt_BR">Documento do KWord (criptografado)</comment>
- <comment xml:lang="ro">Document KWord (criptat)</comment>
- <comment xml:lang="ru">Документ KWord (зашифрованный)</comment>
- <comment xml:lang="sk">Dokument KWord (šifrovaný)</comment>
- <comment xml:lang="sl">Dokument KWord (šifriran)</comment>
- <comment xml:lang="sq">Dokument KWord (i kriptuar)</comment>
- <comment xml:lang="sr">документ К-речи (шифровани)</comment>
- <comment xml:lang="sv">KWord-dokument (krypterat)</comment>
- <comment xml:lang="tr">KWord belgesi (şifreli)</comment>
- <comment xml:lang="uk">документ KWord (зашифрований)</comment>
- <comment xml:lang="vi">Tài liệu KWord (đã mật mã)</comment>
+ <comment xml:lang="zh_TW">KWord 文件 (加密)</comment>
<comment xml:lang="zh_CN">KWord 文档(加密)</comment>
- <comment xml:lang="zh_TW">KWord 文件 (已加密)</comment>
+ <comment xml:lang="vi">Tài liệu KWord (đã mật mã)</comment>
+ <comment xml:lang="uk">документ KWord (зашифрований)</comment>
+ <comment xml:lang="tr">KWord belgesi (şifreli)</comment>
+ <comment xml:lang="sv">KWord-dokument (krypterat)</comment>
+ <comment xml:lang="sr">документ К-речи (шифровани)</comment>
+ <comment xml:lang="sq">dokument KWord (i fshehtëzuar)</comment>
+ <comment xml:lang="sl">Dokument KWord (šifriran)</comment>
+ <comment xml:lang="si">KWord ලේඛනය (සංකේතනය කළ)</comment>
+ <comment xml:lang="sk">Dokument KWord (šifrovaný)</comment>
+ <comment xml:lang="ru">Документ KWord (зашифрованный)</comment>
+ <comment xml:lang="ro">Document KWord (criptat)</comment>
+ <comment xml:lang="pt_BR">Documento do KWord (criptografado)</comment>
+ <comment xml:lang="pt">documento KWord (encriptado)</comment>
+ <comment xml:lang="pl">Dokument KWord (zaszyfrowany)</comment>
+ <comment xml:lang="oc">document KWord (chifrat)</comment>
+ <comment xml:lang="nn">Kryptert KWord-dokument</comment>
+ <comment xml:lang="nl">KWord-document (versleuteld)</comment>
+ <comment xml:lang="nb">KWord-dokument (kryptert)</comment>
+ <comment xml:lang="ms">Dokumen Kword (terenkripsi)</comment>
+ <comment xml:lang="lv">KWord dokuments (šifrēts)</comment>
+ <comment xml:lang="lt">KWord dokumentas (užšifruotas)</comment>
+ <comment xml:lang="ko">암호화된 KWord 문서</comment>
+ <comment xml:lang="kk">KWord құжаты (шифрленген)</comment>
+ <comment xml:lang="ja">KWord (暗号化) ドキュメント</comment>
+ <comment xml:lang="it">Documento KWord (cifrato)</comment>
+ <comment xml:lang="is">KWord skjal (dulritað)</comment>
+ <comment xml:lang="id">Dokumen KWord (terenkripsi)</comment>
+ <comment xml:lang="ia">Documento KWord (cryptate)</comment>
+ <comment xml:lang="hu">KWord-dokumentum (titkosított)</comment>
+ <comment xml:lang="hr">KWord dokument (šifriran)</comment>
+ <comment xml:lang="he">מסמך KWord (מוצפן)</comment>
+ <comment xml:lang="gl">documento de KWord (cifrado)</comment>
+ <comment xml:lang="ga">cáipéis KWord (criptithe)</comment>
+ <comment xml:lang="fur">document KWord (cifrât)</comment>
+ <comment xml:lang="fr">document KWord (chiffré)</comment>
+ <comment xml:lang="fo">KWord skjal (bronglað)</comment>
+ <comment xml:lang="fi">KWord-asiakirja (salattu)</comment>
+ <comment xml:lang="eu">KWord dokumentua (zifratuta)</comment>
+ <comment xml:lang="es">documento de KWord (cifrado)</comment>
+ <comment xml:lang="eo">KWord-dokumento (ĉifrita)</comment>
+ <comment xml:lang="en_GB">KWord document (encrypted)</comment>
+ <comment xml:lang="el">Έγγραφο KWord (κρυπτογραφημένο)</comment>
+ <comment xml:lang="de">KWord-Dokument (verschlüsselt)</comment>
+ <comment xml:lang="da">KWord-dokument (krypteret)</comment>
+ <comment xml:lang="cs">dokument KWord (šifrovaný)</comment>
+ <comment xml:lang="ca">document KWord (xifrat)</comment>
+ <comment xml:lang="bg">Документ — KWord, шифриран</comment>
+ <comment xml:lang="be@latin">Dakument KWord (zašyfravany)</comment>
+ <comment xml:lang="be">дакумент KWord (зашыфраваны)</comment>
+ <comment xml:lang="ast">Documentu de Kword (cifráu)</comment>
+ <comment xml:lang="ar">مستند KWord (مشفر)</comment>
+ <comment xml:lang="af">KWord-dokument (geënkripteer)</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="0x0d1a2701" type="big32" offset="0"/>
+ <magic>
+ <match type="big32" value="0x0d1a2701" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-lha">
<comment>LHA archive</comment>
- <comment xml:lang="ar">أرشيف LHA</comment>
- <comment xml:lang="az">LHA arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ LHA</comment>
- <comment xml:lang="bg">Архив — LHA</comment>
- <comment xml:lang="ca">arxiu LHA</comment>
- <comment xml:lang="cs">archiv LHA</comment>
- <comment xml:lang="cy">Archif LHA</comment>
- <comment xml:lang="da">LHA-arkiv</comment>
- <comment xml:lang="de">LHA-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο LHA</comment>
- <comment xml:lang="en_GB">LHA archive</comment>
- <comment xml:lang="eo">LHA-arkivo</comment>
- <comment xml:lang="es">archivador LHA</comment>
- <comment xml:lang="eu">LHA artxiboa</comment>
- <comment xml:lang="fi">LHA-arkisto</comment>
- <comment xml:lang="fo">LHA skjalasavn</comment>
- <comment xml:lang="fr">archive LHA</comment>
- <comment xml:lang="ga">cartlann LHA</comment>
- <comment xml:lang="gl">arquivo LHA</comment>
- <comment xml:lang="he">ארכיון LHA</comment>
- <comment xml:lang="hr">LHA arhiva</comment>
- <comment xml:lang="hu">LHA-archívum</comment>
- <comment xml:lang="ia">Archivo LHA</comment>
- <comment xml:lang="id">Arsip LHA</comment>
- <comment xml:lang="it">Archivio LHA</comment>
- <comment xml:lang="ja">LHA アーカイブ</comment>
- <comment xml:lang="kk">LHA архиві</comment>
- <comment xml:lang="ko">LHA 압축 파일</comment>
- <comment xml:lang="lt">LHA archyvas</comment>
- <comment xml:lang="lv">LHA arhīvs</comment>
- <comment xml:lang="ms">Arkib LHA</comment>
- <comment xml:lang="nb">LHA-arkiv</comment>
- <comment xml:lang="nl">LHA-archief</comment>
- <comment xml:lang="nn">LHA-arkiv</comment>
- <comment xml:lang="oc">archiu LHA</comment>
- <comment xml:lang="pl">Archiwum LHA</comment>
- <comment xml:lang="pt">arquivo LHA</comment>
- <comment xml:lang="pt_BR">Pacote LHA</comment>
- <comment xml:lang="ro">Arhivă LHA</comment>
- <comment xml:lang="ru">Архив LHA</comment>
- <comment xml:lang="sk">Archív LHA</comment>
- <comment xml:lang="sl">Datoteka arhiva LHA</comment>
- <comment xml:lang="sq">Arkiv LHA</comment>
- <comment xml:lang="sr">ЛХА архива</comment>
- <comment xml:lang="sv">LHA-arkiv</comment>
- <comment xml:lang="tr">LHA arşivi</comment>
- <comment xml:lang="uk">архів LHA</comment>
- <comment xml:lang="vi">Kho nén LHA</comment>
- <comment xml:lang="zh_CN">LHA 归档文件</comment>
<comment xml:lang="zh_TW">LHA 封存檔</comment>
+ <comment xml:lang="zh_CN">LHA 归档文件</comment>
+ <comment xml:lang="vi">Kho nén LHA</comment>
+ <comment xml:lang="uk">архів LHA</comment>
+ <comment xml:lang="tr">LHA arşivi</comment>
+ <comment xml:lang="sv">LHA-arkiv</comment>
+ <comment xml:lang="sr">ЛХА архива</comment>
+ <comment xml:lang="sq">arkiv LHA</comment>
+ <comment xml:lang="sl">Datoteka arhiva LHA</comment>
+ <comment xml:lang="si">LHA ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív LHA</comment>
+ <comment xml:lang="ru">Архив LHA</comment>
+ <comment xml:lang="ro">Arhivă LHA</comment>
+ <comment xml:lang="pt_BR">Pacote LHA</comment>
+ <comment xml:lang="pt">arquivo LHA</comment>
+ <comment xml:lang="pl">Archiwum LHA</comment>
+ <comment xml:lang="oc">archiu LHA</comment>
+ <comment xml:lang="nn">LHA-arkiv</comment>
+ <comment xml:lang="nl">LHA-archief</comment>
+ <comment xml:lang="nb">LHA-arkiv</comment>
+ <comment xml:lang="ms">Arkib LHA</comment>
+ <comment xml:lang="lv">LHA arhīvs</comment>
+ <comment xml:lang="lt">LHA archyvas</comment>
+ <comment xml:lang="ko">LHA 압축 파일</comment>
+ <comment xml:lang="kk">LHA архиві</comment>
+ <comment xml:lang="ja">LHA アーカイブ</comment>
+ <comment xml:lang="it">Archivio LHA</comment>
+ <comment xml:lang="is">LHA safnskrá</comment>
+ <comment xml:lang="id">Arsip LHA</comment>
+ <comment xml:lang="ia">Archivo LHA</comment>
+ <comment xml:lang="hu">LHA-archívum</comment>
+ <comment xml:lang="hr">LHA arhiva</comment>
+ <comment xml:lang="he">ארכיון LHA</comment>
+ <comment xml:lang="gl">arquivo LHA</comment>
+ <comment xml:lang="ga">cartlann LHA</comment>
+ <comment xml:lang="fur">archivi LHA</comment>
+ <comment xml:lang="fr">archive LHA</comment>
+ <comment xml:lang="fo">LHA skjalasavn</comment>
+ <comment xml:lang="fi">LHA-arkisto</comment>
+ <comment xml:lang="eu">LHA artxiboa</comment>
+ <comment xml:lang="es">archivador LHA</comment>
+ <comment xml:lang="eo">LHA-arkivo</comment>
+ <comment xml:lang="en_GB">LHA archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο LHA</comment>
+ <comment xml:lang="de">LHA-Archiv</comment>
+ <comment xml:lang="da">LHA-arkiv</comment>
+ <comment xml:lang="cy">Archif LHA</comment>
+ <comment xml:lang="cs">archiv LHA</comment>
+ <comment xml:lang="ca">arxiu LHA</comment>
+ <comment xml:lang="bg">Архив — LHA</comment>
+ <comment xml:lang="be@latin">Archiŭ LHA</comment>
+ <comment xml:lang="be">архіў LHA</comment>
+ <comment xml:lang="az">LHA arxivi</comment>
+ <comment xml:lang="ar">أرشيف LHA</comment>
+ <comment xml:lang="af">LHA-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="-lh -" type="string" offset="2"/>
- <match value="-lh0-" type="string" offset="2"/>
- <match value="-lh1-" type="string" offset="2"/>
- <match value="-lh2-" type="string" offset="2"/>
- <match value="-lh3-" type="string" offset="2"/>
- <match value="-lh4-" type="string" offset="2"/>
- <match value="-lh5-" type="string" offset="2"/>
- <match value="-lh40-" type="string" offset="2"/>
- <match value="-lhd-" type="string" offset="2"/>
- <match value="-lz4-" type="string" offset="2"/>
- <match value="-lz5-" type="string" offset="2"/>
- <match value="-lzs-" type="string" offset="2"/>
+ <match type="string" value="-lh -" offset="2"/>
+ <match type="string" value="-lh0-" offset="2"/>
+ <match type="string" value="-lh1-" offset="2"/>
+ <match type="string" value="-lh2-" offset="2"/>
+ <match type="string" value="-lh3-" offset="2"/>
+ <match type="string" value="-lh4-" offset="2"/>
+ <match type="string" value="-lh5-" offset="2"/>
+ <match type="string" value="-lh40-" offset="2"/>
+ <match type="string" value="-lhd-" offset="2"/>
+ <match type="string" value="-lz4-" offset="2"/>
+ <match type="string" value="-lz5-" offset="2"/>
+ <match type="string" value="-lzs-" offset="2"/>
</magic>
<glob pattern="*.lha"/>
<glob pattern="*.lzh"/>
@@ -14772,413 +16067,445 @@
</mime-type>
<mime-type type="application/x-lhz">
<comment>LHZ archive</comment>
- <comment xml:lang="ar">أرشيف LHZ</comment>
- <comment xml:lang="be@latin">Archiŭ LHZ</comment>
- <comment xml:lang="bg">Архив — LHZ</comment>
- <comment xml:lang="ca">arxiu LHZ</comment>
- <comment xml:lang="cs">archiv LHZ</comment>
- <comment xml:lang="da">LHZ-arkiv</comment>
- <comment xml:lang="de">LHZ-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο LHZ</comment>
- <comment xml:lang="en_GB">LHZ archive</comment>
- <comment xml:lang="eo">LHZ-arkivo</comment>
- <comment xml:lang="es">archivador LHZ</comment>
- <comment xml:lang="eu">LHZ artxiboa</comment>
- <comment xml:lang="fi">LHZ-arkisto</comment>
- <comment xml:lang="fo">LHZ skjalasavn</comment>
- <comment xml:lang="fr">archive LHZ</comment>
- <comment xml:lang="ga">cartlann LHZ</comment>
- <comment xml:lang="gl">arquivo LHZ</comment>
- <comment xml:lang="he">ארכיון LHZ</comment>
- <comment xml:lang="hr">LHZ arhiva</comment>
- <comment xml:lang="hu">LHZ-archívum</comment>
- <comment xml:lang="ia">Archivo LHZ</comment>
- <comment xml:lang="id">Arsip LHZ</comment>
- <comment xml:lang="it">Archivio LHZ</comment>
- <comment xml:lang="ja">LHZ アーカイブ</comment>
- <comment xml:lang="kk">LHZ архиві</comment>
- <comment xml:lang="ko">LHZ 압축 파일</comment>
- <comment xml:lang="lt">LHZ archyvas</comment>
- <comment xml:lang="lv">LHZ arhīvs</comment>
- <comment xml:lang="ms">Arkib LHZ</comment>
- <comment xml:lang="nb">LHZ-arkiv</comment>
- <comment xml:lang="nl">LHZ-archief</comment>
- <comment xml:lang="nn">LHZ-arkiv</comment>
- <comment xml:lang="oc">archiu LHZ</comment>
- <comment xml:lang="pl">Archiwum LHZ</comment>
- <comment xml:lang="pt">arquivo LHZ</comment>
- <comment xml:lang="pt_BR">Pacote LHZ</comment>
- <comment xml:lang="ro">Arhivă LHZ</comment>
- <comment xml:lang="ru">Архив LHZ</comment>
- <comment xml:lang="sk">Archív LHZ</comment>
- <comment xml:lang="sl">Datoteka arhiva LHZ</comment>
- <comment xml:lang="sq">Arkiv LHZ</comment>
- <comment xml:lang="sr">ЛХЗ архива</comment>
- <comment xml:lang="sv">LHZ-arkiv</comment>
- <comment xml:lang="tr">LHZ arşivi</comment>
- <comment xml:lang="uk">архів LHZ</comment>
- <comment xml:lang="vi">Kho nén LHZ (LHA đã nén)</comment>
- <comment xml:lang="zh_CN">LHZ 归档文件</comment>
<comment xml:lang="zh_TW">LHZ 封存檔</comment>
+ <comment xml:lang="zh_CN">LHZ 归档文件</comment>
+ <comment xml:lang="vi">Kho nén LHZ (LHA đã nén)</comment>
+ <comment xml:lang="uk">архів LHZ</comment>
+ <comment xml:lang="tr">LHZ arşivi</comment>
+ <comment xml:lang="sv">LHZ-arkiv</comment>
+ <comment xml:lang="sr">ЛХЗ архива</comment>
+ <comment xml:lang="sq">arkiv LHZ</comment>
+ <comment xml:lang="sl">Datoteka arhiva LHZ</comment>
+ <comment xml:lang="si">LHZ ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív LHZ</comment>
+ <comment xml:lang="ru">Архив LHZ</comment>
+ <comment xml:lang="ro">Arhivă LHZ</comment>
+ <comment xml:lang="pt_BR">Pacote LHZ</comment>
+ <comment xml:lang="pt">arquivo LHZ</comment>
+ <comment xml:lang="pl">Archiwum LHZ</comment>
+ <comment xml:lang="oc">archiu LHZ</comment>
+ <comment xml:lang="nn">LHZ-arkiv</comment>
+ <comment xml:lang="nl">LHZ-archief</comment>
+ <comment xml:lang="nb">LHZ-arkiv</comment>
+ <comment xml:lang="ms">Arkib LHZ</comment>
+ <comment xml:lang="lv">LHZ arhīvs</comment>
+ <comment xml:lang="lt">LHZ archyvas</comment>
+ <comment xml:lang="ko">LHZ 압축 파일</comment>
+ <comment xml:lang="kk">LHZ архиві</comment>
+ <comment xml:lang="ja">LHZ アーカイブ</comment>
+ <comment xml:lang="it">Archivio LHZ</comment>
+ <comment xml:lang="is">LHZ safnskrá</comment>
+ <comment xml:lang="id">Arsip LHZ</comment>
+ <comment xml:lang="ia">Archivo LHZ</comment>
+ <comment xml:lang="hu">LHZ-archívum</comment>
+ <comment xml:lang="hr">LHZ arhiva</comment>
+ <comment xml:lang="he">ארכיון LHZ</comment>
+ <comment xml:lang="gl">arquivo LHZ</comment>
+ <comment xml:lang="ga">cartlann LHZ</comment>
+ <comment xml:lang="fur">archivi LHZ</comment>
+ <comment xml:lang="fr">archive LHZ</comment>
+ <comment xml:lang="fo">LHZ skjalasavn</comment>
+ <comment xml:lang="fi">LHZ-arkisto</comment>
+ <comment xml:lang="eu">LHZ artxiboa</comment>
+ <comment xml:lang="es">archivador LHZ</comment>
+ <comment xml:lang="eo">LHZ-arkivo</comment>
+ <comment xml:lang="en_GB">LHZ archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο LHZ</comment>
+ <comment xml:lang="de">LHZ-Archiv</comment>
+ <comment xml:lang="da">LHZ-arkiv</comment>
+ <comment xml:lang="cs">archiv LHZ</comment>
+ <comment xml:lang="ca">arxiu LHZ</comment>
+ <comment xml:lang="bg">Архив — LHZ</comment>
+ <comment xml:lang="be@latin">Archiŭ LHZ</comment>
+ <comment xml:lang="be">архіў LHZ</comment>
+ <comment xml:lang="ar">أرشيف LHZ</comment>
+ <comment xml:lang="af">LHZ-argief</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.lhz"/>
</mime-type>
- <mime-type type="text/vnd.qt.linguist">
- <comment>message catalog</comment>
- <comment xml:lang="ar">كتالوج الرسالة</comment>
- <comment xml:lang="be@latin">kataloh paviedamleńniaŭ</comment>
- <comment xml:lang="bg">Каталог със съобщения</comment>
- <comment xml:lang="ca">catàleg de missatges</comment>
- <comment xml:lang="cs">katalog zpráv</comment>
- <comment xml:lang="da">meddelelseskatalog</comment>
- <comment xml:lang="de">Nachrichtenkatalog</comment>
- <comment xml:lang="el">Κατάλογος μηνυμάτων</comment>
- <comment xml:lang="en_GB">message catalogue</comment>
- <comment xml:lang="eo">katalogo de mesaĝoj</comment>
- <comment xml:lang="es">catálogo de mensajes</comment>
- <comment xml:lang="eu">mezuen katalogoa</comment>
- <comment xml:lang="fi">viestiluettelo</comment>
- <comment xml:lang="fo">boðskrá</comment>
- <comment xml:lang="fr">catalogue de messages</comment>
- <comment xml:lang="ga">catalóg theachtaireachtaí</comment>
- <comment xml:lang="gl">catálogo de mensaxes</comment>
- <comment xml:lang="he">קטלוג הודעות</comment>
- <comment xml:lang="hr">Katalog poruka</comment>
- <comment xml:lang="hu">üzenetkatalógus</comment>
- <comment xml:lang="ia">Catalogo de messages</comment>
- <comment xml:lang="id">katalog pesan</comment>
- <comment xml:lang="it">Catalogo di messaggi</comment>
- <comment xml:lang="ja">メッセージカタログ</comment>
- <comment xml:lang="kk">мәлімдемелер каталогы</comment>
- <comment xml:lang="ko">메시지 카탈로그</comment>
- <comment xml:lang="lt">laiškų katalogas</comment>
- <comment xml:lang="lv">ziņojumu katalogs</comment>
- <comment xml:lang="ms">Katalog mesej</comment>
- <comment xml:lang="nb">meldingskatalog</comment>
- <comment xml:lang="nl">berichtencatalogus</comment>
- <comment xml:lang="nn">meldingskatalog</comment>
- <comment xml:lang="oc">catalòg de messatges</comment>
- <comment xml:lang="pl">Katalog wiadomości</comment>
- <comment xml:lang="pt">catálogo de mensagens</comment>
- <comment xml:lang="pt_BR">Catálogo de mensagens</comment>
- <comment xml:lang="ro">catalog de mesaje</comment>
- <comment xml:lang="ru">Каталог сообщений</comment>
- <comment xml:lang="sk">Katalóg správ</comment>
- <comment xml:lang="sl">katalogov sporočil</comment>
- <comment xml:lang="sq">Katallog mesazhesh</comment>
- <comment xml:lang="sr">каталог порука</comment>
- <comment xml:lang="sv">meddelandekatalog</comment>
- <comment xml:lang="tr">ileti kataloğu</comment>
+ <mime-type type="text/vnd.trolltech.linguist">
+ <comment>Message catalog</comment>
<comment xml:lang="uk">каталог повідомлень</comment>
- <comment xml:lang="vi">phân loại thông điệp</comment>
- <comment xml:lang="zh_CN">消息库</comment>
- <comment xml:lang="zh_TW">訊息目錄</comment>
+ <comment xml:lang="sv">Meddelandekatalog</comment>
+ <comment xml:lang="ru">Каталог сообщений</comment>
+ <comment xml:lang="pl">Katalog wiadomości</comment>
+ <comment xml:lang="it">Catalogo di messaggi</comment>
+ <comment xml:lang="gl">Catálogo de mensaxes</comment>
+ <comment xml:lang="eu">Mezu-katalogoa</comment>
+ <comment xml:lang="es">catálogo de mensajes</comment>
+ <comment xml:lang="de">Nachrichtenkatalog</comment>
+ <comment xml:lang="be">каталог паведамленняў</comment>
<sub-class-of type="application/xml"/>
<magic>
- <match value="&lt;TS" type="string" offset="0:256"/>
+ <match type="string" value="&lt;TS " offset="0:256"/>
+ <match type="string" value="&lt;TS&gt;" offset="0:256"/>
</magic>
<glob pattern="*.ts"/>
<alias type="application/x-linguist"/>
- <alias type="text/vnd.trolltech.linguist"/>
+ <alias type="text/vnd.qt.linguist"/>
</mime-type>
<mime-type type="application/x-lyx">
<comment>LyX document</comment>
- <comment xml:lang="ar">مستند LyX</comment>
- <comment xml:lang="ast">Documentu de Lyx</comment>
- <comment xml:lang="be@latin">Dakument LyX</comment>
- <comment xml:lang="bg">Документ — LyX</comment>
- <comment xml:lang="ca">document LyX</comment>
- <comment xml:lang="cs">dokument LyX</comment>
- <comment xml:lang="da">LyX-dokument</comment>
- <comment xml:lang="de">LyX-Dokument</comment>
- <comment xml:lang="el">Έγγραφο LyX</comment>
- <comment xml:lang="en_GB">LyX document</comment>
- <comment xml:lang="eo">LyX-dokumento</comment>
- <comment xml:lang="es">documento de LyX</comment>
- <comment xml:lang="eu">LyX dokumentua</comment>
- <comment xml:lang="fi">LyX-asiakirja</comment>
- <comment xml:lang="fo">LyX skjal</comment>
- <comment xml:lang="fr">document LyX</comment>
- <comment xml:lang="ga">cáipéis LyX</comment>
- <comment xml:lang="gl">documento LyX</comment>
- <comment xml:lang="he">מסמך Lyx</comment>
- <comment xml:lang="hr">LyX dokument</comment>
- <comment xml:lang="hu">LyX-dokumentum</comment>
- <comment xml:lang="ia">Documento LyX</comment>
- <comment xml:lang="id">Dokumen LyX</comment>
- <comment xml:lang="it">Documento LyX</comment>
- <comment xml:lang="ja">LyX ドキュメント</comment>
- <comment xml:lang="kk">LyX құжаты</comment>
- <comment xml:lang="ko">LyX 문서</comment>
- <comment xml:lang="lt">LyX dokumentas</comment>
- <comment xml:lang="lv">LyX dokuments</comment>
- <comment xml:lang="ms">Dokumen LyX</comment>
- <comment xml:lang="nb">LyX-dokument</comment>
- <comment xml:lang="nl">LyX-document</comment>
- <comment xml:lang="nn">LyX-dokument</comment>
- <comment xml:lang="oc">document LyX</comment>
- <comment xml:lang="pl">Dokument LyX</comment>
- <comment xml:lang="pt">documento LyX</comment>
- <comment xml:lang="pt_BR">Documento LyX</comment>
- <comment xml:lang="ro">Document LyX</comment>
- <comment xml:lang="ru">Документ LyX</comment>
- <comment xml:lang="sk">Dokument LyX</comment>
- <comment xml:lang="sl">Dokument LyX</comment>
- <comment xml:lang="sq">Dokument LyX</comment>
- <comment xml:lang="sr">ЛиКс документ</comment>
- <comment xml:lang="sv">LyX-dokument</comment>
- <comment xml:lang="tr">LyX belgesi</comment>
- <comment xml:lang="uk">документ LyX</comment>
- <comment xml:lang="vi">Tài liệu LyX</comment>
- <comment xml:lang="zh_CN">LyX 文档</comment>
<comment xml:lang="zh_TW">LyX 文件</comment>
+ <comment xml:lang="zh_CN">LyX 文档</comment>
+ <comment xml:lang="vi">Tài liệu LyX</comment>
+ <comment xml:lang="uk">документ LyX</comment>
+ <comment xml:lang="tr">LyX belgesi</comment>
+ <comment xml:lang="sv">LyX-dokument</comment>
+ <comment xml:lang="sr">ЛиКс документ</comment>
+ <comment xml:lang="sq">dokument LyX</comment>
+ <comment xml:lang="sl">Dokument LyX</comment>
+ <comment xml:lang="si">LyX ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument LyX</comment>
+ <comment xml:lang="ru">Документ LyX</comment>
+ <comment xml:lang="ro">Document LyX</comment>
+ <comment xml:lang="pt_BR">Documento LyX</comment>
+ <comment xml:lang="pt">documento LyX</comment>
+ <comment xml:lang="pl">Dokument LyX</comment>
+ <comment xml:lang="oc">document LyX</comment>
+ <comment xml:lang="nn">LyX-dokument</comment>
+ <comment xml:lang="nl">LyX-document</comment>
+ <comment xml:lang="nb">LyX-dokument</comment>
+ <comment xml:lang="ms">Dokumen LyX</comment>
+ <comment xml:lang="lv">LyX dokuments</comment>
+ <comment xml:lang="lt">LyX dokumentas</comment>
+ <comment xml:lang="ko">LyX 문서</comment>
+ <comment xml:lang="kk">LyX құжаты</comment>
+ <comment xml:lang="ja">LyX ドキュメント</comment>
+ <comment xml:lang="it">Documento LyX</comment>
+ <comment xml:lang="is">LyX skjal</comment>
+ <comment xml:lang="id">Dokumen LyX</comment>
+ <comment xml:lang="ia">Documento LyX</comment>
+ <comment xml:lang="hu">LyX-dokumentum</comment>
+ <comment xml:lang="hr">LyX dokument</comment>
+ <comment xml:lang="he">מסמך Lyx</comment>
+ <comment xml:lang="gl">documento LyX</comment>
+ <comment xml:lang="ga">cáipéis LyX</comment>
+ <comment xml:lang="fur">document LyX</comment>
+ <comment xml:lang="fr">document LyX</comment>
+ <comment xml:lang="fo">LyX skjal</comment>
+ <comment xml:lang="fi">LyX-asiakirja</comment>
+ <comment xml:lang="eu">LyX dokumentua</comment>
+ <comment xml:lang="es">documento de LyX</comment>
+ <comment xml:lang="eo">LyX-dokumento</comment>
+ <comment xml:lang="en_GB">LyX document</comment>
+ <comment xml:lang="el">Έγγραφο LyX</comment>
+ <comment xml:lang="de">LyX-Dokument</comment>
+ <comment xml:lang="da">LyX-dokument</comment>
+ <comment xml:lang="cs">dokument LyX</comment>
+ <comment xml:lang="ca">document LyX</comment>
+ <comment xml:lang="bg">Документ — LyX</comment>
+ <comment xml:lang="be@latin">Dakument LyX</comment>
+ <comment xml:lang="be">дакумент LyX</comment>
+ <comment xml:lang="ast">Documentu de Lyx</comment>
+ <comment xml:lang="ar">مستند LyX</comment>
+ <comment xml:lang="af">LyX-dokument</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="#LyX" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#LyX" offset="0"/>
</magic>
<glob pattern="*.lyx"/>
<alias type="text/x-lyx"/>
</mime-type>
<mime-type type="application/x-lz4">
<comment>LZ4 archive</comment>
- <comment xml:lang="ca">arxiu LZ4</comment>
- <comment xml:lang="cs">archiv LZ4</comment>
- <comment xml:lang="da">LZ4-arkiv</comment>
- <comment xml:lang="de">LZ4-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο LZ4</comment>
- <comment xml:lang="en_GB">LZ4 archive</comment>
- <comment xml:lang="es">archivador LZ4</comment>
- <comment xml:lang="eu">LZ4 artxiboa</comment>
- <comment xml:lang="fi">LZ4-arkisto</comment>
- <comment xml:lang="fr">archive LZ4</comment>
- <comment xml:lang="ga">Cartlann LZ4</comment>
- <comment xml:lang="gl">Arquivo LZ4</comment>
- <comment xml:lang="he">ארכיון LZ4</comment>
- <comment xml:lang="hr">LZ4 arhiva</comment>
- <comment xml:lang="hu">LZ4 archívum</comment>
- <comment xml:lang="ia">Archivo LZ4</comment>
- <comment xml:lang="id">Arsip LZ4</comment>
- <comment xml:lang="it">Archivio LZ4</comment>
- <comment xml:lang="kk">LZ4 архиві</comment>
- <comment xml:lang="ko">LZ4 압축 파일</comment>
- <comment xml:lang="oc">archiu LZ4</comment>
- <comment xml:lang="pl">Archiwum LZ4</comment>
- <comment xml:lang="pt">arquivo LZ4</comment>
- <comment xml:lang="pt_BR">Pacote LZ4</comment>
- <comment xml:lang="ru">Архив LZ4</comment>
- <comment xml:lang="sk">Archív LZ4</comment>
- <comment xml:lang="sl">Datoteka arhiva LZ4</comment>
- <comment xml:lang="sr">ЛЗ4 архива</comment>
- <comment xml:lang="sv">LZ4-arkiv</comment>
- <comment xml:lang="tr">LZ4 arşivi</comment>
- <comment xml:lang="uk">архів LZ4</comment>
- <comment xml:lang="zh_CN">LZ4 归档文件</comment>
<comment xml:lang="zh_TW">LZ4 封存檔</comment>
+ <comment xml:lang="zh_CN">LZ4 归档文件</comment>
+ <comment xml:lang="uk">архів LZ4</comment>
+ <comment xml:lang="tr">LZ4 arşivi</comment>
+ <comment xml:lang="sv">LZ4-arkiv</comment>
+ <comment xml:lang="sr">ЛЗ4 архива</comment>
+ <comment xml:lang="sq">arkiv LZ4</comment>
+ <comment xml:lang="sl">Datoteka arhiva LZ4</comment>
+ <comment xml:lang="si">LZ4 ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív LZ4</comment>
+ <comment xml:lang="ru">Архив LZ4</comment>
+ <comment xml:lang="pt_BR">Pacote LZ4</comment>
+ <comment xml:lang="pt">arquivo LZ4</comment>
+ <comment xml:lang="pl">Archiwum LZ4</comment>
+ <comment xml:lang="oc">archiu LZ4</comment>
+ <comment xml:lang="nl">LZ4-archief</comment>
+ <comment xml:lang="ko">LZ4 압축 파일</comment>
+ <comment xml:lang="kk">LZ4 архиві</comment>
+ <comment xml:lang="ja">LZ4 アーカイヴ</comment>
+ <comment xml:lang="it">Archivio LZ4</comment>
+ <comment xml:lang="is">LZ4 safnskrá</comment>
+ <comment xml:lang="id">Arsip LZ4</comment>
+ <comment xml:lang="ia">Archivo LZ4</comment>
+ <comment xml:lang="hu">LZ4 archívum</comment>
+ <comment xml:lang="hr">LZ4 arhiva</comment>
+ <comment xml:lang="he">ארכיון LZ4</comment>
+ <comment xml:lang="gl">Arquivo LZ4</comment>
+ <comment xml:lang="ga">Cartlann LZ4</comment>
+ <comment xml:lang="fur">archivi LZ4</comment>
+ <comment xml:lang="fr">archive LZ4</comment>
+ <comment xml:lang="fi">LZ4-arkisto</comment>
+ <comment xml:lang="eu">LZ4 artxiboa</comment>
+ <comment xml:lang="es">archivador LZ4</comment>
+ <comment xml:lang="en_GB">LZ4 archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο LZ4</comment>
+ <comment xml:lang="de">LZ4-Archiv</comment>
+ <comment xml:lang="da">LZ4-arkiv</comment>
+ <comment xml:lang="cs">archiv LZ4</comment>
+ <comment xml:lang="ca">arxiu LZ4</comment>
+ <comment xml:lang="bg">Архив — LZ4</comment>
+ <comment xml:lang="be">архіў LZ4</comment>
+ <comment xml:lang="ar">أرشيف LZ4</comment>
+ <comment xml:lang="af">LZ4-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="0x184d2204" type="little32" offset="0"/>
- <match value="0x184c2102" type="little32" offset="0"/>
+ <match type="little32" value="0x184d2204" offset="0"/>
+ <match type="little32" value="0x184c2102" offset="0"/>
</magic>
<glob pattern="*.lz4"/>
</mime-type>
<mime-type type="application/x-lz4-compressed-tar">
<comment>Tar archive (LZ4-compressed)</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió LZ4)</comment>
- <comment xml:lang="cs">archiv Tar (komprimace LZ4)</comment>
- <comment xml:lang="da">Tar-arkiv (LZ4-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (LZ4-komprimiert)</comment>
- <comment xml:lang="en_GB">Tar archive (LZ4-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con LZ4)</comment>
- <comment xml:lang="eu">Tar artxiboa (LZ4-rekin konprimatua)</comment>
- <comment xml:lang="fi">Tar-arkisto (LZ4-pakattu)</comment>
- <comment xml:lang="fr">archive tar (compression LZ4)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZ4)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י LZ4)</comment>
- <comment xml:lang="hr">Tar arhiva (LZ4 sažeto)</comment>
- <comment xml:lang="hu">Tar archívum (LZ4-el tömörítve)</comment>
- <comment xml:lang="id">arsip tar (terkompresi LZ4)</comment>
- <comment xml:lang="it">Archivio tar (compresso con LZ4)</comment>
- <comment xml:lang="kk">Tar архиві (LZ4-пен сығылған)</comment>
- <comment xml:lang="ko">Tar 묶음 파일(LZ4 압축)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja LZ4)</comment>
- <comment xml:lang="pt_BR">Arquvio Tar (compactado com LZ4)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый lz4)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou LZ4)</comment>
- <comment xml:lang="sr">Тар архива (запакована ЛЗ4-ом)</comment>
- <comment xml:lang="sv">Tar-arkiv (LZ4-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (LZ4 ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений LZ4)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (LZ4 壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(LZ4 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (LZ4 格式壓縮)</comment>
+ <comment xml:lang="uk">архів tar (стиснений LZ4)</comment>
+ <comment xml:lang="tr">Tar arşivi (LZ4 ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (LZ4-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована ЛЗ4-ом)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me LZ4)</comment>
+ <comment xml:lang="sl">Arhiv tar (stisnjen, LZ4)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (LZ4-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou LZ4)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый lz4)</comment>
+ <comment xml:lang="pt_BR">Arquivo Tar (compactado com LZ4)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja LZ4)</comment>
+ <comment xml:lang="oc">archiu Tar (compression LZ4)</comment>
+ <comment xml:lang="nl">Tar-archief (gecomprimeerd met LZ4)</comment>
+ <comment xml:lang="ko">Tar 묶음 파일(LZ4 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (LZ4-пен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (LZ4 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con LZ4)</comment>
+ <comment xml:lang="is">Tar safnskrá (LZ4-þjappað)</comment>
+ <comment xml:lang="id">Arsip tar (terkompresi LZ4)</comment>
+ <comment xml:lang="hu">Tar archívum (LZ4 tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (LZ4 sažeto)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י LZ4)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZ4)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun LZ4)</comment>
+ <comment xml:lang="fr">archive tar (compression LZ4)</comment>
+ <comment xml:lang="fi">Tar-arkisto (LZ4-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (LZ4-rekin konprimatua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con LZ4)</comment>
+ <comment xml:lang="en_GB">Tar archive (LZ4-compressed)</comment>
+ <comment xml:lang="de">Tar-Archiv (LZ4-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (LZ4-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimace LZ4)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió LZ4)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с LZ4</comment>
+ <comment xml:lang="be">архіў tar (сцісканне LZ4)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-LZ4)</comment>
+ <comment xml:lang="af">Tar-argief (LZ4-saamgepers)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-lz4"/>
<glob pattern="*.tar.lz4"/>
</mime-type>
<mime-type type="application/x-lzip">
<comment>Lzip archive</comment>
- <comment xml:lang="ar">أرشيف Lzip</comment>
- <comment xml:lang="bg">Архив — lzip</comment>
- <comment xml:lang="ca">arxiu lzip</comment>
- <comment xml:lang="cs">archiv Lzip</comment>
- <comment xml:lang="da">Lzip-arkiv</comment>
- <comment xml:lang="de">Lzip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Lzip</comment>
- <comment xml:lang="en_GB">Lzip archive</comment>
- <comment xml:lang="eo">Lzip-arkivo</comment>
- <comment xml:lang="es">archivador Lzip</comment>
- <comment xml:lang="eu">Lzip artxiboa</comment>
- <comment xml:lang="fi">Lzip-arkisto</comment>
- <comment xml:lang="fo">Lzip skjalasavn</comment>
- <comment xml:lang="fr">archive lzip</comment>
- <comment xml:lang="ga">cartlann Lzip</comment>
- <comment xml:lang="gl">arquivo Lzip</comment>
- <comment xml:lang="he">ארכיון Lzip</comment>
- <comment xml:lang="hr">Lzip arhiva</comment>
- <comment xml:lang="hu">Lzip archívum</comment>
- <comment xml:lang="ia">Archivo Lzip</comment>
- <comment xml:lang="id">Arsip Lzip</comment>
- <comment xml:lang="it">Archivio Lzip</comment>
- <comment xml:lang="ja">Lzip アーカイブ</comment>
- <comment xml:lang="kk">Lzip архиві</comment>
- <comment xml:lang="ko">LZIP 압축 파일</comment>
- <comment xml:lang="lt">Lzip archyvas</comment>
- <comment xml:lang="lv">Lzip arhīvs</comment>
- <comment xml:lang="nl">Lzip archief</comment>
- <comment xml:lang="oc">archiu lzip</comment>
- <comment xml:lang="pl">Archiwum lzip</comment>
- <comment xml:lang="pt">arquivo LZip</comment>
- <comment xml:lang="pt_BR">Pacote Lzip</comment>
- <comment xml:lang="ro">Arhivă Lzip</comment>
- <comment xml:lang="ru">Архив LZIP</comment>
- <comment xml:lang="sk">Archív Lzip</comment>
- <comment xml:lang="sl">Datoteka arhiva Lzip</comment>
- <comment xml:lang="sr">Лзип архива</comment>
- <comment xml:lang="sv">Lzip-arkiv</comment>
- <comment xml:lang="tr">Lzip arşivi</comment>
- <comment xml:lang="uk">архів lzip</comment>
- <comment xml:lang="zh_CN">Lzip 归档文件</comment>
<comment xml:lang="zh_TW">Lzip 封存檔</comment>
+ <comment xml:lang="zh_CN">Lzip 归档文件</comment>
+ <comment xml:lang="uk">архів lzip</comment>
+ <comment xml:lang="tr">Lzip arşivi</comment>
+ <comment xml:lang="sv">Lzip-arkiv</comment>
+ <comment xml:lang="sr">Лзип архива</comment>
+ <comment xml:lang="sq">arkiv Lzip</comment>
+ <comment xml:lang="sl">Datoteka arhiva Lzip</comment>
+ <comment xml:lang="si">Lzip සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Lzip</comment>
+ <comment xml:lang="ru">Архив LZIP</comment>
+ <comment xml:lang="ro">Arhivă Lzip</comment>
+ <comment xml:lang="pt_BR">Pacote Lzip</comment>
+ <comment xml:lang="pt">arquivo LZip</comment>
+ <comment xml:lang="pl">Archiwum lzip</comment>
+ <comment xml:lang="oc">archiu lzip</comment>
+ <comment xml:lang="nl">Lzip-archief</comment>
+ <comment xml:lang="lv">Lzip arhīvs</comment>
+ <comment xml:lang="lt">Lzip archyvas</comment>
+ <comment xml:lang="ko">LZIP 압축 파일</comment>
+ <comment xml:lang="kk">Lzip архиві</comment>
+ <comment xml:lang="ja">Lzip アーカイブ</comment>
+ <comment xml:lang="it">Archivio Lzip</comment>
+ <comment xml:lang="is">Lzip safnskrá</comment>
+ <comment xml:lang="id">Arsip Lzip</comment>
+ <comment xml:lang="ia">Archivo Lzip</comment>
+ <comment xml:lang="hu">Lzip archívum</comment>
+ <comment xml:lang="hr">Lzip arhiva</comment>
+ <comment xml:lang="he">ארכיון Lzip</comment>
+ <comment xml:lang="gl">arquivo Lzip</comment>
+ <comment xml:lang="ga">cartlann Lzip</comment>
+ <comment xml:lang="fur">archivi Lzip</comment>
+ <comment xml:lang="fr">archive lzip</comment>
+ <comment xml:lang="fo">Lzip skjalasavn</comment>
+ <comment xml:lang="fi">Lzip-arkisto</comment>
+ <comment xml:lang="eu">Lzip artxiboa</comment>
+ <comment xml:lang="es">archivador Lzip</comment>
+ <comment xml:lang="eo">Lzip-arkivo</comment>
+ <comment xml:lang="en_GB">Lzip archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Lzip</comment>
+ <comment xml:lang="de">Lzip-Archiv</comment>
+ <comment xml:lang="da">Lzip-arkiv</comment>
+ <comment xml:lang="cs">archiv Lzip</comment>
+ <comment xml:lang="ca">arxiu lzip</comment>
+ <comment xml:lang="bg">Архив — Lzip</comment>
+ <comment xml:lang="be">архіў Lzip</comment>
+ <comment xml:lang="ar">أرشيف Lzip</comment>
+ <comment xml:lang="af">Lzip-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="LZIP" type="string" offset="0"/>
+ <match type="string" value="LZIP" offset="0"/>
</magic>
<glob pattern="*.lz"/>
</mime-type>
<mime-type type="application/x-lzip-compressed-tar">
<comment>Tar archive (lzip-compressed)</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió lzip)</comment>
- <comment xml:lang="cs">archiv Tar (komprimace lzip)</comment>
- <comment xml:lang="da">Tar-arkiv (lzip-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (lzip-komprimiert)</comment>
- <comment xml:lang="en_GB">Tar archive (lzip-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con lzip)</comment>
- <comment xml:lang="eu">Tar artxiboa (lzip-rekin konprimatua)</comment>
- <comment xml:lang="fi">Tar-arkisto (lzip-pakattu)</comment>
- <comment xml:lang="fr">archive tar (compressée lzip)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le lzip)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י lzip)</comment>
- <comment xml:lang="hr">Tar arhiva (lzip sažeto)</comment>
- <comment xml:lang="hu">Tar archívum (lzippel tömörítve)</comment>
- <comment xml:lang="id">arsip tar (terkompresi lzip)</comment>
- <comment xml:lang="it">Archivio tar (compresso con lzip)</comment>
- <comment xml:lang="kk">Tar архиві (lzip-пен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(LZIP 압축)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja lzip)</comment>
- <comment xml:lang="pt_BR">Arquivo Tar (compactado com lzip)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый lzip)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou lzip)</comment>
- <comment xml:lang="sr">Тар архива (запакована лзипом)</comment>
- <comment xml:lang="sv">Tar-arkiv (lzip-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (lzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений lzip)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (lzip 壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(lzip 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (lzip 格式壓縮)</comment>
+ <comment xml:lang="uk">архів tar (стиснений lzip)</comment>
+ <comment xml:lang="tr">Tar arşivi (lzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (lzip-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована лзипом)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me lzip)</comment>
+ <comment xml:lang="sl">Arhiv tar (stisnjen, lzip)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (lzip-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou lzip)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый lzip)</comment>
+ <comment xml:lang="pt_BR">Arquivo Tar (compactado com lzip)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja lzip)</comment>
+ <comment xml:lang="oc">archiu Tar (compression lzip)</comment>
+ <comment xml:lang="nl">Tar-archief (gecomprimeerd met lzip)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(LZIP 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (lzip-пен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (lzip 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con lzip)</comment>
+ <comment xml:lang="is">Tar safnskrá (lzip-þjappað)</comment>
+ <comment xml:lang="id">Arsip tar (terkompresi lzip)</comment>
+ <comment xml:lang="hu">Tar archívum (lzip tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (lzip sažeto)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י lzip)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le lzip)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun lzip)</comment>
+ <comment xml:lang="fr">archive tar (compressée lzip)</comment>
+ <comment xml:lang="fi">Tar-arkisto (lzip-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (lzip-rekin konprimatua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con LZIP)</comment>
+ <comment xml:lang="en_GB">Tar archive (lzip-compressed)</comment>
+ <comment xml:lang="de">Tar-Archiv (lzip-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (lzip-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimace lzip)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió lzip)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с Lzip</comment>
+ <comment xml:lang="be">архіў tar (сцісканне lzip)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-lzip)</comment>
+ <comment xml:lang="af">Tar-argief (lzip-saamgepers)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-lzip"/>
<glob pattern="*.tar.lz"/>
</mime-type>
<mime-type type="application/x-lzpdf">
<comment>PDF document (lzip-compressed)</comment>
- <comment xml:lang="ast">Documentu PDF (comprimíu en lzip)</comment>
- <comment xml:lang="ca">document PDF (amb compressió lzip)</comment>
- <comment xml:lang="cs">dokument PDF (komprimace lzip)</comment>
- <comment xml:lang="de">PDF-Dokument (lzip-komprimiert)</comment>
- <comment xml:lang="en_GB">PDF document (lzip-compressed)</comment>
- <comment xml:lang="es">documento PDF (comprimido con lzip)</comment>
- <comment xml:lang="eu">PDF dokumentua (lzip-rekin konprimitua)</comment>
- <comment xml:lang="fi">PDF-asiakirja (lzip-pakattu)</comment>
- <comment xml:lang="fr">document PDF (compressé lzip)</comment>
- <comment xml:lang="ga">cáipéis PDF (comhbhrúite le lzip)</comment>
- <comment xml:lang="hr">PDF dokument (lzip sažeto)</comment>
- <comment xml:lang="hu">PDF dokumentum (lzip-tömörítésű)</comment>
- <comment xml:lang="id">dokumen PDF (termkompresi lzip)</comment>
- <comment xml:lang="it">Documento PDF (compresso con lzip)</comment>
- <comment xml:lang="kk">PDF құжаты (lzip-пен сығылған)</comment>
- <comment xml:lang="ko">PDF 문서(LZIP 압축)</comment>
- <comment xml:lang="pl">Dokument PDF (kompresja lzip)</comment>
- <comment xml:lang="pt_BR">Documento PDF (compactado com lzip)</comment>
- <comment xml:lang="ru">Документ PDF (сжатый lzip)</comment>
- <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou lzip)</comment>
- <comment xml:lang="sr">ПДФ документ (запакован лзип-ом)</comment>
- <comment xml:lang="sv">PDF-dokument (lzip-komprimerat)</comment>
- <comment xml:lang="tr">PDF belgesi (lzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ PDF (стиснений lzip)</comment>
+ <comment xml:lang="zh_TW">PDF 文件 (lzip 壓縮)</comment>
<comment xml:lang="zh_CN">PDF 文档(lzip 压缩)</comment>
- <comment xml:lang="zh_TW">PDF 文件 (lzip 格式壓縮)</comment>
+ <comment xml:lang="uk">документ PDF (стиснений lzip)</comment>
+ <comment xml:lang="tr">PDF belgesi (lzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">PDF-dokument (lzip-komprimerat)</comment>
+ <comment xml:lang="sr">ПДФ документ (запакован лзип-ом)</comment>
+ <comment xml:lang="sq">dokument PDF (ngjeshur me lzip)</comment>
+ <comment xml:lang="sl">Dokument PDF (stisnjen, lzip)</comment>
+ <comment xml:lang="si">PDF ලේඛනය (lzip-compressed)</comment>
+ <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou lzip)</comment>
+ <comment xml:lang="ru">Документ PDF (сжатый lzip)</comment>
+ <comment xml:lang="pt_BR">Documento PDF (compactado com lzip)</comment>
+ <comment xml:lang="pl">Dokument PDF (kompresja lzip)</comment>
+ <comment xml:lang="oc">document PDF (compressat amb lzip)</comment>
+ <comment xml:lang="nl">PDF-document (gecomprimeerd met lzip)</comment>
+ <comment xml:lang="ko">PDF 문서(LZIP 압축)</comment>
+ <comment xml:lang="kk">PDF құжаты (lzip-пен сығылған)</comment>
+ <comment xml:lang="ja">PDF ドキュメント (lzip 圧縮)</comment>
+ <comment xml:lang="it">Documento PDF (compresso con lzip)</comment>
+ <comment xml:lang="is">PDF skjal (lzip-þjappað)</comment>
+ <comment xml:lang="id">Dokumen PDF (termkompresi lzip)</comment>
+ <comment xml:lang="hu">PDF dokumentum (lzip tömörítésű)</comment>
+ <comment xml:lang="hr">PDF dokument (lzip sažeto)</comment>
+ <comment xml:lang="he">מסמך PDF (דחוס ב־lzip)</comment>
+ <comment xml:lang="ga">cáipéis PDF (comhbhrúite le lzip)</comment>
+ <comment xml:lang="fur">document PDF (comprimût cun lzip)</comment>
+ <comment xml:lang="fr">document PDF (compressé lzip)</comment>
+ <comment xml:lang="fi">PDF-asiakirja (lzip-pakattu)</comment>
+ <comment xml:lang="eu">PDF dokumentua (lzip-rekin konprimitua)</comment>
+ <comment xml:lang="es">documento PDF (comprimido con LZIP)</comment>
+ <comment xml:lang="en_GB">PDF document (lzip-compressed)</comment>
+ <comment xml:lang="de">PDF-Dokument (lzip-komprimiert)</comment>
+ <comment xml:lang="da">PDF-dokument (lzip-komprimeret)</comment>
+ <comment xml:lang="cs">dokument PDF (komprimace lzip)</comment>
+ <comment xml:lang="ca">document PDF (amb compressió lzip)</comment>
+ <comment xml:lang="bg">Документ — PDF, компресиран с Lzip</comment>
+ <comment xml:lang="be">дакумент PDF (сцісканне lzip)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en lzip)</comment>
+ <comment xml:lang="ar">مستند PDF (مضغوط-lzip)</comment>
+ <comment xml:lang="af">PDF-dokument (lzip-saamgepers)</comment>
<sub-class-of type="application/x-lzip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.pdf.lz"/>
</mime-type>
<mime-type type="application/x-lzma">
<comment>LZMA archive</comment>
- <comment xml:lang="ar">أرشيف LZMA</comment>
- <comment xml:lang="be@latin">Archiŭ LZMA</comment>
- <comment xml:lang="bg">Архив — LZMA</comment>
- <comment xml:lang="ca">arxiu LZMA</comment>
- <comment xml:lang="cs">archiv LZMA</comment>
- <comment xml:lang="da">LZHA-arkiv</comment>
- <comment xml:lang="de">LZMA-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο LZMA</comment>
- <comment xml:lang="en_GB">LZMA archive</comment>
- <comment xml:lang="eo">LZMA-arkivo</comment>
- <comment xml:lang="es">archivador LZMA</comment>
- <comment xml:lang="eu">LZMA artxiboa</comment>
- <comment xml:lang="fi">LZMA-arkisto</comment>
- <comment xml:lang="fo">LZMA skjalasavn</comment>
- <comment xml:lang="fr">archive LZMA</comment>
- <comment xml:lang="ga">cartlann LZMA</comment>
- <comment xml:lang="gl">arquivo LZMA</comment>
- <comment xml:lang="he">ארכיון LZMA</comment>
- <comment xml:lang="hr">LZMA arhiva</comment>
- <comment xml:lang="hu">LZMA-archívum</comment>
- <comment xml:lang="ia">Archivo LZMA</comment>
- <comment xml:lang="id">Arsip LZMA</comment>
- <comment xml:lang="it">Archivio LZMA</comment>
- <comment xml:lang="ja">LZMA アーカイブ</comment>
- <comment xml:lang="kk">LZMA архиві</comment>
- <comment xml:lang="ko">LZMA 압축 파일</comment>
- <comment xml:lang="lt">LZMA archyvas</comment>
- <comment xml:lang="lv">LZMA arhīvs</comment>
- <comment xml:lang="nb">LZMA-arkiv</comment>
- <comment xml:lang="nl">LZMA-archief</comment>
- <comment xml:lang="nn">LZMA-arkiv</comment>
- <comment xml:lang="oc">archiu LZMA</comment>
- <comment xml:lang="pl">Archiwum LZMA</comment>
- <comment xml:lang="pt">arquivo LZMA</comment>
- <comment xml:lang="pt_BR">Pacote LZMA</comment>
- <comment xml:lang="ro">Arhivă LZMA</comment>
- <comment xml:lang="ru">Архив LZMA</comment>
- <comment xml:lang="sk">Archív LZMA</comment>
- <comment xml:lang="sl">Datoteka arhiva LZMA</comment>
- <comment xml:lang="sq">Arkiv LZMA</comment>
- <comment xml:lang="sr">ЛЗМА архива</comment>
- <comment xml:lang="sv">LZMA-arkiv</comment>
- <comment xml:lang="tr">LZMA arşivi</comment>
- <comment xml:lang="uk">архів LZMA</comment>
- <comment xml:lang="vi">Kho nén LZMA</comment>
- <comment xml:lang="zh_CN">LZMA 归档文件</comment>
<comment xml:lang="zh_TW">LZMA 封存檔</comment>
+ <comment xml:lang="zh_CN">LZMA 归档文件</comment>
+ <comment xml:lang="vi">Kho nén LZMA</comment>
+ <comment xml:lang="uk">архів LZMA</comment>
+ <comment xml:lang="tr">LZMA arşivi</comment>
+ <comment xml:lang="sv">LZMA-arkiv</comment>
+ <comment xml:lang="sr">ЛЗМА архива</comment>
+ <comment xml:lang="sq">arkiv LZMA</comment>
+ <comment xml:lang="sl">Datoteka arhiva LZMA</comment>
+ <comment xml:lang="si">LZMA ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív LZMA</comment>
+ <comment xml:lang="ru">Архив LZMA</comment>
+ <comment xml:lang="ro">Arhivă LZMA</comment>
+ <comment xml:lang="pt_BR">Pacote LZMA</comment>
+ <comment xml:lang="pt">arquivo LZMA</comment>
+ <comment xml:lang="pl">Archiwum LZMA</comment>
+ <comment xml:lang="oc">archiu LZMA</comment>
+ <comment xml:lang="nn">LZMA-arkiv</comment>
+ <comment xml:lang="nl">LZMA-archief</comment>
+ <comment xml:lang="nb">LZMA-arkiv</comment>
+ <comment xml:lang="lv">LZMA arhīvs</comment>
+ <comment xml:lang="lt">LZMA archyvas</comment>
+ <comment xml:lang="ko">LZMA 압축 파일</comment>
+ <comment xml:lang="kk">LZMA архиві</comment>
+ <comment xml:lang="ja">LZMA アーカイブ</comment>
+ <comment xml:lang="it">Archivio LZMA</comment>
+ <comment xml:lang="is">LZMA safnskrá</comment>
+ <comment xml:lang="id">Arsip LZMA</comment>
+ <comment xml:lang="ia">Archivo LZMA</comment>
+ <comment xml:lang="hu">LZMA-archívum</comment>
+ <comment xml:lang="hr">LZMA arhiva</comment>
+ <comment xml:lang="he">ארכיון LZMA</comment>
+ <comment xml:lang="gl">arquivo LZMA</comment>
+ <comment xml:lang="ga">cartlann LZMA</comment>
+ <comment xml:lang="fur">archivi LZMA</comment>
+ <comment xml:lang="fr">archive LZMA</comment>
+ <comment xml:lang="fo">LZMA skjalasavn</comment>
+ <comment xml:lang="fi">LZMA-arkisto</comment>
+ <comment xml:lang="eu">LZMA artxiboa</comment>
+ <comment xml:lang="es">archivador LZMA</comment>
+ <comment xml:lang="eo">LZMA-arkivo</comment>
+ <comment xml:lang="en_GB">LZMA archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο LZMA</comment>
+ <comment xml:lang="de">LZMA-Archiv</comment>
+ <comment xml:lang="da">LZHA-arkiv</comment>
+ <comment xml:lang="cs">archiv LZMA</comment>
+ <comment xml:lang="ca">arxiu LZMA</comment>
+ <comment xml:lang="bg">Архив — LZMA</comment>
+ <comment xml:lang="be@latin">Archiŭ LZMA</comment>
+ <comment xml:lang="be">архіў LZMA</comment>
+ <comment xml:lang="ar">أرشيف LZMA</comment>
+ <comment xml:lang="af">LZMA-argief</comment>
<acronym>LZMA</acronym>
<expanded-acronym>Lempel-Ziv-Markov chain-Algorithm</expanded-acronym>
<generic-icon name="package-x-generic"/>
@@ -15186,52 +16513,57 @@
</mime-type>
<mime-type type="application/x-lzma-compressed-tar">
<comment>Tar archive (LZMA-compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط-LZMA)</comment>
- <comment xml:lang="be@latin">Archiŭ tar (LZMA-skampresavany)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран с LZMA</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió LZMA)</comment>
- <comment xml:lang="cs">archiv Tar (komprimace LZMA)</comment>
- <comment xml:lang="da">Tar-arkiv (LZMA-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (LZMA-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με LZMA)</comment>
- <comment xml:lang="en_GB">Tar archive (LZMA-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con LZMA)</comment>
- <comment xml:lang="eu">Tar artxiboa (LZMA-rekin konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (LZMA-pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn (LZMA-stappað)</comment>
- <comment xml:lang="fr">archive tar (compression LZMA)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZMA)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido con LZMA)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י LZMA)</comment>
- <comment xml:lang="hr">Tar arhiva (LZMA sažeta)</comment>
- <comment xml:lang="hu">Tar archívum (LZMA-val tömörítve)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite con LZMA)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi LZMA)</comment>
- <comment xml:lang="it">Archivio tar (compresso con LZMA)</comment>
- <comment xml:lang="ja">Tar アーカイブ (LZMA 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (LZMA-мен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(LZMA 압축)</comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas su LZMA)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests ar LZMA)</comment>
- <comment xml:lang="nb">Tar-arkiv (LZMA-komprimert)</comment>
- <comment xml:lang="nl">Tar-archief (ingepakt met LZMA)</comment>
- <comment xml:lang="nn">Tar-arkiv (pakka med LZMA)</comment>
- <comment xml:lang="oc">archiu tar (compression LZMA)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja LZMA)</comment>
- <comment xml:lang="pt">arquivo Tar (compressão LZMA)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado com LZMA)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată LZMA)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый lzma)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou LZMA)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z LZMA)</comment>
- <comment xml:lang="sq">Arkiv tar (i kompresuar me LZMA)</comment>
- <comment xml:lang="sr">Тар архива (запакована ЛЗМА-ом)</comment>
- <comment xml:lang="sv">Tar-arkiv (LZMA-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (LZMA ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений LZMA)</comment>
- <comment xml:lang="vi">Kho nén tar (đã nén LZMA)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (LZMA 壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(LZMA 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (LZMA 格式壓縮)</comment>
+ <comment xml:lang="vi">Kho nén tar (đã nén LZMA)</comment>
+ <comment xml:lang="uk">архів tar (стиснений LZMA)</comment>
+ <comment xml:lang="tr">Tar arşivi (LZMA ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (LZMA-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована ЛЗМА-ом)</comment>
+ <comment xml:lang="sq">arkiv Tar (ngjeshur me LZMA)</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z LZMA)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (LZMA-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou LZMA)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый lzma)</comment>
+ <comment xml:lang="ro">Arhivă Tar (comprimată LZMA)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado com LZMA)</comment>
+ <comment xml:lang="pt">arquivo Tar (compressão LZMA)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja LZMA)</comment>
+ <comment xml:lang="oc">archiu tar (compression LZMA)</comment>
+ <comment xml:lang="nn">Tar-arkiv (pakka med LZMA)</comment>
+ <comment xml:lang="nl">Tar-archief (gecomprimeerd met LZMA)</comment>
+ <comment xml:lang="nb">Tar-arkiv (LZMA-komprimert)</comment>
+ <comment xml:lang="lv">Tar arhīvs (saspiests ar LZMA)</comment>
+ <comment xml:lang="lt">Tar archyvas (suglaudintas su LZMA)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(LZMA 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (LZMA-мен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (LZMA 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con LZMA)</comment>
+ <comment xml:lang="is">Tar safnskrá (LZMA-þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi LZMA)</comment>
+ <comment xml:lang="ia">Archivo Tar (comprimite con LZMA)</comment>
+ <comment xml:lang="hu">Tar archívum (LZMA tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (LZMA sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י LZMA)</comment>
+ <comment xml:lang="gl">arquivo Tar (comprimido con LZMA)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZMA)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun LZMA)</comment>
+ <comment xml:lang="fr">archive tar (compression LZMA)</comment>
+ <comment xml:lang="fo">Tar skjalasavn (LZMA-stappað)</comment>
+ <comment xml:lang="fi">Tar-arkisto (LZMA-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (LZMA-rekin konprimitua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con LZMA)</comment>
+ <comment xml:lang="en_GB">Tar archive (LZMA-compressed)</comment>
+ <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με LZMA)</comment>
+ <comment xml:lang="de">Tar-Archiv (LZMA-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (LZMA-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimace LZMA)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió LZMA)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с LZMA</comment>
+ <comment xml:lang="be@latin">Archiŭ tar (LZMA-skampresavany)</comment>
+ <comment xml:lang="be">архіў tar (сцісканне LZMA)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-LZMA)</comment>
+ <comment xml:lang="af">Tar-argief (LZMA-saamgepers)</comment>
<sub-class-of type="application/x-lzma"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.tar.lzma"/>
@@ -15239,637 +16571,732 @@
</mime-type>
<mime-type type="application/x-lzop">
<comment>LZO archive</comment>
- <comment xml:lang="ar">أرشيف LZO</comment>
- <comment xml:lang="be@latin">Archiŭ LZO</comment>
- <comment xml:lang="bg">Архив — LZO</comment>
- <comment xml:lang="ca">arxiu LZO</comment>
- <comment xml:lang="cs">archiv LZO</comment>
- <comment xml:lang="da">LZO-arkiv</comment>
- <comment xml:lang="de">LZO-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο LZO</comment>
- <comment xml:lang="en_GB">LZO archive</comment>
- <comment xml:lang="eo">LZO-arkivo</comment>
- <comment xml:lang="es">archivador LZO</comment>
- <comment xml:lang="eu">LZO artxiboa</comment>
- <comment xml:lang="fi">LZO-arkisto</comment>
- <comment xml:lang="fo">LZO skjalasavn</comment>
- <comment xml:lang="fr">archive LZO</comment>
- <comment xml:lang="ga">cartlann LZO</comment>
- <comment xml:lang="gl">arquivo LZO</comment>
- <comment xml:lang="he">ארכיון LZO</comment>
- <comment xml:lang="hr">LZO arhiva</comment>
- <comment xml:lang="hu">LZO-archívum</comment>
- <comment xml:lang="ia">Archivo LZO</comment>
- <comment xml:lang="id">Arsip LZO</comment>
- <comment xml:lang="it">Archivio LZO</comment>
- <comment xml:lang="ja">LZO アーカイブ</comment>
- <comment xml:lang="kk">LZO архиві</comment>
- <comment xml:lang="ko">LZO 압축 파일</comment>
- <comment xml:lang="lt">LZO archyvas</comment>
- <comment xml:lang="lv">LZO arhīvs</comment>
- <comment xml:lang="ms">Arkib LZO</comment>
- <comment xml:lang="nb">LZO-arkiv</comment>
- <comment xml:lang="nl">LZO-archief</comment>
- <comment xml:lang="nn">LZO-arkiv</comment>
- <comment xml:lang="oc">archiu LZO</comment>
- <comment xml:lang="pl">Archiwum LZO</comment>
- <comment xml:lang="pt">arquivo LZO</comment>
- <comment xml:lang="pt_BR">Pacote LZO</comment>
- <comment xml:lang="ro">Arhivă LZO</comment>
- <comment xml:lang="ru">Архив LZO</comment>
- <comment xml:lang="sk">Archív LZO</comment>
- <comment xml:lang="sl">Datoteka arhiva LZO</comment>
- <comment xml:lang="sq">Arkiv LZO</comment>
- <comment xml:lang="sr">ЛЗО архива</comment>
- <comment xml:lang="sv">LZO-arkiv</comment>
- <comment xml:lang="tr">LZO arşivi</comment>
- <comment xml:lang="uk">архів LZO</comment>
- <comment xml:lang="vi">Kho nén LZO</comment>
- <comment xml:lang="zh_CN">LZO 归档文件</comment>
<comment xml:lang="zh_TW">LZO 封存檔</comment>
+ <comment xml:lang="zh_CN">LZO 归档文件</comment>
+ <comment xml:lang="vi">Kho nén LZO</comment>
+ <comment xml:lang="uk">архів LZO</comment>
+ <comment xml:lang="tr">LZO arşivi</comment>
+ <comment xml:lang="sv">LZO-arkiv</comment>
+ <comment xml:lang="sr">ЛЗО архива</comment>
+ <comment xml:lang="sq">arkiv LZO</comment>
+ <comment xml:lang="sl">Datoteka arhiva LZO</comment>
+ <comment xml:lang="si">LZO ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív LZO</comment>
+ <comment xml:lang="ru">Архив LZO</comment>
+ <comment xml:lang="ro">Arhivă LZO</comment>
+ <comment xml:lang="pt_BR">Pacote LZO</comment>
+ <comment xml:lang="pt">arquivo LZO</comment>
+ <comment xml:lang="pl">Archiwum LZO</comment>
+ <comment xml:lang="oc">archiu LZO</comment>
+ <comment xml:lang="nn">LZO-arkiv</comment>
+ <comment xml:lang="nl">LZO-archief</comment>
+ <comment xml:lang="nb">LZO-arkiv</comment>
+ <comment xml:lang="ms">Arkib LZO</comment>
+ <comment xml:lang="lv">LZO arhīvs</comment>
+ <comment xml:lang="lt">LZO archyvas</comment>
+ <comment xml:lang="ko">LZO 압축 파일</comment>
+ <comment xml:lang="kk">LZO архиві</comment>
+ <comment xml:lang="ja">LZO アーカイブ</comment>
+ <comment xml:lang="it">Archivio LZO</comment>
+ <comment xml:lang="is">LZO safnskrá</comment>
+ <comment xml:lang="id">Arsip LZO</comment>
+ <comment xml:lang="ia">Archivo LZO</comment>
+ <comment xml:lang="hu">LZO-archívum</comment>
+ <comment xml:lang="hr">LZO arhiva</comment>
+ <comment xml:lang="he">ארכיון LZO</comment>
+ <comment xml:lang="gl">arquivo LZO</comment>
+ <comment xml:lang="ga">cartlann LZO</comment>
+ <comment xml:lang="fur">archivi LZO</comment>
+ <comment xml:lang="fr">archive LZO</comment>
+ <comment xml:lang="fo">LZO skjalasavn</comment>
+ <comment xml:lang="fi">LZO-arkisto</comment>
+ <comment xml:lang="eu">LZO artxiboa</comment>
+ <comment xml:lang="es">archivador LZO</comment>
+ <comment xml:lang="eo">LZO-arkivo</comment>
+ <comment xml:lang="en_GB">LZO archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο LZO</comment>
+ <comment xml:lang="de">LZO-Archiv</comment>
+ <comment xml:lang="da">LZO-arkiv</comment>
+ <comment xml:lang="cs">archiv LZO</comment>
+ <comment xml:lang="ca">arxiu LZO</comment>
+ <comment xml:lang="bg">Архив — LZO</comment>
+ <comment xml:lang="be@latin">Archiŭ LZO</comment>
+ <comment xml:lang="be">архіў LZO</comment>
+ <comment xml:lang="ar">أرشيف LZO</comment>
+ <comment xml:lang="af">LZO-argief</comment>
<acronym>LZO</acronym>
<expanded-acronym>Lempel-Ziv-Oberhumer</expanded-acronym>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" type="string" offset="0"/>
+ <match type="string" value="\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" offset="0"/>
</magic>
<glob pattern="*.lzo"/>
</mime-type>
<mime-type type="application/x-qpress">
<comment>Qpress archive</comment>
- <comment xml:lang="ca">arxiu Qpress</comment>
- <comment xml:lang="cs">archiv Qpress</comment>
- <comment xml:lang="da">Qpress-arkiv</comment>
- <comment xml:lang="de">Qpress-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Qpress</comment>
- <comment xml:lang="en_GB">Qpress archive</comment>
- <comment xml:lang="es">archivador de Qpress</comment>
- <comment xml:lang="fi">Qpress-arkisto</comment>
- <comment xml:lang="fr">Archive Qpress</comment>
- <comment xml:lang="ga">cartlann Qpress</comment>
- <comment xml:lang="gl">Arquivo Qpress</comment>
- <comment xml:lang="he">ארכיון Qpress</comment>
- <comment xml:lang="hr">Qpress arhiva</comment>
- <comment xml:lang="hu">Qpress archívum</comment>
- <comment xml:lang="ia">Archivo Qpress</comment>
- <comment xml:lang="id">Arsip Qpress</comment>
- <comment xml:lang="it">Archivio Qpress</comment>
- <comment xml:lang="kk">Qpress архиві</comment>
- <comment xml:lang="ko">Qpress 압축 파일</comment>
- <comment xml:lang="oc">Archiu Qpress</comment>
- <comment xml:lang="pl">Archiwum Qpress</comment>
- <comment xml:lang="pt">arquivo Qpress</comment>
- <comment xml:lang="pt_BR">Pacote Qpress</comment>
- <comment xml:lang="ru">Архив Qpress</comment>
- <comment xml:lang="sk">Archív Qpress</comment>
- <comment xml:lang="sl">Datoteka arhiva Qpress</comment>
- <comment xml:lang="sr">Купрес архива</comment>
- <comment xml:lang="sv">Qpress-arkiv</comment>
- <comment xml:lang="tr">Qpress arşivi</comment>
- <comment xml:lang="uk">архів Qpress</comment>
- <comment xml:lang="zh_CN">Qpress 归档文件</comment>
<comment xml:lang="zh_TW">Qpress 封存檔</comment>
+ <comment xml:lang="zh_CN">Qpress 归档文件</comment>
+ <comment xml:lang="uk">архів Qpress</comment>
+ <comment xml:lang="tr">Qpress arşivi</comment>
+ <comment xml:lang="sv">Qpress-arkiv</comment>
+ <comment xml:lang="sr">Купрес архива</comment>
+ <comment xml:lang="sq">arkiv Qpress</comment>
+ <comment xml:lang="sl">Datoteka arhiva Qpress</comment>
+ <comment xml:lang="si">Qpress සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Qpress</comment>
+ <comment xml:lang="ru">Архив Qpress</comment>
+ <comment xml:lang="pt_BR">Pacote Qpress</comment>
+ <comment xml:lang="pt">arquivo Qpress</comment>
+ <comment xml:lang="pl">Archiwum Qpress</comment>
+ <comment xml:lang="oc">Archiu Qpress</comment>
+ <comment xml:lang="nl">Qpress-archief</comment>
+ <comment xml:lang="ko">Qpress 압축 파일</comment>
+ <comment xml:lang="kk">Qpress архиві</comment>
+ <comment xml:lang="ja">Qpress アーカイブ</comment>
+ <comment xml:lang="it">Archivio Qpress</comment>
+ <comment xml:lang="is">Qpress safnskrá</comment>
+ <comment xml:lang="id">Arsip Qpress</comment>
+ <comment xml:lang="ia">Archivo Qpress</comment>
+ <comment xml:lang="hu">Qpress archívum</comment>
+ <comment xml:lang="hr">Qpress arhiva</comment>
+ <comment xml:lang="he">ארכיון Qpress</comment>
+ <comment xml:lang="gl">Arquivo Qpress</comment>
+ <comment xml:lang="ga">cartlann Qpress</comment>
+ <comment xml:lang="fur">archivi Qpress</comment>
+ <comment xml:lang="fr">Archive Qpress</comment>
+ <comment xml:lang="fi">Qpress-arkisto</comment>
+ <comment xml:lang="eu">Qpress artxiboa</comment>
+ <comment xml:lang="es">archivador de Qpress</comment>
+ <comment xml:lang="en_GB">Qpress archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Qpress</comment>
+ <comment xml:lang="de">Qpress-Archiv</comment>
+ <comment xml:lang="da">Qpress-arkiv</comment>
+ <comment xml:lang="cs">archiv Qpress</comment>
+ <comment xml:lang="ca">arxiu Qpress</comment>
+ <comment xml:lang="bg">Архив — Qpress</comment>
+ <comment xml:lang="be">архіў Qpress</comment>
+ <comment xml:lang="ar">أرشيف Qpress</comment>
+ <comment xml:lang="af">Qpress-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="qpress10" type="string" offset="0"/>
+ <match type="string" value="qpress10" offset="0"/>
</magic>
<glob pattern="*.qp"/>
</mime-type>
<mime-type type="application/x-xar">
<comment>XAR archive</comment>
- <comment xml:lang="ca">arxiu XAR</comment>
- <comment xml:lang="cs">archiv XAR</comment>
- <comment xml:lang="da">XAR-arkiv</comment>
- <comment xml:lang="de">XAR-Archiv</comment>
- <comment xml:lang="en_GB">XAR archive</comment>
- <comment xml:lang="es">archivador XAR</comment>
- <comment xml:lang="eu">XAR artxiboa</comment>
- <comment xml:lang="fi">XAR-arkisto</comment>
- <comment xml:lang="fr">archive XAR</comment>
- <comment xml:lang="ga">cartlann XAR</comment>
- <comment xml:lang="he">ארכיון XAR</comment>
- <comment xml:lang="hr">XAR arhiva</comment>
- <comment xml:lang="hu">XAR archívum</comment>
- <comment xml:lang="id">Arsip XAR</comment>
- <comment xml:lang="it">Archivio XAR</comment>
- <comment xml:lang="kk">XAR архиві</comment>
- <comment xml:lang="ko">XAR 아카이브</comment>
- <comment xml:lang="oc">Archiu XAR</comment>
- <comment xml:lang="pl">Archiwum XAR</comment>
- <comment xml:lang="pt_BR">Arquivo XAR</comment>
- <comment xml:lang="ru">Архив XAR</comment>
- <comment xml:lang="sk">Archív XAR</comment>
- <comment xml:lang="sr">ИксАР архива</comment>
- <comment xml:lang="sv">XAR-arkiv</comment>
- <comment xml:lang="tr">XAR arşivi</comment>
- <comment xml:lang="uk">архів XAR</comment>
- <comment xml:lang="zh_CN">XAR 归档文件</comment>
<comment xml:lang="zh_TW">XAR 封存檔</comment>
+ <comment xml:lang="zh_CN">XAR 归档文件</comment>
+ <comment xml:lang="uk">архів XAR</comment>
+ <comment xml:lang="tr">XAR arşivi</comment>
+ <comment xml:lang="sv">XAR-arkiv</comment>
+ <comment xml:lang="sr">ИксАР архива</comment>
+ <comment xml:lang="sq">arkvi XAR</comment>
+ <comment xml:lang="sl">Arhiv XAR</comment>
+ <comment xml:lang="si">XAR ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív XAR</comment>
+ <comment xml:lang="ru">Архив XAR</comment>
+ <comment xml:lang="pt_BR">Arquivo XAR</comment>
+ <comment xml:lang="pl">Archiwum XAR</comment>
+ <comment xml:lang="oc">Archiu XAR</comment>
+ <comment xml:lang="nl">XAR-archief</comment>
+ <comment xml:lang="ko">XAR 압축 파일</comment>
+ <comment xml:lang="kk">XAR архиві</comment>
+ <comment xml:lang="ja">XAR アーカイブ</comment>
+ <comment xml:lang="it">Archivio XAR</comment>
+ <comment xml:lang="is">XAR safnskrá</comment>
+ <comment xml:lang="id">Arsip XAR</comment>
+ <comment xml:lang="hu">XAR archívum</comment>
+ <comment xml:lang="hr">XAR arhiva</comment>
+ <comment xml:lang="he">ארכיון XAR</comment>
+ <comment xml:lang="gl">Arquivo XAR</comment>
+ <comment xml:lang="ga">cartlann XAR</comment>
+ <comment xml:lang="fur">archivi XAR</comment>
+ <comment xml:lang="fr">archive XAR</comment>
+ <comment xml:lang="fi">XAR-arkisto</comment>
+ <comment xml:lang="eu">XAR artxiboa</comment>
+ <comment xml:lang="es">archivador XAR</comment>
+ <comment xml:lang="en_GB">XAR archive</comment>
+ <comment xml:lang="de">XAR-Archiv</comment>
+ <comment xml:lang="da">XAR-arkiv</comment>
+ <comment xml:lang="cs">archiv XAR</comment>
+ <comment xml:lang="ca">arxiu XAR</comment>
+ <comment xml:lang="bg">Архив — XAR</comment>
+ <comment xml:lang="be">архіў XAR</comment>
+ <comment xml:lang="ar">أرشيف XAR</comment>
+ <comment xml:lang="af">XAR-argief</comment>
<acronym>XAR</acronym>
<expanded-acronym>eXtensible ARchive</expanded-acronym>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="0x78617221" type="big32" offset="0"/>
+ <match type="big32" value="0x78617221" offset="0"/>
</magic>
<glob pattern="*.xar"/>
-
+ <!-- OS X 10.5+ installer package -->
<glob pattern="*.pkg"/>
</mime-type>
<mime-type type="application/zlib">
<comment>Zlib archive</comment>
- <comment xml:lang="ca">arxiu Zlib</comment>
- <comment xml:lang="cs">archiv Zlib</comment>
- <comment xml:lang="da">Zlib-arkiv</comment>
- <comment xml:lang="de">Zlib-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Zlib</comment>
- <comment xml:lang="en_GB">Zlib archive</comment>
- <comment xml:lang="es">archivador Zlib</comment>
- <comment xml:lang="fi">Zlib-arkisto</comment>
- <comment xml:lang="fr">Archive Zlib</comment>
- <comment xml:lang="ga">cartlann Zlib</comment>
- <comment xml:lang="gl">Arquivo Zlib</comment>
- <comment xml:lang="he">ארכיון Zlib</comment>
- <comment xml:lang="hr">Zlib arhiva</comment>
- <comment xml:lang="hu">Zlib archívum</comment>
- <comment xml:lang="ia">Archivo Zlib</comment>
- <comment xml:lang="id">Arsip Zlib</comment>
- <comment xml:lang="it">Archivio zlib</comment>
- <comment xml:lang="kk">Zlib архиві</comment>
- <comment xml:lang="ko">Zlib 압축 파일</comment>
- <comment xml:lang="oc">Archiu Zlib</comment>
- <comment xml:lang="pl">Archiwum Zlib</comment>
- <comment xml:lang="pt">arquivo Zlib</comment>
- <comment xml:lang="pt_BR">Pacote Zlib</comment>
- <comment xml:lang="ru">Архив Zlib</comment>
- <comment xml:lang="sk">Archív Zlib</comment>
- <comment xml:lang="sl">Datoteka arhiva Zlib</comment>
- <comment xml:lang="sr">Злиб архива</comment>
- <comment xml:lang="sv">Zlib-arkiv</comment>
- <comment xml:lang="tr">Zlib arşivi</comment>
- <comment xml:lang="uk">архів zlib</comment>
- <comment xml:lang="zh_CN">Alzip 归档文件</comment>
<comment xml:lang="zh_TW">Zlib 封存檔</comment>
+ <comment xml:lang="zh_CN">Alzip 归档文件</comment>
+ <comment xml:lang="uk">архів zlib</comment>
+ <comment xml:lang="tr">Zlib arşivi</comment>
+ <comment xml:lang="sv">Zlib-arkiv</comment>
+ <comment xml:lang="sr">Злиб архива</comment>
+ <comment xml:lang="sq">arkiv Zlib</comment>
+ <comment xml:lang="sl">Datoteka arhiva Zlib</comment>
+ <comment xml:lang="si">Zlib ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Zlib</comment>
+ <comment xml:lang="ru">Архив Zlib</comment>
+ <comment xml:lang="pt_BR">Pacote Zlib</comment>
+ <comment xml:lang="pt">arquivo Zlib</comment>
+ <comment xml:lang="pl">Archiwum Zlib</comment>
+ <comment xml:lang="oc">Archiu Zlib</comment>
+ <comment xml:lang="nl">Zlib-archief</comment>
+ <comment xml:lang="ko">Zlib 압축 파일</comment>
+ <comment xml:lang="kk">Zlib архиві</comment>
+ <comment xml:lang="ja">Zlib アーカイブ</comment>
+ <comment xml:lang="it">Archivio zlib</comment>
+ <comment xml:lang="is">Zlib safnskrá</comment>
+ <comment xml:lang="id">Arsip Zlib</comment>
+ <comment xml:lang="ia">Archivo Zlib</comment>
+ <comment xml:lang="hu">Zlib archívum</comment>
+ <comment xml:lang="hr">Zlib arhiva</comment>
+ <comment xml:lang="he">ארכיון Zlib</comment>
+ <comment xml:lang="gl">Arquivo Zlib</comment>
+ <comment xml:lang="ga">cartlann Zlib</comment>
+ <comment xml:lang="fur">archivi Zlib</comment>
+ <comment xml:lang="fr">Archive Zlib</comment>
+ <comment xml:lang="fi">Zlib-arkisto</comment>
+ <comment xml:lang="eu">Zlib artxiboa</comment>
+ <comment xml:lang="es">archivador Zlib</comment>
+ <comment xml:lang="en_GB">Zlib archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Zlib</comment>
+ <comment xml:lang="de">Zlib-Archiv</comment>
+ <comment xml:lang="da">Zlib-arkiv</comment>
+ <comment xml:lang="cs">archiv Zlib</comment>
+ <comment xml:lang="ca">arxiu Zlib</comment>
+ <comment xml:lang="bg">Архив — Zlib</comment>
+ <comment xml:lang="be">архіў Zlib</comment>
+ <comment xml:lang="ar">أرشيف Zlib</comment>
+ <comment xml:lang="af">Zlib-argief</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.zz"/>
</mime-type>
<mime-type type="application/x-magicpoint">
<comment>MagicPoint presentation</comment>
- <comment xml:lang="ar">عرض تقديمي MagicPoint</comment>
- <comment xml:lang="be@latin">Prezentacyja MagicPoint</comment>
- <comment xml:lang="bg">Презентация — MagicPoint</comment>
- <comment xml:lang="ca">presentació de MagicPoint</comment>
- <comment xml:lang="cs">prezentace MagicPoint</comment>
- <comment xml:lang="cy">Cyflwyniad MagicPoint</comment>
- <comment xml:lang="da">MagicPoint-præsentation</comment>
- <comment xml:lang="de">MagicPoint-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση MagicPoint</comment>
- <comment xml:lang="en_GB">MagicPoint presentation</comment>
- <comment xml:lang="eo">MagicPoint-prezentaĵo</comment>
- <comment xml:lang="es">presentación de MagicPoint</comment>
- <comment xml:lang="eu">MagicPoint aurkezpena</comment>
- <comment xml:lang="fi">MagicPoint-esitys</comment>
- <comment xml:lang="fo">MagicPoint framløga</comment>
- <comment xml:lang="fr">présentation MagicPoint</comment>
- <comment xml:lang="ga">láithreoireacht MagicPoint</comment>
- <comment xml:lang="gl">presentación de MagicPoint</comment>
- <comment xml:lang="he">מצגת MagicPoint</comment>
- <comment xml:lang="hr">MagicPoint prezentacija</comment>
- <comment xml:lang="hu">MagicPoint-bemutató</comment>
- <comment xml:lang="ia">Presentation MagicPoint</comment>
- <comment xml:lang="id">Presentasi MagicPoint</comment>
- <comment xml:lang="it">Presentazione MagicPoint</comment>
- <comment xml:lang="ja">MagicPoint プレゼンテーション</comment>
- <comment xml:lang="ka">MagicPoint-ის პრეზენტაცია</comment>
- <comment xml:lang="kk">MagicPoint презентациясы</comment>
- <comment xml:lang="ko">MagicPoint 프레젠테이션</comment>
- <comment xml:lang="lt">MagicPoint pateiktis</comment>
- <comment xml:lang="lv">MagicPoint prezentācija</comment>
- <comment xml:lang="ms">Persembahan MagicPoint</comment>
- <comment xml:lang="nb">MagicPoint-presentasjon</comment>
- <comment xml:lang="nl">MagicPoint-presentatie</comment>
- <comment xml:lang="nn">MagicPoint-presentasjon</comment>
- <comment xml:lang="oc">presentacion MagicPoint</comment>
- <comment xml:lang="pl">Prezentacja programu MagicPoint</comment>
- <comment xml:lang="pt">apresentação MagicPoint</comment>
- <comment xml:lang="pt_BR">Apresentação do MagicPoint</comment>
- <comment xml:lang="ro">Prezentare MagicPoint</comment>
- <comment xml:lang="ru">Презентация MagicPoint</comment>
- <comment xml:lang="sk">Prezentácia MagicPoint</comment>
- <comment xml:lang="sl">Predstavitev MagicPoint</comment>
- <comment xml:lang="sq">Prezantim MagicPoint</comment>
- <comment xml:lang="sr">презентација Меџик Поинта</comment>
- <comment xml:lang="sv">MagicPoint-presentation</comment>
- <comment xml:lang="tr">MagicPoint sunumu</comment>
- <comment xml:lang="uk">презентація MagicPoint</comment>
- <comment xml:lang="vi">Trình diễn MagicPoint</comment>
+ <comment xml:lang="zh_TW">MagicPoint 簡報</comment>
<comment xml:lang="zh_CN">MagicPoint 演示文稿</comment>
- <comment xml:lang="zh_TW">MagicPoint 簡報檔</comment>
+ <comment xml:lang="vi">Trình diễn MagicPoint</comment>
+ <comment xml:lang="uk">презентація MagicPoint</comment>
+ <comment xml:lang="tr">MagicPoint sunumu</comment>
+ <comment xml:lang="sv">MagicPoint-presentation</comment>
+ <comment xml:lang="sr">презентација Меџик Поинта</comment>
+ <comment xml:lang="sq">paraqitje MagicPoint</comment>
+ <comment xml:lang="sl">Predstavitev MagicPoint</comment>
+ <comment xml:lang="si">MagicPoint ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia MagicPoint</comment>
+ <comment xml:lang="ru">Презентация MagicPoint</comment>
+ <comment xml:lang="ro">Prezentare MagicPoint</comment>
+ <comment xml:lang="pt_BR">Apresentação do MagicPoint</comment>
+ <comment xml:lang="pt">apresentação MagicPoint</comment>
+ <comment xml:lang="pl">Prezentacja programu MagicPoint</comment>
+ <comment xml:lang="oc">presentacion MagicPoint</comment>
+ <comment xml:lang="nn">MagicPoint-presentasjon</comment>
+ <comment xml:lang="nl">MagicPoint-presentatie</comment>
+ <comment xml:lang="nb">MagicPoint-presentasjon</comment>
+ <comment xml:lang="ms">Persembahan MagicPoint</comment>
+ <comment xml:lang="lv">MagicPoint prezentācija</comment>
+ <comment xml:lang="lt">MagicPoint pateiktis</comment>
+ <comment xml:lang="ko">MagicPoint 프레젠테이션</comment>
+ <comment xml:lang="kk">MagicPoint презентациясы</comment>
+ <comment xml:lang="ka">MagicPoint-ის პრეზენტაცია</comment>
+ <comment xml:lang="ja">MagicPoint プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione MagicPoint</comment>
+ <comment xml:lang="is">MagicPoint framsetning</comment>
+ <comment xml:lang="id">Presentasi MagicPoint</comment>
+ <comment xml:lang="ia">Presentation MagicPoint</comment>
+ <comment xml:lang="hu">MagicPoint-bemutató</comment>
+ <comment xml:lang="hr">MagicPoint prezentacija</comment>
+ <comment xml:lang="he">מצגת MagicPoint</comment>
+ <comment xml:lang="gl">presentación de MagicPoint</comment>
+ <comment xml:lang="ga">láithreoireacht MagicPoint</comment>
+ <comment xml:lang="fur">presentazion MagicPoint</comment>
+ <comment xml:lang="fr">présentation MagicPoint</comment>
+ <comment xml:lang="fo">MagicPoint framløga</comment>
+ <comment xml:lang="fi">MagicPoint-esitys</comment>
+ <comment xml:lang="eu">MagicPoint aurkezpena</comment>
+ <comment xml:lang="es">presentación de MagicPoint</comment>
+ <comment xml:lang="eo">MagicPoint-prezentaĵo</comment>
+ <comment xml:lang="en_GB">MagicPoint presentation</comment>
+ <comment xml:lang="el">Παρουσίαση MagicPoint</comment>
+ <comment xml:lang="de">MagicPoint-Präsentation</comment>
+ <comment xml:lang="da">MagicPoint-præsentation</comment>
+ <comment xml:lang="cy">Cyflwyniad MagicPoint</comment>
+ <comment xml:lang="cs">prezentace MagicPoint</comment>
+ <comment xml:lang="ca">presentació de MagicPoint</comment>
+ <comment xml:lang="bg">Презентация — MagicPoint</comment>
+ <comment xml:lang="be@latin">Prezentacyja MagicPoint</comment>
+ <comment xml:lang="be">прэзентацыя MagicPoint</comment>
+ <comment xml:lang="ar">عرض تقديمي MagicPoint</comment>
+ <comment xml:lang="af">MagicPoint-voorlegging</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.mgp"/>
</mime-type>
<mime-type type="application/x-macbinary">
<comment>Macintosh MacBinary file</comment>
- <comment xml:lang="ar">ملف Macintosh MacBinary</comment>
- <comment xml:lang="be@latin">Fajł Macintosh MacBinary</comment>
- <comment xml:lang="bg">Файл — MacBinary</comment>
- <comment xml:lang="ca">fitxer MacBinary de Macintosh</comment>
- <comment xml:lang="cs">soubor MacBinary pro Macintosh </comment>
- <comment xml:lang="da">Macintosh MacBinary-fil</comment>
- <comment xml:lang="de">Macintosh-MacBinary-Datei</comment>
- <comment xml:lang="el">Εκτελέσιμο Macintosh MacBinary</comment>
- <comment xml:lang="en_GB">Macintosh MacBinary file</comment>
- <comment xml:lang="eo">MacBinary-dosiero de Macintosh</comment>
- <comment xml:lang="es">archivo de Macintosh MacBinary</comment>
- <comment xml:lang="eu">Macintosh MacBinary fitxategia</comment>
- <comment xml:lang="fi">Macintosh MacBinary -tiedosto</comment>
- <comment xml:lang="fo">Macintosh MacBinary fíla</comment>
- <comment xml:lang="fr">fichier Macintosh MacBinary</comment>
- <comment xml:lang="ga">comhad Macintosh MacBinary</comment>
- <comment xml:lang="gl">ficheiro MacBinary de Macintosh</comment>
- <comment xml:lang="he">קובץ בינרי של מקינטוש</comment>
- <comment xml:lang="hr">Macintosh MacBinary datoteka</comment>
- <comment xml:lang="hu">Macintosh MacBinary-fájl</comment>
- <comment xml:lang="ia">File MacBinary de Macintosh</comment>
- <comment xml:lang="id">Berkas Macintosh MacBinary</comment>
- <comment xml:lang="it">File Macintosh MacBinary</comment>
- <comment xml:lang="ja">Macintosh MacBinary ファイル</comment>
- <comment xml:lang="kk">Macintosh MacBinary файлы</comment>
- <comment xml:lang="ko">MacBinary 파일</comment>
- <comment xml:lang="lt">Macintosh MacBinary failas</comment>
- <comment xml:lang="lv">Macintosh MacBinary datne</comment>
- <comment xml:lang="ms">Fail MacBinary Macintosh</comment>
- <comment xml:lang="nb">Macintosh MacBinary-fil</comment>
- <comment xml:lang="nl">Macintosh MacBinary-bestand</comment>
- <comment xml:lang="nn">Macintosh MacBinary-fil</comment>
- <comment xml:lang="oc">fichièr Macintosh MacBinary</comment>
- <comment xml:lang="pl">Plik MacBinary Macintosh</comment>
- <comment xml:lang="pt">ficheiro MacBinary de Macintosh</comment>
- <comment xml:lang="pt_BR">Arquivo do Macintosh MacBinary</comment>
- <comment xml:lang="ro">Fișier Macintosh MacBinary</comment>
- <comment xml:lang="ru">Файл Macintosh MacBinary</comment>
- <comment xml:lang="sk">Súbor pre Macintosh MacBinary</comment>
- <comment xml:lang="sl">Izvedljiva dvojiška datoteka Macintosh MacBinary</comment>
- <comment xml:lang="sq">File MacBinary Macintosh</comment>
- <comment xml:lang="sr">Мекинтош Мек Бинари датотека</comment>
- <comment xml:lang="sv">Macintosh MacBinary-fil</comment>
- <comment xml:lang="tr">Macintosh MacBinary dosyası</comment>
- <comment xml:lang="uk">файл Macintosh MacBinary</comment>
- <comment xml:lang="vi">Tập tin nhị phân MacBinary của Macintosh</comment>
- <comment xml:lang="zh_CN">Macintosh MacBinary 文件</comment>
<comment xml:lang="zh_TW">Macintosh MacBinary 檔</comment>
+ <comment xml:lang="zh_CN">Macintosh MacBinary 文件</comment>
+ <comment xml:lang="vi">Tập tin nhị phân MacBinary của Macintosh</comment>
+ <comment xml:lang="uk">файл Macintosh MacBinary</comment>
+ <comment xml:lang="tr">Macintosh MacBinary dosyası</comment>
+ <comment xml:lang="sv">Macintosh MacBinary-fil</comment>
+ <comment xml:lang="sr">Мекинтош Мек Бинари датотека</comment>
+ <comment xml:lang="sq">kartelë MacBinary Macintosh</comment>
+ <comment xml:lang="sl">Izvedljiva dvojiška datoteka Macintosh MacBinary</comment>
+ <comment xml:lang="si">Macintosh MacBinary ගොනුව</comment>
+ <comment xml:lang="sk">Súbor pre Macintosh MacBinary</comment>
+ <comment xml:lang="ru">Файл Macintosh MacBinary</comment>
+ <comment xml:lang="ro">Fișier Macintosh MacBinary</comment>
+ <comment xml:lang="pt_BR">Arquivo do Macintosh MacBinary</comment>
+ <comment xml:lang="pt">ficheiro MacBinary de Macintosh</comment>
+ <comment xml:lang="pl">Plik MacBinary Macintosh</comment>
+ <comment xml:lang="oc">fichièr Macintosh MacBinary</comment>
+ <comment xml:lang="nn">Macintosh MacBinary-fil</comment>
+ <comment xml:lang="nl">Macintosh MacBinary-bestand</comment>
+ <comment xml:lang="nb">Macintosh MacBinary-fil</comment>
+ <comment xml:lang="ms">Fail MacBinary Macintosh</comment>
+ <comment xml:lang="lv">Macintosh MacBinary datne</comment>
+ <comment xml:lang="lt">Macintosh MacBinary failas</comment>
+ <comment xml:lang="ko">MacBinary 파일</comment>
+ <comment xml:lang="kk">Macintosh MacBinary файлы</comment>
+ <comment xml:lang="ja">Macintosh MacBinary ファイル</comment>
+ <comment xml:lang="it">File Macintosh MacBinary</comment>
+ <comment xml:lang="is">Macintosh MacBinary skrá</comment>
+ <comment xml:lang="id">Berkas Macintosh MacBinary</comment>
+ <comment xml:lang="ia">File MacBinary de Macintosh</comment>
+ <comment xml:lang="hu">Macintosh MacBinary-fájl</comment>
+ <comment xml:lang="hr">Macintosh MacBinary datoteka</comment>
+ <comment xml:lang="he">קובץ בינרי של מקינטוש</comment>
+ <comment xml:lang="gl">ficheiro MacBinary de Macintosh</comment>
+ <comment xml:lang="ga">comhad Macintosh MacBinary</comment>
+ <comment xml:lang="fur">file MacBinary di Macintosh</comment>
+ <comment xml:lang="fr">fichier Macintosh MacBinary</comment>
+ <comment xml:lang="fo">Macintosh MacBinary fíla</comment>
+ <comment xml:lang="fi">Macintosh MacBinary -tiedosto</comment>
+ <comment xml:lang="eu">Macintosh MacBinary fitxategia</comment>
+ <comment xml:lang="es">archivo de Macintosh MacBinary</comment>
+ <comment xml:lang="eo">MacBinary-dosiero de Macintosh</comment>
+ <comment xml:lang="en_GB">Macintosh MacBinary file</comment>
+ <comment xml:lang="el">Εκτελέσιμο Macintosh MacBinary</comment>
+ <comment xml:lang="de">Macintosh-MacBinary-Datei</comment>
+ <comment xml:lang="da">Macintosh MacBinary-fil</comment>
+ <comment xml:lang="cs">soubor MacBinary pro Macintosh </comment>
+ <comment xml:lang="ca">fitxer MacBinary de Macintosh</comment>
+ <comment xml:lang="bg">Файл — MacBinary</comment>
+ <comment xml:lang="be@latin">Fajł Macintosh MacBinary</comment>
+ <comment xml:lang="be">файл Macintosh MacBinary</comment>
+ <comment xml:lang="ar">ملف Macintosh MacBinary</comment>
+ <comment xml:lang="af">Macintosh MacBinary-lêer</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="mBIN" type="string" offset="102"/>
+ <magic>
+ <match type="string" value="mBIN" offset="102"/>
</magic>
</mime-type>
<mime-type type="application/x-matroska">
<comment>Matroska stream</comment>
- <comment xml:lang="ar">دفق Matroska</comment>
- <comment xml:lang="be@latin">Płyń Matroska</comment>
- <comment xml:lang="bg">Поток — Matroska</comment>
- <comment xml:lang="ca">flux Matroska</comment>
- <comment xml:lang="cs">proud Matroska</comment>
- <comment xml:lang="da">Matroskastrøm</comment>
- <comment xml:lang="de">Matroska-Datenstrom</comment>
- <comment xml:lang="el">Ροή Matroska</comment>
- <comment xml:lang="en_GB">Matroska stream</comment>
- <comment xml:lang="es">flujo Matroska</comment>
- <comment xml:lang="eu">Matroska korrontea</comment>
- <comment xml:lang="fi">Matroska-virta</comment>
- <comment xml:lang="fo">Matroska streymur</comment>
- <comment xml:lang="fr">flux Matroska</comment>
- <comment xml:lang="ga">sruth Matroska</comment>
- <comment xml:lang="gl">fluxo de Matroska</comment>
- <comment xml:lang="he">זרימת Matroska</comment>
- <comment xml:lang="hr">Matroška zapis</comment>
- <comment xml:lang="hu">Matroska adatfolyam</comment>
- <comment xml:lang="ia">Fluxo Matroska</comment>
- <comment xml:lang="id">Stream Matroska</comment>
- <comment xml:lang="it">Stream Matroska</comment>
- <comment xml:lang="ja">Matroska ストリーム</comment>
- <comment xml:lang="ka">Matroska-ის ნაკადი</comment>
- <comment xml:lang="kk">Matroska ағымы</comment>
- <comment xml:lang="ko">Matroska 스트림</comment>
- <comment xml:lang="lt">Matroska srautas</comment>
- <comment xml:lang="lv">Matroska straume</comment>
- <comment xml:lang="nl">Matroska-stream</comment>
- <comment xml:lang="nn">Matroska-straum</comment>
- <comment xml:lang="oc">flux Matroska</comment>
- <comment xml:lang="pl">Strumień Matroska</comment>
- <comment xml:lang="pt">fluxo Matroska</comment>
- <comment xml:lang="pt_BR">Transmissão do Matroska</comment>
- <comment xml:lang="ro">Flux Matroska</comment>
- <comment xml:lang="ru">Поток Matroska</comment>
- <comment xml:lang="sk">Stream Matroska</comment>
- <comment xml:lang="sl">Pretočni vir Matroska</comment>
- <comment xml:lang="sq">Stream Matroska</comment>
- <comment xml:lang="sr">Матрошкин ток</comment>
- <comment xml:lang="sv">Matroska-ström</comment>
- <comment xml:lang="tr">Matroska akışı</comment>
- <comment xml:lang="uk">потік даних Matroska</comment>
- <comment xml:lang="vi">Luồng Matroska</comment>
- <comment xml:lang="zh_CN">Matroska 流</comment>
<comment xml:lang="zh_TW">Matroska 串流</comment>
+ <comment xml:lang="zh_CN">Matroska 流</comment>
+ <comment xml:lang="vi">Luồng Matroska</comment>
+ <comment xml:lang="uk">потік даних Matroska</comment>
+ <comment xml:lang="tr">Matroska akışı</comment>
+ <comment xml:lang="sv">Matroska-ström</comment>
+ <comment xml:lang="sr">Матрошкин ток</comment>
+ <comment xml:lang="sq">rrjedhë Matroska</comment>
+ <comment xml:lang="sl">Pretočni vir Matroska</comment>
+ <comment xml:lang="si">Matroska ධාරාව</comment>
+ <comment xml:lang="sk">Stream Matroska</comment>
+ <comment xml:lang="ru">Поток Matroska</comment>
+ <comment xml:lang="ro">Flux Matroska</comment>
+ <comment xml:lang="pt_BR">Transmissão do Matroska</comment>
+ <comment xml:lang="pt">fluxo Matroska</comment>
+ <comment xml:lang="pl">Strumień Matroska</comment>
+ <comment xml:lang="oc">flux Matroska</comment>
+ <comment xml:lang="nn">Matroska-straum</comment>
+ <comment xml:lang="nl">Matroska-stream</comment>
+ <comment xml:lang="lv">Matroska straume</comment>
+ <comment xml:lang="lt">Matroska srautas</comment>
+ <comment xml:lang="ko">Matroska 스트림</comment>
+ <comment xml:lang="kk">Matroska ағымы</comment>
+ <comment xml:lang="ka">Matroska-ის ნაკადი</comment>
+ <comment xml:lang="ja">Matroska ストリーム</comment>
+ <comment xml:lang="it">Stream Matroska</comment>
+ <comment xml:lang="is">Matroska streymi</comment>
+ <comment xml:lang="id">Stream Matroska</comment>
+ <comment xml:lang="ia">Fluxo Matroska</comment>
+ <comment xml:lang="hu">Matroska adatfolyam</comment>
+ <comment xml:lang="hr">Matroška zapis</comment>
+ <comment xml:lang="he">זרימת Matroska</comment>
+ <comment xml:lang="gl">fluxo de Matroska</comment>
+ <comment xml:lang="ga">sruth Matroska</comment>
+ <comment xml:lang="fur">flus Matroska</comment>
+ <comment xml:lang="fr">flux Matroska</comment>
+ <comment xml:lang="fo">Matroska streymur</comment>
+ <comment xml:lang="fi">Matroska-virta</comment>
+ <comment xml:lang="eu">Matroska korrontea</comment>
+ <comment xml:lang="es">flujo Matroska</comment>
+ <comment xml:lang="en_GB">Matroska stream</comment>
+ <comment xml:lang="el">Ροή Matroska</comment>
+ <comment xml:lang="de">Matroska-Datenstrom</comment>
+ <comment xml:lang="da">Matroska-strøm</comment>
+ <comment xml:lang="cs">proud Matroska</comment>
+ <comment xml:lang="ca">flux Matroska</comment>
+ <comment xml:lang="bg">Поток — Matroska</comment>
+ <comment xml:lang="be@latin">Płyń Matroska</comment>
+ <comment xml:lang="be">плынь Matroska</comment>
+ <comment xml:lang="ar">دفق Matroska</comment>
+ <comment xml:lang="af">Matroska-stroom</comment>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
-
- <match value="0x1a45dfa3" type="big32" offset="0">
-
- <match value="0x4282" type="big16" offset="5:65">
-
- <match value="matroska" type="string" offset="8:75"/>
+ <magic>
+ <!-- EBML ID -->
+ <match type="big32" value="0x1a45dfa3" offset="0">
+ <!-- DocumentType ID -->
+ <match type="big16" value="0x4282" offset="5:65">
+ <!-- DocumentType -->
+ <match type="string" value="matroska" offset="8:75"/>
</match>
</match>
</magic>
</mime-type>
<mime-type type="video/x-matroska">
<comment>Matroska video</comment>
- <comment xml:lang="ar">Matroska مرئي</comment>
- <comment xml:lang="ast">Videu en Matroska</comment>
- <comment xml:lang="be@latin">Videa Matroska</comment>
- <comment xml:lang="bg">Видео — Matroska</comment>
- <comment xml:lang="ca">vídeo Matroska</comment>
- <comment xml:lang="cs">video Matroska</comment>
- <comment xml:lang="da">Matroskavideo</comment>
- <comment xml:lang="de">Matroska-Video</comment>
- <comment xml:lang="el">Βίντεο Matroska</comment>
- <comment xml:lang="en_GB">Matroska video</comment>
- <comment xml:lang="eo">Matroska-video</comment>
- <comment xml:lang="es">vídeo Matroska</comment>
- <comment xml:lang="eu">Matroska bideoa</comment>
- <comment xml:lang="fi">Matroska-video</comment>
- <comment xml:lang="fo">Matroska video</comment>
- <comment xml:lang="fr">vidéo Matroska</comment>
- <comment xml:lang="ga">físeán Matroska</comment>
- <comment xml:lang="gl">vídeo de Matroska</comment>
- <comment xml:lang="he">וידאו Matroska</comment>
- <comment xml:lang="hr">Matroška video snimka</comment>
- <comment xml:lang="hu">Matroska-videó</comment>
- <comment xml:lang="ia">Video Matroska</comment>
- <comment xml:lang="id">Video Matroska</comment>
- <comment xml:lang="it">Video Matroska</comment>
- <comment xml:lang="ja">Matroska 動画</comment>
- <comment xml:lang="ka">Matroska-ის ვიდეო</comment>
- <comment xml:lang="kk">Matroska видеосы</comment>
- <comment xml:lang="ko">Matroska 동영상</comment>
- <comment xml:lang="lt">Matroska vaizdo įrašas</comment>
- <comment xml:lang="lv">Matroska video</comment>
- <comment xml:lang="ms">Video Matroska</comment>
- <comment xml:lang="nb">Matroska-film</comment>
- <comment xml:lang="nl">Matroska-video</comment>
- <comment xml:lang="nn">Matroska-video</comment>
- <comment xml:lang="oc">vidèo Matroska</comment>
- <comment xml:lang="pl">Plik wideo Matroska</comment>
- <comment xml:lang="pt">vídeo Matroska</comment>
- <comment xml:lang="pt_BR">Vídeo Matroska</comment>
- <comment xml:lang="ro">Video Matroska</comment>
- <comment xml:lang="ru">Видео Matroska</comment>
- <comment xml:lang="sk">Video Matroska</comment>
- <comment xml:lang="sl">Video datoteka Matroska</comment>
- <comment xml:lang="sq">Video Matroska</comment>
- <comment xml:lang="sr">Матрошкин видео</comment>
- <comment xml:lang="sv">Matroska-video</comment>
- <comment xml:lang="tr">Matroska video</comment>
- <comment xml:lang="uk">відеокліп Matroska</comment>
- <comment xml:lang="vi">Ảnh động Matroska</comment>
- <comment xml:lang="zh_CN">Matroska 视频</comment>
<comment xml:lang="zh_TW">Matroska 視訊</comment>
+ <comment xml:lang="zh_CN">Matroska 视频</comment>
+ <comment xml:lang="vi">Ảnh động Matroska</comment>
+ <comment xml:lang="uk">відеокліп Matroska</comment>
+ <comment xml:lang="tr">Matroska video</comment>
+ <comment xml:lang="sv">Matroska-video</comment>
+ <comment xml:lang="sr">Матрошкин видео</comment>
+ <comment xml:lang="sq">video Matroska</comment>
+ <comment xml:lang="sl">Video datoteka Matroska</comment>
+ <comment xml:lang="si">Matroska වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Matroska</comment>
+ <comment xml:lang="ru">Видео Matroska</comment>
+ <comment xml:lang="ro">Video Matroska</comment>
+ <comment xml:lang="pt_BR">Vídeo Matroska</comment>
+ <comment xml:lang="pt">vídeo Matroska</comment>
+ <comment xml:lang="pl">Plik wideo Matroska</comment>
+ <comment xml:lang="oc">vidèo Matroska</comment>
+ <comment xml:lang="nn">Matroska-video</comment>
+ <comment xml:lang="nl">Matroska-video</comment>
+ <comment xml:lang="nb">Matroska-film</comment>
+ <comment xml:lang="ms">Video Matroska</comment>
+ <comment xml:lang="lv">Matroska video</comment>
+ <comment xml:lang="lt">Matroska vaizdo įrašas</comment>
+ <comment xml:lang="ko">Matroska 동영상</comment>
+ <comment xml:lang="kk">Matroska видеосы</comment>
+ <comment xml:lang="ka">Matroska-ის ვიდეო</comment>
+ <comment xml:lang="ja">Matroska 動画</comment>
+ <comment xml:lang="it">Video Matroska</comment>
+ <comment xml:lang="is">Matroska myndskeið</comment>
+ <comment xml:lang="id">Video Matroska</comment>
+ <comment xml:lang="ia">Video Matroska</comment>
+ <comment xml:lang="hu">Matroska-videó</comment>
+ <comment xml:lang="hr">Matroška video snimka</comment>
+ <comment xml:lang="he">וידאו Matroska</comment>
+ <comment xml:lang="gl">vídeo de Matroska</comment>
+ <comment xml:lang="ga">físeán Matroska</comment>
+ <comment xml:lang="fur">video Matroska</comment>
+ <comment xml:lang="fr">vidéo Matroska</comment>
+ <comment xml:lang="fo">Matroska video</comment>
+ <comment xml:lang="fi">Matroska-video</comment>
+ <comment xml:lang="eu">Matroska bideoa</comment>
+ <comment xml:lang="es">vídeo Matroska</comment>
+ <comment xml:lang="eo">Matroska-video</comment>
+ <comment xml:lang="en_GB">Matroska video</comment>
+ <comment xml:lang="el">Βίντεο Matroska</comment>
+ <comment xml:lang="de">Matroska-Video</comment>
+ <comment xml:lang="da">Matroska-video</comment>
+ <comment xml:lang="cs">video Matroska</comment>
+ <comment xml:lang="ca">vídeo Matroska</comment>
+ <comment xml:lang="bg">Видео — Matroska</comment>
+ <comment xml:lang="be@latin">Videa Matroska</comment>
+ <comment xml:lang="be">відэа Matroska</comment>
+ <comment xml:lang="ast">Videu en Matroska</comment>
+ <comment xml:lang="ar">فيديو Matroska</comment>
+ <comment xml:lang="af">Matroska-video</comment>
<glob pattern="*.mkv"/>
<sub-class-of type="application/x-matroska"/>
</mime-type>
<mime-type type="video/x-matroska-3d">
<comment>Matroska 3D video</comment>
- <comment xml:lang="ast">Videu en Matroska 3D</comment>
- <comment xml:lang="ca">vídeo Matroska 3D</comment>
- <comment xml:lang="cs">3D video Matroska</comment>
- <comment xml:lang="da">Matroska 3D-video</comment>
- <comment xml:lang="de">Matroska 3D-Video</comment>
- <comment xml:lang="el">Βίντεο 3Δ Matroska</comment>
- <comment xml:lang="en_GB">Matroska 3D video</comment>
- <comment xml:lang="es">vídeo Matroska en 3D</comment>
- <comment xml:lang="eu">Matroska 3D bideoa</comment>
- <comment xml:lang="fi">Matroska 3D-video</comment>
- <comment xml:lang="fr">vidéo Matroska 3D</comment>
- <comment xml:lang="ga">físeán Matroska 3D</comment>
- <comment xml:lang="gl">Video Matroska 3D</comment>
- <comment xml:lang="he">סרטון תלת ממדי מסוג Matroska</comment>
- <comment xml:lang="hr">Matroška 3D video snimka</comment>
- <comment xml:lang="hu">Matroska 3D videó</comment>
- <comment xml:lang="ia">Video 3D Matroska</comment>
- <comment xml:lang="id">Video 3D Matroska</comment>
- <comment xml:lang="it">Video Matroska 3D</comment>
- <comment xml:lang="kk">Matroska 3D видеосы</comment>
- <comment xml:lang="ko">Matroska 3D 동영상</comment>
- <comment xml:lang="oc">vidèo Matroska 3D</comment>
- <comment xml:lang="pl">Plik wideo Matroska 3D</comment>
- <comment xml:lang="pt">vídeo 3D Matroska</comment>
- <comment xml:lang="pt_BR">Vídeo 3D Matroska</comment>
- <comment xml:lang="ru">Видео Matroska 3D</comment>
- <comment xml:lang="sk">3D video Matroska</comment>
- <comment xml:lang="sl">Video datoteka Matroska 3D</comment>
- <comment xml:lang="sr">Матрошкин 3Д видео</comment>
- <comment xml:lang="sv">Matroska 3D-video</comment>
- <comment xml:lang="tr">Matroska 3B video</comment>
- <comment xml:lang="uk">відеокліп Matroska 3D</comment>
- <comment xml:lang="zh_CN">Matroska 3D 视频</comment>
<comment xml:lang="zh_TW">Matroska 3D 視訊</comment>
+ <comment xml:lang="zh_CN">Matroska 3D 视频</comment>
+ <comment xml:lang="uk">відеокліп Matroska 3D</comment>
+ <comment xml:lang="tr">Matroska 3B video</comment>
+ <comment xml:lang="sv">Matroska 3D-video</comment>
+ <comment xml:lang="sr">Матрошкин 3Д видео</comment>
+ <comment xml:lang="sq">video Matroska 3D</comment>
+ <comment xml:lang="sl">Video datoteka Matroska 3D</comment>
+ <comment xml:lang="si">Matroska 3D වීඩියෝ</comment>
+ <comment xml:lang="sk">3D video Matroska</comment>
+ <comment xml:lang="ru">Видео Matroska 3D</comment>
+ <comment xml:lang="pt_BR">Vídeo 3D Matroska</comment>
+ <comment xml:lang="pt">vídeo 3D Matroska</comment>
+ <comment xml:lang="pl">Plik wideo Matroska 3D</comment>
+ <comment xml:lang="oc">vidèo Matroska 3D</comment>
+ <comment xml:lang="nl">Matroska-3D-video</comment>
+ <comment xml:lang="ko">Matroska 3D 동영상</comment>
+ <comment xml:lang="kk">Matroska 3D видеосы</comment>
+ <comment xml:lang="ja">Matroska 3D ビデオ</comment>
+ <comment xml:lang="it">Video Matroska 3D</comment>
+ <comment xml:lang="is">Matroska 3D myndskeið</comment>
+ <comment xml:lang="id">Video 3D Matroska</comment>
+ <comment xml:lang="ia">Video 3D Matroska</comment>
+ <comment xml:lang="hu">Matroska 3D videó</comment>
+ <comment xml:lang="hr">Matroška 3D video snimka</comment>
+ <comment xml:lang="he">סרטון תלת ממדי מסוג Matroska</comment>
+ <comment xml:lang="gl">Video Matroska 3D</comment>
+ <comment xml:lang="ga">físeán Matroska 3D</comment>
+ <comment xml:lang="fur">video 3D Matroska</comment>
+ <comment xml:lang="fr">vidéo Matroska 3D</comment>
+ <comment xml:lang="fi">Matroska 3D-video</comment>
+ <comment xml:lang="eu">Matroska 3D bideoa</comment>
+ <comment xml:lang="es">vídeo Matroska en 3D</comment>
+ <comment xml:lang="en_GB">Matroska 3D video</comment>
+ <comment xml:lang="el">Βίντεο 3Δ Matroska</comment>
+ <comment xml:lang="de">Matroska-3D-Video</comment>
+ <comment xml:lang="da">Matroska 3D-video</comment>
+ <comment xml:lang="cs">3D video Matroska</comment>
+ <comment xml:lang="ca">vídeo Matroska 3D</comment>
+ <comment xml:lang="bg">Видео — Matroska 3D</comment>
+ <comment xml:lang="be">відэа Matroska 3D</comment>
+ <comment xml:lang="ast">Videu en Matroska 3D</comment>
+ <comment xml:lang="ar">فيديو Matroska 3D</comment>
+ <comment xml:lang="af">Matroska 3D video</comment>
<glob pattern="*.mk3d"/>
<sub-class-of type="application/x-matroska"/>
</mime-type>
<mime-type type="audio/x-matroska">
<comment>Matroska audio</comment>
- <comment xml:lang="ar">سمعي Matroska</comment>
- <comment xml:lang="be@latin">Aŭdyjo Matroska</comment>
- <comment xml:lang="bg">Аудио — Matroska</comment>
- <comment xml:lang="ca">àudio de Matroska</comment>
- <comment xml:lang="cs">zvuk Matroska</comment>
- <comment xml:lang="da">Matroskalyd</comment>
- <comment xml:lang="de">Matroska-Audio</comment>
- <comment xml:lang="el">Ήχος Matroska</comment>
- <comment xml:lang="en_GB">Matroska audio</comment>
- <comment xml:lang="eo">Matroska-sondosiero</comment>
- <comment xml:lang="es">sonido Matroska</comment>
- <comment xml:lang="eu">Matroska audioa</comment>
- <comment xml:lang="fi">Matroska-ääni</comment>
- <comment xml:lang="fo">Matroska ljóður</comment>
- <comment xml:lang="fr">audio Matroska</comment>
- <comment xml:lang="ga">fuaim Matroska</comment>
- <comment xml:lang="gl">son de Matroska</comment>
- <comment xml:lang="he">שמע Matroska</comment>
- <comment xml:lang="hr">Matroška zvučni zapis</comment>
- <comment xml:lang="hu">Matroska hang</comment>
- <comment xml:lang="ia">Audio Matroska</comment>
- <comment xml:lang="id">Audio Matroska</comment>
- <comment xml:lang="it">Audio Matroska</comment>
- <comment xml:lang="ja">Matroska オーディオ</comment>
- <comment xml:lang="ka">Matroska-ის აუდიო</comment>
- <comment xml:lang="kk">Matroska аудиосы</comment>
- <comment xml:lang="ko">Matroska 오디오</comment>
- <comment xml:lang="lt">Matroska garso įrašas</comment>
- <comment xml:lang="lv">Matroska audio</comment>
- <comment xml:lang="nb">Matroska-lyd</comment>
- <comment xml:lang="nl">Matroska-audio</comment>
- <comment xml:lang="nn">Matroska-lyd</comment>
- <comment xml:lang="oc">àudio Matroska</comment>
- <comment xml:lang="pl">Plik dźwiękowy Matroska</comment>
- <comment xml:lang="pt">áudio Matroska</comment>
- <comment xml:lang="pt_BR">Áudio Matroska</comment>
- <comment xml:lang="ro">Audio Matroska</comment>
- <comment xml:lang="ru">Аудио Matroska</comment>
- <comment xml:lang="sk">Zvuk Matroska</comment>
- <comment xml:lang="sl">Zvočna datoteka Matroska</comment>
- <comment xml:lang="sq">Audio Matroska</comment>
- <comment xml:lang="sr">Матрошкин звук</comment>
- <comment xml:lang="sv">Matroska-ljud</comment>
- <comment xml:lang="tr">Matroska ses</comment>
- <comment xml:lang="uk">звук Matroska</comment>
- <comment xml:lang="vi">Âm thanh Matroska</comment>
- <comment xml:lang="zh_CN">Matroska 音频</comment>
<comment xml:lang="zh_TW">Matroska 音訊</comment>
+ <comment xml:lang="zh_CN">Matroska 音频</comment>
+ <comment xml:lang="vi">Âm thanh Matroska</comment>
+ <comment xml:lang="uk">звук Matroska</comment>
+ <comment xml:lang="tr">Matroska ses</comment>
+ <comment xml:lang="sv">Matroska-ljud</comment>
+ <comment xml:lang="sr">Матрошкин звук</comment>
+ <comment xml:lang="sq">audio Matroska</comment>
+ <comment xml:lang="sl">Zvočna datoteka Matroska</comment>
+ <comment xml:lang="si">Matroska ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk Matroska</comment>
+ <comment xml:lang="ru">Аудио Matroska</comment>
+ <comment xml:lang="ro">Audio Matroska</comment>
+ <comment xml:lang="pt_BR">Áudio Matroska</comment>
+ <comment xml:lang="pt">áudio Matroska</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Matroska</comment>
+ <comment xml:lang="oc">àudio Matroska</comment>
+ <comment xml:lang="nn">Matroska-lyd</comment>
+ <comment xml:lang="nl">Matroska-audio</comment>
+ <comment xml:lang="nb">Matroska-lyd</comment>
+ <comment xml:lang="lv">Matroska audio</comment>
+ <comment xml:lang="lt">Matroska garso įrašas</comment>
+ <comment xml:lang="ko">Matroska 오디오</comment>
+ <comment xml:lang="kk">Matroska аудиосы</comment>
+ <comment xml:lang="ka">Matroska-ის აუდიო</comment>
+ <comment xml:lang="ja">Matroska オーディオ</comment>
+ <comment xml:lang="it">Audio Matroska</comment>
+ <comment xml:lang="is">Matroska hljóðskrá</comment>
+ <comment xml:lang="id">Audio Matroska</comment>
+ <comment xml:lang="ia">Audio Matroska</comment>
+ <comment xml:lang="hu">Matroska hang</comment>
+ <comment xml:lang="hr">Matroška zvučni zapis</comment>
+ <comment xml:lang="he">שמע Matroska</comment>
+ <comment xml:lang="gl">son de Matroska</comment>
+ <comment xml:lang="ga">fuaim Matroska</comment>
+ <comment xml:lang="fur">audio Matroska</comment>
+ <comment xml:lang="fr">audio Matroska</comment>
+ <comment xml:lang="fo">Matroska ljóður</comment>
+ <comment xml:lang="fi">Matroska-ääni</comment>
+ <comment xml:lang="eu">Matroska audioa</comment>
+ <comment xml:lang="es">sonido Matroska</comment>
+ <comment xml:lang="eo">Matroska-sondosiero</comment>
+ <comment xml:lang="en_GB">Matroska audio</comment>
+ <comment xml:lang="el">Ήχος Matroska</comment>
+ <comment xml:lang="de">Matroska-Audio</comment>
+ <comment xml:lang="da">Matroska-lyd</comment>
+ <comment xml:lang="cs">zvuk Matroska</comment>
+ <comment xml:lang="ca">àudio Matroska</comment>
+ <comment xml:lang="bg">Аудио — Matroska</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Matroska</comment>
+ <comment xml:lang="be">аўдыя Matroska</comment>
+ <comment xml:lang="ar">صوت Matroska</comment>
+ <comment xml:lang="af">Matroska-oudio</comment>
<glob pattern="*.mka"/>
<sub-class-of type="application/x-matroska"/>
</mime-type>
<mime-type type="video/webm">
<comment>WebM video</comment>
- <comment xml:lang="ar">WebM مرئي</comment>
- <comment xml:lang="ast">Videu en WebM</comment>
- <comment xml:lang="bg">Видео — WebM</comment>
- <comment xml:lang="ca">vídeo WebM</comment>
- <comment xml:lang="cs">video WebM</comment>
- <comment xml:lang="da">WebM-video</comment>
- <comment xml:lang="de">WebM-Video</comment>
- <comment xml:lang="el">Βίντεο WebM</comment>
- <comment xml:lang="en_GB">WebM video</comment>
- <comment xml:lang="eo">WebM-video</comment>
- <comment xml:lang="es">vídeo WebM</comment>
- <comment xml:lang="eu">WebM bideoa</comment>
- <comment xml:lang="fi">WebM-video</comment>
- <comment xml:lang="fo">WebM video</comment>
- <comment xml:lang="fr">vidéo WebM</comment>
- <comment xml:lang="ga">físeán WebM</comment>
- <comment xml:lang="gl">vídeo WebM</comment>
- <comment xml:lang="he">וידאו WebM</comment>
- <comment xml:lang="hr">WebM video snimka</comment>
- <comment xml:lang="hu">WebM videó</comment>
- <comment xml:lang="ia">Video WebM</comment>
- <comment xml:lang="id">Video WebM</comment>
- <comment xml:lang="it">Video WebM</comment>
- <comment xml:lang="ja">WebM 動画</comment>
- <comment xml:lang="kk">WebM видеосы</comment>
- <comment xml:lang="ko">WebM 동영상</comment>
- <comment xml:lang="lt">WebM vaizdo įrašas</comment>
- <comment xml:lang="lv">WebM video</comment>
- <comment xml:lang="nl">WebM video</comment>
- <comment xml:lang="oc">vidèo WebM</comment>
- <comment xml:lang="pl">Plik wideo WebM</comment>
- <comment xml:lang="pt">vídeo WebM</comment>
- <comment xml:lang="pt_BR">Vídeo WebM</comment>
- <comment xml:lang="ro">Video WebM</comment>
- <comment xml:lang="ru">Видео WebM</comment>
- <comment xml:lang="sk">Video WebM</comment>
- <comment xml:lang="sl">Video datoteka WebM</comment>
- <comment xml:lang="sr">ВебМ видео</comment>
- <comment xml:lang="sv">WebM-video</comment>
- <comment xml:lang="tr">WebM video</comment>
- <comment xml:lang="uk">відео WebM</comment>
- <comment xml:lang="zh_CN">WebM 视频</comment>
<comment xml:lang="zh_TW">WebM 視訊</comment>
+ <comment xml:lang="zh_CN">WebM 视频</comment>
+ <comment xml:lang="uk">відео WebM</comment>
+ <comment xml:lang="tr">WebM video</comment>
+ <comment xml:lang="sv">WebM-video</comment>
+ <comment xml:lang="sr">ВебМ видео</comment>
+ <comment xml:lang="sq">audio WebM</comment>
+ <comment xml:lang="sl">Video datoteka WebM</comment>
+ <comment xml:lang="si">WebM වීඩියෝව</comment>
+ <comment xml:lang="sk">Video WebM</comment>
+ <comment xml:lang="ru">Видео WebM</comment>
+ <comment xml:lang="ro">Video WebM</comment>
+ <comment xml:lang="pt_BR">Vídeo WebM</comment>
+ <comment xml:lang="pt">vídeo WebM</comment>
+ <comment xml:lang="pl">Plik wideo WebM</comment>
+ <comment xml:lang="oc">vidèo WebM</comment>
+ <comment xml:lang="nl">WebM-video</comment>
+ <comment xml:lang="lv">WebM video</comment>
+ <comment xml:lang="lt">WebM vaizdo įrašas</comment>
+ <comment xml:lang="ko">WebM 동영상</comment>
+ <comment xml:lang="kk">WebM видеосы</comment>
+ <comment xml:lang="ja">WebM 動画</comment>
+ <comment xml:lang="it">Video WebM</comment>
+ <comment xml:lang="is">WebM myndskeið</comment>
+ <comment xml:lang="id">Video WebM</comment>
+ <comment xml:lang="ia">Video WebM</comment>
+ <comment xml:lang="hu">WebM videó</comment>
+ <comment xml:lang="hr">WebM video snimka</comment>
+ <comment xml:lang="he">וידאו WebM</comment>
+ <comment xml:lang="gl">vídeo WebM</comment>
+ <comment xml:lang="ga">físeán WebM</comment>
+ <comment xml:lang="fur">video WebM</comment>
+ <comment xml:lang="fr">vidéo WebM</comment>
+ <comment xml:lang="fo">WebM video</comment>
+ <comment xml:lang="fi">WebM-video</comment>
+ <comment xml:lang="eu">WebM bideoa</comment>
+ <comment xml:lang="es">vídeo WebM</comment>
+ <comment xml:lang="eo">WebM-video</comment>
+ <comment xml:lang="en_GB">WebM video</comment>
+ <comment xml:lang="el">Βίντεο WebM</comment>
+ <comment xml:lang="de">WebM-Video</comment>
+ <comment xml:lang="da">WebM-video</comment>
+ <comment xml:lang="cs">video WebM</comment>
+ <comment xml:lang="ca">vídeo WebM</comment>
+ <comment xml:lang="bg">Видео — WebM</comment>
+ <comment xml:lang="be">відэа WebM</comment>
+ <comment xml:lang="ast">Videu en WebM</comment>
+ <comment xml:lang="ar">فيديو WebM</comment>
+ <comment xml:lang="af">WebM-video</comment>
<glob pattern="*.webm"/>
- <magic priority="50">
-
- <match value="0x1a45dfa3" type="big32" offset="0">
-
- <match value="0x4282" type="big16" offset="5:65">
-
- <match value="webm" type="string" offset="8:75"/>
+ <magic>
+ <!-- EBML ID -->
+ <match type="big32" value="0x1a45dfa3" offset="0">
+ <!-- DocumentType ID -->
+ <match type="big16" value="0x4282" offset="5:65">
+ <!-- DocumentType -->
+ <match type="string" value="webm" offset="8:75"/>
</match>
</match>
</magic>
</mime-type>
<mime-type type="audio/webm">
<comment>WebM audio</comment>
- <comment xml:lang="ar">WebM سمعي</comment>
- <comment xml:lang="bg">Аудио — WebM</comment>
- <comment xml:lang="ca">àudio de WebM</comment>
- <comment xml:lang="cs">zvuk WebM</comment>
- <comment xml:lang="da">WebM-lyd</comment>
- <comment xml:lang="de">WebM-Audio</comment>
- <comment xml:lang="el">Ήχος WebM</comment>
- <comment xml:lang="en_GB">WebM audio</comment>
- <comment xml:lang="eo">WebM-sondosiero</comment>
- <comment xml:lang="es">sonido WebM</comment>
- <comment xml:lang="eu">WebM audioa</comment>
- <comment xml:lang="fi">WebM-ääni</comment>
- <comment xml:lang="fo">WebM ljóður</comment>
- <comment xml:lang="fr">audio WebM</comment>
- <comment xml:lang="ga">fuaim WebM</comment>
- <comment xml:lang="gl">son WebM</comment>
- <comment xml:lang="he">שמע WebM</comment>
- <comment xml:lang="hr">WebM zvučni zapis</comment>
- <comment xml:lang="hu">WebM hang</comment>
- <comment xml:lang="ia">Audio WebM</comment>
- <comment xml:lang="id">Audio WebM</comment>
- <comment xml:lang="it">Audio WebM</comment>
- <comment xml:lang="ja">WebM オーディオ</comment>
- <comment xml:lang="kk">WebM аудиосы</comment>
- <comment xml:lang="ko">WebM 오디오</comment>
- <comment xml:lang="lt">WebM garso įrašas</comment>
- <comment xml:lang="lv">WebM audio</comment>
- <comment xml:lang="nl">WebM audio</comment>
- <comment xml:lang="oc">àudio WebM</comment>
- <comment xml:lang="pl">Plik dźwiękowy WebM</comment>
- <comment xml:lang="pt">áudio WebM</comment>
- <comment xml:lang="pt_BR">Áudio WebM</comment>
- <comment xml:lang="ro">Audio WebM</comment>
- <comment xml:lang="ru">Аудио WebM</comment>
- <comment xml:lang="sk">Zvuk WebM</comment>
- <comment xml:lang="sl">Zvočna datoteka WebM</comment>
- <comment xml:lang="sr">ВебМ звук</comment>
- <comment xml:lang="sv">WebM-ljud</comment>
- <comment xml:lang="tr">WebM sesi</comment>
- <comment xml:lang="uk">звук WebM</comment>
- <comment xml:lang="zh_CN">WebM 音频</comment>
<comment xml:lang="zh_TW">WebM 音訊</comment>
+ <comment xml:lang="zh_CN">WebM 音频</comment>
+ <comment xml:lang="uk">звук WebM</comment>
+ <comment xml:lang="tr">WebM sesi</comment>
+ <comment xml:lang="sv">WebM-ljud</comment>
+ <comment xml:lang="sr">ВебМ звук</comment>
+ <comment xml:lang="sq">audio WebM</comment>
+ <comment xml:lang="sl">Zvočna datoteka WebM</comment>
+ <comment xml:lang="si">WebM ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk WebM</comment>
+ <comment xml:lang="ru">Аудио WebM</comment>
+ <comment xml:lang="ro">Audio WebM</comment>
+ <comment xml:lang="pt_BR">Áudio WebM</comment>
+ <comment xml:lang="pt">áudio WebM</comment>
+ <comment xml:lang="pl">Plik dźwiękowy WebM</comment>
+ <comment xml:lang="oc">àudio WebM</comment>
+ <comment xml:lang="nl">WebM-audio</comment>
+ <comment xml:lang="lv">WebM audio</comment>
+ <comment xml:lang="lt">WebM garso įrašas</comment>
+ <comment xml:lang="ko">WebM 오디오</comment>
+ <comment xml:lang="kk">WebM аудиосы</comment>
+ <comment xml:lang="ja">WebM オーディオ</comment>
+ <comment xml:lang="it">Audio WebM</comment>
+ <comment xml:lang="is">WebM hljóðskrá</comment>
+ <comment xml:lang="id">Audio WebM</comment>
+ <comment xml:lang="ia">Audio WebM</comment>
+ <comment xml:lang="hu">WebM hang</comment>
+ <comment xml:lang="hr">WebM zvučni zapis</comment>
+ <comment xml:lang="he">שמע WebM</comment>
+ <comment xml:lang="gl">son WebM</comment>
+ <comment xml:lang="ga">fuaim WebM</comment>
+ <comment xml:lang="fur">audio WebM</comment>
+ <comment xml:lang="fr">audio WebM</comment>
+ <comment xml:lang="fo">WebM ljóður</comment>
+ <comment xml:lang="fi">WebM-ääni</comment>
+ <comment xml:lang="eu">WebM audioa</comment>
+ <comment xml:lang="es">sonido WebM</comment>
+ <comment xml:lang="eo">WebM-sondosiero</comment>
+ <comment xml:lang="en_GB">WebM audio</comment>
+ <comment xml:lang="el">Ήχος WebM</comment>
+ <comment xml:lang="de">WebM-Audio</comment>
+ <comment xml:lang="da">WebM-lyd</comment>
+ <comment xml:lang="cs">zvuk WebM</comment>
+ <comment xml:lang="ca">àudio WebM</comment>
+ <comment xml:lang="bg">Аудио — WebM</comment>
+ <comment xml:lang="be">аўдыя WebM</comment>
+ <comment xml:lang="ar">صوت WebM</comment>
+ <comment xml:lang="af">WebM-oudio</comment>
<sub-class-of type="video/webm"/>
</mime-type>
<mime-type type="application/x-mimearchive">
<comment>MHTML web archive</comment>
- <comment xml:lang="ca">arxiu web MHTML</comment>
- <comment xml:lang="cs">webový archiv MHTML</comment>
- <comment xml:lang="da">MHTML-netarkiv</comment>
- <comment xml:lang="de">MHTML-Webarchiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο ιστού MHTML</comment>
- <comment xml:lang="en_GB">MHTML web archive</comment>
- <comment xml:lang="es">archivador web MHTML</comment>
- <comment xml:lang="eu">MHTML web artxiboa</comment>
- <comment xml:lang="fi">MHTML-kooste</comment>
- <comment xml:lang="fr">archive web MHTML</comment>
- <comment xml:lang="ga">cartlann ghréasáin MHTML</comment>
- <comment xml:lang="gl">Arquivo web MHTML</comment>
- <comment xml:lang="he">ארכיון רשת MHTML</comment>
- <comment xml:lang="hr">MHTML web arhiva</comment>
- <comment xml:lang="hu">MHTML webarchívum</comment>
- <comment xml:lang="ia">Archivo web MHTML</comment>
- <comment xml:lang="id">Arsip web MHTML</comment>
- <comment xml:lang="it">Archivio web MHTML</comment>
- <comment xml:lang="ja">MHTML Web アーカイブ</comment>
- <comment xml:lang="kk">MHTML веб архиві</comment>
- <comment xml:lang="ko">MHTML 웹 보관 파일</comment>
- <comment xml:lang="lv">MHTML tīmekļa arhīvs</comment>
- <comment xml:lang="oc">archiu web MHTML</comment>
- <comment xml:lang="pl">Archiwum witryny MHTML</comment>
- <comment xml:lang="pt">arquivo web MHTML</comment>
- <comment xml:lang="pt_BR">Pacote web MHTML</comment>
- <comment xml:lang="ru">Веб-архив MHTML</comment>
- <comment xml:lang="sk">Webový archív MHTML</comment>
- <comment xml:lang="sl">Spletni arhiv MHTML</comment>
- <comment xml:lang="sr">МХТМЛ веб архива</comment>
- <comment xml:lang="sv">MHTML-webbarkiv</comment>
- <comment xml:lang="tr">MHTML web arşivi</comment>
- <comment xml:lang="uk">вебархів MHTML</comment>
- <comment xml:lang="zh_CN">MHTML 网络归档</comment>
<comment xml:lang="zh_TW">MHTML 網頁封存檔</comment>
+ <comment xml:lang="zh_CN">MHTML 网络归档</comment>
+ <comment xml:lang="uk">вебархів MHTML</comment>
+ <comment xml:lang="tr">MHTML web arşivi</comment>
+ <comment xml:lang="sv">MHTML-webbarkiv</comment>
+ <comment xml:lang="sr">МХТМЛ веб архива</comment>
+ <comment xml:lang="sq">arkiv web MHTML</comment>
+ <comment xml:lang="sl">Spletni arhiv MHTML</comment>
+ <comment xml:lang="si">MHTML වෙබ් සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Webový archív MHTML</comment>
+ <comment xml:lang="ru">Веб-архив MHTML</comment>
+ <comment xml:lang="pt_BR">Pacote web MHTML</comment>
+ <comment xml:lang="pt">arquivo web MHTML</comment>
+ <comment xml:lang="pl">Archiwum witryny MHTML</comment>
+ <comment xml:lang="oc">archiu web MHTML</comment>
+ <comment xml:lang="nl">MHTML-webarchief</comment>
+ <comment xml:lang="lv">MHTML tīmekļa arhīvs</comment>
+ <comment xml:lang="ko">MHTML 웹 보관 파일</comment>
+ <comment xml:lang="kk">MHTML веб архиві</comment>
+ <comment xml:lang="ja">MHTML Web アーカイブ</comment>
+ <comment xml:lang="it">Archivio web MHTML</comment>
+ <comment xml:lang="is">MHTML vefsafnskrá</comment>
+ <comment xml:lang="id">Arsip web MHTML</comment>
+ <comment xml:lang="ia">Archivo web MHTML</comment>
+ <comment xml:lang="hu">MHTML webarchívum</comment>
+ <comment xml:lang="hr">MHTML web arhiva</comment>
+ <comment xml:lang="he">ארכיון רשת MHTML</comment>
+ <comment xml:lang="gl">Arquivo web MHTML</comment>
+ <comment xml:lang="ga">cartlann ghréasáin MHTML</comment>
+ <comment xml:lang="fur">archivi web MHTML</comment>
+ <comment xml:lang="fr">archive web MHTML</comment>
+ <comment xml:lang="fi">MHTML-kooste</comment>
+ <comment xml:lang="eu">MHTML web artxiboa</comment>
+ <comment xml:lang="es">archivador web MHTML</comment>
+ <comment xml:lang="en_GB">MHTML web archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο ιστού MHTML</comment>
+ <comment xml:lang="de">MHTML-Webarchiv</comment>
+ <comment xml:lang="da">MHTML-webarkiv</comment>
+ <comment xml:lang="cs">webový archiv MHTML</comment>
+ <comment xml:lang="ca">arxiu web MHTML</comment>
+ <comment xml:lang="bg">Архив — MHTML</comment>
+ <comment xml:lang="be">вэб-архіў MHTML</comment>
+ <comment xml:lang="ar">أرشيف ويب MHTML</comment>
+ <comment xml:lang="af">MHTML-webargief</comment>
<acronym>MHTML</acronym>
<expanded-acronym>MIME HTML</expanded-acronym>
<glob pattern="*.mhtml"/>
@@ -15878,153 +17305,160 @@
</mime-type>
<mime-type type="application/mxf">
<comment>MXF video</comment>
- <comment xml:lang="ar">MXF مرئي</comment>
- <comment xml:lang="ast">Videu en MXF</comment>
- <comment xml:lang="bg">Видео — MXF</comment>
- <comment xml:lang="ca">vídeo MXF</comment>
- <comment xml:lang="cs">video MXF</comment>
- <comment xml:lang="da">MXF-video</comment>
- <comment xml:lang="de">MXF-Video</comment>
- <comment xml:lang="el">Βίντεο MXF</comment>
- <comment xml:lang="en_GB">MXF video</comment>
- <comment xml:lang="eo">MXF-video</comment>
- <comment xml:lang="es">vídeo MXF</comment>
- <comment xml:lang="eu">MXF bideoa</comment>
- <comment xml:lang="fi">MXF-video</comment>
- <comment xml:lang="fo">MXF video</comment>
- <comment xml:lang="fr">vidéo MXF</comment>
- <comment xml:lang="ga">físeán MXF</comment>
- <comment xml:lang="gl">vídeo MXF</comment>
- <comment xml:lang="he">וידאו MXF</comment>
- <comment xml:lang="hr">MXF video snimka</comment>
- <comment xml:lang="hu">MXF videó</comment>
- <comment xml:lang="ia">Video MXF</comment>
- <comment xml:lang="id">Video MXF</comment>
- <comment xml:lang="it">Video MXF</comment>
- <comment xml:lang="ja">MXF 動画</comment>
- <comment xml:lang="ka">MXF ვიდეო</comment>
- <comment xml:lang="kk">MXF видеосы</comment>
- <comment xml:lang="ko">MXF 동영상</comment>
- <comment xml:lang="lt">MXF vaizdo įrašas</comment>
- <comment xml:lang="lv">MXF video</comment>
- <comment xml:lang="nl">MXF video</comment>
- <comment xml:lang="oc">vidèo MXF</comment>
- <comment xml:lang="pl">Plik wideo MXF</comment>
- <comment xml:lang="pt">vídeo MXF</comment>
- <comment xml:lang="pt_BR">Vídeo MXF</comment>
- <comment xml:lang="ro">Video MXF</comment>
- <comment xml:lang="ru">Видео MXF</comment>
- <comment xml:lang="sk">Video MXF</comment>
- <comment xml:lang="sl">Video datoteka MXF</comment>
- <comment xml:lang="sr">МИксФ видео</comment>
- <comment xml:lang="sv">MXF-video</comment>
- <comment xml:lang="tr">MXF video</comment>
- <comment xml:lang="uk">відеокліп MXF</comment>
- <comment xml:lang="zh_CN">MXF 视频</comment>
<comment xml:lang="zh_TW">MXF 視訊</comment>
+ <comment xml:lang="zh_CN">MXF 视频</comment>
+ <comment xml:lang="uk">відеокліп MXF</comment>
+ <comment xml:lang="tr">MXF video</comment>
+ <comment xml:lang="sv">MXF-video</comment>
+ <comment xml:lang="sr">МИксФ видео</comment>
+ <comment xml:lang="sq">video MXF</comment>
+ <comment xml:lang="sl">Video datoteka MXF</comment>
+ <comment xml:lang="si">MXF වීඩියෝව</comment>
+ <comment xml:lang="sk">Video MXF</comment>
+ <comment xml:lang="ru">Видео MXF</comment>
+ <comment xml:lang="ro">Video MXF</comment>
+ <comment xml:lang="pt_BR">Vídeo MXF</comment>
+ <comment xml:lang="pt">vídeo MXF</comment>
+ <comment xml:lang="pl">Plik wideo MXF</comment>
+ <comment xml:lang="oc">vidèo MXF</comment>
+ <comment xml:lang="nl">MXF-video</comment>
+ <comment xml:lang="lv">MXF video</comment>
+ <comment xml:lang="lt">MXF vaizdo įrašas</comment>
+ <comment xml:lang="ko">MXF 동영상</comment>
+ <comment xml:lang="kk">MXF видеосы</comment>
+ <comment xml:lang="ka">MXF ვიდეო</comment>
+ <comment xml:lang="ja">MXF 動画</comment>
+ <comment xml:lang="it">Video MXF</comment>
+ <comment xml:lang="is">MXF myndskeið</comment>
+ <comment xml:lang="id">Video MXF</comment>
+ <comment xml:lang="ia">Video MXF</comment>
+ <comment xml:lang="hu">MXF videó</comment>
+ <comment xml:lang="hr">MXF video snimka</comment>
+ <comment xml:lang="he">וידאו MXF</comment>
+ <comment xml:lang="gl">vídeo MXF</comment>
+ <comment xml:lang="ga">físeán MXF</comment>
+ <comment xml:lang="fur">video MXF</comment>
+ <comment xml:lang="fr">vidéo MXF</comment>
+ <comment xml:lang="fo">MXF video</comment>
+ <comment xml:lang="fi">MXF-video</comment>
+ <comment xml:lang="eu">MXF bideoa</comment>
+ <comment xml:lang="es">vídeo MXF</comment>
+ <comment xml:lang="eo">MXF-video</comment>
+ <comment xml:lang="en_GB">MXF video</comment>
+ <comment xml:lang="el">Βίντεο MXF</comment>
+ <comment xml:lang="de">MXF-Video</comment>
+ <comment xml:lang="da">MXF-video</comment>
+ <comment xml:lang="cs">video MXF</comment>
+ <comment xml:lang="ca">vídeo MXF</comment>
+ <comment xml:lang="bg">Видео — MXF</comment>
+ <comment xml:lang="be">відэа MXF</comment>
+ <comment xml:lang="ast">Videu en MXF</comment>
+ <comment xml:lang="ar">فيديو MXF</comment>
+ <comment xml:lang="af">MXF-video</comment>
<acronym>MXF</acronym>
<expanded-acronym>Material Exchange Format</expanded-acronym>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
- <match value="\x06\x0e\x2b\x34\x02\x05\x01\x01\x0d\x01\x02\x01\x01\x02" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="\x06\x0e\x2b\x34\x02\x05\x01\x01\x0d\x01\x02\x01\x01\x02" offset="0:256"/>
</magic>
<glob pattern="*.mxf"/>
</mime-type>
<mime-type type="text/x-ocl">
<comment>OCL file</comment>
- <comment xml:lang="ar">ملف OCL</comment>
- <comment xml:lang="be@latin">Fajł OCL</comment>
- <comment xml:lang="bg">Файл — OCL</comment>
- <comment xml:lang="ca">fitxer OCL</comment>
- <comment xml:lang="cs">soubor OCL</comment>
- <comment xml:lang="da">OCL-fil</comment>
- <comment xml:lang="de">OCL-Datei</comment>
- <comment xml:lang="el">Αρχείο OCL</comment>
- <comment xml:lang="en_GB">OCL file</comment>
- <comment xml:lang="eo">OCL-dosiero</comment>
- <comment xml:lang="es">archivo OCL</comment>
- <comment xml:lang="eu">OCL fitxategia</comment>
- <comment xml:lang="fi">OCL-tiedosto</comment>
- <comment xml:lang="fo">OCL fíla</comment>
- <comment xml:lang="fr">fichier OCL</comment>
- <comment xml:lang="ga">comhad OCL</comment>
- <comment xml:lang="gl">ficheiro OCL</comment>
- <comment xml:lang="he">קובץ OCL</comment>
- <comment xml:lang="hr">OCL datoteka</comment>
- <comment xml:lang="hu">OCL fájl</comment>
- <comment xml:lang="ia">File OCL</comment>
- <comment xml:lang="id">Berkas OCL</comment>
- <comment xml:lang="it">File OCL</comment>
- <comment xml:lang="ja">OCL ファイル</comment>
- <comment xml:lang="kk">OCL файлы</comment>
- <comment xml:lang="ko">OCL 파일</comment>
- <comment xml:lang="lt">OCL failas</comment>
- <comment xml:lang="lv">OCL datne</comment>
- <comment xml:lang="nb">OCL-fil</comment>
- <comment xml:lang="nl">OCL-bestand</comment>
- <comment xml:lang="nn">OCL-fil</comment>
- <comment xml:lang="oc">fichièr OCL</comment>
- <comment xml:lang="pl">Plik OCL</comment>
- <comment xml:lang="pt">ficheiro OCL</comment>
- <comment xml:lang="pt_BR">Arquivo OCL</comment>
- <comment xml:lang="ro">Fișier OCL</comment>
- <comment xml:lang="ru">Файл OCL</comment>
- <comment xml:lang="sk">Súbor OCL</comment>
- <comment xml:lang="sl">Datoteka OCL</comment>
- <comment xml:lang="sq">File OCL</comment>
- <comment xml:lang="sr">ОЦЛ датотека</comment>
- <comment xml:lang="sv">OCL-fil</comment>
- <comment xml:lang="tr">OCL dosyası</comment>
- <comment xml:lang="uk">файл OCL</comment>
- <comment xml:lang="vi">Tập tin OCL</comment>
- <comment xml:lang="zh_CN">OCL 文件</comment>
<comment xml:lang="zh_TW">OCL 檔</comment>
+ <comment xml:lang="zh_CN">OCL 文件</comment>
+ <comment xml:lang="vi">Tập tin OCL</comment>
+ <comment xml:lang="uk">файл OCL</comment>
+ <comment xml:lang="tr">OCL dosyası</comment>
+ <comment xml:lang="sv">OCL-fil</comment>
+ <comment xml:lang="sr">ОЦЛ датотека</comment>
+ <comment xml:lang="sq">kartelë OCL</comment>
+ <comment xml:lang="sl">Datoteka OCL</comment>
+ <comment xml:lang="si">OCL ගොනුව</comment>
+ <comment xml:lang="sk">Súbor OCL</comment>
+ <comment xml:lang="ru">Файл OCL</comment>
+ <comment xml:lang="ro">Fișier OCL</comment>
+ <comment xml:lang="pt_BR">Arquivo OCL</comment>
+ <comment xml:lang="pt">ficheiro OCL</comment>
+ <comment xml:lang="pl">Plik OCL</comment>
+ <comment xml:lang="oc">fichièr OCL</comment>
+ <comment xml:lang="nn">OCL-fil</comment>
+ <comment xml:lang="nl">OCL-bestand</comment>
+ <comment xml:lang="nb">OCL-fil</comment>
+ <comment xml:lang="lv">OCL datne</comment>
+ <comment xml:lang="lt">OCL failas</comment>
+ <comment xml:lang="ko">OCL 파일</comment>
+ <comment xml:lang="kk">OCL файлы</comment>
+ <comment xml:lang="ja">OCL ファイル</comment>
+ <comment xml:lang="it">File OCL</comment>
+ <comment xml:lang="is">OCL skrá</comment>
+ <comment xml:lang="id">Berkas OCL</comment>
+ <comment xml:lang="ia">File OCL</comment>
+ <comment xml:lang="hu">OCL fájl</comment>
+ <comment xml:lang="hr">OCL datoteka</comment>
+ <comment xml:lang="he">קובץ OCL</comment>
+ <comment xml:lang="gl">ficheiro OCL</comment>
+ <comment xml:lang="ga">comhad OCL</comment>
+ <comment xml:lang="fur">file OCL</comment>
+ <comment xml:lang="fr">fichier OCL</comment>
+ <comment xml:lang="fo">OCL fíla</comment>
+ <comment xml:lang="fi">OCL-tiedosto</comment>
+ <comment xml:lang="eu">OCL fitxategia</comment>
+ <comment xml:lang="es">archivo OCL</comment>
+ <comment xml:lang="eo">OCL-dosiero</comment>
+ <comment xml:lang="en_GB">OCL file</comment>
+ <comment xml:lang="el">Αρχείο OCL</comment>
+ <comment xml:lang="de">OCL-Datei</comment>
+ <comment xml:lang="da">OCL-fil</comment>
+ <comment xml:lang="cs">soubor OCL</comment>
+ <comment xml:lang="ca">fitxer OCL</comment>
+ <comment xml:lang="bg">Файл — OCL</comment>
+ <comment xml:lang="be@latin">Fajł OCL</comment>
+ <comment xml:lang="be">файл OCL</comment>
+ <comment xml:lang="ar">ملف OCL</comment>
+ <comment xml:lang="af">OCL-lêer</comment>
<acronym>OCL</acronym>
<expanded-acronym>Object Constraint Language</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.ocl"/>
</mime-type>
<mime-type type="text/x-cobol">
- <comment>COBOL source file</comment>
- <comment xml:lang="bg">Изходен код — COBOL</comment>
- <comment xml:lang="ca">codi font en COBOL</comment>
- <comment xml:lang="cs">zdrojový soubor COBOL</comment>
- <comment xml:lang="da">COBOL-kildefil</comment>
- <comment xml:lang="de">COBOL-Quelldatei</comment>
- <comment xml:lang="el">Πηγαίο αρχείο COBOL</comment>
- <comment xml:lang="en_GB">COBOL source file</comment>
- <comment xml:lang="eo">COBOL-fontdosiero</comment>
- <comment xml:lang="es">archivo fuente de COBOL</comment>
- <comment xml:lang="eu">COBOL iturburu-kodea</comment>
- <comment xml:lang="fi">COBOL-lähdekoodi</comment>
- <comment xml:lang="fr">fichier source COBOL</comment>
- <comment xml:lang="ga">cód foinseach COBOL</comment>
- <comment xml:lang="gl">ficheiro fonte de COBOL</comment>
- <comment xml:lang="he">קובץ מקור של COBOL</comment>
- <comment xml:lang="hr">COBOL izvorna datoteka</comment>
- <comment xml:lang="hu">COBOL forrásfájl</comment>
- <comment xml:lang="ia">File de codice fonte COBOL</comment>
- <comment xml:lang="id">Berkas sumber COBOL</comment>
- <comment xml:lang="it">File sorgente COBOL</comment>
- <comment xml:lang="ja">COBOL ソースファイル</comment>
- <comment xml:lang="ka">COBOL-ის საწყისი ფაილი</comment>
- <comment xml:lang="kk">COBOL бастапқы коды</comment>
- <comment xml:lang="ko">COBOL 소스 파일</comment>
- <comment xml:lang="lv">COBOL pirmkods</comment>
- <comment xml:lang="nl">COBOL bronbestand</comment>
- <comment xml:lang="oc">fichièr font COBOL</comment>
- <comment xml:lang="pl">Plik źródłowy COBOL</comment>
- <comment xml:lang="pt">ficheiro origem COBOL</comment>
- <comment xml:lang="pt_BR">Arquivo de código-fonte em COBOL</comment>
- <comment xml:lang="ru">Файл исходного кода на COBOL</comment>
- <comment xml:lang="sk">Zdrojový súbor COBOLu</comment>
+ <comment>COBOL source code</comment>
+ <comment xml:lang="zh_TW">COBOL 原始碼</comment>
+ <comment xml:lang="zh_CN">COBOL 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою COBOL</comment>
+ <comment xml:lang="tr">COBOL kaynak kodu</comment>
+ <comment xml:lang="sv">COBOL-källkod</comment>
+ <comment xml:lang="sq">kod burim COBOL</comment>
<comment xml:lang="sl">Izvorna koda COBOL</comment>
- <comment xml:lang="sr">изворна датотека КОБОЛ-а</comment>
- <comment xml:lang="sv">COBOL-källkodsfil</comment>
- <comment xml:lang="tr">COBOL kaynak dosyası</comment>
- <comment xml:lang="uk">вихідний код мовою COBOL</comment>
- <comment xml:lang="zh_CN">COBOL 源文件</comment>
- <comment xml:lang="zh_TW">COBOL 源檔</comment>
+ <comment xml:lang="si">COBOL මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód COBOL</comment>
+ <comment xml:lang="ru">Исходный код COBOL</comment>
+ <comment xml:lang="pt_BR">Código-fonte COBOL</comment>
+ <comment xml:lang="pl">Kod źródłowy COBOL</comment>
+ <comment xml:lang="oc">còdi font COBOL</comment>
+ <comment xml:lang="nl">COBOL-broncode</comment>
+ <comment xml:lang="ko">코볼 소스 코드</comment>
+ <comment xml:lang="kk">COBOL бастапқы коды</comment>
+ <comment xml:lang="ja">COBOL ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente COBOL</comment>
+ <comment xml:lang="is">COBOL frumkóði</comment>
+ <comment xml:lang="id">Kode sumber COBOL</comment>
+ <comment xml:lang="hu">COBOL forráskód</comment>
+ <comment xml:lang="hr">COBOL izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור COBOL</comment>
+ <comment xml:lang="gl">Código fonte en COBOL</comment>
+ <comment xml:lang="fr">code source COBOL</comment>
+ <comment xml:lang="fi">COBOL-lähdekoodi</comment>
+ <comment xml:lang="eu">COBOL iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en COBOL</comment>
+ <comment xml:lang="en_GB">COBOL source code</comment>
+ <comment xml:lang="de">COBOL-Quelltext</comment>
+ <comment xml:lang="da">COBOL-kildekode</comment>
+ <comment xml:lang="ca">codi font en COBOL</comment>
+ <comment xml:lang="bg">Изходен код — COBOL</comment>
+ <comment xml:lang="be">зыходны код COBOL</comment>
+ <comment xml:lang="ar">شيفرة مصدر كوبول</comment>
<acronym>COBOL</acronym>
<expanded-acronym>COmmon Business Oriented Language</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -16033,660 +17467,832 @@
</mime-type>
<mime-type type="application/x-mobipocket-ebook">
<comment>Mobipocket e-book</comment>
- <comment xml:lang="bg">Е-книга — Mobipocket</comment>
- <comment xml:lang="ca">llibre electrònic Mobipocket </comment>
- <comment xml:lang="cs">elektronická kniha Mobipocket</comment>
- <comment xml:lang="da">Mobipocket e-bog</comment>
- <comment xml:lang="de">Mobipocket E-Book</comment>
- <comment xml:lang="el">Ηλεκτρονικό βιβλίο Mobipocket</comment>
- <comment xml:lang="en_GB">Mobipocket e-book</comment>
- <comment xml:lang="es">libro electrónico de Mobipocket</comment>
- <comment xml:lang="eu">Mobipocket liburua</comment>
- <comment xml:lang="fi">Mobipocket e-kirja</comment>
- <comment xml:lang="fr">livre numérique Mobipocket</comment>
- <comment xml:lang="ga">r-leabhar Mobipocket</comment>
- <comment xml:lang="gl">E-book Mobipocket</comment>
- <comment xml:lang="he">ספר אלקטרוני של Mobipocket</comment>
- <comment xml:lang="hr">Mobipocket e-knjiga</comment>
- <comment xml:lang="hu">Mobipocket e-könyv</comment>
- <comment xml:lang="ia">E-libro Mobipocket</comment>
- <comment xml:lang="id">e-book Mobipocket</comment>
- <comment xml:lang="it">E-book Mobipocket</comment>
- <comment xml:lang="ja">Mobipocket 電子書籍</comment>
- <comment xml:lang="ka">Mobipocket-ის ელწიგნი</comment>
- <comment xml:lang="kk">Mobipocket эл. кітабы</comment>
- <comment xml:lang="ko">Mobipocket 전자책</comment>
- <comment xml:lang="lv">Mobipocket e-grāmata</comment>
- <comment xml:lang="nl">Mobipocket e-book</comment>
- <comment xml:lang="oc">libre numeric Mobipocket</comment>
- <comment xml:lang="pl">E-book Mobipocket</comment>
- <comment xml:lang="pt">ebook Mobipocket</comment>
- <comment xml:lang="pt_BR">E-book Mobipocket</comment>
- <comment xml:lang="ru">Электронная книга Mobipocket</comment>
- <comment xml:lang="sk">E-kniha Mobipocket</comment>
- <comment xml:lang="sl">e-knjiga Mobipocket</comment>
- <comment xml:lang="sr">Мобипокет ел. књига</comment>
- <comment xml:lang="sv">Mobipocket-e-bok</comment>
- <comment xml:lang="tr">Mobipocket e-kitap</comment>
- <comment xml:lang="uk">електронна книга Mobipocket</comment>
- <comment xml:lang="zh_CN">Mobipocket 电子书</comment>
<comment xml:lang="zh_TW">Mobipocket e-book</comment>
+ <comment xml:lang="zh_CN">Mobipocket 电子书</comment>
+ <comment xml:lang="uk">електронна книга Mobipocket</comment>
+ <comment xml:lang="tr">Mobipocket e-kitap</comment>
+ <comment xml:lang="sv">Mobipocket-e-bok</comment>
+ <comment xml:lang="sr">Мобипокет ел. књига</comment>
+ <comment xml:lang="sq">e-libër Mobipocket</comment>
+ <comment xml:lang="sl">e-knjiga Mobipocket</comment>
+ <comment xml:lang="si">මොබිපොකට් ඊ-පොත</comment>
+ <comment xml:lang="sk">E-kniha Mobipocket</comment>
+ <comment xml:lang="ru">Электронная книга Mobipocket</comment>
+ <comment xml:lang="pt_BR">E-book Mobipocket</comment>
+ <comment xml:lang="pt">ebook Mobipocket</comment>
+ <comment xml:lang="pl">E-book Mobipocket</comment>
+ <comment xml:lang="oc">libre numeric Mobipocket</comment>
+ <comment xml:lang="nl">Mobipocket e-book</comment>
+ <comment xml:lang="lv">Mobipocket e-grāmata</comment>
+ <comment xml:lang="ko">Mobipocket 전자책</comment>
+ <comment xml:lang="kk">Mobipocket эл. кітабы</comment>
+ <comment xml:lang="ka">Mobipocket-ის ელწიგნი</comment>
+ <comment xml:lang="ja">Mobipocket 電子書籍</comment>
+ <comment xml:lang="it">E-book Mobipocket</comment>
+ <comment xml:lang="is">Mobipocket rafbók</comment>
+ <comment xml:lang="id">E-book Mobipocket</comment>
+ <comment xml:lang="ia">E-libro Mobipocket</comment>
+ <comment xml:lang="hu">Mobipocket e-könyv</comment>
+ <comment xml:lang="hr">Mobipocket e-knjiga</comment>
+ <comment xml:lang="he">ספר אלקטרוני של Mobipocket</comment>
+ <comment xml:lang="gl">E-book Mobipocket</comment>
+ <comment xml:lang="ga">r-leabhar Mobipocket</comment>
+ <comment xml:lang="fur">e-book Mobipocket</comment>
+ <comment xml:lang="fr">livre numérique Mobipocket</comment>
+ <comment xml:lang="fi">Mobipocket-e-kirja</comment>
+ <comment xml:lang="eu">Mobipocket liburua</comment>
+ <comment xml:lang="es">libro electrónico de Mobipocket</comment>
+ <comment xml:lang="en_GB">Mobipocket e-book</comment>
+ <comment xml:lang="el">Ηλεκτρονικό βιβλίο Mobipocket</comment>
+ <comment xml:lang="de">Mobipocket E-Book</comment>
+ <comment xml:lang="da">Mobipocket e-bog</comment>
+ <comment xml:lang="cs">elektronická kniha Mobipocket</comment>
+ <comment xml:lang="ca">llibre electrònic Mobipocket </comment>
+ <comment xml:lang="bg">Е-книга — Mobipocket</comment>
+ <comment xml:lang="be">электронная кніга Mobipocket</comment>
+ <comment xml:lang="ar">كتاب إلكتروني Mobipocket</comment>
+ <comment xml:lang="af">Mobipocket e-boek</comment>
<sub-class-of type="application/vnd.palm"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.mobi"/>
<glob pattern="*.prc"/>
<magic priority="30">
-
- <match value="TEXtREAd" type="string" offset="60"/>
+ <!-- This also matches AportisDoc, so lower the priority and prefer extension -->
+ <match type="string" offset="60" value="TEXtREAd"/>
</magic>
<magic priority="80">
- <match value="BOOKMOBI" type="string" offset="60"/>
+ <match type="string" offset="60" value="BOOKMOBI"/>
</magic>
</mime-type>
<mime-type type="application/x-mif">
<comment>Adobe FrameMaker MIF document</comment>
- <comment xml:lang="ar">مستند أدوبي الصانع للإطارات MIF</comment>
- <comment xml:lang="ast">Documentu MIF d'Adobe FrameMaker</comment>
- <comment xml:lang="be@latin">Dakument Adobe FrameMaker MIF</comment>
- <comment xml:lang="bg">Документ — Adobe FrameMaker MIF</comment>
- <comment xml:lang="ca">document MIF d'Adobe FrameMaker</comment>
- <comment xml:lang="cs">dokument Adobe FrameMaker MIF</comment>
- <comment xml:lang="da">Adobe FrameMaker MIF-dokument</comment>
- <comment xml:lang="de">Adobe-FrameMaker-MIF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο MIF του Adobe FrameMaker </comment>
- <comment xml:lang="en_GB">Adobe FrameMaker MIF document</comment>
- <comment xml:lang="eo">MIF-dokumento de Adobe FrameMaker</comment>
- <comment xml:lang="es">documento MIF de Adobe FrameMaker</comment>
- <comment xml:lang="eu">Adobe FrameMaker-en MIF dokumentua</comment>
- <comment xml:lang="fi">Adobe FrameMaker MIF -asiakirja</comment>
- <comment xml:lang="fo">Adobe FrameMaker MIF skjal</comment>
- <comment xml:lang="fr">document MIF Adobe FrameMaker</comment>
- <comment xml:lang="ga">cáipéis MIF Adobe FrameMaker</comment>
- <comment xml:lang="gl">documento MIF de Adobe FrameMaker</comment>
- <comment xml:lang="he">מסמך MIF של Adobe FrameMaker</comment>
- <comment xml:lang="hr">Adobe FrameMaker MIF dokument</comment>
- <comment xml:lang="hu">Adobe FrameMaker MIF-dokumentum</comment>
- <comment xml:lang="ia">Documento MIF de Adobe FrameMaker</comment>
- <comment xml:lang="id">Dokumen Adobe FrameMaker MIF</comment>
- <comment xml:lang="it">Documento MIF Adobe FrameMaker</comment>
- <comment xml:lang="ja">Adobe FrameMaker MIF ドキュメント</comment>
- <comment xml:lang="ka">Adobe FrameMaker-ის MIF დოკუმენტი</comment>
- <comment xml:lang="kk">Adobe FrameMaker MIF құжаты</comment>
- <comment xml:lang="ko">Adobe 프레임메이커 MIF 문서</comment>
- <comment xml:lang="lt">Adobe FrameMaker MIF dokumentas</comment>
- <comment xml:lang="lv">Adobe FrameMaker MIF dokuments</comment>
- <comment xml:lang="nb">Adobe FrameMaker MIF-dokument</comment>
- <comment xml:lang="nl">Adobe FrameMaker MIF-document</comment>
- <comment xml:lang="nn">Adobe FrameMaker MIF-dokument</comment>
- <comment xml:lang="oc">document MIF Adobe FrameMaker</comment>
- <comment xml:lang="pl">Dokument MIF Adobe FrameMaker</comment>
- <comment xml:lang="pt">documento Adobe FrameMaker MIF</comment>
- <comment xml:lang="pt_BR">Documento MIF do Adobe FrameMaker</comment>
- <comment xml:lang="ro">Document Adobe FrameMaker MIF</comment>
- <comment xml:lang="ru">Документ Adobe FrameMaker MIF</comment>
- <comment xml:lang="sk">Dokument Adobe FrameMaker MIF</comment>
- <comment xml:lang="sl">Dokument Adobe FrameMaker MIF</comment>
- <comment xml:lang="sq">Dokument MIF Adobe FrameMaker</comment>
- <comment xml:lang="sr">Адобе Фрејм Мејкер МИФ документ</comment>
- <comment xml:lang="sv">Adobe FrameMaker MIF-dokument</comment>
- <comment xml:lang="tr">Adobe FrameMaker MIF belgesi</comment>
- <comment xml:lang="uk">документ Adobe FrameMaker MIF</comment>
- <comment xml:lang="vi">Tài liệu Adobe FrameMaker MIF</comment>
- <comment xml:lang="zh_CN">Adobe FrameMaker MIF 文档</comment>
<comment xml:lang="zh_TW">Adobe FrameMaker MIF 文件</comment>
+ <comment xml:lang="zh_CN">Adobe FrameMaker MIF 文档</comment>
+ <comment xml:lang="vi">Tài liệu Adobe FrameMaker MIF</comment>
+ <comment xml:lang="uk">документ Adobe FrameMaker MIF</comment>
+ <comment xml:lang="tr">Adobe FrameMaker MIF belgesi</comment>
+ <comment xml:lang="sv">Adobe FrameMaker MIF-dokument</comment>
+ <comment xml:lang="sr">Адобе Фрејм Мејкер МИФ документ</comment>
+ <comment xml:lang="sq">dokument MIF Adobe FrameMaker</comment>
+ <comment xml:lang="sl">Dokument Adobe FrameMaker MIF</comment>
+ <comment xml:lang="si">Adobe FrameMaker MIF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Adobe FrameMaker MIF</comment>
+ <comment xml:lang="ru">Документ Adobe FrameMaker MIF</comment>
+ <comment xml:lang="ro">Document Adobe FrameMaker MIF</comment>
+ <comment xml:lang="pt_BR">Documento MIF do Adobe FrameMaker</comment>
+ <comment xml:lang="pt">documento Adobe FrameMaker MIF</comment>
+ <comment xml:lang="pl">Dokument MIF Adobe FrameMaker</comment>
+ <comment xml:lang="oc">document MIF Adobe FrameMaker</comment>
+ <comment xml:lang="nn">Adobe FrameMaker MIF-dokument</comment>
+ <comment xml:lang="nl">Adobe FrameMaker MIF-document</comment>
+ <comment xml:lang="nb">Adobe FrameMaker MIF-dokument</comment>
+ <comment xml:lang="lv">Adobe FrameMaker MIF dokuments</comment>
+ <comment xml:lang="lt">Adobe FrameMaker MIF dokumentas</comment>
+ <comment xml:lang="ko">Adobe 프레임메이커 MIF 문서</comment>
+ <comment xml:lang="kk">Adobe FrameMaker MIF құжаты</comment>
+ <comment xml:lang="ka">Adobe FrameMaker-ის MIF დოკუმენტი</comment>
+ <comment xml:lang="ja">Adobe FrameMaker MIF ドキュメント</comment>
+ <comment xml:lang="it">Documento MIF Adobe FrameMaker</comment>
+ <comment xml:lang="is">Adobe FrameMaker MIF skjal</comment>
+ <comment xml:lang="id">Dokumen Adobe FrameMaker MIF</comment>
+ <comment xml:lang="ia">Documento MIF de Adobe FrameMaker</comment>
+ <comment xml:lang="hu">Adobe FrameMaker MIF-dokumentum</comment>
+ <comment xml:lang="hr">Adobe FrameMaker MIF dokument</comment>
+ <comment xml:lang="he">מסמך MIF של Adobe FrameMaker</comment>
+ <comment xml:lang="gl">documento MIF de Adobe FrameMaker</comment>
+ <comment xml:lang="ga">cáipéis MIF Adobe FrameMaker</comment>
+ <comment xml:lang="fur">document MIF di Adobe FrameMaker</comment>
+ <comment xml:lang="fr">document MIF Adobe FrameMaker</comment>
+ <comment xml:lang="fo">Adobe FrameMaker MIF skjal</comment>
+ <comment xml:lang="fi">Adobe FrameMaker MIF -asiakirja</comment>
+ <comment xml:lang="eu">Adobe FrameMaker-en MIF dokumentua</comment>
+ <comment xml:lang="es">documento MIF de Adobe FrameMaker</comment>
+ <comment xml:lang="eo">MIF-dokumento de Adobe FrameMaker</comment>
+ <comment xml:lang="en_GB">Adobe FrameMaker MIF document</comment>
+ <comment xml:lang="el">Έγγραφο MIF του Adobe FrameMaker </comment>
+ <comment xml:lang="de">Adobe-FrameMaker-MIF-Dokument</comment>
+ <comment xml:lang="da">Adobe FrameMaker MIF-dokument</comment>
+ <comment xml:lang="cs">dokument Adobe FrameMaker MIF</comment>
+ <comment xml:lang="ca">document MIF d'Adobe FrameMaker</comment>
+ <comment xml:lang="bg">Документ — Adobe FrameMaker MIF</comment>
+ <comment xml:lang="be@latin">Dakument Adobe FrameMaker MIF</comment>
+ <comment xml:lang="be">дакумент Adobe FrameMaker MIF</comment>
+ <comment xml:lang="ast">Documentu MIF d'Adobe FrameMaker</comment>
+ <comment xml:lang="ar">مستند أدوبي FrameMaker MIF</comment>
+ <comment xml:lang="af">Adobe FrameMaker MIF-dokument</comment>
<glob pattern="*.mif"/>
</mime-type>
<mime-type type="application/x-mozilla-bookmarks">
<comment>Mozilla bookmarks</comment>
- <comment xml:lang="ar">علامات موزيلا</comment>
- <comment xml:lang="be@latin">Zakładki Mozilla</comment>
- <comment xml:lang="bg">Отметки — Mozilla</comment>
- <comment xml:lang="ca">llista d'adreces d'interès de Mozilla</comment>
- <comment xml:lang="cs">záložky Mozilla</comment>
- <comment xml:lang="da">Mozillabogmærker</comment>
- <comment xml:lang="de">Mozilla-Lesezeichen</comment>
- <comment xml:lang="el">Σελιδοδείκτες Mozilla</comment>
- <comment xml:lang="en_GB">Mozilla bookmarks</comment>
- <comment xml:lang="eo">Mozilla-legosignoj</comment>
- <comment xml:lang="es">marcadores de Mozilla</comment>
- <comment xml:lang="eu">Mozillako laster-markak</comment>
- <comment xml:lang="fi">Mozilla-kirjanmerkit</comment>
- <comment xml:lang="fo">Mozilla bókamerki</comment>
- <comment xml:lang="fr">marque-pages Mozilla</comment>
- <comment xml:lang="ga">leabharmharcanna Mozilla</comment>
- <comment xml:lang="gl">Marcadores de Mozilla</comment>
- <comment xml:lang="he">סימניה של Mozilla</comment>
- <comment xml:lang="hr">Mozilla zabilješke</comment>
- <comment xml:lang="hu">Mozilla-könyvjelzők</comment>
- <comment xml:lang="ia">Marcapaginas Mozilla</comment>
- <comment xml:lang="id">Bookmark Mozilla</comment>
- <comment xml:lang="it">Segnalibri Mozilla</comment>
- <comment xml:lang="ja">Mozilla ブックマーク</comment>
- <comment xml:lang="kk">Mozilla бетбелгілері</comment>
- <comment xml:lang="ko">모질라 책갈피</comment>
- <comment xml:lang="lt">Mozilla žymelės</comment>
- <comment xml:lang="lv">Mozilla grāmatzīmes</comment>
- <comment xml:lang="ms">Tandabuku Mozilla</comment>
- <comment xml:lang="nb">Mozilla-bokmerker</comment>
- <comment xml:lang="nl">Mozilla-bladwijzers</comment>
- <comment xml:lang="nn">Mozilla-bokmerker</comment>
- <comment xml:lang="oc">marcapaginas Mozilla</comment>
- <comment xml:lang="pl">Zakładki Mozilla</comment>
- <comment xml:lang="pt">marcadores do Mozilla</comment>
- <comment xml:lang="pt_BR">Favoritos do Mozilla</comment>
- <comment xml:lang="ro">Semne de carte Mozilla</comment>
- <comment xml:lang="ru">Закладки Mozilla</comment>
- <comment xml:lang="sk">Záložky Mozilla</comment>
- <comment xml:lang="sl">Datoteka zaznamkov Mozilla</comment>
- <comment xml:lang="sq">Libërshënues Mozilla</comment>
- <comment xml:lang="sr">Мозилини обележивачи</comment>
- <comment xml:lang="sv">Mozilla-bokmärken</comment>
- <comment xml:lang="tr">Mozilla yer imleri</comment>
- <comment xml:lang="uk">закладки Mozilla</comment>
- <comment xml:lang="vi">Liên kết đã lưu Mozilla</comment>
- <comment xml:lang="zh_CN">Mozilla 书签</comment>
<comment xml:lang="zh_TW">Mozilla 書籤</comment>
+ <comment xml:lang="zh_CN">Mozilla 书签</comment>
+ <comment xml:lang="vi">Liên kết đã lưu Mozilla</comment>
+ <comment xml:lang="uk">закладки Mozilla</comment>
+ <comment xml:lang="tr">Mozilla yer imleri</comment>
+ <comment xml:lang="sv">Mozilla-bokmärken</comment>
+ <comment xml:lang="sr">Мозилини обележивачи</comment>
+ <comment xml:lang="sq">faqerojtës Mozilla</comment>
+ <comment xml:lang="sl">Datoteka zaznamkov Mozilla</comment>
+ <comment xml:lang="si">මොසිල්ලා පිටු සලකුණු</comment>
+ <comment xml:lang="sk">Záložky Mozilla</comment>
+ <comment xml:lang="ru">Закладки Mozilla</comment>
+ <comment xml:lang="ro">Semne de carte Mozilla</comment>
+ <comment xml:lang="pt_BR">Favoritos do Mozilla</comment>
+ <comment xml:lang="pt">marcadores do Mozilla</comment>
+ <comment xml:lang="pl">Zakładki Mozilla</comment>
+ <comment xml:lang="oc">marcapaginas Mozilla</comment>
+ <comment xml:lang="nn">Mozilla-bokmerker</comment>
+ <comment xml:lang="nl">Mozilla-bladwijzers</comment>
+ <comment xml:lang="nb">Mozilla-bokmerker</comment>
+ <comment xml:lang="ms">Tandabuku Mozilla</comment>
+ <comment xml:lang="lv">Mozilla grāmatzīmes</comment>
+ <comment xml:lang="lt">Mozilla žymelės</comment>
+ <comment xml:lang="ko">모질라 책갈피</comment>
+ <comment xml:lang="kk">Mozilla бетбелгілері</comment>
+ <comment xml:lang="ja">Mozilla ブックマーク</comment>
+ <comment xml:lang="it">Segnalibri Mozilla</comment>
+ <comment xml:lang="is">Mozilla bókamerki</comment>
+ <comment xml:lang="id">Bookmark Mozilla</comment>
+ <comment xml:lang="ia">Marcapaginas Mozilla</comment>
+ <comment xml:lang="hu">Mozilla-könyvjelzők</comment>
+ <comment xml:lang="hr">Mozilla zabilješke</comment>
+ <comment xml:lang="he">סימניה של Mozilla</comment>
+ <comment xml:lang="gl">Marcadores de Mozilla</comment>
+ <comment xml:lang="ga">leabharmharcanna Mozilla</comment>
+ <comment xml:lang="fur">segnelibris Mozilla</comment>
+ <comment xml:lang="fr">marque-pages Mozilla</comment>
+ <comment xml:lang="fo">Mozilla bókamerki</comment>
+ <comment xml:lang="fi">Mozilla-kirjanmerkit</comment>
+ <comment xml:lang="eu">Mozillako laster-markak</comment>
+ <comment xml:lang="es">marcadores de Mozilla</comment>
+ <comment xml:lang="eo">Mozilla-legosignoj</comment>
+ <comment xml:lang="en_GB">Mozilla bookmarks</comment>
+ <comment xml:lang="el">Σελιδοδείκτες Mozilla</comment>
+ <comment xml:lang="de">Mozilla-Lesezeichen</comment>
+ <comment xml:lang="da">Mozillabogmærker</comment>
+ <comment xml:lang="cs">záložky Mozilla</comment>
+ <comment xml:lang="ca">llista d'adreces d'interès de Mozilla</comment>
+ <comment xml:lang="bg">Отметки — Mozilla</comment>
+ <comment xml:lang="be@latin">Zakładki Mozilla</comment>
+ <comment xml:lang="be">закладкі Mozilla</comment>
+ <comment xml:lang="ar">علامات موزيلا</comment>
+ <comment xml:lang="af">Mozilla-boekmerke</comment>
<sub-class-of type="text/html"/>
<generic-icon name="text-html"/>
<magic priority="80">
- <match value="&lt;!DOCTYPE NETSCAPE-Bookmark-file-1&gt;" type="string" offset="0:64"/>
+ <match type="string" value="&lt;!DOCTYPE NETSCAPE-Bookmark-file-1&gt;" offset="0:64"/>
</magic>
<alias type="application/x-netscape-bookmarks"/>
</mime-type>
- <mime-type type="application/x-ms-dos-executable">
- <comment>DOS/Windows executable</comment>
- <comment xml:lang="ar">تنفيذي DOS/Windows</comment>
- <comment xml:lang="be@latin">Vykonvalny fajł DOS/Windows</comment>
- <comment xml:lang="bg">Изпълним файл — DOS/Windows</comment>
- <comment xml:lang="ca">executable de DOS o de Windows</comment>
- <comment xml:lang="cs">spustitelný soubor pro DOS/Windows</comment>
- <comment xml:lang="da">DOS-/Windowskørbar</comment>
- <comment xml:lang="de">DOS/Windows-Programmdatei</comment>
- <comment xml:lang="el">Εκτελέσιμο DOS/Windows</comment>
- <comment xml:lang="en_GB">DOS/Windows executable</comment>
- <comment xml:lang="eo">DOS/Windows-plenumebla</comment>
- <comment xml:lang="es">ejecutable de DOS/Windows</comment>
- <comment xml:lang="eu">DOS/Windows-eko exekutagarria</comment>
- <comment xml:lang="fi">DOS/Windows-ohjelma</comment>
- <comment xml:lang="fo">DOS/Windows inningarfør</comment>
- <comment xml:lang="fr">exécutable DOS/Windows</comment>
- <comment xml:lang="ga">comhad inrite DOS/Windows</comment>
- <comment xml:lang="gl">executábel de DOS/Windows</comment>
- <comment xml:lang="he">קובץ בר־הרצה של DOS/חלונות</comment>
- <comment xml:lang="hr">DOS/Windows izvršna datoteka</comment>
- <comment xml:lang="hu">DOS/Windows futtatható</comment>
- <comment xml:lang="ia">Executabile DOS/Windows</comment>
- <comment xml:lang="id">DOS/Windows dapat dieksekusi</comment>
- <comment xml:lang="it">Eseguibile DOS/Windows</comment>
- <comment xml:lang="ja">DOS/Windows 実行ファイル</comment>
- <comment xml:lang="ka">DOS/Windows გაშვებადი ფაილი</comment>
- <comment xml:lang="kk">DOS/Windows орындалатын файлы</comment>
- <comment xml:lang="ko">DOS/Windows 실행 파일</comment>
- <comment xml:lang="lt">DOS/Windows vykdomasis failas</comment>
- <comment xml:lang="lv">DOS/Windows izpildāmais</comment>
- <comment xml:lang="ms">Bolehlaksana DOS/Windows</comment>
- <comment xml:lang="nb">Kjørbar fil for DOS/Windows</comment>
- <comment xml:lang="nl">DOS/Windows-uitvoerbaar bestand</comment>
- <comment xml:lang="nn">DOS/Windows køyrbar fil</comment>
- <comment xml:lang="oc">executable DOS/Windows</comment>
- <comment xml:lang="pl">Program DOS/Windows</comment>
- <comment xml:lang="pt">executável DOS/Windows</comment>
- <comment xml:lang="pt_BR">Executável do DOS/Windows</comment>
- <comment xml:lang="ro">Executabil DOS/Windows</comment>
- <comment xml:lang="ru">Исполняемый файл DOS/Windows</comment>
- <comment xml:lang="sk">Spustiteľný súbor pre DOS/Windows</comment>
- <comment xml:lang="sl">Izvedljiva datoteka DOS/Windows</comment>
- <comment xml:lang="sq">I ekzekutueshëm DOS/Windows</comment>
- <comment xml:lang="sr">ДОС/Виндоуз извршна</comment>
- <comment xml:lang="sv">Körbar DOS/Windows-fil</comment>
- <comment xml:lang="tr">DOS/Windows çalıştırılabilir</comment>
- <comment xml:lang="uk">виконуваний файл DOS/Windows</comment>
- <comment xml:lang="vi">Tập tin có thực hiện được DOS/Windows</comment>
- <comment xml:lang="zh_CN">DOS/Windows 可执行文件</comment>
- <comment xml:lang="zh_TW">DOS/Windows 可執行檔</comment>
+ <mime-type type="application/x-msdownload">
+ <comment>Windows or DOS program</comment>
+ <acronym>DOS</acronym>
+ <expanded-acronym>Disk Operating System</expanded-acronym>
+ <sub-class-of type="application/x-executable"/>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="MZ" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="MZ" offset="0"/>
</magic>
<glob pattern="*.exe"/>
+ <glob pattern="*.dll"/>
+ <glob pattern="*.cpl"/>
+ <glob pattern="*.drv"/>
+ <glob pattern="*.scr"/>
+ <alias type="application/x-ms-dos-executable"/>
+ </mime-type>
+ <mime-type type="application/x-dosexec">
+ <comment>DOS executable</comment>
+ <acronym>DOS</acronym>
+ <expanded-acronym>Disk Operating System</expanded-acronym>
+ <sub-class-of type="application/x-msdownload"/>
+ <generic-icon name="application-x-executable"/>
+ <magic priority="60">
+ <match type="string" value="MZ" offset="0">
+ <match type="little16" mask="0xffc0" value="0" offset="24"/>
+ </match>
+ </magic>
+ <glob pattern="*.exe" weight="30"/>
+ </mime-type>
+ <mime-type type="application/x-ms-ne-executable">
+ <comment>16-bit Windows program</comment>
+ <sub-class-of type="application/x-msdownload"/>
+ <generic-icon name="application-x-executable"/>
+ <magic priority="70">
+ <match type="string" value="MZ" offset="0">
+ <match type="string" value="NE" offset="64:256"/>
+ </match>
+ </magic>
+ <glob pattern="*.exe" weight="20"/>
+ <glob pattern="*.dll" weight="20"/>
+ <glob pattern="*.cpl" weight="20"/>
+ <glob pattern="*.drv" weight="20"/>
+ <glob pattern="*.scr" weight="20"/>
+ </mime-type>
+ <mime-type type="application/vnd.microsoft.portable-executable">
+ <comment>Windows or EFI program</comment>
+ <acronym>EFI</acronym>
+ <expanded-acronym>Extensible Firmware Interface</expanded-acronym>
+ <sub-class-of type="application/x-msdownload"/>
+ <generic-icon name="application-x-executable"/>
+ <magic priority="80">
+ <match type="string" value="MZ" offset="0">
+ <match type="string" value="PE\0\0" offset="64:256"/>
+ </match>
+ </magic>
+ <glob pattern="*.exe" weight="40"/>
+ <glob pattern="*.dll" weight="40"/>
+ <glob pattern="*.cpl" weight="40"/>
+ <glob pattern="*.drv" weight="40"/>
+ <glob pattern="*.scr" weight="40"/>
+ <glob pattern="*.efi"/>
+ <glob pattern="*.ocx"/>
+ <glob pattern="*.sys"/>
+ <glob pattern="*.lib"/>
+ </mime-type>
+ <mime-type type="application/x-ms-pdb">
+ <comment>Windows program database</comment>
+ <comment xml:lang="uk">база даних програм Windows</comment>
+ <comment xml:lang="sv">Windows-programdatabas</comment>
+ <comment xml:lang="ru">База данных программ Windows</comment>
+ <comment xml:lang="pl">Baza danych programów Windows</comment>
+ <comment xml:lang="eu">Windows programen datu-basea</comment>
+ <comment xml:lang="es">base de datos de programa de Windows</comment>
+ <comment xml:lang="de">Windows-Programmdatenbank</comment>
+ <magic>
+ <match type="string" value="Microsoft C/C++ MSF 7.00\r\n\x1aDS" offset="0"/>
+ <match type="string" value="Microsoft C/C++ program database 2.00\r\n\x1aJG" offset="0"/>
+ </magic>
+ <glob pattern="*.pdb"/>
+ </mime-type>
+ <mime-type type="application/x-bat">
+ <comment>DOS/Windows batch file</comment>
+ <comment xml:lang="uk">пакетний файл DOS/Windows</comment>
+ <comment xml:lang="sv">DOS/Windows-batchfil</comment>
+ <comment xml:lang="ru">Пакетный файл DOS/Windows</comment>
+ <comment xml:lang="pl">Plik wsadowy DOS/Windows</comment>
+ <comment xml:lang="ja">DOS/Windowsバッチファイル</comment>
+ <comment xml:lang="it">File batch DOS/Windows</comment>
+ <comment xml:lang="gl">Ficheiro en lote DOS/Windows</comment>
+ <comment xml:lang="eu">DOS/Windows sortakako fitxategia</comment>
+ <comment xml:lang="es">archivo por lotes de DOS/Windows</comment>
+ <comment xml:lang="de">DOS/Windows Stapelverarbeitungsdatei</comment>
+ <comment xml:lang="be">выконвальны файл DOS/Windows</comment>
+ <sub-class-of type="text/plain"/>
+ <alias type="application/bat"/>
+ <generic-icon name="text-x-script"/>
+ <glob pattern="*.bat"/>
+ </mime-type>
+ <mime-type type="application/x-powershell">
+ <comment>PowerShell script</comment>
+ <comment xml:lang="uk">скрипт PowerShell</comment>
+ <comment xml:lang="sv">PowerShell-skript</comment>
+ <comment xml:lang="ru">Сценарий PowerShell</comment>
+ <comment xml:lang="pl">Skrypt PowerShell</comment>
+ <comment xml:lang="es">secuencia de órdenes de PowerShell</comment>
+ <comment xml:lang="de">PowerShell-Skript</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-script"/>
+ <magic>
+ <match type="string" value="#Requires -PSEdition Core" offset="0"/>
+ <match type="string" value="#Requires -PSEdition Desktop" offset="0"/>
+ </magic>
+ <glob pattern="*.ps1"/>
+ </mime-type>
+ <mime-type type="application/x-ms-shortcut">
+ <comment>Windows shortcut</comment>
+ <comment xml:lang="uk">ярлик Windows</comment>
+ <comment xml:lang="sv">Windows-genväg</comment>
+ <comment xml:lang="ru">Ярлык Windows</comment>
+ <comment xml:lang="pl">Skrót Windows</comment>
+ <comment xml:lang="es">acceso directo de Windows</comment>
+ <comment xml:lang="de">Windows-Verweis</comment>
+ <generic-icon name="emblem-symbolic-link"/>
+ <magic>
+ <match type="string" value="\x4c\x00\x00\x00\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46" offset="0"/>
+ </magic>
+ <glob pattern="*.lnk"/>
+ <alias type="application/x-win-lnk"/>
</mime-type>
<mime-type type="application/x-mswinurl">
<comment>Internet shortcut</comment>
- <comment xml:lang="ar">اختصار الإنترنت</comment>
- <comment xml:lang="be@latin">Sieciŭnaja spasyłka</comment>
- <comment xml:lang="bg">Адрес в Интернет</comment>
- <comment xml:lang="ca">drecera d'Internet</comment>
- <comment xml:lang="cs">odkaz do Internetu</comment>
- <comment xml:lang="da">Internetgenvej</comment>
- <comment xml:lang="de">Internet-Verweis</comment>
- <comment xml:lang="el">Συντόμευση διαδικτύου</comment>
- <comment xml:lang="en_GB">Internet shortcut</comment>
- <comment xml:lang="es">acceso directo a Internet</comment>
- <comment xml:lang="eu">Interneteko lasterbidea</comment>
- <comment xml:lang="fi">Internet-pikakuvake</comment>
- <comment xml:lang="fo">Alnetssnarvegur</comment>
- <comment xml:lang="fr">raccourci Internet</comment>
- <comment xml:lang="ga">aicearra Idirlín</comment>
- <comment xml:lang="gl">atallo de Internet</comment>
- <comment xml:lang="he">קיצור דרך של האינטרנט</comment>
- <comment xml:lang="hr">Internetski prečac</comment>
- <comment xml:lang="hu">Internetes indítóikon</comment>
- <comment xml:lang="ia">Ligamine Internet</comment>
- <comment xml:lang="id">Jalan pintas Internet</comment>
- <comment xml:lang="it">Scorciatoia Internet</comment>
- <comment xml:lang="ja">インターネットショートカット</comment>
- <comment xml:lang="kk">Интернет сілтемесі</comment>
- <comment xml:lang="ko">인터넷 바로 가기</comment>
- <comment xml:lang="lt">Interneto nuoroda</comment>
- <comment xml:lang="lv">Interneta īsceļš</comment>
- <comment xml:lang="nb">Internettsnarvei</comment>
- <comment xml:lang="nl">internetkoppeling</comment>
- <comment xml:lang="nn">Internett-snarveg</comment>
- <comment xml:lang="oc">acorchi Internet</comment>
- <comment xml:lang="pl">Skrót internetowy</comment>
- <comment xml:lang="pt">atalho da Internet</comment>
- <comment xml:lang="pt_BR">Atalho da Internet</comment>
- <comment xml:lang="ro">Scurtătură Internet</comment>
- <comment xml:lang="ru">Интернет-ссылка</comment>
- <comment xml:lang="sk">Internetový odkaz</comment>
- <comment xml:lang="sl">Internetna bližnjica</comment>
- <comment xml:lang="sq">Shkurtim internet</comment>
- <comment xml:lang="sr">интернет пречица</comment>
- <comment xml:lang="sv">Internetgenväg</comment>
- <comment xml:lang="tr">İnternet kısayolu</comment>
- <comment xml:lang="uk">інтернет-посилання</comment>
- <comment xml:lang="vi">Lối tắt Internet</comment>
- <comment xml:lang="zh_CN">Internet 快捷方式</comment>
<comment xml:lang="zh_TW">網際網路捷徑</comment>
- <magic priority="50">
- <match value="InternetShortcut" type="string" offset="1"/>
- <match value="DEFAULT" type="string" offset="1">
- <match value="BASEURL=" type="string" offset="11"/>
+ <comment xml:lang="zh_CN">Internet 快捷方式</comment>
+ <comment xml:lang="vi">Lối tắt Internet</comment>
+ <comment xml:lang="uk">інтернет-посилання</comment>
+ <comment xml:lang="tr">İnternet kısayolu</comment>
+ <comment xml:lang="sv">Internetgenväg</comment>
+ <comment xml:lang="sr">интернет пречица</comment>
+ <comment xml:lang="sq">shkurtore Internet</comment>
+ <comment xml:lang="sl">Internetna bližnjica</comment>
+ <comment xml:lang="si">අන්තර්ජාල කෙටි මග</comment>
+ <comment xml:lang="sk">Internetový odkaz</comment>
+ <comment xml:lang="ru">Интернет-ссылка</comment>
+ <comment xml:lang="ro">Scurtătură Internet</comment>
+ <comment xml:lang="pt_BR">Atalho da Internet</comment>
+ <comment xml:lang="pt">atalho da Internet</comment>
+ <comment xml:lang="pl">Skrót internetowy</comment>
+ <comment xml:lang="oc">acorchi Internet</comment>
+ <comment xml:lang="nn">Internett-snarveg</comment>
+ <comment xml:lang="nl">internetkoppeling</comment>
+ <comment xml:lang="nb">Internettsnarvei</comment>
+ <comment xml:lang="lv">Interneta īsceļš</comment>
+ <comment xml:lang="lt">Interneto nuoroda</comment>
+ <comment xml:lang="ko">인터넷 바로 가기</comment>
+ <comment xml:lang="kk">Интернет сілтемесі</comment>
+ <comment xml:lang="ja">インターネットショートカット</comment>
+ <comment xml:lang="it">Scorciatoia Internet</comment>
+ <comment xml:lang="is">Internet-flýtileið</comment>
+ <comment xml:lang="id">Jalan pintas Internet</comment>
+ <comment xml:lang="ia">Ligamine Internet</comment>
+ <comment xml:lang="hu">Internetes indítóikon</comment>
+ <comment xml:lang="hr">Internetski prečac</comment>
+ <comment xml:lang="he">קיצור דרך של האינטרנט</comment>
+ <comment xml:lang="gl">atallo de Internet</comment>
+ <comment xml:lang="ga">aicearra Idirlín</comment>
+ <comment xml:lang="fur">scurte di internet</comment>
+ <comment xml:lang="fr">raccourci Internet</comment>
+ <comment xml:lang="fo">Alnetssnarvegur</comment>
+ <comment xml:lang="fi">Internet-pikakuvake</comment>
+ <comment xml:lang="eu">Interneteko lasterbidea</comment>
+ <comment xml:lang="es">acceso directo a Internet</comment>
+ <comment xml:lang="en_GB">Internet shortcut</comment>
+ <comment xml:lang="el">Συντόμευση διαδικτύου</comment>
+ <comment xml:lang="de">Internet-Verweis</comment>
+ <comment xml:lang="da">Internetgenvej</comment>
+ <comment xml:lang="cs">odkaz do Internetu</comment>
+ <comment xml:lang="ca">drecera d'Internet</comment>
+ <comment xml:lang="bg">Адрес в Интернет</comment>
+ <comment xml:lang="be@latin">Sieciŭnaja spasyłka</comment>
+ <comment xml:lang="be">ярлык інтэрнэту</comment>
+ <comment xml:lang="ar">اختصار إنترنت</comment>
+ <comment xml:lang="af">Internet-kortpad</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="emblem-symbolic-link"/>
+ <magic>
+ <match type="string" value="InternetShortcut" offset="1"/>
+ <match type="string" value="DEFAULT" offset="1">
+ <match type="string" value="BASEURL=" offset="11"/>
</match>
</magic>
<glob pattern="*.url"/>
</mime-type>
<mime-type type="application/x-mswrite">
<comment>WRI document</comment>
- <comment xml:lang="ar">مستند WRI</comment>
- <comment xml:lang="ast">Documentu WRI</comment>
- <comment xml:lang="be@latin">Dakument WRI</comment>
- <comment xml:lang="bg">Документ — WRI</comment>
- <comment xml:lang="ca">document WRI</comment>
- <comment xml:lang="cs">dokument WRI</comment>
- <comment xml:lang="da">WRI-dokument</comment>
- <comment xml:lang="de">WRI-Dokument</comment>
- <comment xml:lang="el">Έγγραφο WRI</comment>
- <comment xml:lang="en_GB">WRI document</comment>
- <comment xml:lang="eo">WRI-dokumento</comment>
- <comment xml:lang="es">documento WRI</comment>
- <comment xml:lang="eu">WRI dokumentua</comment>
- <comment xml:lang="fi">WRI-asiakirja</comment>
- <comment xml:lang="fo">WRI skjal</comment>
- <comment xml:lang="fr">document WRI</comment>
- <comment xml:lang="ga">cáipéis WRI</comment>
- <comment xml:lang="gl">documento WRI</comment>
- <comment xml:lang="he">מסמך WRI</comment>
- <comment xml:lang="hr">WRI dokument</comment>
- <comment xml:lang="hu">WRI dokumentum</comment>
- <comment xml:lang="ia">Documento WRI</comment>
- <comment xml:lang="id">Dokumen WRI</comment>
- <comment xml:lang="it">Documento WRI</comment>
- <comment xml:lang="ja">WRI ドキュメント</comment>
- <comment xml:lang="kk">WRI құжаты</comment>
- <comment xml:lang="ko">WRI 문서</comment>
- <comment xml:lang="lt">WRI dokumentas</comment>
- <comment xml:lang="lv">WRI dokuments</comment>
- <comment xml:lang="nb">WRI-dokument</comment>
- <comment xml:lang="nl">WRI-document</comment>
- <comment xml:lang="nn">WRI-dokument</comment>
- <comment xml:lang="oc">document WRI</comment>
- <comment xml:lang="pl">Dokument WRI</comment>
- <comment xml:lang="pt">documento WRI</comment>
- <comment xml:lang="pt_BR">Documento WRI</comment>
- <comment xml:lang="ro">Document WRI</comment>
- <comment xml:lang="ru">Документ WRI</comment>
- <comment xml:lang="sk">Dokument WRI</comment>
- <comment xml:lang="sl">Dokument WRI</comment>
- <comment xml:lang="sq">Dokument WRI</comment>
- <comment xml:lang="sr">ВРИ документ</comment>
- <comment xml:lang="sv">WRI-dokument</comment>
- <comment xml:lang="tr">WRI belgesi</comment>
- <comment xml:lang="uk">документ WRI</comment>
- <comment xml:lang="vi">Tài liệu WRI</comment>
- <comment xml:lang="zh_CN">WRI 文档</comment>
<comment xml:lang="zh_TW">WRI 文件</comment>
+ <comment xml:lang="zh_CN">WRI 文档</comment>
+ <comment xml:lang="vi">Tài liệu WRI</comment>
+ <comment xml:lang="uk">документ WRI</comment>
+ <comment xml:lang="tr">WRI belgesi</comment>
+ <comment xml:lang="sv">WRI-dokument</comment>
+ <comment xml:lang="sr">ВРИ документ</comment>
+ <comment xml:lang="sq">dokument WRI</comment>
+ <comment xml:lang="sl">Dokument WRI</comment>
+ <comment xml:lang="si">WRI ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument WRI</comment>
+ <comment xml:lang="ru">Документ WRI</comment>
+ <comment xml:lang="ro">Document WRI</comment>
+ <comment xml:lang="pt_BR">Documento WRI</comment>
+ <comment xml:lang="pt">documento WRI</comment>
+ <comment xml:lang="pl">Dokument WRI</comment>
+ <comment xml:lang="oc">document WRI</comment>
+ <comment xml:lang="nn">WRI-dokument</comment>
+ <comment xml:lang="nl">WRI-document</comment>
+ <comment xml:lang="nb">WRI-dokument</comment>
+ <comment xml:lang="lv">WRI dokuments</comment>
+ <comment xml:lang="lt">WRI dokumentas</comment>
+ <comment xml:lang="ko">WRI 문서</comment>
+ <comment xml:lang="kk">WRI құжаты</comment>
+ <comment xml:lang="ja">WRI ドキュメント</comment>
+ <comment xml:lang="it">Documento WRI</comment>
+ <comment xml:lang="is">WRI skjal</comment>
+ <comment xml:lang="id">Dokumen WRI</comment>
+ <comment xml:lang="ia">Documento WRI</comment>
+ <comment xml:lang="hu">WRI dokumentum</comment>
+ <comment xml:lang="hr">WRI dokument</comment>
+ <comment xml:lang="he">מסמך WRI</comment>
+ <comment xml:lang="gl">documento WRI</comment>
+ <comment xml:lang="ga">cáipéis WRI</comment>
+ <comment xml:lang="fur">document WRI</comment>
+ <comment xml:lang="fr">document WRI</comment>
+ <comment xml:lang="fo">WRI skjal</comment>
+ <comment xml:lang="fi">WRI-asiakirja</comment>
+ <comment xml:lang="eu">WRI dokumentua</comment>
+ <comment xml:lang="es">documento WRI</comment>
+ <comment xml:lang="eo">WRI-dokumento</comment>
+ <comment xml:lang="en_GB">WRI document</comment>
+ <comment xml:lang="el">Έγγραφο WRI</comment>
+ <comment xml:lang="de">WRI-Dokument</comment>
+ <comment xml:lang="da">WRI-dokument</comment>
+ <comment xml:lang="cs">dokument WRI</comment>
+ <comment xml:lang="ca">document WRI</comment>
+ <comment xml:lang="bg">Документ — WRI</comment>
+ <comment xml:lang="be@latin">Dakument WRI</comment>
+ <comment xml:lang="be">дакумент WRI</comment>
+ <comment xml:lang="ast">Documentu WRI</comment>
+ <comment xml:lang="ar">مستند WRI</comment>
+ <comment xml:lang="af">WRI-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.wri"/>
</mime-type>
<mime-type type="application/x-msx-rom">
<comment>MSX ROM</comment>
- <comment xml:lang="ar">MSX ROM</comment>
- <comment xml:lang="be@latin">MSX ROM</comment>
- <comment xml:lang="bg">ROM — MSX</comment>
- <comment xml:lang="ca">ROM de MSX</comment>
- <comment xml:lang="cs">ROM pro MSX</comment>
- <comment xml:lang="cy">ROM MSX</comment>
- <comment xml:lang="da">MSX-rom</comment>
- <comment xml:lang="de">MSX ROM</comment>
- <comment xml:lang="el">MSX ROM</comment>
- <comment xml:lang="en_GB">MSX ROM</comment>
- <comment xml:lang="eo">MSX-NLM</comment>
- <comment xml:lang="es">ROM de MSX</comment>
- <comment xml:lang="eu">MSX-ko ROMa</comment>
- <comment xml:lang="fi">MSX-ROM</comment>
- <comment xml:lang="fo">MSX ROM</comment>
- <comment xml:lang="fr">ROM MSX</comment>
- <comment xml:lang="ga">ROM MSX</comment>
- <comment xml:lang="gl">ROM de MSX</comment>
- <comment xml:lang="he">MSX ROM</comment>
- <comment xml:lang="hr">MSX ROM</comment>
- <comment xml:lang="hu">MSX ROM</comment>
- <comment xml:lang="ia">ROM pro MSX</comment>
- <comment xml:lang="id">Memori baca-saja MSX</comment>
- <comment xml:lang="it">ROM MSX</comment>
- <comment xml:lang="ja">MSX ROM</comment>
- <comment xml:lang="ka">MSX-ის ROM</comment>
- <comment xml:lang="kk">MSX ROM</comment>
- <comment xml:lang="ko">MSX 롬</comment>
- <comment xml:lang="lt">MSX ROM</comment>
- <comment xml:lang="lv">MSX ROM</comment>
- <comment xml:lang="ms">ROM MSX</comment>
- <comment xml:lang="nb">MSX-ROM</comment>
- <comment xml:lang="nl">MSX-ROM</comment>
- <comment xml:lang="nn">MSX-ROM</comment>
- <comment xml:lang="oc">ROM MSX</comment>
- <comment xml:lang="pl">Plik ROM konsoli MSX</comment>
- <comment xml:lang="pt">ROM MSX</comment>
- <comment xml:lang="pt_BR">ROM de MSX</comment>
- <comment xml:lang="ro">ROM MSX</comment>
- <comment xml:lang="ru">MSX ROM</comment>
- <comment xml:lang="sk">ROM pre MSX</comment>
- <comment xml:lang="sl">Bralni pomnilnik MSX</comment>
- <comment xml:lang="sq">ROM MSX</comment>
- <comment xml:lang="sr">МСИкс РОМ</comment>
- <comment xml:lang="sv">MSX-rom</comment>
- <comment xml:lang="tr">MSX ROM</comment>
- <comment xml:lang="uk">ППП MSX</comment>
- <comment xml:lang="vi">ROM MSX</comment>
- <comment xml:lang="zh_CN">MSX ROM</comment>
<comment xml:lang="zh_TW">MSX ROM</comment>
+ <comment xml:lang="zh_CN">MSX ROM</comment>
+ <comment xml:lang="vi">ROM MSX</comment>
+ <comment xml:lang="uk">ППП MSX</comment>
+ <comment xml:lang="tr">MSX ROM</comment>
+ <comment xml:lang="sv">MSX-rom</comment>
+ <comment xml:lang="sr">МСИкс РОМ</comment>
+ <comment xml:lang="sq">ROM MSX</comment>
+ <comment xml:lang="sl">Bralni pomnilnik MSX</comment>
+ <comment xml:lang="si">MSX ROM</comment>
+ <comment xml:lang="sk">ROM pre MSX</comment>
+ <comment xml:lang="ru">MSX ROM</comment>
+ <comment xml:lang="ro">ROM MSX</comment>
+ <comment xml:lang="pt_BR">ROM de MSX</comment>
+ <comment xml:lang="pt">ROM MSX</comment>
+ <comment xml:lang="pl">Plik ROM konsoli MSX</comment>
+ <comment xml:lang="oc">ROM MSX</comment>
+ <comment xml:lang="nn">MSX-ROM</comment>
+ <comment xml:lang="nl">MSX-ROM</comment>
+ <comment xml:lang="nb">MSX-ROM</comment>
+ <comment xml:lang="ms">ROM MSX</comment>
+ <comment xml:lang="lv">MSX ROM</comment>
+ <comment xml:lang="lt">MSX ROM</comment>
+ <comment xml:lang="ko">MSX 롬</comment>
+ <comment xml:lang="kk">MSX ROM</comment>
+ <comment xml:lang="ka">MSX-ის ROM</comment>
+ <comment xml:lang="ja">MSX ROM</comment>
+ <comment xml:lang="it">ROM MSX</comment>
+ <comment xml:lang="is">MSX ROM</comment>
+ <comment xml:lang="id">Memori baca-saja MSX</comment>
+ <comment xml:lang="ia">ROM pro MSX</comment>
+ <comment xml:lang="hu">MSX ROM</comment>
+ <comment xml:lang="hr">MSX ROM</comment>
+ <comment xml:lang="he">MSX ROM</comment>
+ <comment xml:lang="gl">ROM de MSX</comment>
+ <comment xml:lang="ga">ROM MSX</comment>
+ <comment xml:lang="fur">ROM MSX</comment>
+ <comment xml:lang="fr">ROM MSX</comment>
+ <comment xml:lang="fo">MSX ROM</comment>
+ <comment xml:lang="fi">MSX-ROM</comment>
+ <comment xml:lang="eu">MSX-ko ROMa</comment>
+ <comment xml:lang="es">ROM de MSX</comment>
+ <comment xml:lang="eo">MSX-NLM</comment>
+ <comment xml:lang="en_GB">MSX ROM</comment>
+ <comment xml:lang="el">MSX ROM</comment>
+ <comment xml:lang="de">MSX-ROM</comment>
+ <comment xml:lang="da">MSX-ROM</comment>
+ <comment xml:lang="cy">ROM MSX</comment>
+ <comment xml:lang="cs">ROM pro MSX</comment>
+ <comment xml:lang="ca">ROM de MSX</comment>
+ <comment xml:lang="bg">ROM — MSX</comment>
+ <comment xml:lang="be@latin">MSX ROM</comment>
+ <comment xml:lang="be">MSX ROM</comment>
+ <comment xml:lang="ar">روم MSX</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.msx"/>
</mime-type>
<mime-type type="application/x-m4">
<comment>M4 macro</comment>
- <comment xml:lang="ar">M4 macro</comment>
- <comment xml:lang="be@latin">Makras M4</comment>
- <comment xml:lang="bg">Макроси — M4</comment>
- <comment xml:lang="ca">macro M4</comment>
- <comment xml:lang="cs">makro M4</comment>
- <comment xml:lang="da">M4-makro</comment>
- <comment xml:lang="de">M4-Makro</comment>
- <comment xml:lang="el">Μακροεντολή m4</comment>
- <comment xml:lang="en_GB">M4 macro</comment>
- <comment xml:lang="es">macro M4</comment>
- <comment xml:lang="eu">M4 makroa</comment>
- <comment xml:lang="fi">M4-makro</comment>
- <comment xml:lang="fo">M4 fjølvi</comment>
- <comment xml:lang="fr">macro M4</comment>
- <comment xml:lang="ga">macra M4</comment>
- <comment xml:lang="gl">macro M4</comment>
- <comment xml:lang="he">מאקרו M4</comment>
- <comment xml:lang="hr">M4 makro</comment>
- <comment xml:lang="hu">M4 makró</comment>
- <comment xml:lang="ia">Macro M4</comment>
- <comment xml:lang="id">Makro M4</comment>
- <comment xml:lang="it">Macro M4</comment>
- <comment xml:lang="ja">M4 マクロ</comment>
- <comment xml:lang="kk">M4 макросы</comment>
- <comment xml:lang="ko">M4 매크로</comment>
- <comment xml:lang="lt">M4 macro</comment>
- <comment xml:lang="lv">M4 makross</comment>
- <comment xml:lang="nb">M4-makro</comment>
- <comment xml:lang="nl">M4-macro</comment>
- <comment xml:lang="nn">M4-makro</comment>
- <comment xml:lang="oc">macro M4</comment>
- <comment xml:lang="pl">Makro M4</comment>
- <comment xml:lang="pt">macro M4</comment>
- <comment xml:lang="pt_BR">Macro M4</comment>
- <comment xml:lang="ro">Macro M4</comment>
- <comment xml:lang="ru">Макрос M4</comment>
- <comment xml:lang="sk">Makro M4</comment>
- <comment xml:lang="sl">Makro datoteka M4</comment>
- <comment xml:lang="sq">Macro M4</comment>
- <comment xml:lang="sr">М4 макро</comment>
- <comment xml:lang="sv">M4-makro</comment>
- <comment xml:lang="tr">M4 makrosu</comment>
- <comment xml:lang="uk">макрос M4</comment>
- <comment xml:lang="vi">Vĩ lệnh M4</comment>
- <comment xml:lang="zh_CN">M4 宏</comment>
<comment xml:lang="zh_TW">M4 巨集</comment>
+ <comment xml:lang="zh_CN">M4 宏</comment>
+ <comment xml:lang="vi">Vĩ lệnh M4</comment>
+ <comment xml:lang="uk">макрос M4</comment>
+ <comment xml:lang="tr">M4 makrosu</comment>
+ <comment xml:lang="sv">M4-makro</comment>
+ <comment xml:lang="sr">М4 макро</comment>
+ <comment xml:lang="sq">Macro M4</comment>
+ <comment xml:lang="sl">Makro datoteka M4</comment>
+ <comment xml:lang="si">M4 මැක්රෝ</comment>
+ <comment xml:lang="sk">Makro M4</comment>
+ <comment xml:lang="ru">Макрос M4</comment>
+ <comment xml:lang="ro">Macro M4</comment>
+ <comment xml:lang="pt_BR">Macro M4</comment>
+ <comment xml:lang="pt">macro M4</comment>
+ <comment xml:lang="pl">Makro M4</comment>
+ <comment xml:lang="oc">macro M4</comment>
+ <comment xml:lang="nn">M4-makro</comment>
+ <comment xml:lang="nl">M4-macro</comment>
+ <comment xml:lang="nb">M4-makro</comment>
+ <comment xml:lang="lv">M4 makross</comment>
+ <comment xml:lang="lt">M4 macro</comment>
+ <comment xml:lang="ko">M4 매크로</comment>
+ <comment xml:lang="kk">M4 макросы</comment>
+ <comment xml:lang="ja">M4 マクロ</comment>
+ <comment xml:lang="it">Macro M4</comment>
+ <comment xml:lang="is">M4 fjölvi</comment>
+ <comment xml:lang="id">Makro M4</comment>
+ <comment xml:lang="ia">Macro M4</comment>
+ <comment xml:lang="hu">M4 makró</comment>
+ <comment xml:lang="hr">M4 makro</comment>
+ <comment xml:lang="he">מאקרו M4</comment>
+ <comment xml:lang="gl">macro M4</comment>
+ <comment xml:lang="ga">macra M4</comment>
+ <comment xml:lang="fur">macro M4</comment>
+ <comment xml:lang="fr">macro M4</comment>
+ <comment xml:lang="fo">M4 fjølvi</comment>
+ <comment xml:lang="fi">M4-makro</comment>
+ <comment xml:lang="eu">M4 makroa</comment>
+ <comment xml:lang="es">macro M4</comment>
+ <comment xml:lang="en_GB">M4 macro</comment>
+ <comment xml:lang="el">Μακροεντολή m4</comment>
+ <comment xml:lang="de">M4-Makro</comment>
+ <comment xml:lang="da">M4-makro</comment>
+ <comment xml:lang="cs">makro M4</comment>
+ <comment xml:lang="ca">macro M4</comment>
+ <comment xml:lang="bg">Макроси — M4</comment>
+ <comment xml:lang="be@latin">Makras M4</comment>
+ <comment xml:lang="be">макрас M4</comment>
+ <comment xml:lang="ar">ماكرو M4</comment>
+ <comment xml:lang="af">M4-makro</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.m4"/>
</mime-type>
<mime-type type="application/x-n64-rom">
<comment>Nintendo64 ROM</comment>
- <comment xml:lang="ar">Nintendo64 ROM</comment>
- <comment xml:lang="be@latin">Nintendo64 ROM</comment>
- <comment xml:lang="bg">ROM — Nintendo64</comment>
- <comment xml:lang="ca">ROM de Nintendo64</comment>
- <comment xml:lang="cs">ROM pro Nintendo64</comment>
- <comment xml:lang="da">Nintendo64-rom</comment>
- <comment xml:lang="de">Nintendo64 ROM</comment>
- <comment xml:lang="el">Nintendo64 ROM</comment>
- <comment xml:lang="en_GB">Nintendo64 ROM</comment>
- <comment xml:lang="eo">Nintendo64-NLM</comment>
- <comment xml:lang="es">ROM de Nintendo64</comment>
- <comment xml:lang="eu">Nintendo64-ko ROMa</comment>
- <comment xml:lang="fi">Nintendo64-ROM</comment>
- <comment xml:lang="fo">Nintendo64 ROM</comment>
- <comment xml:lang="fr">ROM Nintendo64</comment>
- <comment xml:lang="ga">ROM Nintendo64</comment>
- <comment xml:lang="gl">ROM de Nintendo64</comment>
- <comment xml:lang="he">ROM של Nintendo64</comment>
- <comment xml:lang="hr">Nintendo64 ROM</comment>
- <comment xml:lang="hu">Nintendo64 ROM</comment>
- <comment xml:lang="ia">ROM pro Nintendo64</comment>
- <comment xml:lang="id">Memori baca-saja Nintendo64</comment>
- <comment xml:lang="it">ROM Nintendo64</comment>
- <comment xml:lang="ja">Nintendo64 ROM</comment>
- <comment xml:lang="kk">Nintendo64 ROM</comment>
- <comment xml:lang="ko">닌텐도 64 롬</comment>
- <comment xml:lang="lt">Nintendo64 ROM</comment>
- <comment xml:lang="lv">Nintendo64 ROM</comment>
- <comment xml:lang="ms">ROM Nintendo64</comment>
- <comment xml:lang="nb">Nintendo64-ROM</comment>
- <comment xml:lang="nl">Nintendo64-ROM</comment>
- <comment xml:lang="nn">Nintendo64-ROM</comment>
- <comment xml:lang="oc">ROM Nintendo64</comment>
- <comment xml:lang="pl">Plik ROM konsoli Nintendo64</comment>
- <comment xml:lang="pt">ROM Nintendo64</comment>
- <comment xml:lang="pt_BR">ROM de Nintendo64</comment>
- <comment xml:lang="ro">ROM Nintendo64</comment>
- <comment xml:lang="ru">Nintendo64 ROM</comment>
- <comment xml:lang="sk">ROM pre Nintendo64</comment>
- <comment xml:lang="sl">Bralni pomnilnik Nintendo64</comment>
- <comment xml:lang="sq">ROM Nintendo64</comment>
- <comment xml:lang="sr">Нинтендо64 РОМ</comment>
- <comment xml:lang="sv">Nintendo64-rom</comment>
- <comment xml:lang="tr">Nintendo64 ROM</comment>
- <comment xml:lang="uk">ППП Nintendo64</comment>
- <comment xml:lang="vi">ROM Nintendo64</comment>
- <comment xml:lang="zh_CN">任天堂 64 ROM</comment>
<comment xml:lang="zh_TW">Nintendo64 ROM</comment>
+ <comment xml:lang="zh_CN">任天堂 64 ROM</comment>
+ <comment xml:lang="vi">ROM Nintendo64</comment>
+ <comment xml:lang="uk">ППП Nintendo64</comment>
+ <comment xml:lang="tr">Nintendo64 ROM</comment>
+ <comment xml:lang="sv">Nintendo64-rom</comment>
+ <comment xml:lang="sr">Нинтендо64 РОМ</comment>
+ <comment xml:lang="sq">ROM Nintendo64</comment>
+ <comment xml:lang="sl">Bralni pomnilnik Nintendo64</comment>
+ <comment xml:lang="si">Nintendo64 ROM</comment>
+ <comment xml:lang="sk">ROM pre Nintendo64</comment>
+ <comment xml:lang="ru">Nintendo64 ROM</comment>
+ <comment xml:lang="ro">ROM Nintendo64</comment>
+ <comment xml:lang="pt_BR">ROM de Nintendo64</comment>
+ <comment xml:lang="pt">ROM Nintendo64</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Nintendo64</comment>
+ <comment xml:lang="oc">ROM Nintendo64</comment>
+ <comment xml:lang="nn">Nintendo64-ROM</comment>
+ <comment xml:lang="nl">Nintendo64-ROM</comment>
+ <comment xml:lang="nb">Nintendo64-ROM</comment>
+ <comment xml:lang="ms">ROM Nintendo64</comment>
+ <comment xml:lang="lv">Nintendo64 ROM</comment>
+ <comment xml:lang="lt">Nintendo64 ROM</comment>
+ <comment xml:lang="ko">닌텐도 64 롬</comment>
+ <comment xml:lang="kk">Nintendo64 ROM</comment>
+ <comment xml:lang="ja">Nintendo64 ROM</comment>
+ <comment xml:lang="it">ROM Nintendo64</comment>
+ <comment xml:lang="is">Nintendo64 ROM</comment>
+ <comment xml:lang="id">Memori baca-saja Nintendo64</comment>
+ <comment xml:lang="ia">ROM pro Nintendo64</comment>
+ <comment xml:lang="hu">Nintendo64 ROM</comment>
+ <comment xml:lang="hr">Nintendo64 ROM</comment>
+ <comment xml:lang="he">ROM של Nintendo64</comment>
+ <comment xml:lang="gl">ROM de Nintendo64</comment>
+ <comment xml:lang="ga">ROM Nintendo64</comment>
+ <comment xml:lang="fur">ROM Nintendo64</comment>
+ <comment xml:lang="fr">ROM Nintendo64</comment>
+ <comment xml:lang="fo">Nintendo64 ROM</comment>
+ <comment xml:lang="fi">Nintendo64-ROM</comment>
+ <comment xml:lang="eu">Nintendo64-ko ROMa</comment>
+ <comment xml:lang="es">ROM de Nintendo64</comment>
+ <comment xml:lang="eo">Nintendo64-NLM</comment>
+ <comment xml:lang="en_GB">Nintendo64 ROM</comment>
+ <comment xml:lang="el">Nintendo64 ROM</comment>
+ <comment xml:lang="de">Nintendo64-ROM</comment>
+ <comment xml:lang="da">Nintendo64-ROM</comment>
+ <comment xml:lang="cs">ROM pro Nintendo64</comment>
+ <comment xml:lang="ca">ROM de Nintendo64</comment>
+ <comment xml:lang="bg">ROM — Nintendo64</comment>
+ <comment xml:lang="be@latin">Nintendo64 ROM</comment>
+ <comment xml:lang="be">Nintendo64 ROM</comment>
+ <comment xml:lang="ar">روم Nintendo64</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.n64"/>
<glob pattern="*.z64"/>
<glob pattern="*.v64"/>
<magic>
-
- <match value="0x80371240" type="big32" offset="0"/>
-
- <match value="0x37804012" type="big32" offset="0"/>
-
- <match value="0x40123780" type="big32" offset="0"/>
+ <!-- native *.z64 -->
+ <match type="big32" offset="0" value="0x80371240"/>
+ <!-- byteswapped [BADC] *.v64 -->
+ <match type="big32" offset="0" value="0x37804012"/>
+ <!-- wordswapped [DCBA] *.n64 -->
+ <match type="big32" offset="0" value="0x40123780"/>
</magic>
</mime-type>
<mime-type type="application/x-nautilus-link">
<comment>Nautilus link</comment>
- <comment xml:lang="ar">وصلة Nautilus</comment>
- <comment xml:lang="az">Nautilus körpüsü</comment>
- <comment xml:lang="be@latin">Spasyłka Nautilus</comment>
- <comment xml:lang="bg">Връзка — Nautilus</comment>
- <comment xml:lang="ca">enllaç de Nautilus</comment>
- <comment xml:lang="cs">odkaz Nautilus</comment>
- <comment xml:lang="cy">Cyswllt Nautilus</comment>
- <comment xml:lang="da">Nautilus-henvisning</comment>
- <comment xml:lang="de">Nautilus-Verknüpfung</comment>
- <comment xml:lang="el">Σύνδεσμος Nautilus</comment>
- <comment xml:lang="en_GB">Nautilus link</comment>
- <comment xml:lang="eo">Nautilus-ligilo</comment>
- <comment xml:lang="es">enlace de Nautilus</comment>
- <comment xml:lang="eu">Nautilus esteka</comment>
- <comment xml:lang="fi">Nautilus-linkki</comment>
- <comment xml:lang="fo">Nautilus leinkja</comment>
- <comment xml:lang="fr">lien Nautilus</comment>
- <comment xml:lang="ga">nasc Nautilus</comment>
- <comment xml:lang="gl">ligazón de nautilus</comment>
- <comment xml:lang="he">קישור של Nautilus</comment>
- <comment xml:lang="hr">Nautilusova poveznica</comment>
- <comment xml:lang="hu">Nautilus-link</comment>
- <comment xml:lang="ia">Ligamine Nautilus</comment>
- <comment xml:lang="id">Taut Nautilus</comment>
- <comment xml:lang="it">Collegamento Nautilus</comment>
- <comment xml:lang="ja">Nautilus リンク</comment>
- <comment xml:lang="kk">Nautilus сілтемесі</comment>
- <comment xml:lang="ko">노틸러스 바로 가기</comment>
- <comment xml:lang="lt">Nautilus nuoroda</comment>
- <comment xml:lang="lv">Nautilus saite</comment>
- <comment xml:lang="ms">Pautan Nautilus</comment>
- <comment xml:lang="nb">Nautilus-lenke</comment>
- <comment xml:lang="nl">Nautilus-verwijzing</comment>
- <comment xml:lang="nn">Nautilus-lenke</comment>
- <comment xml:lang="oc">ligam Nautilus</comment>
- <comment xml:lang="pl">Odnośnik Nautilus</comment>
- <comment xml:lang="pt">atalho Nautilus</comment>
- <comment xml:lang="pt_BR">Link do Nautilus</comment>
- <comment xml:lang="ro">Legătură Nautilus</comment>
- <comment xml:lang="ru">Ссылка Nautilus</comment>
- <comment xml:lang="sk">Odkaz Nautilus</comment>
- <comment xml:lang="sl">Datoteka povezave Nautilus</comment>
- <comment xml:lang="sq">Lidhje Nautilus</comment>
- <comment xml:lang="sr">Наутилусова веза</comment>
- <comment xml:lang="sv">Nautiluslänk</comment>
- <comment xml:lang="tr">Nautilus bağlantısı</comment>
- <comment xml:lang="uk">посилання Nautilus</comment>
- <comment xml:lang="vi">Liên kết Nautilus</comment>
+ <comment xml:lang="zh_TW">Nautilus 連結</comment>
<comment xml:lang="zh_CN">Nautilus 链接</comment>
- <comment xml:lang="zh_TW">Nautilus 鏈結</comment>
+ <comment xml:lang="vi">Liên kết Nautilus</comment>
+ <comment xml:lang="uk">посилання Nautilus</comment>
+ <comment xml:lang="tr">Nautilus bağlantısı</comment>
+ <comment xml:lang="sv">Nautiluslänk</comment>
+ <comment xml:lang="sr">Наутилусова веза</comment>
+ <comment xml:lang="sq">lidhje Nautilus</comment>
+ <comment xml:lang="sl">Datoteka povezave Nautilus</comment>
+ <comment xml:lang="si">Nautilus සබැඳිය</comment>
+ <comment xml:lang="sk">Odkaz Nautilus</comment>
+ <comment xml:lang="ru">Ссылка Nautilus</comment>
+ <comment xml:lang="ro">Legătură Nautilus</comment>
+ <comment xml:lang="pt_BR">Link do Nautilus</comment>
+ <comment xml:lang="pt">atalho Nautilus</comment>
+ <comment xml:lang="pl">Odnośnik Nautilus</comment>
+ <comment xml:lang="oc">ligam Nautilus</comment>
+ <comment xml:lang="nn">Nautilus-lenke</comment>
+ <comment xml:lang="nl">Nautilus-verwijzing</comment>
+ <comment xml:lang="nb">Nautilus-lenke</comment>
+ <comment xml:lang="ms">Pautan Nautilus</comment>
+ <comment xml:lang="lv">Nautilus saite</comment>
+ <comment xml:lang="lt">Nautilus nuoroda</comment>
+ <comment xml:lang="ko">노틸러스 바로 가기</comment>
+ <comment xml:lang="kk">Nautilus сілтемесі</comment>
+ <comment xml:lang="ja">Nautilus リンク</comment>
+ <comment xml:lang="it">Collegamento Nautilus</comment>
+ <comment xml:lang="is">Nautilus tengill</comment>
+ <comment xml:lang="id">Taut Nautilus</comment>
+ <comment xml:lang="ia">Ligamine Nautilus</comment>
+ <comment xml:lang="hu">Nautilus-link</comment>
+ <comment xml:lang="hr">Nautilusova poveznica</comment>
+ <comment xml:lang="he">קישור של Nautilus</comment>
+ <comment xml:lang="gl">ligazón de nautilus</comment>
+ <comment xml:lang="ga">nasc Nautilus</comment>
+ <comment xml:lang="fur">colegament Nautilus</comment>
+ <comment xml:lang="fr">lien Nautilus</comment>
+ <comment xml:lang="fo">Nautilus leinkja</comment>
+ <comment xml:lang="fi">Nautilus-linkki</comment>
+ <comment xml:lang="eu">Nautilus esteka</comment>
+ <comment xml:lang="es">enlace de Nautilus</comment>
+ <comment xml:lang="eo">Nautilus-ligilo</comment>
+ <comment xml:lang="en_GB">Nautilus link</comment>
+ <comment xml:lang="el">Σύνδεσμος Nautilus</comment>
+ <comment xml:lang="de">Nautilus-Verknüpfung</comment>
+ <comment xml:lang="da">Nautilus-henvisning</comment>
+ <comment xml:lang="cy">Cyswllt Nautilus</comment>
+ <comment xml:lang="cs">odkaz Nautilus</comment>
+ <comment xml:lang="ca">enllaç de Nautilus</comment>
+ <comment xml:lang="bg">Връзка — Nautilus</comment>
+ <comment xml:lang="be@latin">Spasyłka Nautilus</comment>
+ <comment xml:lang="be">спасылка Nautilus</comment>
+ <comment xml:lang="az">Nautilus körpüsü</comment>
+ <comment xml:lang="ar">وصلة Nautilus</comment>
+ <comment xml:lang="af">Nautilus-skakel</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="&lt;nautilus_object nautilus_link" type="string" offset="0:32"/>
+ <magic>
+ <match type="string" value="&lt;nautilus_object nautilus_link" offset="0:32"/>
</magic>
</mime-type>
<mime-type type="application/x-neo-geo-pocket-rom">
<comment>Neo-Geo Pocket ROM</comment>
- <comment xml:lang="ca">ROM de Neo-Geo Pocket</comment>
- <comment xml:lang="cs">ROM pro Neo-Geo Pocket</comment>
- <comment xml:lang="da">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="de">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="en_GB">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="es">ROM de Neo-Geo Pocket</comment>
- <comment xml:lang="eu">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="fi">Neo-Geo Pocket -ROM</comment>
- <comment xml:lang="fr">ROM Neo-Geo Pocket</comment>
- <comment xml:lang="ga">ROM Neo-Geo Pocket</comment>
- <comment xml:lang="hr">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="hu">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="id">ROM Neo-Geo Pocket</comment>
- <comment xml:lang="it">ROM Neo-Geo Pocket</comment>
- <comment xml:lang="kk">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="ko">네오지오 포켓 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Neo-Geo Pocket</comment>
- <comment xml:lang="pt_BR">ROM de Neo-Geo Pocket</comment>
- <comment xml:lang="ru">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="sk">ROM pre Neo-Geo Pocket</comment>
- <comment xml:lang="sr">Нео-Гео Покет РОМ</comment>
- <comment xml:lang="sv">Neo-Geo Pocket-rom</comment>
- <comment xml:lang="tr">Neo-Geo Pocket ROM</comment>
- <comment xml:lang="uk">ППП Neo-Geo Pocket</comment>
- <comment xml:lang="zh_CN">Neo-Geo Pocket ROM</comment>
<comment xml:lang="zh_TW">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="zh_CN">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="uk">ППП Neo-Geo Pocket</comment>
+ <comment xml:lang="tr">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="sv">Neo-Geo Pocket-rom</comment>
+ <comment xml:lang="sr">Нео-Гео Покет РОМ</comment>
+ <comment xml:lang="sq">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="sl">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="si">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="sk">ROM pre Neo-Geo Pocket</comment>
+ <comment xml:lang="ru">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Neo-Geo Pocket</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Neo-Geo Pocket</comment>
+ <comment xml:lang="nl">Neo-Geo Pocket-ROM</comment>
+ <comment xml:lang="ko">네오지오 포켓 롬</comment>
+ <comment xml:lang="kk">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="ja">ネオジオポケット ROM</comment>
+ <comment xml:lang="it">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="is">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="id">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="hu">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="hr">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="he">ROM מסוג Neo-Geo Pocket</comment>
+ <comment xml:lang="gl">ROM de Neo-Geo Pocket</comment>
+ <comment xml:lang="ga">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="fur">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="fr">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="fi">Neo-Geo Pocket -ROM</comment>
+ <comment xml:lang="eu">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="es">ROM de Neo-Geo Pocket</comment>
+ <comment xml:lang="en_GB">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="de">Neo-Geo-Pocket-ROM</comment>
+ <comment xml:lang="da">Neo-Geo Pocket-ROM</comment>
+ <comment xml:lang="cs">ROM pro Neo-Geo Pocket</comment>
+ <comment xml:lang="ca">ROM de Neo-Geo Pocket</comment>
+ <comment xml:lang="bg">ROM — Neo-Geo Pocket</comment>
+ <comment xml:lang="be">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="ar">روم Neo-Geo Pocket</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.ngp"/>
<magic>
- <match value="0x0" type="byte" offset="35">
- <match value="COPYRIGHT BY SNK CORPORATION" type="string" offset="0"/>
- <match value=" LICENSED BY SNK CORPORATION" type="string" offset="0"/>
+ <match offset="35" type="byte" value="0x0">
+ <match offset="0" type="string" value="COPYRIGHT BY SNK CORPORATION"/>
+ <match offset="0" type="string" value=" LICENSED BY SNK CORPORATION"/>
</match>
</magic>
</mime-type>
<mime-type type="application/x-neo-geo-pocket-color-rom">
<comment>Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="zh_TW">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="zh_CN">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="uk">ППП Neo-Geo Pocket Color</comment>
+ <comment xml:lang="tr">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="sv">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="sq">ROM Neo-Geo Pocket Color</comment>
+ <comment xml:lang="sl">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="si">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="sk">ROM pre Neo-Geo Pocket Color</comment>
+ <comment xml:lang="ru">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Neo-Geo Pocket Color</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Neo-Geo Pocket Color</comment>
+ <comment xml:lang="nl">Neo-Geo Pocket Color-ROM</comment>
+ <comment xml:lang="ko">네오지오 포켓 컬러 롬</comment>
+ <comment xml:lang="kk">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="ja">ネオジオポケットカラー ROM</comment>
+ <comment xml:lang="it">ROM Neo-Geo Pocket Color</comment>
+ <comment xml:lang="is">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="id">ROM Neo-Geo Pocket Color</comment>
+ <comment xml:lang="hu">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="hr">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="he">ROM של Neo-Geo Pocket</comment>
+ <comment xml:lang="gl">ROM de Neo-Geo Pocket Color</comment>
+ <comment xml:lang="ga">ROM datha Neo-Geo Pocket</comment>
+ <comment xml:lang="fur">ROM Neo-Geo Pocket Color</comment>
+ <comment xml:lang="fr">ROM Neo-Geo Pocket Color</comment>
+ <comment xml:lang="fi">Neo-Geo Pocket Color -ROM</comment>
+ <comment xml:lang="eu">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="es">ROM de Neo-Geo Pocket Color</comment>
+ <comment xml:lang="en_GB">Neo-Geo Pocket Colour ROM</comment>
+ <comment xml:lang="de">Neo-Geo-Pocket-Color-ROM</comment>
+ <comment xml:lang="da">Neo-Geo Pocket Color-ROM</comment>
+ <comment xml:lang="cs">ROM pro Neo-Geo Pocket Color</comment>
+ <comment xml:lang="ca">ROM de Neo-Geo Pocket Color</comment>
+ <comment xml:lang="bg">ROM — Neo-Geo Pocket Color</comment>
+ <comment xml:lang="be">Neo-Geo Pocket Color ROM</comment>
+ <comment xml:lang="ar">روم Neo-Geo Pocket Color</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.ngc"/>
<magic>
- <match value="0x10" type="byte" offset="35">
- <match value="COPYRIGHT BY SNK CORPORATION" type="string" offset="0"/>
- <match value=" LICENSED BY SNK CORPORATION" type="string" offset="0"/>
+ <match offset="35" type="byte" value="0x10">
+ <match offset="0" type="string" value="COPYRIGHT BY SNK CORPORATION"/>
+ <match offset="0" type="string" value=" LICENSED BY SNK CORPORATION"/>
</match>
</magic>
</mime-type>
<mime-type type="application/x-nes-rom">
-
+ <!-- Translate this to Famicom if the console was known as such in your locale -->
<comment>NES ROM</comment>
- <comment xml:lang="ar">NES ROM</comment>
- <comment xml:lang="be@latin">NES ROM</comment>
- <comment xml:lang="bg">ROM — NES</comment>
- <comment xml:lang="ca">ROM de NES</comment>
- <comment xml:lang="cs">ROM pro NES</comment>
- <comment xml:lang="cy">ROM NES</comment>
- <comment xml:lang="da">NES-rom</comment>
- <comment xml:lang="de">NES ROM</comment>
- <comment xml:lang="el">NES ROM</comment>
- <comment xml:lang="en_GB">NES ROM</comment>
- <comment xml:lang="eo">NES-NLM</comment>
- <comment xml:lang="es">ROM de NES</comment>
- <comment xml:lang="eu">NES-eko ROMa</comment>
- <comment xml:lang="fi">NES-ROM</comment>
- <comment xml:lang="fo">NES ROM</comment>
- <comment xml:lang="fr">ROM NES</comment>
- <comment xml:lang="ga">ROM NES</comment>
- <comment xml:lang="gl">ROM de NES</comment>
- <comment xml:lang="he">ROM של NES</comment>
- <comment xml:lang="hr">NES ROM</comment>
- <comment xml:lang="hu">NES ROM</comment>
- <comment xml:lang="ia">ROM pro NES</comment>
- <comment xml:lang="id">Memori baca-saja NES</comment>
- <comment xml:lang="it">ROM NES</comment>
- <comment xml:lang="ja">ファミコン ROM</comment>
- <comment xml:lang="kk">NES ROM</comment>
- <comment xml:lang="ko">NES 롬</comment>
- <comment xml:lang="lt">NES ROM</comment>
- <comment xml:lang="lv">NES ROM</comment>
- <comment xml:lang="ms">ROM NES</comment>
- <comment xml:lang="nb">NES ROM</comment>
- <comment xml:lang="nl">Nintendo</comment>
- <comment xml:lang="nn">NES-ROM</comment>
- <comment xml:lang="oc">ROM NES</comment>
- <comment xml:lang="pl">Plik ROM konsoli NES</comment>
- <comment xml:lang="pt">ROM NES</comment>
- <comment xml:lang="pt_BR">ROM de NES</comment>
- <comment xml:lang="ro">ROM NES</comment>
- <comment xml:lang="ru">NES ROM</comment>
- <comment xml:lang="sk">ROM pre NES</comment>
- <comment xml:lang="sl">Bralni pomnilnik NES</comment>
- <comment xml:lang="sq">ROM NES</comment>
- <comment xml:lang="sr">НЕС РОМ</comment>
- <comment xml:lang="sv">NES-rom</comment>
- <comment xml:lang="tr">NES ROM</comment>
- <comment xml:lang="uk">ППП NES</comment>
- <comment xml:lang="vi">ROM NES</comment>
+ <comment xml:lang="zh_TW">任天堂紅白機 ROM</comment>
<comment xml:lang="zh_CN">NES ROM</comment>
- <comment xml:lang="zh_TW">任天堂 ROM</comment>
+ <comment xml:lang="vi">ROM NES</comment>
+ <comment xml:lang="uk">ППП NES</comment>
+ <comment xml:lang="tr">NES ROM</comment>
+ <comment xml:lang="sv">NES-rom</comment>
+ <comment xml:lang="sr">НЕС РОМ</comment>
+ <comment xml:lang="sq">ROM NES</comment>
+ <comment xml:lang="sl">Bralni pomnilnik NES</comment>
+ <comment xml:lang="si">NES ROM</comment>
+ <comment xml:lang="sk">ROM pre NES</comment>
+ <comment xml:lang="ru">NES ROM</comment>
+ <comment xml:lang="ro">ROM NES</comment>
+ <comment xml:lang="pt_BR">ROM de NES</comment>
+ <comment xml:lang="pt">ROM NES</comment>
+ <comment xml:lang="pl">Plik ROM konsoli NES</comment>
+ <comment xml:lang="oc">ROM NES</comment>
+ <comment xml:lang="nn">NES-ROM</comment>
+ <comment xml:lang="nl">Super Nintendo-ROM</comment>
+ <comment xml:lang="nb">NES ROM</comment>
+ <comment xml:lang="ms">ROM NES</comment>
+ <comment xml:lang="lv">NES ROM</comment>
+ <comment xml:lang="lt">NES ROM</comment>
+ <comment xml:lang="ko">NES 롬</comment>
+ <comment xml:lang="kk">NES ROM</comment>
+ <comment xml:lang="ja">ファミコン ROM</comment>
+ <comment xml:lang="it">ROM NES</comment>
+ <comment xml:lang="is">NES ROM</comment>
+ <comment xml:lang="id">Memori baca-saja NES</comment>
+ <comment xml:lang="ia">ROM pro NES</comment>
+ <comment xml:lang="hu">NES ROM</comment>
+ <comment xml:lang="hr">NES ROM</comment>
+ <comment xml:lang="he">ROM של NES</comment>
+ <comment xml:lang="gl">ROM de NES</comment>
+ <comment xml:lang="ga">ROM NES</comment>
+ <comment xml:lang="fur">ROM NES</comment>
+ <comment xml:lang="fr">ROM NES</comment>
+ <comment xml:lang="fo">NES ROM</comment>
+ <comment xml:lang="fi">NES-ROM</comment>
+ <comment xml:lang="eu">NES-eko ROMa</comment>
+ <comment xml:lang="es">ROM de NES</comment>
+ <comment xml:lang="eo">NES-NLM</comment>
+ <comment xml:lang="en_GB">NES ROM</comment>
+ <comment xml:lang="el">NES ROM</comment>
+ <comment xml:lang="de">NES-ROM</comment>
+ <comment xml:lang="da">NES-ROM</comment>
+ <comment xml:lang="cy">ROM NES</comment>
+ <comment xml:lang="cs">ROM pro NES</comment>
+ <comment xml:lang="ca">ROM de NES</comment>
+ <comment xml:lang="bg">ROM — NES</comment>
+ <comment xml:lang="be@latin">NES ROM</comment>
+ <comment xml:lang="be">NES ROM</comment>
+ <comment xml:lang="ar">روم NES</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.nes"/>
<glob pattern="*.nez"/>
@@ -16695,55 +18301,59 @@
</mime-type>
<mime-type type="application/x-netcdf">
<comment>Unidata NetCDF document</comment>
- <comment xml:lang="ar">مستند Unidata NetCDF</comment>
- <comment xml:lang="ast">Documentu NetCDF d'Unidata</comment>
- <comment xml:lang="be@latin">Dakument Unidata NetCDF</comment>
- <comment xml:lang="bg">Документ — Unidata NetCDF</comment>
- <comment xml:lang="ca">document d'Unidata NetCDF</comment>
- <comment xml:lang="cs">dokument Unidata NetCDF</comment>
- <comment xml:lang="da">Unidata NetCDF-dokument</comment>
- <comment xml:lang="de">Unidata-NetCDF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Unidata NetCDF</comment>
- <comment xml:lang="en_GB">Unidata NetCDF document</comment>
- <comment xml:lang="eo">dokumento en NetCDF-formato de Unidata</comment>
- <comment xml:lang="es">documento de Unidata NetCDF</comment>
- <comment xml:lang="eu">Unidata NetCDF dokumentua</comment>
- <comment xml:lang="fi">Unidata NetCDF -asiakirja</comment>
- <comment xml:lang="fo">Unidata NetCDF skjal</comment>
- <comment xml:lang="fr">document Unidata NetCDF</comment>
- <comment xml:lang="ga">cáipéis Unidata NetCDF</comment>
- <comment xml:lang="gl">Documentno de Unixdata NetCDF</comment>
- <comment xml:lang="he">מסמך של Unidata NetCDF</comment>
- <comment xml:lang="hr">Unidata NetCDF dokument</comment>
- <comment xml:lang="hu">Unidata NetCDF-dokumentum</comment>
- <comment xml:lang="ia">Documento Unidata NetCDF</comment>
- <comment xml:lang="id">Dokumen Unidata NetCDF</comment>
- <comment xml:lang="it">Documento Unidata NetCDF</comment>
- <comment xml:lang="ja">Unidata NetCDF ドキュメント</comment>
- <comment xml:lang="kk">Unidata NetCDF құжаты</comment>
- <comment xml:lang="ko">Unidata NetCDF 문서</comment>
- <comment xml:lang="lt">Unidata NetCDF dokumentas</comment>
- <comment xml:lang="lv">Unidata NetCDF dokuments</comment>
- <comment xml:lang="ms">Dokumen Unidata NetCDF</comment>
- <comment xml:lang="nb">Unidata NetCDF-dokument</comment>
- <comment xml:lang="nl">Unidata NetCDF-document</comment>
- <comment xml:lang="nn">Unidata netCDF-dokument</comment>
- <comment xml:lang="oc">document Unidata NetCDF</comment>
- <comment xml:lang="pl">Dokument Unidata NetCDF</comment>
- <comment xml:lang="pt">documento Unidata NetCDF</comment>
- <comment xml:lang="pt_BR">Documento do Unidata NetCDF</comment>
- <comment xml:lang="ro">Document Unidata NetCDF</comment>
- <comment xml:lang="ru">Документ Unidata NetCDF</comment>
- <comment xml:lang="sk">Dokument Unidata NetCDF</comment>
- <comment xml:lang="sl">Dokument Unidata NetCDF</comment>
- <comment xml:lang="sq">Dokument Unidata NetCDF</comment>
- <comment xml:lang="sr">документ Унидата НетЦДФ-а</comment>
- <comment xml:lang="sv">Unidata NetCDF-dokument</comment>
- <comment xml:lang="tr">Unidata NetCDF belgesi</comment>
- <comment xml:lang="uk">документ Unidata NetCDF</comment>
- <comment xml:lang="vi">Tài liệu NetCDF Unidata</comment>
- <comment xml:lang="zh_CN">Unidata NetCDF 文档</comment>
<comment xml:lang="zh_TW">Unidata NetCDF 文件</comment>
+ <comment xml:lang="zh_CN">Unidata NetCDF 文档</comment>
+ <comment xml:lang="vi">Tài liệu NetCDF Unidata</comment>
+ <comment xml:lang="uk">документ Unidata NetCDF</comment>
+ <comment xml:lang="tr">Unidata NetCDF belgesi</comment>
+ <comment xml:lang="sv">Unidata NetCDF-dokument</comment>
+ <comment xml:lang="sr">документ Унидата НетЦДФ-а</comment>
+ <comment xml:lang="sq">dokument Unidata NetCDF</comment>
+ <comment xml:lang="sl">Dokument Unidata NetCDF</comment>
+ <comment xml:lang="si">Unidata NetCDF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Unidata NetCDF</comment>
+ <comment xml:lang="ru">Документ Unidata NetCDF</comment>
+ <comment xml:lang="ro">Document Unidata NetCDF</comment>
+ <comment xml:lang="pt_BR">Documento do Unidata NetCDF</comment>
+ <comment xml:lang="pt">documento Unidata NetCDF</comment>
+ <comment xml:lang="pl">Dokument Unidata NetCDF</comment>
+ <comment xml:lang="oc">document Unidata NetCDF</comment>
+ <comment xml:lang="nn">Unidata netCDF-dokument</comment>
+ <comment xml:lang="nl">Unidata NetCDF-document</comment>
+ <comment xml:lang="nb">Unidata NetCDF-dokument</comment>
+ <comment xml:lang="ms">Dokumen Unidata NetCDF</comment>
+ <comment xml:lang="lv">Unidata NetCDF dokuments</comment>
+ <comment xml:lang="lt">Unidata NetCDF dokumentas</comment>
+ <comment xml:lang="ko">Unidata NetCDF 문서</comment>
+ <comment xml:lang="kk">Unidata NetCDF құжаты</comment>
+ <comment xml:lang="ja">Unidata NetCDF ドキュメント</comment>
+ <comment xml:lang="it">Documento Unidata NetCDF</comment>
+ <comment xml:lang="is">Unidata NetCDF skjal</comment>
+ <comment xml:lang="id">Dokumen Unidata NetCDF</comment>
+ <comment xml:lang="ia">Documento Unidata NetCDF</comment>
+ <comment xml:lang="hu">Unidata NetCDF-dokumentum</comment>
+ <comment xml:lang="hr">Unidata NetCDF dokument</comment>
+ <comment xml:lang="he">מסמך של Unidata NetCDF</comment>
+ <comment xml:lang="gl">Documentno de Unixdata NetCDF</comment>
+ <comment xml:lang="ga">cáipéis Unidata NetCDF</comment>
+ <comment xml:lang="fur">document Unidata NetCDF</comment>
+ <comment xml:lang="fr">document Unidata NetCDF</comment>
+ <comment xml:lang="fo">Unidata NetCDF skjal</comment>
+ <comment xml:lang="fi">Unidata NetCDF -asiakirja</comment>
+ <comment xml:lang="eu">Unidata NetCDF dokumentua</comment>
+ <comment xml:lang="es">documento de Unidata NetCDF</comment>
+ <comment xml:lang="eo">dokumento en NetCDF-formato de Unidata</comment>
+ <comment xml:lang="en_GB">Unidata NetCDF document</comment>
+ <comment xml:lang="el">Έγγραφο Unidata NetCDF</comment>
+ <comment xml:lang="de">Unidata-NetCDF-Dokument</comment>
+ <comment xml:lang="da">Unidata NetCDF-dokument</comment>
+ <comment xml:lang="cs">dokument Unidata NetCDF</comment>
+ <comment xml:lang="ca">document d'Unidata NetCDF</comment>
+ <comment xml:lang="bg">Документ — Unidata NetCDF</comment>
+ <comment xml:lang="be@latin">Dakument Unidata NetCDF</comment>
+ <comment xml:lang="be">дакумент Unidata NetCDF</comment>
+ <comment xml:lang="ast">Documentu NetCDF d'Unidata</comment>
+ <comment xml:lang="ar">مستند Unidata NetCDF</comment>
<acronym>NetCDF</acronym>
<expanded-acronym>Network Common Data Form</expanded-acronym>
<generic-icon name="x-office-document"/>
@@ -16752,162 +18362,138 @@
</mime-type>
<mime-type type="application/x-nzb">
<comment>NewzBin usenet index</comment>
- <comment xml:lang="bg">Индекс — Usenet, NewzBin</comment>
- <comment xml:lang="ca">índex d'Usenet NewzBin</comment>
- <comment xml:lang="cs">index NewzBin diskuzních skupin Usenet</comment>
- <comment xml:lang="da">NewzBin-brugernetindex</comment>
- <comment xml:lang="de">NewzBin-Usenet-Index</comment>
- <comment xml:lang="el">Ευρετήριο usenet NewzBin</comment>
- <comment xml:lang="en_GB">NewzBin usenet index</comment>
- <comment xml:lang="es">índice NewzBin de usenet</comment>
- <comment xml:lang="eu">NewzBin usenet indizea</comment>
- <comment xml:lang="fr">index usenet </comment>
- <comment xml:lang="ga">innéacs usenet NewzBin</comment>
- <comment xml:lang="gl">Índice de usenet NEwzBin</comment>
- <comment xml:lang="he">אינדקס שרתי חדשות NewzBin</comment>
- <comment xml:lang="hr">NewzBin usenet indeks</comment>
- <comment xml:lang="hu">NewzBin usenet index</comment>
- <comment xml:lang="ia">Indice de usenet NewzBin</comment>
- <comment xml:lang="id">Indeks usenet NewzBin</comment>
- <comment xml:lang="it">Indice Usenet NewzBiz</comment>
- <comment xml:lang="ja">NewzBin Usenet インデックス</comment>
- <comment xml:lang="kk">NewzBin usenet индексі</comment>
- <comment xml:lang="ko">NewzBin 유즈넷 인덱스</comment>
- <comment xml:lang="lv">NewzBin usenet rādītājs</comment>
- <comment xml:lang="nl">NewzBin usenet index</comment>
- <comment xml:lang="oc">indèx usenet NewzBin</comment>
- <comment xml:lang="pl">Indeks grup dyskusyjnych NewzBin</comment>
- <comment xml:lang="pt">índice usenet NewzBin</comment>
- <comment xml:lang="pt_BR">Índice de usenet NewzBin</comment>
- <comment xml:lang="ru">Индекс usenet NewzBin</comment>
- <comment xml:lang="sk">Index Usenetu NewzBin</comment>
- <comment xml:lang="sl">Kazalo usenet NewzBin</comment>
- <comment xml:lang="sr">Њузбин попис јузнета</comment>
- <comment xml:lang="sv">NewzBin-usenetindex</comment>
- <comment xml:lang="tr">NewzBin usenet dizini</comment>
- <comment xml:lang="uk">покажчик usenet NewzBin</comment>
- <comment xml:lang="zh_CN">NewzBin Usenet 索引</comment>
<comment xml:lang="zh_TW">NewzBin usenet 索引</comment>
+ <comment xml:lang="zh_CN">NewzBin Usenet 索引</comment>
+ <comment xml:lang="uk">покажчик usenet NewzBin</comment>
+ <comment xml:lang="tr">NewzBin usenet dizini</comment>
+ <comment xml:lang="sv">NewzBin-usenetindex</comment>
+ <comment xml:lang="sr">Њузбин попис јузнета</comment>
+ <comment xml:lang="sq">tregues usenet NewzBin</comment>
+ <comment xml:lang="sl">Kazalo usenet NewzBin</comment>
+ <comment xml:lang="si">NewzBin Usenet index</comment>
+ <comment xml:lang="sk">Index Usenetu NewzBin</comment>
+ <comment xml:lang="ru">Индекс usenet NewzBin</comment>
+ <comment xml:lang="pt_BR">Índice de usenet NewzBin</comment>
+ <comment xml:lang="pt">índice usenet NewzBin</comment>
+ <comment xml:lang="pl">Indeks grup dyskusyjnych NewzBin</comment>
+ <comment xml:lang="oc">indèx usenet NewzBin</comment>
+ <comment xml:lang="nl">NewzBin usenet-index</comment>
+ <comment xml:lang="lv">NewzBin usenet rādītājs</comment>
+ <comment xml:lang="ko">NewzBin 유즈넷 인덱스</comment>
+ <comment xml:lang="kk">NewzBin usenet индексі</comment>
+ <comment xml:lang="ja">NewzBin Usenet インデックス</comment>
+ <comment xml:lang="it">Indice Usenet NewzBiz</comment>
+ <comment xml:lang="is">NewzBin usenet yfirlit</comment>
+ <comment xml:lang="id">Indeks usenet NewzBin</comment>
+ <comment xml:lang="ia">Indice de usenet NewzBin</comment>
+ <comment xml:lang="hu">NewzBin usenet index</comment>
+ <comment xml:lang="hr">NewzBin usenet indeks</comment>
+ <comment xml:lang="he">אינדקס שרתי חדשות NewzBin</comment>
+ <comment xml:lang="gl">Índice de usenet NEwzBin</comment>
+ <comment xml:lang="ga">innéacs usenet NewzBin</comment>
+ <comment xml:lang="fur">tabele usenet NewzBin</comment>
+ <comment xml:lang="fr">index usenet </comment>
+ <comment xml:lang="fi">NewzBin usenet -indeksi</comment>
+ <comment xml:lang="eu">NewzBin usenet indizea</comment>
+ <comment xml:lang="es">índice NewzBin de usenet</comment>
+ <comment xml:lang="en_GB">NewzBin usenet index</comment>
+ <comment xml:lang="el">Ευρετήριο usenet NewzBin</comment>
+ <comment xml:lang="de">NewzBin Usenet-Index</comment>
+ <comment xml:lang="da">NewzBin usenet-indeks</comment>
+ <comment xml:lang="cs">index NewzBin diskuzních skupin Usenet</comment>
+ <comment xml:lang="ca">índex d'Usenet NewzBin</comment>
+ <comment xml:lang="bg">Индекс — Usenet, NewzBin</comment>
+ <comment xml:lang="be">індэкс usenet NewzBin</comment>
+ <comment xml:lang="ar">فهرس يوزنت NewzBin</comment>
<sub-class-of type="application/xml"/>
<magic priority="80">
- <match value="&lt;nzb" type="string" offset="0:256"/>
+ <match type="string" value="&lt;nzb" offset="0:256"/>
</magic>
<glob pattern="*.nzb"/>
</mime-type>
<mime-type type="application/x-object">
- <comment>object code</comment>
- <comment xml:lang="ar">رمز الكائن</comment>
- <comment xml:lang="be@latin">abjektny kod</comment>
- <comment xml:lang="bg">Обектен код</comment>
- <comment xml:lang="ca">codi objecte</comment>
- <comment xml:lang="cs">objektový kód</comment>
- <comment xml:lang="da">objektkode</comment>
- <comment xml:lang="de">Objektcode</comment>
- <comment xml:lang="el">Μεταφρασμένος κώδικας</comment>
- <comment xml:lang="en_GB">object code</comment>
- <comment xml:lang="eo">celkodo</comment>
- <comment xml:lang="es">código objeto</comment>
- <comment xml:lang="eu">objektu kodea</comment>
- <comment xml:lang="fi">objektikoodi</comment>
- <comment xml:lang="fr">code objet</comment>
- <comment xml:lang="ga">cód réada</comment>
- <comment xml:lang="gl">código obxecto</comment>
- <comment xml:lang="he">קוד אובייקט</comment>
- <comment xml:lang="hr">Object kôd</comment>
- <comment xml:lang="hu">tárgykód</comment>
- <comment xml:lang="ia">Codice objecto</comment>
- <comment xml:lang="id">kode objek</comment>
- <comment xml:lang="it">Codice oggetto</comment>
- <comment xml:lang="ja">オブジェクトコード</comment>
- <comment xml:lang="kk">объектті коды</comment>
- <comment xml:lang="ko">개체 코드</comment>
- <comment xml:lang="lt">objektinis kodas</comment>
- <comment xml:lang="lv">objekta kods</comment>
- <comment xml:lang="ms">Kod objek</comment>
- <comment xml:lang="nb">objektkode</comment>
- <comment xml:lang="nl">objectcode</comment>
- <comment xml:lang="nn">objektkode</comment>
- <comment xml:lang="oc">còde objet</comment>
- <comment xml:lang="pl">Kod obiektowy</comment>
- <comment xml:lang="pt">código de objeto</comment>
- <comment xml:lang="pt_BR">Código-objeto</comment>
- <comment xml:lang="ro">cod sursă obiect</comment>
- <comment xml:lang="ru">Объектный код</comment>
- <comment xml:lang="sk">Objektový kód</comment>
- <comment xml:lang="sl">predmetna koda</comment>
- <comment xml:lang="sq">Kod objekti</comment>
- <comment xml:lang="sr">објектни ко̂д</comment>
- <comment xml:lang="sv">objektkod</comment>
- <comment xml:lang="tr">nesne kodu</comment>
+ <comment>Object code</comment>
<comment xml:lang="uk">об'єктний код</comment>
- <comment xml:lang="vi">mã đối tượng</comment>
- <comment xml:lang="zh_CN">目标代码</comment>
- <comment xml:lang="zh_TW">目的碼</comment>
+ <comment xml:lang="sv">Objektkod</comment>
+ <comment xml:lang="ru">Объектный код</comment>
+ <comment xml:lang="pl">Kod obiektowy</comment>
+ <comment xml:lang="ja">目的符号文書</comment>
+ <comment xml:lang="it">Codice oggetto</comment>
+ <comment xml:lang="gl">Código obxecto</comment>
+ <comment xml:lang="eu">Objektu-kodea</comment>
+ <comment xml:lang="es">código de objeto</comment>
+ <comment xml:lang="de">Objektcode</comment>
+ <comment xml:lang="be">аб'ектны код</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="\177ELF" type="string" offset="0">
- <match value="1" type="byte" offset="5">
- <match value="1" type="little16" offset="16"/>
+ <magic>
+ <match type="string" value="\177ELF" offset="0">
+ <match type="byte" value="1" offset="5">
+ <match type="little16" value="1" offset="16"/>
</match>
</match>
- <match value="\177ELF" type="string" offset="0">
- <match value="2" type="byte" offset="5">
- <match value="1" type="big16" offset="16"/>
+ <match type="string" value="\177ELF" offset="0">
+ <match type="byte" value="2" offset="5">
+ <match type="big16" value="1" offset="16"/>
</match>
</match>
</magic>
<glob pattern="*.o"/>
+ <glob pattern="*.mod" weight="40"/>
</mime-type>
<mime-type type="application/annodex">
<comment>Annodex exchange format</comment>
- <comment xml:lang="ar">صيغة Annodex البديلة</comment>
- <comment xml:lang="bg">Формат за обмяна — Annodex</comment>
- <comment xml:lang="ca">format d'intercanvi Annodex</comment>
- <comment xml:lang="cs">výměnný formát Annodex</comment>
- <comment xml:lang="da">Udvekslingsformat for Annodex</comment>
- <comment xml:lang="de">Annodex-Wechselformat</comment>
- <comment xml:lang="el">Μορφή ανταλλαγής Annodex</comment>
- <comment xml:lang="en_GB">Annodex exchange format</comment>
- <comment xml:lang="es">formato de intercambio de Annodex</comment>
- <comment xml:lang="eu">Annodex trukatze-formatua</comment>
- <comment xml:lang="fi">Annodex-siirtomuoto</comment>
- <comment xml:lang="fo">Annodex umbýtingarsnið</comment>
- <comment xml:lang="fr">format d'échange Annodex</comment>
- <comment xml:lang="ga">formáid mhalairte Annodex</comment>
- <comment xml:lang="gl">formato intercambiábel de Annodex</comment>
- <comment xml:lang="he">תבנית החלפת Annodex</comment>
- <comment xml:lang="hr">Annodex format razmjene</comment>
- <comment xml:lang="hu">Annodex csereformátum</comment>
- <comment xml:lang="ia">Formato de excambio Annodex</comment>
- <comment xml:lang="id">Format pertukaran Annodex</comment>
- <comment xml:lang="it">Formato di scambio Annodex</comment>
- <comment xml:lang="ja">Annodex 交換フォーマット</comment>
- <comment xml:lang="ka">Annodex-ის გაცვლითი ფორმატი</comment>
- <comment xml:lang="kk">Annodex алмасу пішімі</comment>
- <comment xml:lang="ko">Annodex 교환 형식</comment>
- <comment xml:lang="lt">Annodex mainų formatas</comment>
- <comment xml:lang="lv">Annodex apmaiņas formāts</comment>
- <comment xml:lang="nl">Annodex-exchange</comment>
- <comment xml:lang="oc">format d'escambi Annodex</comment>
- <comment xml:lang="pl">Format wymiany Annodex</comment>
- <comment xml:lang="pt">formato de troca Annodex</comment>
- <comment xml:lang="pt_BR">Formato de troca Annodex</comment>
- <comment xml:lang="ro">Format schimb Annodex</comment>
- <comment xml:lang="ru">Формат обмена Annodex</comment>
- <comment xml:lang="sk">Formát pre výmenu Annodex</comment>
- <comment xml:lang="sl">Izmenjalna datoteka Annodex</comment>
- <comment xml:lang="sr">Анодексов запис размене</comment>
- <comment xml:lang="sv">Annodex-utväxlingsformat</comment>
- <comment xml:lang="tr">Annodex değişim biçimi</comment>
- <comment xml:lang="uk">формат обміну даними Annodex</comment>
- <comment xml:lang="vi">Định dạng trao đổi Annodex</comment>
- <comment xml:lang="zh_CN">Annodex 交换格式</comment>
<comment xml:lang="zh_TW">Annodex 交換格式</comment>
+ <comment xml:lang="zh_CN">Annodex 交换格式</comment>
+ <comment xml:lang="vi">Định dạng trao đổi Annodex</comment>
+ <comment xml:lang="uk">формат обміну даними Annodex</comment>
+ <comment xml:lang="tr">Annodex değişim biçimi</comment>
+ <comment xml:lang="sv">Annodex-utväxlingsformat</comment>
+ <comment xml:lang="sr">Анодексов запис размене</comment>
+ <comment xml:lang="sl">Izmenjalna datoteka Annodex</comment>
+ <comment xml:lang="si">Annodex හුවමාරු ආකෘතිය</comment>
+ <comment xml:lang="sk">Formát pre výmenu Annodex</comment>
+ <comment xml:lang="ru">Формат обмена Annodex</comment>
+ <comment xml:lang="ro">Format schimb Annodex</comment>
+ <comment xml:lang="pt_BR">Formato de troca Annodex</comment>
+ <comment xml:lang="pt">formato de troca Annodex</comment>
+ <comment xml:lang="pl">Format wymiany Annodex</comment>
+ <comment xml:lang="oc">format d'escambi Annodex</comment>
+ <comment xml:lang="nl">Annodex-exchange</comment>
+ <comment xml:lang="lv">Annodex apmaiņas formāts</comment>
+ <comment xml:lang="lt">Annodex mainų formatas</comment>
+ <comment xml:lang="ko">Annodex 교환 형식</comment>
+ <comment xml:lang="kk">Annodex алмасу пішімі</comment>
+ <comment xml:lang="ka">Annodex-ის გაცვლითი ფორმატი</comment>
+ <comment xml:lang="ja">Annodex 交換フォーマット</comment>
+ <comment xml:lang="it">Formato di scambio Annodex</comment>
+ <comment xml:lang="is">Annodex skiptiskráasnið</comment>
+ <comment xml:lang="id">Format pertukaran Annodex</comment>
+ <comment xml:lang="ia">Formato de excambio Annodex</comment>
+ <comment xml:lang="hu">Annodex csereformátum</comment>
+ <comment xml:lang="hr">Annodex format razmjene</comment>
+ <comment xml:lang="he">תבנית החלפת Annodex</comment>
+ <comment xml:lang="gl">formato intercambiábel de Annodex</comment>
+ <comment xml:lang="ga">formáid mhalairte Annodex</comment>
+ <comment xml:lang="fur">formât di scambi Annodex</comment>
+ <comment xml:lang="fr">format d'échange Annodex</comment>
+ <comment xml:lang="fo">Annodex umbýtingarsnið</comment>
+ <comment xml:lang="fi">Annodex-siirtomuoto</comment>
+ <comment xml:lang="eu">Annodex trukatze-formatua</comment>
+ <comment xml:lang="es">formato de intercambio de Annodex</comment>
+ <comment xml:lang="en_GB">Annodex exchange format</comment>
+ <comment xml:lang="el">Μορφή ανταλλαγής Annodex</comment>
+ <comment xml:lang="de">Annodex-Austauschformat</comment>
+ <comment xml:lang="da">Udvekslingsformat for Annodex</comment>
+ <comment xml:lang="cs">výměnný formát Annodex</comment>
+ <comment xml:lang="ca">format d'intercanvi Annodex</comment>
+ <comment xml:lang="bg">Формат за обмяна — Annodex</comment>
+ <comment xml:lang="be">фармат абмену Annodex</comment>
+ <comment xml:lang="ar">صيغة تبادل Annodex</comment>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
- <match value="OggS" type="string" offset="0">
- <match value="fishead\0" type="string" offset="28">
- <match value="CMML\0\0\0\0" type="string" offset="56:512"/>
+ <magic>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="fishead\0" offset="28">
+ <match type="string" value="CMML\0\0\0\0" offset="56:512"/>
</match>
</match>
</magic>
@@ -16915,57 +18501,46 @@
<alias type="application/x-annodex"/>
</mime-type>
<mime-type type="video/annodex">
- <comment>Annodex Video</comment>
- <comment xml:lang="ar">Annodex مرئي</comment>
- <comment xml:lang="ast">Videu n'Annodex</comment>
- <comment xml:lang="bg">Видео — Annodex</comment>
- <comment xml:lang="ca">Annodex Video</comment>
- <comment xml:lang="cs">video Annodex</comment>
- <comment xml:lang="da">Annodexvideo</comment>
- <comment xml:lang="de">Annodex-Video</comment>
- <comment xml:lang="el">Βίντεο Annodex</comment>
- <comment xml:lang="en_GB">Annodex Video</comment>
- <comment xml:lang="eo">Annodex-video</comment>
- <comment xml:lang="es">vídeo Annodex</comment>
- <comment xml:lang="eu">Annodex bideoa</comment>
- <comment xml:lang="fi">Annodex-video</comment>
- <comment xml:lang="fo">Annodex video</comment>
- <comment xml:lang="fr">vidéo Annodex</comment>
- <comment xml:lang="ga">Físeán Annodex</comment>
- <comment xml:lang="gl">vídeo de Annodex</comment>
- <comment xml:lang="he">וידאו Annodex</comment>
- <comment xml:lang="hr">Annodex video snimka</comment>
- <comment xml:lang="hu">Annodex videó</comment>
- <comment xml:lang="ia">Video Annodex</comment>
- <comment xml:lang="id">Video Annodex</comment>
- <comment xml:lang="it">Video Annodex</comment>
- <comment xml:lang="ja">Annodex 動画</comment>
- <comment xml:lang="ka">Annodex-ის ვიდეო</comment>
- <comment xml:lang="kk">Annodex видеосы</comment>
- <comment xml:lang="ko">Annodex 동영상</comment>
- <comment xml:lang="lt">Annodex vaizdo įrašas</comment>
- <comment xml:lang="lv">Annodex video</comment>
- <comment xml:lang="nl">Annodex Video</comment>
- <comment xml:lang="oc">vidèo Annodex</comment>
- <comment xml:lang="pl">Plik wideo Annodex</comment>
- <comment xml:lang="pt">vídeo Annodex</comment>
- <comment xml:lang="pt_BR">Vídeo Annodex</comment>
- <comment xml:lang="ro">Video Annodex</comment>
- <comment xml:lang="ru">Видео Annodex</comment>
- <comment xml:lang="sk">Video Annodex</comment>
- <comment xml:lang="sl">Video datoteka Annodex</comment>
- <comment xml:lang="sr">Анодекс видео</comment>
- <comment xml:lang="sv">Annodex-video</comment>
- <comment xml:lang="tr">Annodex Video</comment>
- <comment xml:lang="uk">відеокліп Annodex</comment>
- <comment xml:lang="vi">Ảnh động Annodex</comment>
- <comment xml:lang="zh_CN">Annodex 视频</comment>
+ <comment>Annodex video</comment>
<comment xml:lang="zh_TW">Annodex 視訊</comment>
+ <comment xml:lang="zh_CN">Annodex 视频</comment>
+ <comment xml:lang="uk">відео Annodex</comment>
+ <comment xml:lang="tr">Annodex video</comment>
+ <comment xml:lang="sv">Annodex-video</comment>
+ <comment xml:lang="sq">video Annodex</comment>
+ <comment xml:lang="sl">Video Annodex</comment>
+ <comment xml:lang="si">Annodex වීඩියෝව</comment>
+ <comment xml:lang="ru">Видео Annodex</comment>
+ <comment xml:lang="pt_BR">Vídeo Annodex</comment>
+ <comment xml:lang="pl">Plik wideo Annodex</comment>
+ <comment xml:lang="oc">vidèo Annodex</comment>
+ <comment xml:lang="nl">Annodex-video</comment>
+ <comment xml:lang="ko">Annodex 동영상</comment>
+ <comment xml:lang="kk">Annodex видеосы</comment>
+ <comment xml:lang="ja">Annodex 動画</comment>
+ <comment xml:lang="it">Video Annodex</comment>
+ <comment xml:lang="is">Annodex myndskeið</comment>
+ <comment xml:lang="id">Video Annodex</comment>
+ <comment xml:lang="hu">Annodex videó</comment>
+ <comment xml:lang="hr">Annodex video snimka</comment>
+ <comment xml:lang="he">סרטון Annodex</comment>
+ <comment xml:lang="gl">Vídeo de Annodex</comment>
+ <comment xml:lang="fr">vidéo Annodex</comment>
+ <comment xml:lang="fi">Annodex-video</comment>
+ <comment xml:lang="eu">Annodex bideoa</comment>
+ <comment xml:lang="es">vídeo Annodex</comment>
+ <comment xml:lang="en_GB">Annodex video</comment>
+ <comment xml:lang="de">Annodex-Video</comment>
+ <comment xml:lang="da">Annodex-video</comment>
+ <comment xml:lang="ca">vídeo Annodex</comment>
+ <comment xml:lang="bg">Видео — Annodex</comment>
+ <comment xml:lang="be">відэа Annodex</comment>
+ <comment xml:lang="ar">فيديو Annodex</comment>
<sub-class-of type="application/annodex"/>
- <magic priority="50">
- <match value="OggS" type="string" offset="0">
- <match value="fishead\0" type="string" offset="28">
- <match value="CMML\0\0\0\0" type="string" offset="56:512"/>
+ <magic>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="fishead\0" offset="28">
+ <match type="string" value="CMML\0\0\0\0" offset="56:512"/>
</match>
</match>
</magic>
@@ -16973,56 +18548,46 @@
<alias type="video/x-annodex"/>
</mime-type>
<mime-type type="audio/annodex">
- <comment>Annodex Audio</comment>
- <comment xml:lang="ar">Annodex سمعي</comment>
- <comment xml:lang="bg">Аудио — Annodex</comment>
- <comment xml:lang="ca">Annodex Audio</comment>
- <comment xml:lang="cs">zvuk Annodex</comment>
- <comment xml:lang="da">Annodexlyd</comment>
- <comment xml:lang="de">Annodex-Audio</comment>
- <comment xml:lang="el">Ήχος Annodex</comment>
- <comment xml:lang="en_GB">Annodex Audio</comment>
- <comment xml:lang="eo">Annodex-sondosiero</comment>
- <comment xml:lang="es">sonido Annodex</comment>
- <comment xml:lang="eu">Annodex audioa</comment>
- <comment xml:lang="fi">Annodex-ääni</comment>
- <comment xml:lang="fo">Annodex ljóður</comment>
- <comment xml:lang="fr">audio Annodex</comment>
- <comment xml:lang="ga">Fuaim Annodex</comment>
- <comment xml:lang="gl">son de Annodex</comment>
- <comment xml:lang="he">שמע Annodex</comment>
- <comment xml:lang="hr">Annodex zvučni zapis</comment>
- <comment xml:lang="hu">Annodex hang</comment>
- <comment xml:lang="ia">Audio Annodex</comment>
- <comment xml:lang="id">Audio Annodex</comment>
- <comment xml:lang="it">Audio Annodex</comment>
- <comment xml:lang="ja">Annodex オーディオ</comment>
- <comment xml:lang="ka">Annodex-ის აუდიო</comment>
- <comment xml:lang="kk">Annodex аудиосы</comment>
- <comment xml:lang="ko">Annodex 오디오</comment>
- <comment xml:lang="lt">Annodex garso įrašas</comment>
- <comment xml:lang="lv">Annodex audio</comment>
- <comment xml:lang="nl">Annodex Audio</comment>
- <comment xml:lang="oc">àudio Annodex</comment>
- <comment xml:lang="pl">Plik dźwiękowy Annodex</comment>
- <comment xml:lang="pt">áudio Annodex</comment>
- <comment xml:lang="pt_BR">Áudio Annodex</comment>
- <comment xml:lang="ro">Audio Annodex</comment>
- <comment xml:lang="ru">Аудио Annodex</comment>
- <comment xml:lang="sk">Zvuk Annodex</comment>
- <comment xml:lang="sl">Zvočna datoteka Annodex</comment>
- <comment xml:lang="sr">Анодекс аудио</comment>
- <comment xml:lang="sv">Annodex-ljud</comment>
- <comment xml:lang="tr">Annodex Sesi</comment>
- <comment xml:lang="uk">звук Annodex</comment>
- <comment xml:lang="vi">Âm thanh Annodex</comment>
- <comment xml:lang="zh_CN">Annodex 音频</comment>
+ <comment>Annodex audio</comment>
<comment xml:lang="zh_TW">Annodex 音訊</comment>
+ <comment xml:lang="zh_CN">Annodex 音频</comment>
+ <comment xml:lang="uk">звук Annodex</comment>
+ <comment xml:lang="tr">Annodex sesi</comment>
+ <comment xml:lang="sv">Annodex-ljud</comment>
+ <comment xml:lang="sq">audio Annodex</comment>
+ <comment xml:lang="sl">Zvok Annodex</comment>
+ <comment xml:lang="si">ඇනෝඩෙක්ස් ඕඩියෝ</comment>
+ <comment xml:lang="ru">Аудио Annodex</comment>
+ <comment xml:lang="pt_BR">Áudio Annodex</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Annodex</comment>
+ <comment xml:lang="oc">àudio Annodex</comment>
+ <comment xml:lang="nl">Annodex-audio</comment>
+ <comment xml:lang="ko">Annodex 오디오</comment>
+ <comment xml:lang="kk">Annodex аудиосы</comment>
+ <comment xml:lang="ja">Annodex オーディオ</comment>
+ <comment xml:lang="it">Audio Annodex</comment>
+ <comment xml:lang="is">Annodex hljóðskrá</comment>
+ <comment xml:lang="id">Audio Annodex</comment>
+ <comment xml:lang="hu">Annodex hang</comment>
+ <comment xml:lang="hr">Annodex zvučni zapis</comment>
+ <comment xml:lang="he">שמע Annodex</comment>
+ <comment xml:lang="gl">Son de Annodex</comment>
+ <comment xml:lang="fr">audio Annodex</comment>
+ <comment xml:lang="fi">Annodex-ääni</comment>
+ <comment xml:lang="eu">Annodex audioa</comment>
+ <comment xml:lang="es">sonido Annodex</comment>
+ <comment xml:lang="en_GB">Annodex audio</comment>
+ <comment xml:lang="de">Annodex-Audio</comment>
+ <comment xml:lang="da">Annodex-lyd</comment>
+ <comment xml:lang="ca">àudio Annodex</comment>
+ <comment xml:lang="bg">Аудио — Annodex</comment>
+ <comment xml:lang="be">аўдыя Annodex</comment>
+ <comment xml:lang="ar">صوت Annodex</comment>
<sub-class-of type="application/annodex"/>
- <magic priority="50">
- <match value="OggS" type="string" offset="0">
- <match value="fishead\0" type="string" offset="28">
- <match value="CMML\0\0\0\0" type="string" offset="56:512"/>
+ <magic>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="fishead\0" offset="28">
+ <match type="string" value="CMML\0\0\0\0" offset="56:512"/>
</match>
</match>
</magic>
@@ -17031,112 +18596,106 @@
</mime-type>
<mime-type type="application/ogg">
<comment>Ogg multimedia file</comment>
- <comment xml:lang="ar">ملف وسائط متعددة Ogg</comment>
- <comment xml:lang="be@latin">Multymedyjny fajł Ogg</comment>
- <comment xml:lang="bg">Мултимедия — Ogg</comment>
- <comment xml:lang="ca">fitxer multimèdia Ogg</comment>
- <comment xml:lang="cs">multimediální soubor Ogg</comment>
- <comment xml:lang="da">Ogg multimedie-fil</comment>
- <comment xml:lang="de">Ogg-Multimediadatei</comment>
- <comment xml:lang="el">Αρχείο πολυμέσων Ogg</comment>
- <comment xml:lang="en_GB">Ogg multimedia file</comment>
- <comment xml:lang="es">archivo multimedia Ogg</comment>
- <comment xml:lang="eu">Ogg multimediako fitxategia</comment>
- <comment xml:lang="fi">Ogg-multimediatiedosto</comment>
- <comment xml:lang="fo">Ogg margmiðlafíla</comment>
- <comment xml:lang="fr">fichier multimédia Ogg</comment>
- <comment xml:lang="ga">comhad ilmheán Ogg</comment>
- <comment xml:lang="gl">ficheiro multimedia Ogg</comment>
- <comment xml:lang="he">קובץ מולטימדיה Ogg</comment>
- <comment xml:lang="hr">Ogg multimedijalna datoteka</comment>
- <comment xml:lang="hu">Ogg multimédiafájl</comment>
- <comment xml:lang="ia">File multimedial Ogg</comment>
- <comment xml:lang="id">Berkas multimedia Ogg</comment>
- <comment xml:lang="it">File multimediale Ogg</comment>
- <comment xml:lang="ja">Ogg マルチメディアファイル</comment>
- <comment xml:lang="ka">Ogg-ის მულტიმედია ფაილი</comment>
- <comment xml:lang="kk">Ogg мультимедиа файлы</comment>
- <comment xml:lang="ko">Ogg 멀티미디어 파일</comment>
- <comment xml:lang="lt">Ogg multimedijos failas</comment>
- <comment xml:lang="lv">Ogg multimediju datne</comment>
- <comment xml:lang="nb">Ogg-multimediafil</comment>
- <comment xml:lang="nl">Ogg-multimediabestand</comment>
- <comment xml:lang="nn">Ogg multimediafil</comment>
- <comment xml:lang="oc">fichièr multimèdia Ogg</comment>
- <comment xml:lang="pl">Plik multimedialny Ogg</comment>
- <comment xml:lang="pt">ficheiro multimédia Ogg</comment>
- <comment xml:lang="pt_BR">Arquivo multimídia Ogg</comment>
- <comment xml:lang="ro">Fișier multimedia Ogg</comment>
- <comment xml:lang="ru">Мультимедийный файл Ogg</comment>
- <comment xml:lang="sk">Súbor multimédií Ogg</comment>
- <comment xml:lang="sl">Večpredstavnostna datoteka Ogg</comment>
- <comment xml:lang="sq">File multimedial Ogg</comment>
- <comment xml:lang="sr">Огг мултимедијална датотека</comment>
- <comment xml:lang="sv">Ogg-multimediafil</comment>
- <comment xml:lang="tr">Ogg çokluortam dosyası</comment>
- <comment xml:lang="uk">мультимедійний файл Ogg</comment>
- <comment xml:lang="vi">Tập tin đa phương tiện Ogg</comment>
- <comment xml:lang="zh_CN">Ogg 多媒体文件</comment>
<comment xml:lang="zh_TW">Ogg 多媒體檔案</comment>
+ <comment xml:lang="zh_CN">Ogg 多媒体文件</comment>
+ <comment xml:lang="vi">Tập tin đa phương tiện Ogg</comment>
+ <comment xml:lang="uk">мультимедійний файл Ogg</comment>
+ <comment xml:lang="tr">Ogg çoklu ortam dosyası</comment>
+ <comment xml:lang="sv">Ogg-multimediafil</comment>
+ <comment xml:lang="sr">Огг мултимедијална датотека</comment>
+ <comment xml:lang="sq">kartelë multimediale Ogg</comment>
+ <comment xml:lang="sl">Večpredstavnostna datoteka Ogg</comment>
+ <comment xml:lang="si">Ogg බහුමාධ්‍ය ගොනුව</comment>
+ <comment xml:lang="sk">Súbor multimédií Ogg</comment>
+ <comment xml:lang="ru">Мультимедийный файл Ogg</comment>
+ <comment xml:lang="ro">Fișier multimedia Ogg</comment>
+ <comment xml:lang="pt_BR">Arquivo multimídia Ogg</comment>
+ <comment xml:lang="pt">ficheiro multimédia Ogg</comment>
+ <comment xml:lang="pl">Plik multimedialny Ogg</comment>
+ <comment xml:lang="oc">fichièr multimèdia Ogg</comment>
+ <comment xml:lang="nn">Ogg multimediafil</comment>
+ <comment xml:lang="nl">Ogg-multimediabestand</comment>
+ <comment xml:lang="nb">Ogg-multimediafil</comment>
+ <comment xml:lang="lv">Ogg multimediju datne</comment>
+ <comment xml:lang="lt">Ogg multimedijos failas</comment>
+ <comment xml:lang="ko">Ogg 멀티미디어 파일</comment>
+ <comment xml:lang="kk">Ogg мультимедиа файлы</comment>
+ <comment xml:lang="ka">Ogg-ის მულტიმედია ფაილი</comment>
+ <comment xml:lang="ja">Ogg マルチメディアファイル</comment>
+ <comment xml:lang="it">File multimediale Ogg</comment>
+ <comment xml:lang="is">OGG margmiðlunarskrá</comment>
+ <comment xml:lang="id">Berkas multimedia Ogg</comment>
+ <comment xml:lang="ia">File multimedial Ogg</comment>
+ <comment xml:lang="hu">Ogg multimédiafájl</comment>
+ <comment xml:lang="hr">Ogg multimedijalna datoteka</comment>
+ <comment xml:lang="he">קובץ מולטימדיה Ogg</comment>
+ <comment xml:lang="gl">ficheiro multimedia Ogg</comment>
+ <comment xml:lang="ga">comhad ilmheán Ogg</comment>
+ <comment xml:lang="fur">file multimediâl Ogg</comment>
+ <comment xml:lang="fr">fichier multimédia Ogg</comment>
+ <comment xml:lang="fo">Ogg margmiðlafíla</comment>
+ <comment xml:lang="fi">Ogg-multimediatiedosto</comment>
+ <comment xml:lang="eu">Ogg multimediako fitxategia</comment>
+ <comment xml:lang="es">archivo multimedia Ogg</comment>
+ <comment xml:lang="en_GB">Ogg multimedia file</comment>
+ <comment xml:lang="el">Αρχείο πολυμέσων Ogg</comment>
+ <comment xml:lang="de">Ogg-Multimediadatei</comment>
+ <comment xml:lang="da">Ogg multimedie-fil</comment>
+ <comment xml:lang="cs">multimediální soubor Ogg</comment>
+ <comment xml:lang="ca">fitxer multimèdia Ogg</comment>
+ <comment xml:lang="bg">Мултимедия — Ogg</comment>
+ <comment xml:lang="be@latin">Multymedyjny fajł Ogg</comment>
+ <comment xml:lang="be">мультымедыйны файл Ogg</comment>
+ <comment xml:lang="ar">ملف وسائط متعددة Ogg</comment>
+ <comment xml:lang="af">Ogg-multimedialêer</comment>
<generic-icon name="video-x-generic"/>
<alias type="application/x-ogg"/>
- <magic priority="50">
- <match value="OggS" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="OggS" offset="0"/>
</magic>
<glob pattern="*.ogx"/>
</mime-type>
<mime-type type="audio/ogg">
- <comment>Ogg Audio</comment>
- <comment xml:lang="ar">Ogg سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Ogg</comment>
- <comment xml:lang="bg">Аудио — Ogg</comment>
- <comment xml:lang="ca">àudio d'Ogg</comment>
- <comment xml:lang="cs">zvuk Ogg</comment>
- <comment xml:lang="da">Ogg-lyd</comment>
- <comment xml:lang="de">Ogg-Audio</comment>
- <comment xml:lang="el">Ήχος Ogg</comment>
- <comment xml:lang="en_GB">Ogg Audio</comment>
- <comment xml:lang="es">sonido Ogg</comment>
- <comment xml:lang="eu">Ogg audioa</comment>
- <comment xml:lang="fi">Ogg-ääni</comment>
- <comment xml:lang="fo">Ogg ljóður</comment>
- <comment xml:lang="fr">audio Ogg</comment>
- <comment xml:lang="ga">Fuaim Ogg</comment>
- <comment xml:lang="gl">son Ogg</comment>
- <comment xml:lang="he">שמע Ogg</comment>
- <comment xml:lang="hr">Ogg zvučni zapis</comment>
- <comment xml:lang="hu">Ogg hang</comment>
- <comment xml:lang="ia">Audio Ogg</comment>
- <comment xml:lang="id">Audio Ogg</comment>
- <comment xml:lang="it">Audio Ogg</comment>
- <comment xml:lang="ja">Ogg オーディオ</comment>
- <comment xml:lang="ka">Ogg-ის აუდიო</comment>
- <comment xml:lang="kk">Ogg аудиосы</comment>
- <comment xml:lang="ko">Ogg 오디오</comment>
- <comment xml:lang="lt">Ogg garso įrašas</comment>
- <comment xml:lang="lv">Ogg audio</comment>
- <comment xml:lang="nb">Ogg lyd</comment>
- <comment xml:lang="nl">Ogg-audio</comment>
- <comment xml:lang="nn">Ogg-lyd</comment>
- <comment xml:lang="oc">àudio Ogg</comment>
- <comment xml:lang="pl">Plik dźwiękowy Ogg</comment>
- <comment xml:lang="pt">áudio Ogg</comment>
- <comment xml:lang="pt_BR">Áudio Ogg</comment>
- <comment xml:lang="ro">Audio Ogg</comment>
- <comment xml:lang="ru">Аудио Ogg</comment>
- <comment xml:lang="sk">Zvuk Ogg</comment>
- <comment xml:lang="sl">Zvočna datoteka Ogg</comment>
- <comment xml:lang="sq">Audio Ogg</comment>
- <comment xml:lang="sr">Огг звук</comment>
- <comment xml:lang="sv">Ogg-ljud</comment>
- <comment xml:lang="tr">Ogg Sesi</comment>
- <comment xml:lang="uk">звук ogg</comment>
- <comment xml:lang="vi">Âm thanh Ogg</comment>
- <comment xml:lang="zh_CN">Ogg 音频</comment>
+ <comment>Ogg audio</comment>
<comment xml:lang="zh_TW">Ogg 音訊</comment>
+ <comment xml:lang="zh_CN">Ogg 音频</comment>
+ <comment xml:lang="uk">звук ogg</comment>
+ <comment xml:lang="tr">Ogg sesi</comment>
+ <comment xml:lang="sv">Ogg-ljud</comment>
+ <comment xml:lang="sr">ОГГ аудио</comment>
+ <comment xml:lang="sq">audio Ogg</comment>
+ <comment xml:lang="sl">Zvok Ogg</comment>
+ <comment xml:lang="si">ඕග් ඕඩියෝ</comment>
+ <comment xml:lang="sk">Zvuk Ogg</comment>
+ <comment xml:lang="ru">Аудио Ogg</comment>
+ <comment xml:lang="pt_BR">Áudio Ogg</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Ogg</comment>
+ <comment xml:lang="oc">àudio Ogg</comment>
+ <comment xml:lang="nl">Ogg-audio</comment>
+ <comment xml:lang="ko">Ogg 오디오</comment>
+ <comment xml:lang="kk">Ogg аулиосы</comment>
+ <comment xml:lang="ja">Ogg オーディオ</comment>
+ <comment xml:lang="it">Audio Ogg</comment>
+ <comment xml:lang="is">Ogg hljóðskrá</comment>
+ <comment xml:lang="id">Audio Ogg</comment>
+ <comment xml:lang="hu">Ogg hang</comment>
+ <comment xml:lang="hr">Ogg zvučni zapis</comment>
+ <comment xml:lang="he">שמע Ogg</comment>
+ <comment xml:lang="gl">Son Ogg</comment>
+ <comment xml:lang="fr">audio Ogg</comment>
+ <comment xml:lang="fi">Ogg-ääni</comment>
+ <comment xml:lang="eu">Ogg audioa</comment>
+ <comment xml:lang="es">sonido Ogg</comment>
+ <comment xml:lang="en_GB">Ogg audio</comment>
+ <comment xml:lang="de">Ogg-Audio</comment>
+ <comment xml:lang="da">Ogg-lyd</comment>
+ <comment xml:lang="ca">àudio Ogg</comment>
+ <comment xml:lang="bg">Аудио — Ogg</comment>
+ <comment xml:lang="be">аўдыя Ogg</comment>
+ <comment xml:lang="ar">صوت Ogg</comment>
<sub-class-of type="application/ogg"/>
- <magic priority="50">
- <match value="OggS" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="OggS" offset="0"/>
</magic>
<glob pattern="*.oga"/>
<glob pattern="*.ogg"/>
@@ -17144,58 +18703,46 @@
<alias type="audio/x-ogg"/>
</mime-type>
<mime-type type="video/ogg">
- <comment>Ogg Video</comment>
- <comment xml:lang="ar">Ogg مرئي</comment>
- <comment xml:lang="ast">Videu n'Ogg</comment>
- <comment xml:lang="be@latin">Videa Ogg</comment>
- <comment xml:lang="bg">Видео — Ogg</comment>
- <comment xml:lang="ca">vídeo Ogg</comment>
- <comment xml:lang="cs">video Ogg</comment>
- <comment xml:lang="da">Ogg-video</comment>
- <comment xml:lang="de">Ogg-Video</comment>
- <comment xml:lang="el">Βίντεο Ogg</comment>
- <comment xml:lang="en_GB">Ogg Video</comment>
- <comment xml:lang="es">vídeo Ogg</comment>
- <comment xml:lang="eu">Ogg bideoa</comment>
- <comment xml:lang="fi">Ogg-video</comment>
- <comment xml:lang="fo">Ogg Video</comment>
- <comment xml:lang="fr">vidéo Ogg</comment>
- <comment xml:lang="ga">Físeán Ogg</comment>
- <comment xml:lang="gl">vídeo Ogg</comment>
- <comment xml:lang="he">וידאו Ogg</comment>
- <comment xml:lang="hr">Ogg video snimka</comment>
- <comment xml:lang="hu">Ogg videó</comment>
- <comment xml:lang="ia">Video Ogg</comment>
- <comment xml:lang="id">Video Ogg</comment>
- <comment xml:lang="it">Video Ogg</comment>
- <comment xml:lang="ja">Ogg 動画</comment>
- <comment xml:lang="ka">Ogg ვიდეო</comment>
- <comment xml:lang="kk">Ogg видеосы</comment>
- <comment xml:lang="ko">Ogg 동영상</comment>
- <comment xml:lang="lt">Ogg vaizdo įrašas</comment>
- <comment xml:lang="lv">Ogg video</comment>
- <comment xml:lang="nb">Ogg video</comment>
- <comment xml:lang="nl">Ogg-video</comment>
- <comment xml:lang="nn">Ogg-video</comment>
- <comment xml:lang="oc">vidèo Ogg</comment>
- <comment xml:lang="pl">Plik wideo Ogg</comment>
- <comment xml:lang="pt">vídeo Ogg</comment>
- <comment xml:lang="pt_BR">Vídeo Ogg</comment>
- <comment xml:lang="ro">Video Ogg</comment>
- <comment xml:lang="ru">Видео Ogg</comment>
- <comment xml:lang="sk">Video Ogg</comment>
- <comment xml:lang="sl">Video datoteka Ogg</comment>
- <comment xml:lang="sq">Video Ogg</comment>
- <comment xml:lang="sr">Огг снимак</comment>
- <comment xml:lang="sv">Ogg-video</comment>
- <comment xml:lang="tr">Ogg Video</comment>
- <comment xml:lang="uk">відеокліп ogg</comment>
- <comment xml:lang="vi">Ảnh động Ogg</comment>
- <comment xml:lang="zh_CN">Ogg 视频</comment>
+ <comment>Ogg video</comment>
<comment xml:lang="zh_TW">Ogg 視訊</comment>
+ <comment xml:lang="zh_CN">Ogg 视频</comment>
+ <comment xml:lang="uk">відео ogg</comment>
+ <comment xml:lang="tr">Ogg video</comment>
+ <comment xml:lang="sv">Ogg-video</comment>
+ <comment xml:lang="sr">ОГГ видео</comment>
+ <comment xml:lang="sq">video Ogg</comment>
+ <comment xml:lang="sl">Video Ogg</comment>
+ <comment xml:lang="si">ඔග් වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Ogg</comment>
+ <comment xml:lang="ru">Видео Ogg</comment>
+ <comment xml:lang="pt_BR">Vídeo Ogg</comment>
+ <comment xml:lang="pl">Plik wideo Ogg</comment>
+ <comment xml:lang="oc">vidèo Ogg</comment>
+ <comment xml:lang="nl">Ogg-video</comment>
+ <comment xml:lang="ko">Ogg 동영상</comment>
+ <comment xml:lang="kk">Ogg видеосы</comment>
+ <comment xml:lang="ja">Ogg 動画</comment>
+ <comment xml:lang="it">Video Ogg</comment>
+ <comment xml:lang="is">Ogg myndskeið</comment>
+ <comment xml:lang="id">Video Ogg</comment>
+ <comment xml:lang="hu">Ogg videó</comment>
+ <comment xml:lang="hr">Ogg video snimka</comment>
+ <comment xml:lang="he">וידאו Ogg</comment>
+ <comment xml:lang="gl">Vídeo Ogg</comment>
+ <comment xml:lang="fr">vidéo Ogg</comment>
+ <comment xml:lang="fi">Ogg-video</comment>
+ <comment xml:lang="eu">Ogg bideoa</comment>
+ <comment xml:lang="es">vídeo Ogg</comment>
+ <comment xml:lang="en_GB">Ogg video</comment>
+ <comment xml:lang="de">Ogg-Video</comment>
+ <comment xml:lang="da">Ogg-video</comment>
+ <comment xml:lang="ca">vídeo Ogg</comment>
+ <comment xml:lang="bg">Видео — Ogg</comment>
+ <comment xml:lang="be">відэа Ogg</comment>
+ <comment xml:lang="ar">فيديو Ogg</comment>
<sub-class-of type="application/ogg"/>
- <magic priority="50">
- <match value="OggS" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="OggS" offset="0"/>
</magic>
<glob pattern="*.ogv"/>
<glob pattern="*.ogg"/>
@@ -17203,63 +18750,68 @@
</mime-type>
<mime-type type="audio/x-vorbis+ogg">
<comment>Ogg Vorbis audio</comment>
- <comment xml:lang="ar">Ogg Vorbis سمعي</comment>
- <comment xml:lang="az">Ogg Vorbis audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo Ogg Vorbis</comment>
- <comment xml:lang="bg">Аудио — Ogg Vorbis</comment>
- <comment xml:lang="ca">àudio d'Ogg Vorbis</comment>
- <comment xml:lang="cs">zvuk Ogg Vorbis</comment>
- <comment xml:lang="cy">Sain Ogg Vorbis</comment>
- <comment xml:lang="da">Ogg Vorbis-lyd</comment>
- <comment xml:lang="de">Ogg-Vorbis-Audio</comment>
- <comment xml:lang="el">Ήχος Ogg Vobris</comment>
- <comment xml:lang="en_GB">Ogg Vorbis audio</comment>
- <comment xml:lang="eo">Ogg-Vorbis-sondosiero</comment>
- <comment xml:lang="es">sonido Ogg Vorbis</comment>
- <comment xml:lang="eu">Ogg Vorbis audioa</comment>
- <comment xml:lang="fi">Ogg Vorbis -ääni</comment>
- <comment xml:lang="fo">Ogg Vorbis ljóður</comment>
- <comment xml:lang="fr">audio Ogg Vorbis</comment>
- <comment xml:lang="ga">fuaim Ogg Vorbis</comment>
- <comment xml:lang="gl">son Ogg Vorbis</comment>
- <comment xml:lang="he">שמע Ogg Vorbis</comment>
- <comment xml:lang="hr">Ogg Vorbis zvučni zapis</comment>
- <comment xml:lang="hu">Ogg Vorbis hang</comment>
- <comment xml:lang="ia">Audio Ogg Vorbis</comment>
- <comment xml:lang="id">Audio Ogg Vorbis</comment>
- <comment xml:lang="it">Audio Ogg Vorbis</comment>
- <comment xml:lang="ja">Ogg Vorbis オーディオ</comment>
- <comment xml:lang="ka">Ogg Vorbis აუდიო</comment>
- <comment xml:lang="kk">Ogg Vorbis аудиосы</comment>
- <comment xml:lang="ko">Ogg Vorbis 오디오</comment>
- <comment xml:lang="lt">Ogg Vorbis garso įrašas</comment>
- <comment xml:lang="lv">Ogg Vorbis audio</comment>
- <comment xml:lang="ms">Audio Ogg Vorbis</comment>
- <comment xml:lang="nb">Ogg Vorbis lyd</comment>
- <comment xml:lang="nl">Ogg Vorbis-audio</comment>
- <comment xml:lang="nn">Ogg Vorbis-lyd</comment>
- <comment xml:lang="oc">àudio Ogg Vorbis</comment>
- <comment xml:lang="pl">Plik dźwiękowy Ogg Vorbis</comment>
- <comment xml:lang="pt">áudio Ogg Vorbis</comment>
- <comment xml:lang="pt_BR">Áudio Ogg Vorbis</comment>
- <comment xml:lang="ro">Audio Ogg Vorbis</comment>
- <comment xml:lang="ru">Аудио Ogg Vorbis</comment>
- <comment xml:lang="sk">Zvuk Ogg Vorbis</comment>
- <comment xml:lang="sl">Zvočna datoteka Ogg Vorbis</comment>
- <comment xml:lang="sq">Audio Ogg Vorbis</comment>
- <comment xml:lang="sr">Огг Ворбис звук</comment>
- <comment xml:lang="sv">Ogg Vorbis-ljud</comment>
- <comment xml:lang="tr">Ogg Vorbis sesi</comment>
- <comment xml:lang="uk">звук ogg Vorbis</comment>
- <comment xml:lang="vi">Âm thanh Vorbis Ogg</comment>
- <comment xml:lang="zh_CN">Ogg Vorbis 音频</comment>
<comment xml:lang="zh_TW">Ogg Vorbis 音訊</comment>
+ <comment xml:lang="zh_CN">Ogg Vorbis 音频</comment>
+ <comment xml:lang="vi">Âm thanh Vorbis Ogg</comment>
+ <comment xml:lang="uk">звук ogg Vorbis</comment>
+ <comment xml:lang="tr">Ogg Vorbis sesi</comment>
+ <comment xml:lang="sv">Ogg Vorbis-ljud</comment>
+ <comment xml:lang="sr">Огг Ворбис звук</comment>
+ <comment xml:lang="sq">audio Ogg Vorbis</comment>
+ <comment xml:lang="sl">Zvočna datoteka Ogg Vorbis</comment>
+ <comment xml:lang="si">Ogg Vorbis ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk Ogg Vorbis</comment>
+ <comment xml:lang="ru">Аудио Ogg Vorbis</comment>
+ <comment xml:lang="ro">Audio Ogg Vorbis</comment>
+ <comment xml:lang="pt_BR">Áudio Ogg Vorbis</comment>
+ <comment xml:lang="pt">áudio Ogg Vorbis</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Ogg Vorbis</comment>
+ <comment xml:lang="oc">àudio Ogg Vorbis</comment>
+ <comment xml:lang="nn">Ogg Vorbis-lyd</comment>
+ <comment xml:lang="nl">Ogg Vorbis-audio</comment>
+ <comment xml:lang="nb">Ogg Vorbis lyd</comment>
+ <comment xml:lang="ms">Audio Ogg Vorbis</comment>
+ <comment xml:lang="lv">Ogg Vorbis audio</comment>
+ <comment xml:lang="lt">Ogg Vorbis garso įrašas</comment>
+ <comment xml:lang="ko">Ogg Vorbis 오디오</comment>
+ <comment xml:lang="kk">Ogg Vorbis аудиосы</comment>
+ <comment xml:lang="ka">Ogg Vorbis აუდიო</comment>
+ <comment xml:lang="ja">Ogg Vorbis オーディオ</comment>
+ <comment xml:lang="it">Audio Ogg Vorbis</comment>
+ <comment xml:lang="is">Ogg Vorbis hljóðskrá</comment>
+ <comment xml:lang="id">Audio Ogg Vorbis</comment>
+ <comment xml:lang="ia">Audio Ogg Vorbis</comment>
+ <comment xml:lang="hu">Ogg Vorbis hang</comment>
+ <comment xml:lang="hr">Ogg Vorbis zvučni zapis</comment>
+ <comment xml:lang="he">שמע Ogg Vorbis</comment>
+ <comment xml:lang="gl">son Ogg Vorbis</comment>
+ <comment xml:lang="ga">fuaim Ogg Vorbis</comment>
+ <comment xml:lang="fur">audio Ogg Vorbis</comment>
+ <comment xml:lang="fr">audio Ogg Vorbis</comment>
+ <comment xml:lang="fo">Ogg Vorbis ljóður</comment>
+ <comment xml:lang="fi">Ogg Vorbis -ääni</comment>
+ <comment xml:lang="eu">Ogg Vorbis audioa</comment>
+ <comment xml:lang="es">sonido Ogg Vorbis</comment>
+ <comment xml:lang="eo">Ogg-Vorbis-sondosiero</comment>
+ <comment xml:lang="en_GB">Ogg Vorbis audio</comment>
+ <comment xml:lang="el">Ήχος Ogg Vobris</comment>
+ <comment xml:lang="de">Ogg-Vorbis-Audio</comment>
+ <comment xml:lang="da">Ogg Vorbis-lyd</comment>
+ <comment xml:lang="cy">Sain Ogg Vorbis</comment>
+ <comment xml:lang="cs">zvuk Ogg Vorbis</comment>
+ <comment xml:lang="ca">àudio Ogg Vorbis</comment>
+ <comment xml:lang="bg">Аудио — Ogg Vorbis</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Ogg Vorbis</comment>
+ <comment xml:lang="be">аўдыя Ogg Vorbis</comment>
+ <comment xml:lang="az">Ogg Vorbis audio faylı</comment>
+ <comment xml:lang="ar">صوت Ogg Vorbis</comment>
+ <comment xml:lang="af">Ogg Vorbis-oudio</comment>
<sub-class-of type="audio/ogg"/>
<alias type="audio/vorbis"/>
<alias type="audio/x-vorbis"/>
<magic priority="80">
- <match value="OggS" type="string" offset="0">
- <match value="\x01vorbis" type="string" offset="28"/>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="\x01vorbis" offset="28"/>
</match>
</magic>
<glob pattern="*.oga"/>
@@ -17267,58 +18819,63 @@
</mime-type>
<mime-type type="audio/x-flac+ogg">
<comment>Ogg FLAC audio</comment>
- <comment xml:lang="ar">Ogg FLAC سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Ogg FLAC</comment>
- <comment xml:lang="bg">Аудио — Ogg FLAC</comment>
- <comment xml:lang="ca">àudio FLAC d'Ogg</comment>
- <comment xml:lang="cs">zvuk Ogg FLAC</comment>
- <comment xml:lang="da">Ogg FLAC-lyd</comment>
- <comment xml:lang="de">Ogg-FLAC-Audio</comment>
- <comment xml:lang="el">Ήχος Ogg FLAC</comment>
- <comment xml:lang="en_GB">Ogg FLAC audio</comment>
- <comment xml:lang="es">sonido Ogg FLAC</comment>
- <comment xml:lang="eu">Ogg FLAC audioa</comment>
- <comment xml:lang="fi">Ogg FLAC -ääni</comment>
- <comment xml:lang="fo">Ogg FLAC ljóður</comment>
- <comment xml:lang="fr">audio Ogg FLAC</comment>
- <comment xml:lang="ga">fuaim Ogg FLAC</comment>
- <comment xml:lang="gl">son Ogg FLAC</comment>
- <comment xml:lang="he">שמע Ogg FLAC</comment>
- <comment xml:lang="hr">Ogg FLAC zvučni zapis</comment>
- <comment xml:lang="hu">Ogg FLAC hang</comment>
- <comment xml:lang="ia">Audio Ogg FLAC</comment>
- <comment xml:lang="id">Audio Ogg FLAC</comment>
- <comment xml:lang="it">Audio Ogg FLAC</comment>
- <comment xml:lang="ja">Ogg FLAC オーディオ</comment>
- <comment xml:lang="ka">Ogg FLAC აუდიო</comment>
- <comment xml:lang="kk">Ogg FLAC аудиосы</comment>
- <comment xml:lang="ko">Ogg FLAC 오디오</comment>
- <comment xml:lang="lt">Ogg FLAC garso įrašas</comment>
- <comment xml:lang="lv">Ogg FLAC audio</comment>
- <comment xml:lang="nb">Ogg FLAC-lyd</comment>
- <comment xml:lang="nl">Ogg FLAC-audio</comment>
- <comment xml:lang="nn">Ogg FLAC-lyd</comment>
- <comment xml:lang="oc">àudio Ogg FLAC</comment>
- <comment xml:lang="pl">Plik dźwiękowy Ogg FLAC</comment>
- <comment xml:lang="pt">áudio Ogg FLAC</comment>
- <comment xml:lang="pt_BR">Áudio Ogg FLAC</comment>
- <comment xml:lang="ro">Audio Ogg FLAC</comment>
- <comment xml:lang="ru">Аудио Ogg FLAC</comment>
- <comment xml:lang="sk">Zvuk Ogg FLAC</comment>
- <comment xml:lang="sl">Zvočna datoteka Ogg FLAC</comment>
- <comment xml:lang="sq">Audio Ogg FLAC</comment>
- <comment xml:lang="sr">Огг ФЛАЦ звук</comment>
- <comment xml:lang="sv">Ogg FLAC-ljud</comment>
- <comment xml:lang="tr">Ogg FLAC sesi</comment>
- <comment xml:lang="uk">звук ogg FLAC</comment>
- <comment xml:lang="vi">Âm thanh FLAC Ogg</comment>
- <comment xml:lang="zh_CN">Ogg FLAC 音频</comment>
<comment xml:lang="zh_TW">Ogg FLAC 音訊</comment>
+ <comment xml:lang="zh_CN">Ogg FLAC 音频</comment>
+ <comment xml:lang="vi">Âm thanh FLAC Ogg</comment>
+ <comment xml:lang="uk">звук ogg FLAC</comment>
+ <comment xml:lang="tr">Ogg FLAC sesi</comment>
+ <comment xml:lang="sv">Ogg FLAC-ljud</comment>
+ <comment xml:lang="sr">Огг ФЛАЦ звук</comment>
+ <comment xml:lang="sq">audio Ogg FLAC</comment>
+ <comment xml:lang="sl">Zvočna datoteka Ogg FLAC</comment>
+ <comment xml:lang="si">Ogg FLAC ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk Ogg FLAC</comment>
+ <comment xml:lang="ru">Аудио Ogg FLAC</comment>
+ <comment xml:lang="ro">Audio Ogg FLAC</comment>
+ <comment xml:lang="pt_BR">Áudio Ogg FLAC</comment>
+ <comment xml:lang="pt">áudio Ogg FLAC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Ogg FLAC</comment>
+ <comment xml:lang="oc">àudio Ogg FLAC</comment>
+ <comment xml:lang="nn">Ogg FLAC-lyd</comment>
+ <comment xml:lang="nl">Ogg FLAC-audio</comment>
+ <comment xml:lang="nb">Ogg FLAC-lyd</comment>
+ <comment xml:lang="lv">Ogg FLAC audio</comment>
+ <comment xml:lang="lt">Ogg FLAC garso įrašas</comment>
+ <comment xml:lang="ko">Ogg FLAC 오디오</comment>
+ <comment xml:lang="kk">Ogg FLAC аудиосы</comment>
+ <comment xml:lang="ka">Ogg FLAC აუდიო</comment>
+ <comment xml:lang="ja">Ogg FLAC オーディオ</comment>
+ <comment xml:lang="it">Audio Ogg FLAC</comment>
+ <comment xml:lang="is">Ogg FLAC hljóðskrá</comment>
+ <comment xml:lang="id">Audio Ogg FLAC</comment>
+ <comment xml:lang="ia">Audio Ogg FLAC</comment>
+ <comment xml:lang="hu">Ogg FLAC hang</comment>
+ <comment xml:lang="hr">Ogg FLAC zvučni zapis</comment>
+ <comment xml:lang="he">שמע Ogg FLAC</comment>
+ <comment xml:lang="gl">son Ogg FLAC</comment>
+ <comment xml:lang="ga">fuaim Ogg FLAC</comment>
+ <comment xml:lang="fur">audio Ogg FLAC</comment>
+ <comment xml:lang="fr">audio Ogg FLAC</comment>
+ <comment xml:lang="fo">Ogg FLAC ljóður</comment>
+ <comment xml:lang="fi">Ogg FLAC -ääni</comment>
+ <comment xml:lang="eu">Ogg FLAC audioa</comment>
+ <comment xml:lang="es">sonido Ogg FLAC</comment>
+ <comment xml:lang="en_GB">Ogg FLAC audio</comment>
+ <comment xml:lang="el">Ήχος Ogg FLAC</comment>
+ <comment xml:lang="de">Ogg-FLAC-Audio</comment>
+ <comment xml:lang="da">Ogg FLAC-lyd</comment>
+ <comment xml:lang="cs">zvuk Ogg FLAC</comment>
+ <comment xml:lang="ca">àudio Ogg FLAC</comment>
+ <comment xml:lang="bg">Аудио — Ogg FLAC</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Ogg FLAC</comment>
+ <comment xml:lang="be">аўдыя Ogg FLAC</comment>
+ <comment xml:lang="ar">صوت Ogg FLAC</comment>
+ <comment xml:lang="af">Ogg FLAC-oudio</comment>
<sub-class-of type="audio/ogg"/>
<alias type="audio/x-oggflac"/>
<magic priority="80">
- <match value="OggS" type="string" offset="0">
- <match value="fLaC" type="string" offset="28"/>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="fLaC" offset="28"/>
</match>
<match value="OggS" type="string" offset="0">
<match value="\177FLAC" type="string" offset="28"/>
@@ -17329,841 +18886,1014 @@
</mime-type>
<mime-type type="audio/x-opus+ogg">
<comment>Opus audio</comment>
- <comment xml:lang="ca">àudio d'Opus</comment>
- <comment xml:lang="cs">zvuk Opus</comment>
- <comment xml:lang="da">Opus-lyd</comment>
- <comment xml:lang="de">Opus-Audio</comment>
- <comment xml:lang="el">Ήχος Opus </comment>
- <comment xml:lang="en_GB">Opus audio</comment>
- <comment xml:lang="es">sonido Opus</comment>
- <comment xml:lang="eu">Opus audioa</comment>
- <comment xml:lang="fi">Opus-ääni</comment>
- <comment xml:lang="fr">audio Opus</comment>
- <comment xml:lang="ga">fuaim Opus</comment>
- <comment xml:lang="gl">Son Opus</comment>
- <comment xml:lang="he">שמע Opus</comment>
- <comment xml:lang="hr">Opus zvučni zapis</comment>
- <comment xml:lang="hu">Opus hang</comment>
- <comment xml:lang="ia">Audio Opus</comment>
- <comment xml:lang="id">Audio Opus</comment>
- <comment xml:lang="it">Audio Opus</comment>
- <comment xml:lang="kk">Opus аудиосы</comment>
- <comment xml:lang="ko">Opus 오디오</comment>
- <comment xml:lang="oc">àudio Opus</comment>
- <comment xml:lang="pl">Plik dźwiękowy Opus</comment>
- <comment xml:lang="pt">áudio Opus</comment>
- <comment xml:lang="pt_BR">Áudio Opus</comment>
- <comment xml:lang="ru">Аудио Opus</comment>
- <comment xml:lang="sk">Zvuk Opu</comment>
- <comment xml:lang="sl">Zvočna datoteka Opus</comment>
- <comment xml:lang="sr">Опус звук</comment>
- <comment xml:lang="sv">Opus-ljud</comment>
- <comment xml:lang="tr">Opus sesi</comment>
- <comment xml:lang="uk">звук Opus</comment>
- <comment xml:lang="zh_CN">Opus 音频</comment>
<comment xml:lang="zh_TW">Opus 音訊</comment>
+ <comment xml:lang="zh_CN">Opus 音频</comment>
+ <comment xml:lang="uk">звук Opus</comment>
+ <comment xml:lang="tr">Opus sesi</comment>
+ <comment xml:lang="sv">Opus-ljud</comment>
+ <comment xml:lang="sr">Опус звук</comment>
+ <comment xml:lang="sq">audio Opus</comment>
+ <comment xml:lang="sl">Zvočna datoteka Opus</comment>
+ <comment xml:lang="si">ඕපස් ඕඩියෝ</comment>
+ <comment xml:lang="sk">Zvuk Opu</comment>
+ <comment xml:lang="ru">Аудио Opus</comment>
+ <comment xml:lang="pt_BR">Áudio Opus</comment>
+ <comment xml:lang="pt">áudio Opus</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Opus</comment>
+ <comment xml:lang="oc">àudio Opus</comment>
+ <comment xml:lang="nl">Opus-audio</comment>
+ <comment xml:lang="ko">Opus 오디오</comment>
+ <comment xml:lang="kk">Opus аудиосы</comment>
+ <comment xml:lang="ja">Opus オーディオ</comment>
+ <comment xml:lang="it">Audio Opus</comment>
+ <comment xml:lang="is">Opus hljóðskrá</comment>
+ <comment xml:lang="id">Audio Opus</comment>
+ <comment xml:lang="ia">Audio Opus</comment>
+ <comment xml:lang="hu">Opus hang</comment>
+ <comment xml:lang="hr">Opus zvučni zapis</comment>
+ <comment xml:lang="he">שמע Opus</comment>
+ <comment xml:lang="gl">Son Opus</comment>
+ <comment xml:lang="ga">fuaim Opus</comment>
+ <comment xml:lang="fur">audio Opus</comment>
+ <comment xml:lang="fr">audio Opus</comment>
+ <comment xml:lang="fi">Opus-ääni</comment>
+ <comment xml:lang="eu">Opus audioa</comment>
+ <comment xml:lang="es">sonido Opus</comment>
+ <comment xml:lang="en_GB">Opus audio</comment>
+ <comment xml:lang="el">Ήχος Opus </comment>
+ <comment xml:lang="de">Opus-Audio</comment>
+ <comment xml:lang="da">Opus-lyd</comment>
+ <comment xml:lang="cs">zvuk Opus</comment>
+ <comment xml:lang="ca">àudio Opus</comment>
+ <comment xml:lang="bg">Аудио — Opus</comment>
+ <comment xml:lang="be">аўдыя Opus</comment>
+ <comment xml:lang="ar">صوت Opus</comment>
+ <comment xml:lang="af">Opus-oudio</comment>
<sub-class-of type="audio/ogg"/>
<magic priority="80">
- <match value="OggS" type="string" offset="0">
- <match value="OpusHead" type="string" offset="28"/>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="OpusHead" offset="28"/>
</match>
</magic>
<glob pattern="*.opus"/>
</mime-type>
<mime-type type="audio/x-speex+ogg">
<comment>Ogg Speex audio</comment>
- <comment xml:lang="ar">Ogg Speex سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Ogg Speex</comment>
- <comment xml:lang="bg">Аудио — Ogg Speex</comment>
- <comment xml:lang="ca">àudio Speex d'Ogg</comment>
- <comment xml:lang="cs">zvuk Ogg Speex</comment>
- <comment xml:lang="da">Ogg Speex-lyd</comment>
- <comment xml:lang="de">Ogg-Speex-Audio</comment>
- <comment xml:lang="el">Ήχος Ogg Speex</comment>
- <comment xml:lang="en_GB">Ogg Speex audio</comment>
- <comment xml:lang="es">sonido Ogg Speex</comment>
- <comment xml:lang="eu">Ogg Speex audioa</comment>
- <comment xml:lang="fi">Ogg Speex -ääni</comment>
- <comment xml:lang="fo">Ogg Speex ljóður</comment>
- <comment xml:lang="fr">audio Ogg Speex</comment>
- <comment xml:lang="ga">fuaim Ogg Speex</comment>
- <comment xml:lang="gl">son Ogg Speex</comment>
- <comment xml:lang="he">שמע Ogg Speex</comment>
- <comment xml:lang="hr">Ogg Speex zvučni zapis</comment>
- <comment xml:lang="hu">Ogg Speex hang</comment>
- <comment xml:lang="ia">Audio Ogg Speex</comment>
- <comment xml:lang="id">Audio Ogg Speex</comment>
- <comment xml:lang="it">Audio Ogg Speex</comment>
- <comment xml:lang="ja">Ogg Speex オーディオ</comment>
- <comment xml:lang="ka">Ogg Speex აუდიო</comment>
- <comment xml:lang="kk">Ogg Speex аудиосы</comment>
- <comment xml:lang="ko">Ogg Speex 오디오</comment>
- <comment xml:lang="lt">Ogg Speex garso įrašas</comment>
- <comment xml:lang="lv">Ogg Speex audio</comment>
- <comment xml:lang="nb">Ogg Speex lyd</comment>
- <comment xml:lang="nl">Ogg Speex-audio</comment>
- <comment xml:lang="nn">Ogg Speex-lyd</comment>
- <comment xml:lang="oc">àudio Ogg Speex</comment>
- <comment xml:lang="pl">Plik dźwiękowy Ogg Speex</comment>
- <comment xml:lang="pt">áudio Ogg Speex</comment>
- <comment xml:lang="pt_BR">Áudio Ogg Speex</comment>
- <comment xml:lang="ro">Audio Ogg Speex</comment>
- <comment xml:lang="ru">Аудио Ogg Speex</comment>
- <comment xml:lang="sk">Zvuk Ogg Speex</comment>
- <comment xml:lang="sl">Zvočna datoteka Ogg Speex</comment>
- <comment xml:lang="sq">Audio Ogg Speex</comment>
- <comment xml:lang="sr">Огг Спикс звук</comment>
- <comment xml:lang="sv">Ogg Speex-ljud</comment>
- <comment xml:lang="tr">Ogg Speex sesi</comment>
- <comment xml:lang="uk">звук ogg Speex</comment>
- <comment xml:lang="vi">Âm thanh Speex Ogg</comment>
- <comment xml:lang="zh_CN">Ogg Speex 音频</comment>
<comment xml:lang="zh_TW">Ogg Speex 音訊</comment>
+ <comment xml:lang="zh_CN">Ogg Speex 音频</comment>
+ <comment xml:lang="vi">Âm thanh Speex Ogg</comment>
+ <comment xml:lang="uk">звук ogg Speex</comment>
+ <comment xml:lang="tr">Ogg Speex sesi</comment>
+ <comment xml:lang="sv">Ogg Speex-ljud</comment>
+ <comment xml:lang="sr">Огг Спикс звук</comment>
+ <comment xml:lang="sq">audio Ogg Speex</comment>
+ <comment xml:lang="sl">Zvočna datoteka Ogg Speex</comment>
+ <comment xml:lang="si">Ogg Speex ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk Ogg Speex</comment>
+ <comment xml:lang="ru">Аудио Ogg Speex</comment>
+ <comment xml:lang="ro">Audio Ogg Speex</comment>
+ <comment xml:lang="pt_BR">Áudio Ogg Speex</comment>
+ <comment xml:lang="pt">áudio Ogg Speex</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Ogg Speex</comment>
+ <comment xml:lang="oc">àudio Ogg Speex</comment>
+ <comment xml:lang="nn">Ogg Speex-lyd</comment>
+ <comment xml:lang="nl">Ogg Speex-audio</comment>
+ <comment xml:lang="nb">Ogg Speex lyd</comment>
+ <comment xml:lang="lv">Ogg Speex audio</comment>
+ <comment xml:lang="lt">Ogg Speex garso įrašas</comment>
+ <comment xml:lang="ko">Ogg Speex 오디오</comment>
+ <comment xml:lang="kk">Ogg Speex аудиосы</comment>
+ <comment xml:lang="ka">Ogg Speex აუდიო</comment>
+ <comment xml:lang="ja">Ogg Speex オーディオ</comment>
+ <comment xml:lang="it">Audio Ogg Speex</comment>
+ <comment xml:lang="is">Ogg Speex hljóðskrá</comment>
+ <comment xml:lang="id">Audio Ogg Speex</comment>
+ <comment xml:lang="ia">Audio Ogg Speex</comment>
+ <comment xml:lang="hu">Ogg Speex hang</comment>
+ <comment xml:lang="hr">Ogg Speex zvučni zapis</comment>
+ <comment xml:lang="he">שמע Ogg Speex</comment>
+ <comment xml:lang="gl">son Ogg Speex</comment>
+ <comment xml:lang="ga">fuaim Ogg Speex</comment>
+ <comment xml:lang="fur">audio Ogg Speex</comment>
+ <comment xml:lang="fr">audio Ogg Speex</comment>
+ <comment xml:lang="fo">Ogg Speex ljóður</comment>
+ <comment xml:lang="fi">Ogg Speex -ääni</comment>
+ <comment xml:lang="eu">Ogg Speex audioa</comment>
+ <comment xml:lang="es">sonido Ogg Speex</comment>
+ <comment xml:lang="en_GB">Ogg Speex audio</comment>
+ <comment xml:lang="el">Ήχος Ogg Speex</comment>
+ <comment xml:lang="de">Ogg-Speex-Audio</comment>
+ <comment xml:lang="da">Ogg Speex-lyd</comment>
+ <comment xml:lang="cs">zvuk Ogg Speex</comment>
+ <comment xml:lang="ca">àudio Ogg Speex</comment>
+ <comment xml:lang="bg">Аудио — Ogg Speex</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Ogg Speex</comment>
+ <comment xml:lang="be">аўдыя Ogg Speex</comment>
+ <comment xml:lang="ar">صوت Ogg Speex</comment>
+ <comment xml:lang="af">Ogg Speex-oudio</comment>
<sub-class-of type="audio/ogg"/>
<magic priority="80">
- <match value="OggS" type="string" offset="0">
- <match value="Speex " type="string" offset="28"/>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="Speex " offset="28"/>
</match>
</magic>
<glob pattern="*.oga"/>
<glob pattern="*.ogg"/>
+ <glob pattern="*.spx"/>
</mime-type>
<mime-type type="audio/x-speex">
<comment>Speex audio</comment>
- <comment xml:lang="ar">Speex سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Speex</comment>
- <comment xml:lang="bg">Аудио — Speex</comment>
- <comment xml:lang="ca">àudio de Speex</comment>
- <comment xml:lang="cs">zvuk Speex</comment>
- <comment xml:lang="da">Speexlyd</comment>
- <comment xml:lang="de">Speex-Audio</comment>
- <comment xml:lang="el">Ήχος Speex</comment>
- <comment xml:lang="en_GB">Speex audio</comment>
- <comment xml:lang="es">sonido Speex</comment>
- <comment xml:lang="eu">Speex audioa</comment>
- <comment xml:lang="fi">Speex-ääni</comment>
- <comment xml:lang="fo">Speex ljóður</comment>
- <comment xml:lang="fr">audio Speex</comment>
- <comment xml:lang="ga">fuaim Speex</comment>
- <comment xml:lang="gl">son Speex</comment>
- <comment xml:lang="he">שמע של Speex</comment>
- <comment xml:lang="hr">Speex zvučni zapis</comment>
- <comment xml:lang="hu">Speex hang</comment>
- <comment xml:lang="ia">Audio Speex</comment>
- <comment xml:lang="id">Audio Speex</comment>
- <comment xml:lang="it">Audio Speex</comment>
- <comment xml:lang="ja">Speex オーディオ</comment>
- <comment xml:lang="kk">Speex аудиосы</comment>
- <comment xml:lang="ko">Speex 오디오</comment>
- <comment xml:lang="lt">Speex garso įrašas</comment>
- <comment xml:lang="lv">Speex audio</comment>
- <comment xml:lang="nb">Speex lyd</comment>
- <comment xml:lang="nl">Speex-audio</comment>
- <comment xml:lang="nn">Speex-lyd</comment>
- <comment xml:lang="oc">àudio Speex</comment>
- <comment xml:lang="pl">Plik dźwiękowy Speex</comment>
- <comment xml:lang="pt">áudio Speex</comment>
- <comment xml:lang="pt_BR">Áudio Speex</comment>
- <comment xml:lang="ro">Audio Speex</comment>
- <comment xml:lang="ru">Аудио Speex</comment>
- <comment xml:lang="sk">Zvuk Speex</comment>
- <comment xml:lang="sl">Zvočna datoteka Speex</comment>
- <comment xml:lang="sq">Audio Speex</comment>
- <comment xml:lang="sr">Спикс звук</comment>
- <comment xml:lang="sv">Speex-ljud</comment>
- <comment xml:lang="tr">Speex sesi</comment>
- <comment xml:lang="uk">звук Speex</comment>
- <comment xml:lang="vi">Âm thanh Speex</comment>
- <comment xml:lang="zh_CN">Speex 音频</comment>
<comment xml:lang="zh_TW">Speex 音訊</comment>
- <magic priority="50">
- <match value="Speex" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">Speex 音频</comment>
+ <comment xml:lang="vi">Âm thanh Speex</comment>
+ <comment xml:lang="uk">звук Speex</comment>
+ <comment xml:lang="tr">Speex sesi</comment>
+ <comment xml:lang="sv">Speex-ljud</comment>
+ <comment xml:lang="sr">Спикс звук</comment>
+ <comment xml:lang="sq">audio Speex</comment>
+ <comment xml:lang="sl">Zvočna datoteka Speex</comment>
+ <comment xml:lang="si">ස්පීක්ස් ඕඩියෝ</comment>
+ <comment xml:lang="sk">Zvuk Speex</comment>
+ <comment xml:lang="ru">Аудио Speex</comment>
+ <comment xml:lang="ro">Audio Speex</comment>
+ <comment xml:lang="pt_BR">Áudio Speex</comment>
+ <comment xml:lang="pt">áudio Speex</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Speex</comment>
+ <comment xml:lang="oc">àudio Speex</comment>
+ <comment xml:lang="nn">Speex-lyd</comment>
+ <comment xml:lang="nl">Speex-audio</comment>
+ <comment xml:lang="nb">Speex lyd</comment>
+ <comment xml:lang="lv">Speex audio</comment>
+ <comment xml:lang="lt">Speex garso įrašas</comment>
+ <comment xml:lang="ko">Speex 오디오</comment>
+ <comment xml:lang="kk">Speex аудиосы</comment>
+ <comment xml:lang="ja">Speex オーディオ</comment>
+ <comment xml:lang="it">Audio Speex</comment>
+ <comment xml:lang="is">Speex hljóðskrá</comment>
+ <comment xml:lang="id">Audio Speex</comment>
+ <comment xml:lang="ia">Audio Speex</comment>
+ <comment xml:lang="hu">Speex hang</comment>
+ <comment xml:lang="hr">Speex zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Speex</comment>
+ <comment xml:lang="gl">son Speex</comment>
+ <comment xml:lang="ga">fuaim Speex</comment>
+ <comment xml:lang="fur">audio Speex</comment>
+ <comment xml:lang="fr">audio Speex</comment>
+ <comment xml:lang="fo">Speex ljóður</comment>
+ <comment xml:lang="fi">Speex-ääni</comment>
+ <comment xml:lang="eu">Speex audioa</comment>
+ <comment xml:lang="es">sonido Speex</comment>
+ <comment xml:lang="en_GB">Speex audio</comment>
+ <comment xml:lang="el">Ήχος Speex</comment>
+ <comment xml:lang="de">Speex-Audio</comment>
+ <comment xml:lang="da">Speex-lyd</comment>
+ <comment xml:lang="cs">zvuk Speex</comment>
+ <comment xml:lang="ca">àudio Speex</comment>
+ <comment xml:lang="bg">Аудио — Speex</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Speex</comment>
+ <comment xml:lang="be">аўдыя Speex</comment>
+ <comment xml:lang="ar">صوت Speex</comment>
+ <comment xml:lang="af">Speex-oudio</comment>
+ <magic>
+ <match type="string" value="Speex" offset="0"/>
</magic>
<glob pattern="*.spx"/>
</mime-type>
<mime-type type="video/x-theora+ogg">
<comment>Ogg Theora video</comment>
- <comment xml:lang="ar">Ogg Theora مرئي</comment>
- <comment xml:lang="ast">Videu n'Ogg Theora</comment>
- <comment xml:lang="be@latin">Videa Ogg Theora</comment>
- <comment xml:lang="bg">Видео — Ogg Theora</comment>
- <comment xml:lang="ca">vídeo Ogg Theora</comment>
- <comment xml:lang="cs">video Ogg Theora</comment>
- <comment xml:lang="da">Ogg Theora-video</comment>
- <comment xml:lang="de">Ogg-Theora-Video</comment>
- <comment xml:lang="el">Βίντεο Ogg Theora</comment>
- <comment xml:lang="en_GB">Ogg Theora video</comment>
- <comment xml:lang="es">vídeo Ogg Theora</comment>
- <comment xml:lang="eu">Ogg Theora bideoa</comment>
- <comment xml:lang="fi">Ogg Theora -video</comment>
- <comment xml:lang="fo">Ogg Theora video</comment>
- <comment xml:lang="fr">vidéo Ogg Theora</comment>
- <comment xml:lang="ga">físeán Ogg Theora</comment>
- <comment xml:lang="gl">vídeo Ogg Theora</comment>
- <comment xml:lang="he">שמע Ogg Theora</comment>
- <comment xml:lang="hr">Ogg Theora video snimka</comment>
- <comment xml:lang="hu">Ogg Theora videó</comment>
- <comment xml:lang="ia">Video Ogg Theora</comment>
- <comment xml:lang="id">Video Ogg Theora</comment>
- <comment xml:lang="it">Video Ogg Theora</comment>
- <comment xml:lang="ja">Ogg Theora 動画</comment>
- <comment xml:lang="ka">Ogg Theora ვიდეო</comment>
- <comment xml:lang="kk">Ogg Theora видеосы</comment>
- <comment xml:lang="ko">Ogg Theora 동영상</comment>
- <comment xml:lang="lt">Ogg Theora vaizdo įrašas</comment>
- <comment xml:lang="lv">Ogg Theora video</comment>
- <comment xml:lang="nb">Ogg Theora video</comment>
- <comment xml:lang="nl">Ogg Theora-video</comment>
- <comment xml:lang="nn">Ogg Theora-video</comment>
- <comment xml:lang="oc">vidèo Ogg Theora</comment>
- <comment xml:lang="pl">Plik wideo Ogg Theora</comment>
- <comment xml:lang="pt">vídeo Ogg Theora</comment>
- <comment xml:lang="pt_BR">Vídeo Ogg Theora</comment>
- <comment xml:lang="ro">Video Ogg Theora</comment>
- <comment xml:lang="ru">Видео Ogg Theora</comment>
- <comment xml:lang="sk">Video Ogg Theora</comment>
- <comment xml:lang="sl">Video datoteka Ogg Theora</comment>
- <comment xml:lang="sq">Video Ogg Theora</comment>
- <comment xml:lang="sr">Огг Теора видео</comment>
- <comment xml:lang="sv">Ogg Theora-video</comment>
- <comment xml:lang="tr">Ogg Theora video</comment>
- <comment xml:lang="uk">відеокліп ogg Theora</comment>
- <comment xml:lang="vi">Ảnh động Theora Ogg</comment>
- <comment xml:lang="zh_CN">Ogg Theora 视频</comment>
<comment xml:lang="zh_TW">Ogg Theora 視訊</comment>
+ <comment xml:lang="zh_CN">Ogg Theora 视频</comment>
+ <comment xml:lang="vi">Ảnh động Theora Ogg</comment>
+ <comment xml:lang="uk">відеокліп ogg Theora</comment>
+ <comment xml:lang="tr">Ogg Theora video</comment>
+ <comment xml:lang="sv">Ogg Theora-video</comment>
+ <comment xml:lang="sr">Огг Теора видео</comment>
+ <comment xml:lang="sq">video Ogg Theora</comment>
+ <comment xml:lang="sl">Video datoteka Ogg Theora</comment>
+ <comment xml:lang="si">Ogg Theora වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Ogg Theora</comment>
+ <comment xml:lang="ru">Видео Ogg Theora</comment>
+ <comment xml:lang="ro">Video Ogg Theora</comment>
+ <comment xml:lang="pt_BR">Vídeo Ogg Theora</comment>
+ <comment xml:lang="pt">vídeo Ogg Theora</comment>
+ <comment xml:lang="pl">Plik wideo Ogg Theora</comment>
+ <comment xml:lang="oc">vidèo Ogg Theora</comment>
+ <comment xml:lang="nn">Ogg Theora-video</comment>
+ <comment xml:lang="nl">Ogg Theora-video</comment>
+ <comment xml:lang="nb">Ogg Theora video</comment>
+ <comment xml:lang="lv">Ogg Theora video</comment>
+ <comment xml:lang="lt">Ogg Theora vaizdo įrašas</comment>
+ <comment xml:lang="ko">Ogg Theora 동영상</comment>
+ <comment xml:lang="kk">Ogg Theora видеосы</comment>
+ <comment xml:lang="ka">Ogg Theora ვიდეო</comment>
+ <comment xml:lang="ja">Ogg Theora 動画</comment>
+ <comment xml:lang="it">Video Ogg Theora</comment>
+ <comment xml:lang="is">Ogg Theora myndskeið</comment>
+ <comment xml:lang="id">Video Ogg Theora</comment>
+ <comment xml:lang="ia">Video Ogg Theora</comment>
+ <comment xml:lang="hu">Ogg Theora videó</comment>
+ <comment xml:lang="hr">Ogg Theora video snimka</comment>
+ <comment xml:lang="he">שמע Ogg Theora</comment>
+ <comment xml:lang="gl">vídeo Ogg Theora</comment>
+ <comment xml:lang="ga">físeán Ogg Theora</comment>
+ <comment xml:lang="fur">video Ogg Theora</comment>
+ <comment xml:lang="fr">vidéo Ogg Theora</comment>
+ <comment xml:lang="fo">Ogg Theora video</comment>
+ <comment xml:lang="fi">Ogg Theora -video</comment>
+ <comment xml:lang="eu">Ogg Theora bideoa</comment>
+ <comment xml:lang="es">vídeo Ogg Theora</comment>
+ <comment xml:lang="en_GB">Ogg Theora video</comment>
+ <comment xml:lang="el">Βίντεο Ogg Theora</comment>
+ <comment xml:lang="de">Ogg-Theora-Video</comment>
+ <comment xml:lang="da">Ogg Theora-video</comment>
+ <comment xml:lang="cs">video Ogg Theora</comment>
+ <comment xml:lang="ca">vídeo Ogg Theora</comment>
+ <comment xml:lang="bg">Видео — Ogg Theora</comment>
+ <comment xml:lang="be@latin">Videa Ogg Theora</comment>
+ <comment xml:lang="be">відэа Ogg Theora</comment>
+ <comment xml:lang="ast">Videu n'Ogg Theora</comment>
+ <comment xml:lang="ar">فيديو Ogg Theora</comment>
+ <comment xml:lang="af">Ogg Theora-video</comment>
<sub-class-of type="video/ogg"/>
<alias type="video/x-theora"/>
<magic priority="80">
- <match value="OggS" type="string" offset="0">
- <match value="\x80theora" type="string" offset="28"/>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="\x80theora" offset="28"/>
</match>
</magic>
<glob pattern="*.ogg"/>
</mime-type>
<mime-type type="video/x-ogm+ogg">
<comment>OGM video</comment>
- <comment xml:lang="ar">OGM مرئي</comment>
- <comment xml:lang="ast">Videu n'OGM</comment>
- <comment xml:lang="be@latin">Videa OGM</comment>
- <comment xml:lang="bg">Видео — OGM</comment>
- <comment xml:lang="ca">vídeo OGM</comment>
- <comment xml:lang="cs">video OGM</comment>
- <comment xml:lang="da">OGM-video</comment>
- <comment xml:lang="de">OGM-Video</comment>
- <comment xml:lang="el">Βίντεο OGM</comment>
- <comment xml:lang="en_GB">OGM video</comment>
- <comment xml:lang="eo">OGM-video</comment>
- <comment xml:lang="es">vídeo OGM</comment>
- <comment xml:lang="eu">OGM bideoa</comment>
- <comment xml:lang="fi">OGM-video</comment>
- <comment xml:lang="fo">OGM video</comment>
- <comment xml:lang="fr">vidéo OGM</comment>
- <comment xml:lang="ga">físeán OGM</comment>
- <comment xml:lang="gl">vídeo OGM</comment>
- <comment xml:lang="he">וידאו OGM</comment>
- <comment xml:lang="hr">OGM video snimka</comment>
- <comment xml:lang="hu">OGM-videó</comment>
- <comment xml:lang="ia">Video OGM</comment>
- <comment xml:lang="id">Video OGM</comment>
- <comment xml:lang="it">Video OGM</comment>
- <comment xml:lang="ja">OGM 動画</comment>
- <comment xml:lang="ka">OGM ვიდეო</comment>
- <comment xml:lang="kk">OGM видеосы</comment>
- <comment xml:lang="ko">OGM 동영상</comment>
- <comment xml:lang="lt">OGM vaizdo įrašas</comment>
- <comment xml:lang="lv">OGM video</comment>
- <comment xml:lang="nb">OGM-film</comment>
- <comment xml:lang="nl">OGM-video</comment>
- <comment xml:lang="nn">OGM-video</comment>
- <comment xml:lang="oc">vidèo OGM</comment>
- <comment xml:lang="pl">Plik wideo OGM</comment>
- <comment xml:lang="pt">vídeo OGM</comment>
- <comment xml:lang="pt_BR">Vídeo OGM</comment>
- <comment xml:lang="ro">Video OGM</comment>
- <comment xml:lang="ru">Видео OGM</comment>
- <comment xml:lang="sk">Video OGM</comment>
- <comment xml:lang="sl">Video datoteka OGM</comment>
- <comment xml:lang="sq">Video OGM</comment>
- <comment xml:lang="sr">ОГМ видео</comment>
- <comment xml:lang="sv">OGM-video</comment>
- <comment xml:lang="tr">OGM video</comment>
- <comment xml:lang="uk">відеокліп OGM</comment>
- <comment xml:lang="vi">Ảnh động OGM</comment>
- <comment xml:lang="zh_CN">OGM 视频</comment>
<comment xml:lang="zh_TW">OGM 視訊</comment>
+ <comment xml:lang="zh_CN">OGM 视频</comment>
+ <comment xml:lang="vi">Ảnh động OGM</comment>
+ <comment xml:lang="uk">відеокліп OGM</comment>
+ <comment xml:lang="tr">OGM video</comment>
+ <comment xml:lang="sv">OGM-video</comment>
+ <comment xml:lang="sr">ОГМ видео</comment>
+ <comment xml:lang="sq">video OGM</comment>
+ <comment xml:lang="sl">Video datoteka OGM</comment>
+ <comment xml:lang="si">OGM වීඩියෝව</comment>
+ <comment xml:lang="sk">Video OGM</comment>
+ <comment xml:lang="ru">Видео OGM</comment>
+ <comment xml:lang="ro">Video OGM</comment>
+ <comment xml:lang="pt_BR">Vídeo OGM</comment>
+ <comment xml:lang="pt">vídeo OGM</comment>
+ <comment xml:lang="pl">Plik wideo OGM</comment>
+ <comment xml:lang="oc">vidèo OGM</comment>
+ <comment xml:lang="nn">OGM-video</comment>
+ <comment xml:lang="nl">OGM-video</comment>
+ <comment xml:lang="nb">OGM-film</comment>
+ <comment xml:lang="lv">OGM video</comment>
+ <comment xml:lang="lt">OGM vaizdo įrašas</comment>
+ <comment xml:lang="ko">OGM 동영상</comment>
+ <comment xml:lang="kk">OGM видеосы</comment>
+ <comment xml:lang="ka">OGM ვიდეო</comment>
+ <comment xml:lang="ja">OGM 動画</comment>
+ <comment xml:lang="it">Video OGM</comment>
+ <comment xml:lang="is">OGM myndskeið</comment>
+ <comment xml:lang="id">Video OGM</comment>
+ <comment xml:lang="ia">Video OGM</comment>
+ <comment xml:lang="hu">OGM-videó</comment>
+ <comment xml:lang="hr">OGM video snimka</comment>
+ <comment xml:lang="he">וידאו OGM</comment>
+ <comment xml:lang="gl">vídeo OGM</comment>
+ <comment xml:lang="ga">físeán OGM</comment>
+ <comment xml:lang="fur">video OGM</comment>
+ <comment xml:lang="fr">vidéo OGM</comment>
+ <comment xml:lang="fo">OGM video</comment>
+ <comment xml:lang="fi">OGM-video</comment>
+ <comment xml:lang="eu">OGM bideoa</comment>
+ <comment xml:lang="es">vídeo OGM</comment>
+ <comment xml:lang="eo">OGM-video</comment>
+ <comment xml:lang="en_GB">OGM video</comment>
+ <comment xml:lang="el">Βίντεο OGM</comment>
+ <comment xml:lang="de">OGM-Video</comment>
+ <comment xml:lang="da">OGM-video</comment>
+ <comment xml:lang="cs">video OGM</comment>
+ <comment xml:lang="ca">vídeo OGM</comment>
+ <comment xml:lang="bg">Видео — OGM</comment>
+ <comment xml:lang="be@latin">Videa OGM</comment>
+ <comment xml:lang="be">відэа OGM</comment>
+ <comment xml:lang="ast">Videu n'OGM</comment>
+ <comment xml:lang="ar">فيديو OGM</comment>
+ <comment xml:lang="af">OGM-video</comment>
<sub-class-of type="video/ogg"/>
<alias type="video/x-ogm"/>
<magic priority="80">
- <match value="OggS" type="string" offset="0">
- <match value="video" type="string" offset="29"/>
+ <match type="string" value="OggS" offset="0">
+ <match type="string" value="video" offset="29"/>
</match>
</magic>
<glob pattern="*.ogm"/>
</mime-type>
-
+ <!-- These are typically compount document of various types, so prefer
+ extensions for these -->
<mime-type type="application/x-ole-storage">
<comment>OLE2 compound document storage</comment>
- <comment xml:lang="ar">تخزين مجمع مستند OLE2</comment>
- <comment xml:lang="ast">Almacenamientu de documentos compuestu por OLE2</comment>
- <comment xml:lang="be@latin">Schovišča dla kampanentaŭ dakumentu OLE2</comment>
- <comment xml:lang="bg">Съставен документ-хранилище — OLE2</comment>
- <comment xml:lang="ca">emmagatzematge de documents compostos OLE2</comment>
- <comment xml:lang="cs">úložiště složeného dokumentu OLE2</comment>
- <comment xml:lang="da">OLE2-sammensat dokumentlager</comment>
- <comment xml:lang="de">OLE2-Verbunddokumentenspeicher</comment>
- <comment xml:lang="el">Αρχείο συμπαγούς αποθήκευσης εγγράφων OLE2</comment>
- <comment xml:lang="en_GB">OLE2 compound document storage</comment>
- <comment xml:lang="eo">OLE2-deponejo de parentezaj dokumentoj</comment>
- <comment xml:lang="es">almacenamiento de documentos compuestos OLE2</comment>
- <comment xml:lang="eu">OLE2 konposatutako dokumentu-bilduma</comment>
- <comment xml:lang="fi">OLE2-yhdisteasiakirjatallenne</comment>
- <comment xml:lang="fo">OLE2 samansett skjalagoymsla</comment>
- <comment xml:lang="fr">document de stockage composé OLE2</comment>
- <comment xml:lang="ga">stóras cáipéisí comhshuite OLE2</comment>
- <comment xml:lang="gl">almacenamento de documento composto OLE2</comment>
- <comment xml:lang="he">אחסון מסמך משותף OLE2</comment>
- <comment xml:lang="hr">OLE2 pohrana složenog dokumenta</comment>
- <comment xml:lang="hu">OLE2 összetett dokumentumtároló</comment>
- <comment xml:lang="ia">Magazin de documentos composite OLE2</comment>
- <comment xml:lang="id">penyimpan dokumen kompon OLE2</comment>
- <comment xml:lang="it">Memorizzazione documento composto OLE2</comment>
- <comment xml:lang="ja">OLE2 複合ドキュメントストレージ</comment>
- <comment xml:lang="kk">OLE2 құрама құжаттар қоймасы</comment>
- <comment xml:lang="ko">OLE2 복합 문서</comment>
- <comment xml:lang="lt">OLE2 sudėtinių dokumentų laikmena</comment>
- <comment xml:lang="lv">OLE2 savienoto dokumentu glabātuve</comment>
- <comment xml:lang="ms">Storan dokumen halaman OLE2</comment>
- <comment xml:lang="nb">OLE-lager for sammensatte dokumenter</comment>
- <comment xml:lang="nl">OLE2-samengestelde documentopslag</comment>
- <comment xml:lang="nn">OLE2 lager for samansett dokument</comment>
- <comment xml:lang="oc">document d'emmagazinatge compausat OLE2</comment>
- <comment xml:lang="pl">Magazyn dokumentu złożonego OLE2</comment>
- <comment xml:lang="pt">armazenamento de documento composto OLE2</comment>
- <comment xml:lang="pt_BR">Armazenamento de documento composto OLE2</comment>
- <comment xml:lang="ro">Document de stocare compus OLE2</comment>
- <comment xml:lang="ru">Хранилище составных документов OLE2</comment>
- <comment xml:lang="sk">Úložisko zloženého dokumentu OLE2</comment>
- <comment xml:lang="sl">Združeni dokument OLE2</comment>
- <comment xml:lang="sq">Arkiv dokumenti i përbërë OLE2</comment>
- <comment xml:lang="sr">смештај ОЛЕ2 сједињеног документа</comment>
- <comment xml:lang="sv">Sammansatt OLE2-dokumentlager</comment>
- <comment xml:lang="tr">OLE2 bileşik belge depolama</comment>
- <comment xml:lang="uk">сховище складних документів OLE2</comment>
- <comment xml:lang="vi">Kho lưu tài liệu ghép OLE2</comment>
- <comment xml:lang="zh_CN">OLE2 组合文档存储</comment>
<comment xml:lang="zh_TW">OLE2 複合文件儲存</comment>
+ <comment xml:lang="zh_CN">OLE2 组合文档存储</comment>
+ <comment xml:lang="vi">Kho lưu tài liệu ghép OLE2</comment>
+ <comment xml:lang="uk">сховище складних документів OLE2</comment>
+ <comment xml:lang="tr">OLE2 bileşik belge depolama</comment>
+ <comment xml:lang="sv">Sammansatt OLE2-dokumentlager</comment>
+ <comment xml:lang="sr">смештај ОЛЕ2 сједињеног документа</comment>
+ <comment xml:lang="sq">depozitë dokumenti të përbërë OLE2</comment>
+ <comment xml:lang="sl">Združeni dokument OLE2</comment>
+ <comment xml:lang="si">OLE2 සංයුක්ත ලේඛන ගබඩා කිරීම</comment>
+ <comment xml:lang="sk">Úložisko zloženého dokumentu OLE2</comment>
+ <comment xml:lang="ru">Хранилище составных документов OLE2</comment>
+ <comment xml:lang="ro">Document de stocare compus OLE2</comment>
+ <comment xml:lang="pt_BR">Armazenamento de documento composto OLE2</comment>
+ <comment xml:lang="pt">armazenamento de documento composto OLE2</comment>
+ <comment xml:lang="pl">Magazyn dokumentu złożonego OLE2</comment>
+ <comment xml:lang="oc">document d'emmagazinatge compausat OLE2</comment>
+ <comment xml:lang="nn">OLE2 lager for samansett dokument</comment>
+ <comment xml:lang="nl">OLE2-samengestelde documentopslag</comment>
+ <comment xml:lang="nb">OLE-lager for sammensatte dokumenter</comment>
+ <comment xml:lang="ms">Storan dokumen halaman OLE2</comment>
+ <comment xml:lang="lv">OLE2 savienoto dokumentu glabātuve</comment>
+ <comment xml:lang="lt">OLE2 sudėtinių dokumentų laikmena</comment>
+ <comment xml:lang="ko">OLE2 복합 문서</comment>
+ <comment xml:lang="kk">OLE2 құрама құжаттар қоймасы</comment>
+ <comment xml:lang="ja">OLE2 複合ドキュメントストレージ</comment>
+ <comment xml:lang="it">Memorizzazione documento composto OLE2</comment>
+ <comment xml:lang="is">OLE2 samsett skjalageymsla</comment>
+ <comment xml:lang="id">Penyimpan dokumen kompon OLE2</comment>
+ <comment xml:lang="ia">Magazin de documentos composite OLE2</comment>
+ <comment xml:lang="hu">OLE2 összetett dokumentumtároló</comment>
+ <comment xml:lang="hr">OLE2 pohrana složenog dokumenta</comment>
+ <comment xml:lang="he">אחסון מסמך משותף OLE2</comment>
+ <comment xml:lang="gl">almacenamento de documento composto OLE2</comment>
+ <comment xml:lang="ga">stóras cáipéisí comhshuite OLE2</comment>
+ <comment xml:lang="fur">memorizazion document compost OLE2</comment>
+ <comment xml:lang="fr">document de stockage composé OLE2</comment>
+ <comment xml:lang="fo">OLE2 samansett skjalagoymsla</comment>
+ <comment xml:lang="fi">OLE2-yhdisteasiakirjatallenne</comment>
+ <comment xml:lang="eu">OLE2 konposatutako dokumentu-bilduma</comment>
+ <comment xml:lang="es">almacenamiento de documentos compuestos OLE2</comment>
+ <comment xml:lang="eo">OLE2-deponejo de parentezaj dokumentoj</comment>
+ <comment xml:lang="en_GB">OLE2 compound document storage</comment>
+ <comment xml:lang="el">Αρχείο συμπαγούς αποθήκευσης εγγράφων OLE2</comment>
+ <comment xml:lang="de">OLE2-Verbunddokumentspeicher</comment>
+ <comment xml:lang="da">OLE2-sammensat dokumentlager</comment>
+ <comment xml:lang="cs">úložiště složeného dokumentu OLE2</comment>
+ <comment xml:lang="ca">emmagatzematge de documents compostos OLE2</comment>
+ <comment xml:lang="bg">Съставен документ-хранилище — OLE2</comment>
+ <comment xml:lang="be@latin">Schovišča dla kampanentaŭ dakumentu OLE2</comment>
+ <comment xml:lang="be">сховішча складаных дакументаў OLE2</comment>
+ <comment xml:lang="ast">Almacenamientu de documentos compuestu por OLE2</comment>
+ <comment xml:lang="ar">تخزين مجمع مستند OLE2</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="\320\317\021\340\241\261\032\341" type="string" offset="0"/>
- <match value="0xe011cfd0" type="little32" offset="0"/>
- </magic>
+ <magic>
+ <match type="string" value="\320\317\021\340\241\261\032\341" offset="0"/>
+ <match type="little32" value="0xe011cfd0" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/vnd.microsoft.windows.thumbnail-cache">
+ <comment>Microsoft Windows Thumbnail Cache</comment>
+ <comment xml:lang="uk">кеш мініатюр Microsoft Windows</comment>
+ <comment xml:lang="sv">Microsoft Windows-miniatyrbildscache</comment>
+ <comment xml:lang="ru">Кэш миниатюр Microsoft Windows</comment>
+ <comment xml:lang="pl">Pamięć podręczna miniatur Microsoft Windows</comment>
+ <comment xml:lang="it">Cache miniuature Microsoft Windows</comment>
+ <comment xml:lang="eu">Microsoft Windows miniatura-cachea</comment>
+ <comment xml:lang="es">antememoria de miniaturas de Microsoft Windows</comment>
+ <comment xml:lang="de">Microsoft Windows-Vorschaubilderzwischenspeicher</comment>
+ <comment xml:lang="be">пакет тэмы Microsoft Windows</comment>
+ <sub-class-of type="application/x-ole-storage"/>
+ <generic-icon name="image-x-generic"/>
+ <glob pattern="ehthumbs.db"/>
+ <glob pattern="ehthumbs_vista.db"/>
+ <glob pattern="image.db"/>
+ <glob pattern="musicthumbs.db"/>
+ <glob pattern="thumbs.db"/>
+ <glob pattern="tvthumb.db"/>
+ <glob pattern="video.db"/>
</mime-type>
<mime-type type="application/vnd.ms-publisher">
<comment>Microsoft Publisher document</comment>
- <comment xml:lang="ast">Documentu de Microsoft Publisher</comment>
- <comment xml:lang="ca">document de Microsoft Publisher</comment>
- <comment xml:lang="cs">dokument Microsoft Publisher</comment>
- <comment xml:lang="da">Microsoft Publisher-dokument</comment>
- <comment xml:lang="de">Microsoft-Publisher-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Microsoft Publisher</comment>
- <comment xml:lang="en_GB">Microsoft Publisher document</comment>
- <comment xml:lang="es">documento de Microsoft Publisher</comment>
- <comment xml:lang="eu">Microsoft Publisher dokumentua</comment>
- <comment xml:lang="fi">Microsoft Publisher -asiakirja</comment>
- <comment xml:lang="fr">document Microsoft Publisher</comment>
- <comment xml:lang="ga">cáipéis Microsoft Publisher</comment>
- <comment xml:lang="gl">Documento de Microsoft Publisher</comment>
- <comment xml:lang="he">מסמך Microsoft Publisher</comment>
- <comment xml:lang="hr">Microsoft Publisher dokument</comment>
- <comment xml:lang="hu">Microsoft Publisher dokumentum</comment>
- <comment xml:lang="ia">Documento Microsoft Publisher</comment>
- <comment xml:lang="id">Dokumen Microsoft Publisher</comment>
- <comment xml:lang="it">Documento Microsoft Publisher</comment>
- <comment xml:lang="kk">Microsoft Publisher құжаты</comment>
- <comment xml:lang="ko">Microsoft Publisher 문서</comment>
- <comment xml:lang="oc">document Microsoft Publisher</comment>
- <comment xml:lang="pl">Dokument Microsoft Publisher</comment>
- <comment xml:lang="pt">documento Microsoft Publisher</comment>
- <comment xml:lang="pt_BR">Documento do Microsoft Publisher</comment>
- <comment xml:lang="ru">Документ Microsoft Publisher</comment>
- <comment xml:lang="sk">Dokument Microsoft Publisher</comment>
- <comment xml:lang="sl">Dokument Microsoft Publisher</comment>
- <comment xml:lang="sr">документ Мајкрософтовог Издавача</comment>
- <comment xml:lang="sv">Microsoft Publisher-dokument</comment>
- <comment xml:lang="tr">Microsoft Publisher belgesi</comment>
- <comment xml:lang="uk">документ Microsoft Publisher</comment>
+ <comment xml:lang="zh_TW">微軟 Publisher 文件</comment>
<comment xml:lang="zh_CN">Microsoft Publisher 文档</comment>
- <comment xml:lang="zh_TW">Microsoft Publisher 文件</comment>
+ <comment xml:lang="uk">документ Microsoft Publisher</comment>
+ <comment xml:lang="tr">Microsoft Publisher belgesi</comment>
+ <comment xml:lang="sv">Microsoft Publisher-dokument</comment>
+ <comment xml:lang="sr">документ Мајкрософтовог Издавача</comment>
+ <comment xml:lang="sq">dokument Microsoft Publisher</comment>
+ <comment xml:lang="sl">Dokument Microsoft Publisher</comment>
+ <comment xml:lang="si">Microsoft Publisher ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Microsoft Publisher</comment>
+ <comment xml:lang="ru">Документ Microsoft Publisher</comment>
+ <comment xml:lang="pt_BR">Documento do Microsoft Publisher</comment>
+ <comment xml:lang="pt">documento Microsoft Publisher</comment>
+ <comment xml:lang="pl">Dokument Microsoft Publisher</comment>
+ <comment xml:lang="oc">document Microsoft Publisher</comment>
+ <comment xml:lang="nl">Microsoft Publisher-document</comment>
+ <comment xml:lang="ko">Microsoft Publisher 문서</comment>
+ <comment xml:lang="kk">Microsoft Publisher құжаты</comment>
+ <comment xml:lang="ja">Microsoft Publisher ドキュメント</comment>
+ <comment xml:lang="it">Documento Microsoft Publisher</comment>
+ <comment xml:lang="is">Microsoft Publisher skjal</comment>
+ <comment xml:lang="id">Dokumen Microsoft Publisher</comment>
+ <comment xml:lang="ia">Documento Microsoft Publisher</comment>
+ <comment xml:lang="hu">Microsoft Publisher dokumentum</comment>
+ <comment xml:lang="hr">Microsoft Publisher dokument</comment>
+ <comment xml:lang="he">מסמך Microsoft Publisher</comment>
+ <comment xml:lang="gl">Documento de Microsoft Publisher</comment>
+ <comment xml:lang="ga">cáipéis Microsoft Publisher</comment>
+ <comment xml:lang="fur">document Microsoft Publisher</comment>
+ <comment xml:lang="fr">document Microsoft Publisher</comment>
+ <comment xml:lang="fi">Microsoft Publisher -asiakirja</comment>
+ <comment xml:lang="eu">Microsoft Publisher dokumentua</comment>
+ <comment xml:lang="es">documento de Microsoft Publisher</comment>
+ <comment xml:lang="en_GB">Microsoft Publisher document</comment>
+ <comment xml:lang="el">Έγγραφο Microsoft Publisher</comment>
+ <comment xml:lang="de">Microsoft-Publisher-Dokument</comment>
+ <comment xml:lang="da">Microsoft Publisher-dokument</comment>
+ <comment xml:lang="cs">dokument Microsoft Publisher</comment>
+ <comment xml:lang="ca">document de Microsoft Publisher</comment>
+ <comment xml:lang="bg">Документ — Microsoft Publisher</comment>
+ <comment xml:lang="be">дакумент Microsoft Publisher</comment>
+ <comment xml:lang="ast">Documentu de Microsoft Publisher</comment>
+ <comment xml:lang="ar">مستند ناشر مايكروسوفت</comment>
+ <comment xml:lang="af">Microsoft Publisher-dokument</comment>
<sub-class-of type="application/x-ole-storage"/>
<glob pattern="*.pub"/>
</mime-type>
<mime-type type="application/x-msi">
<comment>Windows Installer package</comment>
- <comment xml:lang="ar">حزمة مثبّت ويندوز</comment>
- <comment xml:lang="be@latin">Pakunak Windows Installer</comment>
- <comment xml:lang="bg">Пакет — инсталация за Windows</comment>
- <comment xml:lang="ca">paquet de Windows Installer</comment>
- <comment xml:lang="cs">balíček Windows Installer</comment>
- <comment xml:lang="da">Windows Installer-pakke</comment>
- <comment xml:lang="de">Windows-Installationspaket</comment>
- <comment xml:lang="el">Πακέτο Windows Installer</comment>
- <comment xml:lang="en_GB">Windows Installer package</comment>
- <comment xml:lang="es">paquete de instalación de Windows</comment>
- <comment xml:lang="eu">Windows-eko pakete instalatzailea</comment>
- <comment xml:lang="fi">Windows-asennuspaketti</comment>
- <comment xml:lang="fo">Windows innleggingarpakki</comment>
- <comment xml:lang="fr">paquet d'installation Windows</comment>
- <comment xml:lang="ga">pacáiste Windows Installer</comment>
- <comment xml:lang="gl">paquete de instalación de Windows</comment>
- <comment xml:lang="he">חבילה של Windows Installer</comment>
- <comment xml:lang="hr">Windows Instalacijski paket</comment>
- <comment xml:lang="hu">Windows Installer csomag</comment>
- <comment xml:lang="ia">Pacchetto Windows Installer</comment>
- <comment xml:lang="id">Paket Windows Installer</comment>
- <comment xml:lang="it">Pacchetto Windows Installer</comment>
- <comment xml:lang="ja">Windows インストーラパッケージ</comment>
- <comment xml:lang="kk">Windows Installer дестесі</comment>
- <comment xml:lang="ko">Windows 설치 패키지</comment>
- <comment xml:lang="lt">Windows Installer paketas</comment>
- <comment xml:lang="lv">Windows Installer pakotne</comment>
- <comment xml:lang="nl">Windows-installatiepakket</comment>
- <comment xml:lang="nn">Windows Installer-pakke</comment>
- <comment xml:lang="oc">paquet d'installacion Windows</comment>
- <comment xml:lang="pl">Pakiet instalatora Windows</comment>
- <comment xml:lang="pt">pacote de instalação Windows</comment>
- <comment xml:lang="pt_BR">Pacote do Windows Installer</comment>
- <comment xml:lang="ro">Pachet instalator Windows</comment>
- <comment xml:lang="ru">Пакет Windows Installer</comment>
- <comment xml:lang="sk">Balík Windows Installer</comment>
- <comment xml:lang="sl">Datoteka paketa Windows namestilnika</comment>
- <comment xml:lang="sq">Paketë Windows Installer</comment>
- <comment xml:lang="sr">пакет Виндоузовог инсталатера</comment>
- <comment xml:lang="sv">Windows Installer-paket</comment>
- <comment xml:lang="tr">Windows Installer paketi</comment>
- <comment xml:lang="uk">пакунок Windows Installer</comment>
- <comment xml:lang="vi">Gói cài đặt Windows</comment>
- <comment xml:lang="zh_CN">Windows 程序安装包</comment>
<comment xml:lang="zh_TW">Windows Installer 軟體包</comment>
+ <comment xml:lang="zh_CN">Windows 程序安装包</comment>
+ <comment xml:lang="vi">Gói cài đặt Windows</comment>
+ <comment xml:lang="uk">пакунок Windows Installer</comment>
+ <comment xml:lang="tr">Windows Installer paketi</comment>
+ <comment xml:lang="sv">Windows Installer-paket</comment>
+ <comment xml:lang="sr">пакет Виндоузовог инсталатера</comment>
+ <comment xml:lang="sq">paketë Windows Installer</comment>
+ <comment xml:lang="sl">Datoteka paketa Windows namestilnika</comment>
+ <comment xml:lang="si">වින්ඩෝස් ස්ථාපක පැකේජය</comment>
+ <comment xml:lang="sk">Balík Windows Installer</comment>
+ <comment xml:lang="ru">Пакет Windows Installer</comment>
+ <comment xml:lang="ro">Pachet instalator Windows</comment>
+ <comment xml:lang="pt_BR">Pacote do Windows Installer</comment>
+ <comment xml:lang="pt">pacote de instalação Windows</comment>
+ <comment xml:lang="pl">Pakiet instalatora Windows</comment>
+ <comment xml:lang="oc">paquet d'installacion Windows</comment>
+ <comment xml:lang="nn">Windows Installer-pakke</comment>
+ <comment xml:lang="nl">Windows-installatiepakket</comment>
+ <comment xml:lang="lv">Windows Installer pakotne</comment>
+ <comment xml:lang="lt">Windows Installer paketas</comment>
+ <comment xml:lang="ko">Windows 설치 패키지</comment>
+ <comment xml:lang="kk">Windows Installer дестесі</comment>
+ <comment xml:lang="ja">Windows インストーラパッケージ</comment>
+ <comment xml:lang="it">Pacchetto Windows Installer</comment>
+ <comment xml:lang="is">Windows uppsetningarpakki</comment>
+ <comment xml:lang="id">Paket Windows Installer</comment>
+ <comment xml:lang="ia">Pacchetto Windows Installer</comment>
+ <comment xml:lang="hu">Windows Installer csomag</comment>
+ <comment xml:lang="hr">Windows Instalacijski paket</comment>
+ <comment xml:lang="he">חבילה של Windows Installer</comment>
+ <comment xml:lang="gl">paquete de instalación de Windows</comment>
+ <comment xml:lang="ga">pacáiste Windows Installer</comment>
+ <comment xml:lang="fur">pachet Windows Installer</comment>
+ <comment xml:lang="fr">paquet d'installation Windows</comment>
+ <comment xml:lang="fo">Windows innleggingarpakki</comment>
+ <comment xml:lang="fi">Windows-asennuspaketti</comment>
+ <comment xml:lang="eu">Windows-eko pakete instalatzailea</comment>
+ <comment xml:lang="es">paquete de instalación de Windows</comment>
+ <comment xml:lang="en_GB">Windows Installer package</comment>
+ <comment xml:lang="el">Πακέτο Windows Installer</comment>
+ <comment xml:lang="de">Windows-Installationspaket</comment>
+ <comment xml:lang="da">Windows installationsprogram-pakke</comment>
+ <comment xml:lang="cs">balíček Windows Installer</comment>
+ <comment xml:lang="ca">paquet de Windows Installer</comment>
+ <comment xml:lang="bg">Пакет — инсталация за Windows</comment>
+ <comment xml:lang="be@latin">Pakunak Windows Installer</comment>
+ <comment xml:lang="be">пакет Windows Installer</comment>
+ <comment xml:lang="ar">حزمة مثبّت ويندوز</comment>
+ <comment xml:lang="af">Windows-installeerpakket</comment>
<sub-class-of type="application/x-ole-storage"/>
+ <generic-icon name="package-x-generic"/>
<glob pattern="*.msi"/>
</mime-type>
+ <mime-type type="application/appx">
+ <comment>Windows app store package</comment>
+ <comment xml:lang="uk">пакунок крамниці програм Windows</comment>
+ <comment xml:lang="sv">Windows app store-paket</comment>
+ <comment xml:lang="ru">Пакет магазина приложений Windows</comment>
+ <comment xml:lang="pl">Pakiet sklepu z aplikacjami Windows</comment>
+ <comment xml:lang="es">paquete de la tienda de aplicaciones de Windows</comment>
+ <comment xml:lang="de">Windows-Appstore-Paket</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="package-x-generic"/>
+ <glob pattern="*.appx"/>
+ </mime-type>
+ <mime-type type="application/msix">
+ <comment>Windows app store package</comment>
+ <comment xml:lang="uk">пакунок крамниці програм Windows</comment>
+ <comment xml:lang="sv">Windows app store-paket</comment>
+ <comment xml:lang="ru">Пакет магазина приложений Windows</comment>
+ <comment xml:lang="pl">Pakiet sklepu z aplikacjami Windows</comment>
+ <comment xml:lang="es">paquete de la tienda de aplicaciones de Windows</comment>
+ <comment xml:lang="de">Windows-Appstore-Paket</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="package-x-generic"/>
+ <glob pattern="*.msix"/>
+ </mime-type>
+ <mime-type type="application/appxbundle">
+ <comment>Windows app store bundle</comment>
+ <comment xml:lang="uk">комплект крамниці програм Windows</comment>
+ <comment xml:lang="sv">Windows app store-bunt</comment>
+ <comment xml:lang="ru">Объединённый пакет магазина приложений Windows</comment>
+ <comment xml:lang="pl">Paczka sklepu z aplikacjami Windows</comment>
+ <comment xml:lang="de">Zusammengefasste Windows-Appstore-Pakete</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="package-x-generic"/>
+ <glob pattern="*.appxbundle"/>
+ </mime-type>
+ <mime-type type="application/msixbundle">
+ <comment>Windows app store bundle</comment>
+ <comment xml:lang="uk">комплект крамниці програм Windows</comment>
+ <comment xml:lang="sv">Windows app store-bunt</comment>
+ <comment xml:lang="ru">Объединённый пакет магазина приложений Windows</comment>
+ <comment xml:lang="pl">Paczka sklepu z aplikacjami Windows</comment>
+ <comment xml:lang="de">Zusammengefasste Windows-Appstore-Pakete</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="package-x-generic"/>
+ <glob pattern="*.msixbundle"/>
+ </mime-type>
+ <mime-type type="application/appinstaller">
+ <comment>Windows app store installer</comment>
+ <comment xml:lang="uk">встановлювач крамниці програм Windows</comment>
+ <comment xml:lang="sv">Windows app store-installerare</comment>
+ <comment xml:lang="ru">Программа установки магазина приложений Windows</comment>
+ <comment xml:lang="pl">Instalator sklepu z aplikacjami Windows</comment>
+ <comment xml:lang="es">instalador de la tienda de aplicaciones de Windows</comment>
+ <comment xml:lang="de">Windows-Appstore-Installationsprogramm</comment>
+ <sub-class-of type="application/xml"/>
+ <generic-icon name="package-x-generic"/>
+ <magic>
+ <match type="string" value="&lt;AppInstaller" offset="0:256"/>
+ </magic>
+ <glob pattern="*.appinstaller"/>
+ </mime-type>
<mime-type type="application/x-oleo">
<comment>GNU Oleo spreadsheet</comment>
- <comment xml:lang="ar">جدول جنو Oleo</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš GNU Oleo</comment>
- <comment xml:lang="bg">Таблица — GNU Oleo</comment>
- <comment xml:lang="ca">full de càlcul de GNU Oleo</comment>
- <comment xml:lang="cs">sešit GNU Oleo</comment>
- <comment xml:lang="da">GNU Oleo-regneark</comment>
- <comment xml:lang="de">GNU-Oleo-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο GNU Oleo</comment>
- <comment xml:lang="en_GB">GNU Oleo spreadsheet</comment>
- <comment xml:lang="eo">Kalkultabelo de GNU Oleo</comment>
- <comment xml:lang="es">hoja de cálculo de GNU Oleo</comment>
- <comment xml:lang="eu">GNU Oleo kalkulu-orria</comment>
- <comment xml:lang="fi">GNU Oleo -taulukko</comment>
- <comment xml:lang="fo">GNU Oleo rokniark</comment>
- <comment xml:lang="fr">feuille de calcul GNU Oleo</comment>
- <comment xml:lang="ga">scarbhileog GNU Oleo</comment>
- <comment xml:lang="gl">folla de cálculo de Oleo GNU</comment>
- <comment xml:lang="he">גליון נתונים של GNU Oleo</comment>
- <comment xml:lang="hr">GNU Oleo proračunska tablica</comment>
- <comment xml:lang="hu">GNU Oleo-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo GNU Oleo</comment>
- <comment xml:lang="id">Lembar sebar GNU Oleo</comment>
- <comment xml:lang="it">Foglio di calcolo GNU Oleo</comment>
- <comment xml:lang="ja">GNU Oleo スプレッドシート</comment>
- <comment xml:lang="ka">GNU Oleo ცხრილი</comment>
- <comment xml:lang="kk">GNU Oleo электрондық кестесі</comment>
- <comment xml:lang="ko">GNU Oleo 스프레드시트</comment>
- <comment xml:lang="lt">GNU Oleo skaičialentė</comment>
- <comment xml:lang="lv">GNU Oleo izklājlapa</comment>
- <comment xml:lang="ms">Hamparan GNU Oleo</comment>
- <comment xml:lang="nb">GNU Oleo regneark</comment>
- <comment xml:lang="nl">GNU Oleo-rekenblad</comment>
- <comment xml:lang="nn">GNU Oleo-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul GNU Oleo</comment>
- <comment xml:lang="pl">Arkusz GNU Oleo</comment>
- <comment xml:lang="pt">folha de cálculo GNU Oleo</comment>
- <comment xml:lang="pt_BR">Planilha do GNU Oleo</comment>
- <comment xml:lang="ro">Foaie de calcul GNU Oleo</comment>
- <comment xml:lang="ru">Электронная таблица GNU Oleo</comment>
- <comment xml:lang="sk">Zošit GNU Oleo</comment>
- <comment xml:lang="sl">Preglednica GNU Oleo</comment>
- <comment xml:lang="sq">Fletë llogaritje GNU Oleo</comment>
- <comment xml:lang="sr">ГНУ Олео табела</comment>
- <comment xml:lang="sv">GNU Oleo-kalkylblad</comment>
- <comment xml:lang="tr">GNU Oleo çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця GNU Oleo</comment>
- <comment xml:lang="vi">Bảng tính Oleo của GNU</comment>
- <comment xml:lang="zh_CN">GNU Oleo 电子表格</comment>
<comment xml:lang="zh_TW">GNU Oleo 試算表</comment>
+ <comment xml:lang="zh_CN">GNU Oleo 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Oleo của GNU</comment>
+ <comment xml:lang="uk">електронна таблиця GNU Oleo</comment>
+ <comment xml:lang="tr">GNU Oleo hesap çizelgesi</comment>
+ <comment xml:lang="sv">GNU Oleo-kalkylblad</comment>
+ <comment xml:lang="sr">ГНУ Олео табела</comment>
+ <comment xml:lang="sq">fletëllogaritje GNU Oleo</comment>
+ <comment xml:lang="sl">Preglednica GNU Oleo</comment>
+ <comment xml:lang="si">GNU Oleo පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit GNU Oleo</comment>
+ <comment xml:lang="ru">Электронная таблица GNU Oleo</comment>
+ <comment xml:lang="ro">Foaie de calcul GNU Oleo</comment>
+ <comment xml:lang="pt_BR">Planilha do GNU Oleo</comment>
+ <comment xml:lang="pt">folha de cálculo GNU Oleo</comment>
+ <comment xml:lang="pl">Arkusz GNU Oleo</comment>
+ <comment xml:lang="oc">fuèlh de calcul GNU Oleo</comment>
+ <comment xml:lang="nn">GNU Oleo-rekneark</comment>
+ <comment xml:lang="nl">GNU Oleo-rekenblad</comment>
+ <comment xml:lang="nb">GNU Oleo regneark</comment>
+ <comment xml:lang="ms">Hamparan GNU Oleo</comment>
+ <comment xml:lang="lv">GNU Oleo izklājlapa</comment>
+ <comment xml:lang="lt">GNU Oleo skaičialentė</comment>
+ <comment xml:lang="ko">GNU Oleo 스프레드시트</comment>
+ <comment xml:lang="kk">GNU Oleo электрондық кестесі</comment>
+ <comment xml:lang="ka">GNU Oleo ცხრილი</comment>
+ <comment xml:lang="ja">GNU Oleo スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo GNU Oleo</comment>
+ <comment xml:lang="is">GNU Oleo töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar GNU Oleo</comment>
+ <comment xml:lang="ia">Folio de calculo GNU Oleo</comment>
+ <comment xml:lang="hu">GNU Oleo-munkafüzet</comment>
+ <comment xml:lang="hr">GNU Oleo proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של GNU Oleo</comment>
+ <comment xml:lang="gl">folla de cálculo de Oleo GNU</comment>
+ <comment xml:lang="ga">scarbhileog GNU Oleo</comment>
+ <comment xml:lang="fur">sfuei di calcul GNU Oleo</comment>
+ <comment xml:lang="fr">feuille de calcul GNU Oleo</comment>
+ <comment xml:lang="fo">GNU Oleo rokniark</comment>
+ <comment xml:lang="fi">GNU Oleo -taulukko</comment>
+ <comment xml:lang="eu">GNU Oleo kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de GNU Oleo</comment>
+ <comment xml:lang="eo">Kalkultabelo de GNU Oleo</comment>
+ <comment xml:lang="en_GB">GNU Oleo spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο GNU Oleo</comment>
+ <comment xml:lang="de">GNU-Oleo-Tabelle</comment>
+ <comment xml:lang="da">GNU Oleo-regneark</comment>
+ <comment xml:lang="cs">sešit GNU Oleo</comment>
+ <comment xml:lang="ca">full de càlcul de GNU Oleo</comment>
+ <comment xml:lang="bg">Таблица — GNU Oleo</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš GNU Oleo</comment>
+ <comment xml:lang="be">электронная табліца GNU Oleo</comment>
+ <comment xml:lang="ar">جدول جنو Oleo</comment>
+ <comment xml:lang="af">GNU Oleo-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="Oleo" type="string" offset="31"/>
+ <magic>
+ <match type="string" value="Oleo" offset="31"/>
</magic>
<glob pattern="*.oleo"/>
</mime-type>
<mime-type type="application/x-pak">
<comment>PAK archive</comment>
- <comment xml:lang="ar">أرشيف PAK</comment>
- <comment xml:lang="be@latin">Archiŭ PAK</comment>
- <comment xml:lang="bg">Архив — PAK</comment>
- <comment xml:lang="ca">arxiu PAK</comment>
- <comment xml:lang="cs">archiv PAK</comment>
- <comment xml:lang="da">PAK-arkiv</comment>
- <comment xml:lang="de">PAK-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο PAK</comment>
- <comment xml:lang="en_GB">PAK archive</comment>
- <comment xml:lang="eo">PAK-arkivo</comment>
- <comment xml:lang="es">archivador PAK</comment>
- <comment xml:lang="eu">PAK artxiboa</comment>
- <comment xml:lang="fi">PAK-arkisto</comment>
- <comment xml:lang="fo">PAK skjalasavn</comment>
- <comment xml:lang="fr">archive PAK</comment>
- <comment xml:lang="ga">cartlann PAK</comment>
- <comment xml:lang="gl">arquivo PAK</comment>
- <comment xml:lang="he">ארכיון PAK</comment>
- <comment xml:lang="hr">PAK arhiva</comment>
- <comment xml:lang="hu">PAK-archívum</comment>
- <comment xml:lang="ia">Archivo PAK</comment>
- <comment xml:lang="id">Arsip PAK</comment>
- <comment xml:lang="it">Archivio PAK</comment>
- <comment xml:lang="ja">PAK アーカイブ</comment>
- <comment xml:lang="ka">PAK არქივი</comment>
- <comment xml:lang="kk">PAK архиві</comment>
- <comment xml:lang="ko">PAK 압축 파일</comment>
- <comment xml:lang="lt">PAK archyvas</comment>
- <comment xml:lang="lv">PAK arhīvs</comment>
- <comment xml:lang="nb">PAK-arkiv</comment>
- <comment xml:lang="nl">PAK-archief</comment>
- <comment xml:lang="nn">PAK-arkiv</comment>
- <comment xml:lang="oc">archiu PAK</comment>
- <comment xml:lang="pl">Archiwum PAK</comment>
- <comment xml:lang="pt">arquivo PAK</comment>
- <comment xml:lang="pt_BR">Pacote PAK</comment>
- <comment xml:lang="ro">Arhivă PAK</comment>
- <comment xml:lang="ru">Архив PAK</comment>
- <comment xml:lang="sk">Archív PAK</comment>
- <comment xml:lang="sl">Datoteka arhiva PAK</comment>
- <comment xml:lang="sq">Arkiv PAK</comment>
- <comment xml:lang="sr">ПАК архива</comment>
- <comment xml:lang="sv">PAK-arkiv</comment>
- <comment xml:lang="tr">PAK arşivi</comment>
- <comment xml:lang="uk">архів PAK</comment>
- <comment xml:lang="vi">Kho nén PAK</comment>
- <comment xml:lang="zh_CN">PAK 归档文件</comment>
<comment xml:lang="zh_TW">PAK 封存檔</comment>
+ <comment xml:lang="zh_CN">PAK 归档文件</comment>
+ <comment xml:lang="vi">Kho nén PAK</comment>
+ <comment xml:lang="uk">архів PAK</comment>
+ <comment xml:lang="tr">PAK arşivi</comment>
+ <comment xml:lang="sv">PAK-arkiv</comment>
+ <comment xml:lang="sr">ПАК архива</comment>
+ <comment xml:lang="sq">arkiv PAK</comment>
+ <comment xml:lang="sl">Datoteka arhiva PAK</comment>
+ <comment xml:lang="si">PAK ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív PAK</comment>
+ <comment xml:lang="ru">Архив PAK</comment>
+ <comment xml:lang="ro">Arhivă PAK</comment>
+ <comment xml:lang="pt_BR">Pacote PAK</comment>
+ <comment xml:lang="pt">arquivo PAK</comment>
+ <comment xml:lang="pl">Archiwum PAK</comment>
+ <comment xml:lang="oc">archiu PAK</comment>
+ <comment xml:lang="nn">PAK-arkiv</comment>
+ <comment xml:lang="nl">PAK-archief</comment>
+ <comment xml:lang="nb">PAK-arkiv</comment>
+ <comment xml:lang="lv">PAK arhīvs</comment>
+ <comment xml:lang="lt">PAK archyvas</comment>
+ <comment xml:lang="ko">PAK 압축 파일</comment>
+ <comment xml:lang="kk">PAK архиві</comment>
+ <comment xml:lang="ka">PAK არქივი</comment>
+ <comment xml:lang="ja">PAK アーカイブ</comment>
+ <comment xml:lang="it">Archivio PAK</comment>
+ <comment xml:lang="is">PAK safnskrá</comment>
+ <comment xml:lang="id">Arsip PAK</comment>
+ <comment xml:lang="ia">Archivo PAK</comment>
+ <comment xml:lang="hu">PAK-archívum</comment>
+ <comment xml:lang="hr">PAK arhiva</comment>
+ <comment xml:lang="he">ארכיון PAK</comment>
+ <comment xml:lang="gl">arquivo PAK</comment>
+ <comment xml:lang="ga">cartlann PAK</comment>
+ <comment xml:lang="fur">archivi PAK</comment>
+ <comment xml:lang="fr">archive PAK</comment>
+ <comment xml:lang="fo">PAK skjalasavn</comment>
+ <comment xml:lang="fi">PAK-arkisto</comment>
+ <comment xml:lang="eu">PAK artxiboa</comment>
+ <comment xml:lang="es">archivador PAK</comment>
+ <comment xml:lang="eo">PAK-arkivo</comment>
+ <comment xml:lang="en_GB">PAK archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο PAK</comment>
+ <comment xml:lang="de">PAK-Archiv</comment>
+ <comment xml:lang="da">PAK-arkiv</comment>
+ <comment xml:lang="cs">archiv PAK</comment>
+ <comment xml:lang="ca">arxiu PAK</comment>
+ <comment xml:lang="bg">Архив — PAK</comment>
+ <comment xml:lang="be@latin">Archiŭ PAK</comment>
+ <comment xml:lang="be">архіў PAK</comment>
+ <comment xml:lang="ar">أرشيف PAK</comment>
+ <comment xml:lang="af">PAK-argief</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="80">
- <match value="PACK" type="string" offset="0"/>
- </magic>
<glob pattern="*.pak"/>
</mime-type>
<mime-type type="application/vnd.palm">
<comment>Palm OS database</comment>
- <comment xml:lang="ar">قاعدة بيانات Palm OS</comment>
- <comment xml:lang="az">Palm OS mə'lumat bazası</comment>
- <comment xml:lang="be@latin">Baza źviestak Palm OS</comment>
- <comment xml:lang="bg">База от данни — Palm OS</comment>
- <comment xml:lang="ca">base de dades Palm OS</comment>
- <comment xml:lang="cs">databáze Palm OS</comment>
- <comment xml:lang="cy">Cronfa Ddata Palm OS</comment>
- <comment xml:lang="da">Palm OS-database</comment>
- <comment xml:lang="de">Palm-OS-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων Palm OS</comment>
- <comment xml:lang="en_GB">Palm OS database</comment>
- <comment xml:lang="eo">datumbazo de Palm OS</comment>
- <comment xml:lang="es">base de datos de Palm OS</comment>
- <comment xml:lang="eu">Palm OS datu-basea</comment>
- <comment xml:lang="fi">Palm OS -tietokanta</comment>
- <comment xml:lang="fo">Palm OS dátustovnur</comment>
- <comment xml:lang="fr">base de données Palm OS</comment>
- <comment xml:lang="ga">bunachar sonraí Palm OS</comment>
- <comment xml:lang="gl">base de datos de Palm OS</comment>
- <comment xml:lang="he">מסד נתונים של Palm OS</comment>
- <comment xml:lang="hr">Palm OS baza podataka</comment>
- <comment xml:lang="hu">Palm OS-adatbázis</comment>
- <comment xml:lang="ia">Base de datos Palm OS</comment>
- <comment xml:lang="id">Basis data Palm OS</comment>
- <comment xml:lang="it">Database Palm OS</comment>
- <comment xml:lang="ja">Palm OS データベース</comment>
- <comment xml:lang="kk">Palm OS дерекқоры</comment>
- <comment xml:lang="ko">Palm OS 데이터베이스</comment>
- <comment xml:lang="lt">Palm OS duomenų bazė</comment>
- <comment xml:lang="lv">Palm OS datubāze</comment>
- <comment xml:lang="ms">Pangkalandata PalmOS</comment>
- <comment xml:lang="nb">Palm OS-database</comment>
- <comment xml:lang="nl">Palm OS-gegevensbank</comment>
- <comment xml:lang="nn">Palm OS-database</comment>
- <comment xml:lang="oc">banca de donadas Palm OS</comment>
- <comment xml:lang="pl">Baza danych Palm OS</comment>
- <comment xml:lang="pt">base de dados Palm OS</comment>
- <comment xml:lang="pt_BR">Banco de dados do Palm OS</comment>
- <comment xml:lang="ro">Bază de date Palm OS</comment>
- <comment xml:lang="ru">База данных Palm OS</comment>
- <comment xml:lang="sk">Databáza Palm OS</comment>
- <comment xml:lang="sl">Podatkovna zbirka Palm OS</comment>
- <comment xml:lang="sq">Bankë me të dhëna Palm OS</comment>
- <comment xml:lang="sr">база података Палм ОС-а</comment>
- <comment xml:lang="sv">Palm OS-databas</comment>
- <comment xml:lang="tr">Palm OS veritabanı</comment>
- <comment xml:lang="uk">база даних Palm OS</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu PalmOS</comment>
- <comment xml:lang="zh_CN">Palm OS 数据库</comment>
<comment xml:lang="zh_TW">Palm OS 資料庫</comment>
+ <comment xml:lang="zh_CN">Palm OS 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu PalmOS</comment>
+ <comment xml:lang="uk">база даних Palm OS</comment>
+ <comment xml:lang="tr">Palm OS veri tabanı</comment>
+ <comment xml:lang="sv">Palm OS-databas</comment>
+ <comment xml:lang="sr">база података Палм ОС-а</comment>
+ <comment xml:lang="sq">bazë të dhënash Palm OS</comment>
+ <comment xml:lang="sl">Podatkovna zbirka Palm OS</comment>
+ <comment xml:lang="si">Palm OS දත්ත ගබඩාව</comment>
+ <comment xml:lang="sk">Databáza Palm OS</comment>
+ <comment xml:lang="ru">База данных Palm OS</comment>
+ <comment xml:lang="ro">Bază de date Palm OS</comment>
+ <comment xml:lang="pt_BR">Banco de dados do Palm OS</comment>
+ <comment xml:lang="pt">base de dados Palm OS</comment>
+ <comment xml:lang="pl">Baza danych Palm OS</comment>
+ <comment xml:lang="oc">banca de donadas Palm OS</comment>
+ <comment xml:lang="nn">Palm OS-database</comment>
+ <comment xml:lang="nl">Palm OS-database</comment>
+ <comment xml:lang="nb">Palm OS-database</comment>
+ <comment xml:lang="ms">Pangkalandata PalmOS</comment>
+ <comment xml:lang="lv">Palm OS datubāze</comment>
+ <comment xml:lang="lt">Palm OS duomenų bazė</comment>
+ <comment xml:lang="ko">Palm OS 데이터베이스</comment>
+ <comment xml:lang="kk">Palm OS дерекқоры</comment>
+ <comment xml:lang="ja">Palm OS データベース</comment>
+ <comment xml:lang="it">Database Palm OS</comment>
+ <comment xml:lang="is">Palm OS gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data Palm OS</comment>
+ <comment xml:lang="ia">Base de datos Palm OS</comment>
+ <comment xml:lang="hu">Palm OS-adatbázis</comment>
+ <comment xml:lang="hr">Palm OS baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים של Palm OS</comment>
+ <comment xml:lang="gl">base de datos de Palm OS</comment>
+ <comment xml:lang="ga">bunachar sonraí Palm OS</comment>
+ <comment xml:lang="fur">base di dâts Palm OS</comment>
+ <comment xml:lang="fr">base de données Palm OS</comment>
+ <comment xml:lang="fo">Palm OS dátustovnur</comment>
+ <comment xml:lang="fi">Palm OS -tietokanta</comment>
+ <comment xml:lang="eu">Palm OS datu-basea</comment>
+ <comment xml:lang="es">base de datos de Palm OS</comment>
+ <comment xml:lang="eo">datumbazo de Palm OS</comment>
+ <comment xml:lang="en_GB">Palm OS database</comment>
+ <comment xml:lang="el">Βάση δεδομένων Palm OS</comment>
+ <comment xml:lang="de">Palm-OS-Datenbank</comment>
+ <comment xml:lang="da">Palm OS-database</comment>
+ <comment xml:lang="cy">Cronfa Ddata Palm OS</comment>
+ <comment xml:lang="cs">databáze Palm OS</comment>
+ <comment xml:lang="ca">base de dades Palm OS</comment>
+ <comment xml:lang="bg">База от данни — Palm OS</comment>
+ <comment xml:lang="be@latin">Baza źviestak Palm OS</comment>
+ <comment xml:lang="be">база даных Palm OS</comment>
+ <comment xml:lang="az">Palm OS mə'lumat bazası</comment>
+ <comment xml:lang="ar">قاعدة بيانات Palm OS</comment>
+ <comment xml:lang="af">Palm OS-databasis</comment>
<glob pattern="*.prc"/>
- <glob pattern="*.pdb"/>
+ <glob pattern="*.pdb" weight="40"/>
<glob pattern="*.pqa"/>
<glob pattern="*.oprc"/>
<alias type="application/x-palm-database"/>
</mime-type>
<mime-type type="application/x-par2">
<comment>Parchive archive</comment>
- <comment xml:lang="ar">أرشيف Parchive</comment>
- <comment xml:lang="be@latin">Archiŭ Parchive</comment>
- <comment xml:lang="bg">Архив — parchive</comment>
- <comment xml:lang="ca">arxiu Parchive</comment>
- <comment xml:lang="cs">archiv Parchive</comment>
- <comment xml:lang="da">Parchive-arkiv</comment>
- <comment xml:lang="de">Parchive-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Parchive</comment>
- <comment xml:lang="en_GB">Parchive archive</comment>
- <comment xml:lang="es">archivador Parchive</comment>
- <comment xml:lang="eu">Parchive artxiboa</comment>
- <comment xml:lang="fi">Parchive-arkisto</comment>
- <comment xml:lang="fo">Parchive skjalasavn</comment>
- <comment xml:lang="fr">archive Parchive</comment>
- <comment xml:lang="ga">cartlann Parchive</comment>
- <comment xml:lang="gl">arquivo Parchive</comment>
- <comment xml:lang="he">ארכיון של Parchive</comment>
- <comment xml:lang="hr">Parchive arhiva</comment>
- <comment xml:lang="hu">Parchive archívum</comment>
- <comment xml:lang="ia">Archivo Parchive</comment>
- <comment xml:lang="id">Arsip Parchive</comment>
- <comment xml:lang="it">Archivio Parchive</comment>
- <comment xml:lang="ja">Parchive アーカイブ</comment>
- <comment xml:lang="kk">Parchive архиві</comment>
- <comment xml:lang="ko">Parchive 압축 파일</comment>
- <comment xml:lang="lt">Parchive archyvas</comment>
- <comment xml:lang="lv">Parchive arhīvs</comment>
- <comment xml:lang="nb">Parchive-arkiv</comment>
- <comment xml:lang="nl">Parchive-archief</comment>
- <comment xml:lang="nn">Parchive-arkiv</comment>
- <comment xml:lang="oc">archiu Parchive</comment>
- <comment xml:lang="pl">Archiwum parchive</comment>
- <comment xml:lang="pt">arquivo Parchive</comment>
- <comment xml:lang="pt_BR">Pacote Parchive</comment>
- <comment xml:lang="ro">Arhivă Parchive</comment>
- <comment xml:lang="ru">Архив Parchive</comment>
- <comment xml:lang="sk">Archív Parchive</comment>
- <comment xml:lang="sl">Datoteka arhiva Parchive</comment>
- <comment xml:lang="sq">Arkiv Parchive</comment>
- <comment xml:lang="sr">архива Пархива</comment>
- <comment xml:lang="sv">Parchive-arkiv</comment>
- <comment xml:lang="tr">Parchive arşivi</comment>
- <comment xml:lang="uk">архів Parchive</comment>
- <comment xml:lang="vi">Kho nén Parchive</comment>
- <comment xml:lang="zh_CN">Parchive 归档文件</comment>
<comment xml:lang="zh_TW">Parchive 封存檔</comment>
+ <comment xml:lang="zh_CN">Parchive 归档文件</comment>
+ <comment xml:lang="vi">Kho nén Parchive</comment>
+ <comment xml:lang="uk">архів Parchive</comment>
+ <comment xml:lang="tr">Parchive arşivi</comment>
+ <comment xml:lang="sv">Parchive-arkiv</comment>
+ <comment xml:lang="sr">архива Пархива</comment>
+ <comment xml:lang="sq">arkiv Parchive</comment>
+ <comment xml:lang="sl">Datoteka arhiva Parchive</comment>
+ <comment xml:lang="si">Parchive ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Parchive</comment>
+ <comment xml:lang="ru">Архив Parchive</comment>
+ <comment xml:lang="ro">Arhivă Parchive</comment>
+ <comment xml:lang="pt_BR">Pacote Parchive</comment>
+ <comment xml:lang="pt">arquivo Parchive</comment>
+ <comment xml:lang="pl">Archiwum parchive</comment>
+ <comment xml:lang="oc">archiu Parchive</comment>
+ <comment xml:lang="nn">Parchive-arkiv</comment>
+ <comment xml:lang="nl">Parchive-archief</comment>
+ <comment xml:lang="nb">Parchive-arkiv</comment>
+ <comment xml:lang="lv">Parchive arhīvs</comment>
+ <comment xml:lang="lt">Parchive archyvas</comment>
+ <comment xml:lang="ko">Parchive 압축 파일</comment>
+ <comment xml:lang="kk">Parchive архиві</comment>
+ <comment xml:lang="ja">Parchive アーカイブ</comment>
+ <comment xml:lang="it">Archivio Parchive</comment>
+ <comment xml:lang="is">Parchive safnskrá</comment>
+ <comment xml:lang="id">Arsip Parchive</comment>
+ <comment xml:lang="ia">Archivo Parchive</comment>
+ <comment xml:lang="hu">Parchive archívum</comment>
+ <comment xml:lang="hr">Parchive arhiva</comment>
+ <comment xml:lang="he">ארכיון של Parchive</comment>
+ <comment xml:lang="gl">arquivo Parchive</comment>
+ <comment xml:lang="ga">cartlann Parchive</comment>
+ <comment xml:lang="fur">archivi Parchive</comment>
+ <comment xml:lang="fr">archive Parchive</comment>
+ <comment xml:lang="fo">Parchive skjalasavn</comment>
+ <comment xml:lang="fi">Parchive-arkisto</comment>
+ <comment xml:lang="eu">Parchive artxiboa</comment>
+ <comment xml:lang="es">archivador Parchive</comment>
+ <comment xml:lang="en_GB">Parchive archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Parchive</comment>
+ <comment xml:lang="de">Parchive-Archiv</comment>
+ <comment xml:lang="da">Parchive-arkiv</comment>
+ <comment xml:lang="cs">archiv Parchive</comment>
+ <comment xml:lang="ca">arxiu Parchive</comment>
+ <comment xml:lang="bg">Архив — parchive</comment>
+ <comment xml:lang="be@latin">Archiŭ Parchive</comment>
+ <comment xml:lang="be">архіў Parchive</comment>
+ <comment xml:lang="ar">أرشيف Parchive</comment>
+ <comment xml:lang="af">Parchive-argief</comment>
<acronym>Parchive</acronym>
<expanded-acronym>Parity Volume Set Archive</expanded-acronym>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="PAR2" type="string" offset="0"/>
+ <match offset="0" type="string" value="PAR2"/>
</magic>
<glob pattern="*.PAR2"/>
<glob pattern="*.par2"/>
</mime-type>
<mime-type type="application/x-pef-executable">
<comment>PEF executable</comment>
- <comment xml:lang="ar">PEF تنفيذي</comment>
- <comment xml:lang="be@latin">Vykonvalny fajł PEF</comment>
- <comment xml:lang="bg">Изпълним файл — PEF</comment>
- <comment xml:lang="ca">executable PEF</comment>
- <comment xml:lang="cs">spustitelný soubor PEF</comment>
- <comment xml:lang="da">PEF-kørbar</comment>
- <comment xml:lang="de">PEF-Programm</comment>
- <comment xml:lang="el">Εκτελέσιμο PEF</comment>
- <comment xml:lang="en_GB">PEF executable</comment>
- <comment xml:lang="eo">PEF-plenumebla</comment>
- <comment xml:lang="es">ejecutable PEF</comment>
- <comment xml:lang="eu">PEF exekutagarria</comment>
- <comment xml:lang="fi">PEF-ohjelma</comment>
- <comment xml:lang="fo">PEF inningarfør</comment>
- <comment xml:lang="fr">exécutable PEF</comment>
- <comment xml:lang="ga">comhad inrite PEF</comment>
- <comment xml:lang="gl">Executábel PEF</comment>
- <comment xml:lang="he">קובץ הרצה PEF</comment>
- <comment xml:lang="hr">PEF izvršna datoteka</comment>
- <comment xml:lang="hu">PEF futtatható</comment>
- <comment xml:lang="ia">Executabile PEF</comment>
- <comment xml:lang="id">PEF dapat dieksekusi</comment>
- <comment xml:lang="it">Eseguibile PEF</comment>
- <comment xml:lang="ja">PEF 実行ファイル</comment>
- <comment xml:lang="kk">PEF орындалатын файлы</comment>
- <comment xml:lang="ko">PEF 실행 파일</comment>
- <comment xml:lang="lt">PEF vykdomasis failas</comment>
- <comment xml:lang="lv">PEF izpildāmais</comment>
- <comment xml:lang="ms">Bolehlaksana PEF</comment>
- <comment xml:lang="nb">PEF-kjørbar</comment>
- <comment xml:lang="nl">PEF-uitvoerbaar bestand</comment>
- <comment xml:lang="nn">Køyrbar PEF-fil</comment>
- <comment xml:lang="oc">executable PEF</comment>
- <comment xml:lang="pl">Program PEF</comment>
- <comment xml:lang="pt">executável PEF</comment>
- <comment xml:lang="pt_BR">Executável PEF</comment>
- <comment xml:lang="ro">Executabil PEF</comment>
- <comment xml:lang="ru">Исполняемый файл PEF</comment>
- <comment xml:lang="sk">Spustiteľný súbor PEF</comment>
- <comment xml:lang="sl">Izvedljiva datoteka PEF</comment>
- <comment xml:lang="sq">E ekzekutueshme PEF</comment>
- <comment xml:lang="sr">ПЕФ извршна</comment>
- <comment xml:lang="sv">Körbar PEF-fil</comment>
- <comment xml:lang="tr">PEF çalıştırılabilir</comment>
- <comment xml:lang="uk">виконуваний файл PEF</comment>
- <comment xml:lang="vi">Tập tin thực hiện được PEF</comment>
- <comment xml:lang="zh_CN">PEF 可执行文件</comment>
<comment xml:lang="zh_TW">PEF 可執行檔</comment>
+ <comment xml:lang="zh_CN">PEF 可执行文件</comment>
+ <comment xml:lang="vi">Tập tin thực hiện được PEF</comment>
+ <comment xml:lang="uk">виконуваний файл PEF</comment>
+ <comment xml:lang="tr">PEF çalıştırılabilir</comment>
+ <comment xml:lang="sv">Körbar PEF-fil</comment>
+ <comment xml:lang="sr">ПЕФ извршна</comment>
+ <comment xml:lang="sq">e ekzekutueshme PEF</comment>
+ <comment xml:lang="sl">Izvedljiva datoteka PEF</comment>
+ <comment xml:lang="si">PEF ක්‍රියාත්මක කළ හැකිය</comment>
+ <comment xml:lang="sk">Spustiteľný súbor PEF</comment>
+ <comment xml:lang="ru">Исполняемый файл PEF</comment>
+ <comment xml:lang="ro">Executabil PEF</comment>
+ <comment xml:lang="pt_BR">Executável PEF</comment>
+ <comment xml:lang="pt">executável PEF</comment>
+ <comment xml:lang="pl">Program PEF</comment>
+ <comment xml:lang="oc">executable PEF</comment>
+ <comment xml:lang="nn">Køyrbar PEF-fil</comment>
+ <comment xml:lang="nl">PEF-programmabestand</comment>
+ <comment xml:lang="nb">PEF-kjørbar</comment>
+ <comment xml:lang="ms">Bolehlaksana PEF</comment>
+ <comment xml:lang="lv">PEF izpildāmais</comment>
+ <comment xml:lang="lt">PEF vykdomasis failas</comment>
+ <comment xml:lang="ko">PEF 실행 파일</comment>
+ <comment xml:lang="kk">PEF орындалатын файлы</comment>
+ <comment xml:lang="ja">PEF 実行ファイル</comment>
+ <comment xml:lang="it">Eseguibile PEF</comment>
+ <comment xml:lang="is">PEF keyrsluskrá</comment>
+ <comment xml:lang="id">PEF dapat dieksekusi</comment>
+ <comment xml:lang="ia">Executabile PEF</comment>
+ <comment xml:lang="hu">PEF futtatható</comment>
+ <comment xml:lang="hr">PEF izvršna datoteka</comment>
+ <comment xml:lang="he">קובץ הרצה PEF</comment>
+ <comment xml:lang="gl">Executábel PEF</comment>
+ <comment xml:lang="ga">comhad inrite PEF</comment>
+ <comment xml:lang="fur">eseguibil PEF</comment>
+ <comment xml:lang="fr">exécutable PEF</comment>
+ <comment xml:lang="fo">PEF inningarfør</comment>
+ <comment xml:lang="fi">PEF-ohjelma</comment>
+ <comment xml:lang="eu">PEF exekutagarria</comment>
+ <comment xml:lang="es">ejecutable PEF</comment>
+ <comment xml:lang="eo">PEF-plenumebla</comment>
+ <comment xml:lang="en_GB">PEF executable</comment>
+ <comment xml:lang="el">Εκτελέσιμο PEF</comment>
+ <comment xml:lang="de">PEF-Programm</comment>
+ <comment xml:lang="da">PEF-kørbar</comment>
+ <comment xml:lang="cs">spustitelný soubor PEF</comment>
+ <comment xml:lang="ca">executable PEF</comment>
+ <comment xml:lang="bg">Изпълним файл — PEF</comment>
+ <comment xml:lang="be@latin">Vykonvalny fajł PEF</comment>
+ <comment xml:lang="be">выконвальны файл PEF</comment>
+ <comment xml:lang="ar">PEF تنفيذي</comment>
+ <comment xml:lang="af">PEF-uitvoerbaar</comment>
+ <acronym>PEF</acronym>
+ <expanded-acronym>Preferred Executable Format</expanded-acronym>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
- <match value="Joy!" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="Joy!" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-perl">
<comment>Perl script</comment>
- <comment xml:lang="ar">سكربت بيرل</comment>
- <comment xml:lang="be@latin">Skrypt Perl</comment>
- <comment xml:lang="bg">Скрипт — Perl</comment>
- <comment xml:lang="ca">script Perl</comment>
- <comment xml:lang="cs">skript v Perlu</comment>
- <comment xml:lang="cy">Sgript Perl</comment>
- <comment xml:lang="da">Perlprogram</comment>
- <comment xml:lang="de">Perl-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών Perl</comment>
- <comment xml:lang="en_GB">Perl script</comment>
- <comment xml:lang="eo">Perl-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en Perl</comment>
- <comment xml:lang="eu">Perl script-a</comment>
- <comment xml:lang="fi">Perl-komentotiedosto</comment>
- <comment xml:lang="fo">Perl boðrøð</comment>
- <comment xml:lang="fr">script Perl</comment>
- <comment xml:lang="ga">script Perl</comment>
- <comment xml:lang="gl">Script de Perl</comment>
- <comment xml:lang="he">תסריט מעטפת של Perl</comment>
- <comment xml:lang="hr">Perl skripta</comment>
- <comment xml:lang="hu">Perl-parancsfájl</comment>
- <comment xml:lang="ia">Script Perl</comment>
- <comment xml:lang="id">Skrip Perl</comment>
- <comment xml:lang="it">Script Perl</comment>
- <comment xml:lang="ja">Perl スクリプト</comment>
- <comment xml:lang="kk">Perl сценарийі</comment>
- <comment xml:lang="ko">펄 스크립트</comment>
- <comment xml:lang="lt">Perl scenarijus</comment>
- <comment xml:lang="lv">Perl skripts</comment>
- <comment xml:lang="ms">Skrip Perl</comment>
- <comment xml:lang="nb">Perl skript</comment>
- <comment xml:lang="nl">Perl-script</comment>
- <comment xml:lang="nn">Perl-skript</comment>
- <comment xml:lang="oc">escript Perl</comment>
- <comment xml:lang="pl">Skrypt Perl</comment>
- <comment xml:lang="pt">script Perl</comment>
- <comment xml:lang="pt_BR">Script Perl</comment>
- <comment xml:lang="ro">Script Perl</comment>
- <comment xml:lang="ru">Сценарий Perl</comment>
- <comment xml:lang="sk">Skript jazyka Perl</comment>
- <comment xml:lang="sl">Skriptna datoteka Perl</comment>
- <comment xml:lang="sq">Script Perl</comment>
- <comment xml:lang="sr">Перл скрипта</comment>
- <comment xml:lang="sv">Perlskript</comment>
- <comment xml:lang="tr">Perl betiği</comment>
- <comment xml:lang="uk">скрипт на Perl</comment>
- <comment xml:lang="vi">Văn lệnh Perl</comment>
- <comment xml:lang="zh_CN">Perl 脚本</comment>
<comment xml:lang="zh_TW">Perl 指令稿</comment>
+ <comment xml:lang="zh_CN">Perl 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh Perl</comment>
+ <comment xml:lang="uk">скрипт на Perl</comment>
+ <comment xml:lang="tr">Perl betiği</comment>
+ <comment xml:lang="sv">Perlskript</comment>
+ <comment xml:lang="sr">Перл скрипта</comment>
+ <comment xml:lang="sq">programth Perl</comment>
+ <comment xml:lang="sl">Skriptna datoteka Perl</comment>
+ <comment xml:lang="si">පර්ල් පිටපත</comment>
+ <comment xml:lang="sk">Skript jazyka Perl</comment>
+ <comment xml:lang="ru">Сценарий Perl</comment>
+ <comment xml:lang="ro">Script Perl</comment>
+ <comment xml:lang="pt_BR">Script Perl</comment>
+ <comment xml:lang="pt">script Perl</comment>
+ <comment xml:lang="pl">Skrypt Perl</comment>
+ <comment xml:lang="oc">escript Perl</comment>
+ <comment xml:lang="nn">Perl-skript</comment>
+ <comment xml:lang="nl">Perl-script</comment>
+ <comment xml:lang="nb">Perl skript</comment>
+ <comment xml:lang="ms">Skrip Perl</comment>
+ <comment xml:lang="lv">Perl skripts</comment>
+ <comment xml:lang="lt">Perl scenarijus</comment>
+ <comment xml:lang="ko">펄 스크립트</comment>
+ <comment xml:lang="kk">Perl сценарийі</comment>
+ <comment xml:lang="ja">Perl スクリプト</comment>
+ <comment xml:lang="it">Script Perl</comment>
+ <comment xml:lang="is">Perl skrifta</comment>
+ <comment xml:lang="id">Skrip Perl</comment>
+ <comment xml:lang="ia">Script Perl</comment>
+ <comment xml:lang="hu">Perl-parancsfájl</comment>
+ <comment xml:lang="hr">Perl skripta</comment>
+ <comment xml:lang="he">תסריט מעטפת של Perl</comment>
+ <comment xml:lang="gl">Script de Perl</comment>
+ <comment xml:lang="ga">script Perl</comment>
+ <comment xml:lang="fur">script Perl</comment>
+ <comment xml:lang="fr">script Perl</comment>
+ <comment xml:lang="fo">Perl boðrøð</comment>
+ <comment xml:lang="fi">Perl-komentotiedosto</comment>
+ <comment xml:lang="eu">Perl script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Perl</comment>
+ <comment xml:lang="eo">Perl-skripto</comment>
+ <comment xml:lang="en_GB">Perl script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών Perl</comment>
+ <comment xml:lang="de">Perl-Skript</comment>
+ <comment xml:lang="da">Perl-program</comment>
+ <comment xml:lang="cy">Sgript Perl</comment>
+ <comment xml:lang="cs">skript v Perlu</comment>
+ <comment xml:lang="ca">script Perl</comment>
+ <comment xml:lang="bg">Скрипт — Perl</comment>
+ <comment xml:lang="be@latin">Skrypt Perl</comment>
+ <comment xml:lang="be">скрыпт Perl</comment>
+ <comment xml:lang="ar">سكربت بيرل</comment>
+ <comment xml:lang="af">Perl-skrip</comment>
<sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<alias type="text/x-perl"/>
- <magic priority="50">
- <match value='eval \"exec /usr/local/bin/perl' type="string" offset="0"/>
- <match value="/bin/perl" type="string" offset="2:16"/>
- <match value="/bin/env perl" type="string" offset="2:16"/>
- <match value="use strict" type="string" offset="0:256"/>
- <match value="use warnings" type="string" offset="0:256"/>
- <match value="use diagnostics" type="string" offset="0:256"/>
- <match value="use Test::" type="string" offset="0:256"/>
- <match value="BEGIN {" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="eval \&quot;exec /usr/local/bin/perl" offset="0"/>
+ <match type="string" value="/bin/perl" offset="2:16"/>
+ <match type="string" value="/bin/env perl" offset="2:16"/>
+ <match type="string" value="use Test::" offset="0:256"/>
</magic>
<magic priority="40">
- <match value="\n=pod" type="string" offset="0:256"/>
- <match value="\n=head1 NAME" type="string" offset="0:256"/>
- <match value="\n=head1 DESCRIPTION" type="string" offset="0:256"/>
+ <match type="string" value="use strict" offset="0:256"/>
+ <match type="string" value="use warnings" offset="0:256"/>
+ <match type="string" value="use diagnostics" offset="0:256"/>
+ <match type="string" value="\n=pod" offset="0:256"/>
+ <match type="string" value="\n=head1 NAME" offset="0:256"/>
+ <match type="string" value="\n=head1 DESCRIPTION" offset="0:256"/>
+ <match type="string" value="BEGIN {" offset="0:256"/>
</magic>
<glob pattern="*.pl"/>
<glob pattern="*.PL"/>
+ <!-- CPAN-style Perl build script -->
<glob pattern="*.pm"/>
+ <!-- module -->
<glob pattern="*.al"/>
+ <!-- autoloader -->
<glob pattern="*.perl"/>
<glob pattern="*.pod"/>
- <glob weight="10" pattern="*.t"/>
+ <!-- documentation -->
+ <glob pattern="*.t" weight="10"/>
+ <!-- CPAN-style Perl test script -->
</mime-type>
<mime-type type="application/x-php">
<comment>PHP script</comment>
- <comment xml:lang="ar">سكربت PHP</comment>
- <comment xml:lang="az">PHP skripti</comment>
- <comment xml:lang="be@latin">Skrypt PHP</comment>
- <comment xml:lang="bg">Скрипт — PHP</comment>
- <comment xml:lang="ca">script PHP</comment>
- <comment xml:lang="cs">skript PHP</comment>
- <comment xml:lang="cy">Sgript PHP</comment>
- <comment xml:lang="da">PHP-program</comment>
- <comment xml:lang="de">PHP-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών PHP</comment>
- <comment xml:lang="en_GB">PHP script</comment>
- <comment xml:lang="eo">PHP-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en PHP</comment>
- <comment xml:lang="eu">PHP script-a</comment>
- <comment xml:lang="fi">PHP-komentotiedosto</comment>
- <comment xml:lang="fo">PHP boðrøð</comment>
- <comment xml:lang="fr">script PHP</comment>
- <comment xml:lang="ga">script PHP</comment>
- <comment xml:lang="gl">Script de PHP</comment>
- <comment xml:lang="he">תסריט מעטפת של PHP</comment>
- <comment xml:lang="hr">PHP skripta</comment>
- <comment xml:lang="hu">PHP-parancsfájl</comment>
- <comment xml:lang="ia">Script PHP</comment>
- <comment xml:lang="id">Skrip PHP</comment>
- <comment xml:lang="it">Script PHP</comment>
- <comment xml:lang="ja">PHP スクリプト</comment>
- <comment xml:lang="kk">PHP сценарийі</comment>
- <comment xml:lang="ko">PHP 스크립트</comment>
- <comment xml:lang="lt">PHP scenarijus</comment>
- <comment xml:lang="lv">PHP skripts</comment>
- <comment xml:lang="ms">Skrip PHP</comment>
- <comment xml:lang="nb">PHP-skript</comment>
- <comment xml:lang="nl">PHP-script</comment>
- <comment xml:lang="nn">PHP-skript</comment>
- <comment xml:lang="oc">escript PHP</comment>
- <comment xml:lang="pl">Skrypt PHP</comment>
- <comment xml:lang="pt">script PHP</comment>
- <comment xml:lang="pt_BR">Script PHP</comment>
- <comment xml:lang="ro">Script PHP</comment>
- <comment xml:lang="ru">Сценарий PHP</comment>
- <comment xml:lang="sk">Skript PHP</comment>
- <comment xml:lang="sl">Skriptna datoteka PHP</comment>
- <comment xml:lang="sq">Script PHP</comment>
- <comment xml:lang="sr">ПХП скрипта</comment>
- <comment xml:lang="sv">PHP-skript</comment>
- <comment xml:lang="tr">PHP betiği</comment>
- <comment xml:lang="uk">скрипт PHP</comment>
- <comment xml:lang="vi">Văn lệnh PHP</comment>
- <comment xml:lang="zh_CN">PHP 脚本</comment>
<comment xml:lang="zh_TW">PHP 指令稿</comment>
+ <comment xml:lang="zh_CN">PHP 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh PHP</comment>
+ <comment xml:lang="uk">скрипт PHP</comment>
+ <comment xml:lang="tr">PHP betiği</comment>
+ <comment xml:lang="sv">PHP-skript</comment>
+ <comment xml:lang="sr">ПХП скрипта</comment>
+ <comment xml:lang="sq">programth PHP</comment>
+ <comment xml:lang="sl">Skriptna datoteka PHP</comment>
+ <comment xml:lang="si">PHP ස්ක්‍රිප්ට්</comment>
+ <comment xml:lang="sk">Skript PHP</comment>
+ <comment xml:lang="ru">Сценарий PHP</comment>
+ <comment xml:lang="ro">Script PHP</comment>
+ <comment xml:lang="pt_BR">Script PHP</comment>
+ <comment xml:lang="pt">script PHP</comment>
+ <comment xml:lang="pl">Skrypt PHP</comment>
+ <comment xml:lang="oc">escript PHP</comment>
+ <comment xml:lang="nn">PHP-skript</comment>
+ <comment xml:lang="nl">PHP-script</comment>
+ <comment xml:lang="nb">PHP-skript</comment>
+ <comment xml:lang="ms">Skrip PHP</comment>
+ <comment xml:lang="lv">PHP skripts</comment>
+ <comment xml:lang="lt">PHP scenarijus</comment>
+ <comment xml:lang="ko">PHP 스크립트</comment>
+ <comment xml:lang="kk">PHP сценарийі</comment>
+ <comment xml:lang="ja">PHP スクリプト</comment>
+ <comment xml:lang="it">Script PHP</comment>
+ <comment xml:lang="is">PHP skrifta</comment>
+ <comment xml:lang="id">Skrip PHP</comment>
+ <comment xml:lang="ia">Script PHP</comment>
+ <comment xml:lang="hu">PHP-parancsfájl</comment>
+ <comment xml:lang="hr">PHP skripta</comment>
+ <comment xml:lang="he">תסריט מעטפת של PHP</comment>
+ <comment xml:lang="gl">Script de PHP</comment>
+ <comment xml:lang="ga">script PHP</comment>
+ <comment xml:lang="fur">script PHP</comment>
+ <comment xml:lang="fr">script PHP</comment>
+ <comment xml:lang="fo">PHP boðrøð</comment>
+ <comment xml:lang="fi">PHP-komentotiedosto</comment>
+ <comment xml:lang="eu">PHP script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en PHP</comment>
+ <comment xml:lang="eo">PHP-skripto</comment>
+ <comment xml:lang="en_GB">PHP script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών PHP</comment>
+ <comment xml:lang="de">PHP-Skript</comment>
+ <comment xml:lang="da">PHP-program</comment>
+ <comment xml:lang="cy">Sgript PHP</comment>
+ <comment xml:lang="cs">skript PHP</comment>
+ <comment xml:lang="ca">script PHP</comment>
+ <comment xml:lang="bg">Скрипт — PHP</comment>
+ <comment xml:lang="be@latin">Skrypt PHP</comment>
+ <comment xml:lang="be">скрыпт PHP</comment>
+ <comment xml:lang="az">PHP skripti</comment>
+ <comment xml:lang="ar">سكربت PHP</comment>
+ <comment xml:lang="af">PHP-skrip</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<magic priority="80">
- <match value="&lt;?php" type="string" offset="0:64"/>
+ <match type="string" value="&lt;?php" offset="0:64"/>
</magic>
<glob pattern="*.php"/>
<glob pattern="*.php3"/>
@@ -18173,48 +19903,54 @@
</mime-type>
<mime-type type="application/x-pkcs7-certificates">
<comment>PKCS#7 certificate bundle</comment>
- <comment xml:lang="ar">رزمة الشهادة PKCS#7</comment>
- <comment xml:lang="bg">Сбор със сертификати — PKCS#7</comment>
- <comment xml:lang="ca">conjunt de certificats PKCS#7</comment>
- <comment xml:lang="cs">svazek certifikátů PKCS#7</comment>
- <comment xml:lang="da">PKCS#7-certifikatbundt</comment>
- <comment xml:lang="de">PKCS#7-Zertifikatspaket</comment>
- <comment xml:lang="el">Πακέτο ψηφιακών πιστοποιητικών PKCS#7</comment>
- <comment xml:lang="en_GB">PKCS#7 certificate bundle</comment>
- <comment xml:lang="es">lote de certificados PCKS#7</comment>
- <comment xml:lang="eu">PKCS#7 zertifikazio sorta</comment>
- <comment xml:lang="fi">PKCS#7-varmennenippu</comment>
- <comment xml:lang="fo">PKCS#7 váttanar bundi</comment>
- <comment xml:lang="fr">lot de certificats PKCS#7</comment>
- <comment xml:lang="ga">burla teastas PKCS#7</comment>
- <comment xml:lang="gl">paquete de certificado PKCS#7</comment>
- <comment xml:lang="he">בקשה מוסמכת PKCS#7</comment>
- <comment xml:lang="hr">PKCS#7 paket vjerodajnica</comment>
- <comment xml:lang="hu">PKCS#7-tanúsítványcsomag</comment>
- <comment xml:lang="ia">Pacchetto de certificatos PKCS#7</comment>
- <comment xml:lang="id">Bundel sertifikat PKCS#7</comment>
- <comment xml:lang="it">Bundle certificato PKCS#7</comment>
- <comment xml:lang="ja">PKCS#7 証明書</comment>
- <comment xml:lang="kk">PKCS#7 сертификаттар дестесі</comment>
- <comment xml:lang="ko">PKCS#7 인증서 묶음</comment>
- <comment xml:lang="lt">PKCS#7 liudijimų ryšulys</comment>
- <comment xml:lang="lv">PKCS#7 sertifikātu saišķis</comment>
- <comment xml:lang="nl">PKCS#7-certificaatbundel</comment>
- <comment xml:lang="oc">lòt de certificats PKCS#7</comment>
- <comment xml:lang="pl">Pakiet certyfikatu PKCS#7</comment>
- <comment xml:lang="pt">pacote de certificação PKCS#7</comment>
- <comment xml:lang="pt_BR">Pacote de certificados PKCS#7</comment>
- <comment xml:lang="ro">Pachet certificat PKCS#7</comment>
- <comment xml:lang="ru">Пакет сертификата PKCS#7</comment>
- <comment xml:lang="sk">Zväzok certifikátov PKCS#7</comment>
- <comment xml:lang="sl">Datoteka potrdila PKCS#7</comment>
- <comment xml:lang="sr">ПКЦС#7 пакет уверења</comment>
- <comment xml:lang="sv">PKCS#7-certifikatsamling</comment>
- <comment xml:lang="tr">PKCS#7 sertifika paketi</comment>
- <comment xml:lang="uk">комплект сертифікатів PKCS#7</comment>
- <comment xml:lang="vi">Bó chứng nhận PKCS#7</comment>
- <comment xml:lang="zh_CN">PKCS#7 证书束</comment>
<comment xml:lang="zh_TW">PKCS#7 憑證綁包</comment>
+ <comment xml:lang="zh_CN">PKCS#7 证书束</comment>
+ <comment xml:lang="vi">Bó chứng nhận PKCS#7</comment>
+ <comment xml:lang="uk">комплект сертифікатів PKCS#7</comment>
+ <comment xml:lang="tr">PKCS#7 sertifika paketi</comment>
+ <comment xml:lang="sv">PKCS#7-certifikatsamling</comment>
+ <comment xml:lang="sr">ПКЦС#7 пакет уверења</comment>
+ <comment xml:lang="sq">paketë dëshmish PKCS#7</comment>
+ <comment xml:lang="sl">Datoteka potrdila PKCS#7</comment>
+ <comment xml:lang="si">PKCS#7 සහතික මිටියක්</comment>
+ <comment xml:lang="sk">Zväzok certifikátov PKCS#7</comment>
+ <comment xml:lang="ru">Пакет сертификата PKCS#7</comment>
+ <comment xml:lang="ro">Pachet certificat PKCS#7</comment>
+ <comment xml:lang="pt_BR">Pacote de certificados PKCS#7</comment>
+ <comment xml:lang="pt">pacote de certificação PKCS#7</comment>
+ <comment xml:lang="pl">Pakiet certyfikatu PKCS#7</comment>
+ <comment xml:lang="oc">lòt de certificats PKCS#7</comment>
+ <comment xml:lang="nl">PKCS#7-certificaatbundel</comment>
+ <comment xml:lang="lv">PKCS#7 sertifikātu saišķis</comment>
+ <comment xml:lang="lt">PKCS#7 liudijimų ryšulys</comment>
+ <comment xml:lang="ko">PKCS#7 인증서 묶음</comment>
+ <comment xml:lang="kk">PKCS#7 сертификаттар дестесі</comment>
+ <comment xml:lang="ja">PKCS#7 証明書バンドル</comment>
+ <comment xml:lang="it">Bundle certificato PKCS#7</comment>
+ <comment xml:lang="is">PKCS#7 skilríkjavöndull</comment>
+ <comment xml:lang="id">Bundel sertifikat PKCS#7</comment>
+ <comment xml:lang="ia">Pacchetto de certificatos PKCS#7</comment>
+ <comment xml:lang="hu">PKCS#7-tanúsítványcsomag</comment>
+ <comment xml:lang="hr">PKCS#7 paket vjerodajnica</comment>
+ <comment xml:lang="he">בקשה מוסמכת PKCS#7</comment>
+ <comment xml:lang="gl">paquete de certificado PKCS#7</comment>
+ <comment xml:lang="ga">burla teastas PKCS#7</comment>
+ <comment xml:lang="fur">côl di certificâts PKCS#7</comment>
+ <comment xml:lang="fr">lot de certificats PKCS#7</comment>
+ <comment xml:lang="fo">PKCS#7 váttanar bundi</comment>
+ <comment xml:lang="fi">PKCS#7-varmennepaketti</comment>
+ <comment xml:lang="eu">PKCS#7 zertifikazio sorta</comment>
+ <comment xml:lang="es">lote de certificados PCKS#7</comment>
+ <comment xml:lang="en_GB">PKCS#7 certificate bundle</comment>
+ <comment xml:lang="el">Πακέτο ψηφιακών πιστοποιητικών PKCS#7</comment>
+ <comment xml:lang="de">PKCS#7-Zertifikatpaket</comment>
+ <comment xml:lang="da">PKCS#7-certifikatbundt</comment>
+ <comment xml:lang="cs">svazek certifikátů PKCS#7</comment>
+ <comment xml:lang="ca">conjunt de certificats PKCS#7</comment>
+ <comment xml:lang="bg">Пакет със сертификати — PKCS#7</comment>
+ <comment xml:lang="be">пакет сертыфікатаў PKCS#7</comment>
+ <comment xml:lang="ar">رزمة شهادة PKCS#7</comment>
+ <comment xml:lang="af">PKCS#7-sertifikaatbundel</comment>
<acronym>PKCS</acronym>
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<glob pattern="*.p7b"/>
@@ -18222,54 +19958,59 @@
</mime-type>
<mime-type type="application/pkcs12">
<comment>PKCS#12 certificate bundle</comment>
- <comment xml:lang="ar">رزمة الشهادة PKCS#12</comment>
- <comment xml:lang="be@latin">Viazka sertyfikataŭ PKCS#12</comment>
- <comment xml:lang="bg">Сбор със сертификати — PKCS#12</comment>
- <comment xml:lang="ca">conjunt de certificats PKCS#12</comment>
- <comment xml:lang="cs">svazek certifikátů PKCS#12</comment>
- <comment xml:lang="da">PKCS#12-certifikatbundt</comment>
- <comment xml:lang="de">PKCS#12-Zertifikatspaket</comment>
- <comment xml:lang="el">Πακέτο ψηφιακών πιστοποιητικών PKCS#12</comment>
- <comment xml:lang="en_GB">PKCS#12 certificate bundle</comment>
- <comment xml:lang="eo">ligaĵo de PKCS#12-atestiloj</comment>
- <comment xml:lang="es">lote de certificados PCKS#12</comment>
- <comment xml:lang="eu">PKCS#12 zertifikazio sorta</comment>
- <comment xml:lang="fi">PKCS#12-varmennenippu</comment>
- <comment xml:lang="fo">PKCS#12 váttanar bundi</comment>
- <comment xml:lang="fr">lot de certificats PKCS#12</comment>
- <comment xml:lang="ga">burla teastas PKCS#12</comment>
- <comment xml:lang="gl">paquete de certificado PKCS#12</comment>
- <comment xml:lang="he">בקשה מוסמכת PKCS#12</comment>
- <comment xml:lang="hr">PKCS#12 paket vjerodajnica</comment>
- <comment xml:lang="hu">PKCS#12-tanúsítványcsomag</comment>
- <comment xml:lang="ia">Pacchetto de certificatos PKCS#12</comment>
- <comment xml:lang="id">Bundel sertifikat PKCS#12</comment>
- <comment xml:lang="it">Bundle certificato PKCS#12</comment>
- <comment xml:lang="ja">PKCS#12 証明書</comment>
- <comment xml:lang="kk">PKCS#12 сертификаттар дестесі</comment>
- <comment xml:lang="ko">PKCS#12 인증서 묶음</comment>
- <comment xml:lang="lt">PKCS#12 liudijimų ryšulys</comment>
- <comment xml:lang="lv">PKCS#12 sertifikātu saišķis</comment>
- <comment xml:lang="ms">Sijil PKCS#12</comment>
- <comment xml:lang="nb">PKCS#12 sertifikathaug</comment>
- <comment xml:lang="nl">PKCS#12-certificaatbundel</comment>
- <comment xml:lang="nn">PKCS#12-sertifikatbunt</comment>
- <comment xml:lang="oc">lòt de certificats PKCS#12</comment>
- <comment xml:lang="pl">Pakiet certyfikatu PKCS#12</comment>
- <comment xml:lang="pt">pacote de certificação PKCS#12</comment>
- <comment xml:lang="pt_BR">Pacote de certificados PKCS#12</comment>
- <comment xml:lang="ro">Certificat împachetat PKCS#12</comment>
- <comment xml:lang="ru">Пакет сертификата PKCS#12</comment>
- <comment xml:lang="sk">Zväzok certifikátov PKCS#12</comment>
- <comment xml:lang="sl">Datoteka potrdila PKCS#12</comment>
- <comment xml:lang="sq">Bundle çertifikate PKCS#12</comment>
- <comment xml:lang="sr">ПКЦС#12 пакет уверења</comment>
- <comment xml:lang="sv">PKCS#12-certifikatsamling</comment>
- <comment xml:lang="tr">PKCS#12 sertifika paketi</comment>
- <comment xml:lang="uk">комплект сертифікатів PKCS#12</comment>
- <comment xml:lang="vi">Bó chứng nhận PKCS#12</comment>
+ <comment xml:lang="zh_TW">PKCS#12 憑證綁包</comment>
<comment xml:lang="zh_CN">PKCS#12 证书束</comment>
- <comment xml:lang="zh_TW">PKCS#12 憑證檔綁包</comment>
+ <comment xml:lang="vi">Bó chứng nhận PKCS#12</comment>
+ <comment xml:lang="uk">комплект сертифікатів PKCS#12</comment>
+ <comment xml:lang="tr">PKCS#12 sertifika paketi</comment>
+ <comment xml:lang="sv">PKCS#12-certifikatsamling</comment>
+ <comment xml:lang="sr">ПКЦС#12 пакет уверења</comment>
+ <comment xml:lang="sq">paketë dëshmish PKCS#12</comment>
+ <comment xml:lang="sl">Datoteka potrdila PKCS#12</comment>
+ <comment xml:lang="si">PKCS#12 සහතික මිටියක්</comment>
+ <comment xml:lang="sk">Zväzok certifikátov PKCS#12</comment>
+ <comment xml:lang="ru">Пакет сертификата PKCS#12</comment>
+ <comment xml:lang="ro">Certificat împachetat PKCS#12</comment>
+ <comment xml:lang="pt_BR">Pacote de certificados PKCS#12</comment>
+ <comment xml:lang="pt">pacote de certificação PKCS#12</comment>
+ <comment xml:lang="pl">Pakiet certyfikatu PKCS#12</comment>
+ <comment xml:lang="oc">lòt de certificats PKCS#12</comment>
+ <comment xml:lang="nn">PKCS#12-sertifikatbunt</comment>
+ <comment xml:lang="nl">PKCS#12-certificaatbundel</comment>
+ <comment xml:lang="nb">PKCS#12 sertifikathaug</comment>
+ <comment xml:lang="ms">Sijil PKCS#12</comment>
+ <comment xml:lang="lv">PKCS#12 sertifikātu saišķis</comment>
+ <comment xml:lang="lt">PKCS#12 liudijimų ryšulys</comment>
+ <comment xml:lang="ko">PKCS#12 인증서 묶음</comment>
+ <comment xml:lang="kk">PKCS#12 сертификаттар дестесі</comment>
+ <comment xml:lang="ja">PKCS#12 証明書バンドル</comment>
+ <comment xml:lang="it">Bundle certificato PKCS#12</comment>
+ <comment xml:lang="is">PKCS#12 skilríkjavöndull</comment>
+ <comment xml:lang="id">Bundel sertifikat PKCS#12</comment>
+ <comment xml:lang="ia">Pacchetto de certificatos PKCS#12</comment>
+ <comment xml:lang="hu">PKCS#12-tanúsítványcsomag</comment>
+ <comment xml:lang="hr">PKCS#12 paket vjerodajnica</comment>
+ <comment xml:lang="he">בקשה מוסמכת PKCS#12</comment>
+ <comment xml:lang="gl">paquete de certificado PKCS#12</comment>
+ <comment xml:lang="ga">burla teastas PKCS#12</comment>
+ <comment xml:lang="fur">côl di certificâts PKCS#12</comment>
+ <comment xml:lang="fr">lot de certificats PKCS#12</comment>
+ <comment xml:lang="fo">PKCS#12 váttanar bundi</comment>
+ <comment xml:lang="fi">PKCS#12-varmennepaketti</comment>
+ <comment xml:lang="eu">PKCS#12 zertifikazio sorta</comment>
+ <comment xml:lang="es">lote de certificados PCKS#12</comment>
+ <comment xml:lang="eo">ligaĵo de PKCS#12-atestiloj</comment>
+ <comment xml:lang="en_GB">PKCS#12 certificate bundle</comment>
+ <comment xml:lang="el">Πακέτο ψηφιακών πιστοποιητικών PKCS#12</comment>
+ <comment xml:lang="de">PKCS#12-Zertifikatpaket</comment>
+ <comment xml:lang="da">PKCS#12-certifikatbundt</comment>
+ <comment xml:lang="cs">svazek certifikátů PKCS#12</comment>
+ <comment xml:lang="ca">conjunt de certificats PKCS#12</comment>
+ <comment xml:lang="bg">Пакет със сертификати — PKCS#12</comment>
+ <comment xml:lang="be@latin">Viazka sertyfikataŭ PKCS#12</comment>
+ <comment xml:lang="be">пакет сертыфікатаў PKCS#12</comment>
+ <comment xml:lang="ar">رزمة شهادة PKCS#12</comment>
+ <comment xml:lang="af">PKCS#12-sertifikaatbundel</comment>
<acronym>PKCS</acronym>
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<glob pattern="*.p12"/>
@@ -18278,314 +20019,304 @@
</mime-type>
<mime-type type="application/x-planperfect">
<comment>PlanPerfect spreadsheet</comment>
- <comment xml:lang="ar">جدول PlanPerfect</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš PlanPerfect</comment>
- <comment xml:lang="bg">Таблица — PlanPerfect</comment>
- <comment xml:lang="ca">full de càlcul de PlanPerfect</comment>
- <comment xml:lang="cs">sešit PlanPerfect</comment>
- <comment xml:lang="da">PlanPerfect-regneark</comment>
- <comment xml:lang="de">PlanPerfect-Tabelle</comment>
- <comment xml:lang="el">Φύλλο εργασίας PlanPerfect</comment>
- <comment xml:lang="en_GB">PlanPerfect spreadsheet</comment>
- <comment xml:lang="es">hoja de cálculo de PlanPerfect</comment>
- <comment xml:lang="eu">PlanPerfect kalkulu-orria</comment>
- <comment xml:lang="fi">PlanPerfect-taulukko</comment>
- <comment xml:lang="fo">PlanPerfect rokniark</comment>
- <comment xml:lang="fr">feuille de calcul PlanPerfect</comment>
- <comment xml:lang="ga">scarbhileog PlanPerfect</comment>
- <comment xml:lang="gl">folla de cálculo de PlanPerfect</comment>
- <comment xml:lang="he">גליון נתונים של PlanPerfect</comment>
- <comment xml:lang="hr">PlanPerfect proračunska tablica</comment>
- <comment xml:lang="hu">PlanPerfect táblázat</comment>
- <comment xml:lang="ia">Folio de calculo PlanPerfect</comment>
- <comment xml:lang="id">Lembar sebar PlanPerfect</comment>
- <comment xml:lang="it">Foglio di calcolo PlanPerfect</comment>
- <comment xml:lang="ja">PlanPerfect スプレッドシート</comment>
- <comment xml:lang="kk">PlanPerfect электрондық кестесі</comment>
- <comment xml:lang="ko">PlanPerfect 스프레드시트</comment>
- <comment xml:lang="lt">PlanPerfect skaičialentė</comment>
- <comment xml:lang="lv">PlanPerfect izklājlapa</comment>
- <comment xml:lang="nb">PlanPerfect-regneark</comment>
- <comment xml:lang="nl">PlanPerfect-rekenblad</comment>
- <comment xml:lang="nn">PlanPerfect-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul PlanPerfect</comment>
- <comment xml:lang="pl">Arkusz PlanPerfect</comment>
- <comment xml:lang="pt">folha de cálculo PlanPerfect</comment>
- <comment xml:lang="pt_BR">Planilha do PlanPerfect</comment>
- <comment xml:lang="ro">Foaie de calcul PlanPerfect</comment>
- <comment xml:lang="ru">Электронная таблица PlanPerfect</comment>
- <comment xml:lang="sk">Zošit PlanPerfect</comment>
- <comment xml:lang="sl">Preglednica PlanPerfect</comment>
- <comment xml:lang="sq">Fletë llogaritjesh PlanPerfect</comment>
- <comment xml:lang="sr">табела План Перфекта</comment>
- <comment xml:lang="sv">PlanPerfect-kalkylblad</comment>
- <comment xml:lang="tr">PlanPerfect çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця PlanPerfect</comment>
- <comment xml:lang="vi">Bảng tính PlanPerfect</comment>
- <comment xml:lang="zh_CN">PlanPerfect 电子表格</comment>
<comment xml:lang="zh_TW">PlanPerfect 試算表</comment>
+ <comment xml:lang="zh_CN">PlanPerfect 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính PlanPerfect</comment>
+ <comment xml:lang="uk">електронна таблиця PlanPerfect</comment>
+ <comment xml:lang="tr">PlanPerfect hesap çizelgesi</comment>
+ <comment xml:lang="sv">PlanPerfect-kalkylblad</comment>
+ <comment xml:lang="sr">табела План Перфекта</comment>
+ <comment xml:lang="sq">fletëllogaritje PlanPerfect</comment>
+ <comment xml:lang="sl">Preglednica PlanPerfect</comment>
+ <comment xml:lang="si">PlanPerfect පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit PlanPerfect</comment>
+ <comment xml:lang="ru">Электронная таблица PlanPerfect</comment>
+ <comment xml:lang="ro">Foaie de calcul PlanPerfect</comment>
+ <comment xml:lang="pt_BR">Planilha do PlanPerfect</comment>
+ <comment xml:lang="pt">folha de cálculo PlanPerfect</comment>
+ <comment xml:lang="pl">Arkusz PlanPerfect</comment>
+ <comment xml:lang="oc">fuèlh de calcul PlanPerfect</comment>
+ <comment xml:lang="nn">PlanPerfect-rekneark</comment>
+ <comment xml:lang="nl">PlanPerfect-rekenblad</comment>
+ <comment xml:lang="nb">PlanPerfect-regneark</comment>
+ <comment xml:lang="lv">PlanPerfect izklājlapa</comment>
+ <comment xml:lang="lt">PlanPerfect skaičialentė</comment>
+ <comment xml:lang="ko">PlanPerfect 스프레드시트</comment>
+ <comment xml:lang="kk">PlanPerfect электрондық кестесі</comment>
+ <comment xml:lang="ja">PlanPerfect スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo PlanPerfect</comment>
+ <comment xml:lang="is">PlanPerfect töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar PlanPerfect</comment>
+ <comment xml:lang="ia">Folio de calculo PlanPerfect</comment>
+ <comment xml:lang="hu">PlanPerfect táblázat</comment>
+ <comment xml:lang="hr">PlanPerfect proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של PlanPerfect</comment>
+ <comment xml:lang="gl">folla de cálculo de PlanPerfect</comment>
+ <comment xml:lang="ga">scarbhileog PlanPerfect</comment>
+ <comment xml:lang="fur">sfuei di calcul PlanPerfect</comment>
+ <comment xml:lang="fr">feuille de calcul PlanPerfect</comment>
+ <comment xml:lang="fo">PlanPerfect rokniark</comment>
+ <comment xml:lang="fi">PlanPerfect-taulukko</comment>
+ <comment xml:lang="eu">PlanPerfect kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de PlanPerfect</comment>
+ <comment xml:lang="en_GB">PlanPerfect spreadsheet</comment>
+ <comment xml:lang="el">Φύλλο εργασίας PlanPerfect</comment>
+ <comment xml:lang="de">PlanPerfect-Tabelle</comment>
+ <comment xml:lang="da">PlanPerfect-regneark</comment>
+ <comment xml:lang="cs">sešit PlanPerfect</comment>
+ <comment xml:lang="ca">full de càlcul de PlanPerfect</comment>
+ <comment xml:lang="bg">Таблица — PlanPerfect</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš PlanPerfect</comment>
+ <comment xml:lang="be">электронная табліца PlanPerfect</comment>
+ <comment xml:lang="ar">جدول PlanPerfect</comment>
+ <comment xml:lang="af">PlanPerfect-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.pln"/>
</mime-type>
<mime-type type="application/x-pocket-word">
<comment>Pocket Word document</comment>
- <comment xml:lang="ar">مستند Pocket Word</comment>
- <comment xml:lang="ast">Documentu de PocketWord</comment>
- <comment xml:lang="bg">Документ — Pocket Word</comment>
- <comment xml:lang="ca">document de Pocket Word</comment>
- <comment xml:lang="cs">dokument Pocket Word</comment>
- <comment xml:lang="da">Pocket Word-dokument</comment>
- <comment xml:lang="de">Pocket-Word-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Pocket Word</comment>
- <comment xml:lang="en_GB">Pocket Word document</comment>
- <comment xml:lang="es">documento de Pocket Word</comment>
- <comment xml:lang="eu">Pocket Word dokumentua</comment>
- <comment xml:lang="fi">Pocket Word -asiakirja</comment>
- <comment xml:lang="fo">Pocket Word skjal</comment>
- <comment xml:lang="fr">document Pocket Word</comment>
- <comment xml:lang="ga">cáipéis Pocket Word</comment>
- <comment xml:lang="gl">documento de Pocket Word</comment>
- <comment xml:lang="he">מסמך של Pocket Word</comment>
- <comment xml:lang="hr">Pocket Word dokument</comment>
- <comment xml:lang="hu">Pocket Word dokumentum</comment>
- <comment xml:lang="ia">Documento Pocket Word</comment>
- <comment xml:lang="id">Dokumen Pocket Word</comment>
- <comment xml:lang="it">Documento Pocket Word</comment>
- <comment xml:lang="ja">Pocket Word ドキュメント</comment>
- <comment xml:lang="kk">Pocket Word құжаты</comment>
- <comment xml:lang="ko">Pocket Word 문서</comment>
- <comment xml:lang="lt">Pocket Word dokumentas</comment>
- <comment xml:lang="lv">Pocket Word dokuments</comment>
- <comment xml:lang="nl">Pocket Word-document</comment>
- <comment xml:lang="oc">document Pocket Word</comment>
- <comment xml:lang="pl">Dokument Pocket Word</comment>
- <comment xml:lang="pt">documento Pocket Word</comment>
- <comment xml:lang="pt_BR">Documento do Pocket Word</comment>
- <comment xml:lang="ro">Document Pocket Word</comment>
- <comment xml:lang="ru">Документ Pocket Word</comment>
- <comment xml:lang="sk">Dokument Pocket Word</comment>
- <comment xml:lang="sl">Dokument Pocket Word</comment>
- <comment xml:lang="sr">документ Покет Ворда</comment>
- <comment xml:lang="sv">Pocket Word-dokument</comment>
- <comment xml:lang="tr">Pocket Word belgesi</comment>
- <comment xml:lang="uk">документ Pocket Word</comment>
- <comment xml:lang="vi">Tài liệu Pocket Word</comment>
- <comment xml:lang="zh_CN">Pocket Word 文档</comment>
<comment xml:lang="zh_TW">Pocket Word 文件</comment>
+ <comment xml:lang="zh_CN">Pocket Word 文档</comment>
+ <comment xml:lang="vi">Tài liệu Pocket Word</comment>
+ <comment xml:lang="uk">документ Pocket Word</comment>
+ <comment xml:lang="tr">Pocket Word belgesi</comment>
+ <comment xml:lang="sv">Pocket Word-dokument</comment>
+ <comment xml:lang="sr">документ Покет Ворда</comment>
+ <comment xml:lang="sq">dokument Pocket Word</comment>
+ <comment xml:lang="sl">Dokument Pocket Word</comment>
+ <comment xml:lang="si">Pocket Word ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Pocket Word</comment>
+ <comment xml:lang="ru">Документ Pocket Word</comment>
+ <comment xml:lang="ro">Document Pocket Word</comment>
+ <comment xml:lang="pt_BR">Documento do Pocket Word</comment>
+ <comment xml:lang="pt">documento Pocket Word</comment>
+ <comment xml:lang="pl">Dokument Pocket Word</comment>
+ <comment xml:lang="oc">document Pocket Word</comment>
+ <comment xml:lang="nl">Pocket Word-document</comment>
+ <comment xml:lang="lv">Pocket Word dokuments</comment>
+ <comment xml:lang="lt">Pocket Word dokumentas</comment>
+ <comment xml:lang="ko">Pocket Word 문서</comment>
+ <comment xml:lang="kk">Pocket Word құжаты</comment>
+ <comment xml:lang="ja">Pocket Word ドキュメント</comment>
+ <comment xml:lang="it">Documento Pocket Word</comment>
+ <comment xml:lang="is">Pocket Word skjal</comment>
+ <comment xml:lang="id">Dokumen Pocket Word</comment>
+ <comment xml:lang="ia">Documento Pocket Word</comment>
+ <comment xml:lang="hu">Pocket Word dokumentum</comment>
+ <comment xml:lang="hr">Pocket Word dokument</comment>
+ <comment xml:lang="he">מסמך של Pocket Word</comment>
+ <comment xml:lang="gl">documento de Pocket Word</comment>
+ <comment xml:lang="ga">cáipéis Pocket Word</comment>
+ <comment xml:lang="fur">document Pocket Word</comment>
+ <comment xml:lang="fr">document Pocket Word</comment>
+ <comment xml:lang="fo">Pocket Word skjal</comment>
+ <comment xml:lang="fi">Pocket Word -asiakirja</comment>
+ <comment xml:lang="eu">Pocket Word dokumentua</comment>
+ <comment xml:lang="es">documento de Pocket Word</comment>
+ <comment xml:lang="en_GB">Pocket Word document</comment>
+ <comment xml:lang="el">Έγγραφο Pocket Word</comment>
+ <comment xml:lang="de">Pocket-Word-Dokument</comment>
+ <comment xml:lang="da">Pocket Word-dokument</comment>
+ <comment xml:lang="cs">dokument Pocket Word</comment>
+ <comment xml:lang="ca">document de Pocket Word</comment>
+ <comment xml:lang="bg">Документ — Pocket Word</comment>
+ <comment xml:lang="be">дакумент Pocket Word</comment>
+ <comment xml:lang="ast">Documentu de PocketWord</comment>
+ <comment xml:lang="ar">مستند Pocket Word</comment>
+ <comment xml:lang="af">Pocket Word-dokument</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="{\\pwi" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="{\\pwi" offset="0"/>
</magic>
<glob pattern="*.psw"/>
</mime-type>
<mime-type type="application/x-profile">
- <comment>profiler results</comment>
- <comment xml:lang="ar">نتائج المحلل</comment>
- <comment xml:lang="az">profiler nəticələri</comment>
- <comment xml:lang="be@latin">vyniki profilera</comment>
- <comment xml:lang="bg">Резултати от анализатора</comment>
- <comment xml:lang="ca">resultats de profiler</comment>
- <comment xml:lang="cs">výsledky profileru</comment>
- <comment xml:lang="cy">canlyniadau proffeilio</comment>
- <comment xml:lang="da">profileringsresultater</comment>
- <comment xml:lang="de">Profiler-Ergebnisse</comment>
- <comment xml:lang="el">Αποτελέσματα μετρήσεων για την εκτέλεση προγράμματος</comment>
- <comment xml:lang="en_GB">profiler results</comment>
- <comment xml:lang="eo">resultoj de profililo</comment>
- <comment xml:lang="es">resultados del perfilador</comment>
- <comment xml:lang="eu">profiler-aren emaitzak</comment>
- <comment xml:lang="fi">profilointitulokset</comment>
- <comment xml:lang="fr">résultats de profileur</comment>
- <comment xml:lang="ga">torthaí próifíleora</comment>
- <comment xml:lang="gl">resultados do perfilador</comment>
- <comment xml:lang="he">תוצאות מאבחן</comment>
- <comment xml:lang="hr">Rezultati profila</comment>
- <comment xml:lang="hu">profilírozó-eredmények</comment>
- <comment xml:lang="ia">Resultatos de profilator</comment>
- <comment xml:lang="id">hasil profiler</comment>
- <comment xml:lang="it">Risultati profiler</comment>
- <comment xml:lang="ja">プロファイラー結果</comment>
- <comment xml:lang="kk">прифильдеу нәтижелері</comment>
- <comment xml:lang="ko">프로파일러 결과</comment>
- <comment xml:lang="lt">profiliklio rezultatai</comment>
- <comment xml:lang="lv">profilētāja rezultāti</comment>
- <comment xml:lang="ms">Hasil pemprofil</comment>
- <comment xml:lang="nb">profileingsresultat</comment>
- <comment xml:lang="nl">profiler-resultaten</comment>
- <comment xml:lang="nn">profileringsresultat</comment>
- <comment xml:lang="oc">resultats de perfilador</comment>
- <comment xml:lang="pl">Wyniki profilowania</comment>
- <comment xml:lang="pt">resultados de análise de perfil</comment>
- <comment xml:lang="pt_BR">Resultados do profiler</comment>
- <comment xml:lang="ro">rezultate profiler</comment>
- <comment xml:lang="ru">Результаты профилирования</comment>
- <comment xml:lang="sk">Výsledky profilera</comment>
- <comment xml:lang="sl">rezultati profilirnika</comment>
- <comment xml:lang="sq">Rezultate të profiluesit</comment>
- <comment xml:lang="sr">резултати профилатора</comment>
- <comment xml:lang="sv">profilerarresultat</comment>
- <comment xml:lang="tr">profil sonuçları</comment>
+ <comment>Profiler results</comment>
<comment xml:lang="uk">результати профілювання</comment>
- <comment xml:lang="vi">kết quả nét hiện trạng</comment>
- <comment xml:lang="zh_CN">探查器结果</comment>
- <comment xml:lang="zh_TW">硬體資訊產生器成果</comment>
+ <comment xml:lang="sv">Profilerarresultat</comment>
+ <comment xml:lang="ru">Результаты профилирования</comment>
+ <comment xml:lang="pl">Wyniki profilowania</comment>
+ <comment xml:lang="it">Risultati profiler</comment>
+ <comment xml:lang="gl">Resultados dos perfiladores</comment>
+ <comment xml:lang="eu">Profilatzaile-emaitzak</comment>
+ <comment xml:lang="es">resultados de generador de perfiles</comment>
+ <comment xml:lang="de">Profiler-Ergebnisse</comment>
+ <comment xml:lang="be">вынікі прафіліроўшчыка</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<glob pattern="gmon.out"/>
</mime-type>
<mime-type type="application/x-pw">
<comment>Pathetic Writer document</comment>
- <comment xml:lang="ar">مستند Pathetic Writer</comment>
- <comment xml:lang="ast">Documentu de Pathetic Writer</comment>
- <comment xml:lang="be@latin">Dakument Pathetic Writer</comment>
- <comment xml:lang="bg">Документ — Pathetic Writer</comment>
- <comment xml:lang="ca">document de Pathetic Writer</comment>
- <comment xml:lang="cs">dokument Pathetic Writer</comment>
- <comment xml:lang="da">Pathetic Writer-dokument</comment>
- <comment xml:lang="de">Pathetic-Writer-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Pathetic Writer</comment>
- <comment xml:lang="en_GB">Pathetic Writer document</comment>
- <comment xml:lang="eo">dokumento de Pathetic Writer</comment>
- <comment xml:lang="es">documento de Pathetic Writer</comment>
- <comment xml:lang="eu">Pathetic Writer dokumentua</comment>
- <comment xml:lang="fi">Pathetic Writer -asiakirja</comment>
- <comment xml:lang="fo">Pathetic Writer skjal</comment>
- <comment xml:lang="fr">document Pathetic Writer</comment>
- <comment xml:lang="ga">cáipéis Pathetic Writer</comment>
- <comment xml:lang="gl">documento de Pathetic Writer</comment>
- <comment xml:lang="he">מסמך של Pathetic Writer</comment>
- <comment xml:lang="hr">Pathetic Writer dokument</comment>
- <comment xml:lang="hu">Pathetic Writer-dokumentum</comment>
- <comment xml:lang="ia">Documento Pathetic Writer</comment>
- <comment xml:lang="id">Dokumen Pathetic Writer</comment>
- <comment xml:lang="it">Documento Pathetic Writer</comment>
- <comment xml:lang="ja">Pathetic Writer ドキュメント</comment>
- <comment xml:lang="kk">Pathetic Writer құжаты</comment>
- <comment xml:lang="ko">Pathetic Writer 문서</comment>
- <comment xml:lang="lt">Pathetic Writer dokumentas</comment>
- <comment xml:lang="lv">Pathetic Writer dokuments</comment>
- <comment xml:lang="ms">Dokumen Pathetic Writer</comment>
- <comment xml:lang="nb">Pathetic Writer-dokument</comment>
- <comment xml:lang="nl">Pathetic Writer-document</comment>
- <comment xml:lang="nn">Pathetic Writer-dokument</comment>
- <comment xml:lang="oc">document Pathetic Writer</comment>
- <comment xml:lang="pl">Dokument Pathetic Writer</comment>
- <comment xml:lang="pt">documento do Pathetic Writer</comment>
- <comment xml:lang="pt_BR">Documento do Pathetic Writer</comment>
- <comment xml:lang="ro">Document Pathetic Writer</comment>
- <comment xml:lang="ru">Документ Pathetic Writer</comment>
- <comment xml:lang="sk">Dokument Pathetic Writer</comment>
- <comment xml:lang="sl">Dokument Pathetic Writer</comment>
- <comment xml:lang="sq">Dokument Pathetic Writer</comment>
- <comment xml:lang="sr">документ Патетичног Писца</comment>
- <comment xml:lang="sv">Pathetic Writer-dokument</comment>
- <comment xml:lang="tr">Pathetic Writer belgesi</comment>
- <comment xml:lang="uk">документ Pathetic Writer</comment>
- <comment xml:lang="vi">Tài liệu Pathetic Writer</comment>
- <comment xml:lang="zh_CN">Pathetic Writer 文档</comment>
<comment xml:lang="zh_TW">Pathetic Writer 文件</comment>
+ <comment xml:lang="zh_CN">Pathetic Writer 文档</comment>
+ <comment xml:lang="vi">Tài liệu Pathetic Writer</comment>
+ <comment xml:lang="uk">документ Pathetic Writer</comment>
+ <comment xml:lang="tr">Pathetic Writer belgesi</comment>
+ <comment xml:lang="sv">Pathetic Writer-dokument</comment>
+ <comment xml:lang="sr">документ Патетичног Писца</comment>
+ <comment xml:lang="sq">dokument Pathetic Writer</comment>
+ <comment xml:lang="sl">Dokument Pathetic Writer</comment>
+ <comment xml:lang="si">දුක්ඛිත ලේඛක ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Pathetic Writer</comment>
+ <comment xml:lang="ru">Документ Pathetic Writer</comment>
+ <comment xml:lang="ro">Document Pathetic Writer</comment>
+ <comment xml:lang="pt_BR">Documento do Pathetic Writer</comment>
+ <comment xml:lang="pt">documento do Pathetic Writer</comment>
+ <comment xml:lang="pl">Dokument Pathetic Writer</comment>
+ <comment xml:lang="oc">document Pathetic Writer</comment>
+ <comment xml:lang="nn">Pathetic Writer-dokument</comment>
+ <comment xml:lang="nl">Pathetic Writer-document</comment>
+ <comment xml:lang="nb">Pathetic Writer-dokument</comment>
+ <comment xml:lang="ms">Dokumen Pathetic Writer</comment>
+ <comment xml:lang="lv">Pathetic Writer dokuments</comment>
+ <comment xml:lang="lt">Pathetic Writer dokumentas</comment>
+ <comment xml:lang="ko">Pathetic Writer 문서</comment>
+ <comment xml:lang="kk">Pathetic Writer құжаты</comment>
+ <comment xml:lang="ja">Pathetic Writer ドキュメント</comment>
+ <comment xml:lang="it">Documento Pathetic Writer</comment>
+ <comment xml:lang="is">Pathetic Writer skjal</comment>
+ <comment xml:lang="id">Dokumen Pathetic Writer</comment>
+ <comment xml:lang="ia">Documento Pathetic Writer</comment>
+ <comment xml:lang="hu">Pathetic Writer-dokumentum</comment>
+ <comment xml:lang="hr">Pathetic Writer dokument</comment>
+ <comment xml:lang="he">מסמך של Pathetic Writer</comment>
+ <comment xml:lang="gl">documento de Pathetic Writer</comment>
+ <comment xml:lang="ga">cáipéis Pathetic Writer</comment>
+ <comment xml:lang="fur">document Pathetic Writer</comment>
+ <comment xml:lang="fr">document Pathetic Writer</comment>
+ <comment xml:lang="fo">Pathetic Writer skjal</comment>
+ <comment xml:lang="fi">Pathetic Writer -asiakirja</comment>
+ <comment xml:lang="eu">Pathetic Writer dokumentua</comment>
+ <comment xml:lang="es">documento de Pathetic Writer</comment>
+ <comment xml:lang="eo">dokumento de Pathetic Writer</comment>
+ <comment xml:lang="en_GB">Pathetic Writer document</comment>
+ <comment xml:lang="el">Έγγραφο Pathetic Writer</comment>
+ <comment xml:lang="de">Pathetic-Writer-Dokument</comment>
+ <comment xml:lang="da">Pathetic Writer-dokument</comment>
+ <comment xml:lang="cs">dokument Pathetic Writer</comment>
+ <comment xml:lang="ca">document de Pathetic Writer</comment>
+ <comment xml:lang="bg">Документ — Pathetic Writer</comment>
+ <comment xml:lang="be@latin">Dakument Pathetic Writer</comment>
+ <comment xml:lang="be">дакумент Pathetic Writer</comment>
+ <comment xml:lang="ast">Documentu de Pathetic Writer</comment>
+ <comment xml:lang="ar">مستند Pathetic Writer</comment>
+ <comment xml:lang="af">Pathetic Writer-dokument</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.pw"/>
</mime-type>
<mime-type type="application/x-python-bytecode">
<comment>Python bytecode</comment>
- <comment xml:lang="ar">Python bytecode</comment>
- <comment xml:lang="az">Python bayt kodu</comment>
- <comment xml:lang="be@latin">Bajtavy kod Python</comment>
- <comment xml:lang="bg">Байт код — Python</comment>
- <comment xml:lang="ca">bytecode de Python</comment>
- <comment xml:lang="cs">bajtový kód Python</comment>
- <comment xml:lang="cy">Côd beit Python</comment>
- <comment xml:lang="da">Pythonbytekode</comment>
- <comment xml:lang="de">Python-Bytecode</comment>
- <comment xml:lang="el">Συμβολοκώδικας Python</comment>
- <comment xml:lang="en_GB">Python bytecode</comment>
- <comment xml:lang="eo">Python-bajtkodo</comment>
- <comment xml:lang="es">bytecode de Python</comment>
- <comment xml:lang="eu">Python byte-kodea</comment>
- <comment xml:lang="fi">Python-tavukoodi</comment>
- <comment xml:lang="fo">Python býtkota</comment>
- <comment xml:lang="fr">bytecode Python</comment>
- <comment xml:lang="ga">beartchód Python</comment>
- <comment xml:lang="gl">bytecode de Python</comment>
- <comment xml:lang="he">Bytecode של Python</comment>
- <comment xml:lang="hr">Python bajt kôd</comment>
- <comment xml:lang="hu">Python-bájtkód</comment>
- <comment xml:lang="ia">Codice intermediari Python</comment>
- <comment xml:lang="id">Kode bita Python</comment>
- <comment xml:lang="it">Bytecode Python</comment>
- <comment xml:lang="ja">Python バイトコード</comment>
- <comment xml:lang="kk">Python байткоды</comment>
- <comment xml:lang="ko">파이썬 바이트코드</comment>
- <comment xml:lang="lt">Python baitinis kodas</comment>
- <comment xml:lang="lv">Python bitkods</comment>
- <comment xml:lang="ms">Kodbait Python</comment>
- <comment xml:lang="nb">Python-bytekode</comment>
- <comment xml:lang="nl">Python-bytecode</comment>
- <comment xml:lang="nn">Python-bytekode</comment>
- <comment xml:lang="oc">bytecode Python</comment>
- <comment xml:lang="pl">Kod bajtowy Python</comment>
- <comment xml:lang="pt">código binário Python</comment>
- <comment xml:lang="pt_BR">Código compilado Python</comment>
- <comment xml:lang="ro">Bytecode Python</comment>
- <comment xml:lang="ru">Байт-код Python</comment>
- <comment xml:lang="sk">Bajtový kód Python</comment>
- <comment xml:lang="sl">Datoteka bitne kode Python</comment>
- <comment xml:lang="sq">Bytecode Python</comment>
- <comment xml:lang="sr">Питонов бајтни ко̂д</comment>
- <comment xml:lang="sv">Python-bytekod</comment>
- <comment xml:lang="tr">Python bayt kodu</comment>
- <comment xml:lang="uk">байт-код Python</comment>
- <comment xml:lang="vi">Mã byte Python</comment>
- <comment xml:lang="zh_CN">Python 字节码</comment>
<comment xml:lang="zh_TW">Python 位元組碼</comment>
- <magic priority="50">
- <match value="0x994e0d0a" type="big32" offset="0"/>
+ <comment xml:lang="zh_CN">Python 字节码</comment>
+ <comment xml:lang="vi">Mã byte Python</comment>
+ <comment xml:lang="uk">байт-код Python</comment>
+ <comment xml:lang="tr">Python bayt kodu</comment>
+ <comment xml:lang="sv">Python-bytekod</comment>
+ <comment xml:lang="sr">Питонов бајтни ко̂д</comment>
+ <comment xml:lang="sl">Datoteka bitne kode Python</comment>
+ <comment xml:lang="si">පයිතන් බයිට්කෝඩ්</comment>
+ <comment xml:lang="sk">Bajtový kód Python</comment>
+ <comment xml:lang="ru">Байт-код Python</comment>
+ <comment xml:lang="ro">Bytecode Python</comment>
+ <comment xml:lang="pt_BR">Código compilado Python</comment>
+ <comment xml:lang="pt">código binário Python</comment>
+ <comment xml:lang="pl">Kod bajtowy Python</comment>
+ <comment xml:lang="oc">bytecode Python</comment>
+ <comment xml:lang="nn">Python-bytekode</comment>
+ <comment xml:lang="nl">Python-bytecode</comment>
+ <comment xml:lang="nb">Python-bytekode</comment>
+ <comment xml:lang="ms">Kodbait Python</comment>
+ <comment xml:lang="lv">Python bitkods</comment>
+ <comment xml:lang="lt">Python baitinis kodas</comment>
+ <comment xml:lang="ko">파이썬 바이트코드</comment>
+ <comment xml:lang="kk">Python байткоды</comment>
+ <comment xml:lang="ja">Python バイトコード</comment>
+ <comment xml:lang="it">Bytecode Python</comment>
+ <comment xml:lang="is">Python bætakóði</comment>
+ <comment xml:lang="id">Kode bita Python</comment>
+ <comment xml:lang="ia">Codice intermediari Python</comment>
+ <comment xml:lang="hu">Python-bájtkód</comment>
+ <comment xml:lang="hr">Python bajt kôd</comment>
+ <comment xml:lang="he">Bytecode של Python</comment>
+ <comment xml:lang="gl">bytecode de Python</comment>
+ <comment xml:lang="ga">beartchód Python</comment>
+ <comment xml:lang="fur">bytecode di Python</comment>
+ <comment xml:lang="fr">bytecode Python</comment>
+ <comment xml:lang="fo">Python býtkota</comment>
+ <comment xml:lang="fi">Python-tavukoodi</comment>
+ <comment xml:lang="eu">Python byte-kodea</comment>
+ <comment xml:lang="es">código intermedio de Python</comment>
+ <comment xml:lang="eo">Python-bajtkodo</comment>
+ <comment xml:lang="en_GB">Python bytecode</comment>
+ <comment xml:lang="el">Συμβολοκώδικας Python</comment>
+ <comment xml:lang="de">Python-Bytecode</comment>
+ <comment xml:lang="da">Python-bytekode</comment>
+ <comment xml:lang="cy">Côd beit Python</comment>
+ <comment xml:lang="cs">bajtový kód Python</comment>
+ <comment xml:lang="ca">bytecode de Python</comment>
+ <comment xml:lang="bg">Байт код — Python</comment>
+ <comment xml:lang="be@latin">Bajtavy kod Python</comment>
+ <comment xml:lang="be">байт-код Python</comment>
+ <comment xml:lang="az">Python bayt kodu</comment>
+ <comment xml:lang="ar">Python bytecode</comment>
+ <comment xml:lang="af">Python binêre kode</comment>
+ <magic>
+ <match type="big32" value="0x994e0d0a" offset="0"/>
</magic>
<glob pattern="*.pyc"/>
<glob pattern="*.pyo"/>
</mime-type>
<mime-type type="application/x-qtiplot">
<comment>QtiPlot document</comment>
- <comment xml:lang="ast">Documentu de QtiPlot</comment>
- <comment xml:lang="ca">document QtiPlot</comment>
- <comment xml:lang="cs">dokument GtiPlot</comment>
- <comment xml:lang="da">QtiPlot-dokument</comment>
- <comment xml:lang="de">QtiPlot-Dokument</comment>
- <comment xml:lang="el">Έγγραφο QtiPlot</comment>
- <comment xml:lang="en_GB">QtiPlot document</comment>
- <comment xml:lang="es">documento de QtiPlot</comment>
- <comment xml:lang="eu">QtiPlot dokumentua</comment>
- <comment xml:lang="fi">QtiPlot-asiakirja</comment>
- <comment xml:lang="fr">document QtiPlot</comment>
- <comment xml:lang="ga">cáipéis QtiPlot</comment>
- <comment xml:lang="gl">Documento de QtiPilot</comment>
- <comment xml:lang="he">מסמך QtiPlot</comment>
- <comment xml:lang="hr">QtiPlot dokument</comment>
- <comment xml:lang="hu">QtiPlot dokumentum</comment>
- <comment xml:lang="ia">Documento QtiPlot</comment>
- <comment xml:lang="id">Dokumen QtiPlot</comment>
- <comment xml:lang="it">Documento QtiPlot</comment>
- <comment xml:lang="ja">QtiPlot ドキュメント</comment>
- <comment xml:lang="kk">QtiPlot құжаты</comment>
- <comment xml:lang="ko">QtiPlot 문서</comment>
- <comment xml:lang="lv">QtiPlot dokuments</comment>
- <comment xml:lang="oc">document QtiPlot</comment>
- <comment xml:lang="pl">Dokument QtiPlot</comment>
- <comment xml:lang="pt">documento QtiPlot</comment>
- <comment xml:lang="pt_BR">Documento do QtiPlot</comment>
- <comment xml:lang="ru">Документ QtiPlot</comment>
- <comment xml:lang="sk">Dokument QtiPlot</comment>
- <comment xml:lang="sl">Dokument QtiPlot</comment>
- <comment xml:lang="sr">КутиПлот документ</comment>
- <comment xml:lang="sv">QtiPlot-dokument</comment>
- <comment xml:lang="tr">QtiPlot belgesi</comment>
- <comment xml:lang="uk">документ QtiPlot</comment>
- <comment xml:lang="zh_CN">QtiPlot 文档</comment>
<comment xml:lang="zh_TW">QtiPlot 文件</comment>
+ <comment xml:lang="zh_CN">QtiPlot 文档</comment>
+ <comment xml:lang="uk">документ QtiPlot</comment>
+ <comment xml:lang="tr">QtiPlot belgesi</comment>
+ <comment xml:lang="sv">QtiPlot-dokument</comment>
+ <comment xml:lang="sr">КутиПлот документ</comment>
+ <comment xml:lang="sq">dokument QtiPlot</comment>
+ <comment xml:lang="sl">Dokument QtiPlot</comment>
+ <comment xml:lang="si">QtiPlot ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument QtiPlot</comment>
+ <comment xml:lang="ru">Документ QtiPlot</comment>
+ <comment xml:lang="pt_BR">Documento do QtiPlot</comment>
+ <comment xml:lang="pt">documento QtiPlot</comment>
+ <comment xml:lang="pl">Dokument QtiPlot</comment>
+ <comment xml:lang="oc">document QtiPlot</comment>
+ <comment xml:lang="nl">QtiPlot-document</comment>
+ <comment xml:lang="lv">QtiPlot dokuments</comment>
+ <comment xml:lang="ko">QtiPlot 문서</comment>
+ <comment xml:lang="kk">QtiPlot құжаты</comment>
+ <comment xml:lang="ja">QtiPlot ドキュメント</comment>
+ <comment xml:lang="it">Documento QtiPlot</comment>
+ <comment xml:lang="is">QtiPlot skjal</comment>
+ <comment xml:lang="id">Dokumen QtiPlot</comment>
+ <comment xml:lang="ia">Documento QtiPlot</comment>
+ <comment xml:lang="hu">QtiPlot dokumentum</comment>
+ <comment xml:lang="hr">QtiPlot dokument</comment>
+ <comment xml:lang="he">מסמך QtiPlot</comment>
+ <comment xml:lang="gl">Documento de QtiPilot</comment>
+ <comment xml:lang="ga">cáipéis QtiPlot</comment>
+ <comment xml:lang="fur">document QtiPlot</comment>
+ <comment xml:lang="fr">document QtiPlot</comment>
+ <comment xml:lang="fi">QtiPlot-asiakirja</comment>
+ <comment xml:lang="eu">QtiPlot dokumentua</comment>
+ <comment xml:lang="es">documento de QtiPlot</comment>
+ <comment xml:lang="en_GB">QtiPlot document</comment>
+ <comment xml:lang="el">Έγγραφο QtiPlot</comment>
+ <comment xml:lang="de">QtiPlot-Dokument</comment>
+ <comment xml:lang="da">QtiPlot-dokument</comment>
+ <comment xml:lang="cs">dokument GtiPlot</comment>
+ <comment xml:lang="ca">document QtiPlot</comment>
+ <comment xml:lang="bg">Документ — QtiPlot</comment>
+ <comment xml:lang="be">дакумент QtiPlot</comment>
+ <comment xml:lang="ast">Documentu de QtiPlot</comment>
+ <comment xml:lang="ar">مستند QtiPlot</comment>
+ <comment xml:lang="af">QtiPlot-dokument</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
+ <magic>
<match value="QtiPlot" type="string" offset="0"/>
</magic>
<glob pattern="*.qti"/>
@@ -18593,113 +20324,107 @@
</mime-type>
<mime-type type="application/x-quattropro">
<comment>Quattro Pro spreadsheet</comment>
- <comment xml:lang="ar">جدول Quattro Pro</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš Quattro Pro</comment>
- <comment xml:lang="bg">Таблица — Quattro Pro</comment>
- <comment xml:lang="ca">full de càlcul de Quattro Pro</comment>
- <comment xml:lang="cs">sešit Quattro Pro</comment>
- <comment xml:lang="da">Quattro Pro-regneark</comment>
- <comment xml:lang="de">Quattro-Pro-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Quattro Pro</comment>
- <comment xml:lang="en_GB">Quattro Pro spreadsheet</comment>
- <comment xml:lang="eo">sterntabelo de Quattro Pro</comment>
- <comment xml:lang="es">hoja de cálculo de Quattro Pro</comment>
- <comment xml:lang="eu">Quattro Pro kalkulu-orria</comment>
- <comment xml:lang="fi">Quattro Pro -taulukko</comment>
- <comment xml:lang="fo">Quattro Pro rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Quattro Pro</comment>
- <comment xml:lang="ga">scarbhileog Quattro Pro</comment>
- <comment xml:lang="gl">folla de cálculo Quattro Pro</comment>
- <comment xml:lang="he">גליון נתונים של Quattro Pro</comment>
- <comment xml:lang="hr">Quattro Pro proračunska tablica</comment>
- <comment xml:lang="hu">Quattro Pro-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo Quattro Pro</comment>
- <comment xml:lang="id">Lembar sebar Quattro Pro</comment>
- <comment xml:lang="it">Foglio di calcolo Quattro Pro</comment>
- <comment xml:lang="ja">Quattro Pro スプレッドシート</comment>
- <comment xml:lang="kk">Quattro Pro электрондық кестесі</comment>
- <comment xml:lang="ko">Quattro Pro 스프레드시트</comment>
- <comment xml:lang="lt">Quattro Pro skaičialentė</comment>
- <comment xml:lang="lv">Quattro Pro izklājlapa</comment>
- <comment xml:lang="ms">Hamparan Quatro Pro</comment>
- <comment xml:lang="nb">Quattro Pro-regneark</comment>
- <comment xml:lang="nl">Quattro Pro-rekenblad</comment>
- <comment xml:lang="nn">Quattro Pro-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul Quattro Pro</comment>
- <comment xml:lang="pl">Arkusz Quattro Pro</comment>
- <comment xml:lang="pt">folha de cálculo Quattro Pro</comment>
- <comment xml:lang="pt_BR">Planilha do Quattro Pro</comment>
- <comment xml:lang="ro">Foaie de calcul Quattro Pro</comment>
- <comment xml:lang="ru">Электронная таблица Quattro Pro</comment>
- <comment xml:lang="sk">Zošit Quattro Pro</comment>
- <comment xml:lang="sl">Preglednica Quattro Pro</comment>
- <comment xml:lang="sq">Fletë llogaritjesh Quattro Pro</comment>
- <comment xml:lang="sr">Кватро Про табела</comment>
- <comment xml:lang="sv">Quattro Pro-kalkylblad</comment>
- <comment xml:lang="tr">Quattro Pro çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Quattro Pro</comment>
- <comment xml:lang="vi">Bảng tính Quattro Pro</comment>
- <comment xml:lang="zh_CN">Quattro Pro 电子表格</comment>
<comment xml:lang="zh_TW">Quattro Pro 試算表</comment>
+ <comment xml:lang="zh_CN">Quattro Pro 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Quattro Pro</comment>
+ <comment xml:lang="uk">електронна таблиця Quattro Pro</comment>
+ <comment xml:lang="tr">Quattro Pro hesap çizelgesi</comment>
+ <comment xml:lang="sv">Quattro Pro-kalkylblad</comment>
+ <comment xml:lang="sr">Кватро Про табела</comment>
+ <comment xml:lang="sq">fletëllogaritje Quattro Pro</comment>
+ <comment xml:lang="sl">Preglednica Quattro Pro</comment>
+ <comment xml:lang="si">Quattro Pro පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Quattro Pro</comment>
+ <comment xml:lang="ru">Электронная таблица Quattro Pro</comment>
+ <comment xml:lang="ro">Foaie de calcul Quattro Pro</comment>
+ <comment xml:lang="pt_BR">Planilha do Quattro Pro</comment>
+ <comment xml:lang="pt">folha de cálculo Quattro Pro</comment>
+ <comment xml:lang="pl">Arkusz Quattro Pro</comment>
+ <comment xml:lang="oc">fuèlh de calcul Quattro Pro</comment>
+ <comment xml:lang="nn">Quattro Pro-rekneark</comment>
+ <comment xml:lang="nl">Quattro Pro-rekenblad</comment>
+ <comment xml:lang="nb">Quattro Pro-regneark</comment>
+ <comment xml:lang="ms">Hamparan Quatro Pro</comment>
+ <comment xml:lang="lv">Quattro Pro izklājlapa</comment>
+ <comment xml:lang="lt">Quattro Pro skaičialentė</comment>
+ <comment xml:lang="ko">Quattro Pro 스프레드시트</comment>
+ <comment xml:lang="kk">Quattro Pro электрондық кестесі</comment>
+ <comment xml:lang="ja">Quattro Pro スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Quattro Pro</comment>
+ <comment xml:lang="is">Quattro Pro töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Quattro Pro</comment>
+ <comment xml:lang="ia">Folio de calculo Quattro Pro</comment>
+ <comment xml:lang="hu">Quattro Pro-munkafüzet</comment>
+ <comment xml:lang="hr">Quattro Pro proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Quattro Pro</comment>
+ <comment xml:lang="gl">folla de cálculo Quattro Pro</comment>
+ <comment xml:lang="ga">scarbhileog Quattro Pro</comment>
+ <comment xml:lang="fur">sfuei di calcul Quattro Pro</comment>
+ <comment xml:lang="fr">feuille de calcul Quattro Pro</comment>
+ <comment xml:lang="fo">Quattro Pro rokniark</comment>
+ <comment xml:lang="fi">Quattro Pro -taulukko</comment>
+ <comment xml:lang="eu">Quattro Pro kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Quattro Pro</comment>
+ <comment xml:lang="eo">sterntabelo de Quattro Pro</comment>
+ <comment xml:lang="en_GB">Quattro Pro spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Quattro Pro</comment>
+ <comment xml:lang="de">Quattro-Pro-Tabelle</comment>
+ <comment xml:lang="da">Quattro Pro-regneark</comment>
+ <comment xml:lang="cs">sešit Quattro Pro</comment>
+ <comment xml:lang="ca">full de càlcul de Quattro Pro</comment>
+ <comment xml:lang="bg">Таблица — Quattro Pro</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš Quattro Pro</comment>
+ <comment xml:lang="be">электронная табліца Quattro Pro</comment>
+ <comment xml:lang="ar">جدول Quattro Pro</comment>
+ <comment xml:lang="af">Quattro Pro-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.wb1"/>
<glob pattern="*.wb2"/>
<glob pattern="*.wb3"/>
</mime-type>
<mime-type type="application/x-quicktime-media-link">
- <comment>QuickTime metalink playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل QuickTime metalink</comment>
- <comment xml:lang="be@latin">śpis metaspasyłak na pieśni QuickTime</comment>
- <comment xml:lang="bg">Списък за изпълнение — QuickTime</comment>
- <comment xml:lang="ca">llista de reproducció de metaenllaços QuickTime</comment>
- <comment xml:lang="cs">seznam k přehrání metalink QuickTime</comment>
- <comment xml:lang="da">QuickTime metalink-afspilningsliste</comment>
- <comment xml:lang="de">QuickTime-Metalink-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής metalinks QuickTime</comment>
- <comment xml:lang="en_GB">QuickTime metalink playlist</comment>
- <comment xml:lang="es">lista de reproducción de metaenlaces QuickTime</comment>
- <comment xml:lang="eu">QuickTime meta-esteken erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">QuickTime metalink -soittolista</comment>
- <comment xml:lang="fo">QuickTime metaleinkju avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture metalink QuickTime</comment>
- <comment xml:lang="ga">seinmliosta meiteanasc QuickTime</comment>
- <comment xml:lang="gl">lista de reprodución de metaligazóns QuickTime</comment>
- <comment xml:lang="he">רשימת השמעה מקושרת של QuickTime</comment>
- <comment xml:lang="hr">QuickTime meta poveznica popisa izvođenja</comment>
- <comment xml:lang="hu">QuickTime metalink lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection Metalink QuickTime</comment>
- <comment xml:lang="id">Senarai berkas taut meta QuickTime</comment>
- <comment xml:lang="it">Playlist metalink QuickTime</comment>
- <comment xml:lang="ja">QuickTime メタリンク再生リスト</comment>
- <comment xml:lang="kk">QuickTime метасілтемелер ойнау тізімі</comment>
- <comment xml:lang="ko">퀵타임 메타링크 재생 목록</comment>
- <comment xml:lang="lt">QuickTime metanuorodos grojaraštis</comment>
- <comment xml:lang="lv">QuickTime metasaites repertuārs</comment>
- <comment xml:lang="nb">QuickTime metalink-spilleliste</comment>
- <comment xml:lang="nl">QuickTime metalink-afspeellijst</comment>
- <comment xml:lang="nn">QuickTime metalink-speleliste</comment>
- <comment xml:lang="oc">lista de lectura metalink QuickTime</comment>
- <comment xml:lang="pl">Lista odtwarzania metaodnośników QuickTime</comment>
- <comment xml:lang="pt">lista de reprodução QuickTime metalink</comment>
- <comment xml:lang="pt_BR">Lista de reprodução metalink do QuickTime</comment>
- <comment xml:lang="ro">Listă cu metalegături QuickTime</comment>
- <comment xml:lang="ru">Список воспроизведения мета-ссылок QuickTime</comment>
- <comment xml:lang="sk">Zoznam skladieb metalink QuickTime</comment>
+ <comment>QuickTime playlist</comment>
+ <comment xml:lang="zh_TW">QuickTime 播放清單</comment>
+ <comment xml:lang="zh_CN">QuickTime 播放列表</comment>
+ <comment xml:lang="uk">список відтворення QuickTime</comment>
+ <comment xml:lang="tr">QuickTime çalma listesi</comment>
+ <comment xml:lang="sv">QuickTime-spellista</comment>
+ <comment xml:lang="sq">luajlistë QuickTime</comment>
<comment xml:lang="sl">Seznam predvajanja QuickTime</comment>
- <comment xml:lang="sq">Listë titujsh metalink QuickTime</comment>
- <comment xml:lang="sr">списак нумера мета везе Квик Тајма</comment>
- <comment xml:lang="sv">QuickTime-metalänkspellista</comment>
- <comment xml:lang="tr">QuickTime metalink çalma listesi</comment>
- <comment xml:lang="uk">список відтворення QuickTime metalink</comment>
- <comment xml:lang="vi">Danh mục nhạc siêu liên kết Quicktime</comment>
- <comment xml:lang="zh_CN">QuickTime Metalink 播放列表</comment>
- <comment xml:lang="zh_TW">QuickTime metalink 播放清單</comment>
+ <comment xml:lang="si">QuickTime ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb QuickTime</comment>
+ <comment xml:lang="ru">Список воспроизведения QuickTime</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução do QuickTime</comment>
+ <comment xml:lang="pl">Lista odtwarzania QuickTime</comment>
+ <comment xml:lang="oc">lista de lectura QuickTime</comment>
+ <comment xml:lang="nl">QuickTime-afspeellijst</comment>
+ <comment xml:lang="ko">퀵타임 재생 목록</comment>
+ <comment xml:lang="kk">QuickTime ойнау тізімі</comment>
+ <comment xml:lang="ka">QuickTime დასაკრავი სია</comment>
+ <comment xml:lang="ja">QuickTime プレイリスト</comment>
+ <comment xml:lang="it">Playlist QuickTime</comment>
+ <comment xml:lang="is">QuickTime spilunarlisti</comment>
+ <comment xml:lang="id">Daftar putar QuickTime</comment>
+ <comment xml:lang="hu">QuickTime lejátszólista</comment>
+ <comment xml:lang="hr">QuickTime popis izvođenja</comment>
+ <comment xml:lang="he">רשימת השמעה של QuickTime</comment>
+ <comment xml:lang="fr">liste de lecture QuickTime</comment>
+ <comment xml:lang="fi">QuickTime-soittolista</comment>
+ <comment xml:lang="eu">QuickTime erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción de QuickTime</comment>
+ <comment xml:lang="en_GB">QuickTime playlist</comment>
+ <comment xml:lang="de">QuickTime-Wiedergabeliste</comment>
+ <comment xml:lang="da">QuickTime-afspilningsliste</comment>
+ <comment xml:lang="ca">llista de reproducció QuickTime</comment>
+ <comment xml:lang="bg">Списък за изпълнение — QuickTime</comment>
+ <comment xml:lang="be">плэй-ліст QuickTime</comment>
+ <comment xml:lang="ar">قائمة تشغيل كويك تايم</comment>
<generic-icon name="video-x-generic"/>
<sub-class-of type="video/quicktime"/>
<alias type="application/x-quicktimeplayer"/>
<magic priority="60">
<match value="&lt;?xml" type="string" offset="0">
- <match value="&lt;?quicktime" type="string" offset="0:64"/>
+ <match type="string" value="&lt;?quicktime" offset="0:64"/>
</match>
<match value="RTSPtext" type="string" offset="0"/>
<match value="rtsptext" type="string" offset="0"/>
@@ -18709,283 +20434,267 @@
</mime-type>
<mime-type type="application/x-qw">
<comment>Quicken document</comment>
- <comment xml:lang="ar">مستند Quicken</comment>
- <comment xml:lang="ast">Documentu de Quicken</comment>
- <comment xml:lang="az">Quicken sənədi</comment>
- <comment xml:lang="be@latin">Dakument Quicken</comment>
- <comment xml:lang="bg">Документ — Quicken</comment>
- <comment xml:lang="ca">document Quicken</comment>
- <comment xml:lang="cs">dokument Quicken</comment>
- <comment xml:lang="cy">Dogfen Quicken</comment>
- <comment xml:lang="da">Quickendokument</comment>
- <comment xml:lang="de">Quicken-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Quicken</comment>
- <comment xml:lang="en_GB">Quicken document</comment>
- <comment xml:lang="eo">Quicken-dokumento</comment>
- <comment xml:lang="es">documento de Quicken</comment>
- <comment xml:lang="eu">Quicken dokumentua</comment>
- <comment xml:lang="fi">Quicken-asiakirja</comment>
- <comment xml:lang="fo">Quicken skjal</comment>
- <comment xml:lang="fr">document Quicken</comment>
- <comment xml:lang="ga">cáipéis Quicken</comment>
- <comment xml:lang="gl">documento de Quicken</comment>
- <comment xml:lang="he">מסמך של Quicken</comment>
- <comment xml:lang="hr">Quicken dokument</comment>
- <comment xml:lang="hu">Quicken-dokumentum</comment>
- <comment xml:lang="ia">Documento Quicken</comment>
- <comment xml:lang="id">Dokumen Quicken</comment>
- <comment xml:lang="it">Documento Quicken</comment>
- <comment xml:lang="ja">Quicken ドキュメント</comment>
- <comment xml:lang="kk">Quicken құжаты</comment>
- <comment xml:lang="ko">Quicken 문서</comment>
- <comment xml:lang="lt">Quicken dokumentas</comment>
- <comment xml:lang="lv">Quicken dokuments</comment>
- <comment xml:lang="ms">Dokumen Quicken</comment>
- <comment xml:lang="nb">Quicken-dokument</comment>
- <comment xml:lang="nl">Quicken-document</comment>
- <comment xml:lang="nn">Quicken-dokument</comment>
- <comment xml:lang="oc">document Quicken</comment>
- <comment xml:lang="pl">Dokument Quicken</comment>
- <comment xml:lang="pt">documento Quicken</comment>
- <comment xml:lang="pt_BR">Documento do Quicken</comment>
- <comment xml:lang="ro">Document Quicken</comment>
- <comment xml:lang="ru">Документ Quicken</comment>
- <comment xml:lang="sk">Dokument Quicken</comment>
- <comment xml:lang="sl">Dokument Quicken</comment>
- <comment xml:lang="sq">Dokument Quicken</comment>
- <comment xml:lang="sr">Квикен документ</comment>
- <comment xml:lang="sv">Quicken-dokument</comment>
- <comment xml:lang="tr">Quicken belgesi</comment>
- <comment xml:lang="uk">документ Quicken</comment>
- <comment xml:lang="vi">Tài liệu Quicken</comment>
- <comment xml:lang="zh_CN">Quicken 文档</comment>
<comment xml:lang="zh_TW">Quicken 文件</comment>
+ <comment xml:lang="zh_CN">Quicken 文档</comment>
+ <comment xml:lang="vi">Tài liệu Quicken</comment>
+ <comment xml:lang="uk">документ Quicken</comment>
+ <comment xml:lang="tr">Quicken belgesi</comment>
+ <comment xml:lang="sv">Quicken-dokument</comment>
+ <comment xml:lang="sr">Квикен документ</comment>
+ <comment xml:lang="sq">dokument Quicken</comment>
+ <comment xml:lang="sl">Dokument Quicken</comment>
+ <comment xml:lang="si">ඉක්මන් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Quicken</comment>
+ <comment xml:lang="ru">Документ Quicken</comment>
+ <comment xml:lang="ro">Document Quicken</comment>
+ <comment xml:lang="pt_BR">Documento do Quicken</comment>
+ <comment xml:lang="pt">documento Quicken</comment>
+ <comment xml:lang="pl">Dokument Quicken</comment>
+ <comment xml:lang="oc">document Quicken</comment>
+ <comment xml:lang="nn">Quicken-dokument</comment>
+ <comment xml:lang="nl">Quicken-document</comment>
+ <comment xml:lang="nb">Quicken-dokument</comment>
+ <comment xml:lang="ms">Dokumen Quicken</comment>
+ <comment xml:lang="lv">Quicken dokuments</comment>
+ <comment xml:lang="lt">Quicken dokumentas</comment>
+ <comment xml:lang="ko">Quicken 문서</comment>
+ <comment xml:lang="kk">Quicken құжаты</comment>
+ <comment xml:lang="ja">Quicken ドキュメント</comment>
+ <comment xml:lang="it">Documento Quicken</comment>
+ <comment xml:lang="is">Quicken skjal</comment>
+ <comment xml:lang="id">Dokumen Quicken</comment>
+ <comment xml:lang="ia">Documento Quicken</comment>
+ <comment xml:lang="hu">Quicken-dokumentum</comment>
+ <comment xml:lang="hr">Quicken dokument</comment>
+ <comment xml:lang="he">מסמך של Quicken</comment>
+ <comment xml:lang="gl">documento de Quicken</comment>
+ <comment xml:lang="ga">cáipéis Quicken</comment>
+ <comment xml:lang="fur">document Quicken</comment>
+ <comment xml:lang="fr">document Quicken</comment>
+ <comment xml:lang="fo">Quicken skjal</comment>
+ <comment xml:lang="fi">Quicken-asiakirja</comment>
+ <comment xml:lang="eu">Quicken dokumentua</comment>
+ <comment xml:lang="es">documento de Quicken</comment>
+ <comment xml:lang="eo">Quicken-dokumento</comment>
+ <comment xml:lang="en_GB">Quicken document</comment>
+ <comment xml:lang="el">Έγγραφο Quicken</comment>
+ <comment xml:lang="de">Quicken-Dokument</comment>
+ <comment xml:lang="da">Quickendokument</comment>
+ <comment xml:lang="cy">Dogfen Quicken</comment>
+ <comment xml:lang="cs">dokument Quicken</comment>
+ <comment xml:lang="ca">document Quicken</comment>
+ <comment xml:lang="bg">Документ — Quicken</comment>
+ <comment xml:lang="be@latin">Dakument Quicken</comment>
+ <comment xml:lang="be">дакумент Quicken</comment>
+ <comment xml:lang="az">Quicken sənədi</comment>
+ <comment xml:lang="ast">Documentu de Quicken</comment>
+ <comment xml:lang="ar">مستند Quicken</comment>
+ <comment xml:lang="af">Quicken-dokument</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.qif"/>
</mime-type>
<mime-type type="application/vnd.rar">
<comment>RAR archive</comment>
- <comment xml:lang="ar">أرشيف RAR</comment>
- <comment xml:lang="be@latin">Archiŭ RAR</comment>
- <comment xml:lang="bg">Архив — RAR</comment>
- <comment xml:lang="ca">arxiu RAR</comment>
- <comment xml:lang="cs">archiv RAR</comment>
- <comment xml:lang="cy">Archif RAR</comment>
- <comment xml:lang="da">RAR-arkiv</comment>
- <comment xml:lang="de">RAR-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο RAR</comment>
- <comment xml:lang="en_GB">RAR archive</comment>
- <comment xml:lang="eo">RAR-arkivo</comment>
- <comment xml:lang="es">archivador RAR</comment>
- <comment xml:lang="eu">RAR artxiboa</comment>
- <comment xml:lang="fi">RAR-arkisto</comment>
- <comment xml:lang="fo">RAR skjalasavn</comment>
- <comment xml:lang="fr">archive RAR</comment>
- <comment xml:lang="ga">cartlann RAR</comment>
- <comment xml:lang="gl">ficheiro RAR</comment>
- <comment xml:lang="he">ארכיון RAR</comment>
- <comment xml:lang="hr">RAR arhiva</comment>
- <comment xml:lang="hu">RAR-archívum</comment>
- <comment xml:lang="ia">Archivo RAR</comment>
- <comment xml:lang="id">Arsip RAR</comment>
- <comment xml:lang="it">Archivio RAR</comment>
- <comment xml:lang="ja">RAR アーカイブ</comment>
- <comment xml:lang="kk">RAR архиві</comment>
- <comment xml:lang="ko">RAR 압축 파일</comment>
- <comment xml:lang="lt">RAR archyvas</comment>
- <comment xml:lang="lv">RAR arhīvs</comment>
- <comment xml:lang="ms">Arkib RAR</comment>
- <comment xml:lang="nb">RAR-arkiv</comment>
- <comment xml:lang="nl">RAR-archief</comment>
- <comment xml:lang="nn">RAR-arkiv</comment>
- <comment xml:lang="oc">archiu RAR</comment>
- <comment xml:lang="pl">Archiwum RAR</comment>
- <comment xml:lang="pt">arquivo RAR</comment>
- <comment xml:lang="pt_BR">Pacote RAR</comment>
- <comment xml:lang="ro">Arhivă RAR</comment>
- <comment xml:lang="ru">Архив RAR</comment>
- <comment xml:lang="sk">Archív RAR</comment>
- <comment xml:lang="sl">Datoteka arhiva RAR</comment>
- <comment xml:lang="sq">Arkiv RAR</comment>
- <comment xml:lang="sr">РАР архива</comment>
- <comment xml:lang="sv">RAR-arkiv</comment>
- <comment xml:lang="tr">RAR arşivi</comment>
- <comment xml:lang="uk">архів RAR</comment>
- <comment xml:lang="vi">Kho nén RAR</comment>
- <comment xml:lang="zh_CN">RAR 归档文件</comment>
<comment xml:lang="zh_TW">RAR 封存檔</comment>
+ <comment xml:lang="zh_CN">RAR 归档文件</comment>
+ <comment xml:lang="vi">Kho nén RAR</comment>
+ <comment xml:lang="uk">архів RAR</comment>
+ <comment xml:lang="tr">RAR arşivi</comment>
+ <comment xml:lang="sv">RAR-arkiv</comment>
+ <comment xml:lang="sr">РАР архива</comment>
+ <comment xml:lang="sq">arkiv RAR</comment>
+ <comment xml:lang="sl">Datoteka arhiva RAR</comment>
+ <comment xml:lang="si">RAR ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív RAR</comment>
+ <comment xml:lang="ru">Архив RAR</comment>
+ <comment xml:lang="ro">Arhivă RAR</comment>
+ <comment xml:lang="pt_BR">Pacote RAR</comment>
+ <comment xml:lang="pt">arquivo RAR</comment>
+ <comment xml:lang="pl">Archiwum RAR</comment>
+ <comment xml:lang="oc">archiu RAR</comment>
+ <comment xml:lang="nn">RAR-arkiv</comment>
+ <comment xml:lang="nl">RAR-archief</comment>
+ <comment xml:lang="nb">RAR-arkiv</comment>
+ <comment xml:lang="ms">Arkib RAR</comment>
+ <comment xml:lang="lv">RAR arhīvs</comment>
+ <comment xml:lang="lt">RAR archyvas</comment>
+ <comment xml:lang="ko">RAR 압축 파일</comment>
+ <comment xml:lang="kk">RAR архиві</comment>
+ <comment xml:lang="ja">RAR アーカイブ</comment>
+ <comment xml:lang="it">Archivio RAR</comment>
+ <comment xml:lang="is">RAR safnskrá</comment>
+ <comment xml:lang="id">Arsip RAR</comment>
+ <comment xml:lang="ia">Archivo RAR</comment>
+ <comment xml:lang="hu">RAR-archívum</comment>
+ <comment xml:lang="hr">RAR arhiva</comment>
+ <comment xml:lang="he">ארכיון RAR</comment>
+ <comment xml:lang="gl">ficheiro RAR</comment>
+ <comment xml:lang="ga">cartlann RAR</comment>
+ <comment xml:lang="fur">archivi RAR</comment>
+ <comment xml:lang="fr">archive RAR</comment>
+ <comment xml:lang="fo">RAR skjalasavn</comment>
+ <comment xml:lang="fi">RAR-arkisto</comment>
+ <comment xml:lang="eu">RAR artxiboa</comment>
+ <comment xml:lang="es">archivador RAR</comment>
+ <comment xml:lang="eo">RAR-arkivo</comment>
+ <comment xml:lang="en_GB">RAR archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο RAR</comment>
+ <comment xml:lang="de">RAR-Archiv</comment>
+ <comment xml:lang="da">RAR-arkiv</comment>
+ <comment xml:lang="cy">Archif RAR</comment>
+ <comment xml:lang="cs">archiv RAR</comment>
+ <comment xml:lang="ca">arxiu RAR</comment>
+ <comment xml:lang="bg">Архив — RAR</comment>
+ <comment xml:lang="be@latin">Archiŭ RAR</comment>
+ <comment xml:lang="be">архіў RAR</comment>
+ <comment xml:lang="ar">أرشيف RAR</comment>
+ <comment xml:lang="af">RAR-argief</comment>
<acronym>RAR</acronym>
<expanded-acronym>Roshal ARchive</expanded-acronym>
<alias type="application/x-rar"/>
<alias type="application/x-rar-compressed"/>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="Rar!" type="string" offset="0"/>
+ <match type="string" value="Rar!" offset="0"/>
</magic>
<glob pattern="*.rar"/>
</mime-type>
<mime-type type="application/x-dar">
<comment>DAR archive</comment>
- <comment xml:lang="ar">أرشيف DAR</comment>
- <comment xml:lang="be@latin">Archiŭ DAR</comment>
- <comment xml:lang="bg">Архив — DAR</comment>
- <comment xml:lang="ca">arxiu DAR</comment>
- <comment xml:lang="cs">archiv DAR</comment>
- <comment xml:lang="da">DAR-arkiv</comment>
- <comment xml:lang="de">DAR-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο DAR</comment>
- <comment xml:lang="en_GB">DAR archive</comment>
- <comment xml:lang="eo">DAR-arkivo</comment>
- <comment xml:lang="es">archivador DAR</comment>
- <comment xml:lang="eu">DAR artxiboa</comment>
- <comment xml:lang="fi">DAR-arkisto</comment>
- <comment xml:lang="fo">DAR skjalasavn</comment>
- <comment xml:lang="fr">archive DAR</comment>
- <comment xml:lang="ga">cartlann DAR</comment>
- <comment xml:lang="gl">arquivo DAR</comment>
- <comment xml:lang="he">ארכיון DAR</comment>
- <comment xml:lang="hr">DAR arhiva</comment>
- <comment xml:lang="hu">DAR archívum</comment>
- <comment xml:lang="ia">Archivo DAR</comment>
- <comment xml:lang="id">Arsip DAR</comment>
- <comment xml:lang="it">Archivio DAR</comment>
- <comment xml:lang="ja">DAR アーカイブ</comment>
- <comment xml:lang="ka">DAR არქივი</comment>
- <comment xml:lang="kk">DAR архиві</comment>
- <comment xml:lang="ko">DAR 묶음 파일</comment>
- <comment xml:lang="lt">DAR archyvas</comment>
- <comment xml:lang="lv">DAR arhīvs</comment>
- <comment xml:lang="nb">DAR-arkiv</comment>
- <comment xml:lang="nl">DAR-archief</comment>
- <comment xml:lang="nn">DAR-arkiv</comment>
- <comment xml:lang="oc">archiu DAR</comment>
- <comment xml:lang="pl">Archiwum DAR</comment>
- <comment xml:lang="pt">arquivo DAR</comment>
- <comment xml:lang="pt_BR">Pacote DAR</comment>
- <comment xml:lang="ro">Arhivă DAR</comment>
- <comment xml:lang="ru">Архив DAR</comment>
- <comment xml:lang="sk">Archív DAR</comment>
- <comment xml:lang="sl">Datoteka arhiva DAR</comment>
- <comment xml:lang="sq">Arkiv DAR</comment>
- <comment xml:lang="sr">ДАР архива</comment>
- <comment xml:lang="sv">DAR-arkiv</comment>
- <comment xml:lang="tr">DAR arşivi</comment>
- <comment xml:lang="uk">архів DAR</comment>
- <comment xml:lang="vi">Kho nén DAR</comment>
- <comment xml:lang="zh_CN">DAR 归档文件</comment>
<comment xml:lang="zh_TW">DAR 封存檔</comment>
+ <comment xml:lang="zh_CN">DAR 归档文件</comment>
+ <comment xml:lang="vi">Kho nén DAR</comment>
+ <comment xml:lang="uk">архів DAR</comment>
+ <comment xml:lang="tr">DAR arşivi</comment>
+ <comment xml:lang="sv">DAR-arkiv</comment>
+ <comment xml:lang="sr">ДАР архива</comment>
+ <comment xml:lang="sq">arkiv DAR</comment>
+ <comment xml:lang="sl">Datoteka arhiva DAR</comment>
+ <comment xml:lang="si">DAR ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív DAR</comment>
+ <comment xml:lang="ru">Архив DAR</comment>
+ <comment xml:lang="ro">Arhivă DAR</comment>
+ <comment xml:lang="pt_BR">Pacote DAR</comment>
+ <comment xml:lang="pt">arquivo DAR</comment>
+ <comment xml:lang="pl">Archiwum DAR</comment>
+ <comment xml:lang="oc">archiu DAR</comment>
+ <comment xml:lang="nn">DAR-arkiv</comment>
+ <comment xml:lang="nl">DAR-archief</comment>
+ <comment xml:lang="nb">DAR-arkiv</comment>
+ <comment xml:lang="lv">DAR arhīvs</comment>
+ <comment xml:lang="lt">DAR archyvas</comment>
+ <comment xml:lang="ko">DAR 묶음 파일</comment>
+ <comment xml:lang="kk">DAR архиві</comment>
+ <comment xml:lang="ka">DAR არქივი</comment>
+ <comment xml:lang="ja">DAR アーカイブ</comment>
+ <comment xml:lang="it">Archivio DAR</comment>
+ <comment xml:lang="is">DAR safnskrá</comment>
+ <comment xml:lang="id">Arsip DAR</comment>
+ <comment xml:lang="ia">Archivo DAR</comment>
+ <comment xml:lang="hu">DAR archívum</comment>
+ <comment xml:lang="hr">DAR arhiva</comment>
+ <comment xml:lang="he">ארכיון DAR</comment>
+ <comment xml:lang="gl">arquivo DAR</comment>
+ <comment xml:lang="ga">cartlann DAR</comment>
+ <comment xml:lang="fur">archivi DAR</comment>
+ <comment xml:lang="fr">archive DAR</comment>
+ <comment xml:lang="fo">DAR skjalasavn</comment>
+ <comment xml:lang="fi">DAR-arkisto</comment>
+ <comment xml:lang="eu">DAR artxiboa</comment>
+ <comment xml:lang="es">archivador DAR</comment>
+ <comment xml:lang="eo">DAR-arkivo</comment>
+ <comment xml:lang="en_GB">DAR archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο DAR</comment>
+ <comment xml:lang="de">DAR-Archiv</comment>
+ <comment xml:lang="da">DAR-arkiv</comment>
+ <comment xml:lang="cs">archiv DAR</comment>
+ <comment xml:lang="ca">arxiu DAR</comment>
+ <comment xml:lang="bg">Архив — DAR</comment>
+ <comment xml:lang="be@latin">Archiŭ DAR</comment>
+ <comment xml:lang="be">архіў DAR</comment>
+ <comment xml:lang="ar">أرشيف DAR</comment>
+ <comment xml:lang="af">DAR-argief</comment>
+ <acronym>DAR</acronym>
+ <expanded-acronym>Disk ARchive</expanded-acronym>
<generic-icon name="package-x-generic"/>
<magic>
- <match value="123" type="big32" offset="0"/>
+ <match type="big32" value="123" offset="0"/>
</magic>
<glob pattern="*.dar"/>
</mime-type>
<mime-type type="application/x-alz">
<comment>Alzip archive</comment>
- <comment xml:lang="ar">أرشيف Alzip</comment>
- <comment xml:lang="be@latin">Archiŭ Alzip</comment>
- <comment xml:lang="bg">Архив — alzip</comment>
- <comment xml:lang="ca">arxiu Alzip</comment>
- <comment xml:lang="cs">archiv Alzip</comment>
- <comment xml:lang="da">Alziparkiv</comment>
- <comment xml:lang="de">Alzip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Alzip</comment>
- <comment xml:lang="en_GB">Alzip archive</comment>
- <comment xml:lang="eo">Alzip-arkivo</comment>
- <comment xml:lang="es">archivador Alzip</comment>
- <comment xml:lang="eu">Alzip artxiboa</comment>
- <comment xml:lang="fi">Alzip-arkisto</comment>
- <comment xml:lang="fo">Alsip skjalasavn</comment>
- <comment xml:lang="fr">archive alzip</comment>
- <comment xml:lang="ga">cartlann Alzip</comment>
- <comment xml:lang="gl">arquivo Alzip</comment>
- <comment xml:lang="he">ארכיון Alzip</comment>
- <comment xml:lang="hr">Alzip arhiva</comment>
- <comment xml:lang="hu">Alzip archívum</comment>
- <comment xml:lang="ia">Archivo Alzip</comment>
- <comment xml:lang="id">Arsip Alzip</comment>
- <comment xml:lang="it">Archivio Alzip</comment>
- <comment xml:lang="ja">Alzip アーカイブ</comment>
- <comment xml:lang="ka">Alzip არქივი</comment>
- <comment xml:lang="kk">Alzip архиві</comment>
- <comment xml:lang="ko">알집 압축 파일</comment>
- <comment xml:lang="lt">Alzip archyvas</comment>
- <comment xml:lang="lv">Alzip arhīvs</comment>
- <comment xml:lang="nb">Alzip-arkiv</comment>
- <comment xml:lang="nl">Alzip-archief</comment>
- <comment xml:lang="nn">Alzip-arkiv</comment>
- <comment xml:lang="oc">archiu alzip</comment>
- <comment xml:lang="pl">Archiwum alzip</comment>
- <comment xml:lang="pt">arquivo Alzip</comment>
- <comment xml:lang="pt_BR">Pacote Alzip</comment>
- <comment xml:lang="ro">Arhivă Alzip</comment>
- <comment xml:lang="ru">Архив ALZIP</comment>
- <comment xml:lang="sk">Archív Alzip</comment>
- <comment xml:lang="sl">Datoteka arhiva Alzip</comment>
- <comment xml:lang="sq">Arkiv Alzip</comment>
- <comment xml:lang="sr">Алзип архива</comment>
- <comment xml:lang="sv">Alzip-arkiv</comment>
- <comment xml:lang="tr">Alzip arşivi</comment>
- <comment xml:lang="uk">архів Alzip</comment>
- <comment xml:lang="vi">Kho nén Alzip</comment>
- <comment xml:lang="zh_CN">Alzip 归档文件</comment>
<comment xml:lang="zh_TW">Alzip 封存檔</comment>
+ <comment xml:lang="zh_CN">Alzip 归档文件</comment>
+ <comment xml:lang="vi">Kho nén Alzip</comment>
+ <comment xml:lang="uk">архів Alzip</comment>
+ <comment xml:lang="tr">Alzip arşivi</comment>
+ <comment xml:lang="sv">Alzip-arkiv</comment>
+ <comment xml:lang="sr">Алзип архива</comment>
+ <comment xml:lang="sq">arkiv Alzip</comment>
+ <comment xml:lang="sl">Datoteka arhiva Alzip</comment>
+ <comment xml:lang="si">Alzip සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív Alzip</comment>
+ <comment xml:lang="ru">Архив ALZIP</comment>
+ <comment xml:lang="ro">Arhivă Alzip</comment>
+ <comment xml:lang="pt_BR">Pacote Alzip</comment>
+ <comment xml:lang="pt">arquivo Alzip</comment>
+ <comment xml:lang="pl">Archiwum alzip</comment>
+ <comment xml:lang="oc">archiu alzip</comment>
+ <comment xml:lang="nn">Alzip-arkiv</comment>
+ <comment xml:lang="nl">Alzip-archief</comment>
+ <comment xml:lang="nb">Alzip-arkiv</comment>
+ <comment xml:lang="lv">Alzip arhīvs</comment>
+ <comment xml:lang="lt">Alzip archyvas</comment>
+ <comment xml:lang="ko">알집 압축 파일</comment>
+ <comment xml:lang="kk">Alzip архиві</comment>
+ <comment xml:lang="ka">Alzip არქივი</comment>
+ <comment xml:lang="ja">Alzip アーカイブ</comment>
+ <comment xml:lang="it">Archivio Alzip</comment>
+ <comment xml:lang="is">Alzip safnskrá</comment>
+ <comment xml:lang="id">Arsip Alzip</comment>
+ <comment xml:lang="ia">Archivo Alzip</comment>
+ <comment xml:lang="hu">Alzip archívum</comment>
+ <comment xml:lang="hr">Alzip arhiva</comment>
+ <comment xml:lang="he">ארכיון Alzip</comment>
+ <comment xml:lang="gl">arquivo Alzip</comment>
+ <comment xml:lang="ga">cartlann Alzip</comment>
+ <comment xml:lang="fur">archivi Alzip</comment>
+ <comment xml:lang="fr">archive alzip</comment>
+ <comment xml:lang="fo">Alsip skjalasavn</comment>
+ <comment xml:lang="fi">Alzip-arkisto</comment>
+ <comment xml:lang="eu">Alzip artxiboa</comment>
+ <comment xml:lang="es">archivador Alzip</comment>
+ <comment xml:lang="eo">Alzip-arkivo</comment>
+ <comment xml:lang="en_GB">Alzip archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Alzip</comment>
+ <comment xml:lang="de">ALZip-Archiv</comment>
+ <comment xml:lang="da">Alzip-arkiv</comment>
+ <comment xml:lang="cs">archiv Alzip</comment>
+ <comment xml:lang="ca">arxiu Alzip</comment>
+ <comment xml:lang="bg">Архив — alzip</comment>
+ <comment xml:lang="be@latin">Archiŭ Alzip</comment>
+ <comment xml:lang="be">архіў Alzip</comment>
+ <comment xml:lang="ar">أرشيف Alzip</comment>
+ <comment xml:lang="af">Alzip-argief</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="ALZ" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="ALZ" offset="0"/>
</magic>
<glob pattern="*.alz"/>
</mime-type>
<mime-type type="text/x-reject">
- <comment>rejected patch</comment>
- <comment xml:lang="ar">رقعة مرفوضة</comment>
- <comment xml:lang="be@latin">niepryniaty patch</comment>
- <comment xml:lang="bg">Отхвърлен файл с кръпка</comment>
- <comment xml:lang="ca">pedaç rebutjat</comment>
- <comment xml:lang="cs">odmítnutá záplata</comment>
- <comment xml:lang="da">afvist tekstlap</comment>
- <comment xml:lang="de">Abgelehnter Patch</comment>
- <comment xml:lang="el">Διόρθωση που απορρίφθηκε</comment>
- <comment xml:lang="en_GB">rejected patch</comment>
- <comment xml:lang="eo">reĵeta flikaĵo</comment>
- <comment xml:lang="es">parche rechazado</comment>
- <comment xml:lang="eu">baztertutako adabakia</comment>
- <comment xml:lang="fi">hylättyjen muutosten tiedosto</comment>
- <comment xml:lang="fo">vrakað rætting</comment>
- <comment xml:lang="fr">correctif rejeté</comment>
- <comment xml:lang="ga">paiste diúltaithe</comment>
- <comment xml:lang="gl">parche rexeitado</comment>
- <comment xml:lang="he">טלאי שנדחה</comment>
- <comment xml:lang="hr">Odbijena zakrpa</comment>
- <comment xml:lang="hu">visszautasított folt</comment>
- <comment xml:lang="ia">Patch rejectate</comment>
- <comment xml:lang="id">patch ditolak</comment>
- <comment xml:lang="it">Patch rifiutata</comment>
- <comment xml:lang="ja">拒否されたパッチ</comment>
- <comment xml:lang="kk">алынбаған патч</comment>
- <comment xml:lang="ko">거부된 패치 파일</comment>
- <comment xml:lang="lt">atmestas lopas</comment>
- <comment xml:lang="lv">noraidītais ceļš</comment>
- <comment xml:lang="ms">Tampungan ditolak</comment>
- <comment xml:lang="nb">avvist patchfil</comment>
- <comment xml:lang="nl">verworpen patch</comment>
- <comment xml:lang="nn">avvist programfiks</comment>
- <comment xml:lang="oc">correctiu regetat</comment>
- <comment xml:lang="pl">Odrzucona łata</comment>
- <comment xml:lang="pt">patch rejeitado</comment>
- <comment xml:lang="pt_BR">Arquivo de patch rejeitado</comment>
- <comment xml:lang="ro">petec respsins</comment>
+ <comment>Rejected patch</comment>
+ <comment xml:lang="uk">відкинута латка</comment>
+ <comment xml:lang="sv">Avvisad programfix</comment>
<comment xml:lang="ru">Отклонённый патч</comment>
- <comment xml:lang="sk">Odmietnutá záplata</comment>
- <comment xml:lang="sl">zavrnjen popravek</comment>
- <comment xml:lang="sq">Patch i kthyer mbrapsht</comment>
- <comment xml:lang="sr">одбијена закрпа</comment>
- <comment xml:lang="sv">avvisad programfix</comment>
- <comment xml:lang="tr">reddedilmiş yama</comment>
- <comment xml:lang="uk">відхилена латка</comment>
- <comment xml:lang="vi">đắp vá bị từ chối</comment>
- <comment xml:lang="zh_CN">拒绝的补丁</comment>
- <comment xml:lang="zh_TW">回絕的修補</comment>
+ <comment xml:lang="pl">Odrzucona łata</comment>
+ <comment xml:lang="it">Patch rifiutata</comment>
+ <comment xml:lang="gl">Parche rexeitado</comment>
+ <comment xml:lang="eu">Baztertutako adabakia</comment>
+ <comment xml:lang="es">parche rechazado</comment>
+ <comment xml:lang="de">Abgelehnter Patch</comment>
+ <comment xml:lang="be">адхілены патч</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<alias type="application/x-reject"/>
@@ -18993,98 +20702,112 @@
</mime-type>
<mime-type type="application/x-rpm">
<comment>RPM package</comment>
- <comment xml:lang="ar">حزمة RPM</comment>
- <comment xml:lang="be@latin">Pakunak RPM</comment>
- <comment xml:lang="bg">Пакет — RPM</comment>
- <comment xml:lang="ca">paquet RPM</comment>
- <comment xml:lang="cs">balíček RPM</comment>
- <comment xml:lang="da">RPM-pakke</comment>
- <comment xml:lang="de">RPM-Paket</comment>
- <comment xml:lang="el">Πακέτο RPM</comment>
- <comment xml:lang="en_GB">RPM package</comment>
- <comment xml:lang="eo">RPM-pakaĵo</comment>
- <comment xml:lang="es">paquete RPM</comment>
- <comment xml:lang="eu">RPM paketea</comment>
- <comment xml:lang="fi">RPM-paketti</comment>
- <comment xml:lang="fo">RPM pakki</comment>
- <comment xml:lang="fr">paquet RPM</comment>
- <comment xml:lang="ga">pacáiste RPM</comment>
- <comment xml:lang="gl">paquete RFM</comment>
- <comment xml:lang="he">חבילת RPM</comment>
- <comment xml:lang="hr">RPM paket</comment>
- <comment xml:lang="hu">RPM-csomag</comment>
- <comment xml:lang="ia">Pacchetto RPM</comment>
- <comment xml:lang="id">Paket RPM</comment>
- <comment xml:lang="it">Pacchetto RPM</comment>
- <comment xml:lang="ja">RPM パッケージ</comment>
- <comment xml:lang="kk">RPM дестесі</comment>
- <comment xml:lang="ko">RPM 패키지</comment>
- <comment xml:lang="lt">RPM paketas</comment>
- <comment xml:lang="lv">RPM pakotne</comment>
- <comment xml:lang="ms">Pakej RPM</comment>
- <comment xml:lang="nb">RPM-pakke</comment>
- <comment xml:lang="nl">RPM-pakket</comment>
- <comment xml:lang="nn">RPM-pakke</comment>
- <comment xml:lang="oc">paquet RPM</comment>
- <comment xml:lang="pl">Pakiet RPM</comment>
- <comment xml:lang="pt">pacote RPM</comment>
- <comment xml:lang="pt_BR">Pacote RPM</comment>
- <comment xml:lang="ro">Pachet RPM</comment>
- <comment xml:lang="ru">Пакет RPM</comment>
- <comment xml:lang="sk">Balík RPM</comment>
- <comment xml:lang="sl">Datoteka paketa RPM</comment>
- <comment xml:lang="sq">Paketë RPM</comment>
- <comment xml:lang="sr">РПМ пакет</comment>
- <comment xml:lang="sv">RPM-paket</comment>
- <comment xml:lang="tr">RPM paketi</comment>
- <comment xml:lang="uk">пакунок RPM</comment>
- <comment xml:lang="vi">Gói RPM</comment>
- <comment xml:lang="zh_CN">RPM 软件包</comment>
<comment xml:lang="zh_TW">RPM 軟體包</comment>
+ <comment xml:lang="zh_CN">RPM 软件包</comment>
+ <comment xml:lang="vi">Gói RPM</comment>
+ <comment xml:lang="uk">пакунок RPM</comment>
+ <comment xml:lang="tr">RPM paketi</comment>
+ <comment xml:lang="sv">RPM-paket</comment>
+ <comment xml:lang="sr">РПМ пакет</comment>
+ <comment xml:lang="sq">paketë RPM</comment>
+ <comment xml:lang="sl">Datoteka paketa RPM</comment>
+ <comment xml:lang="si">RPM පැකේජය</comment>
+ <comment xml:lang="sk">Balík RPM</comment>
+ <comment xml:lang="ru">Пакет RPM</comment>
+ <comment xml:lang="ro">Pachet RPM</comment>
+ <comment xml:lang="pt_BR">Pacote RPM</comment>
+ <comment xml:lang="pt">pacote RPM</comment>
+ <comment xml:lang="pl">Pakiet RPM</comment>
+ <comment xml:lang="oc">paquet RPM</comment>
+ <comment xml:lang="nn">RPM-pakke</comment>
+ <comment xml:lang="nl">RPM-pakket</comment>
+ <comment xml:lang="nb">RPM-pakke</comment>
+ <comment xml:lang="ms">Pakej RPM</comment>
+ <comment xml:lang="lv">RPM pakotne</comment>
+ <comment xml:lang="lt">RPM paketas</comment>
+ <comment xml:lang="ko">RPM 패키지</comment>
+ <comment xml:lang="kk">RPM дестесі</comment>
+ <comment xml:lang="ja">RPM パッケージ</comment>
+ <comment xml:lang="it">Pacchetto RPM</comment>
+ <comment xml:lang="is">RPM pakki</comment>
+ <comment xml:lang="id">Paket RPM</comment>
+ <comment xml:lang="ia">Pacchetto RPM</comment>
+ <comment xml:lang="hu">RPM-csomag</comment>
+ <comment xml:lang="hr">RPM paket</comment>
+ <comment xml:lang="he">חבילת RPM</comment>
+ <comment xml:lang="gl">paquete RFM</comment>
+ <comment xml:lang="ga">pacáiste RPM</comment>
+ <comment xml:lang="fur">pachet RPM</comment>
+ <comment xml:lang="fr">paquet RPM</comment>
+ <comment xml:lang="fo">RPM pakki</comment>
+ <comment xml:lang="fi">RPM-paketti</comment>
+ <comment xml:lang="eu">RPM paketea</comment>
+ <comment xml:lang="es">paquete RPM</comment>
+ <comment xml:lang="eo">RPM-pakaĵo</comment>
+ <comment xml:lang="en_GB">RPM package</comment>
+ <comment xml:lang="el">Πακέτο RPM</comment>
+ <comment xml:lang="de">RPM-Paket</comment>
+ <comment xml:lang="da">RPM-pakke</comment>
+ <comment xml:lang="cs">balíček RPM</comment>
+ <comment xml:lang="ca">paquet RPM</comment>
+ <comment xml:lang="bg">Пакет — RPM</comment>
+ <comment xml:lang="be@latin">Pakunak RPM</comment>
+ <comment xml:lang="be">пакет RPM</comment>
+ <comment xml:lang="ar">حزمة RPM</comment>
+ <comment xml:lang="af">RPM-pakket</comment>
<generic-icon name="package-x-generic"/>
<alias type="application/x-redhat-package-manager"/>
- <magic priority="50">
- <match value="\xed\xab\xee\xdb" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\xed\xab\xee\xdb" offset="0"/>
</magic>
<glob pattern="*.rpm"/>
</mime-type>
<mime-type type="application/x-source-rpm">
<comment>Source RPM package</comment>
- <comment xml:lang="ca">paquet RPM de codi font</comment>
- <comment xml:lang="cs">zdrojový balíček RPM</comment>
- <comment xml:lang="da">Kilde RPM-pakke</comment>
- <comment xml:lang="de">Quell-RPM-Paket</comment>
- <comment xml:lang="el">Πακέτο πηγής RPM</comment>
- <comment xml:lang="en_GB">Source RPM package</comment>
- <comment xml:lang="es">paquete de fuente RPM</comment>
- <comment xml:lang="eu">Iturburu RPM paketea</comment>
- <comment xml:lang="fi">RPM-lähdepaketti</comment>
- <comment xml:lang="fr">paquet source RPM</comment>
- <comment xml:lang="ga">pacáiste foinse RPM</comment>
- <comment xml:lang="gl">Paquete RPM de fontes</comment>
- <comment xml:lang="he">חבילת מקור RPM</comment>
- <comment xml:lang="hr">RPM paket izvora</comment>
- <comment xml:lang="hu">Forrás RPM-csomag</comment>
- <comment xml:lang="ia">Pacchetto de fonte RPM</comment>
- <comment xml:lang="id">Paket RPM sumber</comment>
- <comment xml:lang="it">Pacchetto sorgente RPM</comment>
- <comment xml:lang="ja">ソース RPM パッケージ</comment>
- <comment xml:lang="kk">RPM бастапқы код дестесі</comment>
- <comment xml:lang="ko">소스 RPM 패키지</comment>
- <comment xml:lang="lv">Avota RPM pakotne</comment>
- <comment xml:lang="oc">paquet font RPM</comment>
- <comment xml:lang="pl">Źródłowy pakiet RPM</comment>
- <comment xml:lang="pt">pacote origem RPM</comment>
- <comment xml:lang="pt_BR">Pacote fonte RPM</comment>
- <comment xml:lang="ru">Пакет RPM с исходным кодом</comment>
- <comment xml:lang="sk">Zdrojový balík RPM</comment>
- <comment xml:lang="sl">Paket izvorne kode RPM</comment>
- <comment xml:lang="sr">изворни РПМ пакет</comment>
- <comment xml:lang="sv">Käll-RPM-paket</comment>
- <comment xml:lang="tr">Kaynak RPM paketi</comment>
- <comment xml:lang="uk">пакунок RPM з початковим кодом</comment>
- <comment xml:lang="zh_CN">源码 RPM 软件包</comment>
<comment xml:lang="zh_TW">來源 RPM 軟體包</comment>
+ <comment xml:lang="zh_CN">源码 RPM 软件包</comment>
+ <comment xml:lang="uk">пакунок RPM з початковим кодом</comment>
+ <comment xml:lang="tr">Kaynak RPM paketi</comment>
+ <comment xml:lang="sv">Käll-RPM-paket</comment>
+ <comment xml:lang="sr">изворни РПМ пакет</comment>
+ <comment xml:lang="sq">paketë RPM burimi</comment>
+ <comment xml:lang="sl">Paket izvorne kode RPM</comment>
+ <comment xml:lang="si">මූලාශ්‍ර RPM පැකේජය</comment>
+ <comment xml:lang="sk">Zdrojový balík RPM</comment>
+ <comment xml:lang="ru">Пакет RPM с исходным кодом</comment>
+ <comment xml:lang="pt_BR">Pacote fonte RPM</comment>
+ <comment xml:lang="pt">pacote origem RPM</comment>
+ <comment xml:lang="pl">Źródłowy pakiet RPM</comment>
+ <comment xml:lang="oc">paquet font RPM</comment>
+ <comment xml:lang="nl">Source RPM-pakket</comment>
+ <comment xml:lang="lv">Avota RPM pakotne</comment>
+ <comment xml:lang="ko">소스 RPM 패키지</comment>
+ <comment xml:lang="kk">RPM бастапқы код дестесі</comment>
+ <comment xml:lang="ja">ソース RPM パッケージ</comment>
+ <comment xml:lang="it">Pacchetto sorgente RPM</comment>
+ <comment xml:lang="is">RPM grunnkóðapakki</comment>
+ <comment xml:lang="id">Paket RPM sumber</comment>
+ <comment xml:lang="ia">Pacchetto de fonte RPM</comment>
+ <comment xml:lang="hu">Forrás RPM-csomag</comment>
+ <comment xml:lang="hr">RPM paket izvora</comment>
+ <comment xml:lang="he">חבילת מקור RPM</comment>
+ <comment xml:lang="gl">Paquete RPM de fontes</comment>
+ <comment xml:lang="ga">pacáiste foinse RPM</comment>
+ <comment xml:lang="fur">pachet sorzint RPM</comment>
+ <comment xml:lang="fr">paquet source RPM</comment>
+ <comment xml:lang="fi">RPM-lähdepaketti</comment>
+ <comment xml:lang="eu">Iturburu RPM paketea</comment>
+ <comment xml:lang="es">paquete de fuente RPM</comment>
+ <comment xml:lang="en_GB">Source RPM package</comment>
+ <comment xml:lang="el">Πακέτο πηγής RPM</comment>
+ <comment xml:lang="de">RPM-Quellpaket</comment>
+ <comment xml:lang="da">Kilde RPM-pakke</comment>
+ <comment xml:lang="cs">zdrojový balíček RPM</comment>
+ <comment xml:lang="ca">paquet RPM de codi font</comment>
+ <comment xml:lang="bg">Пакет — RPM с изходен код</comment>
+ <comment xml:lang="be">пакет RPM з зыходным кодам</comment>
+ <comment xml:lang="ar">حزمة RPM مصدرية</comment>
+ <comment xml:lang="af">Bron-RPM-pakket</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-rpm"/>
<glob pattern="*.src.rpm"/>
@@ -19092,879 +20815,900 @@
</mime-type>
<mime-type type="application/x-ruby">
<comment>Ruby script</comment>
- <comment xml:lang="ar">سكربت روبي</comment>
- <comment xml:lang="be@latin">Skrypt Ruby</comment>
- <comment xml:lang="bg">Скрипт — Ruby</comment>
- <comment xml:lang="ca">script Ruby</comment>
- <comment xml:lang="cs">skript Ruby</comment>
- <comment xml:lang="da">Rubyprogram</comment>
- <comment xml:lang="de">Ruby-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών Ruby</comment>
- <comment xml:lang="en_GB">Ruby script</comment>
- <comment xml:lang="eo">Ruby-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en Ruby</comment>
- <comment xml:lang="eu">Ruby script-a</comment>
- <comment xml:lang="fi">Ruby-komentotiedosto</comment>
- <comment xml:lang="fo">Ruby boðrøð</comment>
- <comment xml:lang="fr">script Ruby</comment>
- <comment xml:lang="ga">script Ruby</comment>
- <comment xml:lang="gl">Script de Ruby</comment>
- <comment xml:lang="he">תסריט Ruby</comment>
- <comment xml:lang="hr">Ruby skripta</comment>
- <comment xml:lang="hu">Ruby-parancsfájl</comment>
- <comment xml:lang="ia">Script Ruby</comment>
- <comment xml:lang="id">Skrip Ruby</comment>
- <comment xml:lang="it">Script Ruby</comment>
- <comment xml:lang="ja">Ruby スクリプト</comment>
- <comment xml:lang="kk">Ruby сценарийі</comment>
- <comment xml:lang="ko">루비 스크립트</comment>
- <comment xml:lang="lt">Ruby scenarijus</comment>
- <comment xml:lang="lv">Ruby skripts</comment>
- <comment xml:lang="ms">Skrip Ruby</comment>
- <comment xml:lang="nb">Ruby-skript</comment>
- <comment xml:lang="nl">Ruby-script</comment>
- <comment xml:lang="nn">Ruby-skript</comment>
- <comment xml:lang="oc">escript Ruby</comment>
- <comment xml:lang="pl">Skrypt Ruby</comment>
- <comment xml:lang="pt">script Ruby</comment>
- <comment xml:lang="pt_BR">Script Ruby</comment>
- <comment xml:lang="ro">Script Ruby</comment>
- <comment xml:lang="ru">Сценарий Ruby</comment>
- <comment xml:lang="sk">Skript Ruby</comment>
- <comment xml:lang="sl">Skriptna datoteka Ruby</comment>
- <comment xml:lang="sq">Script Ruby</comment>
- <comment xml:lang="sr">Руби скрипта</comment>
- <comment xml:lang="sv">Ruby-skript</comment>
- <comment xml:lang="tr">Ruby betiği</comment>
- <comment xml:lang="uk">скрипт Ruby</comment>
- <comment xml:lang="vi">Văn lệnh Ruby</comment>
- <comment xml:lang="zh_CN">Ruby 脚本</comment>
<comment xml:lang="zh_TW">Ruby 指令稿</comment>
+ <comment xml:lang="zh_CN">Ruby 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh Ruby</comment>
+ <comment xml:lang="uk">скрипт Ruby</comment>
+ <comment xml:lang="tr">Ruby betiği</comment>
+ <comment xml:lang="sv">Ruby-skript</comment>
+ <comment xml:lang="sr">Руби скрипта</comment>
+ <comment xml:lang="sq">programth Ruby</comment>
+ <comment xml:lang="sl">Skriptna datoteka Ruby</comment>
+ <comment xml:lang="si">Ruby පිටපත</comment>
+ <comment xml:lang="sk">Skript Ruby</comment>
+ <comment xml:lang="ru">Сценарий Ruby</comment>
+ <comment xml:lang="ro">Script Ruby</comment>
+ <comment xml:lang="pt_BR">Script Ruby</comment>
+ <comment xml:lang="pt">script Ruby</comment>
+ <comment xml:lang="pl">Skrypt Ruby</comment>
+ <comment xml:lang="oc">escript Ruby</comment>
+ <comment xml:lang="nn">Ruby-skript</comment>
+ <comment xml:lang="nl">Ruby-script</comment>
+ <comment xml:lang="nb">Ruby-skript</comment>
+ <comment xml:lang="ms">Skrip Ruby</comment>
+ <comment xml:lang="lv">Ruby skripts</comment>
+ <comment xml:lang="lt">Ruby scenarijus</comment>
+ <comment xml:lang="ko">루비 스크립트</comment>
+ <comment xml:lang="kk">Ruby сценарийі</comment>
+ <comment xml:lang="ja">Ruby スクリプト</comment>
+ <comment xml:lang="it">Script Ruby</comment>
+ <comment xml:lang="is">Ruby skrifta</comment>
+ <comment xml:lang="id">Skrip Ruby</comment>
+ <comment xml:lang="ia">Script Ruby</comment>
+ <comment xml:lang="hu">Ruby-parancsfájl</comment>
+ <comment xml:lang="hr">Ruby skripta</comment>
+ <comment xml:lang="he">תסריט Ruby</comment>
+ <comment xml:lang="gl">Script de Ruby</comment>
+ <comment xml:lang="ga">script Ruby</comment>
+ <comment xml:lang="fur">script Ruby</comment>
+ <comment xml:lang="fr">script Ruby</comment>
+ <comment xml:lang="fo">Ruby boðrøð</comment>
+ <comment xml:lang="fi">Ruby-komentotiedosto</comment>
+ <comment xml:lang="eu">Ruby script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Ruby</comment>
+ <comment xml:lang="eo">Ruby-skripto</comment>
+ <comment xml:lang="en_GB">Ruby script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών Ruby</comment>
+ <comment xml:lang="de">Ruby-Skript</comment>
+ <comment xml:lang="da">Ruby-program</comment>
+ <comment xml:lang="cs">skript Ruby</comment>
+ <comment xml:lang="ca">script Ruby</comment>
+ <comment xml:lang="bg">Скрипт — Ruby</comment>
+ <comment xml:lang="be@latin">Skrypt Ruby</comment>
+ <comment xml:lang="be">скрыпт Ruby</comment>
+ <comment xml:lang="ar">سكربت روبي</comment>
+ <comment xml:lang="af">Ruby-skrip</comment>
<sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<magic>
- <match value="/bin/env ruby" type="string" offset="2:16"/>
- <match value="/bin/ruby" type="string" offset="2:16"/>
+ <match type="string" value="/bin/env ruby" offset="2:16"/>
+ <match type="string" value="/bin/ruby" offset="2:16"/>
</magic>
<glob pattern="*.rb"/>
</mime-type>
<mime-type type="application/x-markaby">
<comment>Markaby script</comment>
- <comment xml:lang="ar">سكربت Markaby</comment>
- <comment xml:lang="be@latin">Skrypt Markaby</comment>
- <comment xml:lang="bg">Скрипт — Markaby</comment>
- <comment xml:lang="ca">script Markaby</comment>
- <comment xml:lang="cs">skript Markaby</comment>
- <comment xml:lang="da">Markabyprogram</comment>
- <comment xml:lang="de">Markaby-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών Markaby</comment>
- <comment xml:lang="en_GB">Markaby script</comment>
- <comment xml:lang="eo">Markaby-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en Markaby</comment>
- <comment xml:lang="eu">Markaby script-a</comment>
- <comment xml:lang="fi">Markaby-komentotiedosto</comment>
- <comment xml:lang="fo">Markaby boðrøð</comment>
- <comment xml:lang="fr">script Markaby</comment>
- <comment xml:lang="ga">script Markaby</comment>
- <comment xml:lang="gl">Script de Markaby</comment>
- <comment xml:lang="he">תסריט Markby</comment>
- <comment xml:lang="hr">Markaby skripta</comment>
- <comment xml:lang="hu">Markaby parancsfájl</comment>
- <comment xml:lang="ia">Script Markaby</comment>
- <comment xml:lang="id">Skrip Markaby</comment>
- <comment xml:lang="it">Script Markaby</comment>
- <comment xml:lang="ja">Markaby スクリプト</comment>
- <comment xml:lang="ka">Markaby-ის სცენარი</comment>
- <comment xml:lang="kk">Markaby сценарийі</comment>
- <comment xml:lang="ko">Markaby 스크립트</comment>
- <comment xml:lang="lt">Markaby scenarijus</comment>
- <comment xml:lang="lv">Markaby skripts</comment>
- <comment xml:lang="nb">Markaby-skript</comment>
- <comment xml:lang="nl">Markaby-script</comment>
- <comment xml:lang="nn">Markaby-skript</comment>
- <comment xml:lang="oc">escript Markaby</comment>
- <comment xml:lang="pl">Skrypt Markaby</comment>
- <comment xml:lang="pt">script Markaby</comment>
- <comment xml:lang="pt_BR">Script Markaby</comment>
- <comment xml:lang="ro">Script Markaby</comment>
- <comment xml:lang="ru">Сценарий Markaby</comment>
- <comment xml:lang="sk">Skript Markaby</comment>
- <comment xml:lang="sl">Skriptna datoteka Markaby</comment>
- <comment xml:lang="sq">Script Markaby</comment>
- <comment xml:lang="sr">Маркаби скрипта</comment>
- <comment xml:lang="sv">Markaby-skript</comment>
- <comment xml:lang="tr">Markaby betiği</comment>
- <comment xml:lang="uk">скрипт Markaby</comment>
- <comment xml:lang="vi">Văn lệnh Markaby</comment>
- <comment xml:lang="zh_CN">RMarkaby 脚本</comment>
<comment xml:lang="zh_TW">Markaby 指令稿</comment>
+ <comment xml:lang="zh_CN">RMarkaby 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh Markaby</comment>
+ <comment xml:lang="uk">скрипт Markaby</comment>
+ <comment xml:lang="tr">Markaby betiği</comment>
+ <comment xml:lang="sv">Markaby-skript</comment>
+ <comment xml:lang="sr">Маркаби скрипта</comment>
+ <comment xml:lang="sq">programth Markaby</comment>
+ <comment xml:lang="sl">Skriptna datoteka Markaby</comment>
+ <comment xml:lang="si">Markaby පිටපත</comment>
+ <comment xml:lang="sk">Skript Markaby</comment>
+ <comment xml:lang="ru">Сценарий Markaby</comment>
+ <comment xml:lang="ro">Script Markaby</comment>
+ <comment xml:lang="pt_BR">Script Markaby</comment>
+ <comment xml:lang="pt">script Markaby</comment>
+ <comment xml:lang="pl">Skrypt Markaby</comment>
+ <comment xml:lang="oc">escript Markaby</comment>
+ <comment xml:lang="nn">Markaby-skript</comment>
+ <comment xml:lang="nl">Markaby-script</comment>
+ <comment xml:lang="nb">Markaby-skript</comment>
+ <comment xml:lang="lv">Markaby skripts</comment>
+ <comment xml:lang="lt">Markaby scenarijus</comment>
+ <comment xml:lang="ko">Markaby 스크립트</comment>
+ <comment xml:lang="kk">Markaby сценарийі</comment>
+ <comment xml:lang="ka">Markaby-ის სცენარი</comment>
+ <comment xml:lang="ja">Markaby スクリプト</comment>
+ <comment xml:lang="it">Script Markaby</comment>
+ <comment xml:lang="is">Markaby skrifta</comment>
+ <comment xml:lang="id">Skrip Markaby</comment>
+ <comment xml:lang="ia">Script Markaby</comment>
+ <comment xml:lang="hu">Markaby parancsfájl</comment>
+ <comment xml:lang="hr">Markaby skripta</comment>
+ <comment xml:lang="he">תסריט Markby</comment>
+ <comment xml:lang="gl">Script de Markaby</comment>
+ <comment xml:lang="ga">script Markaby</comment>
+ <comment xml:lang="fur">script Markaby</comment>
+ <comment xml:lang="fr">script Markaby</comment>
+ <comment xml:lang="fo">Markaby boðrøð</comment>
+ <comment xml:lang="fi">Markaby-komentotiedosto</comment>
+ <comment xml:lang="eu">Markaby script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Markaby</comment>
+ <comment xml:lang="eo">Markaby-skripto</comment>
+ <comment xml:lang="en_GB">Markaby script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών Markaby</comment>
+ <comment xml:lang="de">Markaby-Skript</comment>
+ <comment xml:lang="da">Markaby-program</comment>
+ <comment xml:lang="cs">skript Markaby</comment>
+ <comment xml:lang="ca">script Markaby</comment>
+ <comment xml:lang="bg">Скрипт — Markaby</comment>
+ <comment xml:lang="be@latin">Skrypt Markaby</comment>
+ <comment xml:lang="be">скрыпт Markaby</comment>
+ <comment xml:lang="ar">سكربت Markaby</comment>
+ <comment xml:lang="af">Markaby-skrip</comment>
<sub-class-of type="application/x-ruby"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.mab"/>
</mime-type>
+ <mime-type type="text/x-crystal">
+ <comment>Crystal source code</comment>
+ <comment xml:lang="zh_TW">Crystal 原始碼</comment>
+ <comment xml:lang="zh_CN">Crystal 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Crystal</comment>
+ <comment xml:lang="tr">Crystal kaynak kodu</comment>
+ <comment xml:lang="sv">Crystal-källkod</comment>
+ <comment xml:lang="sl">Izvorna koda Crystal</comment>
+ <comment xml:lang="si">Crystal source code</comment>
+ <comment xml:lang="ru">Исходный код Crystal</comment>
+ <comment xml:lang="pl">Kod źródłowy Crystal</comment>
+ <comment xml:lang="oc">còdi font Crystal</comment>
+ <comment xml:lang="nl">Crystal-broncode</comment>
+ <comment xml:lang="ko">Crystal 소스 코드</comment>
+ <comment xml:lang="kk">Crystal бастапқы коды</comment>
+ <comment xml:lang="ja">Crystal ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Crystal</comment>
+ <comment xml:lang="hr">Crystal izvorni kôd</comment>
+ <comment xml:lang="gl">Código fonte en Crystal</comment>
+ <comment xml:lang="fi">Crystal-lähdekoodi</comment>
+ <comment xml:lang="eu">Crystal iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Crystal</comment>
+ <comment xml:lang="en_GB">Crystal source code</comment>
+ <comment xml:lang="de">Crystal-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Crystal</comment>
+ <comment xml:lang="ar">شفرة مصدر Crystal</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.cr"/>
+ <alias type="text/crystal"/>
+ </mime-type>
+ <mime-type type="text/julia">
+ <comment>Julia source code</comment>
+ <comment xml:lang="uk">початковий код Julia</comment>
+ <comment xml:lang="sv">Julia-källkod</comment>
+ <comment xml:lang="ru">Исходный код Julia</comment>
+ <comment xml:lang="pl">Kod źródłowy Julia</comment>
+ <comment xml:lang="ja">Julia算譜</comment>
+ <comment xml:lang="it">Codice sorgente Julia</comment>
+ <comment xml:lang="gl">Código fonte en Julia</comment>
+ <comment xml:lang="eu">Julia iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Julia</comment>
+ <comment xml:lang="de">Julia-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Julia</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.jl"/>
+ </mime-type>
<mime-type type="text/rust">
<comment>Rust source code</comment>
- <comment xml:lang="ca">codi font en Rust</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Rust</comment>
- <comment xml:lang="da">Rust-kildekode</comment>
- <comment xml:lang="de">Rust-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Rust</comment>
- <comment xml:lang="en_GB">Rust source code</comment>
- <comment xml:lang="es">código fuente en Rust</comment>
- <comment xml:lang="eu">Rust iturburu-kodea</comment>
- <comment xml:lang="fi">Rust-lähdekoodi</comment>
- <comment xml:lang="fr">code source Rust</comment>
- <comment xml:lang="ga">cód foinseach Rust</comment>
- <comment xml:lang="he">קוד מקור של Rust</comment>
- <comment xml:lang="hr">Rust izvorni kôd</comment>
- <comment xml:lang="hu">Rust forrásfájl</comment>
- <comment xml:lang="ia">Codice-fonte Rust</comment>
- <comment xml:lang="id">Kode program Rust</comment>
- <comment xml:lang="it">Codice sorgente Rust</comment>
- <comment xml:lang="kk">Rust бастапқы коды</comment>
- <comment xml:lang="ko">Rust 소스 코드</comment>
- <comment xml:lang="oc">còde font Rust</comment>
- <comment xml:lang="pl">Kod źródłowy Rust</comment>
- <comment xml:lang="pt">código origem Rust</comment>
- <comment xml:lang="pt_BR">Código-fonte Rust</comment>
- <comment xml:lang="ru">Исходный код Rust</comment>
- <comment xml:lang="sk">Zdrojový kód Rust</comment>
- <comment xml:lang="sr">Раст изворни ко̂д</comment>
- <comment xml:lang="sv">Rust-källkod</comment>
- <comment xml:lang="tr">Rust kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Rust</comment>
- <comment xml:lang="zh_CN">Rust 源代码</comment>
<comment xml:lang="zh_TW">Rust 源碼</comment>
+ <comment xml:lang="zh_CN">Rust 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Rust</comment>
+ <comment xml:lang="tr">Rust kaynak kodu</comment>
+ <comment xml:lang="sv">Rust-källkod</comment>
+ <comment xml:lang="sr">Раст изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Rust</comment>
+ <comment xml:lang="sl">Izvorna koda Rust</comment>
+ <comment xml:lang="si">මලකඩ මූලාශ්ර කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Rust</comment>
+ <comment xml:lang="ru">Исходный код Rust</comment>
+ <comment xml:lang="pt_BR">Código-fonte Rust</comment>
+ <comment xml:lang="pt">código origem Rust</comment>
+ <comment xml:lang="pl">Kod źródłowy Rust</comment>
+ <comment xml:lang="oc">còde font Rust</comment>
+ <comment xml:lang="nl">Rust-broncode</comment>
+ <comment xml:lang="ko">Rust 소스 코드</comment>
+ <comment xml:lang="kk">Rust бастапқы коды</comment>
+ <comment xml:lang="ja">Rust ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Rust</comment>
+ <comment xml:lang="is">Rust frumkóði</comment>
+ <comment xml:lang="id">Kode program Rust</comment>
+ <comment xml:lang="ia">Codice-fonte Rust</comment>
+ <comment xml:lang="hu">Rust forrásfájl</comment>
+ <comment xml:lang="hr">Rust izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Rust</comment>
+ <comment xml:lang="gl">Código fonte en Rust</comment>
+ <comment xml:lang="ga">cód foinseach Rust</comment>
+ <comment xml:lang="fur">codiç sorzint Rust</comment>
+ <comment xml:lang="fr">code source Rust</comment>
+ <comment xml:lang="fi">Rust-lähdekoodi</comment>
+ <comment xml:lang="eu">Rust iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Rust</comment>
+ <comment xml:lang="en_GB">Rust source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Rust</comment>
+ <comment xml:lang="de">Rust-Quelltext</comment>
+ <comment xml:lang="da">Rust-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Rust</comment>
+ <comment xml:lang="ca">codi font en Rust</comment>
+ <comment xml:lang="bg">Изходен код — Rust</comment>
+ <comment xml:lang="be">зыходны код Rust</comment>
+ <comment xml:lang="ar">شفرة مصدر رست</comment>
+ <comment xml:lang="af">Rust-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.rs"/>
</mime-type>
<mime-type type="application/x-sc">
<comment>SC/Xspread spreadsheet</comment>
- <comment xml:lang="ar">جدول SC/Xspread</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš SC/Xspread</comment>
- <comment xml:lang="bg">Таблица — SC/Xspread</comment>
- <comment xml:lang="ca">full de càlcul de SC/Xspread</comment>
- <comment xml:lang="cs">sešit SC/Xspread</comment>
- <comment xml:lang="da">SC/Xspread-regneark</comment>
- <comment xml:lang="de">SX/Xspread-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο SC/Xspread</comment>
- <comment xml:lang="en_GB">SC/Xspread spreadsheet</comment>
- <comment xml:lang="eo">SC/Xspread-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo SC/Xspread</comment>
- <comment xml:lang="eu">SC/Xspread kalkulu-orria</comment>
- <comment xml:lang="fi">SC/Xspread-taulukko</comment>
- <comment xml:lang="fo">SC/Xspread rokniark</comment>
- <comment xml:lang="fr">feuille de calcul SC/Xspread</comment>
- <comment xml:lang="ga">scarbhileog SC/Xspread</comment>
- <comment xml:lang="gl">folla de cálculo SC/Xspread</comment>
- <comment xml:lang="he">גליון נתונים של SC/Xspread</comment>
- <comment xml:lang="hr">SC/Xspread proračunska tablica</comment>
- <comment xml:lang="hu">SC/Xspread táblázat</comment>
- <comment xml:lang="ia">Folio de calculo SC/Xspread</comment>
- <comment xml:lang="id">Lembar sebar SC/Xspread</comment>
- <comment xml:lang="it">Foglio di calcolo SC/Xspread</comment>
- <comment xml:lang="ja">SC/Xspread スプレッドシート</comment>
- <comment xml:lang="kk">SC/Xspread электрондық кестесі</comment>
- <comment xml:lang="ko">SC/Xspread 스프레드시트</comment>
- <comment xml:lang="lt">SC/Xspread skaičialentė</comment>
- <comment xml:lang="lv">SC/Xspread izklājlapa</comment>
- <comment xml:lang="nb">SC/Xspread-regneark</comment>
- <comment xml:lang="nl">SC/Xspread-rekenblad</comment>
- <comment xml:lang="nn">SC/Xspread-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul SC/Xspread</comment>
- <comment xml:lang="pl">Arkusz SC/Xspread</comment>
- <comment xml:lang="pt">folha de cálculo SC/Xspread</comment>
- <comment xml:lang="pt_BR">Planilha do SC/Xspread</comment>
- <comment xml:lang="ro">Foaie de calcul SC/Xspread</comment>
- <comment xml:lang="ru">Электронная таблица SC/Xspread</comment>
- <comment xml:lang="sk">Zošit SC/Xspread</comment>
- <comment xml:lang="sl">Preglednica SC/Xspread</comment>
- <comment xml:lang="sq">Fletë llogaritjesh SC/Xspread</comment>
- <comment xml:lang="sr">табела СЦ/Икс-табеле</comment>
- <comment xml:lang="sv">SC/Xspread-kalkylblad</comment>
- <comment xml:lang="tr">SC/Xspread çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця SC/Xspread</comment>
- <comment xml:lang="vi">Bảng tính SC/Xspread</comment>
- <comment xml:lang="zh_CN">SC/Xspread 电子表格</comment>
<comment xml:lang="zh_TW">SC/Xspread 試算表</comment>
+ <comment xml:lang="zh_CN">SC/Xspread 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính SC/Xspread</comment>
+ <comment xml:lang="uk">електронна таблиця SC/Xspread</comment>
+ <comment xml:lang="tr">SC/Xspread hesap çizelgesi</comment>
+ <comment xml:lang="sv">SC/Xspread-kalkylblad</comment>
+ <comment xml:lang="sr">табела СЦ/Икс-табеле</comment>
+ <comment xml:lang="sq">fletëllogaritje SC/Xspread</comment>
+ <comment xml:lang="sl">Preglednica SC/Xspread</comment>
+ <comment xml:lang="si">SC/Xspread පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit SC/Xspread</comment>
+ <comment xml:lang="ru">Электронная таблица SC/Xspread</comment>
+ <comment xml:lang="ro">Foaie de calcul SC/Xspread</comment>
+ <comment xml:lang="pt_BR">Planilha do SC/Xspread</comment>
+ <comment xml:lang="pt">folha de cálculo SC/Xspread</comment>
+ <comment xml:lang="pl">Arkusz SC/Xspread</comment>
+ <comment xml:lang="oc">fuèlh de calcul SC/Xspread</comment>
+ <comment xml:lang="nn">SC/Xspread-rekneark</comment>
+ <comment xml:lang="nl">SC/Xspread-rekenblad</comment>
+ <comment xml:lang="nb">SC/Xspread-regneark</comment>
+ <comment xml:lang="lv">SC/Xspread izklājlapa</comment>
+ <comment xml:lang="lt">SC/Xspread skaičialentė</comment>
+ <comment xml:lang="ko">SC/Xspread 스프레드시트</comment>
+ <comment xml:lang="kk">SC/Xspread электрондық кестесі</comment>
+ <comment xml:lang="ja">SC/Xspread スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo SC/Xspread</comment>
+ <comment xml:lang="is">SC/Xspread töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar SC/Xspread</comment>
+ <comment xml:lang="ia">Folio de calculo SC/Xspread</comment>
+ <comment xml:lang="hu">SC/Xspread táblázat</comment>
+ <comment xml:lang="hr">SC/Xspread proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של SC/Xspread</comment>
+ <comment xml:lang="gl">folla de cálculo SC/Xspread</comment>
+ <comment xml:lang="ga">scarbhileog SC/Xspread</comment>
+ <comment xml:lang="fur">sfuei di calcul SC/Xspread</comment>
+ <comment xml:lang="fr">feuille de calcul SC/Xspread</comment>
+ <comment xml:lang="fo">SC/Xspread rokniark</comment>
+ <comment xml:lang="fi">SC/Xspread-taulukko</comment>
+ <comment xml:lang="eu">SC/Xspread kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo SC/Xspread</comment>
+ <comment xml:lang="eo">SC/Xspread-kalkultabelo</comment>
+ <comment xml:lang="en_GB">SC/Xspread spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο SC/Xspread</comment>
+ <comment xml:lang="de">SC/Xspread-Tabelle</comment>
+ <comment xml:lang="da">SC/Xspread-regneark</comment>
+ <comment xml:lang="cs">sešit SC/Xspread</comment>
+ <comment xml:lang="ca">full de càlcul de SC/Xspread</comment>
+ <comment xml:lang="bg">Таблица — SC/Xspread</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš SC/Xspread</comment>
+ <comment xml:lang="be">электронная табліца SC/Xspread</comment>
+ <comment xml:lang="ar">جدول SC/Xspread</comment>
+ <comment xml:lang="af">SC/Xspread-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
- <magic priority="50">
- <match value="Spreadsheet" type="string" offset="38"/>
+ <magic>
+ <match type="string" value="Spreadsheet" offset="38"/>
</magic>
</mime-type>
<mime-type type="application/x-shar">
- <comment>shell archive</comment>
- <comment xml:lang="ar">أرشيف شِل</comment>
- <comment xml:lang="az">qabıq arxivi</comment>
- <comment xml:lang="be@latin">archiŭ abałonki</comment>
- <comment xml:lang="bg">Архив на обвивката</comment>
- <comment xml:lang="ca">arxiu de shell</comment>
- <comment xml:lang="cs">archiv shellu</comment>
- <comment xml:lang="cy">archif plisgyn</comment>
- <comment xml:lang="da">skalarkiv</comment>
- <comment xml:lang="de">Shell-Archiv</comment>
- <comment xml:lang="el">Αρχείο κέλυφους</comment>
- <comment xml:lang="en_GB">shell archive</comment>
- <comment xml:lang="eo">ŝel-arkivo</comment>
- <comment xml:lang="es">archivador shell</comment>
- <comment xml:lang="eu">shell artxiboa</comment>
- <comment xml:lang="fi">komentotulkkiarkisto</comment>
- <comment xml:lang="fo">skel savn</comment>
- <comment xml:lang="fr">archive shell</comment>
- <comment xml:lang="ga">cartlann bhlaoisce</comment>
- <comment xml:lang="gl">ficheiro shell</comment>
- <comment xml:lang="he">ארכיון מעטפת</comment>
- <comment xml:lang="hr">Arhiva ljuske</comment>
- <comment xml:lang="hu">héjarchívum</comment>
- <comment xml:lang="ia">Archivo de shell</comment>
- <comment xml:lang="id">arsip shell</comment>
- <comment xml:lang="it">Archivio shell</comment>
- <comment xml:lang="ja">シェルアーカイブ</comment>
- <comment xml:lang="kk">қоршам архиві</comment>
- <comment xml:lang="ko">셸 압축 파일</comment>
- <comment xml:lang="lt">shell archyvas</comment>
- <comment xml:lang="lv">čaulas arhīvs</comment>
- <comment xml:lang="ms">Arkib shell</comment>
- <comment xml:lang="nb">skallarkiv</comment>
- <comment xml:lang="nl">shell-archief</comment>
- <comment xml:lang="nn">skal-arkiv</comment>
- <comment xml:lang="oc">archiu shell</comment>
- <comment xml:lang="pl">Archiwum powłoki</comment>
- <comment xml:lang="pt">arquivo de terminal</comment>
- <comment xml:lang="pt_BR">Pacote shell</comment>
- <comment xml:lang="ro">arhivă shell</comment>
- <comment xml:lang="ru">Архив shell</comment>
- <comment xml:lang="sk">Archív shellu</comment>
- <comment xml:lang="sl">lupinski arhiv</comment>
- <comment xml:lang="sq">Arkiv shell</comment>
- <comment xml:lang="sr">архива љуске</comment>
- <comment xml:lang="sv">skalarkiv</comment>
- <comment xml:lang="tr">kabuk arşivi</comment>
+ <comment>Shell archive</comment>
<comment xml:lang="uk">архів оболонки</comment>
- <comment xml:lang="vi">kho trình bao</comment>
- <comment xml:lang="zh_CN">shell 归档文件</comment>
- <comment xml:lang="zh_TW">shell 封存檔</comment>
+ <comment xml:lang="sv">Skalarkiv</comment>
+ <comment xml:lang="ru">Архив shell</comment>
+ <comment xml:lang="pl">Archiwum powłoki</comment>
+ <comment xml:lang="ja">シェル自己解凍ファイル</comment>
+ <comment xml:lang="it">Archivio shell</comment>
+ <comment xml:lang="gl">Arquivo de Shell</comment>
+ <comment xml:lang="eu">Shell artxiboa</comment>
+ <comment xml:lang="es">archivador Shell</comment>
+ <comment xml:lang="de">Shell-Archiv</comment>
+ <comment xml:lang="be">архіў абалонкі</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.shar"/>
</mime-type>
<mime-type type="application/x-shared-library-la">
- <comment>libtool shared library</comment>
- <comment xml:lang="ar">مكتبة libtool المشتركة</comment>
- <comment xml:lang="be@latin">supolnaja biblijateka libtool</comment>
- <comment xml:lang="bg">Споделена библиотека — libtool</comment>
- <comment xml:lang="ca">biblioteca compartida libtool</comment>
- <comment xml:lang="cs">sdílená knihovna libtool</comment>
- <comment xml:lang="da">libtool delt bibliotek</comment>
- <comment xml:lang="de">Gemeinsame libtool-Bibliothek</comment>
- <comment xml:lang="el">Κοινόχρηστη βιβλιοθήκη libtool</comment>
- <comment xml:lang="en_GB">libtool shared library</comment>
- <comment xml:lang="es">biblioteca compartida de libtool</comment>
- <comment xml:lang="eu">libtool partekatutako liburutegia</comment>
- <comment xml:lang="fi">jaettu libtool-kirjasto</comment>
- <comment xml:lang="fo">libtool felagssavn</comment>
- <comment xml:lang="fr">bibliothèque partagée libtool</comment>
- <comment xml:lang="ga">comhleabharlann libtool</comment>
- <comment xml:lang="gl">biblioteca compartida de libtool</comment>
- <comment xml:lang="he">ספרייה משותפת של libtool</comment>
- <comment xml:lang="hr">libtool dijeljena biblioteka</comment>
- <comment xml:lang="hu">libtool osztott programkönyvtár</comment>
- <comment xml:lang="ia">Bibliotheca commun Libtool</comment>
- <comment xml:lang="id">pustaka bersama libtool</comment>
- <comment xml:lang="it">Libreria condivisa libtool</comment>
- <comment xml:lang="ja">libtool 共有ライブラリ</comment>
- <comment xml:lang="kk">libtool ортақ жинағы</comment>
- <comment xml:lang="ko">libtool 공유 라이브러리</comment>
- <comment xml:lang="lt">libtool bendroji biblioteka</comment>
- <comment xml:lang="lv">libtool koplietotā bibliotēka</comment>
- <comment xml:lang="nb">libtool delt bibliotek</comment>
- <comment xml:lang="nl">gedeelde libtool-bibliotheek</comment>
- <comment xml:lang="nn">libtool delt bibliotek</comment>
- <comment xml:lang="oc">bibliotèca partejada libtool</comment>
- <comment xml:lang="pl">Biblioteka współdzielona libtool</comment>
- <comment xml:lang="pt">biblioteca partilhada libtool</comment>
- <comment xml:lang="pt_BR">Biblioteca compartilhada libtool</comment>
- <comment xml:lang="ro">bibliotecă partajată libtool</comment>
- <comment xml:lang="ru">Разделяемая библиотека libtool</comment>
- <comment xml:lang="sk">Zdieľaná knižnica libtool</comment>
- <comment xml:lang="sl">Souporabna knjižnica libtool</comment>
- <comment xml:lang="sq">Librari e përbashkët libtool</comment>
- <comment xml:lang="sr">дељена библиотека библ-алата</comment>
- <comment xml:lang="sv">delat libtool-bibliotek</comment>
- <comment xml:lang="tr">libtool paylaşımlı kitaplığı</comment>
+ <comment>Libtool shared library</comment>
<comment xml:lang="uk">спільна бібліотека libtool</comment>
- <comment xml:lang="vi">thư viện dùng chung libtool</comment>
- <comment xml:lang="zh_CN">libtool 共享库</comment>
- <comment xml:lang="zh_TW">libtool 共享函式庫</comment>
+ <comment xml:lang="sv">Delat libtool-bibliotek</comment>
+ <comment xml:lang="ru">Разделяемая библиотека libtool</comment>
+ <comment xml:lang="pl">Biblioteka współdzielona libtool</comment>
+ <comment xml:lang="it">Libreria condivisa libtool</comment>
+ <comment xml:lang="eu">Libtool liburutegi partekatua</comment>
+ <comment xml:lang="es">biblioteca compartida de Libtool</comment>
+ <comment xml:lang="de">Gemeinsame libtool-Bibliothek</comment>
+ <comment xml:lang="be">агульная бібліятэка libtool</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.la"/>
</mime-type>
<mime-type type="application/x-sharedlib">
- <comment>shared library</comment>
- <comment xml:lang="ar">مكتبة مشتركة</comment>
- <comment xml:lang="az">bölüşülmüş kitabxana</comment>
- <comment xml:lang="be@latin">supolnaja biblijateka</comment>
- <comment xml:lang="bg">Споделена библиотека</comment>
- <comment xml:lang="ca">biblioteca compartida</comment>
- <comment xml:lang="cs">sdílená knihovna</comment>
- <comment xml:lang="cy">llyfrgell wedi ei rhannu</comment>
- <comment xml:lang="da">delt bibliotek</comment>
- <comment xml:lang="de">Gemeinsame Bibliothek</comment>
- <comment xml:lang="el">Αρχείο κοινόχρηστης βιβλιοθήκης</comment>
- <comment xml:lang="en_GB">shared library</comment>
- <comment xml:lang="eo">dinamike bindebla biblioteko</comment>
- <comment xml:lang="es">biblioteca compartida</comment>
- <comment xml:lang="eu">partekatutako liburutegia</comment>
- <comment xml:lang="fi">jaettu kirjasto</comment>
- <comment xml:lang="fo">felagssavn</comment>
- <comment xml:lang="fr">bibliothèque partagée</comment>
- <comment xml:lang="ga">comhleabharlann</comment>
- <comment xml:lang="gl">biblioteca compartida</comment>
- <comment xml:lang="he">ספרייה משותפת</comment>
- <comment xml:lang="hr">dijeljena biblioteka</comment>
- <comment xml:lang="hu">osztott programkönyvtár</comment>
- <comment xml:lang="ia">Bibliotheca commun</comment>
- <comment xml:lang="id">pustaka bersama</comment>
- <comment xml:lang="it">Libreria condivisa</comment>
- <comment xml:lang="ja">共有ライブラリ</comment>
- <comment xml:lang="kk">бөлісетін библиотека</comment>
- <comment xml:lang="ko">공유 라이브러리</comment>
- <comment xml:lang="lt">bendroji biblioteka</comment>
- <comment xml:lang="lv">koplietotā bibliotēka</comment>
- <comment xml:lang="ms">Pustaka terkongsi</comment>
- <comment xml:lang="nb">delt bibliotek</comment>
- <comment xml:lang="nl">gedeelde bibliotheek</comment>
- <comment xml:lang="nn">delt bibliotek</comment>
- <comment xml:lang="oc">bibliotèca partejada</comment>
- <comment xml:lang="pl">Biblioteka współdzielona</comment>
- <comment xml:lang="pt">biblioteca partilhada</comment>
- <comment xml:lang="pt_BR">Biblioteca compartilhada</comment>
- <comment xml:lang="ro">bibliotecă partajată</comment>
- <comment xml:lang="ru">Разделяемая библиотека</comment>
- <comment xml:lang="sk">Zdieľaná knižnica</comment>
- <comment xml:lang="sl">souporabljena knjižnica</comment>
- <comment xml:lang="sq">Librari e përbashkët</comment>
- <comment xml:lang="sr">дељена библиотека</comment>
- <comment xml:lang="sv">delat bibliotek</comment>
- <comment xml:lang="tr">paylaşımlı kitaplık</comment>
+ <comment>Shared library</comment>
<comment xml:lang="uk">спільна бібліотека</comment>
- <comment xml:lang="vi">thư viện dùng chung</comment>
- <comment xml:lang="zh_CN">共享库</comment>
- <comment xml:lang="zh_TW">共享函式庫</comment>
- <magic priority="50">
- <match value="\177ELF" type="string" offset="0">
- <match value="1" type="byte" offset="5">
- <match value="3" type="little16" offset="16"/>
- </match>
- </match>
- <match value="\177ELF" type="string" offset="0">
- <match value="2" type="byte" offset="5">
- <match value="3" type="big16" offset="16"/>
- </match>
- </match>
- <match value="0603" type="little16" offset="0">
- <match value="020000" type="little16" offset="22" mask="030000"/>
+ <comment xml:lang="sv">Delat bibliotek</comment>
+ <comment xml:lang="ru">Разделяемая библиотека</comment>
+ <comment xml:lang="pl">Biblioteka współdzielona</comment>
+ <comment xml:lang="ja">共有ライブラリ</comment>
+ <comment xml:lang="it">Libreria condivisa</comment>
+ <comment xml:lang="gl">Biblioteca compartida</comment>
+ <comment xml:lang="eu">Liburutegi partekatua</comment>
+ <comment xml:lang="es">biblioteca compartida</comment>
+ <comment xml:lang="de">Gemeinsam genutzte Bibliothek</comment>
+ <comment xml:lang="be">агульная бібліятэка</comment>
+ <magic>
+ <match type="little16" value="0603" offset="0">
+ <match type="little16" mask="030000" value="020000" offset="22"/>
</match>
- <match value="\177ELF \003" type="string" offset="0" mask="0xffffffff000000000000000000000000ff"/>
</magic>
<glob pattern="*.so"/>
+ <glob weight="60" pattern="*.so.[0-9]*"/>
</mime-type>
<mime-type type="application/x-shellscript">
- <comment>shell script</comment>
- <comment xml:lang="ar">سكربت شِل</comment>
- <comment xml:lang="az">qabıq skripti</comment>
- <comment xml:lang="be@latin">skrypt abałonki</comment>
- <comment xml:lang="bg">Скрипт на обвивката</comment>
- <comment xml:lang="ca">script shell</comment>
- <comment xml:lang="cs">skript shellu</comment>
- <comment xml:lang="cy">sgript plisgyn</comment>
- <comment xml:lang="da">skalprogram</comment>
- <comment xml:lang="de">Shell-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών κελύφους</comment>
- <comment xml:lang="en_GB">shell script</comment>
- <comment xml:lang="eo">ŝelskripto</comment>
- <comment xml:lang="es">secuencia de órdenes en shell</comment>
- <comment xml:lang="eu">shell script-a</comment>
- <comment xml:lang="fi">komentotulkin komentotiedosto</comment>
- <comment xml:lang="fo">skel boðrøð</comment>
- <comment xml:lang="fr">script shell</comment>
- <comment xml:lang="ga">script bhlaoisce</comment>
- <comment xml:lang="gl">script de shell</comment>
- <comment xml:lang="he">תסריט מעטפת</comment>
- <comment xml:lang="hr">Skripta ljuske</comment>
- <comment xml:lang="hu">héj-parancsfájl</comment>
- <comment xml:lang="ia">Script de shell</comment>
- <comment xml:lang="id">skrip shell</comment>
- <comment xml:lang="it">Script shell</comment>
- <comment xml:lang="ja">シェルスクリプト</comment>
- <comment xml:lang="kk">қоршам сценарийі</comment>
- <comment xml:lang="ko">셸 스크립트</comment>
- <comment xml:lang="lt">shell scenarijus</comment>
- <comment xml:lang="lv">čaulas skripts</comment>
- <comment xml:lang="ms">Skrip shell</comment>
- <comment xml:lang="nb">skallskript</comment>
- <comment xml:lang="nl">shellscript</comment>
- <comment xml:lang="nn">skalskript</comment>
- <comment xml:lang="oc">escript shell</comment>
- <comment xml:lang="pl">Skrypt powłoki</comment>
- <comment xml:lang="pt">script de terminal</comment>
- <comment xml:lang="pt_BR">Script shell</comment>
- <comment xml:lang="ro">script shell</comment>
- <comment xml:lang="ru">Сценарий shell</comment>
- <comment xml:lang="sk">Skript shellu</comment>
- <comment xml:lang="sl">lupinski skript</comment>
- <comment xml:lang="sq">Script shell</comment>
- <comment xml:lang="sr">скрипта љуске</comment>
- <comment xml:lang="sv">skalskript</comment>
- <comment xml:lang="tr">kabuk betiği</comment>
+ <comment>Shell script</comment>
<comment xml:lang="uk">скрипт оболонки</comment>
- <comment xml:lang="vi">văn lệnh trình bao</comment>
- <comment xml:lang="zh_CN">shell 脚本</comment>
- <comment xml:lang="zh_TW">shell 指令稿</comment>
+ <comment xml:lang="sv">Skalskript</comment>
+ <comment xml:lang="ru">Сценарий shell</comment>
+ <comment xml:lang="pl">Skrypt powłoki</comment>
+ <comment xml:lang="it">Script shell</comment>
+ <comment xml:lang="eu">Shell scripta</comment>
+ <comment xml:lang="es">secuencia de órdenes de consola</comment>
+ <comment xml:lang="de">Shell-Skript</comment>
+ <comment xml:lang="be">скрыпт абалонкі</comment>
<sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
<alias type="text/x-sh"/>
<generic-icon name="text-x-script"/>
- <magic priority="50">
- <match value="# This is a shell archive" type="string" offset="10"/>
- <match value="/bin/bash" type="string" offset="2:16"/>
- <match value="/bin/nawk" type="string" offset="2:16"/>
- <match value="/bin/zsh" type="string" offset="2:16"/>
- <match value="/bin/sh" type="string" offset="2:16"/>
- <match value="/bin/ksh" type="string" offset="2:16"/>
- <match value="/bin/dash" type="string" offset="2:16"/>
- <match value="/bin/env sh" type="string" offset="2:16"/>
- <match value="/bin/env bash" type="string" offset="2:16"/>
- <match value="/bin/env zsh" type="string" offset="2:16"/>
- <match value="/bin/env ksh" type="string" offset="2:16"/>
+ <magic>
+ <match type="string" value="# This is a shell archive" offset="10"/>
+ <match type="string" value="/bin/bash" offset="2:16"/>
+ <match type="string" value="/bin/nawk" offset="2:16"/>
+ <match type="string" value="/bin/zsh" offset="2:16"/>
+ <match type="string" value="/bin/sh" offset="2:16"/>
+ <match type="string" value="/bin/ksh" offset="2:16"/>
+ <match type="string" value="/bin/dash" offset="2:16"/>
+ <match type="string" value="/bin/env sh" offset="2:16"/>
+ <match type="string" value="/bin/env bash" offset="2:16"/>
+ <match type="string" value="/bin/env zsh" offset="2:16"/>
+ <match type="string" value="/bin/env ksh" offset="2:16"/>
</magic>
<glob pattern="*.sh"/>
</mime-type>
+ <mime-type type="application/x-fishscript">
+ <comment>Fish shell script</comment>
+ <comment xml:lang="uk">скрипт оболонки fish</comment>
+ <comment xml:lang="sv">Fish-skalskript</comment>
+ <comment xml:lang="ru">Сценарий fish shell</comment>
+ <comment xml:lang="pl">Skrypt powłoki Fish</comment>
+ <comment xml:lang="it">Script shell Fish</comment>
+ <comment xml:lang="eu">Fish shell scripta</comment>
+ <comment xml:lang="es">secuencia de órdenes de consola Fish</comment>
+ <comment xml:lang="de">Fish-Shell-Skript</comment>
+ <comment xml:lang="be">скрыпт Fish shell</comment>
+ <sub-class-of type="application/x-executable"/>
+ <sub-class-of type="text/plain"/>
+ <alias type="text/x-fish"/>
+ <generic-icon name="text-x-script"/>
+ <magic>
+ <match type="string" value="/bin/env fish" offset="2:16"/>
+ </magic>
+ <glob pattern="*.fish"/>
+ </mime-type>
+ <mime-type type="application/x-nuscript">
+ <comment>Nu shell script</comment>
+ <comment xml:lang="uk">скрипт оболонки nu</comment>
+ <comment xml:lang="sv">Nu-skalskript</comment>
+ <comment xml:lang="ru">Сценарий nu shell</comment>
+ <comment xml:lang="pl">Skrypt powłoki Nu</comment>
+ <comment xml:lang="it">Script shell Nu</comment>
+ <comment xml:lang="eu">Nu shell scripta</comment>
+ <comment xml:lang="es">secuencia de órdenes de consola Nu</comment>
+ <comment xml:lang="de">Nu-Shell-Skript</comment>
+ <comment xml:lang="be">скрыпт Nu shell</comment>
+ <sub-class-of type="application/x-executable"/>
+ <sub-class-of type="text/plain"/>
+ <alias type="text/x-nu"/>
+ <generic-icon name="text-x-script"/>
+ <magic>
+ <match type="string" value="/bin/env nu" offset="2:16"/>
+ </magic>
+ <glob pattern="*.nu"/>
+ </mime-type>
<mime-type type="application/vnd.adobe.flash.movie">
<comment>Shockwave Flash file</comment>
- <comment xml:lang="ar">ملف Shockwave Flash</comment>
- <comment xml:lang="be@latin">Fajł Shockwave Flash</comment>
- <comment xml:lang="bg">Файл — Shockwave Flash</comment>
- <comment xml:lang="ca">fitxer Shockwave Flash</comment>
- <comment xml:lang="cs">soubor Shockwave Flash</comment>
- <comment xml:lang="da">Shockwave Flash-fil</comment>
- <comment xml:lang="de">Shockwave-Flash-Datei</comment>
- <comment xml:lang="el">Αρχείο Shockwave Flash</comment>
- <comment xml:lang="en_GB">Shockwave Flash file</comment>
- <comment xml:lang="eo">dosiero de Shockwave Flash</comment>
- <comment xml:lang="es">archivo Shockwave Flash</comment>
- <comment xml:lang="eu">Shockwave Flash fitxategia</comment>
- <comment xml:lang="fi">Shockwave Flash -tiedosto</comment>
- <comment xml:lang="fo">Shockwave Flash fíla</comment>
- <comment xml:lang="fr">fichier Shockwave Flash</comment>
- <comment xml:lang="ga">comhad Shockwave Flash</comment>
- <comment xml:lang="gl">ficheiro sockwave Flash</comment>
- <comment xml:lang="he">קובץ של Shockwave Flash</comment>
- <comment xml:lang="hr">Shockwave Flash datoteka</comment>
- <comment xml:lang="hu">Shockwave Flash-fájl</comment>
- <comment xml:lang="ia">File Shockwave Flash</comment>
- <comment xml:lang="id">Berkas Shockwave Flash</comment>
- <comment xml:lang="it">File Shockwave Flash</comment>
- <comment xml:lang="ja">Shockwave Flash ファイル</comment>
- <comment xml:lang="kk">Shockwave Flash файлы</comment>
- <comment xml:lang="ko">Shockwave 플래시 파일</comment>
- <comment xml:lang="lt">Shockwave Flash failas</comment>
- <comment xml:lang="lv">Shockwave Flash datne</comment>
- <comment xml:lang="ms">Fail Shockwave Flash</comment>
- <comment xml:lang="nb">Shockwave Flash-fil</comment>
- <comment xml:lang="nl">Shockwave Flash-bestand</comment>
- <comment xml:lang="nn">Shockwave Flash-fil</comment>
- <comment xml:lang="oc">fichièr Shockwave Flash</comment>
- <comment xml:lang="pl">Plik Shockwave Flash</comment>
- <comment xml:lang="pt">ficheiro Shockwave Flash</comment>
- <comment xml:lang="pt_BR">Arquivo Shockwave Flash</comment>
- <comment xml:lang="ro">Fișier Shockwave Flash</comment>
- <comment xml:lang="ru">Файл Shockwave Flash</comment>
- <comment xml:lang="sk">Súbor Shockwave Flash</comment>
- <comment xml:lang="sl">Datoteka Shockwave Flash</comment>
- <comment xml:lang="sq">File Flash Shockwave</comment>
- <comment xml:lang="sr">Шоквејв Флеш датотека</comment>
- <comment xml:lang="sv">Shockwave Flash-fil</comment>
- <comment xml:lang="tr">Shockwave Flash dosyası</comment>
- <comment xml:lang="uk">файл Shockwave Flash</comment>
- <comment xml:lang="vi">Tập tin Flash Shockwave</comment>
- <comment xml:lang="zh_CN">Shockwave Flash 文件</comment>
<comment xml:lang="zh_TW">Shockwave Flash 檔案</comment>
+ <comment xml:lang="zh_CN">Shockwave Flash 文件</comment>
+ <comment xml:lang="vi">Tập tin Flash Shockwave</comment>
+ <comment xml:lang="uk">файл Shockwave Flash</comment>
+ <comment xml:lang="tr">Shockwave Flash dosyası</comment>
+ <comment xml:lang="sv">Shockwave Flash-fil</comment>
+ <comment xml:lang="sr">Шоквејв Флеш датотека</comment>
+ <comment xml:lang="sq">kartelë Shockwave Flash</comment>
+ <comment xml:lang="sl">Datoteka Shockwave Flash</comment>
+ <comment xml:lang="si">කම්පන තරංග ෆ්ලෑෂ් ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Shockwave Flash</comment>
+ <comment xml:lang="ru">Файл Shockwave Flash</comment>
+ <comment xml:lang="ro">Fișier Shockwave Flash</comment>
+ <comment xml:lang="pt_BR">Arquivo Shockwave Flash</comment>
+ <comment xml:lang="pt">ficheiro Shockwave Flash</comment>
+ <comment xml:lang="pl">Plik Shockwave Flash</comment>
+ <comment xml:lang="oc">fichièr Shockwave Flash</comment>
+ <comment xml:lang="nn">Shockwave Flash-fil</comment>
+ <comment xml:lang="nl">Shockwave Flash-bestand</comment>
+ <comment xml:lang="nb">Shockwave Flash-fil</comment>
+ <comment xml:lang="ms">Fail Shockwave Flash</comment>
+ <comment xml:lang="lv">Shockwave Flash datne</comment>
+ <comment xml:lang="lt">Shockwave Flash failas</comment>
+ <comment xml:lang="ko">Shockwave 플래시 파일</comment>
+ <comment xml:lang="kk">Shockwave Flash файлы</comment>
+ <comment xml:lang="ja">Shockwave Flash ファイル</comment>
+ <comment xml:lang="it">File Shockwave Flash</comment>
+ <comment xml:lang="is">Shockwave Flash skrá</comment>
+ <comment xml:lang="id">Berkas Shockwave Flash</comment>
+ <comment xml:lang="ia">File Shockwave Flash</comment>
+ <comment xml:lang="hu">Shockwave Flash-fájl</comment>
+ <comment xml:lang="hr">Shockwave Flash datoteka</comment>
+ <comment xml:lang="he">קובץ של Shockwave Flash</comment>
+ <comment xml:lang="gl">ficheiro sockwave Flash</comment>
+ <comment xml:lang="ga">comhad Shockwave Flash</comment>
+ <comment xml:lang="fur">file Shockwave Flash</comment>
+ <comment xml:lang="fr">fichier Shockwave Flash</comment>
+ <comment xml:lang="fo">Shockwave Flash fíla</comment>
+ <comment xml:lang="fi">Shockwave Flash -tiedosto</comment>
+ <comment xml:lang="eu">Shockwave Flash fitxategia</comment>
+ <comment xml:lang="es">archivo Shockwave Flash</comment>
+ <comment xml:lang="eo">dosiero de Shockwave Flash</comment>
+ <comment xml:lang="en_GB">Shockwave Flash file</comment>
+ <comment xml:lang="el">Αρχείο Shockwave Flash</comment>
+ <comment xml:lang="de">Shockwave-Flash-Datei</comment>
+ <comment xml:lang="da">Shockwave Flash-fil</comment>
+ <comment xml:lang="cs">soubor Shockwave Flash</comment>
+ <comment xml:lang="ca">fitxer Shockwave Flash</comment>
+ <comment xml:lang="bg">Файл — Shockwave Flash</comment>
+ <comment xml:lang="be@latin">Fajł Shockwave Flash</comment>
+ <comment xml:lang="be">файл Shockwave Flash</comment>
+ <comment xml:lang="ar">ملف Shockwave Flash</comment>
+ <comment xml:lang="af">Shockwave Flash-lêer</comment>
<alias type="application/x-shockwave-flash"/>
<alias type="application/futuresplash"/>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
- <match value="FWS" type="string" offset="0"/>
- <match value="CWS" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="FWS" offset="0"/>
+ <match type="string" value="CWS" offset="0"/>
</magic>
<glob pattern="*.swf"/>
<glob pattern="*.spl"/>
</mime-type>
<mime-type type="application/x-shorten">
-
+ <!-- translators: "Shorten" is the name of an audio codec -->
<comment>Shorten audio</comment>
- <comment xml:lang="ar">Shorten سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Shorten</comment>
- <comment xml:lang="bg">Аудио — Shorten</comment>
- <comment xml:lang="ca">àudio de Shorten</comment>
- <comment xml:lang="cs">zvuk Shorten</comment>
- <comment xml:lang="da">Shortenlyd</comment>
- <comment xml:lang="de">Shorten-Audio</comment>
- <comment xml:lang="el">Ήχος Shorten</comment>
- <comment xml:lang="en_GB">Shorten audio</comment>
- <comment xml:lang="eo">Shorten-sondosiero</comment>
- <comment xml:lang="es">sonido Shorten</comment>
- <comment xml:lang="eu">Shorten audioa</comment>
- <comment xml:lang="fi">Shorten-ääni</comment>
- <comment xml:lang="fo">Shorten ljóður</comment>
- <comment xml:lang="fr">audio Shorten</comment>
- <comment xml:lang="ga">fuaim Shorten</comment>
- <comment xml:lang="gl">son Shorten</comment>
- <comment xml:lang="he">שמע של Shorten</comment>
- <comment xml:lang="hr">Shorten zvučni zapis</comment>
- <comment xml:lang="hu">Shorten hang</comment>
- <comment xml:lang="ia">Audio Shorten</comment>
- <comment xml:lang="id">Audio Shorten</comment>
- <comment xml:lang="it">Audio Shorten</comment>
- <comment xml:lang="ja">Shorten オーディオ</comment>
- <comment xml:lang="kk">Shorten аудиосы</comment>
- <comment xml:lang="ko">Shorten 오디오</comment>
- <comment xml:lang="lt">Shorten garso įrašas</comment>
- <comment xml:lang="lv">Shorten audio</comment>
- <comment xml:lang="nb">Shorten lyd</comment>
- <comment xml:lang="nl">Shorten-audio</comment>
- <comment xml:lang="nn">Shorten-lyd</comment>
- <comment xml:lang="oc">àudio Shorten</comment>
- <comment xml:lang="pl">Plik dźwiękowy Shorten</comment>
- <comment xml:lang="pt">áudio Shorten</comment>
- <comment xml:lang="pt_BR">Áudio Shorten</comment>
- <comment xml:lang="ro">Audio Shorten</comment>
- <comment xml:lang="ru">Аудио Shorten</comment>
- <comment xml:lang="sk">Zvuk Shorten</comment>
- <comment xml:lang="sl">Zvočna datoteka Shorten</comment>
- <comment xml:lang="sq">Audio Shorten</comment>
- <comment xml:lang="sr">Шортен звук</comment>
- <comment xml:lang="sv">Shorten-ljud</comment>
- <comment xml:lang="tr">Kısaltılmış ses</comment>
- <comment xml:lang="uk">звук Shorten</comment>
- <comment xml:lang="vi">Âm thanh Shorten</comment>
- <comment xml:lang="zh_CN">Shorten 音频</comment>
<comment xml:lang="zh_TW">Shorten 音訊</comment>
+ <comment xml:lang="zh_CN">Shorten 音频</comment>
+ <comment xml:lang="vi">Âm thanh Shorten</comment>
+ <comment xml:lang="uk">звук Shorten</comment>
+ <comment xml:lang="tr">Shorten sesi</comment>
+ <comment xml:lang="sv">Shorten-ljud</comment>
+ <comment xml:lang="sr">Шортен звук</comment>
+ <comment xml:lang="sq">audio Shorten</comment>
+ <comment xml:lang="sl">Zvočna datoteka Shorten</comment>
+ <comment xml:lang="si">ශ්රව්ය උපකරණ කෙටි කරන්න</comment>
+ <comment xml:lang="sk">Zvuk Shorten</comment>
+ <comment xml:lang="ru">Аудио Shorten</comment>
+ <comment xml:lang="ro">Audio Shorten</comment>
+ <comment xml:lang="pt_BR">Áudio Shorten</comment>
+ <comment xml:lang="pt">áudio Shorten</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Shorten</comment>
+ <comment xml:lang="oc">àudio Shorten</comment>
+ <comment xml:lang="nn">Shorten-lyd</comment>
+ <comment xml:lang="nl">Shorten-audio</comment>
+ <comment xml:lang="nb">Shorten lyd</comment>
+ <comment xml:lang="lv">Shorten audio</comment>
+ <comment xml:lang="lt">Shorten garso įrašas</comment>
+ <comment xml:lang="ko">Shorten 오디오</comment>
+ <comment xml:lang="kk">Shorten аудиосы</comment>
+ <comment xml:lang="ja">Shorten オーディオ</comment>
+ <comment xml:lang="it">Audio Shorten</comment>
+ <comment xml:lang="is">Shorten hljóðskrá</comment>
+ <comment xml:lang="id">Audio Shorten</comment>
+ <comment xml:lang="ia">Audio Shorten</comment>
+ <comment xml:lang="hu">Shorten hang</comment>
+ <comment xml:lang="hr">Shorten zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Shorten</comment>
+ <comment xml:lang="gl">son Shorten</comment>
+ <comment xml:lang="ga">fuaim Shorten</comment>
+ <comment xml:lang="fur">audio Shorten</comment>
+ <comment xml:lang="fr">audio Shorten</comment>
+ <comment xml:lang="fo">Shorten ljóður</comment>
+ <comment xml:lang="fi">Shorten-ääni</comment>
+ <comment xml:lang="eu">Shorten audioa</comment>
+ <comment xml:lang="es">audio Shorten</comment>
+ <comment xml:lang="eo">Shorten-sondosiero</comment>
+ <comment xml:lang="en_GB">Shorten audio</comment>
+ <comment xml:lang="el">Ήχος Shorten</comment>
+ <comment xml:lang="de">Shorten-Audio</comment>
+ <comment xml:lang="da">Shorten-lyd</comment>
+ <comment xml:lang="cs">zvuk Shorten</comment>
+ <comment xml:lang="ca">àudio de Shorten</comment>
+ <comment xml:lang="bg">Аудио — Shorten</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Shorten</comment>
+ <comment xml:lang="be">аўдыя Shorten</comment>
+ <comment xml:lang="ar">صوت Shorten</comment>
+ <comment xml:lang="af">Shorten-oudio</comment>
<generic-icon name="audio-x-generic"/>
- <magic priority="50">
- <match value="ajkg" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="ajkg" offset="0"/>
</magic>
<glob pattern="*.shn"/>
<alias type="audio/x-shorten"/>
</mime-type>
<mime-type type="application/x-siag">
<comment>Siag spreadsheet</comment>
- <comment xml:lang="ar">جدول Siag</comment>
- <comment xml:lang="be@latin">Raźlikovy arkuš Siag</comment>
- <comment xml:lang="bg">Таблица — Siag</comment>
- <comment xml:lang="ca">full de càlcul Siag</comment>
- <comment xml:lang="cs">sešit Siag</comment>
- <comment xml:lang="da">Siagregneark</comment>
- <comment xml:lang="de">Siag-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Siag</comment>
- <comment xml:lang="en_GB">Siag spreadsheet</comment>
- <comment xml:lang="eo">Siag-kalkultabelo</comment>
- <comment xml:lang="es">hoja de cálculo de Siag</comment>
- <comment xml:lang="eu">Siag kalkulu-orria</comment>
- <comment xml:lang="fi">Siag-taulukko</comment>
- <comment xml:lang="fo">Siag rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Siag</comment>
- <comment xml:lang="ga">scarbhileog Siag</comment>
- <comment xml:lang="gl">folla de cálculo de Siag</comment>
- <comment xml:lang="he">גליון נתונים של Siag</comment>
- <comment xml:lang="hr">Siag proračunska tablica</comment>
- <comment xml:lang="hu">Siag-munkafüzet</comment>
- <comment xml:lang="ia">Folio de calculo Siag</comment>
- <comment xml:lang="id">Lembar sebar Siag</comment>
- <comment xml:lang="it">Foglio di calcolo Siag</comment>
- <comment xml:lang="ja">Siag スプレッドシート</comment>
- <comment xml:lang="kk">Siag электрондық кестесі</comment>
- <comment xml:lang="ko">Siag 스프레드시트</comment>
- <comment xml:lang="lt">Siag skaičialentė</comment>
- <comment xml:lang="lv">Siag izklājlapa</comment>
- <comment xml:lang="ms">Hamparan Siag</comment>
- <comment xml:lang="nb">Siag-regneark</comment>
- <comment xml:lang="nl">Siag-rekenblad</comment>
- <comment xml:lang="nn">Siag-rekneark</comment>
- <comment xml:lang="oc">fuèlh de calcul Siag</comment>
- <comment xml:lang="pl">Arkusz Siag</comment>
- <comment xml:lang="pt">folha de cálculo Siag</comment>
- <comment xml:lang="pt_BR">Planilha do Siag</comment>
- <comment xml:lang="ro">Foaie de calcul Siag</comment>
- <comment xml:lang="ru">Электронная таблица Siag</comment>
- <comment xml:lang="sk">Zošit Siag</comment>
- <comment xml:lang="sl">Preglednica Siag</comment>
- <comment xml:lang="sq">Fletë llogaritjesh Siag</comment>
- <comment xml:lang="sr">Сјаг табела</comment>
- <comment xml:lang="sv">Siag-kalkylblad</comment>
- <comment xml:lang="tr">Siag çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Siag</comment>
- <comment xml:lang="vi">Bảng tính Slag</comment>
- <comment xml:lang="zh_CN">Siag 电子表格</comment>
<comment xml:lang="zh_TW">Siag 試算表</comment>
+ <comment xml:lang="zh_CN">Siag 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Slag</comment>
+ <comment xml:lang="uk">електронна таблиця Siag</comment>
+ <comment xml:lang="tr">Siag hesap çizelgesi</comment>
+ <comment xml:lang="sv">Siag-kalkylblad</comment>
+ <comment xml:lang="sr">Сјаг табела</comment>
+ <comment xml:lang="sq">fletëllogaritje Siag</comment>
+ <comment xml:lang="sl">Preglednica Siag</comment>
+ <comment xml:lang="si">Siag පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Siag</comment>
+ <comment xml:lang="ru">Электронная таблица Siag</comment>
+ <comment xml:lang="ro">Foaie de calcul Siag</comment>
+ <comment xml:lang="pt_BR">Planilha do Siag</comment>
+ <comment xml:lang="pt">folha de cálculo Siag</comment>
+ <comment xml:lang="pl">Arkusz Siag</comment>
+ <comment xml:lang="oc">fuèlh de calcul Siag</comment>
+ <comment xml:lang="nn">Siag-rekneark</comment>
+ <comment xml:lang="nl">Siag-rekenblad</comment>
+ <comment xml:lang="nb">Siag-regneark</comment>
+ <comment xml:lang="ms">Hamparan Siag</comment>
+ <comment xml:lang="lv">Siag izklājlapa</comment>
+ <comment xml:lang="lt">Siag skaičialentė</comment>
+ <comment xml:lang="ko">Siag 스프레드시트</comment>
+ <comment xml:lang="kk">Siag электрондық кестесі</comment>
+ <comment xml:lang="ja">Siag スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Siag</comment>
+ <comment xml:lang="is">Siag töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Siag</comment>
+ <comment xml:lang="ia">Folio de calculo Siag</comment>
+ <comment xml:lang="hu">Siag-munkafüzet</comment>
+ <comment xml:lang="hr">Siag proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Siag</comment>
+ <comment xml:lang="gl">folla de cálculo de Siag</comment>
+ <comment xml:lang="ga">scarbhileog Siag</comment>
+ <comment xml:lang="fur">sfuei di calcul Siag</comment>
+ <comment xml:lang="fr">feuille de calcul Siag</comment>
+ <comment xml:lang="fo">Siag rokniark</comment>
+ <comment xml:lang="fi">Siag-taulukko</comment>
+ <comment xml:lang="eu">Siag kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Siag</comment>
+ <comment xml:lang="eo">Siag-kalkultabelo</comment>
+ <comment xml:lang="en_GB">Siag spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Siag</comment>
+ <comment xml:lang="de">Siag-Tabelle</comment>
+ <comment xml:lang="da">Siagregneark</comment>
+ <comment xml:lang="cs">sešit Siag</comment>
+ <comment xml:lang="ca">full de càlcul Siag</comment>
+ <comment xml:lang="bg">Таблица — Siag</comment>
+ <comment xml:lang="be@latin">Raźlikovy arkuš Siag</comment>
+ <comment xml:lang="be">электронная табліца Siag</comment>
+ <comment xml:lang="ar">جدول Siag</comment>
+ <comment xml:lang="af">Siag-sigblad</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.siag"/>
</mime-type>
<mime-type type="image/x-skencil">
<comment>Skencil document</comment>
- <comment xml:lang="ar">مستند Skencil</comment>
- <comment xml:lang="ast">Documentu de Skencil</comment>
- <comment xml:lang="be@latin">Dakument Skencil</comment>
- <comment xml:lang="bg">Документ — Skencil</comment>
- <comment xml:lang="ca">document Skencil</comment>
- <comment xml:lang="cs">dokument Skencil</comment>
- <comment xml:lang="da">Skencildokument</comment>
- <comment xml:lang="de">Skencil-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Skencil</comment>
- <comment xml:lang="en_GB">Skencil document</comment>
- <comment xml:lang="eo">Skencil-dokumento</comment>
- <comment xml:lang="es">documento de Skencil</comment>
- <comment xml:lang="eu">Skencil dokumentua</comment>
- <comment xml:lang="fi">Skencil-asiakirja</comment>
- <comment xml:lang="fo">Skencil skjal</comment>
- <comment xml:lang="fr">document Skencil</comment>
- <comment xml:lang="ga">cáipéis Skencil</comment>
- <comment xml:lang="gl">documento Skencil</comment>
- <comment xml:lang="he">מסמך Skencil</comment>
- <comment xml:lang="hr">Skencil dokument</comment>
- <comment xml:lang="hu">Skencil-dokumentum</comment>
- <comment xml:lang="ia">Documento Skencil</comment>
- <comment xml:lang="id">Dokumen Skencil</comment>
- <comment xml:lang="it">Documento Skencil</comment>
- <comment xml:lang="ja">Skencil ドキュメント</comment>
- <comment xml:lang="kk">Skencil құжаты</comment>
- <comment xml:lang="ko">Skencil 문서</comment>
- <comment xml:lang="lt">Skencil dokumentas</comment>
- <comment xml:lang="lv">Skencil dokuments</comment>
- <comment xml:lang="nl">Skencil-document</comment>
- <comment xml:lang="nn">Skencil-dokument</comment>
- <comment xml:lang="oc">document Skencil</comment>
- <comment xml:lang="pl">Dokument Skencil</comment>
- <comment xml:lang="pt">documento Skencil</comment>
- <comment xml:lang="pt_BR">Documento do Skencil</comment>
- <comment xml:lang="ro">Document Skencil</comment>
- <comment xml:lang="ru">Документ Skencil</comment>
- <comment xml:lang="sk">Dokument Skencil</comment>
- <comment xml:lang="sl">Dokument Skencil</comment>
- <comment xml:lang="sq">Dokument Skencil</comment>
- <comment xml:lang="sr">Скенцил документ</comment>
- <comment xml:lang="sv">Skencil-dokument</comment>
- <comment xml:lang="tr">Skencil belgesi</comment>
- <comment xml:lang="uk">документ Skencil</comment>
- <comment xml:lang="vi">Tài liệu Skencil</comment>
- <comment xml:lang="zh_CN">Skencil 文档</comment>
<comment xml:lang="zh_TW">Skencil 文件</comment>
+ <comment xml:lang="zh_CN">Skencil 文档</comment>
+ <comment xml:lang="vi">Tài liệu Skencil</comment>
+ <comment xml:lang="uk">документ Skencil</comment>
+ <comment xml:lang="tr">Skencil belgesi</comment>
+ <comment xml:lang="sv">Skencil-dokument</comment>
+ <comment xml:lang="sr">Скенцил документ</comment>
+ <comment xml:lang="sq">dokument Skencil</comment>
+ <comment xml:lang="sl">Dokument Skencil</comment>
+ <comment xml:lang="si">ස්කෙන්සිල් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Skencil</comment>
+ <comment xml:lang="ru">Документ Skencil</comment>
+ <comment xml:lang="ro">Document Skencil</comment>
+ <comment xml:lang="pt_BR">Documento do Skencil</comment>
+ <comment xml:lang="pt">documento Skencil</comment>
+ <comment xml:lang="pl">Dokument Skencil</comment>
+ <comment xml:lang="oc">document Skencil</comment>
+ <comment xml:lang="nn">Skencil-dokument</comment>
+ <comment xml:lang="nl">Skencil-document</comment>
+ <comment xml:lang="lv">Skencil dokuments</comment>
+ <comment xml:lang="lt">Skencil dokumentas</comment>
+ <comment xml:lang="ko">Skencil 문서</comment>
+ <comment xml:lang="kk">Skencil құжаты</comment>
+ <comment xml:lang="ja">Skencil ドキュメント</comment>
+ <comment xml:lang="it">Documento Skencil</comment>
+ <comment xml:lang="is">Skencil skjal</comment>
+ <comment xml:lang="id">Dokumen Skencil</comment>
+ <comment xml:lang="ia">Documento Skencil</comment>
+ <comment xml:lang="hu">Skencil-dokumentum</comment>
+ <comment xml:lang="hr">Skencil dokument</comment>
+ <comment xml:lang="he">מסמך Skencil</comment>
+ <comment xml:lang="gl">documento Skencil</comment>
+ <comment xml:lang="ga">cáipéis Skencil</comment>
+ <comment xml:lang="fur">document Skencil</comment>
+ <comment xml:lang="fr">document Skencil</comment>
+ <comment xml:lang="fo">Skencil skjal</comment>
+ <comment xml:lang="fi">Skencil-asiakirja</comment>
+ <comment xml:lang="eu">Skencil dokumentua</comment>
+ <comment xml:lang="es">documento de Skencil</comment>
+ <comment xml:lang="eo">Skencil-dokumento</comment>
+ <comment xml:lang="en_GB">Skencil document</comment>
+ <comment xml:lang="el">Έγγραφο Skencil</comment>
+ <comment xml:lang="de">Skencil-Dokument</comment>
+ <comment xml:lang="da">Skencildokument</comment>
+ <comment xml:lang="cs">dokument Skencil</comment>
+ <comment xml:lang="ca">document Skencil</comment>
+ <comment xml:lang="bg">Документ — Skencil</comment>
+ <comment xml:lang="be@latin">Dakument Skencil</comment>
+ <comment xml:lang="be">дакумент Skencil</comment>
+ <comment xml:lang="ast">Documentu de Skencil</comment>
+ <comment xml:lang="ar">مستند Skencil</comment>
+ <comment xml:lang="af">Skencil-dokument</comment>
<glob pattern="*.sk"/>
<glob pattern="*.sk1"/>
- <magic priority="50">
- <match value="##Sketch" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="##Sketch" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-slp">
<comment>Stampede package</comment>
- <comment xml:lang="ar">حزمة Stampede</comment>
- <comment xml:lang="az">Stampede paketi</comment>
- <comment xml:lang="be@latin">Pakunak Stampede</comment>
- <comment xml:lang="bg">Пакет — Stampede</comment>
- <comment xml:lang="ca">paquet Stampede</comment>
- <comment xml:lang="cs">balíček Stampede</comment>
- <comment xml:lang="cy">Pecyn Stampede</comment>
- <comment xml:lang="da">Stampedepakke</comment>
- <comment xml:lang="de">Stampede-Paket</comment>
- <comment xml:lang="el">Πακέτο Stampede</comment>
- <comment xml:lang="en_GB">Stampede package</comment>
- <comment xml:lang="eo">Stampede-pakaĵo</comment>
- <comment xml:lang="es">paquete Stampede</comment>
- <comment xml:lang="eu">Stampede paketea</comment>
- <comment xml:lang="fi">Stampede-paketti</comment>
- <comment xml:lang="fo">Stampede pakki</comment>
- <comment xml:lang="fr">paquet Stampede</comment>
- <comment xml:lang="ga">pacáiste Stampede</comment>
- <comment xml:lang="gl">paquete Stampede</comment>
- <comment xml:lang="he">חבילה של Stampede</comment>
- <comment xml:lang="hr">Stampede paket</comment>
- <comment xml:lang="hu">Stampede-csomag</comment>
- <comment xml:lang="ia">Pacchetto Stampede</comment>
- <comment xml:lang="id">Paket Stampede</comment>
- <comment xml:lang="it">Pacchetto Stampede</comment>
- <comment xml:lang="ja">Stampede パッケージ</comment>
- <comment xml:lang="kk">Stampede дестесі</comment>
- <comment xml:lang="ko">Stampete 패키지</comment>
- <comment xml:lang="lt">Stampede paketas</comment>
- <comment xml:lang="lv">Stampede pakotne</comment>
- <comment xml:lang="ms">Pakej Stampede</comment>
- <comment xml:lang="nb">Stampede-pakke</comment>
- <comment xml:lang="nl">Stampede-pakket</comment>
- <comment xml:lang="nn">Stampede-pakke</comment>
- <comment xml:lang="oc">paquet Stampede</comment>
- <comment xml:lang="pl">Pakiet Stampede</comment>
- <comment xml:lang="pt">pacote Stampede</comment>
- <comment xml:lang="pt_BR">Pacote Stampede</comment>
- <comment xml:lang="ro">Pachet Stampede</comment>
- <comment xml:lang="ru">Пакет Stampede</comment>
- <comment xml:lang="sk">Balíček Stampede</comment>
- <comment xml:lang="sl">Datoteka paketa Stampede</comment>
- <comment xml:lang="sq">Paketë Stampede</comment>
- <comment xml:lang="sr">Стампеде пакет</comment>
- <comment xml:lang="sv">Stampede-paket</comment>
- <comment xml:lang="tr">Stampede paketi</comment>
- <comment xml:lang="uk">пакунок Stampede</comment>
- <comment xml:lang="vi">Gói Stampede</comment>
- <comment xml:lang="zh_CN">Stampede 软件包</comment>
<comment xml:lang="zh_TW">Stampede 軟體包</comment>
+ <comment xml:lang="zh_CN">Stampede 软件包</comment>
+ <comment xml:lang="vi">Gói Stampede</comment>
+ <comment xml:lang="uk">пакунок Stampede</comment>
+ <comment xml:lang="tr">Stampede paketi</comment>
+ <comment xml:lang="sv">Stampede-paket</comment>
+ <comment xml:lang="sr">Стампеде пакет</comment>
+ <comment xml:lang="sq">paketë Stampede</comment>
+ <comment xml:lang="sl">Datoteka paketa Stampede</comment>
+ <comment xml:lang="si">මුද්දර පැකේජය</comment>
+ <comment xml:lang="sk">Balíček Stampede</comment>
+ <comment xml:lang="ru">Пакет Stampede</comment>
+ <comment xml:lang="ro">Pachet Stampede</comment>
+ <comment xml:lang="pt_BR">Pacote Stampede</comment>
+ <comment xml:lang="pt">pacote Stampede</comment>
+ <comment xml:lang="pl">Pakiet Stampede</comment>
+ <comment xml:lang="oc">paquet Stampede</comment>
+ <comment xml:lang="nn">Stampede-pakke</comment>
+ <comment xml:lang="nl">Stampede-pakket</comment>
+ <comment xml:lang="nb">Stampede-pakke</comment>
+ <comment xml:lang="ms">Pakej Stampede</comment>
+ <comment xml:lang="lv">Stampede pakotne</comment>
+ <comment xml:lang="lt">Stampede paketas</comment>
+ <comment xml:lang="ko">Stampete 패키지</comment>
+ <comment xml:lang="kk">Stampede дестесі</comment>
+ <comment xml:lang="ja">Stampede パッケージ</comment>
+ <comment xml:lang="it">Pacchetto Stampede</comment>
+ <comment xml:lang="is">Stampede pakki</comment>
+ <comment xml:lang="id">Paket Stampede</comment>
+ <comment xml:lang="ia">Pacchetto Stampede</comment>
+ <comment xml:lang="hu">Stampede-csomag</comment>
+ <comment xml:lang="hr">Stampede paket</comment>
+ <comment xml:lang="he">חבילה של Stampede</comment>
+ <comment xml:lang="gl">paquete Stampede</comment>
+ <comment xml:lang="ga">pacáiste Stampede</comment>
+ <comment xml:lang="fur">pachet Stampede</comment>
+ <comment xml:lang="fr">paquet Stampede</comment>
+ <comment xml:lang="fo">Stampede pakki</comment>
+ <comment xml:lang="fi">Stampede-paketti</comment>
+ <comment xml:lang="eu">Stampede paketea</comment>
+ <comment xml:lang="es">paquete Stampede</comment>
+ <comment xml:lang="eo">Stampede-pakaĵo</comment>
+ <comment xml:lang="en_GB">Stampede package</comment>
+ <comment xml:lang="el">Πακέτο Stampede</comment>
+ <comment xml:lang="de">Stampede-Paket</comment>
+ <comment xml:lang="da">Stampedepakke</comment>
+ <comment xml:lang="cy">Pecyn Stampede</comment>
+ <comment xml:lang="cs">balíček Stampede</comment>
+ <comment xml:lang="ca">paquet Stampede</comment>
+ <comment xml:lang="bg">Пакет — Stampede</comment>
+ <comment xml:lang="be@latin">Pakunak Stampede</comment>
+ <comment xml:lang="be">пакет Stampede</comment>
+ <comment xml:lang="az">Stampede paketi</comment>
+ <comment xml:lang="ar">حزمة Stampede</comment>
+ <comment xml:lang="af">Stampede-pakket</comment>
<generic-icon name="package-x-generic"/>
</mime-type>
<mime-type type="application/x-sg1000-rom">
<comment>SG-1000 ROM</comment>
- <comment xml:lang="ca">ROM de SG-1000</comment>
- <comment xml:lang="cs">ROM pro SG-1000</comment>
- <comment xml:lang="da">SG-1000 ROM</comment>
- <comment xml:lang="de">SG-1000 ROM</comment>
- <comment xml:lang="en_GB">SG-1000 ROM</comment>
- <comment xml:lang="es">ROM de SG-1000</comment>
- <comment xml:lang="eu">SG-1000 ROM</comment>
- <comment xml:lang="fi">SG-1000 -ROM</comment>
- <comment xml:lang="fr">ROM SG-1000</comment>
- <comment xml:lang="ga">ROM SG-1000</comment>
- <comment xml:lang="hr">SG-1000 ROM</comment>
- <comment xml:lang="hu">SG-1000 ROM</comment>
- <comment xml:lang="id">ROM SG-1000</comment>
- <comment xml:lang="it">ROM SG-1000</comment>
- <comment xml:lang="kk">SG-1000 ROM</comment>
- <comment xml:lang="ko">SG-1000 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli SG-1000</comment>
- <comment xml:lang="pt_BR">ROM de SG-1000</comment>
- <comment xml:lang="ru">SG-1000 ROM</comment>
- <comment xml:lang="sk">ROM pre SG-1000</comment>
- <comment xml:lang="sr">СГ-1000 РОМ</comment>
- <comment xml:lang="sv">SG-1000-rom</comment>
- <comment xml:lang="tr">SG-1000 ROM</comment>
- <comment xml:lang="uk">ППП SG-1000</comment>
- <comment xml:lang="zh_CN">SG-1000 ROM</comment>
<comment xml:lang="zh_TW">SG-1000 ROM</comment>
+ <comment xml:lang="zh_CN">SG-1000 ROM</comment>
+ <comment xml:lang="uk">ППП SG-1000</comment>
+ <comment xml:lang="tr">SG-1000 ROM</comment>
+ <comment xml:lang="sv">SG-1000-rom</comment>
+ <comment xml:lang="sr">СГ-1000 РОМ</comment>
+ <comment xml:lang="sq">ROM SG-1000</comment>
+ <comment xml:lang="sl">SG-1000 ROM</comment>
+ <comment xml:lang="si">SG-1000 ROM</comment>
+ <comment xml:lang="sk">ROM pre SG-1000</comment>
+ <comment xml:lang="ru">SG-1000 ROM</comment>
+ <comment xml:lang="pt_BR">ROM de SG-1000</comment>
+ <comment xml:lang="pl">Plik ROM konsoli SG-1000</comment>
+ <comment xml:lang="nl">SG-1000-ROM</comment>
+ <comment xml:lang="ko">SG-1000 롬</comment>
+ <comment xml:lang="kk">SG-1000 ROM</comment>
+ <comment xml:lang="ja">SG-1000 ROM</comment>
+ <comment xml:lang="it">ROM SG-1000</comment>
+ <comment xml:lang="is">SG-1000 ROM</comment>
+ <comment xml:lang="id">ROM SG-1000</comment>
+ <comment xml:lang="hu">SG-1000 ROM</comment>
+ <comment xml:lang="hr">SG-1000 ROM</comment>
+ <comment xml:lang="he">ROM של SG-1000</comment>
+ <comment xml:lang="ga">ROM SG-1000</comment>
+ <comment xml:lang="fur">ROM SG-1000</comment>
+ <comment xml:lang="fr">ROM SG-1000</comment>
+ <comment xml:lang="fi">SG-1000 -ROM</comment>
+ <comment xml:lang="eu">SG-1000 ROM</comment>
+ <comment xml:lang="es">ROM de SG-1000</comment>
+ <comment xml:lang="en_GB">SG-1000 ROM</comment>
+ <comment xml:lang="de">SG-1000-ROM</comment>
+ <comment xml:lang="da">SG-1000-ROM</comment>
+ <comment xml:lang="cs">ROM pro SG-1000</comment>
+ <comment xml:lang="ca">ROM de SG-1000</comment>
+ <comment xml:lang="bg">ROM — SG-1000</comment>
+ <comment xml:lang="be">SG-1000 ROM</comment>
+ <comment xml:lang="ar">روم SG-1000</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.sg"/>
</mime-type>
<mime-type type="application/x-sms-rom">
-
+ <!-- Translate this to "Master System/Mark III" if the console was known as such in your locale (probably only in Japan) -->
<comment>Master System ROM</comment>
- <comment xml:lang="ca">ROM de Master System</comment>
- <comment xml:lang="cs">ROM pro Master System</comment>
- <comment xml:lang="da">Master System ROM</comment>
- <comment xml:lang="de">Master System ROM</comment>
- <comment xml:lang="en_GB">Master System ROM</comment>
- <comment xml:lang="es">ROM de Master System</comment>
- <comment xml:lang="eu">Master System ROM</comment>
- <comment xml:lang="fi">Master System -ROM</comment>
- <comment xml:lang="fr">ROM Master System</comment>
- <comment xml:lang="ga">ROM Master System</comment>
- <comment xml:lang="hr">Master System ROM</comment>
- <comment xml:lang="hu">Master System ROM</comment>
- <comment xml:lang="id">ROM Master System</comment>
- <comment xml:lang="it">ROM Master System</comment>
- <comment xml:lang="kk">Master System ROM</comment>
- <comment xml:lang="ko">마스터 시스템 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli SMS</comment>
- <comment xml:lang="pt_BR">ROM de Master System</comment>
- <comment xml:lang="ru">Master System ROM</comment>
- <comment xml:lang="sk">ROM pre Master System</comment>
- <comment xml:lang="sr">Мастер Систем РОМ</comment>
- <comment xml:lang="sv">Master System-rom</comment>
- <comment xml:lang="tr">Master System ROM</comment>
- <comment xml:lang="uk">ППП Master System</comment>
- <comment xml:lang="zh_CN">Master System ROM</comment>
<comment xml:lang="zh_TW">Master System ROM</comment>
+ <comment xml:lang="zh_CN">Master System ROM</comment>
+ <comment xml:lang="uk">ППП Master System</comment>
+ <comment xml:lang="tr">Master System ROM</comment>
+ <comment xml:lang="sv">Master System-rom</comment>
+ <comment xml:lang="sr">Мастер Систем РОМ</comment>
+ <comment xml:lang="sq">ROM Master System</comment>
+ <comment xml:lang="si">Master System ROM</comment>
+ <comment xml:lang="sk">ROM pre Master System</comment>
+ <comment xml:lang="ru">Master System ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Master System</comment>
+ <comment xml:lang="pl">Plik ROM konsoli SMS</comment>
+ <comment xml:lang="nl">Master System-ROM</comment>
+ <comment xml:lang="ko">마스터 시스템 롬</comment>
+ <comment xml:lang="kk">Master System ROM</comment>
+ <comment xml:lang="ja">マスターシステム ROM</comment>
+ <comment xml:lang="it">ROM Master System</comment>
+ <comment xml:lang="is">Master System ROM</comment>
+ <comment xml:lang="id">ROM Master System</comment>
+ <comment xml:lang="hu">Master System ROM</comment>
+ <comment xml:lang="hr">Master System ROM</comment>
+ <comment xml:lang="he">ROM של Master System</comment>
+ <comment xml:lang="ga">ROM Master System</comment>
+ <comment xml:lang="fur">ROM Master System</comment>
+ <comment xml:lang="fr">ROM Master System</comment>
+ <comment xml:lang="fi">Master System -ROM</comment>
+ <comment xml:lang="eu">Master System ROM</comment>
+ <comment xml:lang="es">ROM de Master System</comment>
+ <comment xml:lang="en_GB">Master System ROM</comment>
+ <comment xml:lang="de">Master-System-ROM</comment>
+ <comment xml:lang="da">Master System-ROM</comment>
+ <comment xml:lang="cs">ROM pro Master System</comment>
+ <comment xml:lang="ca">ROM de Master System</comment>
+ <comment xml:lang="bg">ROM — Master System</comment>
+ <comment xml:lang="be">Master System ROM</comment>
+ <comment xml:lang="ar">روم Master System</comment>
<generic-icon name="application-x-executable"/>
-
+ <!-- Disabled, the magic would be too far into the file
+ <magic>
+ <match type="string" value="TMR SEGA" offset="32752">
+ <match type="byte" value="0x30" offset="32767" mask="0xf0"/>
+ <match type="byte" value="0x40" offset="32767" mask="0xf0"/>
+ </match>
+ </magic> -->
<glob pattern="*.sms"/>
</mime-type>
<mime-type type="application/x-gamegear-rom">
<comment>Game Gear ROM</comment>
- <comment xml:lang="ca">ROM de Game Gear</comment>
- <comment xml:lang="cs">ROM pro Game Gear</comment>
- <comment xml:lang="da">Game Gear ROM</comment>
- <comment xml:lang="de">Game Gear ROM</comment>
- <comment xml:lang="en_GB">Game Gear ROM</comment>
- <comment xml:lang="es">ROM de Game Gear</comment>
- <comment xml:lang="eu">Game Gear ROM</comment>
- <comment xml:lang="fi">Game Gear -ROM</comment>
- <comment xml:lang="fr">ROM Game Gear</comment>
- <comment xml:lang="ga">ROM Game Gear</comment>
- <comment xml:lang="hr">Game Gear ROM</comment>
- <comment xml:lang="hu">Game Gear ROM</comment>
- <comment xml:lang="id">ROM Game Gear</comment>
- <comment xml:lang="it">ROM Game Gear</comment>
- <comment xml:lang="kk">Game Gear ROM</comment>
- <comment xml:lang="ko">게임 기어 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Game Gear</comment>
- <comment xml:lang="pt_BR">ROM de Game Gear</comment>
- <comment xml:lang="ru">Game Gear ROM</comment>
- <comment xml:lang="sk">ROM pre Game Gear</comment>
- <comment xml:lang="sr">Гејм Гир РОМ</comment>
- <comment xml:lang="sv">Game Gear-rom</comment>
- <comment xml:lang="tr">Game Gear ROM</comment>
- <comment xml:lang="uk">ППП Game Gear</comment>
- <comment xml:lang="zh_CN">Game Gear ROM</comment>
<comment xml:lang="zh_TW">Game Gear ROM</comment>
+ <comment xml:lang="zh_CN">Game Gear ROM</comment>
+ <comment xml:lang="uk">ППП Game Gear</comment>
+ <comment xml:lang="tr">Game Gear ROM</comment>
+ <comment xml:lang="sv">Game Gear-rom</comment>
+ <comment xml:lang="sr">Гејм Гир РОМ</comment>
+ <comment xml:lang="sq">ROM Game Gear</comment>
+ <comment xml:lang="sl">Game Gear ROM</comment>
+ <comment xml:lang="si">Game Gear ROM</comment>
+ <comment xml:lang="sk">ROM pre Game Gear</comment>
+ <comment xml:lang="ru">Game Gear ROM</comment>
+ <comment xml:lang="pt_BR">ROM de Game Gear</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Game Gear</comment>
+ <comment xml:lang="nl">Game Gear-ROM</comment>
+ <comment xml:lang="ko">게임 기어 롬</comment>
+ <comment xml:lang="kk">Game Gear ROM</comment>
+ <comment xml:lang="ja">ゲームギア ROM</comment>
+ <comment xml:lang="it">ROM Game Gear</comment>
+ <comment xml:lang="is">Game Gear ROM</comment>
+ <comment xml:lang="id">ROM Game Gear</comment>
+ <comment xml:lang="hu">Game Gear ROM</comment>
+ <comment xml:lang="hr">Game Gear ROM</comment>
+ <comment xml:lang="he">ROM של Game Gear</comment>
+ <comment xml:lang="ga">ROM Game Gear</comment>
+ <comment xml:lang="fur">ROM Game Gear</comment>
+ <comment xml:lang="fr">ROM Game Gear</comment>
+ <comment xml:lang="fi">Game Gear -ROM</comment>
+ <comment xml:lang="eu">Game Gear ROM</comment>
+ <comment xml:lang="es">ROM de Game Gear</comment>
+ <comment xml:lang="en_GB">Game Gear ROM</comment>
+ <comment xml:lang="de">Game-Gear-ROM</comment>
+ <comment xml:lang="da">Game Gear-ROM</comment>
+ <comment xml:lang="cs">ROM pro Game Gear</comment>
+ <comment xml:lang="ca">ROM de Game Gear</comment>
+ <comment xml:lang="bg">ROM — Game Gear</comment>
+ <comment xml:lang="be">Game Gear ROM</comment>
+ <comment xml:lang="ar">روم جيم جير</comment>
<generic-icon name="application-x-executable"/>
-
+ <!-- Disabled, the magic would be too far into the file
+ <magic>
+ <match type="string" value="TMR SEGA" offset="32752">
+ <match type="byte" value="0x50" offset="32767" mask="0xf0"/>
+ <match type="byte" value="0x60" offset="32767" mask="0xf0"/>
+ <match type="byte" value="0x70" offset="32767" mask="0xf0"/>
+ </match>
+ </magic> -->
<glob pattern="*.gg"/>
</mime-type>
<mime-type type="application/vnd.nintendo.snes.rom">
-
+ <!-- Translate this as Super Famicom (in Far East Asia) or Super Nintendo (in Europe) if the console was known as such in your locale -->
<comment>Super NES ROM</comment>
- <comment xml:lang="ar">Super NES ROM</comment>
- <comment xml:lang="be@latin">Super Nintendo ROM</comment>
- <comment xml:lang="bg">ROM — Super NES</comment>
- <comment xml:lang="ca">ROM de Super NES</comment>
- <comment xml:lang="cs">ROM pro Super Nintendo</comment>
- <comment xml:lang="da">Super NES-rom</comment>
- <comment xml:lang="de">Super NES ROM</comment>
- <comment xml:lang="el">Super NES ROM</comment>
- <comment xml:lang="en_GB">Super NES ROM</comment>
- <comment xml:lang="es">ROM de Super NES</comment>
- <comment xml:lang="eu">Super Nintendo-ko ROMa</comment>
- <comment xml:lang="fi">Super Nintendo -ROM</comment>
- <comment xml:lang="fo">Super NES ROM</comment>
- <comment xml:lang="fr">ROM Super Nintendo</comment>
- <comment xml:lang="ga">ROM Super NES</comment>
- <comment xml:lang="gl">ROM de Super NES</comment>
- <comment xml:lang="he">ROM של Super NES</comment>
- <comment xml:lang="hr">Super NES ROM</comment>
- <comment xml:lang="hu">Super NES ROM</comment>
- <comment xml:lang="ia">ROM pro Super Nintendo</comment>
- <comment xml:lang="id">Memori baca-saja Super Nintendo</comment>
- <comment xml:lang="it">ROM Super Nintendo</comment>
- <comment xml:lang="ja">スーパーファミコン ROM</comment>
- <comment xml:lang="kk">Super NES ROM</comment>
- <comment xml:lang="ko">수퍼 NES 롬</comment>
- <comment xml:lang="lt">Super NES ROM</comment>
- <comment xml:lang="lv">Super NES ROM</comment>
- <comment xml:lang="nb">Super Nintendo ROM</comment>
- <comment xml:lang="nl">Super Nintendo</comment>
- <comment xml:lang="nn">Super NES-ROM</comment>
- <comment xml:lang="oc">ROM Super Nintendo</comment>
- <comment xml:lang="pl">Plik ROM konsoli SNES</comment>
- <comment xml:lang="pt">ROM Super Nintendo</comment>
- <comment xml:lang="pt_BR">ROM de Super Nintendo</comment>
- <comment xml:lang="ro">ROM Super Nintendo</comment>
- <comment xml:lang="ru">Super NES ROM</comment>
- <comment xml:lang="sk">ROM pre Super Nintendo</comment>
- <comment xml:lang="sl">Bralni pomnilnik Super NES</comment>
- <comment xml:lang="sq">ROM Super NES</comment>
- <comment xml:lang="sr">Супер НЕС РОМ</comment>
- <comment xml:lang="sv">Super NES-rom</comment>
- <comment xml:lang="tr">Super NES ROM</comment>
- <comment xml:lang="uk">ППП Super NES</comment>
- <comment xml:lang="vi">ROM Super Nintendo</comment>
- <comment xml:lang="zh_CN">Super NES ROM</comment>
<comment xml:lang="zh_TW">超級任天堂 ROM</comment>
+ <comment xml:lang="zh_CN">Super NES ROM</comment>
+ <comment xml:lang="vi">ROM Super Nintendo</comment>
+ <comment xml:lang="uk">ППП Super NES</comment>
+ <comment xml:lang="tr">Super NES ROM</comment>
+ <comment xml:lang="sv">Super NES-rom</comment>
+ <comment xml:lang="sr">Супер НЕС РОМ</comment>
+ <comment xml:lang="sq">ROM Super NES</comment>
+ <comment xml:lang="sl">Bralni pomnilnik Super NES</comment>
+ <comment xml:lang="si">සුපිරි NES ROM</comment>
+ <comment xml:lang="sk">ROM pre Super Nintendo</comment>
+ <comment xml:lang="ru">Super NES ROM</comment>
+ <comment xml:lang="ro">ROM Super Nintendo</comment>
+ <comment xml:lang="pt_BR">ROM de Super Nintendo</comment>
+ <comment xml:lang="pt">ROM Super Nintendo</comment>
+ <comment xml:lang="pl">Plik ROM konsoli SNES</comment>
+ <comment xml:lang="oc">ROM Super Nintendo</comment>
+ <comment xml:lang="nn">Super NES-ROM</comment>
+ <comment xml:lang="nl">Super Nintendo-ROM</comment>
+ <comment xml:lang="nb">Super Nintendo ROM</comment>
+ <comment xml:lang="lv">Super NES ROM</comment>
+ <comment xml:lang="lt">Super NES ROM</comment>
+ <comment xml:lang="ko">수퍼 NES 롬</comment>
+ <comment xml:lang="kk">Super NES ROM</comment>
+ <comment xml:lang="ja">スーパーファミコン ROM</comment>
+ <comment xml:lang="it">ROM Super Nintendo</comment>
+ <comment xml:lang="is">Super NES ROM</comment>
+ <comment xml:lang="id">Memori baca-saja Super Nintendo</comment>
+ <comment xml:lang="ia">ROM pro Super Nintendo</comment>
+ <comment xml:lang="hu">Super NES ROM</comment>
+ <comment xml:lang="hr">Super NES ROM</comment>
+ <comment xml:lang="he">ROM של Super NES</comment>
+ <comment xml:lang="gl">ROM de Super NES</comment>
+ <comment xml:lang="ga">ROM Super NES</comment>
+ <comment xml:lang="fur">ROM Super Nintendo</comment>
+ <comment xml:lang="fr">ROM Super Nintendo</comment>
+ <comment xml:lang="fo">Super NES ROM</comment>
+ <comment xml:lang="fi">Super Nintendo -ROM</comment>
+ <comment xml:lang="eu">Super Nintendo-ko ROMa</comment>
+ <comment xml:lang="es">ROM de Super NES</comment>
+ <comment xml:lang="en_GB">Super NES ROM</comment>
+ <comment xml:lang="el">Super NES ROM</comment>
+ <comment xml:lang="de">Super-Nintendo-ROM</comment>
+ <comment xml:lang="da">Super NES-ROM</comment>
+ <comment xml:lang="cs">ROM pro Super Nintendo</comment>
+ <comment xml:lang="ca">ROM de Super NES</comment>
+ <comment xml:lang="bg">ROM — Super NES</comment>
+ <comment xml:lang="be@latin">Super Nintendo ROM</comment>
+ <comment xml:lang="be">Super Nintendo ROM</comment>
+ <comment xml:lang="ar">روم Super NES</comment>
<generic-icon name="application-x-executable"/>
<alias type="application/x-snes-rom"/>
<glob pattern="*.sfc"/>
@@ -19972,855 +21716,947 @@
</mime-type>
<mime-type type="application/x-stuffit">
<comment>StuffIt archive</comment>
- <comment xml:lang="ar">أرشيف StuffIt</comment>
- <comment xml:lang="be@latin">Archiŭ StuffIt</comment>
- <comment xml:lang="bg">Архив — StuffIt</comment>
- <comment xml:lang="ca">arxiu StuffIt</comment>
- <comment xml:lang="cs">archiv StuffIt</comment>
- <comment xml:lang="da">StuffIt-arkiv</comment>
- <comment xml:lang="de">StuffIt-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο StuffIt</comment>
- <comment xml:lang="en_GB">StuffIt archive</comment>
- <comment xml:lang="eo">StuffIt-arkivo</comment>
- <comment xml:lang="es">archivador de StuffIt</comment>
- <comment xml:lang="eu">StuffIt artxiboa</comment>
- <comment xml:lang="fi">StuffIt-arkisto</comment>
- <comment xml:lang="fo">StuffIt skjalasavn</comment>
- <comment xml:lang="fr">archive StuffIt</comment>
- <comment xml:lang="ga">cartlann StuffIt</comment>
- <comment xml:lang="gl">arquivo StuffIt</comment>
- <comment xml:lang="he">ארכיון של StuffIt</comment>
- <comment xml:lang="hr">StuffIt arhiva</comment>
- <comment xml:lang="hu">StuffIt-archívum</comment>
- <comment xml:lang="ia">Archivo StuffIt</comment>
- <comment xml:lang="id">Arsip StuffIt</comment>
- <comment xml:lang="it">Archivio StuffIt</comment>
- <comment xml:lang="ja">StuffIt アーカイブ</comment>
- <comment xml:lang="kk">StuffIt архиві</comment>
- <comment xml:lang="ko">StuffIt 압축 파일</comment>
- <comment xml:lang="lt">StuffIt archyvas</comment>
- <comment xml:lang="lv">StuffIt arhīvs</comment>
- <comment xml:lang="nb">StuffIt arkiv</comment>
- <comment xml:lang="nl">StuffIt-archief</comment>
- <comment xml:lang="nn">StuffIt-arkiv</comment>
- <comment xml:lang="oc">archiu StuffIt</comment>
- <comment xml:lang="pl">Archiwum StuffIt</comment>
- <comment xml:lang="pt">arquivo StuffIt</comment>
- <comment xml:lang="pt_BR">Pacote StuffIt</comment>
- <comment xml:lang="ro">Arhivă StuffIt</comment>
- <comment xml:lang="ru">Архив StuffIt</comment>
- <comment xml:lang="sk">Archív StuffIt</comment>
- <comment xml:lang="sl">Datoteka arhiva StuffIt</comment>
- <comment xml:lang="sq">Arkiv StuffIt</comment>
- <comment xml:lang="sr">Стаф Ит архива</comment>
- <comment xml:lang="sv">StuffIt-arkiv </comment>
- <comment xml:lang="tr">StuffIt arşivi</comment>
- <comment xml:lang="uk">архів StuffIt</comment>
- <comment xml:lang="vi">Kho nén Stuffit</comment>
- <comment xml:lang="zh_CN">Macintosh StuffIt 归档文件</comment>
<comment xml:lang="zh_TW">StuffIt 封存檔</comment>
+ <comment xml:lang="zh_CN">Macintosh StuffIt 归档文件</comment>
+ <comment xml:lang="vi">Kho nén Stuffit</comment>
+ <comment xml:lang="uk">архів StuffIt</comment>
+ <comment xml:lang="tr">StuffIt arşivi</comment>
+ <comment xml:lang="sv">StuffIt-arkiv </comment>
+ <comment xml:lang="sr">Стаф Ит архива</comment>
+ <comment xml:lang="sq">arkiv StuffIt</comment>
+ <comment xml:lang="sl">Datoteka arhiva StuffIt</comment>
+ <comment xml:lang="si">StuffIt ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív StuffIt</comment>
+ <comment xml:lang="ru">Архив StuffIt</comment>
+ <comment xml:lang="ro">Arhivă StuffIt</comment>
+ <comment xml:lang="pt_BR">Pacote StuffIt</comment>
+ <comment xml:lang="pt">arquivo StuffIt</comment>
+ <comment xml:lang="pl">Archiwum StuffIt</comment>
+ <comment xml:lang="oc">archiu StuffIt</comment>
+ <comment xml:lang="nn">StuffIt-arkiv</comment>
+ <comment xml:lang="nl">StuffIt-archief</comment>
+ <comment xml:lang="nb">StuffIt arkiv</comment>
+ <comment xml:lang="lv">StuffIt arhīvs</comment>
+ <comment xml:lang="lt">StuffIt archyvas</comment>
+ <comment xml:lang="ko">StuffIt 압축 파일</comment>
+ <comment xml:lang="kk">StuffIt архиві</comment>
+ <comment xml:lang="ja">StuffIt アーカイブ</comment>
+ <comment xml:lang="it">Archivio StuffIt</comment>
+ <comment xml:lang="is">StuffIt safnskrá</comment>
+ <comment xml:lang="id">Arsip StuffIt</comment>
+ <comment xml:lang="ia">Archivo StuffIt</comment>
+ <comment xml:lang="hu">StuffIt-archívum</comment>
+ <comment xml:lang="hr">StuffIt arhiva</comment>
+ <comment xml:lang="he">ארכיון של StuffIt</comment>
+ <comment xml:lang="gl">arquivo StuffIt</comment>
+ <comment xml:lang="ga">cartlann StuffIt</comment>
+ <comment xml:lang="fur">archivi StuffIt</comment>
+ <comment xml:lang="fr">archive StuffIt</comment>
+ <comment xml:lang="fo">StuffIt skjalasavn</comment>
+ <comment xml:lang="fi">StuffIt-arkisto</comment>
+ <comment xml:lang="eu">StuffIt artxiboa</comment>
+ <comment xml:lang="es">archivador de StuffIt</comment>
+ <comment xml:lang="eo">StuffIt-arkivo</comment>
+ <comment xml:lang="en_GB">StuffIt archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο StuffIt</comment>
+ <comment xml:lang="de">StuffIt-Archiv</comment>
+ <comment xml:lang="da">StuffIt-arkiv</comment>
+ <comment xml:lang="cs">archiv StuffIt</comment>
+ <comment xml:lang="ca">arxiu StuffIt</comment>
+ <comment xml:lang="bg">Архив — StuffIt</comment>
+ <comment xml:lang="be@latin">Archiŭ StuffIt</comment>
+ <comment xml:lang="be">архіў StuffIt</comment>
+ <comment xml:lang="ar">أرشيف StuffIt</comment>
+ <comment xml:lang="af">StuffIt-argief</comment>
<generic-icon name="package-x-generic"/>
<alias type="application/stuffit"/>
<alias type="application/x-sit"/>
<magic priority="60">
- <match value="StuffIt " type="string" offset="0"/>
- <match value="SIT!" type="string" offset="0"/>
+ <match type="string" value="StuffIt " offset="0"/>
+ <match type="string" value="SIT!" offset="0"/>
</magic>
<glob pattern="*.sit"/>
</mime-type>
+ <mime-type type="application/x-stuffitx">
+ <comment>StuffIt X archive</comment>
+ <comment xml:lang="uk">архів StuffIt X</comment>
+ <comment xml:lang="sv">StuffIt X-arkiv </comment>
+ <comment xml:lang="ru">Архив StuffIt X</comment>
+ <comment xml:lang="pl">Archiwum StuffIt X</comment>
+ <comment xml:lang="it">Archivio StuffIt X</comment>
+ <comment xml:lang="eu">StuffIt X artxiboa</comment>
+ <comment xml:lang="es">archivador de StuffIt X</comment>
+ <comment xml:lang="de">StuffIt-X-Archiv</comment>
+ <comment xml:lang="be">архіў StuffIt X</comment>
+ <generic-icon name="package-x-generic"/>
+ <alias type="application/x-sitx"/>
+ <magic priority="60">
+ <match type="string" value="StuffIt!" offset="0"/>
+ </magic>
+ <glob pattern="*.sitx"/>
+ </mime-type>
<mime-type type="application/x-subrip">
<comment>SubRip subtitles</comment>
- <comment xml:lang="ar">ترجمات SubRip</comment>
- <comment xml:lang="be@latin">Subtytry SubRip</comment>
- <comment xml:lang="bg">Субтитри — SubRip</comment>
- <comment xml:lang="ca">subtítols SubRip</comment>
- <comment xml:lang="cs">titulky SubRip</comment>
- <comment xml:lang="da">SubRip-undertekster</comment>
- <comment xml:lang="de">SubRip-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι SubRip</comment>
- <comment xml:lang="en_GB">SubRip subtitles</comment>
- <comment xml:lang="eo">SubRip-subtekstoj</comment>
- <comment xml:lang="es">subtítulos SubRip</comment>
- <comment xml:lang="eu">SubRip azpitituluak</comment>
- <comment xml:lang="fi">SubRip-tekstitykset</comment>
- <comment xml:lang="fo">SubRip undirtekstir</comment>
- <comment xml:lang="fr">sous-titres SubRip</comment>
- <comment xml:lang="ga">fotheidil SubRip</comment>
- <comment xml:lang="gl">subtítulos SubRip</comment>
- <comment xml:lang="he">כתוביות של SubRip</comment>
- <comment xml:lang="hr">SubRip podnaslovi</comment>
- <comment xml:lang="hu">SubRip feliratok</comment>
- <comment xml:lang="ia">Subtitulos SubRip</comment>
- <comment xml:lang="id">Subjudul SubRip</comment>
- <comment xml:lang="it">Sottotitoli SubRip</comment>
- <comment xml:lang="ja">SubRip 字幕</comment>
- <comment xml:lang="kk">SubRip субтитрлары</comment>
- <comment xml:lang="ko">SubRip 자막 파일</comment>
- <comment xml:lang="lt">SubRip subtitrai</comment>
- <comment xml:lang="lv">SubRip subtitri</comment>
- <comment xml:lang="nb">SubRip undertekst</comment>
- <comment xml:lang="nl">SubRip-ondertitels</comment>
- <comment xml:lang="nn">SubRip-teksting</comment>
- <comment xml:lang="oc">sostítols SubRip</comment>
- <comment xml:lang="pl">Napisy SubRip</comment>
- <comment xml:lang="pt">legendas SubRip</comment>
- <comment xml:lang="pt_BR">Legendas SubRip</comment>
- <comment xml:lang="ro">Subtitrare SubRip</comment>
- <comment xml:lang="ru">Субтитры SubRip</comment>
- <comment xml:lang="sk">Titulky SubRip</comment>
- <comment xml:lang="sl">Datoteka podnapisov SubRip</comment>
- <comment xml:lang="sq">Nëntituj SubRip</comment>
- <comment xml:lang="sr">Суб Рип преводи</comment>
- <comment xml:lang="sv">SubRip-undertexter</comment>
- <comment xml:lang="tr">SubRip altyazıları</comment>
- <comment xml:lang="uk">субтитри SubRip</comment>
- <comment xml:lang="vi">Phụ đề SubRip</comment>
- <comment xml:lang="zh_CN">SubRip 字幕</comment>
<comment xml:lang="zh_TW">SubRip 字幕</comment>
+ <comment xml:lang="zh_CN">SubRip 字幕</comment>
+ <comment xml:lang="vi">Phụ đề SubRip</comment>
+ <comment xml:lang="uk">субтитри SubRip</comment>
+ <comment xml:lang="tr">SubRip alt yazıları</comment>
+ <comment xml:lang="sv">SubRip-undertexter</comment>
+ <comment xml:lang="sr">Суб Рип преводи</comment>
+ <comment xml:lang="sq">titra SubRip</comment>
+ <comment xml:lang="sl">Datoteka podnapisov SubRip</comment>
+ <comment xml:lang="si">SubRip උපසිරැසි</comment>
+ <comment xml:lang="sk">Titulky SubRip</comment>
+ <comment xml:lang="ru">Субтитры SubRip</comment>
+ <comment xml:lang="ro">Subtitrare SubRip</comment>
+ <comment xml:lang="pt_BR">Legendas SubRip</comment>
+ <comment xml:lang="pt">legendas SubRip</comment>
+ <comment xml:lang="pl">Napisy SubRip</comment>
+ <comment xml:lang="oc">sostítols SubRip</comment>
+ <comment xml:lang="nn">SubRip-teksting</comment>
+ <comment xml:lang="nl">SubRip-ondertitels</comment>
+ <comment xml:lang="nb">SubRip undertekst</comment>
+ <comment xml:lang="lv">SubRip subtitri</comment>
+ <comment xml:lang="lt">SubRip subtitrai</comment>
+ <comment xml:lang="ko">SubRip 자막 파일</comment>
+ <comment xml:lang="kk">SubRip субтитрлары</comment>
+ <comment xml:lang="ja">SubRip 字幕</comment>
+ <comment xml:lang="it">Sottotitoli SubRip</comment>
+ <comment xml:lang="is">SubRip skjátextar</comment>
+ <comment xml:lang="id">Subjudul SubRip</comment>
+ <comment xml:lang="ia">Subtitulos SubRip</comment>
+ <comment xml:lang="hu">SubRip feliratok</comment>
+ <comment xml:lang="hr">SubRip podnaslovi</comment>
+ <comment xml:lang="he">כתוביות של SubRip</comment>
+ <comment xml:lang="gl">subtítulos SubRip</comment>
+ <comment xml:lang="ga">fotheidil SubRip</comment>
+ <comment xml:lang="fur">sottitui SubRip</comment>
+ <comment xml:lang="fr">sous-titres SubRip</comment>
+ <comment xml:lang="fo">SubRip undirtekstir</comment>
+ <comment xml:lang="fi">SubRip-tekstitykset</comment>
+ <comment xml:lang="eu">SubRip azpitituluak</comment>
+ <comment xml:lang="es">subtítulos SubRip</comment>
+ <comment xml:lang="eo">SubRip-subtekstoj</comment>
+ <comment xml:lang="en_GB">SubRip subtitles</comment>
+ <comment xml:lang="el">Υπότιτλοι SubRip</comment>
+ <comment xml:lang="de">SubRip-Untertitel</comment>
+ <comment xml:lang="da">SubRip-undertekster</comment>
+ <comment xml:lang="cs">titulky SubRip</comment>
+ <comment xml:lang="ca">subtítols SubRip</comment>
+ <comment xml:lang="bg">Субтитри — SubRip</comment>
+ <comment xml:lang="be@latin">Subtytry SubRip</comment>
+ <comment xml:lang="be">субцітры SubRip</comment>
+ <comment xml:lang="ar">ترجمات SubRip</comment>
+ <comment xml:lang="af">SubRip-onderskrifte</comment>
<alias type="application/x-srt"/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="1" type="string" offset="0">
- <match value=" --> " type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="1" offset="0">
+ <match type="string" value=" --&gt; " offset="0:256"/>
</match>
</magic>
<glob pattern="*.srt"/>
</mime-type>
<mime-type type="text/vtt">
<comment>WebVTT subtitles</comment>
- <comment xml:lang="bg">Субтитри — WebVTT</comment>
- <comment xml:lang="ca">subtítols WebVTT</comment>
- <comment xml:lang="cs">titulky WebVTT</comment>
- <comment xml:lang="da">WebVTT-undertekster</comment>
- <comment xml:lang="de">WebVTT-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι WebVTT</comment>
- <comment xml:lang="en_GB">WebVTT subtitles</comment>
- <comment xml:lang="es">subtítulos WebVTT</comment>
- <comment xml:lang="eu">WebVTT azpitituluak</comment>
- <comment xml:lang="fi">WebVTT-tekstitykset</comment>
- <comment xml:lang="fr">sous-titres WebVTT</comment>
- <comment xml:lang="ga">fotheidil WebVTT</comment>
- <comment xml:lang="gl">subtítulos WebVTT</comment>
- <comment xml:lang="he">כתוביות WebVTT</comment>
- <comment xml:lang="hr">WebVTT podnaslovi</comment>
- <comment xml:lang="hu">WebVTT feliratok</comment>
- <comment xml:lang="ia">Subtitulos WebVTT</comment>
- <comment xml:lang="id">Subjudul WebVTT</comment>
- <comment xml:lang="it">Sottotitoli WebVTT</comment>
- <comment xml:lang="ja">WebVTT サブタイトル</comment>
- <comment xml:lang="ka">WebVTT ქვეტიტრები</comment>
- <comment xml:lang="kk">WebVTT субтитрлары</comment>
- <comment xml:lang="ko">WebVTT 자막</comment>
- <comment xml:lang="lv">WebVTT subtitri</comment>
- <comment xml:lang="nl">WebVTT ondertitels</comment>
- <comment xml:lang="oc">sostítols WebVTT</comment>
- <comment xml:lang="pl">Napisy WebVTT</comment>
- <comment xml:lang="pt">legendas WebVTT</comment>
- <comment xml:lang="pt_BR">Legendas WebVTT</comment>
- <comment xml:lang="ru">Субтитры WebVTT</comment>
- <comment xml:lang="sk">Titulky WebVTT</comment>
- <comment xml:lang="sl">Podnapisi WebVTT</comment>
- <comment xml:lang="sr">Веб ВТТ преводи</comment>
- <comment xml:lang="sv">WebVTT-undertexter</comment>
- <comment xml:lang="tr">WebVTT altyazıları</comment>
- <comment xml:lang="uk">субтитри WebVTT</comment>
- <comment xml:lang="zh_CN">WebVTT 字幕</comment>
<comment xml:lang="zh_TW">WebVTT 字幕</comment>
+ <comment xml:lang="zh_CN">WebVTT 字幕</comment>
+ <comment xml:lang="uk">субтитри WebVTT</comment>
+ <comment xml:lang="tr">WebVTT alt yazıları</comment>
+ <comment xml:lang="sv">WebVTT-undertexter</comment>
+ <comment xml:lang="sr">Веб ВТТ преводи</comment>
+ <comment xml:lang="sq">titra WebVTT</comment>
+ <comment xml:lang="sl">Podnapisi WebVTT</comment>
+ <comment xml:lang="si">WebVTT උපසිරැසි</comment>
+ <comment xml:lang="sk">Titulky WebVTT</comment>
+ <comment xml:lang="ru">Субтитры WebVTT</comment>
+ <comment xml:lang="pt_BR">Legendas WebVTT</comment>
+ <comment xml:lang="pt">legendas WebVTT</comment>
+ <comment xml:lang="pl">Napisy WebVTT</comment>
+ <comment xml:lang="oc">sostítols WebVTT</comment>
+ <comment xml:lang="nl">WebVTT ondertitels</comment>
+ <comment xml:lang="lv">WebVTT subtitri</comment>
+ <comment xml:lang="ko">WebVTT 자막 파일</comment>
+ <comment xml:lang="kk">WebVTT субтитрлары</comment>
+ <comment xml:lang="ka">WebVTT ქვეტიტრები</comment>
+ <comment xml:lang="ja">WebVTT 字幕</comment>
+ <comment xml:lang="it">Sottotitoli WebVTT</comment>
+ <comment xml:lang="is">WebVTT skjátextar</comment>
+ <comment xml:lang="id">Subjudul WebVTT</comment>
+ <comment xml:lang="ia">Subtitulos WebVTT</comment>
+ <comment xml:lang="hu">WebVTT feliratok</comment>
+ <comment xml:lang="hr">WebVTT podnaslovi</comment>
+ <comment xml:lang="he">כתוביות WebVTT</comment>
+ <comment xml:lang="gl">subtítulos WebVTT</comment>
+ <comment xml:lang="ga">fotheidil WebVTT</comment>
+ <comment xml:lang="fur">sottitui WebVTT</comment>
+ <comment xml:lang="fr">sous-titres WebVTT</comment>
+ <comment xml:lang="fi">WebVTT-tekstitykset</comment>
+ <comment xml:lang="eu">WebVTT azpitituluak</comment>
+ <comment xml:lang="es">subtítulos WebVTT</comment>
+ <comment xml:lang="en_GB">WebVTT subtitles</comment>
+ <comment xml:lang="el">Υπότιτλοι WebVTT</comment>
+ <comment xml:lang="de">WebVTT-Untertitel</comment>
+ <comment xml:lang="da">WebVTT-undertekster</comment>
+ <comment xml:lang="cs">titulky WebVTT</comment>
+ <comment xml:lang="ca">subtítols WebVTT</comment>
+ <comment xml:lang="bg">Субтитри — WebVTT</comment>
+ <comment xml:lang="be">субцітры WebVTT</comment>
+ <comment xml:lang="ar">ترجمات WebVTT</comment>
+ <comment xml:lang="af">WebVTT-onderskrifte</comment>
<acronym>VTT</acronym>
<expanded-acronym>Video Text Tracks</expanded-acronym>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="WEBVTT" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="WEBVTT" offset="0"/>
</magic>
<glob pattern="*.vtt"/>
</mime-type>
<mime-type type="application/x-sami">
<comment>SAMI subtitles</comment>
- <comment xml:lang="ar">ترجمات SAMI</comment>
- <comment xml:lang="be@latin">Subtytry SAMI</comment>
- <comment xml:lang="bg">Субтитри — SAMI</comment>
- <comment xml:lang="ca">subtítols SAMI</comment>
- <comment xml:lang="cs">titulky SAMI</comment>
- <comment xml:lang="da">SAMI-undertekster</comment>
- <comment xml:lang="de">SAMI-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι SAMI</comment>
- <comment xml:lang="en_GB">SAMI subtitles</comment>
- <comment xml:lang="eo">SAMI-subtekstoj</comment>
- <comment xml:lang="es">subtítulos SAMI</comment>
- <comment xml:lang="eu">SAMI azpitituluak</comment>
- <comment xml:lang="fi">SAMI-tekstitykset</comment>
- <comment xml:lang="fo">SAMI undirtekstir</comment>
- <comment xml:lang="fr">sous-titres SAMI</comment>
- <comment xml:lang="ga">fotheidil SAMI</comment>
- <comment xml:lang="gl">subtítulos SAMI</comment>
- <comment xml:lang="he">כתוביות SAMI</comment>
- <comment xml:lang="hr">SAMI podnaslovi</comment>
- <comment xml:lang="hu">SAMI feliratok</comment>
- <comment xml:lang="ia">Subtitulos SAMI</comment>
- <comment xml:lang="id">Subjudul SAMI</comment>
- <comment xml:lang="it">Sottotitoli SAMI</comment>
- <comment xml:lang="ja">SAMI 字幕</comment>
- <comment xml:lang="kk">SAMI субтитрлары</comment>
- <comment xml:lang="ko">SAMI 자막 파일</comment>
- <comment xml:lang="lt">SAMI subtitrai</comment>
- <comment xml:lang="lv">SAMI subtitri</comment>
- <comment xml:lang="nb">SAMI undertekst</comment>
- <comment xml:lang="nl">SAMI-ondertitels</comment>
- <comment xml:lang="nn">SAMI teksting</comment>
- <comment xml:lang="oc">sostítols SAMI</comment>
- <comment xml:lang="pl">Napisy SAMI</comment>
- <comment xml:lang="pt">legendas SAMI</comment>
- <comment xml:lang="pt_BR">Legendas SAMI</comment>
- <comment xml:lang="ro">Subtitrări SAMI</comment>
- <comment xml:lang="ru">Субтитры SAMI</comment>
- <comment xml:lang="sk">Titulky SAMI</comment>
- <comment xml:lang="sl">Datoteka podnapisov SAMI</comment>
- <comment xml:lang="sq">Nëntituj SAMI</comment>
- <comment xml:lang="sr">САМИ преводи</comment>
- <comment xml:lang="sv">SAMI-undertexter</comment>
- <comment xml:lang="tr">SAMI altyazıları</comment>
- <comment xml:lang="uk">субтитри SAMI</comment>
- <comment xml:lang="vi">Phụ đề SAMI</comment>
- <comment xml:lang="zh_CN">SAMI 字幕</comment>
<comment xml:lang="zh_TW">SAMI 字幕</comment>
+ <comment xml:lang="zh_CN">SAMI 字幕</comment>
+ <comment xml:lang="vi">Phụ đề SAMI</comment>
+ <comment xml:lang="uk">субтитри SAMI</comment>
+ <comment xml:lang="tr">SAMI alt yazıları</comment>
+ <comment xml:lang="sv">SAMI-undertexter</comment>
+ <comment xml:lang="sr">САМИ преводи</comment>
+ <comment xml:lang="sq">titra SAMI</comment>
+ <comment xml:lang="sl">Datoteka podnapisov SAMI</comment>
+ <comment xml:lang="si">SAMI උපසිරැසි</comment>
+ <comment xml:lang="sk">Titulky SAMI</comment>
+ <comment xml:lang="ru">Субтитры SAMI</comment>
+ <comment xml:lang="ro">Subtitrări SAMI</comment>
+ <comment xml:lang="pt_BR">Legendas SAMI</comment>
+ <comment xml:lang="pt">legendas SAMI</comment>
+ <comment xml:lang="pl">Napisy SAMI</comment>
+ <comment xml:lang="oc">sostítols SAMI</comment>
+ <comment xml:lang="nn">SAMI teksting</comment>
+ <comment xml:lang="nl">SAMI-ondertitels</comment>
+ <comment xml:lang="nb">SAMI undertekst</comment>
+ <comment xml:lang="lv">SAMI subtitri</comment>
+ <comment xml:lang="lt">SAMI subtitrai</comment>
+ <comment xml:lang="ko">SAMI 자막 파일</comment>
+ <comment xml:lang="kk">SAMI субтитрлары</comment>
+ <comment xml:lang="ja">SAMI 字幕</comment>
+ <comment xml:lang="it">Sottotitoli SAMI</comment>
+ <comment xml:lang="is">SAMI skjátextar</comment>
+ <comment xml:lang="id">Subjudul SAMI</comment>
+ <comment xml:lang="ia">Subtitulos SAMI</comment>
+ <comment xml:lang="hu">SAMI feliratok</comment>
+ <comment xml:lang="hr">SAMI podnaslovi</comment>
+ <comment xml:lang="he">כתוביות SAMI</comment>
+ <comment xml:lang="gl">subtítulos SAMI</comment>
+ <comment xml:lang="ga">fotheidil SAMI</comment>
+ <comment xml:lang="fur">sottitui SAMI</comment>
+ <comment xml:lang="fr">sous-titres SAMI</comment>
+ <comment xml:lang="fo">SAMI undirtekstir</comment>
+ <comment xml:lang="fi">SAMI-tekstitykset</comment>
+ <comment xml:lang="eu">SAMI azpitituluak</comment>
+ <comment xml:lang="es">subtítulos SAMI</comment>
+ <comment xml:lang="eo">SAMI-subtekstoj</comment>
+ <comment xml:lang="en_GB">SAMI subtitles</comment>
+ <comment xml:lang="el">Υπότιτλοι SAMI</comment>
+ <comment xml:lang="de">SAMI-Untertitel</comment>
+ <comment xml:lang="da">SAMI-undertekster</comment>
+ <comment xml:lang="cs">titulky SAMI</comment>
+ <comment xml:lang="ca">subtítols SAMI</comment>
+ <comment xml:lang="bg">Субтитри — SAMI</comment>
+ <comment xml:lang="be@latin">Subtytry SAMI</comment>
+ <comment xml:lang="be">субцітры SAMI</comment>
+ <comment xml:lang="ar">ترجمات SAMI</comment>
+ <comment xml:lang="af">SAMI-onderskrifte</comment>
<acronym>SAMI</acronym>
<expanded-acronym>Synchronized Accessible Media Interchange</expanded-acronym>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="&lt;SAMI&gt;" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;SAMI&gt;" offset="0:256"/>
</magic>
<glob pattern="*.smi"/>
<glob pattern="*.sami"/>
</mime-type>
<mime-type type="text/x-microdvd">
<comment>MicroDVD subtitles</comment>
- <comment xml:lang="ar">ترجمات MicroDVD</comment>
- <comment xml:lang="be@latin">Subtytry MicroDVD</comment>
- <comment xml:lang="bg">Субтитри — MicroDVD</comment>
- <comment xml:lang="ca">subtítols MicroDVD</comment>
- <comment xml:lang="cs">titulky MicroDVD</comment>
- <comment xml:lang="da">MicroDVD-undertekster</comment>
- <comment xml:lang="de">MicroDVD-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι MicroDVD</comment>
- <comment xml:lang="en_GB">MicroDVD subtitles</comment>
- <comment xml:lang="eo">MicroDVD-subtekstoj</comment>
- <comment xml:lang="es">subtítulos de MicroDVD</comment>
- <comment xml:lang="eu">MicroDVD azpitituluak</comment>
- <comment xml:lang="fi">MicroDVD-tekstitykset</comment>
- <comment xml:lang="fo">MicroDVD undirtekstir</comment>
- <comment xml:lang="fr">sous-titres MicroDVD</comment>
- <comment xml:lang="ga">fotheidil MicroDVD</comment>
- <comment xml:lang="gl">subtítulos de MicroDVD</comment>
- <comment xml:lang="he">כתוביות של MicroDVD</comment>
- <comment xml:lang="hr">MicroDVD podnaslovi</comment>
- <comment xml:lang="hu">MicroDVD feliratok</comment>
- <comment xml:lang="ia">Subtitulos MicroDVD</comment>
- <comment xml:lang="id">Subjudul MicroDVD</comment>
- <comment xml:lang="it">Sottotitoli MicroDVD</comment>
- <comment xml:lang="ja">MicroDVD 字幕</comment>
- <comment xml:lang="ka">MicroDVD-ის ქვეტიტრები</comment>
- <comment xml:lang="kk">MicroDVD субтитрлары</comment>
- <comment xml:lang="ko">MicroDVD 자막 파일</comment>
- <comment xml:lang="lt">MicroDVD subtitrai</comment>
- <comment xml:lang="lv">MicroDVD subtitri</comment>
- <comment xml:lang="nb">MicroDVD undertekst</comment>
- <comment xml:lang="nl">MicroDVD-ondertitels</comment>
- <comment xml:lang="nn">MicroDVD-teksting</comment>
- <comment xml:lang="oc">sostítols MicroDVD</comment>
- <comment xml:lang="pl">Napisy MicroDVD</comment>
- <comment xml:lang="pt">legendas MicroDVD</comment>
- <comment xml:lang="pt_BR">Legendas MicroDVD</comment>
- <comment xml:lang="ro">Subtitrări MicroDVD</comment>
- <comment xml:lang="ru">Субтитры MicroDVD</comment>
- <comment xml:lang="sk">Titulky MicroDVD</comment>
- <comment xml:lang="sl">Datoteka podnapisov MicroDVD</comment>
- <comment xml:lang="sq">Nëntituj MicroDVD</comment>
- <comment xml:lang="sr">Микро ДВД преводи</comment>
- <comment xml:lang="sv">MicroDVD-undertexter</comment>
- <comment xml:lang="tr">MicroDVD altyazısı</comment>
- <comment xml:lang="uk">субтитри MicroDVD</comment>
- <comment xml:lang="vi">Phụ đề MicroDVD</comment>
- <comment xml:lang="zh_CN">MicroDVD 字幕</comment>
<comment xml:lang="zh_TW">MicroDVD 字幕</comment>
+ <comment xml:lang="zh_CN">MicroDVD 字幕</comment>
+ <comment xml:lang="vi">Phụ đề MicroDVD</comment>
+ <comment xml:lang="uk">субтитри MicroDVD</comment>
+ <comment xml:lang="tr">MicroDVD alt yazısı</comment>
+ <comment xml:lang="sv">MicroDVD-undertexter</comment>
+ <comment xml:lang="sr">Микро ДВД преводи</comment>
+ <comment xml:lang="sq">titra MicroDVD</comment>
+ <comment xml:lang="sl">Datoteka podnapisov MicroDVD</comment>
+ <comment xml:lang="si">MicroDVD උපසිරැසි</comment>
+ <comment xml:lang="sk">Titulky MicroDVD</comment>
+ <comment xml:lang="ru">Субтитры MicroDVD</comment>
+ <comment xml:lang="ro">Subtitrări MicroDVD</comment>
+ <comment xml:lang="pt_BR">Legendas MicroDVD</comment>
+ <comment xml:lang="pt">legendas MicroDVD</comment>
+ <comment xml:lang="pl">Napisy MicroDVD</comment>
+ <comment xml:lang="oc">sostítols MicroDVD</comment>
+ <comment xml:lang="nn">MicroDVD-teksting</comment>
+ <comment xml:lang="nl">MicroDVD-ondertitels</comment>
+ <comment xml:lang="nb">MicroDVD undertekst</comment>
+ <comment xml:lang="lv">MicroDVD subtitri</comment>
+ <comment xml:lang="lt">MicroDVD subtitrai</comment>
+ <comment xml:lang="ko">MicroDVD 자막 파일</comment>
+ <comment xml:lang="kk">MicroDVD субтитрлары</comment>
+ <comment xml:lang="ka">MicroDVD-ის ქვეტიტრები</comment>
+ <comment xml:lang="ja">MicroDVD 字幕</comment>
+ <comment xml:lang="it">Sottotitoli MicroDVD</comment>
+ <comment xml:lang="is">MicroDVD skjátextar</comment>
+ <comment xml:lang="id">Subjudul MicroDVD</comment>
+ <comment xml:lang="ia">Subtitulos MicroDVD</comment>
+ <comment xml:lang="hu">MicroDVD feliratok</comment>
+ <comment xml:lang="hr">MicroDVD podnaslovi</comment>
+ <comment xml:lang="he">כתוביות של MicroDVD</comment>
+ <comment xml:lang="gl">subtítulos de MicroDVD</comment>
+ <comment xml:lang="ga">fotheidil MicroDVD</comment>
+ <comment xml:lang="fur">sottitui MicroDVD</comment>
+ <comment xml:lang="fr">sous-titres MicroDVD</comment>
+ <comment xml:lang="fo">MicroDVD undirtekstir</comment>
+ <comment xml:lang="fi">MicroDVD-tekstitykset</comment>
+ <comment xml:lang="eu">MicroDVD azpitituluak</comment>
+ <comment xml:lang="es">subtítulos de MicroDVD</comment>
+ <comment xml:lang="eo">MicroDVD-subtekstoj</comment>
+ <comment xml:lang="en_GB">MicroDVD subtitles</comment>
+ <comment xml:lang="el">Υπότιτλοι MicroDVD</comment>
+ <comment xml:lang="de">MicroDVD-Untertitel</comment>
+ <comment xml:lang="da">MicroDVD-undertekster</comment>
+ <comment xml:lang="cs">titulky MicroDVD</comment>
+ <comment xml:lang="ca">subtítols MicroDVD</comment>
+ <comment xml:lang="bg">Субтитри — MicroDVD</comment>
+ <comment xml:lang="be@latin">Subtytry MicroDVD</comment>
+ <comment xml:lang="be">субцітры MicroDVD</comment>
+ <comment xml:lang="ar">ترجمات MicroDVD</comment>
+ <comment xml:lang="af">MicroDVD-onderskrifte</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="{1}" type="string" offset="0"/>
- <match value="{0}" type="string" offset="0"/>
- <match value="}{" type="string" offset="0:6"/>
+ <magic>
+ <match type="string" value="{1}" offset="0"/>
+ <match type="string" value="{0}" offset="0"/>
+ <match type="string" value="}{" offset="0:6"/>
</magic>
<glob pattern="*.sub"/>
</mime-type>
+ <mime-type type="text/x-mpl2">
+ <comment>MPL2 subtitles</comment>
+ <comment xml:lang="uk">субтитри MPL2</comment>
+ <comment xml:lang="sv">MPL2-undertexter</comment>
+ <comment xml:lang="ru">Субтитры MPL2</comment>
+ <comment xml:lang="pl">Napisy MPL2</comment>
+ <comment xml:lang="es">subtítulos MPL2</comment>
+ <comment xml:lang="de">MPL2-Untertitel</comment>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="[1]" offset="0"/>
+ <match type="string" value="[0]" offset="0"/>
+ <match type="string" value="][" offset="0:6"/>
+ </magic>
+ <glob pattern="*.mpl"/>
+ </mime-type>
<mime-type type="text/x-mpsub">
- <comment>MPSub subtitles</comment>
- <comment xml:lang="ar">ترجمات MPSub</comment>
- <comment xml:lang="be@latin">Subtytry MPSub</comment>
- <comment xml:lang="bg">Субтитри — MPSub</comment>
- <comment xml:lang="ca">subtítols MPSub</comment>
- <comment xml:lang="cs">titulky MPSub</comment>
- <comment xml:lang="da">MPSub-undertekster</comment>
- <comment xml:lang="de">MPSub-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι MPSub</comment>
- <comment xml:lang="en_GB">MPSub subtitles</comment>
- <comment xml:lang="eo">MPSub-subtekstoj</comment>
- <comment xml:lang="es">subtítulos MPSub</comment>
- <comment xml:lang="eu">MPSub azpitituluak</comment>
- <comment xml:lang="fi">MPSub-tekstitykset</comment>
- <comment xml:lang="fo">MPSub undirtekstir</comment>
- <comment xml:lang="fr">sous-titres MPSub</comment>
- <comment xml:lang="ga">fotheidil MPSub</comment>
- <comment xml:lang="gl">subtítulos MPSub</comment>
- <comment xml:lang="he">כתוביות MPSub</comment>
- <comment xml:lang="hr">MPSub podnaslovi</comment>
- <comment xml:lang="hu">MPSub feliratok</comment>
- <comment xml:lang="ia">Subtitulos MPSub</comment>
- <comment xml:lang="id">Subjudul MPSub</comment>
- <comment xml:lang="it">Sottotitoli MPSub</comment>
- <comment xml:lang="ja">MPSub サブタイトル</comment>
- <comment xml:lang="ka">MPSub ქვეტიტრები</comment>
- <comment xml:lang="kk">MPSub субтитрлары</comment>
- <comment xml:lang="ko">MPSub 자막 파일</comment>
- <comment xml:lang="lt">MPSub subtitrai</comment>
- <comment xml:lang="lv">MPSub subtitri</comment>
- <comment xml:lang="nb">MPSub undertekst</comment>
- <comment xml:lang="nl">MPSub-ondertitels</comment>
- <comment xml:lang="nn">MPSub-undertekstar</comment>
- <comment xml:lang="oc">sostítols MPSub</comment>
- <comment xml:lang="pl">Napisy MPSub</comment>
- <comment xml:lang="pt">legendas MPSub</comment>
- <comment xml:lang="pt_BR">Legendas MPSub</comment>
- <comment xml:lang="ro">Subtitrări MPSub</comment>
- <comment xml:lang="ru">Субтитры MPSub</comment>
- <comment xml:lang="sk">Titulky MPSub</comment>
- <comment xml:lang="sl">Datoteka podnapisov MPSub</comment>
- <comment xml:lang="sq">Nëntituj MPSub</comment>
- <comment xml:lang="sr">МПСуб преводи</comment>
- <comment xml:lang="sv">MPSub-undertexter</comment>
- <comment xml:lang="tr">MPSub altyazıları</comment>
- <comment xml:lang="uk">субтитри MPSub</comment>
- <comment xml:lang="vi">Phụ đề MPSub</comment>
- <comment xml:lang="zh_CN">MPSub 字幕</comment>
- <comment xml:lang="zh_TW">MPSub 字幕</comment>
- <acronym>MPSub</acronym>
- <expanded-acronym>MPlayer Subtitle</expanded-acronym>
+ <comment>MPlayer subtitles</comment>
+ <comment xml:lang="uk">субтитри MPlayer</comment>
+ <comment xml:lang="sv">MPlayer-undertexter</comment>
+ <comment xml:lang="ru">Субтитры MPlayer</comment>
+ <comment xml:lang="pl">Napisy MPlayer</comment>
+ <comment xml:lang="es">subtítulos de MPlayer</comment>
+ <comment xml:lang="de">MPlayer-Untertitel</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="FORMAT=" type="string" offset="0:256"/>
+ <magic priority="40">
+ <match type="string" value="FORMAT=" offset="0:256"/>
</magic>
<glob pattern="*.sub"/>
</mime-type>
<mime-type type="text/x-ssa">
<comment>SSA subtitles</comment>
- <comment xml:lang="ar">ترجمات SSA</comment>
- <comment xml:lang="be@latin">Subtytry SSA</comment>
- <comment xml:lang="bg">Субтитри — SSA</comment>
- <comment xml:lang="ca">subtítols SSA</comment>
- <comment xml:lang="cs">titulky SSA</comment>
- <comment xml:lang="da">SSA-undertekster</comment>
- <comment xml:lang="de">SSA-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι SSA</comment>
- <comment xml:lang="en_GB">SSA subtitles</comment>
- <comment xml:lang="eo">SSA-subtekstoj</comment>
- <comment xml:lang="es">subtítulos SSA</comment>
- <comment xml:lang="eu">SSA azpitituluak</comment>
- <comment xml:lang="fi">SSA-tekstitykset</comment>
- <comment xml:lang="fo">SSA undirtekstir</comment>
- <comment xml:lang="fr">sous-titres SSA</comment>
- <comment xml:lang="ga">fotheidil SSA</comment>
- <comment xml:lang="gl">Subtitulos SSA</comment>
- <comment xml:lang="he">כתובית SSA</comment>
- <comment xml:lang="hr">SSA podnaslovi</comment>
- <comment xml:lang="hu">SSA feliratok</comment>
- <comment xml:lang="ia">Subtitulos SSA</comment>
- <comment xml:lang="id">Subjudul SSA</comment>
- <comment xml:lang="it">Sottotitoli SSA</comment>
- <comment xml:lang="ja">SSA 字幕</comment>
- <comment xml:lang="kk">SSA субтитрлары</comment>
- <comment xml:lang="ko">SSA 자막 파일</comment>
- <comment xml:lang="lt">SSA subtitrai</comment>
- <comment xml:lang="lv">SSA subtitri</comment>
- <comment xml:lang="nb">SSA undertekst</comment>
- <comment xml:lang="nl">SSA-ondertitels</comment>
- <comment xml:lang="nn">SSA-teksting</comment>
- <comment xml:lang="oc">sostítols SSA</comment>
- <comment xml:lang="pl">Napisy SSA</comment>
- <comment xml:lang="pt">legendas SSA</comment>
- <comment xml:lang="pt_BR">Legendas SSA</comment>
- <comment xml:lang="ro">Subtitrări SSA</comment>
- <comment xml:lang="ru">Субтитры SSA</comment>
- <comment xml:lang="sk">Titulky SSA</comment>
- <comment xml:lang="sl">Datoteka podnapisov SSA</comment>
- <comment xml:lang="sq">Nëntituj SSA</comment>
- <comment xml:lang="sr">ССА преводи</comment>
- <comment xml:lang="sv">SSA-undertexter</comment>
- <comment xml:lang="tr">SSA altyazıları</comment>
- <comment xml:lang="uk">субтитри SSA</comment>
- <comment xml:lang="vi">Phụ đề SSA</comment>
- <comment xml:lang="zh_CN">SSA 字幕</comment>
<comment xml:lang="zh_TW">SSA 字幕</comment>
+ <comment xml:lang="zh_CN">SSA 字幕</comment>
+ <comment xml:lang="vi">Phụ đề SSA</comment>
+ <comment xml:lang="uk">субтитри SSA</comment>
+ <comment xml:lang="tr">SSA alt yazıları</comment>
+ <comment xml:lang="sv">SSA-undertexter</comment>
+ <comment xml:lang="sr">ССА преводи</comment>
+ <comment xml:lang="sq">titra SSA</comment>
+ <comment xml:lang="sl">Datoteka podnapisov SSA</comment>
+ <comment xml:lang="si">SSA උපසිරැසි</comment>
+ <comment xml:lang="sk">Titulky SSA</comment>
+ <comment xml:lang="ru">Субтитры SSA</comment>
+ <comment xml:lang="ro">Subtitrări SSA</comment>
+ <comment xml:lang="pt_BR">Legendas SSA</comment>
+ <comment xml:lang="pt">legendas SSA</comment>
+ <comment xml:lang="pl">Napisy SSA</comment>
+ <comment xml:lang="oc">sostítols SSA</comment>
+ <comment xml:lang="nn">SSA-teksting</comment>
+ <comment xml:lang="nl">SSA-ondertitels</comment>
+ <comment xml:lang="nb">SSA undertekst</comment>
+ <comment xml:lang="lv">SSA subtitri</comment>
+ <comment xml:lang="lt">SSA subtitrai</comment>
+ <comment xml:lang="ko">SSA 자막 파일</comment>
+ <comment xml:lang="kk">SSA субтитрлары</comment>
+ <comment xml:lang="ja">SSA 字幕</comment>
+ <comment xml:lang="it">Sottotitoli SSA</comment>
+ <comment xml:lang="is">SSA skjátextar</comment>
+ <comment xml:lang="id">Subjudul SSA</comment>
+ <comment xml:lang="ia">Subtitulos SSA</comment>
+ <comment xml:lang="hu">SSA feliratok</comment>
+ <comment xml:lang="hr">SSA podnaslovi</comment>
+ <comment xml:lang="he">כתובית SSA</comment>
+ <comment xml:lang="gl">Subtitulos SSA</comment>
+ <comment xml:lang="ga">fotheidil SSA</comment>
+ <comment xml:lang="fur">sottitui SSA</comment>
+ <comment xml:lang="fr">sous-titres SSA</comment>
+ <comment xml:lang="fo">SSA undirtekstir</comment>
+ <comment xml:lang="fi">SSA-tekstitykset</comment>
+ <comment xml:lang="eu">SSA azpitituluak</comment>
+ <comment xml:lang="es">subtítulos SSA</comment>
+ <comment xml:lang="eo">SSA-subtekstoj</comment>
+ <comment xml:lang="en_GB">SSA subtitles</comment>
+ <comment xml:lang="el">Υπότιτλοι SSA</comment>
+ <comment xml:lang="de">SSA-Untertitel</comment>
+ <comment xml:lang="da">SSA-undertekster</comment>
+ <comment xml:lang="cs">titulky SSA</comment>
+ <comment xml:lang="ca">subtítols SSA</comment>
+ <comment xml:lang="bg">Субтитри — SSA</comment>
+ <comment xml:lang="be@latin">Subtytry SSA</comment>
+ <comment xml:lang="be">субцітры SSA</comment>
+ <comment xml:lang="ar">ترجمات SSA</comment>
+ <comment xml:lang="af">SSA-onderskrifte</comment>
<acronym>SSA</acronym>
<expanded-acronym>SubStation Alpha</expanded-acronym>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="[Script Info]" type="string" offset="0:256"/>
- <match value="Dialogue: " type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="[Script Info]" offset="0:256"/>
+ <match type="string" value="Dialogue: " offset="0:256"/>
</magic>
<glob pattern="*.ssa"/>
<glob pattern="*.ass"/>
</mime-type>
<mime-type type="text/x-subviewer">
<comment>SubViewer subtitles</comment>
- <comment xml:lang="ar">ترجمات SubViewer</comment>
- <comment xml:lang="be@latin">Subtytry SubViewer</comment>
- <comment xml:lang="bg">Субтитри — SubViewer</comment>
- <comment xml:lang="ca">subtítols SubViewer</comment>
- <comment xml:lang="cs">titulky SubViewer</comment>
- <comment xml:lang="da">SubViewer-undertekster</comment>
- <comment xml:lang="de">SubViewer-Untertitel</comment>
- <comment xml:lang="el">Υπότιτλοι SubViewer</comment>
- <comment xml:lang="en_GB">SubViewer subtitles</comment>
- <comment xml:lang="eo">SubViewer-subtekstoj</comment>
- <comment xml:lang="es">subtítulos SubViewer</comment>
- <comment xml:lang="eu">SubViewer azpitituluak</comment>
- <comment xml:lang="fi">SubViewer-tekstitykset</comment>
- <comment xml:lang="fo">SubViewer undirtekstir</comment>
- <comment xml:lang="fr">sous-titres SubViewer</comment>
- <comment xml:lang="ga">fotheidil SubViewer</comment>
- <comment xml:lang="gl">subtítulos SubViewer</comment>
- <comment xml:lang="he">כתוביות של SubViewer</comment>
- <comment xml:lang="hr">SubViewer podnaslovi</comment>
- <comment xml:lang="hu">SubViewer feliratok</comment>
- <comment xml:lang="ia">Subtitulos SubViewer</comment>
- <comment xml:lang="id">Subjudul SubViewer</comment>
- <comment xml:lang="it">Sottotitoli SubViewer</comment>
- <comment xml:lang="ja">SubViewer 字幕</comment>
- <comment xml:lang="kk">SubViewer субтитрлары</comment>
- <comment xml:lang="ko">SubViewer 자막 파일</comment>
- <comment xml:lang="lt">SubViewer subtitrai</comment>
- <comment xml:lang="lv">SubViewer subtitri</comment>
- <comment xml:lang="nb">SubViewer undertekst</comment>
- <comment xml:lang="nl">SubViewer-ondertitels</comment>
- <comment xml:lang="nn">SubViewer-teksting</comment>
- <comment xml:lang="oc">sostítols SubViewer</comment>
- <comment xml:lang="pl">Napisy SubViewer</comment>
- <comment xml:lang="pt">legendas SubViewer</comment>
- <comment xml:lang="pt_BR">Legendas SubViewer</comment>
- <comment xml:lang="ro">Subtitrare SubViewer</comment>
- <comment xml:lang="ru">Субтитры SubViewer</comment>
- <comment xml:lang="sk">Titulky SubViewer</comment>
- <comment xml:lang="sl">Datoteka podnapisov SubViewer</comment>
- <comment xml:lang="sq">Nëntituj SubViewer</comment>
- <comment xml:lang="sr">Суб Вјивер преводи</comment>
- <comment xml:lang="sv">SubViewer-undertexter</comment>
- <comment xml:lang="tr">SubViewer altyazıları</comment>
- <comment xml:lang="uk">субтитри SubViewer</comment>
- <comment xml:lang="vi">Phụ đề SubViewer</comment>
- <comment xml:lang="zh_CN">SubViewer 字幕</comment>
<comment xml:lang="zh_TW">SubViewer 字幕</comment>
+ <comment xml:lang="zh_CN">SubViewer 字幕</comment>
+ <comment xml:lang="vi">Phụ đề SubViewer</comment>
+ <comment xml:lang="uk">субтитри SubViewer</comment>
+ <comment xml:lang="tr">SubViewer alt yazıları</comment>
+ <comment xml:lang="sv">SubViewer-undertexter</comment>
+ <comment xml:lang="sr">Суб Вјивер преводи</comment>
+ <comment xml:lang="sq">titra SubViewer</comment>
+ <comment xml:lang="sl">Datoteka podnapisov SubViewer</comment>
+ <comment xml:lang="si">SubViewer උපසිරැසි</comment>
+ <comment xml:lang="sk">Titulky SubViewer</comment>
+ <comment xml:lang="ru">Субтитры SubViewer</comment>
+ <comment xml:lang="ro">Subtitrare SubViewer</comment>
+ <comment xml:lang="pt_BR">Legendas SubViewer</comment>
+ <comment xml:lang="pt">legendas SubViewer</comment>
+ <comment xml:lang="pl">Napisy SubViewer</comment>
+ <comment xml:lang="oc">sostítols SubViewer</comment>
+ <comment xml:lang="nn">SubViewer-teksting</comment>
+ <comment xml:lang="nl">SubViewer-ondertitels</comment>
+ <comment xml:lang="nb">SubViewer undertekst</comment>
+ <comment xml:lang="lv">SubViewer subtitri</comment>
+ <comment xml:lang="lt">SubViewer subtitrai</comment>
+ <comment xml:lang="ko">SubViewer 자막 파일</comment>
+ <comment xml:lang="kk">SubViewer субтитрлары</comment>
+ <comment xml:lang="ja">SubViewer 字幕</comment>
+ <comment xml:lang="it">Sottotitoli SubViewer</comment>
+ <comment xml:lang="is">SubViewer skjátextar</comment>
+ <comment xml:lang="id">Subjudul SubViewer</comment>
+ <comment xml:lang="ia">Subtitulos SubViewer</comment>
+ <comment xml:lang="hu">SubViewer feliratok</comment>
+ <comment xml:lang="hr">SubViewer podnaslovi</comment>
+ <comment xml:lang="he">כתוביות של SubViewer</comment>
+ <comment xml:lang="gl">subtítulos SubViewer</comment>
+ <comment xml:lang="ga">fotheidil SubViewer</comment>
+ <comment xml:lang="fur">sottitui SubViewer</comment>
+ <comment xml:lang="fr">sous-titres SubViewer</comment>
+ <comment xml:lang="fo">SubViewer undirtekstir</comment>
+ <comment xml:lang="fi">SubViewer-tekstitykset</comment>
+ <comment xml:lang="eu">SubViewer azpitituluak</comment>
+ <comment xml:lang="es">subtítulos SubViewer</comment>
+ <comment xml:lang="eo">SubViewer-subtekstoj</comment>
+ <comment xml:lang="en_GB">SubViewer subtitles</comment>
+ <comment xml:lang="el">Υπότιτλοι SubViewer</comment>
+ <comment xml:lang="de">SubViewer-Untertitel</comment>
+ <comment xml:lang="da">SubViewer-undertekster</comment>
+ <comment xml:lang="cs">titulky SubViewer</comment>
+ <comment xml:lang="ca">subtítols SubViewer</comment>
+ <comment xml:lang="bg">Субтитри — SubViewer</comment>
+ <comment xml:lang="be@latin">Subtytry SubViewer</comment>
+ <comment xml:lang="be">субцітры SubViewer</comment>
+ <comment xml:lang="ar">ترجمات SubViewer</comment>
+ <comment xml:lang="af">SubViewer-onderskrifte</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="[INFORMATION]" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="[INFORMATION]" offset="0"/>
</magic>
<glob pattern="*.sub"/>
</mime-type>
<mime-type type="text/x-iMelody">
<comment>iMelody ringtone</comment>
- <comment xml:lang="ar">نغمة iMelody</comment>
- <comment xml:lang="be@latin">Rington iMelody</comment>
- <comment xml:lang="bg">Аудио — iMelody</comment>
- <comment xml:lang="ca">to de trucada iMelody</comment>
- <comment xml:lang="cs">vyzváněcí melodie iMelody</comment>
- <comment xml:lang="da">iMelody-ringetone</comment>
- <comment xml:lang="de">iMelody-Klingelton</comment>
- <comment xml:lang="el">ringtone iMelody</comment>
- <comment xml:lang="en_GB">iMelody ringtone</comment>
- <comment xml:lang="es">tono de llamada iMelody</comment>
- <comment xml:lang="eu">iMelody doinua</comment>
- <comment xml:lang="fi">iMelody-soittoääni</comment>
- <comment xml:lang="fo">iMelody ringitóni</comment>
- <comment xml:lang="fr">sonnerie iMelody</comment>
- <comment xml:lang="ga">ton buailte iMelody</comment>
- <comment xml:lang="gl">Melodía de iMelody</comment>
- <comment xml:lang="he">צלצול של iMelody</comment>
- <comment xml:lang="hr">iMelody melodija zvona</comment>
- <comment xml:lang="hu">iMelody csengőhang</comment>
- <comment xml:lang="ia">Tono de appello iMelody</comment>
- <comment xml:lang="id">nada dering iMelody</comment>
- <comment xml:lang="it">Suoneria iMelody</comment>
- <comment xml:lang="ja">iMelody リングトーン</comment>
- <comment xml:lang="kk">iMelody әуені</comment>
- <comment xml:lang="ko">iMelody 벨소리</comment>
- <comment xml:lang="lt">iMelody skambučio melodija</comment>
- <comment xml:lang="lv">iMelody melodija</comment>
- <comment xml:lang="nb">iMelody ringetone</comment>
- <comment xml:lang="nl">iMelody-beltoon</comment>
- <comment xml:lang="nn">iMelody-ringetone</comment>
- <comment xml:lang="oc">sonariá iMelody</comment>
- <comment xml:lang="pl">Dzwonek iMelody</comment>
- <comment xml:lang="pt">toque iMelody</comment>
- <comment xml:lang="pt_BR">Toque de celular do iMelody</comment>
- <comment xml:lang="ro">Sonerie iMelody</comment>
- <comment xml:lang="ru">Мелодия iMelody</comment>
- <comment xml:lang="sk">Vyzváňacie melódie iMelody</comment>
- <comment xml:lang="sl">Zvonjenje iMelody</comment>
- <comment xml:lang="sq">Zile iMelody</comment>
- <comment xml:lang="sr">звоно ајМелодије</comment>
- <comment xml:lang="sv">iMelody-ringsignal</comment>
- <comment xml:lang="tr">iMelody melodisi</comment>
- <comment xml:lang="uk">рінгтон iMelody</comment>
- <comment xml:lang="vi">tiếng réo iMelody</comment>
- <comment xml:lang="zh_CN">iMelody 铃声</comment>
<comment xml:lang="zh_TW">iMelody 鈴聲</comment>
- <magic priority="50">
- <match value="BEGIN:IMELODY" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">iMelody 铃声</comment>
+ <comment xml:lang="vi">tiếng réo iMelody</comment>
+ <comment xml:lang="uk">рінгтон iMelody</comment>
+ <comment xml:lang="tr">iMelody melodisi</comment>
+ <comment xml:lang="sv">iMelody-ringsignal</comment>
+ <comment xml:lang="sr">звоно ајМелодије</comment>
+ <comment xml:lang="sq">zile iMelody</comment>
+ <comment xml:lang="sl">Zvonjenje iMelody</comment>
+ <comment xml:lang="si">iMelody නාද රටා</comment>
+ <comment xml:lang="sk">Vyzváňacie melódie iMelody</comment>
+ <comment xml:lang="ru">Мелодия iMelody</comment>
+ <comment xml:lang="ro">Sonerie iMelody</comment>
+ <comment xml:lang="pt_BR">Toque de celular do iMelody</comment>
+ <comment xml:lang="pt">toque iMelody</comment>
+ <comment xml:lang="pl">Dzwonek iMelody</comment>
+ <comment xml:lang="oc">sonariá iMelody</comment>
+ <comment xml:lang="nn">iMelody-ringetone</comment>
+ <comment xml:lang="nl">iMelody-beltoon</comment>
+ <comment xml:lang="nb">iMelody ringetone</comment>
+ <comment xml:lang="lv">iMelody melodija</comment>
+ <comment xml:lang="lt">iMelody skambučio melodija</comment>
+ <comment xml:lang="ko">iMelody 벨소리</comment>
+ <comment xml:lang="kk">iMelody әуені</comment>
+ <comment xml:lang="ja">iMelody リングトーン</comment>
+ <comment xml:lang="it">Suoneria iMelody</comment>
+ <comment xml:lang="is">iMelody hringitónn</comment>
+ <comment xml:lang="id">nada dering iMelody</comment>
+ <comment xml:lang="ia">Tono de appello iMelody</comment>
+ <comment xml:lang="hu">iMelody csengőhang</comment>
+ <comment xml:lang="hr">iMelody melodija zvona</comment>
+ <comment xml:lang="he">צלצול של iMelody</comment>
+ <comment xml:lang="gl">Melodía de iMelody</comment>
+ <comment xml:lang="ga">ton buailte iMelody</comment>
+ <comment xml:lang="fur">sunarie iMelody</comment>
+ <comment xml:lang="fr">sonnerie iMelody</comment>
+ <comment xml:lang="fo">iMelody ringitóni</comment>
+ <comment xml:lang="fi">iMelody-soittoääni</comment>
+ <comment xml:lang="eu">iMelody doinua</comment>
+ <comment xml:lang="es">tono de llamada iMelody</comment>
+ <comment xml:lang="en_GB">iMelody ringtone</comment>
+ <comment xml:lang="el">ringtone iMelody</comment>
+ <comment xml:lang="de">iMelody-Klingelton</comment>
+ <comment xml:lang="da">iMelody-ringetone</comment>
+ <comment xml:lang="cs">vyzváněcí melodie iMelody</comment>
+ <comment xml:lang="ca">to de trucada iMelody</comment>
+ <comment xml:lang="bg">Аудио — iMelody</comment>
+ <comment xml:lang="be@latin">Rington iMelody</comment>
+ <comment xml:lang="be">мелодыя выкліку iMelody</comment>
+ <comment xml:lang="ar">نغمة iMelody</comment>
+ <comment xml:lang="af">iMelody-luitoon</comment>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="BEGIN:IMELODY" offset="0"/>
</magic>
<glob pattern="*.imy"/>
<glob pattern="*.ime"/>
<alias type="audio/x-iMelody"/>
<alias type="audio/iMelody"/>
</mime-type>
- <mime-type type="application/x-smaf">
+ <mime-type type="application/vnd.smaf">
<comment>SMAF audio</comment>
- <comment xml:lang="ar">SMAF سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo SMAF</comment>
- <comment xml:lang="bg">Аудио — SMAF</comment>
- <comment xml:lang="ca">àudio SMAF</comment>
- <comment xml:lang="cs">zvuk SMAF</comment>
- <comment xml:lang="da">SMAF-lyd</comment>
- <comment xml:lang="de">SMAF-Audio</comment>
- <comment xml:lang="el">Ήχος SMAF</comment>
- <comment xml:lang="en_GB">SMAF audio</comment>
- <comment xml:lang="eo">SMAF-sondosiero</comment>
- <comment xml:lang="es">sonido SMAF</comment>
- <comment xml:lang="eu">SMAF audioa</comment>
- <comment xml:lang="fi">SMAF-ääni</comment>
- <comment xml:lang="fo">SMAF ljóður</comment>
- <comment xml:lang="fr">audio SMAF</comment>
- <comment xml:lang="ga">fuaim SMAF</comment>
- <comment xml:lang="gl">son SMAF</comment>
- <comment xml:lang="he">שמע SMAF</comment>
- <comment xml:lang="hr">SMAF zvučni zapis</comment>
- <comment xml:lang="hu">SMAF hang</comment>
- <comment xml:lang="ia">Audio SMAF</comment>
- <comment xml:lang="id">Audio SMAF</comment>
- <comment xml:lang="it">Audio SMAF</comment>
- <comment xml:lang="ja">SMAF オーディオ</comment>
- <comment xml:lang="kk">SMAF аудиосы</comment>
- <comment xml:lang="ko">SMAF 오디오</comment>
- <comment xml:lang="lt">SMAF garso įrašas</comment>
- <comment xml:lang="lv">SMAF audio</comment>
- <comment xml:lang="nb">SMAF-lyd</comment>
- <comment xml:lang="nl">SMAF-audio</comment>
- <comment xml:lang="nn">SMAF-lyd</comment>
- <comment xml:lang="oc">àudio SMAF</comment>
- <comment xml:lang="pl">Plik dźwiękowy SMAF</comment>
- <comment xml:lang="pt">áudio SMAF</comment>
- <comment xml:lang="pt_BR">Áudio SMAF</comment>
- <comment xml:lang="ro">Audio SMAF</comment>
- <comment xml:lang="ru">Аудио SMAF</comment>
- <comment xml:lang="sk">Zvuk SMAF</comment>
- <comment xml:lang="sl">Zvočna datoteka SMAF</comment>
- <comment xml:lang="sq">Audio SMAF</comment>
- <comment xml:lang="sr">СМАФ звук</comment>
- <comment xml:lang="sv">SMAF-ljud</comment>
- <comment xml:lang="tr">SMAF sesi</comment>
- <comment xml:lang="uk">звук SMAF</comment>
- <comment xml:lang="vi">Âm thanh SMAF</comment>
- <comment xml:lang="zh_CN">SMAF 音频</comment>
<comment xml:lang="zh_TW">SMAF 音訊</comment>
+ <comment xml:lang="zh_CN">SMAF 音频</comment>
+ <comment xml:lang="vi">Âm thanh SMAF</comment>
+ <comment xml:lang="uk">звук SMAF</comment>
+ <comment xml:lang="tr">SMAF sesi</comment>
+ <comment xml:lang="sv">SMAF-ljud</comment>
+ <comment xml:lang="sr">СМАФ звук</comment>
+ <comment xml:lang="sq">audio SMAF</comment>
+ <comment xml:lang="sl">Zvočna datoteka SMAF</comment>
+ <comment xml:lang="si">SMAF ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk SMAF</comment>
+ <comment xml:lang="ru">Аудио SMAF</comment>
+ <comment xml:lang="ro">Audio SMAF</comment>
+ <comment xml:lang="pt_BR">Áudio SMAF</comment>
+ <comment xml:lang="pt">áudio SMAF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy SMAF</comment>
+ <comment xml:lang="oc">àudio SMAF</comment>
+ <comment xml:lang="nn">SMAF-lyd</comment>
+ <comment xml:lang="nl">SMAF-audio</comment>
+ <comment xml:lang="nb">SMAF-lyd</comment>
+ <comment xml:lang="lv">SMAF audio</comment>
+ <comment xml:lang="lt">SMAF garso įrašas</comment>
+ <comment xml:lang="ko">SMAF 오디오</comment>
+ <comment xml:lang="kk">SMAF аудиосы</comment>
+ <comment xml:lang="ja">SMAF オーディオ</comment>
+ <comment xml:lang="it">Audio SMAF</comment>
+ <comment xml:lang="is">SMAF hljóðskrá</comment>
+ <comment xml:lang="id">Audio SMAF</comment>
+ <comment xml:lang="ia">Audio SMAF</comment>
+ <comment xml:lang="hu">SMAF hang</comment>
+ <comment xml:lang="hr">SMAF zvučni zapis</comment>
+ <comment xml:lang="he">שמע SMAF</comment>
+ <comment xml:lang="gl">son SMAF</comment>
+ <comment xml:lang="ga">fuaim SMAF</comment>
+ <comment xml:lang="fur">audio SMAF</comment>
+ <comment xml:lang="fr">audio SMAF</comment>
+ <comment xml:lang="fo">SMAF ljóður</comment>
+ <comment xml:lang="fi">SMAF-ääni</comment>
+ <comment xml:lang="eu">SMAF audioa</comment>
+ <comment xml:lang="es">audio SMAF</comment>
+ <comment xml:lang="eo">SMAF-sondosiero</comment>
+ <comment xml:lang="en_GB">SMAF audio</comment>
+ <comment xml:lang="el">Ήχος SMAF</comment>
+ <comment xml:lang="de">SMAF-Audio</comment>
+ <comment xml:lang="da">SMAF-lyd</comment>
+ <comment xml:lang="cs">zvuk SMAF</comment>
+ <comment xml:lang="ca">àudio SMAF</comment>
+ <comment xml:lang="bg">Аудио — SMAF</comment>
+ <comment xml:lang="be@latin">Aŭdyjo SMAF</comment>
+ <comment xml:lang="be">аўдыя SMAF</comment>
+ <comment xml:lang="ar">صوت SMAF</comment>
+ <comment xml:lang="af">SMAF-oudio</comment>
<acronym>SMAF</acronym>
<expanded-acronym>Synthetic music Mobile Application Format</expanded-acronym>
<generic-icon name="audio-x-generic"/>
- <magic priority="50">
- <match value="MMMD" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="MMMD" offset="0"/>
</magic>
<glob pattern="*.mmf"/>
<glob pattern="*.smaf"/>
- <alias type="application/vnd.smaf"/>
+ <alias type="application/x-smaf"/>
</mime-type>
<mime-type type="text/x-mrml">
<comment>MRML playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل MRML</comment>
- <comment xml:lang="be@latin">Śpis piesień MRML</comment>
- <comment xml:lang="bg">Списък за изпълнение — MRML</comment>
- <comment xml:lang="ca">llista de reproducció MRML</comment>
- <comment xml:lang="cs">seznam k přehrání MRML</comment>
- <comment xml:lang="da">MRML-afspilningsliste</comment>
- <comment xml:lang="de">MRML-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής MRML</comment>
- <comment xml:lang="en_GB">MRML playlist</comment>
- <comment xml:lang="eo">MRML-ludlisto</comment>
- <comment xml:lang="es">lista de reproducción MRML</comment>
- <comment xml:lang="eu">MRML erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">MRML-soittolista</comment>
- <comment xml:lang="fo">MRML avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture MRML</comment>
- <comment xml:lang="ga">seinmliosta MRML</comment>
- <comment xml:lang="gl">lista de reprodución MRML</comment>
- <comment xml:lang="he">רשימת השמעה MRML</comment>
- <comment xml:lang="hr">MRML popis izvođenja</comment>
- <comment xml:lang="hu">MRML-lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection MRML</comment>
- <comment xml:lang="id">Senarai putar MRML</comment>
- <comment xml:lang="it">Playlist MRML</comment>
- <comment xml:lang="ja">MRML 再生リスト</comment>
- <comment xml:lang="ka">MRML რეპერტუარი</comment>
- <comment xml:lang="kk">MRML ойнау тізімі</comment>
- <comment xml:lang="ko">MRML 재생 목록</comment>
- <comment xml:lang="lt">MRML grojaraštis</comment>
- <comment xml:lang="lv">MRML repertuārs</comment>
- <comment xml:lang="nb">MRML-spilleliste</comment>
- <comment xml:lang="nl">MRML-afspeellijst</comment>
- <comment xml:lang="nn">MRML-speleliste</comment>
- <comment xml:lang="oc">lista de lectura MRML</comment>
- <comment xml:lang="pl">Lista odtwarzania MRML</comment>
- <comment xml:lang="pt">lista de reprodução MRML</comment>
- <comment xml:lang="pt_BR">Lista de reprodução do MRML</comment>
- <comment xml:lang="ro">Listă redare MRML</comment>
- <comment xml:lang="ru">Список воспроизведения MRML</comment>
- <comment xml:lang="sk">Zoznam skladieb MRML</comment>
- <comment xml:lang="sl">Seznam predvajanja MRML</comment>
- <comment xml:lang="sq">Listë titujsh MRML</comment>
- <comment xml:lang="sr">МРМЛ списак нумера</comment>
- <comment xml:lang="sv">MRML-spellista</comment>
- <comment xml:lang="tr">MRML oynatma listesi</comment>
- <comment xml:lang="uk">список відтворення MRML</comment>
- <comment xml:lang="vi">Danh mục nhạc MRML</comment>
- <comment xml:lang="zh_CN">MRML 播放列表</comment>
<comment xml:lang="zh_TW">MRML 播放清單</comment>
+ <comment xml:lang="zh_CN">MRML 播放列表</comment>
+ <comment xml:lang="vi">Danh mục nhạc MRML</comment>
+ <comment xml:lang="uk">список відтворення MRML</comment>
+ <comment xml:lang="tr">MRML çalma listesi</comment>
+ <comment xml:lang="sv">MRML-spellista</comment>
+ <comment xml:lang="sr">МРМЛ списак нумера</comment>
+ <comment xml:lang="sq">luajlistë MRML</comment>
+ <comment xml:lang="sl">Seznam predvajanja MRML</comment>
+ <comment xml:lang="si">MRML ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb MRML</comment>
+ <comment xml:lang="ru">Список воспроизведения MRML</comment>
+ <comment xml:lang="ro">Listă redare MRML</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução do MRML</comment>
+ <comment xml:lang="pt">lista de reprodução MRML</comment>
+ <comment xml:lang="pl">Lista odtwarzania MRML</comment>
+ <comment xml:lang="oc">lista de lectura MRML</comment>
+ <comment xml:lang="nn">MRML-speleliste</comment>
+ <comment xml:lang="nl">MRML-afspeellijst</comment>
+ <comment xml:lang="nb">MRML-spilleliste</comment>
+ <comment xml:lang="lv">MRML repertuārs</comment>
+ <comment xml:lang="lt">MRML grojaraštis</comment>
+ <comment xml:lang="ko">MRML 재생 목록</comment>
+ <comment xml:lang="kk">MRML ойнау тізімі</comment>
+ <comment xml:lang="ka">MRML რეპერტუარი</comment>
+ <comment xml:lang="ja">MRML プレイリスト</comment>
+ <comment xml:lang="it">Playlist MRML</comment>
+ <comment xml:lang="is">MRML spilunarlisti</comment>
+ <comment xml:lang="id">Senarai putar MRML</comment>
+ <comment xml:lang="ia">Lista de selection MRML</comment>
+ <comment xml:lang="hu">MRML-lejátszólista</comment>
+ <comment xml:lang="hr">MRML popis izvođenja</comment>
+ <comment xml:lang="he">רשימת השמעה MRML</comment>
+ <comment xml:lang="gl">lista de reprodución MRML</comment>
+ <comment xml:lang="ga">seinmliosta MRML</comment>
+ <comment xml:lang="fur">liste di riproduzion MRML</comment>
+ <comment xml:lang="fr">liste de lecture MRML</comment>
+ <comment xml:lang="fo">MRML avspælingarlisti</comment>
+ <comment xml:lang="fi">MRML-soittolista</comment>
+ <comment xml:lang="eu">MRML erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción MRML</comment>
+ <comment xml:lang="eo">MRML-ludlisto</comment>
+ <comment xml:lang="en_GB">MRML playlist</comment>
+ <comment xml:lang="el">Λίστα αναπαραγωγής MRML</comment>
+ <comment xml:lang="de">MRML-Wiedergabeliste</comment>
+ <comment xml:lang="da">MRML-afspilningsliste</comment>
+ <comment xml:lang="cs">seznam k přehrání MRML</comment>
+ <comment xml:lang="ca">llista de reproducció MRML</comment>
+ <comment xml:lang="bg">Списък за изпълнение — MRML</comment>
+ <comment xml:lang="be@latin">Śpis piesień MRML</comment>
+ <comment xml:lang="be">плэй-ліст MRML</comment>
+ <comment xml:lang="ar">قائمة تشغيل MRML</comment>
+ <comment xml:lang="af">MRML-speellys</comment>
<acronym>MRML</acronym>
<expanded-acronym>Multimedia Retrieval Markup Language</expanded-acronym>
- <magic priority="50">
- <match value="&lt;mrml " type="string" offset="0"/>
+ <sub-class-of type="application/xml"/>
+ <magic>
+ <match type="string" value="&lt;mrml " offset="0"/>
</magic>
<glob pattern="*.mrml"/>
<glob pattern="*.mrl"/>
</mime-type>
<mime-type type="audio/x-xmf">
<comment>XMF audio</comment>
- <comment xml:lang="ar">XMF سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo XMF</comment>
- <comment xml:lang="bg">Аудио — XMF</comment>
- <comment xml:lang="ca">àudio XMF</comment>
- <comment xml:lang="cs">zvuk XMF</comment>
- <comment xml:lang="da">XMF-lyd</comment>
- <comment xml:lang="de">XMF-Audio</comment>
- <comment xml:lang="el">Ήχος XMF</comment>
- <comment xml:lang="en_GB">XMF audio</comment>
- <comment xml:lang="eo">XMF-sondosiero</comment>
- <comment xml:lang="es">sonido XMF</comment>
- <comment xml:lang="eu">XMF audioa</comment>
- <comment xml:lang="fi">XMF-ääni</comment>
- <comment xml:lang="fo">XMF ljóður</comment>
- <comment xml:lang="fr">audio XMF</comment>
- <comment xml:lang="ga">fuaim XMF</comment>
- <comment xml:lang="gl">son XMF</comment>
- <comment xml:lang="he">שמע XMF</comment>
- <comment xml:lang="hr">XMF zvučni zapis</comment>
- <comment xml:lang="hu">XMF hang</comment>
- <comment xml:lang="ia">Audio XMF</comment>
- <comment xml:lang="id">Audio XMF</comment>
- <comment xml:lang="it">Audio XMF</comment>
- <comment xml:lang="ja">XMF オーディオ</comment>
- <comment xml:lang="kk">XMF аудиосы</comment>
- <comment xml:lang="ko">XMF 오디오</comment>
- <comment xml:lang="lt">XMF garso įrašas</comment>
- <comment xml:lang="lv">XMF audio</comment>
- <comment xml:lang="nb">XMF-lyd</comment>
- <comment xml:lang="nl">XMF-audio</comment>
- <comment xml:lang="nn">XMF-lyd</comment>
- <comment xml:lang="oc">àudio XMF</comment>
- <comment xml:lang="pl">Plik dźwiękowy XMF</comment>
- <comment xml:lang="pt">aúdio XMF</comment>
- <comment xml:lang="pt_BR">Áudio XMF</comment>
- <comment xml:lang="ro">Audio XMF</comment>
- <comment xml:lang="ru">Аудио XMF</comment>
- <comment xml:lang="sk">Zvuk XMF</comment>
- <comment xml:lang="sl">Zvočna datoteka XMF</comment>
- <comment xml:lang="sq">Audio XMF</comment>
- <comment xml:lang="sr">ИксМФ звук</comment>
- <comment xml:lang="sv">XMF-ljud</comment>
- <comment xml:lang="tr">XMF sesi</comment>
- <comment xml:lang="uk">звук XMF</comment>
- <comment xml:lang="vi">Âm thanh XMF</comment>
- <comment xml:lang="zh_CN">XMF 音频</comment>
<comment xml:lang="zh_TW">XMF 音訊</comment>
+ <comment xml:lang="zh_CN">XMF 音频</comment>
+ <comment xml:lang="vi">Âm thanh XMF</comment>
+ <comment xml:lang="uk">звук XMF</comment>
+ <comment xml:lang="tr">XMF sesi</comment>
+ <comment xml:lang="sv">XMF-ljud</comment>
+ <comment xml:lang="sr">ИксМФ звук</comment>
+ <comment xml:lang="sq">audio XMF</comment>
+ <comment xml:lang="sl">Zvočna datoteka XMF</comment>
+ <comment xml:lang="si">XMF ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk XMF</comment>
+ <comment xml:lang="ru">Аудио XMF</comment>
+ <comment xml:lang="ro">Audio XMF</comment>
+ <comment xml:lang="pt_BR">Áudio XMF</comment>
+ <comment xml:lang="pt">aúdio XMF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy XMF</comment>
+ <comment xml:lang="oc">àudio XMF</comment>
+ <comment xml:lang="nn">XMF-lyd</comment>
+ <comment xml:lang="nl">XMF-audio</comment>
+ <comment xml:lang="nb">XMF-lyd</comment>
+ <comment xml:lang="lv">XMF audio</comment>
+ <comment xml:lang="lt">XMF garso įrašas</comment>
+ <comment xml:lang="ko">XMF 오디오</comment>
+ <comment xml:lang="kk">XMF аудиосы</comment>
+ <comment xml:lang="ja">XMF オーディオ</comment>
+ <comment xml:lang="it">Audio XMF</comment>
+ <comment xml:lang="is">XMF hljóðskrá</comment>
+ <comment xml:lang="id">Audio XMF</comment>
+ <comment xml:lang="ia">Audio XMF</comment>
+ <comment xml:lang="hu">XMF hang</comment>
+ <comment xml:lang="hr">XMF zvučni zapis</comment>
+ <comment xml:lang="he">שמע XMF</comment>
+ <comment xml:lang="gl">son XMF</comment>
+ <comment xml:lang="ga">fuaim XMF</comment>
+ <comment xml:lang="fur">audio XMF</comment>
+ <comment xml:lang="fr">audio XMF</comment>
+ <comment xml:lang="fo">XMF ljóður</comment>
+ <comment xml:lang="fi">XMF-ääni</comment>
+ <comment xml:lang="eu">XMF audioa</comment>
+ <comment xml:lang="es">sonido XMF</comment>
+ <comment xml:lang="eo">XMF-sondosiero</comment>
+ <comment xml:lang="en_GB">XMF audio</comment>
+ <comment xml:lang="el">Ήχος XMF</comment>
+ <comment xml:lang="de">XMF-Audio</comment>
+ <comment xml:lang="da">XMF-lyd</comment>
+ <comment xml:lang="cs">zvuk XMF</comment>
+ <comment xml:lang="ca">àudio XMF</comment>
+ <comment xml:lang="bg">Аудио — XMF</comment>
+ <comment xml:lang="be@latin">Aŭdyjo XMF</comment>
+ <comment xml:lang="be">аўдыя XMF</comment>
+ <comment xml:lang="ar">صوت XMF</comment>
+ <comment xml:lang="af">XMF-oudio</comment>
<acronym>XMF</acronym>
<expanded-acronym>eXtensible Music Format</expanded-acronym>
- <magic priority="50">
- <match value="XMF_" type="string" offset="0"/>
- <match value="\130\115\106\137\062\056\060\060\000\000\000\002" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="XMF_" offset="0"/>
</magic>
<glob pattern="*.xmf"/>
<alias type="audio/xmf"/>
- <alias type="audio/mobile-xmf"/>
+ </mime-type>
+ <mime-type type="audio/mobile-xmf">
+ <comment>Mobile XMF audio</comment>
+ <comment xml:lang="uk">звукові дані Mobile XMF</comment>
+ <comment xml:lang="tr">Mobile XMF sesi</comment>
+ <comment xml:lang="sv">Mobile XMF-ljud</comment>
+ <comment xml:lang="sl">Zvok Mobile XMF</comment>
+ <comment xml:lang="si">ජංගම XMF ශ්රව්ය</comment>
+ <comment xml:lang="ru">Аудио Mobile XMF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Mobile XMF</comment>
+ <comment xml:lang="nl">Mobile XMF-audio</comment>
+ <comment xml:lang="ko">모바일 XMF 오디오</comment>
+ <comment xml:lang="kk">Mobile XMF аудиосы</comment>
+ <comment xml:lang="ja">Mobile XMF オーディオ</comment>
+ <comment xml:lang="it">Audio XMF mobile</comment>
+ <comment xml:lang="hr">Mobilni XMF zvuk</comment>
+ <comment xml:lang="fi">Mobiili XMF-ääni</comment>
+ <comment xml:lang="eu">Mobile XMF audioa</comment>
+ <comment xml:lang="es">audio Mobile XMF</comment>
+ <comment xml:lang="en_GB">Mobile XMF audio</comment>
+ <comment xml:lang="de">Mobile-XMF-Audio</comment>
+ <comment xml:lang="be">аўдыя MXMF</comment>
+ <comment xml:lang="ar">صوت Mobile XMF</comment>
+ <acronym>XMF</acronym>
+ <expanded-acronym>eXtensible Music Format</expanded-acronym>
+ <magic>
+ <match type="string" value="\130\115\106\137\062\056\060\060\000\000\000\002" offset="0"/>
+ </magic>
+ <glob pattern="*.mxmf"/>
+ <alias type="audio/vnd.nokia.mobile-xmf"/>
</mime-type>
<mime-type type="application/x-sv4cpio">
<comment>SV4 CPIO archive</comment>
- <comment xml:lang="ar">أرشيف SV4 CPIO</comment>
- <comment xml:lang="az">SV4 CPIO arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ SV4 CPIO</comment>
- <comment xml:lang="bg">Архив — SV4 CPIO</comment>
- <comment xml:lang="ca">arxiu CPIO SV4</comment>
- <comment xml:lang="cs">archiv SV4 CPIO</comment>
- <comment xml:lang="cy">Archif CPIO SV4</comment>
- <comment xml:lang="da">SV4 CPIO-arkiv</comment>
- <comment xml:lang="de">SV4-CPIO-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο SV4 CPIO</comment>
- <comment xml:lang="en_GB">SV4 CPIO archive</comment>
- <comment xml:lang="eo">SV4-CPIO-arkivo</comment>
- <comment xml:lang="es">archivador SV4 CPIO</comment>
- <comment xml:lang="eu">SV4 CPIO artxiboa</comment>
- <comment xml:lang="fi">SV4 CPIO -arkisto</comment>
- <comment xml:lang="fo">SV4 CPIO skjalasavn</comment>
- <comment xml:lang="fr">archive SV4 CPIO</comment>
- <comment xml:lang="ga">cartlann SV4 CPIO</comment>
- <comment xml:lang="gl">arquivo SV4 CPIO</comment>
- <comment xml:lang="he">ארכיון של SV4 SPIO</comment>
- <comment xml:lang="hr">SV4 CPIO arhiva</comment>
- <comment xml:lang="hu">SV4 CPIO-archívum</comment>
- <comment xml:lang="ia">Archivo CPIO SV4</comment>
- <comment xml:lang="id">Arsip SV4 CPIO</comment>
- <comment xml:lang="it">Archivio SV4 CPIO</comment>
- <comment xml:lang="ja">SV4 CPIO アーカイブ</comment>
- <comment xml:lang="kk">SV4 CPIO архиві</comment>
- <comment xml:lang="ko">SV4 CPIO 묶음 파일</comment>
- <comment xml:lang="lt">SV4 CPIO archyvas</comment>
- <comment xml:lang="lv">SV4 CPIO arhīvs</comment>
- <comment xml:lang="ms">Arkib CPIO SV4</comment>
- <comment xml:lang="nb">SV4 CPIO-arkiv</comment>
- <comment xml:lang="nl">SV4 CPIO-archief</comment>
- <comment xml:lang="nn">SV4 CPIO-arkiv</comment>
- <comment xml:lang="oc">archiu SV4 CPIO</comment>
- <comment xml:lang="pl">Archiwum SV4 CPIO</comment>
- <comment xml:lang="pt">arquivo SV4 CPIO</comment>
- <comment xml:lang="pt_BR">Pacote SV4 CPIO</comment>
- <comment xml:lang="ro">Arhivă SV4 CPIO</comment>
- <comment xml:lang="ru">Архив SV4 CPIO</comment>
- <comment xml:lang="sk">Archív SV4 CPIO</comment>
- <comment xml:lang="sl">Datoteka arhiva SV4 CPIO</comment>
- <comment xml:lang="sq">Arkiv SV4 CPIO</comment>
- <comment xml:lang="sr">СВ4 ЦПИО архива</comment>
- <comment xml:lang="sv">SV4 CPIO-arkiv</comment>
- <comment xml:lang="tr">SV4 CPIO arşivi</comment>
- <comment xml:lang="uk">архів SV4 CPIO</comment>
- <comment xml:lang="vi">Kho nén CPIO SV4</comment>
- <comment xml:lang="zh_CN">SV4 CPIO 归档文件</comment>
<comment xml:lang="zh_TW">SV4 CPIO 封存檔</comment>
+ <comment xml:lang="zh_CN">SV4 CPIO 归档文件</comment>
+ <comment xml:lang="vi">Kho nén CPIO SV4</comment>
+ <comment xml:lang="uk">архів SV4 CPIO</comment>
+ <comment xml:lang="tr">SV4 CPIO arşivi</comment>
+ <comment xml:lang="sv">SV4 CPIO-arkiv</comment>
+ <comment xml:lang="sr">СВ4 ЦПИО архива</comment>
+ <comment xml:lang="sq">arkiv SV4 CPIO</comment>
+ <comment xml:lang="sl">Datoteka arhiva SV4 CPIO</comment>
+ <comment xml:lang="si">SV4 CPIO සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív SV4 CPIO</comment>
+ <comment xml:lang="ru">Архив SV4 CPIO</comment>
+ <comment xml:lang="ro">Arhivă SV4 CPIO</comment>
+ <comment xml:lang="pt_BR">Pacote SV4 CPIO</comment>
+ <comment xml:lang="pt">arquivo SV4 CPIO</comment>
+ <comment xml:lang="pl">Archiwum SV4 CPIO</comment>
+ <comment xml:lang="oc">archiu SV4 CPIO</comment>
+ <comment xml:lang="nn">SV4 CPIO-arkiv</comment>
+ <comment xml:lang="nl">SV4 CPIO-archief</comment>
+ <comment xml:lang="nb">SV4 CPIO-arkiv</comment>
+ <comment xml:lang="ms">Arkib CPIO SV4</comment>
+ <comment xml:lang="lv">SV4 CPIO arhīvs</comment>
+ <comment xml:lang="lt">SV4 CPIO archyvas</comment>
+ <comment xml:lang="ko">SV4 CPIO 묶음 파일</comment>
+ <comment xml:lang="kk">SV4 CPIO архиві</comment>
+ <comment xml:lang="ja">SV4 CPIO アーカイブ</comment>
+ <comment xml:lang="it">Archivio SV4 CPIO</comment>
+ <comment xml:lang="is">SV4 CPIO safnskrá</comment>
+ <comment xml:lang="id">Arsip SV4 CPIO</comment>
+ <comment xml:lang="ia">Archivo CPIO SV4</comment>
+ <comment xml:lang="hu">SV4 CPIO-archívum</comment>
+ <comment xml:lang="hr">SV4 CPIO arhiva</comment>
+ <comment xml:lang="he">ארכיון של SV4 SPIO</comment>
+ <comment xml:lang="gl">arquivo SV4 CPIO</comment>
+ <comment xml:lang="ga">cartlann SV4 CPIO</comment>
+ <comment xml:lang="fur">archivi SV4 CPIO</comment>
+ <comment xml:lang="fr">archive SV4 CPIO</comment>
+ <comment xml:lang="fo">SV4 CPIO skjalasavn</comment>
+ <comment xml:lang="fi">SV4 CPIO -arkisto</comment>
+ <comment xml:lang="eu">SV4 CPIO artxiboa</comment>
+ <comment xml:lang="es">archivador SV4 CPIO</comment>
+ <comment xml:lang="eo">SV4-CPIO-arkivo</comment>
+ <comment xml:lang="en_GB">SV4 CPIO archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο SV4 CPIO</comment>
+ <comment xml:lang="de">SV4-CPIO-Archiv</comment>
+ <comment xml:lang="da">SV4 CPIO-arkiv</comment>
+ <comment xml:lang="cy">Archif CPIO SV4</comment>
+ <comment xml:lang="cs">archiv SV4 CPIO</comment>
+ <comment xml:lang="ca">arxiu SV4 CPIO</comment>
+ <comment xml:lang="bg">Архив — SV4 CPIO</comment>
+ <comment xml:lang="be@latin">Archiŭ SV4 CPIO</comment>
+ <comment xml:lang="be">архіў SV4 CPIO</comment>
+ <comment xml:lang="az">SV4 CPIO arxivi</comment>
+ <comment xml:lang="ar">أرشيف SV4 CPIO</comment>
+ <comment xml:lang="af">SV4 CPIO-argief</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.sv4cpio"/>
</mime-type>
<mime-type type="application/x-sv4crc">
<comment>SV4 CPIO archive (with CRC)</comment>
- <comment xml:lang="ar">أرشيف SV4 CPIO (مع CRC)</comment>
- <comment xml:lang="be@latin">Archiŭ SV4 CPIO (z CRC)</comment>
- <comment xml:lang="bg">Архив — SV4 CPIO, проверка за грешки CRC</comment>
- <comment xml:lang="ca">arxiu CPIO SV4 (amb CRC)</comment>
- <comment xml:lang="cs">archiv SV4 CPIO (s CRC)</comment>
- <comment xml:lang="da">SV4 CPIO-arkiv (med CRC)</comment>
- <comment xml:lang="de">SV4-CPIO-Archiv (mit CRC)</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο SV4 CPIO (με CRC)</comment>
- <comment xml:lang="en_GB">SV4 CPIO archive (with CRC)</comment>
- <comment xml:lang="eo">SV4-CPIO-arkivo (kun CRC)</comment>
- <comment xml:lang="es">archivador SV4 CPIO (con CRC)</comment>
- <comment xml:lang="eu">SV4 CPIO artxiboa (CRC-rekin)</comment>
- <comment xml:lang="fi">SV4 CPIO -arkisto (CRC:llä)</comment>
- <comment xml:lang="fo">SV4 CPIO skjalasavn (við CRC)</comment>
- <comment xml:lang="fr">archive SV4 CPIO (avec CRC)</comment>
- <comment xml:lang="ga">cartlann SV4 CPIO (le CRC)</comment>
- <comment xml:lang="gl">Arquivador SV4 CPIO (con CRC)</comment>
- <comment xml:lang="he">ארכיון של SV4 SPIO (עם CRC)</comment>
- <comment xml:lang="hr">SV4 CPIO arhiva (s CRC-om)</comment>
- <comment xml:lang="hu">SV4 CPIO-archívum (CRC-vel)</comment>
- <comment xml:lang="ia">Archivo CPIO SV4 (con CRC)</comment>
- <comment xml:lang="id">Arsip SV4 CPIO (dengan CRC)</comment>
- <comment xml:lang="it">Archivio SV4 CPIO (con CRC)</comment>
- <comment xml:lang="ja">SV4 CPIO アーカイブ (CRC 有り)</comment>
- <comment xml:lang="kk">SV4 CPIO архиві (CRC бар)</comment>
- <comment xml:lang="ko">SV4 CPIO 묶음 파일(CRC 포함)</comment>
- <comment xml:lang="lt">SV4 CPII archyvas (su CRC)</comment>
- <comment xml:lang="lv">SV4 CPIO arhīvs (ar CRC)</comment>
- <comment xml:lang="ms">Arkib CPIO SV4 (dengan CRC)</comment>
- <comment xml:lang="nb">SV4 CPIO-arkiv (med CRC)</comment>
- <comment xml:lang="nl">SV4 CPIO-archief (met CRC)</comment>
- <comment xml:lang="nn">SV4 CPIO arkiv (med CRC)</comment>
- <comment xml:lang="oc">archiu SV4 CPIO (avec CRC)</comment>
- <comment xml:lang="pl">Archiwum SV4 CPIO (z sumą kontrolną)</comment>
- <comment xml:lang="pt">arquivo SV4 CPIO (com CRC)</comment>
- <comment xml:lang="pt_BR">Pacote SV4 CPIO (com CRC)</comment>
- <comment xml:lang="ro">Arhivă SV4 CPIO (cu CRC)</comment>
- <comment xml:lang="ru">Архив SV4 CPIO (с CRC)</comment>
- <comment xml:lang="sk">Archív SV4 CPIO (s CRC)</comment>
- <comment xml:lang="sl">Datoteka arhiva SV4 CPIO (z razpršilom CRC)</comment>
- <comment xml:lang="sq">Arkiv SV4 CPIO (me CRC)</comment>
- <comment xml:lang="sr">СВ4 ЦПИО архива (са ЦРЦ-ом)</comment>
- <comment xml:lang="sv">SV4 CPIO-arkiv (med CRC)</comment>
- <comment xml:lang="tr">SV4 CPIO arşivi (CRC ile)</comment>
- <comment xml:lang="uk">архів SV4 CPIO (з CRC)</comment>
- <comment xml:lang="vi">Kho nén CPIO SV4 (với CRC)</comment>
- <comment xml:lang="zh_CN">SV4 CPIP 归档文件(带 CRC)</comment>
<comment xml:lang="zh_TW">SV4 CPIO 封存檔 (具有 CRC)</comment>
+ <comment xml:lang="zh_CN">SV4 CPIP 归档文件(带 CRC)</comment>
+ <comment xml:lang="vi">Kho nén CPIO SV4 (với CRC)</comment>
+ <comment xml:lang="uk">архів SV4 CPIO (з CRC)</comment>
+ <comment xml:lang="tr">SV4 CPIO arşivi (CRC ile)</comment>
+ <comment xml:lang="sv">SV4 CPIO-arkiv (med CRC)</comment>
+ <comment xml:lang="sr">СВ4 ЦПИО архива (са ЦРЦ-ом)</comment>
+ <comment xml:lang="sq">arkiv SV4 CPIO (me CRC)</comment>
+ <comment xml:lang="sl">Datoteka arhiva SV4 CPIO (z razpršilom CRC)</comment>
+ <comment xml:lang="si">SV4 CPIO සංරක්ෂිතය (CRC සමඟ)</comment>
+ <comment xml:lang="sk">Archív SV4 CPIO (s CRC)</comment>
+ <comment xml:lang="ru">Архив SV4 CPIO (с CRC)</comment>
+ <comment xml:lang="ro">Arhivă SV4 CPIO (cu CRC)</comment>
+ <comment xml:lang="pt_BR">Pacote SV4 CPIO (com CRC)</comment>
+ <comment xml:lang="pt">arquivo SV4 CPIO (com CRC)</comment>
+ <comment xml:lang="pl">Archiwum SV4 CPIO (z sumą kontrolną)</comment>
+ <comment xml:lang="oc">archiu SV4 CPIO (avec CRC)</comment>
+ <comment xml:lang="nn">SV4 CPIO arkiv (med CRC)</comment>
+ <comment xml:lang="nl">SV4 CPIO-archief (met CRC)</comment>
+ <comment xml:lang="nb">SV4 CPIO-arkiv (med CRC)</comment>
+ <comment xml:lang="ms">Arkib CPIO SV4 (dengan CRC)</comment>
+ <comment xml:lang="lv">SV4 CPIO arhīvs (ar CRC)</comment>
+ <comment xml:lang="lt">SV4 CPII archyvas (su CRC)</comment>
+ <comment xml:lang="ko">SV4 CPIO 묶음 파일(CRC 포함)</comment>
+ <comment xml:lang="kk">SV4 CPIO архиві (CRC бар)</comment>
+ <comment xml:lang="ja">SV4 CPIO アーカイブ (CRC 有り)</comment>
+ <comment xml:lang="it">Archivio SV4 CPIO (con CRC)</comment>
+ <comment xml:lang="is">SV4 CPIO safnskrá (með CRC)</comment>
+ <comment xml:lang="id">Arsip SV4 CPIO (dengan CRC)</comment>
+ <comment xml:lang="ia">Archivo CPIO SV4 (con CRC)</comment>
+ <comment xml:lang="hu">SV4 CPIO-archívum (CRC-vel)</comment>
+ <comment xml:lang="hr">SV4 CPIO arhiva (s CRC-om)</comment>
+ <comment xml:lang="he">ארכיון של SV4 SPIO (עם CRC)</comment>
+ <comment xml:lang="gl">Arquivador SV4 CPIO (con CRC)</comment>
+ <comment xml:lang="ga">cartlann SV4 CPIO (le CRC)</comment>
+ <comment xml:lang="fur">archivi SV4 CPIO (cun CRC)</comment>
+ <comment xml:lang="fr">archive SV4 CPIO (avec CRC)</comment>
+ <comment xml:lang="fo">SV4 CPIO skjalasavn (við CRC)</comment>
+ <comment xml:lang="fi">SV4 CPIO -arkisto (CRC:llä)</comment>
+ <comment xml:lang="eu">SV4 CPIO artxiboa (CRC-rekin)</comment>
+ <comment xml:lang="es">archivador SV4 CPIO (con CRC)</comment>
+ <comment xml:lang="eo">SV4-CPIO-arkivo (kun CRC)</comment>
+ <comment xml:lang="en_GB">SV4 CPIO archive (with CRC)</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο SV4 CPIO (με CRC)</comment>
+ <comment xml:lang="de">SV4-CPIO-Archiv (mit CRC)</comment>
+ <comment xml:lang="da">SV4 CPIO-arkiv (med CRC)</comment>
+ <comment xml:lang="cs">archiv SV4 CPIO (s CRC)</comment>
+ <comment xml:lang="ca">arxiu SV4 CPIO (amb CRC)</comment>
+ <comment xml:lang="bg">Архив — SV4 CPIO, проверка за грешки CRC</comment>
+ <comment xml:lang="be@latin">Archiŭ SV4 CPIO (z CRC)</comment>
+ <comment xml:lang="be">архіў SV4 CPIO (z CRC)</comment>
+ <comment xml:lang="ar">أرشيف SV4 CPIO (مع CRC)</comment>
+ <comment xml:lang="af">SV4 CPIO-argief (met CRC)</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.sv4crc"/>
</mime-type>
<mime-type type="application/x-tar">
<comment>Tar archive</comment>
- <comment xml:lang="ar">أرشيف Tar</comment>
- <comment xml:lang="az">Tar arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ tar</comment>
- <comment xml:lang="bg">Архив — tar</comment>
- <comment xml:lang="ca">arxiu tar</comment>
- <comment xml:lang="cs">archiv Tar</comment>
- <comment xml:lang="cy">Archif tar</comment>
- <comment xml:lang="da">Tar-arkiv</comment>
- <comment xml:lang="de">Tar-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Tar</comment>
- <comment xml:lang="en_GB">Tar archive</comment>
- <comment xml:lang="es">archivador Tar</comment>
- <comment xml:lang="eu">Tar artxiboa</comment>
- <comment xml:lang="fi">Tar-arkisto</comment>
- <comment xml:lang="fo">Tar skjalasavn</comment>
- <comment xml:lang="fr">archive tar</comment>
- <comment xml:lang="ga">cartlann Tar</comment>
- <comment xml:lang="gl">arquivo Tar</comment>
- <comment xml:lang="he">ארכיון Tar</comment>
- <comment xml:lang="hr">Tar arhiva</comment>
- <comment xml:lang="hu">Tar archívum</comment>
- <comment xml:lang="ia">Archivo Tar</comment>
- <comment xml:lang="id">Arsip Tar</comment>
- <comment xml:lang="it">Archivio tar</comment>
- <comment xml:lang="ja">Tar アーカイブ</comment>
- <comment xml:lang="kk">Tar архиві</comment>
- <comment xml:lang="ko">TAR 묶음 파일</comment>
- <comment xml:lang="lt">Tar archyvas</comment>
- <comment xml:lang="lv">Tar arhīvs</comment>
- <comment xml:lang="ms">Arkib Tar</comment>
- <comment xml:lang="nb">Tar-arkiv</comment>
- <comment xml:lang="nl">Tar-archief</comment>
- <comment xml:lang="nn">Tar-arkiv</comment>
- <comment xml:lang="oc">archiu tar</comment>
- <comment xml:lang="pl">Archiwum tar</comment>
- <comment xml:lang="pt">arquivo Tar</comment>
- <comment xml:lang="pt_BR">Pacote Tar</comment>
- <comment xml:lang="ro">Arhivă Tar</comment>
- <comment xml:lang="ru">Архив TAR</comment>
- <comment xml:lang="sk">Archív tar</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar</comment>
- <comment xml:lang="sq">Arkiv tar</comment>
- <comment xml:lang="sr">Тар архива</comment>
- <comment xml:lang="sv">Tar-arkiv</comment>
- <comment xml:lang="tr">Tar arşivi</comment>
- <comment xml:lang="uk">архів tar</comment>
- <comment xml:lang="vi">Kho nén tar</comment>
- <comment xml:lang="zh_CN">Tar 归档文件</comment>
<comment xml:lang="zh_TW">Tar 封存檔</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件</comment>
+ <comment xml:lang="vi">Kho nén tar</comment>
+ <comment xml:lang="uk">архів tar</comment>
+ <comment xml:lang="tr">Tar arşivi</comment>
+ <comment xml:lang="sv">Tar-arkiv</comment>
+ <comment xml:lang="sr">Тар архива</comment>
+ <comment xml:lang="sq">arkiv tar</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar</comment>
+ <comment xml:lang="si">තාර ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Tar</comment>
+ <comment xml:lang="ru">Архив TAR</comment>
+ <comment xml:lang="ro">Arhivă Tar</comment>
+ <comment xml:lang="pt_BR">Pacote Tar</comment>
+ <comment xml:lang="pt">arquivo Tar</comment>
+ <comment xml:lang="pl">Archiwum tar</comment>
+ <comment xml:lang="oc">archiu tar</comment>
+ <comment xml:lang="nn">Tar-arkiv</comment>
+ <comment xml:lang="nl">Tar-archief</comment>
+ <comment xml:lang="nb">Tar-arkiv</comment>
+ <comment xml:lang="ms">Arkib Tar</comment>
+ <comment xml:lang="lv">Tar arhīvs</comment>
+ <comment xml:lang="lt">Tar archyvas</comment>
+ <comment xml:lang="ko">TAR 묶음 파일</comment>
+ <comment xml:lang="kk">Tar архиві</comment>
+ <comment xml:lang="ja">Tar アーカイブ</comment>
+ <comment xml:lang="it">Archivio tar</comment>
+ <comment xml:lang="is">Tar safnskrá</comment>
+ <comment xml:lang="id">Arsip Tar</comment>
+ <comment xml:lang="ia">Archivo Tar</comment>
+ <comment xml:lang="hu">Tar archívum</comment>
+ <comment xml:lang="hr">Tar arhiva</comment>
+ <comment xml:lang="he">ארכיון Tar</comment>
+ <comment xml:lang="gl">arquivo Tar</comment>
+ <comment xml:lang="ga">cartlann Tar</comment>
+ <comment xml:lang="fur">archivi Tar</comment>
+ <comment xml:lang="fr">archive tar</comment>
+ <comment xml:lang="fo">Tar skjalasavn</comment>
+ <comment xml:lang="fi">Tar-arkisto</comment>
+ <comment xml:lang="eu">Tar artxiboa</comment>
+ <comment xml:lang="es">archivador Tar</comment>
+ <comment xml:lang="en_GB">Tar archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Tar</comment>
+ <comment xml:lang="de">Tar-Archiv</comment>
+ <comment xml:lang="da">Tar-arkiv</comment>
+ <comment xml:lang="cy">Archif tar</comment>
+ <comment xml:lang="cs">archiv Tar</comment>
+ <comment xml:lang="ca">arxiu tar</comment>
+ <comment xml:lang="bg">Архив — tar</comment>
+ <comment xml:lang="be@latin">Archiŭ tar</comment>
+ <comment xml:lang="be">архіў tar</comment>
+ <comment xml:lang="az">Tar arxivi</comment>
+ <comment xml:lang="ar">أرشيف Tar</comment>
+ <comment xml:lang="af">Tar-argief</comment>
<generic-icon name="package-x-generic"/>
<alias type="application/x-gtar"/>
<magic priority="60">
- <match value="ustar\0" type="string" offset="257"/>
- <match value="ustar\040\040\0" type="string" offset="257"/>
+ <match type="string" value="ustar\0" offset="257"/>
+ <match type="string" value="ustar\040\040\0" offset="257"/>
</magic>
<glob pattern="*.tar"/>
<glob pattern="*.gtar"/>
@@ -20828,382 +22664,243 @@
</mime-type>
<mime-type type="application/x-tarz">
<comment>Tar archive (compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط)</comment>
- <comment xml:lang="be@latin">Archiŭ tar (skampresavany)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió)</comment>
- <comment xml:lang="cs">archiv Tar (komprimovaný)</comment>
- <comment xml:lang="da">Tar-arkiv (komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο)</comment>
- <comment xml:lang="en_GB">Tar archive (compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido)</comment>
- <comment xml:lang="eu">Tar artxiboa (konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn (stappað)</comment>
- <comment xml:lang="fr">archive tar (compressée)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ)</comment>
- <comment xml:lang="hr">Tar arhiva (sažeta)</comment>
- <comment xml:lang="hu">Tar archívum (tömörített)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi)</comment>
- <comment xml:lang="it">Archivio tar (compresso)</comment>
- <comment xml:lang="ja">Tar アーカイブ (compress 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(압축) </comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests)</comment>
- <comment xml:lang="nb">Tar-arkiv (komprimert)</comment>
- <comment xml:lang="nl">Tar-archief (ingepakt)</comment>
- <comment xml:lang="nn">Tar-arkiv (pakka)</comment>
- <comment xml:lang="oc">archiu tar (compressat)</comment>
- <comment xml:lang="pl">Archiwum tar (skompresowane)</comment>
- <comment xml:lang="pt">arquivo Tar (comprimido)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen)</comment>
- <comment xml:lang="sq">Arkiv tar (i kompresuar)</comment>
- <comment xml:lang="sr">Тар архива (запакована)</comment>
- <comment xml:lang="sv">Tar-arkiv (komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений)</comment>
- <comment xml:lang="vi">Kho nén tar (đã nén)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (UNIX 格式壓縮)</comment>
+ <comment xml:lang="vi">Kho nén tar (đã nén)</comment>
+ <comment xml:lang="uk">архів tar (стиснений)</comment>
+ <comment xml:lang="tr">Tar arşivi (sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована)</comment>
+ <comment xml:lang="sq">arkiv tar (i kompresuar)</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый)</comment>
+ <comment xml:lang="ro">Arhivă Tar (comprimată)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado)</comment>
+ <comment xml:lang="pt">arquivo Tar (comprimido)</comment>
+ <comment xml:lang="pl">Archiwum tar (skompresowane)</comment>
+ <comment xml:lang="oc">archiu tar (compressat)</comment>
+ <comment xml:lang="nn">Tar-arkiv (pakka)</comment>
+ <comment xml:lang="nl">Tar-archief (ingepakt)</comment>
+ <comment xml:lang="nb">Tar-arkiv (komprimert)</comment>
+ <comment xml:lang="lv">Tar arhīvs (saspiests)</comment>
+ <comment xml:lang="lt">Tar archyvas (suglaudintas)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(압축) </comment>
+ <comment xml:lang="kk">Tar архиві (сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso)</comment>
+ <comment xml:lang="is">Tar safnskrá (þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi)</comment>
+ <comment xml:lang="ia">Archivo Tar (comprimite)</comment>
+ <comment xml:lang="hu">Tar archívum (tömörített)</comment>
+ <comment xml:lang="hr">Tar arhiva (sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ)</comment>
+ <comment xml:lang="gl">arquivo Tar (comprimido)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût)</comment>
+ <comment xml:lang="fr">archive tar (compressée)</comment>
+ <comment xml:lang="fo">Tar skjalasavn (stappað)</comment>
+ <comment xml:lang="fi">Tar-arkisto (pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (konprimitua)</comment>
+ <comment xml:lang="es">archivador Tar (comprimido)</comment>
+ <comment xml:lang="en_GB">Tar archive (compressed)</comment>
+ <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο)</comment>
+ <comment xml:lang="de">Tar-Archiv (komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimovaný)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран</comment>
+ <comment xml:lang="be@latin">Archiŭ tar (skampresavany)</comment>
+ <comment xml:lang="be">архіў tar (сціснуты)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط)</comment>
+ <comment xml:lang="af">Tar-argief (saamgepers)</comment>
<sub-class-of type="application/x-compress"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.tar.Z"/>
<glob pattern="*.taz"/>
</mime-type>
<mime-type type="application/x-tex-gf">
- <comment>generic font file</comment>
- <comment xml:lang="ar">ملف الخط العام</comment>
- <comment xml:lang="be@latin">zvyčajny fajł šryftu</comment>
- <comment xml:lang="bg">Шрифт</comment>
- <comment xml:lang="ca">fitxer de lletra genèrica</comment>
- <comment xml:lang="cs">obecný soubor s fontem</comment>
- <comment xml:lang="da">general skrifttypefil</comment>
- <comment xml:lang="de">Allgemeine Schriftdatei</comment>
- <comment xml:lang="el">Γενικό αρχείο γραμματοσειράς</comment>
- <comment xml:lang="en_GB">generic font file</comment>
- <comment xml:lang="eo">genera tipara dosiero</comment>
- <comment xml:lang="es">tipo de letra genérico</comment>
- <comment xml:lang="eu">letra-tipo orokorra</comment>
- <comment xml:lang="fi">yleinen fonttitiedosto</comment>
- <comment xml:lang="fo">felagsstavasniðsfíla</comment>
- <comment xml:lang="fr">fichier de polices générique</comment>
- <comment xml:lang="ga">comhad cló ginearálta</comment>
- <comment xml:lang="gl">ficheiro de tipo de fonte xenérica</comment>
- <comment xml:lang="he">קובץ גופן גנרי</comment>
- <comment xml:lang="hr">Izvorna datoteka slova</comment>
- <comment xml:lang="hu">általános betűkészletfájl</comment>
- <comment xml:lang="ia">File de typo de litteras generic</comment>
- <comment xml:lang="id">berkas fonta generik</comment>
- <comment xml:lang="it">File tipo carattere generico</comment>
- <comment xml:lang="ja">一般フォントファイル</comment>
- <comment xml:lang="kk">қаріп файлы</comment>
- <comment xml:lang="ko">일반 글꼴 파일</comment>
- <comment xml:lang="lt">bendras šrifto failas</comment>
- <comment xml:lang="lv">vispārēja fonta datne</comment>
- <comment xml:lang="ms">Fail font generik</comment>
- <comment xml:lang="nb">vanlig skriftfil</comment>
- <comment xml:lang="nl">algemeen lettertypebestand</comment>
- <comment xml:lang="nn">vanleg skrifttypefil</comment>
- <comment xml:lang="oc">fichièr de poliças generic</comment>
- <comment xml:lang="pl">Zwykły plik czcionki</comment>
- <comment xml:lang="pt">ficheiro genérico de letra</comment>
- <comment xml:lang="pt_BR">Arquivo de fonte genérico</comment>
- <comment xml:lang="ro">fișier de font generic</comment>
+ <comment>Generic font file</comment>
+ <comment xml:lang="uk">типовий файл шрифту</comment>
+ <comment xml:lang="sv">Allmän typsnittsfil</comment>
<comment xml:lang="ru">Обычный файл шрифта</comment>
- <comment xml:lang="sk">Obyčajný súbor písma</comment>
- <comment xml:lang="sl">izvorna datoteka pisave</comment>
- <comment xml:lang="sq">File lloj gërme i përgjithshëm</comment>
- <comment xml:lang="sr">општа датотека слова</comment>
- <comment xml:lang="sv">allmän typsnittsfil</comment>
- <comment xml:lang="tr">genel yazı tipi dosyası</comment>
- <comment xml:lang="uk">загальний файл шрифту</comment>
- <comment xml:lang="vi">tập tin phông giống loài</comment>
- <comment xml:lang="zh_CN">通用字体文件</comment>
- <comment xml:lang="zh_TW">通用字型檔</comment>
+ <comment xml:lang="pl">Zwykły plik czcionki</comment>
+ <comment xml:lang="ja">汎用フォント</comment>
+ <comment xml:lang="it">File tipo di carattere generico</comment>
+ <comment xml:lang="eu">Letra-tipoen fitxategi orokorra</comment>
+ <comment xml:lang="es">archivo de tipo de letra genérico</comment>
+ <comment xml:lang="de">Allgemeine Schriftdatei</comment>
+ <comment xml:lang="be">файл тыповага шрыфту</comment>
<generic-icon name="font-x-generic"/>
<glob pattern="*.gf"/>
</mime-type>
<mime-type type="application/x-tex-pk">
- <comment>packed font file</comment>
- <comment xml:lang="ar">ملف الخط المرزم</comment>
- <comment xml:lang="be@latin">zapakavany fajł šryftu</comment>
- <comment xml:lang="bg">Шрифт — компресиран</comment>
- <comment xml:lang="ca">fitxer de lletra empaquetada</comment>
- <comment xml:lang="cs">komprimovaný soubor s fontem</comment>
- <comment xml:lang="da">pakket skrifttypefil</comment>
- <comment xml:lang="de">Gepackte Schriftdatei</comment>
- <comment xml:lang="el">Αρχείο συμπιεσμένης γραμματοσειράς</comment>
- <comment xml:lang="en_GB">packed font file</comment>
- <comment xml:lang="eo">pakigita tipara dosiero</comment>
- <comment xml:lang="es">tipo de letra empaquetado</comment>
- <comment xml:lang="eu">Letra-tipo fitxategi paketatua</comment>
- <comment xml:lang="fi">pakattu fonttitiedosto</comment>
- <comment xml:lang="fo">pakkað stavasniðsfíla</comment>
- <comment xml:lang="fr">fichier de polices empaquetées</comment>
- <comment xml:lang="ga">comhad cló pacáilte</comment>
- <comment xml:lang="gl">ficheiro de fonte empaquetada</comment>
- <comment xml:lang="he">קובץ גופן ארוז</comment>
- <comment xml:lang="hr">Zapakirana datoteka slova</comment>
- <comment xml:lang="hu">packed font-fájl</comment>
- <comment xml:lang="ia">File de typos de litteras impacchettate</comment>
- <comment xml:lang="id">berkas fonta terkemas</comment>
- <comment xml:lang="it">File tipo carattere condensato</comment>
- <comment xml:lang="ja">パックされたフォントファイル</comment>
- <comment xml:lang="kk">қаріп файлы (дестеленген)</comment>
- <comment xml:lang="ko">글꼴 묶음 파일</comment>
- <comment xml:lang="lt">supakuotas šrifto failas</comment>
- <comment xml:lang="lv">sapakota fonta datne</comment>
- <comment xml:lang="ms">Fail font dipek</comment>
- <comment xml:lang="nb">pakket skriftfil</comment>
- <comment xml:lang="nl">ingepakt lettertypebestand</comment>
- <comment xml:lang="nn">pakka skrifttypefil</comment>
- <comment xml:lang="oc">fichièr de poliças empaquetadas</comment>
- <comment xml:lang="pl">Plik ze spakowaną czcionką</comment>
- <comment xml:lang="pt">ficheiro de letras empacotadas</comment>
- <comment xml:lang="pt_BR">Arquivo de fonte empacotado</comment>
- <comment xml:lang="ro">fișier font împachetat</comment>
- <comment xml:lang="ru">Сжатый файл шрифта</comment>
- <comment xml:lang="sk">Komprimovaný súbor písma</comment>
- <comment xml:lang="sl">pakirana datoteka pisave</comment>
- <comment xml:lang="sq">File lloj gërmash i kondensuar</comment>
- <comment xml:lang="sr">пакована датотека слова</comment>
- <comment xml:lang="sv">packad typsnittsfil</comment>
- <comment xml:lang="tr">paketlenmiş yazı tipi dosyası</comment>
+ <comment>Packed font file</comment>
<comment xml:lang="uk">запакований файл шрифту</comment>
- <comment xml:lang="vi">tập tin phông chữ đã đóng gói</comment>
- <comment xml:lang="zh_CN">打包的字体文件</comment>
- <comment xml:lang="zh_TW">包裝字型檔</comment>
+ <comment xml:lang="sv">Packad typsnittsfil</comment>
+ <comment xml:lang="ru">Сжатый файл шрифта</comment>
+ <comment xml:lang="pl">Plik ze spakowaną czcionką</comment>
+ <comment xml:lang="it">File tipo di carattere condensato</comment>
+ <comment xml:lang="eu">Letra-tipoen fitxategi paketatua</comment>
+ <comment xml:lang="es">archivo de tipo de letra empaquetado</comment>
+ <comment xml:lang="de">Gepackte Schriftdatei</comment>
+ <comment xml:lang="be">запакаваны файл шрыфту</comment>
<generic-icon name="font-x-generic"/>
<glob pattern="*.pk"/>
</mime-type>
<mime-type type="application/x-tgif">
<comment>TGIF document</comment>
- <comment xml:lang="ar">مستند TGIF</comment>
- <comment xml:lang="ast">Documentu de TGIF</comment>
- <comment xml:lang="be@latin">Dakument TGIF</comment>
- <comment xml:lang="bg">Документ — TGIF</comment>
- <comment xml:lang="ca">document TGIF</comment>
- <comment xml:lang="cs">dokument TGIF</comment>
- <comment xml:lang="da">TGIF-dokument</comment>
- <comment xml:lang="de">TGIF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο TGIF</comment>
- <comment xml:lang="en_GB">TGIF document</comment>
- <comment xml:lang="eo">TGIF-dokumento</comment>
- <comment xml:lang="es">documento TGIF</comment>
- <comment xml:lang="eu">TGIF dokumentua</comment>
- <comment xml:lang="fi">TGIF-asiakirja</comment>
- <comment xml:lang="fo">TGIF skjal</comment>
- <comment xml:lang="fr">document TGIF</comment>
- <comment xml:lang="ga">cáipéis TGIF</comment>
- <comment xml:lang="gl">documento TGIF</comment>
- <comment xml:lang="he">מסמך TGIF</comment>
- <comment xml:lang="hr">TGIF dokument</comment>
- <comment xml:lang="hu">TGIF-dokumentum</comment>
- <comment xml:lang="ia">Documento TGIF</comment>
- <comment xml:lang="id">Dokumen TGIF</comment>
- <comment xml:lang="it">Documento TGIF</comment>
- <comment xml:lang="ja">TGIF ドキュメント</comment>
- <comment xml:lang="kk">TGIF құжаты</comment>
- <comment xml:lang="ko">TGIF 문서</comment>
- <comment xml:lang="lt">TGIF dokumentas</comment>
- <comment xml:lang="lv">TGIF dokuments</comment>
- <comment xml:lang="ms">Dokumen TGIF</comment>
- <comment xml:lang="nb">TGIF-dokument</comment>
- <comment xml:lang="nl">TGIF-document</comment>
- <comment xml:lang="nn">TGIF-dokument</comment>
- <comment xml:lang="oc">document TGIF</comment>
- <comment xml:lang="pl">Dokument TGIF</comment>
- <comment xml:lang="pt">documento TGIF</comment>
- <comment xml:lang="pt_BR">Documento TGIF</comment>
- <comment xml:lang="ro">Document TGIF</comment>
- <comment xml:lang="ru">Документ TGIF</comment>
- <comment xml:lang="sk">Dokument TGIF</comment>
- <comment xml:lang="sl">Dokument TGIF</comment>
- <comment xml:lang="sq">Dokument TGIF</comment>
- <comment xml:lang="sr">ТГИФ документ</comment>
- <comment xml:lang="sv">TGIF-dokument</comment>
- <comment xml:lang="tr">TGIF belgesi</comment>
- <comment xml:lang="uk">документ TGIF</comment>
- <comment xml:lang="vi">Tài liệu TGIF</comment>
- <comment xml:lang="zh_CN">TGIF 文档</comment>
<comment xml:lang="zh_TW">TGIF 文件</comment>
+ <comment xml:lang="zh_CN">TGIF 文档</comment>
+ <comment xml:lang="vi">Tài liệu TGIF</comment>
+ <comment xml:lang="uk">документ TGIF</comment>
+ <comment xml:lang="tr">TGIF belgesi</comment>
+ <comment xml:lang="sv">TGIF-dokument</comment>
+ <comment xml:lang="sr">ТГИФ документ</comment>
+ <comment xml:lang="sq">dokument TGIF</comment>
+ <comment xml:lang="sl">Dokument TGIF</comment>
+ <comment xml:lang="si">TGIF ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument TGIF</comment>
+ <comment xml:lang="ru">Документ TGIF</comment>
+ <comment xml:lang="ro">Document TGIF</comment>
+ <comment xml:lang="pt_BR">Documento TGIF</comment>
+ <comment xml:lang="pt">documento TGIF</comment>
+ <comment xml:lang="pl">Dokument TGIF</comment>
+ <comment xml:lang="oc">document TGIF</comment>
+ <comment xml:lang="nn">TGIF-dokument</comment>
+ <comment xml:lang="nl">TGIF-document</comment>
+ <comment xml:lang="nb">TGIF-dokument</comment>
+ <comment xml:lang="ms">Dokumen TGIF</comment>
+ <comment xml:lang="lv">TGIF dokuments</comment>
+ <comment xml:lang="lt">TGIF dokumentas</comment>
+ <comment xml:lang="ko">TGIF 문서</comment>
+ <comment xml:lang="kk">TGIF құжаты</comment>
+ <comment xml:lang="ja">TGIF ドキュメント</comment>
+ <comment xml:lang="it">Documento TGIF</comment>
+ <comment xml:lang="is">TGIF skjal</comment>
+ <comment xml:lang="id">Dokumen TGIF</comment>
+ <comment xml:lang="ia">Documento TGIF</comment>
+ <comment xml:lang="hu">TGIF-dokumentum</comment>
+ <comment xml:lang="hr">TGIF dokument</comment>
+ <comment xml:lang="he">מסמך TGIF</comment>
+ <comment xml:lang="gl">documento TGIF</comment>
+ <comment xml:lang="ga">cáipéis TGIF</comment>
+ <comment xml:lang="fur">document TGIF</comment>
+ <comment xml:lang="fr">document TGIF</comment>
+ <comment xml:lang="fo">TGIF skjal</comment>
+ <comment xml:lang="fi">TGIF-asiakirja</comment>
+ <comment xml:lang="eu">TGIF dokumentua</comment>
+ <comment xml:lang="es">documento TGIF</comment>
+ <comment xml:lang="eo">TGIF-dokumento</comment>
+ <comment xml:lang="en_GB">TGIF document</comment>
+ <comment xml:lang="el">Έγγραφο TGIF</comment>
+ <comment xml:lang="de">TGIF-Dokument</comment>
+ <comment xml:lang="da">TGIF-dokument</comment>
+ <comment xml:lang="cs">dokument TGIF</comment>
+ <comment xml:lang="ca">document TGIF</comment>
+ <comment xml:lang="bg">Документ — TGIF</comment>
+ <comment xml:lang="be@latin">Dakument TGIF</comment>
+ <comment xml:lang="be">дакумент TGIF</comment>
+ <comment xml:lang="ast">Documentu de TGIF</comment>
+ <comment xml:lang="ar">مستند TGIF</comment>
+ <comment xml:lang="af">TGIF-dokument</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="%TGIF" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="%TGIF" offset="0"/>
</magic>
<glob pattern="*.obj"/>
</mime-type>
<mime-type type="application/x-theme">
- <comment>theme</comment>
- <comment xml:lang="ar">سمة</comment>
- <comment xml:lang="az">örtük</comment>
- <comment xml:lang="be@latin">matyŭ</comment>
- <comment xml:lang="bg">Тема</comment>
- <comment xml:lang="ca">tema</comment>
- <comment xml:lang="cs">motiv</comment>
- <comment xml:lang="cy">thema</comment>
- <comment xml:lang="da">tema</comment>
- <comment xml:lang="de">Thema</comment>
- <comment xml:lang="el">Θέμα</comment>
- <comment xml:lang="en_GB">theme</comment>
- <comment xml:lang="eo">etoso</comment>
- <comment xml:lang="es">tema</comment>
- <comment xml:lang="eu">gaia</comment>
- <comment xml:lang="fi">teema</comment>
- <comment xml:lang="fo">tema</comment>
- <comment xml:lang="fr">thème</comment>
- <comment xml:lang="ga">téama</comment>
- <comment xml:lang="gl">tema</comment>
- <comment xml:lang="he">ערכת נושא</comment>
- <comment xml:lang="hr">Tema</comment>
- <comment xml:lang="hu">téma</comment>
- <comment xml:lang="ia">Thema</comment>
- <comment xml:lang="id">tema</comment>
- <comment xml:lang="it">Tema</comment>
- <comment xml:lang="ja">テーマ</comment>
- <comment xml:lang="ka">თემა</comment>
- <comment xml:lang="kk">тема</comment>
- <comment xml:lang="ko">테마</comment>
- <comment xml:lang="lt">tema</comment>
- <comment xml:lang="lv">motīvs</comment>
- <comment xml:lang="ms">Tema</comment>
- <comment xml:lang="nb">tema</comment>
- <comment xml:lang="nl">thema</comment>
- <comment xml:lang="nn">drakt</comment>
- <comment xml:lang="oc">tèma</comment>
- <comment xml:lang="pl">Motyw</comment>
- <comment xml:lang="pt">tema</comment>
- <comment xml:lang="pt_BR">Tema</comment>
- <comment xml:lang="ro">temă</comment>
- <comment xml:lang="ru">Тема</comment>
- <comment xml:lang="sk">Motív</comment>
- <comment xml:lang="sl">tema</comment>
- <comment xml:lang="sq">Temë</comment>
- <comment xml:lang="sr">тема</comment>
- <comment xml:lang="sv">tema</comment>
- <comment xml:lang="tr">tema</comment>
+ <comment>Theme</comment>
<comment xml:lang="uk">тема</comment>
- <comment xml:lang="vi">sắc thái</comment>
- <comment xml:lang="zh_CN">主题</comment>
- <comment xml:lang="zh_TW">佈景主題</comment>
+ <comment xml:lang="sv">Tema</comment>
+ <comment xml:lang="ru">Тема</comment>
+ <comment xml:lang="pl">Motyw</comment>
+ <comment xml:lang="it">Tema</comment>
+ <comment xml:lang="gl">Tema</comment>
+ <comment xml:lang="eu">Gaia</comment>
+ <comment xml:lang="es">tema</comment>
+ <comment xml:lang="de">Thema</comment>
+ <comment xml:lang="be">тэма</comment>
<sub-class-of type="application/x-desktop"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.theme"/>
</mime-type>
<mime-type type="application/x-toutdoux">
<comment>ToutDoux document</comment>
- <comment xml:lang="ar">مستند ToutDoux</comment>
- <comment xml:lang="ast">Documentu de ToutDoux</comment>
- <comment xml:lang="az">ToutDoux sənədi</comment>
- <comment xml:lang="be@latin">Dakument ToutDoux</comment>
- <comment xml:lang="bg">Документ — ToutDoux</comment>
- <comment xml:lang="ca">document ToutDoux</comment>
- <comment xml:lang="cs">dokument ToutDoux</comment>
- <comment xml:lang="cy">Dogfen ToutDoux</comment>
- <comment xml:lang="da">ToutDoux-dokument</comment>
- <comment xml:lang="de">ToutDoux-Dokument</comment>
- <comment xml:lang="el">Έγγραφο ToutDoux</comment>
- <comment xml:lang="en_GB">ToutDoux document</comment>
- <comment xml:lang="eo">ToutDoux-dokumento</comment>
- <comment xml:lang="es">documento de ToutDoux</comment>
- <comment xml:lang="eu">ToutDoux dokumentua</comment>
- <comment xml:lang="fi">ToutDoux-asiakirja</comment>
- <comment xml:lang="fo">ToutDoux skjal</comment>
- <comment xml:lang="fr">document ToutDoux</comment>
- <comment xml:lang="ga">cáipéis ToutDoux</comment>
- <comment xml:lang="gl">documento de ToutDoux</comment>
- <comment xml:lang="he">מסמך של ToutDoux</comment>
- <comment xml:lang="hr">ToutDoux dokument</comment>
- <comment xml:lang="hu">ToutDoux-dokumentum</comment>
- <comment xml:lang="ia">Documento ToutDoux</comment>
- <comment xml:lang="id">Dokumen ToutDoux</comment>
- <comment xml:lang="it">Documento ToutDoux</comment>
- <comment xml:lang="ja">ToutDoux ドキュメント</comment>
- <comment xml:lang="kk">ToutDoux құжаты</comment>
- <comment xml:lang="ko">ToutDoux 문서</comment>
- <comment xml:lang="lt">ToutDoux dokumentas</comment>
- <comment xml:lang="lv">ToutDoux dokuments</comment>
- <comment xml:lang="ms">Dokumen ToutDoux</comment>
- <comment xml:lang="nb">ToutDoux-dokument</comment>
- <comment xml:lang="nl">ToutDoux-document</comment>
- <comment xml:lang="nn">ToutDoux-dokument</comment>
- <comment xml:lang="oc">document ToutDoux</comment>
- <comment xml:lang="pl">Dokument ToutDoux</comment>
- <comment xml:lang="pt">documento ToutDoux</comment>
- <comment xml:lang="pt_BR">Documento do ToutDoux</comment>
- <comment xml:lang="ro">Document ToutDoux</comment>
- <comment xml:lang="ru">Документ ToutDoux</comment>
- <comment xml:lang="sk">Dokument ToutDoux</comment>
- <comment xml:lang="sl">Dokument ToutDoux</comment>
- <comment xml:lang="sq">Dokument ToutDoux</comment>
- <comment xml:lang="sr">Туду документ</comment>
- <comment xml:lang="sv">ToutDoux-dokument</comment>
- <comment xml:lang="tr">ToutDoux belgesi</comment>
- <comment xml:lang="uk">документ ToutDoux</comment>
- <comment xml:lang="vi">Tài liệu ToutDoux</comment>
- <comment xml:lang="zh_CN">ToutDoux 文档</comment>
<comment xml:lang="zh_TW">ToutDoux 文件</comment>
+ <comment xml:lang="zh_CN">ToutDoux 文档</comment>
+ <comment xml:lang="vi">Tài liệu ToutDoux</comment>
+ <comment xml:lang="uk">документ ToutDoux</comment>
+ <comment xml:lang="tr">ToutDoux belgesi</comment>
+ <comment xml:lang="sv">ToutDoux-dokument</comment>
+ <comment xml:lang="sr">Туду документ</comment>
+ <comment xml:lang="sq">dokument ToutDoux</comment>
+ <comment xml:lang="sl">Dokument ToutDoux</comment>
+ <comment xml:lang="si">ToutDoux ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument ToutDoux</comment>
+ <comment xml:lang="ru">Документ ToutDoux</comment>
+ <comment xml:lang="ro">Document ToutDoux</comment>
+ <comment xml:lang="pt_BR">Documento do ToutDoux</comment>
+ <comment xml:lang="pt">documento ToutDoux</comment>
+ <comment xml:lang="pl">Dokument ToutDoux</comment>
+ <comment xml:lang="oc">document ToutDoux</comment>
+ <comment xml:lang="nn">ToutDoux-dokument</comment>
+ <comment xml:lang="nl">ToutDoux-document</comment>
+ <comment xml:lang="nb">ToutDoux-dokument</comment>
+ <comment xml:lang="ms">Dokumen ToutDoux</comment>
+ <comment xml:lang="lv">ToutDoux dokuments</comment>
+ <comment xml:lang="lt">ToutDoux dokumentas</comment>
+ <comment xml:lang="ko">ToutDoux 문서</comment>
+ <comment xml:lang="kk">ToutDoux құжаты</comment>
+ <comment xml:lang="ja">ToutDoux ドキュメント</comment>
+ <comment xml:lang="it">Documento ToutDoux</comment>
+ <comment xml:lang="is">ToutDoux skjal</comment>
+ <comment xml:lang="id">Dokumen ToutDoux</comment>
+ <comment xml:lang="ia">Documento ToutDoux</comment>
+ <comment xml:lang="hu">ToutDoux-dokumentum</comment>
+ <comment xml:lang="hr">ToutDoux dokument</comment>
+ <comment xml:lang="he">מסמך של ToutDoux</comment>
+ <comment xml:lang="gl">documento de ToutDoux</comment>
+ <comment xml:lang="ga">cáipéis ToutDoux</comment>
+ <comment xml:lang="fur">document ToutDoux</comment>
+ <comment xml:lang="fr">document ToutDoux</comment>
+ <comment xml:lang="fo">ToutDoux skjal</comment>
+ <comment xml:lang="fi">ToutDoux-asiakirja</comment>
+ <comment xml:lang="eu">ToutDoux dokumentua</comment>
+ <comment xml:lang="es">documento de ToutDoux</comment>
+ <comment xml:lang="eo">ToutDoux-dokumento</comment>
+ <comment xml:lang="en_GB">ToutDoux document</comment>
+ <comment xml:lang="el">Έγγραφο ToutDoux</comment>
+ <comment xml:lang="de">ToutDoux-Dokument</comment>
+ <comment xml:lang="da">ToutDoux-dokument</comment>
+ <comment xml:lang="cy">Dogfen ToutDoux</comment>
+ <comment xml:lang="cs">dokument ToutDoux</comment>
+ <comment xml:lang="ca">document ToutDoux</comment>
+ <comment xml:lang="bg">Документ — ToutDoux</comment>
+ <comment xml:lang="be@latin">Dakument ToutDoux</comment>
+ <comment xml:lang="be">дакумент ToutDoux</comment>
+ <comment xml:lang="az">ToutDoux sənədi</comment>
+ <comment xml:lang="ast">Documentu de ToutDoux</comment>
+ <comment xml:lang="ar">مستند ToutDoux</comment>
+ <comment xml:lang="af">ToutDoux-dokument</comment>
<generic-icon name="x-office-document"/>
</mime-type>
<mime-type type="application/x-trash">
- <comment>backup file</comment>
- <comment xml:lang="ar">ملف النسخ الاحتياطي</comment>
- <comment xml:lang="be@latin">zapasny fajł</comment>
- <comment xml:lang="bg">Резервно копие</comment>
- <comment xml:lang="ca">fitxer de còpia de seguretat</comment>
- <comment xml:lang="cs">záložní soubor</comment>
- <comment xml:lang="da">sikkerhedskopi</comment>
- <comment xml:lang="de">Sicherungsdatei</comment>
- <comment xml:lang="el">Αντίγραφο ασφαλείας</comment>
- <comment xml:lang="en_GB">backup file</comment>
- <comment xml:lang="eo">restaŭrkopio</comment>
- <comment xml:lang="es">archivo de respaldo</comment>
- <comment xml:lang="eu">babes-kopiako fitxategia</comment>
- <comment xml:lang="fi">varmuuskopio</comment>
- <comment xml:lang="fo">trygdarritsfíla</comment>
- <comment xml:lang="fr">fichier de sauvegarde</comment>
- <comment xml:lang="ga">comhad cúltaca</comment>
- <comment xml:lang="gl">ficheiro de copia de seguridade</comment>
- <comment xml:lang="he">קובץ גיבוי</comment>
- <comment xml:lang="hr">Datoteka sigurnosne kopije</comment>
- <comment xml:lang="hu">biztonsági mentés</comment>
- <comment xml:lang="ia">Copia de reserva</comment>
- <comment xml:lang="id">berkas cadangan</comment>
- <comment xml:lang="it">File di backup</comment>
- <comment xml:lang="ja">バックアップファイル</comment>
- <comment xml:lang="kk">резервті көшірмесі</comment>
- <comment xml:lang="ko">백업 파일</comment>
- <comment xml:lang="lt">atsarginis failas</comment>
- <comment xml:lang="lv">dublējuma datne</comment>
- <comment xml:lang="ms">Fail backup</comment>
- <comment xml:lang="nb">sikkerhetskopi</comment>
- <comment xml:lang="nl">reservekopiebestand</comment>
- <comment xml:lang="nn">tryggleikskopi</comment>
- <comment xml:lang="oc">fichièr de salvament</comment>
- <comment xml:lang="pl">Plik zapasowy</comment>
- <comment xml:lang="pt">cópia de segurança</comment>
- <comment xml:lang="pt_BR">Arquivo de backup</comment>
- <comment xml:lang="ro">fișier de backup</comment>
+ <comment>Backup file</comment>
+ <comment xml:lang="uk">Файл резервної копії</comment>
+ <comment xml:lang="sv">Säkerhetskopia</comment>
<comment xml:lang="ru">Резервная копия</comment>
- <comment xml:lang="sk">Záložný súbor</comment>
- <comment xml:lang="sl">varnostna kopija datoteke</comment>
- <comment xml:lang="sq">File backup</comment>
- <comment xml:lang="sr">датотека резерве</comment>
- <comment xml:lang="sv">säkerhetskopia</comment>
- <comment xml:lang="tr">yedek dosyası</comment>
- <comment xml:lang="uk">резервна копія</comment>
- <comment xml:lang="vi">tập tin sao lưu</comment>
- <comment xml:lang="zh_CN">备份文件</comment>
- <comment xml:lang="zh_TW">備份檔</comment>
+ <comment xml:lang="pt_BR">Arquivo de backup</comment>
+ <comment xml:lang="pl">Plik zapasowy</comment>
+ <comment xml:lang="ja">控え</comment>
+ <comment xml:lang="it">File di backup</comment>
+ <comment xml:lang="gl">Ficheiro de respaldo</comment>
+ <comment xml:lang="eu">Babeskopia-fitxategia</comment>
+ <comment xml:lang="es">archivo de copia de respaldo</comment>
+ <comment xml:lang="de">Sicherungsdatei</comment>
+ <comment xml:lang="be">рэзервовая копія файла</comment>
<glob pattern="*~"/>
<glob pattern="*%"/>
<glob pattern="*.bak"/>
@@ -21212,208 +22909,183 @@
</mime-type>
<mime-type type="text/troff">
<comment>Troff document</comment>
- <comment xml:lang="ar">مستند Troff</comment>
- <comment xml:lang="ast">Documentu de Troff</comment>
- <comment xml:lang="az">Troff sənədi</comment>
- <comment xml:lang="be@latin">Dakument Troff</comment>
- <comment xml:lang="bg">Документ — Troff</comment>
- <comment xml:lang="ca">document Troff</comment>
- <comment xml:lang="cs">dokument Troff</comment>
- <comment xml:lang="cy">Dogfen troff</comment>
- <comment xml:lang="da">Troffdokument</comment>
- <comment xml:lang="de">Troff-Dokument</comment>
- <comment xml:lang="el">Έγγραφο troff</comment>
- <comment xml:lang="en_GB">Troff document</comment>
- <comment xml:lang="eo">Troff-dokumento</comment>
- <comment xml:lang="es">documento de Troff</comment>
- <comment xml:lang="eu">Troff dokumentua</comment>
- <comment xml:lang="fi">Troff-asiakirja</comment>
- <comment xml:lang="fo">Troff skjal</comment>
- <comment xml:lang="fr">document Troff</comment>
- <comment xml:lang="ga">cáipéis Troff</comment>
- <comment xml:lang="gl">documento Troff</comment>
- <comment xml:lang="he">מסמך Troff</comment>
- <comment xml:lang="hr">Troff dokument</comment>
- <comment xml:lang="hu">Troff-dokumentum</comment>
- <comment xml:lang="ia">Documento Troff</comment>
- <comment xml:lang="id">Dokumen Troff</comment>
- <comment xml:lang="it">Documento Troff</comment>
- <comment xml:lang="ja">Troff 入力ドキュメント</comment>
- <comment xml:lang="kk">Troff құжаты</comment>
- <comment xml:lang="ko">Troff 문서</comment>
- <comment xml:lang="lt">Troff dokumentas</comment>
- <comment xml:lang="lv">Troff dokuments</comment>
- <comment xml:lang="ms">Dokumen Troff</comment>
- <comment xml:lang="nb">Troff-dokument</comment>
- <comment xml:lang="nl">Troff-document</comment>
- <comment xml:lang="nn">Troff-dokument</comment>
- <comment xml:lang="oc">document Troff</comment>
- <comment xml:lang="pl">Dokument Troff</comment>
- <comment xml:lang="pt">documento Troff</comment>
- <comment xml:lang="pt_BR">Documento Troff</comment>
- <comment xml:lang="ro">Document Troff</comment>
- <comment xml:lang="ru">Документ Troff</comment>
- <comment xml:lang="sk">Dokument troff</comment>
- <comment xml:lang="sl">Dokument Troff</comment>
- <comment xml:lang="sq">Dokument Troff</comment>
- <comment xml:lang="sr">Трофф документ</comment>
- <comment xml:lang="sv">Troff-dokument</comment>
- <comment xml:lang="tr">Troff belgesi</comment>
- <comment xml:lang="uk">документ Troff</comment>
- <comment xml:lang="vi">Tài liệu Troff</comment>
- <comment xml:lang="zh_CN">Troff 文档</comment>
<comment xml:lang="zh_TW">Troff 文件</comment>
+ <comment xml:lang="zh_CN">Troff 文档</comment>
+ <comment xml:lang="vi">Tài liệu Troff</comment>
+ <comment xml:lang="uk">документ Troff</comment>
+ <comment xml:lang="tr">Troff belgesi</comment>
+ <comment xml:lang="sv">Troff-dokument</comment>
+ <comment xml:lang="sr">Трофф документ</comment>
+ <comment xml:lang="sq">dokument Troff</comment>
+ <comment xml:lang="sl">Dokument Troff</comment>
+ <comment xml:lang="si">ට්රොෆ් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument troff</comment>
+ <comment xml:lang="ru">Документ Troff</comment>
+ <comment xml:lang="ro">Document Troff</comment>
+ <comment xml:lang="pt_BR">Documento Troff</comment>
+ <comment xml:lang="pt">documento Troff</comment>
+ <comment xml:lang="pl">Dokument Troff</comment>
+ <comment xml:lang="oc">document Troff</comment>
+ <comment xml:lang="nn">Troff-dokument</comment>
+ <comment xml:lang="nl">Troff-document</comment>
+ <comment xml:lang="nb">Troff-dokument</comment>
+ <comment xml:lang="ms">Dokumen Troff</comment>
+ <comment xml:lang="lv">Troff dokuments</comment>
+ <comment xml:lang="lt">Troff dokumentas</comment>
+ <comment xml:lang="ko">Troff 문서</comment>
+ <comment xml:lang="kk">Troff құжаты</comment>
+ <comment xml:lang="ja">Troff 入力ドキュメント</comment>
+ <comment xml:lang="it">Documento Troff</comment>
+ <comment xml:lang="is">Troff skjal</comment>
+ <comment xml:lang="id">Dokumen Troff</comment>
+ <comment xml:lang="ia">Documento Troff</comment>
+ <comment xml:lang="hu">Troff-dokumentum</comment>
+ <comment xml:lang="hr">Troff dokument</comment>
+ <comment xml:lang="he">מסמך Troff</comment>
+ <comment xml:lang="gl">documento Troff</comment>
+ <comment xml:lang="ga">cáipéis Troff</comment>
+ <comment xml:lang="fur">document Troff</comment>
+ <comment xml:lang="fr">document Troff</comment>
+ <comment xml:lang="fo">Troff skjal</comment>
+ <comment xml:lang="fi">Troff-asiakirja</comment>
+ <comment xml:lang="eu">Troff dokumentua</comment>
+ <comment xml:lang="es">documento de Troff</comment>
+ <comment xml:lang="eo">Troff-dokumento</comment>
+ <comment xml:lang="en_GB">Troff document</comment>
+ <comment xml:lang="el">Έγγραφο troff</comment>
+ <comment xml:lang="de">Troff-Dokument</comment>
+ <comment xml:lang="da">Troffdokument</comment>
+ <comment xml:lang="cy">Dogfen troff</comment>
+ <comment xml:lang="cs">dokument Troff</comment>
+ <comment xml:lang="ca">document Troff</comment>
+ <comment xml:lang="bg">Документ — Troff</comment>
+ <comment xml:lang="be@latin">Dakument Troff</comment>
+ <comment xml:lang="be">дакумент Troff</comment>
+ <comment xml:lang="az">Troff sənədi</comment>
+ <comment xml:lang="ast">Documentu de Troff</comment>
+ <comment xml:lang="ar">مستند Troff</comment>
+ <comment xml:lang="af">Troff-dokument</comment>
<sub-class-of type="text/plain"/>
<alias type="application/x-troff"/>
<alias type="text/x-troff"/>
- <magic priority="50">
- <match value='.\\\"' type="string" offset="0"/>
- <match value="'\\\&quot;" type="string" offset="0"/>
- <match value="'.\\\&quot;" type="string" offset="0"/>
- <match value='\\\"' type="string" offset="0"/>
+ <magic>
+ <match type="string" value=".\\\&quot;" offset="0"/>
+ <match type="string" value="'\\\&quot;" offset="0"/>
+ <match type="string" value="'.\\\&quot;" offset="0"/>
+ <match type="string" value="\\\&quot;" offset="0"/>
</magic>
<glob pattern="*.tr"/>
<glob pattern="*.roff"/>
<glob weight="10" pattern="*.t"/>
</mime-type>
<mime-type type="application/x-troff-man">
- <comment>Manpage manual document</comment>
- <comment xml:lang="ca">document de pàgina man</comment>
- <comment xml:lang="cs">manuálová stránka</comment>
- <comment xml:lang="da">Manpage-manualdokument</comment>
- <comment xml:lang="de">Manpage-Handbuchdokument</comment>
- <comment xml:lang="el">Έγγραφο βοήθειας manpage</comment>
- <comment xml:lang="en_GB">Manpage manual document</comment>
- <comment xml:lang="es">documento de manual de Manpage</comment>
- <comment xml:lang="eu">Manpage eskuliburu dokumentua</comment>
- <comment xml:lang="fr">document manuel Manpage</comment>
- <comment xml:lang="ga">cáipéis lámhleabhair Man</comment>
- <comment xml:lang="he">מסמך תיעוד man</comment>
- <comment xml:lang="hr">Manpage dokument priručnika</comment>
- <comment xml:lang="hu">Manpage kézikönyv-dokumentum</comment>
- <comment xml:lang="ia">Pagina de manual "man"</comment>
- <comment xml:lang="id">Dokumen manual manpage</comment>
- <comment xml:lang="it">Documento di manuale manpage</comment>
- <comment xml:lang="kk">Manpage нұсқаулық құжаты</comment>
- <comment xml:lang="ko">맨 페이지 설명서 문서</comment>
- <comment xml:lang="oc">document de manual Manpage</comment>
- <comment xml:lang="pl">Dokument podręcznika stron pomocy</comment>
- <comment xml:lang="pt">documento de ajuda Manpage</comment>
- <comment xml:lang="pt_BR">Documento Manpage</comment>
- <comment xml:lang="ru">Документ справочной системы Manpage</comment>
- <comment xml:lang="sk">Dokument manuálu Manpage</comment>
- <comment xml:lang="sr">документ упутства странице упутства</comment>
- <comment xml:lang="sv">Manpage-manualdokument</comment>
- <comment xml:lang="tr">Man sayfası el kitabı belgesi</comment>
- <comment xml:lang="uk">документ підручника man</comment>
- <comment xml:lang="zh_CN">Manpage 手册文档</comment>
- <comment xml:lang="zh_TW">Manpage 手冊說明文件</comment>
+ <comment>Manual page</comment>
+ <comment xml:lang="zh_CN">手册页</comment>
+ <comment xml:lang="uk">сторінка підручника</comment>
+ <comment xml:lang="tr">Kılavuz sayfası</comment>
+ <comment xml:lang="sv">Manualsida</comment>
+ <comment xml:lang="si">අත්පොත පිටුව</comment>
+ <comment xml:lang="ru">Страница руководства</comment>
+ <comment xml:lang="pt_BR">Página de manual</comment>
+ <comment xml:lang="pl">Strona podręcznika</comment>
+ <comment xml:lang="nl">Handleidingpagina</comment>
+ <comment xml:lang="ko">man 페이지</comment>
+ <comment xml:lang="kk">Нұсқаулық парағы</comment>
+ <comment xml:lang="ja">マニュアルページ</comment>
+ <comment xml:lang="it">Pagina di manuale</comment>
+ <comment xml:lang="hr">Stranica priručnika</comment>
+ <comment xml:lang="gl">Páxina de manual</comment>
+ <comment xml:lang="fi">Manuaalisivu</comment>
+ <comment xml:lang="eu">Eskuliburu-orria</comment>
+ <comment xml:lang="es">página de manual</comment>
+ <comment xml:lang="en_GB">Manual page</comment>
+ <comment xml:lang="de">Handbuchseite</comment>
+ <comment xml:lang="be">старонка даведкі</comment>
+ <comment xml:lang="ar">صفحة دليل</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<glob pattern="*.man"/>
+ <glob pattern="*.[1-9]"/>
</mime-type>
<mime-type type="application/x-troff-man-compressed">
- <comment>manual page (compressed)</comment>
- <comment xml:lang="ar">صفحة المساعدة (مضغوطة)</comment>
- <comment xml:lang="az">man səhifəsi (sıxışdırılmış)</comment>
- <comment xml:lang="be@latin">staronka dapamohi (skampresavanaja)</comment>
- <comment xml:lang="bg">Страница от справочника, компресирана</comment>
- <comment xml:lang="ca">pàgina de manual (amb compressió)</comment>
- <comment xml:lang="cs">manuálová stránka (komprimovaná)</comment>
- <comment xml:lang="cy">tudalen llawlyfr (wedi ei gywasgu)</comment>
- <comment xml:lang="da">manualside (komprimeret)</comment>
- <comment xml:lang="de">Handbuchseite (komprimiert)</comment>
- <comment xml:lang="el">Σελίδα οδηγιών (συμπιεσμένη)</comment>
- <comment xml:lang="en_GB">manual page (compressed)</comment>
- <comment xml:lang="eo">manpaĝo (kunpremita)</comment>
- <comment xml:lang="es">página de manual (comprimida)</comment>
- <comment xml:lang="eu">eskuliburu orria (konprimitua)</comment>
- <comment xml:lang="fi">manuaalisivu (pakattu)</comment>
- <comment xml:lang="fo">handbókasíða (stappað)</comment>
- <comment xml:lang="fr">page de manuel (compressée)</comment>
- <comment xml:lang="ga">leathanach lámhleabhair (comhbhrúite)</comment>
- <comment xml:lang="gl">páxina de manual (comprimida)</comment>
- <comment xml:lang="he">דף עזר (מכווץ)</comment>
- <comment xml:lang="hr">Stranica priručnika (sažeta)</comment>
- <comment xml:lang="hu">kézikönyvoldal (tömörített)</comment>
- <comment xml:lang="ia">Pagina de manual (comprimite)</comment>
- <comment xml:lang="id">halaman manual (terkompresi)</comment>
- <comment xml:lang="it">Pagina di manuale (compressa)</comment>
- <comment xml:lang="ja">(圧縮) man ページ</comment>
- <comment xml:lang="kk">әдістемелік парағы (сығылған)</comment>
- <comment xml:lang="ko">man 페이지(압축)</comment>
- <comment xml:lang="lt">žinyno puslapis (suglaudintas)</comment>
- <comment xml:lang="lv">rokasgrāmatas lapa (saspiesta)</comment>
- <comment xml:lang="ms">Halaman manual (termampat)</comment>
- <comment xml:lang="nb">manualside (komprimert)</comment>
- <comment xml:lang="nl">handleidingspagina (ingepakt)</comment>
- <comment xml:lang="nn">manualside (pakka)</comment>
- <comment xml:lang="oc">pagina de manual (compressat)</comment>
- <comment xml:lang="pl">Strona podręcznika (skompresowana)</comment>
- <comment xml:lang="pt">página de manual (comprimida)</comment>
- <comment xml:lang="pt_BR">Página de manual (compactada)</comment>
- <comment xml:lang="ro">pagină de manual (comprimată)</comment>
- <comment xml:lang="ru">Страница руководства (сжатая)</comment>
- <comment xml:lang="sk">Manuálová stránka (komprimovaná)</comment>
- <comment xml:lang="sl">stran priročnika (stisnjena)</comment>
- <comment xml:lang="sq">Faqe manuali (e kompresuar)</comment>
- <comment xml:lang="sr">страница упутства (запакована)</comment>
- <comment xml:lang="sv">manualsida (komprimerad)</comment>
- <comment xml:lang="tr">kılavuz dosyası (sıkıştırılmış)</comment>
- <comment xml:lang="uk">сторінка посібника (стиснена)</comment>
- <comment xml:lang="vi">trang hướng dẫn (đã nén)</comment>
+ <comment>Manual page (compressed)</comment>
<comment xml:lang="zh_CN">手册页(压缩)</comment>
- <comment xml:lang="zh_TW">手冊頁面 (壓縮版)</comment>
+ <comment xml:lang="uk">сторінка підручника (стиснена)</comment>
+ <comment xml:lang="tr">Kılavuz sayfası (sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Manualsida (komprimerad)</comment>
+ <comment xml:lang="si">අතින් පිටුව (සම්පීඩිත)</comment>
+ <comment xml:lang="ru">Страница руководства (сжатая)</comment>
+ <comment xml:lang="pt_BR">Página de manual (compactada)</comment>
+ <comment xml:lang="pl">Strona podręcznika (skompresowana)</comment>
+ <comment xml:lang="nl">Handleidingpagina (gecomprimeerd)</comment>
+ <comment xml:lang="ko">man 페이지 (압축)</comment>
+ <comment xml:lang="kk">Нұсқаулық парағы (сығылған)</comment>
+ <comment xml:lang="ja">マニュアルページ (圧縮)</comment>
+ <comment xml:lang="it">Pagina di manuale (compressa)</comment>
+ <comment xml:lang="hr">Stranica priručnika (sažeta)</comment>
+ <comment xml:lang="gl">Páxina de manual (comprimida)</comment>
+ <comment xml:lang="fi">Manuaalisivu (pakattu)</comment>
+ <comment xml:lang="eu">Eskuliburu-orria (konprimatua)</comment>
+ <comment xml:lang="es">página de manual (comprimida)</comment>
+ <comment xml:lang="en_GB">Manual page (compressed)</comment>
+ <comment xml:lang="de">Handbuchseite (komprimiert)</comment>
+ <comment xml:lang="be">старонка даведкі (сціснутая)</comment>
+ <comment xml:lang="ar">صفحة دليل (مضغوطة)</comment>
<generic-icon name="text-x-generic"/>
</mime-type>
<mime-type type="application/x-tzo">
<comment>Tar archive (LZO-compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط-LZO)</comment>
- <comment xml:lang="be@latin">Archiŭ tar (LZO-skampresavany)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран с LZO</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió LZO)</comment>
- <comment xml:lang="cs">archiv Tar (komprimovaný pomocí LZO)</comment>
- <comment xml:lang="da">Tar-arkiv (LZO-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (LZO-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με LZO)</comment>
- <comment xml:lang="en_GB">Tar archive (LZO-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con LZO)</comment>
- <comment xml:lang="eu">Tar artxiboa (LZO-rekin konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (LZO-pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn (LZO-stappað)</comment>
- <comment xml:lang="fr">archive tar (compression LZO)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZO)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido con LZO)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י LZO)</comment>
- <comment xml:lang="hr">Tar arhiva (LZO sažeta)</comment>
- <comment xml:lang="hu">Tar archívum (LZO-val tömörítve)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite con LZO)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi LZO)</comment>
- <comment xml:lang="it">Archivio tar (compresso con LZO)</comment>
- <comment xml:lang="ja">Tar アーカイブ (LZO 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (LZO-мен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(LZO 압축)</comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas su LZO)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests ar LZO)</comment>
- <comment xml:lang="nb">Tar-arkiv (LZO-komprimert)</comment>
- <comment xml:lang="nl">Tar-archief (ingepakt met LZO)</comment>
- <comment xml:lang="nn">Tar-arkiv (pakka med LZO)</comment>
- <comment xml:lang="oc">archiu tar (compression LZO)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja LZO)</comment>
- <comment xml:lang="pt">arquivo Tar (compressão LZO)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado com LZO)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată LZO)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый lzo)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou LZO)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z LZO)</comment>
- <comment xml:lang="sq">Arkiv tar (i kompresuar me LZO)</comment>
- <comment xml:lang="sr">Тар архива (запакована ЛЗО-ом)</comment>
- <comment xml:lang="sv">Tar-arkiv (LZO-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (LZO ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений LZO)</comment>
- <comment xml:lang="vi">Kho nén tar (đã nén LZO)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (LZO 壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(LZO 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (LZO 格式壓縮)</comment>
+ <comment xml:lang="vi">Kho nén tar (đã nén LZO)</comment>
+ <comment xml:lang="uk">архів tar (стиснений LZO)</comment>
+ <comment xml:lang="tr">Tar arşivi (LZO ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (LZO-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована ЛЗО-ом)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me LZO)</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z LZO)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (LZO-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou LZO)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый lzo)</comment>
+ <comment xml:lang="ro">Arhivă Tar (comprimată LZO)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado com LZO)</comment>
+ <comment xml:lang="pt">arquivo Tar (compressão LZO)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja LZO)</comment>
+ <comment xml:lang="oc">archiu tar (compression LZO)</comment>
+ <comment xml:lang="nn">Tar-arkiv (pakka med LZO)</comment>
+ <comment xml:lang="nl">Tar-archief (ingepakt met LZO)</comment>
+ <comment xml:lang="nb">Tar-arkiv (LZO-komprimert)</comment>
+ <comment xml:lang="lv">Tar arhīvs (saspiests ar LZO)</comment>
+ <comment xml:lang="lt">Tar archyvas (suglaudintas su LZO)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(LZO 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (LZO-мен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (LZO 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con LZO)</comment>
+ <comment xml:lang="is">Tar safnskrá (LZO-þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi LZO)</comment>
+ <comment xml:lang="ia">Archivo Tar (comprimite con LZO)</comment>
+ <comment xml:lang="hu">Tar archívum (LZO tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (LZO sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י LZO)</comment>
+ <comment xml:lang="gl">arquivo Tar (comprimido con LZO)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZO)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun LZO)</comment>
+ <comment xml:lang="fr">archive tar (compression LZO)</comment>
+ <comment xml:lang="fo">Tar skjalasavn (LZO-stappað)</comment>
+ <comment xml:lang="fi">Tar-arkisto (LZO-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (LZO-rekin konprimitua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con LZO)</comment>
+ <comment xml:lang="en_GB">Tar archive (LZO-compressed)</comment>
+ <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με LZO)</comment>
+ <comment xml:lang="de">Tar-Archiv (LZO-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (LZO-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimovaný pomocí LZO)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió LZO)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с LZO</comment>
+ <comment xml:lang="be@latin">Archiŭ tar (LZO-skampresavany)</comment>
+ <comment xml:lang="be">архіў tar (сцісканне LZO)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-LZO)</comment>
+ <comment xml:lang="af">Tar-argief (LZO-saamgepers)</comment>
<sub-class-of type="application/x-lzop"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.tar.lzo"/>
@@ -21421,1193 +23093,1402 @@
</mime-type>
<mime-type type="application/x-xz">
<comment>XZ archive</comment>
- <comment xml:lang="ar">أرشيف XZ</comment>
- <comment xml:lang="bg">Архив — XZ</comment>
- <comment xml:lang="ca">arxiu XZ</comment>
- <comment xml:lang="cs">archiv XZ</comment>
- <comment xml:lang="da">XZ-arkiv</comment>
- <comment xml:lang="de">XZ-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο XZ</comment>
- <comment xml:lang="en_GB">XZ archive</comment>
- <comment xml:lang="eo">XZ-arkivo</comment>
- <comment xml:lang="es">archivador XZ</comment>
- <comment xml:lang="eu">XZ artxiboa</comment>
- <comment xml:lang="fi">XZ-arkisto</comment>
- <comment xml:lang="fo">XZ skjalasavn</comment>
- <comment xml:lang="fr">archive XZ</comment>
- <comment xml:lang="ga">cartlann XZ</comment>
- <comment xml:lang="gl">ficheiro XZ</comment>
- <comment xml:lang="he">ארכיון XZ</comment>
- <comment xml:lang="hr">XZ arhiva</comment>
- <comment xml:lang="hu">XZ-archívum</comment>
- <comment xml:lang="ia">Archivo XZ</comment>
- <comment xml:lang="id">Arsip XZ</comment>
- <comment xml:lang="it">Archivio xz</comment>
- <comment xml:lang="ja">XZ アーカイブ</comment>
- <comment xml:lang="kk">XZ архиві</comment>
- <comment xml:lang="ko">XZ 압축 파일</comment>
- <comment xml:lang="lt">XZ archyvas</comment>
- <comment xml:lang="lv">XZ arhīvs</comment>
- <comment xml:lang="nl">XZ archief</comment>
- <comment xml:lang="oc">archiu XZ</comment>
- <comment xml:lang="pl">Archiwum XZ</comment>
- <comment xml:lang="pt">arquivo XZ</comment>
- <comment xml:lang="pt_BR">Pacote XZ</comment>
- <comment xml:lang="ro">Arhivă XZ</comment>
- <comment xml:lang="ru">Архив XZ</comment>
- <comment xml:lang="sk">Archív XZ</comment>
- <comment xml:lang="sl">Datoteka arhiva XZ</comment>
- <comment xml:lang="sr">ИксЗ архива</comment>
- <comment xml:lang="sv">XZ-arkiv</comment>
- <comment xml:lang="tr">XZ arşivi</comment>
- <comment xml:lang="uk">архів XZ</comment>
- <comment xml:lang="zh_CN">XZ 归档文件</comment>
<comment xml:lang="zh_TW">XZ 封存檔</comment>
+ <comment xml:lang="zh_CN">XZ 归档文件</comment>
+ <comment xml:lang="uk">архів XZ</comment>
+ <comment xml:lang="tr">XZ arşivi</comment>
+ <comment xml:lang="sv">XZ-arkiv</comment>
+ <comment xml:lang="sr">ИксЗ архива</comment>
+ <comment xml:lang="sq">arkiv XZ</comment>
+ <comment xml:lang="sl">Datoteka arhiva XZ</comment>
+ <comment xml:lang="si">XZ ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív XZ</comment>
+ <comment xml:lang="ru">Архив XZ</comment>
+ <comment xml:lang="ro">Arhivă XZ</comment>
+ <comment xml:lang="pt_BR">Pacote XZ</comment>
+ <comment xml:lang="pt">arquivo XZ</comment>
+ <comment xml:lang="pl">Archiwum XZ</comment>
+ <comment xml:lang="oc">archiu XZ</comment>
+ <comment xml:lang="nl">XZ archief</comment>
+ <comment xml:lang="lv">XZ arhīvs</comment>
+ <comment xml:lang="lt">XZ archyvas</comment>
+ <comment xml:lang="ko">XZ 압축 파일</comment>
+ <comment xml:lang="kk">XZ архиві</comment>
+ <comment xml:lang="ja">XZ アーカイブ</comment>
+ <comment xml:lang="it">Archivio xz</comment>
+ <comment xml:lang="is">XZ safnskrá</comment>
+ <comment xml:lang="id">Arsip XZ</comment>
+ <comment xml:lang="ia">Archivo XZ</comment>
+ <comment xml:lang="hu">XZ-archívum</comment>
+ <comment xml:lang="hr">XZ arhiva</comment>
+ <comment xml:lang="he">ארכיון XZ</comment>
+ <comment xml:lang="gl">ficheiro XZ</comment>
+ <comment xml:lang="ga">cartlann XZ</comment>
+ <comment xml:lang="fur">archivi XZ</comment>
+ <comment xml:lang="fr">archive XZ</comment>
+ <comment xml:lang="fo">XZ skjalasavn</comment>
+ <comment xml:lang="fi">XZ-arkisto</comment>
+ <comment xml:lang="eu">XZ artxiboa</comment>
+ <comment xml:lang="es">archivador XZ</comment>
+ <comment xml:lang="eo">XZ-arkivo</comment>
+ <comment xml:lang="en_GB">XZ archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο XZ</comment>
+ <comment xml:lang="de">XZ-Archiv</comment>
+ <comment xml:lang="da">XZ-arkiv</comment>
+ <comment xml:lang="cs">archiv XZ</comment>
+ <comment xml:lang="ca">arxiu XZ</comment>
+ <comment xml:lang="bg">Архив — XZ</comment>
+ <comment xml:lang="be">архіў XZ</comment>
+ <comment xml:lang="ar">أرشيف XZ</comment>
+ <comment xml:lang="af">XZ-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="\xfd\x37\x7a\x58\x5a\x00" type="string" offset="0"/>
+ <match type="string" value="\xfd\x37\x7a\x58\x5a\x00" offset="0"/>
</magic>
<glob pattern="*.xz"/>
</mime-type>
<mime-type type="application/x-xz-compressed-tar">
<comment>Tar archive (XZ-compressed)</comment>
- <comment xml:lang="ar">أرشيف Tar (مضغوط-XZ)</comment>
- <comment xml:lang="bg">Архив — tar, компресиран с XZ</comment>
- <comment xml:lang="ca">arxiu tar (amb compressió XZ)</comment>
- <comment xml:lang="cs">archiv Tar (komprimovaný pomocí XZ)</comment>
- <comment xml:lang="da">Tar-arkiv (XZ-komprimeret)</comment>
- <comment xml:lang="de">Tar-Archiv (XZ-komprimiert)</comment>
- <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με XZ)</comment>
- <comment xml:lang="en_GB">Tar archive (XZ-compressed)</comment>
- <comment xml:lang="es">archivador Tar (comprimido con XZ)</comment>
- <comment xml:lang="eu">Tar artxiboa (XZ-rekin konprimitua)</comment>
- <comment xml:lang="fi">Tar-arkisto (XZ-pakattu)</comment>
- <comment xml:lang="fo">Tar skjalasavn(XZ-stappað)</comment>
- <comment xml:lang="fr">archive tar (compression XZ)</comment>
- <comment xml:lang="ga">cartlann Tar (comhbhrúite le XZ)</comment>
- <comment xml:lang="gl">arquivo Tar (comprimido con XZ)</comment>
- <comment xml:lang="he">ארכיון Tar (מכווץ ע״י XZ)</comment>
- <comment xml:lang="hr">Tar arhiva ( XZ sažeta)</comment>
- <comment xml:lang="hu">Tar archívum (XZ-vel tömörítve)</comment>
- <comment xml:lang="ia">Archivo Tar (comprimite con XZ)</comment>
- <comment xml:lang="id">Arsip Tar (terkompresi XZ)</comment>
- <comment xml:lang="it">Archivio tar (compresso con XZ)</comment>
- <comment xml:lang="ja">Tar アーカイブ (XZ 圧縮)</comment>
- <comment xml:lang="kk">Tar архиві (XZ-мен сығылған)</comment>
- <comment xml:lang="ko">TAR 묶음 파일(XZ 압축)</comment>
- <comment xml:lang="lt">Tar archyvas (suglaudintas su XZ)</comment>
- <comment xml:lang="lv">Tar arhīvs (saspiests ar XZ)</comment>
- <comment xml:lang="nl">Tar archief (XZ-compressed)</comment>
- <comment xml:lang="oc">archiu tar (compression XZ)</comment>
- <comment xml:lang="pl">Archiwum tar (kompresja XZ)</comment>
- <comment xml:lang="pt">arquivo Tar (compressão XZ)</comment>
- <comment xml:lang="pt_BR">Pacote Tar (compactado com XZ)</comment>
- <comment xml:lang="ro">Arhivă Tar (comprimată XZ)</comment>
- <comment xml:lang="ru">Архив TAR (сжатый xz)</comment>
- <comment xml:lang="sk">Archív tar (komprimovaný pomocou XZ)</comment>
- <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z XZ)</comment>
- <comment xml:lang="sr">Тар архива (запакована ИксЗ-ом)</comment>
- <comment xml:lang="sv">Tar-arkiv (XZ-komprimerat)</comment>
- <comment xml:lang="tr">Tar arşivi (XZ ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">архів tar (стиснений XZ)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (XZ 壓縮)</comment>
<comment xml:lang="zh_CN">Tar 归档文件(XZ 压缩)</comment>
- <comment xml:lang="zh_TW">Tar 封存檔 (XZ 格式壓縮)</comment>
+ <comment xml:lang="uk">архів tar (стиснений XZ)</comment>
+ <comment xml:lang="tr">Tar arşivi (XZ ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (XZ-komprimerat)</comment>
+ <comment xml:lang="sr">Тар архива (запакована ИксЗ-ом)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me XZ)</comment>
+ <comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z XZ)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (XZ-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Archív Tar (komprimovaný pomocou XZ)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый xz)</comment>
+ <comment xml:lang="ro">Arhivă Tar (comprimată XZ)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado com XZ)</comment>
+ <comment xml:lang="pt">arquivo Tar (compressão XZ)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja XZ)</comment>
+ <comment xml:lang="oc">archiu tar (compression XZ)</comment>
+ <comment xml:lang="nl">Tar archief (XZ-compressed)</comment>
+ <comment xml:lang="lv">Tar arhīvs (saspiests ar XZ)</comment>
+ <comment xml:lang="lt">Tar archyvas (suglaudintas su XZ)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(XZ 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (XZ-мен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (XZ 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con XZ)</comment>
+ <comment xml:lang="is">Tar safnskrá (XZ-þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi XZ)</comment>
+ <comment xml:lang="ia">Archivo Tar (comprimite con XZ)</comment>
+ <comment xml:lang="hu">Tar archívum (XZ tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva ( XZ sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י XZ)</comment>
+ <comment xml:lang="gl">arquivo Tar (comprimido con XZ)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le XZ)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun XZ)</comment>
+ <comment xml:lang="fr">archive tar (compression XZ)</comment>
+ <comment xml:lang="fo">Tar skjalasavn(XZ-stappað)</comment>
+ <comment xml:lang="fi">Tar-arkisto (XZ-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (XZ-rekin konprimitua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con XZ)</comment>
+ <comment xml:lang="en_GB">Tar archive (XZ-compressed)</comment>
+ <comment xml:lang="el">Αρχείο Tar (συμπιεσμένο με XZ)</comment>
+ <comment xml:lang="de">Tar-Archiv (XZ-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (XZ-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimovaný pomocí XZ)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió XZ)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран с XZ</comment>
+ <comment xml:lang="be">архіў tar (сцісканне XZ)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-XZ)</comment>
+ <comment xml:lang="af">Tar-argief (XZ-saamgepers)</comment>
<sub-class-of type="application/x-xz"/>
<generic-icon name="package-x-generic"/>
<glob pattern="*.tar.xz"/>
<glob pattern="*.txz"/>
</mime-type>
+ <mime-type type="application/x-zpaq">
+ <comment>Zpaq Archive</comment>
+ <comment xml:lang="uk">архів zpaq</comment>
+ <comment xml:lang="sv">Zpaq-arkiv</comment>
+ <comment xml:lang="ru">Архив zpaq</comment>
+ <comment xml:lang="pl">Archiwum ZPAQ</comment>
+ <comment xml:lang="it">Archivio zpaq</comment>
+ <comment xml:lang="gl">Arquivo Zpaq</comment>
+ <comment xml:lang="eu">Zpaq artxiboa</comment>
+ <comment xml:lang="es">archivador Zpaq</comment>
+ <comment xml:lang="de">Zpaq-Archiv</comment>
+ <comment xml:lang="be">архіў Zpaq</comment>
+ <generic-icon name="package-x-generic"/>
+ <magic>
+ <match type="string" value="7kSt" offset="0"/>
+ </magic>
+ <glob pattern="*.zpaq"/>
+ </mime-type>
+ <mime-type type="application/zstd">
+ <comment>Zstandard archive</comment>
+ <comment xml:lang="zh_TW">Zstandard 封存檔</comment>
+ <comment xml:lang="zh_CN">Zstandard 归档文件</comment>
+ <comment xml:lang="uk">архів Zstandard</comment>
+ <comment xml:lang="tr">Zstandard arşivi</comment>
+ <comment xml:lang="sv">Zstandard-arkiv</comment>
+ <comment xml:lang="sq">arkiv Zstandard</comment>
+ <comment xml:lang="sl">Arhiv Zstandard</comment>
+ <comment xml:lang="si">Zstandard ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Zstandard</comment>
+ <comment xml:lang="ru">Архив Zstandard</comment>
+ <comment xml:lang="pt_BR">Pacote Zstandard</comment>
+ <comment xml:lang="pl">Archiwum Zstandard</comment>
+ <comment xml:lang="oc">archiu Zstandard</comment>
+ <comment xml:lang="nl">Zstandard-archief</comment>
+ <comment xml:lang="ko">Zstandard 압축 파일</comment>
+ <comment xml:lang="kk">Zstandard архиві</comment>
+ <comment xml:lang="ja">Zstandard アーカイブ</comment>
+ <comment xml:lang="it">Archivio Zstandard</comment>
+ <comment xml:lang="is">Zstandard safnskrá</comment>
+ <comment xml:lang="id">Arsip Zstandard</comment>
+ <comment xml:lang="hu">Zstandard archívum</comment>
+ <comment xml:lang="hr">Zstandard arhiva</comment>
+ <comment xml:lang="he">ארכיון Zstandard</comment>
+ <comment xml:lang="gl">Arquivo de Zstandard</comment>
+ <comment xml:lang="fur">archivi Zstandard</comment>
+ <comment xml:lang="fr">archive Zstandard</comment>
+ <comment xml:lang="fi">Zstandard-arkisto</comment>
+ <comment xml:lang="eu">Zstandard archive</comment>
+ <comment xml:lang="es">archivador Zstandard</comment>
+ <comment xml:lang="en_GB">Zstandard archive</comment>
+ <comment xml:lang="de">Zstandard-Archiv</comment>
+ <comment xml:lang="da">Zstandard-arkiv</comment>
+ <comment xml:lang="cs">archiv Zstandard</comment>
+ <comment xml:lang="ca">arxiu Zstandard</comment>
+ <comment xml:lang="bg">Архив — Zstandard</comment>
+ <comment xml:lang="be">архіў Zstandard</comment>
+ <comment xml:lang="ar">أرشيف Zstandard</comment>
+ <generic-icon name="package-x-generic"/>
+ <magic priority="60">
+ <match type="little32" value="0xFD2FB528" offset="0"/>
+ </magic>
+ <glob pattern="*.zst"/>
+ </mime-type>
+ <mime-type type="application/x-zstd-compressed-tar">
+ <comment>Tar archive (Zstandard-compressed)</comment>
+ <comment xml:lang="zh_TW">Tar 封存檔 (Zstandard 壓縮)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(Zstandard 压缩)</comment>
+ <comment xml:lang="uk">архів tar archive (стиснений Zstandard)</comment>
+ <comment xml:lang="tr">Tar arşivi (Zstandard ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">Tar-arkiv (Zstandard-komprimerat)</comment>
+ <comment xml:lang="sq">arkiv tar (ngjeshur me Zstandard)</comment>
+ <comment xml:lang="sl">Arhiv tar (stisnjen, Zstandard)</comment>
+ <comment xml:lang="si">තාර සංරක්ෂිතය (Zstandard-compressed)</comment>
+ <comment xml:lang="ru">Архив TAR (сжатый zstandard)</comment>
+ <comment xml:lang="pt_BR">Pacote Tar (compactado com Zstandard)</comment>
+ <comment xml:lang="pl">Archiwum tar (kompresja Zstandard)</comment>
+ <comment xml:lang="oc">archiu Tar (compressat amb Zstandard)</comment>
+ <comment xml:lang="nl">Tar-archief (gecomprimeerd met Zstandard)</comment>
+ <comment xml:lang="ko">TAR 묶음 파일(Zstandard 압축)</comment>
+ <comment xml:lang="kk">Tar архиві (Zstandard-пен сығылған)</comment>
+ <comment xml:lang="ja">Tar アーカイブ (ZStandard 圧縮)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con Zstandard)</comment>
+ <comment xml:lang="is">Tar safnskrá (Zstandard þjappað)</comment>
+ <comment xml:lang="id">Arsip Tar (terkompresi Zstandard)</comment>
+ <comment xml:lang="hu">Tar archívum (Zstandard tömörítésű)</comment>
+ <comment xml:lang="hr">Tar arhiva (Zstandard-sažeta)</comment>
+ <comment xml:lang="he">ארכיון Tar (מכווץ ע״י Zstandard)</comment>
+ <comment xml:lang="gl">Arquivo Tar (comprimido Zstandard)</comment>
+ <comment xml:lang="fur">archivi Tar (comprimût cun Zstandard)</comment>
+ <comment xml:lang="fr">archive tar (compression Zstandard)</comment>
+ <comment xml:lang="fi">Tar-arkisto (Zstandard-pakattu)</comment>
+ <comment xml:lang="eu">Tar artxiboa (Zstandard-rekin konprimitua)</comment>
+ <comment xml:lang="es">archivador TAR (comprimido con Zstandard)</comment>
+ <comment xml:lang="en_GB">Tar archive (Zstandard-compressed)</comment>
+ <comment xml:lang="de">Tar-Archiv (Zstandard-komprimiert)</comment>
+ <comment xml:lang="da">Tar-arkiv (Zstandard-komprimeret)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimovaný pomocí Zstandard)</comment>
+ <comment xml:lang="ca">arxiu tar (amb compressió Zstandard)</comment>
+ <comment xml:lang="bg">Архив — tar, компресиран със Zstandard</comment>
+ <comment xml:lang="be">архіў tar (сцісканне Zstandard)</comment>
+ <comment xml:lang="ar">أرشيف Tar (مضغوط-Zstandard)</comment>
+ <generic-icon name="package-x-generic"/>
+ <sub-class-of type="application/zstd"/>
+ <glob pattern="*.tar.zst"/>
+ <glob pattern="*.tzst"/>
+ </mime-type>
<mime-type type="application/x-xzpdf">
<comment>PDF document (XZ-compressed)</comment>
- <comment xml:lang="ast">Documentu PDF (comprimíu en XZ)</comment>
- <comment xml:lang="bg">Документ — PDF, компресиран с XZ</comment>
- <comment xml:lang="ca">document PDF (amb compressió XZ)</comment>
- <comment xml:lang="cs">dokument PDF (komprimovaný pomocí XZ)</comment>
- <comment xml:lang="da">PDF-dokument (XZ-komprimeret)</comment>
- <comment xml:lang="de">PDF-Dokument (XZ-komprimiert)</comment>
- <comment xml:lang="el">Έγγραφο PDF (συμπιεσμένο με XZ)</comment>
- <comment xml:lang="en_GB">PDF document (XZ-compressed)</comment>
- <comment xml:lang="es">documento PDF (comprimido con XZ)</comment>
- <comment xml:lang="eu">PDF dokumentua (XZ-rekin konprimitua)</comment>
- <comment xml:lang="fi">PDF-asiakirja (XZ-pakattu)</comment>
- <comment xml:lang="fr">document PDF (compressé XZ)</comment>
- <comment xml:lang="ga">cáipéis PDF (comhbhrúite le XZ)</comment>
- <comment xml:lang="gl">documento PDF (comprimido en XZ)</comment>
- <comment xml:lang="he">מסמך PDF (מכווץ ע״י XZ)</comment>
- <comment xml:lang="hr">PDF dokument ( XZ sažet)</comment>
- <comment xml:lang="hu">PDF dokumentum (XZ-vel tömörített)</comment>
- <comment xml:lang="ia">Documento PDF (comprimite con XZ)</comment>
- <comment xml:lang="id">Dokumen PDF (terkompresi XZ)</comment>
- <comment xml:lang="it">Documento PDF (compresso con XZ)</comment>
- <comment xml:lang="ja">PDF 文書(XZ 圧縮)</comment>
- <comment xml:lang="ka">PDF დოკუმენტი (XZ-ით შეკუმშული)</comment>
- <comment xml:lang="kk">PDF құжаты (XZ-мен сығылған)</comment>
- <comment xml:lang="ko">PDF 문서(XZ 압축)</comment>
- <comment xml:lang="lv">PDF dokuments (saspiests ar XZ)</comment>
- <comment xml:lang="nl">PDF document (XZ-compressed)</comment>
- <comment xml:lang="oc">document PDF (compressat XZ)</comment>
- <comment xml:lang="pl">Dokument PDF (kompresja XZ)</comment>
- <comment xml:lang="pt">documento PDF (compressão XZ)</comment>
- <comment xml:lang="pt_BR">Documento PDF (compactado com XZ)</comment>
- <comment xml:lang="ru">Документ PDF (сжатый xz)</comment>
- <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou XZ)</comment>
- <comment xml:lang="sl">Dokument PDF (XZ-stisnjen)</comment>
- <comment xml:lang="sr">ПДФ документ (запакован ИксЗ-ом)</comment>
- <comment xml:lang="sv">PDF-dokument (XZ-komprimerat)</comment>
- <comment xml:lang="tr">PDF belgesi (XZ ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">документ PDF (стиснений xz)</comment>
+ <comment xml:lang="zh_TW">PDF 文件 (XZ 壓縮)</comment>
<comment xml:lang="zh_CN">PDF 文档(XZ)</comment>
- <comment xml:lang="zh_TW">PDF 文件 (XZ 格式壓縮)</comment>
+ <comment xml:lang="uk">документ PDF (стиснений xz)</comment>
+ <comment xml:lang="tr">PDF belgesi (XZ ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">PDF-dokument (XZ-komprimerat)</comment>
+ <comment xml:lang="sr">ПДФ документ (запакован ИксЗ-ом)</comment>
+ <comment xml:lang="sq">dokument PDF (ngjeshur me XZ)</comment>
+ <comment xml:lang="sl">Dokument PDF (XZ-stisnjen)</comment>
+ <comment xml:lang="si">PDF ලේඛනය (XZ-සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou XZ)</comment>
+ <comment xml:lang="ru">Документ PDF (сжатый xz)</comment>
+ <comment xml:lang="pt_BR">Documento PDF (compactado com XZ)</comment>
+ <comment xml:lang="pt">documento PDF (compressão XZ)</comment>
+ <comment xml:lang="pl">Dokument PDF (kompresja XZ)</comment>
+ <comment xml:lang="oc">document PDF (compressat XZ)</comment>
+ <comment xml:lang="nl">PDF document (XZ-compressed)</comment>
+ <comment xml:lang="lv">PDF dokuments (saspiests ar XZ)</comment>
+ <comment xml:lang="ko">PDF 문서(XZ 압축)</comment>
+ <comment xml:lang="kk">PDF құжаты (XZ-мен сығылған)</comment>
+ <comment xml:lang="ka">PDF დოკუმენტი (XZ-ით შეკუმშული)</comment>
+ <comment xml:lang="ja">PDF 文書(XZ 圧縮)</comment>
+ <comment xml:lang="it">Documento PDF (compresso con XZ)</comment>
+ <comment xml:lang="is">PDF skjal (XZ-þjappað)</comment>
+ <comment xml:lang="id">Dokumen PDF (terkompresi XZ)</comment>
+ <comment xml:lang="ia">Documento PDF (comprimite con XZ)</comment>
+ <comment xml:lang="hu">PDF dokumentum (XZ tömörítésű)</comment>
+ <comment xml:lang="hr">PDF dokument ( XZ sažet)</comment>
+ <comment xml:lang="he">מסמך PDF (מכווץ ע״י XZ)</comment>
+ <comment xml:lang="gl">documento PDF (comprimido en XZ)</comment>
+ <comment xml:lang="ga">cáipéis PDF (comhbhrúite le XZ)</comment>
+ <comment xml:lang="fur">document PDF (comprimût cun XZ)</comment>
+ <comment xml:lang="fr">document PDF (compressé XZ)</comment>
+ <comment xml:lang="fi">PDF-asiakirja (XZ-pakattu)</comment>
+ <comment xml:lang="eu">PDF dokumentua (XZ-rekin konprimitua)</comment>
+ <comment xml:lang="es">documento PDF (comprimido con XZ)</comment>
+ <comment xml:lang="en_GB">PDF document (XZ-compressed)</comment>
+ <comment xml:lang="el">Έγγραφο PDF (συμπιεσμένο με XZ)</comment>
+ <comment xml:lang="de">PDF-Dokument (XZ-komprimiert)</comment>
+ <comment xml:lang="da">PDF-dokument (XZ-komprimeret)</comment>
+ <comment xml:lang="cs">dokument PDF (komprimovaný pomocí XZ)</comment>
+ <comment xml:lang="ca">document PDF (amb compressió XZ)</comment>
+ <comment xml:lang="bg">Документ — PDF, компресиран с XZ</comment>
+ <comment xml:lang="be">дакумент PDF (сцісканне XZ)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en XZ)</comment>
+ <comment xml:lang="ar">مستند PDF (مضغوط-XZ)</comment>
+ <comment xml:lang="af">PDF-dokument (XZ-saamgepers)</comment>
<sub-class-of type="application/x-xz"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.pdf.xz"/>
</mime-type>
<mime-type type="application/x-ustar">
<comment>Ustar archive</comment>
- <comment xml:lang="ar">أرشيف Ustar</comment>
- <comment xml:lang="be@latin">Archiŭ ustar</comment>
- <comment xml:lang="bg">Архив — ustar</comment>
- <comment xml:lang="ca">arxiu ustar</comment>
- <comment xml:lang="cs">archiv Ustar</comment>
- <comment xml:lang="da">Ustararkiv</comment>
- <comment xml:lang="de">Ustar-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Ustar</comment>
- <comment xml:lang="en_GB">Ustar archive</comment>
- <comment xml:lang="eo">Ustar-arkivo</comment>
- <comment xml:lang="es">archivador de Ustar</comment>
- <comment xml:lang="eu">Ustar artxiboa</comment>
- <comment xml:lang="fi">Ustar-arkisto</comment>
- <comment xml:lang="fo">Ustar skjalasavn</comment>
- <comment xml:lang="fr">archive Ustar</comment>
- <comment xml:lang="ga">cartlann Ustar</comment>
- <comment xml:lang="gl">arquivo Ustar</comment>
- <comment xml:lang="he">ארכיון Ustar</comment>
- <comment xml:lang="hr">Ustar arhiva</comment>
- <comment xml:lang="hu">Ustar archívum</comment>
- <comment xml:lang="ia">Archivo Ustar</comment>
- <comment xml:lang="id">Arsip Ustar</comment>
- <comment xml:lang="it">Archivio ustar</comment>
- <comment xml:lang="ja">Ustar アーカイブ</comment>
- <comment xml:lang="kk">Ustar архиві</comment>
- <comment xml:lang="ko">Ustar 압축 파일</comment>
- <comment xml:lang="lt">Ustar archyvas</comment>
- <comment xml:lang="lv">Ustar arhīvs</comment>
- <comment xml:lang="nb">Ustar-arkiv</comment>
- <comment xml:lang="nl">Ustar-archief</comment>
- <comment xml:lang="nn">Ustar-arkiv</comment>
- <comment xml:lang="oc">archiu Ustar</comment>
- <comment xml:lang="pl">Archiwum ustar</comment>
- <comment xml:lang="pt">arquivo Ustar</comment>
- <comment xml:lang="pt_BR">Pacote Ustar</comment>
- <comment xml:lang="ro">Arhivă Ustar</comment>
- <comment xml:lang="ru">Архив Ustar</comment>
- <comment xml:lang="sk">Archív ustar</comment>
- <comment xml:lang="sl">Datoteka arhiva Ustar</comment>
- <comment xml:lang="sq">Arkiv Ustar</comment>
- <comment xml:lang="sr">Устар архива</comment>
- <comment xml:lang="sv">Ustar-arkiv</comment>
- <comment xml:lang="tr">Ustar arşivi</comment>
- <comment xml:lang="uk">архів ustar</comment>
- <comment xml:lang="vi">Kho nén ustar</comment>
- <comment xml:lang="zh_CN">Ustar 归档文件</comment>
<comment xml:lang="zh_TW">Ustar 封存檔</comment>
+ <comment xml:lang="zh_CN">Ustar 归档文件</comment>
+ <comment xml:lang="vi">Kho nén ustar</comment>
+ <comment xml:lang="uk">архів ustar</comment>
+ <comment xml:lang="tr">Ustar arşivi</comment>
+ <comment xml:lang="sv">Ustar-arkiv</comment>
+ <comment xml:lang="sr">Устар архива</comment>
+ <comment xml:lang="sq">arkiv Ustar</comment>
+ <comment xml:lang="sl">Datoteka arhiva Ustar</comment>
+ <comment xml:lang="si">Ustar ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Ustar</comment>
+ <comment xml:lang="ru">Архив Ustar</comment>
+ <comment xml:lang="ro">Arhivă Ustar</comment>
+ <comment xml:lang="pt_BR">Pacote Ustar</comment>
+ <comment xml:lang="pt">arquivo Ustar</comment>
+ <comment xml:lang="pl">Archiwum ustar</comment>
+ <comment xml:lang="oc">archiu Ustar</comment>
+ <comment xml:lang="nn">Ustar-arkiv</comment>
+ <comment xml:lang="nl">Ustar-archief</comment>
+ <comment xml:lang="nb">Ustar-arkiv</comment>
+ <comment xml:lang="lv">Ustar arhīvs</comment>
+ <comment xml:lang="lt">Ustar archyvas</comment>
+ <comment xml:lang="ko">Ustar 압축 파일</comment>
+ <comment xml:lang="kk">Ustar архиві</comment>
+ <comment xml:lang="ja">Ustar アーカイブ</comment>
+ <comment xml:lang="it">Archivio ustar</comment>
+ <comment xml:lang="is">Ustar safnskrá</comment>
+ <comment xml:lang="id">Arsip Ustar</comment>
+ <comment xml:lang="ia">Archivo Ustar</comment>
+ <comment xml:lang="hu">Ustar archívum</comment>
+ <comment xml:lang="hr">Ustar arhiva</comment>
+ <comment xml:lang="he">ארכיון Ustar</comment>
+ <comment xml:lang="gl">arquivo Ustar</comment>
+ <comment xml:lang="ga">cartlann Ustar</comment>
+ <comment xml:lang="fur">archivi Ustar</comment>
+ <comment xml:lang="fr">archive Ustar</comment>
+ <comment xml:lang="fo">Ustar skjalasavn</comment>
+ <comment xml:lang="fi">Ustar-arkisto</comment>
+ <comment xml:lang="eu">Ustar artxiboa</comment>
+ <comment xml:lang="es">archivador de Ustar</comment>
+ <comment xml:lang="eo">Ustar-arkivo</comment>
+ <comment xml:lang="en_GB">Ustar archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Ustar</comment>
+ <comment xml:lang="de">Ustar-Archiv</comment>
+ <comment xml:lang="da">Ustar-arkiv</comment>
+ <comment xml:lang="cs">archiv Ustar</comment>
+ <comment xml:lang="ca">arxiu ustar</comment>
+ <comment xml:lang="bg">Архив — ustar</comment>
+ <comment xml:lang="be@latin">Archiŭ ustar</comment>
+ <comment xml:lang="be">архіў ustar</comment>
+ <comment xml:lang="ar">أرشيف Ustar</comment>
+ <comment xml:lang="af">Ustar-argief</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.ustar"/>
</mime-type>
<mime-type type="application/x-wais-source">
<comment>WAIS source code</comment>
- <comment xml:lang="ar">شفرة مصدر WAIS</comment>
- <comment xml:lang="az">WAIS mənbə faylı</comment>
- <comment xml:lang="be@latin">Kryničny kod WAIS</comment>
- <comment xml:lang="bg">Изходен код — WAIS</comment>
- <comment xml:lang="ca">codi font en WAIS</comment>
- <comment xml:lang="cs">zdrojový kód WAIS</comment>
- <comment xml:lang="cy">Ffynhonnell Rhaglen WAIS</comment>
- <comment xml:lang="da">WAIS-kildekode</comment>
- <comment xml:lang="de">WAIS-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας WAIS</comment>
- <comment xml:lang="en_GB">WAIS source code</comment>
- <comment xml:lang="eo">WAIS-fontkodo</comment>
- <comment xml:lang="es">código fuente en WAIS</comment>
- <comment xml:lang="eu">WAIS iturburu-kodea</comment>
- <comment xml:lang="fi">WAIS-lähdekoodi</comment>
- <comment xml:lang="fo">WAIS keldukota</comment>
- <comment xml:lang="fr">code source WAIS</comment>
- <comment xml:lang="ga">cód foinseach WAIS</comment>
- <comment xml:lang="gl">código fonte WAIS</comment>
- <comment xml:lang="he">קוד מקור של WAIS</comment>
- <comment xml:lang="hr">WAIS izvorni kôd</comment>
- <comment xml:lang="hu">WAIS-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte WAIS</comment>
- <comment xml:lang="id">Kode program WAIS</comment>
- <comment xml:lang="it">Codice sorgente WAIS</comment>
- <comment xml:lang="ja">WAIS ソースコード</comment>
- <comment xml:lang="kk">WAIS бастапқы коды</comment>
- <comment xml:lang="ko">WAIS 소스 코드</comment>
- <comment xml:lang="lt">WAIS pradinis kodas</comment>
- <comment xml:lang="lv">WAIS pirmkods</comment>
- <comment xml:lang="ms">Kod sumber WAIS</comment>
- <comment xml:lang="nb">WAIS-kildekode</comment>
- <comment xml:lang="nl">WAIS-broncode</comment>
- <comment xml:lang="nn">WAIS-kjeldekode</comment>
- <comment xml:lang="oc">còde font WAIS</comment>
- <comment xml:lang="pl">Plik źródłowy WAIS</comment>
- <comment xml:lang="pt">código origem WAIS</comment>
- <comment xml:lang="pt_BR">Código-fonte WAIS</comment>
- <comment xml:lang="ro">Cod sursă WAIS</comment>
- <comment xml:lang="ru">Исходный код WAIS</comment>
- <comment xml:lang="sk">Zdrojový kód WAIS</comment>
- <comment xml:lang="sl">Datoteka izvorne kode WAIS</comment>
- <comment xml:lang="sq">Kod burues WAIS</comment>
- <comment xml:lang="sr">ВАИС изворни ко̂д</comment>
- <comment xml:lang="sv">WAIS-källkod</comment>
- <comment xml:lang="tr">WAIS kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою WAIS</comment>
- <comment xml:lang="vi">Mã nguồn WAIS</comment>
- <comment xml:lang="zh_CN">WAIS 源代码</comment>
<comment xml:lang="zh_TW">WAIS 源碼</comment>
+ <comment xml:lang="zh_CN">WAIS 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn WAIS</comment>
+ <comment xml:lang="uk">початковий код мовою WAIS</comment>
+ <comment xml:lang="tr">WAIS kaynak kodu</comment>
+ <comment xml:lang="sv">WAIS-källkod</comment>
+ <comment xml:lang="sr">ВАИС изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim WAIS</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode WAIS</comment>
+ <comment xml:lang="si">WAIS මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód WAIS</comment>
+ <comment xml:lang="ru">Исходный код WAIS</comment>
+ <comment xml:lang="ro">Cod sursă WAIS</comment>
+ <comment xml:lang="pt_BR">Código-fonte WAIS</comment>
+ <comment xml:lang="pt">código origem WAIS</comment>
+ <comment xml:lang="pl">Kod źródłowy WAIS</comment>
+ <comment xml:lang="oc">còde font WAIS</comment>
+ <comment xml:lang="nn">WAIS-kjeldekode</comment>
+ <comment xml:lang="nl">WAIS-broncode</comment>
+ <comment xml:lang="nb">WAIS-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber WAIS</comment>
+ <comment xml:lang="lv">WAIS pirmkods</comment>
+ <comment xml:lang="lt">WAIS pradinis kodas</comment>
+ <comment xml:lang="ko">WAIS 소스 코드</comment>
+ <comment xml:lang="kk">WAIS бастапқы коды</comment>
+ <comment xml:lang="ja">WAIS ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente WAIS</comment>
+ <comment xml:lang="is">WAIS frumkóði</comment>
+ <comment xml:lang="id">Kode program WAIS</comment>
+ <comment xml:lang="ia">Codice-fonte WAIS</comment>
+ <comment xml:lang="hu">WAIS-forráskód</comment>
+ <comment xml:lang="hr">WAIS izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של WAIS</comment>
+ <comment xml:lang="gl">código fonte WAIS</comment>
+ <comment xml:lang="ga">cód foinseach WAIS</comment>
+ <comment xml:lang="fur">codiç sorzint WAIS</comment>
+ <comment xml:lang="fr">code source WAIS</comment>
+ <comment xml:lang="fo">WAIS keldukota</comment>
+ <comment xml:lang="fi">WAIS-lähdekoodi</comment>
+ <comment xml:lang="eu">WAIS iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en WAIS</comment>
+ <comment xml:lang="eo">WAIS-fontkodo</comment>
+ <comment xml:lang="en_GB">WAIS source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας WAIS</comment>
+ <comment xml:lang="de">WAIS-Quelltext</comment>
+ <comment xml:lang="da">WAIS-kildekode</comment>
+ <comment xml:lang="cy">Ffynhonnell Rhaglen WAIS</comment>
+ <comment xml:lang="cs">zdrojový kód WAIS</comment>
+ <comment xml:lang="ca">codi font en WAIS</comment>
+ <comment xml:lang="bg">Изходен код — WAIS</comment>
+ <comment xml:lang="be@latin">Kryničny kod WAIS</comment>
+ <comment xml:lang="be">зыходны код WAIS</comment>
+ <comment xml:lang="az">WAIS mənbə faylı</comment>
+ <comment xml:lang="ar">شفرة مصدر WAIS</comment>
+ <comment xml:lang="af">WAIS-bronkode</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<glob pattern="*.src"/>
</mime-type>
<mime-type type="application/x-wpg">
<comment>WordPerfect/Drawperfect image</comment>
- <comment xml:lang="ar">صورة WordPerfect/Drawperfect</comment>
- <comment xml:lang="be@latin">Vyjava WordPerfect/Drawperfect</comment>
- <comment xml:lang="bg">Изображение — WordPerfect/Drawperfect</comment>
- <comment xml:lang="ca">imatge de WordPerfect/Drawperfect</comment>
- <comment xml:lang="cs">obrázek WordPerfect/Drawperfect</comment>
- <comment xml:lang="da">WordPerfect/Drawperfect-billede</comment>
- <comment xml:lang="de">WordPerfect/DrawPerfect-Bild</comment>
- <comment xml:lang="el">Εικόνα WordPerfect/Drawperfect</comment>
- <comment xml:lang="en_GB">WordPerfect/Drawperfect image</comment>
- <comment xml:lang="eo">WordPerfect/Drawperfect-bildo</comment>
- <comment xml:lang="es">imagen de WordPerfect/Drawperfect</comment>
- <comment xml:lang="eu">WordPerfect/Drawperfect irudia</comment>
- <comment xml:lang="fi">WordPerfect/Drawperfect-kuva</comment>
- <comment xml:lang="fo">WordPerfect/Drawperfect mynd</comment>
- <comment xml:lang="fr">image WordPerfect/DrawPerfect</comment>
- <comment xml:lang="ga">íomhá WordPerfect/Drawperfect</comment>
- <comment xml:lang="gl">imaxe de WordPerfect/DrawPerfect</comment>
- <comment xml:lang="he">תמונה של WordPerfect/Drawperfect</comment>
- <comment xml:lang="hr">WordPerfect/Drawperfect slika</comment>
- <comment xml:lang="hu">WordPerfect/Drawperfect-kép</comment>
- <comment xml:lang="ia">Imagine WordPerfect/DrawPerfect</comment>
- <comment xml:lang="id">Gambar WordPerfect/Drawperfect</comment>
- <comment xml:lang="it">Immagine WordPerfect/Drawperfect</comment>
- <comment xml:lang="ja">WordPerfect/Drawperfect 画像</comment>
- <comment xml:lang="kk">WordPerfect/Drawperfect суреті</comment>
- <comment xml:lang="ko">WordPerfect/Drawperfect 그림</comment>
- <comment xml:lang="lt">WordPerfect/Drawperfect paveikslėlis</comment>
- <comment xml:lang="lv">WordPerfect/Drawperfect attēls</comment>
- <comment xml:lang="ms">Imej WordPerfect/Drawperfect</comment>
- <comment xml:lang="nb">WordPerfect-/Drawperfect-bilde</comment>
- <comment xml:lang="nl">WordPerfect/Drawperfect-afbeelding</comment>
- <comment xml:lang="nn">WordPerfect/DrawPerfect-bilete</comment>
- <comment xml:lang="oc">imatge WordPerfect/DrawPerfect</comment>
- <comment xml:lang="pl">Obraz WordPerfect/DrawPerfect</comment>
- <comment xml:lang="pt">imagem do WordPerfect/Drawperfect</comment>
- <comment xml:lang="pt_BR">Imagem do WordPerfect/Drawperfect</comment>
- <comment xml:lang="ro">Imagine WordPerfect/Drawperfect</comment>
- <comment xml:lang="ru">Изображение WordPerfect/Drawperfect</comment>
- <comment xml:lang="sk">Obrázok WordPerfect/Drawperfect</comment>
- <comment xml:lang="sl">Slikovna datoteka Drawperfect</comment>
- <comment xml:lang="sq">Figurë WordPerfect/Drawperfect</comment>
- <comment xml:lang="sr">Ворд Перфект/Дров Перфект слика</comment>
- <comment xml:lang="sv">WordPerfect/Drawperfect-bild</comment>
- <comment xml:lang="tr">WordPerfect/DrawPerfect görüntüsü</comment>
- <comment xml:lang="uk">зображення WordPerfect/Drawperfect</comment>
- <comment xml:lang="vi">Ảnh WordPerfect/Drawperfect</comment>
- <comment xml:lang="zh_CN">WordPerfect/Drawperfect 图像</comment>
<comment xml:lang="zh_TW">WordPerfect/Drawperfect 影像</comment>
+ <comment xml:lang="zh_CN">WordPerfect/Drawperfect 图像</comment>
+ <comment xml:lang="vi">Ảnh WordPerfect/Drawperfect</comment>
+ <comment xml:lang="uk">зображення WordPerfect/Drawperfect</comment>
+ <comment xml:lang="tr">WordPerfect/DrawPerfect görüntüsü</comment>
+ <comment xml:lang="sv">WordPerfect/Drawperfect-bild</comment>
+ <comment xml:lang="sr">Ворд Перфект/Дров Перфект слика</comment>
+ <comment xml:lang="sq">figurë WordPerfect/Drawperfect</comment>
+ <comment xml:lang="sl">Slikovna datoteka Drawperfect</comment>
+ <comment xml:lang="si">WordPerfect/Drawperfect රූපය</comment>
+ <comment xml:lang="sk">Obrázok WordPerfect/Drawperfect</comment>
+ <comment xml:lang="ru">Изображение WordPerfect/Drawperfect</comment>
+ <comment xml:lang="ro">Imagine WordPerfect/Drawperfect</comment>
+ <comment xml:lang="pt_BR">Imagem do WordPerfect/Drawperfect</comment>
+ <comment xml:lang="pt">imagem do WordPerfect/Drawperfect</comment>
+ <comment xml:lang="pl">Obraz WordPerfect/DrawPerfect</comment>
+ <comment xml:lang="oc">imatge WordPerfect/DrawPerfect</comment>
+ <comment xml:lang="nn">WordPerfect/DrawPerfect-bilete</comment>
+ <comment xml:lang="nl">WordPerfect/Drawperfect-afbeelding</comment>
+ <comment xml:lang="nb">WordPerfect-/Drawperfect-bilde</comment>
+ <comment xml:lang="ms">Imej WordPerfect/Drawperfect</comment>
+ <comment xml:lang="lv">WordPerfect/Drawperfect attēls</comment>
+ <comment xml:lang="lt">WordPerfect/Drawperfect paveikslėlis</comment>
+ <comment xml:lang="ko">WordPerfect/Drawperfect 그림</comment>
+ <comment xml:lang="kk">WordPerfect/Drawperfect суреті</comment>
+ <comment xml:lang="ja">WordPerfect/Drawperfect 画像</comment>
+ <comment xml:lang="it">Immagine WordPerfect/Drawperfect</comment>
+ <comment xml:lang="is">WordPerfect/Drawperfect mynd</comment>
+ <comment xml:lang="id">Gambar WordPerfect/Drawperfect</comment>
+ <comment xml:lang="ia">Imagine WordPerfect/DrawPerfect</comment>
+ <comment xml:lang="hu">WordPerfect/Drawperfect-kép</comment>
+ <comment xml:lang="hr">WordPerfect/Drawperfect slika</comment>
+ <comment xml:lang="he">תמונה של WordPerfect/Drawperfect</comment>
+ <comment xml:lang="gl">imaxe de WordPerfect/DrawPerfect</comment>
+ <comment xml:lang="ga">íomhá WordPerfect/Drawperfect</comment>
+ <comment xml:lang="fur">imagjin WordPerfect/Drawperfect</comment>
+ <comment xml:lang="fr">image WordPerfect/DrawPerfect</comment>
+ <comment xml:lang="fo">WordPerfect/Drawperfect mynd</comment>
+ <comment xml:lang="fi">WordPerfect/Drawperfect-kuva</comment>
+ <comment xml:lang="eu">WordPerfect/Drawperfect irudia</comment>
+ <comment xml:lang="es">imagen de WordPerfect/Drawperfect</comment>
+ <comment xml:lang="eo">WordPerfect/Drawperfect-bildo</comment>
+ <comment xml:lang="en_GB">WordPerfect/Drawperfect image</comment>
+ <comment xml:lang="el">Εικόνα WordPerfect/Drawperfect</comment>
+ <comment xml:lang="de">WordPerfect/DrawPerfect-Bild</comment>
+ <comment xml:lang="da">WordPerfect/Drawperfect-billede</comment>
+ <comment xml:lang="cs">obrázek WordPerfect/Drawperfect</comment>
+ <comment xml:lang="ca">imatge de WordPerfect/Drawperfect</comment>
+ <comment xml:lang="bg">Изображение — WordPerfect/Drawperfect</comment>
+ <comment xml:lang="be@latin">Vyjava WordPerfect/Drawperfect</comment>
+ <comment xml:lang="be">выява WordPerfect/Drawperfect</comment>
+ <comment xml:lang="ar">صورة WordPerfect/Drawperfect</comment>
+ <comment xml:lang="af">WordPerfect/Drawperfect-beeld</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.wpg"/>
</mime-type>
<mime-type type="application/x-wonderswan-rom">
<comment>Bandai WonderSwan ROM</comment>
- <comment xml:lang="ca">ROM de Bandai WonderSwan</comment>
- <comment xml:lang="cs">ROM pro Bandai WonderSwan</comment>
- <comment xml:lang="de">Bandai WonderSwan ROM</comment>
- <comment xml:lang="en_GB">Bandai WonderSwan ROM</comment>
- <comment xml:lang="es">ROM de Bandai WonderSwan</comment>
- <comment xml:lang="hr">Bandai WonderSwan ROM</comment>
- <comment xml:lang="hu">Bandai WonderSwan ROM</comment>
- <comment xml:lang="id">ROM Bandai WonderSwan</comment>
- <comment xml:lang="it">ROM Bandai WonderSwan</comment>
- <comment xml:lang="kk">Bandai WonderSwan ROM</comment>
- <comment xml:lang="ko">반다이 원더스완 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Bandai WonderSwan</comment>
- <comment xml:lang="pt_BR">ROM de WonderSwan da Bandai</comment>
- <comment xml:lang="ru">Bandai WonderSwan ROM</comment>
- <comment xml:lang="sk">ROM pre Bandai WonderSwan</comment>
- <comment xml:lang="sv">Bandai WonderSwan-rom</comment>
- <comment xml:lang="uk">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="zh_TW">萬代 WonderSwan ROM</comment>
<comment xml:lang="zh_CN">万代 WonderSwan ROM</comment>
- <comment xml:lang="zh_TW">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="uk">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="tr">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="sv">Bandai WonderSwan-rom</comment>
+ <comment xml:lang="sq">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="si">බන්ඩායි WonderSwan ROM</comment>
+ <comment xml:lang="sk">ROM pre Bandai WonderSwan</comment>
+ <comment xml:lang="ru">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="pt_BR">ROM de WonderSwan da Bandai</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Bandai WonderSwan</comment>
+ <comment xml:lang="nl">Bandai WonderSwan-ROM</comment>
+ <comment xml:lang="ko">반다이 원더스완 롬</comment>
+ <comment xml:lang="kk">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="ja">バンダイワンダースワン ROM</comment>
+ <comment xml:lang="it">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="is">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="id">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="hu">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="hr">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="he">ROM של Bandai WonderSwan</comment>
+ <comment xml:lang="ga">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="fur">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="fr">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="fi">Bandai WonderSwan -ROM</comment>
+ <comment xml:lang="eu">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="es">ROM de Bandai WonderSwan</comment>
+ <comment xml:lang="en_GB">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="de">Bandai-WonderSwan-ROM</comment>
+ <comment xml:lang="da">Bandai WonderSwan-ROM</comment>
+ <comment xml:lang="cs">ROM pro Bandai WonderSwan</comment>
+ <comment xml:lang="ca">ROM de Bandai WonderSwan</comment>
+ <comment xml:lang="bg">ROM — Bandai WonderSwan</comment>
+ <comment xml:lang="be">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="ar">روم Bandai WonderSwan</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.ws"/>
</mime-type>
<mime-type type="application/x-wonderswan-color-rom">
<comment>Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="ca">ROM de Bandai WonderSwan Color</comment>
- <comment xml:lang="cs">ROM pro Bandai WonderSwan Color</comment>
- <comment xml:lang="de">Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="en_GB">Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="es">ROM de Bandai WonderSwan Color</comment>
- <comment xml:lang="hr">Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="hu">Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="id">ROM Bandai WonderSwan Color</comment>
- <comment xml:lang="it">ROM Bandai WonderSwan Color</comment>
- <comment xml:lang="kk">Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="ko">반다이 원더스완 컬러 롬</comment>
- <comment xml:lang="pl">Plik ROM konsoli Bandai WonderSwan Color</comment>
- <comment xml:lang="pt_BR">ROM de WonderSwan Color da Bandai</comment>
- <comment xml:lang="ru">Bandai WonderSwan Color ROM</comment>
- <comment xml:lang="sk">ROM pre Bandai WonderSwan Color</comment>
- <comment xml:lang="sv">Bandai WonderSwan Color-rom</comment>
- <comment xml:lang="uk">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="zh_TW">萬代 WonderSwan Color ROM</comment>
<comment xml:lang="zh_CN">万代 WonderSwan Color ROM</comment>
- <comment xml:lang="zh_TW">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="uk">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="tr">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="sv">Bandai WonderSwan Color-rom</comment>
+ <comment xml:lang="sq">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="si">Bandai WonderSwan වර්ණ ROM</comment>
+ <comment xml:lang="sk">ROM pre Bandai WonderSwan Color</comment>
+ <comment xml:lang="ru">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="pt_BR">ROM de WonderSwan Color da Bandai</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Bandai WonderSwan Color</comment>
+ <comment xml:lang="nl">Bandai WonderSwan Color-ROM</comment>
+ <comment xml:lang="ko">반다이 원더스완 컬러 롬</comment>
+ <comment xml:lang="kk">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="ja">バンダイワンダースワンカラー ROM</comment>
+ <comment xml:lang="it">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="is">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="id">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="hu">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="hr">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="he">ROM של Bandai WonderSwan Color</comment>
+ <comment xml:lang="ga">ROM datha Bandai WonderSwan</comment>
+ <comment xml:lang="fur">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="fr">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="fi">Bandai WonderSwan Color -ROM</comment>
+ <comment xml:lang="eu">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="es">ROM de Bandai WonderSwan Color</comment>
+ <comment xml:lang="en_GB">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="de">Bandai-WonderSwan-Color-ROM</comment>
+ <comment xml:lang="da">Bandai WonderSwan Color-ROM</comment>
+ <comment xml:lang="cs">ROM pro Bandai WonderSwan Color</comment>
+ <comment xml:lang="ca">ROM de Bandai WonderSwan Color</comment>
+ <comment xml:lang="bg">ROM — Bandai WonderSwan Color</comment>
+ <comment xml:lang="be">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="ar">روم لون Bandai WonderSwan</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.wsc"/>
</mime-type>
<mime-type type="application/x-x509-ca-cert">
<comment>DER/PEM/Netscape-encoded X.509 certificate</comment>
- <comment xml:lang="ar">شهادة DER/PEM/Netscape-encoded X.509</comment>
- <comment xml:lang="be@latin">Sertyfikat X.509, zakadavany ŭ DER/PEM/Netscape</comment>
- <comment xml:lang="bg">Сертификат — DER/PEM/Netscape X.509</comment>
- <comment xml:lang="ca">certificat X.509 codificat com DER/PEM/Netscape</comment>
- <comment xml:lang="cs">certifikát X.509 kódovaný jako DER/PEM/Netscape</comment>
- <comment xml:lang="da">DER-/PEM-/Netscapekodet X.509-certifikat</comment>
- <comment xml:lang="de">DER/PEM/Netscape-kodiertes X.509-Zertifikat</comment>
- <comment xml:lang="el">Ψηφιακό πιστοποιητικό X.509 κωδικοποιημένο κατά DER/PEM/Netscape</comment>
- <comment xml:lang="en_GB">DER/PEM/Netscape-encoded X.509 certificate</comment>
- <comment xml:lang="eo">DER/PEM/Netscape-kodigita X.509-atestilo</comment>
- <comment xml:lang="es">certificado X.509 codificado con DER/PEM/Netscape</comment>
- <comment xml:lang="eu">X.509rekin kodetutako DER, PEM edo Netscape zertifikatua</comment>
- <comment xml:lang="fi">DER/PEM/Netscape-koodattu X.509-varmenne</comment>
- <comment xml:lang="fo">DER/PEM/Netscape-encoded X.509 váttan</comment>
- <comment xml:lang="fr">certificat X.509 codé DER/PEM/Netscape</comment>
- <comment xml:lang="ga">teastas X.509 ionchódaithe le DER/PEM/Netscape</comment>
- <comment xml:lang="gl">certificado X.509 codificado con DER/PEM/Netscape</comment>
- <comment xml:lang="he">אישור מסוג X.509 של DER/PEM/Netscape-encoded</comment>
- <comment xml:lang="hr">DER/PEM/Netscape-kodiran X.509 vjerodajnica</comment>
- <comment xml:lang="hu">DER/PEM/Netscape formátumú X.509-tanúsítvány</comment>
- <comment xml:lang="ia">Certificato X.509 codificate in DER/PEM/Netscape</comment>
- <comment xml:lang="id">Sertifikat DER/PEM/Netscape-tersandi X.509</comment>
- <comment xml:lang="it">Certificato X.509 DER/PEM/Netscape</comment>
- <comment xml:lang="ja">DER/PEM/Netscape エンコード X.509 証明書</comment>
- <comment xml:lang="ka">DER/PEM/Netscape კოდირებული X.509 სერტიფიკატი</comment>
- <comment xml:lang="kk">X.509 сертификаты (DER/PEM/Netscape кодталған)</comment>
- <comment xml:lang="ko">DER/PEM/넷스케이프로 인코딩된 X.509 인증서</comment>
- <comment xml:lang="lt">DER/PEM/Netscape-encoded X.509 liudijimas</comment>
- <comment xml:lang="lv">DER/PEM/Netscape-encoded X.509 sertifikāts</comment>
- <comment xml:lang="ms">Sijil X.509 dienkod /DER/PEM/Netscape</comment>
- <comment xml:lang="nb">DER/PEM/Netscape-kodet X.509-sertifikat</comment>
- <comment xml:lang="nl">DER/PEM/Netscape-gecodeerd X.509-certificaat</comment>
- <comment xml:lang="nn">DER/PEM/Netscape-koda X.509-sertifikat</comment>
- <comment xml:lang="oc">certificat X.509 encodat DER/PEM/Netscape</comment>
- <comment xml:lang="pl">Zakodowany w DER/PEM/Netscape certyfikat X.509</comment>
- <comment xml:lang="pt">certificado X.509 codificado com DER/PEM/Netscape</comment>
- <comment xml:lang="pt_BR">Certificado X.509 codificado com DER/PEM/Netscape</comment>
- <comment xml:lang="ro">Certificat DER/PEM/Netscape-codat X.509</comment>
- <comment xml:lang="ru">Сертификат X.509 (DER/PEM/Netscape-закодированный)</comment>
- <comment xml:lang="sk">Certifikát X.509 kódovaný ako DER/PEM/Netscape</comment>
- <comment xml:lang="sl">Datoteka potrdila DER/PEM/Netscape X.509</comment>
- <comment xml:lang="sq">Çertifikatë DER/PEM/Netscape-encoded X.509</comment>
- <comment xml:lang="sr">ДЕР/ПЕМ/Нетскејп кодирано уверење Икс.509</comment>
- <comment xml:lang="sv">DER/PEM/Netscape-kodat X.509-certifikat</comment>
- <comment xml:lang="tr">DER/PEM/Netscape-kodlanmış X.509 sertfikası</comment>
- <comment xml:lang="uk">сертифікат X.509 у форматі DER/PEM/Netscape</comment>
- <comment xml:lang="vi">Chứng nhận X.509 mã hoá bằng Netscape/PEM/DER</comment>
- <comment xml:lang="zh_CN">DER/PEM/Netscape-encoded X.509 证书</comment>
<comment xml:lang="zh_TW">DER/PEM/Netscape 編碼的 X.509 憑證</comment>
+ <comment xml:lang="zh_CN">DER/PEM/Netscape-encoded X.509 证书</comment>
+ <comment xml:lang="vi">Chứng nhận X.509 mã hoá bằng Netscape/PEM/DER</comment>
+ <comment xml:lang="uk">сертифікат X.509 у форматі DER/PEM/Netscape</comment>
+ <comment xml:lang="tr">DER/PEM/Netscape-kodlanmış X.509 sertfikası</comment>
+ <comment xml:lang="sv">DER/PEM/Netscape-kodat X.509-certifikat</comment>
+ <comment xml:lang="sr">ДЕР/ПЕМ/Нетскејп кодирано уверење Икс.509</comment>
+ <comment xml:lang="sq">dëshmi X.509 koduar për DER/PEM/Netscape</comment>
+ <comment xml:lang="sl">Datoteka potrdila DER/PEM/Netscape X.509</comment>
+ <comment xml:lang="si">DER/PEM/Netscape-කේතනය කළ X.509 සහතිකය</comment>
+ <comment xml:lang="sk">Certifikát X.509 kódovaný ako DER/PEM/Netscape</comment>
+ <comment xml:lang="ru">Сертификат X.509 в формате DER/PEM/Netscape</comment>
+ <comment xml:lang="ro">Certificat DER/PEM/Netscape-codat X.509</comment>
+ <comment xml:lang="pt_BR">Certificado X.509 codificado com DER/PEM/Netscape</comment>
+ <comment xml:lang="pt">certificado X.509 codificado com DER/PEM/Netscape</comment>
+ <comment xml:lang="pl">Zakodowany w DER/PEM/Netscape certyfikat X.509</comment>
+ <comment xml:lang="oc">certificat X.509 encodat DER/PEM/Netscape</comment>
+ <comment xml:lang="nn">DER/PEM/Netscape-koda X.509-sertifikat</comment>
+ <comment xml:lang="nl">DER/PEM/Netscape-gecodeerd X.509-certificaat</comment>
+ <comment xml:lang="nb">DER/PEM/Netscape-kodet X.509-sertifikat</comment>
+ <comment xml:lang="ms">Sijil X.509 dienkod /DER/PEM/Netscape</comment>
+ <comment xml:lang="lv">DER/PEM/Netscape-encoded X.509 sertifikāts</comment>
+ <comment xml:lang="lt">DER/PEM/Netscape-encoded X.509 liudijimas</comment>
+ <comment xml:lang="ko">DER/PEM/넷스케이프로 인코딩된 X.509 인증서</comment>
+ <comment xml:lang="kk">X.509 сертификаты (DER/PEM/Netscape кодталған)</comment>
+ <comment xml:lang="ka">DER/PEM/Netscape კოდირებული X.509 სერტიფიკატი</comment>
+ <comment xml:lang="ja">DER/PEM/Netscape エンコード X.509 証明書</comment>
+ <comment xml:lang="it">Certificato X.509 DER/PEM/Netscape</comment>
+ <comment xml:lang="is">DER/PEM/Netscape-kóðað X.509 skilríki</comment>
+ <comment xml:lang="id">Sertifikat DER/PEM/Netscape-tersandi X.509</comment>
+ <comment xml:lang="ia">Certificato X.509 codificate in DER/PEM/Netscape</comment>
+ <comment xml:lang="hu">DER/PEM/Netscape formátumú X.509-tanúsítvány</comment>
+ <comment xml:lang="hr">DER/PEM/Netscape-kodiran X.509 vjerodajnica</comment>
+ <comment xml:lang="he">אישור מסוג X.509 של DER/PEM/Netscape-encoded</comment>
+ <comment xml:lang="gl">certificado X.509 codificado con DER/PEM/Netscape</comment>
+ <comment xml:lang="ga">teastas X.509 ionchódaithe le DER/PEM/Netscape</comment>
+ <comment xml:lang="fur">certificât X.509 codificât cun DER/PEM/Netscape</comment>
+ <comment xml:lang="fr">certificat X.509 codé DER/PEM/Netscape</comment>
+ <comment xml:lang="fo">DER/PEM/Netscape-encoded X.509 váttan</comment>
+ <comment xml:lang="fi">DER/PEM/Netscape-koodattu X.509-varmenne</comment>
+ <comment xml:lang="eu">X.509rekin kodetutako DER, PEM edo Netscape zertifikatua</comment>
+ <comment xml:lang="es">certificado X.509 codificado con DER/PEM/Netscape</comment>
+ <comment xml:lang="eo">DER/PEM/Netscape-kodigita X.509-atestilo</comment>
+ <comment xml:lang="en_GB">DER/PEM/Netscape-encoded X.509 certificate</comment>
+ <comment xml:lang="el">Ψηφιακό πιστοποιητικό X.509 κωδικοποιημένο κατά DER/PEM/Netscape</comment>
+ <comment xml:lang="de">DER/PEM/Netscape-verschlüsseltes X.509-Zertifikat</comment>
+ <comment xml:lang="da">DER-/PEM-/Netscape-kodet X.509-certifikat</comment>
+ <comment xml:lang="cs">certifikát X.509 kódovaný jako DER/PEM/Netscape</comment>
+ <comment xml:lang="ca">certificat X.509 codificat com DER/PEM/Netscape</comment>
+ <comment xml:lang="bg">Сертификат — DER/PEM/Netscape X.509</comment>
+ <comment xml:lang="be@latin">Sertyfikat X.509, zakadavany ŭ DER/PEM/Netscape</comment>
+ <comment xml:lang="be">сертыфікат X.509, закадаваны праз DER/PEM/Netscape</comment>
+ <comment xml:lang="ar">شهادة DER/PEM/Netscape-encoded X.509</comment>
+ <comment xml:lang="af">DER/PEM/Netscape-geënkodeerde X.509-sertifikaat</comment>
<generic-icon name="text-x-generic"/>
+ <magic>
+ <match type="string" value="-----BEGIN CA CERTIFICATE-----" offset="0"/>
+ <match type="string" value="-----BEGIN TRUSTED CERTIFICATE-----" offset="0"/>
+ </magic>
<glob pattern="*.der"/>
<glob pattern="*.crt"/>
<glob pattern="*.cert"/>
<glob pattern="*.pem"/>
</mime-type>
<mime-type type="application/x-zerosize">
- <comment>empty document</comment>
- <comment xml:lang="ar">مستند فارغ</comment>
- <comment xml:lang="ast">documentu baleru</comment>
- <comment xml:lang="be@latin">pusty dakument</comment>
- <comment xml:lang="bg">Празен документ</comment>
- <comment xml:lang="ca">document buit</comment>
- <comment xml:lang="cs">prázdný dokument</comment>
- <comment xml:lang="da">tomt dokument</comment>
- <comment xml:lang="de">Leeres Dokument</comment>
- <comment xml:lang="el">Κενό έγγραφο</comment>
- <comment xml:lang="en_GB">empty document</comment>
- <comment xml:lang="eo">malplena dokumento</comment>
- <comment xml:lang="es">documento vacío</comment>
- <comment xml:lang="eu">dokumentu hutsa</comment>
- <comment xml:lang="fi">tyhjä asiakirja</comment>
- <comment xml:lang="fo">tómt skjal</comment>
- <comment xml:lang="fr">document vide</comment>
- <comment xml:lang="ga">cáipéis fholamh</comment>
- <comment xml:lang="gl">documeto baleiro</comment>
- <comment xml:lang="he">מסמך ריק</comment>
- <comment xml:lang="hr">Prazan dokument</comment>
- <comment xml:lang="hu">üres dokumentum</comment>
- <comment xml:lang="ia">Documento vacue</comment>
- <comment xml:lang="id">dokumen kosong</comment>
- <comment xml:lang="it">Documento vuoto</comment>
- <comment xml:lang="ja">空のドキュメント</comment>
- <comment xml:lang="kk">бос құжат</comment>
- <comment xml:lang="ko">빈 문서</comment>
- <comment xml:lang="lt">tuščias dokumentas</comment>
- <comment xml:lang="lv">tukšs dokuments</comment>
- <comment xml:lang="ms">Dokumen kosong</comment>
- <comment xml:lang="nb">tomt dokument</comment>
- <comment xml:lang="nl">leeg document</comment>
- <comment xml:lang="nn">tomt dokument</comment>
- <comment xml:lang="oc">document void</comment>
- <comment xml:lang="pl">Pusty dokument</comment>
- <comment xml:lang="pt">documento vazio</comment>
- <comment xml:lang="pt_BR">Documento vazio</comment>
- <comment xml:lang="ro">document gol</comment>
- <comment xml:lang="ru">Пустой документ</comment>
- <comment xml:lang="sk">Prázdny dokument</comment>
- <comment xml:lang="sl">prazen dokument</comment>
- <comment xml:lang="sq">Dokument bosh</comment>
- <comment xml:lang="sr">празан документ</comment>
- <comment xml:lang="sv">tomt dokument</comment>
- <comment xml:lang="tr">boş belge</comment>
+ <comment>Empty document</comment>
<comment xml:lang="uk">порожній документ</comment>
- <comment xml:lang="vi">tài liệu rỗng</comment>
- <comment xml:lang="zh_CN">空文档</comment>
- <comment xml:lang="zh_TW">空白文件</comment>
+ <comment xml:lang="sv">Tomt dokument</comment>
+ <comment xml:lang="ru">Пустой документ</comment>
+ <comment xml:lang="pt_BR">Documento em branco</comment>
+ <comment xml:lang="pl">Pusty dokument</comment>
+ <comment xml:lang="ja">空の文書</comment>
+ <comment xml:lang="it">Documento vuoto</comment>
+ <comment xml:lang="eu">Dokumentu hutsa</comment>
+ <comment xml:lang="es">documento vacío</comment>
+ <comment xml:lang="de">Leeres Dokument</comment>
+ <comment xml:lang="be">пусты дакумент</comment>
</mime-type>
<mime-type type="application/x-zoo">
<comment>Zoo archive</comment>
- <comment xml:lang="ar">أرشيف Zoo</comment>
- <comment xml:lang="az">Zoo arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ zoo</comment>
- <comment xml:lang="bg">Архив — zoo</comment>
- <comment xml:lang="ca">arxiu zoo</comment>
- <comment xml:lang="cs">archiv Zoo</comment>
- <comment xml:lang="cy">Archif zoo</comment>
- <comment xml:lang="da">Zooarkiv</comment>
- <comment xml:lang="de">Zoo-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Zoo</comment>
- <comment xml:lang="en_GB">Zoo archive</comment>
- <comment xml:lang="eo">Zoo-arkivo</comment>
- <comment xml:lang="es">archivador Zoo</comment>
- <comment xml:lang="eu">Zoo artxiboa</comment>
- <comment xml:lang="fi">Zoo-arkisto</comment>
- <comment xml:lang="fo">Zoo skjalasavn</comment>
- <comment xml:lang="fr">archive zoo</comment>
- <comment xml:lang="ga">cartlann Zoo</comment>
- <comment xml:lang="gl">ficheiro Zoo</comment>
- <comment xml:lang="he">ארכיון Zoo</comment>
- <comment xml:lang="hr">Zoo arhiva</comment>
- <comment xml:lang="hu">Zoo archívum</comment>
- <comment xml:lang="ia">Archivo Zoo</comment>
- <comment xml:lang="id">Arsip Zoo</comment>
- <comment xml:lang="it">Archivio zoo</comment>
- <comment xml:lang="ja">Zoo アーカイブ</comment>
- <comment xml:lang="kk">Zoo архиві</comment>
- <comment xml:lang="ko">ZOO 압축 파일</comment>
- <comment xml:lang="lt">Zoo archyvas</comment>
- <comment xml:lang="lv">Zoo arhīvs</comment>
- <comment xml:lang="nb">Zoo-arkiv</comment>
- <comment xml:lang="nl">Zoo-archief</comment>
- <comment xml:lang="nn">Zoo-arkiv</comment>
- <comment xml:lang="oc">archiu zoo</comment>
- <comment xml:lang="pl">Archiwum zoo</comment>
- <comment xml:lang="pt">arquivo Zoo</comment>
- <comment xml:lang="pt_BR">Pacote Zoo</comment>
- <comment xml:lang="ro">Arhivă Zoo</comment>
- <comment xml:lang="ru">Архив ZOO</comment>
- <comment xml:lang="sk">Archív zoo</comment>
- <comment xml:lang="sl">Datoteka arhiva ZOO</comment>
- <comment xml:lang="sq">Arkiv zoo</comment>
- <comment xml:lang="sr">Зoo архива</comment>
- <comment xml:lang="sv">Zoo-arkiv</comment>
- <comment xml:lang="tr">Zoo arşivi</comment>
- <comment xml:lang="uk">архів zoo</comment>
- <comment xml:lang="vi">Kho nén zoo</comment>
- <comment xml:lang="zh_CN">Zoo 归档文件</comment>
<comment xml:lang="zh_TW">Zoo 封存檔</comment>
+ <comment xml:lang="zh_CN">Zoo 归档文件</comment>
+ <comment xml:lang="vi">Kho nén zoo</comment>
+ <comment xml:lang="uk">архів zoo</comment>
+ <comment xml:lang="tr">Zoo arşivi</comment>
+ <comment xml:lang="sv">Zoo-arkiv</comment>
+ <comment xml:lang="sr">Зoo архива</comment>
+ <comment xml:lang="sq">arkiv zoo</comment>
+ <comment xml:lang="sl">Datoteka arhiva ZOO</comment>
+ <comment xml:lang="si">සත්වෝද්යාන ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív Zoo</comment>
+ <comment xml:lang="ru">Архив ZOO</comment>
+ <comment xml:lang="ro">Arhivă Zoo</comment>
+ <comment xml:lang="pt_BR">Pacote Zoo</comment>
+ <comment xml:lang="pt">arquivo Zoo</comment>
+ <comment xml:lang="pl">Archiwum zoo</comment>
+ <comment xml:lang="oc">archiu zoo</comment>
+ <comment xml:lang="nn">Zoo-arkiv</comment>
+ <comment xml:lang="nl">Zoo-archief</comment>
+ <comment xml:lang="nb">Zoo-arkiv</comment>
+ <comment xml:lang="lv">Zoo arhīvs</comment>
+ <comment xml:lang="lt">Zoo archyvas</comment>
+ <comment xml:lang="ko">ZOO 압축 파일</comment>
+ <comment xml:lang="kk">Zoo архиві</comment>
+ <comment xml:lang="ja">Zoo アーカイブ</comment>
+ <comment xml:lang="it">Archivio zoo</comment>
+ <comment xml:lang="is">Zoo safnskrá</comment>
+ <comment xml:lang="id">Arsip Zoo</comment>
+ <comment xml:lang="ia">Archivo Zoo</comment>
+ <comment xml:lang="hu">Zoo archívum</comment>
+ <comment xml:lang="hr">Zoo arhiva</comment>
+ <comment xml:lang="he">ארכיון Zoo</comment>
+ <comment xml:lang="gl">ficheiro Zoo</comment>
+ <comment xml:lang="ga">cartlann Zoo</comment>
+ <comment xml:lang="fur">archivi Zoo</comment>
+ <comment xml:lang="fr">archive zoo</comment>
+ <comment xml:lang="fo">Zoo skjalasavn</comment>
+ <comment xml:lang="fi">Zoo-arkisto</comment>
+ <comment xml:lang="eu">Zoo artxiboa</comment>
+ <comment xml:lang="es">archivador Zoo</comment>
+ <comment xml:lang="eo">Zoo-arkivo</comment>
+ <comment xml:lang="en_GB">Zoo archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Zoo</comment>
+ <comment xml:lang="de">Zoo-Archiv</comment>
+ <comment xml:lang="da">Zoo-arkiv</comment>
+ <comment xml:lang="cy">Archif zoo</comment>
+ <comment xml:lang="cs">archiv Zoo</comment>
+ <comment xml:lang="ca">arxiu zoo</comment>
+ <comment xml:lang="bg">Архив — zoo</comment>
+ <comment xml:lang="be@latin">Archiŭ zoo</comment>
+ <comment xml:lang="be">архіў zoo</comment>
+ <comment xml:lang="az">Zoo arxivi</comment>
+ <comment xml:lang="ar">أرشيف Zoo</comment>
+ <comment xml:lang="af">Zoo-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="0xfdc4a7dc" type="little32" offset="20"/>
+ <match type="little32" value="0xfdc4a7dc" offset="20"/>
</magic>
<glob pattern="*.zoo"/>
</mime-type>
<mime-type type="application/xhtml+xml">
<comment>XHTML page</comment>
- <comment xml:lang="ar">صفحة XHTML</comment>
- <comment xml:lang="be@latin">Staronka XHTML</comment>
- <comment xml:lang="bg">Страница — XHTML</comment>
- <comment xml:lang="ca">pàgina XHTML</comment>
- <comment xml:lang="cs">stránka XHTML</comment>
- <comment xml:lang="da">XHTML-side</comment>
- <comment xml:lang="de">XHTML-Seite</comment>
- <comment xml:lang="el">Σελίδα XHTML</comment>
- <comment xml:lang="en_GB">XHTML page</comment>
- <comment xml:lang="eo">XHTML-paĝo</comment>
- <comment xml:lang="es">página XHTML</comment>
- <comment xml:lang="eu">XHTML orria</comment>
- <comment xml:lang="fi">XHTML-sivu</comment>
- <comment xml:lang="fo">XHTML síða</comment>
- <comment xml:lang="fr">page XHTML</comment>
- <comment xml:lang="ga">leathanach XHTML</comment>
- <comment xml:lang="gl">Páxina XHTML</comment>
- <comment xml:lang="he">דף XHTML</comment>
- <comment xml:lang="hr">XHTML stranica</comment>
- <comment xml:lang="hu">XHTML-oldal</comment>
- <comment xml:lang="ia">Pagina XHTML</comment>
- <comment xml:lang="id">Halaman XHTML</comment>
- <comment xml:lang="it">Pagina XHTML</comment>
- <comment xml:lang="ja">XHTML ページ</comment>
- <comment xml:lang="kk">XHTML парағы</comment>
- <comment xml:lang="ko">XHTML 페이지</comment>
- <comment xml:lang="lt">XHTML puslapis</comment>
- <comment xml:lang="lv">XHTML lapa</comment>
- <comment xml:lang="ms">Laman XHTML</comment>
- <comment xml:lang="nb">XHTML-side</comment>
- <comment xml:lang="nl">XHTML-pagina</comment>
- <comment xml:lang="nn">XHTML-side</comment>
- <comment xml:lang="oc">pagina XHTML</comment>
- <comment xml:lang="pl">Strona XHTML</comment>
- <comment xml:lang="pt">página XHTML</comment>
- <comment xml:lang="pt_BR">Página XHTML</comment>
- <comment xml:lang="ro">Pagină XHTML</comment>
- <comment xml:lang="ru">Страница XHTML</comment>
- <comment xml:lang="sk">Stránka XHTML</comment>
- <comment xml:lang="sl">Datoteka spletne strani XHTML</comment>
- <comment xml:lang="sq">Faqe XHTML</comment>
- <comment xml:lang="sr">ИксХТМЛ страница</comment>
- <comment xml:lang="sv">XHTML-sida</comment>
- <comment xml:lang="tr">XHTML sayfası</comment>
- <comment xml:lang="uk">сторінка XHTML</comment>
- <comment xml:lang="vi">Trang XHTML</comment>
- <comment xml:lang="zh_CN">XHTML 页面</comment>
<comment xml:lang="zh_TW">XHTML 網頁</comment>
+ <comment xml:lang="zh_CN">XHTML 页面</comment>
+ <comment xml:lang="vi">Trang XHTML</comment>
+ <comment xml:lang="uk">сторінка XHTML</comment>
+ <comment xml:lang="tr">XHTML sayfası</comment>
+ <comment xml:lang="sv">XHTML-sida</comment>
+ <comment xml:lang="sr">ИксХТМЛ страница</comment>
+ <comment xml:lang="sq">faqe XHTML</comment>
+ <comment xml:lang="sl">Datoteka spletne strani XHTML</comment>
+ <comment xml:lang="si">XHTML පිටුව</comment>
+ <comment xml:lang="sk">Stránka XHTML</comment>
+ <comment xml:lang="ru">Страница XHTML</comment>
+ <comment xml:lang="ro">Pagină XHTML</comment>
+ <comment xml:lang="pt_BR">Página XHTML</comment>
+ <comment xml:lang="pt">página XHTML</comment>
+ <comment xml:lang="pl">Strona XHTML</comment>
+ <comment xml:lang="oc">pagina XHTML</comment>
+ <comment xml:lang="nn">XHTML-side</comment>
+ <comment xml:lang="nl">XHTML-pagina</comment>
+ <comment xml:lang="nb">XHTML-side</comment>
+ <comment xml:lang="ms">Laman XHTML</comment>
+ <comment xml:lang="lv">XHTML lapa</comment>
+ <comment xml:lang="lt">XHTML puslapis</comment>
+ <comment xml:lang="ko">XHTML 페이지</comment>
+ <comment xml:lang="kk">XHTML парағы</comment>
+ <comment xml:lang="ja">XHTML ページ</comment>
+ <comment xml:lang="it">Pagina XHTML</comment>
+ <comment xml:lang="is">XHTML síða</comment>
+ <comment xml:lang="id">Halaman XHTML</comment>
+ <comment xml:lang="ia">Pagina XHTML</comment>
+ <comment xml:lang="hu">XHTML-oldal</comment>
+ <comment xml:lang="hr">XHTML stranica</comment>
+ <comment xml:lang="he">דף XHTML</comment>
+ <comment xml:lang="gl">Páxina XHTML</comment>
+ <comment xml:lang="ga">leathanach XHTML</comment>
+ <comment xml:lang="fur">pagjine XHTML</comment>
+ <comment xml:lang="fr">page XHTML</comment>
+ <comment xml:lang="fo">XHTML síða</comment>
+ <comment xml:lang="fi">XHTML-sivu</comment>
+ <comment xml:lang="eu">XHTML orria</comment>
+ <comment xml:lang="es">página XHTML</comment>
+ <comment xml:lang="eo">XHTML-paĝo</comment>
+ <comment xml:lang="en_GB">XHTML page</comment>
+ <comment xml:lang="el">Σελίδα XHTML</comment>
+ <comment xml:lang="de">XHTML-Seite</comment>
+ <comment xml:lang="da">XHTML-side</comment>
+ <comment xml:lang="cs">stránka XHTML</comment>
+ <comment xml:lang="ca">pàgina XHTML</comment>
+ <comment xml:lang="bg">Страница — XHTML</comment>
+ <comment xml:lang="be@latin">Staronka XHTML</comment>
+ <comment xml:lang="be">старонка XHTML</comment>
+ <comment xml:lang="ar">صفحة XHTML</comment>
+ <comment xml:lang="af">XHTML-bladsy</comment>
<acronym>XHTML</acronym>
<expanded-acronym>Extensible HyperText Markup Language</expanded-acronym>
<sub-class-of type="application/xml"/>
<generic-icon name="text-html"/>
<glob pattern="*.xhtml"/>
<glob pattern="*.xht"/>
+ <glob pattern="*.html"/>
+ <glob pattern="*.htm"/>
<magic priority="60">
- <match value="//W3C//DTD XHTML " type="string" offset="0:256"/>
- <match value="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" type="string" offset="0:256"/>
- <match value="&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml" type="string" offset="0:256"/>
- <match value="&lt;HTML xmlns=&quot;http://www.w3.org/1999/xhtml" type="string" offset="0:256"/>
+ <match type="string" value="//W3C//DTD XHTML " offset="0:256"/>
+ <match type="string" value="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" offset="0:256"/>
+ <match type="string" value="&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml" offset="0:256"/>
+ <match type="string" value="&lt;HTML xmlns=&quot;http://www.w3.org/1999/xhtml" offset="0:256"/>
</magic>
- <root-XML namespaceURI='http://www.w3.org/1999/xhtml' localName='html'/>
+ <root-XML namespaceURI="http://www.w3.org/1999/xhtml" localName="html"/>
</mime-type>
<mime-type type="application/zip">
<comment>Zip archive</comment>
- <comment xml:lang="ar">أرشيف Zip</comment>
- <comment xml:lang="az">Zip arxivi</comment>
- <comment xml:lang="be@latin">Archiŭ zip</comment>
- <comment xml:lang="bg">Архив — zip</comment>
- <comment xml:lang="ca">arxiu zip</comment>
- <comment xml:lang="cs">archiv ZIP</comment>
- <comment xml:lang="cy">Archif ZIP</comment>
- <comment xml:lang="da">Ziparkiv</comment>
- <comment xml:lang="de">Zip-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο Zip</comment>
- <comment xml:lang="en_GB">Zip archive</comment>
- <comment xml:lang="eo">Zip-arkivo</comment>
- <comment xml:lang="es">archivador Zip</comment>
- <comment xml:lang="eu">Zip artxiboa</comment>
- <comment xml:lang="fi">Zip-arkisto</comment>
- <comment xml:lang="fo">Zip skjalasavn</comment>
- <comment xml:lang="fr">archive zip</comment>
- <comment xml:lang="ga">cartlann Zip</comment>
- <comment xml:lang="gl">ficheiro Zip</comment>
- <comment xml:lang="he">ארכיון Zip</comment>
- <comment xml:lang="hr">Zip arhiva</comment>
- <comment xml:lang="hu">Zip archívum</comment>
- <comment xml:lang="ia">Archivo Zip</comment>
- <comment xml:lang="id">Arsip Zip</comment>
- <comment xml:lang="it">Archivio zip</comment>
- <comment xml:lang="ja">Zip アーカイブ</comment>
- <comment xml:lang="kk">Zip архиві</comment>
- <comment xml:lang="ko">ZIP 압축 파일</comment>
- <comment xml:lang="lt">Zip archyvas</comment>
- <comment xml:lang="lv">Zip arhīvs</comment>
- <comment xml:lang="nb">Zip-arkiv</comment>
- <comment xml:lang="nl">Zip-archief</comment>
- <comment xml:lang="nn">Zip-arkiv</comment>
- <comment xml:lang="oc">archiu zip</comment>
- <comment xml:lang="pl">Archiwum ZIP</comment>
- <comment xml:lang="pt">arquivo Zip</comment>
- <comment xml:lang="pt_BR">Pacote Zip</comment>
- <comment xml:lang="ro">Arhivă zip</comment>
- <comment xml:lang="ru">Архив ZIP</comment>
- <comment xml:lang="sk">Archív ZIP</comment>
- <comment xml:lang="sl">Datoteka arhiva ZIP</comment>
- <comment xml:lang="sq">Arkiv zip</comment>
- <comment xml:lang="sr">Зип архива</comment>
- <comment xml:lang="sv">Zip-arkiv</comment>
- <comment xml:lang="tr">Zip arşivi</comment>
- <comment xml:lang="uk">архів zip</comment>
- <comment xml:lang="vi">Kho nén zip</comment>
- <comment xml:lang="zh_CN">Zip 归档文件</comment>
<comment xml:lang="zh_TW">Zip 封存檔</comment>
+ <comment xml:lang="zh_CN">Zip 归档文件</comment>
+ <comment xml:lang="vi">Kho nén zip</comment>
+ <comment xml:lang="uk">архів zip</comment>
+ <comment xml:lang="tr">Zip arşivi</comment>
+ <comment xml:lang="sv">Zip-arkiv</comment>
+ <comment xml:lang="sr">Зип архива</comment>
+ <comment xml:lang="sq">arkiv zip</comment>
+ <comment xml:lang="sl">Datoteka arhiva ZIP</comment>
+ <comment xml:lang="si">Zip සංරක්ෂිතය</comment>
+ <comment xml:lang="sk">Archív ZIP</comment>
+ <comment xml:lang="ru">Архив ZIP</comment>
+ <comment xml:lang="ro">Arhivă zip</comment>
+ <comment xml:lang="pt_BR">Pacote Zip</comment>
+ <comment xml:lang="pt">arquivo Zip</comment>
+ <comment xml:lang="pl">Archiwum ZIP</comment>
+ <comment xml:lang="oc">archiu zip</comment>
+ <comment xml:lang="nn">Zip-arkiv</comment>
+ <comment xml:lang="nl">Zip-archief</comment>
+ <comment xml:lang="nb">Zip-arkiv</comment>
+ <comment xml:lang="lv">Zip arhīvs</comment>
+ <comment xml:lang="lt">Zip archyvas</comment>
+ <comment xml:lang="ko">ZIP 압축 파일</comment>
+ <comment xml:lang="kk">Zip архиві</comment>
+ <comment xml:lang="ja">Zip アーカイブ</comment>
+ <comment xml:lang="it">Archivio zip</comment>
+ <comment xml:lang="is">Zip safnskrá</comment>
+ <comment xml:lang="id">Arsip Zip</comment>
+ <comment xml:lang="ia">Archivo Zip</comment>
+ <comment xml:lang="hu">Zip archívum</comment>
+ <comment xml:lang="hr">Zip arhiva</comment>
+ <comment xml:lang="he">ארכיון Zip</comment>
+ <comment xml:lang="gl">ficheiro Zip</comment>
+ <comment xml:lang="ga">cartlann Zip</comment>
+ <comment xml:lang="fur">archivi Zip</comment>
+ <comment xml:lang="fr">archive zip</comment>
+ <comment xml:lang="fo">Zip skjalasavn</comment>
+ <comment xml:lang="fi">Zip-arkisto</comment>
+ <comment xml:lang="eu">Zip artxiboa</comment>
+ <comment xml:lang="es">archivador Zip</comment>
+ <comment xml:lang="eo">Zip-arkivo</comment>
+ <comment xml:lang="en_GB">Zip archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο Zip</comment>
+ <comment xml:lang="de">Zip-Archiv</comment>
+ <comment xml:lang="da">Zip-arkiv</comment>
+ <comment xml:lang="cy">Archif ZIP</comment>
+ <comment xml:lang="cs">archiv ZIP</comment>
+ <comment xml:lang="ca">arxiu zip</comment>
+ <comment xml:lang="bg">Архив — zip</comment>
+ <comment xml:lang="be@latin">Archiŭ zip</comment>
+ <comment xml:lang="be">архіў zip</comment>
+ <comment xml:lang="az">Zip arxivi</comment>
+ <comment xml:lang="ar">أرشيف Zip</comment>
+ <comment xml:lang="af">Zip-argief</comment>
<alias type="application/x-zip-compressed"/>
<alias type="application/x-zip"/>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="PK\003\004" type="string" offset="0"/>
+ <match type="string" value="PK\003\004" offset="0"/>
</magic>
<glob pattern="*.zip"/>
+ <glob pattern="*.zipx"/>
</mime-type>
<mime-type type="application/x-ms-wim">
- <comment>WIM disk Image</comment>
- <comment xml:lang="ca">imatge de disc WIM</comment>
- <comment xml:lang="cs">obraz disku WIM</comment>
- <comment xml:lang="da">WIM-diskaftryk</comment>
- <comment xml:lang="de">WIM-Datenträgerabbild</comment>
- <comment xml:lang="el">Εικόνα δίσκου WIM</comment>
- <comment xml:lang="en_GB">WIM disk Image</comment>
- <comment xml:lang="es">imagen de disco WIM</comment>
- <comment xml:lang="eu">WIM disko irudia</comment>
- <comment xml:lang="fi">WIM-levytiedosto</comment>
- <comment xml:lang="fr">image disque WIM</comment>
- <comment xml:lang="ga">íomhá diosca WIM</comment>
- <comment xml:lang="he">דמות דיסק WIM</comment>
- <comment xml:lang="hr">WIM slika diska</comment>
- <comment xml:lang="hu">WIM lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco WIM</comment>
- <comment xml:lang="id">Image disk WIM</comment>
- <comment xml:lang="it">Immagine disco WIM</comment>
- <comment xml:lang="kk">WIM диск бейнесі</comment>
- <comment xml:lang="ko">WIM 디스크 이미지</comment>
- <comment xml:lang="oc">imatge disc WIM</comment>
- <comment xml:lang="pl">Obraz dysku WIM</comment>
- <comment xml:lang="pt">imagem de disco WIM</comment>
- <comment xml:lang="pt_BR">Imagem de disco WIM</comment>
- <comment xml:lang="ru">Образ диска WIM</comment>
- <comment xml:lang="sk">Obraz disku WIM</comment>
- <comment xml:lang="sr">слика диска ВИМ-а</comment>
- <comment xml:lang="sv">WIM-diskavbild</comment>
- <comment xml:lang="tr">WIM disk kalıbı</comment>
- <comment xml:lang="uk">образ диска WIM</comment>
- <comment xml:lang="zh_CN">WIM 磁盘映像</comment>
+ <comment>WIM disk image</comment>
<comment xml:lang="zh_TW">WIM 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">WIM 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска WIM</comment>
+ <comment xml:lang="tr">WIM disk görüntüsü</comment>
+ <comment xml:lang="sv">WIM-diskavbildning</comment>
+ <comment xml:lang="sq">pamje disku WIM</comment>
+ <comment xml:lang="sl">Slika diska WIM</comment>
+ <comment xml:lang="si">WIM තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku WIM</comment>
+ <comment xml:lang="ru">Образ диска WIM</comment>
+ <comment xml:lang="pt_BR">Imagem de disco WIM</comment>
+ <comment xml:lang="pl">Obraz dysku WIM</comment>
+ <comment xml:lang="nl">WIM-schijfkopiebestand</comment>
+ <comment xml:lang="ko">WIM 디스크 이미지</comment>
+ <comment xml:lang="kk">WIM диск бейнесі</comment>
+ <comment xml:lang="ja">WIM ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco WIM</comment>
+ <comment xml:lang="is">WIM diskmynd</comment>
+ <comment xml:lang="id">Image disk WIM</comment>
+ <comment xml:lang="hu">WIM lemezkép</comment>
+ <comment xml:lang="hr">WIM slika diska</comment>
+ <comment xml:lang="he">דמות כונן WIM</comment>
+ <comment xml:lang="fr">image disque WIM</comment>
+ <comment xml:lang="fi">WIM-levykuva</comment>
+ <comment xml:lang="eu">WIM disko irudia</comment>
+ <comment xml:lang="es">imagen de disco WIM</comment>
+ <comment xml:lang="en_GB">WIM disk image</comment>
+ <comment xml:lang="de">WIM-Datenträgerabbild</comment>
+ <comment xml:lang="da">WIM-diskaftryk</comment>
+ <comment xml:lang="ca">imatge de disc WIM</comment>
+ <comment xml:lang="bg">Диск — WIM</comment>
+ <comment xml:lang="be">вобраз дыска WIM</comment>
+ <comment xml:lang="ar">صورة قرص WIM</comment>
<acronym>WIM</acronym>
<expanded-acronym>Windows Imaging Format</expanded-acronym>
<magic>
- <match value="MSWIM\000\000\000" type="string" offset="0"/>
+ <match type="string" value="MSWIM\000\000\000" offset="0"/>
</magic>
<glob pattern="*.wim"/>
<glob pattern="*.swm"/>
</mime-type>
<mime-type type="audio/ac3">
<comment>Dolby Digital audio</comment>
- <comment xml:lang="ar">Dolby Digital سمعي</comment>
- <comment xml:lang="az">Dolby Digital audio</comment>
- <comment xml:lang="be@latin">Aŭdyjo Dolby Digital</comment>
- <comment xml:lang="bg">Аудио — Dolby Digital</comment>
- <comment xml:lang="ca">àudio de Dolby Digital</comment>
- <comment xml:lang="cs">zvuk Dolby Digital</comment>
- <comment xml:lang="cy">Sain Dolby Digital</comment>
- <comment xml:lang="da">Dolby Ditital-lyd</comment>
- <comment xml:lang="de">Dolby-Digital-Audio</comment>
- <comment xml:lang="el">Ψηφιακός Ήχος Dolby</comment>
- <comment xml:lang="en_GB">Dolby Digital audio</comment>
- <comment xml:lang="eo">Sondosiero en Dolby Digital</comment>
- <comment xml:lang="es">sonido Dolby Digital</comment>
- <comment xml:lang="eu">Dolby audio digitala</comment>
- <comment xml:lang="fi">Dolby Digital -ääni</comment>
- <comment xml:lang="fo">Dolby Digital ljóður</comment>
- <comment xml:lang="fr">audio Dolby Digital</comment>
- <comment xml:lang="ga">fuaim Dolby Digital</comment>
- <comment xml:lang="gl">son Dolby Digital</comment>
- <comment xml:lang="he">שמע Dolby Digital</comment>
- <comment xml:lang="hr">Dolby Digital zvučni zapis</comment>
- <comment xml:lang="hu">Dolby Digital hang</comment>
- <comment xml:lang="ia">Audio Dolby Digital</comment>
- <comment xml:lang="id">Audio Dolby Digital</comment>
- <comment xml:lang="it">Audio Dolby Digital</comment>
- <comment xml:lang="ja">ドルビーデジタルオーディオ</comment>
- <comment xml:lang="ka">Dolby Digital-ის აუდიო</comment>
- <comment xml:lang="kk">Dolby Digital аудиосы</comment>
- <comment xml:lang="ko">돌비 디지털 오디오</comment>
- <comment xml:lang="lt">Dolby Digital garso įrašas</comment>
- <comment xml:lang="lv">Dolby Digital audio</comment>
- <comment xml:lang="ms">Audio Digital Dolby</comment>
- <comment xml:lang="nb">Dolby digital lyd</comment>
- <comment xml:lang="nl">Dolby Digital-audio</comment>
- <comment xml:lang="nn">Dolby Digital lyd</comment>
- <comment xml:lang="oc">àudio Dolby Digital</comment>
- <comment xml:lang="pl">Plik dźwiękowy Dolby Digital</comment>
- <comment xml:lang="pt">áudio Dolby Digital</comment>
- <comment xml:lang="pt_BR">Áudio Dolby Digital</comment>
- <comment xml:lang="ro">Audio Dolby Digital</comment>
- <comment xml:lang="ru">Аудио Dolby Digital</comment>
- <comment xml:lang="sk">Zvuk Dolby Digital</comment>
- <comment xml:lang="sl">Zvočna datoteka Dolby Digital</comment>
- <comment xml:lang="sq">Audio Dolby Digital</comment>
- <comment xml:lang="sr">Дигитални Долби звук</comment>
- <comment xml:lang="sv">Dolby Digital-ljud</comment>
- <comment xml:lang="tr">Dolby Digital sesi</comment>
- <comment xml:lang="uk">звук Dolby Digital</comment>
- <comment xml:lang="vi">Âm thanh Dolby Digital</comment>
- <comment xml:lang="zh_CN">杜比数字音频</comment>
<comment xml:lang="zh_TW">杜比數位音訊</comment>
- <magic priority="50">
- <match value="0x0b77" type="big16" offset="0"/>
+ <comment xml:lang="zh_CN">杜比数字音频</comment>
+ <comment xml:lang="vi">Âm thanh Dolby Digital</comment>
+ <comment xml:lang="uk">звук Dolby Digital</comment>
+ <comment xml:lang="tr">Dolby Digital sesi</comment>
+ <comment xml:lang="sv">Dolby Digital-ljud</comment>
+ <comment xml:lang="sr">Дигитални Долби звук</comment>
+ <comment xml:lang="sq">audio Dolby Digital</comment>
+ <comment xml:lang="sl">Zvočna datoteka Dolby Digital</comment>
+ <comment xml:lang="si">ඩොල්බි ඩිජිටල් ඕඩියෝ</comment>
+ <comment xml:lang="sk">Zvuk Dolby Digital</comment>
+ <comment xml:lang="ru">Аудио Dolby Digital</comment>
+ <comment xml:lang="ro">Audio Dolby Digital</comment>
+ <comment xml:lang="pt_BR">Áudio Dolby Digital</comment>
+ <comment xml:lang="pt">áudio Dolby Digital</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Dolby Digital</comment>
+ <comment xml:lang="oc">àudio Dolby Digital</comment>
+ <comment xml:lang="nn">Dolby Digital lyd</comment>
+ <comment xml:lang="nl">Dolby Digital-audio</comment>
+ <comment xml:lang="nb">Dolby digital lyd</comment>
+ <comment xml:lang="ms">Audio Digital Dolby</comment>
+ <comment xml:lang="lv">Dolby Digital audio</comment>
+ <comment xml:lang="lt">Dolby Digital garso įrašas</comment>
+ <comment xml:lang="ko">돌비 디지털 오디오</comment>
+ <comment xml:lang="kk">Dolby Digital аудиосы</comment>
+ <comment xml:lang="ka">Dolby Digital-ის აუდიო</comment>
+ <comment xml:lang="ja">ドルビーデジタルオーディオ</comment>
+ <comment xml:lang="it">Audio Dolby Digital</comment>
+ <comment xml:lang="is">Dolby Digital hljóðskrá</comment>
+ <comment xml:lang="id">Audio Dolby Digital</comment>
+ <comment xml:lang="ia">Audio Dolby Digital</comment>
+ <comment xml:lang="hu">Dolby Digital hang</comment>
+ <comment xml:lang="hr">Dolby Digital zvučni zapis</comment>
+ <comment xml:lang="he">שמע Dolby Digital</comment>
+ <comment xml:lang="gl">son Dolby Digital</comment>
+ <comment xml:lang="ga">fuaim Dolby Digital</comment>
+ <comment xml:lang="fur">audio Dolby Digital</comment>
+ <comment xml:lang="fr">audio Dolby Digital</comment>
+ <comment xml:lang="fo">Dolby Digital ljóður</comment>
+ <comment xml:lang="fi">Dolby Digital -ääni</comment>
+ <comment xml:lang="eu">Dolby audio digitala</comment>
+ <comment xml:lang="es">sonido Dolby Digital</comment>
+ <comment xml:lang="eo">Sondosiero en Dolby Digital</comment>
+ <comment xml:lang="en_GB">Dolby Digital audio</comment>
+ <comment xml:lang="el">Ψηφιακός Ήχος Dolby</comment>
+ <comment xml:lang="de">Dolby-Digital-Audio</comment>
+ <comment xml:lang="da">Dolby Ditital-lyd</comment>
+ <comment xml:lang="cy">Sain Dolby Digital</comment>
+ <comment xml:lang="cs">zvuk Dolby Digital</comment>
+ <comment xml:lang="ca">àudio Dolby Digital</comment>
+ <comment xml:lang="bg">Аудио — Dolby Digital</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Dolby Digital</comment>
+ <comment xml:lang="be">аўдыя Dolby Digital</comment>
+ <comment xml:lang="az">Dolby Digital audio</comment>
+ <comment xml:lang="ar">صوت Dolby Digital</comment>
+ <comment xml:lang="af">Dolby Digital-oudio</comment>
+ <magic>
+ <match type="big16" value="0x0b77" offset="0"/>
</magic>
<glob pattern="*.ac3"/>
</mime-type>
<mime-type type="audio/vnd.dts">
<comment>DTS audio</comment>
- <comment xml:lang="ca">àudio DTS</comment>
- <comment xml:lang="cs">zvuk DTS</comment>
- <comment xml:lang="da">DTS-lyd</comment>
- <comment xml:lang="de">DTS-Audio</comment>
- <comment xml:lang="el">Ήχος DTS</comment>
- <comment xml:lang="en_GB">DTS audio</comment>
- <comment xml:lang="es">sonido DTS</comment>
- <comment xml:lang="eu">DTS audioa</comment>
- <comment xml:lang="fi">DTS-ääni</comment>
- <comment xml:lang="fr">audio DTS</comment>
- <comment xml:lang="ga">fuaim DTS</comment>
- <comment xml:lang="gl">Son DTS</comment>
- <comment xml:lang="he">שמע DTS</comment>
- <comment xml:lang="hr">DTS zvučni zapis</comment>
- <comment xml:lang="hu">DTS hang</comment>
- <comment xml:lang="ia">Audio DTS</comment>
- <comment xml:lang="id">Audio DTS</comment>
- <comment xml:lang="it">Audio DTS</comment>
- <comment xml:lang="ja">DTS オーディオ</comment>
- <comment xml:lang="kk">DTS аудиосы</comment>
- <comment xml:lang="ko">DTS 오디오</comment>
- <comment xml:lang="lv">DTS audio</comment>
- <comment xml:lang="oc">àudio DTS</comment>
- <comment xml:lang="pl">Plik dźwiękowy DTS</comment>
- <comment xml:lang="pt">aúdio DTS</comment>
- <comment xml:lang="pt_BR">Áudio DTS</comment>
- <comment xml:lang="ru">Аудио DTS</comment>
- <comment xml:lang="sk">Zvuk DTS</comment>
- <comment xml:lang="sl">Zvok DTS</comment>
- <comment xml:lang="sr">ДТС звук</comment>
- <comment xml:lang="sv">DTS-ljud</comment>
- <comment xml:lang="tr">DTS sesi</comment>
- <comment xml:lang="uk">звукові дані DTS</comment>
- <comment xml:lang="zh_CN">DTS 音频</comment>
<comment xml:lang="zh_TW">DTS 音訊</comment>
- <magic priority="50">
- <match value="0x7FFE8001" type="big32" offset="0"/>
- <match value="0xFE7F0180" type="little32" offset="0"/>
- <match value="0x1FFFE800" type="big32" offset="0"/>
- <match value="0xFF1F00E8" type="little32" offset="0"/>
+ <comment xml:lang="zh_CN">DTS 音频</comment>
+ <comment xml:lang="uk">звукові дані DTS</comment>
+ <comment xml:lang="tr">DTS sesi</comment>
+ <comment xml:lang="sv">DTS-ljud</comment>
+ <comment xml:lang="sr">ДТС звук</comment>
+ <comment xml:lang="sq">audio DTS</comment>
+ <comment xml:lang="sl">Zvok DTS</comment>
+ <comment xml:lang="si">DTS ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk DTS</comment>
+ <comment xml:lang="ru">Аудио DTS</comment>
+ <comment xml:lang="pt_BR">Áudio DTS</comment>
+ <comment xml:lang="pt">aúdio DTS</comment>
+ <comment xml:lang="pl">Plik dźwiękowy DTS</comment>
+ <comment xml:lang="oc">àudio DTS</comment>
+ <comment xml:lang="nl">DTS-audio</comment>
+ <comment xml:lang="lv">DTS audio</comment>
+ <comment xml:lang="ko">DTS 오디오</comment>
+ <comment xml:lang="kk">DTS аудиосы</comment>
+ <comment xml:lang="ja">DTS オーディオ</comment>
+ <comment xml:lang="it">Audio DTS</comment>
+ <comment xml:lang="is">DTS hljóðskrá</comment>
+ <comment xml:lang="id">Audio DTS</comment>
+ <comment xml:lang="ia">Audio DTS</comment>
+ <comment xml:lang="hu">DTS hang</comment>
+ <comment xml:lang="hr">DTS zvučni zapis</comment>
+ <comment xml:lang="he">שמע DTS</comment>
+ <comment xml:lang="gl">Son DTS</comment>
+ <comment xml:lang="ga">fuaim DTS</comment>
+ <comment xml:lang="fur">audio DTS</comment>
+ <comment xml:lang="fr">audio DTS</comment>
+ <comment xml:lang="fi">DTS-ääni</comment>
+ <comment xml:lang="eu">DTS audioa</comment>
+ <comment xml:lang="es">sonido DTS</comment>
+ <comment xml:lang="en_GB">DTS audio</comment>
+ <comment xml:lang="el">Ήχος DTS</comment>
+ <comment xml:lang="de">DTS-Audio</comment>
+ <comment xml:lang="da">DTS-lyd</comment>
+ <comment xml:lang="cs">zvuk DTS</comment>
+ <comment xml:lang="ca">àudio DTS</comment>
+ <comment xml:lang="bg">Аудио — DTS</comment>
+ <comment xml:lang="be">аўдыя DTS</comment>
+ <comment xml:lang="ar">صوت DTS</comment>
+ <comment xml:lang="af">DTS-oudio</comment>
+ <acronym>DTS</acronym>
+ <expanded-acronym>Digital Theater Systems</expanded-acronym>
+ <magic>
+ <match type="big32" value="0x7FFE8001" offset="0"/>
+ <!-- 16bits core be -->
+ <match type="little32" value="0xFE7F0180" offset="0"/>
+ <!-- 16bits core le -->
+ <match type="big32" value="0x1FFFE800" offset="0"/>
+ <!-- 14bits core be -->
+ <match type="little32" value="0xFF1F00E8" offset="0"/>
+ <!-- 14bits core le -->
</magic>
<alias type="audio/x-dts"/>
<glob pattern="*.dts"/>
</mime-type>
<mime-type type="audio/vnd.dts.hd">
- <comment>DTSHD audio</comment>
- <comment xml:lang="ca">àudio DTSHD</comment>
- <comment xml:lang="cs">zvuk DTSHD</comment>
- <comment xml:lang="da">DTSDH-lyd</comment>
- <comment xml:lang="de">DTSHD-Audio</comment>
- <comment xml:lang="el">Ήχος DTSHD</comment>
- <comment xml:lang="en_GB">DTSHD audio</comment>
- <comment xml:lang="es">sonido DTSHD</comment>
- <comment xml:lang="eu">DTSHD audioa</comment>
+ <comment>DTS-HD audio</comment>
+ <comment xml:lang="zh_TW">DTS-HD 音訊</comment>
+ <comment xml:lang="zh_CN">DTS-HD 音频</comment>
+ <comment xml:lang="uk">звукові дані DTS-HD</comment>
+ <comment xml:lang="tr">DTS-HD sesi</comment>
+ <comment xml:lang="sv">DTS-HD-ljud</comment>
+ <comment xml:lang="sl">Zvok DTS-HD</comment>
+ <comment xml:lang="si">DTS-HD ශ්රව්ය</comment>
+ <comment xml:lang="ru">Аудио DTS-HD</comment>
+ <comment xml:lang="pt_BR">Áudio DTS-HD</comment>
+ <comment xml:lang="pl">Plik dźwiękowy DTS-HD</comment>
+ <comment xml:lang="nl">DTS-HD-audio</comment>
+ <comment xml:lang="ko">DTS-HD 오디오</comment>
+ <comment xml:lang="kk">DTS-HD аудиосы</comment>
+ <comment xml:lang="ja">DTS-HD オーディオ</comment>
+ <comment xml:lang="it">Audio DTS-HD</comment>
+ <comment xml:lang="hr">DTS-HD zvučni zapis</comment>
<comment xml:lang="fi">DTS-HD-ääni</comment>
- <comment xml:lang="fr">audio DTSHD</comment>
- <comment xml:lang="ga">fuaim DTSHD</comment>
- <comment xml:lang="gl">Son DTSHD</comment>
- <comment xml:lang="he">שמע DTSHD</comment>
- <comment xml:lang="hr">DTSHD zvučni zapis</comment>
- <comment xml:lang="hu">DTSHD hang</comment>
- <comment xml:lang="ia">Audio DTSHD</comment>
- <comment xml:lang="id">Audio DTSHD</comment>
- <comment xml:lang="it">Audio DTSHD</comment>
- <comment xml:lang="ja">DTSHD オーディオ</comment>
- <comment xml:lang="kk">DTSHD аудиосы</comment>
- <comment xml:lang="ko">DTSHD 오디오</comment>
- <comment xml:lang="lv">DTSHD audio</comment>
- <comment xml:lang="oc">àudio DTSHD</comment>
- <comment xml:lang="pl">Plik dźwiękowy DTSHD</comment>
- <comment xml:lang="pt">áudio DTSHD</comment>
- <comment xml:lang="pt_BR">Áudio DTSHD</comment>
- <comment xml:lang="ru">Аудио DTSHD</comment>
- <comment xml:lang="sk">Zvuk DTSHD</comment>
- <comment xml:lang="sl">Zvok DTSHD</comment>
- <comment xml:lang="sr">ДТСХД звук</comment>
- <comment xml:lang="sv">DTSHD-ljud</comment>
- <comment xml:lang="tr">DTSHD sesi</comment>
- <comment xml:lang="uk">звукові дані DTSHD</comment>
- <comment xml:lang="zh_CN">DTSHD 音频</comment>
- <comment xml:lang="zh_TW">DTSHD 音訊</comment>
+ <comment xml:lang="eu">DTS-HD audioa</comment>
+ <comment xml:lang="es">sonido DTS-HD</comment>
+ <comment xml:lang="en_GB">DTS-HD audio</comment>
+ <comment xml:lang="de">DTS-HD-Audio</comment>
+ <comment xml:lang="be">аўдыя DTS-HD</comment>
+ <comment xml:lang="ar">صوت DTS-HD</comment>
+ <acronym>DTS-HD</acronym>
+ <expanded-acronym>Digital Theater Systems High Definition</expanded-acronym>
<sub-class-of type="audio/vnd.dts"/>
<magic priority="60">
- <match value="0x64582025" type="big32" offset="0:18725"/>
+ <match type="big32" value="0x7FFE8001" offset="0">
+ <!-- 16bits core be -->
+ <match type="big32" value="0x64582025" offset="4:18725"/>
+ <!-- 16bits HD be -->
+ </match>
</magic>
<alias type="audio/x-dtshd"/>
<glob pattern="*.dtshd"/>
</mime-type>
<mime-type type="audio/AMR">
<comment>AMR audio</comment>
- <comment xml:lang="ar">AMR سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo AMR</comment>
- <comment xml:lang="bg">Аудио — AMR</comment>
- <comment xml:lang="ca">àudio AMR</comment>
- <comment xml:lang="cs">zvuk AMR</comment>
- <comment xml:lang="da">AMR-lyd</comment>
- <comment xml:lang="de">AMR-Audio</comment>
- <comment xml:lang="el">Ήχος AMR</comment>
- <comment xml:lang="en_GB">AMR audio</comment>
- <comment xml:lang="eo">AMR-sondosiero</comment>
- <comment xml:lang="es">sonido AMR</comment>
- <comment xml:lang="eu">AMR audioa</comment>
- <comment xml:lang="fi">AMR-ääni</comment>
- <comment xml:lang="fo">AMR ljóður</comment>
- <comment xml:lang="fr">audio AMR</comment>
- <comment xml:lang="ga">fuaim AMR</comment>
- <comment xml:lang="gl">son AMR</comment>
- <comment xml:lang="he">שמע AMR</comment>
- <comment xml:lang="hr">AMR zvučni zapis</comment>
- <comment xml:lang="hu">AMR hang</comment>
- <comment xml:lang="ia">Audio AMR</comment>
- <comment xml:lang="id">Audio AMR</comment>
- <comment xml:lang="it">Audio AMR</comment>
- <comment xml:lang="ja">AMR オーディオ</comment>
- <comment xml:lang="ka">AMR აუდიო</comment>
- <comment xml:lang="kk">AMR аудиосы</comment>
- <comment xml:lang="ko">AMR 오디오</comment>
- <comment xml:lang="lt">AMR garso įrašas</comment>
- <comment xml:lang="lv">AMR audio</comment>
- <comment xml:lang="nb">AMR-lyd</comment>
- <comment xml:lang="nl">AMR-audio</comment>
- <comment xml:lang="nn">AMR-lyd</comment>
- <comment xml:lang="oc">àudio AMR</comment>
- <comment xml:lang="pl">Plik dźwiękowy AMR</comment>
- <comment xml:lang="pt">áudio AMR</comment>
- <comment xml:lang="pt_BR">Áudio AMR</comment>
- <comment xml:lang="ro">Audio AMR</comment>
- <comment xml:lang="ru">Аудио AMR</comment>
- <comment xml:lang="sk">Zvuk AMR</comment>
- <comment xml:lang="sl">Zvočna datoteka AMR</comment>
- <comment xml:lang="sq">Audio AMR</comment>
- <comment xml:lang="sr">АМР звук</comment>
- <comment xml:lang="sv">AMR-ljud</comment>
- <comment xml:lang="tr">AMR sesi</comment>
- <comment xml:lang="uk">звук AMR</comment>
- <comment xml:lang="vi">Âm thanh AMR</comment>
- <comment xml:lang="zh_CN">AMR 音频</comment>
<comment xml:lang="zh_TW">AMR 音訊</comment>
+ <comment xml:lang="zh_CN">AMR 音频</comment>
+ <comment xml:lang="vi">Âm thanh AMR</comment>
+ <comment xml:lang="uk">звук AMR</comment>
+ <comment xml:lang="tr">AMR sesi</comment>
+ <comment xml:lang="sv">AMR-ljud</comment>
+ <comment xml:lang="sr">АМР звук</comment>
+ <comment xml:lang="sq">audio AMR</comment>
+ <comment xml:lang="sl">Zvočna datoteka AMR</comment>
+ <comment xml:lang="si">AMR ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk AMR</comment>
+ <comment xml:lang="ru">Аудио AMR</comment>
+ <comment xml:lang="ro">Audio AMR</comment>
+ <comment xml:lang="pt_BR">Áudio AMR</comment>
+ <comment xml:lang="pt">áudio AMR</comment>
+ <comment xml:lang="pl">Plik dźwiękowy AMR</comment>
+ <comment xml:lang="oc">àudio AMR</comment>
+ <comment xml:lang="nn">AMR-lyd</comment>
+ <comment xml:lang="nl">AMR-audio</comment>
+ <comment xml:lang="nb">AMR-lyd</comment>
+ <comment xml:lang="lv">AMR audio</comment>
+ <comment xml:lang="lt">AMR garso įrašas</comment>
+ <comment xml:lang="ko">AMR 오디오</comment>
+ <comment xml:lang="kk">AMR аудиосы</comment>
+ <comment xml:lang="ka">AMR აუდიო</comment>
+ <comment xml:lang="ja">AMR オーディオ</comment>
+ <comment xml:lang="it">Audio AMR</comment>
+ <comment xml:lang="is">AMR hljóðskrá</comment>
+ <comment xml:lang="id">Audio AMR</comment>
+ <comment xml:lang="ia">Audio AMR</comment>
+ <comment xml:lang="hu">AMR hang</comment>
+ <comment xml:lang="hr">AMR zvučni zapis</comment>
+ <comment xml:lang="he">שמע AMR</comment>
+ <comment xml:lang="gl">son AMR</comment>
+ <comment xml:lang="ga">fuaim AMR</comment>
+ <comment xml:lang="fur">audio AMR</comment>
+ <comment xml:lang="fr">audio AMR</comment>
+ <comment xml:lang="fo">AMR ljóður</comment>
+ <comment xml:lang="fi">AMR-ääni</comment>
+ <comment xml:lang="eu">AMR audioa</comment>
+ <comment xml:lang="es">sonido AMR</comment>
+ <comment xml:lang="eo">AMR-sondosiero</comment>
+ <comment xml:lang="en_GB">AMR audio</comment>
+ <comment xml:lang="el">Ήχος AMR</comment>
+ <comment xml:lang="de">AMR-Audio</comment>
+ <comment xml:lang="da">AMR-lyd</comment>
+ <comment xml:lang="cs">zvuk AMR</comment>
+ <comment xml:lang="ca">àudio AMR</comment>
+ <comment xml:lang="bg">Аудио — AMR</comment>
+ <comment xml:lang="be@latin">Aŭdyjo AMR</comment>
+ <comment xml:lang="be">аўдыя AMR</comment>
+ <comment xml:lang="ar">صوت AMR</comment>
+ <comment xml:lang="af">AMR-oudio</comment>
<acronym>AMR</acronym>
<expanded-acronym>Adaptive Multi-Rate</expanded-acronym>
- <magic priority="50">
- <match value="#!AMR\n" type="string" offset="0"/>
- <match value="#!AMR_MC1.0\n" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#!AMR\n" offset="0"/>
+ <match type="string" value="#!AMR_MC1.0\n" offset="0"/>
</magic>
<glob pattern="*.amr"/>
<alias type="audio/amr-encrypted"/>
</mime-type>
<mime-type type="audio/AMR-WB">
<comment>AMR-WB audio</comment>
- <comment xml:lang="ar">AMR-WB سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo AMR-WB</comment>
- <comment xml:lang="bg">Аудио — AMR-WB</comment>
- <comment xml:lang="ca">àudio AMR-WB</comment>
- <comment xml:lang="cs">zvuk AMR-WB</comment>
- <comment xml:lang="da">AMR-WB-lyd</comment>
- <comment xml:lang="de">AMR-WB-Audio</comment>
- <comment xml:lang="el">Ήχος AMR-WB</comment>
- <comment xml:lang="en_GB">AMR-WB audio</comment>
- <comment xml:lang="eo">AMR-WB-sondosiero</comment>
- <comment xml:lang="es">sonido AMR-WB</comment>
- <comment xml:lang="eu">AMR-WB audioa</comment>
- <comment xml:lang="fi">AMR-WB-ääni</comment>
- <comment xml:lang="fo">AMR-WB ljóður</comment>
- <comment xml:lang="fr">audio AMR-WB</comment>
- <comment xml:lang="ga">fuaim AMR-WB</comment>
- <comment xml:lang="gl">son AMR-WB</comment>
- <comment xml:lang="he">שמע AMR-WN</comment>
- <comment xml:lang="hr">AMR-WB zvučni zapis</comment>
- <comment xml:lang="hu">AMR-WB hang</comment>
- <comment xml:lang="ia">Audio AMR-WB</comment>
- <comment xml:lang="id">Audio AMR-WB</comment>
- <comment xml:lang="it">Audio AMR-WB</comment>
- <comment xml:lang="ja">AMR-WB オーディオ</comment>
- <comment xml:lang="ka">AMR-WB აუდიო</comment>
- <comment xml:lang="kk">AMR-WB аудиосы</comment>
- <comment xml:lang="ko">AMR-WB 오디오</comment>
- <comment xml:lang="lt">AMR-WB garso įrašas</comment>
- <comment xml:lang="lv">AMR-WB audio</comment>
- <comment xml:lang="nb">AMR-WB-lyd</comment>
- <comment xml:lang="nl">AMR-WB-audio</comment>
- <comment xml:lang="nn">AMR-WB-lyd</comment>
- <comment xml:lang="oc">àudio AMR-WB</comment>
- <comment xml:lang="pl">Plik dźwiękowy AMR-WB</comment>
- <comment xml:lang="pt">áudio AMR-WB</comment>
- <comment xml:lang="pt_BR">Áudio AMR-WB</comment>
- <comment xml:lang="ro">Audio AMR-WB</comment>
- <comment xml:lang="ru">Аудио AMR-WB</comment>
- <comment xml:lang="sk">Zvuk AMR-WB</comment>
- <comment xml:lang="sl">Zvočna datoteka AMR-WB</comment>
- <comment xml:lang="sq">Audio AMR-WB</comment>
- <comment xml:lang="sr">АМР-ВБ звук</comment>
- <comment xml:lang="sv">AMR-WB-ljud</comment>
- <comment xml:lang="tr">AMR-WB sesi</comment>
- <comment xml:lang="uk">звук AMR-WB</comment>
- <comment xml:lang="vi">Âm thanh AMR-WB</comment>
- <comment xml:lang="zh_CN">AMR-WB 音频</comment>
<comment xml:lang="zh_TW">AMR-WB 音訊</comment>
+ <comment xml:lang="zh_CN">AMR-WB 音频</comment>
+ <comment xml:lang="vi">Âm thanh AMR-WB</comment>
+ <comment xml:lang="uk">звук AMR-WB</comment>
+ <comment xml:lang="tr">AMR-WB sesi</comment>
+ <comment xml:lang="sv">AMR-WB-ljud</comment>
+ <comment xml:lang="sr">АМР-ВБ звук</comment>
+ <comment xml:lang="sq">audio AMR-WB</comment>
+ <comment xml:lang="sl">Zvočna datoteka AMR-WB</comment>
+ <comment xml:lang="si">AMR-WB ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk AMR-WB</comment>
+ <comment xml:lang="ru">Аудио AMR-WB</comment>
+ <comment xml:lang="ro">Audio AMR-WB</comment>
+ <comment xml:lang="pt_BR">Áudio AMR-WB</comment>
+ <comment xml:lang="pt">áudio AMR-WB</comment>
+ <comment xml:lang="pl">Plik dźwiękowy AMR-WB</comment>
+ <comment xml:lang="oc">àudio AMR-WB</comment>
+ <comment xml:lang="nn">AMR-WB-lyd</comment>
+ <comment xml:lang="nl">AMR-WB-audio</comment>
+ <comment xml:lang="nb">AMR-WB-lyd</comment>
+ <comment xml:lang="lv">AMR-WB audio</comment>
+ <comment xml:lang="lt">AMR-WB garso įrašas</comment>
+ <comment xml:lang="ko">AMR-WB 오디오</comment>
+ <comment xml:lang="kk">AMR-WB аудиосы</comment>
+ <comment xml:lang="ka">AMR-WB აუდიო</comment>
+ <comment xml:lang="ja">AMR-WB オーディオ</comment>
+ <comment xml:lang="it">Audio AMR-WB</comment>
+ <comment xml:lang="is">AMR-WB hljóðskrá</comment>
+ <comment xml:lang="id">Audio AMR-WB</comment>
+ <comment xml:lang="ia">Audio AMR-WB</comment>
+ <comment xml:lang="hu">AMR-WB hang</comment>
+ <comment xml:lang="hr">AMR-WB zvučni zapis</comment>
+ <comment xml:lang="he">שמע AMR-WN</comment>
+ <comment xml:lang="gl">son AMR-WB</comment>
+ <comment xml:lang="ga">fuaim AMR-WB</comment>
+ <comment xml:lang="fur">audio AMR-WB</comment>
+ <comment xml:lang="fr">audio AMR-WB</comment>
+ <comment xml:lang="fo">AMR-WB ljóður</comment>
+ <comment xml:lang="fi">AMR-WB-ääni</comment>
+ <comment xml:lang="eu">AMR-WB audioa</comment>
+ <comment xml:lang="es">sonido AMR-WB</comment>
+ <comment xml:lang="eo">AMR-WB-sondosiero</comment>
+ <comment xml:lang="en_GB">AMR-WB audio</comment>
+ <comment xml:lang="el">Ήχος AMR-WB</comment>
+ <comment xml:lang="de">AMR-WB-Audio</comment>
+ <comment xml:lang="da">AMR-WB-lyd</comment>
+ <comment xml:lang="cs">zvuk AMR-WB</comment>
+ <comment xml:lang="ca">àudio AMR-WB</comment>
+ <comment xml:lang="bg">Аудио — AMR-WB</comment>
+ <comment xml:lang="be@latin">Aŭdyjo AMR-WB</comment>
+ <comment xml:lang="be">аўдыя AMR-WB</comment>
+ <comment xml:lang="ar">صوت AMR-WB</comment>
+ <comment xml:lang="af">AMR-WB-oudio</comment>
<acronym>AMR-WB</acronym>
<expanded-acronym>Adaptive Multi-Rate Wideband</expanded-acronym>
- <magic priority="50">
- <match value="#!AMR-WB\n" type="string" offset="0"/>
- <match value="#!AMR-WB_MC1.0\n" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#!AMR-WB\n" offset="0"/>
+ <match type="string" value="#!AMR-WB_MC1.0\n" offset="0"/>
</magic>
<glob pattern="*.awb"/>
<alias type="audio/amr-wb-encrypted"/>
</mime-type>
<mime-type type="audio/basic">
<comment>ULAW (Sun) audio</comment>
- <comment xml:lang="ar">ULAW (صن) سمعي</comment>
- <comment xml:lang="az">ULAW (Sun) audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo ULAW (Sun)</comment>
- <comment xml:lang="bg">Аудио — ULAW, Sun</comment>
- <comment xml:lang="ca">àudio ULAW (Sun)</comment>
- <comment xml:lang="cs">zvuk ULAW (Sun)</comment>
- <comment xml:lang="cy">Sain ULAW (Sun)</comment>
- <comment xml:lang="da">ULAW-lyd (Sun)</comment>
- <comment xml:lang="de">ULAW-Audio (Sun)</comment>
- <comment xml:lang="el">Ήχος ULAW (Sun)</comment>
- <comment xml:lang="en_GB">ULAW (Sun) audio</comment>
- <comment xml:lang="eo">ULAW-sondosiero (Sun)</comment>
- <comment xml:lang="es">sonido ULAW (Sun)</comment>
- <comment xml:lang="eu">ULAW (sun) audioa</comment>
- <comment xml:lang="fi">ULAW (Sun) -ääni</comment>
- <comment xml:lang="fo">ULAW (Sun) ljóður</comment>
- <comment xml:lang="fr">audio ULAW (Sun)</comment>
- <comment xml:lang="ga">fuaim ULAW (Sun)</comment>
- <comment xml:lang="gl">son ULAW (Sun)</comment>
- <comment xml:lang="he">שמע ULAW (של Sun)</comment>
- <comment xml:lang="hr">ULAW (Sun) zvučni zapis</comment>
- <comment xml:lang="hu">ULAW (Sun) hang</comment>
- <comment xml:lang="ia">Audio ULAW (sun)</comment>
- <comment xml:lang="id">Audio ULAW (Sun)</comment>
- <comment xml:lang="it">Audio ULAW (Sun)</comment>
- <comment xml:lang="ja">ULAW (Sun) オーディオ</comment>
- <comment xml:lang="kk">ULAW (Sun) аудиосы</comment>
- <comment xml:lang="ko">ULAW(Sun) 오디오</comment>
- <comment xml:lang="lt">ULAW (Sun) garso įrašas</comment>
- <comment xml:lang="lv">ULAW (Sun) audio</comment>
- <comment xml:lang="ms">Audio ULAW (Sun)</comment>
- <comment xml:lang="nb">ULAW-lyd (Sun)</comment>
- <comment xml:lang="nl">(Sun) ULAW-audio</comment>
- <comment xml:lang="nn">ULAW (Sun)-lyd</comment>
- <comment xml:lang="oc">àudio ULAW (Sun)</comment>
- <comment xml:lang="pl">Plik dźwiękowy ULAW (Sun)</comment>
- <comment xml:lang="pt">áudio ULAW (Sun)</comment>
- <comment xml:lang="pt_BR">Áudio ULAW (Sun)</comment>
- <comment xml:lang="ro">Fișier audio ULAW (Sun)</comment>
- <comment xml:lang="ru">Аудио ULAW (Sun)</comment>
- <comment xml:lang="sk">Zvuk ULAW (Sun)</comment>
- <comment xml:lang="sl">Zvočna datoteka ULAW (Sun)</comment>
- <comment xml:lang="sq">Audio ULAW (Sun)</comment>
- <comment xml:lang="sr">УЛАВ (Сан) звук</comment>
- <comment xml:lang="sv">ULAW-ljud (Sun)</comment>
- <comment xml:lang="tr">ULAW (Sun) sesi</comment>
- <comment xml:lang="uk">звук ULAW (Sun)</comment>
- <comment xml:lang="vi">Âm thanh ULAW (Sun)</comment>
- <comment xml:lang="zh_CN">ULAW (Sun) 音频</comment>
<comment xml:lang="zh_TW">ULAW (Sun) 音訊</comment>
+ <comment xml:lang="zh_CN">ULAW (Sun) 音频</comment>
+ <comment xml:lang="vi">Âm thanh ULAW (Sun)</comment>
+ <comment xml:lang="uk">звук ULAW (Sun)</comment>
+ <comment xml:lang="tr">ULAW (Sun) sesi</comment>
+ <comment xml:lang="sv">ULAW-ljud (Sun)</comment>
+ <comment xml:lang="sr">УЛАВ (Сан) звук</comment>
+ <comment xml:lang="sq">audio ULAW (Sun)</comment>
+ <comment xml:lang="sl">Zvočna datoteka ULAW (Sun)</comment>
+ <comment xml:lang="si">ULAW (හිරු) ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk ULAW (Sun)</comment>
+ <comment xml:lang="ru">Аудио ULAW (Sun)</comment>
+ <comment xml:lang="ro">Fișier audio ULAW (Sun)</comment>
+ <comment xml:lang="pt_BR">Áudio ULAW (Sun)</comment>
+ <comment xml:lang="pt">áudio ULAW (Sun)</comment>
+ <comment xml:lang="pl">Plik dźwiękowy ULAW (Sun)</comment>
+ <comment xml:lang="oc">àudio ULAW (Sun)</comment>
+ <comment xml:lang="nn">ULAW (Sun)-lyd</comment>
+ <comment xml:lang="nl">(Sun) ULAW-audio</comment>
+ <comment xml:lang="nb">ULAW-lyd (Sun)</comment>
+ <comment xml:lang="ms">Audio ULAW (Sun)</comment>
+ <comment xml:lang="lv">ULAW (Sun) audio</comment>
+ <comment xml:lang="lt">ULAW (Sun) garso įrašas</comment>
+ <comment xml:lang="ko">ULAW(Sun) 오디오</comment>
+ <comment xml:lang="kk">ULAW (Sun) аудиосы</comment>
+ <comment xml:lang="ja">ULAW (Sun) オーディオ</comment>
+ <comment xml:lang="it">Audio ULAW (Sun)</comment>
+ <comment xml:lang="is">ULAW (Sun) hljóðskrá</comment>
+ <comment xml:lang="id">Audio ULAW (Sun)</comment>
+ <comment xml:lang="ia">Audio ULAW (sun)</comment>
+ <comment xml:lang="hu">ULAW (Sun) hang</comment>
+ <comment xml:lang="hr">ULAW (Sun) zvučni zapis</comment>
+ <comment xml:lang="he">שמע ULAW (של Sun)</comment>
+ <comment xml:lang="gl">son ULAW (Sun)</comment>
+ <comment xml:lang="ga">fuaim ULAW (Sun)</comment>
+ <comment xml:lang="fur">audio ULAW (Sun)</comment>
+ <comment xml:lang="fr">audio ULAW (Sun)</comment>
+ <comment xml:lang="fo">ULAW (Sun) ljóður</comment>
+ <comment xml:lang="fi">ULAW (Sun) -ääni</comment>
+ <comment xml:lang="eu">ULAW (sun) audioa</comment>
+ <comment xml:lang="es">sonido ULAW (Sun)</comment>
+ <comment xml:lang="eo">ULAW-sondosiero (Sun)</comment>
+ <comment xml:lang="en_GB">ULAW (Sun) audio</comment>
+ <comment xml:lang="el">Ήχος ULAW (Sun)</comment>
+ <comment xml:lang="de">ULAW-Audio (Sun)</comment>
+ <comment xml:lang="da">ULAW-lyd (Sun)</comment>
+ <comment xml:lang="cy">Sain ULAW (Sun)</comment>
+ <comment xml:lang="cs">zvuk ULAW (Sun)</comment>
+ <comment xml:lang="ca">àudio ULAW (Sun)</comment>
+ <comment xml:lang="bg">Аудио — ULAW, Sun</comment>
+ <comment xml:lang="be@latin">Aŭdyjo ULAW (Sun)</comment>
+ <comment xml:lang="be">аўдыя ULAW (Sun)</comment>
+ <comment xml:lang="az">ULAW (Sun) audio faylı</comment>
+ <comment xml:lang="ar">صوت ULAW (صن)</comment>
+ <comment xml:lang="af">ULAW- (Sun) oudio</comment>
<magic priority="40">
- <match value=".snd" type="string" offset="0"/>
+ <match type="string" value=".snd" offset="0"/>
</magic>
<glob pattern="*.au"/>
<glob pattern="*.snd"/>
</mime-type>
<mime-type type="audio/prs.sid">
<comment>Commodore 64 audio</comment>
- <comment xml:lang="ar">Commodore 64 سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Commodore 64</comment>
- <comment xml:lang="bg">Аудио — Commodore 64</comment>
- <comment xml:lang="ca">àudio de Commodore 64</comment>
- <comment xml:lang="cs">zvuk Commodore 64</comment>
- <comment xml:lang="da">Commodore 64-lyd</comment>
- <comment xml:lang="de">Commodore-64-Audio</comment>
- <comment xml:lang="el">Ήχος Commodore 64</comment>
- <comment xml:lang="en_GB">Commodore 64 audio</comment>
- <comment xml:lang="eo">Sondosiero de Commodore 64</comment>
- <comment xml:lang="es">sonido de Commodore 64</comment>
- <comment xml:lang="eu">Commodore 64 Audioa</comment>
- <comment xml:lang="fi">Commodore 64 -ääni</comment>
- <comment xml:lang="fo">Commodore 64 ljóð</comment>
- <comment xml:lang="fr">audio Commodore 64</comment>
- <comment xml:lang="ga">fuaim Commodore 64</comment>
- <comment xml:lang="gl">son de Commodore 64</comment>
- <comment xml:lang="he">שמע של Commodore 64</comment>
- <comment xml:lang="hr">Commodore 64 zvučni zapis</comment>
- <comment xml:lang="hu">Commodore 64 hang</comment>
- <comment xml:lang="ia">Audio Commodore 64</comment>
- <comment xml:lang="id">Audio Commodore 64</comment>
- <comment xml:lang="it">Audio Commodore 64</comment>
- <comment xml:lang="ja">Commodore 64 オーディオ</comment>
- <comment xml:lang="ka">Commodore 64-ის აუდიო</comment>
- <comment xml:lang="kk">Commodore 64 аудиосы</comment>
- <comment xml:lang="ko">Commodore 64 오디오</comment>
- <comment xml:lang="lt">Commodore 64 garso įrašas</comment>
- <comment xml:lang="lv">Commodore 64 audio</comment>
- <comment xml:lang="ms">Audio Commodore 64</comment>
- <comment xml:lang="nb">Commodore 64-lyd</comment>
- <comment xml:lang="nl">Commodore 64-audio</comment>
- <comment xml:lang="nn">Commodore 64-lyd</comment>
- <comment xml:lang="oc">àudio Commodore 64</comment>
- <comment xml:lang="pl">Plik dźwiękowy Commodore 64</comment>
- <comment xml:lang="pt">áudio Commodore 64</comment>
- <comment xml:lang="pt_BR">Áudio Commodore 64</comment>
- <comment xml:lang="ro">Audio Commodore 64</comment>
- <comment xml:lang="ru">Аудио Commodore 64</comment>
- <comment xml:lang="sk">Zvuk Commodore 64</comment>
- <comment xml:lang="sl">Zvočna datoteka Commodore 64</comment>
- <comment xml:lang="sq">Audio Commodore 64</comment>
- <comment xml:lang="sr">звук Комодора 64</comment>
- <comment xml:lang="sv">Commodore 64-ljud</comment>
- <comment xml:lang="tr">Commodore 64 sesi</comment>
- <comment xml:lang="uk">звук Commodore 64</comment>
- <comment xml:lang="vi">Âm thanh Commodore 64</comment>
- <comment xml:lang="zh_CN">Commodore 64 音频</comment>
<comment xml:lang="zh_TW">Commodore 64 音訊</comment>
- <magic priority="50">
- <match value="PSID" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">Commodore 64 音频</comment>
+ <comment xml:lang="vi">Âm thanh Commodore 64</comment>
+ <comment xml:lang="uk">звук Commodore 64</comment>
+ <comment xml:lang="tr">Commodore 64 sesi</comment>
+ <comment xml:lang="sv">Commodore 64-ljud</comment>
+ <comment xml:lang="sr">звук Комодора 64</comment>
+ <comment xml:lang="sq">audio Commodore 64</comment>
+ <comment xml:lang="sl">Zvočna datoteka Commodore 64</comment>
+ <comment xml:lang="si">කොමදෝරු 64 ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk Commodore 64</comment>
+ <comment xml:lang="ru">Аудио Commodore 64</comment>
+ <comment xml:lang="ro">Audio Commodore 64</comment>
+ <comment xml:lang="pt_BR">Áudio Commodore 64</comment>
+ <comment xml:lang="pt">áudio Commodore 64</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Commodore 64</comment>
+ <comment xml:lang="oc">àudio Commodore 64</comment>
+ <comment xml:lang="nn">Commodore 64-lyd</comment>
+ <comment xml:lang="nl">Commodore 64-audio</comment>
+ <comment xml:lang="nb">Commodore 64-lyd</comment>
+ <comment xml:lang="ms">Audio Commodore 64</comment>
+ <comment xml:lang="lv">Commodore 64 audio</comment>
+ <comment xml:lang="lt">Commodore 64 garso įrašas</comment>
+ <comment xml:lang="ko">Commodore 64 오디오</comment>
+ <comment xml:lang="kk">Commodore 64 аудиосы</comment>
+ <comment xml:lang="ka">Commodore 64-ის აუდიო</comment>
+ <comment xml:lang="ja">Commodore 64 オーディオ</comment>
+ <comment xml:lang="it">Audio Commodore 64</comment>
+ <comment xml:lang="is">Commodore 64 hljóðskrá</comment>
+ <comment xml:lang="id">Audio Commodore 64</comment>
+ <comment xml:lang="ia">Audio Commodore 64</comment>
+ <comment xml:lang="hu">Commodore 64 hang</comment>
+ <comment xml:lang="hr">Commodore 64 zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Commodore 64</comment>
+ <comment xml:lang="gl">son de Commodore 64</comment>
+ <comment xml:lang="ga">fuaim Commodore 64</comment>
+ <comment xml:lang="fur">audio Commodore 64</comment>
+ <comment xml:lang="fr">audio Commodore 64</comment>
+ <comment xml:lang="fo">Commodore 64 ljóð</comment>
+ <comment xml:lang="fi">Commodore 64 -ääni</comment>
+ <comment xml:lang="eu">Commodore 64 Audioa</comment>
+ <comment xml:lang="es">sonido de Commodore 64</comment>
+ <comment xml:lang="eo">Sondosiero de Commodore 64</comment>
+ <comment xml:lang="en_GB">Commodore 64 audio</comment>
+ <comment xml:lang="el">Ήχος Commodore 64</comment>
+ <comment xml:lang="de">Commodore-64-Audio</comment>
+ <comment xml:lang="da">Commodore 64-lyd</comment>
+ <comment xml:lang="cs">zvuk Commodore 64</comment>
+ <comment xml:lang="ca">àudio de Commodore 64</comment>
+ <comment xml:lang="bg">Аудио — Commodore 64</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Commodore 64</comment>
+ <comment xml:lang="be">аўдыя Commodore 64</comment>
+ <comment xml:lang="ar">صوت Commodore 64</comment>
+ <comment xml:lang="af">Commodore 64-oudio</comment>
+ <magic>
+ <match type="string" value="PSID" offset="0"/>
</magic>
<glob pattern="*.sid"/>
<glob pattern="*.psid"/>
</mime-type>
<mime-type type="audio/x-adpcm">
<comment>PCM audio</comment>
- <comment xml:lang="ar">سمعي PCM</comment>
- <comment xml:lang="az">PCM audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo PCM</comment>
- <comment xml:lang="bg">Аудио — PCM</comment>
- <comment xml:lang="ca">àudio PCM</comment>
- <comment xml:lang="cs">zvuk PCM</comment>
- <comment xml:lang="cy">Sain PCM</comment>
- <comment xml:lang="da">PCM-lyd</comment>
- <comment xml:lang="de">PCM-Audio</comment>
- <comment xml:lang="el">Ήχος PCM</comment>
- <comment xml:lang="en_GB">PCM audio</comment>
- <comment xml:lang="eo">PCM-sondosiero</comment>
- <comment xml:lang="es">sonido PCM</comment>
- <comment xml:lang="eu">PCM audioa</comment>
- <comment xml:lang="fi">PCM-ääni</comment>
- <comment xml:lang="fo">PCM ljóður</comment>
- <comment xml:lang="fr">audio PCM</comment>
- <comment xml:lang="ga">fuaim PCM</comment>
- <comment xml:lang="gl">son PCM</comment>
- <comment xml:lang="he">שמע PCM</comment>
- <comment xml:lang="hr">PCM zvučni zapis</comment>
- <comment xml:lang="hu">PCM hang</comment>
- <comment xml:lang="ia">Audio PCM</comment>
- <comment xml:lang="id">Audio PCM</comment>
- <comment xml:lang="it">Audio PCM</comment>
- <comment xml:lang="ja">PCM オーディオ</comment>
- <comment xml:lang="kk">PCM аудиосы</comment>
- <comment xml:lang="ko">PCM 오디오</comment>
- <comment xml:lang="lt">PCM garso įrašas</comment>
- <comment xml:lang="lv">PCM audio</comment>
- <comment xml:lang="ms">Audio PCM</comment>
- <comment xml:lang="nb">PCM-lyd</comment>
- <comment xml:lang="nl">PCM-audio</comment>
- <comment xml:lang="nn">PCM-lyd</comment>
- <comment xml:lang="oc">àudio PCM</comment>
- <comment xml:lang="pl">Plik dźwiękowy PCM</comment>
- <comment xml:lang="pt">áudio PCM</comment>
- <comment xml:lang="pt_BR">Áudio PCM</comment>
- <comment xml:lang="ro">Audio PCM</comment>
- <comment xml:lang="ru">Аудио PCM</comment>
- <comment xml:lang="sk">Zvuk PCM</comment>
- <comment xml:lang="sl">Zvočna datoteka PCM</comment>
- <comment xml:lang="sq">Audio PCM</comment>
- <comment xml:lang="sr">ПЦМ звук</comment>
- <comment xml:lang="sv">PCM-ljud</comment>
- <comment xml:lang="tr">PCM sesi</comment>
- <comment xml:lang="uk">звук PCM</comment>
- <comment xml:lang="vi">Âm thanh PCM</comment>
- <comment xml:lang="zh_CN">PCM 音频</comment>
<comment xml:lang="zh_TW">PCM 音訊</comment>
- <magic priority="50">
- <match value=".snd" type="string" offset="0">
- <match value="23" type="big32" offset="12"/>
+ <comment xml:lang="zh_CN">PCM 音频</comment>
+ <comment xml:lang="vi">Âm thanh PCM</comment>
+ <comment xml:lang="uk">звук PCM</comment>
+ <comment xml:lang="tr">PCM sesi</comment>
+ <comment xml:lang="sv">PCM-ljud</comment>
+ <comment xml:lang="sr">ПЦМ звук</comment>
+ <comment xml:lang="sq">audio PCM</comment>
+ <comment xml:lang="sl">Zvočna datoteka PCM</comment>
+ <comment xml:lang="si">PCM ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk PCM</comment>
+ <comment xml:lang="ru">Аудио PCM</comment>
+ <comment xml:lang="ro">Audio PCM</comment>
+ <comment xml:lang="pt_BR">Áudio PCM</comment>
+ <comment xml:lang="pt">áudio PCM</comment>
+ <comment xml:lang="pl">Plik dźwiękowy PCM</comment>
+ <comment xml:lang="oc">àudio PCM</comment>
+ <comment xml:lang="nn">PCM-lyd</comment>
+ <comment xml:lang="nl">PCM-audio</comment>
+ <comment xml:lang="nb">PCM-lyd</comment>
+ <comment xml:lang="ms">Audio PCM</comment>
+ <comment xml:lang="lv">PCM audio</comment>
+ <comment xml:lang="lt">PCM garso įrašas</comment>
+ <comment xml:lang="ko">PCM 오디오</comment>
+ <comment xml:lang="kk">PCM аудиосы</comment>
+ <comment xml:lang="ja">PCM オーディオ</comment>
+ <comment xml:lang="it">Audio PCM</comment>
+ <comment xml:lang="is">PCM hljóðskrá</comment>
+ <comment xml:lang="id">Audio PCM</comment>
+ <comment xml:lang="ia">Audio PCM</comment>
+ <comment xml:lang="hu">PCM hang</comment>
+ <comment xml:lang="hr">PCM zvučni zapis</comment>
+ <comment xml:lang="he">שמע PCM</comment>
+ <comment xml:lang="gl">son PCM</comment>
+ <comment xml:lang="ga">fuaim PCM</comment>
+ <comment xml:lang="fur">audio PCM</comment>
+ <comment xml:lang="fr">audio PCM</comment>
+ <comment xml:lang="fo">PCM ljóður</comment>
+ <comment xml:lang="fi">PCM-ääni</comment>
+ <comment xml:lang="eu">PCM audioa</comment>
+ <comment xml:lang="es">sonido PCM</comment>
+ <comment xml:lang="eo">PCM-sondosiero</comment>
+ <comment xml:lang="en_GB">PCM audio</comment>
+ <comment xml:lang="el">Ήχος PCM</comment>
+ <comment xml:lang="de">PCM-Audio</comment>
+ <comment xml:lang="da">PCM-lyd</comment>
+ <comment xml:lang="cy">Sain PCM</comment>
+ <comment xml:lang="cs">zvuk PCM</comment>
+ <comment xml:lang="ca">àudio PCM</comment>
+ <comment xml:lang="bg">Аудио — PCM</comment>
+ <comment xml:lang="be@latin">Aŭdyjo PCM</comment>
+ <comment xml:lang="be">аўдыя PCM</comment>
+ <comment xml:lang="az">PCM audio faylı</comment>
+ <comment xml:lang="ar">صوت PCM</comment>
+ <comment xml:lang="af">PCM-oudio</comment>
+ <acronym>PCM</acronym>
+ <expanded-acronym>Pulse-code Modulation</expanded-acronym>
+ <magic>
+ <match type="string" value=".snd" offset="0">
+ <match type="big32" value="23" offset="12"/>
</match>
- <match value="0x0064732E" type="little32" offset="0">
- <match value="1" type="little32" offset="12"/>
- <match value="2" type="little32" offset="12"/>
- <match value="3" type="little32" offset="12"/>
- <match value="4" type="little32" offset="12"/>
- <match value="5" type="little32" offset="12"/>
- <match value="6" type="little32" offset="12"/>
- <match value="7" type="little32" offset="12"/>
- <match value="23" type="little32" offset="12"/>
+ <match type="little32" value="0x0064732E" offset="0">
+ <match type="little32" value="1" offset="12"/>
+ <match type="little32" value="2" offset="12"/>
+ <match type="little32" value="3" offset="12"/>
+ <match type="little32" value="4" offset="12"/>
+ <match type="little32" value="5" offset="12"/>
+ <match type="little32" value="6" offset="12"/>
+ <match type="little32" value="7" offset="12"/>
+ <match type="little32" value="23" offset="12"/>
</match>
</magic>
</mime-type>
<mime-type type="audio/x-aifc">
<comment>AIFC audio</comment>
- <comment xml:lang="ar">AIFC سمعي</comment>
- <comment xml:lang="az">AIFC audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo AIFC</comment>
- <comment xml:lang="bg">Аудио — AIFC</comment>
- <comment xml:lang="ca">àudio AIFC</comment>
- <comment xml:lang="cs">zvuk AIFC</comment>
- <comment xml:lang="cy">Sain AIFC</comment>
- <comment xml:lang="da">AIFC-lyd</comment>
- <comment xml:lang="de">AIFC-Audio</comment>
- <comment xml:lang="el">Ήχος AIFC</comment>
- <comment xml:lang="en_GB">AIFC audio</comment>
- <comment xml:lang="eo">AIFC-sondosiero</comment>
- <comment xml:lang="es">sonido AIFC</comment>
- <comment xml:lang="eu">AIFC audioa</comment>
- <comment xml:lang="fi">AIFC-ääni</comment>
- <comment xml:lang="fo">AIFC ljóður</comment>
- <comment xml:lang="fr">audio AIFC</comment>
- <comment xml:lang="ga">fuaim AIFC</comment>
- <comment xml:lang="gl">son AIFC</comment>
- <comment xml:lang="he">שמע AIFC</comment>
- <comment xml:lang="hr">AIFC zvučni zapis</comment>
- <comment xml:lang="hu">AIFC hang</comment>
- <comment xml:lang="ia">Audio AIFC</comment>
- <comment xml:lang="id">Audio AIFC</comment>
- <comment xml:lang="it">Audio AIFC</comment>
- <comment xml:lang="ja">AIFC オーディオ</comment>
- <comment xml:lang="ka">AIFC აუდიო</comment>
- <comment xml:lang="kk">AIFC аудиосы</comment>
- <comment xml:lang="ko">AIFC 오디오</comment>
- <comment xml:lang="lt">AIFC garso įrašas</comment>
- <comment xml:lang="lv">AIFC audio</comment>
- <comment xml:lang="ms">Audio AIFC</comment>
- <comment xml:lang="nb">AIFC-lyd</comment>
- <comment xml:lang="nl">AIFC-audio</comment>
- <comment xml:lang="nn">AIFC-lyd</comment>
- <comment xml:lang="oc">àudio AIFC</comment>
- <comment xml:lang="pl">Plik dźwiękowy AIFC</comment>
- <comment xml:lang="pt">áudio AIFC</comment>
- <comment xml:lang="pt_BR">Áudio AIFC</comment>
- <comment xml:lang="ro">Fișier audio AIFC</comment>
- <comment xml:lang="ru">Аудио AIFC</comment>
- <comment xml:lang="sk">Zvuk AIFC</comment>
- <comment xml:lang="sl">Zvočna datoteka AIFC</comment>
- <comment xml:lang="sq">Audio AIFC</comment>
- <comment xml:lang="sr">АИФЦ звук</comment>
- <comment xml:lang="sv">AIFC-ljud</comment>
- <comment xml:lang="tr">AIFC sesi</comment>
- <comment xml:lang="uk">звук AIFC</comment>
- <comment xml:lang="vi">Âm thanh AIFC</comment>
- <comment xml:lang="zh_CN">AIFC 音频</comment>
<comment xml:lang="zh_TW">AIFC 音訊</comment>
+ <comment xml:lang="zh_CN">AIFC 音频</comment>
+ <comment xml:lang="vi">Âm thanh AIFC</comment>
+ <comment xml:lang="uk">звук AIFC</comment>
+ <comment xml:lang="tr">AIFC sesi</comment>
+ <comment xml:lang="sv">AIFC-ljud</comment>
+ <comment xml:lang="sr">АИФЦ звук</comment>
+ <comment xml:lang="sq">audio AIFC</comment>
+ <comment xml:lang="sl">Zvočna datoteka AIFC</comment>
+ <comment xml:lang="si">AIFC ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk AIFC</comment>
+ <comment xml:lang="ru">Аудио AIFC</comment>
+ <comment xml:lang="ro">Fișier audio AIFC</comment>
+ <comment xml:lang="pt_BR">Áudio AIFC</comment>
+ <comment xml:lang="pt">áudio AIFC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy AIFC</comment>
+ <comment xml:lang="oc">àudio AIFC</comment>
+ <comment xml:lang="nn">AIFC-lyd</comment>
+ <comment xml:lang="nl">AIFC-audio</comment>
+ <comment xml:lang="nb">AIFC-lyd</comment>
+ <comment xml:lang="ms">Audio AIFC</comment>
+ <comment xml:lang="lv">AIFC audio</comment>
+ <comment xml:lang="lt">AIFC garso įrašas</comment>
+ <comment xml:lang="ko">AIFC 오디오</comment>
+ <comment xml:lang="kk">AIFC аудиосы</comment>
+ <comment xml:lang="ka">AIFC აუდიო</comment>
+ <comment xml:lang="ja">AIFC オーディオ</comment>
+ <comment xml:lang="it">Audio AIFC</comment>
+ <comment xml:lang="is">AIFC hljóðskrá</comment>
+ <comment xml:lang="id">Audio AIFC</comment>
+ <comment xml:lang="ia">Audio AIFC</comment>
+ <comment xml:lang="hu">AIFC hang</comment>
+ <comment xml:lang="hr">AIFC zvučni zapis</comment>
+ <comment xml:lang="he">שמע AIFC</comment>
+ <comment xml:lang="gl">son AIFC</comment>
+ <comment xml:lang="ga">fuaim AIFC</comment>
+ <comment xml:lang="fur">audio AIFC</comment>
+ <comment xml:lang="fr">audio AIFC</comment>
+ <comment xml:lang="fo">AIFC ljóður</comment>
+ <comment xml:lang="fi">AIFC-ääni</comment>
+ <comment xml:lang="eu">AIFC audioa</comment>
+ <comment xml:lang="es">sonido AIFC</comment>
+ <comment xml:lang="eo">AIFC-sondosiero</comment>
+ <comment xml:lang="en_GB">AIFC audio</comment>
+ <comment xml:lang="el">Ήχος AIFC</comment>
+ <comment xml:lang="de">AIFC-Audio</comment>
+ <comment xml:lang="da">AIFC-lyd</comment>
+ <comment xml:lang="cy">Sain AIFC</comment>
+ <comment xml:lang="cs">zvuk AIFC</comment>
+ <comment xml:lang="ca">àudio AIFC</comment>
+ <comment xml:lang="bg">Аудио — AIFC</comment>
+ <comment xml:lang="be@latin">Aŭdyjo AIFC</comment>
+ <comment xml:lang="be">аўдыя AIFC</comment>
+ <comment xml:lang="az">AIFC audio faylı</comment>
+ <comment xml:lang="ar">صوت AIFC</comment>
+ <comment xml:lang="af">AIFC-oudio</comment>
<acronym>AIFC</acronym>
<expanded-acronym>Audio Interchange File format Compressed</expanded-acronym>
<sub-class-of type="application/x-iff"/>
- <magic priority="50">
- <match value="AIFC" type="string" offset="8"/>
+ <magic>
+ <match type="string" value="AIFC" offset="8"/>
</magic>
<glob pattern="*.aifc"/>
<glob pattern="*.aiffc"/>
@@ -22615,535 +24496,762 @@
</mime-type>
<mime-type type="audio/x-aiff">
<comment>AIFF/Amiga/Mac audio</comment>
- <comment xml:lang="ar">AIFF/Amiga/Mac سمعي</comment>
- <comment xml:lang="az">AIFF/Amiga/Mac audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo AIFF/Amiga/Mac</comment>
- <comment xml:lang="bg">Аудио — AIFF/Amiga/Mac</comment>
- <comment xml:lang="ca">àudio AIFF/Amiga/Mac</comment>
- <comment xml:lang="cs">zvuk AIFF/Amiga/Mac</comment>
- <comment xml:lang="cy">Sain AIFF/Amiga/Mac</comment>
- <comment xml:lang="da">AIFF-/Amiga-/Maclyd</comment>
- <comment xml:lang="de">AIFF/Amiga/Mac-Audio</comment>
- <comment xml:lang="el">Ήχος AIFF/Amiga/Mac</comment>
- <comment xml:lang="en_GB">AIFF/Amiga/Mac audio</comment>
- <comment xml:lang="eo">AIFF/Amiga/Mac-sondosiero</comment>
- <comment xml:lang="es">sonido AIFF/Amiga/Mac</comment>
- <comment xml:lang="eu">AIFF/Amiga/Mac audioa</comment>
- <comment xml:lang="fi">AIFF/Amiga/Mac-ääni</comment>
- <comment xml:lang="fo">AIFF/Amiga/Mac ljóður</comment>
- <comment xml:lang="fr">audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="ga">fuaim AIFF/Amiga/Mac</comment>
- <comment xml:lang="gl">son AIFF/Amiga/Mac</comment>
- <comment xml:lang="he">שמע AIFF/Amiga/Mac</comment>
- <comment xml:lang="hr">AIFF/Amiga/Mac zvučni zapis</comment>
- <comment xml:lang="hu">AIFF/Amiga/Mac hang</comment>
- <comment xml:lang="ia">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="id">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="it">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="ja">AIFF/Amiga/Mac オーディオ</comment>
- <comment xml:lang="ka">AIFF/Amiga/Mac აუდიო</comment>
- <comment xml:lang="kk">AIFF/Amiga/Mac аудиосы</comment>
- <comment xml:lang="ko">AIFF/Amiga/Mac 오디오</comment>
- <comment xml:lang="lt">AIFF/Amiga/Mac garso įrašas</comment>
- <comment xml:lang="lv">AIFF/Amiga/Mac audio</comment>
- <comment xml:lang="ms">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="nb">AIFF/Amiga/Mac-lyd</comment>
- <comment xml:lang="nl">AIFF/Amiga/Mac-audio</comment>
- <comment xml:lang="nn">AIFF/Amiga/Mac-lyd</comment>
- <comment xml:lang="oc">àudio AIFF/Amiga/Mac</comment>
- <comment xml:lang="pl">Plik dźwiękowy AIFF/Amiga/Mac</comment>
- <comment xml:lang="pt">áudio AIFF/Amiga/Mac</comment>
- <comment xml:lang="pt_BR">Áudio AIFF/Amiga/Mac</comment>
- <comment xml:lang="ro">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="ru">Аудио AIFF/Amiga/Mac</comment>
- <comment xml:lang="sk">Zvuk AIFF/Amiga/Mac</comment>
- <comment xml:lang="sl">Zvočna datoteka AIFF/Amiga/Mac</comment>
- <comment xml:lang="sq">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="sr">АИФФ/Амига/Мекинтош звук</comment>
- <comment xml:lang="sv">AIFF/Amiga/Mac-ljud</comment>
- <comment xml:lang="tr">AIFF/Amiga/Mac sesi</comment>
- <comment xml:lang="uk">звук AIFF/Amiga/Mac</comment>
- <comment xml:lang="vi">Âm thanh AIFF/Amiga/Mac</comment>
- <comment xml:lang="zh_CN">AIFF/Amiga/Mac 音频</comment>
<comment xml:lang="zh_TW">AIFF/Amiga/Mac 音訊</comment>
+ <comment xml:lang="zh_CN">AIFF/Amiga/Mac 音频</comment>
+ <comment xml:lang="vi">Âm thanh AIFF/Amiga/Mac</comment>
+ <comment xml:lang="uk">звук AIFF/Amiga/Mac</comment>
+ <comment xml:lang="tr">AIFF/Amiga/Mac sesi</comment>
+ <comment xml:lang="sv">AIFF/Amiga/Mac-ljud</comment>
+ <comment xml:lang="sr">АИФФ/Амига/Мекинтош звук</comment>
+ <comment xml:lang="sq">audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="sl">Zvočna datoteka AIFF/Amiga/Mac</comment>
+ <comment xml:lang="si">AIFF/Amiga/Mac ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk AIFF/Amiga/Mac</comment>
+ <comment xml:lang="ru">Аудио AIFF/Amiga/Mac</comment>
+ <comment xml:lang="ro">Audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="pt_BR">Áudio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="pt">áudio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="pl">Plik dźwiękowy AIFF/Amiga/Mac</comment>
+ <comment xml:lang="oc">àudio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="nn">AIFF/Amiga/Mac-lyd</comment>
+ <comment xml:lang="nl">AIFF/Amiga/Mac-audio</comment>
+ <comment xml:lang="nb">AIFF/Amiga/Mac-lyd</comment>
+ <comment xml:lang="ms">Audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="lv">AIFF/Amiga/Mac audio</comment>
+ <comment xml:lang="lt">AIFF/Amiga/Mac garso įrašas</comment>
+ <comment xml:lang="ko">AIFF/Amiga/Mac 오디오</comment>
+ <comment xml:lang="kk">AIFF/Amiga/Mac аудиосы</comment>
+ <comment xml:lang="ka">AIFF/Amiga/Mac აუდიო</comment>
+ <comment xml:lang="ja">AIFF/Amiga/Mac オーディオ</comment>
+ <comment xml:lang="it">Audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="is">AIFF/Amiga/Mac hljóðskrá</comment>
+ <comment xml:lang="id">Audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="ia">Audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="hu">AIFF/Amiga/Mac hang</comment>
+ <comment xml:lang="hr">AIFF/Amiga/Mac zvučni zapis</comment>
+ <comment xml:lang="he">שמע AIFF/Amiga/Mac</comment>
+ <comment xml:lang="gl">son AIFF/Amiga/Mac</comment>
+ <comment xml:lang="ga">fuaim AIFF/Amiga/Mac</comment>
+ <comment xml:lang="fur">audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="fr">audio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="fo">AIFF/Amiga/Mac ljóður</comment>
+ <comment xml:lang="fi">AIFF/Amiga/Mac-ääni</comment>
+ <comment xml:lang="eu">AIFF/Amiga/Mac audioa</comment>
+ <comment xml:lang="es">sonido AIFF/Amiga/Mac</comment>
+ <comment xml:lang="eo">AIFF/Amiga/Mac-sondosiero</comment>
+ <comment xml:lang="en_GB">AIFF/Amiga/Mac audio</comment>
+ <comment xml:lang="el">Ήχος AIFF/Amiga/Mac</comment>
+ <comment xml:lang="de">AIFF/Amiga/Mac-Audio</comment>
+ <comment xml:lang="da">AIFF-/Amiga-/Mac-lyd</comment>
+ <comment xml:lang="cy">Sain AIFF/Amiga/Mac</comment>
+ <comment xml:lang="cs">zvuk AIFF/Amiga/Mac</comment>
+ <comment xml:lang="ca">àudio AIFF/Amiga/Mac</comment>
+ <comment xml:lang="bg">Аудио — AIFF/Amiga/Mac</comment>
+ <comment xml:lang="be@latin">Aŭdyjo AIFF/Amiga/Mac</comment>
+ <comment xml:lang="be">аўдыя AIFF/Amiga/Mac</comment>
+ <comment xml:lang="az">AIFF/Amiga/Mac audio faylı</comment>
+ <comment xml:lang="ar">صوت AIFF/Amiga/Mac</comment>
+ <comment xml:lang="af">AIFF/Amiga/Mac-oudio</comment>
<acronym>AIFF</acronym>
<expanded-acronym>Audio Interchange File Format</expanded-acronym>
<sub-class-of type="application/x-iff"/>
- <magic priority="50">
- <match value="AIFF" type="string" offset="8"/>
- <match value="8SVX" type="string" offset="8"/>
+ <magic>
+ <match type="string" value="AIFF" offset="8"/>
+ <match type="string" value="8SVX" offset="8"/>
</magic>
<glob pattern="*.aiff"/>
<glob pattern="*.aif"/>
</mime-type>
<mime-type type="audio/x-ape">
<comment>Monkey's audio</comment>
- <comment xml:lang="ar">Monkey سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Monkey's</comment>
- <comment xml:lang="bg">Аудио — Monkey</comment>
- <comment xml:lang="ca">àudio de Monkey</comment>
- <comment xml:lang="cs">zvuk Monkey's</comment>
- <comment xml:lang="da">Monkeys lyd</comment>
- <comment xml:lang="de">Monkey's-Audio</comment>
- <comment xml:lang="el">Ήχος Monkey's</comment>
- <comment xml:lang="en_GB">Monkey's audio</comment>
- <comment xml:lang="es">sonido de Monkey</comment>
- <comment xml:lang="eu">Monkey audioa</comment>
- <comment xml:lang="fi">Monkey's Audio -ääni</comment>
- <comment xml:lang="fo">Monkey's ljóður</comment>
- <comment xml:lang="fr">audio Monkey</comment>
- <comment xml:lang="ga">fuaim Monkey's</comment>
- <comment xml:lang="gl">son de Monkey</comment>
- <comment xml:lang="he">שמע של Monkey's</comment>
- <comment xml:lang="hr">Monkey zvučni zapis</comment>
- <comment xml:lang="hu">Monkey hang</comment>
- <comment xml:lang="ia">Audio Monkey's</comment>
- <comment xml:lang="id">Audio Monkey</comment>
- <comment xml:lang="it">Audio Monkey's</comment>
- <comment xml:lang="ja">Monkey's オーディオ</comment>
- <comment xml:lang="kk">Monkey аудиосы</comment>
- <comment xml:lang="ko">Monkey's 오디오</comment>
- <comment xml:lang="lt">Monkey garso įrašas</comment>
- <comment xml:lang="lv">Monkey's audio</comment>
- <comment xml:lang="nb">Monkey's-lyd</comment>
- <comment xml:lang="nl">Monkey's-audio</comment>
- <comment xml:lang="nn">Monkey's Audio-lyd</comment>
- <comment xml:lang="oc">àudio Monkey</comment>
- <comment xml:lang="pl">Plik dźwiękowy Monkey's Audio</comment>
- <comment xml:lang="pt">áudio Monkey</comment>
- <comment xml:lang="pt_BR">Áudio Monkey's</comment>
- <comment xml:lang="ro">Audio Monkey's</comment>
- <comment xml:lang="ru">Аудио Monkey's</comment>
- <comment xml:lang="sk">Zvuk Monkey's</comment>
- <comment xml:lang="sl">Zvočna datoteka Monkey</comment>
- <comment xml:lang="sq">Audio Monkey's</comment>
- <comment xml:lang="sr">Монкијев звук</comment>
- <comment xml:lang="sv">Monkey's audio</comment>
- <comment xml:lang="tr">Monkey's sesi</comment>
- <comment xml:lang="uk">звук Monkey's</comment>
- <comment xml:lang="vi">Âm thanh cua Monkey</comment>
- <comment xml:lang="zh_CN">Monkey's Audio 音频</comment>
<comment xml:lang="zh_TW">Monkey's 音訊</comment>
- <magic priority="50">
- <match value="MAC " type="string" offset="0"/>
+ <comment xml:lang="zh_CN">Monkey's Audio 音频</comment>
+ <comment xml:lang="vi">Âm thanh cua Monkey</comment>
+ <comment xml:lang="uk">звук Monkey's</comment>
+ <comment xml:lang="tr">Monkey's sesi</comment>
+ <comment xml:lang="sv">Monkey's audio</comment>
+ <comment xml:lang="sr">Монкијев звук</comment>
+ <comment xml:lang="sq">audio Monkey's</comment>
+ <comment xml:lang="sl">Zvočna datoteka Monkey</comment>
+ <comment xml:lang="si">වඳුරාගේ හඬ පටය</comment>
+ <comment xml:lang="sk">Zvuk Monkey's</comment>
+ <comment xml:lang="ru">Аудио Monkey's</comment>
+ <comment xml:lang="ro">Audio Monkey's</comment>
+ <comment xml:lang="pt_BR">Áudio Monkey's</comment>
+ <comment xml:lang="pt">áudio Monkey</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Monkey's Audio</comment>
+ <comment xml:lang="oc">àudio Monkey</comment>
+ <comment xml:lang="nn">Monkey's Audio-lyd</comment>
+ <comment xml:lang="nl">Monkey's-audio</comment>
+ <comment xml:lang="nb">Monkey's-lyd</comment>
+ <comment xml:lang="lv">Monkey's audio</comment>
+ <comment xml:lang="lt">Monkey garso įrašas</comment>
+ <comment xml:lang="ko">Monkey's 오디오</comment>
+ <comment xml:lang="kk">Monkey аудиосы</comment>
+ <comment xml:lang="ja">Monkey's オーディオ</comment>
+ <comment xml:lang="it">Audio Monkey's</comment>
+ <comment xml:lang="is">Monkey's hljóðskrá</comment>
+ <comment xml:lang="id">Audio Monkey</comment>
+ <comment xml:lang="ia">Audio Monkey's</comment>
+ <comment xml:lang="hu">Monkey hang</comment>
+ <comment xml:lang="hr">Monkey zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Monkey's</comment>
+ <comment xml:lang="gl">son de Monkey</comment>
+ <comment xml:lang="ga">fuaim Monkey's</comment>
+ <comment xml:lang="fur">audio Monkey's</comment>
+ <comment xml:lang="fr">audio Monkey</comment>
+ <comment xml:lang="fo">Monkey's ljóður</comment>
+ <comment xml:lang="fi">Monkey's Audio -ääni</comment>
+ <comment xml:lang="eu">Monkey audioa</comment>
+ <comment xml:lang="es">sonido de Monkey</comment>
+ <comment xml:lang="en_GB">Monkey's audio</comment>
+ <comment xml:lang="el">Ήχος Monkey's</comment>
+ <comment xml:lang="de">Monkey's-Audio</comment>
+ <comment xml:lang="da">Monkey's-lyd</comment>
+ <comment xml:lang="cs">zvuk Monkey's</comment>
+ <comment xml:lang="ca">àudio de Monkey</comment>
+ <comment xml:lang="bg">Аудио — Monkey</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Monkey's</comment>
+ <comment xml:lang="be">аўдыя Monkey's</comment>
+ <comment xml:lang="ar">صوت Monkey</comment>
+ <magic>
+ <match type="string" value="MAC " offset="0"/>
</magic>
<glob pattern="*.ape"/>
</mime-type>
<mime-type type="audio/x-pn-audibleaudio">
<comment>Audible.Com audio</comment>
- <comment xml:lang="ca">àudio Audible.Com</comment>
- <comment xml:lang="cs">zvuk Audible.Com</comment>
- <comment xml:lang="de">Audible.Com-Audio</comment>
- <comment xml:lang="en_GB">Audible.Com audio</comment>
- <comment xml:lang="es">sonido de Audible.com</comment>
- <comment xml:lang="hr">Audible.Com zvučni zapis</comment>
- <comment xml:lang="hu">Audible.Com hang</comment>
- <comment xml:lang="id">Audio Audible.Com</comment>
- <comment xml:lang="it">Audio Audible.Com</comment>
- <comment xml:lang="kk">Audible.Com аудиосы</comment>
- <comment xml:lang="ko">Audible.Com 오디오</comment>
- <comment xml:lang="pl">Plik dźwiękowy Audible.com</comment>
- <comment xml:lang="pt_BR">Áudio de audible.com</comment>
- <comment xml:lang="ru">Аудио Audible.Com</comment>
- <comment xml:lang="sk">Audio Audible.Com</comment>
- <comment xml:lang="sv">Audible.Com-ljud</comment>
- <comment xml:lang="uk">звук Audible.Com</comment>
- <comment xml:lang="zh_CN">Audible.Com 音频</comment>
<comment xml:lang="zh_TW">Audible.Com 音訊</comment>
- <magic priority="50">
-
- <match value="1469084982" type="big32" offset="4"/>
- <match value="aax " type="string" offset="8"/>
+ <comment xml:lang="zh_CN">Audible.Com 音频</comment>
+ <comment xml:lang="uk">звук Audible.Com</comment>
+ <comment xml:lang="tr">Audible.Com sesi</comment>
+ <comment xml:lang="sv">Audible.Com-ljud</comment>
+ <comment xml:lang="sq">audio Audible.Com</comment>
+ <comment xml:lang="sl">Zvok Audible.Com</comment>
+ <comment xml:lang="si">Audible.Com ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Audio Audible.Com</comment>
+ <comment xml:lang="ru">Аудио Audible.Com</comment>
+ <comment xml:lang="pt_BR">Áudio de audible.com</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Audible.com</comment>
+ <comment xml:lang="nl">Audible.com-audio</comment>
+ <comment xml:lang="ko">Audible.Com 오디오</comment>
+ <comment xml:lang="kk">Audible.Com аудиосы</comment>
+ <comment xml:lang="ja">Audible.Com オーディオ</comment>
+ <comment xml:lang="it">Audio Audible.Com</comment>
+ <comment xml:lang="is">Audible.Com hljóðskrá</comment>
+ <comment xml:lang="id">Audio Audible.Com</comment>
+ <comment xml:lang="hu">Audible.Com hang</comment>
+ <comment xml:lang="hr">Audible.Com zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Audible.Com</comment>
+ <comment xml:lang="ga">fuaim Audible.Com</comment>
+ <comment xml:lang="fur">audio Audible.Com</comment>
+ <comment xml:lang="fr">audio Audible.Com</comment>
+ <comment xml:lang="fi">Audible.Com-ääni</comment>
+ <comment xml:lang="eu">Audible.Com audioa</comment>
+ <comment xml:lang="es">sonido de Audible.com</comment>
+ <comment xml:lang="en_GB">Audible.Com audio</comment>
+ <comment xml:lang="de">Audible.com-Audio</comment>
+ <comment xml:lang="da">Audible.Com-lyd</comment>
+ <comment xml:lang="cs">zvuk Audible.Com</comment>
+ <comment xml:lang="ca">àudio d'Audible.Com</comment>
+ <comment xml:lang="bg">Аудио — Audible.Com</comment>
+ <comment xml:lang="be">аўдыя Audible.Com</comment>
+ <comment xml:lang="ar">صوت Audible.Com</comment>
+ <magic>
+ <!-- https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/aadec.c#L33 -->
+ <match type="big32" value="1469084982" offset="4"/>
</magic>
<glob pattern="*.aa"/>
- <glob pattern="*.aax"/>
<alias type="audio/vnd.audible"/>
- <alias type="audio/vnd.audible.aax"/>
+ </mime-type>
+ <mime-type type="audio/vnd.audible.aax">
+ <comment>Audible Enhanced audio</comment>
+ <comment xml:lang="zh_CN">Audible 增强音频</comment>
+ <comment xml:lang="uk">звук Audible Enhanced</comment>
+ <comment xml:lang="tr">Audible Enhanced sesi</comment>
+ <comment xml:lang="sv">Audible förbättrat ljud</comment>
+ <comment xml:lang="si">ශ්‍රවණය කළ හැකි වැඩිදියුණු කළ ශ්‍රව්‍ය</comment>
+ <comment xml:lang="ru">Аудио Audible Enhanced</comment>
+ <comment xml:lang="pt_BR">Áudio Audible Enhanced</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Audible Enhanced</comment>
+ <comment xml:lang="nl">Audible verbeterde-audio</comment>
+ <comment xml:lang="ko">Audible 확장된 오디오</comment>
+ <comment xml:lang="kk">Audible Enhanced аудиосы</comment>
+ <comment xml:lang="ja">Audible エンハンスオーディオ</comment>
+ <comment xml:lang="it">Audio Audible Enhanced</comment>
+ <comment xml:lang="is">Audible Enhanced hljóðskrá</comment>
+ <comment xml:lang="id">audio Audible Enhanced</comment>
+ <comment xml:lang="hu">Audible Enhanced hang</comment>
+ <comment xml:lang="hr">Audible poboljšani zvučni zapis</comment>
+ <comment xml:lang="he">שמע Audible Enhanced</comment>
+ <comment xml:lang="fr">Audio amélioré Audible</comment>
+ <comment xml:lang="fi">Audible Enhanced -ääni</comment>
+ <comment xml:lang="es">sonido mejorado de Audible</comment>
+ <comment xml:lang="en_GB">Audible Enhanced audio</comment>
+ <comment xml:lang="de">Audible verbessertes Audio</comment>
+ <comment xml:lang="da">Audible Enhanced-lyd</comment>
+ <comment xml:lang="ca">àudio d'Audible Enhanced</comment>
+ <comment xml:lang="be">аўдыя Audible Enhanced</comment>
+ <comment xml:lang="ar">صوت محسن مسموع</comment>
+ <magic>
+ <match type="string" value="ftypaax " offset="4"/>
+ </magic>
+ <glob pattern="*.aax"/>
+ </mime-type>
+ <mime-type type="audio/vnd.audible.aaxc">
+ <comment>Audible Enhanced audio</comment>
+ <comment xml:lang="zh_CN">Audible 增强音频</comment>
+ <comment xml:lang="uk">звук Audible Enhanced</comment>
+ <comment xml:lang="tr">Audible Enhanced sesi</comment>
+ <comment xml:lang="sv">Audible förbättrat ljud</comment>
+ <comment xml:lang="si">ශ්‍රවණය කළ හැකි වැඩිදියුණු කළ ශ්‍රව්‍ය</comment>
+ <comment xml:lang="ru">Аудио Audible Enhanced</comment>
+ <comment xml:lang="pt_BR">Áudio Audible Enhanced</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Audible Enhanced</comment>
+ <comment xml:lang="nl">Audible verbeterde-audio</comment>
+ <comment xml:lang="ko">Audible 확장된 오디오</comment>
+ <comment xml:lang="kk">Audible Enhanced аудиосы</comment>
+ <comment xml:lang="ja">Audible エンハンスオーディオ</comment>
+ <comment xml:lang="it">Audio Audible Enhanced</comment>
+ <comment xml:lang="is">Audible Enhanced hljóðskrá</comment>
+ <comment xml:lang="id">audio Audible Enhanced</comment>
+ <comment xml:lang="hu">Audible Enhanced hang</comment>
+ <comment xml:lang="hr">Audible poboljšani zvučni zapis</comment>
+ <comment xml:lang="he">שמע Audible Enhanced</comment>
+ <comment xml:lang="fr">Audio amélioré Audible</comment>
+ <comment xml:lang="fi">Audible Enhanced -ääni</comment>
+ <comment xml:lang="es">sonido mejorado de Audible</comment>
+ <comment xml:lang="en_GB">Audible Enhanced audio</comment>
+ <comment xml:lang="de">Audible verbessertes Audio</comment>
+ <comment xml:lang="da">Audible Enhanced-lyd</comment>
+ <comment xml:lang="ca">àudio d'Audible Enhanced</comment>
+ <comment xml:lang="be">аўдыя Audible Enhanced</comment>
+ <comment xml:lang="ar">صوت محسن مسموع</comment>
+ <magic priority="50">
+ <match type="string" value="ftypaaxc" offset="4"/>
+ </magic>
+ <glob pattern="*.aaxc"/>
+ </mime-type>
+ <mime-type type="audio/x-dff">
+ <comment>DSDIFF audio</comment>
+ <comment xml:lang="zh_TW">DSDIFF 音訊</comment>
+ <comment xml:lang="zh_CN">DSDIFF 音频</comment>
+ <comment xml:lang="uk">звукові дані DSDIFF</comment>
+ <comment xml:lang="tr">DSDIFF sesi</comment>
+ <comment xml:lang="sv">DSDIFF-ljud</comment>
+ <comment xml:lang="sl">Zvok DSDIFF</comment>
+ <comment xml:lang="si">DSDIFF ශ්රව්ය</comment>
+ <comment xml:lang="ru">Аудио DSDIFF</comment>
+ <comment xml:lang="pt_BR">Áudio DSDIFF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy DSDIFF</comment>
+ <comment xml:lang="nl">DSDIFF-audio</comment>
+ <comment xml:lang="ko">DSDIFF 오디오</comment>
+ <comment xml:lang="kk">DSDIFF аудиосы</comment>
+ <comment xml:lang="ja">DSDIFF オーディオ</comment>
+ <comment xml:lang="it">Audio DSDIFF</comment>
+ <comment xml:lang="hr">DSDIFF zvučni zapis</comment>
+ <comment xml:lang="fi">DSDIFF-ääni</comment>
+ <comment xml:lang="eu">DSDIFF audioa</comment>
+ <comment xml:lang="es">sonido DSDIFF</comment>
+ <comment xml:lang="en_GB">DSDIFF audio</comment>
+ <comment xml:lang="de">DSDIFF-Audio</comment>
+ <comment xml:lang="be">аўдыя DSDIFF</comment>
+ <comment xml:lang="ar">صوت DSDIFF</comment>
+ <acronym>DSDIFF</acronym>
+ <expanded-acronym>Direct Stream Digital Interchange File Format</expanded-acronym>
+ <magic>
+ <!-- from https://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf -->
+ <match value="FRM8" type="string" offset="0">
+ <match value="DSD " type="string" offset="12"/>
+ </match>
+ </magic>
+ <glob pattern="*.dff"/>
+ <alias type="audio/dff"/>
+ </mime-type>
+ <mime-type type="audio/x-dsf">
+ <comment>DSF audio</comment>
+ <comment xml:lang="zh_TW">DSF 音訊</comment>
+ <comment xml:lang="zh_CN">DSF 音频</comment>
+ <comment xml:lang="uk">звукові дані DSF</comment>
+ <comment xml:lang="tr">DSF sesi</comment>
+ <comment xml:lang="sv">DSF-ljud</comment>
+ <comment xml:lang="sl">Zvok DSF</comment>
+ <comment xml:lang="si">DSF ශ්‍රව්‍ය</comment>
+ <comment xml:lang="ru">Аудио DSF</comment>
+ <comment xml:lang="pt_BR">Áudio DSF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy DSF</comment>
+ <comment xml:lang="nl">DSF-audio</comment>
+ <comment xml:lang="ko">DSF 오디오</comment>
+ <comment xml:lang="kk">DSF аудиосы</comment>
+ <comment xml:lang="ja">DSF オーディオ</comment>
+ <comment xml:lang="it">Audio DSF</comment>
+ <comment xml:lang="hr">DSF zvučni zapis</comment>
+ <comment xml:lang="gl">Son DSF</comment>
+ <comment xml:lang="fi">DSF-ääni</comment>
+ <comment xml:lang="eu">DSF audioa</comment>
+ <comment xml:lang="es">sonido DSF</comment>
+ <comment xml:lang="en_GB">DSF audio</comment>
+ <comment xml:lang="de">DSF-Audio</comment>
+ <comment xml:lang="be">аўдыя DSF</comment>
+ <comment xml:lang="ar">صوت DSF</comment>
+ <acronym>DSF</acronym>
+ <expanded-acronym>Direct stream digital Stream File</expanded-acronym>
+ <magic>
+ <!-- from https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf -->
+ <match value="DSD " type="string" offset="0">
+ <match value="fmt " type="string" offset="28">
+ <match value="data" type="string" offset="80"/>
+ </match>
+ </match>
+ </magic>
+ <glob pattern="*.dsf"/>
+ <alias type="audio/dsf"/>
+ <!-- Problematic because some clients expect these mime types to be DSDIFF files -->
+ <alias type="audio/x-dsd"/>
+ <alias type="audio/dsd"/>
</mime-type>
<mime-type type="audio/x-it">
<comment>Impulse Tracker audio</comment>
- <comment xml:lang="ar">Impulse Tracker سمعي</comment>
- <comment xml:lang="az">Impulse Tracker audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo Impulse Tracker</comment>
- <comment xml:lang="bg">Аудио — Impulse Tracker</comment>
- <comment xml:lang="ca">àudio d'Impulse Tracker</comment>
- <comment xml:lang="cs">zvuk Impulse Tracker</comment>
- <comment xml:lang="cy">Sain Impulse Tracker</comment>
- <comment xml:lang="da">Impulse Tracker-lyd</comment>
- <comment xml:lang="de">Impulse-Tracker-Audio</comment>
- <comment xml:lang="el">Ήχος Impulse Tracker</comment>
- <comment xml:lang="en_GB">Impulse Tracker audio</comment>
- <comment xml:lang="eo">Sondosiero de Impulse Tracker</comment>
- <comment xml:lang="es">sonido de Impulse Tracker</comment>
- <comment xml:lang="eu">Impulse Tracker audioa</comment>
- <comment xml:lang="fi">Impulse Tracker -ääni</comment>
- <comment xml:lang="fo">Impulse Tracker ljóður</comment>
- <comment xml:lang="fr">audio Impulse Tracker</comment>
- <comment xml:lang="ga">fuaim Impulse Tracker</comment>
- <comment xml:lang="gl">son de Impulse Tracker</comment>
- <comment xml:lang="he">שמע של Impulse Tracker</comment>
- <comment xml:lang="hr">Impulse Tracker zvučni zapis</comment>
- <comment xml:lang="hu">Impulse Tracker hang</comment>
- <comment xml:lang="ia">Audio Impulse Tracker</comment>
- <comment xml:lang="id">Audio Impulse Tracker</comment>
- <comment xml:lang="it">Audio Impulse Tracker</comment>
- <comment xml:lang="ja">Impulse Tracker オーディオ</comment>
- <comment xml:lang="kk">Impulse Tracker аудиосы</comment>
- <comment xml:lang="ko">Impulse Tracker 오디오</comment>
- <comment xml:lang="lt">Impulse Tracker garso įrašas</comment>
- <comment xml:lang="lv">Impulse Tracker audio</comment>
- <comment xml:lang="ms">Audio Impulse Tracker</comment>
- <comment xml:lang="nb">Impulse Tracker-lyd</comment>
- <comment xml:lang="nl">Impulse Tracker-audio</comment>
- <comment xml:lang="nn">Impulse Tracker lyd</comment>
- <comment xml:lang="oc">àudio Impulse Tracker</comment>
- <comment xml:lang="pl">Plik dźwiękowy Impulse Tracker</comment>
- <comment xml:lang="pt">áudio Impulse Tracker</comment>
- <comment xml:lang="pt_BR">Áudio Impulse Tracker</comment>
- <comment xml:lang="ro">Audio Impulse Tracker</comment>
- <comment xml:lang="ru">Аудио Impulse Tracker</comment>
- <comment xml:lang="sk">Zvuk Impulse Tracker</comment>
- <comment xml:lang="sl">Zvočna datoteka Impulse Tracker</comment>
- <comment xml:lang="sq">Audio Impulse Tracker</comment>
- <comment xml:lang="sr">звук Пратиоца Импулса</comment>
- <comment xml:lang="sv">Impulse Tracker-ljud</comment>
- <comment xml:lang="tr">Impulse Tracker sesi</comment>
- <comment xml:lang="uk">звук Impulse Tracker</comment>
- <comment xml:lang="vi">Âm thanh Impulse Tracker</comment>
- <comment xml:lang="zh_CN">Impulse Tracker 音频</comment>
<comment xml:lang="zh_TW">Impulse Tracker 音訊</comment>
- <magic priority="50">
- <match value="IMPM" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">Impulse Tracker 音频</comment>
+ <comment xml:lang="vi">Âm thanh Impulse Tracker</comment>
+ <comment xml:lang="uk">звук Impulse Tracker</comment>
+ <comment xml:lang="tr">Impulse Tracker sesi</comment>
+ <comment xml:lang="sv">Impulse Tracker-ljud</comment>
+ <comment xml:lang="sr">звук Пратиоца Импулса</comment>
+ <comment xml:lang="sq">audio Impulse Tracker</comment>
+ <comment xml:lang="sl">Zvočna datoteka Impulse Tracker</comment>
+ <comment xml:lang="si">Impulse Tracker ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk Impulse Tracker</comment>
+ <comment xml:lang="ru">Аудио Impulse Tracker</comment>
+ <comment xml:lang="ro">Audio Impulse Tracker</comment>
+ <comment xml:lang="pt_BR">Áudio Impulse Tracker</comment>
+ <comment xml:lang="pt">áudio Impulse Tracker</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Impulse Tracker</comment>
+ <comment xml:lang="oc">àudio Impulse Tracker</comment>
+ <comment xml:lang="nn">Impulse Tracker lyd</comment>
+ <comment xml:lang="nl">Impulse Tracker-audio</comment>
+ <comment xml:lang="nb">Impulse Tracker-lyd</comment>
+ <comment xml:lang="ms">Audio Impulse Tracker</comment>
+ <comment xml:lang="lv">Impulse Tracker audio</comment>
+ <comment xml:lang="lt">Impulse Tracker garso įrašas</comment>
+ <comment xml:lang="ko">Impulse Tracker 오디오</comment>
+ <comment xml:lang="kk">Impulse Tracker аудиосы</comment>
+ <comment xml:lang="ja">Impulse Tracker オーディオ</comment>
+ <comment xml:lang="it">Audio Impulse Tracker</comment>
+ <comment xml:lang="is">Impulse Tracker hljóðskrá</comment>
+ <comment xml:lang="id">Audio Impulse Tracker</comment>
+ <comment xml:lang="ia">Audio Impulse Tracker</comment>
+ <comment xml:lang="hu">Impulse Tracker hang</comment>
+ <comment xml:lang="hr">Impulse Tracker zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Impulse Tracker</comment>
+ <comment xml:lang="gl">son de Impulse Tracker</comment>
+ <comment xml:lang="ga">fuaim Impulse Tracker</comment>
+ <comment xml:lang="fur">audio Impulse Tracker</comment>
+ <comment xml:lang="fr">audio Impulse Tracker</comment>
+ <comment xml:lang="fo">Impulse Tracker ljóður</comment>
+ <comment xml:lang="fi">Impulse Tracker -ääni</comment>
+ <comment xml:lang="eu">Impulse Tracker audioa</comment>
+ <comment xml:lang="es">sonido de Impulse Tracker</comment>
+ <comment xml:lang="eo">Sondosiero de Impulse Tracker</comment>
+ <comment xml:lang="en_GB">Impulse Tracker audio</comment>
+ <comment xml:lang="el">Ήχος Impulse Tracker</comment>
+ <comment xml:lang="de">Impulse-Tracker-Audio</comment>
+ <comment xml:lang="da">Impulse Tracker-lyd</comment>
+ <comment xml:lang="cy">Sain Impulse Tracker</comment>
+ <comment xml:lang="cs">zvuk Impulse Tracker</comment>
+ <comment xml:lang="ca">àudio d'Impulse Tracker</comment>
+ <comment xml:lang="bg">Аудио — Impulse Tracker</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Impulse Tracker</comment>
+ <comment xml:lang="be">аўдыя Impulse Tracker</comment>
+ <comment xml:lang="az">Impulse Tracker audio faylı</comment>
+ <comment xml:lang="ar">صوت Impulse Tracker</comment>
+ <magic>
+ <match type="string" value="IMPM" offset="0"/>
</magic>
<glob pattern="*.it"/>
</mime-type>
<mime-type type="audio/flac">
<comment>FLAC audio</comment>
- <comment xml:lang="ar">FLAC سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo FLAC</comment>
- <comment xml:lang="bg">Аудио — FLAC</comment>
- <comment xml:lang="ca">àudio FLAC</comment>
- <comment xml:lang="cs">zvuk FLAC</comment>
- <comment xml:lang="da">FLAC-lyd</comment>
- <comment xml:lang="de">FLAC-Audio</comment>
- <comment xml:lang="el">Ήχος FLAC</comment>
- <comment xml:lang="en_GB">FLAC audio</comment>
- <comment xml:lang="eo">FLAC-sondosiero</comment>
- <comment xml:lang="es">sonido FLAC</comment>
- <comment xml:lang="eu">FLAC audioa</comment>
- <comment xml:lang="fi">FLAC-ääni</comment>
- <comment xml:lang="fo">FLAC ljóður</comment>
- <comment xml:lang="fr">audio FLAC</comment>
- <comment xml:lang="ga">fuaim FLAC</comment>
- <comment xml:lang="gl">son FLAC</comment>
- <comment xml:lang="he">קובץ שמע מסוג FLAC</comment>
- <comment xml:lang="hr">FLAC zvučni zapis</comment>
- <comment xml:lang="hu">FLAC hang</comment>
- <comment xml:lang="ia">Audio FLAC</comment>
- <comment xml:lang="id">Audio FLAC</comment>
- <comment xml:lang="it">Audio FLAC</comment>
- <comment xml:lang="ja">FLAC オーディオ</comment>
- <comment xml:lang="ka">FLAC აუდიო</comment>
- <comment xml:lang="kk">FLAC аудиосы</comment>
- <comment xml:lang="ko">FLAC 오디오</comment>
- <comment xml:lang="lt">FLAC garso įrašas</comment>
- <comment xml:lang="lv">FLAC audio</comment>
- <comment xml:lang="ms">Audio FLAC</comment>
- <comment xml:lang="nb">FLAC-lyd</comment>
- <comment xml:lang="nl">FLAC-audio</comment>
- <comment xml:lang="nn">FLAC-lyd</comment>
- <comment xml:lang="oc">àudio FLAC</comment>
- <comment xml:lang="pl">Plik dźwiękowy FLAC</comment>
- <comment xml:lang="pt">áudio FLAC</comment>
- <comment xml:lang="pt_BR">Áudio FLAC</comment>
- <comment xml:lang="ro">Audio FLAC</comment>
- <comment xml:lang="ru">Аудио FLAC</comment>
- <comment xml:lang="sk">Zvuk FLAC</comment>
- <comment xml:lang="sl">Zvočna datoteka Flac</comment>
- <comment xml:lang="sq">Audio FLAC</comment>
- <comment xml:lang="sr">ФЛАЦ звук</comment>
- <comment xml:lang="sv">FLAC-ljud</comment>
- <comment xml:lang="tr">FLAC sesi</comment>
- <comment xml:lang="uk">звук FLAC</comment>
- <comment xml:lang="vi">Âm thanh FLAC</comment>
- <comment xml:lang="zh_CN">FLAC 音频</comment>
<comment xml:lang="zh_TW">FLAC 音訊</comment>
- <magic priority="50">
+ <comment xml:lang="zh_CN">FLAC 音频</comment>
+ <comment xml:lang="vi">Âm thanh FLAC</comment>
+ <comment xml:lang="uk">звук FLAC</comment>
+ <comment xml:lang="tr">FLAC sesi</comment>
+ <comment xml:lang="sv">FLAC-ljud</comment>
+ <comment xml:lang="sr">ФЛАЦ звук</comment>
+ <comment xml:lang="sq">audio FLAC</comment>
+ <comment xml:lang="sl">Zvočna datoteka Flac</comment>
+ <comment xml:lang="si">FLAC ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk FLAC</comment>
+ <comment xml:lang="ru">Аудио FLAC</comment>
+ <comment xml:lang="ro">Audio FLAC</comment>
+ <comment xml:lang="pt_BR">Áudio FLAC</comment>
+ <comment xml:lang="pt">áudio FLAC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy FLAC</comment>
+ <comment xml:lang="oc">àudio FLAC</comment>
+ <comment xml:lang="nn">FLAC-lyd</comment>
+ <comment xml:lang="nl">FLAC-audio</comment>
+ <comment xml:lang="nb">FLAC-lyd</comment>
+ <comment xml:lang="ms">Audio FLAC</comment>
+ <comment xml:lang="lv">FLAC audio</comment>
+ <comment xml:lang="lt">FLAC garso įrašas</comment>
+ <comment xml:lang="ko">FLAC 오디오</comment>
+ <comment xml:lang="kk">FLAC аудиосы</comment>
+ <comment xml:lang="ka">FLAC აუდიო</comment>
+ <comment xml:lang="ja">FLAC オーディオ</comment>
+ <comment xml:lang="it">Audio FLAC</comment>
+ <comment xml:lang="is">FLAC hljóðskrá</comment>
+ <comment xml:lang="id">Audio FLAC</comment>
+ <comment xml:lang="ia">Audio FLAC</comment>
+ <comment xml:lang="hu">FLAC hang</comment>
+ <comment xml:lang="hr">FLAC zvučni zapis</comment>
+ <comment xml:lang="he">קובץ שמע מסוג FLAC</comment>
+ <comment xml:lang="gl">son FLAC</comment>
+ <comment xml:lang="ga">fuaim FLAC</comment>
+ <comment xml:lang="fur">audio FLAC</comment>
+ <comment xml:lang="fr">audio FLAC</comment>
+ <comment xml:lang="fo">FLAC ljóður</comment>
+ <comment xml:lang="fi">FLAC-ääni</comment>
+ <comment xml:lang="eu">FLAC audioa</comment>
+ <comment xml:lang="es">sonido FLAC</comment>
+ <comment xml:lang="eo">FLAC-sondosiero</comment>
+ <comment xml:lang="en_GB">FLAC audio</comment>
+ <comment xml:lang="el">Ήχος FLAC</comment>
+ <comment xml:lang="de">FLAC-Audio</comment>
+ <comment xml:lang="da">FLAC-lyd</comment>
+ <comment xml:lang="cs">zvuk FLAC</comment>
+ <comment xml:lang="ca">àudio FLAC</comment>
+ <comment xml:lang="bg">Аудио — FLAC</comment>
+ <comment xml:lang="be@latin">Aŭdyjo FLAC</comment>
+ <comment xml:lang="be">аўдыя FLAC</comment>
+ <comment xml:lang="ar">صوت FLAC</comment>
+ <comment xml:lang="af">FLAC-oudio</comment>
+ <acronym>FLAC</acronym>
+ <expanded-acronym>Free Lossless Audio Codec</expanded-acronym>
+ <magic>
<match value="fLaC" type="string" offset="0"/>
</magic>
<glob pattern="*.flac"/>
<alias type="audio/x-flac"/>
</mime-type>
+ <mime-type type="audio/x-tak">
+ <comment>TAK audio</comment>
+ <comment xml:lang="uk">звук TAK</comment>
+ <comment xml:lang="sv">TAK-ljud</comment>
+ <comment xml:lang="ru">Аудио TAK</comment>
+ <comment xml:lang="pt_BR">Áudio TAK</comment>
+ <comment xml:lang="pl">Plik dźwiękowy TAK</comment>
+ <comment xml:lang="it">Audio Tak</comment>
+ <comment xml:lang="gl">Son TAK</comment>
+ <comment xml:lang="eu">TAK audioa</comment>
+ <comment xml:lang="es">audio TAK</comment>
+ <comment xml:lang="de">TAK-Audio</comment>
+ <comment xml:lang="be">аўдыя TAK</comment>
+ <acronym>TAK</acronym>
+ <expanded-acronym>Tom's lossless Audio Kompressor</expanded-acronym>
+ <magic>
+ <match type="string" value="tBaK" offset="0"/>
+ </magic>
+ <glob pattern="*.tak"/>
+ </mime-type>
<mime-type type="audio/x-wavpack">
<comment>WavPack audio</comment>
- <comment xml:lang="ar">WavPack سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo WavPack</comment>
- <comment xml:lang="bg">Аудио — WavPack</comment>
- <comment xml:lang="ca">àudio de WavPack</comment>
- <comment xml:lang="cs">zvuk WavPack</comment>
- <comment xml:lang="da">WavPack-lyd</comment>
- <comment xml:lang="de">WavPack-Audio</comment>
- <comment xml:lang="el">Ήχος WavePack</comment>
- <comment xml:lang="en_GB">WavPack audio</comment>
- <comment xml:lang="eo">WavPack-sondosiero</comment>
- <comment xml:lang="es">sonido WavPack</comment>
- <comment xml:lang="eu">WavPack audioa</comment>
- <comment xml:lang="fi">WavPack-ääni</comment>
- <comment xml:lang="fo">WavPack ljóður</comment>
- <comment xml:lang="fr">audio WavPack</comment>
- <comment xml:lang="ga">fuaim WavPack</comment>
- <comment xml:lang="gl">son WavPack</comment>
- <comment xml:lang="he">שמע WavPack</comment>
- <comment xml:lang="hr">WavPack zvučni zapis</comment>
- <comment xml:lang="hu">WavPack hang</comment>
- <comment xml:lang="ia">Audio WavPack</comment>
- <comment xml:lang="id">Audio WavPack</comment>
- <comment xml:lang="it">Audio WavPack</comment>
- <comment xml:lang="ja">WavPack オーディオ</comment>
- <comment xml:lang="kk">WavPack аудиосы</comment>
- <comment xml:lang="ko">WavPack 오디오</comment>
- <comment xml:lang="lt">WavPack garso įrašas</comment>
- <comment xml:lang="lv">WavPack audio</comment>
- <comment xml:lang="nb">WavPack-lyd</comment>
- <comment xml:lang="nl">WavPack-audio</comment>
- <comment xml:lang="nn">WavPack-lyd</comment>
- <comment xml:lang="oc">àudio WavPack</comment>
- <comment xml:lang="pl">Plik dźwiękowy WavPack</comment>
- <comment xml:lang="pt">áudio WavPack</comment>
- <comment xml:lang="pt_BR">Áudio WavPack</comment>
- <comment xml:lang="ro">Audio WavPack</comment>
- <comment xml:lang="ru">Аудио WavPack</comment>
- <comment xml:lang="sk">Zvuk WavPack</comment>
- <comment xml:lang="sl">Zvočna datoteka WavPack</comment>
- <comment xml:lang="sq">Audio WavPack</comment>
- <comment xml:lang="sr">Вејвпак звук</comment>
- <comment xml:lang="sv">WavPack-ljud</comment>
- <comment xml:lang="tr">WavPack sesi</comment>
- <comment xml:lang="uk">звук WavPack</comment>
- <comment xml:lang="vi">Âm thanh WavPack</comment>
- <comment xml:lang="zh_CN">WavPack 音频</comment>
<comment xml:lang="zh_TW">WavPack 音訊</comment>
- <magic priority="50">
- <match value="wvpk" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">WavPack 音频</comment>
+ <comment xml:lang="vi">Âm thanh WavPack</comment>
+ <comment xml:lang="uk">звук WavPack</comment>
+ <comment xml:lang="tr">WavPack sesi</comment>
+ <comment xml:lang="sv">WavPack-ljud</comment>
+ <comment xml:lang="sr">Вејвпак звук</comment>
+ <comment xml:lang="sq">audio WavPack</comment>
+ <comment xml:lang="sl">Zvočna datoteka WavPack</comment>
+ <comment xml:lang="si">WavPack ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk WavPack</comment>
+ <comment xml:lang="ru">Аудио WavPack</comment>
+ <comment xml:lang="ro">Audio WavPack</comment>
+ <comment xml:lang="pt_BR">Áudio WavPack</comment>
+ <comment xml:lang="pt">áudio WavPack</comment>
+ <comment xml:lang="pl">Plik dźwiękowy WavPack</comment>
+ <comment xml:lang="oc">àudio WavPack</comment>
+ <comment xml:lang="nn">WavPack-lyd</comment>
+ <comment xml:lang="nl">WavPack-audio</comment>
+ <comment xml:lang="nb">WavPack-lyd</comment>
+ <comment xml:lang="lv">WavPack audio</comment>
+ <comment xml:lang="lt">WavPack garso įrašas</comment>
+ <comment xml:lang="ko">WavPack 오디오</comment>
+ <comment xml:lang="kk">WavPack аудиосы</comment>
+ <comment xml:lang="ja">WavPack オーディオ</comment>
+ <comment xml:lang="it">Audio WavPack</comment>
+ <comment xml:lang="is">WavPack hljóðskrá</comment>
+ <comment xml:lang="id">Audio WavPack</comment>
+ <comment xml:lang="ia">Audio WavPack</comment>
+ <comment xml:lang="hu">WavPack hang</comment>
+ <comment xml:lang="hr">WavPack zvučni zapis</comment>
+ <comment xml:lang="he">שמע WavPack</comment>
+ <comment xml:lang="gl">son WavPack</comment>
+ <comment xml:lang="ga">fuaim WavPack</comment>
+ <comment xml:lang="fur">audio WavPack</comment>
+ <comment xml:lang="fr">audio WavPack</comment>
+ <comment xml:lang="fo">WavPack ljóður</comment>
+ <comment xml:lang="fi">WavPack-ääni</comment>
+ <comment xml:lang="eu">WavPack audioa</comment>
+ <comment xml:lang="es">sonido WavPack</comment>
+ <comment xml:lang="eo">WavPack-sondosiero</comment>
+ <comment xml:lang="en_GB">WavPack audio</comment>
+ <comment xml:lang="el">Ήχος WavePack</comment>
+ <comment xml:lang="de">WavPack-Audio</comment>
+ <comment xml:lang="da">WavPack-lyd</comment>
+ <comment xml:lang="cs">zvuk WavPack</comment>
+ <comment xml:lang="ca">àudio de WavPack</comment>
+ <comment xml:lang="bg">Аудио — WavPack</comment>
+ <comment xml:lang="be@latin">Aŭdyjo WavPack</comment>
+ <comment xml:lang="be">аўдыя WavPack</comment>
+ <comment xml:lang="ar">صوت WavPack</comment>
+ <comment xml:lang="af">WavPack-oudio</comment>
+ <magic>
+ <match type="string" value="wvpk" offset="0"/>
</magic>
<glob pattern="*.wv"/>
<glob pattern="*.wvp"/>
</mime-type>
<mime-type type="audio/x-wavpack-correction">
<comment>WavPack audio correction file</comment>
- <comment xml:lang="ar">ملف تصحيح WavPack السمعي</comment>
- <comment xml:lang="be@latin">Fajł aŭdyjokarekcyi WavPack</comment>
- <comment xml:lang="bg">Файл за корекции на аудио — WavPack</comment>
- <comment xml:lang="ca">fitxer de correcció d'àudio de WavPack</comment>
- <comment xml:lang="cs">opravný zvukový soubor WavPack</comment>
- <comment xml:lang="da">WavPack-lydkorrektionsfil</comment>
- <comment xml:lang="de">WavPack-Audiokorrekturdatei</comment>
- <comment xml:lang="el">Αρχείο διόρθωσης ήχου WavePack</comment>
- <comment xml:lang="en_GB">WavPack audio correction file</comment>
- <comment xml:lang="es">archivo de corrección de sonido WavPack</comment>
- <comment xml:lang="eu">WavPack audio-zuzenketaren fitxategia</comment>
- <comment xml:lang="fi">WavPack-äänikorjaustiedosto</comment>
- <comment xml:lang="fo">WavPack ljóðrættingarfíla</comment>
- <comment xml:lang="fr">fichier de correction audio WavPack</comment>
- <comment xml:lang="ga">comhad ceartúchán fuaime WavPack</comment>
- <comment xml:lang="gl">ficheiro de corrección de son WavPack</comment>
- <comment xml:lang="he">קובץ תיקון שמע של WavPack</comment>
- <comment xml:lang="hr">WavPack datoteka ispravke zvuka</comment>
- <comment xml:lang="hu">WavPack hangjavítási fájl</comment>
- <comment xml:lang="ia">File de correction audio WavPack</comment>
- <comment xml:lang="id">Berkas koreksi audio WavPack</comment>
- <comment xml:lang="it">File correzione audio WavPack</comment>
- <comment xml:lang="ja">WavPack オーディオコレクションファイル</comment>
- <comment xml:lang="kk">WavPack аудио түзету файлы</comment>
- <comment xml:lang="ko">WavPack 오디오 교정 파일</comment>
- <comment xml:lang="lt">WavPack garso korekcijos failas</comment>
- <comment xml:lang="lv">WavPack audio korekciju datne</comment>
- <comment xml:lang="nb">WavPack lydkorrigeringsfil</comment>
- <comment xml:lang="nl">WavPack-audio-correctiebestand</comment>
- <comment xml:lang="nn">WawPack lydopprettingsfil</comment>
- <comment xml:lang="oc">fichièr de correccion àudio WavPack</comment>
- <comment xml:lang="pl">Plik korekcji dźwięku WavPack</comment>
- <comment xml:lang="pt">ficheiro de correção áudio WavPack</comment>
- <comment xml:lang="pt_BR">Arquivo de correção de áudio WavPack</comment>
- <comment xml:lang="ro">Fișier audio de corecție WavPack</comment>
- <comment xml:lang="ru">Файл коррекции аудио WavPack</comment>
- <comment xml:lang="sk">Opravný zvukový súbor WavPack</comment>
- <comment xml:lang="sl">popravljalna zvočna datoteka WavPack</comment>
- <comment xml:lang="sq">File korrigjgimi audio WavPack</comment>
- <comment xml:lang="sr">датотека поправке Вејвпак звука</comment>
- <comment xml:lang="sv">WavPack-ljudkorrigeringsfil</comment>
- <comment xml:lang="tr">WavPack ses düzeltme dosyası</comment>
- <comment xml:lang="uk">файл корекції звуку WavPack</comment>
- <comment xml:lang="vi">Tập tin sửa chữa âm thanh WavPack</comment>
- <comment xml:lang="zh_CN">WavPack 音频校正文件</comment>
<comment xml:lang="zh_TW">WavPack 音訊校正檔</comment>
- <magic priority="50">
- <match value="wvpk" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">WavPack 音频校正文件</comment>
+ <comment xml:lang="vi">Tập tin sửa chữa âm thanh WavPack</comment>
+ <comment xml:lang="uk">файл корекції звуку WavPack</comment>
+ <comment xml:lang="tr">WavPack ses düzeltme dosyası</comment>
+ <comment xml:lang="sv">WavPack-ljudkorrigeringsfil</comment>
+ <comment xml:lang="sr">датотека поправке Вејвпак звука</comment>
+ <comment xml:lang="sq">kartelë saktësimi audio WavPack</comment>
+ <comment xml:lang="sl">popravljalna zvočna datoteka WavPack</comment>
+ <comment xml:lang="si">WavPack ශ්‍රව්‍ය නිවැරදි කිරීමේ ගොනුව</comment>
+ <comment xml:lang="sk">Opravný zvukový súbor WavPack</comment>
+ <comment xml:lang="ru">Файл коррекции аудио WavPack</comment>
+ <comment xml:lang="ro">Fișier audio de corecție WavPack</comment>
+ <comment xml:lang="pt_BR">Arquivo de correção de áudio WavPack</comment>
+ <comment xml:lang="pt">ficheiro de correção áudio WavPack</comment>
+ <comment xml:lang="pl">Plik korekcji dźwięku WavPack</comment>
+ <comment xml:lang="oc">fichièr de correccion àudio WavPack</comment>
+ <comment xml:lang="nn">WawPack lydopprettingsfil</comment>
+ <comment xml:lang="nl">WavPack-audio-correctiebestand</comment>
+ <comment xml:lang="nb">WavPack lydkorrigeringsfil</comment>
+ <comment xml:lang="lv">WavPack audio korekciju datne</comment>
+ <comment xml:lang="lt">WavPack garso korekcijos failas</comment>
+ <comment xml:lang="ko">WavPack 오디오 교정 파일</comment>
+ <comment xml:lang="kk">WavPack аудио түзету файлы</comment>
+ <comment xml:lang="ja">WavPack オーディオコレクションファイル</comment>
+ <comment xml:lang="it">File correzione audio WavPack</comment>
+ <comment xml:lang="is">WavPack hljóðleiðréttingaskrá</comment>
+ <comment xml:lang="id">Berkas koreksi audio WavPack</comment>
+ <comment xml:lang="ia">File de correction audio WavPack</comment>
+ <comment xml:lang="hu">WavPack hangjavítási fájl</comment>
+ <comment xml:lang="hr">WavPack datoteka ispravke zvuka</comment>
+ <comment xml:lang="he">קובץ תיקון שמע של WavPack</comment>
+ <comment xml:lang="gl">ficheiro de corrección de son WavPack</comment>
+ <comment xml:lang="ga">comhad ceartúchán fuaime WavPack</comment>
+ <comment xml:lang="fur">file di corezion audio WavPack</comment>
+ <comment xml:lang="fr">fichier de correction audio WavPack</comment>
+ <comment xml:lang="fo">WavPack ljóðrættingarfíla</comment>
+ <comment xml:lang="fi">WavPack-äänikorjaustiedosto</comment>
+ <comment xml:lang="eu">WavPack audio-zuzenketaren fitxategia</comment>
+ <comment xml:lang="es">archivo de corrección de sonido WavPack</comment>
+ <comment xml:lang="en_GB">WavPack audio correction file</comment>
+ <comment xml:lang="el">Αρχείο διόρθωσης ήχου WavePack</comment>
+ <comment xml:lang="de">WavPack-Audiokorrekturdatei</comment>
+ <comment xml:lang="da">WavPack-lydkorrektionsfil</comment>
+ <comment xml:lang="cs">opravný zvukový soubor WavPack</comment>
+ <comment xml:lang="ca">fitxer de correcció d'àudio de WavPack</comment>
+ <comment xml:lang="bg">Файл за корекции на аудио — WavPack</comment>
+ <comment xml:lang="be@latin">Fajł aŭdyjokarekcyi WavPack</comment>
+ <comment xml:lang="be">файл аўдыякарэкцыі WavPack</comment>
+ <comment xml:lang="ar">ملف تصحيح صوت WavPack</comment>
+ <magic>
+ <match type="string" value="wvpk" offset="0"/>
</magic>
<glob pattern="*.wvc"/>
</mime-type>
<mime-type type="audio/midi">
<comment>MIDI audio</comment>
- <comment xml:lang="ar">MIDI سمعي</comment>
- <comment xml:lang="az">MIDI audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo MIDI</comment>
- <comment xml:lang="bg">Аудио — MIDI</comment>
- <comment xml:lang="ca">àudio MIDI</comment>
- <comment xml:lang="cs">zvuk MIDI</comment>
- <comment xml:lang="cy">Sain MIDI</comment>
- <comment xml:lang="da">MIDI-lyd</comment>
- <comment xml:lang="de">MIDI-Audio</comment>
- <comment xml:lang="el">Ήχος MIDI</comment>
- <comment xml:lang="en_GB">MIDI audio</comment>
- <comment xml:lang="eo">MIDI-sondosiero</comment>
- <comment xml:lang="es">sonido MIDI</comment>
- <comment xml:lang="eu">MIDI audioa</comment>
- <comment xml:lang="fi">MIDI-ääni</comment>
- <comment xml:lang="fo">MIDI ljóður</comment>
- <comment xml:lang="fr">audio MIDI</comment>
- <comment xml:lang="ga">fuaim MIDI</comment>
- <comment xml:lang="gl">son MIDI</comment>
- <comment xml:lang="he">שמע MIDI</comment>
- <comment xml:lang="hr">MIDI zvučni zapis</comment>
- <comment xml:lang="hu">MIDI hang</comment>
- <comment xml:lang="ia">Audio MIDI</comment>
- <comment xml:lang="id">Audio MIDI</comment>
- <comment xml:lang="it">Audio MIDI</comment>
- <comment xml:lang="ja">MIDI オーディオ</comment>
- <comment xml:lang="kk">MIDI аудиосы</comment>
- <comment xml:lang="ko">미디 오디오</comment>
- <comment xml:lang="lt">MIDI garso įrašas</comment>
- <comment xml:lang="lv">MIDI audio</comment>
- <comment xml:lang="ms">Audio MIDI</comment>
- <comment xml:lang="nb">MIDI-lyd</comment>
- <comment xml:lang="nl">MIDI-audio</comment>
- <comment xml:lang="nn">MIDI-lyd</comment>
- <comment xml:lang="oc">àudio MIDI</comment>
- <comment xml:lang="pl">Plik dźwiękowy MIDI</comment>
- <comment xml:lang="pt">áudio MIDI</comment>
- <comment xml:lang="pt_BR">Áudio MIDI</comment>
- <comment xml:lang="ro">Audio MIDI</comment>
- <comment xml:lang="ru">Аудио MIDI</comment>
- <comment xml:lang="sk">Zvuk MIDI</comment>
- <comment xml:lang="sl">Zvočna datoteka MIDI</comment>
- <comment xml:lang="sq">Audio MIDI</comment>
- <comment xml:lang="sr">МИДИ звук</comment>
- <comment xml:lang="sv">MIDI-ljud</comment>
- <comment xml:lang="tr">MIDI sesi</comment>
- <comment xml:lang="uk">звук MIDI</comment>
- <comment xml:lang="vi">Âm thanh MIDI</comment>
- <comment xml:lang="zh_CN">MIDI 音频</comment>
<comment xml:lang="zh_TW">MIDI 音訊</comment>
+ <comment xml:lang="zh_CN">MIDI 音频</comment>
+ <comment xml:lang="vi">Âm thanh MIDI</comment>
+ <comment xml:lang="uk">звук MIDI</comment>
+ <comment xml:lang="tr">MIDI sesi</comment>
+ <comment xml:lang="sv">MIDI-ljud</comment>
+ <comment xml:lang="sr">МИДИ звук</comment>
+ <comment xml:lang="sq">audio MIDI</comment>
+ <comment xml:lang="sl">Zvočna datoteka MIDI</comment>
+ <comment xml:lang="si">MIDI ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk MIDI</comment>
+ <comment xml:lang="ru">Аудио MIDI</comment>
+ <comment xml:lang="ro">Audio MIDI</comment>
+ <comment xml:lang="pt_BR">Áudio MIDI</comment>
+ <comment xml:lang="pt">áudio MIDI</comment>
+ <comment xml:lang="pl">Plik dźwiękowy MIDI</comment>
+ <comment xml:lang="oc">àudio MIDI</comment>
+ <comment xml:lang="nn">MIDI-lyd</comment>
+ <comment xml:lang="nl">MIDI-audio</comment>
+ <comment xml:lang="nb">MIDI-lyd</comment>
+ <comment xml:lang="ms">Audio MIDI</comment>
+ <comment xml:lang="lv">MIDI audio</comment>
+ <comment xml:lang="lt">MIDI garso įrašas</comment>
+ <comment xml:lang="ko">미디 오디오</comment>
+ <comment xml:lang="kk">MIDI аудиосы</comment>
+ <comment xml:lang="ja">MIDI オーディオ</comment>
+ <comment xml:lang="it">Audio MIDI</comment>
+ <comment xml:lang="is">MIDI hljóðskrá</comment>
+ <comment xml:lang="id">Audio MIDI</comment>
+ <comment xml:lang="ia">Audio MIDI</comment>
+ <comment xml:lang="hu">MIDI hang</comment>
+ <comment xml:lang="hr">MIDI zvučni zapis</comment>
+ <comment xml:lang="he">שמע MIDI</comment>
+ <comment xml:lang="gl">son MIDI</comment>
+ <comment xml:lang="ga">fuaim MIDI</comment>
+ <comment xml:lang="fur">audio MIDI</comment>
+ <comment xml:lang="fr">audio MIDI</comment>
+ <comment xml:lang="fo">MIDI ljóður</comment>
+ <comment xml:lang="fi">MIDI-ääni</comment>
+ <comment xml:lang="eu">MIDI audioa</comment>
+ <comment xml:lang="es">sonido MIDI</comment>
+ <comment xml:lang="eo">MIDI-sondosiero</comment>
+ <comment xml:lang="en_GB">MIDI audio</comment>
+ <comment xml:lang="el">Ήχος MIDI</comment>
+ <comment xml:lang="de">MIDI-Audio</comment>
+ <comment xml:lang="da">MIDI-lyd</comment>
+ <comment xml:lang="cy">Sain MIDI</comment>
+ <comment xml:lang="cs">zvuk MIDI</comment>
+ <comment xml:lang="ca">àudio MIDI</comment>
+ <comment xml:lang="bg">Аудио — MIDI</comment>
+ <comment xml:lang="be@latin">Aŭdyjo MIDI</comment>
+ <comment xml:lang="be">аўдыя MIDI</comment>
+ <comment xml:lang="az">MIDI audio faylı</comment>
+ <comment xml:lang="ar">صوت MIDI</comment>
+ <comment xml:lang="af">MIDI-oudio</comment>
+ <acronym>MIDI</acronym>
+ <expanded-acronym>Musical Instrument Digital Interface</expanded-acronym>
<alias type="audio/x-midi"/>
- <magic priority="50">
- <match value="MThd" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="MThd" offset="0"/>
</magic>
<glob pattern="*.mid"/>
<glob pattern="*.midi"/>
<glob pattern="*.kar"/>
</mime-type>
<mime-type type="audio/x-mo3">
- <comment>compressed Tracker audio</comment>
- <comment xml:lang="ar">Tracker سمعي مضغوط</comment>
- <comment xml:lang="be@latin">aŭdyjo skampresavanaha Trackera</comment>
- <comment xml:lang="bg">Аудио — Tracker, компресирано</comment>
- <comment xml:lang="ca">àudio Tracker amb compressió</comment>
- <comment xml:lang="cs">komprimovaný zvuk Tracker</comment>
- <comment xml:lang="da">Trackerkomprimeret lyd</comment>
- <comment xml:lang="de">Komprimiertes Tracker-Audio</comment>
- <comment xml:lang="el">Συμπιεσμένος ήχος Tracker</comment>
- <comment xml:lang="en_GB">compressed Tracker audio</comment>
- <comment xml:lang="es">sonido de Tracker comprimido</comment>
- <comment xml:lang="eu">konprimitutako Tracker audioa</comment>
- <comment xml:lang="fi">pakattu Tracker-ääni</comment>
- <comment xml:lang="fo">stappað Tracker ljóður</comment>
- <comment xml:lang="fr">audio Tracker compressé</comment>
- <comment xml:lang="ga">fuaim chomhbhrúite Tracker</comment>
- <comment xml:lang="gl">son comprimido de Tracker</comment>
- <comment xml:lang="he">שמע גשש מכווץ</comment>
- <comment xml:lang="hr">Sažeti Tracker zvučni zapis</comment>
- <comment xml:lang="hu">tömörített Tracker hang</comment>
- <comment xml:lang="ia">Audio Tracker comprimite</comment>
- <comment xml:lang="id">audio Tracker terkompresi</comment>
- <comment xml:lang="it">Audio compresso Tracker</comment>
- <comment xml:lang="ja">圧縮 Tracker オーディオ</comment>
- <comment xml:lang="kk">сығылған Tracker аудиосы</comment>
- <comment xml:lang="ko">압축된 Tracker 오디오</comment>
- <comment xml:lang="lt">suglaudintas Tracker garso įrašas</comment>
- <comment xml:lang="lv">saspiests Tracker audio</comment>
- <comment xml:lang="nl">ingepakte Tracker-audio</comment>
- <comment xml:lang="nn">komprimert Tracker-lyd</comment>
- <comment xml:lang="oc">àudio Tracker compressat</comment>
- <comment xml:lang="pl">Skompresowany plik dźwiękowy Tracker</comment>
- <comment xml:lang="pt">áudio comprimido Tracker</comment>
- <comment xml:lang="pt_BR">Áudio Tracker compactado</comment>
- <comment xml:lang="ro">Tracker audio comprimat</comment>
+ <comment>Compressed Tracker audio</comment>
+ <comment xml:lang="uk">стиснутий звук tracker</comment>
+ <comment xml:lang="sv">Komprimerat Tracker-ljud</comment>
<comment xml:lang="ru">Сжатое аудио Tracker</comment>
- <comment xml:lang="sk">Komprimovaný zvuk Tracker</comment>
- <comment xml:lang="sl">Skrčena zvočna datoteka Tracker</comment>
- <comment xml:lang="sq">Audio Tracker e kompresuar</comment>
- <comment xml:lang="sr">запаковани звук Пратиоца</comment>
- <comment xml:lang="sv">komprimerat Tracker-ljud</comment>
- <comment xml:lang="tr">sıkıştırılmış Tracker sesi</comment>
- <comment xml:lang="uk">стиснутий звук Tracker</comment>
- <comment xml:lang="vi">âm thanh Tracker đã nén</comment>
- <comment xml:lang="zh_CN">压缩的 Tracker 音频</comment>
- <comment xml:lang="zh_TW">壓縮版 Tracker 音訊</comment>
- <magic priority="50">
- <match value="MO3" type="string" offset="0"/>
+ <comment xml:lang="pl">Skompresowany plik dźwiękowy Tracker</comment>
+ <comment xml:lang="it">Audio compresso Tracker</comment>
+ <comment xml:lang="gl">Son de Tracker comprimido</comment>
+ <comment xml:lang="es">audio de Tracker comprimido</comment>
+ <comment xml:lang="de">Komprimiertes Tracker-Audio</comment>
+ <comment xml:lang="be">сціснутае аўдыя Tracker</comment>
+ <magic>
+ <match type="string" value="MO3" offset="0"/>
</magic>
<glob pattern="*.mo3"/>
</mime-type>
<mime-type type="audio/aac">
<comment>AAC audio</comment>
- <comment xml:lang="ca">àudio AAC</comment>
- <comment xml:lang="cs">zvuk AAC</comment>
- <comment xml:lang="da">AAC-lyd</comment>
- <comment xml:lang="de">AAC-Audio</comment>
- <comment xml:lang="el">Ήχος AAC</comment>
- <comment xml:lang="en_GB">AAC audio</comment>
- <comment xml:lang="es">sonido AAC</comment>
- <comment xml:lang="eu">AAC audioa</comment>
- <comment xml:lang="fi">AAC-ääni</comment>
- <comment xml:lang="fr">audio AAC</comment>
- <comment xml:lang="ga">fuaim AAC</comment>
- <comment xml:lang="gl">Son AAC</comment>
- <comment xml:lang="he">שמע AAC</comment>
- <comment xml:lang="hr">AAC zvučni zapis</comment>
- <comment xml:lang="hu">AAC hang</comment>
- <comment xml:lang="ia">Audio ACC</comment>
- <comment xml:lang="id">Audio AAC</comment>
- <comment xml:lang="it">Audio AAC</comment>
- <comment xml:lang="ja">AAC オーディオ</comment>
- <comment xml:lang="kk">AAC аудиосы</comment>
- <comment xml:lang="ko">AAC 오디오</comment>
- <comment xml:lang="lv">AAC audio</comment>
- <comment xml:lang="oc">àudio AAC</comment>
- <comment xml:lang="pl">Plik dźwiękowy AAC</comment>
- <comment xml:lang="pt">áudio AAC</comment>
- <comment xml:lang="pt_BR">Áudio AAC</comment>
- <comment xml:lang="ru">Аудио AAC</comment>
- <comment xml:lang="sk">Zvuk AAC</comment>
- <comment xml:lang="sl">Zvok AAC</comment>
- <comment xml:lang="sr">ААЦ звук</comment>
- <comment xml:lang="sv">AAC-ljud</comment>
- <comment xml:lang="tr">AAC sesi</comment>
- <comment xml:lang="uk">звукові дані AAC</comment>
- <comment xml:lang="zh_CN">AAC 音频</comment>
<comment xml:lang="zh_TW">AAC 音訊</comment>
+ <comment xml:lang="zh_CN">AAC 音频</comment>
+ <comment xml:lang="uk">звукові дані AAC</comment>
+ <comment xml:lang="tr">AAC sesi</comment>
+ <comment xml:lang="sv">AAC-ljud</comment>
+ <comment xml:lang="sr">ААЦ звук</comment>
+ <comment xml:lang="sq">audio AAC</comment>
+ <comment xml:lang="sl">Zvok AAC</comment>
+ <comment xml:lang="si">AAC ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk AAC</comment>
+ <comment xml:lang="ru">Аудио AAC</comment>
+ <comment xml:lang="pt_BR">Áudio AAC</comment>
+ <comment xml:lang="pt">áudio AAC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy AAC</comment>
+ <comment xml:lang="oc">àudio AAC</comment>
+ <comment xml:lang="nl">AAC-audio</comment>
+ <comment xml:lang="lv">AAC audio</comment>
+ <comment xml:lang="ko">AAC 오디오</comment>
+ <comment xml:lang="kk">AAC аудиосы</comment>
+ <comment xml:lang="ja">AAC オーディオ</comment>
+ <comment xml:lang="it">Audio AAC</comment>
+ <comment xml:lang="is">AAC hljóðskrá</comment>
+ <comment xml:lang="id">Audio AAC</comment>
+ <comment xml:lang="ia">Audio ACC</comment>
+ <comment xml:lang="hu">AAC hang</comment>
+ <comment xml:lang="hr">AAC zvučni zapis</comment>
+ <comment xml:lang="he">שמע AAC</comment>
+ <comment xml:lang="gl">Son AAC</comment>
+ <comment xml:lang="ga">fuaim AAC</comment>
+ <comment xml:lang="fur">audio AAC</comment>
+ <comment xml:lang="fr">audio AAC</comment>
+ <comment xml:lang="fi">AAC-ääni</comment>
+ <comment xml:lang="eu">AAC audioa</comment>
+ <comment xml:lang="es">sonido AAC</comment>
+ <comment xml:lang="en_GB">AAC audio</comment>
+ <comment xml:lang="el">Ήχος AAC</comment>
+ <comment xml:lang="de">AAC-Audio</comment>
+ <comment xml:lang="da">AAC-lyd</comment>
+ <comment xml:lang="cs">zvuk AAC</comment>
+ <comment xml:lang="ca">àudio AAC</comment>
+ <comment xml:lang="bg">Аудио — AAC</comment>
+ <comment xml:lang="be">аўдыя AAC</comment>
+ <comment xml:lang="ar">صوت AAC</comment>
+ <comment xml:lang="af">AAC-oudio</comment>
<acronym>AAC</acronym>
<expanded-acronym>Advanced Audio Coding</expanded-acronym>
- <magic priority="50">
- <match value="ADIF" type="string" offset="0"/>
- <match value="0xFFF0" type="big16" offset="0" mask="0xFFF6"/>
+ <magic>
+ <match type="string" value="ADIF" offset="0"/>
+ <match type="big16" value="0xFFF0" mask="0xFFF6" offset="0"/>
</magic>
<glob pattern="*.aac"/>
<glob pattern="*.adts"/>
- <glob weight="10" pattern="*.ass"/>
+ <glob pattern="*.ass" weight="10"/>
<alias type="audio/x-aac"/>
</mime-type>
<mime-type type="audio/usac">
<comment>USAC audio</comment>
+ <comment xml:lang="zh_TW">USAC 音訊</comment>
+ <comment xml:lang="zh_CN">USAC 音频</comment>
+ <comment xml:lang="uk">звукові дані USAC</comment>
+ <comment xml:lang="tr">USAC sesi</comment>
+ <comment xml:lang="sv">USAC-ljud</comment>
+ <comment xml:lang="sq">audio USAC</comment>
+ <comment xml:lang="sl">Zvok USAC</comment>
+ <comment xml:lang="si">USAC ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk USAC</comment>
+ <comment xml:lang="ru">Аудио USAC</comment>
+ <comment xml:lang="pt_BR">Áudio USAC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy USAC</comment>
+ <comment xml:lang="nl">USAC-audio</comment>
+ <comment xml:lang="ko">USAC 오디오</comment>
+ <comment xml:lang="kk">USAC аудиосы</comment>
+ <comment xml:lang="ja">USAC オーディオ</comment>
+ <comment xml:lang="it">Audio USAC</comment>
+ <comment xml:lang="is">USAC hljóðskrá</comment>
+ <comment xml:lang="id">Audio USAC</comment>
+ <comment xml:lang="hu">USAC hang</comment>
+ <comment xml:lang="hr">USAC zvučni zapis</comment>
+ <comment xml:lang="he">שמע USAC</comment>
+ <comment xml:lang="gl">Son USAC</comment>
+ <comment xml:lang="ga">fuaim USAC</comment>
+ <comment xml:lang="fur">audio USAC</comment>
+ <comment xml:lang="fr">audio USAC</comment>
+ <comment xml:lang="fi">USAC-ääni</comment>
+ <comment xml:lang="eu">USAC audioa</comment>
+ <comment xml:lang="es">sonido USAC</comment>
+ <comment xml:lang="en_GB">USAC audio</comment>
+ <comment xml:lang="de">USAC-Audio</comment>
+ <comment xml:lang="da">USAC-lyd</comment>
+ <comment xml:lang="cs">zvuk USAC</comment>
+ <comment xml:lang="ca">àudio USAC</comment>
+ <comment xml:lang="bg">Аудио — USAC</comment>
+ <comment xml:lang="be">аўдыя USAC</comment>
+ <comment xml:lang="ar">صوت USAC</comment>
+ <comment xml:lang="af">USAC-oudio</comment>
<acronym>USAC</acronym>
<expanded-acronym>Unified Speech and Audio Coding</expanded-acronym>
<glob pattern="*.loas"/>
@@ -23151,125 +25259,170 @@
</mime-type>
<mime-type type="audio/mp4">
<comment>MPEG-4 audio</comment>
- <comment xml:lang="ar">MPEG-4 سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo MPEG-4</comment>
- <comment xml:lang="bg">Аудио — MPEG-4</comment>
- <comment xml:lang="ca">àudio MPEG-4</comment>
- <comment xml:lang="cs">zvuk MPEG-4</comment>
- <comment xml:lang="da">MPEG4-lyd</comment>
- <comment xml:lang="de">MPEG-4-Audio</comment>
- <comment xml:lang="el">Ήχος MPEG-4</comment>
- <comment xml:lang="en_GB">MPEG-4 audio</comment>
- <comment xml:lang="eo">MPEG4-sondosiero</comment>
- <comment xml:lang="es">sonido MPEG-4</comment>
- <comment xml:lang="eu">MPEG-4 audioa</comment>
- <comment xml:lang="fi">MPEG-4-ääni</comment>
- <comment xml:lang="fo">MPEG-4 ljóður</comment>
- <comment xml:lang="fr">audio MPEG-4</comment>
- <comment xml:lang="ga">fuaim MPEG-4</comment>
- <comment xml:lang="gl">son MPEG-4</comment>
- <comment xml:lang="he">שמע MPEG-4</comment>
- <comment xml:lang="hr">MPEG-4 zvučni zapis</comment>
- <comment xml:lang="hu">MPEG-4 hang</comment>
- <comment xml:lang="ia">Audio MPEG-4</comment>
- <comment xml:lang="id">Audio MPEG-4</comment>
- <comment xml:lang="it">Audio MPEG-4</comment>
- <comment xml:lang="ja">MPEG-4 オーディオ</comment>
- <comment xml:lang="ka">MPEG-4 აუდიო</comment>
- <comment xml:lang="kk">MPEG-4 аудиосы</comment>
- <comment xml:lang="ko">MPEG-4 오디오</comment>
- <comment xml:lang="lt">MPEG-4 garso įrašas</comment>
- <comment xml:lang="lv">MPEG-4 audio</comment>
- <comment xml:lang="nb">MPEG-4-lyd</comment>
- <comment xml:lang="nl">MPEG4-audio</comment>
- <comment xml:lang="nn">MPEG-4-lyd</comment>
- <comment xml:lang="oc">àudio MPEG-4</comment>
- <comment xml:lang="pl">Plik dźwiękowy MPEG-4</comment>
- <comment xml:lang="pt">áudio MPEG-4</comment>
- <comment xml:lang="pt_BR">Áudio MPEG-4</comment>
- <comment xml:lang="ro">Audio MPEG-4</comment>
- <comment xml:lang="ru">Аудио MPEG-4</comment>
- <comment xml:lang="sk">Zvuk MPEG-4</comment>
- <comment xml:lang="sl">Zvočna datoteka MPEG-4</comment>
- <comment xml:lang="sq">Audio MPEG-4</comment>
- <comment xml:lang="sr">МПЕГ-4 звук</comment>
- <comment xml:lang="sv">MPEG-4-ljud</comment>
- <comment xml:lang="tr">MPEG-4 sesi</comment>
- <comment xml:lang="uk">звук MPEG-4</comment>
- <comment xml:lang="vi">Âm thanh MPEG-4</comment>
- <comment xml:lang="zh_CN">MPEG-4 音频</comment>
<comment xml:lang="zh_TW">MPEG-4 音訊</comment>
+ <comment xml:lang="zh_CN">MPEG-4 音频</comment>
+ <comment xml:lang="vi">Âm thanh MPEG-4</comment>
+ <comment xml:lang="uk">звук MPEG-4</comment>
+ <comment xml:lang="tr">MPEG-4 sesi</comment>
+ <comment xml:lang="sv">MPEG-4-ljud</comment>
+ <comment xml:lang="sr">МПЕГ-4 звук</comment>
+ <comment xml:lang="sq">audio MPEG-4</comment>
+ <comment xml:lang="sl">Zvočna datoteka MPEG-4</comment>
+ <comment xml:lang="si">MPEG-4 ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk MPEG-4</comment>
+ <comment xml:lang="ru">Аудио MPEG-4</comment>
+ <comment xml:lang="ro">Audio MPEG-4</comment>
+ <comment xml:lang="pt_BR">Áudio MPEG-4</comment>
+ <comment xml:lang="pt">áudio MPEG-4</comment>
+ <comment xml:lang="pl">Plik dźwiękowy MPEG-4</comment>
+ <comment xml:lang="oc">àudio MPEG-4</comment>
+ <comment xml:lang="nn">MPEG-4-lyd</comment>
+ <comment xml:lang="nl">MPEG4-audio</comment>
+ <comment xml:lang="nb">MPEG-4-lyd</comment>
+ <comment xml:lang="lv">MPEG-4 audio</comment>
+ <comment xml:lang="lt">MPEG-4 garso įrašas</comment>
+ <comment xml:lang="ko">MPEG-4 오디오</comment>
+ <comment xml:lang="kk">MPEG-4 аудиосы</comment>
+ <comment xml:lang="ka">MPEG-4 აუდიო</comment>
+ <comment xml:lang="ja">MPEG-4 オーディオ</comment>
+ <comment xml:lang="it">Audio MPEG-4</comment>
+ <comment xml:lang="is">MPEG-4 hljóð</comment>
+ <comment xml:lang="id">Audio MPEG-4</comment>
+ <comment xml:lang="ia">Audio MPEG-4</comment>
+ <comment xml:lang="hu">MPEG-4 hang</comment>
+ <comment xml:lang="hr">MPEG-4 zvučni zapis</comment>
+ <comment xml:lang="he">שמע MPEG-4</comment>
+ <comment xml:lang="gl">son MPEG-4</comment>
+ <comment xml:lang="ga">fuaim MPEG-4</comment>
+ <comment xml:lang="fur">audio MPEG-4</comment>
+ <comment xml:lang="fr">audio MPEG-4</comment>
+ <comment xml:lang="fo">MPEG-4 ljóður</comment>
+ <comment xml:lang="fi">MPEG-4-ääni</comment>
+ <comment xml:lang="eu">MPEG-4 audioa</comment>
+ <comment xml:lang="es">sonido MPEG-4</comment>
+ <comment xml:lang="eo">MPEG4-sondosiero</comment>
+ <comment xml:lang="en_GB">MPEG-4 audio</comment>
+ <comment xml:lang="el">Ήχος MPEG-4</comment>
+ <comment xml:lang="de">MPEG-4-Audio</comment>
+ <comment xml:lang="da">MPEG4-lyd</comment>
+ <comment xml:lang="cs">zvuk MPEG-4</comment>
+ <comment xml:lang="ca">àudio MPEG-4</comment>
+ <comment xml:lang="bg">Аудио — MPEG-4</comment>
+ <comment xml:lang="be@latin">Aŭdyjo MPEG-4</comment>
+ <comment xml:lang="be">аўдыя MPEG-4</comment>
+ <comment xml:lang="ar">صوت MPEG-4</comment>
+ <comment xml:lang="af">MPEG-4-oudio</comment>
<alias type="audio/x-m4a"/>
<alias type="audio/m4a"/>
- <magic priority="50">
- <match value="ftypM4A" type="string" offset="4"/>
+ <magic>
+ <match type="string" value="ftypM4A" offset="4"/>
</magic>
<glob pattern="*.m4a"/>
<glob pattern="*.f4a"/>
</mime-type>
<mime-type type="audio/x-m4r">
- <comment>MPEG-4 Ringtone</comment>
+ <comment>MPEG-4 ringtone</comment>
+ <comment xml:lang="zh_TW">MPEG-4 鈴聲</comment>
+ <comment xml:lang="zh_CN">MPEG-4 铃声</comment>
+ <comment xml:lang="uk">рингтон MPEG-4</comment>
+ <comment xml:lang="tr">MPEG-4 zil sesi</comment>
+ <comment xml:lang="sv">MPEG-4-ringsignal</comment>
+ <comment xml:lang="sq">zile MPEG-4</comment>
+ <comment xml:lang="sl">Zvonjenje MPEG-4</comment>
+ <comment xml:lang="si">MPEG-4 නාද රටාව</comment>
+ <comment xml:lang="sk">Zvonenie MPEG-4</comment>
+ <comment xml:lang="ru">Мелодия MPEG-4</comment>
+ <comment xml:lang="pt_BR">Toque MPEG-4</comment>
+ <comment xml:lang="pl">Dzwonek MPEG-4</comment>
+ <comment xml:lang="nl">MPEG-4-ringtone</comment>
+ <comment xml:lang="ko">MPEG-4 벨소리</comment>
+ <comment xml:lang="kk">MPEG-4 рингтоны</comment>
+ <comment xml:lang="ja">MPEG-4 着信音</comment>
+ <comment xml:lang="it">Suoneria MPEG-4</comment>
+ <comment xml:lang="is">MPEG-4 hringitónn</comment>
+ <comment xml:lang="id">Nada panggil MPEG-4</comment>
+ <comment xml:lang="hu">MPEG-4 csengőhang</comment>
+ <comment xml:lang="hr">MPEG-4 melodija zvona</comment>
+ <comment xml:lang="he">נעימון MPEG-4</comment>
+ <comment xml:lang="gl">Ton de chamada MPEG-4</comment>
+ <comment xml:lang="fr">sonnerie MPEG-4</comment>
+ <comment xml:lang="fi">MPEG-4-soittoääni</comment>
+ <comment xml:lang="eu">MPEG-4 dei-tonua</comment>
+ <comment xml:lang="es">tono de llamada MPEG-4</comment>
+ <comment xml:lang="en_GB">MPEG-4 ringtone</comment>
+ <comment xml:lang="de">MPEG-4-Klingelton</comment>
+ <comment xml:lang="da">MPEG-4-ringetone</comment>
+ <comment xml:lang="ca">to de trucada MPEG-4</comment>
+ <comment xml:lang="bg">Аудио — MPEG-4, звънене</comment>
+ <comment xml:lang="be">мелодыя выкліку MPEG-4</comment>
+ <comment xml:lang="ar">نغمة MPEG-4</comment>
<glob pattern="*.m4r"/>
<sub-class-of type="video/mp4"/>
</mime-type>
<mime-type type="video/mp4">
<comment>MPEG-4 video</comment>
- <comment xml:lang="ar">MPEG-4 مرئي</comment>
- <comment xml:lang="ast">Videu en MPEG-4</comment>
- <comment xml:lang="be@latin">Videa MPEG-4</comment>
- <comment xml:lang="bg">Видео — MPEG-4</comment>
- <comment xml:lang="ca">vídeo MPEG-4</comment>
- <comment xml:lang="cs">video MPEG-4</comment>
- <comment xml:lang="da">MPEG4-video</comment>
- <comment xml:lang="de">MPEG-4-Video</comment>
- <comment xml:lang="el">Βίντεο MPEG-4</comment>
- <comment xml:lang="en_GB">MPEG-4 video</comment>
- <comment xml:lang="eo">MPEG-4-video</comment>
- <comment xml:lang="es">vídeo MPEG-4</comment>
- <comment xml:lang="eu">MPEG-4 bideoa</comment>
- <comment xml:lang="fi">MPEG-4-video</comment>
- <comment xml:lang="fo">MPEG-4 video</comment>
- <comment xml:lang="fr">vidéo MPEG-4</comment>
- <comment xml:lang="ga">físeán MPEG-4</comment>
- <comment xml:lang="gl">vídeo MPEG-4</comment>
- <comment xml:lang="he">וידאו MPEG-4</comment>
- <comment xml:lang="hr">MPEG-4 video snimka</comment>
- <comment xml:lang="hu">MPEG-4 videó</comment>
- <comment xml:lang="ia">Video MPEG-4</comment>
- <comment xml:lang="id">Video MPEG-4</comment>
- <comment xml:lang="it">Video MPEG-4</comment>
- <comment xml:lang="ja">MPEG-4 動画</comment>
- <comment xml:lang="ka">MPEG-4 ვიდეო</comment>
- <comment xml:lang="kk">MPEG-4 видеосы</comment>
- <comment xml:lang="ko">MPEG-4 동영상</comment>
- <comment xml:lang="lt">MPEG-4 vaizdo įrašas</comment>
- <comment xml:lang="lv">MPEG-4 video</comment>
- <comment xml:lang="nb">MPEG-4-film</comment>
- <comment xml:lang="nl">MPEG4-video</comment>
- <comment xml:lang="nn">MPEG-4-video</comment>
- <comment xml:lang="oc">vidèo MPEG-4</comment>
- <comment xml:lang="pl">Plik wideo MPEG-4</comment>
- <comment xml:lang="pt">vídeo MPEG-4</comment>
- <comment xml:lang="pt_BR">Vídeo MPEG-4</comment>
- <comment xml:lang="ro">Video MPEG-4</comment>
- <comment xml:lang="ru">Видео MPEG-4</comment>
- <comment xml:lang="sk">Video MPEG-4</comment>
- <comment xml:lang="sl">Video datoteka MPEG-4</comment>
- <comment xml:lang="sq">Video MPEG-4</comment>
- <comment xml:lang="sr">МПЕГ-4 видео</comment>
- <comment xml:lang="sv">MPEG-4-video</comment>
- <comment xml:lang="tr">MPEG-4 video</comment>
- <comment xml:lang="uk">відеокліп MPEG-4</comment>
- <comment xml:lang="vi">Ảnh động MPEG-4</comment>
- <comment xml:lang="zh_CN">MPEG-4 视频</comment>
<comment xml:lang="zh_TW">MPEG-4 視訊</comment>
+ <comment xml:lang="zh_CN">MPEG-4 视频</comment>
+ <comment xml:lang="vi">Ảnh động MPEG-4</comment>
+ <comment xml:lang="uk">відеокліп MPEG-4</comment>
+ <comment xml:lang="tr">MPEG-4 video</comment>
+ <comment xml:lang="sv">MPEG-4-video</comment>
+ <comment xml:lang="sr">МПЕГ-4 видео</comment>
+ <comment xml:lang="sq">video MPEG-4</comment>
+ <comment xml:lang="sl">Video datoteka MPEG-4</comment>
+ <comment xml:lang="si">MPEG-4 වීඩියෝව</comment>
+ <comment xml:lang="sk">Video MPEG-4</comment>
+ <comment xml:lang="ru">Видео MPEG-4</comment>
+ <comment xml:lang="ro">Video MPEG-4</comment>
+ <comment xml:lang="pt_BR">Vídeo MPEG-4</comment>
+ <comment xml:lang="pt">vídeo MPEG-4</comment>
+ <comment xml:lang="pl">Plik wideo MPEG-4</comment>
+ <comment xml:lang="oc">vidèo MPEG-4</comment>
+ <comment xml:lang="nn">MPEG-4-video</comment>
+ <comment xml:lang="nl">MPEG4-video</comment>
+ <comment xml:lang="nb">MPEG-4-film</comment>
+ <comment xml:lang="lv">MPEG-4 video</comment>
+ <comment xml:lang="lt">MPEG-4 vaizdo įrašas</comment>
+ <comment xml:lang="ko">MPEG-4 동영상</comment>
+ <comment xml:lang="kk">MPEG-4 видеосы</comment>
+ <comment xml:lang="ka">MPEG-4 ვიდეო</comment>
+ <comment xml:lang="ja">MPEG-4 動画</comment>
+ <comment xml:lang="it">Video MPEG-4</comment>
+ <comment xml:lang="is">MPEG-4 myndskeið</comment>
+ <comment xml:lang="id">Video MPEG-4</comment>
+ <comment xml:lang="ia">Video MPEG-4</comment>
+ <comment xml:lang="hu">MPEG-4 videó</comment>
+ <comment xml:lang="hr">MPEG-4 video snimka</comment>
+ <comment xml:lang="he">וידאו MPEG-4</comment>
+ <comment xml:lang="gl">vídeo MPEG-4</comment>
+ <comment xml:lang="ga">físeán MPEG-4</comment>
+ <comment xml:lang="fur">video MPEG-4</comment>
+ <comment xml:lang="fr">vidéo MPEG-4</comment>
+ <comment xml:lang="fo">MPEG-4 video</comment>
+ <comment xml:lang="fi">MPEG-4-video</comment>
+ <comment xml:lang="eu">MPEG-4 bideoa</comment>
+ <comment xml:lang="es">vídeo MPEG-4</comment>
+ <comment xml:lang="eo">MPEG-4-video</comment>
+ <comment xml:lang="en_GB">MPEG-4 video</comment>
+ <comment xml:lang="el">Βίντεο MPEG-4</comment>
+ <comment xml:lang="de">MPEG-4-Video</comment>
+ <comment xml:lang="da">MPEG4-video</comment>
+ <comment xml:lang="cs">video MPEG-4</comment>
+ <comment xml:lang="ca">vídeo MPEG-4</comment>
+ <comment xml:lang="bg">Видео — MPEG-4</comment>
+ <comment xml:lang="be@latin">Videa MPEG-4</comment>
+ <comment xml:lang="be">відэа MPEG-4</comment>
+ <comment xml:lang="ast">Videu en MPEG-4</comment>
+ <comment xml:lang="ar">فيديو MPEG-4</comment>
+ <comment xml:lang="af">MPEG-4-video</comment>
<alias type="video/mp4v-es"/>
- <magic priority="50">
- <match value="ftypisom" type="string" offset="4"/>
- <match value="ftypmp42" type="string" offset="4"/>
- <match value="ftypMSNV" type="string" offset="4"/>
- <match value="ftypM4V " type="string" offset="4"/>
- <match value="ftypf4v " type="string" offset="4"/>
+ <magic>
+ <match type="string" value="ftypisom" offset="4"/>
+ <match type="string" value="ftypmp41" offset="4"/>
+ <match type="string" value="ftypmp42" offset="4"/>
+ <match type="string" value="ftypMSNV" offset="4"/>
+ <match type="string" value="ftypM4V " offset="4"/>
+ <match type="string" value="ftypf4v " offset="4"/>
</magic>
<glob pattern="*.mp4"/>
<glob pattern="*.m4v"/>
@@ -23279,118 +25432,128 @@
</mime-type>
<mime-type type="audio/x-m4b">
<comment>MPEG-4 audio book</comment>
- <comment xml:lang="ar">كتاب MPEG-4 السمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjokniha MPEG-4</comment>
- <comment xml:lang="bg">Аудио книга — MPEG-4</comment>
- <comment xml:lang="ca">llibre d'àudio MPEG-4</comment>
- <comment xml:lang="cs">zvuková kniha MPEG-4</comment>
- <comment xml:lang="da">MPEG4-lydbog</comment>
- <comment xml:lang="de">MPEG-4-Hörbuch</comment>
- <comment xml:lang="el">Ηχητικό βιβλίο MPEG-4</comment>
- <comment xml:lang="en_GB">MPEG-4 audio book</comment>
- <comment xml:lang="eo">MPEG-4-sonlibro</comment>
- <comment xml:lang="es">audiolibro MPEG-4</comment>
- <comment xml:lang="eu">MPEG-4 audio-liburua</comment>
- <comment xml:lang="fi">MPEG-4-äänikirja</comment>
- <comment xml:lang="fo">MPEG-4 ljóðbók</comment>
- <comment xml:lang="fr">livre audio MPEG-4</comment>
- <comment xml:lang="ga">closleabhar MPEG-4</comment>
- <comment xml:lang="gl">sonlibro de MPEG-4</comment>
- <comment xml:lang="he">ספר דיגיטלי MPEG-4</comment>
- <comment xml:lang="hr">MPEG-4 zvučna knjiga</comment>
- <comment xml:lang="hu">MPEG-4 hangoskönyv</comment>
- <comment xml:lang="ia">Libro audio MPEG-4</comment>
- <comment xml:lang="id">Buku audio MPEG-4</comment>
- <comment xml:lang="it">Audiolibro MPEG-4</comment>
- <comment xml:lang="ja">MPEG-4 オーディオブック</comment>
- <comment xml:lang="ka">MPEG-4 აუდიოწიგნი</comment>
- <comment xml:lang="kk">MPEG-4 аудио кітабы</comment>
- <comment xml:lang="ko">MPEG-4 오디오북</comment>
- <comment xml:lang="lt">MPEG-4 garso knyga</comment>
- <comment xml:lang="lv">MPEG-4 audio grāmata</comment>
- <comment xml:lang="nb">MPEG-4-lydbok</comment>
- <comment xml:lang="nl">MPEG4-audioboek</comment>
- <comment xml:lang="nn">MPEG-4-lydbok</comment>
- <comment xml:lang="oc">libre àudio MPEG-4</comment>
- <comment xml:lang="pl">Książka dźwiękowa MPEG-4</comment>
- <comment xml:lang="pt">livro áudio MPEG-4</comment>
- <comment xml:lang="pt_BR">Áudio livro MPEG-4</comment>
- <comment xml:lang="ro">Carte audio MPEG-4</comment>
- <comment xml:lang="ru">Аудиокнига MPEG-4</comment>
- <comment xml:lang="sk">Zvuková kniha MPEG-4</comment>
- <comment xml:lang="sl">Zvočna knjiga MPEG-4</comment>
- <comment xml:lang="sq">Audiolibër MPEG-4</comment>
- <comment xml:lang="sr">МПЕГ-4 звукотека</comment>
- <comment xml:lang="sv">MPEG-4-ljudbok</comment>
- <comment xml:lang="tr">MPEG-4 sesli kitabı</comment>
- <comment xml:lang="uk">аудіокнига MPEG-4</comment>
- <comment xml:lang="vi">Sách âm thanh MPEG-4</comment>
- <comment xml:lang="zh_CN">MPEG-4 有声书</comment>
<comment xml:lang="zh_TW">MPEG-4 音訊書</comment>
+ <comment xml:lang="zh_CN">MPEG-4 有声书</comment>
+ <comment xml:lang="vi">Sách âm thanh MPEG-4</comment>
+ <comment xml:lang="uk">аудіокнига MPEG-4</comment>
+ <comment xml:lang="tr">MPEG-4 sesli kitabı</comment>
+ <comment xml:lang="sv">MPEG-4-ljudbok</comment>
+ <comment xml:lang="sr">МПЕГ-4 звукотека</comment>
+ <comment xml:lang="sq">audiolibër MPEG-4</comment>
+ <comment xml:lang="sl">Zvočna knjiga MPEG-4</comment>
+ <comment xml:lang="si">MPEG-4 ශ්රව්ය පොත</comment>
+ <comment xml:lang="sk">Zvuková kniha MPEG-4</comment>
+ <comment xml:lang="ru">Аудиокнига MPEG-4</comment>
+ <comment xml:lang="ro">Carte audio MPEG-4</comment>
+ <comment xml:lang="pt_BR">Áudio livro MPEG-4</comment>
+ <comment xml:lang="pt">livro áudio MPEG-4</comment>
+ <comment xml:lang="pl">Książka dźwiękowa MPEG-4</comment>
+ <comment xml:lang="oc">libre àudio MPEG-4</comment>
+ <comment xml:lang="nn">MPEG-4-lydbok</comment>
+ <comment xml:lang="nl">MPEG4-audioboek</comment>
+ <comment xml:lang="nb">MPEG-4-lydbok</comment>
+ <comment xml:lang="lv">MPEG-4 audio grāmata</comment>
+ <comment xml:lang="lt">MPEG-4 garso knyga</comment>
+ <comment xml:lang="ko">MPEG-4 오디오북</comment>
+ <comment xml:lang="kk">MPEG-4 аудио кітабы</comment>
+ <comment xml:lang="ka">MPEG-4 აუდიოწიგნი</comment>
+ <comment xml:lang="ja">MPEG-4 オーディオブック</comment>
+ <comment xml:lang="it">Audiolibro MPEG-4</comment>
+ <comment xml:lang="is">MPEG-4 hljóðbók</comment>
+ <comment xml:lang="id">Buku audio MPEG-4</comment>
+ <comment xml:lang="ia">Libro audio MPEG-4</comment>
+ <comment xml:lang="hu">MPEG-4 hangoskönyv</comment>
+ <comment xml:lang="hr">MPEG-4 zvučna knjiga</comment>
+ <comment xml:lang="he">ספר דיגיטלי MPEG-4</comment>
+ <comment xml:lang="gl">sonlibro de MPEG-4</comment>
+ <comment xml:lang="ga">closleabhar MPEG-4</comment>
+ <comment xml:lang="fur">audio-libri MPEG-4</comment>
+ <comment xml:lang="fr">livre audio MPEG-4</comment>
+ <comment xml:lang="fo">MPEG-4 ljóðbók</comment>
+ <comment xml:lang="fi">MPEG-4-äänikirja</comment>
+ <comment xml:lang="eu">MPEG-4 audio-liburua</comment>
+ <comment xml:lang="es">audiolibro MPEG-4</comment>
+ <comment xml:lang="eo">MPEG-4-sonlibro</comment>
+ <comment xml:lang="en_GB">MPEG-4 audio book</comment>
+ <comment xml:lang="el">Ηχητικό βιβλίο MPEG-4</comment>
+ <comment xml:lang="de">MPEG-4-Hörbuch</comment>
+ <comment xml:lang="da">MPEG4-lydbog</comment>
+ <comment xml:lang="cs">zvuková kniha MPEG-4</comment>
+ <comment xml:lang="ca">llibre d'àudio MPEG-4</comment>
+ <comment xml:lang="bg">Аудио книга — MPEG-4</comment>
+ <comment xml:lang="be@latin">Aŭdyjokniha MPEG-4</comment>
+ <comment xml:lang="be">аўдыякніга MPEG-4</comment>
+ <comment xml:lang="ar">كتاب MPEG-4 صوتي</comment>
+ <comment xml:lang="af">MPEG-4-oudioboek</comment>
<sub-class-of type="audio/mp4"/>
- <magic priority="50">
- <match value="ftypM4B" type="string" offset="4"/>
+ <magic>
+ <match type="string" value="ftypM4B" offset="4"/>
</magic>
<glob pattern="*.m4b"/>
<glob pattern="*.f4b"/>
</mime-type>
<mime-type type="video/3gpp">
<comment>3GPP multimedia file</comment>
- <comment xml:lang="ar">ملف وسائط متعددة 3GPP</comment>
- <comment xml:lang="be@latin">Multymedyjny fajł 3GPP</comment>
- <comment xml:lang="bg">Мултимедия — 3GPP</comment>
- <comment xml:lang="ca">fitxer multimèdia 3GPP</comment>
- <comment xml:lang="cs">multimediální soubor 3GPP</comment>
- <comment xml:lang="da">3GPP multimedie-fil</comment>
- <comment xml:lang="de">3GPP-Multimediadatei</comment>
- <comment xml:lang="el">Αρχείο πολυμέσων 3GPP</comment>
- <comment xml:lang="en_GB">3GPP multimedia file</comment>
- <comment xml:lang="es">archivo multimedia 3GPP</comment>
- <comment xml:lang="eu">3GPP multimediako fitxategia</comment>
- <comment xml:lang="fi">3GPP-multimediatiedosto</comment>
- <comment xml:lang="fo">3GGP margmiðlafíla</comment>
- <comment xml:lang="fr">fichier multimédia 3GPP</comment>
- <comment xml:lang="ga">comhad ilmheán 3GPP</comment>
- <comment xml:lang="gl">ficheiro multimedia 3GPP</comment>
- <comment xml:lang="he">קובץ מולטימדיה מסוג 3GPP</comment>
- <comment xml:lang="hr">3GPP multimedijska datoteka</comment>
- <comment xml:lang="hu">3GPP multimédiafájl</comment>
- <comment xml:lang="ia">File multimedial 3GPP</comment>
- <comment xml:lang="id">Berkas multimedia 3GPP</comment>
- <comment xml:lang="it">File multimediale 3GPP</comment>
- <comment xml:lang="ja">3GPP マルチメディアファイル</comment>
- <comment xml:lang="ka">3GPP მულტიმედიური ფაილი</comment>
- <comment xml:lang="kk">3GPP мультимедиялық файлы</comment>
- <comment xml:lang="ko">3GPP 멀티미디어 파일</comment>
- <comment xml:lang="lt">3GPP multimedijos failas</comment>
- <comment xml:lang="lv">3GPP multimediju datne</comment>
- <comment xml:lang="nb">3GPP-multimediafil</comment>
- <comment xml:lang="nl">3GPP-multimediabestand</comment>
- <comment xml:lang="nn">3GPP-multimediafil</comment>
- <comment xml:lang="oc">fichièr multimèdia 3GPP</comment>
- <comment xml:lang="pl">Plik multimedialny 3GPP</comment>
- <comment xml:lang="pt">ficheiro multimédia 3GPP</comment>
- <comment xml:lang="pt_BR">Arquivo multimídia 3GPP</comment>
- <comment xml:lang="ro">Fișier multimedia 3GPP</comment>
- <comment xml:lang="ru">Мультимедийный файл 3GPP</comment>
- <comment xml:lang="sk">Súbor multimédií 3GPP</comment>
- <comment xml:lang="sl">Večpredstavnostna datoteka 3GPP</comment>
- <comment xml:lang="sq">File multimedial 3GPP</comment>
- <comment xml:lang="sr">3ГПП мултимедијална датотека</comment>
- <comment xml:lang="sv">3GPP-multimediafil</comment>
- <comment xml:lang="tr">3GPP multimedya dosyası</comment>
- <comment xml:lang="uk">файл мультимедійних даних 3GPP</comment>
- <comment xml:lang="vi">Tập tin đa phương tiện 3GPP</comment>
- <comment xml:lang="zh_CN">3GPP 多媒体文件</comment>
<comment xml:lang="zh_TW">3GPP 多媒體檔案</comment>
+ <comment xml:lang="zh_CN">3GPP 多媒体文件</comment>
+ <comment xml:lang="vi">Tập tin đa phương tiện 3GPP</comment>
+ <comment xml:lang="uk">файл мультимедійних даних 3GPP</comment>
+ <comment xml:lang="tr">3GPP çoklu ortam dosyası</comment>
+ <comment xml:lang="sv">3GPP-multimediafil</comment>
+ <comment xml:lang="sr">3ГПП мултимедијална датотека</comment>
+ <comment xml:lang="sq">kartelë multimedia 3GPP</comment>
+ <comment xml:lang="sl">Večpredstavnostna datoteka 3GPP</comment>
+ <comment xml:lang="si">3GPP බහුමාධ්‍ය ගොනුව</comment>
+ <comment xml:lang="sk">Súbor multimédií 3GPP</comment>
+ <comment xml:lang="ru">Мультимедийный файл 3GPP</comment>
+ <comment xml:lang="ro">Fișier multimedia 3GPP</comment>
+ <comment xml:lang="pt_BR">Arquivo multimídia 3GPP</comment>
+ <comment xml:lang="pt">ficheiro multimédia 3GPP</comment>
+ <comment xml:lang="pl">Plik multimedialny 3GPP</comment>
+ <comment xml:lang="oc">fichièr multimèdia 3GPP</comment>
+ <comment xml:lang="nn">3GPP-multimediafil</comment>
+ <comment xml:lang="nl">3GPP-multimediabestand</comment>
+ <comment xml:lang="nb">3GPP-multimediafil</comment>
+ <comment xml:lang="lv">3GPP multimediju datne</comment>
+ <comment xml:lang="lt">3GPP multimedijos failas</comment>
+ <comment xml:lang="ko">3GPP 멀티미디어 파일</comment>
+ <comment xml:lang="kk">3GPP мультимедиялық файлы</comment>
+ <comment xml:lang="ka">3GPP მულტიმედიური ფაილი</comment>
+ <comment xml:lang="ja">3GPP マルチメディアファイル</comment>
+ <comment xml:lang="it">File multimediale 3GPP</comment>
+ <comment xml:lang="is">3GPP margmiðlunarskrá</comment>
+ <comment xml:lang="id">Berkas multimedia 3GPP</comment>
+ <comment xml:lang="ia">File multimedial 3GPP</comment>
+ <comment xml:lang="hu">3GPP multimédiafájl</comment>
+ <comment xml:lang="hr">3GPP multimedijska datoteka</comment>
+ <comment xml:lang="he">קובץ מולטימדיה מסוג 3GPP</comment>
+ <comment xml:lang="gl">ficheiro multimedia 3GPP</comment>
+ <comment xml:lang="ga">comhad ilmheán 3GPP</comment>
+ <comment xml:lang="fur">file multimediâl 3GPP</comment>
+ <comment xml:lang="fr">fichier multimédia 3GPP</comment>
+ <comment xml:lang="fo">3GGP margmiðlafíla</comment>
+ <comment xml:lang="fi">3GPP-multimediatiedosto</comment>
+ <comment xml:lang="eu">3GPP multimediako fitxategia</comment>
+ <comment xml:lang="es">archivo multimedia 3GPP</comment>
+ <comment xml:lang="en_GB">3GPP multimedia file</comment>
+ <comment xml:lang="el">Αρχείο πολυμέσων 3GPP</comment>
+ <comment xml:lang="de">3GPP-Multimediadatei</comment>
+ <comment xml:lang="da">3GPP multimedie-fil</comment>
+ <comment xml:lang="cs">multimediální soubor 3GPP</comment>
+ <comment xml:lang="ca">fitxer multimèdia 3GPP</comment>
+ <comment xml:lang="bg">Мултимедия — 3GPP</comment>
+ <comment xml:lang="be@latin">Multymedyjny fajł 3GPP</comment>
+ <comment xml:lang="be">мультымедыйны файл 3GPP</comment>
+ <comment xml:lang="ar">ملف وسائط متعددة 3GPP</comment>
+ <comment xml:lang="af">3GPP-multimedialêer</comment>
<acronym>3GPP</acronym>
<expanded-acronym>3rd Generation Partnership Project</expanded-acronym>
<sub-class-of type="video/mp4"/>
- <magic priority="50">
- <match value="ftyp3ge" type="string" offset="4"/>
- <match value="ftyp3gg" type="string" offset="4"/>
- <match value="ftyp3gp" type="string" offset="4"/>
- <match value="ftyp3gs" type="string" offset="4"/>
+ <magic>
+ <match type="string" value="ftyp3ge" offset="4"/>
+ <match type="string" value="ftyp3gg" offset="4"/>
+ <match type="string" value="ftyp3gp" offset="4"/>
+ <match type="string" value="ftyp3gs" offset="4"/>
</magic>
<glob pattern="*.3gp"/>
<glob pattern="*.3gpp"/>
@@ -23406,52 +25569,58 @@
</mime-type>
<mime-type type="video/3gpp2">
<comment>3GPP2 multimedia file</comment>
- <comment xml:lang="ar">ملف وسائط متعددة 3GPP2</comment>
- <comment xml:lang="bg">Мултимедия — 3GPP2</comment>
- <comment xml:lang="ca">fitxer multimèdia 3GPP2</comment>
- <comment xml:lang="cs">multimediální soubor 3GPP2</comment>
- <comment xml:lang="da">3GPP2 multimedie-fil</comment>
- <comment xml:lang="de">3GPP2-Multimediadatei</comment>
- <comment xml:lang="el">Αρχείο πολυμέσων 3GPP2</comment>
- <comment xml:lang="en_GB">3GPP2 multimedia file</comment>
- <comment xml:lang="es">archivo multimedia 3GPP2</comment>
- <comment xml:lang="eu">3GPP2 multimediako fitxategia</comment>
- <comment xml:lang="fi">3GPP2-multimediatiedosto</comment>
- <comment xml:lang="fo">3GGP2 margmiðlafíla</comment>
- <comment xml:lang="fr">fichier multimédia 3GPP2</comment>
- <comment xml:lang="ga">comhad ilmheán 3GPP2</comment>
- <comment xml:lang="gl">ficheiro multimedia 3GPP2</comment>
- <comment xml:lang="he">קובץ מולטימדיה 3GPP2</comment>
- <comment xml:lang="hr">3GPP2 multimedijska datoteka</comment>
- <comment xml:lang="hu">3GPP2 multimédiafájl</comment>
- <comment xml:lang="ia">File multimedial 3GPP2</comment>
- <comment xml:lang="id">Berkas multimedia 3GPP2</comment>
- <comment xml:lang="it">File multimediale 3GPP2</comment>
- <comment xml:lang="ja">3GPP2 マルチメディアファイル</comment>
- <comment xml:lang="ka">3GPP2 მულტიმედიური ფაილი</comment>
- <comment xml:lang="kk">3GPP2 мультимедиялық файлы</comment>
- <comment xml:lang="ko">3GPP2 멀티미디어 파일</comment>
- <comment xml:lang="lv">3GPP2 multimediju datne</comment>
- <comment xml:lang="nl">3GPP2 multimedia bestand</comment>
- <comment xml:lang="oc">fichièr multimèdia 3GPP2</comment>
- <comment xml:lang="pl">Plik multimedialny 3GPP2</comment>
- <comment xml:lang="pt">ficheiro multimédia 3GPP2</comment>
- <comment xml:lang="pt_BR">Arquivo multimídia 3GPP2</comment>
- <comment xml:lang="ro">Fișier multimedia 3GPP2</comment>
- <comment xml:lang="ru">Мультимедийный файл 3GPP2</comment>
- <comment xml:lang="sk">Súbor multimédií 3GPP2</comment>
- <comment xml:lang="sl">Večpredstavnostna datoteka 3GPP2</comment>
- <comment xml:lang="sr">3ГПП2 мултимедијална датотека</comment>
- <comment xml:lang="sv">3GPP2-multimediafil</comment>
- <comment xml:lang="tr">3GPP2 multimedya dosyası</comment>
- <comment xml:lang="uk">файл мультимедійних даних 3GPP2</comment>
- <comment xml:lang="zh_CN">3GPP2 多媒体文件</comment>
<comment xml:lang="zh_TW">3GPP2 多媒體檔案</comment>
+ <comment xml:lang="zh_CN">3GPP2 多媒体文件</comment>
+ <comment xml:lang="uk">файл мультимедійних даних 3GPP2</comment>
+ <comment xml:lang="tr">3GPP2 çoklu ortam dosyası</comment>
+ <comment xml:lang="sv">3GPP2-multimediafil</comment>
+ <comment xml:lang="sr">3ГПП2 мултимедијална датотека</comment>
+ <comment xml:lang="sq">kartelë multimedia 3GPP2</comment>
+ <comment xml:lang="sl">Večpredstavnostna datoteka 3GPP2</comment>
+ <comment xml:lang="si">3GPP2 බහුමාධ්‍ය ගොනුව</comment>
+ <comment xml:lang="sk">Súbor multimédií 3GPP2</comment>
+ <comment xml:lang="ru">Мультимедийный файл 3GPP2</comment>
+ <comment xml:lang="ro">Fișier multimedia 3GPP2</comment>
+ <comment xml:lang="pt_BR">Arquivo multimídia 3GPP2</comment>
+ <comment xml:lang="pt">ficheiro multimédia 3GPP2</comment>
+ <comment xml:lang="pl">Plik multimedialny 3GPP2</comment>
+ <comment xml:lang="oc">fichièr multimèdia 3GPP2</comment>
+ <comment xml:lang="nl">3GPP2-multimediabestand</comment>
+ <comment xml:lang="lv">3GPP2 multimediju datne</comment>
+ <comment xml:lang="lt">3GPP2 multimedijos failas</comment>
+ <comment xml:lang="ko">3GPP2 멀티미디어 파일</comment>
+ <comment xml:lang="kk">3GPP2 мультимедиялық файлы</comment>
+ <comment xml:lang="ka">3GPP2 მულტიმედიური ფაილი</comment>
+ <comment xml:lang="ja">3GPP2 マルチメディアファイル</comment>
+ <comment xml:lang="it">File multimediale 3GPP2</comment>
+ <comment xml:lang="is">3GPP2 margmiðlunarskrá</comment>
+ <comment xml:lang="id">Berkas multimedia 3GPP2</comment>
+ <comment xml:lang="ia">File multimedial 3GPP2</comment>
+ <comment xml:lang="hu">3GPP2 multimédiafájl</comment>
+ <comment xml:lang="hr">3GPP2 multimedijska datoteka</comment>
+ <comment xml:lang="he">קובץ מולטימדיה 3GPP2</comment>
+ <comment xml:lang="gl">ficheiro multimedia 3GPP2</comment>
+ <comment xml:lang="ga">comhad ilmheán 3GPP2</comment>
+ <comment xml:lang="fur">file multimediâl 3GPP2</comment>
+ <comment xml:lang="fr">fichier multimédia 3GPP2</comment>
+ <comment xml:lang="fo">3GGP2 margmiðlafíla</comment>
+ <comment xml:lang="fi">3GPP2-multimediatiedosto</comment>
+ <comment xml:lang="eu">3GPP2 multimediako fitxategia</comment>
+ <comment xml:lang="es">archivo multimedia 3GPP2</comment>
+ <comment xml:lang="en_GB">3GPP2 multimedia file</comment>
+ <comment xml:lang="el">Αρχείο πολυμέσων 3GPP2</comment>
+ <comment xml:lang="de">3GPP2-Multimediadatei</comment>
+ <comment xml:lang="da">3GPP2 multimedie-fil</comment>
+ <comment xml:lang="cs">multimediální soubor 3GPP2</comment>
+ <comment xml:lang="ca">fitxer multimèdia 3GPP2</comment>
+ <comment xml:lang="bg">Мултимедия — 3GPP2</comment>
+ <comment xml:lang="be">мультымедыйны файл 3GPP2</comment>
+ <comment xml:lang="ar">ملف وسائط متعددة 3GPP2</comment>
+ <comment xml:lang="af">3GPP2-multimedialêer</comment>
<acronym>3GPP2</acronym>
<expanded-acronym>3rd Generation Partnership Project 2</expanded-acronym>
- <sub-class-of type="video/mp4"/>
- <magic priority="50">
- <match value="ftyp3g2" type="string" offset="4"/>
+ <magic>
+ <match type="string" value="ftyp3g2" offset="4"/>
</magic>
<glob pattern="*.3g2"/>
<glob pattern="*.3gp2"/>
@@ -23460,88 +25629,113 @@
</mime-type>
<mime-type type="audio/x-mod">
<comment>Amiga SoundTracker audio</comment>
- <comment xml:lang="ar">مقتفي صوت Amiga السمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Amiga SoundTracker</comment>
- <comment xml:lang="bg">Аудио — Amiga SoundTracker</comment>
- <comment xml:lang="ca">àudio SoundTracker d'Amiga</comment>
- <comment xml:lang="cs">zvuk Amiga SoundTracker</comment>
- <comment xml:lang="da">Amiga SoundTracker-lyd</comment>
- <comment xml:lang="de">Amiga-SoundTracker-Audio</comment>
- <comment xml:lang="el">Ήχος Amiga SoundTracker</comment>
- <comment xml:lang="en_GB">Amiga SoundTracker audio</comment>
- <comment xml:lang="eo">Sondosiero de Amiga SoundTracker</comment>
- <comment xml:lang="es">sonido de Amiga SoundTracker</comment>
- <comment xml:lang="eu">Amiga soundtracker audioa</comment>
- <comment xml:lang="fi">Amiga SoundTracker -ääni</comment>
- <comment xml:lang="fo">Amiga SoundTracker ljóður</comment>
- <comment xml:lang="fr">audio SoundTracker Amiga</comment>
- <comment xml:lang="ga">fuaim Amiga SoundTracker</comment>
- <comment xml:lang="gl">son de Amiga SoundTracker</comment>
- <comment xml:lang="he">קובץ שמע של Amiga SoundTracker</comment>
- <comment xml:lang="hr">Amiga SoundTracker zvučni zapis</comment>
- <comment xml:lang="hu">Amiga SoundTracker hang</comment>
- <comment xml:lang="ia">Audio Amiga SoundTracker</comment>
- <comment xml:lang="id">Audio Amida SoundTracker</comment>
- <comment xml:lang="it">Audio Amiga SoundTracker</comment>
- <comment xml:lang="ja">Amiga SoundTracker オーディオ</comment>
- <comment xml:lang="ka">Amiga SoundTracker-ის აუდიო</comment>
- <comment xml:lang="kk">Amiga SoundTracker аудиосы</comment>
- <comment xml:lang="ko">Amiga SoundTracker 오디오</comment>
- <comment xml:lang="lt">Amiga SoundTracker garso įrašas</comment>
- <comment xml:lang="lv">Amiga SoundTracker audio</comment>
- <comment xml:lang="ms">Audio Amiga Soundtracker</comment>
- <comment xml:lang="nb">Amiga SoundTracker-lyd</comment>
- <comment xml:lang="nl">Amiga SoundTracker-audio</comment>
- <comment xml:lang="nn">Amiga soundtracker-lyd</comment>
- <comment xml:lang="oc">àudio SoundTracker Amiga</comment>
- <comment xml:lang="pl">Plik dźwiękowy Amiga SoundTracker</comment>
- <comment xml:lang="pt">áudio SoundTracker do Amiga</comment>
- <comment xml:lang="pt_BR">Áudio Amiga SoundTracker</comment>
- <comment xml:lang="ro">Audio Amiga SoundTracker</comment>
- <comment xml:lang="ru">Аудио Amiga SoundTracker</comment>
- <comment xml:lang="sk">Zvuk Amiga SoundTracker</comment>
- <comment xml:lang="sl">Zvočna datoteka Amiga SoundTracker</comment>
- <comment xml:lang="sq">Audio Amiga SoundTracker</comment>
- <comment xml:lang="sr">звук Амигиног Пратиоца Звука</comment>
- <comment xml:lang="sv">Amiga SoundTracker-ljud</comment>
- <comment xml:lang="tr">Amiga SoundTracker sesi</comment>
- <comment xml:lang="uk">звук Amiga SoundTracker</comment>
- <comment xml:lang="vi">Âm thanh Amiga SoundTracker</comment>
- <comment xml:lang="zh_CN">Amiga SoundTracker 音频</comment>
<comment xml:lang="zh_TW">Amiga SoundTracker 音訊</comment>
+ <comment xml:lang="zh_CN">Amiga SoundTracker 音频</comment>
+ <comment xml:lang="vi">Âm thanh Amiga SoundTracker</comment>
+ <comment xml:lang="uk">звук Amiga SoundTracker</comment>
+ <comment xml:lang="tr">Amiga SoundTracker sesi</comment>
+ <comment xml:lang="sv">Amiga SoundTracker-ljud</comment>
+ <comment xml:lang="sr">звук Амигиног Пратиоца Звука</comment>
+ <comment xml:lang="sq">audio Amiga SoundTracker</comment>
+ <comment xml:lang="sl">Zvočna datoteka Amiga SoundTracker</comment>
+ <comment xml:lang="si">Amiga SoundTracker ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk Amiga SoundTracker</comment>
+ <comment xml:lang="ru">Аудио Amiga SoundTracker</comment>
+ <comment xml:lang="ro">Audio Amiga SoundTracker</comment>
+ <comment xml:lang="pt_BR">Áudio Amiga SoundTracker</comment>
+ <comment xml:lang="pt">áudio SoundTracker do Amiga</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Amiga SoundTracker</comment>
+ <comment xml:lang="oc">àudio SoundTracker Amiga</comment>
+ <comment xml:lang="nn">Amiga soundtracker-lyd</comment>
+ <comment xml:lang="nl">Amiga SoundTracker-audio</comment>
+ <comment xml:lang="nb">Amiga SoundTracker-lyd</comment>
+ <comment xml:lang="ms">Audio Amiga Soundtracker</comment>
+ <comment xml:lang="lv">Amiga SoundTracker audio</comment>
+ <comment xml:lang="lt">Amiga SoundTracker garso įrašas</comment>
+ <comment xml:lang="ko">Amiga SoundTracker 오디오</comment>
+ <comment xml:lang="kk">Amiga SoundTracker аудиосы</comment>
+ <comment xml:lang="ka">Amiga SoundTracker-ის აუდიო</comment>
+ <comment xml:lang="ja">Amiga SoundTracker オーディオ</comment>
+ <comment xml:lang="it">Audio Amiga SoundTracker</comment>
+ <comment xml:lang="is">Amiga SoundTracker hljóðskrá</comment>
+ <comment xml:lang="id">Audio Amida SoundTracker</comment>
+ <comment xml:lang="ia">Audio Amiga SoundTracker</comment>
+ <comment xml:lang="hu">Amiga SoundTracker hang</comment>
+ <comment xml:lang="hr">Amiga SoundTracker zvučni zapis</comment>
+ <comment xml:lang="he">קובץ שמע של Amiga SoundTracker</comment>
+ <comment xml:lang="gl">son de Amiga SoundTracker</comment>
+ <comment xml:lang="ga">fuaim Amiga SoundTracker</comment>
+ <comment xml:lang="fur">audio Amiga SoundTracker</comment>
+ <comment xml:lang="fr">audio SoundTracker Amiga</comment>
+ <comment xml:lang="fo">Amiga SoundTracker ljóður</comment>
+ <comment xml:lang="fi">Amiga SoundTracker -ääni</comment>
+ <comment xml:lang="eu">Amiga soundtracker audioa</comment>
+ <comment xml:lang="es">sonido de Amiga SoundTracker</comment>
+ <comment xml:lang="eo">Sondosiero de Amiga SoundTracker</comment>
+ <comment xml:lang="en_GB">Amiga SoundTracker audio</comment>
+ <comment xml:lang="el">Ήχος Amiga SoundTracker</comment>
+ <comment xml:lang="de">Amiga-SoundTracker-Audio</comment>
+ <comment xml:lang="da">Amiga SoundTracker-lyd</comment>
+ <comment xml:lang="cs">zvuk Amiga SoundTracker</comment>
+ <comment xml:lang="ca">àudio SoundTracker d'Amiga</comment>
+ <comment xml:lang="bg">Аудио — Amiga SoundTracker</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Amiga SoundTracker</comment>
+ <comment xml:lang="be">аўдыя Amiga SoundTracker</comment>
+ <comment xml:lang="ar">مقتفي صوت Amiga السمعي</comment>
<magic priority="40">
- <match value="MTM" type="string" offset="0"/>
- <match value="MMD0" type="string" offset="0"/>
- <match value="MMD1" type="string" offset="0"/>
- <match value="if" type="string" offset="0">
-
- <match value="0x0" type="byte" offset="110" mask="0xc0">
-
- <match value="0x0" type="byte" offset="111" mask="0x80"/>
- <match value="0x80" type="byte" offset="111"/>
- </match>
-
- <match value="0x40" type="byte" offset="110">
-
- <match value="0x0" type="byte" offset="111" mask="0x80"/>
- <match value="0x80" type="byte" offset="111"/>
- </match>
- </match>
- <match value="JN" type="string" offset="0">
-
- <match value="0x0" type="byte" offset="110" mask="0xc0">
-
- <match value="0x0" type="byte" offset="111" mask="0x80"/>
- <match value="0x80" type="byte" offset="111"/>
+ <match type="string" value="MTM" offset="0"/>
+ <match type="string" value="MMD0" offset="0"/>
+ <match type="string" value="MMD1" offset="0"/>
+ <!-- 669 composer files: "if" and "JN" -->
+ <match type="byte" value="0x0" mask="0x80" offset="112">
+ <match type="string" value="if" offset="0">
+ <!-- tempo list last byte: 0-31 (0 = known false positive) -->
+ <match type="byte" value="0x0" mask="0xe0" offset="368">
+ <!-- number of samples: 0-63 -->
+ <match type="byte" value="0x0" mask="0xc0" offset="110">
+ <!-- number of patterns: 0-128 -->
+ <match type="byte" value="0x0" mask="0x80" offset="111"/>
+ <match type="byte" value="0x80" offset="111"/>
+ </match>
+ <!-- number of samples: 64 -->
+ <match type="byte" value="0x40" offset="110">
+ <match type="byte" value="0x0" mask="0x80" offset="111"/>
+ <match type="byte" value="0x80" offset="111"/>
+ </match>
+ </match>
+ <!-- tempo list last byte: 32 -->
+ <match type="byte" value="0x20" offset="368">
+ <!-- number of samples: 0-63 -->
+ <match type="byte" value="0x0" mask="0xc0" offset="110">
+ <!-- number of patterns: 0-128 -->
+ <match type="byte" value="0x0" mask="0x80" offset="111"/>
+ <match type="byte" value="0x80" offset="111"/>
+ </match>
+ <!-- number of samples: 64 -->
+ <match type="byte" value="0x40" offset="110">
+ <match type="byte" value="0x0" mask="0x80" offset="111"/>
+ <match type="byte" value="0x80" offset="111"/>
+ </match>
+ </match>
</match>
-
- <match value="0x40" type="byte" offset="110">
-
- <match value="0x0" type="byte" offset="111" mask="0x80"/>
- <match value="0x80" type="byte" offset="111"/>
+ <match type="string" value="JN" offset="0">
+ <match type="byte" value="0x0" mask="0xe0" offset="368">
+ <match type="byte" value="0x0" mask="0xc0" offset="110">
+ <match type="byte" value="0x0" mask="0x80" offset="111"/>
+ <match type="byte" value="0x80" offset="111"/>
+ </match>
+ </match>
+ <match type="byte" value="0x20" offset="368">
+ <match type="byte" value="0x40" offset="110">
+ <match type="byte" value="0x0" mask="0x80" offset="111"/>
+ <match type="byte" value="0x80" offset="111"/>
+ </match>
+ </match>
</match>
</match>
- <match value="MAS_UTrack_V00" type="string" offset="0"/>
+ <match type="string" value="MAS_UTrack_V00" offset="0"/>
+ <match type="string" value="M.K." offset="1080"/>
+ <match type="string" value="M!K!" offset="1080"/>
</magic>
<glob pattern="*.mod"/>
<glob pattern="*.ult"/>
@@ -23553,171 +25747,159 @@
</mime-type>
<mime-type type="audio/mp2">
<comment>MP2 audio</comment>
- <comment xml:lang="ar">MP2 سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo MP2</comment>
- <comment xml:lang="bg">Аудио — MP2</comment>
- <comment xml:lang="ca">àudio MP2</comment>
- <comment xml:lang="cs">zvuk MP2</comment>
- <comment xml:lang="da">MP2-lyd</comment>
- <comment xml:lang="de">MP2-Audio</comment>
- <comment xml:lang="el">Ήχος MP2</comment>
- <comment xml:lang="en_GB">MP2 audio</comment>
- <comment xml:lang="eo">MP2-sondosiero</comment>
- <comment xml:lang="es">sonido MP2</comment>
- <comment xml:lang="eu">MP2 audioa</comment>
- <comment xml:lang="fi">MP2-ääni</comment>
- <comment xml:lang="fo">MP2 ljóður</comment>
- <comment xml:lang="fr">audio MP2</comment>
- <comment xml:lang="ga">fuaim MP2</comment>
- <comment xml:lang="gl">son MP2</comment>
- <comment xml:lang="he">שמע MP2</comment>
- <comment xml:lang="hr">MP2 zvučni zapis</comment>
- <comment xml:lang="hu">MP2 hang</comment>
- <comment xml:lang="ia">Audio MP2</comment>
- <comment xml:lang="id">Audio MP2</comment>
- <comment xml:lang="it">Audio MP2</comment>
- <comment xml:lang="ja">MP2 オーディオ</comment>
- <comment xml:lang="kk">MP2 аудиосы</comment>
- <comment xml:lang="ko">MP2 오디오</comment>
- <comment xml:lang="lt">MP2 garso įrašas</comment>
- <comment xml:lang="lv">MP2 audio</comment>
- <comment xml:lang="nb">MP2-lyd</comment>
- <comment xml:lang="nl">MP2-audio</comment>
- <comment xml:lang="nn">MP2-lyd</comment>
- <comment xml:lang="oc">àudio MP2</comment>
- <comment xml:lang="pl">Plik dźwiękowy MP2</comment>
- <comment xml:lang="pt">áudio MP2</comment>
- <comment xml:lang="pt_BR">Áudio MP2</comment>
- <comment xml:lang="ro">Audio MP2</comment>
- <comment xml:lang="ru">Аудио MP2</comment>
- <comment xml:lang="sk">Zvuk MP2</comment>
- <comment xml:lang="sl">Zvočna datoteka MP2</comment>
- <comment xml:lang="sq">Audio MP2</comment>
- <comment xml:lang="sr">МП2 звук</comment>
- <comment xml:lang="sv">MP2-ljud</comment>
- <comment xml:lang="tr">MP2 sesi</comment>
- <comment xml:lang="uk">звук MP2</comment>
- <comment xml:lang="vi">Âm thanh MP2</comment>
- <comment xml:lang="zh_CN">MP2 音频</comment>
<comment xml:lang="zh_TW">MP2 音訊</comment>
+ <comment xml:lang="zh_CN">MP2 音频</comment>
+ <comment xml:lang="vi">Âm thanh MP2</comment>
+ <comment xml:lang="uk">звук MP2</comment>
+ <comment xml:lang="tr">MP2 sesi</comment>
+ <comment xml:lang="sv">MP2-ljud</comment>
+ <comment xml:lang="sr">МП2 звук</comment>
+ <comment xml:lang="sq">audio MP2</comment>
+ <comment xml:lang="sl">Zvočna datoteka MP2</comment>
+ <comment xml:lang="si">MP2 ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk MP2</comment>
+ <comment xml:lang="ru">Аудио MP2</comment>
+ <comment xml:lang="ro">Audio MP2</comment>
+ <comment xml:lang="pt_BR">Áudio MP2</comment>
+ <comment xml:lang="pt">áudio MP2</comment>
+ <comment xml:lang="pl">Plik dźwiękowy MP2</comment>
+ <comment xml:lang="oc">àudio MP2</comment>
+ <comment xml:lang="nn">MP2-lyd</comment>
+ <comment xml:lang="nl">MP2-audio</comment>
+ <comment xml:lang="nb">MP2-lyd</comment>
+ <comment xml:lang="lv">MP2 audio</comment>
+ <comment xml:lang="lt">MP2 garso įrašas</comment>
+ <comment xml:lang="ko">MP2 오디오</comment>
+ <comment xml:lang="kk">MP2 аудиосы</comment>
+ <comment xml:lang="ja">MP2 オーディオ</comment>
+ <comment xml:lang="it">Audio MP2</comment>
+ <comment xml:lang="is">MP2 hljóðskrá</comment>
+ <comment xml:lang="id">Audio MP2</comment>
+ <comment xml:lang="ia">Audio MP2</comment>
+ <comment xml:lang="hu">MP2 hang</comment>
+ <comment xml:lang="hr">MP2 zvučni zapis</comment>
+ <comment xml:lang="he">שמע MP2</comment>
+ <comment xml:lang="gl">son MP2</comment>
+ <comment xml:lang="ga">fuaim MP2</comment>
+ <comment xml:lang="fur">audio MP2</comment>
+ <comment xml:lang="fr">audio MP2</comment>
+ <comment xml:lang="fo">MP2 ljóður</comment>
+ <comment xml:lang="fi">MP2-ääni</comment>
+ <comment xml:lang="eu">MP2 audioa</comment>
+ <comment xml:lang="es">sonido MP2</comment>
+ <comment xml:lang="eo">MP2-sondosiero</comment>
+ <comment xml:lang="en_GB">MP2 audio</comment>
+ <comment xml:lang="el">Ήχος MP2</comment>
+ <comment xml:lang="de">MP2-Audio</comment>
+ <comment xml:lang="da">MP2-lyd</comment>
+ <comment xml:lang="cs">zvuk MP2</comment>
+ <comment xml:lang="ca">àudio MP2</comment>
+ <comment xml:lang="bg">Аудио — MP2</comment>
+ <comment xml:lang="be@latin">Aŭdyjo MP2</comment>
+ <comment xml:lang="be">аўдыя MP2</comment>
+ <comment xml:lang="ar">صوت MP2</comment>
+ <comment xml:lang="af">MP2-oudio</comment>
<alias type="audio/x-mp2"/>
<glob pattern="*.mp2"/>
</mime-type>
<mime-type type="audio/mpeg">
<comment>MP3 audio</comment>
- <comment xml:lang="ar">MP3 سمعي</comment>
- <comment xml:lang="az">MP3 audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo MP3</comment>
- <comment xml:lang="bg">Аудио — MP3</comment>
- <comment xml:lang="ca">àudio MP3</comment>
- <comment xml:lang="cs">zvuk MP3</comment>
- <comment xml:lang="cy">Sain MP3</comment>
- <comment xml:lang="da">MP3-lyd</comment>
- <comment xml:lang="de">MP3-Audio</comment>
- <comment xml:lang="el">Ήχος MP3</comment>
- <comment xml:lang="en_GB">MP3 audio</comment>
- <comment xml:lang="eo">MP3-sondosiero</comment>
- <comment xml:lang="es">sonido MP3</comment>
- <comment xml:lang="eu">MP3 audioa</comment>
- <comment xml:lang="fi">MP3-ääni</comment>
- <comment xml:lang="fo">MP3 ljóður</comment>
- <comment xml:lang="fr">audio MP3</comment>
- <comment xml:lang="ga">fuaim MP3</comment>
- <comment xml:lang="gl">son MP3</comment>
- <comment xml:lang="he">שמע MP3</comment>
- <comment xml:lang="hr">MP3 zvučni zapis</comment>
- <comment xml:lang="hu">MP3 hang</comment>
- <comment xml:lang="ia">Audio MP3</comment>
- <comment xml:lang="id">Audio MP3</comment>
- <comment xml:lang="it">Audio MP3</comment>
- <comment xml:lang="ja">MP3 オーディオ</comment>
- <comment xml:lang="ka">MP3 აუდიო</comment>
- <comment xml:lang="kk">MP3 аудиосы</comment>
- <comment xml:lang="ko">MP3 오디오</comment>
- <comment xml:lang="lt">MP3 garso įrašas</comment>
- <comment xml:lang="lv">MP3 audio</comment>
- <comment xml:lang="ms">Audio MP3</comment>
- <comment xml:lang="nb">MP3-lyd</comment>
- <comment xml:lang="nl">MP3-audio</comment>
- <comment xml:lang="nn">MP3-lyd</comment>
- <comment xml:lang="oc">àudio MP3</comment>
- <comment xml:lang="pl">Plik dźwiękowy MP3</comment>
- <comment xml:lang="pt">áudio MP3</comment>
- <comment xml:lang="pt_BR">Áudio MP3</comment>
- <comment xml:lang="ro">Audio MP3</comment>
- <comment xml:lang="ru">Аудио MP3</comment>
- <comment xml:lang="sk">Zvuk MP3</comment>
- <comment xml:lang="sl">Zvočna datoteka MP3</comment>
- <comment xml:lang="sq">Audio MP3</comment>
- <comment xml:lang="sr">МП3 звук</comment>
- <comment xml:lang="sv">MP3-ljud</comment>
- <comment xml:lang="tr">MP3 sesi</comment>
- <comment xml:lang="uk">звук MP3</comment>
- <comment xml:lang="vi">Âm thanh MP3</comment>
- <comment xml:lang="zh_CN">MP3 音频</comment>
<comment xml:lang="zh_TW">MP3 音訊</comment>
+ <comment xml:lang="zh_CN">MP3 音频</comment>
+ <comment xml:lang="vi">Âm thanh MP3</comment>
+ <comment xml:lang="uk">звук MP3</comment>
+ <comment xml:lang="tr">MP3 sesi</comment>
+ <comment xml:lang="sv">MP3-ljud</comment>
+ <comment xml:lang="sr">МП3 звук</comment>
+ <comment xml:lang="sq">audio MP3</comment>
+ <comment xml:lang="sl">Zvočna datoteka MP3</comment>
+ <comment xml:lang="si">MP3 ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk MP3</comment>
+ <comment xml:lang="ru">Аудио MP3</comment>
+ <comment xml:lang="ro">Audio MP3</comment>
+ <comment xml:lang="pt_BR">Áudio MP3</comment>
+ <comment xml:lang="pt">áudio MP3</comment>
+ <comment xml:lang="pl">Plik dźwiękowy MP3</comment>
+ <comment xml:lang="oc">àudio MP3</comment>
+ <comment xml:lang="nn">MP3-lyd</comment>
+ <comment xml:lang="nl">MP3-audio</comment>
+ <comment xml:lang="nb">MP3-lyd</comment>
+ <comment xml:lang="ms">Audio MP3</comment>
+ <comment xml:lang="lv">MP3 audio</comment>
+ <comment xml:lang="lt">MP3 garso įrašas</comment>
+ <comment xml:lang="ko">MP3 오디오</comment>
+ <comment xml:lang="kk">MP3 аудиосы</comment>
+ <comment xml:lang="ka">MP3 აუდიო</comment>
+ <comment xml:lang="ja">MP3 オーディオ</comment>
+ <comment xml:lang="it">Audio MP3</comment>
+ <comment xml:lang="is">MP3 hljóðskrá</comment>
+ <comment xml:lang="id">Audio MP3</comment>
+ <comment xml:lang="ia">Audio MP3</comment>
+ <comment xml:lang="hu">MP3 hang</comment>
+ <comment xml:lang="hr">MP3 zvučni zapis</comment>
+ <comment xml:lang="he">שמע MP3</comment>
+ <comment xml:lang="gl">son MP3</comment>
+ <comment xml:lang="ga">fuaim MP3</comment>
+ <comment xml:lang="fur">audio MP3</comment>
+ <comment xml:lang="fr">audio MP3</comment>
+ <comment xml:lang="fo">MP3 ljóður</comment>
+ <comment xml:lang="fi">MP3-ääni</comment>
+ <comment xml:lang="eu">MP3 audioa</comment>
+ <comment xml:lang="es">sonido MP3</comment>
+ <comment xml:lang="eo">MP3-sondosiero</comment>
+ <comment xml:lang="en_GB">MP3 audio</comment>
+ <comment xml:lang="el">Ήχος MP3</comment>
+ <comment xml:lang="de">MP3-Audio</comment>
+ <comment xml:lang="da">MP3-lyd</comment>
+ <comment xml:lang="cy">Sain MP3</comment>
+ <comment xml:lang="cs">zvuk MP3</comment>
+ <comment xml:lang="ca">àudio MP3</comment>
+ <comment xml:lang="bg">Аудио — MP3</comment>
+ <comment xml:lang="be@latin">Aŭdyjo MP3</comment>
+ <comment xml:lang="be">аўдыя MP3</comment>
+ <comment xml:lang="az">MP3 audio faylı</comment>
+ <comment xml:lang="ar">صوت MP3</comment>
+ <comment xml:lang="af">MP3-oudio</comment>
<alias type="audio/x-mp3"/>
<alias type="audio/x-mpg"/>
<alias type="audio/x-mpeg"/>
<alias type="audio/mp3"/>
- <magic priority="50">
- <match value="0xfffb" type="big16" offset="0"/>
- <match value="ID3" type="string" offset="0"/>
+ <magic>
+ <match type="big16" value="0xfffa" offset="0"/>
+ <match type="big16" value="0xfffb" offset="0"/>
+ <match type="big16" value="0xfff3" offset="0"/>
+ <match type="big16" value="0xfff2" offset="0"/>
+ <match type="big16" value="0xffe3" offset="0"/>
+ <match type="big16" value="0xffe2" offset="0"/>
+ <match type="string" value="ID3" offset="0"/>
</magic>
<glob pattern="*.mp3"/>
<glob pattern="*.mpga"/>
</mime-type>
<mime-type type="audio/x-mpegurl">
- <comment>MP3 audio (streamed)</comment>
- <comment xml:lang="ar">MP3 سمعي (تدفق)</comment>
- <comment xml:lang="be@latin">Aŭdyjo MP3 (płyń)</comment>
- <comment xml:lang="bg">Аудио — MP3, поточно</comment>
- <comment xml:lang="ca">àudio MP3 (flux)</comment>
- <comment xml:lang="cs">zvuk MP3 (proud)</comment>
- <comment xml:lang="da">MP3-lyd (strøm)</comment>
- <comment xml:lang="de">MP3-Audio (Stream)</comment>
- <comment xml:lang="el">Ήχος MP3 (εκπεμπόμενος)</comment>
- <comment xml:lang="en_GB">MP3 audio (streamed)</comment>
- <comment xml:lang="eo">MP3-sondosiero (fluigate)</comment>
- <comment xml:lang="es">sonido MP3 (en transmisión)</comment>
- <comment xml:lang="eu">MP3 audioa (korrontea)</comment>
- <comment xml:lang="fi">MP3-ääni (virtaus)</comment>
- <comment xml:lang="fo">MP3 ljóður (streymað)</comment>
- <comment xml:lang="fr">audio MP3 (flux)</comment>
- <comment xml:lang="ga">fuaim MP3 (sruthaithe)</comment>
- <comment xml:lang="gl">son MP3 (en stream)</comment>
- <comment xml:lang="he">שמע MP3 (מוזרם)</comment>
- <comment xml:lang="hr">MP3 zvučni zapis (strujanje)</comment>
- <comment xml:lang="hu">MP3 hang (sugárzott)</comment>
- <comment xml:lang="ia">Audio MP3 (fluxo)</comment>
- <comment xml:lang="id">Audio MP3 (stream)</comment>
- <comment xml:lang="it">Audio MP3 (in streaming)</comment>
- <comment xml:lang="ja">MP3 オーディオ (ストリーム)</comment>
- <comment xml:lang="ka">MP3 აუდიო (ნაკადი)</comment>
- <comment xml:lang="kk">MP3 аудиосы (ағымдық)</comment>
- <comment xml:lang="ko">MP3 오디오(스트림)</comment>
- <comment xml:lang="lt">MP3 garso įrašas (transliuojamas)</comment>
- <comment xml:lang="lv">MP3 audio (straumēts)</comment>
- <comment xml:lang="ms">Audio MP3 (aliran)</comment>
- <comment xml:lang="nb">MP3-lyd (streaming)</comment>
- <comment xml:lang="nl">MP3-audio (gestreamd)</comment>
- <comment xml:lang="nn">Strauma MP3-lyd</comment>
- <comment xml:lang="oc">àudio MP3 (flux)</comment>
- <comment xml:lang="pl">Plik dźwiękowy MP3 (strumień)</comment>
- <comment xml:lang="pt">áudio MP3 (em fluxo)</comment>
- <comment xml:lang="pt_BR">Áudio MP3 (em fluxo)</comment>
- <comment xml:lang="ro">Audio MP3 (flux)</comment>
- <comment xml:lang="ru">Аудио MP3 (потоковое)</comment>
- <comment xml:lang="sk">Zvuk MP3 (streamovaný)</comment>
- <comment xml:lang="sl">Zvočna datoteka MP3 (pretočna)</comment>
- <comment xml:lang="sq">Audio MP3 (streamed)</comment>
- <comment xml:lang="sr">МП3 звук (проточан)</comment>
- <comment xml:lang="sv">MP3-ljud (flöde)</comment>
- <comment xml:lang="tr">MP3 sesi (akış)</comment>
- <comment xml:lang="uk">звук MP3 (потоковий)</comment>
- <comment xml:lang="vi">Âm thanh MP3 (chạy luồng)</comment>
- <comment xml:lang="zh_CN">MP3 音频流媒体</comment>
- <comment xml:lang="zh_TW">MP3 音訊 (串流)</comment>
+ <comment>Media playlist</comment>
+ <comment xml:lang="zh_CN">媒体播放列表</comment>
+ <comment xml:lang="uk">мультимедійний список відтворення</comment>
+ <comment xml:lang="tr">Ortam çalma listesi</comment>
+ <comment xml:lang="sv">Mediaspellista</comment>
+ <comment xml:lang="si">මාධ්‍ය ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="ru">Список воспроизведения медиа-данных</comment>
+ <comment xml:lang="pl">Lista odtwarzania multimediów</comment>
+ <comment xml:lang="nl">Media-afspeellijst</comment>
+ <comment xml:lang="ko">Media 재생 목록</comment>
+ <comment xml:lang="kk">Медиа ойнату тізімі</comment>
+ <comment xml:lang="ka">მედიის დასაკრავი სია</comment>
+ <comment xml:lang="ja">メディアプレイリスト</comment>
+ <comment xml:lang="it">Playlist multimediale</comment>
+ <comment xml:lang="hr">Media popis izvođenja</comment>
+ <comment xml:lang="gl">Lista de reprodución multimedia</comment>
+ <comment xml:lang="fi">Media-soittolista</comment>
+ <comment xml:lang="eu">Multimediako erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción de medios</comment>
+ <comment xml:lang="en_GB">Media playlist</comment>
+ <comment xml:lang="de">Medien-Wiedergabeliste</comment>
+ <comment xml:lang="be">плэй-ліст мультымедыя</comment>
+ <comment xml:lang="ar">قائمة تشغيل وسائط</comment>
<sub-class-of type="text/plain"/>
<alias type="audio/mpegurl"/>
<alias type="application/m3u"/>
@@ -23727,111 +25909,97 @@
<glob pattern="*.m3u"/>
<glob pattern="*.m3u8"/>
<glob pattern="*.vlc"/>
- <magic priority="50">
- <match value="#EXTM3U" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#EXTM3U" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/vnd.apple.mpegurl">
- <comment>HTTP Live Streaming playlist</comment>
- <comment xml:lang="ar">قائمة بث HTTP حية</comment>
- <comment xml:lang="bg">Списък за изпълнение — поток по HTTP</comment>
- <comment xml:lang="ca">llista de reproducció en temps real HTTP</comment>
- <comment xml:lang="cs">seznam k přehrání HTTP Live Streaming</comment>
- <comment xml:lang="da">Afspilningsliste til HTTP-livestrøm</comment>
- <comment xml:lang="de">HTTP Live-Streaming-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής ζωντανής μετάδοσης σε HTTP</comment>
- <comment xml:lang="en_GB">HTTP Live Streaming playlist</comment>
- <comment xml:lang="es">lista de reproducción de flujo en directo HTTP</comment>
- <comment xml:lang="eu">HTTP zuzeneko korrontearen erreprodukzio-zerrenda</comment>
- <comment xml:lang="fo">HTTP beinleiðis streymaður avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture de flux HTTP Live</comment>
- <comment xml:lang="ga">seinmliosta sruthaithe bheo HTTP</comment>
- <comment xml:lang="gl">lista de reprodución de fluxo HTTP</comment>
- <comment xml:lang="he">רשימת השמעה הזרימה של HTTP</comment>
- <comment xml:lang="hr">HTTP popis izvođenja emitiranja uživo</comment>
- <comment xml:lang="hu">HTTP élő lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection HTTP Live Streaming</comment>
- <comment xml:lang="id">Daftar putar HTTP Live Streaming</comment>
- <comment xml:lang="it">Playlist Live Steaming HTTP</comment>
- <comment xml:lang="ja">HTTP ライブストリーミング再生リスト</comment>
- <comment xml:lang="kk">HTTP тірі ағым ойнау тізімі</comment>
- <comment xml:lang="ko">HTTP 라이브 스트리밍 재생 목록</comment>
- <comment xml:lang="lt">HTTP tiesioginio transliavimo grojaraštis</comment>
- <comment xml:lang="lv">HTTP dzīvās straumēšanas repertuārs</comment>
- <comment xml:lang="nl">HTTP Live Streaming afspeellijst</comment>
- <comment xml:lang="oc">lista de lectura de flux HTTP Live</comment>
- <comment xml:lang="pl">Lista odtwarzania strumieniowego na żywo HTTP</comment>
- <comment xml:lang="pt">lista de reprodução HTTP Live Streaming</comment>
- <comment xml:lang="pt_BR">Lista de Reprodução Streaming ao Vivo de HTTP</comment>
- <comment xml:lang="ro">Listă de redare difuzată ca flux HTTP</comment>
- <comment xml:lang="ru">Список воспроизведения HTTP-потока</comment>
- <comment xml:lang="sk">Zoznam stôp HTTP Live Streaming</comment>
- <comment xml:lang="sl">Seznam predvajanja živega pretoka HTTP</comment>
- <comment xml:lang="sr">ХТТП списак нумера Живог Протока</comment>
- <comment xml:lang="sv">HTTP Live Streaming-spellista</comment>
- <comment xml:lang="tr">HTTP Canlı Akış çalma listesi</comment>
- <comment xml:lang="uk">список відтворення HTTP Live Streaming</comment>
- <comment xml:lang="zh_CN">HTTP 实时流播放列表</comment>
- <comment xml:lang="zh_TW">HTTP 即時串流播放清單</comment>
+ <comment>Media playlist</comment>
+ <comment xml:lang="zh_CN">媒体播放列表</comment>
+ <comment xml:lang="uk">мультимедійний список відтворення</comment>
+ <comment xml:lang="tr">Ortam çalma listesi</comment>
+ <comment xml:lang="sv">Mediaspellista</comment>
+ <comment xml:lang="si">මාධ්‍ය ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="ru">Список воспроизведения медиа-данных</comment>
+ <comment xml:lang="pl">Lista odtwarzania multimediów</comment>
+ <comment xml:lang="nl">Media-afspeellijst</comment>
+ <comment xml:lang="ko">Media 재생 목록</comment>
+ <comment xml:lang="kk">Медиа ойнату тізімі</comment>
+ <comment xml:lang="ka">მედიის დასაკრავი სია</comment>
+ <comment xml:lang="ja">メディアプレイリスト</comment>
+ <comment xml:lang="it">Playlist multimediale</comment>
+ <comment xml:lang="hr">Media popis izvođenja</comment>
+ <comment xml:lang="gl">Lista de reprodución multimedia</comment>
+ <comment xml:lang="fi">Media-soittolista</comment>
+ <comment xml:lang="eu">Multimediako erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción de medios</comment>
+ <comment xml:lang="en_GB">Media playlist</comment>
+ <comment xml:lang="de">Medien-Wiedergabeliste</comment>
+ <comment xml:lang="be">плэй-ліст мультымедыя</comment>
+ <comment xml:lang="ar">قائمة تشغيل وسائط</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.m3u"/>
<glob pattern="*.m3u8"/>
<magic priority="70">
- <match value="#EXTM3U" type="string" offset="0">
- <match value="#EXT-X-TARGETDURATION" type="string" offset="0:128"/>
- <match value="#EXT-X-STREAM-INF" type="string" offset="0:128"/>
+ <match type="string" value="#EXTM3U" offset="0">
+ <match type="string" value="#EXT-X-TARGETDURATION" offset="0:128"/>
+ <match type="string" value="#EXT-X-STREAM-INF" offset="0:128"/>
</match>
</magic>
</mime-type>
<mime-type type="audio/x-ms-asx">
<comment>Microsoft ASX playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل مايكروسوفت ASX</comment>
- <comment xml:lang="be@latin">Śpis Microsoft ASX</comment>
- <comment xml:lang="bg">Списък за изпълнение — Microsoft ASX</comment>
- <comment xml:lang="ca">llista de reproducció de Microsoft ASX</comment>
- <comment xml:lang="cs">seznam k přehrání Microsoft ASX</comment>
- <comment xml:lang="da">Microsoft ASX-afspilningsliste</comment>
- <comment xml:lang="de">Microsoft-ASX-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής Microsoft ASX</comment>
- <comment xml:lang="en_GB">Microsoft ASX playlist</comment>
- <comment xml:lang="es">lista de reproducción ASX de Microsoft</comment>
- <comment xml:lang="eu">Microsoft ASX erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">Microsoft ASX -soittolista</comment>
- <comment xml:lang="fo">Microsoft ASX avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture Microsoft ASX</comment>
- <comment xml:lang="ga">seinmliosta Microsoft ASX</comment>
- <comment xml:lang="gl">lista de reprodución Microsoft ASX</comment>
- <comment xml:lang="he">רשימת השמעה ASX (מיקרוסופט)</comment>
- <comment xml:lang="hr">Microsoft ASX popis izvođenja</comment>
- <comment xml:lang="hu">Microsoft ASX lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection Microsoft ASX</comment>
- <comment xml:lang="id">Senarai putar Microsoft ASX</comment>
- <comment xml:lang="it">Playlist Microsoft ASX</comment>
- <comment xml:lang="ja">Microsoft ASX 再生リスト</comment>
- <comment xml:lang="ka">Microsoft-ის ASX რეპერტუარი</comment>
- <comment xml:lang="kk">Microsoft ASX ойнау тізімі</comment>
- <comment xml:lang="ko">Microsoft ASX 재생 목록</comment>
- <comment xml:lang="lt">Microsoft ASX grojaraštis</comment>
- <comment xml:lang="lv">Microsoft ASX repertuārs</comment>
- <comment xml:lang="nb">Microsoft ASX-spilleliste</comment>
- <comment xml:lang="nl">Microsoft ASX-afspeellijst</comment>
- <comment xml:lang="nn">Microsoft ASX-speleliste</comment>
- <comment xml:lang="oc">lista de lectura Microsoft ASX</comment>
- <comment xml:lang="pl">Lista odtwarzania Microsoft ASX</comment>
- <comment xml:lang="pt">lista de reprodução Microsoft ASX</comment>
- <comment xml:lang="pt_BR">Lista de reprodução do Microsoft ASX</comment>
- <comment xml:lang="ro">Listă redare Microsoft ASX</comment>
- <comment xml:lang="ru">Список воспроизведения Microsoft ASX</comment>
- <comment xml:lang="sk">Zoznam skladieb Microsoft ASX</comment>
- <comment xml:lang="sl">Seznam predvajanja Microsoft ASX</comment>
- <comment xml:lang="sq">Listë titujsh Microsoft ASF</comment>
- <comment xml:lang="sr">Мајкрософтов АСИкс списак нумера</comment>
- <comment xml:lang="sv">Microsoft ASX-spellista</comment>
- <comment xml:lang="tr">Microsoft ASX çalma listesi</comment>
- <comment xml:lang="uk">список відтворення ASX Microsoft</comment>
- <comment xml:lang="vi">Danh mục nhạc Microsoft ASX</comment>
- <comment xml:lang="zh_CN">Microsoft ASX 播放列表</comment>
<comment xml:lang="zh_TW">微軟 ASX 播放清單</comment>
+ <comment xml:lang="zh_CN">Microsoft ASX 播放列表</comment>
+ <comment xml:lang="vi">Danh mục nhạc Microsoft ASX</comment>
+ <comment xml:lang="uk">список відтворення ASX Microsoft</comment>
+ <comment xml:lang="tr">Microsoft ASX çalma listesi</comment>
+ <comment xml:lang="sv">Microsoft ASX-spellista</comment>
+ <comment xml:lang="sr">Мајкрософтов АСИкс списак нумера</comment>
+ <comment xml:lang="sq">luajlistë Microsoft ASF</comment>
+ <comment xml:lang="sl">Seznam predvajanja Microsoft ASX</comment>
+ <comment xml:lang="si">Microsoft ASX ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb Microsoft ASX</comment>
+ <comment xml:lang="ru">Список воспроизведения Microsoft ASX</comment>
+ <comment xml:lang="ro">Listă redare Microsoft ASX</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução do Microsoft ASX</comment>
+ <comment xml:lang="pt">lista de reprodução Microsoft ASX</comment>
+ <comment xml:lang="pl">Lista odtwarzania Microsoft ASX</comment>
+ <comment xml:lang="oc">lista de lectura Microsoft ASX</comment>
+ <comment xml:lang="nn">Microsoft ASX-speleliste</comment>
+ <comment xml:lang="nl">Microsoft ASX-afspeellijst</comment>
+ <comment xml:lang="nb">Microsoft ASX-spilleliste</comment>
+ <comment xml:lang="lv">Microsoft ASX repertuārs</comment>
+ <comment xml:lang="lt">Microsoft ASX grojaraštis</comment>
+ <comment xml:lang="ko">Microsoft ASX 재생 목록</comment>
+ <comment xml:lang="kk">Microsoft ASX ойнау тізімі</comment>
+ <comment xml:lang="ka">Microsoft-ის ASX რეპერტუარი</comment>
+ <comment xml:lang="ja">Microsoft ASX プレイリスト</comment>
+ <comment xml:lang="it">Playlist Microsoft ASX</comment>
+ <comment xml:lang="is">Microsoft ASX spilunarlisti</comment>
+ <comment xml:lang="id">Senarai putar Microsoft ASX</comment>
+ <comment xml:lang="ia">Lista de selection Microsoft ASX</comment>
+ <comment xml:lang="hu">Microsoft ASX lejátszólista</comment>
+ <comment xml:lang="hr">Microsoft ASX popis izvođenja</comment>
+ <comment xml:lang="he">רשימת השמעה ASX (מיקרוסופט)</comment>
+ <comment xml:lang="gl">lista de reprodución Microsoft ASX</comment>
+ <comment xml:lang="ga">seinmliosta Microsoft ASX</comment>
+ <comment xml:lang="fur">liste di riproduzion Microsoft ASX</comment>
+ <comment xml:lang="fr">liste de lecture Microsoft ASX</comment>
+ <comment xml:lang="fo">Microsoft ASX avspælingarlisti</comment>
+ <comment xml:lang="fi">Microsoft ASX -soittolista</comment>
+ <comment xml:lang="eu">Microsoft ASX erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción ASX de Microsoft</comment>
+ <comment xml:lang="en_GB">Microsoft ASX playlist</comment>
+ <comment xml:lang="el">Λίστα αναπαραγωγής Microsoft ASX</comment>
+ <comment xml:lang="de">Microsoft-ASX-Wiedergabeliste</comment>
+ <comment xml:lang="da">Microsoft ASX-afspilningsliste</comment>
+ <comment xml:lang="cs">seznam k přehrání Microsoft ASX</comment>
+ <comment xml:lang="ca">llista de reproducció de Microsoft ASX</comment>
+ <comment xml:lang="bg">Списък за изпълнение — Microsoft ASX</comment>
+ <comment xml:lang="be@latin">Śpis Microsoft ASX</comment>
+ <comment xml:lang="be">плэй-ліст Microsoft ASX</comment>
+ <comment xml:lang="ar">قائمة تشغيل مايكروسوفت ASX</comment>
<alias type="video/x-ms-wvx"/>
<alias type="video/x-ms-wax"/>
<alias type="video/x-ms-wmx"/>
@@ -23841,118 +26009,128 @@
<glob pattern="*.wvx"/>
<glob pattern="*.wmx"/>
<magic priority="51">
- <match value="ASF " type="string" offset="0"/>
- <match value="&lt;ASX" type="string" offset="0:64"/>
- <match value="&lt;asx" type="string" offset="0:64"/>
- <match value="&lt;Asx" type="string" offset="0:64"/>
+ <match type="string" value="ASF " offset="0"/>
+ <match type="string" value="&lt;ASX" offset="0:64"/>
+ <match type="string" value="&lt;asx" offset="0:64"/>
+ <match type="string" value="&lt;Asx" offset="0:64"/>
</magic>
</mime-type>
<mime-type type="audio/x-psf">
<comment>PSF audio</comment>
- <comment xml:lang="ar">PSF سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo PSF</comment>
- <comment xml:lang="bg">Аудио — PSF</comment>
- <comment xml:lang="ca">àudio PSF</comment>
- <comment xml:lang="cs">zvuk PSF</comment>
- <comment xml:lang="da">PSF-lyd</comment>
- <comment xml:lang="de">PSF-Audio</comment>
- <comment xml:lang="el">Ήχος PSF</comment>
- <comment xml:lang="en_GB">PSF audio</comment>
- <comment xml:lang="eo">PSF-sondosiero</comment>
- <comment xml:lang="es">sonido PSF</comment>
- <comment xml:lang="eu">PSF audioa</comment>
- <comment xml:lang="fi">PSF-ääni</comment>
- <comment xml:lang="fo">PSF ljóður</comment>
- <comment xml:lang="fr">audio PSF</comment>
- <comment xml:lang="ga">fuaim PSF</comment>
- <comment xml:lang="gl">son PSF</comment>
- <comment xml:lang="he">שמע PSF</comment>
- <comment xml:lang="hr">PSF zvučni zapis</comment>
- <comment xml:lang="hu">PSF hang</comment>
- <comment xml:lang="ia">Audio PSF</comment>
- <comment xml:lang="id">Audio PSF</comment>
- <comment xml:lang="it">Audio PSF</comment>
- <comment xml:lang="ja">PSF オーディオ</comment>
- <comment xml:lang="kk">PSF аудиосы</comment>
- <comment xml:lang="ko">PSF 오디오</comment>
- <comment xml:lang="lt">PSF garso įrašas</comment>
- <comment xml:lang="lv">PSF audio</comment>
- <comment xml:lang="nb">PSF-lyd</comment>
- <comment xml:lang="nl">PSF-audio</comment>
- <comment xml:lang="nn">PSF-lyd</comment>
- <comment xml:lang="oc">àudio PSF</comment>
- <comment xml:lang="pl">Plik dźwiękowy PSF</comment>
- <comment xml:lang="pt">áudio PSF</comment>
- <comment xml:lang="pt_BR">Áudio PSF</comment>
- <comment xml:lang="ro">Audio PSF</comment>
- <comment xml:lang="ru">Аудио PSF</comment>
- <comment xml:lang="sk">Zvuk PSF</comment>
- <comment xml:lang="sl">Zvočna datoteka PSF</comment>
- <comment xml:lang="sq">Audio PSF</comment>
- <comment xml:lang="sr">ПСФ звук</comment>
- <comment xml:lang="sv">PSF-ljud</comment>
- <comment xml:lang="tr">PSF sesi</comment>
- <comment xml:lang="uk">звук PSF</comment>
- <comment xml:lang="vi">Âm thanh PSF</comment>
- <comment xml:lang="zh_CN">PSF 音频</comment>
<comment xml:lang="zh_TW">PSF 音訊</comment>
+ <comment xml:lang="zh_CN">PSF 音频</comment>
+ <comment xml:lang="vi">Âm thanh PSF</comment>
+ <comment xml:lang="uk">звук PSF</comment>
+ <comment xml:lang="tr">PSF sesi</comment>
+ <comment xml:lang="sv">PSF-ljud</comment>
+ <comment xml:lang="sr">ПСФ звук</comment>
+ <comment xml:lang="sq">audio PSF</comment>
+ <comment xml:lang="sl">Zvočna datoteka PSF</comment>
+ <comment xml:lang="si">PSF ශ්රව්ය උපකරණ</comment>
+ <comment xml:lang="sk">Zvuk PSF</comment>
+ <comment xml:lang="ru">Аудио PSF</comment>
+ <comment xml:lang="ro">Audio PSF</comment>
+ <comment xml:lang="pt_BR">Áudio PSF</comment>
+ <comment xml:lang="pt">áudio PSF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy PSF</comment>
+ <comment xml:lang="oc">àudio PSF</comment>
+ <comment xml:lang="nn">PSF-lyd</comment>
+ <comment xml:lang="nl">PSF-audio</comment>
+ <comment xml:lang="nb">PSF-lyd</comment>
+ <comment xml:lang="lv">PSF audio</comment>
+ <comment xml:lang="lt">PSF garso įrašas</comment>
+ <comment xml:lang="ko">PSF 오디오</comment>
+ <comment xml:lang="kk">PSF аудиосы</comment>
+ <comment xml:lang="ja">PSF オーディオ</comment>
+ <comment xml:lang="it">Audio PSF</comment>
+ <comment xml:lang="is">PSF hljóðskrá</comment>
+ <comment xml:lang="id">Audio PSF</comment>
+ <comment xml:lang="ia">Audio PSF</comment>
+ <comment xml:lang="hu">PSF hang</comment>
+ <comment xml:lang="hr">PSF zvučni zapis</comment>
+ <comment xml:lang="he">שמע PSF</comment>
+ <comment xml:lang="gl">son PSF</comment>
+ <comment xml:lang="ga">fuaim PSF</comment>
+ <comment xml:lang="fur">audio PSF</comment>
+ <comment xml:lang="fr">audio PSF</comment>
+ <comment xml:lang="fo">PSF ljóður</comment>
+ <comment xml:lang="fi">PSF-ääni</comment>
+ <comment xml:lang="eu">PSF audioa</comment>
+ <comment xml:lang="es">sonido PSF</comment>
+ <comment xml:lang="eo">PSF-sondosiero</comment>
+ <comment xml:lang="en_GB">PSF audio</comment>
+ <comment xml:lang="el">Ήχος PSF</comment>
+ <comment xml:lang="de">PSF-Audio</comment>
+ <comment xml:lang="da">PSF-lyd</comment>
+ <comment xml:lang="cs">zvuk PSF</comment>
+ <comment xml:lang="ca">àudio PSF</comment>
+ <comment xml:lang="bg">Аудио — PSF</comment>
+ <comment xml:lang="be@latin">Aŭdyjo PSF</comment>
+ <comment xml:lang="be">аўдыя PSF</comment>
+ <comment xml:lang="ar">صوت PSF</comment>
+ <comment xml:lang="af">PSF-oudio</comment>
<acronym>PSF</acronym>
<expanded-acronym>Portable Sound Format</expanded-acronym>
- <magic priority="50">
- <match value="PSF" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="PSF" offset="0"/>
</magic>
<glob pattern="*.psf"/>
</mime-type>
<mime-type type="audio/x-minipsf">
<comment>MiniPSF audio</comment>
- <comment xml:lang="ar">MiniPSF سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo MiniPSF</comment>
- <comment xml:lang="bg">Аудио — MiniPSF</comment>
- <comment xml:lang="ca">àudio MiniPSF</comment>
- <comment xml:lang="cs">zvuk MiniPSF</comment>
- <comment xml:lang="da">MiniPSF-lyd</comment>
- <comment xml:lang="de">MiniPSF-Audio</comment>
- <comment xml:lang="el">Ήχος MiniPSF</comment>
- <comment xml:lang="en_GB">MiniPSF audio</comment>
- <comment xml:lang="eo">MiniPSF-sondosiero</comment>
- <comment xml:lang="es">sonido MiniPSF</comment>
- <comment xml:lang="eu">MiniPSF audioa</comment>
- <comment xml:lang="fi">MiniPSF-ääni</comment>
- <comment xml:lang="fo">MiniPSF ljóður</comment>
- <comment xml:lang="fr">audio MiniPSF</comment>
- <comment xml:lang="ga">fuaim MiniPSF</comment>
- <comment xml:lang="gl">son MiniPSF</comment>
- <comment xml:lang="he">שמע של MiniPSP</comment>
- <comment xml:lang="hr">MiniPSF zvučni zapis</comment>
- <comment xml:lang="hu">MiniPSF hang</comment>
- <comment xml:lang="ia">Audio MiniPSF</comment>
- <comment xml:lang="id">Audio MiniPSF</comment>
- <comment xml:lang="it">Audio MiniPSF</comment>
- <comment xml:lang="ja">MiniPSF オーディオ</comment>
- <comment xml:lang="ka">MiniPSF-ის აუდიო</comment>
- <comment xml:lang="kk">MiniPSF аудиосы</comment>
- <comment xml:lang="ko">MiniPSF 오디오</comment>
- <comment xml:lang="lt">MiniPSF garso įrašas</comment>
- <comment xml:lang="lv">MiniPSF audio</comment>
- <comment xml:lang="nb">MiniPSF-lyd</comment>
- <comment xml:lang="nl">MiniPSF-audio</comment>
- <comment xml:lang="nn">MiniPSF-lyd</comment>
- <comment xml:lang="oc">àudio MiniPSF</comment>
- <comment xml:lang="pl">Plik dźwiękowy MiniPSF</comment>
- <comment xml:lang="pt">áudio MiniPSF</comment>
- <comment xml:lang="pt_BR">Áudio MiniPSF</comment>
- <comment xml:lang="ro">Audio MiniPSF</comment>
- <comment xml:lang="ru">Аудио MiniPSF</comment>
- <comment xml:lang="sk">Zvuk MiniPSF</comment>
- <comment xml:lang="sl">Zvočna datoteka MiniPSF</comment>
- <comment xml:lang="sq">Audio MiniPSF</comment>
- <comment xml:lang="sr">Мини ПСФ звук</comment>
- <comment xml:lang="sv">MiniPSF-ljud</comment>
- <comment xml:lang="tr">MiniPSF sesi</comment>
- <comment xml:lang="uk">звук MiniPSF</comment>
- <comment xml:lang="vi">Âm thanh MiniPSF</comment>
- <comment xml:lang="zh_CN">MiniPSF 音频</comment>
<comment xml:lang="zh_TW">MiniPSF 音訊</comment>
+ <comment xml:lang="zh_CN">MiniPSF 音频</comment>
+ <comment xml:lang="vi">Âm thanh MiniPSF</comment>
+ <comment xml:lang="uk">звук MiniPSF</comment>
+ <comment xml:lang="tr">MiniPSF sesi</comment>
+ <comment xml:lang="sv">MiniPSF-ljud</comment>
+ <comment xml:lang="sr">Мини ПСФ звук</comment>
+ <comment xml:lang="sq">audio MiniPSF</comment>
+ <comment xml:lang="sl">Zvočna datoteka MiniPSF</comment>
+ <comment xml:lang="si">MiniPSF ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk MiniPSF</comment>
+ <comment xml:lang="ru">Аудио MiniPSF</comment>
+ <comment xml:lang="ro">Audio MiniPSF</comment>
+ <comment xml:lang="pt_BR">Áudio MiniPSF</comment>
+ <comment xml:lang="pt">áudio MiniPSF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy MiniPSF</comment>
+ <comment xml:lang="oc">àudio MiniPSF</comment>
+ <comment xml:lang="nn">MiniPSF-lyd</comment>
+ <comment xml:lang="nl">MiniPSF-audio</comment>
+ <comment xml:lang="nb">MiniPSF-lyd</comment>
+ <comment xml:lang="lv">MiniPSF audio</comment>
+ <comment xml:lang="lt">MiniPSF garso įrašas</comment>
+ <comment xml:lang="ko">MiniPSF 오디오</comment>
+ <comment xml:lang="kk">MiniPSF аудиосы</comment>
+ <comment xml:lang="ka">MiniPSF-ის აუდიო</comment>
+ <comment xml:lang="ja">MiniPSF オーディオ</comment>
+ <comment xml:lang="it">Audio MiniPSF</comment>
+ <comment xml:lang="is">MiniPSF hljóðskrá</comment>
+ <comment xml:lang="id">Audio MiniPSF</comment>
+ <comment xml:lang="ia">Audio MiniPSF</comment>
+ <comment xml:lang="hu">MiniPSF hang</comment>
+ <comment xml:lang="hr">MiniPSF zvučni zapis</comment>
+ <comment xml:lang="he">שמע של MiniPSP</comment>
+ <comment xml:lang="gl">son MiniPSF</comment>
+ <comment xml:lang="ga">fuaim MiniPSF</comment>
+ <comment xml:lang="fur">audio MiniPSF</comment>
+ <comment xml:lang="fr">audio MiniPSF</comment>
+ <comment xml:lang="fo">MiniPSF ljóður</comment>
+ <comment xml:lang="fi">MiniPSF-ääni</comment>
+ <comment xml:lang="eu">MiniPSF audioa</comment>
+ <comment xml:lang="es">sonido MiniPSF</comment>
+ <comment xml:lang="eo">MiniPSF-sondosiero</comment>
+ <comment xml:lang="en_GB">MiniPSF audio</comment>
+ <comment xml:lang="el">Ήχος MiniPSF</comment>
+ <comment xml:lang="de">MiniPSF-Audio</comment>
+ <comment xml:lang="da">MiniPSF-lyd</comment>
+ <comment xml:lang="cs">zvuk MiniPSF</comment>
+ <comment xml:lang="ca">àudio MiniPSF</comment>
+ <comment xml:lang="bg">Аудио — MiniPSF</comment>
+ <comment xml:lang="be@latin">Aŭdyjo MiniPSF</comment>
+ <comment xml:lang="be">аўдыя MiniPSF</comment>
+ <comment xml:lang="ar">صوت MiniPSF</comment>
+ <comment xml:lang="af">MiniPSF-oudio</comment>
<acronym>MiniPSF</acronym>
<expanded-acronym>Miniature Portable Sound Format</expanded-acronym>
<sub-class-of type="audio/x-psf"/>
@@ -23960,52 +26138,57 @@
</mime-type>
<mime-type type="audio/x-psflib">
<comment>PSFlib audio library</comment>
- <comment xml:lang="ar">مكتبة PSFlib السمعية</comment>
- <comment xml:lang="be@latin">Aŭdyjobiblijateka PSFlib</comment>
- <comment xml:lang="bg">Аудио библиотека — PSFlib</comment>
- <comment xml:lang="ca">biblioteca d'àudio PSFlib</comment>
- <comment xml:lang="cs">zvuková knihovna PSFlib</comment>
- <comment xml:lang="da">PSFlib-lydbibliotek</comment>
- <comment xml:lang="de">PSFlib-Audiobibliothek</comment>
- <comment xml:lang="el">Βιβλιοθήκη ήχου PSFlib</comment>
- <comment xml:lang="en_GB">PSFlib audio library</comment>
- <comment xml:lang="es">biblioteca de sonido PSFlib</comment>
- <comment xml:lang="eu">PSFlib audioaren liburutegia</comment>
- <comment xml:lang="fi">PSFlib-äänikirjasto</comment>
- <comment xml:lang="fo">PSFlib ljóðsavn</comment>
- <comment xml:lang="fr">bibliothèque audio PSFlib</comment>
- <comment xml:lang="ga">leabharlann fhuaime PSFlib</comment>
- <comment xml:lang="gl">Biblioteca de son PSFlib</comment>
- <comment xml:lang="he">ספריית שמע PSFlib</comment>
- <comment xml:lang="hr">PSFlib zvučna biblioteka</comment>
- <comment xml:lang="hu">PSFlib hanggyűjtemény</comment>
- <comment xml:lang="ia">Bibliotheca audio PSFlib</comment>
- <comment xml:lang="id">Pustaka audio PSFlib</comment>
- <comment xml:lang="it">Libreria audio PSFlib</comment>
- <comment xml:lang="ja">PSFlib オーディオライブラリ</comment>
- <comment xml:lang="kk">PSFlib аудио жинағы</comment>
- <comment xml:lang="ko">PSFlib 오디오 라이브러리</comment>
- <comment xml:lang="lt">PSFlib garso biblioteka</comment>
- <comment xml:lang="lv">PSFlib fonotēka</comment>
- <comment xml:lang="nb">PSFlib-lydbibliotek</comment>
- <comment xml:lang="nl">PSFlib-audiobibliotheek</comment>
- <comment xml:lang="nn">PSFlib lydbibliotek</comment>
- <comment xml:lang="oc">bibliotèca àudio PSFlib</comment>
- <comment xml:lang="pl">Biblioteka dźwiękowa PSFlib</comment>
- <comment xml:lang="pt">biblioteca áudio PSFlib</comment>
- <comment xml:lang="pt_BR">Biblioteca de áudio PSFlib</comment>
- <comment xml:lang="ro">Bibliotecă audio PSFlib</comment>
- <comment xml:lang="ru">Фонотека PSFlib</comment>
- <comment xml:lang="sk">Zvuková knižnica PSFlib</comment>
- <comment xml:lang="sl">Zvočna knjižnica PSFlib</comment>
- <comment xml:lang="sq">Librari audio PSFlib</comment>
- <comment xml:lang="sr">библиотека звука ПСФ библиотеке</comment>
- <comment xml:lang="sv">PSFlib-ljudbibliotek</comment>
- <comment xml:lang="tr">PSFlib ses kitaplığı</comment>
- <comment xml:lang="uk">аудіобібліотека PSFlib</comment>
- <comment xml:lang="vi">Thư viện âm thanh PSFlib</comment>
- <comment xml:lang="zh_CN">PSFlib 音频库</comment>
<comment xml:lang="zh_TW">PSFlib 音訊庫</comment>
+ <comment xml:lang="zh_CN">PSFlib 音频库</comment>
+ <comment xml:lang="vi">Thư viện âm thanh PSFlib</comment>
+ <comment xml:lang="uk">аудіобібліотека PSFlib</comment>
+ <comment xml:lang="tr">PSFlib ses kitaplığı</comment>
+ <comment xml:lang="sv">PSFlib-ljudbibliotek</comment>
+ <comment xml:lang="sr">библиотека звука ПСФ библиотеке</comment>
+ <comment xml:lang="sq">bibliotekë audio PSFlib</comment>
+ <comment xml:lang="sl">Zvočna knjižnica PSFlib</comment>
+ <comment xml:lang="si">PSFlib ශ්‍රව්‍ය පුස්තකාලය</comment>
+ <comment xml:lang="sk">Zvuková knižnica PSFlib</comment>
+ <comment xml:lang="ru">Фонотека PSFlib</comment>
+ <comment xml:lang="ro">Bibliotecă audio PSFlib</comment>
+ <comment xml:lang="pt_BR">Biblioteca de áudio PSFlib</comment>
+ <comment xml:lang="pt">biblioteca áudio PSFlib</comment>
+ <comment xml:lang="pl">Biblioteka dźwiękowa PSFlib</comment>
+ <comment xml:lang="oc">bibliotèca àudio PSFlib</comment>
+ <comment xml:lang="nn">PSFlib lydbibliotek</comment>
+ <comment xml:lang="nl">PSFlib-audiobibliotheek</comment>
+ <comment xml:lang="nb">PSFlib-lydbibliotek</comment>
+ <comment xml:lang="lv">PSFlib fonotēka</comment>
+ <comment xml:lang="lt">PSFlib garso biblioteka</comment>
+ <comment xml:lang="ko">PSFlib 오디오 라이브러리</comment>
+ <comment xml:lang="kk">PSFlib аудио жинағы</comment>
+ <comment xml:lang="ja">PSFlib オーディオライブラリ</comment>
+ <comment xml:lang="it">Libreria audio PSFlib</comment>
+ <comment xml:lang="is">PSFlib hljóðaðgerðasafn</comment>
+ <comment xml:lang="id">Pustaka audio PSFlib</comment>
+ <comment xml:lang="ia">Bibliotheca audio PSFlib</comment>
+ <comment xml:lang="hu">PSFlib hanggyűjtemény</comment>
+ <comment xml:lang="hr">PSFlib zvučna biblioteka</comment>
+ <comment xml:lang="he">ספריית שמע PSFlib</comment>
+ <comment xml:lang="gl">Biblioteca de son PSFlib</comment>
+ <comment xml:lang="ga">leabharlann fhuaime PSFlib</comment>
+ <comment xml:lang="fur">librarie audio PSFlib</comment>
+ <comment xml:lang="fr">bibliothèque audio PSFlib</comment>
+ <comment xml:lang="fo">PSFlib ljóðsavn</comment>
+ <comment xml:lang="fi">PSFlib-äänikirjasto</comment>
+ <comment xml:lang="eu">PSFlib audioaren liburutegia</comment>
+ <comment xml:lang="es">biblioteca de sonido PSFlib</comment>
+ <comment xml:lang="en_GB">PSFlib audio library</comment>
+ <comment xml:lang="el">Βιβλιοθήκη ήχου PSFlib</comment>
+ <comment xml:lang="de">PSFlib-Audiobibliothek</comment>
+ <comment xml:lang="da">PSFlib-lydbibliotek</comment>
+ <comment xml:lang="cs">zvuková knihovna PSFlib</comment>
+ <comment xml:lang="ca">biblioteca d'àudio PSFlib</comment>
+ <comment xml:lang="bg">Аудио библиотека — PSFlib</comment>
+ <comment xml:lang="be@latin">Aŭdyjobiblijateka PSFlib</comment>
+ <comment xml:lang="be">аўдыябібліятэка PSFlib</comment>
+ <comment xml:lang="ar">مكتبة صوت PSFlib</comment>
+ <comment xml:lang="af">PSFlib-oudiobiblioteek</comment>
<acronym>PSFlib</acronym>
<expanded-acronym>Portable Sound Format Library</expanded-acronym>
<sub-class-of type="audio/x-psf"/>
@@ -24013,106 +26196,117 @@
</mime-type>
<mime-type type="audio/x-ms-wma">
<comment>Windows Media audio</comment>
- <comment xml:lang="ar">Windows Media سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Windows Media</comment>
- <comment xml:lang="bg">Аудио — Windows Media</comment>
- <comment xml:lang="ca">àudio de Windows Media</comment>
- <comment xml:lang="cs">zvuk Windows Media</comment>
- <comment xml:lang="da">Windows Media-lyd</comment>
- <comment xml:lang="de">Windows-Media-Audio</comment>
- <comment xml:lang="el">Ήχος Windows Media</comment>
- <comment xml:lang="en_GB">Windows Media audio</comment>
- <comment xml:lang="es">sonido de Windows Media</comment>
- <comment xml:lang="eu">Windows Media audioa</comment>
- <comment xml:lang="fi">Windows Media -ääni</comment>
- <comment xml:lang="fo">Windows Media ljóður</comment>
- <comment xml:lang="fr">audio Windows Media</comment>
- <comment xml:lang="ga">fuaim Windows Media</comment>
- <comment xml:lang="gl">son de Windows Media</comment>
- <comment xml:lang="he">שמע של Windows Media</comment>
- <comment xml:lang="hr">Windows Media zvučni zapis</comment>
- <comment xml:lang="hu">Windows Media hang</comment>
- <comment xml:lang="ia">Audio Windows Media</comment>
- <comment xml:lang="id">Audio Windows Media</comment>
- <comment xml:lang="it">Audio Windows Media</comment>
- <comment xml:lang="ja">Windows Media オーディオ</comment>
- <comment xml:lang="kk">Windows Media аудиосы</comment>
- <comment xml:lang="ko">Windows 미디어 오디오</comment>
- <comment xml:lang="lt">Windows Media garso įrašas</comment>
- <comment xml:lang="lv">Windows Media audio</comment>
- <comment xml:lang="nb">Windows Media lyd</comment>
- <comment xml:lang="nl">Windows Media-audio</comment>
- <comment xml:lang="nn">Windows Media-lyd</comment>
- <comment xml:lang="oc">àudio Windows Media</comment>
- <comment xml:lang="pl">Plik dźwiękowy Windows Media</comment>
- <comment xml:lang="pt">áudio Windows Media</comment>
- <comment xml:lang="pt_BR">Áudio do Windows Media</comment>
- <comment xml:lang="ro">Audio Windows Media</comment>
- <comment xml:lang="ru">Аудио Windows Media</comment>
- <comment xml:lang="sk">Zvuk Windows Media</comment>
- <comment xml:lang="sl">Zvočna datoteka Windows Media</comment>
- <comment xml:lang="sq">Audio Windows Media</comment>
- <comment xml:lang="sr">Виндоуз Медија звук</comment>
- <comment xml:lang="sv">Windows Media-ljud</comment>
- <comment xml:lang="tr">Windows Media sesi</comment>
- <comment xml:lang="uk">звук Windows Media</comment>
- <comment xml:lang="vi">Âm thanh Windows Media</comment>
- <comment xml:lang="zh_CN">Windows Media 音频</comment>
<comment xml:lang="zh_TW">Windows Media 音訊</comment>
+ <comment xml:lang="zh_CN">Windows Media 音频</comment>
+ <comment xml:lang="vi">Âm thanh Windows Media</comment>
+ <comment xml:lang="uk">звук Windows Media</comment>
+ <comment xml:lang="tr">Windows Media sesi</comment>
+ <comment xml:lang="sv">Windows Media-ljud</comment>
+ <comment xml:lang="sr">Виндоуз Медија звук</comment>
+ <comment xml:lang="sq">audio Windows Media</comment>
+ <comment xml:lang="sl">Zvočna datoteka Windows Media</comment>
+ <comment xml:lang="si">වින්ඩෝස් මීඩියා ඕඩියෝ</comment>
+ <comment xml:lang="sk">Zvuk Windows Media</comment>
+ <comment xml:lang="ru">Аудио Windows Media</comment>
+ <comment xml:lang="ro">Audio Windows Media</comment>
+ <comment xml:lang="pt_BR">Áudio do Windows Media</comment>
+ <comment xml:lang="pt">áudio Windows Media</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Windows Media</comment>
+ <comment xml:lang="oc">àudio Windows Media</comment>
+ <comment xml:lang="nn">Windows Media-lyd</comment>
+ <comment xml:lang="nl">Windows Media-audio</comment>
+ <comment xml:lang="nb">Windows Media lyd</comment>
+ <comment xml:lang="lv">Windows Media audio</comment>
+ <comment xml:lang="lt">Windows Media garso įrašas</comment>
+ <comment xml:lang="ko">Windows 미디어 오디오</comment>
+ <comment xml:lang="kk">Windows Media аудиосы</comment>
+ <comment xml:lang="ja">Windows Media オーディオ</comment>
+ <comment xml:lang="it">Audio Windows Media</comment>
+ <comment xml:lang="is">Windows Media hljóðskrá</comment>
+ <comment xml:lang="id">Audio Windows Media</comment>
+ <comment xml:lang="ia">Audio Windows Media</comment>
+ <comment xml:lang="hu">Windows Media hang</comment>
+ <comment xml:lang="hr">Windows Media zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Windows Media</comment>
+ <comment xml:lang="gl">son de Windows Media</comment>
+ <comment xml:lang="ga">fuaim Windows Media</comment>
+ <comment xml:lang="fur">audio Windows Media</comment>
+ <comment xml:lang="fr">audio Windows Media</comment>
+ <comment xml:lang="fo">Windows Media ljóður</comment>
+ <comment xml:lang="fi">Windows Media -ääni</comment>
+ <comment xml:lang="eu">Windows Media audioa</comment>
+ <comment xml:lang="es">sonido de Windows Media</comment>
+ <comment xml:lang="en_GB">Windows Media audio</comment>
+ <comment xml:lang="el">Ήχος Windows Media</comment>
+ <comment xml:lang="de">Windows-Media-Audio</comment>
+ <comment xml:lang="da">Windows Media-lyd</comment>
+ <comment xml:lang="cs">zvuk Windows Media</comment>
+ <comment xml:lang="ca">àudio de Windows Media</comment>
+ <comment xml:lang="bg">Аудио — Windows Media</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Windows Media</comment>
+ <comment xml:lang="be">аўдыя Windows Media</comment>
+ <comment xml:lang="ar">فيديو ويندوز ميديا</comment>
+ <comment xml:lang="af">Windows Media-oudio</comment>
<sub-class-of type="application/vnd.ms-asf"/>
<glob pattern="*.wma"/>
<alias type="audio/wma"/>
</mime-type>
<mime-type type="audio/x-musepack">
<comment>Musepack audio</comment>
- <comment xml:lang="ar">Musepack سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo Musepack</comment>
- <comment xml:lang="bg">Аудио — Musepack</comment>
- <comment xml:lang="ca">àudio de Musepack</comment>
- <comment xml:lang="cs">zvuk Musepack</comment>
- <comment xml:lang="da">Musepacklyd</comment>
- <comment xml:lang="de">Musepack-Audio</comment>
- <comment xml:lang="el">Ήχος Musepack</comment>
- <comment xml:lang="en_GB">Musepack audio</comment>
- <comment xml:lang="es">sonido Musepack</comment>
- <comment xml:lang="eu">Musepack audioa</comment>
- <comment xml:lang="fi">Musepack-ääni</comment>
- <comment xml:lang="fo">Musepack ljóður</comment>
- <comment xml:lang="fr">audio Musepack</comment>
- <comment xml:lang="ga">fuaim Musepack</comment>
- <comment xml:lang="gl">son de Musepack</comment>
- <comment xml:lang="he">שמע של Musepack</comment>
- <comment xml:lang="hr">Musepack zvučni zapis</comment>
- <comment xml:lang="hu">Musepack hang</comment>
- <comment xml:lang="ia">Audio Musepack</comment>
- <comment xml:lang="id">Audio Musepack</comment>
- <comment xml:lang="it">Audio Musepack</comment>
- <comment xml:lang="ja">Musepack オーディオ</comment>
- <comment xml:lang="kk">Musepack аудиосы</comment>
- <comment xml:lang="ko">Musepack 오디오</comment>
- <comment xml:lang="lt">Musepack garso įrašas</comment>
- <comment xml:lang="lv">Musepack audio</comment>
- <comment xml:lang="nb">Musepack-lyd</comment>
- <comment xml:lang="nl">Musepack-audio</comment>
- <comment xml:lang="nn">Musepack-lyd</comment>
- <comment xml:lang="oc">àudio Musepack</comment>
- <comment xml:lang="pl">Plik dźwiękowy Musepack</comment>
- <comment xml:lang="pt">áudio Musepack</comment>
- <comment xml:lang="pt_BR">Áudio Musepack</comment>
- <comment xml:lang="ro">Audio Musepack</comment>
- <comment xml:lang="ru">Аудио Musepack</comment>
- <comment xml:lang="sk">Zvuk Musepack</comment>
- <comment xml:lang="sl">Zvočna datoteka Musepack</comment>
- <comment xml:lang="sq">Audio Musepack</comment>
- <comment xml:lang="sr">звук Мјузпака</comment>
- <comment xml:lang="sv">Musepack-ljud</comment>
- <comment xml:lang="tr">Musepack sesi</comment>
- <comment xml:lang="uk">звук Musepack</comment>
- <comment xml:lang="vi">Âm thanh Musepack</comment>
- <comment xml:lang="zh_CN">Musepack 音频</comment>
<comment xml:lang="zh_TW">Musepack 音訊</comment>
- <magic priority="50">
- <match value="MP+" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">Musepack 音频</comment>
+ <comment xml:lang="vi">Âm thanh Musepack</comment>
+ <comment xml:lang="uk">звук Musepack</comment>
+ <comment xml:lang="tr">Musepack sesi</comment>
+ <comment xml:lang="sv">Musepack-ljud</comment>
+ <comment xml:lang="sr">звук Мјузпака</comment>
+ <comment xml:lang="sq">audio Musepack</comment>
+ <comment xml:lang="sl">Zvočna datoteka Musepack</comment>
+ <comment xml:lang="si">Musepack ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk Musepack</comment>
+ <comment xml:lang="ru">Аудио Musepack</comment>
+ <comment xml:lang="ro">Audio Musepack</comment>
+ <comment xml:lang="pt_BR">Áudio Musepack</comment>
+ <comment xml:lang="pt">áudio Musepack</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Musepack</comment>
+ <comment xml:lang="oc">àudio Musepack</comment>
+ <comment xml:lang="nn">Musepack-lyd</comment>
+ <comment xml:lang="nl">Musepack-audio</comment>
+ <comment xml:lang="nb">Musepack-lyd</comment>
+ <comment xml:lang="lv">Musepack audio</comment>
+ <comment xml:lang="lt">Musepack garso įrašas</comment>
+ <comment xml:lang="ko">Musepack 오디오</comment>
+ <comment xml:lang="kk">Musepack аудиосы</comment>
+ <comment xml:lang="ja">Musepack オーディオ</comment>
+ <comment xml:lang="it">Audio Musepack</comment>
+ <comment xml:lang="is">Musepack hljóðskrá</comment>
+ <comment xml:lang="id">Audio Musepack</comment>
+ <comment xml:lang="ia">Audio Musepack</comment>
+ <comment xml:lang="hu">Musepack hang</comment>
+ <comment xml:lang="hr">Musepack zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Musepack</comment>
+ <comment xml:lang="gl">son de Musepack</comment>
+ <comment xml:lang="ga">fuaim Musepack</comment>
+ <comment xml:lang="fur">audio Musepack</comment>
+ <comment xml:lang="fr">audio Musepack</comment>
+ <comment xml:lang="fo">Musepack ljóður</comment>
+ <comment xml:lang="fi">Musepack-ääni</comment>
+ <comment xml:lang="eu">Musepack audioa</comment>
+ <comment xml:lang="es">sonido Musepack</comment>
+ <comment xml:lang="en_GB">Musepack audio</comment>
+ <comment xml:lang="el">Ήχος Musepack</comment>
+ <comment xml:lang="de">Musepack-Audio</comment>
+ <comment xml:lang="da">Musepack-lyd</comment>
+ <comment xml:lang="cs">zvuk Musepack</comment>
+ <comment xml:lang="ca">àudio de Musepack</comment>
+ <comment xml:lang="bg">Аудио — Musepack</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Musepack</comment>
+ <comment xml:lang="be">аўдыя Musepack</comment>
+ <comment xml:lang="ar">صوت Musepack</comment>
+ <comment xml:lang="af">Musepack-oudio</comment>
+ <magic>
+ <match type="string" value="MP+" offset="0"/>
+ <match type="string" value="MPCK" offset="0"/>
</magic>
<glob pattern="*.mpc"/>
<glob pattern="*.mpp"/>
@@ -24120,216 +26314,222 @@
</mime-type>
<mime-type type="audio/vnd.rn-realaudio">
<comment>RealAudio document</comment>
- <comment xml:lang="ar">مستند RealAudio</comment>
- <comment xml:lang="ast">Documentu RealAudio</comment>
- <comment xml:lang="be@latin">Dakument RealAudio</comment>
- <comment xml:lang="bg">Документ — RealAudio</comment>
- <comment xml:lang="ca">document RealAudio</comment>
- <comment xml:lang="cs">dokument RealAudio</comment>
- <comment xml:lang="da">RealAudio-dokument</comment>
- <comment xml:lang="de">RealAudio-Dokument</comment>
- <comment xml:lang="el">Έγγραφο RealAudio</comment>
- <comment xml:lang="en_GB">RealAudio document</comment>
- <comment xml:lang="eo">RealAudio-dokumento</comment>
- <comment xml:lang="es">documento RealAudio</comment>
- <comment xml:lang="eu">RealAudio dokumentua</comment>
- <comment xml:lang="fi">RealAudio-asiakirja</comment>
- <comment xml:lang="fo">RealAudio skjal</comment>
- <comment xml:lang="fr">document RealAudio</comment>
- <comment xml:lang="ga">cáipéis RealAudio</comment>
- <comment xml:lang="gl">documento Realson</comment>
- <comment xml:lang="he">מסמך של RealAudio</comment>
- <comment xml:lang="hr">RealAudio dokument</comment>
- <comment xml:lang="hu">RealAudio dokumentum</comment>
- <comment xml:lang="ia">Documento RealAudio</comment>
- <comment xml:lang="id">Dokumen RealAudio</comment>
- <comment xml:lang="it">Documento RealAudio</comment>
- <comment xml:lang="ja">RealAudio ドキュメント</comment>
- <comment xml:lang="kk">RealAudio құжаты</comment>
- <comment xml:lang="ko">RealAudio 문서</comment>
- <comment xml:lang="lt">RealAudio dokumentas</comment>
- <comment xml:lang="lv">RealAudio dokuments</comment>
- <comment xml:lang="nb">RealAudio-dokument</comment>
- <comment xml:lang="nl">RealAudio-document</comment>
- <comment xml:lang="nn">RealAudio-dokument</comment>
- <comment xml:lang="oc">document RealAudio</comment>
- <comment xml:lang="pl">Dokument RealAudio</comment>
- <comment xml:lang="pt">documento RealAudio</comment>
- <comment xml:lang="pt_BR">Documento RealAudio</comment>
- <comment xml:lang="ro">Document RealAudio</comment>
- <comment xml:lang="ru">Документ RealAudio</comment>
- <comment xml:lang="sk">Dokument RealAudio</comment>
- <comment xml:lang="sl">Dokument RealAudio</comment>
- <comment xml:lang="sq">Dokument RealAudio</comment>
- <comment xml:lang="sr">документ Рил Аудиа</comment>
- <comment xml:lang="sv">RealAudio-dokument</comment>
- <comment xml:lang="tr">RealAudio belgesi</comment>
- <comment xml:lang="uk">документ RealAudio</comment>
- <comment xml:lang="vi">Tài liệu âm thanh RealAudio</comment>
- <comment xml:lang="zh_CN">RealAudio 文档</comment>
<comment xml:lang="zh_TW">RealAudio 文件</comment>
+ <comment xml:lang="zh_CN">RealAudio 文档</comment>
+ <comment xml:lang="vi">Tài liệu âm thanh RealAudio</comment>
+ <comment xml:lang="uk">документ RealAudio</comment>
+ <comment xml:lang="tr">RealAudio belgesi</comment>
+ <comment xml:lang="sv">RealAudio-dokument</comment>
+ <comment xml:lang="sr">документ Рил Аудиа</comment>
+ <comment xml:lang="sq">dokument RealAudio</comment>
+ <comment xml:lang="sl">Dokument RealAudio</comment>
+ <comment xml:lang="si">රියල් ඕඩියෝ ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RealAudio</comment>
+ <comment xml:lang="ru">Документ RealAudio</comment>
+ <comment xml:lang="ro">Document RealAudio</comment>
+ <comment xml:lang="pt_BR">Documento RealAudio</comment>
+ <comment xml:lang="pt">documento RealAudio</comment>
+ <comment xml:lang="pl">Dokument RealAudio</comment>
+ <comment xml:lang="oc">document RealAudio</comment>
+ <comment xml:lang="nn">RealAudio-dokument</comment>
+ <comment xml:lang="nl">RealAudio-document</comment>
+ <comment xml:lang="nb">RealAudio-dokument</comment>
+ <comment xml:lang="lv">RealAudio dokuments</comment>
+ <comment xml:lang="lt">RealAudio dokumentas</comment>
+ <comment xml:lang="ko">RealAudio 문서</comment>
+ <comment xml:lang="kk">RealAudio құжаты</comment>
+ <comment xml:lang="ja">RealAudio ドキュメント</comment>
+ <comment xml:lang="it">Documento RealAudio</comment>
+ <comment xml:lang="is">RealAudio skjal</comment>
+ <comment xml:lang="id">Dokumen RealAudio</comment>
+ <comment xml:lang="ia">Documento RealAudio</comment>
+ <comment xml:lang="hu">RealAudio dokumentum</comment>
+ <comment xml:lang="hr">RealAudio dokument</comment>
+ <comment xml:lang="he">מסמך של RealAudio</comment>
+ <comment xml:lang="gl">documento Realson</comment>
+ <comment xml:lang="ga">cáipéis RealAudio</comment>
+ <comment xml:lang="fur">document RealAudio</comment>
+ <comment xml:lang="fr">document RealAudio</comment>
+ <comment xml:lang="fo">RealAudio skjal</comment>
+ <comment xml:lang="fi">RealAudio-asiakirja</comment>
+ <comment xml:lang="eu">RealAudio dokumentua</comment>
+ <comment xml:lang="es">documento RealAudio</comment>
+ <comment xml:lang="eo">RealAudio-dokumento</comment>
+ <comment xml:lang="en_GB">RealAudio document</comment>
+ <comment xml:lang="el">Έγγραφο RealAudio</comment>
+ <comment xml:lang="de">RealAudio-Dokument</comment>
+ <comment xml:lang="da">RealAudio-dokument</comment>
+ <comment xml:lang="cs">dokument RealAudio</comment>
+ <comment xml:lang="ca">document RealAudio</comment>
+ <comment xml:lang="bg">Документ — RealAudio</comment>
+ <comment xml:lang="be@latin">Dakument RealAudio</comment>
+ <comment xml:lang="be">дакумент RealAudio</comment>
+ <comment xml:lang="ast">Documentu RealAudio</comment>
+ <comment xml:lang="ar">مستند RealAudio</comment>
+ <comment xml:lang="af">RealAudio-dokument</comment>
<glob pattern="*.ra"/>
<glob pattern="*.rax"/>
<alias type="audio/x-pn-realaudio"/>
<alias type="audio/vnd.m-realaudio"/>
</mime-type>
<mime-type type="application/ram">
- <comment>RealMedia Metafile</comment>
- <comment xml:lang="ar">ملف تعريف RealMedia</comment>
- <comment xml:lang="be@latin">Metafajł RealMedia</comment>
- <comment xml:lang="bg">Метафайл — RealMedia</comment>
- <comment xml:lang="ca">metafitxer RealMedia</comment>
- <comment xml:lang="cs">RealMedia Metafile</comment>
- <comment xml:lang="da">RealMedia-metafil</comment>
- <comment xml:lang="de">RealMedia-Metadatei</comment>
- <comment xml:lang="el">Metafile RealMedia</comment>
- <comment xml:lang="en_GB">RealMedia Metafile</comment>
- <comment xml:lang="es">metaarchivo RealMedia</comment>
- <comment xml:lang="eu">RealMedia metafitxategia</comment>
- <comment xml:lang="fi">RealMedia-metatiedosto</comment>
- <comment xml:lang="fo">RealMedia metafíla</comment>
- <comment xml:lang="fr">métafichier RealMedia</comment>
- <comment xml:lang="ga">Meiteachomhad RealMedia</comment>
- <comment xml:lang="gl">Metaficheiro RealMedia</comment>
- <comment xml:lang="he">קובץ מטא של RealMedia</comment>
- <comment xml:lang="hr">RealMedia meta datoteka</comment>
- <comment xml:lang="hu">RealMedia metafájl</comment>
- <comment xml:lang="ia">Metafile RealMedia</comment>
- <comment xml:lang="id">RealMedia Metafile</comment>
- <comment xml:lang="it">Metafile RealMedia</comment>
- <comment xml:lang="ja">RealMedia メタファイル</comment>
- <comment xml:lang="kk">RealMedia метафайлы</comment>
- <comment xml:lang="ko">RealMedia 메타 파일</comment>
- <comment xml:lang="lt">RealMedia metafailas</comment>
- <comment xml:lang="lv">RealMedia metadatne</comment>
- <comment xml:lang="nb">RealMedia-metafil</comment>
- <comment xml:lang="nl">RealMedia-metabestand</comment>
- <comment xml:lang="nn">RealMedia-metafil</comment>
- <comment xml:lang="oc">metafichièr RealMedia</comment>
- <comment xml:lang="pl">Metaplik RealMedia</comment>
- <comment xml:lang="pt">metaficheiro RealMedia</comment>
- <comment xml:lang="pt_BR">Meta arquivo do RealMedia</comment>
- <comment xml:lang="ro">Metafișier RealMedia</comment>
- <comment xml:lang="ru">Мета-файл RealMedia</comment>
- <comment xml:lang="sk">RealMedia Metafile</comment>
- <comment xml:lang="sl">Metadatoteka RealMedia</comment>
- <comment xml:lang="sq">Metafile RealMedia</comment>
- <comment xml:lang="sr">метадатотека Рил Медија</comment>
- <comment xml:lang="sv">RealMedia-metafil</comment>
- <comment xml:lang="tr">RealMedia Meta Dosyası</comment>
- <comment xml:lang="uk">метафайл RealMedia</comment>
- <comment xml:lang="vi">Siêu tập tin RealMedia</comment>
- <comment xml:lang="zh_CN">RealMedia 元文件</comment>
- <comment xml:lang="zh_TW">RealMedia 中介檔</comment>
+ <comment>RealMedia playlist</comment>
+ <comment xml:lang="zh_TW">RealMedia 播放清單</comment>
+ <comment xml:lang="zh_CN">RealMedia 播放列表</comment>
+ <comment xml:lang="uk">список відтворення RealMedia</comment>
+ <comment xml:lang="tr">RealMedia çalma listesi</comment>
+ <comment xml:lang="sv">RealMedia-spellista</comment>
+ <comment xml:lang="sq">luajlistë RealMedia</comment>
+ <comment xml:lang="sl">Seznam predvajanja RealMedia</comment>
+ <comment xml:lang="si">RealMedia ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb RealMedia</comment>
+ <comment xml:lang="ru">Список воспроизведения RealMedia</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução do RealMedia</comment>
+ <comment xml:lang="pl">Lista odtwarzania RealMedia</comment>
+ <comment xml:lang="oc">lista de lectura RealMedia</comment>
+ <comment xml:lang="nl">RealMedia-afspeellijst</comment>
+ <comment xml:lang="lt">RealMedia grojaraštis</comment>
+ <comment xml:lang="ko">RealMedia 재생 목록</comment>
+ <comment xml:lang="kk">RealMedia ойнау тізімі</comment>
+ <comment xml:lang="ka">RealMedia დასაკრავი სია</comment>
+ <comment xml:lang="ja">RealMedia プレイリスト</comment>
+ <comment xml:lang="it">Playlist RealMedia</comment>
+ <comment xml:lang="is">RealMedia spilunarlisti</comment>
+ <comment xml:lang="id">Daftar putar RealMedia</comment>
+ <comment xml:lang="hu">RealMedia lejátszólista</comment>
+ <comment xml:lang="hr">RealMedia popis izvođenja</comment>
+ <comment xml:lang="he">רשימת השמעה של RealMedia</comment>
+ <comment xml:lang="gl">Lista de reprodución RealMedia</comment>
+ <comment xml:lang="fr">liste de lecture RealMedia</comment>
+ <comment xml:lang="fi">RealMedia-soittolista</comment>
+ <comment xml:lang="eu">RealMedia erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción de RealMedia</comment>
+ <comment xml:lang="en_GB">RealMedia playlist</comment>
+ <comment xml:lang="de">RealMedia-Wiedergabeliste</comment>
+ <comment xml:lang="da">RealMedia-afspilningsliste</comment>
+ <comment xml:lang="ca">llista de reproducció RealMedia</comment>
+ <comment xml:lang="bg">Списък за изпълнение — RealMedia</comment>
+ <comment xml:lang="be">плэй-ліст RealMedia</comment>
+ <comment xml:lang="ar">قائمة تشغيل RealMedia</comment>
<glob pattern="*.ram"/>
</mime-type>
<mime-type type="video/vnd.rn-realvideo">
<comment>RealVideo document</comment>
- <comment xml:lang="ar">مستند RealVideo</comment>
- <comment xml:lang="ast">Documentu RealVideo</comment>
- <comment xml:lang="be@latin">Dakument RealVideo</comment>
- <comment xml:lang="bg">Документ — RealVideo</comment>
- <comment xml:lang="ca">document RealVideo</comment>
- <comment xml:lang="cs">dokument RealVideo</comment>
- <comment xml:lang="da">RealAudio-dokument</comment>
- <comment xml:lang="de">RealVideo-Dokument</comment>
- <comment xml:lang="el">Έγγραφο RealVideo</comment>
- <comment xml:lang="en_GB">RealVideo document</comment>
- <comment xml:lang="eo">RealVideo-dokumento</comment>
- <comment xml:lang="es">documento RealVideo</comment>
- <comment xml:lang="eu">RealVideo dokumentua</comment>
- <comment xml:lang="fi">RealVideo-asiakirja</comment>
- <comment xml:lang="fo">RealVideo skjal</comment>
- <comment xml:lang="fr">document RealVideo</comment>
- <comment xml:lang="ga">cáipéis RealVideo</comment>
- <comment xml:lang="gl">documento RealVideo</comment>
- <comment xml:lang="he">מסמך של RealVideo</comment>
- <comment xml:lang="hr">RealVideo dokument</comment>
- <comment xml:lang="hu">RealVideo dokumentum</comment>
- <comment xml:lang="ia">Documento RealVideo</comment>
- <comment xml:lang="id">Dokumen RealVideo</comment>
- <comment xml:lang="it">Documento RealVideo</comment>
- <comment xml:lang="ja">RealVideo ドキュメント</comment>
- <comment xml:lang="kk">RealVideo құжаты</comment>
- <comment xml:lang="ko">RealVideo 문서</comment>
- <comment xml:lang="lt">RealVideo dokumentas</comment>
- <comment xml:lang="lv">RealVideo dokuments</comment>
- <comment xml:lang="nb">RealAudio-dokument</comment>
- <comment xml:lang="nl">RealVideo-document</comment>
- <comment xml:lang="nn">RealVideo-dokument</comment>
- <comment xml:lang="oc">document RealVideo</comment>
- <comment xml:lang="pl">Dokument RealVideo</comment>
- <comment xml:lang="pt">documento RealVideo</comment>
- <comment xml:lang="pt_BR">Documento RealVideo</comment>
- <comment xml:lang="ro">Document RealVideo</comment>
- <comment xml:lang="ru">Документ RealVideo</comment>
- <comment xml:lang="sk">Dokument RealVideo</comment>
- <comment xml:lang="sl">Video datoteka RealVideo</comment>
- <comment xml:lang="sq">Dokument RealVideo</comment>
- <comment xml:lang="sr">документ Рил Видеа</comment>
- <comment xml:lang="sv">RealVideo-dokument</comment>
- <comment xml:lang="tr">RealAudio belgesi</comment>
- <comment xml:lang="uk">документ RealVideo</comment>
- <comment xml:lang="vi">Tài liệu ảnh động RealVideo</comment>
- <comment xml:lang="zh_CN">RealAudio 文档</comment>
<comment xml:lang="zh_TW">RealVideo 文件</comment>
+ <comment xml:lang="zh_CN">RealAudio 文档</comment>
+ <comment xml:lang="vi">Tài liệu ảnh động RealVideo</comment>
+ <comment xml:lang="uk">документ RealVideo</comment>
+ <comment xml:lang="tr">RealVideo belgesi</comment>
+ <comment xml:lang="sv">RealVideo-dokument</comment>
+ <comment xml:lang="sr">документ Рил Видеа</comment>
+ <comment xml:lang="sq">dokument RealVideo</comment>
+ <comment xml:lang="sl">Video datoteka RealVideo</comment>
+ <comment xml:lang="si">RealVideo ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RealVideo</comment>
+ <comment xml:lang="ru">Документ RealVideo</comment>
+ <comment xml:lang="ro">Document RealVideo</comment>
+ <comment xml:lang="pt_BR">Documento RealVideo</comment>
+ <comment xml:lang="pt">documento RealVideo</comment>
+ <comment xml:lang="pl">Dokument RealVideo</comment>
+ <comment xml:lang="oc">document RealVideo</comment>
+ <comment xml:lang="nn">RealVideo-dokument</comment>
+ <comment xml:lang="nl">RealVideo-document</comment>
+ <comment xml:lang="nb">RealAudio-dokument</comment>
+ <comment xml:lang="lv">RealVideo dokuments</comment>
+ <comment xml:lang="lt">RealVideo dokumentas</comment>
+ <comment xml:lang="ko">RealVideo 문서</comment>
+ <comment xml:lang="kk">RealVideo құжаты</comment>
+ <comment xml:lang="ja">RealVideo ドキュメント</comment>
+ <comment xml:lang="it">Documento RealVideo</comment>
+ <comment xml:lang="is">RealVideo skjal</comment>
+ <comment xml:lang="id">Dokumen RealVideo</comment>
+ <comment xml:lang="ia">Documento RealVideo</comment>
+ <comment xml:lang="hu">RealVideo dokumentum</comment>
+ <comment xml:lang="hr">RealVideo dokument</comment>
+ <comment xml:lang="he">מסמך של RealVideo</comment>
+ <comment xml:lang="gl">documento RealVideo</comment>
+ <comment xml:lang="ga">cáipéis RealVideo</comment>
+ <comment xml:lang="fur">document RealVideo</comment>
+ <comment xml:lang="fr">document RealVideo</comment>
+ <comment xml:lang="fo">RealVideo skjal</comment>
+ <comment xml:lang="fi">RealVideo-asiakirja</comment>
+ <comment xml:lang="eu">RealVideo dokumentua</comment>
+ <comment xml:lang="es">documento RealVideo</comment>
+ <comment xml:lang="eo">RealVideo-dokumento</comment>
+ <comment xml:lang="en_GB">RealVideo document</comment>
+ <comment xml:lang="el">Έγγραφο RealVideo</comment>
+ <comment xml:lang="de">RealVideo-Dokument</comment>
+ <comment xml:lang="da">RealAudio-dokument</comment>
+ <comment xml:lang="cs">dokument RealVideo</comment>
+ <comment xml:lang="ca">document RealVideo</comment>
+ <comment xml:lang="bg">Документ — RealVideo</comment>
+ <comment xml:lang="be@latin">Dakument RealVideo</comment>
+ <comment xml:lang="be">дакумент RealVideo</comment>
+ <comment xml:lang="ast">Documentu RealVideo</comment>
+ <comment xml:lang="ar">مستند RealVideo</comment>
+ <comment xml:lang="af">RealVideo-dokument</comment>
<glob pattern="*.rv"/>
<glob pattern="*.rvx"/>
<alias type="video/x-real-video"/>
</mime-type>
<mime-type type="application/vnd.rn-realmedia">
<comment>RealMedia document</comment>
- <comment xml:lang="ar">مستند RealMedia</comment>
- <comment xml:lang="ast">Documentu RealMedia</comment>
- <comment xml:lang="be@latin">Dakument RealMedia</comment>
- <comment xml:lang="bg">Документ — RealMedia</comment>
- <comment xml:lang="ca">document RealMedia</comment>
- <comment xml:lang="cs">dokument RealMedia</comment>
- <comment xml:lang="da">RealMedia-dokument</comment>
- <comment xml:lang="de">RealMedia-Dokument</comment>
- <comment xml:lang="el">Έγγραφο RealMedia</comment>
- <comment xml:lang="en_GB">RealMedia document</comment>
- <comment xml:lang="eo">RealMedia-dokumento</comment>
- <comment xml:lang="es">documento RealMedia</comment>
- <comment xml:lang="eu">RealMedia dokumentua</comment>
- <comment xml:lang="fi">RealMedia-asiakirja</comment>
- <comment xml:lang="fo">RealMedia skjal</comment>
- <comment xml:lang="fr">document RealMedia</comment>
- <comment xml:lang="ga">cáipéis RealMedia</comment>
- <comment xml:lang="gl">documento RealMedia</comment>
- <comment xml:lang="he">מסמך של RealMedia</comment>
- <comment xml:lang="hr">RealMedia dokument</comment>
- <comment xml:lang="hu">RealMedia dokumentum</comment>
- <comment xml:lang="ia">Documento RealMedia</comment>
- <comment xml:lang="id">Dokumen RealMedia</comment>
- <comment xml:lang="it">Documento RealMedia</comment>
- <comment xml:lang="ja">RealMedia ドキュメント</comment>
- <comment xml:lang="kk">RealMedia құжаты</comment>
- <comment xml:lang="ko">RealMedia 문서</comment>
- <comment xml:lang="lt">RealMedia dokumentas</comment>
- <comment xml:lang="lv">RealMedia dokuments</comment>
- <comment xml:lang="nb">RealMedia-dokument</comment>
- <comment xml:lang="nl">RealMedia-document</comment>
- <comment xml:lang="nn">RealMedia-dokument</comment>
- <comment xml:lang="oc">document RealMedia</comment>
- <comment xml:lang="pl">Dokument RealMedia</comment>
- <comment xml:lang="pt">documento RealMedia</comment>
- <comment xml:lang="pt_BR">Documento RealMedia</comment>
- <comment xml:lang="ro">Document RealMedia</comment>
- <comment xml:lang="ru">Документ RealMedia</comment>
- <comment xml:lang="sk">Dokument RealMedia</comment>
- <comment xml:lang="sl">Dokument RealMedia</comment>
- <comment xml:lang="sq">Dokument RealMedia</comment>
- <comment xml:lang="sr">документ Рил Медија</comment>
- <comment xml:lang="sv">RealMedia-dokument</comment>
- <comment xml:lang="tr">RealMedia belgesi</comment>
- <comment xml:lang="uk">документ RealMedia</comment>
- <comment xml:lang="vi">Tài liệu RealMedia</comment>
- <comment xml:lang="zh_CN">RealMedia 文档</comment>
<comment xml:lang="zh_TW">RealMedia 文件</comment>
+ <comment xml:lang="zh_CN">RealMedia 文档</comment>
+ <comment xml:lang="vi">Tài liệu RealMedia</comment>
+ <comment xml:lang="uk">документ RealMedia</comment>
+ <comment xml:lang="tr">RealMedia belgesi</comment>
+ <comment xml:lang="sv">RealMedia-dokument</comment>
+ <comment xml:lang="sr">документ Рил Медија</comment>
+ <comment xml:lang="sq">dokument RealMedia</comment>
+ <comment xml:lang="sl">Dokument RealMedia</comment>
+ <comment xml:lang="si">රියල් මීඩියා ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RealMedia</comment>
+ <comment xml:lang="ru">Документ RealMedia</comment>
+ <comment xml:lang="ro">Document RealMedia</comment>
+ <comment xml:lang="pt_BR">Documento RealMedia</comment>
+ <comment xml:lang="pt">documento RealMedia</comment>
+ <comment xml:lang="pl">Dokument RealMedia</comment>
+ <comment xml:lang="oc">document RealMedia</comment>
+ <comment xml:lang="nn">RealMedia-dokument</comment>
+ <comment xml:lang="nl">RealMedia-document</comment>
+ <comment xml:lang="nb">RealMedia-dokument</comment>
+ <comment xml:lang="lv">RealMedia dokuments</comment>
+ <comment xml:lang="lt">RealMedia dokumentas</comment>
+ <comment xml:lang="ko">RealMedia 문서</comment>
+ <comment xml:lang="kk">RealMedia құжаты</comment>
+ <comment xml:lang="ja">RealMedia ドキュメント</comment>
+ <comment xml:lang="it">Documento RealMedia</comment>
+ <comment xml:lang="is">RealMedia skjal</comment>
+ <comment xml:lang="id">Dokumen RealMedia</comment>
+ <comment xml:lang="ia">Documento RealMedia</comment>
+ <comment xml:lang="hu">RealMedia dokumentum</comment>
+ <comment xml:lang="hr">RealMedia dokument</comment>
+ <comment xml:lang="he">מסמך של RealMedia</comment>
+ <comment xml:lang="gl">documento RealMedia</comment>
+ <comment xml:lang="ga">cáipéis RealMedia</comment>
+ <comment xml:lang="fur">document RealMedia</comment>
+ <comment xml:lang="fr">document RealMedia</comment>
+ <comment xml:lang="fo">RealMedia skjal</comment>
+ <comment xml:lang="fi">RealMedia-asiakirja</comment>
+ <comment xml:lang="eu">RealMedia dokumentua</comment>
+ <comment xml:lang="es">documento RealMedia</comment>
+ <comment xml:lang="eo">RealMedia-dokumento</comment>
+ <comment xml:lang="en_GB">RealMedia document</comment>
+ <comment xml:lang="el">Έγγραφο RealMedia</comment>
+ <comment xml:lang="de">RealMedia-Dokument</comment>
+ <comment xml:lang="da">RealMedia-dokument</comment>
+ <comment xml:lang="cs">dokument RealMedia</comment>
+ <comment xml:lang="ca">document RealMedia</comment>
+ <comment xml:lang="bg">Документ — RealMedia</comment>
+ <comment xml:lang="be@latin">Dakument RealMedia</comment>
+ <comment xml:lang="be">дакумент RealMedia</comment>
+ <comment xml:lang="ast">Documentu RealMedia</comment>
+ <comment xml:lang="ar">مستند RealMedia</comment>
+ <comment xml:lang="af">RealMedia-dokument</comment>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
- <match value=".RMF" type="string" offset="0"/>
+ <magic>
+ <match type="string" value=".RMF" offset="0"/>
</magic>
<glob pattern="*.rm"/>
<glob pattern="*.rmj"/>
@@ -24341,717 +26541,742 @@
</mime-type>
<mime-type type="image/vnd.rn-realpix">
<comment>RealPix document</comment>
- <comment xml:lang="ar">مستند RealPix</comment>
- <comment xml:lang="ast">Documentu RealPix</comment>
- <comment xml:lang="be@latin">Dakument RealPix</comment>
- <comment xml:lang="bg">Документ — RealPix</comment>
- <comment xml:lang="ca">document RealPix</comment>
- <comment xml:lang="cs">dokument RealPix</comment>
- <comment xml:lang="da">RealPix-dokument</comment>
- <comment xml:lang="de">RealPix-Dokument</comment>
- <comment xml:lang="el">Έγγραφο RealPix</comment>
- <comment xml:lang="en_GB">RealPix document</comment>
- <comment xml:lang="eo">RealPix-dokumento</comment>
- <comment xml:lang="es">documento RealPix</comment>
- <comment xml:lang="eu">RealPix dokumentua</comment>
- <comment xml:lang="fi">RealPix-asiakirja</comment>
- <comment xml:lang="fo">RealPix skjal</comment>
- <comment xml:lang="fr">document RealPix</comment>
- <comment xml:lang="ga">cáipéis RealPix</comment>
- <comment xml:lang="gl">documento RealPix</comment>
- <comment xml:lang="he">מסמך של RealPix</comment>
- <comment xml:lang="hr">RealPix dokument</comment>
- <comment xml:lang="hu">RealPix dokumentum</comment>
- <comment xml:lang="ia">Documento RealPix</comment>
- <comment xml:lang="id">Dokumen RealPix</comment>
- <comment xml:lang="it">Documento RealPix</comment>
- <comment xml:lang="ja">RealPix ドキュメント</comment>
- <comment xml:lang="kk">RealPix құжаты</comment>
- <comment xml:lang="ko">RealPix 문서</comment>
- <comment xml:lang="lt">RealPix dokumentas</comment>
- <comment xml:lang="lv">RealPix dokuments</comment>
- <comment xml:lang="nb">RealPix-dokument</comment>
- <comment xml:lang="nl">RealPix-document</comment>
- <comment xml:lang="nn">RealPix-dokument</comment>
- <comment xml:lang="oc">document RealPix</comment>
- <comment xml:lang="pl">Dokument RealPix</comment>
- <comment xml:lang="pt">documento RealPix</comment>
- <comment xml:lang="pt_BR">Documento RealPix</comment>
- <comment xml:lang="ro">Document RealPix</comment>
- <comment xml:lang="ru">Документ RealPix</comment>
- <comment xml:lang="sk">Dokument RealPix</comment>
- <comment xml:lang="sl">Dokument RealPix</comment>
- <comment xml:lang="sq">Dokument RealPix</comment>
- <comment xml:lang="sr">документ Рил Пикса</comment>
- <comment xml:lang="sv">RealPix-dokument</comment>
- <comment xml:lang="tr">RealPix belgesi</comment>
- <comment xml:lang="uk">документ RealPix</comment>
- <comment xml:lang="vi">Tài liệu ảnh RealPix</comment>
- <comment xml:lang="zh_CN">RealPix 文档</comment>
<comment xml:lang="zh_TW">RealPix 文件</comment>
+ <comment xml:lang="zh_CN">RealPix 文档</comment>
+ <comment xml:lang="vi">Tài liệu ảnh RealPix</comment>
+ <comment xml:lang="uk">документ RealPix</comment>
+ <comment xml:lang="tr">RealPix belgesi</comment>
+ <comment xml:lang="sv">RealPix-dokument</comment>
+ <comment xml:lang="sr">документ Рил Пикса</comment>
+ <comment xml:lang="sq">dokument RealPix</comment>
+ <comment xml:lang="sl">Dokument RealPix</comment>
+ <comment xml:lang="si">RealPix ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RealPix</comment>
+ <comment xml:lang="ru">Документ RealPix</comment>
+ <comment xml:lang="ro">Document RealPix</comment>
+ <comment xml:lang="pt_BR">Documento RealPix</comment>
+ <comment xml:lang="pt">documento RealPix</comment>
+ <comment xml:lang="pl">Dokument RealPix</comment>
+ <comment xml:lang="oc">document RealPix</comment>
+ <comment xml:lang="nn">RealPix-dokument</comment>
+ <comment xml:lang="nl">RealPix-document</comment>
+ <comment xml:lang="nb">RealPix-dokument</comment>
+ <comment xml:lang="lv">RealPix dokuments</comment>
+ <comment xml:lang="lt">RealPix dokumentas</comment>
+ <comment xml:lang="ko">RealPix 문서</comment>
+ <comment xml:lang="kk">RealPix құжаты</comment>
+ <comment xml:lang="ja">RealPix ドキュメント</comment>
+ <comment xml:lang="it">Documento RealPix</comment>
+ <comment xml:lang="is">RealPix skjal</comment>
+ <comment xml:lang="id">Dokumen RealPix</comment>
+ <comment xml:lang="ia">Documento RealPix</comment>
+ <comment xml:lang="hu">RealPix dokumentum</comment>
+ <comment xml:lang="hr">RealPix dokument</comment>
+ <comment xml:lang="he">מסמך של RealPix</comment>
+ <comment xml:lang="gl">documento RealPix</comment>
+ <comment xml:lang="ga">cáipéis RealPix</comment>
+ <comment xml:lang="fur">document RealPix</comment>
+ <comment xml:lang="fr">document RealPix</comment>
+ <comment xml:lang="fo">RealPix skjal</comment>
+ <comment xml:lang="fi">RealPix-asiakirja</comment>
+ <comment xml:lang="eu">RealPix dokumentua</comment>
+ <comment xml:lang="es">documento RealPix</comment>
+ <comment xml:lang="eo">RealPix-dokumento</comment>
+ <comment xml:lang="en_GB">RealPix document</comment>
+ <comment xml:lang="el">Έγγραφο RealPix</comment>
+ <comment xml:lang="de">RealPix-Dokument</comment>
+ <comment xml:lang="da">RealPix-dokument</comment>
+ <comment xml:lang="cs">dokument RealPix</comment>
+ <comment xml:lang="ca">document RealPix</comment>
+ <comment xml:lang="bg">Документ — RealPix</comment>
+ <comment xml:lang="be@latin">Dakument RealPix</comment>
+ <comment xml:lang="be">дакумент RealPix</comment>
+ <comment xml:lang="ast">Documentu RealPix</comment>
+ <comment xml:lang="ar">مستند RealPix</comment>
+ <comment xml:lang="af">RealPix-dokument</comment>
<glob pattern="*.rp"/>
</mime-type>
<mime-type type="text/vnd.rn-realtext">
<comment>RealText document</comment>
- <comment xml:lang="ar">مستند RealText</comment>
- <comment xml:lang="ast">Documentu RealText</comment>
- <comment xml:lang="be@latin">Dakument RealText</comment>
- <comment xml:lang="bg">Документ — RealText</comment>
- <comment xml:lang="ca">document RealText</comment>
- <comment xml:lang="cs">dokument RealText</comment>
- <comment xml:lang="da">RealText-dokument</comment>
- <comment xml:lang="de">RealText-Dokument</comment>
- <comment xml:lang="el">Έγγραφο RealText</comment>
- <comment xml:lang="en_GB">RealText document</comment>
- <comment xml:lang="eo">RealText-dokumento</comment>
- <comment xml:lang="es">documento RealText</comment>
- <comment xml:lang="eu">RealText dokumentua</comment>
- <comment xml:lang="fi">RealText-asiakirja</comment>
- <comment xml:lang="fo">RealText skjal</comment>
- <comment xml:lang="fr">document RealText</comment>
- <comment xml:lang="ga">cáipéis RealText</comment>
- <comment xml:lang="gl">documento RealText</comment>
- <comment xml:lang="he">מסמך של RealText</comment>
- <comment xml:lang="hr">RealText dokument</comment>
- <comment xml:lang="hu">RealText dokumentum</comment>
- <comment xml:lang="ia">Documento RealText</comment>
- <comment xml:lang="id">Dokumen RealText</comment>
- <comment xml:lang="it">Documento RealText</comment>
- <comment xml:lang="ja">RealText ドキュメント</comment>
- <comment xml:lang="kk">RealText құжаты</comment>
- <comment xml:lang="ko">RealText 문서</comment>
- <comment xml:lang="lt">RealText dokumentas</comment>
- <comment xml:lang="lv">RealText dokuments</comment>
- <comment xml:lang="nb">RealText-dokument</comment>
- <comment xml:lang="nl">RealText-document</comment>
- <comment xml:lang="nn">RealText-dokument</comment>
- <comment xml:lang="oc">document RealText</comment>
- <comment xml:lang="pl">Dokument RealText</comment>
- <comment xml:lang="pt">documento RealText</comment>
- <comment xml:lang="pt_BR">Documento RealText</comment>
- <comment xml:lang="ro">Document RealText</comment>
- <comment xml:lang="ru">Документ RealText</comment>
- <comment xml:lang="sk">Dokument RealText</comment>
- <comment xml:lang="sl">Dokument RealText</comment>
- <comment xml:lang="sq">Dokument RealText</comment>
- <comment xml:lang="sr">документ Рил Текста</comment>
- <comment xml:lang="sv">RealText-dokument</comment>
- <comment xml:lang="tr">RealText belgesi</comment>
- <comment xml:lang="uk">документ RealText</comment>
- <comment xml:lang="vi">Tài liệu văn bản RealText</comment>
- <comment xml:lang="zh_CN">RealText 文档</comment>
<comment xml:lang="zh_TW">RealText 文件</comment>
+ <comment xml:lang="zh_CN">RealText 文档</comment>
+ <comment xml:lang="vi">Tài liệu văn bản RealText</comment>
+ <comment xml:lang="uk">документ RealText</comment>
+ <comment xml:lang="tr">RealText belgesi</comment>
+ <comment xml:lang="sv">RealText-dokument</comment>
+ <comment xml:lang="sr">документ Рил Текста</comment>
+ <comment xml:lang="sq">dokument RealText</comment>
+ <comment xml:lang="sl">Dokument RealText</comment>
+ <comment xml:lang="si">RealText ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument RealText</comment>
+ <comment xml:lang="ru">Документ RealText</comment>
+ <comment xml:lang="ro">Document RealText</comment>
+ <comment xml:lang="pt_BR">Documento RealText</comment>
+ <comment xml:lang="pt">documento RealText</comment>
+ <comment xml:lang="pl">Dokument RealText</comment>
+ <comment xml:lang="oc">document RealText</comment>
+ <comment xml:lang="nn">RealText-dokument</comment>
+ <comment xml:lang="nl">RealText-document</comment>
+ <comment xml:lang="nb">RealText-dokument</comment>
+ <comment xml:lang="lv">RealText dokuments</comment>
+ <comment xml:lang="lt">RealText dokumentas</comment>
+ <comment xml:lang="ko">RealText 문서</comment>
+ <comment xml:lang="kk">RealText құжаты</comment>
+ <comment xml:lang="ja">RealText ドキュメント</comment>
+ <comment xml:lang="it">Documento RealText</comment>
+ <comment xml:lang="is">RealText skjal</comment>
+ <comment xml:lang="id">Dokumen RealText</comment>
+ <comment xml:lang="ia">Documento RealText</comment>
+ <comment xml:lang="hu">RealText dokumentum</comment>
+ <comment xml:lang="hr">RealText dokument</comment>
+ <comment xml:lang="he">מסמך של RealText</comment>
+ <comment xml:lang="gl">documento RealText</comment>
+ <comment xml:lang="ga">cáipéis RealText</comment>
+ <comment xml:lang="fur">document RealText</comment>
+ <comment xml:lang="fr">document RealText</comment>
+ <comment xml:lang="fo">RealText skjal</comment>
+ <comment xml:lang="fi">RealText-asiakirja</comment>
+ <comment xml:lang="eu">RealText dokumentua</comment>
+ <comment xml:lang="es">documento RealText</comment>
+ <comment xml:lang="eo">RealText-dokumento</comment>
+ <comment xml:lang="en_GB">RealText document</comment>
+ <comment xml:lang="el">Έγγραφο RealText</comment>
+ <comment xml:lang="de">RealText-Dokument</comment>
+ <comment xml:lang="da">RealText-dokument</comment>
+ <comment xml:lang="cs">dokument RealText</comment>
+ <comment xml:lang="ca">document RealText</comment>
+ <comment xml:lang="bg">Документ — RealText</comment>
+ <comment xml:lang="be@latin">Dakument RealText</comment>
+ <comment xml:lang="be">дакумент RealText</comment>
+ <comment xml:lang="ast">Documentu RealText</comment>
+ <comment xml:lang="ar">مستند RealText</comment>
+ <comment xml:lang="af">RealText-dokument</comment>
+ <sub-class-of type="text/plain"/>
<glob pattern="*.rt"/>
</mime-type>
<mime-type type="audio/x-riff">
<comment>RIFF audio</comment>
- <comment xml:lang="ar">RIFF سمعي</comment>
- <comment xml:lang="az">RIFF audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo RIFF</comment>
- <comment xml:lang="bg">Аудио — RIFF</comment>
- <comment xml:lang="ca">àudio RIFF</comment>
- <comment xml:lang="cs">zvuk RIFF</comment>
- <comment xml:lang="cy">Sain RIFF</comment>
- <comment xml:lang="da">RIFF-lyd</comment>
- <comment xml:lang="de">RIFF-Audio</comment>
- <comment xml:lang="el">Ήχος RIFF</comment>
- <comment xml:lang="en_GB">RIFF audio</comment>
- <comment xml:lang="eo">RIFF-sondosiero</comment>
- <comment xml:lang="es">sonido RIFF</comment>
- <comment xml:lang="eu">RIFF audioa</comment>
- <comment xml:lang="fi">RIFF-ääni</comment>
- <comment xml:lang="fo">RIFF ljóð</comment>
- <comment xml:lang="fr">audio RIFF</comment>
- <comment xml:lang="ga">fuaim RIFF</comment>
- <comment xml:lang="gl">son RIFF</comment>
- <comment xml:lang="he">שמע RIFF</comment>
- <comment xml:lang="hr">RIFF zvučni zapis</comment>
- <comment xml:lang="hu">RIFF-kép</comment>
- <comment xml:lang="ia">Audio RIFF</comment>
- <comment xml:lang="id">Audio RIFF</comment>
- <comment xml:lang="it">Audio RIFF</comment>
- <comment xml:lang="ja">RIFF オーディオ</comment>
- <comment xml:lang="kk">RIFF аудиосы</comment>
- <comment xml:lang="ko">RIFF 오디오</comment>
- <comment xml:lang="lt">RIFF garso įrašas</comment>
- <comment xml:lang="lv">RIFF audio</comment>
- <comment xml:lang="ms">Audio RIFF</comment>
- <comment xml:lang="nb">RIFF-lyd</comment>
- <comment xml:lang="nl">RIFF-audio</comment>
- <comment xml:lang="nn">RIFF-lyd</comment>
- <comment xml:lang="oc">àudio RIFF</comment>
- <comment xml:lang="pl">Plik dźwiękowy RIFF</comment>
- <comment xml:lang="pt">áudio RIFF</comment>
- <comment xml:lang="pt_BR">Áudio RIFF</comment>
- <comment xml:lang="ro">Audio RIFF</comment>
- <comment xml:lang="ru">Аудио RIFF</comment>
- <comment xml:lang="sk">Zvuk RIFF</comment>
- <comment xml:lang="sl">Zvočna datoteka RIFF</comment>
- <comment xml:lang="sq">Audio RIFF</comment>
- <comment xml:lang="sr">РИФФ звук</comment>
- <comment xml:lang="sv">RIFF-ljud</comment>
- <comment xml:lang="tr">RIFF sesi</comment>
- <comment xml:lang="uk">звук RIFF</comment>
- <comment xml:lang="vi">Âm thanh RIFF</comment>
- <comment xml:lang="zh_CN">RIFF 音频</comment>
<comment xml:lang="zh_TW">RIFF 音訊</comment>
+ <comment xml:lang="zh_CN">RIFF 音频</comment>
+ <comment xml:lang="vi">Âm thanh RIFF</comment>
+ <comment xml:lang="uk">звук RIFF</comment>
+ <comment xml:lang="tr">RIFF sesi</comment>
+ <comment xml:lang="sv">RIFF-ljud</comment>
+ <comment xml:lang="sr">РИФФ звук</comment>
+ <comment xml:lang="sq">audio RIFF</comment>
+ <comment xml:lang="sl">Zvočna datoteka RIFF</comment>
+ <comment xml:lang="si">RIFF ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk RIFF</comment>
+ <comment xml:lang="ru">Аудио RIFF</comment>
+ <comment xml:lang="ro">Audio RIFF</comment>
+ <comment xml:lang="pt_BR">Áudio RIFF</comment>
+ <comment xml:lang="pt">áudio RIFF</comment>
+ <comment xml:lang="pl">Plik dźwiękowy RIFF</comment>
+ <comment xml:lang="oc">àudio RIFF</comment>
+ <comment xml:lang="nn">RIFF-lyd</comment>
+ <comment xml:lang="nl">RIFF-audio</comment>
+ <comment xml:lang="nb">RIFF-lyd</comment>
+ <comment xml:lang="ms">Audio RIFF</comment>
+ <comment xml:lang="lv">RIFF audio</comment>
+ <comment xml:lang="lt">RIFF garso įrašas</comment>
+ <comment xml:lang="ko">RIFF 오디오</comment>
+ <comment xml:lang="kk">RIFF аудиосы</comment>
+ <comment xml:lang="ja">RIFF オーディオ</comment>
+ <comment xml:lang="it">Audio RIFF</comment>
+ <comment xml:lang="is">RIFF hljóðskrá</comment>
+ <comment xml:lang="id">Audio RIFF</comment>
+ <comment xml:lang="ia">Audio RIFF</comment>
+ <comment xml:lang="hu">RIFF-kép</comment>
+ <comment xml:lang="hr">RIFF zvučni zapis</comment>
+ <comment xml:lang="he">שמע RIFF</comment>
+ <comment xml:lang="gl">son RIFF</comment>
+ <comment xml:lang="ga">fuaim RIFF</comment>
+ <comment xml:lang="fur">audio RIFF</comment>
+ <comment xml:lang="fr">audio RIFF</comment>
+ <comment xml:lang="fo">RIFF ljóð</comment>
+ <comment xml:lang="fi">RIFF-ääni</comment>
+ <comment xml:lang="eu">RIFF audioa</comment>
+ <comment xml:lang="es">sonido RIFF</comment>
+ <comment xml:lang="eo">RIFF-sondosiero</comment>
+ <comment xml:lang="en_GB">RIFF audio</comment>
+ <comment xml:lang="el">Ήχος RIFF</comment>
+ <comment xml:lang="de">RIFF-Audio</comment>
+ <comment xml:lang="da">RIFF-lyd</comment>
+ <comment xml:lang="cy">Sain RIFF</comment>
+ <comment xml:lang="cs">zvuk RIFF</comment>
+ <comment xml:lang="ca">àudio RIFF</comment>
+ <comment xml:lang="bg">Аудио — RIFF</comment>
+ <comment xml:lang="be@latin">Aŭdyjo RIFF</comment>
+ <comment xml:lang="be">аўдыя RIFF</comment>
+ <comment xml:lang="az">RIFF audio faylı</comment>
+ <comment xml:lang="ar">صوت RIFF</comment>
+ <comment xml:lang="af">RIFF-oudio</comment>
</mime-type>
<mime-type type="application/x-riff">
<comment>RIFF container</comment>
- <comment xml:lang="ca">contenidor RIFF</comment>
- <comment xml:lang="cs">kontejner RIFF</comment>
- <comment xml:lang="da">RIFF-container</comment>
- <comment xml:lang="de">RIFF-Container</comment>
- <comment xml:lang="el">Περιέκτης RIFF</comment>
- <comment xml:lang="en_GB">RIFF container</comment>
- <comment xml:lang="es">contenedor RIFF</comment>
- <comment xml:lang="eu">RIFF edukitzailea</comment>
- <comment xml:lang="fr">conteneur RIFF</comment>
- <comment xml:lang="ga">coimeádán RIFF</comment>
- <comment xml:lang="gl">Contenedor RIFF</comment>
- <comment xml:lang="he">מכולת RIFF</comment>
- <comment xml:lang="hr">RIFF spremnik</comment>
- <comment xml:lang="hu">RIFF konténer</comment>
- <comment xml:lang="ia">Receptaculo RIFF</comment>
- <comment xml:lang="id">Wadah RIFF</comment>
- <comment xml:lang="it">Container RIFF</comment>
- <comment xml:lang="kk">RIFF контейнері</comment>
- <comment xml:lang="ko">RIFF 컨테이너</comment>
- <comment xml:lang="oc">contenidor RIFF</comment>
- <comment xml:lang="pl">Kontener RIFF</comment>
- <comment xml:lang="pt">contentor RIFF</comment>
- <comment xml:lang="pt_BR">Contêiner RIFF</comment>
- <comment xml:lang="ru">Контейнер RIFF</comment>
- <comment xml:lang="sk">Kontajner RIFF</comment>
- <comment xml:lang="sl">Vsebnik RIFF</comment>
- <comment xml:lang="sr">РИФФ садржалац</comment>
- <comment xml:lang="sv">RIFF-behållare</comment>
- <comment xml:lang="tr">RIFF deposu</comment>
- <comment xml:lang="uk">контейнер RIFF</comment>
- <comment xml:lang="zh_CN">RIFF 容器</comment>
<comment xml:lang="zh_TW">RIFF 容器</comment>
-
+ <comment xml:lang="zh_CN">RIFF 容器</comment>
+ <comment xml:lang="uk">контейнер RIFF</comment>
+ <comment xml:lang="tr">RIFF deposu</comment>
+ <comment xml:lang="sv">RIFF-behållare</comment>
+ <comment xml:lang="sr">РИФФ садржалац</comment>
+ <comment xml:lang="sq">kontejner RIFF</comment>
+ <comment xml:lang="sl">Vsebnik RIFF</comment>
+ <comment xml:lang="si">RIFF කන්ටේනරය</comment>
+ <comment xml:lang="sk">Kontajner RIFF</comment>
+ <comment xml:lang="ru">Контейнер RIFF</comment>
+ <comment xml:lang="pt_BR">Contêiner RIFF</comment>
+ <comment xml:lang="pt">contentor RIFF</comment>
+ <comment xml:lang="pl">Kontener RIFF</comment>
+ <comment xml:lang="oc">contenidor RIFF</comment>
+ <comment xml:lang="nl">RIFF-container</comment>
+ <comment xml:lang="lt">RIFF konteineris</comment>
+ <comment xml:lang="ko">RIFF 컨테이너</comment>
+ <comment xml:lang="kk">RIFF контейнері</comment>
+ <comment xml:lang="ja">RIFF コンテナ</comment>
+ <comment xml:lang="it">Container RIFF</comment>
+ <comment xml:lang="is">RIFF gagnagámur</comment>
+ <comment xml:lang="id">Wadah RIFF</comment>
+ <comment xml:lang="ia">Receptaculo RIFF</comment>
+ <comment xml:lang="hu">RIFF konténer</comment>
+ <comment xml:lang="hr">RIFF spremnik</comment>
+ <comment xml:lang="he">מכולת RIFF</comment>
+ <comment xml:lang="gl">Contenedor RIFF</comment>
+ <comment xml:lang="ga">coimeádán RIFF</comment>
+ <comment xml:lang="fur">contignidôr RIFF</comment>
+ <comment xml:lang="fr">conteneur RIFF</comment>
+ <comment xml:lang="fi">RIFF-kontti</comment>
+ <comment xml:lang="eu">RIFF edukitzailea</comment>
+ <comment xml:lang="es">contenedor RIFF</comment>
+ <comment xml:lang="en_GB">RIFF container</comment>
+ <comment xml:lang="el">Περιέκτης RIFF</comment>
+ <comment xml:lang="de">RIFF-Container</comment>
+ <comment xml:lang="da">RIFF-container</comment>
+ <comment xml:lang="cs">kontejner RIFF</comment>
+ <comment xml:lang="ca">contenidor RIFF</comment>
+ <comment xml:lang="bg">Контейнер — RIFF</comment>
+ <comment xml:lang="be">кантэйнер RIFF</comment>
+ <comment xml:lang="ar">حاوية RIFF</comment>
+ <comment xml:lang="af">RIFF-houer</comment>
+ <!-- need to be lower prio than avi -->
<magic priority="45">
- <match value="RIFF" type="string" offset="0"/>
+ <match type="string" value="RIFF" offset="0"/>
</magic>
</mime-type>
<mime-type type="audio/x-s3m">
<comment>Scream Tracker 3 audio</comment>
- <comment xml:lang="ar">Scream Tracker 3 سمعي</comment>
- <comment xml:lang="az">Scream Tracker 3 audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo Scream Tracker 3</comment>
- <comment xml:lang="bg">Аудио — Scream Tracker 3</comment>
- <comment xml:lang="ca">àudio de Scream Tracker 3</comment>
- <comment xml:lang="cs">skladba Scream Tracker 3</comment>
- <comment xml:lang="cy">Sain Scream Tracker 3</comment>
- <comment xml:lang="da">Scream Tracker 3-lyd</comment>
- <comment xml:lang="de">Scream-Tracker-3-Audio</comment>
- <comment xml:lang="el">Ήχος Scream Tracker 3</comment>
- <comment xml:lang="en_GB">Scream Tracker 3 audio</comment>
- <comment xml:lang="eo">Sondosiero de Scream Tracker 3</comment>
- <comment xml:lang="es">sonido Scream Tracker 3</comment>
- <comment xml:lang="eu">Scream Tracker 3 audioa</comment>
- <comment xml:lang="fi">Scream Tracker 3 -ääni</comment>
- <comment xml:lang="fo">Scream Tracker 3 ljóður</comment>
- <comment xml:lang="fr">audio Scream Tracker 3</comment>
- <comment xml:lang="ga">fuaim Scream Tracker 3</comment>
- <comment xml:lang="gl">son Scream Tracker 3</comment>
- <comment xml:lang="he">שמע של Scream Tracker 3</comment>
- <comment xml:lang="hr">Scream Tracker 3 zvučni zapis</comment>
- <comment xml:lang="hu">Scream Tracker 3 hang</comment>
- <comment xml:lang="ia">Audio Scream Tracker 3</comment>
- <comment xml:lang="id">Audio Scream Tracker 3</comment>
- <comment xml:lang="it">Audio Scream Tracker 3</comment>
- <comment xml:lang="ja">Scream Tracker 3 オーディオ</comment>
- <comment xml:lang="kk">Scream Tracker 3 аудиосы</comment>
- <comment xml:lang="ko">Scream Tracker 3 오디오</comment>
- <comment xml:lang="lt">Scream Tracker 3 garso įrašas</comment>
- <comment xml:lang="lv">Scream Tracker 3 audio</comment>
- <comment xml:lang="ms">Audio Scream Tracker 3</comment>
- <comment xml:lang="nb">Scream Tracker 3-lyd</comment>
- <comment xml:lang="nl">Scream Tracker 3-audio</comment>
- <comment xml:lang="nn">Sream Tracker 3 lyd</comment>
- <comment xml:lang="oc">àudio Scream Tracker 3</comment>
- <comment xml:lang="pl">Plik dźwiękowy Scream Tracker 3</comment>
- <comment xml:lang="pt">áudio Scream Tracker 3</comment>
- <comment xml:lang="pt_BR">Áudio Scream Tracker 3</comment>
- <comment xml:lang="ro">Audio Scream Tracker 3</comment>
- <comment xml:lang="ru">Аудио Scream Tracker 3</comment>
- <comment xml:lang="sk">Skladba Scream Tracker 3</comment>
- <comment xml:lang="sl">Zvočna datoteka Scream Tracker 3</comment>
- <comment xml:lang="sq">Audio Scream Tracker 3</comment>
- <comment xml:lang="sr">звук Скрим Тракера 3</comment>
- <comment xml:lang="sv">Scream Tracker 3-ljud</comment>
- <comment xml:lang="tr">Scream Tracker 3 sesi</comment>
- <comment xml:lang="uk">звук Scream Tracker 3</comment>
- <comment xml:lang="vi">Âm thanh Scream Tracker 3</comment>
- <comment xml:lang="zh_CN">Scheme Tracker 3 音频</comment>
<comment xml:lang="zh_TW">Scream Tracker 3 音訊</comment>
- <magic priority="50">
+ <comment xml:lang="zh_CN">Scheme Tracker 3 音频</comment>
+ <comment xml:lang="vi">Âm thanh Scream Tracker 3</comment>
+ <comment xml:lang="uk">звук Scream Tracker 3</comment>
+ <comment xml:lang="tr">Scream Tracker 3 sesi</comment>
+ <comment xml:lang="sv">Scream Tracker 3-ljud</comment>
+ <comment xml:lang="sr">звук Скрим Тракера 3</comment>
+ <comment xml:lang="sq">audio Scream Tracker 3</comment>
+ <comment xml:lang="sl">Zvočna datoteka Scream Tracker 3</comment>
+ <comment xml:lang="si">Scream Tracker 3 ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Skladba Scream Tracker 3</comment>
+ <comment xml:lang="ru">Аудио Scream Tracker 3</comment>
+ <comment xml:lang="ro">Audio Scream Tracker 3</comment>
+ <comment xml:lang="pt_BR">Áudio Scream Tracker 3</comment>
+ <comment xml:lang="pt">áudio Scream Tracker 3</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Scream Tracker 3</comment>
+ <comment xml:lang="oc">àudio Scream Tracker 3</comment>
+ <comment xml:lang="nn">Sream Tracker 3 lyd</comment>
+ <comment xml:lang="nl">Scream Tracker 3-audio</comment>
+ <comment xml:lang="nb">Scream Tracker 3-lyd</comment>
+ <comment xml:lang="ms">Audio Scream Tracker 3</comment>
+ <comment xml:lang="lv">Scream Tracker 3 audio</comment>
+ <comment xml:lang="lt">Scream Tracker 3 garso įrašas</comment>
+ <comment xml:lang="ko">Scream Tracker 3 오디오</comment>
+ <comment xml:lang="kk">Scream Tracker 3 аудиосы</comment>
+ <comment xml:lang="ja">Scream Tracker 3 オーディオ</comment>
+ <comment xml:lang="it">Audio Scream Tracker 3</comment>
+ <comment xml:lang="is">Scream Tracker 3 hljóðskrá</comment>
+ <comment xml:lang="id">Audio Scream Tracker 3</comment>
+ <comment xml:lang="ia">Audio Scream Tracker 3</comment>
+ <comment xml:lang="hu">Scream Tracker 3 hang</comment>
+ <comment xml:lang="hr">Scream Tracker 3 zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Scream Tracker 3</comment>
+ <comment xml:lang="gl">son Scream Tracker 3</comment>
+ <comment xml:lang="ga">fuaim Scream Tracker 3</comment>
+ <comment xml:lang="fur">audio Scream Tracker 3</comment>
+ <comment xml:lang="fr">audio Scream Tracker 3</comment>
+ <comment xml:lang="fo">Scream Tracker 3 ljóður</comment>
+ <comment xml:lang="fi">Scream Tracker 3 -ääni</comment>
+ <comment xml:lang="eu">Scream Tracker 3 audioa</comment>
+ <comment xml:lang="es">sonido Scream Tracker 3</comment>
+ <comment xml:lang="eo">Sondosiero de Scream Tracker 3</comment>
+ <comment xml:lang="en_GB">Scream Tracker 3 audio</comment>
+ <comment xml:lang="el">Ήχος Scream Tracker 3</comment>
+ <comment xml:lang="de">Scream-Tracker-3-Audio</comment>
+ <comment xml:lang="da">Scream Tracker 3-lyd</comment>
+ <comment xml:lang="cy">Sain Scream Tracker 3</comment>
+ <comment xml:lang="cs">skladba Scream Tracker 3</comment>
+ <comment xml:lang="ca">àudio de Scream Tracker 3</comment>
+ <comment xml:lang="bg">Аудио — Scream Tracker 3</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Scream Tracker 3</comment>
+ <comment xml:lang="be">аўдыя Scream Tracker 3</comment>
+ <comment xml:lang="az">Scream Tracker 3 audio faylı</comment>
+ <comment xml:lang="ar">صوت Scream Tracker 3</comment>
+ <magic>
<match value="SCRM" type="string" offset="44"/>
</magic>
<glob pattern="*.s3m"/>
</mime-type>
<mime-type type="audio/x-scpls">
<comment>MP3 ShoutCast playlist</comment>
- <comment xml:lang="ar">قائمة تشغيل MP3 ShoutCast</comment>
- <comment xml:lang="be@latin">Śpis piesień dla tranślacyi MP3</comment>
- <comment xml:lang="bg">Списък за изпълнение — MP3 ShoutCast</comment>
- <comment xml:lang="ca">llista de reproducció MP3 ShoutCast</comment>
- <comment xml:lang="cs">seznam k přehrání MP3 ShoutCast</comment>
- <comment xml:lang="da">MP3 ShoutCast-afspilningsliste</comment>
- <comment xml:lang="de">MP3-ShoutCast-Wiedergabeliste</comment>
- <comment xml:lang="el">Λίστα αναπαραγωγής MP3 ShoutCast</comment>
- <comment xml:lang="en_GB">MP3 ShoutCast playlist</comment>
- <comment xml:lang="eo">MP3-ludlisto de ShoutCast</comment>
- <comment xml:lang="es">lista de reproducción MP3 ShoutCast</comment>
- <comment xml:lang="eu">MP3 ShoutCast erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">MP3 ShoutCast -soittolista</comment>
- <comment xml:lang="fo">MP3 ShoutCast avspælingarlisti</comment>
- <comment xml:lang="fr">liste de lecture MP3 ShoutCast</comment>
- <comment xml:lang="ga">seinmliosta MP3 ShoutCast</comment>
- <comment xml:lang="gl">lista de reprodución MP3 de ShoutCast</comment>
- <comment xml:lang="he">רשימת השמעה MP3 של ShoutCast</comment>
- <comment xml:lang="hr">MP3 ShoutCast popis izvođenja</comment>
- <comment xml:lang="hu">MP3 ShoutCast-lejátszólista</comment>
- <comment xml:lang="ia">Lista de selection MP3 ShoutCast</comment>
- <comment xml:lang="id">Senarai putar MP3 ShoutCast</comment>
- <comment xml:lang="it">Playlist MP3 ShoutCast</comment>
- <comment xml:lang="ja">MP3 ShoutCast 再生リスト</comment>
- <comment xml:lang="kk">MP3 ShoutCast ойнау тізімі</comment>
- <comment xml:lang="ko">MP3 ShoutCast 재생 목록</comment>
- <comment xml:lang="lt">MP3 ShoutCast grojaraštis</comment>
- <comment xml:lang="lv">MP3 ShoutCast repertuārs</comment>
- <comment xml:lang="ms">Senaraimain ShoutCast MP3</comment>
- <comment xml:lang="nb">MP3 ShoutCast-spilleliste</comment>
- <comment xml:lang="nl">MP3 ShoutCast-afspeellijst</comment>
- <comment xml:lang="nn">MP3 ShoutCast-speleliste</comment>
- <comment xml:lang="oc">lista de lectura MP3 ShoutCast</comment>
- <comment xml:lang="pl">Lista odtwarzania MP3 ShoutCast</comment>
- <comment xml:lang="pt">lista de reprodução MP3 ShoutCast</comment>
- <comment xml:lang="pt_BR">Lista de reprodução MP3 ShoutCast</comment>
- <comment xml:lang="ro">Listă MP3 ShoutCast</comment>
- <comment xml:lang="ru">Список воспроизведения MP3 ShoutCast</comment>
- <comment xml:lang="sk">Zoznam skladieb MP3 ShoutCast</comment>
- <comment xml:lang="sl">Seznam predvajanja MP3 ShoutCast</comment>
- <comment xml:lang="sq">Listë titujsh MP3 ShoutCast</comment>
- <comment xml:lang="sr">списак МП3 песама Шаут Каста</comment>
- <comment xml:lang="sv">MP3 ShoutCast-spellista</comment>
- <comment xml:lang="tr">MP3 ShoutCast çalma listesi</comment>
- <comment xml:lang="uk">список програвання MP3 ShoutCast</comment>
- <comment xml:lang="vi">Danh mục nhạc MP3 ShoutCast</comment>
- <comment xml:lang="zh_CN">MP3 ShoutCast 播放列表</comment>
<comment xml:lang="zh_TW">MP3 ShoutCast 播放清單</comment>
+ <comment xml:lang="zh_CN">MP3 ShoutCast 播放列表</comment>
+ <comment xml:lang="vi">Danh mục nhạc MP3 ShoutCast</comment>
+ <comment xml:lang="uk">список програвання MP3 ShoutCast</comment>
+ <comment xml:lang="tr">MP3 ShoutCast çalma listesi</comment>
+ <comment xml:lang="sv">MP3 ShoutCast-spellista</comment>
+ <comment xml:lang="sr">списак МП3 песама Шаут Каста</comment>
+ <comment xml:lang="sq">luajlistë MP3 ShoutCast</comment>
+ <comment xml:lang="sl">Seznam predvajanja MP3 ShoutCast</comment>
+ <comment xml:lang="si">MP3 ShoutCast ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="sk">Zoznam skladieb MP3 ShoutCast</comment>
+ <comment xml:lang="ru">Список воспроизведения MP3 ShoutCast</comment>
+ <comment xml:lang="ro">Listă MP3 ShoutCast</comment>
+ <comment xml:lang="pt_BR">Lista de reprodução MP3 ShoutCast</comment>
+ <comment xml:lang="pt">lista de reprodução MP3 ShoutCast</comment>
+ <comment xml:lang="pl">Lista odtwarzania MP3 ShoutCast</comment>
+ <comment xml:lang="oc">lista de lectura MP3 ShoutCast</comment>
+ <comment xml:lang="nn">MP3 ShoutCast-speleliste</comment>
+ <comment xml:lang="nl">MP3 ShoutCast-afspeellijst</comment>
+ <comment xml:lang="nb">MP3 ShoutCast-spilleliste</comment>
+ <comment xml:lang="ms">Senaraimain ShoutCast MP3</comment>
+ <comment xml:lang="lv">MP3 ShoutCast repertuārs</comment>
+ <comment xml:lang="lt">MP3 ShoutCast grojaraštis</comment>
+ <comment xml:lang="ko">MP3 ShoutCast 재생 목록</comment>
+ <comment xml:lang="kk">MP3 ShoutCast ойнау тізімі</comment>
+ <comment xml:lang="ka">MP3 ShoutCast დასაკრავი სია</comment>
+ <comment xml:lang="ja">MP3 ShoutCast プレイリスト</comment>
+ <comment xml:lang="it">Playlist MP3 ShoutCast</comment>
+ <comment xml:lang="is">MP3 ShoutCast spilunarlisti</comment>
+ <comment xml:lang="id">Senarai putar MP3 ShoutCast</comment>
+ <comment xml:lang="ia">Lista de selection MP3 ShoutCast</comment>
+ <comment xml:lang="hu">MP3 ShoutCast-lejátszólista</comment>
+ <comment xml:lang="hr">MP3 ShoutCast popis izvođenja</comment>
+ <comment xml:lang="he">רשימת השמעה MP3 של ShoutCast</comment>
+ <comment xml:lang="gl">lista de reprodución MP3 de ShoutCast</comment>
+ <comment xml:lang="ga">seinmliosta MP3 ShoutCast</comment>
+ <comment xml:lang="fur">liste di riproduzion MP3 ShoutCast</comment>
+ <comment xml:lang="fr">liste de lecture MP3 ShoutCast</comment>
+ <comment xml:lang="fo">MP3 ShoutCast avspælingarlisti</comment>
+ <comment xml:lang="fi">MP3 ShoutCast -soittolista</comment>
+ <comment xml:lang="eu">MP3 ShoutCast erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción MP3 ShoutCast</comment>
+ <comment xml:lang="eo">MP3-ludlisto de ShoutCast</comment>
+ <comment xml:lang="en_GB">MP3 ShoutCast playlist</comment>
+ <comment xml:lang="el">Λίστα αναπαραγωγής MP3 ShoutCast</comment>
+ <comment xml:lang="de">MP3-ShoutCast-Wiedergabeliste</comment>
+ <comment xml:lang="da">MP3 ShoutCast-afspilningsliste</comment>
+ <comment xml:lang="cs">seznam k přehrání MP3 ShoutCast</comment>
+ <comment xml:lang="ca">llista de reproducció MP3 ShoutCast</comment>
+ <comment xml:lang="bg">Списък за изпълнение — MP3 ShoutCast</comment>
+ <comment xml:lang="be@latin">Śpis piesień dla tranślacyi MP3</comment>
+ <comment xml:lang="be">плэй-ліст MP3 ShoutCast</comment>
+ <comment xml:lang="ar">قائمة تشغيل MP3 ShoutCast</comment>
<alias type="application/pls"/>
<alias type="audio/scpls"/>
- <magic priority="50">
- <match value="[playlist]" type="string" offset="0"/>
- <match value="[Playlist]" type="string" offset="0"/>
- <match value="[PLAYLIST]" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="[playlist]" offset="0"/>
+ <match type="string" value="[Playlist]" offset="0"/>
+ <match type="string" value="[PLAYLIST]" offset="0"/>
</magic>
<glob pattern="*.pls"/>
</mime-type>
<mime-type type="audio/x-stm">
<comment>Scream Tracker audio</comment>
- <comment xml:lang="ar">Scream Tracker سمعي</comment>
- <comment xml:lang="az">Scream Tracker audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo Scream Tracker</comment>
- <comment xml:lang="bg">Аудио — Scream Tracker</comment>
- <comment xml:lang="ca">àudio de Scream Tracker</comment>
- <comment xml:lang="cs">skladba Scream Tracker</comment>
- <comment xml:lang="cy">Sain Scream Tracker</comment>
- <comment xml:lang="da">Scream Tracker-lyd</comment>
- <comment xml:lang="de">Scream-Tracker-Audio</comment>
- <comment xml:lang="el">Ήχος Scream Tracker</comment>
- <comment xml:lang="en_GB">Scream Tracker audio</comment>
- <comment xml:lang="eo">Sondosiero de Scream Tracker</comment>
- <comment xml:lang="es">sonido Scream Tracker</comment>
- <comment xml:lang="eu">Scream Tracker audioa</comment>
- <comment xml:lang="fi">Scream Tracker -ääni</comment>
- <comment xml:lang="fo">Scream Tracker ljóður</comment>
- <comment xml:lang="fr">audio Scream Tracker</comment>
- <comment xml:lang="ga">fuaim Scream Tracker</comment>
- <comment xml:lang="gl">son Scream Tracker</comment>
- <comment xml:lang="he">שמע של Scream Tracker</comment>
- <comment xml:lang="hr">Scream Tracker zvučni zapis</comment>
- <comment xml:lang="hu">Scream Tracker hang</comment>
- <comment xml:lang="ia">Audio Scream Tracker</comment>
- <comment xml:lang="id">Audio Scream Tracker</comment>
- <comment xml:lang="it">Audio Scream Tracker</comment>
- <comment xml:lang="ja">Scream Tracker オーディオ</comment>
- <comment xml:lang="kk">Scream Tracker аудиосы</comment>
- <comment xml:lang="ko">Scream Tracker 오디오</comment>
- <comment xml:lang="lt">Scream Tracker garso įrašas</comment>
- <comment xml:lang="lv">Scream Tracker audio</comment>
- <comment xml:lang="ms">Audio Scream Tracker</comment>
- <comment xml:lang="nb">Scream Tracker-lyd</comment>
- <comment xml:lang="nl">Scream Tracker-audio</comment>
- <comment xml:lang="nn">Scream Tracker lyd</comment>
- <comment xml:lang="oc">àudio Scream Tracker</comment>
- <comment xml:lang="pl">Plik dźwiękowy Scream Tracker</comment>
- <comment xml:lang="pt">áudio Scream Tracker</comment>
- <comment xml:lang="pt_BR">Áudio Scream Tracker</comment>
- <comment xml:lang="ro">Audio Scream Tracker</comment>
- <comment xml:lang="ru">Аудио Scream Tracker</comment>
- <comment xml:lang="sk">Skladba Scream Tracker</comment>
- <comment xml:lang="sl">Zvočna datoteka Scream Tracker</comment>
- <comment xml:lang="sq">Audio Scream Tracker</comment>
- <comment xml:lang="sr">звук Скрим Тракера</comment>
- <comment xml:lang="sv">Scream Tracker-ljud</comment>
- <comment xml:lang="tr">Scream Tracker sesi</comment>
- <comment xml:lang="uk">звук Scream Tracker</comment>
- <comment xml:lang="vi">Âm thanh Scream Tracker</comment>
- <comment xml:lang="zh_CN">Scream Tracker 音频</comment>
<comment xml:lang="zh_TW">Scream Tracker 音訊</comment>
+ <comment xml:lang="zh_CN">Scream Tracker 音频</comment>
+ <comment xml:lang="vi">Âm thanh Scream Tracker</comment>
+ <comment xml:lang="uk">звук Scream Tracker</comment>
+ <comment xml:lang="tr">Scream Tracker sesi</comment>
+ <comment xml:lang="sv">Scream Tracker-ljud</comment>
+ <comment xml:lang="sr">звук Скрим Тракера</comment>
+ <comment xml:lang="sq">audio Scream Tracker</comment>
+ <comment xml:lang="sl">Zvočna datoteka Scream Tracker</comment>
+ <comment xml:lang="si">Scream Tracker ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Skladba Scream Tracker</comment>
+ <comment xml:lang="ru">Аудио Scream Tracker</comment>
+ <comment xml:lang="ro">Audio Scream Tracker</comment>
+ <comment xml:lang="pt_BR">Áudio Scream Tracker</comment>
+ <comment xml:lang="pt">áudio Scream Tracker</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Scream Tracker</comment>
+ <comment xml:lang="oc">àudio Scream Tracker</comment>
+ <comment xml:lang="nn">Scream Tracker lyd</comment>
+ <comment xml:lang="nl">Scream Tracker-audio</comment>
+ <comment xml:lang="nb">Scream Tracker-lyd</comment>
+ <comment xml:lang="ms">Audio Scream Tracker</comment>
+ <comment xml:lang="lv">Scream Tracker audio</comment>
+ <comment xml:lang="lt">Scream Tracker garso įrašas</comment>
+ <comment xml:lang="ko">Scream Tracker 오디오</comment>
+ <comment xml:lang="kk">Scream Tracker аудиосы</comment>
+ <comment xml:lang="ja">Scream Tracker オーディオ</comment>
+ <comment xml:lang="it">Audio Scream Tracker</comment>
+ <comment xml:lang="is">Scream Tracker hljóðskrá</comment>
+ <comment xml:lang="id">Audio Scream Tracker</comment>
+ <comment xml:lang="ia">Audio Scream Tracker</comment>
+ <comment xml:lang="hu">Scream Tracker hang</comment>
+ <comment xml:lang="hr">Scream Tracker zvučni zapis</comment>
+ <comment xml:lang="he">שמע של Scream Tracker</comment>
+ <comment xml:lang="gl">son Scream Tracker</comment>
+ <comment xml:lang="ga">fuaim Scream Tracker</comment>
+ <comment xml:lang="fur">audio Scream Tracker</comment>
+ <comment xml:lang="fr">audio Scream Tracker</comment>
+ <comment xml:lang="fo">Scream Tracker ljóður</comment>
+ <comment xml:lang="fi">Scream Tracker -ääni</comment>
+ <comment xml:lang="eu">Scream Tracker audioa</comment>
+ <comment xml:lang="es">sonido Scream Tracker</comment>
+ <comment xml:lang="eo">Sondosiero de Scream Tracker</comment>
+ <comment xml:lang="en_GB">Scream Tracker audio</comment>
+ <comment xml:lang="el">Ήχος Scream Tracker</comment>
+ <comment xml:lang="de">Scream-Tracker-Audio</comment>
+ <comment xml:lang="da">Scream Tracker-lyd</comment>
+ <comment xml:lang="cy">Sain Scream Tracker</comment>
+ <comment xml:lang="cs">skladba Scream Tracker</comment>
+ <comment xml:lang="ca">àudio de Scream Tracker</comment>
+ <comment xml:lang="bg">Аудио — Scream Tracker</comment>
+ <comment xml:lang="be@latin">Aŭdyjo Scream Tracker</comment>
+ <comment xml:lang="be">аўдыя Scream Tracker</comment>
+ <comment xml:lang="az">Scream Tracker audio faylı</comment>
+ <comment xml:lang="ar">صوت Scream Tracker</comment>
<magic>
- <match value="!Scream!\x1A" type="string" offset="20"/>
- <match value="!SCREAM!\x1A" type="string" offset="20"/>
- <match value="BMOD2STM\x1A" type="string" offset="20"/>
+ <match type="string" value="!Scream!\x1A" offset="20"/>
+ <match type="string" value="!SCREAM!\x1A" offset="20"/>
+ <match type="string" value="BMOD2STM\x1A" offset="20"/>
</magic>
<glob pattern="*.stm"/>
</mime-type>
<mime-type type="audio/x-voc">
<comment>VOC audio</comment>
- <comment xml:lang="ar">VOC سمعي</comment>
- <comment xml:lang="az">VOC audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo VOC</comment>
- <comment xml:lang="bg">Аудио — VOC</comment>
- <comment xml:lang="ca">àudio VOC</comment>
- <comment xml:lang="cs">zvuk VOC</comment>
- <comment xml:lang="cy">Sain VOC</comment>
- <comment xml:lang="da">VOC-lyd</comment>
- <comment xml:lang="de">VOC-Audio</comment>
- <comment xml:lang="el">Ήχος VOC</comment>
- <comment xml:lang="en_GB">VOC audio</comment>
- <comment xml:lang="eo">VOC-sondosiero</comment>
- <comment xml:lang="es">sonido VOC</comment>
- <comment xml:lang="eu">VOC audioa</comment>
- <comment xml:lang="fi">VOC-ääni</comment>
- <comment xml:lang="fo">VOC ljóður</comment>
- <comment xml:lang="fr">audio VOC</comment>
- <comment xml:lang="ga">fuaim VOC</comment>
- <comment xml:lang="gl">son VOC</comment>
- <comment xml:lang="he">שמע VOC</comment>
- <comment xml:lang="hr">VOC zvučni zapis</comment>
- <comment xml:lang="hu">VOC hang</comment>
- <comment xml:lang="ia">Audio VOC</comment>
- <comment xml:lang="id">Audio VOC</comment>
- <comment xml:lang="it">Audio VOC</comment>
- <comment xml:lang="ja">VOC オーディオ</comment>
- <comment xml:lang="kk">VOC аудиосы</comment>
- <comment xml:lang="ko">VOC 오디오</comment>
- <comment xml:lang="lt">VOC garso įrašas</comment>
- <comment xml:lang="lv">VOC audio</comment>
- <comment xml:lang="ms">Audio VOC</comment>
- <comment xml:lang="nb">VOC-lyd</comment>
- <comment xml:lang="nl">VOC-audio</comment>
- <comment xml:lang="nn">VOC-lyd</comment>
- <comment xml:lang="oc">àudio VOC</comment>
- <comment xml:lang="pl">Plik dźwiękowy VOC</comment>
- <comment xml:lang="pt">áudio VOC</comment>
- <comment xml:lang="pt_BR">Áudio VOC</comment>
- <comment xml:lang="ro">Audio VOC</comment>
- <comment xml:lang="ru">Аудио VOC</comment>
- <comment xml:lang="sk">Zvuk VOC</comment>
- <comment xml:lang="sl">Zvočna datoteka VOC</comment>
- <comment xml:lang="sq">Audio VOC</comment>
- <comment xml:lang="sr">ВОЦ звук</comment>
- <comment xml:lang="sv">VOC-ljud</comment>
- <comment xml:lang="tr">VOC sesi</comment>
- <comment xml:lang="uk">звук VOC</comment>
- <comment xml:lang="vi">Âm thanh VOC</comment>
- <comment xml:lang="zh_CN">VOC 音频</comment>
<comment xml:lang="zh_TW">VOC 音訊</comment>
+ <comment xml:lang="zh_CN">VOC 音频</comment>
+ <comment xml:lang="vi">Âm thanh VOC</comment>
+ <comment xml:lang="uk">звук VOC</comment>
+ <comment xml:lang="tr">VOC sesi</comment>
+ <comment xml:lang="sv">VOC-ljud</comment>
+ <comment xml:lang="sr">ВОЦ звук</comment>
+ <comment xml:lang="sq">audio VOC</comment>
+ <comment xml:lang="sl">Zvočna datoteka VOC</comment>
+ <comment xml:lang="si">VOC ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk VOC</comment>
+ <comment xml:lang="ru">Аудио VOC</comment>
+ <comment xml:lang="ro">Audio VOC</comment>
+ <comment xml:lang="pt_BR">Áudio VOC</comment>
+ <comment xml:lang="pt">áudio VOC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy VOC</comment>
+ <comment xml:lang="oc">àudio VOC</comment>
+ <comment xml:lang="nn">VOC-lyd</comment>
+ <comment xml:lang="nl">VOC-audio</comment>
+ <comment xml:lang="nb">VOC-lyd</comment>
+ <comment xml:lang="ms">Audio VOC</comment>
+ <comment xml:lang="lv">VOC audio</comment>
+ <comment xml:lang="lt">VOC garso įrašas</comment>
+ <comment xml:lang="ko">VOC 오디오</comment>
+ <comment xml:lang="kk">VOC аудиосы</comment>
+ <comment xml:lang="ja">VOC オーディオ</comment>
+ <comment xml:lang="it">Audio VOC</comment>
+ <comment xml:lang="is">VOC hljóðskrá</comment>
+ <comment xml:lang="id">Audio VOC</comment>
+ <comment xml:lang="ia">Audio VOC</comment>
+ <comment xml:lang="hu">VOC hang</comment>
+ <comment xml:lang="hr">VOC zvučni zapis</comment>
+ <comment xml:lang="he">שמע VOC</comment>
+ <comment xml:lang="gl">son VOC</comment>
+ <comment xml:lang="ga">fuaim VOC</comment>
+ <comment xml:lang="fur">audio VOC</comment>
+ <comment xml:lang="fr">audio VOC</comment>
+ <comment xml:lang="fo">VOC ljóður</comment>
+ <comment xml:lang="fi">VOC-ääni</comment>
+ <comment xml:lang="eu">VOC audioa</comment>
+ <comment xml:lang="es">sonido VOC</comment>
+ <comment xml:lang="eo">VOC-sondosiero</comment>
+ <comment xml:lang="en_GB">VOC audio</comment>
+ <comment xml:lang="el">Ήχος VOC</comment>
+ <comment xml:lang="de">VOC-Audio</comment>
+ <comment xml:lang="da">VOC-lyd</comment>
+ <comment xml:lang="cy">Sain VOC</comment>
+ <comment xml:lang="cs">zvuk VOC</comment>
+ <comment xml:lang="ca">àudio VOC</comment>
+ <comment xml:lang="bg">Аудио — VOC</comment>
+ <comment xml:lang="be@latin">Aŭdyjo VOC</comment>
+ <comment xml:lang="be">аўдыя VOC</comment>
+ <comment xml:lang="az">VOC audio faylı</comment>
+ <comment xml:lang="ar">صوت VOC</comment>
+ <comment xml:lang="af">VOC-oudio</comment>
<glob pattern="*.voc"/>
</mime-type>
- <mime-type type="audio/x-wav">
+ <mime-type type="audio/vnd.wave">
<comment>WAV audio</comment>
- <comment xml:lang="ar">WAV سمعي</comment>
- <comment xml:lang="az">WAV audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo WAV</comment>
- <comment xml:lang="bg">Аудио — WAV</comment>
- <comment xml:lang="ca">àudio WAV</comment>
- <comment xml:lang="cs">zvuk WAV</comment>
- <comment xml:lang="cy">Sain WAV</comment>
- <comment xml:lang="da">WAV-lyd</comment>
- <comment xml:lang="de">WAV-Audio</comment>
- <comment xml:lang="el">Ήχος WAV</comment>
- <comment xml:lang="en_GB">WAV audio</comment>
- <comment xml:lang="eo">WAV-sonkodo</comment>
- <comment xml:lang="es">sonido WAV</comment>
- <comment xml:lang="eu">WAV audioa</comment>
- <comment xml:lang="fi">WAV-ääni</comment>
- <comment xml:lang="fo">WAV ljóður</comment>
- <comment xml:lang="fr">audio WAV</comment>
- <comment xml:lang="ga">fuaim WAV</comment>
- <comment xml:lang="gl">son WAV</comment>
- <comment xml:lang="he">שמע WAV</comment>
- <comment xml:lang="hr">WAV zvučni zapis</comment>
- <comment xml:lang="hu">WAV hang</comment>
- <comment xml:lang="ia">Audio WAV</comment>
- <comment xml:lang="id">Audio WAV</comment>
- <comment xml:lang="it">Audio WAV</comment>
- <comment xml:lang="ja">WAV オーディオ</comment>
- <comment xml:lang="kk">WAV аудиосы</comment>
- <comment xml:lang="ko">WAV 오디오</comment>
- <comment xml:lang="lt">WAV garso įrašas</comment>
- <comment xml:lang="lv">WAV audio</comment>
- <comment xml:lang="ms">Audio VOC</comment>
- <comment xml:lang="nb">WAV-lyd</comment>
- <comment xml:lang="nl">WAV-audio</comment>
- <comment xml:lang="nn">WAV-lyd</comment>
- <comment xml:lang="oc">àudio WAV</comment>
- <comment xml:lang="pl">Plik dźwiękowy WAV</comment>
- <comment xml:lang="pt">áudio WAV</comment>
- <comment xml:lang="pt_BR">Áudio WAV</comment>
- <comment xml:lang="ro">Audio WAV</comment>
- <comment xml:lang="ru">Аудио WAV</comment>
- <comment xml:lang="sk">Zvuk WAV</comment>
- <comment xml:lang="sl">Zvočna datoteka WAV</comment>
- <comment xml:lang="sq">Audio WAV</comment>
- <comment xml:lang="sr">ВАВ звук</comment>
- <comment xml:lang="sv">WAV-ljud</comment>
- <comment xml:lang="tr">WAV sesi</comment>
- <comment xml:lang="uk">звук WAV</comment>
- <comment xml:lang="vi">Âm thanh WAV</comment>
- <comment xml:lang="zh_CN">WAV 音频</comment>
<comment xml:lang="zh_TW">WAV 音訊</comment>
+ <comment xml:lang="zh_CN">WAV 音频</comment>
+ <comment xml:lang="vi">Âm thanh WAV</comment>
+ <comment xml:lang="uk">звук WAV</comment>
+ <comment xml:lang="tr">WAV sesi</comment>
+ <comment xml:lang="sv">WAV-ljud</comment>
+ <comment xml:lang="sr">ВАВ звук</comment>
+ <comment xml:lang="sq">audio WAV</comment>
+ <comment xml:lang="sl">Zvočna datoteka WAV</comment>
+ <comment xml:lang="si">WAV ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk WAV</comment>
+ <comment xml:lang="ru">Аудио WAV</comment>
+ <comment xml:lang="ro">Audio WAV</comment>
+ <comment xml:lang="pt_BR">Áudio WAV</comment>
+ <comment xml:lang="pt">áudio WAV</comment>
+ <comment xml:lang="pl">Plik dźwiękowy WAV</comment>
+ <comment xml:lang="oc">àudio WAV</comment>
+ <comment xml:lang="nn">WAV-lyd</comment>
+ <comment xml:lang="nl">WAV-audio</comment>
+ <comment xml:lang="nb">WAV-lyd</comment>
+ <comment xml:lang="ms">Audio VOC</comment>
+ <comment xml:lang="lv">WAV audio</comment>
+ <comment xml:lang="lt">WAV garso įrašas</comment>
+ <comment xml:lang="ko">WAV 오디오</comment>
+ <comment xml:lang="kk">WAV аудиосы</comment>
+ <comment xml:lang="ja">WAV オーディオ</comment>
+ <comment xml:lang="it">Audio WAV</comment>
+ <comment xml:lang="is">WAV hljóðskrá</comment>
+ <comment xml:lang="id">Audio WAV</comment>
+ <comment xml:lang="ia">Audio WAV</comment>
+ <comment xml:lang="hu">WAV hang</comment>
+ <comment xml:lang="hr">WAV zvučni zapis</comment>
+ <comment xml:lang="he">שמע WAV</comment>
+ <comment xml:lang="gl">son WAV</comment>
+ <comment xml:lang="ga">fuaim WAV</comment>
+ <comment xml:lang="fur">audio WAV</comment>
+ <comment xml:lang="fr">audio WAV</comment>
+ <comment xml:lang="fo">WAV ljóður</comment>
+ <comment xml:lang="fi">WAV-ääni</comment>
+ <comment xml:lang="eu">WAV audioa</comment>
+ <comment xml:lang="es">sonido WAV</comment>
+ <comment xml:lang="eo">WAV-sonkodo</comment>
+ <comment xml:lang="en_GB">WAV audio</comment>
+ <comment xml:lang="el">Ήχος WAV</comment>
+ <comment xml:lang="de">WAV-Audio</comment>
+ <comment xml:lang="da">WAV-lyd</comment>
+ <comment xml:lang="cy">Sain WAV</comment>
+ <comment xml:lang="cs">zvuk WAV</comment>
+ <comment xml:lang="ca">àudio WAV</comment>
+ <comment xml:lang="bg">Аудио — WAV</comment>
+ <comment xml:lang="be@latin">Aŭdyjo WAV</comment>
+ <comment xml:lang="be">аўдыя WAV</comment>
+ <comment xml:lang="az">WAV audio faylı</comment>
+ <comment xml:lang="ar">صوت WAV</comment>
+ <comment xml:lang="af">WAV-oudio</comment>
<alias type="audio/wav"/>
- <alias type="audio/vnd.wave"/>
- <magic priority="50">
- <match value="WAVE" type="string" offset="8"/>
- <match value="WAV " type="string" offset="8"/>
+ <alias type="audio/x-wav"/>
+ <sub-class-of type="application/x-riff"/>
+ <magic>
+ <match type="string" value="WAVE" offset="8"/>
+ <match type="string" value="WAV " offset="8"/>
</magic>
<glob pattern="*.wav"/>
</mime-type>
<mime-type type="audio/x-xi">
- <comment>Scream Tracker instrument</comment>
- <comment xml:lang="ar">آلة Scream Tracker</comment>
- <comment xml:lang="az">Scream Tracker instrumenti</comment>
- <comment xml:lang="be@latin">Instrument Scream Tracker</comment>
- <comment xml:lang="bg">Инструмент — Scream Tracker</comment>
- <comment xml:lang="ca">instrument de Scream Tracker</comment>
- <comment xml:lang="cs">nástroj pro Scream Tracker</comment>
- <comment xml:lang="cy">Offeryn Scream Tracker</comment>
- <comment xml:lang="da">Scream Tracker-instrument</comment>
- <comment xml:lang="de">Scream-Tracker-Instrument</comment>
- <comment xml:lang="el">Μουσικό όργανο Scream Tracker</comment>
- <comment xml:lang="en_GB">Scream Tracker instrument</comment>
- <comment xml:lang="eo">instrumento de Scream Tracker</comment>
- <comment xml:lang="es">instrumento Scream Tracker</comment>
- <comment xml:lang="eu">Scream Tracker instrumentua</comment>
- <comment xml:lang="fi">Scream Tracker -soitin</comment>
- <comment xml:lang="fo">Scream Tracker ljóðføri</comment>
- <comment xml:lang="fr">instrument Scream Tracker</comment>
- <comment xml:lang="ga">ionstraim Scream Tracker</comment>
- <comment xml:lang="gl">Instrumento Scream Tracker</comment>
- <comment xml:lang="he">כלי של Scream Tracker</comment>
- <comment xml:lang="hr">Scream Tracker instrument</comment>
- <comment xml:lang="hu">Scream Tracker hangszer</comment>
- <comment xml:lang="ia">Instrumento Scream Tracker</comment>
- <comment xml:lang="id">Instrumen Scream Tracker</comment>
- <comment xml:lang="it">Strumento Scream Tracker</comment>
- <comment xml:lang="ja">Scream Tracker インストゥルメント</comment>
- <comment xml:lang="kk">Scream Tracker сайманы</comment>
- <comment xml:lang="ko">Scream Tracker 악기</comment>
- <comment xml:lang="lt">Scream Tracker instrumentas</comment>
- <comment xml:lang="lv">Scream Tracker instrumenti</comment>
- <comment xml:lang="ms">Instrumen Scream Tracker</comment>
- <comment xml:lang="nb">Scream Tracker-instrument</comment>
- <comment xml:lang="nl">Scream Tracker-instrument</comment>
- <comment xml:lang="nn">Scream Tracker instrument</comment>
- <comment xml:lang="oc">instrument Scream Tracker</comment>
- <comment xml:lang="pl">Instrument Scream Tracker</comment>
- <comment xml:lang="pt">instrumento Scream Tracker</comment>
- <comment xml:lang="pt_BR">Instrumento Scream Tracker</comment>
- <comment xml:lang="ro">Instrument Scream Tracker</comment>
- <comment xml:lang="ru">Инструмент Scream Tracker</comment>
- <comment xml:lang="sk">Nástroj pre Scream Tracker</comment>
- <comment xml:lang="sl">Datoteka zvoka glasbila Scream Tracker</comment>
- <comment xml:lang="sq">Instrument Scream Tracker</comment>
- <comment xml:lang="sr">инструмент Скрим Тракера</comment>
- <comment xml:lang="sv">Scream Tracker-instrument</comment>
- <comment xml:lang="tr">Scream Tracker çalgısı</comment>
- <comment xml:lang="uk">інструмент Scream Tracker</comment>
- <comment xml:lang="vi">Nhạc khí Scream Tracker</comment>
- <comment xml:lang="zh_CN">Scream Tracker 乐器</comment>
- <comment xml:lang="zh_TW">Scream Tracker 樂器檔</comment>
- <magic priority="50">
+ <comment>FastTracker II instrument</comment>
+ <comment xml:lang="uk">інструмент FastTracker II</comment>
+ <comment xml:lang="sv">FastTracker II-instrument</comment>
+ <comment xml:lang="ru">Инструмент FastTracker II</comment>
+ <comment xml:lang="pl">Instrument FastTracker II</comment>
+ <comment xml:lang="it">Strumento FastTracker II</comment>
+ <comment xml:lang="eu">FastTracker II tresna</comment>
+ <comment xml:lang="es">instrumento de FastTracker II</comment>
+ <comment xml:lang="de">FastTracker-II-Instrument</comment>
+ <comment xml:lang="be">інструмент FastTracker II</comment>
+ <magic>
<match value="Extended Instrument:" type="string" offset="0"/>
</magic>
<glob pattern="*.xi"/>
</mime-type>
<mime-type type="audio/x-xm">
<comment>FastTracker II audio</comment>
- <comment xml:lang="ar">FastTracker II سمعي</comment>
- <comment xml:lang="az">FastTracker II audio faylı</comment>
- <comment xml:lang="be@latin">Aŭdyjo FastTracker II</comment>
- <comment xml:lang="bg">Аудио — FastTracker II</comment>
- <comment xml:lang="ca">àudio de FastTracker II</comment>
- <comment xml:lang="cs">zvuk FastTracker II</comment>
- <comment xml:lang="cy">Sain FastTracker II</comment>
- <comment xml:lang="da">FastTracker II-lyd</comment>
- <comment xml:lang="de">FastTracker-II-Audio</comment>
- <comment xml:lang="el">Ήχος FastTracker II</comment>
- <comment xml:lang="en_GB">FastTracker II audio</comment>
- <comment xml:lang="eo">Sondosiero de FastTracker II</comment>
- <comment xml:lang="es">sonido FastTracker II</comment>
- <comment xml:lang="eu">FastTracker II.ren audioa</comment>
- <comment xml:lang="fi">FastTracker II -ääni</comment>
- <comment xml:lang="fo">FastTracker II ljóður</comment>
- <comment xml:lang="fr">audio FastTracker II</comment>
- <comment xml:lang="ga">fuaim FastTracker II</comment>
- <comment xml:lang="gl">son de FastTracker II</comment>
- <comment xml:lang="he">שמע FastTracker II</comment>
- <comment xml:lang="hr">FastTracker II zvučni zapis</comment>
- <comment xml:lang="hu">FastTracker II hang</comment>
- <comment xml:lang="ia">Audio FastTracker II</comment>
- <comment xml:lang="id">Audio FastTracker II</comment>
- <comment xml:lang="it">Audio FastTracker II</comment>
- <comment xml:lang="ja">FastTracker II オーディオ</comment>
- <comment xml:lang="ka">FastTracker II-ის აუდიო</comment>
- <comment xml:lang="kk">FastTracker II аудиосы</comment>
- <comment xml:lang="ko">FastTracker II 오디오</comment>
- <comment xml:lang="lt">FastTracker II garso įrašas</comment>
- <comment xml:lang="lv">FastTracker II audio</comment>
- <comment xml:lang="ms">Audio FastTracker II</comment>
- <comment xml:lang="nb">FastTracker II-lyd</comment>
- <comment xml:lang="nl">FastTracker II-audio</comment>
- <comment xml:lang="nn">FastTracker II lyd</comment>
- <comment xml:lang="oc">àudio FastTracker II</comment>
- <comment xml:lang="pl">Plik dźwiękowy FastTracker II</comment>
- <comment xml:lang="pt">áudio FastTracker II</comment>
- <comment xml:lang="pt_BR">Áudio FastTracker II</comment>
- <comment xml:lang="ro">Audio FastTracker II</comment>
- <comment xml:lang="ru">Аудио FastTracker II</comment>
- <comment xml:lang="sk">Zvuk FastTracker II</comment>
- <comment xml:lang="sl">Zvočna datoteka FastTracker II</comment>
- <comment xml:lang="sq">Audio FastTracker II</comment>
- <comment xml:lang="sr">звук Фаст Тракера ИИ</comment>
- <comment xml:lang="sv">FastTracker II-ljud</comment>
- <comment xml:lang="tr">FastTracker II sesi</comment>
- <comment xml:lang="uk">звук FastTracker II</comment>
- <comment xml:lang="vi">Âm thanh FastTracker II</comment>
- <comment xml:lang="zh_CN">FastTracker II 音频</comment>
<comment xml:lang="zh_TW">FastTracker II 音訊</comment>
- <magic priority="50">
+ <comment xml:lang="zh_CN">FastTracker II 音频</comment>
+ <comment xml:lang="vi">Âm thanh FastTracker II</comment>
+ <comment xml:lang="uk">звук FastTracker II</comment>
+ <comment xml:lang="tr">FastTracker II sesi</comment>
+ <comment xml:lang="sv">FastTracker II-ljud</comment>
+ <comment xml:lang="sr">звук Фаст Тракера ИИ</comment>
+ <comment xml:lang="sq">audio FastTracker II</comment>
+ <comment xml:lang="sl">Zvočna datoteka FastTracker II</comment>
+ <comment xml:lang="si">FastTracker II ශ්‍රව්‍ය</comment>
+ <comment xml:lang="sk">Zvuk FastTracker II</comment>
+ <comment xml:lang="ru">Аудио FastTracker II</comment>
+ <comment xml:lang="ro">Audio FastTracker II</comment>
+ <comment xml:lang="pt_BR">Áudio FastTracker II</comment>
+ <comment xml:lang="pt">áudio FastTracker II</comment>
+ <comment xml:lang="pl">Plik dźwiękowy FastTracker II</comment>
+ <comment xml:lang="oc">àudio FastTracker II</comment>
+ <comment xml:lang="nn">FastTracker II lyd</comment>
+ <comment xml:lang="nl">FastTracker II-audio</comment>
+ <comment xml:lang="nb">FastTracker II-lyd</comment>
+ <comment xml:lang="ms">Audio FastTracker II</comment>
+ <comment xml:lang="lv">FastTracker II audio</comment>
+ <comment xml:lang="lt">FastTracker II garso įrašas</comment>
+ <comment xml:lang="ko">FastTracker II 오디오</comment>
+ <comment xml:lang="kk">FastTracker II аудиосы</comment>
+ <comment xml:lang="ka">FastTracker II-ის აუდიო</comment>
+ <comment xml:lang="ja">FastTracker II オーディオ</comment>
+ <comment xml:lang="it">Audio FastTracker II</comment>
+ <comment xml:lang="is">FastTracker II hljóðskrá</comment>
+ <comment xml:lang="id">Audio FastTracker II</comment>
+ <comment xml:lang="ia">Audio FastTracker II</comment>
+ <comment xml:lang="hu">FastTracker II hang</comment>
+ <comment xml:lang="hr">FastTracker II zvučni zapis</comment>
+ <comment xml:lang="he">שמע FastTracker II</comment>
+ <comment xml:lang="gl">son de FastTracker II</comment>
+ <comment xml:lang="ga">fuaim FastTracker II</comment>
+ <comment xml:lang="fur">audio FastTracker II</comment>
+ <comment xml:lang="fr">audio FastTracker II</comment>
+ <comment xml:lang="fo">FastTracker II ljóður</comment>
+ <comment xml:lang="fi">FastTracker II -ääni</comment>
+ <comment xml:lang="eu">FastTracker II.ren audioa</comment>
+ <comment xml:lang="es">sonido FastTracker II</comment>
+ <comment xml:lang="eo">Sondosiero de FastTracker II</comment>
+ <comment xml:lang="en_GB">FastTracker II audio</comment>
+ <comment xml:lang="el">Ήχος FastTracker II</comment>
+ <comment xml:lang="de">FastTracker-II-Audio</comment>
+ <comment xml:lang="da">FastTracker II-lyd</comment>
+ <comment xml:lang="cy">Sain FastTracker II</comment>
+ <comment xml:lang="cs">zvuk FastTracker II</comment>
+ <comment xml:lang="ca">àudio de FastTracker II</comment>
+ <comment xml:lang="bg">Аудио — FastTracker II</comment>
+ <comment xml:lang="be@latin">Aŭdyjo FastTracker II</comment>
+ <comment xml:lang="be">аўдыя FastTracker II</comment>
+ <comment xml:lang="az">FastTracker II audio faylı</comment>
+ <comment xml:lang="ar">صوت FastTracker II</comment>
+ <magic>
<match value="Extended Module:" type="string" offset="0"/>
</magic>
<glob pattern="*.xm"/>
</mime-type>
<mime-type type="audio/x-tta">
<comment>TrueAudio audio</comment>
- <comment xml:lang="ar">TrueAudio سمعي</comment>
- <comment xml:lang="be@latin">Aŭdyjo TrueAudio</comment>
- <comment xml:lang="bg">Аудио — TrueAudio</comment>
- <comment xml:lang="ca">àudio de TrueAudio</comment>
- <comment xml:lang="cs">zvuk TrueAudio</comment>
- <comment xml:lang="da">TrueAudio-lyd</comment>
- <comment xml:lang="de">TrueAudio-Audio</comment>
- <comment xml:lang="el">Ήχος TrueAudio</comment>
- <comment xml:lang="en_GB">TrueAudio audio</comment>
- <comment xml:lang="eo">TrueAudio-sondosiero</comment>
- <comment xml:lang="es">sonido TrueAudio</comment>
- <comment xml:lang="eu">TrueAudio audioa</comment>
- <comment xml:lang="fi">TrueAudio-ääni</comment>
- <comment xml:lang="fo">TrueAudio ljóður</comment>
- <comment xml:lang="fr">audio TrueAudio</comment>
- <comment xml:lang="ga">fuaim TrueAudio</comment>
- <comment xml:lang="gl">son Trueson</comment>
- <comment xml:lang="he">שמע TrueAudio</comment>
- <comment xml:lang="hr">TrueAudio zvučni zapis</comment>
- <comment xml:lang="hu">TrueAudio hang</comment>
- <comment xml:lang="ia">Audio TrueAudio</comment>
- <comment xml:lang="id">Audio TrueAudio</comment>
- <comment xml:lang="it">Audio TrueAudio</comment>
- <comment xml:lang="ja">TrueAudio オーディオ</comment>
- <comment xml:lang="kk">TrueAudio аудиосы</comment>
- <comment xml:lang="ko">TrueAudio 오디오</comment>
- <comment xml:lang="lt">TrueAudio garso įrašas</comment>
- <comment xml:lang="lv">TrueAudio audio</comment>
- <comment xml:lang="nb">TrueAudio-lyd</comment>
- <comment xml:lang="nl">TrueAudio-audio</comment>
- <comment xml:lang="nn">TrueAudio-lyd</comment>
- <comment xml:lang="oc">àudio TrueAudio</comment>
- <comment xml:lang="pl">Plik dźwiękowy TrueAudio</comment>
- <comment xml:lang="pt">áudio TrueAudio</comment>
- <comment xml:lang="pt_BR">Áudio TrueAudio</comment>
- <comment xml:lang="ro">Audio TrueAudio</comment>
- <comment xml:lang="ru">Аудио TrueAudio</comment>
- <comment xml:lang="sk">Zvuk TrueAudio</comment>
- <comment xml:lang="sl">Zvočna datoteka TrueAudio</comment>
- <comment xml:lang="sq">Audio TrueAudio</comment>
- <comment xml:lang="sr">Тру Аудио звук</comment>
- <comment xml:lang="sv">TrueAudio-ljud</comment>
- <comment xml:lang="tr">TrueAudio sesi</comment>
- <comment xml:lang="uk">звук TrueAudio</comment>
- <comment xml:lang="vi">Âm thanh TrueAudio</comment>
- <comment xml:lang="zh_CN">TrueAudio 音频</comment>
<comment xml:lang="zh_TW">TrueAudio 音訊</comment>
+ <comment xml:lang="zh_CN">TrueAudio 音频</comment>
+ <comment xml:lang="vi">Âm thanh TrueAudio</comment>
+ <comment xml:lang="uk">звук TrueAudio</comment>
+ <comment xml:lang="tr">TrueAudio sesi</comment>
+ <comment xml:lang="sv">TrueAudio-ljud</comment>
+ <comment xml:lang="sr">Тру Аудио звук</comment>
+ <comment xml:lang="sq">audio TrueAudio</comment>
+ <comment xml:lang="sl">Zvočna datoteka TrueAudio</comment>
+ <comment xml:lang="si">TrueAudio ශ්රව්ය</comment>
+ <comment xml:lang="sk">Zvuk TrueAudio</comment>
+ <comment xml:lang="ru">Аудио TrueAudio</comment>
+ <comment xml:lang="ro">Audio TrueAudio</comment>
+ <comment xml:lang="pt_BR">Áudio TrueAudio</comment>
+ <comment xml:lang="pt">áudio TrueAudio</comment>
+ <comment xml:lang="pl">Plik dźwiękowy TrueAudio</comment>
+ <comment xml:lang="oc">àudio TrueAudio</comment>
+ <comment xml:lang="nn">TrueAudio-lyd</comment>
+ <comment xml:lang="nl">TrueAudio-audio</comment>
+ <comment xml:lang="nb">TrueAudio-lyd</comment>
+ <comment xml:lang="lv">TrueAudio audio</comment>
+ <comment xml:lang="lt">TrueAudio garso įrašas</comment>
+ <comment xml:lang="ko">TrueAudio 오디오</comment>
+ <comment xml:lang="kk">TrueAudio аудиосы</comment>
+ <comment xml:lang="ja">TrueAudio オーディオ</comment>
+ <comment xml:lang="it">Audio TrueAudio</comment>
+ <comment xml:lang="is">TrueAudio hljóðskrá</comment>
+ <comment xml:lang="id">Audio TrueAudio</comment>
+ <comment xml:lang="ia">Audio TrueAudio</comment>
+ <comment xml:lang="hu">TrueAudio hang</comment>
+ <comment xml:lang="hr">TrueAudio zvučni zapis</comment>
+ <comment xml:lang="he">שמע TrueAudio</comment>
+ <comment xml:lang="gl">son Trueson</comment>
+ <comment xml:lang="ga">fuaim TrueAudio</comment>
+ <comment xml:lang="fur">audio TrueAudio</comment>
+ <comment xml:lang="fr">audio TrueAudio</comment>
+ <comment xml:lang="fo">TrueAudio ljóður</comment>
+ <comment xml:lang="fi">TrueAudio-ääni</comment>
+ <comment xml:lang="eu">TrueAudio audioa</comment>
+ <comment xml:lang="es">sonido TrueAudio</comment>
+ <comment xml:lang="eo">TrueAudio-sondosiero</comment>
+ <comment xml:lang="en_GB">TrueAudio audio</comment>
+ <comment xml:lang="el">Ήχος TrueAudio</comment>
+ <comment xml:lang="de">TrueAudio-Audio</comment>
+ <comment xml:lang="da">TrueAudio-lyd</comment>
+ <comment xml:lang="cs">zvuk TrueAudio</comment>
+ <comment xml:lang="ca">àudio TrueAudio</comment>
+ <comment xml:lang="bg">Аудио — TrueAudio</comment>
+ <comment xml:lang="be@latin">Aŭdyjo TrueAudio</comment>
+ <comment xml:lang="be">аўдыя TrueAudio</comment>
+ <comment xml:lang="ar">صوت TrueAudio</comment>
+ <comment xml:lang="af">TrueAudio-oudio</comment>
<alias type="audio/tta"/>
- <magic priority="50">
+ <magic>
<match value="TTA1" type="string" offset="0"/>
</magic>
<glob pattern="*.tta"/>
</mime-type>
<mime-type type="image/bmp">
<comment>Windows BMP image</comment>
- <comment xml:lang="ar">صورة Windows BMP</comment>
- <comment xml:lang="az">Windows BMP rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava Windows BMP</comment>
- <comment xml:lang="bg">Изображение — Windows BMP</comment>
- <comment xml:lang="ca">imatge BMP de Windows</comment>
- <comment xml:lang="cs">obrázek Windows BMP</comment>
- <comment xml:lang="cy">Delwedd BMP Windows</comment>
- <comment xml:lang="da">Windows BMP-billede</comment>
- <comment xml:lang="de">Windows-BMP-Bild</comment>
- <comment xml:lang="el">Εικόνα Windows BMP</comment>
- <comment xml:lang="en_GB">Windows BMP image</comment>
- <comment xml:lang="eo">BMP-bildo de Vindozo</comment>
- <comment xml:lang="es">imagen BMP de Windows</comment>
- <comment xml:lang="eu">Windows BMP irudia</comment>
- <comment xml:lang="fi">Windows BMP -kuva</comment>
- <comment xml:lang="fo">Windows BMP mynd</comment>
- <comment xml:lang="fr">image Windows BMP</comment>
- <comment xml:lang="ga">íomhá BMP Windows</comment>
- <comment xml:lang="gl">imaxe BMP de Windows</comment>
- <comment xml:lang="he">תמונת BMP של Windows</comment>
- <comment xml:lang="hr">Windows BMP slika</comment>
- <comment xml:lang="hu">Windows BMP-kép</comment>
- <comment xml:lang="ia">Imagine BMP de Windows</comment>
- <comment xml:lang="id">Citra Windows BMP</comment>
- <comment xml:lang="it">Immagine Windows BMP</comment>
- <comment xml:lang="ja">Windows BMP 画像</comment>
- <comment xml:lang="kk">Windows BMP суреті</comment>
- <comment xml:lang="ko">Windows BMP 그림</comment>
- <comment xml:lang="lt">Windows BMP paveikslėlis</comment>
- <comment xml:lang="lv">Windows BMP attēls</comment>
- <comment xml:lang="ms">Imej BMP Windows</comment>
- <comment xml:lang="nb">Windows BMP-bilde</comment>
- <comment xml:lang="nl">Windows BMP-afbeelding</comment>
- <comment xml:lang="nn">Windows BMP-bilete</comment>
- <comment xml:lang="oc">imatge Windows BMP</comment>
- <comment xml:lang="pl">Obraz BMP Windows</comment>
- <comment xml:lang="pt">imagem BMP Windows</comment>
- <comment xml:lang="pt_BR">Imagem BMP do Windows</comment>
- <comment xml:lang="ro">Imagine Windows BMP</comment>
- <comment xml:lang="ru">Изображение Windows BMP</comment>
- <comment xml:lang="sk">Obrázok Windows BMP</comment>
- <comment xml:lang="sl">Slikovna datoteka Windows BMP</comment>
- <comment xml:lang="sq">Figurë Windows BMP</comment>
- <comment xml:lang="sr">Виндоузова БМП слика</comment>
- <comment xml:lang="sv">Windows BMP-bild</comment>
- <comment xml:lang="tr">Windows BMP görüntüsü</comment>
- <comment xml:lang="uk">зображення Windows BMP</comment>
- <comment xml:lang="vi">Ảnh BMP Windows</comment>
- <comment xml:lang="zh_CN">Windows BMP 图像</comment>
<comment xml:lang="zh_TW">Windows BMP 影像</comment>
- <magic priority="50">
- <match value="BMxxxx\000\000" type="string" offset="0" mask="0xffff00000000ffff"/>
- <match value="BM" type="string" offset="0">
- <match value="12" type="byte" offset="14"/>
- <match value="64" type="byte" offset="14"/>
- <match value="40" type="byte" offset="14"/>
+ <comment xml:lang="zh_CN">Windows BMP 图像</comment>
+ <comment xml:lang="vi">Ảnh BMP Windows</comment>
+ <comment xml:lang="uk">зображення Windows BMP</comment>
+ <comment xml:lang="tr">Windows BMP görüntüsü</comment>
+ <comment xml:lang="sv">Windows BMP-bild</comment>
+ <comment xml:lang="sr">Виндоузова БМП слика</comment>
+ <comment xml:lang="sq">figurë Windows BMP</comment>
+ <comment xml:lang="sl">Slikovna datoteka Windows BMP</comment>
+ <comment xml:lang="si">වින්ඩෝස් BMP රූපය</comment>
+ <comment xml:lang="sk">Obrázok Windows BMP</comment>
+ <comment xml:lang="ru">Изображение Windows BMP</comment>
+ <comment xml:lang="ro">Imagine Windows BMP</comment>
+ <comment xml:lang="pt_BR">Imagem BMP do Windows</comment>
+ <comment xml:lang="pt">imagem BMP Windows</comment>
+ <comment xml:lang="pl">Obraz BMP Windows</comment>
+ <comment xml:lang="oc">imatge Windows BMP</comment>
+ <comment xml:lang="nn">Windows BMP-bilete</comment>
+ <comment xml:lang="nl">Windows BMP-afbeelding</comment>
+ <comment xml:lang="nb">Windows BMP-bilde</comment>
+ <comment xml:lang="ms">Imej BMP Windows</comment>
+ <comment xml:lang="lv">Windows BMP attēls</comment>
+ <comment xml:lang="lt">Windows BMP paveikslėlis</comment>
+ <comment xml:lang="ko">Windows BMP 그림</comment>
+ <comment xml:lang="kk">Windows BMP суреті</comment>
+ <comment xml:lang="ja">Windows BMP 画像</comment>
+ <comment xml:lang="it">Immagine Windows BMP</comment>
+ <comment xml:lang="is">Windows BMP mynd</comment>
+ <comment xml:lang="id">Citra Windows BMP</comment>
+ <comment xml:lang="ia">Imagine BMP de Windows</comment>
+ <comment xml:lang="hu">Windows BMP-kép</comment>
+ <comment xml:lang="hr">Windows BMP slika</comment>
+ <comment xml:lang="he">תמונת BMP של Windows</comment>
+ <comment xml:lang="gl">imaxe BMP de Windows</comment>
+ <comment xml:lang="ga">íomhá BMP Windows</comment>
+ <comment xml:lang="fur">imagjin Windows BMP</comment>
+ <comment xml:lang="fr">image Windows BMP</comment>
+ <comment xml:lang="fo">Windows BMP mynd</comment>
+ <comment xml:lang="fi">Windows BMP -kuva</comment>
+ <comment xml:lang="eu">Windows BMP irudia</comment>
+ <comment xml:lang="es">imagen BMP de Windows</comment>
+ <comment xml:lang="eo">BMP-bildo de Vindozo</comment>
+ <comment xml:lang="en_GB">Windows BMP image</comment>
+ <comment xml:lang="el">Εικόνα Windows BMP</comment>
+ <comment xml:lang="de">Windows BMP-Bild</comment>
+ <comment xml:lang="da">Windows BMP-billede</comment>
+ <comment xml:lang="cy">Delwedd BMP Windows</comment>
+ <comment xml:lang="cs">obrázek Windows BMP</comment>
+ <comment xml:lang="ca">imatge BMP de Windows</comment>
+ <comment xml:lang="bg">Изображение — Windows BMP</comment>
+ <comment xml:lang="be@latin">Vyjava Windows BMP</comment>
+ <comment xml:lang="be">выява Windows BMP</comment>
+ <comment xml:lang="az">Windows BMP rəsmi</comment>
+ <comment xml:lang="ar">صورة Windows BMP</comment>
+ <comment xml:lang="af">Windows BMP-beeld</comment>
+ <magic>
+ <match type="string" mask="0xffff00000000ffff" value="BMxxxx\000\000" offset="0"/>
+ <match type="string" value="BM" offset="0">
+ <match type="byte" value="12" offset="14"/>
+ <match type="byte" value="64" offset="14"/>
+ <match type="byte" value="40" offset="14"/>
</match>
</magic>
<glob pattern="*.bmp"/>
@@ -25061,402 +27286,431 @@
</mime-type>
<mime-type type="image/vnd.wap.wbmp">
<comment>WBMP image</comment>
- <comment xml:lang="ar">صورة WBMP</comment>
- <comment xml:lang="be@latin">Vyjava WBMP</comment>
- <comment xml:lang="bg">Изображение — WBMP</comment>
- <comment xml:lang="ca">imatge WBMP</comment>
- <comment xml:lang="cs">obrázek WBMP</comment>
- <comment xml:lang="da">WBMP-billede</comment>
- <comment xml:lang="de">WBMP-Bild</comment>
- <comment xml:lang="el">Εικόνα WBMP</comment>
- <comment xml:lang="en_GB">WBMP image</comment>
- <comment xml:lang="eo">WBMP-bildo</comment>
- <comment xml:lang="es">imagen WBMP</comment>
- <comment xml:lang="eu">WBMP irudia</comment>
- <comment xml:lang="fi">WBMP-kuva</comment>
- <comment xml:lang="fo">WBMP mynd</comment>
- <comment xml:lang="fr">image WBMP</comment>
- <comment xml:lang="ga">íomhá WBMP</comment>
- <comment xml:lang="gl">imaxe WBMP</comment>
- <comment xml:lang="he">תמונת WBMP</comment>
- <comment xml:lang="hr">WBMP slika</comment>
- <comment xml:lang="hu">WBMP kép</comment>
- <comment xml:lang="ia">Imagine WBMP</comment>
- <comment xml:lang="id">Citra WBMP</comment>
- <comment xml:lang="it">Immagine WBMP</comment>
- <comment xml:lang="ja">WBMP 画像</comment>
- <comment xml:lang="kk">WBMP суреті</comment>
- <comment xml:lang="ko">WBMP 그림</comment>
- <comment xml:lang="lt">WBMP paveikslėlis</comment>
- <comment xml:lang="lv">WBMP attēls</comment>
- <comment xml:lang="nb">WBMP-bilde</comment>
- <comment xml:lang="nl">WBMP-afbeelding</comment>
- <comment xml:lang="nn">WBMP-bilete</comment>
- <comment xml:lang="oc">imatge WBMP</comment>
- <comment xml:lang="pl">Obraz WBMP</comment>
- <comment xml:lang="pt">imagem WBMP</comment>
- <comment xml:lang="pt_BR">Imagem WBMP</comment>
- <comment xml:lang="ro">Imagine WBMP</comment>
- <comment xml:lang="ru">Изображение WBMP</comment>
- <comment xml:lang="sk">Obrázok WBMP</comment>
- <comment xml:lang="sl">Slikovna datoteka WBMP</comment>
- <comment xml:lang="sq">Figurë WBMP</comment>
- <comment xml:lang="sr">ВБМП слика</comment>
- <comment xml:lang="sv">WBMP-bild</comment>
- <comment xml:lang="tr">WBMP görüntüsü</comment>
- <comment xml:lang="uk">зображення WBMP</comment>
- <comment xml:lang="vi">Ảnh WBMP</comment>
- <comment xml:lang="zh_CN">WBMP 图像</comment>
<comment xml:lang="zh_TW">WBMP 影像</comment>
+ <comment xml:lang="zh_CN">WBMP 图像</comment>
+ <comment xml:lang="vi">Ảnh WBMP</comment>
+ <comment xml:lang="uk">зображення WBMP</comment>
+ <comment xml:lang="tr">WBMP görüntüsü</comment>
+ <comment xml:lang="sv">WBMP-bild</comment>
+ <comment xml:lang="sr">ВБМП слика</comment>
+ <comment xml:lang="sq">figurë WBMP</comment>
+ <comment xml:lang="sl">Slikovna datoteka WBMP</comment>
+ <comment xml:lang="si">WBMP රූපය</comment>
+ <comment xml:lang="sk">Obrázok WBMP</comment>
+ <comment xml:lang="ru">Изображение WBMP</comment>
+ <comment xml:lang="ro">Imagine WBMP</comment>
+ <comment xml:lang="pt_BR">Imagem WBMP</comment>
+ <comment xml:lang="pt">imagem WBMP</comment>
+ <comment xml:lang="pl">Obraz WBMP</comment>
+ <comment xml:lang="oc">imatge WBMP</comment>
+ <comment xml:lang="nn">WBMP-bilete</comment>
+ <comment xml:lang="nl">WBMP-afbeelding</comment>
+ <comment xml:lang="nb">WBMP-bilde</comment>
+ <comment xml:lang="lv">WBMP attēls</comment>
+ <comment xml:lang="lt">WBMP paveikslėlis</comment>
+ <comment xml:lang="ko">WBMP 그림</comment>
+ <comment xml:lang="kk">WBMP суреті</comment>
+ <comment xml:lang="ja">WBMP 画像</comment>
+ <comment xml:lang="it">Immagine WBMP</comment>
+ <comment xml:lang="is">WBMP mynd</comment>
+ <comment xml:lang="id">Citra WBMP</comment>
+ <comment xml:lang="ia">Imagine WBMP</comment>
+ <comment xml:lang="hu">WBMP kép</comment>
+ <comment xml:lang="hr">WBMP slika</comment>
+ <comment xml:lang="he">תמונת WBMP</comment>
+ <comment xml:lang="gl">imaxe WBMP</comment>
+ <comment xml:lang="ga">íomhá WBMP</comment>
+ <comment xml:lang="fur">imagjin WBMP</comment>
+ <comment xml:lang="fr">image WBMP</comment>
+ <comment xml:lang="fo">WBMP mynd</comment>
+ <comment xml:lang="fi">WBMP-kuva</comment>
+ <comment xml:lang="eu">WBMP irudia</comment>
+ <comment xml:lang="es">imagen WBMP</comment>
+ <comment xml:lang="eo">WBMP-bildo</comment>
+ <comment xml:lang="en_GB">WBMP image</comment>
+ <comment xml:lang="el">Εικόνα WBMP</comment>
+ <comment xml:lang="de">WBMP-Bild</comment>
+ <comment xml:lang="da">WBMP-billede</comment>
+ <comment xml:lang="cs">obrázek WBMP</comment>
+ <comment xml:lang="ca">imatge WBMP</comment>
+ <comment xml:lang="bg">Изображение — WBMP</comment>
+ <comment xml:lang="be@latin">Vyjava WBMP</comment>
+ <comment xml:lang="be">выява WBMP</comment>
+ <comment xml:lang="ar">صورة WBMP</comment>
+ <comment xml:lang="af">WBMP-beeld</comment>
<acronym>WBMP</acronym>
<expanded-acronym>WAP bitmap</expanded-acronym>
<glob pattern="*.wbmp"/>
</mime-type>
<mime-type type="image/cgm">
- <comment>Computer Graphics Metafile</comment>
- <comment xml:lang="ar">ملف تعريف رسوميات الحاسوب</comment>
- <comment xml:lang="az">Kompüter Qrafikası Meta Faylı</comment>
- <comment xml:lang="be@latin">Metafajł Computer Graphics</comment>
- <comment xml:lang="bg">Метафайл — Computer Graphics</comment>
- <comment xml:lang="ca">metafitxer de Computer Graphics</comment>
- <comment xml:lang="cs">Computer Graphics Metafile</comment>
- <comment xml:lang="cy">Delwedd ffurf CGM</comment>
- <comment xml:lang="da">Computer Graphics-metafil</comment>
- <comment xml:lang="de">CGM-Datei</comment>
- <comment xml:lang="el">Αρχείο Computer Graphics Metafile</comment>
- <comment xml:lang="en_GB">Computer Graphics Metafile</comment>
- <comment xml:lang="es">metaarchivo de Computer Graphics</comment>
- <comment xml:lang="eu">Ordenagailuko grafikoen meta-fitxategia</comment>
- <comment xml:lang="fi">Computer Graphics -metatiedosto</comment>
- <comment xml:lang="fo">Teldugrafikk metafíla</comment>
- <comment xml:lang="fr">métafichier Computer Graphics</comment>
- <comment xml:lang="ga">Meiteachomhad Grafaicí Ríomhaire</comment>
- <comment xml:lang="gl">metaficheiro de Computer Graphics</comment>
- <comment xml:lang="he">קובץ-מטה מסוג Computer Graphics</comment>
- <comment xml:lang="hr">Computer Graphics meta datoteka</comment>
- <comment xml:lang="hu">Computer Graphics-metafájl</comment>
- <comment xml:lang="ia">Metafile Computer Graphics</comment>
- <comment xml:lang="id">Computer Graphics Metafile</comment>
- <comment xml:lang="it">Computer Graphics Metafile</comment>
- <comment xml:lang="ja">コンピューターグラフィックメタファイル</comment>
- <comment xml:lang="kk">компьютерлік графика метафайлы</comment>
- <comment xml:lang="ko">컴퓨터 그래픽스 메타 파일</comment>
- <comment xml:lang="lt">Computer Graphics metafailas</comment>
- <comment xml:lang="lv">Datorgrafikas metadatne</comment>
- <comment xml:lang="ms">Failmeta Grafik Komputer</comment>
- <comment xml:lang="nb">Computer Graphics Metafile</comment>
- <comment xml:lang="nl">Computer Graphics-metabestand</comment>
- <comment xml:lang="nn">Computer Graphics Metafile</comment>
- <comment xml:lang="oc">metafichièr Computer Graphics</comment>
- <comment xml:lang="pl">Metaplik grafiki komputerowej (CGM)</comment>
- <comment xml:lang="pt">metaficheiro Computer Graphics</comment>
- <comment xml:lang="pt_BR">Meta-arquivo do Computer Graphics</comment>
- <comment xml:lang="ro">Metafișier Computer Graphics</comment>
- <comment xml:lang="ru">Метафайл компьютерной графики</comment>
- <comment xml:lang="sk">Computer Graphics Metafile</comment>
- <comment xml:lang="sl">Metadatoteka računalniške grafike (CGM)</comment>
- <comment xml:lang="sq">Metafile Computer Graphics</comment>
- <comment xml:lang="sr">Метадатотека рачунарске графике</comment>
- <comment xml:lang="sv">Computer Graphics Metafil</comment>
- <comment xml:lang="tr">Computer Graphics Meta dosyası</comment>
- <comment xml:lang="uk">метафайл комп'ютерної графіки</comment>
- <comment xml:lang="vi">Siêu tập tin đồ họa máy tính (CMF)</comment>
- <comment xml:lang="zh_CN">计算机图形图元文件 (CGM)</comment>
+ <comment>CGM image</comment>
<comment xml:lang="zh_TW">CGM 影像</comment>
+ <comment xml:lang="zh_CN">CGM 图像</comment>
+ <comment xml:lang="uk">зображення CGM</comment>
+ <comment xml:lang="tr">CGM görüntüsü</comment>
+ <comment xml:lang="sv">CGM-bild</comment>
+ <comment xml:lang="sq">figurë CGM</comment>
+ <comment xml:lang="sl">Slika CGM</comment>
+ <comment xml:lang="si">CGM රූපය</comment>
+ <comment xml:lang="sk">Obrázok CGM</comment>
+ <comment xml:lang="ru">Изображение CGM</comment>
+ <comment xml:lang="pt_BR">Imagem CGM</comment>
+ <comment xml:lang="pl">Obraz CGM</comment>
+ <comment xml:lang="oc">imatge CGM</comment>
+ <comment xml:lang="nl">CGM-afbeelding</comment>
+ <comment xml:lang="ko">CGM 이미지</comment>
+ <comment xml:lang="kk">CGM суреті</comment>
+ <comment xml:lang="ja">CGM 画像</comment>
+ <comment xml:lang="it">Immagine CGM</comment>
+ <comment xml:lang="is">CGM mynd</comment>
+ <comment xml:lang="id">Citra CGM</comment>
+ <comment xml:lang="hu">CGM-kép</comment>
+ <comment xml:lang="hr">CGM slika</comment>
+ <comment xml:lang="he">תמונת CGM</comment>
+ <comment xml:lang="fr">image CGM</comment>
+ <comment xml:lang="fi">CGM-kuva</comment>
+ <comment xml:lang="eu">CGM irudia</comment>
+ <comment xml:lang="es">imagen CGM</comment>
+ <comment xml:lang="en_GB">CGM image</comment>
+ <comment xml:lang="de">CGM-Bild</comment>
+ <comment xml:lang="da">CGM-billede</comment>
+ <comment xml:lang="ca">imatge CGM</comment>
+ <comment xml:lang="bg">Изображение — CGM</comment>
+ <comment xml:lang="be">выява CGM</comment>
+ <comment xml:lang="ar">صورة CGM</comment>
+ <acronym>CGM</acronym>
+ <expanded-acronym>Computer Graphics Metafile</expanded-acronym>
<glob pattern="*.cgm"/>
</mime-type>
- <mime-type type="image/fax-g3">
- <comment>CCITT G3 fax</comment>
- <comment xml:lang="ar">فاكس CCITT G3</comment>
- <comment xml:lang="be@latin">Faks CCITT G3</comment>
- <comment xml:lang="bg">Факс — CCITT G3</comment>
- <comment xml:lang="ca">fax CCITT G3</comment>
- <comment xml:lang="cs">fax CCITT G3</comment>
- <comment xml:lang="da">CCITT G3-fax</comment>
+ <mime-type type="image/g3fax">
+ <comment>CCITT G3 fax image</comment>
+ <comment xml:lang="zh_TW">CCITT G3 傳真影像</comment>
+ <comment xml:lang="zh_CN">CCITT G3 传真图像</comment>
+ <comment xml:lang="uk">зображення факсу G3 CCITT</comment>
+ <comment xml:lang="tr">CCITT G3 faks görüntüsü</comment>
+ <comment xml:lang="sv">CCITT G3 faxbild</comment>
+ <comment xml:lang="sq">figurë faks CCITT G3</comment>
+ <comment xml:lang="sl">Slikovna datoteka faksimila CCITT G3</comment>
+ <comment xml:lang="si">CCITT G3 ෆැක්ස් රූපය</comment>
+ <comment xml:lang="ru">Факсовое изображение CCITT G3</comment>
+ <comment xml:lang="pt_BR">Imagem de fax CCITT G3</comment>
+ <comment xml:lang="pl">Obraz faksowy G3 CCITT</comment>
+ <comment xml:lang="nl">CCITT G3-faxafbeelding</comment>
+ <comment xml:lang="ko">CCITT G3 팩스 이미지</comment>
+ <comment xml:lang="kk">CCITT G3 факс суреті</comment>
+ <comment xml:lang="ja">CCITT G3 ファックス画像</comment>
+ <comment xml:lang="it">Immagine fax CCIT G3</comment>
+ <comment xml:lang="is">CCITT G3 faxmynd</comment>
+ <comment xml:lang="id">Citra faks CCITT G3</comment>
+ <comment xml:lang="hu">CCITT G3-faxkép</comment>
+ <comment xml:lang="hr">CCITT G3 slika faksa</comment>
+ <comment xml:lang="he">תמונת פקס של CCITT G3</comment>
+ <comment xml:lang="fr">image de télécopie CCITT G3</comment>
+ <comment xml:lang="fi">CCITT G3 -faksikuva</comment>
+ <comment xml:lang="eu">CCITT G3 fax irudia</comment>
+ <comment xml:lang="es">imagen de fax CCITT G3</comment>
+ <comment xml:lang="en_GB">CCITT G3 fax image</comment>
<comment xml:lang="de">CCITT-G3-Fax</comment>
- <comment xml:lang="el">φαξ σε μορφή CCITT G3</comment>
- <comment xml:lang="en_GB">CCITT G3 fax</comment>
- <comment xml:lang="eo">G3-fakso de CCITT</comment>
- <comment xml:lang="es">fax de CCITT G3</comment>
- <comment xml:lang="eu">CCITT G3 faxa</comment>
- <comment xml:lang="fi">CCITT G3 -faksi</comment>
- <comment xml:lang="fo">CCITT G3 telefaks</comment>
- <comment xml:lang="fr">télécopie G3 CCITT</comment>
- <comment xml:lang="ga">facs CCITT G3</comment>
- <comment xml:lang="gl">fax de CCITT G3</comment>
- <comment xml:lang="he">פקס של CCITT G3</comment>
- <comment xml:lang="hr">CCITT G3 faks</comment>
- <comment xml:lang="hu">CCITT G3-fax</comment>
- <comment xml:lang="ia">Fax CCITT G3</comment>
- <comment xml:lang="id">Faks CCITT G3</comment>
- <comment xml:lang="it">Fax CCITT G3</comment>
- <comment xml:lang="ja">CCITT G3 FAX</comment>
- <comment xml:lang="ka">CCITT G3 ფაქსი</comment>
- <comment xml:lang="kk">CCITT G3 факсі</comment>
- <comment xml:lang="ko">CCITT G3 팩스</comment>
- <comment xml:lang="lt">CCITT G3 faksas</comment>
- <comment xml:lang="lv">CCITT G3 fakss</comment>
- <comment xml:lang="ms">Faks g3 CCITT</comment>
- <comment xml:lang="nb">CCITT G3-faks</comment>
- <comment xml:lang="nl">CCITT G3-fax</comment>
- <comment xml:lang="nn">CCITT G3-fax</comment>
- <comment xml:lang="oc">telecòpia G3 CCITT</comment>
- <comment xml:lang="pl">Faks CCITT G3</comment>
- <comment xml:lang="pt">fax CCITT G3</comment>
- <comment xml:lang="pt_BR">Fax do CCITT G3</comment>
- <comment xml:lang="ro">Fax CCITT G3</comment>
- <comment xml:lang="ru">Факс CCITT G3</comment>
- <comment xml:lang="sk">Fax CCITT G3</comment>
- <comment xml:lang="sl">Datoteka faksimila CCITT G3</comment>
- <comment xml:lang="sq">Fax CCITT G3</comment>
- <comment xml:lang="sr">ЦЦИТТ Г3 факс</comment>
- <comment xml:lang="sv">CCITT G3-fax</comment>
- <comment xml:lang="tr">CCITT G3 faksı</comment>
- <comment xml:lang="uk">факс CCITT G3</comment>
- <comment xml:lang="vi">Điện thư G3 CCITT</comment>
- <comment xml:lang="zh_CN">CCITT G3 传真</comment>
- <comment xml:lang="zh_TW">CCITT G3 傳真檔</comment>
+ <comment xml:lang="da">CCITT G3-faxbillede</comment>
+ <comment xml:lang="ca">imatge de fax CCITT G3</comment>
+ <comment xml:lang="bg">Изображение — CCITT G3, факс</comment>
+ <comment xml:lang="be">выява факса CCITT G3</comment>
+ <comment xml:lang="ar">صورة فاكس CCITT G3</comment>
+ <acronym>CCITT</acronym>
+ <expanded-acronym>Comité Consultatif International Téléphonique et Télégraphique</expanded-acronym>
<glob pattern="*.g3"/>
- </mime-type>
- <mime-type type="image/g3fax">
- <comment>G3 fax image</comment>
- <comment xml:lang="ar">صورة فاكس G3</comment>
- <comment xml:lang="az">G3 faks rəsmi</comment>
- <comment xml:lang="be@latin">Faksavaja vyjava G3</comment>
- <comment xml:lang="bg">Изображение — факс G3</comment>
- <comment xml:lang="ca">imatge de fax G3</comment>
- <comment xml:lang="cs">faxový obrázek G3</comment>
- <comment xml:lang="cy">Delwedd Ffacs G3</comment>
- <comment xml:lang="da">G3-faxbillede</comment>
- <comment xml:lang="de">G3-Faxbild</comment>
- <comment xml:lang="el">Εικόνα φαξ G3</comment>
- <comment xml:lang="en_GB">G3 fax image</comment>
- <comment xml:lang="eo">G3-faksbildo</comment>
- <comment xml:lang="es">imagen de fax G3</comment>
- <comment xml:lang="eu">G3 fax-irudia</comment>
- <comment xml:lang="fi">G3-faksikuva</comment>
- <comment xml:lang="fo">G3 fax mynd</comment>
- <comment xml:lang="fr">image de télécopie G3</comment>
- <comment xml:lang="ga">íomhá fhacs G3</comment>
- <comment xml:lang="gl">imaxe de fax G3</comment>
- <comment xml:lang="he">תמונת פקס של G3</comment>
- <comment xml:lang="hr">G3 slika faksa</comment>
- <comment xml:lang="hu">G3-faxkép</comment>
- <comment xml:lang="ia">Imagine de fax G3</comment>
- <comment xml:lang="id">Citra faks G3</comment>
- <comment xml:lang="it">Immagine fax G3</comment>
- <comment xml:lang="ja">G3 FAX 画像</comment>
- <comment xml:lang="ka">G3 fax გამოსახულება</comment>
- <comment xml:lang="kk">G3 факс суреті</comment>
- <comment xml:lang="ko">G3 팩스 그림</comment>
- <comment xml:lang="lt">G3 fax paveikslėlis</comment>
- <comment xml:lang="lv">G3 faksa attēls</comment>
- <comment xml:lang="ms">Imej fax G3</comment>
- <comment xml:lang="nb">G3-faksbilde</comment>
- <comment xml:lang="nl">G3 faxafbeelding</comment>
- <comment xml:lang="nn">G3 faksbilete</comment>
- <comment xml:lang="oc">imatge de telecòpia G3</comment>
- <comment xml:lang="pl">Obraz faksowy G3</comment>
- <comment xml:lang="pt">imagem de fax G3</comment>
- <comment xml:lang="pt_BR">Imagem de fax G3</comment>
- <comment xml:lang="ro">Imagine fax G3</comment>
- <comment xml:lang="ru">Факсовое изображение G3</comment>
- <comment xml:lang="sk">Obrázok fax G3</comment>
- <comment xml:lang="sl">Slikovna datoteka G3 fax</comment>
- <comment xml:lang="sq">Figurë Fax G3</comment>
- <comment xml:lang="sr">слика Г3 факса</comment>
- <comment xml:lang="sv">G3-faxbild</comment>
- <comment xml:lang="tr">G3 fax görüntüsü</comment>
- <comment xml:lang="uk">факс G3</comment>
- <comment xml:lang="vi">Ảnh điện thư G3</comment>
- <comment xml:lang="zh_CN">G3 传真图像</comment>
- <comment xml:lang="zh_TW">G3 傳真圖</comment>
+ <alias type="image/fax-g3"/>
</mime-type>
<mime-type type="image/gif">
<comment>GIF image</comment>
- <comment xml:lang="ar">صورة GIF</comment>
- <comment xml:lang="az">GIF rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava GIF</comment>
- <comment xml:lang="bg">Изображение — GIF</comment>
- <comment xml:lang="ca">imatge GIF</comment>
- <comment xml:lang="cs">obrázek GIF</comment>
- <comment xml:lang="cy">Delwedd GIF</comment>
- <comment xml:lang="da">GIF-billede</comment>
- <comment xml:lang="de">GIF-Bild</comment>
- <comment xml:lang="el">Εικόνα GIF</comment>
- <comment xml:lang="en_GB">GIF image</comment>
- <comment xml:lang="eo">GIF-bildo</comment>
- <comment xml:lang="es">imagen GIF</comment>
- <comment xml:lang="eu">GIF irudia</comment>
- <comment xml:lang="fi">GIF-kuva</comment>
- <comment xml:lang="fo">GIF mynd</comment>
- <comment xml:lang="fr">image GIF</comment>
- <comment xml:lang="ga">íomhá GIF</comment>
- <comment xml:lang="gl">imaxe GIF</comment>
- <comment xml:lang="he">תמונת GIF</comment>
- <comment xml:lang="hr">GIF slika</comment>
- <comment xml:lang="hu">GIF-kép</comment>
- <comment xml:lang="ia">Imagine GIF</comment>
- <comment xml:lang="id">Citra GIF</comment>
- <comment xml:lang="it">Immagine GIF</comment>
- <comment xml:lang="ja">GIF 画像</comment>
- <comment xml:lang="ka">GIF გამოსახულება</comment>
- <comment xml:lang="kk">GIF суреті</comment>
- <comment xml:lang="ko">GIF 그림</comment>
- <comment xml:lang="lt">GIF paveikslėlis</comment>
- <comment xml:lang="lv">GIF attēls</comment>
- <comment xml:lang="ms">Imej GIF</comment>
- <comment xml:lang="nb">GIF-bilde</comment>
- <comment xml:lang="nl">GIF-afbeelding</comment>
- <comment xml:lang="nn">GIF-bilete</comment>
- <comment xml:lang="oc">imatge GIF</comment>
- <comment xml:lang="pl">Obraz GIF</comment>
- <comment xml:lang="pt">imagem GIF</comment>
- <comment xml:lang="pt_BR">Imagem GIF</comment>
- <comment xml:lang="ro">Imagine GIF</comment>
- <comment xml:lang="ru">Изображение GIF</comment>
- <comment xml:lang="sk">Obrázok GIF</comment>
- <comment xml:lang="sl">Slikovna datoteka GIF</comment>
- <comment xml:lang="sq">Figurë GIF</comment>
- <comment xml:lang="sr">ГИФ слика</comment>
- <comment xml:lang="sv">GIF-bild</comment>
- <comment xml:lang="tr">GIF görüntüsü</comment>
- <comment xml:lang="uk">зображення GIF</comment>
- <comment xml:lang="vi">Ảnh GIF</comment>
- <comment xml:lang="zh_CN">GIF 图像</comment>
<comment xml:lang="zh_TW">GIF 影像</comment>
- <magic priority="50">
- <match value="GIF8" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">GIF 图像</comment>
+ <comment xml:lang="vi">Ảnh GIF</comment>
+ <comment xml:lang="uk">зображення GIF</comment>
+ <comment xml:lang="tr">GIF görüntüsü</comment>
+ <comment xml:lang="sv">GIF-bild</comment>
+ <comment xml:lang="sr">ГИФ слика</comment>
+ <comment xml:lang="sq">figurë GIF</comment>
+ <comment xml:lang="sl">Slikovna datoteka GIF</comment>
+ <comment xml:lang="si">GIF රූපය</comment>
+ <comment xml:lang="sk">Obrázok GIF</comment>
+ <comment xml:lang="ru">Изображение GIF</comment>
+ <comment xml:lang="ro">Imagine GIF</comment>
+ <comment xml:lang="pt_BR">Imagem GIF</comment>
+ <comment xml:lang="pt">imagem GIF</comment>
+ <comment xml:lang="pl">Obraz GIF</comment>
+ <comment xml:lang="oc">imatge GIF</comment>
+ <comment xml:lang="nn">GIF-bilete</comment>
+ <comment xml:lang="nl">GIF-afbeelding</comment>
+ <comment xml:lang="nb">GIF-bilde</comment>
+ <comment xml:lang="ms">Imej GIF</comment>
+ <comment xml:lang="lv">GIF attēls</comment>
+ <comment xml:lang="lt">GIF paveikslėlis</comment>
+ <comment xml:lang="ko">GIF 그림</comment>
+ <comment xml:lang="kk">GIF суреті</comment>
+ <comment xml:lang="ka">GIF გამოსახულება</comment>
+ <comment xml:lang="ja">GIF 画像</comment>
+ <comment xml:lang="it">Immagine GIF</comment>
+ <comment xml:lang="is">GIF mynd</comment>
+ <comment xml:lang="id">Citra GIF</comment>
+ <comment xml:lang="ia">Imagine GIF</comment>
+ <comment xml:lang="hu">GIF-kép</comment>
+ <comment xml:lang="hr">GIF slika</comment>
+ <comment xml:lang="he">תמונת GIF</comment>
+ <comment xml:lang="gl">imaxe GIF</comment>
+ <comment xml:lang="ga">íomhá GIF</comment>
+ <comment xml:lang="fur">imagjin GIF</comment>
+ <comment xml:lang="fr">image GIF</comment>
+ <comment xml:lang="fo">GIF mynd</comment>
+ <comment xml:lang="fi">GIF-kuva</comment>
+ <comment xml:lang="eu">GIF irudia</comment>
+ <comment xml:lang="es">imagen GIF</comment>
+ <comment xml:lang="eo">GIF-bildo</comment>
+ <comment xml:lang="en_GB">GIF image</comment>
+ <comment xml:lang="el">Εικόνα GIF</comment>
+ <comment xml:lang="de">GIF-Bild</comment>
+ <comment xml:lang="da">GIF-billede</comment>
+ <comment xml:lang="cy">Delwedd GIF</comment>
+ <comment xml:lang="cs">obrázek GIF</comment>
+ <comment xml:lang="ca">imatge GIF</comment>
+ <comment xml:lang="bg">Изображение — GIF</comment>
+ <comment xml:lang="be@latin">Vyjava GIF</comment>
+ <comment xml:lang="be">выява GIF</comment>
+ <comment xml:lang="az">GIF rəsmi</comment>
+ <comment xml:lang="ar">صورة GIF</comment>
+ <comment xml:lang="af">GIF-beeld</comment>
+ <acronym>GIF</acronym>
+ <expanded-acronym>Graphics Interchange Format</expanded-acronym>
+ <magic>
+ <match type="string" value="GIF8" offset="0"/>
</magic>
<glob pattern="*.gif"/>
</mime-type>
<mime-type type="image/heif">
<comment>HEIF image</comment>
+ <comment xml:lang="zh_TW">HEIF 影像</comment>
+ <comment xml:lang="zh_CN">HEIF 图像</comment>
+ <comment xml:lang="uk">зображення HEIF</comment>
+ <comment xml:lang="tr">HEIF görüntüsü</comment>
+ <comment xml:lang="sv">HEIF-bild</comment>
+ <comment xml:lang="sq">figurë HEIF</comment>
+ <comment xml:lang="sl">Slika HEIF</comment>
+ <comment xml:lang="si">HEIF රූපය</comment>
+ <comment xml:lang="sk">Obrázok HEIF</comment>
+ <comment xml:lang="ru">Изображение HEIF</comment>
+ <comment xml:lang="pt_BR">Imagem HEIF</comment>
+ <comment xml:lang="pl">Obraz HEIF</comment>
+ <comment xml:lang="nl">HEIF-afbeelding</comment>
+ <comment xml:lang="ko">HEIF 그림</comment>
+ <comment xml:lang="kk">HEIF суреті</comment>
+ <comment xml:lang="ja">HEIF 画像</comment>
+ <comment xml:lang="it">Immagine HEIF</comment>
+ <comment xml:lang="is">HEIF mynd</comment>
+ <comment xml:lang="id">Citra HEIF</comment>
+ <comment xml:lang="hu">HEIF kép</comment>
+ <comment xml:lang="hr">HEIF slika</comment>
+ <comment xml:lang="he">תמונת HEIF</comment>
+ <comment xml:lang="ga">íomhá HEIF</comment>
+ <comment xml:lang="fur">imagjin HEIF</comment>
+ <comment xml:lang="fr">image HEIF</comment>
+ <comment xml:lang="fi">HEIF-kuva</comment>
+ <comment xml:lang="eu">HEIF irudia</comment>
+ <comment xml:lang="es">imagen HEIF</comment>
+ <comment xml:lang="en_GB">HEIF image</comment>
+ <comment xml:lang="de">HEIF-Bild</comment>
+ <comment xml:lang="da">HEIF-billede</comment>
+ <comment xml:lang="cs">obrázek HEIF</comment>
+ <comment xml:lang="ca">imatge HEIF</comment>
+ <comment xml:lang="bg">Изображение — HEIF</comment>
+ <comment xml:lang="be">выява HEIF</comment>
+ <comment xml:lang="ar">صورة HEIF</comment>
+ <comment xml:lang="af">HEIF-beeld</comment>
<acronym>HEIF</acronym>
<expanded-acronym>High Efficiency Image File</expanded-acronym>
+ <magic priority="40">
+ <!-- less than AVIF due to ftypmif1 -->
+ <match type="string" value="ftypmif1" offset="4"/>
+ <match type="string" value="ftypmsf1" offset="4"/>
+ <match type="string" value="ftypheic" offset="4"/>
+ <match type="string" value="ftypheix" offset="4"/>
+ <match type="string" value="ftyphevc" offset="4"/>
+ <match type="string" value="ftyphevx" offset="4"/>
+ </magic>
<glob pattern="*.heic"/>
<glob pattern="*.heif"/>
+ <glob pattern="*.hif"/>
<alias type="image/heic"/>
<alias type="image/heic-sequence"/>
<alias type="image/heif-sequence"/>
</mime-type>
<mime-type type="image/ief">
<comment>IEF image</comment>
- <comment xml:lang="ar">صورة IEF</comment>
- <comment xml:lang="az">IEF rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava IEF</comment>
- <comment xml:lang="bg">Изображение — IEF</comment>
- <comment xml:lang="ca">imatge IEF</comment>
- <comment xml:lang="cs">obrázek IEF</comment>
- <comment xml:lang="cy">Delwedd IEF</comment>
- <comment xml:lang="da">IEF-billede</comment>
- <comment xml:lang="de">IEF-Bild</comment>
- <comment xml:lang="el">Εικόνα IEF</comment>
- <comment xml:lang="en_GB">IEF image</comment>
- <comment xml:lang="eo">IEF-bildo</comment>
- <comment xml:lang="es">imagen IEF</comment>
- <comment xml:lang="eu">IEF irudia</comment>
- <comment xml:lang="fi">IEF-kuva</comment>
- <comment xml:lang="fo">IEF mynd</comment>
- <comment xml:lang="fr">image IEF</comment>
- <comment xml:lang="ga">íomhá IEF</comment>
- <comment xml:lang="gl">imaxe IEF</comment>
- <comment xml:lang="he">תמונת IEF</comment>
- <comment xml:lang="hr">IEF slika</comment>
- <comment xml:lang="hu">IEF-kép</comment>
- <comment xml:lang="ia">Imagine IEF</comment>
- <comment xml:lang="id">Citra IEF</comment>
- <comment xml:lang="it">Immagine IEF</comment>
- <comment xml:lang="ja">IEF 画像</comment>
- <comment xml:lang="kk">IEF суреті</comment>
- <comment xml:lang="ko">IEF 그림</comment>
- <comment xml:lang="lt">IEF paveikslėlis</comment>
- <comment xml:lang="lv">IEF attēls</comment>
- <comment xml:lang="ms">Imej IEF</comment>
- <comment xml:lang="nb">IEF-bilde</comment>
- <comment xml:lang="nl">IEF-afbeelding</comment>
- <comment xml:lang="nn">IEF-bilete</comment>
- <comment xml:lang="oc">imatge IEF</comment>
- <comment xml:lang="pl">Obraz IEF</comment>
- <comment xml:lang="pt">imagem IEF</comment>
- <comment xml:lang="pt_BR">Imagem IEF</comment>
- <comment xml:lang="ro">Imagine IEF</comment>
- <comment xml:lang="ru">Изображение IEF</comment>
- <comment xml:lang="sk">Obrázok IEF</comment>
- <comment xml:lang="sl">Slikovna datoteka IEF</comment>
- <comment xml:lang="sq">Figurë IEF</comment>
- <comment xml:lang="sr">ИЕФ слика</comment>
- <comment xml:lang="sv">IEF-bild</comment>
- <comment xml:lang="tr">IEF görüntüsü</comment>
- <comment xml:lang="uk">зображення IEF</comment>
- <comment xml:lang="vi">Ảnh IEF</comment>
- <comment xml:lang="zh_CN">IEF 图像</comment>
<comment xml:lang="zh_TW">IEF 影像</comment>
+ <comment xml:lang="zh_CN">IEF 图像</comment>
+ <comment xml:lang="vi">Ảnh IEF</comment>
+ <comment xml:lang="uk">зображення IEF</comment>
+ <comment xml:lang="tr">IEF görüntüsü</comment>
+ <comment xml:lang="sv">IEF-bild</comment>
+ <comment xml:lang="sr">ИЕФ слика</comment>
+ <comment xml:lang="sq">figurë IEF</comment>
+ <comment xml:lang="sl">Slikovna datoteka IEF</comment>
+ <comment xml:lang="si">IEF රූපය</comment>
+ <comment xml:lang="sk">Obrázok IEF</comment>
+ <comment xml:lang="ru">Изображение IEF</comment>
+ <comment xml:lang="ro">Imagine IEF</comment>
+ <comment xml:lang="pt_BR">Imagem IEF</comment>
+ <comment xml:lang="pt">imagem IEF</comment>
+ <comment xml:lang="pl">Obraz IEF</comment>
+ <comment xml:lang="oc">imatge IEF</comment>
+ <comment xml:lang="nn">IEF-bilete</comment>
+ <comment xml:lang="nl">IEF-afbeelding</comment>
+ <comment xml:lang="nb">IEF-bilde</comment>
+ <comment xml:lang="ms">Imej IEF</comment>
+ <comment xml:lang="lv">IEF attēls</comment>
+ <comment xml:lang="lt">IEF paveikslėlis</comment>
+ <comment xml:lang="ko">IEF 그림</comment>
+ <comment xml:lang="kk">IEF суреті</comment>
+ <comment xml:lang="ja">IEF 画像</comment>
+ <comment xml:lang="it">Immagine IEF</comment>
+ <comment xml:lang="is">IEF mynd</comment>
+ <comment xml:lang="id">Citra IEF</comment>
+ <comment xml:lang="ia">Imagine IEF</comment>
+ <comment xml:lang="hu">IEF-kép</comment>
+ <comment xml:lang="hr">IEF slika</comment>
+ <comment xml:lang="he">תמונת IEF</comment>
+ <comment xml:lang="gl">imaxe IEF</comment>
+ <comment xml:lang="ga">íomhá IEF</comment>
+ <comment xml:lang="fur">imagjin IEF</comment>
+ <comment xml:lang="fr">image IEF</comment>
+ <comment xml:lang="fo">IEF mynd</comment>
+ <comment xml:lang="fi">IEF-kuva</comment>
+ <comment xml:lang="eu">IEF irudia</comment>
+ <comment xml:lang="es">imagen IEF</comment>
+ <comment xml:lang="eo">IEF-bildo</comment>
+ <comment xml:lang="en_GB">IEF image</comment>
+ <comment xml:lang="el">Εικόνα IEF</comment>
+ <comment xml:lang="de">IEF-Bild</comment>
+ <comment xml:lang="da">IEF-billede</comment>
+ <comment xml:lang="cy">Delwedd IEF</comment>
+ <comment xml:lang="cs">obrázek IEF</comment>
+ <comment xml:lang="ca">imatge IEF</comment>
+ <comment xml:lang="bg">Изображение — IEF</comment>
+ <comment xml:lang="be@latin">Vyjava IEF</comment>
+ <comment xml:lang="be">выява IEF</comment>
+ <comment xml:lang="az">IEF rəsmi</comment>
+ <comment xml:lang="ar">صورة IEF</comment>
+ <comment xml:lang="af">IEF-beeld</comment>
<glob pattern="*.ief"/>
</mime-type>
<mime-type type="image/jpeg">
<comment>JPEG image</comment>
- <comment xml:lang="ar">صورة JPEG</comment>
- <comment xml:lang="az">JPEG rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava JPEG</comment>
- <comment xml:lang="bg">Изображение — JPEG</comment>
- <comment xml:lang="ca">imatge JPEG</comment>
- <comment xml:lang="cs">obrázek JPEG</comment>
- <comment xml:lang="cy">Delwedd JPEG</comment>
- <comment xml:lang="da">JPEG-billede</comment>
- <comment xml:lang="de">JPEG-Bild</comment>
- <comment xml:lang="el">Εικόνα JPEG</comment>
- <comment xml:lang="en_GB">JPEG image</comment>
- <comment xml:lang="eo">JPEG-bildo</comment>
- <comment xml:lang="es">imagen JPEG</comment>
- <comment xml:lang="eu">JPEG irudia</comment>
- <comment xml:lang="fi">JPEG-kuva</comment>
- <comment xml:lang="fo">JPEG mynd</comment>
- <comment xml:lang="fr">image JPEG</comment>
- <comment xml:lang="ga">íomhá JPEG</comment>
- <comment xml:lang="gl">imaxe JPEG</comment>
- <comment xml:lang="he">תמונת JPEG</comment>
- <comment xml:lang="hr">JPEG slika</comment>
- <comment xml:lang="hu">JPEG-kép</comment>
- <comment xml:lang="ia">Imagine JPEG</comment>
- <comment xml:lang="id">Citra JPEG</comment>
- <comment xml:lang="it">Immagine JPEG</comment>
- <comment xml:lang="ja">JPEG 画像 </comment>
- <comment xml:lang="kk">JPEG суреті</comment>
- <comment xml:lang="ko">JPEG 그림</comment>
- <comment xml:lang="lt">JPEG paveikslėlis</comment>
- <comment xml:lang="lv">JPEG attēls</comment>
- <comment xml:lang="ms">Imej JPEG</comment>
- <comment xml:lang="nb">JPEG-bilde</comment>
- <comment xml:lang="nl">JPEG-afbeelding</comment>
- <comment xml:lang="nn">JPEG-bilete</comment>
- <comment xml:lang="oc">imatge JPEG</comment>
- <comment xml:lang="pl">Obraz JPEG</comment>
- <comment xml:lang="pt">imagem JPEG</comment>
- <comment xml:lang="pt_BR">Imagem JPEG</comment>
- <comment xml:lang="ro">Imagine JPEG</comment>
- <comment xml:lang="ru">Изображение JPEG</comment>
- <comment xml:lang="sk">Obrázok JPEG</comment>
- <comment xml:lang="sl">Slikovna datoteka JPEG</comment>
- <comment xml:lang="sq">Figurë JPEG</comment>
- <comment xml:lang="sr">ЈПЕГ слика</comment>
- <comment xml:lang="sv">JPEG-bild</comment>
- <comment xml:lang="tr">JPEG görüntüsü</comment>
- <comment xml:lang="uk">зображення JPEG</comment>
- <comment xml:lang="vi">Ảnh JPEG</comment>
- <comment xml:lang="zh_CN">JPEG 图像</comment>
<comment xml:lang="zh_TW">JPEG 影像</comment>
- <magic priority="50">
- <match value="\377\330\377" type="string" offset="0"/>
- <match value="0xffd8" type="big16" offset="0"/>
+ <comment xml:lang="zh_CN">JPEG 图像</comment>
+ <comment xml:lang="vi">Ảnh JPEG</comment>
+ <comment xml:lang="uk">зображення JPEG</comment>
+ <comment xml:lang="tr">JPEG görüntüsü</comment>
+ <comment xml:lang="sv">JPEG-bild</comment>
+ <comment xml:lang="sr">ЈПЕГ слика</comment>
+ <comment xml:lang="sq">figurë JPEG</comment>
+ <comment xml:lang="sl">Slikovna datoteka JPEG</comment>
+ <comment xml:lang="si">JPEG රූපය</comment>
+ <comment xml:lang="sk">Obrázok JPEG</comment>
+ <comment xml:lang="ru">Изображение JPEG</comment>
+ <comment xml:lang="ro">Imagine JPEG</comment>
+ <comment xml:lang="pt_BR">Imagem JPEG</comment>
+ <comment xml:lang="pt">imagem JPEG</comment>
+ <comment xml:lang="pl">Obraz JPEG</comment>
+ <comment xml:lang="oc">imatge JPEG</comment>
+ <comment xml:lang="nn">JPEG-bilete</comment>
+ <comment xml:lang="nl">JPEG-afbeelding</comment>
+ <comment xml:lang="nb">JPEG-bilde</comment>
+ <comment xml:lang="ms">Imej JPEG</comment>
+ <comment xml:lang="lv">JPEG attēls</comment>
+ <comment xml:lang="lt">JPEG paveikslėlis</comment>
+ <comment xml:lang="ko">JPEG 그림</comment>
+ <comment xml:lang="kk">JPEG суреті</comment>
+ <comment xml:lang="ka">JPEG გამოსახულება</comment>
+ <comment xml:lang="ja">JPEG 画像 </comment>
+ <comment xml:lang="it">Immagine JPEG</comment>
+ <comment xml:lang="is">JPEG mynd</comment>
+ <comment xml:lang="id">Citra JPEG</comment>
+ <comment xml:lang="ia">Imagine JPEG</comment>
+ <comment xml:lang="hu">JPEG-kép</comment>
+ <comment xml:lang="hr">JPEG slika</comment>
+ <comment xml:lang="he">תמונת JPEG</comment>
+ <comment xml:lang="gl">imaxe JPEG</comment>
+ <comment xml:lang="ga">íomhá JPEG</comment>
+ <comment xml:lang="fur">imagjin JPEG</comment>
+ <comment xml:lang="fr">image JPEG</comment>
+ <comment xml:lang="fo">JPEG mynd</comment>
+ <comment xml:lang="fi">JPEG-kuva</comment>
+ <comment xml:lang="eu">JPEG irudia</comment>
+ <comment xml:lang="es">imagen JPEG</comment>
+ <comment xml:lang="eo">JPEG-bildo</comment>
+ <comment xml:lang="en_GB">JPEG image</comment>
+ <comment xml:lang="el">Εικόνα JPEG</comment>
+ <comment xml:lang="de">JPEG-Bild</comment>
+ <comment xml:lang="da">JPEG-billede</comment>
+ <comment xml:lang="cy">Delwedd JPEG</comment>
+ <comment xml:lang="cs">obrázek JPEG</comment>
+ <comment xml:lang="ca">imatge JPEG</comment>
+ <comment xml:lang="bg">Изображение — JPEG</comment>
+ <comment xml:lang="be@latin">Vyjava JPEG</comment>
+ <comment xml:lang="be">выява JPEG</comment>
+ <comment xml:lang="az">JPEG rəsmi</comment>
+ <comment xml:lang="ar">صورة JPEG</comment>
+ <comment xml:lang="af">JPEG-beeld</comment>
+ <acronym>JPEG</acronym>
+ <expanded-acronym>Joint Photographic Experts Group</expanded-acronym>
+ <magic>
+ <match type="string" value="\377\330\377" offset="0"/>
+ <match type="big16" value="0xffd8" offset="0"/>
</magic>
- <glob pattern="*.jpeg"/>
<glob pattern="*.jpg"/>
+ <glob pattern="*.jpeg"/>
<glob pattern="*.jpe"/>
+ <glob pattern="*.jfif"/>
<alias type="image/pjpeg"/>
</mime-type>
<mime-type type="video/x-mjpeg">
<comment>MJPEG video stream</comment>
+ <comment xml:lang="zh_TW">MJPEG 視訊串流</comment>
+ <comment xml:lang="zh_CN">MJPEG 视频流</comment>
+ <comment xml:lang="uk">відеопотік MJPEG</comment>
+ <comment xml:lang="tr">MJPEG video akışı</comment>
+ <comment xml:lang="sv">MJPEG-videoström</comment>
+ <comment xml:lang="sq">transmetim video MJEPG</comment>
+ <comment xml:lang="si">MJPEG වීඩියෝ ප්‍රවාහය</comment>
+ <comment xml:lang="sk">Stream videa MJPEG</comment>
+ <comment xml:lang="ru">Видеопоток MJPEG</comment>
+ <comment xml:lang="pt_BR">Fluxo de vídeo MPEG</comment>
+ <comment xml:lang="pl">Strumień wideo MJPEG</comment>
+ <comment xml:lang="nl">MJPEG-video-stream</comment>
+ <comment xml:lang="lt">MJPEG vaizdo srautas</comment>
+ <comment xml:lang="ko">MJPEG 동영상 스트림</comment>
+ <comment xml:lang="kk">MJPEG видео ағыны</comment>
+ <comment xml:lang="ja">MJPEG 動画ストリーム</comment>
+ <comment xml:lang="it">Stream video MJPEG</comment>
+ <comment xml:lang="is">MJPEG myndmerkisstreymi</comment>
+ <comment xml:lang="id">Stream video MJPEG</comment>
+ <comment xml:lang="hu">MJPEG videofolyam</comment>
+ <comment xml:lang="hr">Prijenos MJPEG videa</comment>
+ <comment xml:lang="he">תזרים וידאו MJPEG</comment>
+ <comment xml:lang="ga">sruth físe MJPEG</comment>
+ <comment xml:lang="fur">trasmission video MJPEG</comment>
+ <comment xml:lang="fr">flux vidéo MJPEG</comment>
+ <comment xml:lang="fi">MJPEG-videon suoratoisto</comment>
+ <comment xml:lang="eu">MJPEG bideo korrontea</comment>
+ <comment xml:lang="es">videotransmisión MJPEG</comment>
+ <comment xml:lang="en_GB">MJPEG video stream</comment>
+ <comment xml:lang="de">MJPEG-Videodatenstrom</comment>
+ <comment xml:lang="da">MJPEG-videostrøm</comment>
+ <comment xml:lang="cs">datový tok videa MJPEG</comment>
+ <comment xml:lang="ca">flux de vídeo MJPEG</comment>
+ <comment xml:lang="bg">Поток — MJPEG, видео</comment>
+ <comment xml:lang="be">плынь відэа MJPEG</comment>
+ <comment xml:lang="ar">دفق فيديو MJPEG</comment>
+ <comment xml:lang="af">MJPEG-videostroom</comment>
<acronym>MJPEG</acronym>
<expanded-acronym>Motion JPEG</expanded-acronym>
<sub-class-of type="image/jpeg"/>
@@ -25465,27 +27719,42 @@
</mime-type>
<mime-type type="image/x-jp2-codestream">
<comment>JPEG-2000 codestream</comment>
- <comment xml:lang="ca">flux de codis JPEG-2000</comment>
- <comment xml:lang="cs">datový tok JPEG-2000</comment>
- <comment xml:lang="de">JPEG-2000 Codestream</comment>
- <comment xml:lang="en_GB">JPEG-2000 codestream</comment>
- <comment xml:lang="es">secuencia de código JPEG-2000</comment>
- <comment xml:lang="hr">JPEG-2000 kôd strujanja</comment>
- <comment xml:lang="hu">JPEG-2000 kódfolyam</comment>
- <comment xml:lang="id">codestream JPEG-2000</comment>
- <comment xml:lang="it">Codestream JPEG-2000</comment>
- <comment xml:lang="kk">JPEG-2000 код ағыны</comment>
- <comment xml:lang="ko">JPEG-2000 코드스트림</comment>
- <comment xml:lang="pl">Strumień kodu JPEG-2000</comment>
- <comment xml:lang="pt_BR">Imagem JPEG-2000</comment>
- <comment xml:lang="ru">Кодовый поток JPEG-2000</comment>
- <comment xml:lang="sk">JPEG-2000 codestream</comment>
- <comment xml:lang="sv">JPEG-2000-kodström</comment>
- <comment xml:lang="uk">потік коду JPEG-2000</comment>
- <comment xml:lang="zh_CN">JPEG-2000 码流</comment>
<comment xml:lang="zh_TW">JPEG-2000 代碼串流</comment>
- <magic priority="50">
- <match value="0xff4fff51" type="big32" offset="0"/>
+ <comment xml:lang="zh_CN">JPEG-2000 码流</comment>
+ <comment xml:lang="uk">потік коду JPEG-2000</comment>
+ <comment xml:lang="tr">JPEG-2000 codestream</comment>
+ <comment xml:lang="sv">JPEG-2000-kodström</comment>
+ <comment xml:lang="si">JPEG-2000 කේත ප්‍රවාහය</comment>
+ <comment xml:lang="sk">JPEG-2000 codestream</comment>
+ <comment xml:lang="ru">Кодовый поток JPEG-2000</comment>
+ <comment xml:lang="pt_BR">Imagem JPEG-2000</comment>
+ <comment xml:lang="pl">Strumień kodu JPEG-2000</comment>
+ <comment xml:lang="nl">JPEG-2000-codestream</comment>
+ <comment xml:lang="ko">JPEG-2000 코드스트림</comment>
+ <comment xml:lang="kk">JPEG-2000 код ағыны</comment>
+ <comment xml:lang="ja">JPEG-2000 コードストリーム</comment>
+ <comment xml:lang="it">Codestream JPEG-2000</comment>
+ <comment xml:lang="is">JPEG-2000 kóðastreymi</comment>
+ <comment xml:lang="id">Codestream JPEG-2000</comment>
+ <comment xml:lang="hu">JPEG-2000 kódfolyam</comment>
+ <comment xml:lang="hr">JPEG-2000 kôd strujanja</comment>
+ <comment xml:lang="he">תזרים קוד JPEG-2000</comment>
+ <comment xml:lang="ga">códsruth JPEG-2000</comment>
+ <comment xml:lang="fur">trasmission codiç JPEG-2000</comment>
+ <comment xml:lang="fr">flux de code JPEG-2000</comment>
+ <comment xml:lang="fi">JPEG-2000-koodivirta</comment>
+ <comment xml:lang="eu">JPEG-2000 kodekorrontea</comment>
+ <comment xml:lang="es">secuencia de código JPEG-2000</comment>
+ <comment xml:lang="en_GB">JPEG-2000 codestream</comment>
+ <comment xml:lang="de">JPEG-2000 Codestream</comment>
+ <comment xml:lang="da">JPEG-2000-kodestrøm</comment>
+ <comment xml:lang="cs">datový tok JPEG-2000</comment>
+ <comment xml:lang="ca">flux de codis JPEG-2000</comment>
+ <comment xml:lang="bg">Поток — JPEG-2000, кодирано</comment>
+ <comment xml:lang="be">плынь кода JPEG-2000</comment>
+ <comment xml:lang="ar">تيار شفرة JPEG-2000</comment>
+ <magic>
+ <match type="big32" value="0xff4fff51" offset="0"/>
</magic>
<glob pattern="*.j2c"/>
<glob pattern="*.j2k"/>
@@ -25493,176 +27762,274 @@
</mime-type>
<mime-type type="image/jp2">
<comment>JPEG-2000 JP2 image</comment>
- <comment xml:lang="ca">imatge JPEG-2000 JP2</comment>
- <comment xml:lang="cs">obrázek JPEG-2000 JP2</comment>
- <comment xml:lang="de">JPEG-2000 JP2-Bild</comment>
- <comment xml:lang="en_GB">JPEG-2000 JP2 image</comment>
- <comment xml:lang="es">imagen JPEG-2000 JP2</comment>
- <comment xml:lang="fi">JPEG-2000 JP2 -kuva</comment>
- <comment xml:lang="hr">JPEG-2000 JP2 slika</comment>
- <comment xml:lang="hu">JPEG-2000 JP2 kép</comment>
- <comment xml:lang="id">Citra JPEG-2000 JP2</comment>
- <comment xml:lang="it">Immagine JPEG-2000 JP2</comment>
- <comment xml:lang="kk">JPEG-2000 JP2 суреті</comment>
- <comment xml:lang="ko">JPEG-2000 JP2 그림</comment>
- <comment xml:lang="pl">Obraz JP2 JPEG-2000</comment>
- <comment xml:lang="pt_BR">Imagem JP2 de JPEG-2000</comment>
- <comment xml:lang="ru">Изоражение JPEG-2000 JP2</comment>
- <comment xml:lang="sk">Obrázok JPEG-2000 JP2</comment>
- <comment xml:lang="sv">JPEG-2000 JP2-bild</comment>
- <comment xml:lang="uk">зображення JP2 JPEG-2000</comment>
- <comment xml:lang="zh_CN">JPEG-2000 JP2 图像</comment>
<comment xml:lang="zh_TW">JPEG-2000 JP2 影像</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 JP2 图像</comment>
+ <comment xml:lang="uk">зображення JP2 JPEG-2000</comment>
+ <comment xml:lang="tr">JPEG-2000 JP2 görüntüsü</comment>
+ <comment xml:lang="sv">JPEG-2000 JP2-bild</comment>
+ <comment xml:lang="sq">figurë JPEG-2000 JP2</comment>
+ <comment xml:lang="sl">Slika JPEG-2000 JP2</comment>
+ <comment xml:lang="si">JPEG-2000 JP2 රූපය</comment>
+ <comment xml:lang="sk">Obrázok JPEG-2000 JP2</comment>
+ <comment xml:lang="ru">Изображение JPEG-2000 JP2</comment>
+ <comment xml:lang="pt_BR">Imagem JP2 de JPEG-2000</comment>
+ <comment xml:lang="pl">Obraz JP2 JPEG-2000</comment>
+ <comment xml:lang="oc">imatge JPEG-2000 JP2</comment>
+ <comment xml:lang="nl">JPEG-2000 JP2-afbeelding</comment>
+ <comment xml:lang="ko">JPEG-2000 JP2 그림</comment>
+ <comment xml:lang="kk">JPEG-2000 JP2 суреті</comment>
+ <comment xml:lang="ja">JPEG-2000 JP2 画像</comment>
+ <comment xml:lang="it">Immagine JPEG-2000 JP2</comment>
+ <comment xml:lang="is">JPEG-2000 JP2 mynd</comment>
+ <comment xml:lang="id">Citra JPEG-2000 JP2</comment>
+ <comment xml:lang="hu">JPEG-2000 JP2 kép</comment>
+ <comment xml:lang="hr">JPEG-2000 JP2 slika</comment>
+ <comment xml:lang="he">תמונת JP2 של JPEG-2000</comment>
+ <comment xml:lang="ga">íomhá JPEG-2000 JP2</comment>
+ <comment xml:lang="fur">imagjin JPEG-2000 JP2</comment>
+ <comment xml:lang="fr">image JPEG-2000 JP2</comment>
+ <comment xml:lang="fi">JPEG-2000 JP2 -kuva</comment>
+ <comment xml:lang="eu">JPEG-2000 JP2 irudia</comment>
+ <comment xml:lang="es">imagen JPEG-2000 JP2</comment>
+ <comment xml:lang="en_GB">JPEG-2000 JP2 image</comment>
+ <comment xml:lang="de">JPEG-2000 JP2-Bild</comment>
+ <comment xml:lang="da">JPEG-2000 JP2-billede</comment>
+ <comment xml:lang="cs">obrázek JPEG-2000 JP2</comment>
+ <comment xml:lang="ca">imatge JPEG-2000 JP2</comment>
+ <comment xml:lang="bg">Изображение — JPEG-2000 JP2</comment>
+ <comment xml:lang="be">выява JPEG-2000 JP2</comment>
+ <comment xml:lang="ar">صورة JPEG-2000 JP2</comment>
+ <comment xml:lang="af">JPEG-2000 JP2-beeld</comment>
<acronym>JP2</acronym>
<expanded-acronym>JPEG-2000</expanded-acronym>
<alias type="image/jpeg2000"/>
<alias type="image/jpeg2000-image"/>
<alias type="image/x-jpeg2000-image"/>
- <magic priority="50">
- <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jp2\x20" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ <magic>
+ <match type="string" mask="0xffffffffffffffffffffffff0000000000000000ffffffff" value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jp2\x20" offset="0"/>
</magic>
<glob pattern="*.jp2"/>
<glob pattern="*.jpg2"/>
</mime-type>
<mime-type type="image/jpx">
<comment>JPEG-2000 JPX image</comment>
- <comment xml:lang="ca">imatge JPEG-2000 JPX</comment>
- <comment xml:lang="cs">obrázek JPEG-2000 JPX</comment>
- <comment xml:lang="de">JPEG-2000 JPX-Bild</comment>
- <comment xml:lang="en_GB">JPEG-2000 JPX image</comment>
- <comment xml:lang="es">imagen JPEG-2000 JPX</comment>
- <comment xml:lang="fi">JPEG-2000 JPX -kuva</comment>
- <comment xml:lang="hr">JPEG-2000 JPX slika</comment>
- <comment xml:lang="hu">JPEG-2000 JPX kép</comment>
- <comment xml:lang="id">Citra JPEG-2000 JPX</comment>
- <comment xml:lang="it">Immagine JPEG-2000 JPX</comment>
- <comment xml:lang="kk">JPEG-2000 JPX суреті</comment>
- <comment xml:lang="ko">JPEG-2000 JPX 그림</comment>
- <comment xml:lang="pl">Obraz JPX JPEG-2000</comment>
- <comment xml:lang="pt_BR">Imagem JPX de JPEG-2000</comment>
- <comment xml:lang="ru">Изображение JPEG-2000 JPX</comment>
- <comment xml:lang="sk">Obrázok JPEG-2000 JPX</comment>
- <comment xml:lang="sv">JPEG-2000 JPX-bild</comment>
- <comment xml:lang="uk">зображення JPX JPEG-2000</comment>
- <comment xml:lang="zh_CN">JPEG-2000 JPX 图像</comment>
<comment xml:lang="zh_TW">JPEG-2000 JPX 影像</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 JPX 图像</comment>
+ <comment xml:lang="uk">зображення JPX JPEG-2000</comment>
+ <comment xml:lang="tr">JPEG-2000 JPX görüntüsü</comment>
+ <comment xml:lang="sv">JPEG-2000 JPX-bild</comment>
+ <comment xml:lang="sq"> image JPEG-2000 JPX</comment>
+ <comment xml:lang="sl">Slika JPEG-2000 JPX</comment>
+ <comment xml:lang="si">JPEG-2000 JPX රූපය</comment>
+ <comment xml:lang="sk">Obrázok JPEG-2000 JPX</comment>
+ <comment xml:lang="ru">Изображение JPEG-2000 JPX</comment>
+ <comment xml:lang="pt_BR">Imagem JPX de JPEG-2000</comment>
+ <comment xml:lang="pl">Obraz JPX JPEG-2000</comment>
+ <comment xml:lang="oc">imatge JPEG-2000 JPX</comment>
+ <comment xml:lang="nl">JPEG-2000 JPX-afbeelding</comment>
+ <comment xml:lang="ko">JPEG-2000 JPX 그림</comment>
+ <comment xml:lang="kk">JPEG-2000 JPX суреті</comment>
+ <comment xml:lang="ja">JPEG-2000 JPX 画像</comment>
+ <comment xml:lang="it">Immagine JPEG-2000 JPX</comment>
+ <comment xml:lang="is">JPEG-2000 JPX mynd</comment>
+ <comment xml:lang="id">Citra JPEG-2000 JPX</comment>
+ <comment xml:lang="hu">JPEG-2000 JPX kép</comment>
+ <comment xml:lang="hr">JPEG-2000 JPX slika</comment>
+ <comment xml:lang="he">תמונת JPX של JPEG-2000</comment>
+ <comment xml:lang="ga">íomhá JPEG-2000 JPX</comment>
+ <comment xml:lang="fur">imagjinJPEG-2000 JPX</comment>
+ <comment xml:lang="fr">image JPEG-2000 JPX</comment>
+ <comment xml:lang="fi">JPEG-2000 JPX -kuva</comment>
+ <comment xml:lang="eu">JPEG-2000 JPX irudia</comment>
+ <comment xml:lang="es">imagen JPEG-2000 JPX</comment>
+ <comment xml:lang="en_GB">JPEG-2000 JPX image</comment>
+ <comment xml:lang="de">JPEG-2000 JPX-Bild</comment>
+ <comment xml:lang="da">JPEG-2000 JPX-billede</comment>
+ <comment xml:lang="cs">obrázek JPEG-2000 JPX</comment>
+ <comment xml:lang="ca">imatge JPEG-2000 JPX</comment>
+ <comment xml:lang="bg">Изображение — JPEG-2000 JPX</comment>
+ <comment xml:lang="be">выява JPEG-2000 JPX</comment>
+ <comment xml:lang="ar">صورة JPEG-2000 JPX</comment>
+ <comment xml:lang="af">JPEG-2000 JPX-beeld</comment>
<acronym>JPX</acronym>
<expanded-acronym>JPEG-2000 eXtended</expanded-acronym>
- <magic priority="50">
- <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jpx\x20" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ <magic>
+ <match type="string" mask="0xffffffffffffffffffffffff0000000000000000ffffffff" value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jpx\x20" offset="0"/>
</magic>
<glob pattern="*.jpf"/>
<glob pattern="*.jpx"/>
</mime-type>
<mime-type type="image/jpm">
<comment>JPEG-2000 JPM image</comment>
- <comment xml:lang="ca">imatge JPEG-2000 JPM</comment>
- <comment xml:lang="cs">obrázek JPEG-2000 JPM</comment>
- <comment xml:lang="de">JPEG-2000 JPM-Bild</comment>
- <comment xml:lang="en_GB">JPEG-2000 JPM image</comment>
- <comment xml:lang="es">imagen JPEG-2000 JPM</comment>
- <comment xml:lang="fi">JPEG-2000 JPM -kuva</comment>
- <comment xml:lang="hr">JPEG-2000 JPM slika</comment>
- <comment xml:lang="hu">JPEG-2000 JPM kép</comment>
- <comment xml:lang="id">Citra JPEG-2000 JPM</comment>
- <comment xml:lang="it">Immagine JPEG-2000 JPM</comment>
- <comment xml:lang="kk">JPEG-2000 JPM суреті</comment>
- <comment xml:lang="ko">JPEG-2000 JPM 그림</comment>
- <comment xml:lang="pl">Obraz JPM JPEG-2000</comment>
- <comment xml:lang="pt_BR">Imagem JPM de JPEG-2000</comment>
- <comment xml:lang="ru">Изображение JPEG-2000 JPM</comment>
- <comment xml:lang="sk">Obrázok JPEG-2000 JPM</comment>
- <comment xml:lang="sv">JPEG-2000 JPM-bild</comment>
- <comment xml:lang="uk">зображення JPM JPEG-2000</comment>
- <comment xml:lang="zh_CN">JPEG-2000 JPM 图像</comment>
<comment xml:lang="zh_TW">JPEG-2000 JPM 影像</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 JPM 图像</comment>
+ <comment xml:lang="uk">зображення JPM JPEG-2000</comment>
+ <comment xml:lang="tr">JPEG-2000 JPM görüntüsü</comment>
+ <comment xml:lang="sv">JPEG-2000 JPM-bild</comment>
+ <comment xml:lang="sq">figurë JPEG-2000 JPM</comment>
+ <comment xml:lang="sl">Slika JPEG-2000 JPM</comment>
+ <comment xml:lang="si">JPEG-2000 JPM රූපය</comment>
+ <comment xml:lang="sk">Obrázok JPEG-2000 JPM</comment>
+ <comment xml:lang="ru">Изображение JPEG-2000 JPM</comment>
+ <comment xml:lang="pt_BR">Imagem JPM de JPEG-2000</comment>
+ <comment xml:lang="pl">Obraz JPM JPEG-2000</comment>
+ <comment xml:lang="oc">imatge JPEG-2000 JPM</comment>
+ <comment xml:lang="nl">JPEG-2000 JPM-afbeelding</comment>
+ <comment xml:lang="ko">JPEG-2000 JPM 그림</comment>
+ <comment xml:lang="kk">JPEG-2000 JPM суреті</comment>
+ <comment xml:lang="ja">JPEG-2000 JPM 画像</comment>
+ <comment xml:lang="it">Immagine JPEG-2000 JPM</comment>
+ <comment xml:lang="is">JPEG-2000 JPM mynd</comment>
+ <comment xml:lang="id">Citra JPEG-2000 JPM</comment>
+ <comment xml:lang="hu">JPEG-2000 JPM kép</comment>
+ <comment xml:lang="hr">JPEG-2000 JPM slika</comment>
+ <comment xml:lang="he">תמונת JPM של JPEG-2000</comment>
+ <comment xml:lang="ga">íomhá JPEG-2000 JPM</comment>
+ <comment xml:lang="fur">imagjin JPEG-2000 JPM</comment>
+ <comment xml:lang="fr">image JPEG-2000 JPM</comment>
+ <comment xml:lang="fi">JPEG-2000 JPM -kuva</comment>
+ <comment xml:lang="eu">JPEG-2000 JPM irudia</comment>
+ <comment xml:lang="es">imagen JPEG-2000 JPM</comment>
+ <comment xml:lang="en_GB">JPEG-2000 JPM image</comment>
+ <comment xml:lang="de">JPEG-2000 JPM-Bild</comment>
+ <comment xml:lang="da">JPEG-2000 JPM-billede</comment>
+ <comment xml:lang="cs">obrázek JPEG-2000 JPM</comment>
+ <comment xml:lang="ca">imatge JPEG-2000 JPM</comment>
+ <comment xml:lang="bg">Изображение — JPEG-2000 JPM</comment>
+ <comment xml:lang="be">выява JPEG-2000 JPM</comment>
+ <comment xml:lang="ar">صورة JPEG-2000 JPM</comment>
+ <comment xml:lang="af">JPEG-2000 JPM-beeld</comment>
<acronym>JPM</acronym>
<expanded-acronym>JPEG-2000 Mixed</expanded-acronym>
- <magic priority="50">
- <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jpm\x20" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ <magic>
+ <match type="string" mask="0xffffffffffffffffffffffff0000000000000000ffffffff" value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jpm\x20" offset="0"/>
</magic>
<glob pattern="*.jpm"/>
<glob pattern="*.jpgm"/>
</mime-type>
<mime-type type="video/mj2">
<comment>JPEG-2000 MJ2 video</comment>
- <comment xml:lang="ca">vídeo JPEG-2000 MJ2</comment>
- <comment xml:lang="cs">video JPEG-2000 MJ2</comment>
- <comment xml:lang="de">JPEG-2000 MJ2-Video</comment>
- <comment xml:lang="en_GB">JPEG-2000 MJ2 video</comment>
- <comment xml:lang="es">vídeo JPEG-2000 MJ2</comment>
- <comment xml:lang="fi">JPEG-2000 MJ2 -video</comment>
- <comment xml:lang="hr">JPEG-2000 MJ2 video snimka</comment>
- <comment xml:lang="hu">JPEG-2000 MJ2 videó</comment>
- <comment xml:lang="id">Video JPEG-2000 MJ2</comment>
- <comment xml:lang="it">Video JPEG-2000 MJ2</comment>
- <comment xml:lang="kk">JPEG-2000 MJ2 видеосы</comment>
- <comment xml:lang="ko">JPEG-2000 MJ2 동영상</comment>
- <comment xml:lang="pl">Plik wideo MJ2 JPEG-2000</comment>
- <comment xml:lang="pt_BR">Imagem MJ2 de JPEG-2000</comment>
- <comment xml:lang="ru">Видео JPEG-2000 MJ2</comment>
- <comment xml:lang="sk">Video JPEG-2000 MJ2</comment>
- <comment xml:lang="sv">JPEG-2000 MJ2-bild</comment>
- <comment xml:lang="uk">зображення MJ2 JPEG-2000</comment>
- <comment xml:lang="zh_CN">JPEG-2000 MJ2 视频</comment>
<comment xml:lang="zh_TW">JPEG-2000 MJ2 視訊</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 MJ2 视频</comment>
+ <comment xml:lang="uk">зображення MJ2 JPEG-2000</comment>
+ <comment xml:lang="tr">JPEG-2000 MJ2 videosu</comment>
+ <comment xml:lang="sv">JPEG-2000 MJ2-bild</comment>
+ <comment xml:lang="sq">video JPEG-2000 MJ2</comment>
+ <comment xml:lang="sl">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="si">JPEG-2000 MJ2 වීඩියෝව</comment>
+ <comment xml:lang="sk">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="ru">Видео JPEG-2000 MJ2</comment>
+ <comment xml:lang="pt_BR">Imagem MJ2 de JPEG-2000</comment>
+ <comment xml:lang="pl">Plik wideo MJ2 JPEG-2000</comment>
+ <comment xml:lang="oc">vidèo JPEG-2000 MJ2</comment>
+ <comment xml:lang="nl">JPEG-2000 MJ2-video</comment>
+ <comment xml:lang="ko">JPEG-2000 MJ2 동영상</comment>
+ <comment xml:lang="kk">JPEG-2000 MJ2 видеосы</comment>
+ <comment xml:lang="ja">JPEG-2000 MJ2 動画</comment>
+ <comment xml:lang="it">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="is">JPEG-2000 MJ2 myndskeið</comment>
+ <comment xml:lang="id">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="hu">JPEG-2000 MJ2 videó</comment>
+ <comment xml:lang="hr">JPEG-2000 MJ2 video snimka</comment>
+ <comment xml:lang="he">סרטון MJ2 של JPEG-2000</comment>
+ <comment xml:lang="ga">íomhá JPEG-2000 MJ2</comment>
+ <comment xml:lang="fur">video JPEG-2000 MJ2</comment>
+ <comment xml:lang="fr">vidéo JPEG-2000 MJ2</comment>
+ <comment xml:lang="fi">JPEG-2000 MJ2 -video</comment>
+ <comment xml:lang="eu">JPEG-2000 MJ2 bideoa</comment>
+ <comment xml:lang="es">vídeo JPEG-2000 MJ2</comment>
+ <comment xml:lang="en_GB">JPEG-2000 MJ2 video</comment>
+ <comment xml:lang="de">JPEG-2000 MJ2-Video</comment>
+ <comment xml:lang="da">JPEG-2000 MJ2-video</comment>
+ <comment xml:lang="cs">video JPEG-2000 MJ2</comment>
+ <comment xml:lang="ca">vídeo JPEG-2000 MJ2</comment>
+ <comment xml:lang="bg">Видео — JPEG-2000 MJ2</comment>
+ <comment xml:lang="be">відэа JPEG-2000 MJ2</comment>
+ <comment xml:lang="ar">فيديو JPEG-2000 MJ2</comment>
+ <comment xml:lang="af">JPEG-2000 MJ2-video</comment>
<acronym>MJ2</acronym>
<expanded-acronym>Motion JPEG-2000</expanded-acronym>
- <magic priority="50">
- <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a mjp2" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ <magic>
+ <match type="string" mask="0xffffffffffffffffffffffff0000000000000000ffffffff" value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a mjp2" offset="0"/>
</magic>
<glob pattern="*.mj2"/>
<glob pattern="*.mjp2"/>
</mime-type>
+ <mime-type type="image/jxl">
+ <comment>JPEG XL image</comment>
+ <comment xml:lang="zh_TW">JPEG XL 影像</comment>
+ <comment xml:lang="zh_CN">JPEG XL 图像</comment>
+ <comment xml:lang="uk">зображення JPEG XL</comment>
+ <comment xml:lang="tr">JPEG XL görüntüsü</comment>
+ <comment xml:lang="sv">JPEG XL-bild</comment>
+ <comment xml:lang="sl">Slika JPEG XL</comment>
+ <comment xml:lang="si">JPEG XL රූපය</comment>
+ <comment xml:lang="ru">Изображение JPEG XL</comment>
+ <comment xml:lang="pt_BR">Imagem JPEG XL</comment>
+ <comment xml:lang="pl">Obraz JPEG XL</comment>
+ <comment xml:lang="oc">imatge JPEG XL</comment>
+ <comment xml:lang="nl">JPEG XL-afbeelding</comment>
+ <comment xml:lang="ko">JPEG XL 그림</comment>
+ <comment xml:lang="kk">JPEG XL суреті</comment>
+ <comment xml:lang="ja">JPEG XL 画像 </comment>
+ <comment xml:lang="it">Immagine JPEG XL</comment>
+ <comment xml:lang="hr">JPEG XL slika</comment>
+ <comment xml:lang="gl">Imaxe JPEG XL</comment>
+ <comment xml:lang="fi">JPEG XL-kuva</comment>
+ <comment xml:lang="eu">JPEG XL irudia</comment>
+ <comment xml:lang="es">imagen JPEG XL</comment>
+ <comment xml:lang="en_GB">JPEG XL image</comment>
+ <comment xml:lang="de">JPEG-XL-Bild</comment>
+ <comment xml:lang="be">выява JPEG XL</comment>
+ <comment xml:lang="ar">صورة JPEG XL</comment>
+ <magic>
+ <match type="string" offset="0" value="\xFF\x0A"/>
+ <match type="string" offset="0" value="\0\0\0\x0CJXL \x0D\x0A\x87\x0A"/>
+ </magic>
+ <glob pattern="*.jxl"/>
+ </mime-type>
<mime-type type="image/openraster">
- <comment>OpenRaster archiving image</comment>
- <comment xml:lang="ar">صورة أرشيف OpenRaster</comment>
+ <comment>OpenRaster image</comment>
+ <comment xml:lang="zh_TW">OpenRaster 影像</comment>
+ <comment xml:lang="zh_CN">OpenRaster 图像</comment>
+ <comment xml:lang="uk">зображення OpenRaster</comment>
+ <comment xml:lang="tr">OpenRaster görüntüsü</comment>
+ <comment xml:lang="sv">OpenRaster-bild</comment>
+ <comment xml:lang="sq">figurë OpenRaster</comment>
+ <comment xml:lang="sl">Slika OpenRaster</comment>
+ <comment xml:lang="si">OpenRaster රූපය</comment>
+ <comment xml:lang="sk">Obrázok OpenRaster</comment>
+ <comment xml:lang="ru">Изображение OpenRaster</comment>
+ <comment xml:lang="pt_BR">Imagem OpenRaster</comment>
+ <comment xml:lang="pl">Obraz OpenRaster</comment>
+ <comment xml:lang="oc">imatge OpenRaster</comment>
+ <comment xml:lang="nl">OpenRaster-afbeelding</comment>
+ <comment xml:lang="ko">OpenRaster 그림</comment>
+ <comment xml:lang="kk">OpenRaster суреті</comment>
+ <comment xml:lang="ja">OpenRaster 画像</comment>
+ <comment xml:lang="it">Immagine OpenRaster</comment>
+ <comment xml:lang="is">OpenRaster-mynd</comment>
+ <comment xml:lang="id">Citra OpenRaster</comment>
+ <comment xml:lang="hu">OpenRaster kép</comment>
+ <comment xml:lang="hr">OpenRaster slika</comment>
+ <comment xml:lang="he">תמונת OpenRaster</comment>
+ <comment xml:lang="gl">Imaxe OpenRaster</comment>
+ <comment xml:lang="fr">image OpenRaster</comment>
+ <comment xml:lang="fi">OpenRaster-kuva</comment>
+ <comment xml:lang="eu">OpenRaster irudia</comment>
+ <comment xml:lang="es">imagen OpenRaster</comment>
+ <comment xml:lang="en_GB">OpenRaster image</comment>
+ <comment xml:lang="de">OpenRaster-Bild</comment>
+ <comment xml:lang="da">OpenRaster-billede</comment>
+ <comment xml:lang="ca">imatge OpenRaster</comment>
<comment xml:lang="bg">Изображение — OpenRaster</comment>
- <comment xml:lang="ca">imatge d'arxivat OpenRaster</comment>
- <comment xml:lang="cs">archivační obraz OpenRaster</comment>
- <comment xml:lang="da">OpenRaster-arkivaftryk</comment>
- <comment xml:lang="de">OpenRaster-Archivierungsbild</comment>
- <comment xml:lang="el">Εικόνα αρχειοθέτησης OpenRaster</comment>
- <comment xml:lang="en_GB">OpenRaster archiving image</comment>
- <comment xml:lang="es">imagen de archivado de OpenRaster</comment>
- <comment xml:lang="eu">OpenRaster artxiboaren irudia</comment>
- <comment xml:lang="fi">OpenRaster-arkistokuva</comment>
- <comment xml:lang="fo">OpenRaster goymslumynd</comment>
- <comment xml:lang="fr">image d'archive OpenRaster</comment>
- <comment xml:lang="ga">íomhá chartlannaithe OpenRaster</comment>
- <comment xml:lang="gl">imaxe arquivada de OpenRaster</comment>
- <comment xml:lang="he">תמונת ארכיון של OpenRaster</comment>
- <comment xml:lang="hr">OpenRaster slika arhive</comment>
- <comment xml:lang="hu">OpenRaster archiválási kép</comment>
- <comment xml:lang="ia">Imagine de archivo OpenRaster</comment>
- <comment xml:lang="id">Gambar pengarsipan OpenRaster</comment>
- <comment xml:lang="it">Immagine archiviazione OpenRaster</comment>
- <comment xml:lang="ja">OpenRaster アーカイブイメージ</comment>
- <comment xml:lang="ka">OpenRaster-ის საარქივო გამოსახულება</comment>
- <comment xml:lang="kk">OpenRaster архивтеу суреті</comment>
- <comment xml:lang="ko">OpenRaster 압축 이미지</comment>
- <comment xml:lang="lt">OpenRaster archyvavimo paveikslėlis</comment>
- <comment xml:lang="lv">OpenRaster arhivēšanas attēls</comment>
- <comment xml:lang="nl">OpenRaster archiverings-image</comment>
- <comment xml:lang="oc">imatge d'archiu OpenRaster</comment>
- <comment xml:lang="pl">Archiwalny obraz OpenRaster</comment>
- <comment xml:lang="pt">imagem arquivo OpenRaster</comment>
- <comment xml:lang="pt_BR">Imagem de arquivamento OpenRaster</comment>
- <comment xml:lang="ro">Arhivă imagine OpenRaster</comment>
- <comment xml:lang="ru">Архивное изображение OpenRaster</comment>
- <comment xml:lang="sk">Archivačný obrázok OpenRaster</comment>
- <comment xml:lang="sl">Odtis arhiva OpenRaster</comment>
- <comment xml:lang="sr">слика Опен Растер архивирања</comment>
- <comment xml:lang="sv">OpenRaster-arkivbild</comment>
- <comment xml:lang="tr">OpenRaster arşivleme görüntüsü</comment>
- <comment xml:lang="uk">архівоване зображення OpenRaster</comment>
- <comment xml:lang="zh_CN">OpenRaster 归档图像</comment>
- <comment xml:lang="zh_TW">OpenRaster 封存影像</comment>
+ <comment xml:lang="be">выява OpenRaster</comment>
+ <comment xml:lang="ar">صورة OpenRaster</comment>
<sub-class-of type="application/zip"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="mimetype" type="string" offset="30">
- <match value="image/openraster" type="string" offset="38"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="mimetype" offset="30">
+ <match type="string" value="image/openraster" offset="38"/>
</match>
</match>
</magic>
@@ -25670,229 +28037,248 @@
</mime-type>
<mime-type type="image/x-dds">
<comment>DirectDraw surface</comment>
- <comment xml:lang="ar">مساحة DirectDraw</comment>
- <comment xml:lang="be@latin">Pavierchnia DirectDraw</comment>
- <comment xml:lang="bg">Изображение — повърхност на DirectDraw</comment>
- <comment xml:lang="ca">superfície DirectDraw</comment>
- <comment xml:lang="cs">povrch DirectDraw</comment>
- <comment xml:lang="da">DirectDraw-overflade</comment>
- <comment xml:lang="de">DirectDraw-Oberfläche</comment>
- <comment xml:lang="el">Επιφάνεια DirectDraw</comment>
- <comment xml:lang="en_GB">DirectDraw surface</comment>
- <comment xml:lang="es">superficie de DirectDraw</comment>
- <comment xml:lang="eu">DirectDraw gainazala</comment>
- <comment xml:lang="fi">DirectDraw-piirtoalue</comment>
- <comment xml:lang="fo">DirectDraw yvirflata</comment>
- <comment xml:lang="fr">surface DirectDraw</comment>
- <comment xml:lang="ga">dromchla DirectDraw</comment>
- <comment xml:lang="gl">superficie de DirectDraw</comment>
- <comment xml:lang="he">משטח של DirectDraw</comment>
- <comment xml:lang="hr">DirectDraw ploha</comment>
- <comment xml:lang="hu">DirectDraw felület</comment>
- <comment xml:lang="ia">Superficie DirectDraw</comment>
- <comment xml:lang="id">Permukaan DirectDraw</comment>
- <comment xml:lang="it">Superficie DirectDraw</comment>
- <comment xml:lang="ja">DirectDraw サーフェイス</comment>
- <comment xml:lang="ka">DirectDraw-ის ზედაპირი</comment>
- <comment xml:lang="kk">DirectDraw жазықтығы</comment>
- <comment xml:lang="ko">DirectDraw 서피스</comment>
- <comment xml:lang="lt">DirectDraw paviršius</comment>
- <comment xml:lang="lv">DirectDraw virsma</comment>
- <comment xml:lang="nb">DirectDraw-overflate</comment>
- <comment xml:lang="nl">DirectDraw-oppervlak</comment>
- <comment xml:lang="nn">DirectDraw-overflate</comment>
- <comment xml:lang="oc">surfàcia DirectDraw</comment>
- <comment xml:lang="pl">Powierzchnia DirectDraw</comment>
- <comment xml:lang="pt">superfície DirectDraw</comment>
- <comment xml:lang="pt_BR">Superfície do DirectDraw</comment>
- <comment xml:lang="ro">Suprafață DirectDraw</comment>
- <comment xml:lang="ru">Плоскость DirectDraw</comment>
- <comment xml:lang="sk">Plocha DirectDraw</comment>
- <comment xml:lang="sl">Datoteka predmeta DirectDraw</comment>
- <comment xml:lang="sq">Superfaqe DirectDraw</comment>
- <comment xml:lang="sr">Директ Дров површина</comment>
- <comment xml:lang="sv">DirectDraw-yta</comment>
- <comment xml:lang="tr">DirectDraw yüzeyi</comment>
- <comment xml:lang="uk">поверхня DirectDraw</comment>
- <comment xml:lang="vi">Mặt DirectDraw</comment>
- <comment xml:lang="zh_CN">DirectDraw 表面</comment>
<comment xml:lang="zh_TW">DirectDraw 表面</comment>
- <magic priority="50">
+ <comment xml:lang="zh_CN">DirectDraw 表面</comment>
+ <comment xml:lang="vi">Mặt DirectDraw</comment>
+ <comment xml:lang="uk">поверхня DirectDraw</comment>
+ <comment xml:lang="tr">DirectDraw yüzeyi</comment>
+ <comment xml:lang="sv">DirectDraw-yta</comment>
+ <comment xml:lang="sr">Директ Дров површина</comment>
+ <comment xml:lang="sq">sipërfaqe DirectDraw</comment>
+ <comment xml:lang="sl">Datoteka predmeta DirectDraw</comment>
+ <comment xml:lang="si">DirectDraw මතුපිට</comment>
+ <comment xml:lang="sk">Plocha DirectDraw</comment>
+ <comment xml:lang="ru">Плоскость DirectDraw</comment>
+ <comment xml:lang="ro">Suprafață DirectDraw</comment>
+ <comment xml:lang="pt_BR">Superfície do DirectDraw</comment>
+ <comment xml:lang="pt">superfície DirectDraw</comment>
+ <comment xml:lang="pl">Powierzchnia DirectDraw</comment>
+ <comment xml:lang="oc">surfàcia DirectDraw</comment>
+ <comment xml:lang="nn">DirectDraw-overflate</comment>
+ <comment xml:lang="nl">DirectDraw-oppervlak</comment>
+ <comment xml:lang="nb">DirectDraw-overflate</comment>
+ <comment xml:lang="lv">DirectDraw virsma</comment>
+ <comment xml:lang="lt">DirectDraw paviršius</comment>
+ <comment xml:lang="ko">DirectDraw 서피스</comment>
+ <comment xml:lang="kk">DirectDraw жазықтығы</comment>
+ <comment xml:lang="ka">DirectDraw-ის ზედაპირი</comment>
+ <comment xml:lang="ja">DirectDraw サーフェイス</comment>
+ <comment xml:lang="it">Superficie DirectDraw</comment>
+ <comment xml:lang="is">DirectDraw yfirborðsupplýsingar</comment>
+ <comment xml:lang="id">Permukaan DirectDraw</comment>
+ <comment xml:lang="ia">Superficie DirectDraw</comment>
+ <comment xml:lang="hu">DirectDraw felület</comment>
+ <comment xml:lang="hr">DirectDraw ploha</comment>
+ <comment xml:lang="he">משטח של DirectDraw</comment>
+ <comment xml:lang="gl">superficie de DirectDraw</comment>
+ <comment xml:lang="ga">dromchla DirectDraw</comment>
+ <comment xml:lang="fur">superficie DirectDraw</comment>
+ <comment xml:lang="fr">surface DirectDraw</comment>
+ <comment xml:lang="fo">DirectDraw yvirflata</comment>
+ <comment xml:lang="fi">DirectDraw-piirtoalue</comment>
+ <comment xml:lang="eu">DirectDraw gainazala</comment>
+ <comment xml:lang="es">superficie de DirectDraw</comment>
+ <comment xml:lang="en_GB">DirectDraw surface</comment>
+ <comment xml:lang="el">Επιφάνεια DirectDraw</comment>
+ <comment xml:lang="de">DirectDraw-Oberfläche</comment>
+ <comment xml:lang="da">DirectDraw-overflade</comment>
+ <comment xml:lang="cs">povrch DirectDraw</comment>
+ <comment xml:lang="ca">superfície DirectDraw</comment>
+ <comment xml:lang="bg">Изображение — повърхност на DirectDraw</comment>
+ <comment xml:lang="be@latin">Pavierchnia DirectDraw</comment>
+ <comment xml:lang="be">паверхня DirectDraw</comment>
+ <comment xml:lang="ar">سطح DirectDraw</comment>
+ <magic>
<match value="DDS" type="string" offset="0"/>
</magic>
<glob pattern="*.dds"/>
</mime-type>
<mime-type type="image/x-xcursor">
<comment>X11 cursor</comment>
- <comment xml:lang="ar">مؤشر X11</comment>
- <comment xml:lang="be@latin">Kursor X11</comment>
- <comment xml:lang="bg">Курсор — X11</comment>
- <comment xml:lang="ca">cursor X11</comment>
- <comment xml:lang="cs">kurzor X11</comment>
- <comment xml:lang="da">X11-markør</comment>
- <comment xml:lang="de">X11-Zeiger</comment>
- <comment xml:lang="el">Δρομέας X11</comment>
- <comment xml:lang="en_GB">X11 cursor</comment>
- <comment xml:lang="es">cursor de X11</comment>
- <comment xml:lang="eu">X11 kurtsorea</comment>
- <comment xml:lang="fi">X11-osoitin</comment>
- <comment xml:lang="fo">X11 vísi</comment>
- <comment xml:lang="fr">curseur X11</comment>
- <comment xml:lang="ga">cúrsóir X11</comment>
- <comment xml:lang="gl">Cursor X11</comment>
- <comment xml:lang="he">סמן של X11</comment>
- <comment xml:lang="hr">X11 pokazivač</comment>
- <comment xml:lang="hu">X11 kurzor</comment>
- <comment xml:lang="ia">Cursor X11</comment>
- <comment xml:lang="id">Kursor X11</comment>
- <comment xml:lang="it">Cursore X11</comment>
- <comment xml:lang="ja">X11 カーソル</comment>
- <comment xml:lang="kk">X11 курсоры</comment>
- <comment xml:lang="ko">X11 커서</comment>
- <comment xml:lang="lt">X11 žymiklis</comment>
- <comment xml:lang="lv">X11 kursors</comment>
- <comment xml:lang="nb">X11-markør</comment>
- <comment xml:lang="nl">X11-muisaanwijzer</comment>
- <comment xml:lang="nn">X11-peikar</comment>
- <comment xml:lang="oc">cursor X11</comment>
- <comment xml:lang="pl">Kursor X11</comment>
- <comment xml:lang="pt">cursor X11</comment>
- <comment xml:lang="pt_BR">Cursor do X11</comment>
- <comment xml:lang="ro">Cursor X11</comment>
- <comment xml:lang="ru">Курсор X11</comment>
- <comment xml:lang="sk">Kurzor X11</comment>
- <comment xml:lang="sl">Datoteka kazalke X11</comment>
- <comment xml:lang="sq">Kursor X11</comment>
- <comment xml:lang="sr">Икс11 курсор</comment>
- <comment xml:lang="sv">X11-muspekare</comment>
- <comment xml:lang="tr">X11 imleci</comment>
- <comment xml:lang="uk">курсор X11</comment>
- <comment xml:lang="vi">Con chạy X11</comment>
- <comment xml:lang="zh_CN">X11 指针</comment>
<comment xml:lang="zh_TW">X11 滑鼠游標</comment>
- <magic priority="50">
- <match value="Xcur" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">X11 指针</comment>
+ <comment xml:lang="vi">Con chạy X11</comment>
+ <comment xml:lang="uk">курсор X11</comment>
+ <comment xml:lang="tr">X11 imleci</comment>
+ <comment xml:lang="sv">X11-muspekare</comment>
+ <comment xml:lang="sr">Икс11 курсор</comment>
+ <comment xml:lang="sq">kursor X11</comment>
+ <comment xml:lang="sl">Datoteka kazalke X11</comment>
+ <comment xml:lang="si">X11 කර්සරය</comment>
+ <comment xml:lang="sk">Kurzor X11</comment>
+ <comment xml:lang="ru">Курсор X11</comment>
+ <comment xml:lang="ro">Cursor X11</comment>
+ <comment xml:lang="pt_BR">Cursor do X11</comment>
+ <comment xml:lang="pt">cursor X11</comment>
+ <comment xml:lang="pl">Kursor X11</comment>
+ <comment xml:lang="oc">cursor X11</comment>
+ <comment xml:lang="nn">X11-peikar</comment>
+ <comment xml:lang="nl">X11-muisaanwijzer</comment>
+ <comment xml:lang="nb">X11-markør</comment>
+ <comment xml:lang="lv">X11 kursors</comment>
+ <comment xml:lang="lt">X11 žymeklis</comment>
+ <comment xml:lang="ko">X11 커서</comment>
+ <comment xml:lang="kk">X11 курсоры</comment>
+ <comment xml:lang="ja">X11 カーソル</comment>
+ <comment xml:lang="it">Cursore X11</comment>
+ <comment xml:lang="is">X11 bendill</comment>
+ <comment xml:lang="id">Kursor X11</comment>
+ <comment xml:lang="ia">Cursor X11</comment>
+ <comment xml:lang="hu">X11 kurzor</comment>
+ <comment xml:lang="hr">X11 pokazivač</comment>
+ <comment xml:lang="he">סמן של X11</comment>
+ <comment xml:lang="gl">Cursor X11</comment>
+ <comment xml:lang="ga">cúrsóir X11</comment>
+ <comment xml:lang="fur">cursôr X11</comment>
+ <comment xml:lang="fr">curseur X11</comment>
+ <comment xml:lang="fo">X11 vísi</comment>
+ <comment xml:lang="fi">X11-osoitin</comment>
+ <comment xml:lang="eu">X11 kurtsorea</comment>
+ <comment xml:lang="es">cursor de X11</comment>
+ <comment xml:lang="en_GB">X11 cursor</comment>
+ <comment xml:lang="el">Δρομέας X11</comment>
+ <comment xml:lang="de">X11-Mauszeiger</comment>
+ <comment xml:lang="da">X11-markør</comment>
+ <comment xml:lang="cs">kurzor X11</comment>
+ <comment xml:lang="ca">cursor de X11</comment>
+ <comment xml:lang="bg">Курсор — X11</comment>
+ <comment xml:lang="be@latin">Kursor X11</comment>
+ <comment xml:lang="be">курсор X11</comment>
+ <comment xml:lang="ar">مؤشر X11</comment>
+ <comment xml:lang="af">X11-wyser</comment>
+ <magic>
+ <match type="string" value="Xcur" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/x-exr">
<comment>EXR image</comment>
- <comment xml:lang="ar">صورة EXR</comment>
- <comment xml:lang="be@latin">Vyjava EXR</comment>
- <comment xml:lang="bg">Изображение — EXR</comment>
- <comment xml:lang="ca">imatge EXR</comment>
- <comment xml:lang="cs">obrázek EXR</comment>
- <comment xml:lang="da">EXR-billede</comment>
- <comment xml:lang="de">EXR-Bild</comment>
- <comment xml:lang="el">Εικόνα EXR</comment>
- <comment xml:lang="en_GB">EXR image</comment>
- <comment xml:lang="eo">EXR-bildo</comment>
- <comment xml:lang="es">imagen EXR</comment>
- <comment xml:lang="eu">EXR irudia</comment>
- <comment xml:lang="fi">EXR-kuva</comment>
- <comment xml:lang="fo">EXR mynd</comment>
- <comment xml:lang="fr">image EXR</comment>
- <comment xml:lang="ga">íomhá EXR</comment>
- <comment xml:lang="gl">imaxe EXR</comment>
- <comment xml:lang="he">תמונת EXR</comment>
- <comment xml:lang="hr">EXR slika</comment>
- <comment xml:lang="hu">EXR kép</comment>
- <comment xml:lang="ia">Imagine EXR</comment>
- <comment xml:lang="id">Citra EXR</comment>
- <comment xml:lang="it">Immagine EXR</comment>
- <comment xml:lang="ja">EXR 画像</comment>
- <comment xml:lang="ka">EXR გამოსახულება</comment>
- <comment xml:lang="kk">EXR суреті</comment>
- <comment xml:lang="ko">EXR 그림</comment>
- <comment xml:lang="lt">EXR paveikslėlis</comment>
- <comment xml:lang="lv">EXR attēls</comment>
- <comment xml:lang="nb">EXR-bilde</comment>
- <comment xml:lang="nl">EXR-afbeelding</comment>
- <comment xml:lang="nn">EXR-bilete</comment>
- <comment xml:lang="oc">imatge EXR</comment>
- <comment xml:lang="pl">Obraz EXR</comment>
- <comment xml:lang="pt">imagem EXR</comment>
- <comment xml:lang="pt_BR">Imagem EXR</comment>
- <comment xml:lang="ro">Imagine EXR</comment>
- <comment xml:lang="ru">Изображение EXR</comment>
- <comment xml:lang="sk">Obrázok EXR</comment>
- <comment xml:lang="sl">Slikovna datoteka EXR</comment>
- <comment xml:lang="sq">Figurë EXR</comment>
- <comment xml:lang="sr">ЕИксР слика</comment>
- <comment xml:lang="sv">EXR-bild</comment>
- <comment xml:lang="tr">EXR görüntüsü</comment>
- <comment xml:lang="uk">зображення EXR</comment>
- <comment xml:lang="vi">Ảnh EXR</comment>
- <comment xml:lang="zh_CN">EXR 图像</comment>
<comment xml:lang="zh_TW">EXR 影像</comment>
- <magic priority="50">
- <match value="20000630" type="little32" offset="0"/>
+ <comment xml:lang="zh_CN">EXR 图像</comment>
+ <comment xml:lang="vi">Ảnh EXR</comment>
+ <comment xml:lang="uk">зображення EXR</comment>
+ <comment xml:lang="tr">EXR görüntüsü</comment>
+ <comment xml:lang="sv">EXR-bild</comment>
+ <comment xml:lang="sr">ЕИксР слика</comment>
+ <comment xml:lang="sq">figurë EXR</comment>
+ <comment xml:lang="sl">Slikovna datoteka EXR</comment>
+ <comment xml:lang="si">EXR රූපය</comment>
+ <comment xml:lang="sk">Obrázok EXR</comment>
+ <comment xml:lang="ru">Изображение EXR</comment>
+ <comment xml:lang="ro">Imagine EXR</comment>
+ <comment xml:lang="pt_BR">Imagem EXR</comment>
+ <comment xml:lang="pt">imagem EXR</comment>
+ <comment xml:lang="pl">Obraz EXR</comment>
+ <comment xml:lang="oc">imatge EXR</comment>
+ <comment xml:lang="nn">EXR-bilete</comment>
+ <comment xml:lang="nl">EXR-afbeelding</comment>
+ <comment xml:lang="nb">EXR-bilde</comment>
+ <comment xml:lang="lv">EXR attēls</comment>
+ <comment xml:lang="lt">EXR paveikslėlis</comment>
+ <comment xml:lang="ko">EXR 그림</comment>
+ <comment xml:lang="kk">EXR суреті</comment>
+ <comment xml:lang="ka">EXR გამოსახულება</comment>
+ <comment xml:lang="ja">EXR 画像</comment>
+ <comment xml:lang="it">Immagine EXR</comment>
+ <comment xml:lang="is">EXR mynd</comment>
+ <comment xml:lang="id">Citra EXR</comment>
+ <comment xml:lang="ia">Imagine EXR</comment>
+ <comment xml:lang="hu">EXR kép</comment>
+ <comment xml:lang="hr">EXR slika</comment>
+ <comment xml:lang="he">תמונת EXR</comment>
+ <comment xml:lang="gl">imaxe EXR</comment>
+ <comment xml:lang="ga">íomhá EXR</comment>
+ <comment xml:lang="fur">imagjin EXR</comment>
+ <comment xml:lang="fr">image EXR</comment>
+ <comment xml:lang="fo">EXR mynd</comment>
+ <comment xml:lang="fi">EXR-kuva</comment>
+ <comment xml:lang="eu">EXR irudia</comment>
+ <comment xml:lang="es">imagen EXR</comment>
+ <comment xml:lang="eo">EXR-bildo</comment>
+ <comment xml:lang="en_GB">EXR image</comment>
+ <comment xml:lang="el">Εικόνα EXR</comment>
+ <comment xml:lang="de">EXR-Bild</comment>
+ <comment xml:lang="da">EXR-billede</comment>
+ <comment xml:lang="cs">obrázek EXR</comment>
+ <comment xml:lang="ca">imatge EXR</comment>
+ <comment xml:lang="bg">Изображение — EXR</comment>
+ <comment xml:lang="be@latin">Vyjava EXR</comment>
+ <comment xml:lang="be">выява EXR</comment>
+ <comment xml:lang="ar">صورة EXR</comment>
+ <comment xml:lang="af">EXR-beeld</comment>
+ <magic>
+ <match type="little32" value="20000630" offset="0"/>
</magic>
<glob pattern="*.exr"/>
</mime-type>
<mime-type type="image/x-pict">
<comment>Macintosh Quickdraw/PICT drawing</comment>
- <comment xml:lang="ar">رسمة ماكنتوش Quickdraw/PICT</comment>
- <comment xml:lang="be@latin">Rysunak Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="bg">Чертеж — Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="ca">dibuix Quickdraw/PICT de Macintosh</comment>
- <comment xml:lang="cs">kresba Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="da">Macintosh Quickdraw/PICT-tegning</comment>
- <comment xml:lang="de">Macintosh-Quickdraw/PICT-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="en_GB">Macintosh Quickdraw/PICT drawing</comment>
- <comment xml:lang="eo">Quickdraw/PICT-grafikaĵo de Macintosh</comment>
- <comment xml:lang="es">dibujo de Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="eu">Macintosh Quickdraw/PICT marrazkia</comment>
- <comment xml:lang="fi">Macintosh Quickdraw/PICT -piirros</comment>
- <comment xml:lang="fo">Macintosh Quickdraw/PICT tekning</comment>
- <comment xml:lang="fr">dessin Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="ga">líníocht Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="gl">debuxo de Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="he">ציור של Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="hr">Macintosh Quickdraw/PICT crtež</comment>
- <comment xml:lang="hu">Macintosh Quickdraw/PICT-rajz</comment>
- <comment xml:lang="ia">Designo QuickDraw/PICT de Macintosh</comment>
- <comment xml:lang="id">Gambar Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="it">Disegno Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="ja">Macintosh Quickdraw/PICT ドロー</comment>
- <comment xml:lang="kk">Macintosh Quickdraw/PICT суреті</comment>
- <comment xml:lang="ko">매킨토시 Quickdraw/PICT 그림</comment>
- <comment xml:lang="lt">Macintosh Quickdraw/PICT piešinys</comment>
- <comment xml:lang="lv">Macintosh Quickdraw/PICT zīmējums</comment>
- <comment xml:lang="ms">Lukisan Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="nb">Macintosh Quickdraw/PICT-tegning</comment>
- <comment xml:lang="nl">Macintosh Quickdraw/PICT-tekening</comment>
- <comment xml:lang="nn">Macintosh Quickdraw/PICT-teikning</comment>
- <comment xml:lang="oc">dessenh Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="pl">Rysunek QuickDraw/PICT Macintosh</comment>
- <comment xml:lang="pt">desenho Quickdraw/PICT de Macintosh</comment>
- <comment xml:lang="pt_BR">Desenho do Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="ro">Desen Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="ru">Рисунок Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="sk">Kresba Macintosh QuickDraw/PICT</comment>
- <comment xml:lang="sl">Datoteka risbe Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="sq">Vizatim Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="sr">Мекинтошов Квикдров/ПИЦТ цртеж</comment>
- <comment xml:lang="sv">Macintosh Quickdraw/PICT-teckning</comment>
- <comment xml:lang="tr">Macintosh Quickdraw/PICT çizimi</comment>
- <comment xml:lang="uk">малюнок Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="vi">Bản vẽ Quickdraw/PICT của Macintosh</comment>
- <comment xml:lang="zh_CN">Macintosh Quickdraw/PICT 绘图</comment>
<comment xml:lang="zh_TW">Macintosh Quickdraw/PICT 繪圖</comment>
- <magic priority="50">
- <match value="0x0011" type="big16" offset="10">
- <match value="0x02FF" type="big16" offset="12">
- <match value="0x0C00" type="big16" offset="14">
- <match value="0xFFFE" type="big16" offset="16"/>
+ <comment xml:lang="zh_CN">Macintosh Quickdraw/PICT 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ Quickdraw/PICT của Macintosh</comment>
+ <comment xml:lang="uk">малюнок Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="tr">Macintosh Quickdraw/PICT çizimi</comment>
+ <comment xml:lang="sv">Macintosh Quickdraw/PICT-teckning</comment>
+ <comment xml:lang="sr">Мекинтошов Квикдров/ПИЦТ цртеж</comment>
+ <comment xml:lang="sq">vizatim Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="sl">Datoteka risbe Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="si">Macintosh Quickdraw/PICT ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba Macintosh QuickDraw/PICT</comment>
+ <comment xml:lang="ru">Рисунок Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="ro">Desen Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="pt_BR">Desenho do Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="pt">desenho Quickdraw/PICT de Macintosh</comment>
+ <comment xml:lang="pl">Rysunek QuickDraw/PICT Macintosh</comment>
+ <comment xml:lang="oc">dessenh Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="nn">Macintosh Quickdraw/PICT-teikning</comment>
+ <comment xml:lang="nl">Macintosh Quickdraw/PICT-tekening</comment>
+ <comment xml:lang="nb">Macintosh Quickdraw/PICT-tegning</comment>
+ <comment xml:lang="ms">Lukisan Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="lv">Macintosh Quickdraw/PICT zīmējums</comment>
+ <comment xml:lang="lt">Macintosh Quickdraw/PICT piešinys</comment>
+ <comment xml:lang="ko">매킨토시 Quickdraw/PICT 그림</comment>
+ <comment xml:lang="kk">Macintosh Quickdraw/PICT суреті</comment>
+ <comment xml:lang="ja">Macintosh Quickdraw/PICT ドロー</comment>
+ <comment xml:lang="it">Disegno Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="is">Macintosh Quickdraw/PICT teikning</comment>
+ <comment xml:lang="id">Gambar Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="ia">Designo QuickDraw/PICT de Macintosh</comment>
+ <comment xml:lang="hu">Macintosh Quickdraw/PICT-rajz</comment>
+ <comment xml:lang="hr">Macintosh Quickdraw/PICT crtež</comment>
+ <comment xml:lang="he">ציור של Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="gl">debuxo de Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="ga">líníocht Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="fur">dissen Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="fr">dessin Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="fo">Macintosh Quickdraw/PICT tekning</comment>
+ <comment xml:lang="fi">Macintosh Quickdraw/PICT -piirros</comment>
+ <comment xml:lang="eu">Macintosh Quickdraw/PICT marrazkia</comment>
+ <comment xml:lang="es">dibujo de Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="eo">Quickdraw/PICT-grafikaĵo de Macintosh</comment>
+ <comment xml:lang="en_GB">Macintosh Quickdraw/PICT drawing</comment>
+ <comment xml:lang="el">Σχέδιο Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="de">Macintosh-Quickdraw/PICT-Zeichnung</comment>
+ <comment xml:lang="da">Macintosh Quickdraw/PICT-tegning</comment>
+ <comment xml:lang="cs">kresba Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="ca">dibuix Quickdraw/PICT de Macintosh</comment>
+ <comment xml:lang="bg">Чертеж — Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="be@latin">Rysunak Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="be">рысунак Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="ar">رسمة ماكنتوش Quickdraw/PICT</comment>
+ <comment xml:lang="af">Macintosh Quickdraw/PICT-tekening</comment>
+ <magic>
+ <match type="big16" value="0x0011" offset="10">
+ <match type="big16" value="0x02FF" offset="12">
+ <match type="big16" value="0x0C00" offset="14">
+ <match type="big16" value="0xFFFE" offset="16"/>
</match>
</match>
</match>
</magic>
- <magic priority="50">
- <match value="0x0011" type="big16" offset="522">
- <match value="0x02FF" type="big16" offset="524">
- <match value="0x0C00" type="big16" offset="526">
- <match value="0xFFFE" type="big16" offset="528"/>
+ <magic>
+ <match type="big16" value="0x0011" offset="522">
+ <match type="big16" value="0x02FF" offset="524">
+ <match type="big16" value="0x0C00" offset="526">
+ <match type="big16" value="0xFFFE" offset="528"/>
</match>
</match>
</match>
@@ -25904,52 +28290,57 @@
</mime-type>
<mime-type type="application/x-ufraw">
<comment>UFRaw ID image</comment>
- <comment xml:lang="ar">صورة UFRaw ID</comment>
- <comment xml:lang="be@latin">Vyjava UFRaw ID</comment>
- <comment xml:lang="bg">Изображение — UFRaw ID</comment>
- <comment xml:lang="ca">imatge ID UFRaw</comment>
- <comment xml:lang="cs">obrázek ID UFRaw</comment>
- <comment xml:lang="da">UFRaw ID-billede</comment>
- <comment xml:lang="de">UFRaw-Bildbeschreibungsdatei</comment>
- <comment xml:lang="el">Εικόνα UFRaw</comment>
- <comment xml:lang="en_GB">UFRaw ID image</comment>
- <comment xml:lang="es">imagen de identificación UFRaw</comment>
- <comment xml:lang="eu">UFRaw ID irudia</comment>
- <comment xml:lang="fi">UFRaw ID -kuva</comment>
- <comment xml:lang="fo">UFRaw ID mynd</comment>
- <comment xml:lang="fr">image ID UFRaw</comment>
- <comment xml:lang="ga">íomhá aitheantais UFRaw</comment>
- <comment xml:lang="gl">imaxe de identificación UFRaw</comment>
- <comment xml:lang="he">תמונה של UFRaw ID</comment>
- <comment xml:lang="hr">UFRaw ID slika</comment>
- <comment xml:lang="hu">UFRaw azonosítófájl</comment>
- <comment xml:lang="ia">Imagine UFRaw ID</comment>
- <comment xml:lang="id">Citra UFRaw ID</comment>
- <comment xml:lang="it">Immagine UFRaw ID</comment>
- <comment xml:lang="ja">UFRaw ID イメージ</comment>
- <comment xml:lang="kk">UFRaw ID суреті</comment>
- <comment xml:lang="ko">UFRaw ID 그림</comment>
- <comment xml:lang="lt">UFRaw ID paveikslėlis</comment>
- <comment xml:lang="lv">UFRaw ID attēls</comment>
- <comment xml:lang="nb">UFRaw ID-bilde</comment>
- <comment xml:lang="nl">UFRaw ID-afbeelding</comment>
- <comment xml:lang="nn">UFRaw ID-bilete</comment>
- <comment xml:lang="oc">imatge ID UFRaw</comment>
- <comment xml:lang="pl">Obraz UFRaw ID</comment>
- <comment xml:lang="pt">imagem UFRaw ID</comment>
- <comment xml:lang="pt_BR">Imagem ID do UFRaw</comment>
- <comment xml:lang="ro">ID imagine UFRaw</comment>
- <comment xml:lang="ru">Изображение UFRaw ID</comment>
- <comment xml:lang="sk">Obrázok ID UFRaw</comment>
- <comment xml:lang="sl">Slikovna datoteka UFRaw ID</comment>
- <comment xml:lang="sq">Figurë UFRaw ID</comment>
- <comment xml:lang="sr">УФ сирова ИД слика</comment>
- <comment xml:lang="sv">UFRaw ID-bild</comment>
- <comment xml:lang="tr">UFRaw ID görüntüsü</comment>
- <comment xml:lang="uk">зображення UFRaw ID</comment>
- <comment xml:lang="vi">Ảnh ID UFRaw</comment>
- <comment xml:lang="zh_CN">UFRaw ID 图像</comment>
<comment xml:lang="zh_TW">UFRaw ID 影像</comment>
+ <comment xml:lang="zh_CN">UFRaw ID 图像</comment>
+ <comment xml:lang="vi">Ảnh ID UFRaw</comment>
+ <comment xml:lang="uk">зображення UFRaw ID</comment>
+ <comment xml:lang="tr">UFRaw ID görüntüsü</comment>
+ <comment xml:lang="sv">UFRaw ID-bild</comment>
+ <comment xml:lang="sr">УФ сирова ИД слика</comment>
+ <comment xml:lang="sq">figurë UFRaw ID</comment>
+ <comment xml:lang="sl">Slikovna datoteka UFRaw ID</comment>
+ <comment xml:lang="si">UFRaw ID රූපය</comment>
+ <comment xml:lang="sk">Obrázok ID UFRaw</comment>
+ <comment xml:lang="ru">Изображение UFRaw ID</comment>
+ <comment xml:lang="ro">ID imagine UFRaw</comment>
+ <comment xml:lang="pt_BR">Imagem ID do UFRaw</comment>
+ <comment xml:lang="pt">imagem UFRaw ID</comment>
+ <comment xml:lang="pl">Obraz UFRaw ID</comment>
+ <comment xml:lang="oc">imatge ID UFRaw</comment>
+ <comment xml:lang="nn">UFRaw ID-bilete</comment>
+ <comment xml:lang="nl">UFRaw ID-afbeelding</comment>
+ <comment xml:lang="nb">UFRaw ID-bilde</comment>
+ <comment xml:lang="lv">UFRaw ID attēls</comment>
+ <comment xml:lang="lt">UFRaw ID paveikslėlis</comment>
+ <comment xml:lang="ko">UFRaw ID 그림</comment>
+ <comment xml:lang="kk">UFRaw ID суреті</comment>
+ <comment xml:lang="ja">UFRaw ID イメージ</comment>
+ <comment xml:lang="it">Immagine UFRaw ID</comment>
+ <comment xml:lang="is">UFRaw ID mynd</comment>
+ <comment xml:lang="id">Citra UFRaw ID</comment>
+ <comment xml:lang="ia">Imagine UFRaw ID</comment>
+ <comment xml:lang="hu">UFRaw azonosítófájl</comment>
+ <comment xml:lang="hr">UFRaw ID slika</comment>
+ <comment xml:lang="he">תמונה של UFRaw ID</comment>
+ <comment xml:lang="gl">imaxe de identificación UFRaw</comment>
+ <comment xml:lang="ga">íomhá aitheantais UFRaw</comment>
+ <comment xml:lang="fur">imagjin UFRaw ID</comment>
+ <comment xml:lang="fr">image ID UFRaw</comment>
+ <comment xml:lang="fo">UFRaw ID mynd</comment>
+ <comment xml:lang="fi">UFRaw ID -kuva</comment>
+ <comment xml:lang="eu">UFRaw ID irudia</comment>
+ <comment xml:lang="es">imagen de identificación UFRaw</comment>
+ <comment xml:lang="en_GB">UFRaw ID image</comment>
+ <comment xml:lang="el">Εικόνα UFRaw</comment>
+ <comment xml:lang="de">UFRaw-Bildbeschreibungsdatei</comment>
+ <comment xml:lang="da">UFRaw ID-billede</comment>
+ <comment xml:lang="cs">obrázek ID UFRaw</comment>
+ <comment xml:lang="ca">imatge ID UFRaw</comment>
+ <comment xml:lang="bg">Изображение — UFRaw ID</comment>
+ <comment xml:lang="be@latin">Vyjava UFRaw ID</comment>
+ <comment xml:lang="be">выява UFRaw ID</comment>
+ <comment xml:lang="ar">صورة UFRaw ID</comment>
+ <comment xml:lang="af">UFRaw ID-beeld</comment>
<acronym>UFRaw</acronym>
<expanded-acronym>Unidentified Flying Raw</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -25957,329 +28348,351 @@
<glob pattern="*.ufraw"/>
</mime-type>
<mime-type type="image/x-dcraw">
- <comment>digital raw image</comment>
- <comment xml:lang="ar">صورة رقمية خامة</comment>
- <comment xml:lang="be@latin">suvoraja ličbavaja vyjava</comment>
- <comment xml:lang="bg">Изображение — digital raw</comment>
- <comment xml:lang="ca">imatge digital en cru</comment>
- <comment xml:lang="cs">digitální surový obrázek</comment>
- <comment xml:lang="da">digitalt råbillede</comment>
- <comment xml:lang="de">Digitales Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη ψηφιακή εικόνα</comment>
- <comment xml:lang="en_GB">digital raw image</comment>
- <comment xml:lang="es">imagen digital en bruto</comment>
- <comment xml:lang="eu">irudi gordin digitala</comment>
- <comment xml:lang="fi">digitaalinen raakakuva</comment>
- <comment xml:lang="fo">talgild rámynd</comment>
- <comment xml:lang="fr">image brute numérique</comment>
- <comment xml:lang="ga">amhíomhá dhigiteach</comment>
- <comment xml:lang="gl">imaxe en bruto dixital</comment>
- <comment xml:lang="he">תמונה דיגטלית גולמית</comment>
- <comment xml:lang="hr">Digitalna osnovna slika</comment>
- <comment xml:lang="hu">digitális nyers kép</comment>
- <comment xml:lang="ia">Imagine brute digital</comment>
- <comment xml:lang="id">citra mentah digital</comment>
- <comment xml:lang="it">Immagine raw digitale</comment>
- <comment xml:lang="ja">デジタル raw 画像</comment>
- <comment xml:lang="kk">өңделмеген сандық суреттер</comment>
- <comment xml:lang="ko">디지털 원본 사진</comment>
- <comment xml:lang="lt">skaitmeninis neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">digitāls jēlattēls</comment>
- <comment xml:lang="nb">digitalt raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt digitaal beeld</comment>
- <comment xml:lang="nn">digitalt råbilete</comment>
- <comment xml:lang="oc">imatge brut numeric</comment>
- <comment xml:lang="pl">Surowy obraz cyfrowy</comment>
- <comment xml:lang="pt">imagem digital em bruto</comment>
- <comment xml:lang="pt_BR">Imagem digital bruta</comment>
- <comment xml:lang="ro">imagine digitală brută</comment>
+ <comment>Digital raw image</comment>
+ <comment xml:lang="uk">простий цифровий негатив</comment>
+ <comment xml:lang="sv">Digital råbild</comment>
<comment xml:lang="ru">Необработанное цифровое изображение</comment>
- <comment xml:lang="sk">Digitálny surový obrázok</comment>
- <comment xml:lang="sl">surova digitalna slika</comment>
- <comment xml:lang="sq">Figurë raw dixhitale</comment>
- <comment xml:lang="sr">дигитална сирова слика</comment>
- <comment xml:lang="sv">digital råbild</comment>
- <comment xml:lang="tr">sayısal ham görüntü</comment>
- <comment xml:lang="uk">зображення цифрового негатива</comment>
- <comment xml:lang="vi">ảnh thô số</comment>
- <comment xml:lang="zh_CN">数字化原始图像</comment>
- <comment xml:lang="zh_TW">數位原生影像</comment>
+ <comment xml:lang="pl">Surowy obraz cyfrowy</comment>
+ <comment xml:lang="ja">生写真</comment>
+ <comment xml:lang="it">Immagine raw digitale</comment>
+ <comment xml:lang="gl">Imaxe RAW dixital</comment>
+ <comment xml:lang="eu">Irudi digital gordina</comment>
+ <comment xml:lang="es">imagen digital en bruto</comment>
+ <comment xml:lang="de">Digitales Rohbild</comment>
+ <comment xml:lang="be">неапрацаваная лічбавая выява</comment>
</mime-type>
<mime-type type="image/x-adobe-dng">
<comment>Adobe DNG negative</comment>
- <comment xml:lang="ar">Adobe DNG negative</comment>
- <comment xml:lang="be@latin">Adobe DNG Negative</comment>
- <comment xml:lang="bg">Изображение — Adobe DNG negative</comment>
- <comment xml:lang="ca">negatiu DNG d'Adobe</comment>
- <comment xml:lang="cs">negativ Adobe (DNG)</comment>
- <comment xml:lang="da">Adobe DNG-negativ</comment>
- <comment xml:lang="de">Adobe Digitales Negativ</comment>
- <comment xml:lang="el">Αρνητικό Adobe DNG</comment>
- <comment xml:lang="en_GB">Adobe DNG negative</comment>
- <comment xml:lang="es">negativo DNG de Adobe</comment>
- <comment xml:lang="eu">Adobe DNG negatiboa</comment>
- <comment xml:lang="fi">Adobe-DNG-negatiivi</comment>
- <comment xml:lang="fo">Adobe DNG negativ</comment>
- <comment xml:lang="fr">négatif DNG Adobe</comment>
- <comment xml:lang="ga">claonchló DNG Adobe</comment>
- <comment xml:lang="gl">negativo DNG de Adobe</comment>
- <comment xml:lang="he">תשליל Adobe DNG</comment>
- <comment xml:lang="hr">Adobe DNG negativ</comment>
- <comment xml:lang="hu">Adobe DNG negatív</comment>
- <comment xml:lang="ia">Negativo Adobe DNG</comment>
- <comment xml:lang="id">Negatif Adobe DNG</comment>
- <comment xml:lang="it">Negativo Adobe DNG</comment>
- <comment xml:lang="ja">Adobe DNG ネガ</comment>
- <comment xml:lang="ka">Adobe DNG-ის ნეგატივი</comment>
- <comment xml:lang="kk">Adobe DNG негативі</comment>
- <comment xml:lang="ko">Adobe DNG 네거티브</comment>
- <comment xml:lang="lt">Adobe DNG negatyvas</comment>
- <comment xml:lang="lv">Adobe DNG negatīvs</comment>
- <comment xml:lang="nb">Adobe DNG-negativ</comment>
- <comment xml:lang="nl">Adobe DNG-negatief</comment>
- <comment xml:lang="nn">Adobe DNG-negativ</comment>
- <comment xml:lang="oc">négatif DNG Adobe</comment>
- <comment xml:lang="pl">Negatyw DNG Adobe</comment>
- <comment xml:lang="pt">negativo Adobe DNG</comment>
- <comment xml:lang="pt_BR">Negativo DNG da Adobe</comment>
- <comment xml:lang="ro">Negativ Adobe DNG</comment>
- <comment xml:lang="ru">Негатив Adobe DNG</comment>
- <comment xml:lang="sk">Adobe Digital Negative (DNG)</comment>
- <comment xml:lang="sl">Datoteka negativa Adobe DNG</comment>
- <comment xml:lang="sq">Negativ Adobe DNG</comment>
- <comment xml:lang="sr">Адобов ДНГ негатив</comment>
- <comment xml:lang="sv">Adobe DNG-negativ</comment>
- <comment xml:lang="tr">Adobe DNG negatifi</comment>
- <comment xml:lang="uk">цифровий негатив DNG Adobe</comment>
- <comment xml:lang="vi">Âm bản Adobe DNG</comment>
- <comment xml:lang="zh_CN">Adobe DNG 负片</comment>
<comment xml:lang="zh_TW">Adobe DNG 負片</comment>
+ <comment xml:lang="zh_CN">Adobe DNG 负片</comment>
+ <comment xml:lang="vi">Âm bản Adobe DNG</comment>
+ <comment xml:lang="uk">цифровий негатив DNG Adobe</comment>
+ <comment xml:lang="tr">Adobe DNG negatifi</comment>
+ <comment xml:lang="sv">Adobe DNG-negativ</comment>
+ <comment xml:lang="sr">Адобов ДНГ негатив</comment>
+ <comment xml:lang="sq">negativ Adobe DNG</comment>
+ <comment xml:lang="sl">Datoteka negativa Adobe DNG</comment>
+ <comment xml:lang="si">Adobe DNG සෘණ</comment>
+ <comment xml:lang="sk">Adobe Digital Negative (DNG)</comment>
+ <comment xml:lang="ru">Негатив Adobe DNG</comment>
+ <comment xml:lang="ro">Negativ Adobe DNG</comment>
+ <comment xml:lang="pt_BR">Negativo DNG da Adobe</comment>
+ <comment xml:lang="pt">negativo Adobe DNG</comment>
+ <comment xml:lang="pl">Negatyw DNG Adobe</comment>
+ <comment xml:lang="oc">négatif DNG Adobe</comment>
+ <comment xml:lang="nn">Adobe DNG-negativ</comment>
+ <comment xml:lang="nl">Adobe DNG-negatief</comment>
+ <comment xml:lang="nb">Adobe DNG-negativ</comment>
+ <comment xml:lang="lv">Adobe DNG negatīvs</comment>
+ <comment xml:lang="lt">Adobe DNG negatyvas</comment>
+ <comment xml:lang="ko">Adobe DNG 네거티브</comment>
+ <comment xml:lang="kk">Adobe DNG негативі</comment>
+ <comment xml:lang="ka">Adobe DNG-ის ნეგატივი</comment>
+ <comment xml:lang="ja">Adobe DNG ネガ</comment>
+ <comment xml:lang="it">Negativo Adobe DNG</comment>
+ <comment xml:lang="is">Adobe DNG negatíva</comment>
+ <comment xml:lang="id">Negatif Adobe DNG</comment>
+ <comment xml:lang="ia">Negativo Adobe DNG</comment>
+ <comment xml:lang="hu">Adobe DNG negatív</comment>
+ <comment xml:lang="hr">Adobe DNG negativ</comment>
+ <comment xml:lang="he">תשליל Adobe DNG</comment>
+ <comment xml:lang="gl">negativo DNG de Adobe</comment>
+ <comment xml:lang="ga">claonchló DNG Adobe</comment>
+ <comment xml:lang="fur">negatîf Adobe DNG</comment>
+ <comment xml:lang="fr">négatif DNG Adobe</comment>
+ <comment xml:lang="fo">Adobe DNG negativ</comment>
+ <comment xml:lang="fi">Adobe-DNG-negatiivi</comment>
+ <comment xml:lang="eu">Adobe DNG negatiboa</comment>
+ <comment xml:lang="es">negativo DNG de Adobe</comment>
+ <comment xml:lang="en_GB">Adobe DNG negative</comment>
+ <comment xml:lang="el">Αρνητικό Adobe DNG</comment>
+ <comment xml:lang="de">Adobe Digitales Negativ</comment>
+ <comment xml:lang="da">Adobe DNG-negativ</comment>
+ <comment xml:lang="cs">negativ Adobe (DNG)</comment>
+ <comment xml:lang="ca">negatiu DNG d'Adobe</comment>
+ <comment xml:lang="bg">Изображение — Adobe DNG negative</comment>
+ <comment xml:lang="be@latin">Adobe DNG Negative</comment>
+ <comment xml:lang="be">Adobe DNG Negative</comment>
+ <comment xml:lang="ar">سالبة Adobe DNG</comment>
+ <comment xml:lang="af">Adobe DNG-negatief</comment>
<acronym>DNG</acronym>
<expanded-acronym>Digital Negative</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
<sub-class-of type="image/tiff"/>
<glob pattern="*.dng"/>
</mime-type>
-
-
+ <!-- Canon has 3 formats: CRW, CR2 and CR3 !-->
+ <!-- CRW is easy !-->
<mime-type type="image/x-canon-crw">
<comment>Canon CRW raw image</comment>
- <comment xml:lang="ar">صورة Canon CRW خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Canon CRW</comment>
- <comment xml:lang="bg">Изображение — Canon CRW raw</comment>
- <comment xml:lang="ca">imatge en cru de Canon CRW</comment>
- <comment xml:lang="cs">surový obrázek Canon CRW</comment>
- <comment xml:lang="da">Canon CRW-råbillede</comment>
- <comment xml:lang="de">Canon-CRW-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Canon CRW</comment>
- <comment xml:lang="en_GB">Canon CRW raw image</comment>
- <comment xml:lang="es">imagen en bruto CRW de Canon</comment>
- <comment xml:lang="eu">Canon CRW irudi gordina</comment>
- <comment xml:lang="fi">Canon-CRW-raakakuva</comment>
- <comment xml:lang="fo">Canon CRW rámynd</comment>
- <comment xml:lang="fr">image brute CRW Canon</comment>
- <comment xml:lang="ga">amhíomhá Canon CRW</comment>
- <comment xml:lang="gl">imaxe en bruto de Canon CRW</comment>
- <comment xml:lang="he">תמונה גולמית של Canon CRW</comment>
- <comment xml:lang="hr">Canon CRW osnovna slika</comment>
- <comment xml:lang="hu">Canon CRW nyers kép</comment>
- <comment xml:lang="ia">Imagine brute CRW Canon</comment>
- <comment xml:lang="id">Citra mentah Canon CRW</comment>
- <comment xml:lang="it">Immagine raw Canon CRW</comment>
- <comment xml:lang="ja">Canon CRW raw 画像</comment>
- <comment xml:lang="ka">Canon CRW raw გამოსახულება</comment>
- <comment xml:lang="kk">Canon CRW өңделмеген суреті</comment>
- <comment xml:lang="ko">캐논 CRW RAW 사진</comment>
- <comment xml:lang="lt">Canon CRW neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Canon CRW jēlattēls</comment>
- <comment xml:lang="nb">Canon CRW raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Canon CRW-beeld</comment>
- <comment xml:lang="nn">Canon CRW råbilete</comment>
- <comment xml:lang="oc">imatge brut CRW Canon</comment>
- <comment xml:lang="pl">Surowy obraz CRW Canon</comment>
- <comment xml:lang="pt">imagem em bruto Canon CRW</comment>
- <comment xml:lang="pt_BR">Imagem bruta CRW da Canon</comment>
- <comment xml:lang="ro">Imagine brută Canon CRW</comment>
- <comment xml:lang="ru">Необработанное изображение Canon CRW</comment>
- <comment xml:lang="sk">Surový obrázok Canon CRW</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Canon CRW</comment>
- <comment xml:lang="sq">Figurë raw Canon CRW</comment>
- <comment xml:lang="sr">Кенон ЦРВ сирова слика</comment>
- <comment xml:lang="sv">Canon CRW-råbild</comment>
- <comment xml:lang="tr">Canon CRW ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив CRW Canon</comment>
- <comment xml:lang="vi">Ảnh thô Canon CRW</comment>
+ <comment xml:lang="zh_TW">Canon CRW 原始影像</comment>
<comment xml:lang="zh_CN">佳能 CRW 原始图像</comment>
- <comment xml:lang="zh_TW">Canon CRW 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Canon CRW</comment>
+ <comment xml:lang="uk">цифровий негатив CRW Canon</comment>
+ <comment xml:lang="tr">Canon CRW ham görüntüsü</comment>
+ <comment xml:lang="sv">Canon CRW-råbild</comment>
+ <comment xml:lang="sr">Кенон ЦРВ сирова слика</comment>
+ <comment xml:lang="sq">figurë Canon CRW e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Canon CRW</comment>
+ <comment xml:lang="si">Canon CRW අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Canon CRW</comment>
+ <comment xml:lang="ru">Необработанное изображение Canon CRW</comment>
+ <comment xml:lang="ro">Imagine brută Canon CRW</comment>
+ <comment xml:lang="pt_BR">Imagem bruta CRW da Canon</comment>
+ <comment xml:lang="pt">imagem em bruto Canon CRW</comment>
+ <comment xml:lang="pl">Surowy obraz CRW Canon</comment>
+ <comment xml:lang="oc">imatge brut CRW Canon</comment>
+ <comment xml:lang="nn">Canon CRW råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Canon CRW-beeld</comment>
+ <comment xml:lang="nb">Canon CRW raw-bilde</comment>
+ <comment xml:lang="lv">Canon CRW jēlattēls</comment>
+ <comment xml:lang="lt">Canon CRW neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">캐논 CRW RAW 사진</comment>
+ <comment xml:lang="kk">Canon CRW өңделмеген суреті</comment>
+ <comment xml:lang="ka">Canon CRW raw გამოსახულება</comment>
+ <comment xml:lang="ja">Canon CRW raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Canon CRW</comment>
+ <comment xml:lang="is">Canon CRW hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Canon CRW</comment>
+ <comment xml:lang="ia">Imagine brute CRW Canon</comment>
+ <comment xml:lang="hu">Canon CRW nyers kép</comment>
+ <comment xml:lang="hr">Canon CRW osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Canon CRW</comment>
+ <comment xml:lang="gl">imaxe en bruto de Canon CRW</comment>
+ <comment xml:lang="ga">amhíomhá Canon CRW</comment>
+ <comment xml:lang="fur">imagjin grese Canon CRW</comment>
+ <comment xml:lang="fr">image brute CRW Canon</comment>
+ <comment xml:lang="fo">Canon CRW rámynd</comment>
+ <comment xml:lang="fi">Canon-CRW-raakakuva</comment>
+ <comment xml:lang="eu">Canon CRW irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto CRW de Canon</comment>
+ <comment xml:lang="en_GB">Canon CRW raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Canon CRW</comment>
+ <comment xml:lang="de">Canon-CRW-Rohbild</comment>
+ <comment xml:lang="da">Canon CRW raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Canon CRW</comment>
+ <comment xml:lang="ca">imatge en cru de Canon CRW</comment>
+ <comment xml:lang="bg">Изображение — Canon CRW raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Canon CRW</comment>
+ <comment xml:lang="be">неапрацаваная выява Canon CRW</comment>
+ <comment xml:lang="ar">صورة Canon CRW خامة</comment>
+ <comment xml:lang="af">Canon CRW rou beeld</comment>
<acronym>CRW</acronym>
<expanded-acronym>Canon RaW</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
+ <magic>
<match value="II\x1a\x00\x00\x00HEAPCCDR" type="string" offset="0"/>
</magic>
<glob pattern="*.crw"/>
</mime-type>
-
+ <!-- CR2 is a TIFF !-->
<mime-type type="image/x-canon-cr2">
<comment>Canon CR2 raw image</comment>
- <comment xml:lang="ar">صورة Canon CR2 خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Canon CR2</comment>
- <comment xml:lang="bg">Изображение — Canon CR2 raw</comment>
- <comment xml:lang="ca">imatge en cru de Canon CR2</comment>
- <comment xml:lang="cs">surový obrázek Canon CR2</comment>
- <comment xml:lang="da">Canon CR2-råbillede</comment>
- <comment xml:lang="de">Canon-CR2-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Canon CR2</comment>
- <comment xml:lang="en_GB">Canon CR2 raw image</comment>
- <comment xml:lang="es">imagen en bruto CR2 de Canon</comment>
- <comment xml:lang="eu">Canon CR2 irudi gordina</comment>
- <comment xml:lang="fi">Canon-CR2-raakakuva</comment>
- <comment xml:lang="fo">Canon CR2 rámynd</comment>
- <comment xml:lang="fr">image brute CR2 Canon</comment>
- <comment xml:lang="ga">amhíomhá Canon CR2</comment>
- <comment xml:lang="gl">imaxe en bruto de Canon CR2</comment>
- <comment xml:lang="he">תמונה גולמית של Canon CR2</comment>
- <comment xml:lang="hr">Canon CR2 osnovna slika</comment>
- <comment xml:lang="hu">Canon CR2 nyers kép</comment>
- <comment xml:lang="ia">Imagine brute CR2 Canon</comment>
- <comment xml:lang="id">Citra mentah Canon CR2</comment>
- <comment xml:lang="it">Immagine raw Canon CR2</comment>
- <comment xml:lang="ja">Canon CR2 raw 画像</comment>
- <comment xml:lang="ka">Canon CR2 raw გამოსახულება</comment>
- <comment xml:lang="kk">Canon CR2 өңделмеген суреті</comment>
- <comment xml:lang="ko">캐논 CR2 RAW 사진</comment>
- <comment xml:lang="lt">Canon CR2 neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Canon CR2 jēlattēls</comment>
- <comment xml:lang="nb">Canon CR2 raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Canon CR2-beeld</comment>
- <comment xml:lang="nn">Canon CR2 råbilete</comment>
- <comment xml:lang="oc">imatge brut CR2 Canon</comment>
- <comment xml:lang="pl">Surowy obraz CR2 Canon</comment>
- <comment xml:lang="pt">imagem em bruto Canon CR2</comment>
- <comment xml:lang="pt_BR">Imagem bruta CR2 da Canon</comment>
- <comment xml:lang="ro">Imagine brută Canon CR2</comment>
- <comment xml:lang="ru">Необработанное изображение Canon CR2</comment>
- <comment xml:lang="sk">Surový obrázok Canon CR2</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Canon CR2</comment>
- <comment xml:lang="sq">Figurë raw Canon CR2</comment>
- <comment xml:lang="sr">Кенон ЦР2 сирова слика</comment>
- <comment xml:lang="sv">Canon CR2-råbild</comment>
- <comment xml:lang="tr">Canon CR2 ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив CR2 Canon</comment>
- <comment xml:lang="vi">Ảnh thô Canon CR2</comment>
+ <comment xml:lang="zh_TW">Canon CR2 原始影像</comment>
<comment xml:lang="zh_CN">佳能 CR2 原始图像</comment>
- <comment xml:lang="zh_TW">Canon CR2 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Canon CR2</comment>
+ <comment xml:lang="uk">цифровий негатив CR2 Canon</comment>
+ <comment xml:lang="tr">Canon CR2 ham görüntüsü</comment>
+ <comment xml:lang="sv">Canon CR2-råbild</comment>
+ <comment xml:lang="sr">Кенон ЦР2 сирова слика</comment>
+ <comment xml:lang="sq">figurë Canon CR2 e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Canon CR2</comment>
+ <comment xml:lang="si">Canon CR2 අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Canon CR2</comment>
+ <comment xml:lang="ru">Необработанное изображение Canon CR2</comment>
+ <comment xml:lang="ro">Imagine brută Canon CR2</comment>
+ <comment xml:lang="pt_BR">Imagem bruta CR2 da Canon</comment>
+ <comment xml:lang="pt">imagem em bruto Canon CR2</comment>
+ <comment xml:lang="pl">Surowy obraz CR2 Canon</comment>
+ <comment xml:lang="oc">imatge brut CR2 Canon</comment>
+ <comment xml:lang="nn">Canon CR2 råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Canon CR2-beeld</comment>
+ <comment xml:lang="nb">Canon CR2 raw-bilde</comment>
+ <comment xml:lang="lv">Canon CR2 jēlattēls</comment>
+ <comment xml:lang="lt">Canon CR2 neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">캐논 CR2 RAW 사진</comment>
+ <comment xml:lang="kk">Canon CR2 өңделмеген суреті</comment>
+ <comment xml:lang="ka">Canon CR2 raw გამოსახულება</comment>
+ <comment xml:lang="ja">Canon CR2 raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Canon CR2</comment>
+ <comment xml:lang="is">Canon CR2 hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Canon CR2</comment>
+ <comment xml:lang="ia">Imagine brute CR2 Canon</comment>
+ <comment xml:lang="hu">Canon CR2 nyers kép</comment>
+ <comment xml:lang="hr">Canon CR2 osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Canon CR2</comment>
+ <comment xml:lang="gl">imaxe en bruto de Canon CR2</comment>
+ <comment xml:lang="ga">amhíomhá Canon CR2</comment>
+ <comment xml:lang="fur">imagjin grese Canon CR2</comment>
+ <comment xml:lang="fr">image brute CR2 Canon</comment>
+ <comment xml:lang="fo">Canon CR2 rámynd</comment>
+ <comment xml:lang="fi">Canon-CR2-raakakuva</comment>
+ <comment xml:lang="eu">Canon CR2 irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto CR2 de Canon</comment>
+ <comment xml:lang="en_GB">Canon CR2 raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Canon CR2</comment>
+ <comment xml:lang="de">Canon-CR2-Rohbild</comment>
+ <comment xml:lang="da">Canon CR2 raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Canon CR2</comment>
+ <comment xml:lang="ca">imatge en cru de Canon CR2</comment>
+ <comment xml:lang="bg">Изображение — Canon CR2 raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Canon CR2</comment>
+ <comment xml:lang="be">неапрацаваная выява Canon CR2</comment>
+ <comment xml:lang="ar">صورة Canon CR2 خامة</comment>
+ <comment xml:lang="af">Canon CR2 rou beeld</comment>
<acronym>CR2</acronym>
<expanded-acronym>Canon Raw 2</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
<sub-class-of type="image/tiff"/>
<glob pattern="*.cr2"/>
</mime-type>
+ <mime-type type="image/x-canon-cr3">
+ <comment>Canon CR3 raw image</comment>
+ <comment xml:lang="zh_TW">Canon CR3 原始影像</comment>
+ <comment xml:lang="zh_CN">佳能 CR3 原始图像</comment>
+ <comment xml:lang="uk">цифровий негатив CR3 Canon</comment>
+ <comment xml:lang="tr">Canon CR3 ham görüntüsü</comment>
+ <comment xml:lang="sv">Canon CR3-råbild</comment>
+ <comment xml:lang="sl">Neobdelana slika Canon CR3</comment>
+ <comment xml:lang="si">Canon CR3 අමු රූපය</comment>
+ <comment xml:lang="ru">Необработанное изображение Canon CR3</comment>
+ <comment xml:lang="pt_BR">Imagem bruta CR3 da Canon</comment>
+ <comment xml:lang="pl">Surowy obraz CR3 Canon</comment>
+ <comment xml:lang="oc">imatge brut Canon CR3</comment>
+ <comment xml:lang="nl">onbewerkt Canon CR3 beeld</comment>
+ <comment xml:lang="ko">캐논 CR3 RAW 사진</comment>
+ <comment xml:lang="kk">Canon CR3 өңделмеген суреті</comment>
+ <comment xml:lang="ja">Canon CR3 raw 画像ファイル</comment>
+ <comment xml:lang="it">Immagine raw Canon CR3</comment>
+ <comment xml:lang="hr">Canon CR3 osnovna slika</comment>
+ <comment xml:lang="gl">Imaxe RAW de Canon CR3</comment>
+ <comment xml:lang="fi">Canon CR3-raakakuva</comment>
+ <comment xml:lang="eu">Canon CR3 irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto CR3 de Canon</comment>
+ <comment xml:lang="en_GB">Canon CR3 raw image</comment>
+ <comment xml:lang="de">Canon-CR3-Rohbild</comment>
+ <comment xml:lang="be">неапрацаваная выява Canon CR3</comment>
+ <comment xml:lang="ar">صورة Canon CR3 خامة</comment>
+ <acronym>CR3</acronym>
+ <expanded-acronym>Canon Raw 3</expanded-acronym>
+ <sub-class-of type="image/x-dcraw"/>
+ <glob pattern="*.cr3"/>
+ </mime-type>
<mime-type type="image/x-fuji-raf">
<comment>Fuji RAF raw image</comment>
- <comment xml:lang="ar">صورة Fuji RAF خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Fuji RAF</comment>
- <comment xml:lang="bg">Изображение — Fuji RAF raw</comment>
- <comment xml:lang="ca">imatge en cru de Fuji RAF</comment>
- <comment xml:lang="cs">surový obrázek Fuji RAF</comment>
- <comment xml:lang="da">Fuji RAF-råbillede</comment>
- <comment xml:lang="de">Fuji-RAF-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Fuji RAF</comment>
- <comment xml:lang="en_GB">Fuji RAF raw image</comment>
- <comment xml:lang="es">imagen en bruto RAF de Fuji</comment>
- <comment xml:lang="eu">Fuji RAF irudi gordina</comment>
- <comment xml:lang="fi">Fuji-RAF-raakakuva</comment>
- <comment xml:lang="fo">Fuji RAF raw mynd</comment>
- <comment xml:lang="fr">image brute RAF Fuji</comment>
- <comment xml:lang="ga">amhíomhá Fuji RAF</comment>
- <comment xml:lang="gl">imaxe en bruto de Fuji RAF</comment>
- <comment xml:lang="he">תמונה גולמית של Fuji RAF</comment>
- <comment xml:lang="hr">Fuji RAF osnovna slika</comment>
- <comment xml:lang="hu">Fuji RAF nyers kép</comment>
- <comment xml:lang="ia">Imagine brute RAF de Fuji</comment>
- <comment xml:lang="id">Citra mentah Fuji RAF</comment>
- <comment xml:lang="it">Immagine raw Fuji RAF</comment>
- <comment xml:lang="ja">Fuji RAF raw 画像</comment>
- <comment xml:lang="ka">Fuji RAF-ის raw გამოსახულება</comment>
- <comment xml:lang="kk">Fuji RAF өңделмеген суреті</comment>
- <comment xml:lang="ko">후지 RAF RAW 사진</comment>
- <comment xml:lang="lt">Fuji RAF neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Fuji RAF jēlattēls</comment>
- <comment xml:lang="nb">Fuji RAF raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Fuji RAF-beeld</comment>
- <comment xml:lang="nn">Fuji RAF rått bilete</comment>
- <comment xml:lang="oc">imatge brut RAF Fuji</comment>
- <comment xml:lang="pl">Surowy obraz RAF Fuji</comment>
- <comment xml:lang="pt">imagem em bruto Fuji RAF</comment>
- <comment xml:lang="pt_BR">Imagem bruta RAF da Fuji</comment>
- <comment xml:lang="ro">Imagine brută Fuji RAF</comment>
- <comment xml:lang="ru">Необработанное изображение Fuji RAF</comment>
- <comment xml:lang="sk">Surový obrázok Fuji RAF</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Fuji RAF</comment>
- <comment xml:lang="sq">Figurë raw Fuji RAF</comment>
- <comment xml:lang="sr">Фуџи РАФ сирова слика</comment>
- <comment xml:lang="sv">Fuji RAF-råbild</comment>
- <comment xml:lang="tr">Fuji RAF ham görüntüsü</comment>
- <comment xml:lang="uk">Цифровий негатив RAF Fuji</comment>
- <comment xml:lang="vi">Ảnh thô Fuji RAF</comment>
+ <comment xml:lang="zh_TW">Fuji RAF 原始影像</comment>
<comment xml:lang="zh_CN">富士 RAF 原始图像</comment>
- <comment xml:lang="zh_TW">Fuji RAF 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Fuji RAF</comment>
+ <comment xml:lang="uk">Цифровий негатив RAF Fuji</comment>
+ <comment xml:lang="tr">Fuji RAF ham görüntüsü</comment>
+ <comment xml:lang="sv">Fuji RAF-råbild</comment>
+ <comment xml:lang="sr">Фуџи РАФ сирова слика</comment>
+ <comment xml:lang="sq">figurë Fuji RAF e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Fuji RAF</comment>
+ <comment xml:lang="si">Fuji RAF අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Fuji RAF</comment>
+ <comment xml:lang="ru">Необработанное изображение Fuji RAF</comment>
+ <comment xml:lang="ro">Imagine brută Fuji RAF</comment>
+ <comment xml:lang="pt_BR">Imagem bruta RAF da Fuji</comment>
+ <comment xml:lang="pt">imagem em bruto Fuji RAF</comment>
+ <comment xml:lang="pl">Surowy obraz RAF Fuji</comment>
+ <comment xml:lang="oc">imatge brut RAF Fuji</comment>
+ <comment xml:lang="nn">Fuji RAF rått bilete</comment>
+ <comment xml:lang="nl">onbewerkt Fuji RAF-beeld</comment>
+ <comment xml:lang="nb">Fuji RAF raw-bilde</comment>
+ <comment xml:lang="lv">Fuji RAF jēlattēls</comment>
+ <comment xml:lang="lt">Fuji RAF neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">후지 RAF RAW 사진</comment>
+ <comment xml:lang="kk">Fuji RAF өңделмеген суреті</comment>
+ <comment xml:lang="ka">Fuji RAF-ის raw გამოსახულება</comment>
+ <comment xml:lang="ja">Fuji RAF raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Fuji RAF</comment>
+ <comment xml:lang="is">Fuji RAF hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Fuji RAF</comment>
+ <comment xml:lang="ia">Imagine brute RAF de Fuji</comment>
+ <comment xml:lang="hu">Fuji RAF nyers kép</comment>
+ <comment xml:lang="hr">Fuji RAF osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Fuji RAF</comment>
+ <comment xml:lang="gl">imaxe en bruto de Fuji RAF</comment>
+ <comment xml:lang="ga">amhíomhá Fuji RAF</comment>
+ <comment xml:lang="fur">imagjin grese Fuji RAF</comment>
+ <comment xml:lang="fr">image brute RAF Fuji</comment>
+ <comment xml:lang="fo">Fuji RAF raw mynd</comment>
+ <comment xml:lang="fi">Fuji-RAF-raakakuva</comment>
+ <comment xml:lang="eu">Fuji RAF irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto RAF de Fuji</comment>
+ <comment xml:lang="en_GB">Fuji RAF raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Fuji RAF</comment>
+ <comment xml:lang="de">Fuji-RAF-Rohbild</comment>
+ <comment xml:lang="da">Fuji RAF raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Fuji RAF</comment>
+ <comment xml:lang="ca">imatge en cru de Fuji RAF</comment>
+ <comment xml:lang="bg">Изображение — Fuji RAF raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Fuji RAF</comment>
+ <comment xml:lang="be">неапрацаваная выява Fuji RAF</comment>
+ <comment xml:lang="ar">صورة Fuji RAF خامة</comment>
+ <comment xml:lang="af">Fuji RAF rou beeld</comment>
<acronym>RAF</acronym>
<expanded-acronym>RAw Format</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
+ <magic>
<match value="FUJIFILMCCD-RAW " type="string" offset="0"/>
</magic>
<glob pattern="*.raf"/>
</mime-type>
<mime-type type="image/x-kodak-dcr">
<comment>Kodak DCR raw image</comment>
- <comment xml:lang="ar">صورة Kodak DCR خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Kodak DCR</comment>
- <comment xml:lang="bg">Изображение — Kodak DCR raw</comment>
- <comment xml:lang="ca">imatge en cru de Kodak DCR</comment>
- <comment xml:lang="cs">surový obrázek Kodak DCR</comment>
- <comment xml:lang="da">Kodak DCR-råbillede</comment>
- <comment xml:lang="de">Kodak-DCR-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Kodak DCR</comment>
- <comment xml:lang="en_GB">Kodak DCR raw image</comment>
- <comment xml:lang="es">imagen en bruto DCR de Kodak</comment>
- <comment xml:lang="eu">Kodak DCR irudi gordina</comment>
- <comment xml:lang="fi">Kodak-DCR-raakakuva</comment>
- <comment xml:lang="fo">Kodak DCR rámynd</comment>
- <comment xml:lang="fr">image brute DCR Kodak</comment>
- <comment xml:lang="ga">amhíomhá Kodak DCR</comment>
- <comment xml:lang="gl">imaxe en bruto de Kodad DCR</comment>
- <comment xml:lang="he">תמונה גולמית של Kodak DCR</comment>
- <comment xml:lang="hr">Kodak DCR osnovna slika</comment>
- <comment xml:lang="hu">Kodak DCR nyers kép</comment>
- <comment xml:lang="ia">Imagine brute DCR de Kodak</comment>
- <comment xml:lang="id">Citra mentah Kodak DCR</comment>
- <comment xml:lang="it">Immagine raw Kodak DCR</comment>
- <comment xml:lang="ja">Kodak DCR raw 画像</comment>
- <comment xml:lang="kk">Kodak DCR өңделмеген суреті</comment>
- <comment xml:lang="ko">코닥 DCR RAW 사진</comment>
- <comment xml:lang="lt">Kodak DCR neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Kodak DCR jēlattēls</comment>
- <comment xml:lang="nb">Kodak DCR raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Kodak DCR-beeld</comment>
- <comment xml:lang="nn">Kodak DCR råbilete</comment>
- <comment xml:lang="oc">imatge brut DCR Kodak</comment>
- <comment xml:lang="pl">Surowy obraz DCR Kodak</comment>
- <comment xml:lang="pt">imagem em bruto Kodak DCR</comment>
- <comment xml:lang="pt_BR">Imagem bruta DCR da Kodak</comment>
- <comment xml:lang="ro">Imagine brută Kodak DCR</comment>
- <comment xml:lang="ru">Необработанное изображение Kodak DCR</comment>
- <comment xml:lang="sk">Surový obrázok Kodak DCR</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Kodak DCR</comment>
- <comment xml:lang="sq">Figurë raw Kodak DCR</comment>
- <comment xml:lang="sr">Кодак ДЦР сирова слика</comment>
- <comment xml:lang="sv">Kodak DCR-råbild</comment>
- <comment xml:lang="tr">Kodak DCR ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив DCR Kodak</comment>
- <comment xml:lang="vi">Ảnh thô Kodak DCR</comment>
+ <comment xml:lang="zh_TW">Kodak DCR 原始影像</comment>
<comment xml:lang="zh_CN">柯达 DCR 原始图像</comment>
- <comment xml:lang="zh_TW">Kodak DCR 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Kodak DCR</comment>
+ <comment xml:lang="uk">цифровий негатив DCR Kodak</comment>
+ <comment xml:lang="tr">Kodak DCR ham görüntüsü</comment>
+ <comment xml:lang="sv">Kodak DCR-råbild</comment>
+ <comment xml:lang="sr">Кодак ДЦР сирова слика</comment>
+ <comment xml:lang="sq">figurë Kodak DCR e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Kodak DCR</comment>
+ <comment xml:lang="si">Kodak DCR අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Kodak DCR</comment>
+ <comment xml:lang="ru">Необработанное изображение Kodak DCR</comment>
+ <comment xml:lang="ro">Imagine brută Kodak DCR</comment>
+ <comment xml:lang="pt_BR">Imagem bruta DCR da Kodak</comment>
+ <comment xml:lang="pt">imagem em bruto Kodak DCR</comment>
+ <comment xml:lang="pl">Surowy obraz DCR Kodak</comment>
+ <comment xml:lang="oc">imatge brut DCR Kodak</comment>
+ <comment xml:lang="nn">Kodak DCR råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Kodak DCR-beeld</comment>
+ <comment xml:lang="nb">Kodak DCR raw-bilde</comment>
+ <comment xml:lang="lv">Kodak DCR jēlattēls</comment>
+ <comment xml:lang="lt">Kodak DCR neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">코닥 DCR RAW 사진</comment>
+ <comment xml:lang="kk">Kodak DCR өңделмеген суреті</comment>
+ <comment xml:lang="ja">Kodak DCR raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Kodak DCR</comment>
+ <comment xml:lang="is">Kodak DCR hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Kodak DCR</comment>
+ <comment xml:lang="ia">Imagine brute DCR de Kodak</comment>
+ <comment xml:lang="hu">Kodak DCR nyers kép</comment>
+ <comment xml:lang="hr">Kodak DCR osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Kodak DCR</comment>
+ <comment xml:lang="gl">imaxe en bruto de Kodad DCR</comment>
+ <comment xml:lang="ga">amhíomhá Kodak DCR</comment>
+ <comment xml:lang="fur">imagjin grese Kodak DCR</comment>
+ <comment xml:lang="fr">image brute DCR Kodak</comment>
+ <comment xml:lang="fo">Kodak DCR rámynd</comment>
+ <comment xml:lang="fi">Kodak-DCR-raakakuva</comment>
+ <comment xml:lang="eu">Kodak DCR irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto DCR de Kodak</comment>
+ <comment xml:lang="en_GB">Kodak DCR raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Kodak DCR</comment>
+ <comment xml:lang="de">Kodak-DCR-Rohbild</comment>
+ <comment xml:lang="da">Kodak DCR raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Kodak DCR</comment>
+ <comment xml:lang="ca">imatge en cru de Kodak DCR</comment>
+ <comment xml:lang="bg">Изображение — Kodak DCR raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Kodak DCR</comment>
+ <comment xml:lang="be">неапрацаваная выява Kodak DCR</comment>
+ <comment xml:lang="ar">صورة Kodak DCR خامة</comment>
+ <comment xml:lang="af">Kodak DCR rou beeld</comment>
<acronym>DCR</acronym>
<expanded-acronym>Digital Camera Raw</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26288,52 +28701,57 @@
</mime-type>
<mime-type type="image/x-kodak-k25">
<comment>Kodak K25 raw image</comment>
- <comment xml:lang="ar">صورة Kodak K25 خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Kodak K25</comment>
- <comment xml:lang="bg">Изображение — Kodak K25 raw</comment>
- <comment xml:lang="ca">imatge en cru de Kodak K25</comment>
- <comment xml:lang="cs">surový obrázek Kodak K25</comment>
- <comment xml:lang="da">Kodak K25-råbillede</comment>
- <comment xml:lang="de">Kodak-K25-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Kodak K25</comment>
- <comment xml:lang="en_GB">Kodak K25 raw image</comment>
- <comment xml:lang="es">imagen en bruto K25 de Kodak</comment>
- <comment xml:lang="eu">Kodak K25 raw image</comment>
- <comment xml:lang="fi">Kodak-K25-raakakuva</comment>
- <comment xml:lang="fo">Kodak K25 rámynd</comment>
- <comment xml:lang="fr">image brute K25 Kodak</comment>
- <comment xml:lang="ga">amhíomhá Kodak K25</comment>
- <comment xml:lang="gl">imaxe en bruto de Kodad K25</comment>
- <comment xml:lang="he">תמונה גולמית של Kodak K25</comment>
- <comment xml:lang="hr">Kodak K25 osnovna slika</comment>
- <comment xml:lang="hu">Kodak K25 nyers kép</comment>
- <comment xml:lang="ia">Imagine brute K25 de Kodak</comment>
- <comment xml:lang="id">Citra mentah Kodak K25</comment>
- <comment xml:lang="it">Immagine raw Kodak K25</comment>
- <comment xml:lang="ja">Kodak K25 raw 画像</comment>
- <comment xml:lang="kk">Kodak K25 өңделмеген суреті</comment>
- <comment xml:lang="ko">코닥 K25 RAW 사진</comment>
- <comment xml:lang="lt">Kodak K25 neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Kodak K25 jēlattēls</comment>
- <comment xml:lang="nb">Kodak K25 raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Kodak K25-beeld</comment>
- <comment xml:lang="nn">Kodak K25 råbilete</comment>
- <comment xml:lang="oc">imatge brut K25 Kodak</comment>
- <comment xml:lang="pl">Surowy obraz K25 Kodak</comment>
- <comment xml:lang="pt">imagem em bruto Kodak K25</comment>
- <comment xml:lang="pt_BR">Imagem bruta K25 da Kodak</comment>
- <comment xml:lang="ro">Imagine brută Kodak K25</comment>
- <comment xml:lang="ru">Необработанное изображение Kodak K25</comment>
- <comment xml:lang="sk">Surový obrázok Kodak K25</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Kodak K25</comment>
- <comment xml:lang="sq">Figurë raw Kodak K25</comment>
- <comment xml:lang="sr">Кодак К25 сирова слика</comment>
- <comment xml:lang="sv">Kodak K25-råbild</comment>
- <comment xml:lang="tr">Kodak K25 ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив K25 Kodak</comment>
- <comment xml:lang="vi">Ảnh thô Kodak K25</comment>
+ <comment xml:lang="zh_TW">Kodak K25 原始影像</comment>
<comment xml:lang="zh_CN">柯达 K25 原始图像</comment>
- <comment xml:lang="zh_TW">Kodak K25 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Kodak K25</comment>
+ <comment xml:lang="uk">цифровий негатив K25 Kodak</comment>
+ <comment xml:lang="tr">Kodak K25 ham görüntüsü</comment>
+ <comment xml:lang="sv">Kodak K25-råbild</comment>
+ <comment xml:lang="sr">Кодак К25 сирова слика</comment>
+ <comment xml:lang="sq">figurë Kodak K25 e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Kodak K25</comment>
+ <comment xml:lang="si">Kodak K25 අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Kodak K25</comment>
+ <comment xml:lang="ru">Необработанное изображение Kodak K25</comment>
+ <comment xml:lang="ro">Imagine brută Kodak K25</comment>
+ <comment xml:lang="pt_BR">Imagem bruta K25 da Kodak</comment>
+ <comment xml:lang="pt">imagem em bruto Kodak K25</comment>
+ <comment xml:lang="pl">Surowy obraz K25 Kodak</comment>
+ <comment xml:lang="oc">imatge brut K25 Kodak</comment>
+ <comment xml:lang="nn">Kodak K25 råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Kodak K25-beeld</comment>
+ <comment xml:lang="nb">Kodak K25 raw-bilde</comment>
+ <comment xml:lang="lv">Kodak K25 jēlattēls</comment>
+ <comment xml:lang="lt">Kodak K25 neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">코닥 K25 RAW 사진</comment>
+ <comment xml:lang="kk">Kodak K25 өңделмеген суреті</comment>
+ <comment xml:lang="ja">Kodak K25 raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Kodak K25</comment>
+ <comment xml:lang="is">Kodak K25 hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Kodak K25</comment>
+ <comment xml:lang="ia">Imagine brute K25 de Kodak</comment>
+ <comment xml:lang="hu">Kodak K25 nyers kép</comment>
+ <comment xml:lang="hr">Kodak K25 osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Kodak K25</comment>
+ <comment xml:lang="gl">imaxe en bruto de Kodad K25</comment>
+ <comment xml:lang="ga">amhíomhá Kodak K25</comment>
+ <comment xml:lang="fur">imagjin grese Kodak K25</comment>
+ <comment xml:lang="fr">image brute K25 Kodak</comment>
+ <comment xml:lang="fo">Kodak K25 rámynd</comment>
+ <comment xml:lang="fi">Kodak-K25-raakakuva</comment>
+ <comment xml:lang="eu">Kodak K25 raw image</comment>
+ <comment xml:lang="es">imagen en bruto K25 de Kodak</comment>
+ <comment xml:lang="en_GB">Kodak K25 raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Kodak K25</comment>
+ <comment xml:lang="de">Kodak-K25-Rohbild</comment>
+ <comment xml:lang="da">Kodak K25 raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Kodak K25</comment>
+ <comment xml:lang="ca">imatge en cru de Kodak K25</comment>
+ <comment xml:lang="bg">Изображение — Kodak K25 raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Kodak K25</comment>
+ <comment xml:lang="be">неапрацаваная выява Kodak K25</comment>
+ <comment xml:lang="ar">صورة Kodak K25 خامة</comment>
+ <comment xml:lang="af">Kodak K25 rou beeld</comment>
<acronym>K25</acronym>
<expanded-acronym>Kodak DC25</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26342,52 +28760,57 @@
</mime-type>
<mime-type type="image/x-kodak-kdc">
<comment>Kodak KDC raw image</comment>
- <comment xml:lang="ar">صورة Kodak KDC خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Kodak KDC</comment>
- <comment xml:lang="bg">Изображение — Kodak KDC raw</comment>
- <comment xml:lang="ca">imatge en cru de Kodak KDC</comment>
- <comment xml:lang="cs">surový obrázek Kodak KDC</comment>
- <comment xml:lang="da">Kodak KDC-råbillede</comment>
- <comment xml:lang="de">Kodak-KDC-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Kodak KDC</comment>
- <comment xml:lang="en_GB">Kodak KDC raw image</comment>
- <comment xml:lang="es">imagen en bruto KDC de Kodak</comment>
- <comment xml:lang="eu">Kodak KDC irudi gordina</comment>
- <comment xml:lang="fi">Kodak-KDC-raakakuva</comment>
- <comment xml:lang="fo">Kodak KDC rámynd</comment>
- <comment xml:lang="fr">image brute KDC Kodak</comment>
- <comment xml:lang="ga">amhíomhá Kodak KDC</comment>
- <comment xml:lang="gl">imaxe en bruto de Kodad KDC</comment>
- <comment xml:lang="he">תמונה גולמית של Kodak KDC</comment>
- <comment xml:lang="hr">Kodak KDC osnovna slika</comment>
- <comment xml:lang="hu">Kodak KDC nyers kép</comment>
- <comment xml:lang="ia">Imagine brute KDC de Kodak</comment>
- <comment xml:lang="id">Citra mentah Kodak KDC</comment>
- <comment xml:lang="it">Immagine raw Kodak KDC</comment>
- <comment xml:lang="ja">Kodak KDC raw 画像</comment>
- <comment xml:lang="kk">Kodak KDC өңделмеген суреті</comment>
- <comment xml:lang="ko">코닥 KDC RAW 사진</comment>
- <comment xml:lang="lt">Kodak KDC neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Kodak KDC jēlattēls</comment>
- <comment xml:lang="nb">Kodak KDC raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Kodak KDC-beeld</comment>
- <comment xml:lang="nn">Kodak KDC råbilete</comment>
- <comment xml:lang="oc">imatge brut KDC Kodak</comment>
- <comment xml:lang="pl">Surowy obraz KDC Kodak</comment>
- <comment xml:lang="pt">imagem em bruto Kodak KDC</comment>
- <comment xml:lang="pt_BR">Imagem bruta KDC da Kodak</comment>
- <comment xml:lang="ro">Imagine brută Kodak KDC</comment>
- <comment xml:lang="ru">Необработанное изображение Kodak KDC</comment>
- <comment xml:lang="sk">Surový obrázok Kodak KDC</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Kodak KDC</comment>
- <comment xml:lang="sq">Figurë raw Kodak KDC</comment>
- <comment xml:lang="sr">Кодак КДЦ сирова слика</comment>
- <comment xml:lang="sv">Kodak KDC-råbild</comment>
- <comment xml:lang="tr">Kodak KDC ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив KDC Kodak</comment>
- <comment xml:lang="vi">Ảnh thô Kodak KDC</comment>
+ <comment xml:lang="zh_TW">Kodak KDC 原始影像</comment>
<comment xml:lang="zh_CN">柯达 KDC 原始图像</comment>
- <comment xml:lang="zh_TW">Kodak KDC 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Kodak KDC</comment>
+ <comment xml:lang="uk">цифровий негатив KDC Kodak</comment>
+ <comment xml:lang="tr">Kodak KDC ham görüntüsü</comment>
+ <comment xml:lang="sv">Kodak KDC-råbild</comment>
+ <comment xml:lang="sr">Кодак КДЦ сирова слика</comment>
+ <comment xml:lang="sq">figurë Kodak KDC e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Kodak KDC</comment>
+ <comment xml:lang="si">Kodak KDC අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Kodak KDC</comment>
+ <comment xml:lang="ru">Необработанное изображение Kodak KDC</comment>
+ <comment xml:lang="ro">Imagine brută Kodak KDC</comment>
+ <comment xml:lang="pt_BR">Imagem bruta KDC da Kodak</comment>
+ <comment xml:lang="pt">imagem em bruto Kodak KDC</comment>
+ <comment xml:lang="pl">Surowy obraz KDC Kodak</comment>
+ <comment xml:lang="oc">imatge brut KDC Kodak</comment>
+ <comment xml:lang="nn">Kodak KDC råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Kodak KDC-beeld</comment>
+ <comment xml:lang="nb">Kodak KDC raw-bilde</comment>
+ <comment xml:lang="lv">Kodak KDC jēlattēls</comment>
+ <comment xml:lang="lt">Kodak KDC neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">코닥 KDC RAW 사진</comment>
+ <comment xml:lang="kk">Kodak KDC өңделмеген суреті</comment>
+ <comment xml:lang="ja">Kodak KDC raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Kodak KDC</comment>
+ <comment xml:lang="is">Kodak KDC hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Kodak KDC</comment>
+ <comment xml:lang="ia">Imagine brute KDC de Kodak</comment>
+ <comment xml:lang="hu">Kodak KDC nyers kép</comment>
+ <comment xml:lang="hr">Kodak KDC osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Kodak KDC</comment>
+ <comment xml:lang="gl">imaxe en bruto de Kodad KDC</comment>
+ <comment xml:lang="ga">amhíomhá Kodak KDC</comment>
+ <comment xml:lang="fur">imagjin grese Kodak KDC</comment>
+ <comment xml:lang="fr">image brute KDC Kodak</comment>
+ <comment xml:lang="fo">Kodak KDC rámynd</comment>
+ <comment xml:lang="fi">Kodak-KDC-raakakuva</comment>
+ <comment xml:lang="eu">Kodak KDC irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto KDC de Kodak</comment>
+ <comment xml:lang="en_GB">Kodak KDC raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Kodak KDC</comment>
+ <comment xml:lang="de">Kodak-KDC-Rohbild</comment>
+ <comment xml:lang="da">Kodak KDC raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Kodak KDC</comment>
+ <comment xml:lang="ca">imatge en cru de Kodak KDC</comment>
+ <comment xml:lang="bg">Изображение — Kodak KDC raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Kodak KDC</comment>
+ <comment xml:lang="be">неапрацаваная выява Kodak KDC</comment>
+ <comment xml:lang="ar">صورة Kodak KDC خامة</comment>
+ <comment xml:lang="af">Kodak KDC rou beeld</comment>
<acronym>KDC</acronym>
<expanded-acronym>Kodak Digital Camera</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26399,274 +28822,339 @@
</mime-type>
<mime-type type="image/x-minolta-mrw">
<comment>Minolta MRW raw image</comment>
- <comment xml:lang="ar">صورة Minolta MRW خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Minolta MRW</comment>
- <comment xml:lang="bg">Изображение — Minolta MRW raw</comment>
- <comment xml:lang="ca">imatge en cru de Minolta MRW</comment>
- <comment xml:lang="cs">surový obrázek Minolta MRW</comment>
- <comment xml:lang="da">Minolta MRW-råbillede</comment>
- <comment xml:lang="de">Minolta-MRW-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Minolta MRW</comment>
- <comment xml:lang="en_GB">Minolta MRW raw image</comment>
- <comment xml:lang="es">imagen en bruto MRW de Minolta</comment>
- <comment xml:lang="eu">Minolta MRW irudi gordina</comment>
- <comment xml:lang="fi">Minolta-MRW-raakakuva</comment>
- <comment xml:lang="fo">Minolta MRW rámynd</comment>
- <comment xml:lang="fr">image brute MRW Minolta</comment>
- <comment xml:lang="ga">amhíomhá Minolta MRW</comment>
- <comment xml:lang="gl">imaxe RAW de Minolta MRW</comment>
- <comment xml:lang="he">תמונה גולמית של Minolta MRW</comment>
- <comment xml:lang="hr">Minolta MRW osnovna slika</comment>
- <comment xml:lang="hu">Minolta MRW nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Minolta MRW</comment>
- <comment xml:lang="id">Citra mentah Minolta MRW</comment>
- <comment xml:lang="it">Immagine raw Minolta MRW</comment>
- <comment xml:lang="ja">Minolta MRW raw 画像</comment>
- <comment xml:lang="kk">Minolta MRW өңделмеген суреті</comment>
- <comment xml:lang="ko">미놀타 MRW RAW 사진</comment>
- <comment xml:lang="lt">Minolta MRW neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Minolta MRW jēlattēls</comment>
- <comment xml:lang="nb">Minolta MRW raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Minolta MRW-beeld</comment>
- <comment xml:lang="nn">Minolta MRW råbilete</comment>
- <comment xml:lang="oc">imatge brut MRW Minolta</comment>
- <comment xml:lang="pl">Surowy obraz MRW Minolta</comment>
- <comment xml:lang="pt">imagem em bruto Minolta MRW</comment>
- <comment xml:lang="pt_BR">Imagem bruta MRW do Minolta</comment>
- <comment xml:lang="ro">Imagine brută Minolta MRW</comment>
- <comment xml:lang="ru">Необработанное изображение Minolta MRW</comment>
- <comment xml:lang="sk">Surový obrázok Minolta MRW</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Minolta MRW</comment>
- <comment xml:lang="sq">Figurë raw Minolta MRW</comment>
- <comment xml:lang="sr">Минолта МРВ сирова слика</comment>
- <comment xml:lang="sv">Minolta MRW-råbild</comment>
- <comment xml:lang="tr">Minolta MRW ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив MRW Minolta</comment>
- <comment xml:lang="vi">Ảnh thô Minolta MRW</comment>
+ <comment xml:lang="zh_TW">Minolta MRW 原始影像</comment>
<comment xml:lang="zh_CN">美能达 MRW 原始图像</comment>
- <comment xml:lang="zh_TW">Minolta MRW 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Minolta MRW</comment>
+ <comment xml:lang="uk">цифровий негатив MRW Minolta</comment>
+ <comment xml:lang="tr">Minolta MRW ham görüntüsü</comment>
+ <comment xml:lang="sv">Minolta MRW-råbild</comment>
+ <comment xml:lang="sr">Минолта МРВ сирова слика</comment>
+ <comment xml:lang="sq">figurë Minolta MRW e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Minolta MRW</comment>
+ <comment xml:lang="si">Minolta MRW අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Minolta MRW</comment>
+ <comment xml:lang="ru">Необработанное изображение Minolta MRW</comment>
+ <comment xml:lang="ro">Imagine brută Minolta MRW</comment>
+ <comment xml:lang="pt_BR">Imagem bruta MRW do Minolta</comment>
+ <comment xml:lang="pt">imagem em bruto Minolta MRW</comment>
+ <comment xml:lang="pl">Surowy obraz MRW Minolta</comment>
+ <comment xml:lang="oc">imatge brut MRW Minolta</comment>
+ <comment xml:lang="nn">Minolta MRW råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Minolta MRW-beeld</comment>
+ <comment xml:lang="nb">Minolta MRW raw-bilde</comment>
+ <comment xml:lang="lv">Minolta MRW jēlattēls</comment>
+ <comment xml:lang="lt">Minolta MRW neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">미놀타 MRW RAW 사진</comment>
+ <comment xml:lang="kk">Minolta MRW өңделмеген суреті</comment>
+ <comment xml:lang="ja">Minolta MRW raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Minolta MRW</comment>
+ <comment xml:lang="is">Minolta MRW hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Minolta MRW</comment>
+ <comment xml:lang="ia">Imagine brute Minolta MRW</comment>
+ <comment xml:lang="hu">Minolta MRW nyers kép</comment>
+ <comment xml:lang="hr">Minolta MRW osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Minolta MRW</comment>
+ <comment xml:lang="gl">imaxe RAW de Minolta MRW</comment>
+ <comment xml:lang="ga">amhíomhá Minolta MRW</comment>
+ <comment xml:lang="fur">imagjin grese Minolta MRW</comment>
+ <comment xml:lang="fr">image brute MRW Minolta</comment>
+ <comment xml:lang="fo">Minolta MRW rámynd</comment>
+ <comment xml:lang="fi">Minolta-MRW-raakakuva</comment>
+ <comment xml:lang="eu">Minolta MRW irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto MRW de Minolta</comment>
+ <comment xml:lang="en_GB">Minolta MRW raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Minolta MRW</comment>
+ <comment xml:lang="de">Minolta-MRW-Rohbild</comment>
+ <comment xml:lang="da">Minolta MRW raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Minolta MRW</comment>
+ <comment xml:lang="ca">imatge en cru de Minolta MRW</comment>
+ <comment xml:lang="bg">Изображение — Minolta MRW raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Minolta MRW</comment>
+ <comment xml:lang="be">неапрацаваная выява Minolta MRW</comment>
+ <comment xml:lang="ar">صورة Minolta MRW خامة</comment>
+ <comment xml:lang="af">Minolta MRW rou beeld</comment>
<acronym>MRW</acronym>
<expanded-acronym>Minolta RaW</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
+ <magic>
<match value="\x00MRM" type="string" offset="0"/>
</magic>
<glob pattern="*.mrw"/>
</mime-type>
<mime-type type="image/x-nikon-nef">
<comment>Nikon NEF raw image</comment>
- <comment xml:lang="ar">صورة Nikon NEF خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Nikon NEF</comment>
- <comment xml:lang="bg">Изображение — Nikon NEF raw</comment>
- <comment xml:lang="ca">imatge en cru de Nikon NEF</comment>
- <comment xml:lang="cs">surový obrázek Nikon NEF</comment>
- <comment xml:lang="da">Nikon NEF-råbillede</comment>
- <comment xml:lang="de">Nikon-NEF-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Nikon NEF</comment>
- <comment xml:lang="en_GB">Nikon NEF raw image</comment>
- <comment xml:lang="es">imagen en bruto NEF de Nikon</comment>
- <comment xml:lang="eu">Nikon NEF irudi gordina</comment>
- <comment xml:lang="fi">Nikon-NEF-raakakuva</comment>
- <comment xml:lang="fo">Nikon NEF rámynd</comment>
- <comment xml:lang="fr">image brute NEF Nikon</comment>
- <comment xml:lang="ga">amhíomhá Nikon NEF</comment>
- <comment xml:lang="gl">imaxe RAW NEF Nikon</comment>
- <comment xml:lang="he">תמונה גולמית של Nikon NEF</comment>
- <comment xml:lang="hr">Nikon NEF osnovna slika</comment>
- <comment xml:lang="hu">Nikon NEF nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Nikon NEF</comment>
- <comment xml:lang="id">Citra mentah Nikon NEF</comment>
- <comment xml:lang="it">Immagine raw Nikon NEF</comment>
- <comment xml:lang="ja">Nikon NEF raw イメージ</comment>
- <comment xml:lang="kk">Nikon NEF өңделмеген суреті</comment>
- <comment xml:lang="ko">니콘 NEF RAW 사진</comment>
- <comment xml:lang="lt">Nikon NEF neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Nikon NEF jēlattēls</comment>
- <comment xml:lang="nb">Nikon NEF raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Nikon NEF-beeld</comment>
- <comment xml:lang="nn">Nikon NEF råbilete</comment>
- <comment xml:lang="oc">imatge brut NEF Nikon</comment>
- <comment xml:lang="pl">Surowy obraz NEF Nikon</comment>
- <comment xml:lang="pt">imagem em bruto Nikon NEF</comment>
- <comment xml:lang="pt_BR">Imagem bruta NEF da Nikon</comment>
- <comment xml:lang="ro">Imagine brută Nikon NEF</comment>
- <comment xml:lang="ru">Необработанное изображение Nikon NEF</comment>
- <comment xml:lang="sk">Surový obrázok Nikon NEF</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Nikon NEF</comment>
- <comment xml:lang="sq">Figurë raw Nikon NEF</comment>
- <comment xml:lang="sr">Никон НЕФ сирова слика</comment>
- <comment xml:lang="sv">Nikon NEF-råbild</comment>
- <comment xml:lang="tr">Nikon NEF ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив NEF Nikon</comment>
- <comment xml:lang="vi">Ảnh thô Nikon NEF</comment>
+ <comment xml:lang="zh_TW">Nikon NEF 原始影像</comment>
<comment xml:lang="zh_CN">尼康 NEF 原始图像</comment>
- <comment xml:lang="zh_TW">Nikon NEF 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Nikon NEF</comment>
+ <comment xml:lang="uk">цифровий негатив NEF Nikon</comment>
+ <comment xml:lang="tr">Nikon NEF ham görüntüsü</comment>
+ <comment xml:lang="sv">Nikon NEF-råbild</comment>
+ <comment xml:lang="sr">Никон НЕФ сирова слика</comment>
+ <comment xml:lang="sq">figurë Nikon NEF e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Nikon NEF</comment>
+ <comment xml:lang="si">Nikon NEF අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Nikon NEF</comment>
+ <comment xml:lang="ru">Необработанное изображение Nikon NEF</comment>
+ <comment xml:lang="ro">Imagine brută Nikon NEF</comment>
+ <comment xml:lang="pt_BR">Imagem bruta NEF da Nikon</comment>
+ <comment xml:lang="pt">imagem em bruto Nikon NEF</comment>
+ <comment xml:lang="pl">Surowy obraz NEF Nikon</comment>
+ <comment xml:lang="oc">imatge brut NEF Nikon</comment>
+ <comment xml:lang="nn">Nikon NEF råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Nikon NEF-beeld</comment>
+ <comment xml:lang="nb">Nikon NEF raw-bilde</comment>
+ <comment xml:lang="lv">Nikon NEF jēlattēls</comment>
+ <comment xml:lang="lt">Nikon NEF neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">니콘 NEF RAW 사진</comment>
+ <comment xml:lang="kk">Nikon NEF өңделмеген суреті</comment>
+ <comment xml:lang="ja">Nikon NEF raw イメージ</comment>
+ <comment xml:lang="it">Immagine raw Nikon NEF</comment>
+ <comment xml:lang="is">Nikon NEF hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Nikon NEF</comment>
+ <comment xml:lang="ia">Imagine brute Nikon NEF</comment>
+ <comment xml:lang="hu">Nikon NEF nyers kép</comment>
+ <comment xml:lang="hr">Nikon NEF osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Nikon NEF</comment>
+ <comment xml:lang="gl">imaxe RAW NEF Nikon</comment>
+ <comment xml:lang="ga">amhíomhá Nikon NEF</comment>
+ <comment xml:lang="fur">imagjin grese Nikon NEF</comment>
+ <comment xml:lang="fr">image brute NEF Nikon</comment>
+ <comment xml:lang="fo">Nikon NEF rámynd</comment>
+ <comment xml:lang="fi">Nikon-NEF-raakakuva</comment>
+ <comment xml:lang="eu">Nikon NEF irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto NEF de Nikon</comment>
+ <comment xml:lang="en_GB">Nikon NEF raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Nikon NEF</comment>
+ <comment xml:lang="de">Nikon-NEF-Rohbild</comment>
+ <comment xml:lang="da">Nikon NEF raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Nikon NEF</comment>
+ <comment xml:lang="ca">imatge en cru de Nikon NEF</comment>
+ <comment xml:lang="bg">Изображение — Nikon NEF raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Nikon NEF</comment>
+ <comment xml:lang="be">неапрацаваная выява Nikon NEF</comment>
+ <comment xml:lang="ar">صورة Nikon NEF خامة</comment>
+ <comment xml:lang="af">Nikon NEF rou beeld</comment>
<acronym>NEF</acronym>
<expanded-acronym>Nikon Electronic Format</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
<sub-class-of type="image/tiff"/>
<glob pattern="*.nef"/>
</mime-type>
+ <mime-type type="image/x-nikon-nrw">
+ <comment>Nikon NRW raw image</comment>
+ <comment xml:lang="zh_TW">Nikon NRW 原始影像</comment>
+ <comment xml:lang="zh_CN">尼康 NRW 原始图像</comment>
+ <comment xml:lang="uk">цифровий негатив NRW Nikon</comment>
+ <comment xml:lang="tr">Nikon NRW ham görüntüsü</comment>
+ <comment xml:lang="sv">Nikon NRW-råbild</comment>
+ <comment xml:lang="sl">Neobdelana slika NRW</comment>
+ <comment xml:lang="si">Nikon NRW අමු රූපය</comment>
+ <comment xml:lang="ru">Необработанное изображение Nikon NRW</comment>
+ <comment xml:lang="pt_BR">Imagem bruta NRW da Nikon</comment>
+ <comment xml:lang="pl">Surowy obraz NRW Nikon</comment>
+ <comment xml:lang="oc">imatge brut Nikon NRW</comment>
+ <comment xml:lang="nl">onbewerkt Nikon NRW beeld</comment>
+ <comment xml:lang="ko">니콘 NRW RAW 사진</comment>
+ <comment xml:lang="kk">Nikon NRW өңделмеген суреті</comment>
+ <comment xml:lang="ja">Nikon NRW raw 画像ファイル</comment>
+ <comment xml:lang="it">Immagine raw Nikon NRW</comment>
+ <comment xml:lang="hr">Nikon NRW osnovna slika</comment>
+ <comment xml:lang="gl">Imaxe RAW de Nikon NRW</comment>
+ <comment xml:lang="fi">Nikon-NRW-raakakuva</comment>
+ <comment xml:lang="eu">Nikon NRW irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto NRW de Nikon</comment>
+ <comment xml:lang="en_GB">Nikon NRW raw image</comment>
+ <comment xml:lang="de">Nikon-NRW-Rohbild</comment>
+ <comment xml:lang="be">неапрацаваная выява Nikon NRW</comment>
+ <comment xml:lang="ar">صورة Nikon NRW خامة</comment>
+ <sub-class-of type="image/x-dcraw"/>
+ <sub-class-of type="image/tiff"/>
+ <glob pattern="*.nrw"/>
+ </mime-type>
<mime-type type="image/x-olympus-orf">
<comment>Olympus ORF raw image</comment>
- <comment xml:lang="ar">صورة Olympus ORF خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Olympus ORF</comment>
- <comment xml:lang="bg">Изображение — Olympus ORF raw</comment>
- <comment xml:lang="ca">imatge en cru d'Olympus ORF</comment>
- <comment xml:lang="cs">surový obrázek Olympus ORF</comment>
- <comment xml:lang="da">Olympus ORF-råbillede</comment>
- <comment xml:lang="de">Olympus-ORF-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Olympus ORF</comment>
- <comment xml:lang="en_GB">Olympus ORF raw image</comment>
- <comment xml:lang="es">imagen en bruto ORF de Olympus</comment>
- <comment xml:lang="eu">Olympus ORF irudi gordina</comment>
- <comment xml:lang="fi">Olympus-ORF-raakakuva</comment>
- <comment xml:lang="fo">Olympus ORF rámynd</comment>
- <comment xml:lang="fr">image brute ORF Olympus</comment>
- <comment xml:lang="ga">amhíomhá Olympus ORF</comment>
- <comment xml:lang="gl">imaxe en bruto de Olympus ORF</comment>
- <comment xml:lang="he">תמונה גולמית של Olympus ORF</comment>
- <comment xml:lang="hr">Olympus ORF osnovna slika</comment>
- <comment xml:lang="hu">Olympus ORF nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Olympus ORF</comment>
- <comment xml:lang="id">Citra mentah Olympus ORF</comment>
- <comment xml:lang="it">Immagine raw Olympus ORF</comment>
- <comment xml:lang="ja">Olympus ORF raw 画像</comment>
- <comment xml:lang="ka">Olympus ORF-ის raw გამოსახულება</comment>
- <comment xml:lang="kk">Olympus ORF өңделмеген суреті</comment>
- <comment xml:lang="ko">올림푸스 ORF RAW 사진</comment>
- <comment xml:lang="lt">Olympus ORF neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Olympus ORF jēlattēls</comment>
- <comment xml:lang="nb">Olympus ORF raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Olympus ORF-beeld</comment>
- <comment xml:lang="nn">Olympus ORF råbilete</comment>
- <comment xml:lang="oc">imatge brut ORF Olympus</comment>
- <comment xml:lang="pl">Surowy obraz Olympus ORF</comment>
- <comment xml:lang="pt">imagem em bruto Olympus ORF</comment>
- <comment xml:lang="pt_BR">Imagem bruta ORF da Olympus</comment>
- <comment xml:lang="ro">Imagine brută Olympus ORF</comment>
- <comment xml:lang="ru">Необработанное изображение Olympus ORF</comment>
- <comment xml:lang="sk">Surový obrázok Olympus ORF</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Olympus ORF</comment>
- <comment xml:lang="sq">Figurë raw Olympus ORF</comment>
- <comment xml:lang="sr">Олимпус ОРФ сирова слика</comment>
- <comment xml:lang="sv">Olympus ORF-råbild</comment>
- <comment xml:lang="tr">Olympus ORF ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив ORF Olympus</comment>
- <comment xml:lang="vi">Ảnh thô Olympus ORF</comment>
+ <comment xml:lang="zh_TW">Olympus ORF 原始影像</comment>
<comment xml:lang="zh_CN">奥林巴斯 ORF 原始图像</comment>
- <comment xml:lang="zh_TW">Olympus ORF 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Olympus ORF</comment>
+ <comment xml:lang="uk">цифровий негатив ORF Olympus</comment>
+ <comment xml:lang="tr">Olympus ORF ham görüntüsü</comment>
+ <comment xml:lang="sv">Olympus ORF-råbild</comment>
+ <comment xml:lang="sr">Олимпус ОРФ сирова слика</comment>
+ <comment xml:lang="sq">figurë Olympus ORF e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Olympus ORF</comment>
+ <comment xml:lang="si">Olympus ORF අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Olympus ORF</comment>
+ <comment xml:lang="ru">Необработанное изображение Olympus ORF</comment>
+ <comment xml:lang="ro">Imagine brută Olympus ORF</comment>
+ <comment xml:lang="pt_BR">Imagem bruta ORF da Olympus</comment>
+ <comment xml:lang="pt">imagem em bruto Olympus ORF</comment>
+ <comment xml:lang="pl">Surowy obraz Olympus ORF</comment>
+ <comment xml:lang="oc">imatge brut ORF Olympus</comment>
+ <comment xml:lang="nn">Olympus ORF råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Olympus ORF-beeld</comment>
+ <comment xml:lang="nb">Olympus ORF raw-bilde</comment>
+ <comment xml:lang="lv">Olympus ORF jēlattēls</comment>
+ <comment xml:lang="lt">Olympus ORF neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">올림푸스 ORF RAW 사진</comment>
+ <comment xml:lang="kk">Olympus ORF өңделмеген суреті</comment>
+ <comment xml:lang="ka">Olympus ORF-ის raw გამოსახულება</comment>
+ <comment xml:lang="ja">Olympus ORF raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Olympus ORF</comment>
+ <comment xml:lang="is">Olympus ORF hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Olympus ORF</comment>
+ <comment xml:lang="ia">Imagine brute Olympus ORF</comment>
+ <comment xml:lang="hu">Olympus ORF nyers kép</comment>
+ <comment xml:lang="hr">Olympus ORF osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Olympus ORF</comment>
+ <comment xml:lang="gl">imaxe en bruto de Olympus ORF</comment>
+ <comment xml:lang="ga">amhíomhá Olympus ORF</comment>
+ <comment xml:lang="fur">imagjin grese Olympus ORF</comment>
+ <comment xml:lang="fr">image brute ORF Olympus</comment>
+ <comment xml:lang="fo">Olympus ORF rámynd</comment>
+ <comment xml:lang="fi">Olympus-ORF-raakakuva</comment>
+ <comment xml:lang="eu">Olympus ORF irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto ORF de Olympus</comment>
+ <comment xml:lang="en_GB">Olympus ORF raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Olympus ORF</comment>
+ <comment xml:lang="de">Olympus-ORF-Rohbild</comment>
+ <comment xml:lang="da">Olympus ORF raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Olympus ORF</comment>
+ <comment xml:lang="ca">imatge en cru d'Olympus ORF</comment>
+ <comment xml:lang="bg">Изображение — Olympus ORF raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Olympus ORF</comment>
+ <comment xml:lang="be">неапрацаваная выява Olympus ORF</comment>
+ <comment xml:lang="ar">صورة Olympus ORF خامة</comment>
+ <comment xml:lang="af">Olympus ORF rou beeld</comment>
<acronym>ORF</acronym>
<expanded-acronym>Olympus Raw Format</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
-
-
-
-
-
+ <magic>
+ <!-- an ORF file is basically a TIFF file with a non standard !-->
+ <!-- header IIRO which is not nice since it is only composed !-->
+ <!-- of ASCII codes. Fortunately, the TIFF header is followed !-->
+ <!-- by the offset of the first TIFF ifd which is always !-->
+ <!-- 0x00000008 (Little endian) for an ORF !-->
<match value="IIRO\x08\x00\x00\x00" type="string" offset="0"/>
</magic>
<glob pattern="*.orf"/>
</mime-type>
<mime-type type="image/x-panasonic-rw">
<comment>Panasonic raw image</comment>
- <comment xml:lang="ar">صورة Panasonic خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Panasonic</comment>
- <comment xml:lang="bg">Изображение — Panasonic raw</comment>
- <comment xml:lang="ca">imatge en cru de Panasonic</comment>
- <comment xml:lang="cs">surový obrázek Panasonic</comment>
- <comment xml:lang="da">Panasonicråbillede (raw)</comment>
- <comment xml:lang="de">Panasonic-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Panasonic</comment>
- <comment xml:lang="en_GB">Panasonic raw image</comment>
- <comment xml:lang="es">imagen en bruto de Panasonic</comment>
- <comment xml:lang="eu">Panasonic irudi gordina</comment>
- <comment xml:lang="fi">Panasonic-raakakuva</comment>
- <comment xml:lang="fo">Panasonic rámynd</comment>
- <comment xml:lang="fr">image brute Panasonic</comment>
- <comment xml:lang="ga">amhíomhá Panasonic</comment>
- <comment xml:lang="gl">imaxe en bruto de Panasonic</comment>
- <comment xml:lang="he">תמונה גולמית של Panasonic</comment>
- <comment xml:lang="hr">Panasonic osnovna slika</comment>
- <comment xml:lang="hu">Panasonic nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Panasonic</comment>
- <comment xml:lang="id">Citra mentah Panasonic</comment>
- <comment xml:lang="it">Immagine raw Panasonic</comment>
- <comment xml:lang="ja">Panasonic raw 画像</comment>
- <comment xml:lang="kk">Panasonic өңделмеген суреті</comment>
- <comment xml:lang="ko">파나소닉 RAW 사진</comment>
- <comment xml:lang="lt">Panasonic neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Panasonic jēlattēls</comment>
- <comment xml:lang="nb">Panasonic raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Panasonic-beeld</comment>
- <comment xml:lang="nn">Panasonic råbilete</comment>
- <comment xml:lang="oc">imatge brut Panasonic</comment>
- <comment xml:lang="pl">Obraz raw Panasonic</comment>
- <comment xml:lang="pt">imagem em bruto Panasonic</comment>
- <comment xml:lang="pt_BR">Imagem bruta da Panasonic</comment>
- <comment xml:lang="ro">Imagine brută Panasonic</comment>
- <comment xml:lang="ru">Необработанное изображение Panasonic</comment>
- <comment xml:lang="sk">Surový obrázok Panasonic</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Panasonic</comment>
- <comment xml:lang="sq">Figurë raw Panasonic</comment>
- <comment xml:lang="sr">Панасоник сирова слика</comment>
- <comment xml:lang="sv">Panasonic-råbild</comment>
- <comment xml:lang="tr">Panasonic ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив Panasonic</comment>
- <comment xml:lang="vi">Ảnh thô Panasonic</comment>
+ <comment xml:lang="zh_TW">Panasonic 原始影像</comment>
<comment xml:lang="zh_CN">松下原始图像</comment>
- <comment xml:lang="zh_TW">Panasonic 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Panasonic</comment>
+ <comment xml:lang="uk">цифровий негатив Panasonic</comment>
+ <comment xml:lang="tr">Panasonic ham görüntüsü</comment>
+ <comment xml:lang="sv">Panasonic-råbild</comment>
+ <comment xml:lang="sr">Панасоник сирова слика</comment>
+ <comment xml:lang="sq">figurë Panasonic e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Panasonic</comment>
+ <comment xml:lang="si">පැනසොනික් අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Panasonic</comment>
+ <comment xml:lang="ru">Необработанное изображение Panasonic</comment>
+ <comment xml:lang="ro">Imagine brută Panasonic</comment>
+ <comment xml:lang="pt_BR">Imagem bruta da Panasonic</comment>
+ <comment xml:lang="pt">imagem em bruto Panasonic</comment>
+ <comment xml:lang="pl">Obraz raw Panasonic</comment>
+ <comment xml:lang="oc">imatge brut Panasonic</comment>
+ <comment xml:lang="nn">Panasonic råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Panasonic-beeld</comment>
+ <comment xml:lang="nb">Panasonic raw-bilde</comment>
+ <comment xml:lang="lv">Panasonic jēlattēls</comment>
+ <comment xml:lang="lt">Panasonic neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">파나소닉 RAW 사진</comment>
+ <comment xml:lang="kk">Panasonic өңделмеген суреті</comment>
+ <comment xml:lang="ja">Panasonic raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Panasonic</comment>
+ <comment xml:lang="is">Panasonic hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Panasonic</comment>
+ <comment xml:lang="ia">Imagine brute Panasonic</comment>
+ <comment xml:lang="hu">Panasonic nyers kép</comment>
+ <comment xml:lang="hr">Panasonic osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Panasonic</comment>
+ <comment xml:lang="gl">imaxe en bruto de Panasonic</comment>
+ <comment xml:lang="ga">amhíomhá Panasonic</comment>
+ <comment xml:lang="fur">imagjin grese Panasonic</comment>
+ <comment xml:lang="fr">image brute Panasonic</comment>
+ <comment xml:lang="fo">Panasonic rámynd</comment>
+ <comment xml:lang="fi">Panasonic-raakakuva</comment>
+ <comment xml:lang="eu">Panasonic irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto de Panasonic</comment>
+ <comment xml:lang="en_GB">Panasonic raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Panasonic</comment>
+ <comment xml:lang="de">Panasonic-Rohbild</comment>
+ <comment xml:lang="da">Panasonic raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Panasonic</comment>
+ <comment xml:lang="ca">imatge en cru de Panasonic</comment>
+ <comment xml:lang="bg">Изображение — Panasonic raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Panasonic</comment>
+ <comment xml:lang="be">неапрацаваная выява Panasonic</comment>
+ <comment xml:lang="ar">صورة Panasonic خامة</comment>
+ <comment xml:lang="af">Panasonic rou beeld</comment>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
-
+ <magic>
+ <!-- Some kind of TIFF file with a non-standard version in prefix !-->
<match value="IIU\x00\x08\x00\x00\x00" type="string" offset="0"/>
</magic>
<glob pattern="*.raw"/>
<alias type="image/x-panasonic-raw"/>
</mime-type>
<mime-type type="image/x-panasonic-rw2">
- <comment>Panasonic raw2 image</comment>
- <comment xml:lang="bg">Изображение — Panasonic raw2</comment>
- <comment xml:lang="ca">imatge «RAW2» de Panasonic</comment>
- <comment xml:lang="cs">surový obrázek Panasonic raw2</comment>
- <comment xml:lang="da">Panasonic-rå2-billede (raw)</comment>
- <comment xml:lang="de">Panasonic raw2-Bild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Panasonic (raw2)</comment>
- <comment xml:lang="en_GB">Panasonic raw2 image</comment>
- <comment xml:lang="es">imagen en bruto raw2 de Panasonic</comment>
- <comment xml:lang="eu">Panasonic raw2 irudia</comment>
- <comment xml:lang="fi">Panasonic raw2 -kuva</comment>
- <comment xml:lang="fr">image raw2 Panasonic</comment>
- <comment xml:lang="ga">íomhá raw2 Panasonic</comment>
- <comment xml:lang="gl">imaxe en bruto raw2 de Panasonic</comment>
- <comment xml:lang="he">תמונת raw2 של Panasonic</comment>
- <comment xml:lang="hr">Panasonic raw2 image</comment>
- <comment xml:lang="hu">Panasonic raw2 kép</comment>
- <comment xml:lang="ia">Imagine raw2 Panasonic</comment>
- <comment xml:lang="id">Image Panasonic raw2</comment>
- <comment xml:lang="it">Immagine raw2 Panasonic</comment>
- <comment xml:lang="ja">Panasonic raw2 画像</comment>
- <comment xml:lang="kk">Panasonic raw2 суреті</comment>
- <comment xml:lang="ko">파나소닉 RAW2 사진</comment>
- <comment xml:lang="lv">Panasonic raw2 jēlattēls</comment>
- <comment xml:lang="nl">Panasonic raw2 image</comment>
- <comment xml:lang="oc">imatge raw2 Panasonic</comment>
- <comment xml:lang="pl">Obraz raw2 Panasonic</comment>
+ <comment>Panasonic raw image</comment>
+ <comment xml:lang="zh_TW">Panasonic 原始影像</comment>
+ <comment xml:lang="zh_CN">松下原始图像</comment>
+ <comment xml:lang="vi">Ảnh thô Panasonic</comment>
+ <comment xml:lang="uk">цифровий негатив Panasonic</comment>
+ <comment xml:lang="tr">Panasonic ham görüntüsü</comment>
+ <comment xml:lang="sv">Panasonic-råbild</comment>
+ <comment xml:lang="sr">Панасоник сирова слика</comment>
+ <comment xml:lang="sq">figurë Panasonic e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Panasonic</comment>
+ <comment xml:lang="si">පැනසොනික් අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Panasonic</comment>
+ <comment xml:lang="ru">Необработанное изображение Panasonic</comment>
+ <comment xml:lang="ro">Imagine brută Panasonic</comment>
+ <comment xml:lang="pt_BR">Imagem bruta da Panasonic</comment>
<comment xml:lang="pt">imagem em bruto Panasonic</comment>
- <comment xml:lang="pt_BR">Imagem raw2 da Panasonic</comment>
- <comment xml:lang="ru">Необработанное изображение Panasonic raw2</comment>
- <comment xml:lang="sk">Surový obrázok Panasonic raw2</comment>
- <comment xml:lang="sl">Slikovna datoteka Panasonic raw2</comment>
- <comment xml:lang="sr">Панасоник сирова2 слика</comment>
- <comment xml:lang="sv">Panasonic raw2-bild</comment>
- <comment xml:lang="tr">Panasonic raw2 görüntüsü</comment>
- <comment xml:lang="uk">зображення формату raw2 Panasonic</comment>
- <comment xml:lang="zh_CN">松下 raw2 图像</comment>
- <comment xml:lang="zh_TW">Panasonic raw2 影像</comment>
+ <comment xml:lang="pl">Obraz raw Panasonic</comment>
+ <comment xml:lang="oc">imatge brut Panasonic</comment>
+ <comment xml:lang="nn">Panasonic råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Panasonic-beeld</comment>
+ <comment xml:lang="nb">Panasonic raw-bilde</comment>
+ <comment xml:lang="lv">Panasonic jēlattēls</comment>
+ <comment xml:lang="lt">Panasonic neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">파나소닉 RAW 사진</comment>
+ <comment xml:lang="kk">Panasonic өңделмеген суреті</comment>
+ <comment xml:lang="ja">Panasonic raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Panasonic</comment>
+ <comment xml:lang="is">Panasonic hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Panasonic</comment>
+ <comment xml:lang="ia">Imagine brute Panasonic</comment>
+ <comment xml:lang="hu">Panasonic nyers kép</comment>
+ <comment xml:lang="hr">Panasonic osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Panasonic</comment>
+ <comment xml:lang="gl">imaxe en bruto de Panasonic</comment>
+ <comment xml:lang="ga">amhíomhá Panasonic</comment>
+ <comment xml:lang="fur">imagjin grese Panasonic</comment>
+ <comment xml:lang="fr">image brute Panasonic</comment>
+ <comment xml:lang="fo">Panasonic rámynd</comment>
+ <comment xml:lang="fi">Panasonic-raakakuva</comment>
+ <comment xml:lang="eu">Panasonic irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto de Panasonic</comment>
+ <comment xml:lang="en_GB">Panasonic raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Panasonic</comment>
+ <comment xml:lang="de">Panasonic-Rohbild</comment>
+ <comment xml:lang="da">Panasonic raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Panasonic</comment>
+ <comment xml:lang="ca">imatge en cru de Panasonic</comment>
+ <comment xml:lang="bg">Изображение — Panasonic raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Panasonic</comment>
+ <comment xml:lang="be">неапрацаваная выява Panasonic</comment>
+ <comment xml:lang="ar">صورة Panasonic خامة</comment>
+ <comment xml:lang="af">Panasonic rou beeld</comment>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
-
+ <magic>
+ <!-- Some kind of TIFF file with a non-standard version in prefix !-->
<match value="IIU\x00\x18\x00\x00\x00" type="string" offset="0"/>
</magic>
<glob pattern="*.rw2"/>
@@ -26674,52 +29162,57 @@
</mime-type>
<mime-type type="image/x-pentax-pef">
<comment>Pentax PEF raw image</comment>
- <comment xml:lang="ar">صورة Pentax PEF خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Pentax PEF</comment>
- <comment xml:lang="bg">Изображение — Pentax PEF raw</comment>
- <comment xml:lang="ca">imatge en cru de Pentax PEF</comment>
- <comment xml:lang="cs">surový obrázek Pentax PEF</comment>
- <comment xml:lang="da">Pentax PEF-råbillede</comment>
- <comment xml:lang="de">Pentax-PEF-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Pentax PEF</comment>
- <comment xml:lang="en_GB">Pentax PEF raw image</comment>
- <comment xml:lang="es">imagen en bruto PEF de Pentax</comment>
- <comment xml:lang="eu">Pentax PEF irudi gordina</comment>
- <comment xml:lang="fi">Pentax-PEF-raakakuva</comment>
- <comment xml:lang="fo">Pentax PEF rámynd</comment>
- <comment xml:lang="fr">image brute PEF Pentax</comment>
- <comment xml:lang="ga">amhíomhá Pentax PEF</comment>
- <comment xml:lang="gl">imaxe en bruto PEF de Pentax</comment>
- <comment xml:lang="he">תמונה גולמית של Pentax PEF</comment>
- <comment xml:lang="hr">Pentax PEF osnovna slika</comment>
- <comment xml:lang="hu">Pentax PEF nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Pentax PEF</comment>
- <comment xml:lang="id">Citra mentah Pentax PEF</comment>
- <comment xml:lang="it">Immagine raw Pentax PEF</comment>
- <comment xml:lang="ja">Pentax PEF raw 画像</comment>
- <comment xml:lang="kk">Pentax PEF өңделмеген суреті</comment>
- <comment xml:lang="ko">펜탁스 PEF RAW 사진</comment>
- <comment xml:lang="lt">Pentax PEF neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Pentax PEF jēlattēls</comment>
- <comment xml:lang="nb">Pentax PEF raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Pentax PEF-beeld</comment>
- <comment xml:lang="nn">Pentax PEF råbilete</comment>
- <comment xml:lang="oc">imatge brut PEF Pentax</comment>
- <comment xml:lang="pl">Surowy obraz Pentax PEF</comment>
- <comment xml:lang="pt">imagem em bruto Pentax PEF</comment>
- <comment xml:lang="pt_BR">Imagem bruta PEF da Pentax</comment>
- <comment xml:lang="ro">Imagine brută Pentax PEF</comment>
- <comment xml:lang="ru">Необработанное изображение Pentax PEF</comment>
- <comment xml:lang="sk">Surový obrázok Pentax PEF</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Pentax PEF</comment>
- <comment xml:lang="sq">Figurë raw Pentax PEF</comment>
- <comment xml:lang="sr">Пентакс ПЕФ сирова слика</comment>
- <comment xml:lang="sv">Pentax PEF-råbild</comment>
- <comment xml:lang="tr">Pentax PEF ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив PEF Pentax</comment>
- <comment xml:lang="vi">Ảnh thô Pentax PEF</comment>
+ <comment xml:lang="zh_TW">Pentax PEF 原始影像</comment>
<comment xml:lang="zh_CN">宾得 PEF 原始图像</comment>
- <comment xml:lang="zh_TW">Pentax PEF 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Pentax PEF</comment>
+ <comment xml:lang="uk">цифровий негатив PEF Pentax</comment>
+ <comment xml:lang="tr">Pentax PEF ham görüntüsü</comment>
+ <comment xml:lang="sv">Pentax PEF-råbild</comment>
+ <comment xml:lang="sr">Пентакс ПЕФ сирова слика</comment>
+ <comment xml:lang="sq">figurë Pentax PEF e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Pentax PEF</comment>
+ <comment xml:lang="si">Pentax PEF අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Pentax PEF</comment>
+ <comment xml:lang="ru">Необработанное изображение Pentax PEF</comment>
+ <comment xml:lang="ro">Imagine brută Pentax PEF</comment>
+ <comment xml:lang="pt_BR">Imagem bruta PEF da Pentax</comment>
+ <comment xml:lang="pt">imagem em bruto Pentax PEF</comment>
+ <comment xml:lang="pl">Surowy obraz Pentax PEF</comment>
+ <comment xml:lang="oc">imatge brut PEF Pentax</comment>
+ <comment xml:lang="nn">Pentax PEF råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Pentax PEF-beeld</comment>
+ <comment xml:lang="nb">Pentax PEF raw-bilde</comment>
+ <comment xml:lang="lv">Pentax PEF jēlattēls</comment>
+ <comment xml:lang="lt">Pentax PEF neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">펜탁스 PEF RAW 사진</comment>
+ <comment xml:lang="kk">Pentax PEF өңделмеген суреті</comment>
+ <comment xml:lang="ja">Pentax PEF raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Pentax PEF</comment>
+ <comment xml:lang="is">Pentax PEF hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Pentax PEF</comment>
+ <comment xml:lang="ia">Imagine brute Pentax PEF</comment>
+ <comment xml:lang="hu">Pentax PEF nyers kép</comment>
+ <comment xml:lang="hr">Pentax PEF osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Pentax PEF</comment>
+ <comment xml:lang="gl">imaxe en bruto PEF de Pentax</comment>
+ <comment xml:lang="ga">amhíomhá Pentax PEF</comment>
+ <comment xml:lang="fur">imagjin grese Pentax PEF</comment>
+ <comment xml:lang="fr">image brute PEF Pentax</comment>
+ <comment xml:lang="fo">Pentax PEF rámynd</comment>
+ <comment xml:lang="fi">Pentax-PEF-raakakuva</comment>
+ <comment xml:lang="eu">Pentax PEF irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto PEF de Pentax</comment>
+ <comment xml:lang="en_GB">Pentax PEF raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Pentax PEF</comment>
+ <comment xml:lang="de">Pentax-PEF-Rohbild</comment>
+ <comment xml:lang="da">Pentax PEF raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Pentax PEF</comment>
+ <comment xml:lang="ca">imatge en cru de Pentax PEF</comment>
+ <comment xml:lang="bg">Изображение — Pentax PEF raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Pentax PEF</comment>
+ <comment xml:lang="be">неапрацаваная выява Pentax PEF</comment>
+ <comment xml:lang="ar">صورة Pentax PEF خامة</comment>
+ <comment xml:lang="af">Pentax PEF rou beeld</comment>
<acronym>PEF</acronym>
<expanded-acronym>Pentax Electronic Format</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26728,59 +29221,64 @@
</mime-type>
<mime-type type="image/x-sigma-x3f">
<comment>Sigma X3F raw image</comment>
- <comment xml:lang="ar">صورة Sigma X3F خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Sigma X3F</comment>
- <comment xml:lang="bg">Изображение — Sigma X3F raw</comment>
- <comment xml:lang="ca">imatge en cru de Sigma X3F</comment>
- <comment xml:lang="cs">surový obrázek Sigma X3F</comment>
- <comment xml:lang="da">Sigma X3F-råbillede</comment>
- <comment xml:lang="de">Sigma-X3F-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sigma X3F</comment>
- <comment xml:lang="en_GB">Sigma X3F raw image</comment>
- <comment xml:lang="es">imagen en bruto X3F de Sigma</comment>
- <comment xml:lang="eu">Sigma X3F irudi gordina</comment>
- <comment xml:lang="fi">Sigma-X3F-raakakuva</comment>
- <comment xml:lang="fo">Sigma X3F rámynd</comment>
- <comment xml:lang="fr">image brute X3F Sigma</comment>
- <comment xml:lang="ga">amhíomhá Sigma X3F</comment>
- <comment xml:lang="gl">imaxe en bruto X3F de Sigma</comment>
- <comment xml:lang="he">תמונה גולמית של Sigma X3F</comment>
- <comment xml:lang="hr">Sigma X3F osnovna slika</comment>
- <comment xml:lang="hu">Sigma XF3 nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Sigma X3F</comment>
- <comment xml:lang="id">Citra mentah Sigma X3F</comment>
- <comment xml:lang="it">Immagine raw Sigma X3F</comment>
- <comment xml:lang="ja">Sigma X3F raw 画像</comment>
- <comment xml:lang="kk">Sigma X3F өңделмеген суреті</comment>
- <comment xml:lang="ko">시그마 X3F RAW 사진</comment>
- <comment xml:lang="lt">Sigma X3F neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Sigma X3F jēlattēls</comment>
- <comment xml:lang="nb">Sigma X3F raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Sigma X3F-beeld</comment>
- <comment xml:lang="nn">Sigma X3F råbilete</comment>
- <comment xml:lang="oc">imatge brut X3F Sigma</comment>
- <comment xml:lang="pl">Surowy obraz X3F Sigma</comment>
- <comment xml:lang="pt">imagem em bruto Sigma X3F</comment>
- <comment xml:lang="pt_BR">Imagem bruta X3F da Sigma</comment>
- <comment xml:lang="ro">Imagine brută Sigma X3F</comment>
- <comment xml:lang="ru">Необработанное изображение Sigma X3F</comment>
- <comment xml:lang="sk">Surový obrázok Sigma X3F</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Sigma X3F</comment>
- <comment xml:lang="sq">Fifurë raw Sigma X3F</comment>
- <comment xml:lang="sr">Сигма Икс3Ф сирова слика</comment>
- <comment xml:lang="sv">Sigma X3F-råbild</comment>
- <comment xml:lang="tr">Sigma X3F ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив X3F Sigma</comment>
- <comment xml:lang="vi">Ảnh thô Sigma X3F</comment>
+ <comment xml:lang="zh_TW">Sigma X3F 原始影像</comment>
<comment xml:lang="zh_CN">适马 X3F 原始图像</comment>
- <comment xml:lang="zh_TW">Sigma X3F 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Sigma X3F</comment>
+ <comment xml:lang="uk">цифровий негатив X3F Sigma</comment>
+ <comment xml:lang="tr">Sigma X3F ham görüntüsü</comment>
+ <comment xml:lang="sv">Sigma X3F-råbild</comment>
+ <comment xml:lang="sr">Сигма Икс3Ф сирова слика</comment>
+ <comment xml:lang="sq">figurë Sigma X3F e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Sigma X3F</comment>
+ <comment xml:lang="si">Sigma X3F අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Sigma X3F</comment>
+ <comment xml:lang="ru">Необработанное изображение Sigma X3F</comment>
+ <comment xml:lang="ro">Imagine brută Sigma X3F</comment>
+ <comment xml:lang="pt_BR">Imagem bruta X3F da Sigma</comment>
+ <comment xml:lang="pt">imagem em bruto Sigma X3F</comment>
+ <comment xml:lang="pl">Surowy obraz X3F Sigma</comment>
+ <comment xml:lang="oc">imatge brut X3F Sigma</comment>
+ <comment xml:lang="nn">Sigma X3F råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Sigma X3F-beeld</comment>
+ <comment xml:lang="nb">Sigma X3F raw-bilde</comment>
+ <comment xml:lang="lv">Sigma X3F jēlattēls</comment>
+ <comment xml:lang="lt">Sigma X3F neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">시그마 X3F RAW 사진</comment>
+ <comment xml:lang="kk">Sigma X3F өңделмеген суреті</comment>
+ <comment xml:lang="ja">Sigma X3F raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Sigma X3F</comment>
+ <comment xml:lang="is">Sigma X3F hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Sigma X3F</comment>
+ <comment xml:lang="ia">Imagine brute Sigma X3F</comment>
+ <comment xml:lang="hu">Sigma XF3 nyers kép</comment>
+ <comment xml:lang="hr">Sigma X3F osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Sigma X3F</comment>
+ <comment xml:lang="gl">imaxe en bruto X3F de Sigma</comment>
+ <comment xml:lang="ga">amhíomhá Sigma X3F</comment>
+ <comment xml:lang="fur">imagjin grese Sigma X3F</comment>
+ <comment xml:lang="fr">image brute X3F Sigma</comment>
+ <comment xml:lang="fo">Sigma X3F rámynd</comment>
+ <comment xml:lang="fi">Sigma-X3F-raakakuva</comment>
+ <comment xml:lang="eu">Sigma X3F irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto X3F de Sigma</comment>
+ <comment xml:lang="en_GB">Sigma X3F raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sigma X3F</comment>
+ <comment xml:lang="de">Sigma-X3F-Rohbild</comment>
+ <comment xml:lang="da">Sigma X3F raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Sigma X3F</comment>
+ <comment xml:lang="ca">imatge en cru de Sigma X3F</comment>
+ <comment xml:lang="bg">Изображение — Sigma X3F raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Sigma X3F</comment>
+ <comment xml:lang="be">неапрацаваная выява Sigma X3F</comment>
+ <comment xml:lang="ar">صورة Sigma X3F خامة</comment>
+ <comment xml:lang="af">Sigma X3F rou beeld</comment>
<acronym>X3F</acronym>
<expanded-acronym>X3 Foveon</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
- <magic priority="50">
-
+ <magic>
+ <!-- The header is "FOVb" (Foveon) !-->
<match value="FOVb" type="string" offset="0">
-
+ <!-- Followed by a 32bit LSB specifying the version number (major.minor) !-->
<match value="0x00FF00FF" type="little32" offset="4" mask="0xFF00FF00"/>
</match>
</magic>
@@ -26788,52 +29286,57 @@
</mime-type>
<mime-type type="image/x-sony-srf">
<comment>Sony SRF raw image</comment>
- <comment xml:lang="ar">صورة Sony SRF خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Sony SRF</comment>
- <comment xml:lang="bg">Изображение — Sony SRF raw</comment>
- <comment xml:lang="ca">imatge en cru de Sony SRF</comment>
- <comment xml:lang="cs">surový obrázek Sony SRF</comment>
- <comment xml:lang="da">Sony SRF-råbillede</comment>
- <comment xml:lang="de">Sony-SRF-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sony SRF</comment>
- <comment xml:lang="en_GB">Sony SRF raw image</comment>
- <comment xml:lang="es">imagen en bruto SRF de Sony</comment>
- <comment xml:lang="eu">Sony SRF irudi gordina</comment>
- <comment xml:lang="fi">Sony-SRF-raakakuva</comment>
- <comment xml:lang="fo">Sony SRF rámynd</comment>
- <comment xml:lang="fr">image brute SRF Sony</comment>
- <comment xml:lang="ga">amhíomhá Sony SRF</comment>
- <comment xml:lang="gl">imaxe en bruto SRF de sony</comment>
- <comment xml:lang="he">תמונה גולמית של Sony SRF</comment>
- <comment xml:lang="hr">Sony SRF osnovna slika</comment>
- <comment xml:lang="hu">Sony SRF nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Sony SRF</comment>
- <comment xml:lang="id">Citra mentah Sony SRF</comment>
- <comment xml:lang="it">Immagine raw Sony SRF</comment>
- <comment xml:lang="ja">Sony SRF raw 画像</comment>
- <comment xml:lang="kk">Sony SRF өңделмеген суреті</comment>
- <comment xml:lang="ko">소니 SRF RAW 사진</comment>
- <comment xml:lang="lt">Sony SRF neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Sony SRF jēlattēls</comment>
- <comment xml:lang="nb">Sony SRF raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Sony SRF-beeld</comment>
- <comment xml:lang="nn">Sony SRF råbilete</comment>
- <comment xml:lang="oc">imatge brut SRF Sony</comment>
- <comment xml:lang="pl">Surowy obraz SRF Sony</comment>
- <comment xml:lang="pt">imagem em bruto Sony SRF</comment>
- <comment xml:lang="pt_BR">Imagem bruta SRF da Sony</comment>
- <comment xml:lang="ro">Imagine brută Sony SRF</comment>
- <comment xml:lang="ru">Необработанное изображение Sony SRF</comment>
- <comment xml:lang="sk">Surový obrázok Sony SRF</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Sony SRF</comment>
- <comment xml:lang="sq">Figurë raw Sony SRF</comment>
- <comment xml:lang="sr">Сони СРФ сирова слика</comment>
- <comment xml:lang="sv">Sony SRF-råbild</comment>
- <comment xml:lang="tr">Sony SRF ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив SRF Sony</comment>
- <comment xml:lang="vi">Ảnh thô Sony SRF</comment>
+ <comment xml:lang="zh_TW">Sony SRF 原始影像</comment>
<comment xml:lang="zh_CN">索尼 SRF 原始映像</comment>
- <comment xml:lang="zh_TW">Sony SRF 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Sony SRF</comment>
+ <comment xml:lang="uk">цифровий негатив SRF Sony</comment>
+ <comment xml:lang="tr">Sony SRF ham görüntüsü</comment>
+ <comment xml:lang="sv">Sony SRF-råbild</comment>
+ <comment xml:lang="sr">Сони СРФ сирова слика</comment>
+ <comment xml:lang="sq">figurë Sony SRF e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Sony SRF</comment>
+ <comment xml:lang="si">Sony SRF අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Sony SRF</comment>
+ <comment xml:lang="ru">Необработанное изображение Sony SRF</comment>
+ <comment xml:lang="ro">Imagine brută Sony SRF</comment>
+ <comment xml:lang="pt_BR">Imagem bruta SRF da Sony</comment>
+ <comment xml:lang="pt">imagem em bruto Sony SRF</comment>
+ <comment xml:lang="pl">Surowy obraz SRF Sony</comment>
+ <comment xml:lang="oc">imatge brut SRF Sony</comment>
+ <comment xml:lang="nn">Sony SRF råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Sony SRF-beeld</comment>
+ <comment xml:lang="nb">Sony SRF raw-bilde</comment>
+ <comment xml:lang="lv">Sony SRF jēlattēls</comment>
+ <comment xml:lang="lt">Sony SRF neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">소니 SRF RAW 사진</comment>
+ <comment xml:lang="kk">Sony SRF өңделмеген суреті</comment>
+ <comment xml:lang="ja">Sony SRF raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Sony SRF</comment>
+ <comment xml:lang="is">Sony SRF hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Sony SRF</comment>
+ <comment xml:lang="ia">Imagine brute Sony SRF</comment>
+ <comment xml:lang="hu">Sony SRF nyers kép</comment>
+ <comment xml:lang="hr">Sony SRF osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Sony SRF</comment>
+ <comment xml:lang="gl">imaxe en bruto SRF de sony</comment>
+ <comment xml:lang="ga">amhíomhá Sony SRF</comment>
+ <comment xml:lang="fur">imagjin grese Sony SRF</comment>
+ <comment xml:lang="fr">image brute SRF Sony</comment>
+ <comment xml:lang="fo">Sony SRF rámynd</comment>
+ <comment xml:lang="fi">Sony-SRF-raakakuva</comment>
+ <comment xml:lang="eu">Sony SRF irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto SRF de Sony</comment>
+ <comment xml:lang="en_GB">Sony SRF raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sony SRF</comment>
+ <comment xml:lang="de">Sony-SRF-Rohbild</comment>
+ <comment xml:lang="da">Sony SRF raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Sony SRF</comment>
+ <comment xml:lang="ca">imatge en cru de Sony SRF</comment>
+ <comment xml:lang="bg">Изображение — Sony SRF raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Sony SRF</comment>
+ <comment xml:lang="be">неапрацаваная выява Sony SRF</comment>
+ <comment xml:lang="ar">صورة Sony SRF خامة</comment>
+ <comment xml:lang="af">Sony SRF rou beeld</comment>
<acronym>SRF</acronym>
<expanded-acronym>Sony Raw Format</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26842,52 +29345,57 @@
</mime-type>
<mime-type type="image/x-sony-sr2">
<comment>Sony SR2 raw image</comment>
- <comment xml:lang="ar">صورة Sony SR2 خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Sony SR2</comment>
- <comment xml:lang="bg">Изображение — Sony SR2 raw</comment>
- <comment xml:lang="ca">imatge en cru de Sony SR2</comment>
- <comment xml:lang="cs">surový obrázek Sony SR2</comment>
- <comment xml:lang="da">Sony SR2-råbillede</comment>
- <comment xml:lang="de">Sony-SR2-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sony SR2</comment>
- <comment xml:lang="en_GB">Sony SR2 raw image</comment>
- <comment xml:lang="es">imagen en bruto SR2 de Sony</comment>
- <comment xml:lang="eu">Sony SR2 irudi gordina</comment>
- <comment xml:lang="fi">Sony-SR2-raakakuva</comment>
- <comment xml:lang="fo">Sony SR2 rámynd</comment>
- <comment xml:lang="fr">image brute SR2 Sony</comment>
- <comment xml:lang="ga">amhíomhá Sony SR2</comment>
- <comment xml:lang="gl">imaxe en bruto SR2 de sony</comment>
- <comment xml:lang="he">תמונה גולמית של Sony SR2</comment>
- <comment xml:lang="hr">Sony SR2 osnovna slika</comment>
- <comment xml:lang="hu">Sony SR2 nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Sony SR2</comment>
- <comment xml:lang="id">Citra mentah Sony SR2</comment>
- <comment xml:lang="it">Immagine raw Sony SR2</comment>
- <comment xml:lang="ja">Sony SR2 raw 画像</comment>
- <comment xml:lang="kk">Sony SR2 өңделмеген суреті</comment>
- <comment xml:lang="ko">소니 SR2 RAW 사진</comment>
- <comment xml:lang="lt">Sony SR2 neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Sony SR2 jēlattēls</comment>
- <comment xml:lang="nb">Sony SR2 raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Sony SR2-beeld</comment>
- <comment xml:lang="nn">Sony SR2 råbilete</comment>
- <comment xml:lang="oc">imatge brut SR2 Sony</comment>
- <comment xml:lang="pl">Surowy obraz SR2 Sony</comment>
- <comment xml:lang="pt">imagem em bruto Sony SR2</comment>
- <comment xml:lang="pt_BR">Imagem bruta SR2 da Sony</comment>
- <comment xml:lang="ro">Imagine brută Sony SR2</comment>
- <comment xml:lang="ru">Необработанное изображение Sony SR2</comment>
- <comment xml:lang="sk">Surový obrázok Sony SR2</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Sony SR2</comment>
- <comment xml:lang="sq">Figurë raw Sony SR2</comment>
- <comment xml:lang="sr">Сони СР2 сирова слика</comment>
- <comment xml:lang="sv">Sony SR2-råbild</comment>
- <comment xml:lang="tr">Sony SR2 ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив SR2 Sony</comment>
- <comment xml:lang="vi">Ảnh thô Sony SR2</comment>
+ <comment xml:lang="zh_TW">Sony SR2 原始影像</comment>
<comment xml:lang="zh_CN">索尼 SR2 原始映像</comment>
- <comment xml:lang="zh_TW">Sony SR2 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Sony SR2</comment>
+ <comment xml:lang="uk">цифровий негатив SR2 Sony</comment>
+ <comment xml:lang="tr">Sony SR2 ham görüntüsü</comment>
+ <comment xml:lang="sv">Sony SR2-råbild</comment>
+ <comment xml:lang="sr">Сони СР2 сирова слика</comment>
+ <comment xml:lang="sq">figurë Sony SR2 e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Sony SR2</comment>
+ <comment xml:lang="si">Sony SR2 අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Sony SR2</comment>
+ <comment xml:lang="ru">Необработанное изображение Sony SR2</comment>
+ <comment xml:lang="ro">Imagine brută Sony SR2</comment>
+ <comment xml:lang="pt_BR">Imagem bruta SR2 da Sony</comment>
+ <comment xml:lang="pt">imagem em bruto Sony SR2</comment>
+ <comment xml:lang="pl">Surowy obraz SR2 Sony</comment>
+ <comment xml:lang="oc">imatge brut SR2 Sony</comment>
+ <comment xml:lang="nn">Sony SR2 råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Sony SR2-beeld</comment>
+ <comment xml:lang="nb">Sony SR2 raw-bilde</comment>
+ <comment xml:lang="lv">Sony SR2 jēlattēls</comment>
+ <comment xml:lang="lt">Sony SR2 neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">소니 SR2 RAW 사진</comment>
+ <comment xml:lang="kk">Sony SR2 өңделмеген суреті</comment>
+ <comment xml:lang="ja">Sony SR2 raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Sony SR2</comment>
+ <comment xml:lang="is">Sony SR2 hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Sony SR2</comment>
+ <comment xml:lang="ia">Imagine brute Sony SR2</comment>
+ <comment xml:lang="hu">Sony SR2 nyers kép</comment>
+ <comment xml:lang="hr">Sony SR2 osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Sony SR2</comment>
+ <comment xml:lang="gl">imaxe en bruto SR2 de sony</comment>
+ <comment xml:lang="ga">amhíomhá Sony SR2</comment>
+ <comment xml:lang="fur">imagjin grese Sony SR2</comment>
+ <comment xml:lang="fr">image brute SR2 Sony</comment>
+ <comment xml:lang="fo">Sony SR2 rámynd</comment>
+ <comment xml:lang="fi">Sony-SR2-raakakuva</comment>
+ <comment xml:lang="eu">Sony SR2 irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto SR2 de Sony</comment>
+ <comment xml:lang="en_GB">Sony SR2 raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sony SR2</comment>
+ <comment xml:lang="de">Sony-SR2-Rohbild</comment>
+ <comment xml:lang="da">Sony SR2 raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Sony SR2</comment>
+ <comment xml:lang="ca">imatge en cru de Sony SR2</comment>
+ <comment xml:lang="bg">Изображение — Sony SR2 raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Sony SR2</comment>
+ <comment xml:lang="be">неапрацаваная выява Sony SR2</comment>
+ <comment xml:lang="ar">صورة Sony SR2 خامة</comment>
+ <comment xml:lang="af">Sony SR2 rou beeld</comment>
<acronym>SR2</acronym>
<expanded-acronym>Sony Raw format 2</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26896,52 +29404,57 @@
</mime-type>
<mime-type type="image/x-sony-arw">
<comment>Sony ARW raw image</comment>
- <comment xml:lang="ar">صورة Sony ARW خامة</comment>
- <comment xml:lang="be@latin">Suvoraja vyjava Sony ARW</comment>
- <comment xml:lang="bg">Изображение — Sony ARW raw</comment>
- <comment xml:lang="ca">imatge en cru de Sony ARW</comment>
- <comment xml:lang="cs">surový obrázek Sony ARW</comment>
- <comment xml:lang="da">Sony ARW-råbillede</comment>
- <comment xml:lang="de">Sony-ARW-Rohbild</comment>
- <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sony ARW</comment>
- <comment xml:lang="en_GB">Sony ARW raw image</comment>
- <comment xml:lang="es">imagen en bruto ARW de Sony</comment>
- <comment xml:lang="eu">Sony ARW irudi gordina</comment>
- <comment xml:lang="fi">Sony-ARW-raakakuva</comment>
- <comment xml:lang="fo">Sony ARW rámynd</comment>
- <comment xml:lang="fr">image brute ARW Sony</comment>
- <comment xml:lang="ga">amhíomhá Sony ARW</comment>
- <comment xml:lang="gl">imaxe en bruto ARW de sony</comment>
- <comment xml:lang="he">תמונה גולמית של Sony ARW</comment>
- <comment xml:lang="hr">Sony ARW osnovna slika</comment>
- <comment xml:lang="hu">Sony ARW nyers kép</comment>
- <comment xml:lang="ia">Imagine brute Sony ARW</comment>
- <comment xml:lang="id">Citra mentah Sony ARW</comment>
- <comment xml:lang="it">Immagine raw Sony ARW</comment>
- <comment xml:lang="ja">Sony ARW raw 画像</comment>
- <comment xml:lang="kk">Sony ARW өңделмеген суреті</comment>
- <comment xml:lang="ko">소니 ARW RAW 사진</comment>
- <comment xml:lang="lt">Sony ARW neapdorotas paveikslėlis</comment>
- <comment xml:lang="lv">Sony ARW jēlattēls</comment>
- <comment xml:lang="nb">Sony ARW raw-bilde</comment>
- <comment xml:lang="nl">onbewerkt Sony ARW-beeld</comment>
- <comment xml:lang="nn">Sony ARW råbilete</comment>
- <comment xml:lang="oc">imatge brut ARW Sony</comment>
- <comment xml:lang="pl">Surowy obraz ARW Sony</comment>
- <comment xml:lang="pt">imagem em bruto Sony ARW</comment>
- <comment xml:lang="pt_BR">Imagem bruta ARW da Sony</comment>
- <comment xml:lang="ro">Imagine brută Sony ARW</comment>
- <comment xml:lang="ru">Необработанное изображение Sony ARW</comment>
- <comment xml:lang="sk">Surový obrázok Sony ARW</comment>
- <comment xml:lang="sl">Surova slikovna datoteka Sony ARW</comment>
- <comment xml:lang="sq">Figurë raw Sony ARW</comment>
- <comment xml:lang="sr">Сони АРВ сирова слика</comment>
- <comment xml:lang="sv">Sony ARW-råbild</comment>
- <comment xml:lang="tr">Sony ARW ham görüntüsü</comment>
- <comment xml:lang="uk">цифровий негатив ARW Sony</comment>
- <comment xml:lang="vi">Ảnh thô Sony ARW</comment>
+ <comment xml:lang="zh_TW">Sony ARW 原始影像</comment>
<comment xml:lang="zh_CN">索尼 ARW 原始映像</comment>
- <comment xml:lang="zh_TW">Sony ARW 原生影像</comment>
+ <comment xml:lang="vi">Ảnh thô Sony ARW</comment>
+ <comment xml:lang="uk">цифровий негатив ARW Sony</comment>
+ <comment xml:lang="tr">Sony ARW ham görüntüsü</comment>
+ <comment xml:lang="sv">Sony ARW-råbild</comment>
+ <comment xml:lang="sr">Сони АРВ сирова слика</comment>
+ <comment xml:lang="sq">figurë Sony ARW e papërpunuar</comment>
+ <comment xml:lang="sl">Surova slikovna datoteka Sony ARW</comment>
+ <comment xml:lang="si">Sony ARW අමු රූපය</comment>
+ <comment xml:lang="sk">Surový obrázok Sony ARW</comment>
+ <comment xml:lang="ru">Необработанное изображение Sony ARW</comment>
+ <comment xml:lang="ro">Imagine brută Sony ARW</comment>
+ <comment xml:lang="pt_BR">Imagem bruta ARW da Sony</comment>
+ <comment xml:lang="pt">imagem em bruto Sony ARW</comment>
+ <comment xml:lang="pl">Surowy obraz ARW Sony</comment>
+ <comment xml:lang="oc">imatge brut ARW Sony</comment>
+ <comment xml:lang="nn">Sony ARW råbilete</comment>
+ <comment xml:lang="nl">onbewerkt Sony ARW-beeld</comment>
+ <comment xml:lang="nb">Sony ARW raw-bilde</comment>
+ <comment xml:lang="lv">Sony ARW jēlattēls</comment>
+ <comment xml:lang="lt">Sony ARW neapdorotas paveikslėlis</comment>
+ <comment xml:lang="ko">소니 ARW RAW 사진</comment>
+ <comment xml:lang="kk">Sony ARW өңделмеген суреті</comment>
+ <comment xml:lang="ja">Sony ARW raw 画像</comment>
+ <comment xml:lang="it">Immagine raw Sony ARW</comment>
+ <comment xml:lang="is">Sony ARW hrámynd</comment>
+ <comment xml:lang="id">Citra mentah Sony ARW</comment>
+ <comment xml:lang="ia">Imagine brute Sony ARW</comment>
+ <comment xml:lang="hu">Sony ARW nyers kép</comment>
+ <comment xml:lang="hr">Sony ARW osnovna slika</comment>
+ <comment xml:lang="he">תמונה גולמית של Sony ARW</comment>
+ <comment xml:lang="gl">imaxe en bruto ARW de sony</comment>
+ <comment xml:lang="ga">amhíomhá Sony ARW</comment>
+ <comment xml:lang="fur">imagjin grese Sony ARW</comment>
+ <comment xml:lang="fr">image brute ARW Sony</comment>
+ <comment xml:lang="fo">Sony ARW rámynd</comment>
+ <comment xml:lang="fi">Sony-ARW-raakakuva</comment>
+ <comment xml:lang="eu">Sony ARW irudi gordina</comment>
+ <comment xml:lang="es">imagen en bruto ARW de Sony</comment>
+ <comment xml:lang="en_GB">Sony ARW raw image</comment>
+ <comment xml:lang="el">Ανεπεξέργαστη εικόνα Sony ARW</comment>
+ <comment xml:lang="de">Sony-ARW-Rohbild</comment>
+ <comment xml:lang="da">Sony ARW raw-billede</comment>
+ <comment xml:lang="cs">surový obrázek Sony ARW</comment>
+ <comment xml:lang="ca">imatge en cru de Sony ARW</comment>
+ <comment xml:lang="bg">Изображение — Sony ARW raw</comment>
+ <comment xml:lang="be@latin">Suvoraja vyjava Sony ARW</comment>
+ <comment xml:lang="be">неапрацаваная выява Sony ARW</comment>
+ <comment xml:lang="ar">صورة Sony ARW خامة</comment>
+ <comment xml:lang="af">Sony ARW rou beeld</comment>
<acronym>ARW</acronym>
<expanded-acronym>Alpha Raw format</expanded-acronym>
<sub-class-of type="image/x-dcraw"/>
@@ -26950,908 +29463,912 @@
</mime-type>
<mime-type type="image/png">
<comment>PNG image</comment>
- <comment xml:lang="ar">صورة PNG</comment>
- <comment xml:lang="az">PNG rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava PNG</comment>
- <comment xml:lang="bg">Изображение — PNG</comment>
- <comment xml:lang="ca">imatge PNG</comment>
- <comment xml:lang="cs">obrázek PNG</comment>
- <comment xml:lang="cy">Delwedd PNG</comment>
- <comment xml:lang="da">PNG-billede</comment>
- <comment xml:lang="de">PNG-Bild</comment>
- <comment xml:lang="el">Εικόνα PNG</comment>
- <comment xml:lang="en_GB">PNG image</comment>
- <comment xml:lang="eo">PNG-bildo</comment>
- <comment xml:lang="es">imagen PNG</comment>
- <comment xml:lang="eu">PNG irudia</comment>
- <comment xml:lang="fi">PNG-kuva</comment>
- <comment xml:lang="fo">PNG mynd</comment>
- <comment xml:lang="fr">image PNG</comment>
- <comment xml:lang="ga">íomhá PNG</comment>
- <comment xml:lang="gl">imaxe PNG</comment>
- <comment xml:lang="he">תמונת PNG</comment>
- <comment xml:lang="hr">PNG slika</comment>
- <comment xml:lang="hu">PNG-kép</comment>
- <comment xml:lang="ia">Imagine PNG</comment>
- <comment xml:lang="id">Citra PNG</comment>
- <comment xml:lang="it">Immagine PNG</comment>
- <comment xml:lang="ja">PNG 画像</comment>
- <comment xml:lang="kk">PNG суреті</comment>
- <comment xml:lang="ko">PNG 그림</comment>
- <comment xml:lang="lt">PNG paveikslėlis</comment>
- <comment xml:lang="lv">PNG attēls</comment>
- <comment xml:lang="ms">Imej PNG</comment>
- <comment xml:lang="nb">PNG-bilde</comment>
- <comment xml:lang="nl">PNG-afbeelding</comment>
- <comment xml:lang="nn">PNG-bilete</comment>
- <comment xml:lang="oc">imatge PNG</comment>
- <comment xml:lang="pl">Obraz PNG</comment>
- <comment xml:lang="pt">imagem PNG</comment>
- <comment xml:lang="pt_BR">Imagem PNG</comment>
- <comment xml:lang="ro">Imagine PNG</comment>
- <comment xml:lang="ru">Изображение PNG</comment>
- <comment xml:lang="sk">Obrázok PNG</comment>
- <comment xml:lang="sl">Slikovna datoteka PNG</comment>
- <comment xml:lang="sq">Figurë PNG</comment>
- <comment xml:lang="sr">ПНГ слика</comment>
- <comment xml:lang="sv">PNG-bild</comment>
- <comment xml:lang="tr">PNG görüntüsü</comment>
- <comment xml:lang="uk">зображення PNG</comment>
- <comment xml:lang="vi">Ảnh PNG</comment>
- <comment xml:lang="zh_CN">PNG 图像</comment>
<comment xml:lang="zh_TW">PNG 影像</comment>
- <magic priority="50">
- <match value="\x89PNG" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">PNG 图像</comment>
+ <comment xml:lang="vi">Ảnh PNG</comment>
+ <comment xml:lang="uk">зображення PNG</comment>
+ <comment xml:lang="tr">PNG görüntüsü</comment>
+ <comment xml:lang="sv">PNG-bild</comment>
+ <comment xml:lang="sr">ПНГ слика</comment>
+ <comment xml:lang="sq">figurë PNG</comment>
+ <comment xml:lang="sl">Slikovna datoteka PNG</comment>
+ <comment xml:lang="si">PNG රූපය</comment>
+ <comment xml:lang="sk">Obrázok PNG</comment>
+ <comment xml:lang="ru">Изображение PNG</comment>
+ <comment xml:lang="ro">Imagine PNG</comment>
+ <comment xml:lang="pt_BR">Imagem PNG</comment>
+ <comment xml:lang="pt">imagem PNG</comment>
+ <comment xml:lang="pl">Obraz PNG</comment>
+ <comment xml:lang="oc">imatge PNG</comment>
+ <comment xml:lang="nn">PNG-bilete</comment>
+ <comment xml:lang="nl">PNG-afbeelding</comment>
+ <comment xml:lang="nb">PNG-bilde</comment>
+ <comment xml:lang="ms">Imej PNG</comment>
+ <comment xml:lang="lv">PNG attēls</comment>
+ <comment xml:lang="lt">PNG paveikslėlis</comment>
+ <comment xml:lang="ko">PNG 그림</comment>
+ <comment xml:lang="kk">PNG суреті</comment>
+ <comment xml:lang="ka">PNG გამოსახულება</comment>
+ <comment xml:lang="ja">PNG 画像</comment>
+ <comment xml:lang="it">Immagine PNG</comment>
+ <comment xml:lang="is">PNG mynd</comment>
+ <comment xml:lang="id">Citra PNG</comment>
+ <comment xml:lang="ia">Imagine PNG</comment>
+ <comment xml:lang="hu">PNG-kép</comment>
+ <comment xml:lang="hr">PNG slika</comment>
+ <comment xml:lang="he">תמונת PNG</comment>
+ <comment xml:lang="gl">imaxe PNG</comment>
+ <comment xml:lang="ga">íomhá PNG</comment>
+ <comment xml:lang="fur">imagjin PNG</comment>
+ <comment xml:lang="fr">image PNG</comment>
+ <comment xml:lang="fo">PNG mynd</comment>
+ <comment xml:lang="fi">PNG-kuva</comment>
+ <comment xml:lang="eu">PNG irudia</comment>
+ <comment xml:lang="es">imagen PNG</comment>
+ <comment xml:lang="eo">PNG-bildo</comment>
+ <comment xml:lang="en_GB">PNG image</comment>
+ <comment xml:lang="el">Εικόνα PNG</comment>
+ <comment xml:lang="de">PNG-Bild</comment>
+ <comment xml:lang="da">PNG-billede</comment>
+ <comment xml:lang="cy">Delwedd PNG</comment>
+ <comment xml:lang="cs">obrázek PNG</comment>
+ <comment xml:lang="ca">imatge PNG</comment>
+ <comment xml:lang="bg">Изображение — PNG</comment>
+ <comment xml:lang="be@latin">Vyjava PNG</comment>
+ <comment xml:lang="be">выява PNG</comment>
+ <comment xml:lang="az">PNG rəsmi</comment>
+ <comment xml:lang="ar">صورة PNG</comment>
+ <comment xml:lang="af">PNG-beeld</comment>
+ <acronym>PNG</acronym>
+ <expanded-acronym>Portable Network Graphics</expanded-acronym>
+ <magic>
+ <match type="string" value="\x89PNG\r\n\x1A\n" offset="0"/>
</magic>
<glob pattern="*.png"/>
</mime-type>
+ <mime-type type="image/apng">
+ <comment>Animated PNG image</comment>
+ <comment xml:lang="uk">анімоване зображення PNG</comment>
+ <comment xml:lang="sv">Animerad PNG-bild</comment>
+ <comment xml:lang="ru">Анимированное изображение PNG</comment>
+ <comment xml:lang="pl">Animowany obraz PNG</comment>
+ <comment xml:lang="ja">PNG動画</comment>
+ <comment xml:lang="it">Immagine PNG animata</comment>
+ <comment xml:lang="gl">Imaxe de PNG animado</comment>
+ <comment xml:lang="eu">PNG irudi animatua</comment>
+ <comment xml:lang="es">imagen PNG animada</comment>
+ <comment xml:lang="de">Animiertes PNG-Bild</comment>
+ <comment xml:lang="be">анімаваная выява PNG</comment>
+ <acronym>PNG</acronym>
+ <expanded-acronym>Portable Network Graphics</expanded-acronym>
+ <sub-class-of type="image/png"/>
+ <magic priority="60">
+ <match type="string" value="\x89PNG\r\n\x1A\n" offset="0">
+ <match type="string" value="acTL" offset="37"/>
+ </match>
+ </magic>
+ <glob pattern="*.apng"/>
+ <glob pattern="*.png" weight="40"/>
+ <alias type="image/vnd.mozilla.apng"/>
+ </mime-type>
<mime-type type="image/rle">
- <comment>Run Length Encoded bitmap image</comment>
- <comment xml:lang="ar">تشغيل صورة نقطية طولية الترميز</comment>
- <comment xml:lang="be@latin">Bitmapnaja vyjava, zakadavanaja ŭ Run Length</comment>
- <comment xml:lang="bg">Изображение — RLE Bitmap</comment>
- <comment xml:lang="ca">imatge de mapa de bits «Run Lenght Encoded»</comment>
- <comment xml:lang="cs">obrázek bitové mapy Run Length Encoded</comment>
- <comment xml:lang="da">Run Length Encoded-bitmapbillede</comment>
- <comment xml:lang="de">Lauflängenkodiertes Bitmap-Bild</comment>
- <comment xml:lang="el">Εικόνα bitmap κωδικοποιημένου μήκος εκτέλεσης</comment>
- <comment xml:lang="en_GB">Run Length Encoded bitmap image</comment>
- <comment xml:lang="es">mapa de bits con codificación del tamaño durante la ejecución</comment>
- <comment xml:lang="eu">'Run Lenght Encoded' bitmap irudia</comment>
- <comment xml:lang="fi">RLE-koodattu bittikartta</comment>
- <comment xml:lang="fr">image matricielle Run Length Encoded</comment>
- <comment xml:lang="ga">íomhá ghiotánmhapach ionchódaithe fad reatha</comment>
- <comment xml:lang="gl">mapa de bits con codificación do tamaño durante a execución</comment>
- <comment xml:lang="he">מקודד מפת סיביות של Run Length</comment>
- <comment xml:lang="hr">Run Length Encoded bitmap slika</comment>
- <comment xml:lang="hu">Run Length Encoded bitkép</comment>
- <comment xml:lang="ia">Imagine raster in codification Run-Length</comment>
- <comment xml:lang="id">Citra peta bit Run Length Encoded</comment>
- <comment xml:lang="it">Immagine bitmap RLE (Run Length Encoded)</comment>
- <comment xml:lang="ja">ランレングス符号化ビットマップ画像</comment>
- <comment xml:lang="kk">RLE сығылған растрлік суреті</comment>
- <comment xml:lang="ko">RLE 인코딩된 비트맵 그림</comment>
- <comment xml:lang="lt">Run Length Encoded rastrinis paveikslėlis</comment>
- <comment xml:lang="lv">Secīgo atkārtojumu kodēts bitkartes attēls</comment>
- <comment xml:lang="nb">Run Length Encoded bitmap bilde</comment>
- <comment xml:lang="nl">RLE-gecodeerde bitmap-afbeelding</comment>
- <comment xml:lang="nn">Run Length Encoded punktgrafikk</comment>
- <comment xml:lang="oc">imatge matriciala Run Length Encoded</comment>
- <comment xml:lang="pl">Obraz bitmapy RLE</comment>
- <comment xml:lang="pt">mapa de bitas Run Length Encoded</comment>
- <comment xml:lang="pt_BR">Classe de comprimento imagem bitmap codificada</comment>
- <comment xml:lang="ro">Imagine bitmap codată RLE</comment>
- <comment xml:lang="ru">Растровое изображение, сжатое RLE</comment>
- <comment xml:lang="sk">Bitmapový obrázok Run Length Encoded</comment>
- <comment xml:lang="sl">Zaporedno kodirana bitna slika (RLE)</comment>
- <comment xml:lang="sq">Figurë bitmap RLE (Run Length Encoded)</comment>
- <comment xml:lang="sr">битмап слика кодирана дужином скупине</comment>
- <comment xml:lang="sv">Körlängdskodad bitmappbild</comment>
- <comment xml:lang="tr">Run Length Encoded bit eşlem görüntüsü</comment>
+ <comment>RLE bitmap image</comment>
+ <comment xml:lang="zh_TW">RLE 點陣影像</comment>
+ <comment xml:lang="zh_CN">RLE 位图图像</comment>
<comment xml:lang="uk">растрове зображення RLE</comment>
- <comment xml:lang="vi">Ảnh mảng mã hóa chiều dài chạy (RLE)</comment>
- <comment xml:lang="zh_CN">游程编码位图</comment>
- <comment xml:lang="zh_TW">Run Length Encoded 點陣影像</comment>
+ <comment xml:lang="tr">RLE bit eşlem görüntüsü</comment>
+ <comment xml:lang="sv">RLE bitmappsbild</comment>
+ <comment xml:lang="sq">figurë bitmap RLE</comment>
+ <comment xml:lang="sl">Bitna slika RLE</comment>
+ <comment xml:lang="si">RLE බිට්මැප් රූපය</comment>
+ <comment xml:lang="ru">Растровое изображение RLE</comment>
+ <comment xml:lang="pt_BR">Imagem bitmap RLE</comment>
+ <comment xml:lang="pl">Obraz bitmapy RLE</comment>
+ <comment xml:lang="nl">RLE-bitmapafbeelding</comment>
+ <comment xml:lang="ko">RLE 비트맵 그림</comment>
+ <comment xml:lang="kk">RLE растрлық суреті</comment>
+ <comment xml:lang="ja">RLE ビットマップ画像</comment>
+ <comment xml:lang="it">Immagine bitmap RLE</comment>
+ <comment xml:lang="is">RLE bitamynd</comment>
+ <comment xml:lang="id">Citra bitmap RLE</comment>
+ <comment xml:lang="hu">RLE bitkép</comment>
+ <comment xml:lang="hr">RLE bitmap slika</comment>
+ <comment xml:lang="he">תמונת מפת סיביות RLE</comment>
+ <comment xml:lang="gl">Imaxe de mapa de bits RLE</comment>
+ <comment xml:lang="fr">image matricielle RLE</comment>
+ <comment xml:lang="fi">RLE-bittikarttakuva</comment>
+ <comment xml:lang="eu">RLE bitmap irudia</comment>
+ <comment xml:lang="es">imagen de mapa de los bit RLE</comment>
+ <comment xml:lang="en_GB">RLE bitmap image</comment>
+ <comment xml:lang="de">Lauflängenkodiertes Bitmap-Bild</comment>
+ <comment xml:lang="da">RLE bitmap-billede</comment>
+ <comment xml:lang="ca">imatge de mapa de bits RLE</comment>
+ <comment xml:lang="bg">Изображение — RLE bitmap</comment>
+ <comment xml:lang="be">растравая выява RLE</comment>
+ <comment xml:lang="ar">صورة نقطية RLE</comment>
+ <acronym>RLE</acronym>
+ <expanded-acronym>Run Length Encoded</expanded-acronym>
<glob pattern="*.rle"/>
</mime-type>
<mime-type type="image/svg+xml">
<comment>SVG image</comment>
- <comment xml:lang="ar">صورة SVG</comment>
- <comment xml:lang="be@latin">Vyjava SVG</comment>
- <comment xml:lang="bg">Изображение — SVG</comment>
- <comment xml:lang="ca">imatge SVG</comment>
- <comment xml:lang="cs">obrázek SVG</comment>
- <comment xml:lang="da">SVG-billede</comment>
- <comment xml:lang="de">SVG-Bild</comment>
- <comment xml:lang="el">Εικόνα SVG</comment>
- <comment xml:lang="en_GB">SVG image</comment>
- <comment xml:lang="eo">SVG-bildo</comment>
- <comment xml:lang="es">imagen SVG</comment>
- <comment xml:lang="eu">SVG irudia</comment>
- <comment xml:lang="fi">SVG-kuva</comment>
- <comment xml:lang="fo">SVG mynd</comment>
- <comment xml:lang="fr">image SVG</comment>
- <comment xml:lang="ga">íomhá SVG</comment>
- <comment xml:lang="gl">imaxe SVG</comment>
- <comment xml:lang="he">תמונת SVG</comment>
- <comment xml:lang="hr">SVG slika</comment>
- <comment xml:lang="hu">SVG kép</comment>
- <comment xml:lang="ia">Imagine SVG</comment>
- <comment xml:lang="id">Citra SVG</comment>
- <comment xml:lang="it">Immagine SVG</comment>
- <comment xml:lang="ja">SVG 画像</comment>
- <comment xml:lang="kk">SVG суреті</comment>
- <comment xml:lang="ko">SVG 그림</comment>
- <comment xml:lang="lt">SVG paveikslėlis</comment>
- <comment xml:lang="lv">SVG attēls</comment>
- <comment xml:lang="nb">SVG-bilde</comment>
- <comment xml:lang="nl">SVG-afbeelding</comment>
- <comment xml:lang="nn">SVG-bilete</comment>
- <comment xml:lang="oc">imatge SVG</comment>
- <comment xml:lang="pl">Obraz SVG</comment>
- <comment xml:lang="pt">imagem SVG</comment>
- <comment xml:lang="pt_BR">Imagem SVG</comment>
- <comment xml:lang="ro">Imagine SVG</comment>
- <comment xml:lang="ru">Изображение SVG</comment>
- <comment xml:lang="sk">Obrázok SVG</comment>
- <comment xml:lang="sl">Slikovna vektorska datoteka SVG</comment>
- <comment xml:lang="sq">Figurë SVG</comment>
- <comment xml:lang="sr">СВГ слика</comment>
- <comment xml:lang="sv">SVG-bild</comment>
- <comment xml:lang="tr">SVG görüntüsü</comment>
- <comment xml:lang="uk">зображення SVG</comment>
- <comment xml:lang="vi">Ảnh SVG</comment>
- <comment xml:lang="zh_CN">SVG 图像</comment>
<comment xml:lang="zh_TW">SVG 影像</comment>
+ <comment xml:lang="zh_CN">SVG 图像</comment>
+ <comment xml:lang="vi">Ảnh SVG</comment>
+ <comment xml:lang="uk">зображення SVG</comment>
+ <comment xml:lang="tr">SVG görüntüsü</comment>
+ <comment xml:lang="sv">SVG-bild</comment>
+ <comment xml:lang="sr">СВГ слика</comment>
+ <comment xml:lang="sq">figurë SVG</comment>
+ <comment xml:lang="sl">Slikovna vektorska datoteka SVG</comment>
+ <comment xml:lang="si">SVG රූපය</comment>
+ <comment xml:lang="sk">Obrázok SVG</comment>
+ <comment xml:lang="ru">Изображение SVG</comment>
+ <comment xml:lang="ro">Imagine SVG</comment>
+ <comment xml:lang="pt_BR">Imagem SVG</comment>
+ <comment xml:lang="pt">imagem SVG</comment>
+ <comment xml:lang="pl">Obraz SVG</comment>
+ <comment xml:lang="oc">imatge SVG</comment>
+ <comment xml:lang="nn">SVG-bilete</comment>
+ <comment xml:lang="nl">SVG-afbeelding</comment>
+ <comment xml:lang="nb">SVG-bilde</comment>
+ <comment xml:lang="lv">SVG attēls</comment>
+ <comment xml:lang="lt">SVG paveikslėlis</comment>
+ <comment xml:lang="ko">SVG 그림</comment>
+ <comment xml:lang="kk">SVG суреті</comment>
+ <comment xml:lang="ka">SVG გამოსახულება</comment>
+ <comment xml:lang="ja">SVG 画像</comment>
+ <comment xml:lang="it">Immagine SVG</comment>
+ <comment xml:lang="is">SVG mynd</comment>
+ <comment xml:lang="id">Citra SVG</comment>
+ <comment xml:lang="ia">Imagine SVG</comment>
+ <comment xml:lang="hu">SVG kép</comment>
+ <comment xml:lang="hr">SVG slika</comment>
+ <comment xml:lang="he">תמונת SVG</comment>
+ <comment xml:lang="gl">imaxe SVG</comment>
+ <comment xml:lang="ga">íomhá SVG</comment>
+ <comment xml:lang="fur">imagjin SVG</comment>
+ <comment xml:lang="fr">image SVG</comment>
+ <comment xml:lang="fo">SVG mynd</comment>
+ <comment xml:lang="fi">SVG-kuva</comment>
+ <comment xml:lang="eu">SVG irudia</comment>
+ <comment xml:lang="es">imagen SVG</comment>
+ <comment xml:lang="eo">SVG-bildo</comment>
+ <comment xml:lang="en_GB">SVG image</comment>
+ <comment xml:lang="el">Εικόνα SVG</comment>
+ <comment xml:lang="de">SVG-Bild</comment>
+ <comment xml:lang="da">SVG-billede</comment>
+ <comment xml:lang="cs">obrázek SVG</comment>
+ <comment xml:lang="ca">imatge SVG</comment>
+ <comment xml:lang="bg">Изображение — SVG</comment>
+ <comment xml:lang="be@latin">Vyjava SVG</comment>
+ <comment xml:lang="be">выява SVG</comment>
+ <comment xml:lang="ar">صورة SVG</comment>
+ <comment xml:lang="af">SVG-beeld</comment>
<acronym>SVG</acronym>
<expanded-acronym>Scalable Vector Graphics</expanded-acronym>
<sub-class-of type="application/xml"/>
<magic priority="80">
- <match value="&lt;!DOCTYPE svg" type="string" offset="0:256"/>
- <match value="&lt;svg" type="string" offset="0:256"/>
+ <match type="string" value="&lt;!DOCTYPE svg" offset="0:256"/>
+ </magic>
+ <magic priority="80">
+ <match type="string" value="&lt;!-- Created with Inkscape" offset="0"/>
+ <match type="string" value="&lt;svg" offset="0"/>
+ </magic>
+ <magic priority="45">
+ <match type="string" value="&lt;svg" offset="1:256"/>
</magic>
<glob pattern="*.svg"/>
<root-XML namespaceURI="http://www.w3.org/2000/svg" localName="svg"/>
</mime-type>
<mime-type type="image/svg+xml-compressed">
- <comment>compressed SVG image</comment>
- <comment xml:lang="ar">صورة SVG مضغوطة</comment>
- <comment xml:lang="be@latin">skampresavanaja vyjava SVG</comment>
- <comment xml:lang="bg">Изображение — SVG, компресирано</comment>
- <comment xml:lang="ca">imatge SVG amb compressió</comment>
- <comment xml:lang="cs">komprimovaný obrázek SVG</comment>
- <comment xml:lang="da">SVG-komprimeret billede</comment>
- <comment xml:lang="de">Komprimiertes SVG-Bild</comment>
- <comment xml:lang="el">Συμπιεσμένη εικόνα SVG</comment>
- <comment xml:lang="en_GB">compressed SVG image</comment>
- <comment xml:lang="es">imagen SVG comprimida</comment>
- <comment xml:lang="eu">konprimitutako SVG irudia</comment>
- <comment xml:lang="fi">pakattu SVG-kuva</comment>
- <comment xml:lang="fo">stappað SVG mynd</comment>
- <comment xml:lang="fr">image SVG compressée</comment>
- <comment xml:lang="ga">íomhá SVG comhbhrúite</comment>
- <comment xml:lang="gl">imaxe SVG comprimida</comment>
- <comment xml:lang="he">תמונת SVG מכווצת</comment>
- <comment xml:lang="hr">Sažeta SVG slika</comment>
- <comment xml:lang="hu">tömörített SVG kép</comment>
- <comment xml:lang="ia">Imagine SVG comprimite</comment>
- <comment xml:lang="id">Citra SVG terkompresi</comment>
- <comment xml:lang="it">Immagine SVG compressa</comment>
- <comment xml:lang="ja">圧縮 SVG 画像</comment>
- <comment xml:lang="kk">сығылған SVG суреті</comment>
- <comment xml:lang="ko">압축된 SVG 그림</comment>
- <comment xml:lang="lt">suglaudintas SVG paveikslėlis</comment>
- <comment xml:lang="lv">saspiests SVG attēls</comment>
- <comment xml:lang="nb">komprimert SVG-bilde</comment>
- <comment xml:lang="nl">ingepakte SVG-afbeelding</comment>
- <comment xml:lang="nn">komprimert SVG-bilete</comment>
- <comment xml:lang="oc">imatge SVG compressat</comment>
- <comment xml:lang="pl">Skompresowany obraz SVG</comment>
- <comment xml:lang="pt">imagem SVG comprimida</comment>
- <comment xml:lang="pt_BR">Imagem SVG compactada</comment>
- <comment xml:lang="ro">imagine comprimată SVG</comment>
- <comment xml:lang="ru">Сжатое изображение SVG</comment>
- <comment xml:lang="sk">Komprimovaný obrázok SVG</comment>
- <comment xml:lang="sl">Slikovna datoteka SVG (stisnjena)</comment>
- <comment xml:lang="sq">Figurë SVG e kompresuar</comment>
- <comment xml:lang="sr">запакована СВГ слика</comment>
- <comment xml:lang="sv">komprimerad SVG-bild</comment>
- <comment xml:lang="tr">sıkıştırılmış SVG görüntüsü</comment>
+ <comment>Compressed SVG image</comment>
<comment xml:lang="uk">стиснене зображення SVG</comment>
- <comment xml:lang="vi">ảnh SVG đã nén</comment>
- <comment xml:lang="zh_CN">压缩的 SVG 图像</comment>
- <comment xml:lang="zh_TW">壓縮版 SVG 影像</comment>
+ <comment xml:lang="sv">Komprimerad SVG-bild</comment>
+ <comment xml:lang="ru">Сжатое изображение SVG</comment>
+ <comment xml:lang="pl">Skompresowany obraz SVG</comment>
+ <comment xml:lang="ja">SVG画像(圧縮)</comment>
+ <comment xml:lang="it">Immagine SVG compressa</comment>
+ <comment xml:lang="gl">Imaxe SVG comprimido</comment>
+ <comment xml:lang="eu">SVG irudi konprimatua</comment>
+ <comment xml:lang="es">imagen SVG comprimida</comment>
+ <comment xml:lang="de">Komprimiertes SVG-Bild</comment>
+ <comment xml:lang="be">сціснутая выява SVG</comment>
<acronym>SVG</acronym>
<expanded-acronym>Scalable Vector Graphics</expanded-acronym>
<sub-class-of type="application/gzip"/>
<glob pattern="*.svgz"/>
+ <glob pattern="*.svg.gz"/>
</mime-type>
<mime-type type="image/tiff">
<comment>TIFF image</comment>
- <comment xml:lang="ar">صورة TIFF</comment>
- <comment xml:lang="be@latin">Vyjava TIFF</comment>
- <comment xml:lang="bg">Изображение — TIFF</comment>
- <comment xml:lang="ca">imatge TIFF</comment>
- <comment xml:lang="cs">obrázek TIFF</comment>
- <comment xml:lang="da">TIFF-billede</comment>
- <comment xml:lang="de">TIFF-Bild</comment>
- <comment xml:lang="el">Εικόνα TIFF</comment>
- <comment xml:lang="en_GB">TIFF image</comment>
- <comment xml:lang="eo">TIFF-bildo</comment>
- <comment xml:lang="es">imagen TIFF</comment>
- <comment xml:lang="eu">TIFF irudia</comment>
- <comment xml:lang="fi">TIFF-kuva</comment>
- <comment xml:lang="fo">TIFF mynd</comment>
- <comment xml:lang="fr">image TIFF</comment>
- <comment xml:lang="ga">íomhá TIFF</comment>
- <comment xml:lang="gl">imaxe TIFF</comment>
- <comment xml:lang="he">תמונת TIFF</comment>
- <comment xml:lang="hr">TIFF slika</comment>
- <comment xml:lang="hu">TIFF-kép</comment>
- <comment xml:lang="ia">Imagine TIFF</comment>
- <comment xml:lang="id">Citra TIFF</comment>
- <comment xml:lang="it">Immagine TIFF</comment>
- <comment xml:lang="ja">TIFF 画像</comment>
- <comment xml:lang="kk">TIFF суреті</comment>
- <comment xml:lang="ko">TIFF 그림</comment>
- <comment xml:lang="lt">TIFF paveikslėlis</comment>
- <comment xml:lang="lv">TIFF attēls</comment>
- <comment xml:lang="ms">Imej TIFF</comment>
- <comment xml:lang="nb">TIFF-bilde</comment>
- <comment xml:lang="nl">TIFF-afbeelding</comment>
- <comment xml:lang="nn">TIFF-bilete</comment>
- <comment xml:lang="oc">imatge TIFF</comment>
- <comment xml:lang="pl">Obraz TIFF</comment>
- <comment xml:lang="pt">imagem TIFF</comment>
- <comment xml:lang="pt_BR">Imagem TIFF</comment>
- <comment xml:lang="ro">Imagine TIFF</comment>
- <comment xml:lang="ru">Изображение TIFF</comment>
- <comment xml:lang="sk">Obrázok TIFF</comment>
- <comment xml:lang="sl">Slikovna datoteka TIFF</comment>
- <comment xml:lang="sq">Figurë TIFF</comment>
- <comment xml:lang="sr">ТИФФ слика</comment>
- <comment xml:lang="sv">TIFF-bild</comment>
- <comment xml:lang="tr">TIFF görüntüsü</comment>
- <comment xml:lang="uk">зображення TIFF</comment>
- <comment xml:lang="vi">Ảnh TIFF</comment>
- <comment xml:lang="zh_CN">TIFF 图像</comment>
<comment xml:lang="zh_TW">TIFF 影像</comment>
+ <comment xml:lang="zh_CN">TIFF 图像</comment>
+ <comment xml:lang="vi">Ảnh TIFF</comment>
+ <comment xml:lang="uk">зображення TIFF</comment>
+ <comment xml:lang="tr">TIFF görüntüsü</comment>
+ <comment xml:lang="sv">TIFF-bild</comment>
+ <comment xml:lang="sr">ТИФФ слика</comment>
+ <comment xml:lang="sq">figurë TIFF</comment>
+ <comment xml:lang="sl">Slikovna datoteka TIFF</comment>
+ <comment xml:lang="si">TIFF රූපය</comment>
+ <comment xml:lang="sk">Obrázok TIFF</comment>
+ <comment xml:lang="ru">Изображение TIFF</comment>
+ <comment xml:lang="ro">Imagine TIFF</comment>
+ <comment xml:lang="pt_BR">Imagem TIFF</comment>
+ <comment xml:lang="pt">imagem TIFF</comment>
+ <comment xml:lang="pl">Obraz TIFF</comment>
+ <comment xml:lang="oc">imatge TIFF</comment>
+ <comment xml:lang="nn">TIFF-bilete</comment>
+ <comment xml:lang="nl">TIFF-afbeelding</comment>
+ <comment xml:lang="nb">TIFF-bilde</comment>
+ <comment xml:lang="ms">Imej TIFF</comment>
+ <comment xml:lang="lv">TIFF attēls</comment>
+ <comment xml:lang="lt">TIFF paveikslėlis</comment>
+ <comment xml:lang="ko">TIFF 그림</comment>
+ <comment xml:lang="kk">TIFF суреті</comment>
+ <comment xml:lang="ja">TIFF 画像</comment>
+ <comment xml:lang="it">Immagine TIFF</comment>
+ <comment xml:lang="is">TIFF mynd</comment>
+ <comment xml:lang="id">Citra TIFF</comment>
+ <comment xml:lang="ia">Imagine TIFF</comment>
+ <comment xml:lang="hu">TIFF-kép</comment>
+ <comment xml:lang="hr">TIFF slika</comment>
+ <comment xml:lang="he">תמונת TIFF</comment>
+ <comment xml:lang="gl">imaxe TIFF</comment>
+ <comment xml:lang="ga">íomhá TIFF</comment>
+ <comment xml:lang="fur">imagjin TIFF</comment>
+ <comment xml:lang="fr">image TIFF</comment>
+ <comment xml:lang="fo">TIFF mynd</comment>
+ <comment xml:lang="fi">TIFF-kuva</comment>
+ <comment xml:lang="eu">TIFF irudia</comment>
+ <comment xml:lang="es">imagen TIFF</comment>
+ <comment xml:lang="eo">TIFF-bildo</comment>
+ <comment xml:lang="en_GB">TIFF image</comment>
+ <comment xml:lang="el">Εικόνα TIFF</comment>
+ <comment xml:lang="de">TIFF-Bild</comment>
+ <comment xml:lang="da">TIFF-billede</comment>
+ <comment xml:lang="cs">obrázek TIFF</comment>
+ <comment xml:lang="ca">imatge TIFF</comment>
+ <comment xml:lang="bg">Изображение — TIFF</comment>
+ <comment xml:lang="be@latin">Vyjava TIFF</comment>
+ <comment xml:lang="be">выява TIFF</comment>
+ <comment xml:lang="ar">صورة TIFF</comment>
+ <comment xml:lang="af">TIFF-beeld</comment>
<acronym>TIFF</acronym>
<expanded-acronym>Tagged Image File Format</expanded-acronym>
- <magic priority="50">
- <match value="MM\x00\x2a" type="string" offset="0"/>
- <match value="II\x2a\x00" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="MM\x00\x2a" offset="0"/>
+ <match type="string" value="II\x2a\x00" offset="0"/>
</magic>
<glob pattern="*.tif"/>
<glob pattern="*.tiff"/>
</mime-type>
<mime-type type="image/x-tiff-multipage">
<comment>Multi-page TIFF image</comment>
- <comment xml:lang="ca">imatge TIFF multipàgina</comment>
- <comment xml:lang="cs">vícestránkový obrázek TIFF</comment>
- <comment xml:lang="da">Flersidet TIFF-billede</comment>
- <comment xml:lang="de">Mehrseitiges TIFF-Bild</comment>
- <comment xml:lang="el">Πολυσέλιδη εικόνα TIFF</comment>
- <comment xml:lang="en_GB">Multi-page TIFF image</comment>
- <comment xml:lang="es">imagen TIFF de varias páginas</comment>
- <comment xml:lang="fi">Monisivuinen TIFF-kuva</comment>
- <comment xml:lang="fr">Image TIFF multi-page</comment>
- <comment xml:lang="ga">íomhá il-leathanach TIFF</comment>
- <comment xml:lang="gl">Imaxe TIFF multipáxina</comment>
- <comment xml:lang="he">תמונת TIFF עם ריבוי עמודים</comment>
- <comment xml:lang="hr">Višestrana TIFF slika</comment>
- <comment xml:lang="hu">Többoldalas TIFF kép</comment>
- <comment xml:lang="ia">Imagine TIFF multi-pagina</comment>
- <comment xml:lang="id">Citra TIFF multi halaman</comment>
- <comment xml:lang="it">Immagine TIFF multi-pagina</comment>
- <comment xml:lang="kk">Көпбеттік TIFF суреті</comment>
- <comment xml:lang="ko">다중 페이지 TIFF 그림</comment>
- <comment xml:lang="oc">Imatge TIFF multipagina</comment>
- <comment xml:lang="pl">Wielostronnicowy obraz TIFF</comment>
- <comment xml:lang="pt">imagem TIFF multipágina</comment>
- <comment xml:lang="pt_BR">Imagem TIFF multipágina</comment>
- <comment xml:lang="ru">Многостраничное изображение TIFF</comment>
- <comment xml:lang="sk">Viacstránkový obrázok TIFF</comment>
- <comment xml:lang="sl">Večstranska slika TIFF</comment>
- <comment xml:lang="sr">Вишестранична ТИФФ слика</comment>
- <comment xml:lang="sv">Flersidig TIFF-bild</comment>
- <comment xml:lang="tr">Çok sayfalı TIFF görüntüsü</comment>
- <comment xml:lang="uk">багатосторінкове зображення TIFF</comment>
- <comment xml:lang="zh_CN">多页 TIFF 图像</comment>
<comment xml:lang="zh_TW">多頁 TIFF 影像</comment>
+ <comment xml:lang="zh_CN">多页 TIFF 图像</comment>
+ <comment xml:lang="uk">багатосторінкове зображення TIFF</comment>
+ <comment xml:lang="tr">Çok sayfalı TIFF görüntüsü</comment>
+ <comment xml:lang="sv">Flersidig TIFF-bild</comment>
+ <comment xml:lang="sr">Вишестранична ТИФФ слика</comment>
+ <comment xml:lang="sq">figurë TIFF me shumë faqe</comment>
+ <comment xml:lang="sl">Večstranska slika TIFF</comment>
+ <comment xml:lang="si">බහු-පිටු TIFF රූපය</comment>
+ <comment xml:lang="sk">Viacstránkový obrázok TIFF</comment>
+ <comment xml:lang="ru">Многостраничное изображение TIFF</comment>
+ <comment xml:lang="pt_BR">Imagem TIFF multipágina</comment>
+ <comment xml:lang="pt">imagem TIFF multipágina</comment>
+ <comment xml:lang="pl">Wielostronnicowy obraz TIFF</comment>
+ <comment xml:lang="oc">Imatge TIFF multipagina</comment>
+ <comment xml:lang="nl">Multi-pagina TIFF-afbeelding</comment>
+ <comment xml:lang="ko">다중 페이지 TIFF 그림</comment>
+ <comment xml:lang="kk">Көпбеттік TIFF суреті</comment>
+ <comment xml:lang="ja">マルチページ TIFF 画像</comment>
+ <comment xml:lang="it">Immagine TIFF multi-pagina</comment>
+ <comment xml:lang="is">Margsíðna TIFF mynd</comment>
+ <comment xml:lang="id">Citra TIFF multi halaman</comment>
+ <comment xml:lang="ia">Imagine TIFF multi-pagina</comment>
+ <comment xml:lang="hu">Többoldalas TIFF kép</comment>
+ <comment xml:lang="hr">Višestrana TIFF slika</comment>
+ <comment xml:lang="he">תמונת TIFF עם ריבוי עמודים</comment>
+ <comment xml:lang="gl">Imaxe TIFF multipáxina</comment>
+ <comment xml:lang="ga">íomhá il-leathanach TIFF</comment>
+ <comment xml:lang="fur">imagjin a plui pagjinis TIFF</comment>
+ <comment xml:lang="fr">Image TIFF multi-page</comment>
+ <comment xml:lang="fi">Monisivuinen TIFF-kuva</comment>
+ <comment xml:lang="eu">Multi-page TIFF irudia</comment>
+ <comment xml:lang="es">imagen TIFF multipágina</comment>
+ <comment xml:lang="en_GB">Multi-page TIFF image</comment>
+ <comment xml:lang="el">Πολυσέλιδη εικόνα TIFF</comment>
+ <comment xml:lang="de">Mehrseitiges TIFF-Bild</comment>
+ <comment xml:lang="da">Flersidet TIFF-billede</comment>
+ <comment xml:lang="cs">vícestránkový obrázek TIFF</comment>
+ <comment xml:lang="ca">imatge TIFF multipàgina</comment>
+ <comment xml:lang="bg">Изображение — TIFF, много страници</comment>
+ <comment xml:lang="be">шматстаронкавая выява TIFF</comment>
+ <comment xml:lang="ar">صورة TIFF متعددة الصفحات</comment>
+ <comment xml:lang="af">Multibladsy TIFF-beeld</comment>
<acronym>TIFF</acronym>
<expanded-acronym>Tagged Image File Format</expanded-acronym>
<sub-class-of type="image/tiff"/>
</mime-type>
<mime-type type="image/vnd.dwg">
<comment>AutoCAD image</comment>
- <comment xml:lang="ar">صورة AutoCAD</comment>
- <comment xml:lang="az">AutoCAD rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava AutoCAD</comment>
- <comment xml:lang="bg">Изображение — AutoCAD</comment>
- <comment xml:lang="ca">imatge d'AutoCAD</comment>
- <comment xml:lang="cs">výkres AutoCAD</comment>
- <comment xml:lang="cy">Delwedd AutoCAD</comment>
- <comment xml:lang="da">AutoCAD-billede</comment>
- <comment xml:lang="de">AutoCAD-Bild</comment>
- <comment xml:lang="el">Εικόνα AutoCAD</comment>
- <comment xml:lang="en_GB">AutoCAD image</comment>
- <comment xml:lang="eo">AutoCAD-bildo</comment>
- <comment xml:lang="es">imagen de AutoCAD</comment>
- <comment xml:lang="eu">AutoCAD-eko irudia</comment>
- <comment xml:lang="fi">AutoCAD-kuva</comment>
- <comment xml:lang="fo">AutoCAD mynd</comment>
- <comment xml:lang="fr">image AutoCAD</comment>
- <comment xml:lang="ga">íomhá AutoCAD</comment>
- <comment xml:lang="gl">imaxe de AutoCAD</comment>
- <comment xml:lang="he">תמונה של AutoCAD</comment>
- <comment xml:lang="hr">AutoCAD slika</comment>
- <comment xml:lang="hu">AutoCAD-kép</comment>
- <comment xml:lang="ia">Imagine AutoCAD</comment>
- <comment xml:lang="id">Citra AutoCAD</comment>
- <comment xml:lang="it">Immagine AutoCAD</comment>
- <comment xml:lang="ja">AutoCAD 画像</comment>
- <comment xml:lang="ka">AutoCAD-ის გამოსახულება</comment>
- <comment xml:lang="kk">AutoCAD суреті</comment>
- <comment xml:lang="ko">AutoCAD 그림</comment>
- <comment xml:lang="lt">AutoCAD paveikslėlis</comment>
- <comment xml:lang="lv">AutoCAD attēls</comment>
- <comment xml:lang="ms">Imej AutoCAD</comment>
- <comment xml:lang="nb">AutoCAD-bilde</comment>
- <comment xml:lang="nl">AutoCAD-afbeelding</comment>
- <comment xml:lang="nn">AutoCAD-bilete</comment>
- <comment xml:lang="oc">imatge AutoCAD</comment>
- <comment xml:lang="pl">Obraz AutoCAD</comment>
- <comment xml:lang="pt">imagem AutoCAD</comment>
- <comment xml:lang="pt_BR">Imagem do AutoCAD</comment>
- <comment xml:lang="ro">Imagine AutoCAD</comment>
- <comment xml:lang="ru">Изображение AutoCAD</comment>
- <comment xml:lang="sk">Obrázok AutoCAD</comment>
- <comment xml:lang="sl">Slikovna datoteka AutoCAD</comment>
- <comment xml:lang="sq">Figurë AutoCAD</comment>
- <comment xml:lang="sr">АутоКАД слика</comment>
- <comment xml:lang="sv">AutoCAD-bild</comment>
- <comment xml:lang="tr">AutoCAD görüntüsü</comment>
- <comment xml:lang="uk">зображення AutoCAD</comment>
- <comment xml:lang="vi">Ảnh AutoCAD</comment>
- <comment xml:lang="zh_CN">AutoCAD 图像</comment>
<comment xml:lang="zh_TW">AutoCAD 影像</comment>
+ <comment xml:lang="zh_CN">AutoCAD 图像</comment>
+ <comment xml:lang="vi">Ảnh AutoCAD</comment>
+ <comment xml:lang="uk">зображення AutoCAD</comment>
+ <comment xml:lang="tr">AutoCAD görüntüsü</comment>
+ <comment xml:lang="sv">AutoCAD-bild</comment>
+ <comment xml:lang="sr">АутоКАД слика</comment>
+ <comment xml:lang="sq">figurë AutoCAD</comment>
+ <comment xml:lang="sl">Slikovna datoteka AutoCAD</comment>
+ <comment xml:lang="si">AutoCAD රූපය</comment>
+ <comment xml:lang="sk">Obrázok AutoCAD</comment>
+ <comment xml:lang="ru">Изображение AutoCAD</comment>
+ <comment xml:lang="ro">Imagine AutoCAD</comment>
+ <comment xml:lang="pt_BR">Imagem do AutoCAD</comment>
+ <comment xml:lang="pt">imagem AutoCAD</comment>
+ <comment xml:lang="pl">Obraz AutoCAD</comment>
+ <comment xml:lang="oc">imatge AutoCAD</comment>
+ <comment xml:lang="nn">AutoCAD-bilete</comment>
+ <comment xml:lang="nl">AutoCAD-afbeelding</comment>
+ <comment xml:lang="nb">AutoCAD-bilde</comment>
+ <comment xml:lang="ms">Imej AutoCAD</comment>
+ <comment xml:lang="lv">AutoCAD attēls</comment>
+ <comment xml:lang="lt">AutoCAD paveikslėlis</comment>
+ <comment xml:lang="ko">AutoCAD 그림</comment>
+ <comment xml:lang="kk">AutoCAD суреті</comment>
+ <comment xml:lang="ka">AutoCAD-ის გამოსახულება</comment>
+ <comment xml:lang="ja">AutoCAD 画像</comment>
+ <comment xml:lang="it">Immagine AutoCAD</comment>
+ <comment xml:lang="is">AutoCAD mynd</comment>
+ <comment xml:lang="id">Citra AutoCAD</comment>
+ <comment xml:lang="ia">Imagine AutoCAD</comment>
+ <comment xml:lang="hu">AutoCAD-kép</comment>
+ <comment xml:lang="hr">AutoCAD slika</comment>
+ <comment xml:lang="he">תמונה של AutoCAD</comment>
+ <comment xml:lang="gl">imaxe de AutoCAD</comment>
+ <comment xml:lang="ga">íomhá AutoCAD</comment>
+ <comment xml:lang="fur">imagjin AutoCAD</comment>
+ <comment xml:lang="fr">image AutoCAD</comment>
+ <comment xml:lang="fo">AutoCAD mynd</comment>
+ <comment xml:lang="fi">AutoCAD-kuva</comment>
+ <comment xml:lang="eu">AutoCAD-eko irudia</comment>
+ <comment xml:lang="es">imagen de AutoCAD</comment>
+ <comment xml:lang="eo">AutoCAD-bildo</comment>
+ <comment xml:lang="en_GB">AutoCAD image</comment>
+ <comment xml:lang="el">Εικόνα AutoCAD</comment>
+ <comment xml:lang="de">AutoCAD-Bild</comment>
+ <comment xml:lang="da">AutoCAD-billede</comment>
+ <comment xml:lang="cy">Delwedd AutoCAD</comment>
+ <comment xml:lang="cs">výkres AutoCAD</comment>
+ <comment xml:lang="ca">imatge d'AutoCAD</comment>
+ <comment xml:lang="bg">Изображение — AutoCAD</comment>
+ <comment xml:lang="be@latin">Vyjava AutoCAD</comment>
+ <comment xml:lang="be">выява AutoCAD</comment>
+ <comment xml:lang="az">AutoCAD rəsmi</comment>
+ <comment xml:lang="ar">صورة AutoCAD</comment>
+ <comment xml:lang="af">AutoCAD-beeld</comment>
<glob pattern="*.dwg"/>
</mime-type>
<mime-type type="image/vnd.dxf">
<comment>DXF vector image</comment>
- <comment xml:lang="ar">صورة DXF نقطية</comment>
- <comment xml:lang="be@latin">Vektarnaja vyjava DXF</comment>
- <comment xml:lang="bg">Изображение — DXF</comment>
- <comment xml:lang="ca">imatge vectorial DXF</comment>
- <comment xml:lang="cs">vektorový obrázek DXF</comment>
- <comment xml:lang="da">DXF-vektorbillede</comment>
- <comment xml:lang="de">DXF-Vektorbild</comment>
- <comment xml:lang="el">Διανυσματική εικόνα DXF</comment>
- <comment xml:lang="en_GB">DXF vector image</comment>
- <comment xml:lang="eo">vektora DXF-bildo</comment>
- <comment xml:lang="es">imagen vectorial DXF</comment>
- <comment xml:lang="eu">DXF bektore-grafikoa</comment>
- <comment xml:lang="fi">DXF-vektorikuva</comment>
- <comment xml:lang="fo">DXF vektormynd</comment>
- <comment xml:lang="fr">image vectorielle DXF</comment>
- <comment xml:lang="ga">íomhá veicteoireach DXF</comment>
- <comment xml:lang="gl">imaxe de vector DXF</comment>
- <comment xml:lang="he">תמונת DXF וקטורית</comment>
- <comment xml:lang="hr">DXF vektorska slika</comment>
- <comment xml:lang="hu">DXF-vektorkép</comment>
- <comment xml:lang="ia">Imagine vectorial DXF</comment>
- <comment xml:lang="id">Citra vektor DXF</comment>
- <comment xml:lang="it">Immagine vettoriale DXF</comment>
- <comment xml:lang="ja">DXF ベクター画像</comment>
- <comment xml:lang="ka">DXF ვექტორული გამოსახულება</comment>
- <comment xml:lang="kk">DXF векторлық суреті</comment>
- <comment xml:lang="ko">DXF 벡터 그림</comment>
- <comment xml:lang="lt">DXF vektorinis paveikslėlis</comment>
- <comment xml:lang="lv">DXF vektora attēls</comment>
- <comment xml:lang="ms">Imej vektor DXF</comment>
- <comment xml:lang="nb">DXF-vektorgrafikk</comment>
- <comment xml:lang="nl">DXF-vectorafbeelding</comment>
- <comment xml:lang="nn">DXF-vektorgrafikk</comment>
- <comment xml:lang="oc">imatge vectorial DXF</comment>
- <comment xml:lang="pl">Obraz wektorowy DXF</comment>
- <comment xml:lang="pt">imagem de vectores DXF</comment>
- <comment xml:lang="pt_BR">Imagem vetorial DXF</comment>
- <comment xml:lang="ro">Imagine vectorială DXF</comment>
- <comment xml:lang="ru">Векторное изображение DXF</comment>
- <comment xml:lang="sk">Vektorový obrázok DXF</comment>
- <comment xml:lang="sl">Slikovna vektorska datoteka DXF</comment>
- <comment xml:lang="sq">Figurë vektoriale DFX</comment>
- <comment xml:lang="sr">ДИксФ векторска графика</comment>
- <comment xml:lang="sv">DXF-vektorbild</comment>
- <comment xml:lang="tr">DXF vektör görüntüsü</comment>
- <comment xml:lang="uk">векторне зображення DXF</comment>
- <comment xml:lang="vi">Ảnh véc-tơ DXF</comment>
- <comment xml:lang="zh_CN">DXF 矢量图像</comment>
<comment xml:lang="zh_TW">DXF 向量圖</comment>
+ <comment xml:lang="zh_CN">DXF 矢量图像</comment>
+ <comment xml:lang="vi">Ảnh véc-tơ DXF</comment>
+ <comment xml:lang="uk">векторне зображення DXF</comment>
+ <comment xml:lang="tr">DXF vektör görüntüsü</comment>
+ <comment xml:lang="sv">DXF-vektorbild</comment>
+ <comment xml:lang="sr">ДИксФ векторска графика</comment>
+ <comment xml:lang="sq">figurë vektoriale DFX</comment>
+ <comment xml:lang="sl">Slikovna vektorska datoteka DXF</comment>
+ <comment xml:lang="si">DXF දෛශික රූපය</comment>
+ <comment xml:lang="sk">Vektorový obrázok DXF</comment>
+ <comment xml:lang="ru">Векторное изображение DXF</comment>
+ <comment xml:lang="ro">Imagine vectorială DXF</comment>
+ <comment xml:lang="pt_BR">Imagem vetorial DXF</comment>
+ <comment xml:lang="pt">imagem de vectores DXF</comment>
+ <comment xml:lang="pl">Obraz wektorowy DXF</comment>
+ <comment xml:lang="oc">imatge vectorial DXF</comment>
+ <comment xml:lang="nn">DXF-vektorgrafikk</comment>
+ <comment xml:lang="nl">DXF-vectorafbeelding</comment>
+ <comment xml:lang="nb">DXF-vektorgrafikk</comment>
+ <comment xml:lang="ms">Imej vektor DXF</comment>
+ <comment xml:lang="lv">DXF vektora attēls</comment>
+ <comment xml:lang="lt">DXF vektorinis paveikslėlis</comment>
+ <comment xml:lang="ko">DXF 벡터 그림</comment>
+ <comment xml:lang="kk">DXF векторлық суреті</comment>
+ <comment xml:lang="ka">DXF ვექტორული გამოსახულება</comment>
+ <comment xml:lang="ja">DXF ベクター画像</comment>
+ <comment xml:lang="it">Immagine vettoriale DXF</comment>
+ <comment xml:lang="is">DXF vigurteikning</comment>
+ <comment xml:lang="id">Citra vektor DXF</comment>
+ <comment xml:lang="ia">Imagine vectorial DXF</comment>
+ <comment xml:lang="hu">DXF-vektorkép</comment>
+ <comment xml:lang="hr">DXF vektorska slika</comment>
+ <comment xml:lang="he">תמונת DXF וקטורית</comment>
+ <comment xml:lang="gl">imaxe de vector DXF</comment>
+ <comment xml:lang="ga">íomhá veicteoireach DXF</comment>
+ <comment xml:lang="fur">imagjin vetoriâl DXF</comment>
+ <comment xml:lang="fr">image vectorielle DXF</comment>
+ <comment xml:lang="fo">DXF vektormynd</comment>
+ <comment xml:lang="fi">DXF-vektorikuva</comment>
+ <comment xml:lang="eu">DXF bektore-grafikoa</comment>
+ <comment xml:lang="es">imagen vectorial DXF</comment>
+ <comment xml:lang="eo">vektora DXF-bildo</comment>
+ <comment xml:lang="en_GB">DXF vector image</comment>
+ <comment xml:lang="el">Διανυσματική εικόνα DXF</comment>
+ <comment xml:lang="de">DXF-Vektorbild</comment>
+ <comment xml:lang="da">DXF-vektorbillede</comment>
+ <comment xml:lang="cs">vektorový obrázek DXF</comment>
+ <comment xml:lang="ca">imatge vectorial DXF</comment>
+ <comment xml:lang="bg">Изображение — DXF</comment>
+ <comment xml:lang="be@latin">Vektarnaja vyjava DXF</comment>
+ <comment xml:lang="be">вектарная выява DXF</comment>
+ <comment xml:lang="ar">صورة DXF نقطية</comment>
+ <comment xml:lang="af">DXF-vektorbeeld</comment>
<glob pattern="*.dxf"/>
- <magic priority="50">
- <match value="\nHEADER\n" type="string" offset="0:64"/>
- <match value="\x0d\nHEADER\x0d\n" type="string" offset="0:64"/>
+ <magic>
+ <match type="string" value="\nHEADER\n" offset="0:64"/>
+ <match type="string" value="\x0d\nHEADER\x0d\n" offset="0:64"/>
</magic>
</mime-type>
<mime-type type="image/vnd.ms-modi">
- <comment>Microsoft Document Imaging format</comment>
- <comment xml:lang="ar">صيغة مستند تصوير مايكروسوفت</comment>
- <comment xml:lang="ast">Formatu d'imáxenes de Microsoft Document</comment>
- <comment xml:lang="bg">Изображение — Microsoft Document Imaging</comment>
- <comment xml:lang="ca">format Microsoft Document Imaging</comment>
- <comment xml:lang="cs">formát Microsoft Document Imaging</comment>
- <comment xml:lang="da">Microsofts dokumentbilledformat</comment>
- <comment xml:lang="de">Microsoft-Document-Imaging-Bildformat</comment>
- <comment xml:lang="el">Μορφή Microsoft Document Imaging</comment>
- <comment xml:lang="en_GB">Microsoft Document Imaging format</comment>
- <comment xml:lang="es">formato de imagen para documentos de Microsoft</comment>
- <comment xml:lang="eu">Microsoft Document Imaging formatua</comment>
- <comment xml:lang="fi">Microsoft Document Imaging -muoto</comment>
- <comment xml:lang="fo">Microsoft Document Imaging snið</comment>
- <comment xml:lang="fr">format Document Imaging Microsoft</comment>
- <comment xml:lang="ga">formáid Microsoft Document Imaging</comment>
- <comment xml:lang="gl">formato de Microsoft Document Imaging</comment>
- <comment xml:lang="he">תבנית של Microsoft Document Imaging</comment>
- <comment xml:lang="hr">Microsoft Document Imaging format</comment>
- <comment xml:lang="hu">Microsoft Document Imaging formátum</comment>
- <comment xml:lang="ia">File in formato Microsoft Document Imaging</comment>
- <comment xml:lang="id">Format Microsoft Document Imaging</comment>
- <comment xml:lang="it">Formato MDI (Microsoft Document Imaging)</comment>
- <comment xml:lang="ja">Microsoft ドキュメントイメージフォーマット</comment>
- <comment xml:lang="kk">Microsoft Document Imaging пішімі</comment>
- <comment xml:lang="ko">Microsoft 문서 이미지 형식</comment>
- <comment xml:lang="lt">Microsoft Document Imaging formatas</comment>
- <comment xml:lang="lv">Microsoft dokumentu attēlošanas formāts</comment>
- <comment xml:lang="nl">Microsoft Document Imaging</comment>
- <comment xml:lang="oc">format Document Imaging Microsoft</comment>
- <comment xml:lang="pl">Format Microsoft Document Imaging</comment>
- <comment xml:lang="pt">formato Microsoft Document Imaging</comment>
- <comment xml:lang="pt_BR">Formato do Microsoft Document Imaging</comment>
- <comment xml:lang="ro">Format Microsoft Document Imaging</comment>
- <comment xml:lang="ru">Формат Microsoft Document Imaging</comment>
- <comment xml:lang="sk">Formát Microsoft Document Imaging</comment>
- <comment xml:lang="sl">Zapis Microsoft Document Imaging</comment>
- <comment xml:lang="sr">запис слика Мајкрософтовог документа</comment>
- <comment xml:lang="sv">Microsoft Document Imaging-format</comment>
- <comment xml:lang="tr">Microsoft Belge Görüntüleme biçimi</comment>
- <comment xml:lang="uk">формат Microsoft Document Imaging</comment>
- <comment xml:lang="vi">Định dạng tạo ảnh tài liệu Microsoft</comment>
- <comment xml:lang="zh_CN">Microsoft Document Imaging 格式</comment>
- <comment xml:lang="zh_TW">微軟文件影像格式</comment>
+ <comment>MDI image</comment>
+ <comment xml:lang="zh_TW">MDI 影像</comment>
+ <comment xml:lang="zh_CN">MDI 图像</comment>
+ <comment xml:lang="uk">зображення MDI</comment>
+ <comment xml:lang="tr">MDI görüntüsü</comment>
+ <comment xml:lang="sv">MDI-bild</comment>
+ <comment xml:lang="sq">figurë MDI</comment>
+ <comment xml:lang="sl">Slika MDI</comment>
+ <comment xml:lang="si">MDI රූපය</comment>
+ <comment xml:lang="sk">Obrázok MDI</comment>
+ <comment xml:lang="ru">Изображение MDI</comment>
+ <comment xml:lang="pt_BR">Imagem MDI</comment>
+ <comment xml:lang="pl">Obraz MDI</comment>
+ <comment xml:lang="oc">imatge MDI</comment>
+ <comment xml:lang="nl">MDI-afbeelding</comment>
+ <comment xml:lang="ko">MDI 그림</comment>
+ <comment xml:lang="kk">MDI суреті</comment>
+ <comment xml:lang="ja">MDI 画像</comment>
+ <comment xml:lang="it">Immagine MDI</comment>
+ <comment xml:lang="is">MDI mynd</comment>
+ <comment xml:lang="id">Citra MDI</comment>
+ <comment xml:lang="hu">MDI-kép</comment>
+ <comment xml:lang="hr">MDI slika</comment>
+ <comment xml:lang="he">תמונת MDI</comment>
+ <comment xml:lang="gl">Imaxe MDI</comment>
+ <comment xml:lang="fr">image MDI</comment>
+ <comment xml:lang="fi">MDI-kuva</comment>
+ <comment xml:lang="eu">MDI irudia</comment>
+ <comment xml:lang="es">imagen MDI</comment>
+ <comment xml:lang="en_GB">MDI image</comment>
+ <comment xml:lang="de">MDI-Bild</comment>
+ <comment xml:lang="da">MDI-billede</comment>
+ <comment xml:lang="ca">imatge MDI</comment>
+ <comment xml:lang="bg">Изображение — MDI</comment>
+ <comment xml:lang="be">выява MDI</comment>
+ <comment xml:lang="ar">صورة MDI</comment>
<acronym>MDI</acronym>
<expanded-acronym>Microsoft Document Imaging</expanded-acronym>
<glob pattern="*.mdi"/>
- <magic priority="50">
- <match value="\x45\x50\x2A\x00" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\x45\x50\x2A\x00" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="image/jxr">
+ <comment>JPEG XR image</comment>
+ <comment xml:lang="uk">зображення JPEG XR</comment>
+ <comment xml:lang="sv">JPEG XR-bild</comment>
+ <comment xml:lang="ru">Изображение JPEG XR</comment>
+ <comment xml:lang="pt_BR">Imagem JPEG XR</comment>
+ <comment xml:lang="pl">Obraz JPEG XR</comment>
+ <comment xml:lang="it">Immagine JPEG XR</comment>
+ <comment xml:lang="gl">Imaxe JPEG XR</comment>
+ <comment xml:lang="eu">JPEG XR irudia</comment>
+ <comment xml:lang="es">imagen JPEG XR</comment>
+ <comment xml:lang="de">JPEG-XR-Bild</comment>
+ <comment xml:lang="be">выява JPEG XR</comment>
+ <acronym>XR</acronym>
+ <expanded-acronym>Extended Range</expanded-acronym>
+ <glob pattern="*.jxr"/>
+ <glob pattern="*.hdp"/>
+ <glob pattern="*.wdp"/>
+ <magic>
+ <match type="string" value="II\xBC\x01" offset="0"/>
</magic>
+ <alias type="image/vnd.ms-photo"/>
</mime-type>
<mime-type type="image/webp">
<comment>WebP image</comment>
- <comment xml:lang="ca">imatge WebP</comment>
- <comment xml:lang="cs">obrázek WebP</comment>
- <comment xml:lang="da">WebP-billede</comment>
- <comment xml:lang="de">WebP-Bild</comment>
- <comment xml:lang="el">Εικόνα WebP</comment>
- <comment xml:lang="en_GB">WebP image</comment>
- <comment xml:lang="es">imagen WebP</comment>
- <comment xml:lang="eu">WebP irudia</comment>
- <comment xml:lang="fi">WebP-kuva</comment>
- <comment xml:lang="fr">image WebP</comment>
- <comment xml:lang="ga">íomhá WebP</comment>
- <comment xml:lang="gl">Imaxe WebP</comment>
- <comment xml:lang="he">תמונת WebP</comment>
- <comment xml:lang="hr">WebP slika</comment>
- <comment xml:lang="hu">WebP kép</comment>
- <comment xml:lang="ia">Imagine WebP</comment>
- <comment xml:lang="id">Citra WebP</comment>
- <comment xml:lang="it">Immagine WebP</comment>
- <comment xml:lang="kk">WebP суреті</comment>
- <comment xml:lang="ko">WebP 그림</comment>
- <comment xml:lang="oc">imatge WebP</comment>
- <comment xml:lang="pl">Obraz WebP</comment>
- <comment xml:lang="pt">imagem WebP</comment>
- <comment xml:lang="pt_BR">Imagem WebP</comment>
- <comment xml:lang="ru">Изображение WebP</comment>
- <comment xml:lang="sk">Obrázok WebP</comment>
- <comment xml:lang="sl">Slika WebP</comment>
- <comment xml:lang="sr">ВебП слика</comment>
- <comment xml:lang="sv">WebP-bild</comment>
- <comment xml:lang="tr">WebP görüntüsü</comment>
- <comment xml:lang="uk">зображення WebP</comment>
- <comment xml:lang="zh_CN">WebP 图像</comment>
<comment xml:lang="zh_TW">WebP 影像</comment>
- <magic priority="50">
- <match value="RIFF" type="string" offset="0">
- <match value="WEBP" type="string" offset="8"/>
+ <comment xml:lang="zh_CN">WebP 图像</comment>
+ <comment xml:lang="uk">зображення WebP</comment>
+ <comment xml:lang="tr">WebP görüntüsü</comment>
+ <comment xml:lang="sv">WebP-bild</comment>
+ <comment xml:lang="sr">ВебП слика</comment>
+ <comment xml:lang="sq">figurë WebP</comment>
+ <comment xml:lang="sl">Slika WebP</comment>
+ <comment xml:lang="si">WebP රූපය</comment>
+ <comment xml:lang="sk">Obrázok WebP</comment>
+ <comment xml:lang="ru">Изображение WebP</comment>
+ <comment xml:lang="pt_BR">Imagem WebP</comment>
+ <comment xml:lang="pt">imagem WebP</comment>
+ <comment xml:lang="pl">Obraz WebP</comment>
+ <comment xml:lang="oc">imatge WebP</comment>
+ <comment xml:lang="nl">WebP-afbeelding</comment>
+ <comment xml:lang="ko">WebP 그림</comment>
+ <comment xml:lang="kk">WebP суреті</comment>
+ <comment xml:lang="ja">WebP 画像</comment>
+ <comment xml:lang="it">Immagine WebP</comment>
+ <comment xml:lang="is">WebP-mynd</comment>
+ <comment xml:lang="id">Citra WebP</comment>
+ <comment xml:lang="ia">Imagine WebP</comment>
+ <comment xml:lang="hu">WebP kép</comment>
+ <comment xml:lang="hr">WebP slika</comment>
+ <comment xml:lang="he">תמונת WebP</comment>
+ <comment xml:lang="gl">Imaxe WebP</comment>
+ <comment xml:lang="ga">íomhá WebP</comment>
+ <comment xml:lang="fur">imagjin WebP</comment>
+ <comment xml:lang="fr">image WebP</comment>
+ <comment xml:lang="fi">WebP-kuva</comment>
+ <comment xml:lang="eu">WebP irudia</comment>
+ <comment xml:lang="es">imagen WebP</comment>
+ <comment xml:lang="en_GB">WebP image</comment>
+ <comment xml:lang="el">Εικόνα WebP</comment>
+ <comment xml:lang="de">WebP-Bild</comment>
+ <comment xml:lang="da">WebP-billede</comment>
+ <comment xml:lang="cs">obrázek WebP</comment>
+ <comment xml:lang="ca">imatge WebP</comment>
+ <comment xml:lang="bg">Изображение — WebP</comment>
+ <comment xml:lang="be">выява WebP</comment>
+ <comment xml:lang="ar">صورة WebP</comment>
+ <comment xml:lang="af">WebP-beeld</comment>
+ <magic>
+ <match type="string" value="RIFF" offset="0">
+ <match type="string" value="WEBP" offset="8"/>
</match>
</magic>
<glob pattern="*.webp"/>
</mime-type>
<mime-type type="image/x-3ds">
<comment>3D Studio image</comment>
- <comment xml:lang="ar">صورة استديو ثلاثية الأبعاد</comment>
- <comment xml:lang="az">3D Studio rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava 3D Studio</comment>
- <comment xml:lang="bg">Изображение — 3D Studio</comment>
- <comment xml:lang="ca">imatge de 3D Studio</comment>
- <comment xml:lang="cs">obrázek 3D Studio</comment>
- <comment xml:lang="cy">Delwedd "3D Studio"</comment>
- <comment xml:lang="da">3D Studio-billede</comment>
- <comment xml:lang="de">3D-Studio-Bild</comment>
- <comment xml:lang="el">Εικόνα 3D Studio</comment>
- <comment xml:lang="en_GB">3D Studio image</comment>
- <comment xml:lang="eo">bildo de 3D Studio</comment>
- <comment xml:lang="es">imagen de 3D Studio</comment>
- <comment xml:lang="eu">3D Studio-ko irudia</comment>
- <comment xml:lang="fi">3D Studio -kuva</comment>
- <comment xml:lang="fo">3D Studio mynd</comment>
- <comment xml:lang="fr">image 3D Studio</comment>
- <comment xml:lang="ga">íomhá 3D Studio</comment>
- <comment xml:lang="gl">Imaxe de 3D Studio</comment>
- <comment xml:lang="he">תמונת 3D Studio</comment>
- <comment xml:lang="hr">3D Studio slika</comment>
- <comment xml:lang="hu">3D Studio-kép</comment>
- <comment xml:lang="ia">Imagine 3D Studio</comment>
- <comment xml:lang="id">Citra 3D Studio</comment>
- <comment xml:lang="it">Immagine 3D Studio</comment>
- <comment xml:lang="ja">3D Studio 画像</comment>
- <comment xml:lang="ka">3D Studio-ის გამოსახულება</comment>
- <comment xml:lang="kk">3D Studio суреті</comment>
- <comment xml:lang="ko">3D Studio 그림</comment>
- <comment xml:lang="lt">3D Studio paveikslėlis</comment>
- <comment xml:lang="lv">3D Studio attēls</comment>
- <comment xml:lang="ms">Imej 3D Studio</comment>
- <comment xml:lang="nb">3D Studio-bilde</comment>
- <comment xml:lang="nl">3D-Studio-afbeelding</comment>
- <comment xml:lang="nn">3D Studio-bilete</comment>
- <comment xml:lang="oc">imatge 3D Studio</comment>
- <comment xml:lang="pl">Obraz 3D Studio</comment>
- <comment xml:lang="pt">imagem 3D Studio</comment>
- <comment xml:lang="pt_BR">Imagem do 3D Studio</comment>
- <comment xml:lang="ro">Imagine 3D Studio</comment>
- <comment xml:lang="ru">Сцена 3D Studio</comment>
- <comment xml:lang="sk">Obrázok 3D Studio</comment>
- <comment xml:lang="sl">Slikovna datoteka 3D Studio</comment>
- <comment xml:lang="sq">Figurë 3D Studio</comment>
- <comment xml:lang="sr">слика 3Д Студија</comment>
- <comment xml:lang="sv">3D Studio-bild</comment>
- <comment xml:lang="tr">3D Studio görüntüsü</comment>
- <comment xml:lang="uk">зображення 3D Studio</comment>
- <comment xml:lang="vi">Ảnh xuởng vẽ 3D</comment>
- <comment xml:lang="zh_CN">3D Studio 图像</comment>
<comment xml:lang="zh_TW">3D Studio 影像</comment>
+ <comment xml:lang="zh_CN">3D Studio 图像</comment>
+ <comment xml:lang="vi">Ảnh xuởng vẽ 3D</comment>
+ <comment xml:lang="uk">зображення 3D Studio</comment>
+ <comment xml:lang="tr">3D Studio görüntüsü</comment>
+ <comment xml:lang="sv">3D Studio-bild</comment>
+ <comment xml:lang="sr">слика 3Д Студија</comment>
+ <comment xml:lang="sq">figurë 3D Studio</comment>
+ <comment xml:lang="sl">Slikovna datoteka 3D Studio</comment>
+ <comment xml:lang="si">3D ස්ටුඩියෝ රූපය</comment>
+ <comment xml:lang="sk">Obrázok 3D Studio</comment>
+ <comment xml:lang="ru">Сцена 3D Studio</comment>
+ <comment xml:lang="ro">Imagine 3D Studio</comment>
+ <comment xml:lang="pt_BR">Imagem do 3D Studio</comment>
+ <comment xml:lang="pt">imagem 3D Studio</comment>
+ <comment xml:lang="pl">Obraz 3D Studio</comment>
+ <comment xml:lang="oc">imatge 3D Studio</comment>
+ <comment xml:lang="nn">3D Studio-bilete</comment>
+ <comment xml:lang="nl">3D-Studio-afbeelding</comment>
+ <comment xml:lang="nb">3D Studio-bilde</comment>
+ <comment xml:lang="ms">Imej 3D Studio</comment>
+ <comment xml:lang="lv">3D Studio attēls</comment>
+ <comment xml:lang="lt">3D Studio paveikslėlis</comment>
+ <comment xml:lang="ko">3D Studio 그림</comment>
+ <comment xml:lang="kk">3D Studio суреті</comment>
+ <comment xml:lang="ka">3D Studio-ის გამოსახულება</comment>
+ <comment xml:lang="ja">3D Studio 画像</comment>
+ <comment xml:lang="it">Immagine 3D Studio</comment>
+ <comment xml:lang="is">3D Studio mynd</comment>
+ <comment xml:lang="id">Citra 3D Studio</comment>
+ <comment xml:lang="ia">Imagine 3D Studio</comment>
+ <comment xml:lang="hu">3D Studio-kép</comment>
+ <comment xml:lang="hr">3D Studio slika</comment>
+ <comment xml:lang="he">תמונת 3D Studio</comment>
+ <comment xml:lang="gl">Imaxe de 3D Studio</comment>
+ <comment xml:lang="ga">íomhá 3D Studio</comment>
+ <comment xml:lang="fur">imagjin 3D Studio</comment>
+ <comment xml:lang="fr">image 3D Studio</comment>
+ <comment xml:lang="fo">3D Studio mynd</comment>
+ <comment xml:lang="fi">3D Studio -kuva</comment>
+ <comment xml:lang="eu">3D Studio-ko irudia</comment>
+ <comment xml:lang="es">imagen de 3D Studio</comment>
+ <comment xml:lang="eo">bildo de 3D Studio</comment>
+ <comment xml:lang="en_GB">3D Studio image</comment>
+ <comment xml:lang="el">Εικόνα 3D Studio</comment>
+ <comment xml:lang="de">3D-Studio-Bild</comment>
+ <comment xml:lang="da">3D Studio-billede</comment>
+ <comment xml:lang="cy">Delwedd "3D Studio"</comment>
+ <comment xml:lang="cs">obrázek 3D Studio</comment>
+ <comment xml:lang="ca">imatge de 3D Studio</comment>
+ <comment xml:lang="bg">Изображение — 3D Studio</comment>
+ <comment xml:lang="be@latin">Vyjava 3D Studio</comment>
+ <comment xml:lang="be">выява 3D Studio</comment>
+ <comment xml:lang="az">3D Studio rəsmi</comment>
+ <comment xml:lang="ar">صورة 3دي استديو</comment>
+ <comment xml:lang="af">3D Studio-beeld</comment>
<glob pattern="*.3ds"/>
+ <magic priority="30">
+ <match offset="0" type="big16" value="0x4d4d"/>
+ </magic>
</mime-type>
<mime-type type="image/x-applix-graphics">
<comment>Applix Graphics image</comment>
- <comment xml:lang="ar">صورة رسوميات Applix</comment>
- <comment xml:lang="be@latin">Vyjava Applix Graphics</comment>
- <comment xml:lang="bg">Изображение — Applix Graphics</comment>
- <comment xml:lang="ca">imatge d'Applix Graphics</comment>
- <comment xml:lang="cs">obrázek Applix Graphics</comment>
- <comment xml:lang="da">Applix Graphics-billede</comment>
- <comment xml:lang="de">Applix-Graphics-Bild</comment>
- <comment xml:lang="el">Εικόνα Applix Graphics</comment>
- <comment xml:lang="en_GB">Applix Graphics image</comment>
- <comment xml:lang="eo">bildo de Applix Graphics</comment>
- <comment xml:lang="es">imagen de Applix Graphics</comment>
- <comment xml:lang="eu">Applix Graphics irudia</comment>
- <comment xml:lang="fi">Applix Graphics -kuva</comment>
- <comment xml:lang="fo">Applix Graphics mynd</comment>
- <comment xml:lang="fr">image Applix Graphics</comment>
- <comment xml:lang="ga">íomhá Applix Graphics</comment>
- <comment xml:lang="gl">imaxe de Applix Graphics</comment>
- <comment xml:lang="he">תמונה של Applix Graphics</comment>
- <comment xml:lang="hr">Applix Graphics slika</comment>
- <comment xml:lang="hu">Applix Graphics-kép</comment>
- <comment xml:lang="ia">Imagine Applix Graphics</comment>
- <comment xml:lang="id">Citra Applix Graphics</comment>
- <comment xml:lang="it">Immagine Applix Graphics</comment>
- <comment xml:lang="ja">Applix Graphics 画像</comment>
- <comment xml:lang="ka">Applix Graphics-ის გამოსახულება</comment>
- <comment xml:lang="kk">Applix Graphics суреті</comment>
- <comment xml:lang="ko">Applix Graphics 그림</comment>
- <comment xml:lang="lt">Applix Graphics paveikslėlis</comment>
- <comment xml:lang="lv">Applix Graphics attēls</comment>
- <comment xml:lang="ms">Imej Applix Graphics</comment>
- <comment xml:lang="nb">Applix Graphics-dokument</comment>
- <comment xml:lang="nl">Applix Graphics-afbeelding</comment>
- <comment xml:lang="nn">Applix Graphics-dokument</comment>
- <comment xml:lang="oc">imatge Applix Graphics</comment>
- <comment xml:lang="pl">Obraz Applix Graphics</comment>
- <comment xml:lang="pt">imagem Applix Graphics</comment>
- <comment xml:lang="pt_BR">Imagem do Applix Graphics</comment>
- <comment xml:lang="ro">Imagine Applix Graphics</comment>
- <comment xml:lang="ru">Изображение Applix Graphics</comment>
- <comment xml:lang="sk">Obrázok Applix Graphics</comment>
- <comment xml:lang="sl">Slikovna datoteka Applix Graphics</comment>
- <comment xml:lang="sq">Figurë Applix Graphics</comment>
- <comment xml:lang="sr">Апликсов графички документ</comment>
- <comment xml:lang="sv">Applix Graphics-bild</comment>
- <comment xml:lang="tr">Applix Graphics görüntüsü</comment>
- <comment xml:lang="uk">зображення Applix Graphics</comment>
- <comment xml:lang="vi">Ảnh Applix Graphics</comment>
- <comment xml:lang="zh_CN">Applix Graphics 图像</comment>
<comment xml:lang="zh_TW">Applix Graphics 影像</comment>
- <magic priority="50">
- <match value="*BEGIN" type="string" offset="0">
- <match value="GRAPHICS" type="string" offset="7"/>
+ <comment xml:lang="zh_CN">Applix Graphics 图像</comment>
+ <comment xml:lang="vi">Ảnh Applix Graphics</comment>
+ <comment xml:lang="uk">зображення Applix Graphics</comment>
+ <comment xml:lang="tr">Applix Graphics görüntüsü</comment>
+ <comment xml:lang="sv">Applix Graphics-bild</comment>
+ <comment xml:lang="sr">Апликсов графички документ</comment>
+ <comment xml:lang="sq">figurë Applix Graphics</comment>
+ <comment xml:lang="sl">Slikovna datoteka Applix Graphics</comment>
+ <comment xml:lang="si">Applix Graphics රූපය</comment>
+ <comment xml:lang="sk">Obrázok Applix Graphics</comment>
+ <comment xml:lang="ru">Изображение Applix Graphics</comment>
+ <comment xml:lang="ro">Imagine Applix Graphics</comment>
+ <comment xml:lang="pt_BR">Imagem do Applix Graphics</comment>
+ <comment xml:lang="pt">imagem Applix Graphics</comment>
+ <comment xml:lang="pl">Obraz Applix Graphics</comment>
+ <comment xml:lang="oc">imatge Applix Graphics</comment>
+ <comment xml:lang="nn">Applix Graphics-dokument</comment>
+ <comment xml:lang="nl">Applix Graphics-afbeelding</comment>
+ <comment xml:lang="nb">Applix Graphics-dokument</comment>
+ <comment xml:lang="ms">Imej Applix Graphics</comment>
+ <comment xml:lang="lv">Applix Graphics attēls</comment>
+ <comment xml:lang="lt">Applix Graphics paveikslėlis</comment>
+ <comment xml:lang="ko">Applix Graphics 그림</comment>
+ <comment xml:lang="kk">Applix Graphics суреті</comment>
+ <comment xml:lang="ka">Applix Graphics-ის გამოსახულება</comment>
+ <comment xml:lang="ja">Applix Graphics 画像</comment>
+ <comment xml:lang="it">Immagine Applix Graphics</comment>
+ <comment xml:lang="is">Applix Graphics mynd</comment>
+ <comment xml:lang="id">Citra Applix Graphics</comment>
+ <comment xml:lang="ia">Imagine Applix Graphics</comment>
+ <comment xml:lang="hu">Applix Graphics-kép</comment>
+ <comment xml:lang="hr">Applix Graphics slika</comment>
+ <comment xml:lang="he">תמונה של Applix Graphics</comment>
+ <comment xml:lang="gl">imaxe de Applix Graphics</comment>
+ <comment xml:lang="ga">íomhá Applix Graphics</comment>
+ <comment xml:lang="fur">imagjin Applix Graphics</comment>
+ <comment xml:lang="fr">image Applix Graphics</comment>
+ <comment xml:lang="fo">Applix Graphics mynd</comment>
+ <comment xml:lang="fi">Applix Graphics -kuva</comment>
+ <comment xml:lang="eu">Applix Graphics irudia</comment>
+ <comment xml:lang="es">imagen de Applix Graphics</comment>
+ <comment xml:lang="eo">bildo de Applix Graphics</comment>
+ <comment xml:lang="en_GB">Applix Graphics image</comment>
+ <comment xml:lang="el">Εικόνα Applix Graphics</comment>
+ <comment xml:lang="de">Applix-Graphics-Bild</comment>
+ <comment xml:lang="da">Applix Graphics-billede</comment>
+ <comment xml:lang="cs">obrázek Applix Graphics</comment>
+ <comment xml:lang="ca">imatge d'Applix Graphics</comment>
+ <comment xml:lang="bg">Изображение — Applix Graphics</comment>
+ <comment xml:lang="be@latin">Vyjava Applix Graphics</comment>
+ <comment xml:lang="be">выява Applix Graphics</comment>
+ <comment xml:lang="ar">صورة رسوميات Applix</comment>
+ <comment xml:lang="af">Applix Graphics-beeld</comment>
+ <magic>
+ <match type="string" value="*BEGIN" offset="0">
+ <match type="string" value="GRAPHICS" offset="7"/>
</match>
</magic>
<glob pattern="*.ag"/>
</mime-type>
<mime-type type="image/x-bzeps">
- <comment>EPS image (bzip-compressed)</comment>
- <comment xml:lang="ar">صورة EPS (مضغوط-bzip)</comment>
- <comment xml:lang="be@latin">Vyjava EPS (bzip-skampresavanaja)</comment>
- <comment xml:lang="bg">Изображение — EPS, компресирано с bzip</comment>
- <comment xml:lang="ca">imatge EPS (amb compressió bzip)</comment>
- <comment xml:lang="cs">obrázek EPS (komprimovaný pomocí bzip)</comment>
- <comment xml:lang="da">EPS-billede (bzip-komprimeret)</comment>
- <comment xml:lang="de">EPS-Bild (bzip-komprimiert)</comment>
- <comment xml:lang="el">Εικόνα EPS (συμπιεσμένη bzip)</comment>
- <comment xml:lang="en_GB">EPS image (bzip-compressed)</comment>
- <comment xml:lang="es">imagen EPS (comprimida con bzip)</comment>
- <comment xml:lang="eu">EPS irudia (bzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">EPS-kuva (bzip-pakattu)</comment>
- <comment xml:lang="fo">EPS mynd (bzip-stappað)</comment>
- <comment xml:lang="fr">image EPS (compressée bzip)</comment>
- <comment xml:lang="ga">íomhá EPS (comhbhrúite le bzip)</comment>
- <comment xml:lang="gl">imaxe EPS (comprimida con bzip)</comment>
- <comment xml:lang="he">תמונת EPS (מכווץ בbzip)</comment>
- <comment xml:lang="hr">EPS slika (bzip sažeta)</comment>
- <comment xml:lang="hu">EPS kép (bzip-tömörítésű)</comment>
- <comment xml:lang="ia">Imagine EPS (comprimite con bzip)</comment>
- <comment xml:lang="id">Citra EPS (terkompresi bzip)</comment>
- <comment xml:lang="it">Immagine EPS (compressa con bzip)</comment>
- <comment xml:lang="ja">EPS 画像 (bzip 圧縮)</comment>
- <comment xml:lang="ka">EPS გამოსახულება (bzip-ით შეკუმშული)</comment>
- <comment xml:lang="kk">EPS суреті (bzip-пен сығылған)</comment>
- <comment xml:lang="ko">EPS 그림(BZIP 압축)</comment>
- <comment xml:lang="lt">EPS paveikslėlis (suglaudintas su bzip)</comment>
- <comment xml:lang="lv">EPS attēls (saspiests ar bzip)</comment>
- <comment xml:lang="nb">EPS-bilde (bzip-komprimert)</comment>
- <comment xml:lang="nl">EPS-afbeelding (ingepakt met bzip)</comment>
- <comment xml:lang="nn">EPS-bilete (pakka med bzip)</comment>
- <comment xml:lang="oc">imatge EPS (compressat bzip)</comment>
- <comment xml:lang="pl">Obraz EPS (kompresja bzip)</comment>
- <comment xml:lang="pt">imagem EPS (compressão bzip)</comment>
- <comment xml:lang="pt_BR">Imagem EPS (compactada com bzip)</comment>
- <comment xml:lang="ro">Imagine EPS (compresie bzip)</comment>
- <comment xml:lang="ru">Изображение EPS (сжатое bzip)</comment>
- <comment xml:lang="sk">Obrázok EPS (komprimovaný pomocou bzip)</comment>
- <comment xml:lang="sl">Slikovna datoteka EPS (stisnjena z bzip)</comment>
- <comment xml:lang="sq">Figurë EPS (e kompresuar me bzip)</comment>
- <comment xml:lang="sr">ЕПС слика (запакована бзип-ом)</comment>
- <comment xml:lang="sv">EPS-bild (bzip-komprimerad)</comment>
- <comment xml:lang="tr">EPS görüntüsü (bzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">зображення EPS (стиснене bzip)</comment>
- <comment xml:lang="vi">Ảnh EPS (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">EPS 图像(bzip 压缩)</comment>
- <comment xml:lang="zh_TW">EPS 影像 (bzip 格式壓縮)</comment>
- <sub-class-of type="application/x-bzip"/>
+ <comment>EPS image (bzip2-compressed)</comment>
+ <comment xml:lang="uk">зображення EPS (стиснений bzip2)</comment>
+ <comment xml:lang="sv">EPS-bild (bzip2-komprimerad)</comment>
+ <comment xml:lang="ru">Изображение EPS (сжатое bzip2)</comment>
+ <comment xml:lang="pl">Obraz EPS (kompresja bzip2)</comment>
+ <comment xml:lang="es">imagen EPS (comprimida con BZIP2)</comment>
+ <comment xml:lang="de">EPS-Bild (bzip2-komprimiert)</comment>
+ <sub-class-of type="application/x-bzip2"/>
<glob pattern="*.eps.bz2"/>
<glob pattern="*.epsi.bz2"/>
<glob pattern="*.epsf.bz2"/>
</mime-type>
<mime-type type="image/x-cmu-raster">
<comment>CMU raster image</comment>
- <comment xml:lang="ar">صورة CMU نقطية</comment>
- <comment xml:lang="az">CMU raster rəsmi</comment>
- <comment xml:lang="be@latin">Rastravaja vyjava CMU</comment>
- <comment xml:lang="bg">Изображение — CMU raster</comment>
- <comment xml:lang="ca">imatge ràster CMU</comment>
- <comment xml:lang="cs">rastrový obrázek CMU</comment>
- <comment xml:lang="cy">Delwedd raster CMU</comment>
- <comment xml:lang="da">CMU-rasterbillede</comment>
- <comment xml:lang="de">CMU-Rasterbild</comment>
- <comment xml:lang="el">Εικόνα ράστερ CMU</comment>
- <comment xml:lang="en_GB">CMU raster image</comment>
- <comment xml:lang="eo">rastruma bildo de CMU</comment>
- <comment xml:lang="es">imagen ráster CMU</comment>
- <comment xml:lang="eu">CMU bilbe-irudia</comment>
- <comment xml:lang="fi">CMU-rasterikuva</comment>
- <comment xml:lang="fo">CMU raster mynd</comment>
- <comment xml:lang="fr">image raster CMU</comment>
- <comment xml:lang="ga">íomhá rastar CMU</comment>
- <comment xml:lang="gl">imaxe raster CMU</comment>
- <comment xml:lang="he">תמונת סריקה CMU</comment>
- <comment xml:lang="hr">CMU iscrtana slika</comment>
- <comment xml:lang="hu">CMU-raszterkép</comment>
- <comment xml:lang="ia">Imagine raster CMU</comment>
- <comment xml:lang="id">Citra raster CMU</comment>
- <comment xml:lang="it">Immagine raster CMU</comment>
- <comment xml:lang="ja">CMU ラスター画像</comment>
- <comment xml:lang="ka">CMU-ის რასტრული გამოსახულება</comment>
- <comment xml:lang="kk">CMU растрлық суреті</comment>
- <comment xml:lang="ko">CMU 래스터 그림</comment>
- <comment xml:lang="lt">CMU rastrinis paveikslėlis</comment>
- <comment xml:lang="lv">CMU rastra attēls</comment>
- <comment xml:lang="ms">Imej raster CMU</comment>
- <comment xml:lang="nb">CMU-rasterbilde</comment>
- <comment xml:lang="nl">CMU-rasterafbeelding</comment>
- <comment xml:lang="nn">CMU rasterbilete</comment>
- <comment xml:lang="oc">imatge raster CMU</comment>
- <comment xml:lang="pl">Obraz rastrowy CMU</comment>
- <comment xml:lang="pt">imagem raster CMU</comment>
- <comment xml:lang="pt_BR">Imagem raster CMU</comment>
- <comment xml:lang="ro">Imagine raster CMU</comment>
- <comment xml:lang="ru">Растровое изображение CMU</comment>
- <comment xml:lang="sk">Rastrový obrázok CMU</comment>
- <comment xml:lang="sl">Slikovna rastrska datoteka CMU</comment>
- <comment xml:lang="sq">Figurë raster CMU</comment>
- <comment xml:lang="sr">ЦМУ растерска слика</comment>
- <comment xml:lang="sv">CMU-rasterbild</comment>
- <comment xml:lang="tr">CMU tarama görüntüsü</comment>
- <comment xml:lang="uk">растрове зображення CMU</comment>
- <comment xml:lang="vi">Ảnh mành CMU</comment>
- <comment xml:lang="zh_CN">CMU 光栅图像</comment>
<comment xml:lang="zh_TW">CMU raster 影像</comment>
+ <comment xml:lang="zh_CN">CMU 光栅图像</comment>
+ <comment xml:lang="vi">Ảnh mành CMU</comment>
+ <comment xml:lang="uk">растрове зображення CMU</comment>
+ <comment xml:lang="tr">CMU tarama görüntüsü</comment>
+ <comment xml:lang="sv">CMU-rasterbild</comment>
+ <comment xml:lang="sr">ЦМУ растерска слика</comment>
+ <comment xml:lang="sq">figurë raster CMU</comment>
+ <comment xml:lang="sl">Slikovna rastrska datoteka CMU</comment>
+ <comment xml:lang="si">CMU රාස්ටර් රූපය</comment>
+ <comment xml:lang="sk">Rastrový obrázok CMU</comment>
+ <comment xml:lang="ru">Растровое изображение CMU</comment>
+ <comment xml:lang="ro">Imagine raster CMU</comment>
+ <comment xml:lang="pt_BR">Imagem raster CMU</comment>
+ <comment xml:lang="pt">imagem raster CMU</comment>
+ <comment xml:lang="pl">Obraz rastrowy CMU</comment>
+ <comment xml:lang="oc">imatge raster CMU</comment>
+ <comment xml:lang="nn">CMU rasterbilete</comment>
+ <comment xml:lang="nl">CMU-rasterafbeelding</comment>
+ <comment xml:lang="nb">CMU-rasterbilde</comment>
+ <comment xml:lang="ms">Imej raster CMU</comment>
+ <comment xml:lang="lv">CMU rastra attēls</comment>
+ <comment xml:lang="lt">CMU rastrinis paveikslėlis</comment>
+ <comment xml:lang="ko">CMU 래스터 그림</comment>
+ <comment xml:lang="kk">CMU растрлық суреті</comment>
+ <comment xml:lang="ka">CMU-ის რასტრული გამოსახულება</comment>
+ <comment xml:lang="ja">CMU ラスター画像</comment>
+ <comment xml:lang="it">Immagine raster CMU</comment>
+ <comment xml:lang="is">CMU rastamynd</comment>
+ <comment xml:lang="id">Citra raster CMU</comment>
+ <comment xml:lang="ia">Imagine raster CMU</comment>
+ <comment xml:lang="hu">CMU-raszterkép</comment>
+ <comment xml:lang="hr">CMU iscrtana slika</comment>
+ <comment xml:lang="he">תמונת סריקה CMU</comment>
+ <comment xml:lang="gl">imaxe raster CMU</comment>
+ <comment xml:lang="ga">íomhá rastar CMU</comment>
+ <comment xml:lang="fur">imagjin raster CMU</comment>
+ <comment xml:lang="fr">image raster CMU</comment>
+ <comment xml:lang="fo">CMU raster mynd</comment>
+ <comment xml:lang="fi">CMU-rasterikuva</comment>
+ <comment xml:lang="eu">CMU bilbe-irudia</comment>
+ <comment xml:lang="es">imagen ráster CMU</comment>
+ <comment xml:lang="eo">rastruma bildo de CMU</comment>
+ <comment xml:lang="en_GB">CMU raster image</comment>
+ <comment xml:lang="el">Εικόνα ράστερ CMU</comment>
+ <comment xml:lang="de">CMU-Rasterbild</comment>
+ <comment xml:lang="da">CMU-rasterbillede</comment>
+ <comment xml:lang="cy">Delwedd raster CMU</comment>
+ <comment xml:lang="cs">rastrový obrázek CMU</comment>
+ <comment xml:lang="ca">imatge ràster CMU</comment>
+ <comment xml:lang="bg">Изображение — CMU raster</comment>
+ <comment xml:lang="be@latin">Rastravaja vyjava CMU</comment>
+ <comment xml:lang="be">растравая выява CMU</comment>
+ <comment xml:lang="az">CMU raster rəsmi</comment>
+ <comment xml:lang="ar">صورة CMU نقطية</comment>
+ <comment xml:lang="af">CMU-roosterbeeld</comment>
<glob pattern="*.ras"/>
</mime-type>
<mime-type type="image/x-compressed-xcf">
- <comment>compressed GIMP image</comment>
- <comment xml:lang="ar">صورة GIMP مضغوطة</comment>
- <comment xml:lang="be@latin">skampresavanaja vyjava GIMP</comment>
- <comment xml:lang="bg">Изображение — GIMP, компресирано</comment>
- <comment xml:lang="ca">imatge GIMP amb compressió</comment>
- <comment xml:lang="cs">komprimovaný obrázek GIMP</comment>
- <comment xml:lang="da">komprimeret GIMP-billede</comment>
- <comment xml:lang="de">Komprimiertes GIMP-Bild</comment>
- <comment xml:lang="el">Συμπιεσμένη εικόνα GIMP</comment>
- <comment xml:lang="en_GB">compressed GIMP image</comment>
- <comment xml:lang="es">imagen GIMP comprimida</comment>
- <comment xml:lang="eu">konprimitutako GIMP irudia</comment>
- <comment xml:lang="fi">pakattu GIMP-kuva</comment>
- <comment xml:lang="fo">stappað GIMP mynd</comment>
- <comment xml:lang="fr">image GIMP compressée</comment>
- <comment xml:lang="ga">íomhá GIMP comhbhrúite</comment>
- <comment xml:lang="gl">imaxe de GIMP comprimida</comment>
- <comment xml:lang="he">תמונת GIMP מכווצת</comment>
- <comment xml:lang="hr">Sažeta GIMP slika</comment>
- <comment xml:lang="hu">tömörített GIMP kép</comment>
- <comment xml:lang="ia">Imagine GIMP comprimite</comment>
- <comment xml:lang="id">Citra GIMP terkompresi</comment>
- <comment xml:lang="it">Immagine GIMP compressa</comment>
- <comment xml:lang="ja">圧縮 GIMP 画像</comment>
- <comment xml:lang="kk">сығылған GIMP суреті</comment>
- <comment xml:lang="ko">압축된 GIMP 그림</comment>
- <comment xml:lang="lt">suglaudintas GIMP paveikslėlis</comment>
- <comment xml:lang="lv">saspiests GIMP attēls</comment>
- <comment xml:lang="nb">komprimert GIMP-bilde</comment>
- <comment xml:lang="nl">ingepakte GIMP-afbeelding</comment>
- <comment xml:lang="nn">komprimert GIMP-bilete</comment>
- <comment xml:lang="oc">imatge GIMP compressat</comment>
- <comment xml:lang="pl">Skompresowany obraz GIMP</comment>
- <comment xml:lang="pt">imagem GIMP comprimida</comment>
- <comment xml:lang="pt_BR">Imagem do GIMP compactada</comment>
- <comment xml:lang="ro">imagine comprimată GIMP</comment>
- <comment xml:lang="ru">Сжатое изображение GIMP</comment>
- <comment xml:lang="sk">Komprimovaný obrázok GIMP</comment>
- <comment xml:lang="sl">Slikovna datoteka GIMP (stisnjena)</comment>
- <comment xml:lang="sq">Figurë GIMP e kompresuar</comment>
- <comment xml:lang="sr">запакована ГИМП слика</comment>
- <comment xml:lang="sv">komprimerad GIMP-bild</comment>
- <comment xml:lang="tr">sıkıştırılmış GIMP görüntüsü</comment>
+ <comment>Compressed GIMP image</comment>
<comment xml:lang="uk">стиснене зображення GIMP</comment>
- <comment xml:lang="vi">ảnh GIMP đã nén</comment>
- <comment xml:lang="zh_CN">压缩的 GIMP 图像</comment>
- <comment xml:lang="zh_TW">壓縮版 GIMP 影像</comment>
+ <comment xml:lang="sv">Komprimerad GIMP-bild</comment>
+ <comment xml:lang="ru">Сжатое изображение GIMP</comment>
+ <comment xml:lang="pl">Skompresowany obraz GIMP</comment>
+ <comment xml:lang="ja">GIMP画像(圧縮)</comment>
+ <comment xml:lang="it">Immagine GIMP compressa</comment>
+ <comment xml:lang="gl">Imaxe GIMP comprimida</comment>
+ <comment xml:lang="eu">GIMP irudi konprimatua</comment>
+ <comment xml:lang="es">imagen de GIMP comprimida</comment>
+ <comment xml:lang="de">Komprimiertes GIMP-Bild</comment>
+ <comment xml:lang="be">сціснутая выява GIMP</comment>
<glob pattern="*.xcf.gz"/>
<glob pattern="*.xcf.bz2"/>
</mime-type>
<mime-type type="application/dicom">
<comment>DICOM image</comment>
- <comment xml:lang="ar">صورة DICOM</comment>
- <comment xml:lang="be@latin">Vyjava DICOM</comment>
- <comment xml:lang="bg">Изображение — DICOM</comment>
- <comment xml:lang="ca">imatge DICOM</comment>
- <comment xml:lang="cs">obrázek DICOM</comment>
- <comment xml:lang="da">DICOM-billede</comment>
- <comment xml:lang="de">DICOM-Bild</comment>
- <comment xml:lang="el">Εικόνα DICOM</comment>
- <comment xml:lang="en_GB">DICOM image</comment>
- <comment xml:lang="eo">DICOM-bildo</comment>
- <comment xml:lang="es">imagen DICOM</comment>
- <comment xml:lang="eu">DICOM irudia</comment>
- <comment xml:lang="fi">DICOM-kuva</comment>
- <comment xml:lang="fo">DICOM mynd</comment>
- <comment xml:lang="fr">image DICOM</comment>
- <comment xml:lang="ga">íomhá DICOM</comment>
- <comment xml:lang="gl">imaxe DICOM</comment>
- <comment xml:lang="he">תמונת DICOM</comment>
- <comment xml:lang="hr">DICOM slika</comment>
- <comment xml:lang="hu">DICOM kép</comment>
- <comment xml:lang="ia">Imagine DICOM</comment>
- <comment xml:lang="id">Citra DICOM</comment>
- <comment xml:lang="it">Immagine DICOM</comment>
- <comment xml:lang="ja">DICOM 画像</comment>
- <comment xml:lang="ka">DICOM გამოსახულება</comment>
- <comment xml:lang="kk">DICOM суреті</comment>
- <comment xml:lang="ko">DICOM 그림</comment>
- <comment xml:lang="lt">DICOM paveikslėlis</comment>
- <comment xml:lang="lv">DICOM attēls</comment>
- <comment xml:lang="nb">DICOM-bilde</comment>
- <comment xml:lang="nl">DICOM-afbeelding</comment>
- <comment xml:lang="nn">DICOM-bilete</comment>
- <comment xml:lang="oc">imatge DICOM</comment>
- <comment xml:lang="pl">Obraz DICOM</comment>
- <comment xml:lang="pt">imagem DICOM</comment>
- <comment xml:lang="pt_BR">Imagem DICOM</comment>
- <comment xml:lang="ro">Imagine DICOM</comment>
- <comment xml:lang="ru">Изображение DICOM</comment>
- <comment xml:lang="sk">Obrázok DICOM</comment>
- <comment xml:lang="sl">Slikovna datoteka DICOM</comment>
- <comment xml:lang="sq">Figurë DICOM</comment>
- <comment xml:lang="sr">ДИКОМ слика</comment>
- <comment xml:lang="sv">DICOM-bild</comment>
- <comment xml:lang="tr">DICOM görüntüsü</comment>
- <comment xml:lang="uk">зображення DICOM</comment>
- <comment xml:lang="vi">Ảnh DICOM</comment>
- <comment xml:lang="zh_CN">DICOM 图像</comment>
<comment xml:lang="zh_TW">DICOM 影像</comment>
+ <comment xml:lang="zh_CN">DICOM 图像</comment>
+ <comment xml:lang="vi">Ảnh DICOM</comment>
+ <comment xml:lang="uk">зображення DICOM</comment>
+ <comment xml:lang="tr">DICOM görüntüsü</comment>
+ <comment xml:lang="sv">DICOM-bild</comment>
+ <comment xml:lang="sr">ДИКОМ слика</comment>
+ <comment xml:lang="sq">figurë DICOM</comment>
+ <comment xml:lang="sl">Slikovna datoteka DICOM</comment>
+ <comment xml:lang="si">DICOM රූපය</comment>
+ <comment xml:lang="sk">Obrázok DICOM</comment>
+ <comment xml:lang="ru">Изображение DICOM</comment>
+ <comment xml:lang="ro">Imagine DICOM</comment>
+ <comment xml:lang="pt_BR">Imagem DICOM</comment>
+ <comment xml:lang="pt">imagem DICOM</comment>
+ <comment xml:lang="pl">Obraz DICOM</comment>
+ <comment xml:lang="oc">imatge DICOM</comment>
+ <comment xml:lang="nn">DICOM-bilete</comment>
+ <comment xml:lang="nl">DICOM-afbeelding</comment>
+ <comment xml:lang="nb">DICOM-bilde</comment>
+ <comment xml:lang="lv">DICOM attēls</comment>
+ <comment xml:lang="lt">DICOM paveikslėlis</comment>
+ <comment xml:lang="ko">DICOM 그림</comment>
+ <comment xml:lang="kk">DICOM суреті</comment>
+ <comment xml:lang="ka">DICOM გამოსახულება</comment>
+ <comment xml:lang="ja">DICOM 画像</comment>
+ <comment xml:lang="it">Immagine DICOM</comment>
+ <comment xml:lang="is">DICOM mynd</comment>
+ <comment xml:lang="id">Citra DICOM</comment>
+ <comment xml:lang="ia">Imagine DICOM</comment>
+ <comment xml:lang="hu">DICOM kép</comment>
+ <comment xml:lang="hr">DICOM slika</comment>
+ <comment xml:lang="he">תמונת DICOM</comment>
+ <comment xml:lang="gl">imaxe DICOM</comment>
+ <comment xml:lang="ga">íomhá DICOM</comment>
+ <comment xml:lang="fur">imagjin DICOM</comment>
+ <comment xml:lang="fr">image DICOM</comment>
+ <comment xml:lang="fo">DICOM mynd</comment>
+ <comment xml:lang="fi">DICOM-kuva</comment>
+ <comment xml:lang="eu">DICOM irudia</comment>
+ <comment xml:lang="es">imagen DICOM</comment>
+ <comment xml:lang="eo">DICOM-bildo</comment>
+ <comment xml:lang="en_GB">DICOM image</comment>
+ <comment xml:lang="el">Εικόνα DICOM</comment>
+ <comment xml:lang="de">DICOM-Bild</comment>
+ <comment xml:lang="da">DICOM-billede</comment>
+ <comment xml:lang="cs">obrázek DICOM</comment>
+ <comment xml:lang="ca">imatge DICOM</comment>
+ <comment xml:lang="bg">Изображение — DICOM</comment>
+ <comment xml:lang="be@latin">Vyjava DICOM</comment>
+ <comment xml:lang="be">выява DICOM</comment>
+ <comment xml:lang="ar">صورة DICOM</comment>
+ <comment xml:lang="af">DICOM-beeld</comment>
<acronym>DICOM</acronym>
<expanded-acronym>Digital Imaging and Communications in Medicine</expanded-acronym>
<generic-icon name="image-x-generic"/>
<glob pattern="dicomdir"/>
<glob pattern="*.dcm"/>
- <magic priority="50">
- <match value="DICM" type="string" offset="128"/>
+ <magic>
+ <match type="string" value="DICM" offset="128"/>
</magic>
</mime-type>
<mime-type type="application/x-docbook+xml">
<comment>DocBook document</comment>
- <comment xml:lang="ar">مستند DocBook</comment>
- <comment xml:lang="ast">Documentu DocBook</comment>
- <comment xml:lang="be@latin">Dakument DocBook</comment>
- <comment xml:lang="bg">Документ — DocBook</comment>
- <comment xml:lang="ca">document DocBook</comment>
- <comment xml:lang="cs">dokument DocBook</comment>
- <comment xml:lang="da">DocBook-dokument</comment>
- <comment xml:lang="de">DocBook-Dokument</comment>
- <comment xml:lang="el">Έγγραφο DocBook</comment>
- <comment xml:lang="en_GB">DocBook document</comment>
- <comment xml:lang="eo">DocBook-dokumento</comment>
- <comment xml:lang="es">documento DocBook</comment>
- <comment xml:lang="eu">DocBook dokumentua</comment>
- <comment xml:lang="fi">DocBook-asiakirja</comment>
- <comment xml:lang="fo">DocBook skjal</comment>
- <comment xml:lang="fr">document DocBook</comment>
- <comment xml:lang="ga">cáipéis DocBook</comment>
- <comment xml:lang="gl">documento de DocBook</comment>
- <comment xml:lang="he">מסמך DocBook</comment>
- <comment xml:lang="hr">DocBook dokument</comment>
- <comment xml:lang="hu">DocBook dokumentum</comment>
- <comment xml:lang="ia">Documento DocBook</comment>
- <comment xml:lang="id">Dokumen DocBook</comment>
- <comment xml:lang="it">Documento DocBook</comment>
- <comment xml:lang="ja">DocBook ドキュメント</comment>
- <comment xml:lang="ka">DocBook-ის დოკუმენტი</comment>
- <comment xml:lang="kk">DocBook құжаты</comment>
- <comment xml:lang="ko">DocBook 문서</comment>
- <comment xml:lang="lt">DocBook dokumentas</comment>
- <comment xml:lang="lv">DocBook dokuments</comment>
- <comment xml:lang="nb">DocBook-dokument</comment>
- <comment xml:lang="nl">DocBook-document</comment>
- <comment xml:lang="nn">DocBook-dokument</comment>
- <comment xml:lang="oc">document DocBook</comment>
- <comment xml:lang="pl">Dokument DocBook</comment>
- <comment xml:lang="pt">documento DocBook</comment>
- <comment xml:lang="pt_BR">Documento DocBook</comment>
- <comment xml:lang="ro">Document DocBook</comment>
- <comment xml:lang="ru">Документ DocBook</comment>
- <comment xml:lang="sk">Dokument DocBook</comment>
- <comment xml:lang="sl">Dokument DocBook</comment>
- <comment xml:lang="sq">Dokument DocBook</comment>
- <comment xml:lang="sr">Док Бук документ</comment>
- <comment xml:lang="sv">DocBook-dokument</comment>
- <comment xml:lang="tr">DocBook belgesi</comment>
- <comment xml:lang="uk">документ DocBook</comment>
- <comment xml:lang="vi">Tài liệu DocBook</comment>
- <comment xml:lang="zh_CN">DocBook 文档</comment>
<comment xml:lang="zh_TW">DocBook 文件</comment>
+ <comment xml:lang="zh_CN">DocBook 文档</comment>
+ <comment xml:lang="vi">Tài liệu DocBook</comment>
+ <comment xml:lang="uk">документ DocBook</comment>
+ <comment xml:lang="tr">DocBook belgesi</comment>
+ <comment xml:lang="sv">DocBook-dokument</comment>
+ <comment xml:lang="sr">Док Бук документ</comment>
+ <comment xml:lang="sq">dokument DocBook</comment>
+ <comment xml:lang="sl">Dokument DocBook</comment>
+ <comment xml:lang="si">DocBook ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument DocBook</comment>
+ <comment xml:lang="ru">Документ DocBook</comment>
+ <comment xml:lang="ro">Document DocBook</comment>
+ <comment xml:lang="pt_BR">Documento DocBook</comment>
+ <comment xml:lang="pt">documento DocBook</comment>
+ <comment xml:lang="pl">Dokument DocBook</comment>
+ <comment xml:lang="oc">document DocBook</comment>
+ <comment xml:lang="nn">DocBook-dokument</comment>
+ <comment xml:lang="nl">DocBook-document</comment>
+ <comment xml:lang="nb">DocBook-dokument</comment>
+ <comment xml:lang="lv">DocBook dokuments</comment>
+ <comment xml:lang="lt">DocBook dokumentas</comment>
+ <comment xml:lang="ko">DocBook 문서</comment>
+ <comment xml:lang="kk">DocBook құжаты</comment>
+ <comment xml:lang="ka">DocBook-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">DocBook ドキュメント</comment>
+ <comment xml:lang="it">Documento DocBook</comment>
+ <comment xml:lang="is">DocBook skjal</comment>
+ <comment xml:lang="id">Dokumen DocBook</comment>
+ <comment xml:lang="ia">Documento DocBook</comment>
+ <comment xml:lang="hu">DocBook dokumentum</comment>
+ <comment xml:lang="hr">DocBook dokument</comment>
+ <comment xml:lang="he">מסמך DocBook</comment>
+ <comment xml:lang="gl">documento de DocBook</comment>
+ <comment xml:lang="ga">cáipéis DocBook</comment>
+ <comment xml:lang="fur">document DocBook</comment>
+ <comment xml:lang="fr">document DocBook</comment>
+ <comment xml:lang="fo">DocBook skjal</comment>
+ <comment xml:lang="fi">DocBook-asiakirja</comment>
+ <comment xml:lang="eu">DocBook dokumentua</comment>
+ <comment xml:lang="es">documento DocBook</comment>
+ <comment xml:lang="eo">DocBook-dokumento</comment>
+ <comment xml:lang="en_GB">DocBook document</comment>
+ <comment xml:lang="el">Έγγραφο DocBook</comment>
+ <comment xml:lang="de">DocBook-Dokument</comment>
+ <comment xml:lang="da">DocBook-dokument</comment>
+ <comment xml:lang="cs">dokument DocBook</comment>
+ <comment xml:lang="ca">document DocBook</comment>
+ <comment xml:lang="bg">Документ — DocBook</comment>
+ <comment xml:lang="be@latin">Dakument DocBook</comment>
+ <comment xml:lang="be">дакумент DocBook</comment>
+ <comment xml:lang="ast">Documentu DocBook</comment>
+ <comment xml:lang="ar">مستند DocBook</comment>
+ <comment xml:lang="af">DocBook-dokument</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="x-office-document"/>
<magic priority="90">
@@ -27867,119 +30384,129 @@
</mime-type>
<mime-type type="image/x-dib">
<comment>DIB image</comment>
- <comment xml:lang="ar">صورة DIB</comment>
- <comment xml:lang="be@latin">Vyjava DIB</comment>
- <comment xml:lang="bg">Изображение — DIB</comment>
- <comment xml:lang="ca">imatge DIB</comment>
- <comment xml:lang="cs">obrázek DIB</comment>
- <comment xml:lang="da">DIB-billede</comment>
- <comment xml:lang="de">DIB-Bild</comment>
- <comment xml:lang="el">Εικόνα DIB</comment>
- <comment xml:lang="en_GB">DIB image</comment>
- <comment xml:lang="eo">DIB-bildo</comment>
- <comment xml:lang="es">imagen DIB</comment>
- <comment xml:lang="eu">DIB irudia</comment>
- <comment xml:lang="fi">DIB-kuva</comment>
- <comment xml:lang="fo">DIB mynd</comment>
- <comment xml:lang="fr">image DIB</comment>
- <comment xml:lang="ga">íomhá DIB</comment>
- <comment xml:lang="gl">imaxe DIB</comment>
- <comment xml:lang="he">תמונת DIB</comment>
- <comment xml:lang="hr">DIB slika</comment>
- <comment xml:lang="hu">DIB kép</comment>
- <comment xml:lang="ia">Imagine DIB</comment>
- <comment xml:lang="id">Citra DIB</comment>
- <comment xml:lang="it">Immagine DIB</comment>
- <comment xml:lang="ja">DIB 画像</comment>
- <comment xml:lang="ka">DIB გამოსახულება</comment>
- <comment xml:lang="kk">DIB суреті</comment>
- <comment xml:lang="ko">DIB 그림</comment>
- <comment xml:lang="lt">DIB paveikslėlis</comment>
- <comment xml:lang="lv">DIB attēls</comment>
- <comment xml:lang="nb">DIB-bilde</comment>
- <comment xml:lang="nl">DIB-afbeelding</comment>
- <comment xml:lang="nn">DIB-bilete</comment>
- <comment xml:lang="oc">imatge DIB</comment>
- <comment xml:lang="pl">Obraz DIB</comment>
- <comment xml:lang="pt">imagem DIB</comment>
- <comment xml:lang="pt_BR">Imagem DIB</comment>
- <comment xml:lang="ro">Imagine DIB</comment>
- <comment xml:lang="ru">Изображение DIB</comment>
- <comment xml:lang="sk">Obrázok DIB</comment>
- <comment xml:lang="sl">Slikovna datoteka DIB</comment>
- <comment xml:lang="sq">Figurë DIB</comment>
- <comment xml:lang="sr">ДИБ слика</comment>
- <comment xml:lang="sv">DIB-bild</comment>
- <comment xml:lang="tr">DIB görüntüsü</comment>
- <comment xml:lang="uk">зображення DIB</comment>
- <comment xml:lang="vi">Ảnh DIB</comment>
- <comment xml:lang="zh_CN">DIB 图像</comment>
<comment xml:lang="zh_TW">DIB 影像</comment>
+ <comment xml:lang="zh_CN">DIB 图像</comment>
+ <comment xml:lang="vi">Ảnh DIB</comment>
+ <comment xml:lang="uk">зображення DIB</comment>
+ <comment xml:lang="tr">DIB görüntüsü</comment>
+ <comment xml:lang="sv">DIB-bild</comment>
+ <comment xml:lang="sr">ДИБ слика</comment>
+ <comment xml:lang="sq">figurë DIB</comment>
+ <comment xml:lang="sl">Slikovna datoteka DIB</comment>
+ <comment xml:lang="si">DIB රූපය</comment>
+ <comment xml:lang="sk">Obrázok DIB</comment>
+ <comment xml:lang="ru">Изображение DIB</comment>
+ <comment xml:lang="ro">Imagine DIB</comment>
+ <comment xml:lang="pt_BR">Imagem DIB</comment>
+ <comment xml:lang="pt">imagem DIB</comment>
+ <comment xml:lang="pl">Obraz DIB</comment>
+ <comment xml:lang="oc">imatge DIB</comment>
+ <comment xml:lang="nn">DIB-bilete</comment>
+ <comment xml:lang="nl">DIB-afbeelding</comment>
+ <comment xml:lang="nb">DIB-bilde</comment>
+ <comment xml:lang="lv">DIB attēls</comment>
+ <comment xml:lang="lt">DIB paveikslėlis</comment>
+ <comment xml:lang="ko">DIB 그림</comment>
+ <comment xml:lang="kk">DIB суреті</comment>
+ <comment xml:lang="ka">DIB გამოსახულება</comment>
+ <comment xml:lang="ja">DIB 画像</comment>
+ <comment xml:lang="it">Immagine DIB</comment>
+ <comment xml:lang="is">DIB mynd</comment>
+ <comment xml:lang="id">Citra DIB</comment>
+ <comment xml:lang="ia">Imagine DIB</comment>
+ <comment xml:lang="hu">DIB kép</comment>
+ <comment xml:lang="hr">DIB slika</comment>
+ <comment xml:lang="he">תמונת DIB</comment>
+ <comment xml:lang="gl">imaxe DIB</comment>
+ <comment xml:lang="ga">íomhá DIB</comment>
+ <comment xml:lang="fur">imagjin DIB</comment>
+ <comment xml:lang="fr">image DIB</comment>
+ <comment xml:lang="fo">DIB mynd</comment>
+ <comment xml:lang="fi">DIB-kuva</comment>
+ <comment xml:lang="eu">DIB irudia</comment>
+ <comment xml:lang="es">imagen DIB</comment>
+ <comment xml:lang="eo">DIB-bildo</comment>
+ <comment xml:lang="en_GB">DIB image</comment>
+ <comment xml:lang="el">Εικόνα DIB</comment>
+ <comment xml:lang="de">DIB-Bild</comment>
+ <comment xml:lang="da">DIB-billede</comment>
+ <comment xml:lang="cs">obrázek DIB</comment>
+ <comment xml:lang="ca">imatge DIB</comment>
+ <comment xml:lang="bg">Изображение — DIB</comment>
+ <comment xml:lang="be@latin">Vyjava DIB</comment>
+ <comment xml:lang="be">выява DIB</comment>
+ <comment xml:lang="ar">صورة DIB</comment>
+ <comment xml:lang="af">DIB-beeld</comment>
<acronym>DIB</acronym>
<expanded-acronym>Device Independent Bitmap</expanded-acronym>
- <magic priority="50">
- <match value="\x28\00\00\00" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\x28\00\00\00" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/vnd.djvu">
<comment>DjVu image</comment>
- <comment xml:lang="ar">صورة DjVu</comment>
- <comment xml:lang="be@latin">Vyjava DjVu</comment>
- <comment xml:lang="bg">Изображение — DjVu</comment>
- <comment xml:lang="ca">imatge DjVu</comment>
- <comment xml:lang="cs">obrázek DjVu</comment>
- <comment xml:lang="da">DjVu-billede</comment>
- <comment xml:lang="de">DjVu-Bild</comment>
- <comment xml:lang="el">Εικόνα DjVu</comment>
- <comment xml:lang="en_GB">DjVu image</comment>
- <comment xml:lang="eo">DjVu-bildo</comment>
- <comment xml:lang="es">imagen DjVu</comment>
- <comment xml:lang="eu">DjVU-ko irudia</comment>
- <comment xml:lang="fi">DjVu-kuva</comment>
- <comment xml:lang="fo">DjVu mynd</comment>
- <comment xml:lang="fr">image DjVu</comment>
- <comment xml:lang="ga">íomhá DjVu</comment>
- <comment xml:lang="gl">imaxe de DjVu</comment>
- <comment xml:lang="he">תמונת DjVu</comment>
- <comment xml:lang="hr">DjVu slika</comment>
- <comment xml:lang="hu">DjVu-kép</comment>
- <comment xml:lang="ia">Imagine DjVu</comment>
- <comment xml:lang="id">Citra DjVu</comment>
- <comment xml:lang="it">Immagine DjVu</comment>
- <comment xml:lang="ja">DjVu 画像</comment>
- <comment xml:lang="ka">DjVu გამოსახულება</comment>
- <comment xml:lang="kk">DjVu суреті</comment>
- <comment xml:lang="ko">DjVu 그림</comment>
- <comment xml:lang="lt">DjVu paveikslėlis</comment>
- <comment xml:lang="lv">DjVu attēls</comment>
- <comment xml:lang="ms">Imej DjVu</comment>
- <comment xml:lang="nb">DjVu-bilde</comment>
- <comment xml:lang="nl">DjVu-afbeelding</comment>
- <comment xml:lang="nn">DjVu-bilete</comment>
- <comment xml:lang="oc">imatge DjVu</comment>
- <comment xml:lang="pl">Obraz DjVu</comment>
- <comment xml:lang="pt">imagem DjVu</comment>
- <comment xml:lang="pt_BR">Imagem DjVu</comment>
- <comment xml:lang="ro">Imagine DjVu</comment>
- <comment xml:lang="ru">Изображение DjVu</comment>
- <comment xml:lang="sk">Obrázok DjVu</comment>
- <comment xml:lang="sl">Slikovna datoteka DjVu</comment>
- <comment xml:lang="sq">Figurë DjVu</comment>
- <comment xml:lang="sr">ДјВу слика</comment>
- <comment xml:lang="sv">DjVu-bild</comment>
- <comment xml:lang="tr">DjVu görüntüsü</comment>
- <comment xml:lang="uk">зображення DjVu</comment>
- <comment xml:lang="vi">Ảnh DjVu</comment>
- <comment xml:lang="zh_CN">DjVu 图像</comment>
<comment xml:lang="zh_TW">DjVu 影像</comment>
+ <comment xml:lang="zh_CN">DjVu 图像</comment>
+ <comment xml:lang="vi">Ảnh DjVu</comment>
+ <comment xml:lang="uk">зображення DjVu</comment>
+ <comment xml:lang="tr">DjVu görüntüsü</comment>
+ <comment xml:lang="sv">DjVu-bild</comment>
+ <comment xml:lang="sr">ДјВу слика</comment>
+ <comment xml:lang="sq">figurë DjVu</comment>
+ <comment xml:lang="sl">Slikovna datoteka DjVu</comment>
+ <comment xml:lang="si">DjVu රූපය</comment>
+ <comment xml:lang="sk">Obrázok DjVu</comment>
+ <comment xml:lang="ru">Изображение DjVu</comment>
+ <comment xml:lang="ro">Imagine DjVu</comment>
+ <comment xml:lang="pt_BR">Imagem DjVu</comment>
+ <comment xml:lang="pt">imagem DjVu</comment>
+ <comment xml:lang="pl">Obraz DjVu</comment>
+ <comment xml:lang="oc">imatge DjVu</comment>
+ <comment xml:lang="nn">DjVu-bilete</comment>
+ <comment xml:lang="nl">DjVu-afbeelding</comment>
+ <comment xml:lang="nb">DjVu-bilde</comment>
+ <comment xml:lang="ms">Imej DjVu</comment>
+ <comment xml:lang="lv">DjVu attēls</comment>
+ <comment xml:lang="lt">DjVu paveikslėlis</comment>
+ <comment xml:lang="ko">DjVu 그림</comment>
+ <comment xml:lang="kk">DjVu суреті</comment>
+ <comment xml:lang="ka">DjVu გამოსახულება</comment>
+ <comment xml:lang="ja">DjVu 画像</comment>
+ <comment xml:lang="it">Immagine DjVu</comment>
+ <comment xml:lang="is">DjVu mynd</comment>
+ <comment xml:lang="id">Citra DjVu</comment>
+ <comment xml:lang="ia">Imagine DjVu</comment>
+ <comment xml:lang="hu">DjVu-kép</comment>
+ <comment xml:lang="hr">DjVu slika</comment>
+ <comment xml:lang="he">תמונת DjVu</comment>
+ <comment xml:lang="gl">imaxe de DjVu</comment>
+ <comment xml:lang="ga">íomhá DjVu</comment>
+ <comment xml:lang="fur">imagjin DjVu</comment>
+ <comment xml:lang="fr">image DjVu</comment>
+ <comment xml:lang="fo">DjVu mynd</comment>
+ <comment xml:lang="fi">DjVu-kuva</comment>
+ <comment xml:lang="eu">DjVU-ko irudia</comment>
+ <comment xml:lang="es">imagen DjVu</comment>
+ <comment xml:lang="eo">DjVu-bildo</comment>
+ <comment xml:lang="en_GB">DjVu image</comment>
+ <comment xml:lang="el">Εικόνα DjVu</comment>
+ <comment xml:lang="de">DjVu-Bild</comment>
+ <comment xml:lang="da">DjVu-billede</comment>
+ <comment xml:lang="cs">obrázek DjVu</comment>
+ <comment xml:lang="ca">imatge DjVu</comment>
+ <comment xml:lang="bg">Изображение — DjVu</comment>
+ <comment xml:lang="be@latin">Vyjava DjVu</comment>
+ <comment xml:lang="be">выява DjVu</comment>
+ <comment xml:lang="ar">صورة DjVu</comment>
+ <comment xml:lang="af">DjVu-beeld</comment>
<alias type="image/x-djvu"/>
<alias type="image/x.djvu"/>
<magic priority="80">
- <match value="AT&amp;TFORM" type="string" offset="0">
- <match value="DJVU" type="string" offset="12"/>
+ <match type="string" offset="0" value="AT&amp;TFORM">
+ <match type="string" offset="12" value="DJVU"/>
</match>
- <match value="FORM" type="string" offset="0">
- <match value="DJVU" type="string" offset="8"/>
+ <match type="string" offset="0" value="FORM">
+ <match type="string" offset="8" value="DJVU"/>
</match>
</magic>
<glob pattern="*.djvu"/>
@@ -27987,45 +30514,58 @@
</mime-type>
<mime-type type="image/vnd.djvu+multipage">
<comment>DjVu document</comment>
- <comment xml:lang="ast">Documentu DjVu</comment>
- <comment xml:lang="ca">document DjVu</comment>
- <comment xml:lang="cs">dokument DjVu</comment>
- <comment xml:lang="da">DjVu-dokument</comment>
- <comment xml:lang="de">DjVu-Dokument</comment>
- <comment xml:lang="el">Έγγραφο DjVu</comment>
- <comment xml:lang="en_GB">DjVu document</comment>
- <comment xml:lang="es">documento DjVu</comment>
- <comment xml:lang="eu">DjVu dokumentua</comment>
- <comment xml:lang="fi">DjVu-asiakirja</comment>
- <comment xml:lang="fr">document DjVu</comment>
- <comment xml:lang="ga">cáipéis DjVu</comment>
- <comment xml:lang="he">מסמך DjVu</comment>
- <comment xml:lang="hr">DjVu dokument</comment>
- <comment xml:lang="hu">DjVu dokumentum</comment>
- <comment xml:lang="ia">Documento DjVu</comment>
- <comment xml:lang="id">Dokumen DjVu</comment>
- <comment xml:lang="it">Documento DjVu</comment>
- <comment xml:lang="kk">DjVu құжаты</comment>
- <comment xml:lang="ko">DjVu 문서</comment>
- <comment xml:lang="oc">document DjVu</comment>
- <comment xml:lang="pl">Dokument DjVu</comment>
- <comment xml:lang="pt">documento DjVu</comment>
- <comment xml:lang="pt_BR">Documento DjVu</comment>
- <comment xml:lang="ru">Документ DjVu</comment>
- <comment xml:lang="sk">Dokument DjVu</comment>
- <comment xml:lang="sr">ДјВу документ</comment>
- <comment xml:lang="sv">DjVu-dokument</comment>
- <comment xml:lang="tr">DjVu belgesi</comment>
- <comment xml:lang="uk">документ DjVu</comment>
- <comment xml:lang="zh_CN">DjVu 文档</comment>
<comment xml:lang="zh_TW">DjVu 文件</comment>
+ <comment xml:lang="zh_CN">DjVu 文档</comment>
+ <comment xml:lang="uk">документ DjVu</comment>
+ <comment xml:lang="tr">DjVu belgesi</comment>
+ <comment xml:lang="sv">DjVu-dokument</comment>
+ <comment xml:lang="sr">ДјВу документ</comment>
+ <comment xml:lang="sq">dokument DjVu</comment>
+ <comment xml:lang="sl">Dokument DjVu</comment>
+ <comment xml:lang="si">DjVu ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument DjVu</comment>
+ <comment xml:lang="ru">Документ DjVu</comment>
+ <comment xml:lang="pt_BR">Documento DjVu</comment>
+ <comment xml:lang="pt">documento DjVu</comment>
+ <comment xml:lang="pl">Dokument DjVu</comment>
+ <comment xml:lang="oc">document DjVu</comment>
+ <comment xml:lang="nl">DjVu-document</comment>
+ <comment xml:lang="lt">DjVu dokumentas</comment>
+ <comment xml:lang="ko">DjVu 문서</comment>
+ <comment xml:lang="kk">DjVu құжаты</comment>
+ <comment xml:lang="ja">DjVu ドキュメント</comment>
+ <comment xml:lang="it">Documento DjVu</comment>
+ <comment xml:lang="is">DjVu skjal</comment>
+ <comment xml:lang="id">Dokumen DjVu</comment>
+ <comment xml:lang="ia">Documento DjVu</comment>
+ <comment xml:lang="hu">DjVu dokumentum</comment>
+ <comment xml:lang="hr">DjVu dokument</comment>
+ <comment xml:lang="he">מסמך DjVu</comment>
+ <comment xml:lang="gl">Documento DjVu</comment>
+ <comment xml:lang="ga">cáipéis DjVu</comment>
+ <comment xml:lang="fur">document DjVu</comment>
+ <comment xml:lang="fr">document DjVu</comment>
+ <comment xml:lang="fi">DjVu-asiakirja</comment>
+ <comment xml:lang="eu">DjVu dokumentua</comment>
+ <comment xml:lang="es">documento DjVu</comment>
+ <comment xml:lang="en_GB">DjVu document</comment>
+ <comment xml:lang="el">Έγγραφο DjVu</comment>
+ <comment xml:lang="de">DjVu-Dokument</comment>
+ <comment xml:lang="da">DjVu-dokument</comment>
+ <comment xml:lang="cs">dokument DjVu</comment>
+ <comment xml:lang="ca">document DjVu</comment>
+ <comment xml:lang="bg">Документ — DjVu</comment>
+ <comment xml:lang="be">дакумент DjVu</comment>
+ <comment xml:lang="ast">Documentu DjVu</comment>
+ <comment xml:lang="ar">مستند DjVu</comment>
+ <comment xml:lang="af">DjVu-dokument</comment>
<generic-icon name="x-office-document"/>
<magic priority="80">
- <match value="AT&amp;TFORM" type="string" offset="0">
- <match value="DJVM" type="string" offset="12"/>
+ <match type="string" offset="0" value="AT&amp;TFORM">
+ <match type="string" offset="12" value="DJVM"/>
</match>
- <match value="FORM" type="string" offset="0">
- <match value="DJVM" type="string" offset="8"/>
+ <match type="string" offset="0" value="FORM">
+ <match type="string" offset="8" value="DJVM"/>
</match>
</magic>
<sub-class-of type="image/vnd.djvu"/>
@@ -28034,290 +30574,318 @@
</mime-type>
<mime-type type="image/dpx">
<comment>DPX image</comment>
- <comment xml:lang="ar">صورة DPX</comment>
- <comment xml:lang="be@latin">Vyjava DPX</comment>
- <comment xml:lang="bg">Изображение — DPX</comment>
- <comment xml:lang="ca">imatge DPX</comment>
- <comment xml:lang="cs">obrázek DPX</comment>
- <comment xml:lang="da">DPX-billede</comment>
- <comment xml:lang="de">DPX-Bild</comment>
- <comment xml:lang="el">Εικόνα DPX</comment>
- <comment xml:lang="en_GB">DPX image</comment>
- <comment xml:lang="eo">DPX-bildo</comment>
- <comment xml:lang="es">imagen DPX</comment>
- <comment xml:lang="eu">DPX irudia</comment>
- <comment xml:lang="fi">DPX-kuva</comment>
- <comment xml:lang="fo">DPX mynd</comment>
- <comment xml:lang="fr">image DPX</comment>
- <comment xml:lang="ga">íomhá DPX</comment>
- <comment xml:lang="gl">imaxe DPX</comment>
- <comment xml:lang="he">תמונת DPX</comment>
- <comment xml:lang="hr">DPX slika</comment>
- <comment xml:lang="hu">DPX kép</comment>
- <comment xml:lang="ia">Imagine DPX</comment>
- <comment xml:lang="id">Citra DPX</comment>
- <comment xml:lang="it">Immagine DPX</comment>
- <comment xml:lang="ja">DPX 画像</comment>
- <comment xml:lang="ka">DPX გამოსახულება</comment>
- <comment xml:lang="kk">DPX суреті</comment>
- <comment xml:lang="ko">DPX 그림</comment>
- <comment xml:lang="lt">DPX paveikslėlis</comment>
- <comment xml:lang="lv">DPX attēls</comment>
- <comment xml:lang="nb">DPX-bilde</comment>
- <comment xml:lang="nl">DPX-afbeelding</comment>
- <comment xml:lang="nn">DPX-bilete</comment>
- <comment xml:lang="oc">imatge DPX</comment>
- <comment xml:lang="pl">Obraz DPX</comment>
- <comment xml:lang="pt">imagem DPX</comment>
- <comment xml:lang="pt_BR">Imagem DPX</comment>
- <comment xml:lang="ro">Imagine DPX</comment>
- <comment xml:lang="ru">Изображение DPX</comment>
- <comment xml:lang="sk">Obrázok DPX</comment>
- <comment xml:lang="sl">Slikovna datoteka DPX</comment>
- <comment xml:lang="sq">Figurë DPX</comment>
- <comment xml:lang="sr">ДПИкс слика</comment>
- <comment xml:lang="sv">DPX-bild</comment>
- <comment xml:lang="tr">DPX görüntüsü</comment>
- <comment xml:lang="uk">зображення DPX</comment>
- <comment xml:lang="vi">Ảnh DPX</comment>
- <comment xml:lang="zh_CN">DPX 图像</comment>
<comment xml:lang="zh_TW">DPX 影像</comment>
+ <comment xml:lang="zh_CN">DPX 图像</comment>
+ <comment xml:lang="vi">Ảnh DPX</comment>
+ <comment xml:lang="uk">зображення DPX</comment>
+ <comment xml:lang="tr">DPX görüntüsü</comment>
+ <comment xml:lang="sv">DPX-bild</comment>
+ <comment xml:lang="sr">ДПИкс слика</comment>
+ <comment xml:lang="sq">figurë DPX</comment>
+ <comment xml:lang="sl">Slikovna datoteka DPX</comment>
+ <comment xml:lang="si">DPX රූපය</comment>
+ <comment xml:lang="sk">Obrázok DPX</comment>
+ <comment xml:lang="ru">Изображение DPX</comment>
+ <comment xml:lang="ro">Imagine DPX</comment>
+ <comment xml:lang="pt_BR">Imagem DPX</comment>
+ <comment xml:lang="pt">imagem DPX</comment>
+ <comment xml:lang="pl">Obraz DPX</comment>
+ <comment xml:lang="oc">imatge DPX</comment>
+ <comment xml:lang="nn">DPX-bilete</comment>
+ <comment xml:lang="nl">DPX-afbeelding</comment>
+ <comment xml:lang="nb">DPX-bilde</comment>
+ <comment xml:lang="lv">DPX attēls</comment>
+ <comment xml:lang="lt">DPX paveikslėlis</comment>
+ <comment xml:lang="ko">DPX 그림</comment>
+ <comment xml:lang="kk">DPX суреті</comment>
+ <comment xml:lang="ka">DPX გამოსახულება</comment>
+ <comment xml:lang="ja">DPX 画像</comment>
+ <comment xml:lang="it">Immagine DPX</comment>
+ <comment xml:lang="is">DPX mynd</comment>
+ <comment xml:lang="id">Citra DPX</comment>
+ <comment xml:lang="ia">Imagine DPX</comment>
+ <comment xml:lang="hu">DPX kép</comment>
+ <comment xml:lang="hr">DPX slika</comment>
+ <comment xml:lang="he">תמונת DPX</comment>
+ <comment xml:lang="gl">imaxe DPX</comment>
+ <comment xml:lang="ga">íomhá DPX</comment>
+ <comment xml:lang="fur">imagjin DPX</comment>
+ <comment xml:lang="fr">image DPX</comment>
+ <comment xml:lang="fo">DPX mynd</comment>
+ <comment xml:lang="fi">DPX-kuva</comment>
+ <comment xml:lang="eu">DPX irudia</comment>
+ <comment xml:lang="es">imagen DPX</comment>
+ <comment xml:lang="eo">DPX-bildo</comment>
+ <comment xml:lang="en_GB">DPX image</comment>
+ <comment xml:lang="el">Εικόνα DPX</comment>
+ <comment xml:lang="de">DPX-Bild</comment>
+ <comment xml:lang="da">DPX-billede</comment>
+ <comment xml:lang="cs">obrázek DPX</comment>
+ <comment xml:lang="ca">imatge DPX</comment>
+ <comment xml:lang="bg">Изображение — DPX</comment>
+ <comment xml:lang="be@latin">Vyjava DPX</comment>
+ <comment xml:lang="be">выява DPX</comment>
+ <comment xml:lang="ar">صورة DPX</comment>
+ <comment xml:lang="af">DPX-beeld</comment>
<acronym>DPX</acronym>
<expanded-acronym>Digital Moving Picture Exchange</expanded-acronym>
- <magic priority="50">
- <match value="0x53445058" type="big32" offset="0"/>
+ <magic>
+ <match type="big32" value="0x53445058" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/x-eps">
<comment>EPS image</comment>
- <comment xml:lang="ar">صورة EPS</comment>
- <comment xml:lang="be@latin">Vyjava EPS</comment>
- <comment xml:lang="bg">Изображение — EPS</comment>
- <comment xml:lang="ca">imatge EPS</comment>
- <comment xml:lang="cs">obrázek EPS</comment>
- <comment xml:lang="da">EPS-billede</comment>
- <comment xml:lang="de">EPS-Bild</comment>
- <comment xml:lang="el">Εικόνα EPS</comment>
- <comment xml:lang="en_GB">EPS image</comment>
- <comment xml:lang="eo">EPS-bildo</comment>
- <comment xml:lang="es">imagen EPS</comment>
- <comment xml:lang="eu">EPS irudia</comment>
- <comment xml:lang="fi">EPS-kuva</comment>
- <comment xml:lang="fo">EPS mynd</comment>
- <comment xml:lang="fr">image EPS</comment>
- <comment xml:lang="ga">íomhá EPS</comment>
- <comment xml:lang="gl">imaxe EPS</comment>
- <comment xml:lang="he">תמונת EPS</comment>
- <comment xml:lang="hr">EPS slika</comment>
- <comment xml:lang="hu">EPS kép</comment>
- <comment xml:lang="ia">Imagine EPS</comment>
- <comment xml:lang="id">Citra EPS</comment>
- <comment xml:lang="it">Immagine EPS</comment>
- <comment xml:lang="ja">EPS 画像</comment>
- <comment xml:lang="ka">EPS გამოსახულება</comment>
- <comment xml:lang="kk">EPS суреті</comment>
- <comment xml:lang="ko">EPS 그림</comment>
- <comment xml:lang="lt">EPS paveikslėlis</comment>
- <comment xml:lang="lv">EPS attēls</comment>
- <comment xml:lang="nb">EPS-bilde</comment>
- <comment xml:lang="nl">EPS-afbeelding</comment>
- <comment xml:lang="nn">EPS-bilete</comment>
- <comment xml:lang="oc">imatge EPS</comment>
- <comment xml:lang="pl">Obraz EPS</comment>
- <comment xml:lang="pt">imagem EPS</comment>
- <comment xml:lang="pt_BR">Imagem EPS</comment>
- <comment xml:lang="ro">Imagine EPS</comment>
- <comment xml:lang="ru">Изображение EPS</comment>
- <comment xml:lang="sk">Obrázok EPS</comment>
- <comment xml:lang="sl">Slikovna datoteka EPS</comment>
- <comment xml:lang="sq">Figurë EPS</comment>
- <comment xml:lang="sr">ЕПС слика</comment>
- <comment xml:lang="sv">EPS-bild</comment>
- <comment xml:lang="tr">EPS görüntüsü</comment>
- <comment xml:lang="uk">зображення EPS</comment>
- <comment xml:lang="vi">Ảnh EPS</comment>
- <comment xml:lang="zh_CN">EPS 图像</comment>
<comment xml:lang="zh_TW">EPS 影像</comment>
+ <comment xml:lang="zh_CN">EPS 图像</comment>
+ <comment xml:lang="vi">Ảnh EPS</comment>
+ <comment xml:lang="uk">зображення EPS</comment>
+ <comment xml:lang="tr">EPS görüntüsü</comment>
+ <comment xml:lang="sv">EPS-bild</comment>
+ <comment xml:lang="sr">ЕПС слика</comment>
+ <comment xml:lang="sq">figurë EPS</comment>
+ <comment xml:lang="sl">Slikovna datoteka EPS</comment>
+ <comment xml:lang="si">EPS රූපය</comment>
+ <comment xml:lang="sk">Obrázok EPS</comment>
+ <comment xml:lang="ru">Изображение EPS</comment>
+ <comment xml:lang="ro">Imagine EPS</comment>
+ <comment xml:lang="pt_BR">Imagem EPS</comment>
+ <comment xml:lang="pt">imagem EPS</comment>
+ <comment xml:lang="pl">Obraz EPS</comment>
+ <comment xml:lang="oc">imatge EPS</comment>
+ <comment xml:lang="nn">EPS-bilete</comment>
+ <comment xml:lang="nl">EPS-afbeelding</comment>
+ <comment xml:lang="nb">EPS-bilde</comment>
+ <comment xml:lang="lv">EPS attēls</comment>
+ <comment xml:lang="lt">EPS paveikslėlis</comment>
+ <comment xml:lang="ko">EPS 그림</comment>
+ <comment xml:lang="kk">EPS суреті</comment>
+ <comment xml:lang="ka">EPS გამოსახულება</comment>
+ <comment xml:lang="ja">EPS 画像</comment>
+ <comment xml:lang="it">Immagine EPS</comment>
+ <comment xml:lang="is">EPS mynd</comment>
+ <comment xml:lang="id">Citra EPS</comment>
+ <comment xml:lang="ia">Imagine EPS</comment>
+ <comment xml:lang="hu">EPS kép</comment>
+ <comment xml:lang="hr">EPS slika</comment>
+ <comment xml:lang="he">תמונת EPS</comment>
+ <comment xml:lang="gl">imaxe EPS</comment>
+ <comment xml:lang="ga">íomhá EPS</comment>
+ <comment xml:lang="fur">imagjin EPS</comment>
+ <comment xml:lang="fr">image EPS</comment>
+ <comment xml:lang="fo">EPS mynd</comment>
+ <comment xml:lang="fi">EPS-kuva</comment>
+ <comment xml:lang="eu">EPS irudia</comment>
+ <comment xml:lang="es">imagen EPS</comment>
+ <comment xml:lang="eo">EPS-bildo</comment>
+ <comment xml:lang="en_GB">EPS image</comment>
+ <comment xml:lang="el">Εικόνα EPS</comment>
+ <comment xml:lang="de">EPS-Bild</comment>
+ <comment xml:lang="da">EPS-billede</comment>
+ <comment xml:lang="cs">obrázek EPS</comment>
+ <comment xml:lang="ca">imatge EPS</comment>
+ <comment xml:lang="bg">Изображение — EPS</comment>
+ <comment xml:lang="be@latin">Vyjava EPS</comment>
+ <comment xml:lang="be">выява EPS</comment>
+ <comment xml:lang="ar">صورة EPS</comment>
+ <comment xml:lang="af">EPS-beeld</comment>
<acronym>EPS</acronym>
<expanded-acronym>Encapsulated PostScript</expanded-acronym>
<sub-class-of type="application/postscript"/>
<magic priority="90">
- <match value="%!" type="string" offset="0">
- <match value="EPS" type="string" offset="15"/>
+ <match type="string" value="%!" offset="0">
+ <match type="string" value="EPS" offset="15"/>
</match>
- <match value="\004%!" type="string" offset="0">
- <match value="EPS" type="string" offset="16"/>
+ <match type="string" value="\004%!" offset="0">
+ <match type="string" value="EPS" offset="16"/>
</match>
- <match value="0xC5D0D3C6" type="big32" offset="0"/>
+ <match type="big32" value="0xC5D0D3C6" offset="0"/>
</magic>
<glob pattern="*.eps"/>
<glob pattern="*.epsi"/>
<glob pattern="*.epsf"/>
</mime-type>
- <mime-type type="image/fits">
+ <mime-type type="application/fits">
<comment>FITS document</comment>
- <comment xml:lang="ar">مستند FITS</comment>
- <comment xml:lang="ast">Documentu FITS</comment>
- <comment xml:lang="be@latin">Dakument FITS</comment>
- <comment xml:lang="bg">Документ — FITS</comment>
- <comment xml:lang="ca">document FITS</comment>
- <comment xml:lang="cs">dokument FITS</comment>
- <comment xml:lang="da">FITS-dokument</comment>
- <comment xml:lang="de">FITS-Dokument</comment>
- <comment xml:lang="el">Έγγραφο FITS</comment>
- <comment xml:lang="en_GB">FITS document</comment>
- <comment xml:lang="eo">FITS-dokumento</comment>
- <comment xml:lang="es">documento FITS</comment>
- <comment xml:lang="eu">FITS dokumentua</comment>
- <comment xml:lang="fi">FITS-asiakirja</comment>
- <comment xml:lang="fo">FITS skjal</comment>
- <comment xml:lang="fr">document FITS</comment>
- <comment xml:lang="ga">cáipéis FITS</comment>
- <comment xml:lang="gl">documento FICT</comment>
- <comment xml:lang="he">מסמך FITS</comment>
- <comment xml:lang="hr">FITS dokument</comment>
- <comment xml:lang="hu">FITS dokumentum</comment>
- <comment xml:lang="ia">Documento FITS</comment>
- <comment xml:lang="id">Dokumen FITS</comment>
- <comment xml:lang="it">Documento FITS</comment>
- <comment xml:lang="ja">FITS ドキュメント</comment>
- <comment xml:lang="ka">FITS დოკუმენტი</comment>
- <comment xml:lang="kk">FITS құжаты</comment>
- <comment xml:lang="ko">FITS 문서</comment>
- <comment xml:lang="lt">FITS dokumentas</comment>
- <comment xml:lang="lv">FITS dokuments</comment>
- <comment xml:lang="nb">FITS-dokument</comment>
- <comment xml:lang="nl">FITS-document</comment>
- <comment xml:lang="nn">FITS-dokument</comment>
- <comment xml:lang="oc">document FITS</comment>
- <comment xml:lang="pl">Dokument FITS</comment>
- <comment xml:lang="pt">documento FITS</comment>
- <comment xml:lang="pt_BR">Documento FITS</comment>
- <comment xml:lang="ro">Document FITS</comment>
- <comment xml:lang="ru">Документ FITS</comment>
- <comment xml:lang="sk">Dokument FITS</comment>
- <comment xml:lang="sl">Dokument FITS</comment>
- <comment xml:lang="sq">Dokument FITS</comment>
- <comment xml:lang="sr">ФИТС документ</comment>
- <comment xml:lang="sv">FITS-dokument</comment>
- <comment xml:lang="tr">FITS belgesi</comment>
- <comment xml:lang="uk">документ FITS</comment>
- <comment xml:lang="vi">Tài liệu FITS</comment>
- <comment xml:lang="zh_CN">FITS 文档</comment>
<comment xml:lang="zh_TW">FITS 文件</comment>
+ <comment xml:lang="zh_CN">FITS 文档</comment>
+ <comment xml:lang="vi">Tài liệu FITS</comment>
+ <comment xml:lang="uk">документ FITS</comment>
+ <comment xml:lang="tr">FITS belgesi</comment>
+ <comment xml:lang="sv">FITS-dokument</comment>
+ <comment xml:lang="sr">ФИТС документ</comment>
+ <comment xml:lang="sq">dokument FITS</comment>
+ <comment xml:lang="sl">Dokument FITS</comment>
+ <comment xml:lang="si">FITS ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument FITS</comment>
+ <comment xml:lang="ru">Документ FITS</comment>
+ <comment xml:lang="ro">Document FITS</comment>
+ <comment xml:lang="pt_BR">Documento FITS</comment>
+ <comment xml:lang="pt">documento FITS</comment>
+ <comment xml:lang="pl">Dokument FITS</comment>
+ <comment xml:lang="oc">document FITS</comment>
+ <comment xml:lang="nn">FITS-dokument</comment>
+ <comment xml:lang="nl">FITS-document</comment>
+ <comment xml:lang="nb">FITS-dokument</comment>
+ <comment xml:lang="lv">FITS dokuments</comment>
+ <comment xml:lang="lt">FITS dokumentas</comment>
+ <comment xml:lang="ko">FITS 문서</comment>
+ <comment xml:lang="kk">FITS құжаты</comment>
+ <comment xml:lang="ka">FITS დოკუმენტი</comment>
+ <comment xml:lang="ja">FITS ドキュメント</comment>
+ <comment xml:lang="it">Documento FITS</comment>
+ <comment xml:lang="is">FITS skjalskjal</comment>
+ <comment xml:lang="id">Dokumen FITS</comment>
+ <comment xml:lang="ia">Documento FITS</comment>
+ <comment xml:lang="hu">FITS dokumentum</comment>
+ <comment xml:lang="hr">FITS dokument</comment>
+ <comment xml:lang="he">מסמך FITS</comment>
+ <comment xml:lang="gl">documento FICT</comment>
+ <comment xml:lang="ga">cáipéis FITS</comment>
+ <comment xml:lang="fur">document FITS</comment>
+ <comment xml:lang="fr">document FITS</comment>
+ <comment xml:lang="fo">FITS skjal</comment>
+ <comment xml:lang="fi">FITS-asiakirja</comment>
+ <comment xml:lang="eu">FITS dokumentua</comment>
+ <comment xml:lang="es">documento FITS</comment>
+ <comment xml:lang="eo">FITS-dokumento</comment>
+ <comment xml:lang="en_GB">FITS document</comment>
+ <comment xml:lang="el">Έγγραφο FITS</comment>
+ <comment xml:lang="de">FITS-Dokument</comment>
+ <comment xml:lang="da">FITS-dokument</comment>
+ <comment xml:lang="cs">dokument FITS</comment>
+ <comment xml:lang="ca">document FITS</comment>
+ <comment xml:lang="bg">Документ — FITS</comment>
+ <comment xml:lang="be@latin">Dakument FITS</comment>
+ <comment xml:lang="be">дакумент FITS</comment>
+ <comment xml:lang="ast">Documentu FITS</comment>
+ <comment xml:lang="ar">مستند FITS</comment>
+ <comment xml:lang="af">FITS-dokument</comment>
<acronym>FITS</acronym>
<expanded-acronym>Flexible Image Transport System</expanded-acronym>
- <magic priority="50">
- <match value="SIMPLE =" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="SIMPLE =" offset="0"/>
</magic>
<glob pattern="*.fits"/>
+ <glob pattern="*.fit"/>
+ <glob pattern="*.fts"/>
<alias type="image/x-fits"/>
+ <alias type="image/fits"/>
</mime-type>
<mime-type type="image/x-fpx">
<comment>FPX image</comment>
- <comment xml:lang="ar">صورة FPX</comment>
- <comment xml:lang="be@latin">Vyjava FPX</comment>
- <comment xml:lang="bg">Изображение — FPX</comment>
- <comment xml:lang="ca">imatge FPX</comment>
- <comment xml:lang="cs">obrázek FPX</comment>
- <comment xml:lang="da">FPX-billede</comment>
- <comment xml:lang="de">FPX-Bild</comment>
- <comment xml:lang="el">Εικόνα FPX</comment>
- <comment xml:lang="en_GB">FPX image</comment>
- <comment xml:lang="eo">FPX-bildo</comment>
- <comment xml:lang="es">imagen FPX</comment>
- <comment xml:lang="eu">FPX irudia</comment>
- <comment xml:lang="fi">FPX-kuva</comment>
- <comment xml:lang="fo">FPX mynd</comment>
- <comment xml:lang="fr">image FPX</comment>
- <comment xml:lang="ga">íomhá FPX</comment>
- <comment xml:lang="gl">imaxe FPX</comment>
- <comment xml:lang="he">תמונת FPX</comment>
- <comment xml:lang="hr">FPX slika</comment>
- <comment xml:lang="hu">FPX kép</comment>
- <comment xml:lang="ia">Imagine FPX</comment>
- <comment xml:lang="id">Citra FPX</comment>
- <comment xml:lang="it">Immagine FPX</comment>
- <comment xml:lang="ja">FPX 画像</comment>
- <comment xml:lang="ka">FPX გამოსახულება</comment>
- <comment xml:lang="kk">FPX суреті</comment>
- <comment xml:lang="ko">FPX 그림</comment>
- <comment xml:lang="lt">FPX paveikslėlis</comment>
- <comment xml:lang="lv">FPX attēls</comment>
- <comment xml:lang="nb">FPX-bilde</comment>
- <comment xml:lang="nl">FPX-afbeelding</comment>
- <comment xml:lang="nn">FPX-bilete</comment>
- <comment xml:lang="oc">imatge FPX</comment>
- <comment xml:lang="pl">Obraz FPX</comment>
- <comment xml:lang="pt">imagem FPX</comment>
- <comment xml:lang="pt_BR">Imagem FPX</comment>
- <comment xml:lang="ro">Imagine FPX</comment>
- <comment xml:lang="ru">Изображение FPX</comment>
- <comment xml:lang="sk">Obrázok FPX</comment>
- <comment xml:lang="sl">Slikovna datoteka FPX</comment>
- <comment xml:lang="sq">Figurë FPX</comment>
- <comment xml:lang="sr">ФПИкс слика</comment>
- <comment xml:lang="sv">FPX-bild</comment>
- <comment xml:lang="tr">FPX görüntüsü</comment>
- <comment xml:lang="uk">зображення FPX</comment>
- <comment xml:lang="vi">Ảnh FPX</comment>
- <comment xml:lang="zh_CN">FPX 图像</comment>
<comment xml:lang="zh_TW">FPX 影像</comment>
+ <comment xml:lang="zh_CN">FPX 图像</comment>
+ <comment xml:lang="vi">Ảnh FPX</comment>
+ <comment xml:lang="uk">зображення FPX</comment>
+ <comment xml:lang="tr">FPX görüntüsü</comment>
+ <comment xml:lang="sv">FPX-bild</comment>
+ <comment xml:lang="sr">ФПИкс слика</comment>
+ <comment xml:lang="sq">figurë FPX</comment>
+ <comment xml:lang="sl">Slikovna datoteka FPX</comment>
+ <comment xml:lang="si">FPX රූපය</comment>
+ <comment xml:lang="sk">Obrázok FPX</comment>
+ <comment xml:lang="ru">Изображение FPX</comment>
+ <comment xml:lang="ro">Imagine FPX</comment>
+ <comment xml:lang="pt_BR">Imagem FPX</comment>
+ <comment xml:lang="pt">imagem FPX</comment>
+ <comment xml:lang="pl">Obraz FPX</comment>
+ <comment xml:lang="oc">imatge FPX</comment>
+ <comment xml:lang="nn">FPX-bilete</comment>
+ <comment xml:lang="nl">FPX-afbeelding</comment>
+ <comment xml:lang="nb">FPX-bilde</comment>
+ <comment xml:lang="lv">FPX attēls</comment>
+ <comment xml:lang="lt">FPX paveikslėlis</comment>
+ <comment xml:lang="ko">FPX 그림</comment>
+ <comment xml:lang="kk">FPX суреті</comment>
+ <comment xml:lang="ka">FPX გამოსახულება</comment>
+ <comment xml:lang="ja">FPX 画像</comment>
+ <comment xml:lang="it">Immagine FPX</comment>
+ <comment xml:lang="is">FPX mynd</comment>
+ <comment xml:lang="id">Citra FPX</comment>
+ <comment xml:lang="ia">Imagine FPX</comment>
+ <comment xml:lang="hu">FPX kép</comment>
+ <comment xml:lang="hr">FPX slika</comment>
+ <comment xml:lang="he">תמונת FPX</comment>
+ <comment xml:lang="gl">imaxe FPX</comment>
+ <comment xml:lang="ga">íomhá FPX</comment>
+ <comment xml:lang="fur">imagjin FPX</comment>
+ <comment xml:lang="fr">image FPX</comment>
+ <comment xml:lang="fo">FPX mynd</comment>
+ <comment xml:lang="fi">FPX-kuva</comment>
+ <comment xml:lang="eu">FPX irudia</comment>
+ <comment xml:lang="es">imagen FPX</comment>
+ <comment xml:lang="eo">FPX-bildo</comment>
+ <comment xml:lang="en_GB">FPX image</comment>
+ <comment xml:lang="el">Εικόνα FPX</comment>
+ <comment xml:lang="de">FPX-Bild</comment>
+ <comment xml:lang="da">FPX-billede</comment>
+ <comment xml:lang="cs">obrázek FPX</comment>
+ <comment xml:lang="ca">imatge FPX</comment>
+ <comment xml:lang="bg">Изображение — FPX</comment>
+ <comment xml:lang="be@latin">Vyjava FPX</comment>
+ <comment xml:lang="be">выява FPX</comment>
+ <comment xml:lang="ar">صورة FPX</comment>
+ <comment xml:lang="af">FPX-beeld</comment>
<acronym>FPX</acronym>
<expanded-acronym>FlashPiX</expanded-acronym>
- <magic priority="50">
- <match value="0x46506978" type="big32" offset="0"/>
+ <magic>
+ <match type="big32" value="0x46506978" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/x-gzeps">
<comment>EPS image (gzip-compressed)</comment>
- <comment xml:lang="ar">صورة EPS (مضغوط-gzip)</comment>
- <comment xml:lang="be@latin">Vyjava EPS (gzip-skampresavanaja)</comment>
- <comment xml:lang="bg">Изображение — EPS, компресирано с gzip</comment>
- <comment xml:lang="ca">imatge EPS (amb compressió gzip)</comment>
- <comment xml:lang="cs">obrázek EPS (komprimovaný pomocí gzip)</comment>
- <comment xml:lang="da">EPS-billede (gzip-komprimeret)</comment>
- <comment xml:lang="de">EPS-Bild (gzip-komprimiert)</comment>
- <comment xml:lang="el">Εικόνα EPS (συμπιεσμένη gzip)</comment>
- <comment xml:lang="en_GB">EPS image (gzip-compressed)</comment>
- <comment xml:lang="es">imagen EPS (comprimida con gzip)</comment>
- <comment xml:lang="eu">EPS irudia (gzip-ekin konprimitua)</comment>
- <comment xml:lang="fi">EPS-kuva (gzip-pakattu)</comment>
- <comment xml:lang="fo">EPS mynd (gzip-stappað)</comment>
- <comment xml:lang="fr">image EPS (compressée gzip)</comment>
- <comment xml:lang="ga">íomhá EPS (comhbhrúite le gzip)</comment>
- <comment xml:lang="gl">imaxe EPS (comprimida con gzip)</comment>
- <comment xml:lang="he">תמונת EPS (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">EPS slika (gzip sažeta)</comment>
- <comment xml:lang="hu">EPS kép (gzip-tömörítésű)</comment>
- <comment xml:lang="ia">Imagine EPS (comprimite con gzip)</comment>
- <comment xml:lang="id">Citra EPS (terkompresi gzip)</comment>
- <comment xml:lang="it">Immagine EPS (compressa con gzip)</comment>
- <comment xml:lang="ja">EPS 画像 (gzip 圧縮)</comment>
- <comment xml:lang="ka">EPS გამოსახულება (gzip-ით შეკუმშული)</comment>
- <comment xml:lang="kk">EPS суреті (gzip-пен сығылған)</comment>
- <comment xml:lang="ko">EPS 그림(GZIP 압축)</comment>
- <comment xml:lang="lt">EPS paveikslėlis (suglaudintas su gzip)</comment>
- <comment xml:lang="lv">EPS attēls (saspiests ar gzip)</comment>
- <comment xml:lang="nb">EPS-bilde (gzip-komprimert)</comment>
- <comment xml:lang="nl">EPS-afbeelding (ingepakt met gzip)</comment>
- <comment xml:lang="nn">EPS-bilete (pakka med gzip)</comment>
- <comment xml:lang="oc">imatge EPS (compressat gzip)</comment>
- <comment xml:lang="pl">Obraz EPS (kompresja gzip)</comment>
- <comment xml:lang="pt">imagem EPS (compressão gzip)</comment>
- <comment xml:lang="pt_BR">Imagem EPS (compactada com gzip)</comment>
- <comment xml:lang="ro">Imagine EPS (compresie gzip)</comment>
- <comment xml:lang="ru">Изображение EPS (сжатое gzip)</comment>
- <comment xml:lang="sk">Obrázok EPS (komprimovaný pomocou gzip)</comment>
- <comment xml:lang="sl">Slikovna datoteka EPS (stisnjena z gzip)</comment>
- <comment xml:lang="sq">Figurë EPS (e kompresuar me gzip)</comment>
- <comment xml:lang="sr">ЕПС слика (запакована гзип-ом)</comment>
- <comment xml:lang="sv">EPS-bild (gzip-komprimerad)</comment>
- <comment xml:lang="tr">EPS görüntüsü (gzip ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">зображення EPS (стиснене gzip)</comment>
- <comment xml:lang="vi">Ảnh EPS (đã nén gzip)</comment>
+ <comment xml:lang="zh_TW">EPS 影像 (gzip 壓縮)</comment>
<comment xml:lang="zh_CN">EPS 图像(gzip 压缩)</comment>
- <comment xml:lang="zh_TW">EPS 影像 (gzip 格式壓縮)</comment>
+ <comment xml:lang="vi">Ảnh EPS (đã nén gzip)</comment>
+ <comment xml:lang="uk">зображення EPS (стиснене gzip)</comment>
+ <comment xml:lang="tr">EPS görüntüsü (gzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="sv">EPS-bild (gzip-komprimerad)</comment>
+ <comment xml:lang="sr">ЕПС слика (запакована гзип-ом)</comment>
+ <comment xml:lang="sq">figurë EPS (ngjeshur me gzip)</comment>
+ <comment xml:lang="sl">Slikovna datoteka EPS (stisnjena z gzip)</comment>
+ <comment xml:lang="si">EPS රූපය (gzip සම්පීඩිත)</comment>
+ <comment xml:lang="sk">Obrázok EPS (komprimovaný pomocou gzip)</comment>
+ <comment xml:lang="ru">Изображение EPS (сжатое gzip)</comment>
+ <comment xml:lang="ro">Imagine EPS (compresie gzip)</comment>
+ <comment xml:lang="pt_BR">Imagem EPS (compactada com gzip)</comment>
+ <comment xml:lang="pt">imagem EPS (compressão gzip)</comment>
+ <comment xml:lang="pl">Obraz EPS (kompresja gzip)</comment>
+ <comment xml:lang="oc">imatge EPS (compressat gzip)</comment>
+ <comment xml:lang="nn">EPS-bilete (pakka med gzip)</comment>
+ <comment xml:lang="nl">EPS-afbeelding (ingepakt met gzip)</comment>
+ <comment xml:lang="nb">EPS-bilde (gzip-komprimert)</comment>
+ <comment xml:lang="lv">EPS attēls (saspiests ar gzip)</comment>
+ <comment xml:lang="lt">EPS paveikslėlis (suglaudintas su gzip)</comment>
+ <comment xml:lang="ko">EPS 그림(GZIP 압축)</comment>
+ <comment xml:lang="kk">EPS суреті (gzip-пен сығылған)</comment>
+ <comment xml:lang="ka">EPS გამოსახულება (gzip-ით შეკუმშული)</comment>
+ <comment xml:lang="ja">EPS 画像 (gzip 圧縮)</comment>
+ <comment xml:lang="it">Immagine EPS (compressa con gzip)</comment>
+ <comment xml:lang="is">EPS mynd (gzip-þjöppuð)</comment>
+ <comment xml:lang="id">Citra EPS (terkompresi gzip)</comment>
+ <comment xml:lang="ia">Imagine EPS (comprimite con gzip)</comment>
+ <comment xml:lang="hu">EPS kép (gzip tömörítésű)</comment>
+ <comment xml:lang="hr">EPS slika (gzip sažeta)</comment>
+ <comment xml:lang="he">תמונת EPS (מכווץ ע״י gzip)</comment>
+ <comment xml:lang="gl">imaxe EPS (comprimida con gzip)</comment>
+ <comment xml:lang="ga">íomhá EPS (comhbhrúite le gzip)</comment>
+ <comment xml:lang="fur">imagjin EPS (comprimude cun gzip)</comment>
+ <comment xml:lang="fr">image EPS (compressée gzip)</comment>
+ <comment xml:lang="fo">EPS mynd (gzip-stappað)</comment>
+ <comment xml:lang="fi">EPS-kuva (gzip-pakattu)</comment>
+ <comment xml:lang="eu">EPS irudia (gzip-ekin konprimitua)</comment>
+ <comment xml:lang="es">imagen EPS (comprimida con GZIP)</comment>
+ <comment xml:lang="en_GB">EPS image (gzip-compressed)</comment>
+ <comment xml:lang="el">Εικόνα EPS (συμπιεσμένη gzip)</comment>
+ <comment xml:lang="de">EPS-Bild (gzip-komprimiert)</comment>
+ <comment xml:lang="da">EPS-billede (gzip-komprimeret)</comment>
+ <comment xml:lang="cs">obrázek EPS (komprimovaný pomocí gzip)</comment>
+ <comment xml:lang="ca">imatge EPS (amb compressió gzip)</comment>
+ <comment xml:lang="bg">Изображение — EPS, компресирано с gzip</comment>
+ <comment xml:lang="be@latin">Vyjava EPS (gzip-skampresavanaja)</comment>
+ <comment xml:lang="be">выява EPS (сцісканне gzip)</comment>
+ <comment xml:lang="ar">صورة EPS (مضغوط-gzip)</comment>
+ <comment xml:lang="af">EPS-beeld (gzip-saamgepers)</comment>
<sub-class-of type="application/gzip"/>
<glob pattern="*.eps.gz"/>
<glob pattern="*.epsi.gz"/>
@@ -28325,41 +30893,54 @@
</mime-type>
<mime-type type="image/vnd.microsoft.icon">
<comment>Windows icon</comment>
- <comment xml:lang="ca">icona de Windows</comment>
- <comment xml:lang="cs">ikona Windows</comment>
- <comment xml:lang="da">Windows-ikon</comment>
- <comment xml:lang="de">Windows-Symbol</comment>
- <comment xml:lang="el">Εικονίδιο Windows</comment>
- <comment xml:lang="en_GB">Windows icon</comment>
- <comment xml:lang="es">icono de Windows</comment>
- <comment xml:lang="eu">Windows ikonoa</comment>
- <comment xml:lang="fi">Windows-kuvake</comment>
- <comment xml:lang="fr">icône Windows</comment>
- <comment xml:lang="ga">deilbhín Windows</comment>
- <comment xml:lang="he">סמל של Windows</comment>
- <comment xml:lang="hr">Windows ikona</comment>
- <comment xml:lang="hu">Windows ikon</comment>
- <comment xml:lang="ia">Icone pro Windows</comment>
- <comment xml:lang="id">Ikon Windows</comment>
- <comment xml:lang="it">Icona Windows</comment>
- <comment xml:lang="kk">Windows таңбашасы</comment>
- <comment xml:lang="ko">윈도우 아이콘</comment>
- <comment xml:lang="oc">icòna Windows</comment>
- <comment xml:lang="pl">Ikona Windows</comment>
- <comment xml:lang="pt">ícone Windows</comment>
- <comment xml:lang="pt_BR">Ícone do Windows</comment>
- <comment xml:lang="ru">Значок Windows</comment>
- <comment xml:lang="sk">Ikona Windows</comment>
- <comment xml:lang="sl">Ikona Windows</comment>
- <comment xml:lang="sr">Иконица Виндоуза</comment>
- <comment xml:lang="sv">Windows-ikon</comment>
- <comment xml:lang="tr">Windows simgesi</comment>
- <comment xml:lang="uk">піктограма Windows</comment>
- <comment xml:lang="zh_CN">Windows 图标</comment>
<comment xml:lang="zh_TW">Windows 圖示</comment>
- <magic priority="50">
- <match value="\0\0\1\0" type="string" offset="0">
- <match value="\0" type="string" offset="5"/>
+ <comment xml:lang="zh_CN">Windows 图标</comment>
+ <comment xml:lang="uk">піктограма Windows</comment>
+ <comment xml:lang="tr">Windows simgesi</comment>
+ <comment xml:lang="sv">Windows-ikon</comment>
+ <comment xml:lang="sr">Иконица Виндоуза</comment>
+ <comment xml:lang="sq">ikonë Windows</comment>
+ <comment xml:lang="sl">Ikona Windows</comment>
+ <comment xml:lang="si">වින්ඩෝස් නිරූපකය</comment>
+ <comment xml:lang="sk">Ikona Windows</comment>
+ <comment xml:lang="ru">Значок Windows</comment>
+ <comment xml:lang="pt_BR">Ícone do Windows</comment>
+ <comment xml:lang="pt">ícone Windows</comment>
+ <comment xml:lang="pl">Ikona Windows</comment>
+ <comment xml:lang="oc">icòna Windows</comment>
+ <comment xml:lang="nl">Windows-pictogram</comment>
+ <comment xml:lang="lt">Windows piktograma</comment>
+ <comment xml:lang="ko">Windows 아이콘</comment>
+ <comment xml:lang="kk">Windows таңбашасы</comment>
+ <comment xml:lang="ka">Windows icon</comment>
+ <comment xml:lang="ja">Windows アイコン</comment>
+ <comment xml:lang="it">Icona Windows</comment>
+ <comment xml:lang="is">Windows táknmynd</comment>
+ <comment xml:lang="id">Ikon Windows</comment>
+ <comment xml:lang="ia">Icone pro Windows</comment>
+ <comment xml:lang="hu">Windows ikon</comment>
+ <comment xml:lang="hr">Windows ikona</comment>
+ <comment xml:lang="he">סמל של Windows</comment>
+ <comment xml:lang="gl">Icona de Windows</comment>
+ <comment xml:lang="ga">deilbhín Windows</comment>
+ <comment xml:lang="fur">icone Windows</comment>
+ <comment xml:lang="fr">icône Windows</comment>
+ <comment xml:lang="fi">Windows-kuvake</comment>
+ <comment xml:lang="eu">Windows ikonoa</comment>
+ <comment xml:lang="es">icono de Windows</comment>
+ <comment xml:lang="en_GB">Windows icon</comment>
+ <comment xml:lang="el">Εικονίδιο Windows</comment>
+ <comment xml:lang="de">Windows-Symbol</comment>
+ <comment xml:lang="da">Windows-ikon</comment>
+ <comment xml:lang="cs">ikona Windows</comment>
+ <comment xml:lang="ca">icona de Windows</comment>
+ <comment xml:lang="bg">Икона — Windows</comment>
+ <comment xml:lang="be">значок Windows</comment>
+ <comment xml:lang="ar">أيقونة ويندوز</comment>
+ <comment xml:lang="af">Windows-ikoon</comment>
+ <magic>
+ <match type="string" value="\0\0\1\0" offset="0">
+ <match type="string" value="\0" offset="5"/>
</match>
</magic>
<glob pattern="*.ico"/>
@@ -28372,115 +30953,125 @@
</mime-type>
<mime-type type="image/x-icns">
<comment>MacOS X icon</comment>
- <comment xml:lang="ar">أيقونة MacOS X</comment>
- <comment xml:lang="be@latin">Ikona MacOS X</comment>
- <comment xml:lang="bg">Икона — MacOS X</comment>
- <comment xml:lang="ca">icona MacOS X</comment>
- <comment xml:lang="cs">ikona MacOS X</comment>
- <comment xml:lang="da">MacOS X-ikon</comment>
- <comment xml:lang="de">MacOS-X-Symbol</comment>
- <comment xml:lang="el">Εικονίδιο MacOS X</comment>
- <comment xml:lang="en_GB">MacOS X icon</comment>
- <comment xml:lang="eo">MacOS-X-piktogramo</comment>
- <comment xml:lang="es">icono de OS X</comment>
- <comment xml:lang="eu">MacOS X ikonoa</comment>
- <comment xml:lang="fi">MacOS X -kuvake</comment>
- <comment xml:lang="fo">MacOS X ímynd</comment>
- <comment xml:lang="fr">icône MacOS X</comment>
- <comment xml:lang="ga">deilbhín MacOS X</comment>
- <comment xml:lang="gl">Icona de MacOS X</comment>
- <comment xml:lang="he">סמל בתקן MacOS X</comment>
- <comment xml:lang="hr">MacOS X ikona</comment>
- <comment xml:lang="hu">MacOS X ikon</comment>
- <comment xml:lang="ia">Icone de Mac OS X</comment>
- <comment xml:lang="id">Ikon MacOS X</comment>
- <comment xml:lang="it">Icona MacOS X</comment>
- <comment xml:lang="ja">MacOS X アイコン</comment>
- <comment xml:lang="ka">MacOS X-ის ხატულა</comment>
- <comment xml:lang="kk">MacOS X таңбашасы</comment>
- <comment xml:lang="ko">Mac OS X 아이콘</comment>
- <comment xml:lang="lt">MacOS X piktograma</comment>
- <comment xml:lang="lv">MacOS X ikona</comment>
- <comment xml:lang="nb">MacOS X-ikon</comment>
- <comment xml:lang="nl">MacOS-X-pictogram</comment>
- <comment xml:lang="nn">MacOS X-ikon</comment>
- <comment xml:lang="oc">icòna MacOS X</comment>
- <comment xml:lang="pl">Ikona Mac OS X</comment>
- <comment xml:lang="pt">ćone MacOS X</comment>
- <comment xml:lang="pt_BR">Ícone do MacOS X</comment>
- <comment xml:lang="ro">Iconiță MacOS X</comment>
- <comment xml:lang="ru">Значок MacOS X</comment>
- <comment xml:lang="sk">Ikona MacOS X</comment>
- <comment xml:lang="sl">Datoteka ikone MacOS X</comment>
- <comment xml:lang="sq">Ikonë MacOS X</comment>
- <comment xml:lang="sr">МекОС Икс иконица</comment>
- <comment xml:lang="sv">MacOS X-ikon</comment>
- <comment xml:lang="tr">MacOS X simgesi</comment>
- <comment xml:lang="uk">піктограма MacOS X</comment>
- <comment xml:lang="vi">Biểu tượng MacOS X</comment>
- <comment xml:lang="zh_CN">MacOS X 图标</comment>
<comment xml:lang="zh_TW">MacOS X 圖示</comment>
+ <comment xml:lang="zh_CN">MacOS X 图标</comment>
+ <comment xml:lang="vi">Biểu tượng MacOS X</comment>
+ <comment xml:lang="uk">піктограма MacOS X</comment>
+ <comment xml:lang="tr">MacOS X simgesi</comment>
+ <comment xml:lang="sv">MacOS X-ikon</comment>
+ <comment xml:lang="sr">МекОС Икс иконица</comment>
+ <comment xml:lang="sq">ikonë MacOS X</comment>
+ <comment xml:lang="sl">Datoteka ikone MacOS X</comment>
+ <comment xml:lang="si">MacOS X නිරූපකය</comment>
+ <comment xml:lang="sk">Ikona MacOS X</comment>
+ <comment xml:lang="ru">Значок MacOS X</comment>
+ <comment xml:lang="ro">Iconiță MacOS X</comment>
+ <comment xml:lang="pt_BR">Ícone do MacOS X</comment>
+ <comment xml:lang="pt">ícone MacOS X</comment>
+ <comment xml:lang="pl">Ikona Mac OS X</comment>
+ <comment xml:lang="oc">icòna MacOS X</comment>
+ <comment xml:lang="nn">MacOS X-ikon</comment>
+ <comment xml:lang="nl">MacOS-X-pictogram</comment>
+ <comment xml:lang="nb">MacOS X-ikon</comment>
+ <comment xml:lang="lv">MacOS X ikona</comment>
+ <comment xml:lang="lt">MacOS X piktograma</comment>
+ <comment xml:lang="ko">Mac OS X 아이콘</comment>
+ <comment xml:lang="kk">MacOS X таңбашасы</comment>
+ <comment xml:lang="ka">MacOS X-ის ხატულა</comment>
+ <comment xml:lang="ja">MacOS X アイコン</comment>
+ <comment xml:lang="it">Icona MacOS X</comment>
+ <comment xml:lang="is">MacOS X táknmynd</comment>
+ <comment xml:lang="id">Ikon MacOS X</comment>
+ <comment xml:lang="ia">Icone de Mac OS X</comment>
+ <comment xml:lang="hu">MacOS X ikon</comment>
+ <comment xml:lang="hr">MacOS X ikona</comment>
+ <comment xml:lang="he">סמל בתקן MacOS X</comment>
+ <comment xml:lang="gl">Icona de MacOS X</comment>
+ <comment xml:lang="ga">deilbhín MacOS X</comment>
+ <comment xml:lang="fur">icone MacOS X</comment>
+ <comment xml:lang="fr">icône MacOS X</comment>
+ <comment xml:lang="fo">MacOS X ímynd</comment>
+ <comment xml:lang="fi">MacOS X -kuvake</comment>
+ <comment xml:lang="eu">MacOS X ikonoa</comment>
+ <comment xml:lang="es">icono de OS X</comment>
+ <comment xml:lang="eo">MacOS-X-piktogramo</comment>
+ <comment xml:lang="en_GB">MacOS X icon</comment>
+ <comment xml:lang="el">Εικονίδιο MacOS X</comment>
+ <comment xml:lang="de">MacOS-X-Symbol</comment>
+ <comment xml:lang="da">MacOS X-ikon</comment>
+ <comment xml:lang="cs">ikona MacOS X</comment>
+ <comment xml:lang="ca">icona MacOS X</comment>
+ <comment xml:lang="bg">Икона — MacOS X</comment>
+ <comment xml:lang="be@latin">Ikona MacOS X</comment>
+ <comment xml:lang="be">значок MacOS X</comment>
+ <comment xml:lang="ar">أيقونة MacOS X</comment>
+ <comment xml:lang="af">MacOS X-ikoon</comment>
<glob pattern="*.icns"/>
- <magic priority="50">
- <match value="icns" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="icns" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/x-ilbm">
<comment>ILBM image</comment>
- <comment xml:lang="ar">صورة ILBM</comment>
- <comment xml:lang="az">ILBM rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava ILBM</comment>
- <comment xml:lang="bg">Изображение — ILBM</comment>
- <comment xml:lang="ca">imatge ILBM</comment>
- <comment xml:lang="cs">obrázek ILMB</comment>
- <comment xml:lang="cy">Delwedd ILBM</comment>
- <comment xml:lang="da">ILBM-billede</comment>
- <comment xml:lang="de">ILBM-Bild</comment>
- <comment xml:lang="el">Εικόνα ILBM</comment>
- <comment xml:lang="en_GB">ILBM image</comment>
- <comment xml:lang="eo">ILBM-bildo</comment>
- <comment xml:lang="es">imagen ILBM</comment>
- <comment xml:lang="eu">ILBM irudia</comment>
- <comment xml:lang="fi">ILBM-kuva</comment>
- <comment xml:lang="fo">ILBM mynd</comment>
- <comment xml:lang="fr">image ILBM</comment>
- <comment xml:lang="ga">íomhá ILBM</comment>
- <comment xml:lang="gl">imaxe ILBM</comment>
- <comment xml:lang="he">תמונת ILBM</comment>
- <comment xml:lang="hr">ILBM slika</comment>
- <comment xml:lang="hu">ILBM-kép</comment>
- <comment xml:lang="ia">Imagine ILBM</comment>
- <comment xml:lang="id">Citra ILBM</comment>
- <comment xml:lang="it">Immagine ILBM</comment>
- <comment xml:lang="ja">ILBM 画像</comment>
- <comment xml:lang="kk">ILBM суреті</comment>
- <comment xml:lang="ko">ILBM 그림</comment>
- <comment xml:lang="lt">ILBM paveikslėlis</comment>
- <comment xml:lang="lv">ILBM attēls</comment>
- <comment xml:lang="ms">Imej ILBM</comment>
- <comment xml:lang="nb">ILBM-bilde</comment>
- <comment xml:lang="nl">ILBM-afbeelding</comment>
- <comment xml:lang="nn">ILMB-bilete</comment>
- <comment xml:lang="oc">imatge ILBM</comment>
- <comment xml:lang="pl">Obraz ILBM</comment>
- <comment xml:lang="pt">imagem ILBM</comment>
- <comment xml:lang="pt_BR">Imagem ILBM</comment>
- <comment xml:lang="ro">Imagine ILBM</comment>
- <comment xml:lang="ru">Изображение ILBM</comment>
- <comment xml:lang="sk">Obrázok ILMB</comment>
- <comment xml:lang="sl">Slikovna datoteka ILBM</comment>
- <comment xml:lang="sq">Figurë ILBM</comment>
- <comment xml:lang="sr">ИЛБМ слика</comment>
- <comment xml:lang="sv">ILBM-bild</comment>
- <comment xml:lang="tr">ILBM görüntüsü</comment>
- <comment xml:lang="uk">зображення ILBM</comment>
- <comment xml:lang="vi">Ảnh ILBM</comment>
- <comment xml:lang="zh_CN">ILBM 图像</comment>
<comment xml:lang="zh_TW">ILBM 影像</comment>
+ <comment xml:lang="zh_CN">ILBM 图像</comment>
+ <comment xml:lang="vi">Ảnh ILBM</comment>
+ <comment xml:lang="uk">зображення ILBM</comment>
+ <comment xml:lang="tr">ILBM görüntüsü</comment>
+ <comment xml:lang="sv">ILBM-bild</comment>
+ <comment xml:lang="sr">ИЛБМ слика</comment>
+ <comment xml:lang="sq">figurë ILBM</comment>
+ <comment xml:lang="sl">Slikovna datoteka ILBM</comment>
+ <comment xml:lang="si">ILBM රූපය</comment>
+ <comment xml:lang="sk">Obrázok ILMB</comment>
+ <comment xml:lang="ru">Изображение ILBM</comment>
+ <comment xml:lang="ro">Imagine ILBM</comment>
+ <comment xml:lang="pt_BR">Imagem ILBM</comment>
+ <comment xml:lang="pt">imagem ILBM</comment>
+ <comment xml:lang="pl">Obraz ILBM</comment>
+ <comment xml:lang="oc">imatge ILBM</comment>
+ <comment xml:lang="nn">ILMB-bilete</comment>
+ <comment xml:lang="nl">ILBM-afbeelding</comment>
+ <comment xml:lang="nb">ILBM-bilde</comment>
+ <comment xml:lang="ms">Imej ILBM</comment>
+ <comment xml:lang="lv">ILBM attēls</comment>
+ <comment xml:lang="lt">ILBM paveikslėlis</comment>
+ <comment xml:lang="ko">ILBM 그림</comment>
+ <comment xml:lang="kk">ILBM суреті</comment>
+ <comment xml:lang="ja">ILBM 画像</comment>
+ <comment xml:lang="it">Immagine ILBM</comment>
+ <comment xml:lang="is">ILBM mynd</comment>
+ <comment xml:lang="id">Citra ILBM</comment>
+ <comment xml:lang="ia">Imagine ILBM</comment>
+ <comment xml:lang="hu">ILBM-kép</comment>
+ <comment xml:lang="hr">ILBM slika</comment>
+ <comment xml:lang="he">תמונת ILBM</comment>
+ <comment xml:lang="gl">imaxe ILBM</comment>
+ <comment xml:lang="ga">íomhá ILBM</comment>
+ <comment xml:lang="fur">imagjin ILBM</comment>
+ <comment xml:lang="fr">image ILBM</comment>
+ <comment xml:lang="fo">ILBM mynd</comment>
+ <comment xml:lang="fi">ILBM-kuva</comment>
+ <comment xml:lang="eu">ILBM irudia</comment>
+ <comment xml:lang="es">imagen ILBM</comment>
+ <comment xml:lang="eo">ILBM-bildo</comment>
+ <comment xml:lang="en_GB">ILBM image</comment>
+ <comment xml:lang="el">Εικόνα ILBM</comment>
+ <comment xml:lang="de">ILBM-Bild</comment>
+ <comment xml:lang="da">ILBM-billede</comment>
+ <comment xml:lang="cy">Delwedd ILBM</comment>
+ <comment xml:lang="cs">obrázek ILMB</comment>
+ <comment xml:lang="ca">imatge ILBM</comment>
+ <comment xml:lang="bg">Изображение — ILBM</comment>
+ <comment xml:lang="be@latin">Vyjava ILBM</comment>
+ <comment xml:lang="be">выява ILBM</comment>
+ <comment xml:lang="az">ILBM rəsmi</comment>
+ <comment xml:lang="ar">صورة ILBM</comment>
+ <comment xml:lang="af">ILBM-beeld</comment>
<acronym>ILBM</acronym>
<expanded-acronym>InterLeaved BitMap</expanded-acronym>
<sub-class-of type="application/x-iff"/>
- <magic priority="50">
+ <magic>
<match value="ILBM" type="string" offset="8"/>
<match value="PBM " type="string" offset="8"/>
</magic>
@@ -28491,379 +31082,416 @@
</mime-type>
<mime-type type="image/x-jng">
<comment>JNG image</comment>
- <comment xml:lang="ar">صورة JNG</comment>
- <comment xml:lang="az">JNG rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava JNG</comment>
- <comment xml:lang="bg">Изображение — JNG</comment>
- <comment xml:lang="ca">imatge JNG</comment>
- <comment xml:lang="cs">obrázek JNG</comment>
- <comment xml:lang="cy">Delwedd JNG</comment>
- <comment xml:lang="da">JNG-billede</comment>
- <comment xml:lang="de">JNG-Bild</comment>
- <comment xml:lang="el">Εικόνα JNG</comment>
- <comment xml:lang="en_GB">JNG image</comment>
- <comment xml:lang="eo">JNG-bildo</comment>
- <comment xml:lang="es">imagen JNG</comment>
- <comment xml:lang="eu">JNG irudia</comment>
- <comment xml:lang="fi">JNG-kuva</comment>
- <comment xml:lang="fo">JNG mynd</comment>
- <comment xml:lang="fr">image JNG</comment>
- <comment xml:lang="ga">íomhá JNG</comment>
- <comment xml:lang="gl">imaxe JNG</comment>
- <comment xml:lang="he">תמונת JNG</comment>
- <comment xml:lang="hr">JNG slika</comment>
- <comment xml:lang="hu">JNG-kép</comment>
- <comment xml:lang="ia">Imagine JNG</comment>
- <comment xml:lang="id">Citra JNG</comment>
- <comment xml:lang="it">Immagine JNG</comment>
- <comment xml:lang="ja">JNG 画像</comment>
- <comment xml:lang="kk">JNG суреті</comment>
- <comment xml:lang="ko">JNG 그림</comment>
- <comment xml:lang="lt">JNG paveikslėlis</comment>
- <comment xml:lang="lv">JNG attēls</comment>
- <comment xml:lang="ms">Imej PNG</comment>
- <comment xml:lang="nb">JNG-bilde</comment>
- <comment xml:lang="nl">JNG-afbeelding</comment>
- <comment xml:lang="nn">JNG-bilete</comment>
- <comment xml:lang="oc">imatge JNG</comment>
- <comment xml:lang="pl">Obraz JNG</comment>
- <comment xml:lang="pt">imagem JNG</comment>
- <comment xml:lang="pt_BR">Imagem JNG</comment>
- <comment xml:lang="ro">Imagine JNG</comment>
- <comment xml:lang="ru">Изображение JNG</comment>
- <comment xml:lang="sk">Obrázok JNG</comment>
- <comment xml:lang="sl">Slikovna datoteka JNG</comment>
- <comment xml:lang="sq">Figurë JNG</comment>
- <comment xml:lang="sr">ЈНГ слика</comment>
- <comment xml:lang="sv">JNG-bild</comment>
- <comment xml:lang="tr">JNG görüntüsü</comment>
- <comment xml:lang="uk">зображення JNG</comment>
- <comment xml:lang="vi">Ảnh JNG</comment>
- <comment xml:lang="zh_CN">JNG 图像</comment>
<comment xml:lang="zh_TW">JNG 影像</comment>
+ <comment xml:lang="zh_CN">JNG 图像</comment>
+ <comment xml:lang="vi">Ảnh JNG</comment>
+ <comment xml:lang="uk">зображення JNG</comment>
+ <comment xml:lang="tr">JNG görüntüsü</comment>
+ <comment xml:lang="sv">JNG-bild</comment>
+ <comment xml:lang="sr">ЈНГ слика</comment>
+ <comment xml:lang="sq">figurë JNG</comment>
+ <comment xml:lang="sl">Slikovna datoteka JNG</comment>
+ <comment xml:lang="si">JNG රූපය</comment>
+ <comment xml:lang="sk">Obrázok JNG</comment>
+ <comment xml:lang="ru">Изображение JNG</comment>
+ <comment xml:lang="ro">Imagine JNG</comment>
+ <comment xml:lang="pt_BR">Imagem JNG</comment>
+ <comment xml:lang="pt">imagem JNG</comment>
+ <comment xml:lang="pl">Obraz JNG</comment>
+ <comment xml:lang="oc">imatge JNG</comment>
+ <comment xml:lang="nn">JNG-bilete</comment>
+ <comment xml:lang="nl">JNG-afbeelding</comment>
+ <comment xml:lang="nb">JNG-bilde</comment>
+ <comment xml:lang="ms">Imej PNG</comment>
+ <comment xml:lang="lv">JNG attēls</comment>
+ <comment xml:lang="lt">JNG paveikslėlis</comment>
+ <comment xml:lang="ko">JNG 그림</comment>
+ <comment xml:lang="kk">JNG суреті</comment>
+ <comment xml:lang="ja">JNG 画像</comment>
+ <comment xml:lang="it">Immagine JNG</comment>
+ <comment xml:lang="is">JNG mynd</comment>
+ <comment xml:lang="id">Citra JNG</comment>
+ <comment xml:lang="ia">Imagine JNG</comment>
+ <comment xml:lang="hu">JNG-kép</comment>
+ <comment xml:lang="hr">JNG slika</comment>
+ <comment xml:lang="he">תמונת JNG</comment>
+ <comment xml:lang="gl">imaxe JNG</comment>
+ <comment xml:lang="ga">íomhá JNG</comment>
+ <comment xml:lang="fur">imagjin JNG</comment>
+ <comment xml:lang="fr">image JNG</comment>
+ <comment xml:lang="fo">JNG mynd</comment>
+ <comment xml:lang="fi">JNG-kuva</comment>
+ <comment xml:lang="eu">JNG irudia</comment>
+ <comment xml:lang="es">imagen JNG</comment>
+ <comment xml:lang="eo">JNG-bildo</comment>
+ <comment xml:lang="en_GB">JNG image</comment>
+ <comment xml:lang="el">Εικόνα JNG</comment>
+ <comment xml:lang="de">JNG-Bild</comment>
+ <comment xml:lang="da">JNG-billede</comment>
+ <comment xml:lang="cy">Delwedd JNG</comment>
+ <comment xml:lang="cs">obrázek JNG</comment>
+ <comment xml:lang="ca">imatge JNG</comment>
+ <comment xml:lang="bg">Изображение — JNG</comment>
+ <comment xml:lang="be@latin">Vyjava JNG</comment>
+ <comment xml:lang="be">выява JNG</comment>
+ <comment xml:lang="az">JNG rəsmi</comment>
+ <comment xml:lang="ar">صورة JNG</comment>
+ <comment xml:lang="af">JNG-beeld</comment>
<acronym>JNG</acronym>
<expanded-acronym>JPEG Network Graphics</expanded-acronym>
<glob pattern="*.jng"/>
</mime-type>
<mime-type type="image/x-lwo">
<comment>LightWave object</comment>
- <comment xml:lang="ar">كائن LightWave</comment>
- <comment xml:lang="az">LightWave cismi</comment>
- <comment xml:lang="be@latin">Abjekt LightWave</comment>
- <comment xml:lang="bg">Обект — LightWave</comment>
- <comment xml:lang="ca">objecte de LightWave</comment>
- <comment xml:lang="cs">objekt LightWave</comment>
- <comment xml:lang="cy">Gwrthrych LightWave</comment>
- <comment xml:lang="da">LightWave-objekt</comment>
- <comment xml:lang="de">LightWave-Objekt</comment>
- <comment xml:lang="el">Αντικείμενο LightWave</comment>
- <comment xml:lang="en_GB">LightWave object</comment>
- <comment xml:lang="eo">LightWave-objekto</comment>
- <comment xml:lang="es">objeto de LightWave</comment>
- <comment xml:lang="eu">LightWave objektua</comment>
- <comment xml:lang="fi">LightWave-esine</comment>
- <comment xml:lang="fo">LightWave lutur</comment>
- <comment xml:lang="fr">objet LightWave</comment>
- <comment xml:lang="ga">réad LightWave</comment>
- <comment xml:lang="gl">obxecto de LightWave</comment>
- <comment xml:lang="he">עצם LightWave</comment>
- <comment xml:lang="hr">LightWave objekt</comment>
- <comment xml:lang="hu">LightWave-objektum</comment>
- <comment xml:lang="ia">Objecto LightWave</comment>
- <comment xml:lang="id">Proyek LightWave</comment>
- <comment xml:lang="it">Oggetto LightWave</comment>
- <comment xml:lang="ja">LightWave オブジェクト</comment>
- <comment xml:lang="kk">LightWave объекті</comment>
- <comment xml:lang="ko">LightWave 개체</comment>
- <comment xml:lang="lt">LightWave objektas</comment>
- <comment xml:lang="lv">LightWave objekts</comment>
- <comment xml:lang="ms">Objek LightWave</comment>
- <comment xml:lang="nb">LightWave-objekt</comment>
- <comment xml:lang="nl">LightWave-object</comment>
- <comment xml:lang="nn">LightWave-objekt</comment>
- <comment xml:lang="oc">objècte LightWave</comment>
- <comment xml:lang="pl">Obiekt LightWave</comment>
- <comment xml:lang="pt">Objecto LightWave</comment>
- <comment xml:lang="pt_BR">Objeto LightWave</comment>
- <comment xml:lang="ro">Obiect LightWave</comment>
- <comment xml:lang="ru">Объект LightWave</comment>
- <comment xml:lang="sk">Objekt LightWave</comment>
- <comment xml:lang="sl">Datoteka predmeta LightWave</comment>
- <comment xml:lang="sq">Objekt LightWave</comment>
- <comment xml:lang="sr">Лајт Вејв објекат</comment>
- <comment xml:lang="sv">LightWave-objekt</comment>
- <comment xml:lang="tr">LightWave nesnesi</comment>
- <comment xml:lang="uk">об'єкт LightWave</comment>
- <comment xml:lang="vi">Đối tượng LightWave</comment>
- <comment xml:lang="zh_CN">LightWave 对象</comment>
<comment xml:lang="zh_TW">LightWave 物件</comment>
+ <comment xml:lang="zh_CN">LightWave 对象</comment>
+ <comment xml:lang="vi">Đối tượng LightWave</comment>
+ <comment xml:lang="uk">об'єкт LightWave</comment>
+ <comment xml:lang="tr">LightWave nesnesi</comment>
+ <comment xml:lang="sv">LightWave-objekt</comment>
+ <comment xml:lang="sr">Лајт Вејв објекат</comment>
+ <comment xml:lang="sq">objekt LightWave</comment>
+ <comment xml:lang="sl">Datoteka predmeta LightWave</comment>
+ <comment xml:lang="si">LightWave වස්තුව</comment>
+ <comment xml:lang="sk">Objekt LightWave</comment>
+ <comment xml:lang="ru">Объект LightWave</comment>
+ <comment xml:lang="ro">Obiect LightWave</comment>
+ <comment xml:lang="pt_BR">Objeto LightWave</comment>
+ <comment xml:lang="pt">Objecto LightWave</comment>
+ <comment xml:lang="pl">Obiekt LightWave</comment>
+ <comment xml:lang="oc">objècte LightWave</comment>
+ <comment xml:lang="nn">LightWave-objekt</comment>
+ <comment xml:lang="nl">LightWave-object</comment>
+ <comment xml:lang="nb">LightWave-objekt</comment>
+ <comment xml:lang="ms">Objek LightWave</comment>
+ <comment xml:lang="lv">LightWave objekts</comment>
+ <comment xml:lang="lt">LightWave objektas</comment>
+ <comment xml:lang="ko">LightWave 개체</comment>
+ <comment xml:lang="kk">LightWave объекті</comment>
+ <comment xml:lang="ja">LightWave オブジェクト</comment>
+ <comment xml:lang="it">Oggetto LightWave</comment>
+ <comment xml:lang="is">LightWave hlutur</comment>
+ <comment xml:lang="id">Proyek LightWave</comment>
+ <comment xml:lang="ia">Objecto LightWave</comment>
+ <comment xml:lang="hu">LightWave-objektum</comment>
+ <comment xml:lang="hr">LightWave objekt</comment>
+ <comment xml:lang="he">עצם LightWave</comment>
+ <comment xml:lang="gl">obxecto de LightWave</comment>
+ <comment xml:lang="ga">réad LightWave</comment>
+ <comment xml:lang="fur">ogjet LightWave</comment>
+ <comment xml:lang="fr">objet LightWave</comment>
+ <comment xml:lang="fo">LightWave lutur</comment>
+ <comment xml:lang="fi">LightWave-esine</comment>
+ <comment xml:lang="eu">LightWave objektua</comment>
+ <comment xml:lang="es">objeto de LightWave</comment>
+ <comment xml:lang="eo">LightWave-objekto</comment>
+ <comment xml:lang="en_GB">LightWave object</comment>
+ <comment xml:lang="el">Αντικείμενο LightWave</comment>
+ <comment xml:lang="de">LightWave-Objekt</comment>
+ <comment xml:lang="da">LightWave-objekt</comment>
+ <comment xml:lang="cy">Gwrthrych LightWave</comment>
+ <comment xml:lang="cs">objekt LightWave</comment>
+ <comment xml:lang="ca">objecte de LightWave</comment>
+ <comment xml:lang="bg">Обект — LightWave</comment>
+ <comment xml:lang="be@latin">Abjekt LightWave</comment>
+ <comment xml:lang="be">аб'ект LightWave</comment>
+ <comment xml:lang="az">LightWave cismi</comment>
+ <comment xml:lang="ar">كائن LightWave</comment>
+ <comment xml:lang="af">LightWave-objek</comment>
<glob pattern="*.lwo"/>
<glob pattern="*.lwob"/>
</mime-type>
<mime-type type="image/x-lws">
<comment>LightWave scene</comment>
- <comment xml:lang="ar">مشهد LightWave</comment>
- <comment xml:lang="az">LightWave səhnəsi</comment>
- <comment xml:lang="be@latin">Scena LightWave</comment>
- <comment xml:lang="bg">Сцена — LightWave</comment>
- <comment xml:lang="ca">escena de LightWave</comment>
- <comment xml:lang="cs">scéna LightWave</comment>
- <comment xml:lang="cy">Golygfa LightWave</comment>
- <comment xml:lang="da">LightWave-scene</comment>
- <comment xml:lang="de">LightWave-Szene</comment>
- <comment xml:lang="el">Σκηνή LightWave</comment>
- <comment xml:lang="en_GB">LightWave scene</comment>
- <comment xml:lang="eo">LightWave-sceno</comment>
- <comment xml:lang="es">escena de LightWave</comment>
- <comment xml:lang="eu">LightWave eszena</comment>
- <comment xml:lang="fi">LightWave-maisema</comment>
- <comment xml:lang="fo">LightWave leikmynd</comment>
- <comment xml:lang="fr">scène LightWave</comment>
- <comment xml:lang="ga">radharc LightWave</comment>
- <comment xml:lang="gl">escena de LightWave</comment>
- <comment xml:lang="he">סצנה של LightWave</comment>
- <comment xml:lang="hr">LightWave scena</comment>
- <comment xml:lang="hu">LightWave-jelenet</comment>
- <comment xml:lang="ia">Scena LightWave</comment>
- <comment xml:lang="id">Scene LightWave</comment>
- <comment xml:lang="it">Scena LightWave</comment>
- <comment xml:lang="ja">LightWave シーン</comment>
- <comment xml:lang="kk">LightWave сахнасы</comment>
- <comment xml:lang="ko">LightWave 장면</comment>
- <comment xml:lang="lt">LightWave scena</comment>
- <comment xml:lang="lv">LightWave aina</comment>
- <comment xml:lang="ms">Babak LightWave</comment>
- <comment xml:lang="nb">LightWave-scene</comment>
- <comment xml:lang="nl">LightWave-scène</comment>
- <comment xml:lang="nn">LightWave-scene</comment>
- <comment xml:lang="oc">scèna LightWave</comment>
- <comment xml:lang="pl">Scena Lightwave</comment>
- <comment xml:lang="pt">cenário LightWave</comment>
- <comment xml:lang="pt_BR">Cena LightWave</comment>
- <comment xml:lang="ro">Scenă LightWave</comment>
- <comment xml:lang="ru">Сцена LightWave</comment>
- <comment xml:lang="sk">Scéna LightWave</comment>
- <comment xml:lang="sl">Datoteka scene LightWave</comment>
- <comment xml:lang="sq">Skenë LightWave</comment>
- <comment xml:lang="sr">Лајт Вејв сцена</comment>
- <comment xml:lang="sv">LightWave-scen</comment>
- <comment xml:lang="tr">LightWave sahnesi</comment>
- <comment xml:lang="uk">сцена LightWave</comment>
- <comment xml:lang="vi">Cảnh LightWave</comment>
- <comment xml:lang="zh_CN">LightWave 场景</comment>
<comment xml:lang="zh_TW">LightWave 場景</comment>
+ <comment xml:lang="zh_CN">LightWave 场景</comment>
+ <comment xml:lang="vi">Cảnh LightWave</comment>
+ <comment xml:lang="uk">сцена LightWave</comment>
+ <comment xml:lang="tr">LightWave sahnesi</comment>
+ <comment xml:lang="sv">LightWave-scen</comment>
+ <comment xml:lang="sr">Лајт Вејв сцена</comment>
+ <comment xml:lang="sq">skenë LightWave</comment>
+ <comment xml:lang="sl">Datoteka scene LightWave</comment>
+ <comment xml:lang="si">LightWave දර්ශනය</comment>
+ <comment xml:lang="sk">Scéna LightWave</comment>
+ <comment xml:lang="ru">Сцена LightWave</comment>
+ <comment xml:lang="ro">Scenă LightWave</comment>
+ <comment xml:lang="pt_BR">Cena LightWave</comment>
+ <comment xml:lang="pt">cenário LightWave</comment>
+ <comment xml:lang="pl">Scena Lightwave</comment>
+ <comment xml:lang="oc">scèna LightWave</comment>
+ <comment xml:lang="nn">LightWave-scene</comment>
+ <comment xml:lang="nl">LightWave-scène</comment>
+ <comment xml:lang="nb">LightWave-scene</comment>
+ <comment xml:lang="ms">Babak LightWave</comment>
+ <comment xml:lang="lv">LightWave aina</comment>
+ <comment xml:lang="lt">LightWave scena</comment>
+ <comment xml:lang="ko">LightWave 장면</comment>
+ <comment xml:lang="kk">LightWave сахнасы</comment>
+ <comment xml:lang="ja">LightWave シーン</comment>
+ <comment xml:lang="it">Scena LightWave</comment>
+ <comment xml:lang="is">LightWave sviðsmynd</comment>
+ <comment xml:lang="id">Scene LightWave</comment>
+ <comment xml:lang="ia">Scena LightWave</comment>
+ <comment xml:lang="hu">LightWave-jelenet</comment>
+ <comment xml:lang="hr">LightWave scena</comment>
+ <comment xml:lang="he">סצנה של LightWave</comment>
+ <comment xml:lang="gl">escena de LightWave</comment>
+ <comment xml:lang="ga">radharc LightWave</comment>
+ <comment xml:lang="fur">sene LightWave</comment>
+ <comment xml:lang="fr">scène LightWave</comment>
+ <comment xml:lang="fo">LightWave leikmynd</comment>
+ <comment xml:lang="fi">LightWave-maisema</comment>
+ <comment xml:lang="eu">LightWave eszena</comment>
+ <comment xml:lang="es">escena de LightWave</comment>
+ <comment xml:lang="eo">LightWave-sceno</comment>
+ <comment xml:lang="en_GB">LightWave scene</comment>
+ <comment xml:lang="el">Σκηνή LightWave</comment>
+ <comment xml:lang="de">LightWave-Szene</comment>
+ <comment xml:lang="da">LightWave-scene</comment>
+ <comment xml:lang="cy">Golygfa LightWave</comment>
+ <comment xml:lang="cs">scéna LightWave</comment>
+ <comment xml:lang="ca">escena de LightWave</comment>
+ <comment xml:lang="bg">Сцена — LightWave</comment>
+ <comment xml:lang="be@latin">Scena LightWave</comment>
+ <comment xml:lang="be">сцэна LightWave</comment>
+ <comment xml:lang="az">LightWave səhnəsi</comment>
+ <comment xml:lang="ar">مشهد LightWave</comment>
+ <comment xml:lang="af">LightWave-toneel</comment>
<glob pattern="*.lws"/>
</mime-type>
<mime-type type="image/x-macpaint">
<comment>MacPaint Bitmap image</comment>
- <comment xml:lang="ar">صورة MacPaint Bitmap</comment>
- <comment xml:lang="be@latin">Bitmapnaja vyjava MacPaint</comment>
- <comment xml:lang="bg">Изображение — MacPaint Bitmap</comment>
- <comment xml:lang="ca">imatge de mapa de bits MacPaint</comment>
- <comment xml:lang="cs">obrázek MacPaint Bitmap</comment>
- <comment xml:lang="da">MacPaint BitMap-billede</comment>
- <comment xml:lang="de">MacPaint-Bitmap-Datei</comment>
- <comment xml:lang="el">Εικόνα Bitmap MacPaint</comment>
- <comment xml:lang="en_GB">MacPaint Bitmap image</comment>
- <comment xml:lang="es">imagen de mapa de bits de MacPaint</comment>
- <comment xml:lang="eu">MacPaint Bitmap irudia</comment>
- <comment xml:lang="fi">MacPaint-bittikartta</comment>
- <comment xml:lang="fo">MacPaint Bitmap mynd</comment>
- <comment xml:lang="fr">image matricielle MacPaint</comment>
- <comment xml:lang="ga">íomhá ghiotánmhapach MacPaint</comment>
- <comment xml:lang="gl">imaxe de mapa de bits MacPaint</comment>
- <comment xml:lang="he">תמונת מפת-סיביות של MacPaint</comment>
- <comment xml:lang="hr">MacPaint Bitmap slika</comment>
- <comment xml:lang="hu">MacPaint bitkép</comment>
- <comment xml:lang="ia">Imagine bitmap de MacPaint</comment>
- <comment xml:lang="id">Citra MacPaint Bitmap</comment>
- <comment xml:lang="it">Immagine Bitmap MacPaint</comment>
- <comment xml:lang="ja">MacPaint ビットマップ画像</comment>
- <comment xml:lang="kk">MacPaint растрлық суреті</comment>
- <comment xml:lang="ko">MacPaint 비트맵 그림</comment>
- <comment xml:lang="lt">MacPaint rastrinis paveikslėlis</comment>
- <comment xml:lang="lv">MacPaint bitkartes attēls</comment>
- <comment xml:lang="nb">MacPaint Bitmap-bilde</comment>
- <comment xml:lang="nl">MacPaint-bitmap-afbeelding</comment>
- <comment xml:lang="nn">MacPaint punktbilete</comment>
- <comment xml:lang="oc">imatge matricial MacPaint</comment>
- <comment xml:lang="pl">Obraz bitmapowy MacPaint</comment>
- <comment xml:lang="pt">imagem MacPaint Bitmap</comment>
- <comment xml:lang="pt_BR">Imagem de bitmap do MacPaint</comment>
- <comment xml:lang="ro">Imagine MacPaint Bitmap</comment>
- <comment xml:lang="ru">Растровое изображение MacPaint</comment>
- <comment xml:lang="sk">Obrázok MacPaint Bitmap</comment>
- <comment xml:lang="sl">Slikovna bitna datoteka MacPaint</comment>
- <comment xml:lang="sq">Figurë BitMap MacPaint</comment>
- <comment xml:lang="sr">Мек Пеинт битмап слика</comment>
- <comment xml:lang="sv">MacPaint Bitmap-bild</comment>
- <comment xml:lang="tr">MacPaint bit eşlem görüntüsü</comment>
- <comment xml:lang="uk">растрове зображення MacPaint</comment>
- <comment xml:lang="vi">Ảnh mảng MacPaint</comment>
- <comment xml:lang="zh_CN">MacPaint 位图</comment>
<comment xml:lang="zh_TW">MacPaint 點陣影像</comment>
+ <comment xml:lang="zh_CN">MacPaint 位图</comment>
+ <comment xml:lang="vi">Ảnh mảng MacPaint</comment>
+ <comment xml:lang="uk">растрове зображення MacPaint</comment>
+ <comment xml:lang="tr">MacPaint bit eşlem görüntüsü</comment>
+ <comment xml:lang="sv">MacPaint Bitmap-bild</comment>
+ <comment xml:lang="sr">Мек Пеинт битмап слика</comment>
+ <comment xml:lang="sq">figurë BitMap MacPaint</comment>
+ <comment xml:lang="sl">Slikovna bitna datoteka MacPaint</comment>
+ <comment xml:lang="si">MacPaint Bitmap රූපය</comment>
+ <comment xml:lang="sk">Obrázok MacPaint Bitmap</comment>
+ <comment xml:lang="ru">Растровое изображение MacPaint</comment>
+ <comment xml:lang="ro">Imagine MacPaint Bitmap</comment>
+ <comment xml:lang="pt_BR">Imagem de bitmap do MacPaint</comment>
+ <comment xml:lang="pt">imagem MacPaint Bitmap</comment>
+ <comment xml:lang="pl">Obraz bitmapowy MacPaint</comment>
+ <comment xml:lang="oc">imatge matricial MacPaint</comment>
+ <comment xml:lang="nn">MacPaint punktbilete</comment>
+ <comment xml:lang="nl">MacPaint-bitmap-afbeelding</comment>
+ <comment xml:lang="nb">MacPaint Bitmap-bilde</comment>
+ <comment xml:lang="lv">MacPaint bitkartes attēls</comment>
+ <comment xml:lang="lt">MacPaint rastrinis paveikslėlis</comment>
+ <comment xml:lang="ko">MacPaint 비트맵 그림</comment>
+ <comment xml:lang="kk">MacPaint растрлық суреті</comment>
+ <comment xml:lang="ja">MacPaint ビットマップ画像</comment>
+ <comment xml:lang="it">Immagine Bitmap MacPaint</comment>
+ <comment xml:lang="is">MacPaint bitamynd</comment>
+ <comment xml:lang="id">Citra MacPaint Bitmap</comment>
+ <comment xml:lang="ia">Imagine bitmap de MacPaint</comment>
+ <comment xml:lang="hu">MacPaint bitkép</comment>
+ <comment xml:lang="hr">MacPaint Bitmap slika</comment>
+ <comment xml:lang="he">תמונת מפת-סיביות של MacPaint</comment>
+ <comment xml:lang="gl">imaxe de mapa de bits MacPaint</comment>
+ <comment xml:lang="ga">íomhá ghiotánmhapach MacPaint</comment>
+ <comment xml:lang="fur">imagjin bitmap MacPaint</comment>
+ <comment xml:lang="fr">image matricielle MacPaint</comment>
+ <comment xml:lang="fo">MacPaint Bitmap mynd</comment>
+ <comment xml:lang="fi">MacPaint-bittikartta</comment>
+ <comment xml:lang="eu">MacPaint Bitmap irudia</comment>
+ <comment xml:lang="es">imagen de mapa de bits de MacPaint</comment>
+ <comment xml:lang="en_GB">MacPaint Bitmap image</comment>
+ <comment xml:lang="el">Εικόνα Bitmap MacPaint</comment>
+ <comment xml:lang="de">MacPaint-Bitmap-Datei</comment>
+ <comment xml:lang="da">MacPaint BitMap-billede</comment>
+ <comment xml:lang="cs">obrázek MacPaint Bitmap</comment>
+ <comment xml:lang="ca">imatge de mapa de bits MacPaint</comment>
+ <comment xml:lang="bg">Изображение — MacPaint Bitmap</comment>
+ <comment xml:lang="be@latin">Bitmapnaja vyjava MacPaint</comment>
+ <comment xml:lang="be">растравая выява MacPaint</comment>
+ <comment xml:lang="ar">صورة MacPaint Bitmap</comment>
+ <comment xml:lang="af">MacPaint-roosterbeeld</comment>
<glob pattern="*.pntg"/>
</mime-type>
<mime-type type="image/x-msod">
<comment>Office drawing</comment>
- <comment xml:lang="ar">تصميم أوفيس</comment>
- <comment xml:lang="be@latin">Ofisny rysunak</comment>
- <comment xml:lang="bg">Чертеж — Office</comment>
- <comment xml:lang="ca">dibuix d'Office</comment>
- <comment xml:lang="cs">kresba Office</comment>
- <comment xml:lang="da">Officetegning</comment>
- <comment xml:lang="de">Office-Zeichnung</comment>
- <comment xml:lang="el">Σχέδιο Office</comment>
- <comment xml:lang="en_GB">Office drawing</comment>
- <comment xml:lang="es">dibujo de Office</comment>
- <comment xml:lang="eu">Office marrazkia</comment>
- <comment xml:lang="fi">Office-piirros</comment>
- <comment xml:lang="fo">Office tekning</comment>
- <comment xml:lang="fr">dessin Office</comment>
- <comment xml:lang="ga">líníocht Office</comment>
- <comment xml:lang="gl">debuxo de Office</comment>
- <comment xml:lang="he">ציור של Office</comment>
- <comment xml:lang="hr">Office crtež</comment>
- <comment xml:lang="hu">Office rajz</comment>
- <comment xml:lang="ia">Designo Office</comment>
- <comment xml:lang="id">Gambar Office</comment>
- <comment xml:lang="it">Disegno Office</comment>
- <comment xml:lang="ja">Office ドロー</comment>
- <comment xml:lang="kk">Office суреті</comment>
- <comment xml:lang="ko">오피스 그리기</comment>
- <comment xml:lang="lt">Office piešinys</comment>
- <comment xml:lang="lv">Office zīmējums</comment>
- <comment xml:lang="nb">Office-tegning</comment>
- <comment xml:lang="nl">Office-tekening</comment>
- <comment xml:lang="nn">Office-teikning</comment>
- <comment xml:lang="oc">dessenh Office</comment>
- <comment xml:lang="pl">Rysunek Office</comment>
- <comment xml:lang="pt">desenho Office</comment>
- <comment xml:lang="pt_BR">Desenho do Office</comment>
- <comment xml:lang="ro">Desen Office</comment>
- <comment xml:lang="ru">Рисунок Office</comment>
- <comment xml:lang="sk">Kresba Office</comment>
- <comment xml:lang="sl">Datoteka risbe Office</comment>
- <comment xml:lang="sq">Vizatim Office</comment>
- <comment xml:lang="sr">Канцеларијски цртеж</comment>
- <comment xml:lang="sv">Office-teckning</comment>
- <comment xml:lang="tr">Ofis çizimi</comment>
- <comment xml:lang="uk">малюнок Office</comment>
- <comment xml:lang="vi">Bản vẽ Office</comment>
- <comment xml:lang="zh_CN">Office 绘图</comment>
<comment xml:lang="zh_TW">Office 繪圖</comment>
+ <comment xml:lang="zh_CN">Office 绘图</comment>
+ <comment xml:lang="vi">Bản vẽ Office</comment>
+ <comment xml:lang="uk">малюнок Office</comment>
+ <comment xml:lang="tr">Ofis çizimi</comment>
+ <comment xml:lang="sv">Office-teckning</comment>
+ <comment xml:lang="sr">Канцеларијски цртеж</comment>
+ <comment xml:lang="sq">vizatim Office</comment>
+ <comment xml:lang="sl">Datoteka risbe Office</comment>
+ <comment xml:lang="si">කාර්යාල ඇඳීම</comment>
+ <comment xml:lang="sk">Kresba Office</comment>
+ <comment xml:lang="ru">Рисунок Office</comment>
+ <comment xml:lang="ro">Desen Office</comment>
+ <comment xml:lang="pt_BR">Desenho do Office</comment>
+ <comment xml:lang="pt">desenho Office</comment>
+ <comment xml:lang="pl">Rysunek Office</comment>
+ <comment xml:lang="oc">dessenh Office</comment>
+ <comment xml:lang="nn">Office-teikning</comment>
+ <comment xml:lang="nl">Office-tekening</comment>
+ <comment xml:lang="nb">Office-tegning</comment>
+ <comment xml:lang="lv">Office zīmējums</comment>
+ <comment xml:lang="lt">Office piešinys</comment>
+ <comment xml:lang="ko">오피스 그리기</comment>
+ <comment xml:lang="kk">Office суреті</comment>
+ <comment xml:lang="ja">Office ドロー</comment>
+ <comment xml:lang="it">Disegno Office</comment>
+ <comment xml:lang="is">Office teikning</comment>
+ <comment xml:lang="id">Gambar Office</comment>
+ <comment xml:lang="ia">Designo Office</comment>
+ <comment xml:lang="hu">Office rajz</comment>
+ <comment xml:lang="hr">Office crtež</comment>
+ <comment xml:lang="he">ציור של Office</comment>
+ <comment xml:lang="gl">debuxo de Office</comment>
+ <comment xml:lang="ga">líníocht Office</comment>
+ <comment xml:lang="fur">dissen di Office</comment>
+ <comment xml:lang="fr">dessin Office</comment>
+ <comment xml:lang="fo">Office tekning</comment>
+ <comment xml:lang="fi">Office-piirros</comment>
+ <comment xml:lang="eu">Office marrazkia</comment>
+ <comment xml:lang="es">dibujo de Office</comment>
+ <comment xml:lang="en_GB">Office drawing</comment>
+ <comment xml:lang="el">Σχέδιο Office</comment>
+ <comment xml:lang="de">Office-Zeichnung</comment>
+ <comment xml:lang="da">Officetegning</comment>
+ <comment xml:lang="cs">kresba Office</comment>
+ <comment xml:lang="ca">dibuix d'Office</comment>
+ <comment xml:lang="bg">Чертеж — Office</comment>
+ <comment xml:lang="be@latin">Ofisny rysunak</comment>
+ <comment xml:lang="be">рысунак Office</comment>
+ <comment xml:lang="ar">تصميم أوفيس</comment>
+ <comment xml:lang="af">Office-tekening</comment>
<glob pattern="*.msod"/>
</mime-type>
<mime-type type="image/x-niff">
<comment>NIFF image</comment>
- <comment xml:lang="ar">صورة NIFF</comment>
- <comment xml:lang="be@latin">Vyjava NIFF</comment>
- <comment xml:lang="bg">Изображение — NIFF</comment>
- <comment xml:lang="ca">imatge NIFF</comment>
- <comment xml:lang="cs">obrázek NIFF</comment>
- <comment xml:lang="da">NIFF-billede</comment>
- <comment xml:lang="de">NIFF-Bild</comment>
- <comment xml:lang="el">Εικόνα NIFF</comment>
- <comment xml:lang="en_GB">NIFF image</comment>
- <comment xml:lang="eo">NIFF-bildo</comment>
- <comment xml:lang="es">imagen NIFF</comment>
- <comment xml:lang="eu">NIFF irudia</comment>
- <comment xml:lang="fi">NIFF-kuva</comment>
- <comment xml:lang="fo">NIFF mynd</comment>
- <comment xml:lang="fr">image NIFF</comment>
- <comment xml:lang="ga">íomhá NIFF</comment>
- <comment xml:lang="gl">imaxe NIFF</comment>
- <comment xml:lang="he">תמונת NIFF</comment>
- <comment xml:lang="hr">NIFF slika</comment>
- <comment xml:lang="hu">NIFF kép</comment>
- <comment xml:lang="ia">Imagine NIFF</comment>
- <comment xml:lang="id">Citra NIFF</comment>
- <comment xml:lang="it">Immagine NIFF</comment>
- <comment xml:lang="ja">NIFF 画像</comment>
- <comment xml:lang="kk">NIFF суреті</comment>
- <comment xml:lang="ko">NIFF 그림</comment>
- <comment xml:lang="lt">NIFF paveikslėlis</comment>
- <comment xml:lang="lv">NIFF attēls</comment>
- <comment xml:lang="nb">NIFF-bilde</comment>
- <comment xml:lang="nl">NIFF-afbeelding</comment>
- <comment xml:lang="nn">NIFF-bilete</comment>
- <comment xml:lang="oc">imatge NIFF</comment>
- <comment xml:lang="pl">Obraz NIFF</comment>
- <comment xml:lang="pt">imagem NIFF</comment>
- <comment xml:lang="pt_BR">Imagem NIFF</comment>
- <comment xml:lang="ro">Imagine NIF</comment>
- <comment xml:lang="ru">Изображение NIFF</comment>
- <comment xml:lang="sk">Obrázok NIFF</comment>
- <comment xml:lang="sl">Slikovna datoteka NIFF</comment>
- <comment xml:lang="sq">Figurë NIFF</comment>
- <comment xml:lang="sr">НИФФ слика</comment>
- <comment xml:lang="sv">NIFF-bild</comment>
- <comment xml:lang="tr">NIFF görüntüsü</comment>
- <comment xml:lang="uk">зображення NIFF</comment>
- <comment xml:lang="vi">Ảnh NIFF</comment>
- <comment xml:lang="zh_CN">NIFF 图像</comment>
<comment xml:lang="zh_TW">NIFF 影像</comment>
+ <comment xml:lang="zh_CN">NIFF 图像</comment>
+ <comment xml:lang="vi">Ảnh NIFF</comment>
+ <comment xml:lang="uk">зображення NIFF</comment>
+ <comment xml:lang="tr">NIFF görüntüsü</comment>
+ <comment xml:lang="sv">NIFF-bild</comment>
+ <comment xml:lang="sr">НИФФ слика</comment>
+ <comment xml:lang="sq">figurë NIFF</comment>
+ <comment xml:lang="sl">Slikovna datoteka NIFF</comment>
+ <comment xml:lang="si">NIFF රූපය</comment>
+ <comment xml:lang="sk">Obrázok NIFF</comment>
+ <comment xml:lang="ru">Изображение NIFF</comment>
+ <comment xml:lang="ro">Imagine NIF</comment>
+ <comment xml:lang="pt_BR">Imagem NIFF</comment>
+ <comment xml:lang="pt">imagem NIFF</comment>
+ <comment xml:lang="pl">Obraz NIFF</comment>
+ <comment xml:lang="oc">imatge NIFF</comment>
+ <comment xml:lang="nn">NIFF-bilete</comment>
+ <comment xml:lang="nl">NIFF-afbeelding</comment>
+ <comment xml:lang="nb">NIFF-bilde</comment>
+ <comment xml:lang="lv">NIFF attēls</comment>
+ <comment xml:lang="lt">NIFF paveikslėlis</comment>
+ <comment xml:lang="ko">NIFF 그림</comment>
+ <comment xml:lang="kk">NIFF суреті</comment>
+ <comment xml:lang="ja">NIFF 画像</comment>
+ <comment xml:lang="it">Immagine NIFF</comment>
+ <comment xml:lang="is">NIFF mynd</comment>
+ <comment xml:lang="id">Citra NIFF</comment>
+ <comment xml:lang="ia">Imagine NIFF</comment>
+ <comment xml:lang="hu">NIFF kép</comment>
+ <comment xml:lang="hr">NIFF slika</comment>
+ <comment xml:lang="he">תמונת NIFF</comment>
+ <comment xml:lang="gl">imaxe NIFF</comment>
+ <comment xml:lang="ga">íomhá NIFF</comment>
+ <comment xml:lang="fur">imagjin NIFF</comment>
+ <comment xml:lang="fr">image NIFF</comment>
+ <comment xml:lang="fo">NIFF mynd</comment>
+ <comment xml:lang="fi">NIFF-kuva</comment>
+ <comment xml:lang="eu">NIFF irudia</comment>
+ <comment xml:lang="es">imagen NIFF</comment>
+ <comment xml:lang="eo">NIFF-bildo</comment>
+ <comment xml:lang="en_GB">NIFF image</comment>
+ <comment xml:lang="el">Εικόνα NIFF</comment>
+ <comment xml:lang="de">NIFF-Bild</comment>
+ <comment xml:lang="da">NIFF-billede</comment>
+ <comment xml:lang="cs">obrázek NIFF</comment>
+ <comment xml:lang="ca">imatge NIFF</comment>
+ <comment xml:lang="bg">Изображение — NIFF</comment>
+ <comment xml:lang="be@latin">Vyjava NIFF</comment>
+ <comment xml:lang="be">выява NIFF</comment>
+ <comment xml:lang="ar">صورة NIFF</comment>
+ <comment xml:lang="af">NIFF-beeld</comment>
+ <acronym>NIFF</acronym>
+ <expanded-acronym>Navy Image File Format</expanded-acronym>
<magic priority="80">
- <match value="IIN1" type="string" offset="0"/>
+ <match type="string" value="IIN1" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/vnd.zbrush.pcx">
<comment>PCX image</comment>
- <comment xml:lang="ar">صورة PCX</comment>
- <comment xml:lang="be@latin">Vyjava PCX</comment>
- <comment xml:lang="bg">Изображение — PCX</comment>
- <comment xml:lang="ca">imatge PCX</comment>
- <comment xml:lang="cs">obrázek PCX</comment>
- <comment xml:lang="da">PCX-billede</comment>
- <comment xml:lang="de">PCX-Bild</comment>
- <comment xml:lang="el">Εικόνα PCX</comment>
- <comment xml:lang="en_GB">PCX image</comment>
- <comment xml:lang="eo">PCX-bildo</comment>
- <comment xml:lang="es">imagen PCX</comment>
- <comment xml:lang="eu">PCX irudia</comment>
- <comment xml:lang="fi">PCX-kuva</comment>
- <comment xml:lang="fo">PCX mynd</comment>
- <comment xml:lang="fr">image PCX</comment>
- <comment xml:lang="ga">íomhá PCX</comment>
- <comment xml:lang="gl">imaxe PCX</comment>
- <comment xml:lang="he">תמונת PCX</comment>
- <comment xml:lang="hr">PCX slika</comment>
- <comment xml:lang="hu">PCX kép</comment>
- <comment xml:lang="ia">Imagine PCX</comment>
- <comment xml:lang="id">Citra PCX</comment>
- <comment xml:lang="it">Immagine PCX</comment>
- <comment xml:lang="ja">PCX 画像</comment>
- <comment xml:lang="kk">PCX суреті</comment>
- <comment xml:lang="ko">PCX 그림</comment>
- <comment xml:lang="lt">PCX paveikslėlis</comment>
- <comment xml:lang="lv">PCX attēls</comment>
- <comment xml:lang="nb">PCX-bilde</comment>
- <comment xml:lang="nl">PCX-afbeelding</comment>
- <comment xml:lang="nn">PCX-bilete</comment>
- <comment xml:lang="oc">imatge PCX</comment>
- <comment xml:lang="pl">Obraz PCX</comment>
- <comment xml:lang="pt">imagem PCX</comment>
- <comment xml:lang="pt_BR">Imagem PCX</comment>
- <comment xml:lang="ro">Imagine PCX</comment>
- <comment xml:lang="ru">Изображение PCX</comment>
- <comment xml:lang="sk">Obrázok PCX</comment>
- <comment xml:lang="sl">Slikovna datoteka PCX</comment>
- <comment xml:lang="sq">Figurë PCX</comment>
- <comment xml:lang="sr">ПЦИкс слика</comment>
- <comment xml:lang="sv">PCX-bild</comment>
- <comment xml:lang="tr">PCX görüntüsü</comment>
- <comment xml:lang="uk">зображення PCX</comment>
- <comment xml:lang="vi">Ảnh PCX</comment>
- <comment xml:lang="zh_CN">PCX 图像</comment>
<comment xml:lang="zh_TW">PCX 影像</comment>
+ <comment xml:lang="zh_CN">PCX 图像</comment>
+ <comment xml:lang="vi">Ảnh PCX</comment>
+ <comment xml:lang="uk">зображення PCX</comment>
+ <comment xml:lang="tr">PCX görüntüsü</comment>
+ <comment xml:lang="sv">PCX-bild</comment>
+ <comment xml:lang="sr">ПЦИкс слика</comment>
+ <comment xml:lang="sq">figurë PCX</comment>
+ <comment xml:lang="sl">Slikovna datoteka PCX</comment>
+ <comment xml:lang="si">PCX රූපය</comment>
+ <comment xml:lang="sk">Obrázok PCX</comment>
+ <comment xml:lang="ru">Изображение PCX</comment>
+ <comment xml:lang="ro">Imagine PCX</comment>
+ <comment xml:lang="pt_BR">Imagem PCX</comment>
+ <comment xml:lang="pt">imagem PCX</comment>
+ <comment xml:lang="pl">Obraz PCX</comment>
+ <comment xml:lang="oc">imatge PCX</comment>
+ <comment xml:lang="nn">PCX-bilete</comment>
+ <comment xml:lang="nl">PCX-afbeelding</comment>
+ <comment xml:lang="nb">PCX-bilde</comment>
+ <comment xml:lang="lv">PCX attēls</comment>
+ <comment xml:lang="lt">PCX paveikslėlis</comment>
+ <comment xml:lang="ko">PCX 그림</comment>
+ <comment xml:lang="kk">PCX суреті</comment>
+ <comment xml:lang="ja">PCX 画像</comment>
+ <comment xml:lang="it">Immagine PCX</comment>
+ <comment xml:lang="is">PCX mynd</comment>
+ <comment xml:lang="id">Citra PCX</comment>
+ <comment xml:lang="ia">Imagine PCX</comment>
+ <comment xml:lang="hu">PCX kép</comment>
+ <comment xml:lang="hr">PCX slika</comment>
+ <comment xml:lang="he">תמונת PCX</comment>
+ <comment xml:lang="gl">imaxe PCX</comment>
+ <comment xml:lang="ga">íomhá PCX</comment>
+ <comment xml:lang="fur">imagjin PCX</comment>
+ <comment xml:lang="fr">image PCX</comment>
+ <comment xml:lang="fo">PCX mynd</comment>
+ <comment xml:lang="fi">PCX-kuva</comment>
+ <comment xml:lang="eu">PCX irudia</comment>
+ <comment xml:lang="es">imagen PCX</comment>
+ <comment xml:lang="eo">PCX-bildo</comment>
+ <comment xml:lang="en_GB">PCX image</comment>
+ <comment xml:lang="el">Εικόνα PCX</comment>
+ <comment xml:lang="de">PCX-Bild</comment>
+ <comment xml:lang="da">PCX-billede</comment>
+ <comment xml:lang="cs">obrázek PCX</comment>
+ <comment xml:lang="ca">imatge PCX</comment>
+ <comment xml:lang="bg">Изображение — PCX</comment>
+ <comment xml:lang="be@latin">Vyjava PCX</comment>
+ <comment xml:lang="be">выява PCX</comment>
+ <comment xml:lang="ar">صورة PCX</comment>
+ <comment xml:lang="af">PCX-beeld</comment>
<acronym>PCX</acronym>
<expanded-acronym>PiCture eXchange</expanded-acronym>
- <magic priority="50">
- <match value="10" type="byte" offset="0">
- <match value="0" type="byte" offset="1"/>
- <match value="2" type="byte" offset="1"/>
- <match value="3" type="byte" offset="1"/>
- <match value="5" type="byte" offset="1"/>
+ <magic>
+ <match type="byte" value="10" offset="0">
+ <match type="byte" value="0" offset="1"/>
+ <match type="byte" value="2" offset="1"/>
+ <match type="byte" value="3" offset="1"/>
+ <match type="byte" value="5" offset="1"/>
</match>
</magic>
<glob pattern="*.pcx"/>
@@ -28871,368 +31499,405 @@
</mime-type>
<mime-type type="image/x-photo-cd">
<comment>PCD image</comment>
- <comment xml:lang="ar">صورة PCD</comment>
- <comment xml:lang="be@latin">Vyjava PCD</comment>
- <comment xml:lang="bg">Изображение — PCD</comment>
- <comment xml:lang="ca">imatge PCD</comment>
- <comment xml:lang="cs">obrázek PCD</comment>
- <comment xml:lang="da">PCD-billede</comment>
- <comment xml:lang="de">PCD-Bild</comment>
- <comment xml:lang="el">Εικόνα PCD</comment>
- <comment xml:lang="en_GB">PCD image</comment>
- <comment xml:lang="eo">PCD-bildo</comment>
- <comment xml:lang="es">imagen PCD</comment>
- <comment xml:lang="eu">PCD irudia</comment>
- <comment xml:lang="fi">PCD-kuva</comment>
- <comment xml:lang="fo">PCD mynd</comment>
- <comment xml:lang="fr">image PCD</comment>
- <comment xml:lang="ga">íomhá PCD</comment>
- <comment xml:lang="gl">imaxe PCD</comment>
- <comment xml:lang="he">תמונת PCD</comment>
- <comment xml:lang="hr">PCD slika</comment>
- <comment xml:lang="hu">PCD kép</comment>
- <comment xml:lang="ia">Imagine PCD</comment>
- <comment xml:lang="id">Citra PCD</comment>
- <comment xml:lang="it">Immagine PCD</comment>
- <comment xml:lang="ja">PCD 画像</comment>
- <comment xml:lang="ka">PCD გამოსახულება</comment>
- <comment xml:lang="kk">PCD суреті</comment>
- <comment xml:lang="ko">PCD 그림</comment>
- <comment xml:lang="lt">PCD paveikslėlis</comment>
- <comment xml:lang="lv">PCD attēls</comment>
- <comment xml:lang="nb">PCD-bilde</comment>
- <comment xml:lang="nl">PCD-afbeelding</comment>
- <comment xml:lang="nn">PCD-bilete</comment>
- <comment xml:lang="oc">imatge PCD</comment>
- <comment xml:lang="pl">Obraz PCD</comment>
- <comment xml:lang="pt">imagem PCD</comment>
- <comment xml:lang="pt_BR">Imagem PCD</comment>
- <comment xml:lang="ro">Imagine PCD</comment>
- <comment xml:lang="ru">Изображение PCD</comment>
- <comment xml:lang="sk">Obrázok PCD</comment>
- <comment xml:lang="sl">Slikovna datoteka PCD</comment>
- <comment xml:lang="sq">Figurë PCD</comment>
- <comment xml:lang="sr">ПЦД слика</comment>
- <comment xml:lang="sv">PCD-bild</comment>
- <comment xml:lang="tr">PCD görüntüsü</comment>
- <comment xml:lang="uk">зображення PCD</comment>
- <comment xml:lang="vi">Ảnh PCD</comment>
- <comment xml:lang="zh_CN">PCD 图像</comment>
<comment xml:lang="zh_TW">PCD 影像</comment>
+ <comment xml:lang="zh_CN">PCD 图像</comment>
+ <comment xml:lang="vi">Ảnh PCD</comment>
+ <comment xml:lang="uk">зображення PCD</comment>
+ <comment xml:lang="tr">PCD görüntüsü</comment>
+ <comment xml:lang="sv">PCD-bild</comment>
+ <comment xml:lang="sr">ПЦД слика</comment>
+ <comment xml:lang="sq">figurë PCD</comment>
+ <comment xml:lang="sl">Slikovna datoteka PCD</comment>
+ <comment xml:lang="si">PCD රූපය</comment>
+ <comment xml:lang="sk">Obrázok PCD</comment>
+ <comment xml:lang="ru">Изображение PCD</comment>
+ <comment xml:lang="ro">Imagine PCD</comment>
+ <comment xml:lang="pt_BR">Imagem PCD</comment>
+ <comment xml:lang="pt">imagem PCD</comment>
+ <comment xml:lang="pl">Obraz PCD</comment>
+ <comment xml:lang="oc">imatge PCD</comment>
+ <comment xml:lang="nn">PCD-bilete</comment>
+ <comment xml:lang="nl">PCD-afbeelding</comment>
+ <comment xml:lang="nb">PCD-bilde</comment>
+ <comment xml:lang="lv">PCD attēls</comment>
+ <comment xml:lang="lt">PCD paveikslėlis</comment>
+ <comment xml:lang="ko">PCD 그림</comment>
+ <comment xml:lang="kk">PCD суреті</comment>
+ <comment xml:lang="ka">PCD გამოსახულება</comment>
+ <comment xml:lang="ja">PCD 画像</comment>
+ <comment xml:lang="it">Immagine PCD</comment>
+ <comment xml:lang="is">PCD mynd</comment>
+ <comment xml:lang="id">Citra PCD</comment>
+ <comment xml:lang="ia">Imagine PCD</comment>
+ <comment xml:lang="hu">PCD kép</comment>
+ <comment xml:lang="hr">PCD slika</comment>
+ <comment xml:lang="he">תמונת PCD</comment>
+ <comment xml:lang="gl">imaxe PCD</comment>
+ <comment xml:lang="ga">íomhá PCD</comment>
+ <comment xml:lang="fur">imagjin PCD</comment>
+ <comment xml:lang="fr">image PCD</comment>
+ <comment xml:lang="fo">PCD mynd</comment>
+ <comment xml:lang="fi">PCD-kuva</comment>
+ <comment xml:lang="eu">PCD irudia</comment>
+ <comment xml:lang="es">imagen PCD</comment>
+ <comment xml:lang="eo">PCD-bildo</comment>
+ <comment xml:lang="en_GB">PCD image</comment>
+ <comment xml:lang="el">Εικόνα PCD</comment>
+ <comment xml:lang="de">PCD-Bild</comment>
+ <comment xml:lang="da">PCD-billede</comment>
+ <comment xml:lang="cs">obrázek PCD</comment>
+ <comment xml:lang="ca">imatge PCD</comment>
+ <comment xml:lang="bg">Изображение — PCD</comment>
+ <comment xml:lang="be@latin">Vyjava PCD</comment>
+ <comment xml:lang="be">выява PCD</comment>
+ <comment xml:lang="ar">صورة PCD</comment>
+ <comment xml:lang="af">PCD-beeld</comment>
<acronym>PCD</acronym>
<expanded-acronym>PhotoCD</expanded-acronym>
+ <generic-icon name="media-optical"/>
<glob pattern="*.pcd"/>
</mime-type>
<mime-type type="image/x-portable-anymap">
<comment>PNM image</comment>
- <comment xml:lang="ar">صورة PNM</comment>
- <comment xml:lang="az">PNM rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava PNM</comment>
- <comment xml:lang="bg">Изображение — PNM</comment>
- <comment xml:lang="ca">imatge PNM</comment>
- <comment xml:lang="cs">obrázek PNM</comment>
- <comment xml:lang="cy">Delwedd PNM</comment>
- <comment xml:lang="da">PNM-billede</comment>
- <comment xml:lang="de">PNM-Bild</comment>
- <comment xml:lang="el">Εικόνα PNM</comment>
- <comment xml:lang="en_GB">PNM image</comment>
- <comment xml:lang="eo">PNM-bildo</comment>
- <comment xml:lang="es">imagen PNM</comment>
- <comment xml:lang="eu">PNM irudia</comment>
- <comment xml:lang="fi">PNM-kuva</comment>
- <comment xml:lang="fo">PNM mynd</comment>
- <comment xml:lang="fr">image PNM</comment>
- <comment xml:lang="ga">íomhá PNM</comment>
- <comment xml:lang="gl">imaxe PNM</comment>
- <comment xml:lang="he">תמונת PNM</comment>
- <comment xml:lang="hr">PNM slika</comment>
- <comment xml:lang="hu">PNM-kép</comment>
- <comment xml:lang="ia">Imagine PNM</comment>
- <comment xml:lang="id">Citra PNM</comment>
- <comment xml:lang="it">Immagine PNM</comment>
- <comment xml:lang="ja">PNM 画像</comment>
- <comment xml:lang="kk">PNM суреті</comment>
- <comment xml:lang="ko">PNM 그림</comment>
- <comment xml:lang="lt">PNM paveikslėlis</comment>
- <comment xml:lang="lv">PNM attēls</comment>
- <comment xml:lang="ms">Imej PNM</comment>
- <comment xml:lang="nb">PNM-bilde</comment>
- <comment xml:lang="nl">PNM-afbeelding</comment>
- <comment xml:lang="nn">PNM-bilete</comment>
- <comment xml:lang="oc">imatge PNM</comment>
- <comment xml:lang="pl">Obraz PNM</comment>
- <comment xml:lang="pt">imagem PNM</comment>
- <comment xml:lang="pt_BR">Imagem PNM</comment>
- <comment xml:lang="ro">Imagine PNM</comment>
- <comment xml:lang="ru">Изображение PNM</comment>
- <comment xml:lang="sk">Obrázok PNM</comment>
- <comment xml:lang="sl">Slikovna datoteka PNM</comment>
- <comment xml:lang="sq">Figurë PNM</comment>
- <comment xml:lang="sr">ПНМ слика</comment>
- <comment xml:lang="sv">PNM-bild</comment>
- <comment xml:lang="tr">PNM görüntüsü</comment>
- <comment xml:lang="uk">зображення PNM</comment>
- <comment xml:lang="vi">Ảnh PNM</comment>
- <comment xml:lang="zh_CN">PNM 图像</comment>
<comment xml:lang="zh_TW">PNM 影像</comment>
+ <comment xml:lang="zh_CN">PNM 图像</comment>
+ <comment xml:lang="vi">Ảnh PNM</comment>
+ <comment xml:lang="uk">зображення PNM</comment>
+ <comment xml:lang="tr">PNM görüntüsü</comment>
+ <comment xml:lang="sv">PNM-bild</comment>
+ <comment xml:lang="sr">ПНМ слика</comment>
+ <comment xml:lang="sq">figurë PNM</comment>
+ <comment xml:lang="sl">Slikovna datoteka PNM</comment>
+ <comment xml:lang="si">PNM රූපය</comment>
+ <comment xml:lang="sk">Obrázok PNM</comment>
+ <comment xml:lang="ru">Изображение PNM</comment>
+ <comment xml:lang="ro">Imagine PNM</comment>
+ <comment xml:lang="pt_BR">Imagem PNM</comment>
+ <comment xml:lang="pt">imagem PNM</comment>
+ <comment xml:lang="pl">Obraz PNM</comment>
+ <comment xml:lang="oc">imatge PNM</comment>
+ <comment xml:lang="nn">PNM-bilete</comment>
+ <comment xml:lang="nl">PNM-afbeelding</comment>
+ <comment xml:lang="nb">PNM-bilde</comment>
+ <comment xml:lang="ms">Imej PNM</comment>
+ <comment xml:lang="lv">PNM attēls</comment>
+ <comment xml:lang="lt">PNM paveikslėlis</comment>
+ <comment xml:lang="ko">PNM 그림</comment>
+ <comment xml:lang="kk">PNM суреті</comment>
+ <comment xml:lang="ka">PNM გამოსახულება</comment>
+ <comment xml:lang="ja">PNM 画像</comment>
+ <comment xml:lang="it">Immagine PNM</comment>
+ <comment xml:lang="is">PNM mynd</comment>
+ <comment xml:lang="id">Citra PNM</comment>
+ <comment xml:lang="ia">Imagine PNM</comment>
+ <comment xml:lang="hu">PNM-kép</comment>
+ <comment xml:lang="hr">PNM slika</comment>
+ <comment xml:lang="he">תמונת PNM</comment>
+ <comment xml:lang="gl">imaxe PNM</comment>
+ <comment xml:lang="ga">íomhá PNM</comment>
+ <comment xml:lang="fur">imagjin PNM</comment>
+ <comment xml:lang="fr">image PNM</comment>
+ <comment xml:lang="fo">PNM mynd</comment>
+ <comment xml:lang="fi">PNM-kuva</comment>
+ <comment xml:lang="eu">PNM irudia</comment>
+ <comment xml:lang="es">imagen PNM</comment>
+ <comment xml:lang="eo">PNM-bildo</comment>
+ <comment xml:lang="en_GB">PNM image</comment>
+ <comment xml:lang="el">Εικόνα PNM</comment>
+ <comment xml:lang="de">PNM-Bild</comment>
+ <comment xml:lang="da">PNM-billede</comment>
+ <comment xml:lang="cy">Delwedd PNM</comment>
+ <comment xml:lang="cs">obrázek PNM</comment>
+ <comment xml:lang="ca">imatge PNM</comment>
+ <comment xml:lang="bg">Изображение — PNM</comment>
+ <comment xml:lang="be@latin">Vyjava PNM</comment>
+ <comment xml:lang="be">выява PNM</comment>
+ <comment xml:lang="az">PNM rəsmi</comment>
+ <comment xml:lang="ar">صورة PNM</comment>
+ <comment xml:lang="af">PNM-beeld</comment>
+ <acronym>PNM</acronym>
+ <expanded-acronym>Portable Anymap</expanded-acronym>
<glob pattern="*.pnm"/>
</mime-type>
<mime-type type="image/x-portable-bitmap">
<comment>PBM image</comment>
- <comment xml:lang="ar">صورة PBM</comment>
- <comment xml:lang="be@latin">Vyjava PBM</comment>
- <comment xml:lang="bg">Изображение — PBM</comment>
- <comment xml:lang="ca">imatge PBM</comment>
- <comment xml:lang="cs">obrázek PBM</comment>
- <comment xml:lang="cy">Delwedd PBM</comment>
- <comment xml:lang="da">PBM-billede</comment>
- <comment xml:lang="de">PBM-Bild</comment>
- <comment xml:lang="el">Εικόνα PBM</comment>
- <comment xml:lang="en_GB">PBM image</comment>
- <comment xml:lang="eo">PBM-bildo</comment>
- <comment xml:lang="es">imagen PBM</comment>
- <comment xml:lang="eu">PBM irudia</comment>
- <comment xml:lang="fi">PBM-kuva</comment>
- <comment xml:lang="fo">PBM mynd</comment>
- <comment xml:lang="fr">image PBM</comment>
- <comment xml:lang="ga">íomhá PBM</comment>
- <comment xml:lang="gl">imaxe PBM</comment>
- <comment xml:lang="he">תמונת PBM</comment>
- <comment xml:lang="hr">PBM slika</comment>
- <comment xml:lang="hu">PBM kép</comment>
- <comment xml:lang="ia">Imagine PBM</comment>
- <comment xml:lang="id">Citra PBM</comment>
- <comment xml:lang="it">Immagine PBM</comment>
- <comment xml:lang="ja">PBM 画像</comment>
- <comment xml:lang="ka">PBM გამოსახულება</comment>
- <comment xml:lang="kk">PBM суреті</comment>
- <comment xml:lang="ko">PBM 그림</comment>
- <comment xml:lang="lt">PBM paveikslėlis</comment>
- <comment xml:lang="lv">PBM attēls</comment>
- <comment xml:lang="nb">PBM-bilde</comment>
- <comment xml:lang="nl">PBM-afbeelding</comment>
- <comment xml:lang="nn">PBM-bilete</comment>
- <comment xml:lang="oc">imatge PBM</comment>
- <comment xml:lang="pl">Obraz PBM</comment>
- <comment xml:lang="pt">imagem PBM</comment>
- <comment xml:lang="pt_BR">Imagem PBM</comment>
- <comment xml:lang="ro">Imagine PBM</comment>
- <comment xml:lang="ru">Изображение PBM</comment>
- <comment xml:lang="sk">Obrázok PBM</comment>
- <comment xml:lang="sl">Slikovna datoteka PBM</comment>
- <comment xml:lang="sq">Figurë PBM</comment>
- <comment xml:lang="sr">ПБМ слика</comment>
- <comment xml:lang="sv">PBM-bild</comment>
- <comment xml:lang="tr">PBM görüntüsü</comment>
- <comment xml:lang="uk">зображення PBM</comment>
- <comment xml:lang="vi">Ảnh PBM</comment>
- <comment xml:lang="zh_CN">PBM 图像</comment>
<comment xml:lang="zh_TW">PBM 影像</comment>
+ <comment xml:lang="zh_CN">PBM 图像</comment>
+ <comment xml:lang="vi">Ảnh PBM</comment>
+ <comment xml:lang="uk">зображення PBM</comment>
+ <comment xml:lang="tr">PBM görüntüsü</comment>
+ <comment xml:lang="sv">PBM-bild</comment>
+ <comment xml:lang="sr">ПБМ слика</comment>
+ <comment xml:lang="sq">figurë PBM</comment>
+ <comment xml:lang="sl">Slikovna datoteka PBM</comment>
+ <comment xml:lang="si">PBM රූපය</comment>
+ <comment xml:lang="sk">Obrázok PBM</comment>
+ <comment xml:lang="ru">Изображение PBM</comment>
+ <comment xml:lang="ro">Imagine PBM</comment>
+ <comment xml:lang="pt_BR">Imagem PBM</comment>
+ <comment xml:lang="pt">imagem PBM</comment>
+ <comment xml:lang="pl">Obraz PBM</comment>
+ <comment xml:lang="oc">imatge PBM</comment>
+ <comment xml:lang="nn">PBM-bilete</comment>
+ <comment xml:lang="nl">PBM-afbeelding</comment>
+ <comment xml:lang="nb">PBM-bilde</comment>
+ <comment xml:lang="lv">PBM attēls</comment>
+ <comment xml:lang="lt">PBM paveikslėlis</comment>
+ <comment xml:lang="ko">PBM 그림</comment>
+ <comment xml:lang="kk">PBM суреті</comment>
+ <comment xml:lang="ka">PBM გამოსახულება</comment>
+ <comment xml:lang="ja">PBM 画像</comment>
+ <comment xml:lang="it">Immagine PBM</comment>
+ <comment xml:lang="is">PBM mynd</comment>
+ <comment xml:lang="id">Citra PBM</comment>
+ <comment xml:lang="ia">Imagine PBM</comment>
+ <comment xml:lang="hu">PBM kép</comment>
+ <comment xml:lang="hr">PBM slika</comment>
+ <comment xml:lang="he">תמונת PBM</comment>
+ <comment xml:lang="gl">imaxe PBM</comment>
+ <comment xml:lang="ga">íomhá PBM</comment>
+ <comment xml:lang="fur">imagjin PBM</comment>
+ <comment xml:lang="fr">image PBM</comment>
+ <comment xml:lang="fo">PBM mynd</comment>
+ <comment xml:lang="fi">PBM-kuva</comment>
+ <comment xml:lang="eu">PBM irudia</comment>
+ <comment xml:lang="es">imagen PBM</comment>
+ <comment xml:lang="eo">PBM-bildo</comment>
+ <comment xml:lang="en_GB">PBM image</comment>
+ <comment xml:lang="el">Εικόνα PBM</comment>
+ <comment xml:lang="de">PBM-Bild</comment>
+ <comment xml:lang="da">PBM-billede</comment>
+ <comment xml:lang="cy">Delwedd PBM</comment>
+ <comment xml:lang="cs">obrázek PBM</comment>
+ <comment xml:lang="ca">imatge PBM</comment>
+ <comment xml:lang="bg">Изображение — PBM</comment>
+ <comment xml:lang="be@latin">Vyjava PBM</comment>
+ <comment xml:lang="be">выява PBM</comment>
+ <comment xml:lang="ar">صورة PBM</comment>
+ <comment xml:lang="af">PBM-beeld</comment>
<acronym>PBM</acronym>
<expanded-acronym>Portable BitMap</expanded-acronym>
<sub-class-of type="image/x-portable-anymap"/>
- <magic priority="50">
- <match value="P1" type="string" offset="0">
- <match value="0x0a" type="byte" offset="2"/>
- <match value="0x20" type="byte" offset="2"/>
- <match value="0x09" type="byte" offset="2"/>
- <match value="0x0d" type="byte" offset="2"/>
+ <magic>
+ <match type="string" value="P1" offset="0">
+ <match type="byte" value="0x0a" offset="2"/>
+ <match type="byte" value="0x20" offset="2"/>
+ <match type="byte" value="0x09" offset="2"/>
+ <match type="byte" value="0x0d" offset="2"/>
</match>
- <match value="P4" type="string" offset="0">
- <match value="0x0a" type="byte" offset="2"/>
- <match value="0x20" type="byte" offset="2"/>
- <match value="0x09" type="byte" offset="2"/>
- <match value="0x0d" type="byte" offset="2"/>
+ <match type="string" value="P4" offset="0">
+ <match type="byte" value="0x0a" offset="2"/>
+ <match type="byte" value="0x20" offset="2"/>
+ <match type="byte" value="0x09" offset="2"/>
+ <match type="byte" value="0x0d" offset="2"/>
</match>
</magic>
<glob pattern="*.pbm"/>
</mime-type>
<mime-type type="image/x-portable-graymap">
<comment>PGM image</comment>
- <comment xml:lang="ar">صورة PGM</comment>
- <comment xml:lang="be@latin">Vyjava PGM</comment>
- <comment xml:lang="bg">Изображение — PGM</comment>
- <comment xml:lang="ca">imatge PGM</comment>
- <comment xml:lang="cs">obrázek PGM</comment>
- <comment xml:lang="cy">Delwedd PGM</comment>
- <comment xml:lang="da">PGM-billede</comment>
- <comment xml:lang="de">PGM-Bild</comment>
- <comment xml:lang="el">Εικόνα PGM</comment>
- <comment xml:lang="en_GB">PGM image</comment>
- <comment xml:lang="eo">PGM-bildo</comment>
- <comment xml:lang="es">imagen PGM</comment>
- <comment xml:lang="eu">PGM irudia</comment>
- <comment xml:lang="fi">PGM-kuva</comment>
- <comment xml:lang="fo">PGM mynd</comment>
- <comment xml:lang="fr">image PGM</comment>
- <comment xml:lang="ga">íomhá PGM</comment>
- <comment xml:lang="gl">imaxe PGM</comment>
- <comment xml:lang="he">תמונת PGM</comment>
- <comment xml:lang="hr">PGM slika</comment>
- <comment xml:lang="hu">PGM kép</comment>
- <comment xml:lang="ia">Imagine PGM</comment>
- <comment xml:lang="id">Citra PGM</comment>
- <comment xml:lang="it">Immagine PGM</comment>
- <comment xml:lang="ja">PGM 画像</comment>
- <comment xml:lang="kk">PGM суреті</comment>
- <comment xml:lang="ko">PGM 그림</comment>
- <comment xml:lang="lt">PGM paveikslėlis</comment>
- <comment xml:lang="lv">PGM attēls</comment>
- <comment xml:lang="nb">PGM-bilde</comment>
- <comment xml:lang="nl">PGM-afbeelding</comment>
- <comment xml:lang="nn">PGM-bilete</comment>
- <comment xml:lang="oc">imatge PGM</comment>
- <comment xml:lang="pl">Obraz PGM</comment>
- <comment xml:lang="pt">imagem PGM</comment>
- <comment xml:lang="pt_BR">Imagem PGM</comment>
- <comment xml:lang="ro">Imagine PGM</comment>
- <comment xml:lang="ru">Изображение PGM</comment>
- <comment xml:lang="sk">Obrázok PGM</comment>
- <comment xml:lang="sl">Slikovna datoteka PGM</comment>
- <comment xml:lang="sq">Figurë PGM</comment>
- <comment xml:lang="sr">ПГМ слика</comment>
- <comment xml:lang="sv">PGM-bild</comment>
- <comment xml:lang="tr">PGM görüntüsü</comment>
- <comment xml:lang="uk">зображення PGM</comment>
- <comment xml:lang="vi">Ảnh PGM</comment>
- <comment xml:lang="zh_CN">PGM 图像</comment>
<comment xml:lang="zh_TW">PGM 影像</comment>
+ <comment xml:lang="zh_CN">PGM 图像</comment>
+ <comment xml:lang="vi">Ảnh PGM</comment>
+ <comment xml:lang="uk">зображення PGM</comment>
+ <comment xml:lang="tr">PGM görüntüsü</comment>
+ <comment xml:lang="sv">PGM-bild</comment>
+ <comment xml:lang="sr">ПГМ слика</comment>
+ <comment xml:lang="sq">figurë PGM</comment>
+ <comment xml:lang="sl">Slikovna datoteka PGM</comment>
+ <comment xml:lang="si">PGM රූපය</comment>
+ <comment xml:lang="sk">Obrázok PGM</comment>
+ <comment xml:lang="ru">Изображение PGM</comment>
+ <comment xml:lang="ro">Imagine PGM</comment>
+ <comment xml:lang="pt_BR">Imagem PGM</comment>
+ <comment xml:lang="pt">imagem PGM</comment>
+ <comment xml:lang="pl">Obraz PGM</comment>
+ <comment xml:lang="oc">imatge PGM</comment>
+ <comment xml:lang="nn">PGM-bilete</comment>
+ <comment xml:lang="nl">PGM-afbeelding</comment>
+ <comment xml:lang="nb">PGM-bilde</comment>
+ <comment xml:lang="lv">PGM attēls</comment>
+ <comment xml:lang="lt">PGM paveikslėlis</comment>
+ <comment xml:lang="ko">PGM 그림</comment>
+ <comment xml:lang="kk">PGM суреті</comment>
+ <comment xml:lang="ka">PGM გამოსახულება</comment>
+ <comment xml:lang="ja">PGM 画像</comment>
+ <comment xml:lang="it">Immagine PGM</comment>
+ <comment xml:lang="is">PGM mynd</comment>
+ <comment xml:lang="id">Citra PGM</comment>
+ <comment xml:lang="ia">Imagine PGM</comment>
+ <comment xml:lang="hu">PGM kép</comment>
+ <comment xml:lang="hr">PGM slika</comment>
+ <comment xml:lang="he">תמונת PGM</comment>
+ <comment xml:lang="gl">imaxe PGM</comment>
+ <comment xml:lang="ga">íomhá PGM</comment>
+ <comment xml:lang="fur">imagjin PGM</comment>
+ <comment xml:lang="fr">image PGM</comment>
+ <comment xml:lang="fo">PGM mynd</comment>
+ <comment xml:lang="fi">PGM-kuva</comment>
+ <comment xml:lang="eu">PGM irudia</comment>
+ <comment xml:lang="es">imagen PGM</comment>
+ <comment xml:lang="eo">PGM-bildo</comment>
+ <comment xml:lang="en_GB">PGM image</comment>
+ <comment xml:lang="el">Εικόνα PGM</comment>
+ <comment xml:lang="de">PGM-Bild</comment>
+ <comment xml:lang="da">PGM-billede</comment>
+ <comment xml:lang="cy">Delwedd PGM</comment>
+ <comment xml:lang="cs">obrázek PGM</comment>
+ <comment xml:lang="ca">imatge PGM</comment>
+ <comment xml:lang="bg">Изображение — PGM</comment>
+ <comment xml:lang="be@latin">Vyjava PGM</comment>
+ <comment xml:lang="be">выява PGM</comment>
+ <comment xml:lang="ar">صورة PGM</comment>
+ <comment xml:lang="af">PGM-beeld</comment>
<acronym>PGM</acronym>
<expanded-acronym>Portable GrayMap</expanded-acronym>
<sub-class-of type="image/x-portable-anymap"/>
- <magic priority="50">
- <match value="P2" type="string" offset="0">
- <match value="0x0a" type="byte" offset="2"/>
- <match value="0x20" type="byte" offset="2"/>
- <match value="0x09" type="byte" offset="2"/>
- <match value="0x0d" type="byte" offset="2"/>
+ <magic>
+ <match type="string" value="P2" offset="0">
+ <match type="byte" value="0x0a" offset="2"/>
+ <match type="byte" value="0x20" offset="2"/>
+ <match type="byte" value="0x09" offset="2"/>
+ <match type="byte" value="0x0d" offset="2"/>
</match>
- <match value="P5" type="string" offset="0">
- <match value="0x0a" type="byte" offset="2"/>
- <match value="0x20" type="byte" offset="2"/>
- <match value="0x09" type="byte" offset="2"/>
- <match value="0x0d" type="byte" offset="2"/>
+ <match type="string" value="P5" offset="0">
+ <match type="byte" value="0x0a" offset="2"/>
+ <match type="byte" value="0x20" offset="2"/>
+ <match type="byte" value="0x09" offset="2"/>
+ <match type="byte" value="0x0d" offset="2"/>
</match>
</magic>
<glob pattern="*.pgm"/>
</mime-type>
<mime-type type="image/x-portable-pixmap">
<comment>PPM image</comment>
- <comment xml:lang="ar">صورة PPM</comment>
- <comment xml:lang="be@latin">Vyjava PPM</comment>
- <comment xml:lang="bg">Изображение — PPM</comment>
- <comment xml:lang="ca">imatge PPM</comment>
- <comment xml:lang="cs">obrázek PPM</comment>
- <comment xml:lang="cy">Delwedd PPM</comment>
- <comment xml:lang="da">PPM-billede</comment>
- <comment xml:lang="de">PPM-Bild</comment>
- <comment xml:lang="el">Εικόνα PPM</comment>
- <comment xml:lang="en_GB">PPM image</comment>
- <comment xml:lang="eo">PPM-bildo</comment>
- <comment xml:lang="es">imagen PPM</comment>
- <comment xml:lang="eu">PPM irudia</comment>
- <comment xml:lang="fi">PPM-kuva</comment>
- <comment xml:lang="fo">PPM mynd</comment>
- <comment xml:lang="fr">image PPM</comment>
- <comment xml:lang="ga">íomhá PPM</comment>
- <comment xml:lang="gl">imaxe PPM</comment>
- <comment xml:lang="he">תמונת PPM</comment>
- <comment xml:lang="hr">PPM slika</comment>
- <comment xml:lang="hu">PPM kép</comment>
- <comment xml:lang="ia">Imagine PPM</comment>
- <comment xml:lang="id">Citra PPM</comment>
- <comment xml:lang="it">Immagine PPM</comment>
- <comment xml:lang="ja">PPM 画像</comment>
- <comment xml:lang="kk">PPM суреті</comment>
- <comment xml:lang="ko">PPM 그림</comment>
- <comment xml:lang="lt">PPM paveikslėlis</comment>
- <comment xml:lang="lv">PPM attēls</comment>
- <comment xml:lang="nb">PPM-bilde</comment>
- <comment xml:lang="nl">PPM-afbeelding</comment>
- <comment xml:lang="nn">PPM-bilete</comment>
- <comment xml:lang="oc">imatge PPM</comment>
- <comment xml:lang="pl">Obraz PPM</comment>
- <comment xml:lang="pt">imagem PPM</comment>
- <comment xml:lang="pt_BR">Imagem PPM</comment>
- <comment xml:lang="ro">Imagine PPM</comment>
- <comment xml:lang="ru">Изображение PPM</comment>
- <comment xml:lang="sk">Obrázok PPM</comment>
- <comment xml:lang="sl">Slikovna datoteka PPM</comment>
- <comment xml:lang="sq">Figurë PPM</comment>
- <comment xml:lang="sr">ППМ слика</comment>
- <comment xml:lang="sv">PPM-bild</comment>
- <comment xml:lang="tr">PPM görüntüsü</comment>
- <comment xml:lang="uk">зображення PPM</comment>
- <comment xml:lang="vi">Ảnh PPM</comment>
- <comment xml:lang="zh_CN">PPM 图像</comment>
<comment xml:lang="zh_TW">PPM 影像</comment>
+ <comment xml:lang="zh_CN">PPM 图像</comment>
+ <comment xml:lang="vi">Ảnh PPM</comment>
+ <comment xml:lang="uk">зображення PPM</comment>
+ <comment xml:lang="tr">PPM görüntüsü</comment>
+ <comment xml:lang="sv">PPM-bild</comment>
+ <comment xml:lang="sr">ППМ слика</comment>
+ <comment xml:lang="sq">figurë PPM</comment>
+ <comment xml:lang="sl">Slikovna datoteka PPM</comment>
+ <comment xml:lang="si">PPM රූපය</comment>
+ <comment xml:lang="sk">Obrázok PPM</comment>
+ <comment xml:lang="ru">Изображение PPM</comment>
+ <comment xml:lang="ro">Imagine PPM</comment>
+ <comment xml:lang="pt_BR">Imagem PPM</comment>
+ <comment xml:lang="pt">imagem PPM</comment>
+ <comment xml:lang="pl">Obraz PPM</comment>
+ <comment xml:lang="oc">imatge PPM</comment>
+ <comment xml:lang="nn">PPM-bilete</comment>
+ <comment xml:lang="nl">PPM-afbeelding</comment>
+ <comment xml:lang="nb">PPM-bilde</comment>
+ <comment xml:lang="lv">PPM attēls</comment>
+ <comment xml:lang="lt">PPM paveikslėlis</comment>
+ <comment xml:lang="ko">PPM 그림</comment>
+ <comment xml:lang="kk">PPM суреті</comment>
+ <comment xml:lang="ka">PPM გამოსახულება</comment>
+ <comment xml:lang="ja">PPM 画像</comment>
+ <comment xml:lang="it">Immagine PPM</comment>
+ <comment xml:lang="is">PPM mynd</comment>
+ <comment xml:lang="id">Citra PPM</comment>
+ <comment xml:lang="ia">Imagine PPM</comment>
+ <comment xml:lang="hu">PPM kép</comment>
+ <comment xml:lang="hr">PPM slika</comment>
+ <comment xml:lang="he">תמונת PPM</comment>
+ <comment xml:lang="gl">imaxe PPM</comment>
+ <comment xml:lang="ga">íomhá PPM</comment>
+ <comment xml:lang="fur">imagjin PPM</comment>
+ <comment xml:lang="fr">image PPM</comment>
+ <comment xml:lang="fo">PPM mynd</comment>
+ <comment xml:lang="fi">PPM-kuva</comment>
+ <comment xml:lang="eu">PPM irudia</comment>
+ <comment xml:lang="es">imagen PPM</comment>
+ <comment xml:lang="eo">PPM-bildo</comment>
+ <comment xml:lang="en_GB">PPM image</comment>
+ <comment xml:lang="el">Εικόνα PPM</comment>
+ <comment xml:lang="de">PPM-Bild</comment>
+ <comment xml:lang="da">PPM-billede</comment>
+ <comment xml:lang="cy">Delwedd PPM</comment>
+ <comment xml:lang="cs">obrázek PPM</comment>
+ <comment xml:lang="ca">imatge PPM</comment>
+ <comment xml:lang="bg">Изображение — PPM</comment>
+ <comment xml:lang="be@latin">Vyjava PPM</comment>
+ <comment xml:lang="be">выява PPM</comment>
+ <comment xml:lang="ar">صورة PPM</comment>
+ <comment xml:lang="af">PPM-beeld</comment>
<acronym>PPM</acronym>
<expanded-acronym>Portable PixMap</expanded-acronym>
<sub-class-of type="image/x-portable-anymap"/>
- <magic priority="50">
- <match value="P3" type="string" offset="0">
- <match value="0x0a" type="byte" offset="2"/>
- <match value="0x20" type="byte" offset="2"/>
- <match value="0x09" type="byte" offset="2"/>
- <match value="0x0d" type="byte" offset="2"/>
+ <magic>
+ <match type="string" value="P3" offset="0">
+ <match type="byte" value="0x0a" offset="2"/>
+ <match type="byte" value="0x20" offset="2"/>
+ <match type="byte" value="0x09" offset="2"/>
+ <match type="byte" value="0x0d" offset="2"/>
</match>
- <match value="P6" type="string" offset="0">
- <match value="0x0a" type="byte" offset="2"/>
- <match value="0x20" type="byte" offset="2"/>
- <match value="0x09" type="byte" offset="2"/>
- <match value="0x0d" type="byte" offset="2"/>
+ <match type="string" value="P6" offset="0">
+ <match type="byte" value="0x0a" offset="2"/>
+ <match type="byte" value="0x20" offset="2"/>
+ <match type="byte" value="0x09" offset="2"/>
+ <match type="byte" value="0x0d" offset="2"/>
</match>
</magic>
<glob pattern="*.ppm"/>
</mime-type>
<mime-type type="image/vnd.adobe.photoshop">
<comment>Photoshop image</comment>
- <comment xml:lang="ar">صورة فوتوشوب</comment>
- <comment xml:lang="bg">Изображение — Photoshop</comment>
- <comment xml:lang="ca">imatge de Photoshop</comment>
- <comment xml:lang="cs">obrázek Photoshop</comment>
- <comment xml:lang="da">Photoshop-billede</comment>
- <comment xml:lang="de">Photoshop-Bild</comment>
- <comment xml:lang="el">Εικόνα Photoshop</comment>
- <comment xml:lang="en_GB">Photoshop image</comment>
- <comment xml:lang="eo">Photoshop-bildo</comment>
- <comment xml:lang="es">imagen de Photoshop</comment>
- <comment xml:lang="eu">Photoshop irudia</comment>
- <comment xml:lang="fi">Photoshop-kuva</comment>
- <comment xml:lang="fo">Photoshop mynd</comment>
- <comment xml:lang="fr">image Photoshop</comment>
- <comment xml:lang="ga">íomhá Photoshop</comment>
- <comment xml:lang="gl">imaxe de Photoshop</comment>
- <comment xml:lang="he">תמונת Photoshop</comment>
- <comment xml:lang="hr">Photoshop slika</comment>
- <comment xml:lang="hu">Photoshop-kép</comment>
- <comment xml:lang="ia">Imagine Photoshop</comment>
- <comment xml:lang="id">Citra Photoshop</comment>
- <comment xml:lang="it">Immagine Photoshop</comment>
- <comment xml:lang="ja">Photoshop 画像</comment>
- <comment xml:lang="kk">изображение Photoshop</comment>
- <comment xml:lang="ko">포토샵 이미지</comment>
- <comment xml:lang="lt">Photoshop paveikslėlis</comment>
- <comment xml:lang="lv">Photoshop attēls</comment>
- <comment xml:lang="ms">Imej Photoshop</comment>
- <comment xml:lang="nl">Photoshop-afbeelding</comment>
- <comment xml:lang="oc">imatge Photoshop</comment>
- <comment xml:lang="pl">Obraz Photoshop</comment>
- <comment xml:lang="pt">imagem Photoshop</comment>
- <comment xml:lang="pt_BR">Imagem do Photoshop</comment>
- <comment xml:lang="ro">Imagine Photoshop</comment>
- <comment xml:lang="ru">Изображение Photoshop</comment>
- <comment xml:lang="sk">Obrázok Photoshop</comment>
- <comment xml:lang="sl">Slikovna datoteka Photoshop</comment>
- <comment xml:lang="sr">Фотошоп слика</comment>
- <comment xml:lang="sv">Photoshop-bild</comment>
- <comment xml:lang="tr">Photoshop görüntüsü</comment>
- <comment xml:lang="uk">зображення Photoshop</comment>
- <comment xml:lang="vi">Ảnh Photoshop</comment>
- <comment xml:lang="zh_CN">Photoshop 图像</comment>
<comment xml:lang="zh_TW">Photoshop 影像</comment>
- <magic priority="50">
- <match value="8BPS \000\000\000\000" type="string" offset="0" mask="0xffffffff0000ffffffff"/>
+ <comment xml:lang="zh_CN">Photoshop 图像</comment>
+ <comment xml:lang="vi">Ảnh Photoshop</comment>
+ <comment xml:lang="uk">зображення Photoshop</comment>
+ <comment xml:lang="tr">Photoshop görüntüsü</comment>
+ <comment xml:lang="sv">Photoshop-bild</comment>
+ <comment xml:lang="sr">Фотошоп слика</comment>
+ <comment xml:lang="sq">figurë Photoshop</comment>
+ <comment xml:lang="sl">Slikovna datoteka Photoshop</comment>
+ <comment xml:lang="si">Photoshop රූපය</comment>
+ <comment xml:lang="sk">Obrázok Photoshop</comment>
+ <comment xml:lang="ru">Изображение Photoshop</comment>
+ <comment xml:lang="ro">Imagine Photoshop</comment>
+ <comment xml:lang="pt_BR">Imagem do Photoshop</comment>
+ <comment xml:lang="pt">imagem Photoshop</comment>
+ <comment xml:lang="pl">Obraz Photoshop</comment>
+ <comment xml:lang="oc">imatge Photoshop</comment>
+ <comment xml:lang="nl">Photoshop-afbeelding</comment>
+ <comment xml:lang="ms">Imej Photoshop</comment>
+ <comment xml:lang="lv">Photoshop attēls</comment>
+ <comment xml:lang="lt">Photoshop paveikslėlis</comment>
+ <comment xml:lang="ko">포토샵 이미지</comment>
+ <comment xml:lang="kk">изображение Photoshop</comment>
+ <comment xml:lang="ja">Photoshop 画像</comment>
+ <comment xml:lang="it">Immagine Photoshop</comment>
+ <comment xml:lang="is">Photoshop mynd</comment>
+ <comment xml:lang="id">Citra Photoshop</comment>
+ <comment xml:lang="ia">Imagine Photoshop</comment>
+ <comment xml:lang="hu">Photoshop-kép</comment>
+ <comment xml:lang="hr">Photoshop slika</comment>
+ <comment xml:lang="he">תמונת Photoshop</comment>
+ <comment xml:lang="gl">imaxe de Photoshop</comment>
+ <comment xml:lang="ga">íomhá Photoshop</comment>
+ <comment xml:lang="fur">imagjin Photoshop</comment>
+ <comment xml:lang="fr">image Photoshop</comment>
+ <comment xml:lang="fo">Photoshop mynd</comment>
+ <comment xml:lang="fi">Photoshop-kuva</comment>
+ <comment xml:lang="eu">Photoshop irudia</comment>
+ <comment xml:lang="es">imagen de Photoshop</comment>
+ <comment xml:lang="eo">Photoshop-bildo</comment>
+ <comment xml:lang="en_GB">Photoshop image</comment>
+ <comment xml:lang="el">Εικόνα Photoshop</comment>
+ <comment xml:lang="de">Photoshop-Bild</comment>
+ <comment xml:lang="da">Photoshop-billede</comment>
+ <comment xml:lang="cs">obrázek Photoshop</comment>
+ <comment xml:lang="ca">imatge de Photoshop</comment>
+ <comment xml:lang="bg">Изображение — Photoshop</comment>
+ <comment xml:lang="be">выява Photoshop</comment>
+ <comment xml:lang="ar">صورة فوتوشوب</comment>
+ <comment xml:lang="af">Photoshop-beeld</comment>
+ <magic>
+ <match type="string" mask="0xffffffff0000ffffffff" value="8BPS \000\000\000\000" offset="0"/>
</magic>
<glob pattern="*.psd"/>
<alias type="image/psd"/>
@@ -29244,226 +31909,246 @@
</mime-type>
<mime-type type="image/x-rgb">
<comment>RGB image</comment>
- <comment xml:lang="ar">صورة RGB</comment>
- <comment xml:lang="az">RGB rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava RGB</comment>
- <comment xml:lang="bg">Изображение — RGB</comment>
- <comment xml:lang="ca">imatge RGB</comment>
- <comment xml:lang="cs">obrázek RGB</comment>
- <comment xml:lang="cy">Delwedd RGB</comment>
- <comment xml:lang="da">RGB-billede</comment>
- <comment xml:lang="de">RGB-Bild</comment>
- <comment xml:lang="el">Εικόνα RGB</comment>
- <comment xml:lang="en_GB">RGB image</comment>
- <comment xml:lang="eo">RGB-bildo</comment>
- <comment xml:lang="es">imagen RGB</comment>
- <comment xml:lang="eu">RGB irudia</comment>
- <comment xml:lang="fi">RGB-kuva</comment>
- <comment xml:lang="fo">RGB mynd</comment>
- <comment xml:lang="fr">image RGB</comment>
- <comment xml:lang="ga">íomhá RGB</comment>
- <comment xml:lang="gl">imaxe RGB</comment>
- <comment xml:lang="he">תמונת RGB</comment>
- <comment xml:lang="hr">RGB slika</comment>
- <comment xml:lang="hu">RGB-kép</comment>
- <comment xml:lang="ia">Imagine RGB</comment>
- <comment xml:lang="id">Citra RGB</comment>
- <comment xml:lang="it">Immagine RGB</comment>
- <comment xml:lang="ja">RGB 画像</comment>
- <comment xml:lang="kk">RGB суреті</comment>
- <comment xml:lang="ko">RGB 그림</comment>
- <comment xml:lang="lt">RGB paveikslėlis</comment>
- <comment xml:lang="lv">RGB attēls</comment>
- <comment xml:lang="ms">Imej RGB</comment>
- <comment xml:lang="nb">RGB-bilde</comment>
- <comment xml:lang="nl">RGB-afbeelding</comment>
- <comment xml:lang="nn">RGB-bilete</comment>
- <comment xml:lang="oc">imatge RGB</comment>
- <comment xml:lang="pl">Obraz RGB</comment>
- <comment xml:lang="pt">imagem RGB</comment>
- <comment xml:lang="pt_BR">Imagem RGB</comment>
- <comment xml:lang="ro">Imagine RGB</comment>
- <comment xml:lang="ru">Изображение RGB</comment>
- <comment xml:lang="sk">Obrázok RGB</comment>
- <comment xml:lang="sl">Slikovna datoteka RGB</comment>
- <comment xml:lang="sq">Figurë RGB</comment>
- <comment xml:lang="sr">РГБ слика</comment>
- <comment xml:lang="sv">RGB-bild</comment>
- <comment xml:lang="tr">RGB görüntüsü</comment>
- <comment xml:lang="uk">зображення RGB</comment>
- <comment xml:lang="vi">Ảnh kiểu RGB</comment>
- <comment xml:lang="zh_CN">RGB 图像</comment>
<comment xml:lang="zh_TW">RGB 影像</comment>
+ <comment xml:lang="zh_CN">RGB 图像</comment>
+ <comment xml:lang="vi">Ảnh kiểu RGB</comment>
+ <comment xml:lang="uk">зображення RGB</comment>
+ <comment xml:lang="tr">RGB görüntüsü</comment>
+ <comment xml:lang="sv">RGB-bild</comment>
+ <comment xml:lang="sr">РГБ слика</comment>
+ <comment xml:lang="sq">figurë RGB</comment>
+ <comment xml:lang="sl">Slikovna datoteka RGB</comment>
+ <comment xml:lang="si">RGB රූපය</comment>
+ <comment xml:lang="sk">Obrázok RGB</comment>
+ <comment xml:lang="ru">Изображение RGB</comment>
+ <comment xml:lang="ro">Imagine RGB</comment>
+ <comment xml:lang="pt_BR">Imagem RGB</comment>
+ <comment xml:lang="pt">imagem RGB</comment>
+ <comment xml:lang="pl">Obraz RGB</comment>
+ <comment xml:lang="oc">imatge RGB</comment>
+ <comment xml:lang="nn">RGB-bilete</comment>
+ <comment xml:lang="nl">RGB-afbeelding</comment>
+ <comment xml:lang="nb">RGB-bilde</comment>
+ <comment xml:lang="ms">Imej RGB</comment>
+ <comment xml:lang="lv">RGB attēls</comment>
+ <comment xml:lang="lt">RGB paveikslėlis</comment>
+ <comment xml:lang="ko">RGB 그림</comment>
+ <comment xml:lang="kk">RGB суреті</comment>
+ <comment xml:lang="ja">RGB 画像</comment>
+ <comment xml:lang="it">Immagine RGB</comment>
+ <comment xml:lang="is">RGB mynd</comment>
+ <comment xml:lang="id">Citra RGB</comment>
+ <comment xml:lang="ia">Imagine RGB</comment>
+ <comment xml:lang="hu">RGB-kép</comment>
+ <comment xml:lang="hr">RGB slika</comment>
+ <comment xml:lang="he">תמונת RGB</comment>
+ <comment xml:lang="gl">imaxe RGB</comment>
+ <comment xml:lang="ga">íomhá RGB</comment>
+ <comment xml:lang="fur">imagjin RGB</comment>
+ <comment xml:lang="fr">image RGB</comment>
+ <comment xml:lang="fo">RGB mynd</comment>
+ <comment xml:lang="fi">RGB-kuva</comment>
+ <comment xml:lang="eu">RGB irudia</comment>
+ <comment xml:lang="es">imagen RGB</comment>
+ <comment xml:lang="eo">RGB-bildo</comment>
+ <comment xml:lang="en_GB">RGB image</comment>
+ <comment xml:lang="el">Εικόνα RGB</comment>
+ <comment xml:lang="de">RGB-Bild</comment>
+ <comment xml:lang="da">RGB-billede</comment>
+ <comment xml:lang="cy">Delwedd RGB</comment>
+ <comment xml:lang="cs">obrázek RGB</comment>
+ <comment xml:lang="ca">imatge RGB</comment>
+ <comment xml:lang="bg">Изображение — RGB</comment>
+ <comment xml:lang="be@latin">Vyjava RGB</comment>
+ <comment xml:lang="be">выява RGB</comment>
+ <comment xml:lang="az">RGB rəsmi</comment>
+ <comment xml:lang="ar">صورة RGB</comment>
+ <comment xml:lang="af">RGB-beeld</comment>
<glob pattern="*.rgb"/>
</mime-type>
<mime-type type="image/x-sgi">
<comment>SGI image</comment>
- <comment xml:lang="ar">صورة SGI</comment>
- <comment xml:lang="be@latin">Vyjava SGI</comment>
- <comment xml:lang="bg">Изображение — SGI</comment>
- <comment xml:lang="ca">imatge SGI</comment>
- <comment xml:lang="cs">obrázek SGI</comment>
- <comment xml:lang="da">SGI-billede</comment>
- <comment xml:lang="de">SGI-Bild</comment>
- <comment xml:lang="el">Εικόνα SGI</comment>
- <comment xml:lang="en_GB">SGI image</comment>
- <comment xml:lang="eo">SGI-bildo</comment>
- <comment xml:lang="es">imagen SGI</comment>
- <comment xml:lang="eu">SGI irudia</comment>
- <comment xml:lang="fi">SGI-kuva</comment>
- <comment xml:lang="fo">SGI mynd</comment>
- <comment xml:lang="fr">image SGI</comment>
- <comment xml:lang="ga">íomhá SGI</comment>
- <comment xml:lang="gl">imaxe SGI</comment>
- <comment xml:lang="he">תמונת SGI</comment>
- <comment xml:lang="hr">SGI slika</comment>
- <comment xml:lang="hu">SGI kép</comment>
- <comment xml:lang="ia">Imagine SGI</comment>
- <comment xml:lang="id">Citra SGI</comment>
- <comment xml:lang="it">Immagine SGI</comment>
- <comment xml:lang="ja">SGI 画像</comment>
- <comment xml:lang="kk">SGI суреті</comment>
- <comment xml:lang="ko">SGI 그림</comment>
- <comment xml:lang="lt">SGI paveikslėlis</comment>
- <comment xml:lang="lv">SGI attēls</comment>
- <comment xml:lang="nb">SGI-bilde</comment>
- <comment xml:lang="nl">SGI-afbeelding</comment>
- <comment xml:lang="nn">SGI-bilete</comment>
- <comment xml:lang="oc">imatge SGI</comment>
- <comment xml:lang="pl">Obraz SGI</comment>
- <comment xml:lang="pt">imagem SGI</comment>
- <comment xml:lang="pt_BR">Imagem SGI</comment>
- <comment xml:lang="ro">Imagine SGI</comment>
- <comment xml:lang="ru">Изображение SGI</comment>
- <comment xml:lang="sk">Obrázok SGI</comment>
- <comment xml:lang="sl">Slikovna datoteka SGI</comment>
- <comment xml:lang="sq">Figurë SGI</comment>
- <comment xml:lang="sr">СГИ слика</comment>
- <comment xml:lang="sv">SGI-bild</comment>
- <comment xml:lang="tr">SGI görüntüsü</comment>
- <comment xml:lang="uk">зображення SGI</comment>
- <comment xml:lang="vi">Ảnh SGI</comment>
- <comment xml:lang="zh_CN">SGI 图像</comment>
<comment xml:lang="zh_TW">SGI 影像</comment>
+ <comment xml:lang="zh_CN">SGI 图像</comment>
+ <comment xml:lang="vi">Ảnh SGI</comment>
+ <comment xml:lang="uk">зображення SGI</comment>
+ <comment xml:lang="tr">SGI görüntüsü</comment>
+ <comment xml:lang="sv">SGI-bild</comment>
+ <comment xml:lang="sr">СГИ слика</comment>
+ <comment xml:lang="sq">figurë SGI</comment>
+ <comment xml:lang="sl">Slikovna datoteka SGI</comment>
+ <comment xml:lang="si">SGI රූපය</comment>
+ <comment xml:lang="sk">Obrázok SGI</comment>
+ <comment xml:lang="ru">Изображение SGI</comment>
+ <comment xml:lang="ro">Imagine SGI</comment>
+ <comment xml:lang="pt_BR">Imagem SGI</comment>
+ <comment xml:lang="pt">imagem SGI</comment>
+ <comment xml:lang="pl">Obraz SGI</comment>
+ <comment xml:lang="oc">imatge SGI</comment>
+ <comment xml:lang="nn">SGI-bilete</comment>
+ <comment xml:lang="nl">SGI-afbeelding</comment>
+ <comment xml:lang="nb">SGI-bilde</comment>
+ <comment xml:lang="lv">SGI attēls</comment>
+ <comment xml:lang="lt">SGI paveikslėlis</comment>
+ <comment xml:lang="ko">SGI 그림</comment>
+ <comment xml:lang="kk">SGI суреті</comment>
+ <comment xml:lang="ja">SGI 画像</comment>
+ <comment xml:lang="it">Immagine SGI</comment>
+ <comment xml:lang="is">SGI mynd</comment>
+ <comment xml:lang="id">Citra SGI</comment>
+ <comment xml:lang="ia">Imagine SGI</comment>
+ <comment xml:lang="hu">SGI kép</comment>
+ <comment xml:lang="hr">SGI slika</comment>
+ <comment xml:lang="he">תמונת SGI</comment>
+ <comment xml:lang="gl">imaxe SGI</comment>
+ <comment xml:lang="ga">íomhá SGI</comment>
+ <comment xml:lang="fur">imagjin SGI</comment>
+ <comment xml:lang="fr">image SGI</comment>
+ <comment xml:lang="fo">SGI mynd</comment>
+ <comment xml:lang="fi">SGI-kuva</comment>
+ <comment xml:lang="eu">SGI irudia</comment>
+ <comment xml:lang="es">imagen SGI</comment>
+ <comment xml:lang="eo">SGI-bildo</comment>
+ <comment xml:lang="en_GB">SGI image</comment>
+ <comment xml:lang="el">Εικόνα SGI</comment>
+ <comment xml:lang="de">SGI-Bild</comment>
+ <comment xml:lang="da">SGI-billede</comment>
+ <comment xml:lang="cs">obrázek SGI</comment>
+ <comment xml:lang="ca">imatge SGI</comment>
+ <comment xml:lang="bg">Изображение — SGI</comment>
+ <comment xml:lang="be@latin">Vyjava SGI</comment>
+ <comment xml:lang="be">выява SGI</comment>
+ <comment xml:lang="ar">صورة SGI</comment>
+ <comment xml:lang="af">SGI-beeld</comment>
<glob pattern="*.sgi"/>
</mime-type>
<mime-type type="image/x-sun-raster">
<comment>Sun raster image</comment>
- <comment xml:lang="ar">صورة Sun raster</comment>
- <comment xml:lang="be@latin">Rastravaja vyjava Sun</comment>
- <comment xml:lang="bg">Изображение — Sun raster</comment>
- <comment xml:lang="ca">imatge ràster Sun</comment>
- <comment xml:lang="cs">rastrový obrázek Sun</comment>
- <comment xml:lang="da">Sun rasterbillede</comment>
- <comment xml:lang="de">Sun-Rasterbild</comment>
- <comment xml:lang="el">Εικόνα Sun raster</comment>
- <comment xml:lang="en_GB">Sun raster image</comment>
- <comment xml:lang="es">imagen rasterizada de Sun</comment>
- <comment xml:lang="eu">Sun raster irudia</comment>
- <comment xml:lang="fi">Sun-rasterikuva</comment>
- <comment xml:lang="fo">Sun raster mynd</comment>
- <comment xml:lang="fr">image raster Sun</comment>
- <comment xml:lang="ga">íomhá rastar Sun</comment>
- <comment xml:lang="gl">imaxe ráster de Sun</comment>
- <comment xml:lang="he">תמונה סרוקה של Sun</comment>
- <comment xml:lang="hr">Sun iscrtana slika</comment>
- <comment xml:lang="hu">SUN raszterkép</comment>
- <comment xml:lang="ia">Imagine raster Sun</comment>
- <comment xml:lang="id">Citra raster Sun</comment>
- <comment xml:lang="it">Immagine raster Sun</comment>
- <comment xml:lang="ja">Sun ラスタ画像</comment>
- <comment xml:lang="kk">Sun растрлық суреті</comment>
- <comment xml:lang="ko">Sun 래스터 그림</comment>
- <comment xml:lang="lt">Sun rastrinis paveikslėlis</comment>
- <comment xml:lang="lv">Sun rastra attēls</comment>
- <comment xml:lang="nb">Sun rasterbilde</comment>
- <comment xml:lang="nl">Sun-rasterafbeelding</comment>
- <comment xml:lang="nn">Sun rasterbilete</comment>
- <comment xml:lang="oc">imatge raster Sun</comment>
- <comment xml:lang="pl">Obraz rastrowy Sun</comment>
- <comment xml:lang="pt">imagem raster Sun</comment>
- <comment xml:lang="pt_BR">Imagem raster da Sun</comment>
- <comment xml:lang="ro">Imagine rasterizată Sun</comment>
- <comment xml:lang="ru">Растровое изображение Sun</comment>
- <comment xml:lang="sk">Rastrový obrázok Sun</comment>
- <comment xml:lang="sl">Slikovna rastrska datoteka Sun</comment>
- <comment xml:lang="sq">Figurë raster Sun</comment>
- <comment xml:lang="sr">слика Сановог растера</comment>
- <comment xml:lang="sv">Sun-rasterbild</comment>
- <comment xml:lang="tr">Sun raster görüntüsü</comment>
- <comment xml:lang="uk">растрове зображення Sun</comment>
- <comment xml:lang="vi">Ảnh mành Sun</comment>
- <comment xml:lang="zh_CN">Sun 光栅图像</comment>
<comment xml:lang="zh_TW">Sun raster 影像</comment>
- <magic priority="50">
- <match value="0x59a66a95" type="big32" offset="0"/>
+ <comment xml:lang="zh_CN">Sun 光栅图像</comment>
+ <comment xml:lang="vi">Ảnh mành Sun</comment>
+ <comment xml:lang="uk">растрове зображення Sun</comment>
+ <comment xml:lang="tr">Sun raster görüntüsü</comment>
+ <comment xml:lang="sv">Sun-rasterbild</comment>
+ <comment xml:lang="sr">слика Сановог растера</comment>
+ <comment xml:lang="sq">figurë raster Sun</comment>
+ <comment xml:lang="sl">Slikovna rastrska datoteka Sun</comment>
+ <comment xml:lang="si">හිරු රස්ටර් රූපය</comment>
+ <comment xml:lang="sk">Rastrový obrázok Sun</comment>
+ <comment xml:lang="ru">Растровое изображение Sun</comment>
+ <comment xml:lang="ro">Imagine rasterizată Sun</comment>
+ <comment xml:lang="pt_BR">Imagem raster da Sun</comment>
+ <comment xml:lang="pt">imagem raster Sun</comment>
+ <comment xml:lang="pl">Obraz rastrowy Sun</comment>
+ <comment xml:lang="oc">imatge raster Sun</comment>
+ <comment xml:lang="nn">Sun rasterbilete</comment>
+ <comment xml:lang="nl">Sun-rasterafbeelding</comment>
+ <comment xml:lang="nb">Sun rasterbilde</comment>
+ <comment xml:lang="lv">Sun rastra attēls</comment>
+ <comment xml:lang="lt">Sun rastrinis paveikslėlis</comment>
+ <comment xml:lang="ko">Sun 래스터 그림</comment>
+ <comment xml:lang="kk">Sun растрлық суреті</comment>
+ <comment xml:lang="ja">Sun ラスタ画像</comment>
+ <comment xml:lang="it">Immagine raster Sun</comment>
+ <comment xml:lang="is">Sun rastamynd</comment>
+ <comment xml:lang="id">Citra raster Sun</comment>
+ <comment xml:lang="ia">Imagine raster Sun</comment>
+ <comment xml:lang="hu">SUN raszterkép</comment>
+ <comment xml:lang="hr">Sun iscrtana slika</comment>
+ <comment xml:lang="he">תמונה סרוקה של Sun</comment>
+ <comment xml:lang="gl">imaxe ráster de Sun</comment>
+ <comment xml:lang="ga">íomhá rastar Sun</comment>
+ <comment xml:lang="fur">imagjin raster Sun</comment>
+ <comment xml:lang="fr">image raster Sun</comment>
+ <comment xml:lang="fo">Sun raster mynd</comment>
+ <comment xml:lang="fi">Sun-rasterikuva</comment>
+ <comment xml:lang="eu">Sun raster irudia</comment>
+ <comment xml:lang="es">imagen rasterizada de Sun</comment>
+ <comment xml:lang="en_GB">Sun raster image</comment>
+ <comment xml:lang="el">Εικόνα Sun raster</comment>
+ <comment xml:lang="de">Sun-Rasterbild</comment>
+ <comment xml:lang="da">Sun rasterbillede</comment>
+ <comment xml:lang="cs">rastrový obrázek Sun</comment>
+ <comment xml:lang="ca">imatge ràster Sun</comment>
+ <comment xml:lang="bg">Изображение — Sun raster</comment>
+ <comment xml:lang="be@latin">Rastravaja vyjava Sun</comment>
+ <comment xml:lang="be">выява Sun raster</comment>
+ <comment xml:lang="ar">صورة Sun raster</comment>
+ <comment xml:lang="af">Sun-roosterbeeld</comment>
+ <magic>
+ <match type="big32" value="0x59a66a95" offset="0"/>
</magic>
<glob pattern="*.sun"/>
</mime-type>
<mime-type type="image/x-tga">
<comment>TGA image</comment>
- <comment xml:lang="ar">صورة TGA</comment>
- <comment xml:lang="be@latin">Vyjava TGA</comment>
- <comment xml:lang="bg">Изображение — TGA</comment>
- <comment xml:lang="ca">imatge TGA</comment>
- <comment xml:lang="cs">obrázek TGA</comment>
- <comment xml:lang="da">TGA-billede</comment>
- <comment xml:lang="de">TGA-Bild</comment>
- <comment xml:lang="el">Εικόνα TGA</comment>
- <comment xml:lang="en_GB">TGA image</comment>
- <comment xml:lang="eo">TGA-bildo</comment>
- <comment xml:lang="es">imagen TGA</comment>
- <comment xml:lang="eu">TGA irudia</comment>
- <comment xml:lang="fi">TGA-kuva</comment>
- <comment xml:lang="fo">TGA mynd</comment>
- <comment xml:lang="fr">image TGA</comment>
- <comment xml:lang="ga">íomhá TGA</comment>
- <comment xml:lang="gl">imaxe TGA</comment>
- <comment xml:lang="he">תמונת TGA</comment>
- <comment xml:lang="hr">TGA slika</comment>
- <comment xml:lang="hu">TGA kép</comment>
- <comment xml:lang="ia">Imagine TGA</comment>
- <comment xml:lang="id">Citra TGA</comment>
- <comment xml:lang="it">Immagine TGA</comment>
- <comment xml:lang="ja">TGA 画像</comment>
- <comment xml:lang="kk">TGA суреті</comment>
- <comment xml:lang="ko">TGA 그림</comment>
- <comment xml:lang="lt">TGA paveikslėlis</comment>
- <comment xml:lang="lv">TGA attēls</comment>
- <comment xml:lang="nb">TGA-bilde</comment>
- <comment xml:lang="nl">TGA-afbeelding</comment>
- <comment xml:lang="nn">TGA-bilete</comment>
- <comment xml:lang="oc">imatge TGA</comment>
- <comment xml:lang="pl">Obraz TGA</comment>
- <comment xml:lang="pt">imagem TGA</comment>
- <comment xml:lang="pt_BR">Imagem TGA</comment>
- <comment xml:lang="ro">Imagine TGA</comment>
- <comment xml:lang="ru">Изображение TGA</comment>
- <comment xml:lang="sk">Obrázok TGA</comment>
- <comment xml:lang="sl">Slikovna datoteka TGA</comment>
- <comment xml:lang="sq">Figurë TGA</comment>
- <comment xml:lang="sr">ТГА слика</comment>
- <comment xml:lang="sv">TGA-bild</comment>
- <comment xml:lang="tr">TGA görüntüsü</comment>
- <comment xml:lang="uk">зображення TGA</comment>
- <comment xml:lang="vi">Ảnh TGA</comment>
- <comment xml:lang="zh_CN">TGA 图像</comment>
<comment xml:lang="zh_TW">TGA 影像</comment>
+ <comment xml:lang="zh_CN">TGA 图像</comment>
+ <comment xml:lang="vi">Ảnh TGA</comment>
+ <comment xml:lang="uk">зображення TGA</comment>
+ <comment xml:lang="tr">TGA görüntüsü</comment>
+ <comment xml:lang="sv">TGA-bild</comment>
+ <comment xml:lang="sr">ТГА слика</comment>
+ <comment xml:lang="sq">figurë TGA</comment>
+ <comment xml:lang="sl">Slikovna datoteka TGA</comment>
+ <comment xml:lang="si">TGA රූපය</comment>
+ <comment xml:lang="sk">Obrázok TGA</comment>
+ <comment xml:lang="ru">Изображение TGA</comment>
+ <comment xml:lang="ro">Imagine TGA</comment>
+ <comment xml:lang="pt_BR">Imagem TGA</comment>
+ <comment xml:lang="pt">imagem TGA</comment>
+ <comment xml:lang="pl">Obraz TGA</comment>
+ <comment xml:lang="oc">imatge TGA</comment>
+ <comment xml:lang="nn">TGA-bilete</comment>
+ <comment xml:lang="nl">TGA-afbeelding</comment>
+ <comment xml:lang="nb">TGA-bilde</comment>
+ <comment xml:lang="lv">TGA attēls</comment>
+ <comment xml:lang="lt">TGA paveikslėlis</comment>
+ <comment xml:lang="ko">TGA 그림</comment>
+ <comment xml:lang="kk">TGA суреті</comment>
+ <comment xml:lang="ja">TGA 画像</comment>
+ <comment xml:lang="it">Immagine TGA</comment>
+ <comment xml:lang="is">TGA mynd</comment>
+ <comment xml:lang="id">Citra TGA</comment>
+ <comment xml:lang="ia">Imagine TGA</comment>
+ <comment xml:lang="hu">TGA kép</comment>
+ <comment xml:lang="hr">TGA slika</comment>
+ <comment xml:lang="he">תמונת TGA</comment>
+ <comment xml:lang="gl">imaxe TGA</comment>
+ <comment xml:lang="ga">íomhá TGA</comment>
+ <comment xml:lang="fur">imagjin TGA</comment>
+ <comment xml:lang="fr">image TGA</comment>
+ <comment xml:lang="fo">TGA mynd</comment>
+ <comment xml:lang="fi">TGA-kuva</comment>
+ <comment xml:lang="eu">TGA irudia</comment>
+ <comment xml:lang="es">imagen TGA</comment>
+ <comment xml:lang="eo">TGA-bildo</comment>
+ <comment xml:lang="en_GB">TGA image</comment>
+ <comment xml:lang="el">Εικόνα TGA</comment>
+ <comment xml:lang="de">TGA-Bild</comment>
+ <comment xml:lang="da">TGA-billede</comment>
+ <comment xml:lang="cs">obrázek TGA</comment>
+ <comment xml:lang="ca">imatge TGA</comment>
+ <comment xml:lang="bg">Изображение — TGA</comment>
+ <comment xml:lang="be@latin">Vyjava TGA</comment>
+ <comment xml:lang="be">выява TGA</comment>
+ <comment xml:lang="ar">صورة TGA</comment>
+ <comment xml:lang="af">TGA-beeld</comment>
<acronym>TGA</acronym>
<expanded-acronym>Truevision Graphics Adapter</expanded-acronym>
<magic priority="10">
- <match value="\1\1" type="string" offset="1"/>
- <match value="\1\11" type="string" offset="1"/>
- <match value="\0\3" type="string" offset="1"/>
- <match value="\0\xa" type="string" offset="1"/>
- <match value="\0\xb" type="string" offset="1"/>
+ <match type="string" value="\1\1" offset="1"/>
+ <match type="string" value="\1\11" offset="1"/>
+ <match type="string" value="\0\3" offset="1"/>
+ <match type="string" value="\0\xa" offset="1"/>
+ <match type="string" value="\0\xb" offset="1"/>
</magic>
- <magic priority="50">
- <match value="\0\2" type="string" offset="1">
- <match value="0x08" type="byte" offset="16"/>
- <match value="0x10" type="byte" offset="16"/>
- <match value="0x18" type="byte" offset="16"/>
- <match value="0x20" type="byte" offset="16"/>
+ <magic>
+ <match type="string" value="\0\2" offset="1">
+ <match type="byte" value="0x08" offset="16"/>
+ <match type="byte" value="0x10" offset="16"/>
+ <match type="byte" value="0x18" offset="16"/>
+ <match type="byte" value="0x20" offset="16"/>
</match>
</magic>
<glob pattern="*.tga"/>
@@ -29471,180 +32156,202 @@
<glob pattern="*.tpic"/>
<glob pattern="*.vda"/>
<glob pattern="*.vst"/>
+ <alias type="application/tga"/>
+ <alias type="application/x-targa"/>
+ <alias type="application/x-tga"/>
+ <alias type="image/targa"/>
+ <alias type="image/tga"/>
<alias type="image/x-icb"/>
+ <alias type="image/x-targa"/>
</mime-type>
<mime-type type="image/x-win-bitmap">
<comment>Windows cursor</comment>
- <comment xml:lang="ar">مؤشر ويندوز</comment>
- <comment xml:lang="be@latin">Kursor Windows</comment>
- <comment xml:lang="bg">Курсор — Windows</comment>
- <comment xml:lang="ca">cursor de Windows</comment>
- <comment xml:lang="cs">kurzor Windows</comment>
- <comment xml:lang="da">Windowsmarkør</comment>
- <comment xml:lang="de">Windows-Cursor</comment>
- <comment xml:lang="el">Δρομέας Windows</comment>
- <comment xml:lang="en_GB">Windows cursor</comment>
- <comment xml:lang="eo">Windows-kursoro</comment>
- <comment xml:lang="es">cursor de Windows</comment>
- <comment xml:lang="eu">Windows kurtsorea</comment>
- <comment xml:lang="fi">Windows-osoitin</comment>
- <comment xml:lang="fo">Windows vísi</comment>
- <comment xml:lang="fr">curseur Windows</comment>
- <comment xml:lang="ga">cúrsóir Windows</comment>
- <comment xml:lang="gl">Cursor de Windows</comment>
- <comment xml:lang="he">סמן של Windows</comment>
- <comment xml:lang="hr">Windows pokazivač</comment>
- <comment xml:lang="hu">Windows-kurzor</comment>
- <comment xml:lang="ia">Cursor pro Windows</comment>
- <comment xml:lang="id">Kursor Windows</comment>
- <comment xml:lang="it">Cursore Windows</comment>
- <comment xml:lang="ja">Windows カーソル</comment>
- <comment xml:lang="kk">Windows курсоры</comment>
- <comment xml:lang="ko">Windows 커서</comment>
- <comment xml:lang="lt">Windows žymiklis</comment>
- <comment xml:lang="lv">Windows kursors</comment>
- <comment xml:lang="ms">Kursor Windows</comment>
- <comment xml:lang="nb">Windows-markør</comment>
- <comment xml:lang="nl">Windows-muisaanwijzer</comment>
- <comment xml:lang="nn">Windows-peikar</comment>
- <comment xml:lang="oc">cursor Windows</comment>
- <comment xml:lang="pl">Kursor Windows</comment>
- <comment xml:lang="pt">cursor Windows</comment>
- <comment xml:lang="pt_BR">Cursor do Windows</comment>
- <comment xml:lang="ro">Cursor Windows</comment>
- <comment xml:lang="ru">Курсор Windows</comment>
- <comment xml:lang="sk">Kurzor Windows</comment>
- <comment xml:lang="sl">Datoteka kazalke Windows</comment>
- <comment xml:lang="sq">Kursor Windows</comment>
- <comment xml:lang="sr">Виндоузов курсор</comment>
- <comment xml:lang="sv">Windows-muspekare</comment>
- <comment xml:lang="tr">Windows imleci</comment>
- <comment xml:lang="uk">курсор Windows</comment>
- <comment xml:lang="vi">Con chạy Windows</comment>
- <comment xml:lang="zh_CN">Windows 光标</comment>
<comment xml:lang="zh_TW">Windows 滑鼠游標</comment>
- <magic priority="50">
- <match value="\0\0\2\0" type="string" offset="0">
- <match value="\0" type="string" offset="5"/>
+ <comment xml:lang="zh_CN">Windows 光标</comment>
+ <comment xml:lang="vi">Con chạy Windows</comment>
+ <comment xml:lang="uk">курсор Windows</comment>
+ <comment xml:lang="tr">Windows imleci</comment>
+ <comment xml:lang="sv">Windows-muspekare</comment>
+ <comment xml:lang="sr">Виндоузов курсор</comment>
+ <comment xml:lang="sq">kursor Windows</comment>
+ <comment xml:lang="sl">Datoteka kazalke Windows</comment>
+ <comment xml:lang="si">වින්ඩෝස් කර්සරය</comment>
+ <comment xml:lang="sk">Kurzor Windows</comment>
+ <comment xml:lang="ru">Курсор Windows</comment>
+ <comment xml:lang="ro">Cursor Windows</comment>
+ <comment xml:lang="pt_BR">Cursor do Windows</comment>
+ <comment xml:lang="pt">cursor Windows</comment>
+ <comment xml:lang="pl">Kursor Windows</comment>
+ <comment xml:lang="oc">cursor Windows</comment>
+ <comment xml:lang="nn">Windows-peikar</comment>
+ <comment xml:lang="nl">Windows-muisaanwijzer</comment>
+ <comment xml:lang="nb">Windows-markør</comment>
+ <comment xml:lang="ms">Kursor Windows</comment>
+ <comment xml:lang="lv">Windows kursors</comment>
+ <comment xml:lang="lt">Windows žymeklis</comment>
+ <comment xml:lang="ko">Windows 커서</comment>
+ <comment xml:lang="kk">Windows курсоры</comment>
+ <comment xml:lang="ja">Windows カーソル</comment>
+ <comment xml:lang="it">Cursore Windows</comment>
+ <comment xml:lang="is">Windows bendill</comment>
+ <comment xml:lang="id">Kursor Windows</comment>
+ <comment xml:lang="ia">Cursor pro Windows</comment>
+ <comment xml:lang="hu">Windows-kurzor</comment>
+ <comment xml:lang="hr">Windows pokazivač</comment>
+ <comment xml:lang="he">סמן של Windows</comment>
+ <comment xml:lang="gl">Cursor de Windows</comment>
+ <comment xml:lang="ga">cúrsóir Windows</comment>
+ <comment xml:lang="fur">cursôr di Windows</comment>
+ <comment xml:lang="fr">curseur Windows</comment>
+ <comment xml:lang="fo">Windows vísi</comment>
+ <comment xml:lang="fi">Windows-osoitin</comment>
+ <comment xml:lang="eu">Windows kurtsorea</comment>
+ <comment xml:lang="es">cursor de Windows</comment>
+ <comment xml:lang="eo">Windows-kursoro</comment>
+ <comment xml:lang="en_GB">Windows cursor</comment>
+ <comment xml:lang="el">Δρομέας Windows</comment>
+ <comment xml:lang="de">Windows-Mauszeiger</comment>
+ <comment xml:lang="da">Windowsmarkør</comment>
+ <comment xml:lang="cs">kurzor Windows</comment>
+ <comment xml:lang="ca">cursor de Windows</comment>
+ <comment xml:lang="bg">Курсор — Windows</comment>
+ <comment xml:lang="be@latin">Kursor Windows</comment>
+ <comment xml:lang="be">курсор Windows</comment>
+ <comment xml:lang="ar">مؤشر ويندوز</comment>
+ <comment xml:lang="af">Windows-wyser</comment>
+ <magic>
+ <match type="string" value="\0\0\2\0" offset="0">
+ <match type="string" value="\0" offset="5"/>
</match>
</magic>
<glob pattern="*.cur"/>
</mime-type>
<mime-type type="application/x-navi-animation">
<comment>Windows animated cursor</comment>
- <comment xml:lang="ar">مؤشر ويندوز المتحرك</comment>
- <comment xml:lang="be@latin">Animavany kursor Windows</comment>
- <comment xml:lang="bg">Курсор — Windows, анимиран</comment>
- <comment xml:lang="ca">cursor animat de Windows</comment>
- <comment xml:lang="cs">animovaný kurzor Windows</comment>
- <comment xml:lang="da">Windowsanimeret markør</comment>
- <comment xml:lang="de">Animierter Windows-Cursor</comment>
- <comment xml:lang="el">Κινούμενος δρομέας Windows</comment>
- <comment xml:lang="en_GB">Windows animated cursor</comment>
- <comment xml:lang="es">cursor animado de Windows</comment>
- <comment xml:lang="eu">Windows-eko kurtsore animatua</comment>
- <comment xml:lang="fi">animoitu Windows-osoitin</comment>
- <comment xml:lang="fo">Windows livindaigjørdur vísi</comment>
- <comment xml:lang="fr">curseur animé Windows</comment>
- <comment xml:lang="ga">cúrsóir beoite Windows</comment>
- <comment xml:lang="gl">Cursor animado de Windows</comment>
- <comment xml:lang="he">סמן מונפש של Windows</comment>
- <comment xml:lang="hr">Windows animirani pokazivač</comment>
- <comment xml:lang="hu">Windows animált kurzor</comment>
- <comment xml:lang="ia">Cursor animate pro Windows</comment>
- <comment xml:lang="id">Kursor animasi Windows</comment>
- <comment xml:lang="it">Cursore animato Windows</comment>
- <comment xml:lang="ja">Windows アニメーションカーソル</comment>
- <comment xml:lang="kk">Windows анимациясы бар курсор</comment>
- <comment xml:lang="ko">Windows 움직이는 커서</comment>
- <comment xml:lang="lt">Animuotas Windows žymiklis</comment>
- <comment xml:lang="lv">Windows animēts kursors</comment>
- <comment xml:lang="nl">geanimeerde Windows-muisaanwijzer</comment>
- <comment xml:lang="nn">Windows animert peikar</comment>
- <comment xml:lang="oc">cursor animat Windows</comment>
- <comment xml:lang="pl">Animowany kursor Windows</comment>
- <comment xml:lang="pt">cursor animado Windows</comment>
- <comment xml:lang="pt_BR">Cursor animado do Windows</comment>
- <comment xml:lang="ro">Cursor animat Windows</comment>
- <comment xml:lang="ru">Анимированный курсор Windows</comment>
- <comment xml:lang="sk">Animovaný kurzor Windows</comment>
- <comment xml:lang="sl">Datoteka animirane kazalke Windows</comment>
- <comment xml:lang="sq">Kursor i animuar Windows</comment>
- <comment xml:lang="sr">Виндоузов анимирани курсор</comment>
- <comment xml:lang="sv">Animerad Windows-muspekare</comment>
- <comment xml:lang="tr">Windows canlandırmalı imleci</comment>
- <comment xml:lang="uk">анімований курсор Windows</comment>
- <comment xml:lang="vi">Con chạy hoạt họa Windows</comment>
- <comment xml:lang="zh_CN">Windows 动态光标</comment>
<comment xml:lang="zh_TW">Windows 滑鼠動畫游標</comment>
- <magic priority="50">
- <match value="RIFF" type="string" offset="0">
- <match value="ACON" type="string" offset="8"/>
+ <comment xml:lang="zh_CN">Windows 动态光标</comment>
+ <comment xml:lang="vi">Con chạy hoạt họa Windows</comment>
+ <comment xml:lang="uk">анімований курсор Windows</comment>
+ <comment xml:lang="tr">Windows canlandırmalı imleci</comment>
+ <comment xml:lang="sv">Animerad Windows-muspekare</comment>
+ <comment xml:lang="sr">Виндоузов анимирани курсор</comment>
+ <comment xml:lang="sq">kursor i animuar Windows</comment>
+ <comment xml:lang="sl">Datoteka animirane kazalke Windows</comment>
+ <comment xml:lang="si">වින්ඩෝස් සජීවිකරණ කර්සරය</comment>
+ <comment xml:lang="sk">Animovaný kurzor Windows</comment>
+ <comment xml:lang="ru">Анимированный курсор Windows</comment>
+ <comment xml:lang="ro">Cursor animat Windows</comment>
+ <comment xml:lang="pt_BR">Cursor animado do Windows</comment>
+ <comment xml:lang="pt">cursor animado Windows</comment>
+ <comment xml:lang="pl">Animowany kursor Windows</comment>
+ <comment xml:lang="oc">cursor animat Windows</comment>
+ <comment xml:lang="nn">Windows animert peikar</comment>
+ <comment xml:lang="nl">geanimeerde Windows-muisaanwijzer</comment>
+ <comment xml:lang="lv">Windows animēts kursors</comment>
+ <comment xml:lang="lt">Animuotas Windows žymeklis</comment>
+ <comment xml:lang="ko">Windows 움직이는 커서</comment>
+ <comment xml:lang="kk">Windows анимациясы бар курсор</comment>
+ <comment xml:lang="ka">Windows -ის ანიმირებული კურსორი</comment>
+ <comment xml:lang="ja">Windows アニメーションカーソル</comment>
+ <comment xml:lang="it">Cursore animato Windows</comment>
+ <comment xml:lang="is">Windows hreyfibendill</comment>
+ <comment xml:lang="id">Kursor animasi Windows</comment>
+ <comment xml:lang="ia">Cursor animate pro Windows</comment>
+ <comment xml:lang="hu">Windows animált kurzor</comment>
+ <comment xml:lang="hr">Windows animirani pokazivač</comment>
+ <comment xml:lang="he">סמן מונפש של Windows</comment>
+ <comment xml:lang="gl">Cursor animado de Windows</comment>
+ <comment xml:lang="ga">cúrsóir beoite Windows</comment>
+ <comment xml:lang="fur">cursôr animât di Windows</comment>
+ <comment xml:lang="fr">curseur animé Windows</comment>
+ <comment xml:lang="fo">Windows livindaigjørdur vísi</comment>
+ <comment xml:lang="fi">animoitu Windows-osoitin</comment>
+ <comment xml:lang="eu">Windows-eko kurtsore animatua</comment>
+ <comment xml:lang="es">cursor animado de Windows</comment>
+ <comment xml:lang="en_GB">Windows animated cursor</comment>
+ <comment xml:lang="el">Κινούμενος δρομέας Windows</comment>
+ <comment xml:lang="de">Animierter Windows-Mauszeiger</comment>
+ <comment xml:lang="da">Windowsanimeret markør</comment>
+ <comment xml:lang="cs">animovaný kurzor Windows</comment>
+ <comment xml:lang="ca">cursor animat de Windows</comment>
+ <comment xml:lang="bg">Курсор — Windows, анимиран</comment>
+ <comment xml:lang="be@latin">Animavany kursor Windows</comment>
+ <comment xml:lang="be">анімаваны курсор Windows</comment>
+ <comment xml:lang="ar">مؤشر ويندوز متحرك</comment>
+ <comment xml:lang="af">Windows geanimeerde wyser</comment>
+ <magic>
+ <match type="string" value="RIFF" offset="0">
+ <match type="string" value="ACON" offset="8"/>
</match>
</magic>
<glob pattern="*.ani"/>
</mime-type>
<mime-type type="image/emf">
<comment>EMF image</comment>
- <comment xml:lang="ar">صورة EMF</comment>
- <comment xml:lang="be@latin">Vyjava EMF</comment>
- <comment xml:lang="bg">Изображение — EMF</comment>
- <comment xml:lang="ca">imatge EMF</comment>
- <comment xml:lang="cs">obrázek EMF</comment>
- <comment xml:lang="da">EMF-billede</comment>
- <comment xml:lang="de">EMF-Bild</comment>
- <comment xml:lang="el">Εικόνα EMF</comment>
- <comment xml:lang="en_GB">EMF image</comment>
- <comment xml:lang="eo">EMF-bildo</comment>
- <comment xml:lang="es">imagen EMF</comment>
- <comment xml:lang="eu">EMF irudia</comment>
- <comment xml:lang="fi">EMF-kuva</comment>
- <comment xml:lang="fo">EMF mynd</comment>
- <comment xml:lang="fr">image EMF</comment>
- <comment xml:lang="ga">íomhá EMF</comment>
- <comment xml:lang="gl">imaxe EMF</comment>
- <comment xml:lang="he">תמונת EMF</comment>
- <comment xml:lang="hr">EMF slika</comment>
- <comment xml:lang="hu">EMF kép</comment>
- <comment xml:lang="ia">Imagine EMF</comment>
- <comment xml:lang="id">Citra EMF</comment>
- <comment xml:lang="it">Immagine EMF</comment>
- <comment xml:lang="ja">EMF 画像</comment>
- <comment xml:lang="ka">EMF გამოსახულება</comment>
- <comment xml:lang="kk">EMF суреті</comment>
- <comment xml:lang="ko">EMF 그림</comment>
- <comment xml:lang="lt">EMF paveikslėlis</comment>
- <comment xml:lang="lv">EMF attēls</comment>
- <comment xml:lang="nb">EMF-bilde</comment>
- <comment xml:lang="nl">EMF-afbeelding</comment>
- <comment xml:lang="nn">EMF-bilete</comment>
- <comment xml:lang="oc">imatge EMF</comment>
- <comment xml:lang="pl">Obraz EMF</comment>
- <comment xml:lang="pt">imagem EMF</comment>
- <comment xml:lang="pt_BR">Imagem EMF</comment>
- <comment xml:lang="ro">Imagine EMF</comment>
- <comment xml:lang="ru">Изображение EMF</comment>
- <comment xml:lang="sk">Obrázok EMF</comment>
- <comment xml:lang="sl">Slikovna datoteka EMF</comment>
- <comment xml:lang="sq">Figurë EMF</comment>
- <comment xml:lang="sr">ЕМФ слика</comment>
- <comment xml:lang="sv">EMF-bild</comment>
- <comment xml:lang="tr">EMF görüntüsü</comment>
- <comment xml:lang="uk">зображення EMF</comment>
- <comment xml:lang="vi">Ảnh EMF</comment>
- <comment xml:lang="zh_CN">EMF 图像</comment>
<comment xml:lang="zh_TW">EMF 影像</comment>
+ <comment xml:lang="zh_CN">EMF 图像</comment>
+ <comment xml:lang="vi">Ảnh EMF</comment>
+ <comment xml:lang="uk">зображення EMF</comment>
+ <comment xml:lang="tr">EMF görüntüsü</comment>
+ <comment xml:lang="sv">EMF-bild</comment>
+ <comment xml:lang="sr">ЕМФ слика</comment>
+ <comment xml:lang="sq">figurë EMF</comment>
+ <comment xml:lang="sl">Slikovna datoteka EMF</comment>
+ <comment xml:lang="si">EMF රූපය</comment>
+ <comment xml:lang="sk">Obrázok EMF</comment>
+ <comment xml:lang="ru">Изображение EMF</comment>
+ <comment xml:lang="ro">Imagine EMF</comment>
+ <comment xml:lang="pt_BR">Imagem EMF</comment>
+ <comment xml:lang="pt">imagem EMF</comment>
+ <comment xml:lang="pl">Obraz EMF</comment>
+ <comment xml:lang="oc">imatge EMF</comment>
+ <comment xml:lang="nn">EMF-bilete</comment>
+ <comment xml:lang="nl">EMF-afbeelding</comment>
+ <comment xml:lang="nb">EMF-bilde</comment>
+ <comment xml:lang="lv">EMF attēls</comment>
+ <comment xml:lang="lt">EMF paveikslėlis</comment>
+ <comment xml:lang="ko">EMF 그림</comment>
+ <comment xml:lang="kk">EMF суреті</comment>
+ <comment xml:lang="ka">EMF გამოსახულება</comment>
+ <comment xml:lang="ja">EMF 画像</comment>
+ <comment xml:lang="it">Immagine EMF</comment>
+ <comment xml:lang="is">EMF mynd</comment>
+ <comment xml:lang="id">Citra EMF</comment>
+ <comment xml:lang="ia">Imagine EMF</comment>
+ <comment xml:lang="hu">EMF kép</comment>
+ <comment xml:lang="hr">EMF slika</comment>
+ <comment xml:lang="he">תמונת EMF</comment>
+ <comment xml:lang="gl">imaxe EMF</comment>
+ <comment xml:lang="ga">íomhá EMF</comment>
+ <comment xml:lang="fur">imagjin EMF</comment>
+ <comment xml:lang="fr">image EMF</comment>
+ <comment xml:lang="fo">EMF mynd</comment>
+ <comment xml:lang="fi">EMF-kuva</comment>
+ <comment xml:lang="eu">EMF irudia</comment>
+ <comment xml:lang="es">imagen EMF</comment>
+ <comment xml:lang="eo">EMF-bildo</comment>
+ <comment xml:lang="en_GB">EMF image</comment>
+ <comment xml:lang="el">Εικόνα EMF</comment>
+ <comment xml:lang="de">EMF-Bild</comment>
+ <comment xml:lang="da">EMF-billede</comment>
+ <comment xml:lang="cs">obrázek EMF</comment>
+ <comment xml:lang="ca">imatge EMF</comment>
+ <comment xml:lang="bg">Изображение — EMF</comment>
+ <comment xml:lang="be@latin">Vyjava EMF</comment>
+ <comment xml:lang="be">выява EMF</comment>
+ <comment xml:lang="ar">صورة EMF</comment>
+ <comment xml:lang="af">EMF-beeld</comment>
<acronym>EMF</acronym>
<expanded-acronym>Enhanced MetaFile</expanded-acronym>
<glob pattern="*.emf"/>
<alias type="image/x-emf"/>
<alias type="application/x-emf"/>
<alias type="application/emf"/>
- <magic priority="50">
- <match value="0x00000001" type="little32" offset="0">
- <match value="0x464D4520" type="little32" offset="40">
- <match value="0x00010000" type="little32" offset="44">
- <match value="0x0000" type="little16" offset="58"/>
+ <magic>
+ <match type="little32" offset="0" value="0x00000001">
+ <match type="little32" offset="40" value="0x464D4520">
+ <match type="little32" offset="44" value="0x00010000">
+ <match type="little16" offset="58" value="0x0000"/>
</match>
</match>
</match>
@@ -29652,66 +32359,71 @@
</mime-type>
<mime-type type="image/wmf">
<comment>WMF image</comment>
- <comment xml:lang="ar">صورة WMF</comment>
- <comment xml:lang="be@latin">Vyjava WMF</comment>
- <comment xml:lang="bg">Изображение — WMF</comment>
- <comment xml:lang="ca">imatge WMF</comment>
- <comment xml:lang="cs">obrázek WMF</comment>
- <comment xml:lang="da">WMF-billede</comment>
- <comment xml:lang="de">WMF-Bild</comment>
- <comment xml:lang="el">Εικόνα WML</comment>
- <comment xml:lang="en_GB">WMF image</comment>
- <comment xml:lang="eo">WMF-bildo</comment>
- <comment xml:lang="es">imagen WMF</comment>
- <comment xml:lang="eu">WMF irudia</comment>
- <comment xml:lang="fi">WMF-kuva</comment>
- <comment xml:lang="fo">WMF mynd</comment>
- <comment xml:lang="fr">image WMF</comment>
- <comment xml:lang="ga">íomhá WMF</comment>
- <comment xml:lang="gl">imaxe WMF</comment>
- <comment xml:lang="he">תמונת WMF</comment>
- <comment xml:lang="hr">WMF slika</comment>
- <comment xml:lang="hu">WMF kép</comment>
- <comment xml:lang="ia">Imagine WMF</comment>
- <comment xml:lang="id">Citra WMF</comment>
- <comment xml:lang="it">Immagine WMF</comment>
- <comment xml:lang="ja">WMF 画像</comment>
- <comment xml:lang="kk">WMF суреті</comment>
- <comment xml:lang="ko">WMF 그림</comment>
- <comment xml:lang="lt">WMF paveikslėlis</comment>
- <comment xml:lang="lv">WMF attēls</comment>
- <comment xml:lang="nb">WMF-bilde</comment>
- <comment xml:lang="nl">WMF-afbeelding</comment>
- <comment xml:lang="nn">WMF-bilete</comment>
- <comment xml:lang="oc">imatge WMF</comment>
- <comment xml:lang="pl">Obraz WMF</comment>
- <comment xml:lang="pt">imagem WMF</comment>
- <comment xml:lang="pt_BR">Imagem WMF</comment>
- <comment xml:lang="ro">Imagine WMF</comment>
- <comment xml:lang="ru">Изображение WMF</comment>
- <comment xml:lang="sk">Obrázok WMF</comment>
- <comment xml:lang="sl">Slikovna datoteka WMF</comment>
- <comment xml:lang="sq">Figurë WMF</comment>
- <comment xml:lang="sr">ВМФ слика</comment>
- <comment xml:lang="sv">WMF-bild</comment>
- <comment xml:lang="tr">WMF görüntüsü</comment>
- <comment xml:lang="uk">зображення WMF</comment>
- <comment xml:lang="vi">Ảnh WMF</comment>
- <comment xml:lang="zh_CN">WMF 图像</comment>
<comment xml:lang="zh_TW">WMF 影像</comment>
+ <comment xml:lang="zh_CN">WMF 图像</comment>
+ <comment xml:lang="vi">Ảnh WMF</comment>
+ <comment xml:lang="uk">зображення WMF</comment>
+ <comment xml:lang="tr">WMF görüntüsü</comment>
+ <comment xml:lang="sv">WMF-bild</comment>
+ <comment xml:lang="sr">ВМФ слика</comment>
+ <comment xml:lang="sq">figurë WMF</comment>
+ <comment xml:lang="sl">Slikovna datoteka WMF</comment>
+ <comment xml:lang="si">WMF රූපය</comment>
+ <comment xml:lang="sk">Obrázok WMF</comment>
+ <comment xml:lang="ru">Изображение WMF</comment>
+ <comment xml:lang="ro">Imagine WMF</comment>
+ <comment xml:lang="pt_BR">Imagem WMF</comment>
+ <comment xml:lang="pt">imagem WMF</comment>
+ <comment xml:lang="pl">Obraz WMF</comment>
+ <comment xml:lang="oc">imatge WMF</comment>
+ <comment xml:lang="nn">WMF-bilete</comment>
+ <comment xml:lang="nl">WMF-afbeelding</comment>
+ <comment xml:lang="nb">WMF-bilde</comment>
+ <comment xml:lang="lv">WMF attēls</comment>
+ <comment xml:lang="lt">WMF paveikslėlis</comment>
+ <comment xml:lang="ko">WMF 그림</comment>
+ <comment xml:lang="kk">WMF суреті</comment>
+ <comment xml:lang="ja">WMF 画像</comment>
+ <comment xml:lang="it">Immagine WMF</comment>
+ <comment xml:lang="is">WMF mynd</comment>
+ <comment xml:lang="id">Citra WMF</comment>
+ <comment xml:lang="ia">Imagine WMF</comment>
+ <comment xml:lang="hu">WMF kép</comment>
+ <comment xml:lang="hr">WMF slika</comment>
+ <comment xml:lang="he">תמונת WMF</comment>
+ <comment xml:lang="gl">imaxe WMF</comment>
+ <comment xml:lang="ga">íomhá WMF</comment>
+ <comment xml:lang="fur">imagjin WMF</comment>
+ <comment xml:lang="fr">image WMF</comment>
+ <comment xml:lang="fo">WMF mynd</comment>
+ <comment xml:lang="fi">WMF-kuva</comment>
+ <comment xml:lang="eu">WMF irudia</comment>
+ <comment xml:lang="es">imagen WMF</comment>
+ <comment xml:lang="eo">WMF-bildo</comment>
+ <comment xml:lang="en_GB">WMF image</comment>
+ <comment xml:lang="el">Εικόνα WML</comment>
+ <comment xml:lang="de">WMF-Bild</comment>
+ <comment xml:lang="da">WMF-billede</comment>
+ <comment xml:lang="cs">obrázek WMF</comment>
+ <comment xml:lang="ca">imatge WMF</comment>
+ <comment xml:lang="bg">Изображение — WMF</comment>
+ <comment xml:lang="be@latin">Vyjava WMF</comment>
+ <comment xml:lang="be">выява WMF</comment>
+ <comment xml:lang="ar">صورة WMF</comment>
+ <comment xml:lang="af">WMF-beeld</comment>
<acronym>WMF</acronym>
<expanded-acronym>Windows Metafile</expanded-acronym>
- <magic priority="50">
-
- <match value="0x9AC6CDD7" type="little32" offset="0">
-
- <match value="0x0001" type="little16" offset="22">
- <match value="0x0009" type="little16" offset="24"/>
+ <magic>
+ <!-- Placeable Metafile Header !-->
+ <match type="little32" offset="0" value="0x9AC6CDD7">
+ <!-- Followed by the standard Windows Metafile Header !-->
+ <match type="little16" offset="22" value="0x0001">
+ <match type="little16" offset="24" value="0x0009"/>
</match>
</match>
-
- <match value="0x0001" type="little16" offset="0">
- <match value="0x0009" type="little16" offset="2"/>
+ <!-- or just the standard Windows Metafile Header !-->
+ <match type="little16" offset="0" value="0x0001">
+ <match type="little16" offset="2" value="0x0009"/>
</match>
</magic>
<glob pattern="*.wmf"/>
@@ -29723,1873 +32435,1286 @@
</mime-type>
<mime-type type="image/x-xbitmap">
<comment>XBM image</comment>
- <comment xml:lang="ar">صورة XBM</comment>
- <comment xml:lang="be@latin">Vyjava XBM</comment>
- <comment xml:lang="bg">Изображение — XBM</comment>
- <comment xml:lang="ca">imatge XBM</comment>
- <comment xml:lang="cs">obrázek XBM</comment>
- <comment xml:lang="da">XBM-billede</comment>
- <comment xml:lang="de">XBM-Bild</comment>
- <comment xml:lang="el">Εικόνα XBM</comment>
- <comment xml:lang="en_GB">XBM image</comment>
- <comment xml:lang="eo">XBM-bildo</comment>
- <comment xml:lang="es">imagen XBM</comment>
- <comment xml:lang="eu">XBM irudia</comment>
- <comment xml:lang="fi">XBM-kuva</comment>
- <comment xml:lang="fo">XBM mynd</comment>
- <comment xml:lang="fr">image XBM</comment>
- <comment xml:lang="ga">íomhá XBM</comment>
- <comment xml:lang="gl">imaxe XBM</comment>
- <comment xml:lang="he">תמונת XBM</comment>
- <comment xml:lang="hr">XBM slika</comment>
- <comment xml:lang="hu">XBM-kép</comment>
- <comment xml:lang="ia">Imagine XBM</comment>
- <comment xml:lang="id">Citra XBM</comment>
- <comment xml:lang="it">Immagine XBM</comment>
- <comment xml:lang="ja">XBM 画像</comment>
- <comment xml:lang="kk">XBM суреті</comment>
- <comment xml:lang="ko">XBM 그림</comment>
- <comment xml:lang="lt">XBM paveikslėlis</comment>
- <comment xml:lang="lv">XBM attēls</comment>
- <comment xml:lang="nb">XBM-bilde</comment>
- <comment xml:lang="nl">XBM-afbeelding</comment>
- <comment xml:lang="nn">XBM-bilete</comment>
- <comment xml:lang="oc">imatge XBM</comment>
- <comment xml:lang="pl">Obraz XBM</comment>
- <comment xml:lang="pt">imagem XBM</comment>
- <comment xml:lang="pt_BR">Imagem XBM</comment>
- <comment xml:lang="ro">Imagine XBM</comment>
- <comment xml:lang="ru">Изображение XBM</comment>
- <comment xml:lang="sk">Obrázok XBM</comment>
- <comment xml:lang="sl">Slikovna datoteka XBM</comment>
- <comment xml:lang="sq">Figurë XBM</comment>
- <comment xml:lang="sr">ИксБМ слика</comment>
- <comment xml:lang="sv">XBM-bild</comment>
- <comment xml:lang="tr">XBM görüntüsü</comment>
- <comment xml:lang="uk">зображення XBM</comment>
- <comment xml:lang="vi">Ảnh XBM</comment>
- <comment xml:lang="zh_CN">XBM 图像</comment>
<comment xml:lang="zh_TW">XBM 影像</comment>
+ <comment xml:lang="zh_CN">XBM 图像</comment>
+ <comment xml:lang="vi">Ảnh XBM</comment>
+ <comment xml:lang="uk">зображення XBM</comment>
+ <comment xml:lang="tr">XBM görüntüsü</comment>
+ <comment xml:lang="sv">XBM-bild</comment>
+ <comment xml:lang="sr">ИксБМ слика</comment>
+ <comment xml:lang="sq">figurë XBM</comment>
+ <comment xml:lang="sl">Slikovna datoteka XBM</comment>
+ <comment xml:lang="si">XBM රූපය</comment>
+ <comment xml:lang="sk">Obrázok XBM</comment>
+ <comment xml:lang="ru">Изображение XBM</comment>
+ <comment xml:lang="ro">Imagine XBM</comment>
+ <comment xml:lang="pt_BR">Imagem XBM</comment>
+ <comment xml:lang="pt">imagem XBM</comment>
+ <comment xml:lang="pl">Obraz XBM</comment>
+ <comment xml:lang="oc">imatge XBM</comment>
+ <comment xml:lang="nn">XBM-bilete</comment>
+ <comment xml:lang="nl">XBM-afbeelding</comment>
+ <comment xml:lang="nb">XBM-bilde</comment>
+ <comment xml:lang="lv">XBM attēls</comment>
+ <comment xml:lang="lt">XBM paveikslėlis</comment>
+ <comment xml:lang="ko">XBM 그림</comment>
+ <comment xml:lang="kk">XBM суреті</comment>
+ <comment xml:lang="ja">XBM 画像</comment>
+ <comment xml:lang="it">Immagine XBM</comment>
+ <comment xml:lang="is">XBM mynd</comment>
+ <comment xml:lang="id">Citra XBM</comment>
+ <comment xml:lang="ia">Imagine XBM</comment>
+ <comment xml:lang="hu">XBM-kép</comment>
+ <comment xml:lang="hr">XBM slika</comment>
+ <comment xml:lang="he">תמונת XBM</comment>
+ <comment xml:lang="gl">imaxe XBM</comment>
+ <comment xml:lang="ga">íomhá XBM</comment>
+ <comment xml:lang="fur">imagjin XBM</comment>
+ <comment xml:lang="fr">image XBM</comment>
+ <comment xml:lang="fo">XBM mynd</comment>
+ <comment xml:lang="fi">XBM-kuva</comment>
+ <comment xml:lang="eu">XBM irudia</comment>
+ <comment xml:lang="es">imagen XBM</comment>
+ <comment xml:lang="eo">XBM-bildo</comment>
+ <comment xml:lang="en_GB">XBM image</comment>
+ <comment xml:lang="el">Εικόνα XBM</comment>
+ <comment xml:lang="de">XBM-Bild</comment>
+ <comment xml:lang="da">XBM-billede</comment>
+ <comment xml:lang="cs">obrázek XBM</comment>
+ <comment xml:lang="ca">imatge XBM</comment>
+ <comment xml:lang="bg">Изображение — XBM</comment>
+ <comment xml:lang="be@latin">Vyjava XBM</comment>
+ <comment xml:lang="be">выява XBM</comment>
+ <comment xml:lang="ar">صورة XBM</comment>
+ <comment xml:lang="af">XBM-beeld</comment>
<acronym>XBM</acronym>
<expanded-acronym>X BitMap</expanded-acronym>
<glob pattern="*.xbm"/>
</mime-type>
<mime-type type="image/x-xcf">
<comment>GIMP image</comment>
- <comment xml:lang="ar">صورة GIMP</comment>
- <comment xml:lang="be@latin">Vyjava GIMP</comment>
- <comment xml:lang="bg">Изображение — GIMP</comment>
- <comment xml:lang="ca">imatge de GIMP</comment>
- <comment xml:lang="cs">obrázek GIMP</comment>
- <comment xml:lang="da">GIMP-billede</comment>
- <comment xml:lang="de">GIMP-Bild</comment>
- <comment xml:lang="el">Εικόνα GIMP</comment>
- <comment xml:lang="en_GB">GIMP image</comment>
- <comment xml:lang="eo">GIMP-bildo</comment>
- <comment xml:lang="es">imagen del GIMP</comment>
- <comment xml:lang="eu">GIMP irudia</comment>
- <comment xml:lang="fi">GIMP-kuva</comment>
- <comment xml:lang="fo">GIMP mynd</comment>
- <comment xml:lang="fr">image GIMP</comment>
- <comment xml:lang="ga">íomhá GIMP</comment>
- <comment xml:lang="gl">imaxe de GIMP</comment>
- <comment xml:lang="he">תמונת GIMP</comment>
- <comment xml:lang="hr">GIMP slika</comment>
- <comment xml:lang="hu">GIMP-kép</comment>
- <comment xml:lang="ia">Imagine GIMP</comment>
- <comment xml:lang="id">Citra GIMP</comment>
- <comment xml:lang="it">Immagine GIMP</comment>
- <comment xml:lang="ja">GIMP 画像</comment>
- <comment xml:lang="ka">GIMP გამოსახულება</comment>
- <comment xml:lang="kk">GIMP суреті</comment>
- <comment xml:lang="ko">GIMP 그림</comment>
- <comment xml:lang="lt">GIMP paveikslėlis</comment>
- <comment xml:lang="lv">GIMP attēls</comment>
- <comment xml:lang="ms">Imej GIMP</comment>
- <comment xml:lang="nb">GIMP-bilde</comment>
- <comment xml:lang="nl">GIMP-afbeelding</comment>
- <comment xml:lang="nn">GIMP-bilete</comment>
- <comment xml:lang="oc">imatge GIMP</comment>
- <comment xml:lang="pl">Obraz GIMP</comment>
- <comment xml:lang="pt">imagem GIMP</comment>
- <comment xml:lang="pt_BR">Imagem do GIMP</comment>
- <comment xml:lang="ro">Imagine GIMP</comment>
- <comment xml:lang="ru">Изображение GIMP</comment>
- <comment xml:lang="sk">Obrázok GIMP</comment>
- <comment xml:lang="sl">Slikovna datoteka GIMP</comment>
- <comment xml:lang="sq">Figurë GIMP</comment>
- <comment xml:lang="sr">Гимпова слика</comment>
- <comment xml:lang="sv">GIMP-bild</comment>
- <comment xml:lang="tr">GIMP görüntüsü</comment>
- <comment xml:lang="uk">зображення GIMP</comment>
- <comment xml:lang="vi">Ảnh GIMP</comment>
- <comment xml:lang="zh_CN">GIMP 图像</comment>
<comment xml:lang="zh_TW">GIMP 影像</comment>
+ <comment xml:lang="zh_CN">GIMP 图像</comment>
+ <comment xml:lang="vi">Ảnh GIMP</comment>
+ <comment xml:lang="uk">зображення GIMP</comment>
+ <comment xml:lang="tr">GIMP görüntüsü</comment>
+ <comment xml:lang="sv">GIMP-bild</comment>
+ <comment xml:lang="sr">Гимпова слика</comment>
+ <comment xml:lang="sq">figurë GIMP</comment>
+ <comment xml:lang="sl">Slikovna datoteka GIMP</comment>
+ <comment xml:lang="si">GIMP රූපය</comment>
+ <comment xml:lang="sk">Obrázok GIMP</comment>
+ <comment xml:lang="ru">Изображение GIMP</comment>
+ <comment xml:lang="ro">Imagine GIMP</comment>
+ <comment xml:lang="pt_BR">Imagem do GIMP</comment>
+ <comment xml:lang="pt">imagem GIMP</comment>
+ <comment xml:lang="pl">Obraz GIMP</comment>
+ <comment xml:lang="oc">imatge GIMP</comment>
+ <comment xml:lang="nn">GIMP-bilete</comment>
+ <comment xml:lang="nl">GIMP-afbeelding</comment>
+ <comment xml:lang="nb">GIMP-bilde</comment>
+ <comment xml:lang="ms">Imej GIMP</comment>
+ <comment xml:lang="lv">GIMP attēls</comment>
+ <comment xml:lang="lt">GIMP paveikslėlis</comment>
+ <comment xml:lang="ko">GIMP 그림</comment>
+ <comment xml:lang="kk">GIMP суреті</comment>
+ <comment xml:lang="ka">GIMP გამოსახულება</comment>
+ <comment xml:lang="ja">GIMP 画像</comment>
+ <comment xml:lang="it">Immagine GIMP</comment>
+ <comment xml:lang="is">GIMP mynd</comment>
+ <comment xml:lang="id">Citra GIMP</comment>
+ <comment xml:lang="ia">Imagine GIMP</comment>
+ <comment xml:lang="hu">GIMP-kép</comment>
+ <comment xml:lang="hr">GIMP slika</comment>
+ <comment xml:lang="he">תמונת GIMP</comment>
+ <comment xml:lang="gl">imaxe de GIMP</comment>
+ <comment xml:lang="ga">íomhá GIMP</comment>
+ <comment xml:lang="fur">imagjin GIMP</comment>
+ <comment xml:lang="fr">image GIMP</comment>
+ <comment xml:lang="fo">GIMP mynd</comment>
+ <comment xml:lang="fi">GIMP-kuva</comment>
+ <comment xml:lang="eu">GIMP irudia</comment>
+ <comment xml:lang="es">imagen del GIMP</comment>
+ <comment xml:lang="eo">GIMP-bildo</comment>
+ <comment xml:lang="en_GB">GIMP image</comment>
+ <comment xml:lang="el">Εικόνα GIMP</comment>
+ <comment xml:lang="de">GIMP-Bild</comment>
+ <comment xml:lang="da">GIMP-billede</comment>
+ <comment xml:lang="cs">obrázek GIMP</comment>
+ <comment xml:lang="ca">imatge de GIMP</comment>
+ <comment xml:lang="bg">Изображение — GIMP</comment>
+ <comment xml:lang="be@latin">Vyjava GIMP</comment>
+ <comment xml:lang="be">выява GIMP</comment>
+ <comment xml:lang="ar">صورة GIMP</comment>
+ <comment xml:lang="af">GIMP-beeld</comment>
<glob pattern="*.xcf"/>
- <magic priority="50">
- <match value="gimp xcf file" type="string" offset="0"/>
- <match value="gimp xcf v" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="gimp xcf file" offset="0"/>
+ <match type="string" value="gimp xcf v" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/x-gimp-gbr">
<comment>GIMP brush</comment>
- <comment xml:lang="ca">pinzell de GIMP</comment>
- <comment xml:lang="cs">štětec GIMP</comment>
- <comment xml:lang="de">GIMP-Pinsel</comment>
- <comment xml:lang="en_GB">GIMP brush</comment>
- <comment xml:lang="es">pincel del GIMP</comment>
- <comment xml:lang="hr">GIMP kist</comment>
- <comment xml:lang="hu">GIMP ecset</comment>
- <comment xml:lang="id">Kuas GIMP</comment>
- <comment xml:lang="it">Pennello GIMP</comment>
- <comment xml:lang="kk">GIMP бояу жаққышы</comment>
- <comment xml:lang="ko">GIMP 붓</comment>
- <comment xml:lang="pl">Pędzel programu GIMP</comment>
- <comment xml:lang="pt_BR">Pincel do GIMP</comment>
- <comment xml:lang="ru">Кисть GIMP</comment>
- <comment xml:lang="sk">Štetec aplikácie GIMP</comment>
- <comment xml:lang="sv">GIMP-pensel</comment>
- <comment xml:lang="uk">пензель GIMP</comment>
- <comment xml:lang="zh_CN">GIMP 笔刷</comment>
<comment xml:lang="zh_TW">GIMP 筆刷</comment>
+ <comment xml:lang="zh_CN">GIMP 笔刷</comment>
+ <comment xml:lang="uk">пензель GIMP</comment>
+ <comment xml:lang="tr">GIMP fırçası</comment>
+ <comment xml:lang="sv">GIMP-pensel</comment>
+ <comment xml:lang="sq">penel GIMP</comment>
+ <comment xml:lang="sl">Čopič GIMP</comment>
+ <comment xml:lang="si">GIMP බුරුසුව</comment>
+ <comment xml:lang="sk">Štetec aplikácie GIMP</comment>
+ <comment xml:lang="ru">Кисть GIMP</comment>
+ <comment xml:lang="pt_BR">Pincel do GIMP</comment>
+ <comment xml:lang="pl">Pędzel programu GIMP</comment>
+ <comment xml:lang="nl">GIMP-kwast</comment>
+ <comment xml:lang="ko">GIMP 붓</comment>
+ <comment xml:lang="kk">GIMP бояу жаққышы</comment>
+ <comment xml:lang="ka">GIMP-ის ფუნჯი</comment>
+ <comment xml:lang="ja">GIMP ブラシ</comment>
+ <comment xml:lang="it">Pennello GIMP</comment>
+ <comment xml:lang="is">GIMP-pensill</comment>
+ <comment xml:lang="id">Kuas GIMP</comment>
+ <comment xml:lang="hu">GIMP ecset</comment>
+ <comment xml:lang="hr">GIMP kist</comment>
+ <comment xml:lang="he">מברשת GIMP</comment>
+ <comment xml:lang="gl">Pincel de GIMP</comment>
+ <comment xml:lang="ga">scuab GIMP</comment>
+ <comment xml:lang="fur">pinel GIMP</comment>
+ <comment xml:lang="fr">brosse GIMP</comment>
+ <comment xml:lang="fi">GIMP-sivellin</comment>
+ <comment xml:lang="eu">GIMP pintzela</comment>
+ <comment xml:lang="es">pincel del GIMP</comment>
+ <comment xml:lang="en_GB">GIMP brush</comment>
+ <comment xml:lang="de">GIMP-Pinsel</comment>
+ <comment xml:lang="da">GIMP-pensel</comment>
+ <comment xml:lang="cs">štětec GIMP</comment>
+ <comment xml:lang="ca">pinzell de GIMP</comment>
+ <comment xml:lang="bg">Четка — GIMP</comment>
+ <comment xml:lang="be">пэндзаль GIMP</comment>
+ <comment xml:lang="ar">فرشاة جمب</comment>
+ <comment xml:lang="af">GIMP-kwas</comment>
<glob pattern="*.gbr"/>
- <magic priority="50">
- <match value="GIMP" type="string" offset="20"/>
+ <magic>
+ <match type="string" value="GIMP" offset="20"/>
</magic>
</mime-type>
<mime-type type="image/x-gimp-gih">
<comment>GIMP brush pipe</comment>
- <comment xml:lang="ca">conducte del pinzell de GIMP</comment>
- <comment xml:lang="cs">zřetězení štětců GIMP</comment>
- <comment xml:lang="de">GIMP-Pinselanimation</comment>
- <comment xml:lang="en_GB">GIMP brush pipe</comment>
- <comment xml:lang="es">pincel animado del GIMP</comment>
- <comment xml:lang="hr">GIMP valjkasti kist</comment>
- <comment xml:lang="hu">GIMP ecsetcsatorna</comment>
- <comment xml:lang="id">Pipa kuas GIMP</comment>
- <comment xml:lang="it">Pipe pennello GIMP</comment>
- <comment xml:lang="kk">GIMP бояу жаққыш түтігі</comment>
- <comment xml:lang="ko">GIMP 붓 파이프</comment>
- <comment xml:lang="pl">Potok pędzla programu GIMP</comment>
- <comment xml:lang="pt_BR">Tubo de pincel do GIMP</comment>
- <comment xml:lang="ru">Анимированная кисть GIMP</comment>
- <comment xml:lang="sv">GIMP-penselrör</comment>
- <comment xml:lang="uk">канал пензлів GIMP</comment>
- <comment xml:lang="zh_CN">GIMP 管刷</comment>
<comment xml:lang="zh_TW">GIMP 筆刷導管</comment>
+ <comment xml:lang="zh_CN">GIMP 管刷</comment>
+ <comment xml:lang="uk">канал пензлів GIMP</comment>
+ <comment xml:lang="tr">GIMP fırça borusu</comment>
+ <comment xml:lang="sv">GIMP-penselrör</comment>
+ <comment xml:lang="si">GIMP බුරුසු පයිප්ප</comment>
+ <comment xml:lang="ru">Анимированная кисть GIMP</comment>
+ <comment xml:lang="pt_BR">Tubo de pincel do GIMP</comment>
+ <comment xml:lang="pl">Potok pędzla programu GIMP</comment>
+ <comment xml:lang="nl">GIMP-kwast-pijp</comment>
+ <comment xml:lang="ko">GIMP 붓 파이프</comment>
+ <comment xml:lang="kk">GIMP бояу жаққыш түтігі</comment>
+ <comment xml:lang="ja">GIMP パイプブラシ</comment>
+ <comment xml:lang="it">Pipe pennello GIMP</comment>
+ <comment xml:lang="is">GIMP-pensilpípa</comment>
+ <comment xml:lang="id">Pipa kuas GIMP</comment>
+ <comment xml:lang="hu">GIMP ecsetcsatorna</comment>
+ <comment xml:lang="hr">Proces GIMP kista</comment>
+ <comment xml:lang="he">צינורית מברשת GIMP</comment>
+ <comment xml:lang="ga">píopa scuaba GIMP</comment>
+ <comment xml:lang="fur">condot pinel GIMP</comment>
+ <comment xml:lang="fr">brosse animée GIMP</comment>
+ <comment xml:lang="fi">GIMP-sivellinputki</comment>
+ <comment xml:lang="eu">GIMP pintzel hodia pipe</comment>
+ <comment xml:lang="es">pincel animado del GIMP</comment>
+ <comment xml:lang="en_GB">GIMP brush pipe</comment>
+ <comment xml:lang="de">Animierter GIMP-Pinsel</comment>
+ <comment xml:lang="da">GIMP-penselrør</comment>
+ <comment xml:lang="cs">zřetězení štětců GIMP</comment>
+ <comment xml:lang="ca">conducte del pinzell de GIMP</comment>
+ <comment xml:lang="bg">Конвейер с четки — GIMP</comment>
+ <comment xml:lang="be">самаробны пэндзаль GIMP</comment>
+ <comment xml:lang="ar">أنبوب فرشاة GIMP</comment>
<glob pattern="*.gih"/>
</mime-type>
<mime-type type="image/x-gimp-pat">
<comment>GIMP pattern</comment>
- <comment xml:lang="ca">patró de GIMP</comment>
- <comment xml:lang="cs">vzorek GIMP</comment>
- <comment xml:lang="de">GIMP-Muster</comment>
- <comment xml:lang="en_GB">GIMP pattern</comment>
- <comment xml:lang="es">patrón del GIMP</comment>
- <comment xml:lang="hr">GIMP uzorak</comment>
- <comment xml:lang="hu">GIMP minta</comment>
- <comment xml:lang="id">Pola GIMP</comment>
- <comment xml:lang="it">Motivo GIMP</comment>
- <comment xml:lang="kk">GIMP оюы</comment>
- <comment xml:lang="ko">GIMP 패턴</comment>
- <comment xml:lang="pl">Deseń programu GIMP</comment>
- <comment xml:lang="pt_BR">Textura do GIMP</comment>
- <comment xml:lang="ru">Шаблон GIMP</comment>
- <comment xml:lang="sk">Vzor aplikácie GIMP</comment>
- <comment xml:lang="sv">GIMP-mönster</comment>
- <comment xml:lang="uk">візерунок GIMP</comment>
- <comment xml:lang="zh_CN">GIMP 图案</comment>
<comment xml:lang="zh_TW">GIMP 樣式</comment>
+ <comment xml:lang="zh_CN">GIMP 图案</comment>
+ <comment xml:lang="uk">візерунок GIMP</comment>
+ <comment xml:lang="tr">GIMP deseni</comment>
+ <comment xml:lang="sv">GIMP-mönster</comment>
+ <comment xml:lang="sl">Vzorec GIMP</comment>
+ <comment xml:lang="si">GIMP රටාව</comment>
+ <comment xml:lang="sk">Vzor aplikácie GIMP</comment>
+ <comment xml:lang="ru">Шаблон GIMP</comment>
+ <comment xml:lang="pt_BR">Textura do GIMP</comment>
+ <comment xml:lang="pl">Deseń programu GIMP</comment>
+ <comment xml:lang="nl">GIMP-patroon</comment>
+ <comment xml:lang="ko">GIMP 패턴</comment>
+ <comment xml:lang="kk">GIMP оюы</comment>
+ <comment xml:lang="ka">GIMP შაბლონი</comment>
+ <comment xml:lang="ja">GIMP パターン</comment>
+ <comment xml:lang="it">Motivo GIMP</comment>
+ <comment xml:lang="is">GIMP-mynstur</comment>
+ <comment xml:lang="id">Pola GIMP</comment>
+ <comment xml:lang="hu">GIMP minta</comment>
+ <comment xml:lang="hr">GIMP uzorak</comment>
+ <comment xml:lang="he">מרקם של GIMP</comment>
+ <comment xml:lang="gl">Patrón de GIMP</comment>
+ <comment xml:lang="ga">patrún GIMP</comment>
+ <comment xml:lang="fur">motîf GIMP</comment>
+ <comment xml:lang="fr">motif GIMP</comment>
+ <comment xml:lang="fi">GIMP-kuvio</comment>
+ <comment xml:lang="eu">GIMP eredua</comment>
+ <comment xml:lang="es">patrón del GIMP</comment>
+ <comment xml:lang="en_GB">GIMP pattern</comment>
+ <comment xml:lang="de">GIMP-Muster</comment>
+ <comment xml:lang="da">GIMP-mønster</comment>
+ <comment xml:lang="cs">vzorek GIMP</comment>
+ <comment xml:lang="ca">patró de GIMP</comment>
+ <comment xml:lang="bg">Шарка — GIMP</comment>
+ <comment xml:lang="be">узор GIMP</comment>
+ <comment xml:lang="ar">نقش GIMP</comment>
+ <comment xml:lang="af">GIMP-patroon</comment>
<glob pattern="*.pat"/>
- <magic priority="50">
- <match value="GPAT" type="string" offset="20"/>
+ <magic>
+ <match type="string" value="GPAT" offset="20"/>
</magic>
</mime-type>
<mime-type type="image/x-xfig">
<comment>XFig image</comment>
- <comment xml:lang="ar">صورة XFig</comment>
- <comment xml:lang="be@latin">Vyjava XFig</comment>
- <comment xml:lang="bg">Изображение — XFig</comment>
- <comment xml:lang="ca">imatge de XFig</comment>
- <comment xml:lang="cs">obrázek XFig</comment>
- <comment xml:lang="da">XFig-billede</comment>
- <comment xml:lang="de">XFig-Bild</comment>
- <comment xml:lang="el">Εικόνα XFig</comment>
- <comment xml:lang="en_GB">XFig image</comment>
- <comment xml:lang="eo">XFig-bildo</comment>
- <comment xml:lang="es">imagen de XFig</comment>
- <comment xml:lang="eu">XFig irudia</comment>
- <comment xml:lang="fi">XFig-kuva</comment>
- <comment xml:lang="fo">XFig mynd</comment>
- <comment xml:lang="fr">image XFig</comment>
- <comment xml:lang="ga">íomhá XFig</comment>
- <comment xml:lang="gl">imaxe de XFig</comment>
- <comment xml:lang="he">תמונת XFig</comment>
- <comment xml:lang="hr">XFig slika</comment>
- <comment xml:lang="hu">XFig-kép</comment>
- <comment xml:lang="ia">Imagine XFig</comment>
- <comment xml:lang="id">Citra XFig</comment>
- <comment xml:lang="it">Immagine XFig</comment>
- <comment xml:lang="ja">XFig 画像</comment>
- <comment xml:lang="kk">XFig суреті</comment>
- <comment xml:lang="ko">XFig 그림</comment>
- <comment xml:lang="lt">XFig paveikslėlis</comment>
- <comment xml:lang="lv">XFig attēls</comment>
- <comment xml:lang="ms">Imej XFig</comment>
- <comment xml:lang="nb">XFig-bilde</comment>
- <comment xml:lang="nl">XFig-afbeelding</comment>
- <comment xml:lang="nn">XFig-bilete</comment>
- <comment xml:lang="oc">imatge XFig</comment>
- <comment xml:lang="pl">Obraz XFig</comment>
- <comment xml:lang="pt">imagem XFig</comment>
- <comment xml:lang="pt_BR">Imagem do XFig</comment>
- <comment xml:lang="ro">Imagine XFig</comment>
- <comment xml:lang="ru">Изображение XFig</comment>
- <comment xml:lang="sk">Obrázok XFig</comment>
- <comment xml:lang="sl">Slikovna datoteka XFig</comment>
- <comment xml:lang="sq">Figurë XFig</comment>
- <comment xml:lang="sr">ИксФиг слика</comment>
- <comment xml:lang="sv">XFig-bild</comment>
- <comment xml:lang="tr">XFig görüntüsü</comment>
- <comment xml:lang="uk">зображення XFig</comment>
- <comment xml:lang="vi">Ảnh XFig</comment>
- <comment xml:lang="zh_CN">XFig 图像</comment>
<comment xml:lang="zh_TW">XFig 影像</comment>
+ <comment xml:lang="zh_CN">XFig 图像</comment>
+ <comment xml:lang="vi">Ảnh XFig</comment>
+ <comment xml:lang="uk">зображення XFig</comment>
+ <comment xml:lang="tr">XFig görüntüsü</comment>
+ <comment xml:lang="sv">XFig-bild</comment>
+ <comment xml:lang="sr">ИксФиг слика</comment>
+ <comment xml:lang="sq">figurë XFig</comment>
+ <comment xml:lang="sl">Slikovna datoteka XFig</comment>
+ <comment xml:lang="si">XFig රූපය</comment>
+ <comment xml:lang="sk">Obrázok XFig</comment>
+ <comment xml:lang="ru">Изображение XFig</comment>
+ <comment xml:lang="ro">Imagine XFig</comment>
+ <comment xml:lang="pt_BR">Imagem do XFig</comment>
+ <comment xml:lang="pt">imagem XFig</comment>
+ <comment xml:lang="pl">Obraz XFig</comment>
+ <comment xml:lang="oc">imatge XFig</comment>
+ <comment xml:lang="nn">XFig-bilete</comment>
+ <comment xml:lang="nl">XFig-afbeelding</comment>
+ <comment xml:lang="nb">XFig-bilde</comment>
+ <comment xml:lang="ms">Imej XFig</comment>
+ <comment xml:lang="lv">XFig attēls</comment>
+ <comment xml:lang="lt">XFig paveikslėlis</comment>
+ <comment xml:lang="ko">XFig 그림</comment>
+ <comment xml:lang="kk">XFig суреті</comment>
+ <comment xml:lang="ja">XFig 画像</comment>
+ <comment xml:lang="it">Immagine XFig</comment>
+ <comment xml:lang="is">XFig mynd</comment>
+ <comment xml:lang="id">Citra XFig</comment>
+ <comment xml:lang="ia">Imagine XFig</comment>
+ <comment xml:lang="hu">XFig-kép</comment>
+ <comment xml:lang="hr">XFig slika</comment>
+ <comment xml:lang="he">תמונת XFig</comment>
+ <comment xml:lang="gl">imaxe de XFig</comment>
+ <comment xml:lang="ga">íomhá XFig</comment>
+ <comment xml:lang="fur">imagjin XFig</comment>
+ <comment xml:lang="fr">image XFig</comment>
+ <comment xml:lang="fo">XFig mynd</comment>
+ <comment xml:lang="fi">XFig-kuva</comment>
+ <comment xml:lang="eu">XFig irudia</comment>
+ <comment xml:lang="es">imagen de XFig</comment>
+ <comment xml:lang="eo">XFig-bildo</comment>
+ <comment xml:lang="en_GB">XFig image</comment>
+ <comment xml:lang="el">Εικόνα XFig</comment>
+ <comment xml:lang="de">XFig-Bild</comment>
+ <comment xml:lang="da">XFig-billede</comment>
+ <comment xml:lang="cs">obrázek XFig</comment>
+ <comment xml:lang="ca">imatge de XFig</comment>
+ <comment xml:lang="bg">Изображение — XFig</comment>
+ <comment xml:lang="be@latin">Vyjava XFig</comment>
+ <comment xml:lang="be">выява XFig</comment>
+ <comment xml:lang="ar">صورة XFig</comment>
+ <comment xml:lang="af">XFig-beeld</comment>
<glob pattern="*.fig"/>
- <magic priority="50">
- <match value="#FIG" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#FIG" offset="0"/>
</magic>
</mime-type>
<mime-type type="image/x-xpixmap">
<comment>XPM image</comment>
- <comment xml:lang="ar">صورة XPM</comment>
- <comment xml:lang="be@latin">Vyjava XPM</comment>
- <comment xml:lang="bg">Изображение — XPM</comment>
- <comment xml:lang="ca">imatge XPM</comment>
- <comment xml:lang="cs">obrázek XPM</comment>
- <comment xml:lang="cy">Delwedd XPM</comment>
- <comment xml:lang="da">XPM-billede</comment>
- <comment xml:lang="de">XPM-Bild</comment>
- <comment xml:lang="el">Εικόνα XPM</comment>
- <comment xml:lang="en_GB">XPM image</comment>
- <comment xml:lang="eo">XPM-bildo</comment>
- <comment xml:lang="es">imagen XPM</comment>
- <comment xml:lang="eu">XPM irudia</comment>
- <comment xml:lang="fi">XPM-kuva</comment>
- <comment xml:lang="fo">XPM mynd</comment>
- <comment xml:lang="fr">image XPM</comment>
- <comment xml:lang="ga">íomhá XPM</comment>
- <comment xml:lang="gl">imaxe XPM</comment>
- <comment xml:lang="he">תמונת XPM</comment>
- <comment xml:lang="hr">XPM slika</comment>
- <comment xml:lang="hu">XPM kép</comment>
- <comment xml:lang="ia">Imagine XPM</comment>
- <comment xml:lang="id">Citra XPM</comment>
- <comment xml:lang="it">Immagine XPM</comment>
- <comment xml:lang="ja">XPM 画像</comment>
- <comment xml:lang="kk">XPM суреті</comment>
- <comment xml:lang="ko">XPM 그림</comment>
- <comment xml:lang="lt">XPM paveikslėlis</comment>
- <comment xml:lang="lv">XPM attēls</comment>
- <comment xml:lang="nb">XPM-bilde</comment>
- <comment xml:lang="nl">XPM-afbeelding</comment>
- <comment xml:lang="nn">XPM-bilete</comment>
- <comment xml:lang="oc">imatge XPM</comment>
- <comment xml:lang="pl">Obraz XPM</comment>
- <comment xml:lang="pt">imagem XPM</comment>
- <comment xml:lang="pt_BR">Imagem XPM</comment>
- <comment xml:lang="ro">Imagine XPM</comment>
- <comment xml:lang="ru">Изображение XPM</comment>
- <comment xml:lang="sk">Obrázok XPM</comment>
- <comment xml:lang="sl">Slikovna datoteka XPM</comment>
- <comment xml:lang="sq">Figurë XPM</comment>
- <comment xml:lang="sr">ИксПМ слика</comment>
- <comment xml:lang="sv">XPM-bild</comment>
- <comment xml:lang="tr">XPM görüntüsü</comment>
- <comment xml:lang="uk">зображення XPM</comment>
- <comment xml:lang="vi">Ảnh XPM</comment>
- <comment xml:lang="zh_CN">XPM 图像</comment>
<comment xml:lang="zh_TW">XPM 影像</comment>
+ <comment xml:lang="zh_CN">XPM 图像</comment>
+ <comment xml:lang="vi">Ảnh XPM</comment>
+ <comment xml:lang="uk">зображення XPM</comment>
+ <comment xml:lang="tr">XPM görüntüsü</comment>
+ <comment xml:lang="sv">XPM-bild</comment>
+ <comment xml:lang="sr">ИксПМ слика</comment>
+ <comment xml:lang="sq">figurë XPM</comment>
+ <comment xml:lang="sl">Slikovna datoteka XPM</comment>
+ <comment xml:lang="si">XPM රූපය</comment>
+ <comment xml:lang="sk">Obrázok XPM</comment>
+ <comment xml:lang="ru">Изображение XPM</comment>
+ <comment xml:lang="ro">Imagine XPM</comment>
+ <comment xml:lang="pt_BR">Imagem XPM</comment>
+ <comment xml:lang="pt">imagem XPM</comment>
+ <comment xml:lang="pl">Obraz XPM</comment>
+ <comment xml:lang="oc">imatge XPM</comment>
+ <comment xml:lang="nn">XPM-bilete</comment>
+ <comment xml:lang="nl">XPM-afbeelding</comment>
+ <comment xml:lang="nb">XPM-bilde</comment>
+ <comment xml:lang="lv">XPM attēls</comment>
+ <comment xml:lang="lt">XPM paveikslėlis</comment>
+ <comment xml:lang="ko">XPM 그림</comment>
+ <comment xml:lang="kk">XPM суреті</comment>
+ <comment xml:lang="ja">XPM 画像</comment>
+ <comment xml:lang="it">Immagine XPM</comment>
+ <comment xml:lang="is">XPM mynd</comment>
+ <comment xml:lang="id">Citra XPM</comment>
+ <comment xml:lang="ia">Imagine XPM</comment>
+ <comment xml:lang="hu">XPM kép</comment>
+ <comment xml:lang="hr">XPM slika</comment>
+ <comment xml:lang="he">תמונת XPM</comment>
+ <comment xml:lang="gl">imaxe XPM</comment>
+ <comment xml:lang="ga">íomhá XPM</comment>
+ <comment xml:lang="fur">imagjin XPM</comment>
+ <comment xml:lang="fr">image XPM</comment>
+ <comment xml:lang="fo">XPM mynd</comment>
+ <comment xml:lang="fi">XPM-kuva</comment>
+ <comment xml:lang="eu">XPM irudia</comment>
+ <comment xml:lang="es">imagen XPM</comment>
+ <comment xml:lang="eo">XPM-bildo</comment>
+ <comment xml:lang="en_GB">XPM image</comment>
+ <comment xml:lang="el">Εικόνα XPM</comment>
+ <comment xml:lang="de">XPM-Bild</comment>
+ <comment xml:lang="da">XPM-billede</comment>
+ <comment xml:lang="cy">Delwedd XPM</comment>
+ <comment xml:lang="cs">obrázek XPM</comment>
+ <comment xml:lang="ca">imatge XPM</comment>
+ <comment xml:lang="bg">Изображение — XPM</comment>
+ <comment xml:lang="be@latin">Vyjava XPM</comment>
+ <comment xml:lang="be">выява XPM</comment>
+ <comment xml:lang="ar">صورة XPM</comment>
+ <comment xml:lang="af">XPM-beeld</comment>
<acronym>XPM</acronym>
<expanded-acronym>X PixMap</expanded-acronym>
- <magic priority="50">
- <match value="/* XPM" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="/* XPM */" offset="0"/>
+ <match type="string" value="! XPM2\n" offset="0"/>
</magic>
<glob pattern="*.xpm"/>
<alias type="image/x-xpm"/>
</mime-type>
<mime-type type="image/x-xwindowdump">
<comment>X window image</comment>
- <comment xml:lang="ar">صورة X window</comment>
- <comment xml:lang="az">X window rəsmi</comment>
- <comment xml:lang="be@latin">Vyjava vakna X</comment>
- <comment xml:lang="bg">Изображение — X Window</comment>
- <comment xml:lang="ca">imatge de X window</comment>
- <comment xml:lang="cs">obrázek X window</comment>
- <comment xml:lang="cy">Delwedd ffenest X</comment>
- <comment xml:lang="da">X-billede</comment>
- <comment xml:lang="de">X-Window-Bild</comment>
- <comment xml:lang="el">Εικόνα περιβάλλοντος X</comment>
- <comment xml:lang="en_GB">X window image</comment>
- <comment xml:lang="eo">bildo de X window</comment>
- <comment xml:lang="es">imagen de ventana de X</comment>
- <comment xml:lang="eu">X window irudia</comment>
- <comment xml:lang="fi">X-ikkunakuva</comment>
- <comment xml:lang="fo">X vindeyga mynd</comment>
- <comment xml:lang="fr">image X window</comment>
- <comment xml:lang="ga">íomhá X-windows</comment>
- <comment xml:lang="gl">imaxe de X Window</comment>
- <comment xml:lang="he">תמונת חלון של X</comment>
- <comment xml:lang="hr">X window slika</comment>
- <comment xml:lang="hu">X window-kép</comment>
- <comment xml:lang="ia">Imagine X Window</comment>
- <comment xml:lang="id">Citra X window</comment>
- <comment xml:lang="it">Immagine X window</comment>
- <comment xml:lang="ja">X window 画像</comment>
- <comment xml:lang="kk">X window суреті</comment>
- <comment xml:lang="ko">X 윈도 그림</comment>
- <comment xml:lang="lt">X window paveikslėlis</comment>
- <comment xml:lang="lv">X window attēls</comment>
- <comment xml:lang="ms">Imej tetingkap X</comment>
- <comment xml:lang="nb">X-Windows skjermbilde</comment>
- <comment xml:lang="nl">X-window-afbeelding</comment>
- <comment xml:lang="nn">X window bilete</comment>
- <comment xml:lang="oc">imatge X window</comment>
- <comment xml:lang="pl">Obraz X Window</comment>
- <comment xml:lang="pt">imagem de janela X</comment>
- <comment xml:lang="pt_BR">Imagem de janela do X</comment>
- <comment xml:lang="ro">Imagine X window</comment>
- <comment xml:lang="ru">Изображение X window</comment>
- <comment xml:lang="sk">Obrázok X window</comment>
- <comment xml:lang="sl">slika X oken</comment>
- <comment xml:lang="sq">Figurë X window</comment>
- <comment xml:lang="sr">слика Икс прозора</comment>
- <comment xml:lang="sv">X-fönsterbild</comment>
- <comment xml:lang="tr">X pencere görüntüsü</comment>
- <comment xml:lang="uk">зображення X window</comment>
- <comment xml:lang="vi">Ảnh cửa sổ X</comment>
- <comment xml:lang="zh_CN">X Window 图像</comment>
<comment xml:lang="zh_TW">X window 影像</comment>
+ <comment xml:lang="zh_CN">X Window 图像</comment>
+ <comment xml:lang="vi">Ảnh cửa sổ X</comment>
+ <comment xml:lang="uk">зображення X window</comment>
+ <comment xml:lang="tr">X pencere görüntüsü</comment>
+ <comment xml:lang="sv">X-fönsterbild</comment>
+ <comment xml:lang="sr">слика Икс прозора</comment>
+ <comment xml:lang="sq">figurë X window</comment>
+ <comment xml:lang="sl">slika X oken</comment>
+ <comment xml:lang="si">X කවුළු රූපය</comment>
+ <comment xml:lang="sk">Obrázok X window</comment>
+ <comment xml:lang="ru">Изображение X window</comment>
+ <comment xml:lang="ro">Imagine X window</comment>
+ <comment xml:lang="pt_BR">Imagem de janela do X</comment>
+ <comment xml:lang="pt">imagem de janela X</comment>
+ <comment xml:lang="pl">Obraz X Window</comment>
+ <comment xml:lang="oc">imatge X window</comment>
+ <comment xml:lang="nn">X window bilete</comment>
+ <comment xml:lang="nl">X-window-afbeelding</comment>
+ <comment xml:lang="nb">X-Windows skjermbilde</comment>
+ <comment xml:lang="ms">Imej tetingkap X</comment>
+ <comment xml:lang="lv">X window attēls</comment>
+ <comment xml:lang="lt">X window paveikslėlis</comment>
+ <comment xml:lang="ko">X 윈도 그림</comment>
+ <comment xml:lang="kk">X window суреті</comment>
+ <comment xml:lang="ja">X window 画像</comment>
+ <comment xml:lang="it">Immagine X window</comment>
+ <comment xml:lang="is">X window mynd</comment>
+ <comment xml:lang="id">Citra X window</comment>
+ <comment xml:lang="ia">Imagine X Window</comment>
+ <comment xml:lang="hu">X window-kép</comment>
+ <comment xml:lang="hr">X window slika</comment>
+ <comment xml:lang="he">תמונת חלון של X</comment>
+ <comment xml:lang="gl">imaxe de X Window</comment>
+ <comment xml:lang="ga">íomhá X-windows</comment>
+ <comment xml:lang="fur">imagjin X window</comment>
+ <comment xml:lang="fr">image X window</comment>
+ <comment xml:lang="fo">X vindeyga mynd</comment>
+ <comment xml:lang="fi">X-ikkunakuva</comment>
+ <comment xml:lang="eu">X window irudia</comment>
+ <comment xml:lang="es">imagen de ventana de X</comment>
+ <comment xml:lang="eo">bildo de X window</comment>
+ <comment xml:lang="en_GB">X window image</comment>
+ <comment xml:lang="el">Εικόνα περιβάλλοντος X</comment>
+ <comment xml:lang="de">X-Window-Bild</comment>
+ <comment xml:lang="da">X-billede</comment>
+ <comment xml:lang="cy">Delwedd ffenest X</comment>
+ <comment xml:lang="cs">obrázek X window</comment>
+ <comment xml:lang="ca">imatge de X window</comment>
+ <comment xml:lang="bg">Изображение — X Window</comment>
+ <comment xml:lang="be@latin">Vyjava vakna X</comment>
+ <comment xml:lang="be">выява X window</comment>
+ <comment xml:lang="az">X window rəsmi</comment>
+ <comment xml:lang="ar">صورة X window</comment>
+ <comment xml:lang="af">X window-beeld</comment>
<glob pattern="*.xwd"/>
</mime-type>
<mime-type type="inode/blockdevice">
- <comment>block device</comment>
- <comment xml:lang="ar">جهاز كتلي</comment>
- <comment xml:lang="ast">preséu de bloques</comment>
- <comment xml:lang="be@latin">blokavaja pryłada</comment>
- <comment xml:lang="bg">Блоково устройство</comment>
- <comment xml:lang="ca">dispositiu de blocs</comment>
- <comment xml:lang="cs">blokové zařízení</comment>
- <comment xml:lang="da">blokenhed</comment>
- <comment xml:lang="de">Blockorientiertes Gerät</comment>
- <comment xml:lang="el">Συσκευή block</comment>
- <comment xml:lang="en_GB">block device</comment>
- <comment xml:lang="eo">bloka disponaĵo</comment>
- <comment xml:lang="es">dispositivo de bloques</comment>
- <comment xml:lang="eu">bloke-gailua</comment>
- <comment xml:lang="fi">laitetiedosto</comment>
- <comment xml:lang="fo">blokka tóleind</comment>
- <comment xml:lang="fr">périphérique de blocs</comment>
- <comment xml:lang="ga">gléas bloc</comment>
- <comment xml:lang="gl">dispositivo de bloque</comment>
- <comment xml:lang="he">התקן בלוק</comment>
- <comment xml:lang="hr">Blokovski uređaj</comment>
- <comment xml:lang="hu">blokkos eszköz</comment>
- <comment xml:lang="ia">Dispositivo de blocos</comment>
- <comment xml:lang="id">peranti blok</comment>
- <comment xml:lang="it">Device a blocchi</comment>
- <comment xml:lang="ja">ブロックデバイス</comment>
- <comment xml:lang="kk">блоктық құрылғысы</comment>
- <comment xml:lang="ko">블록 장치</comment>
- <comment xml:lang="lt">blokinis įrenginys</comment>
- <comment xml:lang="lv">bloka ierīce</comment>
- <comment xml:lang="ms">Peranti blok</comment>
- <comment xml:lang="nb">blokkenhet</comment>
- <comment xml:lang="nl">blok-apparaat</comment>
- <comment xml:lang="nn">blokk-eining</comment>
- <comment xml:lang="oc">periferic de blòts</comment>
- <comment xml:lang="pl">Urządzenie blokowe</comment>
- <comment xml:lang="pt">dispositivo de bloco</comment>
- <comment xml:lang="pt_BR">Dispositivo de bloco</comment>
- <comment xml:lang="ro">dispozitiv bloc</comment>
- <comment xml:lang="ru">Блочное устройство</comment>
- <comment xml:lang="sk">Blokové zariadenie</comment>
- <comment xml:lang="sl">bločna naprava</comment>
- <comment xml:lang="sq">device me blloqe</comment>
- <comment xml:lang="sr">блок уређај</comment>
- <comment xml:lang="sv">blockenhet</comment>
- <comment xml:lang="tr">blok aygıtı</comment>
+ <comment>Block device</comment>
<comment xml:lang="uk">блоковий пристрій</comment>
- <comment xml:lang="vi">thiết bị khối</comment>
- <comment xml:lang="zh_CN">块设备</comment>
- <comment xml:lang="zh_TW">區塊裝置</comment>
+ <comment xml:lang="sv">Blockenhet</comment>
+ <comment xml:lang="ru">Блочное устройство</comment>
+ <comment xml:lang="pl">Urządzenie blokowe</comment>
+ <comment xml:lang="ja">区画様機器</comment>
+ <comment xml:lang="it">Device a blocchi</comment>
+ <comment xml:lang="gl">Dispositivo de bloque</comment>
+ <comment xml:lang="eu">Bloke-gailua</comment>
+ <comment xml:lang="es">dispositivo de bloques</comment>
+ <comment xml:lang="de">Blockorientiertes Gerät</comment>
+ <comment xml:lang="be">блокавая прылада</comment>
</mime-type>
<mime-type type="inode/chardevice">
- <comment>character device</comment>
- <comment xml:lang="ar">جهاز حرفي</comment>
- <comment xml:lang="ast">preséu de caráuteres</comment>
- <comment xml:lang="be@latin">znakavaja pryłada</comment>
- <comment xml:lang="bg">Символно устройство</comment>
- <comment xml:lang="ca">dispositiu de caràcters</comment>
- <comment xml:lang="cs">znakové zařízení</comment>
- <comment xml:lang="da">tegnenhed</comment>
- <comment xml:lang="de">Zeichenorientiertes Gerät</comment>
- <comment xml:lang="el">Συσκευή χαρακτήρων</comment>
- <comment xml:lang="en_GB">character device</comment>
- <comment xml:lang="eo">signa disponaĵo</comment>
- <comment xml:lang="es">dispositivo de caracteres</comment>
- <comment xml:lang="eu">karaktereen gailua</comment>
- <comment xml:lang="fi">merkkilaite</comment>
- <comment xml:lang="fo">stavatóleind</comment>
- <comment xml:lang="fr">périphérique de caractères</comment>
- <comment xml:lang="ga">gléas carachtar</comment>
- <comment xml:lang="gl">dispositivo de caracter</comment>
- <comment xml:lang="he">התקן תכונה</comment>
- <comment xml:lang="hr">Znakovni uređaj</comment>
- <comment xml:lang="hu">karakteres eszköz</comment>
- <comment xml:lang="ia">Dispositivo de characteres</comment>
- <comment xml:lang="id">peranti karakter</comment>
- <comment xml:lang="it">Device a caratteri</comment>
- <comment xml:lang="ja">キャラクタデバイス</comment>
- <comment xml:lang="kk">символдық құрылғысы</comment>
- <comment xml:lang="ko">문자 장치</comment>
- <comment xml:lang="lt">simbolinis įrenginys</comment>
- <comment xml:lang="lv">rakstzīmju ierīce</comment>
- <comment xml:lang="ms">Peranti aksara</comment>
- <comment xml:lang="nb">tegnenhet</comment>
- <comment xml:lang="nl">byte-apparaat</comment>
- <comment xml:lang="nn">teikneining</comment>
- <comment xml:lang="oc">periferic de caractèrs</comment>
- <comment xml:lang="pl">Urządzenie znakowe</comment>
- <comment xml:lang="pt">dispositivo de caracteres</comment>
- <comment xml:lang="pt_BR">Dispositivo de caractere</comment>
- <comment xml:lang="ro">dispozitiv caracter</comment>
+ <comment>Character device</comment>
+ <comment xml:lang="uk">Символьний пристрій</comment>
+ <comment xml:lang="sv">Teckenenhet</comment>
<comment xml:lang="ru">Символьное устройство</comment>
- <comment xml:lang="sk">Znakové zariadenie</comment>
- <comment xml:lang="sl">znakovna naprava</comment>
- <comment xml:lang="sq">device me karaktere</comment>
- <comment xml:lang="sr">знаковни уређај</comment>
- <comment xml:lang="sv">teckenenhet</comment>
- <comment xml:lang="tr">karakter aygıtı</comment>
- <comment xml:lang="uk">символьний пристрій</comment>
- <comment xml:lang="vi">thiết bị ký tự</comment>
- <comment xml:lang="zh_CN">字符设备</comment>
- <comment xml:lang="zh_TW">字元裝置</comment>
+ <comment xml:lang="pl">Urządzenie znakowe</comment>
+ <comment xml:lang="ja">文字様機器</comment>
+ <comment xml:lang="it">Device a caratteri</comment>
+ <comment xml:lang="gl">Dispositivo de caracter</comment>
+ <comment xml:lang="eu">Karaktere-gailua</comment>
+ <comment xml:lang="es">dispositivo de caracteres</comment>
+ <comment xml:lang="de">Zeichenorientiertes Gerät</comment>
+ <comment xml:lang="be">сімвальная прылада</comment>
</mime-type>
<mime-type type="inode/directory">
- <comment>folder</comment>
- <comment xml:lang="ar">مجلّد</comment>
- <comment xml:lang="ast">carpeta</comment>
- <comment xml:lang="be@latin">kataloh</comment>
- <comment xml:lang="bg">Папка</comment>
- <comment xml:lang="ca">carpeta</comment>
- <comment xml:lang="cs">složka</comment>
- <comment xml:lang="da">mappe</comment>
- <comment xml:lang="de">Ordner</comment>
- <comment xml:lang="el">Φάκελος</comment>
- <comment xml:lang="en_GB">folder</comment>
- <comment xml:lang="eo">dosierujo</comment>
- <comment xml:lang="es">carpeta</comment>
- <comment xml:lang="eu">karpeta</comment>
- <comment xml:lang="fi">kansio</comment>
- <comment xml:lang="fo">mappa</comment>
- <comment xml:lang="fr">dossier</comment>
- <comment xml:lang="ga">fillteán</comment>
- <comment xml:lang="gl">cartafol</comment>
- <comment xml:lang="he">תיקייה</comment>
- <comment xml:lang="hr">Mapa</comment>
- <comment xml:lang="hu">mappa</comment>
- <comment xml:lang="ia">Dossier</comment>
- <comment xml:lang="id">folder</comment>
- <comment xml:lang="it">Cartella</comment>
- <comment xml:lang="ja">フォルダー</comment>
- <comment xml:lang="kk">бума</comment>
- <comment xml:lang="ko">폴더</comment>
- <comment xml:lang="lt">aplankas</comment>
- <comment xml:lang="lv">mape</comment>
- <comment xml:lang="ms">Folder</comment>
- <comment xml:lang="nb">mappe</comment>
- <comment xml:lang="nl">map</comment>
- <comment xml:lang="nn">mappe</comment>
- <comment xml:lang="oc">dorsièr</comment>
- <comment xml:lang="pl">Katalog</comment>
- <comment xml:lang="pt">pasta</comment>
- <comment xml:lang="pt_BR">Pasta</comment>
- <comment xml:lang="ro">dosar</comment>
+ <comment>Folder</comment>
+ <comment xml:lang="uk">Тека</comment>
+ <comment xml:lang="sv">Mapp</comment>
<comment xml:lang="ru">Папка</comment>
- <comment xml:lang="sk">Priečinok</comment>
- <comment xml:lang="sl">mapa</comment>
- <comment xml:lang="sq">Kartelë</comment>
- <comment xml:lang="sr">фасцикла</comment>
- <comment xml:lang="sv">mapp</comment>
- <comment xml:lang="tr">dizin</comment>
- <comment xml:lang="uk">тека</comment>
- <comment xml:lang="vi">thư mục</comment>
- <comment xml:lang="zh_CN">文件夹</comment>
- <comment xml:lang="zh_TW">資料夾</comment>
+ <comment xml:lang="pt_BR">Pasta</comment>
+ <comment xml:lang="pl">Katalog</comment>
+ <comment xml:lang="ja">フォルダ</comment>
+ <comment xml:lang="it">Cartella</comment>
+ <comment xml:lang="gl">Cartafol</comment>
+ <comment xml:lang="eu">Karpeta</comment>
+ <comment xml:lang="es">carpeta</comment>
+ <comment xml:lang="de">Ordner</comment>
+ <comment xml:lang="be">папка</comment>
<generic-icon name="folder"/>
<alias type="x-directory/normal"/>
</mime-type>
<mime-type type="inode/fifo">
- <comment>pipe</comment>
- <comment xml:lang="ar">إنبوب</comment>
- <comment xml:lang="be@latin">kanvejer</comment>
- <comment xml:lang="bg">Конвейер</comment>
- <comment xml:lang="ca">conducte</comment>
- <comment xml:lang="cs">roura</comment>
- <comment xml:lang="da">datakanal</comment>
- <comment xml:lang="de">Pipe</comment>
- <comment xml:lang="el">Διοχέτευση</comment>
- <comment xml:lang="en_GB">pipe</comment>
- <comment xml:lang="eo">dukto</comment>
- <comment xml:lang="es">tubería</comment>
- <comment xml:lang="eu">kanalizazioa</comment>
- <comment xml:lang="fi">putki</comment>
- <comment xml:lang="fo">rør</comment>
- <comment xml:lang="fr">tube</comment>
- <comment xml:lang="ga">píopa</comment>
- <comment xml:lang="gl">tubería</comment>
- <comment xml:lang="he">צינור</comment>
- <comment xml:lang="hr">Slivnik</comment>
- <comment xml:lang="hu">adatcsatorna</comment>
- <comment xml:lang="ia">Tubo</comment>
- <comment xml:lang="id">pipa</comment>
- <comment xml:lang="it">Pipe</comment>
- <comment xml:lang="ja">パイプ</comment>
- <comment xml:lang="kk">арна</comment>
- <comment xml:lang="ko">파이프</comment>
- <comment xml:lang="lt">konvejeris</comment>
- <comment xml:lang="lv">programmkanāls</comment>
- <comment xml:lang="ms">Paip</comment>
- <comment xml:lang="nb">rør</comment>
- <comment xml:lang="nl">pijp</comment>
- <comment xml:lang="nn">røyr</comment>
- <comment xml:lang="oc">tub</comment>
- <comment xml:lang="pl">Potok</comment>
- <comment xml:lang="pt">canal</comment>
- <comment xml:lang="pt_BR">Pipe</comment>
- <comment xml:lang="ro">canal pipe</comment>
+ <comment>Pipe</comment>
+ <comment xml:lang="uk">Канал</comment>
+ <comment xml:lang="sv">Rör</comment>
<comment xml:lang="ru">Канал</comment>
- <comment xml:lang="sk">Rúra</comment>
- <comment xml:lang="sl">cev</comment>
- <comment xml:lang="sq">Pipe</comment>
- <comment xml:lang="sr">спојка</comment>
- <comment xml:lang="sv">rör</comment>
- <comment xml:lang="tr">boru</comment>
- <comment xml:lang="uk">канал</comment>
- <comment xml:lang="vi">ống dẫn</comment>
- <comment xml:lang="zh_CN">管道</comment>
- <comment xml:lang="zh_TW">管線</comment>
+ <comment xml:lang="pl">Potok</comment>
+ <comment xml:lang="ja">パイプ</comment>
+ <comment xml:lang="it">Pipe</comment>
+ <comment xml:lang="gl">Tubería</comment>
+ <comment xml:lang="eu">Kanalizazioa</comment>
+ <comment xml:lang="es">canalización</comment>
+ <comment xml:lang="de">Weiterleitung</comment>
+ <comment xml:lang="be">канал</comment>
</mime-type>
<mime-type type="inode/mount-point">
- <comment>mount point</comment>
- <comment xml:lang="ar">نقطة الوصْل</comment>
- <comment xml:lang="ast">puntu de montaxe</comment>
- <comment xml:lang="be@latin">punkt mantavańnia</comment>
- <comment xml:lang="bg">Точка на монтиране</comment>
- <comment xml:lang="ca">punt de muntatge</comment>
- <comment xml:lang="cs">přípojné místo</comment>
- <comment xml:lang="da">monteringspunkt</comment>
- <comment xml:lang="de">Einhängepunkt</comment>
- <comment xml:lang="el">Σημείο προσάρτησης</comment>
- <comment xml:lang="en_GB">mount point</comment>
- <comment xml:lang="eo">surmetingo</comment>
- <comment xml:lang="es">punto de montaje</comment>
- <comment xml:lang="eu">muntatze-puntua</comment>
- <comment xml:lang="fi">liitospiste</comment>
- <comment xml:lang="fo">ísetingarpunkt</comment>
- <comment xml:lang="fr">point d'accès</comment>
- <comment xml:lang="ga">pointe feistithe</comment>
- <comment xml:lang="gl">punto de montaxe</comment>
- <comment xml:lang="he">נקודת עיגון</comment>
- <comment xml:lang="hr">Točka montiranja</comment>
- <comment xml:lang="hu">csatolási pont</comment>
- <comment xml:lang="ia">Puncto de montage</comment>
- <comment xml:lang="id">titik mount</comment>
- <comment xml:lang="it">Punto di mount</comment>
- <comment xml:lang="ja">マウントポイント</comment>
- <comment xml:lang="kk">тіркеу нүктесі</comment>
- <comment xml:lang="ko">마운트 위치</comment>
- <comment xml:lang="lt">prijungimo taškas</comment>
- <comment xml:lang="lv">montēšanas punkts</comment>
- <comment xml:lang="ms">Titik lekapan</comment>
- <comment xml:lang="nb">monteringspunkt</comment>
- <comment xml:lang="nl">aankoppelingspunt</comment>
- <comment xml:lang="nn">monteringspunkt</comment>
- <comment xml:lang="oc">punt d'accès</comment>
- <comment xml:lang="pl">Punkt montowania</comment>
- <comment xml:lang="pt">ponto de montagem</comment>
- <comment xml:lang="pt_BR">Ponto de montagem</comment>
- <comment xml:lang="ro">loc montare</comment>
+ <comment>Mount point</comment>
+ <comment xml:lang="uk">Точка монтування</comment>
+ <comment xml:lang="sv">Monteringspunkt</comment>
<comment xml:lang="ru">Точка монтирования</comment>
- <comment xml:lang="sk">Miesto pripojenia</comment>
- <comment xml:lang="sl">priklopna točka</comment>
- <comment xml:lang="sq">Pikë montimi</comment>
- <comment xml:lang="sr">тачка прикључења</comment>
- <comment xml:lang="sv">monteringspunkt</comment>
- <comment xml:lang="tr">bağlama noktası</comment>
- <comment xml:lang="uk">точка монтування</comment>
- <comment xml:lang="vi">điểm lắp</comment>
- <comment xml:lang="zh_CN">挂载点</comment>
- <comment xml:lang="zh_TW">掛載點</comment>
+ <comment xml:lang="pt_BR">Ponto de montagem</comment>
+ <comment xml:lang="pl">Punkt montowania</comment>
+ <comment xml:lang="ja">マウント箇所</comment>
+ <comment xml:lang="it">Punto di mount</comment>
+ <comment xml:lang="gl">Punto de montaxe</comment>
+ <comment xml:lang="eu">Muntatze-puntua</comment>
+ <comment xml:lang="es">punto de montaje</comment>
+ <comment xml:lang="de">Einhängepunkt</comment>
+ <comment xml:lang="be">пункт мантавання</comment>
<sub-class-of type="inode/directory"/>
</mime-type>
<mime-type type="inode/socket">
- <comment>socket</comment>
- <comment xml:lang="ar">مقبس</comment>
- <comment xml:lang="be@latin">sokiet</comment>
- <comment xml:lang="bg">Гнездо</comment>
- <comment xml:lang="ca">sòcol</comment>
- <comment xml:lang="cs">socket</comment>
- <comment xml:lang="da">sokkel</comment>
- <comment xml:lang="de">Socket</comment>
- <comment xml:lang="el">Υποδοχή</comment>
- <comment xml:lang="en_GB">socket</comment>
- <comment xml:lang="eo">kontaktoskatolo</comment>
- <comment xml:lang="es">socket</comment>
- <comment xml:lang="eu">socketa</comment>
- <comment xml:lang="fi">pistoke</comment>
- <comment xml:lang="fo">sokkul</comment>
- <comment xml:lang="fr">connecteur réseau</comment>
- <comment xml:lang="ga">soicéad</comment>
- <comment xml:lang="gl">socket</comment>
- <comment xml:lang="he">נקודת חיבור</comment>
- <comment xml:lang="hr">Priključnica</comment>
- <comment xml:lang="hu">illesztőpont</comment>
- <comment xml:lang="ia">Socket</comment>
- <comment xml:lang="id">soket</comment>
- <comment xml:lang="it">Socket</comment>
- <comment xml:lang="ja">ソケット</comment>
- <comment xml:lang="kk">сокет</comment>
- <comment xml:lang="ko">소켓</comment>
- <comment xml:lang="lt">lizdas</comment>
- <comment xml:lang="lv">sokets</comment>
- <comment xml:lang="ms">Soket</comment>
- <comment xml:lang="nb">plugg</comment>
- <comment xml:lang="nl">socket</comment>
- <comment xml:lang="nn">sokkel</comment>
- <comment xml:lang="oc">connector ret</comment>
- <comment xml:lang="pl">Gniazdo</comment>
- <comment xml:lang="pt">tomada</comment>
- <comment xml:lang="pt_BR">Socket</comment>
- <comment xml:lang="ro">socket</comment>
- <comment xml:lang="ru">Сокет</comment>
- <comment xml:lang="sk">Soket</comment>
- <comment xml:lang="sl">vtič</comment>
- <comment xml:lang="sq">Socket</comment>
- <comment xml:lang="sr">прикључница</comment>
- <comment xml:lang="sv">uttag</comment>
- <comment xml:lang="tr">soket</comment>
+ <comment>Socket</comment>
<comment xml:lang="uk">сокет</comment>
- <comment xml:lang="vi">ổ cắm</comment>
- <comment xml:lang="zh_CN">套接字</comment>
- <comment xml:lang="zh_TW">socket</comment>
+ <comment xml:lang="sv">Uttag</comment>
+ <comment xml:lang="ru">Сокет</comment>
+ <comment xml:lang="pl">Gniazdo</comment>
+ <comment xml:lang="ja">ソケット</comment>
+ <comment xml:lang="it">Socket</comment>
+ <comment xml:lang="gl">Socket</comment>
+ <comment xml:lang="eu">Socket-a</comment>
+ <comment xml:lang="es">zócalo</comment>
+ <comment xml:lang="de">Socket</comment>
+ <comment xml:lang="be">сокет</comment>
</mime-type>
<mime-type type="inode/symlink">
- <comment>symbolic link</comment>
- <comment xml:lang="ar">وصلة رمزية</comment>
- <comment xml:lang="ast">enllaz simbólicu</comment>
- <comment xml:lang="az">simvolik körpü</comment>
- <comment xml:lang="be@latin">symbalnaja spasyłka</comment>
- <comment xml:lang="bg">Символна връзка</comment>
- <comment xml:lang="ca">enllaç simbòlic</comment>
- <comment xml:lang="cs">symbolický odkaz</comment>
- <comment xml:lang="cy">cyswllt symbolaidd</comment>
- <comment xml:lang="da">symbolsk henvisning</comment>
- <comment xml:lang="de">Symbolische Verknüpfung</comment>
- <comment xml:lang="el">Συμβολικός σύνδεσμος</comment>
- <comment xml:lang="en_GB">symbolic link</comment>
- <comment xml:lang="eo">simbola ligilo</comment>
- <comment xml:lang="es">enlace simbólico</comment>
- <comment xml:lang="eu">esteka sinbolikoa</comment>
- <comment xml:lang="fi">symbolinen linkki</comment>
- <comment xml:lang="fo">tykislig leinkja</comment>
- <comment xml:lang="fr">lien symbolique</comment>
- <comment xml:lang="ga">nasc siombalach</comment>
- <comment xml:lang="gl">ligazón simbólica</comment>
- <comment xml:lang="he">קישור סימבולי</comment>
- <comment xml:lang="hr">Simbolička poveznica</comment>
- <comment xml:lang="hu">szimbolikus link</comment>
- <comment xml:lang="ia">Ligamine symbolic</comment>
- <comment xml:lang="id">taut simbolik</comment>
- <comment xml:lang="it">Collegamento simbolico</comment>
- <comment xml:lang="ja">シンボリックリンク</comment>
- <comment xml:lang="ka">სიმბოლური ბმული</comment>
- <comment xml:lang="kk">символдық сілтеме</comment>
- <comment xml:lang="ko">심볼릭 링크</comment>
- <comment xml:lang="lt">simbolinė nuoroda</comment>
- <comment xml:lang="lv">simboliskā saite</comment>
- <comment xml:lang="ms">Pautan simbolik</comment>
- <comment xml:lang="nb">symbolsk lenke</comment>
- <comment xml:lang="nl">symbolische koppeling</comment>
- <comment xml:lang="nn">symbolsk lenkje</comment>
- <comment xml:lang="oc">ligam simbolic</comment>
- <comment xml:lang="pl">Dowiązanie symboliczne</comment>
- <comment xml:lang="pt">ligação simbólica</comment>
- <comment xml:lang="pt_BR">Ligação simbólica</comment>
- <comment xml:lang="ro">legătură simbolică</comment>
+ <comment>Symbolic link</comment>
+ <comment xml:lang="uk">Символічне посилання</comment>
+ <comment xml:lang="sv">Symbolisk länk</comment>
<comment xml:lang="ru">Символьная ссылка</comment>
- <comment xml:lang="sk">Symbolický odkaz</comment>
- <comment xml:lang="sl">simbolna povezava</comment>
- <comment xml:lang="sq">Lidhje simbolike</comment>
- <comment xml:lang="sr">симболичка веза</comment>
- <comment xml:lang="sv">symbolisk länk</comment>
- <comment xml:lang="tr">sembolik bağlantı</comment>
- <comment xml:lang="uk">символічне посилання</comment>
- <comment xml:lang="vi">liên kết tượng trưng</comment>
- <comment xml:lang="zh_CN">符号链接</comment>
- <comment xml:lang="zh_TW">符號鏈結</comment>
+ <comment xml:lang="pt_BR">Link simbólico</comment>
+ <comment xml:lang="pl">Dowiązanie symboliczne</comment>
+ <comment xml:lang="ja">シンボリックリンク</comment>
+ <comment xml:lang="it">Collegamento simbolico</comment>
+ <comment xml:lang="gl">Ligazón simbólica</comment>
+ <comment xml:lang="eu">Esteka sinbolikoa</comment>
+ <comment xml:lang="es">enlace simbólico</comment>
+ <comment xml:lang="de">Symbolische Verknüpfung</comment>
+ <comment xml:lang="be">сімвалічная спасылка</comment>
</mime-type>
<mime-type type="message/delivery-status">
- <comment>mail delivery report</comment>
- <comment xml:lang="ar">تقرير تسليم البريد</comment>
- <comment xml:lang="az">poçt yollama raportu</comment>
- <comment xml:lang="be@latin">rapart ab dastaŭcy pošty</comment>
- <comment xml:lang="bg">Отчет за пристигналата поща</comment>
- <comment xml:lang="ca">informe de lliurament de correu</comment>
- <comment xml:lang="cs">zpráva o doručení pošty</comment>
- <comment xml:lang="cy">Adroddiad trosgludo post</comment>
- <comment xml:lang="da">postleveringsrapport</comment>
- <comment xml:lang="de">E-Mail-Zustellungsbericht</comment>
- <comment xml:lang="el">Αναφορά παράδοσης μηνύματος</comment>
- <comment xml:lang="en_GB">mail delivery report</comment>
- <comment xml:lang="eo">raporto pri transdono de retpoŝto</comment>
- <comment xml:lang="es">informe de entrega de correo</comment>
- <comment xml:lang="eu">posta banaketako txostena</comment>
- <comment xml:lang="fi">viestin jakeluilmoitus</comment>
- <comment xml:lang="fo">post útberingarfrásøgn</comment>
- <comment xml:lang="fr">rapport de livraison de courriels</comment>
- <comment xml:lang="ga">tuairisc sheachadta r-phoist</comment>
- <comment xml:lang="gl">informe de entrega de correo</comment>
- <comment xml:lang="he">דוח העברת דואר</comment>
- <comment xml:lang="hr">Izvještaj dostave pošte</comment>
- <comment xml:lang="hu">jelentés levélkézbesítésről</comment>
- <comment xml:lang="ia">Reporto de livration de e-mail</comment>
- <comment xml:lang="id">laporan pengantaran surat</comment>
- <comment xml:lang="it">Rapporto di consegna posta</comment>
- <comment xml:lang="ja">メール配送ポート</comment>
- <comment xml:lang="kk">пошта жеткізілгені туралы отчет</comment>
- <comment xml:lang="ko">메일 배달 보고서</comment>
- <comment xml:lang="lt">pašto pristatymo ataskaita</comment>
- <comment xml:lang="lv">pasta piegādes atskaite</comment>
- <comment xml:lang="ms">Laporan penghantaran mel</comment>
- <comment xml:lang="nb">e-postleveranserapport</comment>
- <comment xml:lang="nl">e-mail-bezorgingsbericht</comment>
- <comment xml:lang="nn">e-post-leveringsrapport</comment>
- <comment xml:lang="oc">rapòrt de liurason de corrièrs electronics</comment>
- <comment xml:lang="pl">Raport z dostarczenia poczty</comment>
- <comment xml:lang="pt">relatório de entrega de email</comment>
- <comment xml:lang="pt_BR">Relatório de entrega de correspondência</comment>
- <comment xml:lang="ro">raport de trimitere email</comment>
+ <comment>Mail delivery report</comment>
+ <comment xml:lang="uk">звіт щодо доставлення пошти</comment>
+ <comment xml:lang="sv">E-postleveransrapport</comment>
<comment xml:lang="ru">Отчёт о доставке сообщения</comment>
- <comment xml:lang="sk">Správa o doručení pošty</comment>
- <comment xml:lang="sl">poročilo dostave pošte</comment>
- <comment xml:lang="sq">Raport mbi dorëzimin e mesazhit</comment>
- <comment xml:lang="sr">извештај доставе поруке</comment>
- <comment xml:lang="sv">e-postleveransrapport</comment>
- <comment xml:lang="tr">posta iletim raporu</comment>
- <comment xml:lang="uk">звіт про доставку пошти</comment>
- <comment xml:lang="vi">thông báo phát thư</comment>
- <comment xml:lang="zh_CN">邮件投递报告</comment>
- <comment xml:lang="zh_TW">郵件寄送回報</comment>
+ <comment xml:lang="pl">Raport z dostarczenia poczty</comment>
+ <comment xml:lang="it">Rapporto di consegna posta</comment>
+ <comment xml:lang="gl">Informe de envío de coreo electrónico</comment>
+ <comment xml:lang="es">informe de entrega de correo</comment>
+ <comment xml:lang="de">E-Mail-Zustellungsbericht</comment>
+ <comment xml:lang="be">справаздача пра дастаўку пошты</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="message/disposition-notification">
- <comment>mail disposition report</comment>
- <comment xml:lang="ar">تقرير ترتيب البريد</comment>
- <comment xml:lang="az">poçt qayıtma raportu</comment>
- <comment xml:lang="be@latin">rapart ab raźmiaščeńni pošty</comment>
- <comment xml:lang="bg">Отчет за състоянието на пощата</comment>
- <comment xml:lang="ca">informe de disposició de correu</comment>
- <comment xml:lang="cs">zpráva o předání pošty</comment>
- <comment xml:lang="cy">adroddiad ffurf post</comment>
- <comment xml:lang="da">postdisponeringsrapport</comment>
- <comment xml:lang="de">E-Mail-Übertragungsbericht</comment>
- <comment xml:lang="el">Αναφορά διάθεσης μηνύματος</comment>
- <comment xml:lang="en_GB">mail disposition report</comment>
- <comment xml:lang="eo">raporto pri dispono de retpoŝto</comment>
- <comment xml:lang="es">informe de disposición de correo</comment>
- <comment xml:lang="eu">posta joerako txostena</comment>
- <comment xml:lang="fi">viestin kuittausilmoitus</comment>
- <comment xml:lang="fo">post avhendingarfrásøgn</comment>
- <comment xml:lang="fr">rapport de disposition de courriels</comment>
- <comment xml:lang="ga">tuairisc chóirithe r-phoist</comment>
- <comment xml:lang="gl">informe de disposición de correo</comment>
- <comment xml:lang="he">דוח אספקת דואר</comment>
- <comment xml:lang="hr">Izvještaj smještaja e-pošte</comment>
- <comment xml:lang="hu">jelentés levélkidobásról</comment>
- <comment xml:lang="ia">Reporto de disposition de e-mail</comment>
- <comment xml:lang="id">laporan disposisi surat</comment>
- <comment xml:lang="it">Rapporto di disposizione posta</comment>
- <comment xml:lang="ja">メール停止レポート</comment>
- <comment xml:lang="kk">пошта жылжытылғаны туралы отчет</comment>
- <comment xml:lang="ko">메일 처리 보고서</comment>
- <comment xml:lang="lt">pašto charakteristikos ataskaita</comment>
- <comment xml:lang="lv">pasta izvietojuma atskaite</comment>
- <comment xml:lang="ms">Laporan pelupusan mel</comment>
- <comment xml:lang="nb">e-postdispositionsrapport</comment>
- <comment xml:lang="nl">e-mail-plaatsingsbericht</comment>
- <comment xml:lang="nn">e-post-disposisjonsrapport</comment>
- <comment xml:lang="oc">rapòrt de disposicion de corrièrs electronics</comment>
- <comment xml:lang="pl">Raport z wysyłania poczty</comment>
- <comment xml:lang="pt">relatório de disposição de email</comment>
- <comment xml:lang="pt_BR">Relatório de disposição de correspondência</comment>
- <comment xml:lang="ro">confirmare primire email</comment>
+ <comment>Mail disposition report</comment>
+ <comment xml:lang="uk">звіт щодо розташування пошти</comment>
+ <comment xml:lang="sv">E-postdispositionsrapport</comment>
<comment xml:lang="ru">Отчёт о перемещении почты</comment>
- <comment xml:lang="sk">Správa o odovzdaní pošty</comment>
- <comment xml:lang="sl">poročilo razporeditve pošte</comment>
- <comment xml:lang="sq">Raport mbi njoftimin e mesazhit</comment>
- <comment xml:lang="sr">извештај слања поруке</comment>
- <comment xml:lang="sv">e-postdispositionsrapport</comment>
- <comment xml:lang="tr">posta silinme raporu</comment>
- <comment xml:lang="uk">звіт про розташування пошти</comment>
- <comment xml:lang="vi">thông báo chuyển nhượng thư</comment>
- <comment xml:lang="zh_CN">邮件接收报告</comment>
- <comment xml:lang="zh_TW">郵件處置回報</comment>
+ <comment xml:lang="pl">Raport z wysyłania poczty</comment>
+ <comment xml:lang="it">Rapporto di disposizione posta</comment>
+ <comment xml:lang="es">informe de disposición de correo</comment>
+ <comment xml:lang="de">E-Mail-Übertragungsbericht</comment>
+ <comment xml:lang="be">справаздача пра дзеянні з поштай</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="message/external-body">
- <comment>reference to remote file</comment>
- <comment xml:lang="ar">مرجع إلى ملف بعيد</comment>
- <comment xml:lang="az">uzaq fayla göstəriş</comment>
- <comment xml:lang="be@latin">spasyłka da addalenaha fajłu</comment>
- <comment xml:lang="bg">Препратка към отдалечен файл</comment>
- <comment xml:lang="ca">referència a fitxer remot</comment>
- <comment xml:lang="cs">odkaz na vzdálený soubor</comment>
- <comment xml:lang="cy">cyfeiriad at ffeil bell</comment>
- <comment xml:lang="da">reference til fjern fil</comment>
- <comment xml:lang="de">Verweis auf entfernte Datei</comment>
- <comment xml:lang="el">Αναφορά σε απομακρυσμένο αρχείο</comment>
- <comment xml:lang="en_GB">reference to remote file</comment>
- <comment xml:lang="eo">referenco al fora dosiero</comment>
- <comment xml:lang="es">referencia a un archivo remoto</comment>
- <comment xml:lang="eu">erreferentzia urruneko fitxategiari</comment>
- <comment xml:lang="fi">viittaus etätiedostoon</comment>
- <comment xml:lang="fo">tilvísing til fjarfílu</comment>
- <comment xml:lang="fr">référence au fichier distant</comment>
- <comment xml:lang="ga">tagairt do chomhad cianda</comment>
- <comment xml:lang="gl">referencia a un ficheiro remoto</comment>
- <comment xml:lang="he">התיחסות לקובץ מרוחק</comment>
- <comment xml:lang="hr">Preporuka na udaljenu datoteku</comment>
- <comment xml:lang="hu">hivatkozás távoli fájlra</comment>
- <comment xml:lang="ia">Referentia a un file remote</comment>
- <comment xml:lang="id">referensi ke berkas jarak jauh</comment>
- <comment xml:lang="it">Riferimento a file remoto</comment>
- <comment xml:lang="ja">リモートファイルへの参照</comment>
- <comment xml:lang="kk">қашықтағы файлға сілтеме</comment>
- <comment xml:lang="ko">원격 파일 참조</comment>
- <comment xml:lang="lt">nuoroda į nutolusį failą</comment>
- <comment xml:lang="lv">norāde uz attālinātu datni</comment>
- <comment xml:lang="ms">Rujukan ke fail jauh</comment>
- <comment xml:lang="nb">referanse til ekstern fil</comment>
- <comment xml:lang="nl">verwijzing naar bestand op afstand</comment>
- <comment xml:lang="nn">referanse til fil over nettverk</comment>
- <comment xml:lang="oc">referéncia al fichièr distant</comment>
- <comment xml:lang="pl">Odwołanie do pliku zdalnego</comment>
- <comment xml:lang="pt">referência a um ficheiro remoto</comment>
- <comment xml:lang="pt_BR">Referência para arquivo remoto</comment>
- <comment xml:lang="ro">referință fișier la distanță</comment>
- <comment xml:lang="ru">Ссылка на удалённый файл</comment>
- <comment xml:lang="sk">Odkaz na vzdialený súbor</comment>
- <comment xml:lang="sl">sklic do oddaljene datoteke</comment>
- <comment xml:lang="sq">Referim për tek file në distancë</comment>
- <comment xml:lang="sr">упута на удаљену датотеку</comment>
- <comment xml:lang="sv">referens till fjärrfil</comment>
- <comment xml:lang="tr">uzaktaki dosyaya başvuru</comment>
+ <comment>Reference to remote file</comment>
<comment xml:lang="uk">посилання на віддалений файл</comment>
- <comment xml:lang="vi">tham chiếu đến tập tin ở xa</comment>
- <comment xml:lang="zh_CN">到远程文件的引用</comment>
- <comment xml:lang="zh_TW">遠端檔案的參照</comment>
+ <comment xml:lang="sv">Referens till fjärrfil</comment>
+ <comment xml:lang="ru">Ссылка на удалённый файл</comment>
+ <comment xml:lang="pl">Odwołanie do pliku zdalnego</comment>
+ <comment xml:lang="it">Riferimento a file remoto</comment>
+ <comment xml:lang="es">referencia a archivo remoto</comment>
+ <comment xml:lang="de">Verweis auf entfernte Datei</comment>
+ <comment xml:lang="be">спасылка на выдалены файл</comment>
<generic-icon name="text-x-generic"/>
</mime-type>
<mime-type type="message/news">
<comment>Usenet news message</comment>
- <comment xml:lang="ar">رسالة أخبار Usenet</comment>
- <comment xml:lang="az">Usenet xəbərlər ismarışı</comment>
- <comment xml:lang="be@latin">Navina Usenet</comment>
- <comment xml:lang="bg">Съобщение — Usenet</comment>
- <comment xml:lang="ca">missatge de notícies Usenet</comment>
- <comment xml:lang="cs">příspěvek do diskusních skupin Usenet</comment>
- <comment xml:lang="cy">Neges newyddion Usenet</comment>
- <comment xml:lang="da">Usenetnyhedsmeddelelse</comment>
- <comment xml:lang="de">Usenet-News-Nachricht</comment>
- <comment xml:lang="el">Μήνυμα ομάδων συζητήσεων Usenet</comment>
- <comment xml:lang="en_GB">Usenet news message</comment>
- <comment xml:lang="eo">novaĵmesaĝo de Usenet</comment>
- <comment xml:lang="es">mensaje de noticias de Usenet</comment>
- <comment xml:lang="eu">Usenet berrien mezua</comment>
- <comment xml:lang="fi">nyyssiviesti</comment>
- <comment xml:lang="fo">Usenet news boð</comment>
- <comment xml:lang="fr">message de groupe d'échange Usenet</comment>
- <comment xml:lang="ga">teachtaireacht nuachta Usenet</comment>
- <comment xml:lang="gl">mensaxes de noticias de Usenet</comment>
- <comment xml:lang="he">הודעת חדשות של Usenet</comment>
- <comment xml:lang="hr">Usenet poruka novosti</comment>
- <comment xml:lang="hu">USENET-hírcsoportüzenet</comment>
- <comment xml:lang="ia">Message de gruppo Usenet</comment>
- <comment xml:lang="id">Pesan berita Usenet</comment>
- <comment xml:lang="it">Messaggio news Usenet</comment>
- <comment xml:lang="ja">Usenet news メッセージ</comment>
- <comment xml:lang="kk">Usenet жаңалық мәлімдемесі</comment>
- <comment xml:lang="ko">유즈넷 뉴스 메시지</comment>
- <comment xml:lang="lt">Usenet naujienų žinutė</comment>
- <comment xml:lang="lv">Usenet jaunumu ziņojums</comment>
- <comment xml:lang="ms">Mesej berita USENET</comment>
- <comment xml:lang="nb">Usenet nyhetsmelding</comment>
- <comment xml:lang="nl">Usenet-nieuwsbericht</comment>
- <comment xml:lang="nn">USENET diskusjonsmelding</comment>
- <comment xml:lang="oc">messatge de grop d'escambi Usenet</comment>
- <comment xml:lang="pl">Wiadomość grupy dyskusyjnej</comment>
- <comment xml:lang="pt">mensagem de notícias Usenet</comment>
- <comment xml:lang="pt_BR">Mensagem de notícias da Usenet</comment>
- <comment xml:lang="ro">Mesaj Usenet de știri </comment>
- <comment xml:lang="ru">Новостное сообщение Usenet</comment>
- <comment xml:lang="sk">Príspevok do diskusných skupín Usenet</comment>
- <comment xml:lang="sl">novičarsko sporočilo Usenet</comment>
- <comment xml:lang="sq">Mesazh lajmesh Usenet</comment>
- <comment xml:lang="sr">Порука новости Јузнета</comment>
- <comment xml:lang="sv">Usenet-diskussionsgruppsmeddelande</comment>
- <comment xml:lang="tr">Usenet haber iletisi</comment>
- <comment xml:lang="uk">повідомлення новин Usenet</comment>
- <comment xml:lang="vi">Thông điệp tin tức USENET</comment>
- <comment xml:lang="zh_CN">Usenet 新闻信</comment>
<comment xml:lang="zh_TW">Usenet 新聞訊息</comment>
+ <comment xml:lang="zh_CN">Usenet 新闻信</comment>
+ <comment xml:lang="vi">Thông điệp tin tức USENET</comment>
+ <comment xml:lang="uk">повідомлення новин Usenet</comment>
+ <comment xml:lang="tr">Usenet haber iletisi</comment>
+ <comment xml:lang="sv">Usenet-diskussionsgruppsmeddelande</comment>
+ <comment xml:lang="sr">Порука новости Јузнета</comment>
+ <comment xml:lang="sq">mesazh lajmesh Usenet</comment>
+ <comment xml:lang="sl">novičarsko sporočilo Usenet</comment>
+ <comment xml:lang="si">යූස්නෙට් පුවත් පණිවිඩය</comment>
+ <comment xml:lang="sk">Príspevok do diskusných skupín Usenet</comment>
+ <comment xml:lang="ru">Новостное сообщение Usenet</comment>
+ <comment xml:lang="ro">Mesaj Usenet de știri </comment>
+ <comment xml:lang="pt_BR">Mensagem de notícias da Usenet</comment>
+ <comment xml:lang="pt">mensagem de notícias Usenet</comment>
+ <comment xml:lang="pl">Wiadomość grupy dyskusyjnej</comment>
+ <comment xml:lang="oc">messatge de grop d'escambi Usenet</comment>
+ <comment xml:lang="nn">USENET diskusjonsmelding</comment>
+ <comment xml:lang="nl">Usenet-nieuwsbericht</comment>
+ <comment xml:lang="nb">Usenet nyhetsmelding</comment>
+ <comment xml:lang="ms">Mesej berita USENET</comment>
+ <comment xml:lang="lv">Usenet jaunumu ziņojums</comment>
+ <comment xml:lang="lt">Usenet naujienų žinutė</comment>
+ <comment xml:lang="ko">유즈넷 뉴스 메시지</comment>
+ <comment xml:lang="kk">Usenet жаңалық мәлімдемесі</comment>
+ <comment xml:lang="ja">Usenet news メッセージ</comment>
+ <comment xml:lang="it">Messaggio news Usenet</comment>
+ <comment xml:lang="is">USENET fréttaskilaboð</comment>
+ <comment xml:lang="id">Pesan berita Usenet</comment>
+ <comment xml:lang="ia">Message de gruppo Usenet</comment>
+ <comment xml:lang="hu">USENET-hírcsoportüzenet</comment>
+ <comment xml:lang="hr">Usenet poruka novosti</comment>
+ <comment xml:lang="he">הודעת חדשות של Usenet</comment>
+ <comment xml:lang="gl">mensaxes de noticias de Usenet</comment>
+ <comment xml:lang="ga">teachtaireacht nuachta Usenet</comment>
+ <comment xml:lang="fur">messaç gnovis Usenet</comment>
+ <comment xml:lang="fr">message de groupe d'échange Usenet</comment>
+ <comment xml:lang="fo">Usenet news boð</comment>
+ <comment xml:lang="fi">nyyssiviesti</comment>
+ <comment xml:lang="eu">Usenet berrien mezua</comment>
+ <comment xml:lang="es">mensaje de noticias de Usenet</comment>
+ <comment xml:lang="eo">novaĵmesaĝo de Usenet</comment>
+ <comment xml:lang="en_GB">Usenet news message</comment>
+ <comment xml:lang="el">Μήνυμα ομάδων συζητήσεων Usenet</comment>
+ <comment xml:lang="de">Usenet-News-Nachricht</comment>
+ <comment xml:lang="da">Usenet-nyhedsmeddelelse</comment>
+ <comment xml:lang="cy">Neges newyddion Usenet</comment>
+ <comment xml:lang="cs">příspěvek do diskusních skupin Usenet</comment>
+ <comment xml:lang="ca">missatge de notícies Usenet</comment>
+ <comment xml:lang="bg">Съобщение — Usenet</comment>
+ <comment xml:lang="be@latin">Navina Usenet</comment>
+ <comment xml:lang="be">навіна Usenet</comment>
+ <comment xml:lang="az">Usenet xəbərlər ismarışı</comment>
+ <comment xml:lang="ar">رسالة أخبار Usenet</comment>
+ <comment xml:lang="af">Usenet-nuusboodskap</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="Article" type="string" offset="0"/>
- <match value="Path:" type="string" offset="0"/>
- <match value="Xref:" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="Article" offset="0"/>
+ <match type="string" value="Path:" offset="0"/>
+ <match type="string" value="Xref:" offset="0"/>
</magic>
</mime-type>
<mime-type type="message/partial">
- <comment>partial email message</comment>
- <comment xml:lang="ar">رسالة البريد الإلكتروني الجزئية</comment>
- <comment xml:lang="az">qismi poçt ismarışı</comment>
- <comment xml:lang="be@latin">niapoŭny list email</comment>
- <comment xml:lang="bg">Част от електронно писмо</comment>
- <comment xml:lang="ca">missatge de correu electrònic parcial</comment>
- <comment xml:lang="cs">částečná e-mailová zpráva</comment>
- <comment xml:lang="cy">darn o neges e-bost</comment>
- <comment xml:lang="da">delvis postmeddelelse</comment>
- <comment xml:lang="de">E-Mail-Nachrichtenfragment</comment>
- <comment xml:lang="el">Τμηματικό ηλ. μήνυμα</comment>
- <comment xml:lang="en_GB">partial email message</comment>
- <comment xml:lang="eo">parta retpoŝta mesaĝo</comment>
- <comment xml:lang="es">mensaje de correo electrónico parcial</comment>
- <comment xml:lang="eu">posta mezu partziala</comment>
- <comment xml:lang="fi">osittainen sähköpostiviesti</comment>
- <comment xml:lang="fr">message partiel de courriel</comment>
- <comment xml:lang="ga">teachtaireacht ríomhphoist neamhiomlán</comment>
- <comment xml:lang="gl">mensaxe de correo electrónico parcial</comment>
- <comment xml:lang="he">מסר דוא״ל חלקי</comment>
- <comment xml:lang="hr">Nepotpuna poruka e-pošte</comment>
- <comment xml:lang="hu">részleges elektronikus levél</comment>
- <comment xml:lang="ia">Message de e-mail partial</comment>
- <comment xml:lang="id">pesan email sebagian</comment>
- <comment xml:lang="it">Messaggio email parziale</comment>
- <comment xml:lang="ja">部分メールメッセージ</comment>
- <comment xml:lang="kk">электронды поштаның үзінді мәлімдемесі</comment>
- <comment xml:lang="ko">전자 우편 메시지 일부</comment>
- <comment xml:lang="lt">nepilnas el. laiškas</comment>
- <comment xml:lang="lv">daļēja e-pasta vēstule</comment>
- <comment xml:lang="ms">Bahagian mesej emel</comment>
- <comment xml:lang="nb">del av e-postmelding</comment>
- <comment xml:lang="nl">gedeeltelijk e-mailbericht</comment>
- <comment xml:lang="nn">del av e-post-melding</comment>
- <comment xml:lang="oc">messatge parcial de corrièr electronic</comment>
- <comment xml:lang="pl">Częściowa wiadomość e-mail</comment>
- <comment xml:lang="pt">mensagem parcial de email</comment>
- <comment xml:lang="pt_BR">Mensagem de e-mail parcial</comment>
- <comment xml:lang="ro">mesaj de email parțial</comment>
- <comment xml:lang="ru">Фрагмент сообщения электронной почты</comment>
- <comment xml:lang="sk">Čiastočná e-mailová správa</comment>
- <comment xml:lang="sl">delno elektronsko sporočilo</comment>
- <comment xml:lang="sq">Mesazh poste i pjesëshëm</comment>
- <comment xml:lang="sr">делимична порука ел. поште</comment>
- <comment xml:lang="sv">del av e-postmeddelande</comment>
- <comment xml:lang="tr">kısmi eposta iletisi</comment>
+ <comment>Partial email message</comment>
<comment xml:lang="uk">часткове поштове повідомлення</comment>
- <comment xml:lang="vi">thư điện tử riêng phần</comment>
- <comment xml:lang="zh_CN">部分电子邮件</comment>
- <comment xml:lang="zh_TW">部份電子郵件訊息</comment>
+ <comment xml:lang="sv">Del av e-postmeddelande</comment>
+ <comment xml:lang="ru">Фрагмент сообщения электронной почты</comment>
+ <comment xml:lang="pl">Częściowa wiadomość e-mail</comment>
+ <comment xml:lang="it">Messaggio email parziale</comment>
+ <comment xml:lang="es">mensaje de correo electrónico parcial</comment>
+ <comment xml:lang="de">E-Mail-Nachrichtenfragment</comment>
+ <comment xml:lang="be">частка электроннага ліста</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="message/rfc822">
- <comment>email message</comment>
- <comment xml:lang="ar">رسالة البريد الإلكتروني</comment>
- <comment xml:lang="be@latin">list email</comment>
- <comment xml:lang="bg">Съобщение по електронната поща</comment>
- <comment xml:lang="ca">missatge de correu electrònic</comment>
- <comment xml:lang="cs">e-mailová zpráva</comment>
- <comment xml:lang="da">postmeddelelse</comment>
- <comment xml:lang="de">E-Mail-Nachricht</comment>
- <comment xml:lang="el">Ηλ. μήνυμα</comment>
- <comment xml:lang="en_GB">email message</comment>
- <comment xml:lang="eo">retpoŝta mesaĝo</comment>
- <comment xml:lang="es">mensaje de correo electrónico</comment>
- <comment xml:lang="eu">helbide elektronikoen mezua</comment>
- <comment xml:lang="fi">sähköpostiviesti</comment>
- <comment xml:lang="fo">t-post boð</comment>
- <comment xml:lang="fr">message de courriel</comment>
- <comment xml:lang="ga">teachtaireacht ríomhphoist</comment>
- <comment xml:lang="gl">mensaxe de correo electrónico</comment>
- <comment xml:lang="he">הודעת דואר אלקטרוני</comment>
- <comment xml:lang="hr">Poruka e-pošte</comment>
- <comment xml:lang="hu">elektronikus levél</comment>
- <comment xml:lang="ia">Message de e-mail</comment>
- <comment xml:lang="id">pesan email</comment>
- <comment xml:lang="it">Messaggio email</comment>
- <comment xml:lang="ja">メール本文</comment>
- <comment xml:lang="kk">пошталық мәлімдеме</comment>
- <comment xml:lang="ko">전자 우편 본문</comment>
- <comment xml:lang="lt">el. laiškas</comment>
- <comment xml:lang="lv">e-pasta vēstule</comment>
- <comment xml:lang="ms">Mesej emel</comment>
- <comment xml:lang="nb">e-postmelding</comment>
- <comment xml:lang="nl">e-mailbericht</comment>
- <comment xml:lang="nn">e-postmelding</comment>
- <comment xml:lang="oc">messatge de corrièr electronic</comment>
- <comment xml:lang="pl">Wiadomość e-mail</comment>
- <comment xml:lang="pt">mensagem de email</comment>
- <comment xml:lang="pt_BR">Mensagem de e-mail</comment>
- <comment xml:lang="ro">mesaj email</comment>
+ <comment>Email message</comment>
+ <comment xml:lang="uk">поштове повідомлення</comment>
+ <comment xml:lang="sv">E-postmeddelande</comment>
<comment xml:lang="ru">Почтовое сообщение</comment>
- <comment xml:lang="sk">E-mailová správa</comment>
- <comment xml:lang="sl">sporočilo elektronske pošte</comment>
- <comment xml:lang="sq">Mesazh poste</comment>
- <comment xml:lang="sr">порука ел. поште</comment>
- <comment xml:lang="sv">e-postmeddelande</comment>
- <comment xml:lang="tr">eposta iletisi</comment>
- <comment xml:lang="uk">повідомлення email</comment>
- <comment xml:lang="vi">thư điện tử</comment>
- <comment xml:lang="zh_CN">电子邮件</comment>
- <comment xml:lang="zh_TW">電子郵件內容</comment>
+ <comment xml:lang="pt_BR">Mensagem de e-mail</comment>
+ <comment xml:lang="pl">Wiadomość e-mail</comment>
+ <comment xml:lang="it">Messaggio email</comment>
+ <comment xml:lang="gl">Mensaxe de correo electrónico</comment>
+ <comment xml:lang="es">mensaje de correo electrónico</comment>
+ <comment xml:lang="de">E-Mail-Nachricht</comment>
+ <comment xml:lang="be">электронны ліст</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="#! rnews" type="string" offset="0"/>
- <match value="Forward to" type="string" offset="0"/>
- <match value="From:" type="string" offset="0"/>
- <match value="N#! rnews" type="string" offset="0"/>
- <match value="Pipe to" type="string" offset="0"/>
- <match value="Received:" type="string" offset="0"/>
- <match value="Relay-Version:" type="string" offset="0"/>
- <match value="Return-Path:" type="string" offset="0"/>
- <match value="Return-path:" type="string" offset="0"/>
- <match value="Subject: " type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#! rnews" offset="0"/>
+ <match type="string" value="Content-Type:" offset="0"/>
+ <match type="string" value="Forward to" offset="0"/>
+ <match type="string" value="From:" offset="0"/>
+ <match type="string" value="N#! rnews" offset="0"/>
+ <match type="string" value="Pipe to" offset="0"/>
+ <match type="string" value="Received:" offset="0"/>
+ <match type="string" value="Relay-Version:" offset="0"/>
+ <match type="string" value="Return-Path:" offset="0"/>
+ <match type="string" value="Return-path:" offset="0"/>
+ <match type="string" value="Subject: " offset="0"/>
+ <match type="string" value="To:" offset="0"/>
</magic>
<glob pattern="*.eml"/>
</mime-type>
<mime-type type="message/x-gnu-rmail">
<comment>GNU mail message</comment>
- <comment xml:lang="ar">رسالة بريد جنو</comment>
- <comment xml:lang="az">GNU poçt ismarışı</comment>
- <comment xml:lang="be@latin">List GNU</comment>
- <comment xml:lang="bg">Съобщение — GNU mail</comment>
- <comment xml:lang="ca">missatge de GNU mail</comment>
- <comment xml:lang="cs">zpráva GNU mail</comment>
- <comment xml:lang="cy">Neges E-Bost GNU</comment>
- <comment xml:lang="da">GNU-postmeddelelse</comment>
- <comment xml:lang="de">GNU-Mail-Nachricht</comment>
- <comment xml:lang="el">Μήνυμα αλληλογραφίας GNU</comment>
- <comment xml:lang="en_GB">GNU mail message</comment>
- <comment xml:lang="eo">mesaĝo de GNU mail</comment>
- <comment xml:lang="es">mensaje de correo de GNU</comment>
- <comment xml:lang="eu">GNU posta mezua</comment>
- <comment xml:lang="fi">GNU-postiviesti</comment>
- <comment xml:lang="fo">GNU mail boð</comment>
- <comment xml:lang="fr">message de courriel GNU</comment>
- <comment xml:lang="ga">teachtaireacht r-phoist GNU</comment>
- <comment xml:lang="gl">mensaxe de correo electrónico de GNU</comment>
- <comment xml:lang="he">הודעת דואר של GNU</comment>
- <comment xml:lang="hr">GNU poruka pošte</comment>
- <comment xml:lang="hu">GNU elektronikus levél</comment>
- <comment xml:lang="ia">Message electronic de GNU</comment>
- <comment xml:lang="id">Pesan surat GNU</comment>
- <comment xml:lang="it">Messaggio GNU mail</comment>
- <comment xml:lang="ja">GNU メールメッセージ</comment>
- <comment xml:lang="ka">GNU mail შეტყობინება</comment>
- <comment xml:lang="kk">GNU пошта хабарламасы</comment>
- <comment xml:lang="ko">GNU 메일 메시지</comment>
- <comment xml:lang="lt">GNU pašto žinutė</comment>
- <comment xml:lang="lv">GNU pasta vēstule</comment>
- <comment xml:lang="ms">Mesej emel GNU</comment>
- <comment xml:lang="nb">GNU e-postmelding</comment>
- <comment xml:lang="nl">GNU-mailbericht</comment>
- <comment xml:lang="nn">GNU e-postmelding</comment>
- <comment xml:lang="oc">messatge de corrièr electronic GNU</comment>
- <comment xml:lang="pl">Wiadomość pocztowa GNU</comment>
- <comment xml:lang="pt">mensagem de email GNU</comment>
- <comment xml:lang="pt_BR">Mensagem de e-mail GNU</comment>
- <comment xml:lang="ro">Mesaj GNU mail</comment>
- <comment xml:lang="ru">Почтовое сообщение GNU</comment>
- <comment xml:lang="sk">Správa GNU mail</comment>
- <comment xml:lang="sl">Sporočilo pošte GNU</comment>
- <comment xml:lang="sq">Mesazh GNU mail</comment>
- <comment xml:lang="sr">порука Гнуове поште</comment>
- <comment xml:lang="sv">GNU-epostmeddelande</comment>
- <comment xml:lang="tr">GNU posta iletisi</comment>
- <comment xml:lang="uk">поштове повідомлення GNU</comment>
- <comment xml:lang="vi">Thư điện tử của GNU</comment>
- <comment xml:lang="zh_CN">GNU mail 信件</comment>
<comment xml:lang="zh_TW">GNU 郵件訊息</comment>
+ <comment xml:lang="zh_CN">GNU mail 信件</comment>
+ <comment xml:lang="vi">Thư điện tử của GNU</comment>
+ <comment xml:lang="uk">поштове повідомлення GNU</comment>
+ <comment xml:lang="tr">GNU posta iletisi</comment>
+ <comment xml:lang="sv">GNU-epostmeddelande</comment>
+ <comment xml:lang="sr">порука Гнуове поште</comment>
+ <comment xml:lang="sq">mesazh GNU mail</comment>
+ <comment xml:lang="sl">Sporočilo pošte GNU</comment>
+ <comment xml:lang="si">GNU තැපැල් පණිවිඩය</comment>
+ <comment xml:lang="sk">Správa GNU mail</comment>
+ <comment xml:lang="ru">Почтовое сообщение GNU</comment>
+ <comment xml:lang="ro">Mesaj GNU mail</comment>
+ <comment xml:lang="pt_BR">Mensagem de e-mail GNU</comment>
+ <comment xml:lang="pt">mensagem de email GNU</comment>
+ <comment xml:lang="pl">Wiadomość pocztowa GNU</comment>
+ <comment xml:lang="oc">messatge de corrièr electronic GNU</comment>
+ <comment xml:lang="nn">GNU e-postmelding</comment>
+ <comment xml:lang="nl">GNU-mailbericht</comment>
+ <comment xml:lang="nb">GNU e-postmelding</comment>
+ <comment xml:lang="ms">Mesej emel GNU</comment>
+ <comment xml:lang="lv">GNU pasta vēstule</comment>
+ <comment xml:lang="lt">GNU pašto žinutė</comment>
+ <comment xml:lang="ko">GNU 메일 메시지</comment>
+ <comment xml:lang="kk">GNU пошта хабарламасы</comment>
+ <comment xml:lang="ka">GNU mail შეტყობინება</comment>
+ <comment xml:lang="ja">GNU メールメッセージ</comment>
+ <comment xml:lang="it">Messaggio GNU mail</comment>
+ <comment xml:lang="is">GNU póst skilaboð</comment>
+ <comment xml:lang="id">Pesan surat GNU</comment>
+ <comment xml:lang="ia">Message electronic de GNU</comment>
+ <comment xml:lang="hu">GNU elektronikus levél</comment>
+ <comment xml:lang="hr">GNU poruka pošte</comment>
+ <comment xml:lang="he">הודעת דואר של GNU</comment>
+ <comment xml:lang="gl">mensaxe de correo electrónico de GNU</comment>
+ <comment xml:lang="ga">teachtaireacht r-phoist GNU</comment>
+ <comment xml:lang="fur">messaç di pueste GNU</comment>
+ <comment xml:lang="fr">message de courriel GNU</comment>
+ <comment xml:lang="fo">GNU mail boð</comment>
+ <comment xml:lang="fi">GNU-postiviesti</comment>
+ <comment xml:lang="eu">GNU posta mezua</comment>
+ <comment xml:lang="es">mensaje de correo de GNU</comment>
+ <comment xml:lang="eo">mesaĝo de GNU mail</comment>
+ <comment xml:lang="en_GB">GNU mail message</comment>
+ <comment xml:lang="el">Μήνυμα αλληλογραφίας GNU</comment>
+ <comment xml:lang="de">GNU-Mail-Nachricht</comment>
+ <comment xml:lang="da">GNU-postmeddelelse</comment>
+ <comment xml:lang="cy">Neges E-Bost GNU</comment>
+ <comment xml:lang="cs">zpráva GNU mail</comment>
+ <comment xml:lang="ca">missatge de GNU mail</comment>
+ <comment xml:lang="bg">Съобщение — GNU mail</comment>
+ <comment xml:lang="be@latin">List GNU</comment>
+ <comment xml:lang="be">электронны ліст GNU</comment>
+ <comment xml:lang="az">GNU poçt ismarışı</comment>
+ <comment xml:lang="ar">رسالة بريد جنو</comment>
+ <comment xml:lang="af">GNU-posboodskap</comment>
<generic-icon name="text-x-generic"/>
<glob pattern="RMAIL"/>
</mime-type>
<mime-type type="model/iges">
<comment>IGES document</comment>
- <comment xml:lang="ast">Documentu IGES</comment>
- <comment xml:lang="ca">document IGES</comment>
- <comment xml:lang="cs">dokument IGES</comment>
- <comment xml:lang="da">IGES-dokument</comment>
- <comment xml:lang="de">IGES-Dokument</comment>
- <comment xml:lang="en_GB">IGES document</comment>
- <comment xml:lang="es">documento IGES</comment>
- <comment xml:lang="eu">IGES dokumentua</comment>
- <comment xml:lang="fi">IGES-asiakirja</comment>
- <comment xml:lang="fr">document IGES</comment>
- <comment xml:lang="ga">cáipéis IGES</comment>
- <comment xml:lang="he">מסמך IGES</comment>
- <comment xml:lang="hr">IGES dokument</comment>
- <comment xml:lang="hu">IGES dokumentum</comment>
- <comment xml:lang="id">dokumen IGES</comment>
- <comment xml:lang="it">Documento IGES</comment>
- <comment xml:lang="kk">IGES құжаты</comment>
- <comment xml:lang="ko">IGES 문서</comment>
- <comment xml:lang="pl">Dokument IGES</comment>
- <comment xml:lang="pt_BR">Documento IGES</comment>
- <comment xml:lang="ru">Документ IGES</comment>
- <comment xml:lang="sk">Dokument IGES</comment>
- <comment xml:lang="sr">ИГЕС документ</comment>
- <comment xml:lang="sv">IGES-dokument</comment>
- <comment xml:lang="tr">IGES belgesi</comment>
- <comment xml:lang="uk">документ IGES</comment>
- <comment xml:lang="zh_CN">IGES 文档</comment>
<comment xml:lang="zh_TW">IGES 文件</comment>
+ <comment xml:lang="zh_CN">IGES 文档</comment>
+ <comment xml:lang="uk">документ IGES</comment>
+ <comment xml:lang="tr">IGES belgesi</comment>
+ <comment xml:lang="sv">IGES-dokument</comment>
+ <comment xml:lang="sr">ИГЕС документ</comment>
+ <comment xml:lang="sq">dokument IGES</comment>
+ <comment xml:lang="sl">Dokument IGES</comment>
+ <comment xml:lang="si">IGES ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument IGES</comment>
+ <comment xml:lang="ru">Документ IGES</comment>
+ <comment xml:lang="pt_BR">Documento IGES</comment>
+ <comment xml:lang="pl">Dokument IGES</comment>
+ <comment xml:lang="oc">document IGES</comment>
+ <comment xml:lang="nl">IGES-document</comment>
+ <comment xml:lang="ko">IGES 문서</comment>
+ <comment xml:lang="kk">IGES құжаты</comment>
+ <comment xml:lang="ja">IGES ドキュメント</comment>
+ <comment xml:lang="it">Documento IGES</comment>
+ <comment xml:lang="is">IGES skjalskjal</comment>
+ <comment xml:lang="id">Dokumen IGES</comment>
+ <comment xml:lang="hu">IGES dokumentum</comment>
+ <comment xml:lang="hr">IGES dokument</comment>
+ <comment xml:lang="he">מסמך IGES</comment>
+ <comment xml:lang="gl">Documento IGES</comment>
+ <comment xml:lang="ga">cáipéis IGES</comment>
+ <comment xml:lang="fur">document IGES</comment>
+ <comment xml:lang="fr">document IGES</comment>
+ <comment xml:lang="fi">IGES-asiakirja</comment>
+ <comment xml:lang="eu">IGES dokumentua</comment>
+ <comment xml:lang="es">documento IGES</comment>
+ <comment xml:lang="en_GB">IGES document</comment>
+ <comment xml:lang="de">IGES-Dokument</comment>
+ <comment xml:lang="da">IGES-dokument</comment>
+ <comment xml:lang="cs">dokument IGES</comment>
+ <comment xml:lang="ca">document IGES</comment>
+ <comment xml:lang="bg">Документ — IGES</comment>
+ <comment xml:lang="be">дакумент IGES</comment>
+ <comment xml:lang="ast">Documentu IGES</comment>
+ <comment xml:lang="ar">مستند IGES</comment>
+ <comment xml:lang="af">IGES-dokument</comment>
<acronym>IGES</acronym>
<expanded-acronym>Initial Graphics Exchange Specification</expanded-acronym>
<generic-icon name="x-office-document"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="S 1\x0a" type="string" offset="72"/>
- <match value="S0000001\x0a" type="string" offset="72"/>
+ <magic>
+ <match type="string" value="S 1\x0a" offset="72"/>
+ <match type="string" value="S0000001\x0a" offset="72"/>
</magic>
<glob pattern="*.igs"/>
<glob pattern="*.iges"/>
</mime-type>
+ <mime-type type="model/gltf-binary">
+ <comment>glTF model</comment>
+ <comment xml:lang="zh_CN">glTF 模型</comment>
+ <comment xml:lang="uk">модель glTF</comment>
+ <comment xml:lang="tr">glTF modeli</comment>
+ <comment xml:lang="sv">glTF-modell</comment>
+ <comment xml:lang="sl">Model gITF</comment>
+ <comment xml:lang="si">glTF ආකෘතිය</comment>
+ <comment xml:lang="ru">glTF-модель</comment>
+ <comment xml:lang="pt_BR">Modelo gITF</comment>
+ <comment xml:lang="pl">Model glTF</comment>
+ <comment xml:lang="oc">modèl glTF</comment>
+ <comment xml:lang="nl">glTF-model</comment>
+ <comment xml:lang="ko">glTF 모델</comment>
+ <comment xml:lang="kk">glTF моделі</comment>
+ <comment xml:lang="ja">glTF モデル</comment>
+ <comment xml:lang="it">Modello glTF</comment>
+ <comment xml:lang="hr">glTF model</comment>
+ <comment xml:lang="he">דגם gITF</comment>
+ <comment xml:lang="gl">Modelo glTF</comment>
+ <comment xml:lang="fi">glTF malli</comment>
+ <comment xml:lang="eu">glTF eredua</comment>
+ <comment xml:lang="es">modelo gITF</comment>
+ <comment xml:lang="en_GB">glTF model</comment>
+ <comment xml:lang="de">glTF-Modell</comment>
+ <comment xml:lang="be">мадэль glTF</comment>
+ <comment xml:lang="ar">نموذج glTF</comment>
+ <acronym>glTF</acronym>
+ <expanded-acronym>GL Transmission Format</expanded-acronym>
+ <generic-icon name="image-x-generic"/>
+ <magic>
+ <match type="string" value="glTF" offset="0"/>
+ </magic>
+ <glob pattern="*.glb"/>
+ </mime-type>
+ <mime-type type="model/gltf+json">
+ <comment>glTF model</comment>
+ <comment xml:lang="zh_CN">glTF 模型</comment>
+ <comment xml:lang="uk">модель glTF</comment>
+ <comment xml:lang="tr">glTF modeli</comment>
+ <comment xml:lang="sv">glTF-modell</comment>
+ <comment xml:lang="sl">Model gITF</comment>
+ <comment xml:lang="si">glTF ආකෘතිය</comment>
+ <comment xml:lang="ru">glTF-модель</comment>
+ <comment xml:lang="pt_BR">Modelo gITF</comment>
+ <comment xml:lang="pl">Model glTF</comment>
+ <comment xml:lang="oc">modèl glTF</comment>
+ <comment xml:lang="nl">glTF-model</comment>
+ <comment xml:lang="ko">glTF 모델</comment>
+ <comment xml:lang="kk">glTF моделі</comment>
+ <comment xml:lang="ja">glTF モデル</comment>
+ <comment xml:lang="it">Modello glTF</comment>
+ <comment xml:lang="hr">glTF model</comment>
+ <comment xml:lang="he">דגם gITF</comment>
+ <comment xml:lang="gl">Modelo glTF</comment>
+ <comment xml:lang="fi">glTF malli</comment>
+ <comment xml:lang="eu">glTF eredua</comment>
+ <comment xml:lang="es">modelo gITF</comment>
+ <comment xml:lang="en_GB">glTF model</comment>
+ <comment xml:lang="de">glTF-Modell</comment>
+ <comment xml:lang="be">мадэль glTF</comment>
+ <comment xml:lang="ar">نموذج glTF</comment>
+ <acronym>glTF</acronym>
+ <expanded-acronym>GL Transmission Format</expanded-acronym>
+ <generic-icon name="image-x-generic"/>
+ <sub-class-of type="application/json"/>
+ <glob pattern="*.gltf"/>
+ </mime-type>
<mime-type type="model/vrml">
<comment>VRML document</comment>
- <comment xml:lang="ar">مستند VRML</comment>
- <comment xml:lang="ast">Documentu VRML</comment>
- <comment xml:lang="az">VRML sənədi</comment>
- <comment xml:lang="be@latin">Dakument VRML</comment>
- <comment xml:lang="bg">Документ — VRML</comment>
- <comment xml:lang="ca">document VRML</comment>
- <comment xml:lang="cs">dokument VRML</comment>
- <comment xml:lang="cy">Dogfen VRML</comment>
- <comment xml:lang="da">VRML-dokument</comment>
- <comment xml:lang="de">VRML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο VRML</comment>
- <comment xml:lang="en_GB">VRML document</comment>
- <comment xml:lang="eo">VRML-dokumento</comment>
- <comment xml:lang="es">documento VRML</comment>
- <comment xml:lang="eu">VRML dokumentua</comment>
- <comment xml:lang="fi">VRML-asiakirja</comment>
- <comment xml:lang="fo">VRML skjal</comment>
- <comment xml:lang="fr">document VRML</comment>
- <comment xml:lang="ga">cáipéis VRML</comment>
- <comment xml:lang="gl">documento VRML</comment>
- <comment xml:lang="he">מסמך VRML</comment>
- <comment xml:lang="hr">VRML dokument</comment>
- <comment xml:lang="hu">VRML-dokumentum</comment>
- <comment xml:lang="ia">Documento VRML</comment>
- <comment xml:lang="id">Dokumen VRML</comment>
- <comment xml:lang="it">Documento VRML</comment>
- <comment xml:lang="ja">VRML ドキュメント</comment>
- <comment xml:lang="kk">VRML құжаты</comment>
- <comment xml:lang="ko">VRML 문서</comment>
- <comment xml:lang="lt">VRML dokumentas</comment>
- <comment xml:lang="lv">VRML dokuments</comment>
- <comment xml:lang="ms">Dokumen VRML</comment>
- <comment xml:lang="nb">VRML-dokument</comment>
- <comment xml:lang="nl">VRML-document</comment>
- <comment xml:lang="nn">VRML-dokument</comment>
- <comment xml:lang="oc">document VRML</comment>
- <comment xml:lang="pl">Dokument VRML</comment>
- <comment xml:lang="pt">documento VRML</comment>
- <comment xml:lang="pt_BR">Documento VRML</comment>
- <comment xml:lang="ro">Document VRML</comment>
- <comment xml:lang="ru">Документ VRML</comment>
- <comment xml:lang="sk">Dokument VRML</comment>
- <comment xml:lang="sl">Dokument VRML</comment>
- <comment xml:lang="sq">Dokument VRML</comment>
- <comment xml:lang="sr">ВРМЛ документ</comment>
- <comment xml:lang="sv">VRML-dokument</comment>
- <comment xml:lang="tr">VRML belgesi</comment>
- <comment xml:lang="uk">документ VRML</comment>
- <comment xml:lang="vi">Tài liệu VRML</comment>
- <comment xml:lang="zh_CN">VRML 文档</comment>
<comment xml:lang="zh_TW">VRML 文件</comment>
+ <comment xml:lang="zh_CN">VRML 文档</comment>
+ <comment xml:lang="vi">Tài liệu VRML</comment>
+ <comment xml:lang="uk">документ VRML</comment>
+ <comment xml:lang="tr">VRML belgesi</comment>
+ <comment xml:lang="sv">VRML-dokument</comment>
+ <comment xml:lang="sr">ВРМЛ документ</comment>
+ <comment xml:lang="sq">dokument VRML</comment>
+ <comment xml:lang="sl">Dokument VRML</comment>
+ <comment xml:lang="si">VRML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument VRML</comment>
+ <comment xml:lang="ru">Документ VRML</comment>
+ <comment xml:lang="ro">Document VRML</comment>
+ <comment xml:lang="pt_BR">Documento VRML</comment>
+ <comment xml:lang="pt">documento VRML</comment>
+ <comment xml:lang="pl">Dokument VRML</comment>
+ <comment xml:lang="oc">document VRML</comment>
+ <comment xml:lang="nn">VRML-dokument</comment>
+ <comment xml:lang="nl">VRML-document</comment>
+ <comment xml:lang="nb">VRML-dokument</comment>
+ <comment xml:lang="ms">Dokumen VRML</comment>
+ <comment xml:lang="lv">VRML dokuments</comment>
+ <comment xml:lang="lt">VRML dokumentas</comment>
+ <comment xml:lang="ko">VRML 문서</comment>
+ <comment xml:lang="kk">VRML құжаты</comment>
+ <comment xml:lang="ja">VRML ドキュメント</comment>
+ <comment xml:lang="it">Documento VRML</comment>
+ <comment xml:lang="is">VRML skjal</comment>
+ <comment xml:lang="id">Dokumen VRML</comment>
+ <comment xml:lang="ia">Documento VRML</comment>
+ <comment xml:lang="hu">VRML-dokumentum</comment>
+ <comment xml:lang="hr">VRML dokument</comment>
+ <comment xml:lang="he">מסמך VRML</comment>
+ <comment xml:lang="gl">documento VRML</comment>
+ <comment xml:lang="ga">cáipéis VRML</comment>
+ <comment xml:lang="fur">document VRML</comment>
+ <comment xml:lang="fr">document VRML</comment>
+ <comment xml:lang="fo">VRML skjal</comment>
+ <comment xml:lang="fi">VRML-asiakirja</comment>
+ <comment xml:lang="eu">VRML dokumentua</comment>
+ <comment xml:lang="es">documento VRML</comment>
+ <comment xml:lang="eo">VRML-dokumento</comment>
+ <comment xml:lang="en_GB">VRML document</comment>
+ <comment xml:lang="el">Έγγραφο VRML</comment>
+ <comment xml:lang="de">VRML-Dokument</comment>
+ <comment xml:lang="da">VRML-dokument</comment>
+ <comment xml:lang="cy">Dogfen VRML</comment>
+ <comment xml:lang="cs">dokument VRML</comment>
+ <comment xml:lang="ca">document VRML</comment>
+ <comment xml:lang="bg">Документ — VRML</comment>
+ <comment xml:lang="be@latin">Dakument VRML</comment>
+ <comment xml:lang="be">дакумент VRML</comment>
+ <comment xml:lang="az">VRML sənədi</comment>
+ <comment xml:lang="ast">Documentu VRML</comment>
+ <comment xml:lang="ar">مستند VRML</comment>
+ <comment xml:lang="af">VRML-dokument</comment>
<acronym>VRML</acronym>
<expanded-acronym>Virtual Reality Modeling Language</expanded-acronym>
<generic-icon name="x-office-document"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="#VRML " type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#VRML " offset="0"/>
</magic>
<glob pattern="*.vrm"/>
<glob pattern="*.vrml"/>
<glob pattern="*.wrl"/>
</mime-type>
+ <mime-type type="model/obj">
+ <comment>OBJ 3D model</comment>
+ <comment xml:lang="zh_CN">OBJ 3D 模型</comment>
+ <comment xml:lang="uk">просторова модель OBJ</comment>
+ <comment xml:lang="tr">OBJ 3B modeli</comment>
+ <comment xml:lang="sv">OBJ-3D-modell</comment>
+ <comment xml:lang="sl">3D-model OBJ</comment>
+ <comment xml:lang="si">OBJ 3D ආකෘතිය</comment>
+ <comment xml:lang="ru">OBJ 3D-модель</comment>
+ <comment xml:lang="pt_BR">Modelo OBJ 3D</comment>
+ <comment xml:lang="pl">Model 3D OBJ</comment>
+ <comment xml:lang="oc">modèl OBJ 3D</comment>
+ <comment xml:lang="nl">OBJ 3D-model</comment>
+ <comment xml:lang="ko">OBJ 3D 모델</comment>
+ <comment xml:lang="kk">OBJ 3D моделі</comment>
+ <comment xml:lang="ja">OBJ 3D モデル</comment>
+ <comment xml:lang="it">Modello OBJ 3D</comment>
+ <comment xml:lang="hr">OBJ 3D model</comment>
+ <comment xml:lang="gl">Modelo OBJ 3D</comment>
+ <comment xml:lang="fi">OBJ 3D-malli</comment>
+ <comment xml:lang="eu">OBJ 3D eredua</comment>
+ <comment xml:lang="es">modelo OBJ 3D</comment>
+ <comment xml:lang="en_GB">OBJ 3D model</comment>
+ <comment xml:lang="de">OBJ-3D-Modell</comment>
+ <comment xml:lang="be">мадэль OBJ 3D</comment>
+ <comment xml:lang="ar">نموذج OBJ 3D</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="image-x-generic"/>
+ <magic>
+ <match type="string" value=" OBJ File: '" offset="0:64"/>
+ <match type="string" value="mtllib " offset="0:256"/>
+ </magic>
+ <glob pattern="*.obj"/>
+ </mime-type>
+ <mime-type type="model/mtl">
+ <comment>OBJ 3D model material library</comment>
+ <comment xml:lang="uk">бібліотека матеріалів просторової моделі OBJ</comment>
+ <comment xml:lang="tr">OBJ 3B modeli malzeme kitaplığı</comment>
+ <comment xml:lang="sv">Materialbibliotek för OBJ 3D-modell</comment>
+ <comment xml:lang="sl">Knjižnica materialov 3D-modelov OBJ</comment>
+ <comment xml:lang="si">OBJ 3D ආදර්ශ ද්රව්ය පුස්තකාලය</comment>
+ <comment xml:lang="ru">Библиотека материалов OBJ 3D-модели</comment>
+ <comment xml:lang="pl">Biblioteka materiałów modeli 3D OBJ</comment>
+ <comment xml:lang="nl">OBJ-3D-model-materiaal­bibliotheek</comment>
+ <comment xml:lang="ko">OBJ 3D 모델 실체 라이브러리</comment>
+ <comment xml:lang="kk">OBJ 3D-моделінің материалдар кітапханасы</comment>
+ <comment xml:lang="ja">OBJ 3D モデルマテリアルライブラリー</comment>
+ <comment xml:lang="it">Modello libreria materiale OBJ 3D</comment>
+ <comment xml:lang="hr">OBJ 3D model biblioteka materijala</comment>
+ <comment xml:lang="fi">OBJ 3D-mallin materiaalikirjasto</comment>
+ <comment xml:lang="es">biblioteca de modelo material OBJ 3D</comment>
+ <comment xml:lang="en_GB">OBJ 3D model material library</comment>
+ <comment xml:lang="de">OBJ-3D-Modell-Materialbibliothek</comment>
+ <comment xml:lang="be">бібліятэка матэрыялаў мадэлі OBJ 3D</comment>
+ <comment xml:lang="ar">مكتبة المواد النموذجية OBJ 3D</comment>
+ <generic-icon name="image-x-generic"/>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="# Blender MTL File: '" offset="0"/>
+ <match type="string" value="newmtl " offset="0:256"/>
+ </magic>
+ <glob pattern="*.mtl"/>
+ </mime-type>
<mime-type type="multipart/alternative">
- <comment>message in several formats</comment>
- <comment xml:lang="ar">رسالة في عدة صيغ</comment>
- <comment xml:lang="az">verici formatlarında ismarış</comment>
- <comment xml:lang="be@latin">paviedamleńnie ŭ niekalkich farmatach</comment>
- <comment xml:lang="bg">Съобщение в няколко формата</comment>
- <comment xml:lang="ca">missatge en diversos formats</comment>
- <comment xml:lang="cs">zpráva v několika formátech</comment>
- <comment xml:lang="cy">neges mewn sawl fformat</comment>
- <comment xml:lang="da">meddelelse i flere formater</comment>
- <comment xml:lang="de">Nachricht in mehreren Formaten</comment>
- <comment xml:lang="el">Μήνυμα σε διάφορες μορφές</comment>
- <comment xml:lang="en_GB">message in several formats</comment>
- <comment xml:lang="eo">mesaĝo en pluraj formatoj</comment>
- <comment xml:lang="es">mensaje en varios formatos</comment>
- <comment xml:lang="eu">hainbat formatuko mezua</comment>
- <comment xml:lang="fi">viesti useissa muodoissa</comment>
- <comment xml:lang="fo">boð í fleiri sniðum</comment>
- <comment xml:lang="fr">message en formats divers</comment>
- <comment xml:lang="ga">teachtaireacht i bhformáidí éagsúla</comment>
- <comment xml:lang="gl">mensaxe en varios formatos</comment>
- <comment xml:lang="he">הודעה במספר תבניות</comment>
- <comment xml:lang="hr">Poruka u nekoliko oblika</comment>
- <comment xml:lang="hu">többféle formátumú üzenet</comment>
- <comment xml:lang="ia">Message in plure formatos</comment>
- <comment xml:lang="id">pesan dalam beberapa format</comment>
- <comment xml:lang="it">Messaggio in diversi formati</comment>
- <comment xml:lang="ja">いくつかの形式でのメッセージ</comment>
- <comment xml:lang="kk">бірнеше пішімдегі мәлімдеме</comment>
- <comment xml:lang="ko">여러가지 형식의 메시지</comment>
- <comment xml:lang="lt">laiškas keletu formatų</comment>
- <comment xml:lang="lv">ziņojums dažādos formātos</comment>
- <comment xml:lang="ms">Mesej dalam beberapa format</comment>
- <comment xml:lang="nb">melding i flere formater</comment>
- <comment xml:lang="nl">bericht in meerdere opmaken</comment>
- <comment xml:lang="nn">melding i fleire format</comment>
- <comment xml:lang="oc">messatge en formats divèrses</comment>
- <comment xml:lang="pl">Wiadomość w wielu formatach</comment>
- <comment xml:lang="pt">mensagem em vários formatos</comment>
- <comment xml:lang="pt_BR">Mensagem em vários formatos</comment>
- <comment xml:lang="ro">mesaj în diferite formate</comment>
- <comment xml:lang="ru">Сообщение в нескольких форматах</comment>
- <comment xml:lang="sk">Správa v niekoľkých formátoch</comment>
- <comment xml:lang="sl">sporočilo v več zapisih</comment>
- <comment xml:lang="sq">Mesazh në formate të ndryshëm</comment>
- <comment xml:lang="sr">порука у неколико записа</comment>
- <comment xml:lang="sv">meddelande i flera format</comment>
- <comment xml:lang="tr">farklı biçimlerde ileti</comment>
+ <comment>Message in several formats</comment>
<comment xml:lang="uk">повідомлення у кількох форматах</comment>
- <comment xml:lang="vi">thông điệp có vài định dạng</comment>
- <comment xml:lang="zh_CN">各种格式的信件</comment>
- <comment xml:lang="zh_TW">多種格式的訊息</comment>
+ <comment xml:lang="sv">Meddelande i flera format</comment>
+ <comment xml:lang="ru">Сообщение в нескольких форматах</comment>
+ <comment xml:lang="pl">Wiadomość w wielu formatach</comment>
+ <comment xml:lang="it">Messaggio in diversi formati</comment>
+ <comment xml:lang="es">mensaje en varios formatos</comment>
+ <comment xml:lang="de">Nachricht in verschiedenen Formaten</comment>
+ <comment xml:lang="be">паведамленне ў некалькіх фарматах</comment>
</mime-type>
<mime-type type="multipart/appledouble">
<comment>Macintosh AppleDouble-encoded file</comment>
- <comment xml:lang="ar">ملف Macintosh AppleDouble مشفر</comment>
- <comment xml:lang="az">Macintosh AppleDouble-kodlanmış fayl</comment>
- <comment xml:lang="be@latin">Fajł Macintosh, AppleDouble-zakadavany</comment>
- <comment xml:lang="bg">Файл — кодиран с Macintosh AppleDouble</comment>
- <comment xml:lang="ca">fitxer codificat AppleDouble de Macintosh</comment>
- <comment xml:lang="cs">soubor kódovaný pomocí Macintosh AppleDouble</comment>
- <comment xml:lang="cy">Ffeil AppleDouble-amgodedig Macintosh</comment>
- <comment xml:lang="da">Macintosh AppleDouble-kodet fil</comment>
- <comment xml:lang="de">Macintosh-Datei (AppleDouble-kodiert)</comment>
- <comment xml:lang="el">Αρχείο Macintosh κωδικοποίησης AppleDouble</comment>
- <comment xml:lang="en_GB">Macintosh AppleDouble-encoded file</comment>
- <comment xml:lang="eo">dosiero kodigita laŭ Macintosh AppleDouble</comment>
- <comment xml:lang="es">archivo Macintosh codificado con AppleDouble</comment>
- <comment xml:lang="eu">Macintosh AppleDouble-rekin kodetutako fitxategia</comment>
- <comment xml:lang="fi">Macintosh AppleDouble -koodattu tiedosto</comment>
- <comment xml:lang="fo">Macintosh AppleDouble-bronglað fíla</comment>
- <comment xml:lang="fr">fichier codé Macintosh AppleDouble</comment>
- <comment xml:lang="ga">comhad ionchódaithe le Macintosh AppleDouble</comment>
- <comment xml:lang="gl">ficheiro de Macintosh codificado con AppleDouble</comment>
- <comment xml:lang="he">קובץ מסוג Macintosh AppleDouble-encoded</comment>
- <comment xml:lang="hr">Macintosh AppleDouble-kodirana datoteka</comment>
- <comment xml:lang="hu">Macintosh AppleDouble kódolású fájl</comment>
- <comment xml:lang="ia">File codificate in AppleDouble de Macintosh</comment>
- <comment xml:lang="id">Berkas tersandi Macintosh AppleDouble</comment>
- <comment xml:lang="it">File Macintosh codificato AppleDouble</comment>
- <comment xml:lang="ja">Macintosh AppleDouble エンコードファイル</comment>
- <comment xml:lang="kk">Macintosh AppleDouble кодталған файлы</comment>
- <comment xml:lang="ko">매킨토시 AppleDouble 인코딩된 파일</comment>
- <comment xml:lang="lt">Macintosh AppleDouble-encoded failas</comment>
- <comment xml:lang="lv">Macintosh AppleDouble-kodēts datne</comment>
- <comment xml:lang="ms">Fail terenkod-AppleDouble Macintosh</comment>
- <comment xml:lang="nb">dokument kodet med Macintosh AppleDouble</comment>
- <comment xml:lang="nl">Macintosh AppleDouble-gecodeerd bestand</comment>
- <comment xml:lang="nn">Macintosh AppleDouble-koda fil</comment>
- <comment xml:lang="oc">fichièr encodat Macintosh AppleDouble</comment>
- <comment xml:lang="pl">Zakodowany w AppleDouble plik Macintosh</comment>
- <comment xml:lang="pt">ficheiro codificado em AppleDouble de Macintosh</comment>
- <comment xml:lang="pt_BR">Arquivo do Macintosh codificado com AppleDouble</comment>
- <comment xml:lang="ro">Fișier codat Macintosh AppleDouble</comment>
- <comment xml:lang="ru">Файл, закодированный Macintosh AppleDouble</comment>
- <comment xml:lang="sk">Súbor kódovaný pomocou Macintosh AppleDouble</comment>
- <comment xml:lang="sl">Kodirana datoteka Macintosh (AppleDouble)</comment>
- <comment xml:lang="sq">File Macintosh i kodifikuar AppleDouble</comment>
- <comment xml:lang="sr">Мекинтошова датотека кодирана Епл Дуплим</comment>
- <comment xml:lang="sv">Macintosh AppleDouble-kodad fil</comment>
- <comment xml:lang="tr">Macintosh AppleDouble-şifreli dosyası</comment>
- <comment xml:lang="uk">файл закодований Macintosh AppleDouble</comment>
- <comment xml:lang="vi">Tập tin đã mã hoá Apple-Double của Macintosh</comment>
- <comment xml:lang="zh_CN">Macintosh AppleDouble 编码的文件</comment>
<comment xml:lang="zh_TW">Macintosh AppleDouble 編碼檔</comment>
+ <comment xml:lang="zh_CN">Macintosh AppleDouble 编码的文件</comment>
+ <comment xml:lang="vi">Tập tin đã mã hoá Apple-Double của Macintosh</comment>
+ <comment xml:lang="uk">файл закодований Macintosh AppleDouble</comment>
+ <comment xml:lang="tr">Macintosh AppleDouble-şifreli dosyası</comment>
+ <comment xml:lang="sv">Macintosh AppleDouble-kodad fil</comment>
+ <comment xml:lang="sr">Мекинтошова датотека кодирана Епл Дуплим</comment>
+ <comment xml:lang="sq">kartelë Macintosh koduar me AppleDouble</comment>
+ <comment xml:lang="sl">Kodirana datoteka Macintosh (AppleDouble)</comment>
+ <comment xml:lang="si">Macintosh AppleDouble-කේතනය කළ ගොනුව</comment>
+ <comment xml:lang="sk">Súbor kódovaný pomocou Macintosh AppleDouble</comment>
+ <comment xml:lang="ru">Файл, закодированный Macintosh AppleDouble</comment>
+ <comment xml:lang="ro">Fișier codat Macintosh AppleDouble</comment>
+ <comment xml:lang="pt_BR">Arquivo do Macintosh codificado com AppleDouble</comment>
+ <comment xml:lang="pt">ficheiro codificado em AppleDouble de Macintosh</comment>
+ <comment xml:lang="pl">Zakodowany w AppleDouble plik Macintosh</comment>
+ <comment xml:lang="oc">fichièr encodat Macintosh AppleDouble</comment>
+ <comment xml:lang="nn">Macintosh AppleDouble-koda fil</comment>
+ <comment xml:lang="nl">Macintosh AppleDouble-gecodeerd bestand</comment>
+ <comment xml:lang="nb">dokument kodet med Macintosh AppleDouble</comment>
+ <comment xml:lang="ms">Fail terenkod-AppleDouble Macintosh</comment>
+ <comment xml:lang="lv">Macintosh AppleDouble-kodēts datne</comment>
+ <comment xml:lang="lt">Macintosh AppleDouble-encoded failas</comment>
+ <comment xml:lang="ko">매킨토시 AppleDouble 인코딩된 파일</comment>
+ <comment xml:lang="kk">Macintosh AppleDouble кодталған файлы</comment>
+ <comment xml:lang="ja">Macintosh AppleDouble エンコードファイル</comment>
+ <comment xml:lang="it">File Macintosh codificato AppleDouble</comment>
+ <comment xml:lang="is">Macintosh AppleDouble-kóðuð skrá</comment>
+ <comment xml:lang="id">Berkas tersandi Macintosh AppleDouble</comment>
+ <comment xml:lang="ia">File codificate in AppleDouble de Macintosh</comment>
+ <comment xml:lang="hu">Macintosh AppleDouble kódolású fájl</comment>
+ <comment xml:lang="hr">Macintosh AppleDouble-kôdirana datoteka</comment>
+ <comment xml:lang="he">קובץ מסוג Macintosh AppleDouble-encoded</comment>
+ <comment xml:lang="gl">ficheiro de Macintosh codificado con AppleDouble</comment>
+ <comment xml:lang="ga">comhad ionchódaithe le Macintosh AppleDouble</comment>
+ <comment xml:lang="fur">file codificât in Macintosh AppleDouble</comment>
+ <comment xml:lang="fr">fichier codé Macintosh AppleDouble</comment>
+ <comment xml:lang="fo">Macintosh AppleDouble-bronglað fíla</comment>
+ <comment xml:lang="fi">Macintosh AppleDouble -koodattu tiedosto</comment>
+ <comment xml:lang="eu">Macintosh AppleDouble-rekin kodetutako fitxategia</comment>
+ <comment xml:lang="es">archivo Macintosh codificado con AppleDouble</comment>
+ <comment xml:lang="eo">dosiero kodigita laŭ Macintosh AppleDouble</comment>
+ <comment xml:lang="en_GB">Macintosh AppleDouble-encoded file</comment>
+ <comment xml:lang="el">Αρχείο Macintosh κωδικοποίησης AppleDouble</comment>
+ <comment xml:lang="de">Macintosh-Datei (AppleDouble-Format)</comment>
+ <comment xml:lang="da">Macintosh AppleDouble-kodet fil</comment>
+ <comment xml:lang="cy">Ffeil AppleDouble-amgodedig Macintosh</comment>
+ <comment xml:lang="cs">soubor kódovaný pomocí Macintosh AppleDouble</comment>
+ <comment xml:lang="ca">fitxer codificat AppleDouble de Macintosh</comment>
+ <comment xml:lang="bg">Файл — кодиран с Macintosh AppleDouble</comment>
+ <comment xml:lang="be@latin">Fajł Macintosh, AppleDouble-zakadavany</comment>
+ <comment xml:lang="be">файл з кадаваннем Macintosh AppleDouble</comment>
+ <comment xml:lang="az">Macintosh AppleDouble-kodlanmış fayl</comment>
+ <comment xml:lang="ar">ملف Macintosh AppleDouble مشفر</comment>
+ <comment xml:lang="af">Macintosh AppleDouble-geënkodeerde lêer</comment>
</mime-type>
<mime-type type="multipart/digest">
- <comment>message digest</comment>
- <comment xml:lang="ar">خلاصة الرسالة</comment>
- <comment xml:lang="az">ismarış daycesti</comment>
- <comment xml:lang="be@latin">digest paviedamleńniaŭ</comment>
- <comment xml:lang="bg">Извадка от съобщение</comment>
- <comment xml:lang="ca">recopilació de missatges</comment>
- <comment xml:lang="cs">přehled zpráv</comment>
- <comment xml:lang="cy">crynodeb negeseuon</comment>
- <comment xml:lang="da">meddelelsessammendrag</comment>
- <comment xml:lang="de">Nachrichtensammlung</comment>
- <comment xml:lang="el">Περίληψη μηνύματος</comment>
- <comment xml:lang="en_GB">message digest</comment>
- <comment xml:lang="eo">mesaĝaro</comment>
- <comment xml:lang="es">recopilación de mensajes</comment>
- <comment xml:lang="eu">mezu laburra</comment>
- <comment xml:lang="fi">viestikokoelma</comment>
- <comment xml:lang="fo">boð samandráttur</comment>
- <comment xml:lang="fr">condensé de message</comment>
- <comment xml:lang="ga">achoimre theachtaireachtaí</comment>
- <comment xml:lang="gl">recompilación de mensaxe</comment>
- <comment xml:lang="he">תקציר ההודעה</comment>
- <comment xml:lang="hr">Poruka kratkg sadržaja</comment>
- <comment xml:lang="hu">ömlesztett üzenet</comment>
- <comment xml:lang="ia">Digesto de messages</comment>
- <comment xml:lang="id">digest pesan</comment>
- <comment xml:lang="it">Digest di messaggi</comment>
- <comment xml:lang="ja">メッセージダイジェスト</comment>
- <comment xml:lang="kk">мәлімдеме профилі</comment>
- <comment xml:lang="ko">메시지 묶음</comment>
- <comment xml:lang="lt">laiškų santrauka</comment>
- <comment xml:lang="lv">ziņojumu apkopojums</comment>
- <comment xml:lang="ms">Jilid mesej</comment>
- <comment xml:lang="nb">medldingssamling</comment>
- <comment xml:lang="nl">berichtenbundel</comment>
- <comment xml:lang="nn">meldingsamandrag</comment>
- <comment xml:lang="oc">condensé de messatge</comment>
- <comment xml:lang="pl">Wiadomość przetwarzania</comment>
- <comment xml:lang="pt">grupo de mensagens</comment>
- <comment xml:lang="pt_BR">Resumo de mensagem</comment>
- <comment xml:lang="ro">colecție mesaje email</comment>
+ <comment>Message digest</comment>
+ <comment xml:lang="uk">контрольна сума повідомлення</comment>
+ <comment xml:lang="sv">Meddelandesamling</comment>
<comment xml:lang="ru">Дайджест сообщения</comment>
- <comment xml:lang="sk">Prehľad správ</comment>
- <comment xml:lang="sl">povzetek sporočila</comment>
- <comment xml:lang="sq">Shpërndarje mesazhesh</comment>
- <comment xml:lang="sr">гомила порука</comment>
- <comment xml:lang="sv">meddelandesamling</comment>
- <comment xml:lang="tr">mesaj özeti</comment>
- <comment xml:lang="uk">збірка повідомлень</comment>
- <comment xml:lang="vi">bản tóm tắt thông điệp</comment>
- <comment xml:lang="zh_CN">信件摘要</comment>
- <comment xml:lang="zh_TW">訊息摘要</comment>
+ <comment xml:lang="pl">Wiadomość przetwarzania</comment>
+ <comment xml:lang="it">Digest di messaggi</comment>
+ <comment xml:lang="es">resumen de mensajes</comment>
+ <comment xml:lang="de">Nachrichtensammlung</comment>
+ <comment xml:lang="be">дайджэст паведамлення</comment>
</mime-type>
<mime-type type="multipart/encrypted">
- <comment>encrypted message</comment>
- <comment xml:lang="ar">رسالة مشفرة</comment>
- <comment xml:lang="az">şifrələnmiş ismarış</comment>
- <comment xml:lang="be@latin">zašyfravanaje paviedamleńnie</comment>
- <comment xml:lang="bg">Шифрирано съобщение</comment>
- <comment xml:lang="ca">missatge xifrat</comment>
- <comment xml:lang="cs">zašifrovaná zpráva</comment>
- <comment xml:lang="cy">Neges wedi ei hamgryptio</comment>
- <comment xml:lang="da">krypteret meddelelse</comment>
- <comment xml:lang="de">Verschlüsselte Nachricht</comment>
- <comment xml:lang="el">Κρυπτογραφημένο μήνυμα</comment>
- <comment xml:lang="en_GB">encrypted message</comment>
- <comment xml:lang="eo">ĉifrita mesaĝo</comment>
- <comment xml:lang="es">mensaje cifrado</comment>
- <comment xml:lang="eu">mezu enkriptatua</comment>
- <comment xml:lang="fi">salattu viesti</comment>
- <comment xml:lang="fo">bronglað boð</comment>
- <comment xml:lang="fr">message chiffré</comment>
- <comment xml:lang="ga">teachtaireacht chriptithe</comment>
- <comment xml:lang="gl">mensaxe cifrado</comment>
- <comment xml:lang="he">הודעה מוצפנת</comment>
- <comment xml:lang="hr">Šifrirana poruka</comment>
- <comment xml:lang="hu">titkosított üzenet</comment>
- <comment xml:lang="ia">Message cryptate</comment>
- <comment xml:lang="id">pesan terenkripsi</comment>
- <comment xml:lang="it">Messaggio cifrato</comment>
- <comment xml:lang="ja">暗号化メッセージ</comment>
- <comment xml:lang="kk">шифрленген мәлімдеме</comment>
- <comment xml:lang="ko">암호화된 메시지</comment>
- <comment xml:lang="lt">užšifruotas laiškas</comment>
- <comment xml:lang="lv">šifrēta vēstule</comment>
- <comment xml:lang="ms">Mesej terenkripsi</comment>
- <comment xml:lang="nb">kryptert melding</comment>
- <comment xml:lang="nl">versleuteld bericht</comment>
- <comment xml:lang="nn">kryptert melding</comment>
- <comment xml:lang="oc">messatge chifrat</comment>
- <comment xml:lang="pl">Wiadomość zaszyfrowana</comment>
- <comment xml:lang="pt">mensagem encriptada</comment>
- <comment xml:lang="pt_BR">Mensagem criptografada</comment>
- <comment xml:lang="ro">mesaj criptat</comment>
+ <comment>Encrypted message</comment>
+ <comment xml:lang="uk">зашифроване повідомлення</comment>
+ <comment xml:lang="sv">Krypterat meddelande</comment>
<comment xml:lang="ru">Зашифрованное сообщение</comment>
- <comment xml:lang="sk">Zašifrovaná správa</comment>
- <comment xml:lang="sl">šifrirano sporočilo</comment>
- <comment xml:lang="sq">Mesazh i kriptuar</comment>
- <comment xml:lang="sr">шифрована порука</comment>
- <comment xml:lang="sv">krypterat meddelande</comment>
- <comment xml:lang="tr">şifrelenmiş mesaj</comment>
- <comment xml:lang="uk">шифроване повідомлення</comment>
- <comment xml:lang="vi">thông điệp đã mật mã</comment>
- <comment xml:lang="zh_CN">加密信件</comment>
- <comment xml:lang="zh_TW">加密訊息</comment>
+ <comment xml:lang="pl">Wiadomość zaszyfrowana</comment>
+ <comment xml:lang="it">Messaggio cifrato</comment>
+ <comment xml:lang="es">mensaje cifrado</comment>
+ <comment xml:lang="de">Verschlüsselte Nachricht</comment>
+ <comment xml:lang="be">зашыфраванае паведамленне</comment>
</mime-type>
<mime-type type="multipart/mixed">
- <comment>compound documents</comment>
- <comment xml:lang="ar">مستندات مركبة</comment>
- <comment xml:lang="ast">documentos compuestos</comment>
- <comment xml:lang="be@latin">składanyja dakumenty</comment>
- <comment xml:lang="bg">Съставни документи</comment>
- <comment xml:lang="ca">documents compostos</comment>
- <comment xml:lang="cs">složené dokumenty</comment>
- <comment xml:lang="da">sammensatte dokumenter</comment>
- <comment xml:lang="de">Verbunddokumente</comment>
- <comment xml:lang="el">Σύνθετα έγγραφα</comment>
- <comment xml:lang="en_GB">compound documents</comment>
- <comment xml:lang="eo">parentezaj dokumentoj</comment>
- <comment xml:lang="es">documentos compuestos</comment>
- <comment xml:lang="eu">konposatutako dokumentuak</comment>
- <comment xml:lang="fi">yhdisteasiakirjat</comment>
- <comment xml:lang="fo">samansett skjøl</comment>
- <comment xml:lang="fr">documents composés</comment>
- <comment xml:lang="ga">cáipéisí comhshuite</comment>
- <comment xml:lang="gl">documentos compostos</comment>
- <comment xml:lang="he">מסמכים מורכבים</comment>
- <comment xml:lang="hr">Složeni dokumenti</comment>
- <comment xml:lang="hu">összetett dokumentumok</comment>
- <comment xml:lang="ia">Documentos composite</comment>
- <comment xml:lang="id">dokumen kompon</comment>
- <comment xml:lang="it">Documenti composti</comment>
- <comment xml:lang="ja">複合ドキュメント</comment>
- <comment xml:lang="kk">құрама құжаттары</comment>
- <comment xml:lang="ko">복합 문서</comment>
- <comment xml:lang="lt">sudurtiniai dokumentai</comment>
- <comment xml:lang="lv">salikti dokumenti</comment>
- <comment xml:lang="ms">Dokumen halaman</comment>
- <comment xml:lang="nb">sammensatte dokumenter</comment>
- <comment xml:lang="nl">samengestelde documenten</comment>
- <comment xml:lang="nn">samansette dokument</comment>
- <comment xml:lang="oc">documents compausats</comment>
- <comment xml:lang="pl">Dokumenty złożone</comment>
- <comment xml:lang="pt">documentos compostos</comment>
- <comment xml:lang="pt_BR">Documentos compostos</comment>
- <comment xml:lang="ro">documente compuse</comment>
- <comment xml:lang="ru">Составные документы</comment>
- <comment xml:lang="sk">Zložené dokumenty</comment>
- <comment xml:lang="sl">združeni dokumenti</comment>
- <comment xml:lang="sq">dokumente të përbërë</comment>
- <comment xml:lang="sr">сједињени документи</comment>
- <comment xml:lang="sv">sammansatta dokument</comment>
- <comment xml:lang="tr">birleşik belgeleri</comment>
+ <comment>Compound documents</comment>
<comment xml:lang="uk">складні документи</comment>
- <comment xml:lang="vi">tài liệu ghép</comment>
- <comment xml:lang="zh_CN">组合文档</comment>
- <comment xml:lang="zh_TW">複合文件</comment>
+ <comment xml:lang="sv">Sammansatta dokument</comment>
+ <comment xml:lang="ru">Составные документы</comment>
+ <comment xml:lang="pl">Dokumenty złożone</comment>
+ <comment xml:lang="it">Documenti composti</comment>
+ <comment xml:lang="de">Verbunddokumente</comment>
+ <comment xml:lang="be">складаныя дакументы</comment>
</mime-type>
<mime-type type="multipart/related">
- <comment>compound document</comment>
- <comment xml:lang="ar">مستند مركب</comment>
- <comment xml:lang="ast">documentu compuestu</comment>
- <comment xml:lang="az">birləşik sənəd</comment>
- <comment xml:lang="be@latin">składany dakument</comment>
- <comment xml:lang="bg">Съставен документ</comment>
- <comment xml:lang="ca">document compost</comment>
- <comment xml:lang="cs">složený dokument</comment>
- <comment xml:lang="cy">dogfen gyfansawdd</comment>
- <comment xml:lang="da">sammensat dokument</comment>
- <comment xml:lang="de">Verbunddokument</comment>
- <comment xml:lang="el">Σύνθετο έγγραφο</comment>
- <comment xml:lang="en_GB">compound document</comment>
- <comment xml:lang="eo">parenteza dokumento</comment>
- <comment xml:lang="es">documento compuesto</comment>
- <comment xml:lang="eu">konposatutako dokumentua</comment>
- <comment xml:lang="fi">yhdisteasiakirja</comment>
- <comment xml:lang="fo">samansett skjal</comment>
- <comment xml:lang="fr">document composé</comment>
- <comment xml:lang="ga">cáipéis comhshuite</comment>
- <comment xml:lang="gl">documento composto</comment>
- <comment xml:lang="he">מסמך מורכב</comment>
- <comment xml:lang="hr">Složeni dokument</comment>
- <comment xml:lang="hu">összetett dokumentum</comment>
- <comment xml:lang="ia">Documento composite</comment>
- <comment xml:lang="id">dokumen kompon</comment>
- <comment xml:lang="it">Documento composto</comment>
- <comment xml:lang="ja">複合ドキュメント</comment>
- <comment xml:lang="kk">құрама құжаты</comment>
- <comment xml:lang="ko">복합 문서</comment>
- <comment xml:lang="lt">sudurtinis dokumentas</comment>
- <comment xml:lang="lv">salikts dokuments</comment>
- <comment xml:lang="ms">Dokumen halaman</comment>
- <comment xml:lang="nb">sammensatt dokument</comment>
- <comment xml:lang="nl">samengesteld document</comment>
- <comment xml:lang="nn">samansett dokument</comment>
- <comment xml:lang="oc">document compausat</comment>
- <comment xml:lang="pl">Dokument złożony</comment>
- <comment xml:lang="pt">documento composto</comment>
- <comment xml:lang="pt_BR">Documento composto</comment>
- <comment xml:lang="ro">document compus</comment>
- <comment xml:lang="ru">Составной документ</comment>
- <comment xml:lang="sk">Zložený dokument</comment>
- <comment xml:lang="sl">združeni dokument</comment>
- <comment xml:lang="sq">dokumet i përbërë</comment>
- <comment xml:lang="sr">сједињени документ</comment>
- <comment xml:lang="sv">sammansatt dokument</comment>
- <comment xml:lang="tr">bileşik belge</comment>
+ <comment>Compound document</comment>
<comment xml:lang="uk">складний документ</comment>
- <comment xml:lang="vi">tài liệu ghép</comment>
- <comment xml:lang="zh_CN">组合文档</comment>
- <comment xml:lang="zh_TW">複合文件</comment>
+ <comment xml:lang="sv">Sammansatt dokument</comment>
+ <comment xml:lang="ru">Составной документ</comment>
+ <comment xml:lang="pl">Dokument złożony</comment>
+ <comment xml:lang="it">Documento composto</comment>
+ <comment xml:lang="de">Verbunddokument</comment>
+ <comment xml:lang="be">складаны дакумент</comment>
</mime-type>
<mime-type type="multipart/report">
- <comment>mail system report</comment>
- <comment xml:lang="ar">تقرير نظام البريد</comment>
- <comment xml:lang="az">poçt sistemi raportu</comment>
- <comment xml:lang="be@latin">rapart paštovaj systemy</comment>
- <comment xml:lang="bg">Отчет за пощенската система</comment>
- <comment xml:lang="ca">informe de sistema de correu</comment>
- <comment xml:lang="cs">zpráva poštovního systému</comment>
- <comment xml:lang="cy">adroddiad system bost</comment>
- <comment xml:lang="da">postsystemrapport</comment>
- <comment xml:lang="de">E-Mail-Systembericht</comment>
- <comment xml:lang="el">Αναφορά συστήματος ηλ. ταχυδρομείου</comment>
- <comment xml:lang="en_GB">mail system report</comment>
- <comment xml:lang="eo">raporto de retpoŝta sistemo</comment>
- <comment xml:lang="es">informe del sistema de correo</comment>
- <comment xml:lang="eu">posta sistemako txostena</comment>
- <comment xml:lang="fi">viestijärjestelmän ilmoitus</comment>
- <comment xml:lang="fo">postkervisfrásøgn</comment>
- <comment xml:lang="fr">rapport système de courriels</comment>
- <comment xml:lang="ga">tuairisc chórais r-phoist</comment>
- <comment xml:lang="gl">informe do sistema de correo</comment>
- <comment xml:lang="he">דו״ח של מערכת הדואר</comment>
- <comment xml:lang="hr">Izvještaj sustava pošte</comment>
- <comment xml:lang="hu">levelezőrendszer jelentése</comment>
- <comment xml:lang="ia">Reporto de systema de e-mail</comment>
- <comment xml:lang="id">laporan sistem surat</comment>
- <comment xml:lang="it">Rapporto di sistema posta</comment>
- <comment xml:lang="ja">メールシステムレポート</comment>
- <comment xml:lang="kk">пошта жүйесінің мәлімдемесі</comment>
- <comment xml:lang="ko">메일 시스템 보고서</comment>
- <comment xml:lang="lt">pašto sistemos ataskaita</comment>
- <comment xml:lang="lv">pasta sistēmas atskaite</comment>
- <comment xml:lang="ms">Laporan sistem mel</comment>
- <comment xml:lang="nb">e-postsystemrapport</comment>
- <comment xml:lang="nl">e-mail-systeembericht</comment>
- <comment xml:lang="nn">e-post-systemrapport</comment>
- <comment xml:lang="oc">rapòrt sistèma de corrièrs electronics</comment>
- <comment xml:lang="pl">Raport systemu pocztowego</comment>
- <comment xml:lang="pt">relatório de sistema de email</comment>
- <comment xml:lang="pt_BR">Relatório do sistema de correspondência</comment>
- <comment xml:lang="ro">raport sistem email</comment>
- <comment xml:lang="ru">Отчёт почтовой системы</comment>
- <comment xml:lang="sk">Správa poštového systému</comment>
- <comment xml:lang="sl">poročilo poštnega sistema</comment>
- <comment xml:lang="sq">Raport i sistemit të postës</comment>
- <comment xml:lang="sr">извештај поштанског система</comment>
- <comment xml:lang="sv">e-postsystemrapport</comment>
- <comment xml:lang="tr">posta sistem raporu</comment>
+ <comment>Mail system report</comment>
<comment xml:lang="uk">звіт поштової системи</comment>
- <comment xml:lang="vi">thông báo hệ thống thư</comment>
- <comment xml:lang="zh_CN">邮件系统报告</comment>
- <comment xml:lang="zh_TW">郵件系統回報</comment>
+ <comment xml:lang="sv">E-postsystemrapport</comment>
+ <comment xml:lang="ru">Отчёт почтовой системы</comment>
+ <comment xml:lang="pl">Raport systemu pocztowego</comment>
+ <comment xml:lang="it">Rapporto di sistema posta</comment>
+ <comment xml:lang="de">E-Mail-Systembericht</comment>
+ <comment xml:lang="be">справаздача паштовай сістэмы</comment>
</mime-type>
<mime-type type="multipart/signed">
- <comment>signed message</comment>
- <comment xml:lang="ar">رسالة موقّعة</comment>
- <comment xml:lang="az">imzalanmış ismarış</comment>
- <comment xml:lang="be@latin">padpisanaje paviedamleńnie</comment>
- <comment xml:lang="bg">Подписано съобщение</comment>
- <comment xml:lang="ca">missatge signat</comment>
- <comment xml:lang="cs">podepsaná zpráva</comment>
- <comment xml:lang="cy">neges lofnodwyd</comment>
- <comment xml:lang="da">signeret meddelelse</comment>
- <comment xml:lang="de">Signierte Nachricht</comment>
- <comment xml:lang="el">Υπογεγραμμένο μήνυμα</comment>
- <comment xml:lang="en_GB">signed message</comment>
- <comment xml:lang="eo">pruvita mesaĝo</comment>
- <comment xml:lang="es">mensaje firmado</comment>
- <comment xml:lang="eu">sinatutako mezua</comment>
- <comment xml:lang="fi">allekirjoitettu viesti</comment>
- <comment xml:lang="fo">undirskrivað boð</comment>
- <comment xml:lang="fr">message signé</comment>
- <comment xml:lang="ga">teachtaireacht sínithe</comment>
- <comment xml:lang="gl">mensaxe firmado</comment>
- <comment xml:lang="he">הודעה חתומה</comment>
- <comment xml:lang="hr">Potpisana poruka</comment>
- <comment xml:lang="hu">aláírt üzenet</comment>
- <comment xml:lang="ia">Message signate</comment>
- <comment xml:lang="id">pesan ditandatangani</comment>
- <comment xml:lang="it">Messaggio firmato</comment>
- <comment xml:lang="ja">署名付きメッセージ</comment>
- <comment xml:lang="kk">қолтаңбасы бар мәлімдеме</comment>
- <comment xml:lang="ko">서명된 메시지</comment>
- <comment xml:lang="lt">pasirašytas laiškas</comment>
- <comment xml:lang="lv">parakstīta ziņa</comment>
- <comment xml:lang="ms">Mesej ditandatangani</comment>
- <comment xml:lang="nb">signert melding</comment>
- <comment xml:lang="nl">ondertekend bericht</comment>
- <comment xml:lang="nn">signert melding</comment>
- <comment xml:lang="oc">messatge signat</comment>
- <comment xml:lang="pl">Podpisana wiadomość</comment>
- <comment xml:lang="pt">mensagem assinada</comment>
- <comment xml:lang="pt_BR">Mensagem assinada</comment>
- <comment xml:lang="ro">mesaj semnat</comment>
- <comment xml:lang="ru">Подписанное сообщение</comment>
- <comment xml:lang="sk">Podpísaná správa</comment>
- <comment xml:lang="sl">podpisano sporočilo</comment>
- <comment xml:lang="sq">Mesazh i firmosur</comment>
- <comment xml:lang="sr">потписана порука</comment>
- <comment xml:lang="sv">signerat meddelande</comment>
- <comment xml:lang="tr">imzalı ileti</comment>
+ <comment>Signed message</comment>
<comment xml:lang="uk">підписане повідомлення</comment>
- <comment xml:lang="vi">thông điệp đã ký</comment>
- <comment xml:lang="zh_CN">签名信件</comment>
- <comment xml:lang="zh_TW">簽署的訊息</comment>
+ <comment xml:lang="sv">Signerat meddelande</comment>
+ <comment xml:lang="ru">Подписанное сообщение</comment>
+ <comment xml:lang="pl">Podpisana wiadomość</comment>
+ <comment xml:lang="it">Messaggio firmato</comment>
+ <comment xml:lang="es">mensaje firmado</comment>
+ <comment xml:lang="de">Signierte Nachricht</comment>
+ <comment xml:lang="be">падпісанае паведамленне</comment>
</mime-type>
<mime-type type="multipart/x-mixed-replace">
- <comment>stream of data (server push)</comment>
- <comment xml:lang="ar">دفق بيانات (دفع خادم)</comment>
- <comment xml:lang="be@latin">płyń źviestak (ad servera)</comment>
- <comment xml:lang="bg">Поток от данни, от страна на сървър</comment>
- <comment xml:lang="ca">flux de dades (enviat pel servidor)</comment>
- <comment xml:lang="cs">proud dat (posílaný serverem)</comment>
- <comment xml:lang="da">datastrøm (serverskubbet)</comment>
- <comment xml:lang="de">Datenstrom (Server-Push)</comment>
- <comment xml:lang="el">Ροή δεδομένων (στελλόμενα από διακομιστή)</comment>
- <comment xml:lang="en_GB">stream of data (server push)</comment>
- <comment xml:lang="eo">datumstrio (puŝata per servilo)</comment>
- <comment xml:lang="es">flujo de datos (por iniciativa del servidor)</comment>
- <comment xml:lang="eu">datu-korrontea (zerbitzari igortzailea)</comment>
- <comment xml:lang="fi">tietovirta (palvelin työntää)</comment>
- <comment xml:lang="fo">streymur av dáta (ambætara skump)</comment>
- <comment xml:lang="fr">flux de données (émis par le serveur)</comment>
- <comment xml:lang="ga">sruth sonraí (brú freastalaí)</comment>
- <comment xml:lang="gl">fluxo de datos (por iniciativa do servidor)</comment>
- <comment xml:lang="he">מידע בזרימה (דחיפה ע״י השרת)</comment>
- <comment xml:lang="hr">Strujanje podataka (poslužiteljem pogurano)</comment>
- <comment xml:lang="hu">sugárzott adatfolyam (kiszolgálóról)</comment>
- <comment xml:lang="ia">Fluxo de datos (pulsate per servitor)</comment>
- <comment xml:lang="id">arus data (dorongan server)</comment>
- <comment xml:lang="it">Flusso di dati (server push)</comment>
- <comment xml:lang="ja">データストリーム (サーバープッシュ型)</comment>
- <comment xml:lang="kk">мәліметтер ағымы (server push)</comment>
- <comment xml:lang="ko">데이터 스트림(서버 푸시)</comment>
- <comment xml:lang="lt">duomenų srautas (iš serverio)</comment>
- <comment xml:lang="lv">datu straume (servera grūsta)</comment>
- <comment xml:lang="ms">Aliran dara (paksaan pelayan)</comment>
- <comment xml:lang="nb">datastrøm (server push)</comment>
- <comment xml:lang="nl">gegevensstroom (server duwt)</comment>
- <comment xml:lang="nn">datastraum (dytta av tenaren)</comment>
- <comment xml:lang="oc">flux de donadas (emés pel servidor)</comment>
- <comment xml:lang="pl">Strumień danych (wymuszenie serwera)</comment>
- <comment xml:lang="pt">fluxo de dados (empurrados pelo servidor)</comment>
- <comment xml:lang="pt_BR">Fluxo de dados (por iniciativa do servidor)</comment>
- <comment xml:lang="ro">flux de date (de la server)</comment>
- <comment xml:lang="ru">Поток данных (server push)</comment>
- <comment xml:lang="sk">Prúd dát (posielaný serverom)</comment>
- <comment xml:lang="sl">pretok podatkov (strežniški)</comment>
- <comment xml:lang="sq">Fluks me të dhëna (server push)</comment>
- <comment xml:lang="sr">ток података (гурање са сервера)</comment>
- <comment xml:lang="sv">dataflöde (serverutsändning)</comment>
- <comment xml:lang="tr">veri akışı (sunucudan gönderilen)</comment>
+ <comment>Stream of data (server push)</comment>
<comment xml:lang="uk">потік даних (від сервера)</comment>
- <comment xml:lang="vi">luồng dữ liệu (trình phục vụ đẩy)</comment>
- <comment xml:lang="zh_CN">数据流(服务器推送)</comment>
- <comment xml:lang="zh_TW">資料串流 (server push)</comment>
+ <comment xml:lang="sv">Dataflöde (serverutsändning)</comment>
+ <comment xml:lang="ru">Поток данных (server push)</comment>
+ <comment xml:lang="pl">Strumień danych (wymuszenie serwera)</comment>
+ <comment xml:lang="it">Flusso di dati (server push)</comment>
+ <comment xml:lang="de">Datenstrom (Server-Push)</comment>
+ <comment xml:lang="be">плынь даных (ад сервера)</comment>
</mime-type>
<mime-type type="text/calendar">
<comment>VCS/ICS calendar</comment>
- <comment xml:lang="ar">سجل VCS/ICS</comment>
- <comment xml:lang="be@latin">Kalandar VCS/ICS</comment>
- <comment xml:lang="bg">Календар — VCS/ICS</comment>
- <comment xml:lang="ca">calendari VCS/ICS</comment>
- <comment xml:lang="cs">kalendář VCS/ICS</comment>
- <comment xml:lang="da">VCS/ICS-kalender</comment>
- <comment xml:lang="de">VCS/ICS-Kalender</comment>
- <comment xml:lang="el">Ημερολόγιο VCS/ICS</comment>
- <comment xml:lang="en_GB">VCS/ICS calendar</comment>
- <comment xml:lang="eo">VCS/ICS-kalendaro</comment>
- <comment xml:lang="es">calendario VCS/ICS</comment>
- <comment xml:lang="eu">VCS/ICS egutegia</comment>
- <comment xml:lang="fi">VCS/ICS-kalenteri</comment>
- <comment xml:lang="fo">VCS/ICS kalendari</comment>
- <comment xml:lang="fr">calendrier VCS/ICS</comment>
- <comment xml:lang="ga">féilire VCS/ICS</comment>
- <comment xml:lang="gl">Calendario VCS/ICS</comment>
- <comment xml:lang="he">לוח שנה VCS/ICS</comment>
- <comment xml:lang="hr">VCS/ICS kalendar</comment>
- <comment xml:lang="hu">VCS/ICS naptár</comment>
- <comment xml:lang="ia">Calendario VCS/ICS</comment>
- <comment xml:lang="id">Kalender VCS/ICS</comment>
- <comment xml:lang="it">Calendario VCS/ICS</comment>
- <comment xml:lang="ja">VCS/ICS カレンダー</comment>
- <comment xml:lang="kk">VCS/ICS күнтізбесі</comment>
- <comment xml:lang="ko">VCS/ICS 달력</comment>
- <comment xml:lang="lt">VCS/ICS kalendorius</comment>
- <comment xml:lang="lv">VCS/ICS kalendārs</comment>
- <comment xml:lang="nb">VCS/ICS-kalender</comment>
- <comment xml:lang="nl">VCS/ICS-kalender</comment>
- <comment xml:lang="nn">VCS/ICS-kalender</comment>
- <comment xml:lang="oc">calendièr VCS/ICS</comment>
- <comment xml:lang="pl">Kalendarz VCS/ICS</comment>
- <comment xml:lang="pt">calendário VCS/ICS</comment>
- <comment xml:lang="pt_BR">Calendário VCS/ICS</comment>
- <comment xml:lang="ro">Calendar VCS/ICS</comment>
- <comment xml:lang="ru">Календарь VCS/ICS</comment>
- <comment xml:lang="sk">Kalendár VCS/ICS</comment>
- <comment xml:lang="sl">Datoteka koledarja VCS/ICS</comment>
- <comment xml:lang="sq">Kalendar VCS/ICS</comment>
- <comment xml:lang="sr">ВЦС/ИЦС календар</comment>
- <comment xml:lang="sv">VCS/ICS-kalender</comment>
- <comment xml:lang="tr">VCS/ICS takvimi</comment>
- <comment xml:lang="uk">календар VCS/ICS</comment>
- <comment xml:lang="vi">Lịch VCS/ICS</comment>
- <comment xml:lang="zh_CN">VCS/ICS 日历</comment>
<comment xml:lang="zh_TW">VCS/ICS 行事曆</comment>
+ <comment xml:lang="zh_CN">VCS/ICS 日历</comment>
+ <comment xml:lang="vi">Lịch VCS/ICS</comment>
+ <comment xml:lang="uk">календар VCS/ICS</comment>
+ <comment xml:lang="tr">VCS/ICS takvimi</comment>
+ <comment xml:lang="sv">VCS/ICS-kalender</comment>
+ <comment xml:lang="sr">ВЦС/ИЦС календар</comment>
+ <comment xml:lang="sq">kalendar VCS/ICS</comment>
+ <comment xml:lang="sl">Datoteka koledarja VCS/ICS</comment>
+ <comment xml:lang="si">VCS/ICS දින දර්ශනය</comment>
+ <comment xml:lang="sk">Kalendár VCS/ICS</comment>
+ <comment xml:lang="ru">Календарь VCS/ICS</comment>
+ <comment xml:lang="ro">Calendar VCS/ICS</comment>
+ <comment xml:lang="pt_BR">Calendário VCS/ICS</comment>
+ <comment xml:lang="pt">calendário VCS/ICS</comment>
+ <comment xml:lang="pl">Kalendarz VCS/ICS</comment>
+ <comment xml:lang="oc">calendièr VCS/ICS</comment>
+ <comment xml:lang="nn">VCS/ICS-kalender</comment>
+ <comment xml:lang="nl">VCS/ICS-kalender</comment>
+ <comment xml:lang="nb">VCS/ICS-kalender</comment>
+ <comment xml:lang="lv">VCS/ICS kalendārs</comment>
+ <comment xml:lang="lt">VCS/ICS kalendorius</comment>
+ <comment xml:lang="ko">VCS/ICS 달력</comment>
+ <comment xml:lang="kk">VCS/ICS күнтізбесі</comment>
+ <comment xml:lang="ja">VCS/ICS カレンダー</comment>
+ <comment xml:lang="it">Calendario VCS/ICS</comment>
+ <comment xml:lang="is">VCS/ICS-dagatal</comment>
+ <comment xml:lang="id">Kalender VCS/ICS</comment>
+ <comment xml:lang="ia">Calendario VCS/ICS</comment>
+ <comment xml:lang="hu">VCS/ICS naptár</comment>
+ <comment xml:lang="hr">VCS/ICS kalendar</comment>
+ <comment xml:lang="he">לוח שנה VCS/ICS</comment>
+ <comment xml:lang="gl">Calendario VCS/ICS</comment>
+ <comment xml:lang="ga">féilire VCS/ICS</comment>
+ <comment xml:lang="fur">calendari VCS/ICS</comment>
+ <comment xml:lang="fr">calendrier VCS/ICS</comment>
+ <comment xml:lang="fo">VCS/ICS kalendari</comment>
+ <comment xml:lang="fi">VCS/ICS-kalenteri</comment>
+ <comment xml:lang="eu">VCS/ICS egutegia</comment>
+ <comment xml:lang="es">calendario VCS/ICS</comment>
+ <comment xml:lang="eo">VCS/ICS-kalendaro</comment>
+ <comment xml:lang="en_GB">VCS/ICS calendar</comment>
+ <comment xml:lang="el">Ημερολόγιο VCS/ICS</comment>
+ <comment xml:lang="de">VCS/ICS-Kalender</comment>
+ <comment xml:lang="da">VCS/ICS-kalender</comment>
+ <comment xml:lang="cs">kalendář VCS/ICS</comment>
+ <comment xml:lang="ca">calendari VCS/ICS</comment>
+ <comment xml:lang="bg">Календар — VCS/ICS</comment>
+ <comment xml:lang="be@latin">Kalandar VCS/ICS</comment>
+ <comment xml:lang="be">каляндар VCS/ICS</comment>
+ <comment xml:lang="ar">سجل VCS/ICS</comment>
+ <comment xml:lang="af">VCS/ICS-kalender</comment>
<acronym>VCS/ICS</acronym>
<expanded-acronym>vCalendar/iCalendar</expanded-acronym>
<sub-class-of type="text/plain"/>
<alias type="text/x-vcalendar"/>
<alias type="application/ics"/>
- <magic priority="50">
- <match value="BEGIN:VCALENDAR" type="string" offset="0"/>
- <match value="begin:vcalendar" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="BEGIN:VCALENDAR" offset="0"/>
+ <match type="string" value="begin:vcalendar" offset="0"/>
</magic>
<glob pattern="*.vcs"/>
<glob pattern="*.ics"/>
</mime-type>
<mime-type type="text/css">
<comment>CSS stylesheet</comment>
- <comment xml:lang="ar">نمط CSS</comment>
- <comment xml:lang="be@latin">Arkuš stylaŭ CSS</comment>
- <comment xml:lang="bg">Стилове — CSS</comment>
- <comment xml:lang="ca">llista d'estil CSS</comment>
- <comment xml:lang="cs">stylopis CSS</comment>
- <comment xml:lang="da">CSS-stilark</comment>
- <comment xml:lang="de">CSS-Stilvorlage</comment>
- <comment xml:lang="el">Φύλλο στυλ CSS</comment>
- <comment xml:lang="en_GB">CSS stylesheet</comment>
- <comment xml:lang="eo">CSS-stilfolio</comment>
- <comment xml:lang="es">hoja de estilos CSS</comment>
- <comment xml:lang="eu">CSS estilo-orria</comment>
- <comment xml:lang="fi">CSS-tyylitiedosto</comment>
- <comment xml:lang="fo">CSS sniðark</comment>
- <comment xml:lang="fr">feuille de style CSS</comment>
- <comment xml:lang="ga">stílbhileog CSS</comment>
- <comment xml:lang="gl">folla de estilos CSS</comment>
- <comment xml:lang="he">גליון עיצוב CSS</comment>
- <comment xml:lang="hr">CSS stilska tablica</comment>
- <comment xml:lang="hu">CSS stíluslap</comment>
- <comment xml:lang="ia">Folio de stilo CSS</comment>
- <comment xml:lang="id">Lembar gaya CSS</comment>
- <comment xml:lang="it">Foglio di stile CSS</comment>
- <comment xml:lang="ja">CSS スタイルシート</comment>
- <comment xml:lang="ka">CSS სტილი</comment>
- <comment xml:lang="kk">CSS стильдер кестесі</comment>
- <comment xml:lang="ko">CSS 스타일시트</comment>
- <comment xml:lang="lt">CSS stiliaus aprašas</comment>
- <comment xml:lang="lv">CSS stilu saraksts</comment>
- <comment xml:lang="nb">CSS-stilark</comment>
- <comment xml:lang="nl">CSS-stijlblad</comment>
- <comment xml:lang="nn">CSS-stilark</comment>
- <comment xml:lang="oc">fuèlh d'estil CSS</comment>
- <comment xml:lang="pl">Arkusz stylów CSS</comment>
- <comment xml:lang="pt">folha de estilos CSS</comment>
- <comment xml:lang="pt_BR">Folha de estilo CSS</comment>
- <comment xml:lang="ro">Pagină de stil CSS</comment>
- <comment xml:lang="ru">Таблица стилей CSS</comment>
- <comment xml:lang="sk">Štýly CSS</comment>
- <comment xml:lang="sl">Slogovna predloga CSS</comment>
- <comment xml:lang="sq">Fletë stili CSS</comment>
- <comment xml:lang="sr">ЦСС стилски лист</comment>
- <comment xml:lang="sv">CSS-stilmall</comment>
- <comment xml:lang="tr">CSS stil kağıdı</comment>
- <comment xml:lang="uk">таблиця стилів CSS</comment>
- <comment xml:lang="vi">Tờ kiểu dáng CSS</comment>
- <comment xml:lang="zh_CN">CSS 样式表</comment>
<comment xml:lang="zh_TW">CSS 樣式表</comment>
+ <comment xml:lang="zh_CN">CSS 样式表</comment>
+ <comment xml:lang="vi">Tờ kiểu dáng CSS</comment>
+ <comment xml:lang="uk">таблиця стилів CSS</comment>
+ <comment xml:lang="tr">CSS stil kağıdı</comment>
+ <comment xml:lang="sv">CSS-stilmall</comment>
+ <comment xml:lang="sr">ЦСС стилски лист</comment>
+ <comment xml:lang="sq">fletëstil CSS</comment>
+ <comment xml:lang="sl">Slogovna predloga CSS</comment>
+ <comment xml:lang="si">CSS මෝස්තර පත්‍රිකාව</comment>
+ <comment xml:lang="sk">Štýly CSS</comment>
+ <comment xml:lang="ru">Таблица стилей CSS</comment>
+ <comment xml:lang="ro">Pagină de stil CSS</comment>
+ <comment xml:lang="pt_BR">Folha de estilo CSS</comment>
+ <comment xml:lang="pt">folha de estilos CSS</comment>
+ <comment xml:lang="pl">Arkusz stylów CSS</comment>
+ <comment xml:lang="oc">fuèlh d'estil CSS</comment>
+ <comment xml:lang="nn">CSS-stilark</comment>
+ <comment xml:lang="nl">CSS-stijlblad</comment>
+ <comment xml:lang="nb">CSS-stilark</comment>
+ <comment xml:lang="lv">CSS stilu saraksts</comment>
+ <comment xml:lang="lt">CSS stiliaus aprašas</comment>
+ <comment xml:lang="ko">CSS 스타일시트</comment>
+ <comment xml:lang="kk">CSS стильдер кестесі</comment>
+ <comment xml:lang="ka">CSS სტილი</comment>
+ <comment xml:lang="ja">CSS スタイルシート</comment>
+ <comment xml:lang="it">Foglio di stile CSS</comment>
+ <comment xml:lang="is">CSS-stílsnið</comment>
+ <comment xml:lang="id">Lembar gaya CSS</comment>
+ <comment xml:lang="ia">Folio de stilo CSS</comment>
+ <comment xml:lang="hu">CSS stíluslap</comment>
+ <comment xml:lang="hr">CSS stilska tablica</comment>
+ <comment xml:lang="he">גיליון עיצוב CSS</comment>
+ <comment xml:lang="gl">folla de estilos CSS</comment>
+ <comment xml:lang="ga">stílbhileog CSS</comment>
+ <comment xml:lang="fur">sfuei di stîl CSS</comment>
+ <comment xml:lang="fr">feuille de style CSS</comment>
+ <comment xml:lang="fo">CSS sniðark</comment>
+ <comment xml:lang="fi">CSS-tyylitiedosto</comment>
+ <comment xml:lang="eu">CSS estilo-orria</comment>
+ <comment xml:lang="es">hoja de estilos CSS</comment>
+ <comment xml:lang="eo">CSS-stilfolio</comment>
+ <comment xml:lang="en_GB">CSS stylesheet</comment>
+ <comment xml:lang="el">Φύλλο στυλ CSS</comment>
+ <comment xml:lang="de">CSS-Stilvorlage</comment>
+ <comment xml:lang="da">CSS-stilark</comment>
+ <comment xml:lang="cs">stylopis CSS</comment>
+ <comment xml:lang="ca">llista d'estil CSS</comment>
+ <comment xml:lang="bg">Стилове — CSS</comment>
+ <comment xml:lang="be@latin">Arkuš stylaŭ CSS</comment>
+ <comment xml:lang="be">табліца стыляў CSS</comment>
+ <comment xml:lang="ar">نمط CSS</comment>
+ <comment xml:lang="af">CSS-stylblad</comment>
<acronym>CSS</acronym>
<expanded-acronym>Cascading Style Sheets</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.css"/>
</mime-type>
<mime-type type="text/vcard">
- <comment>electronic business card</comment>
- <comment xml:lang="ar">بطاقة أعمال إلكترونية</comment>
- <comment xml:lang="be@latin">elektronnaja biznes-kartka</comment>
- <comment xml:lang="bg">Електронна визитна картичка</comment>
- <comment xml:lang="ca">targeta de visita electrònica</comment>
- <comment xml:lang="cs">elektronická navštívenka</comment>
- <comment xml:lang="da">elektronisk visitkort</comment>
- <comment xml:lang="de">Elektronische Visitenkarte</comment>
- <comment xml:lang="el">Ηλεκτρονική επαγγελματική κάρτα</comment>
- <comment xml:lang="en_GB">electronic business card</comment>
- <comment xml:lang="eo">elektronika vizitkarto</comment>
- <comment xml:lang="es">tarjeta de visita electrónica</comment>
- <comment xml:lang="eu">enpresako txartel elektronikoa</comment>
- <comment xml:lang="fi">sähköinen käyntikortti</comment>
- <comment xml:lang="fo">elektroniskt handilskort</comment>
- <comment xml:lang="fr">carte de visite électronique</comment>
- <comment xml:lang="ga">cárta gnó leictreonach</comment>
- <comment xml:lang="gl">tarxeta de negocio electrónica</comment>
- <comment xml:lang="he">כרטיס ביקור אלקטרוני</comment>
- <comment xml:lang="hr">Elektronička posjetnica</comment>
- <comment xml:lang="hu">elektronikus névjegykártya</comment>
- <comment xml:lang="ia">Carta de visita electronic</comment>
- <comment xml:lang="id">kartu bisnis elektronik</comment>
- <comment xml:lang="it">Biglietto da visita elettronico</comment>
- <comment xml:lang="ja">電子名刺</comment>
- <comment xml:lang="kk">электронды визит карточкасы</comment>
- <comment xml:lang="ko">전자 명함</comment>
- <comment xml:lang="lt">elektroninė vizitinė kortelė</comment>
- <comment xml:lang="lv">elektroniskā biznesa kartiņa</comment>
- <comment xml:lang="nl">elektronisch visitekaartje</comment>
- <comment xml:lang="nn">elektronisk visittkort</comment>
- <comment xml:lang="oc">carta de visita electronica</comment>
- <comment xml:lang="pl">Wizytówka elektroniczna</comment>
- <comment xml:lang="pt">cartão de visita eletrónico</comment>
- <comment xml:lang="pt_BR">Cartão de visitas eletrônico</comment>
- <comment xml:lang="ro">carte de vizită electronică</comment>
- <comment xml:lang="ru">Электронная визитная карточка</comment>
- <comment xml:lang="sk">Elektronická vizitka</comment>
- <comment xml:lang="sl">elektronska poslovna vizitka</comment>
- <comment xml:lang="sq">Skedë elektronike biznesi</comment>
- <comment xml:lang="sr">електронска пословна картица</comment>
- <comment xml:lang="sv">elektroniskt visitkort</comment>
- <comment xml:lang="tr">elektronik iş kartı</comment>
+ <comment>Electronic business card</comment>
<comment xml:lang="uk">електронна бізнес-картка</comment>
- <comment xml:lang="vi">danh thiếp điện tử</comment>
- <comment xml:lang="zh_CN">电子商务卡</comment>
- <comment xml:lang="zh_TW">電子商務名片</comment>
+ <comment xml:lang="sv">Elektroniskt visitkort</comment>
+ <comment xml:lang="ru">Электронная визитная карточка</comment>
+ <comment xml:lang="pl">Wizytówka elektroniczna</comment>
+ <comment xml:lang="ja">電子名刺</comment>
+ <comment xml:lang="it">Biglietto da visita elettronico</comment>
+ <comment xml:lang="es">tarjeta de visita electrónica</comment>
+ <comment xml:lang="de">Elektronische Visitenkarte</comment>
+ <comment xml:lang="be">электронная візітная картка</comment>
<alias type="text/directory"/>
<alias type="text/x-vcard"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="BEGIN:VCARD" type="string" offset="0"/>
- <match value="begin:vcard" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="BEGIN:VCARD" offset="0"/>
+ <match type="string" value="begin:vcard" offset="0"/>
</magic>
<glob pattern="*.vcard"/>
<glob pattern="*.vcf"/>
@@ -31598,266 +33723,309 @@
</mime-type>
<mime-type type="text/turtle">
<comment>Turtle document</comment>
- <comment xml:lang="ast">Documentu Turtle</comment>
- <comment xml:lang="ca">document Turtle</comment>
- <comment xml:lang="cs">dokument Turtle</comment>
- <comment xml:lang="da">Turtle-dokument</comment>
- <comment xml:lang="de">Turtle-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Turtle</comment>
- <comment xml:lang="en_GB">Turtle document</comment>
- <comment xml:lang="es">documento de Turtle</comment>
- <comment xml:lang="eu">Turtle dokumentua</comment>
- <comment xml:lang="fi">Turtle-asiakirja</comment>
- <comment xml:lang="fr">document Turtle</comment>
- <comment xml:lang="ga">cáipéis Turtle</comment>
- <comment xml:lang="he">מסמך Turtle</comment>
- <comment xml:lang="hr">Turtle dokument</comment>
- <comment xml:lang="hu">Turtle dokumentum</comment>
- <comment xml:lang="ia">Documento Turtle</comment>
- <comment xml:lang="id">Dokumen Turtle</comment>
- <comment xml:lang="it">Documento Turtle</comment>
- <comment xml:lang="kk">Turtle құжаты</comment>
- <comment xml:lang="ko">Turtle 문서</comment>
- <comment xml:lang="oc">document Turtle</comment>
- <comment xml:lang="pl">Dokument Turtle</comment>
- <comment xml:lang="pt">documento Turtle</comment>
- <comment xml:lang="pt_BR">Documento Turtle</comment>
- <comment xml:lang="ru">Документ Turtle</comment>
- <comment xml:lang="sk">Dokument Turtle</comment>
- <comment xml:lang="sr">Тартл документ</comment>
- <comment xml:lang="sv">Turtle-dokument</comment>
- <comment xml:lang="tr">Turtle belgesi</comment>
- <comment xml:lang="uk">документ Turtle</comment>
- <comment xml:lang="zh_CN">Turtle 文档</comment>
<comment xml:lang="zh_TW">Turtle 文件</comment>
+ <comment xml:lang="zh_CN">Turtle 文档</comment>
+ <comment xml:lang="uk">документ Turtle</comment>
+ <comment xml:lang="tr">Turtle belgesi</comment>
+ <comment xml:lang="sv">Turtle-dokument</comment>
+ <comment xml:lang="sr">Тартл документ</comment>
+ <comment xml:lang="sq">dokument Turtle</comment>
+ <comment xml:lang="sl">Dokument Turtle</comment>
+ <comment xml:lang="si">කැස්බෑ ලියවිල්ල</comment>
+ <comment xml:lang="sk">Dokument Turtle</comment>
+ <comment xml:lang="ru">Документ Turtle</comment>
+ <comment xml:lang="pt_BR">Documento Turtle</comment>
+ <comment xml:lang="pt">documento Turtle</comment>
+ <comment xml:lang="pl">Dokument Turtle</comment>
+ <comment xml:lang="oc">document Turtle</comment>
+ <comment xml:lang="nl">Turtle-document</comment>
+ <comment xml:lang="ko">Turtle 문서</comment>
+ <comment xml:lang="kk">Turtle құжаты</comment>
+ <comment xml:lang="ja">Turtle ドキュメント</comment>
+ <comment xml:lang="it">Documento Turtle</comment>
+ <comment xml:lang="is">Turtle skjal</comment>
+ <comment xml:lang="id">Dokumen Turtle</comment>
+ <comment xml:lang="ia">Documento Turtle</comment>
+ <comment xml:lang="hu">Turtle dokumentum</comment>
+ <comment xml:lang="hr">Turtle dokument</comment>
+ <comment xml:lang="he">מסמך Turtle</comment>
+ <comment xml:lang="ga">cáipéis Turtle</comment>
+ <comment xml:lang="fur">document Turtle</comment>
+ <comment xml:lang="fr">document Turtle</comment>
+ <comment xml:lang="fi">Turtle-asiakirja</comment>
+ <comment xml:lang="eu">Turtle dokumentua</comment>
+ <comment xml:lang="es">documento de Turtle</comment>
+ <comment xml:lang="en_GB">Turtle document</comment>
+ <comment xml:lang="el">Έγγραφο Turtle</comment>
+ <comment xml:lang="de">Turtle-Dokument</comment>
+ <comment xml:lang="da">Turtle-dokument</comment>
+ <comment xml:lang="cs">dokument Turtle</comment>
+ <comment xml:lang="ca">document Turtle</comment>
+ <comment xml:lang="bg">Документ — Turtle</comment>
+ <comment xml:lang="be">дакумент Turtle</comment>
+ <comment xml:lang="ast">Documentu Turtle</comment>
+ <comment xml:lang="ar">وثيقة Turtle</comment>
+ <comment xml:lang="af">Turtle-dokument</comment>
<glob pattern="*.ttl"/>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="text/x-txt2tags">
<comment>txt2tags document</comment>
- <comment xml:lang="ar">مستند txt2tags</comment>
- <comment xml:lang="ast">Documentu txt2tags</comment>
- <comment xml:lang="be@latin">dakument txt2tags</comment>
- <comment xml:lang="bg">Документ — txt2tags</comment>
- <comment xml:lang="ca">document txt2tags</comment>
- <comment xml:lang="cs">dokument txt2tags</comment>
- <comment xml:lang="da">txt2tags-dokument</comment>
- <comment xml:lang="de">txt2tags-Dokument</comment>
- <comment xml:lang="el">Έγγραφο txt2tags</comment>
- <comment xml:lang="en_GB">txt2tags document</comment>
- <comment xml:lang="eo">txt2tags-dokumento</comment>
- <comment xml:lang="es">documento txt2tags</comment>
- <comment xml:lang="eu">txt2tags dokumentua</comment>
- <comment xml:lang="fi">txt2tags-asiakirja</comment>
- <comment xml:lang="fo">txt2tags skjal</comment>
- <comment xml:lang="fr">document txt2tags</comment>
- <comment xml:lang="ga">cáipéis txt2tags</comment>
- <comment xml:lang="gl">documento txt2tags</comment>
- <comment xml:lang="he">מסמך txt2tags</comment>
- <comment xml:lang="hr">txt2tags dokument</comment>
- <comment xml:lang="hu">txt2tags dokumentum</comment>
- <comment xml:lang="ia">Documento txt2tags</comment>
- <comment xml:lang="id">Dokumen txt2tags</comment>
- <comment xml:lang="it">Documento txt2tags</comment>
- <comment xml:lang="ja">txt2tags ドキュメント</comment>
- <comment xml:lang="ka">txt2tags დოკუმენტი</comment>
- <comment xml:lang="kk">txt2tags құжаты</comment>
- <comment xml:lang="ko">txt2tags 문서</comment>
- <comment xml:lang="lt">txt2tags dokumentas</comment>
- <comment xml:lang="lv">txt2tags dokuments</comment>
- <comment xml:lang="nb">txt2tags-dokument</comment>
- <comment xml:lang="nl">txt2tags-document</comment>
- <comment xml:lang="nn">txt2tags-dokument</comment>
- <comment xml:lang="oc">document txt2tags</comment>
- <comment xml:lang="pl">Dokument txt2tags</comment>
- <comment xml:lang="pt">documento txt2tags</comment>
- <comment xml:lang="pt_BR">Documento do txt2tags</comment>
- <comment xml:lang="ro">document txt2tags</comment>
- <comment xml:lang="ru">Документ txt2tags</comment>
- <comment xml:lang="sk">Dokument txt2tags</comment>
- <comment xml:lang="sl">Dokument txt2tags</comment>
- <comment xml:lang="sq">Dokument txt2tags</comment>
- <comment xml:lang="sr">документ текста-у-ознаке</comment>
- <comment xml:lang="sv">txt2tags-dokument</comment>
- <comment xml:lang="tr">txt2tags belgesi</comment>
- <comment xml:lang="uk">документ txt2tags</comment>
- <comment xml:lang="vi">tài liệu txt2tags</comment>
- <comment xml:lang="zh_CN">txt2tags 文档</comment>
<comment xml:lang="zh_TW">txt2tags 文件</comment>
+ <comment xml:lang="zh_CN">txt2tags 文档</comment>
+ <comment xml:lang="vi">tài liệu txt2tags</comment>
+ <comment xml:lang="uk">документ txt2tags</comment>
+ <comment xml:lang="tr">txt2tags belgesi</comment>
+ <comment xml:lang="sv">txt2tags-dokument</comment>
+ <comment xml:lang="sr">документ текста-у-ознаке</comment>
+ <comment xml:lang="sq">dokument txt2tags</comment>
+ <comment xml:lang="sl">Dokument txt2tags</comment>
+ <comment xml:lang="si">txt2tags ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument txt2tags</comment>
+ <comment xml:lang="ru">Документ txt2tags</comment>
+ <comment xml:lang="ro">document txt2tags</comment>
+ <comment xml:lang="pt_BR">Documento do txt2tags</comment>
+ <comment xml:lang="pt">documento txt2tags</comment>
+ <comment xml:lang="pl">Dokument txt2tags</comment>
+ <comment xml:lang="oc">document txt2tags</comment>
+ <comment xml:lang="nn">txt2tags-dokument</comment>
+ <comment xml:lang="nl">txt2tags-document</comment>
+ <comment xml:lang="nb">txt2tags-dokument</comment>
+ <comment xml:lang="lv">txt2tags dokuments</comment>
+ <comment xml:lang="lt">txt2tags dokumentas</comment>
+ <comment xml:lang="ko">txt2tags 문서</comment>
+ <comment xml:lang="kk">txt2tags құжаты</comment>
+ <comment xml:lang="ka">txt2tags დოკუმენტი</comment>
+ <comment xml:lang="ja">txt2tags ドキュメント</comment>
+ <comment xml:lang="it">Documento txt2tags</comment>
+ <comment xml:lang="is">txt2tags skjalskjal</comment>
+ <comment xml:lang="id">dokumen txt2tags</comment>
+ <comment xml:lang="ia">Documento txt2tags</comment>
+ <comment xml:lang="hu">txt2tags dokumentum</comment>
+ <comment xml:lang="hr">txt2tags dokument</comment>
+ <comment xml:lang="he">מסמך txt2tags</comment>
+ <comment xml:lang="gl">documento txt2tags</comment>
+ <comment xml:lang="ga">cáipéis txt2tags</comment>
+ <comment xml:lang="fur">document txt2tags</comment>
+ <comment xml:lang="fr">document txt2tags</comment>
+ <comment xml:lang="fo">txt2tags skjal</comment>
+ <comment xml:lang="fi">txt2tags-asiakirja</comment>
+ <comment xml:lang="eu">txt2tags dokumentua</comment>
+ <comment xml:lang="es">documento txt2tags</comment>
+ <comment xml:lang="eo">txt2tags-dokumento</comment>
+ <comment xml:lang="en_GB">txt2tags document</comment>
+ <comment xml:lang="el">Έγγραφο txt2tags</comment>
+ <comment xml:lang="de">txt2tags-Dokument</comment>
+ <comment xml:lang="da">txt2tags-dokument</comment>
+ <comment xml:lang="cs">dokument txt2tags</comment>
+ <comment xml:lang="ca">document txt2tags</comment>
+ <comment xml:lang="bg">Документ — txt2tags</comment>
+ <comment xml:lang="be@latin">dakument txt2tags</comment>
+ <comment xml:lang="be">дакумент txt2tags</comment>
+ <comment xml:lang="ast">Documentu txt2tags</comment>
+ <comment xml:lang="ar">مستند txt2tags</comment>
+ <comment xml:lang="af">txt2tags-dokument</comment>
<sub-class-of type="text/plain"/>
<magic priority="60">
- <match value="%!postproc" type="string" offset="0"/>
- <match value="%!encoding" type="string" offset="0"/>
+ <match type="string" value="%!postproc" offset="0"/>
+ <match type="string" value="%!encoding" offset="0"/>
</magic>
<glob pattern="*.t2t"/>
</mime-type>
<mime-type type="text/x-verilog">
<comment>Verilog source code</comment>
- <comment xml:lang="bg">Изходен код — Verilog</comment>
- <comment xml:lang="ca">codi font en Verilog</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Verilog</comment>
- <comment xml:lang="da">Verilog-kildekode</comment>
- <comment xml:lang="de">Verilog-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Verilog</comment>
- <comment xml:lang="en_GB">Verilog source code</comment>
- <comment xml:lang="eo">Verilog-fontkodo</comment>
- <comment xml:lang="es">código fuente en Verilog</comment>
- <comment xml:lang="eu">Verilog iturburu-kodea</comment>
- <comment xml:lang="fi">Verilog-lähdekoodi</comment>
- <comment xml:lang="fr">code source Verilog</comment>
- <comment xml:lang="ga">cód foinseach Verilog</comment>
- <comment xml:lang="gl">código fonte en Verilog</comment>
- <comment xml:lang="he">קוד מקור של </comment>
- <comment xml:lang="hr">Verilog izvorni kôd</comment>
- <comment xml:lang="hu">Verilog-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Verilog</comment>
- <comment xml:lang="id">Kode sumber Verilog</comment>
- <comment xml:lang="it">Codice sorgente Verilog</comment>
- <comment xml:lang="ja">Verilog ソースコード</comment>
- <comment xml:lang="kk">Verilog бастапқы коды</comment>
- <comment xml:lang="ko">Verilog 소스 코드</comment>
- <comment xml:lang="lv">Verilog pirmkods</comment>
- <comment xml:lang="nl">Verilog broncode</comment>
- <comment xml:lang="oc">còde font Verilog</comment>
- <comment xml:lang="pl">Kod źródłowy Verilog</comment>
- <comment xml:lang="pt">código origem Verilog</comment>
- <comment xml:lang="pt_BR">Código-fonte Verilog</comment>
- <comment xml:lang="ru">Исходный код Verilog</comment>
- <comment xml:lang="sk">Zdrojový kód Verilog</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Verilog</comment>
- <comment xml:lang="sr">изворни код Верилога</comment>
- <comment xml:lang="sv">Verilog-källkod</comment>
- <comment xml:lang="tr">Verilog kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Verilog</comment>
- <comment xml:lang="zh_CN">Verilog 源代码</comment>
<comment xml:lang="zh_TW">Verilog 源碼</comment>
+ <comment xml:lang="zh_CN">Verilog 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Verilog</comment>
+ <comment xml:lang="tr">Verilog kaynak kodu</comment>
+ <comment xml:lang="sv">Verilog-källkod</comment>
+ <comment xml:lang="sr">изворни код Верилога</comment>
+ <comment xml:lang="sq">kod burim Verilog</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Verilog</comment>
+ <comment xml:lang="si">Verilog මූලාශ්ර කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Verilog</comment>
+ <comment xml:lang="ru">Исходный код Verilog</comment>
+ <comment xml:lang="pt_BR">Código-fonte Verilog</comment>
+ <comment xml:lang="pt">código origem Verilog</comment>
+ <comment xml:lang="pl">Kod źródłowy Verilog</comment>
+ <comment xml:lang="oc">còde font Verilog</comment>
+ <comment xml:lang="nl">Verilog-broncode</comment>
+ <comment xml:lang="lv">Verilog pirmkods</comment>
+ <comment xml:lang="ko">Verilog 소스 코드</comment>
+ <comment xml:lang="kk">Verilog бастапқы коды</comment>
+ <comment xml:lang="ja">Verilog ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Verilog</comment>
+ <comment xml:lang="is">Verilog frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Verilog</comment>
+ <comment xml:lang="ia">Codice-fonte Verilog</comment>
+ <comment xml:lang="hu">Verilog-forráskód</comment>
+ <comment xml:lang="hr">Verilog izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של </comment>
+ <comment xml:lang="gl">código fonte en Verilog</comment>
+ <comment xml:lang="ga">cód foinseach Verilog</comment>
+ <comment xml:lang="fur">codiç sorzint Verilog</comment>
+ <comment xml:lang="fr">code source Verilog</comment>
+ <comment xml:lang="fi">Verilog-lähdekoodi</comment>
+ <comment xml:lang="eu">Verilog iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Verilog</comment>
+ <comment xml:lang="eo">Verilog-fontkodo</comment>
+ <comment xml:lang="en_GB">Verilog source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Verilog</comment>
+ <comment xml:lang="de">Verilog-Quelltext</comment>
+ <comment xml:lang="da">Verilog-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Verilog</comment>
+ <comment xml:lang="ca">codi font en Verilog</comment>
+ <comment xml:lang="bg">Изходен код — Verilog</comment>
+ <comment xml:lang="be">зыходны код Verilog</comment>
+ <comment xml:lang="ar">شفرة مصدر Verilog</comment>
+ <comment xml:lang="af">Verilog-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.v"/>
</mime-type>
<mime-type type="text/x-svhdr">
<comment>SystemVerilog header</comment>
- <comment xml:lang="bg">Заглавен файл — SystemVerilog</comment>
- <comment xml:lang="ca">capçalera de SystemVerilog</comment>
- <comment xml:lang="cs">záhlaví SystemVerilog</comment>
- <comment xml:lang="da">SystemVerilog-teksthoved</comment>
- <comment xml:lang="de">SystemVerilog-Header</comment>
- <comment xml:lang="el">Κεφαλίδα SystemVerilog</comment>
- <comment xml:lang="en_GB">SystemVerilog header</comment>
- <comment xml:lang="es">cabeceras de SystemVerilog</comment>
- <comment xml:lang="eu">SystemVerilog goiburua</comment>
- <comment xml:lang="fi">SystemVerilog-otsake</comment>
- <comment xml:lang="fr">en-tête </comment>
- <comment xml:lang="ga">ceanntásc SystemVerilog</comment>
- <comment xml:lang="gl">Cabeceiras de SystemVerilog</comment>
- <comment xml:lang="he">כותרת SystemVerilog</comment>
- <comment xml:lang="hr">SystemVerilog zaglavlje</comment>
- <comment xml:lang="hu">SystemVerilog fejléc</comment>
- <comment xml:lang="ia">Capite SystemVerilog</comment>
- <comment xml:lang="id">Header SystemVerilog</comment>
- <comment xml:lang="it">Header SystemVerilog</comment>
- <comment xml:lang="ja">SystemVerilog ヘッダー</comment>
- <comment xml:lang="kk">SystemVerilog тақырыптамасы</comment>
- <comment xml:lang="ko">SystemVerilog 헤더</comment>
- <comment xml:lang="lv">SystemVerilog galvene</comment>
- <comment xml:lang="nl">SystemVerilog header</comment>
- <comment xml:lang="oc">entèsta SystemVerilog</comment>
- <comment xml:lang="pl">Nagłówek SystemVerilog</comment>
- <comment xml:lang="pt">cabeçalho SystemVerilog</comment>
- <comment xml:lang="pt_BR">Cabeçalho de SystemVerilog</comment>
- <comment xml:lang="ru">Заголовочный файл SystemVerilog</comment>
- <comment xml:lang="sk">Hlavičky SystemVerilog</comment>
- <comment xml:lang="sl">Datoteka glave SystemVerilog</comment>
- <comment xml:lang="sr">заглавље Система Верилога</comment>
- <comment xml:lang="sv">SystemVerilog-headerfil</comment>
- <comment xml:lang="tr">SystemVerilog başlığı</comment>
- <comment xml:lang="uk">заголовки SystemVerilog</comment>
- <comment xml:lang="zh_CN">SystemVerilog 头文件</comment>
<comment xml:lang="zh_TW">SystemVerilog 標頭</comment>
+ <comment xml:lang="zh_CN">SystemVerilog 头文件</comment>
+ <comment xml:lang="uk">заголовки SystemVerilog</comment>
+ <comment xml:lang="tr">SystemVerilog başlığı</comment>
+ <comment xml:lang="sv">SystemVerilog-headerfil</comment>
+ <comment xml:lang="sr">заглавље Система Верилога</comment>
+ <comment xml:lang="sq">krye SystemVerilog</comment>
+ <comment xml:lang="sl">Datoteka glave SystemVerilog</comment>
+ <comment xml:lang="si">SystemVerilog ශීර්ෂකය</comment>
+ <comment xml:lang="sk">Hlavičky SystemVerilog</comment>
+ <comment xml:lang="ru">Заголовочный файл SystemVerilog</comment>
+ <comment xml:lang="pt_BR">Cabeçalho de SystemVerilog</comment>
+ <comment xml:lang="pt">cabeçalho SystemVerilog</comment>
+ <comment xml:lang="pl">Nagłówek SystemVerilog</comment>
+ <comment xml:lang="oc">entèsta SystemVerilog</comment>
+ <comment xml:lang="nl">SystemVerilog-header</comment>
+ <comment xml:lang="lv">SystemVerilog galvene</comment>
+ <comment xml:lang="ko">SystemVerilog 헤더</comment>
+ <comment xml:lang="kk">SystemVerilog тақырыптамасы</comment>
+ <comment xml:lang="ja">SystemVerilog ヘッダー</comment>
+ <comment xml:lang="it">Header SystemVerilog</comment>
+ <comment xml:lang="is">SystemVerilog haus</comment>
+ <comment xml:lang="id">Header SystemVerilog</comment>
+ <comment xml:lang="ia">Capite SystemVerilog</comment>
+ <comment xml:lang="hu">SystemVerilog fejléc</comment>
+ <comment xml:lang="hr">SystemVerilog zaglavlje</comment>
+ <comment xml:lang="he">כותרת SystemVerilog</comment>
+ <comment xml:lang="gl">Cabeceiras de SystemVerilog</comment>
+ <comment xml:lang="ga">ceanntásc SystemVerilog</comment>
+ <comment xml:lang="fur">intestazion SystemVerilog</comment>
+ <comment xml:lang="fr">en-tête </comment>
+ <comment xml:lang="fi">SystemVerilog-otsake</comment>
+ <comment xml:lang="eu">SystemVerilog goiburua</comment>
+ <comment xml:lang="es">cabeceras de SystemVerilog</comment>
+ <comment xml:lang="en_GB">SystemVerilog header</comment>
+ <comment xml:lang="el">Κεφαλίδα SystemVerilog</comment>
+ <comment xml:lang="de">SystemVerilog-Header</comment>
+ <comment xml:lang="da">SystemVerilog-teksthoved</comment>
+ <comment xml:lang="cs">záhlaví SystemVerilog</comment>
+ <comment xml:lang="ca">capçalera en SystemVerilog</comment>
+ <comment xml:lang="bg">Заглавен файл — SystemVerilog</comment>
+ <comment xml:lang="be">загаловак SystemVerilog</comment>
+ <comment xml:lang="ar">ترويسة SystemVerilog</comment>
<sub-class-of type="text/x-verilog"/>
<glob pattern="*.svh"/>
</mime-type>
<mime-type type="text/x-svsrc">
<comment>SystemVerilog source code</comment>
- <comment xml:lang="bg">Изходен код — SystemVerilog</comment>
- <comment xml:lang="ca">codi font en SystemVerilog</comment>
- <comment xml:lang="cs">zdrojový kód SystemVerilog</comment>
- <comment xml:lang="da">SystemVerilog-kildekode</comment>
- <comment xml:lang="de">SystemVerilog-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας SystemVerilog</comment>
- <comment xml:lang="en_GB">SystemVerilog source code</comment>
- <comment xml:lang="es">código fuente en SystemVerilog</comment>
- <comment xml:lang="eu">SystemVerilog iturburu-kodea</comment>
- <comment xml:lang="fi">SystemVerilog-lähdekoodi</comment>
- <comment xml:lang="fr">code source </comment>
- <comment xml:lang="ga">cód foinseach SystemVerilog</comment>
- <comment xml:lang="gl">código fonte en SystemVerilog</comment>
- <comment xml:lang="he">קוד מקור של SystemVerilog</comment>
- <comment xml:lang="hr">SystemVerilog izvorni kôd</comment>
- <comment xml:lang="hu">SystemVerilog-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte SystemVerilog</comment>
- <comment xml:lang="id">Kode sumber SystemVerilog</comment>
- <comment xml:lang="it">Codice sorgente </comment>
- <comment xml:lang="ja">SystemVerilog ソースコード</comment>
- <comment xml:lang="kk">SystemVerilog бастапқы коды</comment>
- <comment xml:lang="ko">SystemVerilog 소스 코드</comment>
- <comment xml:lang="lv">SystemVerilog pirmkods</comment>
- <comment xml:lang="nl">SystemVerilog broncode</comment>
- <comment xml:lang="oc">còde font SystemVerilog</comment>
- <comment xml:lang="pl">Kod źródłowy SystemVerilog</comment>
- <comment xml:lang="pt">código origem SystemVerilog</comment>
- <comment xml:lang="pt_BR">Código-fonte de SystemVerilog</comment>
- <comment xml:lang="ru">Исходный код SystemVerilog</comment>
- <comment xml:lang="sk">Zdrojový kód SystemVerilog</comment>
- <comment xml:lang="sl">Datoteka izvorne kode SystemVerilog</comment>
- <comment xml:lang="sr">изворни код Система Верилога</comment>
- <comment xml:lang="sv">SystemVerilog-källkod</comment>
- <comment xml:lang="tr">SystemVerilog kaynak kodu</comment>
- <comment xml:lang="uk">вихідний файл мовою SystemVerilog</comment>
- <comment xml:lang="zh_CN">SystemVerilog 源代码</comment>
<comment xml:lang="zh_TW">SystemVerilog 源碼</comment>
+ <comment xml:lang="zh_CN">SystemVerilog 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою SystemVerilog</comment>
+ <comment xml:lang="tr">SystemVerilog kaynak kodu</comment>
+ <comment xml:lang="sv">SystemVerilog-källkod</comment>
+ <comment xml:lang="sr">изворни код Система Верилога</comment>
+ <comment xml:lang="sq">kod burim SystemVerilog</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode SystemVerilog</comment>
+ <comment xml:lang="si">SystemVerilog මූලාශ්‍ර කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód SystemVerilog</comment>
+ <comment xml:lang="ru">Исходный код SystemVerilog</comment>
+ <comment xml:lang="pt_BR">Código-fonte de SystemVerilog</comment>
+ <comment xml:lang="pt">código origem SystemVerilog</comment>
+ <comment xml:lang="pl">Kod źródłowy SystemVerilog</comment>
+ <comment xml:lang="oc">còde font SystemVerilog</comment>
+ <comment xml:lang="nl">SystemVerilog-broncode</comment>
+ <comment xml:lang="lv">SystemVerilog pirmkods</comment>
+ <comment xml:lang="ko">SystemVerilog 소스 코드</comment>
+ <comment xml:lang="kk">SystemVerilog бастапқы коды</comment>
+ <comment xml:lang="ja">SystemVerilog ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente </comment>
+ <comment xml:lang="is">SystemVerilog frumkóði</comment>
+ <comment xml:lang="id">Kode sumber SystemVerilog</comment>
+ <comment xml:lang="ia">Codice-fonte SystemVerilog</comment>
+ <comment xml:lang="hu">SystemVerilog-forráskód</comment>
+ <comment xml:lang="hr">SystemVerilog izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של SystemVerilog</comment>
+ <comment xml:lang="gl">código fonte en SystemVerilog</comment>
+ <comment xml:lang="ga">cód foinseach SystemVerilog</comment>
+ <comment xml:lang="fur">codiç sorzint SystemVerilog</comment>
+ <comment xml:lang="fr">code source </comment>
+ <comment xml:lang="fi">SystemVerilog-lähdekoodi</comment>
+ <comment xml:lang="eu">SystemVerilog iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en SystemVerilog</comment>
+ <comment xml:lang="en_GB">SystemVerilog source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας SystemVerilog</comment>
+ <comment xml:lang="de">SystemVerilog-Quelltext</comment>
+ <comment xml:lang="da">SystemVerilog-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód SystemVerilog</comment>
+ <comment xml:lang="ca">codi font en SystemVerilog</comment>
+ <comment xml:lang="bg">Изходен код — SystemVerilog</comment>
+ <comment xml:lang="be">зыходны код SystemVerilog</comment>
+ <comment xml:lang="ar">شفرة مصدر SystemVerilog</comment>
+ <comment xml:lang="af">SystemVerilog-bronkode</comment>
<sub-class-of type="text/x-verilog"/>
<glob pattern="*.sv"/>
</mime-type>
<mime-type type="text/x-vhdl">
<comment>VHDL source code</comment>
- <comment xml:lang="bg">Изходен код — VHDL</comment>
- <comment xml:lang="ca">codi font en VHDL</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce VHDL</comment>
- <comment xml:lang="da">VHDL-kildekode</comment>
- <comment xml:lang="de">VHDL-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας VHDL</comment>
- <comment xml:lang="en_GB">VHDL source code</comment>
- <comment xml:lang="eo">VHDL-fontkodo</comment>
- <comment xml:lang="es">código fuente en VHDL</comment>
- <comment xml:lang="eu">VHDL iturburu-kodea</comment>
- <comment xml:lang="fi">VHDL-lähdekoodi</comment>
- <comment xml:lang="fr">code source VHDL</comment>
- <comment xml:lang="ga">cód foinseach VHDL</comment>
- <comment xml:lang="gl">código fonte en VHDL</comment>
- <comment xml:lang="he">קוד מקור של VHDL</comment>
- <comment xml:lang="hr">VHDL izvorni kôd</comment>
- <comment xml:lang="hu">VHDL-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte VHDL</comment>
- <comment xml:lang="id">Kode sumber VHDL</comment>
- <comment xml:lang="it">Codice sorgente VHDL</comment>
- <comment xml:lang="ja">VHDL ソースコード</comment>
- <comment xml:lang="kk">VHDL бастапқы коды</comment>
- <comment xml:lang="ko">VHDL 소스 코드</comment>
- <comment xml:lang="lv">VHDL pirmkods</comment>
- <comment xml:lang="nl">VHDL broncode</comment>
- <comment xml:lang="oc">còde font VHDL</comment>
- <comment xml:lang="pl">Kod źródłowy VHDL</comment>
- <comment xml:lang="pt">código origem VHDL</comment>
- <comment xml:lang="pt_BR">Código-fonte VHDL</comment>
- <comment xml:lang="ru">Исходный код VHDL</comment>
- <comment xml:lang="sk">Zdrojový kód VHDL</comment>
- <comment xml:lang="sl">Datoteka izvorne kode VHDL</comment>
- <comment xml:lang="sr">ВХДЛ изворни код</comment>
- <comment xml:lang="sv">VHDL-källkod</comment>
- <comment xml:lang="tr">VHDL kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою VHDL</comment>
- <comment xml:lang="zh_CN">VHDL 源代码</comment>
<comment xml:lang="zh_TW">VHDL 源碼</comment>
+ <comment xml:lang="zh_CN">VHDL 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою VHDL</comment>
+ <comment xml:lang="tr">VHDL kaynak kodu</comment>
+ <comment xml:lang="sv">VHDL-källkod</comment>
+ <comment xml:lang="sr">ВХДЛ изворни код</comment>
+ <comment xml:lang="sq">kod burim VHDL</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode VHDL</comment>
+ <comment xml:lang="si">VHDL මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód VHDL</comment>
+ <comment xml:lang="ru">Исходный код VHDL</comment>
+ <comment xml:lang="pt_BR">Código-fonte VHDL</comment>
+ <comment xml:lang="pt">código origem VHDL</comment>
+ <comment xml:lang="pl">Kod źródłowy VHDL</comment>
+ <comment xml:lang="oc">còde font VHDL</comment>
+ <comment xml:lang="nl">VHDL-broncode</comment>
+ <comment xml:lang="lv">VHDL pirmkods</comment>
+ <comment xml:lang="ko">VHDL 소스 코드</comment>
+ <comment xml:lang="kk">VHDL бастапқы коды</comment>
+ <comment xml:lang="ja">VHDL ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente VHDL</comment>
+ <comment xml:lang="is">VHDL frumkóði</comment>
+ <comment xml:lang="id">Kode sumber VHDL</comment>
+ <comment xml:lang="ia">Codice-fonte VHDL</comment>
+ <comment xml:lang="hu">VHDL-forráskód</comment>
+ <comment xml:lang="hr">VHDL izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של VHDL</comment>
+ <comment xml:lang="gl">código fonte en VHDL</comment>
+ <comment xml:lang="ga">cód foinseach VHDL</comment>
+ <comment xml:lang="fur">codiç sorzint VHDL</comment>
+ <comment xml:lang="fr">code source VHDL</comment>
+ <comment xml:lang="fi">VHDL-lähdekoodi</comment>
+ <comment xml:lang="eu">VHDL iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en VHDL</comment>
+ <comment xml:lang="eo">VHDL-fontkodo</comment>
+ <comment xml:lang="en_GB">VHDL source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας VHDL</comment>
+ <comment xml:lang="de">VHDL-Quelltext</comment>
+ <comment xml:lang="da">VHDL-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce VHDL</comment>
+ <comment xml:lang="ca">codi font en VHDL</comment>
+ <comment xml:lang="bg">Изходен код — VHDL</comment>
+ <comment xml:lang="be">зыходны код VHDL</comment>
+ <comment xml:lang="ar">شفرة مصدر VHDL</comment>
+ <comment xml:lang="af">VHDL-bronkode</comment>
<acronym>VHDL</acronym>
<expanded-acronym>Very-High-Speed Integrated Circuit Hardware Description Language</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -31865,167 +34033,49 @@
<glob pattern="*.vhdl"/>
</mime-type>
<mime-type type="text/enriched">
- <comment>enriched text document</comment>
- <comment xml:lang="ar">مستند نصي مغنى</comment>
- <comment xml:lang="ast">documentu de testu arriquecíu</comment>
- <comment xml:lang="az">zəngin mətn sənədi</comment>
- <comment xml:lang="be@latin">azdobleny tekstavy dakument</comment>
- <comment xml:lang="bg">Документ с обогатен текст</comment>
- <comment xml:lang="ca">document de text enriquit</comment>
- <comment xml:lang="cs">rozšířený textový dokument</comment>
- <comment xml:lang="cy">Dogfen testun wedi ei gyfoethogi</comment>
- <comment xml:lang="da">beriget tekstdokument</comment>
- <comment xml:lang="de">Angereichertes Textdokument</comment>
- <comment xml:lang="el">Έγγραφο εμπλουτισμένου κειμένου</comment>
- <comment xml:lang="en_GB">enriched text document</comment>
- <comment xml:lang="eo">riĉigita teksta dokumento</comment>
- <comment xml:lang="es">documento de texto enriquecido</comment>
- <comment xml:lang="eu">aberastutako testu dokumentua</comment>
- <comment xml:lang="fi">rikastettu tekstiasiakirja</comment>
- <comment xml:lang="fo">ríkað tekstskjal</comment>
- <comment xml:lang="fr">document texte enrichi</comment>
- <comment xml:lang="ga">cáipéis téacs saibhrithe</comment>
- <comment xml:lang="gl">documento de texto enriquecido</comment>
- <comment xml:lang="he">מסמך טקסט מועשר</comment>
- <comment xml:lang="hr">Obogaćeni tekstovni dokument</comment>
- <comment xml:lang="hu">enriched text dokumentum</comment>
- <comment xml:lang="ia">Documento de texto inricchite</comment>
- <comment xml:lang="id">dokumen teks diperkaya</comment>
- <comment xml:lang="it">Documento testo arricchito</comment>
- <comment xml:lang="ja">リッチテキストドキュメント</comment>
- <comment xml:lang="kk">пішімделген мәтіндік құжаты</comment>
- <comment xml:lang="ko">확장된 텍스트 문서</comment>
- <comment xml:lang="lt">praturtinto teksto dokumentas</comment>
- <comment xml:lang="lv">bagātināta teksta formāts</comment>
- <comment xml:lang="ms">Dokumen teks diperkaya</comment>
- <comment xml:lang="nb">riktekst-dokument</comment>
- <comment xml:lang="nl">verrijkt tekstdocument</comment>
- <comment xml:lang="nn">rik tekst tekstdokument</comment>
- <comment xml:lang="oc">document tèxte enriquit</comment>
- <comment xml:lang="pl">Wzbogacony dokument tekstowy</comment>
- <comment xml:lang="pt">documento de texto rico</comment>
- <comment xml:lang="pt_BR">Documento de texto enriquecido</comment>
- <comment xml:lang="ro">document text îmbogățit</comment>
- <comment xml:lang="ru">Форматированный текстовый документ</comment>
- <comment xml:lang="sk">Rozšírený textový dokument</comment>
- <comment xml:lang="sl">dokument z obogatenim besedilom</comment>
- <comment xml:lang="sq">Dokument teksti i pasuruar</comment>
- <comment xml:lang="sr">обогаћени текстуални документ</comment>
- <comment xml:lang="sv">berikat textdokument</comment>
- <comment xml:lang="tr">zenginleştirilmiş metin belgesi</comment>
+ <comment>Enriched text document</comment>
<comment xml:lang="uk">форматований текстовий документ</comment>
- <comment xml:lang="vi">tài liệu văn bản có kiểu dáng</comment>
- <comment xml:lang="zh_CN">浓缩文本文档 (ETF)</comment>
- <comment xml:lang="zh_TW">豐富化文字文件</comment>
+ <comment xml:lang="sv">Enriched text-dokument</comment>
+ <comment xml:lang="ru">Форматированный текстовый документ</comment>
+ <comment xml:lang="pl">Wzbogacony dokument tekstowy</comment>
+ <comment xml:lang="ja">装飾された文書</comment>
+ <comment xml:lang="it">Documento testo arricchito</comment>
+ <comment xml:lang="es">documento de texto enriquecido</comment>
+ <comment xml:lang="de">Angereichertes Textdokument</comment>
+ <comment xml:lang="be">дакумент з фарматаваннем enriched text</comment>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="text/htmlh">
- <comment>help page</comment>
- <comment xml:lang="ar">صفحة المساعدة</comment>
- <comment xml:lang="az">yardım səhifəsi</comment>
- <comment xml:lang="be@latin">staronka dapamohi</comment>
- <comment xml:lang="bg">Страница от помощта</comment>
- <comment xml:lang="ca">pàgina d'ajuda</comment>
- <comment xml:lang="cs">stránka nápovědy</comment>
- <comment xml:lang="cy">tudalen gymorth</comment>
- <comment xml:lang="da">hjælpeside</comment>
- <comment xml:lang="de">Hilfeseite</comment>
- <comment xml:lang="el">Σελίδα βοήθειας</comment>
- <comment xml:lang="en_GB">help page</comment>
- <comment xml:lang="eo">help-paĝo</comment>
- <comment xml:lang="es">página de ayuda</comment>
- <comment xml:lang="eu">laguntzako orria</comment>
- <comment xml:lang="fi">ohjesivu</comment>
- <comment xml:lang="fo">hjálparsíða</comment>
- <comment xml:lang="fr">page d'aide</comment>
- <comment xml:lang="ga">leathanach cabhrach</comment>
- <comment xml:lang="gl">páxina de axuda</comment>
- <comment xml:lang="he">דף עזרה</comment>
- <comment xml:lang="hr">Stranica pomoći</comment>
- <comment xml:lang="hu">súgóoldal</comment>
- <comment xml:lang="ia">Pagina de adjuta</comment>
- <comment xml:lang="id">halaman bantuan</comment>
- <comment xml:lang="it">Pagina di aiuto</comment>
- <comment xml:lang="ja">ヘルプページ</comment>
- <comment xml:lang="kk">анықтама парағы</comment>
- <comment xml:lang="ko">도움말 페이지</comment>
- <comment xml:lang="lt">žinyno puslapis</comment>
- <comment xml:lang="lv">palīdzības lapa</comment>
- <comment xml:lang="ms">Halaman bantuan</comment>
- <comment xml:lang="nb">hjelpside</comment>
- <comment xml:lang="nl">hulppagina</comment>
- <comment xml:lang="nn">hjelpeside</comment>
- <comment xml:lang="oc">pagina d'ajuda</comment>
- <comment xml:lang="pl">Strona pomocy</comment>
- <comment xml:lang="pt">página de ajuda</comment>
- <comment xml:lang="pt_BR">Página de ajuda</comment>
- <comment xml:lang="ro">pagină de ajutor</comment>
+ <comment>Help page</comment>
+ <comment xml:lang="uk">Довідкова сторінка</comment>
+ <comment xml:lang="sv">Hjälpsida</comment>
<comment xml:lang="ru">Страница справки</comment>
- <comment xml:lang="sk">Stránka Pomocníka</comment>
- <comment xml:lang="sl">stran pomoči</comment>
- <comment xml:lang="sq">Faqe ndihme</comment>
- <comment xml:lang="sr">страница помоћи</comment>
- <comment xml:lang="sv">hjälpsida</comment>
- <comment xml:lang="tr">yardım sayfası</comment>
- <comment xml:lang="uk">сторінка довідки</comment>
- <comment xml:lang="vi">trang trợ giúp</comment>
- <comment xml:lang="zh_CN">帮助页面</comment>
- <comment xml:lang="zh_TW">求助頁面</comment>
+ <comment xml:lang="pt_BR">Página de ajuda</comment>
+ <comment xml:lang="pl">Strona pomocy</comment>
+ <comment xml:lang="ja">取説文書</comment>
+ <comment xml:lang="it">Pagina di aiuto</comment>
+ <comment xml:lang="eu">Laguntza-orria</comment>
+ <comment xml:lang="es">página de ayuda</comment>
+ <comment xml:lang="de">Hilfeseite</comment>
+ <comment xml:lang="be">старонка даведкі</comment>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="text/plain">
- <comment>plain text document</comment>
- <comment xml:lang="ar">مستند نصي مجرد</comment>
- <comment xml:lang="ast">documentu de testu planu</comment>
- <comment xml:lang="be@latin">prosty tekstavy dakument</comment>
- <comment xml:lang="bg">Документ с неформатиран текст</comment>
- <comment xml:lang="ca">document de text pla</comment>
- <comment xml:lang="cs">prostý textový dokument</comment>
- <comment xml:lang="da">rent tekstdokument</comment>
- <comment xml:lang="de">Einfaches Textdokument</comment>
- <comment xml:lang="el">Έγγραφο απλού κειμένου</comment>
- <comment xml:lang="en_GB">plain text document</comment>
- <comment xml:lang="eo">plata teksta dokumento</comment>
- <comment xml:lang="es">documento de texto sencillo</comment>
- <comment xml:lang="eu">testu soileko dokumentua</comment>
- <comment xml:lang="fi">perustekstiasiakirja</comment>
- <comment xml:lang="fr">document texte brut</comment>
- <comment xml:lang="ga">cáipéis ghnáth-théacs</comment>
- <comment xml:lang="gl">documento de texto sinxelo</comment>
- <comment xml:lang="he">מסמך טקסט פשוט</comment>
- <comment xml:lang="hr">Običan tekstovni dokument</comment>
- <comment xml:lang="hu">egyszerű szöveg</comment>
- <comment xml:lang="ia">Documento de texto simple</comment>
- <comment xml:lang="id">dokumen teks polos</comment>
- <comment xml:lang="it">Documento in testo semplice</comment>
- <comment xml:lang="ja">平文テキストドキュメント</comment>
- <comment xml:lang="kk">мәтіндік құжаты</comment>
- <comment xml:lang="ko">일반 텍스트 문서</comment>
- <comment xml:lang="lt">paprastas tekstinis dokumentas</comment>
- <comment xml:lang="lv">vienkāršs teksta dokuments</comment>
- <comment xml:lang="ms">Dokumen teks jernih</comment>
- <comment xml:lang="nb">vanlig tekstdokument</comment>
- <comment xml:lang="nl">plattetekst-document</comment>
- <comment xml:lang="nn">vanleg tekstdokument</comment>
- <comment xml:lang="oc">document tèxte brut</comment>
- <comment xml:lang="pl">Zwykły dokument tekstowy</comment>
- <comment xml:lang="pt">documento em texto simples</comment>
- <comment xml:lang="pt_BR">Documento de Texto</comment>
- <comment xml:lang="ro">document text simplu</comment>
+ <comment>Plain text document</comment>
+ <comment xml:lang="uk">простий текстовий документ</comment>
+ <comment xml:lang="sv">Vanligt textdokument</comment>
<comment xml:lang="ru">Текстовый документ</comment>
- <comment xml:lang="sk">Obyčajný textový dokument</comment>
- <comment xml:lang="sl">običajna besedilna datoteka</comment>
- <comment xml:lang="sq">Dokument në tekst të thjeshtë</comment>
- <comment xml:lang="sr">обичан текстуални документ</comment>
- <comment xml:lang="sv">vanligt textdokument</comment>
- <comment xml:lang="tr">düz metin belgesi</comment>
- <comment xml:lang="uk">звичайний текстовий документ</comment>
- <comment xml:lang="vi">tài liệu nhập thô</comment>
- <comment xml:lang="zh_CN">纯文本文档</comment>
- <comment xml:lang="zh_TW">純文字文件</comment>
- <magic priority="50">
- <match value="This is TeX," type="string" offset="0"/>
- <match value="This is METAFONT," type="string" offset="0"/>
+ <comment xml:lang="pt_BR">Documento de texto simples</comment>
+ <comment xml:lang="pl">Zwykły dokument tekstowy</comment>
+ <comment xml:lang="ja">平文文書</comment>
+ <comment xml:lang="it">Documento in testo semplice</comment>
+ <comment xml:lang="eu">Testu soileko dokumentua</comment>
+ <comment xml:lang="es">documento de texto sin formato</comment>
+ <comment xml:lang="de">Einfaches Textdokument</comment>
+ <comment xml:lang="be">звычайны тэкст</comment>
+ <magic>
+ <match type="string" value="This is TeX," offset="0"/>
+ <match type="string" value="This is METAFONT," offset="0"/>
</magic>
<glob pattern="*.txt"/>
<glob pattern="*.asc"/>
@@ -32033,53 +34083,58 @@
</mime-type>
<mime-type type="application/rdf+xml">
<comment>RDF file</comment>
- <comment xml:lang="ar">ملف RDF</comment>
- <comment xml:lang="be@latin">Fajł RDF</comment>
- <comment xml:lang="bg">Файл — RDF</comment>
- <comment xml:lang="ca">fitxer RDF</comment>
- <comment xml:lang="cs">soubor RDF</comment>
- <comment xml:lang="da">RDF-fil</comment>
- <comment xml:lang="de">RDF-Datei</comment>
- <comment xml:lang="el">Αρχείο RDF</comment>
- <comment xml:lang="en_GB">RDF file</comment>
- <comment xml:lang="eo">RDF-dosiero</comment>
- <comment xml:lang="es">archivo RDF</comment>
- <comment xml:lang="eu">RDF fitxategia</comment>
- <comment xml:lang="fi">RDF-tiedosto</comment>
- <comment xml:lang="fo">RDF fíla</comment>
- <comment xml:lang="fr">fichier RDF</comment>
- <comment xml:lang="ga">comhad RDF</comment>
- <comment xml:lang="gl">ficheiro RDF</comment>
- <comment xml:lang="he">קובץ RDF</comment>
- <comment xml:lang="hr">RDF datoteka</comment>
- <comment xml:lang="hu">RDF fájl</comment>
- <comment xml:lang="ia">File RDF</comment>
- <comment xml:lang="id">Arsip RDF</comment>
- <comment xml:lang="it">File RDF</comment>
- <comment xml:lang="ja">RDF ファイル</comment>
- <comment xml:lang="kk">RDF файлы</comment>
- <comment xml:lang="ko">RDF 파일</comment>
- <comment xml:lang="lt">RDF failas</comment>
- <comment xml:lang="lv">RDF datne</comment>
- <comment xml:lang="nb">RDF-fil</comment>
- <comment xml:lang="nl">RDF-bestand</comment>
- <comment xml:lang="nn">RDF-fil</comment>
- <comment xml:lang="oc">fichièr RDF</comment>
- <comment xml:lang="pl">Plik RDF</comment>
- <comment xml:lang="pt">ficheiro RDF</comment>
- <comment xml:lang="pt_BR">Arquivo RDF</comment>
- <comment xml:lang="ro">Fișier RDF</comment>
- <comment xml:lang="ru">Файл RDF</comment>
- <comment xml:lang="sk">Súbor RDF</comment>
- <comment xml:lang="sl">Datoteka RDF</comment>
- <comment xml:lang="sq">File RDF</comment>
- <comment xml:lang="sr">РДФ датотека</comment>
- <comment xml:lang="sv">RDF-fil</comment>
- <comment xml:lang="tr">RDF dosyası</comment>
- <comment xml:lang="uk">файл RDF</comment>
- <comment xml:lang="vi">Tập tin RDF</comment>
- <comment xml:lang="zh_CN">RDF 文件</comment>
<comment xml:lang="zh_TW">RDF 檔</comment>
+ <comment xml:lang="zh_CN">RDF 文件</comment>
+ <comment xml:lang="vi">Tập tin RDF</comment>
+ <comment xml:lang="uk">файл RDF</comment>
+ <comment xml:lang="tr">RDF dosyası</comment>
+ <comment xml:lang="sv">RDF-fil</comment>
+ <comment xml:lang="sr">РДФ датотека</comment>
+ <comment xml:lang="sq">kartelë RDF</comment>
+ <comment xml:lang="sl">Datoteka RDF</comment>
+ <comment xml:lang="si">RDF ගොනුව</comment>
+ <comment xml:lang="sk">Súbor RDF</comment>
+ <comment xml:lang="ru">Файл RDF</comment>
+ <comment xml:lang="ro">Fișier RDF</comment>
+ <comment xml:lang="pt_BR">Arquivo RDF</comment>
+ <comment xml:lang="pt">ficheiro RDF</comment>
+ <comment xml:lang="pl">Plik RDF</comment>
+ <comment xml:lang="oc">fichièr RDF</comment>
+ <comment xml:lang="nn">RDF-fil</comment>
+ <comment xml:lang="nl">RDF-bestand</comment>
+ <comment xml:lang="nb">RDF-fil</comment>
+ <comment xml:lang="lv">RDF datne</comment>
+ <comment xml:lang="lt">RDF failas</comment>
+ <comment xml:lang="ko">RDF 파일</comment>
+ <comment xml:lang="kk">RDF файлы</comment>
+ <comment xml:lang="ja">RDF ファイル</comment>
+ <comment xml:lang="it">File RDF</comment>
+ <comment xml:lang="is">RDF skrá</comment>
+ <comment xml:lang="id">Arsip RDF</comment>
+ <comment xml:lang="ia">File RDF</comment>
+ <comment xml:lang="hu">RDF fájl</comment>
+ <comment xml:lang="hr">RDF datoteka</comment>
+ <comment xml:lang="he">קובץ RDF</comment>
+ <comment xml:lang="gl">ficheiro RDF</comment>
+ <comment xml:lang="ga">comhad RDF</comment>
+ <comment xml:lang="fur">file RDF</comment>
+ <comment xml:lang="fr">fichier RDF</comment>
+ <comment xml:lang="fo">RDF fíla</comment>
+ <comment xml:lang="fi">RDF-tiedosto</comment>
+ <comment xml:lang="eu">RDF fitxategia</comment>
+ <comment xml:lang="es">archivo RDF</comment>
+ <comment xml:lang="eo">RDF-dosiero</comment>
+ <comment xml:lang="en_GB">RDF file</comment>
+ <comment xml:lang="el">Αρχείο RDF</comment>
+ <comment xml:lang="de">RDF-Datei</comment>
+ <comment xml:lang="da">RDF-fil</comment>
+ <comment xml:lang="cs">soubor RDF</comment>
+ <comment xml:lang="ca">fitxer RDF</comment>
+ <comment xml:lang="bg">Файл — RDF</comment>
+ <comment xml:lang="be@latin">Fajł RDF</comment>
+ <comment xml:lang="be">файл RDF</comment>
+ <comment xml:lang="ar">ملف RDF</comment>
+ <comment xml:lang="af">RDF-lêer</comment>
<acronym>RDF</acronym>
<expanded-acronym>Resource Description Framework</expanded-acronym>
<alias type="text/rdf"/>
@@ -32089,203 +34144,153 @@
<glob pattern="*.owl"/>
<root-XML namespaceURI="http://www.w3.org/1999/02/22-rdf-syntax-ns#" localName="RDF"/>
</mime-type>
+ <mime-type type="text/x-rst">
+ <comment>ReStructuredText document</comment>
+ <comment xml:lang="uk">документ ReStructuredText</comment>
+ <comment xml:lang="sv">ReStructuredText-dokument</comment>
+ <comment xml:lang="ru">Документ ReStructuredText</comment>
+ <comment xml:lang="pl">Dokument reStructuredText</comment>
+ <comment xml:lang="it">Documento reStructuredText</comment>
+ <comment xml:lang="eu">ReStructuredText dokumentua</comment>
+ <comment xml:lang="es">documento ReStructuredText</comment>
+ <comment xml:lang="de">reStructuredText-Dokument</comment>
+ <comment xml:lang="be">дакумент reStructuredText</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.rst"/>
+ </mime-type>
<mime-type type="application/owl+xml">
<comment>OWL XML file</comment>
- <comment xml:lang="ca">fitxer XML OWL</comment>
- <comment xml:lang="cs">soubor OWL XML</comment>
- <comment xml:lang="da">OWL XML-fil</comment>
- <comment xml:lang="de">OWL-XML-Datei</comment>
- <comment xml:lang="el">Αρχείο OWL XML</comment>
- <comment xml:lang="en_GB">OWL XML file</comment>
- <comment xml:lang="es">archivo en XML OWL</comment>
- <comment xml:lang="eu">OWL XML fitxategia</comment>
- <comment xml:lang="fr">fichier XML OWL</comment>
- <comment xml:lang="ga">comhad XML OWL</comment>
- <comment xml:lang="hr">OWL XML datoteka</comment>
- <comment xml:lang="hu">OWL XML-fájl</comment>
- <comment xml:lang="ia">File XML OWL</comment>
- <comment xml:lang="id">Berkas XML OWL</comment>
- <comment xml:lang="it">File XML OWL</comment>
- <comment xml:lang="kk">OWL XML файлы</comment>
- <comment xml:lang="ko">OWL XML 파일</comment>
- <comment xml:lang="oc">fichièr OWL XML</comment>
- <comment xml:lang="pl">Plik XML OWL</comment>
- <comment xml:lang="pt">ficheiro OWL XML</comment>
- <comment xml:lang="pt_BR">Arquivo OWL XML</comment>
- <comment xml:lang="ru">Файл XML OWL</comment>
- <comment xml:lang="sk">Súbor XML OWL</comment>
- <comment xml:lang="sr">ОВЛ ИксМЛ датотека</comment>
- <comment xml:lang="sv">OWL XML-fil</comment>
- <comment xml:lang="tr">OWL XML dosyası</comment>
- <comment xml:lang="uk">файл XML OWL</comment>
- <comment xml:lang="zh_CN">OWL XML 文件</comment>
<comment xml:lang="zh_TW">OWL XML 檔案</comment>
+ <comment xml:lang="zh_CN">OWL XML 文件</comment>
+ <comment xml:lang="uk">файл XML OWL</comment>
+ <comment xml:lang="tr">OWL XML dosyası</comment>
+ <comment xml:lang="sv">OWL XML-fil</comment>
+ <comment xml:lang="sr">ОВЛ ИксМЛ датотека</comment>
+ <comment xml:lang="sq">kartelë OWL XML</comment>
+ <comment xml:lang="sl">Datoteka OWL XML</comment>
+ <comment xml:lang="si">OWL XML ගොනුව</comment>
+ <comment xml:lang="sk">Súbor XML OWL</comment>
+ <comment xml:lang="ru">Файл XML OWL</comment>
+ <comment xml:lang="pt_BR">Arquivo OWL XML</comment>
+ <comment xml:lang="pt">ficheiro OWL XML</comment>
+ <comment xml:lang="pl">Plik XML OWL</comment>
+ <comment xml:lang="oc">fichièr OWL XML</comment>
+ <comment xml:lang="nl">OWL XML-bestand</comment>
+ <comment xml:lang="ko">OWL XML 파일</comment>
+ <comment xml:lang="kk">OWL XML файлы</comment>
+ <comment xml:lang="ja">OWL XML ファイル</comment>
+ <comment xml:lang="it">File XML OWL</comment>
+ <comment xml:lang="is">OWL XML skrá</comment>
+ <comment xml:lang="id">Berkas XML OWL</comment>
+ <comment xml:lang="ia">File XML OWL</comment>
+ <comment xml:lang="hu">OWL XML-fájl</comment>
+ <comment xml:lang="hr">OWL XML datoteka</comment>
+ <comment xml:lang="he">קובץ XML מסוג OWL</comment>
+ <comment xml:lang="ga">comhad XML OWL</comment>
+ <comment xml:lang="fur">file OWL XML</comment>
+ <comment xml:lang="fr">fichier XML OWL</comment>
+ <comment xml:lang="fi">OWL XML -tiedosto</comment>
+ <comment xml:lang="eu">OWL XML fitxategia</comment>
+ <comment xml:lang="es">archivo en XML OWL</comment>
+ <comment xml:lang="en_GB">OWL XML file</comment>
+ <comment xml:lang="el">Αρχείο OWL XML</comment>
+ <comment xml:lang="de">OWL-XML-Datei</comment>
+ <comment xml:lang="da">OWL XML-fil</comment>
+ <comment xml:lang="cs">soubor OWL XML</comment>
+ <comment xml:lang="ca">fitxer XML OWL</comment>
+ <comment xml:lang="bg">Файл — OWL XML</comment>
+ <comment xml:lang="be">файл OWL XML</comment>
+ <comment xml:lang="ar">ملف OWL XML</comment>
+ <comment xml:lang="af">OWL XML-lêer</comment>
<acronym>OWL</acronym>
<expanded-acronym>Web Ontology Language</expanded-acronym>
<sub-class-of type="application/xml"/>
<glob pattern="*.owx"/>
<magic>
- <match value="&lt;Ontology" type="string" offset="0:256"/>
+ <match type="string" value="&lt;Ontology" offset="0:256"/>
</magic>
<root-XML namespaceURI="http://www.w3.org/2002/07/owl#" localName="Ontology"/>
</mime-type>
<mime-type type="text/rfc822-headers">
- <comment>email headers</comment>
- <comment xml:lang="ar">ترويسة البريد الإلكتروني</comment>
- <comment xml:lang="az">epoçt başlıqları</comment>
- <comment xml:lang="be@latin">paštovyja zahałoŭki</comment>
- <comment xml:lang="bg">Заглавни части на електронни писма</comment>
- <comment xml:lang="ca">capçaleres de correu electrònic</comment>
- <comment xml:lang="cs">záhlaví e-mailu</comment>
- <comment xml:lang="cy">penawdau e-bost</comment>
- <comment xml:lang="da">posthoveder</comment>
- <comment xml:lang="de">E-Mail-Kopfzeilen</comment>
- <comment xml:lang="el">Κεφαλίδες ηλ. μηνυμάτων</comment>
- <comment xml:lang="en_GB">email headers</comment>
- <comment xml:lang="eo">retpoŝtaj ĉapoj</comment>
- <comment xml:lang="es">cabeceras de correo electrónico</comment>
- <comment xml:lang="eu">helbide elektronikoen goiburuak</comment>
- <comment xml:lang="fi">sähköpostiotsakkeet</comment>
- <comment xml:lang="fo">t-post tekshøvd</comment>
- <comment xml:lang="fr">en-têtes de courriel</comment>
- <comment xml:lang="ga">ceanntásca ríomhphoist</comment>
- <comment xml:lang="gl">cabeceiras de correo electrónico</comment>
- <comment xml:lang="he">כותרת דוא״ל</comment>
- <comment xml:lang="hr">Zaglavlja e-pošte</comment>
- <comment xml:lang="hu">levélfejléc</comment>
- <comment xml:lang="ia">Capites de e-mail</comment>
- <comment xml:lang="id">header email</comment>
- <comment xml:lang="it">Intestazioni email</comment>
- <comment xml:lang="ja">メールヘッダー</comment>
- <comment xml:lang="kk">пошталық тақырыптамалары</comment>
- <comment xml:lang="ko">전자메일 헤더</comment>
- <comment xml:lang="lt">el. laiško antraštės</comment>
- <comment xml:lang="lv">e-pasta galvene</comment>
- <comment xml:lang="ms">Pengepala emel</comment>
- <comment xml:lang="nb">e-posthode</comment>
- <comment xml:lang="nl">e-mail-kopregels</comment>
- <comment xml:lang="nn">e-post-hovud</comment>
- <comment xml:lang="oc">entèstas de corrièr electronic</comment>
- <comment xml:lang="pl">Nagłówki wiadomości e-mail</comment>
- <comment xml:lang="pt">cabeçalhos de email</comment>
- <comment xml:lang="pt_BR">Cabeçalhos de e-mail</comment>
- <comment xml:lang="ro">antete email</comment>
+ <comment>Email headers</comment>
+ <comment xml:lang="uk">заголовки повідомлення ел. пошти</comment>
+ <comment xml:lang="sv">E-posthuvuden</comment>
<comment xml:lang="ru">Почтовые заголовки</comment>
- <comment xml:lang="sk">Hlavičky e-mailu</comment>
- <comment xml:lang="sl">glava elektronske pošte</comment>
- <comment xml:lang="sq">Header email</comment>
- <comment xml:lang="sr">заглавља ел. поште</comment>
- <comment xml:lang="sv">e-posthuvuden</comment>
- <comment xml:lang="tr">eposta başlığı</comment>
- <comment xml:lang="uk">заголовки email</comment>
- <comment xml:lang="vi">dòng đầu thư điện tử</comment>
- <comment xml:lang="zh_CN">电子邮件头</comment>
- <comment xml:lang="zh_TW">電子郵件標頭</comment>
+ <comment xml:lang="pl">Nagłówki wiadomości e-mail</comment>
+ <comment xml:lang="it">Intestazioni email</comment>
+ <comment xml:lang="eu">Posta-goiburuak</comment>
+ <comment xml:lang="es">cabeceras de correo electrónico</comment>
+ <comment xml:lang="de">E-Mail-Kopfzeilen</comment>
+ <comment xml:lang="be">паштовыя загалоўкі</comment>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="text/richtext">
- <comment>rich text document</comment>
- <comment xml:lang="ar">مستند نصي غني</comment>
- <comment xml:lang="ast">documentu de testu ricu</comment>
- <comment xml:lang="az">zəngin mətn sənədi</comment>
- <comment xml:lang="be@latin">azdobleny tekstavy dakument</comment>
- <comment xml:lang="bg">Документ — rich text</comment>
- <comment xml:lang="ca">document de text enriquit</comment>
- <comment xml:lang="cs">textový dokument RTF</comment>
- <comment xml:lang="cy">dogfen testun gyfoethog (rtf)</comment>
- <comment xml:lang="da">richtekstdokument</comment>
- <comment xml:lang="de">RTF-Textdokument</comment>
- <comment xml:lang="el">Έγγραφο εμπλουτισμένου κειμένου (RTF)</comment>
- <comment xml:lang="en_GB">rich text document</comment>
- <comment xml:lang="eo">riĉteksta dokumento</comment>
- <comment xml:lang="es">documento de texto enriquecido</comment>
- <comment xml:lang="eu">aberastutako testu formatua</comment>
- <comment xml:lang="fi">RTF-asiakirja</comment>
- <comment xml:lang="fr">document « rich text »</comment>
- <comment xml:lang="ga">cáipéis mhéith-théacs</comment>
- <comment xml:lang="gl">documento do texto enriquecido</comment>
- <comment xml:lang="he">מסמך טקסט עשיר</comment>
- <comment xml:lang="hr">Obogaćeni tekstovni dokument</comment>
- <comment xml:lang="hu">rich text-dokumentum</comment>
- <comment xml:lang="ia">Documento de texto inricchite</comment>
- <comment xml:lang="id">dokumen teks kaya</comment>
- <comment xml:lang="it">Documento rich text</comment>
- <comment xml:lang="ja">リッチテキストドキュメント</comment>
- <comment xml:lang="kk">пішімделген мәтіні бар құжаты</comment>
- <comment xml:lang="ko">서식 있는 텍스트 문서</comment>
- <comment xml:lang="lt">praturtinto teksto dokumentas</comment>
- <comment xml:lang="lv">bagātā teksta dokuments</comment>
- <comment xml:lang="ms">Dokumen teks diperkaya</comment>
- <comment xml:lang="nb">rik tekst-dokument</comment>
- <comment xml:lang="nl">opgemaakt tekstdocument</comment>
- <comment xml:lang="nn">rik tekst-dokument</comment>
- <comment xml:lang="oc">document « rich text »</comment>
- <comment xml:lang="pl">Dokument Rich Text</comment>
- <comment xml:lang="pt">documento em texto rico</comment>
- <comment xml:lang="pt_BR">Documento rich text</comment>
- <comment xml:lang="ro">document text îmbogățit</comment>
- <comment xml:lang="ru">Документ с форматированным текстом</comment>
- <comment xml:lang="sk">Textový dokument RTF</comment>
- <comment xml:lang="sl">dokument z oblikovanim besedilom</comment>
- <comment xml:lang="sq">Dokument rich text</comment>
- <comment xml:lang="sr">богат текстуални документ</comment>
- <comment xml:lang="sv">RTF-textdokument</comment>
- <comment xml:lang="tr">zengin metin belgesi</comment>
+ <comment>Rich text document</comment>
<comment xml:lang="uk">форматований текстовий документ</comment>
- <comment xml:lang="vi">tài liệu văn bản có kiểu dáng (RTF)</comment>
- <comment xml:lang="zh_CN">富文本文档 (RTF)</comment>
- <comment xml:lang="zh_TW">豐富文字文件</comment>
+ <comment xml:lang="sv">Rich text-dokument</comment>
+ <comment xml:lang="ru">Форматированный текстовый документ</comment>
+ <comment xml:lang="pl">Dokument Rich Text</comment>
+ <comment xml:lang="it">Documento testo arricchito</comment>
+ <comment xml:lang="eu">Testu aberatseko dokumentua</comment>
+ <comment xml:lang="es">documento de texto enriquecido</comment>
+ <comment xml:lang="de">RTF-Textdokument</comment>
+ <comment xml:lang="be">дакумент у фармаце RTF</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.rtx"/>
</mime-type>
<mime-type type="application/rss+xml">
<comment>RSS summary</comment>
- <comment xml:lang="ar">ملخص RSS</comment>
- <comment xml:lang="be@latin">Karotki ahlad RSS</comment>
- <comment xml:lang="bg">Обобщение за сайтове — RSS</comment>
- <comment xml:lang="ca">resum RSS</comment>
- <comment xml:lang="cs">souhrn RSS</comment>
- <comment xml:lang="da">RSS-sammendrag</comment>
- <comment xml:lang="de">RSS-Zusammenfassung</comment>
- <comment xml:lang="el">Σύνοψη RSS</comment>
- <comment xml:lang="en_GB">RSS summary</comment>
- <comment xml:lang="es">resumen de RSS</comment>
- <comment xml:lang="eu">RSS laburpena</comment>
- <comment xml:lang="fi">RSS-tiivistelmä</comment>
- <comment xml:lang="fo">RSS samandráttur</comment>
- <comment xml:lang="fr">résumé RSS</comment>
- <comment xml:lang="ga">achoimre RSS</comment>
- <comment xml:lang="gl">Resumo RSS</comment>
- <comment xml:lang="he">תקציר RSS</comment>
- <comment xml:lang="hr">RSS sažetak</comment>
- <comment xml:lang="hu">RSS összefoglaló</comment>
- <comment xml:lang="ia">Summario RSS</comment>
- <comment xml:lang="id">Ringkasan RSS</comment>
- <comment xml:lang="it">Sommario RSS</comment>
- <comment xml:lang="ja">RSS サマリ</comment>
- <comment xml:lang="kk">RSS жинақталғаны</comment>
- <comment xml:lang="ko">RSS 요약</comment>
- <comment xml:lang="lt">RSS santrauka</comment>
- <comment xml:lang="lv">RSS kopsavilkums</comment>
- <comment xml:lang="nb">RSS-sammendrag</comment>
- <comment xml:lang="nl">RSS-samenvatting</comment>
- <comment xml:lang="nn">RSS-samandrag</comment>
- <comment xml:lang="oc">resumit RSS</comment>
- <comment xml:lang="pl">Podsumowanie RSS</comment>
- <comment xml:lang="pt">resumo RSS</comment>
- <comment xml:lang="pt_BR">Resumo RSS</comment>
- <comment xml:lang="ro">Rezumat RSS</comment>
- <comment xml:lang="ru">Сводка RSS</comment>
- <comment xml:lang="sk">Súhrn RSS</comment>
- <comment xml:lang="sl">Datoteka povzetek RSS</comment>
- <comment xml:lang="sq">Përmbledhje RSS</comment>
- <comment xml:lang="sr">РСС сажетак</comment>
- <comment xml:lang="sv">RSS-sammanfattning</comment>
- <comment xml:lang="tr">RSS özeti</comment>
- <comment xml:lang="uk">зведення сайту RSS</comment>
- <comment xml:lang="vi">Bản tóm tắt RSS</comment>
- <comment xml:lang="zh_CN">RSS 摘要</comment>
<comment xml:lang="zh_TW">RSS 摘要</comment>
+ <comment xml:lang="zh_CN">RSS 摘要</comment>
+ <comment xml:lang="vi">Bản tóm tắt RSS</comment>
+ <comment xml:lang="uk">зведення сайту RSS</comment>
+ <comment xml:lang="tr">RSS özeti</comment>
+ <comment xml:lang="sv">RSS-sammanfattning</comment>
+ <comment xml:lang="sr">РСС сажетак</comment>
+ <comment xml:lang="sq">përmbledhje RSS</comment>
+ <comment xml:lang="sl">Datoteka povzetek RSS</comment>
+ <comment xml:lang="si">RSS සාරාංශය</comment>
+ <comment xml:lang="sk">Súhrn RSS</comment>
+ <comment xml:lang="ru">Сводка RSS</comment>
+ <comment xml:lang="ro">Rezumat RSS</comment>
+ <comment xml:lang="pt_BR">Resumo RSS</comment>
+ <comment xml:lang="pt">resumo RSS</comment>
+ <comment xml:lang="pl">Podsumowanie RSS</comment>
+ <comment xml:lang="oc">resumit RSS</comment>
+ <comment xml:lang="nn">RSS-samandrag</comment>
+ <comment xml:lang="nl">RSS-samenvatting</comment>
+ <comment xml:lang="nb">RSS-sammendrag</comment>
+ <comment xml:lang="lv">RSS kopsavilkums</comment>
+ <comment xml:lang="lt">RSS santrauka</comment>
+ <comment xml:lang="ko">RSS 요약</comment>
+ <comment xml:lang="kk">RSS жинақталғаны</comment>
+ <comment xml:lang="ja">RSS サマリ</comment>
+ <comment xml:lang="it">Sommario RSS</comment>
+ <comment xml:lang="is">RSS samantekt</comment>
+ <comment xml:lang="id">Ringkasan RSS</comment>
+ <comment xml:lang="ia">Summario RSS</comment>
+ <comment xml:lang="hu">RSS összefoglaló</comment>
+ <comment xml:lang="hr">RSS sažetak</comment>
+ <comment xml:lang="he">תקציר RSS</comment>
+ <comment xml:lang="gl">Resumo RSS</comment>
+ <comment xml:lang="ga">achoimre RSS</comment>
+ <comment xml:lang="fur">somari RSS</comment>
+ <comment xml:lang="fr">résumé RSS</comment>
+ <comment xml:lang="fo">RSS samandráttur</comment>
+ <comment xml:lang="fi">RSS-tiivistelmä</comment>
+ <comment xml:lang="eu">RSS laburpena</comment>
+ <comment xml:lang="es">suministro RSS</comment>
+ <comment xml:lang="en_GB">RSS summary</comment>
+ <comment xml:lang="el">Σύνοψη RSS</comment>
+ <comment xml:lang="de">RSS-Zusammenfassung</comment>
+ <comment xml:lang="da">RSS-sammendrag</comment>
+ <comment xml:lang="cs">souhrn RSS</comment>
+ <comment xml:lang="ca">resum RSS</comment>
+ <comment xml:lang="bg">Обобщение за сайтове — RSS</comment>
+ <comment xml:lang="be@latin">Karotki ahlad RSS</comment>
+ <comment xml:lang="be">зводка RSS</comment>
+ <comment xml:lang="ar">ملخص RSS</comment>
+ <comment xml:lang="af">RSS-opsomming</comment>
<acronym>RSS</acronym>
<expanded-acronym>RDF Site Summary</expanded-acronym>
<alias type="text/rss"/>
@@ -32293,172 +34298,187 @@
<generic-icon name="text-html"/>
<glob pattern="*.rss"/>
<magic priority="70">
- <match value="&lt;rss " type="string" offset="0:256"/>
- <match value="&lt;RSS " type="string" offset="0:256"/>
+ <match type="string" value="&lt;rss " offset="0:256"/>
+ <match type="string" value="&lt;RSS " offset="0:256"/>
</magic>
</mime-type>
<mime-type type="application/atom+xml">
<comment>Atom syndication feed</comment>
- <comment xml:lang="ar">مروج تغذية Atom</comment>
- <comment xml:lang="be@latin">Syndykacyjny kanał navinaŭ Atom</comment>
- <comment xml:lang="bg">Емисия — Atom</comment>
- <comment xml:lang="ca">canal de sindicació Atom</comment>
- <comment xml:lang="cs">kanál Atom</comment>
- <comment xml:lang="da">Atom syndication-feed</comment>
- <comment xml:lang="de">Atom-Nachrichtenquelle</comment>
- <comment xml:lang="el">Τροφοδοσία διανομής Atom</comment>
- <comment xml:lang="en_GB">Atom syndication feed</comment>
- <comment xml:lang="es">canal de noticias Atom</comment>
- <comment xml:lang="eu">Atom harpidetze-iturria</comment>
- <comment xml:lang="fi">Atom-yhdistevirta</comment>
- <comment xml:lang="fr">fil de syndication Atom</comment>
- <comment xml:lang="ga">fotha sindeacáitithe Atom</comment>
- <comment xml:lang="gl">fonte de sindicación Atom</comment>
- <comment xml:lang="he">הזנה דרך הרשת של Atom</comment>
- <comment xml:lang="hr">Atom kanal objavljivanja</comment>
- <comment xml:lang="hu">Atom egyesítőfolyam</comment>
- <comment xml:lang="ia">Fluxo de syndication Atom</comment>
- <comment xml:lang="id">Umpan sindikasi Atom</comment>
- <comment xml:lang="it">Feed di distribuzione Atom</comment>
- <comment xml:lang="ja">Atom 配信フィード</comment>
- <comment xml:lang="kk">Atom жаңалықтар таспасы</comment>
- <comment xml:lang="ko">Atom 묶음 피드</comment>
- <comment xml:lang="lt">Atom sindikacijos kanalas</comment>
- <comment xml:lang="lv">Atom sindikāta barotne</comment>
- <comment xml:lang="nb">Atom syndikeringsstrøm</comment>
- <comment xml:lang="nl">Atom-syndicatie-feed</comment>
- <comment xml:lang="nn">Atom-kjelde</comment>
- <comment xml:lang="oc">fial de sindicacion Atom</comment>
- <comment xml:lang="pl">Kanał Atom</comment>
- <comment xml:lang="pt">feed Atom</comment>
- <comment xml:lang="pt_BR">Fonte de notícias Atom</comment>
- <comment xml:lang="ro">Flux agregare Atom</comment>
- <comment xml:lang="ru">Лента новостей Atom</comment>
- <comment xml:lang="sk">Kanál Atom</comment>
- <comment xml:lang="sl">Sindikalni vir Atom</comment>
- <comment xml:lang="sq">Feed për përhapje Atom</comment>
- <comment xml:lang="sr">Атомов довод синдикализације</comment>
- <comment xml:lang="sv">Atom-syndikeringskanal</comment>
- <comment xml:lang="tr">Atom besleme kaynağı</comment>
- <comment xml:lang="uk">трансляція подач Atom</comment>
- <comment xml:lang="vi">Nguồn tin tức Atom</comment>
- <comment xml:lang="zh_CN">Atom 聚合种子</comment>
<comment xml:lang="zh_TW">Atom 聯合供稿饋流</comment>
+ <comment xml:lang="zh_CN">Atom 聚合种子</comment>
+ <comment xml:lang="vi">Nguồn tin tức Atom</comment>
+ <comment xml:lang="uk">трансляція подач Atom</comment>
+ <comment xml:lang="tr">Atom besleme kaynağı</comment>
+ <comment xml:lang="sv">Atom-syndikeringskanal</comment>
+ <comment xml:lang="sr">Атомов довод синдикализације</comment>
+ <comment xml:lang="sq">prurje RSS Atom</comment>
+ <comment xml:lang="sl">Sindikalni vir Atom</comment>
+ <comment xml:lang="si">පරමාණු සින්ඩිකේෂන් පෝෂණය</comment>
+ <comment xml:lang="sk">Kanál Atom</comment>
+ <comment xml:lang="ru">Лента новостей Atom</comment>
+ <comment xml:lang="ro">Flux agregare Atom</comment>
+ <comment xml:lang="pt_BR">Fonte de notícias Atom</comment>
+ <comment xml:lang="pt">feed Atom</comment>
+ <comment xml:lang="pl">Kanał Atom</comment>
+ <comment xml:lang="oc">fial de sindicacion Atom</comment>
+ <comment xml:lang="nn">Atom-kjelde</comment>
+ <comment xml:lang="nl">Atom-syndicatie-feed</comment>
+ <comment xml:lang="nb">Atom syndikeringsstrøm</comment>
+ <comment xml:lang="lv">Atom sindikāta barotne</comment>
+ <comment xml:lang="lt">Atom sindikacijos kanalas</comment>
+ <comment xml:lang="ko">Atom 묶음 피드</comment>
+ <comment xml:lang="kk">Atom жаңалықтар таспасы</comment>
+ <comment xml:lang="ja">Atom 配信フィード</comment>
+ <comment xml:lang="it">Feed di distribuzione Atom</comment>
+ <comment xml:lang="is">Atom fréttastreymi</comment>
+ <comment xml:lang="id">Umpan sindikasi Atom</comment>
+ <comment xml:lang="ia">Fluxo de syndication Atom</comment>
+ <comment xml:lang="hu">Atom egyesítőfolyam</comment>
+ <comment xml:lang="hr">Atom kanal objavljivanja</comment>
+ <comment xml:lang="he">הזנה דרך הרשת של Atom</comment>
+ <comment xml:lang="gl">fonte de sindicación Atom</comment>
+ <comment xml:lang="ga">fotha sindeacáitithe Atom</comment>
+ <comment xml:lang="fur">canâl di notiziis Atom</comment>
+ <comment xml:lang="fr">fil de syndication Atom</comment>
+ <comment xml:lang="fi">Atom-yhdistevirta</comment>
+ <comment xml:lang="eu">Atom harpidetze-iturria</comment>
+ <comment xml:lang="es">suministro de sindicación Atom</comment>
+ <comment xml:lang="en_GB">Atom syndication feed</comment>
+ <comment xml:lang="el">Τροφοδοσία διανομής Atom</comment>
+ <comment xml:lang="de">Atom-Nachrichtenquelle</comment>
+ <comment xml:lang="da">Atom-syndikeringsfeed</comment>
+ <comment xml:lang="cs">kanál Atom</comment>
+ <comment xml:lang="ca">canal de sindicació Atom</comment>
+ <comment xml:lang="bg">Емисия — Atom</comment>
+ <comment xml:lang="be@latin">Syndykacyjny kanał navinaŭ Atom</comment>
+ <comment xml:lang="be">канал сіндыкацыі Atom</comment>
+ <comment xml:lang="ar">مروج تغذية Atom</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="text-html"/>
<glob pattern="*.atom"/>
<magic priority="70">
- <match value="&lt;feed " type="string" offset="0:256"/>
+ <match type="string" value="&lt;feed " offset="0:256"/>
</magic>
<root-XML namespaceURI="http://www.w3.org/2005/Atom" localName="feed"/>
</mime-type>
<mime-type type="text/x-opml+xml">
<comment>OPML syndication feed</comment>
- <comment xml:lang="ar">مروج تغذية OPML</comment>
- <comment xml:lang="be@latin">Syndykacyjny kanał OPML</comment>
- <comment xml:lang="bg">Емисия — OPML</comment>
- <comment xml:lang="ca">canal de sindicació OPML</comment>
- <comment xml:lang="cs">kanál OPML</comment>
- <comment xml:lang="da">OPML-syndikeringsfeed</comment>
- <comment xml:lang="de">OPML-Nachrichtenquelle</comment>
- <comment xml:lang="el">Τροφοδοσία OPML</comment>
- <comment xml:lang="en_GB">OPML syndication feed</comment>
- <comment xml:lang="es">canal de noticias OPML</comment>
- <comment xml:lang="eu">OPML harpidetze-iturria</comment>
- <comment xml:lang="fi">OPML-yhdistevirta</comment>
- <comment xml:lang="fr">fil de syndication OPML</comment>
- <comment xml:lang="ga">fotha sindeacáitithe OPML</comment>
- <comment xml:lang="gl">fonte de sindicación OPML</comment>
- <comment xml:lang="he">הזנה דרך הרשת OPML</comment>
- <comment xml:lang="hr">OPML kanal objavljivanja</comment>
- <comment xml:lang="hu">OPML egyesítőfolyam</comment>
- <comment xml:lang="ia">Fluxo de syndication OPML</comment>
- <comment xml:lang="id">Umpan sindikasi OPML</comment>
- <comment xml:lang="it">Feed di distribuzione OPML</comment>
- <comment xml:lang="ja">OPML 配信フィード</comment>
- <comment xml:lang="kk">OPML жаңалықтар таспасы</comment>
- <comment xml:lang="ko">OPML 묶음 피드</comment>
- <comment xml:lang="lt">OPML sindikacijos kanalas</comment>
- <comment xml:lang="lv">OPML sindikāta barotne</comment>
- <comment xml:lang="nb">OPML syndikeringsstrøm</comment>
- <comment xml:lang="nl">OPML-syndicatie-feed</comment>
- <comment xml:lang="nn">OPML-kjelde</comment>
- <comment xml:lang="oc">fial de sindicacion OPML</comment>
- <comment xml:lang="pl">Kanał OPML</comment>
- <comment xml:lang="pt">feed OPML</comment>
- <comment xml:lang="pt_BR">Fonte de notícias OPML</comment>
- <comment xml:lang="ro">Flux OPML syndication</comment>
- <comment xml:lang="ru">Лента новостей OPML</comment>
- <comment xml:lang="sk">Kanál OPML</comment>
- <comment xml:lang="sl">Sindikalni vir OPML</comment>
- <comment xml:lang="sq">Feed për përhapje OPML</comment>
- <comment xml:lang="sr">ОМПЛ довод синдикализације</comment>
- <comment xml:lang="sv">OPML-syndikeringskanal</comment>
- <comment xml:lang="tr">OPML besleme kaynağı</comment>
- <comment xml:lang="uk">трансляція подач OPML</comment>
- <comment xml:lang="vi">Nguồn tin tức OPML</comment>
- <comment xml:lang="zh_CN">OPML 聚合种子</comment>
<comment xml:lang="zh_TW">OPML 聯合供稿饋流</comment>
+ <comment xml:lang="zh_CN">OPML 聚合种子</comment>
+ <comment xml:lang="vi">Nguồn tin tức OPML</comment>
+ <comment xml:lang="uk">трансляція подач OPML</comment>
+ <comment xml:lang="tr">OPML besleme kaynağı</comment>
+ <comment xml:lang="sv">OPML-syndikeringskanal</comment>
+ <comment xml:lang="sr">ОМПЛ довод синдикализације</comment>
+ <comment xml:lang="sq">Prurje RSS OPML</comment>
+ <comment xml:lang="sl">Sindikalni vir OPML</comment>
+ <comment xml:lang="si">OPML සින්ඩිකේෂන් සංග්‍රහය</comment>
+ <comment xml:lang="sk">Kanál OPML</comment>
+ <comment xml:lang="ru">Лента новостей OPML</comment>
+ <comment xml:lang="ro">Flux OPML syndication</comment>
+ <comment xml:lang="pt_BR">Fonte de notícias OPML</comment>
+ <comment xml:lang="pt">feed OPML</comment>
+ <comment xml:lang="pl">Kanał OPML</comment>
+ <comment xml:lang="oc">fial de sindicacion OPML</comment>
+ <comment xml:lang="nn">OPML-kjelde</comment>
+ <comment xml:lang="nl">OPML-syndicatie-feed</comment>
+ <comment xml:lang="nb">OPML syndikeringsstrøm</comment>
+ <comment xml:lang="lv">OPML sindikāta barotne</comment>
+ <comment xml:lang="lt">OPML sindikacijos kanalas</comment>
+ <comment xml:lang="ko">OPML 묶음 피드</comment>
+ <comment xml:lang="kk">OPML жаңалықтар таспасы</comment>
+ <comment xml:lang="ja">OPML 配信フィード</comment>
+ <comment xml:lang="it">Feed di distribuzione OPML</comment>
+ <comment xml:lang="is">OPML fréttastreymi</comment>
+ <comment xml:lang="id">Umpan sindikasi OPML</comment>
+ <comment xml:lang="ia">Fluxo de syndication OPML</comment>
+ <comment xml:lang="hu">OPML egyesítőfolyam</comment>
+ <comment xml:lang="hr">OPML kanal objavljivanja</comment>
+ <comment xml:lang="he">הזנה דרך הרשת OPML</comment>
+ <comment xml:lang="gl">fonte de sindicación OPML</comment>
+ <comment xml:lang="ga">fotha sindeacáitithe OPML</comment>
+ <comment xml:lang="fur">canâl di notiziis OPML</comment>
+ <comment xml:lang="fr">fil de syndication OPML</comment>
+ <comment xml:lang="fi">OPML-yhdistevirta</comment>
+ <comment xml:lang="eu">OPML harpidetze-iturria</comment>
+ <comment xml:lang="es">suministro de sindicación OPML</comment>
+ <comment xml:lang="en_GB">OPML syndication feed</comment>
+ <comment xml:lang="el">Τροφοδοσία OPML</comment>
+ <comment xml:lang="de">OPML-Nachrichtenquelle</comment>
+ <comment xml:lang="da">OPML-syndikeringsfeed</comment>
+ <comment xml:lang="cs">kanál OPML</comment>
+ <comment xml:lang="ca">canal de sindicació OPML</comment>
+ <comment xml:lang="bg">Емисия — OPML</comment>
+ <comment xml:lang="be@latin">Syndykacyjny kanał OPML</comment>
+ <comment xml:lang="be">канал сіндыкацыі OPML</comment>
+ <comment xml:lang="ar">مروج تغذية OPML</comment>
+ <acronym>OPML</acronym>
+ <expanded-acronym>Outline Processor Markup Language</expanded-acronym>
<sub-class-of type="application/xml"/>
<alias type="text/x-opml"/>
<generic-icon name="text-html"/>
<glob pattern="*.opml"/>
<magic priority="70">
- <match value="&lt;opml " type="string" offset="0:256"/>
+ <match type="string" value="&lt;opml " offset="0:256"/>
</magic>
</mime-type>
<mime-type type="text/sgml">
<comment>SGML document</comment>
- <comment xml:lang="ar">مستند SGML</comment>
- <comment xml:lang="ast">Documentu SGML</comment>
- <comment xml:lang="be@latin">Dakument SGML</comment>
- <comment xml:lang="bg">Документ — SGML</comment>
- <comment xml:lang="ca">document SGML</comment>
- <comment xml:lang="cs">dokument SGML</comment>
- <comment xml:lang="cy">Dogfen SGML</comment>
- <comment xml:lang="da">SGML-dokument</comment>
- <comment xml:lang="de">SGML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο SGML</comment>
- <comment xml:lang="en_GB">SGML document</comment>
- <comment xml:lang="eo">SGML-dokumento</comment>
- <comment xml:lang="es">documento SGML</comment>
- <comment xml:lang="eu">SGML dokumentua</comment>
- <comment xml:lang="fi">SGML-asiakirja</comment>
- <comment xml:lang="fo">SGML skjal</comment>
- <comment xml:lang="fr">document SGML</comment>
- <comment xml:lang="ga">cáipéis SGML</comment>
- <comment xml:lang="gl">documento SGML</comment>
- <comment xml:lang="he">מסמך SGML</comment>
- <comment xml:lang="hr">SGML dokument</comment>
- <comment xml:lang="hu">SGML-dokumentum</comment>
- <comment xml:lang="ia">Documento SGML</comment>
- <comment xml:lang="id">Dokumen SGML</comment>
- <comment xml:lang="it">Documento SGML</comment>
- <comment xml:lang="ja">SGML ドキュメント</comment>
- <comment xml:lang="kk">SGML құжаты</comment>
- <comment xml:lang="ko">SGML 문서</comment>
- <comment xml:lang="lt">SGML dokumentas</comment>
- <comment xml:lang="lv">SGML dokuments</comment>
- <comment xml:lang="ms">Dokumen SGML</comment>
- <comment xml:lang="nb">SGML-dokument</comment>
- <comment xml:lang="nl">SGML-document</comment>
- <comment xml:lang="nn">SGML-dokument</comment>
- <comment xml:lang="oc">document SGML</comment>
- <comment xml:lang="pl">Dokument SGML</comment>
- <comment xml:lang="pt">documento SGML</comment>
- <comment xml:lang="pt_BR">Documento SGML</comment>
- <comment xml:lang="ro">Document SGML</comment>
- <comment xml:lang="ru">Документ SGML</comment>
- <comment xml:lang="sk">Dokument SGML</comment>
- <comment xml:lang="sl">Dokument SGML</comment>
- <comment xml:lang="sq">Dokument SGML</comment>
- <comment xml:lang="sr">СГМЛ документ</comment>
- <comment xml:lang="sv">SGML-dokument</comment>
- <comment xml:lang="tr">SGML belgesi</comment>
- <comment xml:lang="uk">документ SGML</comment>
- <comment xml:lang="vi">Tài liệu SGML</comment>
- <comment xml:lang="zh_CN">SGML 文档</comment>
<comment xml:lang="zh_TW">SGML 文件</comment>
+ <comment xml:lang="zh_CN">SGML 文档</comment>
+ <comment xml:lang="vi">Tài liệu SGML</comment>
+ <comment xml:lang="uk">документ SGML</comment>
+ <comment xml:lang="tr">SGML belgesi</comment>
+ <comment xml:lang="sv">SGML-dokument</comment>
+ <comment xml:lang="sr">СГМЛ документ</comment>
+ <comment xml:lang="sq">dokument SGML</comment>
+ <comment xml:lang="sl">Dokument SGML</comment>
+ <comment xml:lang="si">SGML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument SGML</comment>
+ <comment xml:lang="ru">Документ SGML</comment>
+ <comment xml:lang="ro">Document SGML</comment>
+ <comment xml:lang="pt_BR">Documento SGML</comment>
+ <comment xml:lang="pt">documento SGML</comment>
+ <comment xml:lang="pl">Dokument SGML</comment>
+ <comment xml:lang="oc">document SGML</comment>
+ <comment xml:lang="nn">SGML-dokument</comment>
+ <comment xml:lang="nl">SGML-document</comment>
+ <comment xml:lang="nb">SGML-dokument</comment>
+ <comment xml:lang="ms">Dokumen SGML</comment>
+ <comment xml:lang="lv">SGML dokuments</comment>
+ <comment xml:lang="lt">SGML dokumentas</comment>
+ <comment xml:lang="ko">SGML 문서</comment>
+ <comment xml:lang="kk">SGML құжаты</comment>
+ <comment xml:lang="ja">SGML ドキュメント</comment>
+ <comment xml:lang="it">Documento SGML</comment>
+ <comment xml:lang="is">SGML skjal</comment>
+ <comment xml:lang="id">Dokumen SGML</comment>
+ <comment xml:lang="ia">Documento SGML</comment>
+ <comment xml:lang="hu">SGML-dokumentum</comment>
+ <comment xml:lang="hr">SGML dokument</comment>
+ <comment xml:lang="he">מסמך SGML</comment>
+ <comment xml:lang="gl">documento SGML</comment>
+ <comment xml:lang="ga">cáipéis SGML</comment>
+ <comment xml:lang="fur">document SGML</comment>
+ <comment xml:lang="fr">document SGML</comment>
+ <comment xml:lang="fo">SGML skjal</comment>
+ <comment xml:lang="fi">SGML-asiakirja</comment>
+ <comment xml:lang="eu">SGML dokumentua</comment>
+ <comment xml:lang="es">documento SGML</comment>
+ <comment xml:lang="eo">SGML-dokumento</comment>
+ <comment xml:lang="en_GB">SGML document</comment>
+ <comment xml:lang="el">Έγγραφο SGML</comment>
+ <comment xml:lang="de">SGML-Dokument</comment>
+ <comment xml:lang="da">SGML-dokument</comment>
+ <comment xml:lang="cy">Dogfen SGML</comment>
+ <comment xml:lang="cs">dokument SGML</comment>
+ <comment xml:lang="ca">document SGML</comment>
+ <comment xml:lang="bg">Документ — SGML</comment>
+ <comment xml:lang="be@latin">Dakument SGML</comment>
+ <comment xml:lang="be">дакумент SGML</comment>
+ <comment xml:lang="ast">Documentu SGML</comment>
+ <comment xml:lang="ar">مستند SGML</comment>
+ <comment xml:lang="af">SGML-dokument</comment>
<acronym>SGML</acronym>
<expanded-acronym>Standard Generalized Markup Language</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -32466,110 +34486,76 @@
<glob pattern="*.sgm"/>
</mime-type>
<mime-type type="text/spreadsheet">
- <comment>spreadsheet interchange document</comment>
- <comment xml:lang="ar">مستند تبادل الجدول</comment>
- <comment xml:lang="ast">documentu d'intercambéu de fueyes de cálculu</comment>
- <comment xml:lang="be@latin">dakument dla abmienu raźlikovymi arkušami</comment>
- <comment xml:lang="bg">Документ за обмяна между програми за електронни таблици</comment>
- <comment xml:lang="ca">document d'intercanvi de full de càlcul</comment>
- <comment xml:lang="cs">sešitový výměnný dokument</comment>
- <comment xml:lang="da">regnearksudvekslingsdokument</comment>
- <comment xml:lang="de">Tabellenkalkulations-Austauschdokument</comment>
- <comment xml:lang="el">Έγγραφο ανταλλαγής λογιστικού φύλλου</comment>
- <comment xml:lang="en_GB">spreadsheet interchange document</comment>
- <comment xml:lang="es">documento de intercambio de hojas de cálculo</comment>
- <comment xml:lang="eu">kalkulu-orriak trukatzeko dokumentua</comment>
- <comment xml:lang="fi">taulukkovälitysasiakirja</comment>
- <comment xml:lang="fo">rokniarks umbýtisskjal</comment>
- <comment xml:lang="fr">document d'échange de feuilles de calcul</comment>
- <comment xml:lang="ga">cáipéis idirmhalartaithe scarbhileog</comment>
- <comment xml:lang="gl">documento de intercambio de follas de cálculo</comment>
- <comment xml:lang="he">מסמך גליון נתונים מתחלף</comment>
- <comment xml:lang="hr">Dokument razmjene proračunske tablice</comment>
- <comment xml:lang="hu">spreadsheet-cserélhetődokumentum</comment>
- <comment xml:lang="ia">Documento de intercambio de folio de calculo</comment>
- <comment xml:lang="id">dokumen lembar sebar saling tukar</comment>
- <comment xml:lang="it">Documento di scambio per foglio di calcolo</comment>
- <comment xml:lang="ja">スプレッドシート交換ドキュメント</comment>
- <comment xml:lang="kk">spreadsheet interchange құжаты</comment>
- <comment xml:lang="ko">스프레드시트 교환 문서</comment>
- <comment xml:lang="lt">skaičialenčių apsikeitimo dokumentas</comment>
- <comment xml:lang="lv">izklājlapu apmaiņas dokuments</comment>
- <comment xml:lang="nb">dokument for regnearkutveksling</comment>
- <comment xml:lang="nl">rekenblad-uitwisselingsdocument</comment>
- <comment xml:lang="nn">Utvekslingsdokument for rekneark</comment>
- <comment xml:lang="oc">document d'escambi de fuèlhs de calcul</comment>
- <comment xml:lang="pl">Dokument wymiany arkuszy kalkulacyjnych</comment>
- <comment xml:lang="pt">documento de troca interna de folhas de cálculo</comment>
- <comment xml:lang="pt_BR">Documento de intercâmbio de planilhas</comment>
- <comment xml:lang="ro">document schimb filă de calcul</comment>
- <comment xml:lang="ru">Документ Spreadsheet Interchange</comment>
- <comment xml:lang="sk">Zošitový prenosový dokument</comment>
- <comment xml:lang="sl">dokument izmenjeve preglednic</comment>
- <comment xml:lang="sq">Dokument shkëmbimi për fletë llogaritje</comment>
- <comment xml:lang="sr">документ размене табеле</comment>
- <comment xml:lang="sv">spreadsheet interchange-dokument</comment>
- <comment xml:lang="tr">hesap tablosu değişim belgesi</comment>
+ <comment>Spreadsheet interchange document</comment>
<comment xml:lang="uk">документ обміну ел. таблицями</comment>
- <comment xml:lang="vi">tài liệu hoán đổi bảng tính</comment>
- <comment xml:lang="zh_CN">电子表格交换文档</comment>
- <comment xml:lang="zh_TW">試算表交換文件</comment>
+ <comment xml:lang="sv">Spreadsheet interchange-dokument</comment>
+ <comment xml:lang="ru">Документ Spreadsheet Interchange</comment>
+ <comment xml:lang="pl">Dokument wymiany arkuszy kalkulacyjnych</comment>
+ <comment xml:lang="it">Documento di scambio per foglio di calcolo</comment>
+ <comment xml:lang="es">documento de intercambio de hojas de cálculo</comment>
+ <comment xml:lang="de">Tabellenkalkulations-Austauschdokument</comment>
+ <comment xml:lang="be">дакумент для абмену электроннымі табліцамі</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="ID;" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="ID;" offset="0"/>
</magic>
<glob pattern="*.sylk"/>
<glob pattern="*.slk"/>
</mime-type>
<mime-type type="text/tab-separated-values">
<comment>TSV document</comment>
- <comment xml:lang="ar">مستند TSV</comment>
- <comment xml:lang="ast">Documentu TSV</comment>
- <comment xml:lang="be@latin">Dakument TSV</comment>
- <comment xml:lang="bg">Документ — TSV</comment>
- <comment xml:lang="ca">document TSV</comment>
- <comment xml:lang="cs">dokument TSV</comment>
- <comment xml:lang="da">TSV-dokument</comment>
- <comment xml:lang="de">TSV-Dokument</comment>
- <comment xml:lang="el">Έγγραφο TSV</comment>
- <comment xml:lang="en_GB">TSV document</comment>
- <comment xml:lang="es">documento TSV</comment>
- <comment xml:lang="eu">TSV dokumentua</comment>
- <comment xml:lang="fi">TSV-asiakirja</comment>
- <comment xml:lang="fo">TSV skjal</comment>
- <comment xml:lang="fr">document TSV</comment>
- <comment xml:lang="ga">cáipéis TSV</comment>
- <comment xml:lang="gl">documento TSV</comment>
- <comment xml:lang="he">מסמך TSV</comment>
- <comment xml:lang="hr">TSV dokument</comment>
- <comment xml:lang="hu">TSV dokumentum</comment>
- <comment xml:lang="ia">Documento TSV</comment>
- <comment xml:lang="id">Dokumen TSV</comment>
- <comment xml:lang="it">Documento TSV</comment>
- <comment xml:lang="ja">TSV ドキュメント</comment>
- <comment xml:lang="kk">TSV құжаты</comment>
- <comment xml:lang="ko">TSV 문서</comment>
- <comment xml:lang="lt">TSV dokumentas</comment>
- <comment xml:lang="lv">TSV dokuments</comment>
- <comment xml:lang="nb">TSV-dokument</comment>
- <comment xml:lang="nl">TSV-document</comment>
- <comment xml:lang="nn">TSV-dokument</comment>
- <comment xml:lang="oc">document TSV</comment>
- <comment xml:lang="pl">Dokument TSV</comment>
- <comment xml:lang="pt">documento TSV</comment>
- <comment xml:lang="pt_BR">Documento TSV</comment>
- <comment xml:lang="ro">Document TSV</comment>
- <comment xml:lang="ru">Документ TSV</comment>
- <comment xml:lang="sk">Dokument TSV</comment>
- <comment xml:lang="sl">Dokument TSV</comment>
- <comment xml:lang="sq">Dokument TSV</comment>
- <comment xml:lang="sr">ТСВ документ</comment>
- <comment xml:lang="sv">TSV-dokument</comment>
- <comment xml:lang="tr">TSV belgesi</comment>
- <comment xml:lang="uk">документ TSV</comment>
- <comment xml:lang="vi">Tài liệu TSV</comment>
- <comment xml:lang="zh_CN">TSV 文档</comment>
<comment xml:lang="zh_TW">TSV 文件</comment>
+ <comment xml:lang="zh_CN">TSV 文档</comment>
+ <comment xml:lang="vi">Tài liệu TSV</comment>
+ <comment xml:lang="uk">документ TSV</comment>
+ <comment xml:lang="tr">TSV belgesi</comment>
+ <comment xml:lang="sv">TSV-dokument</comment>
+ <comment xml:lang="sr">ТСВ документ</comment>
+ <comment xml:lang="sq">dokument TSV</comment>
+ <comment xml:lang="sl">Dokument TSV</comment>
+ <comment xml:lang="si">TSV ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument TSV</comment>
+ <comment xml:lang="ru">Документ TSV</comment>
+ <comment xml:lang="ro">Document TSV</comment>
+ <comment xml:lang="pt_BR">Documento TSV</comment>
+ <comment xml:lang="pt">documento TSV</comment>
+ <comment xml:lang="pl">Dokument TSV</comment>
+ <comment xml:lang="oc">document TSV</comment>
+ <comment xml:lang="nn">TSV-dokument</comment>
+ <comment xml:lang="nl">TSV-document</comment>
+ <comment xml:lang="nb">TSV-dokument</comment>
+ <comment xml:lang="lv">TSV dokuments</comment>
+ <comment xml:lang="lt">TSV dokumentas</comment>
+ <comment xml:lang="ko">TSV 문서</comment>
+ <comment xml:lang="kk">TSV құжаты</comment>
+ <comment xml:lang="ja">TSV ドキュメント</comment>
+ <comment xml:lang="it">Documento TSV</comment>
+ <comment xml:lang="is">TSV skjal</comment>
+ <comment xml:lang="id">Dokumen TSV</comment>
+ <comment xml:lang="ia">Documento TSV</comment>
+ <comment xml:lang="hu">TSV dokumentum</comment>
+ <comment xml:lang="hr">TSV dokument</comment>
+ <comment xml:lang="he">מסמך TSV</comment>
+ <comment xml:lang="gl">documento TSV</comment>
+ <comment xml:lang="ga">cáipéis TSV</comment>
+ <comment xml:lang="fur">document TSV</comment>
+ <comment xml:lang="fr">document TSV</comment>
+ <comment xml:lang="fo">TSV skjal</comment>
+ <comment xml:lang="fi">TSV-asiakirja</comment>
+ <comment xml:lang="eu">TSV dokumentua</comment>
+ <comment xml:lang="es">documento TSV</comment>
+ <comment xml:lang="en_GB">TSV document</comment>
+ <comment xml:lang="el">Έγγραφο TSV</comment>
+ <comment xml:lang="de">TSV-Dokument</comment>
+ <comment xml:lang="da">TSV-dokument</comment>
+ <comment xml:lang="cs">dokument TSV</comment>
+ <comment xml:lang="ca">document TSV</comment>
+ <comment xml:lang="bg">Документ — TSV</comment>
+ <comment xml:lang="be@latin">Dakument TSV</comment>
+ <comment xml:lang="be">дакумент TSV</comment>
+ <comment xml:lang="ast">Documentu TSV</comment>
+ <comment xml:lang="ar">مستند TSV</comment>
+ <comment xml:lang="af">TSV-dokument</comment>
<acronym>TSV</acronym>
<expanded-acronym>Tab Separated Values</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -32577,168 +34563,186 @@
</mime-type>
<mime-type type="text/vnd.graphviz">
<comment>Graphviz DOT graph</comment>
- <comment xml:lang="ar">مبيان Graphviz DOT</comment>
- <comment xml:lang="bg">Граф — Graphviz DOT</comment>
- <comment xml:lang="ca">gràfic Graphviz DOT</comment>
- <comment xml:lang="cs">graf Graphviz DOT</comment>
- <comment xml:lang="da">Graphviz DOT-graf</comment>
- <comment xml:lang="de">Graphviz-DOT-Graph</comment>
- <comment xml:lang="el">Γράφημα Graphviz DOT</comment>
- <comment xml:lang="en_GB">Graphviz DOT graph</comment>
- <comment xml:lang="es">gráfico de Graphviz DOT</comment>
- <comment xml:lang="eu">Graphviz DOT grafikoa</comment>
- <comment xml:lang="fi">Graphviz DOT -graafi</comment>
- <comment xml:lang="fo">Graphviz DOT ritmynd</comment>
- <comment xml:lang="fr">graphe Graphviz DOT</comment>
- <comment xml:lang="ga">graf DOT Graphviz</comment>
- <comment xml:lang="gl">gráfica DOT de Graphviz</comment>
- <comment xml:lang="he">תרשים של Graphviz DOT</comment>
- <comment xml:lang="hr">Graphviz DOT grafikon</comment>
- <comment xml:lang="hu">Graphviz DOT-grafikon</comment>
- <comment xml:lang="ia">Graphico DOT de Graphviz</comment>
- <comment xml:lang="id">Grafik Graphviz DOT</comment>
- <comment xml:lang="it">Grafico Graphviz DOT</comment>
- <comment xml:lang="ja">Graphviz DOT グラフ</comment>
- <comment xml:lang="kk">Graphviz DOT сызбасы</comment>
- <comment xml:lang="ko">Graphviz DOT 그래프</comment>
- <comment xml:lang="lt">Graphviz DOT diagrama</comment>
- <comment xml:lang="lv">Graphviz DOT grafiks</comment>
- <comment xml:lang="nl">Graphviz wetenschappelijke grafiek</comment>
- <comment xml:lang="oc">graf Graphviz DOT</comment>
- <comment xml:lang="pl">Wykres DOT Graphviz</comment>
- <comment xml:lang="pt">gráfico Graphviz DOT</comment>
- <comment xml:lang="pt_BR">Gráfico do Graphviz DOT</comment>
- <comment xml:lang="ro">Grafic Graphviz DOT</comment>
- <comment xml:lang="ru">Диаграмма Graphviz DOT</comment>
- <comment xml:lang="sk">Graf Graphviz DOT</comment>
- <comment xml:lang="sl">Datoteka grafikona Graphviz DOT</comment>
- <comment xml:lang="sr">график Графвиз ДОТ-а</comment>
- <comment xml:lang="sv">Graphviz DOT-graf</comment>
- <comment xml:lang="tr">Graphviz DOT grafiği</comment>
- <comment xml:lang="uk">граф DOT Graphviz</comment>
- <comment xml:lang="vi">Biểu đồ DOT Graphviz</comment>
+ <comment xml:lang="zh_TW">Graphviz DOT 圖表</comment>
<comment xml:lang="zh_CN">Graphviz DOT 图形</comment>
- <comment xml:lang="zh_TW">Graphviz DOT 圖</comment>
+ <comment xml:lang="vi">Biểu đồ DOT Graphviz</comment>
+ <comment xml:lang="uk">граф DOT Graphviz</comment>
+ <comment xml:lang="tr">Graphviz DOT grafiği</comment>
+ <comment xml:lang="sv">Graphviz DOT-graf</comment>
+ <comment xml:lang="sr">график Графвиз ДОТ-а</comment>
+ <comment xml:lang="sq">grafik Graphviz DOT</comment>
+ <comment xml:lang="sl">Datoteka grafikona Graphviz DOT</comment>
+ <comment xml:lang="si">Graphviz DOT ප්‍රස්ථාරය</comment>
+ <comment xml:lang="sk">Graf Graphviz DOT</comment>
+ <comment xml:lang="ru">Диаграмма Graphviz DOT</comment>
+ <comment xml:lang="ro">Grafic Graphviz DOT</comment>
+ <comment xml:lang="pt_BR">Gráfico do Graphviz DOT</comment>
+ <comment xml:lang="pt">gráfico Graphviz DOT</comment>
+ <comment xml:lang="pl">Wykres DOT Graphviz</comment>
+ <comment xml:lang="oc">graf Graphviz DOT</comment>
+ <comment xml:lang="nl">Graphviz DOT-grafiek</comment>
+ <comment xml:lang="lv">Graphviz DOT grafiks</comment>
+ <comment xml:lang="lt">Graphviz DOT diagrama</comment>
+ <comment xml:lang="ko">Graphviz DOT 그래프</comment>
+ <comment xml:lang="kk">Graphviz DOT сызбасы</comment>
+ <comment xml:lang="ja">Graphviz DOT グラフ</comment>
+ <comment xml:lang="it">Grafico Graphviz DOT</comment>
+ <comment xml:lang="is">Graphviz DOT punktgraf</comment>
+ <comment xml:lang="id">Grafik Graphviz DOT</comment>
+ <comment xml:lang="ia">Graphico DOT de Graphviz</comment>
+ <comment xml:lang="hu">Graphviz DOT-grafikon</comment>
+ <comment xml:lang="hr">Graphviz DOT grafikon</comment>
+ <comment xml:lang="he">תרשים של Graphviz DOT</comment>
+ <comment xml:lang="gl">gráfica DOT de Graphviz</comment>
+ <comment xml:lang="ga">graf DOT Graphviz</comment>
+ <comment xml:lang="fur">grafic Graphviz DOT</comment>
+ <comment xml:lang="fr">graphe Graphviz DOT</comment>
+ <comment xml:lang="fo">Graphviz DOT ritmynd</comment>
+ <comment xml:lang="fi">Graphviz DOT -graafi</comment>
+ <comment xml:lang="eu">Graphviz DOT grafikoa</comment>
+ <comment xml:lang="es">gráfico de Graphviz DOT</comment>
+ <comment xml:lang="en_GB">Graphviz DOT graph</comment>
+ <comment xml:lang="el">Γράφημα Graphviz DOT</comment>
+ <comment xml:lang="de">Graphviz-DOT-Graph</comment>
+ <comment xml:lang="da">Graphviz DOT-graf</comment>
+ <comment xml:lang="cs">graf Graphviz DOT</comment>
+ <comment xml:lang="ca">gràfic Graphviz DOT</comment>
+ <comment xml:lang="bg">Граф — Graphviz DOT</comment>
+ <comment xml:lang="be">граф Graphviz DOT</comment>
+ <comment xml:lang="ar">مبيان Graphviz DOT</comment>
+ <comment xml:lang="af">Graphviz DOT-grafiek</comment>
+ <sub-class-of type="text/plain"/>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="digraph " type="string" offset="0"/>
- <match value="strict digraph " type="string" offset="0"/>
- <match value="graph " type="string" offset="0"/>
- <match value="strict graph " type="string" offset="0"/>
+ <magic>
+ <match type="string" value="digraph " offset="0"/>
+ <match type="string" value="strict digraph " offset="0"/>
+ <match type="string" value="graph " offset="0"/>
+ <match type="string" value="strict graph " offset="0"/>
</magic>
<glob pattern="*.gv"/>
<glob pattern="*.dot"/>
</mime-type>
<mime-type type="text/vnd.sun.j2me.app-descriptor">
<comment>JAD document</comment>
- <comment xml:lang="ar">مستند JAD</comment>
- <comment xml:lang="ast">Documentu JAD</comment>
- <comment xml:lang="be@latin">Dakument JAD</comment>
- <comment xml:lang="bg">Документ — JAD</comment>
- <comment xml:lang="ca">document JAD</comment>
- <comment xml:lang="cs">dokument JAD</comment>
- <comment xml:lang="da">JAD-dokument</comment>
- <comment xml:lang="de">JAD-Dokument</comment>
- <comment xml:lang="el">Έγγραφο JAD</comment>
- <comment xml:lang="en_GB">JAD document</comment>
- <comment xml:lang="eo">JAD-dokumento</comment>
- <comment xml:lang="es">documento JAD</comment>
- <comment xml:lang="eu">JAD dokumentua</comment>
- <comment xml:lang="fi">JAD-asiakirja</comment>
- <comment xml:lang="fo">JAD skjal</comment>
- <comment xml:lang="fr">document JAD</comment>
- <comment xml:lang="ga">cáipéis JAD</comment>
- <comment xml:lang="gl">documento JAD</comment>
- <comment xml:lang="he">מסמך JAD</comment>
- <comment xml:lang="hr">JAD dokument</comment>
- <comment xml:lang="hu">JAD dokumentum</comment>
- <comment xml:lang="ia">Documento JAD</comment>
- <comment xml:lang="id">Dokumen JAD</comment>
- <comment xml:lang="it">Documento JAD</comment>
- <comment xml:lang="ja">JAD ドキュメント</comment>
- <comment xml:lang="kk">JAD құжаты</comment>
- <comment xml:lang="ko">JAD 문서</comment>
- <comment xml:lang="lt">JAD dokumentas</comment>
- <comment xml:lang="lv">JAD dokuments</comment>
- <comment xml:lang="nb">JAD-dokument</comment>
- <comment xml:lang="nl">JAD-document</comment>
- <comment xml:lang="nn">JAD-dokument</comment>
- <comment xml:lang="oc">document JAD</comment>
- <comment xml:lang="pl">Dokument JAD</comment>
- <comment xml:lang="pt">documento JAD</comment>
- <comment xml:lang="pt_BR">Documento JAD</comment>
- <comment xml:lang="ro">Document JAD</comment>
- <comment xml:lang="ru">Документ JAD</comment>
- <comment xml:lang="sk">Dokument JAD</comment>
- <comment xml:lang="sl">Dokument JAD</comment>
- <comment xml:lang="sq">Dokument JAD</comment>
- <comment xml:lang="sr">ЈАД документ</comment>
- <comment xml:lang="sv">JAD-dokument</comment>
- <comment xml:lang="tr">JAD belgesi</comment>
- <comment xml:lang="uk">документ JAD</comment>
- <comment xml:lang="vi">Tài liệu JAD</comment>
- <comment xml:lang="zh_CN">JAD 文档</comment>
<comment xml:lang="zh_TW">JAD 文件</comment>
+ <comment xml:lang="zh_CN">JAD 文档</comment>
+ <comment xml:lang="vi">Tài liệu JAD</comment>
+ <comment xml:lang="uk">документ JAD</comment>
+ <comment xml:lang="tr">JAD belgesi</comment>
+ <comment xml:lang="sv">JAD-dokument</comment>
+ <comment xml:lang="sr">ЈАД документ</comment>
+ <comment xml:lang="sq">dokument JAD</comment>
+ <comment xml:lang="sl">Dokument JAD</comment>
+ <comment xml:lang="si">JAD ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument JAD</comment>
+ <comment xml:lang="ru">Документ JAD</comment>
+ <comment xml:lang="ro">Document JAD</comment>
+ <comment xml:lang="pt_BR">Documento JAD</comment>
+ <comment xml:lang="pt">documento JAD</comment>
+ <comment xml:lang="pl">Dokument JAD</comment>
+ <comment xml:lang="oc">document JAD</comment>
+ <comment xml:lang="nn">JAD-dokument</comment>
+ <comment xml:lang="nl">JAD-document</comment>
+ <comment xml:lang="nb">JAD-dokument</comment>
+ <comment xml:lang="lv">JAD dokuments</comment>
+ <comment xml:lang="lt">JAD dokumentas</comment>
+ <comment xml:lang="ko">JAD 문서</comment>
+ <comment xml:lang="kk">JAD құжаты</comment>
+ <comment xml:lang="ja">JAD ドキュメント</comment>
+ <comment xml:lang="it">Documento JAD</comment>
+ <comment xml:lang="is">JAD skjal</comment>
+ <comment xml:lang="id">Dokumen JAD</comment>
+ <comment xml:lang="ia">Documento JAD</comment>
+ <comment xml:lang="hu">JAD dokumentum</comment>
+ <comment xml:lang="hr">JAD dokument</comment>
+ <comment xml:lang="he">מסמך JAD</comment>
+ <comment xml:lang="gl">documento JAD</comment>
+ <comment xml:lang="ga">cáipéis JAD</comment>
+ <comment xml:lang="fur">document JAD</comment>
+ <comment xml:lang="fr">document JAD</comment>
+ <comment xml:lang="fo">JAD skjal</comment>
+ <comment xml:lang="fi">JAD-asiakirja</comment>
+ <comment xml:lang="eu">JAD dokumentua</comment>
+ <comment xml:lang="es">documento JAD</comment>
+ <comment xml:lang="eo">JAD-dokumento</comment>
+ <comment xml:lang="en_GB">JAD document</comment>
+ <comment xml:lang="el">Έγγραφο JAD</comment>
+ <comment xml:lang="de">JAD-Dokument</comment>
+ <comment xml:lang="da">JAD-dokument</comment>
+ <comment xml:lang="cs">dokument JAD</comment>
+ <comment xml:lang="ca">document JAD</comment>
+ <comment xml:lang="bg">Документ — JAD</comment>
+ <comment xml:lang="be@latin">Dakument JAD</comment>
+ <comment xml:lang="be">дакумент JAD</comment>
+ <comment xml:lang="ast">Documentu JAD</comment>
+ <comment xml:lang="ar">مستند JAD</comment>
+ <comment xml:lang="af">JAD-dokument</comment>
<acronym>JAD</acronym>
<expanded-acronym>Java Application Descriptor</expanded-acronym>
- <magic priority="50">
- <match value="MIDlet-" type="string" offset="0"/>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="MIDlet-" offset="0"/>
</magic>
<glob pattern="*.jad"/>
</mime-type>
<mime-type type="text/vnd.wap.wml">
<comment>WML document</comment>
- <comment xml:lang="ar">مستند WML</comment>
- <comment xml:lang="ast">Documentu WML</comment>
- <comment xml:lang="az">WML sənədi</comment>
- <comment xml:lang="be@latin">Dakument WML</comment>
- <comment xml:lang="bg">Документ — WML</comment>
- <comment xml:lang="ca">document WML</comment>
- <comment xml:lang="cs">dokument WML</comment>
- <comment xml:lang="cy">Dogfen WML</comment>
- <comment xml:lang="da">WML-dokument</comment>
- <comment xml:lang="de">WML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο WML</comment>
- <comment xml:lang="en_GB">WML document</comment>
- <comment xml:lang="eo">WML-dokumento</comment>
- <comment xml:lang="es">documento WML</comment>
- <comment xml:lang="eu">WML dokumentua</comment>
- <comment xml:lang="fi">WML-asiakirja</comment>
- <comment xml:lang="fo">WML skjal</comment>
- <comment xml:lang="fr">document WML</comment>
- <comment xml:lang="ga">cáipéis WML</comment>
- <comment xml:lang="gl">documento WML</comment>
- <comment xml:lang="he">מסמך WML</comment>
- <comment xml:lang="hr">WML dokument</comment>
- <comment xml:lang="hu">WML-dokumentum</comment>
- <comment xml:lang="ia">Documento WML</comment>
- <comment xml:lang="id">Dokumen WML</comment>
- <comment xml:lang="it">Documento WML</comment>
- <comment xml:lang="ja">WML ドキュメント</comment>
- <comment xml:lang="kk">WML құжаты</comment>
- <comment xml:lang="ko">WML 문서</comment>
- <comment xml:lang="lt">WML dokumentas</comment>
- <comment xml:lang="lv">WML dokuments</comment>
- <comment xml:lang="ms">Dokumen XML</comment>
- <comment xml:lang="nb">WML-dokument</comment>
- <comment xml:lang="nl">WML-document</comment>
- <comment xml:lang="nn">WML-dokument</comment>
- <comment xml:lang="oc">document WML</comment>
- <comment xml:lang="pl">Dokument WML</comment>
- <comment xml:lang="pt">documento WML</comment>
- <comment xml:lang="pt_BR">Documento WML</comment>
- <comment xml:lang="ro">Document WML</comment>
- <comment xml:lang="ru">Документ WML</comment>
- <comment xml:lang="sk">Dokument WML</comment>
- <comment xml:lang="sl">Dokument WML</comment>
- <comment xml:lang="sq">Dokument WML</comment>
- <comment xml:lang="sr">ВМЛ документ</comment>
- <comment xml:lang="sv">WML-dokument</comment>
- <comment xml:lang="tr">WML belgesi</comment>
- <comment xml:lang="uk">документ WML</comment>
- <comment xml:lang="vi">Tài liệu WML</comment>
- <comment xml:lang="zh_CN">WML 文档</comment>
<comment xml:lang="zh_TW">WML 文件</comment>
+ <comment xml:lang="zh_CN">WML 文档</comment>
+ <comment xml:lang="vi">Tài liệu WML</comment>
+ <comment xml:lang="uk">документ WML</comment>
+ <comment xml:lang="tr">WML belgesi</comment>
+ <comment xml:lang="sv">WML-dokument</comment>
+ <comment xml:lang="sr">ВМЛ документ</comment>
+ <comment xml:lang="sq">dokument WML</comment>
+ <comment xml:lang="sl">Dokument WML</comment>
+ <comment xml:lang="si">WML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument WML</comment>
+ <comment xml:lang="ru">Документ WML</comment>
+ <comment xml:lang="ro">Document WML</comment>
+ <comment xml:lang="pt_BR">Documento WML</comment>
+ <comment xml:lang="pt">documento WML</comment>
+ <comment xml:lang="pl">Dokument WML</comment>
+ <comment xml:lang="oc">document WML</comment>
+ <comment xml:lang="nn">WML-dokument</comment>
+ <comment xml:lang="nl">WML-document</comment>
+ <comment xml:lang="nb">WML-dokument</comment>
+ <comment xml:lang="ms">Dokumen XML</comment>
+ <comment xml:lang="lv">WML dokuments</comment>
+ <comment xml:lang="lt">WML dokumentas</comment>
+ <comment xml:lang="ko">WML 문서</comment>
+ <comment xml:lang="kk">WML құжаты</comment>
+ <comment xml:lang="ja">WML ドキュメント</comment>
+ <comment xml:lang="it">Documento WML</comment>
+ <comment xml:lang="is">WML skjal</comment>
+ <comment xml:lang="id">Dokumen WML</comment>
+ <comment xml:lang="ia">Documento WML</comment>
+ <comment xml:lang="hu">WML-dokumentum</comment>
+ <comment xml:lang="hr">WML dokument</comment>
+ <comment xml:lang="he">מסמך WML</comment>
+ <comment xml:lang="gl">documento WML</comment>
+ <comment xml:lang="ga">cáipéis WML</comment>
+ <comment xml:lang="fur">document WML</comment>
+ <comment xml:lang="fr">document WML</comment>
+ <comment xml:lang="fo">WML skjal</comment>
+ <comment xml:lang="fi">WML-asiakirja</comment>
+ <comment xml:lang="eu">WML dokumentua</comment>
+ <comment xml:lang="es">documento WML</comment>
+ <comment xml:lang="eo">WML-dokumento</comment>
+ <comment xml:lang="en_GB">WML document</comment>
+ <comment xml:lang="el">Έγγραφο WML</comment>
+ <comment xml:lang="de">WML-Dokument</comment>
+ <comment xml:lang="da">WML-dokument</comment>
+ <comment xml:lang="cy">Dogfen WML</comment>
+ <comment xml:lang="cs">dokument WML</comment>
+ <comment xml:lang="ca">document WML</comment>
+ <comment xml:lang="bg">Документ — WML</comment>
+ <comment xml:lang="be@latin">Dakument WML</comment>
+ <comment xml:lang="be">дакумент WML</comment>
+ <comment xml:lang="az">WML sənədi</comment>
+ <comment xml:lang="ast">Documentu WML</comment>
+ <comment xml:lang="ar">مستند WML</comment>
+ <comment xml:lang="af">WML-dokument</comment>
<acronym>WML</acronym>
<expanded-acronym>Wireless Markup Language</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -32746,324 +34750,364 @@
</mime-type>
<mime-type type="text/vnd.wap.wmlscript">
<comment>WMLScript program</comment>
- <comment xml:lang="ar">برنامج WMLScript</comment>
- <comment xml:lang="be@latin">Prahrama WMLScript</comment>
- <comment xml:lang="bg">Програма — WMLScript</comment>
- <comment xml:lang="ca">programa WMLScript</comment>
- <comment xml:lang="cs">program WMLScript</comment>
- <comment xml:lang="da">WMLScript-program</comment>
- <comment xml:lang="de">WMLScript-Programm</comment>
- <comment xml:lang="el">Πρόγραμμα WMLScript</comment>
- <comment xml:lang="en_GB">WMLScript program</comment>
- <comment xml:lang="es">programa en WMLScript</comment>
- <comment xml:lang="eu">WMLScript programa</comment>
- <comment xml:lang="fi">WMLScript-ohjelma</comment>
- <comment xml:lang="fo">WMLScript forrit</comment>
- <comment xml:lang="fr">programme WMLScript</comment>
- <comment xml:lang="ga">ríomhchlár WMLScript</comment>
- <comment xml:lang="gl">programa en WMLScript</comment>
- <comment xml:lang="he">תכנית של WMLScript</comment>
- <comment xml:lang="hr">WMLScript program</comment>
- <comment xml:lang="hu">WMLScript program</comment>
- <comment xml:lang="ia">Programma WMLScript</comment>
- <comment xml:lang="id">Program WMLScript</comment>
- <comment xml:lang="it">Programma WMLScript</comment>
- <comment xml:lang="ja">WMLScript プログラム</comment>
- <comment xml:lang="kk">WMLScript бағдарламасы</comment>
- <comment xml:lang="ko">WMLScript 프로그램</comment>
- <comment xml:lang="lt">WMLScript programa</comment>
- <comment xml:lang="lv">WMLScript programma</comment>
- <comment xml:lang="nb">WMLScript-program</comment>
- <comment xml:lang="nl">WMLScript-programma</comment>
- <comment xml:lang="nn">WMLScript-program</comment>
- <comment xml:lang="oc">programa WMLEscript</comment>
- <comment xml:lang="pl">Pogram WMLScript</comment>
- <comment xml:lang="pt">programa WMLScript</comment>
- <comment xml:lang="pt_BR">Programa WMLScript</comment>
- <comment xml:lang="ro">Program WMLScript</comment>
- <comment xml:lang="ru">Программа WMLScript</comment>
- <comment xml:lang="sk">Program WMLScript</comment>
- <comment xml:lang="sl">Programska datoteka WMLScript</comment>
- <comment xml:lang="sq">Program WMLScript</comment>
- <comment xml:lang="sr">програм ВМЛ скрипте</comment>
- <comment xml:lang="sv">WMLScript-program</comment>
- <comment xml:lang="tr">WMLScript programı</comment>
- <comment xml:lang="uk">програма мовою WMLScript</comment>
- <comment xml:lang="vi">Chương trình WMLScript</comment>
- <comment xml:lang="zh_CN">WMLScript 程序</comment>
<comment xml:lang="zh_TW">WMLScript 程式</comment>
+ <comment xml:lang="zh_CN">WMLScript 程序</comment>
+ <comment xml:lang="vi">Chương trình WMLScript</comment>
+ <comment xml:lang="uk">програма мовою WMLScript</comment>
+ <comment xml:lang="tr">WMLScript programı</comment>
+ <comment xml:lang="sv">WMLScript-program</comment>
+ <comment xml:lang="sr">програм ВМЛ скрипте</comment>
+ <comment xml:lang="sq">program WMLScript</comment>
+ <comment xml:lang="sl">Programska datoteka WMLScript</comment>
+ <comment xml:lang="si">WMLScript වැඩසටහන</comment>
+ <comment xml:lang="sk">Program WMLScript</comment>
+ <comment xml:lang="ru">Программа WMLScript</comment>
+ <comment xml:lang="ro">Program WMLScript</comment>
+ <comment xml:lang="pt_BR">Programa WMLScript</comment>
+ <comment xml:lang="pt">programa WMLScript</comment>
+ <comment xml:lang="pl">Pogram WMLScript</comment>
+ <comment xml:lang="oc">programa WMLEscript</comment>
+ <comment xml:lang="nn">WMLScript-program</comment>
+ <comment xml:lang="nl">WMLScript-toepassing</comment>
+ <comment xml:lang="nb">WMLScript-program</comment>
+ <comment xml:lang="lv">WMLScript programma</comment>
+ <comment xml:lang="lt">WMLScript programa</comment>
+ <comment xml:lang="ko">WMLScript 프로그램</comment>
+ <comment xml:lang="kk">WMLScript бағдарламасы</comment>
+ <comment xml:lang="ja">WMLScript プログラム</comment>
+ <comment xml:lang="it">Programma WMLScript</comment>
+ <comment xml:lang="is">WMLScript forrit</comment>
+ <comment xml:lang="id">Program WMLScript</comment>
+ <comment xml:lang="ia">Programma WMLScript</comment>
+ <comment xml:lang="hu">WMLScript program</comment>
+ <comment xml:lang="hr">WMLScript program</comment>
+ <comment xml:lang="he">תכנית של WMLScript</comment>
+ <comment xml:lang="gl">programa en WMLScript</comment>
+ <comment xml:lang="ga">ríomhchlár WMLScript</comment>
+ <comment xml:lang="fur">program WMLScript</comment>
+ <comment xml:lang="fr">programme WMLScript</comment>
+ <comment xml:lang="fo">WMLScript forrit</comment>
+ <comment xml:lang="fi">WMLScript-ohjelma</comment>
+ <comment xml:lang="eu">WMLScript programa</comment>
+ <comment xml:lang="es">programa en WMLScript</comment>
+ <comment xml:lang="en_GB">WMLScript program</comment>
+ <comment xml:lang="el">Πρόγραμμα WMLScript</comment>
+ <comment xml:lang="de">WMLScript-Programm</comment>
+ <comment xml:lang="da">WMLScript-program</comment>
+ <comment xml:lang="cs">program WMLScript</comment>
+ <comment xml:lang="ca">programa WMLScript</comment>
+ <comment xml:lang="bg">Програма — WMLScript</comment>
+ <comment xml:lang="be@latin">Prahrama WMLScript</comment>
+ <comment xml:lang="be">праграма WMLScript</comment>
+ <comment xml:lang="ar">برنامج WMLScript</comment>
+ <comment xml:lang="af">WMLScript-program</comment>
+ <sub-class-of type="text/plain"/>
<glob pattern="*.wmls"/>
</mime-type>
+ <mime-type type="text/vnd.senx.warpscript">
+ <comment>WarpScript source code</comment>
+ <comment xml:lang="zh_TW">WarpScript 原始碼</comment>
+ <comment xml:lang="zh_CN">WarpScript 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою WarpScript</comment>
+ <comment xml:lang="tr">WarpScript kaynak kodu</comment>
+ <comment xml:lang="sv">WarpScript-källkod</comment>
+ <comment xml:lang="sq">kod burim WarpScript</comment>
+ <comment xml:lang="sl">Izvorna koda WarpScript</comment>
+ <comment xml:lang="si">WarpScript මූලාශ්‍ර කේතය</comment>
+ <comment xml:lang="ru">Исходный код WarpScript</comment>
+ <comment xml:lang="pt_BR">Código-fonte WarpScript</comment>
+ <comment xml:lang="pl">Kod źródłowy WarpScript</comment>
+ <comment xml:lang="nl">WarpScript-broncode</comment>
+ <comment xml:lang="ko">WarpScript 소스 코드</comment>
+ <comment xml:lang="kk">WarpScript бастапқы коды</comment>
+ <comment xml:lang="ja">WarpScript ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente WarpScript</comment>
+ <comment xml:lang="is">WarpScript frumkóði</comment>
+ <comment xml:lang="id">Kode sumber WarpScript</comment>
+ <comment xml:lang="hu">WarpScript forráskód</comment>
+ <comment xml:lang="hr">WarpScript izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור ב־WarpScript</comment>
+ <comment xml:lang="gl">Código fonte en WarpScript</comment>
+ <comment xml:lang="fur">codiç sorzint WarpScript</comment>
+ <comment xml:lang="fr">code source WarpScript</comment>
+ <comment xml:lang="fi">WarpScript-lähdekoodi</comment>
+ <comment xml:lang="eu">WarpScript iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en WarpScript</comment>
+ <comment xml:lang="en_GB">WarpScript source code</comment>
+ <comment xml:lang="de">WarpScript-Quelltext</comment>
+ <comment xml:lang="da">WarpScript-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce WarpScript</comment>
+ <comment xml:lang="ca">codi font en WarpScript</comment>
+ <comment xml:lang="bg">Изходен код — WarpScript</comment>
+ <comment xml:lang="be">зыходны код WarpScript</comment>
+ <comment xml:lang="ar">شفرة مصدر WarpScript</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.mc2"/>
+ </mime-type>
<mime-type type="application/x-ace">
<comment>ACE archive</comment>
- <comment xml:lang="ar">أرشيف ACE</comment>
- <comment xml:lang="be@latin">Archiŭ ACE</comment>
- <comment xml:lang="bg">Архив — ACE</comment>
- <comment xml:lang="ca">arxiu ACE</comment>
- <comment xml:lang="cs">archiv ACE</comment>
- <comment xml:lang="da">ACE-arkiv</comment>
- <comment xml:lang="de">ACE-Archiv</comment>
- <comment xml:lang="el">Συμπιεσμένο αρχείο ACE</comment>
- <comment xml:lang="en_GB">ACE archive</comment>
- <comment xml:lang="eo">ACE-arkivo</comment>
- <comment xml:lang="es">archivador ACE</comment>
- <comment xml:lang="eu">ACE artxiboa</comment>
- <comment xml:lang="fi">ACE-arkisto</comment>
- <comment xml:lang="fo">ACE skjalasavn</comment>
- <comment xml:lang="fr">archive ACE</comment>
- <comment xml:lang="ga">cartlann ACE</comment>
- <comment xml:lang="gl">arquivo ACE</comment>
- <comment xml:lang="he">ארכיון ACE</comment>
- <comment xml:lang="hr">ACE arhiva</comment>
- <comment xml:lang="hu">ACE archívum</comment>
- <comment xml:lang="ia">Archivo ACE</comment>
- <comment xml:lang="id">Arsip ACE</comment>
- <comment xml:lang="it">Archivio ACE</comment>
- <comment xml:lang="ja">ACE アーカイブ</comment>
- <comment xml:lang="ka">ACE არქივი</comment>
- <comment xml:lang="kk">ACE архиві</comment>
- <comment xml:lang="ko">ACE 압축 파일</comment>
- <comment xml:lang="lt">ACE archyvas</comment>
- <comment xml:lang="lv">ACE arhīvs</comment>
- <comment xml:lang="nb">ACE-arkiv</comment>
- <comment xml:lang="nl">ACE-archief</comment>
- <comment xml:lang="nn">ACE-arkiv</comment>
- <comment xml:lang="oc">archiu ACE</comment>
- <comment xml:lang="pl">Archiwum ACE</comment>
- <comment xml:lang="pt">arquivo ACE</comment>
- <comment xml:lang="pt_BR">Pacote ACE</comment>
- <comment xml:lang="ro">Arhivă ACE</comment>
- <comment xml:lang="ru">Архив ACE</comment>
- <comment xml:lang="sk">Archív ACE</comment>
- <comment xml:lang="sl">Datoteka arhiva ACE</comment>
- <comment xml:lang="sq">Arkiv ACE</comment>
- <comment xml:lang="sr">АЦЕ архива</comment>
- <comment xml:lang="sv">ACE-arkiv</comment>
- <comment xml:lang="tr">ACE arşivi</comment>
- <comment xml:lang="uk">архів ACE</comment>
- <comment xml:lang="vi">Kho nén ACE</comment>
- <comment xml:lang="zh_CN">ACE 归档文件</comment>
<comment xml:lang="zh_TW">ACE 封存檔</comment>
+ <comment xml:lang="zh_CN">ACE 归档文件</comment>
+ <comment xml:lang="vi">Kho nén ACE</comment>
+ <comment xml:lang="uk">архів ACE</comment>
+ <comment xml:lang="tr">ACE arşivi</comment>
+ <comment xml:lang="sv">ACE-arkiv</comment>
+ <comment xml:lang="sr">АЦЕ архива</comment>
+ <comment xml:lang="sq">arkiv ACE</comment>
+ <comment xml:lang="sl">Datoteka arhiva ACE</comment>
+ <comment xml:lang="si">ACE ලේඛනාගාරය</comment>
+ <comment xml:lang="sk">Archív ACE</comment>
+ <comment xml:lang="ru">Архив ACE</comment>
+ <comment xml:lang="ro">Arhivă ACE</comment>
+ <comment xml:lang="pt_BR">Pacote ACE</comment>
+ <comment xml:lang="pt">arquivo ACE</comment>
+ <comment xml:lang="pl">Archiwum ACE</comment>
+ <comment xml:lang="oc">archiu ACE</comment>
+ <comment xml:lang="nn">ACE-arkiv</comment>
+ <comment xml:lang="nl">ACE-archief</comment>
+ <comment xml:lang="nb">ACE-arkiv</comment>
+ <comment xml:lang="lv">ACE arhīvs</comment>
+ <comment xml:lang="lt">ACE archyvas</comment>
+ <comment xml:lang="ko">ACE 압축 파일</comment>
+ <comment xml:lang="kk">ACE архиві</comment>
+ <comment xml:lang="ka">ACE არქივი</comment>
+ <comment xml:lang="ja">ACE アーカイブ</comment>
+ <comment xml:lang="it">Archivio ACE</comment>
+ <comment xml:lang="is">ACE safnskrá</comment>
+ <comment xml:lang="id">Arsip ACE</comment>
+ <comment xml:lang="ia">Archivo ACE</comment>
+ <comment xml:lang="hu">ACE archívum</comment>
+ <comment xml:lang="hr">ACE arhiva</comment>
+ <comment xml:lang="he">ארכיון ACE</comment>
+ <comment xml:lang="gl">arquivo ACE</comment>
+ <comment xml:lang="ga">cartlann ACE</comment>
+ <comment xml:lang="fur">archivi ACE</comment>
+ <comment xml:lang="fr">archive ACE</comment>
+ <comment xml:lang="fo">ACE skjalasavn</comment>
+ <comment xml:lang="fi">ACE-arkisto</comment>
+ <comment xml:lang="eu">ACE artxiboa</comment>
+ <comment xml:lang="es">archivador ACE</comment>
+ <comment xml:lang="eo">ACE-arkivo</comment>
+ <comment xml:lang="en_GB">ACE archive</comment>
+ <comment xml:lang="el">Συμπιεσμένο αρχείο ACE</comment>
+ <comment xml:lang="de">ACE-Archiv</comment>
+ <comment xml:lang="da">ACE-arkiv</comment>
+ <comment xml:lang="cs">archiv ACE</comment>
+ <comment xml:lang="ca">arxiu ACE</comment>
+ <comment xml:lang="bg">Архив — ACE</comment>
+ <comment xml:lang="be@latin">Archiŭ ACE</comment>
+ <comment xml:lang="be">архіў ACE</comment>
+ <comment xml:lang="ar">أرشيف ACE</comment>
+ <comment xml:lang="af">ACE-argief</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
- <match value="**ACE**" type="string" offset="7"/>
+ <match type="string" value="**ACE**" offset="7"/>
</magic>
<glob pattern="*.ace"/>
</mime-type>
<mime-type type="text/x-adasrc">
<comment>Ada source code</comment>
- <comment xml:lang="ar">شفرة مصدر Ada</comment>
- <comment xml:lang="be@latin">Kryničny kod Ada</comment>
- <comment xml:lang="bg">Изходен код — Ada</comment>
- <comment xml:lang="ca">codi font en Ada</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Ada</comment>
- <comment xml:lang="da">Ada-kildekode</comment>
- <comment xml:lang="de">Ada-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Ada</comment>
- <comment xml:lang="en_GB">Ada source code</comment>
- <comment xml:lang="eo">Ada-fontkodo</comment>
- <comment xml:lang="es">código fuente en Ada</comment>
- <comment xml:lang="eu">Ada iturburu-kodea</comment>
- <comment xml:lang="fi">Ada-lähdekoodi</comment>
- <comment xml:lang="fo">Ada keldukota</comment>
- <comment xml:lang="fr">code source Ada</comment>
- <comment xml:lang="ga">cód foinseach Ada</comment>
- <comment xml:lang="gl">código fonte en Ada</comment>
- <comment xml:lang="he">קוד מקור Ada</comment>
- <comment xml:lang="hr">Ada izvorni kôd</comment>
- <comment xml:lang="hu">Ada-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Ada</comment>
- <comment xml:lang="id">Kode sumber Ada</comment>
- <comment xml:lang="it">Codice sorgente Ada</comment>
- <comment xml:lang="ja">Ada ソースコード</comment>
- <comment xml:lang="ka">Ada-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Ada бастапқы коды</comment>
- <comment xml:lang="ko">Ada 소스 코드</comment>
- <comment xml:lang="lt">Ada pradinis kodas</comment>
- <comment xml:lang="lv">Ada pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Ada</comment>
- <comment xml:lang="nb">Ada-kildekode</comment>
- <comment xml:lang="nl">Ada-broncode</comment>
- <comment xml:lang="nn">Ada-kjeldekode</comment>
- <comment xml:lang="oc">còde font Ada</comment>
- <comment xml:lang="pl">Kod źródłowy Ada</comment>
- <comment xml:lang="pt">código origem Ada</comment>
- <comment xml:lang="pt_BR">Código-fonte Ada</comment>
- <comment xml:lang="ro">Cod sursă Ada</comment>
- <comment xml:lang="ru">Исходный код Ada</comment>
- <comment xml:lang="sk">Zdrojový kód jazyka Ada</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Ada</comment>
- <comment xml:lang="sq">Kod burues Ada</comment>
- <comment xml:lang="sr">Ада изворни ко̂д</comment>
- <comment xml:lang="sv">Ada-källkod</comment>
- <comment xml:lang="tr">Ada kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Ada</comment>
- <comment xml:lang="vi">Mã nguồn Ada</comment>
- <comment xml:lang="zh_CN">Ada 源代码</comment>
<comment xml:lang="zh_TW">Ada 源碼</comment>
+ <comment xml:lang="zh_CN">Ada 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Ada</comment>
+ <comment xml:lang="uk">початковий код мовою Ada</comment>
+ <comment xml:lang="tr">Ada kaynak kodu</comment>
+ <comment xml:lang="sv">Ada-källkod</comment>
+ <comment xml:lang="sr">Ада изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Ada</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Ada</comment>
+ <comment xml:lang="si">Ada මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód jazyka Ada</comment>
+ <comment xml:lang="ru">Исходный код Ada</comment>
+ <comment xml:lang="ro">Cod sursă Ada</comment>
+ <comment xml:lang="pt_BR">Código-fonte Ada</comment>
+ <comment xml:lang="pt">código origem Ada</comment>
+ <comment xml:lang="pl">Kod źródłowy Ada</comment>
+ <comment xml:lang="oc">còde font Ada</comment>
+ <comment xml:lang="nn">Ada-kjeldekode</comment>
+ <comment xml:lang="nl">Ada-broncode</comment>
+ <comment xml:lang="nb">Ada-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Ada</comment>
+ <comment xml:lang="lv">Ada pirmkods</comment>
+ <comment xml:lang="lt">Ada pradinis kodas</comment>
+ <comment xml:lang="ko">Ada 소스 코드</comment>
+ <comment xml:lang="kk">Ada бастапқы коды</comment>
+ <comment xml:lang="ka">Ada-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Ada ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Ada</comment>
+ <comment xml:lang="is">Ada frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Ada</comment>
+ <comment xml:lang="ia">Codice-fonte Ada</comment>
+ <comment xml:lang="hu">Ada-forráskód</comment>
+ <comment xml:lang="hr">Ada izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור Ada</comment>
+ <comment xml:lang="gl">código fonte en Ada</comment>
+ <comment xml:lang="ga">cód foinseach Ada</comment>
+ <comment xml:lang="fur">codiç sorzint Ada</comment>
+ <comment xml:lang="fr">code source Ada</comment>
+ <comment xml:lang="fo">Ada keldukota</comment>
+ <comment xml:lang="fi">Ada-lähdekoodi</comment>
+ <comment xml:lang="eu">Ada iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Ada</comment>
+ <comment xml:lang="eo">Ada-fontkodo</comment>
+ <comment xml:lang="en_GB">Ada source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Ada</comment>
+ <comment xml:lang="de">Ada-Quelltext</comment>
+ <comment xml:lang="da">Ada-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Ada</comment>
+ <comment xml:lang="ca">codi font en Ada</comment>
+ <comment xml:lang="bg">Изходен код — Ada</comment>
+ <comment xml:lang="be@latin">Kryničny kod Ada</comment>
+ <comment xml:lang="be">зыходны код Ada</comment>
+ <comment xml:lang="ar">شفرة مصدر Ada</comment>
+ <comment xml:lang="af">Ada-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.adb"/>
<glob pattern="*.ads"/>
</mime-type>
<mime-type type="text/x-authors">
- <comment>author list</comment>
- <comment xml:lang="ar">لائحة المؤلف</comment>
- <comment xml:lang="be@latin">śpis aŭtaraŭ</comment>
- <comment xml:lang="bg">Списък на авторите</comment>
- <comment xml:lang="ca">llista d'autors</comment>
- <comment xml:lang="cs">seznam autorů</comment>
- <comment xml:lang="da">forfatterliste</comment>
- <comment xml:lang="de">Autorenliste</comment>
- <comment xml:lang="el">Κατάλογος συγγραφέων</comment>
- <comment xml:lang="en_GB">author list</comment>
- <comment xml:lang="eo">listo de aŭtoroj</comment>
- <comment xml:lang="es">lista de autores</comment>
- <comment xml:lang="eu">egile-zerrenda</comment>
- <comment xml:lang="fi">tekijäluettelo</comment>
- <comment xml:lang="fo">høvundalisti</comment>
- <comment xml:lang="fr">liste d'auteurs</comment>
- <comment xml:lang="ga">liosta údar</comment>
- <comment xml:lang="gl">lista de autores</comment>
- <comment xml:lang="he">רשימת יוצרים</comment>
- <comment xml:lang="hr">Popis autora</comment>
- <comment xml:lang="hu">szerzőlista</comment>
- <comment xml:lang="ia">Lista de autores</comment>
- <comment xml:lang="id">senarai penulis</comment>
- <comment xml:lang="it">Elenco autori</comment>
- <comment xml:lang="ja">著者リスト</comment>
- <comment xml:lang="kk">авторлар тізімі</comment>
- <comment xml:lang="ko">저자 목록</comment>
- <comment xml:lang="lt">autorių sąrašas</comment>
- <comment xml:lang="lv">autoru saraksts</comment>
- <comment xml:lang="ms">Senarai penulis</comment>
- <comment xml:lang="nb">forfatterliste</comment>
- <comment xml:lang="nl">auteurslijst</comment>
- <comment xml:lang="nn">forfattarliste</comment>
- <comment xml:lang="oc">lista d'autors</comment>
- <comment xml:lang="pl">Lista autorów</comment>
- <comment xml:lang="pt">lista de autores</comment>
- <comment xml:lang="pt_BR">Lista de autores</comment>
- <comment xml:lang="ro">listă autori</comment>
+ <comment>Author list</comment>
+ <comment xml:lang="uk">список авторів</comment>
+ <comment xml:lang="sv">Författarlista</comment>
<comment xml:lang="ru">Список авторов</comment>
- <comment xml:lang="sk">Zoznam autorov</comment>
- <comment xml:lang="sl">seznam avtorjev</comment>
- <comment xml:lang="sq">Lista e autorëve</comment>
- <comment xml:lang="sr">списак аутора</comment>
- <comment xml:lang="sv">författarlista</comment>
- <comment xml:lang="tr">yazar listesi</comment>
- <comment xml:lang="uk">перелік авторів</comment>
- <comment xml:lang="vi">danh sách tác giả</comment>
- <comment xml:lang="zh_CN">作者列表</comment>
- <comment xml:lang="zh_TW">作者清單</comment>
+ <comment xml:lang="pl">Lista autorów</comment>
+ <comment xml:lang="it">Elenco autori</comment>
+ <comment xml:lang="eu">Egile-zerrenda</comment>
+ <comment xml:lang="es">lista de autores</comment>
+ <comment xml:lang="de">Autorenliste</comment>
+ <comment xml:lang="be">спіс аўтараў</comment>
<sub-class-of type="text/plain"/>
<glob pattern="AUTHORS"/>
</mime-type>
<mime-type type="text/x-bibtex">
<comment>BibTeX document</comment>
- <comment xml:lang="ar">مستند BibTeX</comment>
- <comment xml:lang="ast">Documentu de BibTeX</comment>
- <comment xml:lang="be@latin">Dakument BibTeX</comment>
- <comment xml:lang="bg">Документ — BibTeX</comment>
- <comment xml:lang="ca">document BibTeX</comment>
- <comment xml:lang="cs">dokument BibTeX</comment>
- <comment xml:lang="da">BibTeX-dokument</comment>
- <comment xml:lang="de">BibTeX-Dokument</comment>
- <comment xml:lang="el">Έγγραφο BibTeX</comment>
- <comment xml:lang="en_GB">BibTeX document</comment>
- <comment xml:lang="eo">BibTeX-dokumento</comment>
- <comment xml:lang="es">documento BibTeX</comment>
- <comment xml:lang="eu">BibTeX dokumentua</comment>
- <comment xml:lang="fi">BibTeX-asiakirja</comment>
- <comment xml:lang="fo">BibTeX skjal</comment>
- <comment xml:lang="fr">document BibTeX</comment>
- <comment xml:lang="ga">cáipéis BibTeX</comment>
- <comment xml:lang="gl">documento BibTex</comment>
- <comment xml:lang="he">מסמך BibTeX</comment>
- <comment xml:lang="hr">BibTeX dokument</comment>
- <comment xml:lang="hu">BibTeX dokumentum</comment>
- <comment xml:lang="ia">Documento BibTeX</comment>
- <comment xml:lang="id">Dokumen BibTeX</comment>
- <comment xml:lang="it">Documento BibTeX</comment>
- <comment xml:lang="ja">BibTeX ドキュメント</comment>
- <comment xml:lang="ka">BibTeX-ის დოკუმენტი</comment>
- <comment xml:lang="kk">BibTeX құжаты</comment>
- <comment xml:lang="ko">BibTeX 문서</comment>
- <comment xml:lang="lt">BibTeX dokumentas</comment>
- <comment xml:lang="lv">BibTeX dokuments</comment>
- <comment xml:lang="nb">BibTeX-dokument</comment>
- <comment xml:lang="nl">BibTeX-document</comment>
- <comment xml:lang="nn">BibTeX-dokument</comment>
- <comment xml:lang="oc">document BibTeX</comment>
- <comment xml:lang="pl">Dokument BibTeX</comment>
- <comment xml:lang="pt">documento BibTeX</comment>
- <comment xml:lang="pt_BR">Documento BibTeX</comment>
- <comment xml:lang="ro">Document BibTeX</comment>
- <comment xml:lang="ru">Документ BibTeX</comment>
- <comment xml:lang="sk">Dokument BibTeX</comment>
- <comment xml:lang="sl">Dokument BibTeX</comment>
- <comment xml:lang="sq">Dokument BibTeX</comment>
- <comment xml:lang="sr">Биб ТеКс документ</comment>
- <comment xml:lang="sv">BibTeX-dokument</comment>
- <comment xml:lang="tr">BibTeX belgesi</comment>
- <comment xml:lang="uk">документ BibTeX</comment>
- <comment xml:lang="vi">Tài liệu BibTeX</comment>
- <comment xml:lang="zh_CN">BibTeX 文档</comment>
<comment xml:lang="zh_TW">BibTeX 文件</comment>
+ <comment xml:lang="zh_CN">BibTeX 文档</comment>
+ <comment xml:lang="vi">Tài liệu BibTeX</comment>
+ <comment xml:lang="uk">документ BibTeX</comment>
+ <comment xml:lang="tr">BibTeX belgesi</comment>
+ <comment xml:lang="sv">BibTeX-dokument</comment>
+ <comment xml:lang="sr">Биб ТеКс документ</comment>
+ <comment xml:lang="sq">dokument BibTeX</comment>
+ <comment xml:lang="sl">Dokument BibTeX</comment>
+ <comment xml:lang="si">BibTeX ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument BibTeX</comment>
+ <comment xml:lang="ru">Документ BibTeX</comment>
+ <comment xml:lang="ro">Document BibTeX</comment>
+ <comment xml:lang="pt_BR">Documento BibTeX</comment>
+ <comment xml:lang="pt">documento BibTeX</comment>
+ <comment xml:lang="pl">Dokument BibTeX</comment>
+ <comment xml:lang="oc">document BibTeX</comment>
+ <comment xml:lang="nn">BibTeX-dokument</comment>
+ <comment xml:lang="nl">BibTeX-document</comment>
+ <comment xml:lang="nb">BibTeX-dokument</comment>
+ <comment xml:lang="lv">BibTeX dokuments</comment>
+ <comment xml:lang="lt">BibTeX dokumentas</comment>
+ <comment xml:lang="ko">BibTeX 문서</comment>
+ <comment xml:lang="kk">BibTeX құжаты</comment>
+ <comment xml:lang="ka">BibTeX-ის დოკუმენტი</comment>
+ <comment xml:lang="ja">BibTeX ドキュメント</comment>
+ <comment xml:lang="it">Documento BibTeX</comment>
+ <comment xml:lang="is">BibTeX skjal</comment>
+ <comment xml:lang="id">Dokumen BibTeX</comment>
+ <comment xml:lang="ia">Documento BibTeX</comment>
+ <comment xml:lang="hu">BibTeX dokumentum</comment>
+ <comment xml:lang="hr">BibTeX dokument</comment>
+ <comment xml:lang="he">מסמך BibTeX</comment>
+ <comment xml:lang="gl">documento BibTex</comment>
+ <comment xml:lang="ga">cáipéis BibTeX</comment>
+ <comment xml:lang="fur">document BibTeX</comment>
+ <comment xml:lang="fr">document BibTeX</comment>
+ <comment xml:lang="fo">BibTeX skjal</comment>
+ <comment xml:lang="fi">BibTeX-asiakirja</comment>
+ <comment xml:lang="eu">BibTeX dokumentua</comment>
+ <comment xml:lang="es">documento BibTeX</comment>
+ <comment xml:lang="eo">BibTeX-dokumento</comment>
+ <comment xml:lang="en_GB">BibTeX document</comment>
+ <comment xml:lang="el">Έγγραφο BibTeX</comment>
+ <comment xml:lang="de">BibTeX-Dokument</comment>
+ <comment xml:lang="da">BibTeX-dokument</comment>
+ <comment xml:lang="cs">dokument BibTeX</comment>
+ <comment xml:lang="ca">document BibTeX</comment>
+ <comment xml:lang="bg">Документ — BibTeX</comment>
+ <comment xml:lang="be@latin">Dakument BibTeX</comment>
+ <comment xml:lang="be">дакумент BibTeX</comment>
+ <comment xml:lang="ast">Documentu de BibTeX</comment>
+ <comment xml:lang="ar">مستند BibTeX</comment>
+ <comment xml:lang="af">BibTeX-dokument</comment>
<sub-class-of type="text/plain"/>
<magic>
- <match value="% This file was created with JabRef" type="string" offset="0"/>
+ <match type="string" value="% This file was created with JabRef" offset="0"/>
</magic>
<glob pattern="*.bib"/>
</mime-type>
+ <mime-type type="text/x-blueprint">
+ <comment>Blueprint source code</comment>
+ <comment xml:lang="uk">початковий код синьки</comment>
+ <comment xml:lang="sv">Blueprint-källkod</comment>
+ <comment xml:lang="ru">Исходный код Blueprint</comment>
+ <comment xml:lang="pl">Kod źródłowy Blueprint</comment>
+ <comment xml:lang="it">Codice sorgente Blueprint</comment>
+ <comment xml:lang="gl">Código fonte en Blueprint</comment>
+ <comment xml:lang="es">código fuente en Blueprint</comment>
+ <comment xml:lang="de">Blueprint-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Blueprint</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.blp"/>
+ </mime-type>
<mime-type type="text/x-c++hdr">
<comment>C++ header</comment>
- <comment xml:lang="ar">ترويسة سي++</comment>
- <comment xml:lang="be@latin">Zahałoŭny fajł C++</comment>
- <comment xml:lang="bg">Заглавен файл — C++</comment>
- <comment xml:lang="ca">capçalera en C++</comment>
- <comment xml:lang="cs">hlavičkový soubor C++</comment>
- <comment xml:lang="da">C++-posthoved</comment>
- <comment xml:lang="de">C++-Header</comment>
- <comment xml:lang="el">Κεφαλίδα C++</comment>
- <comment xml:lang="en_GB">C++ header</comment>
- <comment xml:lang="es">cabecera de código fuente en C++</comment>
- <comment xml:lang="eu">C++ goiburua</comment>
- <comment xml:lang="fi">C++-otsake</comment>
- <comment xml:lang="fo">C++ tekshøvd</comment>
- <comment xml:lang="fr">en-tête C++</comment>
- <comment xml:lang="ga">ceanntásc C++</comment>
- <comment xml:lang="gl">cabeceira de código fonte en C++</comment>
- <comment xml:lang="he">כותר C++‎</comment>
- <comment xml:lang="hr">C++ zaglavlje</comment>
- <comment xml:lang="hu">C++ fejléc</comment>
- <comment xml:lang="ia">Capite C++</comment>
- <comment xml:lang="id">Header C++</comment>
- <comment xml:lang="it">Header C++</comment>
- <comment xml:lang="ja">C++ ヘッダー</comment>
- <comment xml:lang="ka">C++-ის თავსართი</comment>
- <comment xml:lang="kk">C++ тақырыптама файлы</comment>
- <comment xml:lang="ko">C++ 헤더</comment>
- <comment xml:lang="lt">C++ antraštė</comment>
- <comment xml:lang="lv">C++ galvene</comment>
- <comment xml:lang="nb">C++-kildekodeheader</comment>
- <comment xml:lang="nl">C++-header</comment>
- <comment xml:lang="nn">C++-kjeldekode-hovud</comment>
- <comment xml:lang="oc">entèsta C++</comment>
- <comment xml:lang="pl">Plik nagłówkowy C++</comment>
- <comment xml:lang="pt">cabeçalho C++</comment>
- <comment xml:lang="pt_BR">Cabeçalho C++</comment>
- <comment xml:lang="ro">Antet C++</comment>
- <comment xml:lang="ru">Заголовочный файл C++</comment>
- <comment xml:lang="sk">Hlavičky jazyka C++</comment>
- <comment xml:lang="sl">Datoteka glave C++</comment>
- <comment xml:lang="sq">Header C++</comment>
- <comment xml:lang="sr">Ц++ заглавље</comment>
- <comment xml:lang="sv">C++-huvud</comment>
- <comment xml:lang="tr">C++ başlığı</comment>
- <comment xml:lang="uk">файл заголовків мовою C++</comment>
- <comment xml:lang="vi">Phần đầu mã nguồn C++</comment>
- <comment xml:lang="zh_CN">C++ 头文件</comment>
<comment xml:lang="zh_TW">C++ 標頭檔</comment>
+ <comment xml:lang="zh_CN">C++ 头文件</comment>
+ <comment xml:lang="vi">Phần đầu mã nguồn C++</comment>
+ <comment xml:lang="uk">файл заголовків мовою C++</comment>
+ <comment xml:lang="tr">C++ başlığı</comment>
+ <comment xml:lang="sv">C++-huvud</comment>
+ <comment xml:lang="sr">Ц++ заглавље</comment>
+ <comment xml:lang="sq">krye C++</comment>
+ <comment xml:lang="sl">Datoteka glave C++</comment>
+ <comment xml:lang="si">C++ ශීර්ෂකය</comment>
+ <comment xml:lang="sk">Hlavičky jazyka C++</comment>
+ <comment xml:lang="ru">Заголовочный файл C++</comment>
+ <comment xml:lang="ro">Antet C++</comment>
+ <comment xml:lang="pt_BR">Cabeçalho C++</comment>
+ <comment xml:lang="pt">cabeçalho C++</comment>
+ <comment xml:lang="pl">Plik nagłówkowy C++</comment>
+ <comment xml:lang="oc">entèsta C++</comment>
+ <comment xml:lang="nn">C++-kjeldekode-hovud</comment>
+ <comment xml:lang="nl">C++-header</comment>
+ <comment xml:lang="nb">C++-kildekodeheader</comment>
+ <comment xml:lang="lv">C++ galvene</comment>
+ <comment xml:lang="lt">C++ antraštė</comment>
+ <comment xml:lang="ko">C++ 헤더</comment>
+ <comment xml:lang="kk">C++ тақырыптама файлы</comment>
+ <comment xml:lang="ka">C++-ის თავსართი</comment>
+ <comment xml:lang="ja">C++ ヘッダー</comment>
+ <comment xml:lang="it">Header C++</comment>
+ <comment xml:lang="is">C++ haus</comment>
+ <comment xml:lang="id">Header C++</comment>
+ <comment xml:lang="ia">Capite C++</comment>
+ <comment xml:lang="hu">C++ fejléc</comment>
+ <comment xml:lang="hr">C++ zaglavlje</comment>
+ <comment xml:lang="he">כותר C++‎</comment>
+ <comment xml:lang="gl">cabeceira de código fonte en C++</comment>
+ <comment xml:lang="ga">ceanntásc C++</comment>
+ <comment xml:lang="fur">intestazion C++</comment>
+ <comment xml:lang="fr">en-tête C++</comment>
+ <comment xml:lang="fo">C++ tekshøvd</comment>
+ <comment xml:lang="fi">C++-otsake</comment>
+ <comment xml:lang="eu">C++ goiburua</comment>
+ <comment xml:lang="es">cabecera de código fuente en C++</comment>
+ <comment xml:lang="en_GB">C++ header</comment>
+ <comment xml:lang="el">Κεφαλίδα C++</comment>
+ <comment xml:lang="de">C++-Header</comment>
+ <comment xml:lang="da">C++-posthoved</comment>
+ <comment xml:lang="cs">hlavičkový soubor C++</comment>
+ <comment xml:lang="ca">capçalera en C++</comment>
+ <comment xml:lang="bg">Заглавен файл — C++</comment>
+ <comment xml:lang="be@latin">Zahałoŭny fajł C++</comment>
+ <comment xml:lang="be">загаловачны файл C++</comment>
+ <comment xml:lang="ar">ترويسة سي++</comment>
<sub-class-of type="text/x-chdr"/>
<glob pattern="*.hh"/>
<glob pattern="*.hp"/>
@@ -33073,55 +35117,60 @@
</mime-type>
<mime-type type="text/x-c++src">
<comment>C++ source code</comment>
- <comment xml:lang="ar">شفرة مصدر سي++</comment>
- <comment xml:lang="be@latin">Kryničny kod C++</comment>
- <comment xml:lang="bg">Изходен код — C++</comment>
- <comment xml:lang="ca">codi font en C++</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce C++</comment>
- <comment xml:lang="da">C++-kildekode</comment>
- <comment xml:lang="de">C++-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας C++</comment>
- <comment xml:lang="en_GB">C++ source code</comment>
- <comment xml:lang="eo">C++-fontkodo</comment>
- <comment xml:lang="es">código fuente en C++</comment>
- <comment xml:lang="eu">C++ iturburu-kodea</comment>
- <comment xml:lang="fi">C++-lähdekoodi</comment>
- <comment xml:lang="fo">C++ keldukota</comment>
- <comment xml:lang="fr">code source C++</comment>
- <comment xml:lang="ga">cód foinseach C++</comment>
- <comment xml:lang="gl">código fonte de C++</comment>
- <comment xml:lang="he">קוד מקור של C++‎</comment>
- <comment xml:lang="hr">C++ izvorni kôd</comment>
- <comment xml:lang="hu">C++-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte C++</comment>
- <comment xml:lang="id">Kode sumber C++</comment>
- <comment xml:lang="it">Codice sorgente C++</comment>
- <comment xml:lang="ja">C++ ソースコード</comment>
- <comment xml:lang="ka">C++-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">C++ бастапқы коды</comment>
- <comment xml:lang="ko">C++ 소스 코드</comment>
- <comment xml:lang="lt">C++ pradinis kodas</comment>
- <comment xml:lang="lv">C++ pirmkods</comment>
- <comment xml:lang="ms">Kod sumber C++</comment>
- <comment xml:lang="nb">C++-kildekode</comment>
- <comment xml:lang="nl">C++-broncode</comment>
- <comment xml:lang="nn">C++-kjeldekode</comment>
- <comment xml:lang="oc">còde font C++</comment>
- <comment xml:lang="pl">Kod źródłowy C++</comment>
- <comment xml:lang="pt">código origem C++</comment>
- <comment xml:lang="pt_BR">Código-fonte C++</comment>
- <comment xml:lang="ro">Cod sursă C++</comment>
- <comment xml:lang="ru">Исходный код C++</comment>
- <comment xml:lang="sk">Zdrojový kód jazyka C++</comment>
- <comment xml:lang="sl">Datoteka izvorne kode C++</comment>
- <comment xml:lang="sq">Kod burues C++</comment>
- <comment xml:lang="sr">Ц++ изворни ко̂д</comment>
- <comment xml:lang="sv">C++-källkod</comment>
- <comment xml:lang="tr">C++ kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою C++</comment>
- <comment xml:lang="vi">Mã nguồn C++</comment>
- <comment xml:lang="zh_CN">C++ 源代码</comment>
<comment xml:lang="zh_TW">C++ 源碼</comment>
+ <comment xml:lang="zh_CN">C++ 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn C++</comment>
+ <comment xml:lang="uk">початковий код мовою C++</comment>
+ <comment xml:lang="tr">C++ kaynak kodu</comment>
+ <comment xml:lang="sv">C++-källkod</comment>
+ <comment xml:lang="sr">Ц++ изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim C++</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode C++</comment>
+ <comment xml:lang="si">C++ මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód jazyka C++</comment>
+ <comment xml:lang="ru">Исходный код C++</comment>
+ <comment xml:lang="ro">Cod sursă C++</comment>
+ <comment xml:lang="pt_BR">Código-fonte C++</comment>
+ <comment xml:lang="pt">código origem C++</comment>
+ <comment xml:lang="pl">Kod źródłowy C++</comment>
+ <comment xml:lang="oc">còde font C++</comment>
+ <comment xml:lang="nn">C++-kjeldekode</comment>
+ <comment xml:lang="nl">C++-broncode</comment>
+ <comment xml:lang="nb">C++-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber C++</comment>
+ <comment xml:lang="lv">C++ pirmkods</comment>
+ <comment xml:lang="lt">C++ pradinis kodas</comment>
+ <comment xml:lang="ko">C++ 소스 코드</comment>
+ <comment xml:lang="kk">C++ бастапқы коды</comment>
+ <comment xml:lang="ka">C++-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">C++ ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente C++</comment>
+ <comment xml:lang="is">C++ frumkóði</comment>
+ <comment xml:lang="id">Kode sumber C++</comment>
+ <comment xml:lang="ia">Codice-fonte C++</comment>
+ <comment xml:lang="hu">C++-forráskód</comment>
+ <comment xml:lang="hr">C++ izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של C++‎</comment>
+ <comment xml:lang="gl">código fonte de C++</comment>
+ <comment xml:lang="ga">cód foinseach C++</comment>
+ <comment xml:lang="fur">codiç sorzint C++</comment>
+ <comment xml:lang="fr">code source C++</comment>
+ <comment xml:lang="fo">C++ keldukota</comment>
+ <comment xml:lang="fi">C++-lähdekoodi</comment>
+ <comment xml:lang="eu">C++ iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en C++</comment>
+ <comment xml:lang="eo">C++-fontkodo</comment>
+ <comment xml:lang="en_GB">C++ source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας C++</comment>
+ <comment xml:lang="de">C++-Quelltext</comment>
+ <comment xml:lang="da">C++-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce C++</comment>
+ <comment xml:lang="ca">codi font en C++</comment>
+ <comment xml:lang="bg">Изходен код — C++</comment>
+ <comment xml:lang="be@latin">Kryničny kod C++</comment>
+ <comment xml:lang="be">зыходны код C++</comment>
+ <comment xml:lang="ar">شفرة مصدر سي++</comment>
+ <comment xml:lang="af">C++-bronkode</comment>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.cpp"/>
<glob pattern="*.cxx"/>
@@ -33131,214 +35180,270 @@
</mime-type>
<mime-type type="text/x-changelog">
<comment>ChangeLog document</comment>
- <comment xml:lang="ar">مستند ChangeLog</comment>
- <comment xml:lang="ast">Documentu de rexistru de cambeos</comment>
- <comment xml:lang="be@latin">Dakument zafiksavanych źmienaŭ ChangeLog</comment>
- <comment xml:lang="bg">Дневник за промени — ChangeLog</comment>
- <comment xml:lang="ca">document de registre de canvis</comment>
- <comment xml:lang="cs">dokument ChangeLog</comment>
- <comment xml:lang="da">ChangeLot-dokument</comment>
- <comment xml:lang="de">Änderungsprotokoll-Dokument</comment>
- <comment xml:lang="el">Έγγραφο ChangeLog</comment>
- <comment xml:lang="en_GB">ChangeLog document</comment>
- <comment xml:lang="es">documento de registro de cambios</comment>
- <comment xml:lang="eu">ChangeLog dokumentua</comment>
- <comment xml:lang="fi">Muutoslokiasiakirja</comment>
- <comment xml:lang="fo">ChangeLog skjal</comment>
- <comment xml:lang="fr">document ChangeLog</comment>
- <comment xml:lang="ga">cáipéis ChangeLog</comment>
- <comment xml:lang="gl">documento Changelog</comment>
- <comment xml:lang="he">מסמך של ChangeLog</comment>
- <comment xml:lang="hr">Dokument zapisa promjena</comment>
- <comment xml:lang="hu">ChangeLog dokumentum</comment>
- <comment xml:lang="ia">Lista de cambiamentos</comment>
- <comment xml:lang="id">Dokumen ChangeLog</comment>
- <comment xml:lang="it">Documento ChangeLog</comment>
- <comment xml:lang="ja">ChangeLog ドキュメント</comment>
- <comment xml:lang="ka">ChangeLog დოკუმენტი</comment>
- <comment xml:lang="kk">ChangeLog құжаты</comment>
- <comment xml:lang="ko">ChangeLog 문서</comment>
- <comment xml:lang="lt">ChangeLog dokumentas</comment>
- <comment xml:lang="lv">ChangeLog dokuments</comment>
- <comment xml:lang="nb">ChangeLog-dokument</comment>
- <comment xml:lang="nl">ChangeLog-document</comment>
- <comment xml:lang="nn">ChangeLog-dokument</comment>
- <comment xml:lang="oc">document ChangeLog</comment>
- <comment xml:lang="pl">Dokument zmian (ChangeLog)</comment>
- <comment xml:lang="pt">documento ChangeLog</comment>
- <comment xml:lang="pt_BR">Documento ChangeLog</comment>
- <comment xml:lang="ro">Document ChangeLog</comment>
- <comment xml:lang="ru">Протокол изменений</comment>
- <comment xml:lang="sk">Dokument ChangeLog</comment>
- <comment xml:lang="sl">Dokument ChangeLog</comment>
- <comment xml:lang="sq">Dokument ChangeLog</comment>
- <comment xml:lang="sr">документ дневника измена</comment>
- <comment xml:lang="sv">Ändringsloggsdokument</comment>
- <comment xml:lang="tr">Değişim Günlüğü belgesi</comment>
- <comment xml:lang="uk">документ ChangeLog</comment>
- <comment xml:lang="vi">Tài liệu ChangeLog (ghi lưu thay đổi)</comment>
- <comment xml:lang="zh_CN">变更日志文档</comment>
<comment xml:lang="zh_TW">ChangeLog 文件</comment>
+ <comment xml:lang="zh_CN">变更日志文档</comment>
+ <comment xml:lang="vi">Tài liệu ChangeLog (ghi lưu thay đổi)</comment>
+ <comment xml:lang="uk">документ ChangeLog</comment>
+ <comment xml:lang="tr">ChangeLog belgesi</comment>
+ <comment xml:lang="sv">Ändringsloggsdokument</comment>
+ <comment xml:lang="sr">документ дневника измена</comment>
+ <comment xml:lang="sq">dokument regjistri ndryshimesh</comment>
+ <comment xml:lang="sl">Dokument ChangeLog</comment>
+ <comment xml:lang="si">ChangeLog ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument ChangeLog</comment>
+ <comment xml:lang="ru">Протокол изменений</comment>
+ <comment xml:lang="ro">Document ChangeLog</comment>
+ <comment xml:lang="pt_BR">Documento ChangeLog</comment>
+ <comment xml:lang="pt">documento ChangeLog</comment>
+ <comment xml:lang="pl">Dokument zmian (ChangeLog)</comment>
+ <comment xml:lang="oc">document ChangeLog</comment>
+ <comment xml:lang="nn">ChangeLog-dokument</comment>
+ <comment xml:lang="nl">ChangeLog-document</comment>
+ <comment xml:lang="nb">ChangeLog-dokument</comment>
+ <comment xml:lang="lv">ChangeLog dokuments</comment>
+ <comment xml:lang="lt">ChangeLog dokumentas</comment>
+ <comment xml:lang="ko">ChangeLog 문서</comment>
+ <comment xml:lang="kk">ChangeLog құжаты</comment>
+ <comment xml:lang="ka">ChangeLog დოკუმენტი</comment>
+ <comment xml:lang="ja">ChangeLog ドキュメント</comment>
+ <comment xml:lang="it">Documento ChangeLog</comment>
+ <comment xml:lang="is">ChangeLog skjal</comment>
+ <comment xml:lang="id">Dokumen ChangeLog</comment>
+ <comment xml:lang="ia">Lista de cambiamentos</comment>
+ <comment xml:lang="hu">ChangeLog dokumentum</comment>
+ <comment xml:lang="hr">Dokument zapisa promjena</comment>
+ <comment xml:lang="he">מסמך של ChangeLog</comment>
+ <comment xml:lang="gl">documento Changelog</comment>
+ <comment xml:lang="ga">cáipéis ChangeLog</comment>
+ <comment xml:lang="fur">document ChangeLog</comment>
+ <comment xml:lang="fr">document ChangeLog</comment>
+ <comment xml:lang="fo">ChangeLog skjal</comment>
+ <comment xml:lang="fi">Muutoslokiasiakirja</comment>
+ <comment xml:lang="eu">ChangeLog dokumentua</comment>
+ <comment xml:lang="es">documento de registro de cambios</comment>
+ <comment xml:lang="en_GB">ChangeLog document</comment>
+ <comment xml:lang="el">Έγγραφο ChangeLog</comment>
+ <comment xml:lang="de">Änderungsprotokoll-Dokument</comment>
+ <comment xml:lang="da">ChangeLot-dokument</comment>
+ <comment xml:lang="cs">dokument ChangeLog</comment>
+ <comment xml:lang="ca">document de registre de canvis</comment>
+ <comment xml:lang="bg">Дневник за промени — ChangeLog</comment>
+ <comment xml:lang="be@latin">Dakument zafiksavanych źmienaŭ ChangeLog</comment>
+ <comment xml:lang="be">дакумент zafiksavanych źmienaŭ ChangeLog</comment>
+ <comment xml:lang="ast">Documentu de rexistru de cambeos</comment>
+ <comment xml:lang="ar">مستند ChangeLog</comment>
+ <comment xml:lang="af">ChangeLog-dokument</comment>
<sub-class-of type="text/plain"/>
<glob pattern="ChangeLog"/>
</mime-type>
<mime-type type="text/x-chdr">
<comment>C header</comment>
- <comment xml:lang="ar">ترويسة C</comment>
- <comment xml:lang="be@latin">Zahałoŭny fajł C</comment>
- <comment xml:lang="bg">Заглавен файл — C</comment>
- <comment xml:lang="ca">capçalera en C</comment>
- <comment xml:lang="cs">hlavičkový soubor C</comment>
- <comment xml:lang="da">C-posthoved</comment>
- <comment xml:lang="de">C-Header</comment>
- <comment xml:lang="el">Κεφαλίδα C</comment>
- <comment xml:lang="en_GB">C header</comment>
- <comment xml:lang="es">cabecera de código fuente en C</comment>
- <comment xml:lang="eu">C goiburua</comment>
- <comment xml:lang="fi">C-otsake</comment>
- <comment xml:lang="fo">C tekshøvd</comment>
- <comment xml:lang="fr">en-tête C</comment>
- <comment xml:lang="ga">ceanntásc C</comment>
- <comment xml:lang="gl">cabeceira de códifo fonte de C</comment>
- <comment xml:lang="he">כותר C</comment>
- <comment xml:lang="hr">C zaglavlje</comment>
- <comment xml:lang="hu">C fejléc</comment>
- <comment xml:lang="ia">Capite C</comment>
- <comment xml:lang="id">Header C</comment>
- <comment xml:lang="it">Header C</comment>
- <comment xml:lang="ja">C ヘッダー</comment>
- <comment xml:lang="ka">C-ის თავსართი</comment>
- <comment xml:lang="kk">C тақырыптама файлы</comment>
- <comment xml:lang="ko">C 헤더</comment>
- <comment xml:lang="lt">C antraštė</comment>
- <comment xml:lang="lv">C galvene</comment>
- <comment xml:lang="nb">C-kildekodeheader</comment>
- <comment xml:lang="nl">C-header</comment>
- <comment xml:lang="nn">C-kjeldekode-hovud</comment>
- <comment xml:lang="oc">entèsta C</comment>
- <comment xml:lang="pl">Plik nagłówkowy C</comment>
- <comment xml:lang="pt">cabeçalho C</comment>
- <comment xml:lang="pt_BR">Cabeçalho C</comment>
- <comment xml:lang="ro">Antet C</comment>
- <comment xml:lang="ru">Заголовочный файл C</comment>
- <comment xml:lang="sk">Hlavičky jazyka C</comment>
- <comment xml:lang="sl">Datoteka glave C</comment>
- <comment xml:lang="sq">Header C</comment>
- <comment xml:lang="sr">Ц заглавље</comment>
- <comment xml:lang="sv">C-huvud</comment>
- <comment xml:lang="tr">C başlığı</comment>
- <comment xml:lang="uk">файл заголовків мовою C</comment>
- <comment xml:lang="vi">Phần đầu mã nguồn C</comment>
- <comment xml:lang="zh_CN">C 程序头文件</comment>
<comment xml:lang="zh_TW">C 標頭檔</comment>
+ <comment xml:lang="zh_CN">C 程序头文件</comment>
+ <comment xml:lang="vi">Phần đầu mã nguồn C</comment>
+ <comment xml:lang="uk">файл заголовків мовою C</comment>
+ <comment xml:lang="tr">C başlığı</comment>
+ <comment xml:lang="sv">C-huvud</comment>
+ <comment xml:lang="sr">Ц заглавље</comment>
+ <comment xml:lang="sq">krye C</comment>
+ <comment xml:lang="sl">Datoteka glave C</comment>
+ <comment xml:lang="si">C ශීර්ෂකය</comment>
+ <comment xml:lang="sk">Hlavičky jazyka C</comment>
+ <comment xml:lang="ru">Заголовочный файл C</comment>
+ <comment xml:lang="ro">Antet C</comment>
+ <comment xml:lang="pt_BR">Cabeçalho C</comment>
+ <comment xml:lang="pt">cabeçalho C</comment>
+ <comment xml:lang="pl">Plik nagłówkowy C</comment>
+ <comment xml:lang="oc">entèsta C</comment>
+ <comment xml:lang="nn">C-kjeldekode-hovud</comment>
+ <comment xml:lang="nl">C-header</comment>
+ <comment xml:lang="nb">C-kildekodeheader</comment>
+ <comment xml:lang="lv">C galvene</comment>
+ <comment xml:lang="lt">C antraštė</comment>
+ <comment xml:lang="ko">C 헤더</comment>
+ <comment xml:lang="kk">C тақырыптама файлы</comment>
+ <comment xml:lang="ka">C-ის თავსართი</comment>
+ <comment xml:lang="ja">C ヘッダー</comment>
+ <comment xml:lang="it">Header C</comment>
+ <comment xml:lang="is">C haus</comment>
+ <comment xml:lang="id">Header C</comment>
+ <comment xml:lang="ia">Capite C</comment>
+ <comment xml:lang="hu">C fejléc</comment>
+ <comment xml:lang="hr">C zaglavlje</comment>
+ <comment xml:lang="he">כותר C</comment>
+ <comment xml:lang="gl">cabeceira de códifo fonte de C</comment>
+ <comment xml:lang="ga">ceanntásc C</comment>
+ <comment xml:lang="fur">intestazion C</comment>
+ <comment xml:lang="fr">en-tête C</comment>
+ <comment xml:lang="fo">C tekshøvd</comment>
+ <comment xml:lang="fi">C-otsake</comment>
+ <comment xml:lang="eu">C goiburua</comment>
+ <comment xml:lang="es">cabecera de código fuente en C</comment>
+ <comment xml:lang="en_GB">C header</comment>
+ <comment xml:lang="el">Κεφαλίδα C</comment>
+ <comment xml:lang="de">C-Header</comment>
+ <comment xml:lang="da">C-posthoved</comment>
+ <comment xml:lang="cs">hlavičkový soubor C</comment>
+ <comment xml:lang="ca">capçalera en C</comment>
+ <comment xml:lang="bg">Заглавен файл — C</comment>
+ <comment xml:lang="be@latin">Zahałoŭny fajł C</comment>
+ <comment xml:lang="be">загаловачны файл C</comment>
+ <comment xml:lang="ar">ترويسة C</comment>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.h"/>
</mime-type>
<mime-type type="text/x-cmake">
<comment>CMake source code</comment>
- <comment xml:lang="ar">شفرة مصدر CMake</comment>
- <comment xml:lang="be@latin">Kryničny kod CMake</comment>
- <comment xml:lang="bg">Изходен код — CMake</comment>
- <comment xml:lang="ca">codi font en CMake</comment>
- <comment xml:lang="cs">zdrojový kód CMake</comment>
- <comment xml:lang="da">CMake-kildekode</comment>
- <comment xml:lang="de">CMake-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας CMake</comment>
- <comment xml:lang="en_GB">CMake source code</comment>
- <comment xml:lang="eo">CMake-fontkodo</comment>
- <comment xml:lang="es">código fuente en CMake</comment>
- <comment xml:lang="eu">CMake iturburu-kodea</comment>
- <comment xml:lang="fi">CMake-lähdekoodi</comment>
- <comment xml:lang="fo">CMake keldukota</comment>
- <comment xml:lang="fr">code source CMake</comment>
- <comment xml:lang="ga">cód foinseach CMake</comment>
- <comment xml:lang="gl">código fonte de CMake</comment>
- <comment xml:lang="he">קוד מקור של CMake</comment>
- <comment xml:lang="hr">CMake izvorni kôd</comment>
- <comment xml:lang="hu">CMake-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte CMake</comment>
- <comment xml:lang="id">Kode sumber CMake</comment>
- <comment xml:lang="it">Codice sorgente CMake</comment>
- <comment xml:lang="ja">CMake ソースコード</comment>
- <comment xml:lang="ka">CMake-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">CMake бастапқы коды</comment>
- <comment xml:lang="ko">CMake 소스 코드</comment>
- <comment xml:lang="lt">CMake pirminis tekstas</comment>
- <comment xml:lang="lv">CMake pirmkods</comment>
- <comment xml:lang="nb">CMake-kildekode</comment>
- <comment xml:lang="nl">CMake-broncode</comment>
- <comment xml:lang="nn">CMake-kjeldekode</comment>
- <comment xml:lang="oc">còde font CMake</comment>
- <comment xml:lang="pl">Kod źródłowy CMake</comment>
- <comment xml:lang="pt">código origem CMake</comment>
- <comment xml:lang="pt_BR">Código-fonte CMake</comment>
- <comment xml:lang="ro">Cod sursă CMake</comment>
- <comment xml:lang="ru">Исходный код CMake</comment>
- <comment xml:lang="sk">Zdrojový kód CMake</comment>
- <comment xml:lang="sl">Datoteka izvorne kode CMake</comment>
- <comment xml:lang="sq">Kod burues CMake</comment>
- <comment xml:lang="sr">Ц Мејк изворни ко̂д</comment>
- <comment xml:lang="sv">CMake-källkod</comment>
- <comment xml:lang="tr">CMake kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код CMake</comment>
- <comment xml:lang="vi">Mã nguồn CMake</comment>
- <comment xml:lang="zh_CN">CMake 源代码</comment>
<comment xml:lang="zh_TW">CMake 源碼</comment>
+ <comment xml:lang="zh_CN">CMake 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn CMake</comment>
+ <comment xml:lang="uk">початковий код мовою CMake</comment>
+ <comment xml:lang="tr">CMake kaynak kodu</comment>
+ <comment xml:lang="sv">CMake-källkod</comment>
+ <comment xml:lang="sr">Ц Мејк изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim CMake</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode CMake</comment>
+ <comment xml:lang="si">CMake මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód CMake</comment>
+ <comment xml:lang="ru">Исходный код CMake</comment>
+ <comment xml:lang="ro">Cod sursă CMake</comment>
+ <comment xml:lang="pt_BR">Código-fonte CMake</comment>
+ <comment xml:lang="pt">código origem CMake</comment>
+ <comment xml:lang="pl">Kod źródłowy CMake</comment>
+ <comment xml:lang="oc">còde font CMake</comment>
+ <comment xml:lang="nn">CMake-kjeldekode</comment>
+ <comment xml:lang="nl">CMake-broncode</comment>
+ <comment xml:lang="nb">CMake-kildekode</comment>
+ <comment xml:lang="lv">CMake pirmkods</comment>
+ <comment xml:lang="lt">CMake pirminis tekstas</comment>
+ <comment xml:lang="ko">CMake 소스 코드</comment>
+ <comment xml:lang="kk">CMake бастапқы коды</comment>
+ <comment xml:lang="ka">CMake-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">CMake ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente CMake</comment>
+ <comment xml:lang="is">CMake frumkóði</comment>
+ <comment xml:lang="id">Kode sumber CMake</comment>
+ <comment xml:lang="ia">Codice-fonte CMake</comment>
+ <comment xml:lang="hu">CMake-forráskód</comment>
+ <comment xml:lang="hr">CMake izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של CMake</comment>
+ <comment xml:lang="gl">código fonte de CMake</comment>
+ <comment xml:lang="ga">cód foinseach CMake</comment>
+ <comment xml:lang="fur">codiç sorzint CMake</comment>
+ <comment xml:lang="fr">code source CMake</comment>
+ <comment xml:lang="fo">CMake keldukota</comment>
+ <comment xml:lang="fi">CMake-lähdekoodi</comment>
+ <comment xml:lang="eu">CMake iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en CMake</comment>
+ <comment xml:lang="eo">CMake-fontkodo</comment>
+ <comment xml:lang="en_GB">CMake source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας CMake</comment>
+ <comment xml:lang="de">CMake-Quelltext</comment>
+ <comment xml:lang="da">CMake-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód CMake</comment>
+ <comment xml:lang="ca">codi font en CMake</comment>
+ <comment xml:lang="bg">Изходен код — CMake</comment>
+ <comment xml:lang="be@latin">Kryničny kod CMake</comment>
+ <comment xml:lang="be">зыходны код CMake</comment>
+ <comment xml:lang="ar">شفرة مصدر CMake</comment>
+ <comment xml:lang="af">CMake-bronkode</comment>
<glob pattern="*.cmake"/>
<glob pattern="CMakeLists.txt"/>
<sub-class-of type="text/plain"/>
</mime-type>
+ <mime-type type="text/x-common-lisp">
+ <comment>Common Lisp source code</comment>
+ <comment xml:lang="zh_TW">Common Lisp 原始碼</comment>
+ <comment xml:lang="zh_CN">Common Lisp 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Common Lisp</comment>
+ <comment xml:lang="tr">Common Lisp kaynak kodu</comment>
+ <comment xml:lang="sv">Common Lisp-källkod</comment>
+ <comment xml:lang="si">පොදු Lisp මූලාශ්‍ර කේතය</comment>
+ <comment xml:lang="ru">Исходный код Common Lisp</comment>
+ <comment xml:lang="pt_BR">Código-fonte Common Lisp</comment>
+ <comment xml:lang="pl">Kod źródłowy Common Lisp</comment>
+ <comment xml:lang="nl">Common Lisp-broncode</comment>
+ <comment xml:lang="ko">Common Lisp 소스 코드</comment>
+ <comment xml:lang="kk">Common Lisp бастапқы коды</comment>
+ <comment xml:lang="ja">Common Lisp ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Common Lisp</comment>
+ <comment xml:lang="is">Sameiginlegur Lisp frumkóði</comment>
+ <comment xml:lang="id">kode sumber Common Lisp</comment>
+ <comment xml:lang="hu">Common Lisp forráskód</comment>
+ <comment xml:lang="hr">Common Lisp izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Common Lisp</comment>
+ <comment xml:lang="gl">Código fonte en Common Lisp</comment>
+ <comment xml:lang="fr">code source Common Lisp</comment>
+ <comment xml:lang="fi">Common Lisp -lähdekoodi</comment>
+ <comment xml:lang="es">código fuente en Common Lisp</comment>
+ <comment xml:lang="en_GB">Common Lisp source code</comment>
+ <comment xml:lang="de">Common-Lisp-Quelltext</comment>
+ <comment xml:lang="da">Common Lisp-kildekode</comment>
+ <comment xml:lang="ca">codi font en Common Lisp</comment>
+ <comment xml:lang="be">зыходны код Common Lisp</comment>
+ <comment xml:lang="ar">شفرة مصدر Common Lisp</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.asd"/>
+ <glob pattern="*.fasl"/>
+ <glob pattern="*.lisp"/>
+ <glob pattern="*.ros"/>
+ </mime-type>
<mime-type type="text/csv">
<comment>CSV document</comment>
- <comment xml:lang="ar">مستند CSV</comment>
- <comment xml:lang="ast">Documentu CVS</comment>
- <comment xml:lang="be@latin">Dakument CSV</comment>
- <comment xml:lang="bg">Документ — CSV</comment>
- <comment xml:lang="ca">document CSV</comment>
- <comment xml:lang="cs">dokument CSV</comment>
- <comment xml:lang="da">CSV-dokument</comment>
- <comment xml:lang="de">CSV-Dokument</comment>
- <comment xml:lang="el">Έγγραφο CSV</comment>
- <comment xml:lang="en_GB">CSV document</comment>
- <comment xml:lang="eo">CSV-dokumento</comment>
- <comment xml:lang="es">documento CSV</comment>
- <comment xml:lang="eu">CSV dokumentua</comment>
- <comment xml:lang="fi">CSV-asiakirja</comment>
- <comment xml:lang="fo">CSV skjal</comment>
- <comment xml:lang="fr">document CSV</comment>
- <comment xml:lang="ga">cáipéis CSV</comment>
- <comment xml:lang="gl">documento CSV</comment>
- <comment xml:lang="he">מסמך CSV</comment>
- <comment xml:lang="hr">CSV dokument</comment>
- <comment xml:lang="hu">CSV dokumentum</comment>
- <comment xml:lang="ia">Documento CSV</comment>
- <comment xml:lang="id">Dokumen CSV</comment>
- <comment xml:lang="it">Documento CSV</comment>
- <comment xml:lang="ja">CSV ドキュメント</comment>
- <comment xml:lang="ka">CSV დოკუმენტი</comment>
- <comment xml:lang="kk">CSV құжаты</comment>
- <comment xml:lang="ko">CSV 문서</comment>
- <comment xml:lang="lt">CSV dokumentas</comment>
- <comment xml:lang="lv">CSV dokuments</comment>
- <comment xml:lang="nb">CSV-dokument</comment>
- <comment xml:lang="nl">CSV-document</comment>
- <comment xml:lang="nn">CSV-dokument</comment>
- <comment xml:lang="oc">document CSV</comment>
- <comment xml:lang="pl">Dokument CSV</comment>
- <comment xml:lang="pt">documento CSV</comment>
- <comment xml:lang="pt_BR">Documento CSV</comment>
- <comment xml:lang="ro">Document CSV</comment>
- <comment xml:lang="ru">Документ CSV</comment>
- <comment xml:lang="sk">Dokument CSV</comment>
- <comment xml:lang="sl">Dokument CSV</comment>
- <comment xml:lang="sq">Dokument CSV</comment>
- <comment xml:lang="sr">ЦСВ документ</comment>
- <comment xml:lang="sv">CSV-dokument</comment>
- <comment xml:lang="tr">CSV belgesi</comment>
- <comment xml:lang="uk">документ CSV</comment>
- <comment xml:lang="vi">Tài liệu CSV</comment>
- <comment xml:lang="zh_CN">CSV 文档</comment>
<comment xml:lang="zh_TW">CSV 文件</comment>
+ <comment xml:lang="zh_CN">CSV 文档</comment>
+ <comment xml:lang="vi">Tài liệu CSV</comment>
+ <comment xml:lang="uk">документ CSV</comment>
+ <comment xml:lang="tr">CSV belgesi</comment>
+ <comment xml:lang="sv">CSV-dokument</comment>
+ <comment xml:lang="sr">ЦСВ документ</comment>
+ <comment xml:lang="sq">dokument CSV</comment>
+ <comment xml:lang="sl">Dokument CSV</comment>
+ <comment xml:lang="si">CSV ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument CSV</comment>
+ <comment xml:lang="ru">Документ CSV</comment>
+ <comment xml:lang="ro">Document CSV</comment>
+ <comment xml:lang="pt_BR">Documento CSV</comment>
+ <comment xml:lang="pt">documento CSV</comment>
+ <comment xml:lang="pl">Dokument CSV</comment>
+ <comment xml:lang="oc">document CSV</comment>
+ <comment xml:lang="nn">CSV-dokument</comment>
+ <comment xml:lang="nl">CSV-document</comment>
+ <comment xml:lang="nb">CSV-dokument</comment>
+ <comment xml:lang="lv">CSV dokuments</comment>
+ <comment xml:lang="lt">CSV dokumentas</comment>
+ <comment xml:lang="ko">CSV 문서</comment>
+ <comment xml:lang="kk">CSV құжаты</comment>
+ <comment xml:lang="ka">CSV დოკუმენტი</comment>
+ <comment xml:lang="ja">CSV ドキュメント</comment>
+ <comment xml:lang="it">Documento CSV</comment>
+ <comment xml:lang="is">CSV skjal</comment>
+ <comment xml:lang="id">Dokumen CSV</comment>
+ <comment xml:lang="ia">Documento CSV</comment>
+ <comment xml:lang="hu">CSV dokumentum</comment>
+ <comment xml:lang="hr">CSV dokument</comment>
+ <comment xml:lang="he">מסמך CSV</comment>
+ <comment xml:lang="gl">documento CSV</comment>
+ <comment xml:lang="ga">cáipéis CSV</comment>
+ <comment xml:lang="fur">document CSV</comment>
+ <comment xml:lang="fr">document CSV</comment>
+ <comment xml:lang="fo">CSV skjal</comment>
+ <comment xml:lang="fi">CSV-asiakirja</comment>
+ <comment xml:lang="eu">CSV dokumentua</comment>
+ <comment xml:lang="es">documento CSV</comment>
+ <comment xml:lang="eo">CSV-dokumento</comment>
+ <comment xml:lang="en_GB">CSV document</comment>
+ <comment xml:lang="el">Έγγραφο CSV</comment>
+ <comment xml:lang="de">CSV-Dokument</comment>
+ <comment xml:lang="da">CSV-dokument</comment>
+ <comment xml:lang="cs">dokument CSV</comment>
+ <comment xml:lang="ca">document CSV</comment>
+ <comment xml:lang="bg">Документ — CSV</comment>
+ <comment xml:lang="be@latin">Dakument CSV</comment>
+ <comment xml:lang="be">дакумент CSV</comment>
+ <comment xml:lang="ast">Documentu CVS</comment>
+ <comment xml:lang="ar">مستند CSV</comment>
+ <comment xml:lang="af">CSV-dokument</comment>
<acronym>CSV</acronym>
<expanded-acronym>Comma Separated Values</expanded-acronym>
<alias type="text/x-comma-separated-values"/>
@@ -33348,351 +35453,313 @@
</mime-type>
<mime-type type="text/csv-schema">
<comment>CSV Schema document</comment>
- <comment xml:lang="ast">Documentu d'esquema CSV</comment>
- <comment xml:lang="ca">document Schema de CSV</comment>
- <comment xml:lang="cs">dokument schématu CSV</comment>
- <comment xml:lang="da">CSV Schema-dokument</comment>
- <comment xml:lang="de">CSV-Schemadokument</comment>
- <comment xml:lang="en_GB">CSV Schema document</comment>
- <comment xml:lang="es">documento esquemático CSV</comment>
- <comment xml:lang="eu">CSV Schema dokumentua</comment>
- <comment xml:lang="fr">document schéma CSV</comment>
- <comment xml:lang="ga">cáipéis scéimre CSV</comment>
- <comment xml:lang="he">מסמך פריסת CSV</comment>
- <comment xml:lang="hr">CSV Shema dokument</comment>
- <comment xml:lang="hu">CSV sémadokumentum</comment>
- <comment xml:lang="ia">Documento CSV Schema</comment>
- <comment xml:lang="id">Dokumen Skema CSV</comment>
- <comment xml:lang="it">Documento schema CSV</comment>
- <comment xml:lang="kk">CSV сұлба құжаты</comment>
- <comment xml:lang="ko">CSV 스키마 문서</comment>
- <comment xml:lang="pl">Dokument schematu CSV</comment>
- <comment xml:lang="pt">documento CSV Schema</comment>
- <comment xml:lang="pt_BR">Documento CSV Schema</comment>
- <comment xml:lang="ru">Документ CSV Schema</comment>
- <comment xml:lang="sk">Dokument schémy CSV</comment>
- <comment xml:lang="sr">документ ЦСВ шеме</comment>
- <comment xml:lang="sv">CSV Schema-dokument</comment>
- <comment xml:lang="tr">CSV Şeması belgesi</comment>
- <comment xml:lang="uk">документ Schema у форматі CSV</comment>
- <comment xml:lang="zh_CN">CSV 架构文档</comment>
<comment xml:lang="zh_TW">CSV Schema 文件</comment>
+ <comment xml:lang="zh_CN">CSV 架构文档</comment>
+ <comment xml:lang="uk">документ Schema у форматі CSV</comment>
+ <comment xml:lang="tr">CSV Şeması belgesi</comment>
+ <comment xml:lang="sv">CSV Schema-dokument</comment>
+ <comment xml:lang="sr">документ ЦСВ шеме</comment>
+ <comment xml:lang="sq">dokument CSV Schema</comment>
+ <comment xml:lang="sl">Dokument CSV Schema</comment>
+ <comment xml:lang="si">CSV ක්‍රම ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument schémy CSV</comment>
+ <comment xml:lang="ru">Документ CSV Schema</comment>
+ <comment xml:lang="pt_BR">Documento CSV Schema</comment>
+ <comment xml:lang="pt">documento CSV Schema</comment>
+ <comment xml:lang="pl">Dokument schematu CSV</comment>
+ <comment xml:lang="nl">CSV-schemadocument</comment>
+ <comment xml:lang="ko">CSV 스키마 문서</comment>
+ <comment xml:lang="kk">CSV сұлба құжаты</comment>
+ <comment xml:lang="ja">CSV Schema ドキュメント</comment>
+ <comment xml:lang="it">Documento schema CSV</comment>
+ <comment xml:lang="is">CSV skemaskjal</comment>
+ <comment xml:lang="id">Dokumen Skema CSV</comment>
+ <comment xml:lang="ia">Documento CSV Schema</comment>
+ <comment xml:lang="hu">CSV sémadokumentum</comment>
+ <comment xml:lang="hr">CSV Shema dokument</comment>
+ <comment xml:lang="he">מסמך פריסת CSV</comment>
+ <comment xml:lang="ga">cáipéis scéimre CSV</comment>
+ <comment xml:lang="fur">document scheme CSV</comment>
+ <comment xml:lang="fr">document schéma CSV</comment>
+ <comment xml:lang="fi">CSV Schema -asiakirja</comment>
+ <comment xml:lang="eu">CSV Schema dokumentua</comment>
+ <comment xml:lang="es">documento esquemático CSV</comment>
+ <comment xml:lang="en_GB">CSV Schema document</comment>
+ <comment xml:lang="de">CSV-Schemadokument</comment>
+ <comment xml:lang="da">CSV Schema-dokument</comment>
+ <comment xml:lang="cs">dokument schématu CSV</comment>
+ <comment xml:lang="ca">document Schema de CSV</comment>
+ <comment xml:lang="bg">Документ — схема на CSV</comment>
+ <comment xml:lang="be">дакумент CSV Schema</comment>
+ <comment xml:lang="ast">Documentu d'esquema CSV</comment>
+ <comment xml:lang="ar">مستند مخطط CSV</comment>
+ <comment xml:lang="af">CSV Schema-dokument</comment>
<acronym>CSV</acronym>
<expanded-acronym>Comma Separated Values</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.csvs"/>
</mime-type>
<mime-type type="text/x-copying">
- <comment>license terms</comment>
- <comment xml:lang="ar">شروط الترخيص</comment>
- <comment xml:lang="ast">términos de llicencia</comment>
- <comment xml:lang="be@latin">licenzijnyja ŭmovy</comment>
- <comment xml:lang="bg">Лицензни условия</comment>
- <comment xml:lang="ca">condicions de llicència</comment>
- <comment xml:lang="cs">licenční podmínky</comment>
- <comment xml:lang="da">licensbetingelser</comment>
- <comment xml:lang="de">Lizenzbedingungen</comment>
- <comment xml:lang="el">Όροι άδειας</comment>
- <comment xml:lang="en_GB">licence terms</comment>
- <comment xml:lang="es">términos de licencia</comment>
- <comment xml:lang="eu">lizentzia baldintzak</comment>
- <comment xml:lang="fi">lisenssiehdot</comment>
- <comment xml:lang="fo">loyvistreytir</comment>
- <comment xml:lang="fr">termes de licence</comment>
- <comment xml:lang="ga">téarmaí ceadúnais</comment>
- <comment xml:lang="gl">termos de licenza</comment>
- <comment xml:lang="he">תנאי רישיון</comment>
- <comment xml:lang="hr">Uvjeti licence</comment>
- <comment xml:lang="hu">licencfeltételek</comment>
- <comment xml:lang="ia">Conditiones de licentia</comment>
- <comment xml:lang="id">persyaratan lisensi</comment>
- <comment xml:lang="it">Termini di licenza</comment>
- <comment xml:lang="ja">ソフトウェアライセンス条項</comment>
- <comment xml:lang="kk">лицензиялық келісімі</comment>
- <comment xml:lang="ko">라이선스 조항</comment>
- <comment xml:lang="lt">licencijos sąlygos</comment>
- <comment xml:lang="lv">licences nosacījumi</comment>
- <comment xml:lang="nb">lisensbestemmelser</comment>
- <comment xml:lang="nl">licentievoorwaarden</comment>
- <comment xml:lang="nn">lisensvilkår</comment>
- <comment xml:lang="oc">tèrmes de licéncia</comment>
- <comment xml:lang="pl">Warunki licencji</comment>
- <comment xml:lang="pt">termos de licença</comment>
- <comment xml:lang="pt_BR">Termos de licença</comment>
- <comment xml:lang="ro">termeni de licență</comment>
+ <comment>License terms</comment>
+ <comment xml:lang="uk">умови ліцензування</comment>
+ <comment xml:lang="sv">Licensvillkor</comment>
<comment xml:lang="ru">Лицензионное соглашение</comment>
- <comment xml:lang="sk">Licenčné podmienky</comment>
- <comment xml:lang="sl">pogoji in dovoljenja uporabe</comment>
- <comment xml:lang="sq">Kushte liçence</comment>
- <comment xml:lang="sr">услови коришћења</comment>
- <comment xml:lang="sv">licensvillkor</comment>
- <comment xml:lang="tr">lisans koşulları</comment>
- <comment xml:lang="uk">ліцензійні умови</comment>
- <comment xml:lang="vi">điều kiện giấy phép</comment>
- <comment xml:lang="zh_CN">软件许可条款</comment>
- <comment xml:lang="zh_TW">授權條款</comment>
+ <comment xml:lang="pl">Warunki licencji</comment>
+ <comment xml:lang="ja">利用許諾</comment>
+ <comment xml:lang="it">Termini di licenza</comment>
+ <comment xml:lang="gl">Termos de licenza</comment>
+ <comment xml:lang="eu">Lizentziaren terminoak</comment>
+ <comment xml:lang="es">términos de licencia</comment>
+ <comment xml:lang="de">Lizenzbedingungen</comment>
+ <comment xml:lang="be">умовы карыстання</comment>
<sub-class-of type="text/plain"/>
<glob pattern="COPYING"/>
</mime-type>
<mime-type type="text/x-credits">
- <comment>author credits</comment>
- <comment xml:lang="ar">شكر وتقدير المؤلف</comment>
- <comment xml:lang="ast">creitos del autor</comment>
- <comment xml:lang="be@latin">zasłuhi aŭtara</comment>
- <comment xml:lang="bg">Благодарности към авторите</comment>
- <comment xml:lang="ca">atribucions d'autor</comment>
- <comment xml:lang="cs">autorské zásluhy</comment>
- <comment xml:lang="da">bidragydere</comment>
- <comment xml:lang="de">Autorendanksagung</comment>
- <comment xml:lang="el">Μνεία συγγραφέων</comment>
- <comment xml:lang="en_GB">author credits</comment>
- <comment xml:lang="es">reconocimiento de autoría</comment>
- <comment xml:lang="fi">tekijöiden kiitokset</comment>
- <comment xml:lang="fo">høvundaheiður</comment>
- <comment xml:lang="fr">remerciements</comment>
- <comment xml:lang="ga">admhálacha údar</comment>
- <comment xml:lang="gl">créditos de autor</comment>
- <comment xml:lang="he">קרדיטים של היוצר</comment>
- <comment xml:lang="hr">Zasluge autora</comment>
- <comment xml:lang="hu">szerzők listája</comment>
- <comment xml:lang="ia">Recognoscentia de autores</comment>
- <comment xml:lang="id">kredit penulis</comment>
- <comment xml:lang="it">Riconoscimenti autori</comment>
- <comment xml:lang="ja">ソフトウェア作者クレジット</comment>
- <comment xml:lang="kk">бағдарлама авторлары</comment>
- <comment xml:lang="ko">작성자 정보</comment>
- <comment xml:lang="lt">padėkos autoriams</comment>
- <comment xml:lang="lv">veidotāji</comment>
- <comment xml:lang="nb">liste med bidragsytere</comment>
- <comment xml:lang="nl">auteursinformatie</comment>
- <comment xml:lang="nn">forfattarliste</comment>
- <comment xml:lang="oc">mercejaments</comment>
- <comment xml:lang="pl">Podziękowania autorów programu</comment>
- <comment xml:lang="pt">créditos de autor</comment>
- <comment xml:lang="pt_BR">Créditos do autor</comment>
- <comment xml:lang="ro">mulțumiri autori</comment>
+ <comment>Author credits</comment>
+ <comment xml:lang="uk">подяки авторам</comment>
+ <comment xml:lang="sv">Författarlista</comment>
<comment xml:lang="ru">Авторы программы</comment>
- <comment xml:lang="sk">Autorské zásluhy</comment>
- <comment xml:lang="sl">avtorske zasluge</comment>
- <comment xml:lang="sq">Kreditë e autorëve</comment>
- <comment xml:lang="sr">заслуге аутора</comment>
- <comment xml:lang="sv">författarlista</comment>
- <comment xml:lang="tr">yazar bilgileri</comment>
- <comment xml:lang="uk">подяки авторам програми</comment>
- <comment xml:lang="vi">công trạng tác giả</comment>
- <comment xml:lang="zh_CN">软件作者致谢</comment>
- <comment xml:lang="zh_TW">作者致謝名單</comment>
+ <comment xml:lang="pl">Podziękowania autorów programu</comment>
+ <comment xml:lang="it">Riconoscimenti autori</comment>
+ <comment xml:lang="gl">Créditos de autor</comment>
+ <comment xml:lang="eu">Egile-kredituak</comment>
+ <comment xml:lang="es">créditos de autoría</comment>
+ <comment xml:lang="de">Autorendanksagung</comment>
+ <comment xml:lang="be">звесткі пра аўтараў</comment>
<sub-class-of type="text/plain"/>
<glob pattern="CREDITS"/>
</mime-type>
<mime-type type="text/x-csrc">
<comment>C source code</comment>
- <comment xml:lang="ar">شفرة مصدر سي</comment>
- <comment xml:lang="be@latin">Kryničny kod C</comment>
- <comment xml:lang="bg">Изходен код — C</comment>
- <comment xml:lang="ca">codi font en C</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce C</comment>
- <comment xml:lang="da">C-kildekode</comment>
- <comment xml:lang="de">C-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας C</comment>
- <comment xml:lang="en_GB">C source code</comment>
- <comment xml:lang="eo">C-fontkodo</comment>
- <comment xml:lang="es">código fuente en C</comment>
- <comment xml:lang="eu">C iturburu-kodea</comment>
- <comment xml:lang="fi">C-lähdekoodi</comment>
- <comment xml:lang="fo">C keldukota</comment>
- <comment xml:lang="fr">code source C</comment>
- <comment xml:lang="ga">cód foinseach C</comment>
- <comment xml:lang="gl">código fonte en C</comment>
- <comment xml:lang="he">קוד מקור של C</comment>
- <comment xml:lang="hr">C izvorni kôd</comment>
- <comment xml:lang="hu">C-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte C</comment>
- <comment xml:lang="id">Kode sumber C</comment>
- <comment xml:lang="it">Codice sorgente C</comment>
- <comment xml:lang="ja">C ソースコード</comment>
- <comment xml:lang="ka">C-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">C бастапқы коды</comment>
- <comment xml:lang="ko">C 소스 코드</comment>
- <comment xml:lang="lt">C pradinis kodas</comment>
- <comment xml:lang="lv">C pirmkods</comment>
- <comment xml:lang="ms">Kod sumber C</comment>
- <comment xml:lang="nb">C-kildekode</comment>
- <comment xml:lang="nl">C-broncode</comment>
- <comment xml:lang="nn">C-kjeldekode</comment>
- <comment xml:lang="oc">còde font C</comment>
- <comment xml:lang="pl">Kod źródłowy C</comment>
- <comment xml:lang="pt">código origem C</comment>
- <comment xml:lang="pt_BR">Código-fonte C</comment>
- <comment xml:lang="ro">Cod sursă C</comment>
- <comment xml:lang="ru">Исходный код C</comment>
- <comment xml:lang="sk">Zdrojový kód jazyka C</comment>
- <comment xml:lang="sl">Datoteka izvorne kode C</comment>
- <comment xml:lang="sq">Kod burues C</comment>
- <comment xml:lang="sr">Ц изворни ко̂д</comment>
- <comment xml:lang="sv">C-källkod</comment>
- <comment xml:lang="tr">C kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою C</comment>
- <comment xml:lang="vi">Mã nguồn C</comment>
- <comment xml:lang="zh_CN">C 源代码</comment>
<comment xml:lang="zh_TW">C 源碼</comment>
+ <comment xml:lang="zh_CN">C 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn C</comment>
+ <comment xml:lang="uk">початковий код мовою C</comment>
+ <comment xml:lang="tr">C kaynak kodu</comment>
+ <comment xml:lang="sv">C-källkod</comment>
+ <comment xml:lang="sr">Ц изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim C</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode C</comment>
+ <comment xml:lang="si">C මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód jazyka C</comment>
+ <comment xml:lang="ru">Исходный код C</comment>
+ <comment xml:lang="ro">Cod sursă C</comment>
+ <comment xml:lang="pt_BR">Código-fonte C</comment>
+ <comment xml:lang="pt">código origem C</comment>
+ <comment xml:lang="pl">Kod źródłowy C</comment>
+ <comment xml:lang="oc">còde font C</comment>
+ <comment xml:lang="nn">C-kjeldekode</comment>
+ <comment xml:lang="nl">C-broncode</comment>
+ <comment xml:lang="nb">C-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber C</comment>
+ <comment xml:lang="lv">C pirmkods</comment>
+ <comment xml:lang="lt">C pradinis kodas</comment>
+ <comment xml:lang="ko">C 소스 코드</comment>
+ <comment xml:lang="kk">C бастапқы коды</comment>
+ <comment xml:lang="ka">C-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">C ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente C</comment>
+ <comment xml:lang="is">C frumkóði</comment>
+ <comment xml:lang="id">Kode sumber C</comment>
+ <comment xml:lang="ia">Codice-fonte C</comment>
+ <comment xml:lang="hu">C-forráskód</comment>
+ <comment xml:lang="hr">C izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של C</comment>
+ <comment xml:lang="gl">código fonte en C</comment>
+ <comment xml:lang="ga">cód foinseach C</comment>
+ <comment xml:lang="fur">codiç sorzint C</comment>
+ <comment xml:lang="fr">code source C</comment>
+ <comment xml:lang="fo">C keldukota</comment>
+ <comment xml:lang="fi">C-lähdekoodi</comment>
+ <comment xml:lang="eu">C iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en C</comment>
+ <comment xml:lang="eo">C-fontkodo</comment>
+ <comment xml:lang="en_GB">C source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας C</comment>
+ <comment xml:lang="de">C-Quelltext</comment>
+ <comment xml:lang="da">C-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce C</comment>
+ <comment xml:lang="ca">codi font en C</comment>
+ <comment xml:lang="bg">Изходен код — C</comment>
+ <comment xml:lang="be@latin">Kryničny kod C</comment>
+ <comment xml:lang="be">зыходны код C</comment>
+ <comment xml:lang="ar">شفرة مصدر سي</comment>
+ <comment xml:lang="af">C-bronkode</comment>
<sub-class-of type="text/plain"/>
<alias type="text/x-c"/>
<glob pattern="*.c" case-sensitive="true"/>
<magic priority="30">
- <match value="/*" type="string" offset="0"/>
- <match value="//" type="string" offset="0"/>
- <match value="#include" type="string" offset="0"/>
+ <match type="string" value="/*" offset="0"/>
+ <match type="string" value="//" offset="0"/>
+ <match type="string" value="#include" offset="0"/>
</magic>
</mime-type>
<mime-type type="text/x-csharp">
<comment>C# source code</comment>
- <comment xml:lang="ar">شفرة مصدر سي#</comment>
- <comment xml:lang="be@latin">Kryničny kod C#</comment>
- <comment xml:lang="bg">Изходен код — C#</comment>
- <comment xml:lang="ca">codi font en C#</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce C#</comment>
- <comment xml:lang="da">C#-kildekode</comment>
- <comment xml:lang="de">C#-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας C#</comment>
- <comment xml:lang="en_GB">C# source code</comment>
- <comment xml:lang="eo">C#-fontkodo</comment>
- <comment xml:lang="es">código fuente en C#</comment>
- <comment xml:lang="eu">C# iturburu-kodea</comment>
- <comment xml:lang="fi">C#-lähdekoodi</comment>
- <comment xml:lang="fo">C# keldukota</comment>
- <comment xml:lang="fr">code source C#</comment>
- <comment xml:lang="ga">cód foinseach C#</comment>
- <comment xml:lang="gl">código fonte en C#</comment>
- <comment xml:lang="he">קוד מקור של C#‎</comment>
- <comment xml:lang="hr">C# izvorni kôd</comment>
- <comment xml:lang="hu">C#-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte C#</comment>
- <comment xml:lang="id">Kode sumber C#</comment>
- <comment xml:lang="it">Codice sorgente C#</comment>
- <comment xml:lang="ja">C# ソースコード</comment>
- <comment xml:lang="ka">C#-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">C# бастапқы коды</comment>
- <comment xml:lang="ko">C# 소스 코드</comment>
- <comment xml:lang="lt">C# pradinis kodas</comment>
- <comment xml:lang="lv">C# pirmkods</comment>
- <comment xml:lang="ms">Kod sumber C#</comment>
- <comment xml:lang="nb">C#-kildekode</comment>
- <comment xml:lang="nl">C#-broncode</comment>
- <comment xml:lang="nn">C#-kjeldekode</comment>
- <comment xml:lang="oc">còde font C#</comment>
- <comment xml:lang="pl">Kod źródłowy C#</comment>
- <comment xml:lang="pt">código origem C#</comment>
- <comment xml:lang="pt_BR">Código-fonte C#</comment>
- <comment xml:lang="ro">Cod sursă C#</comment>
- <comment xml:lang="ru">Исходный код C#</comment>
- <comment xml:lang="sk">Zdrojový kód jazyka C#</comment>
- <comment xml:lang="sl">Datoteka izvorne kode C#</comment>
- <comment xml:lang="sq">Kod burues C#</comment>
- <comment xml:lang="sr">Ц# изворни ко̂д</comment>
- <comment xml:lang="sv">C#-källkod</comment>
- <comment xml:lang="tr">C# kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою C#</comment>
- <comment xml:lang="vi">Mã nguồn C#</comment>
- <comment xml:lang="zh_CN">C# 源代码</comment>
<comment xml:lang="zh_TW">C# 源碼</comment>
+ <comment xml:lang="zh_CN">C# 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn C#</comment>
+ <comment xml:lang="uk">початковий код мовою C#</comment>
+ <comment xml:lang="tr">C# kaynak kodu</comment>
+ <comment xml:lang="sv">C#-källkod</comment>
+ <comment xml:lang="sr">Ц# изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim C#</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode C#</comment>
+ <comment xml:lang="si">C# මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód jazyka C#</comment>
+ <comment xml:lang="ru">Исходный код C#</comment>
+ <comment xml:lang="ro">Cod sursă C#</comment>
+ <comment xml:lang="pt_BR">Código-fonte C#</comment>
+ <comment xml:lang="pt">código origem C#</comment>
+ <comment xml:lang="pl">Kod źródłowy C#</comment>
+ <comment xml:lang="oc">còde font C#</comment>
+ <comment xml:lang="nn">C#-kjeldekode</comment>
+ <comment xml:lang="nl">C#-broncode</comment>
+ <comment xml:lang="nb">C#-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber C#</comment>
+ <comment xml:lang="lv">C# pirmkods</comment>
+ <comment xml:lang="lt">C# pradinis kodas</comment>
+ <comment xml:lang="ko">C# 소스 코드</comment>
+ <comment xml:lang="kk">C# бастапқы коды</comment>
+ <comment xml:lang="ka">C#-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">C# ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente C#</comment>
+ <comment xml:lang="is">C# frumkóði</comment>
+ <comment xml:lang="id">Kode sumber C#</comment>
+ <comment xml:lang="ia">Codice-fonte C#</comment>
+ <comment xml:lang="hu">C#-forráskód</comment>
+ <comment xml:lang="hr">C# izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של C#‎</comment>
+ <comment xml:lang="gl">código fonte en C#</comment>
+ <comment xml:lang="ga">cód foinseach C#</comment>
+ <comment xml:lang="fur">codiç sorzint C#</comment>
+ <comment xml:lang="fr">code source C#</comment>
+ <comment xml:lang="fo">C# keldukota</comment>
+ <comment xml:lang="fi">C#-lähdekoodi</comment>
+ <comment xml:lang="eu">C# iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en C#</comment>
+ <comment xml:lang="eo">C#-fontkodo</comment>
+ <comment xml:lang="en_GB">C# source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας C#</comment>
+ <comment xml:lang="de">C#-Quelltext</comment>
+ <comment xml:lang="da">C#-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce C#</comment>
+ <comment xml:lang="ca">codi font en C#</comment>
+ <comment xml:lang="bg">Изходен код — C#</comment>
+ <comment xml:lang="be@latin">Kryničny kod C#</comment>
+ <comment xml:lang="be">зыходны код C#</comment>
+ <comment xml:lang="ar">شفرة مصدر سي#</comment>
+ <comment xml:lang="af">C#-bronkode</comment>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.cs"/>
</mime-type>
<mime-type type="text/x-vala">
<comment>Vala source code</comment>
- <comment xml:lang="ar">شفرة مصدر Vala</comment>
- <comment xml:lang="be@latin">Kryničny kod Vala</comment>
- <comment xml:lang="bg">Изходен код — Vala</comment>
- <comment xml:lang="ca">codi font en Vala</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Vala</comment>
- <comment xml:lang="da">Valakildekode</comment>
- <comment xml:lang="de">Vala-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Vala</comment>
- <comment xml:lang="en_GB">Vala source code</comment>
- <comment xml:lang="eo">Vala-fontkodo</comment>
- <comment xml:lang="es">código fuente en Vala</comment>
- <comment xml:lang="eu">Vala iturburu-kodea</comment>
- <comment xml:lang="fi">Vala-lähdekoodi</comment>
- <comment xml:lang="fo">Vala keldukota</comment>
- <comment xml:lang="fr">code source Vala</comment>
- <comment xml:lang="ga">cód foinseach Vala</comment>
- <comment xml:lang="gl">código fonte en Vala</comment>
- <comment xml:lang="he">קוד מקור של Vala</comment>
- <comment xml:lang="hr">Vala izvorni kôd</comment>
- <comment xml:lang="hu">Vala forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Vala</comment>
- <comment xml:lang="id">Kode sumber Vala</comment>
- <comment xml:lang="it">Codice sorgente Vala</comment>
- <comment xml:lang="ja">Vala ソースコード</comment>
- <comment xml:lang="kk">Vala бастапқы коды</comment>
- <comment xml:lang="ko">Vala 소스 코드</comment>
- <comment xml:lang="lt">Vala pradinis kodas</comment>
- <comment xml:lang="lv">Vala pirmkods</comment>
- <comment xml:lang="nb">Vala-kildekode</comment>
- <comment xml:lang="nl">Vala-broncode</comment>
- <comment xml:lang="nn">Vala-kjeldekode</comment>
- <comment xml:lang="oc">còde font Vala</comment>
- <comment xml:lang="pl">Kod źródłowy Vala</comment>
- <comment xml:lang="pt">código origem Vala</comment>
- <comment xml:lang="pt_BR">Código-fonte Vala</comment>
- <comment xml:lang="ro">Cod sursă Vala</comment>
- <comment xml:lang="ru">Исходный код Vala</comment>
- <comment xml:lang="sk">Zdrojový kód Vala</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Vala</comment>
- <comment xml:lang="sq">Kod burues Vala</comment>
- <comment xml:lang="sr">Вала изворни ко̂д</comment>
- <comment xml:lang="sv">Vala-källkod</comment>
- <comment xml:lang="tr">Vala kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Vala</comment>
- <comment xml:lang="vi">Mã nguồn Vala</comment>
- <comment xml:lang="zh_CN">Vala 源代码</comment>
<comment xml:lang="zh_TW">Vala 源碼</comment>
+ <comment xml:lang="zh_CN">Vala 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Vala</comment>
+ <comment xml:lang="uk">початковий код мовою Vala</comment>
+ <comment xml:lang="tr">Vala kaynak kodu</comment>
+ <comment xml:lang="sv">Vala-källkod</comment>
+ <comment xml:lang="sr">Вала изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Vala</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Vala</comment>
+ <comment xml:lang="si">වාල මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Vala</comment>
+ <comment xml:lang="ru">Исходный код Vala</comment>
+ <comment xml:lang="ro">Cod sursă Vala</comment>
+ <comment xml:lang="pt_BR">Código-fonte Vala</comment>
+ <comment xml:lang="pt">código origem Vala</comment>
+ <comment xml:lang="pl">Kod źródłowy Vala</comment>
+ <comment xml:lang="oc">còde font Vala</comment>
+ <comment xml:lang="nn">Vala-kjeldekode</comment>
+ <comment xml:lang="nl">Vala-broncode</comment>
+ <comment xml:lang="nb">Vala-kildekode</comment>
+ <comment xml:lang="lv">Vala pirmkods</comment>
+ <comment xml:lang="lt">Vala pradinis kodas</comment>
+ <comment xml:lang="ko">Vala 소스 코드</comment>
+ <comment xml:lang="kk">Vala бастапқы коды</comment>
+ <comment xml:lang="ja">Vala ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Vala</comment>
+ <comment xml:lang="is">Vala frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Vala</comment>
+ <comment xml:lang="ia">Codice-fonte Vala</comment>
+ <comment xml:lang="hu">Vala forráskód</comment>
+ <comment xml:lang="hr">Vala izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Vala</comment>
+ <comment xml:lang="gl">código fonte en Vala</comment>
+ <comment xml:lang="ga">cód foinseach Vala</comment>
+ <comment xml:lang="fur">codiç sorzint Vala</comment>
+ <comment xml:lang="fr">code source Vala</comment>
+ <comment xml:lang="fo">Vala keldukota</comment>
+ <comment xml:lang="fi">Vala-lähdekoodi</comment>
+ <comment xml:lang="eu">Vala iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Vala</comment>
+ <comment xml:lang="eo">Vala-fontkodo</comment>
+ <comment xml:lang="en_GB">Vala source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Vala</comment>
+ <comment xml:lang="de">Vala-Quelltext</comment>
+ <comment xml:lang="da">Vala-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Vala</comment>
+ <comment xml:lang="ca">codi font en Vala</comment>
+ <comment xml:lang="bg">Изходен код — Vala</comment>
+ <comment xml:lang="be@latin">Kryničny kod Vala</comment>
+ <comment xml:lang="be">зыходны код Vala</comment>
+ <comment xml:lang="ar">شفرة مصدر Vala</comment>
+ <comment xml:lang="af">Vala-bronkode</comment>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.vala"/>
<glob pattern="*.vapi"/>
</mime-type>
<mime-type type="text/x-ooc">
<comment>OOC source code</comment>
- <comment xml:lang="bg">Изходен код — OOC</comment>
- <comment xml:lang="ca">codi font en OOC</comment>
- <comment xml:lang="cs">zdrojový kód OOC</comment>
- <comment xml:lang="da">OOC-kildekode</comment>
- <comment xml:lang="de">OOC-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας OOC</comment>
- <comment xml:lang="en_GB">OOC source code</comment>
- <comment xml:lang="eo">OOC-fontkodo</comment>
- <comment xml:lang="es">código fuente en OOC</comment>
- <comment xml:lang="eu">OOC iturburu-kodea</comment>
- <comment xml:lang="fi">OOC-lähdekoodi</comment>
- <comment xml:lang="fr">source code OOC</comment>
- <comment xml:lang="ga">cód foinseach OOC</comment>
- <comment xml:lang="gl">código fonte de OOC</comment>
- <comment xml:lang="he">קוד מקור של OOC</comment>
- <comment xml:lang="hr">OOC izvorni kôd</comment>
- <comment xml:lang="hu">OOC forráskód</comment>
- <comment xml:lang="ia">Codice-fonte OCC</comment>
- <comment xml:lang="id">Kode sumber OOC</comment>
- <comment xml:lang="it">Codice sorgente OOC</comment>
- <comment xml:lang="ja">OOC ソースコード</comment>
- <comment xml:lang="ka">OOC-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">OOC бастапқы коды</comment>
- <comment xml:lang="ko">OOC 소스 코드</comment>
- <comment xml:lang="lv">OOC pirmkods</comment>
- <comment xml:lang="nl">OOC broncode</comment>
- <comment xml:lang="oc">font còde OOC</comment>
- <comment xml:lang="pl">Kod źródłowy OOC</comment>
- <comment xml:lang="pt">código origem OOC</comment>
- <comment xml:lang="pt_BR">Código-fonte OOC</comment>
- <comment xml:lang="ru">Исходный код OOC</comment>
- <comment xml:lang="sk">Zdrojový kód OOC</comment>
- <comment xml:lang="sl">Izvorna koda OOC</comment>
- <comment xml:lang="sr">ООЦ изворни ко̂д</comment>
- <comment xml:lang="sv">OOC-källkod</comment>
- <comment xml:lang="tr">OOC kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою OOC</comment>
- <comment xml:lang="zh_CN">OOC 源代码</comment>
<comment xml:lang="zh_TW">OOC 源碼</comment>
+ <comment xml:lang="zh_CN">OOC 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою OOC</comment>
+ <comment xml:lang="tr">OOC kaynak kodu</comment>
+ <comment xml:lang="sv">OOC-källkod</comment>
+ <comment xml:lang="sr">ООЦ изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim OOC</comment>
+ <comment xml:lang="sl">Izvorna koda OOC</comment>
+ <comment xml:lang="si">OOC මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód OOC</comment>
+ <comment xml:lang="ru">Исходный код OOC</comment>
+ <comment xml:lang="pt_BR">Código-fonte OOC</comment>
+ <comment xml:lang="pt">código origem OOC</comment>
+ <comment xml:lang="pl">Kod źródłowy OOC</comment>
+ <comment xml:lang="oc">font còde OOC</comment>
+ <comment xml:lang="nl">OOC-broncode</comment>
+ <comment xml:lang="lv">OOC pirmkods</comment>
+ <comment xml:lang="ko">OOC 소스 코드</comment>
+ <comment xml:lang="kk">OOC бастапқы коды</comment>
+ <comment xml:lang="ka">OOC-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">OOC ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente OOC</comment>
+ <comment xml:lang="is">OOC frumkóði</comment>
+ <comment xml:lang="id">Kode sumber OOC</comment>
+ <comment xml:lang="ia">Codice-fonte OCC</comment>
+ <comment xml:lang="hu">OOC forráskód</comment>
+ <comment xml:lang="hr">OOC izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של OOC</comment>
+ <comment xml:lang="gl">código fonte de OOC</comment>
+ <comment xml:lang="ga">cód foinseach OOC</comment>
+ <comment xml:lang="fur">codiç sorzint OOC</comment>
+ <comment xml:lang="fr">source code OOC</comment>
+ <comment xml:lang="fi">OOC-lähdekoodi</comment>
+ <comment xml:lang="eu">OOC iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en OOC</comment>
+ <comment xml:lang="eo">OOC-fontkodo</comment>
+ <comment xml:lang="en_GB">OOC source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας OOC</comment>
+ <comment xml:lang="de">OOC-Quelltext</comment>
+ <comment xml:lang="da">OOC-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód OOC</comment>
+ <comment xml:lang="ca">codi font en OOC</comment>
+ <comment xml:lang="bg">Изходен код — OOC</comment>
+ <comment xml:lang="be">зыходны код OOC</comment>
+ <comment xml:lang="ar">شفرة مصدر OOC</comment>
+ <comment xml:lang="af">OOC-bronkode</comment>
<acronym>OOC</acronym>
<expanded-acronym>Out Of Class</expanded-acronym>
<sub-class-of type="text/x-csrc"/>
@@ -33700,57 +35767,62 @@
</mime-type>
<mime-type type="text/x-dcl">
<comment>DCL script</comment>
- <comment xml:lang="ar">سكربت DCL</comment>
- <comment xml:lang="az">DCL skripti</comment>
- <comment xml:lang="be@latin">Skrypt DCL</comment>
- <comment xml:lang="bg">Скрипт — DCL</comment>
- <comment xml:lang="ca">script DCL</comment>
- <comment xml:lang="cs">skript DCL</comment>
- <comment xml:lang="cy">Sgript DCL</comment>
- <comment xml:lang="da">DCL-program</comment>
- <comment xml:lang="de">DCL-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών DCL</comment>
- <comment xml:lang="en_GB">DCL script</comment>
- <comment xml:lang="eo">DCL-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en DCL</comment>
- <comment xml:lang="eu">DCL script-a</comment>
- <comment xml:lang="fi">DCL-komentotiedosto</comment>
- <comment xml:lang="fo">DCL boðrøð</comment>
- <comment xml:lang="fr">script DCL</comment>
- <comment xml:lang="ga">script DCL</comment>
- <comment xml:lang="gl">script de DCL</comment>
- <comment xml:lang="he">תסריט DCL</comment>
- <comment xml:lang="hr">DCL skripta</comment>
- <comment xml:lang="hu">DCL-parancsfájl</comment>
- <comment xml:lang="ia">Script DCL</comment>
- <comment xml:lang="id">Skrip DCL</comment>
- <comment xml:lang="it">Script DCL</comment>
- <comment xml:lang="ja">DCL スクリプト</comment>
- <comment xml:lang="ka">DCL სცენარი</comment>
- <comment xml:lang="kk">DCL сценарийі</comment>
- <comment xml:lang="ko">DCL 스크립트</comment>
- <comment xml:lang="lt">DCL scenarijus</comment>
- <comment xml:lang="lv">DCL skripts</comment>
- <comment xml:lang="ms">Skrip DCL</comment>
- <comment xml:lang="nb">DCL-skript</comment>
- <comment xml:lang="nl">DCL-script</comment>
- <comment xml:lang="nn">DCL-skript</comment>
- <comment xml:lang="oc">escript DCL</comment>
- <comment xml:lang="pl">Skrypt DCL</comment>
- <comment xml:lang="pt">script DCL</comment>
- <comment xml:lang="pt_BR">Script DCL</comment>
- <comment xml:lang="ro">Script DCL</comment>
- <comment xml:lang="ru">Сценарий DCL</comment>
- <comment xml:lang="sk">Skript DCL</comment>
- <comment xml:lang="sl">Skriptna datoteka DCL</comment>
- <comment xml:lang="sq">Script DCL</comment>
- <comment xml:lang="sr">ДЦЛ скрипта</comment>
- <comment xml:lang="sv">DCL-skript</comment>
- <comment xml:lang="tr">DCL betiği</comment>
- <comment xml:lang="uk">скрипт DCL</comment>
- <comment xml:lang="vi">Văn lệnh DCL</comment>
- <comment xml:lang="zh_CN">DCL 脚本</comment>
<comment xml:lang="zh_TW">DCL 指令稿</comment>
+ <comment xml:lang="zh_CN">DCL 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh DCL</comment>
+ <comment xml:lang="uk">скрипт DCL</comment>
+ <comment xml:lang="tr">DCL betiği</comment>
+ <comment xml:lang="sv">DCL-skript</comment>
+ <comment xml:lang="sr">ДЦЛ скрипта</comment>
+ <comment xml:lang="sq">programth DCL</comment>
+ <comment xml:lang="sl">Skriptna datoteka DCL</comment>
+ <comment xml:lang="si">DCL පිටපත</comment>
+ <comment xml:lang="sk">Skript DCL</comment>
+ <comment xml:lang="ru">Сценарий DCL</comment>
+ <comment xml:lang="ro">Script DCL</comment>
+ <comment xml:lang="pt_BR">Script DCL</comment>
+ <comment xml:lang="pt">script DCL</comment>
+ <comment xml:lang="pl">Skrypt DCL</comment>
+ <comment xml:lang="oc">escript DCL</comment>
+ <comment xml:lang="nn">DCL-skript</comment>
+ <comment xml:lang="nl">DCL-script</comment>
+ <comment xml:lang="nb">DCL-skript</comment>
+ <comment xml:lang="ms">Skrip DCL</comment>
+ <comment xml:lang="lv">DCL skripts</comment>
+ <comment xml:lang="lt">DCL scenarijus</comment>
+ <comment xml:lang="ko">DCL 스크립트</comment>
+ <comment xml:lang="kk">DCL сценарийі</comment>
+ <comment xml:lang="ka">DCL სცენარი</comment>
+ <comment xml:lang="ja">DCL スクリプト</comment>
+ <comment xml:lang="it">Script DCL</comment>
+ <comment xml:lang="is">DCL skrifta</comment>
+ <comment xml:lang="id">Skrip DCL</comment>
+ <comment xml:lang="ia">Script DCL</comment>
+ <comment xml:lang="hu">DCL-parancsfájl</comment>
+ <comment xml:lang="hr">DCL skripta</comment>
+ <comment xml:lang="he">תסריט DCL</comment>
+ <comment xml:lang="gl">script de DCL</comment>
+ <comment xml:lang="ga">script DCL</comment>
+ <comment xml:lang="fur">script DCL</comment>
+ <comment xml:lang="fr">script DCL</comment>
+ <comment xml:lang="fo">DCL boðrøð</comment>
+ <comment xml:lang="fi">DCL-komentotiedosto</comment>
+ <comment xml:lang="eu">DCL script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en DCL</comment>
+ <comment xml:lang="eo">DCL-skripto</comment>
+ <comment xml:lang="en_GB">DCL script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών DCL</comment>
+ <comment xml:lang="de">DCL-Skript</comment>
+ <comment xml:lang="da">DCL-program</comment>
+ <comment xml:lang="cy">Sgript DCL</comment>
+ <comment xml:lang="cs">skript DCL</comment>
+ <comment xml:lang="ca">script DCL</comment>
+ <comment xml:lang="bg">Скрипт — DCL</comment>
+ <comment xml:lang="be@latin">Skrypt DCL</comment>
+ <comment xml:lang="be">скрыпт DCL</comment>
+ <comment xml:lang="az">DCL skripti</comment>
+ <comment xml:lang="ar">سكربت DCL</comment>
+ <comment xml:lang="af">DCL-skrip</comment>
<acronym>DCL</acronym>
<expanded-acronym>Data Conversion Laboratory</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -33758,58 +35830,63 @@
</mime-type>
<mime-type type="text/x-dsl">
<comment>DSSSL document</comment>
- <comment xml:lang="ar">مستند DSSSL</comment>
- <comment xml:lang="ast">Documentu DSSSL</comment>
- <comment xml:lang="az">DSSSL sənədi</comment>
- <comment xml:lang="be@latin">Dakument DSSSL</comment>
- <comment xml:lang="bg">Документ — DSSSL</comment>
- <comment xml:lang="ca">document DSSSL</comment>
- <comment xml:lang="cs">dokument DSSSL</comment>
- <comment xml:lang="cy">Dogfen DSSSL</comment>
- <comment xml:lang="da">DSSSL-dokument</comment>
- <comment xml:lang="de">DSSSL-Dokument</comment>
- <comment xml:lang="el">Έγγραφο DSSSL</comment>
- <comment xml:lang="en_GB">DSSSL document</comment>
- <comment xml:lang="eo">DSSSL-dokumento</comment>
- <comment xml:lang="es">documento DSSSL</comment>
- <comment xml:lang="eu">DSSSL dokumentua</comment>
- <comment xml:lang="fi">DSSSL-asiakirja</comment>
- <comment xml:lang="fo">DSSSL skjal</comment>
- <comment xml:lang="fr">document DSSSL</comment>
- <comment xml:lang="ga">cáipéis DSSSL</comment>
- <comment xml:lang="gl">documento DSSSL</comment>
- <comment xml:lang="he">מסמך DSSSL</comment>
- <comment xml:lang="hr">DSSSL dokument</comment>
- <comment xml:lang="hu">DSSSL-dokumentum</comment>
- <comment xml:lang="ia">Documento DSSSL</comment>
- <comment xml:lang="id">Dokumen DSSSL</comment>
- <comment xml:lang="it">Documento DSSSL</comment>
- <comment xml:lang="ja">DSSSL ドキュメント</comment>
- <comment xml:lang="ka">DSSSL დოკუმენტი</comment>
- <comment xml:lang="kk">DSSSL құжаты</comment>
- <comment xml:lang="ko">DSSSL 문서</comment>
- <comment xml:lang="lt">DSSSL dokumentas</comment>
- <comment xml:lang="lv">DSSSL dokuments</comment>
- <comment xml:lang="ms">Dokumen DSSSL</comment>
- <comment xml:lang="nb">DSSSL-dokument</comment>
- <comment xml:lang="nl">DSSSL-document</comment>
- <comment xml:lang="nn">DSSSL-dokument</comment>
- <comment xml:lang="oc">document DSSSL</comment>
- <comment xml:lang="pl">Dokument DSSSL</comment>
- <comment xml:lang="pt">documento DSSSL</comment>
- <comment xml:lang="pt_BR">Documento DSSSL</comment>
- <comment xml:lang="ro">Document DSSSL</comment>
- <comment xml:lang="ru">Документ DSSSL</comment>
- <comment xml:lang="sk">Dokument DSSSL</comment>
- <comment xml:lang="sl">Dokument DSSSL</comment>
- <comment xml:lang="sq">Dokument DSSSL</comment>
- <comment xml:lang="sr">ДСССЛ документ</comment>
- <comment xml:lang="sv">DSSSL-dokument</comment>
- <comment xml:lang="tr">DSSSL belgesi</comment>
- <comment xml:lang="uk">документ DSSSL</comment>
- <comment xml:lang="vi">Tài liệu DSSSL</comment>
- <comment xml:lang="zh_CN">DSSSL 文档</comment>
<comment xml:lang="zh_TW">DSSSL 文件</comment>
+ <comment xml:lang="zh_CN">DSSSL 文档</comment>
+ <comment xml:lang="vi">Tài liệu DSSSL</comment>
+ <comment xml:lang="uk">документ DSSSL</comment>
+ <comment xml:lang="tr">DSSSL belgesi</comment>
+ <comment xml:lang="sv">DSSSL-dokument</comment>
+ <comment xml:lang="sr">ДСССЛ документ</comment>
+ <comment xml:lang="sq">dokument DSSSL</comment>
+ <comment xml:lang="sl">Dokument DSSSL</comment>
+ <comment xml:lang="si">DSSSL ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument DSSSL</comment>
+ <comment xml:lang="ru">Документ DSSSL</comment>
+ <comment xml:lang="ro">Document DSSSL</comment>
+ <comment xml:lang="pt_BR">Documento DSSSL</comment>
+ <comment xml:lang="pt">documento DSSSL</comment>
+ <comment xml:lang="pl">Dokument DSSSL</comment>
+ <comment xml:lang="oc">document DSSSL</comment>
+ <comment xml:lang="nn">DSSSL-dokument</comment>
+ <comment xml:lang="nl">DSSSL-document</comment>
+ <comment xml:lang="nb">DSSSL-dokument</comment>
+ <comment xml:lang="ms">Dokumen DSSSL</comment>
+ <comment xml:lang="lv">DSSSL dokuments</comment>
+ <comment xml:lang="lt">DSSSL dokumentas</comment>
+ <comment xml:lang="ko">DSSSL 문서</comment>
+ <comment xml:lang="kk">DSSSL құжаты</comment>
+ <comment xml:lang="ka">DSSSL დოკუმენტი</comment>
+ <comment xml:lang="ja">DSSSL ドキュメント</comment>
+ <comment xml:lang="it">Documento DSSSL</comment>
+ <comment xml:lang="is">DSSSL skjal</comment>
+ <comment xml:lang="id">Dokumen DSSSL</comment>
+ <comment xml:lang="ia">Documento DSSSL</comment>
+ <comment xml:lang="hu">DSSSL-dokumentum</comment>
+ <comment xml:lang="hr">DSSSL dokument</comment>
+ <comment xml:lang="he">מסמך DSSSL</comment>
+ <comment xml:lang="gl">documento DSSSL</comment>
+ <comment xml:lang="ga">cáipéis DSSSL</comment>
+ <comment xml:lang="fur">document DSSSL</comment>
+ <comment xml:lang="fr">document DSSSL</comment>
+ <comment xml:lang="fo">DSSSL skjal</comment>
+ <comment xml:lang="fi">DSSSL-asiakirja</comment>
+ <comment xml:lang="eu">DSSSL dokumentua</comment>
+ <comment xml:lang="es">documento DSSSL</comment>
+ <comment xml:lang="eo">DSSSL-dokumento</comment>
+ <comment xml:lang="en_GB">DSSSL document</comment>
+ <comment xml:lang="el">Έγγραφο DSSSL</comment>
+ <comment xml:lang="de">DSSSL-Dokument</comment>
+ <comment xml:lang="da">DSSSL-dokument</comment>
+ <comment xml:lang="cy">Dogfen DSSSL</comment>
+ <comment xml:lang="cs">dokument DSSSL</comment>
+ <comment xml:lang="ca">document DSSSL</comment>
+ <comment xml:lang="bg">Документ — DSSSL</comment>
+ <comment xml:lang="be@latin">Dakument DSSSL</comment>
+ <comment xml:lang="be">дакумент DSSSL</comment>
+ <comment xml:lang="az">DSSSL sənədi</comment>
+ <comment xml:lang="ast">Documentu DSSSL</comment>
+ <comment xml:lang="ar">مستند DSSSL</comment>
+ <comment xml:lang="af">DSSSL-dokument</comment>
<acronym>DSSSL</acronym>
<expanded-acronym>Document Style Semantics and Specification Language</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -33817,108 +35894,118 @@
</mime-type>
<mime-type type="text/x-dsrc">
<comment>D source code</comment>
- <comment xml:lang="ar">شفرة مصدر D</comment>
- <comment xml:lang="be@latin">Kryničny kod D</comment>
- <comment xml:lang="bg">Изходен код — D</comment>
- <comment xml:lang="ca">codi font en D</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce D</comment>
- <comment xml:lang="da">D-kildekode</comment>
- <comment xml:lang="de">D-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας D</comment>
- <comment xml:lang="en_GB">D source code</comment>
- <comment xml:lang="eo">D-fontkodo</comment>
- <comment xml:lang="es">código fuente en D</comment>
- <comment xml:lang="eu">D iturburu-kodea</comment>
- <comment xml:lang="fi">D-lähdekoodi</comment>
- <comment xml:lang="fo">D keldukota</comment>
- <comment xml:lang="fr">code source D</comment>
- <comment xml:lang="ga">cód foinseach D</comment>
- <comment xml:lang="gl">código fonte de D</comment>
- <comment xml:lang="he">קוד מקור לשפת D</comment>
- <comment xml:lang="hr">D izvorni kôd</comment>
- <comment xml:lang="hu">D-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte D</comment>
- <comment xml:lang="id">Kode sumber D</comment>
- <comment xml:lang="it">Codice sorgente D</comment>
- <comment xml:lang="ja">D ソースコード</comment>
- <comment xml:lang="ka">D-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">D бастапқы коды</comment>
- <comment xml:lang="ko">D 소스 코드</comment>
- <comment xml:lang="lt">D pradinis kodas</comment>
- <comment xml:lang="lv">D pirmkods</comment>
- <comment xml:lang="nb">D-kildekode</comment>
- <comment xml:lang="nl">D-broncode</comment>
- <comment xml:lang="nn">D-kjeldekode</comment>
- <comment xml:lang="oc">còde font D</comment>
- <comment xml:lang="pl">Kod źródłowy D</comment>
- <comment xml:lang="pt">código origem D</comment>
- <comment xml:lang="pt_BR">Código-fonte D</comment>
- <comment xml:lang="ro">Cod sursă D</comment>
- <comment xml:lang="ru">Исходный код D</comment>
- <comment xml:lang="sk">Zdrojový kód jazyka D</comment>
- <comment xml:lang="sl">Datoteka izvorne kode D</comment>
- <comment xml:lang="sq">Kod burues D</comment>
- <comment xml:lang="sr">Д изворни ко̂д</comment>
- <comment xml:lang="sv">D-källkod</comment>
- <comment xml:lang="tr">D kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою D</comment>
- <comment xml:lang="vi">Mã nguồn D</comment>
- <comment xml:lang="zh_CN">D 源代码</comment>
<comment xml:lang="zh_TW">D 源碼</comment>
+ <comment xml:lang="zh_CN">D 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn D</comment>
+ <comment xml:lang="uk">початковий код мовою D</comment>
+ <comment xml:lang="tr">D kaynak kodu</comment>
+ <comment xml:lang="sv">D-källkod</comment>
+ <comment xml:lang="sr">Д изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim D</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode D</comment>
+ <comment xml:lang="si">D මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód jazyka D</comment>
+ <comment xml:lang="ru">Исходный код D</comment>
+ <comment xml:lang="ro">Cod sursă D</comment>
+ <comment xml:lang="pt_BR">Código-fonte D</comment>
+ <comment xml:lang="pt">código origem D</comment>
+ <comment xml:lang="pl">Kod źródłowy D</comment>
+ <comment xml:lang="oc">còde font D</comment>
+ <comment xml:lang="nn">D-kjeldekode</comment>
+ <comment xml:lang="nl">D-broncode</comment>
+ <comment xml:lang="nb">D-kildekode</comment>
+ <comment xml:lang="lv">D pirmkods</comment>
+ <comment xml:lang="lt">D pradinis kodas</comment>
+ <comment xml:lang="ko">D 소스 코드</comment>
+ <comment xml:lang="kk">D бастапқы коды</comment>
+ <comment xml:lang="ka">D-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">D ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente D</comment>
+ <comment xml:lang="is">D frumkóði</comment>
+ <comment xml:lang="id">Kode sumber D</comment>
+ <comment xml:lang="ia">Codice-fonte D</comment>
+ <comment xml:lang="hu">D-forráskód</comment>
+ <comment xml:lang="hr">D izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור לשפת D</comment>
+ <comment xml:lang="gl">código fonte de D</comment>
+ <comment xml:lang="ga">cód foinseach D</comment>
+ <comment xml:lang="fur">codiç sorzint D</comment>
+ <comment xml:lang="fr">code source D</comment>
+ <comment xml:lang="fo">D keldukota</comment>
+ <comment xml:lang="fi">D-lähdekoodi</comment>
+ <comment xml:lang="eu">D iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en D</comment>
+ <comment xml:lang="eo">D-fontkodo</comment>
+ <comment xml:lang="en_GB">D source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας D</comment>
+ <comment xml:lang="de">D-Quelltext</comment>
+ <comment xml:lang="da">D-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce D</comment>
+ <comment xml:lang="ca">codi font en D</comment>
+ <comment xml:lang="bg">Изходен код — D</comment>
+ <comment xml:lang="be@latin">Kryničny kod D</comment>
+ <comment xml:lang="be">зыходны код D</comment>
+ <comment xml:lang="ar">شفرة مصدر D</comment>
+ <comment xml:lang="af">D-bronkode</comment>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.d"/>
<glob pattern="*.di"/>
</mime-type>
<mime-type type="application/xml-dtd">
<comment>DTD file</comment>
- <comment xml:lang="ar">ملف DTD</comment>
- <comment xml:lang="be@latin">Fajł DTD</comment>
- <comment xml:lang="bg">Документ — DTD</comment>
- <comment xml:lang="ca">fitxer DTD</comment>
- <comment xml:lang="cs">soubor DTD</comment>
- <comment xml:lang="da">DTD-fil</comment>
- <comment xml:lang="de">DTD-Datei</comment>
- <comment xml:lang="el">Αρχείο DTD</comment>
- <comment xml:lang="en_GB">DTD file</comment>
- <comment xml:lang="eo">DTD-dosiero</comment>
- <comment xml:lang="es">archivo DTD</comment>
- <comment xml:lang="eu">DTD fitxategia</comment>
- <comment xml:lang="fi">DTD-tiedosto</comment>
- <comment xml:lang="fo">DTD fíla</comment>
- <comment xml:lang="fr">fichier DTD</comment>
- <comment xml:lang="ga">comhad DTD</comment>
- <comment xml:lang="gl">ficheiro DTD</comment>
- <comment xml:lang="he">מסמך DTD</comment>
- <comment xml:lang="hr">DTD datoteka</comment>
- <comment xml:lang="hu">DTD fájl</comment>
- <comment xml:lang="ia">File DTD</comment>
- <comment xml:lang="id">Berkas DTD</comment>
- <comment xml:lang="it">File DTD</comment>
- <comment xml:lang="ja">DTD ファイル</comment>
- <comment xml:lang="ka">DTD ფაილი</comment>
- <comment xml:lang="kk">DTD файлы</comment>
- <comment xml:lang="ko">DTD 파일</comment>
- <comment xml:lang="lt">DTD failas</comment>
- <comment xml:lang="lv">DTD datne</comment>
- <comment xml:lang="nb">DTD-fil</comment>
- <comment xml:lang="nl">DTD-bestand</comment>
- <comment xml:lang="nn">DTD-fil</comment>
- <comment xml:lang="oc">fichièr DTD</comment>
- <comment xml:lang="pl">Plik DTD</comment>
- <comment xml:lang="pt">ficheiro DTD</comment>
- <comment xml:lang="pt_BR">Arquivo DTD</comment>
- <comment xml:lang="ro">Fișier DTD</comment>
- <comment xml:lang="ru">Файл DTD</comment>
- <comment xml:lang="sk">Súbor DTD</comment>
- <comment xml:lang="sl">Datoteka DTD</comment>
- <comment xml:lang="sq">File DTD</comment>
- <comment xml:lang="sr">ДТД датотека</comment>
- <comment xml:lang="sv">DTD-fil</comment>
- <comment xml:lang="tr">DTD dosyası</comment>
- <comment xml:lang="uk">файл DTD</comment>
- <comment xml:lang="vi">Tập tin DTD</comment>
- <comment xml:lang="zh_CN">DTD 文件</comment>
<comment xml:lang="zh_TW">DTD 檔</comment>
+ <comment xml:lang="zh_CN">DTD 文件</comment>
+ <comment xml:lang="vi">Tập tin DTD</comment>
+ <comment xml:lang="uk">файл DTD</comment>
+ <comment xml:lang="tr">DTD dosyası</comment>
+ <comment xml:lang="sv">DTD-fil</comment>
+ <comment xml:lang="sr">ДТД датотека</comment>
+ <comment xml:lang="sq">kartelë DTD</comment>
+ <comment xml:lang="sl">Datoteka DTD</comment>
+ <comment xml:lang="si">DTD ගොනුව</comment>
+ <comment xml:lang="sk">Súbor DTD</comment>
+ <comment xml:lang="ru">Файл DTD</comment>
+ <comment xml:lang="ro">Fișier DTD</comment>
+ <comment xml:lang="pt_BR">Arquivo DTD</comment>
+ <comment xml:lang="pt">ficheiro DTD</comment>
+ <comment xml:lang="pl">Plik DTD</comment>
+ <comment xml:lang="oc">fichièr DTD</comment>
+ <comment xml:lang="nn">DTD-fil</comment>
+ <comment xml:lang="nl">DTD-bestand</comment>
+ <comment xml:lang="nb">DTD-fil</comment>
+ <comment xml:lang="lv">DTD datne</comment>
+ <comment xml:lang="lt">DTD failas</comment>
+ <comment xml:lang="ko">DTD 파일</comment>
+ <comment xml:lang="kk">DTD файлы</comment>
+ <comment xml:lang="ka">DTD ფაილი</comment>
+ <comment xml:lang="ja">DTD ファイル</comment>
+ <comment xml:lang="it">File DTD</comment>
+ <comment xml:lang="is">DTD-skrá</comment>
+ <comment xml:lang="id">Berkas DTD</comment>
+ <comment xml:lang="ia">File DTD</comment>
+ <comment xml:lang="hu">DTD fájl</comment>
+ <comment xml:lang="hr">DTD datoteka</comment>
+ <comment xml:lang="he">מסמך DTD</comment>
+ <comment xml:lang="gl">ficheiro DTD</comment>
+ <comment xml:lang="ga">comhad DTD</comment>
+ <comment xml:lang="fur">file DTD</comment>
+ <comment xml:lang="fr">fichier DTD</comment>
+ <comment xml:lang="fo">DTD fíla</comment>
+ <comment xml:lang="fi">DTD-tiedosto</comment>
+ <comment xml:lang="eu">DTD fitxategia</comment>
+ <comment xml:lang="es">archivo DTD</comment>
+ <comment xml:lang="eo">DTD-dosiero</comment>
+ <comment xml:lang="en_GB">DTD file</comment>
+ <comment xml:lang="el">Αρχείο DTD</comment>
+ <comment xml:lang="de">DTD-Datei</comment>
+ <comment xml:lang="da">DTD-fil</comment>
+ <comment xml:lang="cs">soubor DTD</comment>
+ <comment xml:lang="ca">fitxer DTD</comment>
+ <comment xml:lang="bg">Документ — DTD</comment>
+ <comment xml:lang="be@latin">Fajł DTD</comment>
+ <comment xml:lang="be">файл DTD</comment>
+ <comment xml:lang="ar">ملف DTD</comment>
+ <comment xml:lang="af">DTD-lêer</comment>
<acronym>DTD</acronym>
<expanded-acronym>Document Type Definition</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -33928,224 +36015,275 @@
</mime-type>
<mime-type type="text/x-eiffel">
<comment>Eiffel source code</comment>
- <comment xml:lang="ar">شفرة مصدر Eiffel</comment>
- <comment xml:lang="be@latin">Kryničny kod Eiffel</comment>
- <comment xml:lang="bg">Изходен код — Eiffel</comment>
- <comment xml:lang="ca">codi font en Eiffel</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Eiffel</comment>
- <comment xml:lang="da">Eiffelkildekode</comment>
- <comment xml:lang="de">Eiffel-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Eiffel</comment>
- <comment xml:lang="en_GB">Eiffel source code</comment>
- <comment xml:lang="eo">Eiffel-fontkodo</comment>
- <comment xml:lang="es">código fuente en Eiffel</comment>
- <comment xml:lang="eu">Eiffel iturburu-kodea</comment>
- <comment xml:lang="fi">Eiffel-lähdekoodi</comment>
- <comment xml:lang="fo">Eiffel keldukota</comment>
- <comment xml:lang="fr">code source Eiffel</comment>
- <comment xml:lang="ga">cód foinseach Eiffel</comment>
- <comment xml:lang="gl">código fone de Eiffel</comment>
- <comment xml:lang="he">קוד מקור של Eiffel</comment>
- <comment xml:lang="hr">Eiffel izvorni kôd</comment>
- <comment xml:lang="hu">Eiffel forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Eiffel</comment>
- <comment xml:lang="id">Kode sumber Eiffel</comment>
- <comment xml:lang="it">Codice sorgente Eiffel</comment>
- <comment xml:lang="ja">Eiffel ソースコード</comment>
- <comment xml:lang="ka">Eiffel-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Eiffel бастапқы коды</comment>
- <comment xml:lang="ko">Eiffel 소스 코드</comment>
- <comment xml:lang="lt">Eiffel pirminis programos tekstas</comment>
- <comment xml:lang="lv">Eiffel pirmkods</comment>
- <comment xml:lang="nb">Eiffel-kildekode</comment>
- <comment xml:lang="nl">Eiffel-broncode</comment>
- <comment xml:lang="nn">Eiffel-kjeldekode</comment>
- <comment xml:lang="oc">còde font Eiffel</comment>
- <comment xml:lang="pl">Kod źródłowy Eiffel</comment>
- <comment xml:lang="pt">código origem Eiffel</comment>
- <comment xml:lang="pt_BR">Código-fonte Eiffel</comment>
- <comment xml:lang="ro">Cod sursă Eiffel</comment>
- <comment xml:lang="ru">Исходный код Eiffel</comment>
- <comment xml:lang="sk">Zdrojový kód Eiffel</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Eiffel</comment>
- <comment xml:lang="sq">Kod burues Eiffel</comment>
- <comment xml:lang="sr">Ајфел изворни ко̂д</comment>
- <comment xml:lang="sv">Eiffel-källkod</comment>
- <comment xml:lang="tr">Eiffel kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Eiffel</comment>
- <comment xml:lang="vi">Mã nguồn Eiffel</comment>
- <comment xml:lang="zh_CN">Eiffel 源代码</comment>
<comment xml:lang="zh_TW">Eiffel 源碼</comment>
+ <comment xml:lang="zh_CN">Eiffel 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Eiffel</comment>
+ <comment xml:lang="uk">початковий код мовою Eiffel</comment>
+ <comment xml:lang="tr">Eiffel kaynak kodu</comment>
+ <comment xml:lang="sv">Eiffel-källkod</comment>
+ <comment xml:lang="sr">Ајфел изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Eiffel</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Eiffel</comment>
+ <comment xml:lang="si">අයිෆල් මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Eiffel</comment>
+ <comment xml:lang="ru">Исходный код Eiffel</comment>
+ <comment xml:lang="ro">Cod sursă Eiffel</comment>
+ <comment xml:lang="pt_BR">Código-fonte Eiffel</comment>
+ <comment xml:lang="pt">código origem Eiffel</comment>
+ <comment xml:lang="pl">Kod źródłowy Eiffel</comment>
+ <comment xml:lang="oc">còde font Eiffel</comment>
+ <comment xml:lang="nn">Eiffel-kjeldekode</comment>
+ <comment xml:lang="nl">Eiffel-broncode</comment>
+ <comment xml:lang="nb">Eiffel-kildekode</comment>
+ <comment xml:lang="lv">Eiffel pirmkods</comment>
+ <comment xml:lang="lt">Eiffel pirminis programos tekstas</comment>
+ <comment xml:lang="ko">Eiffel 소스 코드</comment>
+ <comment xml:lang="kk">Eiffel бастапқы коды</comment>
+ <comment xml:lang="ka">Eiffel-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Eiffel ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Eiffel</comment>
+ <comment xml:lang="is">Eiffel frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Eiffel</comment>
+ <comment xml:lang="ia">Codice-fonte Eiffel</comment>
+ <comment xml:lang="hu">Eiffel forráskód</comment>
+ <comment xml:lang="hr">Eiffel izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Eiffel</comment>
+ <comment xml:lang="gl">código fone de Eiffel</comment>
+ <comment xml:lang="ga">cód foinseach Eiffel</comment>
+ <comment xml:lang="fur">codiç sorzint Eiffel</comment>
+ <comment xml:lang="fr">code source Eiffel</comment>
+ <comment xml:lang="fo">Eiffel keldukota</comment>
+ <comment xml:lang="fi">Eiffel-lähdekoodi</comment>
+ <comment xml:lang="eu">Eiffel iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Eiffel</comment>
+ <comment xml:lang="eo">Eiffel-fontkodo</comment>
+ <comment xml:lang="en_GB">Eiffel source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Eiffel</comment>
+ <comment xml:lang="de">Eiffel-Quelltext</comment>
+ <comment xml:lang="da">Eiffel-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Eiffel</comment>
+ <comment xml:lang="ca">codi font en Eiffel</comment>
+ <comment xml:lang="bg">Изходен код — Eiffel</comment>
+ <comment xml:lang="be@latin">Kryničny kod Eiffel</comment>
+ <comment xml:lang="be">зыходны код Eiffel</comment>
+ <comment xml:lang="ar">شفرة مصدر Eiffel</comment>
+ <comment xml:lang="af">Eiffel-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.e"/>
<glob pattern="*.eif"/>
</mime-type>
<mime-type type="text/x-emacs-lisp">
<comment>Emacs Lisp source code</comment>
- <comment xml:lang="ar">شفرة مصدر Emacs Lisp</comment>
- <comment xml:lang="az">Emacs Lisp mənbə kodu</comment>
- <comment xml:lang="be@latin">Kryničny kod Emacs Lisp</comment>
- <comment xml:lang="bg">Изходен код — Emacs Lisp</comment>
- <comment xml:lang="ca">codi font en Emacs Lisp</comment>
- <comment xml:lang="cs">zdrojový kód Emacs Lisp</comment>
- <comment xml:lang="cy">Ffynhonnell rhaglen EMACS LISP</comment>
- <comment xml:lang="da">Emacs Lisp-kildekode</comment>
- <comment xml:lang="de">Emacs-Lisp-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Emacs Lisp</comment>
- <comment xml:lang="en_GB">Emacs Lisp source code</comment>
- <comment xml:lang="eo">fontkodo en Emacs Lisp</comment>
- <comment xml:lang="es">código fuente en Lisp de Emacs</comment>
- <comment xml:lang="eu">Emacs Lisp iturburu-kodea</comment>
- <comment xml:lang="fi">Emacs Lisp -lähdekoodi</comment>
- <comment xml:lang="fo">Emacs Lisp keldukota</comment>
- <comment xml:lang="fr">code source Emacs Lisp</comment>
- <comment xml:lang="ga">cód foinseach Emacs Lisp</comment>
- <comment xml:lang="gl">código fonte de Emacs Lisp</comment>
- <comment xml:lang="he">קוד מקור של Emcas Lisp</comment>
- <comment xml:lang="hr">Emacs Lisp izvorni kôd</comment>
- <comment xml:lang="hu">Emacs Lisp-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Lisp de Emacs</comment>
- <comment xml:lang="id">Kode sumber Emacs Lisp</comment>
- <comment xml:lang="it">Codice sorgente Emacs Lisp</comment>
- <comment xml:lang="ja">Emacs Lisp ソースコード</comment>
- <comment xml:lang="ka">Emacs-ის Lisp საწყისი კოდი</comment>
- <comment xml:lang="kk">Emacs Lisp бастапқы коды</comment>
- <comment xml:lang="ko">Emacs Lisp 소스 코드</comment>
- <comment xml:lang="lt">Emacs Lisp pradinis kodas</comment>
- <comment xml:lang="lv">Emacs Lisp pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Emacs Lisp</comment>
- <comment xml:lang="nb">Emacs Lisp-kildekode</comment>
- <comment xml:lang="nl">Emacs Lisp-broncode</comment>
- <comment xml:lang="nn">Emacs Lisp kjeldekode</comment>
- <comment xml:lang="oc">còde font Emacs Lisp</comment>
- <comment xml:lang="pl">Plik źródłowy Emacs Lisp</comment>
- <comment xml:lang="pt">código origem Emacs Lisp</comment>
- <comment xml:lang="pt_BR">Código-fonte Lisp do Emacs</comment>
- <comment xml:lang="ro">Cod sursă Emacs Lisp</comment>
- <comment xml:lang="ru">Исходный код Emacs Lisp</comment>
- <comment xml:lang="sk">Zdrojový kód Emacs Lisp</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Emacs Lisp</comment>
- <comment xml:lang="sq">Kod burues Emacs Lisp</comment>
- <comment xml:lang="sr">Емакс Лисп изворни ко̂д</comment>
- <comment xml:lang="sv">Emacs Lisp-källkod</comment>
- <comment xml:lang="tr">Emacs Lisp kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Emacs Lisp</comment>
- <comment xml:lang="vi">Mã nguồn Lisp Emacs</comment>
- <comment xml:lang="zh_CN">Emacs Lisp 源代码</comment>
<comment xml:lang="zh_TW">Emacs Lisp 源碼</comment>
+ <comment xml:lang="zh_CN">Emacs Lisp 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Lisp Emacs</comment>
+ <comment xml:lang="uk">початковий код мовою Emacs Lisp</comment>
+ <comment xml:lang="tr">Emacs Lisp kaynak kodu</comment>
+ <comment xml:lang="sv">Emacs Lisp-källkod</comment>
+ <comment xml:lang="sr">Емакс Лисп изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Emacs Lisp</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Emacs Lisp</comment>
+ <comment xml:lang="si">Emacs Lisp මූලාශ්‍ර කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Emacs Lisp</comment>
+ <comment xml:lang="ru">Исходный код Emacs Lisp</comment>
+ <comment xml:lang="ro">Cod sursă Emacs Lisp</comment>
+ <comment xml:lang="pt_BR">Código-fonte Lisp do Emacs</comment>
+ <comment xml:lang="pt">código origem Emacs Lisp</comment>
+ <comment xml:lang="pl">Kod źródłowy Emacs Lisp</comment>
+ <comment xml:lang="oc">còde font Emacs Lisp</comment>
+ <comment xml:lang="nn">Emacs Lisp kjeldekode</comment>
+ <comment xml:lang="nl">Emacs Lisp-broncode</comment>
+ <comment xml:lang="nb">Emacs Lisp-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Emacs Lisp</comment>
+ <comment xml:lang="lv">Emacs Lisp pirmkods</comment>
+ <comment xml:lang="lt">Emacs Lisp pradinis kodas</comment>
+ <comment xml:lang="ko">Emacs Lisp 소스 코드</comment>
+ <comment xml:lang="kk">Emacs Lisp бастапқы коды</comment>
+ <comment xml:lang="ka">Emacs-ის Lisp საწყისი კოდი</comment>
+ <comment xml:lang="ja">Emacs Lisp ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Emacs Lisp</comment>
+ <comment xml:lang="is">Emacs Lisp frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Emacs Lisp</comment>
+ <comment xml:lang="ia">Codice-fonte Lisp de Emacs</comment>
+ <comment xml:lang="hu">Emacs Lisp-forráskód</comment>
+ <comment xml:lang="hr">Emacs Lisp izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Emcas Lisp</comment>
+ <comment xml:lang="gl">código fonte de Emacs Lisp</comment>
+ <comment xml:lang="ga">cód foinseach Emacs Lisp</comment>
+ <comment xml:lang="fur">codiç sorzint Emacs Lisp</comment>
+ <comment xml:lang="fr">code source Emacs Lisp</comment>
+ <comment xml:lang="fo">Emacs Lisp keldukota</comment>
+ <comment xml:lang="fi">Emacs Lisp -lähdekoodi</comment>
+ <comment xml:lang="eu">Emacs Lisp iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Lisp de Emacs</comment>
+ <comment xml:lang="eo">fontkodo en Emacs Lisp</comment>
+ <comment xml:lang="en_GB">Emacs Lisp source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Emacs Lisp</comment>
+ <comment xml:lang="de">Emacs-Lisp-Quelltext</comment>
+ <comment xml:lang="da">Emacs Lisp-kildekode</comment>
+ <comment xml:lang="cy">Ffynhonnell rhaglen EMACS LISP</comment>
+ <comment xml:lang="cs">zdrojový kód Emacs Lisp</comment>
+ <comment xml:lang="ca">codi font en Emacs Lisp</comment>
+ <comment xml:lang="bg">Изходен код — Emacs Lisp</comment>
+ <comment xml:lang="be@latin">Kryničny kod Emacs Lisp</comment>
+ <comment xml:lang="be">зыходны код Emacs Lisp</comment>
+ <comment xml:lang="az">Emacs Lisp mənbə kodu</comment>
+ <comment xml:lang="ar">شفرة مصدر Emacs Lisp</comment>
+ <comment xml:lang="af">Emacs Lisp-bronkode</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="\012(" type="string" offset="0"/>
- <match value=";ELC\023\000\000\000" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\012(" offset="0"/>
+ <match type="string" value=";ELC\023\000\000\000" offset="0"/>
</magic>
<glob pattern="*.el"/>
</mime-type>
+ <mime-type type="text/x-elixir">
+ <comment>Elixir source code</comment>
+ <comment xml:lang="zh_TW">Elixir 原始碼</comment>
+ <comment xml:lang="zh_CN">Elixir 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Elixir</comment>
+ <comment xml:lang="tr">Elixir kaynak kodu</comment>
+ <comment xml:lang="sv">Elixir-källkod</comment>
+ <comment xml:lang="sl">Izvorna koda Elixir</comment>
+ <comment xml:lang="si">Elixir මූල කේතය</comment>
+ <comment xml:lang="ru">Исходный код Elixir</comment>
+ <comment xml:lang="pt_BR">Código-fonte Elixir</comment>
+ <comment xml:lang="pl">Kod źródłowy Elixir</comment>
+ <comment xml:lang="nl">Elixir-broncode</comment>
+ <comment xml:lang="ko">Elixir 소스 코드</comment>
+ <comment xml:lang="kk">Elixir бастапқы коды</comment>
+ <comment xml:lang="ja">Elixir ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Elixir</comment>
+ <comment xml:lang="hr">Elixir izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור ב־Elixir</comment>
+ <comment xml:lang="gl">Código de fonte Elixir</comment>
+ <comment xml:lang="fi">Elixir-lähdekoodi</comment>
+ <comment xml:lang="eu">Elixir iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente Elixir</comment>
+ <comment xml:lang="en_GB">Elixir source code</comment>
+ <comment xml:lang="de">Elixir-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Elixir</comment>
+ <comment xml:lang="ar">شفرة مصدر Elixir</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.ex"/>
+ <glob pattern="*.exs"/>
+ </mime-type>
<mime-type type="text/x-erlang">
<comment>Erlang source code</comment>
- <comment xml:lang="ar">شفرة مصدر Erlang</comment>
- <comment xml:lang="be@latin">Kryničny kod Erlang</comment>
- <comment xml:lang="bg">Изходен код — Erlang</comment>
- <comment xml:lang="ca">codi font en Erlang</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Erlang</comment>
- <comment xml:lang="da">Erlangkildekode</comment>
- <comment xml:lang="de">Erlang-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Erlang</comment>
- <comment xml:lang="en_GB">Erlang source code</comment>
- <comment xml:lang="eo">Erlang-fontkodo</comment>
- <comment xml:lang="es">código fuente en Erlang</comment>
- <comment xml:lang="eu">Erlang iturburu-kodea</comment>
- <comment xml:lang="fi">Erlang-lähdekoodi</comment>
- <comment xml:lang="fo">Erlang keldukota</comment>
- <comment xml:lang="fr">code source Erlang</comment>
- <comment xml:lang="ga">cód foinseach Erlang</comment>
- <comment xml:lang="gl">código fonte de Erlang</comment>
- <comment xml:lang="he">קוד מקור של Erlang</comment>
- <comment xml:lang="hr">Erlang izvorni kôd</comment>
- <comment xml:lang="hu">Erlang forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Erlang</comment>
- <comment xml:lang="id">Kode sumber Erlang</comment>
- <comment xml:lang="it">Codice sorgente Erlang</comment>
- <comment xml:lang="ja">Erlang ソースコード</comment>
- <comment xml:lang="ka">Erlang-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Erlang бастапқы коды</comment>
- <comment xml:lang="ko">Erlang 소스 코드</comment>
- <comment xml:lang="lt">Erlang pradinis kodas</comment>
- <comment xml:lang="lv">Erlang pirmkods</comment>
- <comment xml:lang="nb">Erlang-kildekode</comment>
- <comment xml:lang="nl">Erlang-broncode</comment>
- <comment xml:lang="nn">Erlang-kjeldekode</comment>
- <comment xml:lang="oc">còde font Erlang</comment>
- <comment xml:lang="pl">Kod źródłowy Erlang</comment>
- <comment xml:lang="pt">código origem Erlang</comment>
- <comment xml:lang="pt_BR">Código-fonte Erlang</comment>
- <comment xml:lang="ro">Cod sursă Erlang</comment>
- <comment xml:lang="ru">Исходный код Erlang</comment>
- <comment xml:lang="sk">Zdrojový kód Erlang</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Erlang</comment>
- <comment xml:lang="sq">Kod burues Erlang</comment>
- <comment xml:lang="sr">Ерланг изворни ко̂д</comment>
- <comment xml:lang="sv">Erlang-källkod</comment>
- <comment xml:lang="tr">Erlang kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Erlang</comment>
- <comment xml:lang="vi">Mã nguồn Erlang</comment>
- <comment xml:lang="zh_CN">Erlang 源代码</comment>
<comment xml:lang="zh_TW">Erlang 源碼</comment>
+ <comment xml:lang="zh_CN">Erlang 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Erlang</comment>
+ <comment xml:lang="uk">початковий код мовою Erlang</comment>
+ <comment xml:lang="tr">Erlang kaynak kodu</comment>
+ <comment xml:lang="sv">Erlang-källkod</comment>
+ <comment xml:lang="sr">Ерланг изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Erlang</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Erlang</comment>
+ <comment xml:lang="si">Erlang මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Erlang</comment>
+ <comment xml:lang="ru">Исходный код Erlang</comment>
+ <comment xml:lang="ro">Cod sursă Erlang</comment>
+ <comment xml:lang="pt_BR">Código-fonte Erlang</comment>
+ <comment xml:lang="pt">código origem Erlang</comment>
+ <comment xml:lang="pl">Kod źródłowy Erlang</comment>
+ <comment xml:lang="oc">còde font Erlang</comment>
+ <comment xml:lang="nn">Erlang-kjeldekode</comment>
+ <comment xml:lang="nl">Erlang-broncode</comment>
+ <comment xml:lang="nb">Erlang-kildekode</comment>
+ <comment xml:lang="lv">Erlang pirmkods</comment>
+ <comment xml:lang="lt">Erlang pradinis kodas</comment>
+ <comment xml:lang="ko">Erlang 소스 코드</comment>
+ <comment xml:lang="kk">Erlang бастапқы коды</comment>
+ <comment xml:lang="ka">Erlang-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Erlang ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Erlang</comment>
+ <comment xml:lang="is">Erlang frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Erlang</comment>
+ <comment xml:lang="ia">Codice-fonte Erlang</comment>
+ <comment xml:lang="hu">Erlang forráskód</comment>
+ <comment xml:lang="hr">Erlang izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Erlang</comment>
+ <comment xml:lang="gl">código fonte de Erlang</comment>
+ <comment xml:lang="ga">cód foinseach Erlang</comment>
+ <comment xml:lang="fur">codiç sorzint Erlang</comment>
+ <comment xml:lang="fr">code source Erlang</comment>
+ <comment xml:lang="fo">Erlang keldukota</comment>
+ <comment xml:lang="fi">Erlang-lähdekoodi</comment>
+ <comment xml:lang="eu">Erlang iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Erlang</comment>
+ <comment xml:lang="eo">Erlang-fontkodo</comment>
+ <comment xml:lang="en_GB">Erlang source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Erlang</comment>
+ <comment xml:lang="de">Erlang-Quelltext</comment>
+ <comment xml:lang="da">Erlang-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Erlang</comment>
+ <comment xml:lang="ca">codi font en Erlang</comment>
+ <comment xml:lang="bg">Изходен код — Erlang</comment>
+ <comment xml:lang="be@latin">Kryničny kod Erlang</comment>
+ <comment xml:lang="be">зыходны код Erlang</comment>
+ <comment xml:lang="ar">شفرة مصدر Erlang</comment>
+ <comment xml:lang="af">Erlang-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.erl"/>
</mime-type>
<mime-type type="text/x-fortran">
<comment>Fortran source code</comment>
- <comment xml:lang="ar">شفرة مصدر Fortran</comment>
- <comment xml:lang="az">Fortran mənbə kodu</comment>
- <comment xml:lang="be@latin">Kryničny kod Fortran</comment>
- <comment xml:lang="bg">Изходен код — Fortran</comment>
- <comment xml:lang="ca">codi font en Fortran</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Fortran</comment>
- <comment xml:lang="cy">Ffynhonnell rhaglen FORTRAN</comment>
- <comment xml:lang="da">Fortrankildekode</comment>
- <comment xml:lang="de">Fortran-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Fortran</comment>
- <comment xml:lang="en_GB">Fortran source code</comment>
- <comment xml:lang="eo">Fotran-fontkodo</comment>
- <comment xml:lang="es">código fuente en Fortran</comment>
- <comment xml:lang="eu">Fortran-en iturburu-kodea</comment>
- <comment xml:lang="fi">Fortran-lähdekoodi</comment>
- <comment xml:lang="fo">Fortran keldukota</comment>
- <comment xml:lang="fr">code source Fortran</comment>
- <comment xml:lang="ga">cód foinseach Fortran</comment>
- <comment xml:lang="gl">código fonte de Fortran</comment>
- <comment xml:lang="he">קוד מקור של Fortran</comment>
- <comment xml:lang="hr">Fortran izvorni kôd</comment>
- <comment xml:lang="hu">Fortran-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Fortran</comment>
- <comment xml:lang="id">Kode sumber Fortran</comment>
- <comment xml:lang="it">Codice sorgente Fortran</comment>
- <comment xml:lang="ja">Fortran ソースコード</comment>
- <comment xml:lang="ka">Fortran-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Fortran бастапқы коды</comment>
- <comment xml:lang="ko">포트란 소스 코드</comment>
- <comment xml:lang="lt">Fortran pradinis kodas</comment>
- <comment xml:lang="lv">Fortran pirmkods</comment>
- <comment xml:lang="ms">kod sumber Fortran</comment>
- <comment xml:lang="nb">Fortran-kildekode</comment>
- <comment xml:lang="nl">Fortran-broncode</comment>
- <comment xml:lang="nn">Fortran-kjeldekode</comment>
- <comment xml:lang="oc">còde font Fortran</comment>
- <comment xml:lang="pl">Kod źródłowy Fortran</comment>
- <comment xml:lang="pt">código origem Fortran</comment>
- <comment xml:lang="pt_BR">Código-fonte Fortran</comment>
- <comment xml:lang="ro">Cod sursă Fortran</comment>
- <comment xml:lang="ru">Исходный код Fortran</comment>
- <comment xml:lang="sk">Zdrojový kód Fortran</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Fortran</comment>
- <comment xml:lang="sq">Kod burues Fortran</comment>
- <comment xml:lang="sr">Фортран изворни ко̂д</comment>
- <comment xml:lang="sv">Fortran-källkod</comment>
- <comment xml:lang="tr">Fortran kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Fortran</comment>
- <comment xml:lang="vi">Mã nguồn Fortran</comment>
- <comment xml:lang="zh_CN">Fortran 源代码</comment>
<comment xml:lang="zh_TW">Fortran 源碼</comment>
+ <comment xml:lang="zh_CN">Fortran 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Fortran</comment>
+ <comment xml:lang="uk">початковий код мовою Fortran</comment>
+ <comment xml:lang="tr">Fortran kaynak kodu</comment>
+ <comment xml:lang="sv">Fortran-källkod</comment>
+ <comment xml:lang="sr">Фортран изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Fortran</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Fortran</comment>
+ <comment xml:lang="si">Fortran මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Fortran</comment>
+ <comment xml:lang="ru">Исходный код Fortran</comment>
+ <comment xml:lang="ro">Cod sursă Fortran</comment>
+ <comment xml:lang="pt_BR">Código-fonte Fortran</comment>
+ <comment xml:lang="pt">código origem Fortran</comment>
+ <comment xml:lang="pl">Kod źródłowy Fortran</comment>
+ <comment xml:lang="oc">còde font Fortran</comment>
+ <comment xml:lang="nn">Fortran-kjeldekode</comment>
+ <comment xml:lang="nl">Fortran-broncode</comment>
+ <comment xml:lang="nb">Fortran-kildekode</comment>
+ <comment xml:lang="ms">kod sumber Fortran</comment>
+ <comment xml:lang="lv">Fortran pirmkods</comment>
+ <comment xml:lang="lt">Fortran pradinis kodas</comment>
+ <comment xml:lang="ko">포트란 소스 코드</comment>
+ <comment xml:lang="kk">Fortran бастапқы коды</comment>
+ <comment xml:lang="ka">Fortran-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Fortran ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Fortran</comment>
+ <comment xml:lang="is">Fortran frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Fortran</comment>
+ <comment xml:lang="ia">Codice-fonte Fortran</comment>
+ <comment xml:lang="hu">Fortran-forráskód</comment>
+ <comment xml:lang="hr">Fortran izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Fortran</comment>
+ <comment xml:lang="gl">código fonte de Fortran</comment>
+ <comment xml:lang="ga">cód foinseach Fortran</comment>
+ <comment xml:lang="fur">codiç sorzint Fortran</comment>
+ <comment xml:lang="fr">code source Fortran</comment>
+ <comment xml:lang="fo">Fortran keldukota</comment>
+ <comment xml:lang="fi">Fortran-lähdekoodi</comment>
+ <comment xml:lang="eu">Fortran-en iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Fortran</comment>
+ <comment xml:lang="eo">Fotran-fontkodo</comment>
+ <comment xml:lang="en_GB">Fortran source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Fortran</comment>
+ <comment xml:lang="de">Fortran-Quelltext</comment>
+ <comment xml:lang="da">Fortran-kildekode</comment>
+ <comment xml:lang="cy">Ffynhonnell rhaglen FORTRAN</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Fortran</comment>
+ <comment xml:lang="ca">codi font en Fortran</comment>
+ <comment xml:lang="bg">Изходен код — Fortran</comment>
+ <comment xml:lang="be@latin">Kryničny kod Fortran</comment>
+ <comment xml:lang="be">зыходны код Fortran</comment>
+ <comment xml:lang="az">Fortran mənbə kodu</comment>
+ <comment xml:lang="ar">شفرة مصدر Fortran</comment>
+ <comment xml:lang="af">Fortran-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.f"/>
<glob pattern="*.f90"/>
@@ -34154,909 +36292,799 @@
</mime-type>
<mime-type type="text/x-genie">
<comment>Genie source code</comment>
- <comment xml:lang="ca">codi font de Genius</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Genie</comment>
- <comment xml:lang="da">Genie-kildekode</comment>
- <comment xml:lang="de">Genie-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Genie</comment>
- <comment xml:lang="en_GB">Genie source code</comment>
- <comment xml:lang="es">código fuente en Genie</comment>
- <comment xml:lang="eu">Genie iturburu-kodea</comment>
- <comment xml:lang="fi">Genie-lähdekoodi</comment>
- <comment xml:lang="fr">code source Genie</comment>
- <comment xml:lang="ga">cód foinseach Genie</comment>
- <comment xml:lang="he">קוד מקור של Genie</comment>
- <comment xml:lang="hr">Genie izvorni kôd</comment>
- <comment xml:lang="hu">Genie forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Genie</comment>
- <comment xml:lang="id">Kode sumber Genie</comment>
- <comment xml:lang="it">Codice sorgente Genie</comment>
- <comment xml:lang="kk">Genie бастапқы коды</comment>
- <comment xml:lang="ko">Genie 소스 코드</comment>
- <comment xml:lang="oc">còde font Genie</comment>
- <comment xml:lang="pl">Kod źródłowy Genie</comment>
- <comment xml:lang="pt">código origem Genie</comment>
- <comment xml:lang="pt_BR">Código-fonte Genie</comment>
- <comment xml:lang="ru">Исходный код Genie</comment>
- <comment xml:lang="sk">Zdrojový kód Genie</comment>
- <comment xml:lang="sl">Izvorna koda Genie</comment>
- <comment xml:lang="sr">Гение изворни ко̂д</comment>
- <comment xml:lang="sv">Genie-källkod</comment>
- <comment xml:lang="tr">Genie kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Genie</comment>
- <comment xml:lang="zh_CN">Genie 源代码</comment>
<comment xml:lang="zh_TW">Genie 源碼</comment>
+ <comment xml:lang="zh_CN">Genie 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Genie</comment>
+ <comment xml:lang="tr">Genie kaynak kodu</comment>
+ <comment xml:lang="sv">Genie-källkod</comment>
+ <comment xml:lang="sr">Гение изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Genie</comment>
+ <comment xml:lang="sl">Izvorna koda Genie</comment>
+ <comment xml:lang="si">Genie මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Genie</comment>
+ <comment xml:lang="ru">Исходный код Genie</comment>
+ <comment xml:lang="pt_BR">Código-fonte Genie</comment>
+ <comment xml:lang="pt">código origem Genie</comment>
+ <comment xml:lang="pl">Kod źródłowy Genie</comment>
+ <comment xml:lang="oc">còde font Genie</comment>
+ <comment xml:lang="nl">Genie-broncode</comment>
+ <comment xml:lang="ko">Genie 소스 코드</comment>
+ <comment xml:lang="kk">Genie бастапқы коды</comment>
+ <comment xml:lang="ja">Genie ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Genie</comment>
+ <comment xml:lang="is">Genie frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Genie</comment>
+ <comment xml:lang="ia">Codice-fonte Genie</comment>
+ <comment xml:lang="hu">Genie forráskód</comment>
+ <comment xml:lang="hr">Genie izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Genie</comment>
+ <comment xml:lang="gl">Código de fonte Genie</comment>
+ <comment xml:lang="ga">cód foinseach Genie</comment>
+ <comment xml:lang="fur">codiç sorzint Genie</comment>
+ <comment xml:lang="fr">code source Genie</comment>
+ <comment xml:lang="fi">Genie-lähdekoodi</comment>
+ <comment xml:lang="eu">Genie iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Genie</comment>
+ <comment xml:lang="en_GB">Genie source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Genie</comment>
+ <comment xml:lang="de">Genie-Quelltext</comment>
+ <comment xml:lang="da">Genie-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Genie</comment>
+ <comment xml:lang="ca">codi font en Genie</comment>
+ <comment xml:lang="bg">Изходен код — Genie</comment>
+ <comment xml:lang="be">зыходны код Genie</comment>
+ <comment xml:lang="ar">شفرة مصدر Genie</comment>
+ <comment xml:lang="af">Genie-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.gs" case-sensitive="true"/>
<generic-icon name="text-x-generic"/>
</mime-type>
<mime-type type="text/x-gettext-translation">
- <comment>translation file</comment>
- <comment xml:lang="ar">ملف الترجمة</comment>
- <comment xml:lang="ast">ficheru de traducción</comment>
- <comment xml:lang="be@latin">fajł pierakładu</comment>
- <comment xml:lang="bg">Превод</comment>
- <comment xml:lang="ca">fitxer de traducció</comment>
- <comment xml:lang="cs">soubor překladu</comment>
- <comment xml:lang="da">oversættelsesfil</comment>
- <comment xml:lang="de">Übersetzungsdatei</comment>
- <comment xml:lang="el">Αρχείο μετάφρασης</comment>
- <comment xml:lang="en_GB">translation file</comment>
- <comment xml:lang="eo">tradukad-dosiero</comment>
- <comment xml:lang="es">archivo de traducción</comment>
- <comment xml:lang="eu">itzulpen-fitxategia</comment>
- <comment xml:lang="fi">käännöstiedosto</comment>
- <comment xml:lang="fo">týðingarfíla</comment>
- <comment xml:lang="fr">fichier de traduction</comment>
- <comment xml:lang="ga">comhad aistriúcháin</comment>
- <comment xml:lang="gl">ficheiro de tradución</comment>
- <comment xml:lang="he">קובץ תרגום</comment>
- <comment xml:lang="hr">Datoteka prijevoda</comment>
- <comment xml:lang="hu">fordítási fájl</comment>
- <comment xml:lang="ia">File de traduction</comment>
- <comment xml:lang="id">berkas terjemahan</comment>
- <comment xml:lang="it">File traduzione</comment>
- <comment xml:lang="ja">翻訳ファイル</comment>
- <comment xml:lang="ka">თარგმნის ფაილი</comment>
- <comment xml:lang="kk">аудармалар файлы</comment>
- <comment xml:lang="ko">번역 파일</comment>
- <comment xml:lang="lt">vertimo failas</comment>
- <comment xml:lang="lv">tulkošanas datne</comment>
- <comment xml:lang="nb">oversettelsesfil</comment>
- <comment xml:lang="nl">vertalingsbestand</comment>
- <comment xml:lang="nn">omsetjingsfil</comment>
- <comment xml:lang="oc">fichièr de traduccion</comment>
- <comment xml:lang="pl">Plik tłumaczenia</comment>
- <comment xml:lang="pt">ficheiro de tradução</comment>
+ <comment>Translation file</comment>
+ <comment xml:lang="uk">Файл перекладу</comment>
+ <comment xml:lang="sv">Översättningsfil</comment>
+ <comment xml:lang="ru">Файл перевода</comment>
<comment xml:lang="pt_BR">Arquivo de tradução</comment>
- <comment xml:lang="ro">fișier traducere</comment>
- <comment xml:lang="ru">Файл переводов</comment>
- <comment xml:lang="sk">Súbor prekladu</comment>
- <comment xml:lang="sl">datoteka prevoda programa</comment>
- <comment xml:lang="sq">File përkthimesh</comment>
- <comment xml:lang="sr">датотека превода</comment>
- <comment xml:lang="sv">översättningsfil</comment>
- <comment xml:lang="tr">çeviri dosyası</comment>
- <comment xml:lang="uk">файл перекладу</comment>
- <comment xml:lang="vi">tập tin dịch</comment>
- <comment xml:lang="zh_CN">翻译文件</comment>
- <comment xml:lang="zh_TW">翻譯檔</comment>
+ <comment xml:lang="pl">Plik tłumaczenia</comment>
+ <comment xml:lang="ja">翻訳文書</comment>
+ <comment xml:lang="it">File traduzione</comment>
+ <comment xml:lang="gl">Ficheiro de traducións</comment>
+ <comment xml:lang="eu">Itzulpen-fitxategia</comment>
+ <comment xml:lang="es">archivo de traducción</comment>
+ <comment xml:lang="de">Übersetzungsdatei</comment>
+ <comment xml:lang="be">файл перакладу</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.po"/>
<alias type="text/x-po"/>
<alias type="application/x-gettext"/>
</mime-type>
<mime-type type="text/x-gettext-translation-template">
- <comment>translation template</comment>
- <comment xml:lang="ar">قالب الترجمة</comment>
- <comment xml:lang="ast">plantía de traducción</comment>
- <comment xml:lang="be@latin">šablon dla pierakładu</comment>
- <comment xml:lang="bg">Шаблон за преводи</comment>
- <comment xml:lang="ca">plantilla de traducció</comment>
- <comment xml:lang="cs">šablona překladu</comment>
- <comment xml:lang="da">oversættelsesskabelon</comment>
- <comment xml:lang="de">Übersetzungsvorlage</comment>
- <comment xml:lang="el">Πρότυπο μετάφρασης</comment>
- <comment xml:lang="en_GB">translation template</comment>
- <comment xml:lang="eo">tradukad-ŝablono</comment>
- <comment xml:lang="es">plantilla de traducción</comment>
- <comment xml:lang="eu">itzulpenen txantiloia</comment>
- <comment xml:lang="fi">käännösmalli</comment>
- <comment xml:lang="fo">týðingarformur</comment>
- <comment xml:lang="fr">modèle de traduction</comment>
- <comment xml:lang="ga">teimpléad aistriúcháin</comment>
- <comment xml:lang="gl">plantilla de tradución</comment>
- <comment xml:lang="he">תבנית תרגום</comment>
- <comment xml:lang="hr">Predložak prijevoda</comment>
- <comment xml:lang="hu">fordítási sablon</comment>
- <comment xml:lang="ia">Patrono de traduction</comment>
- <comment xml:lang="id">templat terjemahan</comment>
- <comment xml:lang="it">Modello di traduzione</comment>
- <comment xml:lang="ja">翻訳テンプレート</comment>
- <comment xml:lang="ka">თარგმნის შაბლონი</comment>
- <comment xml:lang="kk">аудармалар үлгісі</comment>
- <comment xml:lang="ko">메시지 번역 서식</comment>
- <comment xml:lang="lt">vertimo šablonas</comment>
- <comment xml:lang="lv">tulkošanas veidne</comment>
- <comment xml:lang="nb">mal for oversetting</comment>
- <comment xml:lang="nl">vertalingssjabloon</comment>
- <comment xml:lang="nn">omsetjingsmal</comment>
- <comment xml:lang="oc">modèl de traduccion</comment>
- <comment xml:lang="pl">Szablon tłumaczenia</comment>
- <comment xml:lang="pt">modelo de tradução</comment>
- <comment xml:lang="pt_BR">Modelo de tradução</comment>
- <comment xml:lang="ro">șablon de traducere</comment>
- <comment xml:lang="ru">Шаблон переводов</comment>
- <comment xml:lang="sk">Šablóna prekladu</comment>
- <comment xml:lang="sl">predloga datoteke prevoda programa</comment>
- <comment xml:lang="sq">Model përkthimesh</comment>
- <comment xml:lang="sr">шаблон превода</comment>
- <comment xml:lang="sv">översättningsmall</comment>
- <comment xml:lang="tr">çeviri şablonu</comment>
+ <comment>Translation template</comment>
<comment xml:lang="uk">шаблон перекладу</comment>
- <comment xml:lang="vi">mẫu dịch</comment>
- <comment xml:lang="zh_CN">翻译模板</comment>
- <comment xml:lang="zh_TW">翻譯模版</comment>
+ <comment xml:lang="sv">Översättningsmall</comment>
+ <comment xml:lang="ru">Шаблон перевода</comment>
+ <comment xml:lang="pt_BR">Modelo de tradução</comment>
+ <comment xml:lang="pl">Szablon tłumaczenia</comment>
+ <comment xml:lang="ja">翻訳雛形</comment>
+ <comment xml:lang="it">Modello traduzione</comment>
+ <comment xml:lang="gl">Modelo de tradución</comment>
+ <comment xml:lang="eu">Itzulpen-txantiloia</comment>
+ <comment xml:lang="es">plantilla de traducciones</comment>
+ <comment xml:lang="de">Übersetzungsvorlage</comment>
+ <comment xml:lang="be">шаблон перакладу</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.pot"/>
<alias type="text/x-pot"/>
- <magic priority="50">
- <match value='#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version:' type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="#, fuzzy\nmsgid \&quot;\&quot;\nmsgstr \&quot;\&quot;\n\&quot;Project-Id-Version:" offset="0:256"/>
</magic>
</mime-type>
<mime-type type="text/x-gherkin">
- <comment>feature specification in Gherkin format</comment>
- <comment xml:lang="ca">especificació de funcionalitat en format Gherkin</comment>
- <comment xml:lang="cs">specifikace vlastností ve formátu Gherkin</comment>
- <comment xml:lang="da">funktionspecifikation i Gherkin-format</comment>
- <comment xml:lang="de">Funktionsspezifikation im Gherkin-Format</comment>
- <comment xml:lang="en_GB">feature specification in Gherkin format</comment>
- <comment xml:lang="es">especificación de funcionalidad en formato Gherkin</comment>
- <comment xml:lang="fr">spécification fonctionnelle au format Gherkin</comment>
- <comment xml:lang="ga">sonraíocht gnéithe i bhformáid Gherkin</comment>
- <comment xml:lang="he">פירוט תכונות בתבנית Gherkin</comment>
- <comment xml:lang="hr">opis značajke u Gherkin formatu</comment>
- <comment xml:lang="hu">funkcióleírás Gherkin formátumban</comment>
- <comment xml:lang="id">spesifikasi fitur dalam format Gherkin</comment>
- <comment xml:lang="it">Specifica di funzionalità in formato Gherkin</comment>
- <comment xml:lang="kk">Gherkin пішіміндегі функционалды анықтамалар</comment>
- <comment xml:lang="ko">Gherkin 형식의 기능 명세</comment>
- <comment xml:lang="pl">Specyfikacja funkcji w formacie Gherkin</comment>
- <comment xml:lang="pt_BR">Especificação de recurso no formato Gherkin</comment>
- <comment xml:lang="ru">Функциональные определения в формате Gherkin</comment>
- <comment xml:lang="sk">Špecifikácia funkcie vo formáte Gherkin</comment>
- <comment xml:lang="sr">одредба функције у запису Геркина</comment>
- <comment xml:lang="sv">egenskapsspecifikation i Gherkin-format</comment>
- <comment xml:lang="tr">Gherkin biçiminde özellik belirtimi</comment>
- <comment xml:lang="uk">специфікація можливості у форматі Gherkin</comment>
- <comment xml:lang="zh_CN">Gherkin 格式中的功能规范</comment>
- <comment xml:lang="zh_TW">Gherkin 格式的特徵規格</comment>
+ <comment>Gherkin document</comment>
+ <comment xml:lang="zh_TW">Gherkin 文件</comment>
+ <comment xml:lang="zh_CN">Gherkin 文档</comment>
+ <comment xml:lang="uk">документ Gherkin</comment>
+ <comment xml:lang="tr">Gherkin belgesi</comment>
+ <comment xml:lang="sv">Gherkin-dokument</comment>
+ <comment xml:lang="sq">dokument Gherkin</comment>
+ <comment xml:lang="sl">Dokument Gherkin</comment>
+ <comment xml:lang="si">ගර්කින් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Gherkin</comment>
+ <comment xml:lang="ru">Документ Gherkin</comment>
+ <comment xml:lang="pt_BR">Documento Gherkin</comment>
+ <comment xml:lang="pl">Dokument Gherkin</comment>
+ <comment xml:lang="oc">document Gherkin</comment>
+ <comment xml:lang="nl">Gherkin-document</comment>
+ <comment xml:lang="ko">게르킨 문서</comment>
+ <comment xml:lang="kk">Gherkin құжаты</comment>
+ <comment xml:lang="ja">Gherkin ドキュメント</comment>
+ <comment xml:lang="it">Documento Gherkin</comment>
+ <comment xml:lang="is">Gherkin skjal</comment>
+ <comment xml:lang="id">Dokumen Gherkin</comment>
+ <comment xml:lang="hu">Gherkin dokumentum</comment>
+ <comment xml:lang="hr">Gherkin dokument</comment>
+ <comment xml:lang="he">מסמך Gherkin</comment>
+ <comment xml:lang="gl">Documento Gherkin</comment>
+ <comment xml:lang="fr">document Gherkin</comment>
+ <comment xml:lang="fi">Gherkin-asiakirja</comment>
+ <comment xml:lang="eu">Gherkin dokumentua</comment>
+ <comment xml:lang="es">documento de Gherkin</comment>
+ <comment xml:lang="en_GB">Gherkin document</comment>
+ <comment xml:lang="de">Gherkin-Dokument</comment>
+ <comment xml:lang="da">Gherkin-dokument</comment>
+ <comment xml:lang="ca">document Gherkin</comment>
+ <comment xml:lang="bg">Документ — Gherkin</comment>
+ <comment xml:lang="be">дакумент Gherkin</comment>
+ <comment xml:lang="ar">مستند Gherkin</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.feature"/>
</mime-type>
<mime-type type="text/html">
<comment>HTML document</comment>
- <comment xml:lang="ar">مستند HTML</comment>
- <comment xml:lang="ast">Documentu HTML</comment>
- <comment xml:lang="be@latin">Dakument HTML</comment>
- <comment xml:lang="bg">Документ — HTML</comment>
- <comment xml:lang="ca">document HTML</comment>
- <comment xml:lang="cs">dokument HTML</comment>
- <comment xml:lang="da">HTML-dokument</comment>
- <comment xml:lang="de">HTML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο HTML</comment>
- <comment xml:lang="en_GB">HTML document</comment>
- <comment xml:lang="eo">HTML-dokumento</comment>
- <comment xml:lang="es">documento HTML</comment>
- <comment xml:lang="eu">HTML dokumentua</comment>
- <comment xml:lang="fi">HTML-asiakirja</comment>
- <comment xml:lang="fo">HTML skjal</comment>
- <comment xml:lang="fr">document HTML</comment>
- <comment xml:lang="ga">cáipéis HTML</comment>
- <comment xml:lang="gl">documento HTML</comment>
- <comment xml:lang="he">מסמך HTML</comment>
- <comment xml:lang="hr">HTML dokument</comment>
- <comment xml:lang="hu">HTML dokumentum</comment>
- <comment xml:lang="ia">Documento HTML</comment>
- <comment xml:lang="id">Dokumen HTML</comment>
- <comment xml:lang="it">Documento HTML</comment>
- <comment xml:lang="ja">HTML ドキュメント</comment>
- <comment xml:lang="kk">HTML құжаты</comment>
- <comment xml:lang="ko">HTML 문서</comment>
- <comment xml:lang="lt">HTML dokumentas</comment>
- <comment xml:lang="lv">HTML dokuments</comment>
- <comment xml:lang="nb">HTML-dokument</comment>
- <comment xml:lang="nl">HTML-document</comment>
- <comment xml:lang="nn">HTML-dokument</comment>
- <comment xml:lang="oc">document HTML</comment>
- <comment xml:lang="pl">Dokument HTML</comment>
- <comment xml:lang="pt">documento HTML</comment>
- <comment xml:lang="pt_BR">Documento HTML</comment>
- <comment xml:lang="ro">Document HTML</comment>
- <comment xml:lang="ru">Документ HTML</comment>
- <comment xml:lang="sk">Dokument HTML</comment>
- <comment xml:lang="sl">Dokument HTML</comment>
- <comment xml:lang="sq">Dokument HTML</comment>
- <comment xml:lang="sr">ХТМЛ документ</comment>
- <comment xml:lang="sv">HTML-dokument</comment>
- <comment xml:lang="tr">HTML belgesi</comment>
- <comment xml:lang="uk">документ HTML</comment>
- <comment xml:lang="vi">Tài liệu HTML</comment>
- <comment xml:lang="zh_CN">HTML 文档</comment>
<comment xml:lang="zh_TW">HTML 文件</comment>
+ <comment xml:lang="zh_CN">HTML 文档</comment>
+ <comment xml:lang="vi">Tài liệu HTML</comment>
+ <comment xml:lang="uk">документ HTML</comment>
+ <comment xml:lang="tr">HTML belgesi</comment>
+ <comment xml:lang="sv">HTML-dokument</comment>
+ <comment xml:lang="sr">ХТМЛ документ</comment>
+ <comment xml:lang="sq">dokument HTML</comment>
+ <comment xml:lang="sl">Dokument HTML</comment>
+ <comment xml:lang="si">HTML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument HTML</comment>
+ <comment xml:lang="ru">Документ HTML</comment>
+ <comment xml:lang="ro">Document HTML</comment>
+ <comment xml:lang="pt_BR">Documento HTML</comment>
+ <comment xml:lang="pt">documento HTML</comment>
+ <comment xml:lang="pl">Dokument HTML</comment>
+ <comment xml:lang="oc">document HTML</comment>
+ <comment xml:lang="nn">HTML-dokument</comment>
+ <comment xml:lang="nl">HTML-document</comment>
+ <comment xml:lang="nb">HTML-dokument</comment>
+ <comment xml:lang="lv">HTML dokuments</comment>
+ <comment xml:lang="lt">HTML dokumentas</comment>
+ <comment xml:lang="ko">HTML 문서</comment>
+ <comment xml:lang="kk">HTML құжаты</comment>
+ <comment xml:lang="ja">HTML ドキュメント</comment>
+ <comment xml:lang="it">Documento HTML</comment>
+ <comment xml:lang="is">HTML skjal</comment>
+ <comment xml:lang="id">Dokumen HTML</comment>
+ <comment xml:lang="ia">Documento HTML</comment>
+ <comment xml:lang="hu">HTML dokumentum</comment>
+ <comment xml:lang="hr">HTML dokument</comment>
+ <comment xml:lang="he">מסמך HTML</comment>
+ <comment xml:lang="gl">documento HTML</comment>
+ <comment xml:lang="ga">cáipéis HTML</comment>
+ <comment xml:lang="fur">document HTML</comment>
+ <comment xml:lang="fr">document HTML</comment>
+ <comment xml:lang="fo">HTML skjal</comment>
+ <comment xml:lang="fi">HTML-asiakirja</comment>
+ <comment xml:lang="eu">HTML dokumentua</comment>
+ <comment xml:lang="es">documento HTML</comment>
+ <comment xml:lang="eo">HTML-dokumento</comment>
+ <comment xml:lang="en_GB">HTML document</comment>
+ <comment xml:lang="el">Έγγραφο HTML</comment>
+ <comment xml:lang="de">HTML-Dokument</comment>
+ <comment xml:lang="da">HTML-dokument</comment>
+ <comment xml:lang="cs">dokument HTML</comment>
+ <comment xml:lang="ca">document HTML</comment>
+ <comment xml:lang="bg">Документ — HTML</comment>
+ <comment xml:lang="be@latin">Dakument HTML</comment>
+ <comment xml:lang="be">дакумент HTML</comment>
+ <comment xml:lang="ast">Documentu HTML</comment>
+ <comment xml:lang="ar">مستند HTML</comment>
+ <comment xml:lang="af">HTML-dokument</comment>
<acronym>HTML</acronym>
<expanded-acronym>HyperText Markup Language</expanded-acronym>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="&lt;!DOCTYPE HTML" type="string" offset="0:256"/>
- <match value="&lt;!doctype html" type="string" offset="0:256"/>
- <match value="&lt;HEAD" type="string" offset="0:256"/>
- <match value="&lt;head" type="string" offset="0:256"/>
- <match value="&lt;TITLE" type="string" offset="0:256"/>
- <match value="&lt;title" type="string" offset="0:256"/>
- <match value="&lt;HTML" type="string" offset="0:256"/>
- <match value="&lt;html" type="string" offset="0:256"/>
- <match value="&lt;SCRIPT" type="string" offset="0:256"/>
- <match value="&lt;script" type="string" offset="0:256"/>
- <match value="&lt;BODY" type="string" offset="0"/>
- <match value="&lt;body" type="string" offset="0"/>
- <match value="&lt;!--" type="string" offset="0"/>
- <match value="&lt;h1" type="string" offset="0"/>
- <match value="&lt;H1" type="string" offset="0"/>
- <match value="&lt;!doctype HTML" type="string" offset="0"/>
- <match value="&lt;!DOCTYPE html" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="&lt;!DOCTYPE HTML" offset="0:256"/>
+ <match type="string" value="&lt;!doctype html" offset="0:256"/>
+ <match type="string" value="&lt;!DOCTYPE html" offset="0:256"/>
+ <match type="string" value="&lt;HEAD" offset="0:256"/>
+ <match type="string" value="&lt;head" offset="0:256"/>
+ <match type="string" value="&lt;HTML" offset="0:256"/>
+ <match type="string" value="&lt;html" offset="0:256"/>
+ <match type="string" value="&lt;SCRIPT" offset="0:256"/>
+ <match type="string" value="&lt;script" offset="0:256"/>
+ <match type="string" value="&lt;BODY" offset="0"/>
+ <match type="string" value="&lt;body" offset="0"/>
+ <match type="string" value="&lt;h1" offset="0"/>
+ <match type="string" value="&lt;H1" offset="0"/>
+ <match type="string" value="&lt;!doctype HTML" offset="0"/>
</magic>
- <glob pattern="*.html"/>
- <glob pattern="*.htm"/>
+ <magic priority="40">
+ <match type="string" value="&lt;!--" offset="0"/>
+ <match type="string" value="&lt;TITLE" offset="0:256"/>
+ <match type="string" value="&lt;title" offset="0:256"/>
+ </magic>
+ <glob pattern="*.html" weight="80"/>
+ <glob pattern="*.htm" weight="80"/>
+ </mime-type>
+ <mime-type type="text/x-component">
+ <comment>HTML component</comment>
+ <comment xml:lang="uk">компонент HTML</comment>
+ <comment xml:lang="sv">HTML-komponent</comment>
+ <comment xml:lang="ru">Компонент HTML</comment>
+ <comment xml:lang="pl">Składnik HTML</comment>
+ <comment xml:lang="es">componente de HTML</comment>
+ <comment xml:lang="de">HTML-Komponente</comment>
+ <acronym>HTML</acronym>
+ <expanded-acronym>HyperText Markup Language</expanded-acronym>
+ <sub-class-of type="application/xml"/>
+ <generic-icon name="text-html"/>
+ <glob pattern="*.htc"/>
+ <root-XML namespaceURI="urn:HTMLComponent" localName="PUBLIC"/>
</mime-type>
<mime-type type="text/cache-manifest">
- <comment>Web application cache manifest</comment>
- <comment xml:lang="ar">قائمة التخزين الموقت لتطبيق الويب</comment>
- <comment xml:lang="bg">Манифест за кеша на уеб приложение</comment>
- <comment xml:lang="ca">manifest de memòria cau d'aplicació Web</comment>
- <comment xml:lang="cs">manifest mezipaměti webové aplikace</comment>
- <comment xml:lang="da">Manifest for internetprogrammellemlager</comment>
- <comment xml:lang="de">Webanwendungscache-Manifest</comment>
- <comment xml:lang="el">Δηλωτικό λανθάνουσας μνήμης εφαρμογής Ιστού</comment>
- <comment xml:lang="en_GB">Web application cache manifest</comment>
- <comment xml:lang="es">manifiesto de antememoria de aplicación web</comment>
- <comment xml:lang="eu">Web aplikazioaren cache-aren agiria</comment>
- <comment xml:lang="fo">Net nýtsluskipanarkova manifest</comment>
- <comment xml:lang="fr">manifeste de cache d'application Web</comment>
- <comment xml:lang="ga">lastliosta taisce d'fheidhmchlár Gréasáin</comment>
- <comment xml:lang="gl">manifesto de caché de aplicativo web</comment>
- <comment xml:lang="he">הצהרה של מטמון של תוכנית ברשת</comment>
- <comment xml:lang="hr">Web aplikacija prikaza predmemorije</comment>
- <comment xml:lang="hu">Webalkalmazás gyorsítótár-összefoglalója</comment>
- <comment xml:lang="ia">Manifesto de cache de application web</comment>
- <comment xml:lang="id">Manifes singgahan aplikasi web</comment>
- <comment xml:lang="it">Manifesto cache applicazione Web</comment>
- <comment xml:lang="ja">Web アプリケーションキャッシュ manifest</comment>
- <comment xml:lang="kk">Веб қолданбасының кэш манифесті</comment>
- <comment xml:lang="ko">웹 애플리케이션 캐시 정의</comment>
- <comment xml:lang="lt">Žiniatinklio programos podėlio manifestas</comment>
- <comment xml:lang="lv">Tīmekļa lietotņu keša manifests</comment>
- <comment xml:lang="nl">Webapplicatie cache manifest</comment>
- <comment xml:lang="oc">manifèste d'escondedor d'aplicacion Web</comment>
- <comment xml:lang="pl">Manifest pamięci podręcznej aplikacji WWW</comment>
- <comment xml:lang="pt">manifesto de cache de aplicação web</comment>
- <comment xml:lang="pt_BR">Manifest de cache de aplicação web</comment>
- <comment xml:lang="ro">Manifest de cache pentru aplicații web</comment>
- <comment xml:lang="ru">Манифест кэша веб-приложения</comment>
- <comment xml:lang="sk">Manifest vyrovnávacej pamäte webovej aplikácie</comment>
- <comment xml:lang="sl">Predpomnilnik spletnega programa</comment>
- <comment xml:lang="sr">проглас оставе Веб програма</comment>
- <comment xml:lang="sv">Cachemanifest för webbapplikation</comment>
- <comment xml:lang="tr">Web uygulama önbelleği bildirimi</comment>
- <comment xml:lang="uk">маніфест кешу веб-програми</comment>
- <comment xml:lang="zh_CN">网络应用程序缓存清单</comment>
- <comment xml:lang="zh_TW">網頁應用程式快取聲明</comment>
+ <comment>Web application cache file</comment>
+ <comment xml:lang="zh_CN">Web 应用缓存文件</comment>
+ <comment xml:lang="uk">файл кешу вебпрограми</comment>
+ <comment xml:lang="tr">Web uygulama önbellek dosyası</comment>
+ <comment xml:lang="sv">Webbapplikationscachefil</comment>
+ <comment xml:lang="sq">kartelë fshehtine aplikacioni Web</comment>
+ <comment xml:lang="si">වෙබ් යෙදුම් හැඹිලි ගොනුව</comment>
+ <comment xml:lang="ru">Файл кэша веб-приложения</comment>
+ <comment xml:lang="pt_BR">Arquivo de cache de aplicativo Web</comment>
+ <comment xml:lang="pl">Plik pamięci podręcznej aplikacji WWW</comment>
+ <comment xml:lang="oc">fichièr d'escondedor aplicacion Web</comment>
+ <comment xml:lang="nl">Cachebestand van webtoepassing</comment>
+ <comment xml:lang="ko">웹 애플리케이션 캐시 파일</comment>
+ <comment xml:lang="kk">Веб қолданбасының кэш файлы</comment>
+ <comment xml:lang="ja">Web アプリケーションキャッシュファイル</comment>
+ <comment xml:lang="it">File cache applicazione Web</comment>
+ <comment xml:lang="is">skyndiminnisskrá vefforrits</comment>
+ <comment xml:lang="id">Berkas singgahan aplikasi web</comment>
+ <comment xml:lang="hu">Webalkalmazás gyorsítótárfájl</comment>
+ <comment xml:lang="hr"> Web aplikacija datoteka predmemorije </comment>
+ <comment xml:lang="he">קובץ מטמון של תוכנית ברשת</comment>
+ <comment xml:lang="gl">Ficheiro de caché de aplicación web</comment>
+ <comment xml:lang="fr">fichier de cache d'application Web</comment>
+ <comment xml:lang="fi">Web-sovelluksen välimuistitiedosto</comment>
+ <comment xml:lang="eu">Web-aplikazio katxe fitxategia</comment>
+ <comment xml:lang="es">archivo de antememoria de aplicación web</comment>
+ <comment xml:lang="en_GB">Web application cache file</comment>
+ <comment xml:lang="de">Webanwendungs-Zwischenspeicherdatei</comment>
+ <comment xml:lang="da">Webprogrammellemlagerfil</comment>
+ <comment xml:lang="ca">fitxer de memòria cau d'aplicació Web</comment>
+ <comment xml:lang="bg">Кеш — уеб приложение</comment>
+ <comment xml:lang="be">файл кэша вэб-праграмы</comment>
+ <comment xml:lang="ar">ملف خبيئة تطبيق ويب</comment>
<sub-class-of type="text/plain"/>
<magic>
- <match value="CACHE MANIFEST" type="string" offset="0">
- <match value="\x20" type="string" offset="14"/>
- <match value="\x09" type="string" offset="14"/>
- <match value="\x0a" type="string" offset="14"/>
- <match value="\x0d" type="string" offset="14"/>
+ <match type="string" value="CACHE MANIFEST" offset="0">
+ <match type="string" value="\x20" offset="14"/>
+ <match type="string" value="\x09" offset="14"/>
+ <match type="string" value="\x0a" offset="14"/>
+ <match type="string" value="\x0d" offset="14"/>
</match>
</magic>
<glob pattern="*.manifest"/>
</mime-type>
<mime-type type="text/x-google-video-pointer">
- <comment>Google Video Pointer</comment>
- <comment xml:lang="ar">مؤشر فيديو جوجل</comment>
- <comment xml:lang="ast">Google Video Pointer</comment>
- <comment xml:lang="be@latin">Pakazalnik Google Video</comment>
- <comment xml:lang="bg">Документ-указател към видео на Google</comment>
- <comment xml:lang="ca">apuntador a vídeo de Google</comment>
- <comment xml:lang="cs">Google Video Pointer</comment>
- <comment xml:lang="da">Google Video-peger</comment>
- <comment xml:lang="de">Google Video-Zeiger</comment>
- <comment xml:lang="el">Google Video Pointer</comment>
- <comment xml:lang="en_GB">Google Video Pointer</comment>
- <comment xml:lang="es">lista de reproducción de Google Video (GVP)</comment>
- <comment xml:lang="eu">Google Video-ren erreprodukzio-zerrenda</comment>
- <comment xml:lang="fi">Google-video-osoitin</comment>
- <comment xml:lang="fo">Google Video Pointer</comment>
- <comment xml:lang="fr">pointeur vidéo Google</comment>
- <comment xml:lang="ga">pointeoir Google Video</comment>
- <comment xml:lang="gl">punteiro de vídeo de Google</comment>
- <comment xml:lang="he">מצביע וידאו של Google</comment>
- <comment xml:lang="hr">Google Video pretraživač</comment>
- <comment xml:lang="hu">Google Video Pointer</comment>
- <comment xml:lang="ia">Punctator Google Video</comment>
- <comment xml:lang="id">Google Video Pointer</comment>
- <comment xml:lang="it">Puntatore Google Video</comment>
- <comment xml:lang="ja">Google ビデオポインター</comment>
- <comment xml:lang="kk">Google Video Pointer</comment>
- <comment xml:lang="ko">Google 동영상 포인터</comment>
- <comment xml:lang="lt">Google Video Pointer</comment>
- <comment xml:lang="lv">Google Video Pointer</comment>
- <comment xml:lang="nb">Peker til Google Video</comment>
- <comment xml:lang="nl">Google-videoverwijzing</comment>
- <comment xml:lang="nn">Google Video-peikar</comment>
- <comment xml:lang="oc">puntador vidèo Google</comment>
- <comment xml:lang="pl">Lista odtwarzania Google Video</comment>
- <comment xml:lang="pt">Ponteiro Google Video</comment>
- <comment xml:lang="pt_BR">Ponteiro do Google Vídeo</comment>
- <comment xml:lang="ro">Indicator Google Video</comment>
- <comment xml:lang="ru">Google Video Pointer</comment>
- <comment xml:lang="sk">Google Video Pointer</comment>
- <comment xml:lang="sl">Kazalec Google Video</comment>
- <comment xml:lang="sq">Puntues Google Video</comment>
- <comment xml:lang="sr">Гуглов видео показивач</comment>
- <comment xml:lang="sv">Google Video-pekare</comment>
- <comment xml:lang="tr">Google Video İşaretçisi</comment>
- <comment xml:lang="uk">вказівник відео Google</comment>
- <comment xml:lang="vi">Con trỏ ảnh động Google</comment>
- <comment xml:lang="zh_CN">Google 视频指向</comment>
- <comment xml:lang="zh_TW">Google Video Pointer</comment>
- <magic priority="50">
- <match value="#.download.the.free.Google.Video.Player" type="string" offset="0"/>
- <match value="# download the free Google Video Player" type="string" offset="0"/>
+ <comment>Google Video Pointer shortcut</comment>
+ <comment xml:lang="zh_CN">Google Video Pointer 快捷方式</comment>
+ <comment xml:lang="uk">скорочення вказівника відео Google</comment>
+ <comment xml:lang="tr">Google Video Pointer kısayolu</comment>
+ <comment xml:lang="sv">Google Video Pointer-genväg</comment>
+ <comment xml:lang="sq">shkurtore Google Video Pointer</comment>
+ <comment xml:lang="si">Google Video Pointer කෙටිමඟ</comment>
+ <comment xml:lang="ru">Ссылка Google Video Pointer</comment>
+ <comment xml:lang="pt_BR">Atalho do Google Video Pointer</comment>
+ <comment xml:lang="pl">Skrót listy odtwarzania Google Video</comment>
+ <comment xml:lang="nl">Google Video Pointer-snelkoppeling</comment>
+ <comment xml:lang="ko">구글 동영상 포인터 바로 가기</comment>
+ <comment xml:lang="kk">Google Video Pointer жарлығы</comment>
+ <comment xml:lang="ja">Google Video Pointer ショートカット</comment>
+ <comment xml:lang="it">Scorciatoia Google Video Pointer</comment>
+ <comment xml:lang="is">Google Video Pointer flýtivísun</comment>
+ <comment xml:lang="id">Pintasan Google Video Pointer</comment>
+ <comment xml:lang="hu">Google Video Pointer parancsikon</comment>
+ <comment xml:lang="hr">Google Video pretraživač prečac</comment>
+ <comment xml:lang="he">קיצור למצביע וידאו של Google</comment>
+ <comment xml:lang="fr">raccourci de pointeur vidéo Google</comment>
+ <comment xml:lang="fi">Google Video Pointer -pikakuvake</comment>
+ <comment xml:lang="eu">Google Video Pointer lasterbidea</comment>
+ <comment xml:lang="es">atajo de Google Video Pointer</comment>
+ <comment xml:lang="en_GB">Google Video Pointer shortcut</comment>
+ <comment xml:lang="de">Google-Videozeiger-Verweis</comment>
+ <comment xml:lang="da">Google Video Pointer-genvej</comment>
+ <comment xml:lang="ca">drecera d'apuntador a vídeo de Google</comment>
+ <comment xml:lang="bg">Отметка — Google Video</comment>
+ <comment xml:lang="be">ярлык Google Video Pointer</comment>
+ <comment xml:lang="ar">اختصار مؤشر فيديو غوغل</comment>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="#.download.the.free.Google.Video.Player" offset="0"/>
+ <match type="string" value="# download the free Google Video Player" offset="0"/>
</magic>
<glob pattern="*.gvp"/>
<alias type="text/google-video-pointer"/>
</mime-type>
<mime-type type="text/x-haskell">
<comment>Haskell source code</comment>
- <comment xml:lang="ar">شفرة مصدر Haskell</comment>
- <comment xml:lang="az">Haskell mənbə kodu</comment>
- <comment xml:lang="be@latin">Kryničny kod Haskell</comment>
- <comment xml:lang="bg">Изходен код на Haskell</comment>
- <comment xml:lang="ca">codi font en Haskell</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Haskell</comment>
- <comment xml:lang="cy">Ffynhonnell rhaglen Haskell</comment>
- <comment xml:lang="da">Haskellkildekode</comment>
- <comment xml:lang="de">Haskell-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Haskell</comment>
- <comment xml:lang="en_GB">Haskell source code</comment>
- <comment xml:lang="eo">Haskell-fontkodo</comment>
- <comment xml:lang="es">código fuente en Haskell</comment>
- <comment xml:lang="eu">Haskell iturburu-kodea</comment>
- <comment xml:lang="fi">Haskell-lähdekoodi</comment>
- <comment xml:lang="fo">Haskell keldukota</comment>
- <comment xml:lang="fr">code source Haskell</comment>
- <comment xml:lang="ga">cód foinseach Haskell</comment>
- <comment xml:lang="gl">código fonte de Haskell</comment>
- <comment xml:lang="he">קוד מקור של Haskell</comment>
- <comment xml:lang="hr">Haskell izvorni kôd</comment>
- <comment xml:lang="hu">Haskell-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Haskell</comment>
- <comment xml:lang="id">Kode sumber Haskell</comment>
- <comment xml:lang="it">Codice sorgente Haskell</comment>
- <comment xml:lang="ja">Haskell ソースコード</comment>
- <comment xml:lang="kk">Haskell бастапқы коды</comment>
- <comment xml:lang="ko">Haskell 소스 코드</comment>
- <comment xml:lang="lt">Haskell pradinis kodas</comment>
- <comment xml:lang="lv">Haskell pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Haskell</comment>
- <comment xml:lang="nb">Haskell-kildekode</comment>
- <comment xml:lang="nl">Haskell-broncode</comment>
- <comment xml:lang="nn">Haskell-kjeldekode</comment>
- <comment xml:lang="oc">còde font Haskell</comment>
- <comment xml:lang="pl">Kod źródłowy Haskell</comment>
- <comment xml:lang="pt">código origem Haskell</comment>
- <comment xml:lang="pt_BR">Código-fonte Haskell</comment>
- <comment xml:lang="ro">Cod sursă Haskell</comment>
- <comment xml:lang="ru">Исходный код Haskell</comment>
- <comment xml:lang="sk">Zdrojový kód Haskell</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Haskell</comment>
- <comment xml:lang="sq">Kod burues Haskell</comment>
- <comment xml:lang="sr">Хаскел изворни ко̂д</comment>
- <comment xml:lang="sv">Haskell-källkod</comment>
- <comment xml:lang="tr">Haskell kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Haskell</comment>
- <comment xml:lang="vi">Mã nguồn Haskell</comment>
- <comment xml:lang="zh_CN">Haskell 源代码</comment>
<comment xml:lang="zh_TW">Haskell 源碼</comment>
+ <comment xml:lang="zh_CN">Haskell 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Haskell</comment>
+ <comment xml:lang="uk">початковий код мовою Haskell</comment>
+ <comment xml:lang="tr">Haskell kaynak kodu</comment>
+ <comment xml:lang="sv">Haskell-källkod</comment>
+ <comment xml:lang="sr">Хаскел изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Haskell</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Haskell</comment>
+ <comment xml:lang="si">Haskell මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Haskell</comment>
+ <comment xml:lang="ru">Исходный код Haskell</comment>
+ <comment xml:lang="ro">Cod sursă Haskell</comment>
+ <comment xml:lang="pt_BR">Código-fonte Haskell</comment>
+ <comment xml:lang="pt">código origem Haskell</comment>
+ <comment xml:lang="pl">Kod źródłowy Haskell</comment>
+ <comment xml:lang="oc">còde font Haskell</comment>
+ <comment xml:lang="nn">Haskell-kjeldekode</comment>
+ <comment xml:lang="nl">Haskell-broncode</comment>
+ <comment xml:lang="nb">Haskell-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Haskell</comment>
+ <comment xml:lang="lv">Haskell pirmkods</comment>
+ <comment xml:lang="lt">Haskell pradinis kodas</comment>
+ <comment xml:lang="ko">Haskell 소스 코드</comment>
+ <comment xml:lang="kk">Haskell бастапқы коды</comment>
+ <comment xml:lang="ja">Haskell ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Haskell</comment>
+ <comment xml:lang="is">Haskell frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Haskell</comment>
+ <comment xml:lang="ia">Codice-fonte Haskell</comment>
+ <comment xml:lang="hu">Haskell-forráskód</comment>
+ <comment xml:lang="hr">Haskell izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Haskell</comment>
+ <comment xml:lang="gl">código fonte de Haskell</comment>
+ <comment xml:lang="ga">cód foinseach Haskell</comment>
+ <comment xml:lang="fur">codiç sorzint Haskell</comment>
+ <comment xml:lang="fr">code source Haskell</comment>
+ <comment xml:lang="fo">Haskell keldukota</comment>
+ <comment xml:lang="fi">Haskell-lähdekoodi</comment>
+ <comment xml:lang="eu">Haskell iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Haskell</comment>
+ <comment xml:lang="eo">Haskell-fontkodo</comment>
+ <comment xml:lang="en_GB">Haskell source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Haskell</comment>
+ <comment xml:lang="de">Haskell-Quelltext</comment>
+ <comment xml:lang="da">Haskell-kildekode</comment>
+ <comment xml:lang="cy">Ffynhonnell rhaglen Haskell</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Haskell</comment>
+ <comment xml:lang="ca">codi font en Haskell</comment>
+ <comment xml:lang="bg">Изходен код — Haskell</comment>
+ <comment xml:lang="be@latin">Kryničny kod Haskell</comment>
+ <comment xml:lang="be">зыходны код Haskell</comment>
+ <comment xml:lang="az">Haskell mənbə kodu</comment>
+ <comment xml:lang="ar">شفرة مصدر Haskell</comment>
+ <comment xml:lang="af">Haskell-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.hs"/>
</mime-type>
<mime-type type="text/x-idl">
<comment>IDL document</comment>
- <comment xml:lang="ar">مستند IDL</comment>
- <comment xml:lang="ast">Documentu IDL</comment>
- <comment xml:lang="az">IDL sənədi</comment>
- <comment xml:lang="be@latin">Dakument IDL</comment>
- <comment xml:lang="bg">Документ — IDL</comment>
- <comment xml:lang="ca">document IDL</comment>
- <comment xml:lang="cs">dokument IDL</comment>
- <comment xml:lang="cy">Dogfen IDL</comment>
- <comment xml:lang="da">IDL-dokument</comment>
- <comment xml:lang="de">IDL-Dokument</comment>
- <comment xml:lang="el">Έγγραφο IDL</comment>
- <comment xml:lang="en_GB">IDL document</comment>
- <comment xml:lang="eo">IDL-dokumento</comment>
- <comment xml:lang="es">documento IDL</comment>
- <comment xml:lang="eu">IDL dokumentua</comment>
- <comment xml:lang="fi">IDL-asiakirja</comment>
- <comment xml:lang="fo">IDL skjal</comment>
- <comment xml:lang="fr">document IDL</comment>
- <comment xml:lang="ga">cáipéis IDL</comment>
- <comment xml:lang="gl">documento IDL</comment>
- <comment xml:lang="he">מסמך IDL</comment>
- <comment xml:lang="hr">IDL dokument</comment>
- <comment xml:lang="hu">IDL-dokumentum</comment>
- <comment xml:lang="ia">Documento IDL</comment>
- <comment xml:lang="id">Dokumen IDL</comment>
- <comment xml:lang="it">Documento IDL</comment>
- <comment xml:lang="ja">IDL ドキュメント</comment>
- <comment xml:lang="kk">IDL құжаты</comment>
- <comment xml:lang="ko">IDL 문서</comment>
- <comment xml:lang="lt">IDL dokumentas</comment>
- <comment xml:lang="lv">IDL dokuments</comment>
- <comment xml:lang="ms">Dokumen IDL</comment>
- <comment xml:lang="nb">IDL-dokument</comment>
- <comment xml:lang="nl">IDL-document</comment>
- <comment xml:lang="nn">IDL-dokument</comment>
- <comment xml:lang="oc">document IDL</comment>
- <comment xml:lang="pl">Dokument IDL</comment>
- <comment xml:lang="pt">documento IDL</comment>
- <comment xml:lang="pt_BR">Documento IDL</comment>
- <comment xml:lang="ro">Document IDL</comment>
- <comment xml:lang="ru">Документ IDL</comment>
- <comment xml:lang="sk">Dokument IDL</comment>
- <comment xml:lang="sl">Dokument IDL</comment>
- <comment xml:lang="sq">Dokument IDL</comment>
- <comment xml:lang="sr">ИДЛ документ</comment>
- <comment xml:lang="sv">IDL-dokument</comment>
- <comment xml:lang="tr">IDL belgesi</comment>
- <comment xml:lang="uk">документ IDL</comment>
- <comment xml:lang="vi">Tài liệu IDL</comment>
- <comment xml:lang="zh_CN">IDL 文档</comment>
<comment xml:lang="zh_TW">IDL 文件</comment>
+ <comment xml:lang="zh_CN">IDL 文档</comment>
+ <comment xml:lang="vi">Tài liệu IDL</comment>
+ <comment xml:lang="uk">документ IDL</comment>
+ <comment xml:lang="tr">IDL belgesi</comment>
+ <comment xml:lang="sv">IDL-dokument</comment>
+ <comment xml:lang="sr">ИДЛ документ</comment>
+ <comment xml:lang="sq">dokument IDL</comment>
+ <comment xml:lang="sl">Dokument IDL</comment>
+ <comment xml:lang="si">IDL ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument IDL</comment>
+ <comment xml:lang="ru">Документ IDL</comment>
+ <comment xml:lang="ro">Document IDL</comment>
+ <comment xml:lang="pt_BR">Documento IDL</comment>
+ <comment xml:lang="pt">documento IDL</comment>
+ <comment xml:lang="pl">Dokument IDL</comment>
+ <comment xml:lang="oc">document IDL</comment>
+ <comment xml:lang="nn">IDL-dokument</comment>
+ <comment xml:lang="nl">IDL-document</comment>
+ <comment xml:lang="nb">IDL-dokument</comment>
+ <comment xml:lang="ms">Dokumen IDL</comment>
+ <comment xml:lang="lv">IDL dokuments</comment>
+ <comment xml:lang="lt">IDL dokumentas</comment>
+ <comment xml:lang="ko">IDL 문서</comment>
+ <comment xml:lang="kk">IDL құжаты</comment>
+ <comment xml:lang="ja">IDL ドキュメント</comment>
+ <comment xml:lang="it">Documento IDL</comment>
+ <comment xml:lang="is">IDL skjal</comment>
+ <comment xml:lang="id">Dokumen IDL</comment>
+ <comment xml:lang="ia">Documento IDL</comment>
+ <comment xml:lang="hu">IDL-dokumentum</comment>
+ <comment xml:lang="hr">IDL dokument</comment>
+ <comment xml:lang="he">מסמך IDL</comment>
+ <comment xml:lang="gl">documento IDL</comment>
+ <comment xml:lang="ga">cáipéis IDL</comment>
+ <comment xml:lang="fur">document IDL</comment>
+ <comment xml:lang="fr">document IDL</comment>
+ <comment xml:lang="fo">IDL skjal</comment>
+ <comment xml:lang="fi">IDL-asiakirja</comment>
+ <comment xml:lang="eu">IDL dokumentua</comment>
+ <comment xml:lang="es">documento IDL</comment>
+ <comment xml:lang="eo">IDL-dokumento</comment>
+ <comment xml:lang="en_GB">IDL document</comment>
+ <comment xml:lang="el">Έγγραφο IDL</comment>
+ <comment xml:lang="de">IDL-Dokument</comment>
+ <comment xml:lang="da">IDL-dokument</comment>
+ <comment xml:lang="cy">Dogfen IDL</comment>
+ <comment xml:lang="cs">dokument IDL</comment>
+ <comment xml:lang="ca">document IDL</comment>
+ <comment xml:lang="bg">Документ — IDL</comment>
+ <comment xml:lang="be@latin">Dakument IDL</comment>
+ <comment xml:lang="be">дакумент IDL</comment>
+ <comment xml:lang="az">IDL sənədi</comment>
+ <comment xml:lang="ast">Documentu IDL</comment>
+ <comment xml:lang="ar">مستند IDL</comment>
+ <comment xml:lang="af">IDL-dokument</comment>
<acronym>IDL</acronym>
<expanded-acronym>Interface Definition Language</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.idl"/>
</mime-type>
<mime-type type="text/x-install">
- <comment>installation instructions</comment>
- <comment xml:lang="ar">تعليمات التثبيت</comment>
- <comment xml:lang="ast">instrucciones d'instalación</comment>
- <comment xml:lang="be@latin">instrukcyja dla instalavańnia</comment>
- <comment xml:lang="bg">Инструкции за инсталация</comment>
- <comment xml:lang="ca">instruccions d'instal·lació</comment>
- <comment xml:lang="cs">návod k instalaci</comment>
- <comment xml:lang="da">installationsinstruktioner</comment>
- <comment xml:lang="de">Installationsanleitung</comment>
- <comment xml:lang="el">Οδηγίες εγκατάστασης</comment>
- <comment xml:lang="en_GB">installation instructions</comment>
- <comment xml:lang="es">instrucciones de instalación</comment>
- <comment xml:lang="eu">instalazioaren instrukzioak</comment>
- <comment xml:lang="fi">asennusohjeet</comment>
- <comment xml:lang="fo">innleggingar vegleiðing</comment>
- <comment xml:lang="fr">instructions d'installation</comment>
- <comment xml:lang="ga">treoracha suiteála</comment>
- <comment xml:lang="gl">instrucións de instalación</comment>
- <comment xml:lang="he">הוראות התקנה</comment>
- <comment xml:lang="hr">Upute za instalaciju</comment>
- <comment xml:lang="hu">telepítési utasítások</comment>
- <comment xml:lang="ia">Instructiones de installation</comment>
- <comment xml:lang="id">instruksi instalasi</comment>
- <comment xml:lang="it">Istruzioni di installazione</comment>
- <comment xml:lang="ja">ソフトウェアインストール説明</comment>
- <comment xml:lang="kk">бағдарламаны орнату нұсқаулары</comment>
- <comment xml:lang="ko">설치 방법</comment>
- <comment xml:lang="lt">diegimo instrukcijos</comment>
- <comment xml:lang="lv">instalācijas instrukcijas</comment>
- <comment xml:lang="nb">installationsinstruksjoner</comment>
- <comment xml:lang="nl">installatie-instructies</comment>
- <comment xml:lang="nn">installasjonsinstruksjonar</comment>
- <comment xml:lang="oc">instructions d'installacion</comment>
- <comment xml:lang="pl">Instrukcje instalacji</comment>
- <comment xml:lang="pt">instruções de instalação</comment>
- <comment xml:lang="pt_BR">Instruções de instalação</comment>
- <comment xml:lang="ro">instrucțiuni de instalare</comment>
+ <comment>Installation instructions</comment>
+ <comment xml:lang="uk">настанови щодо встановлення</comment>
+ <comment xml:lang="sv">Installationsinstruktioner</comment>
<comment xml:lang="ru">Инструкции по установке</comment>
- <comment xml:lang="sk">Návod na inštaláciu</comment>
- <comment xml:lang="sl">navodila namestitve</comment>
- <comment xml:lang="sq">Udhëzime instalimi</comment>
- <comment xml:lang="sr">упутства инсталације</comment>
- <comment xml:lang="sv">installationsinstruktioner</comment>
- <comment xml:lang="tr">kurulum yönergeleri</comment>
- <comment xml:lang="uk">інструкції з встановлення</comment>
- <comment xml:lang="vi">hướng dẫn cài đặt</comment>
- <comment xml:lang="zh_CN">软件安装指南</comment>
- <comment xml:lang="zh_TW">安裝指引</comment>
+ <comment xml:lang="pt_BR">Instruções de instalação</comment>
+ <comment xml:lang="pl">Instrukcje instalacji</comment>
+ <comment xml:lang="ja">導入指南</comment>
+ <comment xml:lang="it">Istruzioni di installazione</comment>
+ <comment xml:lang="eu">Instalazio-argibideak</comment>
+ <comment xml:lang="es">instrucciones de instalación</comment>
+ <comment xml:lang="de">Installationsanleitung</comment>
+ <comment xml:lang="be">інструкцыі для ўсталявання</comment>
<sub-class-of type="text/plain"/>
<glob pattern="INSTALL"/>
</mime-type>
<mime-type type="text/x-java">
<comment>Java source code</comment>
- <comment xml:lang="ar">شفرة مصدر Java</comment>
- <comment xml:lang="be@latin">Kryničny kod Java</comment>
- <comment xml:lang="bg">Изходен код на Java</comment>
- <comment xml:lang="ca">codi font en Java</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Java</comment>
- <comment xml:lang="da">Javakildekode</comment>
- <comment xml:lang="de">Java-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Java</comment>
- <comment xml:lang="en_GB">Java source code</comment>
- <comment xml:lang="eo">Java-fontkodo</comment>
- <comment xml:lang="es">código fuente en Java</comment>
- <comment xml:lang="eu">Java iturburu-kodea</comment>
- <comment xml:lang="fi">Java-lähdekoodi</comment>
- <comment xml:lang="fo">Java keldukota</comment>
- <comment xml:lang="fr">code source Java</comment>
- <comment xml:lang="ga">cód foinseach Java</comment>
- <comment xml:lang="gl">código fonte de Java</comment>
- <comment xml:lang="he">קוד מקור ב־Java</comment>
- <comment xml:lang="hr">Java izvorni kôd</comment>
- <comment xml:lang="hu">Java-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Java</comment>
- <comment xml:lang="id">Kode sumber Java</comment>
- <comment xml:lang="it">Codice sorgente Java</comment>
- <comment xml:lang="ja">Java ソースコード</comment>
- <comment xml:lang="kk">Java бастапқы коды</comment>
- <comment xml:lang="ko">Java 소스 코드</comment>
- <comment xml:lang="lt">Java pradinis kodas</comment>
- <comment xml:lang="lv">Java pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Java</comment>
- <comment xml:lang="nb">Java-kildekode</comment>
- <comment xml:lang="nl">Java-broncode</comment>
- <comment xml:lang="nn">Java-kjeldekode</comment>
- <comment xml:lang="oc">còde font Java</comment>
- <comment xml:lang="pl">Kod źródłowy Java</comment>
- <comment xml:lang="pt">código origem Java</comment>
- <comment xml:lang="pt_BR">Código-fonte Java</comment>
- <comment xml:lang="ro">Cod sursă Java</comment>
- <comment xml:lang="ru">Исходный код Java</comment>
- <comment xml:lang="sk">Zdrojový kód Java</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Java</comment>
- <comment xml:lang="sq">Kod burues Java</comment>
- <comment xml:lang="sr">Јава изворни ко̂д</comment>
- <comment xml:lang="sv">Java-källkod</comment>
- <comment xml:lang="tr">Java kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Java</comment>
- <comment xml:lang="vi">Mã nguồn Java</comment>
- <comment xml:lang="zh_CN">Java 源代码</comment>
<comment xml:lang="zh_TW">Java 源碼</comment>
+ <comment xml:lang="zh_CN">Java 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Java</comment>
+ <comment xml:lang="uk">початковий код мовою Java</comment>
+ <comment xml:lang="tr">Java kaynak kodu</comment>
+ <comment xml:lang="sv">Java-källkod</comment>
+ <comment xml:lang="sr">Јава изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Java</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Java</comment>
+ <comment xml:lang="si">ජාවා මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Java</comment>
+ <comment xml:lang="ru">Исходный код Java</comment>
+ <comment xml:lang="ro">Cod sursă Java</comment>
+ <comment xml:lang="pt_BR">Código-fonte Java</comment>
+ <comment xml:lang="pt">código origem Java</comment>
+ <comment xml:lang="pl">Kod źródłowy Java</comment>
+ <comment xml:lang="oc">còde font Java</comment>
+ <comment xml:lang="nn">Java-kjeldekode</comment>
+ <comment xml:lang="nl">Java-broncode</comment>
+ <comment xml:lang="nb">Java-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Java</comment>
+ <comment xml:lang="lv">Java pirmkods</comment>
+ <comment xml:lang="lt">Java pradinis kodas</comment>
+ <comment xml:lang="ko">Java 소스 코드</comment>
+ <comment xml:lang="kk">Java бастапқы коды</comment>
+ <comment xml:lang="ja">Java ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Java</comment>
+ <comment xml:lang="is">Java frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Java</comment>
+ <comment xml:lang="ia">Codice-fonte Java</comment>
+ <comment xml:lang="hu">Java-forráskód</comment>
+ <comment xml:lang="hr">Java izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור ב־Java</comment>
+ <comment xml:lang="gl">código fonte de Java</comment>
+ <comment xml:lang="ga">cód foinseach Java</comment>
+ <comment xml:lang="fur">codiç sorzint Java</comment>
+ <comment xml:lang="fr">code source Java</comment>
+ <comment xml:lang="fo">Java keldukota</comment>
+ <comment xml:lang="fi">Java-lähdekoodi</comment>
+ <comment xml:lang="eu">Java iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Java</comment>
+ <comment xml:lang="eo">Java-fontkodo</comment>
+ <comment xml:lang="en_GB">Java source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Java</comment>
+ <comment xml:lang="de">Java-Quelltext</comment>
+ <comment xml:lang="da">Java-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Java</comment>
+ <comment xml:lang="ca">codi font en Java</comment>
+ <comment xml:lang="bg">Изходен код — Java</comment>
+ <comment xml:lang="be@latin">Kryničny kod Java</comment>
+ <comment xml:lang="be">зыходны код Java</comment>
+ <comment xml:lang="ar">شفرة مصدر Java</comment>
+ <comment xml:lang="af">Java-bronkode</comment>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.java"/>
</mime-type>
<mime-type type="text/x-ldif">
<comment>LDIF address book</comment>
- <comment xml:lang="ar">دفتر عناوين LDIF</comment>
- <comment xml:lang="be@latin">Adrasnaja kniha LDIF</comment>
- <comment xml:lang="bg">Адресна книга — LDIF</comment>
- <comment xml:lang="ca">llibreta d'adreces LDIF</comment>
- <comment xml:lang="cs">adresář LDIF</comment>
- <comment xml:lang="da">LDIF-adressebog</comment>
- <comment xml:lang="de">LDIF-Adressbuch</comment>
- <comment xml:lang="el">Βιβλίο διευθύνσεων LDIF</comment>
- <comment xml:lang="en_GB">LDIF address book</comment>
- <comment xml:lang="eo">LDIF-adresaro</comment>
- <comment xml:lang="es">libreta de direcciones LDIF</comment>
- <comment xml:lang="eu">LDIF helbide-liburua</comment>
- <comment xml:lang="fi">LDIF-osoitekirja</comment>
- <comment xml:lang="fo">LDIF adressubók</comment>
- <comment xml:lang="fr">carnet d'adresses LDIF</comment>
- <comment xml:lang="ga">leabhar seoltaí LDIF</comment>
- <comment xml:lang="gl">lista de enderezos LDIF</comment>
- <comment xml:lang="he">ספר כתובות של LDIF</comment>
- <comment xml:lang="hr">LDIF adresar</comment>
- <comment xml:lang="hu">LDIF címjegyzék</comment>
- <comment xml:lang="ia">Adressario LDIF</comment>
- <comment xml:lang="id">Buku alamat LDIF</comment>
- <comment xml:lang="it">Rubrica LDIF</comment>
- <comment xml:lang="ja">LDIF アドレス帳</comment>
- <comment xml:lang="kk">LDIF адрестер кітабы</comment>
- <comment xml:lang="ko">LDIF 주소록</comment>
- <comment xml:lang="lt">LDIF adresų knygelė</comment>
- <comment xml:lang="lv">LDIF adrešu grāmata</comment>
- <comment xml:lang="nb">LDIF-adressebok</comment>
- <comment xml:lang="nl">LDIF-adresboek</comment>
- <comment xml:lang="nn">LDIF-adressebok</comment>
- <comment xml:lang="oc">quasernet d'adreças LDIF</comment>
- <comment xml:lang="pl">Książka adresowa LDIF</comment>
- <comment xml:lang="pt">livro de endereços LDIF</comment>
- <comment xml:lang="pt_BR">Livro de endereços LDIF</comment>
- <comment xml:lang="ro">Agendă LDIF</comment>
- <comment xml:lang="ru">Адресная книга LDIF</comment>
- <comment xml:lang="sk">Adresár LDIF</comment>
- <comment xml:lang="sl">Datoteka imenika naslovov LDIF</comment>
- <comment xml:lang="sq">Rubrikë LDIF</comment>
- <comment xml:lang="sr">ЛДИФ адресар</comment>
- <comment xml:lang="sv">LDIF-adressbok</comment>
- <comment xml:lang="tr">LDIF adres defteri</comment>
- <comment xml:lang="uk">адресна книга LDIF</comment>
- <comment xml:lang="vi">Sổ địa chỉ LDIF</comment>
- <comment xml:lang="zh_CN">LDIF 地址簿</comment>
<comment xml:lang="zh_TW">LDIF 通訊錄</comment>
+ <comment xml:lang="zh_CN">LDIF 地址簿</comment>
+ <comment xml:lang="vi">Sổ địa chỉ LDIF</comment>
+ <comment xml:lang="uk">адресна книга LDIF</comment>
+ <comment xml:lang="tr">LDIF adres defteri</comment>
+ <comment xml:lang="sv">LDIF-adressbok</comment>
+ <comment xml:lang="sr">ЛДИФ адресар</comment>
+ <comment xml:lang="sq">libër adresash LDIF</comment>
+ <comment xml:lang="sl">Datoteka imenika naslovov LDIF</comment>
+ <comment xml:lang="si">LDIF ලිපින පොත</comment>
+ <comment xml:lang="sk">Adresár LDIF</comment>
+ <comment xml:lang="ru">Адресная книга LDIF</comment>
+ <comment xml:lang="ro">Agendă LDIF</comment>
+ <comment xml:lang="pt_BR">Livro de endereços LDIF</comment>
+ <comment xml:lang="pt">livro de endereços LDIF</comment>
+ <comment xml:lang="pl">Książka adresowa LDIF</comment>
+ <comment xml:lang="oc">quasernet d'adreças LDIF</comment>
+ <comment xml:lang="nn">LDIF-adressebok</comment>
+ <comment xml:lang="nl">LDIF-adresboek</comment>
+ <comment xml:lang="nb">LDIF-adressebok</comment>
+ <comment xml:lang="lv">LDIF adrešu grāmata</comment>
+ <comment xml:lang="lt">LDIF adresų knygelė</comment>
+ <comment xml:lang="ko">LDIF 주소록</comment>
+ <comment xml:lang="kk">LDIF адрестер кітабы</comment>
+ <comment xml:lang="ja">LDIF アドレス帳</comment>
+ <comment xml:lang="it">Rubrica LDIF</comment>
+ <comment xml:lang="is">LDIF-nafnaskrá</comment>
+ <comment xml:lang="id">Buku alamat LDIF</comment>
+ <comment xml:lang="ia">Adressario LDIF</comment>
+ <comment xml:lang="hu">LDIF címjegyzék</comment>
+ <comment xml:lang="hr">LDIF adresar</comment>
+ <comment xml:lang="he">ספר כתובות של LDIF</comment>
+ <comment xml:lang="gl">lista de enderezos LDIF</comment>
+ <comment xml:lang="ga">leabhar seoltaí LDIF</comment>
+ <comment xml:lang="fur">rubriche LDIF</comment>
+ <comment xml:lang="fr">carnet d'adresses LDIF</comment>
+ <comment xml:lang="fo">LDIF adressubók</comment>
+ <comment xml:lang="fi">LDIF-osoitekirja</comment>
+ <comment xml:lang="eu">LDIF helbide-liburua</comment>
+ <comment xml:lang="es">libreta de direcciones LDIF</comment>
+ <comment xml:lang="eo">LDIF-adresaro</comment>
+ <comment xml:lang="en_GB">LDIF address book</comment>
+ <comment xml:lang="el">Βιβλίο διευθύνσεων LDIF</comment>
+ <comment xml:lang="de">LDIF-Adressbuch</comment>
+ <comment xml:lang="da">LDIF-adressebog</comment>
+ <comment xml:lang="cs">adresář LDIF</comment>
+ <comment xml:lang="ca">llibreta d'adreces LDIF</comment>
+ <comment xml:lang="bg">Адресна книга — LDIF</comment>
+ <comment xml:lang="be@latin">Adrasnaja kniha LDIF</comment>
+ <comment xml:lang="be">адрасная кніга LDIF</comment>
+ <comment xml:lang="ar">دفتر عناوين LDIF</comment>
+ <comment xml:lang="af">LDIF-adresboek</comment>
<acronym>LDIF</acronym>
<expanded-acronym>LDAP Data Interchange Format</expanded-acronym>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="dn: cn=" type="string" offset="0"/>
- <match value="dn: mail=" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="dn: cn=" offset="0"/>
+ <match type="string" value="dn: mail=" offset="0"/>
</magic>
<glob pattern="*.ldif"/>
</mime-type>
<mime-type type="text/x-lilypond">
<comment>Lilypond music sheet</comment>
- <comment xml:lang="ar">صفحة موسيقى Lilypond</comment>
- <comment xml:lang="be@latin">Muzyčny arkuš Lilypond</comment>
- <comment xml:lang="bg">Нотация на Lilypond</comment>
- <comment xml:lang="ca">full de música Lilypond</comment>
- <comment xml:lang="cs">notový papír Lilypond</comment>
- <comment xml:lang="da">Lilypondmusikkort</comment>
- <comment xml:lang="de">Lilypond-Notenblatt</comment>
- <comment xml:lang="el">Παρτιτούρα Lilypond</comment>
- <comment xml:lang="en_GB">Lilypond music sheet</comment>
- <comment xml:lang="es">partitura de LilyPond</comment>
- <comment xml:lang="eu">Lilypond musika-orria</comment>
- <comment xml:lang="fi">Lilypond-nuotit</comment>
- <comment xml:lang="fo">Lilypond tónleika ark</comment>
- <comment xml:lang="fr">partition musicale Lilypond</comment>
- <comment xml:lang="ga">bileog cheoil Lilypond</comment>
- <comment xml:lang="gl">folla de música de Lilypond</comment>
- <comment xml:lang="he">דף מוזיקה של Lilypond</comment>
- <comment xml:lang="hr">Lilypond glazbena ljestvica</comment>
- <comment xml:lang="hu">Lilypond kotta</comment>
- <comment xml:lang="ia">Partition musical Lilypond</comment>
- <comment xml:lang="id">Lembar musik Lilypond</comment>
- <comment xml:lang="it">Partitura Lilypond</comment>
- <comment xml:lang="ja">Lilypond 楽譜データ</comment>
- <comment xml:lang="kk">Lilypond музыка тізімі</comment>
- <comment xml:lang="ko">Lilypond 악보</comment>
- <comment xml:lang="lt">Lilypond muzikos lapas</comment>
- <comment xml:lang="lv">Lilypond mūzikas lapa</comment>
- <comment xml:lang="nl">Lilypond-muziekblad</comment>
- <comment xml:lang="nn">Lilypond noteark</comment>
- <comment xml:lang="oc">particion musicala Lilypond</comment>
- <comment xml:lang="pl">Plik partytury Lilypond</comment>
- <comment xml:lang="pt">folha de música Lilypond</comment>
- <comment xml:lang="pt_BR">Partitura do Lilypond</comment>
- <comment xml:lang="ro">Fișă muzică Lilypond</comment>
- <comment xml:lang="ru">Список музыки Lilypond</comment>
- <comment xml:lang="sk">Notový papier Lilypond</comment>
- <comment xml:lang="sl">Glasbena predloga Lilypond</comment>
- <comment xml:lang="sq">Partiturë Lilypond</comment>
- <comment xml:lang="sr">Лилипонд музички лист</comment>
- <comment xml:lang="sv">Lilypond-notblad</comment>
- <comment xml:lang="tr">Lilypond müzik sayfası</comment>
- <comment xml:lang="uk">нотний запис Lilypond</comment>
- <comment xml:lang="vi">Bản nhạc Lilypond</comment>
- <comment xml:lang="zh_CN">Lilypond 乐谱</comment>
<comment xml:lang="zh_TW">Lilypond 樂譜</comment>
+ <comment xml:lang="zh_CN">Lilypond 乐谱</comment>
+ <comment xml:lang="vi">Bản nhạc Lilypond</comment>
+ <comment xml:lang="uk">нотний запис Lilypond</comment>
+ <comment xml:lang="tr">Lilypond müzik sayfası</comment>
+ <comment xml:lang="sv">Lilypond-notblad</comment>
+ <comment xml:lang="sr">Лилипонд музички лист</comment>
+ <comment xml:lang="sq">partiturë Lilypond</comment>
+ <comment xml:lang="sl">Glasbena predloga Lilypond</comment>
+ <comment xml:lang="si">ලිලිපොන්ඩ් සංගීත පත්රය</comment>
+ <comment xml:lang="sk">Notový papier Lilypond</comment>
+ <comment xml:lang="ru">Список музыки Lilypond</comment>
+ <comment xml:lang="ro">Fișă muzică Lilypond</comment>
+ <comment xml:lang="pt_BR">Partitura do Lilypond</comment>
+ <comment xml:lang="pt">folha de música Lilypond</comment>
+ <comment xml:lang="pl">Plik partytury Lilypond</comment>
+ <comment xml:lang="oc">particion musicala Lilypond</comment>
+ <comment xml:lang="nn">Lilypond noteark</comment>
+ <comment xml:lang="nl">Lilypond-muziekblad</comment>
+ <comment xml:lang="lv">Lilypond mūzikas lapa</comment>
+ <comment xml:lang="lt">Lilypond muzikos lapas</comment>
+ <comment xml:lang="ko">Lilypond 악보</comment>
+ <comment xml:lang="kk">Lilypond музыка тізімі</comment>
+ <comment xml:lang="ja">Lilypond 楽譜データ</comment>
+ <comment xml:lang="it">Partitura Lilypond</comment>
+ <comment xml:lang="is">LilyPond nótnablað</comment>
+ <comment xml:lang="id">Lembar musik Lilypond</comment>
+ <comment xml:lang="ia">Partition musical Lilypond</comment>
+ <comment xml:lang="hu">Lilypond kotta</comment>
+ <comment xml:lang="hr">Lilypond glazbena ljestvica</comment>
+ <comment xml:lang="he">דף מוזיקה של Lilypond</comment>
+ <comment xml:lang="gl">folla de música de Lilypond</comment>
+ <comment xml:lang="ga">bileog cheoil Lilypond</comment>
+ <comment xml:lang="fur">spartît Lilypond</comment>
+ <comment xml:lang="fr">partition musicale Lilypond</comment>
+ <comment xml:lang="fo">Lilypond tónleika ark</comment>
+ <comment xml:lang="fi">Lilypond-nuotit</comment>
+ <comment xml:lang="eu">Lilypond musika-orria</comment>
+ <comment xml:lang="es">partitura de LilyPond</comment>
+ <comment xml:lang="en_GB">Lilypond music sheet</comment>
+ <comment xml:lang="el">Παρτιτούρα Lilypond</comment>
+ <comment xml:lang="de">Lilypond-Notenblatt</comment>
+ <comment xml:lang="da">Lilypondmusikkort</comment>
+ <comment xml:lang="cs">notový papír Lilypond</comment>
+ <comment xml:lang="ca">full de música Lilypond</comment>
+ <comment xml:lang="bg">Нотация на Lilypond</comment>
+ <comment xml:lang="be@latin">Muzyčny arkuš Lilypond</comment>
+ <comment xml:lang="be">нотны запіс Lilypond</comment>
+ <comment xml:lang="ar">صفحة موسيقى Lilypond</comment>
+ <comment xml:lang="af">Lilypond-musiekblad</comment>
<glob pattern="*.ly"/>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="text/x-literate-haskell">
<comment>LHS source code</comment>
- <comment xml:lang="ar">شفرة مصدر LHS</comment>
- <comment xml:lang="be@latin">Kryničny kod LHS</comment>
- <comment xml:lang="bg">Изходен код на LHS</comment>
- <comment xml:lang="ca">codi font en LHS</comment>
- <comment xml:lang="cs">zdrojový kód LHS</comment>
- <comment xml:lang="da">LHS-kildekode</comment>
- <comment xml:lang="de">LHS-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας LHS</comment>
- <comment xml:lang="en_GB">LHS source code</comment>
- <comment xml:lang="eo">LHS-fontkodo</comment>
- <comment xml:lang="es">código fuente en LHS</comment>
- <comment xml:lang="eu">LHS iturburu-kodea</comment>
- <comment xml:lang="fi">LHS-lähdekoodi</comment>
- <comment xml:lang="fo">LHS keld</comment>
- <comment xml:lang="fr">code source LHS</comment>
- <comment xml:lang="ga">cód foinseach LHS</comment>
- <comment xml:lang="gl">código fonte en LHS</comment>
- <comment xml:lang="he">קוד מקור של LHS</comment>
- <comment xml:lang="hr">LHS izvorni kôd</comment>
- <comment xml:lang="hu">LHS forráskód</comment>
- <comment xml:lang="ia">Codice-fonte LHS</comment>
- <comment xml:lang="id">Kode sumber LHS</comment>
- <comment xml:lang="it">Codice sorgente LHS</comment>
- <comment xml:lang="ja">LHS ソースコード</comment>
- <comment xml:lang="kk">LHS бастапқы коды</comment>
- <comment xml:lang="ko">LHS 소스 코드</comment>
- <comment xml:lang="lt">LHS pradinis kodas</comment>
- <comment xml:lang="lv">LHS pirmkods</comment>
- <comment xml:lang="nb">LHS-kildekode</comment>
- <comment xml:lang="nl">LHS-broncode</comment>
- <comment xml:lang="nn">LHS-kjeldekode</comment>
- <comment xml:lang="oc">còde font LHS</comment>
- <comment xml:lang="pl">Kod źródłowy LHS</comment>
- <comment xml:lang="pt">código origem LHS</comment>
- <comment xml:lang="pt_BR">Código-fonte LHS</comment>
- <comment xml:lang="ro">Cod sursă LHS</comment>
- <comment xml:lang="ru">Исходный код LHS</comment>
- <comment xml:lang="sk">Zdrojový kód LHS</comment>
- <comment xml:lang="sl">Datoteka izvorne kode LHS</comment>
- <comment xml:lang="sq">Kod burues LHS</comment>
- <comment xml:lang="sr">ЛХС изворни ко̂д</comment>
- <comment xml:lang="sv">LHS-källkod</comment>
- <comment xml:lang="tr">LHS kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код LHS</comment>
- <comment xml:lang="vi">Mã nguồn LHS</comment>
- <comment xml:lang="zh_CN">LHS 源代码</comment>
<comment xml:lang="zh_TW">LHS 源碼</comment>
+ <comment xml:lang="zh_CN">LHS 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn LHS</comment>
+ <comment xml:lang="uk">початковий код LHS</comment>
+ <comment xml:lang="tr">LHS kaynak kodu</comment>
+ <comment xml:lang="sv">LHS-källkod</comment>
+ <comment xml:lang="sr">ЛХС изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim LHS</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode LHS</comment>
+ <comment xml:lang="si">LHS මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód LHS</comment>
+ <comment xml:lang="ru">Исходный код LHS</comment>
+ <comment xml:lang="ro">Cod sursă LHS</comment>
+ <comment xml:lang="pt_BR">Código-fonte LHS</comment>
+ <comment xml:lang="pt">código origem LHS</comment>
+ <comment xml:lang="pl">Kod źródłowy LHS</comment>
+ <comment xml:lang="oc">còde font LHS</comment>
+ <comment xml:lang="nn">LHS-kjeldekode</comment>
+ <comment xml:lang="nl">LHS-broncode</comment>
+ <comment xml:lang="nb">LHS-kildekode</comment>
+ <comment xml:lang="lv">LHS pirmkods</comment>
+ <comment xml:lang="lt">LHS pradinis kodas</comment>
+ <comment xml:lang="ko">LHS 소스 코드</comment>
+ <comment xml:lang="kk">LHS бастапқы коды</comment>
+ <comment xml:lang="ja">LHS ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente LHS</comment>
+ <comment xml:lang="is">LHS frumkóði</comment>
+ <comment xml:lang="id">Kode sumber LHS</comment>
+ <comment xml:lang="ia">Codice-fonte LHS</comment>
+ <comment xml:lang="hu">LHS forráskód</comment>
+ <comment xml:lang="hr">LHS izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של LHS</comment>
+ <comment xml:lang="gl">código fonte en LHS</comment>
+ <comment xml:lang="ga">cód foinseach LHS</comment>
+ <comment xml:lang="fur">codiç sorzint LHS</comment>
+ <comment xml:lang="fr">code source LHS</comment>
+ <comment xml:lang="fo">LHS keld</comment>
+ <comment xml:lang="fi">LHS-lähdekoodi</comment>
+ <comment xml:lang="eu">LHS iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en LHS</comment>
+ <comment xml:lang="eo">LHS-fontkodo</comment>
+ <comment xml:lang="en_GB">LHS source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας LHS</comment>
+ <comment xml:lang="de">LHS-Quelltext</comment>
+ <comment xml:lang="da">LHS-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód LHS</comment>
+ <comment xml:lang="ca">codi font en LHS</comment>
+ <comment xml:lang="bg">Изходен код — LHS</comment>
+ <comment xml:lang="be@latin">Kryničny kod LHS</comment>
+ <comment xml:lang="be">зыходны код LHS</comment>
+ <comment xml:lang="ar">شفرة مصدر LHS</comment>
+ <comment xml:lang="af">LHS-bronkode</comment>
<acronym>LHS</acronym>
<expanded-acronym>Literate Haskell source code</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.lhs"/>
</mime-type>
<mime-type type="text/x-log">
- <comment>application log</comment>
- <comment xml:lang="ar">سجل التطبيق</comment>
- <comment xml:lang="ast">rexistru d'aplicación</comment>
- <comment xml:lang="be@latin">časopis aplikacyi</comment>
- <comment xml:lang="bg">Файл-дневник на приложение</comment>
- <comment xml:lang="ca">registre d'aplicació</comment>
- <comment xml:lang="cs">záznam aplikace</comment>
- <comment xml:lang="da">programlog</comment>
- <comment xml:lang="de">Anwendungsprotokoll</comment>
- <comment xml:lang="el">Καταγραφή εφαρμογή</comment>
- <comment xml:lang="en_GB">application log</comment>
- <comment xml:lang="eo">protokolo de aplikaĵo</comment>
- <comment xml:lang="es">registro de aplicación</comment>
- <comment xml:lang="eu">aplikazio egunkaria</comment>
- <comment xml:lang="fi">sovelluksen lokitiedosto</comment>
- <comment xml:lang="fo">nýtsluskipan logg</comment>
- <comment xml:lang="fr">journal d'application</comment>
- <comment xml:lang="ga">logchomhad feidhmchláir</comment>
- <comment xml:lang="gl">rexistro de aplicativo</comment>
- <comment xml:lang="he">יומן יישום</comment>
- <comment xml:lang="hr">Zapis aplikacije</comment>
- <comment xml:lang="hu">alkalmazás naplója</comment>
- <comment xml:lang="ia">Registro de application</comment>
- <comment xml:lang="id">log aplikasi</comment>
- <comment xml:lang="it">Registro applicazione</comment>
- <comment xml:lang="ja">アプリケーションログ</comment>
- <comment xml:lang="kk">мәлімдемелер журналы</comment>
- <comment xml:lang="ko">프로그램 기록</comment>
- <comment xml:lang="lt">programos žurnalas</comment>
- <comment xml:lang="lv">lietotnes žurnāls</comment>
- <comment xml:lang="ms">Log aplikasi</comment>
- <comment xml:lang="nb">applikasjonslogg</comment>
- <comment xml:lang="nl">programma-logbestand</comment>
- <comment xml:lang="nn">programlogg</comment>
- <comment xml:lang="oc">jornal d'aplicacion</comment>
- <comment xml:lang="pl">Dziennik programu</comment>
- <comment xml:lang="pt">diário de aplicação</comment>
- <comment xml:lang="pt_BR">Registro de aplicativo</comment>
- <comment xml:lang="ro">înregistrare aplicație</comment>
- <comment xml:lang="ru">Журнал сообщений</comment>
- <comment xml:lang="sk">Záznam aplikácie</comment>
- <comment xml:lang="sl">dnevnik programa</comment>
- <comment xml:lang="sq">log i mesazheve të programit</comment>
- <comment xml:lang="sr">дневник програма</comment>
- <comment xml:lang="sv">programlogg</comment>
- <comment xml:lang="tr">uygulama günlüğü</comment>
+ <comment>Application log</comment>
<comment xml:lang="uk">журнал програми</comment>
- <comment xml:lang="vi">bản ghi ứng dụng</comment>
- <comment xml:lang="zh_CN">应用程序日志</comment>
- <comment xml:lang="zh_TW">程式紀錄檔</comment>
+ <comment xml:lang="sv">Programlogg</comment>
+ <comment xml:lang="ru">Журнал сообщений</comment>
+ <comment xml:lang="pl">Dziennik programu</comment>
+ <comment xml:lang="ja">アプリケーション記録</comment>
+ <comment xml:lang="it">Registro applicazione</comment>
+ <comment xml:lang="gl">Rexistro de aplicación</comment>
+ <comment xml:lang="eu">Aplikazio-egunkaria</comment>
+ <comment xml:lang="es">registro de aplicaciones</comment>
+ <comment xml:lang="de">Anwendungsprotokoll</comment>
+ <comment xml:lang="be">журнал праграмы</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.log"/>
</mime-type>
<mime-type type="text/x-makefile">
- <comment>Makefile</comment>
- <comment xml:lang="ar">ملف Makefile</comment>
- <comment xml:lang="az">İnşa faylı</comment>
- <comment xml:lang="be@latin">Makefile</comment>
- <comment xml:lang="bg">Файл — make</comment>
- <comment xml:lang="ca">Makefile</comment>
- <comment xml:lang="cs">Makefile</comment>
- <comment xml:lang="cy">Ffeil "make"</comment>
- <comment xml:lang="da">Bygningsfil</comment>
- <comment xml:lang="de">Makefile</comment>
- <comment xml:lang="el">Makefile</comment>
- <comment xml:lang="en_GB">Makefile</comment>
- <comment xml:lang="eo">Muntodosiero</comment>
- <comment xml:lang="es">Makefile</comment>
- <comment xml:lang="eu">Makefile</comment>
- <comment xml:lang="fi">Makefile</comment>
- <comment xml:lang="fo">Makefile</comment>
- <comment xml:lang="fr">makefile</comment>
- <comment xml:lang="ga">Makefile</comment>
- <comment xml:lang="gl">Makefile</comment>
- <comment xml:lang="he">Makefile</comment>
- <comment xml:lang="hr">Makefile</comment>
- <comment xml:lang="hu">Makefile</comment>
- <comment xml:lang="ia">Makefile</comment>
- <comment xml:lang="id">Makefile</comment>
- <comment xml:lang="it">Makefile</comment>
- <comment xml:lang="ja">Makefile</comment>
- <comment xml:lang="ka">Makefile</comment>
- <comment xml:lang="kk">Makefile (жинау файлы)</comment>
- <comment xml:lang="ko">Makefile</comment>
- <comment xml:lang="lt">Makefile</comment>
- <comment xml:lang="lv">Makefile</comment>
- <comment xml:lang="ms">Makefile</comment>
- <comment xml:lang="nb">Makefile</comment>
- <comment xml:lang="nl">Makefile</comment>
- <comment xml:lang="nn">Makefile</comment>
- <comment xml:lang="oc">makefile</comment>
- <comment xml:lang="pl">Plik make</comment>
- <comment xml:lang="pt">Makefile</comment>
- <comment xml:lang="pt_BR">Makefile (arquivo do make)</comment>
- <comment xml:lang="ro">Makefile</comment>
- <comment xml:lang="ru">Файл Makefile</comment>
- <comment xml:lang="sk">Makefile</comment>
- <comment xml:lang="sl">Datoteka Makefile</comment>
- <comment xml:lang="sq">Makefile</comment>
- <comment xml:lang="sr">датотека стварања</comment>
- <comment xml:lang="sv">Makefil</comment>
- <comment xml:lang="tr">Makefile</comment>
- <comment xml:lang="uk">файл проекту make</comment>
- <comment xml:lang="vi">Tập tin tạo ứng dụng (Makefile)</comment>
- <comment xml:lang="zh_CN">Makefile</comment>
- <comment xml:lang="zh_TW">Makefile</comment>
+ <comment>Makefile build file</comment>
+ <comment xml:lang="zh_CN">Makefile 构建文件</comment>
+ <comment xml:lang="uk">файл збирання Makefile</comment>
+ <comment xml:lang="tr">Makefile derleme dosyası</comment>
+ <comment xml:lang="sv">Makefile-byggfil</comment>
+ <comment xml:lang="sq">kartelë montimi Makefile</comment>
+ <comment xml:lang="si">Makefile ගොඩනැගීමේ ගොනුව</comment>
+ <comment xml:lang="sk">Súbor zostavenia Makefile</comment>
+ <comment xml:lang="ru">Сборочный файл Makefile</comment>
+ <comment xml:lang="pt_BR">Arquivo de compilação Makefile</comment>
+ <comment xml:lang="pl">Plik budowania Makefile</comment>
+ <comment xml:lang="nl">Makefile-compilatiebestand</comment>
+ <comment xml:lang="ko">Makefile 빌드 파일</comment>
+ <comment xml:lang="kk">Makefile құрастыру файлы</comment>
+ <comment xml:lang="ja">Makefile ビルドファイル</comment>
+ <comment xml:lang="it">File compilazione Makefile</comment>
+ <comment xml:lang="is">Makefile byggingaskrá</comment>
+ <comment xml:lang="id">Berkas build Makefile</comment>
+ <comment xml:lang="hu">Makefile összeállítási fájl</comment>
+ <comment xml:lang="hr">Makefile datoteka izgradnje</comment>
+ <comment xml:lang="he">קובץ בניית Makefile</comment>
+ <comment xml:lang="gl">Ficheiro de construción Makefile</comment>
+ <comment xml:lang="fr">fichier de construction Makefile</comment>
+ <comment xml:lang="fi">Makefile-rakennustiedosto</comment>
+ <comment xml:lang="eu">Makefile build fitxategia</comment>
+ <comment xml:lang="es">archivo de generación Makefile</comment>
+ <comment xml:lang="en_GB">Makefile build file</comment>
+ <comment xml:lang="de">Makefile Build-Datei</comment>
+ <comment xml:lang="da">Makefile build-fil</comment>
+ <comment xml:lang="ca">fitxer de construcció Makefile</comment>
+ <comment xml:lang="bg">Проект — Makefile</comment>
+ <comment xml:lang="be">файл зборкі Makefile</comment>
+ <comment xml:lang="ar">ملف بناء Makefile</comment>
<sub-class-of type="text/plain"/>
<glob pattern="makefile"/>
<glob pattern="GNUmakefile"/>
<glob pattern="*.mk"/>
<glob pattern="*.mak"/>
<glob weight="10" pattern="Makefile.*"/>
- <magic priority="50">
- <match value="#!/usr/bin/make" type="string" offset="0"/>
- <match value="#! /usr/bin/make" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#!/usr/bin/make" offset="0"/>
+ <match type="string" value="#! /usr/bin/make" offset="0"/>
</magic>
</mime-type>
<mime-type type="text/markdown">
<comment>Markdown document</comment>
- <comment xml:lang="ast">Documentu Markdown</comment>
- <comment xml:lang="bg">Документ — Markdown</comment>
- <comment xml:lang="ca">document Markdown</comment>
- <comment xml:lang="cs">dokument Markdown</comment>
- <comment xml:lang="da">Markdown-dokument</comment>
- <comment xml:lang="de">Markdown-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Markdown</comment>
- <comment xml:lang="en_GB">Markdown document</comment>
- <comment xml:lang="es">documento Markdown</comment>
- <comment xml:lang="eu">Markdown dokumentua</comment>
- <comment xml:lang="fi">Markdown-asiakirja</comment>
- <comment xml:lang="fr">document Markdown</comment>
- <comment xml:lang="ga">cáipéis Markdown</comment>
- <comment xml:lang="gl">documento de Markdown</comment>
- <comment xml:lang="he">מסמך Markdown</comment>
- <comment xml:lang="hr">Markdown dokument</comment>
- <comment xml:lang="hu">Markdown dokumentum</comment>
- <comment xml:lang="ia">Documento Markdown</comment>
- <comment xml:lang="id">Dokumen markdown</comment>
- <comment xml:lang="it">Documento Markdown</comment>
- <comment xml:lang="ja">Markdown </comment>
- <comment xml:lang="kk">Markdown құжаты</comment>
- <comment xml:lang="ko">마크다운 문서</comment>
- <comment xml:lang="lv">Markdown dokuments</comment>
- <comment xml:lang="nl">Markdown document</comment>
- <comment xml:lang="oc">document Markdown</comment>
- <comment xml:lang="pl">Dokument Markdown</comment>
- <comment xml:lang="pt">documento Markdown</comment>
- <comment xml:lang="pt_BR">Documento Markdown</comment>
- <comment xml:lang="ru">Документ Markdown</comment>
- <comment xml:lang="sk">Dokument Markdown</comment>
- <comment xml:lang="sl">Dokument Markdown</comment>
- <comment xml:lang="sr">Маркдаун документ</comment>
- <comment xml:lang="sv">Markdown-dokument</comment>
- <comment xml:lang="tr">Markdown belgesi</comment>
- <comment xml:lang="uk">документ Markdown</comment>
- <comment xml:lang="zh_CN">Markdown 文档</comment>
<comment xml:lang="zh_TW">Markdown 文件</comment>
+ <comment xml:lang="zh_CN">Markdown 文档</comment>
+ <comment xml:lang="uk">документ Markdown</comment>
+ <comment xml:lang="tr">Markdown belgesi</comment>
+ <comment xml:lang="sv">Markdown-dokument</comment>
+ <comment xml:lang="sr">Маркдаун документ</comment>
+ <comment xml:lang="sq">dokument Markdown</comment>
+ <comment xml:lang="sl">Dokument Markdown</comment>
+ <comment xml:lang="si">සලකුණු ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Markdown</comment>
+ <comment xml:lang="ru">Документ Markdown</comment>
+ <comment xml:lang="pt_BR">Documento Markdown</comment>
+ <comment xml:lang="pt">documento Markdown</comment>
+ <comment xml:lang="pl">Dokument Markdown</comment>
+ <comment xml:lang="oc">document Markdown</comment>
+ <comment xml:lang="nl">Markdown-document</comment>
+ <comment xml:lang="lv">Markdown dokuments</comment>
+ <comment xml:lang="ko">마크다운 문서</comment>
+ <comment xml:lang="kk">Markdown құжаты</comment>
+ <comment xml:lang="ja">Markdown </comment>
+ <comment xml:lang="it">Documento Markdown</comment>
+ <comment xml:lang="is">Markdown skjal</comment>
+ <comment xml:lang="id">Dokumen markdown</comment>
+ <comment xml:lang="ia">Documento Markdown</comment>
+ <comment xml:lang="hu">Markdown dokumentum</comment>
+ <comment xml:lang="hr">Markdown dokument</comment>
+ <comment xml:lang="he">מסמך Markdown</comment>
+ <comment xml:lang="gl">documento de Markdown</comment>
+ <comment xml:lang="ga">cáipéis Markdown</comment>
+ <comment xml:lang="fur">document Markdown</comment>
+ <comment xml:lang="fr">document Markdown</comment>
+ <comment xml:lang="fi">Markdown-asiakirja</comment>
+ <comment xml:lang="eu">Markdown dokumentua</comment>
+ <comment xml:lang="es">documento Markdown</comment>
+ <comment xml:lang="en_GB">Markdown document</comment>
+ <comment xml:lang="el">Έγγραφο Markdown</comment>
+ <comment xml:lang="de">Markdown-Dokument</comment>
+ <comment xml:lang="da">Markdown-dokument</comment>
+ <comment xml:lang="cs">dokument Markdown</comment>
+ <comment xml:lang="ca">document Markdown</comment>
+ <comment xml:lang="bg">Документ — Markdown</comment>
+ <comment xml:lang="be">дакумент Markdown</comment>
+ <comment xml:lang="ast">Documentu Markdown</comment>
+ <comment xml:lang="ar">مستند مارك داون</comment>
+ <comment xml:lang="af">Markdown-dokument</comment>
<sub-class-of type="text/plain"/>
+ <generic-icon name="x-office-document"/>
<glob pattern="*.md"/>
<glob pattern="*.mkd"/>
<glob pattern="*.markdown"/>
@@ -35064,52 +37092,56 @@
</mime-type>
<mime-type type="text/x-moc">
<comment>Qt MOC file</comment>
- <comment xml:lang="ar">ملف Qt MOC</comment>
- <comment xml:lang="be@latin">Fajł Qt MOC</comment>
- <comment xml:lang="bg">Файл — Qt MOC</comment>
- <comment xml:lang="ca">fitxer MOC de Qt</comment>
- <comment xml:lang="cs">soubor Qt MOC</comment>
- <comment xml:lang="da">Qt MOC-fil</comment>
- <comment xml:lang="de">Qt-MOC-Datei</comment>
- <comment xml:lang="el">Αρχείο Qt MOC</comment>
- <comment xml:lang="en_GB">Qt MOC file</comment>
- <comment xml:lang="es">archivo MOC Qt</comment>
- <comment xml:lang="eu">Qt MOC fitxategia</comment>
- <comment xml:lang="fi">Qt MOC -tiedosto</comment>
- <comment xml:lang="fo">Qt MOC fíla</comment>
- <comment xml:lang="fr">fichier Qt MOC</comment>
- <comment xml:lang="ga">comhad MOC Qt</comment>
- <comment xml:lang="gl">ficheiro MOC Qt</comment>
- <comment xml:lang="he">קובץ Qt MOC</comment>
- <comment xml:lang="hr">Qt MOC datoteka</comment>
- <comment xml:lang="hu">Qt MOC fájl</comment>
- <comment xml:lang="ia">File Qt MOC</comment>
- <comment xml:lang="id">Berkas Qt MOC</comment>
- <comment xml:lang="it">File MOC Qt</comment>
- <comment xml:lang="ja">Qt MOC ファイル</comment>
- <comment xml:lang="kk">Qt MOC файлы</comment>
- <comment xml:lang="ko">Qt MOC 파일</comment>
- <comment xml:lang="lt">Qt MOC failas</comment>
- <comment xml:lang="lv">Qt MOC datne</comment>
- <comment xml:lang="nb">Qt MOC-fil</comment>
- <comment xml:lang="nl">Qt MOC-bestand</comment>
- <comment xml:lang="nn">Qt MOC-fil</comment>
- <comment xml:lang="oc">fichièr Qt MOC</comment>
- <comment xml:lang="pl">Plik Qt MOC</comment>
- <comment xml:lang="pt">ficheiro Qt MOC</comment>
- <comment xml:lang="pt_BR">Arquivo Qt MOC</comment>
- <comment xml:lang="ro">Fișier Qt MOC</comment>
- <comment xml:lang="ru">Файл Qt MOC</comment>
- <comment xml:lang="sk">Súbor Qt MOC</comment>
- <comment xml:lang="sl">Datoteka Qt MOC</comment>
- <comment xml:lang="sq">File Qt MOC</comment>
- <comment xml:lang="sr">Кут МОЦ датотека</comment>
- <comment xml:lang="sv">Qt MOC-fil</comment>
- <comment xml:lang="tr">Qt MOC dosyası</comment>
- <comment xml:lang="uk">файл-метаоб'єкт Qt</comment>
- <comment xml:lang="vi">Tập tin MOC của Qt</comment>
- <comment xml:lang="zh_CN">Qt 元对象编译器文件</comment>
<comment xml:lang="zh_TW">Qt MOC 檔</comment>
+ <comment xml:lang="zh_CN">Qt 元对象编译器文件</comment>
+ <comment xml:lang="vi">Tập tin MOC của Qt</comment>
+ <comment xml:lang="uk">файл-метаоб'єкт Qt</comment>
+ <comment xml:lang="tr">Qt MOC dosyası</comment>
+ <comment xml:lang="sv">Qt MOC-fil</comment>
+ <comment xml:lang="sr">Кут МОЦ датотека</comment>
+ <comment xml:lang="sq">kartelë Qt MOC</comment>
+ <comment xml:lang="sl">Datoteka Qt MOC</comment>
+ <comment xml:lang="si">Qt MOC ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Qt MOC</comment>
+ <comment xml:lang="ru">Файл Qt MOC</comment>
+ <comment xml:lang="ro">Fișier Qt MOC</comment>
+ <comment xml:lang="pt_BR">Arquivo Qt MOC</comment>
+ <comment xml:lang="pt">ficheiro Qt MOC</comment>
+ <comment xml:lang="pl">Plik Qt MOC</comment>
+ <comment xml:lang="oc">fichièr Qt MOC</comment>
+ <comment xml:lang="nn">Qt MOC-fil</comment>
+ <comment xml:lang="nl">Qt MOC-bestand</comment>
+ <comment xml:lang="nb">Qt MOC-fil</comment>
+ <comment xml:lang="lv">Qt MOC datne</comment>
+ <comment xml:lang="lt">Qt MOC failas</comment>
+ <comment xml:lang="ko">Qt MOC 파일</comment>
+ <comment xml:lang="kk">Qt MOC файлы</comment>
+ <comment xml:lang="ja">Qt MOC ファイル</comment>
+ <comment xml:lang="it">File MOC Qt</comment>
+ <comment xml:lang="is">Qt MOC-skrá</comment>
+ <comment xml:lang="id">Berkas Qt MOC</comment>
+ <comment xml:lang="ia">File Qt MOC</comment>
+ <comment xml:lang="hu">Qt MOC fájl</comment>
+ <comment xml:lang="hr">Qt MOC datoteka</comment>
+ <comment xml:lang="he">קובץ Qt MOC</comment>
+ <comment xml:lang="gl">ficheiro MOC Qt</comment>
+ <comment xml:lang="ga">comhad MOC Qt</comment>
+ <comment xml:lang="fur">file Qt MOC</comment>
+ <comment xml:lang="fr">fichier Qt MOC</comment>
+ <comment xml:lang="fo">Qt MOC fíla</comment>
+ <comment xml:lang="fi">Qt MOC -tiedosto</comment>
+ <comment xml:lang="eu">Qt MOC fitxategia</comment>
+ <comment xml:lang="es">archivo MOC Qt</comment>
+ <comment xml:lang="en_GB">Qt MOC file</comment>
+ <comment xml:lang="el">Αρχείο Qt MOC</comment>
+ <comment xml:lang="de">Qt-MOC-Datei</comment>
+ <comment xml:lang="da">Qt MOC-fil</comment>
+ <comment xml:lang="cs">soubor Qt MOC</comment>
+ <comment xml:lang="ca">fitxer MOC de Qt</comment>
+ <comment xml:lang="bg">Файл — Qt MOC</comment>
+ <comment xml:lang="be@latin">Fajł Qt MOC</comment>
+ <comment xml:lang="be">файл Qt MOC</comment>
+ <comment xml:lang="ar">ملف Qt MOC</comment>
<acronym>Qt MOC</acronym>
<expanded-acronym>Qt Meta Object Compiler</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -35117,653 +37149,751 @@
</mime-type>
<mime-type type="text/x-ms-regedit">
<comment>Windows Registry extract</comment>
- <comment xml:lang="ar">استخراج مسجل ويندوز</comment>
- <comment xml:lang="be@latin">Element rehistru Windows</comment>
- <comment xml:lang="bg">Извадка от регистъра на Windows</comment>
- <comment xml:lang="ca">extracte de Windows Registry</comment>
- <comment xml:lang="cs">výtah registru Windows</comment>
- <comment xml:lang="da">Windows Registy-udtrækning</comment>
- <comment xml:lang="de">Windows-Registry-Auszug</comment>
- <comment xml:lang="el">Αποσυμπίεση Windows Registry</comment>
- <comment xml:lang="en_GB">Windows Registry extract</comment>
- <comment xml:lang="es">extracto del registro de Windows</comment>
- <comment xml:lang="eu">Windows-eko erregistro erauzlea</comment>
- <comment xml:lang="fi">Windows-rekisteritietue</comment>
- <comment xml:lang="fo">Windows Registry úrdráttur</comment>
- <comment xml:lang="fr">extrait de registre Windows</comment>
- <comment xml:lang="ga">sliocht as Clárlann Windows</comment>
- <comment xml:lang="gl">Extracto do rexistro de Windows</comment>
- <comment xml:lang="he">קובץ רשומות מערכת של Windows</comment>
- <comment xml:lang="hr">Izdvojeni Windows registar</comment>
- <comment xml:lang="hu">Windows Registry kivonat</comment>
- <comment xml:lang="ia">Extracto de registro de systema Windows</comment>
- <comment xml:lang="id">Ekstrak Windows Registry</comment>
- <comment xml:lang="it">Estratto Windows Registry</comment>
- <comment xml:lang="ja">WIndows レジストリ抽出ファイル</comment>
- <comment xml:lang="kk">Windows Registry бөлігі</comment>
- <comment xml:lang="ko">Windows 레지스트리 파일</comment>
- <comment xml:lang="lt">Windows registro ištrauka</comment>
- <comment xml:lang="lv">Windows Registry izvilkums</comment>
- <comment xml:lang="nb">Utdrag av Windows Registry</comment>
- <comment xml:lang="nl">Windows Registry-extract</comment>
- <comment xml:lang="nn">Windows Registry-utdrag</comment>
- <comment xml:lang="oc">extrait de registre Windows</comment>
- <comment xml:lang="pl">Wycinek rejestru Windows</comment>
- <comment xml:lang="pt">extrato do registo do Windows</comment>
- <comment xml:lang="pt_BR">Extrator de registro do Windows</comment>
- <comment xml:lang="ro">Extras al registrului Windows</comment>
- <comment xml:lang="ru">Фрагмент Windows Registry</comment>
- <comment xml:lang="sk">Časť registrov Windows</comment>
- <comment xml:lang="sl">izvleček vpisnika Windows</comment>
- <comment xml:lang="sq">Pjesë Windows Registry</comment>
- <comment xml:lang="sr">исцедак Виндоузовог регистра</comment>
- <comment xml:lang="sv">Windows Registry-utdrag</comment>
- <comment xml:lang="tr">Windows Kayıt Defteri özü</comment>
- <comment xml:lang="uk">частина реєстру Windows</comment>
- <comment xml:lang="vi">Bản trích Registry Windows</comment>
- <comment xml:lang="zh_CN">Windows 注册表提取</comment>
<comment xml:lang="zh_TW">Windows Registry 抽出</comment>
+ <comment xml:lang="zh_CN">Windows 注册表提取</comment>
+ <comment xml:lang="vi">Bản trích Registry Windows</comment>
+ <comment xml:lang="uk">частина реєстру Windows</comment>
+ <comment xml:lang="tr">Windows Kayıt Defteri özü</comment>
+ <comment xml:lang="sv">Windows Registry-utdrag</comment>
+ <comment xml:lang="sr">исцедак Виндоузовог регистра</comment>
+ <comment xml:lang="sq">copëz Windows Registry</comment>
+ <comment xml:lang="sl">izvleček vpisnika Windows</comment>
+ <comment xml:lang="si">වින්ඩෝස් රෙජිස්ට්රි උපුටා ගැනීම</comment>
+ <comment xml:lang="sk">Časť registrov Windows</comment>
+ <comment xml:lang="ru">Фрагмент Windows Registry</comment>
+ <comment xml:lang="ro">Extras al registrului Windows</comment>
+ <comment xml:lang="pt_BR">Extrator de registro do Windows</comment>
+ <comment xml:lang="pt">extrato do registo do Windows</comment>
+ <comment xml:lang="pl">Wycinek rejestru Windows</comment>
+ <comment xml:lang="oc">extrait de registre Windows</comment>
+ <comment xml:lang="nn">Windows Registry-utdrag</comment>
+ <comment xml:lang="nl">Windows Registry-extract</comment>
+ <comment xml:lang="nb">Utdrag av Windows Registry</comment>
+ <comment xml:lang="lv">Windows Registry izvilkums</comment>
+ <comment xml:lang="lt">Windows registro ištrauka</comment>
+ <comment xml:lang="ko">Windows 레지스트리 파일</comment>
+ <comment xml:lang="kk">Windows Registry бөлігі</comment>
+ <comment xml:lang="ja">WIndows レジストリ抽出ファイル</comment>
+ <comment xml:lang="it">Estratto Windows Registry</comment>
+ <comment xml:lang="is">Windows Registry útdráttur</comment>
+ <comment xml:lang="id">Ekstrak Windows Registry</comment>
+ <comment xml:lang="ia">Extracto de registro de systema Windows</comment>
+ <comment xml:lang="hu">Windows Registry kivonat</comment>
+ <comment xml:lang="hr">Izdvojeni Windows registar</comment>
+ <comment xml:lang="he">קובץ רשומות מערכת של Windows</comment>
+ <comment xml:lang="gl">Extracto do rexistro de Windows</comment>
+ <comment xml:lang="ga">sliocht as Clárlann Windows</comment>
+ <comment xml:lang="fur">estrat dal regjistri di Windows</comment>
+ <comment xml:lang="fr">extrait de registre Windows</comment>
+ <comment xml:lang="fo">Windows Registry úrdráttur</comment>
+ <comment xml:lang="fi">Windows-rekisteritietue</comment>
+ <comment xml:lang="eu">Windows-eko erregistro erauzlea</comment>
+ <comment xml:lang="es">extracto del registro de Windows</comment>
+ <comment xml:lang="en_GB">Windows Registry extract</comment>
+ <comment xml:lang="el">Αποσυμπίεση Windows Registry</comment>
+ <comment xml:lang="de">Windows-Registry-Auszug</comment>
+ <comment xml:lang="da">Windows registreringsdatabase-udtrækning</comment>
+ <comment xml:lang="cs">výtah registru Windows</comment>
+ <comment xml:lang="ca">extracte de Windows Registry</comment>
+ <comment xml:lang="bg">Извадка от регистъра на Windows</comment>
+ <comment xml:lang="be@latin">Element rehistru Windows</comment>
+ <comment xml:lang="be">элемент рэгістру Windows</comment>
+ <comment xml:lang="ar">استخراج مسجل ويندوز</comment>
+ <comment xml:lang="af">Windows-registerlêeruittreksel</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="REGEDIT" type="string" offset="0"/>
- <match value="Windows Registry Editor Version 5.00" type="string" offset="0"/>
- <match value="\xff\xfeW\x00i\x00n\x00d\x00o\x00w\x00s\x00 \x00R\x00e\x00g\x00i\x00s\x00t\x00r\x00y\x00 \x00E\x00d\x00i\x00t\x00o\x00r\x00" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="REGEDIT" offset="0"/>
+ <match type="string" value="Windows Registry Editor Version 5.00" offset="0"/>
+ <match type="string" value="\xff\xfeW\x00i\x00n\x00d\x00o\x00w\x00s\x00 \x00R\x00e\x00g\x00i\x00s\x00t\x00r\x00y\x00 \x00E\x00d\x00i\x00t\x00o\x00r\x00" offset="0"/>
</magic>
<glob pattern="*.reg"/>
</mime-type>
<mime-type type="text/x-mof">
- <comment>Managed Object Format</comment>
- <comment xml:lang="ar">صيغة كائن مدار</comment>
- <comment xml:lang="be@latin">Farmat Managed Object</comment>
- <comment xml:lang="bg">Управлявани обекти — MOF</comment>
- <comment xml:lang="ca">format d'objecte gestionat</comment>
- <comment xml:lang="cs">Managed Object Format</comment>
- <comment xml:lang="da">Håndteret objektformat</comment>
- <comment xml:lang="de">Managed Object Format</comment>
- <comment xml:lang="el">Μορφή διαχειριζόμενου αντικειμένου</comment>
- <comment xml:lang="en_GB">Managed Object Format</comment>
- <comment xml:lang="es">formato de objeto gestionado</comment>
- <comment xml:lang="eu">Kudeatutako objektu formatua</comment>
- <comment xml:lang="fi">Managed Object Format</comment>
- <comment xml:lang="fr">format Managed Object</comment>
- <comment xml:lang="ga">formáid réada bainistithe</comment>
- <comment xml:lang="gl">formato de obxecto xestionado</comment>
- <comment xml:lang="he">תבנית פריט מנוהל</comment>
- <comment xml:lang="hr">Managed Object Format</comment>
- <comment xml:lang="hu">Felügyelt objektum (MO) formátum</comment>
- <comment xml:lang="ia">File in formato Managed Object</comment>
- <comment xml:lang="id">Managed Object Format</comment>
- <comment xml:lang="it">Managed Object Format</comment>
- <comment xml:lang="ja">管理オブジェクトフォーマット</comment>
- <comment xml:lang="kk">Басқарылатын объект пішімі</comment>
- <comment xml:lang="ko">관리되는 객체 형식</comment>
- <comment xml:lang="lt">Sutvarkytų objektų formatas</comment>
- <comment xml:lang="lv">Pārvaldītu objektu formāts</comment>
- <comment xml:lang="nb">Managed Object Format</comment>
- <comment xml:lang="nl">Managed Object Format</comment>
- <comment xml:lang="nn">Managed Object Format</comment>
- <comment xml:lang="oc">format Managed Object</comment>
- <comment xml:lang="pl">Plik Managed Object Format</comment>
- <comment xml:lang="pt">formato Managed Object</comment>
- <comment xml:lang="pt_BR">Formato de objeto gerenciado</comment>
- <comment xml:lang="ro">Managed Object Format</comment>
- <comment xml:lang="ru">Формат управляемого объекта</comment>
- <comment xml:lang="sk">Formát Managed Object</comment>
- <comment xml:lang="sl">Datoteka Managed Object</comment>
- <comment xml:lang="sq">Managed Object Format</comment>
- <comment xml:lang="sr">запис управљаног објекта</comment>
- <comment xml:lang="sv">Managed Object Format</comment>
- <comment xml:lang="tr">Yönetilen Nesne Biçimi</comment>
- <comment xml:lang="uk">формат керування об’єктами</comment>
- <comment xml:lang="vi">Định dạng Đối tượng đã Quản lý</comment>
- <comment xml:lang="zh_CN">托管对象格式</comment>
- <comment xml:lang="zh_TW">Managed Object Format</comment>
+ <comment>MOF file</comment>
+ <comment xml:lang="zh_TW">MOF 檔</comment>
+ <comment xml:lang="zh_CN">MOF 文件</comment>
+ <comment xml:lang="uk">файл MOF</comment>
+ <comment xml:lang="tr">MOF dosyası</comment>
+ <comment xml:lang="sv">MOF-fil</comment>
+ <comment xml:lang="sq">kartelë MOF</comment>
+ <comment xml:lang="sl">Datoteka MOF</comment>
+ <comment xml:lang="si">MOF ගොනුව</comment>
+ <comment xml:lang="sk">Súbor MOF</comment>
+ <comment xml:lang="ru">Файл MOF</comment>
+ <comment xml:lang="pt_BR">Arquivo MOF</comment>
+ <comment xml:lang="pl">Plik MOF</comment>
+ <comment xml:lang="oc">fichièr MOF</comment>
+ <comment xml:lang="nl">MOF-bestand</comment>
+ <comment xml:lang="ko">MOF 파일</comment>
+ <comment xml:lang="kk">MOF файлы</comment>
+ <comment xml:lang="ja">MOF ファイル</comment>
+ <comment xml:lang="it">File MOF</comment>
+ <comment xml:lang="is">MOF-skrá</comment>
+ <comment xml:lang="id">Berkas MOF</comment>
+ <comment xml:lang="hu">MOF fájl</comment>
+ <comment xml:lang="hr">MOF datoteka</comment>
+ <comment xml:lang="he">קובץ MOF</comment>
+ <comment xml:lang="gl">Ficheiro MOF</comment>
+ <comment xml:lang="fr">fichier MOF</comment>
+ <comment xml:lang="fi">MOF-tiedosto</comment>
+ <comment xml:lang="eu">MOF fitxategia</comment>
+ <comment xml:lang="es">archivo MOF</comment>
+ <comment xml:lang="en_GB">MOF file</comment>
+ <comment xml:lang="de">MOF-Datei</comment>
+ <comment xml:lang="da">MOF-fil</comment>
+ <comment xml:lang="ca">fitxer MOF</comment>
+ <comment xml:lang="bg">Модел — MOF</comment>
+ <comment xml:lang="be">файл MOF</comment>
+ <comment xml:lang="ar">ملف MOF</comment>
+ <acronym>MOF</acronym>
+ <expanded-acronym>Windows Managed Object File</expanded-acronym>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.mof"/>
</mime-type>
<mime-type type="text/x-mup">
- <comment>Mup publication</comment>
- <comment xml:lang="ar">منشور Mup</comment>
- <comment xml:lang="be@latin">Publikacyja Mup</comment>
- <comment xml:lang="bg">Издание — Mup</comment>
- <comment xml:lang="ca">publicació Mup</comment>
- <comment xml:lang="cs">publikace Mup</comment>
- <comment xml:lang="da">Mupudgivelse</comment>
- <comment xml:lang="de">Mup-Veröffentlichung</comment>
- <comment xml:lang="el">Δημοσίευση Mup</comment>
- <comment xml:lang="en_GB">Mup publication</comment>
- <comment xml:lang="es">publicación Mup</comment>
- <comment xml:lang="eu">Mup publikazioa</comment>
- <comment xml:lang="fi">Mup-julkaisu</comment>
- <comment xml:lang="fo">Mup útgáva</comment>
- <comment xml:lang="fr">publication Mup</comment>
- <comment xml:lang="ga">foilseachán Mup</comment>
- <comment xml:lang="gl">publicación Mup</comment>
- <comment xml:lang="he">פרסום של Mup</comment>
- <comment xml:lang="hr">Mup publikacija</comment>
- <comment xml:lang="hu">Mup publikáció</comment>
- <comment xml:lang="ia">Publication Mup</comment>
- <comment xml:lang="id">Publikasi Mup</comment>
- <comment xml:lang="it">Pubblicazione Mup</comment>
- <comment xml:lang="ja">Mup 出版ファイル</comment>
- <comment xml:lang="kk">Mup жариялымы</comment>
- <comment xml:lang="ko">Mup 출판물</comment>
- <comment xml:lang="lt">Mup leidinys</comment>
- <comment xml:lang="lv">Mup publikācija</comment>
- <comment xml:lang="nb">Mup publikasjon</comment>
- <comment xml:lang="nl">Mup-publicatie</comment>
- <comment xml:lang="nn">Mup-publikasjon</comment>
- <comment xml:lang="oc">publication Mup</comment>
- <comment xml:lang="pl">Publikacja Mup</comment>
- <comment xml:lang="pt">publicação Mup</comment>
- <comment xml:lang="pt_BR">Publicação do Mup</comment>
- <comment xml:lang="ro">Publicație Mup</comment>
- <comment xml:lang="ru">Публикация Mup</comment>
- <comment xml:lang="sk">Publikácie Mup</comment>
- <comment xml:lang="sl">Datoteka objave Mup</comment>
- <comment xml:lang="sq">Publikim Mup</comment>
- <comment xml:lang="sr">Муп објава</comment>
- <comment xml:lang="sv">Mup-publicering</comment>
- <comment xml:lang="tr">Mup uygulaması</comment>
- <comment xml:lang="uk">публікація Mup</comment>
- <comment xml:lang="vi">Bản xuất Mup</comment>
- <comment xml:lang="zh_CN">Mup 应用程序</comment>
- <comment xml:lang="zh_TW">Mup 出版品</comment>
+ <comment>Mup musical composition document</comment>
+ <comment xml:lang="zh_TW">Mup 音樂組合文件</comment>
+ <comment xml:lang="zh_CN">Mup 乐曲文档</comment>
+ <comment xml:lang="uk">документ музичного запису твору Mup</comment>
+ <comment xml:lang="tr">Mup musical composition belgesi</comment>
+ <comment xml:lang="sv">Mup musikkompositionsdokument</comment>
+ <comment xml:lang="sq">dokument kompozimi muzikor Mup</comment>
+ <comment xml:lang="si">Mup සංගීත සංයුතිය ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument hudobnej kompozície Mup</comment>
+ <comment xml:lang="ru">Документ Mup musical composition</comment>
+ <comment xml:lang="pt_BR">Documento de composição musical Mup</comment>
+ <comment xml:lang="pl">Dokument kompozycji muzycznej Mup</comment>
+ <comment xml:lang="nl">Mup-muzikaal-compositie­document</comment>
+ <comment xml:lang="ko">mup 작곡 문서</comment>
+ <comment xml:lang="kk">Mup музыкалық композиция құжаты</comment>
+ <comment xml:lang="ja">Mup 作曲ドキュメント</comment>
+ <comment xml:lang="it">Documento composizione musicale Mup</comment>
+ <comment xml:lang="is">MUP-nótnaskjal</comment>
+ <comment xml:lang="id">Dokumen komposisi musik Mup</comment>
+ <comment xml:lang="hu">Mup zenei kompozíciós dokumentum</comment>
+ <comment xml:lang="hr">Mup dokument glazbene kompozicije</comment>
+ <comment xml:lang="he">מסמך קומפוזיציה מוזיקלית מסוג Mup</comment>
+ <comment xml:lang="gl">Documento de composición musical MUP</comment>
+ <comment xml:lang="fr">document de composition musicale Mup</comment>
+ <comment xml:lang="fi">Mup-sävellysdokumentti</comment>
+ <comment xml:lang="eu">Mup konposizio musikal dokumentua</comment>
+ <comment xml:lang="es">documento de composición musical de Mup</comment>
+ <comment xml:lang="en_GB">Mup musical composition document</comment>
+ <comment xml:lang="de">Mup-Musikkompositions-Dokument</comment>
+ <comment xml:lang="da">Mup-musiksamling-dokument</comment>
+ <comment xml:lang="ca">document de composició musical Mup</comment>
+ <comment xml:lang="bg">Музикална композиция — Mup</comment>
+ <comment xml:lang="be">дакумент музычнай кампазіцыі Mup</comment>
+ <comment xml:lang="ar">وثيقة تأليف موسيقي Mup </comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="//!Mup" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="//!Mup" offset="0"/>
</magic>
<glob pattern="*.mup"/>
<glob pattern="*.not"/>
</mime-type>
<mime-type type="text/x-objcsrc">
<comment>Objective-C source code</comment>
- <comment xml:lang="ar">شفرة مصدر الهدف-C </comment>
- <comment xml:lang="be@latin">Kryničny kod Objective-C</comment>
- <comment xml:lang="bg">Изходен код — Objective C</comment>
- <comment xml:lang="ca">codi font en Objective-C</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Objective-C</comment>
- <comment xml:lang="da">Objektiv C-kildekode</comment>
- <comment xml:lang="de">Objective-C-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Objective-C</comment>
- <comment xml:lang="en_GB">Objective-C source code</comment>
- <comment xml:lang="eo">fontkodo en Objective-C</comment>
- <comment xml:lang="es">código fuente en Objective-C</comment>
- <comment xml:lang="eu">Objective-C iturburu-kodea</comment>
- <comment xml:lang="fi">Objective-C-lähdekoodi</comment>
- <comment xml:lang="fo">Objective-C keldukota</comment>
- <comment xml:lang="fr">code source Objective-C</comment>
- <comment xml:lang="ga">cód foinseach Objective-C</comment>
- <comment xml:lang="gl">código fonte de Objective-C</comment>
- <comment xml:lang="he">קוד מקור של Objective-C</comment>
- <comment xml:lang="hr">Objective-C izvorni kôd</comment>
- <comment xml:lang="hu">Objective-C forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Objective-C</comment>
- <comment xml:lang="id">Kode sumber Objective-C</comment>
- <comment xml:lang="it">Codice sorgente Objective-C</comment>
- <comment xml:lang="ja">Objective-C ソースコード</comment>
- <comment xml:lang="ka">Objective-C-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Objective-C бастапқы коды</comment>
- <comment xml:lang="ko">Objective-C 소스 코드</comment>
- <comment xml:lang="lt">Objective-C pradinis kodas</comment>
- <comment xml:lang="lv">Objective-C pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Objective-C</comment>
- <comment xml:lang="nb">Objective-C-kildekode</comment>
- <comment xml:lang="nl">Objective-C-broncode</comment>
- <comment xml:lang="nn">Objective-C-kjeldekode</comment>
- <comment xml:lang="oc">còde font Objective-C</comment>
- <comment xml:lang="pl">Kod źródłowy Objective-C</comment>
- <comment xml:lang="pt">código origem Objective-C</comment>
- <comment xml:lang="pt_BR">Código-fonte Objective-C</comment>
- <comment xml:lang="ro">Cod sursă Objective-C</comment>
- <comment xml:lang="ru">Исходный код Objective-C</comment>
- <comment xml:lang="sk">Zdrojový kód Objective-C</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Objective-C</comment>
- <comment xml:lang="sq">Kod burues C objekt</comment>
- <comment xml:lang="sr">Објектни-Ц изворни ко̂д</comment>
- <comment xml:lang="sv">Objective-C-källkod</comment>
- <comment xml:lang="tr">Objective-C kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Objective-C</comment>
- <comment xml:lang="vi">Mã nguồn Objective-C</comment>
- <comment xml:lang="zh_CN">Objective-C 源代码</comment>
<comment xml:lang="zh_TW">Objective-C 源碼</comment>
+ <comment xml:lang="zh_CN">Objective-C 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Objective-C</comment>
+ <comment xml:lang="uk">початковий код мовою Objective-C</comment>
+ <comment xml:lang="tr">Objective-C kaynak kodu</comment>
+ <comment xml:lang="sv">Objective-C-källkod</comment>
+ <comment xml:lang="sr">Објектни-Ц изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Objective-C</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Objective-C</comment>
+ <comment xml:lang="si">Objective-C මූලාශ්‍ර කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Objective-C</comment>
+ <comment xml:lang="ru">Исходный код Objective-C</comment>
+ <comment xml:lang="ro">Cod sursă Objective-C</comment>
+ <comment xml:lang="pt_BR">Código-fonte Objective-C</comment>
+ <comment xml:lang="pt">código origem Objective-C</comment>
+ <comment xml:lang="pl">Kod źródłowy Objective-C</comment>
+ <comment xml:lang="oc">còde font Objective-C</comment>
+ <comment xml:lang="nn">Objective-C-kjeldekode</comment>
+ <comment xml:lang="nl">Objective-C-broncode</comment>
+ <comment xml:lang="nb">Objective-C-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Objective-C</comment>
+ <comment xml:lang="lv">Objective-C pirmkods</comment>
+ <comment xml:lang="lt">Objective-C pradinis kodas</comment>
+ <comment xml:lang="ko">Objective-C 소스 코드</comment>
+ <comment xml:lang="kk">Objective-C бастапқы коды</comment>
+ <comment xml:lang="ka">Objective-C-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Objective-C ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Objective-C</comment>
+ <comment xml:lang="is">Objective-C frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Objective-C</comment>
+ <comment xml:lang="ia">Codice-fonte Objective-C</comment>
+ <comment xml:lang="hu">Objective-C forráskód</comment>
+ <comment xml:lang="hr">Objective-C izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Objective-C</comment>
+ <comment xml:lang="gl">código fonte de Objective-C</comment>
+ <comment xml:lang="ga">cód foinseach Objective-C</comment>
+ <comment xml:lang="fur">codiç sorzint Objective-C</comment>
+ <comment xml:lang="fr">code source Objective-C</comment>
+ <comment xml:lang="fo">Objective-C keldukota</comment>
+ <comment xml:lang="fi">Objective-C-lähdekoodi</comment>
+ <comment xml:lang="eu">Objective-C iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Objective-C</comment>
+ <comment xml:lang="eo">fontkodo en Objective-C</comment>
+ <comment xml:lang="en_GB">Objective-C source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Objective-C</comment>
+ <comment xml:lang="de">Objective-C-Quelltext</comment>
+ <comment xml:lang="da">Objektiv C-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Objective-C</comment>
+ <comment xml:lang="ca">codi font en Objective-C</comment>
+ <comment xml:lang="bg">Изходен код — Objective C</comment>
+ <comment xml:lang="be@latin">Kryničny kod Objective-C</comment>
+ <comment xml:lang="be">зыходны код Objective-C</comment>
+ <comment xml:lang="ar">شفرة مصدر Objective-C</comment>
+ <comment xml:lang="af">Objective-C-bronkode</comment>
<sub-class-of type="text/x-csrc"/>
<magic priority="30">
- <match value="#import" type="string" offset="0"/>
+ <match type="string" value="#import" offset="0"/>
</magic>
<glob pattern="*.m"/>
</mime-type>
+ <mime-type type="text/x-objc++src">
+ <comment>Objective-C++ source code</comment>
+ <comment xml:lang="zh_TW">Objective-C++ 原始碼</comment>
+ <comment xml:lang="zh_CN">Objective-C++ 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Objective-C++</comment>
+ <comment xml:lang="tr">Objective-C++ kaynak kodu</comment>
+ <comment xml:lang="sv">Objective-C++-källkod</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Objective-C++</comment>
+ <comment xml:lang="si">අරමුණ-C++ මූල කේතය</comment>
+ <comment xml:lang="ru">Исходный код Objective-C++</comment>
+ <comment xml:lang="pt_BR">Código-fonte Objective-C++</comment>
+ <comment xml:lang="pl">Kod źródłowy Objective-C++</comment>
+ <comment xml:lang="nl">Objective-C++-broncode</comment>
+ <comment xml:lang="ko">Objective-C++ 소스 코드</comment>
+ <comment xml:lang="kk">Objective-C++ бастапқы коды</comment>
+ <comment xml:lang="ja">Objective-C++ ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Objective-C++</comment>
+ <comment xml:lang="hr">Objective-C++ izvorni kôd</comment>
+ <comment xml:lang="gl">Código fonte de Objective-C++</comment>
+ <comment xml:lang="fi">Objective-C++ lähdekoodi</comment>
+ <comment xml:lang="eu">Objective-C++ iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Objective-C++</comment>
+ <comment xml:lang="en_GB">Objective-C++ source code</comment>
+ <comment xml:lang="de">Objective-C++-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Objective-C++</comment>
+ <comment xml:lang="ar">شفرة مصدر Objective-سي++</comment>
+ <sub-class-of type="text/x-c++src"/>
+ <sub-class-of type="text/x-objcsrc"/>
+ <glob pattern="*.mm"/>
+ </mime-type>
<mime-type type="text/x-ocaml">
<comment>OCaml source code</comment>
- <comment xml:lang="ar">شفرة مصدر OCaml</comment>
- <comment xml:lang="be@latin">Kryničny kod OCaml</comment>
- <comment xml:lang="bg">Изходен код — OCaml</comment>
- <comment xml:lang="ca">codi font en OCaml</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce OCaml</comment>
- <comment xml:lang="da">OCaml-kildekode</comment>
- <comment xml:lang="de">OCaml-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας OCaml</comment>
- <comment xml:lang="en_GB">OCaml source code</comment>
- <comment xml:lang="eo">OCaml-fontkodo</comment>
- <comment xml:lang="es">código fuente en OCaml</comment>
- <comment xml:lang="eu">OCaml iturburu-kodea</comment>
- <comment xml:lang="fi">OCaml-lähdekoodi</comment>
- <comment xml:lang="fo">OCaml keldukota</comment>
- <comment xml:lang="fr">code source OCaml</comment>
- <comment xml:lang="ga">cód foinseach OCaml</comment>
- <comment xml:lang="gl">código fonte de OCaml</comment>
- <comment xml:lang="he">קוד מקור של OCaml</comment>
- <comment xml:lang="hr">OCaml izvorni kôd</comment>
- <comment xml:lang="hu">OCaml forráskód</comment>
- <comment xml:lang="ia">Codice-fonte OCaml</comment>
- <comment xml:lang="id">Kode sumber OCaml</comment>
- <comment xml:lang="it">Codice sorgente OCaml</comment>
- <comment xml:lang="ja">OCaml ソースコード</comment>
- <comment xml:lang="kk">OCaml бастапқы коды</comment>
- <comment xml:lang="ko">OCaml 소스 코드</comment>
- <comment xml:lang="lt">OCaml pradinis kodas</comment>
- <comment xml:lang="lv">OCaml pirmkods</comment>
- <comment xml:lang="nb">OCaml-kildekode</comment>
- <comment xml:lang="nl">OCaml-broncode</comment>
- <comment xml:lang="nn">OCaml-kjeldekode</comment>
- <comment xml:lang="oc">còde font OCaml</comment>
- <comment xml:lang="pl">Kod źródłowy OCaml</comment>
- <comment xml:lang="pt">código origem OCaml</comment>
- <comment xml:lang="pt_BR">Código-fonte OCaml</comment>
- <comment xml:lang="ro">Cod sursă OCaml</comment>
- <comment xml:lang="ru">Исходный код OCaml</comment>
- <comment xml:lang="sk">Zdrojový kód OCaml</comment>
- <comment xml:lang="sl">Datoteka izvorne kode OCaml</comment>
- <comment xml:lang="sq">Kod burues OCaml</comment>
- <comment xml:lang="sr">Окемл изворни ко̂д</comment>
- <comment xml:lang="sv">OCaml-källkod</comment>
- <comment xml:lang="tr">OCaml kaynak kodu</comment>
- <comment xml:lang="uk">первинний код мовою OCaml</comment>
- <comment xml:lang="vi">Mã nguồn OCaml</comment>
- <comment xml:lang="zh_CN">OCaml 源代码</comment>
<comment xml:lang="zh_TW">OCaml 源碼</comment>
+ <comment xml:lang="zh_CN">OCaml 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn OCaml</comment>
+ <comment xml:lang="uk">початковий код мовою OCaml</comment>
+ <comment xml:lang="tr">OCaml kaynak kodu</comment>
+ <comment xml:lang="sv">OCaml-källkod</comment>
+ <comment xml:lang="sr">Окемл изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim OCaml</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode OCaml</comment>
+ <comment xml:lang="si">OCaml මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód OCaml</comment>
+ <comment xml:lang="ru">Исходный код OCaml</comment>
+ <comment xml:lang="ro">Cod sursă OCaml</comment>
+ <comment xml:lang="pt_BR">Código-fonte OCaml</comment>
+ <comment xml:lang="pt">código origem OCaml</comment>
+ <comment xml:lang="pl">Kod źródłowy OCaml</comment>
+ <comment xml:lang="oc">còde font OCaml</comment>
+ <comment xml:lang="nn">OCaml-kjeldekode</comment>
+ <comment xml:lang="nl">OCaml-broncode</comment>
+ <comment xml:lang="nb">OCaml-kildekode</comment>
+ <comment xml:lang="lv">OCaml pirmkods</comment>
+ <comment xml:lang="lt">OCaml pradinis kodas</comment>
+ <comment xml:lang="ko">OCaml 소스 코드</comment>
+ <comment xml:lang="kk">OCaml бастапқы коды</comment>
+ <comment xml:lang="ja">OCaml ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente OCaml</comment>
+ <comment xml:lang="is">OCaml frumkóði</comment>
+ <comment xml:lang="id">Kode sumber OCaml</comment>
+ <comment xml:lang="ia">Codice-fonte OCaml</comment>
+ <comment xml:lang="hu">OCaml forráskód</comment>
+ <comment xml:lang="hr">OCaml izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של OCaml</comment>
+ <comment xml:lang="gl">código fonte de OCaml</comment>
+ <comment xml:lang="ga">cód foinseach OCaml</comment>
+ <comment xml:lang="fur">codiç sorzint OCaml</comment>
+ <comment xml:lang="fr">code source OCaml</comment>
+ <comment xml:lang="fo">OCaml keldukota</comment>
+ <comment xml:lang="fi">OCaml-lähdekoodi</comment>
+ <comment xml:lang="eu">OCaml iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en OCaml</comment>
+ <comment xml:lang="eo">OCaml-fontkodo</comment>
+ <comment xml:lang="en_GB">OCaml source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας OCaml</comment>
+ <comment xml:lang="de">OCaml-Quelltext</comment>
+ <comment xml:lang="da">OCaml-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce OCaml</comment>
+ <comment xml:lang="ca">codi font en OCaml</comment>
+ <comment xml:lang="bg">Изходен код — OCaml</comment>
+ <comment xml:lang="be@latin">Kryničny kod OCaml</comment>
+ <comment xml:lang="be">зыходны код OCaml</comment>
+ <comment xml:lang="ar">شفرة مصدر OCaml</comment>
+ <comment xml:lang="af">OCaml-bronkode</comment>
+ <sub-class-of type="text/plain"/>
<glob pattern="*.ml"/>
<glob pattern="*.mli"/>
</mime-type>
<mime-type type="text/x-opencl-src">
<comment>OpenCL source code</comment>
- <comment xml:lang="ca">codi font en OpenCL</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce OpenCL</comment>
- <comment xml:lang="de">OpenCL-Quelltext</comment>
- <comment xml:lang="en_GB">OpenCL source code</comment>
- <comment xml:lang="es">código fuente en OpenCL</comment>
- <comment xml:lang="fi">OpenCL-lähdekoodi</comment>
- <comment xml:lang="hr">OpenCL izvorni kôd</comment>
- <comment xml:lang="hu">OpenCL forráskód</comment>
- <comment xml:lang="id">Kode sumber OpenCL</comment>
- <comment xml:lang="it">Codice sorgente OpenCL</comment>
- <comment xml:lang="kk">OpenCL бастапқы коды</comment>
- <comment xml:lang="ko">OpenCL 소스 코드</comment>
- <comment xml:lang="pl">Kod źródłowy OpenCL</comment>
- <comment xml:lang="pt_BR">Código-fonte do OpenCL</comment>
- <comment xml:lang="ru">Исходный код OpenGL</comment>
- <comment xml:lang="sk">Zdrojový kód OpenCL</comment>
- <comment xml:lang="sv">OpenCL-källkod</comment>
- <comment xml:lang="uk">вихідний код мовою OpenCL</comment>
+ <comment xml:lang="zh_TW">OpenCL 原始碼</comment>
<comment xml:lang="zh_CN">OpenCL 源代码</comment>
- <comment xml:lang="zh_TW">OpenCL 源碼</comment>
+ <comment xml:lang="uk">початковий код мовою OpenCL</comment>
+ <comment xml:lang="tr">OpenCL kaynak kodu</comment>
+ <comment xml:lang="sv">OpenCL-källkod</comment>
+ <comment xml:lang="sq">kod burim OpenCL</comment>
+ <comment xml:lang="sl">Izvorna koda OpenCL</comment>
+ <comment xml:lang="si">OpenCL මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód OpenCL</comment>
+ <comment xml:lang="ru">Исходный код OpenGL</comment>
+ <comment xml:lang="pt_BR">Código-fonte OpenCL</comment>
+ <comment xml:lang="pl">Kod źródłowy OpenCL</comment>
+ <comment xml:lang="oc">còdi font OpenCL</comment>
+ <comment xml:lang="nl">OpenCL-broncode</comment>
+ <comment xml:lang="ko">OpenCL 소스 코드</comment>
+ <comment xml:lang="kk">OpenCL бастапқы коды</comment>
+ <comment xml:lang="ja">OpenCL ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente OpenCL</comment>
+ <comment xml:lang="is">OpenCL frumkóði</comment>
+ <comment xml:lang="id">Kode sumber OpenCL</comment>
+ <comment xml:lang="hu">OpenCL forráskód</comment>
+ <comment xml:lang="hr">OpenCL izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור OpenCL</comment>
+ <comment xml:lang="gl">Código fonte en OpenCL</comment>
+ <comment xml:lang="ga">cód foinseach OpenCL</comment>
+ <comment xml:lang="fur">codiç sorzint OpenCL</comment>
+ <comment xml:lang="fr">code source OpenCL</comment>
+ <comment xml:lang="fi">OpenCL-lähdekoodi</comment>
+ <comment xml:lang="eu">OpenCL iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en OpenCL</comment>
+ <comment xml:lang="en_GB">OpenCL source code</comment>
+ <comment xml:lang="de">OpenCL-Quelltext</comment>
+ <comment xml:lang="da">OpenCL-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce OpenCL</comment>
+ <comment xml:lang="ca">codi font en OpenCL</comment>
+ <comment xml:lang="bg">Изходен код — OpenCL</comment>
+ <comment xml:lang="be">зыходны код OpenCL</comment>
+ <comment xml:lang="ar">شفرة مصدر OpenCL</comment>
+ <comment xml:lang="af">OpenCL-bronkode</comment>
<acronym>OpenCL</acronym>
<expanded-acronym>Open Computing Language</expanded-acronym>
<sub-class-of type="text/x-csrc"/>
<glob pattern="*.cl"/>
</mime-type>
<mime-type type="text/x-matlab">
- <comment>MATLAB script/function</comment>
- <comment xml:lang="ar">سكربت/وظيفة MATLAB</comment>
- <comment xml:lang="be@latin">Skrypt/funkcyja MATLAB</comment>
- <comment xml:lang="bg">Скрипт/функция — MATLAB</comment>
- <comment xml:lang="ca">script/funció MATLAB</comment>
- <comment xml:lang="cs">skript/funkce MATLAB</comment>
- <comment xml:lang="da">MATLAB-program/-funktion</comment>
- <comment xml:lang="de">MATLAB-Skript/-Funktion</comment>
- <comment xml:lang="el">Δέσμη ενεργειών/συνάρτηση MATLAB</comment>
- <comment xml:lang="en_GB">MATLAB script/function</comment>
- <comment xml:lang="es">secuencia de órdenes/función de MATLAB</comment>
- <comment xml:lang="eu">MATLAB script/funtzioa</comment>
- <comment xml:lang="fi">MATLAB-komentotiedosto/funktio</comment>
- <comment xml:lang="fo">MATLAB boðrøð/funka</comment>
- <comment xml:lang="fr">script/fonction MATLAB</comment>
- <comment xml:lang="ga">script/feidhm MATLAB</comment>
- <comment xml:lang="gl">función/script de MATLAB</comment>
- <comment xml:lang="he">תסריט/פונקציית MATLAB</comment>
- <comment xml:lang="hr">MATLAB skripta/funkcija</comment>
- <comment xml:lang="hu">MATLAB parancsfájl/funkció</comment>
- <comment xml:lang="ia">Script/function MATLAB</comment>
- <comment xml:lang="id">Skrip/fungsi MATLAB</comment>
- <comment xml:lang="it">Script/Funzione MATLAB</comment>
- <comment xml:lang="ja">MATLAB スクリプト/関数</comment>
- <comment xml:lang="kk">MATLAB сценарий/функциясы</comment>
- <comment xml:lang="ko">MATLAB 스크립트/함수</comment>
- <comment xml:lang="lt">MATLAB scenarijus / funkcija</comment>
- <comment xml:lang="lv">MATLAB skripts/funkcija</comment>
- <comment xml:lang="nb">Skript/funksjon for MATLAB</comment>
- <comment xml:lang="nl">MATLAB-script/functie</comment>
- <comment xml:lang="nn">MATLAB-skript/funksjon</comment>
- <comment xml:lang="oc">escript/fonction MATLAB</comment>
- <comment xml:lang="pl">Skrypt/funkcja MATLAB</comment>
- <comment xml:lang="pt">script/função MATLAB</comment>
- <comment xml:lang="pt_BR">Script/função do MATLAB</comment>
- <comment xml:lang="ro">Funcție/script MATLAB</comment>
- <comment xml:lang="ru">Сценарий/функция MATLAB</comment>
- <comment xml:lang="sk">Skript/funkcia MATLAB</comment>
- <comment xml:lang="sl">Skriptna datoteka MATLAB</comment>
- <comment xml:lang="sq">Script/Funksion MATLAB</comment>
- <comment xml:lang="sr">скрипта/функција МАТЛАБ-а</comment>
- <comment xml:lang="sv">MATLAB-skript/funktion</comment>
- <comment xml:lang="tr">MATLAB betiği/fonksiyonu</comment>
- <comment xml:lang="uk">скрипт/функція MATLAB</comment>
- <comment xml:lang="vi">Văn lệnh/chức năng MATLAB</comment>
- <comment xml:lang="zh_CN">MATLAB 脚本/函数</comment>
- <comment xml:lang="zh_TW">MATLAB 指令稿/函式</comment>
+ <comment>MATLAB file</comment>
+ <comment xml:lang="zh_TW">MATLAB 檔</comment>
+ <comment xml:lang="zh_CN">MATLAB 文件</comment>
+ <comment xml:lang="uk">файл MATLAB</comment>
+ <comment xml:lang="tr">MATLAB dosyası</comment>
+ <comment xml:lang="sv">MATLAB-fil</comment>
+ <comment xml:lang="sq">kartelë MATLAB</comment>
+ <comment xml:lang="sl">Datoteka MATLAB</comment>
+ <comment xml:lang="si">MATLAB ගොනුව</comment>
+ <comment xml:lang="sk">Súbor MATLAB</comment>
+ <comment xml:lang="ru">Файл MATLAB</comment>
+ <comment xml:lang="pt_BR">Arquivo do MATLAB</comment>
+ <comment xml:lang="pl">Plik MATLAB</comment>
+ <comment xml:lang="nl">MATLAB-bestand</comment>
+ <comment xml:lang="ko">MATLAB 파일</comment>
+ <comment xml:lang="kk">MATLAB файлы</comment>
+ <comment xml:lang="ja">MATLAB ファイル</comment>
+ <comment xml:lang="it">File MATLAB</comment>
+ <comment xml:lang="is">MATLAB-skrá</comment>
+ <comment xml:lang="id">Berkas MATLAB</comment>
+ <comment xml:lang="hu">MATLAB fájl</comment>
+ <comment xml:lang="hr">MATLAB datoteka</comment>
+ <comment xml:lang="he">קובץ MATLAB</comment>
+ <comment xml:lang="gl">Ficheiro de MATLAB</comment>
+ <comment xml:lang="fr">fichier MATLAB</comment>
+ <comment xml:lang="fi">MATLAB-tiedosto</comment>
+ <comment xml:lang="eu">MATLAB fitxategia</comment>
+ <comment xml:lang="es">archivo de MATLAB</comment>
+ <comment xml:lang="en_GB">MATLAB file</comment>
+ <comment xml:lang="de">MATLAB-Datei</comment>
+ <comment xml:lang="da">MATLAB-fil</comment>
+ <comment xml:lang="ca">fitxer MATLAB</comment>
+ <comment xml:lang="bg">Файл — MATLAB</comment>
+ <comment xml:lang="be">файл MATLAB</comment>
+ <comment xml:lang="ar">ملف ماتلاب</comment>
<sub-class-of type="text/plain"/>
<magic priority="10">
- <match value="%" type="string" offset="0"/>
- </magic>
- <magic priority="10">
- <match value="##" type="string" offset="0"/>
+ <match type="string" value="%" offset="0"/>
</magic>
- <magic priority="50">
- <match value="function" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="function" offset="0"/>
</magic>
<glob pattern="*.m"/>
<alias type="text/x-octave"/>
</mime-type>
<mime-type type="text/x-meson">
<comment>Meson source code</comment>
- <comment xml:lang="ca">codi font en Meson</comment>
- <comment xml:lang="cs">zdrojový kód Meson</comment>
- <comment xml:lang="da">Meson-kildekode</comment>
- <comment xml:lang="de">Meson-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Meson</comment>
- <comment xml:lang="en_GB">Meson source code</comment>
- <comment xml:lang="es">código fuente en Meson</comment>
- <comment xml:lang="eu">Meson iturburu-kodea</comment>
- <comment xml:lang="fi">Meson-lähdekoodi</comment>
- <comment xml:lang="fr">code source Meson</comment>
- <comment xml:lang="ga">cód foinseach Meson</comment>
- <comment xml:lang="he">קוד מקור Meson</comment>
- <comment xml:lang="hr">Meson izvorni kôd</comment>
- <comment xml:lang="hu">Meson forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Meson</comment>
- <comment xml:lang="id">Kode sumber Meson</comment>
- <comment xml:lang="it">Codice sorgente Meson</comment>
- <comment xml:lang="kk">Meson бастапқы коды</comment>
- <comment xml:lang="ko">Meson 소스 코드</comment>
- <comment xml:lang="oc">còde font Meson</comment>
- <comment xml:lang="pl">Kod źródłowy Meson</comment>
- <comment xml:lang="pt">código origem Meson</comment>
- <comment xml:lang="pt_BR">Código-fonte Meson</comment>
- <comment xml:lang="ru">Исходный код Meson</comment>
- <comment xml:lang="sk">Zdrojový kód Meson</comment>
- <comment xml:lang="sr">Месон изворни ко̂д</comment>
- <comment xml:lang="sv">Meson-källkod</comment>
- <comment xml:lang="tr">Meson kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Meson</comment>
- <comment xml:lang="zh_CN">Meson 源代码</comment>
<comment xml:lang="zh_TW">Meson 源碼</comment>
+ <comment xml:lang="zh_CN">Meson 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Meson</comment>
+ <comment xml:lang="tr">Meson kaynak kodu</comment>
+ <comment xml:lang="sv">Meson-källkod</comment>
+ <comment xml:lang="sr">Месон изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Meson</comment>
+ <comment xml:lang="sl">Izvorna koda Meson</comment>
+ <comment xml:lang="si">Meson මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Meson</comment>
+ <comment xml:lang="ru">Исходный код Meson</comment>
+ <comment xml:lang="pt_BR">Código-fonte Meson</comment>
+ <comment xml:lang="pt">código origem Meson</comment>
+ <comment xml:lang="pl">Kod źródłowy Meson</comment>
+ <comment xml:lang="oc">còde font Meson</comment>
+ <comment xml:lang="nl">Meson-broncode</comment>
+ <comment xml:lang="ko">Meson 소스 코드</comment>
+ <comment xml:lang="kk">Meson бастапқы коды</comment>
+ <comment xml:lang="ja">Meson ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Meson</comment>
+ <comment xml:lang="is">Meson frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Meson</comment>
+ <comment xml:lang="ia">Codice-fonte Meson</comment>
+ <comment xml:lang="hu">Meson forráskód</comment>
+ <comment xml:lang="hr">Meson izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור Meson</comment>
+ <comment xml:lang="gl">Código fonte Meson</comment>
+ <comment xml:lang="ga">cód foinseach Meson</comment>
+ <comment xml:lang="fur">codiç sorzint Meson</comment>
+ <comment xml:lang="fr">code source Meson</comment>
+ <comment xml:lang="fi">Meson-lähdekoodi</comment>
+ <comment xml:lang="eu">Meson iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Meson</comment>
+ <comment xml:lang="en_GB">Meson source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Meson</comment>
+ <comment xml:lang="de">Meson-Quelltext</comment>
+ <comment xml:lang="da">Meson-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód Meson</comment>
+ <comment xml:lang="ca">codi font en Meson</comment>
+ <comment xml:lang="bg">Изходен код — Meson</comment>
+ <comment xml:lang="be">зыходны код Meson</comment>
+ <comment xml:lang="ar">شفرة مصدر Meson</comment>
+ <comment xml:lang="af">Meson-bronkode</comment>
<glob pattern="meson.build"/>
<glob pattern="meson_options.txt"/>
<sub-class-of type="text/plain"/>
</mime-type>
<mime-type type="text/x-modelica">
<comment>Modelica model</comment>
- <comment xml:lang="ca">model de Modelica</comment>
- <comment xml:lang="cs">model Modelica</comment>
- <comment xml:lang="da">Modelica-model</comment>
- <comment xml:lang="de">Modelica-Modell</comment>
- <comment xml:lang="el">Μοντέλο Modelica</comment>
- <comment xml:lang="en_GB">Modelica model</comment>
- <comment xml:lang="es">modelo de Modelica</comment>
- <comment xml:lang="eu">Modelica modeloa</comment>
- <comment xml:lang="fi">Modelica-malli</comment>
- <comment xml:lang="fr">modèle Modelica</comment>
- <comment xml:lang="ga">samhail Modelica</comment>
- <comment xml:lang="gl">Modelo de Modelica</comment>
- <comment xml:lang="he">דגם של Modelica</comment>
- <comment xml:lang="hr">Modelica model</comment>
- <comment xml:lang="hu">Modelica modell</comment>
- <comment xml:lang="ia">Modello Modelica</comment>
- <comment xml:lang="id">Model Modelica</comment>
- <comment xml:lang="it">Modello Modelica</comment>
- <comment xml:lang="ja">Modelica モデル</comment>
- <comment xml:lang="kk">Modelica моделі</comment>
- <comment xml:lang="ko">Modelica 모델</comment>
- <comment xml:lang="lv">Modelica modelis</comment>
- <comment xml:lang="oc">modèl Modelica</comment>
- <comment xml:lang="pl">Model Modelica</comment>
- <comment xml:lang="pt">modelo Modelica</comment>
- <comment xml:lang="pt_BR">Modelo da Modelica</comment>
- <comment xml:lang="ru">Модель Modelica</comment>
- <comment xml:lang="sk">Model Modelica</comment>
- <comment xml:lang="sl">Model Modelica</comment>
- <comment xml:lang="sr">модел Моделике</comment>
- <comment xml:lang="sv">Modelica-modell</comment>
- <comment xml:lang="tr">Modelica modeli</comment>
- <comment xml:lang="uk">модель Modelica</comment>
- <comment xml:lang="zh_CN">Modelica 模型</comment>
<comment xml:lang="zh_TW">Modelica 模型</comment>
+ <comment xml:lang="zh_CN">Modelica 模型</comment>
+ <comment xml:lang="uk">модель Modelica</comment>
+ <comment xml:lang="tr">Modelica modeli</comment>
+ <comment xml:lang="sv">Modelica-modell</comment>
+ <comment xml:lang="sr">модел Моделике</comment>
+ <comment xml:lang="sq">model Modelica</comment>
+ <comment xml:lang="sl">Model Modelica</comment>
+ <comment xml:lang="si">Modelica ආකෘතිය</comment>
+ <comment xml:lang="sk">Model Modelica</comment>
+ <comment xml:lang="ru">Модель Modelica</comment>
+ <comment xml:lang="pt_BR">Modelo da Modelica</comment>
+ <comment xml:lang="pt">modelo Modelica</comment>
+ <comment xml:lang="pl">Model Modelica</comment>
+ <comment xml:lang="oc">modèl Modelica</comment>
+ <comment xml:lang="nl">Modelica-model</comment>
+ <comment xml:lang="lv">Modelica modelis</comment>
+ <comment xml:lang="ko">Modelica 모델</comment>
+ <comment xml:lang="kk">Modelica моделі</comment>
+ <comment xml:lang="ja">Modelica モデル</comment>
+ <comment xml:lang="it">Modello Modelica</comment>
+ <comment xml:lang="is">Modelica líkan</comment>
+ <comment xml:lang="id">Model Modelica</comment>
+ <comment xml:lang="ia">Modello Modelica</comment>
+ <comment xml:lang="hu">Modelica modell</comment>
+ <comment xml:lang="hr">Modelica model</comment>
+ <comment xml:lang="he">דגם של Modelica</comment>
+ <comment xml:lang="gl">Modelo de Modelica</comment>
+ <comment xml:lang="ga">samhail Modelica</comment>
+ <comment xml:lang="fur">model Modelica</comment>
+ <comment xml:lang="fr">modèle Modelica</comment>
+ <comment xml:lang="fi">Modelica-malli</comment>
+ <comment xml:lang="eu">Modelica modeloa</comment>
+ <comment xml:lang="es">modelo de Modelica</comment>
+ <comment xml:lang="en_GB">Modelica model</comment>
+ <comment xml:lang="el">Μοντέλο Modelica</comment>
+ <comment xml:lang="de">Modelica-Modell</comment>
+ <comment xml:lang="da">Modelica-model</comment>
+ <comment xml:lang="cs">model Modelica</comment>
+ <comment xml:lang="ca">model de Modelica</comment>
+ <comment xml:lang="bg">Модел — Modelica</comment>
+ <comment xml:lang="be">мадэль Modelica</comment>
+ <comment xml:lang="ar">نموذج Modelica</comment>
+ <comment xml:lang="af">Modelica-model</comment>
<sub-class-of type="text/plain"/>
<magic priority="10">
- <match value="//" type="string" offset="0"/>
+ <match type="string" value="//" offset="0"/>
</magic>
- <magic priority="50">
- <match value="function" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="function" offset="0"/>
</magic>
- <magic priority="50">
- <match value="class" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="class" offset="0"/>
</magic>
- <magic priority="50">
- <match value="model" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="model" offset="0"/>
</magic>
- <magic priority="50">
- <match value="record" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="record" offset="0"/>
</magic>
<glob pattern="*.mo"/>
</mime-type>
<mime-type type="text/x-pascal">
<comment>Pascal source code</comment>
- <comment xml:lang="ar">شفرة مصدر باسكال</comment>
- <comment xml:lang="be@latin">Kryničny kod Pascal</comment>
- <comment xml:lang="bg">Изходен код — Pascal</comment>
- <comment xml:lang="ca">codi font en Pascal</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Pascal</comment>
- <comment xml:lang="da">Pascalkildekode</comment>
- <comment xml:lang="de">Pascal-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Pascal</comment>
- <comment xml:lang="en_GB">Pascal source code</comment>
- <comment xml:lang="eo">Pascal-fontkodo</comment>
- <comment xml:lang="es">código fuente en Pascal</comment>
- <comment xml:lang="eu">Pascal iturburu-kodea</comment>
- <comment xml:lang="fi">Pascal-lähdekoodi</comment>
- <comment xml:lang="fo">Pascal keldukota</comment>
- <comment xml:lang="fr">code source Pascal</comment>
- <comment xml:lang="ga">cód foinseach Pascal</comment>
- <comment xml:lang="gl">código fonte en Pascal</comment>
- <comment xml:lang="he">קוד מקור של Pascal</comment>
- <comment xml:lang="hr">Pascal izvorni kôd</comment>
- <comment xml:lang="hu">Pascal-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Pascal</comment>
- <comment xml:lang="id">Kode sumber Pascal</comment>
- <comment xml:lang="it">Codice sorgente Pascal</comment>
- <comment xml:lang="ja">Pascal ソースコード</comment>
- <comment xml:lang="kk">Pascal бастапқы коды</comment>
- <comment xml:lang="ko">파스칼 소스 코드</comment>
- <comment xml:lang="lt">Pascal pradinis kodas</comment>
- <comment xml:lang="lv">Pascal pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Pascal</comment>
- <comment xml:lang="nb">Pascal-kildekode</comment>
- <comment xml:lang="nl">Pascal-broncode</comment>
- <comment xml:lang="nn">Pascal-kjeldekode</comment>
- <comment xml:lang="oc">còde font Pascal</comment>
- <comment xml:lang="pl">Kod źródłowy Pascal</comment>
- <comment xml:lang="pt">código origem Pascal</comment>
- <comment xml:lang="pt_BR">Código-fonte Pascal</comment>
- <comment xml:lang="ro">Cod sursă Pascal</comment>
- <comment xml:lang="ru">Исходный код Pascal</comment>
- <comment xml:lang="sk">Zdrojový kód Pascal</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Pascal</comment>
- <comment xml:lang="sq">Kod burues Pascal</comment>
- <comment xml:lang="sr">Паскалов изворни ко̂д</comment>
- <comment xml:lang="sv">Pascal-källkod</comment>
- <comment xml:lang="tr">Pascal kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Pascal</comment>
- <comment xml:lang="vi">Mã nguồn Pascal</comment>
- <comment xml:lang="zh_CN">Pascal 源代码</comment>
<comment xml:lang="zh_TW">Pascal 源碼</comment>
+ <comment xml:lang="zh_CN">Pascal 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Pascal</comment>
+ <comment xml:lang="uk">початковий код мовою Pascal</comment>
+ <comment xml:lang="tr">Pascal kaynak kodu</comment>
+ <comment xml:lang="sv">Pascal-källkod</comment>
+ <comment xml:lang="sr">Паскалов изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Pascal</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Pascal</comment>
+ <comment xml:lang="si">පැස්කල් මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Pascal</comment>
+ <comment xml:lang="ru">Исходный код Pascal</comment>
+ <comment xml:lang="ro">Cod sursă Pascal</comment>
+ <comment xml:lang="pt_BR">Código-fonte Pascal</comment>
+ <comment xml:lang="pt">código origem Pascal</comment>
+ <comment xml:lang="pl">Kod źródłowy Pascal</comment>
+ <comment xml:lang="oc">còde font Pascal</comment>
+ <comment xml:lang="nn">Pascal-kjeldekode</comment>
+ <comment xml:lang="nl">Pascal-broncode</comment>
+ <comment xml:lang="nb">Pascal-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Pascal</comment>
+ <comment xml:lang="lv">Pascal pirmkods</comment>
+ <comment xml:lang="lt">Pascal pradinis kodas</comment>
+ <comment xml:lang="ko">파스칼 소스 코드</comment>
+ <comment xml:lang="kk">Pascal бастапқы коды</comment>
+ <comment xml:lang="ja">Pascal ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Pascal</comment>
+ <comment xml:lang="is">Pascal frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Pascal</comment>
+ <comment xml:lang="ia">Codice-fonte Pascal</comment>
+ <comment xml:lang="hu">Pascal-forráskód</comment>
+ <comment xml:lang="hr">Pascal izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Pascal</comment>
+ <comment xml:lang="gl">código fonte en Pascal</comment>
+ <comment xml:lang="ga">cód foinseach Pascal</comment>
+ <comment xml:lang="fur">codiç sorzint Pascal</comment>
+ <comment xml:lang="fr">code source Pascal</comment>
+ <comment xml:lang="fo">Pascal keldukota</comment>
+ <comment xml:lang="fi">Pascal-lähdekoodi</comment>
+ <comment xml:lang="eu">Pascal iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Pascal</comment>
+ <comment xml:lang="eo">Pascal-fontkodo</comment>
+ <comment xml:lang="en_GB">Pascal source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Pascal</comment>
+ <comment xml:lang="de">Pascal-Quelltext</comment>
+ <comment xml:lang="da">Pascal-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Pascal</comment>
+ <comment xml:lang="ca">codi font en Pascal</comment>
+ <comment xml:lang="bg">Изходен код — Pascal</comment>
+ <comment xml:lang="be@latin">Kryničny kod Pascal</comment>
+ <comment xml:lang="be">зыходны код Pascal</comment>
+ <comment xml:lang="ar">شفرة مصدر باسكال</comment>
+ <comment xml:lang="af">Pascal-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.p"/>
<glob pattern="*.pas"/>
</mime-type>
<mime-type type="text/x-patch">
- <comment>differences between files</comment>
- <comment xml:lang="ar">الاختلافات بين الملفات</comment>
- <comment xml:lang="be@latin">adroźnieńni pamiž fajłami</comment>
- <comment xml:lang="bg">Разлики между файлове</comment>
- <comment xml:lang="ca">diferències entre fitxers</comment>
- <comment xml:lang="cs">rozdíly mezi soubory</comment>
- <comment xml:lang="da">forskel mellem filer</comment>
- <comment xml:lang="de">Unterschiede zwischen Dateien</comment>
- <comment xml:lang="el">Διαφορές μεταξύ αρχείων</comment>
- <comment xml:lang="en_GB">differences between files</comment>
- <comment xml:lang="eo">diferencoj inter dosieroj</comment>
- <comment xml:lang="es">diferencias entre archivos</comment>
- <comment xml:lang="eu">fitxategien arteko ezberdintasunak</comment>
- <comment xml:lang="fi">tiedostojen väliset erot</comment>
- <comment xml:lang="fo">munur millum fílur</comment>
- <comment xml:lang="fr">différences entre fichiers</comment>
- <comment xml:lang="ga">difríochtaí idir chomhaid</comment>
- <comment xml:lang="gl">diferenzas entre ficheiros</comment>
- <comment xml:lang="he">הבדל בין קבצים</comment>
- <comment xml:lang="hr">Razlike između datoteka</comment>
- <comment xml:lang="hu">diff-különbségfájl</comment>
- <comment xml:lang="ia">Differentias inter files</comment>
- <comment xml:lang="id">perbedaan diantara berkas</comment>
- <comment xml:lang="it">Differenze tra file</comment>
- <comment xml:lang="ja">ファイル間差分</comment>
- <comment xml:lang="kk">файлдар арасындағы айырмашылықтары</comment>
- <comment xml:lang="ko">파일 사이의 차이점</comment>
- <comment xml:lang="lt">skirtumai tarp failų</comment>
- <comment xml:lang="lv">divu datņu atšķirība</comment>
- <comment xml:lang="ms">Perbezaan antara fail</comment>
- <comment xml:lang="nb">forskjeller mellom filer</comment>
- <comment xml:lang="nl">verschillen tussen bestanden</comment>
- <comment xml:lang="nn">skilnader mellom filer</comment>
- <comment xml:lang="oc">différences entre fichièrs</comment>
- <comment xml:lang="pl">Różnica pomiędzy plikami</comment>
- <comment xml:lang="pt">diferenças entre ficheiros</comment>
- <comment xml:lang="pt_BR">Diferenças entre arquivos</comment>
- <comment xml:lang="ro">diferențe între fișiere</comment>
- <comment xml:lang="ru">Различия между файлами</comment>
- <comment xml:lang="sk">Rozdiely medzi súbormi</comment>
- <comment xml:lang="sl">razlike med datotekami</comment>
- <comment xml:lang="sq">Diferencë midis file</comment>
- <comment xml:lang="sr">разлике између датотека</comment>
- <comment xml:lang="sv">skillnader mellan filer</comment>
- <comment xml:lang="tr">dosyalar arasındaki fark</comment>
+ <comment>Differences between files</comment>
<comment xml:lang="uk">різниця між файлами</comment>
- <comment xml:lang="vi">khác biệt giữa các tập tin</comment>
- <comment xml:lang="zh_CN">文件的区别</comment>
- <comment xml:lang="zh_TW">檔案內容差異</comment>
+ <comment xml:lang="sv">Skillnader mellan filer</comment>
+ <comment xml:lang="ru">Различия между файлами</comment>
+ <comment xml:lang="pl">Różnica pomiędzy plikami</comment>
+ <comment xml:lang="ja">差分文書</comment>
+ <comment xml:lang="it">Differenze tra file</comment>
+ <comment xml:lang="gl">Diferenzas entre ficheiros</comment>
+ <comment xml:lang="eu">Fitxategien arteko diferentziak</comment>
+ <comment xml:lang="es">diferencias entre archivos</comment>
+ <comment xml:lang="de">Unterschiede zwischen Dateien</comment>
+ <comment xml:lang="be">адрозненні паміж файламі</comment>
<alias type="text/x-diff"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="diff\t" type="string" offset="0"/>
- <match value="diff " type="string" offset="0"/>
- <match value="***\t" type="string" offset="0"/>
- <match value="*** " type="string" offset="0"/>
- <match value="=== " type="string" offset="0"/>
- <match value="--- " type="string" offset="0"/>
- <match value="Only in\t" type="string" offset="0"/>
- <match value="Only in " type="string" offset="0"/>
- <match value="Common subdirectories: " type="string" offset="0"/>
- <match value="Index:" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="diff\t" offset="0"/>
+ <match type="string" value="diff " offset="0"/>
+ <match type="string" value="***\t" offset="0"/>
+ <match type="string" value="*** " offset="0"/>
+ <match type="string" value="=== " offset="0"/>
+ <match type="string" value="--- " offset="0"/>
+ <match type="string" value="Only in\t" offset="0"/>
+ <match type="string" value="Only in " offset="0"/>
+ <match type="string" value="Common subdirectories: " offset="0"/>
+ <match type="string" value="Index:" offset="0"/>
</magic>
<glob pattern="*.diff"/>
<glob pattern="*.patch"/>
</mime-type>
+ <mime-type type="application/vnd.dart">
+ <comment>Dart source code</comment>
+ <comment xml:lang="zh_TW">Dart 原始碼</comment>
+ <comment xml:lang="zh_CN">Dart 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Dart</comment>
+ <comment xml:lang="tr">Dart kaynak kodu</comment>
+ <comment xml:lang="sv">Dart-källkod</comment>
+ <comment xml:lang="sl">Izvorna koda Dart</comment>
+ <comment xml:lang="si">ඩාර්ට් මූලාශ්‍ර කේතය</comment>
+ <comment xml:lang="ru">Исходный код Dart</comment>
+ <comment xml:lang="pt_BR">Código-fonte Dart</comment>
+ <comment xml:lang="pl">Kod źródłowy Dart</comment>
+ <comment xml:lang="nl">Dart-broncode</comment>
+ <comment xml:lang="ko">Dart 소스 코드</comment>
+ <comment xml:lang="kk">Dart бастапқы коды</comment>
+ <comment xml:lang="ja">Dart ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Dart</comment>
+ <comment xml:lang="hr">Dart izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור ב־Dart</comment>
+ <comment xml:lang="gl">Código fonte Dart</comment>
+ <comment xml:lang="fi">Dart-lähdekoodi</comment>
+ <comment xml:lang="eu">Dart iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente Dart</comment>
+ <comment xml:lang="en_GB">Dart source code</comment>
+ <comment xml:lang="de">Dart-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Dart</comment>
+ <comment xml:lang="ar">شفرة مصدر Dart</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.dart"/>
+ <alias type="text/x-dart"/>
+ </mime-type>
+ <mime-type type="text/x-nim">
+ <comment>Nim source code</comment>
+ <comment xml:lang="uk">початковий код мовою Nim</comment>
+ <comment xml:lang="sv">Nim-källkod</comment>
+ <comment xml:lang="ru">Исходный код Nim</comment>
+ <comment xml:lang="pl">Kod źródłowy Nim</comment>
+ <comment xml:lang="it">Codice sorgente Nim</comment>
+ <comment xml:lang="gl">Código fonte Nim</comment>
+ <comment xml:lang="eu">Nim iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Nim</comment>
+ <comment xml:lang="de">Nim-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Nim</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.nim"/>
+ </mime-type>
+ <mime-type type="text/x-nimscript">
+ <comment>Nimscript source code</comment>
+ <comment xml:lang="uk">початковий код мовою Nimscript</comment>
+ <comment xml:lang="sv">Nimscript-källkod</comment>
+ <comment xml:lang="ru">Исходный код Nimscript</comment>
+ <comment xml:lang="pl">Kod źródłowy NimScript</comment>
+ <comment xml:lang="it">Codice sorgente Nimscript</comment>
+ <comment xml:lang="gl">Código fonte Nimscript</comment>
+ <comment xml:lang="eu">Nimscript iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Nimscript</comment>
+ <comment xml:lang="de">Nimscript-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Nimscript</comment>
+ <sub-class-of type="text/x-nim"/>
+ <glob pattern="*.nims"/>
+ <glob pattern="*.nimble"/>
+ </mime-type>
<mime-type type="text/x-go">
<comment>Go source code</comment>
- <comment xml:lang="bg">Изходен код — Go</comment>
- <comment xml:lang="ca">codi font en Go</comment>
- <comment xml:lang="cs">zdrojový kód v jazyce Go</comment>
- <comment xml:lang="da">Go-kildekode</comment>
- <comment xml:lang="de">Go-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Go</comment>
- <comment xml:lang="en_GB">Go source code</comment>
- <comment xml:lang="eo">Go-fontkodo</comment>
- <comment xml:lang="es">código fuente en Go</comment>
- <comment xml:lang="eu">Go iturburu-kodea</comment>
- <comment xml:lang="fi">Go-lähdekoodi</comment>
- <comment xml:lang="fr">code source Go</comment>
- <comment xml:lang="ga">cód foinseach Go</comment>
- <comment xml:lang="gl">código fonte de Go</comment>
- <comment xml:lang="he">קוד מקור של Go</comment>
- <comment xml:lang="hr">Go izvorni kôd</comment>
- <comment xml:lang="hu">Go forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Go</comment>
- <comment xml:lang="id">Kode sumber Go</comment>
- <comment xml:lang="it">Codice sorgente Go</comment>
- <comment xml:lang="ja">Go ソースコード</comment>
- <comment xml:lang="ka">Go-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Go бастапқы коды</comment>
- <comment xml:lang="ko">Go 소스 코드</comment>
- <comment xml:lang="lv">Go pirmkods</comment>
- <comment xml:lang="nl">Go broncode</comment>
- <comment xml:lang="oc">còde font Go</comment>
- <comment xml:lang="pl">Kod źródłowy Go</comment>
- <comment xml:lang="pt">cigo origem Go</comment>
- <comment xml:lang="pt_BR">Código-fonte Go</comment>
- <comment xml:lang="ru">Исходный код Go</comment>
- <comment xml:lang="sk">Zdrojový kód Go</comment>
- <comment xml:lang="sl">Izvorna koda Go</comment>
- <comment xml:lang="sr">Гоу изворни ко̂д</comment>
- <comment xml:lang="sv">Go-källkod</comment>
- <comment xml:lang="tr">Go kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Go</comment>
- <comment xml:lang="zh_CN">Go 源代码</comment>
<comment xml:lang="zh_TW">Go 源碼</comment>
+ <comment xml:lang="zh_CN">Go 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Go</comment>
+ <comment xml:lang="tr">Go kaynak kodu</comment>
+ <comment xml:lang="sv">Go-källkod</comment>
+ <comment xml:lang="sr">Гоу изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Go</comment>
+ <comment xml:lang="sl">Izvorna koda Go</comment>
+ <comment xml:lang="si">මූල කේතය වෙත යන්න</comment>
+ <comment xml:lang="sk">Zdrojový kód Go</comment>
+ <comment xml:lang="ru">Исходный код Go</comment>
+ <comment xml:lang="pt_BR">Código-fonte Go</comment>
+ <comment xml:lang="pt">cigo origem Go</comment>
+ <comment xml:lang="pl">Kod źródłowy Go</comment>
+ <comment xml:lang="oc">còde font Go</comment>
+ <comment xml:lang="nl">Go-broncode</comment>
+ <comment xml:lang="lv">Go pirmkods</comment>
+ <comment xml:lang="ko">Go 소스 코드</comment>
+ <comment xml:lang="kk">Go бастапқы коды</comment>
+ <comment xml:lang="ka">Go-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Go ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Go</comment>
+ <comment xml:lang="is">Go frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Go</comment>
+ <comment xml:lang="ia">Codice-fonte Go</comment>
+ <comment xml:lang="hu">Go forráskód</comment>
+ <comment xml:lang="hr">Go izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Go</comment>
+ <comment xml:lang="gl">código fonte de Go</comment>
+ <comment xml:lang="ga">cód foinseach Go</comment>
+ <comment xml:lang="fur">codiç sorzint Go</comment>
+ <comment xml:lang="fr">code source Go</comment>
+ <comment xml:lang="fi">Go-lähdekoodi</comment>
+ <comment xml:lang="eu">Go iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Go</comment>
+ <comment xml:lang="eo">Go-fontkodo</comment>
+ <comment xml:lang="en_GB">Go source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Go</comment>
+ <comment xml:lang="de">Go-Quelltext</comment>
+ <comment xml:lang="da">Go-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Go</comment>
+ <comment xml:lang="ca">codi font en Go</comment>
+ <comment xml:lang="bg">Изходен код — Go</comment>
+ <comment xml:lang="be">зыходны код Go</comment>
+ <comment xml:lang="ar">شفرة مصدر غو</comment>
+ <comment xml:lang="af">Go-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.go"/>
</mime-type>
<mime-type type="text/x-scons">
<comment>SCons configuration file</comment>
- <comment xml:lang="ca">fitxer de configuració de SCons</comment>
- <comment xml:lang="cs">konfigurační soubor SCons</comment>
- <comment xml:lang="da">SCons-konfigurationsfil</comment>
- <comment xml:lang="de">SCons-Konfigurationsdatei</comment>
- <comment xml:lang="el">Αρχείο ρυθμίσεων SCons</comment>
- <comment xml:lang="en_GB">SCons configuration file</comment>
- <comment xml:lang="es">archivo de configuración de SCons</comment>
- <comment xml:lang="eu">SCons konfigurazio-fitxategia</comment>
- <comment xml:lang="fi">SCons-asetustiedosto</comment>
- <comment xml:lang="fr">fichier de configuration SCons</comment>
- <comment xml:lang="ga">comhad cumraíochta SCons</comment>
- <comment xml:lang="he">קובץ תצורה של SCons</comment>
- <comment xml:lang="hr">SCons datoteka podešavanja</comment>
- <comment xml:lang="hu">SCons beállítófájl</comment>
- <comment xml:lang="ia">File de cofniguration SCons</comment>
- <comment xml:lang="id">Berkas konfigurasi SCons</comment>
- <comment xml:lang="it">File configurazione SCons</comment>
- <comment xml:lang="kk">SCons баптаулар файлы</comment>
- <comment xml:lang="ko">SCons 설정 파일</comment>
- <comment xml:lang="oc">fichièr de configuracion SCons</comment>
- <comment xml:lang="pl">Plik konfiguracji SCons</comment>
- <comment xml:lang="pt">ficheiro de configuração SCons</comment>
- <comment xml:lang="pt_BR">Arquivo de configuração do SCons</comment>
- <comment xml:lang="ru">Файл настроек SCons</comment>
- <comment xml:lang="sk">Konfiguračný súbor SCons</comment>
- <comment xml:lang="sl">Prilagoditvena datoteka SCons</comment>
- <comment xml:lang="sr">СКонс датотека подешавања</comment>
- <comment xml:lang="sv">SCons-konfigurationsfil</comment>
- <comment xml:lang="tr">SCons yapılandırma dosyası</comment>
- <comment xml:lang="uk">файл налаштувань SCons</comment>
- <comment xml:lang="zh_CN">SCons 配置文件</comment>
<comment xml:lang="zh_TW">SCons 組態檔</comment>
+ <comment xml:lang="zh_CN">SCons 配置文件</comment>
+ <comment xml:lang="uk">файл налаштувань SCons</comment>
+ <comment xml:lang="tr">SCons yapılandırma dosyası</comment>
+ <comment xml:lang="sv">SCons-konfigurationsfil</comment>
+ <comment xml:lang="sr">СКонс датотека подешавања</comment>
+ <comment xml:lang="sq">kartelë formësimi SCons</comment>
+ <comment xml:lang="sl">Prilagoditvena datoteka SCons</comment>
+ <comment xml:lang="si">SCons වින්‍යාස ගොනුව</comment>
+ <comment xml:lang="sk">Konfiguračný súbor SCons</comment>
+ <comment xml:lang="ru">Файл настроек SCons</comment>
+ <comment xml:lang="pt_BR">Arquivo de configuração do SCons</comment>
+ <comment xml:lang="pt">ficheiro de configuração SCons</comment>
+ <comment xml:lang="pl">Plik konfiguracji SCons</comment>
+ <comment xml:lang="oc">fichièr de configuracion SCons</comment>
+ <comment xml:lang="nl">SCons-configuratiebestand</comment>
+ <comment xml:lang="ko">SCons 설정 파일</comment>
+ <comment xml:lang="kk">SCons баптаулар файлы</comment>
+ <comment xml:lang="ja">SCons 設定ファイル</comment>
+ <comment xml:lang="it">File configurazione SCons</comment>
+ <comment xml:lang="is">SCons stillingaskrá</comment>
+ <comment xml:lang="id">Berkas konfigurasi SCons</comment>
+ <comment xml:lang="ia">File de cofniguration SCons</comment>
+ <comment xml:lang="hu">SCons beállítófájl</comment>
+ <comment xml:lang="hr">SCons datoteka podešavanja</comment>
+ <comment xml:lang="he">קובץ תצורה של SCons</comment>
+ <comment xml:lang="gl">Ficheiro de configuración SCons</comment>
+ <comment xml:lang="ga">comhad cumraíochta SCons</comment>
+ <comment xml:lang="fur">file di configurazion SCons</comment>
+ <comment xml:lang="fr">fichier de configuration SCons</comment>
+ <comment xml:lang="fi">SCons-asetustiedosto</comment>
+ <comment xml:lang="eu">SCons konfigurazio-fitxategia</comment>
+ <comment xml:lang="es">archivo de configuración de SCons</comment>
+ <comment xml:lang="en_GB">SCons configuration file</comment>
+ <comment xml:lang="el">Αρχείο ρυθμίσεων SCons</comment>
+ <comment xml:lang="de">SCons-Konfigurationsdatei</comment>
+ <comment xml:lang="da">SCons-konfigurationsfil</comment>
+ <comment xml:lang="cs">konfigurační soubor SCons</comment>
+ <comment xml:lang="ca">fitxer de configuració de SCons</comment>
+ <comment xml:lang="bg">Настройки — SCons</comment>
+ <comment xml:lang="be">файл канфігурацыі SCons</comment>
+ <comment xml:lang="ar">ملف إعداد SCons</comment>
+ <comment xml:lang="af">SCons-opstellingslêer</comment>
<sub-class-of type="text/x-python"/>
<glob pattern="SConstruct"/>
<glob pattern="SConscript"/>
@@ -35771,715 +37901,869 @@
</mime-type>
<mime-type type="text/x-python3">
<comment>Python 3 script</comment>
- <comment xml:lang="ca">script Python 3</comment>
- <comment xml:lang="cs">skript v jazyce Python 3</comment>
- <comment xml:lang="de">Python-3-Skript</comment>
- <comment xml:lang="en_GB">Python 3 script</comment>
- <comment xml:lang="es">secuencia de órdenes en Python 3</comment>
- <comment xml:lang="fi">Python 3 -skripti</comment>
- <comment xml:lang="hr">Python3 skripta</comment>
- <comment xml:lang="hu">Python 3 parancsfájl</comment>
- <comment xml:lang="id">Skrip Python 3</comment>
- <comment xml:lang="it">Script Python 3</comment>
- <comment xml:lang="kk">Python 3 скрипті</comment>
- <comment xml:lang="ko">파이썬 3 스크립트</comment>
- <comment xml:lang="pl">Skrypt Python 3</comment>
- <comment xml:lang="pt_BR">Script Python 3</comment>
- <comment xml:lang="ru">Сценарий Python 3</comment>
- <comment xml:lang="sk">Skript Python 3</comment>
- <comment xml:lang="sv">Python 3-skript</comment>
- <comment xml:lang="uk">скрипт мовою Python 3</comment>
- <comment xml:lang="zh_CN">Python 3 脚本</comment>
<comment xml:lang="zh_TW">Python 3 指令稿</comment>
- <sub-class-of type='text/x-python'/>
+ <comment xml:lang="zh_CN">Python 3 脚本</comment>
+ <comment xml:lang="uk">скрипт мовою Python 3</comment>
+ <comment xml:lang="tr">Python 3 betiği</comment>
+ <comment xml:lang="sv">Python 3-skript</comment>
+ <comment xml:lang="sq">programth Python 3</comment>
+ <comment xml:lang="sl">Skript Python 3</comment>
+ <comment xml:lang="si">Python 3 පිටපත</comment>
+ <comment xml:lang="sk">Skript Python 3</comment>
+ <comment xml:lang="ru">Сценарий Python 3</comment>
+ <comment xml:lang="pt_BR">Script Python 3</comment>
+ <comment xml:lang="pl">Skrypt Python 3</comment>
+ <comment xml:lang="oc">script Python 3</comment>
+ <comment xml:lang="nl">Python 3-script</comment>
+ <comment xml:lang="ko">파이썬 3 스크립트</comment>
+ <comment xml:lang="kk">Python 3 скрипті</comment>
+ <comment xml:lang="ja">Python 3 スクリプト</comment>
+ <comment xml:lang="it">Script Python 3</comment>
+ <comment xml:lang="is">Python 3 skrifta</comment>
+ <comment xml:lang="id">Skrip Python 3</comment>
+ <comment xml:lang="hu">Python 3 parancsfájl</comment>
+ <comment xml:lang="hr">Python3 skripta</comment>
+ <comment xml:lang="he">סקריפט Python 3</comment>
+ <comment xml:lang="ga">script Python 3</comment>
+ <comment xml:lang="fur">script Python 3</comment>
+ <comment xml:lang="fr">script Python 3</comment>
+ <comment xml:lang="fi">Python 3 -komentotiedosto</comment>
+ <comment xml:lang="eu">Python 3 script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Python 3</comment>
+ <comment xml:lang="en_GB">Python 3 script</comment>
+ <comment xml:lang="de">Python-3-Skript</comment>
+ <comment xml:lang="da">Python 3-program</comment>
+ <comment xml:lang="cs">skript v jazyce Python 3</comment>
+ <comment xml:lang="ca">script Python 3</comment>
+ <comment xml:lang="bg">Скрипт — Python 3</comment>
+ <comment xml:lang="be">скрыпт Python 3</comment>
+ <comment xml:lang="ar">سكربت بايثون٣</comment>
+ <comment xml:lang="af">Python 3-skrip</comment>
+ <sub-class-of type="text/x-python"/>
<magic priority="60">
- <match value="#!/bin/python3" type="string" offset="0"/>
- <match value="#! /bin/python3" type="string" offset="0"/>
- <match value='eval \"exec /bin/python3' type="string" offset="0"/>
- <match value="#!/usr/bin/python3" type="string" offset="0"/>
- <match value="#! /usr/bin/python3" type="string" offset="0"/>
- <match value='eval \"exec /usr/bin/python3' type="string" offset="0"/>
- <match value="#!/usr/local/bin/python3" type="string" offset="0"/>
- <match value="#! /usr/local/bin/python3" type="string" offset="0"/>
- <match value='eval \"exec /usr/local/bin/python3' type="string" offset="0"/>
- <match value='/bin/env python3' type="string" offset="2:16"/>
- </magic>
- <glob weight="50" pattern="*.py"/>
- <glob weight="60" pattern="*.py3"/>
- <glob weight="60" pattern="*.py3x"/>
+ <!-- higher priority than text/x-python -->
+ <match type="string" value="#!/bin/python3" offset="0"/>
+ <match type="string" value="#! /bin/python3" offset="0"/>
+ <match type="string" value="eval \&quot;exec /bin/python3" offset="0"/>
+ <match type="string" value="#!/usr/bin/python3" offset="0"/>
+ <match type="string" value="#! /usr/bin/python3" offset="0"/>
+ <match type="string" value="eval \&quot;exec /usr/bin/python3" offset="0"/>
+ <match type="string" value="#!/usr/local/bin/python3" offset="0"/>
+ <match type="string" value="#! /usr/local/bin/python3" offset="0"/>
+ <match type="string" value="eval \&quot;exec /usr/local/bin/python3" offset="0"/>
+ <match type="string" value="/bin/env python3" offset="2:16"/>
+ </magic>
+ <glob pattern="*.py"/>
+ <!-- lower priority than in text/x-python -->
+ <glob pattern="*.py3" weight="60"/>
+ <glob pattern="*.py3x" weight="60"/>
+ <glob pattern="*.pyi" weight="60"/>
</mime-type>
<mime-type type="text/x-python">
<comment>Python script</comment>
- <comment xml:lang="ar">سكربت بايثون</comment>
- <comment xml:lang="be@latin">Skrypt Python</comment>
- <comment xml:lang="bg">Скрипт — Python</comment>
- <comment xml:lang="ca">script Python</comment>
- <comment xml:lang="cs">skript v jazyce Python</comment>
- <comment xml:lang="da">Pythonprogram</comment>
- <comment xml:lang="de">Python-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών Python</comment>
- <comment xml:lang="en_GB">Python script</comment>
- <comment xml:lang="eo">Python-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en Python</comment>
- <comment xml:lang="eu">Python script-a</comment>
- <comment xml:lang="fi">Python-komentotiedosto</comment>
- <comment xml:lang="fo">Python boðrøð</comment>
- <comment xml:lang="fr">script Python</comment>
- <comment xml:lang="ga">script Python</comment>
- <comment xml:lang="gl">Script en Python</comment>
- <comment xml:lang="he">תסריט Python</comment>
- <comment xml:lang="hr">Python skripta</comment>
- <comment xml:lang="hu">Python-parancsfájl</comment>
- <comment xml:lang="ia">Script Python</comment>
- <comment xml:lang="id">Skrip Python</comment>
- <comment xml:lang="it">Script Python</comment>
- <comment xml:lang="ja">Python スクリプト</comment>
- <comment xml:lang="kk">Python сценарийі</comment>
- <comment xml:lang="ko">파이썬 스크립트</comment>
- <comment xml:lang="lt">Python scenarijus</comment>
- <comment xml:lang="lv">Python skripts</comment>
- <comment xml:lang="ms">Skrip Python</comment>
- <comment xml:lang="nb">Python-skript</comment>
- <comment xml:lang="nl">Python-script</comment>
- <comment xml:lang="nn">Python-skript</comment>
- <comment xml:lang="oc">escript Python</comment>
- <comment xml:lang="pl">Skrypt Python</comment>
- <comment xml:lang="pt">script Python</comment>
- <comment xml:lang="pt_BR">Script Python</comment>
- <comment xml:lang="ro">Script Python</comment>
- <comment xml:lang="ru">Сценарий Python</comment>
- <comment xml:lang="sk">Skript Python</comment>
- <comment xml:lang="sl">Skriptna datoteka Python</comment>
- <comment xml:lang="sq">Script Python</comment>
- <comment xml:lang="sr">Питонова скрипта</comment>
- <comment xml:lang="sv">Pythonskript</comment>
- <comment xml:lang="tr">Python betiği</comment>
- <comment xml:lang="uk">скрипт мовою Python</comment>
- <comment xml:lang="vi">Văn lệnh Python</comment>
- <comment xml:lang="zh_CN">Python 脚本</comment>
<comment xml:lang="zh_TW">Python 指令稿</comment>
- <sub-class-of type='application/x-executable'/>
+ <comment xml:lang="zh_CN">Python 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh Python</comment>
+ <comment xml:lang="uk">скрипт мовою Python</comment>
+ <comment xml:lang="tr">Python betiği</comment>
+ <comment xml:lang="sv">Pythonskript</comment>
+ <comment xml:lang="sr">Питонова скрипта</comment>
+ <comment xml:lang="sq">programth Python</comment>
+ <comment xml:lang="sl">Skriptna datoteka Python</comment>
+ <comment xml:lang="si">පයිතන් පිටපත</comment>
+ <comment xml:lang="sk">Skript Python</comment>
+ <comment xml:lang="ru">Сценарий Python</comment>
+ <comment xml:lang="ro">Script Python</comment>
+ <comment xml:lang="pt_BR">Script Python</comment>
+ <comment xml:lang="pt">script Python</comment>
+ <comment xml:lang="pl">Skrypt Python</comment>
+ <comment xml:lang="oc">escript Python</comment>
+ <comment xml:lang="nn">Python-skript</comment>
+ <comment xml:lang="nl">Python-script</comment>
+ <comment xml:lang="nb">Python-skript</comment>
+ <comment xml:lang="ms">Skrip Python</comment>
+ <comment xml:lang="lv">Python skripts</comment>
+ <comment xml:lang="lt">Python scenarijus</comment>
+ <comment xml:lang="ko">파이썬 스크립트</comment>
+ <comment xml:lang="kk">Python сценарийі</comment>
+ <comment xml:lang="ja">Python スクリプト</comment>
+ <comment xml:lang="it">Script Python</comment>
+ <comment xml:lang="is">Python skrifta</comment>
+ <comment xml:lang="id">Skrip Python</comment>
+ <comment xml:lang="ia">Script Python</comment>
+ <comment xml:lang="hu">Python-parancsfájl</comment>
+ <comment xml:lang="hr">Python skripta</comment>
+ <comment xml:lang="he">תסריט Python</comment>
+ <comment xml:lang="gl">Script en Python</comment>
+ <comment xml:lang="ga">script Python</comment>
+ <comment xml:lang="fur">script Python</comment>
+ <comment xml:lang="fr">script Python</comment>
+ <comment xml:lang="fo">Python boðrøð</comment>
+ <comment xml:lang="fi">Python-komentotiedosto</comment>
+ <comment xml:lang="eu">Python script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Python</comment>
+ <comment xml:lang="eo">Python-skripto</comment>
+ <comment xml:lang="en_GB">Python script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών Python</comment>
+ <comment xml:lang="de">Python-Skript</comment>
+ <comment xml:lang="da">Python-program</comment>
+ <comment xml:lang="cs">skript v jazyce Python</comment>
+ <comment xml:lang="ca">script Python</comment>
+ <comment xml:lang="bg">Скрипт — Python</comment>
+ <comment xml:lang="be@latin">Skrypt Python</comment>
+ <comment xml:lang="be">скрыпт Python</comment>
+ <comment xml:lang="ar">سكربت بايثون</comment>
+ <comment xml:lang="af">Python-skrip</comment>
+ <sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="#!/bin/python" type="string" offset="0"/>
- <match value="#! /bin/python" type="string" offset="0"/>
- <match value='eval \"exec /bin/python' type="string" offset="0"/>
- <match value="#!/usr/bin/python" type="string" offset="0"/>
- <match value="#! /usr/bin/python" type="string" offset="0"/>
- <match value='eval \"exec /usr/bin/python' type="string" offset="0"/>
- <match value="#!/usr/local/bin/python" type="string" offset="0"/>
- <match value="#! /usr/local/bin/python" type="string" offset="0"/>
- <match value='eval \"exec /usr/local/bin/python' type="string" offset="0"/>
- <match value='/bin/env python' type="string" offset="2:16"/>
- </magic>
- <glob weight="60" pattern="*.py"/>
- <glob weight="60" pattern="*.pyx"/>
- <glob weight="60" pattern="*.wsgi"/>
+ <magic>
+ <match type="string" value="#!/bin/python" offset="0"/>
+ <match type="string" value="#! /bin/python" offset="0"/>
+ <match type="string" value="eval \&quot;exec /bin/python" offset="0"/>
+ <match type="string" value="#!/usr/bin/python" offset="0"/>
+ <match type="string" value="#! /usr/bin/python" offset="0"/>
+ <match type="string" value="eval \&quot;exec /usr/bin/python" offset="0"/>
+ <match type="string" value="#!/usr/local/bin/python" offset="0"/>
+ <match type="string" value="#! /usr/local/bin/python" offset="0"/>
+ <match type="string" value="eval \&quot;exec /usr/local/bin/python" offset="0"/>
+ <match type="string" value="/bin/env python" offset="2:16"/>
+ </magic>
+ <glob pattern="*.py" weight="60"/>
+ <glob pattern="*.pyx" weight="60"/>
+ <glob pattern="*.wsgi" weight="60"/>
+ </mime-type>
+ <mime-type type="text/x-sagemath">
+ <comment>SageMath script</comment>
+ <comment xml:lang="zh_TW">SageMath 指令稿</comment>
+ <comment xml:lang="zh_CN">SageMath 脚本</comment>
+ <comment xml:lang="uk">скрипт SageMath</comment>
+ <comment xml:lang="tr">SageMath betiği</comment>
+ <comment xml:lang="sv">SageMath-skript</comment>
+ <comment xml:lang="sl">Skript SageMath</comment>
+ <comment xml:lang="si">SageMath පිටපත</comment>
+ <comment xml:lang="ru">Сценарий SageMath</comment>
+ <comment xml:lang="pt_BR">Script SageMath</comment>
+ <comment xml:lang="pl">Skrypt SageMath</comment>
+ <comment xml:lang="nl">SageMath-script</comment>
+ <comment xml:lang="ko">SageMath 스크립트</comment>
+ <comment xml:lang="kk">SageMath сценарийі</comment>
+ <comment xml:lang="ja">SageMath スクリプト</comment>
+ <comment xml:lang="it">Script SageMath</comment>
+ <comment xml:lang="is">SageMath skrifta</comment>
+ <comment xml:lang="id">skrip SageMath</comment>
+ <comment xml:lang="hu">SageMath parancsfájl</comment>
+ <comment xml:lang="hr">SageMath skripta</comment>
+ <comment xml:lang="he">סקריפט SageMath</comment>
+ <comment xml:lang="fr">Script SageMath</comment>
+ <comment xml:lang="fi">SageMath-komentotiedosto</comment>
+ <comment xml:lang="eu">SageMath script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes de SageMath</comment>
+ <comment xml:lang="en_GB">SageMath script</comment>
+ <comment xml:lang="de">SageMath-Skript</comment>
+ <comment xml:lang="da">SageMath-program</comment>
+ <comment xml:lang="ca">script SageMath</comment>
+ <comment xml:lang="be">скрыпт SageMath</comment>
+ <comment xml:lang="ar">سكربت SageMath</comment>
+ <sub-class-of type="text/x-python"/>
+ <glob pattern="*.sage" weight="60"/>
</mime-type>
<mime-type type="text/x-lua">
<comment>Lua script</comment>
- <comment xml:lang="ar">سكربت Lua</comment>
- <comment xml:lang="be@latin">Skrypt Lua</comment>
- <comment xml:lang="bg">Скрипт на Lua</comment>
- <comment xml:lang="ca">script Lua</comment>
- <comment xml:lang="cs">skript v jazyce Lua</comment>
- <comment xml:lang="da">Luaprogram</comment>
- <comment xml:lang="de">Lua-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών Lua</comment>
- <comment xml:lang="en_GB">Lua script</comment>
- <comment xml:lang="eo">Lua-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en Lua</comment>
- <comment xml:lang="eu">Lua script-a</comment>
- <comment xml:lang="fi">Lua-komentotiedosto</comment>
- <comment xml:lang="fo">Lua boðrøð</comment>
- <comment xml:lang="fr">script Lua</comment>
- <comment xml:lang="ga">script Lua</comment>
- <comment xml:lang="gl">script de Lua</comment>
- <comment xml:lang="he">תסריט Lua</comment>
- <comment xml:lang="hr">Lua skripta</comment>
- <comment xml:lang="hu">Lua parancsfájl</comment>
- <comment xml:lang="ia">Script Lua</comment>
- <comment xml:lang="id">Skrip Lua</comment>
- <comment xml:lang="it">Script Lua</comment>
- <comment xml:lang="ja">Lua スクリプト</comment>
- <comment xml:lang="kk">Lua сценарийі</comment>
- <comment xml:lang="ko">Lua 스크립트</comment>
- <comment xml:lang="lt">Lua scenarijus</comment>
- <comment xml:lang="lv">Lua skripts</comment>
- <comment xml:lang="nb">Lua-skript</comment>
- <comment xml:lang="nl">Lua-script</comment>
- <comment xml:lang="nn">Lua-skript</comment>
- <comment xml:lang="oc">escript Lua</comment>
- <comment xml:lang="pl">Skrypt Lua</comment>
- <comment xml:lang="pt">script Lua</comment>
- <comment xml:lang="pt_BR">Script Lua</comment>
- <comment xml:lang="ro">Script Lua</comment>
- <comment xml:lang="ru">Сценарий Lua</comment>
- <comment xml:lang="sk">Skript Lua</comment>
- <comment xml:lang="sl">Skriptna datoteka Lua</comment>
- <comment xml:lang="sq">Script Lua</comment>
- <comment xml:lang="sr">Луа скрипта</comment>
- <comment xml:lang="sv">Lua-skript</comment>
- <comment xml:lang="tr">Lua betiği</comment>
- <comment xml:lang="uk">скрипт Lua</comment>
- <comment xml:lang="vi">Văn lệnh Lua</comment>
- <comment xml:lang="zh_CN">Lua 脚本</comment>
<comment xml:lang="zh_TW">Lua 指令稿</comment>
- <sub-class-of type='application/x-executable'/>
+ <comment xml:lang="zh_CN">Lua 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh Lua</comment>
+ <comment xml:lang="uk">скрипт Lua</comment>
+ <comment xml:lang="tr">Lua betiği</comment>
+ <comment xml:lang="sv">Lua-skript</comment>
+ <comment xml:lang="sr">Луа скрипта</comment>
+ <comment xml:lang="sq">programth Lua</comment>
+ <comment xml:lang="sl">Skriptna datoteka Lua</comment>
+ <comment xml:lang="si">Lua පිටපත</comment>
+ <comment xml:lang="sk">Skript Lua</comment>
+ <comment xml:lang="ru">Сценарий Lua</comment>
+ <comment xml:lang="ro">Script Lua</comment>
+ <comment xml:lang="pt_BR">Script Lua</comment>
+ <comment xml:lang="pt">script Lua</comment>
+ <comment xml:lang="pl">Skrypt Lua</comment>
+ <comment xml:lang="oc">escript Lua</comment>
+ <comment xml:lang="nn">Lua-skript</comment>
+ <comment xml:lang="nl">Lua-script</comment>
+ <comment xml:lang="nb">Lua-skript</comment>
+ <comment xml:lang="lv">Lua skripts</comment>
+ <comment xml:lang="lt">Lua scenarijus</comment>
+ <comment xml:lang="ko">Lua 스크립트</comment>
+ <comment xml:lang="kk">Lua сценарийі</comment>
+ <comment xml:lang="ja">Lua スクリプト</comment>
+ <comment xml:lang="it">Script Lua</comment>
+ <comment xml:lang="is">Lua skrifta</comment>
+ <comment xml:lang="id">Skrip Lua</comment>
+ <comment xml:lang="ia">Script Lua</comment>
+ <comment xml:lang="hu">Lua parancsfájl</comment>
+ <comment xml:lang="hr">Lua skripta</comment>
+ <comment xml:lang="he">תסריט Lua</comment>
+ <comment xml:lang="gl">script de Lua</comment>
+ <comment xml:lang="ga">script Lua</comment>
+ <comment xml:lang="fur">script Lua</comment>
+ <comment xml:lang="fr">script Lua</comment>
+ <comment xml:lang="fo">Lua boðrøð</comment>
+ <comment xml:lang="fi">Lua-komentotiedosto</comment>
+ <comment xml:lang="eu">Lua script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Lua</comment>
+ <comment xml:lang="eo">Lua-skripto</comment>
+ <comment xml:lang="en_GB">Lua script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών Lua</comment>
+ <comment xml:lang="de">Lua-Skript</comment>
+ <comment xml:lang="da">Lua-program</comment>
+ <comment xml:lang="cs">skript v jazyce Lua</comment>
+ <comment xml:lang="ca">script Lua</comment>
+ <comment xml:lang="bg">Скрипт на Lua</comment>
+ <comment xml:lang="be@latin">Skrypt Lua</comment>
+ <comment xml:lang="be">скрыпт Lua</comment>
+ <comment xml:lang="ar">سكربت Lua</comment>
+ <comment xml:lang="af">Lua-skrip</comment>
+ <sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="/bin/lua" type="string" offset="2:16"/>
- <match value="/bin/luajit" type="string" offset="2:16"/>
- <match value="/bin/env lua" type="string" offset="2:16"/>
- <match value="/bin/env luajit" type="string" offset="2:16"/>
+ <magic>
+ <match type="string" value="/bin/lua" offset="2:16"/>
+ <match type="string" value="/bin/luajit" offset="2:16"/>
+ <match type="string" value="/bin/env lua" offset="2:16"/>
+ <match type="string" value="/bin/env luajit" offset="2:16"/>
</magic>
<glob pattern="*.lua"/>
</mime-type>
<mime-type type="text/x-readme">
<comment>README document</comment>
- <comment xml:lang="ar">مستند README</comment>
- <comment xml:lang="ast">Documentu LLEIME</comment>
- <comment xml:lang="az">README sənədi</comment>
- <comment xml:lang="be@latin">Dakument README</comment>
- <comment xml:lang="bg">Документ — „Да се прочете“</comment>
- <comment xml:lang="ca">document README</comment>
- <comment xml:lang="cs">dokument README</comment>
- <comment xml:lang="cy">Dogfen README</comment>
- <comment xml:lang="da">README-dokument</comment>
- <comment xml:lang="de">README-Dokument</comment>
- <comment xml:lang="el">Έγγραφο README</comment>
- <comment xml:lang="en_GB">README document</comment>
- <comment xml:lang="eo">README-dokumento</comment>
- <comment xml:lang="es">documento README</comment>
- <comment xml:lang="eu">README dokumentua</comment>
- <comment xml:lang="fi">LUEMINUT-asiakirja</comment>
- <comment xml:lang="fo">README skjal</comment>
- <comment xml:lang="fr">document LISEZ-MOI</comment>
- <comment xml:lang="ga">cáipéis README</comment>
- <comment xml:lang="gl">documento README</comment>
- <comment xml:lang="he">מסמך README</comment>
- <comment xml:lang="hr">README dokument</comment>
- <comment xml:lang="hu">README-dokumentum</comment>
- <comment xml:lang="ia">Documento LEGE-ME</comment>
- <comment xml:lang="id">Dokumen README</comment>
- <comment xml:lang="it">Documento README</comment>
- <comment xml:lang="ja">README ドキュメント</comment>
- <comment xml:lang="kk">README құжаты</comment>
- <comment xml:lang="ko">README 문서</comment>
- <comment xml:lang="lt">README dokumentas</comment>
- <comment xml:lang="lv">README dokuments</comment>
- <comment xml:lang="ms">Dokumen README</comment>
- <comment xml:lang="nb">README-dokument</comment>
- <comment xml:lang="nl">LEESMIJ-document</comment>
- <comment xml:lang="nn">README-dokument</comment>
- <comment xml:lang="oc">document LISEZ-MOI</comment>
- <comment xml:lang="pl">Dokument README</comment>
- <comment xml:lang="pt">documento LEIA-ME</comment>
- <comment xml:lang="pt_BR">Documento README</comment>
- <comment xml:lang="ro">Document README</comment>
- <comment xml:lang="ru">Документ README</comment>
- <comment xml:lang="sk">Dokument README</comment>
- <comment xml:lang="sl">Dokument README</comment>
- <comment xml:lang="sq">Dokument README</comment>
- <comment xml:lang="sr">документ ПРОЧИТАЈМЕ</comment>
- <comment xml:lang="sv">README-dokument</comment>
- <comment xml:lang="tr">BENİOKU belgesi</comment>
- <comment xml:lang="uk">документ README</comment>
- <comment xml:lang="vi">Tài liệu Đọc Đi (README)</comment>
- <comment xml:lang="zh_CN">README 文档</comment>
<comment xml:lang="zh_TW">README 說明文件</comment>
+ <comment xml:lang="zh_CN">README 文档</comment>
+ <comment xml:lang="vi">Tài liệu Đọc Đi (README)</comment>
+ <comment xml:lang="uk">документ README</comment>
+ <comment xml:lang="tr">README belgesi</comment>
+ <comment xml:lang="sv">README-dokument</comment>
+ <comment xml:lang="sr">документ ПРОЧИТАЈМЕ</comment>
+ <comment xml:lang="sq">dokument README</comment>
+ <comment xml:lang="sl">Dokument README</comment>
+ <comment xml:lang="si">README ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument README</comment>
+ <comment xml:lang="ru">Документ README</comment>
+ <comment xml:lang="ro">Document README</comment>
+ <comment xml:lang="pt_BR">Documento README</comment>
+ <comment xml:lang="pt">documento LEIA-ME</comment>
+ <comment xml:lang="pl">Dokument README</comment>
+ <comment xml:lang="oc">document LISEZ-MOI</comment>
+ <comment xml:lang="nn">README-dokument</comment>
+ <comment xml:lang="nl">LEESMIJ-document</comment>
+ <comment xml:lang="nb">README-dokument</comment>
+ <comment xml:lang="ms">Dokumen README</comment>
+ <comment xml:lang="lv">README dokuments</comment>
+ <comment xml:lang="lt">README dokumentas</comment>
+ <comment xml:lang="ko">README 문서</comment>
+ <comment xml:lang="kk">README құжаты</comment>
+ <comment xml:lang="ja">README ドキュメント</comment>
+ <comment xml:lang="it">Documento README</comment>
+ <comment xml:lang="is">README skjal</comment>
+ <comment xml:lang="id">Dokumen README</comment>
+ <comment xml:lang="ia">Documento LEGE-ME</comment>
+ <comment xml:lang="hu">README-dokumentum</comment>
+ <comment xml:lang="hr">README dokument</comment>
+ <comment xml:lang="he">מסמך README</comment>
+ <comment xml:lang="gl">documento README</comment>
+ <comment xml:lang="ga">cáipéis README</comment>
+ <comment xml:lang="fur">document README</comment>
+ <comment xml:lang="fr">document LISEZ-MOI</comment>
+ <comment xml:lang="fo">README skjal</comment>
+ <comment xml:lang="fi">LUEMINUT-asiakirja</comment>
+ <comment xml:lang="eu">README dokumentua</comment>
+ <comment xml:lang="es">documento README</comment>
+ <comment xml:lang="eo">README-dokumento</comment>
+ <comment xml:lang="en_GB">README document</comment>
+ <comment xml:lang="el">Έγγραφο README</comment>
+ <comment xml:lang="de">README-Dokument</comment>
+ <comment xml:lang="da">README-dokument</comment>
+ <comment xml:lang="cy">Dogfen README</comment>
+ <comment xml:lang="cs">dokument README</comment>
+ <comment xml:lang="ca">document README</comment>
+ <comment xml:lang="bg">Документ — „Да се прочете“</comment>
+ <comment xml:lang="be@latin">Dakument README</comment>
+ <comment xml:lang="be">дакумент README</comment>
+ <comment xml:lang="az">README sənədi</comment>
+ <comment xml:lang="ast">Documentu LLEIME</comment>
+ <comment xml:lang="ar">مستند README</comment>
+ <comment xml:lang="af">README-dokument</comment>
<sub-class-of type="text/plain"/>
<glob weight="10" pattern="README*"/>
</mime-type>
<mime-type type="text/x-nfo">
<comment>NFO document</comment>
- <comment xml:lang="ar">مستند NFO</comment>
- <comment xml:lang="ast">Documentu NFO</comment>
- <comment xml:lang="be@latin">Dakument NFO</comment>
- <comment xml:lang="bg">Документ — NFO</comment>
- <comment xml:lang="ca">document NFO</comment>
- <comment xml:lang="cs">dokument NFO</comment>
- <comment xml:lang="da">NFO-dokument</comment>
- <comment xml:lang="de">NFO-Dokument</comment>
- <comment xml:lang="el">Έγγραφο NFO</comment>
- <comment xml:lang="en_GB">NFO document</comment>
- <comment xml:lang="eo">NFO-dokumento</comment>
- <comment xml:lang="es">documento NFO</comment>
- <comment xml:lang="eu">NFO dokumentua</comment>
- <comment xml:lang="fi">NFO-asiakirja</comment>
- <comment xml:lang="fo">NFO skjal</comment>
- <comment xml:lang="fr">document NFO</comment>
- <comment xml:lang="ga">cáipéis NFO</comment>
- <comment xml:lang="gl">documento NFO</comment>
- <comment xml:lang="he">מסמך NFO</comment>
- <comment xml:lang="hr">NFO dokument</comment>
- <comment xml:lang="hu">NFO-dokumentum</comment>
- <comment xml:lang="ia">Documento NFO</comment>
- <comment xml:lang="id">Dokumen NFO</comment>
- <comment xml:lang="it">Documento NFO</comment>
- <comment xml:lang="ja">NFO ドキュメント</comment>
- <comment xml:lang="kk">NFO құжаты</comment>
- <comment xml:lang="ko">NFO 문서</comment>
- <comment xml:lang="lt">NFO dokumentas</comment>
- <comment xml:lang="lv">NFO dokuments</comment>
- <comment xml:lang="nb">NFO-dokument</comment>
- <comment xml:lang="nl">NFO-document</comment>
- <comment xml:lang="nn">NFO-dokument</comment>
- <comment xml:lang="oc">document NFO</comment>
- <comment xml:lang="pl">Dokument NFO</comment>
- <comment xml:lang="pt">documento NFO</comment>
- <comment xml:lang="pt_BR">Documento NFO</comment>
- <comment xml:lang="ro">Document NFO</comment>
- <comment xml:lang="ru">Документ NFO</comment>
- <comment xml:lang="sk">Dokument NFO</comment>
- <comment xml:lang="sl">Dokument NFO</comment>
- <comment xml:lang="sq">Dokument NFO</comment>
- <comment xml:lang="sr">документ НФО</comment>
- <comment xml:lang="sv">NFO-dokument</comment>
- <comment xml:lang="tr">NFO belgesi</comment>
- <comment xml:lang="uk">документ NFO</comment>
- <comment xml:lang="vi">Tài liệu NFO</comment>
- <comment xml:lang="zh_CN">NFO 文档</comment>
<comment xml:lang="zh_TW">NFO 文件</comment>
+ <comment xml:lang="zh_CN">NFO 文档</comment>
+ <comment xml:lang="vi">Tài liệu NFO</comment>
+ <comment xml:lang="uk">документ NFO</comment>
+ <comment xml:lang="tr">NFO belgesi</comment>
+ <comment xml:lang="sv">NFO-dokument</comment>
+ <comment xml:lang="sr">документ НФО</comment>
+ <comment xml:lang="sq">dokument NFO</comment>
+ <comment xml:lang="sl">Dokument NFO</comment>
+ <comment xml:lang="si">NFO ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument NFO</comment>
+ <comment xml:lang="ru">Документ NFO</comment>
+ <comment xml:lang="ro">Document NFO</comment>
+ <comment xml:lang="pt_BR">Documento NFO</comment>
+ <comment xml:lang="pt">documento NFO</comment>
+ <comment xml:lang="pl">Dokument NFO</comment>
+ <comment xml:lang="oc">document NFO</comment>
+ <comment xml:lang="nn">NFO-dokument</comment>
+ <comment xml:lang="nl">NFO-document</comment>
+ <comment xml:lang="nb">NFO-dokument</comment>
+ <comment xml:lang="lv">NFO dokuments</comment>
+ <comment xml:lang="lt">NFO dokumentas</comment>
+ <comment xml:lang="ko">NFO 문서</comment>
+ <comment xml:lang="kk">NFO құжаты</comment>
+ <comment xml:lang="ja">NFO ドキュメント</comment>
+ <comment xml:lang="it">Documento NFO</comment>
+ <comment xml:lang="is">NFO skjal</comment>
+ <comment xml:lang="id">Dokumen NFO</comment>
+ <comment xml:lang="ia">Documento NFO</comment>
+ <comment xml:lang="hu">NFO-dokumentum</comment>
+ <comment xml:lang="hr">NFO dokument</comment>
+ <comment xml:lang="he">מסמך NFO</comment>
+ <comment xml:lang="gl">documento NFO</comment>
+ <comment xml:lang="ga">cáipéis NFO</comment>
+ <comment xml:lang="fur">document NFO</comment>
+ <comment xml:lang="fr">document NFO</comment>
+ <comment xml:lang="fo">NFO skjal</comment>
+ <comment xml:lang="fi">NFO-asiakirja</comment>
+ <comment xml:lang="eu">NFO dokumentua</comment>
+ <comment xml:lang="es">documento NFO</comment>
+ <comment xml:lang="eo">NFO-dokumento</comment>
+ <comment xml:lang="en_GB">NFO document</comment>
+ <comment xml:lang="el">Έγγραφο NFO</comment>
+ <comment xml:lang="de">NFO-Dokument</comment>
+ <comment xml:lang="da">NFO-dokument</comment>
+ <comment xml:lang="cs">dokument NFO</comment>
+ <comment xml:lang="ca">document NFO</comment>
+ <comment xml:lang="bg">Документ — NFO</comment>
+ <comment xml:lang="be@latin">Dakument NFO</comment>
+ <comment xml:lang="be">дакумент NFO</comment>
+ <comment xml:lang="ast">Documentu NFO</comment>
+ <comment xml:lang="ar">مستند NFO</comment>
+ <comment xml:lang="af">NFO-dokument</comment>
<sub-class-of type="text/x-readme"/>
<glob pattern="*.nfo"/>
</mime-type>
+ <mime-type type="text/x-todo-txt">
+ <comment>Todo.txt file</comment>
+ <comment xml:lang="uk">файл Todo.txt</comment>
+ <comment xml:lang="sv">Todo.txt-fil</comment>
+ <comment xml:lang="ru">Файл Todo.txt</comment>
+ <comment xml:lang="pl">Plik Todo.txt</comment>
+ <comment xml:lang="ja">TODO文書</comment>
+ <comment xml:lang="it">File todo.txt</comment>
+ <comment xml:lang="es">archivo Todo.txt</comment>
+ <comment xml:lang="de">Todo.txt-Datei</comment>
+ <sub-class-of type="text/plain"/>
+ <magic priority="10">
+ <match type="string" value="(A) " offset="0"/>
+ <match type="string" value="x " offset="0"/>
+ </magic>
+ <glob weight="10" pattern="todo.txt"/>
+ </mime-type>
<mime-type type="text/x-rpm-spec">
<comment>RPM spec file</comment>
- <comment xml:lang="ar">ملف مواصفات RPM</comment>
- <comment xml:lang="be@latin">Specyfikacyjny fajł RPM</comment>
- <comment xml:lang="bg">Файл — спецификация за RPM</comment>
- <comment xml:lang="ca">fitxer spec RPM</comment>
- <comment xml:lang="cs">soubor specifikace RPM</comment>
- <comment xml:lang="da">RPM spec-fil</comment>
- <comment xml:lang="de">RPM-Spezifikationsdatei</comment>
- <comment xml:lang="el">Αρχείο spec RPM</comment>
- <comment xml:lang="en_GB">RPM spec file</comment>
- <comment xml:lang="es">archivo de especificaciones RPM</comment>
- <comment xml:lang="eu">RPM espezifikazio fitxategia</comment>
- <comment xml:lang="fi">RPM spec -tiedosto</comment>
- <comment xml:lang="fo">RPM tøknilýsingarfíla</comment>
- <comment xml:lang="fr">fichier de spécification RPM</comment>
- <comment xml:lang="ga">comhad spec RPM</comment>
- <comment xml:lang="gl">ficheiro de especificacións RPM</comment>
- <comment xml:lang="he">קובץ מפרט RPM</comment>
- <comment xml:lang="hr">RPM određena datoteka</comment>
- <comment xml:lang="hu">RPM spec fájl</comment>
- <comment xml:lang="ia">File de specification RPM</comment>
- <comment xml:lang="id">Berkas spesifikasi RPM</comment>
- <comment xml:lang="it">File specifica RPM</comment>
- <comment xml:lang="ja">RPM spec ファイル</comment>
- <comment xml:lang="kk">RPM анықтама файлы</comment>
- <comment xml:lang="ko">RPM spec 파일</comment>
- <comment xml:lang="lt">RPM spec failas</comment>
- <comment xml:lang="lv">RPM specifikācijas datne</comment>
- <comment xml:lang="nb">RPM-spesifikasjonsfil</comment>
- <comment xml:lang="nl">RPM-spec-bestand</comment>
- <comment xml:lang="nn">RPM spec-fil</comment>
- <comment xml:lang="oc">fichièr d'especificacion RPM</comment>
- <comment xml:lang="pl">Plik spec RPM</comment>
- <comment xml:lang="pt">ficheiro de especificações RPM</comment>
- <comment xml:lang="pt_BR">Arquivo de especificação RPM</comment>
- <comment xml:lang="ro">Fișier RPM spec</comment>
- <comment xml:lang="ru">Файл описания RPM</comment>
- <comment xml:lang="sk">Súbor RPM spec</comment>
- <comment xml:lang="sl">Določilna datoteka RPM</comment>
- <comment xml:lang="sq">File specifikimi RPM</comment>
- <comment xml:lang="sr">РПМ посебна датотека</comment>
- <comment xml:lang="sv">RPM spec-fil</comment>
- <comment xml:lang="tr">RPM spec dosyası</comment>
- <comment xml:lang="uk">spec-файл RPM</comment>
- <comment xml:lang="vi">Tập tin đặc tả RPM</comment>
- <comment xml:lang="zh_CN">RPM spec 文件</comment>
<comment xml:lang="zh_TW">RPM spec 規格檔</comment>
+ <comment xml:lang="zh_CN">RPM spec 文件</comment>
+ <comment xml:lang="vi">Tập tin đặc tả RPM</comment>
+ <comment xml:lang="uk">spec-файл RPM</comment>
+ <comment xml:lang="tr">RPM spec dosyası</comment>
+ <comment xml:lang="sv">RPM spec-fil</comment>
+ <comment xml:lang="sr">РПМ посебна датотека</comment>
+ <comment xml:lang="sq">kartelë specifikimesh RPM</comment>
+ <comment xml:lang="sl">Določilna datoteka RPM</comment>
+ <comment xml:lang="si">RPM පිරිවිතර ගොනුව</comment>
+ <comment xml:lang="sk">Súbor RPM spec</comment>
+ <comment xml:lang="ru">Файл описания RPM</comment>
+ <comment xml:lang="ro">Fișier RPM spec</comment>
+ <comment xml:lang="pt_BR">Arquivo de especificação RPM</comment>
+ <comment xml:lang="pt">ficheiro de especificações RPM</comment>
+ <comment xml:lang="pl">Plik spec RPM</comment>
+ <comment xml:lang="oc">fichièr d'especificacion RPM</comment>
+ <comment xml:lang="nn">RPM spec-fil</comment>
+ <comment xml:lang="nl">RPM-spec-bestand</comment>
+ <comment xml:lang="nb">RPM-spesifikasjonsfil</comment>
+ <comment xml:lang="lv">RPM specifikācijas datne</comment>
+ <comment xml:lang="lt">RPM spec failas</comment>
+ <comment xml:lang="ko">RPM spec 파일</comment>
+ <comment xml:lang="kk">RPM анықтама файлы</comment>
+ <comment xml:lang="ja">RPM spec ファイル</comment>
+ <comment xml:lang="it">File specifica RPM</comment>
+ <comment xml:lang="is">RPM spec-skrá</comment>
+ <comment xml:lang="id">Berkas spesifikasi RPM</comment>
+ <comment xml:lang="ia">File de specification RPM</comment>
+ <comment xml:lang="hu">RPM spec fájl</comment>
+ <comment xml:lang="hr">RPM određena datoteka</comment>
+ <comment xml:lang="he">קובץ מפרט RPM</comment>
+ <comment xml:lang="gl">ficheiro de especificacións RPM</comment>
+ <comment xml:lang="ga">comhad spec RPM</comment>
+ <comment xml:lang="fur">file di specifiche RPM</comment>
+ <comment xml:lang="fr">fichier de spécification RPM</comment>
+ <comment xml:lang="fo">RPM tøknilýsingarfíla</comment>
+ <comment xml:lang="fi">RPM spec -tiedosto</comment>
+ <comment xml:lang="eu">RPM espezifikazio fitxategia</comment>
+ <comment xml:lang="es">archivo de especificaciones RPM</comment>
+ <comment xml:lang="en_GB">RPM spec file</comment>
+ <comment xml:lang="el">Αρχείο spec RPM</comment>
+ <comment xml:lang="de">RPM-Spezifikationsdatei</comment>
+ <comment xml:lang="da">RPM spec-fil</comment>
+ <comment xml:lang="cs">soubor specifikace RPM</comment>
+ <comment xml:lang="ca">fitxer spec RPM</comment>
+ <comment xml:lang="bg">Файл — спецификация за RPM</comment>
+ <comment xml:lang="be@latin">Specyfikacyjny fajł RPM</comment>
+ <comment xml:lang="be">файл спецыфікацыі RPM</comment>
+ <comment xml:lang="ar">ملف مواصفات RPM</comment>
+ <comment xml:lang="af">RPM-spesifikasielêer</comment>
<acronym>RPM</acronym>
<expanded-acronym>Red Hat Package Manager</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.spec"/>
- <magic priority="50">
- <match value="Summary: " type="string" offset="0"/>
- <match value="%define " type="string" offset="0"/>
+ <magic>
+ <match type="string" value="Summary: " offset="0"/>
+ <match type="string" value="%define " offset="0"/>
</magic>
</mime-type>
<mime-type type="text/x-sass">
<comment>Sass CSS pre-processor file</comment>
- <comment xml:lang="ca">fitxer preprocessador CSS Sass</comment>
- <comment xml:lang="cs">soubor preprocesoru Sass CSS</comment>
- <comment xml:lang="da">Sass CSS-forbrænderfil</comment>
- <comment xml:lang="de">Sass-CSS-Präprozessordatei</comment>
- <comment xml:lang="en_GB">Sass CSS pre-processor file</comment>
- <comment xml:lang="es">archivo de preprocesador de CSS Sass</comment>
- <comment xml:lang="fr">fichier de prétraitement CSS Sass</comment>
- <comment xml:lang="ga">comhad réamhphróiseálaí CSS Sass</comment>
- <comment xml:lang="he">קובץ קדם עיבוד Sass CSS</comment>
- <comment xml:lang="hr">Sass CSS datoteka predobrade</comment>
- <comment xml:lang="hu">Sass CSS előfeldolgozó fájl</comment>
- <comment xml:lang="id">berkas pre-processor Sass CSS</comment>
- <comment xml:lang="it">File CSS Sass</comment>
- <comment xml:lang="kk">Sass CSS препроцессор файлы</comment>
- <comment xml:lang="ko">Sass CSS 전처리기 파일</comment>
- <comment xml:lang="pl">Plik preprocesora CSS Sass</comment>
- <comment xml:lang="pt_BR">Arquivo de pré-processamento Sass CSS</comment>
- <comment xml:lang="ru">Файл препроцессора Sass CSS</comment>
- <comment xml:lang="sk">Súbor Sass CSS pre-procesora</comment>
- <comment xml:lang="sr">датотека Сас ЦСС пре-процесора</comment>
- <comment xml:lang="sv">Sass CSS-preprocessorfil</comment>
- <comment xml:lang="tr">Sass CSS önişlemci dosyası</comment>
- <comment xml:lang="uk">файл препроцесора CSS Sass</comment>
- <comment xml:lang="zh_CN">Sass CSS 预处理器文件</comment>
<comment xml:lang="zh_TW">Sass CSS 處理器前檔案</comment>
+ <comment xml:lang="zh_CN">Sass CSS 预处理器文件</comment>
+ <comment xml:lang="uk">файл препроцесора CSS Sass</comment>
+ <comment xml:lang="tr">Sass CSS önişlemci dosyası</comment>
+ <comment xml:lang="sv">Sass CSS-preprocessorfil</comment>
+ <comment xml:lang="sr">датотека Сас ЦСС пре-процесора</comment>
+ <comment xml:lang="sq">kartelë pre-procesori CSS Sass</comment>
+ <comment xml:lang="si">Sass CSS පෙර-ප්‍රොසෙසර ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Sass CSS pre-procesora</comment>
+ <comment xml:lang="ru">Файл препроцессора Sass CSS</comment>
+ <comment xml:lang="pt_BR">Arquivo de pré-processamento Sass CSS</comment>
+ <comment xml:lang="pl">Plik preprocesora CSS Sass</comment>
+ <comment xml:lang="nl">SaSS CSS-voorverwerkersbestand</comment>
+ <comment xml:lang="ko">Sass CSS 전처리기 파일</comment>
+ <comment xml:lang="kk">Sass CSS препроцессор файлы</comment>
+ <comment xml:lang="ja">Sass CSS プリプロセッサファイル</comment>
+ <comment xml:lang="it">File CSS Sass</comment>
+ <comment xml:lang="is">Sass CSS pre-processor skrá</comment>
+ <comment xml:lang="id">Berkas pre-processor Sass CSS</comment>
+ <comment xml:lang="hu">Sass CSS előfeldolgozó fájl</comment>
+ <comment xml:lang="hr">Sass CSS datoteka predobrade</comment>
+ <comment xml:lang="he">קובץ קדם עיבוד Sass CSS</comment>
+ <comment xml:lang="ga">comhad réamhphróiseálaí CSS Sass</comment>
+ <comment xml:lang="fur">file di pre-elaborazion di CSS Sass</comment>
+ <comment xml:lang="fr">fichier de prétraitement CSS Sass</comment>
+ <comment xml:lang="fi">Sass CSS esikäsittelijä -tiedosto</comment>
+ <comment xml:lang="eu">Sass CSS fitxategi prozesatu gabea</comment>
+ <comment xml:lang="es">archivo de preprocesador de CSS Sass</comment>
+ <comment xml:lang="en_GB">Sass CSS pre-processor file</comment>
+ <comment xml:lang="de">Sass-CSS-Präprozessordatei</comment>
+ <comment xml:lang="da">Sass CSS pre-processor-fil</comment>
+ <comment xml:lang="cs">soubor preprocesoru Sass CSS</comment>
+ <comment xml:lang="ca">fitxer preprocessador CSS Sass</comment>
+ <comment xml:lang="bg">Директиви за препроцесора — Sass CSS</comment>
+ <comment xml:lang="be">файл прэпрацэсара Sass CSS</comment>
+ <comment xml:lang="ar">ملف Sass CSS قبل المعالج</comment>
+ <comment xml:lang="af">Sass CSS-voorverwerkerlêer</comment>
+ <acronym>Sass</acronym>
+ <expanded-acronym>Syntactically Awesome Style Sheets</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.sass"/>
<generic-icon name="text-x-generic"/>
</mime-type>
<mime-type type="text/x-scala">
<comment>Scala source code</comment>
- <comment xml:lang="bg">Изходен код — Scala</comment>
- <comment xml:lang="ca">codi font en Scala</comment>
- <comment xml:lang="cs">zdrojový kód Scala</comment>
- <comment xml:lang="da">Scala-kildekode</comment>
- <comment xml:lang="de">Scala-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Scala</comment>
- <comment xml:lang="en_GB">Scala source code</comment>
- <comment xml:lang="es">código fuente en Scala</comment>
- <comment xml:lang="eu">Scala iturburu-kodea</comment>
- <comment xml:lang="fi">Scala-lähdekoodi</comment>
- <comment xml:lang="fr">code source Scala</comment>
- <comment xml:lang="ga">cód foinseach Scala</comment>
- <comment xml:lang="gl">código fnote en Scala</comment>
- <comment xml:lang="he">קוד מקור של Scala</comment>
- <comment xml:lang="hr">Scala izvorni kôd</comment>
- <comment xml:lang="hu">Scala forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Scala</comment>
- <comment xml:lang="id">Kode sumber Scala</comment>
- <comment xml:lang="it">Codice sorgente Scala</comment>
- <comment xml:lang="ja">Scala ソースコード</comment>
- <comment xml:lang="ka">Scala-ის საწყისი კოდი</comment>
- <comment xml:lang="kk">Scala бастапқы коды</comment>
- <comment xml:lang="ko">Scala 소스 코드</comment>
- <comment xml:lang="lv">Scala pirmkods</comment>
- <comment xml:lang="nl">Scala broncode</comment>
- <comment xml:lang="oc">còde font Scala</comment>
- <comment xml:lang="pl">Kod źródłowy Scala</comment>
- <comment xml:lang="pt">código origem Scala</comment>
- <comment xml:lang="pt_BR">Código-fonte Scala</comment>
- <comment xml:lang="ru">Исходный код Scala</comment>
- <comment xml:lang="sk">Zdrojový kód Scala</comment>
- <comment xml:lang="sl">Izvorna koda Scala</comment>
- <comment xml:lang="sr">Скала изворни ко̂д</comment>
- <comment xml:lang="sv">Scala-källkod</comment>
- <comment xml:lang="tr">Scala kaynak kodu</comment>
- <comment xml:lang="uk">вихідний код мовою Scala</comment>
- <comment xml:lang="zh_CN">Scala 源代码</comment>
<comment xml:lang="zh_TW">Scala 源碼</comment>
+ <comment xml:lang="zh_CN">Scala 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Scala</comment>
+ <comment xml:lang="tr">Scala kaynak kodu</comment>
+ <comment xml:lang="sv">Scala-källkod</comment>
+ <comment xml:lang="sr">Скала изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Scala</comment>
+ <comment xml:lang="sl">Izvorna koda Scala</comment>
+ <comment xml:lang="si">Scala මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Scala</comment>
+ <comment xml:lang="ru">Исходный код Scala</comment>
+ <comment xml:lang="pt_BR">Código-fonte Scala</comment>
+ <comment xml:lang="pt">código origem Scala</comment>
+ <comment xml:lang="pl">Kod źródłowy Scala</comment>
+ <comment xml:lang="oc">còde font Scala</comment>
+ <comment xml:lang="nl">Scala broncode</comment>
+ <comment xml:lang="lv">Scala pirmkods</comment>
+ <comment xml:lang="ko">Scala 소스 코드</comment>
+ <comment xml:lang="kk">Scala бастапқы коды</comment>
+ <comment xml:lang="ka">Scala-ის საწყისი კოდი</comment>
+ <comment xml:lang="ja">Scala ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Scala</comment>
+ <comment xml:lang="is">Scala frumkóði</comment>
+ <comment xml:lang="id">Kode sumber Scala</comment>
+ <comment xml:lang="ia">Codice-fonte Scala</comment>
+ <comment xml:lang="hu">Scala forráskód</comment>
+ <comment xml:lang="hr">Scala izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Scala</comment>
+ <comment xml:lang="gl">código fnote en Scala</comment>
+ <comment xml:lang="ga">cód foinseach Scala</comment>
+ <comment xml:lang="fur">codiç sorzint Scala</comment>
+ <comment xml:lang="fr">code source Scala</comment>
+ <comment xml:lang="fi">Scala-lähdekoodi</comment>
+ <comment xml:lang="eu">Scala iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Scala</comment>
+ <comment xml:lang="en_GB">Scala source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Scala</comment>
+ <comment xml:lang="de">Scala-Quelltext</comment>
+ <comment xml:lang="da">Scala-kildekode</comment>
+ <comment xml:lang="cs">zdrojový kód Scala</comment>
+ <comment xml:lang="ca">codi font en Scala</comment>
+ <comment xml:lang="bg">Изходен код — Scala</comment>
+ <comment xml:lang="be">зыходны код Scala</comment>
+ <comment xml:lang="ar">شفرة مصدر Scala</comment>
+ <comment xml:lang="af">Scala-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.scala"/>
+ <glob pattern="*.sc"/>
</mime-type>
<mime-type type="text/x-scheme">
<comment>Scheme source code</comment>
- <comment xml:lang="ar">شفرة مصدر Scheme</comment>
- <comment xml:lang="az">Sxem mənbə kodu</comment>
- <comment xml:lang="be@latin">Kryničny kod Scheme</comment>
- <comment xml:lang="bg">Изходен код — Scheme</comment>
- <comment xml:lang="ca">codi font en Scheme</comment>
- <comment xml:lang="cs">zdrojový kód Scheme</comment>
- <comment xml:lang="cy">Ffynhonnell Rhaglen Scheme</comment>
- <comment xml:lang="da">Schemekildekode</comment>
- <comment xml:lang="de">Scheme-Quelltext</comment>
- <comment xml:lang="el">Πηγαίος κώδικας Scheme</comment>
- <comment xml:lang="en_GB">Scheme source code</comment>
- <comment xml:lang="eo">Scheme-fontkodo</comment>
- <comment xml:lang="es">código fuente en Scheme</comment>
- <comment xml:lang="eu">Scheme iturburu-kodea</comment>
- <comment xml:lang="fi">Scheme-lähdekoodi</comment>
- <comment xml:lang="fo">Scheme keldukota</comment>
- <comment xml:lang="fr">code source Scheme</comment>
- <comment xml:lang="ga">cód foinseach Scheme</comment>
- <comment xml:lang="gl">código fonte en Scheme</comment>
- <comment xml:lang="he">קוד מקור של Scheme</comment>
- <comment xml:lang="hr">Scheme izvorni kôd</comment>
- <comment xml:lang="hu">Scheme-forráskód</comment>
- <comment xml:lang="ia">Codice-fonte Scheme</comment>
- <comment xml:lang="id">Kode program Scheme</comment>
- <comment xml:lang="it">Codice sorgente Scheme</comment>
- <comment xml:lang="ja">Scheme ソースコード</comment>
- <comment xml:lang="kk">Scheme бастапқы коды</comment>
- <comment xml:lang="ko">Scheme 소스 코드</comment>
- <comment xml:lang="lt">Scheme pradinis kodas</comment>
- <comment xml:lang="lv">Scheme pirmkods</comment>
- <comment xml:lang="ms">Kod sumber Scheme</comment>
- <comment xml:lang="nb">Scheme-kildekode</comment>
- <comment xml:lang="nl">Scheme-broncode</comment>
- <comment xml:lang="nn">Scheme-kjeldekode</comment>
- <comment xml:lang="oc">còde font Scheme</comment>
- <comment xml:lang="pl">Kod źródłowy Scheme</comment>
- <comment xml:lang="pt">código origem Scheme</comment>
- <comment xml:lang="pt_BR">Código-fonte Scheme</comment>
- <comment xml:lang="ro">Cod sursă Scheme</comment>
- <comment xml:lang="ru">Исходный код Scheme</comment>
- <comment xml:lang="sk">Zdrojový kód Scheme</comment>
- <comment xml:lang="sl">Datoteka izvorne kode Scheme</comment>
- <comment xml:lang="sq">Kod burues Scheme</comment>
- <comment xml:lang="sr">Шемски изворни ко̂д</comment>
- <comment xml:lang="sv">Scheme-källkod</comment>
- <comment xml:lang="tr">Scheme kaynak kodu</comment>
- <comment xml:lang="uk">вихідний файл мовою Scheme</comment>
- <comment xml:lang="vi">Mã nguồn Scheme</comment>
- <comment xml:lang="zh_CN">Scheme 源代码</comment>
<comment xml:lang="zh_TW">Scheme 源碼</comment>
+ <comment xml:lang="zh_CN">Scheme 源代码</comment>
+ <comment xml:lang="vi">Mã nguồn Scheme</comment>
+ <comment xml:lang="uk">початковий код мовою Scheme</comment>
+ <comment xml:lang="tr">Scheme kaynak kodu</comment>
+ <comment xml:lang="sv">Scheme-källkod</comment>
+ <comment xml:lang="sr">Шемски изворни ко̂д</comment>
+ <comment xml:lang="sq">kod burim Scheme</comment>
+ <comment xml:lang="sl">Datoteka izvorne kode Scheme</comment>
+ <comment xml:lang="si">යෝජනා ක්‍රම මූල කේතය</comment>
+ <comment xml:lang="sk">Zdrojový kód Scheme</comment>
+ <comment xml:lang="ru">Исходный код Scheme</comment>
+ <comment xml:lang="ro">Cod sursă Scheme</comment>
+ <comment xml:lang="pt_BR">Código-fonte Scheme</comment>
+ <comment xml:lang="pt">código origem Scheme</comment>
+ <comment xml:lang="pl">Kod źródłowy Scheme</comment>
+ <comment xml:lang="oc">còde font Scheme</comment>
+ <comment xml:lang="nn">Scheme-kjeldekode</comment>
+ <comment xml:lang="nl">Scheme-broncode</comment>
+ <comment xml:lang="nb">Scheme-kildekode</comment>
+ <comment xml:lang="ms">Kod sumber Scheme</comment>
+ <comment xml:lang="lv">Scheme pirmkods</comment>
+ <comment xml:lang="lt">Scheme pradinis kodas</comment>
+ <comment xml:lang="ko">Scheme 소스 코드</comment>
+ <comment xml:lang="kk">Scheme бастапқы коды</comment>
+ <comment xml:lang="ja">Scheme ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Scheme</comment>
+ <comment xml:lang="is">Scheme frumkóði</comment>
+ <comment xml:lang="id">Kode program Scheme</comment>
+ <comment xml:lang="ia">Codice-fonte Scheme</comment>
+ <comment xml:lang="hu">Scheme-forráskód</comment>
+ <comment xml:lang="hr">Scheme izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Scheme</comment>
+ <comment xml:lang="gl">código fonte en Scheme</comment>
+ <comment xml:lang="ga">cód foinseach Scheme</comment>
+ <comment xml:lang="fur">codiç sorzint Scheme</comment>
+ <comment xml:lang="fr">code source Scheme</comment>
+ <comment xml:lang="fo">Scheme keldukota</comment>
+ <comment xml:lang="fi">Scheme-lähdekoodi</comment>
+ <comment xml:lang="eu">Scheme iturburu-kodea</comment>
+ <comment xml:lang="es">código fuente en Scheme</comment>
+ <comment xml:lang="eo">Scheme-fontkodo</comment>
+ <comment xml:lang="en_GB">Scheme source code</comment>
+ <comment xml:lang="el">Πηγαίος κώδικας Scheme</comment>
+ <comment xml:lang="de">Scheme-Quelltext</comment>
+ <comment xml:lang="da">Scheme-kildekode</comment>
+ <comment xml:lang="cy">Ffynhonnell Rhaglen Scheme</comment>
+ <comment xml:lang="cs">zdrojový kód Scheme</comment>
+ <comment xml:lang="ca">codi font en Scheme</comment>
+ <comment xml:lang="bg">Изходен код — Scheme</comment>
+ <comment xml:lang="be@latin">Kryničny kod Scheme</comment>
+ <comment xml:lang="be">зыходны код Scheme</comment>
+ <comment xml:lang="az">Sxem mənbə kodu</comment>
+ <comment xml:lang="ar">شفرة مصدر Scheme</comment>
+ <comment xml:lang="af">Scheme-bronkode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.scm"/>
<glob pattern="*.ss"/>
</mime-type>
<mime-type type="text/x-scss">
- <comment>Sass CSS pre-processor file</comment>
- <comment xml:lang="ca">fitxer preprocessador CSS Sass</comment>
- <comment xml:lang="cs">soubor preprocesoru Sass CSS</comment>
- <comment xml:lang="da">Sass CSS-forbrænderfil</comment>
- <comment xml:lang="de">Sass-CSS-Präprozessordatei</comment>
- <comment xml:lang="en_GB">Sass CSS pre-processor file</comment>
- <comment xml:lang="es">archivo de preprocesador de CSS Sass</comment>
- <comment xml:lang="fr">fichier de prétraitement CSS Sass</comment>
- <comment xml:lang="ga">comhad réamhphróiseálaí CSS Sass</comment>
- <comment xml:lang="he">קובץ קדם עיבוד Sass CSS</comment>
- <comment xml:lang="hr">Sass CSS datoteka predobrade</comment>
- <comment xml:lang="hu">Sass CSS előfeldolgozó fájl</comment>
- <comment xml:lang="id">berkas pre-processor Sass CSS</comment>
- <comment xml:lang="it">File CSS Sass</comment>
- <comment xml:lang="kk">Sass CSS препроцессор файлы</comment>
- <comment xml:lang="ko">Sass CSS 전처리기 파일</comment>
- <comment xml:lang="pl">Plik preprocesora CSS Sass</comment>
- <comment xml:lang="pt_BR">Arquivo de pré-processamento Sass CSS</comment>
- <comment xml:lang="ru">Файл препроцессора Sass CSS</comment>
- <comment xml:lang="sk">Súbor Sass CSS pre-procesora</comment>
- <comment xml:lang="sr">датотека Сас ЦСС пре-процесора</comment>
- <comment xml:lang="sv">Sass CSS-preprocessorfil</comment>
- <comment xml:lang="tr">Sass CSS önişlemci dosyası</comment>
- <comment xml:lang="uk">файл препроцесора CSS Sass</comment>
- <comment xml:lang="zh_CN">Sass CSS 预处理器文件</comment>
- <comment xml:lang="zh_TW">Sass CSS 處理器前檔案</comment>
+ <comment>SCSS pre-processor file</comment>
+ <comment xml:lang="zh_TW">SCSS 前處理器檔</comment>
+ <comment xml:lang="zh_CN">SCSS 预处理文件</comment>
+ <comment xml:lang="uk">файл засобу попередньої обробки SCSS</comment>
+ <comment xml:lang="tr">SCSS ön işleyici dosyası</comment>
+ <comment xml:lang="sv">SCSS förprocessorfil</comment>
+ <comment xml:lang="sq">kartelë pre-procesori SCSS</comment>
+ <comment xml:lang="si">SCSS පෙර සැකසුම් ගොනුව</comment>
+ <comment xml:lang="ru">Файл препроцессора SCSS</comment>
+ <comment xml:lang="pt_BR">Arquivo de pré-processamento SCSS</comment>
+ <comment xml:lang="pl">Plik preprocesora SCSS</comment>
+ <comment xml:lang="nl">SCSS-voorverwerkersbestand</comment>
+ <comment xml:lang="ko">SCSS 전처리 파일</comment>
+ <comment xml:lang="kk">SCSS препроцессор файлы</comment>
+ <comment xml:lang="ja">SCSS プリプロセッサファイル</comment>
+ <comment xml:lang="it">File SCSS</comment>
+ <comment xml:lang="is">SCSS pre-processor skrá</comment>
+ <comment xml:lang="id">Berkas preprosesor SCSS</comment>
+ <comment xml:lang="hu">SCSS előfeldolgozófájl</comment>
+ <comment xml:lang="hr">SCSS datoteka predobrade</comment>
+ <comment xml:lang="he">קובץ עיבוד קדם SCSS</comment>
+ <comment xml:lang="fr">fichier de prétraitement SCSS</comment>
+ <comment xml:lang="fi">SCSS esikäsittelijä -tiedosto</comment>
+ <comment xml:lang="eu">SCSS fitxategi prozesatu gabea</comment>
+ <comment xml:lang="es">archivo de preprocesador SCSS</comment>
+ <comment xml:lang="en_GB">SCSS pre-processor file</comment>
+ <comment xml:lang="de">SCSS-Präprozessordatei</comment>
+ <comment xml:lang="da">SCSS pre-processor-fil</comment>
+ <comment xml:lang="ca">fitxer preprocessador SCSS</comment>
+ <comment xml:lang="bg">Директиви за препроцесора — SCSS</comment>
+ <comment xml:lang="be">файл прэпрацэсара SCSS</comment>
+ <comment xml:lang="ar">ملف SCSS قبل المعالج</comment>
+ <acronym>SCSS</acronym>
+ <expanded-acronym>Sassy CSS</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.scss"/>
<generic-icon name="text-x-generic"/>
</mime-type>
<mime-type type="text/x-setext">
<comment>Setext document</comment>
- <comment xml:lang="ar">مستند Setext</comment>
- <comment xml:lang="ast">Documentu Setext</comment>
- <comment xml:lang="az">Setext sənədi</comment>
- <comment xml:lang="be@latin">Dakument Setext</comment>
- <comment xml:lang="bg">Документ — Setext</comment>
- <comment xml:lang="ca">document Setext</comment>
- <comment xml:lang="cs">dokument Setext</comment>
- <comment xml:lang="cy">Dogfen Setext</comment>
- <comment xml:lang="da">Setextdokument</comment>
- <comment xml:lang="de">Setext-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Setext</comment>
- <comment xml:lang="en_GB">Setext document</comment>
- <comment xml:lang="eo">Setext-dokumento</comment>
- <comment xml:lang="es">documento Setext</comment>
- <comment xml:lang="eu">Setext dokumentua</comment>
- <comment xml:lang="fi">Setext-asiakirja</comment>
- <comment xml:lang="fo">Setext skjal</comment>
- <comment xml:lang="fr">document Setext</comment>
- <comment xml:lang="ga">cáipéis Setext</comment>
- <comment xml:lang="gl">documento Settext</comment>
- <comment xml:lang="he">מסמך של Setext</comment>
- <comment xml:lang="hr">Setext dokument</comment>
- <comment xml:lang="hu">Setext-dokumentum</comment>
- <comment xml:lang="ia">Documento Setext</comment>
- <comment xml:lang="id">Dokumen Setext</comment>
- <comment xml:lang="it">Documento Setext</comment>
- <comment xml:lang="ja">Setext ドキュメント</comment>
- <comment xml:lang="kk">Setext құжаты</comment>
- <comment xml:lang="ko">Setext 문서</comment>
- <comment xml:lang="lt">Setext dokumentas</comment>
- <comment xml:lang="lv">Setext dokuments</comment>
- <comment xml:lang="ms">Dokumen Setext</comment>
- <comment xml:lang="nb">Setext-dokument</comment>
- <comment xml:lang="nl">Setext-document</comment>
- <comment xml:lang="nn">Setext-dokument</comment>
- <comment xml:lang="oc">document Setext</comment>
- <comment xml:lang="pl">Dokument Setext</comment>
- <comment xml:lang="pt">documento Setext</comment>
- <comment xml:lang="pt_BR">Documento Setext</comment>
- <comment xml:lang="ro">Document Setext</comment>
- <comment xml:lang="ru">Документ Setext</comment>
- <comment xml:lang="sk">Dokument Setext</comment>
- <comment xml:lang="sl">Dokument Setext</comment>
- <comment xml:lang="sq">Dokument Setext</comment>
- <comment xml:lang="sr">Сетекст документ</comment>
- <comment xml:lang="sv">Setext-dokument</comment>
- <comment xml:lang="tr">Setext belgesi</comment>
- <comment xml:lang="uk">документ Setext</comment>
- <comment xml:lang="vi">Tài liệu Setext</comment>
- <comment xml:lang="zh_CN">Setext 文档</comment>
<comment xml:lang="zh_TW">Setext 文件</comment>
+ <comment xml:lang="zh_CN">Setext 文档</comment>
+ <comment xml:lang="vi">Tài liệu Setext</comment>
+ <comment xml:lang="uk">документ Setext</comment>
+ <comment xml:lang="tr">Setext belgesi</comment>
+ <comment xml:lang="sv">Setext-dokument</comment>
+ <comment xml:lang="sr">Сетекст документ</comment>
+ <comment xml:lang="sq">dokument Setext</comment>
+ <comment xml:lang="sl">Dokument Setext</comment>
+ <comment xml:lang="si">පෙළ ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Setext</comment>
+ <comment xml:lang="ru">Документ Setext</comment>
+ <comment xml:lang="ro">Document Setext</comment>
+ <comment xml:lang="pt_BR">Documento Setext</comment>
+ <comment xml:lang="pt">documento Setext</comment>
+ <comment xml:lang="pl">Dokument Setext</comment>
+ <comment xml:lang="oc">document Setext</comment>
+ <comment xml:lang="nn">Setext-dokument</comment>
+ <comment xml:lang="nl">Setext-document</comment>
+ <comment xml:lang="nb">Setext-dokument</comment>
+ <comment xml:lang="ms">Dokumen Setext</comment>
+ <comment xml:lang="lv">Setext dokuments</comment>
+ <comment xml:lang="lt">Setext dokumentas</comment>
+ <comment xml:lang="ko">Setext 문서</comment>
+ <comment xml:lang="kk">Setext құжаты</comment>
+ <comment xml:lang="ja">Setext ドキュメント</comment>
+ <comment xml:lang="it">Documento Setext</comment>
+ <comment xml:lang="is">Setext skjal</comment>
+ <comment xml:lang="id">Dokumen Setext</comment>
+ <comment xml:lang="ia">Documento Setext</comment>
+ <comment xml:lang="hu">Setext-dokumentum</comment>
+ <comment xml:lang="hr">Setext dokument</comment>
+ <comment xml:lang="he">מסמך של Setext</comment>
+ <comment xml:lang="gl">documento Settext</comment>
+ <comment xml:lang="ga">cáipéis Setext</comment>
+ <comment xml:lang="fur">document Setext</comment>
+ <comment xml:lang="fr">document Setext</comment>
+ <comment xml:lang="fo">Setext skjal</comment>
+ <comment xml:lang="fi">Setext-asiakirja</comment>
+ <comment xml:lang="eu">Setext dokumentua</comment>
+ <comment xml:lang="es">documento Setext</comment>
+ <comment xml:lang="eo">Setext-dokumento</comment>
+ <comment xml:lang="en_GB">Setext document</comment>
+ <comment xml:lang="el">Έγγραφο Setext</comment>
+ <comment xml:lang="de">Setext-Dokument</comment>
+ <comment xml:lang="da">Setextdokument</comment>
+ <comment xml:lang="cy">Dogfen Setext</comment>
+ <comment xml:lang="cs">dokument Setext</comment>
+ <comment xml:lang="ca">document Setext</comment>
+ <comment xml:lang="bg">Документ — Setext</comment>
+ <comment xml:lang="be@latin">Dakument Setext</comment>
+ <comment xml:lang="be">дакумент Setext</comment>
+ <comment xml:lang="az">Setext sənədi</comment>
+ <comment xml:lang="ast">Documentu Setext</comment>
+ <comment xml:lang="ar">مستند Setext</comment>
+ <comment xml:lang="af">Setext-dokument</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.etx"/>
</mime-type>
<mime-type type="application/sql">
<comment>SQL code</comment>
- <comment xml:lang="ar">شفرة SQL</comment>
- <comment xml:lang="az">SQL kodu</comment>
- <comment xml:lang="be@latin">Kod SQL</comment>
- <comment xml:lang="bg">Код — SQL</comment>
- <comment xml:lang="ca">codi en SQL</comment>
- <comment xml:lang="cs">kód SQL</comment>
- <comment xml:lang="cy">Côd SQL</comment>
- <comment xml:lang="da">SQL-kode</comment>
- <comment xml:lang="de">SQL-Befehle</comment>
- <comment xml:lang="el">Κώδικας SQL</comment>
- <comment xml:lang="en_GB">SQL code</comment>
- <comment xml:lang="eo">SQL-kodo</comment>
- <comment xml:lang="es">código SQL</comment>
- <comment xml:lang="eu">SQL kodea</comment>
- <comment xml:lang="fi">SQL-koodi</comment>
- <comment xml:lang="fo">SQL kota</comment>
- <comment xml:lang="fr">code SQL</comment>
- <comment xml:lang="ga">cód SQL</comment>
- <comment xml:lang="gl">código SQL</comment>
- <comment xml:lang="he">קוד SQL</comment>
- <comment xml:lang="hr">SQL kôd</comment>
- <comment xml:lang="hu">SQL-kód</comment>
- <comment xml:lang="ia">Codice SQL</comment>
- <comment xml:lang="id">Kode SQL</comment>
- <comment xml:lang="it">Codice SQL</comment>
- <comment xml:lang="ja">SQL コード</comment>
- <comment xml:lang="kk">SQL коды</comment>
- <comment xml:lang="ko">SQL 코드</comment>
- <comment xml:lang="lt">SQL kodas</comment>
- <comment xml:lang="lv">SQL kods</comment>
- <comment xml:lang="ms">Kod SQL</comment>
- <comment xml:lang="nb">SQL-kildekode</comment>
- <comment xml:lang="nl">SQL-code</comment>
- <comment xml:lang="nn">SQL-kode</comment>
- <comment xml:lang="oc">còde SQL</comment>
- <comment xml:lang="pl">Kod SQL</comment>
- <comment xml:lang="pt">código SQL</comment>
- <comment xml:lang="pt_BR">Código SQL</comment>
- <comment xml:lang="ro">Cod SQL</comment>
- <comment xml:lang="ru">Код SQL</comment>
- <comment xml:lang="sk">Kód SQL</comment>
- <comment xml:lang="sl">Datoteka kode SQL</comment>
- <comment xml:lang="sq">Kod SQL</comment>
- <comment xml:lang="sr">СКуЛ ко̂д</comment>
- <comment xml:lang="sv">SQL-kod</comment>
- <comment xml:lang="tr">SQL kodu</comment>
- <comment xml:lang="uk">код SQL</comment>
- <comment xml:lang="vi">Mã SQL</comment>
- <comment xml:lang="zh_CN">SQL 代码</comment>
<comment xml:lang="zh_TW">SQL 程式碼</comment>
+ <comment xml:lang="zh_CN">SQL 代码</comment>
+ <comment xml:lang="vi">Mã SQL</comment>
+ <comment xml:lang="uk">код SQL</comment>
+ <comment xml:lang="tr">SQL kodu</comment>
+ <comment xml:lang="sv">SQL-kod</comment>
+ <comment xml:lang="sr">СКуЛ ко̂д</comment>
+ <comment xml:lang="sq">kod SQL</comment>
+ <comment xml:lang="sl">Datoteka kode SQL</comment>
+ <comment xml:lang="si">SQL කේතය</comment>
+ <comment xml:lang="sk">Kód SQL</comment>
+ <comment xml:lang="ru">Код SQL</comment>
+ <comment xml:lang="ro">Cod SQL</comment>
+ <comment xml:lang="pt_BR">Código SQL</comment>
+ <comment xml:lang="pt">código SQL</comment>
+ <comment xml:lang="pl">Kod SQL</comment>
+ <comment xml:lang="oc">còde SQL</comment>
+ <comment xml:lang="nn">SQL-kode</comment>
+ <comment xml:lang="nl">SQL-code</comment>
+ <comment xml:lang="nb">SQL-kildekode</comment>
+ <comment xml:lang="ms">Kod SQL</comment>
+ <comment xml:lang="lv">SQL kods</comment>
+ <comment xml:lang="lt">SQL kodas</comment>
+ <comment xml:lang="ko">SQL 코드</comment>
+ <comment xml:lang="kk">SQL коды</comment>
+ <comment xml:lang="ja">SQL コード</comment>
+ <comment xml:lang="it">Codice SQL</comment>
+ <comment xml:lang="is">SQL kóði</comment>
+ <comment xml:lang="id">Kode SQL</comment>
+ <comment xml:lang="ia">Codice SQL</comment>
+ <comment xml:lang="hu">SQL-kód</comment>
+ <comment xml:lang="hr">SQL kôd</comment>
+ <comment xml:lang="he">קוד SQL</comment>
+ <comment xml:lang="gl">código SQL</comment>
+ <comment xml:lang="ga">cód SQL</comment>
+ <comment xml:lang="fur">codiç SQL</comment>
+ <comment xml:lang="fr">code SQL</comment>
+ <comment xml:lang="fo">SQL kota</comment>
+ <comment xml:lang="fi">SQL-koodi</comment>
+ <comment xml:lang="eu">SQL kodea</comment>
+ <comment xml:lang="es">código SQL</comment>
+ <comment xml:lang="eo">SQL-kodo</comment>
+ <comment xml:lang="en_GB">SQL code</comment>
+ <comment xml:lang="el">Κώδικας SQL</comment>
+ <comment xml:lang="de">SQL-Befehle</comment>
+ <comment xml:lang="da">SQL-kode</comment>
+ <comment xml:lang="cy">Côd SQL</comment>
+ <comment xml:lang="cs">kód SQL</comment>
+ <comment xml:lang="ca">codi en SQL</comment>
+ <comment xml:lang="bg">Код — SQL</comment>
+ <comment xml:lang="be@latin">Kod SQL</comment>
+ <comment xml:lang="be">код SQL</comment>
+ <comment xml:lang="az">SQL kodu</comment>
+ <comment xml:lang="ar">شفرة SQL</comment>
+ <comment xml:lang="af">SQL-kode</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.sql"/>
<alias type="text/x-sql"/>
</mime-type>
- <mime-type type="text/x-tcl">
+ <mime-type type="text/tcl">
<comment>Tcl script</comment>
- <comment xml:lang="ar">سكربت Tcl</comment>
- <comment xml:lang="be@latin">Skrypt Tcl</comment>
- <comment xml:lang="bg">Скрипт — Tcl</comment>
- <comment xml:lang="ca">script Tcl</comment>
- <comment xml:lang="cs">skript Tcl</comment>
- <comment xml:lang="da">Tcl-program</comment>
- <comment xml:lang="de">Tcl-Skript</comment>
- <comment xml:lang="el">Δέσμη ενεργειών Tcl</comment>
- <comment xml:lang="en_GB">Tcl script</comment>
- <comment xml:lang="eo">Tcl-skripto</comment>
- <comment xml:lang="es">secuencia de órdenes en Tcl</comment>
- <comment xml:lang="eu">Tcl script-a</comment>
- <comment xml:lang="fi">Tcl-komentotiedosto</comment>
- <comment xml:lang="fo">Tcl boðrøð</comment>
- <comment xml:lang="fr">script Tcl</comment>
- <comment xml:lang="ga">script Tcl</comment>
- <comment xml:lang="gl">Script en Tcl</comment>
- <comment xml:lang="he">תסריט Tcl</comment>
- <comment xml:lang="hr">Tcl skripta</comment>
- <comment xml:lang="hu">Tcl-parancsfájl</comment>
- <comment xml:lang="ia">Script Tcl</comment>
- <comment xml:lang="id">Skrip Tcl</comment>
- <comment xml:lang="it">Script Tcl</comment>
- <comment xml:lang="ja">Tcl スクリプト</comment>
- <comment xml:lang="kk">Tcl сценарийі</comment>
- <comment xml:lang="ko">Tcl 스크립트</comment>
- <comment xml:lang="lt">Tcl scenarijus</comment>
- <comment xml:lang="lv">Tcl skripts</comment>
- <comment xml:lang="ms">Skrip Tcl</comment>
- <comment xml:lang="nb">Tcl-skript</comment>
- <comment xml:lang="nl">Tcl-script</comment>
- <comment xml:lang="nn">Tcl-skript</comment>
- <comment xml:lang="oc">escript Tcl</comment>
- <comment xml:lang="pl">Skrypt Tcl</comment>
- <comment xml:lang="pt">script Tcl</comment>
- <comment xml:lang="pt_BR">Script Tcl</comment>
- <comment xml:lang="ro">Script Tcl</comment>
- <comment xml:lang="ru">Сценарий Tcl</comment>
- <comment xml:lang="sk">Skript Tcl</comment>
- <comment xml:lang="sl">Skriptna datoteka Tcl</comment>
- <comment xml:lang="sq">Script Tcl</comment>
- <comment xml:lang="sr">Тцл скрипта</comment>
- <comment xml:lang="sv">Tcl-skript</comment>
- <comment xml:lang="tr">Tcl betiği</comment>
- <comment xml:lang="uk">скрипт Tcl</comment>
- <comment xml:lang="vi">Văn lệnh Tcl</comment>
- <comment xml:lang="zh_CN">Tcl 脚本</comment>
<comment xml:lang="zh_TW">Tcl 描述語言檔</comment>
+ <comment xml:lang="zh_CN">Tcl 脚本</comment>
+ <comment xml:lang="vi">Văn lệnh Tcl</comment>
+ <comment xml:lang="uk">скрипт Tcl</comment>
+ <comment xml:lang="tr">Tcl betiği</comment>
+ <comment xml:lang="sv">Tcl-skript</comment>
+ <comment xml:lang="sr">Тцл скрипта</comment>
+ <comment xml:lang="sq">programth Tcl</comment>
+ <comment xml:lang="sl">Skriptna datoteka Tcl</comment>
+ <comment xml:lang="si">Tcl පිටපත</comment>
+ <comment xml:lang="sk">Skript Tcl</comment>
+ <comment xml:lang="ru">Сценарий Tcl</comment>
+ <comment xml:lang="ro">Script Tcl</comment>
+ <comment xml:lang="pt_BR">Script Tcl</comment>
+ <comment xml:lang="pt">script Tcl</comment>
+ <comment xml:lang="pl">Skrypt Tcl</comment>
+ <comment xml:lang="oc">escript Tcl</comment>
+ <comment xml:lang="nn">Tcl-skript</comment>
+ <comment xml:lang="nl">Tcl-script</comment>
+ <comment xml:lang="nb">Tcl-skript</comment>
+ <comment xml:lang="ms">Skrip Tcl</comment>
+ <comment xml:lang="lv">Tcl skripts</comment>
+ <comment xml:lang="lt">Tcl scenarijus</comment>
+ <comment xml:lang="ko">Tcl 스크립트</comment>
+ <comment xml:lang="kk">Tcl сценарийі</comment>
+ <comment xml:lang="ja">Tcl スクリプト</comment>
+ <comment xml:lang="it">Script Tcl</comment>
+ <comment xml:lang="is">Tcl skrifta</comment>
+ <comment xml:lang="id">Skrip Tcl</comment>
+ <comment xml:lang="ia">Script Tcl</comment>
+ <comment xml:lang="hu">Tcl-parancsfájl</comment>
+ <comment xml:lang="hr">Tcl skripta</comment>
+ <comment xml:lang="he">תסריט Tcl</comment>
+ <comment xml:lang="gl">Script en Tcl</comment>
+ <comment xml:lang="ga">script Tcl</comment>
+ <comment xml:lang="fur">script Tcl</comment>
+ <comment xml:lang="fr">script Tcl</comment>
+ <comment xml:lang="fo">Tcl boðrøð</comment>
+ <comment xml:lang="fi">Tcl-komentotiedosto</comment>
+ <comment xml:lang="eu">Tcl script-a</comment>
+ <comment xml:lang="es">secuencia de órdenes en Tcl</comment>
+ <comment xml:lang="eo">Tcl-skripto</comment>
+ <comment xml:lang="en_GB">Tcl script</comment>
+ <comment xml:lang="el">Δέσμη ενεργειών Tcl</comment>
+ <comment xml:lang="de">Tcl-Skript</comment>
+ <comment xml:lang="da">Tcl-program</comment>
+ <comment xml:lang="cs">skript Tcl</comment>
+ <comment xml:lang="ca">script Tcl</comment>
+ <comment xml:lang="bg">Скрипт — Tcl</comment>
+ <comment xml:lang="be@latin">Skrypt Tcl</comment>
+ <comment xml:lang="be">скрыпт Tcl</comment>
+ <comment xml:lang="ar">سكربت Tcl</comment>
+ <comment xml:lang="af">Tcl-skrip</comment>
+ <alias type="text/x-tcl"/>
<sub-class-of type="text/plain"/>
<glob pattern="*.tcl"/>
<glob pattern="*.tk"/>
</mime-type>
<mime-type type="text/x-tex">
<comment>TeX document</comment>
- <comment xml:lang="ar">مستند TeX</comment>
- <comment xml:lang="ast">Documentu TeX</comment>
- <comment xml:lang="be@latin">Dakument TeX</comment>
- <comment xml:lang="bg">Документ — TeX</comment>
- <comment xml:lang="ca">document TeX</comment>
- <comment xml:lang="cs">dokument TeX</comment>
- <comment xml:lang="cy">Dogfen TeX </comment>
- <comment xml:lang="da">TeX-dokument</comment>
- <comment xml:lang="de">TeX-Dokument</comment>
- <comment xml:lang="el">Έγγραφο TeX</comment>
- <comment xml:lang="en_GB">TeX document</comment>
- <comment xml:lang="eo">TeX-dokumento</comment>
- <comment xml:lang="es">documento de TeX</comment>
- <comment xml:lang="eu">TeX dokumentua</comment>
- <comment xml:lang="fi">TeX-asiakirja</comment>
- <comment xml:lang="fo">TeX skjal</comment>
- <comment xml:lang="fr">document TeX</comment>
- <comment xml:lang="ga">cáipéis TeX</comment>
- <comment xml:lang="gl">documenton TeX</comment>
- <comment xml:lang="he">מסמך TeX</comment>
- <comment xml:lang="hr">TeX dokument</comment>
- <comment xml:lang="hu">TeX-dokumentum</comment>
- <comment xml:lang="ia">Documento TeX</comment>
- <comment xml:lang="id">Dokumen TeX</comment>
- <comment xml:lang="it">Documento TeX</comment>
- <comment xml:lang="ja">TeX ドキュメント</comment>
- <comment xml:lang="kk">TeX құжаты</comment>
- <comment xml:lang="ko">TeX 문서</comment>
- <comment xml:lang="lt">TeX dokumentas</comment>
- <comment xml:lang="lv">TeX dokuments</comment>
- <comment xml:lang="ms">Dokumen TeX</comment>
- <comment xml:lang="nb">TeX-dokument</comment>
- <comment xml:lang="nl">TeX-document</comment>
- <comment xml:lang="nn">TeX-dokument</comment>
- <comment xml:lang="oc">document TeX</comment>
- <comment xml:lang="pl">Dokument TeX</comment>
- <comment xml:lang="pt">documento TeX</comment>
- <comment xml:lang="pt_BR">Documento TeX</comment>
- <comment xml:lang="ro">Document TeX</comment>
- <comment xml:lang="ru">Документ TeX</comment>
- <comment xml:lang="sk">Dokument TeX</comment>
- <comment xml:lang="sl">Dokument TeX</comment>
- <comment xml:lang="sq">Dokument TeX</comment>
- <comment xml:lang="sr">ТеКс документ</comment>
- <comment xml:lang="sv">TeX-dokument</comment>
- <comment xml:lang="tr">TeX belgesi</comment>
- <comment xml:lang="uk">документ TeX</comment>
- <comment xml:lang="vi">Tài liệu TeX</comment>
- <comment xml:lang="zh_CN">TeX 文档</comment>
<comment xml:lang="zh_TW">TeX 文件</comment>
+ <comment xml:lang="zh_CN">TeX 文档</comment>
+ <comment xml:lang="vi">Tài liệu TeX</comment>
+ <comment xml:lang="uk">документ TeX</comment>
+ <comment xml:lang="tr">TeX belgesi</comment>
+ <comment xml:lang="sv">TeX-dokument</comment>
+ <comment xml:lang="sr">ТеКс документ</comment>
+ <comment xml:lang="sq">dokument TeX</comment>
+ <comment xml:lang="sl">Dokument TeX</comment>
+ <comment xml:lang="si">TeX ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument TeX</comment>
+ <comment xml:lang="ru">Документ TeX</comment>
+ <comment xml:lang="ro">Document TeX</comment>
+ <comment xml:lang="pt_BR">Documento TeX</comment>
+ <comment xml:lang="pt">documento TeX</comment>
+ <comment xml:lang="pl">Dokument TeX</comment>
+ <comment xml:lang="oc">document TeX</comment>
+ <comment xml:lang="nn">TeX-dokument</comment>
+ <comment xml:lang="nl">TeX-document</comment>
+ <comment xml:lang="nb">TeX-dokument</comment>
+ <comment xml:lang="ms">Dokumen TeX</comment>
+ <comment xml:lang="lv">TeX dokuments</comment>
+ <comment xml:lang="lt">TeX dokumentas</comment>
+ <comment xml:lang="ko">TeX 문서</comment>
+ <comment xml:lang="kk">TeX құжаты</comment>
+ <comment xml:lang="ja">TeX ドキュメント</comment>
+ <comment xml:lang="it">Documento TeX</comment>
+ <comment xml:lang="is">TeX skjal</comment>
+ <comment xml:lang="id">Dokumen TeX</comment>
+ <comment xml:lang="ia">Documento TeX</comment>
+ <comment xml:lang="hu">TeX-dokumentum</comment>
+ <comment xml:lang="hr">TeX dokument</comment>
+ <comment xml:lang="he">מסמך TeX</comment>
+ <comment xml:lang="gl">documenton TeX</comment>
+ <comment xml:lang="ga">cáipéis TeX</comment>
+ <comment xml:lang="fur">document TeX</comment>
+ <comment xml:lang="fr">document TeX</comment>
+ <comment xml:lang="fo">TeX skjal</comment>
+ <comment xml:lang="fi">TeX-asiakirja</comment>
+ <comment xml:lang="eu">TeX dokumentua</comment>
+ <comment xml:lang="es">documento de TeX</comment>
+ <comment xml:lang="eo">TeX-dokumento</comment>
+ <comment xml:lang="en_GB">TeX document</comment>
+ <comment xml:lang="el">Έγγραφο TeX</comment>
+ <comment xml:lang="de">TeX-Dokument</comment>
+ <comment xml:lang="da">TeX-dokument</comment>
+ <comment xml:lang="cy">Dogfen TeX </comment>
+ <comment xml:lang="cs">dokument TeX</comment>
+ <comment xml:lang="ca">document TeX</comment>
+ <comment xml:lang="bg">Документ — TeX</comment>
+ <comment xml:lang="be@latin">Dakument TeX</comment>
+ <comment xml:lang="be">дакумент TeX</comment>
+ <comment xml:lang="ast">Documentu TeX</comment>
+ <comment xml:lang="ar">مستند TeX</comment>
+ <comment xml:lang="af">TeX-dokument</comment>
<sub-class-of type="text/plain"/>
<alias type="application/x-tex"/>
<glob pattern="*.tex"/>
@@ -36490,460 +38774,573 @@
<glob pattern="*.ins"/>
<glob pattern="*.latex"/>
<magic priority="10">
- <match value="%" type="string" offset="0"/>
+ <match type="string" value="%" offset="0"/>
</magic>
- <magic priority="50">
- <match value="documentclass" type="string" offset="1"/>
+ <magic>
+ <match type="string" value="documentclass" offset="1"/>
</magic>
</mime-type>
<mime-type type="text/x-texinfo">
<comment>TeXInfo document</comment>
- <comment xml:lang="ar">مستند TeXInfo</comment>
- <comment xml:lang="ast">Documentu TeXInfo</comment>
- <comment xml:lang="az">TeXInfo sənədi</comment>
- <comment xml:lang="be@latin">Dakument TeXInfo</comment>
- <comment xml:lang="bg">Документ — TeXInfo</comment>
- <comment xml:lang="ca">document TeXInfo</comment>
- <comment xml:lang="cs">dokument TeXInfo</comment>
- <comment xml:lang="cy">Dogfen TeXInfo</comment>
- <comment xml:lang="da">TeXInfo-dokument</comment>
- <comment xml:lang="de">TeXInfo-Dokument</comment>
- <comment xml:lang="el">Έγγραφο TeXInfo</comment>
- <comment xml:lang="en_GB">TeXInfo document</comment>
- <comment xml:lang="eo">TeXInfo-dokumento</comment>
- <comment xml:lang="es">documento de TeXInfo</comment>
- <comment xml:lang="eu">TeXInfo dokumentua</comment>
- <comment xml:lang="fi">TeXInfo-asiakirja</comment>
- <comment xml:lang="fo">TeXInfo skjal</comment>
- <comment xml:lang="fr">document TeXInfo</comment>
- <comment xml:lang="ga">cáipéis TeXInfo</comment>
- <comment xml:lang="gl">documento TeXInfo</comment>
- <comment xml:lang="he">מסמך של TeXInfo</comment>
- <comment xml:lang="hr">TeXInfo dokument</comment>
- <comment xml:lang="hu">TeXInfo-dokumentum</comment>
- <comment xml:lang="ia">Documento TeXInfo</comment>
- <comment xml:lang="id">Dokumen TeXInfo</comment>
- <comment xml:lang="it">Documento TeXInfo</comment>
- <comment xml:lang="ja">TeXInfo ドキュメント</comment>
- <comment xml:lang="kk">TeXInfo құжаты</comment>
- <comment xml:lang="ko">TeXInfo 문서</comment>
- <comment xml:lang="lt">TeXInfo dokumentas</comment>
- <comment xml:lang="lv">TeXInfo dokuments</comment>
- <comment xml:lang="ms">Dokumen TeXInfo</comment>
- <comment xml:lang="nb">TeXInfo-dokument</comment>
- <comment xml:lang="nl">TeXInfo-document</comment>
- <comment xml:lang="nn">TeXInfo-dokument</comment>
- <comment xml:lang="oc">document TeXInfo</comment>
- <comment xml:lang="pl">Dokument TeXInfo</comment>
- <comment xml:lang="pt">documento TeXInfo</comment>
- <comment xml:lang="pt_BR">Documento TeXInfo</comment>
- <comment xml:lang="ro">Document TexInfo</comment>
- <comment xml:lang="ru">Документ TeXInfo</comment>
- <comment xml:lang="sk">Dokument TeXInfo</comment>
- <comment xml:lang="sl">Dokument TeXInfo</comment>
- <comment xml:lang="sq">Dokument TeXInfo</comment>
- <comment xml:lang="sr">ТеКсинфо документ</comment>
- <comment xml:lang="sv">TeXInfo-dokument</comment>
- <comment xml:lang="tr">TeXInfo belgesi</comment>
- <comment xml:lang="uk">документ TeXInfo</comment>
- <comment xml:lang="vi">Tài liệu TeXInfo</comment>
- <comment xml:lang="zh_CN">TeXInfo 文档</comment>
<comment xml:lang="zh_TW">TeXInfo 文件</comment>
+ <comment xml:lang="zh_CN">TeXInfo 文档</comment>
+ <comment xml:lang="vi">Tài liệu TeXInfo</comment>
+ <comment xml:lang="uk">документ TeXInfo</comment>
+ <comment xml:lang="tr">TeXInfo belgesi</comment>
+ <comment xml:lang="sv">TeXInfo-dokument</comment>
+ <comment xml:lang="sr">ТеКсинфо документ</comment>
+ <comment xml:lang="sq">dokument TeXInfo</comment>
+ <comment xml:lang="sl">Dokument TeXInfo</comment>
+ <comment xml:lang="si">TeXInfo ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument TeXInfo</comment>
+ <comment xml:lang="ru">Документ TeXInfo</comment>
+ <comment xml:lang="ro">Document TexInfo</comment>
+ <comment xml:lang="pt_BR">Documento TeXInfo</comment>
+ <comment xml:lang="pt">documento TeXInfo</comment>
+ <comment xml:lang="pl">Dokument TeXInfo</comment>
+ <comment xml:lang="oc">document TeXInfo</comment>
+ <comment xml:lang="nn">TeXInfo-dokument</comment>
+ <comment xml:lang="nl">TeXInfo-document</comment>
+ <comment xml:lang="nb">TeXInfo-dokument</comment>
+ <comment xml:lang="ms">Dokumen TeXInfo</comment>
+ <comment xml:lang="lv">TeXInfo dokuments</comment>
+ <comment xml:lang="lt">TeXInfo dokumentas</comment>
+ <comment xml:lang="ko">TeXInfo 문서</comment>
+ <comment xml:lang="kk">TeXInfo құжаты</comment>
+ <comment xml:lang="ja">TeXInfo ドキュメント</comment>
+ <comment xml:lang="it">Documento TeXInfo</comment>
+ <comment xml:lang="is">TeXInfo skjal</comment>
+ <comment xml:lang="id">Dokumen TeXInfo</comment>
+ <comment xml:lang="ia">Documento TeXInfo</comment>
+ <comment xml:lang="hu">TeXInfo-dokumentum</comment>
+ <comment xml:lang="hr">TeXInfo dokument</comment>
+ <comment xml:lang="he">מסמך של TeXInfo</comment>
+ <comment xml:lang="gl">documento TeXInfo</comment>
+ <comment xml:lang="ga">cáipéis TeXInfo</comment>
+ <comment xml:lang="fur">document TeXInfo</comment>
+ <comment xml:lang="fr">document TeXInfo</comment>
+ <comment xml:lang="fo">TeXInfo skjal</comment>
+ <comment xml:lang="fi">TeXInfo-asiakirja</comment>
+ <comment xml:lang="eu">TeXInfo dokumentua</comment>
+ <comment xml:lang="es">documento de TeXInfo</comment>
+ <comment xml:lang="eo">TeXInfo-dokumento</comment>
+ <comment xml:lang="en_GB">TeXInfo document</comment>
+ <comment xml:lang="el">Έγγραφο TeXInfo</comment>
+ <comment xml:lang="de">TeXInfo-Dokument</comment>
+ <comment xml:lang="da">TeXInfo-dokument</comment>
+ <comment xml:lang="cy">Dogfen TeXInfo</comment>
+ <comment xml:lang="cs">dokument TeXInfo</comment>
+ <comment xml:lang="ca">document TeXInfo</comment>
+ <comment xml:lang="bg">Документ — TeXInfo</comment>
+ <comment xml:lang="be@latin">Dakument TeXInfo</comment>
+ <comment xml:lang="be">дакумент TeXInfo</comment>
+ <comment xml:lang="az">TeXInfo sənədi</comment>
+ <comment xml:lang="ast">Documentu TeXInfo</comment>
+ <comment xml:lang="ar">مستند TeXInfo</comment>
+ <comment xml:lang="af">TeXInfo-dokument</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.texi"/>
<glob pattern="*.texinfo"/>
</mime-type>
+ <mime-type type="text/x-typst">
+ <comment>Typst document</comment>
+ <comment xml:lang="uk">документ Typst</comment>
+ <comment xml:lang="sv">Typst-dokument</comment>
+ <comment xml:lang="ru">Документ Typst</comment>
+ <comment xml:lang="pl">Dokument Typst</comment>
+ <comment xml:lang="it">Documento Typst</comment>
+ <comment xml:lang="gl">Documento de Typst</comment>
+ <comment xml:lang="eu">Typst dokumentua</comment>
+ <comment xml:lang="es">documento de Typst</comment>
+ <comment xml:lang="de">Typst-Dokument</comment>
+ <comment xml:lang="be">дакумент Typst</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.typ"/>
+ </mime-type>
<mime-type type="text/x-troff-me">
<comment>Troff ME input document</comment>
- <comment xml:lang="ar">مستند Troff ME input</comment>
- <comment xml:lang="ast">Documentu d'entrada de Troff ME</comment>
- <comment xml:lang="be@latin">Uvodny dakument Troff ME</comment>
- <comment xml:lang="bg">Изходен документ — Troff ME</comment>
- <comment xml:lang="ca">document d'entrada Troff ME</comment>
- <comment xml:lang="cs">vstupní dokument Troff ME</comment>
- <comment xml:lang="da">Troff ME inddata-dokument</comment>
- <comment xml:lang="de">Troff-ME-Eingabedokument</comment>
- <comment xml:lang="el">Έγγραφο εντολών troff ME</comment>
- <comment xml:lang="en_GB">Troff ME input document</comment>
- <comment xml:lang="eo">eniga dokumento de Troff ME</comment>
- <comment xml:lang="es">documento de entrada Troff ME</comment>
- <comment xml:lang="eu">Troff ME sarrerako dokumentua</comment>
- <comment xml:lang="fi">Troff ME -syöteasiakirja</comment>
- <comment xml:lang="fo">Troff ME inntaksskjal</comment>
- <comment xml:lang="fr">document d'entrée Troff ME</comment>
- <comment xml:lang="ga">cáipéis ionchurtha Troff ME</comment>
- <comment xml:lang="gl">documento de entrada Troff ME</comment>
- <comment xml:lang="he">מסמך קלט של Troff ME</comment>
- <comment xml:lang="hr">Troff ME ulazni dokument</comment>
- <comment xml:lang="hu">Troff ME bemeneti dokumentum</comment>
- <comment xml:lang="ia">Documento de entrata Troff ME</comment>
- <comment xml:lang="id">Dokumen masukan Troff ME</comment>
- <comment xml:lang="it">Documento di input Troff ME</comment>
- <comment xml:lang="ja">Troff ME 入力ドキュメント</comment>
- <comment xml:lang="kk">Troff ME кіріс құжаты</comment>
- <comment xml:lang="ko">Troff ME 입력 문서</comment>
- <comment xml:lang="lt">Troff ME įvesties dokumentas</comment>
- <comment xml:lang="lv">Troff ME ievades dokuments</comment>
- <comment xml:lang="ms">Dokumen input Troff ME</comment>
- <comment xml:lang="nb">Troff ME-inndatadokument</comment>
- <comment xml:lang="nl">Troff ME-invoerdocument</comment>
- <comment xml:lang="nn">Troff ME inndata-dokument</comment>
- <comment xml:lang="oc">document d'entrada Troff ME</comment>
- <comment xml:lang="pl">Dokument wejściowy Troff ME</comment>
- <comment xml:lang="pt">documento origem Troff ME</comment>
- <comment xml:lang="pt_BR">Documento de entrada Troff ME</comment>
- <comment xml:lang="ro">Document intrare Troff ME</comment>
- <comment xml:lang="ru">Входной документ Troff ME</comment>
- <comment xml:lang="sk">Vstupný dokument Troff ME</comment>
- <comment xml:lang="sl">Vnosni dokument Troff ME</comment>
- <comment xml:lang="sq">Dokument i input Troff ME</comment>
- <comment xml:lang="sr">Трофф МЕ улазни документ</comment>
- <comment xml:lang="sv">Troff ME-indatadokument</comment>
- <comment xml:lang="tr">Troff ME girdi belgesi</comment>
- <comment xml:lang="uk">вхідний документ Troff ME</comment>
- <comment xml:lang="vi">Tài liệu nhập ME Troff</comment>
- <comment xml:lang="zh_CN">Troff ME 输入文档</comment>
<comment xml:lang="zh_TW">Troff ME 輸入文件</comment>
+ <comment xml:lang="zh_CN">Troff ME 输入文档</comment>
+ <comment xml:lang="vi">Tài liệu nhập ME Troff</comment>
+ <comment xml:lang="uk">вхідний документ Troff ME</comment>
+ <comment xml:lang="tr">Troff ME girdi belgesi</comment>
+ <comment xml:lang="sv">Troff ME-indatadokument</comment>
+ <comment xml:lang="sr">Трофф МЕ улазни документ</comment>
+ <comment xml:lang="sq">dokument ME input-i për Troff</comment>
+ <comment xml:lang="sl">Vnosni dokument Troff ME</comment>
+ <comment xml:lang="si">ට්‍රොෆ් ME ආදාන ලේඛනය</comment>
+ <comment xml:lang="sk">Vstupný dokument Troff ME</comment>
+ <comment xml:lang="ru">Входной документ Troff ME</comment>
+ <comment xml:lang="ro">Document intrare Troff ME</comment>
+ <comment xml:lang="pt_BR">Documento de entrada Troff ME</comment>
+ <comment xml:lang="pt">documento origem Troff ME</comment>
+ <comment xml:lang="pl">Dokument wejściowy Troff ME</comment>
+ <comment xml:lang="oc">document d'entrada Troff ME</comment>
+ <comment xml:lang="nn">Troff ME inndata-dokument</comment>
+ <comment xml:lang="nl">Troff ME-invoerdocument</comment>
+ <comment xml:lang="nb">Troff ME-inndatadokument</comment>
+ <comment xml:lang="ms">Dokumen input Troff ME</comment>
+ <comment xml:lang="lv">Troff ME ievades dokuments</comment>
+ <comment xml:lang="lt">Troff ME įvesties dokumentas</comment>
+ <comment xml:lang="ko">Troff ME 입력 문서</comment>
+ <comment xml:lang="kk">Troff ME кіріс құжаты</comment>
+ <comment xml:lang="ja">Troff ME 入力ドキュメント</comment>
+ <comment xml:lang="it">Documento di input Troff ME</comment>
+ <comment xml:lang="is">Troff ME inngangsskjal</comment>
+ <comment xml:lang="id">Dokumen masukan Troff ME</comment>
+ <comment xml:lang="ia">Documento de entrata Troff ME</comment>
+ <comment xml:lang="hu">Troff ME bemeneti dokumentum</comment>
+ <comment xml:lang="hr">Troff ME ulazni dokument</comment>
+ <comment xml:lang="he">מסמך קלט של Troff ME</comment>
+ <comment xml:lang="gl">documento de entrada Troff ME</comment>
+ <comment xml:lang="ga">cáipéis ionchurtha Troff ME</comment>
+ <comment xml:lang="fur">document di jentrade Troff ME</comment>
+ <comment xml:lang="fr">document d'entrée Troff ME</comment>
+ <comment xml:lang="fo">Troff ME inntaksskjal</comment>
+ <comment xml:lang="fi">Troff ME -syöteasiakirja</comment>
+ <comment xml:lang="eu">Troff ME sarrerako dokumentua</comment>
+ <comment xml:lang="es">documento de entrada Troff ME</comment>
+ <comment xml:lang="eo">eniga dokumento de Troff ME</comment>
+ <comment xml:lang="en_GB">Troff ME input document</comment>
+ <comment xml:lang="el">Έγγραφο εντολών troff ME</comment>
+ <comment xml:lang="de">Troff-ME-Eingabedokument</comment>
+ <comment xml:lang="da">Troff ME inddata-dokument</comment>
+ <comment xml:lang="cs">vstupní dokument Troff ME</comment>
+ <comment xml:lang="ca">document d'entrada Troff ME</comment>
+ <comment xml:lang="bg">Изходен документ — Troff ME</comment>
+ <comment xml:lang="be@latin">Uvodny dakument Troff ME</comment>
+ <comment xml:lang="be">уваходны дакумент Troff ME</comment>
+ <comment xml:lang="ast">Documentu d'entrada de Troff ME</comment>
+ <comment xml:lang="ar">مستند Troff ME input</comment>
+ <comment xml:lang="af">Troff ME-toevoerdokument</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.me"/>
</mime-type>
<mime-type type="text/x-troff-mm">
<comment>Troff MM input document</comment>
- <comment xml:lang="ar">مستند Troff MM input</comment>
- <comment xml:lang="ast">Documentu d'entrada de Troff MM</comment>
- <comment xml:lang="be@latin">Uvodny dakument Troff MM</comment>
- <comment xml:lang="bg">Изходен документ — Troff MM</comment>
- <comment xml:lang="ca">document d'entrada Troff MM</comment>
- <comment xml:lang="cs">vstupní dokument Troff MM</comment>
- <comment xml:lang="da">Troff MM inddata-dokument</comment>
- <comment xml:lang="de">Troff-MM-Eingabedokument</comment>
- <comment xml:lang="el">Έγγραφο εντολών troff MM</comment>
- <comment xml:lang="en_GB">Troff MM input document</comment>
- <comment xml:lang="eo">eniga dokumento de Troff MM</comment>
- <comment xml:lang="es">documento de entrada Troff MM</comment>
- <comment xml:lang="eu">Troff MM sarrerako dokumentua</comment>
- <comment xml:lang="fi">Troff MM -syöteasiakirja</comment>
- <comment xml:lang="fo">Troff MM inntaksskjal</comment>
- <comment xml:lang="fr">document d'entrée Troff MM</comment>
- <comment xml:lang="ga">cáipéis ionchurtha Troff MM</comment>
- <comment xml:lang="gl">documento de entrada Troff MM</comment>
- <comment xml:lang="he">מסמך קלט של Troff MM</comment>
- <comment xml:lang="hr">Troff MM ulazni dokument</comment>
- <comment xml:lang="hu">Troff MM bemeneti dokumentum</comment>
- <comment xml:lang="ia">Documento de entrata Troff MM</comment>
- <comment xml:lang="id">Dokumen masukan Troff MM</comment>
- <comment xml:lang="it">Documento di input Troff MM</comment>
- <comment xml:lang="ja">Troff MM 入力ドキュメント</comment>
- <comment xml:lang="kk">Troff MM кіріс құжаты</comment>
- <comment xml:lang="ko">Troff MM 입력 문서</comment>
- <comment xml:lang="lt">Troff MM įvesties dokumentas</comment>
- <comment xml:lang="lv">Troff MM ievades dokuments</comment>
- <comment xml:lang="ms">Dokumen input Troff MM</comment>
- <comment xml:lang="nb">Troff MM-inndatadokument</comment>
- <comment xml:lang="nl">Troff MM-invoerdocument</comment>
- <comment xml:lang="nn">Troff MM inndata-dokument</comment>
- <comment xml:lang="oc">document d'entrada Troff MM</comment>
- <comment xml:lang="pl">Dokument wejściowy Troff MM</comment>
- <comment xml:lang="pt">documento origem Troff MM</comment>
- <comment xml:lang="pt_BR">Documento de entrada Troff MM</comment>
- <comment xml:lang="ro">Document intrare Troff MM</comment>
- <comment xml:lang="ru">Входной документ Troff MM</comment>
- <comment xml:lang="sk">Vstupný dokument Troff MM</comment>
- <comment xml:lang="sl">Vnosni dokument Troff MM</comment>
- <comment xml:lang="sq">Dokument i input Troff MM</comment>
- <comment xml:lang="sr">Трофф ММ улазни документ</comment>
- <comment xml:lang="sv">Troff MM-indatadokument</comment>
- <comment xml:lang="tr">Troff MM girdi belgesi</comment>
- <comment xml:lang="uk">вхідний документ Troff MM</comment>
- <comment xml:lang="vi">Tài liệu nhập MM Troff</comment>
- <comment xml:lang="zh_CN">Troff MM 输入文档</comment>
<comment xml:lang="zh_TW">Troff MM 輸入文件</comment>
- <sub-class-of type="text/plain"/>
+ <comment xml:lang="zh_CN">Troff MM 输入文档</comment>
+ <comment xml:lang="vi">Tài liệu nhập MM Troff</comment>
+ <comment xml:lang="uk">вхідний документ Troff MM</comment>
+ <comment xml:lang="tr">Troff MM girdi belgesi</comment>
+ <comment xml:lang="sv">Troff MM-indatadokument</comment>
+ <comment xml:lang="sr">Трофф ММ улазни документ</comment>
+ <comment xml:lang="sq">dokument MM input-i për Troff</comment>
+ <comment xml:lang="sl">Vnosni dokument Troff MM</comment>
+ <comment xml:lang="si">Troff MM ආදාන ලේඛනය</comment>
+ <comment xml:lang="sk">Vstupný dokument Troff MM</comment>
+ <comment xml:lang="ru">Входной документ Troff MM</comment>
+ <comment xml:lang="ro">Document intrare Troff MM</comment>
+ <comment xml:lang="pt_BR">Documento de entrada Troff MM</comment>
+ <comment xml:lang="pt">documento origem Troff MM</comment>
+ <comment xml:lang="pl">Dokument wejściowy Troff MM</comment>
+ <comment xml:lang="oc">document d'entrada Troff MM</comment>
+ <comment xml:lang="nn">Troff MM inndata-dokument</comment>
+ <comment xml:lang="nl">Troff MM-invoerdocument</comment>
+ <comment xml:lang="nb">Troff MM-inndatadokument</comment>
+ <comment xml:lang="ms">Dokumen input Troff MM</comment>
+ <comment xml:lang="lv">Troff MM ievades dokuments</comment>
+ <comment xml:lang="lt">Troff MM įvesties dokumentas</comment>
+ <comment xml:lang="ko">Troff MM 입력 문서</comment>
+ <comment xml:lang="kk">Troff MM кіріс құжаты</comment>
+ <comment xml:lang="ja">Troff MM 入力ドキュメント</comment>
+ <comment xml:lang="it">Documento di input Troff MM</comment>
+ <comment xml:lang="is">Troff MM inngangsskjal</comment>
+ <comment xml:lang="id">Dokumen masukan Troff MM</comment>
+ <comment xml:lang="ia">Documento de entrata Troff MM</comment>
+ <comment xml:lang="hu">Troff MM bemeneti dokumentum</comment>
+ <comment xml:lang="hr">Troff MM ulazni dokument</comment>
+ <comment xml:lang="he">מסמך קלט של Troff MM</comment>
+ <comment xml:lang="gl">documento de entrada Troff MM</comment>
+ <comment xml:lang="ga">cáipéis ionchurtha Troff MM</comment>
+ <comment xml:lang="fur">document di jentrade Troff MM</comment>
+ <comment xml:lang="fr">document d'entrée Troff MM</comment>
+ <comment xml:lang="fo">Troff MM inntaksskjal</comment>
+ <comment xml:lang="fi">Troff MM -syöteasiakirja</comment>
+ <comment xml:lang="eu">Troff MM sarrerako dokumentua</comment>
+ <comment xml:lang="es">documento de entrada Troff MM</comment>
+ <comment xml:lang="eo">eniga dokumento de Troff MM</comment>
+ <comment xml:lang="en_GB">Troff MM input document</comment>
+ <comment xml:lang="el">Έγγραφο εντολών troff MM</comment>
+ <comment xml:lang="de">Troff-MM-Eingabedokument</comment>
+ <comment xml:lang="da">Troff MM inddata-dokument</comment>
+ <comment xml:lang="cs">vstupní dokument Troff MM</comment>
+ <comment xml:lang="ca">document d'entrada Troff MM</comment>
+ <comment xml:lang="bg">Изходен документ — Troff MM</comment>
+ <comment xml:lang="be@latin">Uvodny dakument Troff MM</comment>
+ <comment xml:lang="be">уваходны дакумент Troff MM</comment>
+ <comment xml:lang="ast">Documentu d'entrada de Troff MM</comment>
+ <comment xml:lang="ar">مستند Troff MM input</comment>
+ <comment xml:lang="af">Troff MM-toevoerdokument</comment>
+ <sub-class-of type="text/troff"/>
<glob pattern="*.mm"/>
</mime-type>
<mime-type type="text/x-troff-ms">
<comment>Troff MS input document</comment>
- <comment xml:lang="ar">مستند Troff MS input</comment>
- <comment xml:lang="ast">Documentu d'entrada de Troff MS</comment>
- <comment xml:lang="be@latin">Uvodny dakument Troff MS</comment>
- <comment xml:lang="bg">Изходен документ — Troff MS</comment>
- <comment xml:lang="ca">document d'entrada Troff MS</comment>
- <comment xml:lang="cs">vstupní dokument Troff MS</comment>
- <comment xml:lang="da">Troff MS inddata-dokument</comment>
- <comment xml:lang="de">Troff-MS-Eingabedokument</comment>
- <comment xml:lang="el">Έγγραφο εντολών troff MS</comment>
- <comment xml:lang="en_GB">Troff MS input document</comment>
- <comment xml:lang="eo">eniga dokumento de Troff MS</comment>
- <comment xml:lang="es">documento de entrada Troff MS</comment>
- <comment xml:lang="eu">Troff MS sarrerako dokumentua</comment>
- <comment xml:lang="fi">Troff MS -syöteasiakirja</comment>
- <comment xml:lang="fo">Troff MS inntaksskjal</comment>
- <comment xml:lang="fr">document d'entrée Troff MS</comment>
- <comment xml:lang="ga">cáipéis ionchurtha Troff MS</comment>
- <comment xml:lang="gl">documento de entrada Troff MS</comment>
- <comment xml:lang="he">מסמך קלט של Troff MS</comment>
- <comment xml:lang="hr">Troff MS ulazni dokument</comment>
- <comment xml:lang="hu">Troff MS bemeneti dokumentum</comment>
- <comment xml:lang="ia">Documento de entrata Troff MS</comment>
- <comment xml:lang="id">Dokumen masukan Troff MS</comment>
- <comment xml:lang="it">Documento di input Troff MS</comment>
- <comment xml:lang="ja">Troff MS 入力ドキュメント</comment>
- <comment xml:lang="kk">Troff MS кіріс құжаты</comment>
- <comment xml:lang="ko">Troff MS 입력 문서</comment>
- <comment xml:lang="lt">Troff MS įvesties dokumentas</comment>
- <comment xml:lang="lv">Troff MS ievades dokuments</comment>
- <comment xml:lang="ms">Dokumen input Troff MS</comment>
- <comment xml:lang="nb">Troff MS-inndatadokument</comment>
- <comment xml:lang="nl">Troff MS-invoerdocument</comment>
- <comment xml:lang="nn">Troff MS inndata-dokument</comment>
- <comment xml:lang="oc">document d'entrada Troff MS</comment>
- <comment xml:lang="pl">Dokument wejściowy Troff MS</comment>
- <comment xml:lang="pt">documento origem Troff MS</comment>
- <comment xml:lang="pt_BR">Documento de entrada Troff MS</comment>
- <comment xml:lang="ro">Document intrare Troff MS</comment>
- <comment xml:lang="ru">Входной документ Troff MS</comment>
- <comment xml:lang="sk">Vstupný dokument Troff MS</comment>
- <comment xml:lang="sl">Vnosni dokument Troff MS</comment>
- <comment xml:lang="sq">Dokument i input Troff MS</comment>
- <comment xml:lang="sr">Трофф МС улазни документ</comment>
- <comment xml:lang="sv">Troff MS-indatadokument</comment>
- <comment xml:lang="tr">Troff MS girdi belgesi</comment>
- <comment xml:lang="uk">вхідний документ Troff MS</comment>
- <comment xml:lang="vi">Tài liệu nhập MS Troff</comment>
- <comment xml:lang="zh_CN">Troff MS 输入文档</comment>
<comment xml:lang="zh_TW">Troff MS 輸入文件</comment>
+ <comment xml:lang="zh_CN">Troff MS 输入文档</comment>
+ <comment xml:lang="vi">Tài liệu nhập MS Troff</comment>
+ <comment xml:lang="uk">вхідний документ Troff MS</comment>
+ <comment xml:lang="tr">Troff MS girdi belgesi</comment>
+ <comment xml:lang="sv">Troff MS-indatadokument</comment>
+ <comment xml:lang="sr">Трофф МС улазни документ</comment>
+ <comment xml:lang="sq">dokument MS input-i për Troff</comment>
+ <comment xml:lang="sl">Vnosni dokument Troff MS</comment>
+ <comment xml:lang="si">Troff MS ආදාන ලේඛනය</comment>
+ <comment xml:lang="sk">Vstupný dokument Troff MS</comment>
+ <comment xml:lang="ru">Входной документ Troff MS</comment>
+ <comment xml:lang="ro">Document intrare Troff MS</comment>
+ <comment xml:lang="pt_BR">Documento de entrada Troff MS</comment>
+ <comment xml:lang="pt">documento origem Troff MS</comment>
+ <comment xml:lang="pl">Dokument wejściowy Troff MS</comment>
+ <comment xml:lang="oc">document d'entrada Troff MS</comment>
+ <comment xml:lang="nn">Troff MS inndata-dokument</comment>
+ <comment xml:lang="nl">Troff MS-invoerdocument</comment>
+ <comment xml:lang="nb">Troff MS-inndatadokument</comment>
+ <comment xml:lang="ms">Dokumen input Troff MS</comment>
+ <comment xml:lang="lv">Troff MS ievades dokuments</comment>
+ <comment xml:lang="lt">Troff MS įvesties dokumentas</comment>
+ <comment xml:lang="ko">Troff MS 입력 문서</comment>
+ <comment xml:lang="kk">Troff MS кіріс құжаты</comment>
+ <comment xml:lang="ja">Troff MS 入力ドキュメント</comment>
+ <comment xml:lang="it">Documento di input Troff MS</comment>
+ <comment xml:lang="is">Troff MS inngangsskjal</comment>
+ <comment xml:lang="id">Dokumen masukan Troff MS</comment>
+ <comment xml:lang="ia">Documento de entrata Troff MS</comment>
+ <comment xml:lang="hu">Troff MS bemeneti dokumentum</comment>
+ <comment xml:lang="hr">Troff MS ulazni dokument</comment>
+ <comment xml:lang="he">מסמך קלט של Troff MS</comment>
+ <comment xml:lang="gl">documento de entrada Troff MS</comment>
+ <comment xml:lang="ga">cáipéis ionchurtha Troff MS</comment>
+ <comment xml:lang="fur">document di jentrade Troff MS</comment>
+ <comment xml:lang="fr">document d'entrée Troff MS</comment>
+ <comment xml:lang="fo">Troff MS inntaksskjal</comment>
+ <comment xml:lang="fi">Troff MS -syöteasiakirja</comment>
+ <comment xml:lang="eu">Troff MS sarrerako dokumentua</comment>
+ <comment xml:lang="es">documento de entrada Troff MS</comment>
+ <comment xml:lang="eo">eniga dokumento de Troff MS</comment>
+ <comment xml:lang="en_GB">Troff MS input document</comment>
+ <comment xml:lang="el">Έγγραφο εντολών troff MS</comment>
+ <comment xml:lang="de">Troff-MS-Eingabedokument</comment>
+ <comment xml:lang="da">Troff MS inddata-dokument</comment>
+ <comment xml:lang="cs">vstupní dokument Troff MS</comment>
+ <comment xml:lang="ca">document d'entrada Troff MS</comment>
+ <comment xml:lang="bg">Изходен документ — Troff MS</comment>
+ <comment xml:lang="be@latin">Uvodny dakument Troff MS</comment>
+ <comment xml:lang="be">уваходны дакумент Troff MS</comment>
+ <comment xml:lang="ast">Documentu d'entrada de Troff MS</comment>
+ <comment xml:lang="ar">مستند Troff MS input</comment>
+ <comment xml:lang="af">Troff MS-toevoerdokument</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.ms"/>
</mime-type>
<mime-type type="text/x-twig">
<comment>Twig template</comment>
- <comment xml:lang="ca">plantilla Twig</comment>
- <comment xml:lang="cs">šablona Twig</comment>
- <comment xml:lang="da">Twig-skabelon</comment>
- <comment xml:lang="de">Twig-Vorlage</comment>
- <comment xml:lang="en_GB">Twig template</comment>
- <comment xml:lang="es">plantilla de Twig</comment>
- <comment xml:lang="eu">Twig txantiloia</comment>
- <comment xml:lang="fr">modèle Twig</comment>
- <comment xml:lang="ga">teimpléad Twig</comment>
- <comment xml:lang="he">תבנית Twig</comment>
- <comment xml:lang="hr">Twig predložak</comment>
- <comment xml:lang="hu">Twig-sablon</comment>
- <comment xml:lang="id">templat Twig</comment>
- <comment xml:lang="it">Modello twig</comment>
- <comment xml:lang="kk">Twig үлгісі</comment>
- <comment xml:lang="ko">Twig 문서 서식</comment>
- <comment xml:lang="pl">Szablon Twig</comment>
- <comment xml:lang="pt_BR">Modelo Twig</comment>
- <comment xml:lang="ru">Шаблон Twig</comment>
- <comment xml:lang="sk">Šablóna Twig</comment>
- <comment xml:lang="sr">Твиг шаблон</comment>
- <comment xml:lang="sv">Twig-mall</comment>
- <comment xml:lang="tr">Twig şablonu</comment>
- <comment xml:lang="uk">шаблон twig</comment>
- <comment xml:lang="zh_CN">Twig 模板</comment>
<comment xml:lang="zh_TW">Twig 範本</comment>
+ <comment xml:lang="zh_CN">Twig 模板</comment>
+ <comment xml:lang="uk">шаблон twig</comment>
+ <comment xml:lang="tr">Twig şablonu</comment>
+ <comment xml:lang="sv">Twig-mall</comment>
+ <comment xml:lang="sr">Твиг шаблон</comment>
+ <comment xml:lang="sq">gjedhe Twig</comment>
+ <comment xml:lang="sl">Predloga Twig</comment>
+ <comment xml:lang="si">අතු අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna Twig</comment>
+ <comment xml:lang="ru">Шаблон Twig</comment>
+ <comment xml:lang="pt_BR">Modelo Twig</comment>
+ <comment xml:lang="pl">Szablon Twig</comment>
+ <comment xml:lang="oc">modèl Twig</comment>
+ <comment xml:lang="nl">Twig-sjabloon</comment>
+ <comment xml:lang="ko">Twig 문서 서식</comment>
+ <comment xml:lang="kk">Twig үлгісі</comment>
+ <comment xml:lang="ja">Twig テンプレート</comment>
+ <comment xml:lang="it">Modello twig</comment>
+ <comment xml:lang="is">Twig-sniðmát</comment>
+ <comment xml:lang="id">Templat Twig</comment>
+ <comment xml:lang="hu">Twig-sablon</comment>
+ <comment xml:lang="hr">Twig predložak</comment>
+ <comment xml:lang="he">תבנית Twig</comment>
+ <comment xml:lang="gl">Plantilla de Twig</comment>
+ <comment xml:lang="ga">teimpléad Twig</comment>
+ <comment xml:lang="fur">model Twig</comment>
+ <comment xml:lang="fr">modèle Twig</comment>
+ <comment xml:lang="fi">Twig-malli</comment>
+ <comment xml:lang="eu">Twig txantiloia</comment>
+ <comment xml:lang="es">plantilla de Twig</comment>
+ <comment xml:lang="en_GB">Twig template</comment>
+ <comment xml:lang="de">Twig-Vorlage</comment>
+ <comment xml:lang="da">Twig-skabelon</comment>
+ <comment xml:lang="cs">šablona Twig</comment>
+ <comment xml:lang="ca">plantilla Twig</comment>
+ <comment xml:lang="bg">Шаблон — Twig</comment>
+ <comment xml:lang="be">шаблон Twig</comment>
+ <comment xml:lang="ar">قالب Twig</comment>
+ <comment xml:lang="af">Twig-sjabloon</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.twig"/>
<generic-icon name="text-x-generic-template"/>
</mime-type>
<mime-type type="text/x-uil">
<comment>X-Motif UIL table</comment>
- <comment xml:lang="ar">جدول X-Motif UIL</comment>
- <comment xml:lang="be@latin">Tablica X-Motif UIL</comment>
- <comment xml:lang="bg">Таблица — X-Motif UIL</comment>
- <comment xml:lang="ca">taula UIL de X-Motif</comment>
- <comment xml:lang="cs">tabulka X-Motif UIL</comment>
- <comment xml:lang="da">X-Motif UIL-tabel</comment>
- <comment xml:lang="de">X-Motif-UIL-Tabelle</comment>
- <comment xml:lang="el">Πίνακας X-Motif UIL</comment>
- <comment xml:lang="en_GB">X-Motif UIL table</comment>
- <comment xml:lang="es">tabla de X-Motif UIL</comment>
- <comment xml:lang="eu">X-Motif UIL taula</comment>
- <comment xml:lang="fi">X-Motif UIL -taulukko</comment>
- <comment xml:lang="fo">X-Motif UIL talva</comment>
- <comment xml:lang="fr">table X-Motif UIL</comment>
- <comment xml:lang="ga">tábla X-Motif UIL</comment>
- <comment xml:lang="gl">Táboa de X-Motif UIL</comment>
- <comment xml:lang="he">טבלה של X-Motif UIL</comment>
- <comment xml:lang="hr">X-Motif UIL tablica</comment>
- <comment xml:lang="hu">X-Motif UIL-táblázat</comment>
- <comment xml:lang="ia">Tabella X-Motif UIL</comment>
- <comment xml:lang="id">Tabel X-Motif UIL</comment>
- <comment xml:lang="it">Tabella UIL X-Motif</comment>
- <comment xml:lang="ja">X-Motif UIL 表</comment>
- <comment xml:lang="kk">X-Motif UIL кестесі</comment>
- <comment xml:lang="ko">X-Motif UIL 테이블</comment>
- <comment xml:lang="lt">X-Motif UIL lentelė</comment>
- <comment xml:lang="lv">X-Motif UIL tabula</comment>
- <comment xml:lang="ms">Jadual X-Motif UIL</comment>
- <comment xml:lang="nb">X-Motif UIL-tabell</comment>
- <comment xml:lang="nl">X-Motif UIL-tabel</comment>
- <comment xml:lang="nn">X-Motif UIL-tabell</comment>
- <comment xml:lang="oc">taula X-Motif UIL</comment>
- <comment xml:lang="pl">Tabela UIL X-Motif</comment>
- <comment xml:lang="pt">tabela UIL do X-Motif</comment>
- <comment xml:lang="pt_BR">Tabela UIL do X-Motif</comment>
- <comment xml:lang="ro">Tabel X-Motif UIL</comment>
- <comment xml:lang="ru">Таблица UIL X-Motif</comment>
- <comment xml:lang="sk">Tabuľka X-Motif UIL</comment>
- <comment xml:lang="sl">Preglednica X-Motif UIL</comment>
- <comment xml:lang="sq">Tabelë X-Motif UIL</comment>
- <comment xml:lang="sr">Икс-Мотиф УИЛ табела</comment>
- <comment xml:lang="sv">X-Motif UIL-tabell</comment>
- <comment xml:lang="tr">X-Motif UIL tablosu</comment>
- <comment xml:lang="uk">таблиця X-Motif UIL</comment>
- <comment xml:lang="vi">Bảng UIL X-Motif</comment>
- <comment xml:lang="zh_CN">X-Motif UIL 表</comment>
<comment xml:lang="zh_TW">X-Motif UIL 表格</comment>
+ <comment xml:lang="zh_CN">X-Motif UIL 表</comment>
+ <comment xml:lang="vi">Bảng UIL X-Motif</comment>
+ <comment xml:lang="uk">таблиця X-Motif UIL</comment>
+ <comment xml:lang="tr">X-Motif UIL tablosu</comment>
+ <comment xml:lang="sv">X-Motif UIL-tabell</comment>
+ <comment xml:lang="sr">Икс-Мотиф УИЛ табела</comment>
+ <comment xml:lang="sq">tabelë X-Motif UIL</comment>
+ <comment xml:lang="sl">Preglednica X-Motif UIL</comment>
+ <comment xml:lang="si">X-Motif UIL වගුව</comment>
+ <comment xml:lang="sk">Tabuľka X-Motif UIL</comment>
+ <comment xml:lang="ru">Таблица UIL X-Motif</comment>
+ <comment xml:lang="ro">Tabel X-Motif UIL</comment>
+ <comment xml:lang="pt_BR">Tabela UIL do X-Motif</comment>
+ <comment xml:lang="pt">tabela UIL do X-Motif</comment>
+ <comment xml:lang="pl">Tabela UIL X-Motif</comment>
+ <comment xml:lang="oc">taula X-Motif UIL</comment>
+ <comment xml:lang="nn">X-Motif UIL-tabell</comment>
+ <comment xml:lang="nl">X-Motif UIL-tabel</comment>
+ <comment xml:lang="nb">X-Motif UIL-tabell</comment>
+ <comment xml:lang="ms">Jadual X-Motif UIL</comment>
+ <comment xml:lang="lv">X-Motif UIL tabula</comment>
+ <comment xml:lang="lt">X-Motif UIL lentelė</comment>
+ <comment xml:lang="ko">X-Motif UIL 테이블</comment>
+ <comment xml:lang="kk">X-Motif UIL кестесі</comment>
+ <comment xml:lang="ja">X-Motif UIL 表</comment>
+ <comment xml:lang="it">Tabella UIL X-Motif</comment>
+ <comment xml:lang="is">X-Motif UIL tafla</comment>
+ <comment xml:lang="id">Tabel X-Motif UIL</comment>
+ <comment xml:lang="ia">Tabella X-Motif UIL</comment>
+ <comment xml:lang="hu">X-Motif UIL-táblázat</comment>
+ <comment xml:lang="hr">X-Motif UIL tablica</comment>
+ <comment xml:lang="he">טבלה של X-Motif UIL</comment>
+ <comment xml:lang="gl">Táboa de X-Motif UIL</comment>
+ <comment xml:lang="ga">tábla X-Motif UIL</comment>
+ <comment xml:lang="fur">tabele X-Motif UIL</comment>
+ <comment xml:lang="fr">table X-Motif UIL</comment>
+ <comment xml:lang="fo">X-Motif UIL talva</comment>
+ <comment xml:lang="fi">X-Motif UIL -taulukko</comment>
+ <comment xml:lang="eu">X-Motif UIL taula</comment>
+ <comment xml:lang="es">tabla de X-Motif UIL</comment>
+ <comment xml:lang="en_GB">X-Motif UIL table</comment>
+ <comment xml:lang="el">Πίνακας X-Motif UIL</comment>
+ <comment xml:lang="de">X-Motif-UIL-Tabelle</comment>
+ <comment xml:lang="da">X-Motif UIL-tabel</comment>
+ <comment xml:lang="cs">tabulka X-Motif UIL</comment>
+ <comment xml:lang="ca">taula UIL de X-Motif</comment>
+ <comment xml:lang="bg">Таблица — X-Motif UIL</comment>
+ <comment xml:lang="be@latin">Tablica X-Motif UIL</comment>
+ <comment xml:lang="be">табліца X-Motif UIL</comment>
+ <comment xml:lang="ar">جدول X-Motif UIL</comment>
+ <comment xml:lang="af">X-Motif UIL-tabel</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.uil"/>
</mime-type>
<mime-type type="text/x-uri">
- <comment>resource location</comment>
- <comment xml:lang="ar">موقع المورد</comment>
- <comment xml:lang="be@latin">pałažeńnie resursu</comment>
- <comment xml:lang="bg">Местоположение на ресурс</comment>
- <comment xml:lang="ca">localització de recurs</comment>
- <comment xml:lang="cs">umístění prostředku</comment>
- <comment xml:lang="da">resurseplacering</comment>
- <comment xml:lang="de">Ressourcenort</comment>
- <comment xml:lang="el">Τοποθεσία πόρου</comment>
- <comment xml:lang="en_GB">resource location</comment>
- <comment xml:lang="eo">loko de risurco</comment>
- <comment xml:lang="es">ubicación del recurso</comment>
- <comment xml:lang="eu">baliabidearen kokalekua</comment>
- <comment xml:lang="fi">resurssisijainti</comment>
- <comment xml:lang="fo">tilfeingisstaður</comment>
- <comment xml:lang="fr">localisation de ressource</comment>
- <comment xml:lang="ga">suíomh acmhainne</comment>
- <comment xml:lang="gl">localización do recurso</comment>
- <comment xml:lang="he">מיקום של משאב</comment>
- <comment xml:lang="hr">Lokacija resursa</comment>
- <comment xml:lang="hu">erőforrás-hely</comment>
- <comment xml:lang="ia">Loco de ressources</comment>
- <comment xml:lang="id">lokasi sumber daya</comment>
- <comment xml:lang="it">Posizione risorsa</comment>
- <comment xml:lang="ja">リソースの場所</comment>
- <comment xml:lang="kk">ресурс орналасуы</comment>
- <comment xml:lang="ko">자원 위치</comment>
- <comment xml:lang="lt">resurso vieta</comment>
- <comment xml:lang="lv">resursa atrašanās vieta</comment>
- <comment xml:lang="ms">Lokasi sumber</comment>
- <comment xml:lang="nb">ressurslokasjon</comment>
- <comment xml:lang="nl">bronlocatie</comment>
- <comment xml:lang="nn">ressursplassering</comment>
- <comment xml:lang="oc">localizacion de ressorsa</comment>
- <comment xml:lang="pl">Położenie zasobu</comment>
- <comment xml:lang="pt">localização de recurso</comment>
- <comment xml:lang="pt_BR">Localização de recurso</comment>
- <comment xml:lang="ro">locație de resursă</comment>
- <comment xml:lang="ru">Расположение ресурса</comment>
- <comment xml:lang="sk">Umiestnenie zdroja</comment>
- <comment xml:lang="sl">mesto vira</comment>
- <comment xml:lang="sq">Pozicion rezerve</comment>
- <comment xml:lang="sr">путања изворишта</comment>
- <comment xml:lang="sv">resursplats</comment>
- <comment xml:lang="tr">kaynak ayırma</comment>
+ <comment>Resource location</comment>
<comment xml:lang="uk">розташування ресурсу</comment>
- <comment xml:lang="vi">địa điểm tài nguyên</comment>
- <comment xml:lang="zh_CN">资源位置</comment>
- <comment xml:lang="zh_TW">資源位置</comment>
+ <comment xml:lang="sv">Resursplats</comment>
+ <comment xml:lang="ru">Расположение ресурса</comment>
+ <comment xml:lang="pl">Położenie zasobu</comment>
+ <comment xml:lang="it">Posizione risorsa</comment>
+ <comment xml:lang="gl">Localización de recurso</comment>
+ <comment xml:lang="eu">Baliabideen kokalekua</comment>
+ <comment xml:lang="es">ubicación de recurso</comment>
+ <comment xml:lang="de">Ressourcenort</comment>
+ <comment xml:lang="be">размяшчэнне рэсурсу</comment>
<sub-class-of type="text/plain"/>
-
+ <!-- Note: text/uri-list is reserved by the XDND protocol! -->
</mime-type>
<mime-type type="text/x-uuencode">
<comment>uuencoded file</comment>
- <comment xml:lang="ca">fitxer uuencoded</comment>
- <comment xml:lang="cs">soubor kódovaný pomocí uuencoding</comment>
- <comment xml:lang="da">uuencodede-fil</comment>
- <comment xml:lang="de">Datei im uuencode-Format</comment>
- <comment xml:lang="el">Αρχείο κωδικοποιημένο unix σε unix (uuencoded)</comment>
- <comment xml:lang="en_GB">uuencoded file</comment>
- <comment xml:lang="es">archivo codificado con uuencode</comment>
- <comment xml:lang="eu">uuencode-aturiko fitxategia</comment>
- <comment xml:lang="fr">fichier uuencodé</comment>
- <comment xml:lang="ga">comhad uuencoded</comment>
- <comment xml:lang="gl">Ficheiro uuencoded</comment>
- <comment xml:lang="he">קובץ בקידוד uu</comment>
- <comment xml:lang="hr">uuencoded datoteka</comment>
- <comment xml:lang="hu">uuencode-olt fájl</comment>
- <comment xml:lang="ia">File in uuencode</comment>
- <comment xml:lang="id">Berkas ter-uuencode</comment>
- <comment xml:lang="it">File uuencoded</comment>
- <comment xml:lang="ja">未エンコードファイル</comment>
- <comment xml:lang="kk">uuencode кодталған файлы</comment>
- <comment xml:lang="ko">uuencoded 파일</comment>
- <comment xml:lang="lv">uu kodējuma datne</comment>
- <comment xml:lang="oc">fichièr uuencodat</comment>
- <comment xml:lang="pl">Plik zakodowany za pomocą uuencode</comment>
- <comment xml:lang="pt">ficheiro uuencoded</comment>
- <comment xml:lang="pt_BR">Arquivo codificado UUE</comment>
- <comment xml:lang="ru">Файл, кодированный uuencode</comment>
- <comment xml:lang="sk">Súbor v kódovaní uuencode</comment>
- <comment xml:lang="sl">Datoteka uuencode</comment>
- <comment xml:lang="sr">уукодирана датотека</comment>
- <comment xml:lang="sv">uuencode-fil</comment>
- <comment xml:lang="tr">uuencoded dosyası</comment>
- <comment xml:lang="uk">файл даних у форматі UUE</comment>
- <comment xml:lang="zh_CN">Uuencode 文件</comment>
<comment xml:lang="zh_TW">uuencoded 檔</comment>
+ <comment xml:lang="zh_CN">Uuencode 文件</comment>
+ <comment xml:lang="uk">файл даних у форматі UUE</comment>
+ <comment xml:lang="tr">uuencoded dosyası</comment>
+ <comment xml:lang="sv">uuencode-fil</comment>
+ <comment xml:lang="sr">уукодирана датотека</comment>
+ <comment xml:lang="sl">Datoteka uuencode</comment>
+ <comment xml:lang="si">uuencoded ගොනුව</comment>
+ <comment xml:lang="sk">Súbor v kódovaní uuencode</comment>
+ <comment xml:lang="ru">Файл, кодированный uuencode</comment>
+ <comment xml:lang="pt_BR">Arquivo codificado UUE</comment>
+ <comment xml:lang="pt">ficheiro uuencoded</comment>
+ <comment xml:lang="pl">Plik zakodowany za pomocą uuencode</comment>
+ <comment xml:lang="oc">fichièr uuencodat</comment>
+ <comment xml:lang="nl">uuencoded bestand</comment>
+ <comment xml:lang="lv">uu kodējuma datne</comment>
+ <comment xml:lang="ko">uuencoded 파일</comment>
+ <comment xml:lang="kk">uuencode кодталған файлы</comment>
+ <comment xml:lang="ja">未エンコードファイル</comment>
+ <comment xml:lang="it">File uuencoded</comment>
+ <comment xml:lang="is">uuencoded skrá</comment>
+ <comment xml:lang="id">berkas ter-uuencode</comment>
+ <comment xml:lang="ia">File in uuencode</comment>
+ <comment xml:lang="hu">uuencode-olt fájl</comment>
+ <comment xml:lang="hr">uuencoded datoteka</comment>
+ <comment xml:lang="he">קובץ בקידוד uu</comment>
+ <comment xml:lang="gl">Ficheiro uuencoded</comment>
+ <comment xml:lang="ga">comhad uuencoded</comment>
+ <comment xml:lang="fur">file codificât cun uuencode</comment>
+ <comment xml:lang="fr">fichier uuencodé</comment>
+ <comment xml:lang="fi">uuenkoodattu tiedosto</comment>
+ <comment xml:lang="eu">uuencode-aturiko fitxategia</comment>
+ <comment xml:lang="es">archivo codificado con uuencode</comment>
+ <comment xml:lang="en_GB">uuencoded file</comment>
+ <comment xml:lang="el">Αρχείο κωδικοποιημένο unix σε unix (uuencoded)</comment>
+ <comment xml:lang="de">Datei im uuencode-Format</comment>
+ <comment xml:lang="da">uuencodede-fil</comment>
+ <comment xml:lang="cs">soubor kódovaný pomocí uuencoding</comment>
+ <comment xml:lang="ca">fitxer uuencoded</comment>
+ <comment xml:lang="bg">Файл — кодиран с uuencode</comment>
+ <comment xml:lang="be">файл, закадаваны uuencode</comment>
+ <comment xml:lang="ar">ملف uuencoded</comment>
+ <comment xml:lang="af">uu-geënkodeerde lêer</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.uue"/>
- <magic priority="50">
- <match value="begin " type="string" offset="0"/>
+ <magic>
+ <match type="string" value="begin " offset="0"/>
</magic>
<alias type="zz-application/zz-winassoc-uu"/>
</mime-type>
+ <mime-type type="text/x-basic">
+ <comment>BASIC program</comment>
+ <comment xml:lang="uk">програма BASIC</comment>
+ <comment xml:lang="sv">BASIC-program</comment>
+ <comment xml:lang="ru">Программа BASIC</comment>
+ <comment xml:lang="pl">Program BASIC</comment>
+ <comment xml:lang="es">programa en BASIC</comment>
+ <comment xml:lang="de">BASIC-Programm</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-script"/>
+ <glob pattern="*.bas"/>
+ </mime-type>
+ <mime-type type="text/x-vb">
+ <comment>Visual Basic .NET source code</comment>
+ <comment xml:lang="uk">початковий код Visual Basic .NET</comment>
+ <comment xml:lang="sv">Visual Basic .NET-källkod</comment>
+ <comment xml:lang="ru">Исходный код Visual Basic .NET</comment>
+ <comment xml:lang="pl">Kod źródłowy Visual Basic .NET</comment>
+ <comment xml:lang="es">código fuente en Visual Basic .NET</comment>
+ <comment xml:lang="de">Visual-Basic-.NET-Quelltext</comment>
+ <sub-class-of type="text/plain"/>
+ <magic>
+ <match type="string" value="Imports" offset="0"/>
+ <match type="string" value="Module" offset="0"/>
+ <match type="string" value="REM" offset="0"/>
+ </magic>
+ <glob pattern="*.vb"/>
+ </mime-type>
+ <mime-type type="text/vbscript">
+ <comment>VBScript program</comment>
+ <comment xml:lang="zh_TW">VBScript 程式</comment>
+ <comment xml:lang="zh_CN">VBScript 程序</comment>
+ <comment xml:lang="uk">програма мовою VBScript</comment>
+ <comment xml:lang="tr">VBScript programı</comment>
+ <comment xml:lang="sv">VBScript-program</comment>
+ <comment xml:lang="sl">Programska datoteka VBScript</comment>
+ <comment xml:lang="si">VBScript වැඩසටහන</comment>
+ <comment xml:lang="ru">Программа VBScript</comment>
+ <comment xml:lang="pt_BR">Programa VBScript</comment>
+ <comment xml:lang="pl">Pogram VBScript</comment>
+ <comment xml:lang="oc">programa VBScript</comment>
+ <comment xml:lang="nl">VBScript-programma</comment>
+ <comment xml:lang="ko">VBScript 프로그램</comment>
+ <comment xml:lang="kk">VBScript бағдарламасы</comment>
+ <comment xml:lang="ja">VBScript プログラム</comment>
+ <comment xml:lang="it">Programma VBScript</comment>
+ <comment xml:lang="is">VBScript forrit</comment>
+ <comment xml:lang="id">program VBScript</comment>
+ <comment xml:lang="hu">VBScript program</comment>
+ <comment xml:lang="hr">VBScript program</comment>
+ <comment xml:lang="he">תכנית VBScript</comment>
+ <comment xml:lang="gl">Programa VBScript</comment>
+ <comment xml:lang="fr">programme VBScript</comment>
+ <comment xml:lang="fi">VBScript-ohjelma</comment>
+ <comment xml:lang="eu">VBScript programa</comment>
+ <comment xml:lang="es">programa en VBScript</comment>
+ <comment xml:lang="en_GB">VBScript program</comment>
+ <comment xml:lang="de">VBScript-Programm</comment>
+ <comment xml:lang="da">VBScript-program</comment>
+ <comment xml:lang="ca">programa VBScript</comment>
+ <comment xml:lang="be">праграма VBScript</comment>
+ <comment xml:lang="ar">برنامج في بي سكريبت</comment>
+ <alias type="text/vbs"/>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-script"/>
+ <glob pattern="*.vbs"/>
+ </mime-type>
+ <mime-type type="text/vbscript.encode">
+ <comment>Encoded VBScript program</comment>
+ <comment xml:lang="uk">кодована програма VBScript</comment>
+ <comment xml:lang="sv">Kodat VBScript-program</comment>
+ <comment xml:lang="ru">Зашифрованная программа на VBScript</comment>
+ <comment xml:lang="pl">Zakodowany program VBScript</comment>
+ <comment xml:lang="es">Programa en VBScript codificado</comment>
+ <comment xml:lang="de">Verschlüsseltes VBScript-Programm</comment>
+ <sub-class-of type="application/x-executable"/>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-script"/>
+ <magic>
+ <match type="string" value="#@~^" offset="0"/>
+ </magic>
+ <glob pattern="*.vbe"/>
+ </mime-type>
<mime-type type="text/x-xmi">
<comment>XMI file</comment>
- <comment xml:lang="ar">ملف XMI</comment>
- <comment xml:lang="be@latin">Fajł XMI</comment>
- <comment xml:lang="bg">Файл — XMI</comment>
- <comment xml:lang="ca">fitxer XMI</comment>
- <comment xml:lang="cs">soubor XMI</comment>
- <comment xml:lang="da">XMI-fil</comment>
- <comment xml:lang="de">XMI-Datei</comment>
- <comment xml:lang="el">Αρχείο XML</comment>
- <comment xml:lang="en_GB">XMI file</comment>
- <comment xml:lang="eo">XMI-dosiero</comment>
- <comment xml:lang="es">archivo XMI</comment>
- <comment xml:lang="eu">XMI fitxategia</comment>
- <comment xml:lang="fi">XMI-tiedosto</comment>
- <comment xml:lang="fo">XMI fíla</comment>
- <comment xml:lang="fr">fichier XMI</comment>
- <comment xml:lang="ga">comhad XMI</comment>
- <comment xml:lang="gl">ficheiro XMI</comment>
- <comment xml:lang="he">קובץ XMI</comment>
- <comment xml:lang="hr">XMI datoteka</comment>
- <comment xml:lang="hu">XMI fájl</comment>
- <comment xml:lang="ia">File XMI</comment>
- <comment xml:lang="id">Berkas XMI</comment>
- <comment xml:lang="it">File XMI</comment>
- <comment xml:lang="ja">XMI ファイル</comment>
- <comment xml:lang="kk">XMI файлы</comment>
- <comment xml:lang="ko">XMI 파일</comment>
- <comment xml:lang="lt">XMI failas</comment>
- <comment xml:lang="lv">XMI datne</comment>
- <comment xml:lang="nb">XMI-fil</comment>
- <comment xml:lang="nl">XMI-bestand</comment>
- <comment xml:lang="nn">XMI-fil</comment>
- <comment xml:lang="oc">fichièr XMI</comment>
- <comment xml:lang="pl">Plik XMI</comment>
- <comment xml:lang="pt">ficheiro XMI</comment>
- <comment xml:lang="pt_BR">Arquivo XMI</comment>
- <comment xml:lang="ro">Fișier XMI</comment>
- <comment xml:lang="ru">Файл XMI</comment>
- <comment xml:lang="sk">Súbor XMI</comment>
- <comment xml:lang="sl">Datoteka XMI</comment>
- <comment xml:lang="sq">File XMI</comment>
- <comment xml:lang="sr">ИксМИ датотека</comment>
- <comment xml:lang="sv">XMI-fil</comment>
- <comment xml:lang="tr">XMI dosyası</comment>
- <comment xml:lang="uk">файл XMI</comment>
- <comment xml:lang="vi">Tập tin XMI</comment>
- <comment xml:lang="zh_CN">XMI 文件</comment>
<comment xml:lang="zh_TW">XMI 檔</comment>
+ <comment xml:lang="zh_CN">XMI 文件</comment>
+ <comment xml:lang="vi">Tập tin XMI</comment>
+ <comment xml:lang="uk">файл XMI</comment>
+ <comment xml:lang="tr">XMI dosyası</comment>
+ <comment xml:lang="sv">XMI-fil</comment>
+ <comment xml:lang="sr">ИксМИ датотека</comment>
+ <comment xml:lang="sq">kartelë XMI</comment>
+ <comment xml:lang="sl">Datoteka XMI</comment>
+ <comment xml:lang="si">XMI ගොනුව</comment>
+ <comment xml:lang="sk">Súbor XMI</comment>
+ <comment xml:lang="ru">Файл XMI</comment>
+ <comment xml:lang="ro">Fișier XMI</comment>
+ <comment xml:lang="pt_BR">Arquivo XMI</comment>
+ <comment xml:lang="pt">ficheiro XMI</comment>
+ <comment xml:lang="pl">Plik XMI</comment>
+ <comment xml:lang="oc">fichièr XMI</comment>
+ <comment xml:lang="nn">XMI-fil</comment>
+ <comment xml:lang="nl">XMI-bestand</comment>
+ <comment xml:lang="nb">XMI-fil</comment>
+ <comment xml:lang="lv">XMI datne</comment>
+ <comment xml:lang="lt">XMI failas</comment>
+ <comment xml:lang="ko">XMI 파일</comment>
+ <comment xml:lang="kk">XMI файлы</comment>
+ <comment xml:lang="ja">XMI ファイル</comment>
+ <comment xml:lang="it">File XMI</comment>
+ <comment xml:lang="is">XMI-skrá</comment>
+ <comment xml:lang="id">Berkas XMI</comment>
+ <comment xml:lang="ia">File XMI</comment>
+ <comment xml:lang="hu">XMI fájl</comment>
+ <comment xml:lang="hr">XMI datoteka</comment>
+ <comment xml:lang="he">קובץ XMI</comment>
+ <comment xml:lang="gl">ficheiro XMI</comment>
+ <comment xml:lang="ga">comhad XMI</comment>
+ <comment xml:lang="fur">file XMI</comment>
+ <comment xml:lang="fr">fichier XMI</comment>
+ <comment xml:lang="fo">XMI fíla</comment>
+ <comment xml:lang="fi">XMI-tiedosto</comment>
+ <comment xml:lang="eu">XMI fitxategia</comment>
+ <comment xml:lang="es">archivo XMI</comment>
+ <comment xml:lang="eo">XMI-dosiero</comment>
+ <comment xml:lang="en_GB">XMI file</comment>
+ <comment xml:lang="el">Αρχείο XML</comment>
+ <comment xml:lang="de">XMI-Datei</comment>
+ <comment xml:lang="da">XMI-fil</comment>
+ <comment xml:lang="cs">soubor XMI</comment>
+ <comment xml:lang="ca">fitxer XMI</comment>
+ <comment xml:lang="bg">Файл — XMI</comment>
+ <comment xml:lang="be@latin">Fajł XMI</comment>
+ <comment xml:lang="be">файл XMI</comment>
+ <comment xml:lang="ar">ملف XMI</comment>
+ <comment xml:lang="af">XMI-lêer</comment>
<acronym>XMI</acronym>
<expanded-acronym>XML Metadata Interchange</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -36953,53 +39350,58 @@
</mime-type>
<mime-type type="text/x-xslfo">
<comment>XSL FO file</comment>
- <comment xml:lang="ar">ملف XSL FO</comment>
- <comment xml:lang="be@latin">Fajł XSL FO</comment>
- <comment xml:lang="bg">Форматиращ файл — XSL FO</comment>
- <comment xml:lang="ca">fitxer FO XSL</comment>
- <comment xml:lang="cs">soubor XSL FO</comment>
- <comment xml:lang="da">XML FO-fil</comment>
- <comment xml:lang="de">XSL-FO-Datei</comment>
- <comment xml:lang="el">Αρχείο XSL FO</comment>
- <comment xml:lang="en_GB">XSL FO file</comment>
- <comment xml:lang="eo">XSL-FO-dosiero</comment>
- <comment xml:lang="es">archivo XSL FO</comment>
- <comment xml:lang="eu">XSL FO fitxategia</comment>
- <comment xml:lang="fi">XSL FO -tiedosto</comment>
- <comment xml:lang="fo">XSL FO fíla</comment>
- <comment xml:lang="fr">fichier XSL FO</comment>
- <comment xml:lang="ga">comhad XSL FO</comment>
- <comment xml:lang="gl">ficheiro XSL FO</comment>
- <comment xml:lang="he">קובץ XSL FO</comment>
- <comment xml:lang="hr">XSL FO datoteka</comment>
- <comment xml:lang="hu">XSL FO fájl</comment>
- <comment xml:lang="ia">File XSL FO</comment>
- <comment xml:lang="id">Berkas XSL FO</comment>
- <comment xml:lang="it">File XSL FO</comment>
- <comment xml:lang="ja">XSL FO ファイル</comment>
- <comment xml:lang="kk">XSL FO файлы</comment>
- <comment xml:lang="ko">XSL 포매팅 개체 파일</comment>
- <comment xml:lang="lt">XSL FO failas</comment>
- <comment xml:lang="lv">XSL FO datne</comment>
- <comment xml:lang="nb">FO-fil for XSL</comment>
- <comment xml:lang="nl">XSL FO-bestand</comment>
- <comment xml:lang="nn">XSL FO-fil</comment>
- <comment xml:lang="oc">fichièr XSL FO</comment>
- <comment xml:lang="pl">Plik XSL FO</comment>
- <comment xml:lang="pt">ficheiro XSL FO</comment>
- <comment xml:lang="pt_BR">Arquivo XSL FO</comment>
- <comment xml:lang="ro">Fișier XSL FO</comment>
- <comment xml:lang="ru">Файл XSL FO</comment>
- <comment xml:lang="sk">Súbor XSL FO</comment>
- <comment xml:lang="sl">Datoteka XSL FO</comment>
- <comment xml:lang="sq">File XSL FO</comment>
- <comment xml:lang="sr">ИксСЛ ФО датотека</comment>
- <comment xml:lang="sv">XSL FO-fil</comment>
- <comment xml:lang="tr">XSL FO dosyası</comment>
- <comment xml:lang="uk">файл XSL FO</comment>
- <comment xml:lang="vi">Tập tin FO của XSL (XFO)</comment>
- <comment xml:lang="zh_CN">XSL 格式化对象文件</comment>
<comment xml:lang="zh_TW">XSL FO 檔</comment>
+ <comment xml:lang="zh_CN">XSL 格式化对象文件</comment>
+ <comment xml:lang="vi">Tập tin FO của XSL (XFO)</comment>
+ <comment xml:lang="uk">файл XSL FO</comment>
+ <comment xml:lang="tr">XSL FO dosyası</comment>
+ <comment xml:lang="sv">XSL FO-fil</comment>
+ <comment xml:lang="sr">ИксСЛ ФО датотека</comment>
+ <comment xml:lang="sq">kartelë XSL FO</comment>
+ <comment xml:lang="sl">Datoteka XSL FO</comment>
+ <comment xml:lang="si">XSL FO ගොනුව</comment>
+ <comment xml:lang="sk">Súbor XSL FO</comment>
+ <comment xml:lang="ru">Файл XSL FO</comment>
+ <comment xml:lang="ro">Fișier XSL FO</comment>
+ <comment xml:lang="pt_BR">Arquivo XSL FO</comment>
+ <comment xml:lang="pt">ficheiro XSL FO</comment>
+ <comment xml:lang="pl">Plik XSL FO</comment>
+ <comment xml:lang="oc">fichièr XSL FO</comment>
+ <comment xml:lang="nn">XSL FO-fil</comment>
+ <comment xml:lang="nl">XSL FO-bestand</comment>
+ <comment xml:lang="nb">FO-fil for XSL</comment>
+ <comment xml:lang="lv">XSL FO datne</comment>
+ <comment xml:lang="lt">XSL FO failas</comment>
+ <comment xml:lang="ko">XSL 포매팅 개체 파일</comment>
+ <comment xml:lang="kk">XSL FO файлы</comment>
+ <comment xml:lang="ja">XSL FO ファイル</comment>
+ <comment xml:lang="it">File XSL FO</comment>
+ <comment xml:lang="is">XSL FO skrá</comment>
+ <comment xml:lang="id">Berkas XSL FO</comment>
+ <comment xml:lang="ia">File XSL FO</comment>
+ <comment xml:lang="hu">XSL FO fájl</comment>
+ <comment xml:lang="hr">XSL FO datoteka</comment>
+ <comment xml:lang="he">קובץ XSL FO</comment>
+ <comment xml:lang="gl">ficheiro XSL FO</comment>
+ <comment xml:lang="ga">comhad XSL FO</comment>
+ <comment xml:lang="fur">file XSL FO</comment>
+ <comment xml:lang="fr">fichier XSL FO</comment>
+ <comment xml:lang="fo">XSL FO fíla</comment>
+ <comment xml:lang="fi">XSL FO -tiedosto</comment>
+ <comment xml:lang="eu">XSL FO fitxategia</comment>
+ <comment xml:lang="es">archivo XSL FO</comment>
+ <comment xml:lang="eo">XSL-FO-dosiero</comment>
+ <comment xml:lang="en_GB">XSL FO file</comment>
+ <comment xml:lang="el">Αρχείο XSL FO</comment>
+ <comment xml:lang="de">XSL-FO-Datei</comment>
+ <comment xml:lang="da">XML FO-fil</comment>
+ <comment xml:lang="cs">soubor XSL FO</comment>
+ <comment xml:lang="ca">fitxer FO XSL</comment>
+ <comment xml:lang="bg">Форматиращ файл — XSL FO</comment>
+ <comment xml:lang="be@latin">Fajł XSL FO</comment>
+ <comment xml:lang="be">файл XSL FO</comment>
+ <comment xml:lang="ar">ملف XSL FO</comment>
+ <comment xml:lang="af">XSL FO-lêer</comment>
<acronym>XSL FO</acronym>
<expanded-acronym>XSL Formatting Objects</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -37009,71 +39411,76 @@
</mime-type>
<mime-type type="text/x-iptables">
<comment>iptables configuration file</comment>
- <comment xml:lang="ar">ملف تضبيط iptables</comment>
- <comment xml:lang="ast">ficheru de configuración d'iptables</comment>
- <comment xml:lang="be@latin">kanfihuracyjny fajł iptables</comment>
- <comment xml:lang="bg">Настройки за iptables</comment>
- <comment xml:lang="ca">fitxer de configuració d'iptables</comment>
- <comment xml:lang="cs">soubor nastavení iptables</comment>
- <comment xml:lang="da">iptableskonfigurationsfil</comment>
- <comment xml:lang="de">iptables-Konfigurationsdatei</comment>
- <comment xml:lang="el">Αρχείο ρυθμίσεων iptables</comment>
- <comment xml:lang="en_GB">iptables configuration file</comment>
- <comment xml:lang="es">archivo de configuración de iptables</comment>
- <comment xml:lang="eu">iptables konfigurazio-fitxategia</comment>
- <comment xml:lang="fi">iptables-asetustiedosto</comment>
- <comment xml:lang="fo">iptables samansetingarfíla</comment>
- <comment xml:lang="fr">fichier de configuration iptables</comment>
- <comment xml:lang="ga">comhad cumraíochta iptables</comment>
- <comment xml:lang="gl">ficheiro de configuración de iptables</comment>
- <comment xml:lang="he">קובץ הגדרה של iptables</comment>
- <comment xml:lang="hr">iptables datoteka podešavanja</comment>
- <comment xml:lang="hu">iptables beállítófájl</comment>
- <comment xml:lang="ia">File de configuration IPTables</comment>
- <comment xml:lang="id">berkas konfigurasi iptables</comment>
- <comment xml:lang="it">File configurazione iptables</comment>
- <comment xml:lang="ja">iptables 設定ファイル</comment>
- <comment xml:lang="kk">iptables баптаулар файлы</comment>
- <comment xml:lang="ko">iptables 설정 파일</comment>
- <comment xml:lang="lt">iptables konfigūracijos failas</comment>
- <comment xml:lang="lv">iptables konfigurācijas datne</comment>
- <comment xml:lang="nb">konfigurasjonsfil for iptables</comment>
- <comment xml:lang="nl">iptables-configuratiebestand</comment>
- <comment xml:lang="nn">iptables oppsettfil</comment>
- <comment xml:lang="oc">fichièr de configuracion iptables</comment>
- <comment xml:lang="pl">Plik konfiguracji iptables</comment>
- <comment xml:lang="pt">ficheiro de configuração iptables</comment>
- <comment xml:lang="pt_BR">Arquivo de configuração do iptables</comment>
- <comment xml:lang="ro">fișier configurare iptables</comment>
- <comment xml:lang="ru">Файл настроек iptables</comment>
- <comment xml:lang="sk">Súbor nastavení iptables</comment>
- <comment xml:lang="sl">nastavitvena datoteka iptables</comment>
- <comment xml:lang="sq">File konfigurimi iptables</comment>
- <comment xml:lang="sr">датотека подешавања иптабела</comment>
- <comment xml:lang="sv">iptables-konfigurationsfil</comment>
- <comment xml:lang="tr">iptables yapılandırma dosyası</comment>
- <comment xml:lang="uk">файл налаштувань iptables</comment>
- <comment xml:lang="vi">tập tin cấu hình iptables</comment>
- <comment xml:lang="zh_CN">iptables 防火墙配置文件</comment>
<comment xml:lang="zh_TW">iptables 組態檔</comment>
+ <comment xml:lang="zh_CN">iptables 防火墙配置文件</comment>
+ <comment xml:lang="vi">tập tin cấu hình iptables</comment>
+ <comment xml:lang="uk">файл налаштувань iptables</comment>
+ <comment xml:lang="tr">iptables yapılandırma dosyası</comment>
+ <comment xml:lang="sv">iptables-konfigurationsfil</comment>
+ <comment xml:lang="sr">датотека подешавања иптабела</comment>
+ <comment xml:lang="sq">kartelë formësimi iptables</comment>
+ <comment xml:lang="sl">nastavitvena datoteka iptables</comment>
+ <comment xml:lang="si">iptables වින්‍යාස ගොනුව</comment>
+ <comment xml:lang="sk">Súbor nastavení iptables</comment>
+ <comment xml:lang="ru">Файл настроек iptables</comment>
+ <comment xml:lang="ro">fișier configurare iptables</comment>
+ <comment xml:lang="pt_BR">Arquivo de configuração do iptables</comment>
+ <comment xml:lang="pt">ficheiro de configuração iptables</comment>
+ <comment xml:lang="pl">Plik konfiguracji iptables</comment>
+ <comment xml:lang="oc">fichièr de configuracion iptables</comment>
+ <comment xml:lang="nn">iptables oppsettfil</comment>
+ <comment xml:lang="nl">iptables-configuratiebestand</comment>
+ <comment xml:lang="nb">konfigurasjonsfil for iptables</comment>
+ <comment xml:lang="lv">iptables konfigurācijas datne</comment>
+ <comment xml:lang="lt">iptables konfigūracijos failas</comment>
+ <comment xml:lang="ko">iptables 설정 파일</comment>
+ <comment xml:lang="kk">iptables баптаулар файлы</comment>
+ <comment xml:lang="ja">iptables 設定ファイル</comment>
+ <comment xml:lang="it">File configurazione iptables</comment>
+ <comment xml:lang="is">iptables stillingaskrá</comment>
+ <comment xml:lang="id">berkas konfigurasi iptables</comment>
+ <comment xml:lang="ia">File de configuration IPTables</comment>
+ <comment xml:lang="hu">iptables beállítófájl</comment>
+ <comment xml:lang="hr">iptables datoteka podešavanja</comment>
+ <comment xml:lang="he">קובץ הגדרה של iptables</comment>
+ <comment xml:lang="gl">ficheiro de configuración de iptables</comment>
+ <comment xml:lang="ga">comhad cumraíochta iptables</comment>
+ <comment xml:lang="fur">file di configurazion di iptables</comment>
+ <comment xml:lang="fr">fichier de configuration iptables</comment>
+ <comment xml:lang="fo">iptables samansetingarfíla</comment>
+ <comment xml:lang="fi">iptables-asetustiedosto</comment>
+ <comment xml:lang="eu">iptables konfigurazio-fitxategia</comment>
+ <comment xml:lang="es">archivo de configuración de iptables</comment>
+ <comment xml:lang="en_GB">iptables configuration file</comment>
+ <comment xml:lang="el">Αρχείο ρυθμίσεων iptables</comment>
+ <comment xml:lang="de">iptables-Konfigurationsdatei</comment>
+ <comment xml:lang="da">iptableskonfigurationsfil</comment>
+ <comment xml:lang="cs">soubor nastavení iptables</comment>
+ <comment xml:lang="ca">fitxer de configuració d'iptables</comment>
+ <comment xml:lang="bg">Настройки за iptables</comment>
+ <comment xml:lang="be@latin">kanfihuracyjny fajł iptables</comment>
+ <comment xml:lang="be">файл канфігурацыі iptables</comment>
+ <comment xml:lang="ast">ficheru de configuración d'iptables</comment>
+ <comment xml:lang="ar">ملف إعداد iptables</comment>
+ <comment xml:lang="af">iptables-opstellingslêer</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="/etc/sysconfig/iptables" type="string" offset="0:256"/>
- <match value="*filter" type="string" offset="0:256">
- <match value=":INPUT" type="string" offset="0:256">
- <match value=":FORWARD" type="string" offset="0:256">
- <match value=":OUTPUT" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="/etc/sysconfig/iptables" offset="0:256"/>
+ <match type="string" value="*filter" offset="0:256">
+ <match type="string" value=":INPUT" offset="0:256">
+ <match type="string" value=":FORWARD" offset="0:256">
+ <match type="string" value=":OUTPUT" offset="0:256"/>
</match>
</match>
</match>
- <match value="-A INPUT" type="string" offset="0:256">
- <match value="-A FORWARD" type="string" offset="0:256">
- <match value="-A OUTPUT" type="string" offset="0:256"/>
+ <match type="string" value="-A INPUT" offset="0:256">
+ <match type="string" value="-A FORWARD" offset="0:256">
+ <match type="string" value="-A OUTPUT" offset="0:256"/>
</match>
</match>
- <match value="-P INPUT" type="string" offset="0:256">
- <match value="-P FORWARD" type="string" offset="0:256">
- <match value="-P OUTPUT" type="string" offset="0:256"/>
+ <match type="string" value="-P INPUT" offset="0:256">
+ <match type="string" value="-P FORWARD" offset="0:256">
+ <match type="string" value="-P OUTPUT" offset="0:256"/>
</match>
</match>
</magic>
@@ -37081,95 +39488,92 @@
</mime-type>
<mime-type type="text/x-dbus-service">
<comment>D-Bus service file</comment>
- <comment xml:lang="ca">fitxer de servei de D-Bus</comment>
- <comment xml:lang="cs">soubor služby D-Bus</comment>
- <comment xml:lang="de">D-Bus-Dienstdatei</comment>
- <comment xml:lang="en_GB">D-Bus service file</comment>
- <comment xml:lang="es">archivo de servicio de D-Bus</comment>
- <comment xml:lang="eu">D-Bus zerbitzu fitxategia</comment>
- <comment xml:lang="fi">D-Bus-palvelutiedosto</comment>
- <comment xml:lang="fr">fichier de service D-Bus</comment>
- <comment xml:lang="ga">comhad seirbhíse D-Bus</comment>
- <comment xml:lang="hr">Datoteka D-Bus usluge</comment>
- <comment xml:lang="hu">D-Bus szolgáltatás fájl</comment>
- <comment xml:lang="id">berkas layanan D-Bus</comment>
- <comment xml:lang="it">File servizio D-Bus</comment>
- <comment xml:lang="kk">D-Bus қызметтік файлы</comment>
- <comment xml:lang="ko">D-Bus 서비스 파일</comment>
- <comment xml:lang="pl">Plik usługi D-Bus</comment>
- <comment xml:lang="pt_BR">Arquivo de serviço do D-Bus</comment>
- <comment xml:lang="ru">Файл службы D-Bus</comment>
- <comment xml:lang="sk">Súbor služby D-Bus</comment>
- <comment xml:lang="sr">датотека услуге Д-сабирнице</comment>
- <comment xml:lang="sv">D-BUS-tjänstfil</comment>
- <comment xml:lang="tr">D-Bus hizmeti dosyası</comment>
- <comment xml:lang="uk">файл служби D-Bus</comment>
- <comment xml:lang="zh_CN">D-Bus 服务文件</comment>
<comment xml:lang="zh_TW">D-Bus 服務檔</comment>
+ <comment xml:lang="zh_CN">D-Bus 服务文件</comment>
+ <comment xml:lang="uk">файл служби D-Bus</comment>
+ <comment xml:lang="tr">D-Bus hizmeti dosyası</comment>
+ <comment xml:lang="sv">D-BUS-tjänstfil</comment>
+ <comment xml:lang="sr">датотека услуге Д-сабирнице</comment>
+ <comment xml:lang="sq">kartelë shërbimi D-Bus</comment>
+ <comment xml:lang="si">D-බස් සේවා ගොනුව</comment>
+ <comment xml:lang="sk">Súbor služby D-Bus</comment>
+ <comment xml:lang="ru">Файл службы D-Bus</comment>
+ <comment xml:lang="pt_BR">Arquivo de serviço do D-Bus</comment>
+ <comment xml:lang="pl">Plik usługi D-Bus</comment>
+ <comment xml:lang="nl">D-Bus-servicebestand</comment>
+ <comment xml:lang="ko">D-Bus 서비스 파일</comment>
+ <comment xml:lang="kk">D-Bus қызметтік файлы</comment>
+ <comment xml:lang="ja">D-Bus サービスファイル</comment>
+ <comment xml:lang="it">File servizio D-Bus</comment>
+ <comment xml:lang="is">D-Bus þjónustuskrá</comment>
+ <comment xml:lang="id">Berkas layanan D-Bus</comment>
+ <comment xml:lang="hu">D-Bus szolgáltatás fájl</comment>
+ <comment xml:lang="hr">Datoteka D-Bus usluge</comment>
+ <comment xml:lang="he">קובץ שירות D-Bus</comment>
+ <comment xml:lang="gl">Ficheiro de servizo D-Bus</comment>
+ <comment xml:lang="ga">comhad seirbhíse D-Bus</comment>
+ <comment xml:lang="fur">file di servizi D-Bus</comment>
+ <comment xml:lang="fr">fichier de service D-Bus</comment>
+ <comment xml:lang="fi">D-Bus-palvelutiedosto</comment>
+ <comment xml:lang="eu">D-Bus zerbitzu fitxategia</comment>
+ <comment xml:lang="es">archivo de servicio de D-Bus</comment>
+ <comment xml:lang="en_GB">D-Bus service file</comment>
+ <comment xml:lang="de">D-Bus-Dienstdatei</comment>
+ <comment xml:lang="da">D-Bus-tjenestefil</comment>
+ <comment xml:lang="cs">soubor služby D-Bus</comment>
+ <comment xml:lang="ca">fitxer de servei de D-Bus</comment>
+ <comment xml:lang="bg">Услуга — D-Bus</comment>
+ <comment xml:lang="be">файл сэрвісу D-Bus</comment>
+ <comment xml:lang="ar">ملف خدمة دي-باص</comment>
+ <comment xml:lang="af">D-Bus-dienslêer</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="\n[D-BUS Service]\n" type="string" offset="0:256"/>
- <match value="[D-BUS Service]\n" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\n[D-BUS Service]\n" offset="0:256"/>
+ <match type="string" value="[D-BUS Service]\n" offset="0"/>
</magic>
<glob pattern="*.service"/>
</mime-type>
<mime-type type="text/x-systemd-unit">
- <comment>systemd unit file</comment>
- <comment xml:lang="ast">ficheru d'unidaes de systemd</comment>
- <comment xml:lang="ca">fitxer d'unitat de systemd</comment>
- <comment xml:lang="cs">jednotkový soubor systemd</comment>
- <comment xml:lang="de">systemd-Einheitsdatei</comment>
- <comment xml:lang="en_GB">systemd unit file</comment>
- <comment xml:lang="es">archivo de unidad de systemd</comment>
- <comment xml:lang="eu">systemd unitate fitxategia</comment>
- <comment xml:lang="fi">systemd-yksikkötiedosto</comment>
- <comment xml:lang="fr">fichier d'unité systemd</comment>
- <comment xml:lang="ga">comhad aonaid systemd</comment>
- <comment xml:lang="hr">Datoteka systemd jedinice</comment>
- <comment xml:lang="hu">systemd egység fájl</comment>
- <comment xml:lang="id">berkas unit systemd</comment>
- <comment xml:lang="it">File unità systemd</comment>
- <comment xml:lang="kk">systemd юнит файлы</comment>
- <comment xml:lang="ko">systemd 유닛 파일</comment>
- <comment xml:lang="pl">Plik jednostki systemd</comment>
- <comment xml:lang="pt_BR">Arquivo de unit do systemd</comment>
- <comment xml:lang="ru">Модульный файл Systemd</comment>
- <comment xml:lang="sk">Súbor jednotky systemd</comment>
- <comment xml:lang="sr">датотека јединице системд-а</comment>
- <comment xml:lang="sv">systemd-enhetsfil</comment>
- <comment xml:lang="tr">systemd birim dosyası</comment>
+ <comment>Systemd unit file</comment>
<comment xml:lang="uk">файл модуля systemd</comment>
- <comment xml:lang="zh_CN">systemd 单元文件</comment>
- <comment xml:lang="zh_TW">systemd 單位檔</comment>
+ <comment xml:lang="sv">Systemd-enhetsfil</comment>
+ <comment xml:lang="ru">Модульный файл Systemd</comment>
+ <comment xml:lang="pl">Plik jednostki systemd</comment>
+ <comment xml:lang="ja">systemdのunitファイル</comment>
+ <comment xml:lang="it">File unità systemd</comment>
+ <comment xml:lang="gl">Ficheiro de unidade de Systemd</comment>
+ <comment xml:lang="eu">Systemd unitate-fitxategia</comment>
+ <comment xml:lang="es">archivo de unidad de Systemd</comment>
+ <comment xml:lang="de">Systemd-Einheitendatei</comment>
+ <comment xml:lang="be">файл адзінкі systemd</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
-
- <match value="\n[Unit]\n" type="string" offset="0:256"/>
- <match value="\n[Install]\n" type="string" offset="0:256"/>
- <match value="\n[Automount]\n" type="string" offset="0:256"/>
-
- <match value="\n[Mount]\n" type="string" offset="0:256"/>
- <match value="\n[Path]\n" type="string" offset="0:256"/>
- <match value="\n[Scope]\n" type="string" offset="0:256"/>
- <match value="\n[Service]\n" type="string" offset="0:256"/>
- <match value="\n[Slice]\n" type="string" offset="0:256"/>
- <match value="\n[Socket]\n" type="string" offset="0:256"/>
- <match value="\n[Swap]\n" type="string" offset="0:256"/>
-
- <match value="\n[Timer]\n" type="string" offset="0:256"/>
-
-
- <match value="[Unit]\n" type="string" offset="0"/>
- <match value="[Install]\n" type="string" offset="0"/>
- <match value="[Automount]\n" type="string" offset="0"/>
- <match value="[Mount]\n" type="string" offset="0"/>
- <match value="[Path]\n" type="string" offset="0"/>
- <match value="[Scope]\n" type="string" offset="0"/>
- <match value="[Service]\n" type="string" offset="0"/>
- <match value="[Slice]\n" type="string" offset="0"/>
- <match value="[Socket]\n" type="string" offset="0"/>
- <match value="[Swap]\n" type="string" offset="0"/>
- <match value="[Timer]\n" type="string" offset="0"/>
+ <magic>
+ <!-- Matches part-way through the file. -->
+ <match type="string" value="\n[Unit]\n" offset="0:256"/>
+ <match type="string" value="\n[Install]\n" offset="0:256"/>
+ <match type="string" value="\n[Automount]\n" offset="0:256"/>
+ <!-- Note no [Device] section exists (https://www.freedesktop.org/software/systemd/man/systemd.device.html) -->
+ <match type="string" value="\n[Mount]\n" offset="0:256"/>
+ <match type="string" value="\n[Path]\n" offset="0:256"/>
+ <match type="string" value="\n[Scope]\n" offset="0:256"/>
+ <match type="string" value="\n[Service]\n" offset="0:256"/>
+ <match type="string" value="\n[Slice]\n" offset="0:256"/>
+ <match type="string" value="\n[Socket]\n" offset="0:256"/>
+ <match type="string" value="\n[Swap]\n" offset="0:256"/>
+ <!-- Note no [Target] section exists (https://www.freedesktop.org/software/systemd/man/systemd.target.html) -->
+ <match type="string" value="\n[Timer]\n" offset="0:256"/>
+ <!-- Matches at the start of the file. -->
+ <match type="string" value="[Unit]\n" offset="0"/>
+ <match type="string" value="[Install]\n" offset="0"/>
+ <match type="string" value="[Automount]\n" offset="0"/>
+ <match type="string" value="[Mount]\n" offset="0"/>
+ <match type="string" value="[Path]\n" offset="0"/>
+ <match type="string" value="[Scope]\n" offset="0"/>
+ <match type="string" value="[Service]\n" offset="0"/>
+ <match type="string" value="[Slice]\n" offset="0"/>
+ <match type="string" value="[Socket]\n" offset="0"/>
+ <match type="string" value="[Swap]\n" offset="0"/>
+ <match type="string" value="[Timer]\n" offset="0"/>
</magic>
<glob pattern="*.automount"/>
<glob pattern="*.device"/>
@@ -37185,175 +39589,234 @@
</mime-type>
<mime-type type="application/xslt+xml">
<comment>XSLT stylesheet</comment>
- <comment xml:lang="ar">نمط XSLT</comment>
- <comment xml:lang="be@latin">Arkuš stylaŭ XSLT</comment>
- <comment xml:lang="bg">Стилове — XSLT</comment>
- <comment xml:lang="ca">full d'estil XSLT</comment>
- <comment xml:lang="cs">stylopis XSLT</comment>
- <comment xml:lang="da">XSLT-stilark</comment>
- <comment xml:lang="de">XSLT-Stylesheet</comment>
- <comment xml:lang="el">Φύλλο στυλ XSLT</comment>
- <comment xml:lang="en_GB">XSLT stylesheet</comment>
- <comment xml:lang="eo">XSLT-stilfolio</comment>
- <comment xml:lang="es">hoja de estilos XSLT</comment>
- <comment xml:lang="eu">XSLT estilo-orria</comment>
- <comment xml:lang="fi">XSLT-tyylitiedosto</comment>
- <comment xml:lang="fo">XSLT sniðark</comment>
- <comment xml:lang="fr">feuille de style XSLT</comment>
- <comment xml:lang="ga">stílbhileog XSLT</comment>
- <comment xml:lang="gl">folla de estilo XSLT</comment>
- <comment xml:lang="he">גליון סגנון XSLT</comment>
- <comment xml:lang="hr">XSLT stilska tablica</comment>
- <comment xml:lang="hu">XSLT-stíluslap</comment>
- <comment xml:lang="ia">Folio de stilo XSLT</comment>
- <comment xml:lang="id">Lembar gaya XSLT</comment>
- <comment xml:lang="it">Foglio di stile XSLT</comment>
- <comment xml:lang="ja">XSLT スタイルシート</comment>
- <comment xml:lang="kk">XSLT стильдер кестесі</comment>
- <comment xml:lang="ko">XSLT 스타일시트</comment>
- <comment xml:lang="lt">XSLT stiliaus aprašas</comment>
- <comment xml:lang="lv">XSLT izklājlapa</comment>
- <comment xml:lang="ms">Helaian Gaya XSLT</comment>
- <comment xml:lang="nb">XSLT-stilark</comment>
- <comment xml:lang="nl">XSLT-stijlblad</comment>
- <comment xml:lang="nn">XSLT-stilark</comment>
- <comment xml:lang="oc">fuèlh d'estil XSLT</comment>
- <comment xml:lang="pl">Arkusz stylów XSLT</comment>
- <comment xml:lang="pt">folha de estilos XSLT</comment>
- <comment xml:lang="pt_BR">Folha de estilo XSLT</comment>
- <comment xml:lang="ro">Fișă de stil XSLT</comment>
- <comment xml:lang="ru">Таблица стилей XSLT</comment>
- <comment xml:lang="sk">Štýl XSLT</comment>
- <comment xml:lang="sl">Slogovna predloga XSLT</comment>
- <comment xml:lang="sq">Fletë stili XSLT</comment>
- <comment xml:lang="sr">ИксСЛТ стилски лист</comment>
- <comment xml:lang="sv">XSLT-stilmall</comment>
- <comment xml:lang="tr">XSLT çalışma sayfası</comment>
- <comment xml:lang="uk">таблиця стилів XSLT</comment>
- <comment xml:lang="vi">Tờ kiểu dáng XSLT</comment>
- <comment xml:lang="zh_CN">XSLT 样式表</comment>
<comment xml:lang="zh_TW">XSLT 樣式表</comment>
+ <comment xml:lang="zh_CN">XSLT 样式表</comment>
+ <comment xml:lang="vi">Tờ kiểu dáng XSLT</comment>
+ <comment xml:lang="uk">таблиця стилів XSLT</comment>
+ <comment xml:lang="tr">XSLT çalışma sayfası</comment>
+ <comment xml:lang="sv">XSLT-stilmall</comment>
+ <comment xml:lang="sr">ИксСЛТ стилски лист</comment>
+ <comment xml:lang="sq">fletëstil XSLT</comment>
+ <comment xml:lang="sl">Slogovna predloga XSLT</comment>
+ <comment xml:lang="si">XSLT මෝස්තර පත්‍රිකාව</comment>
+ <comment xml:lang="sk">Štýl XSLT</comment>
+ <comment xml:lang="ru">Таблица стилей XSLT</comment>
+ <comment xml:lang="ro">Fișă de stil XSLT</comment>
+ <comment xml:lang="pt_BR">Folha de estilo XSLT</comment>
+ <comment xml:lang="pt">folha de estilos XSLT</comment>
+ <comment xml:lang="pl">Arkusz stylów XSLT</comment>
+ <comment xml:lang="oc">fuèlh d'estil XSLT</comment>
+ <comment xml:lang="nn">XSLT-stilark</comment>
+ <comment xml:lang="nl">XSLT-stijlblad</comment>
+ <comment xml:lang="nb">XSLT-stilark</comment>
+ <comment xml:lang="ms">Helaian Gaya XSLT</comment>
+ <comment xml:lang="lv">XSLT izklājlapa</comment>
+ <comment xml:lang="lt">XSLT stiliaus aprašas</comment>
+ <comment xml:lang="ko">XSLT 스타일시트</comment>
+ <comment xml:lang="kk">XSLT стильдер кестесі</comment>
+ <comment xml:lang="ja">XSLT スタイルシート</comment>
+ <comment xml:lang="it">Foglio di stile XSLT</comment>
+ <comment xml:lang="is">XSLT stílblað</comment>
+ <comment xml:lang="id">Lembar gaya XSLT</comment>
+ <comment xml:lang="ia">Folio de stilo XSLT</comment>
+ <comment xml:lang="hu">XSLT-stíluslap</comment>
+ <comment xml:lang="hr">XSLT stilska tablica</comment>
+ <comment xml:lang="he">גיליון סגנון XSLT</comment>
+ <comment xml:lang="gl">folla de estilo XSLT</comment>
+ <comment xml:lang="ga">stílbhileog XSLT</comment>
+ <comment xml:lang="fur">sfuei di calcul XSLT</comment>
+ <comment xml:lang="fr">feuille de style XSLT</comment>
+ <comment xml:lang="fo">XSLT sniðark</comment>
+ <comment xml:lang="fi">XSLT-tyylitiedosto</comment>
+ <comment xml:lang="eu">XSLT estilo-orria</comment>
+ <comment xml:lang="es">hoja de estilos XSLT</comment>
+ <comment xml:lang="eo">XSLT-stilfolio</comment>
+ <comment xml:lang="en_GB">XSLT stylesheet</comment>
+ <comment xml:lang="el">Φύλλο στυλ XSLT</comment>
+ <comment xml:lang="de">XSLT-Stilvorlage</comment>
+ <comment xml:lang="da">XSLT-stilark</comment>
+ <comment xml:lang="cs">stylopis XSLT</comment>
+ <comment xml:lang="ca">full d'estil XSLT</comment>
+ <comment xml:lang="bg">Стилове — XSLT</comment>
+ <comment xml:lang="be@latin">Arkuš stylaŭ XSLT</comment>
+ <comment xml:lang="be">табліца стыляў XSLT</comment>
+ <comment xml:lang="ar">نمط XSLT</comment>
+ <comment xml:lang="af">XSLT-stylblad</comment>
<acronym>XSLT</acronym>
<expanded-acronym>eXtensible Stylesheet Language Transformation</expanded-acronym>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="&lt;xsl:stylesheet" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="&lt;xsl:stylesheet" offset="0:256"/>
</magic>
<glob pattern="*.xsl"/>
<glob pattern="*.xslt"/>
<root-XML namespaceURI="http://www.w3.org/1999/XSL/Transform" localName="stylesheet"/>
<sub-class-of type="application/xml"/>
</mime-type>
+ <mime-type type="text/x-maven+xml">
+ <comment>Maven description file</comment>
+ <comment xml:lang="zh_TW">Maven 描述檔</comment>
+ <comment xml:lang="zh_CN">Maven 描述文件</comment>
+ <comment xml:lang="uk">файл опису Maven</comment>
+ <comment xml:lang="tr">Maven açıklama dosyası</comment>
+ <comment xml:lang="sv">Maven-beskrivningsfil</comment>
+ <comment xml:lang="sq">kartelë përshkrimi Maven</comment>
+ <comment xml:lang="sl">Opisna datoteka Maven</comment>
+ <comment xml:lang="si">Maven විස්තර ගොනුව</comment>
+ <comment xml:lang="sk">Súbor popisu Maven</comment>
+ <comment xml:lang="ru">Файл описания Maven</comment>
+ <comment xml:lang="pt_BR">Arquivo de descrição Maven</comment>
+ <comment xml:lang="pl">Plik opisu Maven</comment>
+ <comment xml:lang="nl">Maven-omschrijvingsbestand</comment>
+ <comment xml:lang="ko">Maven 설명 파일</comment>
+ <comment xml:lang="kk">Maven сипаттама файлы</comment>
+ <comment xml:lang="ja">Maven 説明ファイル</comment>
+ <comment xml:lang="it">File descrizione Mave</comment>
+ <comment xml:lang="is">Maven lýsingarskrá</comment>
+ <comment xml:lang="id">Berkas deskripsi Maven</comment>
+ <comment xml:lang="hu">Maven leírófájl</comment>
+ <comment xml:lang="hr">Maven datoteka opisa</comment>
+ <comment xml:lang="he">קובץ תיאור Maven</comment>
+ <comment xml:lang="gl">Ficheiro de descrición de Maven</comment>
+ <comment xml:lang="ga">cur síos Maven</comment>
+ <comment xml:lang="fur">file di descrizion Maven</comment>
+ <comment xml:lang="fr">fichier de description Maven</comment>
+ <comment xml:lang="fi">Maven-kuvaustiedosto</comment>
+ <comment xml:lang="eu">Maven azalpen fitxategia</comment>
+ <comment xml:lang="es">archivo de descripción de Maven</comment>
+ <comment xml:lang="en_GB">Maven description file</comment>
+ <comment xml:lang="de">Maven-Beschreibungsdatei</comment>
+ <comment xml:lang="da">Maven-beskrivelsesfil</comment>
+ <comment xml:lang="cs">popisný soubor Maven</comment>
+ <comment xml:lang="ca">fitxer de descripció Maven</comment>
+ <comment xml:lang="bg">Модел — Maven</comment>
+ <comment xml:lang="be">файл апісання Maven</comment>
+ <comment xml:lang="ar">ملف وصف Maven</comment>
+ <comment xml:lang="af">Maven-beskrywingslêer</comment>
+ <generic-icon name="text-x-generic"/>
+ <glob pattern="pom.xml"/>
+ <glob pattern="settings.xml"/>
+ <sub-class-of type="application/xml"/>
+ </mime-type>
<mime-type type="text/xmcd">
<comment>XMCD CD database</comment>
- <comment xml:lang="ar">قاعدة بيانات XMCD CD</comment>
- <comment xml:lang="be@latin">Baza źviestak ab dyskach XMCD</comment>
- <comment xml:lang="bg">База от данни за CD-та — XMCD</comment>
- <comment xml:lang="ca">base de dades de CD XMCD</comment>
- <comment xml:lang="cs">databáze XMCD CD</comment>
- <comment xml:lang="da">XMCD-cd-database</comment>
- <comment xml:lang="de">XMCD-CD-Datenbank</comment>
- <comment xml:lang="el">Βάση δεδομένων CD XMCD</comment>
- <comment xml:lang="en_GB">XMCD CD database</comment>
- <comment xml:lang="es">base de datos de CD XMCD</comment>
- <comment xml:lang="eu">XMCD CD datu-basea</comment>
- <comment xml:lang="fi">XMCD CD -tietokanta</comment>
- <comment xml:lang="fo">XMCD fløgu dátustovnur</comment>
- <comment xml:lang="fr">base de données de CD XMCD</comment>
- <comment xml:lang="ga">bunachar sonraí XMCD CD</comment>
- <comment xml:lang="gl">base de datos de CD XMCD</comment>
- <comment xml:lang="he">מסד נתונים XMCD CD</comment>
- <comment xml:lang="hr">XMCD CD baza podataka</comment>
- <comment xml:lang="hu">XMCD CD-adatbázis</comment>
- <comment xml:lang="ia">Base de datos de CD XMCD</comment>
- <comment xml:lang="id">Basis data XMCD CD</comment>
- <comment xml:lang="it">Database XMCD CD</comment>
- <comment xml:lang="ja">XMCD CD データベース</comment>
- <comment xml:lang="kk">XMCD CD дерекқоры</comment>
- <comment xml:lang="ko">XMCD CD 데이터베이스</comment>
- <comment xml:lang="lt">XMCD CD duomenų bazė</comment>
- <comment xml:lang="lv">XMCD CD datubāze</comment>
- <comment xml:lang="nb">XMCD CD-database</comment>
- <comment xml:lang="nl">XMCD CD-gegevensbank</comment>
- <comment xml:lang="nn">XMCD CD-database</comment>
- <comment xml:lang="oc">banca de donadas de CD XMCD</comment>
- <comment xml:lang="pl">Baza danych CD XMCD</comment>
- <comment xml:lang="pt">base de dados XMCD CD</comment>
- <comment xml:lang="pt_BR">Banco de dados de CD XMCD</comment>
- <comment xml:lang="ro">Bază de date XMCD CD</comment>
- <comment xml:lang="ru">База данных компакт-дисков XMCD</comment>
- <comment xml:lang="sk">Databáza XMCD CD</comment>
- <comment xml:lang="sl">Podatkovna zbirka XMCD CD</comment>
- <comment xml:lang="sq">Bazë me të dhëna XMCD CD</comment>
- <comment xml:lang="sr">ИксМЦД ЦД база података</comment>
- <comment xml:lang="sv">XMCD cd-databas</comment>
- <comment xml:lang="tr">XMCD CD veritabanı</comment>
- <comment xml:lang="uk">база даних XMCD CD</comment>
- <comment xml:lang="vi">Cơ sở dữ liệu CD XMCD</comment>
- <comment xml:lang="zh_CN">XMCD CD 数据库</comment>
<comment xml:lang="zh_TW">XMCD CD 資料庫</comment>
+ <comment xml:lang="zh_CN">XMCD CD 数据库</comment>
+ <comment xml:lang="vi">Cơ sở dữ liệu CD XMCD</comment>
+ <comment xml:lang="uk">база даних XMCD CD</comment>
+ <comment xml:lang="tr">XMCD CD veri tabanı</comment>
+ <comment xml:lang="sv">XMCD cd-databas</comment>
+ <comment xml:lang="sr">ИксМЦД ЦД база података</comment>
+ <comment xml:lang="sq">bazë të dhënash XMCD CD</comment>
+ <comment xml:lang="sl">Podatkovna zbirka XMCD CD</comment>
+ <comment xml:lang="si">XMCD CD දත්ත ගබඩාව</comment>
+ <comment xml:lang="sk">Databáza XMCD CD</comment>
+ <comment xml:lang="ru">База данных компакт-дисков XMCD</comment>
+ <comment xml:lang="ro">Bază de date XMCD CD</comment>
+ <comment xml:lang="pt_BR">Banco de dados de CD XMCD</comment>
+ <comment xml:lang="pt">base de dados XMCD CD</comment>
+ <comment xml:lang="pl">Baza danych CD XMCD</comment>
+ <comment xml:lang="oc">banca de donadas de CD XMCD</comment>
+ <comment xml:lang="nn">XMCD CD-database</comment>
+ <comment xml:lang="nl">XMCD CD-gegevensbank</comment>
+ <comment xml:lang="nb">XMCD CD-database</comment>
+ <comment xml:lang="lv">XMCD CD datubāze</comment>
+ <comment xml:lang="lt">XMCD CD duomenų bazė</comment>
+ <comment xml:lang="ko">XMCD CD 데이터베이스</comment>
+ <comment xml:lang="kk">XMCD CD дерекқоры</comment>
+ <comment xml:lang="ja">XMCD CD データベース</comment>
+ <comment xml:lang="it">Database XMCD CD</comment>
+ <comment xml:lang="is">XMCD CD gagnagrunnur</comment>
+ <comment xml:lang="id">Basis data XMCD CD</comment>
+ <comment xml:lang="ia">Base de datos de CD XMCD</comment>
+ <comment xml:lang="hu">XMCD CD-adatbázis</comment>
+ <comment xml:lang="hr">XMCD CD baza podataka</comment>
+ <comment xml:lang="he">מסד נתונים XMCD CD</comment>
+ <comment xml:lang="gl">base de datos de CD XMCD</comment>
+ <comment xml:lang="ga">bunachar sonraí XMCD CD</comment>
+ <comment xml:lang="fur">base di dâts XMCD CD</comment>
+ <comment xml:lang="fr">base de données de CD XMCD</comment>
+ <comment xml:lang="fo">XMCD fløgu dátustovnur</comment>
+ <comment xml:lang="fi">XMCD CD -tietokanta</comment>
+ <comment xml:lang="eu">XMCD CD datu-basea</comment>
+ <comment xml:lang="es">base de datos de CD XMCD</comment>
+ <comment xml:lang="en_GB">XMCD CD database</comment>
+ <comment xml:lang="el">Βάση δεδομένων CD XMCD</comment>
+ <comment xml:lang="de">XMCD-CD-Datenbank</comment>
+ <comment xml:lang="da">XMCD-cd-database</comment>
+ <comment xml:lang="cs">databáze XMCD CD</comment>
+ <comment xml:lang="ca">base de dades de CD XMCD</comment>
+ <comment xml:lang="bg">База от данни за CD-та — XMCD</comment>
+ <comment xml:lang="be@latin">Baza źviestak ab dyskach XMCD</comment>
+ <comment xml:lang="be">база даных кампакт-дыскаў XMCD</comment>
+ <comment xml:lang="ar">قاعدة بيانات XMCD CD</comment>
+ <comment xml:lang="af">XMCD CD-databasis</comment>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="# xmcd" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="# xmcd" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/xml">
<comment>XML document</comment>
- <comment xml:lang="ar">مستند XML</comment>
- <comment xml:lang="ast">Documentu XML</comment>
- <comment xml:lang="be@latin">Dakument XML</comment>
- <comment xml:lang="bg">Документ — XML</comment>
- <comment xml:lang="ca">document XML</comment>
- <comment xml:lang="cs">dokument XML</comment>
- <comment xml:lang="da">XML-dokument</comment>
- <comment xml:lang="de">XML-Dokument</comment>
- <comment xml:lang="el">Έγγραφο XML</comment>
- <comment xml:lang="en_GB">XML document</comment>
- <comment xml:lang="eo">XML-dokumento</comment>
- <comment xml:lang="es">documento XML</comment>
- <comment xml:lang="eu">XML dokumentua</comment>
- <comment xml:lang="fi">XML-asiakirja</comment>
- <comment xml:lang="fo">XML skjal</comment>
- <comment xml:lang="fr">document XML</comment>
- <comment xml:lang="ga">cáipéis XML</comment>
- <comment xml:lang="gl">documento XML</comment>
- <comment xml:lang="he">מסמך XML</comment>
- <comment xml:lang="hr">XML dokument</comment>
- <comment xml:lang="hu">XML dokumentum</comment>
- <comment xml:lang="ia">Documento XML</comment>
- <comment xml:lang="id">Dokumen XML</comment>
- <comment xml:lang="it">Documento XML</comment>
- <comment xml:lang="ja">XML ドキュメント</comment>
- <comment xml:lang="kk">XML құжаты</comment>
- <comment xml:lang="ko">XML 문서</comment>
- <comment xml:lang="lt">XML dokumentas</comment>
- <comment xml:lang="lv">XML dokuments</comment>
- <comment xml:lang="nb">XML-dokument</comment>
- <comment xml:lang="nl">XML-document</comment>
- <comment xml:lang="nn">XML-dokument</comment>
- <comment xml:lang="oc">document XML</comment>
- <comment xml:lang="pl">Dokument XML</comment>
- <comment xml:lang="pt">documento XML</comment>
- <comment xml:lang="pt_BR">Documento XML</comment>
- <comment xml:lang="ro">Document XML</comment>
- <comment xml:lang="ru">Документ XML</comment>
- <comment xml:lang="sk">Dokument XML</comment>
- <comment xml:lang="sl">Dokument XML</comment>
- <comment xml:lang="sq">Dokument XML</comment>
- <comment xml:lang="sr">ИксМЛ документ</comment>
- <comment xml:lang="sv">XML-dokument</comment>
- <comment xml:lang="tr">XML belgesi</comment>
- <comment xml:lang="uk">документ XML</comment>
- <comment xml:lang="vi">Tài liệu XML</comment>
- <comment xml:lang="zh_CN">XML 文档</comment>
<comment xml:lang="zh_TW">XML 文件</comment>
+ <comment xml:lang="zh_CN">XML 文档</comment>
+ <comment xml:lang="vi">Tài liệu XML</comment>
+ <comment xml:lang="uk">документ XML</comment>
+ <comment xml:lang="tr">XML belgesi</comment>
+ <comment xml:lang="sv">XML-dokument</comment>
+ <comment xml:lang="sr">ИксМЛ документ</comment>
+ <comment xml:lang="sq">dokument XML</comment>
+ <comment xml:lang="sl">Dokument XML</comment>
+ <comment xml:lang="si">XML ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument XML</comment>
+ <comment xml:lang="ru">Документ XML</comment>
+ <comment xml:lang="ro">Document XML</comment>
+ <comment xml:lang="pt_BR">Documento XML</comment>
+ <comment xml:lang="pt">documento XML</comment>
+ <comment xml:lang="pl">Dokument XML</comment>
+ <comment xml:lang="oc">document XML</comment>
+ <comment xml:lang="nn">XML-dokument</comment>
+ <comment xml:lang="nl">XML-document</comment>
+ <comment xml:lang="nb">XML-dokument</comment>
+ <comment xml:lang="lv">XML dokuments</comment>
+ <comment xml:lang="lt">XML dokumentas</comment>
+ <comment xml:lang="ko">XML 문서</comment>
+ <comment xml:lang="kk">XML құжаты</comment>
+ <comment xml:lang="ja">XML ドキュメント</comment>
+ <comment xml:lang="it">Documento XML</comment>
+ <comment xml:lang="is">XML skjal</comment>
+ <comment xml:lang="id">Dokumen XML</comment>
+ <comment xml:lang="ia">Documento XML</comment>
+ <comment xml:lang="hu">XML dokumentum</comment>
+ <comment xml:lang="hr">XML dokument</comment>
+ <comment xml:lang="he">מסמך XML</comment>
+ <comment xml:lang="gl">documento XML</comment>
+ <comment xml:lang="ga">cáipéis XML</comment>
+ <comment xml:lang="fur">document XML</comment>
+ <comment xml:lang="fr">document XML</comment>
+ <comment xml:lang="fo">XML skjal</comment>
+ <comment xml:lang="fi">XML-asiakirja</comment>
+ <comment xml:lang="eu">XML dokumentua</comment>
+ <comment xml:lang="es">documento XML</comment>
+ <comment xml:lang="eo">XML-dokumento</comment>
+ <comment xml:lang="en_GB">XML document</comment>
+ <comment xml:lang="el">Έγγραφο XML</comment>
+ <comment xml:lang="de">XML-Dokument</comment>
+ <comment xml:lang="da">XML-dokument</comment>
+ <comment xml:lang="cs">dokument XML</comment>
+ <comment xml:lang="ca">document XML</comment>
+ <comment xml:lang="bg">Документ — XML</comment>
+ <comment xml:lang="be@latin">Dakument XML</comment>
+ <comment xml:lang="be">дакумент XML</comment>
+ <comment xml:lang="ast">Documentu XML</comment>
+ <comment xml:lang="ar">مستند XML</comment>
+ <comment xml:lang="af">XML-dokument</comment>
<acronym>XML</acronym>
<expanded-acronym>eXtensible Markup Language</expanded-acronym>
<sub-class-of type="text/plain"/>
<generic-icon name="text-html"/>
<magic priority="40">
- <match value="&lt;?xml" type="string" offset="0"/>
- <match value="&lt;!--" type="string" offset="0"/>
+ <match type="string" value="&lt;?xml" offset="0"/>
</magic>
<glob pattern="*.xml"/>
<glob pattern="*.xbl"/>
@@ -37363,53 +39826,58 @@
</mime-type>
<mime-type type="application/xml-external-parsed-entity">
<comment>XML entities document</comment>
- <comment xml:lang="ar">مستند كيانات XML</comment>
- <comment xml:lang="ast">Documentu d'entidaes XML</comment>
- <comment xml:lang="be@latin">Dakument elementaŭ XML</comment>
- <comment xml:lang="bg">Документ — заместващи последователности в XML</comment>
- <comment xml:lang="ca">document d'entitats XML</comment>
- <comment xml:lang="cs">dokument entit XML</comment>
- <comment xml:lang="da">XML-enhedsdokument</comment>
- <comment xml:lang="de">XML-Dokument-Entitäten</comment>
- <comment xml:lang="el">Έγγραφο οντοτήτων XML</comment>
- <comment xml:lang="en_GB">XML entities document</comment>
- <comment xml:lang="es">documento de entidades XML</comment>
- <comment xml:lang="eu">XML entitateen dokumentua</comment>
- <comment xml:lang="fi">XML-entiteettiasiakirja</comment>
- <comment xml:lang="fo">XML einindisskjal</comment>
- <comment xml:lang="fr">document d'entités XML</comment>
- <comment xml:lang="ga">cáipéis aonán XML</comment>
- <comment xml:lang="gl">documento de entidades XML</comment>
- <comment xml:lang="he">מסמך ישויות XML</comment>
- <comment xml:lang="hr">Dokument XML subjekata</comment>
- <comment xml:lang="hu">XML egyeddokumentum</comment>
- <comment xml:lang="ia">Documento de entitates XML</comment>
- <comment xml:lang="id">Dokumen entitas XML</comment>
- <comment xml:lang="it">Documento entità XML</comment>
- <comment xml:lang="ja">XML エントリドキュメント</comment>
- <comment xml:lang="kk">XML мәндер құжаты</comment>
- <comment xml:lang="ko">XML 엔티티 문서</comment>
- <comment xml:lang="lt">XML esybių dokumentas</comment>
- <comment xml:lang="lv">XML vienību dokuments</comment>
- <comment xml:lang="nb">XML-entitetsdokument</comment>
- <comment xml:lang="nl">XML entiteiten-document</comment>
- <comment xml:lang="nn">XML-entitet-dokument</comment>
- <comment xml:lang="oc">document d'entitats XML</comment>
- <comment xml:lang="pl">Dokument jednostek XML</comment>
- <comment xml:lang="pt">documento de entidades XML</comment>
- <comment xml:lang="pt_BR">Documento de entidades XML</comment>
- <comment xml:lang="ro">Document entități XML</comment>
- <comment xml:lang="ru">Файл сущностей XML</comment>
- <comment xml:lang="sk">Dokument entít XML</comment>
- <comment xml:lang="sl">Dokument XML določil</comment>
- <comment xml:lang="sq">Dokument njësish XML</comment>
- <comment xml:lang="sr">документ ИксМЛ ставки</comment>
- <comment xml:lang="sv">XML-entitetsdokument</comment>
- <comment xml:lang="tr">XML varlıklar belgesi</comment>
- <comment xml:lang="uk">документ об’єктів XML</comment>
- <comment xml:lang="vi">Tài liệu thực thể XML</comment>
- <comment xml:lang="zh_CN">XML 特征文档</comment>
<comment xml:lang="zh_TW">XML 實體文件</comment>
+ <comment xml:lang="zh_CN">XML 特征文档</comment>
+ <comment xml:lang="vi">Tài liệu thực thể XML</comment>
+ <comment xml:lang="uk">документ об’єктів XML</comment>
+ <comment xml:lang="tr">XML varlıklar belgesi</comment>
+ <comment xml:lang="sv">XML-entitetsdokument</comment>
+ <comment xml:lang="sr">документ ИксМЛ ставки</comment>
+ <comment xml:lang="sq">dokument njësish XML</comment>
+ <comment xml:lang="sl">Dokument XML določil</comment>
+ <comment xml:lang="si">XML ආයතන ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument entít XML</comment>
+ <comment xml:lang="ru">Файл сущностей XML</comment>
+ <comment xml:lang="ro">Document entități XML</comment>
+ <comment xml:lang="pt_BR">Documento de entidades XML</comment>
+ <comment xml:lang="pt">documento de entidades XML</comment>
+ <comment xml:lang="pl">Dokument jednostek XML</comment>
+ <comment xml:lang="oc">document d'entitats XML</comment>
+ <comment xml:lang="nn">XML-entitet-dokument</comment>
+ <comment xml:lang="nl">XML entiteiten-document</comment>
+ <comment xml:lang="nb">XML-entitetsdokument</comment>
+ <comment xml:lang="lv">XML vienību dokuments</comment>
+ <comment xml:lang="lt">XML esybių dokumentas</comment>
+ <comment xml:lang="ko">XML 엔티티 문서</comment>
+ <comment xml:lang="kk">XML мәндер құжаты</comment>
+ <comment xml:lang="ja">XML エントリドキュメント</comment>
+ <comment xml:lang="it">Documento entità XML</comment>
+ <comment xml:lang="is">XML-eininda skjal</comment>
+ <comment xml:lang="id">Dokumen entitas XML</comment>
+ <comment xml:lang="ia">Documento de entitates XML</comment>
+ <comment xml:lang="hu">XML egyeddokumentum</comment>
+ <comment xml:lang="hr">Dokument XML subjekata</comment>
+ <comment xml:lang="he">מסמך ישויות XML</comment>
+ <comment xml:lang="gl">documento de entidades XML</comment>
+ <comment xml:lang="ga">cáipéis aonán XML</comment>
+ <comment xml:lang="fur">document entitâts XML</comment>
+ <comment xml:lang="fr">document d'entités XML</comment>
+ <comment xml:lang="fo">XML einindisskjal</comment>
+ <comment xml:lang="fi">XML-entiteettiasiakirja</comment>
+ <comment xml:lang="eu">XML entitateen dokumentua</comment>
+ <comment xml:lang="es">documento de entidades XML</comment>
+ <comment xml:lang="en_GB">XML entities document</comment>
+ <comment xml:lang="el">Έγγραφο οντοτήτων XML</comment>
+ <comment xml:lang="de">XML-Entitätendokument</comment>
+ <comment xml:lang="da">XML-enhedsdokument</comment>
+ <comment xml:lang="cs">dokument entit XML</comment>
+ <comment xml:lang="ca">document d'entitats XML</comment>
+ <comment xml:lang="bg">Документ — заместващи последователности в XML</comment>
+ <comment xml:lang="be@latin">Dakument elementaŭ XML</comment>
+ <comment xml:lang="be">дакумент сутнасцей XML</comment>
+ <comment xml:lang="ast">Documentu d'entidaes XML</comment>
+ <comment xml:lang="ar">مستند كيانات XML</comment>
+ <comment xml:lang="af">XML-entiteitedokument</comment>
<acronym>XML</acronym>
<expanded-acronym>eXtensible Markup Language</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -37419,177 +39887,192 @@
</mime-type>
<mime-type type="video/dv">
<comment>DV video</comment>
- <comment xml:lang="ar">DV مرئي</comment>
- <comment xml:lang="ast">Videu en DV</comment>
- <comment xml:lang="be@latin">Videa DV</comment>
- <comment xml:lang="bg">Видео — DV</comment>
- <comment xml:lang="ca">vídeo DV</comment>
- <comment xml:lang="cs">video DV</comment>
- <comment xml:lang="da">DV-video</comment>
- <comment xml:lang="de">DV-Video</comment>
- <comment xml:lang="el">Βίντεο DV</comment>
- <comment xml:lang="en_GB">DV video</comment>
- <comment xml:lang="eo">DV-video</comment>
- <comment xml:lang="es">vídeo DV</comment>
- <comment xml:lang="eu">DV bideoa</comment>
- <comment xml:lang="fi">DV-video</comment>
- <comment xml:lang="fo">DV video</comment>
- <comment xml:lang="fr">vidéo DV</comment>
- <comment xml:lang="ga">físeán DV</comment>
- <comment xml:lang="gl">vídeo DV</comment>
- <comment xml:lang="he">וידאו DV</comment>
- <comment xml:lang="hr">DV video snimka</comment>
- <comment xml:lang="hu">DV videó</comment>
- <comment xml:lang="ia">Video DV</comment>
- <comment xml:lang="id">Video DV</comment>
- <comment xml:lang="it">Video DV</comment>
- <comment xml:lang="ja">DV 動画</comment>
- <comment xml:lang="ka">DV ვიდეო</comment>
- <comment xml:lang="kk">DV видеосы</comment>
- <comment xml:lang="ko">DV 동영상</comment>
- <comment xml:lang="lt">DV vaizdo įrašas</comment>
- <comment xml:lang="lv">DV video</comment>
- <comment xml:lang="nb">DV-film</comment>
- <comment xml:lang="nl">DV-video</comment>
- <comment xml:lang="nn">DV-video</comment>
- <comment xml:lang="oc">vidèo DV</comment>
- <comment xml:lang="pl">Plik wideo DV</comment>
- <comment xml:lang="pt">vídeo DV</comment>
- <comment xml:lang="pt_BR">Vídeo DV</comment>
- <comment xml:lang="ro">Video DV</comment>
- <comment xml:lang="ru">Видео DV</comment>
- <comment xml:lang="sk">Video DV</comment>
- <comment xml:lang="sl">Video datoteka DV</comment>
- <comment xml:lang="sq">Video DV</comment>
- <comment xml:lang="sr">ДВ видео</comment>
- <comment xml:lang="sv">DV-video</comment>
- <comment xml:lang="tr">DV video</comment>
- <comment xml:lang="uk">відеокліп DV</comment>
- <comment xml:lang="vi">Ảnh động DV</comment>
- <comment xml:lang="zh_CN">DV 视频</comment>
<comment xml:lang="zh_TW">DV 視訊</comment>
+ <comment xml:lang="zh_CN">DV 视频</comment>
+ <comment xml:lang="vi">Ảnh động DV</comment>
+ <comment xml:lang="uk">відеокліп DV</comment>
+ <comment xml:lang="tr">DV video</comment>
+ <comment xml:lang="sv">DV-video</comment>
+ <comment xml:lang="sr">ДВ видео</comment>
+ <comment xml:lang="sq">video DV</comment>
+ <comment xml:lang="sl">Video datoteka DV</comment>
+ <comment xml:lang="si">DV වීඩියෝ</comment>
+ <comment xml:lang="sk">Video DV</comment>
+ <comment xml:lang="ru">Видео DV</comment>
+ <comment xml:lang="ro">Video DV</comment>
+ <comment xml:lang="pt_BR">Vídeo DV</comment>
+ <comment xml:lang="pt">vídeo DV</comment>
+ <comment xml:lang="pl">Plik wideo DV</comment>
+ <comment xml:lang="oc">vidèo DV</comment>
+ <comment xml:lang="nn">DV-video</comment>
+ <comment xml:lang="nl">DV-video</comment>
+ <comment xml:lang="nb">DV-film</comment>
+ <comment xml:lang="lv">DV video</comment>
+ <comment xml:lang="lt">DV vaizdo įrašas</comment>
+ <comment xml:lang="ko">DV 동영상</comment>
+ <comment xml:lang="kk">DV видеосы</comment>
+ <comment xml:lang="ka">DV ვიდეო</comment>
+ <comment xml:lang="ja">DV 動画</comment>
+ <comment xml:lang="it">Video DV</comment>
+ <comment xml:lang="is">DV myndskeið</comment>
+ <comment xml:lang="id">Video DV</comment>
+ <comment xml:lang="ia">Video DV</comment>
+ <comment xml:lang="hu">DV videó</comment>
+ <comment xml:lang="hr">DV video snimka</comment>
+ <comment xml:lang="he">וידאו DV</comment>
+ <comment xml:lang="gl">vídeo DV</comment>
+ <comment xml:lang="ga">físeán DV</comment>
+ <comment xml:lang="fur">video DV</comment>
+ <comment xml:lang="fr">vidéo DV</comment>
+ <comment xml:lang="fo">DV video</comment>
+ <comment xml:lang="fi">DV-video</comment>
+ <comment xml:lang="eu">DV bideoa</comment>
+ <comment xml:lang="es">vídeo DV</comment>
+ <comment xml:lang="eo">DV-video</comment>
+ <comment xml:lang="en_GB">DV video</comment>
+ <comment xml:lang="el">Βίντεο DV</comment>
+ <comment xml:lang="de">DV-Video</comment>
+ <comment xml:lang="da">DV-video</comment>
+ <comment xml:lang="cs">video DV</comment>
+ <comment xml:lang="ca">vídeo DV</comment>
+ <comment xml:lang="bg">Видео — DV</comment>
+ <comment xml:lang="be@latin">Videa DV</comment>
+ <comment xml:lang="be">відэа DV</comment>
+ <comment xml:lang="ast">Videu en DV</comment>
+ <comment xml:lang="ar">فيديو DV</comment>
+ <comment xml:lang="af">DV-video</comment>
<acronym>DV</acronym>
<expanded-acronym>Digital Video</expanded-acronym>
- <magic priority="50">
- <match value="0x1f070000" type="big32" offset="0" mask="0xffffff00"/>
+ <magic>
+ <match type="big32" value="0x1f070000" mask="0xffffff00" offset="0"/>
</magic>
<glob pattern="*.dv"/>
</mime-type>
<mime-type type="video/isivideo">
<comment>ISI video</comment>
- <comment xml:lang="ar">مرئي ISI</comment>
- <comment xml:lang="ast">Videu n'ISI</comment>
- <comment xml:lang="az">ISI video faylı</comment>
- <comment xml:lang="be@latin">Videa ISI</comment>
- <comment xml:lang="bg">Видео — ISI</comment>
- <comment xml:lang="ca">vídeo ISI</comment>
- <comment xml:lang="cs">video ISI</comment>
- <comment xml:lang="cy">Fideo ISI</comment>
- <comment xml:lang="da">ISI-video</comment>
- <comment xml:lang="de">ISI-Video</comment>
- <comment xml:lang="el">Βίντεο ISI</comment>
- <comment xml:lang="en_GB">ISI video</comment>
- <comment xml:lang="eo">ISI-video</comment>
- <comment xml:lang="es">vídeo ISI</comment>
- <comment xml:lang="eu">ISI bideoa</comment>
- <comment xml:lang="fi">ISI-video</comment>
- <comment xml:lang="fo">ISI video</comment>
- <comment xml:lang="fr">vidéo ISI</comment>
- <comment xml:lang="ga">físeán ISI</comment>
- <comment xml:lang="gl">vídeo ISI</comment>
- <comment xml:lang="he">וידאו ISI</comment>
- <comment xml:lang="hr">ISI video snimka</comment>
- <comment xml:lang="hu">ISI-videó</comment>
- <comment xml:lang="ia">Video ISI</comment>
- <comment xml:lang="id">Video ISI</comment>
- <comment xml:lang="it">Video ISI</comment>
- <comment xml:lang="ja">ISI 動画</comment>
- <comment xml:lang="kk">ISI видеосы</comment>
- <comment xml:lang="ko">ISI 동영상</comment>
- <comment xml:lang="lt">ISI vaizdo įrašas</comment>
- <comment xml:lang="lv">ISI video</comment>
- <comment xml:lang="ms">Video ISI</comment>
- <comment xml:lang="nb">ISI-film</comment>
- <comment xml:lang="nl">ISI-video</comment>
- <comment xml:lang="nn">ISI video</comment>
- <comment xml:lang="oc">vidèo ISI</comment>
- <comment xml:lang="pl">Plik wideo ISI</comment>
- <comment xml:lang="pt">vídeo ISI</comment>
- <comment xml:lang="pt_BR">Vídeo ISI</comment>
- <comment xml:lang="ro">Video ISI</comment>
- <comment xml:lang="ru">Видео ISI</comment>
- <comment xml:lang="sk">Video ISI</comment>
- <comment xml:lang="sl">Video datoteka ISI</comment>
- <comment xml:lang="sq">Video ISI</comment>
- <comment xml:lang="sr">ИСИ видео</comment>
- <comment xml:lang="sv">ISI-video</comment>
- <comment xml:lang="tr">ISI videosu</comment>
- <comment xml:lang="uk">відеокліп ISI</comment>
- <comment xml:lang="vi">Ảnh động ISI</comment>
- <comment xml:lang="zh_CN">ISI 视频</comment>
<comment xml:lang="zh_TW">ISI 視訊</comment>
+ <comment xml:lang="zh_CN">ISI 视频</comment>
+ <comment xml:lang="vi">Ảnh động ISI</comment>
+ <comment xml:lang="uk">відеокліп ISI</comment>
+ <comment xml:lang="tr">ISI videosu</comment>
+ <comment xml:lang="sv">ISI-video</comment>
+ <comment xml:lang="sr">ИСИ видео</comment>
+ <comment xml:lang="sq">video ISI</comment>
+ <comment xml:lang="sl">Video datoteka ISI</comment>
+ <comment xml:lang="si">ISI වීඩියෝව</comment>
+ <comment xml:lang="sk">Video ISI</comment>
+ <comment xml:lang="ru">Видео ISI</comment>
+ <comment xml:lang="ro">Video ISI</comment>
+ <comment xml:lang="pt_BR">Vídeo ISI</comment>
+ <comment xml:lang="pt">vídeo ISI</comment>
+ <comment xml:lang="pl">Plik wideo ISI</comment>
+ <comment xml:lang="oc">vidèo ISI</comment>
+ <comment xml:lang="nn">ISI video</comment>
+ <comment xml:lang="nl">ISI-video</comment>
+ <comment xml:lang="nb">ISI-film</comment>
+ <comment xml:lang="ms">Video ISI</comment>
+ <comment xml:lang="lv">ISI video</comment>
+ <comment xml:lang="lt">ISI vaizdo įrašas</comment>
+ <comment xml:lang="ko">ISI 동영상</comment>
+ <comment xml:lang="kk">ISI видеосы</comment>
+ <comment xml:lang="ja">ISI 動画</comment>
+ <comment xml:lang="it">Video ISI</comment>
+ <comment xml:lang="is">ISI myndskeið</comment>
+ <comment xml:lang="id">Video ISI</comment>
+ <comment xml:lang="ia">Video ISI</comment>
+ <comment xml:lang="hu">ISI-videó</comment>
+ <comment xml:lang="hr">ISI video snimka</comment>
+ <comment xml:lang="he">וידאו ISI</comment>
+ <comment xml:lang="gl">vídeo ISI</comment>
+ <comment xml:lang="ga">físeán ISI</comment>
+ <comment xml:lang="fur">video ISI</comment>
+ <comment xml:lang="fr">vidéo ISI</comment>
+ <comment xml:lang="fo">ISI video</comment>
+ <comment xml:lang="fi">ISI-video</comment>
+ <comment xml:lang="eu">ISI bideoa</comment>
+ <comment xml:lang="es">vídeo ISI</comment>
+ <comment xml:lang="eo">ISI-video</comment>
+ <comment xml:lang="en_GB">ISI video</comment>
+ <comment xml:lang="el">Βίντεο ISI</comment>
+ <comment xml:lang="de">ISI-Video</comment>
+ <comment xml:lang="da">ISI-video</comment>
+ <comment xml:lang="cy">Fideo ISI</comment>
+ <comment xml:lang="cs">video ISI</comment>
+ <comment xml:lang="ca">vídeo ISI</comment>
+ <comment xml:lang="bg">Видео — ISI</comment>
+ <comment xml:lang="be@latin">Videa ISI</comment>
+ <comment xml:lang="be">відэа ISI</comment>
+ <comment xml:lang="az">ISI video faylı</comment>
+ <comment xml:lang="ast">Videu n'ISI</comment>
+ <comment xml:lang="ar">فيديو ISI</comment>
+ <comment xml:lang="af">ISI-video</comment>
</mime-type>
<mime-type type="video/mp2t">
<comment>MPEG-2 transport stream</comment>
- <comment xml:lang="ar">بث نقل MPEG-2</comment>
- <comment xml:lang="bg">Поток — транспорт по MPEG-2</comment>
- <comment xml:lang="ca">flux de transport MPEG-2</comment>
- <comment xml:lang="cs">přenosový proud MPEG-2</comment>
- <comment xml:lang="da">MPEG-2-transportstrøm</comment>
- <comment xml:lang="de">MPEG-2-Transportstrom</comment>
- <comment xml:lang="el">Ροή μεταφοράς MPEG-2</comment>
- <comment xml:lang="en_GB">MPEG-2 transport stream</comment>
- <comment xml:lang="es">flujo de transporte MPEG-2</comment>
- <comment xml:lang="eu">MPEG-2 korronte garraioa</comment>
- <comment xml:lang="fi">MPEG-2 -siirtobittivirta</comment>
- <comment xml:lang="fo">MPEG-2 flutningsstreymur</comment>
- <comment xml:lang="fr">flux de transport MPEG-2</comment>
- <comment xml:lang="ga">sruth aistrithe MPEG-2</comment>
- <comment xml:lang="gl">fluxo de transporte MPEG-2</comment>
- <comment xml:lang="he">העברת זרימה של MPEG-2</comment>
- <comment xml:lang="hr">MPEG-2 transportno strujanje</comment>
- <comment xml:lang="hu">MPEG-2 átviteli adatfolyam</comment>
- <comment xml:lang="ia">Fluxo de transporto MPEG-2</comment>
- <comment xml:lang="id">Stream transport MPEG-2</comment>
- <comment xml:lang="it">Stream di trasporto MPEG-2</comment>
- <comment xml:lang="ja">MPEG-2 トランスポートストリーム</comment>
- <comment xml:lang="ka">MPEG-2-ის ტრანსპორტული ნაკადი</comment>
- <comment xml:lang="kk">MPEG-2 көліктік ағыны</comment>
- <comment xml:lang="ko">MPEG-2 전송 스트림</comment>
- <comment xml:lang="lt">MPEG-2 transportavimo srautas</comment>
- <comment xml:lang="lv">MPEG-2 transporta straume</comment>
- <comment xml:lang="nl">MPEG-2 transport stream</comment>
- <comment xml:lang="oc">flux de transpòrt MPEG-2</comment>
- <comment xml:lang="pl">Strumień przesyłania MPEG-2</comment>
- <comment xml:lang="pt">fluxo de transporte MPEG-2</comment>
- <comment xml:lang="pt_BR">Fluxo de transporte de MPEG-2</comment>
- <comment xml:lang="ro">Flux transport MPEG-2</comment>
- <comment xml:lang="ru">Транспортный поток MPEG-2</comment>
- <comment xml:lang="sk">MPEG-2 Transport Stream</comment>
- <comment xml:lang="sl">Pretočni vir prenosega MPEG</comment>
- <comment xml:lang="sr">МПЕГ-2 ток преноса</comment>
- <comment xml:lang="sv">MPEG-2 transportström</comment>
- <comment xml:lang="tr">MPEG-2 aktarım akışı</comment>
- <comment xml:lang="uk">потік передавання даних MPEG-2</comment>
- <comment xml:lang="zh_CN">MPEG-2 传输流</comment>
<comment xml:lang="zh_TW">MPEG-2 傳輸串流</comment>
+ <comment xml:lang="zh_CN">MPEG-2 传输流</comment>
+ <comment xml:lang="uk">потік передавання даних MPEG-2</comment>
+ <comment xml:lang="tr">MPEG-2 aktarım akışı</comment>
+ <comment xml:lang="sv">MPEG-2 transportström</comment>
+ <comment xml:lang="sr">МПЕГ-2 ток преноса</comment>
+ <comment xml:lang="sl">Pretočni vir prenosega MPEG</comment>
+ <comment xml:lang="si">MPEG-2 ප්රවාහන ප්රවාහය</comment>
+ <comment xml:lang="sk">MPEG-2 Transport Stream</comment>
+ <comment xml:lang="ru">Транспортный поток MPEG-2</comment>
+ <comment xml:lang="ro">Flux transport MPEG-2</comment>
+ <comment xml:lang="pt_BR">Fluxo de transporte de MPEG-2</comment>
+ <comment xml:lang="pt">fluxo de transporte MPEG-2</comment>
+ <comment xml:lang="pl">Strumień przesyłania MPEG-2</comment>
+ <comment xml:lang="oc">flux de transpòrt MPEG-2</comment>
+ <comment xml:lang="nl">MPEG-2 transport stream</comment>
+ <comment xml:lang="lv">MPEG-2 transporta straume</comment>
+ <comment xml:lang="lt">MPEG-2 transportavimo srautas</comment>
+ <comment xml:lang="ko">MPEG-2 전송 스트림</comment>
+ <comment xml:lang="kk">MPEG-2 көліктік ағыны</comment>
+ <comment xml:lang="ka">MPEG-2-ის ტრანსპორტული ნაკადი</comment>
+ <comment xml:lang="ja">MPEG-2 トランスポートストリーム</comment>
+ <comment xml:lang="it">Stream di trasporto MPEG-2</comment>
+ <comment xml:lang="is">MPEG-2 Transport streymi</comment>
+ <comment xml:lang="id">Stream transport MPEG-2</comment>
+ <comment xml:lang="ia">Fluxo de transporto MPEG-2</comment>
+ <comment xml:lang="hu">MPEG-2 átviteli adatfolyam</comment>
+ <comment xml:lang="hr">MPEG-2 transportno strujanje</comment>
+ <comment xml:lang="he">העברת זרימה של MPEG-2</comment>
+ <comment xml:lang="gl">fluxo de transporte MPEG-2</comment>
+ <comment xml:lang="ga">sruth aistrithe MPEG-2</comment>
+ <comment xml:lang="fur">flus di traspuart MPEG-2</comment>
+ <comment xml:lang="fr">flux de transport MPEG-2</comment>
+ <comment xml:lang="fo">MPEG-2 flutningsstreymur</comment>
+ <comment xml:lang="fi">MPEG-2 -siirtobittivirta</comment>
+ <comment xml:lang="eu">MPEG-2 korronte garraioa</comment>
+ <comment xml:lang="es">flujo de transporte MPEG-2</comment>
+ <comment xml:lang="en_GB">MPEG-2 transport stream</comment>
+ <comment xml:lang="el">Ροή μεταφοράς MPEG-2</comment>
+ <comment xml:lang="de">MPEG-2-Transportstrom</comment>
+ <comment xml:lang="da">MPEG-2-transportstrøm</comment>
+ <comment xml:lang="cs">přenosový proud MPEG-2</comment>
+ <comment xml:lang="ca">flux de transport MPEG-2</comment>
+ <comment xml:lang="bg">Поток — транспорт по MPEG-2</comment>
+ <comment xml:lang="be">транспартная плынь MPEG-2</comment>
+ <comment xml:lang="ar">بث نقل MPEG-2</comment>
+ <comment xml:lang="af">MPEG-2-vervoerstroom</comment>
<acronym>MPEG-2 TS</acronym>
<expanded-acronym>Moving Picture Experts Group 2 Transport Stream</expanded-acronym>
- <magic priority="50">
- <match value="0x47" type="byte" offset="0">
- <match value="0x47" type="byte" offset="188">
- <match value="0x47" type="byte" offset="376">
- <match value="0x47" type="byte" offset="564">
- <match value="0x47" type="byte" offset="752"/>
+ <magic>
+ <match type="byte" value="0x47" offset="0">
+ <match type="byte" value="0x47" offset="188">
+ <match type="byte" value="0x47" offset="376">
+ <match type="byte" value="0x47" offset="564">
+ <match type="byte" value="0x47" offset="752"/>
</match>
</match>
</match>
</match>
- <match value="0x47" type="byte" offset="4">
- <match value="0x47" type="byte" offset="196">
- <match value="0x47" type="byte" offset="388">
- <match value="0x47" type="byte" offset="580">
- <match value="0x47" type="byte" offset="772"/>
+ <match type="byte" value="0x47" offset="4">
+ <match type="byte" value="0x47" offset="196">
+ <match type="byte" value="0x47" offset="388">
+ <match type="byte" value="0x47" offset="580">
+ <match type="byte" value="0x47" offset="772"/>
</match>
</match>
</match>
@@ -37608,66 +40091,71 @@
</mime-type>
<mime-type type="video/mpeg">
<comment>MPEG video</comment>
- <comment xml:lang="ar">MPEG مرئي</comment>
- <comment xml:lang="ast">Videu en MPEG</comment>
- <comment xml:lang="be@latin">Videa MPEG</comment>
- <comment xml:lang="bg">Видео — MPEG</comment>
- <comment xml:lang="ca">vídeo MPEG</comment>
- <comment xml:lang="cs">video MPEG</comment>
- <comment xml:lang="da">MPEG-video</comment>
- <comment xml:lang="de">MPEG-Video</comment>
- <comment xml:lang="el">Βίντεο MPEG</comment>
- <comment xml:lang="en_GB">MPEG video</comment>
- <comment xml:lang="eo">MPEG-video</comment>
- <comment xml:lang="es">vídeo MPEG</comment>
- <comment xml:lang="eu">MPEG bideoa</comment>
- <comment xml:lang="fi">MPEG-video</comment>
- <comment xml:lang="fo">MPEG video</comment>
- <comment xml:lang="fr">vidéo MPEG</comment>
- <comment xml:lang="ga">físeán MPEG</comment>
- <comment xml:lang="gl">vídeo MPEG</comment>
- <comment xml:lang="he">וידאו MPEG</comment>
- <comment xml:lang="hr">MPEG video snimka</comment>
- <comment xml:lang="hu">MPEG-videó</comment>
- <comment xml:lang="ia">Video MPEG</comment>
- <comment xml:lang="id">Video MPEG</comment>
- <comment xml:lang="it">Video MPEG</comment>
- <comment xml:lang="ja">MPEG 動画</comment>
- <comment xml:lang="ka">MPEG ვიდეო</comment>
- <comment xml:lang="kk">MPEG видеосы</comment>
- <comment xml:lang="ko">MPEG 동영상</comment>
- <comment xml:lang="lt">MPEG vaizdo įrašas</comment>
- <comment xml:lang="lv">MPEG video</comment>
- <comment xml:lang="ms">Video MPEG</comment>
- <comment xml:lang="nb">MPEG-film</comment>
- <comment xml:lang="nl">MPEG-video</comment>
- <comment xml:lang="nn">MPEG-video</comment>
- <comment xml:lang="oc">vidèo MPEG</comment>
- <comment xml:lang="pl">Plik wideo MPEG</comment>
- <comment xml:lang="pt">vídeo MPEG</comment>
- <comment xml:lang="pt_BR">Vídeo MPEG</comment>
- <comment xml:lang="ro">Video MPEG</comment>
- <comment xml:lang="ru">Видео MPEG</comment>
- <comment xml:lang="sk">Video MPEG</comment>
- <comment xml:lang="sl">Video datoteka MPEG</comment>
- <comment xml:lang="sq">Video MPEG</comment>
- <comment xml:lang="sr">МПЕГ видео</comment>
- <comment xml:lang="sv">MPEG-video</comment>
- <comment xml:lang="tr">MPEG videosu</comment>
- <comment xml:lang="uk">відеокліп MPEG</comment>
- <comment xml:lang="vi">Ảnh động MPEG</comment>
- <comment xml:lang="zh_CN">MPEG 视频</comment>
<comment xml:lang="zh_TW">MPEG 視訊</comment>
+ <comment xml:lang="zh_CN">MPEG 视频</comment>
+ <comment xml:lang="vi">Ảnh động MPEG</comment>
+ <comment xml:lang="uk">відеокліп MPEG</comment>
+ <comment xml:lang="tr">MPEG videosu</comment>
+ <comment xml:lang="sv">MPEG-video</comment>
+ <comment xml:lang="sr">МПЕГ видео</comment>
+ <comment xml:lang="sq">video MPEG</comment>
+ <comment xml:lang="sl">Video datoteka MPEG</comment>
+ <comment xml:lang="si">MPEG වීඩියෝව</comment>
+ <comment xml:lang="sk">Video MPEG</comment>
+ <comment xml:lang="ru">Видео MPEG</comment>
+ <comment xml:lang="ro">Video MPEG</comment>
+ <comment xml:lang="pt_BR">Vídeo MPEG</comment>
+ <comment xml:lang="pt">vídeo MPEG</comment>
+ <comment xml:lang="pl">Plik wideo MPEG</comment>
+ <comment xml:lang="oc">vidèo MPEG</comment>
+ <comment xml:lang="nn">MPEG-video</comment>
+ <comment xml:lang="nl">MPEG-video</comment>
+ <comment xml:lang="nb">MPEG-film</comment>
+ <comment xml:lang="ms">Video MPEG</comment>
+ <comment xml:lang="lv">MPEG video</comment>
+ <comment xml:lang="lt">MPEG vaizdo įrašas</comment>
+ <comment xml:lang="ko">MPEG 동영상</comment>
+ <comment xml:lang="kk">MPEG видеосы</comment>
+ <comment xml:lang="ka">MPEG ვიდეო</comment>
+ <comment xml:lang="ja">MPEG 動画</comment>
+ <comment xml:lang="it">Video MPEG</comment>
+ <comment xml:lang="is">MPEG myndskeið</comment>
+ <comment xml:lang="id">Video MPEG</comment>
+ <comment xml:lang="ia">Video MPEG</comment>
+ <comment xml:lang="hu">MPEG-videó</comment>
+ <comment xml:lang="hr">MPEG video snimka</comment>
+ <comment xml:lang="he">וידאו MPEG</comment>
+ <comment xml:lang="gl">vídeo MPEG</comment>
+ <comment xml:lang="ga">físeán MPEG</comment>
+ <comment xml:lang="fur">video MPEG</comment>
+ <comment xml:lang="fr">vidéo MPEG</comment>
+ <comment xml:lang="fo">MPEG video</comment>
+ <comment xml:lang="fi">MPEG-video</comment>
+ <comment xml:lang="eu">MPEG bideoa</comment>
+ <comment xml:lang="es">vídeo MPEG</comment>
+ <comment xml:lang="eo">MPEG-video</comment>
+ <comment xml:lang="en_GB">MPEG video</comment>
+ <comment xml:lang="el">Βίντεο MPEG</comment>
+ <comment xml:lang="de">MPEG-Video</comment>
+ <comment xml:lang="da">MPEG-video</comment>
+ <comment xml:lang="cs">video MPEG</comment>
+ <comment xml:lang="ca">vídeo MPEG</comment>
+ <comment xml:lang="bg">Видео — MPEG</comment>
+ <comment xml:lang="be@latin">Videa MPEG</comment>
+ <comment xml:lang="be">відэа MPEG</comment>
+ <comment xml:lang="ast">Videu en MPEG</comment>
+ <comment xml:lang="ar">فيديو MPEG</comment>
+ <comment xml:lang="af">MPEG-video</comment>
<acronym>MPEG</acronym>
<expanded-acronym>Moving Picture Experts Group</expanded-acronym>
<alias type="video/x-mpeg"/>
<alias type="video/mpeg-system"/>
<alias type="video/x-mpeg-system"/>
<alias type="video/x-mpeg2"/>
- <magic priority="50">
- <match value="\x47\x3f\xff\x10" type="string" offset="0"/>
- <match value="0x000001b3" type="big32" offset="0"/>
- <match value="0x000001ba" type="big32" offset="0"/>
+ <magic>
+ <match type="string" value="\x47\x3f\xff\x10" offset="0"/>
+ <match type="big32" value="0x000001b3" offset="0"/>
+ <match type="big32" value="0x000001ba" offset="0"/>
</magic>
<glob pattern="*.mpeg"/>
<glob pattern="*.mpg"/>
@@ -37677,50 +40165,35 @@
<glob pattern="[0-9][0-9][0-9].vdr"/>
</mime-type>
<mime-type type="video/vnd.mpegurl">
- <comment>MPEG video (streamed)</comment>
- <comment xml:lang="ast">Videu en MPEG (tresmitíu)</comment>
- <comment xml:lang="bg">Видео — MPEG, поточно</comment>
- <comment xml:lang="ca">vídeo MPEG (flux)</comment>
- <comment xml:lang="cs">video MPEG (proud)</comment>
- <comment xml:lang="da">MPEG-video (streamet)</comment>
- <comment xml:lang="de">MPEG-Video (Datenstrom)</comment>
- <comment xml:lang="el">Βίντεο MPEG (εκπεμπόμενο)</comment>
- <comment xml:lang="en_GB">MPEG video (streamed)</comment>
- <comment xml:lang="es">vídeo MPEG (transmisión)</comment>
- <comment xml:lang="eu">MPEG bideoa (korronte bidez)</comment>
- <comment xml:lang="fi">MPEG-video (virtaus)</comment>
- <comment xml:lang="fr">vidéo MPEG (flux)</comment>
- <comment xml:lang="ga">físeán MPEG (sruthaithe)</comment>
- <comment xml:lang="gl">vídeo MPEG (en stream)</comment>
- <comment xml:lang="he">קובץ MPEG (בהזרמה)</comment>
- <comment xml:lang="hr">MPEG video snimka (strujanje)</comment>
- <comment xml:lang="hu">MPEG videó (szórt)</comment>
- <comment xml:lang="ia">Video MPEG (in fluxo)</comment>
- <comment xml:lang="id">Video MPEG (di-stream-kan)</comment>
- <comment xml:lang="it">Video MPEG (streamed)</comment>
- <comment xml:lang="ja">MPEG ビデオ(ストリーム)</comment>
- <comment xml:lang="ka">MPEG ვიდეო (ნაკადი)</comment>
- <comment xml:lang="kk">MPEG видео (ағымдық)</comment>
- <comment xml:lang="ko">MPEG 동영상(스트리밍)</comment>
- <comment xml:lang="lv">MPEG video (straumēts)</comment>
- <comment xml:lang="nl">MPEG video (streamed)</comment>
- <comment xml:lang="oc">vidèo MPEG (flux)</comment>
- <comment xml:lang="pl">Plik wideo MPEG (strumień)</comment>
- <comment xml:lang="pt">vídeo MPEG (em fluxo)</comment>
- <comment xml:lang="pt_BR">Vídeo MPEG (fluxo)</comment>
- <comment xml:lang="ru">Видео MPEG (потоковое)</comment>
- <comment xml:lang="sk">MPEG video (streamované)</comment>
- <comment xml:lang="sl">MPEG-video (pretočni)</comment>
- <comment xml:lang="sr">МПЕГ видео (проточни)</comment>
- <comment xml:lang="sv">MPEG-video (strömmad)</comment>
- <comment xml:lang="tr">MPEG videosu (akış)</comment>
- <comment xml:lang="uk">відеокліп MPEG (потоковий)</comment>
- <comment xml:lang="zh_CN">MPEG 视频流媒体</comment>
- <comment xml:lang="zh_TW">MPEG 視訊 (串流)</comment>
+ <comment>Video playlist</comment>
+ <comment xml:lang="zh_CN">视频播放列表</comment>
+ <comment xml:lang="uk">список відтворення відео</comment>
+ <comment xml:lang="tr">Video çalma listesi</comment>
+ <comment xml:lang="sv">Videospellista</comment>
+ <comment xml:lang="sl">Seznam predvajanja videoposnetkov</comment>
+ <comment xml:lang="si">වීඩියෝ ධාවන ලැයිස්තුව</comment>
+ <comment xml:lang="ru">Список воспроизведения видео-данных</comment>
+ <comment xml:lang="pl">Lista odtwarzania wideo</comment>
+ <comment xml:lang="oc">lista de lectura vidèo</comment>
+ <comment xml:lang="nl">Video-afspeellijst</comment>
+ <comment xml:lang="ko">동영상 재생 목록</comment>
+ <comment xml:lang="kk">Видео ойнату тізімі</comment>
+ <comment xml:lang="ka">ვიდეო დასაკრავი სია</comment>
+ <comment xml:lang="ja">ビデオ再生リスト</comment>
+ <comment xml:lang="it">Playlist video</comment>
+ <comment xml:lang="hr">Video popis izvođenja</comment>
+ <comment xml:lang="gl">Lista de reprodución de vídeos</comment>
+ <comment xml:lang="fi">Video-soittolista</comment>
+ <comment xml:lang="eu">Bideoen erreprodukzio-zerrenda</comment>
+ <comment xml:lang="es">lista de reproducción de vídeo</comment>
+ <comment xml:lang="en_GB">Video playlist</comment>
+ <comment xml:lang="de">Video-Wiedergabeliste</comment>
+ <comment xml:lang="be">плэй-ліст відэа</comment>
+ <comment xml:lang="ar">قائمة تشغيل فيديو</comment>
<sub-class-of type="text/plain"/>
<alias type="video/x-mpegurl"/>
- <magic priority="50">
- <match value="#EXTM4U" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="#EXTM4U" offset="0"/>
</magic>
<glob pattern="*.m1u"/>
<glob pattern="*.m4u"/>
@@ -37728,60 +40201,65 @@
</mime-type>
<mime-type type="video/quicktime">
<comment>QuickTime video</comment>
- <comment xml:lang="ar">QuickTime مرئي</comment>
- <comment xml:lang="ast">Videu en QuickTime</comment>
- <comment xml:lang="be@latin">Videa QuickTime</comment>
- <comment xml:lang="bg">Видео — QuickTime</comment>
- <comment xml:lang="ca">vídeo QuickTime</comment>
- <comment xml:lang="cs">video QuickTime</comment>
- <comment xml:lang="da">QuickTime-video</comment>
- <comment xml:lang="de">QuickTime-Video</comment>
- <comment xml:lang="el">Βίντεο QuickTime</comment>
- <comment xml:lang="en_GB">QuickTime video</comment>
- <comment xml:lang="eo">QuickTime-video</comment>
- <comment xml:lang="es">vídeo QuickTime</comment>
- <comment xml:lang="eu">QuickTime bideoa</comment>
- <comment xml:lang="fi">QuickTime-video</comment>
- <comment xml:lang="fo">QuickTime video</comment>
- <comment xml:lang="fr">vidéo QuickTime</comment>
- <comment xml:lang="ga">físeán QuickTime</comment>
- <comment xml:lang="gl">vídeo QuickTime</comment>
- <comment xml:lang="he">וידאו של QuickTime</comment>
- <comment xml:lang="hr">QuickTime video snimka</comment>
- <comment xml:lang="hu">QuickTime videó</comment>
- <comment xml:lang="ia">Video QuickTime</comment>
- <comment xml:lang="id">Video QuickTime</comment>
- <comment xml:lang="it">Video QuickTime</comment>
- <comment xml:lang="ja">QuickTime 動画</comment>
- <comment xml:lang="kk">QuickTime видеосы</comment>
- <comment xml:lang="ko">퀵타임 동영상</comment>
- <comment xml:lang="lt">QuickTime vaizdo įrašas</comment>
- <comment xml:lang="lv">QuickTime video</comment>
- <comment xml:lang="ms">Video QuickTime</comment>
- <comment xml:lang="nb">Quicktime film</comment>
- <comment xml:lang="nl">QuickTime-video</comment>
- <comment xml:lang="nn">QuickTime-video</comment>
- <comment xml:lang="oc">vidèo QuickTime</comment>
- <comment xml:lang="pl">Plik wideo QuickTime</comment>
- <comment xml:lang="pt">vídeo QuickTime</comment>
- <comment xml:lang="pt_BR">Vídeo do QuickTime</comment>
- <comment xml:lang="ro">Video QuickTime</comment>
- <comment xml:lang="ru">Видео QuickTime</comment>
- <comment xml:lang="sk">Video QuickTime</comment>
- <comment xml:lang="sl">Video datoteka QuickTime</comment>
- <comment xml:lang="sq">Video QuickTime</comment>
- <comment xml:lang="sr">Квик Тајм видео</comment>
- <comment xml:lang="sv">QuickTime-video</comment>
- <comment xml:lang="tr">QuickTime videosu</comment>
- <comment xml:lang="uk">відеокліп QuickTime</comment>
- <comment xml:lang="vi">Ảnh động QuickTime</comment>
- <comment xml:lang="zh_CN">QuickTime 视频</comment>
<comment xml:lang="zh_TW">QuickTime 視訊</comment>
- <magic priority="50">
- <match value="mdat" type="string" offset="12"/>
- <match value="mdat" type="string" offset="4"/>
- <match value="moov" type="string" offset="4"/>
- <match value="ftypqt" type="string" offset="4"/>
+ <comment xml:lang="zh_CN">QuickTime 视频</comment>
+ <comment xml:lang="vi">Ảnh động QuickTime</comment>
+ <comment xml:lang="uk">відеокліп QuickTime</comment>
+ <comment xml:lang="tr">QuickTime videosu</comment>
+ <comment xml:lang="sv">QuickTime-video</comment>
+ <comment xml:lang="sr">Квик Тајм видео</comment>
+ <comment xml:lang="sq">video QuickTime</comment>
+ <comment xml:lang="sl">Video datoteka QuickTime</comment>
+ <comment xml:lang="si">QuickTime වීඩියෝව</comment>
+ <comment xml:lang="sk">Video QuickTime</comment>
+ <comment xml:lang="ru">Видео QuickTime</comment>
+ <comment xml:lang="ro">Video QuickTime</comment>
+ <comment xml:lang="pt_BR">Vídeo do QuickTime</comment>
+ <comment xml:lang="pt">vídeo QuickTime</comment>
+ <comment xml:lang="pl">Plik wideo QuickTime</comment>
+ <comment xml:lang="oc">vidèo QuickTime</comment>
+ <comment xml:lang="nn">QuickTime-video</comment>
+ <comment xml:lang="nl">QuickTime-video</comment>
+ <comment xml:lang="nb">Quicktime film</comment>
+ <comment xml:lang="ms">Video QuickTime</comment>
+ <comment xml:lang="lv">QuickTime video</comment>
+ <comment xml:lang="lt">QuickTime vaizdo įrašas</comment>
+ <comment xml:lang="ko">퀵타임 동영상</comment>
+ <comment xml:lang="kk">QuickTime видеосы</comment>
+ <comment xml:lang="ja">QuickTime 動画</comment>
+ <comment xml:lang="it">Video QuickTime</comment>
+ <comment xml:lang="is">QuickTime myndskeið</comment>
+ <comment xml:lang="id">Video QuickTime</comment>
+ <comment xml:lang="ia">Video QuickTime</comment>
+ <comment xml:lang="hu">QuickTime videó</comment>
+ <comment xml:lang="hr">QuickTime video snimka</comment>
+ <comment xml:lang="he">וידאו של QuickTime</comment>
+ <comment xml:lang="gl">vídeo QuickTime</comment>
+ <comment xml:lang="ga">físeán QuickTime</comment>
+ <comment xml:lang="fur">video QuickTime</comment>
+ <comment xml:lang="fr">vidéo QuickTime</comment>
+ <comment xml:lang="fo">QuickTime video</comment>
+ <comment xml:lang="fi">QuickTime-video</comment>
+ <comment xml:lang="eu">QuickTime bideoa</comment>
+ <comment xml:lang="es">vídeo QuickTime</comment>
+ <comment xml:lang="eo">QuickTime-video</comment>
+ <comment xml:lang="en_GB">QuickTime video</comment>
+ <comment xml:lang="el">Βίντεο QuickTime</comment>
+ <comment xml:lang="de">QuickTime-Video</comment>
+ <comment xml:lang="da">QuickTime-video</comment>
+ <comment xml:lang="cs">video QuickTime</comment>
+ <comment xml:lang="ca">vídeo QuickTime</comment>
+ <comment xml:lang="bg">Видео — QuickTime</comment>
+ <comment xml:lang="be@latin">Videa QuickTime</comment>
+ <comment xml:lang="be">відэа QuickTime</comment>
+ <comment xml:lang="ast">Videu en QuickTime</comment>
+ <comment xml:lang="ar">فيديو QuickTime</comment>
+ <comment xml:lang="af">QuickTime-video</comment>
+ <magic>
+ <match type="string" value="mdat" offset="12"/>
+ <match type="string" value="mdat" offset="4"/>
+ <match type="string" value="moov" offset="4"/>
+ <match type="string" value="ftypqt" offset="4"/>
</magic>
<glob pattern="*.qt"/>
<glob pattern="*.mov"/>
@@ -37790,706 +40268,867 @@
</mime-type>
<mime-type type="image/x-quicktime">
<comment>QuickTime image</comment>
- <comment xml:lang="ar">صورة QuickTime</comment>
- <comment xml:lang="be@latin">Vyjava QuickTime</comment>
- <comment xml:lang="bg">Изображение — QuickTime</comment>
- <comment xml:lang="ca">imatge QuickTime</comment>
- <comment xml:lang="cs">obrázek QuickTime</comment>
- <comment xml:lang="da">QuickTime-billede</comment>
- <comment xml:lang="de">QuickTime-Bild</comment>
- <comment xml:lang="el">Εικόνα QuickTime</comment>
- <comment xml:lang="en_GB">QuickTime image</comment>
- <comment xml:lang="eo">QuickTime-bildo</comment>
- <comment xml:lang="es">imagen de QuickTime</comment>
- <comment xml:lang="eu">QuickTime irudia</comment>
- <comment xml:lang="fi">QuickTime-kuva</comment>
- <comment xml:lang="fo">QuickTime mynd</comment>
- <comment xml:lang="fr">image QuickTime</comment>
- <comment xml:lang="ga">íomhá QuickTime</comment>
- <comment xml:lang="gl">imaxe QuickTime</comment>
- <comment xml:lang="he">תמונה של QuickTime</comment>
- <comment xml:lang="hr">QuickTime slika</comment>
- <comment xml:lang="hu">QuickTime kép</comment>
- <comment xml:lang="ia">Imagine QuickTime</comment>
- <comment xml:lang="id">Citra QuickTime</comment>
- <comment xml:lang="it">Immagine QuickTime</comment>
- <comment xml:lang="ja">QuickTime 画像</comment>
- <comment xml:lang="kk">QuickTime суреті</comment>
- <comment xml:lang="ko">퀵타임 그림</comment>
- <comment xml:lang="lt">QuickTime paveikslėlis</comment>
- <comment xml:lang="lv">QuickTime attēls</comment>
- <comment xml:lang="nb">Quicktime bilde</comment>
- <comment xml:lang="nl">QuickTime-afbeelding</comment>
- <comment xml:lang="nn">QuickTime-bilete</comment>
- <comment xml:lang="oc">imatge QuickTime</comment>
- <comment xml:lang="pl">Obraz QuickTime</comment>
- <comment xml:lang="pt">imagem QuickTime</comment>
- <comment xml:lang="pt_BR">Imagem do QuickTime</comment>
- <comment xml:lang="ro">Imagine QuickTime</comment>
- <comment xml:lang="ru">Изображение QuickTime</comment>
- <comment xml:lang="sk">Obrázok QuickTime</comment>
- <comment xml:lang="sl">Slikovna datoteka QuickTime</comment>
- <comment xml:lang="sq">Figurë QuickTime</comment>
- <comment xml:lang="sr">Квик Тајм слика</comment>
- <comment xml:lang="sv">QuickTime-bild</comment>
- <comment xml:lang="tr">QuickTime görüntüsü</comment>
- <comment xml:lang="uk">зображення QuickTime</comment>
- <comment xml:lang="vi">Ảnh QuickTime</comment>
- <comment xml:lang="zh_CN">QuickTime 图像</comment>
<comment xml:lang="zh_TW">QuickTime 影像</comment>
- <magic priority="50">
- <match value="idat" type="string" offset="4"/>
+ <comment xml:lang="zh_CN">QuickTime 图像</comment>
+ <comment xml:lang="vi">Ảnh QuickTime</comment>
+ <comment xml:lang="uk">зображення QuickTime</comment>
+ <comment xml:lang="tr">QuickTime görüntüsü</comment>
+ <comment xml:lang="sv">QuickTime-bild</comment>
+ <comment xml:lang="sr">Квик Тајм слика</comment>
+ <comment xml:lang="sq">figurë QuickTime</comment>
+ <comment xml:lang="sl">Slikovna datoteka QuickTime</comment>
+ <comment xml:lang="si">QuickTime රූපය</comment>
+ <comment xml:lang="sk">Obrázok QuickTime</comment>
+ <comment xml:lang="ru">Изображение QuickTime</comment>
+ <comment xml:lang="ro">Imagine QuickTime</comment>
+ <comment xml:lang="pt_BR">Imagem do QuickTime</comment>
+ <comment xml:lang="pt">imagem QuickTime</comment>
+ <comment xml:lang="pl">Obraz QuickTime</comment>
+ <comment xml:lang="oc">imatge QuickTime</comment>
+ <comment xml:lang="nn">QuickTime-bilete</comment>
+ <comment xml:lang="nl">QuickTime-afbeelding</comment>
+ <comment xml:lang="nb">Quicktime bilde</comment>
+ <comment xml:lang="lv">QuickTime attēls</comment>
+ <comment xml:lang="lt">QuickTime paveikslėlis</comment>
+ <comment xml:lang="ko">퀵타임 그림</comment>
+ <comment xml:lang="kk">QuickTime суреті</comment>
+ <comment xml:lang="ja">QuickTime 画像</comment>
+ <comment xml:lang="it">Immagine QuickTime</comment>
+ <comment xml:lang="is">QuickTime mynd</comment>
+ <comment xml:lang="id">Citra QuickTime</comment>
+ <comment xml:lang="ia">Imagine QuickTime</comment>
+ <comment xml:lang="hu">QuickTime kép</comment>
+ <comment xml:lang="hr">QuickTime slika</comment>
+ <comment xml:lang="he">תמונה של QuickTime</comment>
+ <comment xml:lang="gl">imaxe QuickTime</comment>
+ <comment xml:lang="ga">íomhá QuickTime</comment>
+ <comment xml:lang="fur">imagjin QuickTime</comment>
+ <comment xml:lang="fr">image QuickTime</comment>
+ <comment xml:lang="fo">QuickTime mynd</comment>
+ <comment xml:lang="fi">QuickTime-kuva</comment>
+ <comment xml:lang="eu">QuickTime irudia</comment>
+ <comment xml:lang="es">imagen de QuickTime</comment>
+ <comment xml:lang="eo">QuickTime-bildo</comment>
+ <comment xml:lang="en_GB">QuickTime image</comment>
+ <comment xml:lang="el">Εικόνα QuickTime</comment>
+ <comment xml:lang="de">QuickTime-Bild</comment>
+ <comment xml:lang="da">QuickTime-billede</comment>
+ <comment xml:lang="cs">obrázek QuickTime</comment>
+ <comment xml:lang="ca">imatge QuickTime</comment>
+ <comment xml:lang="bg">Изображение — QuickTime</comment>
+ <comment xml:lang="be@latin">Vyjava QuickTime</comment>
+ <comment xml:lang="be">выява QuickTime</comment>
+ <comment xml:lang="ar">صورة QuickTime</comment>
+ <comment xml:lang="af">QuickTime-beeld</comment>
+ <magic>
+ <match type="string" value="idat" offset="4"/>
</magic>
<glob pattern="*.qtif"/>
<glob pattern="*.qif"/>
</mime-type>
<mime-type type="image/ktx">
<comment>Khronos texture image</comment>
- <comment xml:lang="ca">imatge de textura de Khronos</comment>
- <comment xml:lang="cs">obrázek s texturou Khronos</comment>
- <comment xml:lang="de">Khronos-Texturbild</comment>
- <comment xml:lang="en_GB">Khronos texture image</comment>
- <comment xml:lang="es">imagen de textura de Khronos</comment>
- <comment xml:lang="fr">image de texture Khronos</comment>
- <comment xml:lang="ga">íomhá uigeachta Khronos</comment>
- <comment xml:lang="hr">Khronos tekstura slika</comment>
- <comment xml:lang="hu">Khronos textúra kép</comment>
- <comment xml:lang="id">citra tekstur Khronos</comment>
- <comment xml:lang="it">Immagine texture Khronos</comment>
- <comment xml:lang="kk">Khronos текстура суреті</comment>
- <comment xml:lang="ko">크로노스 텍스처 파일</comment>
- <comment xml:lang="pl">Obraz tekstury Khronos</comment>
- <comment xml:lang="pt_BR">Imagem de textura do Khronos</comment>
- <comment xml:lang="ru">Изображение текстуры Khronos</comment>
- <comment xml:lang="sk">Obrázok textúry Khronos</comment>
- <comment xml:lang="sr">слика Кронос текстуре</comment>
- <comment xml:lang="sv">Khronos-texturbild</comment>
- <comment xml:lang="tr">Khronos kaplama görüntüsü</comment>
- <comment xml:lang="uk">зображення текстури Khronos</comment>
- <comment xml:lang="zh_CN">Khronos 纹理图像</comment>
<comment xml:lang="zh_TW">Khronos 紋理影像</comment>
+ <comment xml:lang="zh_CN">Khronos 纹理图像</comment>
+ <comment xml:lang="uk">зображення текстури Khronos</comment>
+ <comment xml:lang="tr">Khronos kaplama görüntüsü</comment>
+ <comment xml:lang="sv">Khronos-texturbild</comment>
+ <comment xml:lang="sr">слика Кронос текстуре</comment>
+ <comment xml:lang="sl">Slika teksture Khronos</comment>
+ <comment xml:lang="si">ක්‍රොනොස් වයනය රූපය</comment>
+ <comment xml:lang="sk">Obrázok textúry Khronos</comment>
+ <comment xml:lang="ru">Изображение текстуры Khronos</comment>
+ <comment xml:lang="pt_BR">Imagem de textura do Khronos</comment>
+ <comment xml:lang="pl">Obraz tekstury Khronos</comment>
+ <comment xml:lang="nl">Khronos-textuurafbeelding</comment>
+ <comment xml:lang="ko">크로노스 텍스처 파일</comment>
+ <comment xml:lang="kk">Khronos текстура суреті</comment>
+ <comment xml:lang="ja">Khronos テクスチャ画像</comment>
+ <comment xml:lang="it">Immagine texture Khronos</comment>
+ <comment xml:lang="is">Khronos efnisáferðarmynd</comment>
+ <comment xml:lang="id">Citra tekstur Khronos</comment>
+ <comment xml:lang="hu">Khronos textúra kép</comment>
+ <comment xml:lang="hr">Khronos tekstura slika</comment>
+ <comment xml:lang="he">תמונת מרקם של Khronos</comment>
+ <comment xml:lang="gl">Imaxe de textura Khronos</comment>
+ <comment xml:lang="ga">íomhá uigeachta Khronos</comment>
+ <comment xml:lang="fur">imagjin di struture/texture Khronos</comment>
+ <comment xml:lang="fr">image de texture Khronos</comment>
+ <comment xml:lang="fi">Khronos-tekstuurikuva</comment>
+ <comment xml:lang="eu">Khronos testura irudia</comment>
+ <comment xml:lang="es">imagen de textura de Khronos</comment>
+ <comment xml:lang="en_GB">Khronos texture image</comment>
+ <comment xml:lang="de">Khronos-Texturbild</comment>
+ <comment xml:lang="da">Khronos-strukturbillede</comment>
+ <comment xml:lang="cs">obrázek s texturou Khronos</comment>
+ <comment xml:lang="ca">imatge de textura de Khronos</comment>
+ <comment xml:lang="bg">Изображение — текстура за Khronos</comment>
+ <comment xml:lang="be">выява тэкстуры Khronos</comment>
+ <comment xml:lang="ar">صور نسيج Khronos</comment>
+ <comment xml:lang="af">Khronos-tekstuurbeeld</comment>
<magic priority="80">
- <match value="0xAB4B5458" type="big32" offset="0">
- <match value="0x203131BB" type="big32" offset="4">
- <match value="0x0D0A1A0A" type="big32" offset="8"/>
+ <match type="big32" value="0xAB4B5458" offset="0">
+ <match type="big32" value="0x203131BB" offset="4">
+ <match type="big32" value="0x0D0A1A0A" offset="8"/>
</match>
</match>
</magic>
<glob pattern="*.ktx"/>
</mime-type>
+ <mime-type type="image/ktx2">
+ <comment>Khronos texture image</comment>
+ <comment xml:lang="zh_TW">Khronos 紋理影像</comment>
+ <comment xml:lang="zh_CN">Khronos 纹理图像</comment>
+ <comment xml:lang="uk">зображення текстури Khronos</comment>
+ <comment xml:lang="tr">Khronos kaplama görüntüsü</comment>
+ <comment xml:lang="sv">Khronos-texturbild</comment>
+ <comment xml:lang="sr">слика Кронос текстуре</comment>
+ <comment xml:lang="sl">Slika teksture Khronos</comment>
+ <comment xml:lang="si">ක්‍රොනොස් වයනය රූපය</comment>
+ <comment xml:lang="sk">Obrázok textúry Khronos</comment>
+ <comment xml:lang="ru">Изображение текстуры Khronos</comment>
+ <comment xml:lang="pt_BR">Imagem de textura do Khronos</comment>
+ <comment xml:lang="pl">Obraz tekstury Khronos</comment>
+ <comment xml:lang="nl">Khronos-textuurafbeelding</comment>
+ <comment xml:lang="ko">크로노스 텍스처 파일</comment>
+ <comment xml:lang="kk">Khronos текстура суреті</comment>
+ <comment xml:lang="ja">Khronos テクスチャ画像</comment>
+ <comment xml:lang="it">Immagine texture Khronos</comment>
+ <comment xml:lang="is">Khronos efnisáferðarmynd</comment>
+ <comment xml:lang="id">Citra tekstur Khronos</comment>
+ <comment xml:lang="hu">Khronos textúra kép</comment>
+ <comment xml:lang="hr">Khronos tekstura slika</comment>
+ <comment xml:lang="he">תמונת מרקם של Khronos</comment>
+ <comment xml:lang="gl">Imaxe de textura Khronos</comment>
+ <comment xml:lang="ga">íomhá uigeachta Khronos</comment>
+ <comment xml:lang="fur">imagjin di struture/texture Khronos</comment>
+ <comment xml:lang="fr">image de texture Khronos</comment>
+ <comment xml:lang="fi">Khronos-tekstuurikuva</comment>
+ <comment xml:lang="eu">Khronos testura irudia</comment>
+ <comment xml:lang="es">imagen de textura de Khronos</comment>
+ <comment xml:lang="en_GB">Khronos texture image</comment>
+ <comment xml:lang="de">Khronos-Texturbild</comment>
+ <comment xml:lang="da">Khronos-strukturbillede</comment>
+ <comment xml:lang="cs">obrázek s texturou Khronos</comment>
+ <comment xml:lang="ca">imatge de textura de Khronos</comment>
+ <comment xml:lang="bg">Изображение — текстура за Khronos</comment>
+ <comment xml:lang="be">выява тэкстуры Khronos</comment>
+ <comment xml:lang="ar">صور نسيج Khronos</comment>
+ <comment xml:lang="af">Khronos-tekstuurbeeld</comment>
+ <magic priority="80">
+ <match type="big32" value="0xAB4B5458" offset="0">
+ <match type="big32" value="0x203230BB" offset="4">
+ <match type="big32" value="0x0D0A1A0A" offset="8"/>
+ </match>
+ </match>
+ </magic>
+ <glob pattern="*.ktx2"/>
+ </mime-type>
+ <mime-type type="image/astc">
+ <comment>ASTC texture</comment>
+ <comment xml:lang="uk">текстура ASTC</comment>
+ <comment xml:lang="tr">ASTC dokusu</comment>
+ <comment xml:lang="sv">ASTC-textur</comment>
+ <comment xml:lang="sl">Tekstura ASTC</comment>
+ <comment xml:lang="si">ASTC වයනය</comment>
+ <comment xml:lang="ru">Текстура ASTC</comment>
+ <comment xml:lang="pt_BR">Textura ASTC</comment>
+ <comment xml:lang="pl">Tekstura ASTC</comment>
+ <comment xml:lang="nl">ASTC-textuur</comment>
+ <comment xml:lang="ko">ASTC 텍스처</comment>
+ <comment xml:lang="kk">ASTC текстурасы</comment>
+ <comment xml:lang="ja">ASTC テクスチャ</comment>
+ <comment xml:lang="it">Texture ASTC</comment>
+ <comment xml:lang="is">ASTC efnisáferð</comment>
+ <comment xml:lang="id">tekstur ASTC</comment>
+ <comment xml:lang="hu">ASTC textúra</comment>
+ <comment xml:lang="hr">ASTC tekstura</comment>
+ <comment xml:lang="he">מרקם של ASTC</comment>
+ <comment xml:lang="gl">Textura ASTC</comment>
+ <comment xml:lang="fr">Texture ASTC</comment>
+ <comment xml:lang="fi">ASTC-tekstuuri</comment>
+ <comment xml:lang="es">textura ASTC</comment>
+ <comment xml:lang="en_GB">ASTC texture</comment>
+ <comment xml:lang="de">ASTC-Textur</comment>
+ <comment xml:lang="da">ASTC-struktur</comment>
+ <comment xml:lang="ca">textura ASTC</comment>
+ <comment xml:lang="be">тэкстура ASTC</comment>
+ <comment xml:lang="ar">نسيج ASTC</comment>
+ <acronym>ASTC</acronym>
+ <expanded-acronym>Advanced Scalable Texture Compression</expanded-acronym>
+ <glob pattern="*.astc"/>
+ <magic priority="80">
+ <match type="little32" value="0x5CA1AB13" offset="0"/>
+ </magic>
+ </mime-type>
<mime-type type="video/vnd.vivo">
<comment>Vivo video</comment>
- <comment xml:lang="ar">Vivo مرئي</comment>
- <comment xml:lang="ast">Videu en Vivo</comment>
- <comment xml:lang="az">Vivo video faylı</comment>
- <comment xml:lang="be@latin">Videa Vivo</comment>
- <comment xml:lang="bg">Видео — Vivo</comment>
- <comment xml:lang="ca">vídeo Vivo</comment>
- <comment xml:lang="cs">video Vivo</comment>
- <comment xml:lang="cy">Fideo Vivo</comment>
- <comment xml:lang="da">Vivo-video</comment>
- <comment xml:lang="de">Vivo-Video</comment>
- <comment xml:lang="el">Βίντεο Vivo</comment>
- <comment xml:lang="en_GB">Vivo video</comment>
- <comment xml:lang="eo">Vivo-video</comment>
- <comment xml:lang="es">vídeo Vivo</comment>
- <comment xml:lang="eu">Vivo bideoa</comment>
- <comment xml:lang="fi">Vivo-video</comment>
- <comment xml:lang="fo">Vivo video</comment>
- <comment xml:lang="fr">vidéo Vivo</comment>
- <comment xml:lang="ga">físeán Vivo</comment>
- <comment xml:lang="gl">vídeo Vivo</comment>
- <comment xml:lang="he">וידאו של Vivo</comment>
- <comment xml:lang="hr">Vivo video snimka</comment>
- <comment xml:lang="hu">Vivo-videó</comment>
- <comment xml:lang="ia">Video Vivo</comment>
- <comment xml:lang="id">Video Vivo</comment>
- <comment xml:lang="it">Video Vivo</comment>
- <comment xml:lang="ja">Vivo 動画</comment>
- <comment xml:lang="kk">Vivo видеосы</comment>
- <comment xml:lang="ko">Vivo 동영상</comment>
- <comment xml:lang="lt">Vivo vaizdo įrašas</comment>
- <comment xml:lang="lv">Vivo video</comment>
- <comment xml:lang="ms">Video Vivo</comment>
- <comment xml:lang="nb">Vivo-film</comment>
- <comment xml:lang="nl">Vivo-video</comment>
- <comment xml:lang="nn">Vivo-film</comment>
- <comment xml:lang="oc">vidèo Vivo</comment>
- <comment xml:lang="pl">Plik wideo Vivo</comment>
- <comment xml:lang="pt">vídeo Vivo</comment>
- <comment xml:lang="pt_BR">Vídeo Vivo</comment>
- <comment xml:lang="ro">Video Vivo</comment>
- <comment xml:lang="ru">Видео Vivo</comment>
- <comment xml:lang="sk">Video Vivo</comment>
- <comment xml:lang="sl">Video datoteka Vivo</comment>
- <comment xml:lang="sq">Video Vivo</comment>
- <comment xml:lang="sr">Виво видео</comment>
- <comment xml:lang="sv">Vivo-video</comment>
- <comment xml:lang="tr">Vivo videosu</comment>
- <comment xml:lang="uk">відео Vivo</comment>
- <comment xml:lang="vi">Ảnh động Vivo</comment>
- <comment xml:lang="zh_CN">Vivo 视频</comment>
<comment xml:lang="zh_TW">Vivo 視訊</comment>
+ <comment xml:lang="zh_CN">Vivo 视频</comment>
+ <comment xml:lang="vi">Ảnh động Vivo</comment>
+ <comment xml:lang="uk">відео Vivo</comment>
+ <comment xml:lang="tr">Vivo videosu</comment>
+ <comment xml:lang="sv">Vivo-video</comment>
+ <comment xml:lang="sr">Виво видео</comment>
+ <comment xml:lang="sq">video Vivo</comment>
+ <comment xml:lang="sl">Video datoteka Vivo</comment>
+ <comment xml:lang="si">Vivo වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Vivo</comment>
+ <comment xml:lang="ru">Видео Vivo</comment>
+ <comment xml:lang="ro">Video Vivo</comment>
+ <comment xml:lang="pt_BR">Vídeo Vivo</comment>
+ <comment xml:lang="pt">vídeo Vivo</comment>
+ <comment xml:lang="pl">Plik wideo Vivo</comment>
+ <comment xml:lang="oc">vidèo Vivo</comment>
+ <comment xml:lang="nn">Vivo-film</comment>
+ <comment xml:lang="nl">Vivo-video</comment>
+ <comment xml:lang="nb">Vivo-film</comment>
+ <comment xml:lang="ms">Video Vivo</comment>
+ <comment xml:lang="lv">Vivo video</comment>
+ <comment xml:lang="lt">Vivo vaizdo įrašas</comment>
+ <comment xml:lang="ko">Vivo 동영상</comment>
+ <comment xml:lang="kk">Vivo видеосы</comment>
+ <comment xml:lang="ja">Vivo 動画</comment>
+ <comment xml:lang="it">Video Vivo</comment>
+ <comment xml:lang="is">Vivo myndskeið</comment>
+ <comment xml:lang="id">Video Vivo</comment>
+ <comment xml:lang="ia">Video Vivo</comment>
+ <comment xml:lang="hu">Vivo-videó</comment>
+ <comment xml:lang="hr">Vivo video snimka</comment>
+ <comment xml:lang="he">וידאו של Vivo</comment>
+ <comment xml:lang="gl">vídeo Vivo</comment>
+ <comment xml:lang="ga">físeán Vivo</comment>
+ <comment xml:lang="fur">video Vivo</comment>
+ <comment xml:lang="fr">vidéo Vivo</comment>
+ <comment xml:lang="fo">Vivo video</comment>
+ <comment xml:lang="fi">Vivo-video</comment>
+ <comment xml:lang="eu">Vivo bideoa</comment>
+ <comment xml:lang="es">vídeo Vivo</comment>
+ <comment xml:lang="eo">Vivo-video</comment>
+ <comment xml:lang="en_GB">Vivo video</comment>
+ <comment xml:lang="el">Βίντεο Vivo</comment>
+ <comment xml:lang="de">Vivo-Video</comment>
+ <comment xml:lang="da">Vivo-video</comment>
+ <comment xml:lang="cy">Fideo Vivo</comment>
+ <comment xml:lang="cs">video Vivo</comment>
+ <comment xml:lang="ca">vídeo Vivo</comment>
+ <comment xml:lang="bg">Видео — Vivo</comment>
+ <comment xml:lang="be@latin">Videa Vivo</comment>
+ <comment xml:lang="be">відэа Vivo</comment>
+ <comment xml:lang="az">Vivo video faylı</comment>
+ <comment xml:lang="ast">Videu en Vivo</comment>
+ <comment xml:lang="ar">فيديو Vivo</comment>
+ <comment xml:lang="af">Vivo-video</comment>
<alias type="video/vivo"/>
<glob pattern="*.viv"/>
<glob pattern="*.vivo"/>
</mime-type>
<mime-type type="video/wavelet">
<comment>Wavelet video</comment>
- <comment xml:lang="ar">Wavelet مرئي</comment>
- <comment xml:lang="ast">Videu en Wavelet</comment>
- <comment xml:lang="az">Wavelet video faylı</comment>
- <comment xml:lang="be@latin">Videa Wavelet</comment>
- <comment xml:lang="bg">Видео — Wavelet</comment>
- <comment xml:lang="ca">vídeo Wavelet</comment>
- <comment xml:lang="cs">video Wavelet</comment>
- <comment xml:lang="cy">Fideo Wavelet</comment>
- <comment xml:lang="da">Waveletvideo</comment>
- <comment xml:lang="de">Wavelet-Video</comment>
- <comment xml:lang="el">Βίντεο Wavelet</comment>
- <comment xml:lang="en_GB">Wavelet video</comment>
- <comment xml:lang="eo">Wavelet-video</comment>
- <comment xml:lang="es">vídeo Wavelet</comment>
- <comment xml:lang="eu">Wavelet bideoa</comment>
- <comment xml:lang="fi">Wavelet-video</comment>
- <comment xml:lang="fo">Wavelet video</comment>
- <comment xml:lang="fr">vidéo Wavelet</comment>
- <comment xml:lang="ga">físeán Wavelet</comment>
- <comment xml:lang="gl">vídeo Wavelet</comment>
- <comment xml:lang="he">וידאו של Wavelet</comment>
- <comment xml:lang="hr">Wavelet video snimka</comment>
- <comment xml:lang="hu">Wavelet-videó</comment>
- <comment xml:lang="ia">Video Wavelet</comment>
- <comment xml:lang="id">Video Wavelet</comment>
- <comment xml:lang="it">Video Wavelet</comment>
- <comment xml:lang="ja">Wavelet 動画</comment>
- <comment xml:lang="kk">Wavelet видеосы</comment>
- <comment xml:lang="ko">Wavelet 동영상</comment>
- <comment xml:lang="lt">Wavelet vaizdo įrašas</comment>
- <comment xml:lang="lv">Wavelet video</comment>
- <comment xml:lang="ms">Video Wavelet</comment>
- <comment xml:lang="nb">Wavelet-film</comment>
- <comment xml:lang="nl">Wavelet-video</comment>
- <comment xml:lang="nn">Wavelet video</comment>
- <comment xml:lang="oc">vidèo Wavelet</comment>
- <comment xml:lang="pl">Plik wideo Wavelet</comment>
- <comment xml:lang="pt">vídeo Wavelet</comment>
- <comment xml:lang="pt_BR">Vídeo Wavelet</comment>
- <comment xml:lang="ro">Video Wavelet</comment>
- <comment xml:lang="ru">Видео Wavelet</comment>
- <comment xml:lang="sk">Video Wavelet</comment>
- <comment xml:lang="sl">Video datoteka Wavelet</comment>
- <comment xml:lang="sq">Video Wavelet</comment>
- <comment xml:lang="sr">Вејвелет видео</comment>
- <comment xml:lang="sv">Wavelet-video</comment>
- <comment xml:lang="tr">Wavelet videosu</comment>
- <comment xml:lang="uk">відеокліп Wavelet</comment>
- <comment xml:lang="vi">Ảnh động Wavelet</comment>
- <comment xml:lang="zh_CN">Wavelet 视频</comment>
<comment xml:lang="zh_TW">Wavelet 視訊</comment>
+ <comment xml:lang="zh_CN">Wavelet 视频</comment>
+ <comment xml:lang="vi">Ảnh động Wavelet</comment>
+ <comment xml:lang="uk">відеокліп Wavelet</comment>
+ <comment xml:lang="tr">Wavelet videosu</comment>
+ <comment xml:lang="sv">Wavelet-video</comment>
+ <comment xml:lang="sr">Вејвелет видео</comment>
+ <comment xml:lang="sq">video Wavelet</comment>
+ <comment xml:lang="sl">Video datoteka Wavelet</comment>
+ <comment xml:lang="si">Wavelet වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Wavelet</comment>
+ <comment xml:lang="ru">Видео Wavelet</comment>
+ <comment xml:lang="ro">Video Wavelet</comment>
+ <comment xml:lang="pt_BR">Vídeo Wavelet</comment>
+ <comment xml:lang="pt">vídeo Wavelet</comment>
+ <comment xml:lang="pl">Plik wideo Wavelet</comment>
+ <comment xml:lang="oc">vidèo Wavelet</comment>
+ <comment xml:lang="nn">Wavelet video</comment>
+ <comment xml:lang="nl">Wavelet-video</comment>
+ <comment xml:lang="nb">Wavelet-film</comment>
+ <comment xml:lang="ms">Video Wavelet</comment>
+ <comment xml:lang="lv">Wavelet video</comment>
+ <comment xml:lang="lt">Wavelet vaizdo įrašas</comment>
+ <comment xml:lang="ko">Wavelet 동영상</comment>
+ <comment xml:lang="kk">Wavelet видеосы</comment>
+ <comment xml:lang="ja">Wavelet 動画</comment>
+ <comment xml:lang="it">Video Wavelet</comment>
+ <comment xml:lang="is">Wavelet myndskeið</comment>
+ <comment xml:lang="id">Video Wavelet</comment>
+ <comment xml:lang="ia">Video Wavelet</comment>
+ <comment xml:lang="hu">Wavelet-videó</comment>
+ <comment xml:lang="hr">Wavelet video snimka</comment>
+ <comment xml:lang="he">וידאו של Wavelet</comment>
+ <comment xml:lang="gl">vídeo Wavelet</comment>
+ <comment xml:lang="ga">físeán Wavelet</comment>
+ <comment xml:lang="fur">video Wavelet</comment>
+ <comment xml:lang="fr">vidéo Wavelet</comment>
+ <comment xml:lang="fo">Wavelet video</comment>
+ <comment xml:lang="fi">Wavelet-video</comment>
+ <comment xml:lang="eu">Wavelet bideoa</comment>
+ <comment xml:lang="es">vídeo Wavelet</comment>
+ <comment xml:lang="eo">Wavelet-video</comment>
+ <comment xml:lang="en_GB">Wavelet video</comment>
+ <comment xml:lang="el">Βίντεο Wavelet</comment>
+ <comment xml:lang="de">Wavelet-Video</comment>
+ <comment xml:lang="da">Wavelet-video</comment>
+ <comment xml:lang="cy">Fideo Wavelet</comment>
+ <comment xml:lang="cs">video Wavelet</comment>
+ <comment xml:lang="ca">vídeo Wavelet</comment>
+ <comment xml:lang="bg">Видео — Wavelet</comment>
+ <comment xml:lang="be@latin">Videa Wavelet</comment>
+ <comment xml:lang="be">відэа Wavelet</comment>
+ <comment xml:lang="az">Wavelet video faylı</comment>
+ <comment xml:lang="ast">Videu en Wavelet</comment>
+ <comment xml:lang="ar">فيديو Wavelet</comment>
+ <comment xml:lang="af">Wavelet-video</comment>
</mime-type>
<mime-type type="video/x-anim">
<comment>ANIM animation</comment>
- <comment xml:lang="ar">تحريكة ANIM</comment>
- <comment xml:lang="az">ANIM animasiyası</comment>
- <comment xml:lang="be@latin">Animacyja ANIM</comment>
- <comment xml:lang="bg">Анимация — ANIM</comment>
- <comment xml:lang="ca">animació ANIM</comment>
- <comment xml:lang="cs">animace ANIM</comment>
- <comment xml:lang="cy">Animeiddiad ANIM</comment>
- <comment xml:lang="da">ANIM-animation</comment>
- <comment xml:lang="de">ANIM-Animation</comment>
- <comment xml:lang="el">Κινούμενο σχέδιο ANIM</comment>
- <comment xml:lang="en_GB">ANIM animation</comment>
- <comment xml:lang="eo">ANIM-animacio</comment>
- <comment xml:lang="es">animación ANIM</comment>
- <comment xml:lang="eu">ANIM animazioa</comment>
- <comment xml:lang="fi">ANIM-animaatio</comment>
- <comment xml:lang="fo">ANIM teknmyndagerð</comment>
- <comment xml:lang="fr">animation ANIM</comment>
- <comment xml:lang="ga">beochan ANIM</comment>
- <comment xml:lang="gl">animación ANIM</comment>
- <comment xml:lang="he">הנפשת ANIM</comment>
- <comment xml:lang="hr">ANIM animacija</comment>
- <comment xml:lang="hu">ANIM-animáció</comment>
- <comment xml:lang="ia">Animation ANIM</comment>
- <comment xml:lang="id">Animasi ANIM</comment>
- <comment xml:lang="it">Animazione ANIM</comment>
- <comment xml:lang="ja">ANIM アニメーション</comment>
- <comment xml:lang="ka">ANIM ანიმაცია</comment>
- <comment xml:lang="kk">ANIM анимациясы</comment>
- <comment xml:lang="ko">ANIM 동화상</comment>
- <comment xml:lang="lt">ANIM animacija</comment>
- <comment xml:lang="lv">ANIM animācija</comment>
- <comment xml:lang="ms">Animasi ANIM</comment>
- <comment xml:lang="nb">ANIM-animasjon</comment>
- <comment xml:lang="nl">ANIM-animatie</comment>
- <comment xml:lang="nn">ANIM-animasjon</comment>
- <comment xml:lang="oc">animacion ANIM</comment>
- <comment xml:lang="pl">Plik animacji ANIM</comment>
- <comment xml:lang="pt">animação ANIM</comment>
- <comment xml:lang="pt_BR">Animação ANIM</comment>
- <comment xml:lang="ro">Animație ANIM</comment>
- <comment xml:lang="ru">Анимация ANIM</comment>
- <comment xml:lang="sk">Animácia ANIM</comment>
- <comment xml:lang="sl">Datoteka animacije ANIM</comment>
- <comment xml:lang="sq">Animim ANIM</comment>
- <comment xml:lang="sr">АНИМ анимација</comment>
- <comment xml:lang="sv">ANIM-animering</comment>
- <comment xml:lang="tr">ANIM canlandırması</comment>
- <comment xml:lang="uk">анімація ANIM</comment>
- <comment xml:lang="vi">Hoạt ảnh ANIM</comment>
- <comment xml:lang="zh_CN">ANIM 动画</comment>
<comment xml:lang="zh_TW">ANIM 動畫</comment>
+ <comment xml:lang="zh_CN">ANIM 动画</comment>
+ <comment xml:lang="vi">Hoạt ảnh ANIM</comment>
+ <comment xml:lang="uk">анімація ANIM</comment>
+ <comment xml:lang="tr">ANIM canlandırması</comment>
+ <comment xml:lang="sv">ANIM-animering</comment>
+ <comment xml:lang="sr">АНИМ анимација</comment>
+ <comment xml:lang="sq">animacion ANIM</comment>
+ <comment xml:lang="sl">Datoteka animacije ANIM</comment>
+ <comment xml:lang="si">ANIM සජීවිකරණය</comment>
+ <comment xml:lang="sk">Animácia ANIM</comment>
+ <comment xml:lang="ru">Анимация ANIM</comment>
+ <comment xml:lang="ro">Animație ANIM</comment>
+ <comment xml:lang="pt_BR">Animação ANIM</comment>
+ <comment xml:lang="pt">animação ANIM</comment>
+ <comment xml:lang="pl">Plik animacji ANIM</comment>
+ <comment xml:lang="oc">animacion ANIM</comment>
+ <comment xml:lang="nn">ANIM-animasjon</comment>
+ <comment xml:lang="nl">ANIM-animatie</comment>
+ <comment xml:lang="nb">ANIM-animasjon</comment>
+ <comment xml:lang="ms">Animasi ANIM</comment>
+ <comment xml:lang="lv">ANIM animācija</comment>
+ <comment xml:lang="lt">ANIM animacija</comment>
+ <comment xml:lang="ko">ANIM 동화상</comment>
+ <comment xml:lang="kk">ANIM анимациясы</comment>
+ <comment xml:lang="ka">ANIM ანიმაცია</comment>
+ <comment xml:lang="ja">ANIM アニメーション</comment>
+ <comment xml:lang="it">Animazione ANIM</comment>
+ <comment xml:lang="is">ANIM hreyfimynd</comment>
+ <comment xml:lang="id">Animasi ANIM</comment>
+ <comment xml:lang="ia">Animation ANIM</comment>
+ <comment xml:lang="hu">ANIM-animáció</comment>
+ <comment xml:lang="hr">ANIM animacija</comment>
+ <comment xml:lang="he">הנפשת ANIM</comment>
+ <comment xml:lang="gl">animación ANIM</comment>
+ <comment xml:lang="ga">beochan ANIM</comment>
+ <comment xml:lang="fur">animazion ANIM</comment>
+ <comment xml:lang="fr">animation ANIM</comment>
+ <comment xml:lang="fo">ANIM teknmyndagerð</comment>
+ <comment xml:lang="fi">ANIM-animaatio</comment>
+ <comment xml:lang="eu">ANIM animazioa</comment>
+ <comment xml:lang="es">animación ANIM</comment>
+ <comment xml:lang="eo">ANIM-animacio</comment>
+ <comment xml:lang="en_GB">ANIM animation</comment>
+ <comment xml:lang="el">Κινούμενο σχέδιο ANIM</comment>
+ <comment xml:lang="de">ANIM-Animation</comment>
+ <comment xml:lang="da">ANIM-animation</comment>
+ <comment xml:lang="cy">Animeiddiad ANIM</comment>
+ <comment xml:lang="cs">animace ANIM</comment>
+ <comment xml:lang="ca">animació ANIM</comment>
+ <comment xml:lang="bg">Анимация — ANIM</comment>
+ <comment xml:lang="be@latin">Animacyja ANIM</comment>
+ <comment xml:lang="be">анімацыя ANIM</comment>
+ <comment xml:lang="az">ANIM animasiyası</comment>
+ <comment xml:lang="ar">تحريكة ANIM</comment>
+ <comment xml:lang="af">ANIM-animasie</comment>
<glob pattern="*.anim[1-9j]"/>
</mime-type>
<mime-type type="video/x-flic">
<comment>FLIC animation</comment>
- <comment xml:lang="ar">تحريكة FLIC</comment>
- <comment xml:lang="be@latin">Animacyja FLIC</comment>
- <comment xml:lang="bg">Анимация — FLIC</comment>
- <comment xml:lang="ca">animació FLIC</comment>
- <comment xml:lang="cs">animace FLIC</comment>
- <comment xml:lang="da">FLIC-animation</comment>
- <comment xml:lang="de">FLIC-Animation</comment>
- <comment xml:lang="el">Κινούμενο σχέδιο FLIC</comment>
- <comment xml:lang="en_GB">FLIC animation</comment>
- <comment xml:lang="es">animación FLIC</comment>
- <comment xml:lang="eu">FLIC animazioa</comment>
- <comment xml:lang="fi">FLIC-animaatio</comment>
- <comment xml:lang="fo">FLIC teknimyndagerð</comment>
- <comment xml:lang="fr">animation FLIC</comment>
- <comment xml:lang="ga">beochan FLIC</comment>
- <comment xml:lang="gl">animación FLIC</comment>
- <comment xml:lang="he">הנפשת FLIC</comment>
- <comment xml:lang="hr">FLIC animacija</comment>
- <comment xml:lang="hu">FLIC animáció</comment>
- <comment xml:lang="ia">Animation FLIC</comment>
- <comment xml:lang="id">Animasi FLIC</comment>
- <comment xml:lang="it">Animazione FLIC</comment>
- <comment xml:lang="ja">FLIC アニメーション</comment>
- <comment xml:lang="ka">FLIC ანიმაცია</comment>
- <comment xml:lang="kk">FLIC анимациясы</comment>
- <comment xml:lang="ko">FLIC 동화상</comment>
- <comment xml:lang="lt">FLIC animacija</comment>
- <comment xml:lang="lv">FLIC animācija</comment>
- <comment xml:lang="nb">FLIC-animasjon</comment>
- <comment xml:lang="nl">FLIC-animatie</comment>
- <comment xml:lang="nn">FLIC-animasjon</comment>
- <comment xml:lang="oc">animacion FLIC</comment>
- <comment xml:lang="pl">Plik animacji FLIC</comment>
- <comment xml:lang="pt">animação FLIC</comment>
- <comment xml:lang="pt_BR">Animação FLIC</comment>
- <comment xml:lang="ro">Animație FLIC</comment>
- <comment xml:lang="ru">Анимация FLIC</comment>
- <comment xml:lang="sk">Animácia FLIC</comment>
- <comment xml:lang="sl">Datoteka animacije FLIC</comment>
- <comment xml:lang="sq">Animim FLIC</comment>
- <comment xml:lang="sr">ФЛИЦ анимација</comment>
- <comment xml:lang="sv">FLIC-animering</comment>
- <comment xml:lang="tr">FLIC animasyonu</comment>
- <comment xml:lang="uk">анімація FLIC</comment>
- <comment xml:lang="vi">Hoạt ảnh FLIC</comment>
- <comment xml:lang="zh_CN">FLIC 动画</comment>
<comment xml:lang="zh_TW">FLIC 動畫</comment>
+ <comment xml:lang="zh_CN">FLIC 动画</comment>
+ <comment xml:lang="vi">Hoạt ảnh FLIC</comment>
+ <comment xml:lang="uk">анімація FLIC</comment>
+ <comment xml:lang="tr">FLIC animasyonu</comment>
+ <comment xml:lang="sv">FLIC-animering</comment>
+ <comment xml:lang="sr">ФЛИЦ анимација</comment>
+ <comment xml:lang="sq">animacion FLIC</comment>
+ <comment xml:lang="sl">Datoteka animacije FLIC</comment>
+ <comment xml:lang="si">FLIC සජීවිකරණය</comment>
+ <comment xml:lang="sk">Animácia FLIC</comment>
+ <comment xml:lang="ru">Анимация FLIC</comment>
+ <comment xml:lang="ro">Animație FLIC</comment>
+ <comment xml:lang="pt_BR">Animação FLIC</comment>
+ <comment xml:lang="pt">animação FLIC</comment>
+ <comment xml:lang="pl">Plik animacji FLIC</comment>
+ <comment xml:lang="oc">animacion FLIC</comment>
+ <comment xml:lang="nn">FLIC-animasjon</comment>
+ <comment xml:lang="nl">FLIC-animatie</comment>
+ <comment xml:lang="nb">FLIC-animasjon</comment>
+ <comment xml:lang="lv">FLIC animācija</comment>
+ <comment xml:lang="lt">FLIC animacija</comment>
+ <comment xml:lang="ko">FLIC 동화상</comment>
+ <comment xml:lang="kk">FLIC анимациясы</comment>
+ <comment xml:lang="ka">FLIC ანიმაცია</comment>
+ <comment xml:lang="ja">FLIC アニメーション</comment>
+ <comment xml:lang="it">Animazione FLIC</comment>
+ <comment xml:lang="is">FLIC-hreyfimynd</comment>
+ <comment xml:lang="id">Animasi FLIC</comment>
+ <comment xml:lang="ia">Animation FLIC</comment>
+ <comment xml:lang="hu">FLIC animáció</comment>
+ <comment xml:lang="hr">FLIC animacija</comment>
+ <comment xml:lang="he">הנפשת FLIC</comment>
+ <comment xml:lang="gl">animación FLIC</comment>
+ <comment xml:lang="ga">beochan FLIC</comment>
+ <comment xml:lang="fur">animazion FLIC</comment>
+ <comment xml:lang="fr">animation FLIC</comment>
+ <comment xml:lang="fo">FLIC teknimyndagerð</comment>
+ <comment xml:lang="fi">FLIC-animaatio</comment>
+ <comment xml:lang="eu">FLIC animazioa</comment>
+ <comment xml:lang="es">animación FLIC</comment>
+ <comment xml:lang="en_GB">FLIC animation</comment>
+ <comment xml:lang="el">Κινούμενο σχέδιο FLIC</comment>
+ <comment xml:lang="de">FLIC-Animation</comment>
+ <comment xml:lang="da">FLIC-animation</comment>
+ <comment xml:lang="cs">animace FLIC</comment>
+ <comment xml:lang="ca">animació FLIC</comment>
+ <comment xml:lang="bg">Анимация — FLIC</comment>
+ <comment xml:lang="be@latin">Animacyja FLIC</comment>
+ <comment xml:lang="be">анімацыя FLIC</comment>
+ <comment xml:lang="ar">تحريكة FLIC</comment>
+ <comment xml:lang="af">FLIC-animasie</comment>
<alias type="video/fli"/>
<alias type="video/x-fli"/>
- <magic priority="50">
- <match value="0xAF11" type="little16" offset="0"/>
- <match value="0xAF12" type="little16" offset="0"/>
+ <magic>
+ <match type="little16" value="0xAF11" offset="0"/>
+ <match type="little16" value="0xAF12" offset="0"/>
</magic>
<glob pattern="*.fli"/>
<glob pattern="*.flc"/>
</mime-type>
<mime-type type="application/x-hwp">
<comment>Haansoft Hangul document</comment>
- <comment xml:lang="ar">مستند Haansoft Hangul</comment>
- <comment xml:lang="ast">Documentu de Haansoft Hangul</comment>
- <comment xml:lang="be@latin">Dakument Haansoft Hangul</comment>
- <comment xml:lang="bg">Документ — Haansoft Hangul</comment>
- <comment xml:lang="ca">document d'Haansoft Hangul</comment>
- <comment xml:lang="cs">dokument Haansoft Hangul</comment>
- <comment xml:lang="da">Haansoft Hangul-dokument</comment>
- <comment xml:lang="de">Haansoft-Hangul-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Haansoft Hangul</comment>
- <comment xml:lang="en_GB">Haansoft Hangul document</comment>
- <comment xml:lang="es">documento de Haansoft Hangul</comment>
- <comment xml:lang="eu">Haansoft Hangul dokumentua</comment>
- <comment xml:lang="fi">Haansoft Hangul -asiakirja</comment>
- <comment xml:lang="fo">Haansoft Hangul skjal</comment>
- <comment xml:lang="fr">document Haansoft Hangul</comment>
- <comment xml:lang="ga">cáipéis Haansoft Hangul</comment>
- <comment xml:lang="gl">documento de Haansoft Hangul</comment>
- <comment xml:lang="he">מסמך Haansoft Hangul</comment>
- <comment xml:lang="hr">Haansoft Hangul dokument</comment>
- <comment xml:lang="hu">Haansoft hangul dokumentum</comment>
- <comment xml:lang="ia">Documento Haansoft Hangul</comment>
- <comment xml:lang="id">Dokumen Haansoft Hangul</comment>
- <comment xml:lang="it">Documento Haansoft Hangul</comment>
- <comment xml:lang="ja">Haansoft Hangul ドキュメント</comment>
- <comment xml:lang="kk">Haansoft Hangul құжаты</comment>
- <comment xml:lang="ko">한소프트 한글 문서</comment>
- <comment xml:lang="lt">Haansoft Hangul dokumentas</comment>
- <comment xml:lang="lv">Haansoft Hangul dokuments</comment>
- <comment xml:lang="nb">Haansoft Hangul-dokument</comment>
- <comment xml:lang="nl">Haansoft Hangul-document</comment>
- <comment xml:lang="nn">Haansoft Hangul-dokument</comment>
- <comment xml:lang="oc">document Haansoft Hangul</comment>
- <comment xml:lang="pl">Dokument Haansoft Hangul</comment>
- <comment xml:lang="pt">documento Haansoft Hangul</comment>
- <comment xml:lang="pt_BR">Documento do Haansoft Hangul</comment>
- <comment xml:lang="ro">Document Haansoft Hangul</comment>
- <comment xml:lang="ru">Документ Haansoft Hangul</comment>
- <comment xml:lang="sk">Dokument Haansoft Hangul</comment>
- <comment xml:lang="sl">Dokument Haansoft Hangul</comment>
- <comment xml:lang="sq">Dokument Haansoft Hangul</comment>
- <comment xml:lang="sr">Хансофт Хангул документ</comment>
- <comment xml:lang="sv">Haansoft Hangul-dokument</comment>
- <comment xml:lang="tr">Haansoft Hangul belgesi</comment>
- <comment xml:lang="uk">документ Haansoft Hangul</comment>
- <comment xml:lang="vi">Tài liệu Hangul Haansoft</comment>
- <comment xml:lang="zh_CN">Haansoft Hangul 文档</comment>
<comment xml:lang="zh_TW">Haansoft 韓文文件</comment>
+ <comment xml:lang="zh_CN">Haansoft Hangul 文档</comment>
+ <comment xml:lang="vi">Tài liệu Hangul Haansoft</comment>
+ <comment xml:lang="uk">документ Haansoft Hangul</comment>
+ <comment xml:lang="tr">Haansoft Hangul belgesi</comment>
+ <comment xml:lang="sv">Haansoft Hangul-dokument</comment>
+ <comment xml:lang="sr">Хансофт Хангул документ</comment>
+ <comment xml:lang="sq">dokument Haansoft Hangul</comment>
+ <comment xml:lang="sl">Dokument Haansoft Hangul</comment>
+ <comment xml:lang="si">Haansoft Hangul ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Haansoft Hangul</comment>
+ <comment xml:lang="ru">Документ Haansoft Hangul</comment>
+ <comment xml:lang="ro">Document Haansoft Hangul</comment>
+ <comment xml:lang="pt_BR">Documento do Haansoft Hangul</comment>
+ <comment xml:lang="pt">documento Haansoft Hangul</comment>
+ <comment xml:lang="pl">Dokument Haansoft Hangul</comment>
+ <comment xml:lang="oc">document Haansoft Hangul</comment>
+ <comment xml:lang="nn">Haansoft Hangul-dokument</comment>
+ <comment xml:lang="nl">Haansoft Hangul-document</comment>
+ <comment xml:lang="nb">Haansoft Hangul-dokument</comment>
+ <comment xml:lang="lv">Haansoft Hangul dokuments</comment>
+ <comment xml:lang="lt">Haansoft Hangul dokumentas</comment>
+ <comment xml:lang="ko">한소프트 한글 문서</comment>
+ <comment xml:lang="kk">Haansoft Hangul құжаты</comment>
+ <comment xml:lang="ja">Haansoft Hangul ドキュメント</comment>
+ <comment xml:lang="it">Documento Haansoft Hangul</comment>
+ <comment xml:lang="is">Haansoft Hangul skjal</comment>
+ <comment xml:lang="id">Dokumen Haansoft Hangul</comment>
+ <comment xml:lang="ia">Documento Haansoft Hangul</comment>
+ <comment xml:lang="hu">Haansoft hangul dokumentum</comment>
+ <comment xml:lang="hr">Haansoft Hangul dokument</comment>
+ <comment xml:lang="he">מסמך Haansoft Hangul</comment>
+ <comment xml:lang="gl">documento de Haansoft Hangul</comment>
+ <comment xml:lang="ga">cáipéis Haansoft Hangul</comment>
+ <comment xml:lang="fur">document Haansoft Hangul</comment>
+ <comment xml:lang="fr">document Haansoft Hangul</comment>
+ <comment xml:lang="fo">Haansoft Hangul skjal</comment>
+ <comment xml:lang="fi">Haansoft Hangul -asiakirja</comment>
+ <comment xml:lang="eu">Haansoft Hangul dokumentua</comment>
+ <comment xml:lang="es">documento de Haansoft Hangul</comment>
+ <comment xml:lang="en_GB">Haansoft Hangul document</comment>
+ <comment xml:lang="el">Έγγραφο Haansoft Hangul</comment>
+ <comment xml:lang="de">Haansoft-Hangul-Dokument</comment>
+ <comment xml:lang="da">Haansoft Hangul-dokument</comment>
+ <comment xml:lang="cs">dokument Haansoft Hangul</comment>
+ <comment xml:lang="ca">document d'Haansoft Hangul</comment>
+ <comment xml:lang="bg">Документ — Haansoft Hangul</comment>
+ <comment xml:lang="be@latin">Dakument Haansoft Hangul</comment>
+ <comment xml:lang="be">дакумент Haansoft Hangul</comment>
+ <comment xml:lang="ast">Documentu de Haansoft Hangul</comment>
+ <comment xml:lang="ar">مستند Haansoft Hangul</comment>
+ <comment xml:lang="af">Haansoft Hangul-dokument</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="HWP Document File" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="HWP Document File" offset="0"/>
</magic>
<glob pattern="*.hwp"/>
<alias type="application/vnd.haansoft-hwp"/>
</mime-type>
<mime-type type="application/x-hwt">
<comment>Haansoft Hangul document template</comment>
- <comment xml:lang="ar">قالب مستند Haansoft Hangul</comment>
- <comment xml:lang="ast">Plantía de documentu de Haansoft Hangul</comment>
- <comment xml:lang="be@latin">Šablon dakumentu Haansoft Hangul</comment>
- <comment xml:lang="bg">Шаблон за документи — Haansoft Hangul</comment>
- <comment xml:lang="ca">plantilla de document d'Haansoft Hangul</comment>
- <comment xml:lang="cs">šablona dokumentu Haansoft Hangul</comment>
- <comment xml:lang="da">Haansoft Hangul-dokumentskabelon</comment>
- <comment xml:lang="de">Haansoft-Hangul-Dokumentvorlage</comment>
- <comment xml:lang="el">Πρότυπο εγγράφου Haansoft Hangul</comment>
- <comment xml:lang="en_GB">Haansoft Hangul document template</comment>
- <comment xml:lang="es">plantilla de documento de Haansoft Hangul</comment>
- <comment xml:lang="eu">Haansoft Hangul dokumentuaren txantiloia</comment>
- <comment xml:lang="fi">Haansoft Hangul -asiakirjamalli</comment>
- <comment xml:lang="fo">Haansoft Hangul skjalaformur</comment>
- <comment xml:lang="fr">modèle de document Haansoft Hangul</comment>
- <comment xml:lang="ga">teimpléad cháipéis Haansoft Hangul</comment>
- <comment xml:lang="gl">modelo de documento de Haansoft Hangul</comment>
- <comment xml:lang="he">תבנית מסמך של Haansoft Hangul</comment>
- <comment xml:lang="hr">Haansoft Hangul predložak dokumenta</comment>
- <comment xml:lang="hu">Haansoft hangul dokumentumsablon</comment>
- <comment xml:lang="ia">Patrono de documento Haansoft Hangul</comment>
- <comment xml:lang="id">Templat dokumen Haansoft Hangul</comment>
- <comment xml:lang="it">Modello documento Haansoft Hangul</comment>
- <comment xml:lang="ja">Haansoft Hangul ドキュメントテンプレート</comment>
- <comment xml:lang="kk">Haansoft Hangul құжат үлгісі</comment>
- <comment xml:lang="ko">한소프트 한글 문서 서식</comment>
- <comment xml:lang="lt">Haansoft Hangul dokumento šablonas</comment>
- <comment xml:lang="lv">Haansoft Hangul dokumentu veidne</comment>
- <comment xml:lang="nb">Haansoft Hangul-dokumentmal</comment>
- <comment xml:lang="nl">Haansoft Hangul-documentsjabloon</comment>
- <comment xml:lang="nn">Haansoft Hangul-dokumentmal</comment>
- <comment xml:lang="oc">modèl de document Haansoft Hangul</comment>
- <comment xml:lang="pl">Szablon dokumentu Haansoft Hangul</comment>
- <comment xml:lang="pt">modelo de documento Haansoft Hangul</comment>
- <comment xml:lang="pt_BR">Modelo de documento do Haansoft Hangul</comment>
- <comment xml:lang="ro">Document șablon Haansoft Hangul</comment>
- <comment xml:lang="ru">Шаблон документа Haansoft Hangul</comment>
- <comment xml:lang="sk">Šablóna dokumentu Haansoft Hangul</comment>
- <comment xml:lang="sl">Predloga dokumenta Haansoft Hangul</comment>
- <comment xml:lang="sq">Model dokumenti Haansoft Hangul</comment>
- <comment xml:lang="sr">шаблон Хансофт Хангул документа</comment>
- <comment xml:lang="sv">Haansoft Hangul-dokumentmall</comment>
- <comment xml:lang="tr">Haansoft Hangul belge şablonu</comment>
- <comment xml:lang="uk">шаблон документа Haansoft Hangul</comment>
- <comment xml:lang="vi">Mẫu tài liệu Hangul Haansoft</comment>
- <comment xml:lang="zh_CN">Haansoft Hangul 文档模板</comment>
<comment xml:lang="zh_TW">Haansoft 韓文文件範本</comment>
+ <comment xml:lang="zh_CN">Haansoft Hangul 文档模板</comment>
+ <comment xml:lang="vi">Mẫu tài liệu Hangul Haansoft</comment>
+ <comment xml:lang="uk">шаблон документа Haansoft Hangul</comment>
+ <comment xml:lang="tr">Haansoft Hangul belge şablonu</comment>
+ <comment xml:lang="sv">Haansoft Hangul-dokumentmall</comment>
+ <comment xml:lang="sr">шаблон Хансофт Хангул документа</comment>
+ <comment xml:lang="sq">gjedhe dokumentesh Haansoft Hangul</comment>
+ <comment xml:lang="sl">Predloga dokumenta Haansoft Hangul</comment>
+ <comment xml:lang="si">Haansoft Hangul ලේඛන අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna dokumentu Haansoft Hangul</comment>
+ <comment xml:lang="ru">Шаблон документа Haansoft Hangul</comment>
+ <comment xml:lang="ro">Document șablon Haansoft Hangul</comment>
+ <comment xml:lang="pt_BR">Modelo de documento do Haansoft Hangul</comment>
+ <comment xml:lang="pt">modelo de documento Haansoft Hangul</comment>
+ <comment xml:lang="pl">Szablon dokumentu Haansoft Hangul</comment>
+ <comment xml:lang="oc">modèl de document Haansoft Hangul</comment>
+ <comment xml:lang="nn">Haansoft Hangul-dokumentmal</comment>
+ <comment xml:lang="nl">Haansoft Hangul-documentsjabloon</comment>
+ <comment xml:lang="nb">Haansoft Hangul-dokumentmal</comment>
+ <comment xml:lang="lv">Haansoft Hangul dokumentu veidne</comment>
+ <comment xml:lang="lt">Haansoft Hangul dokumento šablonas</comment>
+ <comment xml:lang="ko">한소프트 한글 문서 서식</comment>
+ <comment xml:lang="kk">Haansoft Hangul құжат үлгісі</comment>
+ <comment xml:lang="ja">Haansoft Hangul ドキュメントテンプレート</comment>
+ <comment xml:lang="it">Modello documento Haansoft Hangul</comment>
+ <comment xml:lang="is">Haansoft Hangul sniðskjal</comment>
+ <comment xml:lang="id">Templat dokumen Haansoft Hangul</comment>
+ <comment xml:lang="ia">Patrono de documento Haansoft Hangul</comment>
+ <comment xml:lang="hu">Haansoft hangul dokumentumsablon</comment>
+ <comment xml:lang="hr">Haansoft Hangul predložak dokumenta</comment>
+ <comment xml:lang="he">תבנית מסמך של Haansoft Hangul</comment>
+ <comment xml:lang="gl">modelo de documento de Haansoft Hangul</comment>
+ <comment xml:lang="ga">teimpléad cháipéis Haansoft Hangul</comment>
+ <comment xml:lang="fur">model document Haansoft Hangul</comment>
+ <comment xml:lang="fr">modèle de document Haansoft Hangul</comment>
+ <comment xml:lang="fo">Haansoft Hangul skjalaformur</comment>
+ <comment xml:lang="fi">Haansoft Hangul -asiakirjamalli</comment>
+ <comment xml:lang="eu">Haansoft Hangul dokumentuaren txantiloia</comment>
+ <comment xml:lang="es">plantilla de documento de Haansoft Hangul</comment>
+ <comment xml:lang="en_GB">Haansoft Hangul document template</comment>
+ <comment xml:lang="el">Πρότυπο εγγράφου Haansoft Hangul</comment>
+ <comment xml:lang="de">Haansoft-Hangul-Dokumentvorlage</comment>
+ <comment xml:lang="da">Haansoft Hangul-dokumentskabelon</comment>
+ <comment xml:lang="cs">šablona dokumentu Haansoft Hangul</comment>
+ <comment xml:lang="ca">plantilla de document d'Haansoft Hangul</comment>
+ <comment xml:lang="bg">Шаблон за документи — Haansoft Hangul</comment>
+ <comment xml:lang="be@latin">Šablon dakumentu Haansoft Hangul</comment>
+ <comment xml:lang="be">шаблон дакумента Haansoft Hangul</comment>
+ <comment xml:lang="ast">Plantía de documentu de Haansoft Hangul</comment>
+ <comment xml:lang="ar">قالب مستند Haansoft Hangul</comment>
+ <comment xml:lang="af">Haansoft Hangul-dokumentsjabloon</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.hwt"/>
<alias type="application/vnd.haansoft-hwt"/>
</mime-type>
<mime-type type="video/x-mng">
<comment>MNG animation</comment>
- <comment xml:lang="ar">تحريكة MNG</comment>
- <comment xml:lang="be@latin">Animacyja MNG</comment>
- <comment xml:lang="bg">Анимация — MNG</comment>
- <comment xml:lang="ca">animació MNG</comment>
- <comment xml:lang="cs">animace MNG</comment>
- <comment xml:lang="da">MNG-animation</comment>
- <comment xml:lang="de">MNG-Animation</comment>
- <comment xml:lang="el">Κινούμενο σχέδιο MNG</comment>
- <comment xml:lang="en_GB">MNG animation</comment>
- <comment xml:lang="eo">MNG-animacio</comment>
- <comment xml:lang="es">animación MNG</comment>
- <comment xml:lang="eu">MNG animazioa</comment>
- <comment xml:lang="fi">MNG-animaatio</comment>
- <comment xml:lang="fo">MNG teknimyndagerð</comment>
- <comment xml:lang="fr">animation MNG</comment>
- <comment xml:lang="ga">beochan MNG</comment>
- <comment xml:lang="gl">animación MNG</comment>
- <comment xml:lang="he">הנפשת MNG</comment>
- <comment xml:lang="hr">MNG animacija</comment>
- <comment xml:lang="hu">MNG-animáció</comment>
- <comment xml:lang="ia">Animation MNG</comment>
- <comment xml:lang="id">Animasi MNG</comment>
- <comment xml:lang="it">Animazione MNG</comment>
- <comment xml:lang="ja">MNG アニメーション</comment>
- <comment xml:lang="kk">MNG анимациясы</comment>
- <comment xml:lang="ko">MNG 동화상</comment>
- <comment xml:lang="lt">MNG animacija</comment>
- <comment xml:lang="lv">MNG animācija</comment>
- <comment xml:lang="ms">Animasi MNG</comment>
- <comment xml:lang="nb">MNG-animasjon</comment>
- <comment xml:lang="nl">MNG-animatie</comment>
- <comment xml:lang="nn">MNG-animasjon</comment>
- <comment xml:lang="oc">animacion MNG</comment>
- <comment xml:lang="pl">Animacja MNG</comment>
- <comment xml:lang="pt">animação MNG</comment>
- <comment xml:lang="pt_BR">Animação MNG</comment>
- <comment xml:lang="ro">Animație MNG</comment>
- <comment xml:lang="ru">Анимация MNG</comment>
- <comment xml:lang="sk">Animácia MNG</comment>
- <comment xml:lang="sl">Datoteka animacije MNG</comment>
- <comment xml:lang="sq">Animim MNG</comment>
- <comment xml:lang="sr">МНГ анимација</comment>
- <comment xml:lang="sv">MNG-animering</comment>
- <comment xml:lang="tr">MNG canlandırması</comment>
- <comment xml:lang="uk">анімація MNG</comment>
- <comment xml:lang="vi">Hoạt ảnh MNG</comment>
- <comment xml:lang="zh_CN">MNG 动画</comment>
<comment xml:lang="zh_TW">MNG 動畫</comment>
+ <comment xml:lang="zh_CN">MNG 动画</comment>
+ <comment xml:lang="vi">Hoạt ảnh MNG</comment>
+ <comment xml:lang="uk">анімація MNG</comment>
+ <comment xml:lang="tr">MNG canlandırması</comment>
+ <comment xml:lang="sv">MNG-animering</comment>
+ <comment xml:lang="sr">МНГ анимација</comment>
+ <comment xml:lang="sq">animacion MNG</comment>
+ <comment xml:lang="sl">Datoteka animacije MNG</comment>
+ <comment xml:lang="si">MNG සජීවිකරණය</comment>
+ <comment xml:lang="sk">Animácia MNG</comment>
+ <comment xml:lang="ru">Анимация MNG</comment>
+ <comment xml:lang="ro">Animație MNG</comment>
+ <comment xml:lang="pt_BR">Animação MNG</comment>
+ <comment xml:lang="pt">animação MNG</comment>
+ <comment xml:lang="pl">Animacja MNG</comment>
+ <comment xml:lang="oc">animacion MNG</comment>
+ <comment xml:lang="nn">MNG-animasjon</comment>
+ <comment xml:lang="nl">MNG-animatie</comment>
+ <comment xml:lang="nb">MNG-animasjon</comment>
+ <comment xml:lang="ms">Animasi MNG</comment>
+ <comment xml:lang="lv">MNG animācija</comment>
+ <comment xml:lang="lt">MNG animacija</comment>
+ <comment xml:lang="ko">MNG 동화상</comment>
+ <comment xml:lang="kk">MNG анимациясы</comment>
+ <comment xml:lang="ja">MNG アニメーション</comment>
+ <comment xml:lang="it">Animazione MNG</comment>
+ <comment xml:lang="is">MNG hreyfimynd</comment>
+ <comment xml:lang="id">Animasi MNG</comment>
+ <comment xml:lang="ia">Animation MNG</comment>
+ <comment xml:lang="hu">MNG-animáció</comment>
+ <comment xml:lang="hr">MNG animacija</comment>
+ <comment xml:lang="he">הנפשת MNG</comment>
+ <comment xml:lang="gl">animación MNG</comment>
+ <comment xml:lang="ga">beochan MNG</comment>
+ <comment xml:lang="fur">animazion MNG</comment>
+ <comment xml:lang="fr">animation MNG</comment>
+ <comment xml:lang="fo">MNG teknimyndagerð</comment>
+ <comment xml:lang="fi">MNG-animaatio</comment>
+ <comment xml:lang="eu">MNG animazioa</comment>
+ <comment xml:lang="es">animación MNG</comment>
+ <comment xml:lang="eo">MNG-animacio</comment>
+ <comment xml:lang="en_GB">MNG animation</comment>
+ <comment xml:lang="el">Κινούμενο σχέδιο MNG</comment>
+ <comment xml:lang="de">MNG-Animation</comment>
+ <comment xml:lang="da">MNG-animation</comment>
+ <comment xml:lang="cs">animace MNG</comment>
+ <comment xml:lang="ca">animació MNG</comment>
+ <comment xml:lang="bg">Анимация — MNG</comment>
+ <comment xml:lang="be@latin">Animacyja MNG</comment>
+ <comment xml:lang="be">анімацыя MNG</comment>
+ <comment xml:lang="ar">تحريكة MNG</comment>
+ <comment xml:lang="af">MNG-animasie</comment>
<acronym>MNG</acronym>
<expanded-acronym>Multiple-Image Network Graphics</expanded-acronym>
- <magic priority="50">
- <match value="\x8AMNG\x0D\x0A\x1A\x0A" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="\x8AMNG\x0D\x0A\x1A\x0A" offset="0"/>
</magic>
<glob pattern="*.mng"/>
</mime-type>
<mime-type type="application/vnd.ms-asf">
<comment>ASF video</comment>
- <comment xml:lang="ar">ASF مرئي</comment>
- <comment xml:lang="ast">Videu n'ASF</comment>
- <comment xml:lang="be@latin">Videa ASF</comment>
- <comment xml:lang="bg">Видео — ASF</comment>
- <comment xml:lang="ca">vídeo ASF</comment>
- <comment xml:lang="cs">video ASF</comment>
- <comment xml:lang="da">ASF-video</comment>
- <comment xml:lang="de">ASF-Video</comment>
- <comment xml:lang="el">Βίντεο ASF</comment>
- <comment xml:lang="en_GB">ASF video</comment>
- <comment xml:lang="eo">ASF-video</comment>
- <comment xml:lang="es">vídeo ASF</comment>
- <comment xml:lang="eu">ASF bideoa</comment>
- <comment xml:lang="fi">ASF-video</comment>
- <comment xml:lang="fo">ASF video</comment>
- <comment xml:lang="fr">vidéo ASF</comment>
- <comment xml:lang="ga">físeán ASF</comment>
- <comment xml:lang="gl">vídeo ASF</comment>
- <comment xml:lang="he">וידאו ASF</comment>
- <comment xml:lang="hr">ASF video snimka</comment>
- <comment xml:lang="hu">ASF videó</comment>
- <comment xml:lang="ia">Video ASF</comment>
- <comment xml:lang="id">Video ASF</comment>
- <comment xml:lang="it">Video ASF</comment>
- <comment xml:lang="ja">ASF 動画</comment>
- <comment xml:lang="ka">ASF ვიდეო</comment>
- <comment xml:lang="kk">ASF видеосы</comment>
- <comment xml:lang="ko">ASF 동영상</comment>
- <comment xml:lang="lt">ASF vaizdo įrašas</comment>
- <comment xml:lang="lv">ASF video</comment>
- <comment xml:lang="nb">ASF-film</comment>
- <comment xml:lang="nl">ASF-video</comment>
- <comment xml:lang="nn">ASF-video</comment>
- <comment xml:lang="oc">vidèo ASF</comment>
- <comment xml:lang="pl">Plik wideo ASF</comment>
- <comment xml:lang="pt">vídeo ASF</comment>
- <comment xml:lang="pt_BR">Vídeo ASF</comment>
- <comment xml:lang="ro">Video ASF</comment>
- <comment xml:lang="ru">Видео ASF</comment>
- <comment xml:lang="sk">Video ASF</comment>
- <comment xml:lang="sl">Video datoteka ASF</comment>
- <comment xml:lang="sq">Video ASF</comment>
- <comment xml:lang="sr">АСФ видео</comment>
- <comment xml:lang="sv">ASF-video</comment>
- <comment xml:lang="tr">ASF videosu</comment>
- <comment xml:lang="uk">відеокліп ASF</comment>
- <comment xml:lang="vi">Ảnh động ASF</comment>
- <comment xml:lang="zh_CN">ASF 视频</comment>
<comment xml:lang="zh_TW">ASF 視訊</comment>
+ <comment xml:lang="zh_CN">ASF 视频</comment>
+ <comment xml:lang="vi">Ảnh động ASF</comment>
+ <comment xml:lang="uk">відеокліп ASF</comment>
+ <comment xml:lang="tr">ASF videosu</comment>
+ <comment xml:lang="sv">ASF-video</comment>
+ <comment xml:lang="sr">АСФ видео</comment>
+ <comment xml:lang="sq">video ASF</comment>
+ <comment xml:lang="sl">Video datoteka ASF</comment>
+ <comment xml:lang="si">ASF වීඩියෝව</comment>
+ <comment xml:lang="sk">Video ASF</comment>
+ <comment xml:lang="ru">Видео ASF</comment>
+ <comment xml:lang="ro">Video ASF</comment>
+ <comment xml:lang="pt_BR">Vídeo ASF</comment>
+ <comment xml:lang="pt">vídeo ASF</comment>
+ <comment xml:lang="pl">Plik wideo ASF</comment>
+ <comment xml:lang="oc">vidèo ASF</comment>
+ <comment xml:lang="nn">ASF-video</comment>
+ <comment xml:lang="nl">ASF-video</comment>
+ <comment xml:lang="nb">ASF-film</comment>
+ <comment xml:lang="lv">ASF video</comment>
+ <comment xml:lang="lt">ASF vaizdo įrašas</comment>
+ <comment xml:lang="ko">ASF 동영상</comment>
+ <comment xml:lang="kk">ASF видеосы</comment>
+ <comment xml:lang="ka">ASF ვიდეო</comment>
+ <comment xml:lang="ja">ASF 動画</comment>
+ <comment xml:lang="it">Video ASF</comment>
+ <comment xml:lang="is">ASF myndskeið</comment>
+ <comment xml:lang="id">Video ASF</comment>
+ <comment xml:lang="ia">Video ASF</comment>
+ <comment xml:lang="hu">ASF videó</comment>
+ <comment xml:lang="hr">ASF video snimka</comment>
+ <comment xml:lang="he">וידאו ASF</comment>
+ <comment xml:lang="gl">vídeo ASF</comment>
+ <comment xml:lang="ga">físeán ASF</comment>
+ <comment xml:lang="fur">video ASF</comment>
+ <comment xml:lang="fr">vidéo ASF</comment>
+ <comment xml:lang="fo">ASF video</comment>
+ <comment xml:lang="fi">ASF-video</comment>
+ <comment xml:lang="eu">ASF bideoa</comment>
+ <comment xml:lang="es">vídeo ASF</comment>
+ <comment xml:lang="eo">ASF-video</comment>
+ <comment xml:lang="en_GB">ASF video</comment>
+ <comment xml:lang="el">Βίντεο ASF</comment>
+ <comment xml:lang="de">ASF-Video</comment>
+ <comment xml:lang="da">ASF-video</comment>
+ <comment xml:lang="cs">video ASF</comment>
+ <comment xml:lang="ca">vídeo ASF</comment>
+ <comment xml:lang="bg">Видео — ASF</comment>
+ <comment xml:lang="be@latin">Videa ASF</comment>
+ <comment xml:lang="be">відэа ASF</comment>
+ <comment xml:lang="ast">Videu n'ASF</comment>
+ <comment xml:lang="ar">فيديو ASF</comment>
+ <comment xml:lang="af">ASF-video</comment>
<acronym>ASF</acronym>
<expanded-acronym>Advanced Streaming Format</expanded-acronym>
<alias type="video/x-ms-wm"/>
<alias type="video/x-ms-asf"/>
<alias type="video/x-ms-asf-plugin"/>
<glob pattern="*.asf"/>
- <magic priority="50">
- <match value="0x3026b275" type="big32" offset="0"/>
- <match value="[Reference]" type="string" offset="0"/>
+ <magic>
+ <match type="big32" value="0x3026b275" offset="0"/>
+ <match type="string" value="[Reference]" offset="0"/>
</magic>
</mime-type>
<mime-type type="application/x-netshow-channel">
<comment>Windows Media Station file</comment>
- <comment xml:lang="ar">ملف محطة Windows Media</comment>
- <comment xml:lang="be@latin">Fajł Windows Media Station</comment>
- <comment xml:lang="bg">Файл — Windows Media Station</comment>
- <comment xml:lang="ca">fitxer de Windows Media Station</comment>
- <comment xml:lang="cs">soubor Windows Media Station</comment>
- <comment xml:lang="da">Windows Media Station-fil</comment>
- <comment xml:lang="de">Windows-Media-Streamingbeschreibung</comment>
- <comment xml:lang="el">Αρχείο Windows Media Station</comment>
- <comment xml:lang="en_GB">Windows Media Station file</comment>
- <comment xml:lang="es">archivo de emisora de Windows Media</comment>
- <comment xml:lang="eu">Windows Media Station fitxategia</comment>
- <comment xml:lang="fi">Windows Media Station-tiedosto</comment>
- <comment xml:lang="fo">Windows Media Station fíla</comment>
- <comment xml:lang="fr">fichier Windows Media Station</comment>
- <comment xml:lang="ga">comhad Windows Media Station</comment>
- <comment xml:lang="gl">ficheiro de emisora de Windows Media</comment>
- <comment xml:lang="he">קובץ תחנה של Windows Media</comment>
- <comment xml:lang="hr">Windows Media Station datoteka</comment>
- <comment xml:lang="hu">Windows Media Station fájl</comment>
- <comment xml:lang="ia">File de station Windows Media</comment>
- <comment xml:lang="id">Berkas Windows Media Station</comment>
- <comment xml:lang="it">File Windows Media Station</comment>
- <comment xml:lang="ja">Windows Media Station ファイル</comment>
- <comment xml:lang="kk">Windows Media Station файлы</comment>
- <comment xml:lang="ko">Windows Media Station 파일</comment>
- <comment xml:lang="lt">Windows Media Station failas</comment>
- <comment xml:lang="lv">Windows Media Station datne</comment>
- <comment xml:lang="nb">Windows Media Station-fil</comment>
- <comment xml:lang="nl">Windows Media Station-bestand</comment>
- <comment xml:lang="nn">Windows Media Station-fil</comment>
- <comment xml:lang="oc">fichièr Windows Media Station</comment>
- <comment xml:lang="pl">Plik Windows Media Station</comment>
- <comment xml:lang="pt">ficheiro Windows Media Station</comment>
- <comment xml:lang="pt_BR">Arquivo de estação do Windows Media</comment>
- <comment xml:lang="ro">Fișier Windows Media Station</comment>
- <comment xml:lang="ru">Файл Windows Media Station</comment>
- <comment xml:lang="sk">Súbor Windows Media Station</comment>
- <comment xml:lang="sl">Datoteka Windows Media Station</comment>
- <comment xml:lang="sq">File Windows Media Station</comment>
- <comment xml:lang="sr">датотека станице Виндоузовог Медија</comment>
- <comment xml:lang="sv">Windows Media Station-fil</comment>
- <comment xml:lang="tr">Windows Media Station dosyası</comment>
- <comment xml:lang="uk">файл Windows Media Station</comment>
- <comment xml:lang="vi">Tập tin Windows Media Station</comment>
- <comment xml:lang="zh_CN">Windows 媒体工作站文件</comment>
<comment xml:lang="zh_TW">Windows Media Station 檔</comment>
+ <comment xml:lang="zh_CN">Windows 媒体工作站文件</comment>
+ <comment xml:lang="vi">Tập tin Windows Media Station</comment>
+ <comment xml:lang="uk">файл Windows Media Station</comment>
+ <comment xml:lang="tr">Windows Media Station dosyası</comment>
+ <comment xml:lang="sv">Windows Media Station-fil</comment>
+ <comment xml:lang="sr">датотека станице Виндоузовог Медија</comment>
+ <comment xml:lang="sq">kartelë Windows Media Station</comment>
+ <comment xml:lang="sl">Datoteka Windows Media Station</comment>
+ <comment xml:lang="si">Windows Media Station ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Windows Media Station</comment>
+ <comment xml:lang="ru">Файл Windows Media Station</comment>
+ <comment xml:lang="ro">Fișier Windows Media Station</comment>
+ <comment xml:lang="pt_BR">Arquivo de estação do Windows Media</comment>
+ <comment xml:lang="pt">ficheiro Windows Media Station</comment>
+ <comment xml:lang="pl">Plik Windows Media Station</comment>
+ <comment xml:lang="oc">fichièr Windows Media Station</comment>
+ <comment xml:lang="nn">Windows Media Station-fil</comment>
+ <comment xml:lang="nl">Windows Media Station-bestand</comment>
+ <comment xml:lang="nb">Windows Media Station-fil</comment>
+ <comment xml:lang="lv">Windows Media Station datne</comment>
+ <comment xml:lang="lt">Windows Media Station failas</comment>
+ <comment xml:lang="ko">Windows Media Station 파일</comment>
+ <comment xml:lang="kk">Windows Media Station файлы</comment>
+ <comment xml:lang="ja">Windows Media Station ファイル</comment>
+ <comment xml:lang="it">File Windows Media Station</comment>
+ <comment xml:lang="is">Windows Media Station skrá</comment>
+ <comment xml:lang="id">Berkas Windows Media Station</comment>
+ <comment xml:lang="ia">File de station Windows Media</comment>
+ <comment xml:lang="hu">Windows Media Station fájl</comment>
+ <comment xml:lang="hr">Windows Media Station datoteka</comment>
+ <comment xml:lang="he">קובץ תחנה של Windows Media</comment>
+ <comment xml:lang="gl">ficheiro de emisora de Windows Media</comment>
+ <comment xml:lang="ga">comhad Windows Media Station</comment>
+ <comment xml:lang="fur">file Windows Media Station</comment>
+ <comment xml:lang="fr">fichier Windows Media Station</comment>
+ <comment xml:lang="fo">Windows Media Station fíla</comment>
+ <comment xml:lang="fi">Windows Media Station -tiedosto</comment>
+ <comment xml:lang="eu">Windows Media Station fitxategia</comment>
+ <comment xml:lang="es">archivo de emisora de Windows Media</comment>
+ <comment xml:lang="en_GB">Windows Media Station file</comment>
+ <comment xml:lang="el">Αρχείο Windows Media Station</comment>
+ <comment xml:lang="de">Windows-Media-Station-Datei</comment>
+ <comment xml:lang="da">Windows Media Station-fil</comment>
+ <comment xml:lang="cs">soubor Windows Media Station</comment>
+ <comment xml:lang="ca">fitxer de Windows Media Station</comment>
+ <comment xml:lang="bg">Файл — Windows Media Station</comment>
+ <comment xml:lang="be@latin">Fajł Windows Media Station</comment>
+ <comment xml:lang="be">файл Windows Media Station</comment>
+ <comment xml:lang="ar">ملف محطة ويندوز ميديا</comment>
+ <comment xml:lang="af">Windows Media Station-lêer</comment>
<sub-class-of type="application/vnd.ms-asf"/>
<generic-icon name="video-x-generic"/>
<glob pattern="*.nsc"/>
- <magic priority="50">
- <match value="[Address]" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="[Address]" offset="0"/>
</magic>
</mime-type>
<mime-type type="video/x-ms-wmv">
<comment>Windows Media video</comment>
- <comment xml:lang="ar">Windows Media مرئي</comment>
- <comment xml:lang="ast">Videu de Windows Media</comment>
- <comment xml:lang="be@latin">Videa Windows Media</comment>
- <comment xml:lang="bg">Видео — Windows Media</comment>
- <comment xml:lang="ca">vídeo de Windows Media</comment>
- <comment xml:lang="cs">video Windows Media</comment>
- <comment xml:lang="da">Windows Medie-video</comment>
- <comment xml:lang="de">Windows-Media-Video</comment>
- <comment xml:lang="el">Βίντεο Windows Media</comment>
- <comment xml:lang="en_GB">Windows Media video</comment>
- <comment xml:lang="es">vídeo de Windows Media</comment>
- <comment xml:lang="eu">Windows Media bideoa</comment>
- <comment xml:lang="fi">Windows Media -video</comment>
- <comment xml:lang="fo">Windows Media video</comment>
- <comment xml:lang="fr">vidéo Windows Media</comment>
- <comment xml:lang="ga">físeán Windows Media</comment>
- <comment xml:lang="gl">vídeo de Windows Media</comment>
- <comment xml:lang="he">וידאו של Windows Media</comment>
- <comment xml:lang="hr">Windows Media video snimka</comment>
- <comment xml:lang="hu">Windows Media videó</comment>
- <comment xml:lang="ia">Video Windows Media</comment>
- <comment xml:lang="id">Video Windows Media</comment>
- <comment xml:lang="it">Video Windows Media</comment>
- <comment xml:lang="ja">Windows Media 動画</comment>
- <comment xml:lang="kk">Windows Media видеосы</comment>
- <comment xml:lang="ko">Windows 미디어 오디오</comment>
- <comment xml:lang="lt">Windows Media vaizdo įrašas</comment>
- <comment xml:lang="lv">Windows Media video</comment>
- <comment xml:lang="nb">Windows Media film</comment>
- <comment xml:lang="nl">Windows Media-video</comment>
- <comment xml:lang="nn">Windows Media-video</comment>
- <comment xml:lang="oc">vidèo Windows Media</comment>
- <comment xml:lang="pl">Plik wideo Windows Media</comment>
- <comment xml:lang="pt">vídeo Windows Media</comment>
- <comment xml:lang="pt_BR">Vídeo do Windows Media</comment>
- <comment xml:lang="ro">Video Windows Media</comment>
- <comment xml:lang="ru">Видео Windows Media</comment>
- <comment xml:lang="sk">Video Windows Media</comment>
- <comment xml:lang="sl">Video datoteka Windows Media</comment>
- <comment xml:lang="sq">Video Windows Media</comment>
- <comment xml:lang="sr">Виндоуз Медија видео</comment>
- <comment xml:lang="sv">Windows Media-video</comment>
- <comment xml:lang="tr">Windows Media videosu</comment>
- <comment xml:lang="uk">відеокліп Windows Media</comment>
- <comment xml:lang="vi">Ảnh động Windows Media</comment>
- <comment xml:lang="zh_CN">Windows Media 视频</comment>
<comment xml:lang="zh_TW">Windows Media 視訊</comment>
+ <comment xml:lang="zh_CN">Windows Media 视频</comment>
+ <comment xml:lang="vi">Ảnh động Windows Media</comment>
+ <comment xml:lang="uk">відеокліп Windows Media</comment>
+ <comment xml:lang="tr">Windows Media videosu</comment>
+ <comment xml:lang="sv">Windows Media-video</comment>
+ <comment xml:lang="sr">Виндоуз Медија видео</comment>
+ <comment xml:lang="sq">video Windows Media</comment>
+ <comment xml:lang="sl">Video datoteka Windows Media</comment>
+ <comment xml:lang="si">වින්ඩෝස් මීඩියා වීඩියෝව</comment>
+ <comment xml:lang="sk">Video Windows Media</comment>
+ <comment xml:lang="ru">Видео Windows Media</comment>
+ <comment xml:lang="ro">Video Windows Media</comment>
+ <comment xml:lang="pt_BR">Vídeo do Windows Media</comment>
+ <comment xml:lang="pt">vídeo Windows Media</comment>
+ <comment xml:lang="pl">Plik wideo Windows Media</comment>
+ <comment xml:lang="oc">vidèo Windows Media</comment>
+ <comment xml:lang="nn">Windows Media-video</comment>
+ <comment xml:lang="nl">Windows Media-video</comment>
+ <comment xml:lang="nb">Windows Media film</comment>
+ <comment xml:lang="lv">Windows Media video</comment>
+ <comment xml:lang="lt">Windows Media vaizdo įrašas</comment>
+ <comment xml:lang="ko">Windows 미디어 오디오</comment>
+ <comment xml:lang="kk">Windows Media видеосы</comment>
+ <comment xml:lang="ja">Windows Media 動画</comment>
+ <comment xml:lang="it">Video Windows Media</comment>
+ <comment xml:lang="is">Windows Media myndskeið</comment>
+ <comment xml:lang="id">Video Windows Media</comment>
+ <comment xml:lang="ia">Video Windows Media</comment>
+ <comment xml:lang="hu">Windows Media videó</comment>
+ <comment xml:lang="hr">Windows Media video snimka</comment>
+ <comment xml:lang="he">וידאו של Windows Media</comment>
+ <comment xml:lang="gl">vídeo de Windows Media</comment>
+ <comment xml:lang="ga">físeán Windows Media</comment>
+ <comment xml:lang="fur">video Windows Media</comment>
+ <comment xml:lang="fr">vidéo Windows Media</comment>
+ <comment xml:lang="fo">Windows Media video</comment>
+ <comment xml:lang="fi">Windows Media -video</comment>
+ <comment xml:lang="eu">Windows Media bideoa</comment>
+ <comment xml:lang="es">vídeo de Windows Media</comment>
+ <comment xml:lang="en_GB">Windows Media video</comment>
+ <comment xml:lang="el">Βίντεο Windows Media</comment>
+ <comment xml:lang="de">Windows-Media-Video</comment>
+ <comment xml:lang="da">Windows Medie-video</comment>
+ <comment xml:lang="cs">video Windows Media</comment>
+ <comment xml:lang="ca">vídeo de Windows Media</comment>
+ <comment xml:lang="bg">Видео — Windows Media</comment>
+ <comment xml:lang="be@latin">Videa Windows Media</comment>
+ <comment xml:lang="be">відэа Windows Media</comment>
+ <comment xml:lang="ast">Videu de Windows Media</comment>
+ <comment xml:lang="ar">فيديو ويندوز ميديا</comment>
+ <comment xml:lang="af">Windows Media-video</comment>
<sub-class-of type="application/vnd.ms-asf"/>
<glob pattern="*.wmv"/>
</mime-type>
- <mime-type type="video/x-msvideo">
+ <mime-type type="video/vnd.avi">
<comment>AVI video</comment>
- <comment xml:lang="ar">AVI مرئي</comment>
- <comment xml:lang="ast">Videu n'AVI</comment>
- <comment xml:lang="az">AVI video faylı</comment>
- <comment xml:lang="be@latin">Videa AVI</comment>
- <comment xml:lang="bg">Видео — AVI</comment>
- <comment xml:lang="ca">vídeo AVI</comment>
- <comment xml:lang="cs">video AVI</comment>
- <comment xml:lang="cy">Fideo AVI</comment>
- <comment xml:lang="da">AVI-video</comment>
- <comment xml:lang="de">AVI-Video</comment>
- <comment xml:lang="el">Βίντεο AVI</comment>
- <comment xml:lang="en_GB">AVI video</comment>
- <comment xml:lang="eo">AVI-video</comment>
- <comment xml:lang="es">vídeo AVI</comment>
- <comment xml:lang="eu">AVI bideoa</comment>
- <comment xml:lang="fi">AVI-video</comment>
- <comment xml:lang="fo">AVI video</comment>
- <comment xml:lang="fr">vidéo AVI</comment>
- <comment xml:lang="ga">físeán AVI</comment>
- <comment xml:lang="gl">vídeo AVI</comment>
- <comment xml:lang="he">וידאו AVI</comment>
- <comment xml:lang="hr">AVI video snimka</comment>
- <comment xml:lang="hu">AVI-videó</comment>
- <comment xml:lang="ia">Video AVI</comment>
- <comment xml:lang="id">Video AVI</comment>
- <comment xml:lang="it">Video AVI</comment>
- <comment xml:lang="ja">AVI 動画</comment>
- <comment xml:lang="ka">AVI ვიდეო</comment>
- <comment xml:lang="kk">AVI видеосы</comment>
- <comment xml:lang="ko">AVI 동영상</comment>
- <comment xml:lang="lt">AVI vaizdo įrašas</comment>
- <comment xml:lang="lv">AVI video</comment>
- <comment xml:lang="ms">Video AVI</comment>
- <comment xml:lang="nb">AVI-film</comment>
- <comment xml:lang="nl">AVI-video</comment>
- <comment xml:lang="nn">AVI-video</comment>
- <comment xml:lang="oc">vidèo AVI</comment>
- <comment xml:lang="pl">Plik wideo AVI</comment>
- <comment xml:lang="pt">vídeo AVI</comment>
- <comment xml:lang="pt_BR">Vídeo AVI</comment>
- <comment xml:lang="ro">Video AVI</comment>
- <comment xml:lang="ru">Видео AVI</comment>
- <comment xml:lang="sk">Video AVI</comment>
- <comment xml:lang="sl">Video datoteka AVI</comment>
- <comment xml:lang="sq">Video AVI</comment>
- <comment xml:lang="sr">АВИ видео</comment>
- <comment xml:lang="sv">AVI-video</comment>
- <comment xml:lang="tr">AVI videosu</comment>
- <comment xml:lang="uk">відеокліп AVI</comment>
- <comment xml:lang="vi">Ảnh động AVI</comment>
- <comment xml:lang="zh_CN">AVI 视频</comment>
<comment xml:lang="zh_TW">AVI 視訊</comment>
+ <comment xml:lang="zh_CN">AVI 视频</comment>
+ <comment xml:lang="vi">Ảnh động AVI</comment>
+ <comment xml:lang="uk">відеокліп AVI</comment>
+ <comment xml:lang="tr">AVI videosu</comment>
+ <comment xml:lang="sv">AVI-video</comment>
+ <comment xml:lang="sr">АВИ видео</comment>
+ <comment xml:lang="sq">video AVI</comment>
+ <comment xml:lang="sl">Video datoteka AVI</comment>
+ <comment xml:lang="si">AVI වීඩියෝ</comment>
+ <comment xml:lang="sk">Video AVI</comment>
+ <comment xml:lang="ru">Видео AVI</comment>
+ <comment xml:lang="ro">Video AVI</comment>
+ <comment xml:lang="pt_BR">Vídeo AVI</comment>
+ <comment xml:lang="pt">vídeo AVI</comment>
+ <comment xml:lang="pl">Plik wideo AVI</comment>
+ <comment xml:lang="oc">vidèo AVI</comment>
+ <comment xml:lang="nn">AVI-video</comment>
+ <comment xml:lang="nl">AVI-video</comment>
+ <comment xml:lang="nb">AVI-film</comment>
+ <comment xml:lang="ms">Video AVI</comment>
+ <comment xml:lang="lv">AVI video</comment>
+ <comment xml:lang="lt">AVI vaizdo įrašas</comment>
+ <comment xml:lang="ko">AVI 동영상</comment>
+ <comment xml:lang="kk">AVI видеосы</comment>
+ <comment xml:lang="ka">AVI ვიდეო</comment>
+ <comment xml:lang="ja">AVI 動画</comment>
+ <comment xml:lang="it">Video AVI</comment>
+ <comment xml:lang="is">AVI myndskeið</comment>
+ <comment xml:lang="id">Video AVI</comment>
+ <comment xml:lang="ia">Video AVI</comment>
+ <comment xml:lang="hu">AVI-videó</comment>
+ <comment xml:lang="hr">AVI video snimka</comment>
+ <comment xml:lang="he">וידאו AVI</comment>
+ <comment xml:lang="gl">vídeo AVI</comment>
+ <comment xml:lang="ga">físeán AVI</comment>
+ <comment xml:lang="fur">video AVI</comment>
+ <comment xml:lang="fr">vidéo AVI</comment>
+ <comment xml:lang="fo">AVI video</comment>
+ <comment xml:lang="fi">AVI-video</comment>
+ <comment xml:lang="eu">AVI bideoa</comment>
+ <comment xml:lang="es">vídeo AVI</comment>
+ <comment xml:lang="eo">AVI-video</comment>
+ <comment xml:lang="en_GB">AVI video</comment>
+ <comment xml:lang="el">Βίντεο AVI</comment>
+ <comment xml:lang="de">AVI-Video</comment>
+ <comment xml:lang="da">AVI-video</comment>
+ <comment xml:lang="cy">Fideo AVI</comment>
+ <comment xml:lang="cs">video AVI</comment>
+ <comment xml:lang="ca">vídeo AVI</comment>
+ <comment xml:lang="bg">Видео — AVI</comment>
+ <comment xml:lang="be@latin">Videa AVI</comment>
+ <comment xml:lang="be">відэа AVI</comment>
+ <comment xml:lang="az">AVI video faylı</comment>
+ <comment xml:lang="ast">Videu n'AVI</comment>
+ <comment xml:lang="ar">فيديو AVI</comment>
+ <comment xml:lang="af">AVI-video</comment>
<acronym>AVI</acronym>
<expanded-acronym>Audio Video Interleave</expanded-acronym>
<alias type="video/x-avi"/>
@@ -38497,12 +41136,13 @@
<alias type="video/divx"/>
<alias type="video/msvideo"/>
<alias type="video/vnd.divx"/>
- <magic priority="50">
- <match value="RIFF" type="string" offset="0">
- <match value="AVI " type="string" offset="8"/>
+ <alias type="video/x-msvideo"/>
+ <magic>
+ <match type="string" value="RIFF" offset="0">
+ <match type="string" value="AVI " offset="8"/>
</match>
- <match value="AVF0" type="string" offset="0">
- <match value="AVI " type="string" offset="8"/>
+ <match type="string" value="AVF0" offset="0">
+ <match type="string" value="AVI " offset="8"/>
</match>
</magic>
<glob pattern="*.avi"/>
@@ -38511,275 +41151,300 @@
</mime-type>
<mime-type type="video/x-nsv">
<comment>NullSoft video</comment>
- <comment xml:lang="ar">NullSoft مرئي</comment>
- <comment xml:lang="ast">Videu de NullSoft</comment>
- <comment xml:lang="be@latin">Videa NullSoft</comment>
- <comment xml:lang="bg">Видео — NullSoft</comment>
- <comment xml:lang="ca">vídeo NullSoft</comment>
- <comment xml:lang="cs">video NullSoft</comment>
- <comment xml:lang="da">NullSoft-video</comment>
- <comment xml:lang="de">NullSoft-Video</comment>
- <comment xml:lang="el">Βίντεο Nullsoft</comment>
- <comment xml:lang="en_GB">NullSoft video</comment>
- <comment xml:lang="eo">NullSoft-video</comment>
- <comment xml:lang="es">vídeo NullSoft</comment>
- <comment xml:lang="eu">NullSoft bideoa</comment>
- <comment xml:lang="fi">NullSoft-video</comment>
- <comment xml:lang="fo">NullSoft video</comment>
- <comment xml:lang="fr">vidéo NullSoft</comment>
- <comment xml:lang="ga">físeán NullSoft</comment>
- <comment xml:lang="gl">vídeo de NullSoft</comment>
- <comment xml:lang="he">וידאו של NullSot</comment>
- <comment xml:lang="hr">NullSoft video snimka</comment>
- <comment xml:lang="hu">NullSoft videó</comment>
- <comment xml:lang="ia">Video NullSoft</comment>
- <comment xml:lang="id">Video NullSoft</comment>
- <comment xml:lang="it">Video NullSoft</comment>
- <comment xml:lang="ja">NullSoft 動画</comment>
- <comment xml:lang="kk">NullSoft видеосы</comment>
- <comment xml:lang="ko">널소프트 동영상</comment>
- <comment xml:lang="lt">NullSoft vaizdo įrašas</comment>
- <comment xml:lang="lv">NullSoft video</comment>
- <comment xml:lang="nb">Nullsoft-film</comment>
- <comment xml:lang="nl">NullSoft-video</comment>
- <comment xml:lang="nn">NullSoft-video</comment>
- <comment xml:lang="oc">vidèo NullSoft</comment>
- <comment xml:lang="pl">Plik wideo NullSoft</comment>
- <comment xml:lang="pt">vídeo NullSoft</comment>
- <comment xml:lang="pt_BR">Vídeo do NullSoft</comment>
- <comment xml:lang="ro">Video NullSoft</comment>
- <comment xml:lang="ru">Видео Nullsoft</comment>
- <comment xml:lang="sk">Video NullSoft</comment>
- <comment xml:lang="sl">Video datoteka NullSoft</comment>
- <comment xml:lang="sq">Video NullSoft</comment>
- <comment xml:lang="sr">Нул Софт видео</comment>
- <comment xml:lang="sv">NullSoft-video</comment>
- <comment xml:lang="tr">Nullsoft videosu</comment>
- <comment xml:lang="uk">відеокліп NullSoft</comment>
- <comment xml:lang="vi">Ảnh động NullSoft</comment>
- <comment xml:lang="zh_CN">NullSoft 视频</comment>
<comment xml:lang="zh_TW">NullSoft 視訊</comment>
- <magic priority="50">
- <match value="NSVf" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">NullSoft 视频</comment>
+ <comment xml:lang="vi">Ảnh động NullSoft</comment>
+ <comment xml:lang="uk">відеокліп NullSoft</comment>
+ <comment xml:lang="tr">Nullsoft videosu</comment>
+ <comment xml:lang="sv">NullSoft-video</comment>
+ <comment xml:lang="sr">Нул Софт видео</comment>
+ <comment xml:lang="sq">video NullSoft</comment>
+ <comment xml:lang="sl">Video datoteka NullSoft</comment>
+ <comment xml:lang="si">NullSoft වීඩියෝව</comment>
+ <comment xml:lang="sk">Video NullSoft</comment>
+ <comment xml:lang="ru">Видео Nullsoft</comment>
+ <comment xml:lang="ro">Video NullSoft</comment>
+ <comment xml:lang="pt_BR">Vídeo do NullSoft</comment>
+ <comment xml:lang="pt">vídeo NullSoft</comment>
+ <comment xml:lang="pl">Plik wideo NullSoft</comment>
+ <comment xml:lang="oc">vidèo NullSoft</comment>
+ <comment xml:lang="nn">NullSoft-video</comment>
+ <comment xml:lang="nl">NullSoft-video</comment>
+ <comment xml:lang="nb">Nullsoft-film</comment>
+ <comment xml:lang="lv">NullSoft video</comment>
+ <comment xml:lang="lt">NullSoft vaizdo įrašas</comment>
+ <comment xml:lang="ko">널소프트 동영상</comment>
+ <comment xml:lang="kk">NullSoft видеосы</comment>
+ <comment xml:lang="ja">NullSoft 動画</comment>
+ <comment xml:lang="it">Video NullSoft</comment>
+ <comment xml:lang="is">Nullsoft myndskeið</comment>
+ <comment xml:lang="id">Video NullSoft</comment>
+ <comment xml:lang="ia">Video NullSoft</comment>
+ <comment xml:lang="hu">NullSoft videó</comment>
+ <comment xml:lang="hr">NullSoft video snimka</comment>
+ <comment xml:lang="he">וידאו של NullSot</comment>
+ <comment xml:lang="gl">vídeo de NullSoft</comment>
+ <comment xml:lang="ga">físeán NullSoft</comment>
+ <comment xml:lang="fur">video NullSoft</comment>
+ <comment xml:lang="fr">vidéo NullSoft</comment>
+ <comment xml:lang="fo">NullSoft video</comment>
+ <comment xml:lang="fi">NullSoft-video</comment>
+ <comment xml:lang="eu">NullSoft bideoa</comment>
+ <comment xml:lang="es">vídeo NullSoft</comment>
+ <comment xml:lang="eo">NullSoft-video</comment>
+ <comment xml:lang="en_GB">NullSoft video</comment>
+ <comment xml:lang="el">Βίντεο Nullsoft</comment>
+ <comment xml:lang="de">NullSoft-Video</comment>
+ <comment xml:lang="da">NullSoft-video</comment>
+ <comment xml:lang="cs">video NullSoft</comment>
+ <comment xml:lang="ca">vídeo NullSoft</comment>
+ <comment xml:lang="bg">Видео — NullSoft</comment>
+ <comment xml:lang="be@latin">Videa NullSoft</comment>
+ <comment xml:lang="be">відэа NullSoft</comment>
+ <comment xml:lang="ast">Videu de NullSoft</comment>
+ <comment xml:lang="ar">فيديو NullSoft</comment>
+ <comment xml:lang="af">NullSoft-video</comment>
+ <magic>
+ <match type="string" value="NSVf" offset="0"/>
</magic>
<glob pattern="*.nsv"/>
</mime-type>
<mime-type type="application/sdp">
<comment>SDP multicast stream file</comment>
- <comment xml:lang="ar">ملف دفق متعدد البث SDP</comment>
- <comment xml:lang="be@latin">Šmatadrasny płynievy fajł SDP</comment>
- <comment xml:lang="bg">Файл за поток — SDP multicast</comment>
- <comment xml:lang="ca">fitxer de flux de multidifusió SDP</comment>
- <comment xml:lang="cs">soubor vícesměrového vysílání proudu SDP</comment>
- <comment xml:lang="da">SDP multicast-strømfil</comment>
- <comment xml:lang="de">SDP-Multicast-Datenstromdatei</comment>
- <comment xml:lang="el">Αρχείο ροής πολλαπλής αναμετάδοσης SDP</comment>
- <comment xml:lang="en_GB">SDP multicast stream file</comment>
- <comment xml:lang="es">archivo de flujo multicast SDP</comment>
- <comment xml:lang="eu">SDP multicast korrontearen fitxategia</comment>
- <comment xml:lang="fi">SDP-monilähetysvirran tiedosto</comment>
- <comment xml:lang="fo">SDP margvarpað streymafíla</comment>
- <comment xml:lang="fr">fichier de flux multidiffusion SDP</comment>
- <comment xml:lang="ga">comhad shruth ilchraolacháin SDP</comment>
- <comment xml:lang="gl">ficheiro de fluxo multicast SDP</comment>
- <comment xml:lang="he">קובץ שידור בזרימה SDP</comment>
- <comment xml:lang="hr">SDP datoteka strujanja emitiranja</comment>
- <comment xml:lang="hu">SDP multicast műsorfájl</comment>
- <comment xml:lang="ia">File de fluxo multidiffusion SDP</comment>
- <comment xml:lang="id">Berkas SDP multicast stream</comment>
- <comment xml:lang="it">File stream multicast SDP</comment>
- <comment xml:lang="ja">SDP マルチキャストストリームファイル</comment>
- <comment xml:lang="kk">SDP мультикаст ағым файлы</comment>
- <comment xml:lang="ko">SDP 멀티캐스트 스트림 파일</comment>
- <comment xml:lang="lt">SDP daugiaadresio srauto failas</comment>
- <comment xml:lang="lv">SDP multiraides straumes datne</comment>
- <comment xml:lang="nb">SDP-multicaststrøm</comment>
- <comment xml:lang="nl">SDP-multicast-streambestand</comment>
- <comment xml:lang="nn">SDP multicast straumfil</comment>
- <comment xml:lang="oc">fichièr de flux multidifusion SDP</comment>
- <comment xml:lang="pl">Plik strumienia multicast SDP</comment>
- <comment xml:lang="pt">ficheiro de fluxo SDP multicast</comment>
- <comment xml:lang="pt_BR">Arquivo de canal multicast SDP</comment>
- <comment xml:lang="ro">Fișier flux multicast SDP</comment>
- <comment xml:lang="ru">Файл мультикаст-потока SDP</comment>
- <comment xml:lang="sk">Súbor viacsmerového vysielania prúdu SDP</comment>
- <comment xml:lang="sl">Pretočni vir večsmernega oddajanja</comment>
- <comment xml:lang="sq">File stream multicast SDP</comment>
- <comment xml:lang="sr">СДП датотека тока вишеструког емитовања</comment>
- <comment xml:lang="sv">SDP multicast stream-fil</comment>
- <comment xml:lang="tr">SDP çoklu yayın akışı dosyası</comment>
- <comment xml:lang="uk">файл потокової трансляції SDP</comment>
- <comment xml:lang="vi">Tập tin luồng truyền một-nhiều SDP</comment>
- <comment xml:lang="zh_CN">SDP 多播流文件</comment>
<comment xml:lang="zh_TW">SDP multicast 串流檔</comment>
+ <comment xml:lang="zh_CN">SDP 多播流文件</comment>
+ <comment xml:lang="vi">Tập tin luồng truyền một-nhiều SDP</comment>
+ <comment xml:lang="uk">файл потокової трансляції SDP</comment>
+ <comment xml:lang="tr">SDP çoklu yayın akışı dosyası</comment>
+ <comment xml:lang="sv">SDP multicast stream-fil</comment>
+ <comment xml:lang="sr">СДП датотека тока вишеструког емитовања</comment>
+ <comment xml:lang="sq">kartelë transmetimi multicast SDP</comment>
+ <comment xml:lang="sl">Pretočni vir večsmernega oddajanja</comment>
+ <comment xml:lang="si">SDP බහු විකාශන ප්‍රවාහ ගොනුව</comment>
+ <comment xml:lang="sk">Súbor viacsmerového vysielania prúdu SDP</comment>
+ <comment xml:lang="ru">Файл мультикаст-потока SDP</comment>
+ <comment xml:lang="ro">Fișier flux multicast SDP</comment>
+ <comment xml:lang="pt_BR">Arquivo de canal multicast SDP</comment>
+ <comment xml:lang="pt">ficheiro de fluxo SDP multicast</comment>
+ <comment xml:lang="pl">Plik strumienia multicast SDP</comment>
+ <comment xml:lang="oc">fichièr de flux multidifusion SDP</comment>
+ <comment xml:lang="nn">SDP multicast straumfil</comment>
+ <comment xml:lang="nl">SDP-multicast-streambestand</comment>
+ <comment xml:lang="nb">SDP-multicaststrøm</comment>
+ <comment xml:lang="lv">SDP multiraides straumes datne</comment>
+ <comment xml:lang="lt">SDP daugiaadresio srauto failas</comment>
+ <comment xml:lang="ko">SDP 멀티캐스트 스트림 파일</comment>
+ <comment xml:lang="kk">SDP мультикаст ағым файлы</comment>
+ <comment xml:lang="ja">SDP マルチキャストストリームファイル</comment>
+ <comment xml:lang="it">File stream multicast SDP</comment>
+ <comment xml:lang="is">SDP multicast streymisskrá</comment>
+ <comment xml:lang="id">Berkas SDP multicast stream</comment>
+ <comment xml:lang="ia">File de fluxo multidiffusion SDP</comment>
+ <comment xml:lang="hu">SDP multicast műsorfájl</comment>
+ <comment xml:lang="hr">SDP datoteka strujanja emitiranja</comment>
+ <comment xml:lang="he">קובץ שידור בזרימה SDP</comment>
+ <comment xml:lang="gl">ficheiro de fluxo multicast SDP</comment>
+ <comment xml:lang="ga">comhad shruth ilchraolacháin SDP</comment>
+ <comment xml:lang="fur">file di flus a trasmission multiple SDP</comment>
+ <comment xml:lang="fr">fichier de flux multidiffusion SDP</comment>
+ <comment xml:lang="fo">SDP margvarpað streymafíla</comment>
+ <comment xml:lang="fi">SDP-monilähetysvirran tiedosto</comment>
+ <comment xml:lang="eu">SDP multicast korrontearen fitxategia</comment>
+ <comment xml:lang="es">archivo de flujo multicast SDP</comment>
+ <comment xml:lang="en_GB">SDP multicast stream file</comment>
+ <comment xml:lang="el">Αρχείο ροής πολλαπλής αναμετάδοσης SDP</comment>
+ <comment xml:lang="de">SDP-Multicast-Datenstromdatei</comment>
+ <comment xml:lang="da">SDP multicast-strømfil</comment>
+ <comment xml:lang="cs">soubor vícesměrového vysílání proudu SDP</comment>
+ <comment xml:lang="ca">fitxer de flux de multidifusió SDP</comment>
+ <comment xml:lang="bg">Поток — SDP multicast</comment>
+ <comment xml:lang="be@latin">Šmatadrasny płynievy fajł SDP</comment>
+ <comment xml:lang="be">файл шматадраснай плыні SDP</comment>
+ <comment xml:lang="ar">ملف دفق متعدد البث SDP</comment>
<acronym>SDP</acronym>
<expanded-acronym>Session Description Protocol</expanded-acronym>
<sub-class-of type="text/plain"/>
<alias type="application/x-sdp"/>
<alias type="application/vnd.sdp"/>
<generic-icon name="video-x-generic"/>
- <magic priority="50">
- <match value="v=" type="string" offset="0">
- <match value="s=" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="v=" offset="0">
+ <match type="string" value="s=" offset="0:256"/>
</match>
</magic>
<glob pattern="*.sdp"/>
</mime-type>
<mime-type type="video/x-sgi-movie">
<comment>SGI video</comment>
- <comment xml:lang="ar">SGI مرئي</comment>
- <comment xml:lang="ast">Videu en SGI</comment>
- <comment xml:lang="az">SGI video faylı</comment>
- <comment xml:lang="be@latin">Videa SGI</comment>
- <comment xml:lang="bg">Видео — SGI</comment>
- <comment xml:lang="ca">vídeo SGI</comment>
- <comment xml:lang="cs">video SGI</comment>
- <comment xml:lang="cy">Video SGI</comment>
- <comment xml:lang="da">SGI-video</comment>
- <comment xml:lang="de">SGI-Video</comment>
- <comment xml:lang="el">Βίντεο SGI</comment>
- <comment xml:lang="en_GB">SGI video</comment>
- <comment xml:lang="eo">SGI-video</comment>
- <comment xml:lang="es">vídeo SGI</comment>
- <comment xml:lang="eu">SGI bideoa</comment>
- <comment xml:lang="fi">SGI-video</comment>
- <comment xml:lang="fo">SGI video</comment>
- <comment xml:lang="fr">vidéo SGI</comment>
- <comment xml:lang="ga">físeán SGI</comment>
- <comment xml:lang="gl">vídeo SGI</comment>
- <comment xml:lang="he">וידאו SGI</comment>
- <comment xml:lang="hr">SGI video snimka</comment>
- <comment xml:lang="hu">SGI-videó</comment>
- <comment xml:lang="ia">Video SGI</comment>
- <comment xml:lang="id">Video SGI</comment>
- <comment xml:lang="it">Video SGI</comment>
- <comment xml:lang="ja">SGI 動画</comment>
- <comment xml:lang="kk">SGI видеосы</comment>
- <comment xml:lang="ko">SGI 동영상</comment>
- <comment xml:lang="lt">SGI vaizdo įrašas</comment>
- <comment xml:lang="lv">SGI video</comment>
- <comment xml:lang="ms">Video SGI</comment>
- <comment xml:lang="nb">SGI-film</comment>
- <comment xml:lang="nl">SGI-video</comment>
- <comment xml:lang="nn">SGI-video</comment>
- <comment xml:lang="oc">vidèo SGI</comment>
- <comment xml:lang="pl">Plik wideo SGI</comment>
- <comment xml:lang="pt">vídeo SGI</comment>
- <comment xml:lang="pt_BR">Vídeo SGI</comment>
- <comment xml:lang="ro">Video SGI</comment>
- <comment xml:lang="ru">Видео SGI</comment>
- <comment xml:lang="sk">Video SGI</comment>
- <comment xml:lang="sl">Video datoteka SGI</comment>
- <comment xml:lang="sq">Video SGI</comment>
- <comment xml:lang="sr">СГИ видео</comment>
- <comment xml:lang="sv">SGI-video</comment>
- <comment xml:lang="tr">SGI videosu</comment>
- <comment xml:lang="uk">відеокліп SGI</comment>
- <comment xml:lang="vi">Ảnh động SGI</comment>
- <comment xml:lang="zh_CN">SGI 视频</comment>
<comment xml:lang="zh_TW">SGI 視訊</comment>
- <magic priority="50">
- <match value="MOVI" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">SGI 视频</comment>
+ <comment xml:lang="vi">Ảnh động SGI</comment>
+ <comment xml:lang="uk">відеокліп SGI</comment>
+ <comment xml:lang="tr">SGI videosu</comment>
+ <comment xml:lang="sv">SGI-video</comment>
+ <comment xml:lang="sr">СГИ видео</comment>
+ <comment xml:lang="sq">video SGI</comment>
+ <comment xml:lang="sl">Video datoteka SGI</comment>
+ <comment xml:lang="si">SGI වීඩියෝව</comment>
+ <comment xml:lang="sk">Video SGI</comment>
+ <comment xml:lang="ru">Видео SGI</comment>
+ <comment xml:lang="ro">Video SGI</comment>
+ <comment xml:lang="pt_BR">Vídeo SGI</comment>
+ <comment xml:lang="pt">vídeo SGI</comment>
+ <comment xml:lang="pl">Plik wideo SGI</comment>
+ <comment xml:lang="oc">vidèo SGI</comment>
+ <comment xml:lang="nn">SGI-video</comment>
+ <comment xml:lang="nl">SGI-video</comment>
+ <comment xml:lang="nb">SGI-film</comment>
+ <comment xml:lang="ms">Video SGI</comment>
+ <comment xml:lang="lv">SGI video</comment>
+ <comment xml:lang="lt">SGI vaizdo įrašas</comment>
+ <comment xml:lang="ko">SGI 동영상</comment>
+ <comment xml:lang="kk">SGI видеосы</comment>
+ <comment xml:lang="ja">SGI 動画</comment>
+ <comment xml:lang="it">Video SGI</comment>
+ <comment xml:lang="is">SGI myndskeið</comment>
+ <comment xml:lang="id">Video SGI</comment>
+ <comment xml:lang="ia">Video SGI</comment>
+ <comment xml:lang="hu">SGI-videó</comment>
+ <comment xml:lang="hr">SGI video snimka</comment>
+ <comment xml:lang="he">וידאו SGI</comment>
+ <comment xml:lang="gl">vídeo SGI</comment>
+ <comment xml:lang="ga">físeán SGI</comment>
+ <comment xml:lang="fur">video SGI</comment>
+ <comment xml:lang="fr">vidéo SGI</comment>
+ <comment xml:lang="fo">SGI video</comment>
+ <comment xml:lang="fi">SGI-video</comment>
+ <comment xml:lang="eu">SGI bideoa</comment>
+ <comment xml:lang="es">vídeo SGI</comment>
+ <comment xml:lang="eo">SGI-video</comment>
+ <comment xml:lang="en_GB">SGI video</comment>
+ <comment xml:lang="el">Βίντεο SGI</comment>
+ <comment xml:lang="de">SGI-Video</comment>
+ <comment xml:lang="da">SGI-video</comment>
+ <comment xml:lang="cy">Video SGI</comment>
+ <comment xml:lang="cs">video SGI</comment>
+ <comment xml:lang="ca">vídeo SGI</comment>
+ <comment xml:lang="bg">Видео — SGI</comment>
+ <comment xml:lang="be@latin">Videa SGI</comment>
+ <comment xml:lang="be">відэа SGI</comment>
+ <comment xml:lang="az">SGI video faylı</comment>
+ <comment xml:lang="ast">Videu en SGI</comment>
+ <comment xml:lang="ar">فيديو SGI</comment>
+ <comment xml:lang="af">SGI-video</comment>
+ <magic>
+ <match type="string" value="MOVI" offset="0"/>
</magic>
<glob pattern="*.movie"/>
</mime-type>
<mime-type type="application/vnd.emusic-emusic_package">
<comment>eMusic download package</comment>
- <comment xml:lang="ar">حزمة تنزيل eMusic</comment>
- <comment xml:lang="be@latin">pakunak zahruzki eMusic</comment>
- <comment xml:lang="bg">Пакет за сваляне — eMusic</comment>
- <comment xml:lang="ca">paquet de descàrrega eMusic</comment>
- <comment xml:lang="cs">balíček stahování eMusic</comment>
- <comment xml:lang="da">eMusic-hentpakke</comment>
- <comment xml:lang="de">eMusic-Download-Paket</comment>
- <comment xml:lang="el">Πακέτο λήψης eMusic</comment>
- <comment xml:lang="en_GB">eMusic download package</comment>
- <comment xml:lang="es">paquete de descarga eMusic</comment>
- <comment xml:lang="eu">eMusic deskargaren paketea</comment>
- <comment xml:lang="fi">eMusic-imurointipaketti</comment>
- <comment xml:lang="fo">eMusic niðurtøkupakki</comment>
- <comment xml:lang="fr">paquet de téléchargement eMusic</comment>
- <comment xml:lang="ga">pacáiste íosluchtú eMusic</comment>
- <comment xml:lang="gl">paquete de descarga de eMusic</comment>
- <comment xml:lang="he">חבילת הורדה של eMusic</comment>
- <comment xml:lang="hr">eMusic preuzeti paket</comment>
- <comment xml:lang="hu">eMusic letöltési csomag</comment>
- <comment xml:lang="ia">Pacchetto de discargamento eMusic</comment>
- <comment xml:lang="id">paket unduh eMusic</comment>
- <comment xml:lang="it">Pacchetto scaricamento eMusic</comment>
- <comment xml:lang="ja">eMusic ダウンロードパッケージ</comment>
- <comment xml:lang="kk">eMusic жүктемелер дестесі</comment>
- <comment xml:lang="ko">eMusic 다운로드 패키지</comment>
- <comment xml:lang="lt">eMusic atsiuntimo paketas</comment>
- <comment xml:lang="lv">eMusic lejupielādes paciņa</comment>
- <comment xml:lang="nb">eMusic nedlastingspakke</comment>
- <comment xml:lang="nl">eMusic-downloadpakket</comment>
- <comment xml:lang="nn">eMusic nedlastingspakke</comment>
- <comment xml:lang="oc">paquet de telecargament eMusic</comment>
- <comment xml:lang="pl">Pobrany pakiet eMusic</comment>
- <comment xml:lang="pt">pacote transferido eMusic</comment>
- <comment xml:lang="pt_BR">Pacote de download do eMusic</comment>
- <comment xml:lang="ro">pachet descărcare eMusic</comment>
- <comment xml:lang="ru">Пакет загрузок eMusic</comment>
- <comment xml:lang="sk">Balíček sťahovania eMusic</comment>
- <comment xml:lang="sl">Datoteka paketa eMusic</comment>
- <comment xml:lang="sq">Paketë shkarkimi eMusic</comment>
- <comment xml:lang="sr">пакет преузимања еМузике</comment>
- <comment xml:lang="sv">eMusic-hämtningspaket</comment>
- <comment xml:lang="tr">eMusic indirme paketi</comment>
- <comment xml:lang="uk">пакунок завантаження eMusic</comment>
- <comment xml:lang="vi">gói nhạc tải xuống eMusic</comment>
- <comment xml:lang="zh_CN">eMusic 下载包</comment>
<comment xml:lang="zh_TW">eMusic 下載包</comment>
+ <comment xml:lang="zh_CN">eMusic 下载包</comment>
+ <comment xml:lang="vi">gói nhạc tải xuống eMusic</comment>
+ <comment xml:lang="uk">пакунок завантаження eMusic</comment>
+ <comment xml:lang="tr">eMusic indirme paketi</comment>
+ <comment xml:lang="sv">eMusic-hämtningspaket</comment>
+ <comment xml:lang="sr">пакет преузимања еМузике</comment>
+ <comment xml:lang="sq">paketë shkarkimi eMusic</comment>
+ <comment xml:lang="sl">Datoteka paketa eMusic</comment>
+ <comment xml:lang="si">eMusic බාගත කිරීමේ පැකේජය</comment>
+ <comment xml:lang="sk">Balíček sťahovania eMusic</comment>
+ <comment xml:lang="ru">Пакет загрузок eMusic</comment>
+ <comment xml:lang="ro">pachet descărcare eMusic</comment>
+ <comment xml:lang="pt_BR">Pacote de download do eMusic</comment>
+ <comment xml:lang="pt">pacote transferido eMusic</comment>
+ <comment xml:lang="pl">Pobrany pakiet eMusic</comment>
+ <comment xml:lang="oc">paquet de telecargament eMusic</comment>
+ <comment xml:lang="nn">eMusic nedlastingspakke</comment>
+ <comment xml:lang="nl">eMusic-downloadpakket</comment>
+ <comment xml:lang="nb">eMusic nedlastingspakke</comment>
+ <comment xml:lang="lv">eMusic lejupielādes paciņa</comment>
+ <comment xml:lang="lt">eMusic atsiuntimo paketas</comment>
+ <comment xml:lang="ko">eMusic 다운로드 패키지</comment>
+ <comment xml:lang="kk">eMusic жүктемелер дестесі</comment>
+ <comment xml:lang="ja">eMusic ダウンロードパッケージ</comment>
+ <comment xml:lang="it">Pacchetto scaricamento eMusic</comment>
+ <comment xml:lang="is">eMusic niðurhalspakki</comment>
+ <comment xml:lang="id">paket unduh eMusic</comment>
+ <comment xml:lang="ia">Pacchetto de discargamento eMusic</comment>
+ <comment xml:lang="hu">eMusic letöltési csomag</comment>
+ <comment xml:lang="hr">eMusic preuzeti paket</comment>
+ <comment xml:lang="he">חבילת הורדה של eMusic</comment>
+ <comment xml:lang="gl">paquete de descarga de eMusic</comment>
+ <comment xml:lang="ga">pacáiste íosluchtú eMusic</comment>
+ <comment xml:lang="fur">pachet di discjariament eMusic</comment>
+ <comment xml:lang="fr">paquet de téléchargement eMusic</comment>
+ <comment xml:lang="fo">eMusic niðurtøkupakki</comment>
+ <comment xml:lang="fi">eMusic-imurointipaketti</comment>
+ <comment xml:lang="eu">eMusic deskargaren paketea</comment>
+ <comment xml:lang="es">paquete de descarga eMusic</comment>
+ <comment xml:lang="en_GB">eMusic download package</comment>
+ <comment xml:lang="el">Πακέτο λήψης eMusic</comment>
+ <comment xml:lang="de">eMusic-Download-Paket</comment>
+ <comment xml:lang="da">eMusic-downloadpakke</comment>
+ <comment xml:lang="cs">balíček stahování eMusic</comment>
+ <comment xml:lang="ca">paquet de baixades d'eMusic</comment>
+ <comment xml:lang="bg">Пакет за сваляне — eMusic</comment>
+ <comment xml:lang="be@latin">pakunak zahruzki eMusic</comment>
+ <comment xml:lang="be">пакет спампоўвання eMusic</comment>
+ <comment xml:lang="ar">حزمة تنزيل eMusic</comment>
+ <comment xml:lang="af">eMusic-aflaaipakket</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="nF7YLao" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="nF7YLao" offset="0"/>
</magic>
<glob pattern="*.emp"/>
</mime-type>
<mime-type type="application/vnd.google-earth.kml+xml">
<comment>KML geographic data</comment>
- <comment xml:lang="ar">بيانات جغرافية KML</comment>
- <comment xml:lang="bg">Географски данни — KML</comment>
- <comment xml:lang="ca">dades geogràfiques KML</comment>
- <comment xml:lang="cs">geografická data KML</comment>
- <comment xml:lang="da">Geografiske data i KML-format</comment>
- <comment xml:lang="de">KML geographische Daten</comment>
- <comment xml:lang="el">Γεωγραφικά δεδομένα KML</comment>
- <comment xml:lang="en_GB">KML geographic data</comment>
- <comment xml:lang="es">datos geográficos KML</comment>
- <comment xml:lang="eu">KML datu geografikoak</comment>
- <comment xml:lang="fi">KML-paikkatieto</comment>
- <comment xml:lang="fo">KML landafrøðilig dáta</comment>
- <comment xml:lang="fr">données géographiques KML</comment>
- <comment xml:lang="ga">sonraí geografacha KML</comment>
- <comment xml:lang="gl">datos xeográficos KML</comment>
- <comment xml:lang="he">מידע גאוגרפי KML</comment>
- <comment xml:lang="hr">KML geografski podaci</comment>
- <comment xml:lang="hu">KML földrajzi adatok</comment>
- <comment xml:lang="ia">Datos geographic KML</comment>
- <comment xml:lang="id">Data geografis KML</comment>
- <comment xml:lang="it">Dati geografici KML</comment>
- <comment xml:lang="ja">KML 地理データ</comment>
- <comment xml:lang="kk">KML географилық ақпараты</comment>
- <comment xml:lang="ko">KML 지리 정보 데이터</comment>
- <comment xml:lang="lt">KML geografiniai duomenys</comment>
- <comment xml:lang="lv">KML ģeogrāfiskie dati</comment>
- <comment xml:lang="nl">KML geographic data</comment>
- <comment xml:lang="oc">donadas geograficas KML</comment>
- <comment xml:lang="pl">Dane geograficzne KML</comment>
- <comment xml:lang="pt">dados geográficos KML</comment>
- <comment xml:lang="pt_BR">Dados geográficos KML</comment>
- <comment xml:lang="ro">Date geografice KML</comment>
- <comment xml:lang="ru">Географические данные KML</comment>
- <comment xml:lang="sk">Zemepisné údaje KML</comment>
- <comment xml:lang="sl">Datoteka geografskih podatkov KML</comment>
- <comment xml:lang="sr">КМЛ географски подаци</comment>
- <comment xml:lang="sv">KML geografisk data</comment>
- <comment xml:lang="tr">KML coğrafi verisi</comment>
- <comment xml:lang="uk">географічні дані KML</comment>
- <comment xml:lang="zh_CN">KML 地理数据</comment>
<comment xml:lang="zh_TW">KML 地理資料</comment>
+ <comment xml:lang="zh_CN">KML 地理数据</comment>
+ <comment xml:lang="uk">географічні дані KML</comment>
+ <comment xml:lang="tr">KML coğrafi verisi</comment>
+ <comment xml:lang="sv">KML geografisk data</comment>
+ <comment xml:lang="sr">КМЛ географски подаци</comment>
+ <comment xml:lang="sq">të dhëna gjeografike KML</comment>
+ <comment xml:lang="sl">Datoteka geografskih podatkov KML</comment>
+ <comment xml:lang="si">KML භූගෝලීය දත්ත</comment>
+ <comment xml:lang="sk">Zemepisné údaje KML</comment>
+ <comment xml:lang="ru">Географические данные KML</comment>
+ <comment xml:lang="ro">Date geografice KML</comment>
+ <comment xml:lang="pt_BR">Dados geográficos KML</comment>
+ <comment xml:lang="pt">dados geográficos KML</comment>
+ <comment xml:lang="pl">Dane geograficzne KML</comment>
+ <comment xml:lang="oc">donadas geograficas KML</comment>
+ <comment xml:lang="nl">KML geografische gegevens</comment>
+ <comment xml:lang="lv">KML ģeogrāfiskie dati</comment>
+ <comment xml:lang="lt">KML geografiniai duomenys</comment>
+ <comment xml:lang="ko">KML 지리 정보 데이터</comment>
+ <comment xml:lang="kk">KML географилық ақпараты</comment>
+ <comment xml:lang="ja">KML 地理データ</comment>
+ <comment xml:lang="it">Dati geografici KML</comment>
+ <comment xml:lang="is">KML hnattstaðsetningargögn</comment>
+ <comment xml:lang="id">Data geografis KML</comment>
+ <comment xml:lang="ia">Datos geographic KML</comment>
+ <comment xml:lang="hu">KML földrajzi adatok</comment>
+ <comment xml:lang="hr">KML geografski podaci</comment>
+ <comment xml:lang="he">מידע גאוגרפי KML</comment>
+ <comment xml:lang="gl">datos xeográficos KML</comment>
+ <comment xml:lang="ga">sonraí geografacha KML</comment>
+ <comment xml:lang="fur">dâts gjeografics KML</comment>
+ <comment xml:lang="fr">données géographiques KML</comment>
+ <comment xml:lang="fo">KML landafrøðilig dáta</comment>
+ <comment xml:lang="fi">KML-paikkatieto</comment>
+ <comment xml:lang="eu">KML datu geografikoak</comment>
+ <comment xml:lang="es">datos geográficos KML</comment>
+ <comment xml:lang="en_GB">KML geographic data</comment>
+ <comment xml:lang="el">Γεωγραφικά δεδομένα KML</comment>
+ <comment xml:lang="de">KML-Geodaten</comment>
+ <comment xml:lang="da">Geografiske data i KML-format</comment>
+ <comment xml:lang="cs">geografická data KML</comment>
+ <comment xml:lang="ca">dades geogràfiques KML</comment>
+ <comment xml:lang="bg">Географски данни — KML</comment>
+ <comment xml:lang="be">геаграфічныя даныя KML</comment>
+ <comment xml:lang="ar">بيانات جغرافية KML</comment>
+ <comment xml:lang="af">KML geografiese data</comment>
<acronym>KML</acronym>
<expanded-acronym>Keyhole Markup Language</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -38788,47 +41453,53 @@
</mime-type>
<mime-type type="application/vnd.google-earth.kmz">
<comment>KML geographic compressed data</comment>
- <comment xml:lang="ar">بيانات جغرافية مضغوطة KML</comment>
- <comment xml:lang="bg">Географски данни — KML, компресирани</comment>
- <comment xml:lang="ca">dades geogràfiques KML amb compressió</comment>
- <comment xml:lang="cs">komprimovaná geografická data KML</comment>
- <comment xml:lang="da">KML-geografiske komprimerede data</comment>
- <comment xml:lang="de">KML geographische komprimierte Daten</comment>
- <comment xml:lang="el">Γεωγραφικά συμπιεσμένα δεδομένα KML</comment>
- <comment xml:lang="en_GB">KML geographic compressed data</comment>
- <comment xml:lang="es">datos geográficos comprimidos KML</comment>
- <comment xml:lang="eu">KML datu geografiko konprimituak</comment>
- <comment xml:lang="fi">Pakattu KML-paikkatieto</comment>
- <comment xml:lang="fo">KML landafrøðilig stappað dáta</comment>
- <comment xml:lang="fr">données géographiques KML compressées</comment>
- <comment xml:lang="ga">sonraí comhbhrúite geografacha KML</comment>
- <comment xml:lang="gl">datos xeográficos KML comprimidos </comment>
- <comment xml:lang="he">מידע גאוגרפי דחוס KML</comment>
- <comment xml:lang="hr">KML sažeti geografski podaci</comment>
- <comment xml:lang="hu">KML tömörített földrajzi adatok</comment>
- <comment xml:lang="ia">Datos geographic KML comprimite</comment>
- <comment xml:lang="id">Data geografis KML terkompresi</comment>
- <comment xml:lang="it">Dati geografici KML compressi</comment>
- <comment xml:lang="ja">KML 地理圧縮データ</comment>
- <comment xml:lang="kk">KML географиялық сығылған ақпарат</comment>
- <comment xml:lang="ko">KML 지리 정보 압축 데이터</comment>
- <comment xml:lang="lt">KML geografiniai suglaudinti duomenys</comment>
- <comment xml:lang="lv">KML saspiesti ģeogrāfiskie dati</comment>
- <comment xml:lang="nl">KML geographic compressed data</comment>
- <comment xml:lang="oc">donadas geograficas KML compressats</comment>
- <comment xml:lang="pl">Skompresowane dane geograficzne KML</comment>
- <comment xml:lang="pt">dados geográficos comprimidos KML</comment>
- <comment xml:lang="pt_BR">Dados geográficos KML compactados</comment>
- <comment xml:lang="ro">Date geografice comprimate KML</comment>
- <comment xml:lang="ru">Сжатые географические данные KML</comment>
- <comment xml:lang="sk">Komprimované zemepisné údaje KML</comment>
- <comment xml:lang="sl">Skrčeni geografski podatki KML</comment>
- <comment xml:lang="sr">КМЛ географски запаковани подаци</comment>
- <comment xml:lang="sv">KML geografiskt komprimerat data</comment>
- <comment xml:lang="tr">KML sıkıştırılmış coğrafi verisi</comment>
- <comment xml:lang="uk">стиснуті географічні дані KML</comment>
- <comment xml:lang="zh_CN">KML 地理压缩数据</comment>
<comment xml:lang="zh_TW">KML 地理壓縮資料</comment>
+ <comment xml:lang="zh_CN">KML 地理压缩数据</comment>
+ <comment xml:lang="uk">стиснуті географічні дані KML</comment>
+ <comment xml:lang="tr">KML sıkıştırılmış coğrafi verisi</comment>
+ <comment xml:lang="sv">KML geografiskt komprimerat data</comment>
+ <comment xml:lang="sr">КМЛ географски запаковани подаци</comment>
+ <comment xml:lang="sq">të dhëna gjeografike KML të ngjeshura</comment>
+ <comment xml:lang="sl">Skrčeni geografski podatki KML</comment>
+ <comment xml:lang="si">KML භූගෝලීය සම්පීඩිත දත්ත</comment>
+ <comment xml:lang="sk">Komprimované zemepisné údaje KML</comment>
+ <comment xml:lang="ru">Сжатые географические данные KML</comment>
+ <comment xml:lang="ro">Date geografice comprimate KML</comment>
+ <comment xml:lang="pt_BR">Dados geográficos KML compactados</comment>
+ <comment xml:lang="pt">dados geográficos comprimidos KML</comment>
+ <comment xml:lang="pl">Skompresowane dane geograficzne KML</comment>
+ <comment xml:lang="oc">donadas geograficas KML compressats</comment>
+ <comment xml:lang="nl">KML geografische gecomprimeerde gegevens</comment>
+ <comment xml:lang="lv">KML saspiesti ģeogrāfiskie dati</comment>
+ <comment xml:lang="lt">KML geografiniai suglaudinti duomenys</comment>
+ <comment xml:lang="ko">KML 지리 정보 압축 데이터</comment>
+ <comment xml:lang="kk">KML географиялық сығылған ақпарат</comment>
+ <comment xml:lang="ja">KML 地理圧縮データ</comment>
+ <comment xml:lang="it">Dati geografici KML compressi</comment>
+ <comment xml:lang="is">KML þjöppuð hnattstaðsetningargögn</comment>
+ <comment xml:lang="id">Data geografis KML terkompresi</comment>
+ <comment xml:lang="ia">Datos geographic KML comprimite</comment>
+ <comment xml:lang="hu">KML tömörített földrajzi adatok</comment>
+ <comment xml:lang="hr">KML sažeti geografski podaci</comment>
+ <comment xml:lang="he">מידע גאוגרפי דחוס KML</comment>
+ <comment xml:lang="gl">datos xeográficos KML comprimidos </comment>
+ <comment xml:lang="ga">sonraí comhbhrúite geografacha KML</comment>
+ <comment xml:lang="fur">dâts gjeografics KML comprimûts</comment>
+ <comment xml:lang="fr">données géographiques KML compressées</comment>
+ <comment xml:lang="fo">KML landafrøðilig stappað dáta</comment>
+ <comment xml:lang="fi">pakattu KML-paikkatieto</comment>
+ <comment xml:lang="eu">KML datu geografiko konprimituak</comment>
+ <comment xml:lang="es">datos geográficos comprimidos KML</comment>
+ <comment xml:lang="en_GB">KML geographic compressed data</comment>
+ <comment xml:lang="el">Γεωγραφικά συμπιεσμένα δεδομένα KML</comment>
+ <comment xml:lang="de">Komprimierte KML-Geodaten</comment>
+ <comment xml:lang="da">KML-geografiske komprimerede data</comment>
+ <comment xml:lang="cs">komprimovaná geografická data KML</comment>
+ <comment xml:lang="ca">dades geogràfiques KML amb compressió</comment>
+ <comment xml:lang="bg">Географски данни — KML, компресирани</comment>
+ <comment xml:lang="be">сціснутыя геаграфічныя даныя KML</comment>
+ <comment xml:lang="ar">بيانات جغرافية مضغوطة KML</comment>
+ <comment xml:lang="af">KML saamgepersde geografiese data</comment>
<acronym>KML</acronym>
<expanded-acronym>Keyhole Markup Language</expanded-acronym>
<sub-class-of type="application/zip"/>
@@ -38836,30 +41507,44 @@
</mime-type>
<mime-type type="application/geo+json">
<comment>GeoJSON geospatial data</comment>
- <comment xml:lang="ca">dades geomàtiques GeoJSON</comment>
- <comment xml:lang="cs">geoprostorová data GeoJSON</comment>
- <comment xml:lang="da">GEoJSON-geospatiale data</comment>
- <comment xml:lang="de">GeoJSON raumbezogene Daten</comment>
- <comment xml:lang="en_GB">GeoJSON geospatial data</comment>
- <comment xml:lang="es">datos geoespaciales en GeoJSON</comment>
- <comment xml:lang="fr">données géospatiales GeoJSON</comment>
- <comment xml:lang="ga">sonraí geospásúla GeoJSON</comment>
- <comment xml:lang="hr">GeoJSON geoprostorni podaci</comment>
- <comment xml:lang="hu">GeoJSON téradatok</comment>
- <comment xml:lang="id">Data geospasial GeoJSON</comment>
- <comment xml:lang="it">Dati geo-spaziali GeoJSON</comment>
- <comment xml:lang="kk">GeoJSON геокеңістіктік деректері</comment>
- <comment xml:lang="ko">GeoJSON 지리 정보 데이터</comment>
- <comment xml:lang="pl">Dane geoprzestrzenne GeoJSON</comment>
- <comment xml:lang="pt_BR">Dados geoespaciais GeoJSON</comment>
- <comment xml:lang="ru">Геопространственные данные GeoJSON</comment>
- <comment xml:lang="sk">Geopriestorové údaje GeoJSON</comment>
- <comment xml:lang="sr">ГеоЈСОН геопросторни подаци</comment>
- <comment xml:lang="sv">Geospatialt GeoJSON-data</comment>
- <comment xml:lang="tr">GeoJSON coğrafi veriler</comment>
- <comment xml:lang="uk">геопросторові дані GeoJSON</comment>
- <comment xml:lang="zh_CN">GeoJSON 地理空间数据</comment>
<comment xml:lang="zh_TW">GeoJSON 地理空間資料</comment>
+ <comment xml:lang="zh_CN">GeoJSON 地理空间数据</comment>
+ <comment xml:lang="uk">геопросторові дані GeoJSON</comment>
+ <comment xml:lang="tr">GeoJSON coğrafi verileri</comment>
+ <comment xml:lang="sv">Geospatialt GeoJSON-data</comment>
+ <comment xml:lang="sr">ГеоЈСОН геопросторни подаци</comment>
+ <comment xml:lang="sq">të dhëna gjeohapësinore GeoJSON</comment>
+ <comment xml:lang="si">GeoJSON භූගෝලීය දත්ත</comment>
+ <comment xml:lang="sk">Geopriestorové údaje GeoJSON</comment>
+ <comment xml:lang="ru">Геопространственные данные GeoJSON</comment>
+ <comment xml:lang="pt_BR">Dados geoespaciais GeoJSON</comment>
+ <comment xml:lang="pl">Dane geoprzestrzenne GeoJSON</comment>
+ <comment xml:lang="nl">GeoJSON geospatiële gegevens</comment>
+ <comment xml:lang="ko">GeoJSON 지리 정보 데이터</comment>
+ <comment xml:lang="kk">GeoJSON геокеңістіктік деректері</comment>
+ <comment xml:lang="ja">GeoJSON 地理空間データ</comment>
+ <comment xml:lang="it">Dati geo-spaziali GeoJSON</comment>
+ <comment xml:lang="is">GeoJSON landupplýsingagögn</comment>
+ <comment xml:lang="id">Data geospasial GeoJSON</comment>
+ <comment xml:lang="hu">GeoJSON téradatok</comment>
+ <comment xml:lang="hr">GeoJSON geoprostorni podaci</comment>
+ <comment xml:lang="he">נתונים מרחביים ב־GeoJSON</comment>
+ <comment xml:lang="gl">Datos xeoespaciais GeoJSON</comment>
+ <comment xml:lang="ga">sonraí geospásúla GeoJSON</comment>
+ <comment xml:lang="fur">dâts gjeo-spaziâls GeoJSON</comment>
+ <comment xml:lang="fr">données géospatiales GeoJSON</comment>
+ <comment xml:lang="fi">GeoJSON-paikkatieto</comment>
+ <comment xml:lang="eu">GeoJSON geomatika datua</comment>
+ <comment xml:lang="es">datos geoespaciales en GeoJSON</comment>
+ <comment xml:lang="en_GB">GeoJSON geospatial data</comment>
+ <comment xml:lang="de">GeoJSON raumbezogene Daten</comment>
+ <comment xml:lang="da">GEoJSON-geospatiale data</comment>
+ <comment xml:lang="cs">geoprostorová data GeoJSON</comment>
+ <comment xml:lang="ca">dades geomàtiques GeoJSON</comment>
+ <comment xml:lang="bg">Географски данни — GeoJSON</comment>
+ <comment xml:lang="be">геапрасторавыя даныя GeoJSON</comment>
+ <comment xml:lang="ar">بيانات جغرافية مكانية GeoJSON</comment>
+ <comment xml:lang="af">GeoJSON georuimtelike data</comment>
<sub-class-of type="application/json"/>
<glob pattern="*.geojson"/>
<glob pattern="*.geo.json"/>
@@ -38867,34 +41552,46 @@
</mime-type>
<mime-type type="application/gpx+xml">
<comment>GPX geographic data</comment>
- <comment xml:lang="ca">dades geogràfiques GPX</comment>
- <comment xml:lang="cs">geografická data GPX</comment>
- <comment xml:lang="da">GPX-geografiske data</comment>
- <comment xml:lang="de">GPX geographische Daten</comment>
- <comment xml:lang="en_GB">GPX geographic data</comment>
- <comment xml:lang="es">datos geográficos en GPX</comment>
- <comment xml:lang="eu">GPX datu geografikoak</comment>
- <comment xml:lang="fi">GPX-paikkatieto</comment>
- <comment xml:lang="fr">données géographiques GPX</comment>
- <comment xml:lang="ga">sonraí geografacha GPX</comment>
- <comment xml:lang="he">נתונים גאוגרפיים GPX</comment>
- <comment xml:lang="hr">GPX geografski podaci</comment>
- <comment xml:lang="hu">GPX földrajzi adatok</comment>
- <comment xml:lang="id">Data geografis GPX</comment>
- <comment xml:lang="it">Dati geografici GPX</comment>
- <comment xml:lang="kk">GPX географикалық деректері</comment>
- <comment xml:lang="ko">GPX 지리 공간정보 데이터</comment>
- <comment xml:lang="oc">Donadas geograficas GPX</comment>
- <comment xml:lang="pl">Dane geograficzne GPX</comment>
- <comment xml:lang="pt_BR">Dados geográficos GPX</comment>
- <comment xml:lang="ru">Географические данные GPX</comment>
- <comment xml:lang="sk">Zemepisné údaje GPX</comment>
- <comment xml:lang="sr">ГПИкс географски подаци</comment>
- <comment xml:lang="sv">GPX geografisk data</comment>
- <comment xml:lang="tr">GPX coğrafi verileri</comment>
- <comment xml:lang="uk">географічні дані GPX</comment>
- <comment xml:lang="zh_CN">GPX 地理数据</comment>
<comment xml:lang="zh_TW">GPX 地理資料</comment>
+ <comment xml:lang="zh_CN">GPX 地理数据</comment>
+ <comment xml:lang="uk">географічні дані GPX</comment>
+ <comment xml:lang="tr">GPX coğrafi verileri</comment>
+ <comment xml:lang="sv">GPX geografisk data</comment>
+ <comment xml:lang="sr">ГПИкс географски подаци</comment>
+ <comment xml:lang="sq">të dhëna gjeografike GPX</comment>
+ <comment xml:lang="sl">Zemljepisni podatki GPX</comment>
+ <comment xml:lang="si">GPX භූගෝලීය දත්ත</comment>
+ <comment xml:lang="sk">Zemepisné údaje GPX</comment>
+ <comment xml:lang="ru">Географические данные GPX</comment>
+ <comment xml:lang="pt_BR">Dados geográficos GPX</comment>
+ <comment xml:lang="pl">Dane geograficzne GPX</comment>
+ <comment xml:lang="oc">Donadas geograficas GPX</comment>
+ <comment xml:lang="nl">GPX geografische gegevens</comment>
+ <comment xml:lang="ko">GPX 지리 공간정보 데이터</comment>
+ <comment xml:lang="kk">GPX географикалық деректері</comment>
+ <comment xml:lang="ja">GPX 地理データ</comment>
+ <comment xml:lang="it">Dati geografici GPX</comment>
+ <comment xml:lang="is">GPX hnattstaðsetningargögn</comment>
+ <comment xml:lang="id">Data geografis GPX</comment>
+ <comment xml:lang="hu">GPX földrajzi adatok</comment>
+ <comment xml:lang="hr">GPX geografski podaci</comment>
+ <comment xml:lang="he">נתונים גאוגרפיים GPX</comment>
+ <comment xml:lang="gl">Datos xeográficos GPX</comment>
+ <comment xml:lang="ga">sonraí geografacha GPX</comment>
+ <comment xml:lang="fur">dâts gjeografics GPX</comment>
+ <comment xml:lang="fr">données géographiques GPX</comment>
+ <comment xml:lang="fi">GPX-paikkatieto</comment>
+ <comment xml:lang="eu">GPX datu geografikoak</comment>
+ <comment xml:lang="es">datos geográficos en GPX</comment>
+ <comment xml:lang="en_GB">GPX geographic data</comment>
+ <comment xml:lang="de">GPX geographische Daten</comment>
+ <comment xml:lang="da">GPX-geografiske data</comment>
+ <comment xml:lang="cs">geografická data GPX</comment>
+ <comment xml:lang="ca">dades geogràfiques GPX</comment>
+ <comment xml:lang="bg">Географски данни — GPX</comment>
+ <comment xml:lang="be">геаграфічныя даныя GPX</comment>
+ <comment xml:lang="ar">بيانات جغرافية GPX</comment>
+ <comment xml:lang="af">GPX geografiese data</comment>
<acronym>GPX</acronym>
<expanded-acronym>GPS Exchange Format</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -38907,53 +41604,58 @@
</mime-type>
<mime-type type="application/x-ica">
<comment>Citrix ICA settings file</comment>
- <comment xml:lang="ar">ملف إعدادات Citrix ICA</comment>
- <comment xml:lang="be@latin">Fajł naładaŭ Citrix ICA</comment>
- <comment xml:lang="bg">Настройки — Citrix ICA</comment>
- <comment xml:lang="ca">fitxer d'ajusts de Citrix ICA</comment>
- <comment xml:lang="cs">soubor nastavení Citrix ICA</comment>
- <comment xml:lang="da">Citrix ICA-opsætningsfil</comment>
- <comment xml:lang="de">Citrix-ICA-Einstellungsdatei</comment>
- <comment xml:lang="el">Αρχείο ρυθμίσεων Citrix ICA</comment>
- <comment xml:lang="en_GB">Citrix ICA settings file</comment>
- <comment xml:lang="es">archivo de configuración de Citrix ICA</comment>
- <comment xml:lang="eu">Citrix ICA ezarpenen fitxategia</comment>
- <comment xml:lang="fi">Citrix ICA -asetustiedosto</comment>
- <comment xml:lang="fo">Citrix ICA stillingarfíla</comment>
- <comment xml:lang="fr">fichier de paramètres ICA Citrix</comment>
- <comment xml:lang="ga">comhad socruithe Citrix ICA</comment>
- <comment xml:lang="gl">ficheiro de configuracións de Citrix ICA</comment>
- <comment xml:lang="he">קובץ הגדרות של Citrix ICA</comment>
- <comment xml:lang="hr">Citrix ICA datoteka postavki</comment>
- <comment xml:lang="hu">Citrix ICA beállításfájl</comment>
- <comment xml:lang="ia">File de configuration ICA Citrix</comment>
- <comment xml:lang="id">Berkas penataan Citrix ICA</comment>
- <comment xml:lang="it">File impostazioni Citrix ICA</comment>
- <comment xml:lang="ja">Citrix ICA 設定ファイル</comment>
- <comment xml:lang="ka">Citrix ICA-ის პარამეტრების ფაილი</comment>
- <comment xml:lang="kk">Citrix ICA баптаулар файлы</comment>
- <comment xml:lang="ko">시트릭스 ICA 설정 파일</comment>
- <comment xml:lang="lt">Citrix ICA parametrų failas</comment>
- <comment xml:lang="lv">Citrix ICA iestatījumu datne</comment>
- <comment xml:lang="nb">Innstillingsfil for Citrix ICA</comment>
- <comment xml:lang="nl">Citrix ICA-instellingen</comment>
- <comment xml:lang="nn">Citrix ICA-innstillingsfil</comment>
- <comment xml:lang="oc">fichièr de paramètres ICA Citrix</comment>
- <comment xml:lang="pl">Plik ustawień Citrix ICA</comment>
- <comment xml:lang="pt">ficheiro de definições Citrix ICA</comment>
- <comment xml:lang="pt_BR">Arquivo de configuração do Citrix ICA</comment>
- <comment xml:lang="ro">Fișier de configurări Citrix ICA</comment>
- <comment xml:lang="ru">Файл настроек Citrix ICA</comment>
- <comment xml:lang="sk">Súbor nastavení Citrix ICA</comment>
- <comment xml:lang="sl">Nastavitvena datoteka Citrix ICA</comment>
- <comment xml:lang="sq">File rregullimesh Citrix ICA</comment>
- <comment xml:lang="sr">датотека подешавања Цитрикс ИЦА-а</comment>
- <comment xml:lang="sv">Citrix ICA-inställningsfil</comment>
- <comment xml:lang="tr">Citrix ICA ayar dosyası</comment>
- <comment xml:lang="uk">файл параметрів ICA Citrix</comment>
- <comment xml:lang="vi">Tập tin thiết lập ICA Citrix</comment>
- <comment xml:lang="zh_CN">Citrix ICA 设置文件</comment>
<comment xml:lang="zh_TW">Citrix ICA 設定值檔案</comment>
+ <comment xml:lang="zh_CN">Citrix ICA 设置文件</comment>
+ <comment xml:lang="vi">Tập tin thiết lập ICA Citrix</comment>
+ <comment xml:lang="uk">файл параметрів ICA Citrix</comment>
+ <comment xml:lang="tr">Citrix ICA ayar dosyası</comment>
+ <comment xml:lang="sv">Citrix ICA-inställningsfil</comment>
+ <comment xml:lang="sr">датотека подешавања Цитрикс ИЦА-а</comment>
+ <comment xml:lang="sq">kartelë rregullimesh Citrix ICA</comment>
+ <comment xml:lang="sl">Nastavitvena datoteka Citrix ICA</comment>
+ <comment xml:lang="si">Citrix ICA සැකසුම් ගොනුව</comment>
+ <comment xml:lang="sk">Súbor nastavení Citrix ICA</comment>
+ <comment xml:lang="ru">Файл настроек Citrix ICA</comment>
+ <comment xml:lang="ro">Fișier de configurări Citrix ICA</comment>
+ <comment xml:lang="pt_BR">Arquivo de configuração do Citrix ICA</comment>
+ <comment xml:lang="pt">ficheiro de definições Citrix ICA</comment>
+ <comment xml:lang="pl">Plik ustawień Citrix ICA</comment>
+ <comment xml:lang="oc">fichièr de paramètres ICA Citrix</comment>
+ <comment xml:lang="nn">Citrix ICA-innstillingsfil</comment>
+ <comment xml:lang="nl">Citrix ICA-instellingen</comment>
+ <comment xml:lang="nb">Innstillingsfil for Citrix ICA</comment>
+ <comment xml:lang="lv">Citrix ICA iestatījumu datne</comment>
+ <comment xml:lang="lt">Citrix ICA parametrų failas</comment>
+ <comment xml:lang="ko">시트릭스 ICA 설정 파일</comment>
+ <comment xml:lang="kk">Citrix ICA баптаулар файлы</comment>
+ <comment xml:lang="ka">Citrix ICA-ის პარამეტრების ფაილი</comment>
+ <comment xml:lang="ja">Citrix ICA 設定ファイル</comment>
+ <comment xml:lang="it">File impostazioni Citrix ICA</comment>
+ <comment xml:lang="is">Citrix ICA stillingaskrá</comment>
+ <comment xml:lang="id">Berkas penataan Citrix ICA</comment>
+ <comment xml:lang="ia">File de configuration ICA Citrix</comment>
+ <comment xml:lang="hu">Citrix ICA beállításfájl</comment>
+ <comment xml:lang="hr">Citrix ICA datoteka postavki</comment>
+ <comment xml:lang="he">קובץ הגדרות של Citrix ICA</comment>
+ <comment xml:lang="gl">ficheiro de configuracións de Citrix ICA</comment>
+ <comment xml:lang="ga">comhad socruithe Citrix ICA</comment>
+ <comment xml:lang="fur">file impostazions Citrix ICA</comment>
+ <comment xml:lang="fr">fichier de paramètres ICA Citrix</comment>
+ <comment xml:lang="fo">Citrix ICA stillingarfíla</comment>
+ <comment xml:lang="fi">Citrix ICA -asetustiedosto</comment>
+ <comment xml:lang="eu">Citrix ICA ezarpenen fitxategia</comment>
+ <comment xml:lang="es">archivo de configuración de Citrix ICA</comment>
+ <comment xml:lang="en_GB">Citrix ICA settings file</comment>
+ <comment xml:lang="el">Αρχείο ρυθμίσεων Citrix ICA</comment>
+ <comment xml:lang="de">Citrix-ICA-Einstellungsdatei</comment>
+ <comment xml:lang="da">Citrix ICA-opsætningsfil</comment>
+ <comment xml:lang="cs">soubor nastavení Citrix ICA</comment>
+ <comment xml:lang="ca">fitxer d'ajusts de Citrix ICA</comment>
+ <comment xml:lang="bg">Настройки — Citrix ICA</comment>
+ <comment xml:lang="be@latin">Fajł naładaŭ Citrix ICA</comment>
+ <comment xml:lang="be">файл налад Citrix ICA</comment>
+ <comment xml:lang="ar">ملف إعدادات Citrix ICA</comment>
+ <comment xml:lang="af">Citrix ICA-instellingslêer</comment>
<acronym>ICA</acronym>
<expanded-acronym>Independent Computing Architecture</expanded-acronym>
<sub-class-of type="text/plain"/>
@@ -38962,53 +41664,58 @@
</mime-type>
<mime-type type="application/vnd.mozilla.xul+xml">
<comment>XUL interface document</comment>
- <comment xml:lang="ar">مستند واجهة XUL</comment>
- <comment xml:lang="ast">Documentu d'interfaz XUL</comment>
- <comment xml:lang="be@latin">Interfejsny dakument XUL</comment>
- <comment xml:lang="bg">Документ — интерфейс за XUL</comment>
- <comment xml:lang="ca">document d'interfície XUL</comment>
- <comment xml:lang="cs">dokument rozhraní XUL</comment>
- <comment xml:lang="da">XUL-grænsefladedokument</comment>
- <comment xml:lang="de">XUL-Oberflächendokument</comment>
- <comment xml:lang="el">Έγγραφο διεπαφής XUL</comment>
- <comment xml:lang="en_GB">XUL interface document</comment>
- <comment xml:lang="es">documento de interfaz XUL</comment>
- <comment xml:lang="eu">XUL interfazearen dokumentua</comment>
- <comment xml:lang="fi">XUL-käyttöliittymäasiakirja</comment>
- <comment xml:lang="fo">XUL markamótsskjal</comment>
- <comment xml:lang="fr">document d'interface XUL</comment>
- <comment xml:lang="ga">cáipéis chomhéadan XUL</comment>
- <comment xml:lang="gl">documento de interface XUL</comment>
- <comment xml:lang="he">מסמך ממשק XUL</comment>
- <comment xml:lang="hr">XUL dokument sučelja</comment>
- <comment xml:lang="hu">XUL-felületdokumentum</comment>
- <comment xml:lang="ia">Documento de interfacie XUL</comment>
- <comment xml:lang="id">Dokumen antarmuka XUL</comment>
- <comment xml:lang="it">Documento interfaccia XUL</comment>
- <comment xml:lang="ja">XUL インターフェイスドキュメント</comment>
- <comment xml:lang="kk">XUL интерфейс құжаты</comment>
- <comment xml:lang="ko">XUL 인터페이스 문서</comment>
- <comment xml:lang="lt">XUL sąsajos dokumentas</comment>
- <comment xml:lang="lv">XUL saskarnes dokuments</comment>
- <comment xml:lang="nb">XUL-grensesnittdokument</comment>
- <comment xml:lang="nl">XUL-interface-document</comment>
- <comment xml:lang="nn">XUL-grensesnitt-dokument</comment>
- <comment xml:lang="oc">document d'interfàcia XUL</comment>
- <comment xml:lang="pl">Dokument interfejsu XUL</comment>
- <comment xml:lang="pt">documento de ambiente XUL</comment>
- <comment xml:lang="pt_BR">Documento de interface XUL</comment>
- <comment xml:lang="ro">Document interfață XUL</comment>
- <comment xml:lang="ru">Документ интерфейса XUL</comment>
- <comment xml:lang="sk">Dokument rozhrania XUL</comment>
- <comment xml:lang="sl">Dokument vmesnika XUL</comment>
- <comment xml:lang="sq">Dokument interfaqe XUL</comment>
- <comment xml:lang="sr">документ ИксУЛ сучеља</comment>
- <comment xml:lang="sv">XUL-gränssnittsdokument</comment>
- <comment xml:lang="tr">XUL arayüz belgesi</comment>
- <comment xml:lang="uk">документ інтерфейсу XUL</comment>
- <comment xml:lang="vi">Tài liệu giao diện XUL</comment>
- <comment xml:lang="zh_CN">XUL 界面文档</comment>
<comment xml:lang="zh_TW">XUL 介面文件</comment>
+ <comment xml:lang="zh_CN">XUL 界面文档</comment>
+ <comment xml:lang="vi">Tài liệu giao diện XUL</comment>
+ <comment xml:lang="uk">документ інтерфейсу XUL</comment>
+ <comment xml:lang="tr">XUL arayüz belgesi</comment>
+ <comment xml:lang="sv">XUL-gränssnittsdokument</comment>
+ <comment xml:lang="sr">документ ИксУЛ сучеља</comment>
+ <comment xml:lang="sq">dokument ndërfaqeje XUL</comment>
+ <comment xml:lang="sl">Dokument vmesnika XUL</comment>
+ <comment xml:lang="si">XUL අතුරුමුහුණත් ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument rozhrania XUL</comment>
+ <comment xml:lang="ru">Документ интерфейса XUL</comment>
+ <comment xml:lang="ro">Document interfață XUL</comment>
+ <comment xml:lang="pt_BR">Documento de interface XUL</comment>
+ <comment xml:lang="pt">documento de ambiente XUL</comment>
+ <comment xml:lang="pl">Dokument interfejsu XUL</comment>
+ <comment xml:lang="oc">document d'interfàcia XUL</comment>
+ <comment xml:lang="nn">XUL-grensesnitt-dokument</comment>
+ <comment xml:lang="nl">XUL-interface-document</comment>
+ <comment xml:lang="nb">XUL-grensesnittdokument</comment>
+ <comment xml:lang="lv">XUL saskarnes dokuments</comment>
+ <comment xml:lang="lt">XUL sąsajos dokumentas</comment>
+ <comment xml:lang="ko">XUL 인터페이스 문서</comment>
+ <comment xml:lang="kk">XUL интерфейс құжаты</comment>
+ <comment xml:lang="ja">XUL インターフェイスドキュメント</comment>
+ <comment xml:lang="it">Documento interfaccia XUL</comment>
+ <comment xml:lang="is">XUL viðmótsskjal</comment>
+ <comment xml:lang="id">Dokumen antarmuka XUL</comment>
+ <comment xml:lang="ia">Documento de interfacie XUL</comment>
+ <comment xml:lang="hu">XUL-felületdokumentum</comment>
+ <comment xml:lang="hr">XUL dokument sučelja</comment>
+ <comment xml:lang="he">מסמך ממשק XUL</comment>
+ <comment xml:lang="gl">documento de interface XUL</comment>
+ <comment xml:lang="ga">cáipéis chomhéadan XUL</comment>
+ <comment xml:lang="fur">document di interface XUL</comment>
+ <comment xml:lang="fr">document d'interface XUL</comment>
+ <comment xml:lang="fo">XUL markamótsskjal</comment>
+ <comment xml:lang="fi">XUL-käyttöliittymäasiakirja</comment>
+ <comment xml:lang="eu">XUL interfazearen dokumentua</comment>
+ <comment xml:lang="es">documento de interfaz XUL</comment>
+ <comment xml:lang="en_GB">XUL interface document</comment>
+ <comment xml:lang="el">Έγγραφο διεπαφής XUL</comment>
+ <comment xml:lang="de">XUL-Benutzeroberflächendokument</comment>
+ <comment xml:lang="da">XUL-grænsefladedokument</comment>
+ <comment xml:lang="cs">dokument rozhraní XUL</comment>
+ <comment xml:lang="ca">document d'interfície XUL</comment>
+ <comment xml:lang="bg">Документ — интерфейс, XUL</comment>
+ <comment xml:lang="be@latin">Interfejsny dakument XUL</comment>
+ <comment xml:lang="be">дакумент інтэрфейсу XUL</comment>
+ <comment xml:lang="ast">Documentu d'interfaz XUL</comment>
+ <comment xml:lang="ar">مستند واجهة XUL</comment>
+ <comment xml:lang="af">XUL-koppelvlakdokument</comment>
<acronym>XUL</acronym>
<expanded-acronym>XML User interface markup Language</expanded-acronym>
<sub-class-of type="application/xml"/>
@@ -39018,631 +41725,711 @@
</mime-type>
<mime-type type="application/x-xpinstall">
<comment>XPInstall installer module</comment>
- <comment xml:lang="ar">وحدة مثبت XPInstall </comment>
- <comment xml:lang="bg">Пакет — инсталация XPInstall</comment>
- <comment xml:lang="ca">mòdul de l'instal·lador XPinstall</comment>
- <comment xml:lang="cs">modul instalátoru XPInstall</comment>
- <comment xml:lang="da">XPInstall-installationsmodul</comment>
- <comment xml:lang="de">XPInstall-Installationsmodul</comment>
- <comment xml:lang="el">Άρθρωμα εγκατάστασης XPInstall</comment>
- <comment xml:lang="en_GB">XPInstall installer module</comment>
- <comment xml:lang="es">módulo del instalador XPInstall</comment>
- <comment xml:lang="eu">XPInstall instalatzailearen modulua</comment>
- <comment xml:lang="fi">XPInstall-asennuspaketti</comment>
- <comment xml:lang="fo">XPInstall innleggjaramótul</comment>
- <comment xml:lang="fr">module d'installation XPInstall</comment>
- <comment xml:lang="ga">modúl suiteála XPInstall</comment>
- <comment xml:lang="gl">Módulo do instalador XPInstall</comment>
- <comment xml:lang="he">מודול התקנה של XPInstall</comment>
- <comment xml:lang="hr">XPInstall instalacijski modul</comment>
- <comment xml:lang="hu">XPInstall telepítőmodul</comment>
- <comment xml:lang="ia">Modulo de installation XPInstall</comment>
- <comment xml:lang="id">Modul installer XPInstall</comment>
- <comment xml:lang="it">Modulo installatore XPInstall</comment>
- <comment xml:lang="ja">XPInstall インストーラモジュール</comment>
- <comment xml:lang="kk">XPInstall орнату модулі</comment>
- <comment xml:lang="ko">XPInstall 설치 프로그램 모듈</comment>
- <comment xml:lang="lt">XPInstall įdiegiklio modulis</comment>
- <comment xml:lang="lv">XPInstall instalatora modulis</comment>
- <comment xml:lang="nl">XPInstall installeer module</comment>
- <comment xml:lang="oc">modul d'installacion XPInstall</comment>
- <comment xml:lang="pl">Moduł instalatora XPInstall</comment>
- <comment xml:lang="pt">módulo de instalador XPInstall</comment>
- <comment xml:lang="pt_BR">Módulo de instalador XPInstall</comment>
- <comment xml:lang="ro">Modul de instalare XPInstall</comment>
- <comment xml:lang="ru">Модуль установщика XPInstall</comment>
- <comment xml:lang="sk">Modul inštalátora XPInstall</comment>
- <comment xml:lang="sl">modul namestilnika XPInstall</comment>
- <comment xml:lang="sr">модул инсталатера Инсталирања ИксПе-а</comment>
- <comment xml:lang="sv">XPInstall-installeringsmodul</comment>
- <comment xml:lang="tr">XPInstall kurulum modülü</comment>
- <comment xml:lang="uk">модуль засобу встановлення XPInstall</comment>
- <comment xml:lang="zh_CN">XPInstall 安装工具模块</comment>
<comment xml:lang="zh_TW">XPInstall 安裝程式模組</comment>
+ <comment xml:lang="zh_CN">XPInstall 安装工具模块</comment>
+ <comment xml:lang="uk">модуль засобу встановлення XPInstall</comment>
+ <comment xml:lang="tr">XPInstall kurulum modülü</comment>
+ <comment xml:lang="sv">XPInstall-installeringsmodul</comment>
+ <comment xml:lang="sr">модул инсталатера Инсталирања ИксПе-а</comment>
+ <comment xml:lang="sq">modul instaluesi XPInstall</comment>
+ <comment xml:lang="sl">modul namestilnika XPInstall</comment>
+ <comment xml:lang="si">XPI ස්ථාපක මොඩියුලය ස්ථාපනය කරන්න</comment>
+ <comment xml:lang="sk">Modul inštalátora XPInstall</comment>
+ <comment xml:lang="ru">Модуль установщика XPInstall</comment>
+ <comment xml:lang="ro">Modul de instalare XPInstall</comment>
+ <comment xml:lang="pt_BR">Módulo de instalador XPInstall</comment>
+ <comment xml:lang="pt">módulo de instalador XPInstall</comment>
+ <comment xml:lang="pl">Moduł instalatora XPInstall</comment>
+ <comment xml:lang="oc">modul d'installacion XPInstall</comment>
+ <comment xml:lang="nl">XPInstall installeer module</comment>
+ <comment xml:lang="lv">XPInstall instalatora modulis</comment>
+ <comment xml:lang="lt">XPInstall įdiegiklio modulis</comment>
+ <comment xml:lang="ko">XPInstall 설치 프로그램 모듈</comment>
+ <comment xml:lang="kk">XPInstall орнату модулі</comment>
+ <comment xml:lang="ja">XPInstall インストーラモジュール</comment>
+ <comment xml:lang="it">Modulo installatore XPInstall</comment>
+ <comment xml:lang="is">XPInstall uppsetningareining</comment>
+ <comment xml:lang="id">Modul installer XPInstall</comment>
+ <comment xml:lang="ia">Modulo de installation XPInstall</comment>
+ <comment xml:lang="hu">XPInstall telepítőmodul</comment>
+ <comment xml:lang="hr">XPInstall instalacijski modul</comment>
+ <comment xml:lang="he">מודול התקנה של XPInstall</comment>
+ <comment xml:lang="gl">Módulo do instalador XPInstall</comment>
+ <comment xml:lang="ga">modúl suiteála XPInstall</comment>
+ <comment xml:lang="fur">modul instaladôr XPInstall</comment>
+ <comment xml:lang="fr">module d'installation XPInstall</comment>
+ <comment xml:lang="fo">XPInstall innleggjaramótul</comment>
+ <comment xml:lang="fi">XPInstall-asennuspaketti</comment>
+ <comment xml:lang="eu">XPInstall instalatzailearen modulua</comment>
+ <comment xml:lang="es">módulo del instalador XPInstall</comment>
+ <comment xml:lang="en_GB">XPInstall installer module</comment>
+ <comment xml:lang="el">Άρθρωμα εγκατάστασης XPInstall</comment>
+ <comment xml:lang="de">XPInstall-Installationsmodul</comment>
+ <comment xml:lang="da">XPInstall-installationsmodul</comment>
+ <comment xml:lang="cs">modul instalátoru XPInstall</comment>
+ <comment xml:lang="ca">mòdul de l'instal·lador XPinstall</comment>
+ <comment xml:lang="bg">Пакет — инсталация XPInstall</comment>
+ <comment xml:lang="be">модуль усталёўшчыка XPInstall</comment>
+ <comment xml:lang="ar">وحدة مثبت XPInstall</comment>
+ <comment xml:lang="af">XPInstall-installasiemodule</comment>
<sub-class-of type="application/zip"/>
<glob pattern="*.xpi"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
<comment>Word 2007 document</comment>
- <comment xml:lang="ar">مستند Word 2007</comment>
- <comment xml:lang="ast">Documentu de Word 2007</comment>
- <comment xml:lang="bg">Документ — Word 2007</comment>
- <comment xml:lang="ca">document de Word 2007</comment>
- <comment xml:lang="cs">dokument Word 2007</comment>
- <comment xml:lang="da">Word 2007-dokument</comment>
- <comment xml:lang="de">Word-2007-Dokument</comment>
- <comment xml:lang="el">Έγγραφο Word 2007</comment>
- <comment xml:lang="en_GB">Word 2007 document</comment>
- <comment xml:lang="es">documento de Word 2007</comment>
- <comment xml:lang="eu">Word 2007 dokumentua</comment>
- <comment xml:lang="fi">Word 2007 -asiakirja</comment>
- <comment xml:lang="fo">Word 2007 skjal</comment>
- <comment xml:lang="fr">document Word 2007</comment>
- <comment xml:lang="ga">cáipéis Word 2007</comment>
- <comment xml:lang="gl">documento de Word 2007</comment>
- <comment xml:lang="he">מסמך Word 2007</comment>
- <comment xml:lang="hr">Word 2007 dokument</comment>
- <comment xml:lang="hu">Word 2007 dokumentum</comment>
- <comment xml:lang="ia">Documento Word 2007</comment>
- <comment xml:lang="id">Dokumen Word 2007</comment>
- <comment xml:lang="it">Documento Word 2007</comment>
- <comment xml:lang="ja">Word 2007 ドキュメント</comment>
- <comment xml:lang="kk">Word 2007 құжаты</comment>
- <comment xml:lang="ko">Word 2007 문서</comment>
- <comment xml:lang="lt">Word 2007 dokumentas</comment>
- <comment xml:lang="lv">Word 2007 dokuments</comment>
- <comment xml:lang="nl">Word 2007-document</comment>
- <comment xml:lang="oc">document Word 2007</comment>
- <comment xml:lang="pl">Dokument Word 2007</comment>
- <comment xml:lang="pt">documento Word 2007</comment>
- <comment xml:lang="pt_BR">Documento do Word 2007</comment>
- <comment xml:lang="ro">Document Word 2007</comment>
- <comment xml:lang="ru">Документ Word 2007</comment>
- <comment xml:lang="sk">Dokument Word 2007</comment>
- <comment xml:lang="sl">Dokument Word 2007</comment>
- <comment xml:lang="sr">документ Ворда 2007</comment>
- <comment xml:lang="sv">Word 2007-dokument</comment>
- <comment xml:lang="tr">Word 2007 belgesi</comment>
- <comment xml:lang="uk">документ Word 2007</comment>
- <comment xml:lang="vi">Tài liệu Word 2007</comment>
- <comment xml:lang="zh_CN">Word 2007 文档</comment>
<comment xml:lang="zh_TW">Word 2007 文件</comment>
+ <comment xml:lang="zh_CN">Word 2007 文档</comment>
+ <comment xml:lang="vi">Tài liệu Word 2007</comment>
+ <comment xml:lang="uk">документ Word 2007</comment>
+ <comment xml:lang="tr">Word 2007 belgesi</comment>
+ <comment xml:lang="sv">Word 2007-dokument</comment>
+ <comment xml:lang="sr">документ Ворда 2007</comment>
+ <comment xml:lang="sq">dokument Word 2007</comment>
+ <comment xml:lang="sl">Dokument Word 2007</comment>
+ <comment xml:lang="si">Word 2007 ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Word 2007</comment>
+ <comment xml:lang="ru">Документ Word 2007</comment>
+ <comment xml:lang="ro">Document Word 2007</comment>
+ <comment xml:lang="pt_BR">Documento do Word 2007</comment>
+ <comment xml:lang="pt">documento Word 2007</comment>
+ <comment xml:lang="pl">Dokument Word 2007</comment>
+ <comment xml:lang="oc">document Word 2007</comment>
+ <comment xml:lang="nl">Word 2007-document</comment>
+ <comment xml:lang="lv">Word 2007 dokuments</comment>
+ <comment xml:lang="lt">Word 2007 dokumentas</comment>
+ <comment xml:lang="ko">Word 2007 문서</comment>
+ <comment xml:lang="kk">Word 2007 құжаты</comment>
+ <comment xml:lang="ja">Word 2007 ドキュメント</comment>
+ <comment xml:lang="it">Documento Word 2007</comment>
+ <comment xml:lang="is">Word 2007 skjal</comment>
+ <comment xml:lang="id">Dokumen Word 2007</comment>
+ <comment xml:lang="ia">Documento Word 2007</comment>
+ <comment xml:lang="hu">Word 2007 dokumentum</comment>
+ <comment xml:lang="hr">Word 2007 dokument</comment>
+ <comment xml:lang="he">מסמך Word 2007</comment>
+ <comment xml:lang="gl">documento de Word 2007</comment>
+ <comment xml:lang="ga">cáipéis Word 2007</comment>
+ <comment xml:lang="fur">document Word 2007</comment>
+ <comment xml:lang="fr">document Word 2007</comment>
+ <comment xml:lang="fo">Word 2007 skjal</comment>
+ <comment xml:lang="fi">Word 2007 -asiakirja</comment>
+ <comment xml:lang="eu">Word 2007 dokumentua</comment>
+ <comment xml:lang="es">documento de Word 2007</comment>
+ <comment xml:lang="en_GB">Word 2007 document</comment>
+ <comment xml:lang="el">Έγγραφο Word 2007</comment>
+ <comment xml:lang="de">Word-2007-Dokument</comment>
+ <comment xml:lang="da">Word 2007-dokument</comment>
+ <comment xml:lang="cs">dokument Word 2007</comment>
+ <comment xml:lang="ca">document de Word 2007</comment>
+ <comment xml:lang="bg">Документ — Word 2007</comment>
+ <comment xml:lang="be">дакумент Word 2007</comment>
+ <comment xml:lang="ast">Documentu de Word 2007</comment>
+ <comment xml:lang="ar">مستند ورد 2007</comment>
+ <comment xml:lang="af">Word 2007-dokument</comment>
<glob pattern="*.docx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
<comment>Word 2007 document template</comment>
- <comment xml:lang="ast">Plantía de documentu de Word 2007</comment>
- <comment xml:lang="bg">Шаблон за документи — Word 2007</comment>
- <comment xml:lang="ca">plantilla de document de Word 2007</comment>
- <comment xml:lang="cs">šablona dokumentu Word 2007</comment>
- <comment xml:lang="da">Word 2007-dokumentskabelon</comment>
- <comment xml:lang="de">Word-2007-Dokumentvorlage</comment>
- <comment xml:lang="el">Πρότυπο έγγραφο Word 2007</comment>
- <comment xml:lang="en_GB">Word 2007 document template</comment>
- <comment xml:lang="es">plantilla de documento de Word 2007</comment>
- <comment xml:lang="eu">Word 2007 dokumentuaren txantiloia</comment>
- <comment xml:lang="fi">Word 2007 -asiakirjamalli</comment>
- <comment xml:lang="fr">modèle de document Word 2007</comment>
- <comment xml:lang="ga">teimpléad cháipéis Word 2007</comment>
- <comment xml:lang="gl">Plantilla de documento de Word 2007</comment>
- <comment xml:lang="he">תבנית מסמך של Word 2007</comment>
- <comment xml:lang="hr">Word 2007 predložak dokumenta</comment>
- <comment xml:lang="hu">Word 2007 dokumentumsablon</comment>
- <comment xml:lang="ia">Patrono de documento Word 2007</comment>
- <comment xml:lang="id">Templat dokumen Word 2007</comment>
- <comment xml:lang="it">Modello documento Word 2007</comment>
- <comment xml:lang="ja">Word 2007 文書テンプレート</comment>
- <comment xml:lang="ka">Word 2007-ის დოკუმენტის შაბლონი</comment>
- <comment xml:lang="kk">Word 2007 құжатының үлгісі</comment>
- <comment xml:lang="ko">Word 2007 문서 서식</comment>
- <comment xml:lang="lv">Word 2007 dokumenta veidne</comment>
- <comment xml:lang="nl">Word 2007 document sjabloon</comment>
- <comment xml:lang="oc">modèl de document Word 2007</comment>
- <comment xml:lang="pl">Szablon dokumentu Word 2007</comment>
- <comment xml:lang="pt">modelo de documento Word 2007</comment>
- <comment xml:lang="pt_BR">Modelo de documento do Word 2007</comment>
- <comment xml:lang="ru">Шаблон документа Word 2007</comment>
- <comment xml:lang="sk">Šablóna dokumentu Word 2007</comment>
- <comment xml:lang="sl">Predloga dokumenta Word 2007</comment>
- <comment xml:lang="sr">шаблон документа Ворда 2007</comment>
- <comment xml:lang="sv">Word 2007-dokumentmall</comment>
- <comment xml:lang="tr">Word 2007 belge şablonu</comment>
- <comment xml:lang="uk">шаблон документа Word 2007</comment>
- <comment xml:lang="zh_CN">Word 2007 文档模板</comment>
<comment xml:lang="zh_TW">Word 2007 文件範本</comment>
+ <comment xml:lang="zh_CN">Word 2007 文档模板</comment>
+ <comment xml:lang="uk">шаблон документа Word 2007</comment>
+ <comment xml:lang="tr">Word 2007 belge şablonu</comment>
+ <comment xml:lang="sv">Word 2007-dokumentmall</comment>
+ <comment xml:lang="sr">шаблон документа Ворда 2007</comment>
+ <comment xml:lang="sq">gjedhe dokumentesh Word 2007</comment>
+ <comment xml:lang="sl">Predloga dokumenta Word 2007</comment>
+ <comment xml:lang="si">Word 2007 ලේඛන සැකිල්ල</comment>
+ <comment xml:lang="sk">Šablóna dokumentu Word 2007</comment>
+ <comment xml:lang="ru">Шаблон документа Word 2007</comment>
+ <comment xml:lang="pt_BR">Modelo de documento do Word 2007</comment>
+ <comment xml:lang="pt">modelo de documento Word 2007</comment>
+ <comment xml:lang="pl">Szablon dokumentu Word 2007</comment>
+ <comment xml:lang="oc">modèl de document Word 2007</comment>
+ <comment xml:lang="nl">Word 2007-documentsjabloon</comment>
+ <comment xml:lang="lv">Word 2007 dokumenta veidne</comment>
+ <comment xml:lang="ko">Word 2007 문서 서식</comment>
+ <comment xml:lang="kk">Word 2007 құжатының үлгісі</comment>
+ <comment xml:lang="ka">Word 2007-ის დოკუმენტის შაბლონი</comment>
+ <comment xml:lang="ja">Word 2007 ドキュメントテンプレート</comment>
+ <comment xml:lang="it">Modello documento Word 2007</comment>
+ <comment xml:lang="is">Word sniðmát fyrir textaskjal</comment>
+ <comment xml:lang="id">Templat dokumen Word 2007</comment>
+ <comment xml:lang="ia">Patrono de documento Word 2007</comment>
+ <comment xml:lang="hu">Word 2007 dokumentumsablon</comment>
+ <comment xml:lang="hr">Word 2007 predložak dokumenta</comment>
+ <comment xml:lang="he">תבנית מסמך של Word 2007</comment>
+ <comment xml:lang="gl">Plantilla de documento de Word 2007</comment>
+ <comment xml:lang="ga">teimpléad cháipéis Word 2007</comment>
+ <comment xml:lang="fur">model document Word 2007</comment>
+ <comment xml:lang="fr">modèle de document Word 2007</comment>
+ <comment xml:lang="fi">Word 2007 -asiakirjamalli</comment>
+ <comment xml:lang="eu">Word 2007 dokumentuaren txantiloia</comment>
+ <comment xml:lang="es">plantilla de documento de Word 2007</comment>
+ <comment xml:lang="en_GB">Word 2007 document template</comment>
+ <comment xml:lang="el">Πρότυπο έγγραφο Word 2007</comment>
+ <comment xml:lang="de">Word-2007-Dokumentvorlage</comment>
+ <comment xml:lang="da">Word 2007-dokumentskabelon</comment>
+ <comment xml:lang="cs">šablona dokumentu Word 2007</comment>
+ <comment xml:lang="ca">plantilla de document de Word 2007</comment>
+ <comment xml:lang="bg">Шаблон за документи — Word 2007</comment>
+ <comment xml:lang="be">шаблон дакумента Word 2007</comment>
+ <comment xml:lang="ast">Plantía de documentu de Word 2007</comment>
+ <comment xml:lang="ar">قالب مستند ورد 2007</comment>
+ <comment xml:lang="af">Word 2007-dokumentsjabloon</comment>
<glob pattern="*.dotx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.presentationml.presentation">
<comment>PowerPoint 2007 presentation</comment>
- <comment xml:lang="ar">عرض تقديمي PowerPoint 2007</comment>
- <comment xml:lang="bg">Презентация — PowerPoint 2007</comment>
- <comment xml:lang="ca">presentació de PowerPoint 2007</comment>
- <comment xml:lang="cs">prezentace PowerPoint 2007</comment>
- <comment xml:lang="da">PowerPoint 2007-præsentation</comment>
- <comment xml:lang="de">PowerPoint-2007-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση PowerPoint 2007</comment>
- <comment xml:lang="en_GB">PowerPoint 2007 presentation</comment>
- <comment xml:lang="es">presentación de PowerPoint 2007</comment>
- <comment xml:lang="eu">PowerPoint 2007 aurkezpena</comment>
- <comment xml:lang="fi">PowerPoint 2007 -esitys</comment>
- <comment xml:lang="fo">PowerPoint 2007 framløga</comment>
- <comment xml:lang="fr">présentation PowerPoint 2007</comment>
- <comment xml:lang="ga">láithreoireacht PowerPoint 2007</comment>
- <comment xml:lang="gl">presentación de PowerPoint 2007</comment>
- <comment xml:lang="he">מצגת של PowerPoint 2007</comment>
- <comment xml:lang="hr">PowerPoint 2007 prezentacija</comment>
- <comment xml:lang="hu">PowerPoint 2007 prezentáció</comment>
- <comment xml:lang="ia">Presentation PowerPoint 2007</comment>
- <comment xml:lang="id">Presentasi PowerPoint 2007</comment>
- <comment xml:lang="it">Presentazione standard PowerPoint 2007</comment>
- <comment xml:lang="ja">PowerPoint 2007 プレゼンテーション</comment>
- <comment xml:lang="kk">PowerPoint 2007 презентациясы</comment>
- <comment xml:lang="ko">PowerPoint 2007 프레젠테이션</comment>
- <comment xml:lang="lt">PowerPoint 2007 pateiktis</comment>
- <comment xml:lang="lv">PowerPoint 2007 prezentācija</comment>
- <comment xml:lang="nl">PowerPoint 2007-presentatie</comment>
- <comment xml:lang="oc">presentacion PowerPoint 2007</comment>
- <comment xml:lang="pl">Prezentacja PowerPoint 2007</comment>
- <comment xml:lang="pt">apresentação PowerPoint 2007</comment>
- <comment xml:lang="pt_BR">Apresentação do PowerPoint 2007</comment>
- <comment xml:lang="ro">Prezentare PowerPoint 2007</comment>
- <comment xml:lang="ru">Презентация PowerPoint 2007</comment>
- <comment xml:lang="sk">Prezentácia PowerPoint 2007</comment>
- <comment xml:lang="sl">Predstavitev Microsoft PowerPoint 2007</comment>
- <comment xml:lang="sr">презентација Пауер Поинта 2007</comment>
- <comment xml:lang="sv">PowerPoint 2007-presentation</comment>
- <comment xml:lang="tr">PowerPoint 2007 sunumu</comment>
- <comment xml:lang="uk">презентація PowerPoint 2007</comment>
- <comment xml:lang="vi">Trình diễn PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">PowerPoint 2007 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 簡報</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 演示文稿</comment>
+ <comment xml:lang="vi">Trình diễn PowerPoint 2007</comment>
+ <comment xml:lang="uk">презентація PowerPoint 2007</comment>
+ <comment xml:lang="tr">PowerPoint 2007 sunumu</comment>
+ <comment xml:lang="sv">PowerPoint 2007-presentation</comment>
+ <comment xml:lang="sr">презентација Пауер Поинта 2007</comment>
+ <comment xml:lang="sq">paraqitje PowerPoint 2007</comment>
+ <comment xml:lang="sl">Predstavitev Microsoft PowerPoint 2007</comment>
+ <comment xml:lang="si">PowerPoint 2007 ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia PowerPoint 2007</comment>
+ <comment xml:lang="ru">Презентация PowerPoint 2007</comment>
+ <comment xml:lang="ro">Prezentare PowerPoint 2007</comment>
+ <comment xml:lang="pt_BR">Apresentação do PowerPoint 2007</comment>
+ <comment xml:lang="pt">apresentação PowerPoint 2007</comment>
+ <comment xml:lang="pl">Prezentacja PowerPoint 2007</comment>
+ <comment xml:lang="oc">presentacion PowerPoint 2007</comment>
+ <comment xml:lang="nl">PowerPoint 2007-presentatie</comment>
+ <comment xml:lang="lv">PowerPoint 2007 prezentācija</comment>
+ <comment xml:lang="lt">PowerPoint 2007 pateiktis</comment>
+ <comment xml:lang="ko">PowerPoint 2007 프레젠테이션</comment>
+ <comment xml:lang="kk">PowerPoint 2007 презентациясы</comment>
+ <comment xml:lang="ja">PowerPoint 2007 プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione standard PowerPoint 2007</comment>
+ <comment xml:lang="is">PowerPoint 2007 kynning</comment>
+ <comment xml:lang="id">Presentasi PowerPoint 2007</comment>
+ <comment xml:lang="ia">Presentation PowerPoint 2007</comment>
+ <comment xml:lang="hu">PowerPoint 2007 prezentáció</comment>
+ <comment xml:lang="hr">PowerPoint 2007 prezentacija</comment>
+ <comment xml:lang="he">מצגת של PowerPoint 2007</comment>
+ <comment xml:lang="gl">presentación de PowerPoint 2007</comment>
+ <comment xml:lang="ga">láithreoireacht PowerPoint 2007</comment>
+ <comment xml:lang="fur">presentazion PowerPoint 2007</comment>
+ <comment xml:lang="fr">présentation PowerPoint 2007</comment>
+ <comment xml:lang="fo">PowerPoint 2007 framløga</comment>
+ <comment xml:lang="fi">PowerPoint 2007 -esitys</comment>
+ <comment xml:lang="eu">PowerPoint 2007 aurkezpena</comment>
+ <comment xml:lang="es">presentación de PowerPoint 2007</comment>
+ <comment xml:lang="en_GB">PowerPoint 2007 presentation</comment>
+ <comment xml:lang="el">Παρουσίαση PowerPoint 2007</comment>
+ <comment xml:lang="de">PowerPoint-2007-Präsentation</comment>
+ <comment xml:lang="da">PowerPoint 2007-præsentation</comment>
+ <comment xml:lang="cs">prezentace PowerPoint 2007</comment>
+ <comment xml:lang="ca">presentació de PowerPoint 2007</comment>
+ <comment xml:lang="bg">Презентация — PowerPoint 2007</comment>
+ <comment xml:lang="be">прэзентацыя PowerPoint 2007</comment>
+ <comment xml:lang="ar">عرض تقديمي بوربوينت 2007</comment>
+ <comment xml:lang="af">PowerPoint 2007-voorlegging</comment>
<glob pattern="*.pptx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slide">
<comment>PowerPoint 2007 slide</comment>
- <comment xml:lang="bg">Кадър — PoerPoint 2007</comment>
- <comment xml:lang="ca">dispositiva de PowerPoint 2007</comment>
- <comment xml:lang="cs">snímek PowerPoint 2007</comment>
- <comment xml:lang="da">PowerPoint 2007-slide</comment>
- <comment xml:lang="de">PowerPoint 2007-Folie</comment>
- <comment xml:lang="el">Διαφάνεια PowerPoint 2007</comment>
- <comment xml:lang="en_GB">PowerPoint 2007 slide</comment>
- <comment xml:lang="es">diapositiva de PowerPoint 2007</comment>
- <comment xml:lang="eu">PowerPoint 2007 diapositiba</comment>
- <comment xml:lang="fi">PowerPoint 2007 -dia</comment>
- <comment xml:lang="fr">diapositive PowerPoint 2007</comment>
- <comment xml:lang="ga">sleamhnán PowerPoint 2007</comment>
- <comment xml:lang="gl">Diaporama de PowerPoint 2007</comment>
- <comment xml:lang="he">שקופית של PowerPoint 2007</comment>
- <comment xml:lang="hr">PowerPoint 2007 slikovna prezentacija</comment>
- <comment xml:lang="hu">PowerPoint 2007 dia</comment>
- <comment xml:lang="ia">Diapositiva PowerPoint 2007</comment>
- <comment xml:lang="id">Slide PowerPoint 2007</comment>
- <comment xml:lang="it">Diapositiva PowerPoint 2007</comment>
- <comment xml:lang="ja">PowerPoint 2007 スライド</comment>
- <comment xml:lang="ka">PowerPoint 2007-ის სლაიდი</comment>
- <comment xml:lang="kk">PowerPoint 2007 слайды</comment>
- <comment xml:lang="ko">PowerPoint 2007 슬라이드</comment>
- <comment xml:lang="lv">PowerPoint 2007 slaids</comment>
- <comment xml:lang="nl">PowerPoint 2007 dia</comment>
- <comment xml:lang="oc">diapositive PowerPoint 2007</comment>
- <comment xml:lang="pl">Slajd PowerPoint 2007</comment>
- <comment xml:lang="pt">diapositivo PowerPoint 2007</comment>
- <comment xml:lang="pt_BR">Slide do PowerPoint 2007</comment>
- <comment xml:lang="ru">Слайд PowerPoint 2007</comment>
- <comment xml:lang="sk">Snímka PowerPoint 2007</comment>
- <comment xml:lang="sl">Prosojnica PowerPoint 2007</comment>
- <comment xml:lang="sr">слајд Пауер Поинта 2007</comment>
- <comment xml:lang="sv">PowerPoint 2007-bildspel</comment>
- <comment xml:lang="tr">PowerPoint 2007 slaytı</comment>
- <comment xml:lang="uk">слайд PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">PowerPoint 2007 幻灯片</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 投影片</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 幻灯片</comment>
+ <comment xml:lang="uk">слайд PowerPoint 2007</comment>
+ <comment xml:lang="tr">PowerPoint 2007 slaytı</comment>
+ <comment xml:lang="sv">PowerPoint 2007-bildspel</comment>
+ <comment xml:lang="sr">слајд Пауер Поинта 2007</comment>
+ <comment xml:lang="sq">diapozitiv PowerPoint 2007</comment>
+ <comment xml:lang="sl">Prosojnica PowerPoint 2007</comment>
+ <comment xml:lang="si">PowerPoint 2007 ස්ලයිඩය</comment>
+ <comment xml:lang="sk">Snímka PowerPoint 2007</comment>
+ <comment xml:lang="ru">Слайд PowerPoint 2007</comment>
+ <comment xml:lang="pt_BR">Slide do PowerPoint 2007</comment>
+ <comment xml:lang="pt">diapositivo PowerPoint 2007</comment>
+ <comment xml:lang="pl">Slajd PowerPoint 2007</comment>
+ <comment xml:lang="oc">diapositive PowerPoint 2007</comment>
+ <comment xml:lang="nl">PowerPoint 2007-dia</comment>
+ <comment xml:lang="lv">PowerPoint 2007 slaids</comment>
+ <comment xml:lang="ko">PowerPoint 2007 슬라이드</comment>
+ <comment xml:lang="kk">PowerPoint 2007 слайды</comment>
+ <comment xml:lang="ka">PowerPoint 2007-ის სლაიდი</comment>
+ <comment xml:lang="ja">PowerPoint 2007 スライド</comment>
+ <comment xml:lang="it">Diapositiva PowerPoint 2007</comment>
+ <comment xml:lang="is">PowerPoint 2007 skyggna</comment>
+ <comment xml:lang="id">Slide PowerPoint 2007</comment>
+ <comment xml:lang="ia">Diapositiva PowerPoint 2007</comment>
+ <comment xml:lang="hu">PowerPoint 2007 dia</comment>
+ <comment xml:lang="hr">PowerPoint 2007 slikovna prezentacija</comment>
+ <comment xml:lang="he">שקופית של PowerPoint 2007</comment>
+ <comment xml:lang="gl">Diaporama de PowerPoint 2007</comment>
+ <comment xml:lang="ga">sleamhnán PowerPoint 2007</comment>
+ <comment xml:lang="fur">diapositive PowerPoint 2007</comment>
+ <comment xml:lang="fr">diapositive PowerPoint 2007</comment>
+ <comment xml:lang="fi">PowerPoint 2007 -dia</comment>
+ <comment xml:lang="eu">PowerPoint 2007 diapositiba</comment>
+ <comment xml:lang="es">diapositiva de PowerPoint 2007</comment>
+ <comment xml:lang="en_GB">PowerPoint 2007 slide</comment>
+ <comment xml:lang="el">Διαφάνεια PowerPoint 2007</comment>
+ <comment xml:lang="de">PowerPoint-2007-Folie</comment>
+ <comment xml:lang="da">PowerPoint 2007-slide</comment>
+ <comment xml:lang="cs">snímek PowerPoint 2007</comment>
+ <comment xml:lang="ca">dispositiva de PowerPoint 2007</comment>
+ <comment xml:lang="bg">Кадър — PoerPoint 2007</comment>
+ <comment xml:lang="be">слайд PowerPoint 2007</comment>
+ <comment xml:lang="ar">شريحة بوربوينت 2007</comment>
+ <comment xml:lang="af">PowerPoint 2007-skyfie</comment>
<glob pattern="*.sldx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
<comment>PowerPoint 2007 show</comment>
- <comment xml:lang="ar">عرض PowerPoint 2007</comment>
- <comment xml:lang="bg">Презентация-шоу — PowerPoint 2007</comment>
- <comment xml:lang="ca">exposició de PowerPoint 2007</comment>
- <comment xml:lang="cs">prezentace PowerPoint 2007</comment>
- <comment xml:lang="da">PowerPoint 2007-dias</comment>
- <comment xml:lang="de">PowerPoint-2007-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση PowerPoint 2007</comment>
- <comment xml:lang="en_GB">PowerPoint 2007 show</comment>
- <comment xml:lang="es">presentación autoejecutable de PowerPoint 2007</comment>
- <comment xml:lang="eu">PowerPoint 2007 ikuskizuna</comment>
- <comment xml:lang="fi">PowerPoint 2007 -diaesitys</comment>
- <comment xml:lang="fo">PowerPoint 2007 framsýning</comment>
- <comment xml:lang="fr">diaporama PowerPoint 2007</comment>
- <comment xml:lang="ga">taispeántas PowerPoint 2007</comment>
- <comment xml:lang="gl">Exposición de PowerPoint 2007</comment>
- <comment xml:lang="he">תצוגה של PowerPoint 2007</comment>
- <comment xml:lang="hr">PowerPoint 2007 prezentacija</comment>
- <comment xml:lang="hu">PowerPoint 2007 bemutató</comment>
- <comment xml:lang="ia">Projection de diapositivas PowerPoint 2007</comment>
- <comment xml:lang="id">Presentasi PowerPoint 2007</comment>
- <comment xml:lang="it">Solo presentazione PowerPoint 2007</comment>
- <comment xml:lang="ja">PowerPoint 2007 プレゼンテーション</comment>
- <comment xml:lang="kk">PowerPoint 2007 көрсетілімі</comment>
- <comment xml:lang="ko">PowerPoint 2007 쇼</comment>
- <comment xml:lang="lt">PowerPoint 2007 pateiktis</comment>
- <comment xml:lang="lv">PowerPoint 2007 slīdrāde</comment>
- <comment xml:lang="nl">PowerPoint 2007 show</comment>
- <comment xml:lang="oc">diaporama PowerPoint 2007</comment>
- <comment xml:lang="pl">Pokaz PowerPoint 2007</comment>
- <comment xml:lang="pt">espetáculo PowerPoint 2007</comment>
- <comment xml:lang="pt_BR">Apresentação do PowerPoint 2007</comment>
- <comment xml:lang="ro">Prezentare PowerPoint 2007</comment>
- <comment xml:lang="ru">Презентация PowerPoint 2007</comment>
- <comment xml:lang="sk">Ukážka PowerPoint 2007</comment>
- <comment xml:lang="sl">Zagonska predstavitev PowerPoint 2007</comment>
- <comment xml:lang="sr">приказ Пауер Поинта 2007</comment>
- <comment xml:lang="sv">PowerPoint 2007-visning</comment>
- <comment xml:lang="tr">PowerPoint 2007 gösterisi</comment>
- <comment xml:lang="uk">показ слайдів PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">PowerPoint 2007 放映</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 展示</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 放映</comment>
+ <comment xml:lang="uk">показ слайдів PowerPoint 2007</comment>
+ <comment xml:lang="tr">PowerPoint 2007 gösterisi</comment>
+ <comment xml:lang="sv">PowerPoint 2007-visning</comment>
+ <comment xml:lang="sr">приказ Пауер Поинта 2007</comment>
+ <comment xml:lang="sl">Zagonska predstavitev PowerPoint 2007</comment>
+ <comment xml:lang="si">PowerPoint 2007 ප්රදර්ශනය</comment>
+ <comment xml:lang="sk">Ukážka PowerPoint 2007</comment>
+ <comment xml:lang="ru">Презентация PowerPoint 2007</comment>
+ <comment xml:lang="ro">Prezentare PowerPoint 2007</comment>
+ <comment xml:lang="pt_BR">Apresentação do PowerPoint 2007</comment>
+ <comment xml:lang="pt">espetáculo PowerPoint 2007</comment>
+ <comment xml:lang="pl">Pokaz PowerPoint 2007</comment>
+ <comment xml:lang="oc">diaporama PowerPoint 2007</comment>
+ <comment xml:lang="nl">PowerPoint 2007-show</comment>
+ <comment xml:lang="lv">PowerPoint 2007 slīdrāde</comment>
+ <comment xml:lang="lt">PowerPoint 2007 pateiktis</comment>
+ <comment xml:lang="ko">PowerPoint 2007 쇼</comment>
+ <comment xml:lang="kk">PowerPoint 2007 көрсетілімі</comment>
+ <comment xml:lang="ja">PowerPoint 2007 プレゼンテーション</comment>
+ <comment xml:lang="it">Solo presentazione PowerPoint 2007</comment>
+ <comment xml:lang="is">PowerPoint 2007 glærukynning</comment>
+ <comment xml:lang="id">Presentasi PowerPoint 2007</comment>
+ <comment xml:lang="ia">Projection de diapositivas PowerPoint 2007</comment>
+ <comment xml:lang="hu">PowerPoint 2007 bemutató</comment>
+ <comment xml:lang="hr">PowerPoint 2007 prezentacija</comment>
+ <comment xml:lang="he">תצוגה של PowerPoint 2007</comment>
+ <comment xml:lang="gl">Exposición de PowerPoint 2007</comment>
+ <comment xml:lang="ga">taispeántas PowerPoint 2007</comment>
+ <comment xml:lang="fur">esecuzion presentazion PowerPoint 2007</comment>
+ <comment xml:lang="fr">diaporama PowerPoint 2007</comment>
+ <comment xml:lang="fo">PowerPoint 2007 framsýning</comment>
+ <comment xml:lang="fi">PowerPoint 2007 -diaesitys</comment>
+ <comment xml:lang="eu">PowerPoint 2007 ikuskizuna</comment>
+ <comment xml:lang="es">presentación autoejecutable de PowerPoint 2007</comment>
+ <comment xml:lang="en_GB">PowerPoint 2007 show</comment>
+ <comment xml:lang="el">Παρουσίαση PowerPoint 2007</comment>
+ <comment xml:lang="de">PowerPoint-2007-Präsentation</comment>
+ <comment xml:lang="da">PowerPoint 2007-dias</comment>
+ <comment xml:lang="cs">prezentace PowerPoint 2007</comment>
+ <comment xml:lang="ca">exposició de PowerPoint 2007</comment>
+ <comment xml:lang="bg">Презентация-шоу — PowerPoint 2007</comment>
+ <comment xml:lang="be">паказ слайдаў PowerPoint 2007</comment>
+ <comment xml:lang="ar">عرض بوربوينت 2007</comment>
+ <comment xml:lang="af">PowerPoint 2007-vertoning</comment>
<glob pattern="*.ppsx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.presentationml.template">
<comment>PowerPoint 2007 presentation template</comment>
- <comment xml:lang="bg">Шаблон за презентации — PowerPoint 2007</comment>
- <comment xml:lang="ca">plantilla de presentació de PowerPoint 2007</comment>
- <comment xml:lang="cs">šablona prezentace PowerPoint 2007</comment>
- <comment xml:lang="da">PowerPoint 2007-præsentationsskabelon</comment>
- <comment xml:lang="de">PowerPoint 2007-Präsentationsvorlage</comment>
- <comment xml:lang="el">Πρότυπο παρουσίασης PowerPoint 2007</comment>
- <comment xml:lang="en_GB">PowerPoint 2007 presentation template</comment>
- <comment xml:lang="es">plantilla de presentación de PowerPoint 2007</comment>
- <comment xml:lang="eu">PowerPoint 2007 aurkezpen txantiloia</comment>
- <comment xml:lang="fi">PowerPoint 2007 -esitysmalli</comment>
- <comment xml:lang="fr">modèle de présentation PowerPoint 2007</comment>
- <comment xml:lang="ga">teimpléad láithreoireachta PowerPoint 2007</comment>
- <comment xml:lang="gl">modelo de presentación de PowerPoint 2007</comment>
- <comment xml:lang="he">תבנית למצגת של PowerPoint 2007</comment>
- <comment xml:lang="hr">PowerPoint 2007 predložak prezentacije</comment>
- <comment xml:lang="hu">PowerPoint 2007 bemutatósablon</comment>
- <comment xml:lang="ia">Patrono de presentation PowerPoint 2007</comment>
- <comment xml:lang="id">Templat presentasi PowerPoint 2007</comment>
- <comment xml:lang="it">Modello presentazione PowerPoint 2007</comment>
- <comment xml:lang="ja">PowerPoint 2007 プレゼンテーションテンプレート</comment>
- <comment xml:lang="ka">PowerPoint 2007-ის პრეზენტაციის შაბლონი</comment>
- <comment xml:lang="kk">PowerPoint 2007 презентация шаблоны</comment>
- <comment xml:lang="ko">PowerPoint 2007 프레젠테이션 서식</comment>
- <comment xml:lang="lv">PowerPoint 2007 prezentācijas veidne</comment>
- <comment xml:lang="nl">PowerPoint 2007 presentation sjabloon</comment>
- <comment xml:lang="oc">modèl de presentacion PowerPoint 2007</comment>
- <comment xml:lang="pl">Szablon prezentacji PowerPoint 2007</comment>
- <comment xml:lang="pt">modelo de apresentação PowerPoint 2007</comment>
- <comment xml:lang="pt_BR">Modelo de apresentação do PowerPoint 2007</comment>
- <comment xml:lang="ru">Шаблон презентации PowerPoint 2007</comment>
- <comment xml:lang="sk">Šablóna prezentácie PowerPoint 2007</comment>
- <comment xml:lang="sl">Predloga predstavitve PowerPoint 2007</comment>
- <comment xml:lang="sr">шаблон презентације Пауер Поинта 2007</comment>
- <comment xml:lang="sv">PowerPoint 2007-presentationsmall</comment>
- <comment xml:lang="tr">PowerPoint 2007 sunum şablonu</comment>
- <comment xml:lang="uk">шаблон презентації PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">PowerPoint 2007 演示文稿模板</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 簡報範本</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 演示文稿模板</comment>
+ <comment xml:lang="uk">шаблон презентації PowerPoint 2007</comment>
+ <comment xml:lang="tr">PowerPoint 2007 sunum şablonu</comment>
+ <comment xml:lang="sv">PowerPoint 2007-presentationsmall</comment>
+ <comment xml:lang="sr">шаблон презентације Пауер Поинта 2007</comment>
+ <comment xml:lang="sq">gjedhe paraqitjesh PowerPoint 2007</comment>
+ <comment xml:lang="sl">Predloga predstavitve PowerPoint 2007</comment>
+ <comment xml:lang="si">PowerPoint 2007 ඉදිරිපත් කිරීමේ අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna prezentácie PowerPoint 2007</comment>
+ <comment xml:lang="ru">Шаблон презентации PowerPoint 2007</comment>
+ <comment xml:lang="pt_BR">Modelo de apresentação do PowerPoint 2007</comment>
+ <comment xml:lang="pt">modelo de apresentação PowerPoint 2007</comment>
+ <comment xml:lang="pl">Szablon prezentacji PowerPoint 2007</comment>
+ <comment xml:lang="oc">modèl de presentacion PowerPoint 2007</comment>
+ <comment xml:lang="nl">PowerPoint 2007-presentatiesjabloon</comment>
+ <comment xml:lang="lv">PowerPoint 2007 prezentācijas veidne</comment>
+ <comment xml:lang="ko">PowerPoint 2007 프레젠테이션 서식</comment>
+ <comment xml:lang="kk">PowerPoint 2007 презентация шаблоны</comment>
+ <comment xml:lang="ka">PowerPoint 2007-ის პრეზენტაციის შაბლონი</comment>
+ <comment xml:lang="ja">PowerPoint 2007 プレゼンテーションテンプレート</comment>
+ <comment xml:lang="it">Modello presentazione PowerPoint 2007</comment>
+ <comment xml:lang="is">PowerPoint 2007 sniðmát fyrir glærukynningu</comment>
+ <comment xml:lang="id">Templat presentasi PowerPoint 2007</comment>
+ <comment xml:lang="ia">Patrono de presentation PowerPoint 2007</comment>
+ <comment xml:lang="hu">PowerPoint 2007 bemutatósablon</comment>
+ <comment xml:lang="hr">PowerPoint 2007 predložak prezentacije</comment>
+ <comment xml:lang="he">תבנית למצגת של PowerPoint 2007</comment>
+ <comment xml:lang="gl">modelo de presentación de PowerPoint 2007</comment>
+ <comment xml:lang="ga">teimpléad láithreoireachta PowerPoint 2007</comment>
+ <comment xml:lang="fur">model presentazion PowerPoint 2007</comment>
+ <comment xml:lang="fr">modèle de présentation PowerPoint 2007</comment>
+ <comment xml:lang="fi">PowerPoint 2007 -esitysmalli</comment>
+ <comment xml:lang="eu">PowerPoint 2007 aurkezpen txantiloia</comment>
+ <comment xml:lang="es">plantilla de presentación de PowerPoint 2007</comment>
+ <comment xml:lang="en_GB">PowerPoint 2007 presentation template</comment>
+ <comment xml:lang="el">Πρότυπο παρουσίασης PowerPoint 2007</comment>
+ <comment xml:lang="de">PowerPoint-2007-Präsentationsvorlage</comment>
+ <comment xml:lang="da">PowerPoint 2007-præsentationsskabelon</comment>
+ <comment xml:lang="cs">šablona prezentace PowerPoint 2007</comment>
+ <comment xml:lang="ca">plantilla de presentació de PowerPoint 2007</comment>
+ <comment xml:lang="bg">Шаблон за презентации — PowerPoint 2007</comment>
+ <comment xml:lang="be">шаблон прэзентацыі PowerPoint 2007</comment>
+ <comment xml:lang="ar">قالب عرض بوربوينت 2007</comment>
+ <comment xml:lang="af">PowerPoint 2007-voorleggingsjabloon</comment>
<glob pattern="*.potx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<comment>Excel 2007 spreadsheet</comment>
- <comment xml:lang="ar">جدول Excel 2007</comment>
- <comment xml:lang="bg">Таблица — Excel 2007</comment>
- <comment xml:lang="ca">full de càlcul d'Excel 2007</comment>
- <comment xml:lang="cs">sešit Excel 2007</comment>
- <comment xml:lang="da">Excel 2007-regneark</comment>
- <comment xml:lang="de">Excel-2007-Tabelle</comment>
- <comment xml:lang="el">Λογιστικό φύλλο Excel 2007</comment>
- <comment xml:lang="en_GB">Excel 2007 spreadsheet</comment>
- <comment xml:lang="es">hoja de cálculo de Excel 2007</comment>
- <comment xml:lang="eu">Excel 2007 kalkulu-orria</comment>
- <comment xml:lang="fi">Excel 2007 -taulukko</comment>
- <comment xml:lang="fo">Excel 2007 rokniark</comment>
- <comment xml:lang="fr">feuille de calcul Excel 2007</comment>
- <comment xml:lang="ga">scarbhileog Excel 2007</comment>
- <comment xml:lang="gl">folla de cálculo de Excel 2007</comment>
- <comment xml:lang="he">גליון נתונים של Excel 2007</comment>
- <comment xml:lang="hr">Excel 2007 proračunska tablica</comment>
- <comment xml:lang="hu">Excel 2007 táblázat</comment>
- <comment xml:lang="ia">Folio de calculo Excel 2007</comment>
- <comment xml:lang="id">Lembar sebar Excel 2007</comment>
- <comment xml:lang="it">Foglio di calcolo Excel 2007</comment>
- <comment xml:lang="ja">Excel 2007 スプレッドシート</comment>
- <comment xml:lang="ka">Excel 2007-ის ცხრილი</comment>
- <comment xml:lang="kk">Excel 2007 электрондық кестесі</comment>
- <comment xml:lang="ko">Excel 2007 스프레드시트</comment>
- <comment xml:lang="lt">Excel 2007 skaičialentė</comment>
- <comment xml:lang="lv">Excel 2007 izklājlapa</comment>
- <comment xml:lang="nl">Excel 2007-rekenblad</comment>
- <comment xml:lang="oc">fuèlh de calcul Excel 2007</comment>
- <comment xml:lang="pl">Arkusz Excel 2007</comment>
- <comment xml:lang="pt">folha de cálculo Excel 2007</comment>
- <comment xml:lang="pt_BR">Planilha do Excel 2007</comment>
- <comment xml:lang="ro">Foaie de calcul Excel 2007</comment>
- <comment xml:lang="ru">Электронная таблица Excel 2007</comment>
- <comment xml:lang="sk">Zošit Excel 2007</comment>
- <comment xml:lang="sl">Razpredelnica Microsoft Excel 2007</comment>
- <comment xml:lang="sr">табела Ексела 2007</comment>
- <comment xml:lang="sv">Excel 2007-kalkylblad</comment>
- <comment xml:lang="tr">Excel 2007 çalışma sayfası</comment>
- <comment xml:lang="uk">ел. таблиця Excel 2007</comment>
- <comment xml:lang="vi">Bảng tính Excel 2007</comment>
- <comment xml:lang="zh_CN">Excel 2007 电子表格</comment>
<comment xml:lang="zh_TW">Excel 2007 試算表</comment>
+ <comment xml:lang="zh_CN">Excel 2007 电子表格</comment>
+ <comment xml:lang="vi">Bảng tính Excel 2007</comment>
+ <comment xml:lang="uk">електронна таблиця Excel 2007</comment>
+ <comment xml:lang="tr">Excel 2007 hesap çizelgesi sayfası</comment>
+ <comment xml:lang="sv">Excel 2007-kalkylblad</comment>
+ <comment xml:lang="sr">табела Ексела 2007</comment>
+ <comment xml:lang="sq">fletëllogaritje Excel 2007</comment>
+ <comment xml:lang="sl">Razpredelnica Microsoft Excel 2007</comment>
+ <comment xml:lang="si">Excel 2007 පැතුරුම්පත</comment>
+ <comment xml:lang="sk">Zošit Excel 2007</comment>
+ <comment xml:lang="ru">Электронная таблица Excel 2007</comment>
+ <comment xml:lang="ro">Foaie de calcul Excel 2007</comment>
+ <comment xml:lang="pt_BR">Planilha do Excel 2007</comment>
+ <comment xml:lang="pt">folha de cálculo Excel 2007</comment>
+ <comment xml:lang="pl">Arkusz Excel 2007</comment>
+ <comment xml:lang="oc">fuèlh de calcul Excel 2007</comment>
+ <comment xml:lang="nl">Excel 2007-rekenblad</comment>
+ <comment xml:lang="lv">Excel 2007 izklājlapa</comment>
+ <comment xml:lang="lt">Excel 2007 skaičialentė</comment>
+ <comment xml:lang="ko">Excel 2007 스프레드시트</comment>
+ <comment xml:lang="kk">Excel 2007 электрондық кестесі</comment>
+ <comment xml:lang="ka">Excel 2007-ის ცხრილი</comment>
+ <comment xml:lang="ja">Excel 2007 スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Excel 2007</comment>
+ <comment xml:lang="is">Excel 2007 töflureikniskjal</comment>
+ <comment xml:lang="id">Lembar sebar Excel 2007</comment>
+ <comment xml:lang="ia">Folio de calculo Excel 2007</comment>
+ <comment xml:lang="hu">Excel 2007 táblázat</comment>
+ <comment xml:lang="hr">Excel 2007 proračunska tablica</comment>
+ <comment xml:lang="he">גיליון נתונים של Excel 2007</comment>
+ <comment xml:lang="gl">folla de cálculo de Excel 2007</comment>
+ <comment xml:lang="ga">scarbhileog Excel 2007</comment>
+ <comment xml:lang="fur">sfuei di calcul Excel 2007</comment>
+ <comment xml:lang="fr">feuille de calcul Excel 2007</comment>
+ <comment xml:lang="fo">Excel 2007 rokniark</comment>
+ <comment xml:lang="fi">Excel 2007 -taulukko</comment>
+ <comment xml:lang="eu">Excel 2007 kalkulu-orria</comment>
+ <comment xml:lang="es">hoja de cálculo de Excel 2007</comment>
+ <comment xml:lang="en_GB">Excel 2007 spreadsheet</comment>
+ <comment xml:lang="el">Λογιστικό φύλλο Excel 2007</comment>
+ <comment xml:lang="de">Excel-2007-Tabelle</comment>
+ <comment xml:lang="da">Excel 2007-regneark</comment>
+ <comment xml:lang="cs">sešit Excel 2007</comment>
+ <comment xml:lang="ca">full de càlcul d'Excel 2007</comment>
+ <comment xml:lang="bg">Таблица — Excel 2007</comment>
+ <comment xml:lang="be">электронная табліца Excel 2007</comment>
+ <comment xml:lang="ar">جدول اكسل 2007</comment>
+ <comment xml:lang="af">Excel 2007-sigblad</comment>
<glob pattern="*.xlsx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.template">
<comment>Excel 2007 spreadsheet template</comment>
- <comment xml:lang="bg">Шаблон за таблици — Excel 2007</comment>
- <comment xml:lang="ca">plantilla de full de càlcul d'Excel 2007</comment>
- <comment xml:lang="cs">šablona sešitu Excel 2007</comment>
- <comment xml:lang="da">Excel 2007-regnearksskabelon</comment>
- <comment xml:lang="de">Excel 2007-Tabellenvorlage</comment>
- <comment xml:lang="el">Πρότυπο λογιστικού φύλλου Excel 2007</comment>
- <comment xml:lang="en_GB">Excel 2007 spreadsheet template</comment>
- <comment xml:lang="es">plantilla de hoja de cálculo de Excel 2007</comment>
- <comment xml:lang="eu">Excel 2007 kalkulu-orri txantiloia</comment>
- <comment xml:lang="fi">Excel 2007 -taulukkomalli</comment>
- <comment xml:lang="fr">modèle de feuille de calcul Excel 2007</comment>
- <comment xml:lang="ga">teimpléad scarbhileoige Excel 2007</comment>
- <comment xml:lang="gl">modelo de folla de cálculo Excel 2007</comment>
- <comment xml:lang="he">תבנית של גיליון נתונים של Excel 2007</comment>
- <comment xml:lang="hr">Excel 2007 predložak proračunske tablice</comment>
- <comment xml:lang="hu">Excel 2007 táblázatsablon</comment>
- <comment xml:lang="ia">Patrono de folio de calculo Excel 2007</comment>
- <comment xml:lang="id">Templat lembar kerja Excel 2007</comment>
- <comment xml:lang="it">Modello foglio di calcolo Excel 2007</comment>
- <comment xml:lang="ja">Excel 2007 スプレッドシートテンプレート</comment>
- <comment xml:lang="ka">Excel 2007-ის ცხრილის შაბლონი</comment>
- <comment xml:lang="kk">Excel 2007 кесте шаблоны</comment>
- <comment xml:lang="ko">Excel 2007 스프레드시트 서식</comment>
- <comment xml:lang="lv">Excel 2007 izklājlapas veidne</comment>
- <comment xml:lang="nl">Excel 2007 spreadsheet sjabloon</comment>
- <comment xml:lang="oc">modèl de fuèlh de calcul Excel 2007</comment>
- <comment xml:lang="pl">Szablon arkusza Excel 2007</comment>
- <comment xml:lang="pt">modelo de folha de cálculo Excel 2007</comment>
- <comment xml:lang="pt_BR">Modelo de planilha do Excel 2007</comment>
- <comment xml:lang="ru">Шаблон электронной таблицы Excel 2007</comment>
- <comment xml:lang="sk">Šablóna zošitu Excel 2007</comment>
- <comment xml:lang="sl">Predloga razpredelnice Excel 2007</comment>
- <comment xml:lang="sr">шаблон табеле Ексела 2007</comment>
- <comment xml:lang="sv">Excel 2007-kalkylarksmall</comment>
- <comment xml:lang="tr">Excel 2007 çalışma sayfası şablonu</comment>
- <comment xml:lang="uk">шаблон електронної таблиці Excel 2007</comment>
- <comment xml:lang="zh_CN">Excel 2007 电子表格模板</comment>
<comment xml:lang="zh_TW">Excel 2007 試算表範本</comment>
+ <comment xml:lang="zh_CN">Excel 2007 电子表格模板</comment>
+ <comment xml:lang="uk">шаблон електронної таблиці Excel 2007</comment>
+ <comment xml:lang="tr">Excel 2007 hesap çizelgesi şablonu</comment>
+ <comment xml:lang="sv">Excel 2007-kalkylarksmall</comment>
+ <comment xml:lang="sr">шаблон табеле Ексела 2007</comment>
+ <comment xml:lang="sq">gjedhe fletëllogaritjesh Excel 2007</comment>
+ <comment xml:lang="sl">Predloga razpredelnice Excel 2007</comment>
+ <comment xml:lang="si">Excel 2007 පැතුරුම්පත් අච්චුව</comment>
+ <comment xml:lang="sk">Šablóna zošitu Excel 2007</comment>
+ <comment xml:lang="ru">Шаблон электронной таблицы Excel 2007</comment>
+ <comment xml:lang="pt_BR">Modelo de planilha do Excel 2007</comment>
+ <comment xml:lang="pt">modelo de folha de cálculo Excel 2007</comment>
+ <comment xml:lang="pl">Szablon arkusza Excel 2007</comment>
+ <comment xml:lang="oc">modèl de fuèlh de calcul Excel 2007</comment>
+ <comment xml:lang="nl">Excel 2007 spreadsheet sjabloon</comment>
+ <comment xml:lang="lv">Excel 2007 izklājlapas veidne</comment>
+ <comment xml:lang="ko">Excel 2007 스프레드시트 서식</comment>
+ <comment xml:lang="kk">Excel 2007 кесте шаблоны</comment>
+ <comment xml:lang="ka">Excel 2007-ის ცხრილის შაბლონი</comment>
+ <comment xml:lang="ja">Excel 2007 スプレッドシートテンプレート</comment>
+ <comment xml:lang="it">Modello foglio di calcolo Excel 2007</comment>
+ <comment xml:lang="is">Excel 2007 töflureiknisniðmát</comment>
+ <comment xml:lang="id">Templat lembar kerja Excel 2007</comment>
+ <comment xml:lang="ia">Patrono de folio de calculo Excel 2007</comment>
+ <comment xml:lang="hu">Excel 2007 táblázatsablon</comment>
+ <comment xml:lang="hr">Excel 2007 predložak proračunske tablice</comment>
+ <comment xml:lang="he">תבנית של גיליון נתונים של Excel 2007</comment>
+ <comment xml:lang="gl">modelo de folla de cálculo Excel 2007</comment>
+ <comment xml:lang="ga">teimpléad scarbhileoige Excel 2007</comment>
+ <comment xml:lang="fur">model sfuei di calcul Excel 2007</comment>
+ <comment xml:lang="fr">modèle de feuille de calcul Excel 2007</comment>
+ <comment xml:lang="fi">Excel 2007 -taulukkomalli</comment>
+ <comment xml:lang="eu">Excel 2007 kalkulu-orri txantiloia</comment>
+ <comment xml:lang="es">plantilla de hoja de cálculo de Excel 2007</comment>
+ <comment xml:lang="en_GB">Excel 2007 spreadsheet template</comment>
+ <comment xml:lang="el">Πρότυπο λογιστικού φύλλου Excel 2007</comment>
+ <comment xml:lang="de">Excel-2007-Tabellenvorlage</comment>
+ <comment xml:lang="da">Excel 2007-regnearksskabelon</comment>
+ <comment xml:lang="cs">šablona sešitu Excel 2007</comment>
+ <comment xml:lang="ca">plantilla de full de càlcul d'Excel 2007</comment>
+ <comment xml:lang="bg">Шаблон за таблици — Excel 2007</comment>
+ <comment xml:lang="be">шаблон электроннай табліцы Excel 2007</comment>
+ <comment xml:lang="ar">قالب جدول اكسل 2007</comment>
+ <comment xml:lang="af">Excel 2007-sigbladsjabloon</comment>
<glob pattern="*.xltx"/>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
</mime-type>
+ <mime-type type="application/vnd.ms-officetheme">
+ <comment>Microsoft Office 2007 theme</comment>
+ <comment xml:lang="uk">тема Microsoft Office 2007</comment>
+ <comment xml:lang="sv">Microsoft Office 2007-tema</comment>
+ <comment xml:lang="ru">Тема Microsoft Office 2007</comment>
+ <comment xml:lang="pl">Motyw Microsoft Office 2007</comment>
+ <comment xml:lang="it">Tema Microsoft Office 2007</comment>
+ <comment xml:lang="eu">Microsoft Office 2007 gaia</comment>
+ <comment xml:lang="es">tema de Microsoft Office 2007</comment>
+ <comment xml:lang="de">Microsoft-Office-2007-Thema</comment>
+ <comment xml:lang="be">тэма Microsoft Office 2007</comment>
+ <glob pattern="*.thmx"/>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="text-x-generic-template"/>
+ </mime-type>
<mime-type type="application/x-t602">
<comment>T602 document</comment>
- <comment xml:lang="ar">مستند T602</comment>
- <comment xml:lang="ast">Documentu T602</comment>
- <comment xml:lang="be@latin">Dakument T602</comment>
- <comment xml:lang="bg">Документ — T602</comment>
- <comment xml:lang="ca">document T602</comment>
- <comment xml:lang="cs">dokument T602</comment>
- <comment xml:lang="da">T602-dokument</comment>
- <comment xml:lang="de">T602-Dokument</comment>
- <comment xml:lang="el">Έγγραφο T602</comment>
- <comment xml:lang="en_GB">T602 document</comment>
- <comment xml:lang="eo">T602-dokumento</comment>
- <comment xml:lang="es">documento T602</comment>
- <comment xml:lang="eu">T602 dokumentua</comment>
- <comment xml:lang="fi">T602-asiakirja</comment>
- <comment xml:lang="fo">T602 skjal</comment>
- <comment xml:lang="fr">document T602</comment>
- <comment xml:lang="ga">cáipéis T602</comment>
- <comment xml:lang="gl">documento T602</comment>
- <comment xml:lang="he">מסמך T602</comment>
- <comment xml:lang="hr">T602 dokument</comment>
- <comment xml:lang="hu">T602 dokumentum</comment>
- <comment xml:lang="ia">Documento T602</comment>
- <comment xml:lang="id">Dokumen T602</comment>
- <comment xml:lang="it">Documento T602</comment>
- <comment xml:lang="ja">T602 ドキュメント</comment>
- <comment xml:lang="kk">T602 құжаты</comment>
- <comment xml:lang="ko">T602 문서</comment>
- <comment xml:lang="lt">T602 dokumentas</comment>
- <comment xml:lang="lv">T602 dokuments</comment>
- <comment xml:lang="nb">T602-dokument</comment>
- <comment xml:lang="nl">T602-document</comment>
- <comment xml:lang="nn">T602-dokument</comment>
- <comment xml:lang="oc">document T602</comment>
- <comment xml:lang="pl">Dokument T602</comment>
- <comment xml:lang="pt">documento T602</comment>
- <comment xml:lang="pt_BR">Documento T602</comment>
- <comment xml:lang="ro">Document T602</comment>
- <comment xml:lang="ru">Документ T602</comment>
- <comment xml:lang="sk">Dokument T602</comment>
- <comment xml:lang="sl">Dokument T602</comment>
- <comment xml:lang="sq">Dokument T602</comment>
- <comment xml:lang="sr">Т602 документ</comment>
- <comment xml:lang="sv">T602-dokument</comment>
- <comment xml:lang="tr">T602 belgesi</comment>
- <comment xml:lang="uk">документ T602</comment>
- <comment xml:lang="vi">Tài liệu T602</comment>
- <comment xml:lang="zh_CN">T602 文档</comment>
<comment xml:lang="zh_TW">T602 文件</comment>
+ <comment xml:lang="zh_CN">T602 文档</comment>
+ <comment xml:lang="vi">Tài liệu T602</comment>
+ <comment xml:lang="uk">документ T602</comment>
+ <comment xml:lang="tr">T602 belgesi</comment>
+ <comment xml:lang="sv">T602-dokument</comment>
+ <comment xml:lang="sr">Т602 документ</comment>
+ <comment xml:lang="sq">dokument T602</comment>
+ <comment xml:lang="sl">Dokument T602</comment>
+ <comment xml:lang="si">T602 ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument T602</comment>
+ <comment xml:lang="ru">Документ T602</comment>
+ <comment xml:lang="ro">Document T602</comment>
+ <comment xml:lang="pt_BR">Documento T602</comment>
+ <comment xml:lang="pt">documento T602</comment>
+ <comment xml:lang="pl">Dokument T602</comment>
+ <comment xml:lang="oc">document T602</comment>
+ <comment xml:lang="nn">T602-dokument</comment>
+ <comment xml:lang="nl">T602-document</comment>
+ <comment xml:lang="nb">T602-dokument</comment>
+ <comment xml:lang="lv">T602 dokuments</comment>
+ <comment xml:lang="lt">T602 dokumentas</comment>
+ <comment xml:lang="ko">T602 문서</comment>
+ <comment xml:lang="kk">T602 құжаты</comment>
+ <comment xml:lang="ja">T602 ドキュメント</comment>
+ <comment xml:lang="it">Documento T602</comment>
+ <comment xml:lang="is">T602 skjal</comment>
+ <comment xml:lang="id">Dokumen T602</comment>
+ <comment xml:lang="ia">Documento T602</comment>
+ <comment xml:lang="hu">T602 dokumentum</comment>
+ <comment xml:lang="hr">T602 dokument</comment>
+ <comment xml:lang="he">מסמך T602</comment>
+ <comment xml:lang="gl">documento T602</comment>
+ <comment xml:lang="ga">cáipéis T602</comment>
+ <comment xml:lang="fur">document T602</comment>
+ <comment xml:lang="fr">document T602</comment>
+ <comment xml:lang="fo">T602 skjal</comment>
+ <comment xml:lang="fi">T602-asiakirja</comment>
+ <comment xml:lang="eu">T602 dokumentua</comment>
+ <comment xml:lang="es">documento T602</comment>
+ <comment xml:lang="eo">T602-dokumento</comment>
+ <comment xml:lang="en_GB">T602 document</comment>
+ <comment xml:lang="el">Έγγραφο T602</comment>
+ <comment xml:lang="de">T602-Dokument</comment>
+ <comment xml:lang="da">T602-dokument</comment>
+ <comment xml:lang="cs">dokument T602</comment>
+ <comment xml:lang="ca">document T602</comment>
+ <comment xml:lang="bg">Документ — T602</comment>
+ <comment xml:lang="be@latin">Dakument T602</comment>
+ <comment xml:lang="be">дакумент T602</comment>
+ <comment xml:lang="ast">Documentu T602</comment>
+ <comment xml:lang="ar">مستند T602</comment>
+ <comment xml:lang="af">T602-dokument</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
- <match value="@CT 0" type="string" offset="0"/>
- <match value="@CT 1" type="string" offset="0"/>
- <match value="@CT 2" type="string" offset="0"/>
+ <magic>
+ <match offset="0" type="string" value="@CT 0"/>
+ <match offset="0" type="string" value="@CT 1"/>
+ <match offset="0" type="string" value="@CT 2"/>
</magic>
<glob pattern="*.602"/>
</mime-type>
<mime-type type="application/x-cisco-vpn-settings">
- <comment>Cisco VPN Settings</comment>
- <comment xml:lang="ar">إعدادات Cisco VPN</comment>
- <comment xml:lang="be@latin">Nałady Cisco VPN</comment>
- <comment xml:lang="bg">Настройки — ВЧМ на Cisco</comment>
- <comment xml:lang="ca">ajusts VPN de Cisco</comment>
- <comment xml:lang="cs">nastavení Cisco VPN</comment>
- <comment xml:lang="da">Cisco VPN-opsætning</comment>
- <comment xml:lang="de">Cisco-VPN-Einstellungen</comment>
- <comment xml:lang="el">Ρυθμίσεις Cisco VPN</comment>
- <comment xml:lang="en_GB">Cisco VPN Settings</comment>
- <comment xml:lang="es">configuración de VPN de Cisco</comment>
- <comment xml:lang="eu">Cisco VPN ezarpenak</comment>
- <comment xml:lang="fi">Cisco VPN -asetukset</comment>
- <comment xml:lang="fo">Cisco VPN stillingar</comment>
- <comment xml:lang="fr">paramètres VPN Cisco</comment>
- <comment xml:lang="ga">socruithe VPN Cisco</comment>
- <comment xml:lang="gl">configuracións de VPN de Cisco</comment>
- <comment xml:lang="he">הגדרות של Cisco VPN</comment>
- <comment xml:lang="hr">Cisco VPN postavke</comment>
- <comment xml:lang="hu">Cisco VPN beállítások</comment>
- <comment xml:lang="ia">Configuration VPN Cisco</comment>
- <comment xml:lang="id">Penataan Cisco VPN</comment>
- <comment xml:lang="it">Impostazioni VPN Cisco</comment>
- <comment xml:lang="ja">Cisco VPN 設定</comment>
- <comment xml:lang="ka">Cisco VPN-ის პარამეტრები</comment>
- <comment xml:lang="kk">Cisco VPN баптаулары</comment>
- <comment xml:lang="ko">Cisco VPN 설정</comment>
- <comment xml:lang="lt">Cisco VPN parametrai</comment>
- <comment xml:lang="lv">Cisco VPN iestatījumi</comment>
- <comment xml:lang="nb">Cisco VPN-innstillinger</comment>
- <comment xml:lang="nl">Cisco VPN-instellingen</comment>
- <comment xml:lang="nn">Cisco VPN-innstillingar</comment>
- <comment xml:lang="oc">paramètres VPN Cisco</comment>
- <comment xml:lang="pl">Ustawienia VPN Cisco</comment>
- <comment xml:lang="pt">definições de Cisco VPN</comment>
- <comment xml:lang="pt_BR">Configurações de VPN da Cisco</comment>
- <comment xml:lang="ro">Configurări VPN Cisco</comment>
- <comment xml:lang="ru">Файл настроек Cisco VPN</comment>
- <comment xml:lang="sk">Nastavenia Cisco VPN</comment>
- <comment xml:lang="sl">Datoteka nastavitev Cisco VPN</comment>
- <comment xml:lang="sq">Rregullime VPN Cisco</comment>
- <comment xml:lang="sr">подешавања Циско ВПН-а</comment>
- <comment xml:lang="sv">Cisco VPN-inställningar</comment>
- <comment xml:lang="tr">Cisco VPN Ayarları</comment>
- <comment xml:lang="uk">параметри VPN Cisco</comment>
- <comment xml:lang="vi">Thiết lập VPN Cisco</comment>
+ <comment>Cisco VPN settings</comment>
+ <comment xml:lang="zh_TW">Cisco VPN 設定</comment>
<comment xml:lang="zh_CN">Cisco VPN 设置</comment>
- <comment xml:lang="zh_TW">Cisco VPN 設定值</comment>
+ <comment xml:lang="uk">параметри VPN Cisco</comment>
+ <comment xml:lang="tr">Cisco VPN ayarları</comment>
+ <comment xml:lang="sv">Cisco VPN-inställningar</comment>
+ <comment xml:lang="sq">rregullime VPN-je Cisco</comment>
+ <comment xml:lang="sl">Nastavitve Cisco VPN</comment>
+ <comment xml:lang="si">Cisco VPN සැකසුම්</comment>
+ <comment xml:lang="sk">Nastavenia Cisco VPN</comment>
+ <comment xml:lang="ru">Файл настроек Cisco VPN</comment>
+ <comment xml:lang="pt_BR">Configurações de VPN da Cisco</comment>
+ <comment xml:lang="pl">Ustawienia VPN Cisco</comment>
+ <comment xml:lang="oc">paramètres VPN Cisco</comment>
+ <comment xml:lang="nl">Cisco VPN-instellingen</comment>
+ <comment xml:lang="ko">시스코 VPN 설정</comment>
+ <comment xml:lang="kk">Cisco VPN баптаулары</comment>
+ <comment xml:lang="ja">Cisco VPN 設定</comment>
+ <comment xml:lang="it">Impostazioni VPN Cisco</comment>
+ <comment xml:lang="is">Cisco VPN-stillingar</comment>
+ <comment xml:lang="id">Pengaturan VPN Cisco</comment>
+ <comment xml:lang="hu">Cisco VPN beállítások</comment>
+ <comment xml:lang="hr">Cisco VPN postavke</comment>
+ <comment xml:lang="he">הגדרות VPN של Cisco</comment>
+ <comment xml:lang="gl">Configuracións de Cisco VPN</comment>
+ <comment xml:lang="fr">paramètres VPN Cisco</comment>
+ <comment xml:lang="fi">Ciscon VPN-asetukset</comment>
+ <comment xml:lang="eu">Cisco VPN ezarpenak</comment>
+ <comment xml:lang="es">configuración de Cisco VPN</comment>
+ <comment xml:lang="en_GB">Cisco VPN settings</comment>
+ <comment xml:lang="de">Cisco-VPN-Einstellungen</comment>
+ <comment xml:lang="da">Cisco VPN-indstillinger</comment>
+ <comment xml:lang="ca">ajusts VPN de Cisco</comment>
+ <comment xml:lang="bg">Настройки — ВЧМ на Cisco</comment>
+ <comment xml:lang="be">налады Cisco VPN</comment>
+ <comment xml:lang="ar">إعدادات Cisco VPN</comment>
+ <sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
- <magic priority="50">
- <match value="[main]" type="string" offset="0">
- <match value="AuthType=" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="[main]" offset="0">
+ <match type="string" value="AuthType=" offset="0:256"/>
</match>
</magic>
<glob pattern="*.pcf"/>
</mime-type>
<mime-type type="application/vnd.iccprofile">
<comment>ICC profile</comment>
- <comment xml:lang="ar">تشكيلة OCL</comment>
- <comment xml:lang="ast">Perfil ICC</comment>
- <comment xml:lang="bg">Цветови профил — OCL</comment>
- <comment xml:lang="ca">perfil ICC</comment>
- <comment xml:lang="cs">profil ICC</comment>
- <comment xml:lang="da">ICC-profil</comment>
- <comment xml:lang="de">ICC-Profil</comment>
- <comment xml:lang="el">Προφίλ ICC</comment>
- <comment xml:lang="en_GB">ICC profile</comment>
- <comment xml:lang="eo">ICC-profilo</comment>
- <comment xml:lang="es">perfil ICC</comment>
- <comment xml:lang="eu">ICC profila</comment>
- <comment xml:lang="fi">ICC-profiili</comment>
- <comment xml:lang="fo">ICC umhvarv</comment>
- <comment xml:lang="fr">profil ICC</comment>
- <comment xml:lang="ga">próifíl ICC</comment>
- <comment xml:lang="gl">perfíl ICC</comment>
- <comment xml:lang="he">פרופיל ICC</comment>
- <comment xml:lang="hr">ICC profil</comment>
- <comment xml:lang="hu">ICC profil</comment>
- <comment xml:lang="ia">Profilo ICC</comment>
- <comment xml:lang="id">Profil ICC</comment>
- <comment xml:lang="it">Profilo ICC</comment>
- <comment xml:lang="ja">ICC プロファイル</comment>
- <comment xml:lang="kk">ICC профайлы</comment>
- <comment xml:lang="ko">ICC 프로필</comment>
- <comment xml:lang="lt">ICC profilis</comment>
- <comment xml:lang="lv">ICC profils</comment>
- <comment xml:lang="nl">ICC profiel</comment>
- <comment xml:lang="oc">perfil ICC</comment>
- <comment xml:lang="pl">Profil ICC</comment>
- <comment xml:lang="pt">perfil ICC</comment>
- <comment xml:lang="pt_BR">Perfil ICC</comment>
- <comment xml:lang="ro">Profil ICC</comment>
- <comment xml:lang="ru">Профиль ICC</comment>
- <comment xml:lang="sk">Profil farieb ICC</comment>
- <comment xml:lang="sl">Datoteka profila ICC</comment>
- <comment xml:lang="sr">ИЦЦ профил</comment>
- <comment xml:lang="sv">ICC-profil</comment>
- <comment xml:lang="tr">ICC profili</comment>
- <comment xml:lang="uk">профіль ICC</comment>
+ <comment xml:lang="zh_TW">ICC 設定組合</comment>
<comment xml:lang="zh_CN">ICC 配置文件</comment>
- <comment xml:lang="zh_TW">ICC 設定檔</comment>
- <magic priority="50">
- <match value="acsp" type="string" offset="36"/>
+ <comment xml:lang="uk">профіль ICC</comment>
+ <comment xml:lang="tr">ICC profili</comment>
+ <comment xml:lang="sv">ICC-profil</comment>
+ <comment xml:lang="sr">ИЦЦ профил</comment>
+ <comment xml:lang="sq">profil ICC</comment>
+ <comment xml:lang="sl">Datoteka profila ICC</comment>
+ <comment xml:lang="si">ICC පැතිකඩ</comment>
+ <comment xml:lang="sk">Profil farieb ICC</comment>
+ <comment xml:lang="ru">Профиль ICC</comment>
+ <comment xml:lang="ro">Profil ICC</comment>
+ <comment xml:lang="pt_BR">Perfil ICC</comment>
+ <comment xml:lang="pt">perfil ICC</comment>
+ <comment xml:lang="pl">Profil ICC</comment>
+ <comment xml:lang="oc">perfil ICC</comment>
+ <comment xml:lang="nl">ICC-profiel</comment>
+ <comment xml:lang="lv">ICC profils</comment>
+ <comment xml:lang="lt">ICC profilis</comment>
+ <comment xml:lang="ko">ICC 프로필</comment>
+ <comment xml:lang="kk">ICC профайлы</comment>
+ <comment xml:lang="ka">ICC პროფილი</comment>
+ <comment xml:lang="ja">ICC プロファイル</comment>
+ <comment xml:lang="it">Profilo ICC</comment>
+ <comment xml:lang="is">ICC snið</comment>
+ <comment xml:lang="id">Profil ICC</comment>
+ <comment xml:lang="ia">Profilo ICC</comment>
+ <comment xml:lang="hu">ICC profil</comment>
+ <comment xml:lang="hr">ICC profil</comment>
+ <comment xml:lang="he">פרופיל ICC</comment>
+ <comment xml:lang="gl">perfíl ICC</comment>
+ <comment xml:lang="ga">próifíl ICC</comment>
+ <comment xml:lang="fur">profîl ICC</comment>
+ <comment xml:lang="fr">profil ICC</comment>
+ <comment xml:lang="fo">ICC umhvarv</comment>
+ <comment xml:lang="fi">ICC-profiili</comment>
+ <comment xml:lang="eu">ICC profila</comment>
+ <comment xml:lang="es">perfil ICC</comment>
+ <comment xml:lang="eo">ICC-profilo</comment>
+ <comment xml:lang="en_GB">ICC profile</comment>
+ <comment xml:lang="el">Προφίλ ICC</comment>
+ <comment xml:lang="de">ICC-Profil</comment>
+ <comment xml:lang="da">ICC-profil</comment>
+ <comment xml:lang="cs">profil ICC</comment>
+ <comment xml:lang="ca">perfil ICC</comment>
+ <comment xml:lang="bg">Цветови профил — OCL</comment>
+ <comment xml:lang="be">профіль ICC</comment>
+ <comment xml:lang="ast">Perfil ICC</comment>
+ <comment xml:lang="ar">تشكيلة ICC</comment>
+ <comment xml:lang="af">ICC-profiel</comment>
+ <acronym>ICC</acronym>
+ <expanded-acronym>International Color Consortium</expanded-acronym>
+ <magic>
+ <match type="string" value="acsp" offset="36"/>
</magic>
<glob pattern="*.icc"/>
<glob pattern="*.icm"/>
</mime-type>
<mime-type type="application/x-it87">
<comment>IT 8.7 color calibration file</comment>
- <comment xml:lang="ar">ملف ضبط ألوان IT 8.7</comment>
- <comment xml:lang="bg">Файл за цветово калибриране — IT 8.7</comment>
- <comment xml:lang="ca">fitxer de calibratge de color IT 8.7</comment>
- <comment xml:lang="cs">soubor kalibrace barev IT 8.7</comment>
- <comment xml:lang="da">IT 8.7 farvekalibreringsfil</comment>
- <comment xml:lang="de">IT 8.7-Farbkalibrierungsdatei</comment>
- <comment xml:lang="el">Αρχείο βαθμονόμησης χρώματος ΙΤ 8.7</comment>
- <comment xml:lang="en_GB">IT 8.7 color calibration file</comment>
- <comment xml:lang="es">archivo de calibración de color IT 8.7</comment>
- <comment xml:lang="eu">IT 8.7 kolore-kalibrazioaren fitxategia</comment>
- <comment xml:lang="fi">IT 8.7 -värikalibrointitiedosto</comment>
- <comment xml:lang="fo">IT 8.7 litstillingarfíla</comment>
- <comment xml:lang="fr">fichier de calibration couleur IT 8.7</comment>
- <comment xml:lang="ga">comhad calabraithe dathanna IT 8.7</comment>
- <comment xml:lang="gl">ficheiro de calibración de cor IT 8.7</comment>
- <comment xml:lang="he">קובץ כיול צבע IT 8.7</comment>
- <comment xml:lang="hr">IT 8.7 datoteka kalibracije boja</comment>
- <comment xml:lang="hu">IT 8.7 színkalibrációs fájl</comment>
- <comment xml:lang="ia">File de calibration de colores IT 8.7</comment>
- <comment xml:lang="id">Berkas kalibrasi warna IT 8.7</comment>
- <comment xml:lang="it">File calibrazione colore IT 8.7</comment>
- <comment xml:lang="ja">IT 8.7 カラーキャリブレーションファイル</comment>
- <comment xml:lang="kk">IT 8.7 түс баптау файлы</comment>
- <comment xml:lang="ko">IT 8.7 색 조율 파일</comment>
- <comment xml:lang="lt">IT 8.7 spalvų kalibravimo failas</comment>
- <comment xml:lang="lv">IT 8.7 krāsu kalibrācijas datne</comment>
- <comment xml:lang="nl">IT 8.7 kleurcalibratie bestand</comment>
- <comment xml:lang="oc">fichièr de calibracion color IT 8.7</comment>
- <comment xml:lang="pl">Plik kalibracji kolorów IT 8.7</comment>
- <comment xml:lang="pt">ficheiro de calibração de cor IT 8.7</comment>
- <comment xml:lang="pt_BR">Arquivo de calibração de cor IT 8.7</comment>
- <comment xml:lang="ro">Fișier de calibrare a culorii IT 8.7</comment>
- <comment xml:lang="ru">Файл калибровки цвета IT 8.7</comment>
- <comment xml:lang="sk">Súbor kalibrácie farieb IT 8.7</comment>
- <comment xml:lang="sl">Umeritvena datoteka barve IT 8.7</comment>
- <comment xml:lang="sr">ИТ 8.7 датотека калибрације боје</comment>
- <comment xml:lang="sv">IT 8.7-färgkalibreringsfil</comment>
- <comment xml:lang="tr">IT 8.7 renk kalibrasyon dosyası</comment>
- <comment xml:lang="uk">файл калібрування кольорів IT 8.7</comment>
- <comment xml:lang="zh_CN">IT 8.7 色彩校准文件</comment>
<comment xml:lang="zh_TW">IT 8.7 色彩校正檔</comment>
- <magic priority="50">
- <match value="IT8.7" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">IT 8.7 色彩校准文件</comment>
+ <comment xml:lang="uk">файл калібрування кольорів IT 8.7</comment>
+ <comment xml:lang="tr">IT 8.7 renk kalibrasyon dosyası</comment>
+ <comment xml:lang="sv">IT 8.7-färgkalibreringsfil</comment>
+ <comment xml:lang="sr">ИТ 8.7 датотека калибрације боје</comment>
+ <comment xml:lang="sq">kartelë kalibrimi ngjyrash IT 8.7</comment>
+ <comment xml:lang="sl">Umeritvena datoteka barve IT 8.7</comment>
+ <comment xml:lang="si">IT 8.7 වර්ණ ක්‍රමාංකන ගොනුව</comment>
+ <comment xml:lang="sk">Súbor kalibrácie farieb IT 8.7</comment>
+ <comment xml:lang="ru">Файл калибровки цвета IT 8.7</comment>
+ <comment xml:lang="ro">Fișier de calibrare a culorii IT 8.7</comment>
+ <comment xml:lang="pt_BR">Arquivo de calibração de cor IT 8.7</comment>
+ <comment xml:lang="pt">ficheiro de calibração de cor IT 8.7</comment>
+ <comment xml:lang="pl">Plik kalibracji kolorów IT 8.7</comment>
+ <comment xml:lang="oc">fichièr de calibracion color IT 8.7</comment>
+ <comment xml:lang="nl">IT 8.7-kleurcalibratiebestand</comment>
+ <comment xml:lang="lv">IT 8.7 krāsu kalibrācijas datne</comment>
+ <comment xml:lang="lt">IT 8.7 spalvų kalibravimo failas</comment>
+ <comment xml:lang="ko">IT 8.7 색 조율 파일</comment>
+ <comment xml:lang="kk">IT 8.7 түс баптау файлы</comment>
+ <comment xml:lang="ja">IT 8.7 カラーキャリブレーションファイル</comment>
+ <comment xml:lang="it">File calibrazione colore IT 8.7</comment>
+ <comment xml:lang="is">IT 8.7 litkvörðunarskrá</comment>
+ <comment xml:lang="id">Berkas kalibrasi warna IT 8.7</comment>
+ <comment xml:lang="ia">File de calibration de colores IT 8.7</comment>
+ <comment xml:lang="hu">IT 8.7 színkalibrációs fájl</comment>
+ <comment xml:lang="hr">IT 8.7 datoteka kalibracije boja</comment>
+ <comment xml:lang="he">קובץ כיול צבע IT 8.7</comment>
+ <comment xml:lang="gl">ficheiro de calibración de cor IT 8.7</comment>
+ <comment xml:lang="ga">comhad calabraithe dathanna IT 8.7</comment>
+ <comment xml:lang="fur">file calibradure colôr IT 8.7</comment>
+ <comment xml:lang="fr">fichier de calibration couleur IT 8.7</comment>
+ <comment xml:lang="fo">IT 8.7 litstillingarfíla</comment>
+ <comment xml:lang="fi">IT 8.7 -värikalibrointitiedosto</comment>
+ <comment xml:lang="eu">IT 8.7 kolore-kalibrazioaren fitxategia</comment>
+ <comment xml:lang="es">archivo de calibración de color IT 8.7</comment>
+ <comment xml:lang="en_GB">IT 8.7 color calibration file</comment>
+ <comment xml:lang="el">Αρχείο βαθμονόμησης χρώματος ΙΤ 8.7</comment>
+ <comment xml:lang="de">IT-8.7-Farbkalibrierungsdatei</comment>
+ <comment xml:lang="da">IT 8.7 farvekalibreringsfil</comment>
+ <comment xml:lang="cs">soubor kalibrace barev IT 8.7</comment>
+ <comment xml:lang="ca">fitxer de calibratge de color IT 8.7</comment>
+ <comment xml:lang="bg">Цветово калибриране — IT 8.7</comment>
+ <comment xml:lang="be">файл каліброўкі колеру IT 8.7</comment>
+ <comment xml:lang="ar">ملف ضبط ألوان IT 8.7</comment>
+ <magic>
+ <match type="string" value="IT8.7" offset="0"/>
</magic>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
@@ -39650,43 +42437,51 @@
</mime-type>
<mime-type type="application/x-ccmx">
<comment>CCMX color correction file</comment>
- <comment xml:lang="ca">fitxer de correcció de color CCMX</comment>
- <comment xml:lang="cs">soubor korekce barev CCMX</comment>
- <comment xml:lang="da">CCMX-farvekorrektionsfil</comment>
- <comment xml:lang="de">CCMX-Farbkorrekturdatei</comment>
- <comment xml:lang="el">Αρχείο διόρθωσης χρωμάτων CCMX</comment>
- <comment xml:lang="en_GB">CCMX colour correction file</comment>
- <comment xml:lang="es">archivo de corrección de color CCMX</comment>
- <comment xml:lang="eu">CCMX kolore-kalibrazioaren fitxategia</comment>
- <comment xml:lang="fi">CCMX-värikorjaustiedosto</comment>
- <comment xml:lang="fr">fichier de correction colorimétrique CCMX</comment>
- <comment xml:lang="ga">comhad ceartúchán dathanna CCMX</comment>
- <comment xml:lang="gl">Ficheiro de corrección de cor CCMX</comment>
- <comment xml:lang="he">קובץ תיקון צבע מסוג CCMX</comment>
- <comment xml:lang="hr">CCMX datotkea ispravka boja</comment>
- <comment xml:lang="hu">CCMX színjavítási fájl</comment>
- <comment xml:lang="ia">File de correction de colores CCMX</comment>
- <comment xml:lang="id">Berkas koreksi warna CCMX</comment>
- <comment xml:lang="it">File correzione colore CCMX</comment>
- <comment xml:lang="ja">CCMX カラー訂正ファイル</comment>
- <comment xml:lang="kk">CCMX түсті келтіру файлы</comment>
- <comment xml:lang="ko">CCMX 색상 보정 파일</comment>
- <comment xml:lang="lv">CCMX krāsu korekciju datne</comment>
- <comment xml:lang="oc">fichièr de correccion colorimetrica CCMX</comment>
- <comment xml:lang="pl">Plik korekcji kolorów CCMX</comment>
- <comment xml:lang="pt">ficheiro de correção de cor CCMX</comment>
- <comment xml:lang="pt_BR">Arquivo de correção de cor CCMX</comment>
- <comment xml:lang="ru">Файл цветовой коррекции CCMX</comment>
- <comment xml:lang="sk">Súbor korekcie farieb CCMX</comment>
- <comment xml:lang="sl">Datoteka barvne poprave CCMX</comment>
- <comment xml:lang="sr">ЦЦМИкс датотека поправке боје</comment>
- <comment xml:lang="sv">CCMX-färgkorrigeringsfil</comment>
- <comment xml:lang="tr">CCMX renk düzeltme dosyası</comment>
- <comment xml:lang="uk">файл даних виправлення кольорів CCMX</comment>
- <comment xml:lang="zh_CN">CCMX 色彩校准文件</comment>
<comment xml:lang="zh_TW">CCMX 色彩校正檔</comment>
- <magic priority="50">
- <match value="CCMX" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">CCMX 色彩校准文件</comment>
+ <comment xml:lang="uk">файл даних виправлення кольорів CCMX</comment>
+ <comment xml:lang="tr">CCMX renk düzeltme dosyası</comment>
+ <comment xml:lang="sv">CCMX-färgkorrigeringsfil</comment>
+ <comment xml:lang="sr">ЦЦМИкс датотека поправке боје</comment>
+ <comment xml:lang="sq">kartelë saktësimi ngjyrash CCMX</comment>
+ <comment xml:lang="sl">Datoteka barvne poprave CCMX</comment>
+ <comment xml:lang="si">CCMX වර්ණ නිවැරදි කිරීමේ ගොනුව</comment>
+ <comment xml:lang="sk">Súbor korekcie farieb CCMX</comment>
+ <comment xml:lang="ru">Файл цветовой коррекции CCMX</comment>
+ <comment xml:lang="pt_BR">Arquivo de correção de cor CCMX</comment>
+ <comment xml:lang="pt">ficheiro de correção de cor CCMX</comment>
+ <comment xml:lang="pl">Plik korekcji kolorów CCMX</comment>
+ <comment xml:lang="oc">fichièr de correccion colorimetrica CCMX</comment>
+ <comment xml:lang="nl">CCMX-kleurcorrectiebestand</comment>
+ <comment xml:lang="lv">CCMX krāsu korekciju datne</comment>
+ <comment xml:lang="ko">CCMX 색상 보정 파일</comment>
+ <comment xml:lang="kk">CCMX түсті келтіру файлы</comment>
+ <comment xml:lang="ja">CCMX カラー訂正ファイル</comment>
+ <comment xml:lang="it">File correzione colore CCMX</comment>
+ <comment xml:lang="is">CCMX litleiðréttingarskrá</comment>
+ <comment xml:lang="id">Berkas koreksi warna CCMX</comment>
+ <comment xml:lang="ia">File de correction de colores CCMX</comment>
+ <comment xml:lang="hu">CCMX színjavítási fájl</comment>
+ <comment xml:lang="hr">CCMX datotkea ispravka boja</comment>
+ <comment xml:lang="he">קובץ תיקון צבע מסוג CCMX</comment>
+ <comment xml:lang="gl">Ficheiro de corrección de cor CCMX</comment>
+ <comment xml:lang="ga">comhad ceartúchán dathanna CCMX</comment>
+ <comment xml:lang="fur">file corezion colôr CCMX</comment>
+ <comment xml:lang="fr">fichier de correction colorimétrique CCMX</comment>
+ <comment xml:lang="fi">CCMX-värikorjaustiedosto</comment>
+ <comment xml:lang="eu">CCMX kolore-kalibrazioaren fitxategia</comment>
+ <comment xml:lang="es">archivo de corrección de color CCMX</comment>
+ <comment xml:lang="en_GB">CCMX colour correction file</comment>
+ <comment xml:lang="el">Αρχείο διόρθωσης χρωμάτων CCMX</comment>
+ <comment xml:lang="de">CCMX-Farbkorrekturdatei</comment>
+ <comment xml:lang="da">CCMX-farvekorrektionsfil</comment>
+ <comment xml:lang="cs">soubor korekce barev CCMX</comment>
+ <comment xml:lang="ca">fitxer de correcció de color CCMX</comment>
+ <comment xml:lang="bg">Цветови поправки — CCMX</comment>
+ <comment xml:lang="be">файл карэкцыі колеру CCMX</comment>
+ <comment xml:lang="ar">ملف تصحيح لون CCMX</comment>
+ <magic>
+ <match type="string" value="CCMX" offset="0"/>
</magic>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
@@ -39694,1150 +42489,962 @@
</mime-type>
<mime-type type="application/winhlp">
<comment>WinHelp help file</comment>
- <comment xml:lang="ca">fitxer d'ajuda WinHelp</comment>
- <comment xml:lang="cs">soubor nápovědy WinHelp</comment>
- <comment xml:lang="da">WinHelp-hjælpefil</comment>
- <comment xml:lang="de">WinHelp-Hilfedatei</comment>
- <comment xml:lang="el">Αρχείο βοήθειας WinHelp</comment>
- <comment xml:lang="en_GB">WinHelp help file</comment>
- <comment xml:lang="es">archivo de ayuda de WinHelp</comment>
- <comment xml:lang="eu">WinHelp laguntza fitxategia</comment>
- <comment xml:lang="fi">WinHelp-ohjetiedosto</comment>
- <comment xml:lang="fr">fichier d'aide WinHelp</comment>
- <comment xml:lang="ga">comhad cabhrach WinHelp</comment>
- <comment xml:lang="gl">Ficheiro de axuda WinHelp</comment>
- <comment xml:lang="he">קובץ עזרה מסוג WinHelp</comment>
- <comment xml:lang="hr">WinHelp datoteka pomoći</comment>
- <comment xml:lang="hu">WinHelp súgófájl</comment>
- <comment xml:lang="ia">File de adjuta WinHelp</comment>
- <comment xml:lang="id">Berkas bantuan WinHelp</comment>
- <comment xml:lang="it">File aiuto WInHelp</comment>
- <comment xml:lang="ja">WinHelp ヘルプファイル</comment>
- <comment xml:lang="kk">WinHelp көмек файлы</comment>
- <comment xml:lang="ko">WinHelp 도움말 파일</comment>
- <comment xml:lang="lv">WinHelp palīdzības datne</comment>
- <comment xml:lang="oc">fichièr d'ajuda WinHelp</comment>
- <comment xml:lang="pl">Plik pomocy WinHelp</comment>
- <comment xml:lang="pt">ficheiro de ajuda WinHelp</comment>
- <comment xml:lang="pt_BR">Arquivo de ajuda WinHelp</comment>
- <comment xml:lang="ru">Файл справки WinHelp</comment>
- <comment xml:lang="sk">Súbor Pomocníka WinHelp</comment>
- <comment xml:lang="sl">Datoteka pomoči WinHelp</comment>
- <comment xml:lang="sr">датотека помоћи Вин хелпа</comment>
- <comment xml:lang="sv">WinHelp-hjälpfil</comment>
- <comment xml:lang="tr">WinHelp yardım dosyası</comment>
- <comment xml:lang="uk">файл довідки WinHelp</comment>
- <comment xml:lang="zh_CN">WinHelp 帮助文件</comment>
<comment xml:lang="zh_TW">WinHelp 說明檔</comment>
- <magic priority="50">
- <match value="0x00035f3f" type="little32" offset="0"/>
+ <comment xml:lang="zh_CN">WinHelp 帮助文件</comment>
+ <comment xml:lang="uk">файл довідки WinHelp</comment>
+ <comment xml:lang="tr">WinHelp yardım dosyası</comment>
+ <comment xml:lang="sv">WinHelp-hjälpfil</comment>
+ <comment xml:lang="sr">датотека помоћи Вин хелпа</comment>
+ <comment xml:lang="sq">kartelë ndihme WinHelp</comment>
+ <comment xml:lang="sl">Datoteka pomoči WinHelp</comment>
+ <comment xml:lang="si">WinHelp උදව් ගොනුව</comment>
+ <comment xml:lang="sk">Súbor Pomocníka WinHelp</comment>
+ <comment xml:lang="ru">Файл справки WinHelp</comment>
+ <comment xml:lang="pt_BR">Arquivo de ajuda WinHelp</comment>
+ <comment xml:lang="pt">ficheiro de ajuda WinHelp</comment>
+ <comment xml:lang="pl">Plik pomocy WinHelp</comment>
+ <comment xml:lang="oc">fichièr d'ajuda WinHelp</comment>
+ <comment xml:lang="nl">WinHelp-hulpbestand</comment>
+ <comment xml:lang="lv">WinHelp palīdzības datne</comment>
+ <comment xml:lang="ko">WinHelp 도움말 파일</comment>
+ <comment xml:lang="kk">WinHelp көмек файлы</comment>
+ <comment xml:lang="ja">WinHelp ヘルプファイル</comment>
+ <comment xml:lang="it">File aiuto WInHelp</comment>
+ <comment xml:lang="is">WinHelp-hjálparskrá</comment>
+ <comment xml:lang="id">Berkas bantuan WinHelp</comment>
+ <comment xml:lang="ia">File de adjuta WinHelp</comment>
+ <comment xml:lang="hu">WinHelp súgófájl</comment>
+ <comment xml:lang="hr">WinHelp datoteka pomoći</comment>
+ <comment xml:lang="he">קובץ עזרה מסוג WinHelp</comment>
+ <comment xml:lang="gl">Ficheiro de axuda WinHelp</comment>
+ <comment xml:lang="ga">comhad cabhrach WinHelp</comment>
+ <comment xml:lang="fur">file di jutori WinHelp</comment>
+ <comment xml:lang="fr">fichier d'aide WinHelp</comment>
+ <comment xml:lang="fi">WinHelp-ohjetiedosto</comment>
+ <comment xml:lang="eu">WinHelp laguntza fitxategia</comment>
+ <comment xml:lang="es">archivo de ayuda de WinHelp</comment>
+ <comment xml:lang="en_GB">WinHelp help file</comment>
+ <comment xml:lang="el">Αρχείο βοήθειας WinHelp</comment>
+ <comment xml:lang="de">WinHelp-Hilfedatei</comment>
+ <comment xml:lang="da">WinHelp-hjælpefil</comment>
+ <comment xml:lang="cs">soubor nápovědy WinHelp</comment>
+ <comment xml:lang="ca">fitxer d'ajuda WinHelp</comment>
+ <comment xml:lang="bg">Помощен файл — WinHelp</comment>
+ <comment xml:lang="be">файл даведкі WinHelp</comment>
+ <comment xml:lang="ar">ملف مساعدة ويندوز</comment>
+ <comment xml:lang="af">WinHelp-hulplêer</comment>
+ <magic>
+ <match type="little32" value="0x00035f3f" offset="0"/>
</magic>
<glob pattern="*.hlp"/>
<alias type="zz-application/zz-winassoc-hlp"/>
</mime-type>
<mime-type type="application/x-bsdiff">
- <comment>binary differences between files</comment>
- <comment xml:lang="ca">diferencies binàries entre fitxers</comment>
- <comment xml:lang="cs">binární rozdíl mezi soubory</comment>
- <comment xml:lang="da">binære forskelle mellem filer</comment>
- <comment xml:lang="de">binäre Unterschiede zwischen Dateien</comment>
- <comment xml:lang="en_GB">binary differences between files</comment>
- <comment xml:lang="es">diferencias entre archivos binarios</comment>
- <comment xml:lang="eu">fitxategi binarioen arteko ezberdinstasunak</comment>
- <comment xml:lang="fr">différences binaires entre fichiers</comment>
- <comment xml:lang="ga">difríochtaí dénártha idir comhaid</comment>
- <comment xml:lang="he">הבדלים בינריים בין קבצים</comment>
- <comment xml:lang="hr">Binarne razlike između datoteka</comment>
- <comment xml:lang="hu">bináris különbségfájl</comment>
- <comment xml:lang="id">perbedaan biner antar berkas</comment>
- <comment xml:lang="it">Differenze binarie tra file</comment>
- <comment xml:lang="kk">файлдар арасындағы бинарлық айырмашылықтар</comment>
- <comment xml:lang="ko">바이너리 차이 비교 파일</comment>
- <comment xml:lang="pl">Binarna różnica pomiędzy plikami</comment>
- <comment xml:lang="pt_BR">Diferenças binárias entre arquivos</comment>
- <comment xml:lang="ru">Двоичные различия между файлами</comment>
- <comment xml:lang="sk">Binárne rozdiely medzi súbormi</comment>
- <comment xml:lang="sr">бинарне разлике датотека</comment>
- <comment xml:lang="sv">binära skillnader mellan filer</comment>
- <comment xml:lang="tr">dosyalar arasındaki ikilik farklar</comment>
+ <comment>Binary differences between files</comment>
<comment xml:lang="uk">двійкова різниця між файлами</comment>
- <comment xml:lang="zh_CN">文件的二进制区别</comment>
- <comment xml:lang="zh_TW">檔案間的二進位差異</comment>
+ <comment xml:lang="sv">Binära skillnader mellan filer</comment>
+ <comment xml:lang="ru">Двоичные различия между файлами</comment>
+ <comment xml:lang="pl">Binarna różnica pomiędzy plikami</comment>
+ <comment xml:lang="it">Differenze binarie tra file</comment>
+ <comment xml:lang="eu">Fitxategien arteko diferentzia bitarra</comment>
+ <comment xml:lang="es">diferencias binarias entre archivos</comment>
+ <comment xml:lang="de">Binäre Unterschiede zwischen Dateien</comment>
+ <comment xml:lang="be">бінарныя адрозненні паміж файламі</comment>
<magic>
- <match value="BSDIFF40" type="string" offset="0"/>
- <match value="BSDIFN40" type="string" offset="0"/>
+ <match type="string" value="BSDIFF40" offset="0"/>
+ <match type="string" value="BSDIFN40" offset="0"/>
</magic>
<glob pattern="*.bsdiff"/>
</mime-type>
-
-
+ <!-- Tree content-types -->
<mime-type type="x-content/image-dcf">
-
- <comment>digital photos</comment>
- <comment xml:lang="ar">الصور الرقمية</comment>
- <comment xml:lang="be@latin">ličbavyja zdymki</comment>
- <comment xml:lang="bg">Цифрови фотографии</comment>
- <comment xml:lang="ca">fotos digitals</comment>
- <comment xml:lang="cs">digitální fotografie</comment>
- <comment xml:lang="da">digitale billeder</comment>
- <comment xml:lang="de">Digitale Fotos</comment>
- <comment xml:lang="el">Ψηφιακές φωτογραφίες</comment>
- <comment xml:lang="en_GB">digital photos</comment>
- <comment xml:lang="es">fotos digitales</comment>
- <comment xml:lang="eu">argazki digitalak</comment>
- <comment xml:lang="fi">digivalokuvia</comment>
- <comment xml:lang="fo">talgildar myndir</comment>
- <comment xml:lang="fr">photos numériques</comment>
- <comment xml:lang="ga">grianghraif dhigiteacha</comment>
- <comment xml:lang="gl">fotos dixitais</comment>
- <comment xml:lang="he">תמונות דיגיטליות</comment>
- <comment xml:lang="hr">Digitalne fotografije</comment>
- <comment xml:lang="hu">digitális fényképek</comment>
- <comment xml:lang="ia">Photos digital</comment>
- <comment xml:lang="id">foto digital</comment>
- <comment xml:lang="it">Foto digitali</comment>
- <comment xml:lang="ja">デジタルフォト</comment>
- <comment xml:lang="kk">сандық фотосуреттер</comment>
- <comment xml:lang="ko">디지털 사진</comment>
- <comment xml:lang="lt">skaitmeninės nuotraukos</comment>
- <comment xml:lang="lv">digitāla fotogrāfija</comment>
- <comment xml:lang="nl">digitale foto's</comment>
- <comment xml:lang="nn">digitale fotografi</comment>
- <comment xml:lang="oc">fòtos numericas</comment>
- <comment xml:lang="pl">Zdjęcia cyfrowe</comment>
- <comment xml:lang="pt">fotografias digitais</comment>
- <comment xml:lang="pt_BR">Fotos digitais</comment>
- <comment xml:lang="ro">fotografii digitale</comment>
- <comment xml:lang="ru">Цифровые фотографии</comment>
- <comment xml:lang="sk">Digitálne fotografie</comment>
- <comment xml:lang="sl">digitalne fotografije</comment>
- <comment xml:lang="sq">Fotografi dixhitale</comment>
- <comment xml:lang="sr">дигиталне фотографије</comment>
- <comment xml:lang="sv">digitalbilder</comment>
- <comment xml:lang="tr">sayısal fotoğraflar</comment>
+ <!-- http://en.wikipedia.org/wiki/Design_rule_for_Camera_File_system -->
+ <comment>Digital photos</comment>
<comment xml:lang="uk">цифрові фотографії</comment>
- <comment xml:lang="vi">ảnh chụp số</comment>
- <comment xml:lang="zh_CN">数字化图像</comment>
- <comment xml:lang="zh_TW">數位相片</comment>
+ <comment xml:lang="sv">Digitalbilder</comment>
+ <comment xml:lang="ru">Цифровые фотографии</comment>
+ <comment xml:lang="pt_BR">Fotos digitais</comment>
+ <comment xml:lang="pl">Zdjęcia cyfrowe</comment>
+ <comment xml:lang="it">Foto digitali</comment>
+ <comment xml:lang="gl">Fotos dixitais</comment>
+ <comment xml:lang="eu">Argazki digitalak</comment>
+ <comment xml:lang="es">fotografías digitales</comment>
+ <comment xml:lang="de">Digitale Fotos</comment>
+ <comment xml:lang="be">лічбавыя фатаграфіі</comment>
<treemagic>
- <treematch type="directory" path="dcim" non-empty="true"/>
+ <treematch path="dcim" type="directory" non-empty="true"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/video-vcd">
-
+ <!-- TRANSLATORS: This is a brand-name, not a generic term. Please see
+ http://en.wikipedia.org/wiki/Video_CD
+ http://www.herongyang.com/CD-DVD/VCD-Movie-File-Directory-Structure.html -->
<comment>Video CD</comment>
- <comment xml:lang="ar">Video CD</comment>
- <comment xml:lang="ast">CD de videu</comment>
- <comment xml:lang="be@latin">Videa CD</comment>
- <comment xml:lang="bg">CD — видео</comment>
- <comment xml:lang="ca">Video CD</comment>
- <comment xml:lang="cs">Video CD</comment>
- <comment xml:lang="da">Video-cd</comment>
- <comment xml:lang="de">Video-CD</comment>
- <comment xml:lang="el">Video CD</comment>
- <comment xml:lang="en_GB">Video CD</comment>
- <comment xml:lang="eo">Video-KD</comment>
- <comment xml:lang="es">Video CD</comment>
- <comment xml:lang="eu">Bideo CDa</comment>
- <comment xml:lang="fi">Video CD</comment>
- <comment xml:lang="fo">Video CD</comment>
- <comment xml:lang="fr">CD vidéo</comment>
- <comment xml:lang="ga">dlúthdhiosca físe</comment>
- <comment xml:lang="gl">Video CD</comment>
- <comment xml:lang="he">תקליטור וידאו</comment>
- <comment xml:lang="hr">Video CD</comment>
- <comment xml:lang="hu">Video CD</comment>
- <comment xml:lang="ia">Video CD</comment>
- <comment xml:lang="id">Video CD</comment>
- <comment xml:lang="it">Video CD</comment>
- <comment xml:lang="ja">ビデオ CD</comment>
- <comment xml:lang="kk">видео CD</comment>
- <comment xml:lang="ko">비디오 CD</comment>
- <comment xml:lang="lt">Vaizdo CD</comment>
- <comment xml:lang="lv">Video CD</comment>
- <comment xml:lang="nl">video-CD</comment>
- <comment xml:lang="nn">Video-CD</comment>
- <comment xml:lang="oc">CD vidèo</comment>
- <comment xml:lang="pl">Video CD</comment>
- <comment xml:lang="pt">Video CD</comment>
- <comment xml:lang="pt_BR">CD de vídeo</comment>
- <comment xml:lang="ro">CD video</comment>
- <comment xml:lang="ru">Видео CD</comment>
- <comment xml:lang="sk">Video CD</comment>
- <comment xml:lang="sl">Video CD</comment>
- <comment xml:lang="sq">CD Video</comment>
- <comment xml:lang="sr">Видео ЦД</comment>
- <comment xml:lang="sv">Video-cd</comment>
- <comment xml:lang="tr">Video CD</comment>
- <comment xml:lang="uk">Video CD</comment>
- <comment xml:lang="vi">Đĩa CD ảnh động</comment>
- <comment xml:lang="zh_CN">VCD</comment>
<comment xml:lang="zh_TW">Video CD</comment>
+ <comment xml:lang="zh_CN">VCD</comment>
+ <comment xml:lang="vi">Đĩa CD ảnh động</comment>
+ <comment xml:lang="uk">Video CD</comment>
+ <comment xml:lang="tr">Video CD</comment>
+ <comment xml:lang="sv">Video-cd</comment>
+ <comment xml:lang="sr">Видео ЦД</comment>
+ <comment xml:lang="sq">CD Video</comment>
+ <comment xml:lang="sl">Video CD</comment>
+ <comment xml:lang="si">වීඩියෝ සීඩී</comment>
+ <comment xml:lang="sk">Video CD</comment>
+ <comment xml:lang="ru">Видео CD</comment>
+ <comment xml:lang="ro">CD video</comment>
+ <comment xml:lang="pt_BR">CD de vídeo</comment>
+ <comment xml:lang="pt">Video CD</comment>
+ <comment xml:lang="pl">Video CD</comment>
+ <comment xml:lang="oc">CD vidèo</comment>
+ <comment xml:lang="nn">Video-CD</comment>
+ <comment xml:lang="nl">video-CD</comment>
+ <comment xml:lang="lv">Video CD</comment>
+ <comment xml:lang="lt">Vaizdo CD</comment>
+ <comment xml:lang="ko">비디오 CD</comment>
+ <comment xml:lang="kk">видео CD</comment>
+ <comment xml:lang="ka">ვიდეო CD</comment>
+ <comment xml:lang="ja">ビデオ CD</comment>
+ <comment xml:lang="it">Video CD</comment>
+ <comment xml:lang="is">Video CD-mynddiskur</comment>
+ <comment xml:lang="id">Video CD</comment>
+ <comment xml:lang="ia">Video CD</comment>
+ <comment xml:lang="hu">Video CD</comment>
+ <comment xml:lang="hr">Video CD</comment>
+ <comment xml:lang="he">תקליטור וידאו</comment>
+ <comment xml:lang="gl">Video CD</comment>
+ <comment xml:lang="ga">dlúthdhiosca físe</comment>
+ <comment xml:lang="fur">Video CD</comment>
+ <comment xml:lang="fr">CD vidéo</comment>
+ <comment xml:lang="fo">Video CD</comment>
+ <comment xml:lang="fi">Video CD</comment>
+ <comment xml:lang="eu">Bideo CDa</comment>
+ <comment xml:lang="es">Video CD</comment>
+ <comment xml:lang="eo">Video-KD</comment>
+ <comment xml:lang="en_GB">Video CD</comment>
+ <comment xml:lang="el">Video CD</comment>
+ <comment xml:lang="de">Video-CD</comment>
+ <comment xml:lang="da">Video-cd</comment>
+ <comment xml:lang="cs">Video CD</comment>
+ <comment xml:lang="ca">Video CD</comment>
+ <comment xml:lang="bg">CD — видео</comment>
+ <comment xml:lang="be@latin">Videa CD</comment>
+ <comment xml:lang="be">відэа CD</comment>
+ <comment xml:lang="ast">CD de videu</comment>
+ <comment xml:lang="ar">سي دي فيديو</comment>
+ <comment xml:lang="af">Video-CD</comment>
<treemagic>
- <treematch type="file" path="mpegav/AVSEQ01.DAT"/>
+ <treematch path="mpegav/AVSEQ01.DAT" type="file"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/video-svcd">
-
+ <!-- TRANSLATORS: This is a brand-name, not a generic term. Please see
+ http://en.wikipedia.org/wiki/Super_Video_CD
+ http://everything2.com/index.pl?node_id=1009222 -->
<comment>Super Video CD</comment>
- <comment xml:lang="ar">Super Video CD</comment>
- <comment xml:lang="ast">CD de Super Video</comment>
- <comment xml:lang="be@latin">Super Video CD</comment>
- <comment xml:lang="bg">CD — супер видео</comment>
- <comment xml:lang="ca">Super Video CD</comment>
- <comment xml:lang="cs">Super Video CD</comment>
- <comment xml:lang="da">Super Video-cd</comment>
- <comment xml:lang="de">Super-Video-CD</comment>
- <comment xml:lang="el">Super Video CD</comment>
- <comment xml:lang="en_GB">Super Video CD</comment>
- <comment xml:lang="eo">Super-Video-KD</comment>
- <comment xml:lang="es">Super Video CD</comment>
- <comment xml:lang="eu">Super Bideo CDa</comment>
- <comment xml:lang="fi">Super Video CD</comment>
- <comment xml:lang="fo">Super Video CD</comment>
- <comment xml:lang="fr">Super VCD</comment>
- <comment xml:lang="ga">dlúthdhiosca Super Video</comment>
- <comment xml:lang="gl">Super vídeo CD</comment>
- <comment xml:lang="he">Super Video CD</comment>
- <comment xml:lang="hr">Super Video CD</comment>
- <comment xml:lang="hu">Super Video CD</comment>
- <comment xml:lang="ia">Super Video CD</comment>
- <comment xml:lang="id">Super Video CD</comment>
- <comment xml:lang="it">Super Video CD</comment>
- <comment xml:lang="ja">スーパービデオ CD</comment>
- <comment xml:lang="kk">Super Video CD</comment>
- <comment xml:lang="ko">수퍼 비디오 CD</comment>
- <comment xml:lang="lt">Super vaizdo CD</comment>
- <comment xml:lang="lv">Super Video CD</comment>
- <comment xml:lang="nl">super-video-CD</comment>
- <comment xml:lang="nn">Super Video-CD</comment>
- <comment xml:lang="oc">Super VCD</comment>
- <comment xml:lang="pl">Super Video CD</comment>
- <comment xml:lang="pt">Super Video CD</comment>
- <comment xml:lang="pt_BR">CD de Super Vídeo (SVCD)</comment>
- <comment xml:lang="ro">Super Video CD</comment>
- <comment xml:lang="ru">Super Video CD</comment>
- <comment xml:lang="sk">Super Video CD</comment>
- <comment xml:lang="sl">Super Video CD</comment>
- <comment xml:lang="sq">CD Super Video</comment>
- <comment xml:lang="sr">Супер видео ЦД</comment>
- <comment xml:lang="sv">Super Video CD</comment>
- <comment xml:lang="tr">Super Video CD</comment>
- <comment xml:lang="uk">Super Video CD</comment>
- <comment xml:lang="vi">Đĩa CD siêu ảnh động</comment>
- <comment xml:lang="zh_CN">SVCD</comment>
<comment xml:lang="zh_TW">Super Video CD</comment>
+ <comment xml:lang="zh_CN">SVCD</comment>
+ <comment xml:lang="vi">Đĩa CD siêu ảnh động</comment>
+ <comment xml:lang="uk">Super Video CD</comment>
+ <comment xml:lang="tr">Super Video CD</comment>
+ <comment xml:lang="sv">Super Video CD</comment>
+ <comment xml:lang="sr">Супер видео ЦД</comment>
+ <comment xml:lang="sq">CD Super Video</comment>
+ <comment xml:lang="sl">Super Video CD</comment>
+ <comment xml:lang="si">සුපිරි වීඩියෝ CD</comment>
+ <comment xml:lang="sk">Super Video CD</comment>
+ <comment xml:lang="ru">Super Video CD</comment>
+ <comment xml:lang="ro">Super Video CD</comment>
+ <comment xml:lang="pt_BR">CD de Super Vídeo (SVCD)</comment>
+ <comment xml:lang="pt">Super Video CD</comment>
+ <comment xml:lang="pl">Super Video CD</comment>
+ <comment xml:lang="oc">Super VCD</comment>
+ <comment xml:lang="nn">Super Video-CD</comment>
+ <comment xml:lang="nl">super-video-CD</comment>
+ <comment xml:lang="lv">Super Video CD</comment>
+ <comment xml:lang="lt">Super vaizdo CD</comment>
+ <comment xml:lang="ko">수퍼 비디오 CD</comment>
+ <comment xml:lang="kk">Super Video CD</comment>
+ <comment xml:lang="ka">Super Video CD</comment>
+ <comment xml:lang="ja">スーパービデオ CD</comment>
+ <comment xml:lang="it">Super Video CD</comment>
+ <comment xml:lang="is">Super Video CD-mynddiskur</comment>
+ <comment xml:lang="id">Super Video CD</comment>
+ <comment xml:lang="ia">Super Video CD</comment>
+ <comment xml:lang="hu">Super Video CD</comment>
+ <comment xml:lang="hr">Super Video CD</comment>
+ <comment xml:lang="he">Super Video CD</comment>
+ <comment xml:lang="gl">Super vídeo CD</comment>
+ <comment xml:lang="ga">dlúthdhiosca Super Video</comment>
+ <comment xml:lang="fur">Super Video CD</comment>
+ <comment xml:lang="fr">Super VCD</comment>
+ <comment xml:lang="fo">Super Video CD</comment>
+ <comment xml:lang="fi">Super Video CD</comment>
+ <comment xml:lang="eu">Super Bideo CDa</comment>
+ <comment xml:lang="es">Super Video CD</comment>
+ <comment xml:lang="eo">Super-Video-KD</comment>
+ <comment xml:lang="en_GB">Super Video CD</comment>
+ <comment xml:lang="el">Super Video CD</comment>
+ <comment xml:lang="de">Super-Video-CD</comment>
+ <comment xml:lang="da">Super Video-cd</comment>
+ <comment xml:lang="cs">Super Video CD</comment>
+ <comment xml:lang="ca">Super Video CD</comment>
+ <comment xml:lang="bg">CD — супер видео</comment>
+ <comment xml:lang="be@latin">Super Video CD</comment>
+ <comment xml:lang="be">Super Video CD</comment>
+ <comment xml:lang="ast">CD de Super Video</comment>
+ <comment xml:lang="ar">سي دي فيديو فائق</comment>
+ <comment xml:lang="af">Super Video-CD</comment>
<treemagic>
- <treematch type="file" path="MPEG2/AVSEQ01.MPG"/>
+ <treematch path="MPEG2/AVSEQ01.MPG" type="file"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/video-dvd">
-
- <comment>video DVD</comment>
- <comment xml:lang="ar">DVD مرئي</comment>
- <comment xml:lang="ast">DVD de videu</comment>
- <comment xml:lang="be@latin">videa DVD</comment>
- <comment xml:lang="bg">DVD — видео</comment>
- <comment xml:lang="ca">DVD-Video</comment>
- <comment xml:lang="cs">videodisk DVD</comment>
- <comment xml:lang="da">video-dvd</comment>
- <comment xml:lang="de">Video-DVD</comment>
- <comment xml:lang="el">Βίντεο DVD</comment>
- <comment xml:lang="en_GB">video DVD</comment>
- <comment xml:lang="eo">video-DVD</comment>
- <comment xml:lang="es">DVD de vídeo</comment>
- <comment xml:lang="eu">bideo DVDa</comment>
- <comment xml:lang="fi">video-DVD</comment>
- <comment xml:lang="fo">video DVD</comment>
- <comment xml:lang="fr">DVD vidéo</comment>
- <comment xml:lang="ga">DVD físe</comment>
- <comment xml:lang="gl">DVD de vídeo</comment>
- <comment xml:lang="he">DVD וידאו</comment>
- <comment xml:lang="hr">Video DVD</comment>
- <comment xml:lang="hu">video DVD</comment>
- <comment xml:lang="ia">DVD video</comment>
- <comment xml:lang="id">DVD video</comment>
- <comment xml:lang="it">DVD video</comment>
- <comment xml:lang="ja">ビデオ DVD</comment>
- <comment xml:lang="ka">ვიდეო DVD</comment>
- <comment xml:lang="kk">видео DVD</comment>
- <comment xml:lang="ko">동영상 DVD</comment>
- <comment xml:lang="lt">vaizdo DVD</comment>
- <comment xml:lang="lv">video DVD</comment>
- <comment xml:lang="nl">video-DVD</comment>
- <comment xml:lang="nn">Video-DVD</comment>
- <comment xml:lang="oc">DVD vidèo</comment>
- <comment xml:lang="pl">DVD-Video</comment>
- <comment xml:lang="pt">DVD vídeo</comment>
- <comment xml:lang="pt_BR">DVD de vídeo</comment>
- <comment xml:lang="ro">DVD video</comment>
+ <!-- http://en.wikipedia.org/wiki/DVD-Video -->
+ <comment>Video DVD</comment>
+ <comment xml:lang="uk">DVD з відеозаписами</comment>
+ <comment xml:lang="sv">Video-dvd</comment>
<comment xml:lang="ru">Видео DVD</comment>
- <comment xml:lang="sk">DVD-Video</comment>
- <comment xml:lang="sl">video DVD</comment>
- <comment xml:lang="sq">DVD video</comment>
- <comment xml:lang="sr">видео ДВД</comment>
- <comment xml:lang="sv">video-dvd</comment>
- <comment xml:lang="tr">video DVD</comment>
- <comment xml:lang="uk">відео-DVD</comment>
- <comment xml:lang="vi">đĩa DVD ảnh động</comment>
- <comment xml:lang="zh_CN">视频 DVD</comment>
- <comment xml:lang="zh_TW">視訊 DVD</comment>
+ <comment xml:lang="pt_BR">DVD de vídeo</comment>
+ <comment xml:lang="pl">DVD-Video</comment>
+ <comment xml:lang="ja">動画DVD</comment>
+ <comment xml:lang="it">DVD video</comment>
+ <comment xml:lang="gl">DVD de vídeo</comment>
+ <comment xml:lang="eu">Bideoko DVDa</comment>
+ <comment xml:lang="es">DVD de vídeo</comment>
+ <comment xml:lang="de">Video-DVD</comment>
+ <comment xml:lang="be">відэа DVD</comment>
<treemagic>
- <treematch type="file" path="VIDEO_TS/VIDEO_TS.IFO"/>
- <treematch type="file" path="VIDEO_TS/VIDEO_TS.IFO;1"/>
- <treematch type="file" path="VIDEO_TS.IFO"/>
- <treematch type="file" path="VIDEO_TS.IFO;1"/>
+ <treematch path="VIDEO_TS/VIDEO_TS.IFO" type="file"/>
+ <treematch path="VIDEO_TS/VIDEO_TS.IFO;1" type="file"/>
+ <treematch path="VIDEO_TS.IFO" type="file"/>
+ <treematch path="VIDEO_TS.IFO;1" type="file"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/audio-cdda">
-
- <comment>audio CD</comment>
- <comment xml:lang="ar">CD سمعي</comment>
- <comment xml:lang="be@latin">aŭdyjo CD</comment>
- <comment xml:lang="bg">CD — аудио</comment>
- <comment xml:lang="ca">CD d'àudio</comment>
- <comment xml:lang="cs">zvukové CD</comment>
- <comment xml:lang="da">lyd-cd</comment>
- <comment xml:lang="de">Audio-CD</comment>
- <comment xml:lang="el">CD ήχου</comment>
- <comment xml:lang="en_GB">audio CD</comment>
- <comment xml:lang="eo">Son-KD</comment>
- <comment xml:lang="es">CD de sonido</comment>
- <comment xml:lang="eu">Audio CDa</comment>
- <comment xml:lang="fi">ääni-CD</comment>
- <comment xml:lang="fo">audio CD</comment>
- <comment xml:lang="fr">CD audio</comment>
- <comment xml:lang="ga">dlúthdhiosca fuaime</comment>
- <comment xml:lang="gl">CD de son</comment>
- <comment xml:lang="he">תקליטור שמע</comment>
- <comment xml:lang="hr">Glazbeni CD</comment>
- <comment xml:lang="hu">hang CD</comment>
- <comment xml:lang="ia">CD audio</comment>
- <comment xml:lang="id">CD audio</comment>
- <comment xml:lang="it">CD audio</comment>
- <comment xml:lang="ja">オーディオ CD</comment>
- <comment xml:lang="kk">аудио CD</comment>
- <comment xml:lang="ko">오디오 CD</comment>
- <comment xml:lang="lt">garso CD</comment>
- <comment xml:lang="lv">audio CD</comment>
- <comment xml:lang="nl">audio-CD</comment>
- <comment xml:lang="nn">lyd-CD</comment>
- <comment xml:lang="oc">CD àudio</comment>
- <comment xml:lang="pl">CD-Audio</comment>
- <comment xml:lang="pt">CD áudio</comment>
- <comment xml:lang="pt_BR">CD de áudio</comment>
- <comment xml:lang="ro">CD audio</comment>
+ <!-- http://en.wikipedia.org/wiki/Red_Book_(audio_CD_standard) -->
+ <comment>Audio CD</comment>
+ <comment xml:lang="uk">звуковий компакт-диск</comment>
+ <comment xml:lang="sv">Ljud-cd</comment>
<comment xml:lang="ru">Аудио CD</comment>
- <comment xml:lang="sk">Zvukové CD</comment>
- <comment xml:lang="sl">zvočni CD</comment>
- <comment xml:lang="sq">CD audio</comment>
- <comment xml:lang="sr">звучни ЦД</comment>
- <comment xml:lang="sv">ljud-cd</comment>
- <comment xml:lang="tr">Müzik CD'si</comment>
- <comment xml:lang="uk">звуковий CD</comment>
- <comment xml:lang="vi">đĩa CD âm thanh</comment>
- <comment xml:lang="zh_CN">音频 CD</comment>
- <comment xml:lang="zh_TW">音訊 CD</comment>
+ <comment xml:lang="pt_BR">CD de áudio</comment>
+ <comment xml:lang="pl">CD-Audio</comment>
+ <comment xml:lang="ja">音声CD</comment>
+ <comment xml:lang="it">CD audio</comment>
+ <comment xml:lang="gl">CD de son</comment>
+ <comment xml:lang="eu">Audioko CDa</comment>
+ <comment xml:lang="es">CD de audio</comment>
+ <comment xml:lang="de">Audio-CD</comment>
+ <comment xml:lang="be">аўдыя CD</comment>
</mime-type>
-
<mime-type type="x-content/blank-cd">
-
- <comment>blank CD disc</comment>
- <comment xml:lang="ar">قرص CD فارغ</comment>
- <comment xml:lang="be@latin">čysty dysk CD</comment>
- <comment xml:lang="bg">CD — празно</comment>
- <comment xml:lang="ca">disc CD en blanc</comment>
- <comment xml:lang="cs">prázdný disk CD</comment>
- <comment xml:lang="da">tom cd-disk</comment>
- <comment xml:lang="de">Leere CD</comment>
- <comment xml:lang="el">Κενό CD</comment>
- <comment xml:lang="en_GB">blank CD disc</comment>
- <comment xml:lang="es">disco CD en blanco</comment>
- <comment xml:lang="eu">CD disko hutsa</comment>
- <comment xml:lang="fi">tyhjä CD-levy</comment>
- <comment xml:lang="fo">blonk fløga</comment>
- <comment xml:lang="fr">CD vierge</comment>
- <comment xml:lang="ga">dlúthdhiosca folamh</comment>
- <comment xml:lang="gl">disco de CD en brancho</comment>
- <comment xml:lang="he">תקליטור ריק</comment>
- <comment xml:lang="hr">Prazni CD disk</comment>
- <comment xml:lang="hu">üres CD-lemez</comment>
- <comment xml:lang="ia">Disco CD vacue</comment>
- <comment xml:lang="id">cakram CD kosong</comment>
- <comment xml:lang="it">Disco vuoto CD</comment>
- <comment xml:lang="ja">ブランク CD ディスク</comment>
- <comment xml:lang="kk">таза CD дискі</comment>
- <comment xml:lang="ko">빈 CD 디스크</comment>
- <comment xml:lang="lt">tuščias CD diskas</comment>
- <comment xml:lang="lv">tukšs CD disks</comment>
- <comment xml:lang="nl">blanco CD</comment>
- <comment xml:lang="nn">tom CD-plate</comment>
- <comment xml:lang="oc">CD verge</comment>
- <comment xml:lang="pl">Pusta płyta CD</comment>
- <comment xml:lang="pt">CD vazio</comment>
- <comment xml:lang="pt_BR">Disco CD vazio</comment>
- <comment xml:lang="ro">disc gol CD</comment>
- <comment xml:lang="ru">Чистый диск CD</comment>
- <comment xml:lang="sk">Prázdny disk CD</comment>
- <comment xml:lang="sl">prazen CD disk</comment>
- <comment xml:lang="sq">Disk bosh CD</comment>
- <comment xml:lang="sr">празан ЦД диск</comment>
- <comment xml:lang="sv">tom cd-skiva</comment>
- <comment xml:lang="tr">boş CD diski</comment>
+ <!-- http://en.wikipedia.org/wiki/Compact_Disc -->
+ <comment>Blank CD disc</comment>
<comment xml:lang="uk">порожній компакт-диск</comment>
- <comment xml:lang="vi">đĩa CD trống</comment>
- <comment xml:lang="zh_CN">空 CD 光盘</comment>
- <comment xml:lang="zh_TW">空白 CD 光碟</comment>
+ <comment xml:lang="sv">Tom cd-skiva</comment>
+ <comment xml:lang="ru">Чистый диск CD</comment>
+ <comment xml:lang="pt_BR">Disco CD vazio</comment>
+ <comment xml:lang="pl">Pusta płyta CD</comment>
+ <comment xml:lang="ja">空CD</comment>
+ <comment xml:lang="it">Disco vuoto CD</comment>
+ <comment xml:lang="gl">Disco de CD en branco</comment>
+ <comment xml:lang="eu">CD disko hutsa</comment>
+ <comment xml:lang="es">disco CD vacío</comment>
+ <comment xml:lang="de">Leere CD</comment>
+ <comment xml:lang="be">чысты дыск CD</comment>
</mime-type>
-
<mime-type type="x-content/blank-dvd">
-
- <comment>blank DVD disc</comment>
- <comment xml:lang="ar">قرص DVD فارغ</comment>
- <comment xml:lang="be@latin">čysty dysk DVD</comment>
- <comment xml:lang="bg">DVD — празно</comment>
- <comment xml:lang="ca">disc DVD en blanc</comment>
- <comment xml:lang="cs">prázdný disk DVD</comment>
- <comment xml:lang="da">tom dvd-disk</comment>
- <comment xml:lang="de">Leere DVD</comment>
- <comment xml:lang="el">Κενό DVD</comment>
- <comment xml:lang="en_GB">blank DVD disc</comment>
- <comment xml:lang="es">disco DVD en blanco</comment>
- <comment xml:lang="eu">DVD disko hutsa</comment>
- <comment xml:lang="fi">tyhjä DVD-levy</comment>
- <comment xml:lang="fo">blonk margfløga</comment>
- <comment xml:lang="fr">DVD vierge</comment>
- <comment xml:lang="ga">DVD folamh</comment>
- <comment xml:lang="gl">disco de DVD en branco</comment>
- <comment xml:lang="he">תקליטור DVD ריק</comment>
- <comment xml:lang="hr">Prazni DVD disk</comment>
- <comment xml:lang="hu">üres DVD-lemez</comment>
- <comment xml:lang="ia">Disco DVD vacue</comment>
- <comment xml:lang="id">cakram DVD kosong</comment>
- <comment xml:lang="it">Disco vuoto DVD</comment>
- <comment xml:lang="ja">ブランク DVD ディスク</comment>
- <comment xml:lang="kk">таза DVD дискі</comment>
- <comment xml:lang="ko">빈 DVD 디스크</comment>
- <comment xml:lang="lt">tuščias DVD diskas</comment>
- <comment xml:lang="lv">tukšs DVD disks</comment>
- <comment xml:lang="nl">blanco DVD</comment>
- <comment xml:lang="nn">tom DVD-plate</comment>
- <comment xml:lang="oc">DVD verge</comment>
- <comment xml:lang="pl">Pusta płyta DVD</comment>
- <comment xml:lang="pt">DVD vazio</comment>
- <comment xml:lang="pt_BR">Disco DVD vazio</comment>
- <comment xml:lang="ro">disc gol DVD</comment>
- <comment xml:lang="ru">Чистый диск DVD</comment>
- <comment xml:lang="sk">Prázdny disk DVD</comment>
- <comment xml:lang="sl">prazen DVD disk</comment>
- <comment xml:lang="sq">Disk bosh DVD</comment>
- <comment xml:lang="sr">празан ДВД диск</comment>
- <comment xml:lang="sv">tom dvd-skiva</comment>
- <comment xml:lang="tr">boş DVD diski</comment>
+ <!-- http://en.wikipedia.org/wiki/DVD -->
+ <comment>Blank DVD disc</comment>
<comment xml:lang="uk">порожній диск DVD</comment>
- <comment xml:lang="vi">đĩa DVD trống</comment>
- <comment xml:lang="zh_CN">空 DVD 光盘</comment>
- <comment xml:lang="zh_TW">空白 DVD 光碟</comment>
+ <comment xml:lang="sv">Tom dvd-skiva</comment>
+ <comment xml:lang="ru">Чистый диск DVD</comment>
+ <comment xml:lang="pt_BR">Disco DVD vazio</comment>
+ <comment xml:lang="pl">Pusta płyta DVD</comment>
+ <comment xml:lang="ja">空DVD</comment>
+ <comment xml:lang="it">Disco vuoto DVD</comment>
+ <comment xml:lang="gl">Disco de DVD en branco</comment>
+ <comment xml:lang="eu">DVD disko hutsa</comment>
+ <comment xml:lang="es">disco DVD vacío</comment>
+ <comment xml:lang="de">Leere DVD</comment>
+ <comment xml:lang="be">чысты дыск DVD</comment>
</mime-type>
-
<mime-type type="x-content/blank-bd">
-
- <comment>blank Blu-ray disc</comment>
- <comment xml:lang="ar">قرص بلو-راي فارغ</comment>
- <comment xml:lang="be@latin">čysty dysk Blu-ray</comment>
- <comment xml:lang="bg">Blu-ray — празно</comment>
- <comment xml:lang="ca">disc Blu-Ray en blanc</comment>
- <comment xml:lang="cs">prázdný disk Blu-ray</comment>
- <comment xml:lang="da">tom Blu-ray-disk</comment>
- <comment xml:lang="de">Leere Blu-ray-Scheibe</comment>
- <comment xml:lang="el">Κενό Blu-ray</comment>
- <comment xml:lang="en_GB">blank Blu-ray disc</comment>
- <comment xml:lang="es">disco Blu-ray en blanco</comment>
- <comment xml:lang="eu">Blu-ray disko hutsa</comment>
- <comment xml:lang="fi">tyhjä Blu-ray-levy</comment>
- <comment xml:lang="fo">blankur Blu-ray diskur</comment>
- <comment xml:lang="fr">disque Blu-Ray vierge</comment>
- <comment xml:lang="ga">diosca folamh Blu-Ray</comment>
- <comment xml:lang="gl">disco Blu-ray en branco</comment>
- <comment xml:lang="he">תקליטור בלו־ריי ריק</comment>
- <comment xml:lang="hr">Prazni Blu-ray disk</comment>
- <comment xml:lang="hu">üres Blu-Ray lemez</comment>
- <comment xml:lang="ia">Disco Bly-ray vacue</comment>
- <comment xml:lang="id">cakram Blu-ray kosong</comment>
- <comment xml:lang="it">Disco vuoto Blu-ray</comment>
- <comment xml:lang="ja">ブランク Blu-ray ディスク</comment>
- <comment xml:lang="kk">таза Blu-ray дискі</comment>
- <comment xml:lang="ko">빈 블루레이 디스크</comment>
- <comment xml:lang="lt">tuščias Blu-ray diskas</comment>
- <comment xml:lang="lv">tukšs Blu-ray disks</comment>
- <comment xml:lang="nl">blanco Blu-ray-disk</comment>
- <comment xml:lang="nn">tom Blu-Ray-plate</comment>
- <comment xml:lang="oc">disc Blu-Ray verge</comment>
- <comment xml:lang="pl">Pusta płyta Blu-ray</comment>
- <comment xml:lang="pt">Blu-Ray vazio</comment>
- <comment xml:lang="pt_BR">Disco Blu-ray vazio</comment>
- <comment xml:lang="ro">disc gol Blu-ray</comment>
- <comment xml:lang="ru">Чистый диск Blu-ray</comment>
- <comment xml:lang="sk">Prázdny disk Blu-ray</comment>
- <comment xml:lang="sl">prazen Blu-Ray disk</comment>
- <comment xml:lang="sq">Disk bosh Blu-ray</comment>
- <comment xml:lang="sr">празан Блу-реј диск</comment>
- <comment xml:lang="sv">tom Blu-ray-skiva</comment>
- <comment xml:lang="tr">boş Blue-ray diski</comment>
+ <!-- http://en.wikipedia.org/wiki/Blu-ray_Disc -->
+ <comment>Blank Blu-ray disc</comment>
<comment xml:lang="uk">порожній диск Blu-ray</comment>
- <comment xml:lang="vi">đĩa Blu-ray trống</comment>
- <comment xml:lang="zh_CN">空蓝光 DVD</comment>
- <comment xml:lang="zh_TW">空白 Blu-ray 光碟</comment>
+ <comment xml:lang="sv">Tom Blu-ray-skiva</comment>
+ <comment xml:lang="ru">Чистый диск Blu-ray</comment>
+ <comment xml:lang="pt_BR">Disco Blu-ray vazio</comment>
+ <comment xml:lang="pl">Pusta płyta Blu-ray</comment>
+ <comment xml:lang="it">Disco vuoto Blu-ray</comment>
+ <comment xml:lang="gl">Disco Blu-ray en branco</comment>
+ <comment xml:lang="eu">Blu-ray disko hutsa</comment>
+ <comment xml:lang="es">disco Blu-ray vacío</comment>
+ <comment xml:lang="de">Leere Blu-ray</comment>
+ <comment xml:lang="be">чысты дыск Blu-ray</comment>
</mime-type>
-
<mime-type type="x-content/blank-hddvd">
-
- <comment>blank HD DVD disc</comment>
- <comment xml:lang="ar">قرص HD DVD فارغ</comment>
- <comment xml:lang="be@latin">čysty dysk HD DVD</comment>
- <comment xml:lang="bg">HD DVD — празно</comment>
- <comment xml:lang="ca">disc HD-DVD en blanc</comment>
- <comment xml:lang="cs">prázdný disk HD DVD</comment>
- <comment xml:lang="da">tom HD dvd-disk</comment>
- <comment xml:lang="de">Leere HD-DVD</comment>
- <comment xml:lang="el">Κενό HD DVD</comment>
- <comment xml:lang="en_GB">blank HD DVD disc</comment>
- <comment xml:lang="es">disco HD DVD en blanco</comment>
- <comment xml:lang="eu">HD DVD disko hutsa</comment>
- <comment xml:lang="fi">tyhjä HD DVD -levy</comment>
- <comment xml:lang="fo">blankur HD DVD diskur</comment>
- <comment xml:lang="fr">disque HD-DVD vierge</comment>
- <comment xml:lang="ga">HD DVD folamh</comment>
- <comment xml:lang="gl">disco de HD DVD en branco</comment>
- <comment xml:lang="he">דיסק HD DVD ריק</comment>
- <comment xml:lang="hr">Prazni HD DVD disk</comment>
- <comment xml:lang="hu">üres HD DVD-lemez</comment>
- <comment xml:lang="ia">Disco HD DVD vacue</comment>
- <comment xml:lang="id">cakram HD DVD kosong</comment>
- <comment xml:lang="it">Disco vuoto DVD HD</comment>
- <comment xml:lang="ja">ブランク HD DVD ディスク</comment>
- <comment xml:lang="kk">таза HD DVD дискі</comment>
- <comment xml:lang="ko">빈 HD DVD 디스크</comment>
- <comment xml:lang="lt">tuščias HD DVD diskas</comment>
- <comment xml:lang="lv">tukšs HD DVD disks</comment>
- <comment xml:lang="nl">blanco HD-DVD</comment>
- <comment xml:lang="nn">tom HD-DVD-plate</comment>
- <comment xml:lang="oc">disc HD-DVD verge</comment>
- <comment xml:lang="pl">Pusta płyta HD DVD</comment>
- <comment xml:lang="pt">HD DVD vazio</comment>
- <comment xml:lang="pt_BR">Disco HD DVD vazio</comment>
- <comment xml:lang="ro">disc gol HD DVD</comment>
- <comment xml:lang="ru">Чистый диск HD DVD</comment>
- <comment xml:lang="sk">Prázdny disk HD DVD</comment>
- <comment xml:lang="sl">prazen HD DVD disk</comment>
- <comment xml:lang="sq">Disk bosh DVD HD</comment>
- <comment xml:lang="sr">празан ХД ДВД диск</comment>
- <comment xml:lang="sv">tom HD DVD-skiva</comment>
- <comment xml:lang="tr">boş HD DVD diski</comment>
+ <!-- http://en.wikipedia.org/wiki/HD_DVD -->
+ <comment>Blank HD DVD disc</comment>
<comment xml:lang="uk">порожній диск HD DVD</comment>
- <comment xml:lang="vi">đĩa DVD HD trống</comment>
- <comment xml:lang="zh_CN">空 HD DVD 光盘</comment>
- <comment xml:lang="zh_TW">空白 HD DVD 光碟</comment>
+ <comment xml:lang="sv">Tom HD DVD-skiva</comment>
+ <comment xml:lang="ru">Чистый диск HD DVD</comment>
+ <comment xml:lang="pt_BR">Disco HD DVD vazio</comment>
+ <comment xml:lang="pl">Pusta płyta HD DVD</comment>
+ <comment xml:lang="it">Disco vuoto DVD HD</comment>
+ <comment xml:lang="gl">Disco de HD DVD en branco</comment>
+ <comment xml:lang="eu">HD DVD disko hutsa</comment>
+ <comment xml:lang="es">disco HD DVD vacío</comment>
+ <comment xml:lang="de">Leere HD-DVD</comment>
+ <comment xml:lang="be">чысты дыск HD DVD</comment>
</mime-type>
-
<mime-type type="x-content/audio-dvd">
-
- <comment>audio DVD</comment>
- <comment xml:lang="ar">DVD سمعي</comment>
- <comment xml:lang="be@latin">aŭdyjo DVD</comment>
- <comment xml:lang="bg">DVD — аудио</comment>
- <comment xml:lang="ca">DVD d'àudio</comment>
- <comment xml:lang="cs">zvukové DVD</comment>
- <comment xml:lang="da">lyd-dvd</comment>
- <comment xml:lang="de">Audio-DVD</comment>
- <comment xml:lang="el">DVD ήχου</comment>
- <comment xml:lang="en_GB">audio DVD</comment>
- <comment xml:lang="eo">Son-DVD</comment>
- <comment xml:lang="es">DVD de sonido</comment>
- <comment xml:lang="eu">audio DVDa</comment>
- <comment xml:lang="fi">ääni-DVD</comment>
- <comment xml:lang="fo">Ljóð DVD</comment>
- <comment xml:lang="fr">DVD audio</comment>
- <comment xml:lang="ga">DVD fuaime</comment>
- <comment xml:lang="gl">DVD de son</comment>
- <comment xml:lang="he">DVD שמע</comment>
- <comment xml:lang="hr">Glazbeni DVD</comment>
- <comment xml:lang="hu">hang DVD</comment>
- <comment xml:lang="ia">DVD audio</comment>
- <comment xml:lang="id">DVD audio</comment>
- <comment xml:lang="it">DVD audio</comment>
- <comment xml:lang="ja">オーディオ DVD</comment>
- <comment xml:lang="kk">аудио DVD</comment>
- <comment xml:lang="ko">오디오 DVD</comment>
- <comment xml:lang="lt">garso DVD</comment>
- <comment xml:lang="lv">audio DVD</comment>
- <comment xml:lang="nl">audio-DVD</comment>
- <comment xml:lang="nn">lyd-DVD</comment>
- <comment xml:lang="oc">DVD àudio</comment>
- <comment xml:lang="pl">DVD-Audio</comment>
- <comment xml:lang="pt">DVD áudio</comment>
- <comment xml:lang="pt_BR">DVD de áudio</comment>
- <comment xml:lang="ro">DVD audio</comment>
+ <!-- http://en.wikipedia.org/wiki/DVD-Audio -->
+ <comment>Audio DVD</comment>
+ <comment xml:lang="uk">Звуковий DVD</comment>
+ <comment xml:lang="sv">Ljud-dvd</comment>
<comment xml:lang="ru">Аудио DVD</comment>
- <comment xml:lang="sk">Zvukové DVD</comment>
- <comment xml:lang="sl">zvočni DVD</comment>
- <comment xml:lang="sq">DVD audio</comment>
- <comment xml:lang="sr">звучни ДВД</comment>
- <comment xml:lang="sv">ljud-dvd</comment>
- <comment xml:lang="tr">Müzik DVD'si</comment>
- <comment xml:lang="uk">звуковий DVD</comment>
- <comment xml:lang="vi">đĩa DVD âm thanh</comment>
- <comment xml:lang="zh_CN">音频 DVD</comment>
- <comment xml:lang="zh_TW">音訊 DVD</comment>
+ <comment xml:lang="pt_BR">DVD de áudio</comment>
+ <comment xml:lang="pl">DVD-Audio</comment>
+ <comment xml:lang="it">DVD audio</comment>
+ <comment xml:lang="gl">DVD de son</comment>
+ <comment xml:lang="eu">Audioko DVDa</comment>
+ <comment xml:lang="es">DVD de audio</comment>
+ <comment xml:lang="de">Audio-DVD</comment>
+ <comment xml:lang="be">аўдыя DVD</comment>
<treemagic>
- <treematch type="file" path="AUDIO_TS/AUDIO_TS.IFO"/>
- <treematch type="file" path="AUDIO_TS/AUDIO_TS.IFO;1"/>
+ <treematch path="AUDIO_TS/AUDIO_TS.IFO" type="file"/>
+ <treematch path="AUDIO_TS/AUDIO_TS.IFO;1" type="file"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/video-bluray">
-
+ <!-- http://en.wikipedia.org/wiki/Blu-ray_Disc
+ http://www.blu-raydisc.com/Section-13470/Section-13890/Index.html -->
<comment>Blu-ray video disc</comment>
- <comment xml:lang="ar">قرص بلو-راي مرئي</comment>
- <comment xml:lang="ast">Discu Blu-ray de videu</comment>
- <comment xml:lang="be@latin">Videadysk Blu-ray</comment>
- <comment xml:lang="bg">Blu-ray — видео</comment>
- <comment xml:lang="ca">disc de vídeo Blu-Ray</comment>
- <comment xml:lang="cs">videodisk Blu-ray</comment>
- <comment xml:lang="da">Blu-ray video-disk</comment>
- <comment xml:lang="de">Blu-ray-Videoscheibe</comment>
- <comment xml:lang="el">Δίσκος βίντεο Blu-ray</comment>
- <comment xml:lang="en_GB">Blu-ray video disc</comment>
- <comment xml:lang="es">disco de vídeo Blu-ray</comment>
- <comment xml:lang="eu">Blu-ray bideo-diskoa</comment>
- <comment xml:lang="fi">Blu-ray-videolevy</comment>
- <comment xml:lang="fo">Blu-ray diskur</comment>
- <comment xml:lang="fr">disque vidéo Blu-Ray</comment>
- <comment xml:lang="ga">diosca físe Blu-Ray</comment>
- <comment xml:lang="gl">disco de vídeo Blu-ray</comment>
- <comment xml:lang="he">תקליטור וידאו מסוג בלו־ריי</comment>
- <comment xml:lang="hr">Blu-ray video disk</comment>
- <comment xml:lang="hu">Blu-ray videolemez</comment>
- <comment xml:lang="ia">Disco video Blu-ray</comment>
- <comment xml:lang="id">Cakram video Blu-ray</comment>
- <comment xml:lang="it">Disco video Blu-ray</comment>
- <comment xml:lang="ja">Blu-ray ビデオディスク</comment>
- <comment xml:lang="ka">Blu-ray ვიდეო დისკი</comment>
- <comment xml:lang="kk">Blu-ray видео дискі</comment>
- <comment xml:lang="ko">블루레이 동영상 디스크</comment>
- <comment xml:lang="lt">Blu-ray vaizdo diskas</comment>
- <comment xml:lang="lv">Blu-ray video disks</comment>
- <comment xml:lang="nl">Blu-ray-videodisk</comment>
- <comment xml:lang="nn">Blu-Ray videoplate</comment>
- <comment xml:lang="oc">disc vidèo Blu-Ray</comment>
- <comment xml:lang="pl">Płyta wideo Blu-ray</comment>
- <comment xml:lang="pt">Blu-ray de vídeo</comment>
- <comment xml:lang="pt_BR">Disco de vídeo Blu-ray</comment>
- <comment xml:lang="ro">Disc video Blu-ray</comment>
- <comment xml:lang="ru">Видеодиск Blu-ray</comment>
- <comment xml:lang="sk">Videodisk Blu-ray</comment>
- <comment xml:lang="sl">Blu-ray video disk</comment>
- <comment xml:lang="sq">Disk video Blu-ray</comment>
- <comment xml:lang="sr">Блу-реј видео диск</comment>
- <comment xml:lang="sv">Blu-ray-videoskiva</comment>
- <comment xml:lang="tr">Blu-ray video diski</comment>
- <comment xml:lang="uk">відеодиск Blu-ray</comment>
- <comment xml:lang="vi">Đĩa ảnh động Blu-ray</comment>
- <comment xml:lang="zh_CN">蓝光视频光盘</comment>
<comment xml:lang="zh_TW">Blu-ray 視訊光碟</comment>
+ <comment xml:lang="zh_CN">蓝光视频光盘</comment>
+ <comment xml:lang="vi">Đĩa ảnh động Blu-ray</comment>
+ <comment xml:lang="uk">відеодиск Blu-ray</comment>
+ <comment xml:lang="tr">Blu-ray video diski</comment>
+ <comment xml:lang="sv">Blu-ray-videoskiva</comment>
+ <comment xml:lang="sr">Блу-реј видео диск</comment>
+ <comment xml:lang="sq">disk video Blu-ray</comment>
+ <comment xml:lang="sl">Blu-ray video disk</comment>
+ <comment xml:lang="si">Blu-ray වීඩියෝ තැටිය</comment>
+ <comment xml:lang="sk">Videodisk Blu-ray</comment>
+ <comment xml:lang="ru">Видеодиск Blu-ray</comment>
+ <comment xml:lang="ro">Disc video Blu-ray</comment>
+ <comment xml:lang="pt_BR">Disco de vídeo Blu-ray</comment>
+ <comment xml:lang="pt">Blu-ray de vídeo</comment>
+ <comment xml:lang="pl">Płyta wideo Blu-ray</comment>
+ <comment xml:lang="oc">disc vidèo Blu-Ray</comment>
+ <comment xml:lang="nn">Blu-Ray videoplate</comment>
+ <comment xml:lang="nl">Blu-ray-videodisk</comment>
+ <comment xml:lang="lv">Blu-ray video disks</comment>
+ <comment xml:lang="lt">Blu-ray vaizdo diskas</comment>
+ <comment xml:lang="ko">블루레이 동영상 디스크</comment>
+ <comment xml:lang="kk">Blu-ray видео дискі</comment>
+ <comment xml:lang="ka">Blu-ray ვიდეო დისკი</comment>
+ <comment xml:lang="ja">Blu-ray ビデオディスク</comment>
+ <comment xml:lang="it">Disco video Blu-ray</comment>
+ <comment xml:lang="is">Blu-Ray mynddiskur</comment>
+ <comment xml:lang="id">Cakram video Blu-ray</comment>
+ <comment xml:lang="ia">Disco video Blu-ray</comment>
+ <comment xml:lang="hu">Blu-ray videolemez</comment>
+ <comment xml:lang="hr">Blu-ray video disk</comment>
+ <comment xml:lang="he">תקליטור וידאו מסוג בלו־ריי</comment>
+ <comment xml:lang="gl">disco de vídeo Blu-ray</comment>
+ <comment xml:lang="ga">diosca físe Blu-Ray</comment>
+ <comment xml:lang="fur">disc video Blu-ray</comment>
+ <comment xml:lang="fr">disque vidéo Blu-Ray</comment>
+ <comment xml:lang="fo">Blu-ray diskur</comment>
+ <comment xml:lang="fi">Blu-ray-videolevy</comment>
+ <comment xml:lang="eu">Blu-ray bideo-diskoa</comment>
+ <comment xml:lang="es">disco de vídeo Blu-ray</comment>
+ <comment xml:lang="en_GB">Blu-ray video disc</comment>
+ <comment xml:lang="el">Δίσκος βίντεο Blu-ray</comment>
+ <comment xml:lang="de">Blu-ray-Video</comment>
+ <comment xml:lang="da">Blu-ray-videodisk</comment>
+ <comment xml:lang="cs">videodisk Blu-ray</comment>
+ <comment xml:lang="ca">disc de vídeo Blu-Ray</comment>
+ <comment xml:lang="bg">Blu-ray — видео</comment>
+ <comment xml:lang="be@latin">Videadysk Blu-ray</comment>
+ <comment xml:lang="be">відэадыск Blu-ray</comment>
+ <comment xml:lang="ast">Discu Blu-ray de videu</comment>
+ <comment xml:lang="ar">قرص فيديو بلو-راي</comment>
+ <comment xml:lang="af">Blu-ray-videoskyf</comment>
<treemagic>
- <treematch type="directory" path="BDAV" non-empty="true"/>
- <treematch type="directory" path="BDMV" non-empty="true"/>
+ <treematch path="BDAV" type="directory" non-empty="true"/>
+ <treematch path="BDMV" type="directory" non-empty="true"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/video-hddvd">
-
+ <!-- http://en.wikipedia.org/wiki/HD_DVD
+ http://www.dvdafteredit.com/wiki/The_HVDVD_TS_Folder -->
<comment>HD DVD video disc</comment>
- <comment xml:lang="ar">قرص HD DVD مرئي</comment>
- <comment xml:lang="ast">Discu HD DVD de videu</comment>
- <comment xml:lang="be@latin">Videadysk HD DVD</comment>
- <comment xml:lang="bg">HD DVD — видео</comment>
- <comment xml:lang="ca">disc de vídeo HD-DVD</comment>
- <comment xml:lang="cs">Videodisk HD DVD</comment>
- <comment xml:lang="da">HD DVD-videodisk</comment>
- <comment xml:lang="de">HD-DVD-Videoscheibe</comment>
- <comment xml:lang="el">Δίσκος βίντεο HD DVD</comment>
- <comment xml:lang="en_GB">HD DVD video disc</comment>
- <comment xml:lang="es">disco de vídeo HD DVD</comment>
- <comment xml:lang="eu">HD DVD bideo-diskoa</comment>
- <comment xml:lang="fi">HD DVD -videolevy</comment>
- <comment xml:lang="fo">HD DVD video diskur</comment>
- <comment xml:lang="fr">disque vidéo HD DVD</comment>
- <comment xml:lang="ga">diosca físe HD DVD</comment>
- <comment xml:lang="gl">disco de vídeo HD DVD</comment>
- <comment xml:lang="he">תקליטור וידאו HD DVD</comment>
- <comment xml:lang="hr">HD DVD video disk</comment>
- <comment xml:lang="hu">HD DVD videolemez</comment>
- <comment xml:lang="ia">Disco video HD DVD</comment>
- <comment xml:lang="id">Cakram video HD DVD</comment>
- <comment xml:lang="it">Disco video DVD HD</comment>
- <comment xml:lang="ja">HD DVD ビデオディスク</comment>
- <comment xml:lang="kk">HD DVD видео дискі</comment>
- <comment xml:lang="ko">HD DVD 동영상 디스크</comment>
- <comment xml:lang="lt">HD DVD vaizdo diskas</comment>
- <comment xml:lang="lv">HD DVD video disks</comment>
- <comment xml:lang="nl">HD-DVD-videodisk</comment>
- <comment xml:lang="nn">HD-DVD-videodisk</comment>
- <comment xml:lang="oc">disc vidèo HD DVD</comment>
- <comment xml:lang="pl">Płyta wideo HD DVD</comment>
- <comment xml:lang="pt">HD DVD de vídeo</comment>
- <comment xml:lang="pt_BR">Disco de vídeo HD DVD</comment>
- <comment xml:lang="ro">Disc video HD DVD</comment>
- <comment xml:lang="ru">Видеодиск HD DVD</comment>
- <comment xml:lang="sk">Videodisk HD DVD</comment>
- <comment xml:lang="sl">HD DVD video disk</comment>
- <comment xml:lang="sq">Disk video DVD HD</comment>
- <comment xml:lang="sr">ХД ДВД видео диск</comment>
- <comment xml:lang="sv">HD DVD-videoskiva</comment>
- <comment xml:lang="tr">HD DVD vidyo diski</comment>
- <comment xml:lang="uk">відеодиск HD DVD</comment>
- <comment xml:lang="vi">Đĩa ảnh động DVD HD</comment>
- <comment xml:lang="zh_CN">HD DVD 视频光盘</comment>
<comment xml:lang="zh_TW">HD DVD 視訊光碟</comment>
+ <comment xml:lang="zh_CN">HD DVD 视频光盘</comment>
+ <comment xml:lang="vi">Đĩa ảnh động DVD HD</comment>
+ <comment xml:lang="uk">відеодиск HD DVD</comment>
+ <comment xml:lang="tr">HD DVD vidyo diski</comment>
+ <comment xml:lang="sv">HD DVD-videoskiva</comment>
+ <comment xml:lang="sr">ХД ДВД видео диск</comment>
+ <comment xml:lang="sq">disk video DVD HD</comment>
+ <comment xml:lang="sl">HD DVD video disk</comment>
+ <comment xml:lang="si">HD DVD වීඩියෝ තැටිය</comment>
+ <comment xml:lang="sk">Videodisk HD DVD</comment>
+ <comment xml:lang="ru">Видеодиск HD DVD</comment>
+ <comment xml:lang="ro">Disc video HD DVD</comment>
+ <comment xml:lang="pt_BR">Disco de vídeo HD DVD</comment>
+ <comment xml:lang="pt">HD DVD de vídeo</comment>
+ <comment xml:lang="pl">Płyta wideo HD DVD</comment>
+ <comment xml:lang="oc">disc vidèo HD DVD</comment>
+ <comment xml:lang="nn">HD-DVD-videodisk</comment>
+ <comment xml:lang="nl">HD-DVD-videodisk</comment>
+ <comment xml:lang="lv">HD DVD video disks</comment>
+ <comment xml:lang="lt">HD DVD vaizdo diskas</comment>
+ <comment xml:lang="ko">HD DVD 동영상 디스크</comment>
+ <comment xml:lang="kk">HD DVD видео дискі</comment>
+ <comment xml:lang="ka">HD DVD ვიდეო დისკი</comment>
+ <comment xml:lang="ja">HD DVD ビデオディスク</comment>
+ <comment xml:lang="it">Disco video DVD HD</comment>
+ <comment xml:lang="is">HD DVD mynddiskur</comment>
+ <comment xml:lang="id">Cakram video HD DVD</comment>
+ <comment xml:lang="ia">Disco video HD DVD</comment>
+ <comment xml:lang="hu">HD DVD videolemez</comment>
+ <comment xml:lang="hr">HD DVD video disk</comment>
+ <comment xml:lang="he">תקליטור וידאו HD DVD</comment>
+ <comment xml:lang="gl">disco de vídeo HD DVD</comment>
+ <comment xml:lang="ga">diosca físe HD DVD</comment>
+ <comment xml:lang="fur">disc video HD DVD</comment>
+ <comment xml:lang="fr">disque vidéo HD DVD</comment>
+ <comment xml:lang="fo">HD DVD video diskur</comment>
+ <comment xml:lang="fi">HD DVD -videolevy</comment>
+ <comment xml:lang="eu">HD DVD bideo-diskoa</comment>
+ <comment xml:lang="es">disco de vídeo HD DVD</comment>
+ <comment xml:lang="en_GB">HD DVD video disc</comment>
+ <comment xml:lang="el">Δίσκος βίντεο HD DVD</comment>
+ <comment xml:lang="de">HD-DVD-Video</comment>
+ <comment xml:lang="da">HD DVD-videodisk</comment>
+ <comment xml:lang="cs">Videodisk HD DVD</comment>
+ <comment xml:lang="ca">disc de vídeo HD-DVD</comment>
+ <comment xml:lang="bg">HD DVD — видео</comment>
+ <comment xml:lang="be@latin">Videadysk HD DVD</comment>
+ <comment xml:lang="be">відэадыск HD DVD</comment>
+ <comment xml:lang="ast">Discu HD DVD de videu</comment>
+ <comment xml:lang="ar">قرص فيديو HD DVD</comment>
+ <comment xml:lang="af">HD-DVD-videoskyf</comment>
<treemagic>
- <treematch type="file" path="HVDVD_TS/HV000I01.IFO"/>
- <treematch type="file" path="HVDVD_TS/HV001I01.IFO"/>
- <treematch type="file" path="HVDVD_TS/HVA00001.VTI"/>
+ <treematch path="HVDVD_TS/HV000I01.IFO" type="file"/>
+ <treematch path="HVDVD_TS/HV001I01.IFO" type="file"/>
+ <treematch path="HVDVD_TS/HVA00001.VTI" type="file"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/ebook-reader">
-
- <comment>e-book reader</comment>
- <comment xml:lang="bg">Четец на е-книги</comment>
- <comment xml:lang="ca">lector de llibres electrònics</comment>
- <comment xml:lang="cs">čtečka elektronických knih</comment>
- <comment xml:lang="da">e-bogslæser</comment>
- <comment xml:lang="de">E-Book-Leser</comment>
- <comment xml:lang="el">Αναγνώστης ηλεκτρονικών βιβλίων</comment>
- <comment xml:lang="en_GB">e-book reader</comment>
- <comment xml:lang="es">lector de libros electrónicos</comment>
- <comment xml:lang="eu">e-book irakurlea</comment>
- <comment xml:lang="fi">e-kirjan lukulaite</comment>
- <comment xml:lang="fr">lecteur de livre numérique</comment>
- <comment xml:lang="ga">léitheoir r-leabhair</comment>
- <comment xml:lang="gl">lector de libros electrónicos</comment>
- <comment xml:lang="he">קורא ספרים אלקטרוניים</comment>
- <comment xml:lang="hr">Čitač e-knjiga</comment>
- <comment xml:lang="hu">e-könyvolvasó</comment>
- <comment xml:lang="ia">Lector de libro electronic</comment>
- <comment xml:lang="id">Pembaca e-book</comment>
- <comment xml:lang="it">Lettore e-book</comment>
- <comment xml:lang="ja">電子書籍リーダー</comment>
- <comment xml:lang="kk">электронды кітаптарды оқу құрылғысы</comment>
- <comment xml:lang="ko">전자책 리더</comment>
- <comment xml:lang="lv">e-grāmatu lasītājs</comment>
- <comment xml:lang="nl">e-book reader</comment>
- <comment xml:lang="oc">lector de libre numeric</comment>
- <comment xml:lang="pl">Czytnik e-booków</comment>
- <comment xml:lang="pt">leitor de ebooks</comment>
- <comment xml:lang="pt_BR">Leitor de e-book</comment>
+ <!-- see fd.o hal spec -->
+ <comment>E-book reader</comment>
+ <comment xml:lang="uk">пристрій для читання ел. книг</comment>
+ <comment xml:lang="sv">E-bokläsare</comment>
<comment xml:lang="ru">Устройство для чтения электронных книг</comment>
- <comment xml:lang="sk">Čítačka e-kníh</comment>
- <comment xml:lang="sl">Bralnik elektronskih knjig</comment>
- <comment xml:lang="sr">читач ел. књига</comment>
- <comment xml:lang="sv">e-bokläsare</comment>
- <comment xml:lang="tr">e-kitap okuyucu</comment>
- <comment xml:lang="uk">пристрій для читання електронних книг</comment>
- <comment xml:lang="zh_CN">电子书阅读器</comment>
- <comment xml:lang="zh_TW">e-book 閱讀器</comment>
+ <comment xml:lang="pt_BR">Leitor de e-book</comment>
+ <comment xml:lang="pl">Czytnik e-booków</comment>
+ <comment xml:lang="ja">電子書籍閲覧機</comment>
+ <comment xml:lang="it">Lettore e-book</comment>
+ <comment xml:lang="gl">Lector de libros electrónicos</comment>
+ <comment xml:lang="es">lector de libros electrónicos</comment>
+ <comment xml:lang="de">E-Book-Reader</comment>
+ <comment xml:lang="be">электронная кніга</comment>
<treemagic>
- <treematch type="directory" path=".kobo" non-empty="true"/>
+ <treematch path=".kobo" type="directory" non-empty="true"/>
<treematch path="system/com.amazon.ebook.booklet.reader" non-empty="false"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/image-picturecd">
-
+ <!-- TRANSLATORS: This is a brand-name, not a generic term. Please see
+ http://en.wikipedia.org/wiki/Picture_CD
+ http://www.re.org/kristin/picturecd.html -->
<comment>Picture CD</comment>
- <comment xml:lang="ar">Picture CD</comment>
- <comment xml:lang="be@latin">Picture CD</comment>
- <comment xml:lang="bg">CD — изображения</comment>
- <comment xml:lang="ca">Picture CD</comment>
- <comment xml:lang="cs">Picture CD</comment>
- <comment xml:lang="da">Billedcd</comment>
- <comment xml:lang="de">Picture CD</comment>
- <comment xml:lang="el">CD εικόνων</comment>
- <comment xml:lang="en_GB">Picture CD</comment>
- <comment xml:lang="es">Picture CD</comment>
- <comment xml:lang="eu">Picture CD</comment>
- <comment xml:lang="fi">Picture CD</comment>
- <comment xml:lang="fo">Picture CD</comment>
- <comment xml:lang="fr">CD Picture</comment>
- <comment xml:lang="ga">dlúthdhiosca grianghraf</comment>
- <comment xml:lang="gl">Picture CD</comment>
- <comment xml:lang="he">תקליטור תמונות</comment>
- <comment xml:lang="hr">Slikovni CD</comment>
- <comment xml:lang="hu">Picture CD</comment>
- <comment xml:lang="ia">Disco Picture CD</comment>
- <comment xml:lang="id">CD Gambar</comment>
- <comment xml:lang="it">Picture CD</comment>
- <comment xml:lang="ja">ピクチャー CD</comment>
- <comment xml:lang="kk">Picture CD</comment>
- <comment xml:lang="ko">Picture CD</comment>
- <comment xml:lang="lt">Paveikslėlių CD</comment>
- <comment xml:lang="lv">Attēlu CD</comment>
- <comment xml:lang="nl">foto-CD</comment>
- <comment xml:lang="nn">Bilete-CD</comment>
- <comment xml:lang="oc">CD Picture</comment>
- <comment xml:lang="pl">Picture CD</comment>
- <comment xml:lang="pt">Picture CD</comment>
- <comment xml:lang="pt_BR">CD de Fotos</comment>
- <comment xml:lang="ro">CD cu fotografii</comment>
- <comment xml:lang="ru">Picture CD</comment>
- <comment xml:lang="sk">Picture CD</comment>
- <comment xml:lang="sl">Slikovni CD</comment>
- <comment xml:lang="sq">Picture CD</comment>
- <comment xml:lang="sr">ЦД са сликама</comment>
- <comment xml:lang="sv">Picture CD</comment>
- <comment xml:lang="tr">Resim CD'si</comment>
- <comment xml:lang="uk">CD з зображеннями</comment>
- <comment xml:lang="vi">Đĩa CD ảnh</comment>
- <comment xml:lang="zh_CN">柯达 Picture CD</comment>
<comment xml:lang="zh_TW">圖片 CD</comment>
+ <comment xml:lang="zh_CN">柯达 Picture CD</comment>
+ <comment xml:lang="vi">Đĩa CD ảnh</comment>
+ <comment xml:lang="uk">CD з зображеннями</comment>
+ <comment xml:lang="tr">Resim CD'si</comment>
+ <comment xml:lang="sv">Picture CD</comment>
+ <comment xml:lang="sr">ЦД са сликама</comment>
+ <comment xml:lang="sq">Picture CD</comment>
+ <comment xml:lang="sl">Slikovni CD</comment>
+ <comment xml:lang="si">පින්තූර සීඩී</comment>
+ <comment xml:lang="sk">Picture CD</comment>
+ <comment xml:lang="ru">Picture CD</comment>
+ <comment xml:lang="ro">CD cu fotografii</comment>
+ <comment xml:lang="pt_BR">CD de Fotos</comment>
+ <comment xml:lang="pt">Picture CD</comment>
+ <comment xml:lang="pl">Picture CD</comment>
+ <comment xml:lang="oc">CD Picture</comment>
+ <comment xml:lang="nn">Bilete-CD</comment>
+ <comment xml:lang="nl">Picture CD</comment>
+ <comment xml:lang="lv">Attēlu CD</comment>
+ <comment xml:lang="lt">Paveikslėlių CD</comment>
+ <comment xml:lang="ko">Picture CD</comment>
+ <comment xml:lang="kk">Picture CD</comment>
+ <comment xml:lang="ka">ფოტო სურათებიანი CD</comment>
+ <comment xml:lang="ja">ピクチャー CD</comment>
+ <comment xml:lang="it">Picture CD</comment>
+ <comment xml:lang="is">Picture CD-mynddiskur</comment>
+ <comment xml:lang="id">CD Gambar</comment>
+ <comment xml:lang="ia">Disco Picture CD</comment>
+ <comment xml:lang="hu">Picture CD</comment>
+ <comment xml:lang="hr">Slikovni CD</comment>
+ <comment xml:lang="he">תקליטור תמונות</comment>
+ <comment xml:lang="gl">Picture CD</comment>
+ <comment xml:lang="ga">dlúthdhiosca grianghraf</comment>
+ <comment xml:lang="fur">Picture CD</comment>
+ <comment xml:lang="fr">CD Picture</comment>
+ <comment xml:lang="fo">Picture CD</comment>
+ <comment xml:lang="fi">Picture CD</comment>
+ <comment xml:lang="eu">Picture CD</comment>
+ <comment xml:lang="es">Picture CD</comment>
+ <comment xml:lang="en_GB">Picture CD</comment>
+ <comment xml:lang="el">CD εικόνων</comment>
+ <comment xml:lang="de">Kodak Picture-CD</comment>
+ <comment xml:lang="da">Billedcd</comment>
+ <comment xml:lang="cs">Picture CD</comment>
+ <comment xml:lang="ca">CD d'imatges</comment>
+ <comment xml:lang="bg">Picture CD — изображения</comment>
+ <comment xml:lang="be@latin">Picture CD</comment>
+ <comment xml:lang="be">Picture CD</comment>
+ <comment xml:lang="ar">سي دي صورة</comment>
+ <comment xml:lang="af">Picture CD</comment>
<treemagic>
- <treematch type="directory" path="PICTURES" non-empty="true" match-case="true"/>
+ <treematch path="PICTURES" type="directory" non-empty="true" match-case="true"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/audio-player">
-
- <comment>portable audio player</comment>
- <comment xml:lang="ar">مشغل الملفات المسموعة المحمولة</comment>
- <comment xml:lang="be@latin">pieranosny aŭdyjoplayer</comment>
- <comment xml:lang="bg">Преносим аудио плеър</comment>
- <comment xml:lang="ca">reproductor d'àudio portàtil</comment>
- <comment xml:lang="cs">přenosný zvukový přehrávač</comment>
- <comment xml:lang="da">bærbar lydafspiller</comment>
- <comment xml:lang="de">Portables Audio-Wiedergabegerät</comment>
- <comment xml:lang="el">Φορητός αναπαραγωγέας μουσικής</comment>
- <comment xml:lang="en_GB">portable audio player</comment>
- <comment xml:lang="es">dispositivo de sonido portátil</comment>
- <comment xml:lang="eu">audio erreproduzigailu eramangarria</comment>
- <comment xml:lang="fi">siirrettävä äänisoitin</comment>
- <comment xml:lang="fo">leysur ljóðavspælari</comment>
- <comment xml:lang="fr">lecteur audio portable</comment>
- <comment xml:lang="ga">seinnteoir iniompartha fuaime</comment>
- <comment xml:lang="gl">dispositivo de son portábel</comment>
- <comment xml:lang="he">נגן מוזיקה נייד</comment>
- <comment xml:lang="hr">Prenosivi glazbeni svirač</comment>
- <comment xml:lang="hu">hordozható zenelejátszó</comment>
- <comment xml:lang="ia">Lector audio portabile</comment>
- <comment xml:lang="id">pemutar audio portable</comment>
- <comment xml:lang="it">Lettore audio portabile</comment>
- <comment xml:lang="ja">ポータブルオーディオプレイヤー</comment>
- <comment xml:lang="kk">тасымалы аудио плеер</comment>
- <comment xml:lang="ko">휴대용 오디오 재생기</comment>
- <comment xml:lang="lt">nešiojamasis garso leistuvas</comment>
- <comment xml:lang="lv">portatīvais audio atskaņotājs</comment>
- <comment xml:lang="nl">draagbare audiospeler</comment>
- <comment xml:lang="nn">portable audio layer</comment>
- <comment xml:lang="oc">lector àudio portable</comment>
- <comment xml:lang="pl">Przenośny odtwarzacz dźwięku</comment>
- <comment xml:lang="pt">reprodutor áudio portátil</comment>
- <comment xml:lang="pt_BR">Reprodutor de áudio portátil</comment>
- <comment xml:lang="ro">player audio portabil</comment>
+ <!-- see fd.o hal spec -->
+ <comment>Portable audio player</comment>
+ <comment xml:lang="uk">портативний звуковий програвач</comment>
+ <comment xml:lang="sv">Bärbar ljudspelare</comment>
<comment xml:lang="ru">Портативный аудиопроигрыватель</comment>
- <comment xml:lang="sk">Prenosný hudobný prehrávač</comment>
- <comment xml:lang="sl">prenosni predvajalnik zvoka</comment>
- <comment xml:lang="sq">Lexues audio portativ</comment>
- <comment xml:lang="sr">преносна музичка справица</comment>
- <comment xml:lang="sv">bärbar ljudspelare</comment>
- <comment xml:lang="tr">taşınabilir ses oynatıcısı</comment>
- <comment xml:lang="uk">портативний аудіопрогравач</comment>
- <comment xml:lang="vi">bộ phát nhạc di động</comment>
- <comment xml:lang="zh_CN">便携式音频播放器</comment>
- <comment xml:lang="zh_TW">可攜式音訊播放程式</comment>
+ <comment xml:lang="pl">Przenośny odtwarzacz dźwięku</comment>
+ <comment xml:lang="it">Lettore audio portabile</comment>
+ <comment xml:lang="es">reproductor de audio portátil</comment>
+ <comment xml:lang="de">Portables Audio-Wiedergabegerät</comment>
+ <comment xml:lang="be">партатыўны аўдыяплэер</comment>
+ </mime-type>
+ <mime-type type="x-content/ostree-repository">
+ <!-- https://github.com/ostreedev/ostree/blob/master/man/ostree-create-usb.xml -->
+ <comment>OSTree software updates</comment>
+ <comment xml:lang="zh_TW">OSTree 軟體更新</comment>
+ <comment xml:lang="zh_CN">OSTree 软件更新</comment>
+ <comment xml:lang="uk">оновлення програмного забезпечення OSTree</comment>
+ <comment xml:lang="tr">OSTree yazılım güncellemeleri</comment>
+ <comment xml:lang="sv">OSTree programvaruuppdateringar</comment>
+ <comment xml:lang="sq">përditësime software-i OSTree</comment>
+ <comment xml:lang="sl">Posodobitve programja OSTree</comment>
+ <comment xml:lang="si">OSTree මෘදුකාංග යාවත්කාලීන</comment>
+ <comment xml:lang="ru">Обновления программного обеспечения OSTree</comment>
+ <comment xml:lang="pt_BR">Atualizações de software OSTree</comment>
+ <comment xml:lang="pl">Aktualizacje oprogramowania OSTree</comment>
+ <comment xml:lang="nl">OSTree-software-updates</comment>
+ <comment xml:lang="ko">OSTree 소프트웨어 업데이트</comment>
+ <comment xml:lang="kk">OSTree бағдарламалық қамтама жаңартулары</comment>
+ <comment xml:lang="ja">OSTree ソフトウェアアップデート</comment>
+ <comment xml:lang="it">Aggiornamenti software OSTree</comment>
+ <comment xml:lang="is">OSTree hugbúnaðaruppfærslur</comment>
+ <comment xml:lang="id">Pemutakhiran perangkat lunak OSTree</comment>
+ <comment xml:lang="hu">OSTree szoftverfrissítések</comment>
+ <comment xml:lang="hr">OSTree nadopune softvera</comment>
+ <comment xml:lang="he">עדכוני תכנה של OSTree</comment>
+ <comment xml:lang="fr">mises à jour logicielles OSTree</comment>
+ <comment xml:lang="fi">OSTree-ohjelmistopäivitykset</comment>
+ <comment xml:lang="eu">OSTree software eguneraketak</comment>
+ <comment xml:lang="es">actualizaciones de programas de OSTree</comment>
+ <comment xml:lang="en_GB">OSTree software updates</comment>
+ <comment xml:lang="de">OSTree-Softwareaktualisierungen</comment>
+ <comment xml:lang="da">OSTree-softwareopdateringer</comment>
+ <comment xml:lang="ca">actualitzacions de programari OSTree</comment>
+ <comment xml:lang="bg">Обновление — OSTree</comment>
+ <comment xml:lang="be">абнаўленні ПЗ OSTree</comment>
+ <comment xml:lang="ar">تحديثات برامج OSTree</comment>
+ <treemagic>
+ <treematch path=".ostree" type="directory" non-empty="true" match-case="true"/>
+ <treematch path="ostree/repo" type="directory" non-empty="true" match-case="true"/>
+ <treematch path="var/lib/flatpak/repo" type="directory" non-empty="true" match-case="true"/>
+ </treemagic>
</mime-type>
-
<mime-type type="x-content/software">
-
- <comment>software</comment>
- <comment xml:lang="ar">برنامج</comment>
- <comment xml:lang="be@latin">prahrama</comment>
- <comment xml:lang="bg">Софтуер</comment>
- <comment xml:lang="ca">programari</comment>
- <comment xml:lang="cs">software</comment>
- <comment xml:lang="da">software</comment>
- <comment xml:lang="de">Software</comment>
- <comment xml:lang="el">Λογισμικό</comment>
- <comment xml:lang="en_GB">software</comment>
- <comment xml:lang="es">software</comment>
- <comment xml:lang="eu">softwarea</comment>
- <comment xml:lang="fi">ohjelmisto</comment>
- <comment xml:lang="fo">ritbúnaður</comment>
- <comment xml:lang="fr">logiciel</comment>
- <comment xml:lang="ga">bogearraí</comment>
- <comment xml:lang="gl">software</comment>
- <comment xml:lang="he">תכנה</comment>
- <comment xml:lang="hr">Softver</comment>
- <comment xml:lang="hu">szoftver</comment>
- <comment xml:lang="ia">Software</comment>
- <comment xml:lang="id">peranti lunak</comment>
- <comment xml:lang="it">Software</comment>
- <comment xml:lang="ja">ソフトウェア</comment>
- <comment xml:lang="ka">პროგრამული უზრუნველყოფა</comment>
- <comment xml:lang="kk">бағдарламалық қамтама</comment>
- <comment xml:lang="ko">소프트웨어</comment>
- <comment xml:lang="lt">programinė įranga</comment>
- <comment xml:lang="lv">programmatūra</comment>
- <comment xml:lang="nl">software</comment>
- <comment xml:lang="nn">programvare</comment>
- <comment xml:lang="oc">logicial</comment>
- <comment xml:lang="pl">Oprogramowanie</comment>
- <comment xml:lang="pt">programa</comment>
- <comment xml:lang="pt_BR">Aplicativo</comment>
- <comment xml:lang="ro">software</comment>
- <comment xml:lang="ru">Программное обеспечение</comment>
- <comment xml:lang="sk">Softvér</comment>
- <comment xml:lang="sl">programska oprema</comment>
- <comment xml:lang="sq">Software</comment>
- <comment xml:lang="sr">софтвер</comment>
- <comment xml:lang="sv">programvara</comment>
- <comment xml:lang="tr">yazılım</comment>
+ <!-- http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
+ http://bugzilla.gnome.org/show_bug.cgi?id=509823#c3 -->
+ <comment>Software</comment>
<comment xml:lang="uk">програмне забезпечення</comment>
- <comment xml:lang="vi">phần mềm</comment>
- <comment xml:lang="zh_CN">软件</comment>
- <comment xml:lang="zh_TW">軟體</comment>
+ <comment xml:lang="sv">Programvara</comment>
+ <comment xml:lang="ru">Программное обеспечение</comment>
+ <comment xml:lang="pt_BR">Software</comment>
+ <comment xml:lang="pl">Oprogramowanie</comment>
+ <comment xml:lang="ja">ソフトウェア</comment>
+ <comment xml:lang="it">Software</comment>
+ <comment xml:lang="gl">Software</comment>
+ <comment xml:lang="eu">Softwarea</comment>
+ <comment xml:lang="es">sóftwer</comment>
+ <comment xml:lang="de">Software</comment>
+ <comment xml:lang="be">праграмнае забеспячэнне</comment>
</mime-type>
-
<mime-type type="x-content/unix-software">
-
+ <!-- http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
+ http://bugzilla.gnome.org/show_bug.cgi?id=509823#c3 -->
<comment>UNIX software</comment>
- <comment xml:lang="ar">برنامج يونكس</comment>
- <comment xml:lang="bg">Софтуер за UNIX</comment>
- <comment xml:lang="ca">programari d'UNIX</comment>
- <comment xml:lang="cs">software systému UNIX</comment>
- <comment xml:lang="da">UNIX-programmer</comment>
- <comment xml:lang="de">UNIX-Software</comment>
- <comment xml:lang="el">Λογισμικό UNIX</comment>
- <comment xml:lang="en_GB">UNIX software</comment>
- <comment xml:lang="es">software de UNIX</comment>
- <comment xml:lang="eu">UNIXeko softwarea</comment>
- <comment xml:lang="fi">UNIX-ohjelmisto</comment>
- <comment xml:lang="fo">UNIX ritbúnaður</comment>
- <comment xml:lang="fr">logiciel UNIX</comment>
- <comment xml:lang="ga">bogearraí UNIX</comment>
- <comment xml:lang="gl">Software de UNIX</comment>
- <comment xml:lang="he">תכנה ל־UNIX</comment>
- <comment xml:lang="hr">UNIX softver</comment>
- <comment xml:lang="hu">UNIX-szoftver</comment>
- <comment xml:lang="ia">Software pro UNIX</comment>
- <comment xml:lang="id">Peranti lunak UNIX</comment>
- <comment xml:lang="it">Software UNIX</comment>
- <comment xml:lang="ja">UNIX ソフトウェア</comment>
- <comment xml:lang="kk">UNIX бағдарламасы</comment>
- <comment xml:lang="ko">UNIX 소프트웨어</comment>
- <comment xml:lang="lt">UNIX programinė įranga</comment>
- <comment xml:lang="lv">UNIX programmatūra</comment>
- <comment xml:lang="nl">UNIX software</comment>
- <comment xml:lang="oc">logicial UNIX</comment>
- <comment xml:lang="pl">Oprogramowanie systemu UNIX</comment>
- <comment xml:lang="pt">programa UNIX</comment>
- <comment xml:lang="pt_BR">Aplicativo UNIX</comment>
- <comment xml:lang="ro">Software UNIX</comment>
- <comment xml:lang="ru">Программа UNIX</comment>
- <comment xml:lang="sk">Softvér UNIX</comment>
- <comment xml:lang="sl">Programska datoteka UNIX</comment>
- <comment xml:lang="sr">ЈУНИКС-ов софтвер</comment>
- <comment xml:lang="sv">UNIX-programvara</comment>
- <comment xml:lang="tr">UNIX yazılımı</comment>
- <comment xml:lang="uk">програмне забезпечення UNIX</comment>
- <comment xml:lang="zh_CN">UNIX 软件</comment>
<comment xml:lang="zh_TW">UNIX 軟體</comment>
+ <comment xml:lang="zh_CN">UNIX 软件</comment>
+ <comment xml:lang="uk">програмне забезпечення UNIX</comment>
+ <comment xml:lang="tr">UNIX yazılımı</comment>
+ <comment xml:lang="sv">UNIX-programvara</comment>
+ <comment xml:lang="sr">ЈУНИКС-ов софтвер</comment>
+ <comment xml:lang="sq">software UNIX</comment>
+ <comment xml:lang="sl">Programska datoteka UNIX</comment>
+ <comment xml:lang="si">UNIX මෘදුකාංගය</comment>
+ <comment xml:lang="sk">Softvér UNIX</comment>
+ <comment xml:lang="ru">Программа UNIX</comment>
+ <comment xml:lang="ro">Software UNIX</comment>
+ <comment xml:lang="pt_BR">Aplicativo UNIX</comment>
+ <comment xml:lang="pt">programa UNIX</comment>
+ <comment xml:lang="pl">Oprogramowanie systemu UNIX</comment>
+ <comment xml:lang="oc">logicial UNIX</comment>
+ <comment xml:lang="nl">UNIX-software</comment>
+ <comment xml:lang="lv">UNIX programmatūra</comment>
+ <comment xml:lang="lt">UNIX programinė įranga</comment>
+ <comment xml:lang="ko">UNIX 소프트웨어</comment>
+ <comment xml:lang="kk">UNIX бағдарламасы</comment>
+ <comment xml:lang="ja">UNIX ソフトウェア</comment>
+ <comment xml:lang="it">Software UNIX</comment>
+ <comment xml:lang="is">UNIX hugbúnaður</comment>
+ <comment xml:lang="id">Peranti lunak UNIX</comment>
+ <comment xml:lang="ia">Software pro UNIX</comment>
+ <comment xml:lang="hu">UNIX-szoftver</comment>
+ <comment xml:lang="hr">UNIX softver</comment>
+ <comment xml:lang="he">תכנה ל־UNIX</comment>
+ <comment xml:lang="gl">Software de UNIX</comment>
+ <comment xml:lang="ga">bogearraí UNIX</comment>
+ <comment xml:lang="fur">software UNIX</comment>
+ <comment xml:lang="fr">logiciel UNIX</comment>
+ <comment xml:lang="fo">UNIX ritbúnaður</comment>
+ <comment xml:lang="fi">UNIX-ohjelmisto</comment>
+ <comment xml:lang="eu">UNIXeko softwarea</comment>
+ <comment xml:lang="es">software de UNIX</comment>
+ <comment xml:lang="en_GB">UNIX software</comment>
+ <comment xml:lang="el">Λογισμικό UNIX</comment>
+ <comment xml:lang="de">UNIX-Software</comment>
+ <comment xml:lang="da">UNIX-programmer</comment>
+ <comment xml:lang="cs">software systému UNIX</comment>
+ <comment xml:lang="ca">programari d'UNIX</comment>
+ <comment xml:lang="bg">Софтуер — UNIX</comment>
+ <comment xml:lang="be">ПЗ UNIX</comment>
+ <comment xml:lang="ar">برنامج يونكس</comment>
+ <comment xml:lang="af">UNIX-sagteware</comment>
<sub-class-of type="x-content/software"/>
<treemagic>
- <treematch type="file" path=".autorun" match-case="true"/>
- <treematch type="file" path="autorun" match-case="true"/>
- <treematch type="file" path="autorun.sh" match-case="true"/>
+ <treematch path=".autorun" type="file" match-case="true"/>
+ <treematch path="autorun" type="file" match-case="true"/>
+ <treematch path="autorun.sh" type="file" match-case="true"/>
</treemagic>
</mime-type>
-
<mime-type type="x-content/win32-software">
-
+ <!-- http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
+ http://bugzilla.gnome.org/show_bug.cgi?id=509823#c3 -->
<comment>Windows software</comment>
- <comment xml:lang="ar">برنامج ويندوز</comment>
- <comment xml:lang="bg">Софтуер — Windows</comment>
- <comment xml:lang="ca">programari de Windows</comment>
- <comment xml:lang="cs">software systému Windows</comment>
- <comment xml:lang="da">Windowsprogram</comment>
- <comment xml:lang="de">Windows-Software</comment>
- <comment xml:lang="el">Λογισμικό Windows</comment>
- <comment xml:lang="en_GB">Windows software</comment>
- <comment xml:lang="es">software de Windows</comment>
- <comment xml:lang="eu">Windows-eko softwarea</comment>
- <comment xml:lang="fi">Windows-ohjelmisto</comment>
- <comment xml:lang="fo">Windows ritbúnaður</comment>
- <comment xml:lang="fr">logiciel Windows</comment>
- <comment xml:lang="ga">bogearraí Windows</comment>
- <comment xml:lang="gl">Software de Windows</comment>
- <comment xml:lang="he">תכנה ל־Windows</comment>
- <comment xml:lang="hr">Windows softver</comment>
- <comment xml:lang="hu">Windows-szoftver</comment>
- <comment xml:lang="ia">Software Windows</comment>
- <comment xml:lang="id">Piranti lunak Windows</comment>
- <comment xml:lang="it">Software Windows</comment>
- <comment xml:lang="ja">Windows ソフトウェア</comment>
- <comment xml:lang="kk">Windows бағдарламасы</comment>
- <comment xml:lang="ko">Windows 소프트웨어</comment>
- <comment xml:lang="lt">Windows programinė įranga</comment>
- <comment xml:lang="lv">Windows programmatūra</comment>
- <comment xml:lang="nl">Windows software</comment>
- <comment xml:lang="oc">logicial Windows</comment>
- <comment xml:lang="pl">Oprogramowanie systemu Windows</comment>
- <comment xml:lang="pt">programa Windows</comment>
- <comment xml:lang="pt_BR">Programa do Windows</comment>
- <comment xml:lang="ro">Software Windows</comment>
- <comment xml:lang="ru">Программа Windows</comment>
- <comment xml:lang="sk">Softvér Windows</comment>
- <comment xml:lang="sl">Programska oprema za okolje Windows</comment>
- <comment xml:lang="sr">Виндоузов софтвер</comment>
- <comment xml:lang="sv">Windows-program</comment>
- <comment xml:lang="tr">Windows yazılımı</comment>
- <comment xml:lang="uk">програмне забезпечення Windows</comment>
- <comment xml:lang="zh_CN">Windows 软件</comment>
<comment xml:lang="zh_TW">Windows 軟體</comment>
+ <comment xml:lang="zh_CN">Windows 软件</comment>
+ <comment xml:lang="uk">програмне забезпечення Windows</comment>
+ <comment xml:lang="tr">Windows yazılımı</comment>
+ <comment xml:lang="sv">Windows-program</comment>
+ <comment xml:lang="sr">Виндоузов софтвер</comment>
+ <comment xml:lang="sq">software Windows</comment>
+ <comment xml:lang="sl">Programska oprema za okolje Windows</comment>
+ <comment xml:lang="si">වින්ඩෝස් මෘදුකාංග</comment>
+ <comment xml:lang="sk">Softvér Windows</comment>
+ <comment xml:lang="ru">Программа Windows</comment>
+ <comment xml:lang="ro">Software Windows</comment>
+ <comment xml:lang="pt_BR">Programa do Windows</comment>
+ <comment xml:lang="pt">programa Windows</comment>
+ <comment xml:lang="pl">Oprogramowanie systemu Windows</comment>
+ <comment xml:lang="oc">logicial Windows</comment>
+ <comment xml:lang="nl">Windows-software</comment>
+ <comment xml:lang="lv">Windows programmatūra</comment>
+ <comment xml:lang="lt">Windows programinė įranga</comment>
+ <comment xml:lang="ko">Windows 소프트웨어</comment>
+ <comment xml:lang="kk">Windows бағдарламасы</comment>
+ <comment xml:lang="ka">Windows-ის პროგრამა</comment>
+ <comment xml:lang="ja">Windows ソフトウェア</comment>
+ <comment xml:lang="it">Software Windows</comment>
+ <comment xml:lang="is">Windows hugbúnaður</comment>
+ <comment xml:lang="id">Piranti lunak Windows</comment>
+ <comment xml:lang="ia">Software Windows</comment>
+ <comment xml:lang="hu">Windows-szoftver</comment>
+ <comment xml:lang="hr">Windows softver</comment>
+ <comment xml:lang="he">תכנה ל־Windows</comment>
+ <comment xml:lang="gl">Software de Windows</comment>
+ <comment xml:lang="ga">bogearraí Windows</comment>
+ <comment xml:lang="fur">software Windows</comment>
+ <comment xml:lang="fr">logiciel Windows</comment>
+ <comment xml:lang="fo">Windows ritbúnaður</comment>
+ <comment xml:lang="fi">Windows-ohjelmisto</comment>
+ <comment xml:lang="eu">Windows-eko softwarea</comment>
+ <comment xml:lang="es">software de Windows</comment>
+ <comment xml:lang="en_GB">Windows software</comment>
+ <comment xml:lang="el">Λογισμικό Windows</comment>
+ <comment xml:lang="de">Windows-Software</comment>
+ <comment xml:lang="da">Windowsprogram</comment>
+ <comment xml:lang="cs">software systému Windows</comment>
+ <comment xml:lang="ca">programari de Windows</comment>
+ <comment xml:lang="bg">Софтуер — Windows</comment>
+ <comment xml:lang="be">ПЗ Windows</comment>
+ <comment xml:lang="ar">برنامج ويندوز</comment>
+ <comment xml:lang="af">Windows-sagteware</comment>
<sub-class-of type="x-content/software"/>
<treemagic>
- <treematch type="file" path="autorun.exe" executable="true"/>
- <treematch type="file" path="autorun.inf"/>
+ <treematch path="autorun.exe" type="file" executable="true"/>
+ <treematch path="autorun.inf" type="file"/>
</treemagic>
</mime-type>
-
<mime-type type="application/trig">
<comment>TriG RDF document</comment>
- <comment xml:lang="ast">Documentu RDF TriG</comment>
- <comment xml:lang="ca">document TriG RDF</comment>
- <comment xml:lang="cs">dokument Trig RDF</comment>
- <comment xml:lang="da">TriG RDF-dokument</comment>
- <comment xml:lang="de">TriG-RDF-Dokument</comment>
- <comment xml:lang="el">Έγγραφο TriG RDF</comment>
- <comment xml:lang="en_GB">TriG RDF document</comment>
- <comment xml:lang="es">documento RDF de TriG</comment>
- <comment xml:lang="eu">TriG RDF dokumentua</comment>
- <comment xml:lang="fi">TriG RDF -asiakirja</comment>
- <comment xml:lang="fr">document RDF TriG</comment>
- <comment xml:lang="ga">cáipéis RDF TriG</comment>
- <comment xml:lang="gl">Documento RDF TriG</comment>
- <comment xml:lang="he">מסמך RDF של TriG</comment>
- <comment xml:lang="hr">TriG RDF dokument</comment>
- <comment xml:lang="hu">TriG RDF dokumentum</comment>
- <comment xml:lang="ia">Documento TriG RDF</comment>
- <comment xml:lang="id">Dokumen TriG RDF</comment>
- <comment xml:lang="it">Documento TriG RDF</comment>
- <comment xml:lang="kk">TriG RDF құжаты</comment>
- <comment xml:lang="ko">TriG RDF 문서</comment>
- <comment xml:lang="oc">document RDF TriG</comment>
- <comment xml:lang="pl">Dokument RDF TriG</comment>
- <comment xml:lang="pt">documento TriG RDF</comment>
- <comment xml:lang="pt_BR">Documento RDF do TriG</comment>
- <comment xml:lang="ru">Документ TriG RDF</comment>
- <comment xml:lang="sk">RDF dokument TriG</comment>
- <comment xml:lang="sl">Dokument TriG RDF</comment>
- <comment xml:lang="sr">ТриГ РДФ документ</comment>
- <comment xml:lang="sv">TriG RDF-dokument</comment>
- <comment xml:lang="tr">TriG RDF belgesi</comment>
- <comment xml:lang="uk">документ RDF TriG</comment>
- <comment xml:lang="zh_CN">TriG RDF 文档</comment>
<comment xml:lang="zh_TW">TriG RDF 文件</comment>
+ <comment xml:lang="zh_CN">TriG RDF 文档</comment>
+ <comment xml:lang="uk">документ RDF TriG</comment>
+ <comment xml:lang="tr">TriG RDF belgesi</comment>
+ <comment xml:lang="sv">TriG RDF-dokument</comment>
+ <comment xml:lang="sr">ТриГ РДФ документ</comment>
+ <comment xml:lang="sq">dokument TriG RDF</comment>
+ <comment xml:lang="sl">Dokument TriG RDF</comment>
+ <comment xml:lang="si">TriG RDF ලේඛනය</comment>
+ <comment xml:lang="sk">RDF dokument TriG</comment>
+ <comment xml:lang="ru">Документ TriG RDF</comment>
+ <comment xml:lang="pt_BR">Documento RDF do TriG</comment>
+ <comment xml:lang="pt">documento TriG RDF</comment>
+ <comment xml:lang="pl">Dokument RDF TriG</comment>
+ <comment xml:lang="oc">document RDF TriG</comment>
+ <comment xml:lang="nl">TriG RDF-document</comment>
+ <comment xml:lang="ko">TriG RDF 문서</comment>
+ <comment xml:lang="kk">TriG RDF құжаты</comment>
+ <comment xml:lang="ja">TriG RDF ドキュメント</comment>
+ <comment xml:lang="it">Documento TriG RDF</comment>
+ <comment xml:lang="is">TriG RDF skjal</comment>
+ <comment xml:lang="id">Dokumen TriG RDF</comment>
+ <comment xml:lang="ia">Documento TriG RDF</comment>
+ <comment xml:lang="hu">TriG RDF dokumentum</comment>
+ <comment xml:lang="hr">TriG RDF dokument</comment>
+ <comment xml:lang="he">מסמך RDF של TriG</comment>
+ <comment xml:lang="gl">Documento RDF TriG</comment>
+ <comment xml:lang="ga">cáipéis RDF TriG</comment>
+ <comment xml:lang="fur">document TriG RDF</comment>
+ <comment xml:lang="fr">document RDF TriG</comment>
+ <comment xml:lang="fi">TriG RDF -asiakirja</comment>
+ <comment xml:lang="eu">TriG RDF dokumentua</comment>
+ <comment xml:lang="es">documento RDF de TriG</comment>
+ <comment xml:lang="en_GB">TriG RDF document</comment>
+ <comment xml:lang="el">Έγγραφο TriG RDF</comment>
+ <comment xml:lang="de">TriG-RDF-Dokument</comment>
+ <comment xml:lang="da">TriG RDF-dokument</comment>
+ <comment xml:lang="cs">dokument Trig RDF</comment>
+ <comment xml:lang="ca">document TriG RDF</comment>
+ <comment xml:lang="bg">Документ — TriG RDF</comment>
+ <comment xml:lang="be">дакумент TriG RDF</comment>
+ <comment xml:lang="ast">Documentu RDF TriG</comment>
+ <comment xml:lang="ar">وثيقة TriG RDF</comment>
+ <comment xml:lang="af">TriG RDF-dokument</comment>
<acronym>TriG</acronym>
<expanded-acronym>TriG RDF Graph Triple Language</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.trig"/>
<alias type="application/x-trig"/>
</mime-type>
-
- <mime-type type="application/x-iwork-keynote-sffkey">
+ <mime-type type="application/vnd.apple.keynote">
<comment>Apple Keynote 5 presentation</comment>
- <comment xml:lang="ca">presentació Keynote 5 d'Apple</comment>
- <comment xml:lang="cs">prezentace Apple Keynote 5</comment>
- <comment xml:lang="da">Apple Keynote 5-præsentation</comment>
- <comment xml:lang="de">Apple-Keynote-5-Präsentation</comment>
- <comment xml:lang="el">Παρουσίαση Apple Keynote 5</comment>
- <comment xml:lang="en_GB">Apple Keynote 5 presentation</comment>
- <comment xml:lang="es">presentación de Apple Keynote 5</comment>
- <comment xml:lang="eu">Apple Keynote 5 aurkezpena</comment>
- <comment xml:lang="fi">Apple Keynote 5 -esitys</comment>
- <comment xml:lang="fr">présentation Apple Keynote 5</comment>
- <comment xml:lang="ga">láithreoireacht Apple Keynote 5</comment>
- <comment xml:lang="gl">Presentación de Apple Keynote 5</comment>
- <comment xml:lang="he">מצגת Apple Keynote 5</comment>
- <comment xml:lang="hr">Apple Keynote 5 prezentacija</comment>
- <comment xml:lang="hu">Apple Keynote 5 prezentáció</comment>
- <comment xml:lang="ia">Presentation Apple Keynote 5</comment>
- <comment xml:lang="id">Presentasi Apple Keynote 5</comment>
- <comment xml:lang="it">Presentazione Apple Keynote 5</comment>
- <comment xml:lang="kk">Apple Keynote 5 презентациясы</comment>
- <comment xml:lang="ko">Apple 키노트 5 프레젠테이션</comment>
- <comment xml:lang="oc">presentacion Apple Keynote 5</comment>
- <comment xml:lang="pl">Prezentacja Apple Keynote 5</comment>
- <comment xml:lang="pt">apresentação Apple Keynote 5</comment>
- <comment xml:lang="pt_BR">Apresentação do Apple Keynote 5</comment>
- <comment xml:lang="ru">Презентация Apple Keynote 5</comment>
- <comment xml:lang="sk">Prezentácia Apple Keynote 5</comment>
- <comment xml:lang="sl">Predstavitev Apple Keynote 5</comment>
- <comment xml:lang="sr">презентација Епл Кинота 5</comment>
- <comment xml:lang="sv">Apple Keynote 5-presentation</comment>
- <comment xml:lang="tr">Apple Keynote 5 sunumu</comment>
- <comment xml:lang="uk">презентація Apple Keynote 5</comment>
- <comment xml:lang="zh_CN">Apple Keynote 5 演示文稿</comment>
<comment xml:lang="zh_TW">Apple Keynote 5 簡報</comment>
+ <comment xml:lang="zh_CN">Apple Keynote 5 演示文稿</comment>
+ <comment xml:lang="uk">презентація Apple Keynote 5</comment>
+ <comment xml:lang="tr">Apple Keynote 5 sunumu</comment>
+ <comment xml:lang="sv">Apple Keynote 5-presentation</comment>
+ <comment xml:lang="sr">презентација Епл Кинота 5</comment>
+ <comment xml:lang="sq">paraqitje Apple Keynote 5</comment>
+ <comment xml:lang="sl">Predstavitev Apple Keynote 5</comment>
+ <comment xml:lang="si">Apple Keynote 5 ඉදිරිපත් කිරීම</comment>
+ <comment xml:lang="sk">Prezentácia Apple Keynote 5</comment>
+ <comment xml:lang="ru">Презентация Apple Keynote 5</comment>
+ <comment xml:lang="pt_BR">Apresentação do Apple Keynote 5</comment>
+ <comment xml:lang="pt">apresentação Apple Keynote 5</comment>
+ <comment xml:lang="pl">Prezentacja Apple Keynote 5</comment>
+ <comment xml:lang="oc">presentacion Apple Keynote 5</comment>
+ <comment xml:lang="nl">Apple Keynote 5-presentatie</comment>
+ <comment xml:lang="ko">Apple 키노트 5 프레젠테이션</comment>
+ <comment xml:lang="kk">Apple Keynote 5 презентациясы</comment>
+ <comment xml:lang="ja">Apple Keynote 5 プレゼンテーション</comment>
+ <comment xml:lang="it">Presentazione Apple Keynote 5</comment>
+ <comment xml:lang="is">Apple Keynote 5 glærukynning</comment>
+ <comment xml:lang="id">Presentasi Apple Keynote 5</comment>
+ <comment xml:lang="ia">Presentation Apple Keynote 5</comment>
+ <comment xml:lang="hu">Apple Keynote 5 prezentáció</comment>
+ <comment xml:lang="hr">Apple Keynote 5 prezentacija</comment>
+ <comment xml:lang="he">מצגת Apple Keynote 5</comment>
+ <comment xml:lang="gl">Presentación de Apple Keynote 5</comment>
+ <comment xml:lang="ga">láithreoireacht Apple Keynote 5</comment>
+ <comment xml:lang="fur">presentazion Apple Keynote 5</comment>
+ <comment xml:lang="fr">présentation Apple Keynote 5</comment>
+ <comment xml:lang="fi">Apple Keynote 5 -esitys</comment>
+ <comment xml:lang="eu">Apple Keynote 5 aurkezpena</comment>
+ <comment xml:lang="es">presentación de Apple Keynote 5</comment>
+ <comment xml:lang="en_GB">Apple Keynote 5 presentation</comment>
+ <comment xml:lang="el">Παρουσίαση Apple Keynote 5</comment>
+ <comment xml:lang="de">Apple-Keynote-5-Präsentation</comment>
+ <comment xml:lang="da">Apple Keynote 5-præsentation</comment>
+ <comment xml:lang="cs">prezentace Apple Keynote 5</comment>
+ <comment xml:lang="ca">presentació d'Apple Keynote 5</comment>
+ <comment xml:lang="bg">Презентация — Apple Keynote 5</comment>
+ <comment xml:lang="be">прэзентацыя Apple Keynote 5</comment>
+ <comment xml:lang="ar">عرض أبل كي نوت ٥</comment>
+ <comment xml:lang="af">Apple Keynote 5-voorlegging</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
<magic priority="70">
- <match value="PK\003\004" type="string" offset="0">
- <match value="index.apxl" type="string" offset="30"/>
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="index.apxl" offset="30"/>
</match>
</magic>
- <glob pattern="*.key"/>
- <alias type="application/vnd.apple.keynote"/>
+ <glob pattern="*.key" weight="80"/>
+ <alias type="application/x-iwork-keynote-sffkey"/>
+ </mime-type>
+ <mime-type type="application/vnd.apple.numbers">
+ <comment>Apple Numbers spreadsheet</comment>
+ <comment xml:lang="zh_TW">Apple Numbers 試算表</comment>
+ <comment xml:lang="uk">електронні таблиці Apple Numbers</comment>
+ <comment xml:lang="tr">Apple Numbers hesap çizelgesi</comment>
+ <comment xml:lang="sv">Apple Numbers-kalkylblad</comment>
+ <comment xml:lang="sl">Razpredelnica Apple Numbers</comment>
+ <comment xml:lang="si">ඇපල් අංක පැතුරුම්පත</comment>
+ <comment xml:lang="ru">Электронная таблица Apple Numbers</comment>
+ <comment xml:lang="pl">Arkusz Apple Numbers</comment>
+ <comment xml:lang="nl">Apple Numbers-werkblad</comment>
+ <comment xml:lang="ko">애플 넘버스 스프레드시트</comment>
+ <comment xml:lang="kk">Apple Numbers электрондық кестесі</comment>
+ <comment xml:lang="ja">Apple Numbers スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Apple Numbers</comment>
+ <comment xml:lang="hr">Apple Numbers proračunska tablica</comment>
+ <comment xml:lang="fi">Apple Numbers-taulukko</comment>
+ <comment xml:lang="es">hoja de cálculo Apple Numbers</comment>
+ <comment xml:lang="en_GB">Apple Numbers spreadsheet</comment>
+ <comment xml:lang="de">Apple-Numbers-Tabelle</comment>
+ <comment xml:lang="be">электронная табліца Apple Numbers</comment>
+ <comment xml:lang="ar">جدول أرقام أبل</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="x-office-spreadsheet"/>
+ <magic priority="65">
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="index.xml" offset="30"/>
+ <match type="string" value="Index/Document.iwa" offset="30"/>
+ </match>
+ </magic>
+ <glob pattern="*.numbers"/>
+ <alias type="application/x-iwork-numbers-sffnumbers"/>
+ </mime-type>
+ <mime-type type="application/vnd.apple.pages">
+ <comment>Apple Pages document</comment>
+ <comment xml:lang="zh_TW">Apple Pages 文件</comment>
+ <comment xml:lang="uk">документ Apple Pages</comment>
+ <comment xml:lang="tr">Apple Pages belgesi</comment>
+ <comment xml:lang="sv">Apple Pages-dokument</comment>
+ <comment xml:lang="sl">Dokument Apple Pages</comment>
+ <comment xml:lang="si">Apple පිටු ලේඛනය</comment>
+ <comment xml:lang="ru">Документ Apple Pages</comment>
+ <comment xml:lang="pl">Dokument Apple Pages</comment>
+ <comment xml:lang="nl">Apple Pages-document</comment>
+ <comment xml:lang="ko">애플 페이지 문서</comment>
+ <comment xml:lang="kk">Apple Pages құжаты</comment>
+ <comment xml:lang="ja">Apple Pages ドキュメント</comment>
+ <comment xml:lang="it">Documento Apple Pages</comment>
+ <comment xml:lang="hr">Apple Pages dokument</comment>
+ <comment xml:lang="fi">Apple Pages-asiakirja</comment>
+ <comment xml:lang="eu">Apple Pages dokumentua</comment>
+ <comment xml:lang="es">documento de Apple Pages</comment>
+ <comment xml:lang="en_GB">Apple Pages document</comment>
+ <comment xml:lang="de">Apple-Pages-Dokument</comment>
+ <comment xml:lang="be">дакумент Apple Pages</comment>
+ <comment xml:lang="ar">مستند صفحات أبل</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="x-office-document"/>
+ <magic priority="70">
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="index.xml" offset="30"/>
+ <match type="string" value="Index/Document.iwa" offset="30"/>
+ </match>
+ </magic>
+ <glob pattern="*.pages"/>
+ <alias type="application/x-iwork-pages-sffpages"/>
+ </mime-type>
+ <mime-type type="application/vnd.apple.pkpass">
+ <comment>Apple Wallet pass</comment>
+ <comment xml:lang="uk">пропуск Apple Wallet</comment>
+ <comment xml:lang="tr">Apple Cüzdan geçişi</comment>
+ <comment xml:lang="sv">Apple Wallet-pass</comment>
+ <comment xml:lang="si">Apple Wallet පාස්</comment>
+ <comment xml:lang="ru">Пропуск Apple Wallet</comment>
+ <comment xml:lang="pl">Hasło Apple Wallet</comment>
+ <comment xml:lang="nl">Apple Wallet-pas</comment>
+ <comment xml:lang="ko">애플 지갑 인증</comment>
+ <comment xml:lang="kk">Apple Wallet рұқсатнамасы</comment>
+ <comment xml:lang="ja">Apple ウォレットパス</comment>
+ <comment xml:lang="it">Pass Apple Wallet</comment>
+ <comment xml:lang="hr">Apple Novčanik propusnica</comment>
+ <comment xml:lang="gl">Pase de Apple Wallet</comment>
+ <comment xml:lang="fi">Apple Wallet-kulkulupa</comment>
+ <comment xml:lang="es">monedero Apple Wallet</comment>
+ <comment xml:lang="en_GB">Apple Wallet pass</comment>
+ <comment xml:lang="de">Apple-Wallet-Pass</comment>
+ <comment xml:lang="be">пропуск Apple Wallet</comment>
+ <comment xml:lang="ar">بطاقة محفظة أبل</comment>
+ <sub-class-of type="application/zip"/>
+ <magic priority="65">
+ <match type="string" value="PK\003\004" offset="0">
+ <match type="string" value="pass.json" offset="30"/>
+ </match>
+ </magic>
+ <glob pattern="*.pkpass"/>
</mime-type>
-
<mime-type type="application/x-pagemaker">
- <comment>Adobe PageMaker</comment>
- <comment xml:lang="ca">Adobe PageMaker</comment>
- <comment xml:lang="cs">Adobe PageMaker</comment>
- <comment xml:lang="da">Adobe PageMaker</comment>
- <comment xml:lang="de">Adobe PageMaker</comment>
- <comment xml:lang="el">Adobe PageMaker</comment>
- <comment xml:lang="en_GB">Adobe PageMaker</comment>
- <comment xml:lang="es">Adobe PageMaker</comment>
- <comment xml:lang="eu">Adobe PageMaker</comment>
- <comment xml:lang="fi">Adobe PageMaker</comment>
- <comment xml:lang="fr">Adobe PageMaker</comment>
- <comment xml:lang="ga">Adobe PageMaker</comment>
- <comment xml:lang="gl">Adobe PageMaker</comment>
- <comment xml:lang="he">Adobe PageMaker</comment>
- <comment xml:lang="hr">Adobe PageMaker</comment>
- <comment xml:lang="hu">Adobe PageMaker</comment>
- <comment xml:lang="ia">Adobe PageMaker</comment>
- <comment xml:lang="id">Adobe PageMaker</comment>
- <comment xml:lang="it">Adobe PageMaker</comment>
- <comment xml:lang="kk">Adobe PageMaker</comment>
- <comment xml:lang="ko">Adobe 페이지메이커</comment>
- <comment xml:lang="oc">Adobe PageMaker</comment>
- <comment xml:lang="pl">Adobe PageMaker</comment>
- <comment xml:lang="pt">Adobe PageMaker</comment>
- <comment xml:lang="pt_BR">Adobe PageMaker</comment>
- <comment xml:lang="ru">Adobe PageMaker</comment>
- <comment xml:lang="sk">Adobe PageMaker</comment>
+ <comment>Adobe PageMaker document</comment>
+ <comment xml:lang="zh_TW">Adobe PageMaker 文件</comment>
+ <comment xml:lang="zh_CN">Adobe PageMaker 文档</comment>
+ <comment xml:lang="uk">документ Adobe PageMaker</comment>
+ <comment xml:lang="tr">Adobe PageMaker belgesi</comment>
+ <comment xml:lang="sv">Adobe PageMaker-dokument</comment>
+ <comment xml:lang="sq">dokument Adobe PageMaker</comment>
<comment xml:lang="sl">Dokument Adobe PageMaker</comment>
- <comment xml:lang="sr">Адобе Пејџ Мејкер</comment>
- <comment xml:lang="sv">Adobe PageMaker</comment>
- <comment xml:lang="tr">Adobe PageMaker</comment>
- <comment xml:lang="uk">Adobe PageMaker</comment>
- <comment xml:lang="zh_CN">Adobe PageMaker</comment>
- <comment xml:lang="zh_TW">Adobe PageMaker</comment>
+ <comment xml:lang="si">Adobe PageMaker ලේඛනය</comment>
+ <comment xml:lang="sk">Dokument Adobe PageMaker</comment>
+ <comment xml:lang="ru">Документ Adobe PageMaker</comment>
+ <comment xml:lang="pt_BR">Documento do Adobe PageMaker</comment>
+ <comment xml:lang="pl">Dokument Adobe PageMaker</comment>
+ <comment xml:lang="nl">Adobe PageMaker-document</comment>
+ <comment xml:lang="ko">어도비 페이지메이커 문서</comment>
+ <comment xml:lang="kk">Adobe PageMaker құжаты</comment>
+ <comment xml:lang="ja">Adobe PageMaker ドキュメント</comment>
+ <comment xml:lang="it">Documento Adobe PageMaker</comment>
+ <comment xml:lang="is">Adobe PageMaker skjal</comment>
+ <comment xml:lang="id">Dokume Adobe PageMaker</comment>
+ <comment xml:lang="hu">Adobe PageMaker dokumentum</comment>
+ <comment xml:lang="hr">Adobe PageMaker dokument</comment>
+ <comment xml:lang="he">מסמך Adobe PageMaker</comment>
+ <comment xml:lang="gl">Documento de Adobe Pagemaker</comment>
+ <comment xml:lang="fr">document Adobe PageMaker</comment>
+ <comment xml:lang="fi">Adobe PageMaker -asiakirja</comment>
+ <comment xml:lang="eu">Adobe PageMaker dokumentua</comment>
+ <comment xml:lang="es">documento de Adobe PageMaker</comment>
+ <comment xml:lang="en_GB">Adobe PageMaker document</comment>
+ <comment xml:lang="de">Adobe-PageMaker-Dokument</comment>
+ <comment xml:lang="da">Adobe PageMaker-dokument</comment>
+ <comment xml:lang="ca">document d'Adobe PageMaker</comment>
+ <comment xml:lang="bg">Документ — Adobe PageMaker</comment>
+ <comment xml:lang="be">дакумент Adobe PageMaker</comment>
+ <comment xml:lang="ar">مستند أدوبي بيج ميكر</comment>
<sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.p65"/>
@@ -40845,266 +43452,325 @@
<glob pattern="*.pm6"/>
<glob pattern="*.pmd"/>
</mime-type>
-
<mime-type type="application/x-doom-wad">
- <comment>Doom WAD</comment>
- <comment xml:lang="ca">WAD de Doom</comment>
- <comment xml:lang="cs">datový balík WAD hry Doom</comment>
- <comment xml:lang="da">Doom WAD</comment>
- <comment xml:lang="de">Doom WAD</comment>
- <comment xml:lang="en_GB">Doom WAD</comment>
- <comment xml:lang="es">WAD de Doom</comment>
- <comment xml:lang="eu">Doom WAD</comment>
- <comment xml:lang="fr">WAD Doom</comment>
- <comment xml:lang="ga">WAD Doom</comment>
- <comment xml:lang="hr">Doom WAD</comment>
- <comment xml:lang="hu">Doom WAD</comment>
- <comment xml:lang="ia">WAD pro Doom</comment>
- <comment xml:lang="id">WAD Doom</comment>
- <comment xml:lang="it">WAD Doom</comment>
- <comment xml:lang="kk">Doom WAD</comment>
- <comment xml:lang="ko">둠 WAD</comment>
+ <comment>Doom WAD file</comment>
+ <comment xml:lang="zh_TW">Doom WAD 檔</comment>
+ <comment xml:lang="zh_CN">Doom WAD 文件</comment>
+ <comment xml:lang="uk">файл WAD Doom</comment>
+ <comment xml:lang="tr">Doom WAD dosyası</comment>
+ <comment xml:lang="sv">Doom WAD-fil</comment>
+ <comment xml:lang="sq">kartelë Doom WAD</comment>
+ <comment xml:lang="sl">Datoteka Doom WAD</comment>
+ <comment xml:lang="si">Doom WAD ගොනුව</comment>
+ <comment xml:lang="ru">Файл Doom WAD</comment>
+ <comment xml:lang="pt_BR">Arquivo Doom WAD</comment>
<comment xml:lang="pl">Plik WAD gry Doom</comment>
- <comment xml:lang="pt">Doom WAD</comment>
- <comment xml:lang="pt_BR">Doom WAD</comment>
- <comment xml:lang="ru">WAD Doom</comment>
- <comment xml:lang="sk">Doom WAD</comment>
- <comment xml:lang="sr">Дум ВАД</comment>
- <comment xml:lang="sv">Doom-WAD</comment>
- <comment xml:lang="tr">Doom WAD</comment>
- <comment xml:lang="uk">WAD Doom</comment>
- <comment xml:lang="zh_CN">Doom WAD</comment>
- <comment xml:lang="zh_TW">Doom WAD</comment>
+ <comment xml:lang="nl">Doom WAD-bestand</comment>
+ <comment xml:lang="ko">둠 WAD 파일</comment>
+ <comment xml:lang="kk">Doom WAD файлы</comment>
+ <comment xml:lang="ja">Doom WAD ファイル</comment>
+ <comment xml:lang="it">File WAD Doom</comment>
+ <comment xml:lang="is">Doom WAD skrá</comment>
+ <comment xml:lang="id">Berkas WAD Doom</comment>
+ <comment xml:lang="hu">Doom WAD fájl</comment>
+ <comment xml:lang="hr">Doom WAD datoteka</comment>
+ <comment xml:lang="he">קובץ WAD של Doom</comment>
+ <comment xml:lang="gl">Ficheiro de Doom WAD</comment>
+ <comment xml:lang="fr">fichier Doom WAD</comment>
+ <comment xml:lang="fi">Doom WAD -tiedosto</comment>
+ <comment xml:lang="eu">Doom WAD fitxategia</comment>
+ <comment xml:lang="es">archivo WAD de Doom</comment>
+ <comment xml:lang="en_GB">Doom WAD file</comment>
+ <comment xml:lang="de">Doom-WAD-Datei</comment>
+ <comment xml:lang="da">Doom WAD-fil</comment>
+ <comment xml:lang="ca">fitxer WAD de Doom</comment>
+ <comment xml:lang="bg">Ниво — Doom</comment>
+ <comment xml:lang="be">файл Doom WAD</comment>
+ <comment xml:lang="ar">ملف Doom WAD</comment>
<acronym>WAD</acronym>
<expanded-acronym>Where's All the Data</expanded-acronym>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="IWAD" type="string" offset="0"/>
- <match value="PWAD" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="IWAD" offset="0"/>
+ <match type="string" value="PWAD" offset="0"/>
</magic>
- <glob weight="80" pattern="*.wad"/>
+ <glob pattern="*.wad" weight="80"/>
</mime-type>
-
<mime-type type="application/x-amiga-disk-format">
<comment>Amiga disk image</comment>
- <comment xml:lang="ca">imatge de disc d'Amiga</comment>
- <comment xml:lang="cs">obraz disku pro Amigu</comment>
- <comment xml:lang="da">Amiga-diskaftryk</comment>
- <comment xml:lang="de">Amiga-Datenträgerabbild</comment>
- <comment xml:lang="el">Εικόνα δίσκου Amiga</comment>
- <comment xml:lang="en_GB">Amiga disk image</comment>
- <comment xml:lang="es">imagen de disco de Amiga</comment>
- <comment xml:lang="eu">Amiga disko irudia</comment>
- <comment xml:lang="fi">Amiga-levytiedosto</comment>
- <comment xml:lang="fr">image disque Amiga</comment>
- <comment xml:lang="ga">íomhá diosca Amiga</comment>
- <comment xml:lang="he">דמות כונן Amiga</comment>
- <comment xml:lang="hr">Amiga slika diska</comment>
- <comment xml:lang="hu">Amiga lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco Amiga</comment>
- <comment xml:lang="id">Image disk Amiga</comment>
- <comment xml:lang="it">Disco immagine Amiga</comment>
- <comment xml:lang="kk">Amiga диск бейнесі</comment>
- <comment xml:lang="ko">Amiga 디스크 이미지</comment>
- <comment xml:lang="oc">imatge disc Amiga</comment>
- <comment xml:lang="pl">Obraz dysku Amiga</comment>
- <comment xml:lang="pt">imagem de disco Amiga</comment>
- <comment xml:lang="pt_BR">Imagem de disco Amiga</comment>
- <comment xml:lang="ru">Образ диска Amiga</comment>
- <comment xml:lang="sk">Obraz disku Amiga</comment>
- <comment xml:lang="sr">слика диска Амиге</comment>
- <comment xml:lang="sv">Amiga-diskavbild</comment>
- <comment xml:lang="tr">Amiga disk kalıbı</comment>
- <comment xml:lang="uk">образ диска Amiga</comment>
- <comment xml:lang="zh_CN">Amiga 磁盘映像</comment>
<comment xml:lang="zh_TW">Amiga 磁碟映像檔</comment>
- <magic priority="50">
- <match value="DOS\x00" type="string" offset="0"/>
+ <comment xml:lang="zh_CN">Amiga 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска Amiga</comment>
+ <comment xml:lang="tr">Amiga disk görüntüsü</comment>
+ <comment xml:lang="sv">Amiga-diskavbild</comment>
+ <comment xml:lang="sr">слика диска Амиге</comment>
+ <comment xml:lang="sq">pamje disku Amiga</comment>
+ <comment xml:lang="sl">Slika diska Amiga</comment>
+ <comment xml:lang="si">Amiga තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku Amiga</comment>
+ <comment xml:lang="ru">Образ диска Amiga</comment>
+ <comment xml:lang="pt_BR">Imagem de disco Amiga</comment>
+ <comment xml:lang="pt">imagem de disco Amiga</comment>
+ <comment xml:lang="pl">Obraz dysku Amiga</comment>
+ <comment xml:lang="oc">imatge disc Amiga</comment>
+ <comment xml:lang="nl">Amiga-schijfkopiebestand</comment>
+ <comment xml:lang="ko">Amiga 디스크 이미지</comment>
+ <comment xml:lang="kk">Amiga диск бейнесі</comment>
+ <comment xml:lang="ja">Amiga ディスクイメージ</comment>
+ <comment xml:lang="it">Disco immagine Amiga</comment>
+ <comment xml:lang="is">Amiga diskmynd</comment>
+ <comment xml:lang="id">Image disk Amiga</comment>
+ <comment xml:lang="ia">Imagine de disco Amiga</comment>
+ <comment xml:lang="hu">Amiga lemezkép</comment>
+ <comment xml:lang="hr">Amiga slika diska</comment>
+ <comment xml:lang="he">דמות כונן Amiga</comment>
+ <comment xml:lang="gl">Imaxe de disco de Amiga</comment>
+ <comment xml:lang="ga">íomhá diosca Amiga</comment>
+ <comment xml:lang="fur">imagjin disc Amiga</comment>
+ <comment xml:lang="fr">image disque Amiga</comment>
+ <comment xml:lang="fi">Amiga-levytiedosto</comment>
+ <comment xml:lang="eu">Amiga disko irudia</comment>
+ <comment xml:lang="es">imagen de disco de Amiga</comment>
+ <comment xml:lang="en_GB">Amiga disk image</comment>
+ <comment xml:lang="el">Εικόνα δίσκου Amiga</comment>
+ <comment xml:lang="de">Amiga-Datenträgerabbild</comment>
+ <comment xml:lang="da">Amiga-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku pro Amigu</comment>
+ <comment xml:lang="ca">imatge de disc d'Amiga</comment>
+ <comment xml:lang="bg">Диск — Amiga</comment>
+ <comment xml:lang="be">вобраз дыска Amiga</comment>
+ <comment xml:lang="ar">صورة قرص Amiga</comment>
+ <comment xml:lang="af">Amiga-skyfbeeldlêer</comment>
+ <magic>
+ <match type="string" value="DOS\x00" offset="0"/>
</magic>
<glob pattern="*.adf"/>
</mime-type>
-
<mime-type type="application/vnd.flatpak">
<comment>Flatpak application bundle</comment>
- <comment xml:lang="ca">paquet d'aplicació Flatpak</comment>
- <comment xml:lang="cs">balíček Flatpak s aplikací</comment>
- <comment xml:lang="da">Flatpak-programsamling</comment>
- <comment xml:lang="de">Flatpak-Anwendungspaket</comment>
- <comment xml:lang="en_GB">Flatpak application bundle</comment>
- <comment xml:lang="es">paquete de aplicación Flatpak</comment>
- <comment xml:lang="eu">Flatpak aplikazio bilduma</comment>
- <comment xml:lang="fi">Flatpak-sovelluspaketti</comment>
- <comment xml:lang="fr">lot applicatif Flatpak</comment>
- <comment xml:lang="ga">burla feidhmchláir Flatpak</comment>
- <comment xml:lang="he">חבילת יישומי Flatpak</comment>
- <comment xml:lang="hr">Flatpak paket aplikacije</comment>
- <comment xml:lang="hu">Flatpak alkalmazáscsomag</comment>
- <comment xml:lang="id">bundel aplikasi Flatpak</comment>
- <comment xml:lang="it">Bundle applicazione Flatpak</comment>
- <comment xml:lang="kk">Flatpak қолданбалар дестесі</comment>
- <comment xml:lang="ko">Flatpak 프로그램 번들</comment>
- <comment xml:lang="pl">Pakiet programu Flatpak</comment>
- <comment xml:lang="pt_BR">Pacote de aplicativo Flatpak</comment>
- <comment xml:lang="ru">Пакет приложения Flatpak</comment>
- <comment xml:lang="sk">Balík aplikácií Flatpak</comment>
- <comment xml:lang="sr">скуп програма Флатпака</comment>
- <comment xml:lang="sv">Flatpak-programbunt</comment>
- <comment xml:lang="tr">Flatpak uygulama paketi</comment>
- <comment xml:lang="uk">пакунок із програмами Flatpak</comment>
- <comment xml:lang="zh_CN">Flatpak 应用组合包</comment>
<comment xml:lang="zh_TW">Flatpak 應用程式套組</comment>
+ <comment xml:lang="zh_CN">Flatpak 应用组合包</comment>
+ <comment xml:lang="uk">пакунок із програмами Flatpak</comment>
+ <comment xml:lang="tr">Flatpak uygulama paketi</comment>
+ <comment xml:lang="sv">Flatpak-programbunt</comment>
+ <comment xml:lang="sr">скуп програма Флатпака</comment>
+ <comment xml:lang="sq">paketë aplikacionesh Flatpak</comment>
+ <comment xml:lang="si">Flatpak යෙදුම් මිටියක්</comment>
+ <comment xml:lang="sk">Balík aplikácií Flatpak</comment>
+ <comment xml:lang="ru">Пакет приложения Flatpak</comment>
+ <comment xml:lang="pt_BR">Pacote de aplicativo Flatpak</comment>
+ <comment xml:lang="pl">Pakiet programu Flatpak</comment>
+ <comment xml:lang="nl">Flatpak-toepassingsbundel</comment>
+ <comment xml:lang="ko">Flatpak 프로그램 번들</comment>
+ <comment xml:lang="kk">Flatpak қолданбалар дестесі</comment>
+ <comment xml:lang="ja">Flatpak アプリケーションバンドル</comment>
+ <comment xml:lang="it">Bundle applicazione Flatpak</comment>
+ <comment xml:lang="is">Flatpak forritavöndull</comment>
+ <comment xml:lang="id">Bundel aplikasi Flatpak</comment>
+ <comment xml:lang="hu">Flatpak alkalmazáscsomag</comment>
+ <comment xml:lang="hr">Flatpak paket aplikacije</comment>
+ <comment xml:lang="he">חבילת יישומי Flatpak</comment>
+ <comment xml:lang="ga">burla feidhmchláir Flatpak</comment>
+ <comment xml:lang="fur">côl di aplicazions Flatpak</comment>
+ <comment xml:lang="fr">lot applicatif Flatpak</comment>
+ <comment xml:lang="fi">Flatpak-sovelluspaketti</comment>
+ <comment xml:lang="eu">Flatpak aplikazio bilduma</comment>
+ <comment xml:lang="es">paquete de aplicación Flatpak</comment>
+ <comment xml:lang="en_GB">Flatpak application bundle</comment>
+ <comment xml:lang="de">Flatpak-Anwendungspaket</comment>
+ <comment xml:lang="da">Flatpak-programsamling</comment>
+ <comment xml:lang="cs">balíček Flatpak s aplikací</comment>
+ <comment xml:lang="ca">paquet d'aplicació Flatpak</comment>
+ <comment xml:lang="bg">Програмен пакет — Flatpak</comment>
+ <comment xml:lang="be">пакет праграмы Flatpak</comment>
+ <comment xml:lang="ar">حزمة تطبيق Flatpak</comment>
+ <comment xml:lang="af">Flatpak-toepassingsbundel</comment>
<generic-icon name="package-x-generic"/>
- <magic priority="50">
- <match value="xdg-app\x00\x01\x00\x89\xe5" type="string" offset="0"/>
- <match value="flatpak\x00\x01\x00\x89\xe5" type="string" offset="0"/>
+ <magic>
+ <match type="string" value="xdg-app\x00\x01\x00\x89\xe5" offset="0"/>
+ <match type="string" value="flatpak\x00\x01\x00\x89\xe5" offset="0"/>
</magic>
<glob pattern="*.flatpak"/>
<glob pattern="*.xdgapp"/>
<alias type="application/vnd.xdgapp"/>
</mime-type>
-
<mime-type type="application/vnd.flatpak.repo">
<comment>Flatpak repository description</comment>
- <comment xml:lang="ca">descripció de dipòsit de Flatpak</comment>
- <comment xml:lang="cs">popis repozitáře Flatpak</comment>
- <comment xml:lang="da">Flatpak-arkivbeskrivelse</comment>
- <comment xml:lang="de">Flatpak-Repositoriumsbeschreibung</comment>
- <comment xml:lang="en_GB">Flatpak repository description</comment>
- <comment xml:lang="es">descripción de repositorio de Flatpak</comment>
- <comment xml:lang="eu">Flatpak biltegi deskribapena</comment>
- <comment xml:lang="fi">Flatpak-ohjelmistolähdekuvaus</comment>
- <comment xml:lang="fr">description de dépôt Flatpak</comment>
- <comment xml:lang="ga">cur síos ar stórlann Flatpak</comment>
- <comment xml:lang="he">תיאור מאגר Flatpak</comment>
- <comment xml:lang="hr">Flatpak opis repozitorija</comment>
- <comment xml:lang="hu">Flatpak tárolóleírás</comment>
- <comment xml:lang="id">deskripsi repositori Flatpak</comment>
- <comment xml:lang="it">Descrizione repository Flatpack</comment>
- <comment xml:lang="kk">Flatpak репозиторийі сипаттамасы</comment>
- <comment xml:lang="ko">Flatpak 저장소 디스크립션</comment>
- <comment xml:lang="pl">Opis repozytorium Flatpak</comment>
- <comment xml:lang="pt_BR">Descrição de repositório Flatpak</comment>
- <comment xml:lang="ru">Описание репозитория Flatpak</comment>
- <comment xml:lang="sk">Popis repozitára Flatpak</comment>
- <comment xml:lang="sr">опис ризнице Флатпака</comment>
- <comment xml:lang="sv">Flatpak-förrådsbeskrivning</comment>
- <comment xml:lang="tr">Flatpak depo açıklaması</comment>
- <comment xml:lang="uk">опис сховища Flatpak</comment>
- <comment xml:lang="zh_CN">Flatpak 软件库描述</comment>
<comment xml:lang="zh_TW">Flatpak 軟體庫描述</comment>
+ <comment xml:lang="zh_CN">Flatpak 软件库描述</comment>
+ <comment xml:lang="uk">опис сховища Flatpak</comment>
+ <comment xml:lang="tr">Flatpak depo açıklaması</comment>
+ <comment xml:lang="sv">Flatpak-förrådsbeskrivning</comment>
+ <comment xml:lang="sr">опис ризнице Флатпака</comment>
+ <comment xml:lang="sq">përshkrim depoje Flatpak</comment>
+ <comment xml:lang="si">Flatpak ගබඩා විස්තරය</comment>
+ <comment xml:lang="sk">Popis repozitára Flatpak</comment>
+ <comment xml:lang="ru">Описание репозитория Flatpak</comment>
+ <comment xml:lang="pt_BR">Descrição de repositório Flatpak</comment>
+ <comment xml:lang="pl">Opis repozytorium Flatpak</comment>
+ <comment xml:lang="nl">Flatpak-pakketbronomschrijving</comment>
+ <comment xml:lang="ko">Flatpak 저장소 디스크립션</comment>
+ <comment xml:lang="kk">Flatpak репозиторийі сипаттамасы</comment>
+ <comment xml:lang="ja">Flatpak リポジトリ説明</comment>
+ <comment xml:lang="it">Descrizione repository Flatpack</comment>
+ <comment xml:lang="is">Flatpak lýsing gagnasafns</comment>
+ <comment xml:lang="id">Deskripsi repositori Flatpak</comment>
+ <comment xml:lang="hu">Flatpak tárolóleírás</comment>
+ <comment xml:lang="hr">Flatpak opis repozitorija</comment>
+ <comment xml:lang="he">תיאור מאגר Flatpak</comment>
+ <comment xml:lang="ga">cur síos ar stórlann Flatpak</comment>
+ <comment xml:lang="fur">descrizion dipuesit Flatpak</comment>
+ <comment xml:lang="fr">description de dépôt Flatpak</comment>
+ <comment xml:lang="fi">Flatpak-ohjelmistolähdekuvaus</comment>
+ <comment xml:lang="eu">Flatpak biltegi deskribapena</comment>
+ <comment xml:lang="es">descripción de repositorio de Flatpak</comment>
+ <comment xml:lang="en_GB">Flatpak repository description</comment>
+ <comment xml:lang="de">Flatpak-Repositorybeschreibung</comment>
+ <comment xml:lang="da">Flatpak-arkivbeskrivelse</comment>
+ <comment xml:lang="cs">popis repozitáře Flatpak</comment>
+ <comment xml:lang="ca">descripció de dipòsit de Flatpak</comment>
+ <comment xml:lang="bg">Описание на хранилище — Flatpak</comment>
+ <comment xml:lang="be">апісанне рэпазіторыя Flatpak</comment>
+ <comment xml:lang="ar">وصف مستودع Flatpak</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="[Flatpak Repo]" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="[Flatpak Repo]" offset="0:256"/>
</magic>
<glob pattern="*.flatpakrepo"/>
</mime-type>
-
<mime-type type="application/vnd.flatpak.ref">
<comment>Flatpak repository reference</comment>
- <comment xml:lang="ca">referència de dipòsit Flatpak</comment>
- <comment xml:lang="cs">odkaz na repozitář Flatpak</comment>
- <comment xml:lang="de">Flatpak-Repositoriumsreferenz</comment>
- <comment xml:lang="en_GB">Flatpak repository reference</comment>
- <comment xml:lang="es">referencia a repositorio de Flatpak</comment>
- <comment xml:lang="eu">Flatpak biltegi erreferentzia</comment>
- <comment xml:lang="fi">Flatpak-ohjelmistolähdeviite</comment>
- <comment xml:lang="fr">référence de dépôt Flatpak</comment>
- <comment xml:lang="ga">tagairt do stórlann Flatpak</comment>
- <comment xml:lang="hr">Flatpak preporučeni repozitorij</comment>
- <comment xml:lang="hu">Flatpak tárolóhivatkozás</comment>
- <comment xml:lang="id">acuan repositori Flatpak</comment>
- <comment xml:lang="it">Riferimento repository Flatpack</comment>
- <comment xml:lang="kk">Flatpak репозиторийіне сілтеме</comment>
- <comment xml:lang="ko">Flatpak 저장소 참조</comment>
- <comment xml:lang="pl">Odwołanie do repozytorium Flatpak</comment>
- <comment xml:lang="pt_BR">Referência de repositório Flatpak</comment>
- <comment xml:lang="ru">Ссылка на репозиторий Flatpak</comment>
- <comment xml:lang="sk">Referencia repozitára Flatpak</comment>
- <comment xml:lang="sr">упута ризнице Флатпака</comment>
- <comment xml:lang="sv">Flatpak-förrådsreferens</comment>
- <comment xml:lang="tr">Flatpak depo başvurusu</comment>
- <comment xml:lang="uk">посилання на сховище Flatpak</comment>
- <comment xml:lang="zh_CN">Flatpak 软件库引用</comment>
<comment xml:lang="zh_TW">Flatpak 軟體庫參照</comment>
+ <comment xml:lang="zh_CN">Flatpak 软件库引用</comment>
+ <comment xml:lang="uk">посилання на сховище Flatpak</comment>
+ <comment xml:lang="tr">Flatpak depo atfı</comment>
+ <comment xml:lang="sv">Flatpak-förrådsreferens</comment>
+ <comment xml:lang="sr">упута ризнице Флатпака</comment>
+ <comment xml:lang="sq">referencë depoje Flatpak</comment>
+ <comment xml:lang="si">Flatpak නිධිය යොමුව</comment>
+ <comment xml:lang="sk">Referencia repozitára Flatpak</comment>
+ <comment xml:lang="ru">Ссылка на репозиторий Flatpak</comment>
+ <comment xml:lang="pt_BR">Referência de repositório Flatpak</comment>
+ <comment xml:lang="pl">Odwołanie do repozytorium Flatpak</comment>
+ <comment xml:lang="nl">Flatpak-pakketbronverwijzing</comment>
+ <comment xml:lang="ko">Flatpak 저장소 참조</comment>
+ <comment xml:lang="kk">Flatpak репозиторийіне сілтеме</comment>
+ <comment xml:lang="ja">Flatpak リポジトリリファレンス</comment>
+ <comment xml:lang="it">Riferimento repository Flatpack</comment>
+ <comment xml:lang="is">Flatpak tilvísun gagnasafns</comment>
+ <comment xml:lang="id">Acuan repositori Flatpak</comment>
+ <comment xml:lang="hu">Flatpak tárolóhivatkozás</comment>
+ <comment xml:lang="hr">Flatpak preporučeni repozitorij</comment>
+ <comment xml:lang="he">הפניית מאגר Flatpak</comment>
+ <comment xml:lang="ga">tagairt do stórlann Flatpak</comment>
+ <comment xml:lang="fur">riferiment dipuesit Flatpak</comment>
+ <comment xml:lang="fr">référence de dépôt Flatpak</comment>
+ <comment xml:lang="fi">Flatpak-ohjelmistolähdeviite</comment>
+ <comment xml:lang="eu">Flatpak biltegi erreferentzia</comment>
+ <comment xml:lang="es">referencia a repositorio de Flatpak</comment>
+ <comment xml:lang="en_GB">Flatpak repository reference</comment>
+ <comment xml:lang="de">Flatpak-Repositoryreferenz</comment>
+ <comment xml:lang="da">Flatpak-arkivreference</comment>
+ <comment xml:lang="cs">odkaz na repozitář Flatpak</comment>
+ <comment xml:lang="ca">referència de dipòsit Flatpak</comment>
+ <comment xml:lang="bg">Указател към хранилище — Flatpak</comment>
+ <comment xml:lang="be">спасылкая рэпазіторыя Flatpak</comment>
+ <comment xml:lang="ar">مرجع مستودع Flatpak</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="text/plain"/>
- <magic priority="50">
- <match value="[Flatpak Ref]" type="string" offset="0:256"/>
+ <magic>
+ <match type="string" value="[Flatpak Ref]" offset="0:256"/>
</magic>
<glob pattern="*.flatpakref"/>
</mime-type>
-
<mime-type type="application/vnd.squashfs">
- <comment>Squashfs filesystem</comment>
- <comment xml:lang="ca">Sistema de fitxers Squashfs</comment>
- <comment xml:lang="cs">souborový systém Squashfs</comment>
- <comment xml:lang="da">Squashfs-filsystem</comment>
- <comment xml:lang="de">Squashfs-Dateisystem</comment>
- <comment xml:lang="en_GB">Squashfs filesystem</comment>
- <comment xml:lang="es">sistema de archivos Squashfs</comment>
- <comment xml:lang="eu">Squashfs fitxategi sistema</comment>
- <comment xml:lang="fi">Squashfs-tiedostojärjestelmä</comment>
- <comment xml:lang="fr">système de fichiers Squashfs</comment>
- <comment xml:lang="ga">córas comhad Squashfs</comment>
- <comment xml:lang="he">מערכת קבצים Squashfs</comment>
- <comment xml:lang="hr">Squashfs datotečni sustav</comment>
- <comment xml:lang="hu">Squashfs fájlrendszer</comment>
- <comment xml:lang="id">sistem berkas Squashfs</comment>
- <comment xml:lang="it">File system squashfs</comment>
- <comment xml:lang="kk">Squashfs файлдық жүйесі</comment>
- <comment xml:lang="ko">Squashfs 파일 시스템</comment>
- <comment xml:lang="pl">System plików SquashFS</comment>
- <comment xml:lang="pt_BR">Sistema de arquivos Squashfs</comment>
- <comment xml:lang="ru">Файловая система Squashfs</comment>
- <comment xml:lang="sk">Systém súborov Squashfs</comment>
- <comment xml:lang="sr">систем датотека Сквошфс</comment>
- <comment xml:lang="sv">Squashfs-filsystem</comment>
- <comment xml:lang="tr">Squashfs dosya sistemi</comment>
- <comment xml:lang="uk">файлова система squashfs</comment>
- <comment xml:lang="zh_CN">Squashfs 文件系统</comment>
- <comment xml:lang="zh_TW">Squashfs 檔案系統</comment>
- <magic priority="50">
- <match value="sqsh" type="string" offset="0"/>
- <match value="hsqs" type="string" offset="0"/>
+ <comment>Squashfs filesystem image</comment>
+ <comment xml:lang="zh_TW">Squashfs 檔案系統映像</comment>
+ <comment xml:lang="zh_CN">Squashfs 文件系统映像</comment>
+ <comment xml:lang="uk">образ файлової системи squashfs</comment>
+ <comment xml:lang="tr">Squashfs dosya sistemi görüntüsü</comment>
+ <comment xml:lang="sv">Squashfs filsystemsavbildning</comment>
+ <comment xml:lang="sq">pamje sistemi kartelash Squashfs</comment>
+ <comment xml:lang="si">Squashfs ගොනු පද්ධති රූපය</comment>
+ <comment xml:lang="sk">Obraz systému súborov Squashfs</comment>
+ <comment xml:lang="ru">Образ файловой системы Squashfs</comment>
+ <comment xml:lang="pt_BR">Imagem de sistema de arquivos Squashfs</comment>
+ <comment xml:lang="pl">Obraz systemu plików SquashFS</comment>
+ <comment xml:lang="nl">Squashfs-schijfkopiebestand</comment>
+ <comment xml:lang="ko">Squashfs 파일 시스템 이미지</comment>
+ <comment xml:lang="kk">Squashfs файлдық жүйе бейнесі</comment>
+ <comment xml:lang="ja">Squashfs ファイルシステムイメージ</comment>
+ <comment xml:lang="it">Immagine file system squashfs</comment>
+ <comment xml:lang="is">Squashfs skráakerfismynd</comment>
+ <comment xml:lang="id">Image sistem berkas Squashfs</comment>
+ <comment xml:lang="hu">Squashfs fájlrenszerkép</comment>
+ <comment xml:lang="hr">Squashfs slika datotečnog sustava</comment>
+ <comment xml:lang="he">תמונת מערכת קבצים Squashfs</comment>
+ <comment xml:lang="fr">image de système de fichiers Squashfs</comment>
+ <comment xml:lang="fi">Squashfs-tiedostojärjestelmän levykuva</comment>
+ <comment xml:lang="eu">Squashfs fitxategi sistema irudia</comment>
+ <comment xml:lang="es">imagen de sistema de archivos de Squashfs</comment>
+ <comment xml:lang="en_GB">Squashfs filesystem image</comment>
+ <comment xml:lang="de">Squashfs-Dateisystemabbild</comment>
+ <comment xml:lang="da">Squashfs-filsystemaftryk</comment>
+ <comment xml:lang="ca">imatge de sistema de fitxers Squashfs</comment>
+ <comment xml:lang="bg">Диск — Squashfs</comment>
+ <comment xml:lang="be">вобраз файлавай сістэмы Squashfs</comment>
+ <comment xml:lang="ar">صورة نظام ملفات Squashfs</comment>
+ <sub-class-of type="application/vnd.efi.img"/>
+ <magic>
+ <match type="string" value="sqsh" offset="0"/>
+ <match type="string" value="hsqs" offset="0"/>
</magic>
<glob pattern="*.sqsh"/>
</mime-type>
-
-
+ <!-- AppImage application bundle (Type 2) -->
<mime-type type="application/vnd.appimage">
<comment>AppImage application bundle</comment>
- <comment xml:lang="ca">paquet d'aplicació AppImage</comment>
- <comment xml:lang="cs">balíček AppImage s aplikací</comment>
- <comment xml:lang="da">Applmage-programsamling</comment>
- <comment xml:lang="de">AppImage-Anwendungspaket</comment>
- <comment xml:lang="en_GB">AppImage application bundle</comment>
- <comment xml:lang="es">paquete de aplicación AppImage</comment>
- <comment xml:lang="eu">AppImage aplikazio bilduma</comment>
- <comment xml:lang="fi">AppImage-sovelluspaketti</comment>
- <comment xml:lang="fr">lot applicatif AppImage</comment>
- <comment xml:lang="ga">burla feidhmchláir AppImage</comment>
- <comment xml:lang="he">חבילת יישומי AppImage</comment>
- <comment xml:lang="hr">AppImage paket aplikacije</comment>
- <comment xml:lang="hu">AppImage alkalmazáscsomag</comment>
- <comment xml:lang="id">bundel aplikasi AppImage</comment>
- <comment xml:lang="it">Bundle applicazione AppImage</comment>
- <comment xml:lang="kk">AppImage қолданбалар дестесі</comment>
- <comment xml:lang="ko">AppImage 프로그램 번들</comment>
- <comment xml:lang="pl">Pakiet programu AppImage</comment>
- <comment xml:lang="pt_BR">Pacote de aplicativo AppImage</comment>
- <comment xml:lang="ru">Пакет приложения AppImage</comment>
- <comment xml:lang="sk">Balík aplikácií AppImage</comment>
- <comment xml:lang="sr">скуп програма Ап-слике</comment>
- <comment xml:lang="sv">AppImage-programbunt</comment>
- <comment xml:lang="tr">AppImage uygulama paketi</comment>
- <comment xml:lang="uk">пакунок із програмами AppImage</comment>
- <comment xml:lang="zh_CN">AppImage 应用组合包</comment>
<comment xml:lang="zh_TW">AppImage 應用程式套組</comment>
+ <comment xml:lang="zh_CN">AppImage 应用组合包</comment>
+ <comment xml:lang="uk">пакунок із програмами AppImage</comment>
+ <comment xml:lang="tr">AppImage uygulama paketi</comment>
+ <comment xml:lang="sv">AppImage-programbunt</comment>
+ <comment xml:lang="sr">скуп програма Ап-слике</comment>
+ <comment xml:lang="sq">paketë aplikacioni AppImage</comment>
+ <comment xml:lang="si">AppImage යෙදුම් මිටියක්</comment>
+ <comment xml:lang="sk">Balík aplikácií AppImage</comment>
+ <comment xml:lang="ru">Пакет приложения AppImage</comment>
+ <comment xml:lang="pt_BR">Pacote de aplicativo AppImage</comment>
+ <comment xml:lang="pt">pacote de aplicação AppImage</comment>
+ <comment xml:lang="pl">Pakiet programu AppImage</comment>
+ <comment xml:lang="nl">AppImage-toepassingsbundel</comment>
+ <comment xml:lang="ko">AppImage 프로그램 번들</comment>
+ <comment xml:lang="kk">AppImage қолданбалар дестесі</comment>
+ <comment xml:lang="ja">AppImage アプリケーションバンドル</comment>
+ <comment xml:lang="it">Bundle applicazione AppImage</comment>
+ <comment xml:lang="is">AppImage forritavöndull</comment>
+ <comment xml:lang="id">Bundel aplikasi AppImage</comment>
+ <comment xml:lang="hu">AppImage alkalmazáscsomag</comment>
+ <comment xml:lang="hr">AppImage paket aplikacije</comment>
+ <comment xml:lang="he">חבילת יישומי AppImage</comment>
+ <comment xml:lang="gl">Paquete de aplicación de AppImage</comment>
+ <comment xml:lang="ga">burla feidhmchláir AppImage</comment>
+ <comment xml:lang="fur">côl di aplicazions AppImage</comment>
+ <comment xml:lang="fr">lot applicatif AppImage</comment>
+ <comment xml:lang="fi">AppImage-sovelluspaketti</comment>
+ <comment xml:lang="eu">AppImage aplikazio bilduma</comment>
+ <comment xml:lang="es">paquete de aplicación AppImage</comment>
+ <comment xml:lang="en_GB">AppImage application bundle</comment>
+ <comment xml:lang="de">AppImage-Anwendungspaket</comment>
+ <comment xml:lang="da">AppImage-programsamling</comment>
+ <comment xml:lang="cs">balíček AppImage s aplikací</comment>
+ <comment xml:lang="ca">paquet d'aplicació AppImage</comment>
+ <comment xml:lang="bg">Програмен пакет — AppImage</comment>
+ <comment xml:lang="be">пакет праграмы AppImage</comment>
+ <comment xml:lang="ar">حزمة تطبيق AppImage</comment>
+ <comment xml:lang="af">AppImage-toepassingsbundel</comment>
<sub-class-of type="application/x-executable"/>
<sub-class-of type="application/vnd.squashfs"/>
<generic-icon name="application-x-executable"/>
- <magic priority="50">
+ <magic>
<match value="ELF" type="string" offset="1">
<match value="0x41" type="byte" offset="8">
<match value="0x49" type="byte" offset="9">
@@ -41115,119 +43781,1145 @@
</magic>
<glob weight="60" pattern="*.appimage"/>
</mime-type>
-
<mime-type type="application/vnd.snap">
<comment>Snap package</comment>
- <comment xml:lang="ca">Paquet Snap</comment>
- <comment xml:lang="cs">balíček Snap</comment>
- <comment xml:lang="da">Snap-pakke</comment>
- <comment xml:lang="de">Snap-Paket</comment>
- <comment xml:lang="en_GB">Snap package</comment>
- <comment xml:lang="es">paquete Snap</comment>
- <comment xml:lang="eu">Snap paketea</comment>
- <comment xml:lang="fi">Snap-paketti</comment>
- <comment xml:lang="fr">paquet Snap</comment>
- <comment xml:lang="ga">pacáiste Snap</comment>
- <comment xml:lang="he">חבילת Snap</comment>
- <comment xml:lang="hr">Snap paket</comment>
- <comment xml:lang="hu">Snap-csomag</comment>
- <comment xml:lang="id">paket Snap</comment>
- <comment xml:lang="it">Pacchetto snap</comment>
- <comment xml:lang="kk">Snap дестесі</comment>
- <comment xml:lang="ko">Snap 패키지</comment>
- <comment xml:lang="pl">Pakiet Snap</comment>
- <comment xml:lang="pt_BR">Pacote Snap</comment>
- <comment xml:lang="ru">Пакет Snap</comment>
- <comment xml:lang="sk">Balík Snap</comment>
- <comment xml:lang="sr">Снап пакет</comment>
- <comment xml:lang="sv">Snap-paket</comment>
- <comment xml:lang="tr">Snap paketi</comment>
- <comment xml:lang="uk">пакунок snap</comment>
- <comment xml:lang="zh_CN">Snap 软件包</comment>
<comment xml:lang="zh_TW">Snap 軟體包</comment>
+ <comment xml:lang="zh_CN">Snap 软件包</comment>
+ <comment xml:lang="uk">пакунок snap</comment>
+ <comment xml:lang="tr">Snap paketi</comment>
+ <comment xml:lang="sv">Snap-paket</comment>
+ <comment xml:lang="sr">Снап пакет</comment>
+ <comment xml:lang="sq">paketë Snap</comment>
+ <comment xml:lang="sl">Paket Snap</comment>
+ <comment xml:lang="si">Snap පැකේජය</comment>
+ <comment xml:lang="sk">Balík Snap</comment>
+ <comment xml:lang="ru">Пакет Snap</comment>
+ <comment xml:lang="pt_BR">Pacote Snap</comment>
+ <comment xml:lang="pl">Pakiet Snap</comment>
+ <comment xml:lang="oc">paquet Snap</comment>
+ <comment xml:lang="nl">Snap-pakket</comment>
+ <comment xml:lang="ko">Snap 패키지</comment>
+ <comment xml:lang="kk">Snap дестесі</comment>
+ <comment xml:lang="ja">Snap パッケージ</comment>
+ <comment xml:lang="it">Pacchetto snap</comment>
+ <comment xml:lang="is">Snap-pakki</comment>
+ <comment xml:lang="id">Paket Snap</comment>
+ <comment xml:lang="hu">Snap-csomag</comment>
+ <comment xml:lang="hr">Snap paket</comment>
+ <comment xml:lang="he">חבילת Snap</comment>
+ <comment xml:lang="ga">pacáiste Snap</comment>
+ <comment xml:lang="fur">pachet Snap</comment>
+ <comment xml:lang="fr">paquet Snap</comment>
+ <comment xml:lang="fi">Snap-paketti</comment>
+ <comment xml:lang="eu">Snap paketea</comment>
+ <comment xml:lang="es">paquete Snap</comment>
+ <comment xml:lang="en_GB">Snap package</comment>
+ <comment xml:lang="de">Snap-Paket</comment>
+ <comment xml:lang="da">Snap-pakke</comment>
+ <comment xml:lang="cs">balíček Snap</comment>
+ <comment xml:lang="ca">paquet snap</comment>
+ <comment xml:lang="bg">Пакет — Snap</comment>
+ <comment xml:lang="be">пакет Snap</comment>
+ <comment xml:lang="ar">حزمة سناب</comment>
+ <comment xml:lang="af">Snap-pakket</comment>
<glob pattern="*.snap"/>
<sub-class-of type="application/vnd.squashfs"/>
</mime-type>
-
-
+ <!-- 3D models and GCODEs -->
+ <mime-type type="model/3mf">
+ <comment>3MF document</comment>
+ <comment xml:lang="zh_CN">3MF 文档</comment>
+ <comment xml:lang="uk">документ 3MF</comment>
+ <comment xml:lang="tr">3MF belgesi</comment>
+ <comment xml:lang="sv">3MF-dokument</comment>
+ <comment xml:lang="sl">Dokument 3MF</comment>
+ <comment xml:lang="si">3MF ලේඛනය</comment>
+ <comment xml:lang="ru">Документ 3MF</comment>
+ <comment xml:lang="pt_BR">Documento 3MF</comment>
+ <comment xml:lang="pl">Dokument 3MF</comment>
+ <comment xml:lang="nl">3MF-document</comment>
+ <comment xml:lang="ko">3MF 문서</comment>
+ <comment xml:lang="kk">3MF құжаты</comment>
+ <comment xml:lang="ja">3MF ドキュメント</comment>
+ <comment xml:lang="it">Documento 3MF</comment>
+ <comment xml:lang="hr">3MF dokument</comment>
+ <comment xml:lang="fi">3MF-asiakirja</comment>
+ <comment xml:lang="eu">3MF dokumentua</comment>
+ <comment xml:lang="es">documento 3MF</comment>
+ <comment xml:lang="en_GB">3MF document</comment>
+ <comment xml:lang="de">3MF-Dokument</comment>
+ <comment xml:lang="be">дакумент 3MF</comment>
+ <comment xml:lang="ar">مستند 3MF</comment>
+ <acronym>3MF</acronym>
+ <expanded-acronym>3D Manufacturing Format</expanded-acronym>
+ <glob pattern="*.3mf"/>
+ <alias type="application/vnd.ms-3mfdocument"/>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="image-x-generic"/>
+ </mime-type>
<mime-type type="model/stl">
<comment>STL 3D model</comment>
+ <comment xml:lang="zh_TW">STL 3D 模型</comment>
+ <comment xml:lang="zh_CN">STL 3D 模型</comment>
+ <comment xml:lang="uk">просторова модель STL</comment>
+ <comment xml:lang="tr">STL 3D modeli</comment>
+ <comment xml:lang="sv">STL-3D-modell</comment>
+ <comment xml:lang="sq">model STL 3D</comment>
+ <comment xml:lang="sl">Model STL 3D</comment>
+ <comment xml:lang="si">STL 3D ආකෘතිය</comment>
+ <comment xml:lang="sk">STL 3D model</comment>
+ <comment xml:lang="ru">3D-модель STL</comment>
+ <comment xml:lang="pt_BR">Modelo 3D STL</comment>
+ <comment xml:lang="pl">Model 3D STL</comment>
+ <comment xml:lang="nl">STL 3D-model</comment>
+ <comment xml:lang="ko">STL 3D 모델</comment>
+ <comment xml:lang="kk">STL 3D моделі</comment>
+ <comment xml:lang="ja">STL 3D モデル</comment>
+ <comment xml:lang="it">Modello 3D STL</comment>
+ <comment xml:lang="is">STL 3D-líkan</comment>
+ <comment xml:lang="id">Model 3D STL</comment>
+ <comment xml:lang="hu">STL 3D modell</comment>
+ <comment xml:lang="hr">STL 3D model</comment>
+ <comment xml:lang="he">דגם תלת ממדי של STL</comment>
+ <comment xml:lang="ga">samhail 3T STL</comment>
+ <comment xml:lang="fur">model STL 3D</comment>
+ <comment xml:lang="fr">modèle 3D STL</comment>
+ <comment xml:lang="fi">STL 3D-malli</comment>
+ <comment xml:lang="eu">STL 3D modeloa</comment>
+ <comment xml:lang="es">modelo 3D de STL</comment>
+ <comment xml:lang="en_GB">STL 3D model</comment>
+ <comment xml:lang="de">STL 3D-Modell</comment>
+ <comment xml:lang="da">STL 3D-model</comment>
+ <comment xml:lang="cs">3D model STL</comment>
+ <comment xml:lang="ca">model 3D STL</comment>
+ <comment xml:lang="bg">Модел — STL 3D</comment>
+ <comment xml:lang="be">мадэль STL 3D</comment>
+ <comment xml:lang="ar">نموذج STL 3D</comment>
+ <comment xml:lang="af">STL 3D-model</comment>
<acronym>STL</acronym>
<expanded-acronym>StereoLithography</expanded-acronym>
- <magic priority="50">
- <match value="solid" type="string" offset="0"/>
- <match value="SOLID" type="string" offset="0"/>
+ <generic-icon name="image-x-generic"/>
+ <magic>
+ <match type="string" value="solid" offset="0"/>
+ <match type="string" value="SOLID" offset="0"/>
</magic>
<glob pattern="*.stl"/>
<alias type="model/x.stl-ascii"/>
<alias type="model/x.stl-binary"/>
</mime-type>
-
<mime-type type="text/x.gcode">
<comment>G-code file</comment>
- <comment xml:lang="ca">fitxer G-code</comment>
- <comment xml:lang="cs">soubor G-code</comment>
- <comment xml:lang="de">G-Code-Datei</comment>
- <comment xml:lang="en_GB">G-code file</comment>
- <comment xml:lang="es">archivo G-code</comment>
- <comment xml:lang="eu">G-code fitxategia</comment>
- <comment xml:lang="fi">G-code-tiedosto</comment>
- <comment xml:lang="fr">fichier G-code</comment>
- <comment xml:lang="ga">comhad G-code</comment>
- <comment xml:lang="hr">G-kôd datoteka</comment>
- <comment xml:lang="hu">G-code fájl</comment>
- <comment xml:lang="id">berkas G-code</comment>
- <comment xml:lang="it">File G-code</comment>
- <comment xml:lang="kk">G-code файлы</comment>
- <comment xml:lang="ko">지-코드 파일</comment>
- <comment xml:lang="pl">Plik G-code</comment>
- <comment xml:lang="pt_BR">Arquivo G-code</comment>
- <comment xml:lang="ru">Файл G-code</comment>
- <comment xml:lang="sk">Súbor G-code</comment>
- <comment xml:lang="sr">датотека Г-ко̂да</comment>
- <comment xml:lang="sv">G-code-fil</comment>
- <comment xml:lang="tr">G-code dosyası</comment>
- <comment xml:lang="uk">файл G-code</comment>
- <comment xml:lang="zh_CN">G-code 文件</comment>
<comment xml:lang="zh_TW">G-code 檔案</comment>
+ <comment xml:lang="zh_CN">G-code 文件</comment>
+ <comment xml:lang="uk">файл G-code</comment>
+ <comment xml:lang="tr">G-code dosyası</comment>
+ <comment xml:lang="sv">G-code-fil</comment>
+ <comment xml:lang="sr">датотека Г-ко̂да</comment>
+ <comment xml:lang="sq">kartelë G-code</comment>
+ <comment xml:lang="sl">Datoteka G-code</comment>
+ <comment xml:lang="si">G-කේත ගොනුව</comment>
+ <comment xml:lang="sk">Súbor G-code</comment>
+ <comment xml:lang="ru">Файл G-code</comment>
+ <comment xml:lang="pt_BR">Arquivo G-code</comment>
+ <comment xml:lang="pl">Plik G-code</comment>
+ <comment xml:lang="oc">fichièr G-code</comment>
+ <comment xml:lang="nl">G-code-bestand</comment>
+ <comment xml:lang="ko">G-code 파일</comment>
+ <comment xml:lang="kk">G-code файлы</comment>
+ <comment xml:lang="ja">G-code ファイル</comment>
+ <comment xml:lang="it">File G-code</comment>
+ <comment xml:lang="is">G-code skrá</comment>
+ <comment xml:lang="id">Berkas G-code</comment>
+ <comment xml:lang="hu">G-code fájl</comment>
+ <comment xml:lang="hr">G-kôd datoteka</comment>
+ <comment xml:lang="he">קובץ G-code</comment>
+ <comment xml:lang="ga">comhad G-code</comment>
+ <comment xml:lang="fur">file G-code</comment>
+ <comment xml:lang="fr">fichier G-code</comment>
+ <comment xml:lang="fi">G-code-tiedosto</comment>
+ <comment xml:lang="eu">G-code fitxategia</comment>
+ <comment xml:lang="es">archivo G-code</comment>
+ <comment xml:lang="en_GB">G-code file</comment>
+ <comment xml:lang="de">G-Code-Datei</comment>
+ <comment xml:lang="da">G-code-fil</comment>
+ <comment xml:lang="cs">soubor G-code</comment>
+ <comment xml:lang="ca">fitxer G-code</comment>
+ <comment xml:lang="bg">Модел — G-code</comment>
+ <comment xml:lang="be">файл G-code</comment>
+ <comment xml:lang="ar">ملف G-code</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
<glob pattern="*.gcode"/>
</mime-type>
-
+ <mime-type type="text/x-gcode-gx">
+ <comment>G-code Extended file</comment>
+ <comment xml:lang="uk">файл G-code Extended</comment>
+ <comment xml:lang="tr">G-code Uzatılmış dosyası</comment>
+ <comment xml:lang="sv">Utökad G-code-fil</comment>
+ <comment xml:lang="si">G-කේත විස්තීරණ ගොනුව</comment>
+ <comment xml:lang="ru">Файл G-code Extended</comment>
+ <comment xml:lang="pl">Plik rozszerzonego G-code</comment>
+ <comment xml:lang="nl">G-code Extended-bestand</comment>
+ <comment xml:lang="ko">G-code 확장 파일</comment>
+ <comment xml:lang="kk">G-code Extended файлы</comment>
+ <comment xml:lang="ja">G-code 拡張ファイル</comment>
+ <comment xml:lang="it">File G-code Extended</comment>
+ <comment xml:lang="hr">G-kôd proširena datoteka</comment>
+ <comment xml:lang="fi">G-code Extended-tiedosto</comment>
+ <comment xml:lang="es">archivo G-code extendido</comment>
+ <comment xml:lang="en_GB">G-code Extended file</comment>
+ <comment xml:lang="de">Erweiterte G-Code-Datei</comment>
+ <comment xml:lang="be">файл G-code Extended</comment>
+ <comment xml:lang="ar">ملف غي-كود الموسع</comment>
+ <magic>
+ <match type="string" value="xgcode 1.0" offset="0"/>
+ </magic>
+ <glob pattern="*.gx"/>
+ </mime-type>
<mime-type type="application/x-fds-disk">
<comment>Nintendo FDS disk image</comment>
- <comment xml:lang="ca">Imatge de disc Nintendo FDS</comment>
- <comment xml:lang="cs">obraz disku pro Nintendo FDS</comment>
- <comment xml:lang="de">Nintendo-FDS-Datenträgerabbild</comment>
- <comment xml:lang="en_GB">Nintendo FDS disk image</comment>
- <comment xml:lang="es">imagen de disco FDS de Nintendo</comment>
- <comment xml:lang="eu">Nintendo FDS disko irudia</comment>
- <comment xml:lang="fi">Nintendo FDS -levykuva</comment>
- <comment xml:lang="fr">image disque Nintendo FDS</comment>
- <comment xml:lang="ga">íomhá diosca Nintendo FDS</comment>
- <comment xml:lang="hr">Nintendo FDS slika diska</comment>
- <comment xml:lang="hu">Nintendo FDS lemezkép</comment>
- <comment xml:lang="id">image disk Nintendo FDS</comment>
- <comment xml:lang="it">Immagine disco Nintendo FDS</comment>
- <comment xml:lang="kk">Nintendo FDS диск бейнесі</comment>
- <comment xml:lang="ko">닌텐도 FDS 디스크 이미지</comment>
- <comment xml:lang="pl">Obraz dysku Nintendo FDS</comment>
- <comment xml:lang="pt_BR">Imagem de disco Nintendo FDS</comment>
- <comment xml:lang="ru">Образ диска Nintendo FDS</comment>
- <comment xml:lang="sk">Obraz disku Nintendo FDS</comment>
- <comment xml:lang="sr">Нинтендо ФДС слика диска</comment>
- <comment xml:lang="sv">Nintendo FDS-diskavbild</comment>
- <comment xml:lang="tr">Nintendo FDS disk kalıbı</comment>
- <comment xml:lang="uk">образ диска FDS Nintendo</comment>
- <comment xml:lang="zh_CN">任天堂 FDS 磁盘映像</comment>
<comment xml:lang="zh_TW">Nintendo FDS 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">任天堂 FDS 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска FDS Nintendo</comment>
+ <comment xml:lang="tr">Nintendo FDS disk görüntüsü</comment>
+ <comment xml:lang="sv">Nintendo FDS-diskavbild</comment>
+ <comment xml:lang="sr">Нинтендо ФДС слика диска</comment>
+ <comment xml:lang="sq">pamje disku Nintendo FDS</comment>
+ <comment xml:lang="sl">Slika diska Nintendo FDS</comment>
+ <comment xml:lang="si">Nintendo FDS තැටි රූපය</comment>
+ <comment xml:lang="sk">Obraz disku Nintendo FDS</comment>
+ <comment xml:lang="ru">Образ диска Nintendo FDS</comment>
+ <comment xml:lang="pt_BR">Imagem de disco Nintendo FDS</comment>
+ <comment xml:lang="pl">Obraz dysku Nintendo FDS</comment>
+ <comment xml:lang="nl">Nintendo FDS-schijfkopiebestand</comment>
+ <comment xml:lang="ko">닌텐도 FDS 디스크 이미지</comment>
+ <comment xml:lang="kk">Nintendo FDS диск бейнесі</comment>
+ <comment xml:lang="ja">Nintendo FDS ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco Nintendo FDS</comment>
+ <comment xml:lang="is">Nintendo FDS diskmynd</comment>
+ <comment xml:lang="id">Image disk Nintendo FDS</comment>
+ <comment xml:lang="hu">Nintendo FDS lemezkép</comment>
+ <comment xml:lang="hr">Nintendo FDS slika diska</comment>
+ <comment xml:lang="he">תמונת כונן Nintendo FDS</comment>
+ <comment xml:lang="ga">íomhá diosca Nintendo FDS</comment>
+ <comment xml:lang="fur">imagjin disc Nintendo FDS</comment>
+ <comment xml:lang="fr">image disque Nintendo FDS</comment>
+ <comment xml:lang="fi">Nintendo FDS -levykuva</comment>
+ <comment xml:lang="eu">Nintendo FDS disko irudia</comment>
+ <comment xml:lang="es">imagen de disco FDS de Nintendo</comment>
+ <comment xml:lang="en_GB">Nintendo FDS disk image</comment>
+ <comment xml:lang="de">Nintendo-FDS-Datenträgerabbild</comment>
+ <comment xml:lang="da">Nintendo FDS-diskaftryk</comment>
+ <comment xml:lang="cs">obraz disku pro Nintendo FDS</comment>
+ <comment xml:lang="ca">imatge de disc Nintendo FDS</comment>
+ <comment xml:lang="bg">Диск — Nintendo FDS</comment>
+ <comment xml:lang="be">вобраз дыска Nintendo FDS</comment>
+ <comment xml:lang="ar">صورة قرص نينتندو اف دي اس</comment>
+ <comment xml:lang="af">Nintendo FDS-skyfbeeldlêer</comment>
<acronym>FDS</acronym>
<expanded-acronym>Famicom Disk System</expanded-acronym>
<glob pattern="*.fds"/>
<magic>
- <match value="*NINTENDO-HVC*" type="string" offset="1"/>
+ <match type="string" value="*NINTENDO-HVC*" offset="1"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/ovf">
+ <comment>OVF disk image</comment>
+ <comment xml:lang="zh_CN">OVF 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска OVF</comment>
+ <comment xml:lang="tr">OVF disk görüntüsü</comment>
+ <comment xml:lang="sv">OVF-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska OVF</comment>
+ <comment xml:lang="si">OVF තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска OVF</comment>
+ <comment xml:lang="pt_BR">Imagem de disco OVF</comment>
+ <comment xml:lang="pl">Obraz dysku OVF</comment>
+ <comment xml:lang="nl">OVF-schijfkopiebestand</comment>
+ <comment xml:lang="ko">OVF 디스크 이미지</comment>
+ <comment xml:lang="kk">OVF диск бейнесі</comment>
+ <comment xml:lang="ja">OVF ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco OVF</comment>
+ <comment xml:lang="hr">OVF slika diska</comment>
+ <comment xml:lang="fi">OVF-levykuva</comment>
+ <comment xml:lang="eu">OVF disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco OVF</comment>
+ <comment xml:lang="en_GB">OVF disk image</comment>
+ <comment xml:lang="de">OVF-Datenträgerabbild</comment>
+ <comment xml:lang="be">вобраз дыска OVF</comment>
+ <comment xml:lang="ar">صورة قرص OVF</comment>
+ <acronym>OVF</acronym>
+ <expanded-acronym>Open Virtualization Format</expanded-acronym>
+ <glob pattern="*.ova"/>
+ <magic priority="62">
+ <match type="string" value=".ovf" offset="1:256">
+ <match type="string" value="ustar\0" offset="257"/>
+ <match type="string" value="ustar\040\040\0" offset="257"/>
+ </match>
</magic>
+ <alias type="application/x-virtualbox-ova"/>
+ <sub-class-of type="application/x-tar"/>
+ </mime-type>
+ <mime-type type="application/x-qed-disk">
+ <comment>QEMU QED disk image</comment>
+ <comment xml:lang="zh_TW">QEMU QED 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">QEMU QED 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска QED QEMU</comment>
+ <comment xml:lang="tr">QEMU QED disk görüntüsü</comment>
+ <comment xml:lang="sv">QEMU QED-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska QEMU QED</comment>
+ <comment xml:lang="si">QEMU QED තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска QEMU QED</comment>
+ <comment xml:lang="pt_BR">Imagem de disco QEMU QED</comment>
+ <comment xml:lang="pl">Obraz dysku QED QEMU</comment>
+ <comment xml:lang="nl">QEMU QED-schijfkopiebestand</comment>
+ <comment xml:lang="ko">QEMU QED 디스크 이미지</comment>
+ <comment xml:lang="kk">QEMU QED диск бейнесі</comment>
+ <comment xml:lang="ja">QEMU QED ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco QEMU QED</comment>
+ <comment xml:lang="hr">QEMU QED slika diska</comment>
+ <comment xml:lang="fi">QEMU QED-levykuva</comment>
+ <comment xml:lang="eu">QEMU QED disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco QED de QEMU</comment>
+ <comment xml:lang="en_GB">QEMU QED disk image</comment>
+ <comment xml:lang="de">QEMU-QED-Datenträgerabbild</comment>
+ <comment xml:lang="be">вобраз дыска QEMU QED</comment>
+ <comment xml:lang="ar">صورة قرص QEMU QED</comment>
+ <acronym>QED</acronym>
+ <expanded-acronym>QEMU Enhanced Disk</expanded-acronym>
+ <glob pattern="*.qed"/>
+ <magic>
+ <match type="string" value="QED\0" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-qemu-disk">
+ <comment>QEMU QCOW disk image</comment>
+ <comment xml:lang="zh_TW">QEMU QCOW 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">QEMU QCOW 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска QCOW QEMU</comment>
+ <comment xml:lang="tr">QEMU QCOW disk görüntüsü</comment>
+ <comment xml:lang="sv">QEMU QCOW-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska QEMU QCOW</comment>
+ <comment xml:lang="si">QEMU QCOW තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска QEMU QCOW</comment>
+ <comment xml:lang="pt_BR">Imagem de disco QEMU QCOW</comment>
+ <comment xml:lang="pl">Obraz dysku QCOW QEMU</comment>
+ <comment xml:lang="nl">QEMU QCOW-schijfkopiebestand</comment>
+ <comment xml:lang="ko">QEMU QCOW 디스크 이미지</comment>
+ <comment xml:lang="kk">QEMU QCOW диск бейнесі</comment>
+ <comment xml:lang="ja">QEMU QCOW ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco QEMU QCOW</comment>
+ <comment xml:lang="is">QEMU QCOW diskmynd</comment>
+ <comment xml:lang="id">Image disk QCOW QEMU</comment>
+ <comment xml:lang="hu">QEMU QCOW lemezkép</comment>
+ <comment xml:lang="hr">QEMU QCOW slika diska</comment>
+ <comment xml:lang="he">תמונת כונן QEMU QCOW</comment>
+ <comment xml:lang="fr">image disque QEMU QCOW</comment>
+ <comment xml:lang="fi">QEMU QCOW -levykuva</comment>
+ <comment xml:lang="eu">QEMU QCOW disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco QCOW de QEMU</comment>
+ <comment xml:lang="en_GB">QEMU QCOW disk image</comment>
+ <comment xml:lang="de">QEMU-QCOW-Datenträgerabbild</comment>
+ <comment xml:lang="da">QEMU QCOW-diskaftryk</comment>
+ <comment xml:lang="ca">imatge de disc QEMU QCOW</comment>
+ <comment xml:lang="be">вобраз дыска QEMU QCOW</comment>
+ <comment xml:lang="ar">صورة قرص QEMU QCOW</comment>
+ <acronym>QCOW</acronym>
+ <expanded-acronym>QEMU Copy On Write</expanded-acronym>
+ <glob pattern="*.qcow2"/>
+ <glob pattern="*.qcow"/>
+ <magic>
+ <match type="string" value="QFI" offset="0">
+ <match value="0xfb" type="byte" offset="3"/>
+ </match>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-vhd-disk">
+ <comment>VHD disk image</comment>
+ <comment xml:lang="zh_TW">VHD 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">VHD 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска VHD</comment>
+ <comment xml:lang="tr">VHD disk görüntüsü</comment>
+ <comment xml:lang="sv">VHD-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska VHD</comment>
+ <comment xml:lang="si">VHD තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска VHD</comment>
+ <comment xml:lang="pt_BR">Imagem de disco VHD</comment>
+ <comment xml:lang="pl">Obraz dysku VHD</comment>
+ <comment xml:lang="nl">VHD-schijfkopiebestand</comment>
+ <comment xml:lang="ko">VHD 디스크 이미지</comment>
+ <comment xml:lang="kk">VHD диск бейнесі</comment>
+ <comment xml:lang="ja">VHD ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco VHD</comment>
+ <comment xml:lang="hr">VHD slika diska</comment>
+ <comment xml:lang="fi">VHD-levykuva</comment>
+ <comment xml:lang="eu">VHD disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco VHD</comment>
+ <comment xml:lang="en_GB">VHD disk image</comment>
+ <comment xml:lang="de">VHD-Datenträgerabbild</comment>
+ <comment xml:lang="be">вобраз дыска VHD</comment>
+ <comment xml:lang="ar">صورة قرص VHD</comment>
+ <acronym>VHD</acronym>
+ <expanded-acronym>Virtual Hard Disk</expanded-acronym>
+ <glob pattern="*.vhd"/>
+ <glob pattern="*.vpc"/>
+ <magic>
+ <match type="string" value="conectix" offset="0"/>
+ </magic>
+ <alias type="application/x-virtualbox-vhd"/>
+ </mime-type>
+ <mime-type type="application/x-vhdx-disk">
+ <comment>VHDX disk image</comment>
+ <comment xml:lang="zh_TW">VHDX 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">VHDX 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска VHDX</comment>
+ <comment xml:lang="tr">VHDX disk görüntüsü</comment>
+ <comment xml:lang="sv">VHDX-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska VHDX</comment>
+ <comment xml:lang="si">VHDX තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска VHDX</comment>
+ <comment xml:lang="pt_BR">Imagem de disco VHDX</comment>
+ <comment xml:lang="pl">Obraz dysku VHDX</comment>
+ <comment xml:lang="nl">VHDX-schijfkopiebestand</comment>
+ <comment xml:lang="ko">VHDX 디스크 이미지</comment>
+ <comment xml:lang="kk">VHDX диск бейнесі</comment>
+ <comment xml:lang="ja">VHDX ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco VHDX</comment>
+ <comment xml:lang="hr">VHDX slika diska</comment>
+ <comment xml:lang="fi">VHDX-levykuva</comment>
+ <comment xml:lang="eu">VHDX disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco VHDX</comment>
+ <comment xml:lang="en_GB">VHDX disk image</comment>
+ <comment xml:lang="de">VHDX-Datenträgerabbild</comment>
+ <comment xml:lang="be">вобраз дыска VHDX</comment>
+ <comment xml:lang="ar">صورة قرص VHDX</comment>
+ <acronym>VHDX</acronym>
+ <expanded-acronym>Virtual Hard Disk v2</expanded-acronym>
+ <glob pattern="*.vhdx"/>
+ <magic>
+ <match type="string" value="vhdxfile" offset="0"/>
+ </magic>
+ <alias type="application/x-virtualbox-vhdx"/>
+ </mime-type>
+ <mime-type type="application/x-vmdk-disk">
+ <comment>VMDK disk image</comment>
+ <comment xml:lang="zh_TW">VMDK 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">VMDK 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска VMDK</comment>
+ <comment xml:lang="tr">VMDK disk görüntüsü</comment>
+ <comment xml:lang="sv">VMDK-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska VMDK</comment>
+ <comment xml:lang="si">VMDK තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска VMDK</comment>
+ <comment xml:lang="pt_BR">Imagem de disco VMDK</comment>
+ <comment xml:lang="pl">Obraz dysku VMDK</comment>
+ <comment xml:lang="nl">VMDK-schijfkopiebestand</comment>
+ <comment xml:lang="ko">VMDK 디스크 이미지</comment>
+ <comment xml:lang="kk">VMDK диск бейнесі</comment>
+ <comment xml:lang="ja">VMDK ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco VMDK</comment>
+ <comment xml:lang="hr">VMDK slika diska</comment>
+ <comment xml:lang="fi">VMDK-levykuva</comment>
+ <comment xml:lang="eu">VMDK disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco VMDK</comment>
+ <comment xml:lang="en_GB">VMDK disk image</comment>
+ <comment xml:lang="de">VMDK-Datenträgerabbild</comment>
+ <comment xml:lang="be">вобраз дыска VMDK</comment>
+ <comment xml:lang="ar">صورة قرص VMDK</comment>
+ <acronym>VMDK</acronym>
+ <expanded-acronym>Virtual Machine Disk</expanded-acronym>
+ <glob pattern="*.vmdk"/>
+ <magic>
+ <match type="string" value="KDMV\x01\x00\x00\x00" offset="0"/>
+ <match type="string" value="KDMV\x02\x00\x00\x00" offset="0"/>
+ </magic>
+ <alias type="application/x-virtualbox-vmdk"/>
+ </mime-type>
+ <mime-type type="application/x-vdi-disk">
+ <comment>VDI disk image</comment>
+ <comment xml:lang="zh_TW">VDI 磁碟映像檔</comment>
+ <comment xml:lang="zh_CN">VDI 磁盘映像</comment>
+ <comment xml:lang="uk">образ диска VDI</comment>
+ <comment xml:lang="tr">VDI disk görüntüsü</comment>
+ <comment xml:lang="sv">VDI-diskavbildning</comment>
+ <comment xml:lang="sl">Slika diska VDI</comment>
+ <comment xml:lang="si">VDI තැටි රූපය</comment>
+ <comment xml:lang="ru">Образ диска VDI</comment>
+ <comment xml:lang="pt_BR">Imagem de disco VDI</comment>
+ <comment xml:lang="pl">Obraz dysku VDI</comment>
+ <comment xml:lang="nl">VDI-schijfkopiebestand</comment>
+ <comment xml:lang="ko">VDI 디스크 이미지</comment>
+ <comment xml:lang="kk">VDI диск бейнесі</comment>
+ <comment xml:lang="ja">VDI ディスクイメージ</comment>
+ <comment xml:lang="it">Immagine disco VDI</comment>
+ <comment xml:lang="hr">VDI slika diska</comment>
+ <comment xml:lang="fi">VDI-levykuva</comment>
+ <comment xml:lang="eu">VDI disko-irudia</comment>
+ <comment xml:lang="es">imagen de disco VDI</comment>
+ <comment xml:lang="en_GB">VDI disk image</comment>
+ <comment xml:lang="de">VDI-Datenträgerabbild</comment>
+ <comment xml:lang="be">вобраз дыска VDI</comment>
+ <comment xml:lang="ar">صورة قرص VDI</comment>
+ <acronym>VDI</acronym>
+ <expanded-acronym>Virtual Disk Image</expanded-acronym>
+ <glob pattern="*.vdi"/>
+ <magic>
+ <match type="string" value="&lt;&lt;&lt; QEMU VM Virtual Disk Image &gt;&gt;&gt;\n" offset="0"/>
+ <match type="string" value="&lt;&lt;&lt; Oracle VM VirtualBox Disk Image &gt;&gt;&gt;\n" offset="0"/>
+ <match type="string" value="&lt;&lt;&lt; Sun VirtualBox Disk Image &gt;&gt;&gt;\n" offset="0"/>
+ <match type="string" value="&lt;&lt;&lt; Sun xVM VirtualBox Disk Image &gt;&gt;&gt;\n" offset="0"/>
+ <match type="string" value="&lt;&lt;&lt; innotek VirtualBox Disk Image &gt;&gt;&gt;" offset="0"/>
+ <match type="string" value="&lt;&lt;&lt; CloneVDI VirtualBox Disk Image &gt;&gt;&gt;\n" offset="0"/>
+ </magic>
+ <alias type="application/x-virtualbox-vdi"/>
+ </mime-type>
+ <mime-type type="application/x-appleworks-document">
+ <comment>AppleWorks document</comment>
+ <comment xml:lang="zh_TW">AppleWorks 文件</comment>
+ <comment xml:lang="zh_CN">AppleWorks 文档</comment>
+ <comment xml:lang="uk">документ AppleWorks</comment>
+ <comment xml:lang="tr">AppleWorks belgesi</comment>
+ <comment xml:lang="sv">AppleWorks-dokument</comment>
+ <comment xml:lang="sl">Dokument AppleWorks</comment>
+ <comment xml:lang="si">AppleWorks ලේඛනය</comment>
+ <comment xml:lang="ru">Документ AppleWorks</comment>
+ <comment xml:lang="pt_BR">Documento AppleWorks</comment>
+ <comment xml:lang="pl">Dokument AppleWorks</comment>
+ <comment xml:lang="oc">document AppleWorks</comment>
+ <comment xml:lang="nl">AppleWorks-document</comment>
+ <comment xml:lang="ko">AppleWorks 문서</comment>
+ <comment xml:lang="kk">AppleWorks құжаты</comment>
+ <comment xml:lang="ja">AppleWorks ドキュメント</comment>
+ <comment xml:lang="it">Documento AppleWorks</comment>
+ <comment xml:lang="is">AppleWorks skjal</comment>
+ <comment xml:lang="id">Dokumen AppleWorks</comment>
+ <comment xml:lang="hu">AppleWorks-dokumentum</comment>
+ <comment xml:lang="hr">AppleWorks dokument</comment>
+ <comment xml:lang="he">מסמך AppleWorks</comment>
+ <comment xml:lang="fr">document AppleWorks</comment>
+ <comment xml:lang="fi">AppleWorks-asiakirja</comment>
+ <comment xml:lang="eu">AppleWorks dokumentua</comment>
+ <comment xml:lang="es">documento de AppleWorks</comment>
+ <comment xml:lang="en_GB">AppleWorks document</comment>
+ <comment xml:lang="de">AppleWorks-Dokument</comment>
+ <comment xml:lang="da">AppleWorks-dokument</comment>
+ <comment xml:lang="ca">document AppleWorks</comment>
+ <comment xml:lang="be">дакумент AppleWorks</comment>
+ <comment xml:lang="ar">مستند AppleWorks</comment>
+ <generic-icon name="x-office-document"/>
+ <glob pattern="*.cwk"/>
+ </mime-type>
+ <mime-type type="application/x-bps-patch">
+ <comment>BPS patch</comment>
+ <comment xml:lang="zh_TW">BPS 修補檔</comment>
+ <comment xml:lang="zh_CN">BPS 补丁</comment>
+ <comment xml:lang="uk">латка BPS</comment>
+ <comment xml:lang="tr">BPS yaması</comment>
+ <comment xml:lang="sv">BPS-patch</comment>
+ <comment xml:lang="sl">Popravek BPS</comment>
+ <comment xml:lang="si">BPS පැච්</comment>
+ <comment xml:lang="sk">Záplata BPS</comment>
+ <comment xml:lang="ru">Патч BPS</comment>
+ <comment xml:lang="pt_BR">Patch BPS</comment>
+ <comment xml:lang="pl">Łata BPS</comment>
+ <comment xml:lang="nl">BPS-patch</comment>
+ <comment xml:lang="ko">BPS 패치</comment>
+ <comment xml:lang="kk">BPS өзгерісі</comment>
+ <comment xml:lang="ja">BPS パッチ</comment>
+ <comment xml:lang="it">Patch BPS</comment>
+ <comment xml:lang="is">BPS kóðabót</comment>
+ <comment xml:lang="id">Patch BPS</comment>
+ <comment xml:lang="hu">BPS javítócsomag</comment>
+ <comment xml:lang="hr">BPS zakrpa</comment>
+ <comment xml:lang="he">טלאי BPS</comment>
+ <comment xml:lang="fr">correctif BPS</comment>
+ <comment xml:lang="fi">BPS-korjaus</comment>
+ <comment xml:lang="es">parche BPS</comment>
+ <comment xml:lang="en_GB">BPS patch</comment>
+ <comment xml:lang="de">BPS-Patch</comment>
+ <comment xml:lang="da">BPS-rettelse</comment>
+ <comment xml:lang="ca">pedaç de BPS</comment>
+ <comment xml:lang="be">патч BPS</comment>
+ <comment xml:lang="ar">رقعة BPS</comment>
+ <acronym>BPS</acronym>
+ <expanded-acronym>Binary Patching System</expanded-acronym>
+ <glob pattern="*.bps"/>
+ <magic>
+ <match type="string" value="BPS1" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-ips-patch">
+ <comment>IPS patch</comment>
+ <comment xml:lang="zh_TW">IPS 修補檔</comment>
+ <comment xml:lang="zh_CN">IPS 补丁</comment>
+ <comment xml:lang="uk">латка IPS</comment>
+ <comment xml:lang="tr">IPS yaması</comment>
+ <comment xml:lang="sv">IPS-patch</comment>
+ <comment xml:lang="sl">Popravek IPS</comment>
+ <comment xml:lang="si">IPS පැච්</comment>
+ <comment xml:lang="ru">Патч IPS</comment>
+ <comment xml:lang="pt_BR">Patch IPS</comment>
+ <comment xml:lang="pl">Łata IPS</comment>
+ <comment xml:lang="nl">IPS-patch</comment>
+ <comment xml:lang="ko">IPS 패치</comment>
+ <comment xml:lang="kk">IPS өзгерісі</comment>
+ <comment xml:lang="ja">IPS パッチ</comment>
+ <comment xml:lang="it">Patch IPS</comment>
+ <comment xml:lang="is">IPS kóðabót</comment>
+ <comment xml:lang="id">Patch IPS</comment>
+ <comment xml:lang="hu">IPS javítócsomag</comment>
+ <comment xml:lang="hr">IPS zakrpa</comment>
+ <comment xml:lang="he">טלאי IPS</comment>
+ <comment xml:lang="fr">correctif IPS</comment>
+ <comment xml:lang="fi">IPS-korjaus</comment>
+ <comment xml:lang="es">parche IPS</comment>
+ <comment xml:lang="en_GB">IPS patch</comment>
+ <comment xml:lang="de">IPS-Patch</comment>
+ <comment xml:lang="da">IPS-rettelse</comment>
+ <comment xml:lang="ca">pedaç d'IPS</comment>
+ <comment xml:lang="be">патч IPS</comment>
+ <comment xml:lang="ar">رقعة IPS</comment>
+ <acronym>IPS</acronym>
+ <expanded-acronym>International Patching System</expanded-acronym>
+ <glob pattern="*.ips"/>
+ <magic>
+ <match type="string" value="PATCH" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-pyspread-spreadsheet">
+ <comment>Pyspread spreadsheet</comment>
+ <comment xml:lang="zh_TW">Pyspread 試算表</comment>
+ <comment xml:lang="zh_CN">Pyspread 电子表格</comment>
+ <comment xml:lang="uk">електронна таблиця Pyspread</comment>
+ <comment xml:lang="tr">Pyspread hesap çizelgesi</comment>
+ <comment xml:lang="sv">Pyspread-kalkylblad</comment>
+ <comment xml:lang="sl">Preglednica Pyspread</comment>
+ <comment xml:lang="si">Pyspread පැතුරුම්පත</comment>
+ <comment xml:lang="ru">Электронная таблица Pyspread</comment>
+ <comment xml:lang="pt_BR">Planilha do Pyspread</comment>
+ <comment xml:lang="pl">Arkusz pyspread</comment>
+ <comment xml:lang="nl">Pyspread werkblad</comment>
+ <comment xml:lang="ko">Pyspread 스프레드시트</comment>
+ <comment xml:lang="kk">Pyspread электрондық кестесі</comment>
+ <comment xml:lang="ja">Pyspread スプレッドシート</comment>
+ <comment xml:lang="it">Foglio di calcolo Pyspread</comment>
+ <comment xml:lang="is">Pyspread töflureikniskjal</comment>
+ <comment xml:lang="id">lembar kerja Pyspread</comment>
+ <comment xml:lang="hu">Pyspread-munkafüzet</comment>
+ <comment xml:lang="hr">Pyspread proračunska tablica</comment>
+ <comment xml:lang="he">גיליון Pyspread</comment>
+ <comment xml:lang="fr">feuille de calcul Pyspread</comment>
+ <comment xml:lang="fi">Pyspread-taulukko</comment>
+ <comment xml:lang="es">hoja de cálculo de Pyspread</comment>
+ <comment xml:lang="en_GB">Pyspread spreadsheet</comment>
+ <comment xml:lang="de">Pyspread-Tabelle</comment>
+ <comment xml:lang="da">Pyspread-regneark</comment>
+ <comment xml:lang="ca">full de càlcul de Pyspread</comment>
+ <comment xml:lang="be">электронная табліца Pyspread</comment>
+ <comment xml:lang="ar">ورقة عمل Pyspread</comment>
+ <glob pattern="*.pysu"/>
+ <magic>
+ <match type="string" value="[Pyspread save file version]" offset="0"/>
+ </magic>
+ <generic-icon name="x-office-spreadsheet"/>
+ </mime-type>
+ <mime-type type="application/x-pyspread-bz-spreadsheet">
+ <comment>Pyspread spreadsheet (bzip2-compressed)</comment>
+ <comment xml:lang="uk">електронна таблиця Pyspread (стиснена bzip2)</comment>
+ <comment xml:lang="sv">Pyspread-kalkylblad (bzip2-komprimerat)</comment>
+ <comment xml:lang="ru">Электронная таблица Pyspread (сжатая bzip2)</comment>
+ <comment xml:lang="pl">Arkusz pyspread (kompresja bzip2)</comment>
+ <comment xml:lang="es">hoja de cálculo de Pyspread (comprimida con BZIP2)</comment>
+ <comment xml:lang="de">Pyspread-Tabelle (bzip2-komprimiert)</comment>
+ <sub-class-of type="application/x-bzip2"/>
+ <glob pattern="*.pys"/>
+ <generic-icon name="x-office-spreadsheet"/>
+ </mime-type>
+ <mime-type type="text/x-kotlin">
+ <comment>Kotlin source code</comment>
+ <comment xml:lang="zh_TW">Kotlin 原始碼</comment>
+ <comment xml:lang="zh_CN">Kotlin 源代码</comment>
+ <comment xml:lang="uk">початковий код мовою Kotlin</comment>
+ <comment xml:lang="tr">Kotlin kaynak kodu</comment>
+ <comment xml:lang="sv">Kotlin-källkod</comment>
+ <comment xml:lang="sl">Izvorna koda Kotlin</comment>
+ <comment xml:lang="si">Kotlin මූල කේතය</comment>
+ <comment xml:lang="ru">Исходный код Kotlin</comment>
+ <comment xml:lang="pt_BR">Código-fonte Kotlin</comment>
+ <comment xml:lang="pl">Kod źródłowy Kotlin</comment>
+ <comment xml:lang="oc">còdi font Kotlin</comment>
+ <comment xml:lang="nl">Kotlin-broncode</comment>
+ <comment xml:lang="ko">Kotlin 소스 코드</comment>
+ <comment xml:lang="kk">Kotlin бастапқы коды</comment>
+ <comment xml:lang="ja">Kotlin ソースコード</comment>
+ <comment xml:lang="it">Codice sorgente Kotlin</comment>
+ <comment xml:lang="is">Kotlin frumkóði</comment>
+ <comment xml:lang="id">kode sumber Kotlin</comment>
+ <comment xml:lang="hu">Kotlin forráskód</comment>
+ <comment xml:lang="hr">Kotlin izvorni kôd</comment>
+ <comment xml:lang="he">קוד מקור של Kotlin</comment>
+ <comment xml:lang="gl">Código fonte en Kotlin</comment>
+ <comment xml:lang="fr">code source Kotlin</comment>
+ <comment xml:lang="fi">Kotlin-lähdekoodi</comment>
+ <comment xml:lang="es">código fuente en Kotlin</comment>
+ <comment xml:lang="en_GB">Kotlin source code</comment>
+ <comment xml:lang="de">Kotlin-Quelltext</comment>
+ <comment xml:lang="da">Kotlin-kildekode</comment>
+ <comment xml:lang="ca">codi font en Kotlin</comment>
+ <comment xml:lang="be">зыходны код Kotlin</comment>
+ <comment xml:lang="ar">شفرة مصدر Kotlin</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.kt"/>
+ </mime-type>
+ <mime-type type="text/x-devicetree-source">
+ <comment>Devicetree source code</comment>
+ <comment xml:lang="uk">початковий код devicetree</comment>
+ <comment xml:lang="sv">Enhetsträdskällkod</comment>
+ <comment xml:lang="ru">Исходный код Devicetree</comment>
+ <comment xml:lang="pl">Kod źródłowy DeviceTree</comment>
+ <comment xml:lang="it">Codice sorgente Devicetree</comment>
+ <comment xml:lang="gl">Código fonte en Devicetree</comment>
+ <comment xml:lang="es">código fuente de árbol de dispositivos</comment>
+ <comment xml:lang="de">Gerätebaum-Quelltext</comment>
+ <comment xml:lang="be">зыходны код Devicetree</comment>
+ <acronym>DTS</acronym>
+ <expanded-acronym>Device Tree Source</expanded-acronym>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.dts"/>
+ <glob pattern="*.dtsi"/>
+ <magic>
+ <match type="string" mask="0x8080" value="\000\000" offset="0">
+ <match type="string" value="/dts-v1/" offset="0:4080"/>
+ </match>
+ </magic>
+ <magic priority="40">
+ <match type="string" mask="0x8080" value="\000\000" offset="0">
+ <match type="string" value="/ {" offset="0:4090"/>
+ <match type="string" value="include " offset="0:4080">
+ <match type="string" value=".dts" offset="10:4090"/>
+ </match>
+ </match>
+ </magic>
+ </mime-type>
+ <mime-type type="text/x-devicetree-binary">
+ <comment>Flattened Devicetree</comment>
+ <comment xml:lang="uk">зведене Devicetree</comment>
+ <comment xml:lang="sv">Utplattat enhetsträd</comment>
+ <comment xml:lang="ru">Плоское дерево устройств</comment>
+ <comment xml:lang="pl">Spłaszczone DeviceTree</comment>
+ <comment xml:lang="it">Devicetree compatto</comment>
+ <comment xml:lang="es">árbol de dispositivos aplanado</comment>
+ <comment xml:lang="de">Verflachter Gerätebaum</comment>
+ <acronym>DTB</acronym>
+ <expanded-acronym>Device Tree Binary</expanded-acronym>
+ <glob pattern="*.dtb"/>
+ <magic>
+ <match type="big32" value="0xd00dfeed" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="image/avif">
+ <comment>AVIF image</comment>
+ <comment xml:lang="zh_TW">AVIF 影像</comment>
+ <comment xml:lang="zh_CN">AVIF 图像</comment>
+ <comment xml:lang="uk">зображення AVIF</comment>
+ <comment xml:lang="tr">AVIF görüntüsü</comment>
+ <comment xml:lang="sv">AVIF-bild</comment>
+ <comment xml:lang="sl">Slika AVIF</comment>
+ <comment xml:lang="si">AVIF රූපය</comment>
+ <comment xml:lang="ru">Изображение AVIF</comment>
+ <comment xml:lang="pt_BR">Imagem AVIF</comment>
+ <comment xml:lang="pl">Obraz AVIF</comment>
+ <comment xml:lang="oc">imatge AVIF</comment>
+ <comment xml:lang="nl">AVIF-afbeelding</comment>
+ <comment xml:lang="ko">AVIF 그림</comment>
+ <comment xml:lang="kk">AVIF суреті</comment>
+ <comment xml:lang="ja">AVIF 画像</comment>
+ <comment xml:lang="it">Immagine AVIF</comment>
+ <comment xml:lang="hr">AVIF slika</comment>
+ <comment xml:lang="fi">AVIF-kuva</comment>
+ <comment xml:lang="eu">AVIF irudia</comment>
+ <comment xml:lang="es">imagen AVIF</comment>
+ <comment xml:lang="en_GB">AVIF image</comment>
+ <comment xml:lang="de">AVIF-Bild</comment>
+ <comment xml:lang="be">выява AVIF</comment>
+ <comment xml:lang="ar">صورة AVIF</comment>
+ <acronym>AVIF</acronym>
+ <expanded-acronym>AV1 Image File Format</expanded-acronym>
+ <magic>
+ <match type="string" value="ftypavif" offset="4"/>
+ <match type="string" value="ftypavis" offset="4"/>
+ <match type="string" value="ftypmif1" offset="4">
+ <match type="string" value="avif" offset="16"/>
+ <match type="string" value="avif" offset="20"/>
+ <match type="string" value="avif" offset="24"/>
+ </match>
+ </magic>
+ <glob pattern="*.avif"/>
+ <glob pattern="*.avifs"/>
+ <alias type="image/avif-sequence"/>
+ </mime-type>
+ <mime-type type="image/qoi">
+ <comment>Quite OK Image Format</comment>
+ <comment xml:lang="uk">формат зображень Quite OK</comment>
+ <comment xml:lang="sv">Quite OK Image-format</comment>
+ <comment xml:lang="ru">Формат изображений Quite OK</comment>
+ <comment xml:lang="pl">Obraz QOI</comment>
+ <comment xml:lang="it">Formato immagine Quite OK</comment>
+ <comment xml:lang="es">formato de imagen Quite OK</comment>
+ <comment xml:lang="de">Quite-OK-Bildformat</comment>
+ <magic>
+ <match type="string" value="qoif" offset="0"/>
+ </magic>
+ <glob pattern="*.qoi"/>
+ </mime-type>
+ <mime-type type="video/vnd.radgamettools.bink">
+ <comment>Bink Video</comment>
+ <comment xml:lang="zh_CN">Bink 视频</comment>
+ <comment xml:lang="uk">відео Bink</comment>
+ <comment xml:lang="tr">Bink Videosu</comment>
+ <comment xml:lang="sv">Bink-video</comment>
+ <comment xml:lang="sl">Video Bink</comment>
+ <comment xml:lang="si">බින්ක් වීඩියෝව</comment>
+ <comment xml:lang="ru">Видео Bink</comment>
+ <comment xml:lang="pt_BR">Vídeo Bink</comment>
+ <comment xml:lang="pl">Plik wideo Bink</comment>
+ <comment xml:lang="nl">Bink-video</comment>
+ <comment xml:lang="ko">Bink 동영상</comment>
+ <comment xml:lang="kk">Bink видеосы</comment>
+ <comment xml:lang="ja">Bink 動画</comment>
+ <comment xml:lang="it">Video Bink</comment>
+ <comment xml:lang="hr">Bink video snimka</comment>
+ <comment xml:lang="fi">Bink Video</comment>
+ <comment xml:lang="eu">Bink bideoa</comment>
+ <comment xml:lang="es">vídeo BINK</comment>
+ <comment xml:lang="en_GB">Bink Video</comment>
+ <comment xml:lang="de">Bink-Video</comment>
+ <comment xml:lang="be">відэа Bink</comment>
+ <comment xml:lang="ar">فيديو Bink</comment>
+ <magic>
+ <match type="string" value="BIK" offset="0">
+ <match type="string" value="b" offset="3"/>
+ <match type="string" value="f" offset="3"/>
+ <match type="string" value="g" offset="3"/>
+ <match type="string" value="h" offset="3"/>
+ <match type="string" value="i" offset="3"/>
+ </match>
+ <match type="string" value="KB2" offset="0">
+ <match type="string" value="a" offset="3"/>
+ <match type="string" value="d" offset="3"/>
+ <match type="string" value="f" offset="3"/>
+ <match type="string" value="g" offset="3"/>
+ <match type="string" value="h" offset="3"/>
+ <match type="string" value="i" offset="3"/>
+ <match type="string" value="j" offset="3"/>
+ <match type="string" value="k" offset="3"/>
+ </match>
+ </magic>
+ <glob pattern="*.bik"/>
+ <glob pattern="*.bk2"/>
+ </mime-type>
+ <mime-type type="video/vnd.radgamettools.smacker">
+ <comment>Smacker Video</comment>
+ <comment xml:lang="zh_CN">Smacker 视频</comment>
+ <comment xml:lang="uk">відео Smacker</comment>
+ <comment xml:lang="tr">Smacker Videosu</comment>
+ <comment xml:lang="sv">Smacker-video</comment>
+ <comment xml:lang="sl">Video Smacker</comment>
+ <comment xml:lang="si">ස්මකර් වීඩියෝව</comment>
+ <comment xml:lang="ru">Видео Smacker</comment>
+ <comment xml:lang="pt_BR">Vídeo Smacker</comment>
+ <comment xml:lang="pl">Plik wideo Smacker</comment>
+ <comment xml:lang="nl">Smacker-video</comment>
+ <comment xml:lang="ko">Smacker 동영상</comment>
+ <comment xml:lang="kk">Smacker видеосы</comment>
+ <comment xml:lang="ja">Smacker 動画</comment>
+ <comment xml:lang="it">Video Smacker</comment>
+ <comment xml:lang="hr">Smacker video snimka</comment>
+ <comment xml:lang="fi">Smacker Video</comment>
+ <comment xml:lang="eu">Smacker bideoa</comment>
+ <comment xml:lang="es">vídeo Smacker</comment>
+ <comment xml:lang="en_GB">Smacker Video</comment>
+ <comment xml:lang="de">Smacker-Video</comment>
+ <comment xml:lang="be">відэа Smacker</comment>
+ <comment xml:lang="ar">فيديو Smacker</comment>
+ <magic>
+ <match type="string" value="SMK" offset="0">
+ <match type="string" value="2" offset="3"/>
+ <match type="string" value="4" offset="3"/>
+ </match>
+ </magic>
+ <glob pattern="*.smk"/>
+ </mime-type>
+ <mime-type type="text/org">
+ <comment>Org-mode file</comment>
+ <comment xml:lang="zh_CN">Org-mode 文件</comment>
+ <comment xml:lang="uk">файл Org-mode</comment>
+ <comment xml:lang="tr">Org-mode dosyası</comment>
+ <comment xml:lang="sv">Org-mode-fil</comment>
+ <comment xml:lang="sl">Datoteka org-mode</comment>
+ <comment xml:lang="si">Org-mode ගොනුව</comment>
+ <comment xml:lang="ru">Файл Org-mode</comment>
+ <comment xml:lang="pl">Plik Org-mode</comment>
+ <comment xml:lang="nl">Org-mode-bestand</comment>
+ <comment xml:lang="ko">Org-mode 파일</comment>
+ <comment xml:lang="kk">Org-mode файлы</comment>
+ <comment xml:lang="ja">Org-mode ファイル</comment>
+ <comment xml:lang="it">File Org-mode</comment>
+ <comment xml:lang="hr">Org-mode datoteka</comment>
+ <comment xml:lang="fi">Org-mode-tiedosto</comment>
+ <comment xml:lang="es">archivo modo Org</comment>
+ <comment xml:lang="en_GB">Org-mode file</comment>
+ <comment xml:lang="de">Org-mode-Datei</comment>
+ <comment xml:lang="be">файл Org-mode</comment>
+ <comment xml:lang="ar">ملف Org-mode</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.org"/>
+ </mime-type>
+ <mime-type type="application/x-openzim">
+ <comment>OpenZIM file</comment>
+ <comment xml:lang="zh_CN">OpenZIM 文件</comment>
+ <comment xml:lang="uk">файл OpenZIM</comment>
+ <comment xml:lang="tr">OpenZIM dosyası</comment>
+ <comment xml:lang="sv">OpenZIM-fil</comment>
+ <comment xml:lang="sl">Datoteka OpenZIM</comment>
+ <comment xml:lang="si">OpenZIM ගොනුව</comment>
+ <comment xml:lang="ru">Файл OpenZIM</comment>
+ <comment xml:lang="pt_BR">Arquivo OpenZIM</comment>
+ <comment xml:lang="pl">Plik OpenZIM</comment>
+ <comment xml:lang="oc">fichièr OpenZIM</comment>
+ <comment xml:lang="nl">OpenZIM-bestand</comment>
+ <comment xml:lang="ko">OpenZIM 파일</comment>
+ <comment xml:lang="kk">OpenZIM файлы</comment>
+ <comment xml:lang="ja">OpenZIM ファイル</comment>
+ <comment xml:lang="it">File OpenZIM</comment>
+ <comment xml:lang="hr">OpenZIM datoteka</comment>
+ <comment xml:lang="fi">OpenZIM-tiedosto</comment>
+ <comment xml:lang="eu">OpenZIM fitxategia</comment>
+ <comment xml:lang="es">archivo OpenZIM</comment>
+ <comment xml:lang="en_GB">OpenZIM file</comment>
+ <comment xml:lang="de">OpenZIM-Datei</comment>
+ <comment xml:lang="be">файл OpenZIM</comment>
+ <comment xml:lang="ar">ملف OpenZIM </comment>
+ <acronym>ZIM</acronym>
+ <expanded-acronym>Zeno IMproved</expanded-acronym>
+ <glob pattern="*.zim"/>
+ <magic>
+ <match type="string" value="\x5a\x49\x4d\x04" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/sparql-query">
+ <comment>SPARQL query</comment>
+ <comment xml:lang="zh_CN">SPARQL 查询</comment>
+ <comment xml:lang="uk">запит SPARQL</comment>
+ <comment xml:lang="tr">SPARQL sorgusu</comment>
+ <comment xml:lang="sv">SPARQL-fråga</comment>
+ <comment xml:lang="sl">Poizvedba SPARQL</comment>
+ <comment xml:lang="si">SPARQL විමසුම</comment>
+ <comment xml:lang="ru">Запрос SPARQL</comment>
+ <comment xml:lang="pl">Zapytanie SPARQL</comment>
+ <comment xml:lang="nl">SPARQL-zoekopdracht</comment>
+ <comment xml:lang="ko">SPARQL 질의문</comment>
+ <comment xml:lang="kk">SPARQL сұранымы</comment>
+ <comment xml:lang="ka">SPARQL მოთხოვნა</comment>
+ <comment xml:lang="ja">SPARQL クエリー</comment>
+ <comment xml:lang="it">Ricerca SPARQL</comment>
+ <comment xml:lang="hr">SPARQL zahtjev</comment>
+ <comment xml:lang="he">שאילתת SPARQL</comment>
+ <comment xml:lang="fi">SPARQL-kysely</comment>
+ <comment xml:lang="eu">SPARQL kontsulta</comment>
+ <comment xml:lang="es">consulta SPARQL</comment>
+ <comment xml:lang="en_GB">SPARQL query</comment>
+ <comment xml:lang="de">SPARQL-Abfrage</comment>
+ <comment xml:lang="be">запыт SPARQL</comment>
+ <comment xml:lang="ar">استعلام SPARQL</comment>
+ <acronym>SPARQL</acronym>
+ <expanded-acronym>SPARQL Protocol and RDF Query Language</expanded-acronym>
+ <glob pattern="*.qs"/>
+ <magic priority="40">
+ <match type="string" value="PREFIX" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/sparql-results+xml">
+ <comment>SPARQL query results</comment>
+ <comment xml:lang="zh_CN">SPARQL 查询结果</comment>
+ <comment xml:lang="uk">результати запиту SPARQL</comment>
+ <comment xml:lang="tr">SPARQL sorgu sonuçları</comment>
+ <comment xml:lang="sv">SPARQL-frågeresultat</comment>
+ <comment xml:lang="sl">Rezultati poizvedbe SPARQL</comment>
+ <comment xml:lang="si">SPARQL විමසුම් ප්රතිඵල</comment>
+ <comment xml:lang="ru">Результаты запроса SPARQL</comment>
+ <comment xml:lang="pl">Wyniki zapytania SPARQL</comment>
+ <comment xml:lang="nl">SPARQL-zoekopdrachtresultaten</comment>
+ <comment xml:lang="ko">SPARQL 질의문 결과</comment>
+ <comment xml:lang="kk">SPARQL сұраным нәтижелері</comment>
+ <comment xml:lang="ja">SPARQL クエリーの結果</comment>
+ <comment xml:lang="it">Risultati ricerca SPARQL</comment>
+ <comment xml:lang="hr">Rezultati SPARQL zahtjeva</comment>
+ <comment xml:lang="he">תוצאות שאילתת SPARQL</comment>
+ <comment xml:lang="fi">SPARQL-kyselyn tulokset</comment>
+ <comment xml:lang="eu">SPARQL kontsultaren emaitzak</comment>
+ <comment xml:lang="es">resultados de consulta SPARQL</comment>
+ <comment xml:lang="en_GB">SPARQL query results</comment>
+ <comment xml:lang="de">SPARQL-Abfrageergebnisse</comment>
+ <comment xml:lang="be">вынікі запыту SPARQL</comment>
+ <comment xml:lang="ar">نتائج استعلام SPARQL</comment>
+ <acronym>SPARQL</acronym>
+ <expanded-acronym>SPARQL Protocol and RDF Query Language</expanded-acronym>
+ <sub-class-of type="application/xml"/>
+ <root-XML namespaceURI="http://www.w3.org/2005/sparql-results#" localName="sparql"/>
+ <glob pattern="*.srx"/>
+ </mime-type>
+ <mime-type type="application/wasm">
+ <comment>WASM binary module</comment>
+ <comment xml:lang="uk">двійковий модуль WASM</comment>
+ <comment xml:lang="sv">WASM-binärmodul</comment>
+ <comment xml:lang="ru">Двоичный модуль WASM</comment>
+ <comment xml:lang="pl">Moduł binarny WASM</comment>
+ <comment xml:lang="es">módulo binario de WASM</comment>
+ <comment xml:lang="de">WASM-Binärmodul</comment>
+ <acronym>WASM</acronym>
+ <expanded-acronym>Web Assembly</expanded-acronym>
+ <glob pattern="*.wasm"/>
+ <magic>
+ <match type="string" value="\000asm" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-openvpn-profile">
+ <comment>OpenVPN profile</comment>
+ <comment xml:lang="uk">профіль OpenVPN</comment>
+ <comment xml:lang="sv">OpenVPN-profil</comment>
+ <comment xml:lang="ru">Профиль OpenVPN</comment>
+ <comment xml:lang="pl">Profil OpenVPN</comment>
+ <comment xml:lang="it">Profilo OpenVPN</comment>
+ <comment xml:lang="es">perfil OpenVPN</comment>
+ <comment xml:lang="de">OpenVPN-Profil</comment>
+ <comment xml:lang="be">профіль OpenVPN</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-generic"/>
+ <glob pattern="*.openvpn"/>
+ <glob pattern="*.ovpn"/>
+ </mime-type>
+ <mime-type type="application/x-modrinth-modpack+zip">
+ <comment>Modrinth Modpack</comment>
+ <comment xml:lang="uk">модпак Modrinth</comment>
+ <comment xml:lang="sv">Modrinth-moddpack</comment>
+ <comment xml:lang="ru">Модификационный пакет Modrinth</comment>
+ <comment xml:lang="pl">Pakiet modów Modrinth</comment>
+ <comment xml:lang="it">Modpack Modrinth</comment>
+ <comment xml:lang="es">paquete de modificaciones de Modrinth</comment>
+ <comment xml:lang="de">Modrinth-Modpack</comment>
+ <sub-class-of type="application/zip"/>
+ <generic-icon name="package-x-generic"/>
+ <glob pattern="*.mrpack"/>
+ </mime-type>
+ <mime-type type="application/cbor">
+ <comment>CBOR Data</comment>
+ <comment xml:lang="zh_TW">CBOR 資料</comment>
+ <comment xml:lang="uk">дані CBOR</comment>
+ <comment xml:lang="sv">CBOR-data</comment>
+ <comment xml:lang="ru">Данные CBOR</comment>
+ <comment xml:lang="pl">Dane CBOR</comment>
+ <comment xml:lang="it">Dati CBOR</comment>
+ <comment xml:lang="es">datos CBOR</comment>
+ <comment xml:lang="de">CBOR-Daten</comment>
+ <comment xml:lang="be">даныя CBOR</comment>
+ <acronym>CBOR</acronym>
+ <expanded-acronym>Concise Binary Object Representation</expanded-acronym>
+ <glob pattern="*.cbor"/>
+ </mime-type>
+ <mime-type type="application/x-eris-link+cbor">
+ <comment>ERIS Link</comment>
+ <comment xml:lang="uk">посилання ERIS</comment>
+ <comment xml:lang="sv">ERIS-länk</comment>
+ <comment xml:lang="ru">Ссылка ERIS</comment>
+ <comment xml:lang="pl">Dowiązanie ERIS</comment>
+ <comment xml:lang="it">Collegamento ERIS</comment>
+ <comment xml:lang="es">enlace ERIS</comment>
+ <comment xml:lang="de">ERIS-Verweis</comment>
+ <comment xml:lang="be">спасылка ERIS</comment>
+ <acronym>ERIS</acronym>
+ <expanded-acronym>Encoding for Robust Immutable Storage</expanded-acronym>
+ <sub-class-of type="application/cbor"/>
+ <glob pattern="*.eris"/>
+ <magic priority="90">
+ <match type="string" value="\xD9\xD9\xF7\x84\xD9\x01\x14\x58\x42" offset="0"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/vnd.gerber">
+ <comment>Gerber file</comment>
+ <comment xml:lang="uk">файл Gerber</comment>
+ <comment xml:lang="sv">Gerber-fil</comment>
+ <comment xml:lang="ru">Файл Gerber</comment>
+ <comment xml:lang="pl">Plik Gerber</comment>
+ <comment xml:lang="it">File Gerber</comment>
+ <comment xml:lang="es">archivo de Gerber</comment>
+ <comment xml:lang="de">Gerber-Datei</comment>
+ <comment xml:lang="be">файл Gerber</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.gbr"/>
+ <!--Try to match with some common opening commands-->
+ <magic>
+ <!--A comment line-->
+ <match type="string" value="G04 " offset="0"/>
+ <!--Some setup macros-->
+ <match type="string" value="%FSLA" offset="0"/>
+ <match type="string" value="%MO" offset="0"/>
+ <match type="string" value="%TF." offset="0"/>
+ <!--Seems to be common with files exported from some programs-->
+ <match type="string" value="G75*" offset="0"/>
+ </magic>
+ <generic-icon name="text-x-generic"/>
+ <!--Already being used as the MIME identifier by some programs-->
+ <alias type="application/x-gerber"/>
+ </mime-type>
+ <mime-type type="application/x-gerber-job">
+ <comment>Gerber job file</comment>
+ <comment xml:lang="uk">файл завдання Gerber</comment>
+ <comment xml:lang="sv">Gerber-jobbfil</comment>
+ <comment xml:lang="ru">Файл работ Gerber</comment>
+ <comment xml:lang="pl">Plik zadania Gerber</comment>
+ <comment xml:lang="it">File lavoro Gerber</comment>
+ <comment xml:lang="es">archivo de tarea de Gerber</comment>
+ <comment xml:lang="de">Gerber-Aufgabendatei</comment>
+ <comment xml:lang="be">працоўны файл Gerber</comment>
+ <sub-class-of type="application/json"/>
+ <glob pattern="*.gbrjob"/>
+ <generic-icon name="text-x-generic"/>
+ </mime-type>
+ <mime-type type="application/x-excellon">
+ <comment>Excellon drill file</comment>
+ <comment xml:lang="uk">файл drill Excellon</comment>
+ <comment xml:lang="sv">Excellon-borrfil</comment>
+ <comment xml:lang="ru">Файл Excellon drill</comment>
+ <comment xml:lang="pl">Plik wiercenia Excellon</comment>
+ <comment xml:lang="es">archivo de perforación de Excellon</comment>
+ <comment xml:lang="de">Excellon-Bohrdatei</comment>
+ <sub-class-of type="text/plain"/>
+ <glob pattern="*.drl"/>
+ <magic>
+ <!--This is always the header for an excellon drill file-->
+ <match type="string" value="M48\n" offset="0"/>
+ </magic>
+ <generic-icon name="text-x-generic"/>
+ </mime-type>
+ <mime-type type="application/x-tiled-tmx">
+ <comment>Tiled map files</comment>
+ <comment xml:lang="uk">файли мозаїчної карти</comment>
+ <comment xml:lang="sv">Tiled-kartfiler</comment>
+ <comment xml:lang="ru">Файлы карты Tiled</comment>
+ <comment xml:lang="pl">Pliki map Tiled</comment>
+ <comment xml:lang="es">archivos de mapa en mosaico</comment>
+ <comment xml:lang="de">Tiled-Kartendatei</comment>
+ <sub-class-of type="application/xml"/>
+ <glob pattern="*.tmx"/>
+ </mime-type>
+ <mime-type type="application/x-tiled-tsx">
+ <comment>Tiled tileset files</comment>
+ <comment xml:lang="uk">файл набору плиток мозаїки</comment>
+ <comment xml:lang="sv">Tiled-kartrutuppsättningsfiler</comment>
+ <comment xml:lang="ru">Файлы наборов плиток Tiled</comment>
+ <comment xml:lang="pl">Pliki zestawów kafli Tiled</comment>
+ <comment xml:lang="de">Tiled-Kartensetdatei</comment>
+ <sub-class-of type="application/xml"/>
+ <glob pattern="*.tsx"/>
</mime-type>
-
</mime-info>
diff --git a/src/corelib/mimetypes/mimetypes.pri b/src/corelib/mimetypes/mimetypes.pri
deleted file mode 100644
index 288ccf063e..0000000000
--- a/src/corelib/mimetypes/mimetypes.pri
+++ /dev/null
@@ -1,55 +0,0 @@
-# Qt core mimetype module
-
-qtConfig(mimetype) {
- HEADERS += \
- mimetypes/qmimedatabase.h \
- mimetypes/qmimetype.h \
- mimetypes/qmimemagicrulematcher_p.h \
- mimetypes/qmimetype_p.h \
- mimetypes/qmimetypeparser_p.h \
- mimetypes/qmimedatabase_p.h \
- mimetypes/qmimemagicrule_p.h \
- mimetypes/qmimeglobpattern_p.h \
- mimetypes/qmimeprovider_p.h
-
- SOURCES += \
- mimetypes/qmimedatabase.cpp \
- mimetypes/qmimetype.cpp \
- mimetypes/qmimemagicrulematcher.cpp \
- mimetypes/qmimetypeparser.cpp \
- mimetypes/qmimemagicrule.cpp \
- mimetypes/qmimeglobpattern.cpp \
- mimetypes/qmimeprovider.cpp
-
- MIME_DATABASE = mimetypes/mime/packages/freedesktop.org.xml
- OTHER_FILES += $$MIME_DATABASE
-
- qtConfig(mimetype-database) {
- outpath = .rcc
- android {
- outpath = $$outpath/$${QT_ARCH}
- }
- debug_and_release {
- CONFIG(debug, debug|release): outpath = $$outpath/debug
- else: outpath = $$outpath/release
- }
-
- mimedb.depends = $$PWD/mime/generate.pl
- equals(MAKEFILE_GENERATOR, MSVC.NET)|equals(MAKEFILE_GENERATOR, MSBUILD)|isEmpty(QMAKE_SH) {
- mimedb.commands = cmd /c $$shell_path($$PWD/mime/generate.bat)
- mimedb.depends += $$PWD/mime/generate.bat $$PWD/mime/hexdump.ps1
- } else {
- mimedb.commands = perl $${mimedb.depends}
- }
-
- qtConfig(zstd): mimedb.commands += --zstd
- mimedb.commands += ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
-
- mimedb.output = $$outpath/qmimeprovider_database.cpp
- mimedb.input = MIME_DATABASE
- mimedb.variable_out = INCLUDED_SOURCES
- QMAKE_EXTRA_COMPILERS += mimedb
- INCLUDEPATH += $$outpath
- unset(outpath)
- }
-}
diff --git a/src/corelib/mimetypes/mimetypes.qrc b/src/corelib/mimetypes/mimetypes.qrc
deleted file mode 100644
index 4720bd302a..0000000000
--- a/src/corelib/mimetypes/mimetypes.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/qt-project.org/qmime/packages">
- <file alias="freedesktop.org.xml" compression-algorithm="best">mime/packages/freedesktop.org.xml</file>
- </qresource>
-</RCC>
diff --git a/src/corelib/mimetypes/mimetypes_resources.cmake b/src/corelib/mimetypes/mimetypes_resources.cmake
index a91d25cc2c..00fa4f5271 100644
--- a/src/corelib/mimetypes/mimetypes_resources.cmake
+++ b/src/corelib/mimetypes/mimetypes_resources.cmake
@@ -1,6 +1,9 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# List of files that need to be packaged as resources.
# This file exists solely because of unit tests that need access to this
-# information as well. This was previosly handled by referrencing a qrc
+# information as well. This was previously handled by referencing a qrc
# file with the same information
set(corelib_mimetypes_resource_file
@@ -12,7 +15,7 @@ function(corelib_add_mimetypes_resources target)
set_source_files_properties("${source_file}"
PROPERTIES QT_RESOURCE_ALIAS "freedesktop.org.xml"
)
- qt_add_resource(${target} "mimetypes"
+ qt_internal_add_resource(${target} "mimetypes"
PREFIX
"/qt-project.org/qmime/packages"
FILES
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index aef4bc4a6b..d52ccacbe7 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qplatformdefs.h> // always first
@@ -46,6 +10,9 @@
#include "qmimeprovider_p.h"
#include "qmimetype_p.h"
+#include <private/qduplicatetracker_p.h>
+#include <private/qfilesystementry_p.h>
+
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
@@ -59,6 +26,17 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+static QString directoryMimeType()
+{
+ return QStringLiteral("inode/directory");
+}
+static QString plainTextMimeType()
+{
+ return QStringLiteral("text/plain");
+}
+
Q_GLOBAL_STATIC(QMimeDatabasePrivate, staticQMimeDatabase)
QMimeDatabasePrivate *QMimeDatabasePrivate::instance()
@@ -67,7 +45,7 @@ QMimeDatabasePrivate *QMimeDatabasePrivate::instance()
}
QMimeDatabasePrivate::QMimeDatabasePrivate()
- : m_defaultMimeType(QLatin1String("application/octet-stream"))
+ : m_defaultMimeType(QStringLiteral("application/octet-stream"))
{
}
@@ -75,6 +53,7 @@ QMimeDatabasePrivate::~QMimeDatabasePrivate()
{
}
+Q_CONSTINIT
#ifdef QT_BUILD_INTERNAL
Q_CORE_EXPORT
#else
@@ -90,32 +69,32 @@ bool QMimeDatabasePrivate::shouldCheck()
return true;
}
-#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+static QStringList locateMimeDirectories()
+{
+ return QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("mime"), QStandardPaths::LocateDirectory);
+}
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
# define QT_USE_MMAP
#endif
void QMimeDatabasePrivate::loadProviders()
{
// We use QStandardPaths every time to check if new files appeared
- QStringList mimeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
+ const QStringList mimeDirs = locateMimeDirectories();
const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool {
- return QFileInfo::exists(mimeDir + QStringLiteral("/packages/freedesktop.org.xml")); }
+ return QFileInfo::exists(mimeDir + "/packages/freedesktop.org.xml"_L1); }
);
+ const bool needInternalDB = QMimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd();
//qDebug() << "mime dirs:" << mimeDirs;
Providers currentProviders;
std::swap(m_providers, currentProviders);
- if (QMimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd()) {
- m_providers.reserve(mimeDirs.size() + 1);
- m_providers.push_back(Providers::value_type(new QMimeXMLProvider(this, QMimeXMLProvider::InternalDatabase)));
- } else {
- m_providers.reserve(mimeDirs.size());
- }
+ m_providers.reserve(mimeDirs.size() + (needInternalDB ? 1 : 0));
- for (const QString &mimeDir : qAsConst(mimeDirs)) {
- const QString cacheFile = mimeDir + QStringLiteral("/mime.cache");
- QFileInfo fileInfo(cacheFile);
+ for (const QString &mimeDir : mimeDirs) {
+ const QString cacheFile = mimeDir + "/mime.cache"_L1;
// Check if we already have a provider for this dir
const auto predicate = [mimeDir](const std::unique_ptr<QMimeProviderBase> &prov)
{
@@ -125,7 +104,7 @@ void QMimeDatabasePrivate::loadProviders()
if (it == currentProviders.end()) {
std::unique_ptr<QMimeProviderBase> provider;
#if defined(QT_USE_MMAP)
- if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && fileInfo.exists()) {
+ if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && QFileInfo::exists(cacheFile)) {
provider.reset(new QMimeBinaryProvider(this, mimeDir));
//qDebug() << "Created binary provider for" << mimeDir;
if (!provider->isValid()) {
@@ -148,6 +127,28 @@ void QMimeDatabasePrivate::loadProviders()
m_providers.push_back(std::move(provider));
}
}
+ // mimeDirs is sorted "most local first, most global last"
+ // so the internal XML DB goes at the end
+ if (needInternalDB) {
+ // Check if we already have a provider for the InternalDatabase
+ const auto isInternal = [](const std::unique_ptr<QMimeProviderBase> &prov)
+ {
+ return prov && prov->isInternalDatabase();
+ };
+ const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), isInternal);
+ if (it == currentProviders.end()) {
+ m_providers.push_back(Providers::value_type(new QMimeXMLProvider(this, QMimeXMLProvider::InternalDatabase)));
+ } else {
+ m_providers.push_back(std::move(*it));
+ }
+ }
+
+ auto it = m_providers.begin();
+ (*it)->setOverrideProvider(nullptr);
+ ++it;
+ const auto end = m_providers.end();
+ for (; it != end; ++it)
+ (*it)->setOverrideProvider((it - 1)->get());
}
const QMimeDatabasePrivate::Providers &QMimeDatabasePrivate::providers()
@@ -183,20 +184,18 @@ QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
{
const QString mimeName = resolveAlias(nameOrAlias);
for (const auto &provider : providers()) {
- const QMimeType mime = provider->mimeTypeForName(mimeName);
- if (mime.isValid())
- return mime;
+ if (provider->knowsMimeType(mimeName))
+ return QMimeType(QMimeTypePrivate(mimeName));
}
return {};
}
QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
{
- if (fileName.endsWith(QLatin1Char('/')))
- return QStringList() << QLatin1String("inode/directory");
+ if (fileName.endsWith(u'/'))
+ return { directoryMimeType() };
- const QString shortName = QFileInfo(fileName).fileName();
- const QMimeGlobMatchResult result = findByFileName(shortName);
+ const QMimeGlobMatchResult result = findByFileName(fileName);
QStringList matchingMimeTypes = result.m_matchingMimeTypes;
matchingMimeTypes.sort(); // make it deterministic
return matchingMimeTypes;
@@ -205,61 +204,74 @@ QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileName)
{
QMimeGlobMatchResult result;
- // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
+ const QString fileNameExcludingPath = QFileSystemEntry(fileName).fileName();
for (const auto &provider : providers())
- provider->addFileNameMatches(fileName, result);
+ provider->addFileNameMatches(fileNameExcludingPath, result);
return result;
}
-void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
+QMimeTypePrivate::LocaleHash QMimeDatabasePrivate::localeComments(const QString &name)
{
QMutexLocker locker(&mutex);
- if (mimePrivate.name.isEmpty())
- return; // invalid mimetype
- if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
- Q_ASSERT(mimePrivate.fromCache);
- QMimeBinaryProvider::loadMimeTypePrivate(mimePrivate);
+ for (const auto &provider : providers()) {
+ auto comments = provider->localeComments(name);
+ if (!comments.isEmpty())
+ return comments; // maybe we want to merge in comments from more global providers, in
+ // case of more translations?
}
+ return {};
}
-void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate)
+QStringList QMimeDatabasePrivate::globPatterns(const QString &name)
{
QMutexLocker locker(&mutex);
- if (mimePrivate.fromCache) {
- mimePrivate.genericIconName.clear();
- for (const auto &provider : providers()) {
- provider->loadGenericIcon(mimePrivate);
- if (!mimePrivate.genericIconName.isEmpty())
- break;
- }
+ QStringList patterns;
+ const auto &providerList = providers();
+ // reverse iteration because we start from most global, add up, clear if delete-all, and add up
+ // again.
+ for (auto rit = providerList.rbegin(); rit != providerList.rend(); ++rit) {
+ auto *provider = rit->get();
+ if (provider->hasGlobDeleteAll(name))
+ patterns.clear();
+ patterns += provider->globPatterns(name);
}
+ return patterns;
}
-void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate)
+QString QMimeDatabasePrivate::genericIcon(const QString &name)
{
QMutexLocker locker(&mutex);
- if (mimePrivate.fromCache) {
- mimePrivate.iconName.clear();
- for (const auto &provider : providers()) {
- provider->loadIcon(mimePrivate);
- if (!mimePrivate.iconName.isEmpty())
- break;
- }
+ for (const auto &provider : providers()) {
+ QString genericIconName = provider->genericIcon(name);
+ if (!genericIconName.isEmpty())
+ return genericIconName;
}
+ return {};
}
-static QString fallbackParent(const QString &mimeTypeName)
+QString QMimeDatabasePrivate::icon(const QString &name)
{
- const QStringView myGroup = QStringView{mimeTypeName}.left(mimeTypeName.indexOf(QLatin1Char('/')));
+ QMutexLocker locker(&mutex);
+ for (const auto &provider : providers()) {
+ QString iconName = provider->icon(name);
+ if (!iconName.isEmpty())
+ return iconName;
+ }
+ return {};
+}
+
+QString QMimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
+{
+ const QStringView myGroup = QStringView{mimeTypeName}.left(mimeTypeName.indexOf(u'/'));
// All text/* types are subclasses of text/plain.
- if (myGroup == QLatin1String("text") && mimeTypeName != QLatin1String("text/plain"))
- return QLatin1String("text/plain");
+ if (myGroup == "text"_L1 && mimeTypeName != plainTextMimeType())
+ return plainTextMimeType();
// All real-file mimetypes implicitly derive from application/octet-stream
- if (myGroup != QLatin1String("inode") &&
+ if (myGroup != "inode"_L1 &&
// ignore non-file extensions
- myGroup != QLatin1String("all") && myGroup != QLatin1String("fonts") && myGroup != QLatin1String("print") && myGroup != QLatin1String("uri")
- && mimeTypeName != QLatin1String("application/octet-stream")) {
- return QLatin1String("application/octet-stream");
+ myGroup != "all"_L1 && myGroup != "fonts"_L1 && myGroup != "print"_L1 && myGroup != "uri"_L1
+ && mimeTypeName != defaultMimeType()) {
+ return defaultMimeType();
}
return QString();
}
@@ -311,7 +323,7 @@ static inline bool isTextFile(const QByteArray &data)
const char *p = data.constData();
const char *e = p + qMin(128, data.size());
for ( ; p < e; ++p) {
- if ((unsigned char)(*p) < 32 && *p != 9 && *p !=10 && *p != 13)
+ if (static_cast<unsigned char>(*p) < 32 && *p != 9 && *p !=10 && *p != 13)
return false;
}
@@ -322,42 +334,37 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy
{
if (data.isEmpty()) {
*accuracyPtr = 100;
- return mimeTypeForName(QLatin1String("application/x-zerosize"));
+ return mimeTypeForName(QStringLiteral("application/x-zerosize"));
}
- *accuracyPtr = 0;
- QMimeType candidate;
+ QMimeMagicResult result;
for (const auto &provider : providers())
- provider->findByMagic(data, accuracyPtr, candidate);
+ provider->findByMagic(data, result);
- if (candidate.isValid())
- return candidate;
+ if (result.isValid()) {
+ *accuracyPtr = result.accuracy;
+ return QMimeType(QMimeTypePrivate(result.candidate));
+ }
if (isTextFile(data)) {
*accuracyPtr = 5;
- return mimeTypeForName(QLatin1String("text/plain"));
+ return mimeTypeForName(plainTextMimeType());
}
return mimeTypeForName(defaultMimeType());
}
-QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *accuracyPtr)
+QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device)
{
// First, glob patterns are evaluated. If there is a match with max weight,
// this one is selected and we are done. Otherwise, the file contents are
// evaluated and the match with the highest value (either a magic priority or
// a glob pattern weight) is selected. Matching starts from max level (most
// specific) in both cases, even when there is already a suffix matching candidate.
- *accuracyPtr = 0;
// Pass 1) Try to match on the file name
- QMimeGlobMatchResult candidatesByName;
- if (fileName.endsWith(QLatin1Char('/')))
- candidatesByName.addMatch(QLatin1String("inode/directory"), 100, QString());
- else
- candidatesByName = findByFileName(QFileInfo(fileName).fileName());
- if (candidatesByName.m_allMatchingMimeTypes.count() == 1) {
- *accuracyPtr = 100;
+ QMimeGlobMatchResult candidatesByName = findByFileName(fileName);
+ if (candidatesByName.m_allMatchingMimeTypes.size() == 1) {
const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
if (mime.isValid())
return mime;
@@ -366,44 +373,123 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
// Extension is unknown, or matches multiple mimetypes.
// Pass 2) Match on content, if we can read the data
- if (device->isOpen()) {
+ const auto matchOnContent = [this, &candidatesByName](QIODevice *device) {
+ const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
+ if (device->isOpen()) {
+ // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
+ // This is much faster than seeking back and forth into QIODevice.
+ const QByteArray data = device->peek(16384);
+
+ if (openedByUs)
+ device->close();
+
+ int magicAccuracy = 0;
+ QMimeType candidateByData(findByData(data, &magicAccuracy));
+
+ // Disambiguate conflicting extensions (if magic matching found something)
+ if (candidateByData.isValid() && magicAccuracy > 0) {
+ const QString sniffedMime = candidateByData.name();
+ // If the sniffedMime matches a highest-weight glob match, use it
+ if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
+ return candidateByData;
+ }
+ for (const QString &m : std::as_const(candidatesByName.m_allMatchingMimeTypes)) {
+ if (inherits(m, sniffedMime)) {
+ // We have magic + pattern pointing to this, so it's a pretty good match
+ return mimeTypeForName(m);
+ }
+ }
+ if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) {
+ // No glob, use magic
+ return candidateByData;
+ }
+ }
+ }
+ if (candidatesByName.m_allMatchingMimeTypes.size() > 1) {
+ candidatesByName.m_matchingMimeTypes.sort(); // make it deterministic
+ const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
+ if (mime.isValid())
+ return mime;
+ }
+
+ return mimeTypeForName(defaultMimeType());
+ };
+
+ if (device)
+ return matchOnContent(device);
+
+ QFile fallbackFile(fileName);
+ return matchOnContent(&fallbackFile);
+}
+
+QMimeType QMimeDatabasePrivate::mimeTypeForFileExtension(const QString &fileName)
+{
+ const QStringList matches = mimeTypeForFileName(fileName);
+ if (matches.isEmpty()) {
+ return mimeTypeForName(defaultMimeType());
+ } else {
+ // We have to pick one in case of multiple matches.
+ return mimeTypeForName(matches.first());
+ }
+}
+
+QMimeType QMimeDatabasePrivate::mimeTypeForData(QIODevice *device)
+{
+ int accuracy = 0;
+ const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
+ if (device->isOpen()) {
// Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
// This is much faster than seeking back and forth into QIODevice.
const QByteArray data = device->peek(16384);
+ QMimeType result = findByData(data, &accuracy);
+ if (openedByUs)
+ device->close();
+ return result;
+ }
+ return mimeTypeForName(defaultMimeType());
+}
- int magicAccuracy = 0;
- QMimeType candidateByData(findByData(data, &magicAccuracy));
-
- // Disambiguate conflicting extensions (if magic matching found something)
- if (candidateByData.isValid() && magicAccuracy > 0) {
- const QString sniffedMime = candidateByData.name();
- // If the sniffedMime matches a glob match, use it
- if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
- *accuracyPtr = 100;
- return candidateByData;
- }
- for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) {
- if (inherits(m, sniffedMime)) {
- // We have magic + pattern pointing to this, so it's a pretty good match
- *accuracyPtr = 100;
- return mimeTypeForName(m);
- }
- }
- *accuracyPtr = magicAccuracy;
- return candidateByData;
+QMimeType QMimeDatabasePrivate::mimeTypeForFile(const QString &fileName,
+ const QFileInfo &fileInfo,
+ QMimeDatabase::MatchMode mode)
+{
+ if (false) {
+#ifdef Q_OS_UNIX
+ } else if (fileInfo.isNativePath()) {
+ // If this is a local file, we'll want to do a stat() ourselves so we can
+ // detect additional inode types. In addition we want to follow symlinks.
+ const QByteArray nativeFilePath = QFile::encodeName(fileName);
+ QT_STATBUF statBuffer;
+ if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
+ if (S_ISDIR(statBuffer.st_mode))
+ return mimeTypeForName(directoryMimeType());
+ if (S_ISCHR(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/chardevice"));
+ if (S_ISBLK(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/blockdevice"));
+ if (S_ISFIFO(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/fifo"));
+ if (S_ISSOCK(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/socket"));
}
+#endif
+ } else if (fileInfo.isDir()) {
+ return mimeTypeForName(directoryMimeType());
}
- if (candidatesByName.m_allMatchingMimeTypes.count() > 1) {
- candidatesByName.m_matchingMimeTypes.sort(); // make it deterministic
- *accuracyPtr = 20;
- const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
- if (mime.isValid())
- return mime;
+ switch (mode) {
+ case QMimeDatabase::MatchDefault:
+ break;
+ case QMimeDatabase::MatchExtension:
+ return mimeTypeForFileExtension(fileName);
+ case QMimeDatabase::MatchContent: {
+ QFile file(fileName);
+ return mimeTypeForData(&file);
}
-
- return mimeTypeForName(defaultMimeType());
+ }
+ // MatchDefault:
+ return mimeTypeForFileNameAndData(fileName, nullptr);
}
QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
@@ -417,6 +503,7 @@ QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
{
const QString resolvedParent = resolveAlias(parent);
+ QDuplicateTracker<QString> seen;
std::stack<QString, QStringList> toCheck;
toCheck.push(mime);
while (!toCheck.empty()) {
@@ -425,8 +512,11 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
const QString mimeName = toCheck.top();
toCheck.pop();
const auto parentList = parents(mimeName);
- for (const QString &par : parentList)
- toCheck.push(resolveAlias(par));
+ for (const QString &par : parentList) {
+ const QString resolvedPar = resolveAlias(par);
+ if (!seen.hasSeen(resolvedPar))
+ toCheck.push(resolvedPar);
+ }
}
return false;
}
@@ -468,7 +558,7 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
\snippet code/src_corelib_mimetype_qmimedatabase.cpp 0
- \sa QMimeType, {MIME Type Browser Example}
+ \sa QMimeType, {MIME Type Browser}
*/
/*!
@@ -537,47 +627,7 @@ QMimeType QMimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mo
{
QMutexLocker locker(&d->mutex);
- if (fileInfo.isDir())
- return d->mimeTypeForName(QLatin1String("inode/directory"));
-
- QFile file(fileInfo.absoluteFilePath());
-
-#ifdef Q_OS_UNIX
- // Cannot access statBuf.st_mode from the filesystem engine, so we have to stat again.
- // In addition we want to follow symlinks.
- const QByteArray nativeFilePath = QFile::encodeName(file.fileName());
- QT_STATBUF statBuffer;
- if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
- if (S_ISCHR(statBuffer.st_mode))
- return d->mimeTypeForName(QLatin1String("inode/chardevice"));
- if (S_ISBLK(statBuffer.st_mode))
- return d->mimeTypeForName(QLatin1String("inode/blockdevice"));
- if (S_ISFIFO(statBuffer.st_mode))
- return d->mimeTypeForName(QLatin1String("inode/fifo"));
- if (S_ISSOCK(statBuffer.st_mode))
- return d->mimeTypeForName(QLatin1String("inode/socket"));
- }
-#endif
-
- int priority = 0;
- switch (mode) {
- case MatchDefault:
- file.open(QIODevice::ReadOnly); // isOpen() will be tested by method below
- return d->mimeTypeForFileNameAndData(fileInfo.absoluteFilePath(), &file, &priority);
- case MatchExtension:
- locker.unlock();
- return mimeTypeForFile(fileInfo.absoluteFilePath(), mode);
- case MatchContent:
- if (file.open(QIODevice::ReadOnly)) {
- locker.unlock();
- return mimeTypeForData(&file);
- } else {
- return d->mimeTypeForName(d->defaultMimeType());
- }
- default:
- Q_ASSERT(false);
- }
- return d->mimeTypeForName(d->defaultMimeType());
+ return d->mimeTypeForFile(fileInfo.filePath(), fileInfo, mode);
}
/*!
@@ -587,22 +637,13 @@ QMimeType QMimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mo
*/
QMimeType QMimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const
{
+ QMutexLocker locker(&d->mutex);
+
if (mode == MatchExtension) {
- QMutexLocker locker(&d->mutex);
- const QStringList matches = d->mimeTypeForFileName(fileName);
- const int matchCount = matches.count();
- if (matchCount == 0) {
- return d->mimeTypeForName(d->defaultMimeType());
- } else if (matchCount == 1) {
- return d->mimeTypeForName(matches.first());
- } else {
- // We have to pick one.
- return d->mimeTypeForName(matches.first());
- }
+ return d->mimeTypeForFileExtension(fileName);
} else {
- // Implemented as a wrapper around mimeTypeForFile(QFileInfo), so no mutex.
QFileInfo fileInfo(fileName);
- return mimeTypeForFile(fileInfo, mode);
+ return d->mimeTypeForFile(fileName, fileInfo, mode);
}
}
@@ -624,7 +665,7 @@ QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) co
const QStringList matches = d->mimeTypeForFileName(fileName);
QList<QMimeType> mimes;
- mimes.reserve(matches.count());
+ mimes.reserve(matches.size());
for (const QString &mime : matches)
mimes.append(d->mimeTypeForName(mime));
return mimes;
@@ -638,7 +679,7 @@ QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) co
QString QMimeDatabase::suffixForFileName(const QString &fileName) const
{
QMutexLocker locker(&d->mutex);
- const int suffixLength = d->findByFileName(QFileInfo(fileName).fileName()).m_knownSuffixLength;
+ const qsizetype suffixLength = d->findByFileName(fileName).m_knownSuffixLength;
return fileName.right(suffixLength);
}
@@ -668,18 +709,7 @@ QMimeType QMimeDatabase::mimeTypeForData(QIODevice *device) const
{
QMutexLocker locker(&d->mutex);
- int accuracy = 0;
- const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
- if (device->isOpen()) {
- // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
- // This is much faster than seeking back and forth into QIODevice.
- const QByteArray data = device->peek(16384);
- const QMimeType result = d->findByData(data, &accuracy);
- if (openedByUs)
- device->close();
- return result;
- }
- return d->mimeTypeForName(d->defaultMimeType());
+ return d->mimeTypeForData(device);
}
/*!
@@ -702,7 +732,7 @@ QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const
return mimeTypeForFile(url.toLocalFile());
const QString scheme = url.scheme();
- if (scheme.startsWith(QLatin1String("http")) || scheme == QLatin1String("mailto"))
+ if (scheme.startsWith("http"_L1) || scheme == "mailto"_L1)
return mimeTypeForName(d->defaultMimeType());
return mimeTypeForFile(url.path(), MatchExtension);
@@ -730,11 +760,11 @@ QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const
QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const
{
QMutexLocker locker(&d->mutex);
- int accuracy = 0;
- const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
- const QMimeType result = d->mimeTypeForFileNameAndData(fileName, device, &accuracy);
- if (openedByUs)
- device->close();
+
+ if (fileName.endsWith(u'/'))
+ return d->mimeTypeForName(directoryMimeType());
+
+ const QMimeType result = d->mimeTypeForFileNameAndData(fileName, device);
return result;
}
@@ -757,10 +787,13 @@ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIO
QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const
{
QMutexLocker locker(&d->mutex);
+
+ if (fileName.endsWith(u'/'))
+ return d->mimeTypeForName(directoryMimeType());
+
QBuffer buffer(const_cast<QByteArray *>(&data));
buffer.open(QIODevice::ReadOnly);
- int accuracy = 0;
- return d->mimeTypeForFileNameAndData(fileName, &buffer, &accuracy);
+ return d->mimeTypeForFileNameAndData(fileName, &buffer);
}
/*!
diff --git a/src/corelib/mimetypes/qmimedatabase.h b/src/corelib/mimetypes/qmimedatabase.h
index 9111e5a04c..acf1edff27 100644
--- a/src/corelib/mimetypes/qmimedatabase.h
+++ b/src/corelib/mimetypes/qmimedatabase.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEDATABASE_H
#define QMIMEDATABASE_H
diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h
index e6af23e7ed..cb28f0b791 100644
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEDATABASE_P_H
#define QMIMEDATABASE_P_H
@@ -52,6 +16,7 @@
// We mean it.
//
+#include "qmimedatabase.h"
#include "qmimetype.h"
QT_REQUIRE_CONFIG(mimetype);
@@ -68,6 +33,7 @@ QT_REQUIRE_CONFIG(mimetype);
QT_BEGIN_NAMESPACE
+class QFileInfo;
class QIODevice;
class QMimeDatabase;
class QMimeProviderBase;
@@ -82,7 +48,7 @@ public:
static QMimeDatabasePrivate *instance();
- inline QString defaultMimeType() const { return m_defaultMimeType; }
+ const QString &defaultMimeType() const { return m_defaultMimeType; }
bool inherits(const QString &mime, const QString &parent);
@@ -91,15 +57,19 @@ public:
QString resolveAlias(const QString &nameOrAlias);
QStringList parents(const QString &mimeName);
QMimeType mimeTypeForName(const QString &nameOrAlias);
- QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr);
+ QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device);
+ QMimeType mimeTypeForFileExtension(const QString &fileName);
+ QMimeType mimeTypeForData(QIODevice *device);
+ QMimeType mimeTypeForFile(const QString &fileName, const QFileInfo &fileInfo, QMimeDatabase::MatchMode mode);
QMimeType findByData(const QByteArray &data, int *priorityPtr);
QStringList mimeTypeForFileName(const QString &fileName);
QMimeGlobMatchResult findByFileName(const QString &fileName);
// API for QMimeType. Takes care of locking the mutex.
- void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate);
- void loadGenericIcon(QMimeTypePrivate &mimePrivate);
- void loadIcon(QMimeTypePrivate &mimePrivate);
+ QMimeTypePrivate::LocaleHash localeComments(const QString &name);
+ QStringList globPatterns(const QString &name);
+ QString genericIcon(const QString &name);
+ QString icon(const QString &name);
QStringList mimeParents(const QString &mimeName);
QStringList listAliases(const QString &mimeName);
bool mimeInherits(const QString &mime, const QString &parent);
@@ -109,12 +79,13 @@ private:
const Providers &providers();
bool shouldCheck();
void loadProviders();
+ QString fallbackParent(const QString &mimeTypeName) const;
- mutable Providers m_providers;
+ const QString m_defaultMimeType;
+ mutable Providers m_providers; // most local first, most global last
QElapsedTimer m_lastCheck;
public:
- const QString m_defaultMimeType;
QMutex mutex;
};
diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp
index 9264d1a3bb..d50787a0be 100644
--- a/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmimeglobpattern_p.h"
@@ -47,6 +11,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\internal
\class QMimeGlobMatchResult
@@ -56,7 +22,8 @@ QT_BEGIN_NAMESPACE
Handles glob weights, and preferring longer matches over shorter matches.
*/
-void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern, int knownSuffixLength)
+void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern,
+ qsizetype knownSuffixLength)
{
if (m_allMatchingMimeTypes.contains(mimeType))
return;
@@ -68,9 +35,9 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q
bool replace = weight > m_weight;
if (!replace) {
// Compare the length of the match
- if (pattern.length() < m_matchingPatternLength)
+ if (pattern.size() < m_matchingPatternLength)
return; // too short, ignore
- else if (pattern.length() > m_matchingPatternLength) {
+ else if (pattern.size() > m_matchingPatternLength) {
// longer: clear any previous match (like *.bz2, when pattern is *.tar.bz2)
replace = true;
}
@@ -78,16 +45,53 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q
if (replace) {
m_matchingMimeTypes.clear();
// remember the new "longer" length
- m_matchingPatternLength = pattern.length();
+ m_matchingPatternLength = pattern.size();
m_weight = weight;
}
if (!m_matchingMimeTypes.contains(mimeType)) {
m_matchingMimeTypes.append(mimeType);
- m_allMatchingMimeTypes.append(mimeType);
+ if (replace)
+ m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first
+ else
+ m_allMatchingMimeTypes.append(mimeType);
m_knownSuffixLength = knownSuffixLength;
}
}
+QMimeGlobPattern::PatternType QMimeGlobPattern::detectPatternType(QStringView pattern) const
+{
+ const qsizetype patternLength = pattern.size();
+ if (!patternLength)
+ return OtherPattern;
+
+ const qsizetype starCount = pattern.count(u'*');
+ const bool hasSquareBracket = pattern.indexOf(u'[') != -1;
+ const bool hasQuestionMark = pattern.indexOf(u'?') != -1;
+
+ if (!hasSquareBracket && !hasQuestionMark) {
+ if (starCount == 1) {
+ // Patterns like "*~", "*.extension"
+ if (pattern.at(0) == u'*')
+ return SuffixPattern;
+ // Patterns like "README*" (well this is currently the only one like that...)
+ if (pattern.at(patternLength - 1) == u'*')
+ return PrefixPattern;
+ } else if (starCount == 0) {
+ // Names without any wildcards like "README"
+ return LiteralPattern;
+ }
+ }
+
+ if (pattern == "[0-9][0-9][0-9].vdr"_L1)
+ return VdrPattern;
+
+ if (pattern == "*.anim[1-9j]"_L1)
+ return AnimPattern;
+
+ return OtherPattern;
+}
+
+
/*!
\internal
\class QMimeGlobPattern
@@ -97,80 +101,88 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q
\sa QMimeType, QMimeDatabase, QMimeMagicRuleMatcher, QMimeMagicRule
*/
-bool QMimeGlobPattern::matchFileName(const QString &inputFilename) const
+bool QMimeGlobPattern::matchFileName(const QString &inputFileName) const
{
// "Applications MUST match globs case-insensitively, except when the case-sensitive
// attribute is set to true."
// The constructor takes care of putting case-insensitive patterns in lowercase.
- const QString filename = m_caseSensitivity == Qt::CaseInsensitive ? inputFilename.toLower() : inputFilename;
+ const QString fileName = m_caseSensitivity == Qt::CaseInsensitive
+ ? inputFileName.toLower() : inputFileName;
- const int pattern_len = m_pattern.length();
- if (!pattern_len)
+ const qsizetype patternLength = m_pattern.size();
+ if (!patternLength)
return false;
- const int len = filename.length();
-
- const int starCount = m_pattern.count(QLatin1Char('*'));
+ const qsizetype fileNameLength = fileName.size();
- // Patterns like "*~", "*.extension"
- if (m_pattern[0] == QLatin1Char('*') && m_pattern.indexOf(QLatin1Char('[')) == -1 && starCount == 1)
- {
- if (len + 1 < pattern_len) return false;
+ switch (m_patternType) {
+ case SuffixPattern: {
+ if (fileNameLength + 1 < patternLength)
+ return false;
- const QChar *c1 = m_pattern.unicode() + pattern_len - 1;
- const QChar *c2 = filename.unicode() + len - 1;
+ const QChar *c1 = m_pattern.unicode() + patternLength - 1;
+ const QChar *c2 = fileName.unicode() + fileNameLength - 1;
int cnt = 1;
- while (cnt < pattern_len && *c1-- == *c2--)
+ while (cnt < patternLength && *c1-- == *c2--)
++cnt;
- return cnt == pattern_len;
+ return cnt == patternLength;
}
-
- // Patterns like "README*" (well this is currently the only one like that...)
- if (starCount == 1 && m_pattern.at(pattern_len - 1) == QLatin1Char('*')) {
- if (len + 1 < pattern_len) return false;
- if (m_pattern.at(0) == QLatin1Char('*'))
- return filename.indexOf(QStringView{m_pattern}.mid(1, pattern_len - 2)) != -1;
+ case PrefixPattern: {
+ if (fileNameLength + 1 < patternLength)
+ return false;
const QChar *c1 = m_pattern.unicode();
- const QChar *c2 = filename.unicode();
+ const QChar *c2 = fileName.unicode();
int cnt = 1;
- while (cnt < pattern_len && *c1++ == *c2++)
+ while (cnt < patternLength && *c1++ == *c2++)
++cnt;
- return cnt == pattern_len;
+ return cnt == patternLength;
}
-
- // Names without any wildcards like "README"
- if (m_pattern.indexOf(QLatin1Char('[')) == -1 && starCount == 0 && m_pattern.indexOf(QLatin1Char('?')))
- return (m_pattern == filename);
-
- // Other (quite rare) patterns, like "*.anim[1-9j]": use slow but correct method
+ case LiteralPattern:
+ return (m_pattern == fileName);
+ case VdrPattern: // "[0-9][0-9][0-9].vdr" case
+ return fileNameLength == 7
+ && fileName.at(0).isDigit() && fileName.at(1).isDigit() && fileName.at(2).isDigit()
+ && QStringView{fileName}.mid(3, 4) == ".vdr"_L1;
+ case AnimPattern: { // "*.anim[1-9j]" case
+ if (fileNameLength < 6)
+ return false;
+ const QChar lastChar = fileName.at(fileNameLength - 1);
+ const bool lastCharOK = (lastChar.isDigit() && lastChar != u'0')
+ || lastChar == u'j';
+ return lastCharOK && QStringView{fileName}.mid(fileNameLength - 6, 5) == ".anim"_L1;
+ }
+ case OtherPattern:
+ // Other fallback patterns: slow but correct method
#if QT_CONFIG(regularexpression)
- auto rx = QRegularExpression::fromWildcard(m_pattern);
- return rx.match(filename).hasMatch();
+ auto rx = QRegularExpression::fromWildcard(m_pattern);
+ return rx.match(fileName).hasMatch();
#else
- return false;
+ return false;
#endif
+ }
+ return false;
}
-static bool isSimplePattern(const QString &pattern)
+static bool isSimplePattern(QStringView pattern)
{
// starts with "*.", has no other '*'
- return pattern.lastIndexOf(QLatin1Char('*')) == 0
- && pattern.length() > 1
- && pattern.at(1) == QLatin1Char('.') // (other dots are OK, like *.tar.bz2)
+ return pattern.lastIndexOf(u'*') == 0
+ && pattern.size() > 1
+ && pattern.at(1) == u'.' // (other dots are OK, like *.tar.bz2)
// and contains no other special character
- && !pattern.contains(QLatin1Char('?'))
- && !pattern.contains(QLatin1Char('['))
+ && !pattern.contains(u'?')
+ && !pattern.contains(u'[')
;
}
-static bool isFastPattern(const QString &pattern)
+static bool isFastPattern(QStringView pattern)
{
// starts with "*.", has no other '*' and no other '.'
- return pattern.lastIndexOf(QLatin1Char('*')) == 0
- && pattern.lastIndexOf(QLatin1Char('.')) == 1
+ return pattern.lastIndexOf(u'*') == 0
+ && pattern.lastIndexOf(u'.') == 1
// and contains no other special character
- && !pattern.contains(QLatin1Char('?'))
- && !pattern.contains(QLatin1Char('['))
+ && !pattern.contains(u'?')
+ && !pattern.contains(u'[')
;
}
@@ -208,45 +220,45 @@ void QMimeAllGlobPatterns::removeMimeType(const QString &mimeType)
m_lowWeightGlobs.removeMimeType(mimeType);
}
-void QMimeGlobPatternList::match(QMimeGlobMatchResult &result,
- const QString &fileName) const
+void QMimeGlobPatternList::match(QMimeGlobMatchResult &result, const QString &fileName,
+ const AddMatchFilterFunc &filterFunc) const
{
-
- QMimeGlobPatternList::const_iterator it = this->constBegin();
- const QMimeGlobPatternList::const_iterator endIt = this->constEnd();
- for (; it != endIt; ++it) {
- const QMimeGlobPattern &glob = *it;
- if (glob.matchFileName(fileName)) {
+ for (const QMimeGlobPattern &glob : *this) {
+ if (glob.matchFileName(fileName) && filterFunc(glob.mimeType())) {
const QString pattern = glob.pattern();
- const int suffixLen = isSimplePattern(pattern) ? pattern.length() - 2 : 0;
+ const qsizetype suffixLen = isSimplePattern(pattern) ? pattern.size() - strlen("*.") : 0;
result.addMatch(glob.mimeType(), glob.weight(), pattern, suffixLen);
}
}
}
-void QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const
+void QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result,
+ const AddMatchFilterFunc &filterFunc) const
{
// First try the high weight matches (>50), if any.
- m_highWeightGlobs.match(result, fileName);
+ m_highWeightGlobs.match(result, fileName, filterFunc);
// Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
// (which is most of them, so this optimization is definitely worth it)
- const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
+ const qsizetype lastDot = fileName.lastIndexOf(u'.');
if (lastDot != -1) { // if no '.', skip the extension lookup
- const int ext_len = fileName.length() - lastDot - 1;
+ const qsizetype ext_len = fileName.size() - lastDot - 1;
const QString simpleExtension = fileName.right(ext_len).toLower();
// (toLower because fast patterns are always case-insensitive and saved as lowercase)
const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
- const QString simplePattern = QLatin1String("*.") + simpleExtension;
- for (const QString &mime : matchingMimeTypes)
- result.addMatch(mime, 50, simplePattern, simpleExtension.size());
+ const QString simplePattern = "*."_L1 + simpleExtension;
+ for (const QString &mime : matchingMimeTypes) {
+ if (filterFunc(mime)) {
+ result.addMatch(mime, 50, simplePattern, simpleExtension.size());
+ }
+ }
// Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
// at least those with weight 50.
}
// Finally, try the low weight matches (<=50)
- m_lowWeightGlobs.match(result, fileName);
+ m_lowWeightGlobs.match(result, fileName, filterFunc);
}
void QMimeAllGlobPatterns::clear()
diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h
index 49f145e8db..b4316355ba 100644
--- a/src/corelib/mimetypes/qmimeglobpattern_p.h
+++ b/src/corelib/mimetypes/qmimeglobpattern_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEGLOBPATTERN_P_H
#define QMIMEGLOBPATTERN_P_H
@@ -58,17 +22,20 @@ QT_REQUIRE_CONFIG(mimetype);
#include <QtCore/qstringlist.h>
#include <QtCore/qhash.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
struct QMimeGlobMatchResult
{
- void addMatch(const QString &mimeType, int weight, const QString &pattern, int knownSuffixLength = 0);
+ void addMatch(const QString &mimeType, int weight, const QString &pattern,
+ qsizetype knownSuffixLength = 0);
QStringList m_matchingMimeTypes; // only those with highest weight
QStringList m_allMatchingMimeTypes;
int m_weight = 0;
- int m_matchingPatternLength = 0;
- int m_knownSuffixLength = 0;
+ qsizetype m_matchingPatternLength = 0;
+ qsizetype m_knownSuffixLength = 0;
};
class QMimeGlobPattern
@@ -80,7 +47,10 @@ public:
explicit QMimeGlobPattern(const QString &thePattern, const QString &theMimeType, unsigned theWeight = DefaultWeight, Qt::CaseSensitivity s = Qt::CaseInsensitive) :
m_pattern(s == Qt::CaseInsensitive ? thePattern.toLower() : thePattern),
- m_mimeType(theMimeType), m_weight(theWeight), m_caseSensitivity(s)
+ m_mimeType(theMimeType),
+ m_weight(theWeight),
+ m_caseSensitivity(s),
+ m_patternType(detectPatternType(m_pattern))
{
}
@@ -90,9 +60,10 @@ public:
qSwap(m_mimeType, other.m_mimeType);
qSwap(m_weight, other.m_weight);
qSwap(m_caseSensitivity, other.m_caseSensitivity);
+ qSwap(m_patternType, other.m_patternType);
}
- bool matchFileName(const QString &filename) const;
+ bool matchFileName(const QString &inputFileName) const;
inline const QString &pattern() const { return m_pattern; }
inline unsigned weight() const { return m_weight; }
@@ -100,38 +71,50 @@ public:
inline bool isCaseSensitive() const { return m_caseSensitivity == Qt::CaseSensitive; }
private:
+ enum PatternType {
+ SuffixPattern,
+ PrefixPattern,
+ LiteralPattern,
+ VdrPattern, // special handling for "[0-9][0-9][0-9].vdr" pattern
+ AnimPattern, // special handling for "*.anim[1-9j]" pattern
+ OtherPattern
+ };
+ PatternType detectPatternType(QStringView pattern) const;
+
QString m_pattern;
QString m_mimeType;
int m_weight;
Qt::CaseSensitivity m_caseSensitivity;
+ PatternType m_patternType;
};
Q_DECLARE_SHARED(QMimeGlobPattern)
+using AddMatchFilterFunc = std::function<bool(const QString &)>;
+
class QMimeGlobPatternList : public QList<QMimeGlobPattern>
{
public:
- bool hasPattern(const QString &mimeType, const QString &pattern) const
+ bool hasPattern(QStringView mimeType, QStringView pattern) const
{
- const_iterator it = begin();
- const const_iterator myend = end();
- for (; it != myend; ++it)
- if ((*it).pattern() == pattern && (*it).mimeType() == mimeType)
- return true;
- return false;
+ auto matchesMimeAndPattern = [mimeType, pattern](const QMimeGlobPattern &e) {
+ return e.pattern() == pattern && e.mimeType() == mimeType;
+ };
+ return std::any_of(begin(), end(), matchesMimeAndPattern);
}
/*!
"noglobs" is very rare occurrence, so it's ok if it's slow
*/
- void removeMimeType(const QString &mimeType)
+ void removeMimeType(QStringView mimeType)
{
- auto isMimeTypeEqual = [&mimeType](const QMimeGlobPattern &pattern) {
+ auto isMimeTypeEqual = [mimeType](const QMimeGlobPattern &pattern) {
return pattern.mimeType() == mimeType;
};
- erase(std::remove_if(begin(), end(), isMimeTypeEqual), end());
+ removeIf(isMimeTypeEqual);
}
- void match(QMimeGlobMatchResult &result, const QString &fileName) const;
+ void match(QMimeGlobMatchResult &result, const QString &fileName,
+ const AddMatchFilterFunc &filterFunc) const;
};
/*!
@@ -148,7 +131,8 @@ public:
void addGlob(const QMimeGlobPattern &glob);
void removeMimeType(const QString &mimeType);
- void matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const;
+ void matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result,
+ const AddMatchFilterFunc &filterFunc) const;
void clear();
PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"
diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp
index 2c8c2e7199..3c33d53aac 100644
--- a/src/corelib/mimetypes/qmimemagicrule.cpp
+++ b/src/corelib/mimetypes/qmimemagicrule.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define QT_NO_CAST_FROM_ASCII
@@ -47,29 +11,31 @@
#include <QtCore/QDebug>
#include <qendian.h>
+#include <private/qoffsetstringarray_p.h>
+#include <private/qtools_p.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
// in the same order as Type!
-static const char magicRuleTypes_string[] =
- "invalid\0"
- "string\0"
- "host16\0"
- "host32\0"
- "big16\0"
- "big32\0"
- "little16\0"
- "little32\0"
- "byte\0"
- "\0";
-
-static const int magicRuleTypes_indices[] = {
- 0, 8, 15, 22, 29, 35, 41, 50, 59, 64, 0
-};
+static constexpr auto magicRuleTypes = qOffsetStringArray(
+ "invalid",
+ "string",
+ "host16",
+ "host32",
+ "big16",
+ "big32",
+ "little16",
+ "little32",
+ "byte"
+);
QMimeMagicRule::Type QMimeMagicRule::type(const QByteArray &theTypeName)
{
for (int i = String; i <= Byte; ++i) {
- if (theTypeName == magicRuleTypes_string + magicRuleTypes_indices[i])
+ if (theTypeName == magicRuleTypes.at(i))
return Type(i);
}
return Invalid;
@@ -77,7 +43,7 @@ QMimeMagicRule::Type QMimeMagicRule::type(const QByteArray &theTypeName)
QByteArray QMimeMagicRule::typeName(QMimeMagicRule::Type theType)
{
- return magicRuleTypes_string + magicRuleTypes_indices[theType];
+ return magicRuleTypes.at(theType);
}
bool QMimeMagicRule::operator==(const QMimeMagicRule &other) const
@@ -94,12 +60,12 @@ bool QMimeMagicRule::operator==(const QMimeMagicRule &other) const
}
// Used by both providers
-bool QMimeMagicRule::matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength,
- int valueLength, const char *valueData, const char *mask)
+bool QMimeMagicRule::matchSubstring(const char *dataPtr, qsizetype dataSize, int rangeStart, int rangeLength,
+ qsizetype valueLength, const char *valueData, const char *mask)
{
// Size of searched data.
// Example: value="ABC", rangeLength=3 -> we need 3+3-1=5 bytes (ABCxx,xABCx,xxABC would match)
- const int dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart);
+ const qsizetype dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart);
if (!mask) {
// callgrind says QByteArray::indexOf is much slower, since our strings are typically too
@@ -123,7 +89,7 @@ bool QMimeMagicRule::matchSubstring(const char *dataPtr, int dataSize, int range
// deviceSize is 4, so dataNeeded was max'ed to 4.
// maxStartPos = 4 - 3 + 1 = 2, and indeed
// we need to check for a match a positions 0 and 1 (ABCx and xABC).
- const int maxStartPos = dataNeeded - valueLength + 1;
+ const qsizetype maxStartPos = dataNeeded - valueLength + 1;
for (int i = 0; i < maxStartPos; ++i) {
const char *d = readDataBase + i;
bool valid = true;
@@ -181,21 +147,17 @@ static inline QByteArray makePattern(const QByteArray &value)
char c = 0;
for (int i = 0; i < 2 && p + 1 < e; ++i) {
++p;
- if (*p >= '0' && *p <= '9')
- c = (c << 4) + *p - '0';
- else if (*p >= 'a' && *p <= 'f')
- c = (c << 4) + *p - 'a' + 10;
- else if (*p >= 'A' && *p <= 'F')
- c = (c << 4) + *p - 'A' + 10;
+ if (const int h = fromHex(*p); h != -1)
+ c = (c << 4) + h;
else
continue;
}
*data++ = c;
- } else if (*p >= '0' && *p <= '7') { // oct (\\7, or \\77, or \\377)
+ } else if (isOctalDigit(*p)) { // oct (\\7, or \\77, or \\377)
char c = *p - '0';
- if (p + 1 < e && p[1] >= '0' && p[1] <= '7') {
+ if (p + 1 < e && isOctalDigit(p[1])) {
c = (c << 3) + *(++p) - '0';
- if (p + 1 < e && p[1] >= '0' && p[1] <= '7' && p[-1] <= '3')
+ if (p + 1 < e && isOctalDigit(p[1]) && p[-1] <= '3')
c = (c << 3) + *(++p) - '0';
}
*data++ = c;
@@ -231,11 +193,14 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
m_mask(mask),
m_matchFunction(nullptr)
{
- if (Q_UNLIKELY(m_type == Invalid))
- *errorString = QLatin1String("Type ") + type + QLatin1String(" is not supported");
+ if (Q_UNLIKELY(m_type == Invalid)) {
+ if (errorString)
+ *errorString = "Type "_L1 + type + " is not supported"_L1;
+ return;
+ }
// Parse for offset as "1" or "1:10"
- const int colonIndex = offsets.indexOf(QLatin1Char(':'));
+ const qsizetype colonIndex = offsets.indexOf(u':');
const QStringView startPosStr = QStringView{offsets}.mid(0, colonIndex); // \ These decay to returning 'offsets'
const QStringView endPosStr = QStringView{offsets}.mid(colonIndex + 1);// / unchanged when colonIndex == -1
if (Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString)) ||
@@ -257,7 +222,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
if (Q_UNLIKELY(!ok)) {
m_type = Invalid;
if (errorString)
- *errorString = QLatin1String("Invalid magic rule value \"") + QLatin1String(m_value) + QLatin1Char('"');
+ *errorString = "Invalid magic rule value \""_L1 + QLatin1StringView(m_value) + u'"';
return;
}
m_numberMask = !m_mask.isEmpty() ? m_mask.toUInt(&ok, 0) : 0; // autodetect base
@@ -271,7 +236,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
if (Q_UNLIKELY(m_mask.size() < 4 || !m_mask.startsWith("0x"))) {
m_type = Invalid;
if (errorString)
- *errorString = QLatin1String("Invalid magic rule mask \"") + QLatin1String(m_mask) + QLatin1Char('"');
+ *errorString = "Invalid magic rule mask \""_L1 + QLatin1StringView(m_mask) + u'"';
return;
}
const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
@@ -279,7 +244,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
if (Q_UNLIKELY(tempMask.size() != m_pattern.size())) {
m_type = Invalid;
if (errorString)
- *errorString = QLatin1String("Invalid magic rule mask size \"") + QLatin1String(m_mask) + QLatin1Char('"');
+ *errorString = "Invalid magic rule mask size \""_L1 + QLatin1StringView(m_mask) + u'"';
return;
}
m_mask = tempMask;
diff --git a/src/corelib/mimetypes/qmimemagicrule_p.h b/src/corelib/mimetypes/qmimemagicrule_p.h
index 5091d483b6..bd1b72d113 100644
--- a/src/corelib/mimetypes/qmimemagicrule_p.h
+++ b/src/corelib/mimetypes/qmimemagicrule_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEMAGICRULE_P_H
#define QMIMEMAGICRULE_P_H
@@ -99,7 +63,9 @@ public:
static Type type(const QByteArray &type);
static QByteArray typeName(Type type);
- static bool matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength, int valueLength, const char *valueData, const char *mask);
+ static bool matchSubstring(const char *dataPtr, qsizetype dataSize, int rangeStart,
+ int rangeLength, qsizetype valueLength, const char *valueData,
+ const char *mask);
private:
Type m_type;
diff --git a/src/corelib/mimetypes/qmimemagicrulematcher.cpp b/src/corelib/mimetypes/qmimemagicrulematcher.cpp
index 8f44fd2f80..24a12ee561 100644
--- a/src/corelib/mimetypes/qmimemagicrulematcher.cpp
+++ b/src/corelib/mimetypes/qmimemagicrulematcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define QT_NO_CAST_FROM_ASCII
diff --git a/src/corelib/mimetypes/qmimemagicrulematcher_p.h b/src/corelib/mimetypes/qmimemagicrulematcher_p.h
index fe714987e6..02bc73150e 100644
--- a/src/corelib/mimetypes/qmimemagicrulematcher_p.h
+++ b/src/corelib/mimetypes/qmimemagicrulematcher_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEMAGICRULEMATCHER_P_H
#define QMIMEMAGICRULEMATCHER_P_H
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 47b5e42167..458cd46385 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmimeprovider_p.h"
@@ -55,7 +19,7 @@
#include <QtEndian>
#if QT_CONFIG(mimetype_database)
-# if defined(Q_CC_MSVC)
+# if defined(Q_CC_MSVC_ONLY)
# pragma section(".qtmimedatabase", read, shared)
__declspec(allocate(".qtmimedatabase")) __declspec(align(4096))
# elif defined(Q_OS_DARWIN)
@@ -84,17 +48,7 @@ __attribute__((section(".qtmimedatabase"), aligned(4096)))
QT_BEGIN_NAMESPACE
-QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory)
- : m_db(db), m_directory(directory)
-{
-}
-
-
-QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory)
- : QMimeProviderBase(db, directory), m_mimetypeListLoaded(false)
-{
- ensureLoaded();
-}
+using namespace Qt::StringLiterals;
struct QMimeBinaryProvider::CacheFile
{
@@ -123,6 +77,43 @@ struct QMimeBinaryProvider::CacheFile
bool m_valid;
};
+static inline void appendIfNew(QStringList &list, const QString &str)
+{
+ if (!list.contains(str))
+ list.push_back(str);
+}
+
+QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory)
+ : m_db(db), m_directory(directory)
+{
+}
+
+QMimeProviderBase *QMimeProviderBase::overrideProvider() const
+{
+ return m_overrideProvider;
+}
+
+void QMimeProviderBase::setOverrideProvider(QMimeProviderBase *provider)
+{
+ m_overrideProvider = provider;
+}
+
+bool QMimeProviderBase::isMimeTypeGlobsExcluded(const QString &name) const
+{
+ if (m_overrideProvider) {
+ if (m_overrideProvider->hasGlobDeleteAll(name))
+ return true;
+ return m_overrideProvider->isMimeTypeGlobsExcluded(name);
+ }
+ return false;
+}
+
+QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory)
+ : QMimeProviderBase(db, directory), m_mimetypeListLoaded(false)
+{
+ ensureLoaded();
+}
+
QMimeBinaryProvider::CacheFile::CacheFile(const QString &fileName)
: file(fileName), m_valid(false)
{
@@ -143,7 +134,7 @@ bool QMimeBinaryProvider::CacheFile::load()
const int minor = getUint16(2);
m_valid = (major == 1 && minor >= 1 && minor <= 2);
}
- m_mtime = QFileInfo(file).lastModified();
+ m_mtime = QFileInfo(file).lastModified(QTimeZone::UTC);
return m_valid;
}
@@ -157,16 +148,18 @@ bool QMimeBinaryProvider::CacheFile::reload()
return load();
}
-QMimeBinaryProvider::~QMimeBinaryProvider()
-{
- delete m_cacheFile;
-}
+QMimeBinaryProvider::~QMimeBinaryProvider() = default;
bool QMimeBinaryProvider::isValid()
{
return m_cacheFile != nullptr;
}
+bool QMimeBinaryProvider::isInternalDatabase() const
+{
+ return false;
+}
+
// Position of the "list offsets" values, at the beginning of the mime.cache file
enum {
PosAliasListOffset = 4,
@@ -183,7 +176,7 @@ enum {
bool QMimeBinaryProvider::checkCacheChanged()
{
QFileInfo fileInfo(m_cacheFile->file);
- if (fileInfo.lastModified() > m_cacheFile->m_mtime) {
+ if (fileInfo.lastModified(QTimeZone::UTC) > m_cacheFile->m_mtime) {
// Deletion can't happen by just running update-mime-database.
// But the user could use rm -rf :-)
m_cacheFile->reload(); // will mark itself as invalid on failure
@@ -195,40 +188,27 @@ bool QMimeBinaryProvider::checkCacheChanged()
void QMimeBinaryProvider::ensureLoaded()
{
if (!m_cacheFile) {
- const QString cacheFileName = m_directory + QLatin1String("/mime.cache");
- m_cacheFile = new CacheFile(cacheFileName);
+ const QString cacheFileName = m_directory + "/mime.cache"_L1;
+ m_cacheFile = std::make_unique<CacheFile>(cacheFileName);
m_mimetypeListLoaded = false;
+ m_mimetypeExtra.clear();
} else {
- if (checkCacheChanged())
+ if (checkCacheChanged()) {
m_mimetypeListLoaded = false;
- else
+ m_mimetypeExtra.clear();
+ } else {
return; // nothing to do
+ }
}
- if (!m_cacheFile->isValid()) { // verify existence and version
- delete m_cacheFile;
- m_cacheFile = nullptr;
- }
+ if (!m_cacheFile->isValid()) // verify existence and version
+ m_cacheFile.reset();
}
-static QMimeType mimeTypeForNameUnchecked(const QString &name)
-{
- QMimeTypePrivate data;
- data.name = name;
- data.fromCache = true;
- // The rest is retrieved on demand.
- // comment and globPatterns: in loadMimeTypePrivate
- // iconName: in loadIcon
- // genericIconName: in loadGenericIcon
- return QMimeType(data);
-}
-
-QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
+bool QMimeBinaryProvider::knowsMimeType(const QString &name)
{
if (!m_mimetypeListLoaded)
loadMimeTypeList();
- if (!m_mimetypeNames.contains(name))
- return QMimeType(); // unknown mimetype
- return mimeTypeForNameUnchecked(name);
+ return m_mimetypeNames.contains(name);
}
void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
@@ -236,22 +216,34 @@ void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobM
if (fileName.isEmpty())
return;
Q_ASSERT(m_cacheFile);
- const QString lowerFileName = fileName.toLower();
+ int numMatches = 0;
// Check literals (e.g. "Makefile")
- matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName);
- // Check complex globs (e.g. "callgrind.out[0-9]*")
- matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
+ numMatches = matchGlobList(result, m_cacheFile.get(),
+ m_cacheFile->getUint32(PosLiteralListOffset), fileName);
// Check the very common *.txt cases with the suffix tree
- const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
- const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
- const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
- if (result.m_matchingMimeTypes.isEmpty())
- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
+ if (numMatches == 0) {
+ const QString lowerFileName = fileName.toLower();
+ const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
+ const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
+ const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
+ if (matchSuffixTree(result, m_cacheFile.get(), numRoots, firstRootOffset, lowerFileName,
+ lowerFileName.size() - 1, false)) {
+ ++numMatches;
+ } else if (matchSuffixTree(result, m_cacheFile.get(), numRoots, firstRootOffset, fileName,
+ fileName.size() - 1, true)) {
+ ++numMatches;
+ }
+ }
+ // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*")
+ if (numMatches == 0)
+ matchGlobList(result, m_cacheFile.get(), m_cacheFile->getUint32(PosGlobListOffset),
+ fileName);
}
-void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
+int QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off,
+ const QString &fileName)
{
+ int numMatches = 0;
const int numGlobs = cacheFile->getUint32(off);
//qDebug() << "Loading" << numGlobs << "globs from" << cacheFile->file.fileName() << "at offset" << cacheFile->globListOffset;
for (int i = 0; i < numGlobs; ++i) {
@@ -261,19 +253,26 @@ void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile
const int weight = flagsAndWeight & 0xff;
const bool caseSensitive = flagsAndWeight & 0x100;
const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
- const QString pattern = QLatin1String(cacheFile->getCharStar(globOffset));
+ const QString pattern = QLatin1StringView(cacheFile->getCharStar(globOffset));
- const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
+ const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset));
//qDebug() << pattern << mimeType << weight << caseSensitive;
- QMimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
+ if (isMimeTypeGlobsExcluded(mimeType))
+ continue;
- // TODO: this could be done faster for literals where a simple == would do.
- if (glob.matchFileName(fileName))
- result.addMatch(QLatin1String(mimeType), weight, pattern);
+ QMimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
+ if (glob.matchFileName(fileName)) {
+ result.addMatch(mimeType, weight, pattern);
+ ++numMatches;
+ }
}
+ return numMatches;
}
-bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBinaryProvider::CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck)
+bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result,
+ QMimeBinaryProvider::CacheFile *cacheFile, int numEntries,
+ int firstOffset, const QString &fileName,
+ qsizetype charPos, bool caseSensitiveCheck)
{
QChar fileChar = fileName[charPos];
int min = 0;
@@ -300,13 +299,16 @@ bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBin
if (mch != 0)
break;
const int mimeTypeOffset = cacheFile->getUint32(childOff + 4);
- const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
+ const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset));
+ if (isMimeTypeGlobsExcluded(mimeType))
+ continue;
const int flagsAndWeight = cacheFile->getUint32(childOff + 8);
const int weight = flagsAndWeight & 0xff;
const bool caseSensitive = flagsAndWeight & 0x100;
if (caseSensitiveCheck || !caseSensitive) {
- result.addMatch(QLatin1String(mimeType), weight,
- QLatin1Char('*') + QStringView{fileName}.mid(charPos + 1), fileName.size() - charPos - 2);
+ result.addMatch(mimeType, weight,
+ u'*' + QStringView{ fileName }.mid(charPos + 1),
+ fileName.size() - charPos - 2);
success = true;
}
}
@@ -320,7 +322,7 @@ bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBin
bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data)
{
const char *dataPtr = data.constData();
- const int dataSize = data.size();
+ const qsizetype dataSize = data.size();
for (int matchlet = 0; matchlet < numMatchlets; ++matchlet) {
const int off = firstOffset + matchlet * 32;
const int rangeStart = cacheFile->getUint32(off);
@@ -345,7 +347,7 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi
return false;
}
-void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate)
+void QMimeBinaryProvider::findByMagic(const QByteArray &data, QMimeMagicResult &result)
{
const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
const int numMatches = m_cacheFile->getUint32(magicListOffset);
@@ -356,14 +358,16 @@ void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr,
const int off = firstMatchOffset + i * 16;
const int numMatchlets = m_cacheFile->getUint32(off + 8);
const int firstMatchletOffset = m_cacheFile->getUint32(off + 12);
- if (matchMagicRule(m_cacheFile, numMatchlets, firstMatchletOffset, data)) {
+ if (matchMagicRule(m_cacheFile.get(), numMatchlets, firstMatchletOffset, data)) {
const int mimeTypeOffset = m_cacheFile->getUint32(off + 4);
const char *mimeType = m_cacheFile->getCharStar(mimeTypeOffset);
- *accuracyPtr = m_cacheFile->getUint32(off);
- // Return the first match. We have no rules for conflicting magic data...
- // (mime.cache itself is sorted, but what about local overrides with a lower prio?)
- candidate = mimeTypeForNameUnchecked(QLatin1String(mimeType));
- return;
+ const int accuracy = static_cast<int>(m_cacheFile->getUint32(off));
+ if (accuracy > result.accuracy) {
+ result.accuracy = accuracy;
+ result.candidate = QString::fromLatin1(mimeType);
+ // Return the first match, mime.cache is sorted
+ return;
+ }
}
}
}
@@ -393,8 +397,7 @@ void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result)
const int parentOffset = m_cacheFile->getUint32(parentsOffset + 4 + 4 * i);
const char *aParent = m_cacheFile->getCharStar(parentOffset);
const QString strParent = QString::fromLatin1(aParent);
- if (!result.contains(strParent))
- result.append(strParent);
+ appendIfNew(result, strParent);
}
break;
}
@@ -421,7 +424,7 @@ QString QMimeBinaryProvider::resolveAlias(const QString &name)
} else {
const int mimeOffset = m_cacheFile->getUint32(off + 4);
const char *mimeType = m_cacheFile->getCharStar(mimeOffset);
- return QLatin1String(mimeType);
+ return QLatin1StringView(mimeType);
}
}
return QString();
@@ -441,8 +444,7 @@ void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result)
const int aliasOffset = m_cacheFile->getUint32(off);
const char *alias = m_cacheFile->getCharStar(aliasOffset);
const QString strAlias = QString::fromLatin1(alias);
- if (!result.contains(strAlias))
- result.append(strAlias);
+ appendIfNew(result, strAlias);
}
}
}
@@ -454,13 +456,14 @@ void QMimeBinaryProvider::loadMimeTypeList()
m_mimetypeNames.clear();
// Unfortunately mime.cache doesn't have a full list of all mimetypes.
// So we have to parse the plain-text files called "types".
- QFile file(m_directory + QStringLiteral("/types"));
+ QFile file(m_directory + QStringView(u"/types"));
if (file.open(QIODevice::ReadOnly)) {
while (!file.atEnd()) {
- QByteArray line = file.readLine();
- if (line.endsWith('\n'))
- line.chop(1);
- m_mimetypeNames.insert(QString::fromLatin1(line));
+ const QByteArray line = file.readLine();
+ auto lineView = QByteArrayView(line);
+ if (lineView.endsWith('\n'))
+ lineView.chop(1);
+ m_mimetypeNames.insert(QString::fromLatin1(lineView));
}
}
}
@@ -470,114 +473,117 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result)
{
loadMimeTypeList();
if (result.isEmpty()) {
- result.reserve(m_mimetypeNames.count());
- for (const QString &name : qAsConst(m_mimetypeNames))
- result.append(mimeTypeForNameUnchecked(name));
+ result.reserve(m_mimetypeNames.size());
+ for (const QString &name : std::as_const(m_mimetypeNames))
+ result.append(QMimeType(QMimeTypePrivate(name)));
} else {
- for (const QString &name : qAsConst(m_mimetypeNames))
+ for (const QString &name : std::as_const(m_mimetypeNames))
if (std::find_if(result.constBegin(), result.constEnd(), [name](const QMimeType &mime) -> bool { return mime.name() == name; })
== result.constEnd())
- result.append(mimeTypeForNameUnchecked(name));
+ result.append(QMimeType(QMimeTypePrivate(name)));
}
}
-void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
+QMimeTypePrivate::LocaleHash QMimeBinaryProvider::localeComments(const QString &name)
{
-#ifdef QT_NO_XMLSTREAMREADER
- Q_UNUSED(data);
- qWarning("Cannot load mime type since QXmlStreamReader is not available.");
- return;
-#else
- if (data.loaded)
- return;
- data.loaded = true;
- // load comment and globPatterns
-
- const QString file = data.name + QLatin1String(".xml");
- // shared-mime-info since 1.3 lowercases the xml files
- QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file.toLower());
- if (mimeFiles.isEmpty())
- mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file); // pre-1.3
- if (mimeFiles.isEmpty()) {
- qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n"
- "Either it was just removed, or the directory doesn't have executable permission..."
- << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
- return;
- }
+ MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
+ if (it != m_mimetypeExtra.cend())
+ return it->second.localeComments;
+ return {};
+}
- QString mainPattern;
+bool QMimeBinaryProvider::hasGlobDeleteAll(const QString &name)
+{
+ MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
+ if (it != m_mimetypeExtra.cend())
+ return it->second.hasGlobDeleteAll;
+ return {};
+}
+
+QStringList QMimeBinaryProvider::globPatterns(const QString &name)
+{
+ MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
+ if (it != m_mimetypeExtra.cend())
+ return it->second.globPatterns;
+ return {};
+}
- for (QStringList::const_reverse_iterator it = mimeFiles.crbegin(), end = mimeFiles.crend(); it != end; ++it) { // global first, then local.
- QFile qfile(*it);
+QMimeBinaryProvider::MimeTypeExtraMap::const_iterator
+QMimeBinaryProvider::loadMimeTypeExtra(const QString &mimeName)
+{
+#if QT_CONFIG(xmlstreamreader)
+ auto it = m_mimetypeExtra.find(mimeName);
+ if (it == m_mimetypeExtra.cend()) {
+ // load comment and globPatterns
+
+ // shared-mime-info since 1.3 lowercases the xml files
+ QString mimeFile = m_directory + u'/' + mimeName.toLower() + ".xml"_L1;
+ if (!QFile::exists(mimeFile))
+ mimeFile = m_directory + u'/' + mimeName + ".xml"_L1; // pre-1.3
+
+ QFile qfile(mimeFile);
if (!qfile.open(QFile::ReadOnly))
- continue;
+ return m_mimetypeExtra.cend();
+
+ it = m_mimetypeExtra.try_emplace(mimeName).first;
+ MimeTypeExtra &extra = it->second;
+ QString mainPattern;
QXmlStreamReader xml(&qfile);
if (xml.readNextStartElement()) {
- if (xml.name() != QLatin1String("mime-type")) {
- continue;
+ if (xml.name() != "mime-type"_L1) {
+ return m_mimetypeExtra.cend();
}
- const QStringRef name = xml.attributes().value(QLatin1String("type"));
+ const auto name = xml.attributes().value("type"_L1);
if (name.isEmpty())
- continue;
- if (name.compare(data.name, Qt::CaseInsensitive))
- qWarning() << "Got name" << name << "in file" << file << "expected" << data.name;
+ return m_mimetypeExtra.cend();
+ if (name.compare(mimeName, Qt::CaseInsensitive))
+ qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << mimeName;
while (xml.readNextStartElement()) {
- const QStringRef tag = xml.name();
- if (tag == QLatin1String("comment")) {
- QString lang = xml.attributes().value(QLatin1String("xml:lang")).toString();
+ const auto tag = xml.name();
+ if (tag == "comment"_L1) {
+ QString lang = xml.attributes().value("xml:lang"_L1).toString();
const QString text = xml.readElementText();
if (lang.isEmpty()) {
- lang = QLatin1String("default"); // no locale attribute provided, treat it as default.
+ lang = "default"_L1; // no locale attribute provided, treat it as default.
}
- data.localeComments.insert(lang, text);
+ extra.localeComments.insert(lang, text);
continue; // we called readElementText, so we're at the EndElement already.
- } else if (tag == QLatin1String("icon")) { // as written out by shared-mime-info >= 0.40
- data.iconName = xml.attributes().value(QLatin1String("name")).toString();
- } else if (tag == QLatin1String("glob-deleteall")) { // as written out by shared-mime-info >= 0.70
- data.globPatterns.clear();
- } else if (tag == QLatin1String("glob")) { // as written out by shared-mime-info >= 0.70
- const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString();
- if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*'))) {
+ } else if (tag == "glob-deleteall"_L1) { // as written out by shared-mime-info >= 0.70
+ extra.hasGlobDeleteAll = true;
+ } else if (tag == "glob"_L1) { // as written out by shared-mime-info >= 0.70
+ const QString pattern = xml.attributes().value("pattern"_L1).toString();
+ if (mainPattern.isEmpty() && pattern.startsWith(u'*')) {
mainPattern = pattern;
}
- if (!data.globPatterns.contains(pattern))
- data.globPatterns.append(pattern);
+ appendIfNew(extra.globPatterns, pattern);
}
xml.skipCurrentElement();
}
- Q_ASSERT(xml.name() == QLatin1String("mime-type"));
+ Q_ASSERT(xml.name() == "mime-type"_L1);
}
- }
- // Let's assume that shared-mime-info is at least version 0.70
- // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file.
-#if 1
- if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.constFirst() != mainPattern)) {
- // ensure it's first in the list of patterns
- data.globPatterns.removeAll(mainPattern);
- data.globPatterns.prepend(mainPattern);
- }
-#else
- const bool globsInXml = sharedMimeInfoVersion() >= QT_VERSION_CHECK(0, 70, 0);
- if (globsInXml) {
- if (!mainPattern.isEmpty() && data.globPatterns.constFirst() != mainPattern) {
+ // Let's assume that shared-mime-info is at least version 0.70
+ // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file.
+ if (!mainPattern.isEmpty() &&
+ (extra.globPatterns.isEmpty() || extra.globPatterns.constFirst() != mainPattern)) {
// ensure it's first in the list of patterns
- data.globPatterns.removeAll(mainPattern);
- data.globPatterns.prepend(mainPattern);
+ extra.globPatterns.removeAll(mainPattern);
+ extra.globPatterns.prepend(mainPattern);
}
- } else {
- // Fallback: get the patterns from the globs file
- // TODO: This would be the only way to support shared-mime-info < 0.70
- // But is this really worth the effort?
}
-#endif
-#endif //QT_NO_XMLSTREAMREADER
+ return it;
+#else
+ Q_UNUSED(mimeName);
+ qWarning("Cannot load mime type since QXmlStreamReader is not available.");
+ return m_mimetypeExtra.cend();
+#endif // feature xmlstreamreader
}
// Binary search in the icons or generic-icons list
-QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime)
+QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset,
+ const QByteArray &inputMime)
{
const int iconsListOffset = cacheFile->getUint32(posListOffset);
const int numIcons = cacheFile->getUint32(iconsListOffset);
@@ -595,28 +601,22 @@ QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posList
end = medium - 1;
else {
const int iconOffset = cacheFile->getUint32(off + 4);
- return QLatin1String(cacheFile->getCharStar(iconOffset));
+ return QLatin1StringView(cacheFile->getCharStar(iconOffset));
}
}
- return QLatin1String();
+ return QLatin1StringView();
}
-void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
+QString QMimeBinaryProvider::icon(const QString &name)
{
- const QByteArray inputMime = data.name.toLatin1();
- const QLatin1String icon = iconForMime(m_cacheFile, PosIconsListOffset, inputMime);
- if (!icon.isEmpty()) {
- data.iconName = icon;
- }
+ const QByteArray inputMime = name.toLatin1();
+ return iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime);
}
-void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
+QString QMimeBinaryProvider::genericIcon(const QString &name)
{
- const QByteArray inputMime = data.name.toLatin1();
- const QLatin1String icon = iconForMime(m_cacheFile, PosGenericIconsListOffset, inputMime);
- if (!icon.isEmpty()) {
- data.genericIconName = icon;
- }
+ const QByteArray inputMime = name.toLatin1();
+ return iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime);
}
////
@@ -692,43 +692,48 @@ bool QMimeXMLProvider::isValid()
return true;
}
-QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name)
+bool QMimeXMLProvider::isInternalDatabase() const
{
- return m_nameMimeTypeMap.value(name);
+#if QT_CONFIG(mimetype_database)
+ return m_directory == internalMimeFileName();
+#else
+ return false;
+#endif
+}
+
+bool QMimeXMLProvider::knowsMimeType(const QString &name)
+{
+ return m_nameMimeTypeMap.contains(name);
}
void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
{
- m_mimeTypeGlobs.matchingGlobs(fileName, result);
+ auto filterFunc = [this](const QString &name) { return !isMimeTypeGlobsExcluded(name); };
+ m_mimeTypeGlobs.matchingGlobs(fileName, result, filterFunc);
}
-void QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate)
+void QMimeXMLProvider::findByMagic(const QByteArray &data, QMimeMagicResult &result)
{
- QString candidateName;
- bool foundOne = false;
- for (const QMimeMagicRuleMatcher &matcher : qAsConst(m_magicMatchers)) {
+ for (const QMimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) {
if (matcher.matches(data)) {
const int priority = matcher.priority();
- if (priority > *accuracyPtr) {
- *accuracyPtr = priority;
- candidateName = matcher.mimetype();
- foundOne = true;
+ if (priority > result.accuracy) {
+ result.accuracy = priority;
+ result.candidate = matcher.mimetype();
}
}
}
- if (foundOne)
- candidate = mimeTypeForName(candidateName);
}
void QMimeXMLProvider::ensureLoaded()
{
QStringList allFiles;
- const QString packageDir = m_directory + QStringLiteral("/packages");
+ const QString packageDir = m_directory + QStringView(u"/packages");
QDir dir(packageDir);
const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
- allFiles.reserve(files.count());
+ allFiles.reserve(files.size());
for (const QString &xmlFile : files)
- allFiles.append(packageDir + QLatin1Char('/') + xmlFile);
+ allFiles.append(packageDir + u'/' + xmlFile);
if (m_allFiles == allFiles)
return;
@@ -742,10 +747,35 @@ void QMimeXMLProvider::ensureLoaded()
//qDebug() << "Loading" << m_allFiles;
- for (const QString &file : qAsConst(allFiles))
+ for (const QString &file : std::as_const(allFiles))
load(file);
}
+QMimeTypePrivate::LocaleHash QMimeXMLProvider::localeComments(const QString &name)
+{
+ return m_nameMimeTypeMap.value(name).localeComments;
+}
+
+bool QMimeXMLProvider::hasGlobDeleteAll(const QString &name)
+{
+ return m_nameMimeTypeMap.value(name).hasGlobDeleteAll;
+}
+
+QStringList QMimeXMLProvider::globPatterns(const QString &name)
+{
+ return m_nameMimeTypeMap.value(name).globPatterns;
+}
+
+QString QMimeXMLProvider::icon(const QString &name)
+{
+ return m_nameMimeTypeMap.value(name).iconName;
+}
+
+QString QMimeXMLProvider::genericIcon(const QString &name)
+{
+ return m_nameMimeTypeMap.value(name).genericIconName;
+}
+
void QMimeXMLProvider::load(const QString &fileName)
{
QString errorMessage;
@@ -758,7 +788,7 @@ bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage)
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (errorMessage)
- *errorMessage = QLatin1String("Cannot open ") + fileName + QLatin1String(": ") + file.errorString();
+ *errorMessage = "Cannot open "_L1 + fileName + ": "_L1 + file.errorString();
return false;
}
@@ -787,10 +817,9 @@ void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern &glob)
m_mimeTypeGlobs.addGlob(glob);
}
-void QMimeXMLProvider::addMimeType(const QMimeType &mt)
+void QMimeXMLProvider::addMimeType(const QMimeTypeXMLData &mt)
{
- Q_ASSERT(!mt.d.data()->fromCache);
- m_nameMimeTypeMap.insert(mt.name(), mt);
+ m_nameMimeTypeMap.insert(mt.name, mt);
}
void QMimeXMLProvider::addParents(const QString &mime, QStringList &result)
@@ -809,13 +838,10 @@ void QMimeXMLProvider::addParent(const QString &child, const QString &parent)
void QMimeXMLProvider::addAliases(const QString &name, QStringList &result)
{
// Iterate through the whole hash. This method is rarely used.
- for (auto it = m_aliases.constBegin(), end = m_aliases.constEnd() ; it != end ; ++it) {
- if (it.value() == name) {
- if (!result.contains(it.key()))
- result.append(it.key());
- }
+ for (const auto &[alias, mimeName] : std::as_const(m_aliases).asKeyValueRange()) {
+ if (mimeName == name)
+ appendIfNew(result, alias);
}
-
}
QString QMimeXMLProvider::resolveAlias(const QString &name)
@@ -831,13 +857,16 @@ void QMimeXMLProvider::addAlias(const QString &alias, const QString &name)
void QMimeXMLProvider::addAllMimeTypes(QList<QMimeType> &result)
{
if (result.isEmpty()) { // fast path
- result = m_nameMimeTypeMap.values();
+ for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd();
+ it != end; ++it) {
+ result.append(QMimeType(QMimeTypePrivate(it.value().name)));
+ }
} else {
for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
const QString newMime = it.key();
if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const QMimeType &mime) -> bool { return mime.name() == newMime; })
== result.constEnd())
- result.append(it.value());
+ result.append(QMimeType(QMimeTypePrivate(it.value().name)));
}
}
}
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index 9c91903684..3ded01cd46 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMEPROVIDER_P_H
#define QMIMEPROVIDER_P_H
@@ -60,76 +24,116 @@ QT_REQUIRE_CONFIG(mimetype);
#include <QtCore/qdatetime.h>
#include <QtCore/qset.h>
+#include <map>
+
QT_BEGIN_NAMESPACE
class QMimeMagicRuleMatcher;
+class QMimeTypeXMLData;
+class QMimeProviderBase;
+
+struct QMimeMagicResult
+{
+ bool isValid() const { return !candidate.isEmpty(); }
+
+ QString candidate;
+ int accuracy = 0;
+};
class QMimeProviderBase
{
+ Q_DISABLE_COPY(QMimeProviderBase)
+
public:
QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory);
virtual ~QMimeProviderBase() {}
virtual bool isValid() = 0;
- virtual QMimeType mimeTypeForName(const QString &name) = 0;
+ virtual bool isInternalDatabase() const = 0;
+ virtual bool knowsMimeType(const QString &name) = 0;
virtual void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) = 0;
virtual void addParents(const QString &mime, QStringList &result) = 0;
virtual QString resolveAlias(const QString &name) = 0;
virtual void addAliases(const QString &name, QStringList &result) = 0;
- virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) = 0;
+ virtual void findByMagic(const QByteArray &data, QMimeMagicResult &result) = 0;
virtual void addAllMimeTypes(QList<QMimeType> &result) = 0;
- virtual void loadIcon(QMimeTypePrivate &) {}
- virtual void loadGenericIcon(QMimeTypePrivate &) {}
- virtual void ensureLoaded() {}
+ virtual QMimeTypePrivate::LocaleHash localeComments(const QString &name) = 0;
+ virtual bool hasGlobDeleteAll(const QString &name) = 0;
+ virtual QStringList globPatterns(const QString &name) = 0;
+ virtual QString icon(const QString &name) = 0;
+ virtual QString genericIcon(const QString &name) = 0;
+ virtual void ensureLoaded() { }
QString directory() const { return m_directory; }
+ QMimeProviderBase *overrideProvider() const;
+ void setOverrideProvider(QMimeProviderBase *provider);
+ bool isMimeTypeGlobsExcluded(const QString &name) const;
+
QMimeDatabasePrivate *m_db;
QString m_directory;
+ QMimeProviderBase *m_overrideProvider = nullptr; // more "local" than this one
};
/*
Parses the files 'mime.cache' and 'types' on demand
*/
-class QMimeBinaryProvider : public QMimeProviderBase
+class QMimeBinaryProvider final : public QMimeProviderBase
{
public:
QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory);
virtual ~QMimeBinaryProvider();
bool isValid() override;
- QMimeType mimeTypeForName(const QString &name) override;
+ bool isInternalDatabase() const override;
+ bool knowsMimeType(const QString &name) override;
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
void addParents(const QString &mime, QStringList &result) override;
QString resolveAlias(const QString &name) override;
void addAliases(const QString &name, QStringList &result) override;
- void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
+ void findByMagic(const QByteArray &data, QMimeMagicResult &result) override;
void addAllMimeTypes(QList<QMimeType> &result) override;
- static void loadMimeTypePrivate(QMimeTypePrivate &);
- void loadIcon(QMimeTypePrivate &) override;
- void loadGenericIcon(QMimeTypePrivate &) override;
+ QMimeTypePrivate::LocaleHash localeComments(const QString &name) override;
+ bool hasGlobDeleteAll(const QString &name) override;
+ QStringList globPatterns(const QString &name) override;
+ QString icon(const QString &name) override;
+ QString genericIcon(const QString &name) override;
void ensureLoaded() override;
private:
struct CacheFile;
- void matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, const QString &fileName);
- bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck);
- bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
- QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
+ int matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset,
+ const QString &fileName);
+ bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries,
+ int firstOffset, const QString &fileName, qsizetype charPos,
+ bool caseSensitiveCheck);
+ bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset,
+ const QByteArray &data);
+ QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
void loadMimeTypeList();
bool checkCacheChanged();
- CacheFile *m_cacheFile = nullptr;
+ std::unique_ptr<CacheFile> m_cacheFile;
QStringList m_cacheFileNames;
QSet<QString> m_mimetypeNames;
bool m_mimetypeListLoaded;
+ struct MimeTypeExtra
+ {
+ QHash<QString, QString> localeComments;
+ QStringList globPatterns;
+ bool hasGlobDeleteAll = false;
+ };
+ using MimeTypeExtraMap = std::map<QString, MimeTypeExtra>;
+ MimeTypeExtraMap m_mimetypeExtra;
+
+ MimeTypeExtraMap::const_iterator loadMimeTypeExtra(const QString &mimeName);
};
/*
Parses the raw XML files (slower)
*/
-class QMimeXMLProvider : public QMimeProviderBase
+class QMimeXMLProvider final : public QMimeProviderBase
{
public:
enum InternalDatabaseEnum { InternalDatabase };
@@ -143,19 +147,25 @@ public:
~QMimeXMLProvider();
bool isValid() override;
- QMimeType mimeTypeForName(const QString &name) override;
+ bool isInternalDatabase() const override;
+ bool knowsMimeType(const QString &name) override;
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
void addParents(const QString &mime, QStringList &result) override;
QString resolveAlias(const QString &name) override;
void addAliases(const QString &name, QStringList &result) override;
- void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
+ void findByMagic(const QByteArray &data, QMimeMagicResult &result) override;
void addAllMimeTypes(QList<QMimeType> &result) override;
void ensureLoaded() override;
+ QMimeTypePrivate::LocaleHash localeComments(const QString &name) override;
+ bool hasGlobDeleteAll(const QString &name) override;
+ QStringList globPatterns(const QString &name) override;
+ QString icon(const QString &name) override;
+ QString genericIcon(const QString &name) override;
bool load(const QString &fileName, QString *errorMessage);
// Called by the mimetype xml parser
- void addMimeType(const QMimeType &mt);
+ void addMimeType(const QMimeTypeXMLData &mt);
void addGlobPattern(const QMimeGlobPattern &glob);
void addParent(const QString &child, const QString &parent);
void addAlias(const QString &alias, const QString &name);
@@ -165,7 +175,7 @@ private:
void load(const QString &fileName);
void load(const char *data, qsizetype len);
- typedef QHash<QString, QMimeType> NameMimeTypeMap;
+ typedef QHash<QString, QMimeTypeXMLData> NameMimeTypeMap;
NameMimeTypeMap m_nameMimeTypeMap;
typedef QHash<QString, QString> AliasHash;
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 3c10360561..e26c8b898d 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -1,50 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmimetype.h"
#include "qmimetype_p.h"
#include "qmimedatabase_p.h"
-#include "qmimeprovider_p.h"
-
-#include "qmimeglobpattern_p.h"
#include <QtCore/QDebug>
#include <QtCore/QLocale>
@@ -54,32 +15,7 @@
QT_BEGIN_NAMESPACE
-QMimeTypePrivate::QMimeTypePrivate()
- : loaded(false), fromCache(false)
-{}
-
-QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other)
- : loaded(other.d->loaded),
- name(other.d->name),
- localeComments(other.d->localeComments),
- genericIconName(other.d->genericIconName),
- iconName(other.d->iconName),
- globPatterns(other.d->globPatterns)
-{}
-
-void QMimeTypePrivate::clear()
-{
- name.clear();
- localeComments.clear();
- genericIconName.clear();
- iconName.clear();
- globPatterns.clear();
-}
-
-void QMimeTypePrivate::addGlobPattern(const QString &pattern)
-{
- globPatterns.append(pattern);
-}
+using namespace Qt::StringLiterals;
/*!
\class QMimeType
@@ -88,6 +24,7 @@ void QMimeTypePrivate::addGlobPattern(const QString &pattern)
\brief The QMimeType class describes types of file or data, represented by a MIME type string.
\since 5.0
+ \compares equality
For instance a file named "readme.txt" has the MIME type "text/plain".
The MIME type can be determined from the file name, or from the file
@@ -104,7 +41,7 @@ void QMimeTypePrivate::addGlobPattern(const QString &pattern)
MIME types can inherit from each other: for instance a C source file is
a specific type of plain text file, so text/x-csrc inherits text/plain.
- \sa QMimeDatabase, {MIME Type Browser Example}
+ \sa QMimeDatabase, {MIME Type Browser}
*/
/*!
@@ -175,14 +112,15 @@ QMimeType::~QMimeType()
}
/*!
- \fn bool QMimeType::operator==(const QMimeType &other) const;
- Returns \c true if \a other equals this QMimeType object, otherwise returns \c false.
+ \fn bool QMimeType::operator==(const QMimeType &lhs, const QMimeType &rhs);
+ Returns \c true if \a lhs equals to the \a rhs QMimeType object, otherwise
+ returns \c false.
The name is the unique identifier for a mimetype, so two mimetypes with
the same name, are equal.
*/
-bool QMimeType::operator==(const QMimeType &other) const
+bool comparesEqual(const QMimeType &lhs, const QMimeType &rhs) noexcept
{
- return d == other.d || d->name == other.d->name;
+ return lhs.d == rhs.d || lhs.d->name == rhs.d->name;
}
/*!
@@ -198,8 +136,9 @@ size_t qHash(const QMimeType &key, size_t seed) noexcept
}
/*!
- \fn bool QMimeType::operator!=(const QMimeType &other) const;
- Returns \c true if \a other does not equal this QMimeType object, otherwise returns \c false.
+ \fn bool QMimeType::operator!=(const QMimeType &lhs, const QMimeType &rhs);
+ Returns \c true if QMimeType \a lhs is not equal to QMimeType \a rhs,
+ otherwise returns \c false.
*/
/*!
@@ -253,24 +192,38 @@ QString QMimeType::name() const
*/
QString QMimeType::comment() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
-
- QStringList languageList;
- languageList << QLocale().name();
- languageList << QLocale().uiLanguages();
- languageList << QLatin1String("default"); // use the default locale if possible.
- for (const QString &language : qAsConst(languageList)) {
- const QString lang = language == QLatin1String("C") ? QLatin1String("en_US") : language;
- const QString comm = d->localeComments.value(lang);
+ const auto localeComments = QMimeDatabasePrivate::instance()->localeComments(d->name);
+
+ QStringList languageList = QLocale().uiLanguages(QLocale::TagSeparator::Underscore);
+ qsizetype defaultIndex = languageList.indexOf(u"en_US"_s);
+
+ // Include the default locale as fall-back.
+ if (defaultIndex >= 0) {
+ // en_US is generally the default, and may be omitted from the
+ // overtly-named locales in the MIME type's data (QTBUG-105007).
+ ++defaultIndex; // Skip over en_US.
+ // That's typically followed by en_Latn_US and en (in that order):
+ if (defaultIndex < languageList.size() && languageList.at(defaultIndex) == u"en_Latn_US")
+ ++defaultIndex;
+ if (defaultIndex < languageList.size() && languageList.at(defaultIndex) == u"en")
+ ++defaultIndex;
+ } else {
+ // Absent en-US, just append it:
+ defaultIndex = languageList.size();
+ }
+ languageList.insert(defaultIndex, u"default"_s);
+
+ for (const QString &language : std::as_const(languageList)) {
+ const QString lang = language == "C"_L1 ? u"en_US"_s : language;
+ QString comm = localeComments.value(lang);
if (!comm.isEmpty())
return comm;
- const int pos = lang.indexOf(QLatin1Char('_'));
- if (pos != -1) {
- // "pt_BR" not found? try just "pt"
- const QString shortLang = lang.left(pos);
- const QString commShort = d->localeComments.value(shortLang);
- if (!commShort.isEmpty())
- return commShort;
+ const qsizetype cut = lang.indexOf(u'_');
+ // If "de_CH" is missing, check for "de" (and similar):
+ if (cut != -1) {
+ comm = localeComments.value(lang.left(cut));
+ if (!comm.isEmpty())
+ return comm;
}
}
@@ -294,8 +247,8 @@ QString QMimeType::comment() const
*/
QString QMimeType::genericIconName() const
{
- QMimeDatabasePrivate::instance()->loadGenericIcon(const_cast<QMimeTypePrivate&>(*d));
- if (d->genericIconName.isEmpty()) {
+ QString genericIconName = QMimeDatabasePrivate::instance()->genericIcon(d->name);
+ if (genericIconName.isEmpty()) {
// From the spec:
// If the generic icon name is empty (not specified by the mimetype definition)
// then the mimetype is used to generate the generic icon by using the top-level
@@ -303,19 +256,19 @@ QString QMimeType::genericIconName() const
// (i.e. "video-x-generic" in the previous example).
const QString group = name();
QStringView groupRef(group);
- const int slashindex = groupRef.indexOf(QLatin1Char('/'));
+ const qsizetype slashindex = groupRef.indexOf(u'/');
if (slashindex != -1)
groupRef = groupRef.left(slashindex);
- return groupRef + QLatin1String("-x-generic");
+ return groupRef + "-x-generic"_L1;
}
- return d->genericIconName;
+ return genericIconName;
}
static QString make_default_icon_name_from_mimetype_name(QString iconName)
{
- const int slashindex = iconName.indexOf(QLatin1Char('/'));
+ const qsizetype slashindex = iconName.indexOf(u'/');
if (slashindex != -1)
- iconName[slashindex] = QLatin1Char('-');
+ iconName[slashindex] = u'-';
return iconName;
}
@@ -330,11 +283,11 @@ static QString make_default_icon_name_from_mimetype_name(QString iconName)
*/
QString QMimeType::iconName() const
{
- QMimeDatabasePrivate::instance()->loadIcon(const_cast<QMimeTypePrivate&>(*d));
- if (d->iconName.isEmpty()) {
+ QString iconName = QMimeDatabasePrivate::instance()->icon(d->name);
+ if (iconName.isEmpty()) {
return make_default_icon_name_from_mimetype_name(name());
}
- return d->iconName;
+ return iconName;
}
/*!
@@ -346,8 +299,7 @@ QString QMimeType::iconName() const
*/
QStringList QMimeType::globPatterns() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
- return d->globPatterns;
+ return QMimeDatabasePrivate::instance()->globPatterns(d->name);
}
/*!
@@ -376,14 +328,17 @@ QStringList QMimeType::parentMimeTypes() const
static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
{
const QStringList parents = QMimeDatabasePrivate::instance()->mimeParents(mime);
+ QStringList newParents;
for (const QString &parent : parents) {
// I would use QSet, but since order matters I better not
- if (!allParents.contains(parent))
+ if (!allParents.contains(parent)) {
allParents.append(parent);
+ newParents.append(parent);
+ }
}
// We want a breadth-first search, so that the least-specific parent (octet-stream) is last
// This means iterating twice, unfortunately.
- for (const QString &parent : parents)
+ for (const QString &parent : newParents)
collectParentMimeTypes(parent, allParents);
}
@@ -441,14 +396,15 @@ QStringList QMimeType::aliases() const
*/
QStringList QMimeType::suffixes() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
+ const QStringList patterns = globPatterns();
QStringList result;
- for (const QString &pattern : qAsConst(d->globPatterns)) {
+ result.reserve(patterns.size());
+ for (const QString &pattern : patterns) {
// Not a simple suffix if it looks like: README or *. or *.* or *.JP*G or *.JP?
- if (pattern.startsWith(QLatin1String("*.")) &&
- pattern.length() > 2 &&
- pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
+ if (pattern.startsWith("*."_L1) &&
+ pattern.size() > 2 &&
+ pattern.indexOf(u'*', 2) < 0 && pattern.indexOf(u'?', 2) < 0) {
const QString suffix = pattern.mid(2);
result.append(suffix);
}
@@ -484,17 +440,11 @@ QString QMimeType::preferredSuffix() const
*/
QString QMimeType::filterString() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
+ const QStringList patterns = globPatterns();
QString filter;
- if (!d->globPatterns.empty()) {
- filter += comment() + QLatin1String(" (");
- for (int i = 0; i < d->globPatterns.size(); ++i) {
- if (i != 0)
- filter += QLatin1Char(' ');
- filter += d->globPatterns.at(i);
- }
- filter += QLatin1Char(')');
+ if (!patterns.isEmpty()) {
+ filter = comment() + " ("_L1 + patterns.join(u' ') + u')';
}
return filter;
@@ -529,3 +479,5 @@ QDebug operator<<(QDebug debug, const QMimeType &mime)
#endif
QT_END_NAMESPACE
+
+#include "moc_qmimetype.cpp"
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index 5aabbb449e..508a5cfb53 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMETYPE_H
#define QMIMETYPE_H
@@ -78,21 +42,21 @@ public:
QMimeType();
QMimeType(const QMimeType &other);
QMimeType &operator=(const QMimeType &other);
- QMimeType &operator=(QMimeType &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QMimeType)
void swap(QMimeType &other) noexcept
{
- qSwap(d, other.d);
+ d.swap(other.d);
}
explicit QMimeType(const QMimeTypePrivate &dd);
~QMimeType();
-
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QMimeType &other) const;
inline bool operator!=(const QMimeType &other) const
{
return !operator==(other);
}
-
+#endif
bool isValid() const;
bool isDefault() const;
@@ -122,6 +86,10 @@ protected:
friend Q_CORE_EXPORT size_t qHash(const QMimeType &key, size_t seed) noexcept;
QExplicitlySharedDataPointer<QMimeTypePrivate> d;
+
+private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QMimeType &lhs, const QMimeType &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QMimeType)
};
Q_DECLARE_SHARED(QMimeType)
diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h
index 0d6b4b4b12..b6040098a9 100644
--- a/src/corelib/mimetypes/qmimetype_p.h
+++ b/src/corelib/mimetypes/qmimetype_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMETYPE_P_H
#define QMIMETYPE_P_H
@@ -52,13 +16,14 @@
//
#include <QtCore/private/qglobal_p.h>
-#include "qmimetype.h"
+#include <QtCore/qshareddata.h>
QT_REQUIRE_CONFIG(mimetype);
#include <QtCore/qhash.h>
#include <QtCore/qstringlist.h>
+class QMimeBinaryProvider;
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QMimeTypePrivate : public QSharedData
@@ -66,41 +31,12 @@ class Q_AUTOTEST_EXPORT QMimeTypePrivate : public QSharedData
public:
typedef QHash<QString, QString> LocaleHash;
- QMimeTypePrivate();
- explicit QMimeTypePrivate(const QMimeType &other);
+ QMimeTypePrivate() { }
+ explicit QMimeTypePrivate(const QString &name) : name(name) { }
- void clear();
-
- void addGlobPattern(const QString &pattern);
-
- bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first
- bool fromCache; // true if this comes from the binary provider
QString name;
- LocaleHash localeComments;
- QString genericIconName;
- QString iconName;
- QStringList globPatterns;
};
QT_END_NAMESPACE
-#define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \
- QT_BEGIN_NAMESPACE \
- static QMimeType buildQMimeType ( \
- QString &&name, \
- QString &&genericIconName, \
- QString &&iconName, \
- QStringList &&globPatterns \
- ) \
- { \
- QMimeTypePrivate qMimeTypeData; \
- qMimeTypeData.loaded = true; \
- qMimeTypeData.name = std::move(name); \
- qMimeTypeData.genericIconName = std::move(genericIconName); \
- qMimeTypeData.iconName = std::move(iconName); \
- qMimeTypeData.globPatterns = std::move(globPatterns); \
- return QMimeType(qMimeTypeData); \
- } \
- QT_END_NAMESPACE
-
-#endif // QMIMETYPE_P_H
+#endif // QMIMETYPE_P_H
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index dc1c444c56..3f1e53b25d 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define QT_NO_CAST_FROM_ASCII
@@ -53,6 +17,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// XML tags in MIME files
static const char mimeInfoTagC[] = "mime-info";
static const char mimeTypeTagC[] = "mime-type";
@@ -63,6 +29,7 @@ static const char genericIconTagC[] = "generic-icon";
static const char iconTagC[] = "icon";
static const char nameAttributeC[] = "name";
static const char globTagC[] = "glob";
+static const char globDeleteAllTagC[] = "glob-deleteall";
static const char aliasTagC[] = "alias";
static const char patternAttributeC[] = "pattern";
static const char weightAttributeC[] = "weight";
@@ -107,47 +74,50 @@ static const char matchMaskAttributeC[] = "mask";
Overwrite to process the sequence of parsed data
*/
-QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState currentState, const QStringRef &startElement)
+QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState currentState, QStringView startElement)
{
switch (currentState) {
case ParseBeginning:
- if (startElement == QLatin1String(mimeInfoTagC))
+ if (startElement == QLatin1StringView(mimeInfoTagC))
return ParseMimeInfo;
- if (startElement == QLatin1String(mimeTypeTagC))
+ if (startElement == QLatin1StringView(mimeTypeTagC))
return ParseMimeType;
return ParseError;
case ParseMimeInfo:
- return startElement == QLatin1String(mimeTypeTagC) ? ParseMimeType : ParseError;
+ return startElement == QLatin1StringView(mimeTypeTagC) ? ParseMimeType : ParseError;
case ParseMimeType:
case ParseComment:
case ParseGenericIcon:
case ParseIcon:
case ParseGlobPattern:
+ case ParseGlobDeleteAll:
case ParseSubClass:
case ParseAlias:
case ParseOtherMimeTypeSubTag:
case ParseMagicMatchRule:
- if (startElement == QLatin1String(mimeTypeTagC)) // Sequence of <mime-type>
+ if (startElement == QLatin1StringView(mimeTypeTagC)) // Sequence of <mime-type>
return ParseMimeType;
- if (startElement == QLatin1String(commentTagC ))
+ if (startElement == QLatin1StringView(commentTagC))
return ParseComment;
- if (startElement == QLatin1String(genericIconTagC))
+ if (startElement == QLatin1StringView(genericIconTagC))
return ParseGenericIcon;
- if (startElement == QLatin1String(iconTagC))
+ if (startElement == QLatin1StringView(iconTagC))
return ParseIcon;
- if (startElement == QLatin1String(globTagC))
+ if (startElement == QLatin1StringView(globTagC))
return ParseGlobPattern;
- if (startElement == QLatin1String(subClassTagC))
+ if (startElement == QLatin1StringView(globDeleteAllTagC))
+ return ParseGlobDeleteAll;
+ if (startElement == QLatin1StringView(subClassTagC))
return ParseSubClass;
- if (startElement == QLatin1String(aliasTagC))
+ if (startElement == QLatin1StringView(aliasTagC))
return ParseAlias;
- if (startElement == QLatin1String(magicTagC))
+ if (startElement == QLatin1StringView(magicTagC))
return ParseMagic;
- if (startElement == QLatin1String(matchTagC))
+ if (startElement == QLatin1StringView(matchTagC))
return ParseMagicMatchRule;
return ParseOtherMimeTypeSubTag;
case ParseMagic:
- if (startElement == QLatin1String(matchTagC))
+ if (startElement == QLatin1StringView(matchTagC))
return ParseMagicMatchRule;
break;
case ParseError:
@@ -163,18 +133,19 @@ bool QMimeTypeParserBase::parseNumber(QStringView n, int *target, QString *error
*target = n.toInt(&ok);
if (Q_UNLIKELY(!ok)) {
if (errorMessage)
- *errorMessage = QLatin1String("Not a number '") + n + QLatin1String("'.");
+ *errorMessage = "Not a number '"_L1 + n + "'."_L1;
return false;
}
return true;
}
-#ifndef QT_NO_XMLSTREAMREADER
-struct CreateMagicMatchRuleResult {
+#if QT_CONFIG(xmlstreamreader)
+struct CreateMagicMatchRuleResult
+{
QString errorMessage; // must be first
QMimeMagicRule rule;
- CreateMagicMatchRuleResult(const QStringRef &type, const QStringRef &value, const QStringRef &offsets, const QStringRef &mask)
+ CreateMagicMatchRuleResult(QStringView type, QStringView value, QStringView offsets, QStringView mask)
: errorMessage(), rule(type.toString(), value.toUtf8(), offsets.toString(), mask.toLatin1(), &errorMessage)
{
@@ -183,24 +154,18 @@ struct CreateMagicMatchRuleResult {
static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttributes &atts)
{
- const QStringRef type = atts.value(QLatin1String(matchTypeAttributeC));
- const QStringRef value = atts.value(QLatin1String(matchValueAttributeC));
- const QStringRef offsets = atts.value(QLatin1String(matchOffsetAttributeC));
- const QStringRef mask = atts.value(QLatin1String(matchMaskAttributeC));
+ const auto type = atts.value(QLatin1StringView(matchTypeAttributeC));
+ const auto value = atts.value(QLatin1StringView(matchValueAttributeC));
+ const auto offsets = atts.value(QLatin1StringView(matchOffsetAttributeC));
+ const auto mask = atts.value(QLatin1StringView(matchMaskAttributeC));
return CreateMagicMatchRuleResult(type, value, offsets, mask);
}
-#endif
+#endif // feature xmlstreamreader
bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
{
-#ifdef QT_NO_XMLSTREAMREADER
- Q_UNUSED(dev);
- if (errorMessage)
- *errorMessage = QString::fromLatin1("QXmlStreamReader is not available, cannot parse '%1'.").arg(fileName);
- return false;
-#else
- QMimeTypePrivate data;
- data.loaded = true;
+#if QT_CONFIG(xmlstreamreader)
+ QMimeTypeXMLData data;
int priority = 50;
QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules
QList<QMimeMagicRule> rules; // toplevel rules
@@ -213,7 +178,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
const QXmlStreamAttributes atts = reader.attributes();
switch (ps) {
case ParseMimeType: { // start parsing a MIME type name
- const QString name = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+ const QString name = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();
if (name.isEmpty()) {
reader.raiseError(QStringLiteral("Missing 'type'-attribute"));
} else {
@@ -222,15 +187,15 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
}
break;
case ParseGenericIcon:
- data.genericIconName = atts.value(QLatin1String(nameAttributeC)).toString();
+ data.genericIconName = atts.value(QLatin1StringView(nameAttributeC)).toString();
break;
case ParseIcon:
- data.iconName = atts.value(QLatin1String(nameAttributeC)).toString();
+ data.iconName = atts.value(QLatin1StringView(nameAttributeC)).toString();
break;
case ParseGlobPattern: {
- const QString pattern = atts.value(QLatin1String(patternAttributeC)).toString();
- unsigned weight = atts.value(QLatin1String(weightAttributeC)).toInt();
- const bool caseSensitive = atts.value(QLatin1String(caseSensitiveAttributeC)) == QLatin1String("true");
+ const QString pattern = atts.value(QLatin1StringView(patternAttributeC)).toString();
+ unsigned weight = atts.value(QLatin1StringView(weightAttributeC)).toInt();
+ const bool caseSensitive = atts.value(QLatin1StringView(caseSensitiveAttributeC)) == "true"_L1;
if (weight == 0)
weight = QMimeGlobPattern::DefaultWeight;
@@ -242,15 +207,19 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
data.addGlobPattern(pattern); // just for QMimeType::globPatterns()
}
break;
+ case ParseGlobDeleteAll:
+ data.globPatterns.clear();
+ data.hasGlobDeleteAll = true;
+ break;
case ParseSubClass: {
- const QString inheritsFrom = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+ const QString inheritsFrom = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();
if (!inheritsFrom.isEmpty())
processParent(data.name, inheritsFrom);
}
break;
case ParseComment: {
// comments have locale attributes.
- QString locale = atts.value(QLatin1String(localeAttributeC)).toString();
+ QString locale = atts.value(QLatin1StringView(localeAttributeC)).toString();
const QString comment = reader.readElementText();
if (locale.isEmpty())
locale = QString::fromLatin1("default");
@@ -258,14 +227,14 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
}
break;
case ParseAlias: {
- const QString alias = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+ const QString alias = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();
if (!alias.isEmpty())
processAlias(alias, data.name);
}
break;
case ParseMagic: {
priority = 50;
- const QStringRef priorityS = atts.value(QLatin1String(priorityAttributeC));
+ const auto priorityS = atts.value(QLatin1StringView(priorityAttributeC));
if (!priorityS.isEmpty()) {
if (!parseNumber(priorityS, &priority, errorMessage))
return false;
@@ -291,7 +260,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
break;
}
case ParseError:
- reader.raiseError(QLatin1String("Unexpected element <") + reader.name() + QLatin1Char('>'));
+ reader.raiseError("Unexpected element <"_L1 + reader.name() + u'>');
break;
default:
break;
@@ -301,16 +270,16 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
// continue switch QXmlStreamReader::Token...
case QXmlStreamReader::EndElement: // Finished element
{
- const QStringRef elementName = reader.name();
- if (elementName == QLatin1String(mimeTypeTagC)) {
- if (!process(QMimeType(data), errorMessage))
+ const auto elementName = reader.name();
+ if (elementName == QLatin1StringView(mimeTypeTagC)) {
+ if (!process(data, errorMessage))
return false;
data.clear();
- } else if (elementName == QLatin1String(matchTagC)) {
+ } else if (elementName == QLatin1StringView(matchTagC)) {
// Closing a <match> tag, pop stack
currentRules.pop();
//qDebug() << " MATCH closed. Stack size is now" << currentRules.size();
- } else if (elementName == QLatin1String(magicTagC)) {
+ } else if (elementName == QLatin1StringView(magicTagC)) {
//qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority;
// Finished a <magic> sequence
QMimeMagicRuleMatcher ruleMatcher(data.name, priority);
@@ -336,7 +305,27 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
}
return true;
-#endif //QT_NO_XMLSTREAMREADER
+#else
+ Q_UNUSED(dev);
+ if (errorMessage)
+ *errorMessage = "QXmlStreamReader is not available, cannot parse '%1'."_L1.arg(fileName);
+ return false;
+#endif // feature xmlstreamreader
+}
+
+void QMimeTypeXMLData::clear()
+{
+ hasGlobDeleteAll = false;
+ name.clear();
+ localeComments.clear();
+ genericIconName.clear();
+ iconName.clear();
+ globPatterns.clear();
+}
+
+void QMimeTypeXMLData::addGlobPattern(const QString &pattern)
+{
+ globPatterns.append(pattern);
}
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimetypeparser_p.h b/src/corelib/mimetypes/qmimetypeparser_p.h
index dbd3415d77..d4266ffcc0 100644
--- a/src/corelib/mimetypes/qmimetypeparser_p.h
+++ b/src/corelib/mimetypes/qmimetypeparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMIMETYPEPARSER_P_H
@@ -52,7 +16,7 @@
// We mean it.
//
-#include "qmimedatabase_p.h"
+#include <QtCore/qtconfigmacros.h>
QT_REQUIRE_CONFIG(mimetype);
@@ -60,6 +24,21 @@ QT_REQUIRE_CONFIG(mimetype);
QT_BEGIN_NAMESPACE
+class QMimeTypeXMLData
+{
+public:
+ void clear();
+
+ void addGlobPattern(const QString &pattern);
+
+ bool hasGlobDeleteAll = false; // true if the mimetype has a glob-deleteall tag
+ QString name;
+ QMimeTypePrivate::LocaleHash localeComments;
+ QString genericIconName; // TODO move to a struct that's specific to the XML provider
+ QString iconName; // TODO move to a struct that's specific to the XML provider
+ QStringList globPatterns;
+};
+
class QIODevice;
class QMimeTypeParserBase
@@ -75,7 +54,7 @@ public:
static bool parseNumber(QStringView n, int *target, QString *errorMessage);
protected:
- virtual bool process(const QMimeType &t, QString *errorMessage) = 0;
+ virtual bool process(const QMimeTypeXMLData &t, QString *errorMessage) = 0;
virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;
virtual void processParent(const QString &child, const QString &parent) = 0;
virtual void processAlias(const QString &alias, const QString &name) = 0;
@@ -90,6 +69,7 @@ private:
ParseGenericIcon,
ParseIcon,
ParseGlobPattern,
+ ParseGlobDeleteAll,
ParseSubClass,
ParseAlias,
ParseMagic,
@@ -98,7 +78,7 @@ private:
ParseError
};
- static ParseState nextState(ParseState currentState, const QStringRef &startElement);
+ static ParseState nextState(ParseState currentState, QStringView startElement);
};
@@ -108,7 +88,7 @@ public:
explicit QMimeTypeParser(QMimeXMLProvider &provider) : m_provider(provider) {}
protected:
- inline bool process(const QMimeType &t, QString *) override
+ inline bool process(const QMimeTypeXMLData &t, QString *) override
{ m_provider.addMimeType(t); return true; }
inline bool process(const QMimeGlobPattern &glob, QString *) override
diff --git a/src/corelib/platform/android/qandroidextras.cpp b/src/corelib/platform/android/qandroidextras.cpp
new file mode 100644
index 0000000000..aa0c3fd093
--- /dev/null
+++ b/src/corelib/platform/android/qandroidextras.cpp
@@ -0,0 +1,1228 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qandroidextras_p.h"
+
+#include <QtCore/qbuffer.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qjnienvironment.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qset.h>
+
+#if QT_CONFIG(future)
+#include <QtCore/qpromise.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidParcelPrivate
+{
+public:
+ QAndroidParcelPrivate();
+ explicit QAndroidParcelPrivate(const QJniObject& parcel);
+
+ void writeData(const QByteArray &data) const;
+ void writeBinder(const QAndroidBinder &binder) const;
+ void writeFileDescriptor(int fd) const;
+
+ QByteArray readData() const;
+ int readFileDescriptor() const;
+ QAndroidBinder readBinder() const;
+
+private:
+ friend class QAndroidBinder;
+ friend class QAndroidParcel;
+ QJniObject handle;
+};
+
+struct FileDescriptor
+{
+ explicit FileDescriptor(int fd = -1)
+ : handle("java/io/FileDescriptor")
+ {
+ QJniEnvironment().checkAndClearExceptions();
+ handle.setField("descriptor", fd);
+ }
+
+ QJniObject handle;
+};
+
+QAndroidParcelPrivate::QAndroidParcelPrivate()
+ : handle(QJniObject::callStaticObjectMethod("android/os/Parcel","obtain",
+ "()Landroid/os/Parcel;").object())
+{}
+
+QAndroidParcelPrivate::QAndroidParcelPrivate(const QJniObject &parcel)
+ : handle(parcel)
+{}
+
+void QAndroidParcelPrivate::writeData(const QByteArray &data) const
+{
+ if (data.isEmpty())
+ return;
+
+ QJniEnvironment().checkAndClearExceptions();
+ QJniEnvironment env;
+ jbyteArray array = env->NewByteArray(data.size());
+ env->SetByteArrayRegion(array, 0, data.length(),
+ reinterpret_cast<const jbyte*>(data.constData()));
+ handle.callMethod<void>("writeByteArray", "([B)V", array);
+ env->DeleteLocalRef(array);
+}
+
+void QAndroidParcelPrivate::writeBinder(const QAndroidBinder &binder) const
+{
+ QJniEnvironment().checkAndClearExceptions();
+ handle.callMethod<void>("writeStrongBinder", "(Landroid/os/IBinder;)V",
+ binder.handle().object());
+}
+
+void QAndroidParcelPrivate::writeFileDescriptor(int fd) const
+{
+ QJniEnvironment().checkAndClearExceptions();
+ handle.callMethod<void>("writeFileDescriptor", "(Ljava/io/FileDescriptor;)V",
+ FileDescriptor(fd).handle.object());
+}
+
+QByteArray QAndroidParcelPrivate::readData() const
+{
+ QJniEnvironment().checkAndClearExceptions();
+ auto array = handle.callObjectMethod("createByteArray", "()[B");
+ QJniEnvironment env;
+ auto sz = env->GetArrayLength(jbyteArray(array.object()));
+ QByteArray res(sz, Qt::Initialization::Uninitialized);
+ env->GetByteArrayRegion(jbyteArray(array.object()), 0, sz,
+ reinterpret_cast<jbyte *>(res.data()));
+ return res;
+}
+
+int QAndroidParcelPrivate::readFileDescriptor() const
+{
+ QJniEnvironment().checkAndClearExceptions();
+ auto parcelFD = handle.callObjectMethod("readFileDescriptor",
+ "()Landroid/os/ParcelFileDescriptor;");
+ if (parcelFD.isValid())
+ return parcelFD.callMethod<jint>("getFd", "()I");
+ return -1;
+}
+
+QAndroidBinder QAndroidParcelPrivate::readBinder() const
+{
+ QJniEnvironment().checkAndClearExceptions();
+ auto strongBinder = handle.callObjectMethod("readStrongBinder", "()Landroid/os/IBinder;");
+ return QAndroidBinder(strongBinder.object());
+}
+
+/*!
+ \class QAndroidParcel
+ \inheaderfile QtCore/private/qandroidextras_p.h
+ \preliminary
+ \inmodule QtCorePrivate
+ \brief Wraps the most important methods of Android Parcel class.
+
+ The QAndroidParcel is a convenience class that wraps the most important
+ \l {https://developer.android.com/reference/android/os/Parcel.html}{Android Parcel}
+ methods.
+
+ \include qtcore.qdoc qtcoreprivate-usage
+
+ \since 6.2
+*/
+
+/*!
+ Creates a new object.
+ */
+QAndroidParcel::QAndroidParcel()
+ : d(new QAndroidParcelPrivate())
+{
+}
+
+/*!
+ Wraps the \a parcel object.
+ */
+QAndroidParcel::QAndroidParcel(const QJniObject& parcel)
+ : d(new QAndroidParcelPrivate(parcel))
+{
+
+}
+
+QAndroidParcel::~QAndroidParcel()
+{
+}
+
+/*!
+ Writes the provided \a data as a byte array
+ */
+void QAndroidParcel::writeData(const QByteArray &data) const
+{
+ d->writeData(data);
+}
+
+/*!
+ Writes the provided \a value. The value is converted into a
+ QByteArray before is written.
+ */
+void QAndroidParcel::writeVariant(const QVariant &value) const
+{
+ QByteArray buff;
+ QDataStream stream(&buff, QIODevice::WriteOnly);
+ stream << value;
+ d->writeData(buff);
+}
+
+/*!
+ Writes a \a binder object. This is useful for a client to
+ send to a server a binder which can be used by the server callback the client.
+ */
+void QAndroidParcel::writeBinder(const QAndroidBinder &binder) const
+{
+ d->writeBinder(binder);
+}
+
+/*!
+ Writes the provided \a fd.
+ */
+void QAndroidParcel::writeFileDescriptor(int fd) const
+{
+ d->writeFileDescriptor(fd);
+}
+
+/*!
+ Returns the data as a QByteArray
+ */
+QByteArray QAndroidParcel::readData() const
+{
+ return d->readData();
+}
+
+/*!
+ Returns the data as a QVariant
+ */
+QVariant QAndroidParcel::readVariant() const
+{
+ QDataStream stream(d->readData());
+ QVariant res;
+ stream >> res;
+ return res;
+}
+
+/*!
+ Returns the binder as a QAndroidBinder
+ */
+QAndroidBinder QAndroidParcel::readBinder() const
+{
+ return d->readBinder();
+}
+
+/*!
+ Returns the file descriptor
+ */
+int QAndroidParcel::readFileDescriptor() const
+{
+ return d->readFileDescriptor();
+}
+
+/*!
+ The return value is useful to call other Java API which are not covered by this wrapper
+ */
+QJniObject QAndroidParcel::handle() const
+{
+ return d->handle;
+}
+
+
+
+/*!
+ \class QAndroidBinder
+ \inheaderfile QtCore/private/qandroidextras_p.h
+ \preliminary
+ \inmodule QtCorePrivate
+ \brief Wraps the most important methods of Android Binder class.
+
+ The QAndroidBinder is a convenience class that wraps the most important
+ \l {https://developer.android.com/reference/android/os/Binder.html}{Android Binder}
+ methods.
+
+ \include qtcore.qdoc qtcoreprivate-usage
+
+ \since 6.2
+*/
+
+
+/*!
+ \enum QAndroidBinder::CallType
+
+ This enum is used with \l QAndroidBinder::transact() to describe the mode in which the
+ IPC call is performed.
+
+ \value Normal normal IPC, meaning that the caller waits the result from the callee
+ \value OneWay one-way IPC, meaning that the caller returns immediately, without waiting
+ for a result from the callee
+*/
+
+
+class QAndroidBinderPrivate
+{
+public:
+ explicit QAndroidBinderPrivate(QAndroidBinder *binder)
+ : handle("org/qtproject/qt/android/extras/QtAndroidBinder", "(J)V", jlong(binder))
+ , m_isQtAndroidBinder(true)
+ {
+ QJniEnvironment().checkAndClearExceptions();
+ }
+
+ explicit QAndroidBinderPrivate(const QJniObject &binder)
+ : handle(binder), m_isQtAndroidBinder(false) {};
+ void setDeleteListener(const std::function<void()> &func) { m_deleteListener = func; }
+ ~QAndroidBinderPrivate()
+ {
+ if (m_isQtAndroidBinder) {
+ QJniEnvironment().checkAndClearExceptions();
+ handle.callMethod<void>("setId", "(J)V", jlong(0));
+ if (m_deleteListener)
+ m_deleteListener();
+ }
+ }
+
+private:
+ QJniObject handle;
+ std::function<void()> m_deleteListener;
+ bool m_isQtAndroidBinder;
+ friend class QAndroidBinder;
+};
+
+/*!
+ Creates a new object which can be used to perform IPC.
+
+ \sa onTransact, transact
+ */
+QAndroidBinder::QAndroidBinder()
+ : d(new QAndroidBinderPrivate(this))
+{
+}
+
+/*!
+ Creates a new object from the \a binder Java object.
+
+ \sa transact
+ */
+QAndroidBinder::QAndroidBinder(const QJniObject &binder)
+ : d(new QAndroidBinderPrivate(binder))
+{
+}
+
+QAndroidBinder::~QAndroidBinder()
+{
+}
+
+/*!
+ Default implementation is a stub that returns false.
+ The user should override this method to get the transact data from the caller.
+
+ The \a code is the action to perform.
+ The \a data is the marshaled data sent by the caller.\br
+ The \a reply is the marshaled data to be sent to the caller.\br
+ The \a flags are the additional operation flags.\br
+
+ \warning This method is called from Binder's thread which is different
+ from the thread that this object was created.
+
+ \sa transact
+ */
+bool QAndroidBinder::onTransact(int /*code*/, const QAndroidParcel &/*data*/,
+ const QAndroidParcel &/*reply*/, CallType /*flags*/)
+{
+ return false;
+}
+
+/*!
+ Performs an IPC call
+
+ The \a code is the action to perform. Should be between
+ \l {https://developer.android.com/reference/android/os/IBinder.html#FIRST_CALL_TRANSACTION}
+ {FIRST_CALL_TRANSACTION} and
+ \l {https://developer.android.com/reference/android/os/IBinder.html#LAST_CALL_TRANSACTION}
+ {LAST_CALL_TRANSACTION}.\br
+ The \a data is the marshaled data to send to the target.\br
+ The \a reply (if specified) is the marshaled data to be received from the target.
+ May be \b nullptr if you are not interested in the return value.\br
+ The \a flags are the additional operation flags.\br
+
+ \return true on success
+ */
+bool QAndroidBinder::transact(int code, const QAndroidParcel &data,
+ QAndroidParcel *reply, CallType flags) const
+{
+ QJniEnvironment().checkAndClearExceptions();
+ return d->handle.callMethod<jboolean>("transact",
+ "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z",
+ jint(code), data.d->handle.object(),
+ reply ? reply->d->handle.object() : nullptr,
+ jint(flags));
+}
+
+/*!
+ The return value is useful to call other Java API which are not covered by this wrapper
+ */
+QJniObject QAndroidBinder::handle() const
+{
+ return d->handle;
+}
+
+
+
+
+/*!
+ \class QAndroidServiceConnection
+ \inheaderfile QtCore/private/qandroidextras_p.h
+ \preliminary
+ \inmodule QtCorePrivate
+ \brief Wraps the most important methods of Android ServiceConnection class.
+
+ The QAndroidServiceConnection is a convenience abstract class which wraps the
+ \l {https://developer.android.com/reference/android/content/ServiceConnection.html}{AndroidServiceConnection}
+ interface.
+
+ It is useful when you perform a QtAndroidPrivate::bindService operation.
+
+ \include qtcore.qdoc qtcoreprivate-usage
+
+ \since 6.2
+*/
+
+/*!
+ Creates a new object
+ */
+QAndroidServiceConnection::QAndroidServiceConnection()
+ : m_handle("org/qtproject/qt/android/extras/QtAndroidServiceConnection", "(J)V", jlong(this))
+{
+}
+
+/*!
+ Creates a new object from an existing \a serviceConnection.
+
+ It's useful when you have your own Java implementation.
+ Of course onServiceConnected()/onServiceDisconnected()
+ will not be called anymore.
+ */
+QAndroidServiceConnection::QAndroidServiceConnection(const QJniObject &serviceConnection)
+ : m_handle(serviceConnection)
+{
+}
+
+QAndroidServiceConnection::~QAndroidServiceConnection()
+{
+ m_handle.callMethod<void>("setId", "(J)V", jlong(this));
+}
+
+/*!
+ returns the underline QJniObject
+ */
+QJniObject QAndroidServiceConnection::handle() const
+{
+ return m_handle;
+}
+
+/*!
+ \fn void QAndroidServiceConnection::onServiceConnected(const QString &name, const QAndroidBinder &serviceBinder)
+
+ This notification is called when the client managed to connect to the service.
+ The \a name contains the server name, the \a serviceBinder is the binder that the client
+ uses to perform IPC operations.
+
+ \warning This method is called from Binder's thread which is different
+ from the thread that this object was created.
+
+ returns the underline QJniObject
+ */
+
+/*!
+ \fn void QAndroidServiceConnection::onServiceDisconnected(const QString &name)
+
+ Called when a connection to the Service has been lost.
+ The \a name parameter specifies which connectioen was lost.
+
+ \warning This method is called from Binder's thread which is different
+ from the thread that this object was created.
+
+ returns the underline QJniObject
+ */
+
+
+Q_CONSTINIT static QBasicAtomicInteger<uint> nextUniqueActivityRequestCode = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+// Get a unique activity request code.
+static int uniqueActivityRequestCode()
+{
+ constexpr uint ReservedForQtOffset = 0x1000; // Reserve all request codes under 0x1000 for Qt
+
+ const uint requestCodeBase = nextUniqueActivityRequestCode.fetchAndAddRelaxed(1);
+ if (requestCodeBase == uint(INT_MAX) - ReservedForQtOffset)
+ qWarning("Unique activity request code has wrapped. Unexpected behavior may occur.");
+
+ const int requestCode = static_cast<int>(requestCodeBase + ReservedForQtOffset);
+ return requestCode;
+}
+
+class QAndroidActivityResultReceiverPrivate: public QtAndroidPrivate::ActivityResultListener
+{
+public:
+ QAndroidActivityResultReceiver *q;
+ mutable QHash<int, int> localToGlobalRequestCode;
+ mutable QHash<int, int> globalToLocalRequestCode;
+
+ int globalRequestCode(int localRequestCode) const
+ {
+ const auto oldSize = localToGlobalRequestCode.size();
+ auto &e = localToGlobalRequestCode[localRequestCode];
+ if (localToGlobalRequestCode.size() != oldSize) {
+ // new entry, populate:
+ int globalRequestCode = uniqueActivityRequestCode();
+ e = globalRequestCode;
+ globalToLocalRequestCode[globalRequestCode] = localRequestCode;
+ }
+ return e;
+ }
+
+ bool handleActivityResult(jint requestCode, jint resultCode, jobject data)
+ {
+ const auto it = std::as_const(globalToLocalRequestCode).find(requestCode);
+ if (it != globalToLocalRequestCode.cend()) {
+ q->handleActivityResult(*it, resultCode, QJniObject(data));
+ return true;
+ }
+
+ return false;
+ }
+
+ static QAndroidActivityResultReceiverPrivate *get(QAndroidActivityResultReceiver *publicObject)
+ {
+ return publicObject->d.data();
+ }
+};
+
+/*!
+ \class QAndroidActivityResultReceiver
+ \inheaderfile QtCore/private/qandroidextras_p.h
+ \preliminary
+ \inmodule QtCorePrivate
+ \since 6.2
+ \brief Interface used for callbacks from onActivityResult() in the main Android activity.
+
+ Create a subclass of this class to be notified of the results when using the
+ \c QtAndroidPrivate::startActivity() and \c QtAndroidPrivate::startIntentSender() APIs.
+
+ \include qtcore.qdoc qtcoreprivate-usage
+ */
+
+/*!
+ \internal
+*/
+QAndroidActivityResultReceiver::QAndroidActivityResultReceiver()
+ : d(new QAndroidActivityResultReceiverPrivate)
+{
+ d->q = this;
+ QtAndroidPrivate::registerActivityResultListener(d.data());
+}
+
+/*!
+ \internal
+*/
+QAndroidActivityResultReceiver::~QAndroidActivityResultReceiver()
+{
+ QtAndroidPrivate::unregisterActivityResultListener(d.data());
+}
+
+/*!
+ \fn void QAndroidActivityResultReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject &data)
+
+ Reimplement this function to get activity results after starting an activity using
+ either QtAndroidPrivate::startActivity() or QtAndroidPrivate::startIntentSender().
+ The \a receiverRequestCode is the request code unique to this receiver which was
+ originally passed to the startActivity() or startIntentSender() functions. The
+ \a resultCode is the result returned by the activity, and \a data is either null
+ or a Java object of the class android.content.Intent. Both the last to arguments
+ are identical to the arguments passed to onActivityResult().
+*/
+
+
+
+class QAndroidServicePrivate : public QObject, public QtAndroidPrivate::OnBindListener
+{
+public:
+ QAndroidServicePrivate(QAndroidService *service,
+ const std::function<QAndroidBinder*(const QAndroidIntent&)> &binder ={})
+ : m_service(service)
+ , m_binder(binder)
+ {
+ QTimer::singleShot(0,this, [this]{ QtAndroidPrivate::setOnBindListener(this);});
+ }
+
+ ~QAndroidServicePrivate()
+ {
+ QMutexLocker lock(&m_bindersMutex);
+ while (!m_binders.empty()) {
+ auto it = m_binders.begin();
+ lock.unlock();
+ delete (*it);
+ lock.relock();
+ }
+ }
+
+ // OnBindListener interface
+ jobject onBind(jobject intent) override
+ {
+ auto qai = QAndroidIntent(intent);
+ auto binder = m_binder ? m_binder(qai) : m_service->onBind(qai);
+ if (binder) {
+ {
+ QMutexLocker lock(&m_bindersMutex);
+ binder->d->setDeleteListener([this, binder]{binderDestroied(binder);});
+ m_binders.insert(binder);
+ }
+ return binder->handle().object();
+ }
+ return nullptr;
+ }
+
+private:
+ void binderDestroied(QAndroidBinder* obj)
+ {
+ QMutexLocker lock(&m_bindersMutex);
+ m_binders.remove(obj);
+ }
+
+public:
+ QAndroidService *m_service = nullptr;
+ std::function<QAndroidBinder *(const QAndroidIntent &)> m_binder;
+ QMutex m_bindersMutex;
+ QSet<QAndroidBinder*> m_binders;
+};
+
+/*!
+ \class QAndroidService
+ \inheaderfile QtCore/private/qandroidextras_p.h
+ \preliminary
+ \inmodule QtCorePrivate
+ \brief Wraps the most important methods of Android Service class.
+
+ The QAndroidService is a convenience class that wraps the most important
+ \l {https://developer.android.com/reference/android/app/Service.html}{Android Service}
+ methods.
+
+ \include qtcore.qdoc qtcoreprivate-usage
+
+ \since 6.2
+*/
+
+
+/*!
+ \fn QAndroidService::QAndroidService(int &argc, char **argv)
+
+ Creates a new Android service, passing \a argc and \a argv as parameters.
+
+ //! Parameter \a flags is omitted in the documentation.
+
+ \sa QCoreApplication
+ */
+QAndroidService::QAndroidService(int &argc, char **argv, int flags)
+ : QCoreApplication (argc, argv, QtAndroidPrivate::acuqireServiceSetup(flags))
+ , d(new QAndroidServicePrivate{this})
+{
+}
+
+/*!
+ \fn QAndroidService::QAndroidService(int &argc, char **argv, const std::function<QAndroidBinder *(const QAndroidIntent &)> &binder)
+
+ Creates a new Android service, passing \a argc and \a argv as parameters.
+
+ \a binder is used to create a \l {QAndroidBinder}{binder} when needed.
+
+ //! Parameter \a flags is omitted in the documentation.
+
+ \sa QCoreApplication
+ */
+QAndroidService::QAndroidService(int &argc, char **argv,
+ const std::function<QAndroidBinder*(const QAndroidIntent&)> &binder,
+ int flags)
+ : QCoreApplication (argc, argv, QtAndroidPrivate::acuqireServiceSetup(flags))
+ , d(new QAndroidServicePrivate{this, binder})
+{
+}
+
+QAndroidService::~QAndroidService()
+{}
+
+/*!
+ The user must override this method and to return a binder.
+
+ The \a intent parameter contains all the caller information.
+
+ The returned binder is used by the caller to perform IPC calls.
+
+ \warning This method is called from Binder's thread which is different
+ from the thread that this object was created.
+
+ \sa QAndroidBinder::onTransact, QAndroidBinder::transact
+ */
+QAndroidBinder* QAndroidService::onBind(const QAndroidIntent &/*intent*/)
+{
+ return nullptr;
+}
+
+static jboolean onTransact(JNIEnv */*env*/, jclass /*cls*/, jlong id, jint code, jobject data,
+ jobject reply, jint flags)
+{
+ if (!id)
+ return false;
+
+ return reinterpret_cast<QAndroidBinder*>(id)->onTransact(
+ code, QAndroidParcel(data), QAndroidParcel(reply), QAndroidBinder::CallType(flags));
+}
+
+static void onServiceConnected(JNIEnv */*env*/, jclass /*cls*/, jlong id, jstring name,
+ jobject service)
+{
+ if (!id)
+ return;
+
+ return reinterpret_cast<QAndroidServiceConnection *>(id)->onServiceConnected(
+ QJniObject(name).toString(), QAndroidBinder(service));
+}
+
+static void onServiceDisconnected(JNIEnv */*env*/, jclass /*cls*/, jlong id, jstring name)
+{
+ if (!id)
+ return;
+
+ return reinterpret_cast<QAndroidServiceConnection *>(id)->onServiceDisconnected(
+ QJniObject(name).toString());
+}
+
+bool QtAndroidPrivate::registerExtrasNatives(QJniEnvironment &env)
+{
+ static const JNINativeMethod methods[] = {
+ {"onTransact", "(JILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void *)onTransact},
+ {"onServiceConnected", "(JLjava/lang/String;Landroid/os/IBinder;)V", (void *)onServiceConnected},
+ {"onServiceDisconnected", "(JLjava/lang/String;)V", (void *)onServiceDisconnected}
+ };
+
+ return env.registerNativeMethods("org/qtproject/qt/android/extras/QtNative", methods, 3);
+}
+
+/*!
+ \class QAndroidIntent
+ \inheaderfile QtCore/private/qandroidextras_p.h
+ \preliminary
+ \inmodule QtCorePrivate
+ \brief Wraps the most important methods of Android Intent class.
+
+ The QAndroidIntent is a convenience class that wraps the most important
+ \l {https://developer.android.com/reference/android/content/Intent.html}{Android Intent}
+ methods.
+
+ \include qtcore.qdoc qtcoreprivate-usage
+
+ \since 6.2
+*/
+
+/*!
+ Create a new intent
+ */
+QAndroidIntent::QAndroidIntent()
+ : m_handle("android.content.Intent", "()V")
+{
+
+}
+
+QAndroidIntent::~QAndroidIntent()
+{}
+
+/*!
+ Wraps the provided \a intent java object.
+ */
+QAndroidIntent::QAndroidIntent(const QJniObject &intent)
+ : m_handle(intent)
+{
+}
+
+/*!
+ Creates a new intent and sets the provided \a action.
+ */
+QAndroidIntent::QAndroidIntent(const QString &action)
+ : m_handle("android.content.Intent", "(Ljava/lang/String;)V",
+ QJniObject::fromString(action).object())
+{
+ QJniEnvironment().checkAndClearExceptions();
+}
+
+/*!
+ Creates a new intent and sets the provided \a packageContext and the service \a className.
+ Example:
+ \code
+ auto serviceIntent = QAndroidIntent(QtAndroidPrivate::androidActivity().object(), "com.example.MyService");
+ \endcode
+
+ \sa QtAndroidPrivate::bindService
+ */
+QAndroidIntent::QAndroidIntent(const QJniObject &packageContext, const char *className)
+ : m_handle("android/content/Intent", "(Landroid/content/Context;Ljava/lang/Class;)V",
+ packageContext.object(), QJniEnvironment().findClass(className))
+{
+ QJniEnvironment().checkAndClearExceptions();
+}
+
+/*!
+ Sets the \a key with the \a data in the Intent extras
+ */
+void QAndroidIntent::putExtra(const QString &key, const QByteArray &data)
+{
+ QJniEnvironment().checkAndClearExceptions();
+ QJniEnvironment env;
+ jbyteArray array = env->NewByteArray(data.size());
+ env->SetByteArrayRegion(array, 0, data.length(),
+ reinterpret_cast<const jbyte*>(data.constData()));
+ m_handle.callObjectMethod("putExtra", "(Ljava/lang/String;[B)Landroid/content/Intent;",
+ QJniObject::fromString(key).object(), array);
+ env->DeleteLocalRef(array);
+ QJniEnvironment().checkAndClearExceptions();
+}
+
+/*!
+ Returns the extra \a key data from the Intent extras
+ */
+QByteArray QAndroidIntent::extraBytes(const QString &key)
+{
+ QJniEnvironment().checkAndClearExceptions();
+ auto array = m_handle.callObjectMethod("getByteArrayExtra", "(Ljava/lang/String;)[B",
+ QJniObject::fromString(key).object());
+ if (!array.isValid() || !array.object())
+ return QByteArray();
+ QJniEnvironment env;
+ auto sz = env->GetArrayLength(jarray(array.object()));
+ QByteArray res(sz, Qt::Initialization::Uninitialized);
+ env->GetByteArrayRegion(jbyteArray(array.object()), 0, sz,
+ reinterpret_cast<jbyte *>(res.data()));
+ QJniEnvironment().checkAndClearExceptions();
+
+ return res;
+}
+
+/*!
+ Sets the \a key with the \a value in the Intent extras.
+ */
+void QAndroidIntent::putExtra(const QString &key, const QVariant &value)
+{
+ QByteArray buff;
+ QDataStream stream(&buff, QIODevice::WriteOnly);
+ stream << value;
+ putExtra(key, buff);
+}
+
+/*!
+ Returns the extra \a key data from the Intent extras as a QVariant
+ */
+QVariant QAndroidIntent::extraVariant(const QString &key)
+{
+ QDataStream stream(extraBytes(key));
+ QVariant res;
+ stream >> res;
+ return res;
+}
+
+/*!
+ The return value is useful to call other Java API which are not covered by this wrapper
+ */
+QJniObject QAndroidIntent::handle() const
+{
+ return m_handle;
+}
+
+
+
+/*!
+ \namespace QtAndroidPrivate
+ \preliminary
+ \inmodule QtCorePrivate
+ \since 6.2
+ \brief The QtAndroidPrivate namespace provides miscellaneous functions
+ to aid Android development.
+ \inheaderfile QtCore/private/qandroidextras_p.h
+
+ \include qtcore.qdoc qtcoreprivate-usage
+*/
+
+/*!
+ \since 6.2
+ \enum QtAndroidPrivate::BindFlag
+
+ This enum is used with QtAndroidPrivate::bindService to describe the mode in which the
+ binding is performed.
+
+ \value None No options.
+ \value AutoCreate Automatically creates the service as long as the binding exist.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_AUTO_CREATE}
+ {BIND_AUTO_CREATE} documentation for more details.
+ \value DebugUnbind Include debugging help for mismatched calls to unbind.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_DEBUG_UNBIND}
+ {BIND_DEBUG_UNBIND} documentation for more details.
+ \value NotForeground Don't allow this binding to raise the target service's process to the foreground scheduling priority.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_NOT_FOREGROUND}
+ {BIND_NOT_FOREGROUND} documentation for more details.
+ \value AboveClient Indicates that the client application binding to this service considers the service to be more important than the app itself.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_ABOVE_CLIENT}
+ {BIND_ABOVE_CLIENT} documentation for more details.
+ \value AllowOomManagement Allow the process hosting the bound service to go through its normal memory management.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_ALLOW_OOM_MANAGEMENT}
+ {BIND_ALLOW_OOM_MANAGEMENT} documentation for more details.
+ \value WaivePriority Don't impact the scheduling or memory management priority of the target service's hosting process.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_WAIVE_PRIORITY}
+ {BIND_WAIVE_PRIORITY} documentation for more details.
+ \value Important This service is assigned a higher priority so that it is available to the client when needed.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_IMPORTANT}
+ {BIND_IMPORTANT} documentation for more details.
+ \value AdjustWithActivity If binding from an activity, allow the target service's process importance to be raised based on whether the activity is visible to the user.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_ADJUST_WITH_ACTIVITY}
+ {BIND_ADJUST_WITH_ACTIVITY} documentation for more details.
+ \value ExternalService The service being bound is an isolated, external service.
+ See \l {https://developer.android.com/reference/android/content/Context.html#BIND_EXTERNAL_SERVICE}
+ {BIND_EXTERNAL_SERVICE} documentation for more details.
+*/
+
+/*!
+ \since 6.2
+
+ Starts the activity given by \a intent and provides the result asynchronously through the
+ \a resultReceiver if this is non-null.
+
+ If \a resultReceiver is null, then the \c startActivity() method in the \c androidActivity()
+ will be called. Otherwise \c startActivityForResult() will be called.
+
+ The \a receiverRequestCode is a request code unique to the \a resultReceiver, and will be
+ returned along with the result, making it possible to use the same receiver for more than
+ one intent.
+
+ */
+void QtAndroidPrivate::startActivity(const QJniObject &intent,
+ int receiverRequestCode,
+ QAndroidActivityResultReceiver *resultReceiver)
+{
+ QJniObject activity = QtAndroidPrivate::activity();
+ if (resultReceiver != 0) {
+ QAndroidActivityResultReceiverPrivate *resultReceiverD =
+ QAndroidActivityResultReceiverPrivate::get(resultReceiver);
+ activity.callMethod<void>("startActivityForResult",
+ "(Landroid/content/Intent;I)V",
+ intent.object<jobject>(),
+ resultReceiverD->globalRequestCode(receiverRequestCode));
+ } else {
+ activity.callMethod<void>("startActivity",
+ "(Landroid/content/Intent;)V",
+ intent.object<jobject>());
+ }
+}
+
+/*!
+ \since 6.2
+
+ Starts the activity given by \a intent and provides the result asynchronously through the
+ \a resultReceiver if this is non-null.
+
+ If \a resultReceiver is null, then the \c startActivity() method in the \c androidActivity()
+ will be called. Otherwise \c startActivityForResult() will be called.
+
+ The \a receiverRequestCode is a request code unique to the \a resultReceiver, and will be
+ returned along with the result, making it possible to use the same receiver for more than
+ one intent.
+
+ */
+void QtAndroidPrivate::startActivity(const QAndroidIntent &intent,
+ int receiverRequestCode,
+ QAndroidActivityResultReceiver *resultReceiver)
+{
+ startActivity(intent.handle(), receiverRequestCode, resultReceiver);
+}
+
+/*!
+ \since 6.2
+
+ Starts the activity given by \a intent, using the request code \a receiverRequestCode,
+ and provides the result by calling \a callbackFunc.
+*/
+void QtAndroidPrivate::startActivity(const QJniObject &intent,
+ int receiverRequestCode,
+ std::function<void(int, int, const QJniObject &data)> callbackFunc)
+{
+ QJniObject activity = QtAndroidPrivate::activity();
+ QAndroidActivityCallbackResultReceiver::instance()->registerCallback(receiverRequestCode,
+ callbackFunc);
+ startActivity(intent, receiverRequestCode, QAndroidActivityCallbackResultReceiver::instance());
+}
+
+/*!
+ \since 6.2
+
+ Starts the activity given by \a intentSender and provides the result asynchronously through the
+ \a resultReceiver if this is non-null.
+
+ If \a resultReceiver is null, then the \c startIntentSender() method in the \c androidActivity()
+ will be called. Otherwise \c startIntentSenderForResult() will be called.
+
+ The \a receiverRequestCode is a request code unique to the \a resultReceiver, and will be
+ returned along with the result, making it possible to use the same receiver for more than
+ one intent.
+
+*/
+void QtAndroidPrivate::startIntentSender(const QJniObject &intentSender,
+ int receiverRequestCode,
+ QAndroidActivityResultReceiver *resultReceiver)
+{
+ QJniObject activity = QtAndroidPrivate::activity();
+ if (resultReceiver != 0) {
+ QAndroidActivityResultReceiverPrivate *resultReceiverD =
+ QAndroidActivityResultReceiverPrivate::get(resultReceiver);
+ activity.callMethod<void>("startIntentSenderForResult",
+ "(Landroid/content/IntentSender;ILandroid/content/Intent;III)V",
+ intentSender.object<jobject>(),
+ resultReceiverD->globalRequestCode(receiverRequestCode),
+ 0, // fillInIntent
+ 0, // flagsMask
+ 0, // flagsValues
+ 0); // extraFlags
+ } else {
+ activity.callMethod<void>("startIntentSender",
+ "(Landroid/content/IntentSender;Landroid/content/Intent;III)V",
+ intentSender.object<jobject>(),
+ 0, // fillInIntent
+ 0, // flagsMask
+ 0, // flagsValues
+ 0); // extraFlags
+
+ }
+
+}
+
+/*!
+ \since 6.2
+ \fn bool QtAndroidPrivate::bindService(const QAndroidIntent &serviceIntent, const QAndroidServiceConnection &serviceConnection, BindFlags flags = BindFlag::None)
+
+ Binds the service given by \a serviceIntent, \a serviceConnection and \a flags.
+ The \a serviceIntent object identifies the service to connect to.
+ The \a serviceConnection is a listener that receives the information as the service
+ is started and stopped.
+
+ \return true on success
+
+ See \l {https://developer.android.com/reference/android/content/Context.html#bindService%28android.content.Intent,%20android.content.ServiceConnection,%20int%29}
+ {Android documentation} documentation for more details.
+
+ \sa QAndroidIntent, QAndroidServiceConnection, BindFlag
+*/
+bool QtAndroidPrivate::bindService(const QAndroidIntent &serviceIntent,
+ const QAndroidServiceConnection &serviceConnection, BindFlags flags)
+{
+ QJniEnvironment().checkAndClearExceptions();
+ QJniObject contextObj = QtAndroidPrivate::context();
+ return contextObj.callMethod<jboolean>(
+ "bindService",
+ "(Landroid/content/Intent;Landroid/content/ServiceConnection;I)Z",
+ serviceIntent.handle().object(),
+ serviceConnection.handle().object(),
+ jint(flags));
+}
+
+QAndroidActivityCallbackResultReceiver * QAndroidActivityCallbackResultReceiver::s_instance = nullptr;
+
+QAndroidActivityCallbackResultReceiver::QAndroidActivityCallbackResultReceiver()
+ : QAndroidActivityResultReceiver()
+ , callbackMap()
+{
+}
+
+void QAndroidActivityCallbackResultReceiver::handleActivityResult(int receiverRequestCode,
+ int resultCode,
+ const QJniObject &intent)
+{
+ callbackMap[receiverRequestCode](receiverRequestCode, resultCode, intent);
+ callbackMap.remove(receiverRequestCode);
+}
+
+QAndroidActivityCallbackResultReceiver * QAndroidActivityCallbackResultReceiver::instance() {
+ if (!s_instance) {
+ s_instance = new QAndroidActivityCallbackResultReceiver();
+ }
+ return s_instance;
+}
+
+void QAndroidActivityCallbackResultReceiver::registerCallback(
+ int receiverRequestCode,
+ std::function<void(int, int, const QJniObject &data)> callbackFunc)
+{
+ callbackMap.insert(receiverRequestCode, callbackFunc);
+}
+
+// Permissions API
+
+static const char qtNativeClassName[] = "org/qtproject/qt/android/QtNative";
+
+QtAndroidPrivate::PermissionResult resultFromAndroid(jint value)
+{
+ return value == 0 ? QtAndroidPrivate::Authorized : QtAndroidPrivate::Denied;
+}
+
+using PendingPermissionRequestsHash
+ = QHash<int, QSharedPointer<QPromise<QtAndroidPrivate::PermissionResult>>>;
+Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests);
+Q_CONSTINIT static QBasicMutex g_pendingPermissionRequestsMutex;
+
+static int nextRequestCode()
+{
+ Q_CONSTINIT static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0);
+ return counter.fetchAndAddRelaxed(1);
+}
+
+/*!
+ \internal
+
+ This function is called when the result of the permission request is available.
+ Once a permission is requested, the result is braodcast by the OS and listened
+ to by QtActivity which passes it to C++ through a native JNI method call.
+ */
+static void sendRequestPermissionsResult(JNIEnv *env, jobject *obj, jint requestCode,
+ jobjectArray permissions, jintArray grantResults)
+{
+ Q_UNUSED(obj);
+
+ QMutexLocker locker(&g_pendingPermissionRequestsMutex);
+ auto it = g_pendingPermissionRequests->constFind(requestCode);
+ if (it == g_pendingPermissionRequests->constEnd()) {
+ qWarning() << "Found no valid pending permission request for request code" << requestCode;
+ return;
+ }
+
+ auto request = *it;
+ g_pendingPermissionRequests->erase(it);
+ locker.unlock();
+
+ const int size = env->GetArrayLength(permissions);
+ std::unique_ptr<jint[]> results(new jint[size]);
+ env->GetIntArrayRegion(grantResults, 0, size, results.get());
+
+ for (int i = 0 ; i < size; ++i) {
+ QtAndroidPrivate::PermissionResult result = resultFromAndroid(results[i]);
+ request->addResult(result, i);
+ }
+
+ QtAndroidPrivate::releaseAndroidDeadlockProtector();
+ request->finish();
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+requestPermissionsInternal(const QStringList &permissions)
+{
+ // No mechanism to request permission for SDK version below 23, because
+ // permissions defined in the manifest are granted at install time.
+ if (QtAndroidPrivate::androidSdkVersion() < 23) {
+ QList<QtAndroidPrivate::PermissionResult> result;
+ result.reserve(permissions.size());
+ // ### can we kick off all checkPermission()s, and whenAll() collect results?
+ for (const QString &permission : permissions)
+ result.push_back(QtAndroidPrivate::checkPermission(permission).result());
+ return QtFuture::makeReadyRangeFuture(result);
+ }
+
+ if (!QtAndroidPrivate::acquireAndroidDeadlockProtector())
+ return QtFuture::makeReadyValueFuture(QtAndroidPrivate::Denied);
+
+ QSharedPointer<QPromise<QtAndroidPrivate::PermissionResult>> promise;
+ promise.reset(new QPromise<QtAndroidPrivate::PermissionResult>());
+ QFuture<QtAndroidPrivate::PermissionResult> future = promise->future();
+ promise->start();
+
+ const int requestCode = nextRequestCode();
+ QMutexLocker locker(&g_pendingPermissionRequestsMutex);
+ g_pendingPermissionRequests->insert(requestCode, promise);
+ locker.unlock();
+
+ QNativeInterface::QAndroidApplication::runOnAndroidMainThread([permissions, requestCode] {
+ QJniEnvironment env;
+ jclass clazz = env.findClass("java/lang/String");
+ auto array = env->NewObjectArray(permissions.size(), clazz, nullptr);
+ int index = 0;
+
+ for (auto &perm : permissions)
+ env->SetObjectArrayElement(array, index++, QJniObject::fromString(perm).object());
+
+ QJniObject(QtAndroidPrivate::activity()).callMethod<void>("requestPermissions",
+ "([Ljava/lang/String;I)V",
+ array,
+ requestCode);
+ env->DeleteLocalRef(array);
+ });
+
+ return future;
+}
+
+/*!
+ \preliminary
+ Requests the \a permission and returns a QFuture representing the
+ result of the request.
+
+ \since 6.2
+ \sa checkPermission()
+*/
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::requestPermission(const QString &permission)
+{
+ return requestPermissions({permission});
+}
+
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::requestPermissions(const QStringList &permissions)
+{
+ // avoid the uneccessary call and response to an empty permission string
+ if (permissions.isEmpty())
+ return QtFuture::makeReadyValueFuture(QtAndroidPrivate::Denied);
+ return requestPermissionsInternal(permissions);
+}
+
+/*!
+ \preliminary
+ Checks whether this process has the named \a permission and returns a QFuture
+ representing the result of the check.
+
+ \since 6.2
+ \sa requestPermission()
+*/
+QFuture<QtAndroidPrivate::PermissionResult>
+QtAndroidPrivate::checkPermission(const QString &permission)
+{
+ QtAndroidPrivate::PermissionResult result = Denied;
+ if (!permission.isEmpty()) {
+ auto res = QJniObject::callStaticMethod<jint>(qtNativeClassName,
+ "checkSelfPermission",
+ "(Ljava/lang/String;)I",
+ QJniObject::fromString(permission).object());
+ result = resultFromAndroid(res);
+ }
+ return QtFuture::makeReadyValueFuture(result);
+}
+
+bool QtAndroidPrivate::registerPermissionNatives(QJniEnvironment &env)
+{
+ if (QtAndroidPrivate::androidSdkVersion() < 23)
+ return true;
+
+ const JNINativeMethod methods[] = {
+ {"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V",
+ reinterpret_cast<void *>(sendRequestPermissionsResult)
+ }};
+
+ return env.registerNativeMethods(qtNativeClassName, methods, 1);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qandroidextras_p.cpp"
diff --git a/src/corelib/platform/android/qandroidextras_p.h b/src/corelib/platform/android/qandroidextras_p.h
new file mode 100644
index 0000000000..efdc6cf74f
--- /dev/null
+++ b/src/corelib/platform/android/qandroidextras_p.h
@@ -0,0 +1,246 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QANDROIDEXTRAS_H
+#define QANDROIDEXTRAS_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <jni.h>
+#include <functional>
+
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qjniobject.h>
+#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmap.h>
+
+#if QT_CONFIG(future)
+#include <QtCore/qfuture.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidParcel;
+class QAndroidBinderPrivate;
+class QAndroidBinder;
+
+class Q_CORE_EXPORT QAndroidBinder
+{
+public:
+ enum class CallType {
+ Normal = 0,
+ OneWay = 1
+ };
+
+public:
+ explicit QAndroidBinder();
+ QAndroidBinder(const QJniObject &binder);
+
+ virtual ~QAndroidBinder();
+
+ virtual bool onTransact(int code, const QAndroidParcel &data,
+ const QAndroidParcel &reply, CallType flags);
+ bool transact(int code, const QAndroidParcel &data,
+ QAndroidParcel *reply = nullptr, CallType flags = CallType::Normal) const;
+
+ QJniObject handle() const;
+
+private:
+ friend class QAndroidBinderPrivate;
+ friend class QAndroidParcelPrivate;
+ friend class QAndroidServicePrivate;
+ QSharedPointer<QAndroidBinderPrivate> d;
+};
+
+class QAndroidParcelPrivate;
+
+class Q_CORE_EXPORT QAndroidParcel
+{
+public:
+ QAndroidParcel();
+ explicit QAndroidParcel(const QJniObject& parcel);
+ virtual ~QAndroidParcel();
+
+ void writeData(const QByteArray &data) const;
+ void writeVariant(const QVariant &value) const;
+ void writeBinder(const QAndroidBinder &binder) const;
+ void writeFileDescriptor(int fd) const;
+
+ QByteArray readData() const;
+ QVariant readVariant() const;
+ QAndroidBinder readBinder() const;
+ int readFileDescriptor() const;
+
+ QJniObject handle() const;
+
+private:
+ friend class QAndroidParcelPrivate;
+ friend class QAndroidBinder;
+ QSharedPointer<QAndroidParcelPrivate> d;
+};
+
+class QAndroidActivityResultReceiverPrivate;
+
+class Q_CORE_EXPORT QAndroidActivityResultReceiver
+{
+public:
+ QAndroidActivityResultReceiver();
+ virtual ~QAndroidActivityResultReceiver();
+ virtual void handleActivityResult(int receiverRequestCode, int resultCode,
+ const QJniObject &data) = 0;
+
+private:
+ friend class QAndroidActivityResultReceiverPrivate;
+ Q_DISABLE_COPY(QAndroidActivityResultReceiver)
+
+ QScopedPointer<QAndroidActivityResultReceiverPrivate> d;
+};
+
+class Q_CORE_EXPORT QAndroidServiceConnection
+{
+public:
+ QAndroidServiceConnection();
+ explicit QAndroidServiceConnection(const QJniObject &serviceConnection);
+ virtual ~QAndroidServiceConnection();
+
+ virtual void onServiceConnected(const QString &name,
+ const QAndroidBinder &serviceBinder) = 0;
+ virtual void onServiceDisconnected(const QString &name) = 0;
+
+ QJniObject handle() const;
+private:
+ Q_DISABLE_COPY(QAndroidServiceConnection)
+ QJniObject m_handle;
+};
+
+class Q_CORE_EXPORT QAndroidIntent
+{
+public:
+ QAndroidIntent();
+ virtual ~QAndroidIntent();
+ explicit QAndroidIntent(const QJniObject &intent);
+ explicit QAndroidIntent(const QString &action);
+ explicit QAndroidIntent(const QJniObject &packageContext, const char *className);
+
+ void putExtra(const QString &key, const QByteArray &data);
+ QByteArray extraBytes(const QString &key);
+
+ void putExtra(const QString &key, const QVariant &value);
+ QVariant extraVariant(const QString &key);
+
+ QJniObject handle() const;
+
+private:
+ QJniObject m_handle;
+};
+
+class QAndroidServicePrivate;
+
+class Q_CORE_EXPORT QAndroidService : public QCoreApplication
+{
+ Q_OBJECT
+
+public:
+ QAndroidService(int &argc, char **argv
+#ifndef Q_QDOC
+ , int flags = ApplicationFlags
+#endif
+ );
+ QAndroidService(int &argc, char **argv,
+ const std::function<QAndroidBinder*(const QAndroidIntent &intent)> & binder
+#ifndef Q_QDOC
+ , int flags = ApplicationFlags
+#endif
+ );
+ virtual ~QAndroidService();
+
+ virtual QAndroidBinder* onBind(const QAndroidIntent &intent);
+
+private:
+ friend class QAndroidServicePrivate;
+ Q_DISABLE_COPY(QAndroidService)
+
+ QScopedPointer<QAndroidServicePrivate> d;
+};
+
+class QAndroidActivityCallbackResultReceiver: public QAndroidActivityResultReceiver
+{
+public:
+ QAndroidActivityCallbackResultReceiver();
+ void handleActivityResult(int receiverRequestCode, int resultCode,
+ const QJniObject &intent) override;
+ void registerCallback(int receiverRequestCode,
+ std::function<void(int, int, const QJniObject &)> callbackFunc);
+
+ static QAndroidActivityCallbackResultReceiver *instance();
+private:
+ QMap<int, std::function<void(int, int, const QJniObject &data)>> callbackMap;
+
+ static QAndroidActivityCallbackResultReceiver *s_instance;
+};
+
+namespace QtAndroidPrivate
+{
+ Q_CORE_EXPORT void startIntentSender(const QJniObject &intentSender,
+ int receiverRequestCode,
+ QAndroidActivityResultReceiver *resultReceiver = nullptr);
+ Q_CORE_EXPORT void startActivity(const QJniObject &intent,
+ int receiverRequestCode,
+ QAndroidActivityResultReceiver *resultReceiver = nullptr);
+ Q_CORE_EXPORT void startActivity(const QAndroidIntent &intent,
+ int receiverRequestCode,
+ QAndroidActivityResultReceiver *resultReceiver = nullptr);
+ Q_CORE_EXPORT void startActivity(const QJniObject &intent,
+ int receiverRequestCode,
+ std::function<void(int, int, const QJniObject &data)>
+ callbackFunc);
+
+ enum class BindFlag {
+ None = 0x00000000,
+ AutoCreate = 0x00000001,
+ DebugUnbind = 0x00000002,
+ NotForeground = 0x00000004,
+ AboveClient = 0x00000008,
+ AllowOomManagement = 0x00000010,
+ WaivePriority = 0x00000020,
+ Important = 0x00000040,
+ AdjustWithActivity = 0x00000080,
+ ExternalService = -2147483648 // 0x80000000
+
+ };
+ Q_DECLARE_FLAGS(BindFlags, BindFlag)
+
+ Q_CORE_EXPORT bool bindService(const QAndroidIntent &serviceIntent,
+ const QAndroidServiceConnection &serviceConnection,
+ BindFlags flags = BindFlag::None);
+
+#if QT_CONFIG(future)
+ enum PermissionResult {
+ Undetermined,
+ Authorized,
+ Denied
+ };
+
+ Q_CORE_EXPORT QFuture<QtAndroidPrivate::PermissionResult>
+ requestPermission(const QString &permission);
+ QFuture<QtAndroidPrivate::PermissionResult>
+ requestPermissions(const QStringList &permissions);
+ Q_CORE_EXPORT QFuture<QtAndroidPrivate::PermissionResult>
+ checkPermission(const QString &permission);
+#endif
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDEXTRAS_H
diff --git a/src/corelib/platform/android/qandroidnativeinterface.cpp b/src/corelib/platform/android/qandroidnativeinterface.cpp
new file mode 100644
index 0000000000..fc3a09c78b
--- /dev/null
+++ b/src/corelib/platform/android/qandroidnativeinterface.cpp
@@ -0,0 +1,243 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qcoreapplication_platform.h>
+
+#include <QtCore/private/qnativeinterface_p.h>
+#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qjniobject.h>
+#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
+#include <QtCore/qfuture.h>
+#include <QtCore/qfuturewatcher.h>
+#include <QtCore/qpromise.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qthreadpool.h>
+#include <deque>
+#include <memory>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
+static const char qtNativeClassName[] = "org/qtproject/qt/android/QtNative";
+
+struct PendingRunnable {
+ std::function<QVariant()> function;
+ std::shared_ptr<QPromise<QVariant>> promise;
+};
+
+using PendingRunnables = std::deque<PendingRunnable>;
+Q_GLOBAL_STATIC(PendingRunnables, g_pendingRunnables);
+Q_CONSTINIT static QBasicMutex g_pendingRunnablesMutex;
+#endif
+
+/*!
+ \class QNativeInterface::QAndroidApplication
+ \since 6.2
+ \brief Native interface to a core application on Android.
+
+ Accessed through QCoreApplication::nativeInterface().
+
+ \inmodule QtCore
+ \inheaderfile QCoreApplication
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qcoreapplication
+*/
+QT_DEFINE_NATIVE_INTERFACE(QAndroidApplication);
+
+/*!
+ \fn QJniObject QNativeInterface::QAndroidApplication::context()
+
+ Returns the Android context as a \c QJniObject. The context is an \c Activity
+ if the main activity object is valid. Otherwise, the context is a \c Service.
+
+ \since 6.2
+*/
+QtJniTypes::Context QNativeInterface::QAndroidApplication::context()
+{
+ return QtAndroidPrivate::context();
+}
+
+/*!
+ \fn bool QNativeInterface::QAndroidApplication::isActivityContext()
+
+ Returns \c true if QAndroidApplication::context() provides an \c Activity
+ context.
+
+ \since 6.2
+*/
+bool QNativeInterface::QAndroidApplication::isActivityContext()
+{
+ return QtAndroidPrivate::activity().isValid();
+}
+
+/*!
+ \fn int QNativeInterface::QAndroidApplication::sdkVersion()
+
+ Returns the Android SDK version. This is also known as the API level.
+
+ \since 6.2
+*/
+int QNativeInterface::QAndroidApplication::sdkVersion()
+{
+ return QtAndroidPrivate::androidSdkVersion();
+}
+
+/*!
+ \fn void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration)
+
+ Hides the splash screen by using a fade effect for the given \a duration.
+ If \a duration is not provided (default is 0) the splash screen is hidden
+ immedetiately after the app starts.
+
+ \since 6.2
+*/
+void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration)
+{
+ QtAndroidPrivate::activity().callMethod<void>("hideSplashScreen", duration);
+}
+
+/*!
+ Posts the function \a runnable to the Android thread. The function will be
+ queued and executed on the Android UI thread. If the call is made on the
+ Android UI thread \a runnable will be executed immediately. If the Android
+ app is paused or the main Activity is null, \c runnable is added to the
+ Android main thread's queue.
+
+ This call returns a QFuture<QVariant> which allows doing both synchronous
+ and asynchronous calls, and can handle any return type. However, to get
+ a result back from the QFuture::result(), QVariant::value() should be used.
+
+ If the \a runnable execution takes longer than the period of \a timeout,
+ the blocking calls \l QFuture::waitForFinished() and \l QFuture::result()
+ are ended once \a timeout has elapsed. However, if \a runnable has already
+ started execution, it won't be cancelled.
+
+ The following example shows how to run an asynchronous call that expects
+ a return type:
+
+ \code
+ auto task = QNativeInterface::QAndroidApplication::runOnAndroidMainThread([=]() {
+ QJniObject surfaceView;
+ if (!surfaceView.isValid())
+ qDebug() << "SurfaceView object is not valid yet";
+
+ surfaceView = QJniObject("android/view/SurfaceView",
+ "(Landroid/content/Context;)V",
+ QNativeInterface::QAndroidApplication::context());
+
+ return QVariant::fromValue(surfaceView);
+ }).then([](QFuture<QVariant> future) {
+ auto surfaceView = future.result().value<QJniObject>();
+ if (surfaceView.isValid())
+ qDebug() << "Retrieved SurfaceView object is valid";
+ });
+ \endcode
+
+ The following example shows how to run a synchronous call with a void
+ return type:
+
+ \code
+ QNativeInterface::QAndroidApplication::runOnAndroidMainThread([]() {
+ QJniObject activity = QNativeInterface::QAndroidApplication::context();
+ // Hide system ui elements or go full screen
+ activity.callObjectMethod("getWindow", "()Landroid/view/Window;")
+ .callObjectMethod("getDecorView", "()Landroid/view/View;")
+ .callMethod<void>("setSystemUiVisibility", "(I)V", 0xffffffff);
+ }).waitForFinished();
+ \endcode
+
+ \note Becareful about the type of operations you do on the Android's main
+ thread, as any long operation can block the app's UI rendering and input
+ handling. If the function is expected to have long execution time, it's
+ also good to use a \l QDeadlineTimer in your \a runnable to manage
+ the execution and make sure it doesn't block the UI thread. Usually,
+ any operation longer than 5 seconds might block the app's UI. For more
+ information, see \l {Android: Keeping your app responsive}{Keeping your app responsive}.
+
+ \since 6.2
+*/
+#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
+QFuture<QVariant> QNativeInterface::QAndroidApplication::runOnAndroidMainThread(
+ const std::function<QVariant()> &runnable,
+ const QDeadlineTimer timeout)
+{
+ auto promise = std::make_shared<QPromise<QVariant>>();
+ QFuture<QVariant> future = promise->future();
+ promise->start();
+
+ if (!timeout.isForever()) {
+ QThreadPool::globalInstance()->start([=]() mutable {
+ QEventLoop loop;
+ QTimer::singleShot(timeout.remainingTime(), &loop, [&]() {
+ future.cancel();
+ promise->finish();
+ loop.quit();
+ });
+
+ QFutureWatcher<QVariant> watcher;
+ QObject::connect(&watcher, &QFutureWatcher<QVariant>::finished, &loop, [&]() {
+ loop.quit();
+ });
+ QObject::connect(&watcher, &QFutureWatcher<QVariant>::canceled, &loop, [&]() {
+ loop.quit();
+ });
+ watcher.setFuture(future);
+
+ // we're going to sleep, make sure we don't block
+ // QThreadPool::globalInstance():
+
+ QThreadPool::globalInstance()->releaseThread();
+ const auto sg = qScopeGuard([] {
+ QThreadPool::globalInstance()->reserveThread();
+ });
+ loop.exec();
+ });
+ }
+
+ QMutexLocker locker(&g_pendingRunnablesMutex);
+#ifdef __cpp_aggregate_paren_init
+ g_pendingRunnables->emplace_back(runnable, std::move(promise));
+#else
+ g_pendingRunnables->push_back({runnable, std::move(promise)});
+#endif
+ locker.unlock();
+
+ QJniObject::callStaticMethod<void>(qtNativeClassName,
+ "runPendingCppRunnablesOnAndroidThread",
+ "()V");
+ return future;
+}
+
+// function called from Java from Android UI thread
+static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/)
+{
+ // run all posted runnables
+ for (;;) {
+ QMutexLocker locker(&g_pendingRunnablesMutex);
+ if (g_pendingRunnables->empty())
+ break;
+
+ PendingRunnable r = std::move(g_pendingRunnables->front());
+ g_pendingRunnables->pop_front();
+ locker.unlock();
+
+ // run the runnable outside the sync block!
+ if (!r.promise->isCanceled())
+ r.promise->addResult(r.function());
+ r.promise->finish();
+ }
+}
+#endif
+
+bool QtAndroidPrivate::registerNativeInterfaceNatives(QJniEnvironment &env)
+{
+#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
+ const JNINativeMethod methods = {"runPendingCppRunnables", "()V", (void *)runPendingCppRunnables};
+ return env.registerNativeMethods(qtNativeClassName, &methods, 1);
+#else
+ return true;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin.mm
new file mode 100644
index 0000000000..5c527f396c
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin.mm
@@ -0,0 +1,90 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDarwinPermissionPlugin::QDarwinPermissionPlugin(QDarwinPermissionHandler *handler)
+ : QPermissionPlugin()
+ , m_handler(handler)
+{
+}
+
+QDarwinPermissionPlugin::~QDarwinPermissionPlugin()
+{
+ [m_handler release];
+}
+
+Qt::PermissionStatus QDarwinPermissionPlugin::checkPermission(const QPermission &permission)
+{
+ return [m_handler checkPermission:permission];
+}
+
+void QDarwinPermissionPlugin::requestPermission(const QPermission &permission, const PermissionCallback &callback)
+{
+ if (!verifyUsageDescriptions(permission)) {
+ callback(Qt::PermissionStatus::Denied);
+ return;
+ }
+
+ [m_handler requestPermission:permission withCallback:[=](Qt::PermissionStatus status) {
+ // In case the callback comes in on a secondary thread we need to marshal it
+ // back to the main thread. And if it doesn't, we still want to propagate it
+ // via an event, to avoid any GCD locks deadlocking the application on iOS
+ // if the user responds to the result by running a nested event loop.
+ // Luckily Qt::QueuedConnection gives us exactly what we need.
+ QMetaObject::invokeMethod(this, "permissionUpdated", Qt::QueuedConnection,
+ Q_ARG(Qt::PermissionStatus, status), Q_ARG(PermissionCallback, callback));
+ }];
+}
+
+void QDarwinPermissionPlugin::permissionUpdated(Qt::PermissionStatus status, const PermissionCallback &callback)
+{
+ callback(status);
+}
+
+bool QDarwinPermissionPlugin::verifyUsageDescriptions(const QPermission &permission)
+{
+ // FIXME: Look up the responsible process and inspect that,
+ // as that's what needs to have the usage descriptions.
+ // FIXME: Verify entitlements if the process is sandboxed.
+ auto *infoDictionary = NSBundle.mainBundle.infoDictionary;
+ for (auto description : [m_handler usageDescriptionsFor:permission]) {
+ if (!infoDictionary[description.toNSString()]) {
+ qCWarning(lcPermissions) <<
+ "Requesting" << permission.type().name() <<
+ "requires" << description << "in Info.plist";
+ return false;
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+@implementation QDarwinPermissionHandler
+
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ Q_UNREACHABLE(); // All handlers should at least provide a check
+}
+
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ Q_UNUSED(permission);
+ qCWarning(lcPermissions).nospace() << "Could not request " << permission.type().name() << ". "
+ << "Please make sure you have included the required usage description in your Info.plist";
+ callback(Qt::PermissionStatus::Denied);
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+ return {};
+}
+
+@end
+
+#include "moc_qdarwinpermissionplugin_p.cpp"
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_bluetooth.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin_bluetooth.mm
new file mode 100644
index 0000000000..0cd375561f
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_bluetooth.mm
@@ -0,0 +1,86 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p_p.h"
+
+#include <deque>
+
+#include <CoreBluetooth/CoreBluetooth.h>
+
+@interface QDarwinBluetoothPermissionHandler () <CBCentralManagerDelegate>
+@property (nonatomic, retain) CBCentralManager *manager;
+@end
+
+@implementation QDarwinBluetoothPermissionHandler {
+ std::deque<PermissionCallback> m_callbacks;
+}
+
+- (instancetype)init
+{
+ if ((self = [super init]))
+ self.manager = nil;
+
+ return self;
+}
+
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return [self currentStatus];
+}
+
+- (Qt::PermissionStatus)currentStatus
+{
+ auto status = CBCentralManager.authorization;
+ switch (status) {
+ case CBManagerAuthorizationNotDetermined:
+ return Qt::PermissionStatus::Undetermined;
+ case CBManagerAuthorizationRestricted:
+ case CBManagerAuthorizationDenied:
+ return Qt::PermissionStatus::Denied;
+ case CBManagerAuthorizationAllowedAlways:
+ return Qt::PermissionStatus::Granted;
+ }
+
+ qCWarning(lcPermissions) << "Unknown permission status" << status << "detected in" << self;
+ return Qt::PermissionStatus::Denied;
+}
+
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ m_callbacks.push_back(callback);
+ if (!self.manager) {
+ self.manager = [[[CBCentralManager alloc]
+ initWithDelegate:self queue:dispatch_get_main_queue()] autorelease];
+ }
+}
+
+- (void)centralManagerDidUpdateState:(CBCentralManager *)manager
+{
+ Q_ASSERT(manager == self.manager);
+ Q_ASSERT(!m_callbacks.empty());
+
+ auto status = [self currentStatus];
+
+ for (auto callback : m_callbacks)
+ callback(status);
+
+ m_callbacks = {};
+ self.manager = nil;
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+ Q_UNUSED(permission);
+#ifdef Q_OS_MACOS
+ if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur)
+#endif
+ {
+ return { "NSBluetoothAlwaysUsageDescription" };
+ }
+
+ return {};
+}
+@end
+
+#include "moc_qdarwinpermissionplugin_p_p.cpp"
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_calendar.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin_calendar.mm
new file mode 100644
index 0000000000..a3eddd6d8f
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_calendar.mm
@@ -0,0 +1,71 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p_p.h"
+
+#include <EventKit/EventKit.h>
+
+@interface QDarwinCalendarPermissionHandler ()
+@property (nonatomic, retain) EKEventStore *eventStore;
+@end
+
+@implementation QDarwinCalendarPermissionHandler
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return [self currentStatus];
+}
+
+- (Qt::PermissionStatus)currentStatus
+{
+ auto status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
+ switch (status) {
+ case EKAuthorizationStatusNotDetermined:
+ return Qt::PermissionStatus::Undetermined;
+ case EKAuthorizationStatusRestricted:
+ case EKAuthorizationStatusDenied:
+ return Qt::PermissionStatus::Denied;
+ case EKAuthorizationStatusAuthorized:
+ return Qt::PermissionStatus::Granted;
+#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(140000, 170000)
+ case EKAuthorizationStatusWriteOnly:
+ // FIXME: Add WriteOnly AccessMode
+ return Qt::PermissionStatus::Denied;
+#endif
+ }
+
+ qCWarning(lcPermissions) << "Unknown permission status" << status << "detected in" << self;
+ return Qt::PermissionStatus::Denied;
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return { "NSCalendarsUsageDescription" };
+}
+
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ if (!self.eventStore) {
+ // Note: Creating the EKEventStore results in warnings in the
+ // console about "An error occurred in the persistent store".
+ // This seems like a EventKit API bug.
+ self.eventStore = [[EKEventStore new] autorelease];
+ }
+
+ [self.eventStore requestAccessToEntityType:EKEntityTypeEvent
+ completion:^(BOOL granted, NSError * _Nullable error) {
+ Q_UNUSED(granted); // We use status instead
+ // Permission denied will result in an error, which we don't
+ // want to report/log, so we ignore the error and just report
+ // the status.
+ Q_UNUSED(error);
+
+ callback([self currentStatus]);
+ }
+ ];
+}
+
+@end
+
+#include "moc_qdarwinpermissionplugin_p_p.cpp"
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_camera.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin_camera.mm
new file mode 100644
index 0000000000..51c517d6f3
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_camera.mm
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p_p.h"
+
+#include <AVFoundation/AVFoundation.h>
+
+QT_DEFINE_PERMISSION_STATUS_CONVERTER(AVAuthorizationStatus);
+
+#ifndef BUILDING_PERMISSION_REQUEST
+
+@implementation QDarwinCameraPermissionHandler
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ const auto status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+ return nativeStatusToQtStatus(status);
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return { "NSCameraUsageDescription" };
+}
+@end
+
+#include "moc_qdarwinpermissionplugin_p_p.cpp"
+
+#else // Building request
+
+@implementation QDarwinCameraPermissionHandler (Request)
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted)
+ {
+ Q_UNUSED(granted); // We use status instead
+ const auto status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+ callback(nativeStatusToQtStatus(status));
+ }];
+}
+@end
+
+#endif // BUILDING_PERMISSION_REQUEST
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_contacts.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin_contacts.mm
new file mode 100644
index 0000000000..3221b6dc1d
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_contacts.mm
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p_p.h"
+
+#include <Contacts/Contacts.h>
+
+QT_DEFINE_PERMISSION_STATUS_CONVERTER(CNAuthorizationStatus);
+
+@interface QDarwinContactsPermissionHandler ()
+@property (nonatomic, retain) CNContactStore *contactStore;
+@end
+
+@implementation QDarwinContactsPermissionHandler
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return [self currentStatus];
+}
+
+- (Qt::PermissionStatus)currentStatus
+{
+ const auto status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
+ return nativeStatusToQtStatus(status);
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return { "NSContactsUsageDescription" };
+}
+
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ if (!self.contactStore) {
+ // Note: Creating the CNContactStore results in warnings in the
+ // console about "Attempted to register account monitor for types
+ // client is not authorized to access", mentioning CardDAV, LDAP,
+ // and Exchange. This seems like a Contacts API bug.
+ self.contactStore = [[CNContactStore new] autorelease];
+ }
+
+ [self.contactStore requestAccessForEntityType:CNEntityTypeContacts
+ completionHandler:^(BOOL granted, NSError * _Nullable error) {
+ Q_UNUSED(granted); // We use status instead
+ // Permission denied will result in an error, which we don't
+ // want to report/log, so we ignore the error and just report
+ // the status.
+ Q_UNUSED(error);
+
+ callback([self currentStatus]);
+ }
+ ];
+}
+
+@end
+
+#include "moc_qdarwinpermissionplugin_p_p.cpp"
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_location.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin_location.mm
new file mode 100644
index 0000000000..1d32c0fcac
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_location.mm
@@ -0,0 +1,263 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p_p.h"
+
+#include <deque>
+
+#include <CoreLocation/CoreLocation.h>
+
+@interface QDarwinLocationPermissionHandler () <CLLocationManagerDelegate>
+@property (nonatomic, retain) CLLocationManager *manager;
+@end
+
+Q_LOGGING_CATEGORY(lcLocationPermission, "qt.permissions.location");
+
+void warmUpLocationServices()
+{
+ // After creating a CLLocationManager the authorizationStatus
+ // will initially be kCLAuthorizationStatusNotDetermined. The
+ // status will then update to an actual status if the app was
+ // previously authorized/denied once the location services
+ // do some initial book-keeping in the background. By kicking
+ // off a CLLocationManager early on here, we ensure that by
+ // the time the user calls checkPermission the authorization
+ // status has been resolved.
+ qCDebug(lcLocationPermission) << "Warming up location services";
+ [[CLLocationManager new] release];
+}
+
+Q_CONSTRUCTOR_FUNCTION(warmUpLocationServices);
+
+struct PermissionRequest
+{
+ QPermission permission;
+ PermissionCallback callback;
+};
+
+@implementation QDarwinLocationPermissionHandler {
+ std::deque<PermissionRequest> m_requests;
+}
+
+- (instancetype)init
+{
+ if ((self = [super init])) {
+ // The delegate callbacks will come in on the thread that
+ // the CLLocationManager is created on, and we want those
+ // to come in on the main thread, so we defer creation
+ // of the manger until requestPermission, where we know
+ // we are on the main thread.
+ self.manager = nil;
+ }
+
+ return self;
+}
+
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ const auto locationPermission = *permission.value<QLocationPermission>();
+
+ auto status = [self authorizationStatus:locationPermission];
+ if (status != Qt::PermissionStatus::Granted)
+ return status;
+
+ return [self accuracyAuthorization:locationPermission];
+}
+
+- (Qt::PermissionStatus)authorizationStatus:(QLocationPermission)permission
+{
+ NSString *bundleIdentifier = NSBundle.mainBundle.bundleIdentifier;
+ if (!bundleIdentifier || !bundleIdentifier.length) {
+ qCWarning(lcLocationPermission) << "Missing bundle identifier"
+ << "in Info.plist. Can not use location permissions.";
+ return Qt::PermissionStatus::Denied;
+ }
+
+#if defined(Q_OS_VISIONOS)
+ if (permission.availability() == QLocationPermission::Always)
+ return Qt::PermissionStatus::Denied;
+#endif
+
+ auto status = [self authorizationStatus];
+ switch (status) {
+ case kCLAuthorizationStatusRestricted:
+ case kCLAuthorizationStatusDenied:
+ return Qt::PermissionStatus::Denied;
+ case kCLAuthorizationStatusNotDetermined:
+ return Qt::PermissionStatus::Undetermined;
+#if !defined(Q_OS_VISIONOS)
+ case kCLAuthorizationStatusAuthorizedAlways:
+ return Qt::PermissionStatus::Granted;
+#endif
+#if defined(Q_OS_IOS) || defined(Q_OS_VISIONOS)
+ case kCLAuthorizationStatusAuthorizedWhenInUse:
+ if (permission.availability() == QLocationPermission::Always)
+ return Qt::PermissionStatus::Denied;
+ return Qt::PermissionStatus::Granted;
+#endif
+ }
+
+ qCWarning(lcPermissions) << "Unknown permission status" << status << "detected in" << self;
+ return Qt::PermissionStatus::Denied;
+}
+
+- (CLAuthorizationStatus)authorizationStatus
+{
+ if (self.manager) {
+ if (@available(macOS 11, iOS 14, *))
+ return self.manager.authorizationStatus;
+ }
+
+ return QT_IGNORE_DEPRECATIONS(CLLocationManager.authorizationStatus);
+}
+
+- (Qt::PermissionStatus)accuracyAuthorization:(QLocationPermission)permission
+{
+ auto status = CLAccuracyAuthorizationReducedAccuracy;
+ if (@available(macOS 11, iOS 14, *))
+ status = self.manager.accuracyAuthorization;
+
+ switch (status) {
+ case CLAccuracyAuthorizationFullAccuracy:
+ return Qt::PermissionStatus::Granted;
+ case CLAccuracyAuthorizationReducedAccuracy:
+ if (permission.accuracy() == QLocationPermission::Approximate)
+ return Qt::PermissionStatus::Granted;
+ else
+ return Qt::PermissionStatus::Denied;
+ }
+
+ qCWarning(lcPermissions) << "Unknown accuracy status" << status << "detected in" << self;
+ return Qt::PermissionStatus::Denied;
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+#if defined(Q_OS_MACOS)
+ return { "NSLocationUsageDescription" };
+#else // iOS 11 and above
+ QStringList usageDescriptions = { "NSLocationWhenInUseUsageDescription" };
+ const auto locationPermission = *permission.value<QLocationPermission>();
+ if (locationPermission.availability() == QLocationPermission::Always)
+ usageDescriptions << "NSLocationAlwaysAndWhenInUseUsageDescription";
+ return usageDescriptions;
+#endif
+}
+
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ const bool requestAlreadyInFlight = !m_requests.empty();
+
+ m_requests.push_back({ permission, callback });
+
+ if (requestAlreadyInFlight) {
+ qCDebug(lcLocationPermission).nospace() << "Already processing "
+ << m_requests.front().permission << ". Deferring request";
+ } else {
+ [self requestQueuedPermission];
+ }
+}
+
+- (void)requestQueuedPermission
+{
+ Q_ASSERT(!m_requests.empty());
+ const auto permission = m_requests.front().permission;
+
+ qCDebug(lcLocationPermission) << "Requesting" << permission;
+
+ if (!self.manager) {
+ self.manager = [[CLLocationManager new] autorelease];
+ self.manager.delegate = self;
+ }
+
+ const auto locationPermission = *permission.value<QLocationPermission>();
+ switch (locationPermission.availability()) {
+ case QLocationPermission::WhenInUse:
+ // The documentation specifies that requestWhenInUseAuthorization can
+ // only be called when the current authorization status is undetermined.
+ switch ([self authorizationStatus]) {
+ case kCLAuthorizationStatusNotDetermined:
+ [self.manager requestWhenInUseAuthorization];
+ break;
+ default:
+ [self deliverResult];
+ }
+ break;
+ case QLocationPermission::Always:
+#if defined(Q_OS_VISIONOS)
+ [self deliverResult]; // Not supported
+#else
+ // The documentation specifies that requestAlwaysAuthorization can only
+ // be called when the current authorization status is either undetermined,
+ // or authorized when in use.
+ switch ([self authorizationStatus]) {
+ case kCLAuthorizationStatusNotDetermined:
+ [self.manager requestAlwaysAuthorization];
+ break;
+#ifdef Q_OS_IOS
+ case kCLAuthorizationStatusAuthorizedWhenInUse:
+ // Unfortunately when asking for AlwaysAuthorization when in
+ // the WhenInUse state, to "upgrade" the permission, the iOS
+ // location system will not give us a callback if the user
+ // denies the request, leaving us hanging without a way to
+ // respond to the permission request.
+ qCWarning(lcLocationPermission) << "QLocationPermission::WhenInUse"
+ << "can not be upgraded to QLocationPermission::Always on iOS."
+ << "Please request QLocationPermission::Always directly.";
+ Q_FALLTHROUGH();
+#endif
+ default:
+ [self deliverResult];
+ }
+#endif
+ break;
+ }
+}
+
+- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
+{
+ qCDebug(lcLocationPermission) << "Processing authorization"
+ << "update with status" << status;
+
+ if (m_requests.empty()) {
+ qCDebug(lcLocationPermission) << "No requests in flight. Ignoring.";
+ return;
+ }
+
+ if (status == kCLAuthorizationStatusNotDetermined) {
+ // Initializing a CLLocationManager will result in an initial
+ // callback to the delegate even before we've requested any
+ // location permissions. Normally we would ignore this callback
+ // due to the request queue check above, but if this callback
+ // comes in after the application has requested a permission
+ // we don't want to report the undetermined status, but rather
+ // wait for the actual result to come in.
+ qCDebug(lcLocationPermission) << "Ignoring delegate callback"
+ << "with status kCLAuthorizationStatusNotDetermined";
+ return;
+ }
+
+ [self deliverResult];
+}
+
+- (void)deliverResult
+{
+ auto request = m_requests.front();
+ m_requests.pop_front();
+
+ auto status = [self checkPermission:request.permission];
+ qCDebug(lcLocationPermission) << "Result for"
+ << request.permission << "was" << status;
+
+ request.callback(status);
+
+ if (!m_requests.empty()) {
+ qCDebug(lcLocationPermission) << "Still have"
+ << m_requests.size() << "deferred request(s)";
+ [self requestQueuedPermission];
+ }
+}
+
+@end
+
+#include "moc_qdarwinpermissionplugin_p_p.cpp"
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_microphone.mm b/src/corelib/platform/darwin/qdarwinpermissionplugin_microphone.mm
new file mode 100644
index 0000000000..5dc434309d
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_microphone.mm
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdarwinpermissionplugin_p_p.h"
+
+#include <AVFoundation/AVFoundation.h>
+
+QT_DEFINE_PERMISSION_STATUS_CONVERTER(AVAuthorizationStatus);
+
+#ifndef BUILDING_PERMISSION_REQUEST
+
+@implementation QDarwinMicrophonePermissionHandler
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission
+{
+ const auto status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
+ return nativeStatusToQtStatus(status);
+}
+
+- (QStringList)usageDescriptionsFor:(QPermission)permission
+{
+ Q_UNUSED(permission);
+ return { "NSMicrophoneUsageDescription" };
+}
+@end
+
+#include "moc_qdarwinpermissionplugin_p_p.cpp"
+
+#else // Building request
+
+@implementation QDarwinMicrophonePermissionHandler (Request)
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback
+{
+ [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted)
+ {
+ Q_UNUSED(granted); // We use status instead
+ const auto status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
+ callback(nativeStatusToQtStatus(status));
+ }];
+}
+@end
+
+#endif // BUILDING_PERMISSION_REQUEST
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_p.h b/src/corelib/platform/darwin/qdarwinpermissionplugin_p.h
new file mode 100644
index 0000000000..03530133ad
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_p.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QDARWINPERMISSIONPLUGIN_P_H
+#define QDARWINPERMISSIONPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header file may change
+// from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/private/qpermissions_p.h>
+#include <QtCore/private/qcore_mac_p.h>
+
+#if defined(__OBJC__)
+#include <Foundation/NSObject.h>
+#endif
+
+QT_USE_NAMESPACE
+
+using namespace QPermissions::Private;
+
+#if defined(__OBJC__)
+Q_CORE_EXPORT
+#endif
+QT_DECLARE_NAMESPACED_OBJC_INTERFACE(QDarwinPermissionHandler, NSObject
+- (Qt::PermissionStatus)checkPermission:(QPermission)permission;
+- (void)requestPermission:(QPermission)permission withCallback:(PermissionCallback)callback;
+- (QStringList)usageDescriptionsFor:(QPermission)permission;
+)
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QDarwinPermissionPlugin : public QPermissionPlugin
+{
+ Q_OBJECT
+public:
+ QDarwinPermissionPlugin(QDarwinPermissionHandler *handler);
+ ~QDarwinPermissionPlugin();
+
+ Qt::PermissionStatus checkPermission(const QPermission &permission) override;
+ void requestPermission(const QPermission &permission, const PermissionCallback &callback) override;
+
+private:
+ Q_SLOT void permissionUpdated(Qt::PermissionStatus status, const PermissionCallback &callback);
+ bool verifyUsageDescriptions(const QPermission &permission);
+ QDarwinPermissionHandler *m_handler = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDARWINPERMISSIONPLUGIN_P_H
diff --git a/src/corelib/platform/darwin/qdarwinpermissionplugin_p_p.h b/src/corelib/platform/darwin/qdarwinpermissionplugin_p_p.h
new file mode 100644
index 0000000000..649af06507
--- /dev/null
+++ b/src/corelib/platform/darwin/qdarwinpermissionplugin_p_p.h
@@ -0,0 +1,104 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QDARWINPERMISSIONPLUGIN_P_P_H
+#define QDARWINPERMISSIONPLUGIN_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header file may change
+// from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if !defined(QT_DARWIN_PERMISSION_PLUGIN)
+#error "This header should only be included from permission plugins"
+#endif
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/private/qpermissions_p.h>
+#include <QtCore/private/qcore_mac_p.h>
+
+#include "qdarwinpermissionplugin_p.h"
+
+using namespace QPermissions::Private;
+
+#ifndef QT_JOIN
+#define QT_JOIN_IMPL(A, B) A ## B
+#define QT_JOIN(A, B) QT_JOIN_IMPL(A, B)
+#endif
+
+#define PERMISSION_PLUGIN_NAME(SUFFIX) \
+ QT_JOIN(QT_JOIN(QT_JOIN( \
+ QDarwin, QT_DARWIN_PERMISSION_PLUGIN), Permission), SUFFIX)
+
+#define PERMISSION_PLUGIN_CLASSNAME PERMISSION_PLUGIN_NAME(Plugin)
+#define PERMISSION_PLUGIN_HANDLER PERMISSION_PLUGIN_NAME(Handler)
+
+QT_DECLARE_NAMESPACED_OBJC_INTERFACE(
+ PERMISSION_PLUGIN_HANDLER,
+ QDarwinPermissionHandler
+)
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT PERMISSION_PLUGIN_CLASSNAME : public QDarwinPermissionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(
+ IID QPermissionPluginInterface_iid
+ FILE "QDarwin" QT_STRINGIFY(QT_DARWIN_PERMISSION_PLUGIN) "PermissionPlugin.json")
+public:
+ PERMISSION_PLUGIN_CLASSNAME()
+ : QDarwinPermissionPlugin([[PERMISSION_PLUGIN_HANDLER alloc] init])
+ {}
+};
+
+QT_END_NAMESPACE
+
+// Request
+#if defined(BUILDING_PERMISSION_REQUEST)
+extern "C" void PERMISSION_PLUGIN_NAME(Request)() {}
+#endif
+
+// -------------------------------------------------------
+
+namespace {
+template <typename NativeStatus>
+struct NativeStatusHelper;
+
+template <typename NativeStatus>
+Qt::PermissionStatus nativeStatusToQtStatus(NativeStatus status)
+{
+ using Converter = NativeStatusHelper<NativeStatus>;
+ switch (status) {
+ case Converter::Authorized:
+ return Qt::PermissionStatus::Granted;
+ case Converter::Denied:
+ case Converter::Restricted:
+ return Qt::PermissionStatus::Denied;
+ case Converter::Undetermined:
+ return Qt::PermissionStatus::Undetermined;
+ }
+ qCWarning(lcPermissions) << "Unknown permission status" << status << "detected in"
+ << QT_STRINGIFY(QT_DARWIN_PERMISSION_PLUGIN);
+ return Qt::PermissionStatus::Denied;
+}
+} // namespace
+
+#define QT_DEFINE_PERMISSION_STATUS_CONVERTER(NativeStatus) \
+namespace { template<> \
+struct NativeStatusHelper<NativeStatus> \
+{\
+ enum { \
+ Authorized = NativeStatus##Authorized, \
+ Denied = NativeStatus##Denied, \
+ Restricted = NativeStatus##Restricted, \
+ Undetermined = NativeStatus##NotDetermined \
+ }; \
+}; }
+
+#endif // QDARWINPERMISSIONPLUGIN_P_P_H
diff --git a/src/corelib/platform/ios/PrivacyInfo.xcprivacy b/src/corelib/platform/ios/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..5f84a229a5
--- /dev/null
+++ b/src/corelib/platform/ios/PrivacyInfo.xcprivacy
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSPrivacyTracking</key>
+ <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
+ <key>NSPrivacyTrackingDomains</key>
+ <array/>
+ <key>NSPrivacyAccessedAPITypes</key>
+ <array>
+ <dict>
+ <key>NSPrivacyAccessedAPIType</key>
+ <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
+ <key>NSPrivacyAccessedAPITypeReasons</key>
+ <array>
+ <string>0A2A.1</string> <!-- QFileInfo -->
+ </array>
+ </dict>
+ <dict>
+ <key>NSPrivacyAccessedAPIType</key>
+ <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
+ <key>NSPrivacyAccessedAPITypeReasons</key>
+ <array>
+ <string>85F4.1</string> <!-- QStorageInfo -->
+ </array>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/src/corelib/platform/platform.pri b/src/corelib/platform/platform.pri
deleted file mode 100644
index 1fe2db81b0..0000000000
--- a/src/corelib/platform/platform.pri
+++ /dev/null
@@ -1 +0,0 @@
-wasm:include(wasm/wasm.pri)
diff --git a/src/corelib/platform/wasm/qstdweb.cpp b/src/corelib/platform/wasm/qstdweb.cpp
index 198ce897ca..75e76a6806 100644
--- a/src/corelib/platform/wasm/qstdweb.cpp
+++ b/src/corelib/platform/wasm/qstdweb.cpp
@@ -1,53 +1,384 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstdweb_p.h"
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qmimedata.h>
+
#include <emscripten/bind.h>
+#include <emscripten/emscripten.h>
+#include <emscripten/html5.h>
+#include <emscripten/threading.h>
+
#include <cstdint>
#include <iostream>
+#include <unordered_map>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
namespace qstdweb {
+static void usePotentialyUnusedSymbols()
+{
+ // Using this adds a reference on JSEvents and specialHTMLTargets which are always exported.
+ // This hack is needed as it is currently impossible to specify a dollar sign in
+ // target_link_options. The following is impossible:
+ // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$JSEvents
+ // TODO(mikolajboc): QTBUG-108444, review this when cmake gets fixed.
+ // Volatile is to make this unoptimizable, so that the function is referenced, but is not
+ // called at runtime.
+ volatile bool doIt = false;
+ if (doIt)
+ emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 0, NULL);
+}
+
+Q_CONSTRUCTOR_FUNCTION(usePotentialyUnusedSymbols)
typedef double uint53_t; // see Number.MAX_SAFE_INTEGER
+namespace {
+// Reads file in chunks in order to avoid holding two copies in memory at the same time
+struct ChunkedFileReader
+{
+public:
+ static void read(File file, char *buffer, uint32_t offset, uint32_t end,
+ std::function<void()> onCompleted)
+ {
+ (new ChunkedFileReader(end, std::move(onCompleted), std::move(file)))
+ ->readNextChunk(offset, buffer);
+ }
+
+private:
+ ChunkedFileReader(uint32_t end, std::function<void()> onCompleted, File file)
+ : end(end), onCompleted(std::move(onCompleted)), file(std::move(file))
+ {
+ }
+
+ void readNextChunk(uint32_t chunkBegin, char *chunkBuffer)
+ {
+ // Copy current chunk from JS memory to Wasm memory
+ qstdweb::ArrayBuffer result = fileReader.result();
+ qstdweb::Uint8Array(result).copyTo(chunkBuffer);
+
+ // Read next chunk if not at buffer end
+ const uint32_t nextChunkBegin = std::min(chunkBegin + result.byteLength(), end);
+ if (nextChunkBegin == end) {
+ onCompleted();
+ delete this;
+ return;
+ }
+ char *nextChunkBuffer = chunkBuffer + result.byteLength();
+ fileReader.onLoad([this, nextChunkBegin, nextChunkBuffer](emscripten::val) {
+ readNextChunk(nextChunkBegin, nextChunkBuffer);
+ });
+ const uint32_t nextChunkEnd = std::min(nextChunkBegin + chunkSize, end);
+ qstdweb::Blob blob = file.slice(nextChunkBegin, nextChunkEnd);
+ fileReader.readAsArrayBuffer(blob);
+ }
+
+ static constexpr uint32_t chunkSize = 256 * 1024;
+
+ qstdweb::FileReader fileReader;
+ uint32_t end;
+ std::function<void()> onCompleted;
+ File file;
+};
+
+enum class CallbackType {
+ Then,
+ Catch,
+ Finally,
+};
+
+void validateCallbacks(const PromiseCallbacks& callbacks) {
+ Q_ASSERT(!!callbacks.catchFunc || !!callbacks.finallyFunc || !!callbacks.thenFunc);
+}
+
+using ThunkId = int;
+
+#define THUNK_NAME(type, i) callbackThunk##type##i
+
+// A resource pool for exported promise thunk functions. ThunkPool::poolSize sets of
+// 3 promise thunks (then, catch, finally) are exported and can be used by promises
+// in C++. To allocate a thunk, call allocateThunk. When a thunk is ready for use,
+// a callback with allocation RAII object ThunkAllocation will be returned. Deleting
+// the object frees the thunk and automatically makes any pending allocateThunk call
+// run its callback with a free thunk slot.
+class ThunkPool {
+public:
+ static constexpr size_t poolSize = 4;
+
+ // An allocation for a thunk function set. Following the RAII pattern, destruction of
+ // this objects frees a corresponding thunk pool entry.
+ // To actually make the thunks react to a js promise's callbacks, call bindToPromise.
+ class ThunkAllocation {
+ public:
+ ThunkAllocation(int thunkId, ThunkPool* pool) : m_thunkId(thunkId), m_pool(pool) {}
+ ~ThunkAllocation() {
+ m_pool->free(m_thunkId);
+ }
+
+ // The id of the underlaying thunk set
+ int id() const { return m_thunkId; }
+
+ // Binds the corresponding thunk set to the js promise 'target'.
+ void bindToPromise(emscripten::val target, const PromiseCallbacks& callbacks) {
+ using namespace emscripten;
+
+ if (Q_LIKELY(callbacks.thenFunc)) {
+ target = target.call<val>(
+ "then",
+ emscripten::val::module_property(thunkName(CallbackType::Then, id()).data()));
+ }
+ if (callbacks.catchFunc) {
+ target = target.call<val>(
+ "catch",
+ emscripten::val::module_property(thunkName(CallbackType::Catch, id()).data()));
+ }
+ // Guarantee the invocation of at least one callback by always
+ // registering 'finally'. This is required by WebPromiseManager
+ // design
+ target = target.call<val>(
+ "finally", emscripten::val::module_property(
+ thunkName(CallbackType::Finally, id()).data()));
+ }
+
+ private:
+ int m_thunkId;
+ ThunkPool* m_pool;
+ };
+
+ ThunkPool() {
+ std::iota(m_free.begin(), m_free.end(), 0);
+ }
+
+ void setThunkCallback(std::function<void(int, CallbackType, emscripten::val)> callback) {
+ m_callback = std::move(callback);
+ }
+
+ void allocateThunk(std::function<void(std::unique_ptr<ThunkAllocation>)> onAllocated) {
+ if (m_free.empty()) {
+ m_pendingAllocations.push_back(std::move(onAllocated));
+ return;
+ }
+
+ const int thunkId = m_free.back();
+ m_free.pop_back();
+ onAllocated(std::make_unique<ThunkAllocation>(thunkId, this));
+ }
+
+ static QByteArray thunkName(CallbackType type, size_t i) {
+ return QStringLiteral("promiseCallback%1%2").arg([type]() -> QString {
+ switch (type) {
+ case CallbackType::Then:
+ return QStringLiteral("Then");
+ case CallbackType::Catch:
+ return QStringLiteral("Catch");
+ case CallbackType::Finally:
+ return QStringLiteral("Finally");
+ }
+ }()).arg(i).toLatin1();
+ }
+
+ static ThunkPool* get();
+
+#define THUNK(i) \
+ static void THUNK_NAME(Then, i)(emscripten::val result) \
+ { \
+ get()->onThunkCalled(i, CallbackType::Then, std::move(result)); \
+ } \
+ static void THUNK_NAME(Catch, i)(emscripten::val result) \
+ { \
+ get()->onThunkCalled(i, CallbackType::Catch, std::move(result)); \
+ } \
+ static void THUNK_NAME(Finally, i)() \
+ { \
+ get()->onThunkCalled(i, CallbackType::Finally, emscripten::val::undefined()); \
+ }
+
+ THUNK(0);
+ THUNK(1);
+ THUNK(2);
+ THUNK(3);
+
+#undef THUNK
+
+private:
+ void onThunkCalled(int index, CallbackType type, emscripten::val result) {
+ m_callback(index, type, std::move(result));
+ }
+
+ void free(int thunkId) {
+ if (m_pendingAllocations.empty()) {
+ // Return the thunk to the free pool
+ m_free.push_back(thunkId);
+ return;
+ }
+
+ // Take the next enqueued allocation and reuse the thunk
+ auto allocation = m_pendingAllocations.back();
+ m_pendingAllocations.pop_back();
+ allocation(std::make_unique<ThunkAllocation>(thunkId, this));
+ }
+
+ std::function<void(int, CallbackType, emscripten::val)> m_callback;
+
+ std::vector<int> m_free = std::vector<int>(poolSize);
+ std::vector<std::function<void(std::unique_ptr<ThunkAllocation>)>> m_pendingAllocations;
+};
+
+Q_GLOBAL_STATIC(ThunkPool, g_thunkPool)
+
+ThunkPool* ThunkPool::get()
+{
+ return g_thunkPool;
+}
+
+#define CALLBACK_BINDING(i) \
+ emscripten::function(ThunkPool::thunkName(CallbackType::Then, i).data(), \
+ &ThunkPool::THUNK_NAME(Then, i)); \
+ emscripten::function(ThunkPool::thunkName(CallbackType::Catch, i).data(), \
+ &ThunkPool::THUNK_NAME(Catch, i)); \
+ emscripten::function(ThunkPool::thunkName(CallbackType::Finally, i).data(), \
+ &ThunkPool::THUNK_NAME(Finally, i));
+
+EMSCRIPTEN_BINDINGS(qtThunkPool) {
+ CALLBACK_BINDING(0)
+ CALLBACK_BINDING(1)
+ CALLBACK_BINDING(2)
+ CALLBACK_BINDING(3)
+}
+
+#undef CALLBACK_BINDING
+#undef THUNK_NAME
+
+class WebPromiseManager
+{
+public:
+ WebPromiseManager();
+ ~WebPromiseManager();
+
+ WebPromiseManager(const WebPromiseManager& other) = delete;
+ WebPromiseManager(WebPromiseManager&& other) = delete;
+ WebPromiseManager& operator=(const WebPromiseManager& other) = delete;
+ WebPromiseManager& operator=(WebPromiseManager&& other) = delete;
+
+ void adoptPromise(emscripten::val target, PromiseCallbacks callbacks);
+
+ static WebPromiseManager* get();
+
+private:
+ struct RegistryEntry {
+ PromiseCallbacks callbacks;
+ std::unique_ptr<ThunkPool::ThunkAllocation> allocation;
+ };
+
+ static std::optional<CallbackType> parseCallbackType(emscripten::val callbackType);
+
+ void subscribeToJsPromiseCallbacks(int i, const PromiseCallbacks& callbacks, emscripten::val jsContextfulPromise);
+ void promiseThunkCallback(int i, CallbackType type, emscripten::val result);
+
+ void registerPromise(std::unique_ptr<ThunkPool::ThunkAllocation> allocation, PromiseCallbacks promise);
+ void unregisterPromise(ThunkId context);
+
+ std::array<RegistryEntry, ThunkPool::poolSize> m_promiseRegistry;
+};
+
+Q_GLOBAL_STATIC(WebPromiseManager, webPromiseManager)
+
+WebPromiseManager::WebPromiseManager()
+{
+ ThunkPool::get()->setThunkCallback(std::bind(
+ &WebPromiseManager::promiseThunkCallback, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+}
+
+std::optional<CallbackType>
+WebPromiseManager::parseCallbackType(emscripten::val callbackType)
+{
+ if (!callbackType.isString())
+ return std::nullopt;
+
+ const std::string data = callbackType.as<std::string>();
+ if (data == "then")
+ return CallbackType::Then;
+ if (data == "catch")
+ return CallbackType::Catch;
+ if (data == "finally")
+ return CallbackType::Finally;
+ return std::nullopt;
+}
+
+WebPromiseManager::~WebPromiseManager() = default;
+
+WebPromiseManager *WebPromiseManager::get()
+{
+ return webPromiseManager();
+}
+
+void WebPromiseManager::promiseThunkCallback(int context, CallbackType type, emscripten::val result)
+{
+ auto* promiseState = &m_promiseRegistry[context];
+
+ auto* callbacks = &promiseState->callbacks;
+ switch (type) {
+ case CallbackType::Then:
+ callbacks->thenFunc(result);
+ break;
+ case CallbackType::Catch:
+ callbacks->catchFunc(result);
+ break;
+ case CallbackType::Finally:
+ // Final callback may be empty, used solely for promise unregistration
+ if (callbacks->finallyFunc) {
+ callbacks->finallyFunc();
+ }
+ unregisterPromise(context);
+ break;
+ }
+}
+
+void WebPromiseManager::registerPromise(
+ std::unique_ptr<ThunkPool::ThunkAllocation> allocation,
+ PromiseCallbacks callbacks)
+{
+ const ThunkId id = allocation->id();
+ m_promiseRegistry[id] =
+ RegistryEntry {std::move(callbacks), std::move(allocation)};
+}
+
+void WebPromiseManager::unregisterPromise(ThunkId context)
+{
+ m_promiseRegistry[context] = {};
+}
+
+void WebPromiseManager::adoptPromise(emscripten::val target, PromiseCallbacks callbacks) {
+ ThunkPool::get()->allocateThunk([=](std::unique_ptr<ThunkPool::ThunkAllocation> allocation) {
+ allocation->bindToPromise(std::move(target), callbacks);
+ registerPromise(std::move(allocation), std::move(callbacks));
+ });
+}
+#if defined(QT_STATIC)
+
+EM_JS(bool, jsHaveAsyncify, (), { return typeof Asyncify !== "undefined"; });
+EM_JS(bool, jsHaveJspi, (),
+ { return typeof Asyncify !== "undefined" && !!Asyncify.makeAsyncFunction && !!WebAssembly.Function; });
+
+#else
+
+bool jsHaveAsyncify() { return false; }
+bool jsHaveJspi() { return false; }
+
+#endif
+} // namespace
+
+ArrayBuffer::ArrayBuffer(uint32_t size)
+{
+ m_arrayBuffer = emscripten::val::global("ArrayBuffer").new_(size);
+}
ArrayBuffer::ArrayBuffer(const emscripten::val &arrayBuffer)
:m_arrayBuffer(arrayBuffer)
@@ -63,23 +394,92 @@ uint32_t ArrayBuffer::byteLength() const
return m_arrayBuffer["byteLength"].as<uint32_t>();
}
+ArrayBuffer ArrayBuffer::slice(uint32_t begin, uint32_t end) const
+{
+ return ArrayBuffer(m_arrayBuffer.call<emscripten::val>("slice", begin, end));
+}
+
+emscripten::val ArrayBuffer::val() const
+{
+ return m_arrayBuffer;
+}
+
Blob::Blob(const emscripten::val &blob)
:m_blob(blob)
{
}
+Blob Blob::fromArrayBuffer(const ArrayBuffer &arrayBuffer)
+{
+ auto array = emscripten::val::array();
+ array.call<void>("push", arrayBuffer.val());
+ return Blob(emscripten::val::global("Blob").new_(array));
+}
+
uint32_t Blob::size() const
{
return m_blob["size"].as<uint32_t>();
}
+Blob Blob::copyFrom(const char *buffer, uint32_t size, std::string mimeType)
+{
+ Uint8Array contentCopy = Uint8Array::copyFrom(buffer, size);
+
+ emscripten::val contentArray = emscripten::val::array();
+ contentArray.call<void>("push", contentCopy.val());
+ emscripten::val type = emscripten::val::object();
+ type.set("type", std::move(mimeType));
+ return Blob(emscripten::val::global("Blob").new_(contentArray, type));
+}
+
+// Copies content from the given buffer into a Blob object
+Blob Blob::copyFrom(const char *buffer, uint32_t size)
+{
+ return copyFrom(buffer, size, "application/octet-stream");
+}
+
+Blob Blob::slice(uint32_t begin, uint32_t end) const
+{
+ return Blob(m_blob.call<emscripten::val>("slice", begin, end));
+}
+
+ArrayBuffer Blob::arrayBuffer_sync() const
+{
+ QEventLoop loop;
+ emscripten::val buffer;
+ qstdweb::Promise::make(m_blob, QStringLiteral("arrayBuffer"), {
+ .thenFunc = [&loop, &buffer](emscripten::val arrayBuffer) {
+ buffer = arrayBuffer;
+ loop.quit();
+ }
+ });
+ loop.exec();
+ return ArrayBuffer(buffer);
+}
+
+emscripten::val Blob::val() const
+{
+ return m_blob;
+}
+
File::File(const emscripten::val &file)
:m_file(file)
{
}
+File::~File() = default;
+
+File::File(const File &other) = default;
+
+File::File(File &&other) = default;
+
+File &File::operator=(const File &other) = default;
+
+File &File::operator=(File &&other) = default;
+
+
Blob File::slice(uint64_t begin, uint64_t end) const
{
return Blob(m_file.call<emscripten::val>("slice", uint53_t(begin), uint53_t(end)));
@@ -95,6 +495,52 @@ uint64_t File::size() const
return uint64_t(m_file["size"].as<uint53_t>());
}
+std::string Blob::type() const
+{
+ return m_blob["type"].as<std::string>();
+}
+
+// Streams partial file content into the given buffer asynchronously. The completed
+// callback is called on completion.
+void File::stream(uint32_t offset, uint32_t length, char *buffer,
+ std::function<void()> completed) const
+{
+ ChunkedFileReader::read(*this, buffer, offset, offset + length, std::move(completed));
+}
+
+// Streams file content into the given buffer asynchronously. The completed
+// callback is called on completion.
+void File::stream(char *buffer, std::function<void()> completed) const
+{
+ stream(0, size(), buffer, std::move(completed));
+}
+
+std::string File::type() const
+{
+ return m_file["type"].as<std::string>();
+}
+
+emscripten::val File::val() const
+{
+ return m_file;
+}
+
+FileUrlRegistration::FileUrlRegistration(File file)
+{
+ m_path = QString::fromStdString(emscripten::val::global("window")["URL"].call<std::string>(
+ "createObjectURL", file.file()));
+}
+
+FileUrlRegistration::~FileUrlRegistration()
+{
+ emscripten::val::global("window")["URL"].call<void>("revokeObjectURL",
+ emscripten::val(m_path.toStdString()));
+}
+
+FileUrlRegistration::FileUrlRegistration(FileUrlRegistration &&other) = default;
+
+FileUrlRegistration &FileUrlRegistration::operator=(FileUrlRegistration &&other) = default;
+
FileList::FileList(const emscripten::val &fileList)
:m_fileList(fileList)
{
@@ -116,6 +562,11 @@ File FileList::operator[](int index) const
return item(index);
}
+emscripten::val FileList::val() const
+{
+ return m_fileList;
+}
+
ArrayBuffer FileReader::result() const
{
return ArrayBuffer(m_fileReader["result"]);
@@ -126,19 +577,27 @@ void FileReader::readAsArrayBuffer(const Blob &blob) const
m_fileReader.call<void>("readAsArrayBuffer", blob.m_blob);
}
-void FileReader::onLoad(const std::function<void ()> &onLoad)
+void FileReader::onLoad(const std::function<void(emscripten::val)> &onLoad)
{
- m_onLoad.reset(new EventCallback(m_fileReader, "load", onLoad));
+ m_onLoad.reset();
+ m_onLoad = std::make_unique<EventCallback>(m_fileReader, "load", onLoad);
}
-void FileReader::onError(const std::function<void ()> &onError)
+void FileReader::onError(const std::function<void(emscripten::val)> &onError)
{
- m_onError.reset(new EventCallback(m_fileReader, "error", onError));
+ m_onError.reset();
+ m_onError = std::make_unique<EventCallback>(m_fileReader, "error", onError);
}
-void FileReader::onAbort(const std::function<void ()> &onAbort)
+void FileReader::onAbort(const std::function<void(emscripten::val)> &onAbort)
{
- m_onAbort.reset(new EventCallback(m_fileReader, "abort", onAbort));
+ m_onAbort.reset();
+ m_onAbort = std::make_unique<EventCallback>(m_fileReader, "abort", onAbort);
+}
+
+emscripten::val FileReader::val() const
+{
+ return m_fileReader;
}
Uint8Array Uint8Array::heap()
@@ -146,26 +605,37 @@ Uint8Array Uint8Array::heap()
return Uint8Array(heap_());
}
+// Constructs a Uint8Array which references the given emscripten::val, which must contain a JS Unit8Array
Uint8Array::Uint8Array(const emscripten::val &uint8Array)
: m_uint8Array(uint8Array)
{
}
+// Constructs a Uint8Array which references an ArrayBuffer
Uint8Array::Uint8Array(const ArrayBuffer &buffer)
: m_uint8Array(Uint8Array::constructor_().new_(buffer.m_arrayBuffer))
{
}
+// Constructs a Uint8Array which references a view into an ArrayBuffer
Uint8Array::Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length)
: m_uint8Array(Uint8Array::constructor_().new_(buffer.m_arrayBuffer, offset, length))
{
}
-Uint8Array::Uint8Array(char *buffer, uint32_t size)
-:m_uint8Array(Uint8Array::constructor_().new_(Uint8Array::heap().buffer().m_arrayBuffer, uint32_t(buffer), size))
+// Constructs a Uint8Array which references an area on the heap.
+Uint8Array::Uint8Array(const char *buffer, uint32_t size)
+:m_uint8Array(Uint8Array::constructor_().new_(Uint8Array::heap().buffer().m_arrayBuffer, uintptr_t(buffer), size))
+{
+
+}
+
+// Constructs a Uint8Array which allocates and references a new ArrayBuffer with the given size.
+Uint8Array::Uint8Array(uint32_t size)
+: m_uint8Array(Uint8Array::constructor_().new_(size))
{
}
@@ -185,16 +655,56 @@ void Uint8Array::set(const Uint8Array &source)
m_uint8Array.call<void>("set", source.m_uint8Array); // copies source content
}
+Uint8Array Uint8Array::subarray(uint32_t begin, uint32_t end)
+{
+ // Note: using uint64_t here errors with "Cannot convert a BigInt value to a number"
+ // (see JS BigInt and Number types). Use uint32_t for now.
+ return Uint8Array(m_uint8Array.call<emscripten::val>("subarray", begin, end));
+}
+
+// Copies the Uint8Array content to a destination on the heap
void Uint8Array::copyTo(char *destination) const
{
Uint8Array(destination, length()).set(*this);
}
+// Copies the Uint8Array content to a destination QByteArray
+QByteArray Uint8Array::copyToQByteArray() const
+{
+ if (length() > std::numeric_limits<qsizetype>::max())
+ return QByteArray();
+
+ QByteArray destinationArray;
+ destinationArray.resize(length());
+ copyTo(destinationArray.data());
+ return destinationArray;
+}
+
+// Copies the Uint8Array content to a destination on the heap
void Uint8Array::copy(char *destination, const Uint8Array &source)
{
Uint8Array(destination, source.length()).set(source);
}
+// Copies content from a source on the heap to a new Uint8Array object
+Uint8Array Uint8Array::copyFrom(const char *buffer, uint32_t size)
+{
+ Uint8Array contentCopy(size);
+ contentCopy.set(Uint8Array(buffer, size));
+ return contentCopy;
+}
+
+// Copies content from a QByteArray to a new Uint8Array object
+Uint8Array Uint8Array::copyFrom(const QByteArray &buffer)
+{
+ return copyFrom(buffer.constData(), buffer.size());
+}
+
+emscripten::val Uint8Array::val() const
+{
+ return m_uint8Array;
+}
+
emscripten::val Uint8Array::heap_()
{
return emscripten::val::module_property("HEAPU8");
@@ -205,30 +715,221 @@ emscripten::val Uint8Array::constructor_()
return emscripten::val::global("Uint8Array");
}
+class EventListener {
+public:
+ EventListener(uintptr_t handler)
+ :m_handler(handler)
+ {
+
+ }
+
+ // Special function - addEventListender() allows adding an object with a
+ // handleEvent() function which eceives the event.
+ void handleEvent(emscripten::val event) {
+ auto handlerPtr = reinterpret_cast<std::function<void(emscripten::val)> *>(m_handler);
+ (*handlerPtr)(event);
+ }
+
+ uintptr_t m_handler;
+};
+
// Registers a callback function for a named event on the given element. The event
// name must be the name as returned by the Event.type property: e.g. "load", "error".
-EventCallback::EventCallback(emscripten::val element, const std::string &name, const std::function<void ()> &fn)
-:m_fn(fn)
+EventCallback::~EventCallback()
+{
+ m_element.call<void>("removeEventListener", m_eventName, m_eventListener);
+}
+
+EventCallback::EventCallback(emscripten::val element, const std::string &name, const std::function<void(emscripten::val)> &handler)
+ :m_element(element)
+ ,m_eventName(name)
+ ,m_handler(std::make_unique<std::function<void(emscripten::val)>>(handler))
+{
+ uintptr_t handlerUint = reinterpret_cast<uintptr_t>(m_handler.get()); // FIXME: pass pointer directly instead
+ m_eventListener = emscripten::val::module_property("QtEventListener").new_(handlerUint);
+ m_element.call<void>("addEventListener", m_eventName, m_eventListener);
+}
+
+EMSCRIPTEN_BINDINGS(qtStdwebCalback) {
+ emscripten::class_<EventListener>("QtEventListener")
+ .constructor<uintptr_t>()
+ .function("handleEvent", &EventListener::handleEvent);
+}
+
+namespace Promise {
+ void adoptPromise(emscripten::val promiseObject, PromiseCallbacks callbacks) {
+ validateCallbacks(callbacks);
+
+ WebPromiseManager::get()->adoptPromise(
+ std::move(promiseObject), std::move(callbacks));
+ }
+
+ void all(std::vector<emscripten::val> promises, PromiseCallbacks callbacks) {
+ struct State {
+ std::map<int, emscripten::val> results;
+ int remainingThenCallbacks;
+ int remainingFinallyCallbacks;
+ };
+
+ validateCallbacks(callbacks);
+
+ auto state = std::make_shared<State>();
+ state->remainingThenCallbacks = state->remainingFinallyCallbacks = promises.size();
+
+ for (size_t i = 0; i < promises.size(); ++i) {
+ PromiseCallbacks individualPromiseCallback;
+ if (callbacks.thenFunc) {
+ individualPromiseCallback.thenFunc = [i, state, callbacks](emscripten::val partialResult) mutable {
+ state->results.emplace(i, std::move(partialResult));
+ if (!--(state->remainingThenCallbacks)) {
+ std::vector<emscripten::val> transformed;
+ for (auto& data : state->results) {
+ transformed.push_back(std::move(data.second));
+ }
+ callbacks.thenFunc(emscripten::val::array(std::move(transformed)));
+ }
+ };
+ }
+ if (callbacks.catchFunc) {
+ individualPromiseCallback.catchFunc = [state, callbacks](emscripten::val error) mutable {
+ callbacks.catchFunc(error);
+ };
+ }
+ individualPromiseCallback.finallyFunc = [state, callbacks]() mutable {
+ if (!--(state->remainingFinallyCallbacks)) {
+ if (callbacks.finallyFunc)
+ callbacks.finallyFunc();
+ // Explicitly reset here for verbosity, this would have been done automatically with the
+ // destruction of the adopted promise in WebPromiseManager.
+ state.reset();
+ }
+ };
+
+ adoptPromise(std::move(promises.at(i)), std::move(individualPromiseCallback));
+ }
+ }
+}
+
+// Asyncify and thread blocking: Normally, it's not possible to block the main
+// thread, except if asyncify is enabled. Secondary threads can always block.
+//
+// haveAsyncify(): returns true if the main thread can block on QEventLoop::exec(),
+// if either asyncify 1 or 2 (JSPI) is available.
+//
+// haveJspi(): returns true if asyncify 2 (JSPI) is available.
+//
+// canBlockCallingThread(): returns true if the calling thread can block on
+// QEventLoop::exec(), using either asyncify or as a seconarday thread.
+bool haveJspi()
{
- element.set(contextPropertyName(name).c_str(), emscripten::val(intptr_t(this)));
- element.set((std::string("on") + name).c_str(), emscripten::val::module_property("qtStdWebEventCallbackActivate"));
+ static bool HaveJspi = jsHaveJspi();
+ return HaveJspi;
}
-void EventCallback::activate(emscripten::val event)
+bool haveAsyncify()
{
- emscripten::val target = event["target"];
- std::string eventName = event["type"].as<std::string>();
- EventCallback *that = reinterpret_cast<EventCallback *>(target[contextPropertyName(eventName).c_str()].as<intptr_t>());
- that->m_fn();
+ static bool HaveAsyncify = jsHaveAsyncify() || haveJspi();
+ return HaveAsyncify;
}
-std::string EventCallback::contextPropertyName(const std::string &eventName)
+bool canBlockCallingThread()
{
- return std::string("data-qtEventCallbackContext") + eventName;
+ return haveAsyncify() || !emscripten_is_main_runtime_thread();
}
-EMSCRIPTEN_BINDINGS(qtStdwebCalback) {
- emscripten::function("qtStdWebEventCallbackActivate", &EventCallback::activate);
+BlobIODevice::BlobIODevice(Blob blob)
+ : m_blob(blob)
+{
+
+}
+
+bool BlobIODevice::open(QIODevice::OpenMode mode)
+{
+ if (mode.testFlag(QIODevice::WriteOnly))
+ return false;
+ return QIODevice::open(mode);
+}
+
+bool BlobIODevice::isSequential() const
+{
+ return false;
+}
+
+qint64 BlobIODevice::size() const
+{
+ return m_blob.size();
+}
+
+bool BlobIODevice::seek(qint64 pos)
+{
+ if (pos >= size())
+ return false;
+ return QIODevice::seek(pos);
+}
+
+qint64 BlobIODevice::readData(char *data, qint64 maxSize)
+{
+ uint64_t begin = QIODevice::pos();
+ uint64_t end = std::min<uint64_t>(begin + maxSize, size());
+ uint64_t size = end - begin;
+ if (size > 0) {
+ qstdweb::ArrayBuffer buffer = m_blob.slice(begin, end).arrayBuffer_sync();
+ qstdweb::Uint8Array(buffer).copyTo(data);
+ }
+ return size;
+}
+
+qint64 BlobIODevice::writeData(const char *, qint64)
+{
+ Q_UNREACHABLE();
+}
+
+Uint8ArrayIODevice::Uint8ArrayIODevice(Uint8Array array)
+ : m_array(array)
+{
+
+}
+
+bool Uint8ArrayIODevice::open(QIODevice::OpenMode mode)
+{
+ return QIODevice::open(mode);
+}
+
+bool Uint8ArrayIODevice::isSequential() const
+{
+ return false;
+}
+
+qint64 Uint8ArrayIODevice::size() const
+{
+ return m_array.length();
+}
+
+bool Uint8ArrayIODevice::seek(qint64 pos)
+{
+ if (pos >= size())
+ return false;
+ return QIODevice::seek(pos);
+}
+
+qint64 Uint8ArrayIODevice::readData(char *data, qint64 maxSize)
+{
+ uint64_t begin = QIODevice::pos();
+ uint64_t end = std::min<uint64_t>(begin + maxSize, size());
+ uint64_t size = end - begin;
+ if (size > 0)
+ m_array.subarray(begin, end).copyTo(data);
+ return size;
+}
+
+qint64 Uint8ArrayIODevice::writeData(const char *data, qint64 maxSize)
+{
+ uint64_t begin = QIODevice::pos();
+ uint64_t end = std::min<uint64_t>(begin + maxSize, size());
+ uint64_t size = end - begin;
+ if (size > 0)
+ m_array.subarray(begin, end).set(Uint8Array(data, size));
+ return size;
}
} // namespace qstdweb
diff --git a/src/corelib/platform/wasm/qstdweb_p.h b/src/corelib/platform/wasm/qstdweb_p.h
index 75c2ec34b1..a3b5bd5b6b 100644
--- a/src/corelib/platform/wasm/qstdweb_p.h
+++ b/src/corelib/platform/wasm/qstdweb_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTDWEB_P_H
#define QSTDWEB_P_H
@@ -51,17 +15,36 @@
// We mean it.
//
-#include <qglobal.h>
+#include <private/qglobal_p.h>
+#include <QtCore/qglobal.h>
+#include "QtCore/qhash.h"
+#include "QtCore/qiodevice.h"
+
#include <emscripten/val.h>
+
#include <cstdint>
#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <string>
+#include <utility>
+
+#if QT_CONFIG(thread)
+#include <emscripten/proxying.h>
+#include <emscripten/threading.h>
+#endif // #if QT_CONFIG(thread)
QT_BEGIN_NAMESPACE
+class QMimeData;
+
namespace qstdweb {
+ extern const char makeContextfulPromiseFunctionName[];
// DOM API in C++, implemented using emscripten val.h and bind.h.
- // This is private API and can be extened and changed as needed.
+ // This is private API and can be extended and changed as needed.
+ // The API mirrors that of the native API, with some extensions
+ // to ease usage from C++ code.
class ArrayBuffer;
class Blob;
@@ -71,40 +54,84 @@ namespace qstdweb {
class Uint8Array;
class EventCallback;
- class ArrayBuffer {
+ class Q_CORE_EXPORT ArrayBuffer {
public:
+ explicit ArrayBuffer(uint32_t size);
explicit ArrayBuffer(const emscripten::val &arrayBuffer);
uint32_t byteLength() const;
+ ArrayBuffer slice(uint32_t begin, uint32_t end) const;
+ emscripten::val val() const;
private:
friend class Uint8Array;
emscripten::val m_arrayBuffer = emscripten::val::undefined();
};
- class Blob {
+ class Q_CORE_EXPORT Blob {
public:
explicit Blob(const emscripten::val &blob);
+ static Blob fromArrayBuffer(const ArrayBuffer &arrayBuffer);
uint32_t size() const;
+ static Blob copyFrom(const char *buffer, uint32_t size, std::string mimeType);
+ static Blob copyFrom(const char *buffer, uint32_t size);
+ Blob slice(uint32_t begin, uint32_t end) const;
+ ArrayBuffer arrayBuffer_sync() const;
+ emscripten::val val() const;
+ std::string type() const;
private:
friend class FileReader;
emscripten::val m_blob = emscripten::val::undefined();
};
- class File {
+ class Q_CORE_EXPORT File {
public:
File() = default;
explicit File(const emscripten::val &file);
+ ~File();
+
+ File(const File &other);
+ File(File &&other);
+ File &operator=(const File &other);
+ File &operator=(File &&other);
Blob slice(uint64_t begin, uint64_t end) const;
std::string name() const;
uint64_t size() const;
+ std::string type() const;
+ void stream(uint32_t offset, uint32_t length, char *buffer,
+ std::function<void()> completed) const;
+ void stream(char *buffer, std::function<void()> completed) const;
+ emscripten::val val() const;
+ void fileUrlRegistration() const;
+ const QString &fileUrlPath() const { return m_urlPath; }
+ emscripten::val file() const { return m_file; }
private:
emscripten::val m_file = emscripten::val::undefined();
+ QString m_urlPath;
};
- class FileList {
+ class Q_CORE_EXPORT FileUrlRegistration
+ {
+ public:
+ explicit FileUrlRegistration(File file);
+ ~FileUrlRegistration();
+
+ FileUrlRegistration(const FileUrlRegistration &other) = delete;
+ FileUrlRegistration(FileUrlRegistration &&other);
+ FileUrlRegistration &operator=(const FileUrlRegistration &other) = delete;
+ FileUrlRegistration &operator=(FileUrlRegistration &&other);
+
+ const QString &path() const { return m_path; }
+
+ private:
+ QString m_path;
+ };
+
+ using FileUrlRegistrations = std::vector<std::unique_ptr<FileUrlRegistration>>;
+
+ class Q_CORE_EXPORT FileList {
public:
FileList() = default;
explicit FileList(const emscripten::val &fileList);
@@ -112,19 +139,21 @@ namespace qstdweb {
int length() const;
File item(int index) const;
File operator[](int index) const;
+ emscripten::val val() const;
private:
emscripten::val m_fileList = emscripten::val::undefined();
};
- class FileReader {
+ class Q_CORE_EXPORT FileReader {
public:
ArrayBuffer result() const;
void readAsArrayBuffer(const Blob &blob) const;
- void onLoad(const std::function<void ()> &onLoad);
- void onError(const std::function<void ()> &onError);
- void onAbort(const std::function<void ()> &onAbort);
+ void onLoad(const std::function<void(emscripten::val)> &onLoad);
+ void onError(const std::function<void(emscripten::val)> &onError);
+ void onAbort(const std::function<void(emscripten::val)> &onAbort);
+ emscripten::val val() const;
private:
emscripten::val m_fileReader = emscripten::val::global("FileReader").new_();
@@ -133,35 +162,170 @@ namespace qstdweb {
std::unique_ptr<EventCallback> m_onAbort;
};
- class Uint8Array {
+ class Q_CORE_EXPORT Uint8Array {
public:
static Uint8Array heap();
explicit Uint8Array(const emscripten::val &uint8Array);
explicit Uint8Array(const ArrayBuffer &buffer);
+ explicit Uint8Array(uint32_t size);
Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length);
- Uint8Array(char *buffer, uint32_t size);
+ Uint8Array(const char *buffer, uint32_t size);
ArrayBuffer buffer() const;
uint32_t length() const;
void set(const Uint8Array &source);
+ Uint8Array subarray(uint32_t begin, uint32_t end);
void copyTo(char *destination) const;
+ QByteArray copyToQByteArray() const;
+
static void copy(char *destination, const Uint8Array &source);
+ static Uint8Array copyFrom(const char *buffer, uint32_t size);
+ static Uint8Array copyFrom(const QByteArray &buffer);
+ emscripten::val val() const;
+
private:
static emscripten::val heap_();
static emscripten::val constructor_();
emscripten::val m_uint8Array = emscripten::val::undefined();
};
- class EventCallback
+ class Q_CORE_EXPORT EventCallback
+ {
+ public:
+ EventCallback() = default;
+ ~EventCallback();
+ EventCallback(EventCallback const&) = delete;
+ EventCallback& operator=(EventCallback const&) = delete;
+ EventCallback(emscripten::val element, const std::string &name,
+ const std::function<void(emscripten::val)> &fn);
+
+ private:
+ emscripten::val m_element = emscripten::val::undefined();
+ std::string m_eventName;
+ std::unique_ptr<std::function<void(emscripten::val)>> m_handler;
+ emscripten::val m_eventListener = emscripten::val::undefined();
+ };
+
+ struct PromiseCallbacks
+ {
+ std::function<void(emscripten::val)> thenFunc;
+ std::function<void(emscripten::val)> catchFunc;
+ std::function<void()> finallyFunc;
+ };
+
+ namespace Promise {
+ void Q_CORE_EXPORT adoptPromise(emscripten::val promise, PromiseCallbacks callbacks);
+
+ template<typename... Args>
+ void make(emscripten::val target,
+ QString methodName,
+ PromiseCallbacks callbacks,
+ Args... args)
+ {
+ emscripten::val promiseObject = target.call<emscripten::val>(
+ methodName.toStdString().c_str(), std::forward<Args>(args)...);
+ if (promiseObject.isUndefined() || promiseObject["constructor"]["name"].as<std::string>() != "Promise") {
+ qFatal("This function did not return a promise");
+ }
+
+ adoptPromise(std::move(promiseObject), std::move(callbacks));
+ }
+
+ void Q_CORE_EXPORT all(std::vector<emscripten::val> promises, PromiseCallbacks callbacks);
+ };
+
+ template<class F>
+ decltype(auto) bindForever(F wrappedCallback)
+ {
+ return wrappedCallback;
+ }
+
+ class Q_CORE_EXPORT BlobIODevice: public QIODevice
{
public:
- EventCallback(emscripten::val element, const std::string &name, const std::function<void ()> &fn);
- static void activate(emscripten::val event);
+ BlobIODevice(Blob blob);
+ bool open(QIODeviceBase::OpenMode mode) override;
+ bool isSequential() const override;
+ qint64 size() const override;
+ bool seek(qint64 pos) override;
+
+ protected:
+ qint64 readData(char *data, qint64 maxSize) override;
+ qint64 writeData(const char *, qint64) override;
+
private:
- static std::string contextPropertyName(const std::string &eventName);
- std::function<void ()> m_fn;
+ Blob m_blob;
};
+
+ class Uint8ArrayIODevice: public QIODevice
+ {
+ public:
+ Uint8ArrayIODevice(Uint8Array array);
+ bool open(QIODevice::OpenMode mode) override;
+ bool isSequential() const override;
+ qint64 size() const override;
+ bool seek(qint64 pos) override;
+
+ protected:
+ qint64 readData(char *data, qint64 maxSize) override;
+ qint64 writeData(const char *data, qint64 size) override;
+
+ private:
+ Uint8Array m_array;
+ };
+
+ inline emscripten::val window()
+ {
+ static emscripten::val savedWindow = emscripten::val::global("window");
+ return savedWindow;
+ }
+
+ bool haveAsyncify();
+ bool Q_CORE_EXPORT haveJspi();
+ bool canBlockCallingThread();
+
+ struct CancellationFlag
+ {
+ };
+
+#if QT_CONFIG(thread)
+ template<class T>
+ T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue)
+ {
+ T result;
+ queue->proxySync(emscripten_main_runtime_thread_id(),
+ [task, result = &result]() { *result = task(); });
+ return result;
+ }
+
+ template<>
+ inline void proxyCall<void>(std::function<void()> task, emscripten::ProxyingQueue *queue)
+ {
+ queue->proxySync(emscripten_main_runtime_thread_id(), task);
+ }
+
+ template<class T>
+ T runTaskOnMainThread(std::function<T()> task, emscripten::ProxyingQueue *queue)
+ {
+ return emscripten_is_main_runtime_thread() ? task() : proxyCall<T>(std::move(task), queue);
+ }
+
+ template<class T>
+ T runTaskOnMainThread(std::function<T()> task)
+ {
+ emscripten::ProxyingQueue singleUseQueue;
+ return runTaskOnMainThread<T>(task, &singleUseQueue);
+ }
+
+#else
+ template<class T>
+ T runTaskOnMainThread(std::function<T()> task)
+ {
+ return task();
+ }
+#endif // QT_CONFIG(thread)
+
}
QT_END_NAMESPACE
diff --git a/src/corelib/platform/wasm/wasm.pri b/src/corelib/platform/wasm/wasm.pri
deleted file mode 100644
index 73447030fb..0000000000
--- a/src/corelib/platform/wasm/wasm.pri
+++ /dev/null
@@ -1,3 +0,0 @@
-INCLUDEDIR += $$PWD
-HEADERS += $$PWD/qstdweb_p.h
-SOURCES += $$PWD/qstdweb.cpp
diff --git a/src/corelib/platform/windows/qcomobject_p.h b/src/corelib/platform/windows/qcomobject_p.h
new file mode 100644
index 0000000000..8f27a18ff6
--- /dev/null
+++ b/src/corelib/platform/windows/qcomobject_p.h
@@ -0,0 +1,127 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOMOBJECT_P_H
+#define QCOMOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+# include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+template <typename... TInterfaces>
+struct QComObjectTraits
+{
+ static constexpr bool isGuidOf(REFIID riid) noexcept
+ {
+ return ((riid == __uuidof(TInterfaces)) || ...);
+ }
+};
+
+} // namespace QtPrivate
+
+// NOTE: In order to be able to query the intermediate interface, i.e. the one you do not specify in
+// QComObject interface list (TFirstInterface, TInterfaces) but that is a base for any of them
+// (except IUnknown) you need to provide an explicit specialization of function
+// QComObjectTraits<...>::isGuidOf for that type. For example, if you want to inherit interface
+// IMFSampleGrabberSinkCallback which inherits IMFClockStateSink and you want to be able to query
+// the latter one you need to provide this explicit specialization:
+//
+// class SinkCallback : public QComObject<IMFSampleGrabberSinkCallback>
+// {
+// ...
+// };
+//
+// namespace QtPrivate {
+//
+// template <>
+// struct QComObjectTraits<IMFSampleGrabberSinkCallback>
+// {
+// static constexpr bool isGuidOf(REFIID riid) noexcept
+// {
+// return QComObjectTraits<IMFSampleGrabberSinkCallback, IMFClockStateSink>::isGuidOf(riid);
+// }
+// };
+//
+// }
+
+template <typename TFirstInterface, typename... TAdditionalInterfaces>
+class QComObject : public TFirstInterface, public TAdditionalInterfaces...
+{
+public:
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
+ {
+ if (!ppvObject)
+ return E_POINTER;
+
+ if (riid == __uuidof(IUnknown)) {
+ *ppvObject = static_cast<IUnknown *>(static_cast<TFirstInterface *>(this));
+ AddRef();
+
+ return S_OK;
+ }
+
+ return tryQueryInterface<TFirstInterface, TAdditionalInterfaces...>(riid, ppvObject);
+ }
+
+ STDMETHODIMP_(ULONG) AddRef() override { return ++m_referenceCount; }
+
+ STDMETHODIMP_(ULONG) Release() override
+ {
+ const LONG referenceCount = --m_referenceCount;
+ if (referenceCount == 0)
+ delete this;
+
+ return referenceCount;
+ }
+
+protected:
+ QComObject() = default;
+
+ // Destructor is not public. Caller should call Release.
+ // Derived class should make its destructor private to force this behavior.
+ virtual ~QComObject() = default;
+
+private:
+ template <typename TInterface, typename... TRest>
+ HRESULT tryQueryInterface(REFIID riid, void **ppvObject)
+ {
+ if (QtPrivate::QComObjectTraits<TInterface>::isGuidOf(riid)) {
+ *ppvObject = static_cast<TInterface *>(this);
+ AddRef();
+
+ return S_OK;
+ }
+
+ if constexpr (sizeof...(TRest) > 0)
+ return tryQueryInterface<TRest...>(riid, ppvObject);
+
+ *ppvObject = nullptr;
+
+ return E_NOINTERFACE;
+ }
+
+ std::atomic<LONG> m_referenceCount = 1;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_WIN
+
+#endif // QCOMOBJECT_P_H
diff --git a/src/corelib/platform/windows/qfactorycacheregistration.cpp b/src/corelib/platform/windows/qfactorycacheregistration.cpp
new file mode 100644
index 0000000000..6bd69c66d1
--- /dev/null
+++ b/src/corelib/platform/windows/qfactorycacheregistration.cpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qfactorycacheregistration_p.h"
+
+#include <QtCore/QMutex>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
+
+static QBasicMutex registrationMutex;
+static detail::QWinRTFactoryCacheRegistration *firstElement;
+
+detail::QWinRTFactoryCacheRegistration::QWinRTFactoryCacheRegistration(
+ QFunctionPointer clearFunction)
+ : m_clearFunction(clearFunction)
+{
+ QMutexLocker lock(&registrationMutex);
+
+ // forward pointers
+ m_next = std::exchange(firstElement, this);
+
+ // backward pointers
+ m_prevNext = &firstElement;
+ if (m_next)
+ m_next->m_prevNext = &m_next;
+}
+
+detail::QWinRTFactoryCacheRegistration::~QWinRTFactoryCacheRegistration()
+{
+ QMutexLocker lock(&registrationMutex);
+
+ *m_prevNext = m_next;
+
+ if (m_next)
+ m_next->m_prevNext = m_prevNext;
+}
+
+void detail::QWinRTFactoryCacheRegistration::clearAllCaches()
+{
+ QMutexLocker lock(&registrationMutex);
+
+ detail::QWinRTFactoryCacheRegistration *element;
+
+ for (element = firstElement; element != nullptr; element = element->m_next) {
+ element->m_clearFunction();
+ }
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/platform/windows/qfactorycacheregistration_p.h b/src/corelib/platform/windows/qfactorycacheregistration_p.h
new file mode 100644
index 0000000000..d0b19b995b
--- /dev/null
+++ b/src/corelib/platform/windows/qfactorycacheregistration_p.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFACTORYCACHEREGISTRATION_P_H
+#define QFACTORYCACHEREGISTRATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(cpp_winrt)
+# define QT_USE_FACTORY_CACHE_REGISTRATION
+#endif
+
+#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
+
+#include "qt_winrtbase_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace detail {
+
+class QWinRTFactoryCacheRegistration
+{
+public:
+ Q_CORE_EXPORT explicit QWinRTFactoryCacheRegistration(QFunctionPointer clearFunction);
+ Q_CORE_EXPORT ~QWinRTFactoryCacheRegistration();
+ Q_CORE_EXPORT static void clearAllCaches();
+
+ Q_DISABLE_COPY_MOVE(QWinRTFactoryCacheRegistration)
+private:
+ QWinRTFactoryCacheRegistration **m_prevNext = nullptr;
+ QWinRTFactoryCacheRegistration *m_next = nullptr;
+ QFunctionPointer m_clearFunction;
+};
+
+inline QWinRTFactoryCacheRegistration reg([]() noexcept { winrt::clear_factory_cache(); });
+}
+
+QT_END_NAMESPACE
+
+#endif
+#endif // QFACTORYCACHEREGISTRATION_P_H
diff --git a/src/corelib/platform/windows/qt_winrtbase_p.h b/src/corelib/platform/windows/qt_winrtbase_p.h
new file mode 100644
index 0000000000..fb7366f93d
--- /dev/null
+++ b/src/corelib/platform/windows/qt_winrtbase_p.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QT_WINRTBASE_P_H
+#define QT_WINRTBASE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#if QT_CONFIG(cpp_winrt)
+# include <winrt/base.h>
+# include <QtCore/private/qfactorycacheregistration_p.h>
+// Workaround for Windows SDK bug.
+// See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47
+namespace winrt::impl
+{
+ template <typename Async>
+ auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout);
+}
+// See https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/faq#how-do-i-resolve-ambiguities-with-getcurrenttime-and-or-try-
+// for more workarounds.
+#endif // QT_CONFIG(cpp/winrt)
+
+#endif // QT_WINRTBASE_P_H
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
deleted file mode 100644
index 13153e8d0a..0000000000
--- a/src/corelib/plugin/plugin.pri
+++ /dev/null
@@ -1,38 +0,0 @@
-# Qt core library plugin module
-
-HEADERS += \
- plugin/qfactoryinterface.h \
- plugin/qpluginloader.h \
- plugin/qplugin.h \
- plugin/qplugin_p.h \
- plugin/quuid.h \
- plugin/qfactoryloader_p.h
-
-SOURCES += \
- plugin/qfactoryinterface.cpp \
- plugin/qpluginloader.cpp \
- plugin/qfactoryloader.cpp \
- plugin/quuid.cpp
-
-win32 {
- HEADERS += plugin/qsystemlibrary_p.h
- SOURCES += plugin/qsystemlibrary.cpp
-}
-
-qtConfig(library) {
- HEADERS += \
- plugin/qlibrary.h \
- plugin/qlibrary_p.h \
- plugin/qelfparser_p.h \
- plugin/qmachparser_p.h
-
- SOURCES += \
- plugin/qlibrary.cpp \
- plugin/qelfparser_p.cpp \
- plugin/qmachparser.cpp
-
- unix: SOURCES += plugin/qlibrary_unix.cpp
- else: SOURCES += plugin/qlibrary_win.cpp
-
- qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl
-}
diff --git a/src/corelib/plugin/qcoffpeparser.cpp b/src/corelib/plugin/qcoffpeparser.cpp
new file mode 100644
index 0000000000..639e402a07
--- /dev/null
+++ b/src/corelib/plugin/qcoffpeparser.cpp
@@ -0,0 +1,383 @@
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcoffpeparser_p.h"
+
+#include <qendian.h>
+#include <qloggingcategory.h>
+#include <qnumeric.h>
+
+#include <optional>
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+// Whether we include some extra validity checks
+// (checks to ensure we don't read out-of-bounds are always included)
+static constexpr bool IncludeValidityChecks = true;
+
+static constexpr inline auto metadataSectionName() noexcept { return ".qtmetadata"_L1; }
+static constexpr QLatin1StringView truncatedSectionName =
+ metadataSectionName().left(sizeof(IMAGE_SECTION_HEADER::Name));
+
+#ifdef QT_BUILD_INTERNAL
+# define QCOFFPEPARSER_DEBUG
+#endif
+#if defined(QCOFFPEPARSER_DEBUG)
+static Q_LOGGING_CATEGORY(lcCoffPeParser, "qt.core.plugin.coffpeparser")
+# define peDebug qCDebug(lcCoffPeParser) << reinterpret_cast<const char16_t *>(error.errMsg->constData()) << ':'
+#else
+# define peDebug if (false) {} else QNoDebug()
+#endif
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wunused-const-variable")
+
+static const WORD ExpectedMachine =
+#if 0
+ // nothing, just so everything is #elf
+#elif defined(Q_PROCESSOR_ARM_32)
+ IMAGE_FILE_MACHINE_ARMNT
+#elif defined(Q_PROCESSOR_ARM_64)
+ IMAGE_FILE_MACHINE_ARM64
+#elif defined(Q_PROCESSOR_IA64)
+ IMAGE_FILE_MACHINE_IA64
+#elif defined(Q_PROCESSOR_RISCV_32)
+ 0x5032 // IMAGE_FILE_MACHINE_RISCV32
+#elif defined(Q_PROCESSOR_RISCV_64)
+ 0x5064 // IMAGE_FILE_MACHINE_RISCV64
+#elif defined(Q_PROCESSOR_X86_32)
+ IMAGE_FILE_MACHINE_I386
+#elif defined(Q_PROCESSOR_X86_64)
+ IMAGE_FILE_MACHINE_AMD64
+#else
+# error "Unknown Q_PROCESSOR_xxx macro, please update."
+ IMAGE_FILE_MACHINE_UNKNOWN
+#endif
+ ;
+
+static const WORD ExpectedOptionalHeaderSignature =
+ sizeof(void*) == sizeof(quint64) ? IMAGE_NT_OPTIONAL_HDR64_MAGIC :
+ IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+
+namespace {
+struct ErrorMaker
+{
+ QString *errMsg;
+ constexpr ErrorMaker(QString *errMsg) : errMsg(errMsg) {}
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult operator()(QString &&text) const
+ {
+ *errMsg = QLibrary::tr("'%1' is not a valid Windows DLL (%2)").arg(*errMsg, std::move(text));
+ return {};
+ }
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult toosmall() const
+ {
+ *errMsg = QLibrary::tr("'%1' is too small").arg(*errMsg);
+ return {};
+ }
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult notplugin(QString &&explanation) const
+ {
+ *errMsg = QLibrary::tr("'%1' is not a Qt plugin (%2)").arg(*errMsg, explanation);
+ return {};
+ }
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult notfound() const
+ {
+ return notplugin(QLibrary::tr("metadata not found"));
+ }
+};
+
+struct HeaderDebug { const IMAGE_NT_HEADERS *h; };
+Q_DECL_UNUSED static QDebug &operator<<(QDebug &d, HeaderDebug h)
+{
+ switch (h.h->Signature & 0xffff) {
+ case IMAGE_OS2_SIGNATURE: return d << "NE executable";
+ case IMAGE_VXD_SIGNATURE: return d << "LE executable";
+ default: return d << "Unknown file type";
+ case IMAGE_NT_SIGNATURE: break;
+ }
+
+ // the FileHeader and the starting portion of OptionalHeader are the same
+ // for 32- and 64-bit
+ switch (h.h->OptionalHeader.Magic) {
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC: d << "COFF PE"; break;
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC: d << "COFF PE+"; break;
+ default: return d << "Unknown COFF PE type";
+ }
+
+ QDebugStateSaver saver(d);
+ d.nospace() << Qt::hex << Qt::showbase;
+
+ switch (h.h->FileHeader.Machine) {
+ case IMAGE_FILE_MACHINE_I386: d << "i386"; break;
+ case IMAGE_FILE_MACHINE_ARM: d << "ARM"; break;
+ case IMAGE_FILE_MACHINE_ARMNT: d << "ARM Thumb-2"; break;
+ case IMAGE_FILE_MACHINE_THUMB: d << "Thumb"; break;
+ case IMAGE_FILE_MACHINE_IA64: d << "IA-64"; break;
+ case IMAGE_FILE_MACHINE_MIPS16: d << "MIPS16"; break;
+ case IMAGE_FILE_MACHINE_MIPSFPU: d << "MIPS with FPU"; break;
+ case IMAGE_FILE_MACHINE_MIPSFPU16: d << "MIPS16 with FPU"; break;
+ case IMAGE_FILE_MACHINE_AMD64: d << "x86-64"; break;
+ case 0xaa64: d << "AArch64"; break;
+ default: d << h.h->FileHeader.Machine; break;
+ }
+
+ // this usually prints "executable DLL"
+ if (h.h->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
+ d << " executable";
+ if (h.h->FileHeader.Characteristics & IMAGE_FILE_DLL)
+ d << " DLL";
+ if (h.h->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
+ d << " large-address aware";
+
+ d << ", " << Qt::dec << h.h->FileHeader.NumberOfSections << " sections, ";
+ if (h.h->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER32))
+ return d;
+
+ auto optDebug = [&d](const auto *hdr) {
+ d << "(Windows " << hdr->MajorSubsystemVersion
+ << '.' << hdr->MinorSubsystemVersion;
+ switch (hdr->Subsystem) {
+ case IMAGE_SUBSYSTEM_NATIVE: d << " native)"; break;
+ case IMAGE_SUBSYSTEM_WINDOWS_GUI: d << " GUI)"; break;
+ case IMAGE_SUBSYSTEM_WINDOWS_CUI: d << " CUI)"; break;
+ default: d << " subsystem " << hdr->Subsystem << ')'; break;
+ }
+
+ d.space() << Qt::hex << hdr->SizeOfHeaders << "header bytes,"
+ << Qt::dec << hdr->NumberOfRvaAndSizes << "RVA entries";
+ };
+
+ if (h.h->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ optDebug(reinterpret_cast<const IMAGE_OPTIONAL_HEADER64 *>(&h.h->OptionalHeader));
+ else
+ optDebug(reinterpret_cast<const IMAGE_OPTIONAL_HEADER32 *>(&h.h->OptionalHeader));
+ return d;
+}
+
+struct SectionDebug { const IMAGE_SECTION_HEADER *s; };
+Q_DECL_UNUSED static QDebug &operator<<(QDebug &d, SectionDebug s)
+{
+ QDebugStateSaver saver(d);
+ d << Qt::hex << Qt::showbase;
+ d << "contains";
+ if (s.s->Characteristics & IMAGE_SCN_CNT_CODE)
+ d << "CODE";
+ if (s.s->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
+ d << "DATA";
+ if (s.s->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ d << "BSS";
+
+ d << "flags";
+ d.nospace();
+ if (s.s->Characteristics & IMAGE_SCN_MEM_READ)
+ d << 'R';
+ if (s.s->Characteristics & IMAGE_SCN_MEM_WRITE)
+ d << 'W';
+ if (s.s->Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ d << 'X';
+ if (s.s->Characteristics & IMAGE_SCN_MEM_SHARED)
+ d << 'S';
+ if (s.s->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
+ d << 'D';
+
+ d.space() << "offset" << s.s->PointerToRawData << "size" << s.s->SizeOfRawData;
+ return d;
+}
+} // unnamed namespace
+
+QT_WARNING_POP
+
+const IMAGE_NT_HEADERS *checkNtHeaders(QByteArrayView data, const ErrorMaker &error)
+{
+ if (size_t(data.size()) < qMax(sizeof(IMAGE_DOS_HEADER), sizeof(IMAGE_NT_HEADERS))) {
+ peDebug << "file too small:" << size_t(data.size());
+ return error.toosmall(), nullptr;
+ }
+
+ // check if there's a DOS image header (almost everything does)
+ size_t off = 0;
+ auto dosHeader = reinterpret_cast<const IMAGE_DOS_HEADER *>(data.data());
+ if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
+ off = dosHeader->e_lfanew;
+ // peDebug << "DOS file header redirects to offset" << Qt::hex << Qt::showbase << off;
+ if (size_t end; qAddOverflow<sizeof(IMAGE_NT_HEADERS)>(off, &end)
+ || end > size_t(data.size())) {
+ peDebug << "file too small:" << size_t(data.size());
+ return error.toosmall(), nullptr;
+ }
+ }
+
+ // now check the NT headers
+ auto ntHeader = reinterpret_cast<const IMAGE_NT_HEADERS *>(data.data() + off);
+ peDebug << HeaderDebug{ntHeader};
+ if (ntHeader->Signature != IMAGE_NT_SIGNATURE) // "PE\0\0"
+ return error(QLibrary::tr("invalid signature")), nullptr;
+ if (ntHeader->FileHeader.Machine != ExpectedMachine)
+ return error(QLibrary::tr("file is for a different processor")), nullptr;
+ if (ntHeader->FileHeader.NumberOfSections == 0)
+ return error(QLibrary::tr("file has no sections")), nullptr;
+
+ WORD requiredCharacteristics =
+ IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL;
+ if ((ntHeader->FileHeader.Characteristics & requiredCharacteristics) != requiredCharacteristics)
+ return error(QLibrary::tr("wrong characteristics")), nullptr;
+
+ // the optional header is not optional
+ if (ntHeader->OptionalHeader.Magic != ExpectedOptionalHeaderSignature)
+ return error(QLibrary::tr("file is for a different word size")), nullptr;
+ if (ntHeader->OptionalHeader.SizeOfCode == 0)
+ return error.notplugin(QLibrary::tr("file has no code")), nullptr;
+
+ return ntHeader;
+}
+
+static const IMAGE_SECTION_HEADER *
+findSectionTable(QByteArrayView data, const IMAGE_NT_HEADERS *ntHeader, const ErrorMaker &error)
+{
+ // macro IMAGE_FIRST_SECTION can't overflow due to limited range
+ // of type, but adding to the offset from the DOS header could
+ // overflow on 32-bit
+ static_assert(sizeof(ntHeader->FileHeader.SizeOfOptionalHeader) < sizeof(size_t));
+ static_assert(sizeof(ntHeader->FileHeader.NumberOfSections) < sizeof(size_t));
+
+ size_t off = offsetof(IMAGE_NT_HEADERS, OptionalHeader);
+ off += ntHeader->FileHeader.SizeOfOptionalHeader;
+ if (qAddOverflow<size_t>(off, reinterpret_cast<const char *>(ntHeader) - data.data(), &off))
+ return error.toosmall(), nullptr;
+
+ size_t end = ntHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
+
+ // validate that the file is big enough for all sections we're
+ // supposed to have
+ if (qAddOverflow(end, off, &end) || end > size_t(data.size()))
+ return error.toosmall(), nullptr;
+
+ peDebug << "contains" << ntHeader->FileHeader.NumberOfSections << "sections at offset" << off;
+ return reinterpret_cast<const IMAGE_SECTION_HEADER *>(data.data() + off);
+}
+
+static std::optional<QByteArrayView>
+findStringTable(QByteArrayView data, const IMAGE_NT_HEADERS *ntHeader, const ErrorMaker &error)
+{
+ // first, find the symbol table
+ size_t off = ntHeader->FileHeader.PointerToSymbolTable;
+ if (off == 0)
+ return QByteArrayView();
+
+ // skip the symbol table to find the string table after it
+ constexpr size_t SymbolEntrySize = 18;
+ size_t size = ntHeader->FileHeader.NumberOfSymbols;
+ if (qMulOverflow<SymbolEntrySize>(size, &size)
+ || qAddOverflow(off, size, &off)
+ || qAddOverflow(off, sizeof(DWORD), &off)
+ || off > size_t(data.size()))
+ return error.toosmall(), std::nullopt;
+
+ off -= sizeof(DWORD);
+
+ // we've found the string table, ensure it's big enough
+ size = qFromUnaligned<DWORD>(data.data() + off);
+ if (size_t end; qAddOverflow(off, size, &end) || end > size_t(data.size()))
+ return error.toosmall(), std::nullopt;
+
+ // the conversion to signed is fine because we checked above it wasn't
+ // bigger than data.size()
+ return data.sliced(off, size);
+}
+
+static QLatin1StringView findSectionName(const IMAGE_SECTION_HEADER *section, QByteArrayView stringTable)
+{
+ auto ptr = reinterpret_cast<const char *>(section->Name);
+ qsizetype n = qstrnlen(ptr, sizeof(section->Name));
+ if (ptr[0] == '/' && !stringTable.isEmpty()) {
+ // long section name
+ // Microsoft's link.exe does not use these and will truncate the
+ // section name to fit section->Name. GNU binutils' ld does use long
+ // section names on executable image files by default (can be disabled
+ // using --disable-long-section-names). LLVM's lld does generate a
+ // string table in MinGW mode, but does not use it for our section.
+
+ static_assert(sizeof(section->Name) - 1 < std::numeric_limits<uint>::digits10);
+ bool ok;
+ qsizetype offset = QByteArrayView(ptr + 1, n - 1).toUInt(&ok);
+ if (!ok || offset >= stringTable.size())
+ return {};
+
+ ptr = stringTable.data() + offset;
+ n = qstrnlen(ptr, stringTable.size() - offset);
+ }
+
+ return {ptr, n};
+}
+
+QLibraryScanResult QCoffPeParser::parse(QByteArrayView data, QString *errMsg)
+{
+ ErrorMaker error(errMsg);
+ auto ntHeaders = checkNtHeaders(data, error);
+ if (!ntHeaders)
+ return {};
+
+ auto section = findSectionTable(data, ntHeaders, error);
+ if (!ntHeaders)
+ return {};
+
+ QByteArrayView stringTable;
+ if (auto optional = findStringTable(data, ntHeaders, error))
+ stringTable = *optional;
+ else
+ return {};
+
+ // scan the sections now
+ const auto sectionTableEnd = section + ntHeaders->FileHeader.NumberOfSections;
+ for ( ; section < sectionTableEnd; ++section) {
+ QLatin1StringView sectionName = findSectionName(section, stringTable);
+ peDebug << "section" << sectionName << SectionDebug{section};
+ if (IncludeValidityChecks && sectionName.isEmpty())
+ return error(QLibrary::tr("a section name is empty or extends past the end of the file"));
+
+ size_t offset = section->PointerToRawData;
+ if (size_t end; qAddOverflow<size_t>(offset, section->SizeOfRawData, &end)
+ || end > size_t(data.size()))
+ return error(QLibrary::tr("section contents extend past the end of the file"));
+
+ DWORD type = section->Characteristics
+ & (IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA
+ | IMAGE_SCN_CNT_UNINITIALIZED_DATA);
+ if (type != IMAGE_SCN_CNT_INITIALIZED_DATA)
+ continue;
+
+ // if we do have a string table, the name may be complete
+ if (sectionName != truncatedSectionName && sectionName != metadataSectionName())
+ continue;
+ peDebug << "found .qtmetadata section";
+
+ size_t size = qMin(section->SizeOfRawData, section->Misc.VirtualSize);
+ if (size < sizeof(QPluginMetaData::MagicHeader))
+ return error(QLibrary::tr(".qtmetadata section is too small"));
+ if (IncludeValidityChecks) {
+ QByteArrayView expectedMagic = QByteArrayView::fromArray(QPluginMetaData::MagicString);
+ QByteArrayView actualMagic = data.sliced(offset, expectedMagic.size());
+ if (expectedMagic != actualMagic)
+ return error(QLibrary::tr(".qtmetadata section has incorrect magic"));
+
+ if (section->Characteristics & IMAGE_SCN_MEM_WRITE)
+ return error(QLibrary::tr(".qtmetadata section is writable"));
+ if (section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ return error(QLibrary::tr(".qtmetadata section is executable"));
+ }
+
+ return { qsizetype(offset + sizeof(QPluginMetaData::MagicString)),
+ qsizetype(size - sizeof(QPluginMetaData::MagicString)) };
+ }
+
+ return error.notfound();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qcoffpeparser_p.h b/src/corelib/plugin/qcoffpeparser_p.h
new file mode 100644
index 0000000000..19c650fee0
--- /dev/null
+++ b/src/corelib/plugin/qcoffpeparser_p.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+// no, this is not a misspelling of "coffeeparser"
+#ifndef QCOFFPEPARSER_H
+#define QCOFFPEPARSER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qlibrary_p.h"
+
+#if defined(Q_OS_WIN)
+
+QT_BEGIN_NAMESPACE
+
+struct QCoffPeParser
+{
+ static QLibraryScanResult parse(QByteArrayView data, QString *errMsg);
+};
+
+QT_END_NAMESPACE
+
+#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+
+#endif // QCOFFPEPARSER_H
diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp
index 13eee3539e..7f6271cde4 100644
--- a/src/corelib/plugin/qelfparser_p.cpp
+++ b/src/corelib/plugin/qelfparser_p.cpp
@@ -1,238 +1,789 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qelfparser_p.h"
-#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
+#ifdef Q_OF_ELF
#include "qlibrary_p.h"
-#include <qdebug.h>
+
+#include <qloggingcategory.h>
+#include <qnumeric.h>
+#include <qsysinfo.h>
+
+#if __has_include(<elf.h>)
+# include <elf.h>
+#elif __has_include(<sys/elf.h>)
+# include <sys/elf.h>
+#else
+# error "Need ELF header to parse plugins."
+#endif
QT_BEGIN_NAMESPACE
-// #define QELFPARSER_DEBUG 1
-
-const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *sh)
-{
- sh->name = read<qelfword_t>(data);
- data += sizeof(qelfword_t); // sh_name
- sh->type = read<qelfword_t>(data);
- data += sizeof(qelfword_t) // sh_type
- + sizeof(qelfaddr_t) // sh_flags
- + sizeof(qelfaddr_t); // sh_addr
- sh->offset = read<qelfoff_t>(data);
- data += sizeof(qelfoff_t); // sh_offset
- sh->size = read<qelfoff_t>(data);
- data += sizeof(qelfoff_t); // sh_size
- return data;
-}
+using namespace Qt::StringLiterals;
-int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, qsizetype *pos, qsizetype *sectionlen)
-{
+// ### Qt7: propagate the constant and eliminate dead code
+static constexpr bool ElfNotesAreMandatory = QT_VERSION >= QT_VERSION_CHECK(7,0,0);
+
+// Whether we include some extra validity checks
+// (checks to ensure we don't read out-of-bounds are always included)
+static constexpr bool IncludeValidityChecks = true;
+
+#ifdef QT_BUILD_INTERNAL
+# define QELFPARSER_DEBUG
+#endif
#if defined(QELFPARSER_DEBUG)
- qDebug() << "QElfParser::parse " << library;
+static Q_LOGGING_CATEGORY(lcElfParser, "qt.core.plugin.elfparser")
+# define qEDebug qCDebug(lcElfParser) << reinterpret_cast<const char16_t *>(error.errMsg->constData()) << ':'
+#else
+# define qEDebug if (false) {} else QNoDebug()
#endif
- if (fdlen < 64){
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library, QLibrary::tr("file too small"));
- return NotElf;
- }
- const char *data = dataStart;
- if (qstrncmp(data, "\177ELF", 4) != 0) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is not an ELF object").arg(library);
- return NotElf;
- }
- // 32 or 64 bit
- if (data[4] != 1 && data[4] != 2) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("odd cpu architecture"));
- return Corrupt;
- }
- m_bits = (data[4] << 5);
-
- /* If you remove this check, to read ELF objects of a different arch, please make sure you modify the typedefs
- to match the _plugin_ architecture.
- */
- if ((sizeof(void*) == 4 && m_bits != 32) || (sizeof(void*) == 8 && m_bits != 64)) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("wrong cpu architecture"));
- return Corrupt;
- }
- // endian
- if (data[5] == 0) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("odd endianness"));
- return Corrupt;
- }
- m_endian = (data[5] == 1 ? ElfLittleEndian : ElfBigEndian);
-
- data += 16 // e_ident
- + sizeof(qelfhalf_t) // e_type
- + sizeof(qelfhalf_t) // e_machine
- + sizeof(qelfword_t) // e_version
- + sizeof(qelfaddr_t) // e_entry
- + sizeof(qelfoff_t); // e_phoff
-
- qelfoff_t e_shoff = read<qelfoff_t> (data);
- data += sizeof(qelfoff_t) // e_shoff
- + sizeof(qelfword_t); // e_flags
-
- qelfhalf_t e_shsize = read<qelfhalf_t> (data);
-
- if (e_shsize > fdlen) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("unexpected e_shsize"));
- return Corrupt;
- }
-
- data += sizeof(qelfhalf_t) // e_ehsize
- + sizeof(qelfhalf_t) // e_phentsize
- + sizeof(qelfhalf_t); // e_phnum
-
- qelfhalf_t e_shentsize = read<qelfhalf_t> (data);
-
- if (e_shentsize % 4){
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("unexpected e_shentsize"));
- return Corrupt;
- }
- data += sizeof(qelfhalf_t); // e_shentsize
- qelfhalf_t e_shnum = read<qelfhalf_t> (data);
- data += sizeof(qelfhalf_t); // e_shnum
- qelfhalf_t e_shtrndx = read<qelfhalf_t> (data);
- data += sizeof(qelfhalf_t); // e_shtrndx
-
- if ((quint32)(e_shnum * e_shentsize) > fdlen) {
- if (lib) {
- const QString message =
- QLibrary::tr("announced %n section(s), each %1 byte(s), exceed file size",
- nullptr, int(e_shnum)).arg(e_shentsize);
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, message);
- }
- return Corrupt;
- }
+#ifndef PT_GNU_EH_FRAME
+# define PT_GNU_EH_FRAME 0x6474e550
+#endif
+#ifndef PT_GNU_STACK
+# define PT_GNU_STACK 0x6474e551
+#endif
+#ifndef PT_GNU_RELRO
+# define PT_GNU_RELRO 0x6474e552
+#endif
+#ifndef PT_GNU_PROPERTY
+# define PT_GNU_PROPERTY 0x6474e553
+#endif
-#if defined(QELFPARSER_DEBUG)
- qDebug() << e_shnum << "sections starting at " << ("0x" + QByteArray::number(e_shoff, 16)).data() << "each" << e_shentsize << "bytes";
+#ifndef PN_XNUM
+# define PN_XNUM 0xffff
#endif
- ElfSectionHeader strtab;
- qulonglong soff = e_shoff + qelfword_t(e_shentsize) * qelfword_t(e_shtrndx);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wunused-const-variable")
+
+namespace {
+template <QSysInfo::Endian Order> struct ElfEndianTraits
+{
+ static constexpr unsigned char DataOrder = ELFDATA2LSB;
+ template <typename T> static T fromEndian(T value) { return qFromLittleEndian(value); }
+};
+template <> struct ElfEndianTraits<QSysInfo::BigEndian>
+{
+ static constexpr unsigned char DataOrder = ELFDATA2MSB;
+ template <typename T> static T fromEndian(T value) { return qFromBigEndian(value); }
+};
+
+template <typename EquivalentPointerType> struct ElfTypeTraits
+{
+ static constexpr unsigned char Class = ELFCLASS64;
+
+ // integer types
+ using Half = Elf64_Half;
+ using Word = Elf64_Word;
+ using Addr = Elf64_Addr;
+ using Off = Elf64_Off;
- if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)")
- .arg(library, QLibrary::tr("shstrtab section header seems to be at %1")
- .arg(QString::number(soff, 16)));
- return Corrupt;
+ // structure types
+ using Ehdr = Elf64_Ehdr;
+ using Shdr = Elf64_Shdr;
+ using Phdr = Elf64_Phdr;
+ using Nhdr = Elf64_Nhdr;
+};
+template <> struct ElfTypeTraits<quint32>
+{
+ static constexpr unsigned char Class = ELFCLASS32;
+
+ // integer types
+ using Half = Elf32_Half;
+ using Word = Elf32_Word;
+ using Addr = Elf32_Addr;
+ using Off = Elf32_Off;
+
+ // structure types
+ using Ehdr = Elf32_Ehdr;
+ using Shdr = Elf32_Shdr;
+ using Phdr = Elf32_Phdr;
+ using Nhdr = Elf32_Nhdr;
+};
+
+struct ElfMachineCheck
+{
+ static const Elf32_Half ExpectedMachine =
+#if 0
+ // nothing
+#elif defined(Q_PROCESSOR_ALPHA)
+ EM_ALPHA
+#elif defined(Q_PROCESSOR_ARM_32)
+ EM_ARM
+#elif defined(Q_PROCESSOR_ARM_64)
+ EM_AARCH64
+#elif defined(Q_PROCESSOR_BLACKFIN)
+ EM_BLACKFIN
+#elif defined(Q_PROCESSOR_HPPA)
+ EM_PARISC
+#elif defined(Q_PROCESSOR_IA64)
+ EM_IA_64
+#elif defined(Q_PROCESSOR_LOONGARCH)
+ EM_LOONGARCH
+#elif defined(Q_PROCESSOR_M68K)
+ EM_68K
+#elif defined(Q_PROCESSOR_MIPS)
+ EM_MIPS
+#elif defined(Q_PROCESSOR_POWER_32)
+ EM_PPC
+#elif defined(Q_PROCESSOR_POWER_64)
+ EM_PPC64
+#elif defined(Q_PROCESSOR_RISCV)
+ EM_RISCV
+#elif defined(Q_PROCESSOR_S390)
+ EM_S390
+#elif defined(Q_PROCESSOR_SH)
+ EM_SH
+#elif defined(Q_PROCESSOR_SPARC_V9)
+ EM_SPARCV9
+#elif defined(Q_PROCESSOR_SPARC_64)
+ EM_SPARCV9
+#elif defined(Q_PROCESSOR_SPARC)
+ EM_SPARC
+#elif defined(Q_PROCESSOR_WASM)
+#elif defined(Q_PROCESSOR_X86_32)
+ EM_386
+#elif defined(Q_PROCESSOR_X86_64)
+ EM_X86_64
+#else
+# error "Unknown Q_PROCESSOR_xxx macro, please update."
+ EM_NONE
+#endif
+ ;
+};
+
+struct ElfHeaderCommonCheck
+{
+ static_assert(std::is_same_v<decltype(Elf32_Ehdr::e_ident), decltype(Elf64_Ehdr::e_ident)>,
+ "e_ident field is not the same in both Elf32_Ehdr and Elf64_Ehdr");
+
+ // bytes 0-3
+ static bool checkElfMagic(const uchar *ident)
+ {
+ return memcmp(ident, ELFMAG, SELFMAG) == 0;
+ }
+
+ // byte 6
+ static bool checkElfVersion(const uchar *ident)
+ {
+ uchar elfversion = ident[EI_VERSION];
+ return elfversion == EV_CURRENT;
}
- parseSectionHeader(dataStart + soff, &strtab);
- m_stringTableFileOffset = strtab.offset;
+ struct CommonHeader {
+ Elf32_Half type;
+ Elf32_Half machine;
+ Elf32_Word version;
+ };
+};
+
+template <typename EquivalentPointerType = quintptr, QSysInfo::Endian Order = QSysInfo::ByteOrder>
+struct ElfHeaderCheck : public ElfHeaderCommonCheck
+{
+ using TypeTraits = ElfTypeTraits<EquivalentPointerType>;
+ using EndianTraits = ElfEndianTraits<Order>;
+ using Ehdr = typename TypeTraits::Ehdr;
- if ((quint32)(strtab.offset + strtab.size) > fdlen || strtab.offset == 0) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)")
- .arg(library, QLibrary::tr("string table seems to be at %1")
- .arg(QString::number(strtab.offset, 16)));
- return Corrupt;
+ // byte 4
+ static bool checkClass(const uchar *ident)
+ {
+ uchar klass = ident[EI_CLASS];
+ return klass == TypeTraits::Class;
}
-#if defined(QELFPARSER_DEBUG)
- qDebug(".shstrtab at 0x%s", QByteArray::number(m_stringTableFileOffset, 16).data());
+ // byte 5
+ static bool checkDataOrder(const uchar *ident)
+ {
+ uchar data = ident[EI_DATA];
+ return data == EndianTraits::DataOrder;
+ }
+
+ // byte 7
+ static bool checkOsAbi(const uchar *ident)
+ {
+ uchar osabi = ident[EI_OSABI];
+ // we don't check
+ Q_UNUSED(osabi);
+ return true;
+ }
+
+ // byte 8
+ static bool checkAbiVersion(const uchar *ident)
+ {
+ uchar abiversion = ident[EI_ABIVERSION];
+ // we don't check (and I don't know anyone who uses this)
+ Q_UNUSED(abiversion);
+ return true;
+ }
+
+ // bytes 9-16
+ static bool checkPadding(const uchar *ident)
+ {
+ // why would we check this?
+ Q_UNUSED(ident);
+ return true;
+ }
+
+ static bool checkIdent(const Ehdr &header)
+ {
+ return checkElfMagic(header.e_ident)
+ && checkClass(header.e_ident)
+ && checkDataOrder(header.e_ident)
+ && checkElfVersion(header.e_ident)
+ && checkOsAbi(header.e_ident)
+ && checkAbiVersion(header.e_ident)
+ && checkPadding(header.e_ident);
+ }
+
+ static bool checkType(const Ehdr &header)
+ {
+ return header.e_type == ET_DYN;
+ }
+
+ static bool checkMachine(const Ehdr &header)
+ {
+ return header.e_machine == ElfMachineCheck::ExpectedMachine;
+ }
+
+ static bool checkFileVersion(const Ehdr &header)
+ {
+ return header.e_version == EV_CURRENT;
+ }
+
+ static bool checkHeader(const Ehdr &header)
+ {
+ if (!checkIdent(header))
+ return false;
+ if (!IncludeValidityChecks)
+ return true;
+ return checkType(header)
+ && checkMachine(header)
+ && checkFileVersion(header);
+ }
+
+ Q_DECL_COLD_FUNCTION static QString explainCheckFailure(const Ehdr &header)
+ {
+ if (!checkElfMagic(header.e_ident))
+ return QLibrary::tr("invalid signature");
+ if (!checkClass(header.e_ident))
+ return QLibrary::tr("file is for a different word size");
+ if (!checkDataOrder(header.e_ident))
+ return QLibrary::tr("file is for the wrong endianness");
+ if (!checkElfVersion(header.e_ident) || !checkFileVersion(header))
+ return QLibrary::tr("file has an unknown ELF version");
+ if (!checkOsAbi(header.e_ident) || !checkAbiVersion(header.e_ident))
+ return QLibrary::tr("file has an unexpected ABI");
+ if (!checkType(header))
+ return QLibrary::tr("file is not a shared object");
+ if (!checkMachine(header))
+ return QLibrary::tr("file is for a different processor");
+ return QString();
+ }
+
+ static CommonHeader extractCommonHeader(const uchar *data)
+ {
+ auto header = reinterpret_cast<const Ehdr *>(data);
+ CommonHeader r;
+ r.type = EndianTraits::fromEndian(header->e_type);
+ r.machine = EndianTraits::fromEndian(header->e_machine);
+ r.version = EndianTraits::fromEndian(header->e_version);
+ return r;
+ }
+};
+
+struct ElfHeaderDebug { const uchar *e_ident; };
+Q_DECL_UNUSED Q_DECL_COLD_FUNCTION static QDebug &operator<<(QDebug &d, ElfHeaderDebug h)
+{
+ const uchar *e_ident = h.e_ident;
+ if (!ElfHeaderCommonCheck::checkElfMagic(e_ident)) {
+ d << "Not an ELF file (invalid signature)";
+ return d;
+ }
+
+ QDebugStateSaver saver(d);
+ d.nospace();
+ quint8 elfclass = e_ident[EI_CLASS];
+ switch (elfclass) {
+ case ELFCLASSNONE:
+ default:
+ d << "Invalid ELF file (class " << e_ident[EI_CLASS] << "), ";
+ break;
+ case ELFCLASS32:
+ d << "ELF 32-bit ";
+ break;
+ case ELFCLASS64:
+ d << "ELF 64-bit ";
+ break;
+ }
+
+ quint8 dataorder = e_ident[EI_DATA];
+ switch (dataorder) {
+ case ELFDATANONE:
+ default:
+ d << "invalid endianness (" << e_ident[EI_DATA] << ')';
+ break;
+ case ELFDATA2LSB:
+ d << "LSB";
+ break;
+ case ELFDATA2MSB:
+ d << "MSB";
+ break;
+ }
+
+ switch (e_ident[EI_OSABI]) {
+ case ELFOSABI_SYSV: d << " (SYSV"; break;
+ case ELFOSABI_HPUX: d << " (HP-UX"; break;
+ case ELFOSABI_NETBSD: d << " (NetBSD"; break;
+ case ELFOSABI_LINUX: d << " (GNU/Linux"; break;
+ case ELFOSABI_SOLARIS: d << " (Solaris"; break;
+ case ELFOSABI_AIX: d << " (AIX"; break;
+ case ELFOSABI_IRIX: d << " (IRIX"; break;
+ case ELFOSABI_FREEBSD: d << " (FreeBSD"; break;
+ case ELFOSABI_OPENBSD: d << " (OpenBSD"; break;
+ default: d << " (OS ABI " << e_ident[EI_VERSION]; break;
+ }
+
+ if (e_ident[EI_ABIVERSION])
+ d << " v" << e_ident[EI_ABIVERSION];
+ d << ')';
+
+ if (e_ident[EI_VERSION] != 1) {
+ d << ", file version " << e_ident[EI_VERSION];
+ return d;
+ }
+
+ ElfHeaderCommonCheck::CommonHeader r;
+ if (elfclass == ELFCLASS64 && dataorder == ELFDATA2LSB)
+ r = ElfHeaderCheck<quint64, QSysInfo::LittleEndian>::extractCommonHeader(e_ident);
+ else if (elfclass == ELFCLASS32 && dataorder == ELFDATA2LSB)
+ r = ElfHeaderCheck<quint32, QSysInfo::LittleEndian>::extractCommonHeader(e_ident);
+ else if (elfclass == ELFCLASS64 && dataorder == ELFDATA2MSB)
+ r = ElfHeaderCheck<quint64, QSysInfo::BigEndian>::extractCommonHeader(e_ident);
+ else if (elfclass == ELFCLASS32 && dataorder == ELFDATA2MSB)
+ r = ElfHeaderCheck<quint32, QSysInfo::BigEndian>::extractCommonHeader(e_ident);
+ else
+ return d;
+
+ d << ", version " << r.version;
+
+ switch (r.type) {
+ case ET_NONE: d << ", no type"; break;
+ case ET_REL: d << ", relocatable"; break;
+ case ET_EXEC: d << ", executable"; break;
+ case ET_DYN: d << ", shared library or PIC executable"; break;
+ case ET_CORE: d << ", core dump"; break;
+ default: d << ", unknown type " << r.type; break;
+ }
+
+ switch (r.machine) {
+ // list definitely not exhaustive!
+ case EM_NONE: d << ", no machine"; break;
+ case EM_ALPHA: d << ", Alpha"; break;
+ case EM_68K: d << ", MC68000"; break;
+ case EM_ARM: d << ", ARM"; break;
+ case EM_AARCH64: d << ", AArch64"; break;
+#ifdef EM_BLACKFIN
+ case EM_BLACKFIN: d << ", Blackfin"; break;
+#endif
+ case EM_IA_64: d << ", IA-64"; break;
+#ifdef EM_LOONGARCH
+ case EM_LOONGARCH: d << ", LoongArch"; break;
+#endif
+ case EM_MIPS: d << ", MIPS"; break;
+ case EM_PARISC: d << ", HPPA"; break;
+ case EM_PPC: d << ", PowerPC"; break;
+ case EM_PPC64: d << ", PowerPC 64-bit"; break;
+#ifdef EM_RISCV
+ case EM_RISCV: d << ", RISC-V"; break;
#endif
+#ifdef EM_S390
+ case EM_S390: d << ", S/390"; break;
+#endif
+ case EM_SH: d << ", SuperH"; break;
+ case EM_SPARC: d << ", SPARC"; break;
+ case EM_SPARCV9: d << ", SPARCv9"; break;
+ case EM_386: d << ", i386"; break;
+ case EM_X86_64: d << ", x86-64"; break;
+ default: d << ", other machine type " << r.machine; break;
+ }
- const char *s = dataStart + e_shoff;
- for (int i = 0; i < e_shnum; ++i) {
- ElfSectionHeader sh;
- parseSectionHeader(s, &sh);
- if (sh.name == 0) {
- s += e_shentsize;
- continue;
+ return d;
+}
+
+struct ElfSectionDebug { const ElfHeaderCheck<>::TypeTraits::Shdr *shdr; };
+Q_DECL_UNUSED static QDebug &operator<<(QDebug &d, ElfSectionDebug s)
+{
+ // not exhaustive, just a few common things
+ QDebugStateSaver saver(d);
+ d << Qt::hex << Qt::showbase;
+ d << "type";
+ switch (s.shdr->sh_type) {
+ case SHT_NULL: d << "NULL"; break;
+ case SHT_PROGBITS: d << "PROGBITS"; break;
+ case SHT_SYMTAB: d << "SYMTAB"; break;
+ case SHT_STRTAB: d << "STRTAB"; break;
+ case SHT_RELA: d << "RELA"; break;
+ case SHT_HASH: d << "HASH"; break;
+ case SHT_DYNAMIC: d << "DYNAMIC"; break;
+ case SHT_NOTE: d << "NOTE"; break;
+ case SHT_NOBITS: d << "NOBITS"; break;
+ case SHT_DYNSYM: d << "DYNSYM"; break;
+ case SHT_INIT_ARRAY: d << "INIT_ARRAY"; break;
+ case SHT_FINI_ARRAY: d << "FINI_ARRAY"; break;
+ default: d << s.shdr->sh_type;
+ }
+
+ d << "flags";
+ d.nospace();
+ if (s.shdr->sh_flags & SHF_WRITE)
+ d << 'W';
+ if (s.shdr->sh_flags & SHF_ALLOC)
+ d << 'A';
+ if (s.shdr->sh_flags & SHF_EXECINSTR)
+ d << 'X';
+ if (s.shdr->sh_flags & SHF_STRINGS)
+ d << 'S';
+ if (s.shdr->sh_flags & SHF_TLS)
+ d << 'T';
+
+ d.space() << "offset" << s.shdr->sh_offset << "size" << s.shdr->sh_size;
+ return d;
+}
+
+struct ElfProgramDebug { const ElfHeaderCheck<>::TypeTraits::Phdr *phdr; };
+Q_DECL_UNUSED static QDebug &operator<<(QDebug &d, ElfProgramDebug p)
+{
+ QDebugStateSaver saved(d);
+ d << Qt::hex << Qt::showbase << "program";
+ switch (p.phdr->p_type) {
+ case PT_NULL: d << "NULL"; break;
+ case PT_LOAD: d << "LOAD"; break;
+ case PT_DYNAMIC: d << "DYNAMIC"; break;
+ case PT_INTERP: d << "INTERP"; break;
+ case PT_NOTE: d << "NOTE"; break;
+ case PT_PHDR: d << "PHDR"; break;
+ case PT_TLS: d << "TLS"; break;
+ case PT_GNU_EH_FRAME: d << "GNU_EH_FRAME"; break;
+ case PT_GNU_STACK: d << "GNU_STACK"; break;
+ case PT_GNU_RELRO: d << "GNU_RELRO"; break;
+ case PT_GNU_PROPERTY: d << "GNU_PROPERTY"; break;
+ default: d << "type" << p.phdr->p_type; break;
+ }
+
+ d << "offset" << p.phdr->p_offset
+ << "virtaddr" << p.phdr->p_vaddr
+ << "filesz" << p.phdr->p_filesz
+ << "memsz" << p.phdr->p_memsz
+ << "align" << p.phdr->p_align
+ << "flags";
+
+ d.nospace();
+ if (p.phdr->p_flags & PF_R)
+ d << 'R';
+ if (p.phdr->p_flags & PF_W)
+ d << 'W';
+ if (p.phdr->p_flags & PF_X)
+ d << 'X';
+
+ return d;
+}
+
+struct ErrorMaker
+{
+ QString *errMsg;
+ constexpr ErrorMaker(QString *errMsg) : errMsg(errMsg) {}
+
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult operator()(QString &&text) const
+ {
+ *errMsg = QLibrary::tr("'%1' is not a valid ELF object (%2)").arg(*errMsg, std::move(text));
+ return {};
+ }
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult notplugin(QString &&explanation) const
+ {
+ *errMsg = QLibrary::tr("'%1' is not a Qt plugin (%2)").arg(*errMsg, explanation);
+ return {};
+ }
+
+ Q_DECL_COLD_FUNCTION QLibraryScanResult notfound() const
+ {
+ return notplugin(QLibrary::tr("metadata not found"));
+ }
+};
+} // unnamed namespace
+
+QT_WARNING_POP
+
+using T = ElfHeaderCheck<>::TypeTraits;
+
+template <typename F>
+static bool scanProgramHeaders(QByteArrayView data, const ErrorMaker &error, F f)
+{
+ auto header = reinterpret_cast<const T::Ehdr *>(data.data());
+ Q_UNUSED(error);
+
+ auto phdr = reinterpret_cast<const T::Phdr *>(data.data() + header->e_phoff);
+ auto phdr_end = phdr + header->e_phnum;
+ for ( ; phdr != phdr_end; ++phdr) {
+ if (!f(phdr))
+ return false;
+ }
+ return true;
+}
+
+static bool preScanProgramHeaders(QByteArrayView data, const ErrorMaker &error)
+{
+ auto header = reinterpret_cast<const T::Ehdr *>(data.data());
+
+ // first, validate the extent of the full program header table
+ T::Word e_phnum = header->e_phnum;
+ if (e_phnum == PN_XNUM)
+ return error(QLibrary::tr("unimplemented: PN_XNUM program headers")), false;
+ T::Off offset = e_phnum * sizeof(T::Phdr); // can't overflow due to size of T::Half
+ if (qAddOverflow(offset, header->e_phoff, &offset) || offset > size_t(data.size()))
+ return error(QLibrary::tr("program header table extends past the end of the file")), false;
+
+ // confirm validity
+ bool hasCode = false;
+ auto checker = [&](const T::Phdr *phdr) {
+ qEDebug << ElfProgramDebug{phdr};
+
+ if (T::Off end; qAddOverflow(phdr->p_offset, phdr->p_filesz, &end)
+ || end > size_t(data.size()))
+ return error(QLibrary::tr("a program header entry extends past the end of the file")), false;
+
+ // this is not a validity check, it's to exclude debug symbol files
+ if (phdr->p_type == PT_LOAD && phdr->p_filesz != 0 && (phdr->p_flags & PF_X))
+ hasCode = true;
+
+ // this probably applies to all segments, but we'll only apply it to notes
+ if (phdr->p_type == PT_NOTE && qPopulationCount(phdr->p_align) == 1
+ && phdr->p_offset & (phdr->p_align - 1)) {
+ return error(QLibrary::tr("a note segment start is not properly aligned "
+ "(offset 0x%1, alignment %2)")
+ .arg(phdr->p_offset, 6, 16, QChar(u'0'))
+ .arg(phdr->p_align)), false;
}
- const char *shnam = dataStart + m_stringTableFileOffset + sh.name;
-
- if (m_stringTableFileOffset + sh.name > fdlen) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)")
- .arg(library, QLibrary::tr("section name %1 of %2 behind end of file")
- .arg(i).arg(e_shnum));
- return Corrupt;
+
+ return true;
+ };
+ if (!scanProgramHeaders(data, error, checker))
+ return false;
+ if (!hasCode)
+ return error.notplugin(QLibrary::tr("file has no code")), false;
+ return true;
+}
+
+static QLibraryScanResult scanProgramHeadersForNotes(QByteArrayView data, const ErrorMaker &error)
+{
+ // minimum metadata payload is 2 bytes
+ constexpr size_t MinPayloadSize = sizeof(QPluginMetaData::Header) + 2;
+ constexpr qptrdiff MinNoteSize = sizeof(QPluginMetaData::ElfNoteHeader) + 2;
+ constexpr size_t NoteNameSize = sizeof(QPluginMetaData::ElfNoteHeader::name);
+ constexpr size_t NoteAlignment = alignof(QPluginMetaData::ElfNoteHeader);
+ constexpr qptrdiff PayloadStartDelta = offsetof(QPluginMetaData::ElfNoteHeader, header);
+ static_assert(MinNoteSize > PayloadStartDelta);
+ static_assert((PayloadStartDelta & (NoteAlignment - 1)) == 0);
+
+ QLibraryScanResult r = {};
+ auto noteFinder = [&](const T::Phdr *phdr) {
+ if (phdr->p_type != PT_NOTE || phdr->p_align != NoteAlignment)
+ return true;
+
+ // check for signed integer overflows, to avoid issues with the
+ // arithmetic below
+ if (qptrdiff(phdr->p_filesz) < 0) {
+ auto h = reinterpret_cast<const T::Ehdr *>(data.data());
+ auto segments = reinterpret_cast<const T::Phdr *>(data.data() + h->e_phoff);
+ qEDebug << "segment" << (phdr - segments) << "contains a note with size"
+ << Qt::hex << Qt::showbase << phdr->p_filesz
+ << "which is larger than half the virtual memory space";
+ return true;
}
-#if defined(QELFPARSER_DEBUG)
- qDebug() << "++++" << i << shnam;
-#endif
+ // iterate over the notes in this segment
+ T::Off offset = phdr->p_offset;
+ const T::Off end_offset = offset + phdr->p_filesz;
+ while (qptrdiff(end_offset - offset) >= MinNoteSize) {
+ auto nhdr = reinterpret_cast<const T::Nhdr *>(data.data() + offset);
+ T::Word n_namesz = nhdr->n_namesz;
+ T::Word n_descsz = nhdr->n_descsz;
+ T::Word n_type = nhdr->n_type;
- if (qstrcmp(shnam, ".qtmetadata") == 0 || qstrcmp(shnam, ".rodata") == 0) {
- if (!(sh.type & 0x1)) {
- if (shnam[1] == 'r') {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)")
- .arg(library, QLibrary::tr("empty .rodata. not a library."));
- return Corrupt;
- }
-#if defined(QELFPARSER_DEBUG)
- qDebug()<<"section is not program data. skipped.";
-#endif
- s += e_shentsize;
- continue;
- }
+ // overflow check: calculate where the next note will be, if it exists
+ T::Off next_offset = offset;
+ next_offset += sizeof(T::Nhdr); // can't overflow (we checked above)
+ next_offset += NoteAlignment - 3; // offset is aligned, this can't overflow
+ if (qAddOverflow<T::Off>(next_offset, n_namesz, &next_offset))
+ break;
+ next_offset &= -NoteAlignment;
- if (sh.offset == 0 || (sh.offset + sh.size) > fdlen || sh.size < 1) {
- if (lib)
- lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)")
- .arg(library, QLibrary::tr("missing section data. This is not a library."));
- return Corrupt;
+ next_offset += NoteAlignment - 3; // offset is aligned, this can't overflow
+ if (qAddOverflow<T::Off>(next_offset, n_descsz, &next_offset))
+ break;
+ next_offset &= -NoteAlignment;
+ if (next_offset > end_offset)
+ break;
+
+ if (n_namesz == NoteNameSize && n_descsz >= MinPayloadSize
+ && n_type == QPluginMetaData::ElfNoteHeader::NoteType
+ && memcmp(nhdr + 1, QPluginMetaData::ElfNoteHeader::NoteName, NoteNameSize) == 0) {
+ // yes, it's our note
+ r.pos = offset + PayloadStartDelta;
+ r.length = nhdr->n_descsz;
+ return false;
}
- *pos = sh.offset;
- *sectionlen = sh.size;
- if (shnam[1] == 'q')
- return QtMetaDataSection;
+ offset = next_offset;
}
- s += e_shentsize;
+ return true;
+ };
+ scanProgramHeaders(data, error, noteFinder);
+
+ if (!r.length)
+ return r;
+
+ qEDebug << "found Qt metadata in ELF note at"
+ << Qt::hex << Qt::showbase << r.pos << "size" << Qt::reset << r.length;
+ return r;
+}
+
+static QLibraryScanResult scanSections(QByteArrayView data, const ErrorMaker &error)
+{
+ auto header = reinterpret_cast<const T::Ehdr *>(data.data());
+
+ // in order to find the .qtmetadata section, we need to:
+ // a) find the section table
+ // it's located at offset header->e_shoff
+ // validate it
+ T::Word e_shnum = header->e_shnum;
+ T::Off offset = e_shnum * sizeof(T::Shdr); // can't overflow due to size of T::Half
+ if (qAddOverflow(offset, header->e_shoff, &offset) || offset > size_t(data.size()))
+ return error(QLibrary::tr("section table extends past the end of the file"));
+
+ // b) find the section entry for the section header string table (shstrab)
+ // it's a section whose entry is pointed by e_shstrndx
+ auto sections = reinterpret_cast<const T::Shdr *>(data.data() + header->e_shoff);
+ auto sections_end = sections + e_shnum;
+ auto shdr = sections + header->e_shstrndx;
+
+ // validate the shstrtab
+ offset = shdr->sh_offset;
+ T::Off shstrtab_size = shdr->sh_size;
+ qEDebug << "shstrtab section is located at offset" << offset << "size" << shstrtab_size;
+ if (T::Off end; qAddOverflow<T::Off>(offset, shstrtab_size, &end)
+ || end > size_t(data.size()))
+ return error(QLibrary::tr("section header string table extends past the end of the file"));
+
+ // c) iterate over the sections to find .qtmetadata
+ const char *shstrtab_start = data.data() + offset;
+ shdr = sections;
+ for (int section = 0; shdr != sections_end; ++section, ++shdr) {
+ QLatin1StringView name;
+ if (shdr->sh_name < shstrtab_size) {
+ const char *namestart = shstrtab_start + shdr->sh_name;
+ size_t len = qstrnlen(namestart, shstrtab_size - shdr->sh_name);
+ name = QLatin1StringView(namestart, len);
+ }
+ qEDebug << "section" << section << "name" << name << ElfSectionDebug{shdr};
+
+ // sanity check the section
+ if (name.isNull())
+ return error(QLibrary::tr("a section name extends past the end of the file"));
+
+ // sections aren't allowed to extend past the end of the file, unless
+ // they are NOBITS sections
+ if (shdr->sh_type == SHT_NOBITS)
+ continue;
+ if (T::Off end; qAddOverflow(shdr->sh_offset, shdr->sh_size, &end)
+ || end > size_t(data.size())) {
+ return error(QLibrary::tr("section contents extend past the end of the file"));
+ }
+
+ if (name != ".qtmetadata"_L1)
+ continue;
+ qEDebug << "found .qtmetadata section";
+ if (shdr->sh_size < sizeof(QPluginMetaData::MagicHeader))
+ return error(QLibrary::tr(".qtmetadata section is too small"));
+
+ if (IncludeValidityChecks) {
+ QByteArrayView expectedMagic = QByteArrayView::fromArray(QPluginMetaData::MagicString);
+ QByteArrayView actualMagic = data.sliced(shdr->sh_offset, expectedMagic.size());
+ if (expectedMagic != actualMagic)
+ return error(QLibrary::tr(".qtmetadata section has incorrect magic"));
+
+ if (shdr->sh_flags & SHF_WRITE)
+ return error(QLibrary::tr(".qtmetadata section is writable"));
+ if (shdr->sh_flags & SHF_EXECINSTR)
+ return error(QLibrary::tr(".qtmetadata section is executable"));
+ }
+
+ return { qsizetype(shdr->sh_offset + sizeof(QPluginMetaData::MagicString)),
+ qsizetype(shdr->sh_size - sizeof(QPluginMetaData::MagicString)) };
+ }
+
+ // section .qtmetadata not found
+ return error.notfound();
+}
+
+QLibraryScanResult QElfParser::parse(QByteArrayView data, QString *errMsg)
+{
+ ErrorMaker error(errMsg);
+ if (size_t(data.size()) < sizeof(T::Ehdr)) {
+ qEDebug << "file too small:" << size_t(data.size());
+ return error(QLibrary::tr("file too small"));
+ }
+
+ qEDebug << ElfHeaderDebug{ reinterpret_cast<const uchar *>(data.data()) };
+
+ auto header = reinterpret_cast<const T::Ehdr *>(data.data());
+ if (!ElfHeaderCheck<>::checkHeader(*header))
+ return error(ElfHeaderCheck<>::explainCheckFailure(*header));
+
+ qEDebug << "contains" << header->e_phnum << "program headers of"
+ << header->e_phentsize << "bytes at offset" << header->e_phoff;
+ qEDebug << "contains" << header->e_shnum << "sections of" << header->e_shentsize
+ << "bytes at offset" << header->e_shoff
+ << "; section header string table (shstrtab) is entry" << header->e_shstrndx;
+
+ // some sanity checks
+ if constexpr (IncludeValidityChecks) {
+ if (header->e_phentsize != sizeof(T::Phdr))
+ return error(QLibrary::tr("unexpected program header entry size (%1)")
+ .arg(header->e_phentsize));
+ }
+
+ if (!preScanProgramHeaders(data, error))
+ return {};
+
+ if (QLibraryScanResult r = scanProgramHeadersForNotes(data, error); r.length)
+ return r;
+
+ if (!ElfNotesAreMandatory) {
+ if constexpr (IncludeValidityChecks) {
+ if (header->e_shentsize != sizeof(T::Shdr))
+ return error(QLibrary::tr("unexpected section entry size (%1)")
+ .arg(header->e_shentsize));
+ }
+ if (header->e_shoff == 0 || header->e_shnum == 0) {
+ // this is still a valid ELF file but we don't have a section table
+ qEDebug << "no section table present, not able to find Qt metadata";
+ return error.notfound();
+ }
+
+ if (header->e_shnum && header->e_shstrndx >= header->e_shnum)
+ return error(QLibrary::tr("e_shstrndx greater than the number of sections e_shnum (%1 >= %2)")
+ .arg(header->e_shstrndx).arg(header->e_shnum));
+ return scanSections(data, error);
}
- return NoQtSection;
+ return error.notfound();
}
QT_END_NAMESPACE
-#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+#endif // Q_OF_ELF
diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h
index cdf055329d..61498a859a 100644
--- a/src/corelib/plugin/qelfparser_p.h
+++ b/src/corelib/plugin/qelfparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QELFPARSER_P_H
#define QELFPARSER_P_H
@@ -52,55 +16,21 @@
//
#include <qendian.h>
-#include <private/qglobal_p.h>
+#include "qlibrary_p.h"
QT_REQUIRE_CONFIG(library);
-#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
+#ifdef Q_OF_ELF
QT_BEGIN_NAMESPACE
-class QString;
-class QLibraryPrivate;
-
-typedef quint16 qelfhalf_t;
-typedef quint32 qelfword_t;
-typedef quintptr qelfoff_t;
-typedef quintptr qelfaddr_t;
-
-class QElfParser
+struct QElfParser
{
-public:
- enum { QtMetaDataSection, NoQtSection, NotElf, Corrupt };
- enum {ElfLittleEndian = 0, ElfBigEndian = 1};
-
- struct ElfSectionHeader
- {
- qelfword_t name;
- qelfword_t type;
- qelfoff_t offset;
- qelfoff_t size;
- };
-
- int m_endian;
- int m_bits;
- qelfoff_t m_stringTableFileOffset;
-
- template <typename T>
- T read(const char *s)
- {
- if (m_endian == ElfBigEndian)
- return qFromBigEndian<T>(s);
- else
- return qFromLittleEndian<T>(s);
- }
-
- const char *parseSectionHeader(const char* s, ElfSectionHeader *sh);
- int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, qsizetype *pos, qsizetype *sectionlen);
+ static QLibraryScanResult parse(QByteArrayView data, QString *errMsg);
};
QT_END_NAMESPACE
-#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+#endif // Q_OF_ELF
#endif // QELFPARSER_P_H
diff --git a/src/corelib/plugin/qfactoryinterface.cpp b/src/corelib/plugin/qfactoryinterface.cpp
index b503c245c5..1a48d311aa 100644
--- a/src/corelib/plugin/qfactoryinterface.cpp
+++ b/src/corelib/plugin/qfactoryinterface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfactoryinterface.h"
diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h
index 3aec4ddd55..098b7d4201 100644
--- a/src/corelib/plugin/qfactoryinterface.h
+++ b/src/corelib/plugin/qfactoryinterface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFACTORYINTERFACE_H
#define QFACTORYINTERFACE_H
@@ -45,14 +9,13 @@
QT_BEGIN_NAMESPACE
-
struct Q_CORE_EXPORT QFactoryInterface
{
virtual ~QFactoryInterface();
virtual QStringList keys() const = 0;
};
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
Q_DECLARE_INTERFACE(QFactoryInterface, "org.qt-project.Qt.QFactoryInterface")
#endif
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index edadf7180a..e2d9a40cb4 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -1,120 +1,243 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfactoryloader_p.h"
#ifndef QT_NO_QOBJECT
-#include "qfactoryinterface.h"
-#include "qmap.h"
-#include <qdir.h>
-#include <qdebug.h>
-#include "qmutex.h"
-#include "qplugin.h"
-#include "qplugin_p.h"
-#include "qpluginloader.h"
-#include "private/qobject_p.h"
#include "private/qcoreapplication_p.h"
+#include "private/qduplicatetracker_p.h"
+#include "private/qloggingregistry_p.h"
+#include "private/qobject_p.h"
+#include "qcborarray.h"
#include "qcbormap.h"
+#include "qcborstreamreader.h"
#include "qcborvalue.h"
+#include "qdirlisting.h"
+#include "qfileinfo.h"
+#include "qjsonarray.h"
#include "qjsondocument.h"
-#include "qjsonvalue.h"
#include "qjsonobject.h"
-#include "qjsonarray.h"
-#include "private/qduplicatetracker_p.h"
+#include "qmutex.h"
+#include "qplugin.h"
+#include "qplugin_p.h"
+#include "qpluginloader.h"
+
+#if QT_CONFIG(library)
+# include "qlibrary_p.h"
+#endif
#include <qtcore_tracepoints_p.h>
+#include <map>
+#include <vector>
+
QT_BEGIN_NAMESPACE
-static inline int metaDataSignatureLength()
+using namespace Qt::StringLiterals;
+
+Q_TRACE_POINT(qtcore, QFactoryLoader_update, const QString &fileName);
+
+namespace {
+struct IterationResult
{
- return sizeof("QTMETADATA ") - 1;
-}
+ enum Result {
+ FinishedSearch = 0,
+ ContinueSearch,
+
+ // parse errors
+ ParsingError = -1,
+ InvalidMetaDataVersion = -2,
+ InvalidTopLevelItem = -3,
+ InvalidHeaderItem = -4,
+ };
+ Result result;
+ QCborError error = { QCborError::NoError };
+
+ Q_IMPLICIT IterationResult(Result r) : result(r) {}
+ Q_IMPLICIT IterationResult(QCborError e) : result(ParsingError), error(e) {}
+};
-static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QString *errMsg)
+struct QFactoryLoaderIidSearch
{
- // extract the keys not stored in CBOR
- int qt_metadataVersion = quint8(raw[0]);
- int qt_version = qFromBigEndian<quint16>(raw + 1);
- int qt_archRequirements = quint8(raw[3]);
- if (Q_UNLIKELY(raw[-1] != '!' || qt_metadataVersion != 0)) {
- *errMsg = QStringLiteral("Invalid metadata version");
- return QJsonDocument();
+ QLatin1StringView iid;
+ bool matchesIid = false;
+ QFactoryLoaderIidSearch(QLatin1StringView iid) : iid(iid)
+ { Q_ASSERT(!iid.isEmpty()); }
+
+ static IterationResult::Result skip(QCborStreamReader &reader)
+ {
+ // skip this, whatever it is
+ reader.next();
+ return IterationResult::ContinueSearch;
}
- raw += 4;
- size -= 4;
- QByteArray ba = QByteArray::fromRawData(raw, int(size));
- QCborParserError err;
- QCborValue metadata = QCborValue::fromCbor(ba, &err);
+ IterationResult::Result operator()(QtPluginMetaDataKeys key, QCborStreamReader &reader)
+ {
+ if (key != QtPluginMetaDataKeys::IID)
+ return skip(reader);
+ matchesIid = (reader.readAllString() == iid);
+ return IterationResult::FinishedSearch;
+ }
+ IterationResult::Result operator()(QUtf8StringView, QCborStreamReader &reader)
+ {
+ return skip(reader);
+ }
+};
- if (err.error != QCborError::NoError) {
- *errMsg = QLatin1String("Metadata parsing error: ") + err.error.toString();
- return QJsonDocument();
+struct QFactoryLoaderMetaDataKeysExtractor : QFactoryLoaderIidSearch
+{
+ QCborArray keys;
+ QFactoryLoaderMetaDataKeysExtractor(QLatin1StringView iid)
+ : QFactoryLoaderIidSearch(iid)
+ {}
+
+ IterationResult::Result operator()(QtPluginMetaDataKeys key, QCborStreamReader &reader)
+ {
+ if (key == QtPluginMetaDataKeys::IID) {
+ QFactoryLoaderIidSearch::operator()(key, reader);
+ return IterationResult::ContinueSearch;
+ }
+ if (key != QtPluginMetaDataKeys::MetaData)
+ return skip(reader);
+
+ if (!matchesIid)
+ return IterationResult::FinishedSearch;
+ if (!reader.isMap() || !reader.isLengthKnown())
+ return IterationResult::InvalidHeaderItem;
+ if (!reader.enterContainer())
+ return IterationResult::ParsingError;
+ while (reader.isValid()) {
+ // the metadata is JSON, so keys are all strings
+ QByteArray key = reader.readAllUtf8String();
+ if (key == "Keys") {
+ if (!reader.isArray() || !reader.isLengthKnown())
+ return IterationResult::InvalidHeaderItem;
+ keys = QCborValue::fromCbor(reader).toArray();
+ break;
+ }
+ skip(reader);
+ }
+ // warning: we may not have finished iterating over the header
+ return IterationResult::FinishedSearch;
}
+ using QFactoryLoaderIidSearch::operator();
+};
+} // unnamed namespace
- if (!metadata.isMap()) {
- *errMsg = QStringLiteral("Unexpected metadata contents");
- return QJsonDocument();
+template <typename F> static IterationResult iterateInPluginMetaData(QByteArrayView raw, F &&f)
+{
+ QPluginMetaData::Header header;
+ Q_ASSERT(raw.size() >= qsizetype(sizeof(header)));
+ memcpy(&header, raw.data(), sizeof(header));
+ if (Q_UNLIKELY(header.version > QPluginMetaData::CurrentMetaDataVersion))
+ return IterationResult::InvalidMetaDataVersion;
+
+ // use fromRawData to keep QCborStreamReader from copying
+ raw = raw.sliced(sizeof(header));
+ QByteArray ba = QByteArray::fromRawData(raw.data(), raw.size());
+ QCborStreamReader reader(ba);
+ if (reader.isInvalid())
+ return reader.lastError();
+ if (!reader.isMap())
+ return IterationResult::InvalidTopLevelItem;
+ if (!reader.enterContainer())
+ return reader.lastError();
+ while (reader.isValid()) {
+ IterationResult::Result r;
+ if (reader.isInteger()) {
+ // integer key, one of ours
+ qint64 value = reader.toInteger();
+ auto key = QtPluginMetaDataKeys(value);
+ if (qint64(key) != value)
+ return IterationResult::InvalidHeaderItem;
+ if (!reader.next())
+ return reader.lastError();
+ r = f(key, reader);
+ } else if (reader.isString()) {
+ QByteArray key = reader.readAllUtf8String();
+ if (key.isNull())
+ return reader.lastError();
+ r = f(QUtf8StringView(key), reader);
+ } else {
+ return IterationResult::InvalidTopLevelItem;
+ }
+
+ if (QCborError e = reader.lastError())
+ return e;
+ if (r != IterationResult::ContinueSearch)
+ return r;
}
- QJsonObject o;
- o.insert(QLatin1String("version"), qt_version << 8);
- o.insert(QLatin1String("debug"), bool(qt_archRequirements & 1));
- o.insert(QLatin1String("archreq"), qt_archRequirements);
+ if (!reader.leaveContainer())
+ return reader.lastError();
+ return IterationResult::FinishedSearch;
+}
+
+static bool isIidMatch(QByteArrayView raw, QLatin1StringView iid)
+{
+ QFactoryLoaderIidSearch search(iid);
+ iterateInPluginMetaData(raw, search);
+ return search.matchesIid;
+}
+
+bool QPluginParsedMetaData::parse(QByteArrayView raw)
+{
+ QCborMap map;
+ auto r = iterateInPluginMetaData(raw, [&](const auto &key, QCborStreamReader &reader) {
+ QCborValue item = QCborValue::fromCbor(reader);
+ if (item.isInvalid())
+ return IterationResult::ParsingError;
+ if constexpr (std::is_enum_v<std::decay_t<decltype(key)>>)
+ map[int(key)] = item;
+ else
+ map[QString::fromUtf8(key)] = item;
+ return IterationResult::ContinueSearch;
+ });
+
+ switch (r.result) {
+ case IterationResult::FinishedSearch:
+ case IterationResult::ContinueSearch:
+ break;
+
+ // parse errors
+ case IterationResult::ParsingError:
+ return setError(QFactoryLoader::tr("Metadata parsing error: %1").arg(r.error.toString()));
+ case IterationResult::InvalidMetaDataVersion:
+ return setError(QFactoryLoader::tr("Invalid metadata version"));
+ case IterationResult::InvalidTopLevelItem:
+ case IterationResult::InvalidHeaderItem:
+ return setError(QFactoryLoader::tr("Unexpected metadata contents"));
+ }
- // convert the top-level map integer keys
- for (auto it : metadata.toMap()) {
+ // header was validated
+ auto header = qFromUnaligned<QPluginMetaData::Header>(raw.data());
+
+ DecodedArchRequirements archReq =
+ header.version == 0 ? decodeVersion0ArchRequirements(header.plugin_arch_requirements)
+ : decodeVersion1ArchRequirements(header.plugin_arch_requirements);
+
+ // insert the keys not stored in the top-level CBOR map
+ map[int(QtPluginMetaDataKeys::QtVersion)] =
+ QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0);
+ map[int(QtPluginMetaDataKeys::IsDebug)] = archReq.isDebug;
+ map[int(QtPluginMetaDataKeys::Requirements)] = archReq.level;
+
+ data = std::move(map);
+ return true;
+}
+
+QJsonObject QPluginParsedMetaData::toJson() const
+{
+ // convert from the internal CBOR representation to an external JSON one
+ QJsonObject o;
+ for (auto it : data.toMap()) {
QString key;
if (it.first.isInteger()) {
switch (it.first.toInteger()) {
#define CONVERT_TO_STRING(IntKey, StringKey, Description) \
case int(IntKey): key = QStringLiteral(StringKey); break;
QT_PLUGIN_FOREACH_METADATA(CONVERT_TO_STRING)
-#undef CONVERT_TO_STRING
-
- case int(QtPluginMetaDataKeys::Requirements):
- // special case: recreate the debug key
- o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
- key = QStringLiteral("archreq");
- break;
}
} else {
key = it.first.toString();
@@ -123,213 +246,195 @@ static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QStri
if (!key.isEmpty())
o.insert(key, it.second.toJsonValue());
}
- return QJsonDocument(o);
-}
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize, QString *errMsg)
-{
- raw += metaDataSignatureLength();
- sectionSize -= metaDataSignatureLength();
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- if (Q_UNLIKELY(raw[-1] == ' ')) {
- // the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
- uint size = qFromLittleEndian<uint>(raw + 8);
- // but the maximum size of binary JSON is 128 MB
- size = qMin(size, 128U * 1024 * 1024);
- // and it doesn't include the size of the header (8 bytes)
- size += 8;
- // finally, it can't be bigger than the file or section size
- size = qMin(sectionSize, qsizetype(size));
-
- QByteArray json(raw, size);
- return QJsonDocument::fromBinaryData(json);
- }
-#endif
-
- return jsonFromCborMetaData(raw, sectionSize, errMsg);
+ return o;
}
-QT_WARNING_POP
class QFactoryLoaderPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QFactoryLoader)
+ Q_DISABLE_COPY_MOVE(QFactoryLoaderPrivate)
public:
- QFactoryLoaderPrivate(){}
+ QFactoryLoaderPrivate() { }
QByteArray iid;
#if QT_CONFIG(library)
~QFactoryLoaderPrivate();
mutable QMutex mutex;
- QList<QLibraryPrivate*> libraryList;
- QMap<QString,QLibraryPrivate*> keyMap;
+ QDuplicateTracker<QString> loadedPaths;
+ std::vector<QLibraryPrivate::UniquePtr> libraries;
+ std::map<QString, QLibraryPrivate*> keyMap;
QString suffix;
+ QString extraSearchPath;
Qt::CaseSensitivity cs;
- QDuplicateTracker<QString> loadedPaths;
+
+ void updateSinglePath(const QString &pluginDir);
#endif
};
#if QT_CONFIG(library)
-Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders)
+static Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(lcFactoryLoader, "QT_DEBUG_PLUGINS",
+ "qt.core.plugin.factoryloader")
-Q_GLOBAL_STATIC(QRecursiveMutex, qt_factoryloader_mutex)
-
-QFactoryLoaderPrivate::~QFactoryLoaderPrivate()
+namespace {
+struct QFactoryLoaderGlobals
{
- for (QLibraryPrivate *library : qAsConst(libraryList))
- library->release();
+ // needs to be recursive because loading one plugin could cause another
+ // factory to be initialized
+ QRecursiveMutex mutex;
+ QList<QFactoryLoader *> loaders;
+};
}
-void QFactoryLoader::update()
-{
-#ifdef QT_SHARED
- Q_D(QFactoryLoader);
- QStringList paths = QCoreApplication::libraryPaths();
- for (int i = 0; i < paths.count(); ++i) {
- const QString &pluginDir = paths.at(i);
- // Already loaded, skip it...
- if (d->loadedPaths.hasSeen(pluginDir))
- continue;
+Q_GLOBAL_STATIC(QFactoryLoaderGlobals, qt_factoryloader_global)
-#ifdef Q_OS_ANDROID
- QString path = pluginDir;
-#else
- QString path = pluginDir + d->suffix;
-#endif
+QFactoryLoaderPrivate::~QFactoryLoaderPrivate()
+ = default;
- if (qt_debug_component())
- qDebug() << "QFactoryLoader::QFactoryLoader() checking directory path" << path << "...";
+inline void QFactoryLoaderPrivate::updateSinglePath(const QString &path)
+{
+ struct LibraryReleaser {
+ void operator()(QLibraryPrivate *library)
+ { if (library) library->release(); }
+ };
- if (!QDir(path).exists(QLatin1String(".")))
- continue;
+ // If we've already loaded, skip it...
+ if (loadedPaths.hasSeen(path))
+ return;
+
+ qCDebug(lcFactoryLoader) << "checking directory path" << path << "...";
- QStringList plugins = QDir(path).entryList(
+ QDirListing plugins(path,
#if defined(Q_OS_WIN)
- QStringList(QStringLiteral("*.dll")),
+ QStringList(QStringLiteral("*.dll")),
#elif defined(Q_OS_ANDROID)
- QStringList(QLatin1String("libplugins_%1_*.so").arg(d->suffix)),
+ QStringList("libplugins_%1_*.so"_L1.arg(suffix)),
#endif
- QDir::Files);
- QLibraryPrivate *library = nullptr;
-
- for (int j = 0; j < plugins.count(); ++j) {
- QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
-
-#ifdef Q_OS_MAC
- const bool isDebugPlugin = fileName.endsWith(QLatin1String("_debug.dylib"));
- const bool isDebugLibrary =
- #ifdef QT_DEBUG
- true;
- #else
- false;
- #endif
-
- // Skip mismatching plugins so that we don't end up loading both debug and release
- // versions of the same Qt libraries (due to the plugin's dependencies).
- if (isDebugPlugin != isDebugLibrary)
- continue;
+ QDir::Files);
+
+ for (const auto &dirEntry : plugins) {
+ const QString &fileName = dirEntry.fileName();
+#ifdef Q_OS_DARWIN
+ const bool isDebugPlugin = fileName.endsWith("_debug.dylib"_L1);
+ const bool isDebugLibrary =
+ #ifdef QT_DEBUG
+ true;
+ #else
+ false;
+ #endif
+
+ // Skip mismatching plugins so that we don't end up loading both debug and release
+ // versions of the same Qt libraries (due to the plugin's dependencies).
+ if (isDebugPlugin != isDebugLibrary)
+ continue;
#elif defined(Q_PROCESSOR_X86)
- if (fileName.endsWith(QLatin1String(".avx2")) || fileName.endsWith(QLatin1String(".avx512"))) {
- // ignore AVX2-optimized file, we'll do a bait-and-switch to it later
- continue;
- }
+ if (fileName.endsWith(".avx2"_L1) || fileName.endsWith(".avx512"_L1)) {
+ // ignore AVX2-optimized file, we'll do a bait-and-switch to it later
+ continue;
+ }
#endif
- if (qt_debug_component()) {
- qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
- }
+ qCDebug(lcFactoryLoader) << "looking at" << fileName;
- Q_TRACE(QFactoryLoader_update, fileName);
+ Q_TRACE(QFactoryLoader_update, fileName);
- library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
- if (!library->isPlugin()) {
- if (qt_debug_component()) {
- qDebug() << library->errorString << Qt::endl
- << " not a plugin";
- }
- library->release();
- continue;
- }
-
- QStringList keys;
- bool metaDataOk = false;
+ QLibraryPrivate::UniquePtr library;
+ library.reset(QLibraryPrivate::findOrCreate(dirEntry.canonicalFilePath()));
+ if (!library->isPlugin()) {
+ qCDebug(lcFactoryLoader) << library->errorString << Qt::endl
+ << " not a plugin";
+ continue;
+ }
- QString iid = library->metaData.value(QLatin1String("IID")).toString();
- if (iid == QLatin1String(d->iid.constData(), d->iid.size())) {
- QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject();
- metaDataOk = true;
+ QStringList keys;
+ bool metaDataOk = false;
- QJsonArray k = object.value(QLatin1String("Keys")).toArray();
- for (int i = 0; i < k.size(); ++i)
- keys += d->cs ? k.at(i).toString() : k.at(i).toString().toLower();
- }
- if (qt_debug_component())
- qDebug() << "Got keys from plugin meta data" << keys;
+ QString iid = library->metaData.value(QtPluginMetaDataKeys::IID).toString();
+ if (iid == QLatin1StringView(this->iid.constData(), this->iid.size())) {
+ QCborMap object = library->metaData.value(QtPluginMetaDataKeys::MetaData).toMap();
+ metaDataOk = true;
+ const QCborArray k = object.value("Keys"_L1).toArray();
+ for (QCborValueConstRef v : k)
+ keys += cs ? v.toString() : v.toString().toLower();
+ }
+ qCDebug(lcFactoryLoader) << "Got keys from plugin meta data" << keys;
- if (!metaDataOk) {
- library->release();
- continue;
- }
+ if (!metaDataOk)
+ continue;
- int keyUsageCount = 0;
- for (int k = 0; k < keys.count(); ++k) {
- // first come first serve, unless the first
- // library was built with a future Qt version,
- // whereas the new one has a Qt version that fits
- // better
- const QString &key = keys.at(k);
- QLibraryPrivate *previous = d->keyMap.value(key);
- int prev_qt_version = 0;
- if (previous) {
- prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble();
- }
- int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble();
- if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) {
- d->keyMap[key] = library;
- ++keyUsageCount;
- }
- }
- if (keyUsageCount || keys.isEmpty()) {
- library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload
- QMutexLocker locker(&d->mutex);
- d->libraryList += library;
- } else {
- library->release();
+ int keyUsageCount = 0;
+ for (const QString &key : std::as_const(keys)) {
+ // first come first serve, unless the first
+ // library was built with a future Qt version,
+ // whereas the new one has a Qt version that fits
+ // better
+ constexpr int QtVersionNoPatch = QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, 0);
+ QLibraryPrivate *&previous = keyMap[key];
+ int prev_qt_version = 0;
+ if (previous)
+ prev_qt_version = int(previous->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
+ int qt_version = int(library->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
+ if (!previous || (prev_qt_version > QtVersionNoPatch && qt_version <= QtVersionNoPatch)) {
+ previous = library.get(); // we WILL .release()
+ ++keyUsageCount;
}
}
+ if (keyUsageCount || keys.isEmpty()) {
+ library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload
+ QMutexLocker locker(&mutex);
+ libraries.push_back(std::move(library));
+ }
+ };
+}
+
+void QFactoryLoader::update()
+{
+#ifdef QT_SHARED
+ Q_D(QFactoryLoader);
+
+ const QStringList paths = QCoreApplication::libraryPaths();
+ for (const QString &pluginDir : paths) {
+#ifdef Q_OS_ANDROID
+ QString path = pluginDir;
+#else
+ QString path = pluginDir + d->suffix;
+#endif
+
+ d->updateSinglePath(path);
}
+ if (!d->extraSearchPath.isEmpty())
+ d->updateSinglePath(d->extraSearchPath);
#else
Q_D(QFactoryLoader);
- if (qt_debug_component()) {
- qDebug() << "QFactoryLoader::QFactoryLoader() ignoring" << d->iid
- << "since plugins are disabled in static builds";
- }
+ qCDebug(lcFactoryLoader) << "ignoring" << d->iid
+ << "since plugins are disabled in static builds";
#endif
}
QFactoryLoader::~QFactoryLoader()
{
- QMutexLocker locker(qt_factoryloader_mutex());
- qt_factory_loaders()->removeAll(this);
+ if (!qt_factoryloader_global.isDestroyed()) {
+ QMutexLocker locker(&qt_factoryloader_global->mutex);
+ qt_factoryloader_global->loaders.removeOne(this);
+ }
}
-#if defined(Q_OS_UNIX) && !defined (Q_OS_MAC)
+#if defined(Q_OS_UNIX) && !defined (Q_OS_DARWIN)
QLibraryPrivate *QFactoryLoader::library(const QString &key) const
{
Q_D(const QFactoryLoader);
- return d->keyMap.value(d->cs ? key : key.toLower());
+ const auto it = d->keyMap.find(d->cs ? key : key.toLower());
+ if (it == d->keyMap.cend())
+ return nullptr;
+ return it->second;
}
#endif
void QFactoryLoader::refreshAll()
{
- QMutexLocker locker(qt_factoryloader_mutex());
- QList<QFactoryLoader *> *loaders = qt_factory_loaders();
- for (QList<QFactoryLoader *>::const_iterator it = loaders->constBegin();
- it != loaders->constEnd(); ++it) {
- (*it)->update();
+ if (qt_factoryloader_global.exists()) {
+ QMutexLocker locker(&qt_factoryloader_global->mutex);
+ for (QFactoryLoader *loader : std::as_const(qt_factoryloader_global->loaders))
+ loader->update();
}
}
@@ -340,6 +445,9 @@ QFactoryLoader::QFactoryLoader(const char *iid,
Qt::CaseSensitivity cs)
: QObject(*new QFactoryLoaderPrivate)
{
+ Q_ASSERT_X(suffix.startsWith(u'/'), "QFactoryLoader",
+ "For historical reasons, the suffix must start with '/' (and it can't be empty)");
+
moveToThread(QCoreApplicationPrivate::mainThread());
Q_D(QFactoryLoader);
d->iid = iid;
@@ -347,36 +455,93 @@ QFactoryLoader::QFactoryLoader(const char *iid,
d->cs = cs;
d->suffix = suffix;
# ifdef Q_OS_ANDROID
- if (!d->suffix.isEmpty() && d->suffix.at(0) == QLatin1Char('/'))
+ if (!d->suffix.isEmpty() && d->suffix.at(0) == u'/')
d->suffix.remove(0, 1);
# endif
- QMutexLocker locker(qt_factoryloader_mutex());
+ QMutexLocker locker(&qt_factoryloader_global->mutex);
update();
- qt_factory_loaders()->append(this);
+ qt_factoryloader_global->loaders.append(this);
#else
Q_UNUSED(suffix);
Q_UNUSED(cs);
#endif
}
-QList<QJsonObject> QFactoryLoader::metaData() const
+void QFactoryLoader::setExtraSearchPath(const QString &path)
+{
+#if QT_CONFIG(library)
+ Q_D(QFactoryLoader);
+ if (d->extraSearchPath == path)
+ return; // nothing to do
+
+ QMutexLocker locker(&qt_factoryloader_global->mutex);
+ QString oldPath = std::exchange(d->extraSearchPath, path);
+ if (oldPath.isEmpty()) {
+ // easy case, just update this directory
+ d->updateSinglePath(d->extraSearchPath);
+ } else {
+ // must re-scan everything
+ d->loadedPaths.clear();
+ d->libraries.clear();
+ d->keyMap.clear();
+ update();
+ }
+#else
+ Q_UNUSED(path);
+#endif
+}
+
+QFactoryLoader::MetaDataList QFactoryLoader::metaData() const
{
Q_D(const QFactoryLoader);
- QList<QJsonObject> metaData;
+ QList<QPluginParsedMetaData> metaData;
#if QT_CONFIG(library)
QMutexLocker locker(&d->mutex);
- for (int i = 0; i < d->libraryList.size(); ++i)
- metaData.append(d->libraryList.at(i)->metaData);
+ for (const auto &library : d->libraries)
+ metaData.append(library->metaData);
#endif
+ QLatin1StringView iid(d->iid.constData(), d->iid.size());
const auto staticPlugins = QPluginLoader::staticPlugins();
for (const QStaticPlugin &plugin : staticPlugins) {
- const QJsonObject object = plugin.metaData();
- if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size()))
+ QByteArrayView pluginData(static_cast<const char *>(plugin.rawMetaData), plugin.rawMetaDataSize);
+ QPluginParsedMetaData parsed(pluginData);
+ if (parsed.isError() || parsed.value(QtPluginMetaDataKeys::IID) != iid)
continue;
- metaData.append(object);
+ metaData.append(std::move(parsed));
+ }
+
+ // other portions of the code will cast to int (e.g., keyMap())
+ Q_ASSERT(metaData.size() <= std::numeric_limits<int>::max());
+ return metaData;
+}
+
+QList<QCborArray> QFactoryLoader::metaDataKeys() const
+{
+ Q_D(const QFactoryLoader);
+ QList<QCborArray> metaData;
+#if QT_CONFIG(library)
+ QMutexLocker locker(&d->mutex);
+ for (const auto &library : d->libraries) {
+ const QCborValue md = library->metaData.value(QtPluginMetaDataKeys::MetaData);
+ metaData.append(md["Keys"_L1].toArray());
+ }
+#endif
+
+ QLatin1StringView iid(d->iid.constData(), d->iid.size());
+ const auto staticPlugins = QPluginLoader::staticPlugins();
+ for (const QStaticPlugin &plugin : staticPlugins) {
+ QByteArrayView pluginData(static_cast<const char *>(plugin.rawMetaData),
+ plugin.rawMetaDataSize);
+ QFactoryLoaderMetaDataKeysExtractor extractor{ iid };
+ iterateInPluginMetaData(pluginData, extractor);
+ if (extractor.matchesIid)
+ metaData += std::move(extractor.keys);
}
+
+ // other portions of the code will cast to int (e.g., keyMap())
+ Q_ASSERT(metaData.size() <= std::numeric_limits<int>::max());
return metaData;
}
@@ -388,8 +553,8 @@ QObject *QFactoryLoader::instance(int index) const
#if QT_CONFIG(library)
QMutexLocker lock(&d->mutex);
- if (index < d->libraryList.size()) {
- QLibraryPrivate *library = d->libraryList.at(index);
+ if (size_t(index) < d->libraries.size()) {
+ QLibraryPrivate *library = d->libraries[index].get();
if (QObject *obj = library->pluginInstance()) {
if (!obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread());
@@ -397,18 +562,20 @@ QObject *QFactoryLoader::instance(int index) const
}
return nullptr;
}
- index -= d->libraryList.size();
+ // we know d->libraries.size() <= index <= numeric_limits<decltype(index)>::max() → no overflow
+ index -= static_cast<int>(d->libraries.size());
lock.unlock();
#endif
- QList<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins();
- for (int i = 0; i < staticPlugins.count(); ++i) {
- const QJsonObject object = staticPlugins.at(i).metaData();
- if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size()))
+ QLatin1StringView iid(d->iid.constData(), d->iid.size());
+ const QList<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins();
+ for (QStaticPlugin plugin : staticPlugins) {
+ QByteArrayView pluginData(static_cast<const char *>(plugin.rawMetaData), plugin.rawMetaDataSize);
+ if (!isIidMatch(pluginData, iid))
continue;
if (index == 0)
- return staticPlugins.at(i).instance();
+ return plugin.instance();
--index;
}
@@ -418,26 +585,22 @@ QObject *QFactoryLoader::instance(int index) const
QMultiMap<int, QString> QFactoryLoader::keyMap() const
{
QMultiMap<int, QString> result;
- const QList<QJsonObject> metaDataList = metaData();
- for (int i = 0; i < metaDataList.size(); ++i) {
- const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject();
- const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray();
- const int keyCount = keys.size();
- for (int k = 0; k < keyCount; ++k)
- result.insert(i, keys.at(k).toString());
+ const QList<QCborArray> metaDataList = metaDataKeys();
+ for (int i = 0; i < int(metaDataList.size()); ++i) {
+ const QCborArray &keys = metaDataList[i];
+ for (QCborValueConstRef key : keys)
+ result.insert(i, key.toString());
}
return result;
}
int QFactoryLoader::indexOf(const QString &needle) const
{
- const QList<QJsonObject> metaDataList = metaData();
- for (int i = 0; i < metaDataList.size(); ++i) {
- const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject();
- const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray();
- const int keyCount = keys.size();
- for (int k = 0; k < keyCount; ++k) {
- if (!keys.at(k).toString().compare(needle, Qt::CaseInsensitive))
+ const QList<QCborArray> metaDataList = metaDataKeys();
+ for (int i = 0; i < int(metaDataList.size()); ++i) {
+ const QCborArray &keys = metaDataList[i];
+ for (QCborValueConstRef key : keys) {
+ if (key.toString().compare(needle, Qt::CaseInsensitive) == 0)
return i;
}
}
diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h
index 7815ea0b5d..56dc7e6ad1 100644
--- a/src/corelib/plugin/qfactoryloader_p.h
+++ b/src/corelib/plugin/qfactoryloader_p.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFACTORYLOADER_P_H
#define QFACTORYLOADER_P_H
@@ -54,20 +19,43 @@
#include "QtCore/qglobal.h"
#ifndef QT_NO_QOBJECT
-#include "QtCore/qobject.h"
-#include "QtCore/qstringlist.h"
+#include "QtCore/private/qplugin_p.h"
+#include "QtCore/qcbormap.h"
#include "QtCore/qcborvalue.h"
-#include "QtCore/qjsonobject.h"
-#include "QtCore/qjsondocument.h"
#include "QtCore/qmap.h"
-#include "QtCore/qendian.h"
-#if QT_CONFIG(library)
-#include "private/qlibrary_p.h"
-#endif
+#include "QtCore/qobject.h"
+#include "QtCore/qplugin.h"
QT_BEGIN_NAMESPACE
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg);
+class QJsonObject;
+class QLibraryPrivate;
+
+class QPluginParsedMetaData
+{
+ QCborValue data;
+ bool setError(const QString &errorString) Q_DECL_COLD_FUNCTION
+ {
+ data = errorString;
+ return false;
+ }
+public:
+ QPluginParsedMetaData() = default;
+ QPluginParsedMetaData(QByteArrayView input) { parse(input); }
+
+ bool isError() const { return !data.isMap(); }
+ QString errorString() const { return data.toString(); }
+
+ bool parse(QByteArrayView input);
+ bool parse(QPluginMetaData metaData)
+ { return parse(QByteArrayView(reinterpret_cast<const char *>(metaData.data), metaData.size)); }
+
+ QJsonObject toJson() const; // only for QLibrary & QPluginLoader
+
+ // if data is not a map, toMap() returns empty, so shall these functions
+ QCborMap toCbor() const { return data.toMap(); }
+ QCborValue value(QtPluginMetaDataKeys k) const { return data[int(k)]; }
+};
class QFactoryLoaderPrivate;
class Q_CORE_EXPORT QFactoryLoader : public QObject
@@ -86,15 +74,19 @@ public:
void update();
static void refreshAll();
-#if defined(Q_OS_UNIX) && !defined (Q_OS_MAC)
+#if defined(Q_OS_UNIX) && !defined (Q_OS_DARWIN)
QLibraryPrivate *library(const QString &key) const;
-#endif // Q_OS_UNIX && !Q_OS_MAC
+#endif // Q_OS_UNIX && !Q_OS_DARWIN
#endif // QT_CONFIG(library)
+ void setExtraSearchPath(const QString &path);
QMultiMap<int, QString> keyMap() const;
int indexOf(const QString &needle) const;
- QList<QJsonObject> metaData() const;
+ using MetaDataList = QList<QPluginParsedMetaData>;
+
+ MetaDataList metaData() const;
+ QList<QCborArray> metaDataKeys() const;
QObject *instance(int index) const;
};
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 9ea8e2793c..a3ef8e3c52 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -1,84 +1,61 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "qplatformdefs.h"
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlibrary.h"
-
-#include "qfactoryloader_p.h"
#include "qlibrary_p.h"
-#include <qstringlist.h>
+
+#include <q20algorithm.h>
+#include <qbytearraymatcher.h>
+#include <qdebug.h>
+#include <qendian.h>
#include <qfile.h>
#include <qfileinfo.h>
+#include <qjsondocument.h>
#include <qmutex.h>
-#include <qmap.h>
-#include <private/qcoreapplication_p.h>
-#include <private/qsystemerror_p.h>
-#ifdef Q_OS_MAC
+#include <qoperatingsystemversion.h>
+#include <qstringlist.h>
+
+#ifdef Q_OS_DARWIN
# include <private/qcore_mac_p.h>
#endif
-#ifndef NO_ERRNO_H
-#include <errno.h>
-#endif // NO_ERROR_H
-#include <qdebug.h>
-#include <qlist.h>
-#include <qdir.h>
-#include <qendian.h>
-#include <qjsondocument.h>
-#include <qjsonvalue.h>
+#include <private/qcoreapplication_p.h>
+#include <private/qloggingregistry_p.h>
+#include <private/qsystemerror_p.h>
+
+#include "qcoffpeparser_p.h"
#include "qelfparser_p.h"
+#include "qfactoryloader_p.h"
#include "qmachparser_p.h"
#include <qtcore_tracepoints_p.h>
+#include <QtCore/q20map.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+Q_TRACE_POINT(qtcore, QLibraryPrivate_load_entry, const QString &fileName);
+Q_TRACE_POINT(qtcore, QLibraryPrivate_load_exit, bool success);
+
+// On Unix systema and on Windows with MinGW, we can mix and match debug and
+// release plugins without problems. (unless compiled in debug-and-release mode
+// - why?)
+static constexpr bool PluginMustMatchQtDebug =
+ QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows
+#if defined(Q_CC_MINGW)
+ && QT_CONFIG(debug_and_release)
+#endif
+ ;
+
#ifdef QT_NO_DEBUG
-# define QLIBRARY_AS_DEBUG false
+static constexpr bool QtBuildIsDebug = false;
#else
-# define QLIBRARY_AS_DEBUG true
+static constexpr bool QtBuildIsDebug = true;
#endif
-#if defined(Q_OS_UNIX) || (defined(Q_CC_MINGW) && !QT_CONFIG(debug_and_release))
-// We don't use separate debug and release libs on UNIX, so we want
-// to allow loading plugins, regardless of how they were built.
-# define QT_NO_DEBUG_PLUGIN_CHECK
-#endif
+Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(qt_lcDebugPlugins, "QT_DEBUG_PLUGINS", "qt.core.plugin.loader")
+static Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(lcDebugLibrary, "QT_DEBUG_PLUGINS", "qt.core.library")
/*!
\class QLibrary
@@ -185,43 +162,43 @@ QT_BEGIN_NAMESPACE
\sa loadHints
*/
-
-static qsizetype qt_find_pattern(const char *s, qsizetype s_len,
- const char *pattern, ulong p_len)
+static QLibraryScanResult qt_find_pattern(const char *s, qsizetype s_len, QString *errMsg)
{
/*
- we search from the end of the file because on the supported
- systems, the read-only data/text segments are placed at the end
- of the file. HOWEVER, when building with debugging enabled, all
- the debug symbols are placed AFTER the data/text segments.
-
- what does this mean? when building in release mode, the search
- is fast because the data we are looking for is at the end of the
- file... when building in debug mode, the search is slower
- because we have to skip over all the debugging symbols first
- */
-
- if (!s || !pattern || qsizetype(p_len) > s_len)
- return -1;
+ We used to search from the end of the file so we'd skip the code and find
+ the read-only data that usually follows. Unfortunately, in debug builds,
+ the debug sections come after and are usually much bigger than everything
+ else, making this process slower than necessary with debug plugins.
- size_t i, hs = 0, hp = 0, delta = s_len - p_len;
-
- for (i = 0; i < p_len; ++i) {
- hs += s[delta + i];
- hp += pattern[i];
- }
- i = delta;
- for (;;) {
- if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0)
- return i; // can't overflow, by construction
- if (i == 0)
- break;
- --i;
- hs -= s[i + p_len];
- hs += s[i];
+ More importantly, the pattern string may exist in the debug information due
+ to it being used in the plugin in the first place.
+ */
+#if defined(Q_OF_ELF)
+ return QElfParser::parse({s, s_len}, errMsg);
+#elif defined(Q_OF_MACH_O)
+ return QMachOParser::parse(s, s_len, errMsg);
+#elif defined(Q_OS_WIN)
+ return QCoffPeParser::parse({s, s_len}, errMsg);
+#else
+# warning "Qt does not know how to efficiently parse your platform's binary format; using slow fall-back."
+#endif
+ static constexpr auto matcher = [] {
+ // QPluginMetaData::MagicString is not NUL-terminated, but
+ // qMakeStaticByteArrayMatcher requires its argument to be, so
+ // duplicate here, but statically check we didn't mess up:
+ constexpr auto &pattern = "QTMETADATA !";
+ constexpr auto magic = std::string_view(QPluginMetaData::MagicString,
+ sizeof(QPluginMetaData::MagicString));
+ static_assert(pattern == magic);
+ return qMakeStaticByteArrayMatcher(pattern);
+ }();
+ qsizetype i = matcher.indexIn({s, s_len});
+ if (i < 0) {
+ *errMsg = QLibrary::tr("'%1' is not a Qt plugin").arg(*errMsg);
+ return QLibraryScanResult{};
}
-
- return -1;
+ i += sizeof(QPluginMetaData::MagicString);
+ return { i, s_len - i };
}
/*
@@ -234,17 +211,15 @@ static qsizetype qt_find_pattern(const char *s, qsizetype s_len,
information could not be read.
Returns true if version information is present and successfully read.
*/
-static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
+static QLibraryScanResult findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
{
QFile file(library);
if (!file.open(QIODevice::ReadOnly)) {
if (lib)
lib->errorString = file.errorString();
- if (qt_debug_component()) {
- qWarning("%s: %ls", QFile::encodeName(library).constData(),
- qUtf16Printable(QSystemError::stdString()));
- }
- return false;
+ qCWarning(qt_lcDebugPlugins, "%ls: cannot open: %ls", qUtf16Printable(library),
+ qUtf16Printable(file.errorString()));
+ return {};
}
// Files can be bigger than the virtual memory size on 32-bit systems, so
@@ -252,88 +227,54 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
constexpr qint64 MaxMemoryMapSize =
Q_INT64_C(1) << (sizeof(qsizetype) > 4 ? 40 : 29);
- QByteArray data;
qsizetype fdlen = qMin(file.size(), MaxMemoryMapSize);
const char *filedata = reinterpret_cast<char *>(file.map(0, fdlen));
+#ifdef Q_OS_UNIX
if (filedata == nullptr) {
- // Try reading the data into memory instead (up to 64 MB).
+ // If we can't mmap(), then the dynamic loader won't be able to either.
+ // This can't be used as a plugin.
+ qCWarning(qt_lcDebugPlugins, "%ls: failed to map to memory: %ls",
+ qUtf16Printable(library), qUtf16Printable(file.errorString()));
+ return {};
+ }
+#else
+ QByteArray data;
+ if (filedata == nullptr) {
+ // It's unknown at this point whether Windows supports LoadLibrary() on
+ // files that fail to CreateFileMapping / MapViewOfFile, so we err on
+ // the side of doing a regular read into memory (up to 64 MB).
data = file.read(64 * 1024 * 1024);
filedata = data.constData();
fdlen = data.size();
}
+#endif
- /*
- ELF and Mach-O binaries with GCC have .qplugin sections.
- */
- bool hasMetaData = false;
- qsizetype pos = 0;
- char pattern[] = "qTMETADATA ";
- pattern[0] = 'Q'; // Ensure the pattern "QTMETADATA" is not found in this library should QPluginLoader ever encounter it.
- const ulong plen = qstrlen(pattern);
-#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
- int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
- if (r == QElfParser::Corrupt || r == QElfParser::NotElf) {
- if (lib && qt_debug_component()) {
- qWarning("QElfParser: %ls", qUtf16Printable(lib->errorString));
- }
- return false;
- } else if (r == QElfParser::QtMetaDataSection) {
- qsizetype rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
- if (rel < 0)
- pos = -1;
- else
- pos += rel;
- hasMetaData = true;
- }
-#elif defined (Q_OF_MACH_O)
- {
- QString errorString;
- int r = QMachOParser::parse(filedata, fdlen, library, &errorString, &pos, &fdlen);
- if (r == QMachOParser::NotSuitable) {
- if (qt_debug_component())
- qWarning("QMachOParser: %ls", qUtf16Printable(errorString));
- if (lib)
- lib->errorString = errorString;
- return false;
- }
- // even if the metadata section was not found, the Mach-O parser will
- // at least return the boundaries of the right architecture
- qsizetype rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
- if (rel < 0)
- pos = -1;
- else
- pos += rel;
- hasMetaData = true;
- }
-#else
- pos = qt_find_pattern(filedata, fdlen, pattern, plen);
- if (pos > 0)
- hasMetaData = true;
-#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
-
- bool ret = false;
-
- if (pos >= 0 && hasMetaData) {
- const char *data = filedata + pos;
- QString errMsg;
- QJsonDocument doc = qJsonFromRawLibraryMetaData(data, fdlen, &errMsg);
- if (doc.isNull()) {
- qWarning("Found invalid metadata in lib %ls: %ls",
- qUtf16Printable(library), qUtf16Printable(errMsg));
+ QString errMsg = library;
+ QLibraryScanResult r = qt_find_pattern(filedata, fdlen, &errMsg);
+ if (r.length) {
+#if defined(Q_OF_MACH_O)
+ if (r.isEncrypted)
+ return r;
+#endif
+ if (!lib->metaData.parse(QByteArrayView(filedata + r.pos, r.length))) {
+ errMsg = lib->metaData.errorString();
+ qCDebug(qt_lcDebugPlugins, "Found invalid metadata in lib %ls: %ls",
+ qUtf16Printable(library), qUtf16Printable(errMsg));
} else {
- lib->metaData = doc.object();
- if (qt_debug_component())
- qWarning("Found metadata in lib %s, metadata=\n%s\n",
- library.toLocal8Bit().constData(), doc.toJson().constData());
- ret = !doc.isNull();
+ qCDebug(qt_lcDebugPlugins, "Found metadata in lib %ls, metadata=\n%s\n",
+ qUtf16Printable(library),
+ QJsonDocument(lib->metaData.toJson()).toJson().constData());
+ return r;
}
+ } else {
+ qCDebug(qt_lcDebugPlugins, "Failed to find metadata in lib %ls: %ls",
+ qUtf16Printable(library), qUtf16Printable(errMsg));
}
- if (!ret && lib)
- lib->errorString = QLibrary::tr("Failed to extract plugin meta data from '%1'").arg(library);
- file.close();
- return ret;
+ lib->errorString = QLibrary::tr("Failed to extract plugin meta data from '%1': %2")
+ .arg(library, errMsg);
+ return {};
}
static void installCoverageTool(QLibraryPrivate *libPrivate)
@@ -354,8 +295,7 @@ static void installCoverageTool(QLibraryPrivate *libPrivate)
int ret = __coveragescanner_register_library(libPrivate->fileName.toLocal8Bit());
- if (qt_debug_component()) {
- if (ret >= 0) {
+ if (ret >= 0) {
qDebug("coverage data for %ls registered",
qUtf16Printable(libPrivate->fileName));
} else {
@@ -382,13 +322,13 @@ private:
static inline QLibraryStore *instance();
// all members and instance() are protected by qt_library_mutex
- typedef QMap<QString, QLibraryPrivate*> LibraryMap;
+ typedef std::map<QString, QLibraryPrivate *> LibraryMap;
LibraryMap libraryMap;
};
-static QBasicMutex qt_library_mutex;
-static QLibraryStore *qt_library_data = nullptr;
-static bool qt_library_data_once;
+Q_CONSTINIT static QBasicMutex qt_library_mutex;
+Q_CONSTINIT static QLibraryStore *qt_library_data = nullptr;
+Q_CONSTINIT static bool qt_library_data_once;
QLibraryStore::~QLibraryStore()
{
@@ -402,33 +342,31 @@ inline void QLibraryStore::cleanup()
return;
// find any libraries that are still loaded but have a no one attached to them
- LibraryMap::Iterator it = data->libraryMap.begin();
- for (; it != data->libraryMap.end(); ++it) {
- QLibraryPrivate *lib = it.value();
+ for (auto &[_, lib] : data->libraryMap) {
if (lib->libraryRefCount.loadRelaxed() == 1) {
if (lib->libraryUnloadCount.loadRelaxed() > 0) {
Q_ASSERT(lib->pHnd.loadRelaxed());
lib->libraryUnloadCount.storeRelaxed(1);
-#ifdef __GLIBC__
- // glibc has a bug in unloading from global destructors
- // see https://bugzilla.novell.com/show_bug.cgi?id=622977
- // and http://sourceware.org/bugzilla/show_bug.cgi?id=11941
+#if defined(Q_OS_DARWIN)
+ // We cannot fully unload libraries, as we don't know if there are
+ // lingering references (in system threads e.g.) to Objective-C classes
+ // defined in the library.
lib->unload(QLibraryPrivate::NoUnloadSys);
#else
lib->unload();
#endif
}
- delete lib;
- it.value() = 0;
+ delete std::exchange(lib, nullptr);
}
}
- if (qt_debug_component()) {
- // dump all objects that remain
- for (QLibraryPrivate *lib : qAsConst(data->libraryMap)) {
+ // dump all objects that remain
+ if (lcDebugLibrary().isDebugEnabled()) {
+ for (auto &[_, lib] : data->libraryMap) {
if (lib)
- qDebug() << "On QtCore unload," << lib->fileName << "was leaked, with"
- << lib->libraryRefCount.loadRelaxed() << "users";
+ qDebug(lcDebugLibrary)
+ << "On QtCore unload," << lib->fileName << "was leaked, with"
+ << lib->libraryRefCount.loadRelaxed() << "users";
}
}
@@ -455,24 +393,34 @@ QLibraryStore *QLibraryStore::instance()
inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints)
{
+ auto lazyNewLib = [&] {
+ auto result = new QLibraryPrivate(fileName, version, loadHints);
+ result->libraryRefCount.ref();
+ return result;
+ };
+
+ if (fileName.isEmpty()) // request for empty d-pointer in QLibrary::setLoadHints();
+ return lazyNewLib(); // must return an independent (new) object
+
QMutexLocker locker(&qt_library_mutex);
QLibraryStore *data = instance();
- // check if this library is already loaded
- QLibraryPrivate *lib = nullptr;
- if (Q_LIKELY(data)) {
- lib = data->libraryMap.value(fileName);
- if (lib)
- lib->mergeLoadHints(loadHints);
+ if (Q_UNLIKELY(!data)) {
+ locker.unlock();
+ return lazyNewLib();
}
- if (!lib)
- lib = new QLibraryPrivate(fileName, version, loadHints);
- // track this library
- if (Q_LIKELY(data) && !fileName.isEmpty())
- data->libraryMap.insert(fileName, lib);
+ QString mapName = version.isEmpty() ? fileName : fileName + u'\0' + version;
+
+ QLibraryPrivate *&lib = data->libraryMap[std::move(mapName)];
+ if (lib) {
+ // already loaded
+ lib->libraryRefCount.ref();
+ lib->mergeLoadHints(loadHints);
+ } else {
+ lib = lazyNewLib();
+ }
- lib->libraryRefCount.ref();
return lib;
}
@@ -490,9 +438,12 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
Q_ASSERT(lib->libraryUnloadCount.loadRelaxed() == 0);
if (Q_LIKELY(data) && !lib->fileName.isEmpty()) {
- QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
- Q_ASSERT(lib == that);
- Q_UNUSED(that);
+ using q20::erase_if;
+ const auto n = erase_if(data->libraryMap, [lib](const auto &e) {
+ return e.second == lib;
+ });
+ Q_ASSERT_X(n, "~QLibrary", "Did not find this library in the library map");
+ Q_UNUSED(n);
}
delete lib;
}
@@ -500,7 +451,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: fileName(canonicalFileName), fullVersion(version), pluginState(MightBeAPlugin)
{
- loadHintsInt.storeRelaxed(loadHints);
+ loadHintsInt.storeRelaxed(loadHints.toInt());
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
@@ -521,7 +472,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
if (pHnd.loadRelaxed())
return;
- loadHintsInt.storeRelaxed(lh);
+ loadHintsInt.fetchAndOrRelaxed(lh.toInt());
}
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
@@ -533,6 +484,13 @@ QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
{
+ // Set the load hints directly for a dummy if this object is not associated
+ // with a file. Such object is not shared between multiple instances.
+ if (fileName.isEmpty()) {
+ loadHintsInt.storeRelaxed(lh.toInt());
+ return;
+ }
+
// this locks a global mutex
QMutexLocker lock(&qt_library_mutex);
mergeLoadHints(lh);
@@ -541,7 +499,7 @@ void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
QObject *QLibraryPrivate::pluginInstance()
{
// first, check if the instance is cached and hasn't been deleted
- QObject *obj = (QMutexLocker(&mutex), inst.data());
+ QObject *obj = [&](){ QMutexLocker locker(&mutex); return inst.data(); }();
if (obj)
return obj;
@@ -577,13 +535,9 @@ bool QLibraryPrivate::load()
Q_TRACE(QLibraryPrivate_load_entry, fileName);
bool ret = load_sys();
- if (qt_debug_component()) {
- if (ret) {
- qDebug() << "loaded library" << fileName;
- } else {
- qDebug() << qUtf8Printable(errorString);
- }
- }
+ qCDebug(lcDebugLibrary)
+ << fileName
+ << (ret ? "loaded library" : qUtf8Printable(u"cannot load: " + errorString));
if (ret) {
//when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted
//this allows to unload the library at a later time
@@ -605,11 +559,10 @@ bool QLibraryPrivate::unload(UnloadFlag flag)
QMutexLocker locker(&mutex);
delete inst.data();
if (flag == NoUnloadSys || unload_sys()) {
- if (qt_debug_component())
- qWarning() << "QLibraryPrivate::unload succeeded on" << fileName
- << (flag == NoUnloadSys ? "(faked)" : "");
- //when the library is unloaded, we release the reference on it so that 'this'
- //can get deleted
+ qCDebug(lcDebugLibrary) << fileName << "unloaded library"
+ << (flag == NoUnloadSys ? "(faked)" : "");
+ // when the library is unloaded, we release the reference on it so that 'this'
+ // can get deleted
libraryRefCount.deref();
pHnd.storeRelaxed(nullptr);
instanceFactory.storeRelaxed(nullptr);
@@ -638,8 +591,7 @@ QtPluginInstanceFunction QLibraryPrivate::loadPlugin()
instanceFactory.storeRelease(ptr); // two threads may store the same value
return ptr;
}
- if (qt_debug_component())
- qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
+ qCDebug(qt_lcDebugPlugins) << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
pluginState = IsNotAPlugin;
return nullptr;
}
@@ -662,35 +614,43 @@ QtPluginInstanceFunction QLibraryPrivate::loadPlugin()
bool QLibrary::isLibrary(const QString &fileName)
{
#if defined(Q_OS_WIN)
- return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive);
+ return fileName.endsWith(".dll"_L1, Qt::CaseInsensitive);
#else // Generic Unix
+# if defined(Q_OS_DARWIN)
+ // On Apple platforms, dylib look like libmylib.1.0.0.dylib
+ if (fileName.endsWith(".dylib"_L1))
+ return true;
+# endif
QString completeSuffix = QFileInfo(fileName).completeSuffix();
if (completeSuffix.isEmpty())
return false;
- const auto suffixes = QStringView{completeSuffix}.split(QLatin1Char('.'));
- QStringList validSuffixList;
+ // if this throws an empty-array error, you need to fix the #ifdef's:
+ const QLatin1StringView candidates[] = {
# if defined(Q_OS_HPUX)
/*
See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
"In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
- */
- validSuffixList << QLatin1String("sl");
+*/
+ "sl"_L1,
# if defined __ia64
- validSuffixList << QLatin1String("so");
+ "so"_L1,
# endif
# elif defined(Q_OS_AIX)
- validSuffixList << QLatin1String("a") << QLatin1String("so");
+ "a"_L1,
+ "so"_L1,
# elif defined(Q_OS_DARWIN)
- // On Apple platforms, dylib look like libmylib.1.0.0.dylib
- if (suffixes.last() == QLatin1String("dylib"))
- return true;
-
- validSuffixList << QLatin1String("so") << QLatin1String("bundle");
+ "so"_L1,
+ "bundle"_L1,
# elif defined(Q_OS_UNIX)
- validSuffixList << QLatin1String("so");
+ "so"_L1,
# endif
+ }; // candidates
+
+ auto isValidSuffix = [&candidates](QStringView s) {
+ return std::find(std::begin(candidates), std::end(candidates), s) != std::end(candidates);
+ };
// Examples of valid library names:
// libfoo.so
@@ -699,43 +659,54 @@ bool QLibrary::isLibrary(const QString &fileName)
// libfoo-0.3.so
// libfoo-0.3.so.0.3.0
- int suffix;
- int suffixPos = -1;
- for (suffix = 0; suffix < validSuffixList.count() && suffixPos == -1; ++suffix)
- suffixPos = suffixes.indexOf(validSuffixList.at(suffix));
+ auto suffixes = qTokenize(completeSuffix, u'.');
+ auto it = suffixes.begin();
+ const auto end = suffixes.end();
- bool valid = suffixPos != -1;
- for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i)
- if (i != suffixPos)
- (void)suffixes.at(i).toInt(&valid);
- return valid;
+ auto isNumeric = [](QStringView s) { bool ok; (void)s.toInt(&ok); return ok; };
+
+ while (it != end) {
+ if (isValidSuffix(*it++))
+ return q20::ranges::all_of(it, end, isNumeric);
+ }
+ return false; // no valid suffix found
#endif
}
static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
{
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- auto getMetaData = [](QFunctionPointer fptr) {
- auto f = reinterpret_cast<const char * (*)()>(fptr);
- return qMakePair<const char *, size_t>(f(), INT_MAX);
- };
-#else
- auto getMetaData = [](QFunctionPointer fptr) {
- auto f = reinterpret_cast<QPluginMetaData (*)()>(fptr);
- return f();
+ auto error = [=](QString &&explanation) {
+ *errMsg = QLibrary::tr("'%1' is not a Qt plugin (%2)").arg(priv->fileName, std::move(explanation));
+ return false;
};
+
+ QPluginMetaData metaData;
+ QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata_v2");
+ if (pfn) {
+ metaData = reinterpret_cast<QPluginMetaData (*)()>(pfn)();
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+ } else if ((pfn = priv->resolve("qt_plugin_query_metadata"))) {
+ metaData = reinterpret_cast<QPluginMetaData (*)()>(pfn)();
+ if (metaData.size < sizeof(QPluginMetaData::MagicHeader))
+ return error(QLibrary::tr("metadata too small"));
+
+ // adjust the meta data to point to the header
+ auto data = reinterpret_cast<const char *>(metaData.data);
+ data += sizeof(QPluginMetaData::MagicString);
+ metaData.data = data;
+ metaData.size -= sizeof(QPluginMetaData::MagicString);
#endif
+ } else {
+ return error(QLibrary::tr("entrypoint to query the plugin meta data not found"));
+ }
- QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata");
- if (!pfn)
- return false;
+ if (metaData.size < sizeof(QPluginMetaData::Header))
+ return error(QLibrary::tr("metadata too small"));
- auto metaData = getMetaData(pfn);
- QJsonDocument doc = qJsonFromRawLibraryMetaData(reinterpret_cast<const char *>(metaData.data), metaData.size, errMsg);
- if (doc.isNull())
- return false;
- priv->metaData = doc.object();
- return true;
+ if (priv->metaData.parse(metaData))
+ return true;
+ *errMsg = priv->metaData.errorString();
+ return false;
}
bool QLibraryPrivate::isPlugin()
@@ -755,8 +726,8 @@ void QLibraryPrivate::updatePluginState()
bool success = false;
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
- if (fileName.endsWith(QLatin1String(".debug"))) {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
+ if (fileName.endsWith(".debug"_L1)) {
// refuse to load a file that ends in .debug
// these are the debug symbols from the libraries
// the problem is that they are valid shared library files
@@ -771,7 +742,22 @@ void QLibraryPrivate::updatePluginState()
if (!pHnd.loadRelaxed()) {
// scan for the plugin metadata without loading
- success = findPatternUnloaded(fileName, this);
+ QLibraryScanResult result = findPatternUnloaded(fileName, this);
+#if defined(Q_OF_MACH_O)
+ if (result.length && result.isEncrypted) {
+ // We found the .qtmetadata section, but since the library is encrypted
+ // we need to dlopen() it before we can parse the metadata for further
+ // validation.
+ qCDebug(qt_lcDebugPlugins, "Library is encrypted. Doing prospective load before parsing metadata");
+ locker.unlock();
+ load();
+ locker.relock();
+ success = qt_get_metadata(this, &errorString);
+ } else
+#endif
+ {
+ success = result.length != 0;
+ }
} else {
// library is already loaded (probably via QLibrary)
// simply get the target function and call it.
@@ -779,7 +765,7 @@ void QLibraryPrivate::updatePluginState()
}
if (!success) {
- if (errorString.isEmpty()){
+ if (errorString.isEmpty()) {
if (fileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
else
@@ -791,28 +777,24 @@ void QLibraryPrivate::updatePluginState()
pluginState = IsNotAPlugin; // be pessimistic
- uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble();
- bool debug = metaData.value(QLatin1String("debug")).toBool();
+ uint qt_version = uint(metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
+ bool debug = metaData.value(QtPluginMetaDataKeys::IsDebug).toBool();
if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
- if (qt_debug_component()) {
- qWarning("In %s:\n"
+ qCDebug(qt_lcDebugPlugins, "In %s:\n"
" Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
QFile::encodeName(fileName).constData(),
(qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
debug ? "debug" : "release");
- }
errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
- .arg(fileName)
- .arg((qt_version&0xff0000) >> 16)
- .arg((qt_version&0xff00) >> 8)
- .arg(qt_version&0xff)
- .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
-#ifndef QT_NO_DEBUG_PLUGIN_CHECK
- } else if(debug != QLIBRARY_AS_DEBUG) {
+ .arg(fileName,
+ QString::number((qt_version & 0xff0000) >> 16),
+ QString::number((qt_version & 0xff00) >> 8),
+ QString::number(qt_version & 0xff),
+ debug ? "debug"_L1 : "release"_L1);
+ } else if (PluginMustMatchQtDebug && debug != QtBuildIsDebug) {
//don't issue a qWarning since we will hopefully find a non-debug? --Sam
errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
" (Cannot mix debug and release libraries.)").arg(fileName);
-#endif
} else {
pluginState = IsAPlugin;
}
@@ -832,10 +814,13 @@ bool QLibrary::load()
{
if (!d)
return false;
- if (did_load)
+ if (d.tag() == Loaded)
return d->pHnd.loadRelaxed();
- did_load = true;
- return d->load();
+ if (d->load()) {
+ d.setTag(Loaded);
+ return true;
+ }
+ return false;
}
/*!
@@ -849,35 +834,40 @@ bool QLibrary::load()
call will fail, and unloading will only happen when every instance
has called unload().
- Note that on Mac OS X 10.3 (Panther), dynamic libraries cannot be unloaded.
+ Note that on \macos, dynamic libraries cannot be unloaded.
+ QLibrary::unload() will return \c true, but the library will remain
+ loaded into the process.
\sa resolve(), load()
*/
bool QLibrary::unload()
{
- if (did_load) {
- did_load = false;
+ if (d.tag() == Loaded) {
+ d.setTag(NotLoaded);
return d->unload();
}
return false;
}
/*!
- Returns \c true if the library is loaded; otherwise returns \c false.
+ Returns \c true if load() succeeded; otherwise returns \c false.
+
+ \note Prior to Qt 6.6, this function would return \c true even without a
+ call to load() if another QLibrary object on the same library had caused it
+ to be loaded.
\sa load()
*/
bool QLibrary::isLoaded() const
{
- return d && d->pHnd.loadRelaxed();
+ return d.tag() == Loaded;
}
/*!
Constructs a library with the given \a parent.
*/
-QLibrary::QLibrary(QObject *parent)
- :QObject(parent), d(nullptr), did_load(false)
+QLibrary::QLibrary(QObject *parent) : QObject(parent)
{
}
@@ -891,13 +881,11 @@ QLibrary::QLibrary(QObject *parent)
suffix in accordance with the platform, e.g. ".so" on Unix,
".dylib" on \macos and iOS, and ".dll" on Windows. (See \l{fileName}.)
*/
-QLibrary::QLibrary(const QString& fileName, QObject *parent)
- :QObject(parent), d(nullptr), did_load(false)
+QLibrary::QLibrary(const QString &fileName, QObject *parent) : QObject(parent)
{
setFileName(fileName);
}
-
/*!
Constructs a library object with the given \a parent that will
load the library specified by \a fileName and major version number \a verNum.
@@ -908,8 +896,7 @@ QLibrary::QLibrary(const QString& fileName, QObject *parent)
suffix in accordance with the platform, e.g. ".so" on Unix,
".dylib" on \macos and iOS, and ".dll" on Windows. (See \l{fileName}.)
*/
-QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
- :QObject(parent), d(nullptr), did_load(false)
+QLibrary::QLibrary(const QString &fileName, int verNum, QObject *parent) : QObject(parent)
{
setFileNameAndVersion(fileName, verNum);
}
@@ -924,8 +911,8 @@ QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
suffix in accordance with the platform, e.g. ".so" on Unix,
".dylib" on \macos and iOS, and ".dll" on Windows. (See \l{fileName}.)
*/
-QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent)
- :QObject(parent), d(nullptr), did_load(false)
+QLibrary::QLibrary(const QString &fileName, const QString &version, QObject *parent)
+ : QObject(parent)
{
setFileNameAndVersion(fileName, version);
}
@@ -944,7 +931,6 @@ QLibrary::~QLibrary()
d->release();
}
-
/*!
\property QLibrary::fileName
\brief the file name of the library
@@ -968,14 +954,7 @@ QLibrary::~QLibrary()
void QLibrary::setFileName(const QString &fileName)
{
- QLibrary::LoadHints lh;
- if (d) {
- lh = d->loadHints();
- d->release();
- d = nullptr;
- did_load = false;
- }
- d = QLibraryPrivate::findOrCreate(fileName, QString(), lh);
+ setFileNameAndVersion(fileName, QString());
}
QString QLibrary::fileName() const
@@ -998,14 +977,7 @@ QString QLibrary::fileName() const
*/
void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
{
- QLibrary::LoadHints lh;
- if (d) {
- lh = d->loadHints();
- d->release();
- d = nullptr;
- did_load = false;
- }
- d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString(), lh);
+ setFileNameAndVersion(fileName, verNum >= 0 ? QString::number(verNum) : QString());
}
/*!
@@ -1023,10 +995,9 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver
if (d) {
lh = d->loadHints();
d->release();
- d = nullptr;
- did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName, version, lh);
+ QLibraryPrivate *dd = QLibraryPrivate::findOrCreate(fileName, version, lh);
+ d = QTaggedPointer(dd, NotLoaded); // we haven't load()ed
}
/*!
@@ -1161,6 +1132,10 @@ QString QLibrary::errorString() const
lazy symbol resolution, and will not export external symbols for resolution
in other dynamically-loaded libraries.
+ \note Hints can only be cleared when this object is not associated with a
+ file. Hints can only be added once the file name is set (\a hints will
+ be or'ed with the old hints).
+
\note Setting this property after the library has been loaded has no effect
and loadHints() will not reflect those changes.
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h
index 0b37b8b134..f31047b214 100644
--- a/src/corelib/plugin/qlibrary.h
+++ b/src/corelib/plugin/qlibrary.h
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLIBRARY_H
#define QLIBRARY_H
#include <QtCore/qobject.h>
+#include <QtCore/qtaggedpointer.h>
QT_REQUIRE_CONFIG(library);
@@ -62,13 +27,13 @@ public:
DeepBindHint = 0x10
};
Q_DECLARE_FLAGS(LoadHints, LoadHint)
- Q_FLAG(LoadHint)
+ Q_ENUM(LoadHint)
Q_FLAG(LoadHints)
explicit QLibrary(QObject *parent = nullptr);
- explicit QLibrary(const QString& fileName, QObject *parent = nullptr);
- explicit QLibrary(const QString& fileName, int verNum, QObject *parent = nullptr);
- explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = nullptr);
+ explicit QLibrary(const QString &fileName, QObject *parent = nullptr);
+ explicit QLibrary(const QString &fileName, int verNum, QObject *parent = nullptr);
+ explicit QLibrary(const QString &fileName, const QString &version, QObject *parent = nullptr);
~QLibrary();
QFunctionPointer resolve(const char *symbol);
@@ -91,9 +56,14 @@ public:
void setLoadHints(LoadHints hints);
LoadHints loadHints() const;
+
private:
- QLibraryPrivate *d;
- bool did_load;
+ enum LoadStatusTag {
+ NotLoaded,
+ Loaded
+ };
+
+ QTaggedPointer<QLibraryPrivate, LoadStatusTag> d = nullptr;
Q_DISABLE_COPY(QLibrary)
};
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index 3ca544b2de..87d36ee5c8 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLIBRARY_P_H
#define QLIBRARY_P_H
@@ -52,21 +16,34 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
#include "QtCore/qlibrary.h"
+
+#include "QtCore/private/qfactoryloader_p.h"
+#include "QtCore/qloggingcategory.h"
#include "QtCore/qmutex.h"
+#include "QtCore/qplugin.h"
#include "QtCore/qpointer.h"
#include "QtCore/qstringlist.h"
-#include "QtCore/qplugin.h"
#ifdef Q_OS_WIN
# include "QtCore/qt_windows.h"
#endif
+#include <memory>
+
QT_REQUIRE_CONFIG(library);
QT_BEGIN_NAMESPACE
-bool qt_debug_component();
+Q_DECLARE_LOGGING_CATEGORY(qt_lcDebugPlugins)
+
+struct QLibraryScanResult
+{
+ qsizetype pos;
+ qsizetype length;
+#if defined(Q_OF_MACH_O)
+ bool isEncrypted = false;
+#endif
+};
class QLibraryStore;
class QLibraryPrivate
@@ -79,6 +56,12 @@ public:
#endif
enum UnloadFlag { UnloadSys, NoUnloadSys };
+ struct Deleter {
+ // QLibraryPrivate::release() is not, yet, and cannot easily be made, noexcept:
+ void operator()(QLibraryPrivate *p) const { p->release(); }
+ };
+ using UniquePtr = std::unique_ptr<QLibraryPrivate, Deleter>;
+
const QString fileName;
const QString fullVersion;
@@ -104,7 +87,7 @@ public:
// the mutex protects the fields below
QMutex mutex;
QPointer<QObject> inst; // used by QFactoryLoader
- QJsonObject metaData;
+ QPluginParsedMetaData metaData;
QString errorString;
QString qualifiedFileName;
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index a5c72f81d9..a6fb5403cd 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -1,70 +1,31 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2020 Intel Corporation
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
+#include <qcoreapplication.h>
#include <qfile.h>
#include "qlibrary_p.h"
-#include <qcoreapplication.h>
#include <private/qfilesystementry_p.h>
#include <private/qsimd_p.h>
#include <dlfcn.h>
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
# include <private/qcore_mac_p.h>
#endif
#ifdef Q_OS_ANDROID
-# include <private/qjnihelpers_p.h>
+#include <private/qjnihelpers_p.h>
+#include <QtCore/qjnienvironment.h>
#endif
QT_BEGIN_NAMESPACE
-static QString qdlerror()
-{
- const char *err = dlerror();
- return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString();
-}
+using namespace Qt::StringLiterals;
-QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
+QStringList QLibraryPrivate::suffixes_sys(const QString &fullVersion)
{
QStringList suffixes;
#if defined(Q_OS_HPUX)
@@ -81,36 +42,36 @@ QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
// .so is preferred.
# if defined(__ia64)
if (!fullVersion.isEmpty()) {
- suffixes << QLatin1String(".so.%1").arg(fullVersion);
+ suffixes << ".so.%1"_L1.arg(fullVersion);
} else {
- suffixes << QLatin1String(".so");
+ suffixes << ".so"_L1;
}
# endif
if (!fullVersion.isEmpty()) {
- suffixes << QLatin1String(".sl.%1").arg(fullVersion);
- suffixes << QLatin1String(".%1").arg(fullVersion);
+ suffixes << ".sl.%1"_L1.arg(fullVersion);
+ suffixes << ".%1"_L1.arg(fullVersion);
} else {
- suffixes << QLatin1String(".sl");
+ suffixes << ".sl"_L1;
}
#elif defined(Q_OS_AIX)
suffixes << ".a";
#else
if (!fullVersion.isEmpty()) {
- suffixes << QLatin1String(".so.%1").arg(fullVersion);
+ suffixes << ".so.%1"_L1.arg(fullVersion);
} else {
- suffixes << QLatin1String(".so");
+ suffixes << ".so"_L1;
# ifdef Q_OS_ANDROID
suffixes << QStringLiteral(LIBS_SUFFIX);
# endif
}
#endif
-# ifdef Q_OS_MAC
+# ifdef Q_OS_DARWIN
if (!fullVersion.isEmpty()) {
- suffixes << QLatin1String(".%1.bundle").arg(fullVersion);
- suffixes << QLatin1String(".%1.dylib").arg(fullVersion);
+ suffixes << ".%1.bundle"_L1.arg(fullVersion);
+ suffixes << ".%1.dylib"_L1.arg(fullVersion);
} else {
- suffixes << QLatin1String(".bundle") << QLatin1String(".dylib");
+ suffixes << ".bundle"_L1 << ".dylib"_L1;
}
#endif
return suffixes;
@@ -118,21 +79,26 @@ QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
QStringList QLibraryPrivate::prefixes_sys()
{
- return QStringList() << QLatin1String("lib");
+ return QStringList() << "lib"_L1;
}
bool QLibraryPrivate::load_sys()
{
+#if defined(Q_OS_WASM) && defined(QT_STATIC)
+ // emscripten does not support dlopen when using static linking
+ return false;
+#endif
+
QMutexLocker locker(&mutex);
QString attempt;
QFileSystemEntry fsEntry(fileName);
QString path = fsEntry.path();
QString name = fsEntry.fileName();
- if (path == QLatin1String(".") && !fileName.startsWith(path))
+ if (path == "."_L1 && !fileName.startsWith(path))
path.clear();
else
- path += QLatin1Char('/');
+ path += u'/';
QStringList suffixes;
QStringList prefixes;
@@ -141,7 +107,7 @@ bool QLibraryPrivate::load_sys()
suffixes = suffixes_sys(fullVersion);
}
int dlFlags = 0;
- int loadHints = this->loadHints();
+ auto loadHints = this->loadHints();
if (loadHints & QLibrary::ResolveAllSymbolsHint) {
dlFlags |= RTLD_NOW;
} else {
@@ -197,7 +163,7 @@ bool QLibraryPrivate::load_sys()
QStringList tmp;
qSwap(tmp, list);
list.reserve(tmp.size() * 2);
- for (const QString &s : qAsConst(tmp)) {
+ for (const QString &s : std::as_const(tmp)) {
QString modifiedPath = s;
f(&modifiedPath);
list.append(modifiedPath);
@@ -206,10 +172,10 @@ bool QLibraryPrivate::load_sys()
};
if (pluginState == IsAPlugin) {
// add ".avx2" to each suffix in the list
- transform(suffixes, [](QString *s) { s->append(QLatin1String(".avx2")); });
+ transform(suffixes, [](QString *s) { s->append(".avx2"_L1); });
} else {
// prepend "haswell/" to each prefix in the list
- transform(prefixes, [](QString *s) { s->prepend(QLatin1String("haswell/")); });
+ transform(prefixes, [](QString *s) { s->prepend("haswell/"_L1); });
}
}
#endif
@@ -221,15 +187,15 @@ bool QLibraryPrivate::load_sys()
for (int suffix = 0; retry && !hnd && suffix < suffixes.size(); suffix++) {
if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
continue;
- if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/')))
+ if (path.isEmpty() && prefixes.at(prefix).contains(u'/'))
continue;
if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix)))
continue;
if (loadHints & QLibrary::LoadArchiveMemberHint) {
attempt = name;
- int lparen = attempt.indexOf(QLatin1Char('('));
+ qsizetype lparen = attempt.indexOf(u'(');
if (lparen == -1)
- lparen = attempt.count();
+ lparen = attempt.size();
attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix));
} else {
attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
@@ -239,19 +205,11 @@ bool QLibraryPrivate::load_sys()
#ifdef Q_OS_ANDROID
if (!hnd) {
auto attemptFromBundle = attempt;
- hnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags);
- }
- if (hnd) {
- using JniOnLoadPtr = jint (*)(JavaVM *vm, void *reserved);
- JniOnLoadPtr jniOnLoad = reinterpret_cast<JniOnLoadPtr>(dlsym(pHnd, "JNI_OnLoad"));
- if (jniOnLoad && jniOnLoad(QtAndroidPrivate::javaVM(), nullptr) == JNI_ERR) {
- dlclose(hnd);
- pHnd = nullptr;
- }
+ hnd = dlopen(QFile::encodeName(attemptFromBundle.replace(u'/', u'_')), dlFlags);
}
#endif
- if (!hnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
+ if (!hnd && fileName.startsWith(u'/') && QFile::exists(attempt)) {
// We only want to continue if dlopen failed due to that the shared library did not exist.
// However, we are only able to apply this check for absolute filenames (since they are
// not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...)
@@ -261,12 +219,12 @@ bool QLibraryPrivate::load_sys()
}
}
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
if (!hnd) {
QByteArray utf8Bundle = fileName.toUtf8();
QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true);
QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl);
- if(bundle) {
+ if (bundle) {
QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle);
char executableFile[FILENAME_MAX];
CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX);
@@ -278,7 +236,8 @@ bool QLibraryPrivate::load_sys()
locker.relock();
if (!hnd) {
- errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror());
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName,
+ QLatin1StringView(dlerror()));
}
if (hnd) {
qualifiedFileName = attempt;
@@ -290,37 +249,28 @@ bool QLibraryPrivate::load_sys()
bool QLibraryPrivate::unload_sys()
{
- if (dlclose(pHnd.loadAcquire())) {
-#if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in
- char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance
+ bool doTryUnload = true;
+#ifndef RTLD_NODELETE
+ if (loadHints() & QLibrary::PreventUnloadHint)
+ doTryUnload = false;
+#endif
+ if (doTryUnload && dlclose(pHnd.loadAcquire())) {
+ const char *error = dlerror();
+#if defined (Q_OS_QNX)
+ // Workaround until fixed in QNX; fixes crash in
+ // QtDeclarative auto test "qqmlenginecleanup" for instance
if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative"
return true;
- errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName,
- QLatin1String(error));
-#else
- errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName, qdlerror());
#endif
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName,
+ QLatin1StringView(error));
return false;
}
errorString.clear();
return true;
}
-#if defined(Q_OS_LINUX)
-Q_CORE_EXPORT QFunctionPointer qt_linux_find_symbol_sys(const char *symbol)
-{
- return QFunctionPointer(dlsym(RTLD_DEFAULT, symbol));
-}
-#endif
-
-#ifdef Q_OS_MAC
-Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symbol)
-{
- return QFunctionPointer(dlsym(handle, symbol));
-}
-#endif
-
-QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
+QFunctionPointer QLibraryPrivate::resolve_sys(const char *symbol)
{
QFunctionPointer address = QFunctionPointer(dlsym(pHnd.loadAcquire(), symbol));
return address;
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index ef1b389adc..c95118e554 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qlibrary_p.h"
-#include "qfile.h"
+
#include "qdir.h"
+#include "qfile.h"
#include "qfileinfo.h"
#include <private/qfilesystementry_p.h>
@@ -48,6 +13,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
extern QString qt_error_string(int code);
QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
@@ -80,7 +47,7 @@ bool QLibraryPrivate::load_sys()
QStringList attempts;
if (pluginState != IsAPlugin)
- attempts.append(fileName + QLatin1String(".dll"));
+ attempts.append(fileName + ".dll"_L1);
// If the fileName is an absolute path we try that first, otherwise we
// use the system-specific suffix first
@@ -92,7 +59,7 @@ bool QLibraryPrivate::load_sys()
locker.unlock();
Handle hnd = nullptr;
- for (const QString &attempt : qAsConst(attempts)) {
+ for (const QString &attempt : std::as_const(attempts)) {
hnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
// If we have a handle or the last error is something other than "unable
@@ -114,9 +81,9 @@ bool QLibraryPrivate::load_sys()
::GetModuleFileName(hnd, buffer, MAX_PATH);
QString moduleFileName = QString::fromWCharArray(buffer);
- moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
+ moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(u'\\'));
const QDir dir(fsEntry.path());
- if (dir.path() == QLatin1String("."))
+ if (dir.path() == "."_L1)
qualifiedFileName = moduleFileName;
else
qualifiedFileName = dir.filePath(moduleFileName);
@@ -147,7 +114,7 @@ bool QLibraryPrivate::unload_sys()
return true;
}
-QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
+QFunctionPointer QLibraryPrivate::resolve_sys(const char *symbol)
{
FARPROC address = GetProcAddress(pHnd.loadAcquire(), symbol);
return QFunctionPointer(address);
diff --git a/src/corelib/plugin/qmachparser.cpp b/src/corelib/plugin/qmachparser.cpp
index 11670cafe9..7a82b84cb3 100644
--- a/src/corelib/plugin/qmachparser.cpp
+++ b/src/corelib/plugin/qmachparser.cpp
@@ -1,54 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmachparser_p.h"
-#if defined(Q_OF_MACH_O)
-
#include <qendian.h>
-#include "qlibrary_p.h"
#include <mach-o/loader.h>
#include <mach-o/fat.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+// Whether we include some extra validity checks
+// (checks to ensure we don't read out-of-bounds are always included)
+static constexpr bool IncludeValidityChecks = true;
+
#if defined(Q_PROCESSOR_X86_64)
# define MACHO64
static const cpu_type_t my_cputype = CPU_TYPE_X86_64;
@@ -81,15 +48,32 @@ typedef section my_section;
static const uint32_t my_magic = MH_MAGIC;
#endif
-static int ns(const QString &reason, const QString &library, QString *errorString)
+Q_DECL_COLD_FUNCTION
+static QLibraryScanResult notfound(const QString &reason, QString *errorString)
{
- if (errorString)
- *errorString = QLibrary::tr("'%1' is not a valid Mach-O binary (%2)")
- .arg(library, reason.isEmpty() ? QLibrary::tr("file is corrupt") : reason);
- return QMachOParser::NotSuitable;
+ *errorString = QLibrary::tr("'%1' is not a valid Mach-O binary (%2)")
+ .arg(*errorString, reason.isEmpty() ? QLibrary::tr("file is corrupt") : reason);
+ return {};
+}
+
+static bool isEncrypted(const my_mach_header *header)
+{
+ auto commandCursor = uintptr_t(header) + sizeof(my_mach_header);
+ for (uint32_t i = 0; i < header->ncmds; ++i) {
+ load_command *loadCommand = reinterpret_cast<load_command *>(commandCursor);
+ if (loadCommand->cmd == LC_ENCRYPTION_INFO || loadCommand->cmd == LC_ENCRYPTION_INFO_64) {
+ // The layout of encryption_info_command and encryption_info_command_64 is the same
+ // up until and including cryptid, so we can treat it as encryption_info_command.
+ auto encryptionInfoCommand = reinterpret_cast<encryption_info_command*>(loadCommand);
+ return encryptionInfoCommand->cryptid != 0;
+ }
+ commandCursor += loadCommand->cmdsize;
+ }
+
+ return false;
}
-int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QString *errorString, qsizetype *pos, qsizetype *sectionlen)
+QLibraryScanResult QMachOParser::parse(const char *m_s, ulong fdlen, QString *errorString)
{
// The minimum size of a Mach-O binary we're interested in.
// It must have a full Mach header, at least one segment and at least one
@@ -100,21 +84,21 @@ int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QS
static const size_t MinFatHeaderSize = sizeof(fat_header) + 2 * sizeof(fat_arch);
if (Q_UNLIKELY(fdlen < MinFileSize))
- return ns(QLibrary::tr("file too small"), library, errorString);
+ return notfound(QLibrary::tr("file too small"), errorString);
// find out if this is a fat Mach-O binary first
- const my_mach_header *header = 0;
+ const my_mach_header *header = nullptr;
const fat_header *fat = reinterpret_cast<const fat_header *>(m_s);
if (fat->magic == qToBigEndian(FAT_MAGIC)) {
// find our architecture in the binary
const fat_arch *arch = reinterpret_cast<const fat_arch *>(fat + 1);
if (Q_UNLIKELY(fdlen < MinFatHeaderSize)) {
- return ns(QLibrary::tr("file too small"), library, errorString);
+ return notfound(QLibrary::tr("file too small"), errorString);
}
int count = qFromBigEndian(fat->nfat_arch);
if (Q_UNLIKELY(fdlen < sizeof(*fat) + sizeof(*arch) * count))
- return ns(QString(), library, errorString);
+ return notfound(QString(), errorString);
for (int i = 0; i < count; ++i) {
if (arch[i].cputype == qToBigEndian(my_cputype)) {
@@ -123,7 +107,7 @@ int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QS
uint32_t offset = qFromBigEndian(arch[i].offset);
if (Q_UNLIKELY(size > fdlen) || Q_UNLIKELY(offset > fdlen)
|| Q_UNLIKELY(size + offset > fdlen) || Q_UNLIKELY(size < MinFileSize))
- return ns(QString(), library, errorString);
+ return notfound(QString(), errorString);
header = reinterpret_cast<const my_mach_header *>(m_s + offset);
fdlen = size;
@@ -131,36 +115,35 @@ int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QS
}
}
if (!header)
- return ns(QLibrary::tr("no suitable architecture in fat binary"), library, errorString);
+ return notfound(QLibrary::tr("no suitable architecture in fat binary"), errorString);
// check the magic again
if (Q_UNLIKELY(header->magic != my_magic))
- return ns(QString(), library, errorString);
+ return notfound(QString(), errorString);
} else {
header = reinterpret_cast<const my_mach_header *>(m_s);
fat = 0;
// check magic
if (header->magic != my_magic)
- return ns(QLibrary::tr("invalid magic %1").arg(qFromBigEndian(header->magic), 8, 16, QLatin1Char('0')),
- library, errorString);
+ return notfound(QLibrary::tr("invalid magic %1").arg(qFromBigEndian(header->magic),
+ 8, 16, '0'_L1),
+ errorString);
}
- // from this point on, fdlen is specific to this architecture
// from this point on, everything is in host byte order
- *pos = reinterpret_cast<const char *>(header) - m_s;
// (re-)check the CPU type
// ### should we check the CPU subtype? Maybe on ARM?
if (header->cputype != my_cputype) {
if (fat)
- return ns(QString(), library, errorString);
- return ns(QLibrary::tr("wrong architecture"), library, errorString);
+ return notfound(QString(), errorString);
+ return notfound(QLibrary::tr("wrong architecture"), errorString);
}
// check the file type
if (Q_UNLIKELY(header->filetype != MH_BUNDLE && header->filetype != MH_DYLIB))
- return ns(QLibrary::tr("not a dynamic library"), library, errorString);
+ return notfound(QLibrary::tr("not a dynamic library"), errorString);
// find the __TEXT segment, "qtmetadata" section
const my_segment_command *seg = reinterpret_cast<const my_segment_command *>(header + 1);
@@ -171,14 +154,14 @@ int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QS
// We're sure that the file size includes at least one load command
// but we have to check anyway if we're past the first
if (Q_UNLIKELY(fdlen < minsize + sizeof(load_command)))
- return ns(QString(), library, errorString);
+ return notfound(QString(), errorString);
// cmdsize can't be trusted until validated
// so check it against fdlen anyway
// (these are unsigned operations, with overflow behavior specified in the standard)
minsize += seg->cmdsize;
if (Q_UNLIKELY(fdlen < minsize) || Q_UNLIKELY(fdlen < seg->cmdsize))
- return ns(QString(), library, errorString);
+ return notfound(QString(), errorString);
const uint32_t MyLoadCommand = sizeof(void *) > 4 ? LC_SEGMENT_64 : LC_SEGMENT;
if (seg->cmd != MyLoadCommand)
@@ -195,11 +178,25 @@ int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QS
// found it!
if (Q_UNLIKELY(fdlen < sect[j].offset) || Q_UNLIKELY(fdlen < sect[j].size)
|| Q_UNLIKELY(fdlen < sect[j].offset + sect[j].size))
- return ns(QString(), library, errorString);
+ return notfound(QString(), errorString);
+
+ if (sect[j].size < sizeof(QPluginMetaData::MagicHeader))
+ return notfound(QLibrary::tr(".qtmetadata section is too small"), errorString);
+
+ const bool binaryIsEncrypted = isEncrypted(header);
+ qsizetype pos = reinterpret_cast<const char *>(header) - m_s + sect[j].offset;
- *pos += sect[j].offset;
- *sectionlen = sect[j].size;
- return QtMetaDataSection;
+ // We can not read the section data of encrypted libraries until they
+ // have been dlopened(), so skip validity check if that's the case.
+ if (IncludeValidityChecks && !binaryIsEncrypted) {
+ QByteArrayView expectedMagic = QByteArrayView::fromArray(QPluginMetaData::MagicString);
+ QByteArrayView actualMagic = QByteArrayView(m_s + pos, expectedMagic.size());
+ if (expectedMagic != actualMagic)
+ return notfound(QLibrary::tr(".qtmetadata section has incorrect magic"), errorString);
+ }
+
+ pos += sizeof(QPluginMetaData::MagicString);
+ return { pos, qsizetype(sect[j].size - sizeof(QPluginMetaData::MagicString)), binaryIsEncrypted };
}
}
@@ -207,13 +204,9 @@ int QMachOParser::parse(const char *m_s, ulong fdlen, const QString &library, QS
seg = reinterpret_cast<const my_segment_command *>(reinterpret_cast<const char *>(seg) + seg->cmdsize);
}
-// // No Qt section was found, but at least we know that where the proper architecture's boundaries are
-// return NoQtSection;
- if (errorString)
- *errorString = QLibrary::tr("'%1' is not a Qt plugin").arg(library);
- return NotSuitable;
+ // No .qtmetadata section was found
+ *errorString = QLibrary::tr("'%1' is not a Qt plugin").arg(*errorString);
+ return {};
}
QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/plugin/qmachparser_p.h b/src/corelib/plugin/qmachparser_p.h
index 290b68876f..85a174e66e 100644
--- a/src/corelib/plugin/qmachparser_p.h
+++ b/src/corelib/plugin/qmachparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMACHPARSER_P_H
#define QMACHPARSER_P_H
@@ -51,8 +15,7 @@
// We mean it.
//
-#include <qendian.h>
-#include <private/qglobal_p.h>
+#include "qlibrary_p.h"
QT_REQUIRE_CONFIG(library);
@@ -66,12 +29,11 @@ class QLibraryPrivate;
class Q_AUTOTEST_EXPORT QMachOParser
{
public:
- enum { QtMetaDataSection, NoQtSection, NotSuitable };
- static int parse(const char *m_s, ulong fdlen, const QString &library, QString *errorString, qsizetype *pos, qsizetype *sectionlen);
+ static QLibraryScanResult parse(const char *m_s, ulong fdlen, QString *errorString);
};
QT_END_NAMESPACE
-#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
+#endif // defined(Q_OF_MACH_O)
#endif // QMACHPARSER_P_H
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index d53182f1a9..909c8acdcc 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -1,61 +1,23 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLUGIN_H
#define QPLUGIN_H
+#if 0
+#pragma qt_class(QtPlugin)
+#endif
+
#include <QtCore/qobject.h>
#include <QtCore/qpointer.h>
#include <QtCore/qjsonobject.h>
-QT_BEGIN_NAMESPACE
-
+#include <QtCore/q20algorithm.h>
-#ifndef Q_EXTERN_C
-# ifdef __cplusplus
-# define Q_EXTERN_C extern "C"
-# else
-# define Q_EXTERN_C extern
-# endif
-#endif
+QT_BEGIN_NAMESPACE
+// Used up to Qt 6.2
inline constexpr unsigned char qPluginArchRequirements()
{
return 0
@@ -72,53 +34,100 @@ inline constexpr unsigned char qPluginArchRequirements()
}
typedef QObject *(*QtPluginInstanceFunction)();
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-typedef const char *(*QtPluginMetaDataFunction)();
-#else
struct QPluginMetaData
{
- const uchar *data;
+ static constexpr quint8 CurrentMetaDataVersion = 1;
+ static constexpr char MagicString[] = {
+ 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!'
+ };
+
+ template <size_t OSize, typename OO, size_t ISize, typename II>
+ static constexpr void copy(OO (&out)[OSize], II (&in)[ISize])
+ {
+ static_assert(OSize <= ISize, "Output would not be fully initialized");
+ q20::copy_n(in, OSize, out);
+ }
+
+ static constexpr quint8 archRequirements()
+ {
+ quint8 v = 0;
+#if defined(__AVX512F__)
+ v = 4; // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ and AVX512VL
+#elif defined(__AVX__) || defined(__BMI__) || defined(__BMI2__) || defined(__MOVBE__)
+ v = 3; // x86-64-v3: AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
+#elif defined(__SSE3__)
+ v = 2; // x86-64-v2: POPCNT, SSE3, SSSE3, SSE4.1 and SSE4.2.
+#elif defined(__SSE__) || defined(__MMX___)
+ v = 1; // x86-64 baseline: SSE and SSE2
+#endif
+#ifndef QT_NO_DEBUG
+ v |= 0x80;
+#endif
+ return v;
+ }
+
+ struct Header {
+ quint8 version = CurrentMetaDataVersion;
+ quint8 qt_major_version = QT_VERSION_MAJOR;
+ quint8 qt_minor_version = QT_VERSION_MINOR;
+ quint8 plugin_arch_requirements = archRequirements();
+ };
+ static_assert(alignof(Header) == 1, "Alignment of header incorrect with this compiler");
+
+ struct MagicHeader {
+ char magic[sizeof(QPluginMetaData::MagicString)] = {};
+ constexpr MagicHeader() { copy(magic, QPluginMetaData::MagicString); }
+ Header header = {};
+ };
+ static_assert(alignof(MagicHeader) == 1, "Alignment of header incorrect with this compiler");
+
+ struct ElfNoteHeader {
+ static constexpr quint32 NoteType = 0x74510001;
+ static constexpr char NoteName[] = "qt-project!";
+
+ // ELF note header
+ quint32 n_namesz = sizeof(name);
+ quint32 n_descsz;
+ quint32 n_type = NoteType;
+ char name[sizeof(NoteName)] = {};
+
+ // payload
+ alignas(void *) // mandatory alignment as per ELF note requirements
+ Header header = {};
+ constexpr ElfNoteHeader(quint32 payloadSize) : n_descsz(sizeof(header) + payloadSize)
+ { QPluginMetaData::copy(name, NoteName); }
+ };
+ static_assert(alignof(ElfNoteHeader) == alignof(void*), "Alignment of header incorrect with this compiler");
+ static_assert((sizeof(ElfNoteHeader::name) % 4) == 0, "ELF note name length not a multiple of 4");
+
+ const void *data;
size_t size;
};
typedef QPluginMetaData (*QtPluginMetaDataFunction)();
-#endif
struct Q_CORE_EXPORT QStaticPlugin
{
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
public:
constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m)
- : instance(i), rawMetaData(m().data), rawMetaDataSize(m().size)
+ : instance(i), rawMetaDataSize(m().size), rawMetaData(m().data)
{}
QtPluginInstanceFunction instance;
+ QJsonObject metaData() const;
+
private:
- // ### Qt 6: revise, as this is not standard-layout
- const void *rawMetaData;
qsizetype rawMetaDataSize;
-public:
-#elif !defined(Q_QDOC)
- // Note: This struct is initialized using an initializer list.
- // As such, it cannot have any new constructors or variables.
- QtPluginInstanceFunction instance;
- QtPluginMetaDataFunction rawMetaData;
-#else
- // Since qdoc gets confused by the use of function
- // pointers, we add these dummes for it to parse instead:
- QObject *instance();
- const char *rawMetaData();
-#endif
- QJsonObject metaData() const;
+ const void *rawMetaData;
+ friend class QFactoryLoader;
};
Q_DECLARE_TYPEINFO(QStaticPlugin, Q_PRIMITIVE_TYPE);
void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
-#if (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG))
+#if defined(Q_OF_ELF) || (defined(Q_OS_WIN) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG)))
# define QT_PLUGIN_METADATA_SECTION \
__attribute__ ((section (".qtmetadata"))) __attribute__((used))
-#elif defined(Q_OS_MAC)
-// TODO: Implement section parsing on Mac
+#elif defined(Q_OS_DARWIN)
# define QT_PLUGIN_METADATA_SECTION \
__attribute__ ((section ("__TEXT,qtmetadata"))) __attribute__((used))
#elif defined(Q_CC_MSVC)
@@ -130,6 +139,57 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
# define QT_PLUGIN_METADATA_SECTION
#endif
+// Since Qt 6.3
+template <auto (&PluginMetaData)> class QPluginMetaDataV2
+{
+ struct ElfNotePayload : QPluginMetaData::ElfNoteHeader {
+ static constexpr size_t HeaderOffset = offsetof(QPluginMetaData::ElfNoteHeader, header);
+ quint8 payload[sizeof(PluginMetaData)] = {};
+ constexpr ElfNotePayload() : ElfNoteHeader(sizeof(PluginMetaData))
+ { QPluginMetaData::copy(payload, PluginMetaData); }
+ };
+
+ struct RegularPayload : QPluginMetaData::MagicHeader {
+ static constexpr size_t HeaderOffset = offsetof(QPluginMetaData::MagicHeader, header);
+ quint8 payload[sizeof(PluginMetaData)] = {};
+ constexpr RegularPayload() { QPluginMetaData::copy(payload, PluginMetaData); }
+ };
+
+ struct StaticPayload {
+ static constexpr size_t HeaderOffset = 0;
+ QPluginMetaData::Header header = {};
+ quint8 payload[sizeof(PluginMetaData)] = {};
+ constexpr StaticPayload() { QPluginMetaData::copy(payload, PluginMetaData); }
+ };
+
+#if defined(QT_STATICPLUGIN)
+# define QT_PLUGIN_METADATAV2_SECTION
+ using Payload = StaticPayload;
+#elif defined(Q_OF_ELF)
+# ifdef Q_CC_CLANG
+# define QT_PLUGIN_METADATAV2_SECTION \
+ __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *)), \
+ no_sanitize("address")))
+# else
+# define QT_PLUGIN_METADATAV2_SECTION \
+ __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *))))
+# endif
+ using Payload = ElfNotePayload;
+#else
+# define QT_PLUGIN_METADATAV2_SECTION QT_PLUGIN_METADATA_SECTION
+ using Payload = RegularPayload;
+#endif
+
+ Payload payload = {};
+
+public:
+ operator QPluginMetaData() const
+ {
+ Q_ASSERT(reinterpret_cast<const char *>(&payload) + Payload::HeaderOffset ==
+ reinterpret_cast<const char *>(&payload.header));
+ return { &payload.header, sizeof(payload) - Payload::HeaderOffset };
+ }
+};
#define Q_IMPORT_PLUGIN(PLUGIN) \
extern const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGIN(); \
@@ -160,48 +220,38 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
}
#if defined(QT_STATICPLUGIN)
+# define QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) \
+ static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##MANGLEDNAME() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS) \
+ const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##MANGLEDNAME() \
+ { return { qt_plugin_instance_##MANGLEDNAME, qt_plugin_query_metadata_##MANGLEDNAME}; } \
+ /**/
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
- static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \
- Q_PLUGIN_INSTANCE(PLUGINCLASS) \
static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \
- { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \
- const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \
- return { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \
- }
-#else
-# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
- static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \
- Q_PLUGIN_INSTANCE(PLUGINCLASS) \
- static const char *qt_plugin_query_metadata_##PLUGINCLASSNAME() { return reinterpret_cast<const char *>(qt_pluginMetaData); } \
- const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \
- QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \
- return plugin; \
- }
-#endif
+ { return { qt_pluginMetaData_##PLUGINCLASSNAME, sizeof qt_pluginMetaData_##PLUGINCLASSNAME }; } \
+ QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, PLUGINCLASSNAME)
+# define QT_MOC_EXPORT_PLUGIN_V2(PLUGINCLASS, MANGLEDNAME, MD) \
+ static QT_PREPEND_NAMESPACE(QPluginMetaData) qt_plugin_query_metadata_##MANGLEDNAME() \
+ { static constexpr QPluginMetaDataV2<MD> md{}; return md; } \
+ QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME)
#else
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+# define QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) \
+ extern "C" Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS) \
+ /**/
# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
- Q_EXTERN_C Q_DECL_EXPORT \
+ extern "C" Q_DECL_EXPORT \
QPluginMetaData qt_plugin_query_metadata() \
- { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \
- Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
- Q_PLUGIN_INSTANCE(PLUGINCLASS)
-
-#else
-
-# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
- Q_EXTERN_C Q_DECL_EXPORT \
- const char *qt_plugin_query_metadata() \
- { return reinterpret_cast<const char *>(qt_pluginMetaData); } \
- Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
- Q_PLUGIN_INSTANCE(PLUGINCLASS)
-
-#endif
+ { return { qt_pluginMetaData_##PLUGINCLASSNAME, sizeof qt_pluginMetaData_##PLUGINCLASSNAME }; } \
+ QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, PLUGINCLASSNAME)
+# define QT_MOC_EXPORT_PLUGIN_V2(PLUGINCLASS, MANGLEDNAME, MD) \
+ extern "C" Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QPluginMetaData) qt_plugin_query_metadata_v2()\
+ { static constexpr QT_PLUGIN_METADATAV2_SECTION QPluginMetaDataV2<MD> md{}; return md; } \
+ QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME)
#endif
#define Q_EXPORT_PLUGIN(PLUGIN) \
diff --git a/src/corelib/plugin/qplugin.qdoc b/src/corelib/plugin/qplugin.qdoc
index 968fb4820a..0ca248a548 100644
--- a/src/corelib/plugin/qplugin.qdoc
+++ b/src/corelib/plugin/qplugin.qdoc
@@ -1,32 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\headerfile <QtPlugin>
+ \inmodule QtCore
\title Defining Plugins
\keyword qtplugin-defining-plugins
\ingroup plugins
@@ -42,13 +19,10 @@
This macro associates the given \a Identifier (a string literal)
to the interface class called \a ClassName. The \a Identifier must
- be unique. For example:
-
- \snippet plugandpaint/app/interfaces.h 3
+ be unique.
This macro is normally used right after the class definition for
- \a ClassName, in a header file. See the
- \l{tools/plugandpaint/app}{Plug & Paint} example for details.
+ \a ClassName, in a header file.
If you want to use Q_DECLARE_INTERFACE with interface classes
declared in a namespace then you have to make sure the Q_DECLARE_INTERFACE
@@ -76,8 +50,6 @@
\snippet code/doc_src_qplugin.cpp 1
- See the \l{tools/plugandpaint/app}{Plug & Paint} example for details.
-
Note that the class this macro appears on must be default-constructible.
FILE is optional and points to a json file.
@@ -105,11 +77,9 @@
\snippet code/doc_src_qplugin.cpp 2
Static plugins must also be included by the linker when your
- application is built. For Qt's predefined plugins,
- you can use the \c QTPLUGIN to add
- the required plugins to your build. For example:
+ application is built. See \l{Static Plugins} for more information
+ on this.
- \snippet code/doc_src_qplugin.pro 3
- \sa {Static Plugins}, {How to Create Qt Plugins}, {qmake-getting-started}{Getting Started with qmake}
+ \sa {Static Plugins}, {How to Create Qt Plugins}
*/
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
index ce45ebf700..534ca569df 100644
--- a/src/corelib/plugin/qplugin_p.h
+++ b/src/corelib/plugin/qplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLUGIN_P_H
#define QPLUGIN_P_H
@@ -61,7 +25,8 @@ enum class QtPluginMetaDataKeys {
IID,
ClassName,
MetaData,
- URI
+ URI,
+ IsDebug,
};
// F(IntKey, StringKey, Description)
@@ -70,7 +35,63 @@ enum class QtPluginMetaDataKeys {
F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
- F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI")
+ F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI") \
+ /* not output by moc in CBOR */ \
+ F(QtPluginMetaDataKeys::QtVersion, "version", "Qt version") \
+ F(QtPluginMetaDataKeys::Requirements, "archlevel", "Architectural level") \
+ F(QtPluginMetaDataKeys::IsDebug, "debug", "Debug-mode plugin") \
+ /**/
+
+namespace {
+struct DecodedArchRequirements
+{
+ quint8 level;
+ bool isDebug;
+ friend constexpr bool operator==(DecodedArchRequirements r1, DecodedArchRequirements r2)
+ {
+ return r1.level == r2.level && r1.isDebug == r2.isDebug;
+ }
+};
+
+static constexpr DecodedArchRequirements decodeVersion0ArchRequirements(quint8 value)
+{
+ // see qPluginArchRequirements() and QPluginMetaDataV2::archRequirements()
+ DecodedArchRequirements r = {};
+#ifdef Q_PROCESSOR_X86
+ if (value & 4)
+ r.level = 4; // AVX512F -> x86-64-v4
+ else if (value & 2)
+ r.level = 3; // AVX2 -> x86-64-v3
+#endif
+ if (value & 1)
+ r.isDebug = true;
+ return r;
+}
+// self checks
+static_assert(decodeVersion0ArchRequirements(0) == DecodedArchRequirements{ 0, false });
+static_assert(decodeVersion0ArchRequirements(1) == DecodedArchRequirements{ 0, true });
+#ifdef Q_PROCESSOR_X86
+static_assert(decodeVersion0ArchRequirements(2) == DecodedArchRequirements{ 3, false });
+static_assert(decodeVersion0ArchRequirements(3) == DecodedArchRequirements{ 3, true });
+static_assert(decodeVersion0ArchRequirements(4) == DecodedArchRequirements{ 4, false });
+static_assert(decodeVersion0ArchRequirements(5) == DecodedArchRequirements{ 4, true });
+#endif
+
+static constexpr DecodedArchRequirements decodeVersion1ArchRequirements(quint8 value)
+{
+ return { quint8(value & 0x7f), bool(value & 0x80) };
+}
+// self checks
+static_assert(decodeVersion1ArchRequirements(0) == DecodedArchRequirements{ 0, false });
+static_assert(decodeVersion1ArchRequirements(0x80) == DecodedArchRequirements{ 0, true });
+#ifdef Q_PROCESSOR_X86
+static_assert(decodeVersion1ArchRequirements(1) == DecodedArchRequirements{ 1, false });
+static_assert(decodeVersion1ArchRequirements(3) == DecodedArchRequirements{ 3, false});
+static_assert(decodeVersion1ArchRequirements(4) == DecodedArchRequirements{ 4, false });
+static_assert(decodeVersion1ArchRequirements(0x82) == DecodedArchRequirements{ 2, true });
+static_assert(decodeVersion1ArchRequirements(0x84) == DecodedArchRequirements{ 4, true });
+#endif
+} // unnamed namespace
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index b8de3690d9..03b8cfbb84 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -1,55 +1,24 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-
-#include "qplugin.h"
-#include "qcoreapplication.h"
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
#include "qpluginloader.h"
-#include <qfileinfo.h>
-#include "qfactoryloader_p.h"
+
+#include "qcoreapplication.h"
#include "qdebug.h"
#include "qdir.h"
+#include "qfactoryloader_p.h"
+#include "qfileinfo.h"
+#include "qjsondocument.h"
+
+#if QT_CONFIG(library)
+# include "qlibrary_p.h"
+#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if QT_CONFIG(library)
/*!
@@ -102,35 +71,10 @@ QT_BEGIN_NAMESPACE
link to plugins statically. You can use QLibrary if you need to
load dynamic libraries in a statically linked application.
- \sa QLibrary, {Plug & Paint Example}
-*/
-
-/*!
- \class QStaticPlugin
- \inmodule QtCore
- \since 5.2
-
- \brief QStaticPlugin is a struct containing a reference to a
- static plugin instance together with its meta data.
-
- \sa QPluginLoader, {How to Create Qt Plugins}
+ \sa QLibrary
*/
-/*!
- \fn QObject *QStaticPlugin::instance()
-
- Returns the plugin instance.
-
- \sa QPluginLoader::staticInstances()
-*/
-
-/*!
- \fn const char *QStaticPlugin::rawMetaData()
-
- Returns the raw meta data for the plugin.
-
- \sa metaData(), Q_PLUGIN_METADATA()
-*/
+static constexpr QLibrary::LoadHints defaultLoadHints = QLibrary::PreventUnloadHint;
/*!
Constructs a plugin loader with the given \a parent.
@@ -155,7 +99,7 @@ QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)
: QObject(parent), d(nullptr), did_load(false)
{
setFileName(fileName);
- setLoadHints(QLibrary::PreventUnloadHint);
+ setLoadHints(defaultLoadHints);
}
/*!
@@ -213,7 +157,7 @@ QJsonObject QPluginLoader::metaData() const
{
if (!d)
return QJsonObject();
- return d->metaData;
+ return d->metaData.toJson();
}
/*!
@@ -238,7 +182,6 @@ bool QPluginLoader::load()
return d->loadPlugin();
}
-
/*!
Unloads the plugin and returns \c true if the plugin could be
unloaded; otherwise returns \c false.
@@ -261,7 +204,7 @@ bool QPluginLoader::unload()
did_load = false;
return d->unload();
}
- if (d) // Ouch
+ if (d) // Ouch
d->errorString = tr("The plugin was not loaded.");
return false;
}
@@ -292,12 +235,10 @@ static QString locatePlugin(const QString& fileName)
suffixes.prepend(QString());
// Split up "subdir/filename"
- const int slash = fileName.lastIndexOf(QLatin1Char('/'));
+ const qsizetype slash = fileName.lastIndexOf(u'/');
const auto baseName = QStringView{fileName}.mid(slash + 1);
const auto basePath = isAbsolute ? QStringView() : QStringView{fileName}.left(slash + 1); // keep the '/'
- const bool debug = qt_debug_component();
-
QStringList paths;
if (isAbsolute) {
paths.append(fileName.left(slash)); // don't include the '/'
@@ -305,29 +246,26 @@ static QString locatePlugin(const QString& fileName)
paths = QCoreApplication::libraryPaths();
}
- for (const QString &path : qAsConst(paths)) {
- for (const QString &prefix : qAsConst(prefixes)) {
- for (const QString &suffix : qAsConst(suffixes)) {
+ for (const QString &path : std::as_const(paths)) {
+ for (const QString &prefix : std::as_const(prefixes)) {
+ for (const QString &suffix : std::as_const(suffixes)) {
#ifdef Q_OS_ANDROID
{
QString pluginPath = basePath + prefix + baseName + suffix;
- const QString fn = path + QLatin1String("/lib") + pluginPath.replace(QLatin1Char('/'), QLatin1Char('_'));
- if (debug)
- qDebug() << "Trying..." << fn;
+ const QString fn = path + "/lib"_L1 + pluginPath.replace(u'/', u'_');
+ qCDebug(qt_lcDebugPlugins) << "Trying..." << fn;
if (QFileInfo(fn).isFile())
return fn;
}
#endif
- const QString fn = path + QLatin1Char('/') + basePath + prefix + baseName + suffix;
- if (debug)
- qDebug() << "Trying..." << fn;
+ const QString fn = path + u'/' + basePath + prefix + baseName + suffix;
+ qCDebug(qt_lcDebugPlugins) << "Trying..." << fn;
if (QFileInfo(fn).isFile())
return fn;
}
}
}
- if (debug)
- qDebug() << fileName << "not found";
+ qCDebug(qt_lcDebugPlugins) << fileName << "not found";
return QString();
}
#endif
@@ -357,7 +295,7 @@ static QString locatePlugin(const QString& fileName)
void QPluginLoader::setFileName(const QString &fileName)
{
#if defined(QT_SHARED)
- QLibrary::LoadHints lh = QLibrary::PreventUnloadHint;
+ QLibrary::LoadHints lh = defaultLoadHints;
if (d) {
lh = d->loadHints();
d->release();
@@ -372,11 +310,8 @@ void QPluginLoader::setFileName(const QString &fileName)
d->updatePluginState();
#else
- if (qt_debug_component()) {
- qWarning("Cannot load %s into a statically linked Qt library.",
- (const char*)QFile::encodeName(fileName));
- }
- Q_UNUSED(fileName);
+ qCWarning(qt_lcDebugPlugins, "Cannot load '%ls' into a statically linked Qt library.",
+ qUtf16Printable(fileName));
#endif
}
@@ -414,15 +349,21 @@ QString QPluginLoader::errorString() const
void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)
{
if (!d) {
- d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ d = QLibraryPrivate::findOrCreate({}, {}, loadHints); // ugly, but we need a d-ptr
d->errorString.clear();
+ } else {
+ d->setLoadHints(loadHints);
}
- d->setLoadHints(loadHints);
}
QLibrary::LoadHints QPluginLoader::loadHints() const
{
- return d ? d->loadHints() : QLibrary::LoadHints();
+ // Not having a d-pointer means that the user hasn't called
+ // setLoadHints() / setFileName() yet. In setFileName() we will
+ // then force defaultLoadHints on loading, so we must return them
+ // from here as well.
+
+ return d ? d->loadHints() : defaultLoadHints;
}
#endif // QT_CONFIG(library)
@@ -439,7 +380,19 @@ Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)
*/
void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin plugin)
{
- staticPluginList()->append(plugin);
+ // using operator* because we shouldn't be registering plugins while
+ // unloading the application!
+ StaticPluginList &plugins = *staticPluginList;
+
+ // insert the plugin in the list, sorted by address, so we can detect
+ // duplicate registrations
+ auto comparator = [=](const QStaticPlugin &p1, const QStaticPlugin &p2) {
+ using Less = std::less<decltype(plugin.instance)>;
+ return Less{}(p1.instance, p2.instance);
+ };
+ auto pos = std::lower_bound(plugins.constBegin(), plugins.constEnd(), plugin, comparator);
+ if (pos == plugins.constEnd() || pos->instance != plugin.instance)
+ plugins.insert(pos, plugin);
}
/*!
@@ -450,12 +403,11 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin plugin)
QObjectList QPluginLoader::staticInstances()
{
QObjectList instances;
- const StaticPluginList *plugins = staticPluginList();
- if (plugins) {
- const int numPlugins = plugins->size();
- instances.reserve(numPlugins);
- for (int i = 0; i < numPlugins; ++i)
- instances += plugins->at(i).instance();
+ if (staticPluginList.exists()) {
+ const StaticPluginList &plugins = *staticPluginList;
+ instances.reserve(plugins.size());
+ for (QStaticPlugin plugin : plugins)
+ instances += plugin.instance();
}
return instances;
}
@@ -476,25 +428,40 @@ QList<QStaticPlugin> QPluginLoader::staticPlugins()
}
/*!
+ \class QStaticPlugin
+ \inmodule QtCore
+ \since 5.2
+
+ \brief QStaticPlugin is a struct containing a reference to a
+ static plugin instance together with its meta data.
+
+ \sa QPluginLoader, {How to Create Qt Plugins}
+*/
+
+/*!
+ \fn QStaticPlugin::QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m)
+ \internal
+*/
+
+/*!
+ \variable QStaticPlugin::instance
+
+ Holds the plugin instance.
+
+ \sa QPluginLoader::staticInstances()
+*/
+
+/*!
Returns a the meta data for the plugin as a QJsonObject.
- \sa rawMetaData()
+ \sa Q_PLUGIN_METADATA()
*/
QJsonObject QStaticPlugin::metaData() const
{
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- // the data is already loaded, so this doesn't matter
- qsizetype rawMetaDataSize = INT_MAX;
- const char *ptr = rawMetaData();
-#else
- auto ptr = static_cast<const char *>(rawMetaData);
-#endif
-
- QString errMsg;
- QJsonDocument doc = qJsonFromRawLibraryMetaData(ptr, rawMetaDataSize, &errMsg);
- Q_ASSERT(doc.isObject());
- Q_ASSERT(errMsg.isEmpty());
- return doc.object();
+ QByteArrayView data(static_cast<const char *>(rawMetaData), rawMetaDataSize);
+ QPluginParsedMetaData parsed(data);
+ Q_ASSERT(!parsed.isError());
+ return parsed.toJson();
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qpluginloader.h b/src/corelib/plugin/qpluginloader.h
index 81b78aa532..e541994e62 100644
--- a/src/corelib/plugin/qpluginloader.h
+++ b/src/corelib/plugin/qpluginloader.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLUGINLOADER_H
#define QPLUGINLOADER_H
@@ -100,4 +64,4 @@ public:
QT_END_NAMESPACE
-#endif //QPLUGINLOADER_H
+#endif // QPLUGINLOADER_H
diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp
index fe6760c8d8..d3dff226d9 100644
--- a/src/corelib/plugin/qsystemlibrary.cpp
+++ b/src/corelib/plugin/qsystemlibrary.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsystemlibrary_p.h"
#include <QtCore/qvarlengtharray.h>
@@ -72,53 +36,56 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if !defined(QT_BOOTSTRAPPED)
extern QString qAppFileName();
#endif
static QString qSystemDirectory()
{
- QVarLengthArray<wchar_t, MAX_PATH> fullPath;
-
- UINT retLen = ::GetSystemDirectory(fullPath.data(), MAX_PATH);
- if (retLen > MAX_PATH) {
- fullPath.resize(retLen);
- retLen = ::GetSystemDirectory(fullPath.data(), retLen);
- }
- // in some rare cases retLen might be 0
- return QString::fromWCharArray(fullPath.constData(), int(retLen));
+ static const QString result = []() -> QString {
+ QVarLengthArray<wchar_t, MAX_PATH> fullPath = {};
+ UINT retLen = ::GetSystemDirectoryW(fullPath.data(), MAX_PATH);
+ if (retLen > MAX_PATH) {
+ fullPath.resize(retLen);
+ retLen = ::GetSystemDirectoryW(fullPath.data(), retLen);
+ }
+ // in some rare cases retLen might be 0
+ return QString::fromWCharArray(fullPath.constData(), int(retLen));
+ }();
+ return result;
}
HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory /* = true */)
{
+ if (onlySystemDirectory)
+ return ::LoadLibraryExW(libraryName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+
QStringList searchOrder;
#if !defined(QT_BOOTSTRAPPED)
- if (!onlySystemDirectory)
- searchOrder << QFileInfo(qAppFileName()).path();
+ searchOrder << QFileInfo(qAppFileName()).path();
#endif
searchOrder << qSystemDirectory();
- if (!onlySystemDirectory) {
- const QString PATH(QLatin1String(qgetenv("PATH").constData()));
- searchOrder << PATH.split(QLatin1Char(';'), Qt::SkipEmptyParts);
- }
- QString fileName = QString::fromWCharArray(libraryName);
- fileName.append(QLatin1String(".dll"));
+ const QString PATH(QLatin1StringView(qgetenv("PATH")));
+ searchOrder << PATH.split(u';', Qt::SkipEmptyParts);
+
+ const QString fileName = QString::fromWCharArray(libraryName);
// Start looking in the order specified
for (int i = 0; i < searchOrder.count(); ++i) {
QString fullPathAttempt = searchOrder.at(i);
- if (!fullPathAttempt.endsWith(QLatin1Char('\\'))) {
- fullPathAttempt.append(QLatin1Char('\\'));
+ if (!fullPathAttempt.endsWith(u'\\')) {
+ fullPathAttempt.append(u'\\');
}
fullPathAttempt.append(fileName);
HINSTANCE inst = ::LoadLibrary(reinterpret_cast<const wchar_t *>(fullPathAttempt.utf16()));
- if (inst != 0)
+ if (inst != nullptr)
return inst;
}
- return 0;
-
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h
index 4e093c0b7c..0b4ad7dbc2 100644
--- a/src/corelib/plugin/qsystemlibrary_p.h
+++ b/src/corelib/plugin/qsystemlibrary_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSYSTEMLIBRARY_P_H
#define QSYSTEMLIBRARY_P_H
@@ -64,27 +28,23 @@ public:
explicit QSystemLibrary(const QString &libraryName)
{
m_libraryName = libraryName;
- m_handle = 0;
- m_didLoad = false;
}
explicit QSystemLibrary(const wchar_t *libraryName)
{
m_libraryName = QString::fromWCharArray(libraryName);
- m_handle = 0;
- m_didLoad = false;
}
bool load(bool onlySystemDirectory = true)
{
m_handle = load((const wchar_t *)m_libraryName.utf16(), onlySystemDirectory);
m_didLoad = true;
- return (m_handle != 0);
+ return (m_handle != nullptr);
}
bool isLoaded()
{
- return (m_handle != 0);
+ return (m_handle != nullptr);
}
QFunctionPointer resolve(const char *symbol)
@@ -92,7 +52,7 @@ public:
if (!m_didLoad)
load();
if (!m_handle)
- return 0;
+ return nullptr;
return QFunctionPointer(GetProcAddress(m_handle, symbol));
}
@@ -102,14 +62,15 @@ public:
}
static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true);
+
private:
- HINSTANCE m_handle;
- QString m_libraryName;
- bool m_didLoad;
+ HINSTANCE m_handle = nullptr;
+ QString m_libraryName = {};
+ bool m_didLoad = false;
};
QT_END_NAMESPACE
-#endif //Q_OS_WIN
+#endif // Q_OS_WIN
-#endif //QSYSTEMLIBRARY_P_H
+#endif // QSYSTEMLIBRARY_P_H
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index fc70ca1386..9c7216c3c5 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "quuid.h"
@@ -49,6 +13,9 @@
QT_BEGIN_NAMESPACE
+// ensure QList of this is efficient
+static_assert(QTypeInfo<QUuid::Id128Bytes>::isRelocatable);
+
// 16 bytes (a uint, two shorts and a uchar[8]), each represented by two hex
// digits; plus four dashes and a pair of enclosing brace: 16*2 + 4 + 2 = 38.
enum { MaxStringUuidLength = 38 };
@@ -58,7 +25,7 @@ void _q_toHex(char *&dst, Integral value)
{
value = qToBigEndian(value);
- const char* p = reinterpret_cast<const char*>(&value);
+ const char *p = reinterpret_cast<const char *>(&value);
for (uint i = 0; i < sizeof(Integral); ++i, dst += 2) {
dst[0] = QtMiscUtils::toHexLower((p[i] >> 4) & 0xf);
@@ -151,16 +118,12 @@ static QUuid _q_uuidFromHex(const char *src)
static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version)
{
- QByteArray hashResult;
-
- // create a scope so later resize won't reallocate
- {
- QCryptographicHash hash(algorithm);
- hash.addData(ns.toRfc4122());
- hash.addData(baseData);
- hashResult = hash.result();
- }
- hashResult.resize(16); // Sha1 will be too long
+ QCryptographicHash hash(algorithm);
+ hash.addData(ns.toRfc4122());
+ hash.addData(baseData);
+ QByteArrayView hashResult = hash.resultView();
+ Q_ASSERT(hashResult.size() >= 16);
+ hashResult.truncate(16); // Sha1 will be too long
QUuid result = QUuid::fromRfc4122(hashResult);
@@ -290,7 +253,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
\endtable
The field layouts for the DCE versions listed in the table above
- are specified in the \l{http://www.ietf.org/rfc/rfc4122.txt}
+ are specified in the \l{RFC 4122}
{Network Working Group UUID Specification}.
Most platforms provide a tool for generating new UUIDs, e.g. \c
@@ -327,6 +290,125 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
*/
/*!
+ \class QUuid::Id128Bytes
+ \inmodule QtCore
+ \since 6.6
+
+ This trivial structure is 128 bits (16 bytes) in size and holds the binary
+ representation of a UUID. Applications can \c{memcpy()} its contents to and
+ from many other libraries' UUID or GUID structures that take 128-bit
+ values.
+*/
+
+/*!
+ \fn QUuid::Id128Bytes qFromBigEndian(QUuid::Id128Bytes src)
+ \since 6.6
+ \relates QUuid::Id128Bytes
+ \overload
+
+ Converts \a src from big-endian byte order and returns the struct holding
+ the binary representation of UUID in host byte order.
+
+ \sa <QtEndian>
+*/
+
+/*!
+ \fn QUuid::Id128Bytes qFromLittleEndian(QUuid::Id128Bytes src)
+ \since 6.6
+ \relates QUuid::Id128Bytes
+ \overload
+
+ Converts \a src from little-endian byte order and returns the struct holding
+ the binary representation of UUID in host byte order.
+
+ \sa <QtEndian>
+*/
+
+/*!
+ \fn QUuid::Id128Bytes qToBigEndian(QUuid::Id128Bytes src)
+ \since 6.6
+ \relates QUuid::Id128Bytes
+ \overload
+
+ Converts \a src from host byte order and returns the struct holding the
+ binary representation of UUID in big-endian byte order.
+
+ \sa <QtEndian>
+*/
+
+/*!
+ \fn QUuid::Id128Bytes qToLittleEndian(QUuid::Id128Bytes src)
+ \since 6.6
+ \relates QUuid::Id128Bytes
+ \overload
+
+ Converts \a src from host byte order and returns the struct holding the
+ binary representation of UUID in little-endian byte order.
+
+ \sa <QtEndian>
+*/
+
+/*!
+ \fn QUuid::QUuid(Id128Bytes id128, QSysInfo::Endian order) noexcept
+ \since 6.6
+
+ Creates a QUuid based on the integral \a id128 parameter. The input
+ \a id128 parameter is considered to have byte order \a order.
+
+ \sa fromBytes(), toBytes(), toRfc4122(), toUInt128()
+*/
+
+/*!
+ \fn QUuid::fromUInt128(quint128 uuid, QSysInfo::Endian order) noexcept
+ \since 6.6
+
+ Creates a QUuid based on the integral \a uuid parameter. The input \a uuid
+ parameter is considered to have byte order \a order.
+
+ \note This function is only present on platforms that offer a 128-bit
+ integer type.
+
+ \sa toUInt128(), fromBytes(), toBytes(), toRfc4122()
+*/
+
+/*!
+ \fn quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
+ \since 6.6
+
+ Returns a 128-bit integer created from this QUuid on the byte order
+ specified by \a order. The binary content of this function is the same as
+ toRfc4122() if the order is QSysInfo::BigEndian. See that function for more
+ details.
+
+ \note This function is only present on platforms that offer a 128-bit
+ integer type.
+
+ \sa toRfc4122(), fromUInt128(), toBytes(), fromBytes(), QUuid()
+*/
+
+/*!
+ \fn QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept
+ \since 6.6
+
+ Returns a 128-bit ID created from this QUuid on the byte order specified
+ by \a order. The binary content of this function is the same as toRfc4122()
+ if the order is QSysInfo::BigEndian. See that function for more details.
+
+ \sa toRfc4122(), fromBytes(), QUuid()
+*/
+
+/*!
+ \fn QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcept
+ \since 6.6
+
+ Reads 128 bits (16 bytes) from \a bytes using byte order \a order and
+ returns the QUuid corresponding to those bytes. This function does the same
+ as fromRfc4122() if the byte order \a order is QSysInfo::BigEndian.
+
+ \sa fromRfc4122()
+*/
+
+/*!
\fn QUuid::QUuid(const GUID &guid)
Casts a Windows \a guid to a Qt QUuid.
@@ -369,6 +451,8 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
*/
/*!
+ \fn QUuid::QUuid(QAnyStringView text)
+
Creates a QUuid object from the string \a text, which must be
formatted as five hex fields separated by '-', e.g.,
"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
@@ -377,17 +461,18 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
toString() for an explanation of how the five hex fields map to the
public data members in QUuid.
+ \note In Qt versions prior to 6.3, this constructor was an overload
+ set consisting of QString, QByteArray and \c{const char*}
+ instead of one constructor taking QAnyStringView.
+
\sa toString(), QUuid()
*/
-QUuid::QUuid(const QString &text)
- : QUuid(fromString(text))
-{
-}
/*!
+ \fn static QUuid::fromString(QAnyStringView string)
\since 5.10
- Creates a QUuid object from the string \a text, which must be
+ Creates a QUuid object from the string \a string, which must be
formatted as five hex fields separated by '-', e.g.,
"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
digit. The curly braces shown here are optional, but it is normal to
@@ -395,12 +480,16 @@ QUuid::QUuid(const QString &text)
toString() for an explanation of how the five hex fields map to the
public data members in QUuid.
+ \note In Qt versions prior to 6.3, this function was an overload
+ set consisting of QStringView and QLatin1StringView instead of
+ one function taking QAnyStringView.
+
\sa toString(), QUuid()
*/
-QUuid QUuid::fromString(QStringView text) noexcept
+static QUuid uuidFromString(QStringView text) noexcept
{
if (text.size() > MaxStringUuidLength)
- text = text.left(MaxStringUuidLength); // text.truncate(MaxStringUuidLength);
+ text.truncate(MaxStringUuidLength);
char latin1[MaxStringUuidLength + 1];
char *dst = latin1;
@@ -413,55 +502,27 @@ QUuid QUuid::fromString(QStringView text) noexcept
return _q_uuidFromHex(latin1);
}
-/*!
- \since 5.10
- \overload
-
- Creates a QUuid object from the string \a text, which must be
- formatted as five hex fields separated by '-', e.g.,
- "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
- digit. The curly braces shown here are optional, but it is normal to
- include them. If the conversion fails, a null UUID is returned. See
- toString() for an explanation of how the five hex fields map to the
- public data members in QUuid.
-
- \sa toString(), QUuid()
-*/
-QUuid QUuid::fromString(QLatin1String text) noexcept
+static QUuid uuidFromString(QLatin1StringView text) noexcept
{
if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2
- || (text.front() == QLatin1Char('{') && text.size() < MaxStringUuidLength - 1))) {
+ || (text.front() == '{' && text.size() < MaxStringUuidLength - 1))) {
// Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
// and we don't want to read trailing garbage as potentially valid data.
- text = QLatin1String();
+ text = QLatin1StringView();
}
return _q_uuidFromHex(text.data());
}
-/*!
- \internal
-*/
-QUuid::QUuid(const char *text)
- : QUuid(_q_uuidFromHex(text))
+Q_ALWAYS_INLINE
+// can treat UTF-8 the same as Latin-1:
+static QUuid uuidFromString(QUtf8StringView text) noexcept
{
+ return uuidFromString(QLatin1StringView(text.data(), text.size()));
}
-/*!
- Creates a QUuid object from the QByteArray \a text, which must be
- formatted as five hex fields separated by '-', e.g.,
- "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
- digit. The curly braces shown here are optional, but it is normal to
- include them. If the conversion fails, a null UUID is created. See
- toByteArray() for an explanation of how the five hex fields map to the
- public data members in QUuid.
-
- \since 4.8
-
- \sa toByteArray(), QUuid()
-*/
-QUuid::QUuid(const QByteArray &text)
- : QUuid(fromString(QLatin1String(text.data(), text.size())))
+QUuid QUuid::fromString(QAnyStringView text) noexcept
{
+ return text.visit([] (auto text) { return uuidFromString(text); });
}
/*!
@@ -524,34 +585,18 @@ QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData)
If the conversion fails, a null UUID is created.
+ \note In Qt versions prior to 6.3, this function took QByteArray, not
+ QByteArrayView.
+
\since 4.8
- \sa toRfc4122(), QUuid()
+ \sa toRfc4122(), QUuid(), fromBytes()
*/
-QUuid QUuid::fromRfc4122(const QByteArray &bytes)
+QUuid QUuid::fromRfc4122(QByteArrayView bytes) noexcept
{
- if (bytes.isEmpty() || bytes.length() != 16)
+ if (bytes.isEmpty() || bytes.size() != 16)
return QUuid();
-
- uint d1;
- ushort d2, d3;
- uchar d4[8];
-
- const uchar *data = reinterpret_cast<const uchar *>(bytes.constData());
-
- d1 = qFromBigEndian<quint32>(data);
- data += sizeof(quint32);
- d2 = qFromBigEndian<quint16>(data);
- data += sizeof(quint16);
- d3 = qFromBigEndian<quint16>(data);
- data += sizeof(quint16);
-
- for (int i = 0; i < 8; ++i) {
- d4[i] = *(data);
- data++;
- }
-
- return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
+ return fromBytes(bytes.data());
}
/*!
@@ -569,49 +614,6 @@ QUuid QUuid::fromRfc4122(const QByteArray &bytes)
*/
/*!
- Returns the string representation of this QUuid. The string is
- formatted as five hex fields separated by '-' and enclosed in
- curly braces, i.e., "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where
- 'x' is a hex digit. From left to right, the five hex fields are
- obtained from the four public data members in QUuid as follows:
-
- \table
- \header
- \li Field #
- \li Source
-
- \row
- \li 1
- \li data1
-
- \row
- \li 2
- \li data2
-
- \row
- \li 3
- \li data3
-
- \row
- \li 4
- \li data4[0] .. data4[1]
-
- \row
- \li 5
- \li data4[2] .. data4[7]
-
- \endtable
-*/
-QString QUuid::toString() const
-{
- char latin1[MaxStringUuidLength];
- const auto end = _q_uuidToHex(*this, latin1);
- Q_ASSERT(end - latin1 == MaxStringUuidLength);
- Q_UNUSED(end);
- return QString::fromLatin1(latin1, MaxStringUuidLength);
-}
-
-/*!
\since 5.11
Returns the string representation of this QUuid, with the formattiong
@@ -653,51 +655,6 @@ QString QUuid::toString(QUuid::StringFormat mode) const
}
/*!
- Returns the binary representation of this QUuid. The byte array is
- formatted as five hex fields separated by '-' and enclosed in
- curly braces, i.e., "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where
- 'x' is a hex digit. From left to right, the five hex fields are
- obtained from the four public data members in QUuid as follows:
-
- \table
- \header
- \li Field #
- \li Source
-
- \row
- \li 1
- \li data1
-
- \row
- \li 2
- \li data2
-
- \row
- \li 3
- \li data3
-
- \row
- \li 4
- \li data4[0] .. data4[1]
-
- \row
- \li 5
- \li data4[2] .. data4[7]
-
- \endtable
-
- \since 4.8
-*/
-QByteArray QUuid::toByteArray() const
-{
- QByteArray result(MaxStringUuidLength, Qt::Uninitialized);
- const auto end = _q_uuidToHex(*this, const_cast<char*>(result.constData()));
- Q_ASSERT(end - result.constData() == MaxStringUuidLength);
- Q_UNUSED(end);
- return result;
-}
-
-/*!
\since 5.11
Returns the string representation of this QUuid, with the formattiong
@@ -734,7 +691,7 @@ QByteArray QUuid::toByteArray() const
QByteArray QUuid::toByteArray(QUuid::StringFormat mode) const
{
QByteArray result(MaxStringUuidLength, Qt::Uninitialized);
- const auto end = _q_uuidToHex(*this, const_cast<char*>(result.constData()), mode);
+ const auto end = _q_uuidToHex(*this, const_cast<char *>(result.constData()), mode);
result.resize(end - result.constData());
return result;
}
@@ -769,27 +726,16 @@ QByteArray QUuid::toByteArray(QUuid::StringFormat mode) const
\endtable
+ The bytes in the byte array returned by this function contains the same
+ binary content as toBytes().
+
+ \sa toBytes()
\since 4.8
*/
QByteArray QUuid::toRfc4122() const
{
- // we know how many bytes a UUID has, I hope :)
- QByteArray bytes(16, Qt::Uninitialized);
- uchar *data = reinterpret_cast<uchar*>(bytes.data());
-
- qToBigEndian(data1, data);
- data += sizeof(quint32);
- qToBigEndian(data2, data);
- data += sizeof(quint16);
- qToBigEndian(data3, data);
- data += sizeof(quint16);
-
- for (int i = 0; i < 8; ++i) {
- *(data) = data4[i];
- data++;
- }
-
- return bytes;
+ Id128Bytes bytes = toBytes();
+ return QByteArrayView(bytes).toByteArray();
}
#ifndef QT_NO_DATASTREAM
@@ -799,14 +745,19 @@ QByteArray QUuid::toRfc4122() const
*/
QDataStream &operator<<(QDataStream &s, const QUuid &id)
{
- QByteArray bytes;
+ constexpr int NumBytes = sizeof(QUuid);
+ static_assert(NumBytes == 16, "Change the serialization format when this ever hits");
+ char bytes[NumBytes];
if (s.byteOrder() == QDataStream::BigEndian) {
- bytes = id.toRfc4122();
+ const auto id128 = id.toBytes();
+ static_assert(sizeof(id128) == NumBytes);
+ memcpy(bytes, &id128, NumBytes);
} else {
- // we know how many bytes a UUID has, I hope :)
- bytes = QByteArray(16, Qt::Uninitialized);
- uchar *data = reinterpret_cast<uchar*>(bytes.data());
+ auto *data = bytes;
+ // for historical reasons, our little-endian serialization format
+ // stores each of the UUID fields in little endian, instead of storing
+ // a little endian Id128
qToLittleEndian(id.data1, data);
data += sizeof(quint32);
qToLittleEndian(id.data2, data);
@@ -820,9 +771,9 @@ QDataStream &operator<<(QDataStream &s, const QUuid &id)
}
}
- if (s.writeRawData(bytes.data(), 16) != 16) {
+ if (s.writeRawData(bytes, NumBytes) != NumBytes)
s.setStatus(QDataStream::WriteFailed);
- }
+
return s;
}
@@ -832,7 +783,7 @@ QDataStream &operator<<(QDataStream &s, const QUuid &id)
*/
QDataStream &operator>>(QDataStream &s, QUuid &id)
{
- QByteArray bytes(16, Qt::Uninitialized);
+ std::array<char, 16> bytes;
if (s.readRawData(bytes.data(), 16) != 16) {
s.setStatus(QDataStream::ReadPastEnd);
return s;
@@ -841,7 +792,7 @@ QDataStream &operator>>(QDataStream &s, QUuid &id)
if (s.byteOrder() == QDataStream::BigEndian) {
id = QUuid::fromRfc4122(bytes);
} else {
- const uchar *data = reinterpret_cast<const uchar *>(bytes.constData());
+ const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
id.data1 = qFromLittleEndian<quint32>(data);
data += sizeof(quint32);
@@ -1041,7 +992,7 @@ QUuid QUuid::createUuid()
return result;
}
-#else // Q_OS_WIN
+#elif !defined(QT_BOOTSTRAPPED)
QUuid QUuid::createUuid()
{
@@ -1055,7 +1006,7 @@ QUuid QUuid::createUuid()
return result;
}
-#endif // !Q_OS_WIN
+#endif // !Q_OS_WIN && !QT_BOOTSTRAPPED
/*!
\fn bool QUuid::operator==(const GUID &guid) const
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
index bdd74f4b77..7125e8e2cc 100644
--- a/src/corelib/plugin/quuid.h
+++ b/src/corelib/plugin/quuid.h
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QUUID_H
#define QUUID_H
+#include <QtCore/qendian.h>
#include <QtCore/qstring.h>
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
@@ -55,14 +20,13 @@ typedef struct _GUID
#endif
#endif
-#if defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
Q_FORWARD_DECLARE_CF_TYPE(CFUUID);
Q_FORWARD_DECLARE_OBJC_CLASS(NSUUID);
#endif
QT_BEGIN_NAMESPACE
-
class Q_CORE_EXPORT QUuid
{
QUuid(Qt::Initialization) {}
@@ -91,52 +55,74 @@ public:
Id128 = 3
};
-#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_CLANG_QDOC)
+ union alignas(16) Id128Bytes {
+ quint8 data[16];
+ quint16 data16[8];
+ quint32 data32[4];
+ quint64 data64[2];
+#if defined(__SIZEOF_INT128__)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wpedantic") // ISO C++ does not support ‘__int128’ for ‘data128’
+ unsigned __int128 data128[1];
+QT_WARNING_POP
+#elif defined(QT_SUPPORTS_INT128)
+# error "struct QUuid::Id128Bytes should not depend on QT_SUPPORTS_INT128 for ABI reasons."
+# error "Adjust the declaration of the `data128` member above so it is always defined if it's " \
+ "supported by the current compiler/architecture in any configuration."
+#endif
+
+ constexpr explicit operator QByteArrayView() const noexcept
+ {
+ return QByteArrayView(data, sizeof(data));
+ }
+
+ friend constexpr Id128Bytes qbswap(Id128Bytes b) noexcept
+ {
+ // 128-bit byte swap
+ auto b0 = qbswap(b.data64[0]);
+ auto b1 = qbswap(b.data64[1]);
+ b.data64[0] = b1;
+ b.data64[1] = b0;
+ return b;
+ }
+ };
- Q_DECL_CONSTEXPR QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {}
+ constexpr QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {}
- Q_DECL_CONSTEXPR QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3,
+ constexpr QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3,
uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept
: data1(l), data2(w1), data3(w2), data4{b1, b2, b3, b4, b5, b6, b7, b8} {}
-#else
- QUuid() noexcept
- {
- data1 = 0;
- data2 = 0;
- data3 = 0;
- for(int i = 0; i < 8; i++)
- data4[i] = 0;
- }
- QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept
- {
- data1 = l;
- data2 = w1;
- data3 = w2;
- data4[0] = b1;
- data4[1] = b2;
- data4[2] = b3;
- data4[3] = b4;
- data4[4] = b5;
- data4[5] = b6;
- data4[6] = b7;
- data4[7] = b8;
- }
-#endif
+ explicit inline QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept;
- QUuid(const QString &);
+ explicit QUuid(QAnyStringView string) noexcept
+ : QUuid{fromString(string)} {}
+ static QUuid fromString(QAnyStringView string) noexcept;
+#if QT_CORE_REMOVED_SINCE(6, 3)
+ explicit QUuid(const QString &);
static QUuid fromString(QStringView string) noexcept;
- static QUuid fromString(QLatin1String string) noexcept;
- QUuid(const char *);
- QString toString() const;
- QString toString(StringFormat mode) const; // ### Qt6: merge with previous
- QUuid(const QByteArray &);
- QByteArray toByteArray() const;
- QByteArray toByteArray(StringFormat mode) const; // ### Qt6: merge with previous
+ static QUuid fromString(QLatin1StringView string) noexcept;
+ explicit QUuid(const char *);
+ explicit QUuid(const QByteArray &);
+#endif
+ QString toString(StringFormat mode = WithBraces) const;
+ QByteArray toByteArray(StringFormat mode = WithBraces) const;
+ inline Id128Bytes toBytes(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept;
QByteArray toRfc4122() const;
+
+ static inline QUuid fromBytes(const void *bytes, QSysInfo::Endian order = QSysInfo::BigEndian);
+#if QT_CORE_REMOVED_SINCE(6, 3)
static QUuid fromRfc4122(const QByteArray &);
+#endif
+ static QUuid fromRfc4122(QByteArrayView) noexcept;
+
bool isNull() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR bool operator==(const QUuid &orig) const noexcept
+#ifdef QT_SUPPORTS_INT128
+ static constexpr QUuid fromUInt128(quint128 uuid, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept;
+ constexpr quint128 toUInt128(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept;
+#endif
+
+ constexpr bool operator==(const QUuid &orig) const noexcept
{
if (data1 != orig.data1 || data2 != orig.data2 ||
data3 != orig.data3)
@@ -149,7 +135,7 @@ public:
return true;
}
- Q_DECL_RELAXED_CONSTEXPR bool operator!=(const QUuid &orig) const noexcept
+ constexpr bool operator!=(const QUuid &orig) const noexcept
{
return !(*this == orig);
}
@@ -157,43 +143,32 @@ public:
bool operator<(const QUuid &other) const noexcept;
bool operator>(const QUuid &other) const noexcept;
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
// On Windows we have a type GUID that is used by the platform API, so we
// provide convenience operators to cast from and to this type.
-#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_CLANG_QDOC)
- Q_DECL_CONSTEXPR QUuid(const GUID &guid) noexcept
+ constexpr QUuid(const GUID &guid) noexcept
: data1(guid.Data1), data2(guid.Data2), data3(guid.Data3),
data4{guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]} {}
-#else
- QUuid(const GUID &guid) noexcept
- {
- data1 = guid.Data1;
- data2 = guid.Data2;
- data3 = guid.Data3;
- for(int i = 0; i < 8; i++)
- data4[i] = guid.Data4[i];
- }
-#endif
- Q_DECL_RELAXED_CONSTEXPR QUuid &operator=(const GUID &guid) noexcept
+ constexpr QUuid &operator=(const GUID &guid) noexcept
{
*this = QUuid(guid);
return *this;
}
- Q_DECL_RELAXED_CONSTEXPR operator GUID() const noexcept
+ constexpr operator GUID() const noexcept
{
GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } };
return guid;
}
- Q_DECL_RELAXED_CONSTEXPR bool operator==(const GUID &guid) const noexcept
+ constexpr bool operator==(const GUID &guid) const noexcept
{
return *this == QUuid(guid);
}
- Q_DECL_RELAXED_CONSTEXPR bool operator!=(const GUID &guid) const noexcept
+ constexpr bool operator!=(const GUID &guid) const noexcept
{
return !(*this == guid);
}
@@ -215,11 +190,10 @@ public:
return QUuid::createUuidV5(ns, baseData.toUtf8());
}
-
QUuid::Variant variant() const noexcept;
QUuid::Version version() const noexcept;
-#if defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
static QUuid fromCFUUID(CFUUIDRef uuid);
CFUUIDRef toCFUUID() const Q_DECL_CF_RETURNS_RETAINED;
static QUuid fromNSUUID(const NSUUID *uuid);
@@ -245,11 +219,92 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QUuid &);
Q_CORE_EXPORT size_t qHash(const QUuid &uuid, size_t seed = 0) noexcept;
+QUuid::QUuid(Id128Bytes uuid, QSysInfo::Endian order) noexcept
+{
+ if (order == QSysInfo::LittleEndian)
+ uuid = qbswap(uuid);
+ data1 = qFromBigEndian<quint32>(&uuid.data[0]);
+ data2 = qFromBigEndian<quint16>(&uuid.data[4]);
+ data3 = qFromBigEndian<quint16>(&uuid.data[6]);
+ memcpy(data4, &uuid.data[8], sizeof(data4));
+}
+
+QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept
+{
+ Id128Bytes result = {};
+ qToBigEndian(data1, &result.data[0]);
+ qToBigEndian(data2, &result.data[4]);
+ qToBigEndian(data3, &result.data[6]);
+ memcpy(&result.data[8], data4, sizeof(data4));
+ if (order == QSysInfo::LittleEndian)
+ return qbswap(result);
+ return result;
+}
+
+QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order)
+{
+ Id128Bytes result = {};
+ memcpy(result.data, bytes, sizeof(result));
+ return QUuid(result, order);
+}
+
+#ifdef QT_SUPPORTS_INT128
+constexpr QUuid QUuid::fromUInt128(quint128 uuid, QSysInfo::Endian order) noexcept
+{
+ QUuid result = {};
+ if (order == QSysInfo::BigEndian) {
+ result.data1 = qFromBigEndian<quint32>(int(uuid));
+ result.data2 = qFromBigEndian<quint16>(ushort(uuid >> 32));
+ result.data3 = qFromBigEndian<quint16>(ushort(uuid >> 48));
+ for (int i = 0; i < 8; ++i)
+ result.data4[i] = uchar(uuid >> (64 + i * 8));
+ } else {
+ result.data1 = qFromLittleEndian<quint32>(uint(uuid >> 96));
+ result.data2 = qFromLittleEndian<quint16>(ushort(uuid >> 80));
+ result.data3 = qFromLittleEndian<quint16>(ushort(uuid >> 64));
+ for (int i = 0; i < 8; ++i)
+ result.data4[i] = uchar(uuid >> (56 - i * 8));
+ }
+ return result;
+}
+
+constexpr quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
+{
+ quint128 result = {};
+ if (order == QSysInfo::BigEndian) {
+ for (int i = 0; i < 8; ++i)
+ result |= quint64(data4[i]) << (i * 8);
+ result = result << 64;
+ result |= quint64(qToBigEndian<quint16>(data3)) << 48;
+ result |= quint64(qToBigEndian<quint16>(data2)) << 32;
+ result |= qToBigEndian<quint32>(data1);
+ } else {
+ result = qToLittleEndian<quint32>(data1);
+ result = result << 32;
+ result |= quint64(qToLittleEndian<quint16>(data2)) << 16;
+ result |= quint64(qToLittleEndian<quint16>(data3));
+ result = result << 64;
+ for (int i = 0; i < 8; ++i)
+ result |= quint64(data4[i]) << (56 - i * 8);
+ }
+ return result;
+}
+#endif
+
inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept
{ return !(rhs < lhs); }
inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept
{ return !(lhs < rhs); }
+#if defined(Q_QDOC)
+// provide fake declarations of qXXXEndian() functions, so that qDoc could
+// distinguish them from the general template
+QUuid::Id128Bytes qFromBigEndian(QUuid::Id128Bytes src);
+QUuid::Id128Bytes qFromLittleEndian(QUuid::Id128Bytes src);
+QUuid::Id128Bytes qToBigEndian(QUuid::Id128Bytes src);
+QUuid::Id128Bytes qToLittleEndian(QUuid::Id128Bytes src);
+#endif
+
QT_END_NAMESPACE
#endif // QUUID_H
diff --git a/src/corelib/qt_cmdline.cmake b/src/corelib/qt_cmdline.cmake
new file mode 100644
index 0000000000..dddb74cbaf
--- /dev/null
+++ b/src/corelib/qt_cmdline.cmake
@@ -0,0 +1,17 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_commandline_option(doubleconversion TYPE enum VALUES no qt system)
+qt_commandline_option(glib TYPE boolean)
+qt_commandline_option(icu TYPE boolean)
+qt_commandline_option(inotify TYPE boolean)
+qt_commandline_option(journald TYPE boolean)
+qt_commandline_option(libb2 TYPE enum VALUES no qt system)
+qt_commandline_option(mimetype-database TYPE boolean)
+qt_commandline_option(mimetype-database-compression TYPE optionalString VALUES zstd gzip none)
+qt_commandline_option(pcre TYPE enum VALUES no qt system)
+qt_commandline_option(posix-ipc TYPE boolean NAME ipc_posix)
+qt_commandline_option(pps TYPE boolean NAME qqnx_pps)
+qt_commandline_option(slog2 TYPE boolean)
+qt_commandline_option(syslog TYPE boolean)
+qt_commandline_option(trace TYPE optionalString VALUES etw lttng ctf no yes)
diff --git a/src/corelib/qtcore.tracepoints b/src/corelib/qtcore.tracepoints
deleted file mode 100644
index 4647b440a8..0000000000
--- a/src/corelib/qtcore.tracepoints
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-QT_BEGIN_NAMESPACE
-class QEvent;
-QT_END_NAMESPACE
-}
-
-QCoreApplicationPrivate_init_entry()
-QCoreApplicationPrivate_init_exit()
-
-QFactoryLoader_update(const QString &fileName)
-
-QLibraryPrivate_load_entry(const QString &fileName)
-QLibraryPrivate_load_exit(bool success)
-
-QEvent_ctor(QEvent *event, int type)
-QEvent_dtor(QEvent *event, int type)
-
-QCoreApplication_postEvent_entry(QObject *receiver, QEvent *event, int type)
-QCoreApplication_postEvent_exit()
-QCoreApplication_postEvent_event_compressed(QObject *receiver, QEvent *event)
-QCoreApplication_postEvent_event_posted(QObject *receiver, QEvent *event, int type)
-
-QCoreApplication_sendEvent(QObject *receiver, QEvent *event, int type)
-QCoreApplication_sendSpontaneousEvent(QObject *receiver, QEvent *event, int type)
-
-QCoreApplication_notify_entry(QObject *receiver, QEvent *event, int type)
-QCoreApplication_notify_exit(bool consumed, bool filtered)
-
-QObject_ctor(QObject *object)
-QObject_dtor(QObject *object)
-
-QMetaObject_activate_entry(QObject *sender, int signalIndex)
-QMetaObject_activate_exit()
-QMetaObject_activate_slot_entry(QObject *receiver, int slotIndex)
-QMetaObject_activate_slot_exit()
-QMetaObject_activate_slot_functor_entry(void *slotObject)
-QMetaObject_activate_slot_functor_exit()
-QMetaObject_activate_declarative_signal_entry(QObject *sender, int signalIndex)
-QMetaObject_activate_declarative_signal_exit()
-
-qt_message_print(int type, const char *category, const char *function, const char *file, int line, const QString &message)
diff --git a/src/corelib/qtzlib.pro b/src/corelib/qtzlib.pro
deleted file mode 100644
index 744750fbbe..0000000000
--- a/src/corelib/qtzlib.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TARGET = QtZlib
-MODULE = zlib
-MAKEFILE = Makefile.qtzlib
-CONFIG += internal_module header_module alien_syncqt
-QT =
-
-load(qt_module)
diff --git a/src/corelib/serialization/make-xml-parser.sh b/src/corelib/serialization/make-xml-parser.sh
index 0296e4c22b..1889833700 100755
--- a/src/corelib/serialization/make-xml-parser.sh
+++ b/src/corelib/serialization/make-xml-parser.sh
@@ -1,42 +1,6 @@
#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2016 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
me=$(dirname $0)
mkdir -p $me/out
diff --git a/src/corelib/serialization/qbinaryjson.cpp b/src/corelib/serialization/qbinaryjson.cpp
deleted file mode 100644
index 4149705df5..0000000000
--- a/src/corelib/serialization/qbinaryjson.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjson_p.h"
-
-#include <qjsonobject.h>
-#include <qjsonarray.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QBinaryJsonPrivate {
-
-static Q_CONSTEXPR Base emptyArray = {
- { qle_uint(sizeof(Base)) },
- { 0 },
- { qle_uint(0) }
-};
-
-static Q_CONSTEXPR Base emptyObject = {
- { qle_uint(sizeof(Base)) },
- { qToLittleEndian(1U) },
- { qle_uint(0) }
-};
-
-void MutableData::compact()
-{
- static_assert(sizeof(Value) == sizeof(offset));
-
- Base *base = header->root();
- int reserve = 0;
- if (base->is_object) {
- auto *o = static_cast<Object *>(base);
- for (uint i = 0; i < o->length; ++i)
- reserve += o->entryAt(i)->usedStorage(o);
- } else {
- auto *a = static_cast<Array *>(base);
- for (uint i = 0; i < a->length; ++i)
- reserve += a->at(i)->usedStorage(a);
- }
-
- uint size = sizeof(Base) + reserve + base->length * sizeof(offset);
- uint alloc = sizeof(Header) + size;
- auto *h = reinterpret_cast<Header *>(malloc(alloc));
- Q_CHECK_PTR(h);
- h->tag = QJsonDocument::BinaryFormatTag;
- h->version = 1;
- Base *b = h->root();
- b->size = size;
- b->is_object = header->root()->is_object;
- b->length = base->length;
- b->tableOffset = reserve + sizeof(Array);
-
- uint offset = sizeof(Base);
- if (b->is_object) {
- const auto *o = static_cast<const Object *>(base);
- auto *no = static_cast<Object *>(b);
-
- for (uint i = 0; i < o->length; ++i) {
- no->table()[i] = offset;
-
- const Entry *e = o->entryAt(i);
- Entry *ne = no->entryAt(i);
- uint s = e->size();
- memcpy(ne, e, s);
- offset += s;
- uint dataSize = e->value.usedStorage(o);
- if (dataSize) {
- memcpy(reinterpret_cast<char *>(no) + offset, e->value.data(o), dataSize);
- ne->value.value = offset;
- offset += dataSize;
- }
- }
- } else {
- const auto *a = static_cast<const Array *>(base);
- auto *na = static_cast<Array *>(b);
-
- for (uint i = 0; i < a->length; ++i) {
- const Value *v = a->at(i);
- Value *nv = na->at(i);
- *nv = *v;
- uint dataSize = v->usedStorage(a);
- if (dataSize) {
- memcpy(reinterpret_cast<char *>(na) + offset, v->data(a), dataSize);
- nv->value = offset;
- offset += dataSize;
- }
- }
- }
- Q_ASSERT(offset == uint(b->tableOffset));
-
- free(header);
- header = h;
- this->alloc = alloc;
- compactionCounter = 0;
-}
-
-bool ConstData::isValid() const
-{
- if (header->tag != QJsonDocument::BinaryFormatTag || header->version != 1U)
- return false;
-
- const Base *root = header->root();
- const uint maxSize = alloc - sizeof(Header);
- return root->is_object
- ? static_cast<const Object *>(root)->isValid(maxSize)
- : static_cast<const Array *>(root)->isValid(maxSize);
-}
-
-QJsonDocument ConstData::toJsonDocument() const
-{
- const Base *root = header->root();
- return root->is_object
- ? QJsonDocument(static_cast<const Object *>(root)->toJsonObject())
- : QJsonDocument(static_cast<const Array *>(root)->toJsonArray());
-}
-
-uint Base::reserveSpace(uint dataSize, uint posInTable, uint numItems, bool replace)
-{
- Q_ASSERT(posInTable <= length);
- if (size + dataSize >= Value::MaxSize) {
- qWarning("QJson: Document too large to store in data structure %d %d %d",
- uint(size), dataSize, Value::MaxSize);
- return 0;
- }
-
- offset off = tableOffset;
- // move table to new position
- if (replace) {
- memmove(reinterpret_cast<char *>(table()) + dataSize, table(), length * sizeof(offset));
- } else {
- memmove(reinterpret_cast<char *>(table() + posInTable + numItems) + dataSize,
- table() + posInTable, (length - posInTable) * sizeof(offset));
- memmove(reinterpret_cast<char *>(table()) + dataSize, table(), posInTable * sizeof(offset));
- }
- tableOffset += dataSize;
- for (uint i = 0; i < numItems; ++i)
- table()[posInTable + i] = off;
- size += dataSize;
- if (!replace) {
- length += numItems;
- size += numItems * sizeof(offset);
- }
- return off;
-}
-
-uint Object::indexOf(QStringView key, bool *exists) const
-{
- uint min = 0;
- uint n = length;
- while (n > 0) {
- uint half = n >> 1;
- uint middle = min + half;
- if (*entryAt(middle) >= key) {
- n = half;
- } else {
- min = middle + 1;
- n -= half + 1;
- }
- }
- if (min < length && *entryAt(min) == key) {
- *exists = true;
- return min;
- }
- *exists = false;
- return min;
-}
-
-QJsonObject Object::toJsonObject() const
-{
- QJsonObject object;
- for (uint i = 0; i < length; ++i) {
- const Entry *e = entryAt(i);
- object.insert(e->key(), e->value.toJsonValue(this));
- }
- return object;
-}
-
-bool Object::isValid(uint maxSize) const
-{
- if (size > maxSize || tableOffset + length * sizeof(offset) > size)
- return false;
-
- QString lastKey;
- for (uint i = 0; i < length; ++i) {
- if (table()[i] + sizeof(Entry) >= tableOffset)
- return false;
- const Entry *e = entryAt(i);
- if (!e->isValid(tableOffset - table()[i]))
- return false;
- const QString key = e->key();
- if (key < lastKey)
- return false;
- if (!e->value.isValid(this))
- return false;
- lastKey = key;
- }
- return true;
-}
-
-QJsonArray Array::toJsonArray() const
-{
- QJsonArray array;
- const offset *values = table();
- for (uint i = 0; i < length; ++i)
- array.append(reinterpret_cast<const Value *>(values + i)->toJsonValue(this));
- return array;
-}
-
-bool Array::isValid(uint maxSize) const
-{
- if (size > maxSize || tableOffset + length * sizeof(offset) > size)
- return false;
-
- const offset *values = table();
- for (uint i = 0; i < length; ++i) {
- if (!reinterpret_cast<const Value *>(values + i)->isValid(this))
- return false;
- }
- return true;
-}
-
-uint Value::usedStorage(const Base *b) const
-{
- uint s = 0;
- switch (type) {
- case QJsonValue::Double:
- if (!latinOrIntValue)
- s = sizeof(double);
- break;
- case QJsonValue::String: {
- const char *d = data(b);
- s = latinOrIntValue
- ? (sizeof(ushort)
- + qFromLittleEndian(*reinterpret_cast<const ushort *>(d)))
- : (sizeof(int)
- + sizeof(ushort) * qFromLittleEndian(*reinterpret_cast<const int *>(d)));
- break;
- }
- case QJsonValue::Array:
- case QJsonValue::Object:
- s = base(b)->size;
- break;
- case QJsonValue::Null:
- case QJsonValue::Bool:
- default:
- break;
- }
- return alignedSize(s);
-}
-
-QJsonValue Value::toJsonValue(const Base *b) const
-{
- switch (type) {
- case QJsonValue::Null:
- return QJsonValue(QJsonValue::Null);
- case QJsonValue::Bool:
- return QJsonValue(toBoolean());
- case QJsonValue::Double:
- return QJsonValue(toDouble(b));
- case QJsonValue::String:
- return QJsonValue(toString(b));
- case QJsonValue::Array:
- return static_cast<const Array *>(base(b))->toJsonArray();
- case QJsonValue::Object:
- return static_cast<const Object *>(base(b))->toJsonObject();
- case QJsonValue::Undefined:
- return QJsonValue(QJsonValue::Undefined);
- }
- Q_UNREACHABLE();
- return QJsonValue(QJsonValue::Undefined);
-}
-
-inline bool isValidValueOffset(uint offset, uint tableOffset)
-{
- return offset >= sizeof(Base)
- && offset + sizeof(uint) <= tableOffset;
-}
-
-bool Value::isValid(const Base *b) const
-{
- switch (type) {
- case QJsonValue::Null:
- case QJsonValue::Bool:
- return true;
- case QJsonValue::Double:
- return latinOrIntValue || isValidValueOffset(value, b->tableOffset);
- case QJsonValue::String:
- if (!isValidValueOffset(value, b->tableOffset))
- return false;
- if (latinOrIntValue)
- return asLatin1String(b).isValid(b->tableOffset - value);
- return asString(b).isValid(b->tableOffset - value);
- case QJsonValue::Array:
- return isValidValueOffset(value, b->tableOffset)
- && static_cast<const Array *>(base(b))->isValid(b->tableOffset - value);
- case QJsonValue::Object:
- return isValidValueOffset(value, b->tableOffset)
- && static_cast<const Object *>(base(b))->isValid(b->tableOffset - value);
- default:
- return false;
- }
-}
-
-uint Value::requiredStorage(const QBinaryJsonValue &v, bool *compressed)
-{
- *compressed = false;
- switch (v.type()) {
- case QJsonValue::Double:
- if (QBinaryJsonPrivate::compressedNumber(v.toDouble()) != INT_MAX) {
- *compressed = true;
- return 0;
- }
- return sizeof(double);
- case QJsonValue::String: {
- QString s = v.toString();
- *compressed = QBinaryJsonPrivate::useCompressed(s);
- return QBinaryJsonPrivate::qStringSize(s, *compressed);
- }
- case QJsonValue::Array:
- case QJsonValue::Object:
- return v.base ? uint(v.base->size) : sizeof(QBinaryJsonPrivate::Base);
- case QJsonValue::Undefined:
- case QJsonValue::Null:
- case QJsonValue::Bool:
- break;
- }
- return 0;
-}
-
-uint Value::valueToStore(const QBinaryJsonValue &v, uint offset)
-{
- switch (v.type()) {
- case QJsonValue::Undefined:
- case QJsonValue::Null:
- break;
- case QJsonValue::Bool:
- return v.toBool();
- case QJsonValue::Double: {
- int c = QBinaryJsonPrivate::compressedNumber(v.toDouble());
- if (c != INT_MAX)
- return c;
- }
- Q_FALLTHROUGH();
- case QJsonValue::String:
- case QJsonValue::Array:
- case QJsonValue::Object:
- return offset;
- }
- return 0;
-}
-
-void Value::copyData(const QBinaryJsonValue &v, char *dest, bool compressed)
-{
- switch (v.type()) {
- case QJsonValue::Double:
- if (!compressed)
- qToLittleEndian(v.toDouble(), dest);
- break;
- case QJsonValue::String: {
- const QString str = v.toString();
- QBinaryJsonPrivate::copyString(dest, str, compressed);
- break;
- }
- case QJsonValue::Array:
- case QJsonValue::Object: {
- const QBinaryJsonPrivate::Base *b = v.base;
- if (!b)
- b = (v.type() == QJsonValue::Array ? &emptyArray : &emptyObject);
- memcpy(dest, b, b->size);
- break;
- }
- default:
- break;
- }
-}
-
-} // namespace QBinaryJsonPrivate
-
-QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qbinaryjson_p.h b/src/corelib/serialization/qbinaryjson_p.h
deleted file mode 100644
index 3eca794a58..0000000000
--- a/src/corelib/serialization/qbinaryjson_p.h
+++ /dev/null
@@ -1,615 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSON_P_H
-#define QBINARYJSON_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qbinaryjsonvalue_p.h>
-#include <private/qendian_p.h>
-
-#include <qjsondocument.h>
-
-#include <limits>
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-// in qstring.cpp
-void qt_to_latin1_unchecked(uchar *dst, const char16_t *uc, qsizetype len);
-
-/*
- This defines a binary data structure for Json data. The data structure is optimised for fast reading
- and minimum allocations. The whole data structure can be mmap'ed and used directly.
-
- In most cases the binary structure is not as space efficient as a utf8 encoded text representation, but
- much faster to access.
-
- The size requirements are:
-
- String:
- Latin1 data: 2 bytes header + string.length()
- Full Unicode: 4 bytes header + 2*(string.length())
-
- Values: 4 bytes + size of data (size can be 0 for some data)
- bool: 0 bytes
- double: 8 bytes (0 if integer with less than 27bits)
- string: see above
- array: size of array
- object: size of object
- Array: 12 bytes + 4*length + size of Value data
- Object: 12 bytes + 8*length + size of Key Strings + size of Value data
-
- For an example such as
-
- { // object: 12 + 5*8 = 52
- "firstName": "John", // key 12, value 8 = 20
- "lastName" : "Smith", // key 12, value 8 = 20
- "age" : 25, // key 8, value 0 = 8
- "address" : // key 12, object below = 140
- { // object: 12 + 4*8
- "streetAddress": "21 2nd Street", // key 16, value 16
- "city" : "New York", // key 8, value 12
- "state" : "NY", // key 8, value 4
- "postalCode" : "10021" // key 12, value 8
- }, // object total: 128
- "phoneNumber": // key: 16, value array below = 172
- [ // array: 12 + 2*4 + values below: 156
- { // object 12 + 2*8
- "type" : "home", // key 8, value 8
- "number": "212 555-1234" // key 8, value 16
- }, // object total: 68
- { // object 12 + 2*8
- "type" : "fax", // key 8, value 8
- "number": "646 555-4567" // key 8, value 16
- } // object total: 68
- ] // array total: 156
- } // great total: 412 bytes
-
- The uncompressed text file used roughly 500 bytes, so in this case we end up using about
- the same space as the text representation.
-
- Other measurements have shown a slightly bigger binary size than a compact text
- representation where all possible whitespace was stripped out.
-*/
-namespace QBinaryJsonPrivate {
-
-class Array;
-class Object;
-class Value;
-class Entry;
-
-template<typename T>
-using q_littleendian = QLEInteger<T>;
-
-using qle_short = q_littleendian<short>;
-using qle_ushort = q_littleendian<unsigned short>;
-using qle_int = q_littleendian<int>;
-using qle_uint = q_littleendian<unsigned int>;
-
-template<int pos, int width>
-using qle_bitfield = QLEIntegerBitfield<uint, pos, width>;
-
-template<int pos, int width>
-using qle_signedbitfield = QLEIntegerBitfield<int, pos, width>;
-
-using offset = qle_uint;
-
-// round the size up to the next 4 byte boundary
-inline uint alignedSize(uint size) { return (size + 3) & ~3; }
-
-const int MaxLatin1Length = 0x7fff;
-
-static inline bool useCompressed(QStringView s)
-{
- if (s.length() > MaxLatin1Length)
- return false;
- return QtPrivate::isLatin1(s);
-}
-
-static inline bool useCompressed(QLatin1String s)
-{
- return s.size() <= MaxLatin1Length;
-}
-
-static inline uint qStringSize(const QString &string, bool compress)
-{
- uint l = 2 + string.size();
- if (!compress)
- l *= 2;
- return alignedSize(l);
-}
-
-// returns INT_MAX if it can't compress it into 28 bits
-static inline int compressedNumber(double d)
-{
- // this relies on details of how ieee floats are represented
- const int exponent_off = 52;
- const quint64 fraction_mask = 0x000fffffffffffffULL;
- const quint64 exponent_mask = 0x7ff0000000000000ULL;
-
- quint64 val;
- memcpy (&val, &d, sizeof(double));
- int exp = (int)((val & exponent_mask) >> exponent_off) - 1023;
- if (exp < 0 || exp > 25)
- return std::numeric_limits<int>::max();
-
- quint64 non_int = val & (fraction_mask >> exp);
- if (non_int)
- return std::numeric_limits<int>::max();
-
- bool neg = (val >> 63) != 0;
- val &= fraction_mask;
- val |= ((quint64)1 << 52);
- int res = (int)(val >> (52 - exp));
- return neg ? -res : res;
-}
-
-class Latin1String;
-
-class String
-{
-public:
- explicit String(const char *data) : d(reinterpret_cast<const Data *>(data)) {}
-
- struct Data {
- qle_uint length;
- qle_ushort utf16[1];
- };
- const Data *d;
-
- uint byteSize() const { return sizeof(uint) + sizeof(ushort) * d->length; }
- bool isValid(uint maxSize) const
- {
- // Check byteSize() <= maxSize, avoiding integer overflow
- return maxSize >= sizeof(uint)
- && uint(d->length) <= (maxSize - sizeof(uint)) / sizeof(ushort);
- }
-
- static void copy(char *dest, QStringView str)
- {
- Data *data = reinterpret_cast<Data *>(dest);
- data->length = str.length();
- qToLittleEndian<quint16>(str.utf16(), str.length(), data->utf16);
- fillTrailingZeros(data);
- }
-
- static void fillTrailingZeros(Data *data)
- {
- if (data->length & 1)
- data->utf16[data->length] = 0;
- }
-
- bool operator ==(QStringView str) const
- {
- int slen = str.length();
- int l = d->length;
- if (slen != l)
- return false;
- const auto *s = reinterpret_cast<const ushort *>(str.utf16());
- const qle_ushort *a = d->utf16;
- const ushort *b = s;
- while (l-- && *a == *b)
- a++,b++;
- return (l == -1);
- }
-
- bool operator ==(const String &str) const
- {
- if (d->length != str.d->length)
- return false;
- return !memcmp(d->utf16, str.d->utf16, d->length * sizeof(ushort));
- }
-
- QString toString() const
- {
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- return QString(reinterpret_cast<const QChar *>(d->utf16), d->length);
-#else
- const uint l = d->length;
- QString str(l, Qt::Uninitialized);
- QChar *ch = str.data();
- for (uint i = 0; i < l; ++i)
- ch[i] = QChar(d->utf16[i]);
- return str;
-#endif
- }
-};
-
-class Latin1String
-{
-public:
- explicit Latin1String(const char *data) : d(reinterpret_cast<const Data *>(data)) {}
-
- struct Data {
- qle_ushort length;
- char latin1[1];
- };
- const Data *d;
-
- uint byteSize() const { return sizeof(ushort) + sizeof(char) * (d->length); }
- bool isValid(uint maxSize) const { return byteSize() <= maxSize; }
-
- static void copy(char *dest, QStringView src)
- {
- Data *data = reinterpret_cast<Data *>(dest);
- data->length = src.length(); // ### narrows from int to ushort
- auto *l = reinterpret_cast<uchar *>(data->latin1);
- qt_to_latin1_unchecked(l, src.utf16(), data->length);
-
- for (uint len = data->length; quintptr(l + len) & 0x3; ++len)
- l[len] = 0;
- }
-
- QLatin1String toQLatin1String() const noexcept { return QLatin1String(d->latin1, d->length); }
- QString toString() const { return QString::fromLatin1(d->latin1, d->length); }
-};
-
-static inline void copyString(char *dest, QStringView str, bool compress)
-{
- if (compress)
- Latin1String::copy(dest, str);
- else
- String::copy(dest, str);
-}
-
-/*
- Base is the base class for both Object and Array. Both classes work more or less the same way.
- The class starts with a header (defined by the struct below), then followed by data (the data for
- values in the Array case and Entry's (see below) for objects.
-
- After the data a table follows (tableOffset points to it) containing Value objects for Arrays, and
- offsets from the beginning of the object to Entry's in the case of Object.
-
- Entry's in the Object's table are lexicographically sorted by key in the table(). This allows the usage
- of a binary search over the keys in an Object.
- */
-class Base
-{
-public:
- qle_uint size;
- union {
- uint _dummy;
- qle_bitfield<0, 1> is_object;
- qle_bitfield<1, 31> length;
- };
- offset tableOffset;
- // content follows here
-
- bool isObject() const { return !!is_object; }
- bool isArray() const { return !isObject(); }
-
- offset *table()
- {
- return reinterpret_cast<offset *>(reinterpret_cast<char *>(this) + tableOffset);
- }
-
- const offset *table() const
- {
- return reinterpret_cast<const offset *>(reinterpret_cast<const char *>(this) + tableOffset);
- }
-
- uint reserveSpace(uint dataSize, uint posInTable, uint numItems, bool replace);
-};
-
-class Object : public Base
-{
-public:
- const Entry *entryAt(uint i) const
- {
- return reinterpret_cast<const Entry *>(reinterpret_cast<const char *>(this) + table()[i]);
- }
-
- Entry *entryAt(uint i)
- {
- return reinterpret_cast<Entry *>(reinterpret_cast<char *>(this) + table()[i]);
- }
-
- uint indexOf(QStringView key, bool *exists) const;
- QJsonObject toJsonObject() const;
- bool isValid(uint maxSize) const;
-};
-
-class Array : public Base
-{
-public:
- const Value *at(uint i) const { return reinterpret_cast<const Value *>(table() + i); }
- Value *at(uint i) { return reinterpret_cast<Value *>(table() + i); }
-
- QJsonArray toJsonArray() const;
- bool isValid(uint maxSize) const;
-};
-
-class Value
-{
-public:
- enum {
- MaxSize = (1 << 27) - 1
- };
- union {
- uint _dummy;
- qle_bitfield<0, 3> type;
- qle_bitfield<3, 1> latinOrIntValue;
- qle_bitfield<4, 1> latinKey;
- qle_bitfield<5, 27> value;
- qle_signedbitfield<5, 27> int_value;
- };
-
- inline const char *data(const Base *b) const
- {
- return reinterpret_cast<const char *>(b) + value;
- }
-
- uint usedStorage(const Base *b) const;
-
- bool toBoolean() const
- {
- Q_ASSERT(type == QJsonValue::Bool);
- return value != 0;
- }
-
- double toDouble(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::Double);
- if (latinOrIntValue)
- return int_value;
-
- auto i = qFromLittleEndian<quint64>(reinterpret_cast<const uchar *>(b) + value);
- double d;
- memcpy(&d, &i, sizeof(double));
- return d;
- }
-
- QString toString(const Base *b) const
- {
- return latinOrIntValue
- ? asLatin1String(b).toString()
- : asString(b).toString();
- }
-
- String asString(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::String && !latinOrIntValue);
- return String(data(b));
- }
-
- Latin1String asLatin1String(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::String && latinOrIntValue);
- return Latin1String(data(b));
- }
-
- const Base *base(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::Array || type == QJsonValue::Object);
- return reinterpret_cast<const Base *>(data(b));
- }
-
- QJsonValue toJsonValue(const Base *b) const;
- bool isValid(const Base *b) const;
-
- static uint requiredStorage(const QBinaryJsonValue &v, bool *compressed);
- static uint valueToStore(const QBinaryJsonValue &v, uint offset);
- static void copyData(const QBinaryJsonValue &v, char *dest, bool compressed);
-};
-
-class Entry {
-public:
- Value value;
- // key
- // value data follows key
-
- uint size() const
- {
- uint s = sizeof(Entry);
- if (value.latinKey)
- s += shallowLatin1Key().byteSize();
- else
- s += shallowKey().byteSize();
- return alignedSize(s);
- }
-
- uint usedStorage(Base *b) const
- {
- return size() + value.usedStorage(b);
- }
-
- String shallowKey() const
- {
- Q_ASSERT(!value.latinKey);
- return String(reinterpret_cast<const char *>(this) + sizeof(Entry));
- }
-
- Latin1String shallowLatin1Key() const
- {
- Q_ASSERT(value.latinKey);
- return Latin1String(reinterpret_cast<const char *>(this) + sizeof(Entry));
- }
-
- QString key() const
- {
- return value.latinKey
- ? shallowLatin1Key().toString()
- : shallowKey().toString();
- }
-
- bool isValid(uint maxSize) const
- {
- if (maxSize < sizeof(Entry))
- return false;
- maxSize -= sizeof(Entry);
- return value.latinKey
- ? shallowLatin1Key().isValid(maxSize)
- : shallowKey().isValid(maxSize);
- }
-
- bool operator ==(QStringView key) const
- {
- return value.latinKey
- ? (shallowLatin1Key().toQLatin1String() == key)
- : (shallowKey() == key);
- }
-
- bool operator >=(QStringView key) const
- {
- return value.latinKey
- ? (shallowLatin1Key().toQLatin1String() >= key)
- : (shallowKey().toString() >= key);
- }
-};
-
-class Header {
-public:
- qle_uint tag; // 'qbjs'
- qle_uint version; // 1
- Base *root() { return reinterpret_cast<Base *>(this + 1); }
- const Base *root() const { return reinterpret_cast<const Base *>(this + 1); }
-};
-
-class ConstData
-{
- Q_DISABLE_COPY_MOVE(ConstData)
-public:
- const uint alloc;
- union {
- const char *rawData;
- const Header *header;
- };
-
- ConstData(const char *raw, uint a) : alloc(a), rawData(raw) {}
- bool isValid() const;
- QJsonDocument toJsonDocument() const;
-};
-
-class MutableData
-{
- Q_DISABLE_COPY_MOVE(MutableData)
-public:
- QAtomicInt ref;
- uint alloc;
- union {
- char *rawData;
- Header *header;
- };
- uint compactionCounter : 31;
-
- MutableData(char *raw, uint a)
- : alloc(a), rawData(raw), compactionCounter(0)
- {
- }
-
- MutableData(uint reserved, QJsonValue::Type valueType)
- : rawData(nullptr), compactionCounter(0)
- {
- Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object);
-
- alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset);
- header = reinterpret_cast<Header *>(malloc(alloc));
- Q_CHECK_PTR(header);
- header->tag = QJsonDocument::BinaryFormatTag;
- header->version = 1;
- Base *b = header->root();
- b->size = sizeof(Base);
- b->is_object = (valueType == QJsonValue::Object);
- b->tableOffset = sizeof(Base);
- b->length = 0;
- }
-
- ~MutableData()
- {
- free(rawData);
- }
-
- MutableData *clone(const Base *b, uint reserve = 0)
- {
- uint size = sizeof(Header) + b->size;
- if (b == header->root() && ref.loadRelaxed() == 1 && alloc >= size + reserve)
- return this;
-
- if (reserve) {
- if (reserve < 128)
- reserve = 128;
- size = qMax(size + reserve, qMin(size *2, uint(Value::MaxSize)));
- if (size > Value::MaxSize) {
- qWarning("QJson: Document too large to store in data structure");
- return nullptr;
- }
- }
- char *raw = reinterpret_cast<char *>(malloc(size));
- Q_CHECK_PTR(raw);
- memcpy(raw + sizeof(Header), b, b->size);
- auto *h = reinterpret_cast<Header *>(raw);
- h->tag = QJsonDocument::BinaryFormatTag;
- h->version = 1;
- auto *d = new MutableData(raw, size);
- d->compactionCounter = (b == header->root()) ? compactionCounter : 0;
- return d;
- }
-
- char *takeRawData(uint *size)
- {
- *size = alloc;
- char *result = rawData;
- rawData = nullptr;
- alloc = 0;
- return result;
- }
-
- void compact();
-};
-
-} // namespace QBinaryJsonPrivate
-
-Q_DECLARE_TYPEINFO(QBinaryJsonPrivate::Value, Q_PRIMITIVE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSON_P_H
diff --git a/src/corelib/serialization/qbinaryjsonarray.cpp b/src/corelib/serialization/qbinaryjsonarray.cpp
deleted file mode 100644
index 68937fe17d..0000000000
--- a/src/corelib/serialization/qbinaryjsonarray.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjsonarray_p.h"
-#include "qbinaryjson_p.h"
-
-#include <qjsonarray.h>
-
-QT_BEGIN_NAMESPACE
-
-QBinaryJsonArray::~QBinaryJsonArray()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-QBinaryJsonArray QBinaryJsonArray::fromJsonArray(const QJsonArray &array)
-{
- QBinaryJsonArray binary;
- for (const QJsonValue &value : array)
- binary.append(QBinaryJsonValue::fromJsonValue(value));
- if (binary.d) // We want to compact it as it is a root item now
- binary.d->compactionCounter++;
- binary.compact();
- return binary;
-}
-
-void QBinaryJsonArray::append(const QBinaryJsonValue &value)
-{
- const uint i = a ? a->length : 0;
-
- bool compressed;
- uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(value, &compressed);
-
- if (!detach(valueSize + sizeof(QBinaryJsonPrivate::Value)))
- return;
-
- if (!a->length)
- a->tableOffset = sizeof(QBinaryJsonPrivate::Array);
-
- uint valueOffset = a->reserveSpace(valueSize, i, 1, false);
- if (!valueOffset)
- return;
-
- QBinaryJsonPrivate::Value *v = a->at(i);
- v->type = (value.t == QJsonValue::Undefined ? QJsonValue::Null : value.t);
- v->latinOrIntValue = compressed;
- v->latinKey = false;
- v->value = QBinaryJsonPrivate::Value::valueToStore(value, valueOffset);
- if (valueSize) {
- QBinaryJsonPrivate::Value::copyData(value, reinterpret_cast<char *>(a) + valueOffset,
- compressed);
- }
-}
-
-char *QBinaryJsonArray::takeRawData(uint *size)
-{
- if (d)
- return d->takeRawData(size);
- *size = 0;
- return nullptr;
-}
-
-bool QBinaryJsonArray::detach(uint reserve)
-{
- if (!d) {
- if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
- qWarning("QBinaryJson: Document too large to store in data structure");
- return false;
- }
- d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Array);
- a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
- d->ref.ref();
- return true;
- }
- if (reserve == 0 && d->ref.loadRelaxed() == 1)
- return true;
-
- QBinaryJsonPrivate::MutableData *x = d->clone(a, reserve);
- if (!x)
- return false;
- x->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = x;
- a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
- return true;
-}
-
-void QBinaryJsonArray::compact()
-{
- if (!d || !d->compactionCounter)
- return;
-
- detach();
- d->compact();
- a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/corelib/serialization/qbinaryjsonarray_p.h b/src/corelib/serialization/qbinaryjsonarray_p.h
deleted file mode 100644
index 2bb8fed387..0000000000
--- a/src/corelib/serialization/qbinaryjsonarray_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSONARRAY_P_H
-#define QBINARYJSONARRAY_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qbinaryjsonvalue_p.h"
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-class QBinaryJsonArray
-{
- Q_DISABLE_COPY(QBinaryJsonArray)
-public:
- QBinaryJsonArray() = default;
- ~QBinaryJsonArray();
-
- QBinaryJsonArray(QBinaryJsonArray &&other) noexcept
- : d(other.d),
- a(other.a)
- {
- other.d = nullptr;
- other.a = nullptr;
- }
-
- QBinaryJsonArray &operator =(QBinaryJsonArray &&other) noexcept
- {
- qSwap(d, other.d);
- qSwap(a, other.a);
- return *this;
- }
-
- static QBinaryJsonArray fromJsonArray(const QJsonArray &array);
- char *takeRawData(uint *size);
-
-private:
- friend class QBinaryJsonValue;
-
- void append(const QBinaryJsonValue &value);
- void compact();
- bool detach(uint reserve = 0);
-
- QBinaryJsonPrivate::MutableData *d = nullptr;
- QBinaryJsonPrivate::Array *a = nullptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSONARRAY_P_H
diff --git a/src/corelib/serialization/qbinaryjsonobject.cpp b/src/corelib/serialization/qbinaryjsonobject.cpp
deleted file mode 100644
index 3186ab6087..0000000000
--- a/src/corelib/serialization/qbinaryjsonobject.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjsonobject_p.h"
-#include "qbinaryjson_p.h"
-
-#include <qjsonobject.h>
-
-QT_BEGIN_NAMESPACE
-
-QBinaryJsonObject::~QBinaryJsonObject()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-QBinaryJsonObject QBinaryJsonObject::fromJsonObject(const QJsonObject &object)
-{
- QBinaryJsonObject binary;
- for (auto it = object.begin(), end = object.end(); it != end; ++it)
- binary.insert(it.key(), QBinaryJsonValue::fromJsonValue(it.value()));
- if (binary.d) // We want to compact it as it is a root item now
- binary.d->compactionCounter++;
- binary.compact();
- return binary;
-}
-
-void QBinaryJsonObject::insert(const QString &key, const QBinaryJsonValue &value)
-{
- bool latinOrIntValue;
- uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(value, &latinOrIntValue);
-
- bool latinKey = QBinaryJsonPrivate::useCompressed(key);
- uint valueOffset = sizeof(QBinaryJsonPrivate::Entry)
- + QBinaryJsonPrivate::qStringSize(key, latinKey);
- uint requiredSize = valueOffset + valueSize;
-
- if (!detach(requiredSize + sizeof(QBinaryJsonPrivate::offset))) // offset for the new index entry
- return;
-
- if (!o->length)
- o->tableOffset = sizeof(QBinaryJsonPrivate::Object);
-
- bool keyExists = false;
- uint pos = o->indexOf(key, &keyExists);
- if (keyExists)
- ++d->compactionCounter;
-
- uint off = o->reserveSpace(requiredSize, pos, 1, keyExists);
- if (!off)
- return;
-
- QBinaryJsonPrivate::Entry *e = o->entryAt(pos);
- e->value.type = value.t;
- e->value.latinKey = latinKey;
- e->value.latinOrIntValue = latinOrIntValue;
- e->value.value = QBinaryJsonPrivate::Value::valueToStore(
- value, reinterpret_cast<char *>(e) - reinterpret_cast<char *>(o) + valueOffset);
- QBinaryJsonPrivate::copyString(reinterpret_cast<char *>(e + 1), key, latinKey);
- if (valueSize) {
- QBinaryJsonPrivate::Value::copyData(value, reinterpret_cast<char *>(e) + valueOffset,
- latinOrIntValue);
- }
-
- if (d->compactionCounter > 32U && d->compactionCounter >= unsigned(o->length) / 2U)
- compact();
-}
-
-char *QBinaryJsonObject::takeRawData(uint *size) const
-{
- if (d)
- return d->takeRawData(size);
- *size = 0;
- return nullptr;
-}
-
-bool QBinaryJsonObject::detach(uint reserve)
-{
- if (!d) {
- if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
- qWarning("QBinaryJson: Document too large to store in data structure");
- return false;
- }
- d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Object);
- o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
- d->ref.ref();
- return true;
- }
- if (reserve == 0 && d->ref.loadRelaxed() == 1)
- return true;
-
- QBinaryJsonPrivate::MutableData *x = d->clone(o, reserve);
- if (!x)
- return false;
- x->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = x;
- o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
- return true;
-}
-
-void QBinaryJsonObject::compact()
-{
- if (!d || !d->compactionCounter)
- return;
-
- detach();
- d->compact();
- o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qbinaryjsonobject_p.h b/src/corelib/serialization/qbinaryjsonobject_p.h
deleted file mode 100644
index c0991ac339..0000000000
--- a/src/corelib/serialization/qbinaryjsonobject_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSONOBJECT_H
-#define QBINARYJSONOBJECT_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qbinaryjsonvalue_p.h"
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-class QBinaryJsonObject
-{
- Q_DISABLE_COPY(QBinaryJsonObject)
-public:
- QBinaryJsonObject() = default;
- ~QBinaryJsonObject();
-
- QBinaryJsonObject(QBinaryJsonObject &&other) noexcept
- : d(other.d), o(other.o)
- {
- other.d = nullptr;
- other.o = nullptr;
- }
-
- QBinaryJsonObject &operator =(QBinaryJsonObject &&other) noexcept
- {
- qSwap(d, other.d);
- qSwap(o, other.o);
- return *this;
- }
-
- static QBinaryJsonObject fromJsonObject(const QJsonObject &object);
- char *takeRawData(uint *size) const;
-
-private:
- friend class QBinaryJsonValue;
-
- void insert(const QString &key, const QBinaryJsonValue &value);
- bool detach(uint reserve = 0);
- void compact();
-
- QBinaryJsonPrivate::MutableData *d = nullptr;
- QBinaryJsonPrivate::Object *o = nullptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSONOBJECT_P_H
diff --git a/src/corelib/serialization/qbinaryjsonvalue.cpp b/src/corelib/serialization/qbinaryjsonvalue.cpp
deleted file mode 100644
index 7d0bc3d366..0000000000
--- a/src/corelib/serialization/qbinaryjsonvalue.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjsonobject_p.h"
-#include "qbinaryjsonvalue_p.h"
-#include "qbinaryjsonarray_p.h"
-#include "qbinaryjson_p.h"
-
-#include <qjsonarray.h>
-#include <qjsonobject.h>
-
-QT_BEGIN_NAMESPACE
-
-QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
- QBinaryJsonPrivate::Base *parent,
- const QBinaryJsonPrivate::Value &v)
- : t(QJsonValue::Type(uint(v.type)))
-{
- switch (t) {
- case QJsonValue::Undefined:
- case QJsonValue::Null:
- dbl = 0;
- break;
- case QJsonValue::Bool:
- b = v.toBoolean();
- break;
- case QJsonValue::Double:
- dbl = v.toDouble(parent);
- break;
- case QJsonValue::String:
- stringData = v.toString(parent);
- break;
- case QJsonValue::Array:
- case QJsonValue::Object:
- d = data;
- base = v.base(parent);
- break;
- }
- if (d)
- d->ref.ref();
-}
-
-QBinaryJsonValue::QBinaryJsonValue(QString string)
- : d(nullptr), t(QJsonValue::String)
-{
- stringData = std::move(string);
-}
-
-QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a)
- : base(a.a), d(a.d), t(QJsonValue::Array)
-{
- if (d)
- d->ref.ref();
-}
-
-QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o)
- : base(o.o), d(o.d), t(QJsonValue::Object)
-{
- if (d)
- d->ref.ref();
-}
-
-QBinaryJsonValue::~QBinaryJsonValue()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-QBinaryJsonValue QBinaryJsonValue::fromJsonValue(const QJsonValue &json)
-{
- switch (json.type()) {
- case QJsonValue::Bool:
- return QBinaryJsonValue(json.toBool());
- case QJsonValue::Double:
- return QBinaryJsonValue(json.toDouble());
- case QJsonValue::String:
- return QBinaryJsonValue(json.toString());
- case QJsonValue::Array:
- return QBinaryJsonArray::fromJsonArray(json.toArray());
- case QJsonValue::Object:
- return QBinaryJsonObject::fromJsonObject(json.toObject());
- case QJsonValue::Null:
- return QBinaryJsonValue(QJsonValue::Null);
- case QJsonValue::Undefined:
- return QBinaryJsonValue(QJsonValue::Undefined);
- }
- Q_UNREACHABLE();
- return QBinaryJsonValue(QJsonValue::Null);
-}
-
-QString QBinaryJsonValue::toString() const
-{
- if (t != QJsonValue::String)
- return QString();
- return stringData;
-}
-
-void QBinaryJsonValue::detach()
-{
- if (!d)
- return;
-
- QBinaryJsonPrivate::MutableData *x = d->clone(base);
- x->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = x;
- base = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qbinaryjsonvalue_p.h b/src/corelib/serialization/qbinaryjsonvalue_p.h
deleted file mode 100644
index c3b943250c..0000000000
--- a/src/corelib/serialization/qbinaryjsonvalue_p.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSONVALUE_P_H
-#define QBINARYJSONVALUE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qjsonvalue.h>
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-class QBinaryJsonArray;
-class QBinaryJsonObject;
-
-namespace QBinaryJsonPrivate {
-class ConstData;
-class MutableData;
-class Base;
-class Value;
-class Object;
-class Array;
-}
-
-class Q_CORE_EXPORT QBinaryJsonValue
-{
- Q_DISABLE_COPY(QBinaryJsonValue)
-public:
- explicit QBinaryJsonValue(QJsonValue::Type type) : ui(0), t(type) {}
- explicit QBinaryJsonValue(bool b) : b(b), t(QJsonValue::Bool) {}
- explicit QBinaryJsonValue(double n) : dbl(n), t(QJsonValue::Double) {}
- explicit QBinaryJsonValue(QString s);
- QBinaryJsonValue(const QBinaryJsonArray &a);
- QBinaryJsonValue(const QBinaryJsonObject &o);
-
- ~QBinaryJsonValue();
-
- QBinaryJsonValue(QBinaryJsonValue &&other) noexcept
- : ui(other.ui),
- stringData(std::move(other.stringData)),
- d(other.d),
- t(other.t)
- {
- other.ui = 0;
- other.d = nullptr;
- other.t = QJsonValue::Null;
- }
-
- QBinaryJsonValue &operator =(QBinaryJsonValue &&other) noexcept
- {
- qSwap(stringData, other.stringData);
- qSwap(ui, other.ui);
- qSwap(d, other.d);
- qSwap(t, other.t);
- return *this;
- }
-
- static QBinaryJsonValue fromJsonValue(const QJsonValue &json);
- QJsonValue::Type type() const { return t; }
- bool toBool() const { return (t == QJsonValue::Bool) && b; }
- double toDouble() const { return (t == QJsonValue::Double) ? dbl : 0; }
- QString toString() const;
-
-private:
- friend class QBinaryJsonPrivate::Value;
- friend class QBinaryJsonArray;
- friend class QBinaryJsonObject;
-
- QBinaryJsonValue(QBinaryJsonPrivate::MutableData *d, QBinaryJsonPrivate::Base *parent,
- const QBinaryJsonPrivate::Value &v);
-
- void detach();
-
- union {
- quint64 ui;
- bool b;
- double dbl;
- const QBinaryJsonPrivate::Base *base;
- };
- QString stringData;
- QBinaryJsonPrivate::MutableData *d = nullptr; // needed for Objects and Arrays
- QJsonValue::Type t = QJsonValue::Null;
-};
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSONVALUE_P_H
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index 2e0de4f4fc..626fb49a70 100644
--- a/src/corelib/serialization/qcborarray.cpp
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborarray.h"
#include "qcborvalue_p.h"
@@ -49,24 +13,30 @@ using namespace QtCbor;
\class QCborArray
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
\brief The QCborArray class is used to hold an array of CBOR elements.
+ \compares strong
+ \compareswith strong QCborValueConstRef
+ \endcompareswith
+
This class can be used to hold one sequential container in CBOR (an array).
CBOR is the Concise Binary Object Representation, a very compact form of
binary data encoding that is a superset of JSON. It was created by the IETF
Constrained RESTful Environments (CoRE) WG, which has used it in many new
RFCs. It is meant to be used alongside the
- \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
+ \l{RFC 7252}{CoAP protocol}.
QCborArray is very similar to \l QVariantList and \l QJsonArray and its API
is almost identical to those two classes. It can also be converted to and
from those two, though there may be loss of information in some
conversions.
- \sa QCborValue, QCborMap, QJsonArray, QList
+ \sa QCborValue, QCborMap, QJsonArray, QList, {Parsing and displaying CBOR data},
+ {Serialization Converter}, {Saving and Loading a Game}
*/
/*!
@@ -454,7 +424,7 @@ void QCborArray::removeAt(qsizetype i)
bool QCborArray::contains(const QCborValue &value) const
{
for (qsizetype i = 0; i < size(); ++i) {
- int cmp = d->compareElement(i, value);
+ int cmp = d->compareElement(i, value, Comparison::ForEquality);
if (cmp == 0)
return true;
}
@@ -476,9 +446,9 @@ bool QCborArray::contains(const QCborValue &value) const
*/
/*!
- \fn bool QCborArray::operator==(const QCborArray &other) const
+ \fn bool QCborArray::operator==(const QCborArray &lhs, const QCborArray &rhs)
- Compares this array and \a other, comparing each element in sequence, and
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
returns true if both arrays contains the same elements, false otherwise.
For more information on CBOR equality in Qt, see, QCborValue::compare().
@@ -488,9 +458,9 @@ bool QCborArray::contains(const QCborValue &value) const
*/
/*!
- \fn bool QCborArray::operator!=(const QCborArray &other) const
+ \fn bool QCborArray::operator!=(const QCborArray &lhs, const QCborArray &rhs)
- Compares this array and \a other, comparing each element in sequence, and
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
returns true if the two arrays' contents are different, false otherwise.
For more information on CBOR equality in Qt, see, QCborValue::compare().
@@ -500,19 +470,58 @@ bool QCborArray::contains(const QCborValue &value) const
*/
/*!
- \fn bool QCborArray::operator<(const QCborArray &other) const
+ \fn bool QCborArray::operator<(const QCborArray &lhs, const QCborArray &rhs)
- Compares this array and \a other, comparing each element in sequence, and
- returns true if this array should be sorted before \a other, false
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted before \a rhs, false
otherwise.
For more information on CBOR sorting order, see QCborValue::compare().
\sa compare(), QCborValue::operator==(), QCborMap::operator==(),
- operator==(), operator!=()
+ operator==(), operator!=(), operator<=()
*/
/*!
+ \fn bool QCborArray::operator<=(const QCborArray &lhs, const QCborArray &rhs)
+
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted before \a rhs, or if both
+ arrays contains the same elements, false otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=(), operator<()
+*/
+
+/*!
+ \fn bool QCborArray::operator>(const QCborArray &lhs, const QCborArray &rhs)
+
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted after \a rhs, false
+ otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=(), operator>=()
+*/
+
+/*!
+ \fn bool QCborArray::operator>=(const QCborArray &lhs, const QCborArray &rhs)
+
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted after \a rhs, or if both
+ arrays contains the same elements, false otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=(), operator>()
+*/
+
+/*!
\typedef QCborArray::iterator
A synonym to QCborArray::Iterator.
@@ -713,6 +722,10 @@ void QCborArray::detach(qsizetype reserved)
\brief The QCborArray::Iterator class provides an STL-style non-const iterator for QCborArray.
+ \compares strong
+ \compareswith strong QCborArray::ConstIterator
+ \endcompareswith
+
QCborArray::Iterator allows you to iterate over a QCborArray and to modify
the array item associated with the iterator. If you want to iterate over a
const QCborArray, use QCborArray::ConstIterator instead. It is generally a
@@ -809,7 +822,7 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn QCborValueRef QCborArray::Iterator::operator[](qsizetype j)
+ \fn QCborValueRef QCborArray::Iterator::operator[](qsizetype j) const
Returns a modifiable reference to the item at a position \a j steps forward
from the item pointed to by this iterator.
@@ -827,63 +840,63 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborArray::Iterator::operator==(const Iterator &other) const
- \fn bool QCborArray::Iterator::operator==(const ConstIterator &other) const
+ \fn bool QCborArray::Iterator::operator==(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator==(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the array as this
+ Returns \c true if \a lhs points to the same entry in the array as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborArray::Iterator::operator!=(const Iterator &other) const
- \fn bool QCborArray::Iterator::operator!=(const ConstIterator &other) const
+ \fn bool QCborArray::Iterator::operator!=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator!=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to a different entry in the array than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the array than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborArray::Iterator::operator<(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator<(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator<(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator<(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::Iterator::operator<=(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator<=(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator<=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator<=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborArray::Iterator::operator>(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator>(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator>(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator>(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::Iterator::operator>=(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator>=(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator>=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator>=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborArray::Iterator &QCborArray::Iterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the next item in
the array and returns this iterator.
Calling this function on QCborArray::end() leads to undefined results.
@@ -895,14 +908,14 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::Iterator QCborArray::Iterator::operator++(int)
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the next item
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the next item
in the array and returns an iterator to the previously current item.
*/
/*!
\fn QCborArray::Iterator &QCborArray::Iterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--it}, makes the preceding item current and
returns this iterator.
Calling this function on QCborArray::begin() leads to undefined results.
@@ -914,7 +927,7 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::Iterator QCborArray::Iterator::operator--(int)
\overload
- The postfix -- operator, \c{it--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{it--}, makes the preceding item current and
returns an iterator to the previously current item.
*/
@@ -968,6 +981,10 @@ void QCborArray::detach(qsizetype reserved)
\brief The QCborArray::ConstIterator class provides an STL-style const iterator for QCborArray.
+ \compares strong
+ \compareswith strong QCborArray::Iterator
+ \endcompareswith
+
QCborArray::ConstIterator allows you to iterate over a QCborArray. If you
want to modify the QCborArray as you iterate over it, use
QCborArray::Iterator instead. It is generally good practice to use
@@ -1055,7 +1072,7 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn const QCborValueRef QCborArray::ConstIterator::operator[](qsizetype j)
+ \fn QCborValueRef QCborArray::ConstIterator::operator[](qsizetype j) const
Returns the item at a position \a j steps forward from the item pointed to
by this iterator.
@@ -1067,63 +1084,57 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborArray::ConstIterator::operator==(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator==(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator==(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the array as this
+ Returns \c true if \a lhs points to the same entry in the array as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborArray::ConstIterator::operator!=(const Iterator &o) const
- \fn bool QCborArray::ConstIterator::operator!=(const ConstIterator &o) const
+ \fn bool QCborArray::ConstIterator::operator!=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a o points to a different entry in the array than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the array than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborArray::ConstIterator::operator<(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator<(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator<(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::ConstIterator::operator<=(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator<=(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator<=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborArray::ConstIterator::operator>(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator>(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator>(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::ConstIterator::operator>=(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator>=(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator>=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the next item in
the array and returns this iterator.
Calling this function on QCborArray::end() leads to undefined results.
@@ -1135,14 +1146,14 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::ConstIterator QCborArray::ConstIterator::operator++(int)
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the next item
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the next item
in the array and returns an iterator to the previously current item.
*/
/*!
\fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--it}, makes the preceding item current and
returns this iterator.
Calling this function on QCborArray::begin() leads to undefined results.
@@ -1154,7 +1165,7 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::ConstIterator QCborArray::ConstIterator::operator--(int)
\overload
- The postfix -- operator, \c{it--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{it--}, makes the preceding item current and
returns an iterator to the previously current item.
*/
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
index 8d0aceac33..481f316f33 100644
--- a/src/corelib/serialization/qcborarray.h
+++ b/src/corelib/serialization/qcborarray.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORARRAY_H
#define QCBORARRAY_H
@@ -49,13 +13,15 @@ QT_BEGIN_NAMESPACE
class QJsonArray;
class QDataStream;
+namespace QJsonPrivate { class Variant; }
+
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborArray
{
public:
class ConstIterator;
class Iterator {
- mutable QCborValueRef item;
+ QCborValueRef item {};
friend class ConstIterator;
friend class QCborArray;
Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
@@ -66,8 +32,8 @@ public:
typedef QCborValueRef reference;
typedef QCborValueRef *pointer;
- Q_DECL_CONSTEXPR Iterator() = default;
- Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
+ constexpr Iterator() = default;
+ constexpr Iterator(const Iterator &) = default;
Iterator &operator=(const Iterator &other)
{
// rebind the reference
@@ -77,21 +43,23 @@ public:
}
QCborValueRef operator*() const { return item; }
- QCborValueRef *operator->() const { return &item; }
- QCborValueRef operator[](qsizetype j) { return { item.d, item.i + j }; }
-
+ QCborValueRef *operator->() { return &item; }
+ const QCborValueConstRef *operator->() const { return &item; }
+ QCborValueRef operator[](qsizetype j) const { return { item.d, item.i + j }; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
Iterator &operator++() { ++item.i; return *this; }
Iterator operator++(int) { Iterator n = *this; ++item.i; return n; }
Iterator &operator--() { item.i--; return *this; }
@@ -101,10 +69,57 @@ public:
Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + j }); }
Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - j }); }
qsizetype operator-(Iterator j) const { return item.i - j.item.i; }
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static bool comparesEqual_helper(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator)
+ friend bool comparesEqual(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator, ConstIterator)
};
class ConstIterator {
- QCborValueRef item;
+ QCborValueConstRef item;
friend class Iterator;
friend class QCborArray;
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
@@ -115,8 +130,8 @@ public:
typedef const QCborValueRef reference;
typedef const QCborValueRef *pointer;
- Q_DECL_CONSTEXPR ConstIterator() = default;
- Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
+ constexpr ConstIterator() = default;
+ constexpr ConstIterator(const ConstIterator &) = default;
ConstIterator &operator=(const ConstIterator &other)
{
// rebind the reference
@@ -125,22 +140,23 @@ public:
return *this;
}
- const QCborValueRef operator*() const { return item; }
- const QCborValueRef *operator->() const { return &item; }
- const QCborValueRef operator[](qsizetype j) { return { item.d, item.i + j }; }
-
+ QCborValueConstRef operator*() const { return item; }
+ const QCborValueConstRef *operator->() const { return &item; }
+ QCborValueConstRef operator[](qsizetype j) const { return QCborValueRef{ item.d, item.i + j }; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
ConstIterator &operator++() { ++item.i; return *this; }
ConstIterator operator++(int) { ConstIterator n = *this; ++item.i; return n; }
ConstIterator &operator--() { item.i--; return *this; }
@@ -150,6 +166,31 @@ public:
ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + j }); }
ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - j }); }
qsizetype operator-(ConstIterator j) const { return item.i - j.item.i; }
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const ConstIterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(ConstIterator)
};
typedef qsizetype size_type;
@@ -174,7 +215,7 @@ public:
void swap(QCborArray &other) noexcept
{
- qSwap(d, other.d);
+ d.swap(other.d);
}
QCborValue toCborValue() const { return *this; }
@@ -214,19 +255,11 @@ public:
bool contains(const QCborValue &value) const;
int compare(const QCborArray &other) const noexcept Q_DECL_PURE_FUNCTION;
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborArray &other) const
- {
- int c = compare(other);
- if (c > 0) return std::strong_ordering::greater;
- if (c == 0) return std::strong_ordering::equivalent;
- return std::strong_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborArray &other) const noexcept
{ return compare(other) == 0; }
bool operator!=(const QCborArray &other) const noexcept
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborArray &other) const
{ return compare(other) < 0; }
#endif
@@ -265,14 +298,58 @@ public:
static QCborArray fromStringList(const QStringList &list);
static QCborArray fromVariantList(const QVariantList &list);
static QCborArray fromJsonArray(const QJsonArray &array);
+ static QCborArray fromJsonArray(QJsonArray &&array) noexcept;
QVariantList toVariantList() const;
QJsonArray toJsonArray() const;
private:
+ friend Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual(const QCborArray &lhs, const QCborArray &rhs) noexcept;
+ friend Qt::strong_ordering compareThreeWay(const QCborArray &lhs,
+ const QCborArray &rhs) noexcept
+ {
+ int c = lhs.compare(rhs);
+ return Qt::compareThreeWay(c, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborArray)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept;
+ friend bool comparesEqual(const QCborArray &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborArray &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborArray, QCborValue)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept;
+ friend bool comparesEqual(const QCborArray &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborArray &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborArray, QCborValueConstRef)
+
void detach(qsizetype reserve = 0);
friend QCborValue;
friend QCborValueRef;
+ friend class QJsonPrivate::Variant;
explicit QCborArray(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -284,6 +361,7 @@ inline QCborValue::QCborValue(QCborArray &&a)
{
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
inline QCborArray QCborValueRef::toArray() const
{
return concrete().toArray();
@@ -293,6 +371,17 @@ inline QCborArray QCborValueRef::toArray(const QCborArray &a) const
{
return concrete().toArray(a);
}
+#endif
+
+inline QCborArray QCborValueConstRef::toArray() const
+{
+ return concrete().toArray();
+}
+
+inline QCborArray QCborValueConstRef::toArray(const QCborArray &a) const
+{
+ return concrete().toArray(a);
+}
Q_CORE_EXPORT size_t qHash(const QCborArray &array, size_t seed = 0);
diff --git a/src/corelib/serialization/qcborcommon.cpp b/src/corelib/serialization/qcborcommon.cpp
index b29e1f1bf6..b3d4f70aa2 100644
--- a/src/corelib/serialization/qcborcommon.cpp
+++ b/src/corelib/serialization/qcborcommon.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define CBOR_NO_ENCODER_API
#define CBOR_NO_PARSER_API
@@ -46,11 +10,14 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QCborTag)
+
#include <cborerrorstrings.c>
/*!
\headerfile <QtCborCommon>
-
+ \inmodule QtCore
+ \ingroup qtserialization
\brief The <QtCborCommon> header contains definitions common to both the
streaming classes (QCborStreamReader and QCborStreamWriter) and to
QCborValue.
@@ -145,7 +112,7 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
\value PositiveBignum A positive number of arbitrary length, encoded as a byte array in
network byte order. For example, the number 2\sup{64} is represented by
a byte array containing the byte value 0x01 followed by 8 zero bytes.
- \value NegativeBignum A negative number of arbirary length, encoded as the absolute value
+ \value NegativeBignum A negative number of arbitrary length, encoded as the absolute value
of that number, minus one. For example, a byte array containing
byte value 0x02 followed by 8 zero bytes represents the number
-2\sup{65} - 1.
@@ -153,11 +120,11 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
is the exponent of the power of 10, the second the integral
mantissa. The value 273.15 would be encoded as array \c{[-2, 27315]}.
\value Bigfloat Similar to Decimal, but the exponent is a power of 2 instead.
- \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Mac0 A \c Mac0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Mac0 A \c Mac0 map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Sign1 A \c Sign1 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Sign1 A \c Sign1 map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
\value ExpectedBase64url Indicates that the byte array should be encoded using Base64url
if the stream is converted to JSON.
@@ -172,13 +139,13 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
\value RegularExpression Indicates that the string contains a Perl-Compatible Regular
Expression pattern.
\value MimeMessage Indicates that the string contains a MIME message (according to
- \l{https://tools.ietf.org/html/rfc2045}){RFC 2045}.
+ \l{RFC 2045}).
\value Uuid Indicates that the byte array contains a UUID.
- \value COSE_Encrypt An \c Encrypt map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Encrypt An \c Encrypt map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Mac A \c Mac map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Mac A \c Mac map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Sign A \c Sign map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Sign A \c Sign map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
\value Signature No change in interpretation; this tag can be used as the outermost
tag in a CBOR stream as the file header.
@@ -205,14 +172,16 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
/*!
\class QCborError
\inmodule QtCore
- \inheaderfile <QtCborCommon>
+ \inheaderfile QtCborCommon
\reentrant
\since 5.12
\brief The QCborError class holds the error condition found while parsing or
validating a CBOR stream.
- \sa QCborStreamReader, QCborValue, QCborParserError
+ \sa QCborStreamReader, QCborValue, QCborParserError,
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
/*!
@@ -230,8 +199,8 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
element.
\value UnexpectedBreak The CBOR stream contains a Break where it is not allowed (data is
corrupt and the error is not recoverable).
- \value UnknownType The CBOR stream contains an unknown/unparseable Type (data is corrupt
- and the and the error is not recoverable).
+ \value UnknownType The CBOR stream contains an unknown/unparsable Type (data is corrupt
+ and the error is not recoverable).
\value IllegalType The CBOR stream contains a known type in a position it is not allowed
to exist (data is corrupt and the error is not recoverable).
\value IllegalNumber The CBOR stream appears to be encoding a number larger than 64-bit
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
index 1497da3d2e..bd7a93dfe7 100644
--- a/src/corelib/serialization/qcborcommon.h
+++ b/src/corelib/serialization/qcborcommon.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORCOMMON_H
#define QCBORCOMMON_H
@@ -50,7 +14,6 @@
/* X11 headers use these values too, but as defines */
#if defined(False) && defined(True)
-# define QT_X11_DEFINES_FOUND 1
# undef True
# undef False
#endif
@@ -133,9 +96,9 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg);
Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
#endif
-#if !defined(QT_NO_DEBUG_STREAM)
-QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
-QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
+#if !defined(QT_NO_DATASTREAM)
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
#endif
inline size_t qHash(QCborSimpleType tag, size_t seed = 0)
@@ -152,7 +115,7 @@ enum class QCborNegativeInteger : quint64 {};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QCborTag)
+QT_DECL_METATYPE_EXTERN(QCborTag, Q_CORE_EXPORT)
// To avoid changing namespace we need to reinstate defines, even though our .cpp
// will then have to remove them again.
diff --git a/src/corelib/serialization/qcborcommon_p.h b/src/corelib/serialization/qcborcommon_p.h
index 9b7f4b7099..69e80cb9d6 100644
--- a/src/corelib/serialization/qcborcommon_p.h
+++ b/src/corelib/serialization/qcborcommon_p.h
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORCOMMON_P_H
#define QCBORCOMMON_P_H
#include "qcborcommon.h"
+#include "private/qglobal_p.h"
//
// W A R N I N G
diff --git a/src/corelib/serialization/qcbordiagnostic.cpp b/src/corelib/serialization/qcbordiagnostic.cpp
index 2e92dab0a4..e89afc4827 100644
--- a/src/corelib/serialization/qcbordiagnostic.cpp
+++ b/src/corelib/serialization/qcbordiagnostic.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborvalue.h"
#include "qcborvalue_p.h"
@@ -49,6 +13,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace {
class DiagnosticNotation
{
@@ -75,7 +41,7 @@ private:
++dn->nestingLevel;
static const char indent[IndentationWidth + 1] = " ";
if (dn->opts & QCborValue::LineWrapped)
- dn->separator += QLatin1String(indent, IndentationWidth);
+ dn->separator += QLatin1StringView(indent, IndentationWidth);
}
~Nest()
{
@@ -86,7 +52,7 @@ private:
};
DiagnosticNotation(QCborValue::DiagnosticNotationOptions opts_)
- : separator(QLatin1String(opts_ & QCborValue::LineWrapped ? "\n" : "")), opts(opts_)
+ : separator(opts_ & QCborValue::LineWrapped ? "\n"_L1 : ""_L1), opts(opts_)
{
byteArrayFormatStack.push(int(QCborKnownTags::ExpectedBase16));
}
@@ -109,11 +75,11 @@ static QString makeFpString(double d)
} else if (convertDoubleTo(d, &v)) {
s = QString::fromLatin1("%1.0").arg(v);
if (d < 0)
- s.prepend(QLatin1Char('-'));
+ s.prepend(u'-');
} else {
s = QString::number(d, 'g', QLocale::FloatingPointShortest);
if (!s.contains(u'.') && !s.contains(u'e'))
- s += QLatin1Char('.');
+ s += u'.';
}
return s;
}
@@ -131,7 +97,7 @@ static bool isByteArrayEncodingTag(QCborTag tag)
void DiagnosticNotation::appendString(const QString &s)
{
- result += QLatin1Char('"');
+ result += u'"';
const QChar *begin = s.begin();
const QChar *end = s.end();
@@ -161,7 +127,7 @@ void DiagnosticNotation::appendString(const QString &s)
};
int buflen = 2;
QChar buf[10];
- buf[0] = QLatin1Char('\\');
+ buf[0] = u'\\';
buf[1] = QChar::Null;
char16_t uc = ptr->unicode();
@@ -203,18 +169,18 @@ void DiagnosticNotation::appendString(const QString &s)
begin = ptr + 1;
}
- result += QLatin1Char('"');
+ result += u'"';
}
void DiagnosticNotation::appendArray(const QCborArray &a)
{
- result += QLatin1Char('[');
+ result += u'[';
// length 2 (including the space) when not line wrapping
- QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
+ QLatin1StringView commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
{
Nest n(this);
- QLatin1String comma;
+ QLatin1StringView comma;
for (auto v : a) {
result += comma + separator;
comma = commaValue;
@@ -222,28 +188,28 @@ void DiagnosticNotation::appendArray(const QCborArray &a)
}
}
- result += separator + QLatin1Char(']');
+ result += separator + u']';
}
void DiagnosticNotation::appendMap(const QCborMap &m)
{
- result += QLatin1Char('{');
+ result += u'{';
// length 2 (including the space) when not line wrapping
- QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
+ QLatin1StringView commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
{
Nest n(this);
- QLatin1String comma;
+ QLatin1StringView comma;
for (auto v : m) {
result += comma + separator;
comma = commaValue;
appendValue(v.first);
- result += QLatin1String(": ");
+ result += ": "_L1;
appendValue(v.second);
}
}
- result += separator + QLatin1Char('}');
+ result += separator + u'}';
};
void DiagnosticNotation::appendValue(const QCborValue &v)
@@ -276,16 +242,16 @@ void DiagnosticNotation::appendValue(const QCborValue &v)
case QCborValue::Map:
return appendMap(v.toMap());
case QCborValue::False:
- result += QLatin1String("false");
+ result += "false"_L1;
return;
case QCborValue::True:
- result += QLatin1String("true");
+ result += "true"_L1;
return;
case QCborValue::Null:
- result += QLatin1String("null");
+ result += "null"_L1;
return;
case QCborValue::Undefined:
- result += QLatin1String("undefined");
+ result += "undefined"_L1;
return;
case QCborValue::Double:
result += makeFpString(v.toDouble());
@@ -305,9 +271,9 @@ void DiagnosticNotation::appendValue(const QCborValue &v)
bool byteArrayFormat = opts & QCborValue::ExtendedFormat && isByteArrayEncodingTag(v.tag());
if (byteArrayFormat)
byteArrayFormatStack.push(int(v.tag()));
- result += QString::number(quint64(v.tag())) + QLatin1Char('(');
+ result += QString::number(quint64(v.tag())) + u'(';
appendValue(v.taggedValue());
- result += QLatin1Char(')');
+ result += u')';
if (byteArrayFormat)
byteArrayFormatStack.pop();
} else {
@@ -326,7 +292,7 @@ void DiagnosticNotation::appendValue(const QCborValue &v)
would be possible.
CBOR diagnostic notation is specified by
- \l{https://tools.ietf.org/html/rfc7049#section-6}{section 6} of RFC 7049.
+ \l{RFC 7049, section 6}{section 6} of RFC 7049.
It is a text representation of the CBOR stream and it is very similar to
JSON, but it supports the CBOR types not found in JSON. The extended format
enabled by the \l{DiagnosticNotationOption}{ExtendedFormat} flag is
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
index 34c8c72059..038e0d61ce 100644
--- a/src/corelib/serialization/qcbormap.cpp
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcbormap.h"
#include "qcborvalue_p.h"
@@ -48,17 +12,22 @@ using namespace QtCbor;
\class QCborMap
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
\brief The QCborMap class is used to hold an associative container representable in CBOR.
+ \compares strong
+ \compareswith strong QCborValue QCborValueConstRef
+ \endcompareswith
+
This class can be used to hold an associative container in CBOR, a map
between a key and a value type. CBOR is the Concise Binary Object
Representation, a very compact form of binary data encoding that is a
superset of JSON. It was created by the IETF Constrained RESTful
Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ be used alongside the \l{RFC 7252}{CoAP
protocol}.
Unlike JSON and \l QVariantMap, CBOR map keys can be of any type, not just
@@ -82,7 +51,9 @@ using namespace QtCbor;
stringified using a one-way method that the conversion back to QCborMap
will not undo.
- \sa QCborArray, QCborValue, QJsonDocument, QVariantMap
+ \sa QCborArray, QCborValue, QJsonDocument, QVariantMap,
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
/*!
@@ -328,7 +299,7 @@ QList<QCborValue> QCborMap::keys() const
duplicate keys is usually an indication of a problem in the sender.
\sa operator[](qint64), find(qint64), constFind(qint64), remove(qint64), contains(qint64)
- value(QLatin1String), value(const QString &), value(const QCborValue &)
+ value(QLatin1StringView), value(const QString &), value(const QCborValue &)
*/
/*!
@@ -350,7 +321,8 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), find(qint64), constFind(qint64), remove(qint64), contains(qint64)
- operator[](QLatin1String), operator[](const QString &), operator[](const QCborOperator[] &)
+ operator[](QLatin1StringView), operator[](const QString &),
+ operator[](const QCborOperator[] &)
*/
/*!
@@ -366,7 +338,7 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), operator[](qint64), find(qint64), contains(qint64),
- take(QLatin1String), take(const QString &), take(const QCborValue &), insert()
+ take(QLatin1StringView), take(const QString &), take(const QCborValue &), insert()
*/
/*!
@@ -382,7 +354,7 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), operator[](qint64), find(qint64), contains(qint64)
- remove(QLatin1String), remove(const QString &), remove(const QCborValue &)
+ remove(QLatin1StringView), remove(const QString &), remove(const QCborValue &)
*/
/*!
@@ -393,7 +365,7 @@ QList<QCborValue> QCborMap::keys() const
are simpler to encode and decode.
\sa value(qint64), operator[](qint64), find(qint64), remove(qint64),
- contains(QLatin1String), remove(const QString &), remove(const QCborValue &)
+ contains(QLatin1StringView), remove(const QString &), remove(const QCborValue &)
*/
/*!
@@ -418,22 +390,15 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), find(qint64), contains(qint64), remove(qint64),
- operator[](QLatin1String), operator[](const QString &), operator[](const QCborValue &)
+ operator[](QLatin1StringView), operator[](const QString &), operator[](const QCborValue &)
*/
QCborValueRef QCborMap::operator[](qint64 key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
- \fn QCborValue QCborMap::value(QLatin1String key) const
+ \fn QCborValue QCborMap::value(QLatin1StringView key) const
\overload
Returns the QCborValue element in this map that corresponds to key \a key,
@@ -450,13 +415,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa operator[](QLatin1String), find(QLatin1String), constFind(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa operator[](QLatin1StringView), find(QLatin1StringView), constFind(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView)
value(qint64), value(const QString &), value(const QCborValue &)
*/
/*!
- \fn QCborValue QCborMap::operator[](QLatin1String key) const
+ \fn QCborValue QCborMap::operator[](QLatin1StringView key) const
\overload
Returns the QCborValue element in this map that corresponds to key \a key,
@@ -473,13 +438,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), find(QLatin1String), constFind(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa value(QLatin1StringView), find(QLatin1StringView), constFind(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView)
operator[](qint64), operator[](const QString &), operator[](const QCborOperator[] &)
*/
/*!
- \fn QCborValue QCborMap::take(QLatin1String key)
+ \fn QCborValue QCborMap::take(QLatin1StringView key)
Removes the key \a key and the corresponding value from the map and returns
the value, if it is found. If the map contains no such key, this function does nothing.
@@ -490,12 +455,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), contains(QLatin1String),
- take(qint64), take(const QString &), take(const QCborValue &), insert()
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ contains(QLatin1StringView), take(qint64), take(const QString &),
+ take(const QCborValue &), insert()
*/
/*!
- \fn void QCborMap::remove(QLatin1String key)
+ \fn void QCborMap::remove(QLatin1StringView key)
\overload
Removes the key \a key and the corresponding value from the map, if it is
@@ -507,19 +473,21 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), contains(QLatin1String)
- remove(qint64), remove(const QString &), remove(const QCborValue &)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ contains(QLatin1StringView), remove(qint64), remove(const QString &),
+ remove(const QCborValue &)
*/
/*!
- \fn bool QCborMap::contains(QLatin1String key) const
+ \fn bool QCborMap::contains(QLatin1StringView key) const
\overload
Returns true if this map contains a key-value pair identified by key \a
key.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), remove(QLatin1String),
- contains(qint64), remove(const QString &), remove(const QCborValue &)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ remove(QLatin1StringView), contains(qint64), remove(const QString &),
+ remove(const QCborValue &)
*/
/*!
@@ -544,19 +512,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), find(QLatin1String), contains(QLatin1String), remove(QLatin1String),
- operator[](qint64), operator[](const QString &), operator[](const QCborValue &)
+ \sa value(QLatin1StringView), find(QLatin1StringView), contains(QLatin1StringView),
+ remove(QLatin1StringView), operator[](qint64), operator[](const QString &),
+ operator[](const QCborValue &)
*/
-QCborValueRef QCborMap::operator[](QLatin1String key)
+QCborValueRef QCborMap::operator[](QLatin1StringView key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
@@ -579,7 +541,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa operator[](const QString &), find(const QString &), constFind(const QString &),
remove(const QString &), contains(const QString &)
- value(qint64), value(QLatin1String), value(const QCborValue &)
+ value(qint64), value(QLatin1StringView), value(const QCborValue &)
*/
/*!
@@ -602,7 +564,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa value(const QString &), find(const QString &), constFind(const QString &),
remove(const QString &), contains(const QString &)
- operator[](qint64), operator[](QLatin1String), operator[](const QCborOperator[] &)
+ operator[](qint64), operator[](QLatin1StringView), operator[](const QCborOperator[] &)
*/
/*!
@@ -617,8 +579,9 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QString &), operator[](const QString &), find(const QString &), contains(const QString &),
- take(QLatin1String), take(qint64), take(const QCborValue &), insert()
+ \sa value(const QString &), operator[](const QString &), find(const QString &),
+ contains(const QString &), take(QLatin1StringView), take(qint64),
+ take(const QCborValue &), insert()
*/
/*!
@@ -636,7 +599,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa value(const QString &), operator[](const QString &), find(const QString &),
contains(const QString &)
- remove(qint64), remove(QLatin1String), remove(const QCborValue &)
+ remove(qint64), remove(QLatin1StringView), remove(const QCborValue &)
*/
/*!
@@ -648,7 +611,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa value(const QString &), operator[](const QString &), find(const QString &),
remove(const QString &),
- contains(qint64), remove(QLatin1String), remove(const QCborValue &)
+ contains(qint64), remove(QLatin1StringView), remove(const QCborValue &)
*/
/*!
@@ -673,19 +636,13 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QString &), find(const QString &), contains(const QString &), remove(const QString &),
- operator[](qint64), operator[](QLatin1String), operator[](const QCborValue &)
+ \sa value(const QString &), find(const QString &), contains(const QString &),
+ remove(const QString &), operator[](qint64), operator[](QLatin1StringView),
+ operator[](const QCborValue &)
*/
QCborValueRef QCborMap::operator[](const QString & key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -707,7 +664,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa operator[](const QCborValue &), find(const QCborValue &), constFind(const QCborValue &),
remove(const QCborValue &), contains(const QCborValue &)
- value(qint64), value(QLatin1String), value(const QString &)
+ value(qint64), value(QLatin1StringView), value(const QString &)
*/
/*!
@@ -729,7 +686,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa value(const QCborValue &), find(const QCborValue &), constFind(const QCborValue &),
remove(const QCborValue &), contains(const QCborValue &)
- operator[](qint64), operator[](QLatin1String), operator[](const QCborOperator[] &)
+ operator[](qint64), operator[](QLatin1StringView), operator[](const QCborOperator[] &)
*/
/*!
@@ -744,8 +701,9 @@ QCborValueRef QCborMap::operator[](const QString & key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &), contains(const QCborValue &),
- take(QLatin1String), take(const QString &), take(qint64), insert()
+ \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
+ contains(const QCborValue &), take(QLatin1StringView), take(const QString &),
+ take(qint64), insert()
*/
/*!
@@ -762,7 +720,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
contains(const QCborValue &)
- remove(qint64), remove(QLatin1String), remove(const QString &)
+ remove(qint64), remove(QLatin1StringView), remove(const QString &)
*/
/*!
@@ -773,7 +731,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
remove(const QCborValue &),
- contains(qint64), remove(QLatin1String), remove(const QString &)
+ contains(qint64), remove(QLatin1StringView), remove(const QString &)
*/
/*!
@@ -798,19 +756,21 @@ QCborValueRef QCborMap::operator[](const QString & key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QCborValue &), find(const QCborValue &), contains(const QCborValue &), remove(const QCborValue &),
- operator[](qint64), operator[](QLatin1String), operator[](const QString &)
+ \sa value(const QCborValue &), find(const QCborValue &), contains(const QCborValue &),
+ remove(const QCborValue &), operator[](qint64), operator[](QLatin1StringView),
+ operator[](const QString &)
*/
QCborValueRef QCborMap::operator[](const QCborValue &key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey<const QCborValue &>(*this, key);
+}
+
+template <typename KeyType> inline QCborValueRef
+QCborContainerPrivate::findOrAddMapKey(QCborMap &map, KeyType key)
+{
+ QCborValueRef result = findOrAddMapKey<KeyType>(map.d.data(), key);
+ map.d = result.d;
+ return result;
}
/*!
@@ -829,8 +789,8 @@ QCborValueRef QCborMap::operator[](const QCborValue &key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(qint64), operator[](qint64), constFind(qint64), remove(qint64), contains(qint64)
- value(QLatin1String), value(const QString &), value(const QCborValue &)
+ \sa value(qint64), operator[](qint64), constFind(qint64), remove(qint64), contains(qint64),
+ value(QLatin1StringView), value(const QString &), value(const QCborValue &)
*/
QCborMap::iterator QCborMap::find(qint64 key)
{
@@ -840,8 +800,8 @@ QCborMap::iterator QCborMap::find(qint64 key)
}
/*!
- \fn QCborMap::iterator QCborMap::find(QLatin1String key)
- \fn QCborMap::const_iterator QCborMap::find(QLatin1String key) const
+ \fn QCborMap::iterator QCborMap::find(QLatin1StringView key)
+ \fn QCborMap::const_iterator QCborMap::find(QLatin1StringView key) const
\overload
Returns a map iterator to the key-value pair whose key is \a key, if the
@@ -853,11 +813,11 @@ QCborMap::iterator QCborMap::find(qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), constFind(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), constFind(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView),
value(qint64), value(const QString &), value(const QCborValue &)
*/
-QCborMap::iterator QCborMap::find(QLatin1String key)
+QCborMap::iterator QCborMap::find(QLatin1StringView key)
{
detach();
auto it = constFind(key);
@@ -879,8 +839,8 @@ QCborMap::iterator QCborMap::find(QLatin1String key)
is usually an indication of a problem in the sender.
\sa value(const QString &), operator[](const QString &), constFind(const QString &),
- remove(const QString &), contains(const QString &)
- value(qint64), value(QLatin1String), value(const QCborValue &)
+ remove(const QString &), contains(const QString &),
+ value(qint64), value(QLatin1StringView), value(const QCborValue &)
*/
QCborMap::iterator QCborMap::find(const QString & key)
{
@@ -904,8 +864,8 @@ QCborMap::iterator QCborMap::find(const QString & key)
is usually an indication of a problem in the sender.
\sa value(const QCborValue &), operator[](const QCborValue &), constFind(const QCborValue &),
- remove(const QCborValue &), contains(const QCborValue &)
- value(qint64), value(QLatin1String), value(const QString &)
+ remove(const QCborValue &), contains(const QCborValue &),
+ value(qint64), value(QLatin1StringView), value(const QString &)
*/
QCborMap::iterator QCborMap::find(const QCborValue &key)
{
@@ -927,17 +887,12 @@ QCborMap::iterator QCborMap::find(const QCborValue &key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(qint64), operator[](qint64), find(qint64), remove(qint64), contains(qint64)
- value(QLatin1String), value(const QString &), value(const QCborValue &)
+ \sa value(qint64), operator[](qint64), find(qint64), remove(qint64), contains(qint64),
+ value(QLatin1StringView), value(const QString &), value(const QCborValue &)
*/
QCborMap::const_iterator QCborMap::constFind(qint64 key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- const auto &e = d->elements.at(i);
- if (e.type == QCborValue::Integer && e.value == key)
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey(key) : constEnd();
}
/*!
@@ -952,17 +907,13 @@ QCborMap::const_iterator QCborMap::constFind(qint64 key) const
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView),
value(qint64), value(const QString &), value(const QCborValue &)
*/
-QCborMap::const_iterator QCborMap::constFind(QLatin1String key) const
+QCborMap::const_iterator QCborMap::constFind(QLatin1StringView key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- if (d->stringEqualsElement(i, key))
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey(key) : constEnd();
}
/*!
@@ -978,16 +929,12 @@ QCborMap::const_iterator QCborMap::constFind(QLatin1String key) const
is usually an indication of a problem in the sender.
\sa value(const QString &), operator[](const QString &), find(const QString &),
- remove(const QString &), contains(const QString &)
- value(qint64), value(QLatin1String), value(const QCborValue &)
+ remove(const QString &), contains(const QString &),
+ value(qint64), value(QLatin1StringView), value(const QCborValue &)
*/
-QCborMap::const_iterator QCborMap::constFind(const QString & key) const
+QCborMap::const_iterator QCborMap::constFind(const QString &key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- if (d->stringEqualsElement(i, key))
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey(qToStringViewIgnoringNull(key)) : constEnd();
}
/*!
@@ -1004,16 +951,11 @@ QCborMap::const_iterator QCborMap::constFind(const QString & key) const
\sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
remove(const QCborValue &), contains(const QCborValue &),
- value(qint64), value(QLatin1String), value(const QString &)
+ value(qint64), value(QLatin1StringView), value(const QString &)
*/
QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- int cmp = d->compareElement(i, key);
- if (cmp == 0)
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey<const QCborValue &>(key) : constEnd();
}
/*!
@@ -1031,7 +973,7 @@ QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
*/
/*!
- \fn QCborMap::iterator QCborMap::insert(QLatin1String key, const QCborValue &value)
+ \fn QCborMap::iterator QCborMap::insert(QLatin1StringView key, const QCborValue &value)
\overload
Inserts the key \a key and value \a value into this map and returns a map
@@ -1040,8 +982,8 @@ QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
If the map already had a key equal to \a key, its value will be overwritten
by \a value.
- \sa erase(), remove(QLatin1String), value(QLatin1String), operator[](QLatin1String),
- find(QLatin1String), contains(QLatin1String), take(QLatin1String), extract()
+ \sa erase(), remove(QLatin1StringView), value(QLatin1StringView), operator[](QLatin1StringView),
+ find(QLatin1StringView), contains(QLatin1StringView), take(QLatin1StringView), extract()
*/
/*!
@@ -1167,10 +1109,10 @@ QCborValue QCborMap::extract(iterator it)
*/
/*!
- \fn bool QCborMap::operator==(const QCborMap &other) const
+ \fn bool QCborMap::operator==(const QCborMap &lhs, const QCborMap &rhs)
- Compares this map and \a other, comparing each element in sequence, and
- returns true if the two maps contains the same elements in the same order,
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if the two maps contain the same elements in the same order,
false otherwise.
Note that CBOR maps are unordered, which means that two maps containing the
@@ -1186,10 +1128,10 @@ QCborValue QCborMap::extract(iterator it)
*/
/*!
- \fn bool QCborMap::operator!=(const QCborMap &other) const
+ \fn bool QCborMap::operator!=(const QCborMap &lhs, const QCborMap &rhs)
- Compares this map and \a other, comparing each element in sequence, and
- returns true if the two maps contains any different elements or elements in
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if the two maps contain any different elements or elements in
different orders, false otherwise.
Note that CBOR maps are unordered, which means that two maps containing the
@@ -1205,10 +1147,10 @@ QCborValue QCborMap::extract(iterator it)
*/
/*!
- \fn bool QCborMap::operator<(const QCborMap &other) const
+ \fn bool QCborMap::operator<(const QCborMap &lhs, const QCborMap &rhs)
- Compares this map and \a other, comparing each element in sequence, and
- returns true if this map should be sorted before \a other, false
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted before \a rhs, false
otherwise.
Note that CBOR maps are unordered, which means that two maps containing the
@@ -1223,6 +1165,65 @@ QCborValue QCborMap::extract(iterator it)
operator==(), operator!=()
*/
+/*!
+ \fn bool QCborMap::operator<=(const QCborMap &lhs, const QCborMap &rhs)
+
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted before \a rhs or
+ if the two maps contain the same elements in the same order, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborMap::operator>=(const QCborMap &lhs, const QCborMap &rhs)
+
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted after \a rhs or
+ if the two maps contain the same elements in the same order, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborMap::operator>(const QCborMap &lhs, const QCborMap &rhs)
+
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted after \a rhs, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
void QCborMap::detach(qsizetype reserved)
{
d = QCborContainerPrivate::detach(d.data(), reserved ? reserved : size() * 2);
@@ -1237,6 +1238,10 @@ void QCborMap::detach(qsizetype reserved)
\brief The QCborMap::Iterator class provides an STL-style non-const iterator for QCborMap.
+ \compares strong
+ \compareswith strong ConstIterator
+ \endcompareswith
+
QCborMap::Iterator allows you to iterate over a QCborMap and to modify the
value (but not the key) stored under a particular key. If you want to
iterate over a const QCborMap, you should use QCborMap::ConstIterator. It
@@ -1358,63 +1363,63 @@ void QCborMap::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborMap::Iterator::operator==(const Iterator &other) const
- \fn bool QCborMap::Iterator::operator==(const ConstIterator &other) const
+ \fn bool QCborMap::Iterator::operator==(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator==(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the map as this
+ Returns \c true if \a lhs points to the same entry in the map as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborMap::Iterator::operator!=(const Iterator &other) const
- \fn bool QCborMap::Iterator::operator!=(const ConstIterator &other) const
+ \fn bool QCborMap::Iterator::operator!=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator!=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to a different entry in the map than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the map than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborMap::Iterator::operator<(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator<(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator<(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator<(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::Iterator::operator<=(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator<=(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator<=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator<=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborMap::Iterator::operator>(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator>(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator>(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator>(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::Iterator::operator>=(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator>=(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator>=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator>=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborMap::Iterator &QCborMap::Iterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the next item in
the map and returns this iterator.
Calling this function on QCborMap::end() leads to undefined results.
@@ -1426,14 +1431,14 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::Iterator QCborMap::Iterator::operator++(int)
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the next item in
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the next item in
the map and returns an iterator to the previously current item.
*/
/*!
\fn QCborMap::Iterator QCborMap::Iterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--i}, makes the preceding item current and
returns this iterator.
Calling this function on QCborMap::begin() leads to undefined results.
@@ -1445,7 +1450,7 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::Iterator QCborMap::Iterator::operator--(int)
\overload
- The postfix -- operator, \c{i--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{i--}, makes the preceding item current and
returns an iterator pointing to the previously current item.
*/
@@ -1503,6 +1508,10 @@ void QCborMap::detach(qsizetype reserved)
\brief The QCborMap::ConstIterator class provides an STL-style const iterator for QCborMap.
+ \compares strong
+ \compareswith strong Iterator
+ \endcompareswith
+
QCborMap::ConstIterator allows you to iterate over a QCborMap. If you want
to modify the QCborMap as you iterate over it, you must use
QCborMap::Iterator instead. It is generally good practice to use
@@ -1591,7 +1600,7 @@ void QCborMap::detach(qsizetype reserved)
/*!
\fn QCborMap::ConstIterator::value_type QCborMap::ConstIterator::operator*() const
- Returns a pair containing the curent item's key and value.
+ Returns a pair containing the current item's key and value.
\sa key(), value()
*/
@@ -1603,63 +1612,57 @@ void QCborMap::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborMap::ConstIterator::operator==(const ConstIterator &other) const
- \fn bool QCborMap::ConstIterator::operator==(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator==(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the map as this
+ Returns \c true if \a lhs points to the same entry in the map as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborMap::ConstIterator::operator!=(const ConstIterator &other) const
- \fn bool QCborMap::ConstIterator::operator!=(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator!=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to a different entry in the map than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the map than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborMap::ConstIterator::operator<(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator<(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator<(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::ConstIterator::operator<=(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator<=(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator<=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborMap::ConstIterator::operator>(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator>(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator>(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::ConstIterator::operator>=(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator>=(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator>=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the next item in
the map and returns this iterator.
Calling this function on QCborMap::end() leads to undefined results.
@@ -1671,14 +1674,14 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::ConstIterator QCborMap::ConstIterator::operator++(int)
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the next item in
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the next item in
the map and returns an iterator to the previously current item.
*/
/*!
\fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--i}, makes the preceding item current and
returns this iterator.
Calling this function on QCborMap::begin() leads to undefined results.
@@ -1690,7 +1693,7 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::ConstIterator QCborMap::ConstIterator::operator--(int)
\overload
- The postfix -- operator, \c{i--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{i--}, makes the preceding item current and
returns an iterator pointing to the previously current item.
*/
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
index 7e1a4cb485..d2fd769240 100644
--- a/src/corelib/serialization/qcbormap.h
+++ b/src/corelib/serialization/qcbormap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORMAP_H
#define QCBORMAP_H
@@ -47,37 +11,36 @@
QT_BEGIN_NAMESPACE
-template <class Key, class T> class QMap;
-typedef QMap<QString, QVariant> QVariantMap;
-template <class Key, class T> class QHash;
-typedef QHash<QString, QVariant> QVariantHash;
class QJsonObject;
class QDataStream;
+namespace QJsonPrivate { class Variant; }
+
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborMap
{
public:
- typedef QPair<QCborValue, QCborValue> value_type;
+ typedef std::pair<QCborValue, QCborValue> value_type;
typedef QCborValue key_type;
typedef QCborValue mapped_type;
typedef qsizetype size_type;
class ConstIterator;
class Iterator {
- mutable QCborValueRef item; // points to the value
+ QCborValueRef item {}; // points to the value
friend class ConstIterator;
friend class QCborMap;
Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
public:
typedef std::random_access_iterator_tag iterator_category;
typedef qsizetype difference_type;
- typedef QPair<const QCborValueRef, QCborValueRef> value_type;
- typedef QPair<const QCborValueRef, QCborValueRef> reference;
- typedef QPair<const QCborValueRef, QCborValueRef> pointer;
+ typedef std::pair<QCborValueConstRef, QCborValueRef> value_type;
+ typedef std::pair<QCborValueConstRef, QCborValueRef> reference;
+ typedef std::pair<QCborValueConstRef, QCborValueRef> pointer;
- Q_DECL_CONSTEXPR Iterator() = default;
- Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
+ constexpr Iterator() = default;
+ constexpr Iterator(const Iterator &) = default;
+ ~Iterator() = default;
Iterator &operator=(const Iterator &other)
{
// rebind the reference
@@ -86,23 +49,32 @@ public:
return *this;
}
- value_type operator*() const { return { {item.d, item.i - 1}, item }; }
- QCborValueRef *operator->() const { return &item; }
- QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
+ value_type operator*() const { return { QCborValueRef{item.d, item.i - 1}, item }; }
+ value_type operator[](qsizetype j) const { return *(*this + j); }
+ QCborValueRef *operator->() { return &item; }
+ const QCborValueConstRef *operator->() const { return &item; }
+#if QT_VERSION >= QT_VERSION_CHECK(7,0,0)
+ QCborValueConstRef
+#else
+ QCborValue
+#endif
+ key() const { return QCborValueRef(item.d, item.i - 1); }
QCborValueRef value() const { return item; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
Iterator &operator++() { item.i += 2; return *this; }
Iterator operator++(int) { Iterator n = *this; item.i += 2; return n; }
Iterator &operator--() { item.i -= 2; return *this; }
@@ -112,24 +84,74 @@ public:
Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + 2 * j }); }
Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - 2 * j }); }
qsizetype operator-(Iterator j) const { return (item.i - j.item.i) / 2; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static bool comparesEqual_helper(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator)
+ friend bool comparesEqual(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator, ConstIterator)
};
class ConstIterator {
- QCborValueRef item; // points to the value
+ QCborValueConstRef item; // points to the value
friend class Iterator;
friend class QCborMap;
friend class QCborValue;
friend class QCborValueRef;
+ constexpr ConstIterator(QCborValueConstRef it) : item{it} {}
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
public:
typedef std::random_access_iterator_tag iterator_category;
typedef qsizetype difference_type;
- typedef QPair<const QCborValueRef, const QCborValueRef> value_type;
- typedef QPair<const QCborValueRef, const QCborValueRef> reference;
- typedef QPair<const QCborValueRef, const QCborValueRef> pointer;
+ typedef std::pair<QCborValueConstRef, QCborValueConstRef> value_type;
+ typedef std::pair<QCborValueConstRef, QCborValueConstRef> reference;
+ typedef std::pair<QCborValueConstRef, QCborValueConstRef> pointer;
- Q_DECL_CONSTEXPR ConstIterator() = default;
- Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
+ constexpr ConstIterator() = default;
+ constexpr ConstIterator(const ConstIterator &) = default;
+ ~ConstIterator() = default;
ConstIterator &operator=(const ConstIterator &other)
{
// rebind the reference
@@ -138,32 +160,65 @@ public:
return *this;
}
- value_type operator*() const { return { {item.d, item.i - 1}, item }; }
- const QCborValueRef *operator->() const { return &item; }
- QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
- QCborValueRef value() const { return item; }
+ value_type operator*() const { return { QCborValueRef(item.d, item.i - 1), item }; }
+ value_type operator[](qsizetype j) const { return *(*this + j); }
+ const QCborValueConstRef *operator->() const { return &item; }
+#if QT_VERSION >= QT_VERSION_CHECK(7,0,0)
+ QCborValueConstRef
+#else
+ QCborValue
+#endif
+ key() const { return QCborValueRef(item.d, item.i - 1); }
+ QCborValueConstRef value() const { return item; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
ConstIterator &operator++() { item.i += 2; return *this; }
ConstIterator operator++(int) { ConstIterator n = *this; item.i += 2; return n; }
ConstIterator &operator--() { item.i -= 2; return *this; }
ConstIterator operator--(int) { ConstIterator n = *this; item.i -= 2; return n; }
ConstIterator &operator+=(qsizetype j) { item.i += 2 * j; return *this; }
ConstIterator &operator-=(qsizetype j) { item.i -= 2 * j; return *this; }
- ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + 2 * j }); }
- ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - 2 * j }); }
+ ConstIterator operator+(qsizetype j) const { return ConstIterator{ item.d, item.i + 2 * j }; }
+ ConstIterator operator-(qsizetype j) const { return ConstIterator{ item.d, item.i - 2 * j }; }
qsizetype operator-(ConstIterator j) const { return (item.i - j.item.i) / 2; }
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const ConstIterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(ConstIterator)
};
QCborMap() noexcept;
@@ -180,7 +235,7 @@ public:
void swap(QCborMap &other) noexcept
{
- qSwap(d, other.d);
+ d.swap(other.d);
}
QCborValue toCborValue() const { return *this; }
@@ -191,73 +246,65 @@ public:
QList<QCborValue> keys() const;
QCborValue value(qint64 key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
- QCborValue value(QLatin1String key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
+ QCborValue value(QLatin1StringView key) const
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
QCborValue value(const QString & key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
QCborValue value(const QCborValue &key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
template<size_t N> QT_ASCII_CAST_WARN const QCborValue value(const char (&key)[N]) const
{ return value(QString::fromUtf8(key, N - 1)); }
#endif
const QCborValue operator[](qint64 key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
- const QCborValue operator[](QLatin1String key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
+ const QCborValue operator[](QLatin1StringView key) const
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
const QCborValue operator[](const QString & key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
const QCborValue operator[](const QCborValue &key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
template<size_t N> QT_ASCII_CAST_WARN const QCborValue operator[](const char (&key)[N]) const
{ return operator[](QString::fromUtf8(key, N - 1)); }
#endif
QCborValueRef operator[](qint64 key);
- QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](QLatin1StringView key);
QCborValueRef operator[](const QString & key);
QCborValueRef operator[](const QCborValue &key);
QCborValue take(qint64 key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
- QCborValue take(QLatin1String key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
+ QCborValue take(QLatin1StringView key)
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
QCborValue take(const QString &key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
QCborValue take(const QCborValue &key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
void remove(qint64 key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
- void remove(QLatin1String key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
+ void remove(QLatin1StringView key)
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
void remove(const QString & key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
void remove(const QCborValue &key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
bool contains(qint64 key) const
- { const_iterator it = find(key); return it != end(); }
- bool contains(QLatin1String key) const
- { const_iterator it = find(key); return it != end(); }
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
+ bool contains(QLatin1StringView key) const
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
bool contains(const QString & key) const
- { const_iterator it = find(key); return it != end(); }
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
bool contains(const QCborValue &key) const
- { const_iterator it = find(key); return it != end(); }
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
int compare(const QCborMap &other) const noexcept Q_DECL_PURE_FUNCTION;
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborMap &other) const
- {
- int c = compare(other);
- if (c > 0) return std::strong_ordering::greater;
- if (c == 0) return std::strong_ordering::equivalent;
- return std::strong_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborMap &other) const noexcept
{ return compare(other) == 0; }
bool operator!=(const QCborMap &other) const noexcept
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborMap &other) const
{ return compare(other) < 0; }
#endif
@@ -279,15 +326,15 @@ public:
bool empty() const { return isEmpty(); }
iterator find(qint64 key);
- iterator find(QLatin1String key);
+ iterator find(QLatin1StringView key);
iterator find(const QString & key);
iterator find(const QCborValue &key);
const_iterator constFind(qint64 key) const;
- const_iterator constFind(QLatin1String key) const;
+ const_iterator constFind(QLatin1StringView key) const;
const_iterator constFind(const QString & key) const;
const_iterator constFind(const QCborValue &key) const;
const_iterator find(qint64 key) const { return constFind(key); }
- const_iterator find(QLatin1String key) const { return constFind(key); }
+ const_iterator find(QLatin1StringView key) const { return constFind(key); }
const_iterator find(const QString & key) const { return constFind(key); }
const_iterator find(const QCborValue &key) const { return constFind(key); }
@@ -297,7 +344,7 @@ public:
v = value_;
return { d.data(), v.i };
}
- iterator insert(QLatin1String key, const QCborValue &value_)
+ iterator insert(QLatin1StringView key, const QCborValue &value_)
{
QCborValueRef v = operator[](key); // detaches
v = value_;
@@ -320,15 +367,60 @@ public:
static QCborMap fromVariantMap(const QVariantMap &map);
static QCborMap fromVariantHash(const QVariantHash &hash);
static QCborMap fromJsonObject(const QJsonObject &o);
+ static QCborMap fromJsonObject(QJsonObject &&o) noexcept;
QVariantMap toVariantMap() const;
QVariantHash toVariantHash() const;
QJsonObject toJsonObject() const;
private:
+ friend class QCborContainerPrivate;
friend class QCborValue;
friend class QCborValueRef;
+ friend class QJsonPrivate::Variant;
void detach(qsizetype reserve = 0);
+ friend Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual(const QCborMap &lhs, const QCborMap &rhs) noexcept;
+ friend Qt::strong_ordering compareThreeWay(const QCborMap &lhs,
+ const QCborMap &rhs) noexcept
+ {
+ int c = lhs.compare(rhs);
+ return Qt::compareThreeWay(c, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborMap)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept;
+ friend bool comparesEqual(const QCborMap &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborMap &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborMap, QCborValue)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept;
+ friend bool comparesEqual(const QCborMap &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborMap &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborMap, QCborValueConstRef)
+
explicit QCborMap(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -340,6 +432,7 @@ inline QCborValue::QCborValue(QCborMap &&m)
{
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
inline QCborMap QCborValueRef::toMap() const
{
return concrete().toMap();
@@ -349,6 +442,17 @@ inline QCborMap QCborValueRef::toMap(const QCborMap &m) const
{
return concrete().toMap(m);
}
+#endif
+
+inline QCborMap QCborValueConstRef::toMap() const
+{
+ return concrete().toMap();
+}
+
+inline QCborMap QCborValueConstRef::toMap(const QCborMap &m) const
+{
+ return concrete().toMap(m);
+}
Q_CORE_EXPORT size_t qHash(const QCborMap &map, size_t seed = 0);
diff --git a/src/corelib/serialization/qcborstream.h b/src/corelib/serialization/qcborstream.h
index f2b88820cd..7850d26663 100644
--- a/src/corelib/serialization/qcborstream.h
+++ b/src/corelib/serialization/qcborstream.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORSTREAM_H
#define QCBORSTREAM_H
diff --git a/src/corelib/serialization/qcborstreamreader.cpp b/src/corelib/serialization/qcborstreamreader.cpp
index 308fbe9ae9..863c24534a 100644
--- a/src/corelib/serialization/qcborstreamreader.cpp
+++ b/src/corelib/serialization/qcborstreamreader.cpp
@@ -1,52 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborstreamreader.h"
#define CBOR_NO_ENCODER_API
#include <private/qcborcommon_p.h>
-#include <private/qbytearray_p.h>
#include <private/qnumeric_p.h>
#include <private/qstringconverter_p.h>
+#include <qiodevice.h>
#include <qdebug.h>
#include <qstack.h>
+#include <qvarlengtharray.h>
QT_BEGIN_NAMESPACE
@@ -63,6 +28,7 @@ static CborError qt_cbor_decoder_transfer_string(void *token, const void **userp
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
+QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough")
#include <cborparser.c>
@@ -70,13 +36,11 @@ QT_WARNING_POP
static CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
-static CborError Q_DECL_UNUSED cbor_value_get_half_float_as_float(const CborValue *, float *)
+[[maybe_unused]] static CborError cbor_value_get_half_float_as_float(const CborValue *, float *)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
// confirm our constants match TinyCBOR's
@@ -96,6 +60,7 @@ static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
\class QCborStreamReader
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
@@ -107,7 +72,7 @@ static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
Representation, a very compact form of binary data encoding that is
compatible with JSON. It was created by the IETF Constrained RESTful
Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ be used alongside the \l{RFC 7252}{CoAP
protocol}.
QCborStreamReader provides a StAX-like API, similar to that of
@@ -185,7 +150,9 @@ static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
parsing from a QByteArray, or reparse(), if it is instead reading directly
a the QIDOevice that now has more data available (see setDevice()).
- \sa QCborStreamWriter, QCborValue, QXmlStreamReader
+ \sa QCborStreamWriter, QCborValue, QXmlStreamReader,
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
/*!
@@ -563,7 +530,7 @@ public:
CborValue currentElement;
QCborError lastError = {};
- QByteArray::size_type bufferStart;
+ QByteArray::size_type bufferStart = 0;
bool corrupt = false;
QCborStreamReaderPrivate(const QByteArray &data)
@@ -645,27 +612,30 @@ public:
lastError = QCborError { QCborError::Code(int(err)) };
}
- void updateBufferAfterString(qsizetype offset, qsizetype size)
- {
- Q_ASSERT(device);
-
- bufferStart += offset;
- qsizetype newStart = bufferStart + size;
- qsizetype remainingInBuffer = buffer.size() - newStart;
-
- if (remainingInBuffer <= 0) {
- // We've read from the QIODevice more than what was in the buffer.
- buffer.truncate(0);
- } else {
- // There's still data buffered, but we need to move it around.
- char *ptr = buffer.data();
- memmove(ptr, ptr + newStart, remainingInBuffer);
- buffer.truncate(remainingInBuffer);
- }
-
- bufferStart = 0;
- }
+ struct ReadStringChunk {
+ union {
+ char *ptr;
+ QByteArray *array;
+ QString *string;
+ };
+ enum Type { ByteArray = -1, String = -3, Utf8String = -5 };
+ qsizetype maxlen_or_type;
+
+ ReadStringChunk(char *ptr, qsizetype maxlen) : ptr(ptr), maxlen_or_type(maxlen) {}
+ ReadStringChunk(QByteArray *array, Type type = ByteArray) : array(array), maxlen_or_type(type) {}
+ ReadStringChunk(QString *str) : string(str), maxlen_or_type(String) {}
+ bool isString() const { return maxlen_or_type == String; }
+ bool isUtf8String() const { return maxlen_or_type == Utf8String; }
+ bool isByteArray() const { return maxlen_or_type == ByteArray; }
+ bool isPlainPointer() const { return maxlen_or_type >= 0; }
+ };
+ static QCborStreamReader::StringResultCode appendStringChunk(QCborStreamReader &reader, QByteArray *data);
+ bool readFullString(ReadStringChunk params);
+ QCborStreamReader::StringResult<qsizetype> readStringChunk(ReadStringChunk params);
+ qsizetype readStringChunk_byte(ReadStringChunk params, qsizetype len);
+ qsizetype readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len);
+ qsizetype readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len);
bool ensureStringIteration();
};
@@ -715,7 +685,7 @@ static CborError qt_cbor_decoder_transfer_string(void *token, const void **userp
// (otherwise, we'd lose the length information)
qsizetype total;
if (len > size_t(std::numeric_limits<QByteArray::size_type>::max())
- || add_overflow<qsizetype>(offset, len, &total))
+ || qAddOverflow<qsizetype>(offset, len, &total))
return CborErrorDataTooLarge;
// our string transfer is just saving the offset to the userptr
@@ -785,7 +755,7 @@ inline void QCborStreamReader::preparse()
\sa addData(), isValid()
*/
QCborStreamReader::QCborStreamReader()
- : QCborStreamReader(QByteArray())
+ : d(new QCborStreamReaderPrivate({})), type_(Invalid)
{
}
@@ -828,7 +798,7 @@ QCborStreamReader::QCborStreamReader(const QByteArray &data)
Creates a QCborStreamReader object that will parse the CBOR stream found by
reading from \a device. QCborStreamReader does not take ownership of \a
- device, so it must remain valid until this oject is destroyed.
+ device, so it must remain valid until this object is destroyed.
*/
QCborStreamReader::QCborStreamReader(QIODevice *device)
: d(new QCborStreamReaderPrivate(device))
@@ -962,7 +932,7 @@ void QCborStreamReader::reset()
\sa isValid()
*/
-QCborError QCborStreamReader::lastError()
+QCborError QCborStreamReader::lastError() const
{
return d->lastError;
}
@@ -1003,7 +973,7 @@ QCborStreamReader::Type QCborStreamReader::parentContainerType() const
{
if (d->containerStack.isEmpty())
return Invalid;
- return Type(cbor_value_get_type(&qAsConst(d->containerStack).top()));
+ return Type(cbor_value_get_type(&std::as_const(d->containerStack).top()));
}
/*!
@@ -1053,19 +1023,18 @@ bool QCborStreamReader::next(int maxRecursion)
next(maxRecursion - 1);
if (lastError() == QCborError::NoError)
leaveContainer();
- } else if (isString() || isByteArray()) {
- auto r = _readByteArray_helper();
- while (r.status == Ok) {
- if (isString() && r.data.size() > MaxStringSize) {
- d->handleError(CborErrorDataTooLarge);
- break;
- }
- if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) {
- d->handleError(CborErrorInvalidUtf8TextString);
- break;
- }
- r = _readByteArray_helper();
- }
+ } else if (isByteArray()) {
+ char c;
+ StringResult<qsizetype> r;
+ do {
+ r = readStringChunk(&c, 1);
+ } while (r.status == Ok);
+ } else if (isString()) {
+ // we need to use actual readString so we get UTF-8 validation
+ StringResult<QString> r;
+ do {
+ r = readString();
+ } while (r.status == Ok);
} else {
// fixed types
CborError err = cbor_value_advance_fixed(&d->currentElement);
@@ -1324,77 +1293,104 @@ bool QCborStreamReader::leaveContainer()
Decodes one string chunk from the CBOR string and returns it. This function
is used for both regular and chunked string contents, so the caller must
- always loop around calling this function, even if isLengthKnown() has
+ always loop around calling this function, even if isLengthKnown()
is true. The typical use of this function is as follows:
\snippet code/src_corelib_serialization_qcborstream.cpp 27
+ The readAllString() function implements the above loop and some extra checks.
+
+//! [string-no-type-conversions]
This function does not perform any type conversions, including from integers
or from byte arrays. Therefore, it may only be called if isString() returned
true; calling it in any other condition is an error.
+//! [string-no-type-conversions]
- \sa readByteArray(), isString(), readStringChunk()
+ \sa readAllString(), readByteArray(), isString(), readStringChunk()
*/
QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
{
- auto r = _readByteArray_helper();
QCborStreamReader::StringResult<QString> result;
+ auto r = d->readStringChunk(&result.data);
result.status = r.status;
+ if (r.status == Error) {
+ result.data.clear();
+ } else {
+ Q_ASSERT(r.data == result.data.size());
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
+ }
- if (r.status == Ok) {
- // See QUtf8::convertToUnicode() a detailed explanation of why this
- // conversion uses the same number of words or less.
- CborError err = CborNoError;
- if (r.data.size() > MaxStringSize) {
- err = CborErrorDataTooLarge;
- } else {
- QStringConverter::State cs(QStringConverter::Flag::Stateless);
- result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
- if (cs.invalidChars != 0 || cs.remainingChars != 0)
- err = CborErrorInvalidUtf8TextString;
- }
+ return result;
+}
- if (err) {
- d->handleError(err);
- result.data.clear();
- result.status = Error;
- }
+/*!
+ \fn QCborStreamReader::StringResult<QByteArray> QCborStreamReader::readUtf8String()
+ \since 6.7
+
+ Decodes one string chunk from the CBOR string and returns it. This function
+ is used for both regular and chunked string contents, so the caller must
+ always loop around calling this function, even if isLengthKnown() is true.
+ The typical use of this function is as for readString() in the following:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 27
+
+ The readAllUtf8String() function implements the above loop and some extra checks.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \sa readAllString(), readByteArray(), isString(), readStringChunk()
+ */
+QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readUtf8String_helper()
+{
+ using P = QCborStreamReaderPrivate::ReadStringChunk;
+ QCborStreamReader::StringResult<QByteArray> result;
+ auto r = d->readStringChunk(P{ &result.data, P::Utf8String });
+ result.status = r.status;
+ if (r.status == Error) {
+ result.data.clear();
+ } else {
+ Q_ASSERT(r.data == result.data.size());
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
}
+
return result;
}
/*!
- \fn QCborStreamReader::StringResult<QString> QCborStreamReader::readByteArray()
+ \fn QCborStreamReader::StringResult<QByteArray> QCborStreamReader::readByteArray()
Decodes one byte array chunk from the CBOR string and returns it. This
function is used for both regular and chunked contents, so the caller must
- always loop around calling this function, even if isLengthKnown() has
+ always loop around calling this function, even if isLengthKnown()
is true. The typical use of this function is as follows:
\snippet code/src_corelib_serialization_qcborstream.cpp 28
+ The readAllByteArray() function implements the above loop and some extra checks.
+
+//! [bytearray-no-type-conversions]
This function does not perform any type conversions, including from integers
or from strings. Therefore, it may only be called if isByteArray() is true;
calling it in any other condition is an error.
+//! [bytearray-no-type-conversions]
- \sa readString(), isByteArray(), readStringChunk()
+ \sa readAllByteArray(), readString(), isByteArray(), readStringChunk()
*/
QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_helper()
{
QCborStreamReader::StringResult<QByteArray> result;
- result.status = Error;
- qsizetype len = _currentStringChunkSize();
- if (len < 0)
- return result;
- if (len > MaxByteArraySize) {
- d->handleError(CborErrorDataTooLarge);
- return result;
+ auto r = d->readStringChunk(&result.data);
+ result.status = r.status;
+ if (r.status == Error) {
+ result.data.clear();
+ } else {
+ Q_ASSERT(r.data == result.data.size());
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
}
- result.data.resize(len);
- auto r = readStringChunk(result.data.data(), len);
- Q_ASSERT(r.status != Ok || r.data == len);
- result.status = r.status;
return result;
}
@@ -1429,6 +1425,147 @@ qsizetype QCborStreamReader::_currentStringChunkSize() const
return -1;
}
+bool QCborStreamReaderPrivate::readFullString(ReadStringChunk params)
+{
+ auto r = readStringChunk(params);
+ while (r.status == QCborStreamReader::Ok) {
+ // keep appending
+ r = readStringChunk(params);
+ }
+
+ bool ok = r.status == QCborStreamReader::EndOfString;
+ Q_ASSERT(ok == !lastError);
+ return ok;
+}
+
+/*!
+ \fn QCborStreamReader::readAllString()
+ \since 6.7
+
+ Decodes the current text string and returns it. If the string is chunked,
+ this function will iterate over all chunks and concatenate them. If an
+ error happens, this function returns a default-constructed QString(), but
+ that may not be distinguishable from certain empty text strings. Instead,
+ check lastError() to determine if an error has happened.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+//! [note-not-restartable]
+ \note This function cannot be resumed. That is, this function should not
+ be used in contexts where the CBOR data may still be received, for example
+ from a socket or pipe. It should only be used when the full data has
+ already been received and is available in the input QByteArray or
+ QIODevice.
+//! [note-not-restartable]
+
+ \sa readString(), readStringChunk(), isString(), readAllByteArray()
+ */
+/*!
+ \fn QCborStreamReader::readAndAppendToString(QString &dst)
+ \since 6.7
+
+ Decodes the current text string and appends to \a dst. If the string is
+ chunked, this function will iterate over all chunks and concatenate them.
+ If an error happens during decoding, other chunks that could be decoded
+ successfully may have been written to \a dst nonetheless. Returns \c true
+ if the decoding happened without errors, \c false otherwise.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readString(), readStringChunk(), isString(), readAndAppendToByteArray()
+ */
+bool QCborStreamReader::_readAndAppendToString_helper(QString &dst)
+{
+ bool ok = d->readFullString(&dst);
+ if (ok)
+ preparse();
+ return ok;
+}
+
+/*!
+ \fn QCborStreamReader::readAllUtf8String()
+ \since 6.7
+
+ Decodes the current text string and returns it. If the string is chunked,
+ this function will iterate over all chunks and concatenate them. If an
+ error happens, this function returns a default-constructed QString(), but
+ that may not be distinguishable from certain empty text strings. Instead,
+ check lastError() to determine if an error has happened.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readString(), readStringChunk(), isString(), readAllByteArray()
+ */
+/*!
+ \fn QCborStreamReader::readAndAppendToUtf8String(QByteArray &dst)
+ \since 6.7
+
+ Decodes the current text string and appends to \a dst. If the string is
+ chunked, this function will iterate over all chunks and concatenate them.
+ If an error happens during decoding, other chunks that could be decoded
+ successfully may have been written to \a dst nonetheless. Returns \c true
+ if the decoding happened without errors, \c false otherwise.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readString(), readStringChunk(), isString(), readAndAppendToByteArray()
+ */
+bool QCborStreamReader::_readAndAppendToUtf8String_helper(QByteArray &dst)
+{
+ using P = QCborStreamReaderPrivate::ReadStringChunk;
+ bool ok = d->readFullString({ &dst, P::Utf8String });
+ if (ok)
+ preparse();
+ return ok;
+}
+
+/*!
+ \fn QCborStreamReader::readAllByteArray()
+ \since 6.7
+
+ Decodes the current byte string and returns it. If the string is chunked,
+ this function will iterate over all chunks and concatenate them. If an
+ error happens, this function returns a default-constructed QByteArray(),
+ but that may not be distinguishable from certain empty byte strings.
+ Instead, check lastError() to determine if an error has happened.
+
+ \include qcborstreamreader.cpp bytearray-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readByteArray(), readStringChunk(), isByteArray(), readAllString()
+ */
+
+/*!
+ \fn QCborStreamReader::readAndAppendToByteArray(QByteArray &dst)
+ \since 6.7
+
+ Decodes the current byte string and appends to \a dst. If the string is
+ chunked, this function will iterate over all chunks and concatenate them.
+ If an error happens during decoding, other chunks that could be decoded
+ successfully may have been written to \a dst nonetheless. Returns \c true
+ if the decoding happened without errors, \c false otherwise.
+
+ \include qcborstreamreader.cpp bytearray-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readByteArray(), readStringChunk(), isByteArray(), readAndAppendToString()
+ */
+bool QCborStreamReader::_readAndAppendToByteArray_helper(QByteArray &dst)
+{
+ bool ok = d->readFullString(&dst);
+ if (ok)
+ preparse();
+ return ok;
+}
+
/*!
Reads the current string chunk into the buffer pointed to by \a ptr, whose
size is \a maxlen. This function returns a \l StringResult object, with the
@@ -1460,28 +1597,64 @@ qsizetype QCborStreamReader::_currentStringChunkSize() const
QCborStreamReader::StringResult<qsizetype>
QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
{
+ auto r = d->readStringChunk({ptr, maxlen});
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
+ return r;
+}
+
+// used by qcborvalue.cpp
+QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data)
+{
+ return QCborStreamReaderPrivate::appendStringChunk(reader, data);
+}
+
+inline QCborStreamReader::StringResultCode
+QCborStreamReaderPrivate::appendStringChunk(QCborStreamReader &reader, QByteArray *data)
+{
+ auto status = reader.d->readStringChunk(data).status;
+ if (status == QCborStreamReader::EndOfString && reader.lastError() == QCborError::NoError)
+ reader.preparse();
+ return status;
+}
+
+Q_NEVER_INLINE QCborStreamReader::StringResult<qsizetype>
+QCborStreamReaderPrivate::readStringChunk(ReadStringChunk params)
+{
CborError err;
size_t len;
const void *content = nullptr;
QCborStreamReader::StringResult<qsizetype> result;
result.data = 0;
- result.status = Error;
+ result.status = QCborStreamReader::Error;
- d->lastError = {};
- if (!d->ensureStringIteration())
+ lastError = {};
+ if (!ensureStringIteration())
return result;
+ // Note: in the current implementation, the call into TinyCBOR below only
+ // succeeds if we *already* have all the data in memory. That's obvious for
+ // the case of direct memory (no QIODevice), whereas for QIODevices
+ // qt_cbor_decoder_transfer_string() enforces that
+ // QIODevice::bytesAvailable() be bigger than the amount we're about to
+ // read.
+ //
+ // This is an important security gate: if the CBOR stream is corrupt or
+ // malicious, and has an impossibly large string size, we only go past it
+ // if the transfer to the destination buffer will succeed (modulo QIODevice
+ // I/O failures).
+
#if 1
// Using internal TinyCBOR API!
- err = _cbor_value_get_string_chunk(&d->currentElement, &content, &len, &d->currentElement);
+ err = _cbor_value_get_string_chunk(&currentElement, &content, &len, &currentElement);
#else
// the above is effectively the same as:
if (cbor_value_is_byte_string(&currentElement))
- err = cbor_value_get_byte_string_chunk(&d->currentElement, reinterpret_cast<const uint8_t **>(&content),
- &len, &d->currentElement);
+ err = cbor_value_get_byte_string_chunk(&currentElement, reinterpret_cast<const uint8_t **>(&content),
+ &len, &currentElement);
else
- err = cbor_value_get_text_string_chunk(&d->currentElement, reinterpret_cast<const char **>(&content),
- &len, &d->currentElement);
+ err = cbor_value_get_text_string_chunk(&currentElement, reinterpret_cast<const char **>(&content),
+ &len, &currentElement);
#endif
// Range check: using implementation-defined behavior in converting an
@@ -1493,56 +1666,190 @@ QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
if (err) {
if (err == CborErrorNoMoreStringChunks) {
- d->preread();
- err = cbor_value_finish_string_iteration(&d->currentElement);
- result.status = EndOfString;
+ preread();
+ err = cbor_value_finish_string_iteration(&currentElement);
+ result.status = QCborStreamReader::EndOfString;
}
if (err)
- d->handleError(err);
- else
- preparse();
+ handleError(err);
+ // caller musts call preparse()
return result;
}
- // Read the chunk into the user's buffer.
- qint64 actuallyRead;
qptrdiff offset = qptrdiff(content);
+ bufferStart += offset;
+ if (device) {
+ // This first skip can't fail because we've already read this many bytes.
+ device->skip(bufferStart);
+ }
+
+ if (params.isString()) {
+ // readString()
+ result.data = readStringChunk_unicode(params, qsizetype(len));
+ } else if (params.isUtf8String()) {
+ result.data = readStringChunk_utf8(params, qsizetype(len));
+ } else {
+ // readByteArray() or readStringChunk()
+ result.data = readStringChunk_byte(params, qsizetype(len));
+ }
+
+ if (result.data < 0)
+ return result; // error
+
+ // adjust the buffers after we're done reading the string
+ bufferStart += len;
+ if (device) {
+ qsizetype remainingInBuffer = buffer.size() - bufferStart;
+
+ if (remainingInBuffer <= 0) {
+ // We've read from the QIODevice more than what was in the buffer.
+ buffer.truncate(0);
+ } else {
+ // There's still data buffered, but we need to move it around.
+ char *ptr = buffer.data();
+ memmove(ptr, ptr + bufferStart, remainingInBuffer);
+ buffer.truncate(remainingInBuffer);
+ }
+
+ bufferStart = 0;
+ }
+
+ preread();
+ result.status = QCborStreamReader::Ok;
+ return result;
+}
+
+inline qsizetype
+QCborStreamReaderPrivate::readStringChunk_byte(ReadStringChunk params, qsizetype len)
+{
+ qint64 actuallyRead;
qsizetype toRead = qsizetype(len);
- qsizetype left = toRead - maxlen;
- if (left < 0)
- left = 0; // buffer bigger than string
- else
- toRead = maxlen; // buffer smaller than string
+ qsizetype left = 0; // bytes from the chunk not copied to the user buffer, to discard
+ char *ptr = nullptr;
- if (d->device) {
- // This first skip can't fail because we've already read this many bytes.
- d->device->skip(d->bufferStart + qptrdiff(content));
- actuallyRead = d->device->read(ptr, toRead);
+ if (params.isPlainPointer()) {
+ left = toRead - params.maxlen_or_type;
+ if (left < 0)
+ left = 0; // buffer bigger than string
+ else
+ toRead = params.maxlen_or_type; // buffer smaller than string
+ ptr = params.ptr;
+ } else if (!params.isString()) {
+ // See note above on having ensured there is enough incoming data.
+ auto oldSize = params.array->size();
+ auto newSize = oldSize;
+ if (qAddOverflow<decltype(newSize)>(oldSize, toRead, &newSize)) {
+ handleError(CborErrorDataTooLarge);
+ return -1;
+ }
+ QT_TRY {
+ params.array->resize(newSize);
+ } QT_CATCH (const std::bad_alloc &) {
+ // the distinction between DataTooLarge and OOM is mostly for
+ // compatibility with Qt 5; in Qt 6, we could consider everything
+ // to be OOM.
+ handleError(newSize > QByteArray::max_size() ? CborErrorDataTooLarge: CborErrorOutOfMemory);
+ return -1;
+ }
+
+ ptr = const_cast<char *>(params.array->constData()) + oldSize;
+ }
+
+ if (device) {
+ actuallyRead = device->read(ptr, toRead);
if (actuallyRead != toRead) {
actuallyRead = -1;
} else if (left) {
- qint64 skipped = d->device->skip(left);
+ qint64 skipped = device->skip(left);
if (skipped != left)
actuallyRead = -1;
}
if (actuallyRead < 0) {
- d->handleError(CborErrorIO);
- return result;
+ handleError(CborErrorIO);
+ return -1;
}
-
- d->updateBufferAfterString(offset, len);
} else {
actuallyRead = toRead;
- memcpy(ptr, d->buffer.constData() + d->bufferStart + offset, toRead);
- d->bufferStart += QByteArray::size_type(offset + len);
+ memcpy(ptr, buffer.constData() + bufferStart, toRead);
}
- d->preread();
- result.data = actuallyRead;
- result.status = Ok;
- return result;
+ return actuallyRead;
+}
+
+inline qsizetype
+QCborStreamReaderPrivate::readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len)
+{
+ Q_ASSERT(params.isString());
+
+ // See QUtf8::convertToUnicode() a detailed explanation of why this
+ // conversion uses the same number of words or less.
+ qsizetype currentSize = params.string->size();
+ size_t newSize = size_t(utf8len) + size_t(currentSize); // can't overflow
+ if (utf8len > QString::max_size() || qsizetype(newSize) < 0) {
+ handleError(CborErrorDataTooLarge);
+ return -1;
+ }
+ QT_TRY {
+ params.string->resize(qsizetype(newSize));
+ } QT_CATCH (const std::bad_alloc &) {
+ handleError(CborErrorOutOfMemory);
+ return -1;
+ }
+
+ QChar *begin = const_cast<QChar *>(params.string->constData());
+ QChar *ptr = begin + currentSize;
+ QStringConverter::State cs(QStringConverter::Flag::Stateless);
+ if (device == nullptr) {
+ // Easy case: we can decode straight from the buffer we already have
+ ptr = QUtf8::convertToUnicode(ptr, { buffer.constData() + bufferStart, utf8len }, &cs);
+ } else {
+ // read in chunks, to avoid creating large, intermediate buffers
+ constexpr qsizetype StringChunkSize = 16384;
+ qsizetype chunkSize = qMin(StringChunkSize, utf8len);
+ QVarLengthArray<char> chunk(chunkSize);
+
+ cs = { QStringConverter::Flag::ConvertInitialBom };
+ while (utf8len > 0 && cs.invalidChars == 0) {
+ qsizetype toRead = qMin(chunkSize, utf8len);
+ qint64 actuallyRead = device->read(chunk.data(), toRead);
+ if (actuallyRead == toRead)
+ ptr = QUtf8::convertToUnicode(ptr, { chunk.data(), toRead }, &cs);
+
+ if (actuallyRead != toRead) {
+ handleError(CborErrorIO);
+ return -1;
+ }
+ utf8len -= toRead;
+ }
+ }
+
+ if (cs.invalidChars != 0 || cs.remainingChars != 0) {
+ handleError(CborErrorInvalidUtf8TextString);
+ return -1;
+ }
+
+ qsizetype size = ptr - begin;
+ params.string->truncate(ptr - begin);
+ return size - currentSize; // how many bytes we added
+}
+
+inline qsizetype
+QCborStreamReaderPrivate::readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len)
+{
+ qsizetype result = readStringChunk_byte(params, utf8len);
+ if (result < 0)
+ return result;
+
+ // validate the UTF-8 content we've just read
+ QByteArrayView chunk = *params.array;
+ chunk = chunk.last(result);
+ if (QtPrivate::isValidUtf8(chunk))
+ return result;
+
+ handleError(CborErrorInvalidUtf8TextString);
+ return -1;
}
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborstreamreader.h b/src/corelib/serialization/qcborstreamreader.h
index 6d5feccfcf..2666b7c7b2 100644
--- a/src/corelib/serialization/qcborstreamreader.h
+++ b/src/corelib/serialization/qcborstreamreader.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORSTREAMREADER_H
#define QCBORSTREAMREADER_H
@@ -49,8 +13,8 @@
QT_REQUIRE_CONFIG(cborstreamreader);
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
# undef True
# undef False
#endif
@@ -113,7 +77,10 @@ public:
void clear();
void reset();
+#if QT_CORE_REMOVED_SINCE(6, 7)
QCborError lastError();
+#endif
+ QCborError lastError() const;
qint64 currentOffset() const;
@@ -153,7 +120,14 @@ public:
bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
bool leaveContainer();
+ bool readAndAppendToString(QString &dst)
+ { Q_ASSERT(isString()); return _readAndAppendToString_helper(dst); }
+ bool readAndAppendToUtf8String(QByteArray &dst)
+ { Q_ASSERT(isString()); return _readAndAppendToUtf8String_helper(dst); }
+ bool readAndAppendToByteArray(QByteArray &dst)
+ { Q_ASSERT(isByteArray()); return _readAndAppendToByteArray_helper(dst); }
StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
+ StringResult<QByteArray> readUtf8String() { Q_ASSERT(isString()); return _readUtf8String_helper(); }
StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
@@ -175,13 +149,38 @@ public:
return -v - 1;
return v;
}
+ QString readAllString()
+ {
+ QString dst;
+ if (!readAndAppendToString(dst))
+ dst = QString{};
+ return dst;
+ }
+ QByteArray readAllUtf8String()
+ {
+ QByteArray dst;
+ if (!readAndAppendToUtf8String(dst))
+ dst = QByteArray{};
+ return dst;
+ }
+ QByteArray readAllByteArray()
+ {
+ QByteArray dst;
+ if (!readAndAppendToByteArray(dst))
+ dst = QByteArray{};
+ return dst;
+ }
private:
void preparse();
bool _enterContainer_helper();
StringResult<QString> _readString_helper();
+ StringResult<QByteArray> _readUtf8String_helper();
StringResult<QByteArray> _readByteArray_helper();
qsizetype _currentStringChunkSize() const;
+ bool _readAndAppendToString_helper(QString &);
+ bool _readAndAppendToUtf8String_helper(QByteArray &);
+ bool _readAndAppendToByteArray_helper(QByteArray &);
template <typename FP> FP _toFloatingPoint() const noexcept
{
diff --git a/src/corelib/serialization/qcborstreamwriter.cpp b/src/corelib/serialization/qcborstreamwriter.cpp
index 4d6f323e9a..7b5099567e 100644
--- a/src/corelib/serialization/qcborstreamwriter.cpp
+++ b/src/corelib/serialization/qcborstreamwriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborstreamwriter.h"
@@ -43,9 +7,11 @@
#include <private/qcborcommon_p.h>
#include <private/qnumeric_p.h>
+#include <private/qstringconverter_p.h>
#include <qbuffer.h>
#include <qdebug.h>
#include <qstack.h>
+#include <qvarlengtharray.h>
QT_BEGIN_NAMESPACE
@@ -63,16 +29,14 @@ QT_WARNING_POP
// silence compilers that complain about this being a static function declared
// but never defined
-static CborError Q_DECL_UNUSED cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
+[[maybe_unused]] static CborError cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
-static CborError Q_DECL_UNUSED cbor_encode_float_as_half_float(CborEncoder *, float)
+[[maybe_unused]] static CborError cbor_encode_float_as_half_float(CborEncoder *, float)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
@@ -81,6 +45,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\class QCborStreamWriter
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
@@ -92,8 +57,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
Representation, a very compact form of binary data encoding that is
compatible with JSON. It was created by the IETF Constrained RESTful
Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
- protocol}.
+ be used alongside the \l{RFC 7252}{CoAP protocol}.
QCborStreamWriter provides a StAX-like API, similar to that of
\l{QXmlStreamWriter}. It is rather low-level and requires a bit of knowledge
@@ -123,7 +87,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
QCborStreamWriter supports all CBOR features required to create canonical
and strict streams. It implements almost all of the features specified in
- \l {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+ \l {RFC 7049}.
The following table lists the CBOR features that QCborStreamWriter supports.
@@ -151,7 +115,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\section2 Canonical CBOR encoding
Canonical CBOR encoding is defined by
- \l{https://tools.ietf.org/html/rfc7049#section-3.9}{Section 3.9 of RFC
+ \l{RFC 7049, section 3.9}{Section 3.9 of RFC
7049}. Canonical encoding is not a requirement for Qt's CBOR decoding
functionality, but it may be required for some protocols. In particular,
protocols that require the ability to reproduce the same stream identically
@@ -181,7 +145,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\section2 Strict CBOR mode
Strict mode is defined by
- \l{https://tools.ietf.org/html/rfc7049#section-3.10}{Section 3.10 of RFC
+ \l{RFC 7049, section 3.10}{Section 3.10 of RFC
7049}. As for Canonical encoding above, QCborStreamWriter makes it possible
to create strict CBOR streams, but does not require them or validate that
the output is so.
@@ -212,12 +176,14 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\endlist
\sa QCborStreamReader, QCborValue, QXmlStreamWriter
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
class QCborStreamWriterPrivate
{
public:
- static Q_CONSTEXPR quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
+ static constexpr quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
QIODevice *device;
CborEncoder encoder;
@@ -450,11 +416,11 @@ void QCborStreamWriter::append(QCborNegativeInteger n)
/*!
\overload
- Appends the text string \a str to the stream, creating a CBOR Text String
- value. QCborStreamWriter will attempt to write the entire string in one
- chunk.
+ Appends the Latin-1 string viewed by \a str to the stream, creating a CBOR
+ Text String value. QCborStreamWriter will attempt to write the entire string
+ in one chunk.
- The following example appends a simple string to the stream:
+ The following example appends a simple Latin-1 string literal to the stream:
\snippet code/src_corelib_serialization_qcborstream.cpp 8
@@ -467,7 +433,7 @@ void QCborStreamWriter::append(QCborNegativeInteger n)
\sa QCborStreamReader::isString(), QCborStreamReader::readString()
*/
-void QCborStreamWriter::append(QLatin1String str)
+void QCborStreamWriter::append(QLatin1StringView str)
{
// We've got Latin-1 but CBOR wants UTF-8, so check if the string is the
// common subset (US-ASCII).
@@ -475,8 +441,10 @@ void QCborStreamWriter::append(QLatin1String str)
// it is plain US-ASCII
appendTextString(str.latin1(), str.size());
} else {
- // non-ASCII, so we need a pass-through UTF-16
- append(QString(str));
+ // non-ASCII, convert:
+ QVarLengthArray<char> utf8(str.size() * 2); // each L1 char gives at most two U8 units
+ const qsizetype written = QUtf8::convertFromLatin1(utf8.data(), str) - utf8.data();
+ appendTextString(utf8.data(), written);
}
}
@@ -640,11 +608,11 @@ void QCborStreamWriter::appendByteString(const char *data, qsizetype len)
The string pointed to by \a utf8 is expected to be properly encoded UTF-8.
QCborStreamWriter performs no validation that this is the case.
- Unlike the QLatin1String overload of append(), this function is not limited
+ Unlike the QLatin1StringView overload of append(), this function is not limited
to 2 GB. However, note that neither QCborStreamReader::readString() nor
QCborValue support reading CBOR streams with text strings larger than 2 GB.
- \sa append(QLatin1String), append(QStringView),
+ \sa append(QLatin1StringView), append(QStringView),
QCborStreamReader::isString(), QCborStreamReader::readString()
*/
void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
@@ -664,11 +632,11 @@ void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
The string pointed to by \a str is expected to be properly encoded UTF-8.
QCborStreamWriter performs no validation that this is the case.
- Unlike the QLatin1String overload of append(), this function is not limited
+ Unlike the QLatin1StringView overload of append(), this function is not limited
to 2 GB. However, note that neither QCborStreamReader nor QCborValue support
reading CBOR streams with text strings larger than 2 GB.
- \sa append(QLatin1String), append(QStringView),
+ \sa append(QLatin1StringView), append(QStringView),
QCborStreamReader::isString(), QCborStreamReader::readString()
*/
@@ -763,7 +731,8 @@ void QCborStreamWriter::startArray()
seem to allow up to 2\sup{64}-1 elements in the array. However, both
QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{32}-2
items on 32-bit systems and 2\sup{64}-2 items on 64-bit ones. Also note that
- QCborArray is currently limited to 2\sup{27} elements in any platform.
+ QCborArray is currently limited to 2\sup{27} elements on 32-bit platforms and
+ 2\sup{59} elements on 64-bit ones.
\sa startArray(), endArray(), startMap(), QCborStreamReader::isArray(),
QCborStreamReader::isLengthKnown()
@@ -836,7 +805,8 @@ void QCborStreamWriter::startMap()
seem to allow up to 2\sup{64}-1 pairs in the map. However, both
QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{31}-1
items on 32-bit systems and 2\sup{63}-1 items on 64-bit ones. Also note that
- QCborMap is currently limited to 2\sup{26} elements in any platform.
+ QCborMap is currently limited to 2\sup{26} elements on 32-bit platforms and
+ 2\sup{58} on 64-bit ones.
\sa startMap(), endMap(), startArray(), QCborStreamReader::isMap(),
QCborStreamReader::isLengthKnown()
@@ -866,3 +836,7 @@ bool QCborStreamWriter::endMap()
}
QT_END_NAMESPACE
+
+#undef CBOR_ENCODER_WRITER_CONTROL
+#undef CBOR_ENCODER_WRITE_FUNCTION
+#undef CBOR_ENCODER_NO_CHECK_USER
diff --git a/src/corelib/serialization/qcborstreamwriter.h b/src/corelib/serialization/qcborstreamwriter.h
index f8c94ceb93..1018646c99 100644
--- a/src/corelib/serialization/qcborstreamwriter.h
+++ b/src/corelib/serialization/qcborstreamwriter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORSTREAMWRITER_H
#define QCBORSTREAMWRITER_H
@@ -51,8 +15,8 @@
QT_REQUIRE_CONFIG(cborstreamwriter);
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
# undef True
# undef False
#endif
@@ -77,7 +41,7 @@ public:
void append(qint64 i);
void append(QCborNegativeInteger n);
void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
- void append(QLatin1String str);
+ void append(QLatin1StringView str);
void append(QStringView str);
void append(QCborTag tag);
void append(QCborKnownTags tag) { append(QCborTag(tag)); }
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 7e2d8003c7..cd0b842111 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborvalue.h"
#include "qcborvalue_p.h"
@@ -53,7 +17,8 @@
#include <qendian.h>
#include <qlocale.h>
-#include <private/qbytearray_p.h>
+#include <qdatetime.h>
+#include <qtimezone.h>
#include <private/qnumeric_p.h>
#include <private/qsimd_p.h>
@@ -61,21 +26,39 @@
QT_BEGIN_NAMESPACE
+// Worst case memory allocation for a corrupt stream: 256 MB for 32-bit, 1 GB for 64-bit
+static constexpr quint64 MaxAcceptableMemoryUse = (sizeof(void*) == 4 ? 256 : 1024) * 1024 * 1024;
+
+// Internal limits to ensure we don't blow up the memory when parsing a corrupt
+// (possibly crafted to exploit) CBOR stream. The recursion impacts both the
+// maps/arrays we'll open when parsing and the thread's stack, as the parser is
+// itself recursive. If someone really needs more than 1024 layers of nesting,
+// they probably have a weird use-case for which custom parsing and
+// serialisation code would make sense. The limit on element count is the
+// preallocated limit: if the stream does actually have more elements, we will
+// grow the container.
+Q_DECL_UNUSED static constexpr int MaximumRecursionDepth = 1024;
+Q_DECL_UNUSED static constexpr quint64 MaximumPreallocatedElementCount =
+ MaxAcceptableMemoryUse / MaximumRecursionDepth / sizeof(QtCbor::Element) - 1;
+
/*!
\class QCborValue
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
\brief The QCborValue class encapsulates a value in CBOR.
+ \compares strong
+
This class can be used to hold one of the many types available in CBOR.
CBOR is the Concise Binary Object Representation, a very compact form of
binary data encoding that is a superset of JSON. It was created by the IETF
Constrained RESTful Environments (CoRE) WG, which has used it in many
new RFCs. It is meant to be used alongside the
- \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
+ \l{RFC 7252}{CoAP protocol}.
CBOR has three groups of built-in types:
@@ -159,7 +142,7 @@ QT_BEGIN_NAMESPACE
QCborValue supports all CBOR features required to create canonical and
strict streams. It implements almost all of the features specified in \l
- {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+ {RFC 7049}.
The following table lists the CBOR features that QCborValue supports.
@@ -209,8 +192,9 @@ QT_BEGIN_NAMESPACE
array or map it refers to will be modified with the new value. In all other
aspects, its API is identical to QCborValue.
- \sa QCborArray, QCborMap, QCborStreamReader, QCborStreamWriter
- QJsonValue, QJsonDocument
+ \sa QCborArray, QCborMap, QCborStreamReader, QCborStreamWriter,
+ QJsonValue, QJsonDocument, {Serialization Converter}, {Saving and Loading a Game}
+ {Parsing and displaying CBOR data}
*/
/*!
@@ -421,7 +405,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QCborValue::QCborValue(QCborSimpleType st)
- Creates a QCborValue of simple type \a st. The type can later later be retrieved
+ Creates a QCborValue of simple type \a st. The type can later be retrieved
using toSimpleType() as well as isSimpleType(st).
CBOR simple types are types that do not have any associated value, like
@@ -766,6 +750,17 @@ QT_BEGIN_NAMESPACE
using namespace QtCbor;
+static QCborContainerPrivate *assignContainer(QCborContainerPrivate *&d, QCborContainerPrivate *x)
+{
+ if (d == x)
+ return d;
+ if (d)
+ d->deref();
+ if (x)
+ x->ref.ref();
+ return d = x;
+}
+
static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
{
qint64 tag = d->elements.at(0).value;
@@ -793,9 +788,9 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
bool ok = false;
if (e.type == QCborValue::Integer) {
#if QT_POINTER_SIZE == 8
- // we don't have a fast 64-bit mul_overflow implementation on
+ // we don't have a fast 64-bit qMulOverflow implementation on
// 32-bit architectures.
- ok = !mul_overflow(e.value, qint64(1000), &msecs);
+ ok = !qMulOverflow(e.value, qint64(1000), &msecs);
#else
static const qint64 Limit = std::numeric_limits<qint64>::max() / 1000;
ok = (e.value > -Limit && e.value < Limit);
@@ -806,7 +801,7 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs);
}
if (ok)
- dt = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC);
+ dt = QDateTime::fromMSecsSinceEpoch(msecs, QTimeZone::UTC);
}
if (dt.isValid()) {
QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
@@ -895,7 +890,7 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
// no data loss, we could use float
#ifndef QT_BOOTSTRAPPED
if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
- qfloat16 f16 = f;
+ qfloat16 f16 = qfloat16(f);
if (f16 == f)
return writer.append(f16);
}
@@ -909,12 +904,12 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
}
#endif // QT_CONFIG(cborstreamwriter)
-static inline int typeOrder(Element e1, Element e2)
+static inline int typeOrder(QCborValue::Type e1, QCborValue::Type e2)
{
- auto comparable = [](Element e) {
- if (e.type >= 0x10000) // see QCborValue::isTag_helper()
+ auto comparable = [](QCborValue::Type type) {
+ if (type >= 0x10000) // see QCborValue::isTag_helper()
return QCborValue::Tag;
- return e.type;
+ return type;
};
return comparable(e1) - comparable(e2);
}
@@ -928,14 +923,24 @@ QCborContainerPrivate::~QCborContainerPrivate()
}
}
-void QCborContainerPrivate::compact(qsizetype reserved)
+void QCborContainerPrivate::compact()
{
if (usedData > data.size() / 2)
return;
// 50% savings if we recreate the byte data
- // ### TBD
- Q_UNUSED(reserved);
+ QByteArray newData;
+ QByteArray::size_type newUsedData = 0;
+ // Compact only elements that have byte data.
+ // Nested containers will be compacted when their data changes.
+ for (auto &e : elements) {
+ if (e.flags & Element::HasByteData) {
+ if (const ByteData *b = byteData(e))
+ e.value = addByteDataImpl(newData, newUsedData, b->byte(), b->len);
+ }
+ }
+ data = newData;
+ usedData = newUsedData;
}
QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qsizetype reserved)
@@ -943,12 +948,17 @@ QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qs
if (!d) {
d = new QCborContainerPrivate;
} else {
- d = new QCborContainerPrivate(*d);
+ // in case QList::reserve throws
+ QExplicitlySharedDataPointer u(new QCborContainerPrivate(*d));
if (reserved >= 0) {
- d->elements.reserve(reserved);
- d->compact(reserved);
+ u->elements.reserve(reserved);
+ u->compact();
}
- for (auto &e : qAsConst(d->elements)) {
+
+ d = u.take();
+ d->ref.storeRelaxed(0);
+
+ for (auto &e : std::as_const(d->elements)) {
if (e.flags & Element::IsContainer)
e.container->ref.ref();
}
@@ -974,7 +984,7 @@ QCborContainerPrivate *QCborContainerPrivate::grow(QCborContainerPrivate *d, qsi
Q_ASSERT(index >= 0);
d = detach(d, index + 1);
Q_ASSERT(d);
- int j = d->elements.size();
+ qsizetype j = d->elements.size();
while (j++ < index)
d->append(Undefined());
return d;
@@ -1014,10 +1024,23 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
// Copy string data, if any
if (const ByteData *b = value.container->byteData(value.n)) {
- if (this == value.container)
- e.value = addByteData(b->toByteArray(), b->len);
- else
+ const auto flags = e.flags;
+ // The element e has an invalid e.value, because it is copied from
+ // value. It means that calling compact() will trigger an assertion
+ // or just silently corrupt the data.
+ // Temporarily unset the Element::HasByteData flag in order to skip
+ // the element e in the call to compact().
+ e.flags = e.flags & ~Element::HasByteData;
+ if (this == value.container) {
+ const QByteArray valueData = b->toByteArray();
+ compact();
+ e.value = addByteData(valueData, valueData.size());
+ } else {
+ compact();
e.value = addByteData(b->byte(), b->len);
+ }
+ // restore the flags
+ e.flags = flags;
}
if (disp == MoveContainer)
@@ -1042,6 +1065,12 @@ Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(QStringView s)
qt_to_latin1_unchecked(l, s.utf16(), len);
}
+void QCborContainerPrivate::appendNonAsciiString(QStringView s)
+{
+ appendByteData(reinterpret_cast<const char *>(s.utf16()), s.size() * 2,
+ QCborValue::String, QtCbor::Element::StringIsUtf16);
+}
+
QCborValue QCborContainerPrivate::extractAt_complex(Element e)
{
// create a new container for the returned value, containing the byte data
@@ -1054,7 +1083,7 @@ QCborValue QCborContainerPrivate::extractAt_complex(Element e)
// make a shallow copy of the byte data
container->appendByteData(b->byte(), b->len, e.type, e.flags);
usedData -= b->len + qsizetype(sizeof(*b));
- compact(elements.size());
+ compact();
} else {
// just share with the original byte data
container->data = data;
@@ -1065,9 +1094,127 @@ QCborValue QCborContainerPrivate::extractAt_complex(Element e)
return makeValue(e.type, 0, container);
}
+// Similar to QStringIterator::next() but returns malformed surrogate pair
+// itself when one is detected, and returns the length in UTF-8.
+static auto nextUtf32Character(const char16_t *&ptr, const char16_t *end) noexcept
+{
+ Q_ASSERT(ptr != end);
+ struct R {
+ char32_t c;
+ qsizetype len = 1; // in UTF-8 code units (bytes)
+ } r = { *ptr++ };
+
+ if (r.c < 0x0800) {
+ if (r.c >= 0x0080)
+ ++r.len;
+ } else if (!QChar::isHighSurrogate(r.c) || ptr == end) {
+ r.len += 2;
+ } else {
+ r.len += 3;
+ r.c = QChar::surrogateToUcs4(r.c, *ptr++);
+ }
+
+ return r;
+}
+
+static qsizetype stringLengthInUtf8(const char16_t *ptr, const char16_t *end) noexcept
+{
+ qsizetype len = 0;
+ while (ptr < end)
+ len += nextUtf32Character(ptr, end).len;
+ return len;
+}
+
+static int compareStringsInUtf8(QStringView lhs, QStringView rhs, Comparison mode) noexcept
+{
+ if (mode == Comparison::ForEquality)
+ return lhs == rhs ? 0 : 1;
+
+ // The UTF-16 length is *usually* comparable, but not always. There are
+ // pathological cases where they can be wrong, so we need to compare as if
+ // we were doing it in UTF-8. That includes the case of UTF-16 surrogate
+ // pairs, because qstring.cpp sorts them before U+E000-U+FFFF.
+ int diff = 0;
+ qsizetype len1 = 0;
+ qsizetype len2 = 0;
+ const char16_t *src1 = lhs.utf16();
+ const char16_t *src2 = rhs.utf16();
+ const char16_t *end1 = src1 + lhs.size();
+ const char16_t *end2 = src2 + rhs.size();
+
+ // first, scan until we find a difference (if any)
+ do {
+ auto r1 = nextUtf32Character(src1, end1);
+ auto r2 = nextUtf32Character(src2, end2);
+ len1 += r1.len;
+ len2 += r2.len;
+ diff = int(r1.c) - int(r2.c); // no underflow due to limited range
+ } while (src1 < end1 && src2 < end2 && diff == 0);
+
+ // compute the full length past this first difference
+ len1 += stringLengthInUtf8(src1, end1);
+ len2 += stringLengthInUtf8(src2, end2);
+ if (len1 == len2)
+ return diff;
+ return len1 < len2 ? -1 : 1;
+}
+
+static int compareStringsInUtf8(QUtf8StringView lhs, QStringView rhs, Comparison mode) noexcept
+{
+ // CBOR requires that the shortest of the two strings be sorted first, so
+ // we have to calculate the UTF-8 length of the UTF-16 string while
+ // comparing. Unlike the UTF-32 comparison above, we convert the UTF-16
+ // string to UTF-8 so we only need to decode one string.
+
+ const qsizetype len1 = lhs.size();
+ const auto src1 = reinterpret_cast<const uchar *>(lhs.data());
+ const char16_t *src2 = rhs.utf16();
+ const char16_t *const end2 = src2 + rhs.size();
+
+ // Compare the two strings until we find a difference.
+ int diff = 0;
+ qptrdiff idx1 = 0;
+ qsizetype len2 = 0;
+ do {
+ uchar utf8[4]; // longest possible Unicode character in UTF-8
+ uchar *ptr = utf8;
+ char16_t uc = *src2++;
+ int r = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, ptr, src2, end2);
+ Q_UNUSED(r); // ignore failure to encode proper UTF-16 surrogates
+
+ qptrdiff n = ptr - utf8;
+ len2 += n;
+ if (len1 - idx1 < n)
+ return -1; // lhs is definitely shorter
+ diff = memcmp(src1 + idx1, utf8, n);
+ idx1 += n;
+ } while (diff == 0 && idx1 < len1 && src2 < end2);
+
+ if (mode == Comparison::ForEquality && diff)
+ return diff;
+ if ((idx1 == len1) != (src2 == end2)) {
+ // One of the strings ended earlier than the other
+ return idx1 == len1 ? -1 : 1;
+ }
+
+ // We found a difference and neither string ended, so continue calculating
+ // the UTF-8 length of rhs.
+ len2 += stringLengthInUtf8(src2, end2);
+
+ if (len1 != len2)
+ return len1 < len2 ? -1 : 1;
+ return diff;
+}
+
+static int compareStringsInUtf8(QStringView lhs, QUtf8StringView rhs, Comparison mode) noexcept
+{
+ return -compareStringsInUtf8(rhs, lhs, mode);
+}
+
QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
-static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2);
-static int compareElementNoData(const Element &e1, const Element &e2)
+static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2,
+ Comparison mode) noexcept;
+static int compareElementNoData(const Element &e1, const Element &e2) noexcept
{
Q_ASSERT(e1.type == e2.type);
@@ -1080,7 +1227,7 @@ static int compareElementNoData(const Element &e1, const Element &e2)
// -1 -> INT64_MAX + 1 = INT64_MAX - (-1)
// -2 -> INT64_MAX + 2 = INT64_MAX - (-2)
// INT64_MIN -> UINT64_MAX = INT64_MAX - INT64_MIN
- // Note how the unsigned arithmethic is well defined in C++ (it's
+ // Note how the unsigned arithmetic is well defined in C++ (it's
// always performed modulo 2^64).
auto makeSortable = [](qint64 v) {
quint64 u = quint64(v);
@@ -1111,15 +1258,16 @@ static int compareElementNoData(const Element &e1, const Element &e2)
}
static int compareElementRecursive(const QCborContainerPrivate *c1, const Element &e1,
- const QCborContainerPrivate *c2, const Element &e2)
+ const QCborContainerPrivate *c2, const Element &e2,
+ Comparison mode) noexcept
{
- int cmp = typeOrder(e1, e2);
+ int cmp = typeOrder(e1.type, e2.type);
if (cmp != 0)
return cmp;
if ((e1.flags & Element::IsContainer) || (e2.flags & Element::IsContainer))
return compareContainer(e1.flags & Element::IsContainer ? e1.container : nullptr,
- e2.flags & Element::IsContainer ? e2.container : nullptr);
+ e2.flags & Element::IsContainer ? e2.container : nullptr, mode);
// string data?
const ByteData *b1 = c1 ? c1->byteData(e1) : nullptr;
@@ -1127,11 +1275,6 @@ static int compareElementRecursive(const QCborContainerPrivate *c1, const Elemen
if (b1 || b2) {
auto len1 = b1 ? b1->len : 0;
auto len2 = b2 ? b2->len : 0;
-
- if (e1.flags & Element::StringIsUtf16)
- len1 /= 2;
- if (e2.flags & Element::StringIsUtf16)
- len2 /= 2;
if (len1 == 0 || len2 == 0)
return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
@@ -1140,57 +1283,37 @@ static int compareElementRecursive(const QCborContainerPrivate *c1, const Elemen
Q_ASSERT(b2);
// Officially with CBOR, we sort first the string with the shortest
- // UTF-8 length. The length of an ASCII string is the same as its UTF-8
- // and UTF-16 ones, but the UTF-8 length of a string is bigger than the
- // UTF-16 equivalent. Combinations are:
- // 1) UTF-16 and UTF-16
- // 2) UTF-16 and UTF-8 <=== this is the problem case
- // 3) UTF-16 and US-ASCII
- // 4) UTF-8 and UTF-8
- // 5) UTF-8 and US-ASCII
- // 6) US-ASCII and US-ASCII
- if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16)) {
- // Case 1: both UTF-16, so lengths are comparable.
- // (we can't use memcmp in little-endian machines)
- if (len1 == len2)
- return QtPrivate::compareStrings(b1->asStringView(), b2->asStringView());
- return len1 < len2 ? -1 : 1;
- }
+ // UTF-8 length. Since US-ASCII is just a subset of UTF-8, its length
+ // is the UTF-8 length. But the UTF-16 length may not be directly
+ // comparable.
+ if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16))
+ return compareStringsInUtf8(b1->asStringView(), b2->asStringView(), mode);
if (!(e1.flags & Element::StringIsUtf16) && !(e2.flags & Element::StringIsUtf16)) {
- // Cases 4, 5 and 6: neither is UTF-16, so lengths are comparable too
+ // Neither is UTF-16, so lengths are comparable too
// (this case includes byte arrays too)
- if (len1 == len2)
+ if (len1 == len2) {
+ if (mode == Comparison::ForEquality) {
+ // GCC optimizes this to __memcmpeq(); Clang to bcmp()
+ return memcmp(b1->byte(), b2->byte(), size_t(len1)) == 0 ? 0 : 1;
+ }
return memcmp(b1->byte(), b2->byte(), size_t(len1));
+ }
return len1 < len2 ? -1 : 1;
}
- if (!(e1.flags & Element::StringIsAscii) || !(e2.flags & Element::StringIsAscii)) {
- // Case 2: one of them is UTF-8 and the other is UTF-16, so lengths
- // are NOT comparable. We need to convert to UTF-16 first...
- auto string = [](const Element &e, const ByteData *b) {
- return e.flags & Element::StringIsUtf16 ? b->asQStringRaw() : b->toUtf8String();
- };
-
- QString s1 = string(e1, b1);
- QString s2 = string(e2, b2);
- if (s1.size() == s2.size())
- return s1.compare(s2);
- return s1.size() < s2.size() ? -1 : 1;
- }
-
- // Case 3 (UTF-16 and US-ASCII) remains, so lengths are comparable again
- if (len1 != len2)
- return len1 < len2 ? -1 : 1;
+ // Only one is UTF-16
if (e1.flags & Element::StringIsUtf16)
- return QtPrivate::compareStrings(b1->asStringView(), b2->asLatin1());
- return QtPrivate::compareStrings(b1->asLatin1(), b2->asStringView());
+ return compareStringsInUtf8(b1->asStringView(), b2->asUtf8StringView(), mode);
+ else
+ return compareStringsInUtf8(b1->asUtf8StringView(), b2->asStringView(), mode);
}
return compareElementNoData(e1, e2);
}
-static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2)
+static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2,
+ Comparison mode) noexcept
{
auto len1 = c1 ? c1->elements.size() : 0;
auto len2 = c2 ? c2->elements.size() : 0;
@@ -1202,7 +1325,7 @@ static int compareContainer(const QCborContainerPrivate *c1, const QCborContaine
for (qsizetype i = 0; i < len1; ++i) {
const Element &e1 = c1->elements.at(i);
const Element &e2 = c2->elements.at(i);
- int cmp = QCborContainerPrivate::compareElement_helper(c1, e1, c2, e2);
+ int cmp = compareElementRecursive(c1, e1, c2, e2, mode);
if (cmp)
return cmp;
}
@@ -1211,15 +1334,16 @@ static int compareContainer(const QCborContainerPrivate *c1, const QCborContaine
}
inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPrivate *c1, Element e1,
- const QCborContainerPrivate *c2, Element e2)
+ const QCborContainerPrivate *c2, Element e2,
+ Comparison mode) noexcept
{
- return compareElementRecursive(c1, e1, c2, e2);
+ return compareElementRecursive(c1, e1, c2, e2, mode);
}
/*!
- \fn bool QCborValue::operator==(const QCborValue &other) const
+ \fn bool QCborValue::operator==(const QCborValue &lhs, const QCborValue &rhs)
- Compares this value and \a other, and returns true if they hold the same
+ Compares \a lhs and \a rhs, and returns true if they hold the same
contents, false otherwise. If each QCborValue contains an array or map, the
comparison is recursive to elements contained in them.
@@ -1230,9 +1354,9 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
*/
/*!
- \fn bool QCborValue::operator!=(const QCborValue &other) const
+ \fn bool QCborValue::operator!=(const QCborValue &lhs, const QCborValue &rhs)
- Compares this value and \a other, and returns true if contents differ,
+ Compares \a lhs and \a rhs, and returns true if contents differ,
false otherwise. If each QCborValue contains an array or map, the comparison
is recursive to elements contained in them.
@@ -1241,12 +1365,20 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
\sa compare(), QCborValue::operator==(), QCborMap::operator==(),
operator==(), operator<()
*/
+bool comparesEqual(const QCborValue &lhs,
+ const QCborValue &rhs) noexcept
+{
+ Element e1 = QCborContainerPrivate::elementFromValue(lhs);
+ Element e2 = QCborContainerPrivate::elementFromValue(rhs);
+ return compareElementRecursive(lhs.container, e1, rhs.container, e2,
+ Comparison::ForEquality) == 0;
+}
/*!
- \fn bool QCborValue::operator<(const QCborValue &other) const
+ \fn bool QCborValue::operator<(const QCborValue &lhs, const QCborValue &rhs)
- Compares this value and \a other, and returns true if this value should be
- sorted before \a other, false otherwise. If each QCborValue contains an
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted before \a rhs, false otherwise. If each QCborValue contains an
array or map, the comparison is recursive to elements contained in them.
For more information on CBOR sorting order, see QCborValue::compare().
@@ -1256,6 +1388,47 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
*/
/*!
+ \fn bool QCborValue::operator<=(const QCborValue &lhs, const QCborValue &rhs)
+
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted before \a rhs or is being equal to \a rhs, false otherwise.
+ If each QCborValue contains an array or map, the comparison is recursive
+ to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator<(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborValue::operator>(const QCborValue &lhs, const QCborValue &rhs)
+
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted after \a rhs, false otherwise. If each QCborValue contains an
+ array or map, the comparison is recursive to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator>=(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborValue::operator>=(const QCborValue &lhs, const QCborValue &rhs)
+
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted after \a rhs or is being equal to \a rhs, false otherwise.
+ If each QCborValue contains an array or map, the comparison is recursive
+ to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator>(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
Compares this value and \a other, and returns an integer that indicates
whether this value should be sorted prior to (if the result is negative) or
after \a other (if the result is positive). If this function returns 0, the
@@ -1282,8 +1455,8 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
\section3 Sorting order
- Sorting order in CBOR is defined in RFC 7049
- {https://tools.ietf.org/html/rfc7049#section-3.9}{section 3.9}, which
+ Sorting order in CBOR is defined in
+ \l{RFC 7049, section 3.9}, which
discusses the sorting of keys in a map when following the Canonical
encoding. According to the specification, "sorting is performed on the
bytes of the representation of the key data items" and lists as
@@ -1320,17 +1493,59 @@ int QCborValue::compare(const QCborValue &other) const
{
Element e1 = QCborContainerPrivate::elementFromValue(*this);
Element e2 = QCborContainerPrivate::elementFromValue(other);
- return compareElementRecursive(container, e1, other.container, e2);
+ return compareElementRecursive(container, e1, other.container, e2, Comparison::ForOrdering);
+}
+
+bool comparesEqual(const QCborArray &lhs, const QCborArray &rhs) noexcept
+{
+ return compareContainer(lhs.d.constData(), rhs.d.constData(), Comparison::ForEquality) == 0;
}
int QCborArray::compare(const QCborArray &other) const noexcept
{
- return compareContainer(d.data(), other.d.data());
+ return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
+}
+
+bool QCborArray::comparesEqual_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept
+{
+ if (typeOrder(QCborValue::Array, rhs.type()))
+ return false;
+ return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborArray::compareThreeWay_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept
+{
+ int c = typeOrder(QCborValue::Array, rhs.type());
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool comparesEqual(const QCborMap &lhs, const QCborMap &rhs) noexcept
+{
+ return compareContainer(lhs.d.constData(), rhs.d.constData(), Comparison::ForEquality) == 0;
}
int QCborMap::compare(const QCborMap &other) const noexcept
{
- return compareContainer(d.data(), other.d.data());
+ return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
+}
+
+bool QCborMap::comparesEqual_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept
+{
+ if (typeOrder(QCborValue::Map, rhs.type()))
+ return false;
+ return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborMap::compareThreeWay_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept
+{
+ int c = typeOrder(QCborValue::Map, rhs.type());
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
}
#if QT_CONFIG(cborstreamwriter)
@@ -1353,6 +1568,7 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
else
writer.endMap();
} else if (idx < 0) {
+ Q_ASSERT_X(d != nullptr, "QCborValue", "Unexpected null container");
if (d->elements.size() != 2) {
// invalid state!
qWarning("QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
@@ -1363,6 +1579,7 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
writer.append(QCborTag(d->elements.at(0).value));
encodeToCbor(writer, d, 1, opt);
} else {
+ Q_ASSERT_X(d != nullptr, "QCborValue", "Unexpected null container");
// just one element
auto e = d->elements.at(idx);
const ByteData *b = d->byteData(idx);
@@ -1381,7 +1598,7 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
return writer.append(b->asStringView());
return writer.appendTextString(b->byte(), b->len);
}
- return writer.append(QLatin1String());
+ return writer.append(QLatin1StringView());
case QCborValue::Array:
case QCborValue::Map:
@@ -1480,6 +1697,19 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
return e;
}
+// Clamp allocation to avoid crashing due to corrupt stream. This also
+// ensures we never overflow qsizetype. The returned length is doubled for Map
+// entries to account for key-value pairs.
+static qsizetype clampedContainerLength(const QCborStreamReader &reader)
+{
+ if (!reader.isLengthKnown())
+ return 0;
+ int mapShift = reader.isMap() ? 1 : 0;
+ quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift;
+ qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements));
+ return len << mapShift;
+}
+
static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
{
if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
@@ -1488,33 +1718,27 @@ static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &
}
QCborContainerPrivate *d = nullptr;
- int mapShift = reader.isMap() ? 1 : 0;
- if (reader.isLengthKnown()) {
- quint64 len = reader.length();
-
- // Clamp allocation to 1M elements (avoids crashing due to corrupt
- // stream or loss of precision when converting from quint64 to
- // QList::size_type).
- len = qMin(len, quint64(1024 * 1024 - 1));
- if (len) {
- d = new QCborContainerPrivate;
- d->ref.storeRelaxed(1);
- d->elements.reserve(qsizetype(len) << mapShift);
- }
- } else {
- d = new QCborContainerPrivate;
- d->ref.storeRelaxed(1);
+ {
+ // in case QList::reserve throws
+ QExplicitlySharedDataPointer u(new QCborContainerPrivate);
+ if (qsizetype len = clampedContainerLength(reader))
+ u->elements.reserve(len);
+ d = u.take();
}
reader.enterContainer();
- if (reader.lastError() != QCborError::NoError)
+ if (reader.lastError() != QCborError::NoError) {
+ d->elements.clear();
return d;
+ }
while (reader.hasNext() && reader.lastError() == QCborError::NoError)
d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
if (reader.lastError() == QCborError::NoError)
reader.leaveContainer();
+ else
+ d->elements.squeeze();
return d;
}
@@ -1555,41 +1779,10 @@ inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, Q
qt_cbor_stream_set_error(reader.d.data(), error);
}
+extern QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data);
+
void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
{
- auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
- // this duplicates a lot of addByteData, but with overflow checking
- QByteArray::size_type newSize;
- QByteArray::size_type increment = sizeof(QtCbor::ByteData);
- QByteArray::size_type alignment = alignof(QtCbor::ByteData);
- QByteArray::size_type offset = data.size();
-
- // calculate the increment we want
- if (add_overflow(increment, len, &increment))
- return -1;
-
- // align offset
- if (add_overflow(offset, alignment - 1, &offset))
- return -1;
- offset &= ~(alignment - 1);
-
- // and calculate the final size
- if (add_overflow(offset, increment, &newSize))
- return -1;
- if (newSize > MaxByteArraySize)
- return -1;
-
- data.resize(newSize);
- return offset;
- };
- auto dataPtr = [this]() {
- // Null happens when we're reading zero bytes.
- Q_ASSERT(data.isNull() || data.isDetached());
- return const_cast<char *>(data.constData());
- };
-
- Element e = {};
- e.type = (reader.isByteArray() ? QCborValue::ByteArray : QCborValue::String);
if (reader.lastError() != QCborError::NoError)
return;
@@ -1603,56 +1796,73 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
return;
}
- // allocate space, but only if there will be data
- if (len != 0 || !reader.isLengthKnown()) {
- e.flags = Element::HasByteData;
- e.value = addByteData_local(len);
- if (e.value < 0) {
+ Element e = {};
+ e.type = (reader.isByteArray() ? QCborValue::ByteArray : QCborValue::String);
+ if (len || !reader.isLengthKnown()) {
+ // The use of size_t means none of the operations here can overflow because
+ // all inputs are less than half SIZE_MAX.
+ constexpr size_t EstimatedOverhead = 16;
+ constexpr size_t MaxMemoryIncrement = 16384;
+ size_t offset = data.size();
+
+ // add space for aligned ByteData (this can't overflow)
+ offset += sizeof(QtCbor::ByteData) + alignof(QtCbor::ByteData);
+ offset &= ~(alignof(QtCbor::ByteData) - 1);
+ if (offset > size_t(QByteArray::max_size())) {
// overflow
setErrorInReader(reader, { QCborError::DataTooLarge });
return;
}
+
+ // and calculate the size we want to have
+ size_t newCapacity = offset + len; // can't overflow
+ if (size_t(len) > MaxMemoryIncrement - EstimatedOverhead) {
+ // there's a non-zero chance that we won't need this memory at all,
+ // so capa how much we allocate
+ newCapacity = offset + MaxMemoryIncrement - EstimatedOverhead;
+ }
+ if (newCapacity > size_t(QByteArray::max_size())) {
+ // this may cause an allocation failure
+ newCapacity = QByteArray::max_size();
+ }
+ if (newCapacity > size_t(data.capacity()))
+ data.reserve(newCapacity);
+ data.resize(offset + sizeof(QtCbor::ByteData));
+ e.value = offset;
+ e.flags = Element::HasByteData;
}
// read chunks
bool isAscii = (e.type == QCborValue::String);
- auto r = reader.readStringChunk(dataPtr() + e.value + sizeof(ByteData), len);
- while (r.status == QCborStreamReader::Ok) {
+ QCborStreamReader::StringResultCode status = qt_cbor_append_string_chunk(reader, &data);
+ while (status == QCborStreamReader::Ok) {
if (e.type == QCborValue::String && len) {
// verify UTF-8 string validity
- auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
+ auto utf8result = QUtf8::isValidUtf8(QByteArrayView(data).last(len));
if (!utf8result.isValidUtf8) {
- r.status = QCborStreamReader::Error;
+ status = QCborStreamReader::Error;
setErrorInReader(reader, { QCborError::InvalidUtf8String });
break;
}
isAscii = isAscii && utf8result.isValidAscii;
}
- // allocate space for the next chunk
rawlen = reader.currentStringChunkSize();
len = rawlen;
if (len == rawlen) {
- auto oldSize = data.size();
- auto newSize = oldSize;
- if (!add_overflow(newSize, len, &newSize) && newSize < MaxByteArraySize) {
- if (newSize != oldSize)
- data.resize(newSize);
-
- // read the chunk
- r = reader.readStringChunk(dataPtr() + oldSize, len);
- continue;
- }
+ status = qt_cbor_append_string_chunk(reader, &data);
+ } else {
+ // error
+ status = QCborStreamReader::Error;
+ setErrorInReader(reader, { QCborError::DataTooLarge });
}
-
- // error
- r.status = QCborStreamReader::Error;
- setErrorInReader(reader, { QCborError::DataTooLarge });
}
// update size
- if (r.status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
- auto b = new (dataPtr() + e.value) ByteData;
+ if (status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
+ Q_ASSERT(data.isDetached());
+ const char *ptr = data.constData() + e.value;
+ auto b = new (const_cast<char *>(ptr)) ByteData;
b->len = data.size() - e.value - int(sizeof(*b));
usedData += b->len;
@@ -1664,21 +1874,18 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
// check that this UTF-8 text string can be loaded onto a QString
if (e.type == QCborValue::String) {
- if (Q_UNLIKELY(b->len > MaxStringSize)) {
+ if (Q_UNLIKELY(b->len > QString::max_size())) {
setErrorInReader(reader, { QCborError::DataTooLarge });
- r.status = QCborStreamReader::Error;
+ status = QCborStreamReader::Error;
}
}
}
- if (r.status == QCborStreamReader::Error) {
- // There can only be errors if there was data to be read.
- Q_ASSERT(e.flags & Element::HasByteData);
+ if (status == QCborStreamReader::Error) {
data.truncate(e.value);
- return;
+ } else {
+ elements.append(e);
}
-
- elements.append(e);
}
void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
@@ -1727,7 +1934,6 @@ QCborValue::QCborValue(const QByteArray &ba)
container->ref.storeRelaxed(1);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Creates a QCborValue with string value \a s. The value can later be
retrieved using toString().
@@ -1735,7 +1941,6 @@ QCborValue::QCborValue(const QByteArray &ba)
\sa toString(), isString(), isByteArray()
*/
QCborValue::QCborValue(const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
-#endif
/*!
Creates a QCborValue with string value \a s. The value can later be
@@ -1753,12 +1958,12 @@ QCborValue::QCborValue(QStringView s)
/*!
\overload
- Creates a QCborValue with string value \a s. The value can later be
- retrieved using toString().
+ Creates a QCborValue with the Latin-1 string viewed by \a s.
+ The value can later be retrieved using toString().
\sa toString(), isString(), isByteArray()
*/
-QCborValue::QCborValue(QLatin1String s)
+QCborValue::QCborValue(QLatin1StringView s)
: n(0), container(new QCborContainerPrivate), t(String)
{
container->append(s);
@@ -1819,7 +2024,7 @@ QCborValue::QCborValue(QCborTag tag, const QCborValue &tv)
/*!
Copies the contents of \a other into this object.
*/
-QCborValue::QCborValue(const QCborValue &other)
+QCborValue::QCborValue(const QCborValue &other) noexcept
: n(other.n), container(other.container), t(other.t)
{
if (container)
@@ -1864,7 +2069,6 @@ QCborValue::QCborValue(const QUrl &url)
t = Url;
container->elements[1].type = String;
}
-#endif
#if QT_CONFIG(regularexpression)
/*!
@@ -1903,6 +2107,7 @@ QCborValue::QCborValue(const QUuid &uuid)
// change our type
t = Uuid;
}
+#endif
// destructor
void QCborValue::dispose()
@@ -1913,15 +2118,10 @@ void QCborValue::dispose()
/*!
Replaces the contents of this QCborObject with a copy of \a other.
*/
-QCborValue &QCborValue::operator=(const QCborValue &other)
+QCborValue &QCborValue::operator=(const QCborValue &other) noexcept
{
- if (other.container)
- other.container->ref.ref();
- if (container)
- container->deref();
-
n = other.n;
- container = other.container;
+ assignContainer(container, other.container);
t = other.t;
return *this;
}
@@ -2039,7 +2239,6 @@ QUrl QCborValue::toUrl(const QUrl &defaultValue) const
return QUrl::fromEncoded(byteData->asByteArrayView());
}
-#endif
#if QT_CONFIG(regularexpression)
/*!
@@ -2082,6 +2281,7 @@ QUuid QCborValue::toUuid(const QUuid &defaultValue) const
return QUuid::fromRfc4122(byteData->asByteArrayView());
}
+#endif
/*!
\fn QCborArray QCborValue::toArray() const
@@ -2122,7 +2322,8 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
Q_ASSERT(n == -1 || container == nullptr);
if (n < 0)
dd = container;
- return dd ? QCborArray(*dd) : defaultValue;
+ // return QCborArray(*dd); but that's UB if dd is nullptr
+ return dd ? QCborArray(*dd) : QCborArray();
}
/*!
@@ -2164,7 +2365,8 @@ QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
Q_ASSERT(n == -1 || container == nullptr);
if (n < 0)
dd = container;
- return dd ? QCborMap(*dd) : defaultValue;
+ // return QCborMap(*dd); but that's UB if dd is nullptr
+ return dd ? QCborMap(*dd) : QCborMap();
}
/*!
@@ -2181,9 +2383,7 @@ QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
*/
const QCborValue QCborValue::operator[](const QString &key) const
{
- if (isMap())
- return toMap().value(key);
- return QCborValue();
+ return QCborContainerPrivate::findCborMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -2200,11 +2400,9 @@ const QCborValue QCborValue::operator[](const QString &key) const
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-const QCborValue QCborValue::operator[](QLatin1String key) const
+const QCborValue QCborValue::operator[](QLatin1StringView key) const
{
- if (isMap())
- return toMap().value(key);
- return QCborValue();
+ return QCborContainerPrivate::findCborMapKey(*this, key);
}
/*!
@@ -2220,44 +2418,53 @@ const QCborValue QCborValue::operator[](QLatin1String key) const
*/
const QCborValue QCborValue::operator[](qint64 key) const
{
- if (isMap())
- return toMap().value(key);
- if (isArray())
- return toArray().at(key);
- return QCborValue();
+ if (isArray() && container && quint64(key) < quint64(container->elements.size()))
+ return container->valueAt(key);
+ return QCborContainerPrivate::findCborMapKey(*this, key);
}
-/*!
- \internal
- */
-static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
-{
- if (array.size())
- qWarning("Using CBOR array as map forced conversion");
- QCborMap map;
- for (qsizetype i = array.size(); i-- > 0; ) {
- QCborValue entry = array.at(i);
- // Ignore padding entries that may have been added to grow the array
- // when inserting past its end:
- if (!entry.isInvalid())
- map[i] = entry;
- }
- return map;
+static bool shouldArrayRemainArray(qint64 key, QCborValue::Type t, QCborContainerPrivate *container)
+{
+ constexpr qint64 LargeKey = 0x10000;
+ if (t != QCborValue::Array)
+ return false;
+ if (key < 0)
+ return false; // negative keys can't be an array index
+ if (key < LargeKey)
+ return true;
+
+ // Only convert to map if key is greater than array size + 1
+ qsizetype currentSize = container ? container->elements.size() : 0;
+ return key <= currentSize;
}
/*!
\internal
*/
-static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
+static void convertArrayToMap(QCborContainerPrivate *&array)
{
- auto replace = QCborContainerPrivate::detach(container, size);
- Q_ASSERT(replace);
- if (replace != container) {
- if (container)
- container->deref();
- replace->ref.ref();
+ if (Q_LIKELY(!array || array->elements.isEmpty()))
+ return;
+
+ // The Q_LIKELY and the qWarning mark the rest of this function as unlikely
+ qWarning("Using CBOR array as map forced conversion");
+
+ qsizetype size = array->elements.size();
+ QCborContainerPrivate *map = QCborContainerPrivate::detach(array, size * 2);
+ map->elements.resize(size * 2);
+
+ // this may be an in-place copy, so we have to do it from the end
+ auto dst = map->elements.begin();
+ auto src = array->elements.constBegin();
+ for (qsizetype i = size - 1; i >= 0; --i) {
+ Q_ASSERT(src->type != QCborValue::Invalid);
+ dst[i * 2 + 1] = src[i];
}
- return replace;
+ for (qsizetype i = 0; i < size; ++i)
+ dst[i * 2] = { i, QCborValue::Integer };
+
+ // update reference counts
+ assignContainer(array, map);
}
/*!
@@ -2267,16 +2474,48 @@ static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizet
{
auto replace = QCborContainerPrivate::grow(container, index);
Q_ASSERT(replace);
- if (replace != container) {
- if (container)
- container->deref();
- replace->ref.ref();
- }
if (replace->elements.size() == index)
replace->append(Undefined());
else
Q_ASSERT(replace->elements.size() > index);
- return replace;
+ return assignContainer(container, replace);
+}
+
+template <typename KeyType> inline QCborValueRef
+QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
+{
+ // we need a map, so convert if necessary
+ if (self.isArray())
+ convertArrayToMap(self.container);
+ else if (!self.isMap())
+ self = QCborValue(QCborValue::Map);
+ self.t = QCborValue::Map;
+ self.n = -1;
+
+ QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
+ assignContainer(self.container, result.d);
+ return result;
+}
+
+template<typename KeyType> QCborValueRef
+QCborContainerPrivate::findOrAddMapKey(QCborValueRef self, KeyType key)
+{
+ auto &e = self.d->elements[self.i];
+
+ // we need a map, so convert if necessary
+ if (e.type == QCborValue::Array) {
+ convertArrayToMap(e.container);
+ } else if (e.type != QCborValue::Map) {
+ if (e.flags & QtCbor::Element::IsContainer)
+ e.container->deref();
+ e.container = nullptr;
+ }
+ e.flags = QtCbor::Element::IsContainer;
+ e.type = QCborValue::Map;
+
+ QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
+ assignContainer(e.container, result.d);
+ return result;
}
/*!
@@ -2294,30 +2533,7 @@ static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizet
*/
QCborValueRef QCborValue::operator[](const QString &key)
{
- if (!isMap())
- *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
-
- const qsizetype size = container ? container->elements.size() : 0;
- qsizetype index = size + 1;
- bool found = false;
- if (container) {
- QCborMap proxy(*container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- container = maybeDetach(container, size + (found ? 0 : 2));
- Q_ASSERT(container);
- if (!found) {
- container->append(key);
- container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(container->elements.size() & 1));
- Q_ASSERT(index < container->elements.size());
- return { container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -2335,32 +2551,9 @@ QCborValueRef QCborValue::operator[](const QString &key)
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-QCborValueRef QCborValue::operator[](QLatin1String key)
+QCborValueRef QCborValue::operator[](QLatin1StringView key)
{
- if (!isMap())
- *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
-
- const qsizetype size = container ? container->elements.size() : 0;
- qsizetype index = size + 1;
- bool found = false;
- if (container) {
- QCborMap proxy(*container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- container = maybeDetach(container, size + (found ? 0 : 2));
- Q_ASSERT(container);
- if (!found) {
- container->append(key);
- container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(container->elements.size() & 1));
- Q_ASSERT(index < container->elements.size());
- return { container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
@@ -2381,40 +2574,14 @@ QCborValueRef QCborValue::operator[](QLatin1String key)
*/
QCborValueRef QCborValue::operator[](qint64 key)
{
- if (isArray() && key >= 0 && key < 0x10000) {
+ if (shouldArrayRemainArray(key, t, container)) {
container = maybeGrow(container, key);
return { container, qsizetype(key) };
}
- if (!isMap())
- *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
-
- const qsizetype size = container ? container->elements.size() : 0;
- Q_ASSERT(!(size & 1));
- qsizetype index = size + 1;
- bool found = false;
- if (container) {
- QCborMap proxy(*container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- container = maybeDetach(container, size + (found ? 0 : 2));
- Q_ASSERT(container);
- if (!found) {
- container->append(key);
- container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(container->elements.size() & 1));
- Q_ASSERT(index < container->elements.size());
- return { container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
#if QT_CONFIG(cborstreamreader)
-enum { MaximumRecursionDepth = 1024 };
-
/*!
Decodes one item from the CBOR stream found in \a reader and returns the
equivalent representation. This function is recursive: if the item is a map
@@ -2650,10 +2817,12 @@ Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOption
}
}
+# if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
{
concrete().toCbor(writer, opt);
}
+# endif
#endif // QT_CONFIG(cborstreamwriter)
void QCborValueRef::assign(QCborValueRef that, const QCborValue &other)
@@ -2672,6 +2841,151 @@ void QCborValueRef::assign(QCborValueRef that, const QCborValueRef other)
that = other.concrete();
}
+bool QCborValueConstRef::concreteBoolean(QCborValueConstRef self, bool defaultValue) noexcept
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type != QCborValue::False && e.type != QCborValue::True)
+ return defaultValue;
+ return e.type == QCborValue::True;
+}
+
+double QCborValueConstRef::concreteDouble(QCborValueConstRef self, double defaultValue) noexcept
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type == QCborValue::Integer)
+ return e.value;
+ if (e.type != QCborValue::Double)
+ return defaultValue;
+ return e.fpvalue();
+}
+
+qint64 QCborValueConstRef::concreteIntegral(QCborValueConstRef self, qint64 defaultValue) noexcept
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ QCborValue::Type t = e.type;
+ if (t == QCborValue::Double)
+ return e.fpvalue();
+ if (t != QCborValue::Integer)
+ return defaultValue;
+ return e.value;
+}
+
+QByteArray QCborValueConstRef::concreteByteArray(QCborValueConstRef self,
+ const QByteArray &defaultValue)
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type != QCborValue::ByteArray)
+ return defaultValue;
+ return self.d->byteArrayAt(self.i);
+}
+
+QString QCborValueConstRef::concreteString(QCborValueConstRef self, const QString &defaultValue)
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type != QCborValue::String)
+ return defaultValue;
+ return self.d->stringAt(self.i);
+}
+
+bool
+QCborValueConstRef::comparesEqual_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ return compareElementRecursive(lhs.d, e1, rhs.d, e2, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborValueConstRef::compareThreeWay_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ int c = compareElementRecursive(lhs.d, e1, rhs.d, e2, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool
+QCborValueConstRef::comparesEqual_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = QCborContainerPrivate::elementFromValue(rhs);
+ return compareElementRecursive(lhs.d, e1, rhs.container, e2, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborValueConstRef::compareThreeWay_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = QCborContainerPrivate::elementFromValue(rhs);
+ int c = compareElementRecursive(lhs.d, e1, rhs.container, e2, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool QCborArray::comparesEqual_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ if (typeOrder(QCborValue::Array, e2.type))
+ return false;
+ return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborArray::compareThreeWay_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ int c = typeOrder(QCborValue::Array, e2.type);
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool QCborMap::comparesEqual_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ if (typeOrder(QCborValue::Array, e2.type))
+ return false;
+ return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborMap::compareThreeWay_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ int c = typeOrder(QCborValue::Map, e2.type);
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+QCborValue QCborValueConstRef::concrete(QCborValueConstRef self) noexcept
+{
+ return self.d->valueAt(self.i);
+}
+
+QCborValue::Type QCborValueConstRef::concreteType(QCborValueConstRef self) noexcept
+{
+ return self.d->elements.at(self.i).type;
+}
+
+const QCborValue QCborValueConstRef::operator[](const QString &key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+const QCborValue QCborValueConstRef::operator[](const QLatin1StringView key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+const QCborValue QCborValueConstRef::operator[](qint64 key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QCborValue QCborValueRef::concrete(QCborValueRef self) noexcept
{
return self.d->valueAt(self.i);
@@ -2698,8 +3012,7 @@ QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
*/
const QCborValue QCborValueRef::operator[](const QString &key) const
{
- const QCborValue item = d->valueAt(i);
- return item[key];
+ return QCborValueConstRef::operator[](key);
}
/*!
@@ -2718,10 +3031,9 @@ const QCborValue QCborValueRef::operator[](const QString &key) const
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-const QCborValue QCborValueRef::operator[](QLatin1String key) const
+const QCborValue QCborValueRef::operator[](QLatin1StringView key) const
{
- const QCborValue item = d->valueAt(i);
- return item[key];
+ return QCborValueConstRef::operator[](key);
}
/*!
@@ -2738,8 +3050,7 @@ const QCborValue QCborValueRef::operator[](QLatin1String key) const
*/
const QCborValue QCborValueRef::operator[](qint64 key) const
{
- const QCborValue item = d->valueAt(i);
- return item[key];
+ return QCborValueConstRef::operator[](key);
}
/*!
@@ -2758,48 +3069,7 @@ const QCborValue QCborValueRef::operator[](qint64 key) const
*/
QCborValueRef QCborValueRef::operator[](const QString &key)
{
- auto &e = d->elements[i];
- qsizetype size = 0;
- if (e.flags & QtCbor::Element::IsContainer) {
- if (e.container) {
- if (e.type == QCborValue::Array) {
- QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
- qSwap(e.container, repack.container);
- } else if (e.type != QCborValue::Map) {
- e.container->deref();
- e.container = nullptr;
- }
- }
- e.type = QCborValue::Map;
- if (e.container)
- size = e.container->elements.size();
- } else {
- // Stomp any prior e.value, replace with a map (that we'll grow)
- e.container = nullptr;
- e.type = QCborValue::Map;
- e.flags = QtCbor::Element::IsContainer;
- }
-
- qsizetype index = size + 1;
- bool found = false;
- if (e.container) {
- QCborMap proxy(*e.container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- e.container = maybeDetach(e.container, size + (found ? 0 : 2));
- Q_ASSERT(e.container);
- if (!found) {
- e.container->append(key);
- e.container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
- Q_ASSERT(index < e.container->elements.size());
- return { e.container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -2817,50 +3087,9 @@ QCborValueRef QCborValueRef::operator[](const QString &key)
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-QCborValueRef QCborValueRef::operator[](QLatin1String key)
+QCborValueRef QCborValueRef::operator[](QLatin1StringView key)
{
- auto &e = d->elements[i];
- qsizetype size = 0;
- if (e.flags & QtCbor::Element::IsContainer) {
- if (e.container) {
- if (e.type == QCborValue::Array) {
- QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
- qSwap(e.container, repack.container);
- } else if (e.type != QCborValue::Map) {
- e.container->deref();
- e.container = nullptr;
- }
- }
- e.type = QCborValue::Map;
- if (e.container)
- size = e.container->elements.size();
- } else {
- // Stomp any prior e.value, replace with a map (that we'll grow)
- e.container = nullptr;
- e.type = QCborValue::Map;
- e.flags = QtCbor::Element::IsContainer;
- }
-
- qsizetype index = size + 1;
- bool found = false;
- if (e.container) {
- QCborMap proxy(*e.container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- e.container = maybeDetach(e.container, size + (found ? 0 : 2));
- Q_ASSERT(e.container);
- if (!found) {
- e.container->append(key);
- e.container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
- Q_ASSERT(index < e.container->elements.size());
- return { e.container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
@@ -2882,54 +3111,14 @@ QCborValueRef QCborValueRef::operator[](QLatin1String key)
QCborValueRef QCborValueRef::operator[](qint64 key)
{
auto &e = d->elements[i];
- if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) {
+ if (shouldArrayRemainArray(key, e.type, e.container)) {
e.container = maybeGrow(e.container, key);
+ e.flags |= QtCbor::Element::IsContainer;
return { e.container, qsizetype(key) };
}
- qsizetype size = 0;
- if (e.flags & QtCbor::Element::IsContainer) {
- if (e.container) {
- if (e.type == QCborValue::Array) {
- QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
- qSwap(e.container, repack.container);
- } else if (e.type != QCborValue::Map) {
- e.container->deref();
- e.container = nullptr;
- }
- }
- e.type = QCborValue::Map;
- if (e.container)
- size = e.container->elements.size();
- } else {
- // Stomp any prior e.value, replace with a map (that we'll grow)
- e.container = nullptr;
- e.type = QCborValue::Map;
- e.flags = QtCbor::Element::IsContainer;
- }
- Q_ASSERT(!(size & 1));
-
- qsizetype index = size + 1;
- bool found = false;
- if (e.container) {
- QCborMap proxy(*e.container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- e.container = maybeDetach(e.container, size + (found ? 0 : 2));
- Q_ASSERT(e.container);
- if (!found) {
- e.container->append(key);
- e.container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
- Q_ASSERT(index < e.container->elements.size());
- return { e.container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
-
+#endif // < Qt 7
inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
: d(&dd)
@@ -2977,13 +3166,13 @@ size_t qHash(const QCborValue &value, size_t seed)
#ifndef QT_BOOTSTRAPPED
case QCborValue::Url:
return qHash(value.toUrl(), seed);
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
case QCborValue::RegularExpression:
return qHash(value.toRegularExpression(), seed);
-#endif
+# endif
case QCborValue::Uuid:
return qHash(value.toUuid(), seed);
+#endif
case QCborValue::Invalid:
return seed;
default:
@@ -2994,68 +3183,6 @@ size_t qHash(const QCborValue &value, size_t seed)
return qHash(value.toSimpleType(), seed);
}
-#if !defined(QT_NO_DEBUG_STREAM)
-static QDebug debugContents(QDebug &dbg, const QCborValue &v)
-{
- switch (v.type()) {
- case QCborValue::Integer:
- return dbg << v.toInteger();
- case QCborValue::ByteArray:
- return dbg << "QByteArray(" << v.toByteArray() << ')';
- case QCborValue::String:
- return dbg << v.toString();
- case QCborValue::Array:
- return dbg << v.toArray();
- case QCborValue::Map:
- return dbg << v.toMap();
- case QCborValue::Tag:
- dbg << v.tag() << ", ";
- return debugContents(dbg, v.taggedValue());
- case QCborValue::SimpleType:
- break;
- case QCborValue::True:
- return dbg << true;
- case QCborValue::False:
- return dbg << false;
- case QCborValue::Null:
- return dbg << "nullptr";
- case QCborValue::Undefined:
- return dbg;
- case QCborValue::Double: {
- qint64 i = qint64(v.toDouble());
- if (i == v.toDouble())
- return dbg << i << ".0";
- else
- return dbg << v.toDouble();
- }
- case QCborValue::DateTime:
- return dbg << v.toDateTime();
-#ifndef QT_BOOTSTRAPPED
- case QCborValue::Url:
- return dbg << v.toUrl();
-#endif
-#if QT_CONFIG(regularexpression)
- case QCborValue::RegularExpression:
- return dbg << v.toRegularExpression();
-#endif
- case QCborValue::Uuid:
- return dbg << v.toUuid();
- case QCborValue::Invalid:
- return dbg << "<invalid>";
- default:
- break;
- }
- if (v.isSimpleType())
- return dbg << v.toSimpleType();
- return dbg << "<unknown type " << Qt::hex << int(v.type()) << Qt::dec << '>';
-}
-QDebug operator<<(QDebug dbg, const QCborValue &v)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QCborValue(";
- return debugContents(dbg, v) << ')';
-}
-
Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
{
switch (st) {
@@ -3071,16 +3198,6 @@ Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
return nullptr;
}
-QDebug operator<<(QDebug dbg, QCborSimpleType st)
-{
- QDebugStateSaver saver(dbg);
- const char *id = qt_cbor_simpletype_id(st);
- if (id)
- return dbg.nospace() << "QCborSimpleType::" << id;
-
- return dbg.nospace() << "QCborSimpleType(" << uint(st) << ')';
-}
-
Q_CORE_EXPORT const char *qt_cbor_tag_id(QCborTag tag)
{
// Casting to QCborKnownTags's underlying type will make the comparison
@@ -3139,6 +3256,84 @@ Q_CORE_EXPORT const char *qt_cbor_tag_id(QCborTag tag)
return nullptr;
}
+#if !defined(QT_NO_DEBUG_STREAM)
+static QDebug debugContents(QDebug &dbg, const QCborValue &v)
+{
+ switch (v.type()) {
+ case QCborValue::Integer:
+ return dbg << v.toInteger();
+ case QCborValue::ByteArray:
+ return dbg << "QByteArray(" << v.toByteArray() << ')';
+ case QCborValue::String:
+ return dbg << v.toString();
+ case QCborValue::Array:
+ return dbg << v.toArray();
+ case QCborValue::Map:
+ return dbg << v.toMap();
+ case QCborValue::Tag: {
+ QCborTag tag = v.tag();
+ const char *id = qt_cbor_tag_id(tag);
+ if (id)
+ dbg.nospace() << "QCborKnownTags::" << id << ", ";
+ else
+ dbg.nospace() << "QCborTag(" << quint64(tag) << "), ";
+ return dbg << v.taggedValue();
+ }
+ case QCborValue::SimpleType:
+ break;
+ case QCborValue::True:
+ return dbg << true;
+ case QCborValue::False:
+ return dbg << false;
+ case QCborValue::Null:
+ return dbg << "nullptr";
+ case QCborValue::Undefined:
+ return dbg;
+ case QCborValue::Double: {
+ qint64 i;
+ if (convertDoubleTo(v.toDouble(), &i))
+ return dbg << i << ".0";
+ else
+ return dbg << v.toDouble();
+ }
+ case QCborValue::DateTime:
+ return dbg << v.toDateTime();
+#ifndef QT_BOOTSTRAPPED
+ case QCborValue::Url:
+ return dbg << v.toUrl();
+#if QT_CONFIG(regularexpression)
+ case QCborValue::RegularExpression:
+ return dbg << v.toRegularExpression();
+#endif
+ case QCborValue::Uuid:
+ return dbg << v.toUuid();
+#endif
+ case QCborValue::Invalid:
+ return dbg << "<invalid>";
+ default:
+ break;
+ }
+ if (v.isSimpleType())
+ return dbg << v.toSimpleType();
+ return dbg << "<unknown type 0x" << Qt::hex << int(v.type()) << Qt::dec << '>';
+}
+QDebug operator<<(QDebug dbg, const QCborValue &v)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCborValue(";
+ return debugContents(dbg, v) << ')';
+}
+
+QDebug operator<<(QDebug dbg, QCborSimpleType st)
+{
+ QDebugStateSaver saver(dbg);
+ const char *id = qt_cbor_simpletype_id(st);
+ if (id)
+ return dbg.nospace() << "QCborSimpleType::" << id;
+
+ return dbg.nospace() << "QCborSimpleType(" << uint(st) << ')';
+}
+
QDebug operator<<(QDebug dbg, QCborTag tag)
{
QDebugStateSaver saver(dbg);
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index b8c3dce294..93adbec344 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORVALUE_H
#define QCBORVALUE_H
#include <QtCore/qbytearray.h>
-#include <QtCore/qdatetime.h>
#include <QtCore/qcborcommon.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qdatetime.h>
#if QT_CONFIG(regularexpression)
# include <QtCore/qregularexpression.h>
#endif
@@ -52,16 +17,12 @@
#include <QtCore/quuid.h>
#include <QtCore/qvariant.h>
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
# undef True
# undef False
#endif
-#if 0 && __has_include(<compare>)
-# include <compare>
-#endif
-
QT_BEGIN_NAMESPACE
class QCborArray;
@@ -146,11 +107,9 @@ public:
QCborValue(QCborSimpleType st) : t(type_helper(st)) {}
QCborValue(const QByteArray &ba);
-#if QT_STRINGVIEW_LEVEL < 2
QCborValue(const QString &s);
-#endif
QCborValue(QStringView s);
- QCborValue(QLatin1String s);
+ QCborValue(QLatin1StringView s);
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN QCborValue(const char *s) : QCborValue(QString::fromUtf8(s)) {}
#endif
@@ -166,37 +125,30 @@ public:
explicit QCborValue(const QDateTime &dt);
#ifndef QT_BOOTSTRAPPED
explicit QCborValue(const QUrl &url);
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
explicit QCborValue(const QRegularExpression &rx);
-#endif
+# endif
explicit QCborValue(const QUuid &uuid);
+#endif
~QCborValue() { if (container) dispose(); }
// make sure const char* doesn't go call the bool constructor
QCborValue(const void *) = delete;
- QCborValue(const QCborValue &other);
+ QCborValue(const QCborValue &other) noexcept;
QCborValue(QCborValue &&other) noexcept
- : n(other.n), container(other.container), t(other.t)
+ : n(other.n), container(std::exchange(other.container, nullptr)), t(std::exchange(other.t, Undefined))
{
- other.t = Undefined;
- other.container = nullptr;
- }
- QCborValue &operator=(const QCborValue &other);
- QCborValue &operator=(QCborValue &&other) noexcept
- {
- QCborValue tmp(std::move(other));
- swap(tmp);
- return *this;
}
+ QCborValue &operator=(const QCborValue &other) noexcept;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCborValue)
void swap(QCborValue &other) noexcept
{
- qSwap(n, other.n);
- qSwap(container, other.container);
- qSwap(t, other.t);
+ std::swap(n, other.n);
+ qt_ptr_swap(container, other.container);
+ std::swap(t, other.t);
}
Type type() const { return t; }
@@ -245,11 +197,13 @@ public:
QByteArray toByteArray(const QByteArray &defaultValue = {}) const;
QString toString(const QString &defaultValue = {}) const;
QDateTime toDateTime(const QDateTime &defaultValue = {}) const;
+#ifndef QT_BOOTSTRAPPED
QUrl toUrl(const QUrl &defaultValue = {}) const;
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const;
-#endif
+# endif
QUuid toUuid(const QUuid &defaultValue = {}) const;
+#endif
// only forward-declared, need split functions
QCborArray toArray() const;
@@ -258,26 +212,18 @@ public:
QCborMap toMap(const QCborMap &defaultValue) const;
const QCborValue operator[](const QString &key) const;
- const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](QLatin1StringView key) const;
const QCborValue operator[](qint64 key) const;
QCborValueRef operator[](qint64 key);
- QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](QLatin1StringView key);
QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const;
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborValue &other) const
- {
- int c = compare(other);
- if (c > 0) return std::partial_ordering::greater;
- if (c == 0) return std::partial_ordering::equivalent;
- return std::partial_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborValue &other) const noexcept
{ return compare(other) == 0; }
bool operator!=(const QCborValue &other) const noexcept
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborValue &other) const
{ return compare(other) < 0; }
#endif
@@ -303,6 +249,19 @@ public:
QString toDiagnosticNotation(DiagnosticNotationOptions opts = Compact) const;
private:
+ friend Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+ bool comparesEqual(const QCborValue &lhs, const QCborValue &rhs) noexcept;
+ friend Qt::strong_ordering compareThreeWay(const QCborValue &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ int c = lhs.compare(rhs);
+ return Qt::compareThreeWay(c, 0);
+ }
+
+ Q_DECLARE_STRONGLY_ORDERED(QCborValue)
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborValueConstRef;
friend class QCborValueRef;
friend class QCborContainerPrivate;
friend class QJsonPrivate::Value;
@@ -325,23 +284,172 @@ private:
return d;
}
- Q_DECL_CONSTEXPR static Type type_helper(QCborSimpleType st)
+ constexpr static Type type_helper(QCborSimpleType st)
{
return Type(quint8(st) | SimpleType);
}
- Q_DECL_CONSTEXPR static bool isTag_helper(Type tt)
+ constexpr static bool isTag_helper(Type tt)
{
return tt == Tag || tt >= 0x10000;
}
};
Q_DECLARE_SHARED(QCborValue)
-class Q_CORE_EXPORT QCborValueRef
+class QCborValueConstRef
{
public:
+ QCborValueConstRef(const QCborValueConstRef &) = default;
+ QCborValueConstRef &operator=(const QCborValueConstRef &) = delete;
operator QCborValue() const { return concrete(); }
+ QCborValue::Type type() const { return concreteType(*this); }
+ bool isInteger() const { return type() == QCborValue::Integer; }
+ bool isByteArray() const { return type() == QCborValue::ByteArray; }
+ bool isString() const { return type() == QCborValue::String; }
+ bool isArray() const { return type() == QCborValue::Array; }
+ bool isMap() const { return type() == QCborValue::Map; }
+ bool isTag() const { return concrete().isTag(); }
+ bool isFalse() const { return type() == QCborValue::False; }
+ bool isTrue() const { return type() == QCborValue::True; }
+ bool isBool() const { return isFalse() || isTrue(); }
+ bool isNull() const { return type() == QCborValue::Null; }
+ bool isUndefined() const { return type() == QCborValue::Undefined; }
+ bool isDouble() const { return type() == QCborValue::Double; }
+ bool isDateTime() const { return type() == QCborValue::DateTime; }
+ bool isUrl() const { return type() == QCborValue::Url; }
+ bool isRegularExpression() const { return type() == QCborValue::RegularExpression; }
+ bool isUuid() const { return type() == QCborValue::Uuid; }
+ bool isInvalid() const { return type() == QCborValue::Invalid; }
+ bool isContainer() const { return isMap() || isArray(); }
+ bool isSimpleType() const { return concrete().isSimpleType(); }
+ bool isSimpleType(QCborSimpleType st) const { return concrete().isSimpleType(st); }
+
+ QCborSimpleType toSimpleType(QCborSimpleType defaultValue = QCborSimpleType::Undefined) const
+ {
+ return concrete().toSimpleType(defaultValue);
+ }
+
+ QCborTag tag(QCborTag defaultValue = QCborTag(-1)) const
+ { return concrete().tag(defaultValue); }
+ QCborValue taggedValue(const QCborValue &defaultValue = QCborValue()) const
+ { return concrete().taggedValue(defaultValue); }
+
+ qint64 toInteger(qint64 defaultValue = 0) const
+ { return concrete().toInteger(defaultValue); }
+ bool toBool(bool defaultValue = false) const
+ { return concrete().toBool(defaultValue); }
+ double toDouble(double defaultValue = 0) const
+ { return concrete().toDouble(defaultValue); }
+
+ QByteArray toByteArray(const QByteArray &defaultValue = {}) const
+ { return concrete().toByteArray(defaultValue); }
+ QString toString(const QString &defaultValue = {}) const
+ { return concrete().toString(defaultValue); }
+ QDateTime toDateTime(const QDateTime &defaultValue = {}) const
+ { return concrete().toDateTime(defaultValue); }
+#ifndef QT_BOOTSTRAPPED
+ QUrl toUrl(const QUrl &defaultValue = {}) const
+ { return concrete().toUrl(defaultValue); }
+# if QT_CONFIG(regularexpression)
+ QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const
+ { return concrete().toRegularExpression(defaultValue); }
+# endif
+ QUuid toUuid(const QUuid &defaultValue = {}) const
+ { return concrete().toUuid(defaultValue); }
+#endif
+
+ // only forward-declared, need split functions. Implemented in qcbor{array,map}.h
+ inline QCborArray toArray() const;
+ inline QCborArray toArray(const QCborArray &a) const;
+ inline QCborMap toMap() const;
+ inline QCborMap toMap(const QCborMap &m) const;
+
+ Q_CORE_EXPORT const QCborValue operator[](const QString &key) const;
+ Q_CORE_EXPORT const QCborValue operator[](QLatin1StringView key) const;
+ Q_CORE_EXPORT const QCborValue operator[](qint64 key) const;
+
+ int compare(const QCborValue &other) const
+ { return concrete().compare(other); }
+
+ QVariant toVariant() const { return concrete().toVariant(); }
+ inline QJsonValue toJsonValue() const; // in qjsonvalue.h
+
+#if QT_CONFIG(cborstreamwriter)
+ QByteArray toCbor(QCborValue::EncodingOptions opt = QCborValue::NoTransformation) const
+ { return concrete().toCbor(opt); }
+ void toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt = QCborValue::NoTransformation) const
+ { return concrete().toCbor(writer, opt); }
+#endif
+
+ QString toDiagnosticNotation(QCborValue::DiagnosticNotationOptions opt = QCborValue::Compact) const
+ { return concrete().toDiagnosticNotation(opt); }
+
+protected:
+ friend class QCborValue;
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborContainerPrivate;
+
+ QCborValue concrete() const noexcept { return concrete(*this); }
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept;
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept;
+ friend bool comparesEqual(const QCborValueConstRef &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborValueConstRef &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborValueConstRef)
+
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept;
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept;
+ friend bool comparesEqual(const QCborValueConstRef &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborValueConstRef &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborValueConstRef, QCborValue)
+
+ static Q_CORE_EXPORT QCborValue concrete(QCborValueConstRef that) noexcept;
+ static Q_CORE_EXPORT QCborValue::Type concreteType(QCborValueConstRef that) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT bool
+ concreteBoolean(QCborValueConstRef that, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT double
+ concreteDouble(QCborValueConstRef that, double defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT qint64
+ concreteIntegral(QCborValueConstRef that, qint64 defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT QByteArray
+ concreteByteArray(QCborValueConstRef that, const QByteArray &defaultValue);
+ static Q_CORE_EXPORT QString
+ concreteString(QCborValueConstRef that, const QString &defaultValue);
+
+ constexpr QCborValueConstRef() : d(nullptr), i(0) {} // this will actually be invalid
+ constexpr QCborValueConstRef(QCborContainerPrivate *dd, qsizetype ii)
+ : d(dd), i(ii)
+ {}
+ QCborContainerPrivate *d;
+ qsizetype i;
+};
+
+QT_WARNING_PUSH
+QT6_ONLY(QT_WARNING_DISABLE_MSVC(4275)) // non dll-interface class 'QJsonValueConstRef' used as base for dll-interface class 'QJsonValueRef'
+class QT6_ONLY(Q_CORE_EXPORT) QCborValueRef : public QCborValueConstRef
+{
+public:
QCborValueRef(const QCborValueRef &) noexcept = default;
QCborValueRef(QCborValueRef &&) noexcept = default;
QCborValueRef &operator=(const QCborValue &other)
@@ -351,6 +459,15 @@ public:
QCborValueRef &operator=(const QCborValueRef &other)
{ assign(*this, other); return *this; }
+ QT7_ONLY(Q_CORE_EXPORT) QCborValueRef operator[](qint64 key);
+ QT7_ONLY(Q_CORE_EXPORT) QCborValueRef operator[](QLatin1StringView key);
+ QT7_ONLY(Q_CORE_EXPORT) QCborValueRef operator[](const QString & key);
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ // retained for binary compatibility (due to the Q_CORE_EXPORT) because at
+ // least one compiler emits and exports all inlines in an exported class
+
+ operator QCborValue() const { return concrete(); }
QCborValue::Type type() const { return concreteType(); }
bool isInteger() const { return type() == QCborValue::Integer; }
bool isByteArray() const { return type() == QCborValue::ByteArray; }
@@ -378,6 +495,10 @@ public:
{
return type() == QCborValue::type_helper(st);
}
+ QCborSimpleType toSimpleType(QCborSimpleType defaultValue = QCborSimpleType::Undefined) const
+ {
+ return isSimpleType() ? QCborSimpleType(type() & 0xff) : defaultValue;
+ }
QCborTag tag(QCborTag defaultValue = QCborTag(-1)) const
{ return concrete().tag(defaultValue); }
@@ -385,28 +506,28 @@ public:
{ return concrete().taggedValue(defaultValue); }
qint64 toInteger(qint64 defaultValue = 0) const
- { return concrete().toInteger(defaultValue); }
+ { return concreteIntegral(*this, defaultValue); }
bool toBool(bool defaultValue = false) const
- { return concrete().toBool(defaultValue); }
+ { return concreteBoolean(*this, defaultValue); }
double toDouble(double defaultValue = 0) const
- { return concrete().toDouble(defaultValue); }
+ { return concreteDouble(*this, defaultValue); }
QByteArray toByteArray(const QByteArray &defaultValue = {}) const
- { return concrete().toByteArray(defaultValue); }
+ { return concreteByteArray(*this, defaultValue); }
QString toString(const QString &defaultValue = {}) const
- { return concrete().toString(defaultValue); }
+ { return concreteString(*this, defaultValue); }
QDateTime toDateTime(const QDateTime &defaultValue = {}) const
{ return concrete().toDateTime(defaultValue); }
#ifndef QT_BOOTSTRAPPED
QUrl toUrl(const QUrl &defaultValue = {}) const
{ return concrete().toUrl(defaultValue); }
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const
{ return concrete().toRegularExpression(defaultValue); }
-#endif
+# endif
QUuid toUuid(const QUuid &defaultValue = {}) const
{ return concrete().toUuid(defaultValue); }
+#endif
// only forward-declared, need split functions. Implemented in qcbor{array,map}.h
QCborArray toArray() const;
@@ -415,27 +536,16 @@ public:
QCborMap toMap(const QCborMap &m) const;
const QCborValue operator[](const QString &key) const;
- const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](QLatin1StringView key) const;
const QCborValue operator[](qint64 key) const;
- QCborValueRef operator[](qint64 key);
- QCborValueRef operator[](QLatin1String key);
- QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const
{ return concrete().compare(other); }
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborValue &other) const
- {
- int c = compare(other);
- if (c > 0) return std::strong_ordering::greater;
- if (c == 0) return std::strong_ordering::equivalent;
- return std::strong_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborValue &other) const
{ return compare(other) == 0; }
bool operator!=(const QCborValue &other) const
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborValue &other) const
{ return compare(other) < 0; }
#endif
@@ -444,25 +554,17 @@ public:
QJsonValue toJsonValue() const;
#if QT_CONFIG(cborstreamwriter)
+ using QCborValueConstRef::toCbor;
QByteArray toCbor(QCborValue::EncodingOptions opt = QCborValue::NoTransformation)
- { return concrete().toCbor(opt); }
+ { return std::as_const(*this).toCbor(opt); }
void toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt = QCborValue::NoTransformation);
#endif
+ using QCborValueConstRef::toDiagnosticNotation;
QString toDiagnosticNotation(QCborValue::DiagnosticNotationOptions opt = QCborValue::Compact)
- { return concrete().toDiagnosticNotation(opt); }
+ { return std::as_const(*this).toDiagnosticNotation(opt); }
private:
- friend class QCborValue;
- friend class QCborArray;
- friend class QCborMap;
- friend class QCborContainerPrivate;
- friend class QCborValueRefPtr;
-
- // static so we can pass this by value
- static void assign(QCborValueRef that, const QCborValue &other);
- static void assign(QCborValueRef that, QCborValue &&other);
- static void assign(QCborValueRef that, const QCborValueRef other);
static QCborValue concrete(QCborValueRef that) noexcept;
QCborValue concrete() const noexcept { return concrete(*this); }
@@ -470,14 +572,30 @@ private:
QCborValue::Type concreteType() const noexcept { return concreteType(*this); }
// this will actually be invalid...
- Q_DECL_CONSTEXPR QCborValueRef() : d(nullptr), i(0) {}
+ constexpr QCborValueRef() : QCborValueConstRef(nullptr, 0) {}
QCborValueRef(QCborContainerPrivate *dd, qsizetype ii)
- : d(dd), i(ii)
+ : QCborValueConstRef(dd, ii)
{}
- QCborContainerPrivate *d;
- qsizetype i;
+#else
+private:
+ using QCborValueConstRef::QCborValueConstRef;
+#endif // < Qt 7
+
+ friend class QCborValue;
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborContainerPrivate;
+ friend class QCborValueConstRef;
+
+ // static so we can pass this by value
+ QT7_ONLY(Q_CORE_EXPORT) static void assign(QCborValueRef that, const QCborValue &other);
+ QT7_ONLY(Q_CORE_EXPORT) static void assign(QCborValueRef that, QCborValue &&other);
+ QT7_ONLY(Q_CORE_EXPORT) static void assign(QCborValueRef that, const QCborValueRef other);
};
+QT_WARNING_POP
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCborValue::EncodingOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCborValue::DiagnosticNotationOptions)
Q_CORE_EXPORT size_t qHash(const QCborValue &value, size_t seed = 0);
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
index 3b1e45a2a8..33eb912a6d 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORVALUE_P_H
#define QCBORVALUE_P_H
@@ -53,6 +17,10 @@
#include "qcborvalue.h"
+#if QT_CONFIG(cborstreamreader)
+# include "qcborstreamreader.h"
+#endif
+
#include <private/qglobal_p.h>
#include <private/qstringconverter_p.h>
@@ -61,6 +29,11 @@
QT_BEGIN_NAMESPACE
namespace QtCbor {
+enum class Comparison {
+ ForEquality,
+ ForOrdering,
+};
+
struct Undefined {};
struct Element
{
@@ -111,7 +84,8 @@ struct ByteData
QString toUtf8String() const { return QString::fromUtf8(byte(), len); }
QByteArray asByteArrayView() const { return QByteArray::fromRawData(byte(), len); }
- QLatin1String asLatin1() const { return QLatin1String(byte(), len); }
+ QLatin1StringView asLatin1() const { return {byte(), len}; }
+ QUtf8StringView asUtf8StringView() const { return QUtf8StringView(byte(), len); }
QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
};
@@ -134,18 +108,19 @@ public:
QList<QtCbor::Element> elements;
void deref() { if (!ref.deref()) delete this; }
- void compact(qsizetype reserved);
+ void compact();
static QCborContainerPrivate *clone(QCborContainerPrivate *d, qsizetype reserved = -1);
static QCborContainerPrivate *detach(QCborContainerPrivate *d, qsizetype reserved);
static QCborContainerPrivate *grow(QCborContainerPrivate *d, qsizetype index);
- qptrdiff addByteData(const char *block, qsizetype len)
+ static qptrdiff addByteDataImpl(QByteArray &target, QByteArray::size_type &targetUsed,
+ const char *block, qsizetype len)
{
// This function does not do overflow checking, since the len parameter
// is expected to be trusted. There's another version of this function
// in decodeStringFromCbor(), which checks.
- qptrdiff offset = data.size();
+ qptrdiff offset = target.size();
// align offset
offset += alignof(QtCbor::ByteData) - 1;
@@ -153,10 +128,10 @@ public:
qptrdiff increment = qptrdiff(sizeof(QtCbor::ByteData)) + len;
- usedData += increment;
- data.resize(offset + increment);
+ targetUsed += increment;
+ target.resize(offset + increment);
- char *ptr = data.begin() + offset;
+ char *ptr = target.begin() + offset;
auto b = new (ptr) QtCbor::ByteData;
b->len = len;
if (block)
@@ -165,6 +140,11 @@ public:
return offset;
}
+ qptrdiff addByteData(const char *block, qsizetype len)
+ {
+ return addByteDataImpl(data, usedData, block, len);
+ }
+
const QtCbor::ByteData *byteData(QtCbor::Element e) const
{
if ((e.flags & QtCbor::Element::HasByteData) == 0)
@@ -215,7 +195,7 @@ public:
}
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
{
- replaceAt_internal(*elements.insert(elements.begin() + int(idx), {}), value, disp);
+ replaceAt_internal(*elements.insert(idx, {}), value, disp);
}
void append(QtCbor::Undefined)
@@ -245,31 +225,29 @@ public:
{
appendByteData(str, len, QCborValue::String);
}
- void append(QLatin1String s)
+ void append(QLatin1StringView s)
{
if (!QtPrivate::isAscii(s))
- return append(QString(s));
+ return appendNonAsciiString(QString(s));
// US-ASCII is a subset of UTF-8, so we can keep in 8-bit
appendByteData(s.latin1(), s.size(), QCborValue::String,
QtCbor::Element::StringIsAscii);
}
void appendAsciiString(QStringView s);
+ void appendNonAsciiString(QStringView s);
-#if QT_STRINGVIEW_LEVEL < 2
void append(const QString &s)
{
append(qToStringViewIgnoringNull(s));
}
-#endif
void append(QStringView s)
{
if (QtPrivate::isAscii(s))
appendAsciiString(s);
else
- appendByteData(reinterpret_cast<const char *>(s.utf16()), s.size() * 2,
- QCborValue::String, QtCbor::Element::StringIsUtf16);
+ appendNonAsciiString(s);
}
void append(const QCborValue &v)
{
@@ -362,18 +340,18 @@ public:
return e;
}
- static int compareUtf8(const QtCbor::ByteData *b, const QLatin1String &s)
+ static int compareUtf8(const QtCbor::ByteData *b, QLatin1StringView s)
{
- return QUtf8::compareUtf8(b->byte(), b->len, s);
+ return QUtf8::compareUtf8(QByteArrayView(b->byte(), b->len), s);
}
static int compareUtf8(const QtCbor::ByteData *b, QStringView s)
{
- return QUtf8::compareUtf8(b->byte(), b->len, s.data(), s.size());
+ return QUtf8::compareUtf8(QByteArrayView(b->byte(), b->len), s);
}
template<typename String>
- int stringCompareElement(const QtCbor::Element &e, String s) const
+ int stringCompareElement(const QtCbor::Element &e, String s, QtCbor::Comparison mode) const
{
if (e.type != QCborValue::String)
return int(e.type) - int(QCborValue::String);
@@ -382,15 +360,18 @@ public:
if (!b)
return s.isEmpty() ? 0 : -1;
- if (e.flags & QtCbor::Element::StringIsUtf16)
+ if (e.flags & QtCbor::Element::StringIsUtf16) {
+ if (mode == QtCbor::Comparison::ForEquality)
+ return QtPrivate::equalStrings(b->asStringView(), s) ? 0 : 1;
return QtPrivate::compareStrings(b->asStringView(), s);
+ }
return compareUtf8(b, s);
}
template<typename String>
bool stringEqualsElement(const QtCbor::Element &e, String s) const
{
- return stringCompareElement(e, s) == 0;
+ return stringCompareElement(e, s, QtCbor::Comparison::ForEquality) == 0;
}
template<typename String>
@@ -400,12 +381,13 @@ public:
}
static int compareElement_helper(const QCborContainerPrivate *c1, QtCbor::Element e1,
- const QCborContainerPrivate *c2, QtCbor::Element e2);
- int compareElement(qsizetype idx, const QCborValue &value) const
+ const QCborContainerPrivate *c2, QtCbor::Element e2,
+ QtCbor::Comparison mode) noexcept;
+ int compareElement(qsizetype idx, const QCborValue &value, QtCbor::Comparison mode) const
{
auto &e1 = elements.at(idx);
auto e2 = elementFromValue(value);
- return compareElement_helper(this, e1, value.container, e2);
+ return compareElement_helper(this, e1, value.container, e2, mode);
}
void removeAt(qsizetype idx)
@@ -414,9 +396,67 @@ public:
elements.remove(idx);
}
- void decodeValueFromCbor(QCborStreamReader &reader, int remainiingStackDepth);
+ // doesn't apply to JSON
+ template <typename KeyType> QCborValueConstRef findCborMapKey(KeyType key)
+ {
+ qsizetype i = 0;
+ for ( ; i < elements.size(); i += 2) {
+ const auto &e = elements.at(i);
+ bool equals;
+ if constexpr (std::is_same_v<std::decay_t<KeyType>, QCborValue>) {
+ equals = (compareElement(i, key, QtCbor::Comparison::ForEquality) == 0);
+ } else if constexpr (std::is_integral_v<KeyType>) {
+ equals = (e.type == QCborValue::Integer && e.value == key);
+ } else {
+ // assume it's a string
+ equals = stringEqualsElement(i, key);
+ }
+ if (equals)
+ break;
+ }
+ return { this, i + 1 };
+ }
+ template <typename KeyType> static QCborValue findCborMapKey(const QCborValue &self, KeyType key)
+ {
+ if (self.isMap() && self.container) {
+ qsizetype idx = self.container->findCborMapKey(key).i;
+ if (idx < self.container->elements.size())
+ return self.container->valueAt(idx);
+ }
+ return QCborValue();
+ }
+ template <typename KeyType> static QCborValueRef
+ findOrAddMapKey(QCborContainerPrivate *container, KeyType key)
+ {
+ qsizetype size = 0;
+ qsizetype index = size + 1;
+ if (container) {
+ size = container->elements.size();
+ index = container->findCborMapKey<KeyType>(key).i; // returns size + 1 if not found
+ }
+ Q_ASSERT(index & 1);
+ Q_ASSERT((size & 1) == 0);
+
+ container = detach(container, qMax(index + 1, size));
+ Q_ASSERT(container);
+ Q_ASSERT((container->elements.size() & 1) == 0);
+
+ if (index >= size) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+ }
+ template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborMap &map, KeyType key);
+ template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValue &self, KeyType key);
+ template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValueRef self, KeyType key);
+
+#if QT_CONFIG(cborstreamreader)
+ void decodeValueFromCbor(QCborStreamReader &reader, int remainingStackDepth);
void decodeStringFromCbor(QCborStreamReader &reader);
static inline void setErrorInReader(QCborStreamReader &reader, QCborError error);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 7888296b85..329be4a294 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdatastream.h"
#include "qdatastream_p.h"
@@ -51,9 +15,13 @@
QT_BEGIN_NAMESPACE
+constexpr quint32 QDataStream::NullCode;
+constexpr quint32 QDataStream::ExtendedSize;
+
/*!
\class QDataStream
\inmodule QtCore
+ \ingroup qtserialization
\reentrant
\brief The QDataStream class provides serialization of binary data
to a QIODevice.
@@ -102,17 +70,30 @@ QT_BEGIN_NAMESPACE
need of manually defining streaming operators. Enum classes are
serialized using the declared size.
- To take one example, a \c{char *} string is written as a 32-bit
- integer equal to the length of the string including the '\\0' byte,
- followed by all the characters of the string including the
- '\\0' byte. When reading a \c{char *} string, 4 bytes are read to
- create the 32-bit length value, then that many characters for the
- \c {char *} string including the '\\0' terminator are read.
-
The initial I/O device is usually set in the constructor, but can be
changed with setDevice(). If you've reached the end of the data
(or if there is no I/O device set) atEnd() will return true.
+ \section1 Serializing containers and strings
+
+ The serialization format is a length specifier first, then \a l bytes of data.
+ The length specifier is one quint32 if the version is less than 6.7 or if the
+ number of elements is less than 0xfffffffe (2^32 -2). Otherwise there is
+ an extend value 0xfffffffe followed by one quint64 with the actual value.
+ In addition for containers that support isNull(), it is encoded as a single
+ quint32 with all bits set and no data.
+
+ To take one example, if the string size fits into 32 bits, a \c{char *} string
+ is written as a 32-bit integer equal to the length of the string, including
+ the '\\0' byte, followed by all the characters of the string, including the
+ '\\0' byte. If the string size is greater, the value 0xffffffffe is written
+ as a marker of an extended size, followed by 64 bits of the actual size.
+ When reading a \c {char *} string, 4 bytes are read first. If the value is
+ not equal to 0xffffffffe (the marker of extended size), then these 4 bytes
+ are treated as the 32 bit size of the string. Otherwise, the next 8 bytes are
+ read and treated as a 64 bit size of the string. Then, all the characters for
+ the \c {char *} string, including the '\\0' terminator, are read.
+
\section1 Versioning
QDataStream's binary format has evolved since Qt 1.0, and is
@@ -138,9 +119,9 @@ QT_BEGIN_NAMESPACE
\snippet code/src_corelib_io_qdatastream.cpp 4
You can select which byte order to use when serializing data. The
- default setting is big endian (MSB first). Changing it to little
- endian breaks the portability (unless the reader also changes to
- little endian). We recommend keeping this setting unless you have
+ default setting is big-endian (MSB first). Changing it to little-endian
+ breaks the portability (unless the reader also changes to
+ little-endian). We recommend keeping this setting unless you have
special requirements.
\target raw
@@ -199,6 +180,27 @@ QT_BEGIN_NAMESPACE
If no full packet is received, this code restores the stream to the
initial position, after which you need to wait for more data to arrive.
+ \section1 Corruption and Security
+
+ QDataStream is not resilient against corrupted data inputs and should
+ therefore not be used for security-sensitive situations, even when using
+ transactions. Transactions will help determine if a valid input can
+ currently be decoded with the data currently available on an asynchronous
+ device, but will assume that the data that is available is correctly
+ formed.
+
+ Additionally, many QDataStream demarshalling operators will allocate memory
+ based on information found in the stream. Those operators perform no
+ verification on whether the requested amount of memory is reasonable or if
+ it is compatible with the amount of data available in the stream (example:
+ demarshalling a QByteArray or QString may see the request for allocation of
+ several gigabytes of data).
+
+ QDataStream should not be used on content whose provenance cannot be
+ trusted. Applications should be designed to attempt to decode only streams
+ whose provenance is at least as trustworthy as that of the application
+ itself or its plugins.
+
\sa QTextStream, QVariant
*/
@@ -236,6 +238,11 @@ QT_BEGIN_NAMESPACE
data in the underlying device.
\value ReadCorruptData The data stream has read corrupt data.
\value WriteFailed The data stream cannot write to the underlying device.
+ \value [since 6.7] SizeLimitExceeded The data stream cannot read or write
+ the data because its size is larger than supported
+ by the current platform. This can happen, for
+ example, when trying to read more that 2 GiB of
+ data on a 32-bit platform.
*/
/*****************************************************************************
@@ -264,7 +271,7 @@ QT_BEGIN_NAMESPACE
return retVal;
#define CHECK_STREAM_TRANSACTION_PRECOND(retVal) \
- if (!d || d->transactionDepth == 0) { \
+ if (transactionDepth == 0) { \
qWarning("QDataStream: No transaction in progress"); \
return retVal; \
}
@@ -277,12 +284,6 @@ QT_BEGIN_NAMESPACE
QDataStream::QDataStream()
{
- dev = nullptr;
- owndev = false;
- byteorder = BigEndian;
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
@@ -294,15 +295,10 @@ QDataStream::QDataStream()
QDataStream::QDataStream(QIODevice *d)
{
dev = d; // set device
- owndev = false;
- byteorder = BigEndian; // default byte order
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
- \fn QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode mode)
+ \fn QDataStream::QDataStream(QByteArray *a, OpenMode mode)
Constructs a data stream that operates on a byte array, \a a. The
\a mode describes how the device is to be used.
@@ -314,7 +310,7 @@ QDataStream::QDataStream(QIODevice *d)
is created to wrap the byte array.
*/
-QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
+QDataStream::QDataStream(QByteArray *a, OpenMode flags)
{
QBuffer *buf = new QBuffer(a);
#ifndef QT_NO_QOBJECT
@@ -323,10 +319,6 @@ QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
buf->open(flags);
dev = buf;
owndev = true;
- byteorder = BigEndian;
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
@@ -347,10 +339,6 @@ QDataStream::QDataStream(const QByteArray &a)
buf->open(QIODevice::ReadOnly);
dev = buf;
owndev = true;
- byteorder = BigEndian;
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
@@ -396,19 +384,6 @@ void QDataStream::setDevice(QIODevice *d)
dev = d;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
- Unsets the I/O device.
- Use setDevice(nullptr) instead.
-*/
-
-void QDataStream::unsetDevice()
-{
- setDevice(nullptr);
-}
-#endif
-
/*!
\fn bool QDataStream::atEnd() const
@@ -425,16 +400,14 @@ bool QDataStream::atEnd() const
}
/*!
+ \fn QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
+
Returns the floating point precision of the data stream.
\since 4.6
\sa FloatingPointPrecision, setFloatingPointPrecision()
*/
-QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
-{
- return d ? d->floatingPointPrecision : QDataStream::DoublePrecision;
-}
/*!
Sets the floating point precision of the data stream to \a precision. If the floating point precision is
@@ -458,22 +431,17 @@ QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
*/
void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision)
{
- if (!d)
- d.reset(new QDataStreamPrivate());
- d->floatingPointPrecision = precision;
+ fpPrecision = precision;
}
/*!
+ \fn QDataStream::status() const
+
Returns the status of the data stream.
\sa Status, setStatus(), resetStatus()
*/
-QDataStream::Status QDataStream::status() const
-{
- return q_status;
-}
-
/*!
Resets the status of the data stream.
@@ -513,7 +481,7 @@ void QDataStream::setStatus(Status status)
The \a bo parameter can be QDataStream::BigEndian or
QDataStream::LittleEndian.
- The default setting is big endian. We recommend leaving this
+ The default setting is big-endian. We recommend leaving this
setting unless you have special requirements.
\sa byteOrder()
@@ -521,11 +489,14 @@ void QDataStream::setStatus(Status status)
void QDataStream::setByteOrder(ByteOrder bo)
{
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ // accessed by inline byteOrder() prior to Qt 6.8
byteorder = bo;
+#endif
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- noswap = (byteorder == BigEndian);
+ noswap = (bo == BigEndian);
else
- noswap = (byteorder == LittleEndian);
+ noswap = (bo == LittleEndian);
}
@@ -567,6 +538,15 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_13 Version 19 (Qt 5.13)
\value Qt_5_14 Same as Qt_5_13
\value Qt_5_15 Same as Qt_5_13
+ \value Qt_6_0 Version 20 (Qt 6.0)
+ \value Qt_6_1 Same as Qt_6_0
+ \value Qt_6_2 Same as Qt_6_0
+ \value Qt_6_3 Same as Qt_6_0
+ \value Qt_6_4 Same as Qt_6_0
+ \value Qt_6_5 Same as Qt_6_0
+ \value Qt_6_6 Version 21 (Qt 6.6)
+ \value Qt_6_7 Version 22 (Qt 6.7)
+ \value Qt_6_8 Same as Qt_6_7
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
@@ -640,10 +620,7 @@ void QDataStream::startTransaction()
{
CHECK_STREAM_PRECOND(Q_VOID)
- if (!d)
- d.reset(new QDataStreamPrivate());
-
- if (++d->transactionDepth == 1) {
+ if (++transactionDepth == 1) {
dev->startTransaction();
resetStatus();
}
@@ -672,7 +649,7 @@ void QDataStream::startTransaction()
bool QDataStream::commitTransaction()
{
CHECK_STREAM_TRANSACTION_PRECOND(false)
- if (--d->transactionDepth == 0) {
+ if (--transactionDepth == 0) {
CHECK_STREAM_PRECOND(false)
if (q_status == ReadPastEnd) {
@@ -712,7 +689,7 @@ void QDataStream::rollbackTransaction()
setStatus(ReadPastEnd);
CHECK_STREAM_TRANSACTION_PRECOND(Q_VOID)
- if (--d->transactionDepth != 0)
+ if (--transactionDepth != 0)
return;
CHECK_STREAM_PRECOND(Q_VOID)
@@ -748,13 +725,21 @@ void QDataStream::abortTransaction()
q_status = ReadCorruptData;
CHECK_STREAM_TRANSACTION_PRECOND(Q_VOID)
- if (--d->transactionDepth != 0)
+ if (--transactionDepth != 0)
return;
CHECK_STREAM_PRECOND(Q_VOID)
dev->commitTransaction();
}
+/*!
+ \internal
+*/
+bool QDataStream::isDeviceTransactionStarted() const
+{
+ return dev && dev->isTransactionStarted();
+}
+
/*****************************************************************************
QDataStream read functions
*****************************************************************************/
@@ -763,13 +748,13 @@ void QDataStream::abortTransaction()
\internal
*/
-int QDataStream::readBlock(char *data, int len)
+qint64 QDataStream::readBlock(char *data, qint64 len)
{
// Disable reads on failure in transacted stream
if (q_status != Ok && dev->isTransactionStarted())
return -1;
- const int readResult = dev->read(data, len);
+ const qint64 readResult = dev->read(data, len);
if (readResult != len)
setStatus(ReadPastEnd);
return readResult;
@@ -993,25 +978,12 @@ QDataStream &QDataStream::operator>>(double &f)
/*!
\overload
- \since 5.9
- Reads a floating point number from the stream into \a f,
- using the standard IEEE 754 format. Returns a reference to the
- stream.
-*/
-QDataStream &QDataStream::operator>>(qfloat16 &f)
-{
- return *this >> reinterpret_cast<qint16&>(f);
-}
+ Reads string \a s from the stream and returns a reference to the stream.
-
-/*!
- \overload
-
- Reads the '\\0'-terminated string \a s from the stream and returns
- a reference to the stream.
-
- The string is deserialized using \c{readBytes()}.
+ The string is deserialized using \c{readBytes()} where the serialization
+ format is a \c quint32 length specifier first, followed by that many bytes
+ of data. The resulting string is always '\\0'-terminated.
Space for the string is allocated using \c{new []} -- the caller must
destroy it with \c{delete []}.
@@ -1021,14 +993,16 @@ QDataStream &QDataStream::operator>>(qfloat16 &f)
QDataStream &QDataStream::operator>>(char *&s)
{
- uint len = 0;
+ qint64 len = 0;
return readBytes(s, len);
}
/*!
- \overload
+ \overload
+ \since 6.0
- Reads a char from the stream into char \a chr.
+ Reads a 16bit wide char from the stream into \a c and
+ returns a reference to the stream.
*/
QDataStream &QDataStream::operator>>(char16_t &c)
{
@@ -1039,9 +1013,11 @@ QDataStream &QDataStream::operator>>(char16_t &c)
}
/*!
- \overload
+ \overload
+ \since 6.0
- Reads a char from the stream into char \a chr.
+ Reads a 32bit wide character from the stream into \a c and
+ returns a reference to the stream.
*/
QDataStream &QDataStream::operator>>(char32_t &c)
{
@@ -1051,7 +1027,29 @@ QDataStream &QDataStream::operator>>(char32_t &c)
return *this;
}
+#if QT_DEPRECATED_SINCE(6, 11)
+
+/*
+ \deprecated [6.11] Use an overload that takes qint64 length instead.
+*/
+QDataStream &QDataStream::readBytes(char *&s, uint &l)
+{
+ qint64 length = 0;
+ (void)readBytes(s, length);
+ if (length != qint64(uint(length))) {
+ setStatus(SizeLimitExceeded); // Cannot store length in l
+ delete[] s;
+ l = 0;
+ return *this;
+ }
+ l = uint(length);
+ return *this;
+}
+
+#endif // QT_DEPRECATED_SINCE(6, 11)
+
/*!
+ \since 6.7
Reads the buffer \a s from the stream and returns a reference to
the stream.
@@ -1061,46 +1059,53 @@ QDataStream &QDataStream::operator>>(char32_t &c)
The \a l parameter is set to the length of the buffer. If the
string read is empty, \a l is set to 0 and \a s is set to \nullptr.
- The serialization format is a quint32 length specifier first,
- then \a l bytes of data.
+ The serialization format is a length specifier first, then \a l
+ bytes of data. The length specifier is one quint32 if the version
+ is less than 6.7 or if the number of elements is less than 0xfffffffe
+ (2^32 -2), otherwise there is an extend value 0xfffffffe followed by
+ one quint64 with the actual value. In addition for containers that
+ support isNull(), it is encoded as a single quint32 with all bits
+ set and no data.
\sa readRawData(), writeBytes()
*/
-QDataStream &QDataStream::readBytes(char *&s, uint &l)
+QDataStream &QDataStream::readBytes(char *&s, qint64 &l)
{
s = nullptr;
l = 0;
CHECK_STREAM_PRECOND(*this)
- quint32 len;
- *this >> len;
- if (len == 0)
+ qint64 length = readQSizeType(*this);
+ if (length == 0)
return *this;
- const quint32 Step = 1024 * 1024;
- quint32 allocated = 0;
- char *prevBuf = nullptr;
- char *curBuf = nullptr;
+ qsizetype len = qsizetype(length);
+ if (length != len || length < 0) {
+ setStatus(SizeLimitExceeded); // Cannot store len
+ return *this;
+ }
+ qsizetype step = (dev->bytesAvailable() >= len) ? len : 1024 * 1024;
+ qsizetype allocated = 0;
+ std::unique_ptr<char[]> curBuf = nullptr;
+
+ constexpr qsizetype StepIncreaseThreshold = std::numeric_limits<qsizetype>::max() / 2;
do {
- int blockSize = qMin(Step, len - allocated);
- prevBuf = curBuf;
- curBuf = new char[allocated + blockSize + 1];
- if (prevBuf) {
- memcpy(curBuf, prevBuf, allocated);
- delete [] prevBuf;
- }
- if (readBlock(curBuf + allocated, blockSize) != blockSize) {
- delete [] curBuf;
+ qsizetype blockSize = qMin(step, len - allocated);
+ const qsizetype n = allocated + blockSize + 1;
+ if (const auto prevBuf = std::exchange(curBuf, std::make_unique<char[]>(n)))
+ memcpy(curBuf.get(), prevBuf.get(), allocated);
+ if (readBlock(curBuf.get() + allocated, blockSize) != blockSize)
return *this;
- }
allocated += blockSize;
+ if (step <= StepIncreaseThreshold)
+ step *= 2;
} while (allocated < len);
- s = curBuf;
+ s = curBuf.release();
s[len] = '\0';
- l = (uint)len;
+ l = len;
return *this;
}
@@ -1113,7 +1118,7 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l)
\sa readBytes(), QIODevice::read(), writeRawData()
*/
-int QDataStream::readRawData(char *s, int len)
+qint64 QDataStream::readRawData(char *s, qint64 len)
{
CHECK_STREAM_PRECOND(-1)
return readBlock(s, len);
@@ -1251,18 +1256,13 @@ QDataStream &QDataStream::operator<<(qint64 i)
*/
/*!
+ \fn QDataStream &QDataStream::operator<<(bool i)
+ \overload
+
Writes a boolean value, \a i, to the stream. Returns a reference
to the stream.
*/
-QDataStream &QDataStream::operator<<(bool i)
-{
- CHECK_STREAM_WRITE_PRECOND(*this)
- if (!dev->putChar(qint8(i)))
- q_status = WriteFailed;
- return *this;
-}
-
/*!
\overload
@@ -1337,19 +1337,6 @@ QDataStream &QDataStream::operator<<(double f)
/*!
- \fn QDataStream &QDataStream::operator<<(qfloat16 f)
- \overload
- \since 5.9
-
- Writes a floating point number, \a f, to the stream using
- the standard IEEE 754 format. Returns a reference to the stream.
-*/
-QDataStream &QDataStream::operator<<(qfloat16 f)
-{
- return *this << reinterpret_cast<qint16&>(f);
-}
-
-/*!
\overload
Writes the '\\0'-terminated string \a s to the stream and returns a
@@ -1362,13 +1349,9 @@ QDataStream &QDataStream::operator<<(qfloat16 f)
QDataStream &QDataStream::operator<<(const char *s)
{
- if (!s) {
- *this << (quint32)0;
- return *this;
- }
- uint len = qstrlen(s) + 1; // also write null terminator
- *this << (quint32)len; // write length specifier
- writeRawData(s, len);
+ // Include null terminator, unless s itself is null
+ const qint64 len = s ? qint64(qstrlen(s)) + 1 : 0;
+ writeBytes(s, len);
return *this;
}
@@ -1400,22 +1383,26 @@ QDataStream &QDataStream::operator<<(char32_t c)
Writes the length specifier \a len and the buffer \a s to the
stream and returns a reference to the stream.
- The \a len is serialized as a quint32, followed by \a len bytes
- from \a s. Note that the data is \e not encoded.
+ The \a len is serialized as a quint32 and an optional quint64,
+ followed by \a len bytes from \a s. Note that the data is
+ \e not encoded.
\sa writeRawData(), readBytes()
*/
-QDataStream &QDataStream::writeBytes(const char *s, uint len)
+QDataStream &QDataStream::writeBytes(const char *s, qint64 len)
{
+ if (len < 0) {
+ q_status = WriteFailed;
+ return *this;
+ }
CHECK_STREAM_WRITE_PRECOND(*this)
- *this << (quint32)len; // write length specifier
- if (len)
+ // Write length then, if any, content
+ if (writeQSizeType(*this, len) && len > 0)
writeRawData(s, len);
return *this;
}
-
/*!
Writes \a len bytes from \a s to the stream. Returns the
number of bytes actually written, or -1 on error.
@@ -1424,10 +1411,10 @@ QDataStream &QDataStream::writeBytes(const char *s, uint len)
\sa writeBytes(), QIODevice::write(), readRawData()
*/
-int QDataStream::writeRawData(const char *s, int len)
+qint64 QDataStream::writeRawData(const char *s, qint64 len)
{
CHECK_STREAM_WRITE_PRECOND(-1)
- int ret = dev->write(s, len);
+ qint64 ret = dev->write(s, len);
if (ret != len)
q_status = WriteFailed;
return ret;
@@ -1444,13 +1431,13 @@ int QDataStream::writeRawData(const char *s, int len)
\sa QIODevice::seek()
*/
-int QDataStream::skipRawData(int len)
+qint64 QDataStream::skipRawData(qint64 len)
{
CHECK_STREAM_PRECOND(-1)
if (q_status != Ok && dev->isTransactionStarted())
return -1;
- const int skipResult = dev->skip(len);
+ const qint64 skipResult = dev->skip(len);
if (skipResult != len)
setStatus(ReadPastEnd);
return skipResult;
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index d00fb5e7d8..cf37df71d7 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -1,49 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATASTREAM_H
#define QDATASTREAM_H
#include <QtCore/qscopedpointer.h>
-#include <QtCore/qiodevice.h>
-#include <QtCore/qpair.h>
+#include <QtCore/qiodevicebase.h>
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qnamespace.h>
+
+#include <iterator> // std::distance(), std::next()
#ifdef Status
#error qdatastream.h must be included before any header file that defines Status
@@ -51,19 +17,35 @@
QT_BEGIN_NAMESPACE
+#if QT_CORE_REMOVED_SINCE(6, 3)
class qfloat16;
+#endif
class QByteArray;
+class QDataStream;
class QIODevice;
+class QString;
-#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
+#if !defined(QT_NO_DATASTREAM)
class QDataStreamPrivate;
namespace QtPrivate {
class StreamStateSaver;
+template <typename Container>
+QDataStream &readArrayBasedContainer(QDataStream &s, Container &c);
+template <typename Container>
+QDataStream &readListBasedContainer(QDataStream &s, Container &c);
+template <typename Container>
+QDataStream &readAssociativeContainer(QDataStream &s, Container &c);
+template <typename Container>
+QDataStream &writeSequentialContainer(QDataStream &s, const Container &c);
+template <typename Container>
+QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c);
+template <typename Container>
+QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c);
}
-class Q_CORE_EXPORT QDataStream
+class Q_CORE_EXPORT QDataStream : public QIODeviceBase
{
public:
- enum Version {
+ enum Version QT7_ONLY(: quint8) {
Qt_1_0 = 1,
Qt_2_0 = 2,
Qt_2_1 = 3,
@@ -97,8 +79,16 @@ public:
Qt_5_14 = Qt_5_13,
Qt_5_15 = Qt_5_14,
Qt_6_0 = 20,
- Qt_DefaultCompiledVersion = Qt_6_0
-#if QT_VERSION >= 0x060100
+ Qt_6_1 = Qt_6_0,
+ Qt_6_2 = Qt_6_0,
+ Qt_6_3 = Qt_6_0,
+ Qt_6_4 = Qt_6_0,
+ Qt_6_5 = Qt_6_0,
+ Qt_6_6 = 21,
+ Qt_6_7 = 22,
+ Qt_6_8 = Qt_6_7,
+ Qt_DefaultCompiledVersion = Qt_6_8
+#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
};
@@ -108,37 +98,36 @@ public:
LittleEndian = QSysInfo::LittleEndian
};
- enum Status {
+ enum Status QT7_ONLY(: quint8) {
Ok,
ReadPastEnd,
ReadCorruptData,
- WriteFailed
+ WriteFailed,
+ SizeLimitExceeded,
};
- enum FloatingPointPrecision {
+ enum FloatingPointPrecision QT7_ONLY(: quint8) {
SinglePrecision,
DoublePrecision
};
QDataStream();
explicit QDataStream(QIODevice *);
- QDataStream(QByteArray *, QIODevice::OpenMode flags);
+ QDataStream(QByteArray *, OpenMode flags);
QDataStream(const QByteArray &);
~QDataStream();
QIODevice *device() const;
void setDevice(QIODevice *);
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead")
- void unsetDevice();
-#endif
bool atEnd() const;
+ QT_CORE_INLINE_SINCE(6, 8)
Status status() const;
void setStatus(Status status);
void resetStatus();
+ QT_CORE_INLINE_SINCE(6, 8)
FloatingPointPrecision floatingPointPrecision() const;
void setFloatingPointPrecision(FloatingPointPrecision precision);
@@ -148,6 +137,7 @@ public:
int version() const;
void setVersion(int);
+ QDataStream &operator>>(char &i);
QDataStream &operator>>(qint8 &i);
QDataStream &operator>>(quint8 &i);
QDataStream &operator>>(qint16 &i);
@@ -159,13 +149,16 @@ public:
QDataStream &operator>>(std::nullptr_t &ptr) { ptr = nullptr; return *this; }
QDataStream &operator>>(bool &i);
+#if QT_CORE_REMOVED_SINCE(6, 3)
QDataStream &operator>>(qfloat16 &f);
+#endif
QDataStream &operator>>(float &f);
QDataStream &operator>>(double &f);
QDataStream &operator>>(char *&str);
QDataStream &operator>>(char16_t &c);
QDataStream &operator>>(char32_t &c);
+ QDataStream &operator<<(char i);
QDataStream &operator<<(qint8 i);
QDataStream &operator<<(quint8 i);
QDataStream &operator<<(qint16 i);
@@ -175,52 +168,105 @@ public:
QDataStream &operator<<(qint64 i);
QDataStream &operator<<(quint64 i);
QDataStream &operator<<(std::nullptr_t) { return *this; }
+#if QT_CORE_REMOVED_SINCE(6, 8) || defined(Q_QDOC)
QDataStream &operator<<(bool i);
+#endif
+#if !defined(Q_QDOC)
+ // Disable implicit conversions to bool (e.g. for pointers)
+ template <typename T,
+ std::enable_if_t<std::is_same_v<T, bool>, bool> = true>
+ QDataStream &operator<<(T i)
+ {
+ return (*this << qint8(i));
+ }
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 3)
QDataStream &operator<<(qfloat16 f);
+#endif
QDataStream &operator<<(float f);
QDataStream &operator<<(double f);
QDataStream &operator<<(const char *str);
QDataStream &operator<<(char16_t c);
QDataStream &operator<<(char32_t c);
-
+#if QT_DEPRECATED_SINCE(6, 11)
+ QT_DEPRECATED_VERSION_X_6_11("Use an overload that takes qint64 length.")
QDataStream &readBytes(char *&, uint &len);
- int readRawData(char *, int len);
-
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 7)
QDataStream &writeBytes(const char *, uint len);
- int writeRawData(const char *, int len);
-
int skipRawData(int len);
+ int readRawData(char *, int len);
+ int writeRawData(const char *, int len);
+#endif
+ QDataStream &readBytes(char *&, qint64 &len);
+ qint64 readRawData(char *, qint64 len);
+ QDataStream &writeBytes(const char *, qint64 len);
+ qint64 writeRawData(const char *, qint64 len);
+ qint64 skipRawData(qint64 len);
void startTransaction();
bool commitTransaction();
void rollbackTransaction();
void abortTransaction();
+ bool isDeviceTransactionStarted() const;
private:
Q_DISABLE_COPY(QDataStream)
QScopedPointer<QDataStreamPrivate> d;
- QIODevice *dev;
- bool owndev;
- bool noswap;
- ByteOrder byteorder;
- int ver;
- Status q_status;
+ QIODevice *dev = nullptr;
+ bool owndev = false;
+ bool noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ quint8 fpPrecision = QDataStream::DoublePrecision;
+ quint8 q_status = Ok;
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ ByteOrder byteorder = BigEndian;
+ int ver = Qt_DefaultCompiledVersion;
+#else
+ Version ver = Qt_DefaultCompiledVersion;
+#endif
+ quint16 transactionDepth = 0;
+#if QT_CORE_REMOVED_SINCE(6, 7)
int readBlock(char *data, int len);
+#endif
+ qint64 readBlock(char *data, qint64 len);
+ static inline qint64 readQSizeType(QDataStream &s);
+ static inline bool writeQSizeType(QDataStream &s, qint64 value);
+ static constexpr quint32 NullCode = 0xffffffffu;
+ static constexpr quint32 ExtendedSize = 0xfffffffeu;
+
friend class QtPrivate::StreamStateSaver;
+ Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out, const QString &str);
+ Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QString &str);
+ Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out, const QByteArray &ba);
+ Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QByteArray &ba);
+ template <typename Container>
+ friend QDataStream &QtPrivate::readArrayBasedContainer(QDataStream &s, Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::readListBasedContainer(QDataStream &s, Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::readAssociativeContainer(QDataStream &s, Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::writeSequentialContainer(QDataStream &s, const Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::writeAssociativeContainer(QDataStream &s, const Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::writeAssociativeMultiContainer(QDataStream &s,
+ const Container &c);
};
namespace QtPrivate {
class StreamStateSaver
{
+ Q_DISABLE_COPY_MOVE(StreamStateSaver)
public:
inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
{
- if (!stream->dev || !stream->dev->isTransactionStarted())
+ if (!stream->isDeviceTransactionStarted())
stream->resetStatus();
}
inline ~StreamStateSaver()
@@ -242,10 +288,14 @@ QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
StreamStateSaver stateSaver(&s);
c.clear();
- quint32 n;
- s >> n;
+ qint64 size = QDataStream::readQSizeType(s);
+ qsizetype n = size;
+ if (size != n || size < 0) {
+ s.setStatus(QDataStream::SizeLimitExceeded);
+ return s;
+ }
c.reserve(n);
- for (quint32 i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
typename Container::value_type t;
s >> t;
if (s.status() != QDataStream::Ok) {
@@ -264,9 +314,13 @@ QDataStream &readListBasedContainer(QDataStream &s, Container &c)
StreamStateSaver stateSaver(&s);
c.clear();
- quint32 n;
- s >> n;
- for (quint32 i = 0; i < n; ++i) {
+ qint64 size = QDataStream::readQSizeType(s);
+ qsizetype n = size;
+ if (size != n || size < 0) {
+ s.setStatus(QDataStream::SizeLimitExceeded);
+ return s;
+ }
+ for (qsizetype i = 0; i < n; ++i) {
typename Container::value_type t;
s >> t;
if (s.status() != QDataStream::Ok) {
@@ -285,9 +339,13 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
StreamStateSaver stateSaver(&s);
c.clear();
- quint32 n;
- s >> n;
- for (quint32 i = 0; i < n; ++i) {
+ qint64 size = QDataStream::readQSizeType(s);
+ qsizetype n = size;
+ if (size != n || size < 0) {
+ s.setStatus(QDataStream::SizeLimitExceeded);
+ return s;
+ }
+ for (qsizetype i = 0; i < n; ++i) {
typename Container::key_type k;
typename Container::mapped_type t;
s >> k >> t;
@@ -304,7 +362,8 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
template <typename Container>
QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
{
- s << quint32(c.size());
+ if (!QDataStream::writeQSizeType(s, c.size()))
+ return s;
for (const typename Container::value_type &t : c)
s << t;
@@ -314,7 +373,8 @@ QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
template <typename Container>
QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
{
- s << quint32(c.size());
+ if (!QDataStream::writeQSizeType(s, c.size()))
+ return s;
auto it = c.constBegin();
auto end = c.constEnd();
while (it != end) {
@@ -328,7 +388,8 @@ QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
template <typename Container>
QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
{
- s << quint32(c.size());
+ if (!QDataStream::writeQSizeType(s, c.size()))
+ return s;
auto it = c.constBegin();
auto end = c.constEnd();
while (it != end) {
@@ -347,6 +408,20 @@ QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
} // QtPrivate namespace
+template<typename ...T>
+using QDataStreamIfHasOStreamOperators =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
+template<typename Container, typename ...T>
+using QDataStreamIfHasOStreamOperatorsContainer =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
+
+template<typename ...T>
+using QDataStreamIfHasIStreamOperators =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
+template<typename Container, typename ...T>
+using QDataStreamIfHasIStreamOperatorsContainer =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
+
/*****************************************************************************
QDataStream inline functions
*****************************************************************************/
@@ -354,14 +429,61 @@ QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
inline QIODevice *QDataStream::device() const
{ return dev; }
+#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
+QDataStream::Status QDataStream::status() const
+{
+ return Status(q_status);
+}
+
+QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
+{
+ return FloatingPointPrecision(fpPrecision);
+}
+#endif // INLINE_SINCE 6.8
+
inline QDataStream::ByteOrder QDataStream::byteOrder() const
-{ return byteorder; }
+{
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ return noswap ? BigEndian : LittleEndian;
+ return noswap ? LittleEndian : BigEndian;
+}
inline int QDataStream::version() const
{ return ver; }
inline void QDataStream::setVersion(int v)
-{ ver = v; }
+{ ver = Version(v); }
+
+qint64 QDataStream::readQSizeType(QDataStream &s)
+{
+ quint32 first;
+ s >> first;
+ if (first == NullCode)
+ return -1;
+ if (first < ExtendedSize || s.version() < QDataStream::Qt_6_7)
+ return qint64(first);
+ qint64 extendedLen;
+ s >> extendedLen;
+ return extendedLen;
+}
+
+bool QDataStream::writeQSizeType(QDataStream &s, qint64 value)
+{
+ if (value < qint64(ExtendedSize)) {
+ s << quint32(value);
+ } else if (s.version() >= QDataStream::Qt_6_7) {
+ s << ExtendedSize << value;
+ } else if (value == qint64(ExtendedSize)) {
+ s << ExtendedSize;
+ } else {
+ s.setStatus(QDataStream::SizeLimitExceeded); // value is too big for old format
+ return false;
+ }
+ return true;
+}
+
+inline QDataStream &QDataStream::operator>>(char &i)
+{ return *this >> reinterpret_cast<qint8&>(i); }
inline QDataStream &QDataStream::operator>>(quint8 &i)
{ return *this >> reinterpret_cast<qint8&>(i); }
@@ -375,6 +497,9 @@ inline QDataStream &QDataStream::operator>>(quint32 &i)
inline QDataStream &QDataStream::operator>>(quint64 &i)
{ return *this >> reinterpret_cast<qint64&>(i); }
+inline QDataStream &QDataStream::operator<<(char i)
+{ return *this << qint8(i); }
+
inline QDataStream &QDataStream::operator<<(quint8 i)
{ return *this << qint8(i); }
@@ -389,110 +514,174 @@ inline QDataStream &QDataStream::operator<<(quint64 i)
template <typename Enum>
inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e)
-{ return s << e.i; }
+{ return s << typename QFlags<Enum>::Int(e); }
template <typename Enum>
inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
-{ return s >> e.i; }
+{
+ typename QFlags<Enum>::Int i;
+ s >> i;
+ e = QFlag(i);
+ return s;
+}
template <typename T>
-typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
+typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
operator<<(QDataStream &s, const T &t)
{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
template <typename T>
-typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
+typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
+#ifndef Q_QDOC
+
template<typename T>
-inline QDataStream &operator>>(QDataStream &s, QList<T> &v)
+inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T> operator>>(QDataStream &s, QList<T> &v)
{
return QtPrivate::readArrayBasedContainer(s, v);
}
template<typename T>
-inline QDataStream &operator<<(QDataStream &s, const QList<T> &v)
+inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T> operator<<(QDataStream &s, const QList<T> &v)
{
return QtPrivate::writeSequentialContainer(s, v);
}
template <typename T>
-inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
+inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T> operator>>(QDataStream &s, QSet<T> &set)
{
return QtPrivate::readListBasedContainer(s, set);
}
template <typename T>
-inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
+inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T> operator<<(QDataStream &s, const QSet<T> &set)
{
return QtPrivate::writeSequentialContainer(s, set);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
+inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
{
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
+inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
+inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
{
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
+inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeMultiContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
+inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
{
return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
+inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
{
return QtPrivate::writeAssociativeContainer(s, map);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map)
+inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
{
return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
+inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
{
return QtPrivate::writeAssociativeMultiContainer(s, map);
}
-#ifndef QT_NO_DATASTREAM
template <class T1, class T2>
-inline QDataStream& operator>>(QDataStream& s, std::pair<T1, T2> &p)
+inline QDataStreamIfHasIStreamOperators<T1, T2> operator>>(QDataStream& s, std::pair<T1, T2> &p)
{
s >> p.first >> p.second;
return s;
}
template <class T1, class T2>
-inline QDataStream& operator<<(QDataStream& s, const std::pair<T1, T2> &p)
+inline QDataStreamIfHasOStreamOperators<T1, T2> operator<<(QDataStream& s, const std::pair<T1, T2> &p)
{
s << p.first << p.second;
return s;
}
-#endif
+
+#else
+
+template <class T>
+QDataStream &operator>>(QDataStream &s, QList<T> &l);
+
+template <class T>
+QDataStream &operator<<(QDataStream &s, const QList<T> &l);
+
+template <class T>
+QDataStream &operator>>(QDataStream &s, QSet<T> &set);
+
+template <class T>
+QDataStream &operator<<(QDataStream &s, const QSet<T> &set);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map);
+
+template <class T1, class T2>
+QDataStream &operator>>(QDataStream& s, std::pair<T1, T2> &p);
+
+template <class T1, class T2>
+QDataStream &operator<<(QDataStream& s, const std::pair<T1, T2> &p);
+
+#endif // Q_QDOC
+
+inline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination)
+{
+ int combined;
+ s >> combined;
+ combination = QKeyCombination::fromCombined(combined);
+ return s;
+}
+
+inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination)
+{
+ return s << combination.toCombined();
+}
#endif // QT_NO_DATASTREAM
diff --git a/src/corelib/serialization/qdatastream_p.h b/src/corelib/serialization/qdatastream_p.h
index 3ca0ae840e..c4fe7c784c 100644
--- a/src/corelib/serialization/qdatastream_p.h
+++ b/src/corelib/serialization/qdatastream_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATASTREAM_P_H
#define QDATASTREAM_P_H
@@ -60,11 +24,6 @@ QT_BEGIN_NAMESPACE
class QDataStreamPrivate
{
public:
- QDataStreamPrivate() : floatingPointPrecision(QDataStream::DoublePrecision),
- transactionDepth(0) { }
-
- QDataStream::FloatingPointPrecision floatingPointPrecision;
- int transactionDepth;
};
#endif
diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h
index 4589284ef3..5a5b6926be 100644
--- a/src/corelib/serialization/qjson_p.h
+++ b/src/corelib/serialization/qjson_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSON_P_H
#define QJSON_P_H
@@ -56,6 +20,11 @@
#include <qcborvalue.h>
#include <private/qcborvalue_p.h>
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+# include <qjsonarray.h>
+# include <qjsonobject.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QJsonPrivate {
@@ -129,14 +98,13 @@ struct ObjectIterator
ObjectIterator &operator-=(difference_type n) { it -= 2 * n; return *this; }
reference operator*() const { return *it; }
- reference operator[](int n) const { return it[n * 2]; }
+ reference operator[](qsizetype n) const { return it[n * 2]; }
bool operator<(ObjectIterator other) const { return it < other.it; }
bool operator>(ObjectIterator other) const { return it > other.it; }
bool operator<=(ObjectIterator other) const { return it <= other.it; }
bool operator>=(ObjectIterator other) const { return it >= other.it; }
-private:
ElementsIterator it;
};
@@ -149,7 +117,7 @@ inline ObjectIterator<Element, ElementsIterator> operator+(
}
template<typename Element, typename ElementsIterator>
inline ObjectIterator<Element, ElementsIterator> operator+(
- int n, ObjectIterator<Element, ElementsIterator> a)
+ qsizetype n, ObjectIterator<Element, ElementsIterator> a)
{
return {a.elementsIterator() + 2 * n};
}
@@ -161,7 +129,7 @@ inline ObjectIterator<Element, ElementsIterator> operator-(
return {a.elementsIterator() - 2 * n};
}
template<typename Element, typename ElementsIterator>
-inline int operator-(
+inline qsizetype operator-(
ObjectIterator<Element, ElementsIterator> a,
ObjectIterator<Element, ElementsIterator> b)
{
@@ -203,18 +171,47 @@ inline void swap(KeyIterator::reference a, KeyIterator::reference b)
class Value
{
public:
+ static qint64 valueHelper(const QCborValue &v) { return v.n; }
static QCborContainerPrivate *container(const QCborValue &v) { return v.container; }
+ static const QCborContainerPrivate *container(QJsonValueConstRef r) noexcept
+ {
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ return (r.is_object ? r.o->o : r.a->a).data();
+#else
+ return r.d;
+#endif
+ }
+ static QCborContainerPrivate *container(QJsonValueRef r) noexcept
+ {
+ return const_cast<QCborContainerPrivate *>(container(QJsonValueConstRef(r)));
+ }
+ static qsizetype indexHelper(QJsonValueConstRef r) noexcept
+ {
+ qsizetype index = r.index;
+ if (r.is_object)
+ index = index * 2 + 1;
+ return index;
+ }
+ static const QtCbor::Element &elementHelper(QJsonValueConstRef r) noexcept
+ {
+ return container(r)->elements.at(indexHelper(r));
+ }
static QJsonValue fromTrustedCbor(const QCborValue &v)
{
QJsonValue result;
- result.d = v.container;
- result.n = v.n;
- result.t = v.t;
+ result.value = v;
return result;
}
};
+class Variant
+{
+public:
+ static QJsonObject toJsonObject(const QVariantMap &map);
+ static QJsonArray toJsonArray(const QVariantList &list);
+};
+
} // namespace QJsonPrivate
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index 98ace021fc..0c1b0ac7c8 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsonobject.h>
#include <qjsonvalue.h>
@@ -58,11 +22,16 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonArray class encapsulates a JSON array.
+ \compares equality
+ \compareswith equality QJsonValue
+ \endcompareswith
+
A JSON array is a list of values. The list can be manipulated by inserting and
removing QJsonValue's from the array.
@@ -75,7 +44,7 @@ QT_BEGIN_NAMESPACE
You can convert the array to and from text based JSON through QJsonDocument.
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -93,7 +62,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QJsonArray::size_type
- Typedef for int. Provided for STL compatibility.
+ Typedef for qsizetype. Provided for STL compatibility.
*/
/*!
@@ -105,7 +74,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QJsonArray::difference_type
- Typedef for int. Provided for STL compatibility.
+ Typedef for qsizetype. Provided for STL compatibility.
*/
/*!
@@ -155,23 +124,6 @@ QJsonArray::QJsonArray() = default;
QJsonArray::QJsonArray(QCborContainerPrivate *array)
: a(array)
{
- Q_ASSERT(array);
-}
-
-/*!
- This method replaces part of QJsonArray(std::initializer_list<QJsonValue> args) .
- The constructor needs to be inline, but we do not want to leak implementation details
- of this class.
- \note this method is called for an uninitialized object
- \internal
- */
-void QJsonArray::initialize()
-{
- // Because we're being called with uninitialized state, we can't do:
- // a = nullptr;
- // QExplicitlyDataSharedPointer::operator= will read the current value
- void *ptr = &a;
- memset(ptr, 0, sizeof(a));
}
/*!
@@ -191,11 +143,13 @@ QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
Since QJsonArray is implicitly shared, the copy is shallow
as long as the object doesn't get modified.
*/
-QJsonArray::QJsonArray(const QJsonArray &other)
-{
- a = other.a;
-}
+QJsonArray::QJsonArray(const QJsonArray &other) noexcept = default;
+/*!
+ \since 5.10
+
+ Move-constructs a QJsonArray from \a other.
+*/
QJsonArray::QJsonArray(QJsonArray &&other) noexcept
: a(other.a)
{
@@ -205,18 +159,7 @@ QJsonArray::QJsonArray(QJsonArray &&other) noexcept
/*!
Assigns \a other to this array.
*/
-QJsonArray &QJsonArray::operator =(const QJsonArray &other)
-{
- a = other.a;
- return *this;
-}
-
-/*!
- \fn QJsonArray::QJsonArray(QJsonArray &&other)
- \since 5.10
-
- Move-constructs a QJsonArray from \a other.
-*/
+QJsonArray &QJsonArray::operator =(const QJsonArray &other) noexcept = default;
/*!
\fn QJsonArray &QJsonArray::operator =(QJsonArray &&other)
@@ -272,16 +215,20 @@ QJsonArray QJsonArray::fromStringList(const QStringList &list)
return array;
}
+#ifndef QT_NO_VARIANT
/*!
Converts the variant list \a list to a QJsonArray.
The QVariant values in \a list will be converted to JSON values.
+ \note Conversion from \l QVariant is not completely lossless. Please see
+ the documentation in QJsonValue::fromVariant() for more information.
+
\sa toVariantList(), QJsonValue::fromVariant()
*/
QJsonArray QJsonArray::fromVariantList(const QVariantList &list)
{
- return QCborArray::fromVariantList(list).toJsonArray();
+ return QJsonPrivate::Variant::toJsonArray(list);
}
/*!
@@ -293,12 +240,13 @@ QVariantList QJsonArray::toVariantList() const
{
return QCborArray::fromJsonArray(*this).toVariantList();
}
+#endif // !QT_NO_VARIANT
/*!
Returns the number of values stored in the array.
*/
-int QJsonArray::size() const
+qsizetype QJsonArray::size() const
{
return a ? a->elements.size() : 0;
}
@@ -327,7 +275,7 @@ bool QJsonArray::isEmpty() const
The returned QJsonValue is \c Undefined, if \a i is out of bounds.
*/
-QJsonValue QJsonArray::at(int i) const
+QJsonValue QJsonArray::at(qsizetype i) const
{
if (!a || i < 0 || i >= a->elements.size())
return QJsonValue(QJsonValue::Undefined);
@@ -387,11 +335,11 @@ void QJsonArray::append(const QJsonValue &value)
\sa insert(), replace()
*/
-void QJsonArray::removeAt(int i)
+void QJsonArray::removeAt(qsizetype i)
{
- if (!a || i < 0 || i >= a->elements.length())
+ if (!a || i < 0 || i >= a->elements.size())
return;
- detach2();
+ detach();
a->removeAt(i);
}
@@ -423,12 +371,12 @@ void QJsonArray::removeAt(int i)
\sa removeAt()
*/
-QJsonValue QJsonArray::takeAt(int i)
+QJsonValue QJsonArray::takeAt(qsizetype i)
{
- if (!a || i < 0 || i >= a->elements.length())
+ if (!a || i < 0 || i >= a->elements.size())
return QJsonValue(QJsonValue::Undefined);
- detach2();
+ detach();
const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(a->extractAt(i));
a->removeAt(i);
return v;
@@ -441,14 +389,14 @@ QJsonValue QJsonArray::takeAt(int i)
\sa append(), prepend(), replace(), removeAt()
*/
-void QJsonArray::insert(int i, const QJsonValue &value)
+void QJsonArray::insert(qsizetype i, const QJsonValue &value)
{
if (a)
- detach2(a->elements.length() + 1);
+ detach(a->elements.size() + 1);
else
a = new QCborContainerPrivate;
- Q_ASSERT (i >= 0 && i <= a->elements.length());
+ Q_ASSERT (i >= 0 && i <= a->elements.size());
a->insertAt(i, value.type() == QJsonValue::Undefined ? QCborValue(nullptr)
: QCborValue::fromJsonValue(value));
}
@@ -477,10 +425,10 @@ void QJsonArray::insert(int i, const QJsonValue &value)
\sa operator[](), removeAt()
*/
-void QJsonArray::replace(int i, const QJsonValue &value)
+void QJsonArray::replace(qsizetype i, const QJsonValue &value)
{
- Q_ASSERT (a && i >= 0 && i < a->elements.length());
- detach2();
+ Q_ASSERT (a && i >= 0 && i < a->elements.size());
+ detach();
a->replaceAt(i, QCborValue::fromJsonValue(value));
}
@@ -491,7 +439,7 @@ void QJsonArray::replace(int i, const QJsonValue &value)
*/
bool QJsonArray::contains(const QJsonValue &value) const
{
- for (int i = 0; i < size(); i++) {
+ for (qsizetype i = 0; i < size(); i++) {
if (at(i) == value)
return true;
}
@@ -511,9 +459,9 @@ bool QJsonArray::contains(const QJsonValue &value) const
\sa at()
*/
-QJsonValueRef QJsonArray::operator [](int i)
+QJsonValueRef QJsonArray::operator [](qsizetype i)
{
- Q_ASSERT(a && i >= 0 && i < a->elements.length());
+ Q_ASSERT(a && i >= 0 && i < a->elements.size());
return QJsonValueRef(this, i);
}
@@ -522,41 +470,45 @@ QJsonValueRef QJsonArray::operator [](int i)
Same as at().
*/
-QJsonValue QJsonArray::operator[](int i) const
+QJsonValue QJsonArray::operator[](qsizetype i) const
{
return at(i);
}
-/*!
- Returns \c true if this array is equal to \a other.
- */
-bool QJsonArray::operator==(const QJsonArray &other) const
+bool comparesEqual(const QJsonArray &lhs, const QJsonArray &rhs) noexcept
{
- if (a == other.a)
+ if (lhs.a == rhs.a)
return true;
- if (!a)
- return !other.a->elements.length();
- if (!other.a)
- return !a->elements.length();
- if (a->elements.length() != other.a->elements.length())
+ if (!lhs.a)
+ return !rhs.a->elements.size();
+ if (!rhs.a)
+ return !lhs.a->elements.size();
+ if (lhs.a->elements.size() != rhs.a->elements.size())
return false;
- for (int i = 0; i < a->elements.length(); ++i) {
- if (a->valueAt(i) != other.a->valueAt(i))
+ for (qsizetype i = 0; i < lhs.a->elements.size(); ++i) {
+ if (lhs.a->valueAt(i) != rhs.a->valueAt(i))
return false;
}
return true;
}
-/*!
- Returns \c true if this array is not equal to \a other.
- */
-bool QJsonArray::operator!=(const QJsonArray &other) const
+bool comparesEqual(const QJsonArray &lhs, const QJsonValue &rhs) noexcept
{
- return !(*this == other);
+ return lhs == rhs.toArray();
}
+/*! \fn bool QJsonArray::operator==(const QJsonArray &lhs, const QJsonArray &rhs)
+
+ Returns \c true if \a lhs array is equal to \a rhs, \c false otherwise.
+*/
+
+/*! \fn bool QJsonArray::operator!=(const QJsonArray &lhs, const QJsonArray &rhs)
+
+ Returns \c true if \a lhs array is not equal to \a rhs, \c false otherwise.
+*/
+
/*! \fn QJsonArray::iterator QJsonArray::begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
@@ -651,6 +603,10 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\inmodule QtCore
\brief The QJsonArray::iterator class provides an STL-style non-const iterator for QJsonArray.
+ \compares strong
+ \compareswith strong QJsonArray::const_iterator
+ \endcompareswith
+
QJsonArray::iterator allows you to iterate over a QJsonArray
and to modify the array item associated with the
iterator. If you want to iterate over a const QJsonArray, use
@@ -713,7 +669,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa QJsonArray::begin(), QJsonArray::end()
*/
-/*! \fn QJsonArray::iterator::iterator(QJsonArray *array, int index)
+/*! \fn QJsonArray::iterator::iterator(QJsonArray *array, qsizetype index)
\internal
*/
@@ -737,7 +693,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
Returns a pointer to a modifiable reference to the current item.
*/
-/*! \fn QJsonValueRef QJsonArray::iterator::operator[](int j) const
+/*! \fn QJsonValueRef QJsonArray::iterator::operator[](qsizetype j) const
Returns a modifiable reference to the item at offset \a j from the
item pointed to by this iterator (the item at position \c{*this + j}).
@@ -755,60 +711,60 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
*/
/*!
- \fn bool QJsonArray::iterator::operator==(const iterator &other) const
- \fn bool QJsonArray::iterator::operator==(const const_iterator &other) const
+ \fn bool QJsonArray::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator==(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QJsonArray::iterator::operator!=(const iterator &other) const
- \fn bool QJsonArray::iterator::operator!=(const const_iterator &other) const
+ \fn bool QJsonArray::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator!=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonArray::iterator::operator<(const iterator& other) const
- \fn bool QJsonArray::iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator<(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator<(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::iterator::operator<=(const iterator& other) const
- \fn bool QJsonArray::iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator<=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator<=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::iterator::operator>(const iterator& other) const
- \fn bool QJsonArray::iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator>(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator>(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::iterator::operator>=(const iterator& other) const
- \fn bool QJsonArray::iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator>=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator>=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the
next item in the array and returns an iterator to the new current
item.
@@ -821,14 +777,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the
next item in the array and returns an iterator to the previously
current item.
*/
/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item
+ The prefix \c{--} operator, \c{--it}, makes the preceding item
current and returns an iterator to the new current item.
Calling this function on QJsonArray::begin() leads to undefined results.
@@ -840,11 +796,11 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix -- operator, \c{it--}, makes the preceding item
+ The postfix \c{--} operator, \c{it--}, makes the preceding item
current and returns an iterator to the previously current item.
*/
-/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator+=(int j)
+/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -852,7 +808,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(int j)
+/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -860,7 +816,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+=(), operator-()
*/
-/*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(int j) const
+/*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -868,7 +824,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-(), operator+=()
*/
-/*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(int j) const
+/*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -876,7 +832,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+(), operator-=()
*/
-/*! \fn int QJsonArray::iterator::operator-(iterator other) const
+/*! \fn qsizetype QJsonArray::iterator::operator-(iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
@@ -886,6 +842,10 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\inmodule QtCore
\brief The QJsonArray::const_iterator class provides an STL-style const iterator for QJsonArray.
+ \compares strong
+ \compareswith strong QJsonArray::iterator
+ \endcompareswith
+
QJsonArray::const_iterator allows you to iterate over a
QJsonArray. If you want to modify the QJsonArray as
you iterate over it, use QJsonArray::iterator instead. It is generally a
@@ -922,7 +882,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa QJsonArray::constBegin(), QJsonArray::constEnd()
*/
-/*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, int index)
+/*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, qsizetype index)
\internal
*/
@@ -952,27 +912,22 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\internal
*/
-/*! \fn QJsonArray::const_iterator::const_iterator(const const_iterator &other)
-
- Constructs a copy of \a other.
-*/
-
/*! \fn QJsonArray::const_iterator::const_iterator(const iterator &other)
Constructs a copy of \a other.
*/
-/*! \fn QJsonValue QJsonArray::const_iterator::operator*() const
+/*! \fn const QJsonValueRef QJsonArray::const_iterator::operator*() const
Returns the current item.
*/
-/*! \fn QJsonValue *QJsonArray::const_iterator::operator->() const
+/*! \fn const QJsonValueRef *QJsonArray::const_iterator::operator->() const
Returns a pointer to the current item.
*/
-/*! \fn QJsonValue QJsonArray::const_iterator::operator[](int j) const
+/*! \fn QJsonValue QJsonArray::const_iterator::operator[](qsizetype j) const
Returns the item at offset \a j from the item pointed to by this iterator (the item at
position \c{*this + j}).
@@ -983,53 +938,53 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+()
*/
-/*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &other) const
+/*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
-/*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &other) const
+/*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonArray::const_iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator<(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::const_iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator<=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::const_iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator>(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::const_iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator>=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the
next item in the array and returns an iterator to the new current
item.
@@ -1042,14 +997,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the
next item in the array and returns an iterator to the previously
current item.
*/
/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item
+ The prefix \c{--} operator, \c{--it}, makes the preceding item
current and returns an iterator to the new current item.
Calling this function on QJsonArray::begin() leads to undefined results.
@@ -1061,11 +1016,11 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix -- operator, \c{it--}, makes the preceding item
+ The postfix \c{--} operator, \c{it--}, makes the preceding item
current and returns an iterator to the previously current item.
*/
-/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator+=(int j)
+/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -1073,7 +1028,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(int j)
+/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -1081,7 +1036,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+=(), operator-()
*/
-/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(int j) const
+/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -1089,7 +1044,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-(), operator+=()
*/
-/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(int j) const
+/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -1097,27 +1052,16 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+(), operator-=()
*/
-/*! \fn int QJsonArray::const_iterator::operator-(const_iterator other) const
+/*! \fn qsizetype QJsonArray::const_iterator::operator-(const_iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
*/
-
-/*!
- \internal
- */
-void QJsonArray::detach(uint reserve)
-{
- Q_UNUSED(reserve)
- Q_ASSERT(!reserve);
- detach2(0);
-}
-
/*!
\internal
*/
-bool QJsonArray::detach2(uint reserve)
+bool QJsonArray::detach(qsizetype reserve)
{
if (!a)
return true;
@@ -1125,14 +1069,6 @@ bool QJsonArray::detach2(uint reserve)
return a;
}
-/*!
- \internal
- */
-void QJsonArray::compact()
-{
- a->compact(a->elements.size());
-}
-
size_t qHash(const QJsonArray &array, size_t seed)
{
return qHashRange(array.begin(), array.end(), seed);
@@ -1158,9 +1094,7 @@ QDebug operator<<(QDebug dbg, const QJsonArray &a)
#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &stream, const QJsonArray &array)
{
- QJsonDocument doc{array};
- stream << doc.toJson(QJsonDocument::Compact);
- return stream;
+ return stream << QJsonDocument{array};
}
QDataStream &operator>>(QDataStream &stream, QJsonArray &array)
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 4466210ce6..26a04e9196 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONARRAY_H
#define QJSONARRAY_H
@@ -48,7 +12,6 @@
QT_BEGIN_NAMESPACE
class QDebug;
-class QStringList;
typedef QList<QVariant> QVariantList;
class Q_CORE_EXPORT QJsonArray
@@ -60,8 +23,8 @@ public:
~QJsonArray();
- QJsonArray(const QJsonArray &other);
- QJsonArray &operator =(const QJsonArray &other);
+ QJsonArray(const QJsonArray &other) noexcept;
+ QJsonArray &operator =(const QJsonArray &other) noexcept;
QJsonArray(QJsonArray &&other) noexcept;
@@ -75,136 +38,233 @@ public:
static QJsonArray fromVariantList(const QVariantList &list);
QVariantList toVariantList() const;
- int size() const;
- inline int count() const { return size(); }
+ qsizetype size() const;
+ inline qsizetype count() const { return size(); }
bool isEmpty() const;
- QJsonValue at(int i) const;
+ QJsonValue at(qsizetype i) const;
QJsonValue first() const;
QJsonValue last() const;
void prepend(const QJsonValue &value);
void append(const QJsonValue &value);
- void removeAt(int i);
- QJsonValue takeAt(int i);
+ void removeAt(qsizetype i);
+ QJsonValue takeAt(qsizetype i);
inline void removeFirst() { removeAt(0); }
inline void removeLast() { removeAt(size() - 1); }
- void insert(int i, const QJsonValue &value);
- void replace(int i, const QJsonValue &value);
+ void insert(qsizetype i, const QJsonValue &value);
+ void replace(qsizetype i, const QJsonValue &value);
bool contains(const QJsonValue &element) const;
- QJsonValueRef operator[](int i);
- QJsonValue operator[](int i) const;
+ QJsonValueRef operator[](qsizetype i);
+ QJsonValue operator[](qsizetype i) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonArray &other) const;
bool operator!=(const QJsonArray &other) const;
-
+#endif
void swap(QJsonArray &other) noexcept
{
- qSwap(a, other.a);
+ a.swap(other.a);
}
class const_iterator;
class iterator {
public:
- QJsonArray *a;
- int i;
typedef std::random_access_iterator_tag iterator_category;
- typedef int difference_type;
+ typedef qsizetype difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
- typedef QJsonValueRefPtr pointer;
-
- inline iterator() : a(nullptr), i(0) { }
- explicit inline iterator(QJsonArray *array, int index) : a(array), i(index) { }
-
- inline QJsonValueRef operator*() const { return QJsonValueRef(a, i); }
-#ifdef Q_QDOC
- inline QJsonValueRef* operator->() const;
-#else
- inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(a, i); }
+ typedef QJsonValueRef *pointer;
+
+ inline iterator() : item(static_cast<QJsonArray *>(nullptr), 0) { }
+ explicit inline iterator(QJsonArray *array, qsizetype index) : item(array, index) { }
+
+ constexpr iterator(const iterator &other) = default;
+ iterator &operator=(const iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline QJsonValueRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+ inline QJsonValueRef *operator->() { return &item; }
+ inline QJsonValueRef operator[](qsizetype j) const { return *(*this + j); }
+
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const iterator &o) const
+ { return item.d == o.item.d && item.index == o.item.index; }
+ inline bool operator!=(const iterator &o) const { return !operator==(o); }
+ inline bool operator<(const iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ inline bool operator<=(const iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ inline bool operator>(const iterator &other) const { return !operator<=(other); }
+ inline bool operator>=(const iterator &other) const { return !operator<(other); }
+ inline bool operator==(const const_iterator &o) const
+ { return item.d == o.item.d && item.index == o.item.index; }
+ inline bool operator!=(const const_iterator &o) const { return !operator==(o); }
+ inline bool operator<(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ inline bool operator<=(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ inline bool operator>(const const_iterator &other) const { return !operator<=(other); }
+ inline bool operator>=(const const_iterator &other) const { return !operator<(other); }
#endif
- inline QJsonValueRef operator[](int j) const { return QJsonValueRef(a, i + j); }
-
- inline bool operator==(const iterator &o) const { return i == o.i; }
- inline bool operator!=(const iterator &o) const { return i != o.i; }
- inline bool operator<(const iterator& other) const { return i < other.i; }
- inline bool operator<=(const iterator& other) const { return i <= other.i; }
- inline bool operator>(const iterator& other) const { return i > other.i; }
- inline bool operator>=(const iterator& other) const { return i >= other.i; }
- inline bool operator==(const const_iterator &o) const { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const { return i != o.i; }
- inline bool operator<(const const_iterator& other) const { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
- inline iterator &operator++() { ++i; return *this; }
- inline iterator operator++(int) { iterator n = *this; ++i; return n; }
- inline iterator &operator--() { i--; return *this; }
- inline iterator operator--(int) { iterator n = *this; i--; return n; }
- inline iterator &operator+=(int j) { i+=j; return *this; }
- inline iterator &operator-=(int j) { i-=j; return *this; }
- inline iterator operator+(int j) const { return iterator(a, i+j); }
- inline iterator operator-(int j) const { return iterator(a, i-j); }
- inline int operator-(iterator j) const { return i - j.i; }
+ inline iterator &operator++() { ++item.index; return *this; }
+ inline iterator operator++(int) { iterator n = *this; ++item.index; return n; }
+ inline iterator &operator--() { item.index--; return *this; }
+ inline iterator operator--(int) { iterator n = *this; item.index--; return n; }
+ inline iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ inline iterator operator+(qsizetype j) const { iterator r = *this; return r += j; }
+ inline iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline qsizetype operator-(iterator j) const { return item.index - j.item.index; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+
+ static bool comparesEqual_helper(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator)
+ friend bool comparesEqual(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator, const_iterator)
+
+ QJsonValueRef item;
+ friend class QJsonArray;
};
friend class iterator;
class const_iterator {
public:
- const QJsonArray *a;
- int i;
typedef std::random_access_iterator_tag iterator_category;
typedef qptrdiff difference_type;
typedef QJsonValue value_type;
- typedef QJsonValue reference;
- typedef QJsonValuePtr pointer;
-
- inline const_iterator() : a(nullptr), i(0) { }
- explicit inline const_iterator(const QJsonArray *array, int index) : a(array), i(index) { }
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- inline const_iterator(const const_iterator &o) : a(o.a), i(o.i) {} // ### Qt 6: Removed so class can be trivially-copyable
-#endif
- inline const_iterator(const iterator &o) : a(o.a), i(o.i) {}
-
- inline QJsonValue operator*() const { return a->at(i); }
-#ifdef Q_QDOC
- inline QJsonValue* operator->() const;
-#else
- inline QJsonValuePtr operator->() const { return QJsonValuePtr(a->at(i)); }
+ typedef const QJsonValueRef reference;
+ typedef const QJsonValueRef *pointer;
+
+ inline const_iterator() : item(static_cast<QJsonArray *>(nullptr), 0) { }
+ explicit inline const_iterator(const QJsonArray *array, qsizetype index)
+ : item(const_cast<QJsonArray *>(array), index) { }
+ inline const_iterator(const iterator &o) : item(o.item) { }
+
+ constexpr const_iterator(const const_iterator &other) = default;
+ const_iterator &operator=(const const_iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline const QJsonValueConstRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+
+ inline QJsonValueConstRef operator[](qsizetype j) const { return *(*this + j); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const const_iterator &o) const
+ { return item.d == o.item.d && item.index == o.item.index; }
+ inline bool operator!=(const const_iterator &o) const { return !operator==(o); }
+ inline bool operator<(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ inline bool operator<=(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ inline bool operator>(const const_iterator &other) const { return !operator<=(other); }
+ inline bool operator>=(const const_iterator &other) const { return !operator<(other); }
#endif
- inline QJsonValue operator[](int j) const { return a->at(i+j); }
- inline bool operator==(const const_iterator &o) const { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const { return i != o.i; }
- inline bool operator<(const const_iterator& other) const { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
- inline const_iterator &operator++() { ++i; return *this; }
- inline const_iterator operator++(int) { const_iterator n = *this; ++i; return n; }
- inline const_iterator &operator--() { i--; return *this; }
- inline const_iterator operator--(int) { const_iterator n = *this; i--; return n; }
- inline const_iterator &operator+=(int j) { i+=j; return *this; }
- inline const_iterator &operator-=(int j) { i-=j; return *this; }
- inline const_iterator operator+(int j) const { return const_iterator(a, i+j); }
- inline const_iterator operator-(int j) const { return const_iterator(a, i-j); }
- inline int operator-(const_iterator j) const { return i - j.i; }
+ inline const_iterator &operator++() { ++item.index; return *this; }
+ inline const_iterator operator++(int) { const_iterator n = *this; ++item.index; return n; }
+ inline const_iterator &operator--() { item.index--; return *this; }
+ inline const_iterator operator--(int) { const_iterator n = *this; item.index--; return n; }
+ inline const_iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline const_iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ inline const_iterator operator+(qsizetype j) const { const_iterator r = *this; return r += j; }
+ inline const_iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline qsizetype operator-(const_iterator j) const { return item.index - j.item.index; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(const_iterator)
+ QJsonValueConstRef item;
+ friend class QJsonArray;
};
friend class const_iterator;
// stl style
- inline iterator begin() { detach2(); return iterator(this, 0); }
+ inline iterator begin() { detach(); return iterator(this, 0); }
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator constBegin() const { return const_iterator(this, 0); }
inline const_iterator cbegin() const { return const_iterator(this, 0); }
- inline iterator end() { detach2(); return iterator(this, size()); }
+ inline iterator end() { detach(); return iterator(this, size()); }
inline const_iterator end() const { return const_iterator(this, size()); }
inline const_iterator constEnd() const { return const_iterator(this, size()); }
inline const_iterator cend() const { return const_iterator(this, size()); }
- iterator insert(iterator before, const QJsonValue &value) { insert(before.i, value); return before; }
- iterator erase(iterator it) { removeAt(it.i); return it; }
+ iterator insert(iterator before, const QJsonValue &value)
+ { insert(before.item.index, value); return before; }
+ iterator erase(iterator it)
+ { removeAt(it.item.index); return it; }
// more Qt
typedef iterator Iterator;
@@ -224,34 +284,45 @@ public:
inline void pop_front() { removeFirst(); }
inline void pop_back() { removeLast(); }
inline bool empty() const { return isEmpty(); }
- typedef int size_type;
+ typedef qsizetype size_type;
typedef QJsonValue value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef QJsonValueRef reference;
typedef QJsonValue const_reference;
- typedef int difference_type;
+ typedef qsizetype difference_type;
private:
friend class QJsonValue;
+ friend class QJsonValueConstRef;
+ friend class QJsonValueRef;
+ friend class QJsonPrivate::Value;
friend class QJsonDocument;
friend class QCborArray;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonArray &lhs,
+ const QJsonArray &rhs) noexcept;
+
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonArray &lhs,
+ const QJsonValue &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonArray)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonArray, QJsonValue)
+
QJsonArray(QCborContainerPrivate *array);
- void initialize();
- void compact();
- // ### Qt 6: remove me and merge with detach2
- void detach(uint reserve = 0);
- bool detach2(uint reserve = 0);
-
- // ### Qt 6: remove
- void *dead = nullptr;
+ bool detach(qsizetype reserve = 0);
+
QExplicitlySharedDataPointer<QCborContainerPrivate> a;
};
Q_DECLARE_SHARED(QJsonArray)
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+inline QJsonValueConstRef::QJsonValueConstRef(QJsonArray *a, qsizetype idx)
+ : d(a ? a->a.data() : nullptr), is_object(false), index(idx)
+{}
+#endif
+
Q_CORE_EXPORT size_t qHash(const QJsonArray &array, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index 8bb04fa3bf..da07eca8a7 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborvalue.h"
#include "qcborvalue_p.h"
@@ -48,6 +12,9 @@
#include "qjsondocument.h"
#include "qjson_p.h"
+#include <qmap.h>
+#include <qhash.h>
+
#include <private/qnumeric_p.h>
#include <quuid.h>
@@ -55,6 +22,8 @@ QT_BEGIN_NAMESPACE
using namespace QtCbor;
+enum class ConversionMode { FromRaw, FromVariantToJson };
+
static QJsonValue fpToJson(double v)
{
return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
@@ -89,13 +58,13 @@ static QString encodeByteArray(const QCborContainerPrivate *d, qsizetype idx, QC
return QString::fromLatin1(data, data.size());
}
-static QString makeString(const QCborContainerPrivate *d, qsizetype idx);
+static QString makeString(const QCborContainerPrivate *d, qsizetype idx,
+ ConversionMode mode = ConversionMode::FromRaw);
static QString maybeEncodeTag(const QCborContainerPrivate *d)
{
qint64 tag = d->elements.at(0).value;
const Element &e = d->elements.at(1);
- const ByteData *b = d->byteData(e);
switch (tag) {
case qint64(QCborKnownTags::DateTimeString):
@@ -112,8 +81,12 @@ static QString maybeEncodeTag(const QCborContainerPrivate *d)
break;
case qint64(QCborKnownTags::Uuid):
- if (e.type == QCborValue::ByteArray && b->len == sizeof(QUuid))
+#ifndef QT_BOOTSTRAPPED
+ if (const ByteData *b = d->byteData(e); e.type == QCborValue::ByteArray && b
+ && b->len == sizeof(QUuid))
return QUuid::fromRfc4122(b->asByteArrayView()).toString(QUuid::WithoutBraces);
+#endif
+ break;
}
// don't know what to do, bail out
@@ -134,7 +107,8 @@ static QString encodeTag(const QCborContainerPrivate *d)
return s;
}
-static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizetype idx)
+static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizetype idx,
+ ConversionMode mode)
{
const auto &e = d->elements.at(idx);
@@ -146,7 +120,9 @@ static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizety
return QString::number(e.fpvalue());
case QCborValue::ByteArray:
- return encodeByteArray(d, idx, QCborTag(QCborKnownTags::ExpectedBase64url));
+ return mode == ConversionMode::FromVariantToJson
+ ? d->stringAt(idx)
+ : encodeByteArray(d, idx, QCborTag(QCborKnownTags::ExpectedBase64url));
case QCborValue::String:
return d->stringAt(idx);
@@ -190,19 +166,23 @@ static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizety
return simpleTypeString(e.type);
}
-QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx);
+QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx,
+ ConversionMode mode = ConversionMode::FromRaw);
static QJsonValue convertExtendedTypeToJson(QCborContainerPrivate *d)
{
-#ifndef QT_BUILD_QMAKE
qint64 tag = d->elements.at(0).value;
switch (tag) {
case qint64(QCborKnownTags::Url):
- // use the fullly-encoded URL form
+#ifdef QT_BOOTSTRAPPED
+ break;
+#else
+ // use the fully-encoded URL form
if (d->elements.at(1).type == QCborValue::String)
return QUrl::fromEncoded(d->byteData(1)->asByteArrayView()).toString(QUrl::FullyEncoded);
Q_FALLTHROUGH();
+#endif
case qint64(QCborKnownTags::DateTimeString):
case qint64(QCborKnownTags::ExpectedBase64url):
@@ -215,42 +195,43 @@ static QJsonValue convertExtendedTypeToJson(QCborContainerPrivate *d)
return s;
}
}
-#endif
// for all other tags, ignore it and return the converted tagged item
return qt_convertToJson(d, 1);
}
// We need to do this because sub-objects may need conversion.
-static QJsonArray convertToJsonArray(QCborContainerPrivate *d)
+static QJsonArray convertToJsonArray(QCborContainerPrivate *d,
+ ConversionMode mode = ConversionMode::FromRaw)
{
QJsonArray a;
if (d) {
for (qsizetype idx = 0; idx < d->elements.size(); ++idx)
- a.append(qt_convertToJson(d, idx));
+ a.append(qt_convertToJson(d, idx, mode));
}
return a;
}
// We need to do this because the keys need to be sorted and converted to strings
// and sub-objects may need recursive conversion.
-static QJsonObject convertToJsonObject(QCborContainerPrivate *d)
+static QJsonObject convertToJsonObject(QCborContainerPrivate *d,
+ ConversionMode mode = ConversionMode::FromRaw)
{
QJsonObject o;
if (d) {
for (qsizetype idx = 0; idx < d->elements.size(); idx += 2)
- o.insert(makeString(d, idx), qt_convertToJson(d, idx + 1));
+ o.insert(makeString(d, idx), qt_convertToJson(d, idx + 1, mode));
}
return o;
}
-QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
+QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx, ConversionMode mode)
{
// encoding the container itself
if (idx == -QCborValue::Array)
- return convertToJsonArray(d);
+ return convertToJsonArray(d, mode);
if (idx == -QCborValue::Map)
- return convertToJsonObject(d);
+ return convertToJsonObject(d, mode);
if (idx < 0) {
// tag-like type
if (!d || d->elements.size() != 2)
@@ -264,6 +245,15 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
case QCborValue::Integer:
return QJsonValue(e.value);
case QCborValue::ByteArray:
+ if (mode == ConversionMode::FromVariantToJson) {
+ const auto value = makeString(d, idx, mode);
+ return value.isEmpty() ? QJsonValue() : QJsonPrivate::Value::fromTrustedCbor(value);
+ }
+ break;
+ case QCborValue::RegularExpression:
+ if (mode == ConversionMode::FromVariantToJson)
+ return QJsonValue();
+ break;
case QCborValue::String:
case QCborValue::SimpleType:
// make string
@@ -274,10 +264,10 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
case QCborValue::Tag:
case QCborValue::DateTime:
case QCborValue::Url:
- case QCborValue::RegularExpression:
case QCborValue::Uuid:
// recurse
- return qt_convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type);
+ return qt_convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type,
+ mode);
case QCborValue::Null:
case QCborValue::Undefined:
@@ -294,7 +284,7 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
return fpToJson(e.fpvalue());
}
- return QJsonPrivate::Value::fromTrustedCbor(makeString(d, idx));
+ return QJsonPrivate::Value::fromTrustedCbor(makeString(d, idx, mode));
}
/*!
@@ -408,10 +398,12 @@ QJsonValue QCborValue::toJsonValue() const
return QJsonPrivate::Value::fromTrustedCbor(simpleTypeString(type()));
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QJsonValue QCborValueRef::toJsonValue() const
{
return qt_convertToJson(d, i);
}
+#endif
/*!
Recursively converts every \l QCborValue element in this array to JSON
@@ -429,6 +421,14 @@ QJsonArray QCborArray::toJsonArray() const
return convertToJsonArray(d.data());
}
+#ifndef QT_NO_VARIANT
+QJsonArray QJsonPrivate::Variant::toJsonArray(const QVariantList &list)
+{
+ const auto cborArray = QCborArray::fromVariantList(list);
+ return convertToJsonArray(cborArray.d.data(), ConversionMode::FromVariantToJson);
+}
+#endif // !QT_NO_VARIANT
+
/*!
Recursively converts every \l QCborValue value in this map to JSON using
QCborValue::toJsonValue() and creates a string key for all keys that aren't
@@ -471,6 +471,13 @@ QJsonObject QCborMap::toJsonObject() const
return convertToJsonObject(d.data());
}
+#ifndef QT_NO_VARIANT
+QJsonObject QJsonPrivate::Variant::toJsonObject(const QVariantMap &map)
+{
+ const auto cborMap = QCborMap::fromVariantMap(map);
+ return convertToJsonObject(cborMap.d.data(), ConversionMode::FromVariantToJson);
+}
+
/*!
Converts this value to a native Qt type and returns the corresponding QVariant.
@@ -552,15 +559,15 @@ QVariant QCborValue::toVariant() const
#ifndef QT_BOOTSTRAPPED
case Url:
return toUrl();
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
case RegularExpression:
return toRegularExpression();
-#endif
+# endif
case Uuid:
return toUuid();
+#endif
case Invalid:
return QVariant();
@@ -572,9 +579,9 @@ QVariant QCborValue::toVariant() const
if (isSimpleType())
return QVariant::fromValue(toSimpleType());
- Q_UNREACHABLE();
- return QVariant();
+ Q_UNREACHABLE_RETURN(QVariant());
}
+#endif // !QT_NO_VARIANT
/*!
Converts the JSON value contained in \a v into its corresponding CBOR value
@@ -610,7 +617,7 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
case QJsonValue::Bool:
return v.toBool();
case QJsonValue::Double: {
- if (v.t == Integer)
+ if (v.value.t == Integer)
return v.toInteger();
return v.toDouble();
}
@@ -628,11 +635,12 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
return QCborValue();
}
+#ifndef QT_NO_VARIANT
static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
{
// Handle strings and byte arrays directly, to avoid creating a temporary
// dummy container to hold their data.
- int type = variant.userType();
+ int type = variant.metaType().id();
if (type == QMetaType::QString) {
d->append(variant.toString());
} else if (type == QMetaType::QByteArray) {
@@ -679,21 +687,26 @@ static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
\row \li \l QUuid \li Uuid
\endtable
- For any other types, this function will return Null if the QVariant itself
- is null, and otherwise will try to convert to string using
- QVariant::toString(). If the conversion to string fails, this function
- returns Undefined.
+ If QVariant::isNull() returns true, a null QCborValue is returned or
+ inserted into the list or object, regardless of the type carried by
+ QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull()
+ also affects this function.
+
+ For other types not listed above, a conversion to string will be attempted,
+ usually but not always by calling QVariant::toString(). If the conversion
+ fails the value is replaced by an Undefined CBOR value. Note that
+ QVariant::toString() is also lossy for the majority of types.
Please note that the conversions via QVariant::toString() are subject to
- change at any time. QCborValue may be extended in the future to support
- more types, which will result in a change in how this function performs
- conversions.
+ change at any time. Both QVariant and QCborValue may be extended in the
+ future to support more types, which will result in a change in how this
+ function performs conversions.
- \sa toVariant(), fromJsonValue(), QCborArray::toVariantList(), QCborMap::toVariantMap()
+ \sa toVariant(), fromJsonValue(), QCborArray::toVariantList(), QCborMap::toVariantMap(), QJsonValue::fromVariant()
*/
QCborValue QCborValue::fromVariant(const QVariant &variant)
{
- switch (variant.userType()) {
+ switch (variant.metaType().id()) {
case QMetaType::UnknownType:
return {};
case QMetaType::Nullptr:
@@ -724,9 +737,9 @@ QCborValue QCborValue::fromVariant(const QVariant &variant)
#ifndef QT_BOOTSTRAPPED
case QMetaType::QUrl:
return QCborValue(variant.toUrl());
-#endif
case QMetaType::QUuid:
return QCborValue(variant.toUuid());
+#endif
case QMetaType::QVariantList:
return QCborArray::fromVariantList(variant.toList());
case QMetaType::QVariantMap:
@@ -823,6 +836,7 @@ QCborArray QCborArray::fromVariantList(const QVariantList &list)
appendVariant(a.d.data(), v);
return a;
}
+#endif // !QT_NO_VARIANT
/*!
Converts all JSON items found in the \a array array to CBOR using
@@ -843,6 +857,19 @@ QCborArray QCborArray::fromJsonArray(const QJsonArray &array)
}
/*!
+ \overload
+ \since 6.3
+ */
+QCborArray QCborArray::fromJsonArray(QJsonArray &&array) noexcept
+{
+ QCborArray result;
+ result.d = std::exchange(array.a, {});
+ return result;
+
+}
+
+#ifndef QT_NO_VARIANT
+/*!
Converts the CBOR values to QVariant using QCborValue::toVariant() and
"stringifies" all the CBOR keys in this map, returning the QVariantMap that
results from that association list.
@@ -938,6 +965,7 @@ QCborMap QCborMap::fromVariantHash(const QVariantHash &hash)
}
return m;
}
+#endif // !QT_NO_VARIANT
/*!
Converts all JSON items found in the \a obj object to CBOR using
@@ -956,4 +984,15 @@ QCborMap QCborMap::fromJsonObject(const QJsonObject &obj)
return result;
}
+/*!
+ \overload
+ \since 6.3
+ */
+QCborMap QCborMap::fromJsonObject(QJsonObject &&obj) noexcept
+{
+ QCborMap result;
+ result.d = std::exchange(obj.o, {});
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp
index 338b752f13..e2528f18dc 100644
--- a/src/corelib/serialization/qjsondocument.cpp
+++ b/src/corelib/serialization/qjsondocument.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsondocument.h>
#include <qjsonobject.h>
@@ -43,6 +7,8 @@
#include <qjsonarray.h>
#include <qstringlist.h>
#include <qvariant.h>
+#include <qmap.h>
+#include <qhash.h>
#include <qdebug.h>
#include <qcbormap.h>
#include <qcborarray.h>
@@ -52,28 +18,23 @@
#include "qjson_p.h"
#include "qdatastream.h"
-#if QT_CONFIG(binaryjson)
-#include "qbinaryjson_p.h"
-#include "qbinaryjsonobject_p.h"
-#include "qbinaryjsonarray_p.h"
-#endif
-
-#include <private/qmemory_p.h>
-
QT_BEGIN_NAMESPACE
/*! \class QJsonDocument
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonDocument class provides a way to read and write JSON documents.
- QJsonDocument is a class that wraps a complete JSON document and can read and
- write this document both from a UTF-8 encoded text based representation as well
- as Qt's own binary format.
+ \compares equality
+
+ QJsonDocument is a class that wraps a complete JSON document and can read
+ this document from, and write it to, a UTF-8 encoded text-based
+ representation.
A JSON document can be converted from its text-based representation to a QJsonDocument
using QJsonDocument::fromJson(). toJson() converts it back to text. The parser is very
@@ -85,10 +46,7 @@ QT_BEGIN_NAMESPACE
and isObject(). The array or object contained in the document can be retrieved using
array() or object() and then read or manipulated.
- A document can also be created from a stored binary representation using fromBinaryData() or
- fromRawData().
-
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
@@ -148,7 +106,7 @@ QJsonDocument::QJsonDocument(const QJsonArray &array)
\internal
*/
QJsonDocument::QJsonDocument(const QCborValue &data)
- : d(qt_make_unique<QJsonDocumentPrivate>(data))
+ : d(std::make_unique<QJsonDocumentPrivate>(data))
{
Q_ASSERT(d);
}
@@ -167,7 +125,7 @@ QJsonDocument::QJsonDocument(const QJsonDocument &other)
{
if (other.d) {
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
d->value = other.d->value;
} else {
d.reset();
@@ -193,7 +151,7 @@ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
if (this != &other) {
if (other.d) {
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
else
d->clearRawData();
d->value = other.d->value;
@@ -225,180 +183,7 @@ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
Swaps the document \a other with this. This operation is very fast and never fails.
*/
-
-/*! \enum QJsonDocument::DataValidation
-
- This value is used to tell QJsonDocument whether to validate the binary data
- when converting to a QJsonDocument using fromBinaryData() or fromRawData().
-
- \value Validate Validate the data before using it. This is the default.
- \value BypassValidation Bypasses data validation. Only use if you received the
- data from a trusted place and know it's valid, as using of invalid data can crash
- the application.
- */
-
-#if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
-/*!
- \deprecated
-
- Creates a QJsonDocument that uses the first \a size bytes from
- \a data. It assumes \a data contains a binary encoded JSON document.
- The created document does not take ownership of \a data. The data is
- copied into a different data structure, and the original data can be
- deleted or modified afterwards.
-
- \a data has to be aligned to a 4 byte boundary.
-
- \a validation decides whether the data is checked for validity before being used.
- By default the data is validated. If the \a data is not valid, the method returns
- a null document.
-
- Returns a QJsonDocument representing the data.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \note Before Qt 5.15, the caller had to guarantee that \a data would not be
- deleted or modified as long as any QJsonDocument, QJsonObject or QJsonArray
- still referenced the data. From Qt 5.15 on, this is not necessary anymore.
-
- \sa rawData(), fromBinaryData(), isNull(), DataValidation, QCborValue
- */
-QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation)
-{
- if (quintptr(data) & 3) {
- qWarning("QJsonDocument::fromRawData: data has to have 4 byte alignment");
- return QJsonDocument();
- }
-
- if (size < 0 || uint(size) < sizeof(QBinaryJsonPrivate::Header) + sizeof(QBinaryJsonPrivate::Base))
- return QJsonDocument();
-
- std::unique_ptr<QBinaryJsonPrivate::ConstData> binaryData
- = qt_make_unique<QBinaryJsonPrivate::ConstData>(data, size);
-
- return (validation == BypassValidation || binaryData->isValid())
- ? binaryData->toJsonDocument()
- : QJsonDocument();
-}
-
-/*!
- \deprecated
-
- Returns the raw binary representation of the data
- \a size will contain the size of the returned data.
-
- This method is useful to e.g. stream the JSON document
- in its binary form to a file.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \sa QCborValue
- */
-const char *QJsonDocument::rawData(int *size) const
-{
- if (!d) {
- *size = 0;
- return nullptr;
- }
-
- if (!d->rawData) {
- if (isObject()) {
- QBinaryJsonObject o = QBinaryJsonObject::fromJsonObject(object());
- d->rawData = o.takeRawData(&(d->rawDataSize));
- } else {
- QBinaryJsonArray a = QBinaryJsonArray::fromJsonArray(array());
- d->rawData = a.takeRawData(&(d->rawDataSize));
- }
- }
-
- // It would be quite miraculous if not, as we should have hit the 128MB limit then.
- Q_ASSERT(d->rawDataSize <= uint(std::numeric_limits<int>::max()));
-
- *size = d->rawDataSize;
- return d->rawData;
-}
-
-/*!
- \deprecated
- Creates a QJsonDocument from \a data.
-
- \a validation decides whether the data is checked for validity before being used.
- By default the data is validated. If the \a data is not valid, the method returns
- a null document.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \sa toBinaryData(), fromRawData(), isNull(), DataValidation, QCborValue
- */
-QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation)
-{
- if (uint(data.size()) < sizeof(QBinaryJsonPrivate::Header) + sizeof(QBinaryJsonPrivate::Base))
- return QJsonDocument();
-
- QBinaryJsonPrivate::Header h;
- memcpy(&h, data.constData(), sizeof(QBinaryJsonPrivate::Header));
- QBinaryJsonPrivate::Base root;
- memcpy(&root, data.constData() + sizeof(QBinaryJsonPrivate::Header),
- sizeof(QBinaryJsonPrivate::Base));
-
- const uint size = sizeof(QBinaryJsonPrivate::Header) + root.size;
- if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1U || size > uint(data.size()))
- return QJsonDocument();
-
- std::unique_ptr<QBinaryJsonPrivate::ConstData> d
- = qt_make_unique<QBinaryJsonPrivate::ConstData>(data.constData(), size);
-
- return (validation == BypassValidation || d->isValid())
- ? d->toJsonDocument()
- : QJsonDocument();
-}
-
-/*!
- \deprecated
- Returns a binary representation of the document.
-
- The binary representation is also the native format used internally in Qt,
- and is very efficient and fast to convert to and from.
-
- The binary format can be stored on disk and interchanged with other applications
- or computers. fromBinaryData() can be used to convert it back into a
- JSON document.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \sa fromBinaryData(), QCborValue
- */
-QByteArray QJsonDocument::toBinaryData() const
-{
- int size = 0;
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- const char *raw = rawData(&size);
-QT_WARNING_POP
- return QByteArray(raw, size);
-}
-#endif // QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
-
+#ifndef QT_NO_VARIANT
/*!
Creates a QJsonDocument from the QVariant \a variant.
@@ -411,7 +196,7 @@ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
{
QJsonDocument doc;
- switch (variant.userType()) {
+ switch (variant.metaType().id()) {
case QMetaType::QVariantMap:
doc.setObject(QJsonObject::fromVariantMap(variant.toMap()));
break;
@@ -422,7 +207,7 @@ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
doc.setArray(QJsonArray::fromVariantList(variant.toList()));
break;
case QMetaType::QStringList:
- doc.d = qt_make_unique<QJsonDocumentPrivate>();
+ doc.d = std::make_unique<QJsonDocumentPrivate>();
doc.d->value = QCborArray::fromStringList(variant.toStringList());
break;
default:
@@ -449,18 +234,7 @@ QVariant QJsonDocument::toVariant() const
return QJsonArray(container).toVariantList();
return QJsonObject(container).toVariantMap();
}
-
-/*!
- Converts the QJsonDocument to an indented, UTF-8 encoded JSON document.
-
- \sa fromJson()
- */
-#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC)
-QByteArray QJsonDocument::toJson() const
-{
- return toJson(Indented);
-}
-#endif
+#endif // !QT_NO_VARIANT
/*!
\enum QJsonDocument::JsonFormat
@@ -482,7 +256,7 @@ QByteArray QJsonDocument::toJson() const
\sa fromJson(), JsonFormat
*/
-#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC)
+#if !defined(QT_JSON_READONLY) || defined(Q_QDOC)
QByteArray QJsonDocument::toJson(JsonFormat format) const
{
QByteArray json;
@@ -511,11 +285,11 @@ QByteArray QJsonDocument::toJson(JsonFormat format) const
*/
QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error)
{
- QJsonPrivate::Parser parser(json.constData(), json.length());
+ QJsonPrivate::Parser parser(json.constData(), json.size());
QJsonDocument result;
const QCborValue val = parser.parse(error);
if (val.isArray() || val.isMap()) {
- result.d = qt_make_unique<QJsonDocumentPrivate>();
+ result.d = std::make_unique<QJsonDocumentPrivate>();
result.d->value = val;
}
return result;
@@ -600,7 +374,7 @@ QJsonArray QJsonDocument::array() const
void QJsonDocument::setObject(const QJsonObject &object)
{
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
else
d->clearRawData();
@@ -615,14 +389,13 @@ void QJsonDocument::setObject(const QJsonObject &object)
void QJsonDocument::setArray(const QJsonArray &array)
{
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
else
d->clearRawData();
d->value = QCborValue::fromJsonValue(array);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -639,7 +412,6 @@ const QJsonValue QJsonDocument::operator[](const QString &key) const
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\overload
@@ -657,7 +429,7 @@ const QJsonValue QJsonDocument::operator[](QStringView key) const
\overload
\since 5.10
*/
-const QJsonValue QJsonDocument::operator[](QLatin1String key) const
+const QJsonValue QJsonDocument::operator[](QLatin1StringView key) const
{
if (!isObject())
return QJsonValue(QJsonValue::Undefined);
@@ -677,7 +449,7 @@ const QJsonValue QJsonDocument::operator[](QLatin1String key) const
\sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
*/
-const QJsonValue QJsonDocument::operator[](int i) const
+const QJsonValue QJsonDocument::operator[](qsizetype i) const
{
if (!isArray())
return QJsonValue(QJsonValue::Undefined);
@@ -686,18 +458,22 @@ const QJsonValue QJsonDocument::operator[](int i) const
}
/*!
- Returns \c true if the \a other document is equal to this document.
- */
-bool QJsonDocument::operator==(const QJsonDocument &other) const
+ \fn bool QJsonDocument::operator==(const QJsonDocument &lhs, const QJsonDocument &rhs)
+
+ Returns \c true if the \a lhs document is equal to \a rhs document, \c false otherwise.
+*/
+bool comparesEqual(const QJsonDocument &lhs, const QJsonDocument &rhs) noexcept
{
- return (!d) ? (!other.d) : (d->value == other.d->value);
+ if (lhs.d && rhs.d)
+ return lhs.d->value == rhs.d->value;
+ return !lhs.d == !rhs.d;
}
/*!
- \fn bool QJsonDocument::operator!=(const QJsonDocument &other) const
+ \fn bool QJsonDocument::operator!=(const QJsonDocument &lhs, const QJsonDocument &rhs)
- returns \c true if \a other is not equal to this document
- */
+ Returns \c true if the \a lhs document is not equal to \a rhs document, \c false otherwise.
+*/
/*!
returns \c true if this document is null.
diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h
index 8c2840eda7..3659f7b5cb 100644
--- a/src/corelib/serialization/qjsondocument.h
+++ b/src/corelib/serialization/qjsondocument.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONDOCUMENT_H
#define QJSONDOCUMENT_H
+#include <QtCore/qcompare.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qscopedpointer.h>
@@ -106,25 +71,6 @@ public:
void swap(QJsonDocument &other) noexcept;
- enum DataValidation {
- Validate,
- BypassValidation
- };
-
-#if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use CBOR format instead")
- static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate);
-
- QT_DEPRECATED_X("Use CBOR format instead")
- const char *rawData(int *size) const;
-
- QT_DEPRECATED_X("Use CBOR format instead")
- static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
-
- QT_DEPRECATED_X("Use CBOR format instead")
- QByteArray toBinaryData() const;
-#endif // QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
-
static QJsonDocument fromVariant(const QVariant &variant);
QVariant toVariant() const;
@@ -135,9 +81,8 @@ public:
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = nullptr);
-#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC)
- QByteArray toJson() const; //### Merge in Qt6
- QByteArray toJson(JsonFormat format) const;
+#if !defined(QT_JSON_READONLY) || defined(Q_QDOC)
+ QByteArray toJson(JsonFormat format = Indented) const;
#endif
bool isEmpty() const;
@@ -150,22 +95,23 @@ public:
void setObject(const QJsonObject &object);
void setArray(const QJsonArray &array);
-#if QT_STRINGVIEW_LEVEL < 2
const QJsonValue operator[](const QString &key) const;
-#endif
const QJsonValue operator[](QStringView key) const;
- const QJsonValue operator[](QLatin1String key) const;
- const QJsonValue operator[](int i) const;
-
+ const QJsonValue operator[](QLatin1StringView key) const;
+ const QJsonValue operator[](qsizetype i) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonDocument &other) const;
- bool operator!=(const QJsonDocument &other) const { return !(*this == other); }
-
+ bool operator!=(const QJsonDocument &other) const { return !operator==(other); }
+#endif
bool isNull() const;
private:
friend class QJsonValue;
friend class QJsonPrivate::Parser;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonDocument &lhs,
+ const QJsonDocument &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonDocument)
QJsonDocument(const QCborValue &data);
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index bf2bdb957d..2f61de0824 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsonobject.h>
#include <qjsonvalue.h>
@@ -45,6 +9,8 @@
#include <qdebug.h>
#include <qvariant.h>
#include <qcbormap.h>
+#include <qmap.h>
+#include <qhash.h>
#include <private/qcborvalue_p.h>
#include "qjsonwriter_p.h"
@@ -59,11 +25,16 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonObject class encapsulates a JSON object.
+ \compares equality
+ \compareswith equality QJsonValue QJsonValueConstRef
+ \endcompareswith
+
A JSON object is a list of key value pairs, where the keys are unique strings
and the values are represented by a QJsonValue.
@@ -76,7 +47,7 @@ QT_BEGIN_NAMESPACE
You can convert the object to and from text based JSON through QJsonDocument.
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -106,7 +77,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QJsonObject::size_type
- Typedef for int. Provided for STL compatibility.
+ Typedef for qsizetype. Provided for STL compatibility.
*/
@@ -118,7 +89,7 @@ QT_BEGIN_NAMESPACE
QJsonObject::QJsonObject() = default;
/*!
- \fn QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
+ \fn QJsonObject::QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args)
\since 5.4
Constructs a QJsonObject instance initialized from \a args initialization list.
For example:
@@ -137,24 +108,6 @@ QJsonObject::QJsonObject() = default;
QJsonObject::QJsonObject(QCborContainerPrivate *object)
: o(object)
{
- Q_ASSERT(o);
-}
-
-/*!
- This method replaces part of the QJsonObject(std::initializer_list<QPair<QString, QJsonValue>> args) body.
- The constructor needs to be inline, but we do not want to leak implementation details
- of this class.
- \note this method is called for an uninitialized object
- \internal
- */
-
-void QJsonObject::initialize()
-{
- // Because we're being called with uninitialized state, we can't do:
- // o = nullptr;
- // QExplicitlyDataSharedPointer::operator= will read the current value
- void *ptr = &o;
- memset(ptr, 0, sizeof(o));
}
/*!
@@ -162,7 +115,7 @@ void QJsonObject::initialize()
*/
QJsonObject::~QJsonObject() = default;
-QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
+QJsonObject::QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args)
{
for (const auto &arg : args)
insert(arg.first, arg.second);
@@ -174,11 +127,13 @@ QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args
Since QJsonObject is implicitly shared, the copy is shallow
as long as the object does not get modified.
*/
-QJsonObject::QJsonObject(const QJsonObject &other)
-{
- o = other.o;
-}
+QJsonObject::QJsonObject(const QJsonObject &other) noexcept = default;
+
+/*!
+ \since 5.10
+ Move-constructs a QJsonObject from \a other.
+*/
QJsonObject::QJsonObject(QJsonObject &&other) noexcept
: o(other.o)
{
@@ -188,18 +143,8 @@ QJsonObject::QJsonObject(QJsonObject &&other) noexcept
/*!
Assigns \a other to this object.
*/
-QJsonObject &QJsonObject::operator =(const QJsonObject &other)
-{
- o = other.o;
- return *this;
-}
+QJsonObject &QJsonObject::operator =(const QJsonObject &other) noexcept = default;
-/*!
- \fn QJsonObject::QJsonObject(QJsonObject &&other)
- \since 5.10
-
- Move-constructs a QJsonObject from \a other.
-*/
/*!
\fn QJsonObject &QJsonObject::operator =(QJsonObject &&other)
@@ -215,18 +160,21 @@ QJsonObject &QJsonObject::operator =(const QJsonObject &other)
Swaps the object \a other with this. This operation is very fast and never fails.
*/
-
+#ifndef QT_NO_VARIANT
/*!
Converts the variant map \a map to a QJsonObject.
The keys in \a map will be used as the keys in the JSON object,
and the QVariant values will be converted to JSON values.
+ \note Conversion from \l QVariant is not completely lossless. Please see
+ the documentation in QJsonValue::fromVariant() for more information.
+
\sa fromVariantHash(), toVariantMap(), QJsonValue::fromVariant()
*/
QJsonObject QJsonObject::fromVariantMap(const QVariantMap &map)
{
- return QCborMap::fromVariantMap(map).toJsonObject();
+ return QJsonPrivate::Variant::toJsonObject(map);
}
/*!
@@ -248,6 +196,9 @@ QVariantMap QJsonObject::toVariantMap() const
The keys in \a hash will be used as the keys in the JSON object,
and the QVariant values will be converted to JSON values.
+ \note Conversion from \l QVariant is not completely lossless. Please see
+ the documentation in QJsonValue::fromVariant() for more information.
+
\sa fromVariantMap(), toVariantHash(), QJsonValue::fromVariant()
*/
QJsonObject QJsonObject::fromVariantHash(const QVariantHash &hash)
@@ -272,18 +223,19 @@ QVariantHash QJsonObject::toVariantHash() const
{
return QCborMap::fromJsonObject(*this).toVariantHash();
}
+#endif // !QT_NO_VARIANT
/*!
Returns a list of all keys in this object.
- The list is sorted lexographically.
+ The list is sorted alphabetically.
*/
QStringList QJsonObject::keys() const
{
QStringList keys;
if (o) {
- keys.reserve(o->elements.length() / 2);
- for (int i = 0, end = o->elements.length(); i < end; i += 2)
+ keys.reserve(o->elements.size() / 2);
+ for (qsizetype i = 0, end = o->elements.size(); i < end; i += 2)
keys.append(o->stringAt(i));
}
return keys;
@@ -292,9 +244,9 @@ QStringList QJsonObject::keys() const
/*!
Returns the number of (key, value) pairs stored in the object.
*/
-int QJsonObject::size() const
+qsizetype QJsonObject::size() const
{
- return o ? o->elements.length() / 2 : 0;
+ return o ? o->elements.size() / 2 : 0;
}
/*!
@@ -308,8 +260,8 @@ bool QJsonObject::isEmpty() const
}
template<typename String>
-static int indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
- String key, bool *keyExists)
+static qsizetype indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
+ String key, bool *keyExists)
{
const auto begin = QJsonPrivate::ConstKeyIterator(o->elements.constBegin());
const auto end = QJsonPrivate::ConstKeyIterator(o->elements.constEnd());
@@ -317,14 +269,13 @@ static int indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
const auto it = std::lower_bound(
begin, end, key,
[&](const QJsonPrivate::ConstKeyIterator::value_type &e, const String &key) {
- return o->stringCompareElement(e.key(), key) < 0;
+ return o->stringCompareElement(e.key(), key, QtCbor::Comparison::ForOrdering) < 0;
});
*keyExists = (it != end) && o->stringEqualsElement((*it).key(), key);
- return (it - begin) * 2;
+ return it.it - begin.it;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -336,7 +287,6 @@ QJsonValue QJsonObject::value(const QString &key) const
{
return value(QStringView(key));
}
-#endif
/*!
\overload
@@ -351,7 +301,7 @@ QJsonValue QJsonObject::value(QStringView key) const
\overload
\since 5.7
*/
-QJsonValue QJsonObject::value(QLatin1String key) const
+QJsonValue QJsonObject::value(QLatin1StringView key) const
{
return valueImpl(key);
}
@@ -366,13 +316,12 @@ QJsonValue QJsonObject::valueImpl(T key) const
return QJsonValue(QJsonValue::Undefined);
bool keyExists;
- int i = indexOf(o, key, &keyExists);
+ auto i = indexOf(o, key, &keyExists);
if (!keyExists)
return QJsonValue(QJsonValue::Undefined);
return QJsonPrivate::Value::fromTrustedCbor(o->valueAt(i + 1));
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -386,7 +335,6 @@ QJsonValue QJsonObject::operator [](const QString &key) const
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\fn QJsonValue QJsonObject::operator [](QStringView key) const
@@ -396,13 +344,12 @@ QJsonValue QJsonObject::operator [](const QString &key) const
*/
/*!
- \fn QJsonValue QJsonObject::operator [](QLatin1String key) const
+ \fn QJsonValue QJsonObject::operator [](QLatin1StringView key) const
\overload
\since 5.7
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a reference to the value for \a key. If there is no value with key
\a key in the object, one is created with a QJsonValue::Null value and then
@@ -420,7 +367,6 @@ QJsonValueRef QJsonObject::operator [](const QString &key)
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\overload
@@ -435,7 +381,7 @@ QJsonValueRef QJsonObject::operator [](QStringView key)
\overload
\since 5.7
*/
-QJsonValueRef QJsonObject::operator [](QLatin1String key)
+QJsonValueRef QJsonObject::operator [](QLatin1StringView key)
{
return atImpl(key);
}
@@ -450,9 +396,9 @@ QJsonValueRef QJsonObject::atImpl(T key)
o = new QCborContainerPrivate;
bool keyExists = false;
- int index = indexOf(o, key, &keyExists);
+ auto index = indexOf(o, key, &keyExists);
if (!keyExists) {
- detach2(o->elements.length() / 2 + 1);
+ detach(o->elements.size() / 2 + 1);
o->insertAt(index, key);
o->insertAt(index + 1, QCborValue::fromJsonValue(QJsonValue()));
}
@@ -460,7 +406,6 @@ QJsonValueRef QJsonObject::atImpl(T key)
return QJsonValueRef(this, index / 2);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Inserts a new item with the key \a key and a value of \a value.
@@ -478,7 +423,6 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &
{
return insert(QStringView(key), value);
}
-#endif
/*!
\overload
@@ -493,7 +437,7 @@ QJsonObject::iterator QJsonObject::insert(QStringView key, const QJsonValue &val
\overload
\since 5.14
*/
-QJsonObject::iterator QJsonObject::insert(QLatin1String key, const QJsonValue &value)
+QJsonObject::iterator QJsonObject::insert(QLatin1StringView key, const QJsonValue &value)
{
return insertImpl(key, value);
}
@@ -509,7 +453,7 @@ QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
return end();
}
bool keyExists = false;
- int pos = o ? indexOf(o, key, &keyExists) : 0;
+ auto pos = o ? indexOf(o, key, &keyExists) : 0;
return insertAt(pos, key, value, keyExists);
}
@@ -517,10 +461,10 @@ QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
\internal
*/
template <typename T>
-QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &value, bool keyExists)
+QJsonObject::iterator QJsonObject::insertAt(qsizetype pos, T key, const QJsonValue &value, bool keyExists)
{
if (o)
- detach2(o->elements.length() / 2 + (keyExists ? 0 : 1));
+ detach(o->elements.size() / 2 + (keyExists ? 0 : 1));
else
o = new QCborContainerPrivate;
@@ -533,7 +477,6 @@ QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &va
return {this, pos / 2};
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Removes \a key from the object.
@@ -543,7 +486,6 @@ void QJsonObject::remove(const QString &key)
{
remove(QStringView(key));
}
-#endif
/*!
\overload
@@ -558,7 +500,7 @@ void QJsonObject::remove(QStringView key)
\overload
\since 5.14
*/
-void QJsonObject::remove(QLatin1String key)
+void QJsonObject::remove(QLatin1StringView key)
{
removeImpl(key);
}
@@ -573,14 +515,13 @@ void QJsonObject::removeImpl(T key)
return;
bool keyExists;
- int index = indexOf(o, key, &keyExists);
+ auto index = indexOf(o, key, &keyExists);
if (!keyExists)
return;
- removeAt(index / 2);
+ removeAt(index);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Removes \a key from the object.
@@ -594,7 +535,6 @@ QJsonValue QJsonObject::take(const QString &key)
{
return take(QStringView(key));
}
-#endif
/*!
\overload
@@ -609,7 +549,7 @@ QJsonValue QJsonObject::take(QStringView key)
\overload
\since 5.14
*/
-QJsonValue QJsonObject::take(QLatin1String key)
+QJsonValue QJsonObject::take(QLatin1StringView key)
{
return takeImpl(key);
}
@@ -624,16 +564,16 @@ QJsonValue QJsonObject::takeImpl(T key)
return QJsonValue(QJsonValue::Undefined);
bool keyExists;
- int index = indexOf(o, key, &keyExists);
+ auto index = indexOf(o, key, &keyExists);
if (!keyExists)
return QJsonValue(QJsonValue::Undefined);
+ detach();
const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(o->extractAt(index + 1));
- removeAt(index / 2);
+ removeAt(index);
return v;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns \c true if the object contains key \a key.
@@ -643,7 +583,6 @@ bool QJsonObject::contains(const QString &key) const
{
return contains(QStringView(key));
}
-#endif
/*!
\overload
@@ -658,7 +597,7 @@ bool QJsonObject::contains(QStringView key) const
\overload
\since 5.7
*/
-bool QJsonObject::contains(QLatin1String key) const
+bool QJsonObject::contains(QLatin1StringView key) const
{
return containsImpl(key);
}
@@ -678,22 +617,24 @@ bool QJsonObject::containsImpl(T key) const
}
/*!
- Returns \c true if \a other is equal to this object.
- */
-bool QJsonObject::operator==(const QJsonObject &other) const
+ \fn bool QJsonObject::operator==(const QJsonObject &lhs, const QJsonObject &rhs)
+
+ Returns \c true if \a lhs object is equal to \a rhs, \c false otherwise.
+*/
+bool comparesEqual(const QJsonObject &lhs, const QJsonObject &rhs) noexcept
{
- if (o == other.o)
+ if (lhs.o == rhs.o)
return true;
- if (!o)
- return !other.o->elements.length();
- if (!other.o)
- return !o->elements.length();
- if (o->elements.length() != other.o->elements.length())
+ if (!lhs.o)
+ return !rhs.o->elements.size();
+ if (!rhs.o)
+ return !lhs.o->elements.size();
+ if (lhs.o->elements.size() != rhs.o->elements.size())
return false;
- for (int i = 0, end = o->elements.length(); i < end; ++i) {
- if (o->valueAt(i) != other.o->valueAt(i))
+ for (qsizetype i = 0, end = lhs.o->elements.size(); i < end; ++i) {
+ if (lhs.o->valueAt(i) != rhs.o->valueAt(i))
return false;
}
@@ -701,12 +642,10 @@ bool QJsonObject::operator==(const QJsonObject &other) const
}
/*!
- Returns \c true if \a other is not equal to this object.
- */
-bool QJsonObject::operator!=(const QJsonObject &other) const
-{
- return !(*this == other);
-}
+ \fn bool QJsonObject::operator!=(const QJsonObject &lhs, const QJsonObject &rhs)
+
+ Returns \c true if \a lhs object is not equal to \a rhs, \c false otherwise.
+*/
/*!
Removes the (key, value) pair pointed to by the iterator \a it
@@ -717,18 +656,14 @@ bool QJsonObject::operator!=(const QJsonObject &other) const
*/
QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it)
{
- if (it.o != this || it.i < 0 || it.i >= o->elements.length())
- return {this, o->elements.length()};
-
- int index = it.i;
-
- removeAt(index);
+ removeAt(it.item.index * 2);
- // iterator hasn't changed
- return it;
+ // index hasn't changed; the container pointer shouldn't have changed
+ // because we shouldn't have detached (detaching happens on obtaining a
+ // non-const iterator). But just in case we did, reload the pointer.
+ return { this, qsizetype(it.item.index) };
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns an iterator pointing to the item with key \a key in the
map.
@@ -740,7 +675,6 @@ QJsonObject::iterator QJsonObject::find(const QString &key)
{
return find(QStringView(key));
}
-#endif
/*!
\overload
@@ -755,7 +689,7 @@ QJsonObject::iterator QJsonObject::find(QStringView key)
\overload
\since 5.7
*/
-QJsonObject::iterator QJsonObject::find(QLatin1String key)
+QJsonObject::iterator QJsonObject::find(QLatin1StringView key)
{
return findImpl(key);
}
@@ -767,19 +701,17 @@ template <typename T>
QJsonObject::iterator QJsonObject::findImpl(T key)
{
bool keyExists = false;
- int index = o ? indexOf(o, key, &keyExists) : 0;
+ auto index = o ? indexOf(o, key, &keyExists) : 0;
if (!keyExists)
return end();
- detach2();
+ detach();
return {this, index / 2};
}
-#if QT_STRINGVIEW_LEVEL < 2
/*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const
\overload
*/
-#endif
/*! \fn QJsonObject::const_iterator QJsonObject::find(QStringView key) const
@@ -787,13 +719,12 @@ QJsonObject::iterator QJsonObject::findImpl(T key)
\since 5.14
*/
-/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const
+/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1StringView key) const
\overload
\since 5.7
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a const iterator pointing to the item with key \a key in the
map.
@@ -805,7 +736,6 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
{
return constFind(QStringView(key));
}
-#endif
/*!
\overload
@@ -820,7 +750,7 @@ QJsonObject::const_iterator QJsonObject::constFind(QStringView key) const
\overload
\since 5.7
*/
-QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const
+QJsonObject::const_iterator QJsonObject::constFind(QLatin1StringView key) const
{
return constFindImpl(key);
}
@@ -832,20 +762,20 @@ template <typename T>
QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
{
bool keyExists = false;
- int index = o ? indexOf(o, key, &keyExists) : 0;
+ auto index = o ? indexOf(o, key, &keyExists) : 0;
if (!keyExists)
return end();
return {this, index / 2};
}
-/*! \fn int QJsonObject::count() const
+/*! \fn qsizetype QJsonObject::count() const
\overload
Same as size().
*/
-/*! \fn int QJsonObject::length() const
+/*! \fn qsizetype QJsonObject::length() const
\overload
@@ -910,6 +840,10 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject.
+ \compares strong
+ \compareswith strong QJsonObject::const_iterator
+ \endcompareswith
+
QJsonObject::iterator allows you to iterate over a QJsonObject
and to modify the value (but not the key) stored under
a particular key. If you want to iterate over a const QJsonObject, you
@@ -926,7 +860,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
Multiple iterators can be used on the same object. Existing iterators will however
become dangling once the object gets modified.
- \sa QJsonObject::const_iterator, {JSON Support in Qt}, {JSON Save Game Example}
+ \sa QJsonObject::const_iterator, {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*! \typedef QJsonObject::iterator::difference_type
@@ -969,7 +903,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa QJsonObject::begin(), QJsonObject::end()
*/
-/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, int index)
+/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, qsizetype index)
\internal
*/
@@ -1015,12 +949,17 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa key()
*/
-/*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const
+/*! \fn QJsonValueRef *QJsonObject::iterator::operator->()
Returns a pointer to a modifiable reference to the current item.
*/
-/*! \fn const QJsonValueRef QJsonObject::iterator::operator[](int j)
+/*! \fn const QJsonValueConstRef *QJsonObject::iterator::operator->() const
+
+ Returns a pointer to a constant reference to the current item.
+*/
+
+/*! \fn const QJsonValueRef QJsonObject::iterator::operator[](qsizetype j) const
Returns a modifiable reference to the item at offset \a j from the
item pointed to by this iterator (the item at position \c{*this + j}).
@@ -1038,60 +977,60 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
*/
/*!
- \fn bool QJsonObject::iterator::operator==(const iterator &other) const
- \fn bool QJsonObject::iterator::operator==(const const_iterator &other) const
+ \fn bool QJsonObject::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator==(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QJsonObject::iterator::operator!=(const iterator &other) const
- \fn bool QJsonObject::iterator::operator!=(const const_iterator &other) const
+ \fn bool QJsonObject::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator!=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonObject::iterator::operator<(const iterator& other) const
- \fn bool QJsonObject::iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator<(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator<(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::iterator::operator<=(const iterator& other) const
- \fn bool QJsonObject::iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator<=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator<=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::iterator::operator>(const iterator& other) const
- \fn bool QJsonObject::iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator>(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator>(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::iterator::operator>=(const iterator& other) const
- \fn bool QJsonObject::iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator>=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator>=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the
next item in the object and returns an iterator to the new current
item.
@@ -1104,14 +1043,14 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the
next item in the object and returns an iterator to the previously
current item.
*/
/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item
+ The prefix \c{--} operator, \c{--i}, makes the preceding item
current and returns an iterator pointing to the new current item.
Calling this function on QJsonObject::begin() leads to undefined
@@ -1124,12 +1063,12 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix -- operator, \c{i--}, makes the preceding item
+ The postfix \c{--} operator, \c{i--}, makes the preceding item
current and returns an iterator pointing to the previously
current item.
*/
-/*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(int j) const
+/*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -1138,7 +1077,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
*/
-/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(int j) const
+/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -1146,7 +1085,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+()
*/
-/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(int j)
+/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -1154,7 +1093,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(int j)
+/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -1162,7 +1101,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+=(), operator-()
*/
-/*! \fn int QJsonObject::iterator::operator-(iterator other) const
+/*! \fn qsizetype QJsonObject::iterator::operator-(iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
@@ -1175,6 +1114,10 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\since 5.0
\brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject.
+ \compares strong
+ \compareswith strong QJsonObject::iterator
+ \endcompareswith
+
QJsonObject::const_iterator allows you to iterate over a QJsonObject.
If you want to modify the QJsonObject as you iterate
over it, you must use QJsonObject::iterator instead. It is generally
@@ -1191,7 +1134,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
Multiple iterators can be used on the same object. Existing iterators
will however become dangling if the object gets modified.
- \sa QJsonObject::iterator, {JSON Support in Qt}, {JSON Save Game Example}
+ \sa QJsonObject::iterator, {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*! \typedef QJsonObject::const_iterator::difference_type
@@ -1234,7 +1177,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa QJsonObject::constBegin(), QJsonObject::constEnd()
*/
-/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, int index)
+/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, qsizetype index)
\internal
*/
@@ -1250,14 +1193,14 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa value()
*/
-/*! \fn QJsonValue QJsonObject::const_iterator::value() const
+/*! \fn QJsonValueConstRef QJsonObject::const_iterator::value() const
Returns the current item's value.
\sa key(), operator*()
*/
-/*! \fn QJsonValue QJsonObject::const_iterator::operator*() const
+/*! \fn const QJsonValueConstRef QJsonObject::const_iterator::operator*() const
Returns the current item's value.
@@ -1266,12 +1209,12 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa key()
*/
-/*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const
+/*! \fn const QJsonValueConstRef *QJsonObject::const_iterator::operator->() const
Returns a pointer to the current item.
*/
-/*! \fn const QJsonValue QJsonObject::const_iterator::operator[](int j)
+/*! \fn const QJsonValueConstRef QJsonObject::const_iterator::operator[](qsizetype j) const
Returns the item at offset \a j from the item pointed to by this iterator (the item at
position \c{*this + j}).
@@ -1283,55 +1226,53 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
*/
-/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const
- \fn bool QJsonObject::const_iterator::operator==(const iterator &other) const
+/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
-/*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &other) const
- \fn bool QJsonObject::const_iterator::operator!=(const iterator &other) const
+/*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonObject::const_iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator<(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::const_iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator<=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::const_iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator>(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::const_iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator>=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the
next item in the object and returns an iterator to the new current
item.
@@ -1344,14 +1285,14 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the
next item in the object and returns an iterator to the previously
current item.
*/
/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item
+ The prefix \c{--} operator, \c{--i}, makes the preceding item
current and returns an iterator pointing to the new current item.
Calling this function on QJsonObject::begin() leads to undefined
@@ -1364,12 +1305,12 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix -- operator, \c{i--}, makes the preceding item
+ The postfix \c{--} operator, \c{i--}, makes the preceding item
current and returns an iterator pointing to the previously
current item.
*/
-/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(int j) const
+/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -1379,7 +1320,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator-()
*/
-/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(int j) const
+/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -1389,7 +1330,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+()
*/
-/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(int j)
+/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -1399,7 +1340,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(int j)
+/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -1409,7 +1350,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+=(), operator-()
*/
-/*! \fn int QJsonObject::const_iterator::operator-(const_iterator other) const
+/*! \fn qsizetype QJsonObject::const_iterator::operator-(const_iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
@@ -1419,48 +1360,30 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
/*!
\internal
*/
-void QJsonObject::detach(uint reserve)
-{
- Q_UNUSED(reserve)
- Q_ASSERT(!reserve);
- detach2(reserve);
-}
-
-bool QJsonObject::detach2(uint reserve)
+bool QJsonObject::detach(qsizetype reserve)
{
if (!o)
return true;
- o = QCborContainerPrivate::detach(o.data(), reserve ? reserve * 2 : o->elements.length());
+ o = QCborContainerPrivate::detach(o.data(), reserve ? reserve * 2 : o->elements.size());
return o;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
/*!
\internal
*/
-void QJsonObject::compact()
-{
- if (!o)
- return;
-
- detach2();
- o->compact(o->elements.length());
-}
-
-/*!
- \internal
- */
-QString QJsonObject::keyAt(int i) const
+QString QJsonObject::keyAt(qsizetype i) const
{
- Q_ASSERT(o && i >= 0 && i * 2 < o->elements.length());
+ Q_ASSERT(o && i >= 0 && i * 2 < o->elements.size());
return o->stringAt(i * 2);
}
/*!
\internal
*/
-QJsonValue QJsonObject::valueAt(int i) const
+QJsonValue QJsonObject::valueAt(qsizetype i) const
{
- if (!o || i < 0 || 2 * i + 1 >= o->elements.length())
+ if (!o || i < 0 || 2 * i + 1 >= o->elements.size())
return QJsonValue(QJsonValue::Undefined);
return QJsonPrivate::Value::fromTrustedCbor(o->valueAt(2 * i + 1));
}
@@ -1468,10 +1391,10 @@ QJsonValue QJsonObject::valueAt(int i) const
/*!
\internal
*/
-void QJsonObject::setValueAt(int i, const QJsonValue &val)
+void QJsonObject::setValueAt(qsizetype i, const QJsonValue &val)
{
- Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.length());
- detach2();
+ Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.size());
+ detach();
if (val.isUndefined()) {
o->removeAt(2 * i + 1);
o->removeAt(2 * i);
@@ -1479,15 +1402,16 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
o->replaceAt(2 * i + 1, QCborValue::fromJsonValue(val));
}
}
+#endif // Qt 7
/*!
\internal
*/
-void QJsonObject::removeAt(int index)
+void QJsonObject::removeAt(qsizetype index)
{
- detach2();
- o->removeAt(2 * index + 1);
- o->removeAt(2 * index);
+ detach();
+ o->removeAt(index + 1);
+ o->removeAt(index);
}
size_t qHash(const QJsonObject &object, size_t seed)
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index 4002a8bc24..4cdbf4511d 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONOBJECT_H
#define QJSONOBJECT_H
@@ -49,10 +13,6 @@
QT_BEGIN_NAMESPACE
class QDebug;
-template <class Key, class T> class QMap;
-typedef QMap<QString, QVariant> QVariantMap;
-template <class Key, class T> class QHash;
-typedef QHash<QString, QVariant> QVariantHash;
class QCborContainerPrivate;
@@ -61,12 +21,12 @@ class Q_CORE_EXPORT QJsonObject
public:
QJsonObject();
- QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args);
+ QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args);
~QJsonObject();
- QJsonObject(const QJsonObject &other);
- QJsonObject &operator =(const QJsonObject &other);
+ QJsonObject(const QJsonObject &other) noexcept;
+ QJsonObject &operator =(const QJsonObject &other) noexcept;
QJsonObject(QJsonObject &&other) noexcept;
@@ -78,7 +38,7 @@ public:
void swap(QJsonObject &other) noexcept
{
- qSwap(o, other.o);
+ o.swap(other.o);
}
static QJsonObject fromVariantMap(const QVariantMap &map);
@@ -87,156 +47,243 @@ public:
QVariantHash toVariantHash() const;
QStringList keys() const;
- int size() const;
- inline int count() const { return size(); }
- inline int length() const { return size(); }
+ qsizetype size() const;
+ inline qsizetype count() const { return size(); }
+ inline qsizetype length() const { return size(); }
bool isEmpty() const;
-#if QT_STRINGVIEW_LEVEL < 2
QJsonValue value(const QString &key) const;
QJsonValue operator[] (const QString &key) const;
QJsonValueRef operator[] (const QString &key);
-#endif
QJsonValue value(QStringView key) const;
- QJsonValue value(QLatin1String key) const;
+ QJsonValue value(QLatin1StringView key) const;
QJsonValue operator[] (QStringView key) const { return value(key); }
- QJsonValue operator[] (QLatin1String key) const { return value(key); }
+ QJsonValue operator[] (QLatin1StringView key) const { return value(key); }
QJsonValueRef operator[] (QStringView key);
- QJsonValueRef operator[] (QLatin1String key);
+ QJsonValueRef operator[] (QLatin1StringView key);
-#if QT_STRINGVIEW_LEVEL < 2
void remove(const QString &key);
QJsonValue take(const QString &key);
bool contains(const QString &key) const;
-#endif
void remove(QStringView key);
- void remove(QLatin1String key);
+ void remove(QLatin1StringView key);
QJsonValue take(QStringView key);
- QJsonValue take(QLatin1String key);
+ QJsonValue take(QLatin1StringView key);
bool contains(QStringView key) const;
- bool contains(QLatin1String key) const;
+ bool contains(QLatin1StringView key) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonObject &other) const;
bool operator!=(const QJsonObject &other) const;
-
+#endif
class const_iterator;
class iterator
{
friend class const_iterator;
friend class QJsonObject;
- QJsonObject *o;
- int i;
+ QJsonValueRef item;
public:
typedef std::random_access_iterator_tag iterator_category;
- typedef int difference_type;
+ typedef qsizetype difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
- typedef QJsonValuePtr pointer;
-
- Q_DECL_CONSTEXPR inline iterator() : o(nullptr), i(0) {}
- Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
-
- inline QString key() const { return o->keyAt(i); }
- inline QJsonValueRef value() const { return QJsonValueRef(o, i); }
- inline QJsonValueRef operator*() const { return QJsonValueRef(o, i); }
-#ifdef Q_QDOC
- inline QJsonValueRef* operator->() const;
-#else
- inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(o, i); }
+ typedef QJsonValueRef *pointer;
+
+ inline iterator() : item(static_cast<QJsonObject*>(nullptr), 0) { }
+ inline iterator(QJsonObject *obj, qsizetype index) : item(obj, index) { }
+
+ constexpr iterator(const iterator &other) = default;
+ iterator &operator=(const iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline QString key() const { return item.objectKey(); }
+ inline QJsonValueRef value() const { return item; }
+ inline QJsonValueRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+ inline QJsonValueRef *operator->() { return &item; }
+ inline QJsonValueRef operator[](qsizetype j) const { return *(*this + j); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const iterator &other) const { return !operator==(other); }
+ bool operator<(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const iterator& other) const { return !operator<=(other); }
+ bool operator>=(const iterator& other) const { return !operator<(other); }
#endif
- const QJsonValueRef operator[](int j) { return QJsonValueRef(o, i + j); }
-
- inline bool operator==(const iterator &other) const { return i == other.i; }
- inline bool operator!=(const iterator &other) const { return i != other.i; }
- bool operator<(const iterator& other) const { return i < other.i; }
- bool operator<=(const iterator& other) const { return i <= other.i; }
- bool operator>(const iterator& other) const { return i > other.i; }
- bool operator>=(const iterator& other) const { return i >= other.i; }
-
- inline iterator &operator++() { ++i; return *this; }
- inline iterator operator++(int) { iterator r = *this; ++i; return r; }
- inline iterator &operator--() { --i; return *this; }
- inline iterator operator--(int) { iterator r = *this; --i; return r; }
- inline iterator operator+(int j) const
- { iterator r = *this; r.i += j; return r; }
- inline iterator operator-(int j) const { return operator+(-j); }
- inline iterator &operator+=(int j) { i += j; return *this; }
- inline iterator &operator-=(int j) { i -= j; return *this; }
- int operator-(iterator j) const { return i - j.i; }
+ inline iterator &operator++() { ++item.index; return *this; }
+ inline iterator operator++(int) { iterator r = *this; ++item.index; return r; }
+ inline iterator &operator--() { --item.index; return *this; }
+ inline iterator operator--(int) { iterator r = *this; --item.index; return r; }
+ inline iterator operator+(qsizetype j) const { iterator r = *this; return r += j; }
+ inline iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ qsizetype operator-(iterator j) const { return item.index - j.item.index; }
public:
- inline bool operator==(const const_iterator &other) const { return i == other.i; }
- inline bool operator!=(const const_iterator &other) const { return i != other.i; }
- bool operator<(const const_iterator& other) const { return i < other.i; }
- bool operator<=(const const_iterator& other) const { return i <= other.i; }
- bool operator>(const const_iterator& other) const { return i > other.i; }
- bool operator>=(const const_iterator& other) const { return i >= other.i; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const const_iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const const_iterator &other) const { return !operator==(other); }
+ bool operator<(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const const_iterator& other) const { return operator<=(other); }
+ bool operator>=(const const_iterator& other) const { return operator<(other); }
+#endif
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+ static bool comparesEqual_helper(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator)
+
+ friend bool comparesEqual(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator, const_iterator)
};
friend class iterator;
class const_iterator
{
friend class iterator;
- const QJsonObject *o;
- int i;
+ QJsonValueConstRef item;
public:
typedef std::random_access_iterator_tag iterator_category;
- typedef int difference_type;
+ typedef qsizetype difference_type;
typedef QJsonValue value_type;
- typedef QJsonValue reference;
- typedef QJsonValuePtr pointer;
+ typedef const QJsonValueConstRef reference;
+ typedef const QJsonValueConstRef *pointer;
- Q_DECL_CONSTEXPR inline const_iterator() : o(nullptr), i(0) {}
- Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index)
- : o(obj), i(index) {}
+ inline const_iterator() : item(static_cast<QJsonObject*>(nullptr), 0) { }
+ inline const_iterator(const QJsonObject *obj, qsizetype index)
+ : item(const_cast<QJsonObject*>(obj), index) { }
inline const_iterator(const iterator &other)
- : o(other.o), i(other.i) {}
-
- inline QString key() const { return o->keyAt(i); }
- inline QJsonValue value() const { return o->valueAt(i); }
- inline QJsonValue operator*() const { return o->valueAt(i); }
-#ifdef Q_QDOC
- inline QJsonValue* operator->() const;
-#else
- inline QJsonValuePtr operator->() const { return QJsonValuePtr(o->valueAt(i)); }
+ : item(other.item) { }
+
+ constexpr const_iterator(const const_iterator &other) = default;
+ const_iterator &operator=(const const_iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline QString key() const { return item.objectKey(); }
+ inline QJsonValueConstRef value() const { return item; }
+ inline const QJsonValueConstRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+ inline QJsonValueConstRef operator[](qsizetype j) const { return *(*this + j); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const const_iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const const_iterator &other) const { return !operator==(other); }
+ bool operator<(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const const_iterator& other) const { return !operator<=(other); }
+ bool operator>=(const const_iterator& other) const { return !operator<(other); }
+#endif
+ inline const_iterator &operator++() { ++item.index; return *this; }
+ inline const_iterator operator++(int) { const_iterator r = *this; ++item.index; return r; }
+ inline const_iterator &operator--() { --item.index; return *this; }
+ inline const_iterator operator--(int) { const_iterator r = *this; --item.index; return r; }
+ inline const_iterator operator+(qsizetype j) const { const_iterator r = *this; return r += j; }
+ inline const_iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline const_iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline const_iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ qsizetype operator-(const_iterator j) const { return item.index - j.item.index; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const iterator &other) const { return !operator==(other); }
+ bool operator<(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const iterator& other) const { return !operator<=(other); }
+ bool operator>=(const iterator& other) const { return !operator<(other); }
#endif
- const QJsonValue operator[](int j) { return o->valueAt(i + j); }
-
- inline bool operator==(const const_iterator &other) const { return i == other.i; }
- inline bool operator!=(const const_iterator &other) const { return i != other.i; }
- bool operator<(const const_iterator& other) const { return i < other.i; }
- bool operator<=(const const_iterator& other) const { return i <= other.i; }
- bool operator>(const const_iterator& other) const { return i > other.i; }
- bool operator>=(const const_iterator& other) const { return i >= other.i; }
-
- inline const_iterator &operator++() { ++i; return *this; }
- inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; }
- inline const_iterator &operator--() { --i; return *this; }
- inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; }
- inline const_iterator operator+(int j) const
- { const_iterator r = *this; r.i += j; return r; }
- inline const_iterator operator-(int j) const { return operator+(-j); }
- inline const_iterator &operator+=(int j) { i += j; return *this; }
- inline const_iterator &operator-=(int j) { i -= j; return *this; }
- int operator-(const_iterator j) const { return i - j.i; }
-
- inline bool operator==(const iterator &other) const { return i == other.i; }
- inline bool operator!=(const iterator &other) const { return i != other.i; }
- bool operator<(const iterator& other) const { return i < other.i; }
- bool operator<=(const iterator& other) const { return i <= other.i; }
- bool operator>(const iterator& other) const { return i > other.i; }
- bool operator>=(const iterator& other) const { return i >= other.i; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(const_iterator)
};
friend class const_iterator;
// STL style
- inline iterator begin() { detach2(); return iterator(this, 0); }
+ inline iterator begin() { detach(); return iterator(this, 0); }
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator constBegin() const { return const_iterator(this, 0); }
- inline iterator end() { detach2(); return iterator(this, size()); }
+ inline iterator end() { detach(); return iterator(this, size()); }
inline const_iterator end() const { return const_iterator(this, size()); }
inline const_iterator constEnd() const { return const_iterator(this, size()); }
iterator erase(iterator it);
@@ -244,41 +291,52 @@ public:
// more Qt
typedef iterator Iterator;
typedef const_iterator ConstIterator;
-#if QT_STRINGVIEW_LEVEL < 2
iterator find(const QString &key);
const_iterator find(const QString &key) const { return constFind(key); }
const_iterator constFind(const QString &key) const;
iterator insert(const QString &key, const QJsonValue &value);
-#endif
iterator find(QStringView key);
- iterator find(QLatin1String key);
+ iterator find(QLatin1StringView key);
const_iterator find(QStringView key) const { return constFind(key); }
- const_iterator find(QLatin1String key) const { return constFind(key); }
+ const_iterator find(QLatin1StringView key) const { return constFind(key); }
const_iterator constFind(QStringView key) const;
- const_iterator constFind(QLatin1String key) const;
+ const_iterator constFind(QLatin1StringView key) const;
iterator insert(QStringView key, const QJsonValue &value);
- iterator insert(QLatin1String key, const QJsonValue &value);
+ iterator insert(QLatin1StringView key, const QJsonValue &value);
// STL compatibility
typedef QJsonValue mapped_type;
typedef QString key_type;
- typedef int size_type;
+ typedef qsizetype size_type;
inline bool empty() const { return isEmpty(); }
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonObject &lhs,
+ const QJsonObject &rhs) noexcept;
+ friend bool comparesEqual(const QJsonObject &lhs,
+ const QJsonValue &rhs) noexcept
+ {
+ return comparesEqual(lhs, rhs.toObject());
+ }
+ friend bool comparesEqual(const QJsonObject &lhs,
+ const QJsonValueConstRef &rhs) noexcept
+ {
+ return comparesEqual(lhs, rhs.toObject());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject, QJsonValue)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject, QJsonValueConstRef)
friend class QJsonValue;
friend class QJsonDocument;
+ friend class QJsonPrivate::Value;
+ friend class QJsonValueConstRef;
friend class QJsonValueRef;
friend class QCborMap;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
QJsonObject(QCborContainerPrivate *object);
- void initialize();
- // ### Qt 6: remove me and merge with detach2
- void detach(uint reserve = 0);
- bool detach2(uint reserve = 0);
- void compact();
+ bool detach(qsizetype reserve = 0);
template <typename T> QJsonValue valueImpl(T key) const;
template <typename T> QJsonValueRef atImpl(T key);
@@ -289,19 +347,25 @@ private:
template <typename T> const_iterator constFindImpl(T key) const;
template <typename T> iterator insertImpl(T key, const QJsonValue &value);
- QString keyAt(int i) const;
- QJsonValue valueAt(int i) const;
- void setValueAt(int i, const QJsonValue &val);
- void removeAt(int i);
- template <typename T> iterator insertAt(int i, T key, const QJsonValue &val, bool exists);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QString keyAt(qsizetype i) const;
+ QJsonValue valueAt(qsizetype i) const;
+ void setValueAt(qsizetype i, const QJsonValue &val);
+#endif
+ void removeAt(qsizetype i);
+ template <typename T> iterator insertAt(qsizetype i, T key, const QJsonValue &val, bool exists);
- // ### Qt 6: remove
- void *dead = nullptr;
QExplicitlySharedDataPointer<QCborContainerPrivate> o;
};
Q_DECLARE_SHARED(QJsonObject)
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+inline QJsonValueConstRef::QJsonValueConstRef(QJsonObject *o, qsizetype idx)
+ : d(o ? o->o.data() : nullptr), is_object(true), index(idx)
+{}
+#endif
+
Q_CORE_EXPORT size_t qHash(const QJsonObject &object, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index 116e7f6995..ba4887225d 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
@@ -47,23 +11,30 @@
#include "private/qstringconverter_p.h"
#include "private/qcborvalue_p.h"
#include "private/qnumeric_p.h"
+#include <private/qtools_p.h>
//#define PARSER_DEBUG
#ifdef PARSER_DEBUG
-static int indent = 0;
-#define BEGIN qDebug() << QByteArray(4*indent++, ' ').constData() << "pos=" << current
-#define END --indent
-#define DEBUG qDebug() << QByteArray(4*indent, ' ').constData()
+# error currently broken after `current` was moved to StashedContainer
+Q_CONSTINIT static int indent = 0;
+# define QT_PARSER_TRACING_BEGIN \
+ qDebug() << QByteArray(4 * indent++, ' ').constData() << "pos=" << current
+# define QT_PARSER_TRACING_END --indent
+# define QT_PARSER_TRACING_DEBUG qDebug() << QByteArray(4 * indent, ' ').constData()
#else
-#define BEGIN if (1) ; else qDebug()
-#define END do {} while (0)
-#define DEBUG if (1) ; else qDebug()
+# define QT_PARSER_TRACING_BEGIN QT_NO_QDEBUG_MACRO()
+# define QT_PARSER_TRACING_END \
+ do { \
+ } while (0)
+# define QT_PARSER_TRACING_DEBUG QT_NO_QDEBUG_MACRO()
#endif
static const int nestingLimit = 1024;
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
// error strings for the JSON parser
#define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred")
#define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object")
@@ -86,12 +57,13 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonParseError class is used to report errors during JSON parsing.
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -193,7 +165,7 @@ QString QJsonParseError::errorString() const
#ifndef QT_BOOTSTRAPPED
return QCoreApplication::translate("QJsonParseError", sz);
#else
- return QLatin1String(sz);
+ return QLatin1StringView(sz);
#endif
}
@@ -333,7 +305,7 @@ QCborValue Parser::parse(QJsonParseError *error)
QCborValue data;
- DEBUG << Qt::hex << (uint)token;
+ QT_PARSER_TRACING_DEBUG << Qt::hex << (uint)token;
if (token == BeginArray) {
container = new QCborContainerPrivate;
if (!parseArray())
@@ -357,7 +329,7 @@ QCborValue Parser::parse(QJsonParseError *error)
goto error;
}
- END;
+ QT_PARSER_TRACING_END;
{
if (error) {
error->offset = 0;
@@ -379,12 +351,42 @@ error:
return QCborValue();
}
+// We need to retain the _last_ value for any duplicate keys and we need to deref containers.
+// Therefore the manual implementation of std::unique().
+template<typename Iterator, typename Compare, typename Assign>
+static Iterator customAssigningUniqueLast(Iterator first, Iterator last,
+ Compare compare, Assign assign)
+{
+ first = std::adjacent_find(first, last, compare);
+ if (first == last)
+ return last;
+
+ // After adjacent_find, we know that *first and *(first+1) compare equal,
+ // and that first+1 != last.
+ Iterator result = first++;
+ Q_ASSERT(compare(*result, *first));
+ assign(*result, *first);
+ Q_ASSERT(first != last);
+
+ while (++first != last) {
+ if (!compare(*result, *first))
+ ++result;
+ // Due to adjacent_find above, we know that we've at least eliminated one element.
+ // Therefore we have to move each further element across the gap.
+ Q_ASSERT(result != first);
+
+ // We have to overwrite each element we want to eliminate, to deref() the container.
+ // Therefore we don't try to optimize the number of assignments here.
+ assign(*result, *first);
+ }
+
+ return ++result;
+}
static void sortContainer(QCborContainerPrivate *container)
{
using Forward = QJsonPrivate::KeyIterator;
- using Reverse = std::reverse_iterator<Forward>;
using Value = Forward::value_type;
auto compare = [container](const Value &a, const Value &b)
@@ -403,52 +405,47 @@ static void sortContainer(QCborContainerPrivate *container)
if (!bData)
return 1;
- // If StringIsAscii is set, we can use either the UTF-8 or the latin1 comparison
- // for the string as ASCII is a subset of both. If nothing is set, that means UTF-8.
-
- // We are currently missing an efficient comparison between UTF-8 and UTF-16 strings.
- // Therefore, we need to convert the UTF-8 string if we encounter such a case.
-
- if (aKey.flags & QtCbor::Element::StringIsAscii) {
- if (bKey.flags & QtCbor::Element::StringIsAscii)
- return QtPrivate::compareStrings(aData->asLatin1(), bData->asLatin1());
- if (bKey.flags & QtCbor::Element::StringIsUtf16)
- return QtPrivate::compareStrings(aData->asLatin1(), bData->asStringView());
-
- return QCborContainerPrivate::compareUtf8(aData, bData->asLatin1());
- }
+ // US-ASCII (StringIsAscii flag) is just a special case of UTF-8
+ // string, so we can safely ignore the flag.
if (aKey.flags & QtCbor::Element::StringIsUtf16) {
- if (bKey.flags & QtCbor::Element::StringIsAscii)
- return QtPrivate::compareStrings(aData->asStringView(), bData->asLatin1());
if (bKey.flags & QtCbor::Element::StringIsUtf16)
return QtPrivate::compareStrings(aData->asStringView(), bData->asStringView());
- // Nasty case. a is UTF-16 and b is UTF-8
- return QtPrivate::compareStrings(aData->asStringView(), bData->toUtf8String());
+ return -QCborContainerPrivate::compareUtf8(bData, aData->asStringView());
+ } else {
+ if (bKey.flags & QtCbor::Element::StringIsUtf16)
+ return QCborContainerPrivate::compareUtf8(aData, bData->asStringView());
+
+ return QtPrivate::compareStrings(aData->asUtf8StringView(), bData->asUtf8StringView());
}
+ };
- if (bKey.flags & QtCbor::Element::StringIsAscii)
- return QCborContainerPrivate::compareUtf8(aData, bData->asLatin1());
+ // The elements' containers are owned by the outer container, not by the elements themselves.
+ auto move = [](Forward::reference target, Forward::reference source)
+ {
+ QtCbor::Element &targetValue = target.value();
+
+ // If the target has a container, deref it before overwriting, so that we don't leak.
+ if (targetValue.flags & QtCbor::Element::IsContainer)
+ targetValue.container->deref();
- // Nasty case. a is UTF-8 and b is UTF-16
- if (bKey.flags & QtCbor::Element::StringIsUtf16)
- return QtPrivate::compareStrings(aData->toUtf8String(), bData->asStringView());
+ // Do not move, so that we can clear the value afterwards.
+ target = source;
- return QCborContainerPrivate::compareUtf8(aData, bData->asLatin1());
+ // Clear the source value, so that we don't store the same container twice.
+ source.value() = QtCbor::Element();
};
- std::sort(Forward(container->elements.begin()), Forward(container->elements.end()),
- [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; });
+ std::stable_sort(
+ Forward(container->elements.begin()), Forward(container->elements.end()),
+ [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; });
- // We need to retain the _last_ value for any duplicate keys. Therefore the reverse dance here.
- auto it = std::unique(Reverse(container->elements.end()), Reverse(container->elements.begin()),
- [&compare](const Value &a, const Value &b) {
- return compare(a, b) == 0;
- }).base().elementsIterator();
+ Forward result = customAssigningUniqueLast(
+ Forward(container->elements.begin()), Forward(container->elements.end()),
+ [&compare](const Value &a, const Value &b) { return compare(a, b) == 0; }, move);
- // The erase from beginning is expensive but hopefully rare.
- container->elements.erase(container->elements.begin(), it);
+ container->elements.erase(result.elementsIterator(), container->elements.end());
}
@@ -464,7 +461,7 @@ bool Parser::parseObject()
return false;
}
- BEGIN << "parseObject" << json;
+ QT_PARSER_TRACING_BEGIN << "parseObject" << json;
char token = nextToken();
while (token == Quote) {
@@ -482,13 +479,13 @@ bool Parser::parseObject()
}
}
- DEBUG << "end token=" << token;
+ QT_PARSER_TRACING_DEBUG << "end token=" << token;
if (token != EndObject) {
lastError = QJsonParseError::UnterminatedObject;
return false;
}
- END;
+ QT_PARSER_TRACING_END;
--nestingLevel;
@@ -502,7 +499,7 @@ bool Parser::parseObject()
*/
bool Parser::parseMember()
{
- BEGIN << "parseMember";
+ QT_PARSER_TRACING_BEGIN << "parseMember";
if (!parseString())
return false;
@@ -518,7 +515,7 @@ bool Parser::parseMember()
if (!parseValue())
return false;
- END;
+ QT_PARSER_TRACING_END;
return true;
}
@@ -527,7 +524,7 @@ bool Parser::parseMember()
*/
bool Parser::parseArray()
{
- BEGIN << "parseArray";
+ QT_PARSER_TRACING_BEGIN << "parseArray";
if (++nestingLevel > nestingLimit) {
lastError = QJsonParseError::DeepNesting;
@@ -563,8 +560,8 @@ bool Parser::parseArray()
}
}
- DEBUG << "size =" << (container ? container->elements.length() : 0);
- END;
+ QT_PARSER_TRACING_DEBUG << "size =" << (container ? container->elements.size() : 0);
+ QT_PARSER_TRACING_END;
--nestingLevel;
@@ -578,7 +575,7 @@ value = false / null / true / object / array / number / string
bool Parser::parseValue()
{
- BEGIN << "parse Value" << json;
+ QT_PARSER_TRACING_BEGIN << "parse Value" << json;
switch (*json++) {
case 'n':
@@ -590,8 +587,8 @@ bool Parser::parseValue()
*json++ == 'l' &&
*json++ == 'l') {
container->append(QCborValue(QCborValue::Null));
- DEBUG << "value: null";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: null";
+ QT_PARSER_TRACING_END;
return true;
}
lastError = QJsonParseError::IllegalValue;
@@ -605,8 +602,8 @@ bool Parser::parseValue()
*json++ == 'u' &&
*json++ == 'e') {
container->append(QCborValue(true));
- DEBUG << "value: true";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: true";
+ QT_PARSER_TRACING_END;
return true;
}
lastError = QJsonParseError::IllegalValue;
@@ -621,8 +618,8 @@ bool Parser::parseValue()
*json++ == 's' &&
*json++ == 'e') {
container->append(QCborValue(false));
- DEBUG << "value: false";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: false";
+ QT_PARSER_TRACING_END;
return true;
}
lastError = QJsonParseError::IllegalValue;
@@ -630,24 +627,24 @@ bool Parser::parseValue()
case Quote: {
if (!parseString())
return false;
- DEBUG << "value: string";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: string";
+ QT_PARSER_TRACING_END;
return true;
}
case BeginArray: {
StashedContainer stashedContainer(&container, QCborValue::Array);
if (!parseArray())
return false;
- DEBUG << "value: array";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: array";
+ QT_PARSER_TRACING_END;
return true;
}
case BeginObject: {
StashedContainer stashedContainer(&container, QCborValue::Map);
if (!parseObject())
return false;
- DEBUG << "value: object";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: object";
+ QT_PARSER_TRACING_END;
return true;
}
case ValueSeparator:
@@ -663,8 +660,8 @@ bool Parser::parseValue()
--json;
if (!parseNumber())
return false;
- DEBUG << "value: number";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: number";
+ QT_PARSER_TRACING_END;
}
return true;
@@ -690,7 +687,7 @@ bool Parser::parseValue()
bool Parser::parseNumber()
{
- BEGIN << "parseNumber" << json;
+ QT_PARSER_TRACING_BEGIN << "parseNumber" << json;
const char *start = json;
bool isInt = true;
@@ -703,14 +700,14 @@ bool Parser::parseNumber()
if (json < end && *json == '0') {
++json;
} else {
- while (json < end && *json >= '0' && *json <= '9')
+ while (json < end && isAsciiDigit(*json))
++json;
}
// frac = decimal-point 1*DIGIT
if (json < end && *json == '.') {
++json;
- while (json < end && *json >= '0' && *json <= '9') {
+ while (json < end && isAsciiDigit(*json)) {
isInt = isInt && *json == '0';
++json;
}
@@ -722,7 +719,7 @@ bool Parser::parseNumber()
++json;
if (json < end && (*json == '-' || *json == '+'))
++json;
- while (json < end && *json >= '0' && *json <= '9')
+ while (json < end && isAsciiDigit(*json))
++json;
}
@@ -732,14 +729,14 @@ bool Parser::parseNumber()
}
const QByteArray number = QByteArray::fromRawData(start, json - start);
- DEBUG << "numberstring" << number;
+ QT_PARSER_TRACING_DEBUG << "numberstring" << number;
if (isInt) {
bool ok;
qlonglong n = number.toLongLong(&ok);
if (ok) {
container->append(QCborValue(n));
- END;
+ QT_PARSER_TRACING_END;
return true;
}
}
@@ -758,7 +755,7 @@ bool Parser::parseNumber()
else
container->append(QCborValue(d));
- END;
+ QT_PARSER_TRACING_END;
return true;
}
@@ -784,28 +781,26 @@ bool Parser::parseNumber()
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
*/
-static inline bool addHexDigit(char digit, uint *result)
+static inline bool addHexDigit(char digit, char32_t *result)
{
*result <<= 4;
- if (digit >= '0' && digit <= '9')
- *result |= (digit - '0');
- else if (digit >= 'a' && digit <= 'f')
- *result |= (digit - 'a') + 10;
- else if (digit >= 'A' && digit <= 'F')
- *result |= (digit - 'A') + 10;
- else
- return false;
- return true;
+ const int h = fromHex(digit);
+ if (h != -1) {
+ *result |= h;
+ return true;
+ }
+
+ return false;
}
-static inline bool scanEscapeSequence(const char *&json, const char *end, uint *ch)
+static inline bool scanEscapeSequence(const char *&json, const char *end, char32_t *ch)
{
++json;
if (json >= end)
return false;
- DEBUG << "scan escape" << (char)*json;
- uint escaped = *json++;
+ QT_PARSER_TRACING_DEBUG << "scan escape" << (char)*json;
+ uchar escaped = *json++;
switch (escaped) {
case '"':
*ch = '"'; break;
@@ -843,12 +838,12 @@ static inline bool scanEscapeSequence(const char *&json, const char *end, uint *
return true;
}
-static inline bool scanUtf8Char(const char *&json, const char *end, uint *result)
+static inline bool scanUtf8Char(const char *&json, const char *end, char32_t *result)
{
const auto *usrc = reinterpret_cast<const uchar *>(json);
const auto *uend = reinterpret_cast<const uchar *>(end);
const uchar b = *usrc++;
- int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, usrc, uend);
+ qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, usrc, uend);
if (res < 0)
return false;
@@ -862,11 +857,11 @@ bool Parser::parseString()
// try to parse a utf-8 string without escape sequences, and note whether it's 7bit ASCII.
- BEGIN << "parse string" << json;
+ QT_PARSER_TRACING_BEGIN << "parse string" << json;
bool isUtf8 = true;
bool isAscii = true;
while (json < end) {
- uint ch = 0;
+ char32_t ch = 0;
if (*json == '"')
break;
if (*json == '\\') {
@@ -883,10 +878,10 @@ bool Parser::parseString()
}
if (ch > 0x7f)
isAscii = false;
- DEBUG << " " << ch << char(ch);
+ QT_PARSER_TRACING_DEBUG << " " << ch << char(ch);
}
++json;
- DEBUG << "end of string";
+ QT_PARSER_TRACING_DEBUG << "end of string";
if (json >= end) {
lastError = QJsonParseError::UnterminatedString;
return false;
@@ -898,17 +893,17 @@ bool Parser::parseString()
container->appendAsciiString(start, json - start - 1);
else
container->appendUtf8String(start, json - start - 1);
- END;
+ QT_PARSER_TRACING_END;
return true;
}
- DEBUG << "has escape sequences";
+ QT_PARSER_TRACING_DEBUG << "has escape sequences";
json = start;
QString ucs4;
while (json < end) {
- uint ch = 0;
+ char32_t ch = 0;
if (*json == '"')
break;
else if (*json == '\\') {
@@ -931,10 +926,14 @@ bool Parser::parseString()
return false;
}
- container->appendByteData(reinterpret_cast<const char *>(ucs4.utf16()), ucs4.size() * 2,
+ container->appendByteData(reinterpret_cast<const char *>(ucs4.constData()), ucs4.size() * 2,
QCborValue::String, QtCbor::Element::StringIsUtf16);
- END;
+ QT_PARSER_TRACING_END;
return true;
}
QT_END_NAMESPACE
+
+#undef QT_PARSER_TRACING_BEGIN
+#undef QT_PARSER_TRACING_END
+#undef QT_PARSER_TRACING_DEBUG
diff --git a/src/corelib/serialization/qjsonparser_p.h b/src/corelib/serialization/qjsonparser_p.h
index 14d9705447..47830a108e 100644
--- a/src/corelib/serialization/qjsonparser_p.h
+++ b/src/corelib/serialization/qjsonparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONPARSER_P_H
#define QJSONPARSER_P_H
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index 5eb33bd2a3..6c2656d89f 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsonobject.h>
#include <qjsonvalue.h>
@@ -45,6 +10,8 @@
#include <quuid.h>
#include <qvariant.h>
#include <qstringlist.h>
+#include <qmap.h>
+#include <qhash.h>
#include <qdebug.h>
#include "qdatastream.h"
@@ -58,16 +25,44 @@
QT_BEGIN_NAMESPACE
+static QJsonValue::Type convertFromCborType(QCborValue::Type type) noexcept
+{
+ switch (type) {
+ case QCborValue::Null:
+ return QJsonValue::Null;
+ case QCborValue::True:
+ case QCborValue::False:
+ return QJsonValue::Bool;
+ case QCborValue::Double:
+ case QCborValue::Integer:
+ return QJsonValue::Double;
+ case QCborValue::String:
+ return QJsonValue::String;
+ case QCborValue::Array:
+ return QJsonValue::Array;
+ case QCborValue::Map:
+ return QJsonValue::Object;
+ case QCborValue::Undefined:
+ default:
+ return QJsonValue::Undefined;
+ }
+}
+
/*!
\class QJsonValue
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonValue class encapsulates a value in JSON.
+ \compares equality
+ \compareswith equality QJsonValueConstRef QJsonValueRef
+ \endcompareswith
+
A value in JSON can be one of 6 basic types:
JSON is a format to store structured data. It has 6 basic data types:
@@ -101,11 +96,11 @@ QT_BEGIN_NAMESPACE
The following methods return QJsonValueRef:
\list
- \li \l {QJsonArray}::operator[](int i)
+ \li \l {QJsonArray}::operator[](qsizetype i)
\li \l {QJsonObject}::operator[](const QString & key) const
\endlist
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -114,26 +109,25 @@ QT_BEGIN_NAMESPACE
The default is to create a Null value.
*/
QJsonValue::QJsonValue(Type type)
- : d(nullptr), t(QCborValue::Undefined)
{
switch (type) {
case Null:
- t = QCborValue::Null;
+ value = QCborValue::Null;
break;
case Bool:
- t = QCborValue::False;
+ value = QCborValue::False;
break;
case Double:
- t = QCborValue::Double;
+ value = QCborValue::Double;
break;
case String:
- t = QCborValue::String;
+ value = QCborValue::String;
break;
case Array:
- t = QCborValue::Array;
+ value = QCborValue::Array;
break;
case Object:
- t = QCborValue::Map;
+ value = QCborValue::Map;
break;
case Undefined:
break;
@@ -144,24 +138,27 @@ QJsonValue::QJsonValue(Type type)
Creates a value of type Bool, with value \a b.
*/
QJsonValue::QJsonValue(bool b)
- : t(b ? QCborValue::True : QCborValue::False)
+ : value(b)
{
}
+static inline QCborValue doubleValueHelper(double v)
+{
+ qint64 n = 0;
+ // Convert to integer if the number is an integer and changing wouldn't
+ // introduce additional digit precision not present in the double.
+ if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */))
+ return n;
+ else
+ return v;
+}
+
/*!
Creates a value of type Double, with value \a v.
*/
QJsonValue::QJsonValue(double v)
- : d(nullptr)
+ : value(doubleValueHelper(v))
{
- // Convert to integer if the number is an integer and changing wouldn't
- // introduce additional digit precision not present in the double.
- if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */)) {
- t = QCborValue::Integer;
- } else {
- memcpy(&n, &v, sizeof(n));
- t = QCborValue::Double;
- }
}
/*!
@@ -169,7 +166,7 @@ QJsonValue::QJsonValue(double v)
Creates a value of type Double, with value \a v.
*/
QJsonValue::QJsonValue(int v)
- : n(v), t(QCborValue::Integer)
+ : value(v)
{
}
@@ -180,7 +177,7 @@ QJsonValue::QJsonValue(int v)
If you pass in values outside this range expect a loss of precision to occur.
*/
QJsonValue::QJsonValue(qint64 v)
- : n(v), t(QCborValue::Integer)
+ : value(v)
{
}
@@ -188,7 +185,7 @@ QJsonValue::QJsonValue(qint64 v)
Creates a value of type String, with value \a s.
*/
QJsonValue::QJsonValue(const QString &s)
- : QJsonValue(QJsonPrivate::Value::fromTrustedCbor(s))
+ : value(s)
{
}
@@ -204,25 +201,28 @@ QJsonValue::QJsonValue(const QString &s)
\since 5.3
*/
-// ### Qt6: remove
-void QJsonValue::stringDataFromQStringHelper(const QString &string)
+/*!
+ Creates a value of type String, with the Latin-1 string viewed by \a s.
+ */
+QJsonValue::QJsonValue(QLatin1StringView s)
+ : value(s)
{
- *this = QJsonValue(string);
}
/*!
- Creates a value of type String, with value \a s.
+ Creates a value of type Array, with value \a a.
*/
-QJsonValue::QJsonValue(QLatin1String s)
- : QJsonValue(QJsonPrivate::Value::fromTrustedCbor(s))
+QJsonValue::QJsonValue(const QJsonArray &a)
+ : value(QCborArray::fromJsonArray(a))
{
}
/*!
- Creates a value of type Array, with value \a a.
+ \overload
+ \since 6.3
*/
-QJsonValue::QJsonValue(const QJsonArray &a)
- : n(-1), d(a.a), t(QCborValue::Array)
+QJsonValue::QJsonValue(QJsonArray &&a) noexcept
+ : value(QCborArray::fromJsonArray(std::move(a)))
{
}
@@ -230,7 +230,16 @@ QJsonValue::QJsonValue(const QJsonArray &a)
Creates a value of type Object, with value \a o.
*/
QJsonValue::QJsonValue(const QJsonObject &o)
- : n(-1), d(o.o), t(QCborValue::Map)
+ : value(QCborMap::fromJsonObject(o))
+{
+}
+
+/*!
+ \overload
+ \since 6.3
+ */
+QJsonValue::QJsonValue(QJsonObject &&o) noexcept
+ : value(QCborMap::fromJsonObject(std::move(o)))
{
}
@@ -243,38 +252,27 @@ QJsonValue::~QJsonValue() = default;
/*!
Creates a copy of \a other.
*/
-QJsonValue::QJsonValue(const QJsonValue &other)
-{
- n = other.n;
- t = other.t;
- d = other.d;
-}
+QJsonValue::QJsonValue(const QJsonValue &other) noexcept = default;
/*!
Assigns the value stored in \a other to this object.
*/
-QJsonValue &QJsonValue::operator =(const QJsonValue &other)
+QJsonValue &QJsonValue::operator =(const QJsonValue &other) noexcept
{
QJsonValue copy(other);
swap(copy);
return *this;
}
-QJsonValue::QJsonValue(QJsonValue &&other) noexcept :
- n(other.n),
- d(other.d),
- t(other.t)
+QJsonValue::QJsonValue(QJsonValue &&other) noexcept
+ : value(std::move(other.value))
{
- other.n = 0;
- other.d = nullptr;
- other.t = QCborValue::Null;
+ other.value = QCborValue(nullptr);
}
void QJsonValue::swap(QJsonValue &other) noexcept
{
- qSwap(n, other.n);
- qSwap(d, other.d);
- qSwap(t, other.t);
+ value.swap(other.value);
}
/*!
@@ -351,7 +349,7 @@ void QJsonValue::swap(QJsonValue &other) noexcept
error cases as e.g. accessing a non existing key in a QJsonObject.
*/
-
+#ifndef QT_NO_VARIANT
/*!
Converts \a variant to a QJsonValue and returns it.
@@ -439,14 +437,44 @@ void QJsonValue::swap(QJsonValue &other) noexcept
"stringification" of map keys.
\endtable
- For all other QVariant types a conversion to a QString will be attempted. If the returned string
- is empty, a Null QJsonValue will be stored, otherwise a String value using the returned QString.
-
- \sa toVariant()
+ \section2 Loss of information and other types
+
+ QVariant can carry more information than is representable in JSON. If the
+ QVariant is not one of the types above, the conversion is not guaranteed
+ and is subject to change in future versions of Qt, as the UUID one did.
+ Code should strive not to use any other types than those listed above.
+
+ If QVariant::isNull() returns true, a null QJsonValue is returned or
+ inserted into the list or object, regardless of the type carried by
+ QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull()
+ also affects this function.
+
+ A floating point value that is either an infinity or NaN will be converted
+ to a null JSON value. Since Qt 6.0, QJsonValue can store the full precision
+ of any 64-bit signed integer without loss, but in previous versions values
+ outside the range of ±2^53 may lose precision. Unsigned 64-bit values
+ greater than or equal to 2^63 will either lose precision or alias to
+ negative values, so QMetaType::ULongLong should be avoided.
+
+ For other types not listed above, a conversion to string will be attempted,
+ usually but not always by calling QVariant::toString(). If the conversion
+ fails the value is replaced by a null JSON value. Note that
+ QVariant::toString() is also lossy for the majority of types. For example,
+ if the passed QVariant is representing raw byte array data, it is recommended
+ to pre-encode it to \l {RFC 4686}{Base64} (or
+ another lossless encoding), otherwise a lossy conversion using QString::fromUtf8()
+ will be used.
+
+ Please note that the conversions via QVariant::toString() are subject to
+ change at any time. Both QVariant and QJsonValue may be extended in the
+ future to support more types, which will result in a change in how this
+ function performs conversions.
+
+ \sa toVariant(), QCborValue::fromVariant()
*/
QJsonValue QJsonValue::fromVariant(const QVariant &variant)
{
- switch (variant.userType()) {
+ switch (variant.metaType().id()) {
case QMetaType::Nullptr:
return QJsonValue(Null);
case QMetaType::Bool:
@@ -462,8 +490,10 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
return QJsonValue(variant.toLongLong());
Q_FALLTHROUGH();
case QMetaType::Float:
- case QMetaType::Double:
- return QJsonValue(variant.toDouble());
+ case QMetaType::Double: {
+ double v = variant.toDouble();
+ return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
+ }
case QMetaType::QString:
return QJsonValue(variant.toString());
case QMetaType::QStringList:
@@ -522,7 +552,7 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
*/
QVariant QJsonValue::toVariant() const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::True:
return true;
case QCborValue::False:
@@ -534,13 +564,9 @@ QVariant QJsonValue::toVariant() const
case QCborValue::String:
return toString();
case QCborValue::Array:
- return d ?
- QJsonArray(d.data()).toVariantList() :
- QVariantList();
+ return toArray().toVariantList();
case QCborValue::Map:
- return d ?
- QJsonObject(d.data()).toVariantMap() :
- QVariantMap();
+ return toObject().toVariantMap();
case QCborValue::Null:
return QVariant::fromValue(nullptr);
case QCborValue::Undefined:
@@ -566,6 +592,7 @@ QVariant QJsonValue::toVariant() const
error condition, when trying to read an out of bounds value
in an array or a non existent key in an object.
*/
+#endif // !QT_NO_VARIANT
/*!
Returns the type of the value.
@@ -574,25 +601,7 @@ QVariant QJsonValue::toVariant() const
*/
QJsonValue::Type QJsonValue::type() const
{
- switch (t) {
- case QCborValue::Null:
- return QJsonValue::Null;
- case QCborValue::True:
- case QCborValue::False:
- return QJsonValue::Bool;
- case QCborValue::Double:
- case QCborValue::Integer:
- return QJsonValue::Double;
- case QCborValue::String:
- return QJsonValue::String;
- case QCborValue::Array:
- return QJsonValue::Array;
- case QCborValue::Map:
- return QJsonValue::Object;
- case QCborValue::Undefined:
- default:
- return QJsonValue::Undefined;
- }
+ return convertFromCborType(value.type());
}
/*!
@@ -602,7 +611,7 @@ QJsonValue::Type QJsonValue::type() const
*/
bool QJsonValue::toBool(bool defaultValue) const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::True:
return true;
case QCborValue::False:
@@ -621,17 +630,19 @@ bool QJsonValue::toBool(bool defaultValue) const
*/
int QJsonValue::toInt(int defaultValue) const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::Double: {
int dblInt;
if (convertDoubleTo<int>(toDouble(), &dblInt))
return dblInt;
break;
}
- case QCborValue::Integer:
+ case QCborValue::Integer: {
+ const auto n = value.toInteger();
if (qint64(int(n)) == n)
return int(n);
break;
+ }
default:
break;
}
@@ -647,9 +658,9 @@ int QJsonValue::toInt(int defaultValue) const
*/
qint64 QJsonValue::toInteger(qint64 defaultValue) const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::Integer:
- return n;
+ return value.toInteger();
case QCborValue::Double: {
qint64 dblInt;
if (convertDoubleTo<qint64>(toDouble(), &dblInt))
@@ -669,17 +680,7 @@ qint64 QJsonValue::toInteger(qint64 defaultValue) const
*/
double QJsonValue::toDouble(double defaultValue) const
{
- switch (t) {
- case QCborValue::Double: {
- double d;
- memcpy(&d, &n, sizeof(d));
- return d;
- }
- case QCborValue::Integer:
- return double(n);
- default:
- return defaultValue;
- }
+ return value.toDouble(defaultValue);
}
/*!
@@ -689,7 +690,7 @@ double QJsonValue::toDouble(double defaultValue) const
*/
QString QJsonValue::toString(const QString &defaultValue) const
{
- return (t == QCborValue::String && d) ? d->stringAt(n) : defaultValue;
+ return value.toString(defaultValue);
}
/*!
@@ -701,7 +702,7 @@ QString QJsonValue::toString(const QString &defaultValue) const
*/
QString QJsonValue::toString() const
{
- return (t == QCborValue::String && d) ? d->stringAt(n) : QString();
+ return value.toString();
}
/*!
@@ -711,10 +712,15 @@ QString QJsonValue::toString() const
*/
QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const
{
- if (t != QCborValue::Array || n >= 0 || !d)
+ if (!isArray())
return defaultValue;
-
- return QJsonArray(d.data());
+ QCborContainerPrivate *dd = nullptr;
+ const auto n = QJsonPrivate::Value::valueHelper(value);
+ const auto container = QJsonPrivate::Value::container(value);
+ Q_ASSERT(n == -1 || container == nullptr);
+ if (n < 0)
+ dd = container;
+ return QJsonArray(dd);
}
/*!
@@ -736,10 +742,15 @@ QJsonArray QJsonValue::toArray() const
*/
QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const
{
- if (t != QCborValue::Map || n >= 0 || !d)
+ if (!isObject())
return defaultValue;
-
- return QJsonObject(d.data());
+ QCborContainerPrivate *dd = nullptr;
+ const auto container = QJsonPrivate::Value::container(value);
+ const auto n = QJsonPrivate::Value::valueHelper(value);
+ Q_ASSERT(n == -1 || container == nullptr);
+ if (n < 0)
+ dd = container;
+ return QJsonObject(dd);
}
/*!
@@ -754,7 +765,6 @@ QJsonObject QJsonValue::toObject() const
return toObject(QJsonObject());
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -771,7 +781,6 @@ const QJsonValue QJsonValue::operator[](const QString &key) const
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\overload
@@ -789,7 +798,7 @@ const QJsonValue QJsonValue::operator[](QStringView key) const
\overload
\since 5.10
*/
-const QJsonValue QJsonValue::operator[](QLatin1String key) const
+const QJsonValue QJsonValue::operator[](QLatin1StringView key) const
{
if (!isObject())
return QJsonValue(QJsonValue::Undefined);
@@ -809,7 +818,7 @@ const QJsonValue QJsonValue::operator[](QLatin1String key) const
\sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
*/
-const QJsonValue QJsonValue::operator[](int i) const
+const QJsonValue QJsonValue::operator[](qsizetype i) const
{
if (!isArray())
return QJsonValue(QJsonValue::Undefined);
@@ -818,42 +827,37 @@ const QJsonValue QJsonValue::operator[](int i) const
}
/*!
- Returns \c true if the value is equal to \a other.
- */
-bool QJsonValue::operator==(const QJsonValue &other) const
+ \fn bool QJsonValue::operator==(const QJsonValue &lhs, const QJsonValue &rhs)
+
+ Returns \c true if the \a lhs value is equal to \a rhs value, \c false otherwise.
+*/
+bool comparesEqual(const QJsonValue &lhs, const QJsonValue &rhs) noexcept
{
- if (t != other.t) {
- if (isDouble() && other.isDouble()) {
+ if (lhs.value.type() != rhs.value.type()) {
+ if (lhs.isDouble() && rhs.isDouble()) {
// One value Cbor integer, one Cbor double, should interact as doubles.
- return toDouble() == other.toDouble();
+ return lhs.toDouble() == rhs.toDouble();
}
return false;
}
- switch (t) {
+ switch (lhs.value.type()) {
case QCborValue::Undefined:
case QCborValue::Null:
case QCborValue::True:
case QCborValue::False:
break;
case QCborValue::Double:
- return toDouble() == other.toDouble();
+ return lhs.toDouble() == rhs.toDouble();
case QCborValue::Integer:
- return n == other.n;
+ return QJsonPrivate::Value::valueHelper(lhs.value)
+ == QJsonPrivate::Value::valueHelper(rhs.value);
case QCborValue::String:
- return toString() == other.toString();
+ return lhs.toString() == rhs.toString();
case QCborValue::Array:
- if (!d)
- return !other.d || other.d->elements.length() == 0;
- if (!other.d)
- return d->elements.length() == 0;
- return QJsonArray(d.data()) == QJsonArray(other.d.data());
+ return lhs.toArray() == rhs.toArray();
case QCborValue::Map:
- if (!d)
- return !other.d || other.d->elements.length() == 0;
- if (!other.d)
- return d->elements.length() == 0;
- return QJsonObject(d.data()) == QJsonObject(other.d.data());
+ return lhs.toObject() == rhs.toObject();
default:
return false;
}
@@ -861,21 +865,10 @@ bool QJsonValue::operator==(const QJsonValue &other) const
}
/*!
- Returns \c true if the value is not equal to \a other.
- */
-bool QJsonValue::operator!=(const QJsonValue &other) const
-{
- return !(*this == other);
-}
-
-/*!
- \internal
- */
-void QJsonValue::detach()
-{
- d.detach();
-}
+ \fn bool QJsonValue::operator!=(const QJsonValue &lhs, const QJsonValue &rhs)
+ Returns \c true if the \a lhs value is not equal to \a rhs value, \c false otherwise.
+*/
/*!
\class QJsonValueRef
@@ -900,48 +893,200 @@ void QJsonValue::detach()
However, they are not explicitly documented here.
*/
-
-QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
+void QJsonValueRef::detach()
{
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QCborContainerPrivate *d = QJsonPrivate::Value::container(*this);
+ d = QCborContainerPrivate::detach(d, d->elements.size());
+
if (is_object)
- o->setValueAt(index, val);
+ o->o.reset(d);
else
- a->replace(index, val);
+ a->a.reset(d);
+#else
+ d = QCborContainerPrivate::detach(d, d->elements.size());
+#endif
+}
- return *this;
+static QJsonValueRef &assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
+{
+ QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
+ qsizetype index = QJsonPrivate::Value::indexHelper(ref);
+ if (is_object && value.isUndefined()) {
+ d->removeAt(index);
+ d->removeAt(index - 1);
+ } else {
+ d->replaceAt(index, value);
+ }
+
+ return ref;
+}
+
+QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
+{
+ detach();
+ return assignToRef(*this, QCborValue::fromJsonValue(val), is_object);
}
QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
{
- if (is_object)
- o->setValueAt(index, ref);
- else
- a->replace(index, ref);
+ // ### optimize more?
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
+ qsizetype index = QJsonPrivate::Value::indexHelper(ref);
- return *this;
+ if (d == QJsonPrivate::Value::container(*this) &&
+ index == QJsonPrivate::Value::indexHelper(*this))
+ return *this; // self assignment
+
+ detach();
+ return assignToRef(*this, d->valueAt(index), is_object);
}
+#ifndef QT_NO_VARIANT
+QVariant QJsonValueConstRef::toVariant() const
+{
+ return concrete(*this).toVariant();
+}
+#endif // !QT_NO_VARIANT
+
+QJsonArray QJsonValueConstRef::toArray() const
+{
+ return concrete(*this).toArray();
+}
+
+QJsonObject QJsonValueConstRef::toObject() const
+{
+ return concrete(*this).toObject();
+}
+
+QJsonValue::Type QJsonValueConstRef::concreteType(QJsonValueConstRef self) noexcept
+{
+ return convertFromCborType(QJsonPrivate::Value::elementHelper(self).type);
+}
+
+bool QJsonValueConstRef::concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ if (e.type == QCborValue::False)
+ return false;
+ if (e.type == QCborValue::True)
+ return true;
+ return defaultValue;
+}
+
+qint64 QJsonValueConstRef::concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ qint64 v = defaultValue;
+ if (e.type == QCborValue::Double) {
+ // convertDoubleTo modifies the output even on returning false
+ if (!convertDoubleTo<qint64>(e.fpvalue(), &v))
+ v = defaultValue;
+ } else if (e.type == QCborValue::Integer) {
+ v = e.value;
+ }
+ if (clamp && qint64(int(v)) != v)
+ return defaultValue;
+ return v;
+}
+
+double QJsonValueConstRef::concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ if (e.type == QCborValue::Double)
+ return e.fpvalue();
+ if (e.type == QCborValue::Integer)
+ return e.value;
+ return defaultValue;
+}
+
+QString QJsonValueConstRef::concreteString(QJsonValueConstRef self, const QString &defaultValue)
+{
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+ if (d->elements.at(index).type != QCborValue::String)
+ return defaultValue;
+ return d->stringAt(index);
+}
+
+QJsonValue QJsonValueConstRef::concrete(QJsonValueConstRef self) noexcept
+{
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+ return QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index));
+}
+
+QString QJsonValueConstRef::objectKey(QJsonValueConstRef self)
+{
+ Q_ASSERT(self.is_object);
+ Q_ASSERT(self.is_object);
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+
+ Q_ASSERT(d);
+ Q_ASSERT(index < d->elements.size());
+ return d->stringAt(index - 1);
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QVariant QJsonValueRef::toVariant() const
{
- return toValue().toVariant();
+ return QJsonValueConstRef::toVariant();
}
QJsonArray QJsonValueRef::toArray() const
{
- return toValue().toArray();
+ return QJsonValueConstRef::toArray();
}
QJsonObject QJsonValueRef::toObject() const
{
- return toValue().toObject();
+ return QJsonValueConstRef::toObject();
}
QJsonValue QJsonValueRef::toValue() const
{
- if (!is_object)
- return a->at(index);
- return o->valueAt(index);
+ return concrete(*this);
+}
+#else
+QJsonValueRef QJsonValueRef::operator[](qsizetype key)
+{
+ if (d->elements.at(index).type != QCborValue::Array)
+ d->replaceAt(index, QCborValue::Array);
+
+ auto &e = d->elements[index];
+ e.container = QCborContainerPrivate::grow(e.container, key); // detaches
+ e.flags |= QtCbor::Element::IsContainer;
+
+ return QJsonValueRef(e.container, key, false);
+}
+
+QJsonValueRef QJsonValueRef::operator[](QAnyStringView key)
+{
+ // must go through QJsonObject because some of the machinery is non-static
+ // member or file-static in qjsonobject.cpp
+ QJsonObject o = QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index)).toObject();
+ QJsonValueRef ret = key.visit([&](auto v) {
+ if constexpr (std::is_same_v<decltype(v), QUtf8StringView>)
+ return o[QString::fromUtf8(v)];
+ else
+ return o[v];
+ });
+
+ // ### did the QJsonObject::operator[] above detach?
+ QCborContainerPrivate *x = o.o.take();
+ Q_ASSERT(x->ref.loadRelaxed() == 1);
+
+ auto &e = d->elements[index];
+ if (e.flags & QtCbor::Element::IsContainer && e.container != x)
+ o.o.reset(e.container); // might not an object!
+
+ e.flags |= QtCbor::Element::IsContainer;
+ e.container = x;
+
+ return ret;
}
+#endif
size_t qHash(const QJsonValue &value, size_t seed)
{
@@ -961,15 +1106,14 @@ size_t qHash(const QJsonValue &value, size_t seed)
case QJsonValue::Undefined:
return seed;
}
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonValue &o)
{
QDebugStateSaver saver(dbg);
- switch (o.t) {
+ switch (o.value.type()) {
case QCborValue::Undefined:
dbg << "QJsonValue(undefined)";
break;
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index 205ee31dd5..d71dadf837 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -1,49 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONVALUE_H
#define QJSONVALUE_H
+#include <QtCore/qcborvalue.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qshareddata.h>
-#include <QtCore/qcborvalue.h>
QT_BEGIN_NAMESPACE
@@ -75,18 +40,20 @@ public:
QJsonValue(int n);
QJsonValue(qint64 v);
QJsonValue(const QString &s);
- QJsonValue(QLatin1String s);
+ QJsonValue(QLatin1StringView s);
#ifndef QT_NO_CAST_FROM_ASCII
- inline QT_ASCII_CAST_WARN QJsonValue(const char *s)
+ QT_ASCII_CAST_WARN inline QJsonValue(const char *s)
: QJsonValue(QString::fromUtf8(s)) {}
#endif
QJsonValue(const QJsonArray &a);
+ QJsonValue(QJsonArray &&a) noexcept;
QJsonValue(const QJsonObject &o);
+ QJsonValue(QJsonObject &&o) noexcept;
~QJsonValue();
- QJsonValue(const QJsonValue &other);
- QJsonValue &operator =(const QJsonValue &other);
+ QJsonValue(const QJsonValue &other) noexcept;
+ QJsonValue &operator =(const QJsonValue &other) noexcept;
QJsonValue(QJsonValue &&other) noexcept;
@@ -121,17 +88,21 @@ public:
QJsonObject toObject() const;
QJsonObject toObject(const QJsonObject &defaultValue) const;
-#if QT_STRINGVIEW_LEVEL < 2
const QJsonValue operator[](const QString &key) const;
-#endif
const QJsonValue operator[](QStringView key) const;
- const QJsonValue operator[](QLatin1String key) const;
- const QJsonValue operator[](int i) const;
+ const QJsonValue operator[](QLatin1StringView key) const;
+ const QJsonValue operator[](qsizetype i) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonValue &other) const;
bool operator!=(const QJsonValue &other) const;
+#endif
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonValue &lhs,
+ const QJsonValue &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValue)
+
// avoid implicit conversions from char * to bool
QJsonValue(const void *) = delete;
friend class QJsonPrivate::Value;
@@ -141,35 +112,148 @@ private:
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &);
- // ### Qt6: Remove this.
- void stringDataFromQStringHelper(const QString &string);
-
- void detach();
-
- // ### Qt6: change to an actual QCborValue
- qint64 n = 0;
- QExplicitlySharedDataPointer<QCborContainerPrivate> d; // needed for Objects, Arrays, Strings
- QCborValue::Type t;
+ QCborValue value;
// Assert binary compatibility with pre-5.15 QJsonValue
static_assert(sizeof(QExplicitlySharedDataPointer<QCborContainerPrivate>) == sizeof(void *));
static_assert(sizeof(QCborValue::Type) == sizeof(QJsonValue::Type));
};
-class Q_CORE_EXPORT QJsonValueRef
+Q_DECLARE_SHARED(QJsonValue)
+
+class QJsonValueConstRef
{
public:
- QJsonValueRef(QJsonArray *array, int idx)
- : a(array), is_object(false), index(static_cast<uint>(idx)) {}
- QJsonValueRef(QJsonObject *object, int idx)
- : o(object), is_object(true), index(static_cast<uint>(idx)) {}
+ QJsonValueConstRef(const QJsonValueConstRef &) = default;
+ QJsonValueConstRef &operator=(const QJsonValueConstRef &) = delete;
+ inline operator QJsonValue() const { return concrete(*this); }
+
+ Q_CORE_EXPORT QVariant toVariant() const;
+ QJsonValue::Type type() const { return concreteType(*this); }
+ bool isNull() const { return type() == QJsonValue::Null; }
+ bool isBool() const { return type() == QJsonValue::Bool; }
+ bool isDouble() const { return type() == QJsonValue::Double; }
+ bool isString() const { return type() == QJsonValue::String; }
+ bool isArray() const { return type() == QJsonValue::Array; }
+ bool isObject() const { return type() == QJsonValue::Object; }
+ bool isUndefined() const { return type() == QJsonValue::Undefined; }
+
+ bool toBool(bool defaultValue = false) const
+ { return concreteBool(*this, defaultValue); }
+ int toInt(int defaultValue = 0) const
+ { return int(concreteInt(*this, defaultValue, true)); }
+ qint64 toInteger(qint64 defaultValue = 0) const
+ { return concreteInt(*this, defaultValue, false); }
+ double toDouble(double defaultValue = 0) const
+ { return concreteDouble(*this, defaultValue); }
+ QString toString(const QString &defaultValue = {}) const
+ { return concreteString(*this, defaultValue); }
+ Q_CORE_EXPORT QJsonArray toArray() const;
+ Q_CORE_EXPORT QJsonObject toObject() const;
+
+ const QJsonValue operator[](QStringView key) const { return concrete(*this)[key]; }
+ const QJsonValue operator[](QLatin1StringView key) const { return concrete(*this)[key]; }
+ const QJsonValue operator[](qsizetype i) const { return concrete(*this)[i]; }
+
+protected:
+ friend bool comparesEqual(const QJsonValueConstRef &lhs,
+ const QJsonValueConstRef &rhs) noexcept
+ {
+ return comparesEqual(concrete(lhs), concrete(rhs));
+ }
+ friend bool comparesEqual(const QJsonValueConstRef &lhs,
+ const QJsonValue &rhs) noexcept
+ {
+ return comparesEqual(concrete(lhs), rhs);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueConstRef)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueConstRef, QJsonValue)
+
+ Q_CORE_EXPORT static QJsonValue::Type
+ concreteType(QJsonValueConstRef self) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static bool
+ concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static qint64
+ concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static double
+ concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static QString concreteString(QJsonValueConstRef self, const QString &defaultValue);
+ Q_CORE_EXPORT static QJsonValue concrete(QJsonValueConstRef self) noexcept;
+
+ // for iterators
+ Q_CORE_EXPORT static QString objectKey(QJsonValueConstRef self);
+ QString objectKey() const { return objectKey(*this); }
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QJsonValueConstRef(QJsonArray *array, qsizetype idx)
+ : a(array), is_object(false), index(static_cast<quint64>(idx)) {}
+ QJsonValueConstRef(QJsonObject *object, qsizetype idx)
+ : o(object), is_object(true), index(static_cast<quint64>(idx)) {}
+
+ void rebind(QJsonValueConstRef other)
+ {
+ Q_ASSERT(is_object == other.is_object);
+ if (is_object)
+ o = other.o;
+ else
+ a = other.a;
+ index = other.index;
+ }
- inline operator QJsonValue() const { return toValue(); }
- QJsonValueRef &operator = (const QJsonValue &val);
- QJsonValueRef &operator = (const QJsonValueRef &val);
+ union {
+ QJsonArray *a;
+ QJsonObject *o;
+ void *d;
+ };
+ quint64 is_object : 1;
+ quint64 index : 63;
+#else
+ constexpr QJsonValueConstRef(QCborContainerPrivate *d, size_t index, bool is_object)
+ : d(d), is_object(is_object), index(index)
+ {}
+
+ // implemented in qjsonarray.h & qjsonobject.h, to get their d
+ QJsonValueConstRef(QJsonArray *array, qsizetype idx);
+ QJsonValueConstRef(QJsonObject *object, qsizetype idx);
+
+ void rebind(QJsonValueConstRef other)
+ {
+ d = other.d;
+ index = other.index;
+ }
+
+ QCborContainerPrivate *d = nullptr;
+ size_t is_object : 1;
+ size_t index : std::numeric_limits<size_t>::digits - 1;
+#endif
+
+ friend class QJsonArray;
+ friend class QJsonObject;
+ friend class QJsonPrivate::Value;
+};
+
+QT_WARNING_PUSH
+QT6_ONLY(QT_WARNING_DISABLE_MSVC(4275)) // non dll-interface class 'QJsonValueConstRef' used as base for dll-interface class 'QJsonValueRef'
+class QT6_ONLY(Q_CORE_EXPORT) QJsonValueRef : public QJsonValueConstRef
+{
+public:
+ QJsonValueRef(const QJsonValueRef &) = default;
+ QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValue &val);
+ QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValueRef &val);
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ // retained for binary compatibility (due to the Q_CORE_EXPORT) because at
+ // least one compiler emits and exports all inlines in an exported class
+
+ QJsonValueRef(QJsonArray *array, qsizetype idx)
+ : QJsonValueConstRef(array, idx) {}
+ QJsonValueRef(QJsonObject *object, qsizetype idx)
+ : QJsonValueConstRef(object, idx) {}
+
+ operator QJsonValue() const { return toValue(); }
QVariant toVariant() const;
- inline QJsonValue::Type type() const { return toValue().type(); }
+ inline QJsonValue::Type type() const { return QJsonValueConstRef::type(); }
inline bool isNull() const { return type() == QJsonValue::Null; }
inline bool isBool() const { return type() == QJsonValue::Bool; }
inline bool isDouble() const { return type() == QJsonValue::Double; }
@@ -178,59 +262,57 @@ public:
inline bool isObject() const { return type() == QJsonValue::Object; }
inline bool isUndefined() const { return type() == QJsonValue::Undefined; }
- inline bool toBool() const { return toValue().toBool(); }
- inline int toInt() const { return toValue().toInt(); }
- inline double toDouble() const { return toValue().toDouble(); }
- inline QString toString() const { return toValue().toString(); }
+ inline bool toBool(bool defaultValue = false) const { return QJsonValueConstRef::toBool(defaultValue); }
+ inline int toInt(int defaultValue = 0) const { return QJsonValueConstRef::toInt(defaultValue); }
+ inline qint64 toInteger(qint64 defaultValue = 0) const { return QJsonValueConstRef::toInteger(defaultValue); }
+ inline double toDouble(double defaultValue = 0) const { return QJsonValueConstRef::toDouble(defaultValue); }
+ inline QString toString(const QString &defaultValue = {}) const { return QJsonValueConstRef::toString(defaultValue); }
QJsonArray toArray() const;
QJsonObject toObject() const;
- // ### Qt 6: Add default values
- inline bool toBool(bool defaultValue) const { return toValue().toBool(defaultValue); }
- inline int toInt(int defaultValue) const { return toValue().toInt(defaultValue); }
- inline double toDouble(double defaultValue) const { return toValue().toDouble(defaultValue); }
- inline QString toString(const QString &defaultValue) const { return toValue().toString(defaultValue); }
+ const QJsonValue operator[](QStringView key) const { return QJsonValueConstRef::operator[](key); }
+ const QJsonValue operator[](QLatin1StringView key) const { return QJsonValueConstRef::operator[](key); }
+ const QJsonValue operator[](qsizetype i) const { return QJsonValueConstRef::operator[](i); }
- inline bool operator==(const QJsonValue &other) const { return toValue() == other; }
- inline bool operator!=(const QJsonValue &other) const { return toValue() != other; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QJsonValue &other) const { return comparesEqual(*this, other); }
+ inline bool operator!=(const QJsonValue &other) const { return !comparesEqual(*this, other); }
+#endif
private:
- QJsonValue toValue() const;
+ friend bool comparesEqual(const QJsonValueRef &lhs,
+ const QJsonValueRef &rhs) noexcept
+ {
+ return comparesEqual(QJsonValue(lhs), QJsonValue(rhs));
+ }
+ friend bool comparesEqual(const QJsonValueRef &lhs,
+ const QJsonValueConstRef &rhs) noexcept
+ {
+ return comparesEqual(QJsonValue(lhs), QJsonValue(rhs));
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueRef)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueRef, QJsonValueConstRef)
- union {
- QJsonArray *a;
- QJsonObject *o;
- };
- uint is_object : 1;
- uint index : 31;
-};
+ QJsonValue toValue() const;
+#else
+ using QJsonValueConstRef::operator[];
+ Q_CORE_EXPORT QJsonValueRef operator[](QAnyStringView key);
+ Q_CORE_EXPORT QJsonValueRef operator[](qsizetype i);
-// ### Qt 6: Get rid of these fake pointer classes
-class QJsonValuePtr
-{
- QJsonValue value;
-public:
- explicit QJsonValuePtr(const QJsonValue& val)
- : value(val) {}
+private:
+ using QJsonValueConstRef::QJsonValueConstRef;
+#endif // < Qt 7
- QJsonValue& operator*() { return value; }
- QJsonValue* operator->() { return &value; }
+ QT7_ONLY(Q_CORE_EXPORT) void detach();
+ friend class QJsonArray;
+ friend class QJsonObject;
};
+QT_WARNING_POP
-class QJsonValueRefPtr
+inline QJsonValue QCborValueConstRef::toJsonValue() const
{
- QJsonValueRef valueRef;
-public:
- QJsonValueRefPtr(QJsonArray *array, int idx)
- : valueRef(array, idx) {}
- QJsonValueRefPtr(QJsonObject *object, int idx)
- : valueRef(object, idx) {}
-
- QJsonValueRef& operator*() { return valueRef; }
- QJsonValueRef* operator->() { return &valueRef; }
-};
-
-Q_DECLARE_SHARED(QJsonValue)
+ return concrete().toJsonValue();
+}
Q_CORE_EXPORT size_t qHash(const QJsonValue &value, size_t seed = 0);
diff --git a/src/corelib/serialization/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 8610cdff7e..ab34e9228d 100644
--- a/src/corelib/serialization/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <cmath>
#include <qlocale.h>
@@ -58,26 +22,27 @@ static inline uchar hexdig(uint u)
return (u < 0xa ? '0' + u : 'a' + u - 0xa);
}
-static QByteArray escapedString(const QString &s)
+static QByteArray escapedString(QStringView s)
{
// give it a minimum size to ensure the resize() below always adds enough space
- QByteArray ba(qMax(s.length(), 16), Qt::Uninitialized);
+ QByteArray ba(qMax(s.size(), 16), Qt::Uninitialized);
+ auto ba_const_start = [&]() { return reinterpret_cast<const uchar *>(ba.constData()); };
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
- const uchar *ba_end = cursor + ba.length();
- const ushort *src = reinterpret_cast<const ushort *>(s.constBegin());
- const ushort *const end = reinterpret_cast<const ushort *>(s.constEnd());
+ const uchar *ba_end = cursor + ba.size();
+ const char16_t *src = s.utf16();
+ const char16_t *const end = s.utf16() + s.size();
while (src != end) {
if (cursor >= ba_end - 6) {
// ensure we have enough space
- int pos = cursor - (const uchar *)ba.constData();
+ qptrdiff pos = cursor - ba_const_start();
ba.resize(ba.size()*2);
- cursor = (uchar *)ba.data() + pos;
- ba_end = (const uchar *)ba.constData() + ba.length();
+ cursor = reinterpret_cast<uchar *>(ba.data()) + pos;
+ ba_end = ba_const_start() + ba.size();
}
- uint u = *src++;
+ char16_t u = *src++;
if (u < 0x80) {
if (u < 0x20 || u == 0x22 || u == 0x5c) {
*cursor++ = '\\';
@@ -124,7 +89,7 @@ static QByteArray escapedString(const QString &s)
}
}
- ba.resize(cursor - (const uchar *)ba.constData());
+ ba.resize(cursor - ba_const_start());
return ba;
}
@@ -143,7 +108,7 @@ static void valueToJson(const QCborValue &v, QByteArray &json, int indent, bool
break;
case QCborValue::Double: {
const double d = v.toDouble();
- if (qIsFinite(d))
+ if (qt_is_finite(d))
json += QByteArray::number(d, 'g', QLocale::FloatingPointShortest);
else
json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
diff --git a/src/corelib/serialization/qjsonwriter_p.h b/src/corelib/serialization/qjsonwriter_p.h
index 8c263bb7c3..f61840247f 100644
--- a/src/corelib/serialization/qjsonwriter_p.h
+++ b/src/corelib/serialization/qjsonwriter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONWRITER_P_H
#define QJSONWRITER_P_H
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index 3f0c25fd17..e9d650b3e2 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QTEXTSTREAM_DEBUG
static const int QTEXTSTREAM_BUFFERSIZE = 16384;
@@ -50,6 +14,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
\ingroup io
\ingroup string-processing
+ \ingroup qtserialization
\reentrant
QTextStream can operate on a QIODevice, a QByteArray or a
@@ -230,6 +195,9 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
#include "qfile.h"
#include "qnumeric.h"
#include "qvarlengtharray.h"
+#include <private/qdebug_p.h>
+#include <private/qnumeric_p.h>
+#include <private/qtools_p.h>
#include <locale.h>
#include "private/qlocale_p.h"
@@ -239,48 +207,6 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
#include <limits.h>
#include <new>
-#if defined QTEXTSTREAM_DEBUG
-#include <ctype.h>
-#include "private/qtools_p.h"
-
-QT_BEGIN_NAMESPACE
-
-// Returns a human readable representation of the first \a len
-// characters in \a data.
-static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
-{
- if (!data) return "(null)";
- QByteArray out;
- for (int i = 0; i < len; ++i) {
- char c = data[i];
- if (isprint(int(uchar(c)))) {
- out += c;
- } else switch (c) {
- case '\n': out += "\\n"; break;
- case '\r': out += "\\r"; break;
- case '\t': out += "\\t"; break;
- default: {
- const char buf[] = {
- '\\',
- 'x',
- QtMiscUtils::toHexLower(uchar(c) / 16),
- QtMiscUtils::toHexLower(uchar(c) % 16),
- 0
- };
- out += buf;
- }
- }
- }
-
- if (len < maxSize)
- out += "...";
-
- return out;
-}
-QT_END_NAMESPACE
-
-#endif
-
// A precondition macro
#define Q_VOID
#define CHECK_VALID_STREAM(x) do { \
@@ -320,6 +246,9 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
//-------------------------------------------------------------------
/*!
@@ -351,7 +280,7 @@ void QTextStreamPrivate::Params::reset()
realNumberPrecision = 6;
integerBase = 0;
fieldWidth = 0;
- padChar = QLatin1Char(' ');
+ padChar = u' ';
fieldAlignment = QTextStream::AlignRight;
realNumberNotation = QTextStream::SmartNotation;
numberFlags = { };
@@ -368,7 +297,7 @@ void QTextStreamPrivate::reset()
deleteDevice = false;
string = nullptr;
stringOffset = 0;
- stringOpenMode = QIODevice::NotOpen;
+ stringOpenMode = QTextStream::NotOpen;
readBufferOffset = 0;
readBufferStartDevicePos = 0;
@@ -431,10 +360,11 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
if (bytesRead <= 0)
return false;
+#ifndef QT_BOOTSTRAPPED
if (autoDetectUnicode) {
autoDetectUnicode = false;
- auto e = QStringConverter::encodingForData(buf, bytesRead);
+ auto e = QStringConverter::encodingForData(QByteArrayView(buf, bytesRead));
// QStringConverter::Locale implies unknown, so keep the current encoding
if (e) {
encoding = *e;
@@ -445,18 +375,19 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer(), using %s encoding", QStringConverter::nameForEncoding(encoding));
#endif
+#endif
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d",
- qt_prettyDebug(buf, qMin(32,int(bytesRead)) , int(bytesRead)).constData(), int(sizeof(buf)), int(bytesRead));
+ QtDebugUtils::toPrintable(buf, bytesRead, 32).constData(), int(sizeof(buf)), int(bytesRead));
#endif
int oldReadBufferSize = readBuffer.size();
- readBuffer += toUtf16(buf, bytesRead);
+ readBuffer += toUtf16(QByteArrayView(buf, bytesRead));
// remove all '\r\n' in the string.
if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
- QChar CR = QLatin1Char('\r');
+ QChar CR = u'\r';
QChar *writePtr = readBuffer.data() + oldReadBufferSize;
QChar *readPtr = readBuffer.data() + oldReadBufferSize;
QChar *endPtr = readBuffer.data() + readBuffer.size();
@@ -486,7 +417,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer() read %d bytes from device. readBuffer = [%s]", int(bytesRead),
- qt_prettyDebug(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).data());
+ QtDebugUtils::toPrintable(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).constData());
#endif
return true;
}
@@ -524,7 +455,7 @@ void QTextStreamPrivate::flushWriteBuffer()
bool textModeEnabled = device->isTextModeEnabled();
if (textModeEnabled) {
device->setTextModeEnabled(false);
- writeBuffer.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+ writeBuffer.replace(u'\n', "\r\n"_L1);
}
#endif
@@ -536,7 +467,7 @@ void QTextStreamPrivate::flushWriteBuffer()
qint64 bytesWritten = device->write(data);
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::flushWriteBuffer(), device->write(\"%s\") == %d",
- qt_prettyDebug(data.constData(), qMin(data.size(),32), data.size()).constData(), int(bytesWritten));
+ QtDebugUtils::toPrintable(data.constData(), data.size(), 32).constData(), int(bytesWritten));
#endif
#if defined (Q_OS_WIN)
@@ -601,7 +532,6 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
int startOffset = device ? readBufferOffset : stringOffset;
QChar lastChar;
- bool canStillReadFromDevice = true;
do {
int endOffset;
const QChar *chPtr;
@@ -632,9 +562,9 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
}
break;
case EndOfLine:
- if (ch == QLatin1Char('\n')) {
+ if (ch == u'\n') {
foundToken = true;
- delimSize = (lastChar == QLatin1Char('\r')) ? 2 : 1;
+ delimSize = (lastChar == u'\r') ? 2 : 1;
consumeDelimiter = true;
}
lastChar = ch;
@@ -643,7 +573,7 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
}
} while (!foundToken
&& (!maxlen || totalSize < maxlen)
- && (device && (canStillReadFromDevice = fillReadBuffer())));
+ && device && fillReadBuffer());
if (totalSize == 0) {
#if defined (QTEXTSTREAM_DEBUG)
@@ -656,7 +586,7 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
// don't make it part of the line.
if (delimiter == EndOfLine && totalSize > 0 && !foundToken) {
if (((string && stringOffset + totalSize == string->size()) || (device && device->atEnd()))
- && lastChar == QLatin1Char('\r')) {
+ && lastChar == u'\r') {
consumeDelimiter = true;
++delimSize;
}
@@ -754,7 +684,7 @@ inline void QTextStreamPrivate::restoreToSavedConverterState()
/*!
\internal
*/
-void QTextStreamPrivate::write(const QChar *data, int len)
+void QTextStreamPrivate::write(const QChar *data, qsizetype len)
{
if (string) {
// ### What about seek()??
@@ -784,7 +714,7 @@ inline void QTextStreamPrivate::write(QChar ch)
/*!
\internal
*/
-void QTextStreamPrivate::write(QLatin1String data)
+void QTextStreamPrivate::write(QLatin1StringView data)
{
if (string) {
// ### What about seek()??
@@ -799,7 +729,7 @@ void QTextStreamPrivate::write(QLatin1String data)
/*!
\internal
*/
-void QTextStreamPrivate::writePadding(int len)
+void QTextStreamPrivate::writePadding(qsizetype len)
{
if (string) {
// ### What about seek()??
@@ -864,7 +794,7 @@ inline void QTextStreamPrivate::putChar(QChar ch)
/*!
\internal
*/
-QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const
+QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(qsizetype len) const
{
Q_ASSERT(params.fieldWidth > len); // calling padding() when no padding is needed is an error
@@ -891,7 +821,7 @@ QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const
/*!
\internal
*/
-void QTextStreamPrivate::putString(const QChar *data, int len, bool number)
+void QTextStreamPrivate::putString(const QChar *data, qsizetype len, bool number)
{
if (Q_UNLIKELY(params.fieldWidth > len)) {
@@ -920,7 +850,7 @@ void QTextStreamPrivate::putString(const QChar *data, int len, bool number)
/*!
\internal
*/
-void QTextStreamPrivate::putString(QLatin1String data, bool number)
+void QTextStreamPrivate::putString(QLatin1StringView data, bool number)
{
if (Q_UNLIKELY(params.fieldWidth > data.size())) {
@@ -933,7 +863,7 @@ void QTextStreamPrivate::putString(QLatin1String data, bool number)
if (sign == locale.negativeSign() || sign == locale.positiveSign()) {
// write the sign before the padding, then skip it later
write(&sign, 1);
- data = QLatin1String(data.data() + 1, data.size() - 1);
+ data = QLatin1StringView(data.data() + 1, data.size() - 1);
}
}
@@ -945,6 +875,11 @@ void QTextStreamPrivate::putString(QLatin1String data, bool number)
}
}
+void QTextStreamPrivate::putString(QUtf8StringView data, bool number)
+{
+ putString(data.toString(), number);
+}
+
/*!
Constructs a QTextStream. Before you can use it for reading or
writing, you must assign a device or a string.
@@ -983,7 +918,7 @@ QTextStream::QTextStream(QIODevice *device)
Constructs a QTextStream that operates on \a string, using \a
openMode to define the open mode.
*/
-QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(QString *string, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1001,7 +936,7 @@ QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode)
openMode to define the open mode. Internally, the array is wrapped
by a QBuffer.
*/
-QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(QByteArray *array, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1028,7 +963,7 @@ QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode)
\snippet code/src_corelib_io_qtextstream.cpp 3
*/
-QTextStream::QTextStream(const QByteArray &array, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(const QByteArray &array, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1059,7 +994,7 @@ QTextStream::QTextStream(const QByteArray &array, QIODevice::OpenMode openMode)
\snippet code/src_corelib_io_qtextstream.cpp 4
*/
-QTextStream::QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(FILE *fileHandle, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1067,7 +1002,10 @@ QTextStream::QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode)
fileHandle, int(openMode));
#endif
QFile *file = new QFile;
- file->open(fileHandle, openMode);
+ // Discarding the return value of open; even if it failed
+ // (and the file is not open), QTextStream still reports `Ok`
+ // for closed QIODevices, so there's nothing really to do here.
+ (void)file->open(fileHandle, openMode);
Q_D(QTextStream);
d->device = file;
@@ -1272,7 +1210,7 @@ QIODevice *QTextStream::device() const
\sa string(), setDevice()
*/
-void QTextStream::setString(QString *string, QIODevice::OpenMode openMode)
+void QTextStream::setString(QString *string, OpenMode openMode)
{
Q_D(QTextStream);
flush();
@@ -1470,7 +1408,8 @@ QTextStream::RealNumberNotation QTextStream::realNumberNotation() const
/*!
Sets the precision of real numbers to \a precision. This value
describes the number of fraction digits QTextStream should
- write when generating real numbers.
+ write when generating real numbers (FixedNotation, ScientificNotation), or
+ the maximum number of significant digits (SmartNotation).
The precision cannot be a negative value. The default value is 6.
@@ -1489,7 +1428,9 @@ void QTextStream::setRealNumberPrecision(int precision)
/*!
Returns the current real number precision, or the number of fraction
- digits QTextStream will write when generating real numbers.
+ digits QTextStream will write when generating real numbers
+ (FixedNotation, ScientificNotation), or the maximum number of significant
+ digits (SmartNotation).
\sa setRealNumberNotation(), realNumberNotation(), numberFlags(), integerBase()
*/
@@ -1683,7 +1624,7 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
QChar ch;
if (!getChar(&ch))
return npsInvalidPrefix;
- if (ch == QLatin1Char('0')) {
+ if (ch == u'0') {
QChar ch2;
if (!getChar(&ch2)) {
// Result is the number 0
@@ -1692,9 +1633,9 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
}
ch2 = ch2.toLower();
- if (ch2 == QLatin1Char('x')) {
+ if (ch2 == u'x') {
base = 16;
- } else if (ch2 == QLatin1Char('b')) {
+ } else if (ch2 == u'b') {
base = 2;
} else if (ch2.isDigit() && ch2.digitValue() >= 0 && ch2.digitValue() <= 7) {
base = 8;
@@ -1719,9 +1660,9 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
case 2: {
QChar pf1, pf2, dig;
// Parse prefix '0b'
- if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ if (!getChar(&pf1) || pf1 != u'0')
return npsInvalidPrefix;
- if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('b'))
+ if (!getChar(&pf2) || pf2.toLower() != u'b')
return npsInvalidPrefix;
// Parse digits
int ndigits = 0;
@@ -1747,13 +1688,13 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
case 8: {
QChar pf, dig;
// Parse prefix '0'
- if (!getChar(&pf) || pf != QLatin1Char('0'))
+ if (!getChar(&pf) || pf != u'0')
return npsInvalidPrefix;
// Parse digits
int ndigits = 0;
while (getChar(&dig)) {
int n = dig.toLower().unicode();
- if (n >= '0' && n <= '7') {
+ if (isOctalDigit(n)) {
val *= 8;
val += n - '0';
} else {
@@ -1810,20 +1751,17 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
case 16: {
QChar pf1, pf2, dig;
// Parse prefix ' 0x'
- if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ if (!getChar(&pf1) || pf1 != u'0')
return npsInvalidPrefix;
- if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('x'))
+ if (!getChar(&pf2) || pf2.toLower() != u'x')
return npsInvalidPrefix;
// Parse digits
int ndigits = 0;
while (getChar(&dig)) {
- int n = dig.toLower().unicode();
- if (n >= '0' && n <= '9') {
- val <<= 4;
- val += n - '0';
- } else if (n >= 'a' && n <= 'f') {
+ const int h = fromHex(dig.unicode());
+ if (h != -1) {
val <<= 4;
- val += 10 + (n - 'a');
+ val += h;
} else {
ungetChar(dig);
break;
@@ -1979,13 +1917,13 @@ bool QTextStreamPrivate::getReal(double *f)
// nan/+inf/-inf, so here we also check for uppercase and mixed
// case versions.
if (!qstricmp(buf, "nan") || !qstricmp(buf, "+nan") || !qstricmp(buf, "-nan")) {
- *f = qQNaN();
+ *f = qt_qnan();
return true;
} else if (!qstricmp(buf, "+inf") || !qstricmp(buf, "inf")) {
- *f = qInf();
+ *f = qt_inf();
return true;
} else if (!qstricmp(buf, "-inf")) {
- *f = -qInf();
+ *f = -qt_inf();
return true;
}
bool ok;
@@ -2017,7 +1955,7 @@ QTextStream &QTextStream::operator>>(QChar &c)
\overload
Reads a character from the stream and stores it in \a c. The
- character from the stream is converted to ISO-5589-1 before it is
+ character from the stream is converted to ISO-8859-1 before it is
stored.
\sa QChar::toLatin1()
@@ -2031,6 +1969,14 @@ QTextStream &QTextStream::operator>>(char &c)
}
/*!
+ \fn QTextStream &QTextStream::operator>>(char16_t &c)
+ \overload
+ \since 6.4
+
+ Reads a character from the stream and stores it in \a c.
+*/
+
+/*!
Reads an integer from the stream and stores it in \a i, then
returns a reference to the QTextStream. The number is cast to
the correct type before it is stored. If no number was detected on
@@ -2186,7 +2132,7 @@ QTextStream &QTextStream::operator>>(QString &str)
/*!
\overload
- Converts the word to ISO-8859-1, then stores it in \a array.
+ Converts the word to UTF-8, then stores it in \a array.
\sa QString::toLatin1()
*/
@@ -2195,7 +2141,6 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- array.clear();
d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
d->consumeLastToken();
@@ -2203,11 +2148,11 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
int length;
if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
setStatus(ReadPastEnd);
+ array.clear();
return *this;
}
- for (int i = 0; i < length; ++i)
- array += ptr[i].toLatin1();
+ array = QStringView(ptr, length).toUtf8();
d->consumeLastToken();
return *this;
@@ -2216,13 +2161,14 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
/*!
\overload
- Stores the word in \a c, terminated by a '\\0' character. If no word is
- available, only the '\\0' character is stored.
+ Converts the word to UTF-8 and stores it in \a c, terminated by a '\\0'
+ character. If no word is available, only the '\\0' character is stored.
Warning: Although convenient, this operator is dangerous and must
be used with care. QTextStream assumes that \a c points to a
buffer with enough space to hold the word. If the buffer is too
- small, your application may crash.
+ small, your application may crash. For a word consisting of \c{n} QChars,
+ the buffer needs to be at least \c{3*n+1} characters long.
If possible, use the QByteArray operator instead.
*/
@@ -2241,9 +2187,9 @@ QTextStream &QTextStream::operator>>(char *c)
return *this;
}
- for (int i = 0; i < length; ++i)
- *c++ = ptr[i].toLatin1();
- *c = '\0';
+ QStringEncoder encoder(QStringConverter::Utf8);
+ char *e = encoder.appendToBuffer(c, QStringView(ptr, length));
+ *e = '\0';
d->consumeLastToken();
return *this;
}
@@ -2269,7 +2215,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// add thousands group separators. For backward compatibility we
// don't add a group separator for C locale.
if (locale != QLocale::c() && !locale.numberOptions().testFlag(QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
+ flags |= QLocaleData::GroupDigits;
const QLocaleData *dd = locale.d->m_data;
int base = params.integerBase ? params.integerBase : 10;
@@ -2288,8 +2234,8 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// workaround for backward compatibility - in octal form with
// ShowBase flag set zero should be written as '00'
if (number == 0 && base == 8 && params.numberFlags & QTextStream::ShowBase
- && result == QLatin1String("0")) {
- result.prepend(QLatin1Char('0'));
+ && result == "0"_L1) {
+ result.prepend(u'0');
}
}
putString(result, true);
@@ -2323,6 +2269,15 @@ QTextStream &QTextStream::operator<<(char c)
}
/*!
+ \fn QTextStream &QTextStream::operator<<(char16_t c)
+ \overload
+ \since 6.3.1
+
+ Writes the Unicode character \a c to the stream, then returns a
+ reference to the QTextStream.
+*/
+
+/*!
Writes the integer number \a i to the stream, then returns a
reference to the QTextStream. By default, the number is stored in
decimal form, but you can also set the base by calling
@@ -2485,7 +2440,7 @@ QTextStream &QTextStream::operator<<(double f)
flags |= QLocaleData::AddTrailingZeroes | QLocaleData::ShowBase;
}
if (locale() != QLocale::c() && !(numberOptions & QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
+ flags |= QLocaleData::GroupDigits;
if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
@@ -2533,7 +2488,7 @@ QTextStream &QTextStream::operator<<(QStringView string)
Writes \a string to the stream, and returns a reference to the
QTextStream.
*/
-QTextStream &QTextStream::operator<<(QLatin1String string)
+QTextStream &QTextStream::operator<<(QLatin1StringView string)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
@@ -2551,7 +2506,7 @@ QTextStream &QTextStream::operator<<(const QByteArray &array)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- d->putString(QString::fromUtf8(array.constData(), array.length()));
+ d->putString(QString::fromUtf8(array.constData(), array.size()));
return *this;
}
@@ -2559,7 +2514,7 @@ QTextStream &QTextStream::operator<<(const QByteArray &array)
\overload
Writes the constant string pointed to by \a string to the stream. \a
- string is assumed to be in ISO-8859-1 encoding. This operator
+ string is assumed to be in UTF-8 encoding. This operator
is convenient when working with constant string data. Example:
\snippet code/src_corelib_io_qtextstream.cpp 8
@@ -2572,8 +2527,7 @@ QTextStream &QTextStream::operator<<(const char *string)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- // ### Qt6: consider changing to UTF-8
- d->putString(QLatin1String(string));
+ d->putString(QUtf8StringView(string));
return *this;
}
@@ -2600,12 +2554,6 @@ QTextStream &QTextStream::operator<<(const void *ptr)
namespace Qt {
/*!
- \fn QTextStream &bin(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::bin() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(2) on \a stream and returns \a
stream.
@@ -2620,12 +2568,6 @@ QTextStream &bin(QTextStream &stream)
}
/*!
- \fn QTextStream &oct(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::oct() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(8) on \a stream and returns \a
stream.
@@ -2640,12 +2582,6 @@ QTextStream &oct(QTextStream &stream)
}
/*!
- \fn QTextStream &dec(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::dec() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(10) on \a stream and returns \a
stream.
@@ -2660,12 +2596,6 @@ QTextStream &dec(QTextStream &stream)
}
/*!
- \fn QTextStream &hex(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::hex() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(16) on \a stream and returns \a
stream.
@@ -2681,12 +2611,6 @@ QTextStream &hex(QTextStream &stream)
}
/*!
- \fn QTextStream &showbase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::showbase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::ShowBase) on \a stream and returns \a stream.
@@ -2701,12 +2625,6 @@ QTextStream &showbase(QTextStream &stream)
}
/*!
- \fn QTextStream &forcesign(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::forcesign() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::ForceSign) on \a stream and returns \a stream.
@@ -2721,12 +2639,6 @@ QTextStream &forcesign(QTextStream &stream)
}
/*!
- \fn QTextStream &forcepoint(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::forcepoint() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::ForcePoint) on \a stream and returns \a stream.
@@ -2741,12 +2653,6 @@ QTextStream &forcepoint(QTextStream &stream)
}
/*!
- \fn QTextStream &noshowbase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::noshowbase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::ShowBase) on \a stream and returns \a stream.
@@ -2761,12 +2667,6 @@ QTextStream &noshowbase(QTextStream &stream)
}
/*!
- \fn QTextStream &noforcesign(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::noforcesign() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::ForceSign) on \a stream and returns \a stream.
@@ -2781,12 +2681,6 @@ QTextStream &noforcesign(QTextStream &stream)
}
/*!
- \fn QTextStream &noforcepoint(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::noforcepoint() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::ForcePoint) on \a stream and returns \a stream.
@@ -2801,12 +2695,6 @@ QTextStream &noforcepoint(QTextStream &stream)
}
/*!
- \fn QTextStream &uppercasebase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::uppercasebase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::UppercaseBase) on \a stream and returns \a stream.
@@ -2821,12 +2709,6 @@ QTextStream &uppercasebase(QTextStream &stream)
}
/*!
- \fn QTextStream &uppercasedigits(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::uppercasedigits() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::UppercaseDigits) on \a stream and returns \a stream.
@@ -2841,12 +2723,6 @@ QTextStream &uppercasedigits(QTextStream &stream)
}
/*!
- \fn QTextStream &lowercasebase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::lowercasebase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::UppercaseBase) on \a stream and returns \a stream.
@@ -2861,12 +2737,6 @@ QTextStream &lowercasebase(QTextStream &stream)
}
/*!
- \fn QTextStream &lowercasedigits(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::lowercasedigits() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::UppercaseDigits) on \a stream and returns \a stream.
@@ -2881,12 +2751,6 @@ QTextStream &lowercasedigits(QTextStream &stream)
}
/*!
- \fn QTextStream &fixed(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::fixed() instead.
-*/
-
-/*!
Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation)
on \a stream and returns \a stream.
@@ -2901,12 +2765,6 @@ QTextStream &fixed(QTextStream &stream)
}
/*!
- \fn QTextStream &scientific(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::scientific() instead.
-*/
-
-/*!
Calls QTextStream::setRealNumberNotation(QTextStream::ScientificNotation)
on \a stream and returns \a stream.
@@ -2921,18 +2779,12 @@ QTextStream &scientific(QTextStream &stream)
}
/*!
- \fn QTextStream &left(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::left() instead.
-*/
-
-/*!
Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft)
on \a stream and returns \a stream.
\since 5.14
- \sa {QTextStream::}{right()}, {QTextStream::}{center()}, {QTextStream manipulators}
+ \sa right(), center(), {QTextStream manipulators}
*/
QTextStream &left(QTextStream &stream)
{
@@ -2941,18 +2793,12 @@ QTextStream &left(QTextStream &stream)
}
/*!
- \fn QTextStream &right(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::right() instead.
-*/
-
-/*!
Calls QTextStream::setFieldAlignment(QTextStream::AlignRight)
on \a stream and returns \a stream.
\since 5.14
- \sa {QTextStream::}{left()}, {QTextStream::}{center()}, {QTextStream manipulators}
+ \sa left(), center(), {QTextStream manipulators}
*/
QTextStream &right(QTextStream &stream)
{
@@ -2961,18 +2807,12 @@ QTextStream &right(QTextStream &stream)
}
/*!
- \fn QTextStream &center(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::center() instead.
-*/
-
-/*!
Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter)
on \a stream and returns \a stream.
\since 5.14
- \sa {QTextStream::}{left()}, {QTextStream::}{right()}, {QTextStream manipulators}
+ \sa left(), right(), {QTextStream manipulators}
*/
QTextStream &center(QTextStream &stream)
{
@@ -2981,12 +2821,6 @@ QTextStream &center(QTextStream &stream)
}
/*!
- \fn QTextStream &endl(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::endl() instead.
-*/
-
-/*!
Writes '\\n' to the \a stream and flushes the stream.
Equivalent to
@@ -3002,16 +2836,10 @@ QTextStream &center(QTextStream &stream)
*/
QTextStream &endl(QTextStream &stream)
{
- return stream << QLatin1Char('\n') << Qt::flush;
+ return stream << '\n'_L1 << Qt::flush;
}
/*!
- \fn QTextStream &flush(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::flush() instead.
-*/
-
-/*!
Calls QTextStream::flush() on \a stream and returns \a stream.
\since 5.14
@@ -3025,12 +2853,6 @@ QTextStream &flush(QTextStream &stream)
}
/*!
- \fn QTextStream &reset(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::reset() instead.
-*/
-
-/*!
Calls QTextStream::reset() on \a stream and returns \a stream.
\since 5.14
@@ -3044,12 +2866,6 @@ QTextStream &reset(QTextStream &stream)
}
/*!
- \fn QTextStream &ws(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::ws() instead.
-*/
-
-/*!
Calls \l {QTextStream::}{skipWhiteSpace()} on \a stream and returns \a stream.
\since 5.14
@@ -3088,12 +2904,6 @@ QTextStream &ws(QTextStream &stream)
namespace Qt {
/*!
- \fn QTextStream &bom(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::bom() instead.
-*/
-
-/*!
Toggles insertion of the Byte Order Mark on \a stream when QTextStream is
used with a UTF encoding.
@@ -3140,7 +2950,7 @@ void QTextStream::setEncoding(QStringConverter::Encoding encoding)
d->encoding = encoding;
d->toUtf16 = QStringDecoder(d->encoding);
- bool generateBOM = d->hasWrittenData && d->generateBOM;
+ bool generateBOM = !d->hasWrittenData && d->generateBOM;
d->fromUtf16 = QStringEncoder(d->encoding,
generateBOM ? QStringEncoder::Flag::WriteBom : QStringEncoder::Flag::Default);
@@ -3194,7 +3004,7 @@ bool QTextStream::autoDetectUnicode() const
device. If \a generate is false, no BOM will be inserted. This function
must be called before any data is written. Otherwise, it does nothing.
- \sa generateByteOrderMark(), bom()
+ \sa generateByteOrderMark(), {Qt::}{bom()}
*/
void QTextStream::setGenerateByteOrderMark(bool generate)
{
@@ -3249,78 +3059,6 @@ QLocale QTextStream::locale() const
return d->locale;
}
-#if QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC)
-// Deprecated source compatible migration versions:
-namespace QTextStreamFunctions {
-QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
-QTextStream &oct(QTextStream &s) { return Qt::oct(s); }
-QTextStream &dec(QTextStream &s) { return Qt::dec(s); }
-QTextStream &hex(QTextStream &s) { return Qt::hex(s); }
-
-QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); }
-QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); }
-QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); }
-QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); }
-QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); }
-QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); }
-
-QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); }
-QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); }
-QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); }
-QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); }
-
-QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); }
-QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); }
-
-QTextStream &left(QTextStream &s) { return Qt::left(s); }
-QTextStream &right(QTextStream &s) { return Qt::right(s); }
-QTextStream &center(QTextStream &s) { return Qt::center(s); }
-
-QTextStream &endl(QTextStream &s) { return Qt::endl(s); }
-QTextStream &flush(QTextStream &s) { return Qt::flush(s); }
-QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
-
-QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
-
-QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
-} // namespace QTextStreamFunctions
-#endif
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
-// Binary compatible definitions for Qt<5.14
-Q_CORE_EXPORT QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
-Q_CORE_EXPORT QTextStream &oct(QTextStream &s) { return Qt::oct(s); }
-Q_CORE_EXPORT QTextStream &dec(QTextStream &s) { return Qt::dec(s); }
-Q_CORE_EXPORT QTextStream &hex(QTextStream &s) { return Qt::hex(s); }
-
-Q_CORE_EXPORT QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); }
-Q_CORE_EXPORT QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); }
-Q_CORE_EXPORT QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); }
-Q_CORE_EXPORT QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); }
-Q_CORE_EXPORT QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); }
-Q_CORE_EXPORT QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); }
-
-Q_CORE_EXPORT QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); }
-Q_CORE_EXPORT QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); }
-Q_CORE_EXPORT QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); }
-Q_CORE_EXPORT QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); }
-
-Q_CORE_EXPORT QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); }
-Q_CORE_EXPORT QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); }
-
-Q_CORE_EXPORT QTextStream &left(QTextStream &s) { return Qt::left(s); }
-Q_CORE_EXPORT QTextStream &right(QTextStream &s) { return Qt::right(s); }
-Q_CORE_EXPORT QTextStream &center(QTextStream &s) { return Qt::center(s); }
-
-Q_CORE_EXPORT QTextStream &endl(QTextStream &s) { return Qt::endl(s); }
-Q_CORE_EXPORT QTextStream &flush(QTextStream &s) { return Qt::flush(s); }
-Q_CORE_EXPORT QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
-
-Q_CORE_EXPORT QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
-
-Q_CORE_EXPORT QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
-#endif
-
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h
index 1d13ed896c..7a0fc42a68 100644
--- a/src/corelib/serialization/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
@@ -1,62 +1,43 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTSTREAM_H
#define QTEXTSTREAM_H
-#include <QtCore/qiodevice.h>
-#include <QtCore/qstring.h>
+#include <QtCore/qiodevicebase.h>
#include <QtCore/qchar.h>
-#include <QtCore/qlocale.h>
#include <QtCore/qscopedpointer.h>
-#include <QtCore/qstringconverter.h>
+#include <QtCore/qstringconverter_base.h>
#include <stdio.h>
+#if 0
+// the macros around the class name throw off syncqt:
+#pragma qt_class(QTextStream)
+#endif
+
#ifdef Status
#error qtextstream.h must be included before any header file that defines Status
#endif
QT_BEGIN_NAMESPACE
+class QIODevice;
+class QLocale;
+class QString;
+
+#if !QT_DEPRECATED_SINCE(6, 9)
+# define QT_NO_INHERITABLE_TEXT_STREAM
+#endif
+
+#ifdef QT_NO_INHERITABLE_TEXT_STREAM
+# define QT_TEXT_STREAM_FINAL final
+#else
+# define QT_TEXT_STREAM_FINAL
+#endif
+
class QTextStreamPrivate;
-class Q_CORE_EXPORT QTextStream // text stream class
+class Q_CORE_EXPORT QTextStream QT_TEXT_STREAM_FINAL : public QIODeviceBase
{
Q_DECLARE_PRIVATE(QTextStream)
@@ -89,11 +70,12 @@ public:
QTextStream();
explicit QTextStream(QIODevice *device);
- explicit QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
- explicit QTextStream(QString *string, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
- explicit QTextStream(QByteArray *array, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
- explicit QTextStream(const QByteArray &array, QIODevice::OpenMode openMode = QIODevice::ReadOnly);
- virtual ~QTextStream();
+ explicit QTextStream(FILE *fileHandle, OpenMode openMode = ReadWrite);
+ explicit QTextStream(QString *string, OpenMode openMode = ReadWrite);
+ explicit QTextStream(QByteArray *array, OpenMode openMode = ReadWrite);
+ explicit QTextStream(const QByteArray &array, OpenMode openMode = ReadOnly);
+ QT6_ONLY(virtual)
+ ~QTextStream();
void setEncoding(QStringConverter::Encoding encoding);
QStringConverter::Encoding encoding() const;
@@ -108,7 +90,7 @@ public:
void setDevice(QIODevice *device);
QIODevice *device() const;
- void setString(QString *string, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
+ void setString(QString *string, OpenMode openMode = ReadWrite);
QString *string() const;
Status status() const;
@@ -151,6 +133,8 @@ public:
QTextStream &operator>>(QChar &ch);
QTextStream &operator>>(char &ch);
+ QTextStream &operator>>(char16_t &ch)
+ { QChar c; *this >> c; ch = c.unicode(); return *this; }
QTextStream &operator>>(signed short &i);
QTextStream &operator>>(unsigned short &i);
QTextStream &operator>>(signed int &i);
@@ -167,6 +151,7 @@ public:
QTextStream &operator<<(QChar ch);
QTextStream &operator<<(char ch);
+ QTextStream &operator<<(char16_t ch) { return *this << QChar(ch); }
QTextStream &operator<<(signed short i);
QTextStream &operator<<(unsigned short i);
QTextStream &operator<<(signed int i);
@@ -179,7 +164,7 @@ public:
QTextStream &operator<<(double f);
QTextStream &operator<<(const QString &s);
QTextStream &operator<<(QStringView s);
- QTextStream &operator<<(QLatin1String s);
+ QTextStream &operator<<(QLatin1StringView s);
QTextStream &operator<<(const QByteArray &array);
QTextStream &operator<<(const char *c);
QTextStream &operator<<(const void *ptr);
@@ -206,8 +191,8 @@ typedef void (QTextStream::*QTSMFC)(QChar); // manipulator w/QChar argument
class Q_CORE_EXPORT QTextStreamManipulator
{
public:
- Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFI m, int a) noexcept : mf(m), mc(nullptr), arg(a), ch() {}
- Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFC m, QChar c) noexcept : mf(nullptr), mc(m), arg(-1), ch(c) {}
+ constexpr QTextStreamManipulator(QTSMFI m, int a) noexcept : mf(m), mc(nullptr), arg(a), ch() {}
+ constexpr QTextStreamManipulator(QTSMFC m, QChar c) noexcept : mf(nullptr), mc(m), arg(-1), ch(c) {}
void exec(QTextStream &s) { if (mf) { (s.*mf)(arg); } else { (s.*mc)(ch); } }
private:
@@ -261,43 +246,6 @@ Q_CORE_EXPORT QTextStream &ws(QTextStream &s);
} // namespace Qt
-#if QT_DEPRECATED_SINCE(5, 15)
-// This namespace only exists for 'using namespace' declarations.
-namespace QTextStreamFunctions {
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::bin") QTextStream &bin(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::oct") QTextStream &oct(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::dec") QTextStream &dec(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::hex") QTextStream &hex(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::showbase") QTextStream &showbase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::forcesign") QTextStream &forcesign(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::forcepoint") QTextStream &forcepoint(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::noshowbase") QTextStream &noshowbase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::noforcesign") QTextStream &noforcesign(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::noforcepoint") QTextStream &noforcepoint(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::uppercasebase") QTextStream &uppercasebase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::uppercasedigits") QTextStream &uppercasedigits(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::lowercasebase") QTextStream &lowercasebase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::lowercasedigits") QTextStream &lowercasedigits(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::fixed") QTextStream &fixed(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::scientific") QTextStream &scientific(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::left") QTextStream &left(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::right") QTextStream &right(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::center") QTextStream &center(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::endl") QTextStream &endl(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::flush") QTextStream &flush(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::reset") QTextStream &reset(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::bom") QTextStream &bom(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::ws") QTextStream &ws(QTextStream &s);
-} // namespace QTextStreamFunctions
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
-// We use 'using namespace' as that doesn't cause
-// conflicting definitions compiler errors.
-using namespace QTextStreamFunctions;
-QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(5, 15)
-
inline QTextStreamManipulator qSetFieldWidth(int width)
{
QTSMFI func = &QTextStream::setFieldWidth;
diff --git a/src/corelib/serialization/qtextstream_p.h b/src/corelib/serialization/qtextstream_p.h
index cee79a7ecf..909b75d0de 100644
--- a/src/corelib/serialization/qtextstream_p.h
+++ b/src/corelib/serialization/qtextstream_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTSTREAM_P_H
#define QTEXTSTREAM_P_H
@@ -53,6 +17,9 @@
//
#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qstringconverter.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qlocale.h>
#include "qtextstream.h"
QT_BEGIN_NAMESPACE
@@ -68,8 +35,13 @@ public:
inline void setupDevice(QTextStream *stream, QIODevice *device)
{
disconnect();
- if (device)
- connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
+ if (device) {
+ // Force direct connection here so that QTextStream can be used
+ // from multiple threads when the application code is handling
+ // synchronization (see also QTBUG-12055).
+ connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()),
+ Qt::DirectConnection);
+ }
this->stream = stream;
}
@@ -167,21 +139,25 @@ public:
NumberParsingStatus getNumber(qulonglong *l);
bool getReal(double *f);
- inline void write(const QString &data) { write(data.begin(), data.length()); }
+ inline void write(QStringView data) { write(data.begin(), data.size()); }
inline void write(QChar ch);
- void write(const QChar *data, int len);
- void write(QLatin1String data);
- void writePadding(int len);
- inline void putString(const QString &ch, bool number = false) { putString(ch.constData(), ch.length(), number); }
- void putString(const QChar *data, int len, bool number = false);
- void putString(QLatin1String data, bool number = false);
+ void write(const QChar *data, qsizetype len);
+ void write(QLatin1StringView data);
+ void writePadding(qsizetype len);
+ inline void putString(QStringView string, bool number = false)
+ {
+ putString(string.constData(), string.size(), number);
+ }
+ void putString(const QChar *data, qsizetype len, bool number = false);
+ void putString(QLatin1StringView data, bool number = false);
+ void putString(QUtf8StringView data, bool number = false);
inline void putChar(QChar ch);
void putNumber(qulonglong number, bool negative);
struct PaddingResult {
int left, right;
};
- PaddingResult padding(int len) const;
+ PaddingResult padding(qsizetype len) const;
// buffers
bool fillReadBuffer(qint64 maxBytes = -1);
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 21f80eec66..0fe8c87779 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "QtCore/qxmlstream.h"
-#ifndef QT_NO_XMLSTREAM
+#if QT_CONFIG(xmlstream)
#include "qxmlutils_p.h"
#include <qdebug.h>
@@ -49,31 +13,22 @@
#include <qstack.h>
#include <qbuffer.h>
#include <qscopeguard.h>
-#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
-#else
-// This specialization of Q_DECLARE_TR_FUNCTIONS is not in qcoreapplication.h,
-// because that header depends on QObject being available, which is not the
-// case for most bootstrapped applications.
-#define Q_DECLARE_TR_FUNCTIONS(context) \
-public: \
- static inline QString tr(const char *sourceText, const char *comment = nullptr) \
- { Q_UNUSED(comment); return QString::fromUtf8(sourceText); } \
- static inline QString trUtf8(const char *sourceText, const char *comment = nullptr) \
- { Q_UNUSED(comment); return QString::fromUtf8(sourceText); } \
- static inline QString tr(const char *sourceText, const char*, int) \
- { return QString::fromUtf8(sourceText); } \
- static inline QString trUtf8(const char *sourceText, const char*, int) \
- { return QString::fromUtf8(sourceText); } \
-private:
-#endif
-#include <private/qmemory_p.h>
+
+#include <private/qoffsetstringarray_p.h>
+#include <private/qtools_p.h>
#include <iterator>
+#include "qxmlstream_p.h"
+#include "qxmlstreamparser_p.h"
+#include <private/qstringconverter_p.h>
+#include <private/qstringiterator_p.h>
QT_BEGIN_NAMESPACE
-#include "qxmlstream_p.h"
+using namespace QtPrivate;
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
enum { StreamEOF = ~0U };
@@ -92,8 +47,62 @@ auto reversed(Range &r)
template <typename Range>
void reversed(const Range &&) = delete;
+
+// implementation of missing QUtf8StringView methods for ASCII-only needles:
+auto transform(QLatin1StringView haystack, char needle)
+{
+ struct R { QLatin1StringView haystack; char16_t needle; };
+ return R{haystack, uchar(needle)};
+}
+
+auto transform(QStringView haystack, char needle)
+{
+ struct R { QStringView haystack; char16_t needle; };
+ return R{haystack, uchar(needle)};
+}
+
+auto transform(QUtf8StringView haystack, char needle)
+{
+ struct R { QByteArrayView haystack; char needle; };
+ return R{haystack, needle};
+}
+
+auto transform(QLatin1StringView haystack, QLatin1StringView needle)
+{
+ struct R { QLatin1StringView haystack; QLatin1StringView needle; };
+ return R{haystack, needle};
+}
+
+auto transform(QStringView haystack, QLatin1StringView needle)
+{
+ struct R { QStringView haystack; QLatin1StringView needle; };
+ return R{haystack, needle};
+}
+
+auto transform(QUtf8StringView haystack, QLatin1StringView needle)
+{
+ struct R { QLatin1StringView haystack; QLatin1StringView needle; };
+ return R{QLatin1StringView{QByteArrayView{haystack}}, needle};
}
+#define WRAP(method, Needle) \
+ auto method (QAnyStringView s, Needle needle) noexcept \
+ { \
+ return s.visit([needle](auto s) { \
+ auto r = transform(s, needle); \
+ return r.haystack. method (r.needle); \
+ }); \
+ } \
+ /*end*/
+
+WRAP(count, char)
+WRAP(contains, char)
+WRAP(contains, QLatin1StringView)
+WRAP(endsWith, char)
+WRAP(indexOf, QLatin1StringView)
+
+} // unnamed namespace
+
/*!
\enum QXmlStreamReader::TokenType
@@ -132,7 +141,7 @@ void reversed(const Range &&) = delete;
\value DTD The reader reports a DTD in text(), notation
declarations in notationDeclarations(), and entity declarations in
entityDeclarations(). Details of the DTD declaration are reported
- in in dtdName(), dtdPublicId(), and dtdSystemId().
+ in dtdName(), dtdPublicId(), and dtdSystemId().
\value EntityReference The reader reports an entity reference that
could not be resolved. The name of the reference is reported in
@@ -177,7 +186,7 @@ void reversed(const Range &&) = delete;
addData() or by waiting for it to arrive on the device().
\value UnexpectedElementError The parser encountered an element
- that was different to those it expected.
+ or token that was different to those it expected.
*/
@@ -224,7 +233,7 @@ QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*
return QString();
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
{
@@ -280,6 +289,8 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
\ingroup xml-tools
+ \ingroup qtserialization
+
QXmlStreamReader provides a simple streaming API to parse well-formed
XML. It is an alternative to first loading the complete XML into a
DOM tree (see \l QDomDocument). QXmlStreamReader reads data either
@@ -312,13 +323,34 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
include external parsed entities. As long as no error occurs, the
- application code can thus be assured that the data provided by the
- stream reader satisfies the W3C's criteria for well-formed XML. For
- example, you can be certain that all tags are indeed nested and
- closed properly, that references to internal entities have been
- replaced with the correct replacement text, and that attributes have
- been normalized or added according to the internal subset of the
- DTD.
+ application code can thus be assured, that
+ \list
+ \li the data provided by the stream reader satisfies the W3C's
+ criteria for well-formed XML,
+ \li tokens are provided in a valid order.
+ \endlist
+
+ Unless QXmlStreamReader raises an error, it guarantees the following:
+ \list
+ \li All tags are nested and closed properly.
+ \li References to internal entities have been replaced with the
+ correct replacement text.
+ \li Attributes have been normalized or added according to the
+ internal subset of the \l DTD.
+ \li Tokens of type \l StartDocument happen before all others,
+ aside from comments and processing instructions.
+ \li At most one DOCTYPE element (a token of type \l DTD) is present.
+ \li If present, the DOCTYPE appears before all other elements,
+ aside from StartDocument, comments and processing instructions.
+ \endlist
+
+ In particular, once any token of type \l StartElement, \l EndElement,
+ \l Characters, \l EntityReference or \l EndDocument is seen, no
+ tokens of type StartDocument or DTD will be seen. If one is present in
+ the input stream, out of order, an error is raised.
+
+ \note The token types \l Comment and \l ProcessingInstruction may appear
+ anywhere in the stream.
If an error occurs while parsing, atEnd() and hasError() return
true, and error() returns the error that occurred. The functions
@@ -384,13 +416,9 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
token at the time it is reported. In addition, QXmlStreamReader
avoids the many small string allocations that it normally takes to
map an XML document to a convenient and Qt-ish API. It does this by
- reporting all string data as QStringRef rather than real QString
- objects. QStringRef is a thin wrapper around QString substrings that
- provides a subset of the QString API without the memory allocation
- and reference-counting overhead. Calling
- \l{QStringRef::toString()}{toString()} on any of those objects
- returns an equivalent real QString object.
-
+ reporting all string data as QStringView rather than real QString
+ objects. Calling \l{QStringView::toString()}{toString()} on any of
+ those objects returns an equivalent real QString object.
*/
@@ -415,41 +443,55 @@ QXmlStreamReader::QXmlStreamReader(QIODevice *device)
}
/*!
- Creates a new stream reader that reads from \a data.
+ \overload
- \sa addData(), clear(), setDevice()
- */
-QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
- : d_ptr(new QXmlStreamReaderPrivate(this))
-{
- Q_D(QXmlStreamReader);
- d->dataBuffer = data;
-}
+ \fn QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
+
+ Creates a new stream reader that reads from \a data.
+
+ \sa addData(), clear(), setDevice()
+*/
/*!
- Creates a new stream reader that reads from \a data.
+ Creates a new stream reader that reads from \a data.
- \sa addData(), clear(), setDevice()
- */
-QXmlStreamReader::QXmlStreamReader(const QString &data)
+ \note In Qt versions prior to 6.5, this constructor was overloaded
+ for QString and \c {const char*}.
+
+ \sa addData(), clear(), setDevice()
+*/
+QXmlStreamReader::QXmlStreamReader(QAnyStringView data)
: d_ptr(new QXmlStreamReaderPrivate(this))
{
Q_D(QXmlStreamReader);
- d->dataBuffer = data.toUtf8();
- d->decoder = QStringDecoder(QStringDecoder::Utf8);
- d->lockEncoding = true;
+ data.visit([d](auto data) {
+ if constexpr (std::is_same_v<decltype(data), QStringView>) {
+ d->dataBuffer = data.toUtf8();
+ d->decoder = QStringDecoder(QStringDecoder::Utf8);
+ d->lockEncoding = true;
+ } else if constexpr (std::is_same_v<decltype(data), QLatin1StringView>) {
+ // Conversion to a QString is required, to avoid breaking
+ // pre-existing (before porting to QAnyStringView) behavior.
+ d->dataBuffer = QString::fromLatin1(data).toUtf8();
+ d->decoder = QStringDecoder(QStringDecoder::Utf8);
+ d->lockEncoding = true;
+ } else {
+ d->dataBuffer = QByteArray(data.data(), data.size());
+ }
+ });
}
/*!
- Creates a new stream reader that reads from \a data.
+ \internal
- \sa addData(), clear(), setDevice()
- */
-QXmlStreamReader::QXmlStreamReader(const char *data)
+ Creates a new stream reader that reads from \a data.
+ Used by the weak constructor taking a QByteArray.
+*/
+QXmlStreamReader::QXmlStreamReader(const QByteArray &data, PrivateConstructorTag)
: d_ptr(new QXmlStreamReaderPrivate(this))
{
Q_D(QXmlStreamReader);
- d->dataBuffer = QByteArray(data);
+ d->dataBuffer = data;
}
/*!
@@ -498,47 +540,61 @@ QIODevice *QXmlStreamReader::device() const
return d->device;
}
-
/*!
- Adds more \a data for the reader to read. This function does
- nothing if the reader has a device().
+ \overload
- \sa readNext(), clear()
- */
-void QXmlStreamReader::addData(const QByteArray &data)
-{
- Q_D(QXmlStreamReader);
- if (d->device) {
- qWarning("QXmlStreamReader: addData() with device()");
- return;
- }
- d->dataBuffer += data;
-}
+ \fn void QXmlStreamReader::addData(const QByteArray &data)
+
+ Adds more \a data for the reader to read. This function does
+ nothing if the reader has a device().
+
+ \sa readNext(), clear()
+*/
/*!
- Adds more \a data for the reader to read. This function does
- nothing if the reader has a device().
+ Adds more \a data for the reader to read. This function does
+ nothing if the reader has a device().
- \sa readNext(), clear()
- */
-void QXmlStreamReader::addData(const QString &data)
+ \note In Qt versions prior to 6.5, this function was overloaded
+ for QString and \c {const char*}.
+
+ \sa readNext(), clear()
+*/
+void QXmlStreamReader::addData(QAnyStringView data)
{
Q_D(QXmlStreamReader);
- d->lockEncoding = true;
- if (!d->decoder.isValid())
- d->decoder = QStringDecoder(QStringDecoder::Utf8);
- addData(data.toUtf8());
+ data.visit([this, d](auto data) {
+ if constexpr (std::is_same_v<decltype(data), QStringView>) {
+ d->lockEncoding = true;
+ if (!d->decoder.isValid())
+ d->decoder = QStringDecoder(QStringDecoder::Utf8);
+ addDataImpl(data.toUtf8());
+ } else if constexpr (std::is_same_v<decltype(data), QLatin1StringView>) {
+ // Conversion to a QString is required, to avoid breaking
+ // pre-existing (before porting to QAnyStringView) behavior.
+ if (!d->decoder.isValid())
+ d->decoder = QStringDecoder(QStringDecoder::Utf8);
+ addDataImpl(QString::fromLatin1(data).toUtf8());
+ } else {
+ addDataImpl(QByteArray(data.data(), data.size()));
+ }
+ });
}
/*!
- Adds more \a data for the reader to read. This function does
- nothing if the reader has a device().
+ \internal
- \sa readNext(), clear()
- */
-void QXmlStreamReader::addData(const char *data)
+ Adds more \a data for the reader to read. This function does
+ nothing if the reader has a device().
+*/
+void QXmlStreamReader::addDataImpl(const QByteArray &data)
{
- addData(QByteArray(data));
+ Q_D(QXmlStreamReader);
+ if (d->device) {
+ qWarning("QXmlStreamReader: addData() with device()");
+ return;
+ }
+ d->dataBuffer += data;
}
/*!
@@ -625,6 +681,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::readNext()
d->token = -1;
return readNext();
}
+ d->checkToken();
return d->type;
}
@@ -665,7 +722,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
bool QXmlStreamReader::readNextStartElement()
{
while (readNext() != Invalid) {
- if (isEndElement())
+ if (isEndElement() || isEndDocument())
return false;
else if (isStartElement())
return true;
@@ -695,59 +752,28 @@ void QXmlStreamReader::skipCurrentElement()
}
}
-/*
- * Use the following Perl script to generate the error string index list:
-===== PERL SCRIPT ====
-print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
-$counter = 0;
-$i = 0;
-while (<STDIN>) {
- chomp;
- print " \"$_\\0\"\n";
- $sizes[$i++] = $counter;
- $counter += length 1 + $_;
-}
-print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n ";
-for ($j = 0; $j < $i; ++$j) {
- printf "$sizes[$j], ";
-}
-print "0\n};\n";
-===== PERL SCRIPT ====
-
- * The input data is as follows (copied from qxmlstream.h):
-NoToken
-Invalid
-StartDocument
-EndDocument
-StartElement
-EndElement
-Characters
-Comment
-DTD
-EntityReference
-ProcessingInstruction
-*/
-static const char QXmlStreamReader_tokenTypeString_string[] =
- "NoToken\0"
- "Invalid\0"
- "StartDocument\0"
- "EndDocument\0"
- "StartElement\0"
- "EndElement\0"
- "Characters\0"
- "Comment\0"
- "DTD\0"
- "EntityReference\0"
- "ProcessingInstruction\0";
-
-static const short QXmlStreamReader_tokenTypeString_indices[] = {
- 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
-};
+static constexpr auto QXmlStreamReader_tokenTypeString = qOffsetStringArray(
+ "NoToken",
+ "Invalid",
+ "StartDocument",
+ "EndDocument",
+ "StartElement",
+ "EndElement",
+ "Characters",
+ "Comment",
+ "DTD",
+ "EntityReference",
+ "ProcessingInstruction"
+);
+static constexpr auto QXmlStreamReader_XmlContextString = qOffsetStringArray(
+ "Prolog",
+ "Body"
+);
/*!
\property QXmlStreamReader::namespaceProcessing
- The namespace-processing flag of the stream reader
+ \brief the namespace-processing flag of the stream reader.
This property controls whether or not the stream reader processes
namespaces. If enabled, the reader processes namespaces, otherwise
@@ -776,11 +802,19 @@ bool QXmlStreamReader::namespaceProcessing() const
QString QXmlStreamReader::tokenString() const
{
Q_D(const QXmlStreamReader);
- return QLatin1String(QXmlStreamReader_tokenTypeString_string +
- QXmlStreamReader_tokenTypeString_indices[d->type]);
+ return QLatin1StringView(QXmlStreamReader_tokenTypeString.at(d->type));
+}
+
+/*!
+ \internal
+ \return \param ctxt (Prolog/Body) as a string.
+ */
+static constexpr QLatin1StringView contextString(QXmlStreamReaderPrivate::XmlContext ctxt)
+{
+ return QLatin1StringView(QXmlStreamReader_XmlContextString.at(static_cast<int>(ctxt)));
}
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
{
@@ -791,9 +825,10 @@ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
namespaceDeclaration.prefix = addToStringStorage(u"xml");
namespaceDeclaration.namespaceUri = addToStringStorage(u"http://www.w3.org/XML/1998/namespace");
initialTagStackStringStorageSize = tagStackStringStorageSize;
+ tagsDone = false;
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
:q_ptr(q)
@@ -808,7 +843,7 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
init();
#define ADD_PREDEFINED(n, v) \
do { \
- Entity e = Entity::createLiteral(QLatin1String(n), QLatin1String(v)); \
+ Entity e = Entity::createLiteral(n##_L1, v##_L1); \
entityHash.insert(qToStringViewIgnoringNull(e.name), std::move(e)); \
} while (false)
ADD_PREDEFINED("lt", "<");
@@ -822,12 +857,14 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
void QXmlStreamReaderPrivate::init()
{
scanDtd = false;
+ lastAttributeIsCData = false;
token = -1;
token_char = 0;
isEmptyElement = false;
isWhitespace = true;
isCDATA = false;
standalone = false;
+ hasStandalone = false;
tos = 0;
resumeReduction = 0;
state_stack[tos++] = 0;
@@ -864,6 +901,8 @@ void QXmlStreamReaderPrivate::init()
type = QXmlStreamReader::NoToken;
error = QXmlStreamReader::NoError;
+ currentContext = XmlContext::Prolog;
+ foundDTD = false;
}
/*
@@ -879,7 +918,7 @@ void QXmlStreamReaderPrivate::parseEntity(const QString &value)
if (!entityParser)
- entityParser = qt_make_unique<QXmlStreamReaderPrivate>(q);
+ entityParser = std::make_unique<QXmlStreamReaderPrivate>(q);
else
entityParser->init();
entityParser->inParseEntity = true;
@@ -974,8 +1013,8 @@ inline uint QXmlStreamReaderPrivate::peekChar()
*/
bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
{
- int pos = textBuffer.size();
- int oldLineNumber = lineNumber;
+ const qsizetype pos = textBuffer.size();
+ const auto oldLineNumber = lineNumber;
uint c;
while ((c = getChar()) != StreamEOF) {
@@ -1022,7 +1061,7 @@ bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
{
- int n = 0;
+ qsizetype n = 0;
while (str[n]) {
uint c = getChar();
if (c != ushort(str[n])) {
@@ -1035,12 +1074,11 @@ bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, b
}
++n;
}
- for (int i = 0; i < n; ++i)
- textBuffer += QChar(ushort(str[i]));
+ textBuffer += QLatin1StringView(str, n);
if (requireSpace) {
- int s = fastScanSpace();
+ const qsizetype s = fastScanSpace();
if (!s || atEnd) {
- int pos = textBuffer.size() - n - s;
+ qsizetype pos = textBuffer.size() - n - s;
putString(textBuffer, pos);
textBuffer.resize(pos);
return false;
@@ -1150,9 +1188,9 @@ bool QXmlStreamReaderPrivate::scanAttType()
encountered.
*/
-inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
+inline qsizetype QXmlStreamReaderPrivate::fastScanLiteralContent()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
switch (ushort(c)) {
@@ -1174,7 +1212,7 @@ inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
case ' ':
case '\t':
if (normalizeLiterals)
- textBuffer += QLatin1Char(' ');
+ textBuffer += u' ';
else
textBuffer += QChar(c);
++n;
@@ -1193,16 +1231,16 @@ inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
putChar(c);
return n;
}
- textBuffer += QChar(c);
+ textBuffer += QChar(ushort(c));
++n;
}
}
return n;
}
-inline int QXmlStreamReaderPrivate::fastScanSpace()
+inline qsizetype QXmlStreamReaderPrivate::fastScanSpace()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
switch (c) {
@@ -1233,9 +1271,9 @@ inline int QXmlStreamReaderPrivate::fastScanSpace()
Used for text nodes essentially. That is, characters appearing
inside elements.
*/
-inline int QXmlStreamReaderPrivate::fastScanContentCharList()
+inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
switch (ushort(c)) {
@@ -1246,7 +1284,7 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
return n;
case ']': {
isWhitespace = false;
- int pos = textBuffer.size();
+ const qsizetype pos = textBuffer.size();
textBuffer += QChar(ushort(c));
++n;
while ((c = getChar()) == ']') {
@@ -1256,7 +1294,7 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
if (c == 0) {
putString(textBuffer, pos);
textBuffer.resize(pos);
- } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
+ } else if (c == '>' && textBuffer.at(textBuffer.size() - 2) == u']') {
raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
} else {
putChar(c);
@@ -1297,11 +1335,18 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
return n;
}
-inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+// Fast scan an XML attribute name (e.g. "xml:lang").
+inline std::optional<qsizetype> QXmlStreamReaderPrivate::fastScanName(Value *val)
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
+ if (n >= 4096) {
+ // This is too long to be a sensible name, and
+ // can exhaust memory, or the range of decltype(*prefix)
+ raiseNamePrefixTooLongError();
+ return std::nullopt;
+ }
switch (c) {
case '\n':
case ' ':
@@ -1329,16 +1374,16 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
case '+':
case '*':
putChar(c);
- if (prefix && *prefix == n+1) {
- *prefix = 0;
+ if (val && val->prefix == n + 1) {
+ val->prefix = 0;
putChar(':');
--n;
}
return n;
case ':':
- if (prefix) {
- if (*prefix == 0) {
- *prefix = n+2;
+ if (val) {
+ if (val->prefix == 0) {
+ val->prefix = qint16(n + 2);
} else { // only one colon allowed according to the namespace spec.
putChar(c);
return n;
@@ -1349,14 +1394,14 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
}
Q_FALLTHROUGH();
default:
- textBuffer += QChar(c);
+ textBuffer += QChar(ushort(c));
++n;
}
}
- if (prefix)
- *prefix = 0;
- int pos = textBuffer.size() - n;
+ if (val)
+ val->prefix = 0;
+ qsizetype pos = textBuffer.size() - n;
putString(textBuffer, pos);
textBuffer.resize(pos);
return 0;
@@ -1413,9 +1458,9 @@ static inline NameChar fastDetermineNameChar(QChar ch)
return NotName;
}
-inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
+inline qsizetype QXmlStreamReaderPrivate::fastScanNMTOKEN()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
if (fastDetermineNameChar(QChar(c)) == NotName) {
@@ -1427,7 +1472,7 @@ inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
}
}
- int pos = textBuffer.size() - n;
+ qsizetype pos = textBuffer.size() - n;
putString(textBuffer, pos);
textBuffer.resize(pos);
@@ -1479,10 +1524,11 @@ void QXmlStreamReaderPrivate::putReplacementInAttributeValue(QStringView s)
uint QXmlStreamReaderPrivate::getChar_helper()
{
- const int BUFFER_SIZE = 8192;
+ constexpr qsizetype BUFFER_SIZE = 8192;
characterOffset += readBufferPos;
readBufferPos = 0;
- readBuffer.resize(0);
+ if (readBuffer.size())
+ readBuffer.resize(0);
if (decoder.isValid())
nbytesread = 0;
if (device) {
@@ -1508,14 +1554,14 @@ uint QXmlStreamReaderPrivate::getChar_helper()
atEnd = true;
return StreamEOF;
}
- auto encoding = QStringDecoder::encodingForData(rawReadBuffer.constData(), rawReadBuffer.size(), char16_t('<'));
+ auto encoding = QStringDecoder::encodingForData(rawReadBuffer, char16_t('<'));
if (!encoding)
// assume utf-8
encoding = QStringDecoder::Utf8;
decoder = QStringDecoder(*encoding);
}
- readBuffer = decoder(rawReadBuffer.constData(), nbytesread);
+ readBuffer = decoder(QByteArrayView(rawReadBuffer).first(nbytesread));
if (lockEncoding && decoder.hasError()) {
raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
@@ -1534,7 +1580,7 @@ uint QXmlStreamReaderPrivate::getChar_helper()
return StreamEOF;
}
-QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
+XmlStringRef QXmlStreamReaderPrivate::namespaceForPrefix(QStringView prefix)
{
for (const NamespaceDeclaration &namespaceDeclaration : reversed(namespaceDeclarations)) {
if (namespaceDeclaration.prefix == prefix) {
@@ -1547,7 +1593,7 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix));
#endif
- return QStringRef();
+ return XmlStringRef();
}
/*
@@ -1570,25 +1616,25 @@ void QXmlStreamReaderPrivate::resolveTag()
++i;
if (i != n)
continue;
- if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
+ if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == "xmlns"_L1) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
namespaceDeclaration.prefix.clear();
- const QStringRef ns(dtdAttribute.defaultValue);
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+ const XmlStringRef ns(dtdAttribute.defaultValue);
+ if (ns == "http://www.w3.org/2000/xmlns/"_L1 ||
+ ns == "http://www.w3.org/XML/1998/namespace"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
else
namespaceDeclaration.namespaceUri = ns;
- } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
+ } else if (dtdAttribute.attributePrefix == "xmlns"_L1) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = dtdAttribute.attributeName;
- QStringRef namespaceUri = dtdAttribute.defaultValue;
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
+ XmlStringRef namespacePrefix = dtdAttribute.attributeName;
+ XmlStringRef namespaceUri = dtdAttribute.defaultValue;
+ if (((namespacePrefix == "xml"_L1)
+ ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
+ || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
|| namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
+ || namespacePrefix == "xmlns"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
namespaceDeclaration.prefix = namespacePrefix;
@@ -1604,18 +1650,18 @@ void QXmlStreamReaderPrivate::resolveTag()
for (qsizetype i = 0; i < n; ++i) {
QXmlStreamAttribute &attribute = attributes[i];
Attribute &attrib = attributeStack[i];
- QStringRef prefix(symPrefix(attrib.key));
- QStringRef name(symString(attrib.key));
- QStringRef qualifiedName(symName(attrib.key));
- QStringRef value(symString(attrib.value));
+ XmlStringRef prefix(symPrefix(attrib.key));
+ XmlStringRef name(symString(attrib.key));
+ XmlStringRef qualifiedName(symName(attrib.key));
+ XmlStringRef value(symString(attrib.value));
- attribute.m_name = QXmlStreamStringRef(name);
- attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
- attribute.m_value = QXmlStreamStringRef(value);
+ attribute.m_name = name;
+ attribute.m_qualifiedName = qualifiedName;
+ attribute.m_value = value;
if (!prefix.isEmpty()) {
- QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
- attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+ XmlStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
+ attribute.m_namespaceUri = XmlStringRef(attributeNamespaceUri);
}
for (qsizetype j = 0; j < i; ++j) {
@@ -1644,13 +1690,13 @@ void QXmlStreamReaderPrivate::resolveTag()
QXmlStreamAttribute attribute;
- attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
- attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
- attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
+ attribute.m_name = dtdAttribute.attributeName;
+ attribute.m_qualifiedName = dtdAttribute.attributeQualifiedName;
+ attribute.m_value = dtdAttribute.defaultValue;
if (!dtdAttribute.attributePrefix.isEmpty()) {
- QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
- attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+ XmlStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
+ attribute.m_namespaceUri = XmlStringRef(attributeNamespaceUri);
}
attribute.m_isDefault = true;
attributes.append(std::move(attribute));
@@ -1665,8 +1711,8 @@ void QXmlStreamReaderPrivate::resolvePublicNamespaces()
for (qsizetype i = 0; i < n; ++i) {
const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
- publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
- publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri);
+ publicNamespaceDeclaration.m_prefix = namespaceDeclaration.prefix;
+ publicNamespaceDeclaration.m_namespaceUri = namespaceDeclaration.namespaceUri;
}
}
@@ -1676,9 +1722,9 @@ void QXmlStreamReaderPrivate::resolveDtd()
for (qsizetype i = 0; i < notationDeclarations.size(); ++i) {
const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
- publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
- publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId);
- publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId);
+ publicNotationDeclaration.m_name = notationDeclaration.name;
+ publicNotationDeclaration.m_systemId = notationDeclaration.systemId;
+ publicNotationDeclaration.m_publicId = notationDeclaration.publicId;
}
notationDeclarations.clear();
@@ -1686,11 +1732,11 @@ void QXmlStreamReaderPrivate::resolveDtd()
for (qsizetype i = 0; i < entityDeclarations.size(); ++i) {
const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
- publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
- publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName);
- publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId);
- publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId);
- publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value);
+ publicEntityDeclaration.m_name = entityDeclaration.name;
+ publicEntityDeclaration.m_notationName = entityDeclaration.notationName;
+ publicEntityDeclaration.m_systemId = entityDeclaration.systemId;
+ publicEntityDeclaration.m_publicId = entityDeclaration.publicId;
+ publicEntityDeclaration.m_value = entityDeclaration.value;
}
entityDeclarations.clear();
parameterEntityHash.clear();
@@ -1700,11 +1746,11 @@ uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
{
bool ok = true;
uint s;
- // ### add toXShort to QStringRef?
+ // ### add toXShort to XmlString?
if (sym(symbolIndex).c == 'x')
- s = symString(symbolIndex, 1).toUInt(&ok, 16);
+ s = symString(symbolIndex, 1).view().toUInt(&ok, 16);
else
- s = symString(symbolIndex).toUInt(&ok, 10);
+ s = symString(symbolIndex).view().toUInt(&ok, 10);
ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
|| (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= QChar::LastValidCodePoint));
@@ -1713,13 +1759,13 @@ uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
}
-void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
+void QXmlStreamReaderPrivate::checkPublicLiteral(QStringView publicId)
{
//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
- const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
+ const char16_t *data = publicId.utf16();
uchar c = 0;
- int i;
+ qsizetype i;
for (i = publicId.size() - 1; i >= 0; --i) {
if (data[i] < 256)
switch ((c = data[i])) {
@@ -1729,9 +1775,7 @@ void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
case '$': case '_': case '%': case '\'': case '\"':
continue;
default:
- if ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9'))
+ if (isAsciiLetterOrNumber(c))
continue;
}
break;
@@ -1763,8 +1807,8 @@ bool QXmlStreamReaderPrivate::checkStartDocument()
void QXmlStreamReaderPrivate::startDocument()
{
QString err;
- if (documentVersion != QLatin1String("1.0")) {
- if (documentVersion.contains(QLatin1Char(' ')))
+ if (documentVersion != "1.0"_L1) {
+ if (documentVersion.view().contains(u' '))
err = QXmlStream::tr("Invalid XML version string.");
else
err = QXmlStream::tr("Unsupported XML version.");
@@ -1775,18 +1819,17 @@ void QXmlStreamReaderPrivate::startDocument()
* proper order:
*
* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
- bool hasStandalone = false;
for (qsizetype i = 0; err.isNull() && i < n; ++i) {
Attribute &attrib = attributeStack[i];
- QStringRef prefix(symPrefix(attrib.key));
- QStringRef key(symString(attrib.key));
- QStringRef value(symString(attrib.value));
+ XmlStringRef prefix(symPrefix(attrib.key));
+ XmlStringRef key(symString(attrib.key));
+ XmlStringRef value(symString(attrib.value));
- if (prefix.isEmpty() && key == QLatin1String("encoding")) {
+ if (prefix.isEmpty() && key == "encoding"_L1) {
documentEncoding = value;
- if(hasStandalone)
+ if (hasStandalone)
err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
if (!QXmlUtils::isEncName(value))
err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value);
@@ -1797,20 +1840,20 @@ void QXmlStreamReaderPrivate::startDocument()
if (!decoder.isValid()) {
err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
} else {
- readBuffer = decoder(rawReadBuffer.data(), nbytesread);
+ readBuffer = decoder(QByteArrayView(rawReadBuffer).first(nbytesread));
}
}
}
- } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
+ } else if (prefix.isEmpty() && key == "standalone"_L1) {
hasStandalone = true;
- if (value == QLatin1String("yes"))
+ if (value == "yes"_L1)
standalone = true;
- else if (value == QLatin1String("no"))
+ else if (value == "no"_L1)
standalone = false;
else
err = QXmlStream::tr("Standalone accepts only yes or no.");
} else {
- err = QXmlStream::tr("Invalid attribute in XML declaration.");
+ err = QXmlStream::tr("Invalid attribute in XML declaration: %1 = %2").arg(key).arg(value);
}
}
@@ -1839,6 +1882,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
raiseError(QXmlStreamReader::NotWellFormedError, message);
}
+void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
+{
+ // TODO: add a ImplementationLimitsExceededError and use it instead
+ raiseError(QXmlStreamReader::NotWellFormedError,
+ QXmlStream::tr("Length of XML attribute name exceeds implementation limits (4KiB "
+ "characters)."));
+}
+
void QXmlStreamReaderPrivate::parseError()
{
@@ -1851,7 +1902,7 @@ void QXmlStreamReaderPrivate::parseError()
int ers = state_stack[tos];
int nexpected = 0;
int expected[nmax];
- if (token != ERROR)
+ if (token != XML_ERROR)
for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
int k = t_action(ers, tk);
if (k <= 0)
@@ -1864,22 +1915,27 @@ void QXmlStreamReaderPrivate::parseError()
if (nexpected && nexpected < nmax) {
//: '<first option>'
- QString exp_str = QXmlStream::tr("'%1'", "expected").arg(QLatin1String(spell[expected[0]]));
+ QString exp_str = QXmlStream::tr("'%1'", "expected")
+ .arg(QLatin1StringView(spell[expected[0]]));
if (nexpected == 2) {
//: <first option>, '<second option>'
- exp_str = QXmlStream::tr("%1 or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[1]]));
+ exp_str = QXmlStream::tr("%1 or '%2'", "expected")
+ .arg(exp_str, QLatin1StringView(spell[expected[1]]));
} else if (nexpected > 2) {
int s = 1;
for (; s < nexpected - 1; ++s) {
//: <options so far>, '<next option>'
- exp_str = QXmlStream::tr("%1, '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
+ exp_str = QXmlStream::tr("%1, '%2'", "expected")
+ .arg(exp_str, QLatin1StringView(spell[expected[s]]));
}
//: <options so far>, or '<final option>'
- exp_str = QXmlStream::tr("%1, or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
+ exp_str = QXmlStream::tr("%1, or '%2'", "expected")
+ .arg(exp_str, QLatin1StringView(spell[expected[s]]));
}
- error_message = QXmlStream::tr("Expected %1, but got '%2'.").arg(exp_str, QLatin1String(spell[token]));
+ error_message = QXmlStream::tr("Expected %1, but got '%2'.")
+ .arg(exp_str, QLatin1StringView(spell[token]));
} else {
- error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1String(spell[token]));
+ error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1StringView(spell[token]));
}
raiseWellFormedError(error_message);
@@ -1925,7 +1981,7 @@ qint64 QXmlStreamReader::characterOffset() const
/*! Returns the text of \l Characters, \l Comment, \l DTD, or
EntityReference.
*/
-QStringRef QXmlStreamReader::text() const
+QStringView QXmlStreamReader::text() const
{
Q_D(const QXmlStreamReader);
return d->text;
@@ -1968,12 +2024,12 @@ QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
name. Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::dtdName() const
+QStringView QXmlStreamReader::dtdName() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::DTD)
return d->dtdName;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -1983,12 +2039,12 @@ QStringRef QXmlStreamReader::dtdName() const
public identifier. Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::dtdPublicId() const
+QStringView QXmlStreamReader::dtdPublicId() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::DTD)
return d->dtdPublicId;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -1998,12 +2054,12 @@ QStringRef QXmlStreamReader::dtdPublicId() const
system identifier. Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::dtdSystemId() const
+QStringView QXmlStreamReader::dtdSystemId() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::DTD)
return d->dtdSystemId;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -2118,7 +2174,7 @@ QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
switch (readNext()) {
case Characters:
case EntityReference:
- result.insert(result.size(), d->text.unicode(), d->text.size());
+ result.insert(result.size(), d->text);
break;
case EndElement:
return result;
@@ -2184,7 +2240,7 @@ QXmlStreamReader::Error QXmlStreamReader::error() const
/*!
Returns the target of a ProcessingInstruction.
*/
-QStringRef QXmlStreamReader::processingInstructionTarget() const
+QStringView QXmlStreamReader::processingInstructionTarget() const
{
Q_D(const QXmlStreamReader);
return d->processingInstructionTarget;
@@ -2193,7 +2249,7 @@ QStringRef QXmlStreamReader::processingInstructionTarget() const
/*!
Returns the data of a ProcessingInstruction.
*/
-QStringRef QXmlStreamReader::processingInstructionData() const
+QStringView QXmlStreamReader::processingInstructionData() const
{
Q_D(const QXmlStreamReader);
return d->processingInstructionData;
@@ -2206,7 +2262,7 @@ QStringRef QXmlStreamReader::processingInstructionData() const
\sa namespaceUri(), qualifiedName()
*/
-QStringRef QXmlStreamReader::name() const
+QStringView QXmlStreamReader::name() const
{
Q_D(const QXmlStreamReader);
return d->name;
@@ -2217,7 +2273,7 @@ QStringRef QXmlStreamReader::name() const
\sa name(), qualifiedName()
*/
-QStringRef QXmlStreamReader::namespaceUri() const
+QStringView QXmlStreamReader::namespaceUri() const
{
Q_D(const QXmlStreamReader);
return d->namespaceUri;
@@ -2235,7 +2291,7 @@ QStringRef QXmlStreamReader::namespaceUri() const
\sa name(), prefix(), namespaceUri()
*/
-QStringRef QXmlStreamReader::qualifiedName() const
+QStringView QXmlStreamReader::qualifiedName() const
{
Q_D(const QXmlStreamReader);
return d->qualifiedName;
@@ -2250,7 +2306,7 @@ QStringRef QXmlStreamReader::qualifiedName() const
\sa name(), qualifiedName()
*/
-QStringRef QXmlStreamReader::prefix() const
+QStringView QXmlStreamReader::prefix() const
{
Q_D(const QXmlStreamReader);
return d->prefix;
@@ -2265,7 +2321,7 @@ QXmlStreamAttributes QXmlStreamReader::attributes() const
return d->attributes;
}
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
/*!
\class QXmlStreamAttribute
@@ -2276,6 +2332,8 @@ QXmlStreamAttributes QXmlStreamReader::attributes() const
\ingroup xml-tools
+ \compares equality
+
An attribute consists of an optionally empty namespaceUri(), a
name(), a value(), and an isDefault() attribute.
@@ -2290,24 +2348,15 @@ QXmlStreamAttribute::QXmlStreamAttribute()
m_isDefault = false;
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Destructs an attribute.
- */
-QXmlStreamAttribute::~QXmlStreamAttribute()
-{
-}
-#endif
-
/*! Constructs an attribute in the namespace described with \a
namespaceUri with \a name and value \a value.
*/
QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value)
{
- m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
- m_name = m_qualifiedName = QXmlStreamStringRef(QStringRef(&name));
- m_value = QXmlStreamStringRef(QStringRef(&value));
- m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
+ m_namespaceUri = namespaceUri;
+ m_name = m_qualifiedName = name;
+ m_value = value;
+ m_namespaceUri = namespaceUri;
}
/*!
@@ -2315,23 +2364,21 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QStr
*/
QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QString &value)
{
- int colon = qualifiedName.indexOf(QLatin1Char(':'));
- m_name = QXmlStreamStringRef(QStringRef(&qualifiedName,
- colon + 1,
- qualifiedName.size() - (colon + 1)));
- m_qualifiedName = QXmlStreamStringRef(QStringRef(&qualifiedName));
- m_value = QXmlStreamStringRef(QStringRef(&value));
+ qsizetype colon = qualifiedName.indexOf(u':');
+ m_name = qualifiedName.mid(colon + 1);
+ m_qualifiedName = qualifiedName;
+ m_value = value;
}
-/*! \fn QStringRef QXmlStreamAttribute::namespaceUri() const
+/*! \fn QStringView QXmlStreamAttribute::namespaceUri() const
Returns the attribute's resolved namespaceUri, or an empty string
reference if the attribute does not have a defined namespace.
*/
-/*! \fn QStringRef QXmlStreamAttribute::name() const
+/*! \fn QStringView QXmlStreamAttribute::name() const
Returns the attribute's local name.
*/
-/*! \fn QStringRef QXmlStreamAttribute::qualifiedName() const
+/*! \fn QStringView QXmlStreamAttribute::qualifiedName() const
Returns the attribute's qualified name.
A qualified name is the raw name of an attribute in the XML
@@ -2343,7 +2390,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
the attribute's local name().
*/
/*!
- \fn QStringRef QXmlStreamAttribute::prefix() const
+ \fn QStringView QXmlStreamAttribute::prefix() const
\since 4.4
Returns the attribute's namespace prefix.
@@ -2351,7 +2398,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
*/
-/*! \fn QStringRef QXmlStreamAttribute::value() const
+/*! \fn QStringView QXmlStreamAttribute::value() const
Returns the attribute's value.
*/
@@ -2361,41 +2408,17 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
value following an ATTLIST declaration in the DTD; otherwise
returns \c false.
*/
-/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
+/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &lhs, const QXmlStreamAttribute &rhs)
- Compares this attribute with \a other and returns \c true if they are
+ Compares \a lhs attribute with \a rhs and returns \c true if they are
equal; otherwise returns \c false.
*/
-/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
+/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &lhs, const QXmlStreamAttribute &rhs)
- Compares this attribute with \a other and returns \c true if they are
+ Compares \a lhs attribute with \a rhs and returns \c true if they are
not equal; otherwise returns \c false.
*/
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamAttribute::QXmlStreamAttribute(const QXmlStreamAttribute &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this attribute.
- */
-QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &other)
-{
- m_name = other.m_name;
- m_namespaceUri = other.m_namespaceUri;
- m_qualifiedName = other.m_qualifiedName;
- m_value = other.m_value;
- m_isDefault = other.m_isDefault;
- return *this;
-}
-#endif
-
/*!
\class QXmlStreamAttributes
\inmodule QtCore
@@ -2441,6 +2464,8 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o
\ingroup xml-tools
+ \compares equality
+
An notation declaration consists of a name(), a systemId(), and a publicId().
*/
@@ -2451,55 +2476,27 @@ QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
{
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this notation declaration.
- */
-QXmlStreamNotationDeclaration& QXmlStreamNotationDeclaration::operator=(const QXmlStreamNotationDeclaration &other)
-{
- m_name = other.m_name;
- m_systemId = other.m_systemId;
- m_publicId = other.m_publicId;
- return *this;
-}
-
-/*!
-Destructs this notation declaration.
-*/
-QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
-{
-}
-#endif
-
-/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
+/*! \fn QStringView QXmlStreamNotationDeclaration::name() const
Returns the notation name.
*/
-/*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
+/*! \fn QStringView QXmlStreamNotationDeclaration::systemId() const
Returns the system identifier.
*/
-/*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
+/*! \fn QStringView QXmlStreamNotationDeclaration::publicId() const
Returns the public identifier.
*/
-/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &lhs, const QXmlStreamNotationDeclaration &rhs)
- Compares this notation declaration with \a other and returns \c true
+ Compares \a lhs notation declaration with \a rhs and returns \c true
if they are equal; otherwise returns \c false.
*/
-/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &lhs, const QXmlStreamNotationDeclaration &rhs)
- Compares this notation declaration with \a other and returns \c true
+ Compares \a lhs notation declaration with \a rhs and returns \c true
if they are not equal; otherwise returns \c false.
*/
@@ -2519,16 +2516,18 @@ Returns the public identifier.
\ingroup xml-tools
+ \compares equality
+
An namespace declaration consists of a prefix() and a namespaceUri().
*/
-/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &lhs, const QXmlStreamNamespaceDeclaration &rhs)
- Compares this namespace declaration with \a other and returns \c true
+ Compares \a lhs namespace declaration with \a rhs and returns \c true
if they are equal; otherwise returns \c false.
*/
-/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &lhs, const QXmlStreamNamespaceDeclaration &rhs)
- Compares this namespace declaration with \a other and returns \c true
+ Compares \a lhs namespace declaration with \a rhs and returns \c true
if they are not equal; otherwise returns \c false.
*/
@@ -2550,37 +2549,11 @@ QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &pr
m_namespaceUri = namespaceUri;
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this namespace declaration.
- */
-QXmlStreamNamespaceDeclaration& QXmlStreamNamespaceDeclaration::operator=(const QXmlStreamNamespaceDeclaration &other)
-{
- m_prefix = other.m_prefix;
- m_namespaceUri = other.m_namespaceUri;
- return *this;
-}
-/*!
-Destructs this namespace declaration.
-*/
-QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
-{
-}
-#endif
-
-/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
+/*! \fn QStringView QXmlStreamNamespaceDeclaration::prefix() const
Returns the prefix.
*/
-/*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
+/*! \fn QStringView QXmlStreamNamespaceDeclaration::namespaceUri() const
Returns the namespaceUri.
*/
@@ -2596,9 +2569,9 @@ Returns the namespaceUri.
*/
/*!
- \class QXmlStreamStringRef
+ \class QXmlString
\inmodule QtCore
- \since 4.3
+ \since 6.0
\internal
*/
@@ -2611,6 +2584,7 @@ Returns the namespaceUri.
\ingroup xml-tools
+ \compares equality
An entity declaration consists of a name(), a notationName(), a
systemId(), a publicId(), and a value().
*/
@@ -2622,114 +2596,52 @@ QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
{
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this entity declaration.
- */
-QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlStreamEntityDeclaration &other)
-{
- m_name = other.m_name;
- m_notationName = other.m_notationName;
- m_systemId = other.m_systemId;
- m_publicId = other.m_publicId;
- m_value = other.m_value;
- return *this;
-}
-
-/*!
- Destructs this entity declaration.
-*/
-QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
-{
-}
-#endif
-
-/*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other)
- \since 5.6
-
- Swaps this string reference's contents with \a other.
- This function is very fast and never fails.
-*/
-
-/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::name() const
Returns the entity name.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::notationName() const
Returns the notation name.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::systemId() const
Returns the system identifier.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::publicId() const
Returns the public identifier.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::value() const
Returns the entity's value.
*/
-/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
+/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &lhs, const QXmlStreamEntityDeclaration &rhs)
- Compares this entity declaration with \a other and returns \c true if
+ Compares \a lhs entity declaration with \a rhs and returns \c true if
they are equal; otherwise returns \c false.
*/
-/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
+/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &lhs, const QXmlStreamEntityDeclaration &rhs)
- Compares this entity declaration with \a other and returns \c true if
+ Compares \a lhs entity declaration with \a rhs and returns \c true if
they are not equal; otherwise returns \c false.
*/
/*! Returns the value of the attribute \a name in the namespace
described with \a namespaceUri, or an empty string reference if the
attribute is not defined. The \a namespaceUri can be empty.
- */
-QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
-{
- for (const QXmlStreamAttribute &attribute : *this) {
- if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
- return attribute.value();
- }
- return QStringRef();
-}
-
-/*!\overload
- Returns the value of the attribute \a name in the namespace
- described with \a namespaceUri, or an empty string reference if the
- attribute is not defined. The \a namespaceUri can be empty.
- */
-QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, QLatin1String name) const
-{
- for (const QXmlStreamAttribute &attribute : *this) {
- if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
- return attribute.value();
- }
- return QStringRef();
-}
-/*!\overload
- Returns the value of the attribute \a name in the namespace
- described with \a namespaceUri, or an empty string reference if the
- attribute is not defined. The \a namespaceUri can be empty.
+ \note In Qt versions prior to 6.6, this function was implemented as an
+ overload set accepting combinations of QString and QLatin1StringView only.
*/
-QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String name) const
+QStringView QXmlStreamAttributes::value(QAnyStringView namespaceUri, QAnyStringView name) const noexcept
{
for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
return attribute.value();
}
- return QStringRef();
+ return QStringView();
}
/*!\overload
@@ -2743,35 +2655,18 @@ QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String
different prefixes can point to the same namespace), you shouldn't
use qualified names, but a resolved namespaceUri and the attribute's
local name.
- */
-QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
-{
- for (const QXmlStreamAttribute &attribute : *this) {
- if (attribute.qualifiedName() == qualifiedName)
- return attribute.value();
- }
- return QStringRef();
-}
-/*!\overload
+ \note In Qt versions prior to 6.6, this function was implemented as an
+ overload set accepting QString and QLatin1StringView only.
- Returns the value of the attribute with qualified name \a
- qualifiedName , or an empty string reference if the attribute is not
- defined. A qualified name is the raw name of an attribute in the XML
- data. It consists of the namespace prefix, followed by colon,
- followed by the attribute's local name. Since the namespace prefix
- is not unique (the same prefix can point to different namespaces and
- different prefixes can point to the same namespace), you shouldn't
- use qualified names, but a resolved namespaceUri and the attribute's
- local name.
*/
-QStringRef QXmlStreamAttributes::value(QLatin1String qualifiedName) const
+QStringView QXmlStreamAttributes::value(QAnyStringView qualifiedName) const noexcept
{
for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.qualifiedName() == qualifiedName)
return attribute.value();
}
- return QStringRef();
+ return QStringView();
}
/*!Appends a new attribute with \a name in the namespace
@@ -2792,7 +2687,7 @@ void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &v
append(QXmlStreamAttribute(qualifiedName, value));
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
/*! \fn bool QXmlStreamReader::isStartDocument() const
Returns \c true if tokenType() equals \l StartDocument; otherwise returns \c false.
@@ -2853,6 +2748,8 @@ bool QXmlStreamReader::isCDATA() const
XML declaration; otherwise returns \c false.
If no XML declaration has been parsed, this function returns \c false.
+
+ \sa hasStandaloneDeclaration()
*/
bool QXmlStreamReader::isStandaloneDocument() const
{
@@ -2860,6 +2757,21 @@ bool QXmlStreamReader::isStandaloneDocument() const
return d->standalone;
}
+/*!
+ \since 6.6
+
+ Returns \c true if this document has an explicit standalone
+ declaration (can be 'yes' or 'no'); otherwise returns \c false;
+
+ If no XML declaration has been parsed, this function returns \c false.
+
+ \sa isStandaloneDocument()
+ */
+bool QXmlStreamReader::hasStandaloneDeclaration() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->hasStandalone;
+}
/*!
\since 4.4
@@ -2868,12 +2780,12 @@ bool QXmlStreamReader::isStandaloneDocument() const
version string as specified in the XML declaration.
Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::documentVersion() const
+QStringView QXmlStreamReader::documentVersion() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::StartDocument)
return d->documentVersion;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -2883,15 +2795,15 @@ QStringRef QXmlStreamReader::documentVersion() const
encoding string as specified in the XML declaration.
Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::documentEncoding() const
+QStringView QXmlStreamReader::documentEncoding() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::StartDocument)
return d->documentEncoding;
- return QStringRef();
+ return QStringView();
}
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
/*!
\class QXmlStreamWriter
@@ -2903,6 +2815,7 @@ QStringRef QXmlStreamReader::documentEncoding() const
simple streaming API.
\ingroup xml-tools
+ \ingroup qtserialization
QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
XML. Like its related class, it operates on a QIODevice specified
@@ -2967,25 +2880,29 @@ QStringRef QXmlStreamReader::documentEncoding() const
*/
-#ifndef QT_NO_XMLSTREAMWRITER
+#if QT_CONFIG(xmlstreamwriter)
-class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
+class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack
+{
QXmlStreamWriter *q_ptr;
Q_DECLARE_PUBLIC(QXmlStreamWriter)
public:
+ enum class StartElementOption {
+ KeepEverything = 0, // write out every attribute, namespace, &c.
+ OmitNamespaceDeclarations = 1,
+ };
+
QXmlStreamWriterPrivate(QXmlStreamWriter *q);
~QXmlStreamWriterPrivate() {
if (deleteDevice)
delete device;
}
- void write(const QStringRef &);
- void write(const QString &);
- void writeEscaped(const QString &, bool escapeWhitespace = false);
- void write(const char *s, int len);
- template <int N> void write(const char (&s)[N]) { write(s, N - 1); }
+ void write(QAnyStringView s);
+ void writeEscaped(QAnyStringView, bool escapeWhitespace = false);
bool finishStartElement(bool contents = true);
- void writeStartElement(const QString &namespaceUri, const QString &name);
+ void writeStartElement(QAnyStringView namespaceUri, QAnyStringView name,
+ StartElementOption option = StartElementOption::KeepEverything);
QIODevice *device;
QString *stringDevice;
uint deleteDevice :1;
@@ -2996,23 +2913,26 @@ public:
uint hasIoError :1;
uint hasEncodingError :1;
uint autoFormatting :1;
- QByteArray autoFormattingIndent;
+ std::string autoFormattingIndent;
NamespaceDeclaration emptyNamespace;
qsizetype lastNamespaceDeclaration;
- QStringEncoder toUtf8;
- NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
+ NamespaceDeclaration &addExtraNamespace(QAnyStringView namespaceUri, QAnyStringView prefix);
+ NamespaceDeclaration &findNamespace(QAnyStringView namespaceUri, bool writeDeclaration = false, bool noDefault = false);
void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
int namespacePrefixCount;
void indent(int level);
+private:
+ void doWriteToDevice(QStringView s);
+ void doWriteToDevice(QUtf8StringView s);
+ void doWriteToDevice(QLatin1StringView s);
};
QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
- : autoFormattingIndent(4, ' '),
- toUtf8(QStringEncoder::Utf8, QStringEncoder::Flag::Stateless)
+ : autoFormattingIndent(4, ' ')
{
q_ptr = q;
device = nullptr;
@@ -3028,108 +2948,109 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
namespacePrefixCount = 0;
}
-void QXmlStreamWriterPrivate::write(const QStringRef &s)
+void QXmlStreamWriterPrivate::write(QAnyStringView s)
{
if (device) {
if (hasIoError)
return;
- QByteArray bytes = toUtf8(s);
- if (toUtf8.hasError()) {
- hasEncodingError = true;
- return;
- }
- if (device->write(bytes) != bytes.size())
- hasIoError = true;
- }
- else if (stringDevice)
- s.appendTo(stringDevice);
- else
+
+ s.visit([&] (auto s) { doWriteToDevice(s); });
+ } else if (stringDevice) {
+ s.visit([&] (auto s) { stringDevice->append(s); });
+ } else {
qWarning("QXmlStreamWriter: No device");
+ }
}
-void QXmlStreamWriterPrivate::write(const QString &s)
+void QXmlStreamWriterPrivate::writeEscaped(QAnyStringView s, bool escapeWhitespace)
{
- if (device) {
- if (hasIoError)
- return;
- QByteArray bytes = toUtf8(s);
- if (toUtf8.hasError()) {
- hasEncodingError = true;
- return;
+ struct NextLatin1 {
+ char32_t operator()(const char *&it, const char *) const
+ { return uchar(*it++); }
+ };
+ struct NextUtf8 {
+ char32_t operator()(const char *&it, const char *end) const
+ {
+ uchar uc = *it++;
+ char32_t utf32 = 0;
+ char32_t *output = &utf32;
+ qsizetype n = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(uc, output, it, end);
+ return n < 0 ? 0 : utf32;
}
- if (device->write(bytes) != bytes.size())
- hasIoError = true;
- }
- else if (stringDevice)
- stringDevice->append(s);
- else
- qWarning("QXmlStreamWriter: No device");
-}
+ };
+ struct NextUtf16 {
+ char32_t operator()(const QChar *&it, const QChar *end) const
+ {
+ QStringIterator decoder(it, end);
+ char32_t result = decoder.next(u'\0');
+ it = decoder.position();
+ return result;
+ }
+ };
-void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespace)
-{
QString escaped;
escaped.reserve(s.size());
- for ( int i = 0; i < s.size(); ++i ) {
- QChar c = s.at(i);
- switch (c.unicode()) {
- case '<':
- escaped.append(QLatin1String("&lt;"));
- break;
- case '>':
- escaped.append(QLatin1String("&gt;"));
- break;
- case '&':
- escaped.append(QLatin1String("&amp;"));
- break;
- case '\"':
- escaped.append(QLatin1String("&quot;"));
- break;
- case '\t':
- if (escapeWhitespace)
- escaped.append(QLatin1String("&#9;"));
- else
- escaped += c;
- break;
- case '\n':
- if (escapeWhitespace)
- escaped.append(QLatin1String("&#10;"));
- else
- escaped += c;
- break;
- case '\v':
- case '\f':
- hasEncodingError = true;
- break;
- case '\r':
- if (escapeWhitespace)
- escaped.append(QLatin1String("&#13;"));
- else
- escaped += c;
- break;
- default:
- if (c.unicode() > 0x1f && c.unicode() < 0xfffe)
- escaped += c;
- else
- hasEncodingError = true;
- break;
- }
- }
- write(escaped);
-}
+ s.visit([&] (auto s) {
+ using View = decltype(s);
+ using Decoder = std::conditional_t<std::is_same_v<View, QLatin1StringView>, NextLatin1,
+ std::conditional_t<std::is_same_v<View, QUtf8StringView>, NextUtf8, NextUtf16>>;
+
+ auto it = s.begin();
+ const auto end = s.end();
+ Decoder decoder;
+
+ while (it != end) {
+ QLatin1StringView replacement;
+ auto mark = it;
+
+ while (it != end) {
+ auto next_it = it;
+ char32_t uc = decoder(next_it, end);
+ if (uc == u'<') {
+ replacement = "&lt;"_L1;
+ break;
+ } else if (uc == u'>') {
+ replacement = "&gt;"_L1;
+ break;
+ } else if (uc == u'&') {
+ replacement = "&amp;"_L1;
+ break;
+ } else if (uc == u'\"') {
+ replacement = "&quot;"_L1;
+ break;
+ } else if (uc == u'\t') {
+ if (escapeWhitespace) {
+ replacement = "&#9;"_L1;
+ break;
+ }
+ } else if (uc == u'\n') {
+ if (escapeWhitespace) {
+ replacement = "&#10;"_L1;
+ break;
+ }
+ } else if (uc == u'\v' || uc == u'\f') {
+ hasEncodingError = true;
+ break;
+ } else if (uc == u'\r') {
+ if (escapeWhitespace) {
+ replacement = "&#13;"_L1;
+ break;
+ }
+ } else if (uc <= u'\x1F' || uc == u'\uFFFE' || uc == u'\uFFFF') {
+ hasEncodingError = true;
+ break;
+ }
+ it = next_it;
+ }
-// Writes utf8
-void QXmlStreamWriterPrivate::write(const char *s, int len)
-{
- if (device) {
- if (hasIoError)
- return;
- if (device->write(s, len) != len)
- hasIoError = true;
- return;
- }
+ escaped.append(View{mark, it});
+ escaped.append(replacement);
+ if (it != end)
+ ++it;
+ }
+ } );
- write(QString::fromUtf8(s, len));
+ write(escaped);
}
void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
@@ -3155,7 +3076,7 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
if (inEmptyElement) {
write("/>");
- QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = tagStack_pop();
lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
lastWasStartElement = false;
} else {
@@ -3166,7 +3087,33 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
return hadSomethingWritten;
}
-QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
+QXmlStreamPrivateTagStack::NamespaceDeclaration &
+QXmlStreamWriterPrivate::addExtraNamespace(QAnyStringView namespaceUri, QAnyStringView prefix)
+{
+ const bool prefixIsXml = prefix == "xml"_L1;
+ const bool namespaceUriIsXml = namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1;
+ if (prefixIsXml && !namespaceUriIsXml) {
+ qWarning("Reserved prefix 'xml' must not be bound to a different namespace name "
+ "than 'http://www.w3.org/XML/1998/namespace'");
+ } else if (!prefixIsXml && namespaceUriIsXml) {
+ const QString prefixString = prefix.toString();
+ qWarning("The prefix '%ls' must not be bound to namespace name "
+ "'http://www.w3.org/XML/1998/namespace' which 'xml' is already bound to",
+ qUtf16Printable(prefixString));
+ }
+ if (namespaceUri == "http://www.w3.org/2000/xmlns/"_L1) {
+ const QString prefixString = prefix.toString();
+ qWarning("The prefix '%ls' must not be bound to namespace name "
+ "'http://www.w3.org/2000/xmlns/'",
+ qUtf16Printable(prefixString));
+ }
+ auto &namespaceDeclaration = namespaceDeclarations.push();
+ namespaceDeclaration.prefix = addToStringStorage(prefix);
+ namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
+ return namespaceDeclaration;
+}
+
+QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(QAnyStringView namespaceUri, bool writeDeclaration, bool noDefault)
{
for (NamespaceDeclaration &namespaceDeclaration : reversed(namespaceDeclarations)) {
if (namespaceDeclaration.namespaceUri == namespaceUri) {
@@ -3183,7 +3130,7 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
QString s;
int n = ++namespacePrefixCount;
forever {
- s = QLatin1Char('n') + QString::number(n++);
+ s = u'n' + QString::number(n++);
qsizetype j = namespaceDeclarations.size() - 2;
while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
--j;
@@ -3203,10 +3150,43 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
void QXmlStreamWriterPrivate::indent(int level)
{
write("\n");
- for (int i = level; i > 0; --i)
- write(autoFormattingIndent.constData(), autoFormattingIndent.length());
+ for (int i = 0; i < level; ++i)
+ write(autoFormattingIndent);
}
+void QXmlStreamWriterPrivate::doWriteToDevice(QStringView s)
+{
+ constexpr qsizetype MaxChunkSize = 512;
+ char buffer [3 * MaxChunkSize];
+ QStringEncoder::State state;
+ while (!s.isEmpty()) {
+ const qsizetype chunkSize = std::min(s.size(), MaxChunkSize);
+ char *end = QUtf8::convertFromUnicode(buffer, s.first(chunkSize), &state);
+ doWriteToDevice(QUtf8StringView{buffer, end});
+ s = s.sliced(chunkSize);
+ }
+ if (state.remainingChars > 0)
+ hasEncodingError = true;
+}
+
+void QXmlStreamWriterPrivate::doWriteToDevice(QUtf8StringView s)
+{
+ QByteArrayView bytes = s;
+ if (device->write(bytes.data(), bytes.size()) != bytes.size())
+ hasIoError = true;
+}
+
+void QXmlStreamWriterPrivate::doWriteToDevice(QLatin1StringView s)
+{
+ constexpr qsizetype MaxChunkSize = 512;
+ char buffer [2 * MaxChunkSize];
+ while (!s.isEmpty()) {
+ const qsizetype chunkSize = std::min(s.size(), MaxChunkSize);
+ char *end = QUtf8::convertFromLatin1(buffer, s.first(chunkSize));
+ doWriteToDevice(QUtf8StringView{buffer, end});
+ s = s.sliced(chunkSize);
+ }
+}
/*!
Constructs a stream writer.
@@ -3294,7 +3274,7 @@ QIODevice *QXmlStreamWriter::device() const
/*!
\property QXmlStreamWriter::autoFormatting
\since 4.4
- The auto-formatting flag of the stream writer
+ \brief the auto-formatting flag of the stream writer.
This property controls whether or not the stream writer
automatically formats the generated XML data. If enabled, the
@@ -3324,7 +3304,7 @@ void QXmlStreamWriter::setAutoFormatting(bool enable)
/*!
\since 4.4
- Returns \c true if auto formattting is enabled, otherwise \c false.
+ Returns \c true if auto formatting is enabled, otherwise \c false.
*/
bool QXmlStreamWriter::autoFormatting() const
{
@@ -3349,13 +3329,14 @@ bool QXmlStreamWriter::autoFormatting() const
void QXmlStreamWriter::setAutoFormattingIndent(int spacesOrTabs)
{
Q_D(QXmlStreamWriter);
- d->autoFormattingIndent = QByteArray(qAbs(spacesOrTabs), spacesOrTabs >= 0 ? ' ' : '\t');
+ d->autoFormattingIndent.assign(size_t(qAbs(spacesOrTabs)), spacesOrTabs >= 0 ? ' ' : '\t');
}
int QXmlStreamWriter::autoFormattingIndent() const
{
Q_D(const QXmlStreamWriter);
- return d->autoFormattingIndent.count(' ') - d->autoFormattingIndent.count('\t');
+ const QLatin1StringView indent(d->autoFormattingIndent);
+ return indent.count(u' ') - indent.count(u'\t');
}
/*!
@@ -3380,12 +3361,15 @@ bool QXmlStreamWriter::hasError() const
This function can only be called after writeStartElement() before
any content is written, or after writeEmptyElement().
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
+void QXmlStreamWriter::writeAttribute(QAnyStringView qualifiedName, QAnyStringView value)
{
Q_D(QXmlStreamWriter);
Q_ASSERT(d->inStartElement);
- Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+ Q_ASSERT(count(qualifiedName, ':') <= 1);
d->write(" ");
d->write(qualifiedName);
d->write("=\"");
@@ -3400,12 +3384,15 @@ void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QStrin
This function can only be called after writeStartElement() before
any content is written, or after writeEmptyElement().
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
+void QXmlStreamWriter::writeAttribute(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView value)
{
Q_D(QXmlStreamWriter);
Q_ASSERT(d->inStartElement);
- Q_ASSERT(!name.contains(QLatin1Char(':')));
+ Q_ASSERT(!contains(name, ':'));
QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->findNamespace(namespaceUri, true, true);
d->write(" ");
if (!namespaceDeclaration.prefix.isEmpty()) {
@@ -3429,12 +3416,9 @@ void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString
void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute& attribute)
{
if (attribute.namespaceUri().isEmpty())
- writeAttribute(attribute.qualifiedName().toString(),
- attribute.value().toString());
+ writeAttribute(attribute.qualifiedName(), attribute.value());
else
- writeAttribute(attribute.namespaceUri().toString(),
- attribute.name().toString(),
- attribute.value().toString());
+ writeAttribute(attribute.namespaceUri(), attribute.name(), attribute.value());
}
@@ -3464,15 +3448,26 @@ void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
This function mainly exists for completeness. Normally you should
not need use it, because writeCharacters() automatically escapes all
non-content characters.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeCDATA(const QString &text)
+void QXmlStreamWriter::writeCDATA(QAnyStringView text)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
- QString copy(text);
- copy.replace(QLatin1String("]]>"), QLatin1String("]]]]><![CDATA[>"));
d->write("<![CDATA[");
- d->write(copy);
+ while (!text.isEmpty()) {
+ const auto idx = indexOf(text, "]]>"_L1);
+ if (idx < 0)
+ break; // no forbidden sequence found
+ d->write(text.first(idx));
+ d->write("]]" // text[idx, idx + 2)
+ "]]><![CDATA[" // escape sequence to separate ]] and >
+ ">"); // text[idx + 2, idx + 3)
+ text = text.sliced(idx + 3); // skip over "]]>"
+ }
+ d->write(text); // write remainder
d->write("]]>");
}
@@ -3482,8 +3477,11 @@ void QXmlStreamWriter::writeCDATA(const QString &text)
"]]>", ">" is also escaped as "&gt;".
\sa writeEntityReference()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeCharacters(const QString &text)
+void QXmlStreamWriter::writeCharacters(QAnyStringView text)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
@@ -3492,13 +3490,16 @@ void QXmlStreamWriter::writeCharacters(const QString &text)
/*! Writes \a text as XML comment, where \a text must not contain the
- forbidden sequence "--" or end with "-". Note that XML does not
- provide any way to escape "-" in a comment.
+ forbidden sequence \c{--} or end with \c{-}. Note that XML does not
+ provide any way to escape \c{-} in a comment.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeComment(const QString &text)
+void QXmlStreamWriter::writeComment(QAnyStringView text)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-')));
+ Q_ASSERT(!contains(text, "--"_L1) && !endsWith(text, '-'));
if (!d->finishStartElement(false) && d->autoFormatting)
d->indent(d->tagStack.size());
d->write("<!--");
@@ -3510,8 +3511,11 @@ void QXmlStreamWriter::writeComment(const QString &text)
/*! Writes a DTD section. The \a dtd represents the entire
doctypedecl production from the XML 1.0 specification.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeDTD(const QString &dtd)
+void QXmlStreamWriter::writeDTD(QAnyStringView dtd)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
@@ -3527,12 +3531,15 @@ void QXmlStreamWriter::writeDTD(const QString &dtd)
/*! \overload
Writes an empty element with qualified name \a qualifiedName.
Subsequent calls to writeAttribute() will add attributes to this element.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
+void QXmlStreamWriter::writeEmptyElement(QAnyStringView qualifiedName)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
- d->writeStartElement(QString(), qualifiedName);
+ Q_ASSERT(count(qualifiedName, ':') <= 1);
+ d->writeStartElement({}, qualifiedName);
d->inEmptyElement = true;
}
@@ -3543,11 +3550,14 @@ void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
Subsequent calls to writeAttribute() will add attributes to this element.
\sa writeNamespace()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
+void QXmlStreamWriter::writeEmptyElement(QAnyStringView namespaceUri, QAnyStringView name)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!name.contains(QLatin1Char(':')));
+ Q_ASSERT(!contains(name, ':'));
d->writeStartElement(namespaceUri, name);
d->inEmptyElement = true;
}
@@ -3560,8 +3570,10 @@ void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QStr
This is a convenience function equivalent to:
\snippet code/src_corelib_xml_qxmlstream.cpp 1
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
+void QXmlStreamWriter::writeTextElement(QAnyStringView qualifiedName, QAnyStringView text)
{
writeStartElement(qualifiedName);
writeCharacters(text);
@@ -3577,8 +3589,10 @@ void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QStr
This is a convenience function equivalent to:
\snippet code/src_corelib_xml_qxmlstream.cpp 2
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
+void QXmlStreamWriter::writeTextElement(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView text)
{
writeStartElement(namespaceUri, name);
writeCharacters(text);
@@ -3614,7 +3628,7 @@ void QXmlStreamWriter::writeEndElement()
if (d->inStartElement && !d->inEmptyElement) {
d->write("/>");
d->lastWasStartElement = d->inStartElement = false;
- QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = d->tagStack_pop();
d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
return;
}
@@ -3624,7 +3638,7 @@ void QXmlStreamWriter::writeEndElement()
if (d->tagStack.isEmpty())
return;
d->lastWasStartElement = false;
- QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = d->tagStack_pop();
d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
d->write("</");
if (!tag.namespaceDeclaration.prefix.isEmpty()) {
@@ -3639,8 +3653,11 @@ void QXmlStreamWriter::writeEndElement()
/*!
Writes the entity reference \a name to the stream, as "&\a{name};".
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeEntityReference(const QString &name)
+void QXmlStreamWriter::writeEntityReference(QAnyStringView name)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
@@ -3664,19 +3681,17 @@ void QXmlStreamWriter::writeEntityReference(const QString &name)
\e http://www.w3.org/2000/xmlns/ are used for the namespace mechanism
itself and thus completely forbidden in declarations.
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix)
+void QXmlStreamWriter::writeNamespace(QAnyStringView namespaceUri, QAnyStringView prefix)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(prefix != QLatin1String("xmlns"));
+ Q_ASSERT(prefix != "xmlns"_L1);
if (prefix.isEmpty()) {
d->findNamespace(namespaceUri, d->inStartElement);
} else {
- Q_ASSERT(!((prefix == QLatin1String("xml")) ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))));
- Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
- QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
- namespaceDeclaration.prefix = d->addToStringStorage(prefix);
- namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
+ auto &namespaceDeclaration = d->addExtraNamespace(namespaceUri, prefix);
if (d->inStartElement)
d->writeNamespaceDeclaration(namespaceDeclaration);
}
@@ -3692,12 +3707,15 @@ void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString
Note that the namespaces \e http://www.w3.org/XML/1998/namespace
(bound to \e xmlns) and \e http://www.w3.org/2000/xmlns/ (bound to
\e xml) by definition cannot be declared as default.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
+void QXmlStreamWriter::writeDefaultNamespace(QAnyStringView namespaceUri)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/XML/1998/namespace"));
- Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
+ Q_ASSERT(namespaceUri != "http://www.w3.org/XML/1998/namespace"_L1);
+ Q_ASSERT(namespaceUri != "http://www.w3.org/2000/xmlns/"_L1);
QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
namespaceDeclaration.prefix.clear();
namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
@@ -3709,11 +3727,14 @@ void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
/*!
Writes an XML processing instruction with \a target and \a data,
where \a data must not contain the sequence "?>".
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const QString &data)
+void QXmlStreamWriter::writeProcessingInstruction(QAnyStringView target, QAnyStringView data)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!data.contains(QLatin1String("?>")));
+ Q_ASSERT(!contains(data, "?>"_L1));
if (!d->finishStartElement(false) && d->autoFormatting)
d->indent(d->tagStack.size());
d->write("<?");
@@ -3736,7 +3757,7 @@ void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const Q
*/
void QXmlStreamWriter::writeStartDocument()
{
- writeStartDocument(QLatin1String("1.0"));
+ writeStartDocument("1.0"_L1);
}
@@ -3744,8 +3765,11 @@ void QXmlStreamWriter::writeStartDocument()
Writes a document start with the XML version number \a version.
\sa writeEndDocument()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartDocument(const QString &version)
+void QXmlStreamWriter::writeStartDocument(QAnyStringView version)
{
Q_D(QXmlStreamWriter);
d->finishStartElement(false);
@@ -3761,8 +3785,11 @@ void QXmlStreamWriter::writeStartDocument(const QString &version)
\sa writeEndDocument()
\since 4.5
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalone)
+void QXmlStreamWriter::writeStartDocument(QAnyStringView version, bool standalone)
{
Q_D(QXmlStreamWriter);
d->finishStartElement(false);
@@ -3783,12 +3810,15 @@ void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalon
writeAttribute() will add attributes to this element.
\sa writeEndElement(), writeEmptyElement()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
+void QXmlStreamWriter::writeStartElement(QAnyStringView qualifiedName)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
- d->writeStartElement(QString(), qualifiedName);
+ Q_ASSERT(count(qualifiedName, ':') <= 1);
+ d->writeStartElement({}, qualifiedName);
}
@@ -3799,15 +3829,19 @@ void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
element.
\sa writeNamespace(), writeEndElement(), writeEmptyElement()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartElement(const QString &namespaceUri, const QString &name)
+void QXmlStreamWriter::writeStartElement(QAnyStringView namespaceUri, QAnyStringView name)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!name.contains(QLatin1Char(':')));
+ Q_ASSERT(!contains(name, ':'));
d->writeStartElement(namespaceUri, name);
}
-void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, const QString &name)
+void QXmlStreamWriterPrivate::writeStartElement(QAnyStringView namespaceUri, QAnyStringView name,
+ StartElementOption option)
{
if (!finishStartElement(false) && autoFormatting)
indent(tagStack.size());
@@ -3823,12 +3857,14 @@ void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, con
write(tag.name);
inStartElement = lastWasStartElement = true;
- for (qsizetype i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
- writeNamespaceDeclaration(namespaceDeclarations[i]);
+ if (option != StartElementOption::OmitNamespaceDeclarations) {
+ for (qsizetype i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
+ writeNamespaceDeclaration(namespaceDeclarations[i]);
+ }
tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
/*! Writes the current state of the \a reader. All possible valid
states are supported.
@@ -3838,6 +3874,7 @@ void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, con
*/
void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
{
+ Q_D(QXmlStreamWriter);
switch (reader.tokenType()) {
case QXmlStreamReader::NoToken:
break;
@@ -3848,13 +3885,19 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
writeEndDocument();
break;
case QXmlStreamReader::StartElement: {
- writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
- QXmlStreamNamespaceDeclarations namespaceDeclarations = reader.namespaceDeclarations();
- for (int i = 0; i < namespaceDeclarations.size(); ++i) {
- const QXmlStreamNamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(i);
- writeNamespace(namespaceDeclaration.namespaceUri().toString(),
- namespaceDeclaration.prefix().toString());
+ // Namespaces must be added before writeStartElement is called so new prefixes are found
+ QList<QXmlStreamPrivateTagStack::NamespaceDeclaration> extraNamespaces;
+ for (const auto &namespaceDeclaration : reader.namespaceDeclarations()) {
+ auto &extraNamespace = d->addExtraNamespace(namespaceDeclaration.namespaceUri(),
+ namespaceDeclaration.prefix());
+ extraNamespaces.append(extraNamespace);
}
+ d->writeStartElement(
+ reader.namespaceUri(), reader.name(),
+ QXmlStreamWriterPrivate::StartElementOption::OmitNamespaceDeclarations);
+ // Namespace declarations are written afterwards
+ for (const auto &extraNamespace : std::as_const(extraNamespaces))
+ d->writeNamespaceDeclaration(extraNamespace);
writeAttributes(reader.attributes());
} break;
case QXmlStreamReader::EndElement:
@@ -3862,22 +3905,22 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
break;
case QXmlStreamReader::Characters:
if (reader.isCDATA())
- writeCDATA(reader.text().toString());
+ writeCDATA(reader.text());
else
- writeCharacters(reader.text().toString());
+ writeCharacters(reader.text());
break;
case QXmlStreamReader::Comment:
- writeComment(reader.text().toString());
+ writeComment(reader.text());
break;
case QXmlStreamReader::DTD:
- writeDTD(reader.text().toString());
+ writeDTD(reader.text());
break;
case QXmlStreamReader::EntityReference:
- writeEntityReference(reader.name().toString());
+ writeEntityReference(reader.name());
break;
case QXmlStreamReader::ProcessingInstruction:
- writeProcessingInstruction(reader.processingInstructionTarget().toString(),
- reader.processingInstructionData().toString());
+ writeProcessingInstruction(reader.processingInstructionTarget(),
+ reader.processingInstructionData());
break;
default:
Q_ASSERT(reader.tokenType() != QXmlStreamReader::Invalid);
@@ -3886,9 +3929,99 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
}
}
+static constexpr bool isTokenAllowedInContext(QXmlStreamReader::TokenType type,
+ QXmlStreamReaderPrivate::XmlContext ctxt)
+{
+ switch (type) {
+ case QXmlStreamReader::StartDocument:
+ case QXmlStreamReader::DTD:
+ return ctxt == QXmlStreamReaderPrivate::XmlContext::Prolog;
+
+ case QXmlStreamReader::StartElement:
+ case QXmlStreamReader::EndElement:
+ case QXmlStreamReader::Characters:
+ case QXmlStreamReader::EntityReference:
+ case QXmlStreamReader::EndDocument:
+ return ctxt == QXmlStreamReaderPrivate::XmlContext::Body;
+
+ case QXmlStreamReader::Comment:
+ case QXmlStreamReader::ProcessingInstruction:
+ return true;
+
+ case QXmlStreamReader::NoToken:
+ case QXmlStreamReader::Invalid:
+ return false;
+ }
+
+ // GCC 8.x does not treat __builtin_unreachable() as constexpr
+#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
+ Q_UNREACHABLE_RETURN(false);
+#else
+ return false;
+#endif
+}
+
/*!
- \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
- \since 4.5
+ \internal
+ \brief QXmlStreamReader::isValidToken
+ \return \c true if \param type is a valid token type.
+ \return \c false if \param type is an unexpected token,
+ which indicates a non-well-formed or invalid XML stream.
+ */
+bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type)
+{
+ // Don't change currentContext, if Invalid or NoToken occur in the prolog
+ if (type == QXmlStreamReader::Invalid || type == QXmlStreamReader::NoToken)
+ return false;
+
+ // If a token type gets rejected in the body, there is no recovery
+ const bool result = isTokenAllowedInContext(type, currentContext);
+ if (result || currentContext == XmlContext::Body)
+ return result;
+
+ // First non-Prolog token observed => switch context to body and check again.
+ currentContext = XmlContext::Body;
+ return isTokenAllowedInContext(type, currentContext);
+}
+
+/*!
+ \internal
+ Checks token type and raises an error, if it is invalid
+ in the current context (prolog/body).
+ */
+void QXmlStreamReaderPrivate::checkToken()
+{
+ Q_Q(QXmlStreamReader);
+
+ // The token type must be consumed, to keep track if the body has been reached.
+ const XmlContext context = currentContext;
+ const bool ok = isValidToken(type);
+
+ // Do nothing if an error has been raised already (going along with an unexpected token)
+ if (error != QXmlStreamReader::Error::NoError)
+ return;
+
+ if (!ok) {
+ raiseError(QXmlStreamReader::UnexpectedElementError,
+ QXmlStream::tr("Unexpected token type %1 in %2.")
+ .arg(q->tokenString(), contextString(context)));
+ return;
+ }
+
+ if (type != QXmlStreamReader::DTD)
+ return;
+
+ // Raise error on multiple DTD tokens
+ if (foundDTD) {
+ raiseError(QXmlStreamReader::UnexpectedElementError,
+ QXmlStream::tr("Found second DTD token in %1.").arg(contextString(context)));
+ } else {
+ foundDTD = true;
+ }
+}
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(QAnyStringView qualifiedName) const
Returns \c true if this QXmlStreamAttributes has an attribute whose
qualified name is \a qualifiedName; otherwise returns \c false.
@@ -3902,25 +4035,18 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
*/
/*!
- \fn bool QXmlStreamAttributes::hasAttribute(QLatin1String qualifiedName) const
- \overload
- \since 4.5
-*/
-
-/*!
- \fn bool QXmlStreamAttributes::hasAttribute(const QString &namespaceUri,
- const QString &name) const
+ \fn bool QXmlStreamAttributes::hasAttribute(QAnyStringView namespaceUri,
+ QAnyStringView name) const
\overload
- \since 4.5
Returns \c true if this QXmlStreamAttributes has an attribute whose
namespace URI and name correspond to \a namespaceUri and \a name;
otherwise returns \c false.
*/
-#endif // QT_NO_XMLSTREAMREADER
-#endif // QT_NO_XMLSTREAMWRITER
+#endif // feature xmlstreamreader
+#endif // feature xmlstreamwriter
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAM
+#endif // feature xmlstream
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index 876157a9e6..860b7fd727 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -1,45 +1,8 @@
-----------------------------------------------------------------------------
---
--- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QtCore module of the Qt Toolkit.
---
--- $QT_BEGIN_LICENSE:LGPL$
--- Commercial License Usage
--- Licensees holding valid commercial Qt licenses may use this file in
--- accordance with the commercial license agreement provided with the
--- Software or, alternatively, in accordance with the terms contained in
--- a written agreement between you and The Qt Company. For licensing terms
--- and conditions see https://www.qt.io/terms-conditions. For further
--- information use the contact form at https://www.qt.io/contact-us.
---
--- GNU Lesser General Public License Usage
--- Alternatively, this file may be used under the terms of the GNU Lesser
--- General Public License version 3 as published by the Free Software
--- Foundation and appearing in the file LICENSE.LGPL3 included in the
--- packaging of this file. Please review the following information to
--- ensure the GNU Lesser General Public License version 3 requirements
--- will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
---
--- GNU General Public License Usage
--- Alternatively, this file may be used under the terms of the GNU
--- General Public License version 2.0 or (at your option) the GNU General
--- Public license version 3 or any later version approved by the KDE Free
--- Qt Foundation. The licenses are as published by the Free Software
--- Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
--- included in the packaging of this file. Please review the following
--- information to ensure the GNU General Public License requirements will
--- be met: https://www.gnu.org/licenses/gpl-2.0.html and
--- https://www.gnu.org/licenses/gpl-3.0.html.
---
--- $QT_END_LICENSE$
---
-----------------------------------------------------------------------------
-
-%parser QXmlStreamReader_Table
-
-%merged_output qxmlstream_p.h
+-- Copyright (C) 2020 The Qt Company Ltd.
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+%parser QXmlStreamGrammar
+%impl qxmlstreamparser_p.h
%expect 4
@@ -89,13 +52,13 @@
%token IMPLIED "IMPLIED"
%token FIXED "FIXED"
--- conent spec
+-- content spec
%token EMPTY "EMPTY"
%token ANY "ANY"
%token PCDATA "PCDATA"
-- error
-%token ERROR
+%token XML_ERROR
-- entities
%token PARSE_ENTITY
@@ -146,412 +109,54 @@
%start document
-
-
-/.
+/.// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is automatically generated from qxmlstream.g.
+// Changes should be made to that file, not here. Any change to this file will
+// be lost!
+//
+// To regenerate this file, run:
+// qlalr --no-debug --no-lines --qt qxmlstream.g
+//
#include <QtCore/private/qglobal_p.h>
+#include <qxmlstream.h>
+#include "qxmlstream_p.h"
+#include "qxmlutils_p.h"
#include <qstringconverter.h>
-template <typename T> class QXmlStreamSimpleStack {
- T *data;
- qsizetype tos, cap;
-public:
- inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
- inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
-
- inline void reserve(qsizetype extraCapacity) {
- if (tos + extraCapacity + 1 > cap) {
- cap = qMax(tos + extraCapacity + 1, cap << 1 );
- void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
- data = reinterpret_cast<T *>(ptr);
- Q_CHECK_PTR(data);
- }
- }
-
- inline T &push() { reserve(1); return data[++tos]; }
- inline T &rawPush() { return data[++tos]; }
- inline const T &top() const { return data[tos]; }
- inline T &top() { return data[tos]; }
- inline T &pop() { return data[tos--]; }
- inline T &operator[](qsizetype index) { return data[index]; }
- inline const T &at(qsizetype index) const { return data[index]; }
- inline qsizetype size() const { return tos + 1; }
- inline void resize(qsizetype s) { tos = s - 1; }
- inline bool isEmpty() const { return tos < 0; }
- inline void clear() { tos = -1; }
-
- using const_iterator = const T*;
- using iterator = T*;
- T *begin() { return data; }
- const T *begin() const { return data; }
- const T *cbegin() const { return begin(); }
- T *end() { return data + size(); }
- const T *end() const { return data + size(); }
- const T *cend() const { return end(); }
-};
-
-
-class QXmlStream
-{
- Q_DECLARE_TR_FUNCTIONS(QXmlStream)
-};
-
-class QXmlStreamPrivateTagStack {
-public:
- struct NamespaceDeclaration
- {
- QStringRef prefix;
- QStringRef namespaceUri;
- };
-
- struct Tag
- {
- QStringRef name;
- QStringRef qualifiedName;
- NamespaceDeclaration namespaceDeclaration;
- int tagStackStringStorageSize;
- qsizetype namespaceDeclarationsSize;
- };
-
-
- QXmlStreamPrivateTagStack();
- QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
- QString tagStackStringStorage;
- int tagStackStringStorageSize;
- int initialTagStackStringStorageSize;
- bool tagsDone;
-
- inline QStringRef addToStringStorage(const QStringRef &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- inline QStringRef addToStringStorage(const QString &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- QStringRef addToStringStorage(QStringView s)
- {
- int pos = tagStackStringStorageSize;
- int sz = s.size();
- if (pos != tagStackStringStorage.size())
- tagStackStringStorage.resize(pos);
- tagStackStringStorage.append(s.data(), sz);
- tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
- }
-
- QXmlStreamSimpleStack<Tag> tagStack;
+#include <memory>
+#ifndef QXMLSTREAMPARSER_P_H
+#define QXMLSTREAMPARSER_P_H
- inline Tag &tagStack_pop() {
- Tag& tag = tagStack.pop();
- tagStackStringStorageSize = tag.tagStackStringStorageSize;
- namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
- tagsDone = tagStack.isEmpty();
- return tag;
- }
- inline Tag &tagStack_push() {
- Tag &tag = tagStack.push();
- tag.tagStackStringStorageSize = tagStackStringStorageSize;
- tag.namespaceDeclarationsSize = namespaceDeclarations.size();
- return tag;
- }
-};
-
-
-class QXmlStreamEntityResolver;
-#ifndef QT_NO_XMLSTREAMREADER
-class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{
- QXmlStreamReader *q_ptr;
- Q_DECLARE_PUBLIC(QXmlStreamReader)
-public:
- QXmlStreamReaderPrivate(QXmlStreamReader *q);
- ~QXmlStreamReaderPrivate();
- void init();
-
- QByteArray rawReadBuffer;
- QByteArray dataBuffer;
- uchar firstByte;
- qint64 nbytesread;
- QString readBuffer;
- int readBufferPos;
- QXmlStreamSimpleStack<uint> putStack;
- struct Entity {
- Entity() = default;
- Entity(const QString &name, const QString &value)
- : name(name), value(value), external(false), unparsed(false), literal(false),
- hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(QLatin1String name, QLatin1String value)
- { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; }
- QString name, value;
- uint external : 1;
- uint unparsed : 1;
- uint literal : 1;
- uint hasBeenParsed : 1;
- uint isCurrentlyReferenced : 1;
- };
- // these hash tables use a QStringView as a key to avoid creating QStrings
- // just for lookup. The keys are usually views into Entity::name and thus
- // are guaranteed to have the same lifetime as the referenced data:
- QHash<QStringView, Entity> entityHash;
- QHash<QStringView, Entity> parameterEntityHash;
- QXmlStreamSimpleStack<Entity *>entityReferenceStack;
- int entityExpansionLimit = 4096;
- int entityLength = 0;
- inline bool referenceEntity(Entity &entity) {
- if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
- return false;
- }
- // entityLength represents the amount of additional characters the
- // entity expands into (can be negative for e.g. &amp;). It's used to
- // avoid DoS attacks through recursive entity expansions
- entityLength += entity.value.size() - entity.name.size() - 2;
- if (entityLength > entityExpansionLimit) {
- raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
- return false;
- }
- entity.isCurrentlyReferenced = true;
- entityReferenceStack.push() = &entity;
- injectToken(ENTITY_DONE);
- return true;
- }
-
+QT_BEGIN_NAMESPACE
- QIODevice *device;
- bool deleteDevice;
- QStringDecoder decoder;
- bool atEnd;
-
- /*!
- \sa setType()
- */
- QXmlStreamReader::TokenType type;
- QXmlStreamReader::Error error;
- QString errorString;
- QString unresolvedEntity;
-
- qint64 lineNumber, lastLineStart, characterOffset;
-
-
- void write(const QString &);
- void write(const char *);
-
-
- QXmlStreamAttributes attributes;
- QStringRef namespaceForPrefix(const QStringRef &prefix);
- void resolveTag();
- void resolvePublicNamespaces();
- void resolveDtd();
- uint resolveCharRef(int symbolIndex);
- bool checkStartDocument();
- void startDocument();
- void parseError();
- void checkPublicLiteral(const QStringRef &publicId);
-
- bool scanDtd;
- QStringRef lastAttributeValue;
- bool lastAttributeIsCData;
- struct DtdAttribute {
- QStringRef tagName;
- QStringRef attributeQualifiedName;
- QStringRef attributePrefix;
- QStringRef attributeName;
- QStringRef defaultValue;
- bool isCDATA;
- bool isNamespaceAttribute;
- };
- QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
- struct NotationDeclaration {
- QStringRef name;
- QStringRef publicId;
- QStringRef systemId;
- };
- QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
- QXmlStreamNotationDeclarations publicNotationDeclarations;
- QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
-
- struct EntityDeclaration {
- QStringRef name;
- QStringRef notationName;
- QStringRef publicId;
- QStringRef systemId;
- QStringRef value;
- bool parameter;
- bool external;
- inline void clear() {
- name.clear();
- notationName.clear();
- publicId.clear();
- systemId.clear();
- value.clear();
- parameter = external = false;
- }
- };
- QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
- QXmlStreamEntityDeclarations publicEntityDeclarations;
-
- QStringRef text;
-
- QStringRef prefix, namespaceUri, qualifiedName, name;
- QStringRef processingInstructionTarget, processingInstructionData;
- QStringRef dtdName, dtdPublicId, dtdSystemId;
- QStringRef documentVersion, documentEncoding;
- uint isEmptyElement : 1;
- uint isWhitespace : 1;
- uint isCDATA : 1;
- uint standalone : 1;
- uint hasCheckedStartDocument : 1;
- uint normalizeLiterals : 1;
- uint hasSeenTag : 1;
- uint inParseEntity : 1;
- uint referenceToUnparsedEntityDetected : 1;
- uint referenceToParameterEntityDetected : 1;
- uint hasExternalDtdSubset : 1;
- uint lockEncoding : 1;
- uint namespaceProcessing : 1;
-
- int resumeReduction;
- void resume(int rule);
-
- inline bool entitiesMustBeDeclared() const {
- return (!inParseEntity
- && (standalone
- || (!referenceToUnparsedEntityDetected
- && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25
- && !hasExternalDtdSubset)));
- }
-
- // qlalr parser
- int tos;
- int stack_size;
- struct Value {
- int pos;
- int len;
- int prefix;
- ushort c;
- };
-
- Value *sym_stack;
- int *state_stack;
- inline void reallocateStack();
- inline Value &sym(int index) const
- { return sym_stack[tos + index - 1]; }
- QString textBuffer;
- inline void clearTextBuffer() {
- if (!scanDtd) {
- textBuffer.resize(0);
- textBuffer.reserve(256);
- }
- }
- struct Attribute {
- Value key;
- Value value;
- };
- QXmlStreamSimpleStack<Attribute> attributeStack;
-
- inline QStringRef symString(int index) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
- }
- QStringView symView(int index) const
- {
- const Value &symbol = sym(index);
- return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
- }
- inline QStringRef symName(int index) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
- }
- inline QStringRef symString(int index, int offset) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
- }
- inline QStringRef symPrefix(int index) {
- const Value &symbol = sym(index);
- if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
- }
- inline QStringRef symString(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
- }
- inline QStringRef symName(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
- }
- inline QStringRef symPrefix(const Value &symbol) {
- if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
- }
-
- inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
-
-
- short token;
- uint token_char;
-
- uint filterCarriageReturn();
- inline uint getChar();
- inline uint peekChar();
- inline void putChar(uint c) { putStack.push() = c; }
- inline void putChar(QChar c) { putStack.push() = c.unicode(); }
- void putString(QStringView s, qsizetype from = 0);
- void putStringLiteral(QStringView s);
- void putReplacement(QStringView s);
- void putReplacementInAttributeValue(QStringView s);
- uint getChar_helper();
-
- bool scanUntil(const char *str, short tokenToInject = -1);
- bool scanString(const char *str, short tokenToInject, bool requireSpace = true);
- inline void injectToken(ushort tokenToInject) {
- putChar(int(tokenToInject) << 16);
- }
-
- QString resolveUndeclaredEntity(const QString &name);
- void parseEntity(const QString &value);
- std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
-
- bool scanAfterLangleBang();
- bool scanPublicOrSystem();
- bool scanNData();
- bool scanAfterDefaultDecl();
- bool scanAttType();
-
-
- // scan optimization functions. Not strictly necessary but LALR is
- // not very well suited for scanning fast
- int fastScanLiteralContent();
- int fastScanSpace();
- int fastScanContentCharList();
- int fastScanName(int *prefix = nullptr);
- inline int fastScanNMTOKEN();
-
-
- bool parse();
- inline void consumeRule(int);
-
- void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
- void raiseWellFormedError(const QString &message);
-
- QXmlStreamEntityResolver *entityResolver;
-
-private:
- /*! \internal
- Never assign to variable type directly. Instead use this function.
-
- This prevents errors from being ignored.
- */
- inline void setType(const QXmlStreamReader::TokenType t)
- {
- if(type != QXmlStreamReader::Invalid)
- type = t;
- }
-};
+#if QT_CONFIG(xmlstreamreader)
bool QXmlStreamReaderPrivate::parse()
{
// cleanup currently reported token
+ using namespace Qt::StringLiterals;
+
switch (type) {
case QXmlStreamReader::StartElement:
name.clear();
@@ -562,8 +167,9 @@ bool QXmlStreamReaderPrivate::parse()
attributes.clear();
if (isEmptyElement) {
setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
+ Tag tag = tagStack_pop();
namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
name = tag.name;
qualifiedName = tag.qualifiedName;
isEmptyElement = false;
@@ -645,7 +251,7 @@ bool QXmlStreamReaderPrivate::parse()
} else switch (token_char) {
case 0xfffe:
case 0xffff:
- token = ERROR;
+ token = XML_ERROR;
break;
case '\r':
token = SPACE;
@@ -851,12 +457,15 @@ prolog ::=;
entity_done ::= ENTITY_DONE;
/.
- case $rule_number:
- entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ case $rule_number: {
+ auto reference = entityReferenceStack.pop();
+ auto it = reference.hash->find(reference.name);
+ Q_ASSERT(it != reference.hash->end());
+ it->isCurrentlyReferenced = false;
if (entityReferenceStack.isEmpty())
entityLength = 0;
clearSym();
- break;
+ } break;
./
@@ -1055,9 +664,9 @@ attdef ::= attdef_start att_type default_decl;
dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
dtdAttribute.attributeName = addToStringStorage(symString(1));
dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
- dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns")
+ dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == "xmlns"_L1
|| (dtdAttribute.attributePrefix.isEmpty()
- && dtdAttribute.attributeName == QLatin1String("xmlns")));
+ && dtdAttribute.attributeName == "xmlns"_L1));
if (lastAttributeValue.isNull()) {
dtdAttribute.defaultValue.clear();
} else {
@@ -1079,14 +688,14 @@ attlist_decl ::= langle_bang ATTLIST qname attdef_list space_opt RANGLE;
case $rule_number: {
if (referenceToUnparsedEntityDetected && !standalone)
break;
- int n = dtdAttributes.size();
- QStringRef tagName = addToStringStorage(symName(3));
+ qsizetype n = dtdAttributes.size();
+ XmlStringRef tagName = addToStringStorage(symName(3));
while (n--) {
DtdAttribute &dtdAttribute = dtdAttributes[n];
if (!dtdAttribute.tagName.isNull())
break;
dtdAttribute.tagName = tagName;
- for (int i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
&& dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
@@ -1177,7 +786,7 @@ entity_decl ::= entity_decl_start entity_value space_opt RANGLE;
if (!entityDeclaration.external)
entityDeclaration.value = symString(2);
auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) {
+ if (!hash.contains(entityDeclaration.name)) {
Entity entity(entityDeclaration.name.toString(),
entityDeclaration.value.toString());
entity.unparsed = (!entityDeclaration.notationName.isNull());
@@ -1192,11 +801,11 @@ processing_instruction ::= LANGLE QUESTIONMARK name space;
/.
case $rule_number: {
setType(QXmlStreamReader::ProcessingInstruction);
- int pos = sym(4).pos + sym(4).len;
+ const qsizetype pos = sym(4).pos + sym(4).len;
processingInstructionTarget = symString(3);
if (scanUntil("?>")) {
- processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
+ processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive)) {
raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
}
else if (!QXmlUtils::isNCName(processingInstructionTarget))
@@ -1214,7 +823,7 @@ processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE;
case $rule_number:
setType(QXmlStreamReader::ProcessingInstruction);
processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive))
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive))
raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
break;
./
@@ -1244,8 +853,8 @@ comment ::= comment_start RANGLE;
/.
case $rule_number: {
setType(QXmlStreamReader::Comment);
- int pos = sym(1).pos + 4;
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ const qsizetype pos = sym(1).pos + 4;
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
} break;
./
@@ -1256,9 +865,9 @@ cdata ::= langle_bang CDATA_START;
setType(QXmlStreamReader::Characters);
isCDATA = true;
isWhitespace = false;
- int pos = sym(2).pos;
+ const qsizetype pos = sym(2).pos;
if (scanUntil("]]>", -1)) {
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
} else {
resume($rule_number);
return false;
@@ -1392,7 +1001,7 @@ literal_content_start ::= SPACE;
/.
case $rule_number:
if (normalizeLiterals)
- textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
+ textBuffer.data()[textBuffer.size()-1] = u' ';
break;
./
@@ -1506,14 +1115,14 @@ attribute_value_content ::= literal_content | char_ref | entity_ref_in_attribute
attribute ::= qname space_opt EQ space_opt attribute_value;
/.
case $rule_number: {
- QStringRef prefix = symPrefix(1);
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
+ XmlStringRef prefix = symPrefix(1);
+ if (prefix.isEmpty() && symString(1) == "xmlns"_L1 && namespaceProcessing) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
namespaceDeclaration.prefix.clear();
- const QStringRef ns(symString(5));
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+ const XmlStringRef ns(symString(5));
+ if (ns.view() == "http://www.w3.org/2000/xmlns/"_L1 ||
+ ns.view() == "http://www.w3.org/XML/1998/namespace"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
else
namespaceDeclaration.namespaceUri = addToStringStorage(ns);
@@ -1522,10 +1131,9 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
attribute.key = sym(1);
attribute.value = sym(5);
- QStringRef attributeQualifiedName = symName(1);
+ XmlStringRef attributeQualifiedName = symName(1);
bool normalize = false;
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
+ for (const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
if (!dtdAttribute.isCDATA
&& dtdAttribute.tagName == qualifiedName
&& dtdAttribute.attributeQualifiedName == attributeQualifiedName
@@ -1536,10 +1144,10 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
}
if (normalize) {
// normalize attribute value (simplify and trim)
- int pos = textBuffer.size();
- int n = 0;
+ const qsizetype pos = textBuffer.size();
+ qsizetype n = 0;
bool wasSpace = true;
- for (int i = 0; i < attribute.value.len; ++i) {
+ for (qsizetype i = 0; i < attribute.value.len; ++i) {
QChar c = textBuffer.at(attribute.value.pos + i);
if (c.unicode() == ' ') {
if (wasSpace)
@@ -1557,16 +1165,16 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
attribute.value.pos = pos;
attribute.value.len = n;
}
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
+ if (prefix == "xmlns"_L1 && namespaceProcessing) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = symString(attribute.key);
- QStringRef namespaceUri = symString(attribute.value);
+ XmlStringRef namespacePrefix = symString(attribute.key);
+ XmlStringRef namespaceUri = symString(attribute.value);
attributeStack.pop();
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
+ if (((namespacePrefix == "xml"_L1)
+ ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
+ || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
|| namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
+ || namespacePrefix == "xmlns"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
@@ -1619,9 +1227,10 @@ etag ::= LANGLE SLASH qname space_opt RANGLE;
/.
case $rule_number: {
setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
+ Tag tag = tagStack_pop();
namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
name = tag.name;
qualifiedName = tag.qualifiedName;
if (qualifiedName != symName(3))
@@ -1658,7 +1267,7 @@ entity_ref ::= AMPERSAND name SEMICOLON;
}
if (entity.literal)
putStringLiteral(entity.value);
- else if (referenceEntity(entity))
+ else if (referenceEntity(&entityHash, entity))
putReplacement(entity.value);
textBuffer.chop(2 + sym(2).len);
clearSym();
@@ -1695,7 +1304,7 @@ pereference ::= PERCENT name SEMICOLON;
if (entity.unparsed || entity.external) {
referenceToUnparsedEntityDetected = true;
} else {
- if (referenceEntity(entity))
+ if (referenceEntity(&parameterEntityHash, entity))
putString(entity.value);
textBuffer.chop(2 + sym(2).len);
clearSym();
@@ -1732,7 +1341,7 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
}
if (entity.literal)
putStringLiteral(entity.value);
- else if (referenceEntity(entity))
+ else if (referenceEntity(&entityHash, entity))
putReplacementInAttributeValue(entity.value);
textBuffer.chop(2 + sym(2).len);
clearSym();
@@ -1810,7 +1419,12 @@ space_opt ::= space;
qname ::= LETTER;
/.
case $rule_number: {
- sym(1).len += fastScanName(&sym(1).prefix);
+ Value &val = sym(1);
+ if (auto res = fastScanName(&val))
+ val.len += *res;
+ else
+ return false;
+
if (atEnd) {
resume($rule_number);
return false;
@@ -1821,7 +1435,11 @@ qname ::= LETTER;
name ::= LETTER;
/.
case $rule_number:
- sym(1).len += fastScanName();
+ if (auto res = fastScanName())
+ sym(1).len += *res;
+ else
+ return false;
+
if (atEnd) {
resume($rule_number);
return false;
@@ -1868,6 +1486,11 @@ nmtoken ::= COLON;
}
return false;
}
-#endif //QT_NO_XMLSTREAMREADER.xml
+
+#endif // feature xmlstreamreader
+
+QT_END_NAMESPACE
+
+#endif
./
diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index 44f33b111b..8a12c6d611 100644
--- a/src/corelib/serialization/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
@@ -1,89 +1,48 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXMLSTREAM_H
#define QXMLSTREAM_H
#include <QtCore/qiodevice.h>
-#ifndef QT_NO_XMLSTREAM
+#if QT_CONFIG(xmlstream)
+#include <QtCore/qcompare.h>
#include <QtCore/qlist.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
-class Q_CORE_EXPORT QXmlStreamStringRef {
- QString m_string;
- int m_position, m_size;
+class QXmlString {
+ QStringPrivate m_string;
public:
- inline QXmlStreamStringRef():m_position(0), m_size(0){}
- inline QXmlStreamStringRef(const QStringRef &aString)
- :m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){}
- QXmlStreamStringRef(const QString &aString) : m_string(aString), m_position(0), m_size(m_string.size()) {}
- QXmlStreamStringRef(QString &&aString) noexcept : m_string(std::move(aString)), m_position(0), m_size(m_string.size()) {}
+ QXmlString(QStringPrivate &&d) : m_string(std::move(d)) {}
+ QXmlString(const QString &s) : m_string(s.data_ptr()) {}
+ QXmlString & operator=(const QString &s) { m_string = s.data_ptr(); return *this; }
+ QXmlString & operator=(QString &&s) { m_string.swap(s.data_ptr()); return *this; }
+ inline constexpr QXmlString() {}
- void swap(QXmlStreamStringRef &other) noexcept
+ void swap(QXmlString &other) noexcept
{
- qSwap(m_string, other.m_string);
- qSwap(m_position, other.m_position);
- qSwap(m_size, other.m_size);
+ m_string.swap(other.m_string);
}
- inline void clear() { m_string.clear(); m_position = m_size = 0; }
- inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); }
- inline const QString *string() const { return &m_string; }
- inline int position() const { return m_position; }
- inline int size() const { return m_size; }
+ inline operator QStringView() const { return QStringView(m_string.data(), m_string.size); }
+ inline qsizetype size() const { return m_string.size; }
};
-Q_DECLARE_SHARED(QXmlStreamStringRef)
+
+}
+Q_DECLARE_SHARED(QtPrivate::QXmlString)
class QXmlStreamReaderPrivate;
class QXmlStreamAttributes;
class Q_CORE_EXPORT QXmlStreamAttribute {
- QXmlStreamStringRef m_name, m_namespaceUri, m_qualifiedName, m_value;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_name, m_namespaceUri, m_qualifiedName, m_value;
uint m_isDefault : 1;
friend class QXmlStreamReaderPrivate;
friend class QXmlStreamAttributes;
@@ -92,50 +51,60 @@ public:
QXmlStreamAttribute(const QString &qualifiedName, const QString &value);
QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value);
- inline QStringRef namespaceUri() const { return m_namespaceUri; }
- inline QStringRef name() const { return m_name; }
- inline QStringRef qualifiedName() const { return m_qualifiedName; }
- inline QStringRef prefix() const {
- return QStringRef(m_qualifiedName.string(),
- m_qualifiedName.position(),
- qMax(0, m_qualifiedName.size() - m_name.size() - 1));
+ inline QStringView namespaceUri() const { return m_namespaceUri; }
+ inline QStringView name() const { return m_name; }
+ inline QStringView qualifiedName() const { return m_qualifiedName; }
+ inline QStringView prefix() const {
+ return QStringView(m_qualifiedName).left(qMax(0, m_qualifiedName.size() - m_name.size() - 1));
}
- inline QStringRef value() const { return m_value; }
+ inline QStringView value() const { return m_value; }
inline bool isDefault() const { return m_isDefault; }
- inline bool operator==(const QXmlStreamAttribute &other) const {
- return (value() == other.value()
- && (namespaceUri().isNull() ? (qualifiedName() == other.qualifiedName())
- : (namespaceUri() == other.namespaceUri() && name() == other.name())));
- }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamAttribute &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamAttribute &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+
+private:
+ friend bool comparesEqual(const QXmlStreamAttribute &lhs,
+ const QXmlStreamAttribute &rhs) noexcept
+ {
+ return (lhs.value() == rhs.value()
+ && (lhs.namespaceUri().isNull() ? (lhs.qualifiedName() == rhs.qualifiedName())
+ : (lhs.namespaceUri() == rhs.namespaceUri()
+ && lhs.name() == rhs.name())));
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamAttribute)
};
-Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_RELOCATABLE_TYPE);
-class Q_CORE_EXPORT QXmlStreamAttributes : public QList<QXmlStreamAttribute>
+// We export each out-of-line method individually to prevent MSVC from
+// exporting the whole QList class.
+class QXmlStreamAttributes : public QList<QXmlStreamAttribute>
{
public:
inline QXmlStreamAttributes() {}
- QStringRef value(const QString &namespaceUri, const QString &name) const;
- QStringRef value(const QString &namespaceUri, QLatin1String name) const;
- QStringRef value(QLatin1String namespaceUri, QLatin1String name) const;
- QStringRef value(const QString &qualifiedName) const;
- QStringRef value(QLatin1String qualifiedName) const;
- void append(const QString &namespaceUri, const QString &name, const QString &value);
- void append(const QString &qualifiedName, const QString &value);
-
- inline bool hasAttribute(const QString &qualifiedName) const
- {
- return !value(qualifiedName).isNull();
- }
+#if QT_CORE_REMOVED_SINCE(6, 6)
+ Q_CORE_EXPORT QStringView value(const QString &namespaceUri, const QString &name) const;
+ Q_CORE_EXPORT QStringView value(const QString &namespaceUri, QLatin1StringView name) const;
+ Q_CORE_EXPORT QStringView value(QLatin1StringView namespaceUri, QLatin1StringView name) const;
+ Q_CORE_EXPORT QStringView value(const QString &qualifiedName) const;
+ Q_CORE_EXPORT QStringView value(QLatin1StringView qualifiedName) const;
+#endif
+ Q_CORE_EXPORT QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const noexcept;
+ Q_CORE_EXPORT QStringView value(QAnyStringView qualifiedName) const noexcept;
+
+ Q_CORE_EXPORT void append(const QString &namespaceUri, const QString &name, const QString &value);
+ Q_CORE_EXPORT void append(const QString &qualifiedName, const QString &value);
- inline bool hasAttribute(QLatin1String qualifiedName) const
+ bool hasAttribute(QAnyStringView qualifiedName) const
{
return !value(qualifiedName).isNull();
}
- inline bool hasAttribute(const QString &namespaceUri, const QString &name) const
+ bool hasAttribute(QAnyStringView namespaceUri, QAnyStringView name) const
{
return !value(namespaceUri, name).isNull();
}
@@ -144,91 +113,110 @@ public:
};
class Q_CORE_EXPORT QXmlStreamNamespaceDeclaration {
- QXmlStreamStringRef m_prefix, m_namespaceUri;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_prefix, m_namespaceUri;
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamNamespaceDeclaration();
QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri);
- inline QStringRef prefix() const { return m_prefix; }
- inline QStringRef namespaceUri() const { return m_namespaceUri; }
- inline bool operator==(const QXmlStreamNamespaceDeclaration &other) const {
- return (prefix() == other.prefix() && namespaceUri() == other.namespaceUri());
- }
+ inline QStringView prefix() const { return m_prefix; }
+ inline QStringView namespaceUri() const { return m_namespaceUri; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamNamespaceDeclaration &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamNamespaceDeclaration &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+private:
+ friend bool comparesEqual(const QXmlStreamNamespaceDeclaration &lhs,
+ const QXmlStreamNamespaceDeclaration &rhs) noexcept
+ {
+ return (lhs.prefix() == rhs.prefix() && lhs.namespaceUri() == rhs.namespaceUri());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamNamespaceDeclaration)
};
-Q_DECLARE_TYPEINFO(QXmlStreamNamespaceDeclaration, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamNamespaceDeclaration, Q_RELOCATABLE_TYPE);
typedef QList<QXmlStreamNamespaceDeclaration> QXmlStreamNamespaceDeclarations;
class Q_CORE_EXPORT QXmlStreamNotationDeclaration {
- QXmlStreamStringRef m_name, m_systemId, m_publicId;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_name, m_systemId, m_publicId;
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamNotationDeclaration();
- inline QStringRef name() const { return m_name; }
- inline QStringRef systemId() const { return m_systemId; }
- inline QStringRef publicId() const { return m_publicId; }
- inline bool operator==(const QXmlStreamNotationDeclaration &other) const {
- return (name() == other.name() && systemId() == other.systemId()
- && publicId() == other.publicId());
- }
+ inline QStringView name() const { return m_name; }
+ inline QStringView systemId() const { return m_systemId; }
+ inline QStringView publicId() const { return m_publicId; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamNotationDeclaration &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamNotationDeclaration &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+private:
+ friend bool comparesEqual(const QXmlStreamNotationDeclaration &lhs,
+ const QXmlStreamNotationDeclaration &rhs) noexcept
+ {
+ return (lhs.name() == rhs.name() && lhs.systemId() == rhs.systemId()
+ && lhs.publicId() == rhs.publicId());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamNotationDeclaration)
};
-Q_DECLARE_TYPEINFO(QXmlStreamNotationDeclaration, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamNotationDeclaration, Q_RELOCATABLE_TYPE);
typedef QList<QXmlStreamNotationDeclaration> QXmlStreamNotationDeclarations;
class Q_CORE_EXPORT QXmlStreamEntityDeclaration {
- QXmlStreamStringRef m_name, m_notationName, m_systemId, m_publicId, m_value;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_name, m_notationName, m_systemId, m_publicId, m_value;
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamEntityDeclaration();
- inline QStringRef name() const { return m_name; }
- inline QStringRef notationName() const { return m_notationName; }
- inline QStringRef systemId() const { return m_systemId; }
- inline QStringRef publicId() const { return m_publicId; }
- inline QStringRef value() const { return m_value; }
- inline bool operator==(const QXmlStreamEntityDeclaration &other) const {
- return (name() == other.name()
- && notationName() == other.notationName()
- && systemId() == other.systemId()
- && publicId() == other.publicId()
- && value() == other.value());
- }
+ inline QStringView name() const { return m_name; }
+ inline QStringView notationName() const { return m_notationName; }
+ inline QStringView systemId() const { return m_systemId; }
+ inline QStringView publicId() const { return m_publicId; }
+ inline QStringView value() const { return m_value; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamEntityDeclaration &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamEntityDeclaration &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+
+private:
+ friend bool comparesEqual(const QXmlStreamEntityDeclaration &lhs,
+ const QXmlStreamEntityDeclaration &rhs) noexcept
+ {
+ return (lhs.name() == rhs.name()
+ && lhs.notationName() == rhs.notationName()
+ && lhs.systemId() == rhs.systemId()
+ && lhs.publicId() == rhs.publicId()
+ && lhs.value() == rhs.value());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamEntityDeclaration)
};
-Q_DECLARE_TYPEINFO(QXmlStreamEntityDeclaration, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamEntityDeclaration, Q_RELOCATABLE_TYPE);
typedef QList<QXmlStreamEntityDeclaration> QXmlStreamEntityDeclarations;
class Q_CORE_EXPORT QXmlStreamEntityResolver
{
+ Q_DISABLE_COPY_MOVE(QXmlStreamEntityResolver)
public:
+ QXmlStreamEntityResolver() = default;
virtual ~QXmlStreamEntityResolver();
virtual QString resolveEntity(const QString& publicId, const QString& systemId);
virtual QString resolveUndeclaredEntity(const QString &name);
};
-#ifndef QT_NO_XMLSTREAMREADER
-class Q_CORE_EXPORT QXmlStreamReader {
+#if QT_CONFIG(xmlstreamreader)
+class Q_CORE_EXPORT QXmlStreamReader
+{
QDOC_PROPERTY(bool namespaceProcessing READ namespaceProcessing WRITE setNamespaceProcessing)
public:
enum TokenType {
@@ -248,16 +236,27 @@ public:
QXmlStreamReader();
explicit QXmlStreamReader(QIODevice *device);
+#if QT_CORE_REMOVED_SINCE(6, 5)
explicit QXmlStreamReader(const QByteArray &data);
explicit QXmlStreamReader(const QString &data);
explicit QXmlStreamReader(const char * data);
+#endif // QT_CORE_REMOVED_SINCE(6, 5)
+ Q_WEAK_OVERLOAD
+ explicit QXmlStreamReader(const QByteArray &data)
+ : QXmlStreamReader(data, PrivateConstructorTag{}) { }
+ explicit QXmlStreamReader(QAnyStringView data);
~QXmlStreamReader();
void setDevice(QIODevice *device);
QIODevice *device() const;
+#if QT_CORE_REMOVED_SINCE(6, 5)
void addData(const QByteArray &data);
void addData(const QString &data);
void addData(const char *data);
+#endif // QT_CORE_REMOVED_SINCE(6, 5)
+ Q_WEAK_OVERLOAD
+ void addData(const QByteArray &data) { addDataImpl(data); }
+ void addData(QAnyStringView data);
void clear();
@@ -286,8 +285,9 @@ public:
inline bool isProcessingInstruction() const { return tokenType() == ProcessingInstruction; }
bool isStandaloneDocument() const;
- QStringRef documentVersion() const;
- QStringRef documentEncoding() const;
+ bool hasStandaloneDeclaration() const;
+ QStringView documentVersion() const;
+ QStringView documentEncoding() const;
qint64 lineNumber() const;
qint64 columnNumber() const;
@@ -302,24 +302,24 @@ public:
};
QString readElementText(ReadElementTextBehaviour behaviour = ErrorOnUnexpectedElement);
- QStringRef name() const;
- QStringRef namespaceUri() const;
- QStringRef qualifiedName() const;
- QStringRef prefix() const;
+ QStringView name() const;
+ QStringView namespaceUri() const;
+ QStringView qualifiedName() const;
+ QStringView prefix() const;
- QStringRef processingInstructionTarget() const;
- QStringRef processingInstructionData() const;
+ QStringView processingInstructionTarget() const;
+ QStringView processingInstructionData() const;
- QStringRef text() const;
+ QStringView text() const;
QXmlStreamNamespaceDeclarations namespaceDeclarations() const;
void addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaraction);
void addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclaractions);
QXmlStreamNotationDeclarations notationDeclarations() const;
QXmlStreamEntityDeclarations entityDeclarations() const;
- QStringRef dtdName() const;
- QStringRef dtdPublicId() const;
- QStringRef dtdSystemId() const;
+ QStringView dtdName() const;
+ QStringView dtdPublicId() const;
+ QStringView dtdSystemId() const;
int entityExpansionLimit() const;
void setEntityExpansionLimit(int limit);
@@ -344,14 +344,18 @@ public:
QXmlStreamEntityResolver *entityResolver() const;
private:
+ struct PrivateConstructorTag { };
+ QXmlStreamReader(const QByteArray &data, PrivateConstructorTag);
+ void addDataImpl(const QByteArray &data);
+
Q_DISABLE_COPY(QXmlStreamReader)
Q_DECLARE_PRIVATE(QXmlStreamReader)
QScopedPointer<QXmlStreamReaderPrivate> d_ptr;
};
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
-#ifndef QT_NO_XMLSTREAMWRITER
+#if QT_CONFIG(xmlstreamwriter)
class QXmlStreamWriterPrivate;
@@ -375,11 +379,17 @@ public:
void setAutoFormattingIndent(int spacesOrTabs);
int autoFormattingIndent() const;
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeAttribute(const QString &qualifiedName, const QString &value);
void writeAttribute(const QString &namespaceUri, const QString &name, const QString &value);
+#endif
+ void writeAttribute(QAnyStringView qualifiedName, QAnyStringView value);
+ void writeAttribute(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView value);
+
void writeAttribute(const QXmlStreamAttribute& attribute);
void writeAttributes(const QXmlStreamAttributes& attributes);
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeCDATA(const QString &text);
void writeCharacters(const QString &text);
void writeComment(const QString &text);
@@ -391,22 +401,47 @@ public:
void writeTextElement(const QString &qualifiedName, const QString &text);
void writeTextElement(const QString &namespaceUri, const QString &name, const QString &text);
+#endif
+ void writeCDATA(QAnyStringView text);
+ void writeCharacters(QAnyStringView text);
+ void writeComment(QAnyStringView text);
+
+ void writeDTD(QAnyStringView dtd);
+
+ void writeEmptyElement(QAnyStringView qualifiedName);
+ void writeEmptyElement(QAnyStringView namespaceUri, QAnyStringView name);
+
+ void writeTextElement(QAnyStringView qualifiedName, QAnyStringView text);
+ void writeTextElement(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView text);
+
void writeEndDocument();
void writeEndElement();
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeEntityReference(const QString &name);
- void writeNamespace(const QString &namespaceUri, const QString &prefix = QString());
+ void writeNamespace(const QString &namespaceUri, const QString &prefix);
void writeDefaultNamespace(const QString &namespaceUri);
- void writeProcessingInstruction(const QString &target, const QString &data = QString());
+ void writeProcessingInstruction(const QString &target, const QString &data);
+#endif
+ void writeEntityReference(QAnyStringView name);
+ void writeNamespace(QAnyStringView namespaceUri, QAnyStringView prefix = {});
+ void writeDefaultNamespace(QAnyStringView namespaceUri);
+ void writeProcessingInstruction(QAnyStringView target, QAnyStringView data = {});
void writeStartDocument();
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeStartDocument(const QString &version);
void writeStartDocument(const QString &version, bool standalone);
void writeStartElement(const QString &qualifiedName);
void writeStartElement(const QString &namespaceUri, const QString &name);
+#endif
+ void writeStartDocument(QAnyStringView version);
+ void writeStartDocument(QAnyStringView version, bool standalone);
+ void writeStartElement(QAnyStringView qualifiedName);
+ void writeStartElement(QAnyStringView namespaceUri, QAnyStringView name);
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
void writeCurrentToken(const QXmlStreamReader &reader);
#endif
@@ -417,9 +452,10 @@ private:
Q_DECLARE_PRIVATE(QXmlStreamWriter)
QScopedPointer<QXmlStreamWriterPrivate> d_ptr;
};
-#endif // QT_NO_XMLSTREAMWRITER
+#endif // feature xmlstreamwriter
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAM
+#endif // feature xmlstream
+
#endif // QXMLSTREAM_H
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index c9239eb410..a29ee656e9 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//
// W A R N I N G
@@ -50,606 +14,128 @@
#include <QtCore/private/qglobal_p.h>
#include <qstringconverter.h>
+#include <qxmlstream.h>
+#include "qxmlstreamgrammar_p.h"
+#include <QtCore/qhash.h>
+#include <QCoreApplication> // Q_DECLARE_TR_FUNCTIONS
+
+
+#include <memory>
+#include <optional>
-// This file was generated by qlalr - DO NOT EDIT!
#ifndef QXMLSTREAM_P_H
#define QXMLSTREAM_P_H
-#if defined(ERROR)
-# undef ERROR
-#endif
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
-class QXmlStreamReader_Table
+class XmlStringRef
{
public:
- enum VariousConstants {
- EOF_SYMBOL = 0,
- AMPERSAND = 5,
- ANY = 41,
- ATTLIST = 31,
- BANG = 25,
- CDATA = 47,
- CDATA_START = 28,
- COLON = 17,
- COMMA = 19,
- DASH = 20,
- DBLQUOTE = 8,
- DIGIT = 27,
- DOCTYPE = 29,
- DOT = 23,
- ELEMENT = 30,
- EMPTY = 40,
- ENTITIES = 51,
- ENTITY = 32,
- ENTITY_DONE = 45,
- EQ = 14,
- ERROR = 43,
- FIXED = 39,
- HASH = 6,
- ID = 48,
- IDREF = 49,
- IDREFS = 50,
- IMPLIED = 38,
- LANGLE = 3,
- LBRACK = 9,
- LETTER = 26,
- LPAREN = 11,
- NDATA = 36,
- NMTOKEN = 52,
- NMTOKENS = 53,
- NOTATION = 33,
- NOTOKEN = 1,
- PARSE_ENTITY = 44,
- PCDATA = 42,
- PERCENT = 15,
- PIPE = 13,
- PLUS = 21,
- PUBLIC = 35,
- QUESTIONMARK = 24,
- QUOTE = 7,
- RANGLE = 4,
- RBRACK = 10,
- REQUIRED = 37,
- RPAREN = 12,
- SEMICOLON = 18,
- SHIFT_THERE = 56,
- SLASH = 16,
- SPACE = 2,
- STAR = 22,
- SYSTEM = 34,
- UNRESOLVED_ENTITY = 46,
- VERSION = 55,
- XML = 54,
-
- ACCEPT_STATE = 416,
- RULE_COUNT = 270,
- STATE_COUNT = 427,
- TERMINAL_COUNT = 57,
- NON_TERMINAL_COUNT = 84,
-
- GOTO_INDEX_OFFSET = 427,
- GOTO_INFO_OFFSET = 1017,
- GOTO_CHECK_OFFSET = 1017
- };
-
- static const char *const spell [];
- static const short lhs [];
- static const short rhs [];
- static const short goto_default [];
- static const short action_default [];
- static const short action_index [];
- static const short action_info [];
- static const short action_check [];
-
- static inline int nt_action (int state, int nt)
- {
- const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
- if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
- return goto_default [nt];
-
- return action_info [GOTO_INFO_OFFSET + yyn];
- }
-
- static inline int t_action (int state, int token)
- {
- const int yyn = action_index [state] + token;
-
- if (yyn < 0 || action_check [yyn] != token)
- return - action_default [state];
-
- return action_info [yyn];
- }
+ const QString *m_string = nullptr;
+ qsizetype m_pos = 0;
+ qsizetype m_size = 0;
+
+ constexpr XmlStringRef() = default;
+ constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
+ : m_string(string), m_pos(pos), m_size((Q_ASSERT(length >= 0), length))
+ {
+ }
+ XmlStringRef(const QString *string)
+ : XmlStringRef(string, 0, string->size())
+ {
+ }
+
+ operator QXmlString() const {
+ if (!m_string)
+ return QXmlString();
+ QStringPrivate d = m_string->data_ptr();
+ d.setBegin(d.data() + m_pos);
+ d.size = m_size;
+ return QXmlString(std::move(d));
+ }
+
+ void clear() { m_string = nullptr; m_pos = 0; m_size= 0; }
+ QStringView view() const { return m_string ? QStringView(m_string->data() + m_pos, m_size) : QStringView(); }
+ bool isEmpty() const { return m_size == 0; }
+ bool isNull() const { return !m_string; }
+ QString toString() const { return view().toString(); }
+
+ using value_type = QStringView::value_type;
+ using size_type = QStringView::size_type;
+ using difference_type = QStringView::difference_type;
+ using pointer = QStringView::pointer;
+ using const_pointer = QStringView::const_pointer;
+ using reference = QStringView::reference;
+ using const_reference = QStringView::const_reference;
+ using iterator = QStringView::iterator;
+ using const_iterator = QStringView::const_iterator;
+ using reverse_iterator = QStringView::reverse_iterator;
+ using const_reverse_iterator = QStringView::const_reverse_iterator;
+
+#define MAKE_MEMBER(name) \
+ auto name () const noexcept { return view(). name (); }
+ MAKE_MEMBER(data)
+ MAKE_MEMBER(size)
+ MAKE_MEMBER(empty)
+ MAKE_MEMBER(begin)
+ MAKE_MEMBER(end)
+ MAKE_MEMBER(cbegin)
+ MAKE_MEMBER(cend)
+ MAKE_MEMBER(rbegin)
+ MAKE_MEMBER(rend)
+ MAKE_MEMBER(crbegin)
+ MAKE_MEMBER(crend)
+#undef MAKE_MEMBER
+
+#define MAKE_OP(op) \
+ friend auto operator op(const XmlStringRef &lhs, const XmlStringRef &rhs) noexcept { return lhs.view() op rhs.view(); } \
+ /*end*/
+ MAKE_OP(==)
+ MAKE_OP(!=)
+ MAKE_OP(<=)
+ MAKE_OP(>=)
+ MAKE_OP(<)
+ MAKE_OP(>)
+#undef MAKE_OP
+#define MAKE_OP(op) \
+ friend auto operator op(const XmlStringRef &lhs, QStringView rhs) noexcept { return lhs.view() op rhs; } \
+ friend auto operator op(QStringView lhs, const XmlStringRef &rhs) noexcept { return lhs op rhs.view(); } \
+ /*end*/
+ MAKE_OP(==)
+ MAKE_OP(!=)
+ MAKE_OP(<=)
+ MAKE_OP(>=)
+ MAKE_OP(<)
+ MAKE_OP(>)
+#undef MAKE_OP
};
+}
+
+using namespace QtPrivate;
+
+template <typename T> class QXmlStreamSimpleStack
+{
+ Q_DISABLE_COPY_MOVE(QXmlStreamSimpleStack)
-const char *const QXmlStreamReader_Table::spell [] = {
- "end of file", nullptr, " ", "<", ">", "&", "#", "\'", "\"", "[",
- "]", "(", ")", "|", "=", "%", "/", ":", ";", ",",
- "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE",
- "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED",
- "EMPTY", "ANY", "PCDATA", nullptr, nullptr, nullptr, nullptr, "CDATA", "ID", "IDREF",
- "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", nullptr};
-
-const short QXmlStreamReader_Table::lhs [] = {
- 57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
- 67, 68, 64, 72, 72, 72, 75, 66, 66, 66,
- 66, 79, 78, 80, 80, 80, 80, 80, 80, 80,
- 81, 81, 81, 81, 81, 81, 81, 87, 83, 88,
- 88, 88, 88, 91, 92, 93, 93, 93, 93, 94,
- 94, 96, 96, 96, 97, 97, 98, 98, 99, 99,
- 100, 100, 89, 89, 95, 90, 101, 101, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 104, 105,
- 105, 105, 105, 107, 108, 109, 109, 84, 84, 110,
- 110, 112, 112, 85, 85, 85, 65, 65, 76, 114,
- 63, 115, 116, 86, 86, 86, 117, 117, 117, 117,
- 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
- 117, 117, 117, 117, 117, 117, 117, 117, 117, 118,
- 118, 119, 119, 119, 119, 119, 119, 119, 119, 122,
- 70, 70, 70, 70, 123, 124, 123, 124, 123, 124,
- 123, 124, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 125, 73, 113, 113, 113, 113,
- 127, 128, 127, 128, 127, 128, 127, 128, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 106, 106, 106, 106, 131, 132, 131,
- 132, 131, 131, 132, 132, 133, 133, 133, 133, 135,
- 71, 71, 71, 136, 136, 137, 62, 60, 61, 138,
- 121, 82, 130, 134, 120, 139, 139, 139, 139, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 74,
- 69, 69, 77, 111, 102, 102, 102, 102, 102, 140};
-
-const short QXmlStreamReader_Table::rhs [] = {
- 2, 1, 4, 2, 2, 2, 2, 2, 2, 0,
- 1, 1, 9, 2, 4, 0, 4, 4, 6, 6,
- 4, 1, 3, 1, 1, 1, 2, 2, 2, 0,
- 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 1, 1, 1, 1, 2, 1, 1, 1, 0, 2,
- 2, 2, 6, 6, 1, 5, 1, 5, 3, 5,
- 0, 1, 6, 8, 4, 2, 1, 5, 1, 1,
- 1, 1, 1, 1, 1, 1, 6, 7, 1, 2,
- 2, 1, 4, 3, 3, 1, 2, 5, 6, 4,
- 6, 3, 5, 5, 3, 4, 4, 5, 2, 3,
- 2, 2, 4, 5, 5, 7, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
- 2, 2, 3, 3, 2, 2, 2, 2, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 2, 3, 3,
- 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 2, 3, 3, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 5,
- 0, 1, 3, 1, 3, 2, 4, 3, 5, 1,
- 3, 3, 3, 3, 4, 1, 1, 2, 2, 2,
- 4, 2, 2, 2, 2, 2, 2, 2, 0, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 2};
-
-const short QXmlStreamReader_Table::action_default [] = {
- 10, 259, 0, 2, 1, 0, 125, 117, 119, 120,
- 127, 129, 123, 11, 114, 108, 0, 109, 128, 111,
- 115, 113, 121, 124, 126, 107, 110, 112, 118, 116,
- 131, 122, 240, 12, 254, 136, 250, 253, 0, 130,
- 140, 257, 16, 252, 138, 137, 0, 256, 139, 259,
- 231, 258, 255, 0, 0, 264, 0, 247, 246, 0,
- 249, 248, 245, 241, 99, 263, 0, 236, 0, 0,
- 260, 97, 98, 101, 0, 132, 134, 133, 135, 0,
- 0, 261, 0, 0, 176, 0, 173, 165, 167, 168,
- 142, 154, 171, 162, 156, 157, 153, 159, 163, 161,
- 169, 172, 152, 155, 158, 160, 166, 164, 174, 170,
- 150, 175, 0, 144, 148, 146, 151, 141, 149, 0,
- 147, 143, 145, 0, 15, 14, 262, 0, 22, 21,
- 261, 30, 0, 20, 0, 0, 32, 37, 31, 0,
- 33, 261, 0, 34, 0, 24, 0, 35, 0, 26,
- 36, 25, 0, 242, 41, 40, 261, 43, 49, 261,
- 42, 0, 44, 261, 49, 261, 0, 261, 0, 49,
- 0, 48, 46, 47, 51, 52, 261, 261, 0, 57,
- 261, 54, 261, 0, 58, 0, 55, 261, 53, 261,
- 0, 56, 65, 0, 261, 61, 261, 0, 59, 62,
- 63, 0, 261, 0, 0, 60, 64, 45, 50, 66,
- 0, 39, 0, 0, 261, 0, 94, 95, 0, 0,
- 0, 0, 261, 0, 210, 201, 203, 205, 178, 190,
- 208, 199, 193, 191, 194, 189, 196, 198, 206, 209,
- 188, 192, 195, 197, 202, 200, 204, 207, 211, 213,
- 212, 186, 0, 0, 243, 180, 184, 182, 0, 0,
- 93, 187, 177, 185, 0, 183, 179, 181, 92, 0,
- 96, 0, 0, 0, 0, 0, 261, 86, 261, 0,
- 262, 0, 87, 0, 89, 69, 74, 73, 70, 71,
- 72, 261, 75, 76, 0, 0, 0, 269, 268, 266,
- 267, 265, 67, 261, 0, 261, 0, 0, 68, 77,
- 261, 0, 261, 0, 0, 78, 0, 79, 0, 82,
- 85, 0, 0, 215, 225, 224, 0, 227, 229, 228,
- 226, 0, 244, 217, 221, 219, 223, 214, 222, 0,
- 220, 216, 218, 0, 81, 80, 0, 83, 0, 84,
- 88, 100, 0, 38, 0, 0, 0, 0, 91, 90,
- 0, 103, 23, 27, 29, 28, 0, 0, 261, 262,
- 0, 261, 0, 106, 105, 261, 0, 104, 102, 0,
- 0, 18, 261, 17, 0, 19, 0, 0, 251, 0,
- 261, 0, 239, 0, 232, 238, 0, 237, 234, 261,
- 261, 262, 233, 235, 0, 261, 0, 230, 261, 0,
- 261, 0, 231, 0, 0, 13, 270, 9, 5, 8,
- 4, 0, 7, 259, 6, 0, 3};
-
-const short QXmlStreamReader_Table::goto_default [] = {
- 2, 4, 3, 49, 388, 43, 37, 52, 47, 41,
- 249, 53, 127, 84, 393, 81, 85, 126, 42, 46,
- 169, 130, 131, 146, 145, 149, 138, 136, 140, 147,
- 139, 159, 160, 157, 168, 167, 209, 165, 164, 166,
- 187, 180, 196, 200, 303, 302, 295, 321, 320, 319,
- 279, 277, 278, 142, 56, 141, 222, 38, 34, 148,
- 39, 48, 40, 248, 45, 36, 119, 112, 330, 111,
- 264, 252, 251, 250, 339, 326, 325, 329, 398, 399,
- 50, 51, 59, 0};
-
-const short QXmlStreamReader_Table::action_index [] = {
- -21, -57, 33, 119, 960, 70, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, 105, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, 40, -57,
- 795, -57, 47, -57, -57, -57, 107, -57, -57, -57,
- 84, -57, -57, -38, 80, -57, 12, -57, -57, 97,
- -57, -57, -57, -57, -57, -57, 13, -57, 56, 34,
- -57, -57, -57, -57, 51, -57, -57, -57, -57, 53,
- 57, 84, 300, 255, -57, 84, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, 355, -57, -57, -57, -57, -57, -57, 326,
- -57, -57, -57, 48, -57, -57, -57, 50, -57, -57,
- 84, 155, 32, -57, 38, 22, -57, -57, -57, 115,
- -57, 35, 156, -57, 173, -57, 245, -57, 44, -57,
- -57, -57, 16, -57, -57, -57, 29, -57, 116, 29,
- -57, 133, -57, 29, 129, 84, 15, 29, -22, 121,
- 74, -57, -57, -57, -57, 82, 29, 29, 88, -57,
- 29, 7, 29, 86, -57, 83, -57, 27, 19, 26,
- 94, -57, -57, 106, 29, 3, 29, -8, -57, -57,
- -57, 104, 29, -6, -7, -57, -57, -57, -57, -57,
- 17, -57, -2, 11, 29, 18, -57, -57, 850, 65,
- 465, 67, 84, 135, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, 630, 24, -57, -57, -57, -57, 84, 76,
- -57, -57, -57, -57, 740, -57, -57, -57, -57, 39,
- -57, 23, 21, 14, 78, 22, 84, -57, 84, 184,
- 20, 31, -57, 41, -57, -57, -57, -57, -57, -57,
- -57, 84, -57, -57, 36, 126, 162, -57, -57, -57,
- -57, -57, -57, 29, 79, 29, 29, 160, -57, -57,
- 29, 145, 29, 75, 29, -57, 575, -57, 410, -57,
- -57, 110, 64, -57, -57, -57, 685, -57, -57, -57,
- -57, -17, -57, -57, -57, -57, -57, -57, -57, 520,
- -57, -57, -57, 29, -57, -57, 61, -57, 29, -57,
- -57, -57, 29, -57, 29, 29, -15, 29, -57, -57,
- 29, -57, -57, -57, -57, -57, 95, 43, 29, 45,
- 9, 29, 10, -57, -57, 29, 2, -57, -57, -24,
- 190, -57, 29, -57, 1, -57, 905, 150, -57, -26,
- 29, 0, -57, 109, -26, -57, 8, -57, -57, 29,
- 29, -19, -57, -57, -11, 29, 59, -57, 29, -5,
- 29, 103, 29, -16, 6, -57, -57, -57, -57, -57,
- -57, 69, -57, -57, -57, 905, -57,
-
- -84, -84, -84, 204, 75, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, 7, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- 101, -84, -84, -84, -84, -84, -84, -84, -84, 64,
- 54, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, 68, -84, 30, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- 32, -84, -16, -7, -84, 42, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, 45, -84, -84, -84, -84, -84, -84, 44,
- -84, -84, -84, 33, -84, -84, -84, -84, -84, -84,
- 36, 108, -84, -84, -84, 69, -84, -84, -84, 62,
- -84, 63, -84, -84, -84, -84, 118, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -2, -84, -84, -10,
- -84, -84, -84, 25, -21, 11, -84, 20, -84, -25,
- -84, -84, -84, -84, -84, -84, 1, 2, -36, -84,
- -9, -84, 5, -13, -84, -8, -84, 6, -84, 8,
- 12, -84, -84, -84, 23, -84, 4, -1, -84, -84,
- -84, -84, 0, -84, -14, -84, -84, -84, -84, -84,
- -84, -84, 55, -84, 58, -84, -84, -84, -84, 53,
- 47, 123, 67, 66, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -15, -84, -84, -84, -84, -84, 41, 40,
- -84, -84, -84, -84, -46, -84, -84, -84, -84, -84,
- -84, 35, -84, 34, 37, 18, 70, -84, 89, -84,
- 43, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, 48, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, 31, -84, 29, 27, 17, -84, -84,
- 38, 24, 39, -84, 49, -84, 71, -84, 93, -84,
- -84, -84, -12, -84, -84, -84, 94, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, 78,
- -84, -84, -84, 50, -84, -84, 46, -84, 56, -84,
- -84, -84, 60, -84, 61, 59, 51, 57, -84, -84,
- 14, -84, -84, -84, -84, -84, -11, -6, 72, -5,
- -84, -3, -84, -84, -84, 52, -84, -84, -84, -20,
- 77, -84, 21, -84, -84, -84, 76, 16, -84, 19,
- 26, -84, -84, -84, 10, -84, -84, -84, -84, 80,
- 13, 73, -84, -84, -84, 22, -27, -84, 9, -84,
- 28, 15, 82, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, 3, -84, 98, -84};
-
-const short QXmlStreamReader_Table::action_info [] = {
- 65, 332, 65, 405, 392, 385, 377, 65, 414, 410,
- 415, 55, 397, 374, 373, 217, 206, 408, 65, 65,
- 207, 211, 216, 1, 55, 199, 182, 192, 70, 70,
- 63, 70, 189, 416, 153, 350, 133, 70, 72, 55,
- 65, 351, 254, 270, 73, 284, 65, 310, 55, 65,
- 83, 82, 83, 82, 129, 83, 82, 54, 70, 128,
- 83, 82, 66, 64, 83, 82, 318, 316, 318, 316,
- 54, 212, 83, 82, 83, 82, 54, 55, 367, 366,
- 69, 80, 79, 83, 82, 163, 70, 314, 305, 272,
- 55, 306, 305, 354, 163, 177, 55, 163, 379, 163,
- 65, 176, 83, 82, 55, 163, 58, 57, 0, 65,
- 83, 82, 65, 395, 65, 62, 203, 202, 195, 194,
- 65, 417, 16, 61, 60, 396, 156, 272, 0, 66,
- 64, 65, 317, 318, 316, 378, 379, 171, 173, 162,
- 172, 54, 171, 173, 163, 172, 0, 345, 344, 343,
- 171, 173, 0, 172, 0, 155, 154, 70, 134, 65,
- 0, 55, 297, 220, 218, 298, 389, 0, 300, 0,
- 135, 301, 299, 33, 66, 64, 65, 297, 0, 297,
- 298, 0, 298, 300, 0, 300, 301, 299, 301, 299,
- 221, 219, 70, 272, 381, 291, 0, 0, 0, 128,
- 13, 0, 0, 273, 271, 274, 275, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 287, 294, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 285, 288, 289, 290, 286, 292, 293, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 70, 134, 0,
- 0, 0, 0, 0, 0, 362, 0, 108, 0, 103,
- 135, 94, 117, 116, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 0, 94, 102, 90, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 108, 0,
- 103, 0, 94, 121, 120, 95, 104, 97, 105, 99,
- 93, 98, 107, 87, 106, 88, 89, 100, 109, 92,
- 101, 86, 96, 91, 0, 0, 0, 108, 0, 103,
- 0, 94, 114, 113, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 322, 94, 337, 336, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 246, 233, 241,
- 223, 232, 262, 261, 234, 242, 236, 243, 237, 231,
- 0, 245, 225, 244, 226, 227, 238, 247, 230, 239,
- 224, 235, 229, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 322, 94, 341, 340, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 108, 0, 103,
- 322, 94, 324, 323, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 256, 255, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 108, 0, 103,
- 322, 94, 334, 333, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 266, 265, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 30, 0, 25,
- 74, 15, 24, 10, 17, 26, 19, 27, 21, 14,
- 20, 29, 7, 28, 8, 9, 22, 31, 12, 23,
- 6, 18, 11, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 240, 228, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 30, 387, 25,
- 5, 15, 24, 10, 17, 26, 19, 27, 21, 14,
- 20, 29, 7, 28, 8, 9, 22, 31, 12, 23,
- 6, 18, 11, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 32, 0, 0, 0, 0, 0, 0, 0, 33,
- 0, 0, 30, 16, 25, 5, 15, 24, 10, 17,
- 26, 19, 27, 21, 14, 20, 29, 7, 28, 8,
- 9, 22, 31, 12, 23, 6, 18, 11, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 32, 0, 0, 0,
- 0, 0, 0, 0, 33, 0, 0,
-
- 380, 179, 210, 181, 425, 368, 205, 375, 371, 372,
- 161, 208, 204, 178, 185, 174, 201, 183, 188, 198,
- 190, 409, 407, 175, 184, 404, 267, 67, 412, 186,
- 400, 361, 193, 384, 406, 197, 67, 170, 391, 390,
- 411, 307, 331, 304, 309, 125, 124, 71, 132, 191,
- 311, 313, 110, 260, 352, 276, 0, 257, 259, 123,
- 296, 118, 308, 348, 376, 386, 315, 346, 312, 258,
- 215, 394, 360, 349, 358, 213, 359, 353, 356, 269,
- 0, 328, 281, 0, 370, 44, 44, 280, 328, 369,
- 0, 355, 402, 400, 383, 347, 413, 401, 382, 394,
- 158, 283, 426, 328, 328, 357, 280, 0, 44, 214,
- 0, 76, 122, 115, 137, 0, 150, 0, 143, 263,
- 253, 0, 68, 152, 137, 151, 150, 144, 143, 0,
- 0, 0, 0, 0, 327, 365, 268, 144, 35, 35,
- 282, 327, 363, 364, 0, 0, 0, 0, 0, 0,
- 0, 403, 0, 0, 342, 0, 327, 327, 0, 0,
- 0, 35, 78, 0, 75, 77, 0, 0, 0, 338,
- 335, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 423, 0, 420,
- 418, 424, 422, 419, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 421, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0};
-
-const short QXmlStreamReader_Table::action_check [] = {
- 26, 18, 26, 14, 4, 4, 4, 26, 24, 14,
- 4, 26, 4, 4, 4, 4, 22, 55, 26, 26,
- 42, 4, 4, 44, 26, 22, 19, 12, 2, 2,
- 18, 2, 13, 0, 18, 4, 4, 2, 4, 26,
- 26, 20, 18, 4, 4, 4, 26, 11, 26, 26,
- 7, 8, 7, 8, 4, 7, 8, 6, 2, 9,
- 7, 8, 24, 25, 7, 8, 7, 8, 7, 8,
- 6, 36, 7, 8, 7, 8, 6, 26, 34, 35,
- 24, 34, 35, 7, 8, 11, 2, 12, 13, 20,
- 26, 12, 13, 15, 11, 13, 26, 11, 29, 11,
- 26, 19, 7, 8, 26, 11, 26, 27, -1, 26,
- 7, 8, 26, 4, 26, 18, 12, 13, 12, 13,
- 26, 2, 3, 26, 27, 16, 11, 20, -1, 24,
- 25, 26, 6, 7, 8, 28, 29, 21, 22, 6,
- 24, 6, 21, 22, 11, 24, -1, 37, 38, 39,
- 21, 22, -1, 24, -1, 40, 41, 2, 3, 26,
- -1, 26, 17, 7, 8, 20, 16, -1, 23, -1,
- 15, 26, 27, 54, 24, 25, 26, 17, -1, 17,
- 20, -1, 20, 23, -1, 23, 26, 27, 26, 27,
- 34, 35, 2, 20, 4, 11, -1, -1, -1, 9,
- 45, -1, -1, 30, 31, 32, 33, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 32, 33, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 47, 48, 49, 50, 51, 52, 53, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, -1,
- -1, -1, -1, -1, -1, 10, -1, 2, -1, 4,
- 15, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, -1, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 2, -1,
- 4, -1, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, -1, -1, -1, 2, -1, 4,
- -1, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- -1, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, 46, -1, -1, -1, -1, -1, -1, -1, 54,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, 46, -1, -1, -1,
- -1, -1, -1, -1, 54, -1, -1,
-
- 20, 37, 12, 12, 1, 16, 20, 13, 13, 12,
- 12, 36, 12, 12, 12, 36, 12, 12, 12, 20,
- 12, 12, 49, 12, 37, 12, 72, 20, 13, 37,
- 20, 17, 12, 12, 12, 12, 20, 12, 12, 20,
- 12, 12, 54, 12, 17, 13, 13, 17, 12, 37,
- 12, 12, 68, 13, 20, 20, -1, 72, 17, 17,
- 12, 68, 45, 20, 12, 1, 17, 17, 44, 16,
- 12, 17, 54, 17, 17, 12, 17, 17, 17, 12,
- -1, 10, 12, -1, 12, 10, 10, 17, 10, 17,
- -1, 54, 12, 20, 17, 49, 14, 17, 21, 17,
- 38, 12, 4, 10, 10, 54, 17, -1, 10, 54,
- -1, 10, 68, 68, 6, -1, 8, -1, 10, 72,
- 54, -1, 54, 54, 6, 17, 8, 19, 10, -1,
- -1, -1, -1, -1, 63, 17, 13, 19, 63, 63,
- 51, 63, 24, 25, -1, -1, -1, -1, -1, -1,
- -1, 78, -1, -1, 76, -1, 63, 63, -1, -1,
- -1, 63, 61, -1, 63, 64, -1, -1, -1, 76,
- 76, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3, -1, 5,
- 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 19, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1};
-
-
-template <typename T> class QXmlStreamSimpleStack {
T *data;
qsizetype tos, cap;
public:
- inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
- inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
+ inline QXmlStreamSimpleStack()
+ : data(nullptr), tos(-1), cap(0)
+ {}
+ inline ~QXmlStreamSimpleStack()
+ {
+ if (data) {
+ std::destroy_n(data, size());
+ free(data);
+ }
+ }
- inline void reserve(qsizetype extraCapacity) {
+ inline void reserve(qsizetype extraCapacity)
+ {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
@@ -658,11 +144,11 @@ public:
}
}
- inline T &push() { reserve(1); return data[++tos]; }
- inline T &rawPush() { return data[++tos]; }
+ inline T &push() { reserve(1); return rawPush(); }
+ inline T &rawPush() { return *new (data + (++tos)) T; }
inline const T &top() const { return data[tos]; }
inline T &top() { return data[tos]; }
- inline T &pop() { return data[tos--]; }
+ inline T pop() { T t = std::move(data[tos]); std::destroy_at(data + tos); --tos; return t; }
inline T &operator[](qsizetype index) { return data[index]; }
inline const T &at(qsizetype index) const { return data[index]; }
inline qsizetype size() const { return tos + 1; }
@@ -680,7 +166,6 @@ public:
const T *cend() const { return end(); }
};
-
class QXmlStream
{
Q_DECLARE_TR_FUNCTIONS(QXmlStream)
@@ -690,16 +175,16 @@ class QXmlStreamPrivateTagStack {
public:
struct NamespaceDeclaration
{
- QStringRef prefix;
- QStringRef namespaceUri;
+ XmlStringRef prefix;
+ XmlStringRef namespaceUri;
};
struct Tag
{
- QStringRef name;
- QStringRef qualifiedName;
+ XmlStringRef name;
+ XmlStringRef qualifiedName;
NamespaceDeclaration namespaceDeclaration;
- int tagStackStringStorageSize;
+ qsizetype tagStackStringStorageSize;
qsizetype namespaceDeclarationsSize;
};
@@ -707,32 +192,26 @@ public:
QXmlStreamPrivateTagStack();
QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
QString tagStackStringStorage;
- int tagStackStringStorageSize;
- int initialTagStackStringStorageSize;
+ qsizetype tagStackStringStorageSize;
+ qsizetype initialTagStackStringStorageSize;
bool tagsDone;
- inline QStringRef addToStringStorage(const QStringRef &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- inline QStringRef addToStringStorage(const QString &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- QStringRef addToStringStorage(QStringView s)
+ XmlStringRef addToStringStorage(QAnyStringView s)
{
- int pos = tagStackStringStorageSize;
- int sz = s.size();
+ qsizetype pos = tagStackStringStorageSize;
if (pos != tagStackStringStorage.size())
tagStackStringStorage.resize(pos);
- tagStackStringStorage.append(s.data(), sz);
+ s.visit([&](auto s) { tagStackStringStorage.append(s); });
+ qsizetype sz = (tagStackStringStorage.size() - pos);
tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
+ return XmlStringRef(&tagStackStringStorage, pos, sz);
}
QXmlStreamSimpleStack<Tag> tagStack;
- inline Tag &tagStack_pop() {
- Tag& tag = tagStack.pop();
+ inline Tag tagStack_pop() {
+ Tag tag = tagStack.pop();
tagStackStringStorageSize = tag.tagStackStringStorageSize;
namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
tagsDone = tagStack.isEmpty();
@@ -748,8 +227,8 @@ public:
class QXmlStreamEntityResolver;
-#ifndef QT_NO_XMLSTREAMREADER
-class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{
+class QXmlStreamReaderPrivate : public QXmlStreamGrammar, public QXmlStreamPrivateTagStack
+{
QXmlStreamReader *q_ptr;
Q_DECLARE_PUBLIC(QXmlStreamReader)
public:
@@ -762,14 +241,14 @@ public:
uchar firstByte;
qint64 nbytesread;
QString readBuffer;
- int readBufferPos;
+ qsizetype readBufferPos;
QXmlStreamSimpleStack<uint> putStack;
struct Entity {
Entity() = default;
Entity(const QString &name, const QString &value)
: name(name), value(value), external(false), unparsed(false), literal(false),
hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(QLatin1String name, QLatin1String value)
+ static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
{ Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; }
QString name, value;
uint external : 1;
@@ -783,10 +262,17 @@ public:
// are guaranteed to have the same lifetime as the referenced data:
QHash<QStringView, Entity> entityHash;
QHash<QStringView, Entity> parameterEntityHash;
- QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ struct QEntityReference
+ {
+ QHash<QStringView, Entity> *hash;
+ QStringView name;
+ };
+ QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
int entityExpansionLimit = 4096;
int entityLength = 0;
- inline bool referenceEntity(Entity &entity) {
+ inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
+ {
+ Q_ASSERT(hash);
if (entity.isCurrentlyReferenced) {
raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
return false;
@@ -800,7 +286,7 @@ public:
return false;
}
entity.isCurrentlyReferenced = true;
- entityReferenceStack.push() = &entity;
+ entityReferenceStack.push() = { hash, entity.name };
injectToken(ENTITY_DONE);
return true;
}
@@ -811,6 +297,17 @@ public:
QStringDecoder decoder;
bool atEnd;
+ enum class XmlContext
+ {
+ Prolog,
+ Body,
+ };
+
+ XmlContext currentContext = XmlContext::Prolog;
+ bool foundDTD = false;
+ bool isValidToken(QXmlStreamReader::TokenType type);
+ void checkToken();
+
/*!
\sa setType()
*/
@@ -827,7 +324,7 @@ public:
QXmlStreamAttributes attributes;
- QStringRef namespaceForPrefix(const QStringRef &prefix);
+ XmlStringRef namespaceForPrefix(QStringView prefix);
void resolveTag();
void resolvePublicNamespaces();
void resolveDtd();
@@ -835,36 +332,36 @@ public:
bool checkStartDocument();
void startDocument();
void parseError();
- void checkPublicLiteral(const QStringRef &publicId);
+ void checkPublicLiteral(QStringView publicId);
bool scanDtd;
- QStringRef lastAttributeValue;
+ XmlStringRef lastAttributeValue;
bool lastAttributeIsCData;
struct DtdAttribute {
- QStringRef tagName;
- QStringRef attributeQualifiedName;
- QStringRef attributePrefix;
- QStringRef attributeName;
- QStringRef defaultValue;
+ XmlStringRef tagName;
+ XmlStringRef attributeQualifiedName;
+ XmlStringRef attributePrefix;
+ XmlStringRef attributeName;
+ XmlStringRef defaultValue;
bool isCDATA;
bool isNamespaceAttribute;
};
QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
struct NotationDeclaration {
- QStringRef name;
- QStringRef publicId;
- QStringRef systemId;
+ XmlStringRef name;
+ XmlStringRef publicId;
+ XmlStringRef systemId;
};
QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
QXmlStreamNotationDeclarations publicNotationDeclarations;
QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
struct EntityDeclaration {
- QStringRef name;
- QStringRef notationName;
- QStringRef publicId;
- QStringRef systemId;
- QStringRef value;
+ XmlStringRef name;
+ XmlStringRef notationName;
+ XmlStringRef publicId;
+ XmlStringRef systemId;
+ XmlStringRef value;
bool parameter;
bool external;
inline void clear() {
@@ -879,12 +376,12 @@ public:
QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
QXmlStreamEntityDeclarations publicEntityDeclarations;
- QStringRef text;
+ XmlStringRef text;
- QStringRef prefix, namespaceUri, qualifiedName, name;
- QStringRef processingInstructionTarget, processingInstructionData;
- QStringRef dtdName, dtdPublicId, dtdSystemId;
- QStringRef documentVersion, documentEncoding;
+ XmlStringRef prefix, namespaceUri, qualifiedName, name;
+ XmlStringRef processingInstructionTarget, processingInstructionData;
+ XmlStringRef dtdName, dtdPublicId, dtdSystemId;
+ XmlStringRef documentVersion, documentEncoding;
uint isEmptyElement : 1;
uint isWhitespace : 1;
uint isCDATA : 1;
@@ -898,6 +395,7 @@ public:
uint hasExternalDtdSubset : 1;
uint lockEncoding : 1;
uint namespaceProcessing : 1;
+ uint hasStandalone : 1; // TODO: expose in public API
int resumeReduction;
void resume(int rule);
@@ -914,9 +412,9 @@ public:
int tos;
int stack_size;
struct Value {
- int pos;
- int len;
- int prefix;
+ qsizetype pos; // offset into textBuffer
+ qsizetype len; // length incl. prefix (if any)
+ qint16 prefix; // prefix of a name (as in "prefix:name") limited to 4k in fastScanName()
ushort c;
};
@@ -938,39 +436,39 @@ public:
};
QXmlStreamSimpleStack<Attribute> attributeStack;
- inline QStringRef symString(int index) {
+ inline XmlStringRef symString(int index) {
const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
+ return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
}
QStringView symView(int index) const
{
const Value &symbol = sym(index);
return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
}
- inline QStringRef symName(int index) {
+ inline XmlStringRef symName(int index) {
const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
}
- inline QStringRef symString(int index, int offset) {
+ inline XmlStringRef symString(int index, int offset) {
const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
+ return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
}
- inline QStringRef symPrefix(int index) {
+ inline XmlStringRef symPrefix(int index) {
const Value &symbol = sym(index);
if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
+ return XmlStringRef();
}
- inline QStringRef symString(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
+ inline XmlStringRef symString(const Value &symbol) {
+ return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
}
- inline QStringRef symName(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
+ inline XmlStringRef symName(const Value &symbol) {
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
}
- inline QStringRef symPrefix(const Value &symbol) {
+ inline XmlStringRef symPrefix(const Value &symbol) {
if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
+ return XmlStringRef();
}
inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
@@ -1009,11 +507,11 @@ public:
// scan optimization functions. Not strictly necessary but LALR is
// not very well suited for scanning fast
- int fastScanLiteralContent();
- int fastScanSpace();
- int fastScanContentCharList();
- int fastScanName(int *prefix = nullptr);
- inline int fastScanNMTOKEN();
+ qsizetype fastScanLiteralContent();
+ qsizetype fastScanSpace();
+ qsizetype fastScanContentCharList();
+ std::optional<qsizetype> fastScanName(Value *val = nullptr);
+ inline qsizetype fastScanNMTOKEN();
bool parse();
@@ -1021,6 +519,7 @@ public:
void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
void raiseWellFormedError(const QString &message);
+ void raiseNamePrefixTooLongError();
QXmlStreamEntityResolver *entityResolver;
@@ -1032,955 +531,12 @@ private:
*/
inline void setType(const QXmlStreamReader::TokenType t)
{
- if(type != QXmlStreamReader::Invalid)
+ if (type != QXmlStreamReader::Invalid)
type = t;
}
};
-bool QXmlStreamReaderPrivate::parse()
-{
- // cleanup currently reported token
-
- switch (type) {
- case QXmlStreamReader::StartElement:
- name.clear();
- prefix.clear();
- qualifiedName.clear();
- namespaceUri.clear();
- publicNamespaceDeclarations.clear();
- attributes.clear();
- if (isEmptyElement) {
- setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
- namespaceUri = tag.namespaceDeclaration.namespaceUri;
- name = tag.name;
- qualifiedName = tag.qualifiedName;
- isEmptyElement = false;
- return true;
- }
- clearTextBuffer();
- break;
- case QXmlStreamReader::EndElement:
- name.clear();
- prefix.clear();
- qualifiedName.clear();
- namespaceUri.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::DTD:
- publicNotationDeclarations.clear();
- publicEntityDeclarations.clear();
- dtdName.clear();
- dtdPublicId.clear();
- dtdSystemId.clear();
- Q_FALLTHROUGH();
- case QXmlStreamReader::Comment:
- case QXmlStreamReader::Characters:
- isCDATA = false;
- isWhitespace = true;
- text.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::EntityReference:
- text.clear();
- name.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::ProcessingInstruction:
- processingInstructionTarget.clear();
- processingInstructionData.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::NoToken:
- case QXmlStreamReader::Invalid:
- break;
- case QXmlStreamReader::StartDocument:
- lockEncoding = true;
- documentVersion.clear();
- documentEncoding.clear();
- if (decoder.isValid() && decoder.hasError()) {
- raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
- readBuffer.clear();
- return false;
- }
- Q_FALLTHROUGH();
- default:
- clearTextBuffer();
- ;
- }
-
- setType(QXmlStreamReader::NoToken);
-
-
- // the main parse loop
- int act, r;
-
- if (resumeReduction) {
- act = state_stack[tos-1];
- r = resumeReduction;
- resumeReduction = 0;
- goto ResumeReduction;
- }
-
- act = state_stack[tos];
-
- forever {
- if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
- uint cu = getChar();
- token = NOTOKEN;
- token_char = cu == ~0U ? cu : ushort(cu);
- if ((cu != ~0U) && (cu & 0xff0000)) {
- token = cu >> 16;
- } else switch (token_char) {
- case 0xfffe:
- case 0xffff:
- token = ERROR;
- break;
- case '\r':
- token = SPACE;
- if (cu == '\r') {
- if ((token_char = filterCarriageReturn())) {
- ++lineNumber;
- lastLineStart = characterOffset + readBufferPos;
- break;
- }
- } else {
- break;
- }
- Q_FALLTHROUGH();
- case ~0U: {
- token = EOF_SYMBOL;
- if (!tagsDone && !inParseEntity) {
- int a = t_action(act, token);
- if (a < 0) {
- raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
- return false;
- }
- }
-
- } break;
- case '\n':
- ++lineNumber;
- lastLineStart = characterOffset + readBufferPos;
- Q_FALLTHROUGH();
- case ' ':
- case '\t':
- token = SPACE;
- break;
- case '&':
- token = AMPERSAND;
- break;
- case '#':
- token = HASH;
- break;
- case '\'':
- token = QUOTE;
- break;
- case '\"':
- token = DBLQUOTE;
- break;
- case '<':
- token = LANGLE;
- break;
- case '>':
- token = RANGLE;
- break;
- case '[':
- token = LBRACK;
- break;
- case ']':
- token = RBRACK;
- break;
- case '(':
- token = LPAREN;
- break;
- case ')':
- token = RPAREN;
- break;
- case '|':
- token = PIPE;
- break;
- case '=':
- token = EQ;
- break;
- case '%':
- token = PERCENT;
- break;
- case '/':
- token = SLASH;
- break;
- case ':':
- token = COLON;
- break;
- case ';':
- token = SEMICOLON;
- break;
- case ',':
- token = COMMA;
- break;
- case '-':
- token = DASH;
- break;
- case '+':
- token = PLUS;
- break;
- case '*':
- token = STAR;
- break;
- case '.':
- token = DOT;
- break;
- case '?':
- token = QUESTIONMARK;
- break;
- case '!':
- token = BANG;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- token = DIGIT;
- break;
- default:
- if (cu < 0x20)
- token = NOTOKEN;
- else
- token = LETTER;
- break;
- }
- }
-
- act = t_action (act, token);
- if (act == ACCEPT_STATE) {
- // reset the parser in case someone resumes (process instructions can follow a valid document)
- tos = 0;
- state_stack[tos++] = 0;
- state_stack[tos] = 0;
- return true;
- } else if (act > 0) {
- if (++tos >= stack_size-1)
- reallocateStack();
-
- Value &val = sym_stack[tos];
- val.c = token_char;
- val.pos = textBuffer.size();
- val.prefix = 0;
- val.len = 1;
- if (token_char)
- textBuffer += QChar(token_char);
-
- state_stack[tos] = act;
- token = -1;
-
-
- } else if (act < 0) {
- r = - act - 1;
-
-#if defined (QLALR_DEBUG)
- int ridx = rule_index[r];
- printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
- ++ridx;
- for (int i = ridx; i < ridx + rhs[r]; ++i) {
- int symbol = rule_info[i];
- if (const char *name = spell[symbol])
- printf (" %s", name);
- else
- printf (" #%d", symbol);
- }
- printf ("\n");
-#endif
-
- tos -= rhs[r];
- act = state_stack[tos++];
- ResumeReduction:
- switch (r) {
-
- case 0:
- setType(QXmlStreamReader::EndDocument);
- break;
-
- case 1:
- if (type != QXmlStreamReader::Invalid) {
- if (hasSeenTag || inParseEntity) {
- setType(QXmlStreamReader::EndDocument);
- } else {
- raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected."));
- // reset the parser
- tos = 0;
- state_stack[tos++] = 0;
- state_stack[tos] = 0;
- return false;
- }
- }
- break;
-
- case 10:
- entityReferenceStack.pop()->isCurrentlyReferenced = false;
- if (entityReferenceStack.isEmpty())
- entityLength = 0;
- clearSym();
- break;
-
- case 11:
- if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
- resume(11);
- return false;
- }
- break;
-
- case 12:
- setType(QXmlStreamReader::StartDocument);
- documentVersion = symString(6);
- startDocument();
- break;
-
- case 13:
- hasExternalDtdSubset = true;
- dtdSystemId = symString(2);
- break;
-
- case 14:
- checkPublicLiteral(symString(2));
- dtdPublicId = symString(2);
- dtdSystemId = symString(4);
- hasExternalDtdSubset = true;
- break;
-
- case 16:
- if (!scanPublicOrSystem() && atEnd) {
- resume(16);
- return false;
- }
- dtdName = symString(3);
- break;
-
- case 17:
- case 18:
- dtdName = symString(3);
- Q_FALLTHROUGH();
-
- case 19:
- case 20:
- setType(QXmlStreamReader::DTD);
- text = &textBuffer;
- break;
-
- case 21:
- scanDtd = true;
- break;
-
- case 22:
- scanDtd = false;
- break;
-
- case 37:
- if (!scanString(spell[EMPTY], EMPTY, false)
- && !scanString(spell[ANY], ANY, false)
- && atEnd) {
- resume(37);
- return false;
- }
- break;
-
- case 43:
- if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
- resume(43);
- return false;
- }
- break;
-
- case 68: {
- lastAttributeIsCData = true;
- } break;
-
- case 78:
- if (!scanAfterDefaultDecl() && atEnd) {
- resume(78);
- return false;
- }
- break;
-
- case 83:
- sym(1) = sym(2);
- lastAttributeValue.clear();
- lastAttributeIsCData = false;
- if (!scanAttType() && atEnd) {
- resume(83);
- return false;
- }
- break;
-
- case 84: {
- DtdAttribute &dtdAttribute = dtdAttributes.push();
- dtdAttribute.tagName.clear();
- dtdAttribute.isCDATA = lastAttributeIsCData;
- dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
- dtdAttribute.attributeName = addToStringStorage(symString(1));
- dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
- dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns")
- || (dtdAttribute.attributePrefix.isEmpty()
- && dtdAttribute.attributeName == QLatin1String("xmlns")));
- if (lastAttributeValue.isNull()) {
- dtdAttribute.defaultValue.clear();
- } else {
- if (dtdAttribute.isCDATA)
- dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
- else
- dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
-
- }
- } break;
-
- case 88: {
- if (referenceToUnparsedEntityDetected && !standalone)
- break;
- int n = dtdAttributes.size();
- QStringRef tagName = addToStringStorage(symName(3));
- while (n--) {
- DtdAttribute &dtdAttribute = dtdAttributes[n];
- if (!dtdAttribute.tagName.isNull())
- break;
- dtdAttribute.tagName = tagName;
- for (int i = 0; i < n; ++i) {
- if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
- && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
- dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
- break;
- }
- }
- }
- } break;
-
- case 89: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(89);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.push();
- entityDeclaration.clear();
- entityDeclaration.name = symString(3);
- } break;
-
- case 90: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(90);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.push();
- entityDeclaration.clear();
- entityDeclaration.name = symString(5);
- entityDeclaration.parameter = true;
- } break;
-
- case 91: {
- if (!scanNData() && atEnd) {
- resume(91);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- entityDeclaration.systemId = symString(3);
- entityDeclaration.external = true;
- } break;
-
- case 92: {
- if (!scanNData() && atEnd) {
- resume(92);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- checkPublicLiteral((entityDeclaration.publicId = symString(3)));
- entityDeclaration.systemId = symString(5);
- entityDeclaration.external = true;
- } break;
-
- case 93: {
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- entityDeclaration.notationName = symString(3);
- if (entityDeclaration.parameter)
- raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
- }
- Q_FALLTHROUGH();
-
- case 94:
- case 95: {
- if (referenceToUnparsedEntityDetected && !standalone) {
- entityDeclarations.pop();
- break;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- if (!entityDeclaration.external)
- entityDeclaration.value = symString(2);
- auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) {
- Entity entity(entityDeclaration.name.toString(),
- entityDeclaration.value.toString());
- entity.unparsed = (!entityDeclaration.notationName.isNull());
- entity.external = entityDeclaration.external;
- hash.insert(qToStringViewIgnoringNull(entity.name), entity);
- }
- } break;
-
- case 96: {
- setType(QXmlStreamReader::ProcessingInstruction);
- int pos = sym(4).pos + sym(4).len;
- processingInstructionTarget = symString(3);
- if (scanUntil("?>")) {
- processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
- raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
- }
- else if (!QXmlUtils::isNCName(processingInstructionTarget))
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
- .arg(processingInstructionTarget));
- } else if (type != QXmlStreamReader::Invalid){
- resume(96);
- return false;
- }
- } break;
-
- case 97:
- setType(QXmlStreamReader::ProcessingInstruction);
- processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive))
- raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
- break;
-
- case 98:
- if (!scanAfterLangleBang() && atEnd) {
- resume(98);
- return false;
- }
- break;
-
- case 99:
- if (!scanUntil("--")) {
- resume(99);
- return false;
- }
- break;
-
- case 100: {
- setType(QXmlStreamReader::Comment);
- int pos = sym(1).pos + 4;
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
- } break;
-
- case 101: {
- setType(QXmlStreamReader::Characters);
- isCDATA = true;
- isWhitespace = false;
- int pos = sym(2).pos;
- if (scanUntil("]]>", -1)) {
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
- } else {
- resume(101);
- return false;
- }
- } break;
-
- case 102: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(102);
- return false;
- }
- NotationDeclaration &notationDeclaration = notationDeclarations.push();
- notationDeclaration.name = symString(3);
- } break;
-
- case 103: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- notationDeclaration.systemId = symString(3);
- notationDeclaration.publicId.clear();
- } break;
-
- case 104: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- notationDeclaration.systemId.clear();
- checkPublicLiteral((notationDeclaration.publicId = symString(3)));
- } break;
-
- case 105: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- checkPublicLiteral((notationDeclaration.publicId = symString(3)));
- notationDeclaration.systemId = symString(5);
- } break;
-
- case 129:
- isWhitespace = false;
- Q_FALLTHROUGH();
-
- case 130:
- sym(1).len += fastScanContentCharList();
- if (atEnd && !inParseEntity) {
- resume(130);
- return false;
- }
- break;
-
- case 139:
- if (!textBuffer.isEmpty()) {
- setType(QXmlStreamReader::Characters);
- text = &textBuffer;
- }
- break;
-
- case 140:
- case 141:
- clearSym();
- break;
-
- case 142:
- case 143:
- sym(1) = sym(2);
- break;
-
- case 144:
- case 145:
- case 146:
- case 147:
- sym(1).len += sym(2).len;
- break;
-
- case 173:
- if (normalizeLiterals)
- textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
- break;
-
- case 174:
- sym(1).len += fastScanLiteralContent();
- if (atEnd) {
- resume(174);
- return false;
- }
- break;
-
- case 175: {
- if (!QXmlUtils::isPublicID(symString(1))) {
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
- resume(175);
- return false;
- }
- } break;
-
- case 176:
- case 177:
- clearSym();
- break;
-
- case 178:
- case 179:
- sym(1) = sym(2);
- break;
-
- case 180:
- case 181:
- case 182:
- case 183:
- sym(1).len += sym(2).len;
- break;
-
- case 213:
- case 214:
- clearSym();
- break;
-
- case 215:
- case 216:
- sym(1) = sym(2);
- lastAttributeValue = symString(1);
- break;
-
- case 217:
- case 218:
- case 219:
- case 220:
- sym(1).len += sym(2).len;
- break;
-
- case 229: {
- QStringRef prefix = symPrefix(1);
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- namespaceDeclaration.prefix.clear();
-
- const QStringRef ns(symString(5));
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
- raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
- else
- namespaceDeclaration.namespaceUri = addToStringStorage(ns);
- } else {
- Attribute &attribute = attributeStack.push();
- attribute.key = sym(1);
- attribute.value = sym(5);
-
- QStringRef attributeQualifiedName = symName(1);
- bool normalize = false;
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
- if (!dtdAttribute.isCDATA
- && dtdAttribute.tagName == qualifiedName
- && dtdAttribute.attributeQualifiedName == attributeQualifiedName
- ) {
- normalize = true;
- break;
- }
- }
- if (normalize) {
- // normalize attribute value (simplify and trim)
- int pos = textBuffer.size();
- int n = 0;
- bool wasSpace = true;
- for (int i = 0; i < attribute.value.len; ++i) {
- QChar c = textBuffer.at(attribute.value.pos + i);
- if (c.unicode() == ' ') {
- if (wasSpace)
- continue;
- wasSpace = true;
- } else {
- wasSpace = false;
- }
- textBuffer += textBuffer.at(attribute.value.pos + i);
- ++n;
- }
- if (wasSpace)
- while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
- --n;
- attribute.value.pos = pos;
- attribute.value.len = n;
- }
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = symString(attribute.key);
- QStringRef namespaceUri = symString(attribute.value);
- attributeStack.pop();
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
- || namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
- raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
-
- namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
- namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
- }
- }
- } break;
-
- case 235: {
- normalizeLiterals = true;
- Tag &tag = tagStack_push();
- prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2));
- name = tag.name = addToStringStorage(symString(2));
- qualifiedName = tag.qualifiedName = addToStringStorage(symName(2));
- if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
- raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
- } break;
-
- case 236:
- isEmptyElement = true;
- Q_FALLTHROUGH();
-
- case 237:
- setType(QXmlStreamReader::StartElement);
- resolveTag();
- if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
- raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
- hasSeenTag = true;
- break;
-
- case 238: {
- setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
-
- namespaceUri = tag.namespaceDeclaration.namespaceUri;
- name = tag.name;
- qualifiedName = tag.qualifiedName;
- if (qualifiedName != symName(3))
- raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
- } break;
-
- case 239:
- if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
- break;
- }
- setType(QXmlStreamReader::EntityReference);
- name = &unresolvedEntity;
- break;
-
- case 240: {
- sym(1).len += sym(2).len + 1;
- QStringView reference = symView(2);
- if (const auto it = entityHash.find(reference); it != entityHash.end()) {
- Entity &entity = *it;
- if (entity.unparsed) {
- raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
- } else {
- if (!entity.hasBeenParsed) {
- parseEntity(entity.value);
- entity.hasBeenParsed = true;
- }
- if (entity.literal)
- putStringLiteral(entity.value);
- else if (referenceEntity(entity))
- putReplacement(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- }
- break;
- }
-
- if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference.toString());
- if (!replacementText.isNull()) {
- putReplacement(replacementText);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
- }
-
- injectToken(UNRESOLVED_ENTITY);
- unresolvedEntity = symString(2).toString();
- textBuffer.chop(2 + sym(2).len);
- clearSym();
-
- } break;
-
- case 241: {
- sym(1).len += sym(2).len + 1;
- QStringView reference = symView(2);
- if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
- referenceToParameterEntityDetected = true;
- Entity &entity = *it;
- if (entity.unparsed || entity.external) {
- referenceToUnparsedEntityDetected = true;
- } else {
- if (referenceEntity(entity))
- putString(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- }
- } else if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
- }
- } break;
-
- case 242:
- sym(1).len += sym(2).len + 1;
- break;
-
- case 243: {
- sym(1).len += sym(2).len + 1;
- QStringView reference = symView(2);
- if (const auto it = entityHash.find(reference); it != entityHash.end()) {
- Entity &entity = *it;
- if (entity.unparsed || entity.value.isNull()) {
- raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
- break;
- }
- if (!entity.hasBeenParsed) {
- parseEntity(entity.value);
- entity.hasBeenParsed = true;
- }
- if (entity.literal)
- putStringLiteral(entity.value);
- else if (referenceEntity(entity))
- putReplacementInAttributeValue(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
-
- if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference.toString());
- if (!replacementText.isNull()) {
- putReplacement(replacementText);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
- }
- if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
- }
- } break;
-
- case 244: {
- if (char32_t s = resolveCharRef(3)) {
- putStringLiteral(QChar::fromUcs4(s));
- textBuffer.chop(3 + sym(3).len);
- clearSym();
- } else {
- raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
- }
- } break;
-
- case 247:
- case 248:
- sym(1).len += sym(2).len;
- break;
-
- case 259:
- sym(1).len += fastScanSpace();
- if (atEnd) {
- resume(259);
- return false;
- }
- break;
-
- case 262: {
- sym(1).len += fastScanName(&sym(1).prefix);
- if (atEnd) {
- resume(262);
- return false;
- }
- } break;
-
- case 263:
- sym(1).len += fastScanName();
- if (atEnd) {
- resume(263);
- return false;
- }
- break;
-
- case 264:
- case 265:
- case 266:
- case 267:
- case 268:
- sym(1).len += fastScanNMTOKEN();
- if (atEnd) {
- resume(268);
- return false;
- }
-
- break;
-
- default:
- ;
- } // switch
- act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
- if (type != QXmlStreamReader::NoToken)
- return true;
- } else {
- parseError();
- break;
- }
- }
- return false;
-}
-#endif //QT_NO_XMLSTREAMREADER.xml
-
+QT_END_NAMESPACE
#endif // QXMLSTREAM_P_H
diff --git a/src/corelib/serialization/qxmlstreamgrammar.cpp b/src/corelib/serialization/qxmlstreamgrammar.cpp
new file mode 100644
index 0000000000..074b9023ce
--- /dev/null
+++ b/src/corelib/serialization/qxmlstreamgrammar.cpp
@@ -0,0 +1,496 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+// This file was generated by qlalr - DO NOT EDIT!
+#include "qxmlstreamgrammar_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const char *const QXmlStreamGrammar::spell [] = {
+ "end of file", 0, " ", "<", ">", "&", "#", "\'", "\"", "[",
+ "]", "(", ")", "|", "=", "%", "/", ":", ";", ",",
+ "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE",
+ "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED",
+ "EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF",
+ "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", 0
+};
+
+const short QXmlStreamGrammar::lhs [] = {
+ 57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
+ 67, 68, 64, 72, 72, 72, 75, 66, 66, 66,
+ 66, 79, 78, 80, 80, 80, 80, 80, 80, 80,
+ 81, 81, 81, 81, 81, 81, 81, 87, 83, 88,
+ 88, 88, 88, 91, 92, 93, 93, 93, 93, 94,
+ 94, 96, 96, 96, 97, 97, 98, 98, 99, 99,
+ 100, 100, 89, 89, 95, 90, 101, 101, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 104, 105,
+ 105, 105, 105, 107, 108, 109, 109, 84, 84, 110,
+ 110, 112, 112, 85, 85, 85, 65, 65, 76, 114,
+ 63, 115, 116, 86, 86, 86, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 118,
+ 118, 119, 119, 119, 119, 119, 119, 119, 119, 122,
+ 70, 70, 70, 70, 123, 124, 123, 124, 123, 124,
+ 123, 124, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 125, 73, 113, 113, 113, 113,
+ 127, 128, 127, 128, 127, 128, 127, 128, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 106, 106, 106, 106, 131, 132, 131,
+ 132, 131, 131, 132, 132, 133, 133, 133, 133, 135,
+ 71, 71, 71, 136, 136, 137, 62, 60, 61, 138,
+ 121, 82, 130, 134, 120, 139, 139, 139, 139, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 74,
+ 69, 69, 77, 111, 102, 102, 102, 102, 102, 140
+};
+
+const short QXmlStreamGrammar::rhs [] = {
+ 2, 1, 4, 2, 2, 2, 2, 2, 2, 0,
+ 1, 1, 9, 2, 4, 0, 4, 4, 6, 6,
+ 4, 1, 3, 1, 1, 1, 2, 2, 2, 0,
+ 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
+ 1, 1, 1, 1, 2, 1, 1, 1, 0, 2,
+ 2, 2, 6, 6, 1, 5, 1, 5, 3, 5,
+ 0, 1, 6, 8, 4, 2, 1, 5, 1, 1,
+ 1, 1, 1, 1, 1, 1, 6, 7, 1, 2,
+ 2, 1, 4, 3, 3, 1, 2, 5, 6, 4,
+ 6, 3, 5, 5, 3, 4, 4, 5, 2, 3,
+ 2, 2, 4, 5, 5, 7, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
+ 2, 2, 3, 3, 2, 2, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 3, 3,
+ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 3, 3, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 5,
+ 0, 1, 3, 1, 3, 2, 4, 3, 5, 1,
+ 3, 3, 3, 3, 4, 1, 1, 2, 2, 2,
+ 4, 2, 2, 2, 2, 2, 2, 2, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2
+};
+
+const short QXmlStreamGrammar::action_default [] = {
+ 10, 259, 0, 2, 1, 0, 125, 117, 119, 120,
+ 127, 129, 123, 11, 114, 108, 0, 109, 128, 111,
+ 115, 113, 121, 124, 126, 107, 110, 112, 118, 116,
+ 131, 122, 240, 12, 254, 136, 250, 253, 0, 130,
+ 140, 257, 16, 252, 138, 137, 0, 256, 139, 259,
+ 231, 258, 255, 0, 0, 264, 0, 247, 246, 0,
+ 249, 248, 245, 241, 99, 263, 0, 236, 0, 0,
+ 260, 97, 98, 101, 0, 132, 134, 133, 135, 0,
+ 0, 261, 0, 0, 176, 0, 173, 165, 167, 168,
+ 142, 154, 171, 162, 156, 157, 153, 159, 163, 161,
+ 169, 172, 152, 155, 158, 160, 166, 164, 174, 170,
+ 150, 175, 0, 144, 148, 146, 151, 141, 149, 0,
+ 147, 143, 145, 0, 15, 14, 262, 0, 22, 21,
+ 261, 30, 0, 20, 0, 0, 32, 37, 31, 0,
+ 33, 261, 0, 34, 0, 24, 0, 35, 0, 26,
+ 36, 25, 0, 242, 41, 40, 261, 43, 49, 261,
+ 42, 0, 44, 261, 49, 261, 0, 261, 0, 49,
+ 0, 48, 46, 47, 51, 52, 261, 261, 0, 57,
+ 261, 54, 261, 0, 58, 0, 55, 261, 53, 261,
+ 0, 56, 65, 0, 261, 61, 261, 0, 59, 62,
+ 63, 0, 261, 0, 0, 60, 64, 45, 50, 66,
+ 0, 39, 0, 0, 261, 0, 94, 95, 0, 0,
+ 0, 0, 261, 0, 210, 201, 203, 205, 178, 190,
+ 208, 199, 193, 191, 194, 189, 196, 198, 206, 209,
+ 188, 192, 195, 197, 202, 200, 204, 207, 211, 213,
+ 212, 186, 0, 0, 243, 180, 184, 182, 0, 0,
+ 93, 187, 177, 185, 0, 183, 179, 181, 92, 0,
+ 96, 0, 0, 0, 0, 0, 261, 86, 261, 0,
+ 262, 0, 87, 0, 89, 69, 74, 73, 70, 71,
+ 72, 261, 75, 76, 0, 0, 0, 269, 268, 266,
+ 267, 265, 67, 261, 0, 261, 0, 0, 68, 77,
+ 261, 0, 261, 0, 0, 78, 0, 79, 0, 82,
+ 85, 0, 0, 215, 225, 224, 0, 227, 229, 228,
+ 226, 0, 244, 217, 221, 219, 223, 214, 222, 0,
+ 220, 216, 218, 0, 81, 80, 0, 83, 0, 84,
+ 88, 100, 0, 38, 0, 0, 0, 0, 91, 90,
+ 0, 103, 23, 27, 29, 28, 0, 0, 261, 262,
+ 0, 261, 0, 106, 105, 261, 0, 104, 102, 0,
+ 0, 18, 261, 17, 0, 19, 0, 0, 251, 0,
+ 261, 0, 239, 0, 232, 238, 0, 237, 234, 261,
+ 261, 262, 233, 235, 0, 261, 0, 230, 261, 0,
+ 261, 0, 231, 0, 0, 13, 270, 9, 5, 8,
+ 4, 0, 7, 259, 6, 0, 3
+};
+
+const short QXmlStreamGrammar::goto_default [] = {
+ 2, 4, 3, 49, 388, 43, 37, 52, 47, 41,
+ 249, 53, 127, 84, 393, 81, 85, 126, 42, 46,
+ 169, 130, 131, 146, 145, 149, 138, 136, 140, 147,
+ 139, 159, 160, 157, 168, 167, 209, 165, 164, 166,
+ 187, 180, 196, 200, 303, 302, 295, 321, 320, 319,
+ 279, 277, 278, 142, 56, 141, 222, 38, 34, 148,
+ 39, 48, 40, 248, 45, 36, 119, 112, 330, 111,
+ 264, 252, 251, 250, 339, 326, 325, 329, 398, 399,
+ 50, 51, 59, 0
+};
+
+const short QXmlStreamGrammar::action_index [] = {
+ -39, -57, 7, 112, 918, 40, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, 113, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, 9, -57,
+ 753, -57, 70, -57, -57, -57, 88, -57, -57, -57,
+ 53, -57, -57, -37, 69, -57, -7, -57, -57, 128,
+ -57, -57, -57, -57, -57, -57, 32, -57, 55, 31,
+ -57, -57, -57, -57, 75, -57, -57, -57, -57, 77,
+ 92, 53, 313, 284, -57, 53, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, 258, -57, -57, -57, -57, -57, -57, 368,
+ -57, -57, -57, 153, -57, -57, -57, 71, -57, -57,
+ 53, 150, 21, -57, 39, -3, -57, -57, -57, 101,
+ -57, 46, 203, -57, 148, -57, 173, -57, 35, -57,
+ -57, -57, 29, -57, -57, -57, 53, -57, 108, 53,
+ -57, 125, -57, 53, 126, 53, 24, 53, -1, 104,
+ 57, -57, -57, -57, -57, 54, 53, 37, 66, -57,
+ 53, 5, 53, 61, -57, 60, -57, 53, 15, 53,
+ 48, -57, -57, 49, 53, 16, 53, 18, -57, -57,
+ -57, 38, 53, 20, 19, -57, -57, -57, -57, -57,
+ 27, -57, 17, 26, 53, 25, -57, -57, 533, 153,
+ 643, 153, 53, 97, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, 863, 14, -57, -57, -57, -57, 53, 153,
+ -57, -57, -57, -57, 808, -57, -57, -57, -57, 23,
+ -57, -5, 2, 34, 87, 32, 53, -57, 53, 175,
+ 28, 33, -57, 30, -57, -57, -57, -57, -57, -57,
+ -57, 53, -57, -57, 22, 137, 167, -57, -57, -57,
+ -57, -57, -57, 53, 78, 53, 53, 179, -57, -57,
+ 53, 147, 53, 81, -2, -57, 423, -57, 478, -57,
+ -57, 82, 83, -57, -57, -57, 588, -57, -57, -57,
+ -57, 1, -57, -57, -57, -57, -57, -57, -57, 698,
+ -57, -57, -57, 53, -57, -57, 99, -57, 53, -57,
+ -57, -57, 53, -57, 53, 53, -20, 53, -57, -57,
+ 53, -57, -57, -57, -57, -57, 153, 153, 53, 90,
+ 8, 53, 11, -57, -57, 53, 13, -57, -57, -25,
+ 131, -57, 53, -57, 10, -57, 973, 133, -57, -6,
+ 53, 4, -57, 72, -17, -57, 6, -57, -57, 53,
+ 53, -10, -57, -57, 12, 53, 103, -57, 53, -12,
+ 53, 45, 53, -21, 0, -57, -57, -57, -57, -57,
+ -57, 36, -57, -57, -57, 973, -57,
+
+ -84, -84, -84, 118, 69, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 12, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ 103, -84, -84, -84, -84, -84, -84, -84, -84, 71,
+ 64, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 15, -84, 35, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ 48, -84, -5, -34, -84, 38, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, 52, -84, -84, -84, -84, -84, -84, -19,
+ -84, -84, -84, 47, -84, -84, -84, -84, -84, -84,
+ 116, 194, -84, -84, -84, 28, -84, -84, -84, 24,
+ -84, 36, -84, -84, -84, -84, 130, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 4, -84, -84, -1,
+ -84, -84, -84, 29, 17, 27, -84, 18, -84, 0,
+ -84, -84, -84, -84, -84, -84, -3, -4, -36, -84,
+ 25, -84, 9, -8, -84, -11, -84, 19, -84, 26,
+ 14, -84, -84, -84, 30, -84, -9, -16, -84, -84,
+ -84, -84, 1, -84, -2, -84, -84, -84, -84, -84,
+ -84, -84, 50, -84, 58, -84, -84, -84, -84, 68,
+ -13, 62, 33, -7, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -26, -84, -84, -84, -84, -84, 51, 37,
+ -84, -84, -84, -84, -57, -84, -84, -84, -84, -84,
+ -84, 3, -84, -20, -49, -47, 79, -84, 99, -84,
+ 20, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, 42, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, 55, -84, 53, 49, 41, -84, -84,
+ 46, 34, 45, -84, 39, -84, 85, -84, 96, -84,
+ -84, -84, 31, -84, -84, -84, 97, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, 100,
+ -84, -84, -84, 66, -84, -84, 43, -84, 60, -84,
+ -84, -84, 57, -84, 54, 56, 40, 59, -84, -84,
+ 63, -84, -84, -84, -84, -84, 8, 7, 76, 6,
+ -84, 5, -84, -84, -84, 2, -84, -84, -84, -10,
+ 80, -84, -6, -84, -84, -84, 89, -18, -84, 44,
+ 32, -84, -84, -84, 23, -84, -84, -84, -84, 88,
+ 21, 78, -84, -84, -84, 16, -22, -84, 13, -84,
+ 10, 22, 73, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, 11, -84, 98, -84
+};
+
+const short QXmlStreamGrammar::action_info [] = {
+ 70, 65, 410, 414, 415, 1, 55, 416, 392, 65,
+ 397, 63, 374, 73, 385, 373, 65, 377, 408, 332,
+ 65, 65, 351, 55, 182, 133, 405, 270, 189, 216,
+ 217, 211, 254, 310, 284, 72, 192, 350, 199, 70,
+ 0, 207, 206, 55, 65, 65, 54, 153, 70, 0,
+ 203, 202, 83, 82, 65, 70, 272, 70, 55, 163,
+ 65, 195, 194, 66, 64, 379, 55, 177, 163, 367,
+ 366, 163, 163, 176, 65, 129, 395, 163, 0, 69,
+ 128, 54, 212, 65, 83, 82, 65, 65, 396, 54,
+ 306, 305, 65, 314, 305, 58, 57, 83, 82, 83,
+ 82, 55, 354, 54, 80, 79, 318, 316, 272, 55,
+ 318, 316, 156, 55, 417, 16, 378, 379, 0, 345,
+ 344, 343, 0, 55, 0, 171, 173, 0, 172, 171,
+ 173, 162, 172, 70, 0, 381, 163, 66, 64, 65,
+ 128, 155, 154, 317, 318, 316, 62, 171, 173, 389,
+ 172, 65, 70, 134, 61, 60, 0, 66, 64, 65,
+ 83, 82, 0, 0, 297, 135, 33, 298, 272, 0,
+ 300, 0, 0, 301, 299, 70, 134, 0, 273, 271,
+ 274, 275, 0, 362, 297, 0, 291, 298, 135, 0,
+ 300, 0, 0, 301, 299, 13, 297, 0, 0, 298,
+ 0, 0, 300, 0, 0, 301, 299, 287, 294, 0,
+ 220, 218, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 285, 288, 289, 290, 286, 292, 293, 0,
+ 0, 0, 0, 0, 0, 0, 0, 221, 219, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 0, 94, 114, 113, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 108, 0, 103, 0,
+ 94, 117, 116, 95, 104, 97, 105, 99, 93, 98,
+ 107, 87, 106, 88, 89, 100, 109, 92, 101, 86,
+ 96, 91, 0, 0, 0, 108, 0, 103, 0, 94,
+ 102, 90, 95, 104, 97, 105, 99, 93, 98, 107,
+ 87, 106, 88, 89, 100, 109, 92, 101, 86, 96,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 0, 94, 121, 120, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 108, 0, 103, 322, 94,
+ 324, 323, 95, 104, 97, 105, 99, 93, 98, 107,
+ 87, 106, 88, 89, 100, 109, 92, 101, 86, 96,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 322, 94, 337, 336, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 246, 233, 241, 223, 232,
+ 240, 228, 234, 242, 236, 243, 237, 231, 0, 245,
+ 225, 244, 226, 227, 238, 247, 230, 239, 224, 235,
+ 229, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 322, 94, 334, 333, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 246, 233, 241, 223, 232,
+ 262, 261, 234, 242, 236, 243, 237, 231, 0, 245,
+ 225, 244, 226, 227, 238, 247, 230, 239, 224, 235,
+ 229, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 322, 94, 341, 340, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 30, 0, 25, 74, 15,
+ 24, 10, 17, 26, 19, 27, 21, 14, 20, 29,
+ 7, 28, 8, 9, 22, 31, 12, 23, 6, 18,
+ 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 246, 233, 241, 223, 232, 266, 265, 234, 242, 236,
+ 243, 237, 231, 0, 245, 225, 244, 226, 227, 238,
+ 247, 230, 239, 224, 235, 229, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 246, 233, 241, 223, 232,
+ 256, 255, 234, 242, 236, 243, 237, 231, 0, 245,
+ 225, 244, 226, 227, 238, 247, 230, 239, 224, 235,
+ 229, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 30, 16, 25, 5, 15, 24, 10, 17, 26, 19,
+ 27, 21, 14, 20, 29, 7, 28, 8, 9, 22,
+ 31, 12, 23, 6, 18, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 32, 0, 0, 0, 0, 0,
+ 0, 0, 33, 0, 0, 30, 387, 25, 5, 15,
+ 24, 10, 17, 26, 19, 27, 21, 14, 20, 29,
+ 7, 28, 8, 9, 22, 31, 12, 23, 6, 18,
+ 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 32,
+ 0, 0, 0, 0, 0, 0, 0, 33, 0, 0,
+
+ 352, 179, 67, 201, 198, 355, 384, 360, 185, 178,
+ 380, 210, 425, 204, 376, 267, 161, 372, 205, 371,
+ 375, 183, 411, 276, 368, 409, 186, 407, 406, 184,
+ 193, 188, 67, 404, 118, 412, 208, 181, 190, 175,
+ 348, 170, 197, 400, 391, 269, 257, 253, 213, 122,
+ 260, 191, 71, 174, 296, 123, 315, 313, 311, 263,
+ 124, 125, 158, 110, 390, 307, 309, 304, 259, 68,
+ 215, 356, 386, 359, 353, 268, 358, 349, 312, 44,
+ 361, 394, 152, 346, 258, 331, 308, 413, 370, 0,
+ 394, 281, 347, 369, 357, 328, 280, 383, 400, 44,
+ 402, 382, 426, 0, 214, 401, 328, 328, 44, 0,
+ 328, 283, 0, 76, 0, 0, 280, 0, 0, 0,
+ 115, 423, 0, 420, 418, 424, 422, 419, 132, 0,
+ 0, 0, 35, 0, 0, 0, 137, 421, 150, 0,
+ 143, 0, 0, 0, 0, 0, 0, 365, 327, 144,
+ 282, 0, 35, 0, 363, 364, 403, 0, 0, 327,
+ 327, 35, 0, 327, 78, 0, 75, 77, 0, 0,
+ 0, 0, 338, 335, 0, 0, 342, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 137, 0, 150, 0, 143, 0, 0, 0, 0, 0,
+ 0, 151, 0, 144, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const short QXmlStreamGrammar::action_check [] = {
+ 2, 26, 14, 24, 4, 44, 26, 0, 4, 26,
+ 4, 18, 4, 4, 4, 4, 26, 4, 55, 18,
+ 26, 26, 20, 26, 19, 4, 14, 4, 13, 4,
+ 4, 4, 18, 11, 4, 4, 12, 4, 22, 2,
+ -1, 42, 22, 26, 26, 26, 6, 18, 2, -1,
+ 12, 13, 7, 8, 26, 2, 20, 2, 26, 11,
+ 26, 12, 13, 24, 25, 29, 26, 13, 11, 34,
+ 35, 11, 11, 19, 26, 4, 4, 11, -1, 24,
+ 9, 6, 36, 26, 7, 8, 26, 26, 16, 6,
+ 12, 13, 26, 12, 13, 26, 27, 7, 8, 7,
+ 8, 26, 15, 6, 34, 35, 7, 8, 20, 26,
+ 7, 8, 11, 26, 2, 3, 28, 29, -1, 37,
+ 38, 39, -1, 26, -1, 21, 22, -1, 24, 21,
+ 22, 6, 24, 2, -1, 4, 11, 24, 25, 26,
+ 9, 40, 41, 6, 7, 8, 18, 21, 22, 16,
+ 24, 26, 2, 3, 26, 27, -1, 24, 25, 26,
+ 7, 8, -1, -1, 17, 15, 54, 20, 20, -1,
+ 23, -1, -1, 26, 27, 2, 3, -1, 30, 31,
+ 32, 33, -1, 10, 17, -1, 11, 20, 15, -1,
+ 23, -1, -1, 26, 27, 45, 17, -1, -1, 20,
+ -1, -1, 23, -1, -1, 26, 27, 32, 33, -1,
+ 7, 8, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, 47, 48, 49, 50, 51, 52, 53, -1,
+ -1, -1, -1, -1, -1, -1, -1, 34, 35, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, -1, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 2, -1, 4, -1,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, -1, -1, -1, 2, -1, 4, -1, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, -1, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, -1, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, -1, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, -1, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, -1, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, -1, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, -1, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, 46, -1, -1, -1, -1, -1,
+ -1, -1, 54, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, 46,
+ -1, -1, -1, -1, -1, -1, -1, 54, -1, -1,
+
+ 20, 37, 20, 12, 20, 54, 12, 54, 12, 12,
+ 20, 12, 1, 12, 12, 72, 12, 12, 20, 13,
+ 13, 12, 12, 20, 16, 12, 37, 49, 12, 37,
+ 12, 12, 20, 12, 68, 13, 36, 12, 12, 12,
+ 20, 12, 12, 20, 12, 12, 72, 54, 12, 68,
+ 13, 37, 17, 36, 12, 17, 17, 12, 12, 72,
+ 13, 13, 38, 68, 20, 12, 17, 12, 17, 54,
+ 12, 17, 1, 17, 17, 13, 17, 17, 44, 10,
+ 17, 17, 54, 17, 16, 54, 45, 14, 12, -1,
+ 17, 12, 49, 17, 54, 10, 17, 17, 20, 10,
+ 12, 21, 4, -1, 54, 17, 10, 10, 10, -1,
+ 10, 12, -1, 10, -1, -1, 17, -1, -1, -1,
+ 68, 3, -1, 5, 6, 7, 8, 9, 12, -1,
+ -1, -1, 63, -1, -1, -1, 6, 19, 8, -1,
+ 10, -1, -1, -1, -1, -1, -1, 17, 63, 19,
+ 51, -1, 63, -1, 24, 25, 78, -1, -1, 63,
+ 63, 63, -1, 63, 61, -1, 63, 64, -1, -1,
+ -1, -1, 76, 76, -1, -1, 76, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 6, -1, 8, -1, 10, -1, -1, -1, -1, -1,
+ -1, 17, -1, 19, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qxmlstreamgrammar_p.h b/src/corelib/serialization/qxmlstreamgrammar_p.h
new file mode 100644
index 0000000000..80ee8e929f
--- /dev/null
+++ b/src/corelib/serialization/qxmlstreamgrammar_p.h
@@ -0,0 +1,128 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// This file was generated by qlalr - DO NOT EDIT!
+#ifndef QXMLSTREAMGRAMMAR_P_H
+#define QXMLSTREAMGRAMMAR_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QXmlStreamGrammar
+{
+public:
+ enum VariousConstants {
+ EOF_SYMBOL = 0,
+ AMPERSAND = 5,
+ ANY = 41,
+ ATTLIST = 31,
+ BANG = 25,
+ CDATA = 47,
+ CDATA_START = 28,
+ COLON = 17,
+ COMMA = 19,
+ DASH = 20,
+ DBLQUOTE = 8,
+ DIGIT = 27,
+ DOCTYPE = 29,
+ DOT = 23,
+ ELEMENT = 30,
+ EMPTY = 40,
+ ENTITIES = 51,
+ ENTITY = 32,
+ ENTITY_DONE = 45,
+ EQ = 14,
+ FIXED = 39,
+ HASH = 6,
+ ID = 48,
+ IDREF = 49,
+ IDREFS = 50,
+ IMPLIED = 38,
+ LANGLE = 3,
+ LBRACK = 9,
+ LETTER = 26,
+ LPAREN = 11,
+ NDATA = 36,
+ NMTOKEN = 52,
+ NMTOKENS = 53,
+ NOTATION = 33,
+ NOTOKEN = 1,
+ PARSE_ENTITY = 44,
+ PCDATA = 42,
+ PERCENT = 15,
+ PIPE = 13,
+ PLUS = 21,
+ PUBLIC = 35,
+ QUESTIONMARK = 24,
+ QUOTE = 7,
+ RANGLE = 4,
+ RBRACK = 10,
+ REQUIRED = 37,
+ RPAREN = 12,
+ SEMICOLON = 18,
+ SHIFT_THERE = 56,
+ SLASH = 16,
+ SPACE = 2,
+ STAR = 22,
+ SYSTEM = 34,
+ UNRESOLVED_ENTITY = 46,
+ VERSION = 55,
+ XML = 54,
+ XML_ERROR = 43,
+
+ ACCEPT_STATE = 416,
+ RULE_COUNT = 270,
+ STATE_COUNT = 427,
+ TERMINAL_COUNT = 57,
+ NON_TERMINAL_COUNT = 84,
+
+ GOTO_INDEX_OFFSET = 427,
+ GOTO_INFO_OFFSET = 1030,
+ GOTO_CHECK_OFFSET = 1030
+ };
+
+ static const char *const spell[];
+ static const short lhs[];
+ static const short rhs[];
+ static const short goto_default[];
+ static const short action_default[];
+ static const short action_index[];
+ static const short action_info[];
+ static const short action_check[];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
+ if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
+ return goto_default [nt];
+
+ return action_info [GOTO_INFO_OFFSET + yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+QT_END_NAMESPACE
+#endif // QXMLSTREAMGRAMMAR_P_H
+
diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h
new file mode 100644
index 0000000000..1363bf4d41
--- /dev/null
+++ b/src/corelib/serialization/qxmlstreamparser_p.h
@@ -0,0 +1,1006 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is automatically generated from qxmlstream.g.
+// Changes should be made to that file, not here. Any change to this file will
+// be lost!
+//
+// To regenerate this file, run:
+// qlalr --no-debug --no-lines --qt qxmlstream.g
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <qxmlstream.h>
+#include "qxmlstream_p.h"
+#include "qxmlutils_p.h"
+#include <qstringconverter.h>
+
+#include <memory>
+
+#ifndef QXMLSTREAMPARSER_P_H
+#define QXMLSTREAMPARSER_P_H
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(xmlstreamreader)
+
+bool QXmlStreamReaderPrivate::parse()
+{
+ // cleanup currently reported token
+
+ using namespace Qt::StringLiterals;
+
+ switch (type) {
+ case QXmlStreamReader::StartElement:
+ name.clear();
+ prefix.clear();
+ qualifiedName.clear();
+ namespaceUri.clear();
+ publicNamespaceDeclarations.clear();
+ attributes.clear();
+ if (isEmptyElement) {
+ setType(QXmlStreamReader::EndElement);
+ Tag tag = tagStack_pop();
+ namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
+ name = tag.name;
+ qualifiedName = tag.qualifiedName;
+ isEmptyElement = false;
+ return true;
+ }
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::EndElement:
+ name.clear();
+ prefix.clear();
+ qualifiedName.clear();
+ namespaceUri.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::DTD:
+ publicNotationDeclarations.clear();
+ publicEntityDeclarations.clear();
+ dtdName.clear();
+ dtdPublicId.clear();
+ dtdSystemId.clear();
+ Q_FALLTHROUGH();
+ case QXmlStreamReader::Comment:
+ case QXmlStreamReader::Characters:
+ isCDATA = false;
+ isWhitespace = true;
+ text.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::EntityReference:
+ text.clear();
+ name.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::ProcessingInstruction:
+ processingInstructionTarget.clear();
+ processingInstructionData.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::NoToken:
+ case QXmlStreamReader::Invalid:
+ break;
+ case QXmlStreamReader::StartDocument:
+ lockEncoding = true;
+ documentVersion.clear();
+ documentEncoding.clear();
+ if (decoder.isValid() && decoder.hasError()) {
+ raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
+ readBuffer.clear();
+ return false;
+ }
+ Q_FALLTHROUGH();
+ default:
+ clearTextBuffer();
+ ;
+ }
+
+ setType(QXmlStreamReader::NoToken);
+
+
+ // the main parse loop
+ int act, r;
+
+ if (resumeReduction) {
+ act = state_stack[tos-1];
+ r = resumeReduction;
+ resumeReduction = 0;
+ goto ResumeReduction;
+ }
+
+ act = state_stack[tos];
+
+ forever {
+ if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
+ uint cu = getChar();
+ token = NOTOKEN;
+ token_char = cu == ~0U ? cu : ushort(cu);
+ if ((cu != ~0U) && (cu & 0xff0000)) {
+ token = cu >> 16;
+ } else switch (token_char) {
+ case 0xfffe:
+ case 0xffff:
+ token = XML_ERROR;
+ break;
+ case '\r':
+ token = SPACE;
+ if (cu == '\r') {
+ if ((token_char = filterCarriageReturn())) {
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ break;
+ }
+ } else {
+ break;
+ }
+ Q_FALLTHROUGH();
+ case ~0U: {
+ token = EOF_SYMBOL;
+ if (!tagsDone && !inParseEntity) {
+ int a = t_action(act, token);
+ if (a < 0) {
+ raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+ return false;
+ }
+ }
+
+ } break;
+ case '\n':
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ Q_FALLTHROUGH();
+ case ' ':
+ case '\t':
+ token = SPACE;
+ break;
+ case '&':
+ token = AMPERSAND;
+ break;
+ case '#':
+ token = HASH;
+ break;
+ case '\'':
+ token = QUOTE;
+ break;
+ case '\"':
+ token = DBLQUOTE;
+ break;
+ case '<':
+ token = LANGLE;
+ break;
+ case '>':
+ token = RANGLE;
+ break;
+ case '[':
+ token = LBRACK;
+ break;
+ case ']':
+ token = RBRACK;
+ break;
+ case '(':
+ token = LPAREN;
+ break;
+ case ')':
+ token = RPAREN;
+ break;
+ case '|':
+ token = PIPE;
+ break;
+ case '=':
+ token = EQ;
+ break;
+ case '%':
+ token = PERCENT;
+ break;
+ case '/':
+ token = SLASH;
+ break;
+ case ':':
+ token = COLON;
+ break;
+ case ';':
+ token = SEMICOLON;
+ break;
+ case ',':
+ token = COMMA;
+ break;
+ case '-':
+ token = DASH;
+ break;
+ case '+':
+ token = PLUS;
+ break;
+ case '*':
+ token = STAR;
+ break;
+ case '.':
+ token = DOT;
+ break;
+ case '?':
+ token = QUESTIONMARK;
+ break;
+ case '!':
+ token = BANG;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ token = DIGIT;
+ break;
+ default:
+ if (cu < 0x20)
+ token = NOTOKEN;
+ else
+ token = LETTER;
+ break;
+ }
+ }
+
+ act = t_action (act, token);
+ if (act == ACCEPT_STATE) {
+ // reset the parser in case someone resumes (process instructions can follow a valid document)
+ tos = 0;
+ state_stack[tos++] = 0;
+ state_stack[tos] = 0;
+ return true;
+ } else if (act > 0) {
+ if (++tos >= stack_size-1)
+ reallocateStack();
+
+ Value &val = sym_stack[tos];
+ val.c = token_char;
+ val.pos = textBuffer.size();
+ val.prefix = 0;
+ val.len = 1;
+ if (token_char)
+ textBuffer += QChar(token_char);
+
+ state_stack[tos] = act;
+ token = -1;
+
+
+ } else if (act < 0) {
+ r = - act - 1;
+
+#if defined (QLALR_DEBUG)
+ int ridx = rule_index[r];
+ printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
+ ++ridx;
+ for (int i = ridx; i < ridx + rhs[r]; ++i) {
+ int symbol = rule_info[i];
+ if (const char *name = spell[symbol])
+ printf (" %s", name);
+ else
+ printf (" #%d", symbol);
+ }
+ printf ("\n");
+#endif
+
+ tos -= rhs[r];
+ act = state_stack[tos++];
+ ResumeReduction:
+ switch (r) {
+
+ case 0:
+ setType(QXmlStreamReader::EndDocument);
+ break;
+
+ case 1:
+ if (type != QXmlStreamReader::Invalid) {
+ if (hasSeenTag || inParseEntity) {
+ setType(QXmlStreamReader::EndDocument);
+ } else {
+ raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected."));
+ // reset the parser
+ tos = 0;
+ state_stack[tos++] = 0;
+ state_stack[tos] = 0;
+ return false;
+ }
+ }
+ break;
+
+ case 10: {
+ auto reference = entityReferenceStack.pop();
+ auto it = reference.hash->find(reference.name);
+ Q_ASSERT(it != reference.hash->end());
+ it->isCurrentlyReferenced = false;
+ if (entityReferenceStack.isEmpty())
+ entityLength = 0;
+ clearSym();
+ } break;
+
+ case 11:
+ if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
+ resume(11);
+ return false;
+ }
+ break;
+
+ case 12:
+ setType(QXmlStreamReader::StartDocument);
+ documentVersion = symString(6);
+ startDocument();
+ break;
+
+ case 13:
+ hasExternalDtdSubset = true;
+ dtdSystemId = symString(2);
+ break;
+
+ case 14:
+ checkPublicLiteral(symString(2));
+ dtdPublicId = symString(2);
+ dtdSystemId = symString(4);
+ hasExternalDtdSubset = true;
+ break;
+
+ case 16:
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(16);
+ return false;
+ }
+ dtdName = symString(3);
+ break;
+
+ case 17:
+ case 18:
+ dtdName = symString(3);
+ Q_FALLTHROUGH();
+
+ case 19:
+ case 20:
+ setType(QXmlStreamReader::DTD);
+ text = &textBuffer;
+ break;
+
+ case 21:
+ scanDtd = true;
+ break;
+
+ case 22:
+ scanDtd = false;
+ break;
+
+ case 37:
+ if (!scanString(spell[EMPTY], EMPTY, false)
+ && !scanString(spell[ANY], ANY, false)
+ && atEnd) {
+ resume(37);
+ return false;
+ }
+ break;
+
+ case 43:
+ if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
+ resume(43);
+ return false;
+ }
+ break;
+
+ case 68: {
+ lastAttributeIsCData = true;
+ } break;
+
+ case 78:
+ if (!scanAfterDefaultDecl() && atEnd) {
+ resume(78);
+ return false;
+ }
+ break;
+
+ case 83:
+ sym(1) = sym(2);
+ lastAttributeValue.clear();
+ lastAttributeIsCData = false;
+ if (!scanAttType() && atEnd) {
+ resume(83);
+ return false;
+ }
+ break;
+
+ case 84: {
+ DtdAttribute &dtdAttribute = dtdAttributes.push();
+ dtdAttribute.tagName.clear();
+ dtdAttribute.isCDATA = lastAttributeIsCData;
+ dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
+ dtdAttribute.attributeName = addToStringStorage(symString(1));
+ dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
+ dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == "xmlns"_L1
+ || (dtdAttribute.attributePrefix.isEmpty()
+ && dtdAttribute.attributeName == "xmlns"_L1));
+ if (lastAttributeValue.isNull()) {
+ dtdAttribute.defaultValue.clear();
+ } else {
+ if (dtdAttribute.isCDATA)
+ dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
+ else
+ dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
+
+ }
+ } break;
+
+ case 88: {
+ if (referenceToUnparsedEntityDetected && !standalone)
+ break;
+ qsizetype n = dtdAttributes.size();
+ XmlStringRef tagName = addToStringStorage(symName(3));
+ while (n--) {
+ DtdAttribute &dtdAttribute = dtdAttributes[n];
+ if (!dtdAttribute.tagName.isNull())
+ break;
+ dtdAttribute.tagName = tagName;
+ for (qsizetype i = 0; i < n; ++i) {
+ if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
+ && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
+ dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
+ break;
+ }
+ }
+ }
+ } break;
+
+ case 89: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(89);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.push();
+ entityDeclaration.clear();
+ entityDeclaration.name = symString(3);
+ } break;
+
+ case 90: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(90);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.push();
+ entityDeclaration.clear();
+ entityDeclaration.name = symString(5);
+ entityDeclaration.parameter = true;
+ } break;
+
+ case 91: {
+ if (!scanNData() && atEnd) {
+ resume(91);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ entityDeclaration.systemId = symString(3);
+ entityDeclaration.external = true;
+ } break;
+
+ case 92: {
+ if (!scanNData() && atEnd) {
+ resume(92);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ checkPublicLiteral((entityDeclaration.publicId = symString(3)));
+ entityDeclaration.systemId = symString(5);
+ entityDeclaration.external = true;
+ } break;
+
+ case 93: {
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ entityDeclaration.notationName = symString(3);
+ if (entityDeclaration.parameter)
+ raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
+ }
+ Q_FALLTHROUGH();
+
+ case 94:
+ case 95: {
+ if (referenceToUnparsedEntityDetected && !standalone) {
+ entityDeclarations.pop();
+ break;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ if (!entityDeclaration.external)
+ entityDeclaration.value = symString(2);
+ auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
+ if (!hash.contains(entityDeclaration.name)) {
+ Entity entity(entityDeclaration.name.toString(),
+ entityDeclaration.value.toString());
+ entity.unparsed = (!entityDeclaration.notationName.isNull());
+ entity.external = entityDeclaration.external;
+ hash.insert(qToStringViewIgnoringNull(entity.name), entity);
+ }
+ } break;
+
+ case 96: {
+ setType(QXmlStreamReader::ProcessingInstruction);
+ const qsizetype pos = sym(4).pos + sym(4).len;
+ processingInstructionTarget = symString(3);
+ if (scanUntil("?>")) {
+ processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive)) {
+ raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
+ }
+ else if (!QXmlUtils::isNCName(processingInstructionTarget))
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
+ .arg(processingInstructionTarget));
+ } else if (type != QXmlStreamReader::Invalid){
+ resume(96);
+ return false;
+ }
+ } break;
+
+ case 97:
+ setType(QXmlStreamReader::ProcessingInstruction);
+ processingInstructionTarget = symString(3);
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive))
+ raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
+ break;
+
+ case 98:
+ if (!scanAfterLangleBang() && atEnd) {
+ resume(98);
+ return false;
+ }
+ break;
+
+ case 99:
+ if (!scanUntil("--")) {
+ resume(99);
+ return false;
+ }
+ break;
+
+ case 100: {
+ setType(QXmlStreamReader::Comment);
+ const qsizetype pos = sym(1).pos + 4;
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ } break;
+
+ case 101: {
+ setType(QXmlStreamReader::Characters);
+ isCDATA = true;
+ isWhitespace = false;
+ const qsizetype pos = sym(2).pos;
+ if (scanUntil("]]>", -1)) {
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ } else {
+ resume(101);
+ return false;
+ }
+ } break;
+
+ case 102: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(102);
+ return false;
+ }
+ NotationDeclaration &notationDeclaration = notationDeclarations.push();
+ notationDeclaration.name = symString(3);
+ } break;
+
+ case 103: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ notationDeclaration.systemId = symString(3);
+ notationDeclaration.publicId.clear();
+ } break;
+
+ case 104: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ notationDeclaration.systemId.clear();
+ checkPublicLiteral((notationDeclaration.publicId = symString(3)));
+ } break;
+
+ case 105: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ checkPublicLiteral((notationDeclaration.publicId = symString(3)));
+ notationDeclaration.systemId = symString(5);
+ } break;
+
+ case 129:
+ isWhitespace = false;
+ Q_FALLTHROUGH();
+
+ case 130:
+ sym(1).len += fastScanContentCharList();
+ if (atEnd && !inParseEntity) {
+ resume(130);
+ return false;
+ }
+ break;
+
+ case 139:
+ if (!textBuffer.isEmpty()) {
+ setType(QXmlStreamReader::Characters);
+ text = &textBuffer;
+ }
+ break;
+
+ case 140:
+ case 141:
+ clearSym();
+ break;
+
+ case 142:
+ case 143:
+ sym(1) = sym(2);
+ break;
+
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 173:
+ if (normalizeLiterals)
+ textBuffer.data()[textBuffer.size()-1] = u' ';
+ break;
+
+ case 174:
+ sym(1).len += fastScanLiteralContent();
+ if (atEnd) {
+ resume(174);
+ return false;
+ }
+ break;
+
+ case 175: {
+ if (!QXmlUtils::isPublicID(symString(1))) {
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
+ resume(175);
+ return false;
+ }
+ } break;
+
+ case 176:
+ case 177:
+ clearSym();
+ break;
+
+ case 178:
+ case 179:
+ sym(1) = sym(2);
+ break;
+
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 213:
+ case 214:
+ clearSym();
+ break;
+
+ case 215:
+ case 216:
+ sym(1) = sym(2);
+ lastAttributeValue = symString(1);
+ break;
+
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 229: {
+ XmlStringRef prefix = symPrefix(1);
+ if (prefix.isEmpty() && symString(1) == "xmlns"_L1 && namespaceProcessing) {
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+ namespaceDeclaration.prefix.clear();
+
+ const XmlStringRef ns(symString(5));
+ if (ns.view() == "http://www.w3.org/2000/xmlns/"_L1 ||
+ ns.view() == "http://www.w3.org/XML/1998/namespace"_L1)
+ raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+ else
+ namespaceDeclaration.namespaceUri = addToStringStorage(ns);
+ } else {
+ Attribute &attribute = attributeStack.push();
+ attribute.key = sym(1);
+ attribute.value = sym(5);
+
+ XmlStringRef attributeQualifiedName = symName(1);
+ bool normalize = false;
+ for (const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
+ if (!dtdAttribute.isCDATA
+ && dtdAttribute.tagName == qualifiedName
+ && dtdAttribute.attributeQualifiedName == attributeQualifiedName
+ ) {
+ normalize = true;
+ break;
+ }
+ }
+ if (normalize) {
+ // normalize attribute value (simplify and trim)
+ const qsizetype pos = textBuffer.size();
+ qsizetype n = 0;
+ bool wasSpace = true;
+ for (qsizetype i = 0; i < attribute.value.len; ++i) {
+ QChar c = textBuffer.at(attribute.value.pos + i);
+ if (c.unicode() == ' ') {
+ if (wasSpace)
+ continue;
+ wasSpace = true;
+ } else {
+ wasSpace = false;
+ }
+ textBuffer += textBuffer.at(attribute.value.pos + i);
+ ++n;
+ }
+ if (wasSpace)
+ while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
+ --n;
+ attribute.value.pos = pos;
+ attribute.value.len = n;
+ }
+ if (prefix == "xmlns"_L1 && namespaceProcessing) {
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+ XmlStringRef namespacePrefix = symString(attribute.key);
+ XmlStringRef namespaceUri = symString(attribute.value);
+ attributeStack.pop();
+ if (((namespacePrefix == "xml"_L1)
+ ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
+ || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
+ || namespaceUri.isEmpty()
+ || namespacePrefix == "xmlns"_L1)
+ raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+
+ namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
+ namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
+ }
+ }
+ } break;
+
+ case 235: {
+ normalizeLiterals = true;
+ Tag &tag = tagStack_push();
+ prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2));
+ name = tag.name = addToStringStorage(symString(2));
+ qualifiedName = tag.qualifiedName = addToStringStorage(symName(2));
+ if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
+ raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
+ } break;
+
+ case 236:
+ isEmptyElement = true;
+ Q_FALLTHROUGH();
+
+ case 237:
+ setType(QXmlStreamReader::StartElement);
+ resolveTag();
+ if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
+ raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
+ hasSeenTag = true;
+ break;
+
+ case 238: {
+ setType(QXmlStreamReader::EndElement);
+ Tag tag = tagStack_pop();
+
+ namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
+ name = tag.name;
+ qualifiedName = tag.qualifiedName;
+ if (qualifiedName != symName(3))
+ raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
+ } break;
+
+ case 239:
+ if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
+ break;
+ }
+ setType(QXmlStreamReader::EntityReference);
+ name = &unresolvedEntity;
+ break;
+
+ case 240: {
+ sym(1).len += sym(2).len + 1;
+ QStringView reference = symView(2);
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
+ if (entity.unparsed) {
+ raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
+ } else {
+ if (!entity.hasBeenParsed) {
+ parseEntity(entity.value);
+ entity.hasBeenParsed = true;
+ }
+ if (entity.literal)
+ putStringLiteral(entity.value);
+ else if (referenceEntity(&entityHash, entity))
+ putReplacement(entity.value);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ }
+ break;
+ }
+
+ if (entityResolver) {
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
+ if (!replacementText.isNull()) {
+ putReplacement(replacementText);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ break;
+ }
+ }
+
+ injectToken(UNRESOLVED_ENTITY);
+ unresolvedEntity = symString(2).toString();
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+
+ } break;
+
+ case 241: {
+ sym(1).len += sym(2).len + 1;
+ QStringView reference = symView(2);
+ if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
+ referenceToParameterEntityDetected = true;
+ Entity &entity = *it;
+ if (entity.unparsed || entity.external) {
+ referenceToUnparsedEntityDetected = true;
+ } else {
+ if (referenceEntity(&parameterEntityHash, entity))
+ putString(entity.value);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ }
+ } else if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
+ }
+ } break;
+
+ case 242:
+ sym(1).len += sym(2).len + 1;
+ break;
+
+ case 243: {
+ sym(1).len += sym(2).len + 1;
+ QStringView reference = symView(2);
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
+ if (entity.unparsed || entity.value.isNull()) {
+ raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
+ break;
+ }
+ if (!entity.hasBeenParsed) {
+ parseEntity(entity.value);
+ entity.hasBeenParsed = true;
+ }
+ if (entity.literal)
+ putStringLiteral(entity.value);
+ else if (referenceEntity(&entityHash, entity))
+ putReplacementInAttributeValue(entity.value);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ break;
+ }
+
+ if (entityResolver) {
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
+ if (!replacementText.isNull()) {
+ putReplacement(replacementText);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ break;
+ }
+ }
+ if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
+ }
+ } break;
+
+ case 244: {
+ if (char32_t s = resolveCharRef(3)) {
+ putStringLiteral(QChar::fromUcs4(s));
+ textBuffer.chop(3 + sym(3).len);
+ clearSym();
+ } else {
+ raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
+ }
+ } break;
+
+ case 247:
+ case 248:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 259:
+ sym(1).len += fastScanSpace();
+ if (atEnd) {
+ resume(259);
+ return false;
+ }
+ break;
+
+ case 262: {
+ Value &val = sym(1);
+ if (auto res = fastScanName(&val))
+ val.len += *res;
+ else
+ return false;
+
+ if (atEnd) {
+ resume(262);
+ return false;
+ }
+ } break;
+
+ case 263:
+ if (auto res = fastScanName())
+ sym(1).len += *res;
+ else
+ return false;
+
+ if (atEnd) {
+ resume(263);
+ return false;
+ }
+ break;
+
+ case 264:
+ case 265:
+ case 266:
+ case 267:
+ case 268:
+ sym(1).len += fastScanNMTOKEN();
+ if (atEnd) {
+ resume(268);
+ return false;
+ }
+
+ break;
+
+ default:
+ ;
+ } // switch
+ act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
+ if (type != QXmlStreamReader::NoToken)
+ return true;
+ } else {
+ parseError();
+ break;
+ }
+ }
+ return false;
+}
+
+#endif // feature xmlstreamreader
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/corelib/serialization/qxmlutils.cpp b/src/corelib/serialization/qxmlutils.cpp
index 01c84251fd..e6fae7c173 100644
--- a/src/corelib/serialization/qxmlutils.cpp
+++ b/src/corelib/serialization/qxmlutils.cpp
@@ -1,48 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qstring.h>
#include "qxmlutils_p.h"
+#include <private/qtools_p.h>
+
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
/* TODO:
* - isNameChar() doesn't have to be public, it's only needed in
* qdom.cpp -- refactor fixedXmlName() to use isNCName()
@@ -80,7 +48,7 @@ bool QXmlUtils::rangeContains(RangeIter begin, RangeIter end, const QChar c)
return cp >= begin->min;
while (begin != end) {
- int delta = (end - begin) / 2;
+ qptrdiff delta = (end - begin) / 2;
RangeIter mid = begin + delta;
if (mid->min > cp)
@@ -233,16 +201,12 @@ bool QXmlUtils::isEncName(QStringView encName)
if (encName.isEmpty())
return false;
const auto first = encName.front().unicode();
- if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')))
+ if (!(isAsciiLower(first) || isAsciiUpper(first)))
return false;
for (QChar ch : encName.mid(1)) {
const auto cp = ch.unicode();
- if ((cp >= 'a' && cp <= 'z')
- || (cp >= 'A' && cp <= 'Z')
- || (cp >= '0' && cp <= '9')
- || cp == '.' || cp == '_' || cp == '-') {
+ if (isAsciiLetterOrNumber(cp) || cp == '.' || cp == '_' || cp == '-')
continue;
- }
return false;
}
return true;
@@ -271,13 +235,16 @@ bool QXmlUtils::isLetter(const QChar c)
\sa {http://www.w3.org/TR/REC-xml/#NT-Char},
{Extensible Markup Language (XML) 1.0 (Fourth Edition), [2] Char}
*/
-bool QXmlUtils::isChar(const QChar c)
+bool QXmlUtils::isChar(const char32_t c)
{
- return (c.unicode() >= 0x0020 && c.unicode() <= 0xD7FF)
- || c.unicode() == 0x0009
- || c.unicode() == 0x000A
- || c.unicode() == 0x000D
- || (c.unicode() >= 0xE000 && c.unicode() <= 0xFFFD);
+ // The valid range is defined by https://www.w3.org/TR/REC-xml/#NT-Char as following:
+ // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ return (c >= 0x0020 && c <= 0xD7FF)
+ || c == 0x0009
+ || c == 0x000A
+ || c == 0x000D
+ || (c >= 0xE000 && c <= 0xFFFD)
+ || (c >= 0x10000 && c <= 0x10FFFF);
}
/*!
@@ -318,12 +285,8 @@ bool QXmlUtils::isPublicID(QStringView candidate)
for (QChar ch : candidate) {
const ushort cp = ch.unicode();
- if ((cp >= 'a' && cp <= 'z')
- || (cp >= 'A' && cp <= 'Z')
- || (cp >= '0' && cp <= '9'))
- {
+ if (isAsciiLetterOrNumber(cp))
continue;
- }
switch (cp)
{
@@ -371,16 +334,16 @@ bool QXmlUtils::isPublicID(QStringView candidate)
*/
bool QXmlUtils::isNCName(QStringView ncName)
{
- if(ncName.isEmpty())
+ if (ncName.isEmpty())
return false;
const QChar first(ncName.at(0));
- if(!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':')
+ if (!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':')
return false;
for (QChar at : ncName) {
- if(!QXmlUtils::isNameChar(at) || at == QLatin1Char(':'))
+ if (!QXmlUtils::isNameChar(at) || at == u':')
return false;
}
diff --git a/src/corelib/serialization/qxmlutils_p.h b/src/corelib/serialization/qxmlutils_p.h
index db6bddd5be..0ad1758979 100644
--- a/src/corelib/serialization/qxmlutils_p.h
+++ b/src/corelib/serialization/qxmlutils_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXMLUTILS_P_H
#define QXMLUTILS_P_H
@@ -69,7 +33,7 @@ class Q_CORE_EXPORT QXmlUtils
{
public:
static bool isEncName(QStringView encName);
- static bool isChar(const QChar c);
+ static bool isChar(const char32_t c);
static bool isNameChar(const QChar c);
static bool isLetter(const QChar c);
static bool isNCName(QStringView ncName);
diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri
deleted file mode 100644
index ff653ca8f3..0000000000
--- a/src/corelib/serialization/serialization.pri
+++ /dev/null
@@ -1,76 +0,0 @@
-# Qt data formats core module
-
-HEADERS += \
- serialization/qcborarray.h \
- serialization/qcborcommon.h \
- serialization/qcborcommon_p.h \
- serialization/qcbormap.h \
- serialization/qcborstream.h \
- serialization/qcborvalue.h \
- serialization/qcborvalue_p.h \
- serialization/qdatastream.h \
- serialization/qdatastream_p.h \
- serialization/qjson_p.h \
- serialization/qjsondocument.h \
- serialization/qjsonobject.h \
- serialization/qjsonvalue.h \
- serialization/qjsonarray.h \
- serialization/qjsonwriter_p.h \
- serialization/qjsonparser_p.h \
- serialization/qtextstream.h \
- serialization/qtextstream_p.h \
- serialization/qxmlstream.h \
- serialization/qxmlstream_p.h \
- serialization/qxmlutils_p.h
-
-SOURCES += \
- serialization/qcborcommon.cpp \
- serialization/qcbordiagnostic.cpp \
- serialization/qcborvalue.cpp \
- serialization/qdatastream.cpp \
- serialization/qjsoncbor.cpp \
- serialization/qjsondocument.cpp \
- serialization/qjsonobject.cpp \
- serialization/qjsonarray.cpp \
- serialization/qjsonvalue.cpp \
- serialization/qjsonwriter.cpp \
- serialization/qjsonparser.cpp \
- serialization/qtextstream.cpp \
- serialization/qxmlstream.cpp \
- serialization/qxmlutils.cpp
-
-qtConfig(cborstreamreader): {
- SOURCES += \
- serialization/qcborstreamreader.cpp
-
- HEADERS += \
- serialization/qcborstreamreader.h
-}
-
-qtConfig(cborstreamwriter): {
- SOURCES += \
- serialization/qcborstreamwriter.cpp
-
- HEADERS += \
- serialization/qcborstreamwriter.h
-}
-
-qtConfig(binaryjson): {
- HEADERS += \
- serialization/qbinaryjson_p.h \
- serialization/qbinaryjsonarray_p.h \
- serialization/qbinaryjsonobject_p.h \
- serialization/qbinaryjsonvalue_p.h
-
- SOURCES += \
- serialization/qbinaryjson.cpp \
- serialization/qbinaryjsonarray.cpp \
- serialization/qbinaryjsonobject.cpp \
- serialization/qbinaryjsonvalue.cpp \
-}
-
-false: SOURCES += \
- serialization/qcborarray.cpp \
- serialization/qcbormap.cpp
-
-INCLUDEPATH += ../3rdparty/tinycbor/src
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
deleted file mode 100644
index 10f54c3e18..0000000000
--- a/src/corelib/statemachine/qabstractstate.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qabstractstate.h"
-#include "qabstractstate_p.h"
-#include "qstate.h"
-#include "qstate_p.h"
-#include "qstatemachine.h"
-#include "qstatemachine_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QAbstractState
- \inmodule QtCore
-
- \brief The QAbstractState class is the base class of states of a QStateMachine.
-
- \since 4.6
- \ingroup statemachine
-
- The QAbstractState class is the abstract base class of states that are part
- of a QStateMachine. It defines the interface that all state objects have in
- common. QAbstractState is part of \l{The State Machine Framework}.
-
- The entered() signal is emitted when the state has been entered. The
- exited() signal is emitted when the state has been exited.
-
- The parentState() function returns the state's parent state. The machine()
- function returns the state machine that the state is part of.
-
- \section1 Subclassing
-
- The onEntry() function is called when the state is entered; reimplement this
- function to perform custom processing when the state is entered.
-
- The onExit() function is called when the state is exited; reimplement this
- function to perform custom processing when the state is exited.
-*/
-
-/*!
- \property QAbstractState::active
- \since 5.4
-
- \brief the active property of this state. A state is active between
- entered() and exited() signals.
-*/
-
-
-QAbstractStatePrivate::QAbstractStatePrivate(StateType type)
- : stateType(type), isMachine(false), active(false), parentState(nullptr)
-{
-}
-
-QStateMachine *QAbstractStatePrivate::machine() const
-{
- QObject *par = parent;
- while (par != nullptr) {
- if (QStateMachine *mach = qobject_cast<QStateMachine*>(par))
- return mach;
- par = par->parent();
- }
- return nullptr;
-}
-
-void QAbstractStatePrivate::callOnEntry(QEvent *e)
-{
- Q_Q(QAbstractState);
- q->onEntry(e);
-}
-
-void QAbstractStatePrivate::callOnExit(QEvent *e)
-{
- Q_Q(QAbstractState);
- q->onExit(e);
-}
-
-void QAbstractStatePrivate::emitEntered()
-{
- Q_Q(QAbstractState);
- emit q->entered(QAbstractState::QPrivateSignal());
- if (!active) {
- active = true;
- emit q->activeChanged(true);
- }
-}
-
-void QAbstractStatePrivate::emitExited()
-{
- Q_Q(QAbstractState);
- if (active) {
- active = false;
- emit q->activeChanged(false);
- }
- emit q->exited(QAbstractState::QPrivateSignal());
-}
-
-/*!
- Constructs a new state with the given \a parent state.
-*/
-QAbstractState::QAbstractState(QState *parent)
- : QObject(*new QAbstractStatePrivate(QAbstractStatePrivate::AbstractState), parent)
-{
-}
-
-/*!
- \internal
-*/
-QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent)
- : QObject(dd, parent)
-{
-}
-
-/*!
- Destroys this state.
-*/
-QAbstractState::~QAbstractState()
-{
-}
-
-/*!
- Returns this state's parent state, or \nullptr if the state has no
- parent state.
-*/
-QState *QAbstractState::parentState() const
-{
- Q_D(const QAbstractState);
- if (d->parentState != parent())
- d->parentState = qobject_cast<QState*>(parent());
- return d->parentState;
-}
-
-/*!
- Returns the state machine that this state is part of, or \nullptr if
- the state is not part of a state machine.
-*/
-QStateMachine *QAbstractState::machine() const
-{
- Q_D(const QAbstractState);
- return d->machine();
-}
-
-/*!
- Returns whether this state is active.
-
- \sa activeChanged(bool), entered(), exited()
-*/
-bool QAbstractState::active() const
-{
- Q_D(const QAbstractState);
- return d->active;
-}
-
-/*!
- \fn QAbstractState::onExit(QEvent *event)
-
- This function is called when the state is exited. The given \a event is what
- caused the state to be exited. Reimplement this function to perform custom
- processing when the state is exited.
-*/
-
-/*!
- \fn QAbstractState::onEntry(QEvent *event)
-
- This function is called when the state is entered. The given \a event is
- what caused the state to be entered. Reimplement this function to perform
- custom processing when the state is entered.
-*/
-
-/*!
- \fn QAbstractState::entered()
-
- This signal is emitted when the state has been entered (after onEntry() has
- been called).
-*/
-
-/*!
- \fn QAbstractState::exited()
-
- This signal is emitted when the state has been exited (after onExit() has
- been called).
-*/
-
-/*!
- \fn QAbstractState::activeChanged(bool active)
- \since 5.4
-
- This signal is emitted when the active property is changed with \a active as argument.
-
- \sa QAbstractState::active, entered(), exited()
-*/
-
-/*!
- \reimp
-*/
-bool QAbstractState::event(QEvent *e)
-{
- return QObject::event(e);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qabstractstate.cpp"
diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h
deleted file mode 100644
index ffc2eaae13..0000000000
--- a/src/corelib/statemachine/qabstractstate.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QABSTRACTSTATE_H
-#define QABSTRACTSTATE_H
-
-#include <QtCore/qobject.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QState;
-class QStateMachine;
-
-class QAbstractStatePrivate;
-class Q_CORE_EXPORT QAbstractState : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool active READ active NOTIFY activeChanged)
-public:
- ~QAbstractState();
-
- QState *parentState() const;
- QStateMachine *machine() const;
-
- bool active() const;
-
-Q_SIGNALS:
- void entered(QPrivateSignal);
- void exited(QPrivateSignal);
- void activeChanged(bool active);
-
-protected:
- QAbstractState(QState *parent = nullptr);
-
- virtual void onEntry(QEvent *event) = 0;
- virtual void onExit(QEvent *event) = 0;
-
- bool event(QEvent *e) override;
-
-protected:
- QAbstractState(QAbstractStatePrivate &dd, QState *parent);
-
-private:
- Q_DISABLE_COPY(QAbstractState)
- Q_DECLARE_PRIVATE(QAbstractState)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h
deleted file mode 100644
index 11befc187e..0000000000
--- a/src/corelib/statemachine/qabstractstate_p.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QABSTRACTSTATE_P_H
-#define QABSTRACTSTATE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qobject_p.h>
-#include <QtCore/qabstractstate.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QStateMachine;
-
-class QState;
-class QAbstractStatePrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QAbstractState)
-
-public:
- enum StateType {
- AbstractState,
- StandardState,
- FinalState,
- HistoryState
- };
-
- QAbstractStatePrivate(StateType type);
-
- static QAbstractStatePrivate *get(QAbstractState *q)
- { return q->d_func(); }
- static const QAbstractStatePrivate *get(const QAbstractState *q)
- { return q->d_func(); }
-
- QStateMachine *machine() const;
-
- void callOnEntry(QEvent *e);
- void callOnExit(QEvent *e);
-
- void emitEntered();
- void emitExited();
-
- uint stateType:30;
- uint isMachine:1;
- bool active:1;
- mutable QState *parentState;
-};
-
-QT_END_NAMESPACE
-
-#endif // QABSTRACTSTATE_P_H
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
deleted file mode 100644
index df70b54721..0000000000
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qabstracttransition.h"
-#include "qabstracttransition_p.h"
-#include "qabstractstate.h"
-#include "qhistorystate.h"
-#include "qstate.h"
-#include "qstatemachine.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QAbstractTransition
- \inmodule QtCore
-
- \brief The QAbstractTransition class is the base class of transitions between QAbstractState objects.
-
- \since 4.6
- \ingroup statemachine
-
- The QAbstractTransition class is the abstract base class of transitions
- between states (QAbstractState objects) of a
- QStateMachine. QAbstractTransition is part of \l{The State Machine
- Framework}.
-
- The sourceState() function returns the source of the transition. The
- targetStates() function returns the targets of the transition. The machine()
- function returns the state machine that the transition is part of.
-
- The triggered() signal is emitted when the transition has been triggered.
-
- Transitions can cause animations to be played. Use the addAnimation()
- function to add an animation to the transition.
-
- \section1 Subclassing
-
- The eventTest() function is called by the state machine to determine whether
- an event should trigger the transition. In your reimplementation you
- typically check the event type and cast the event object to the proper type,
- and check that one or more properties of the event meet your criteria.
-
- The onTransition() function is called when the transition is triggered;
- reimplement this function to perform custom processing for the transition.
-*/
-
-/*!
- \property QAbstractTransition::sourceState
-
- \brief the source state (parent) of this transition
-*/
-
-/*!
- \property QAbstractTransition::targetState
-
- \brief the target state of this transition
-
- If a transition has no target state, the transition may still be
- triggered, but this will not cause the state machine's configuration to
- change (i.e. the current state will not be exited and re-entered).
-*/
-
-/*!
- \property QAbstractTransition::targetStates
-
- \brief the target states of this transition
-
- If multiple states are specified, all must be descendants of the same
- parallel group state.
-*/
-
-/*!
- \property QAbstractTransition::transitionType
-
- \brief indicates whether this transition is an internal transition, or an external transition.
-
- Internal and external transitions behave the same, except for the case of a transition whose
- source state is a compound state and whose target(s) is a descendant of the source. In such a
- case, an internal transition will not exit and re-enter its source state, while an external one
- will.
-
- By default, the type is an external transition.
-*/
-
-/*!
- \enum QAbstractTransition::TransitionType
-
- This enum specifies the kind of transition. By default, the type is an external transition.
-
- \value ExternalTransition Any state that is the source state of a transition (which is not a
- target-less transition) is left, and re-entered when necessary.
- \value InternalTransition If the target state of a transition is a sub-state of a compound state,
- and that compound state is the source state, an internal transition will
- not leave the source state.
-
- \sa QAbstractTransition::transitionType
-*/
-
-QAbstractTransitionPrivate::QAbstractTransitionPrivate()
- : transitionType(QAbstractTransition::ExternalTransition)
-{
-}
-
-QStateMachine *QAbstractTransitionPrivate::machine() const
-{
- if (QState *source = sourceState())
- return source->machine();
- Q_Q(const QAbstractTransition);
- if (QHistoryState *parent = qobject_cast<QHistoryState *>(q->parent()))
- return parent->machine();
- return nullptr;
-}
-
-bool QAbstractTransitionPrivate::callEventTest(QEvent *e)
-{
- Q_Q(QAbstractTransition);
- return q->eventTest(e);
-}
-
-void QAbstractTransitionPrivate::callOnTransition(QEvent *e)
-{
- Q_Q(QAbstractTransition);
- q->onTransition(e);
-}
-
-QState *QAbstractTransitionPrivate::sourceState() const
-{
- return qobject_cast<QState*>(parent);
-}
-
-void QAbstractTransitionPrivate::emitTriggered()
-{
- Q_Q(QAbstractTransition);
- emit q->triggered(QAbstractTransition::QPrivateSignal());
-}
-
-/*!
- Constructs a new QAbstractTransition object with the given \a sourceState.
-*/
-QAbstractTransition::QAbstractTransition(QState *sourceState)
- : QObject(*new QAbstractTransitionPrivate, sourceState)
-{
-}
-
-/*!
- \internal
-*/
-QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
- QState *parent)
- : QObject(dd, parent)
-{
-}
-
-/*!
- Destroys this transition.
-*/
-QAbstractTransition::~QAbstractTransition()
-{
-}
-
-/*!
- Returns the source state of this transition, or \nullptr if this
- transition has no source state.
-*/
-QState *QAbstractTransition::sourceState() const
-{
- Q_D(const QAbstractTransition);
- return d->sourceState();
-}
-
-/*!
- Returns the target state of this transition, or \nullptr if the
- transition has no target.
-*/
-QAbstractState *QAbstractTransition::targetState() const
-{
- Q_D(const QAbstractTransition);
- if (d->targetStates.isEmpty())
- return nullptr;
- return d->targetStates.first().data();
-}
-
-/*!
- Sets the \a target state of this transition.
-*/
-void QAbstractTransition::setTargetState(QAbstractState* target)
-{
- Q_D(QAbstractTransition);
- if ((d->targetStates.size() == 1 && target == d->targetStates.at(0).data()) ||
- (d->targetStates.isEmpty() && target == nullptr)) {
- return;
- }
- if (!target)
- d->targetStates.clear();
- else
- setTargetStates(QList<QAbstractState*>() << target);
- emit targetStateChanged(QPrivateSignal());
-}
-
-/*!
- Returns the target states of this transition, or an empty list if this
- transition has no target states.
-*/
-QList<QAbstractState*> QAbstractTransition::targetStates() const
-{
- Q_D(const QAbstractTransition);
- QList<QAbstractState*> result;
- for (int i = 0; i < d->targetStates.size(); ++i) {
- QAbstractState *target = d->targetStates.at(i).data();
- if (target)
- result.append(target);
- }
- return result;
-}
-
-/*!
- Sets the target states of this transition to be the given \a targets.
-*/
-void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
-{
- Q_D(QAbstractTransition);
-
- // Verify if any of the new target states is a null-pointer:
- for (int i = 0; i < targets.size(); ++i) {
- if (targets.at(i) == nullptr) {
- qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
- return;
- }
- }
-
- // First clean out any target states that got destroyed, but for which we still have a QPointer
- // around.
- for (int i = 0; i < d->targetStates.size(); ) {
- if (d->targetStates.at(i).isNull()) {
- d->targetStates.remove(i);
- } else {
- ++i;
- }
- }
-
- // Easy check: if both lists are empty, we're done.
- if (targets.isEmpty() && d->targetStates.isEmpty())
- return;
-
- bool sameList = true;
-
- if (targets.size() != d->targetStates.size()) {
- // If the sizes of the lists are different, we don't need to be smart: they're different. So
- // we can just set the new list as the targetStates.
- sameList = false;
- } else {
- QVector<QPointer<QAbstractState> > copy(d->targetStates);
- for (int i = 0; i < targets.size(); ++i) {
- sameList &= copy.removeOne(targets.at(i));
- if (!sameList)
- break; // ok, we now know the lists are not the same, so stop the loop.
- }
-
- sameList &= copy.isEmpty();
- }
-
- if (sameList)
- return;
-
- d->targetStates.resize(targets.size());
- for (int i = 0; i < targets.size(); ++i) {
- d->targetStates[i] = targets.at(i);
- }
-
- emit targetStatesChanged(QPrivateSignal());
-}
-
-/*!
- Returns the type of the transition.
-*/
-QAbstractTransition::TransitionType QAbstractTransition::transitionType() const
-{
- Q_D(const QAbstractTransition);
- return d->transitionType;
-}
-
-/*!
- Sets the type of the transition to \a type.
-*/
-void QAbstractTransition::setTransitionType(TransitionType type)
-{
- Q_D(QAbstractTransition);
- d->transitionType = type;
-}
-
-/*!
- Returns the state machine that this transition is part of, or
- \nullptr if the transition is not part of a state machine.
-*/
-QStateMachine *QAbstractTransition::machine() const
-{
- Q_D(const QAbstractTransition);
- return d->machine();
-}
-
-#if QT_CONFIG(animation)
-
-/*!
- Adds the given \a animation to this transition.
- The transition does not take ownership of the animation.
-
- \sa removeAnimation(), animations()
-*/
-void QAbstractTransition::addAnimation(QAbstractAnimation *animation)
-{
- Q_D(QAbstractTransition);
- if (!animation) {
- qWarning("QAbstractTransition::addAnimation: cannot add null animation");
- return;
- }
- d->animations.append(animation);
-}
-
-/*!
- Removes the given \a animation from this transition.
-
- \sa addAnimation()
-*/
-void QAbstractTransition::removeAnimation(QAbstractAnimation *animation)
-{
- Q_D(QAbstractTransition);
- if (!animation) {
- qWarning("QAbstractTransition::removeAnimation: cannot remove null animation");
- return;
- }
- d->animations.removeOne(animation);
-}
-
-/*!
- Returns the list of animations associated with this transition, or an empty
- list if it has no animations.
-
- \sa addAnimation()
-*/
-QList<QAbstractAnimation*> QAbstractTransition::animations() const
-{
- Q_D(const QAbstractTransition);
- return d->animations;
-}
-
-#endif
-
-/*!
- \fn QAbstractTransition::eventTest(QEvent *event)
-
- This function is called to determine whether the given \a event should cause
- this transition to trigger. Reimplement this function and return true if the
- event should trigger the transition, otherwise return false.
-*/
-
-/*!
- \fn QAbstractTransition::onTransition(QEvent *event)
-
- This function is called when the transition is triggered. The given \a event
- is what caused the transition to trigger. Reimplement this function to
- perform custom processing when the transition is triggered.
-*/
-
-/*!
- \fn QAbstractTransition::triggered()
-
- This signal is emitted when the transition has been triggered (after
- onTransition() has been called).
-*/
-
-/*!
- \fn QAbstractTransition::targetStateChanged()
- \since 5.4
-
- This signal is emitted when the targetState property is changed.
-
- \sa QAbstractTransition::targetState
-*/
-
-/*!
- \fn QAbstractTransition::targetStatesChanged()
- \since 5.4
-
- This signal is emitted when the targetStates property is changed.
-
- \sa QAbstractTransition::targetStates
-*/
-
-/*!
- \reimp
-*/
-bool QAbstractTransition::event(QEvent *e)
-{
- return QObject::event(e);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qabstracttransition.cpp"
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
deleted file mode 100644
index 357e829b6a..0000000000
--- a/src/corelib/statemachine/qabstracttransition.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QABSTRACTTRANSITION_H
-#define QABSTRACTTRANSITION_H
-
-#include <QtCore/qobject.h>
-
-#include <QtCore/qlist.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QEvent;
-class QAbstractState;
-class QState;
-class QStateMachine;
-
-#if QT_CONFIG(animation)
-class QAbstractAnimation;
-#endif
-
-class QAbstractTransitionPrivate;
-class Q_CORE_EXPORT QAbstractTransition : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QState* sourceState READ sourceState)
- Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState NOTIFY targetStateChanged)
- Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates NOTIFY targetStatesChanged)
- Q_PROPERTY(TransitionType transitionType READ transitionType WRITE setTransitionType REVISION(1, 1))
-public:
- enum TransitionType {
- ExternalTransition,
- InternalTransition
- };
- Q_ENUM(TransitionType)
-
- QAbstractTransition(QState *sourceState = nullptr);
- virtual ~QAbstractTransition();
-
- QState *sourceState() const;
- QAbstractState *targetState() const;
- void setTargetState(QAbstractState* target);
- QList<QAbstractState*> targetStates() const;
- void setTargetStates(const QList<QAbstractState*> &targets);
-
- TransitionType transitionType() const;
- void setTransitionType(TransitionType type);
-
- QStateMachine *machine() const;
-
-#if QT_CONFIG(animation)
- void addAnimation(QAbstractAnimation *animation);
- void removeAnimation(QAbstractAnimation *animation);
- QList<QAbstractAnimation*> animations() const;
-#endif
-
-Q_SIGNALS:
- void triggered(QPrivateSignal);
- void targetStateChanged(QPrivateSignal);
- void targetStatesChanged(QPrivateSignal);
-
-protected:
- virtual bool eventTest(QEvent *event) = 0;
-
- virtual void onTransition(QEvent *event) = 0;
-
- bool event(QEvent *e) override;
-
-protected:
- QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent);
-
-private:
- Q_DISABLE_COPY(QAbstractTransition)
- Q_DECLARE_PRIVATE(QAbstractTransition)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
deleted file mode 100644
index 663d777c75..0000000000
--- a/src/corelib/statemachine/qabstracttransition_p.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QABSTRACTTRANSITION_P_H
-#define QABSTRACTTRANSITION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qobject_p.h>
-
-#include <QtCore/qlist.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qsharedpointer.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QAbstractState;
-class QState;
-class QStateMachine;
-
-class QAbstractTransition;
-class Q_CORE_EXPORT QAbstractTransitionPrivate
- : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QAbstractTransition)
-public:
- QAbstractTransitionPrivate();
-
- static QAbstractTransitionPrivate *get(QAbstractTransition *q)
- { return q->d_func(); }
-
- bool callEventTest(QEvent *e);
- virtual void callOnTransition(QEvent *e);
- QState *sourceState() const;
- QStateMachine *machine() const;
- void emitTriggered();
-
- QVector<QPointer<QAbstractState> > targetStates;
- QAbstractTransition::TransitionType transitionType;
-
-#if QT_CONFIG(animation)
- QList<QAbstractAnimation*> animations;
-#endif
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
deleted file mode 100644
index 5dcbcfff47..0000000000
--- a/src/corelib/statemachine/qeventtransition.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qeventtransition.h"
-#include "qeventtransition_p.h"
-#include "qstate.h"
-#include "qstate_p.h"
-#include "qstatemachine.h"
-#include "qstatemachine_p.h"
-#include <qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QEventTransition
- \inmodule QtCore
-
- \brief The QEventTransition class provides a QObject-specific transition for Qt events.
-
- \since 4.6
- \ingroup statemachine
-
- A QEventTransition object binds an event to a particular QObject.
- QEventTransition is part of \l{The State Machine Framework}.
-
- Example:
-
- \code
- QPushButton *button = ...;
- QState *s1 = ...;
- QState *s2 = ...;
- // If in s1 and the button receives an Enter event, transition to s2
- QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter);
- enterTransition->setTargetState(s2);
- s1->addTransition(enterTransition);
- // If in s2 and the button receives an Exit event, transition back to s1
- QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave);
- leaveTransition->setTargetState(s1);
- s2->addTransition(leaveTransition);
- \endcode
-
- \section1 Subclassing
-
- When reimplementing the eventTest() function, you should first call the base
- implementation to verify that the event is a QStateMachine::WrappedEvent for
- the proper object and event type. You may then cast the event to a
- QStateMachine::WrappedEvent and get the original event by calling
- QStateMachine::WrappedEvent::event(), and perform additional checks on that
- object.
-
- \sa QState::addTransition()
-*/
-
-/*!
- \property QEventTransition::eventSource
-
- \brief the event source that this event transition is associated with
-*/
-
-/*!
- \property QEventTransition::eventType
-
- \brief the type of event that this event transition is associated with
-*/
-QEventTransitionPrivate::QEventTransitionPrivate()
-{
- object = nullptr;
- eventType = QEvent::None;
- registered = false;
-}
-
-QEventTransitionPrivate::~QEventTransitionPrivate()
-{
-}
-
-void QEventTransitionPrivate::unregister()
-{
- Q_Q(QEventTransition);
- if (!registered || !machine())
- return;
- QStateMachinePrivate::get(machine())->unregisterEventTransition(q);
-}
-
-void QEventTransitionPrivate::maybeRegister()
-{
- Q_Q(QEventTransition);
- if (QStateMachine *mach = machine())
- QStateMachinePrivate::get(mach)->maybeRegisterEventTransition(q);
-}
-
-/*!
- Constructs a new QEventTransition object with the given \a sourceState.
-*/
-QEventTransition::QEventTransition(QState *sourceState)
- : QAbstractTransition(*new QEventTransitionPrivate, sourceState)
-{
-}
-
-/*!
- Constructs a new QEventTransition object associated with events of the given
- \a type for the given \a object, and with the given \a sourceState.
-*/
-QEventTransition::QEventTransition(QObject *object, QEvent::Type type,
- QState *sourceState)
- : QAbstractTransition(*new QEventTransitionPrivate, sourceState)
-{
- Q_D(QEventTransition);
- d->registered = false;
- d->object = object;
- d->eventType = type;
- d->maybeRegister();
-}
-
-/*!
- \internal
-*/
-QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent)
- : QAbstractTransition(dd, parent)
-{
-}
-
-/*!
- \internal
-*/
-QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object,
- QEvent::Type type, QState *parent)
- : QAbstractTransition(dd, parent)
-{
- Q_D(QEventTransition);
- d->registered = false;
- d->object = object;
- d->eventType = type;
- d->maybeRegister();
-}
-
-/*!
- Destroys this QObject event transition.
-*/
-QEventTransition::~QEventTransition()
-{
-}
-
-/*!
- Returns the event type that this event transition is associated with.
-*/
-QEvent::Type QEventTransition::eventType() const
-{
- Q_D(const QEventTransition);
- return d->eventType;
-}
-
-/*!
- Sets the event \a type that this event transition is associated with.
-*/
-void QEventTransition::setEventType(QEvent::Type type)
-{
- Q_D(QEventTransition);
- if (d->eventType == type)
- return;
- d->unregister();
- d->eventType = type;
- d->maybeRegister();
-}
-
-/*!
- Returns the event source associated with this event transition.
-*/
-QObject *QEventTransition::eventSource() const
-{
- Q_D(const QEventTransition);
- return d->object;
-}
-
-/*!
- Sets the event source associated with this event transition to be the given
- \a object.
-*/
-void QEventTransition::setEventSource(QObject *object)
-{
- Q_D(QEventTransition);
- if (d->object == object)
- return;
- d->unregister();
- d->object = object;
- d->maybeRegister();
-}
-
-/*!
- \reimp
-*/
-bool QEventTransition::eventTest(QEvent *event)
-{
- Q_D(const QEventTransition);
- if (event->type() == QEvent::StateMachineWrapped) {
- QStateMachine::WrappedEvent *we = static_cast<QStateMachine::WrappedEvent*>(event);
- return (we->object() == d->object)
- && (we->event()->type() == d->eventType);
- }
- return false;
-}
-
-/*!
- \reimp
-*/
-void QEventTransition::onTransition(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-bool QEventTransition::event(QEvent *e)
-{
- return QAbstractTransition::event(e);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qeventtransition.cpp"
diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h
deleted file mode 100644
index ff4a991162..0000000000
--- a/src/corelib/statemachine/qeventtransition.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QEVENTTRANSITION_H
-#define QEVENTTRANSITION_H
-
-#include <QtCore/qabstracttransition.h>
-#include <QtCore/qcoreevent.h>
-
-QT_REQUIRE_CONFIG(qeventtransition);
-
-QT_BEGIN_NAMESPACE
-
-class QEventTransitionPrivate;
-class Q_CORE_EXPORT QEventTransition : public QAbstractTransition
-{
- Q_OBJECT
- Q_PROPERTY(QObject* eventSource READ eventSource WRITE setEventSource)
- Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType)
-public:
- QEventTransition(QState *sourceState = nullptr);
- QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = nullptr);
- ~QEventTransition();
-
- QObject *eventSource() const;
- void setEventSource(QObject *object);
-
- QEvent::Type eventType() const;
- void setEventType(QEvent::Type type);
-
-protected:
- bool eventTest(QEvent *event) override;
- void onTransition(QEvent *event) override;
-
- bool event(QEvent *e) override;
-
-protected:
- QEventTransition(QEventTransitionPrivate &dd, QState *parent);
- QEventTransition(QEventTransitionPrivate &dd, QObject *object,
- QEvent::Type type, QState *parent);
-
-private:
- Q_DISABLE_COPY(QEventTransition)
- Q_DECLARE_PRIVATE(QEventTransition)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h
deleted file mode 100644
index e30e12bc8d..0000000000
--- a/src/corelib/statemachine/qeventtransition_p.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QEVENTTRANSITION_P_H
-#define QEVENTTRANSITION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "private/qabstracttransition_p.h"
-
-QT_REQUIRE_CONFIG(qeventtransition);
-
-QT_BEGIN_NAMESPACE
-
-class QEventTransition;
-class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate
-{
- Q_DECLARE_PUBLIC(QEventTransition)
-public:
- QEventTransitionPrivate();
- ~QEventTransitionPrivate();
-
- static QEventTransitionPrivate *get(QEventTransition *q)
- { return q->d_func(); }
-
- void unregister();
- void maybeRegister();
-
- QObject *object;
- bool registered;
- QEvent::Type eventType;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp
deleted file mode 100644
index d8bfd30974..0000000000
--- a/src/corelib/statemachine/qfinalstate.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qfinalstate_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QFinalState
- \inmodule QtCore
-
- \brief The QFinalState class provides a final state.
-
- \since 4.6
- \ingroup statemachine
-
- A final state is used to communicate that (part of) a QStateMachine has
- finished its work. When a final top-level state is entered, the state
- machine's \l{QStateMachine::finished()}{finished}() signal is emitted. In
- general, when a final substate (a child of a QState) is entered, the parent
- state's \l{QState::finished()}{finished}() signal is emitted. QFinalState
- is part of \l{The State Machine Framework}.
-
- To use a final state, you create a QFinalState object and add a transition
- to it from another state. Example:
-
- \code
- QPushButton button;
-
- QStateMachine machine;
- QState *s1 = new QState();
- QFinalState *s2 = new QFinalState();
- s1->addTransition(&button, SIGNAL(clicked()), s2);
- machine.addState(s1);
- machine.addState(s2);
-
- QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));
- machine.setInitialState(s1);
- machine.start();
- \endcode
-
- \sa QState::finished()
-*/
-
-QFinalStatePrivate::QFinalStatePrivate()
- : QAbstractStatePrivate(FinalState)
-{
-}
-
-QFinalStatePrivate::~QFinalStatePrivate()
-{
- // to prevent vtables being generated in every file that includes the private header
-}
-
-/*!
- Constructs a new QFinalState object with the given \a parent state.
-*/
-QFinalState::QFinalState(QState *parent)
- : QAbstractState(*new QFinalStatePrivate, parent)
-{
-}
-
-/*!
- \internal
- */
-QFinalState::QFinalState(QFinalStatePrivate &dd, QState *parent)
- : QAbstractState(dd, parent)
-{
-}
-
-
-/*!
- Destroys this final state.
-*/
-QFinalState::~QFinalState()
-{
-}
-
-/*!
- \reimp
-*/
-void QFinalState::onEntry(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-void QFinalState::onExit(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-bool QFinalState::event(QEvent *e)
-{
- return QAbstractState::event(e);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qfinalstate.cpp"
diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h
deleted file mode 100644
index 1e52a0411d..0000000000
--- a/src/corelib/statemachine/qfinalstate.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFINALSTATE_H
-#define QFINALSTATE_H
-
-#include <QtCore/qabstractstate.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QFinalStatePrivate;
-class Q_CORE_EXPORT QFinalState : public QAbstractState
-{
- Q_OBJECT
-public:
- QFinalState(QState *parent = nullptr);
- ~QFinalState();
-
-protected:
- void onEntry(QEvent *event) override;
- void onExit(QEvent *event) override;
-
- bool event(QEvent *e) override;
-
-protected:
- explicit QFinalState(QFinalStatePrivate &dd, QState *parent);
-
-private:
- Q_DISABLE_COPY(QFinalState)
- Q_DECLARE_PRIVATE(QFinalState)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qfinalstate_p.h b/src/corelib/statemachine/qfinalstate_p.h
deleted file mode 100644
index 65598f6c19..0000000000
--- a/src/corelib/statemachine/qfinalstate_p.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFINALSTATE_P_H
-#define QFINALSTATE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qfinalstate.h"
-#include "private/qabstractstate_p.h"
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class Q_CORE_EXPORT QFinalStatePrivate : public QAbstractStatePrivate
-{
- Q_DECLARE_PUBLIC(QFinalState)
-
-public:
- QFinalStatePrivate();
- ~QFinalStatePrivate();
-};
-
-QT_END_NAMESPACE
-
-#endif // QFINALSTATE_P_H
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
deleted file mode 100644
index e5b8075b96..0000000000
--- a/src/corelib/statemachine/qhistorystate.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qhistorystate.h"
-#include "qhistorystate_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QHistoryState
- \inmodule QtCore
-
- \brief The QHistoryState class provides a means of returning to a previously active substate.
-
- \since 4.6
- \ingroup statemachine
-
- A history state is a pseudo-state that represents the child state that the
- parent state was in the last time the parent state was exited. A transition
- with a history state as its target is in fact a transition to one or more
- other child states of the parent state. QHistoryState is part of \l{The
- State Machine Framework}.
-
- Use the setDefaultState() function to set the state that should be entered
- if the parent state has never been entered. Example:
-
- \code
- QStateMachine machine;
-
- QState *s1 = new QState();
- QState *s11 = new QState(s1);
- QState *s12 = new QState(s1);
-
- QHistoryState *s1h = new QHistoryState(s1);
- s1h->setDefaultState(s11);
-
- machine.addState(s1);
-
- QState *s2 = new QState();
- machine.addState(s2);
-
- QPushButton *button = new QPushButton();
- // Clicking the button will cause the state machine to enter the child state
- // that s1 was in the last time s1 was exited, or the history state's default
- // state if s1 has never been entered.
- s1->addTransition(button, SIGNAL(clicked()), s1h);
- \endcode
-
- If more than one default state has to be entered, or if the transition to the default state(s)
- has to be acted upon, the defaultTransition should be set instead. Note that the eventTest()
- method of that transition will never be called: the selection and execution of the transition is
- done automatically when entering the history state.
-
- By default a history state is shallow, meaning that it won't remember nested
- states. This can be configured through the historyType property.
-*/
-
-/*!
- \property QHistoryState::defaultTransition
-
- \brief the default transition of this history state
-*/
-
-/*!
- \property QHistoryState::defaultState
-
- \brief the default state of this history state
-*/
-
-/*!
- \property QHistoryState::historyType
-
- \brief the type of history that this history state records
-
- The default value of this property is QHistoryState::ShallowHistory.
-*/
-
-/*!
- \enum QHistoryState::HistoryType
-
- This enum specifies the type of history that a QHistoryState records.
-
- \value ShallowHistory Only the immediate child states of the parent state
- are recorded. In this case a transition with the history state as its
- target will end up in the immediate child state that the parent was in the
- last time it was exited. This is the default.
-
- \value DeepHistory Nested states are recorded. In this case a transition
- with the history state as its target will end up in the most deeply nested
- descendant state the parent was in the last time it was exited.
-*/
-
-namespace {
-class DefaultStateTransition: public QAbstractTransition
-{
- Q_OBJECT
-
-public:
- DefaultStateTransition(QHistoryState *source, QAbstractState *target);
-
-protected:
- // It doesn't matter whether this transition matches any event or not. It is always associated
- // with a QHistoryState, and as soon as the state-machine detects that it enters a history
- // state, it will handle this transition as a special case. The history state itself is never
- // entered either: either the stored configuration will be used, or the target(s) of this
- // transition are used.
- bool eventTest(QEvent *event) override { Q_UNUSED(event); return false; }
- void onTransition(QEvent *event) override { Q_UNUSED(event); }
-};
-}
-
-QHistoryStatePrivate::QHistoryStatePrivate()
- : QAbstractStatePrivate(HistoryState)
- , defaultTransition(nullptr)
- , historyType(QHistoryState::ShallowHistory)
-{
-}
-
-DefaultStateTransition::DefaultStateTransition(QHistoryState *source, QAbstractState *target)
- : QAbstractTransition()
-{
- setParent(source);
- setTargetState(target);
-}
-
-/*!
- Constructs a new shallow history state with the given \a parent state.
-*/
-QHistoryState::QHistoryState(QState *parent)
- : QAbstractState(*new QHistoryStatePrivate, parent)
-{
-}
-/*!
- Constructs a new history state of the given \a type, with the given \a
- parent state.
-*/
-QHistoryState::QHistoryState(HistoryType type, QState *parent)
- : QAbstractState(*new QHistoryStatePrivate, parent)
-{
- Q_D(QHistoryState);
- d->historyType = type;
-}
-
-/*!
- Destroys this history state.
-*/
-QHistoryState::~QHistoryState()
-{
-}
-
-/*!
- Returns this history state's default transition. The default transition is
- taken when the history state has never been entered before. The target states
- of the default transition therefore make up the default state.
-
- \since 5.6
-*/
-QAbstractTransition *QHistoryState::defaultTransition() const
-{
- Q_D(const QHistoryState);
- return d->defaultTransition;
-}
-
-/*!
- Sets this history state's default transition to be the given \a transition.
- This will set the source state of the \a transition to the history state.
-
- Note that the eventTest method of the \a transition will never be called.
-
- \since 5.6
-*/
-void QHistoryState::setDefaultTransition(QAbstractTransition *transition)
-{
- Q_D(QHistoryState);
- if (d->defaultTransition != transition) {
- d->defaultTransition = transition;
- transition->setParent(this);
- emit defaultTransitionChanged(QHistoryState::QPrivateSignal());
- }
-}
-
-/*!
- Returns this history state's default state. The default state indicates the
- state to transition to if the parent state has never been entered before.
-*/
-QAbstractState *QHistoryState::defaultState() const
-{
- Q_D(const QHistoryState);
- return d->defaultTransition ? d->defaultTransition->targetState() : nullptr;
-}
-
-static inline bool isSoleEntry(const QList<QAbstractState*> &states, const QAbstractState * state)
-{
- return states.size() == 1 && states.first() == state;
-}
-
-/*!
- Sets this history state's default state to be the given \a state.
- \a state must be a sibling of this history state.
-
- Note that this function does not set \a state as the initial state
- of its parent.
-*/
-void QHistoryState::setDefaultState(QAbstractState *state)
-{
- Q_D(QHistoryState);
- if (state && state->parentState() != parentState()) {
- qWarning("QHistoryState::setDefaultState: state %p does not belong "
- "to this history state's group (%p)", state, parentState());
- return;
- }
- if (!d->defaultTransition || !isSoleEntry(d->defaultTransition->targetStates(), state)) {
- if (!d->defaultTransition || !qobject_cast<DefaultStateTransition*>(d->defaultTransition)) {
- d->defaultTransition = new DefaultStateTransition(this, state);
- emit defaultTransitionChanged(QHistoryState::QPrivateSignal());
- } else {
- d->defaultTransition->setTargetState(state);
- }
- emit defaultStateChanged(QHistoryState::QPrivateSignal());
- }
-}
-
-/*!
- Returns the type of history that this history state records.
-*/
-QHistoryState::HistoryType QHistoryState::historyType() const
-{
- Q_D(const QHistoryState);
- return d->historyType;
-}
-
-/*!
- Sets the \a type of history that this history state records.
-*/
-void QHistoryState::setHistoryType(HistoryType type)
-{
- Q_D(QHistoryState);
- if (d->historyType != type) {
- d->historyType = type;
- emit historyTypeChanged(QHistoryState::QPrivateSignal());
- }
-}
-
-/*!
- \reimp
-*/
-void QHistoryState::onEntry(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-void QHistoryState::onExit(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-bool QHistoryState::event(QEvent *e)
-{
- return QAbstractState::event(e);
-}
-
-/*!
- \fn QHistoryState::defaultStateChanged()
- \since 5.4
-
- This signal is emitted when the defaultState property is changed.
-
- \sa QHistoryState::defaultState
-*/
-
-/*!
- \fn QHistoryState::historyTypeChanged()
- \since 5.4
-
- This signal is emitted when the historyType property is changed.
-
- \sa QHistoryState::historyType
-*/
-
-/*!
- \fn QHistoryState::defaultTransitionChanged()
- \since 5.6
-
- This signal is emitted when the defaultTransition property is changed.
-
- \sa QHistoryState::defaultTransition
-*/
-
-QT_END_NAMESPACE
-
-#include "moc_qhistorystate.cpp"
-#include "qhistorystate.moc"
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
deleted file mode 100644
index 44f4c5d6d4..0000000000
--- a/src/corelib/statemachine/qhistorystate.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QHISTORYSTATE_H
-#define QHISTORYSTATE_H
-
-#include <QtCore/qabstractstate.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QAbstractTransition;
-class QHistoryStatePrivate;
-class Q_CORE_EXPORT QHistoryState : public QAbstractState
-{
- Q_OBJECT
- Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged)
- Q_PROPERTY(QAbstractTransition* defaultTransition READ defaultTransition WRITE setDefaultTransition NOTIFY defaultTransitionChanged)
- Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType NOTIFY historyTypeChanged)
-public:
- enum HistoryType {
- ShallowHistory,
- DeepHistory
- };
- Q_ENUM(HistoryType)
-
- QHistoryState(QState *parent = nullptr);
- QHistoryState(HistoryType type, QState *parent = nullptr);
- ~QHistoryState();
-
- QAbstractTransition *defaultTransition() const;
- void setDefaultTransition(QAbstractTransition *transition);
-
- QAbstractState *defaultState() const;
- void setDefaultState(QAbstractState *state);
-
- HistoryType historyType() const;
- void setHistoryType(HistoryType type);
-
-Q_SIGNALS:
- void defaultTransitionChanged(QPrivateSignal);
- void defaultStateChanged(QPrivateSignal);
- void historyTypeChanged(QPrivateSignal);
-
-protected:
- void onEntry(QEvent *event) override;
- void onExit(QEvent *event) override;
-
- bool event(QEvent *e) override;
-
-private:
- Q_DISABLE_COPY(QHistoryState)
- Q_DECLARE_PRIVATE(QHistoryState)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h
deleted file mode 100644
index 18d571feb7..0000000000
--- a/src/corelib/statemachine/qhistorystate_p.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QHISTORYSTATE_P_H
-#define QHISTORYSTATE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "private/qabstractstate_p.h"
-#include <QtCore/qabstracttransition.h>
-#include <QtCore/qhistorystate.h>
-#include <QtCore/qlist.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QHistoryStatePrivate : public QAbstractStatePrivate
-{
- Q_DECLARE_PUBLIC(QHistoryState)
-
-public:
- QHistoryStatePrivate();
-
- static QHistoryStatePrivate *get(QHistoryState *q)
- { return q->d_func(); }
-
- QAbstractTransition *defaultTransition;
- QHistoryState::HistoryType historyType;
- QList<QAbstractState*> configuration;
-};
-
-QT_END_NAMESPACE
-
-#endif // QHISTORYSTATE_P_H
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
deleted file mode 100644
index a9d5b96920..0000000000
--- a/src/corelib/statemachine/qsignaleventgenerator_p.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSIGNALEVENTGENERATOR_P_H
-#define QSIGNALEVENTGENERATOR_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-#include <QtCore/qobject.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QStateMachine;
-
-class QSignalEventGenerator : public QObject
-{
- Q_OBJECT
-public:
- QSignalEventGenerator(QStateMachine *parent);
-
-private Q_SLOTS:
- void execute(QMethodRawArguments a);
-
-private:
- Q_DISABLE_COPY_MOVE(QSignalEventGenerator)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
deleted file mode 100644
index 8e57695fd7..0000000000
--- a/src/corelib/statemachine/qsignaltransition.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsignaltransition.h"
-#include "qsignaltransition_p.h"
-#include "qstate.h"
-#include "qstate_p.h"
-#include "qstatemachine.h"
-#include "qstatemachine_p.h"
-#include <qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QSignalTransition
- \inmodule QtCore
-
- \brief The QSignalTransition class provides a transition based on a Qt signal.
-
- \since 4.6
- \ingroup statemachine
-
- Typically you would use the overload of QState::addTransition() that takes a
- sender and signal as arguments, rather than creating QSignalTransition
- objects directly. QSignalTransition is part of \l{The State Machine
- Framework}.
-
- You can subclass QSignalTransition and reimplement eventTest() to make a
- signal transition conditional; the event object passed to eventTest() will
- be a QStateMachine::SignalEvent object. Example:
-
- \code
- class CheckedTransition : public QSignalTransition
- {
- public:
- CheckedTransition(QCheckBox *check)
- : QSignalTransition(check, SIGNAL(stateChanged(int))) {}
- protected:
- bool eventTest(QEvent *e) {
- if (!QSignalTransition::eventTest(e))
- return false;
- QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
- return (se->arguments().at(0).toInt() == Qt::Checked);
- }
- };
-
- ...
-
- QCheckBox *check = new QCheckBox();
- check->setTristate(true);
-
- QState *s1 = new QState();
- QState *s2 = new QState();
- CheckedTransition *t1 = new CheckedTransition(check);
- t1->setTargetState(s2);
- s1->addTransition(t1);
- \endcode
-*/
-
-/*!
- \property QSignalTransition::senderObject
-
- \brief the sender object that this signal transition is associated with
-*/
-
-/*!
- \property QSignalTransition::signal
-
- \brief the signal that this signal transition is associated with
-*/
-
-QSignalTransitionPrivate::QSignalTransitionPrivate()
-{
- sender = nullptr;
- signalIndex = -1;
-}
-
-void QSignalTransitionPrivate::unregister()
-{
- Q_Q(QSignalTransition);
- if ((signalIndex == -1) || !machine())
- return;
- QStateMachinePrivate::get(machine())->unregisterSignalTransition(q);
-}
-
-void QSignalTransitionPrivate::maybeRegister()
-{
- Q_Q(QSignalTransition);
- if (QStateMachine *mach = machine())
- QStateMachinePrivate::get(mach)->maybeRegisterSignalTransition(q);
-}
-
-/*!
- Constructs a new signal transition with the given \a sourceState.
-*/
-QSignalTransition::QSignalTransition(QState *sourceState)
- : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
-{
-}
-
-/*!
- Constructs a new signal transition associated with the given \a signal of
- the given \a sender, and with the given \a sourceState.
-*/
-QSignalTransition::QSignalTransition(const QObject *sender, const char *signal,
- QState *sourceState)
- : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
-{
- Q_D(QSignalTransition);
- d->sender = sender;
- d->signal = signal;
- d->maybeRegister();
-}
-
-/*!
- \fn template <typename PointerToMemberFunction> QSignalTransition::QSignalTransition(const QObject *sender, PointerToMemberFunction signal, QState *sourceState)
- \since 5.7
- \overload
-
- Constructs a new signal transition associated with the given \a signal of
- the given \a sender object and with the given \a sourceState.
- This constructor is enabled if the compiler supports delegating constructors,
- as indicated by the presence of the macro Q_COMPILER_DELEGATING_CONSTRUCTORS.
-*/
-
-/*!
- Destroys this signal transition.
-*/
-QSignalTransition::~QSignalTransition()
-{
-}
-
-/*!
- Returns the sender object associated with this signal transition.
-*/
-QObject *QSignalTransition::senderObject() const
-{
- Q_D(const QSignalTransition);
- return const_cast<QObject *>(d->sender);
-}
-
-/*!
- Sets the \a sender object associated with this signal transition.
-*/
-void QSignalTransition::setSenderObject(const QObject *sender)
-{
- Q_D(QSignalTransition);
- if (sender == d->sender)
- return;
- d->unregister();
- d->sender = sender;
- d->maybeRegister();
- emit senderObjectChanged(QPrivateSignal());
-}
-
-/*!
- Returns the signal associated with this signal transition.
-*/
-QByteArray QSignalTransition::signal() const
-{
- Q_D(const QSignalTransition);
- return d->signal;
-}
-
-/*!
- Sets the \a signal associated with this signal transition.
-*/
-void QSignalTransition::setSignal(const QByteArray &signal)
-{
- Q_D(QSignalTransition);
- if (signal == d->signal)
- return;
- d->unregister();
- d->signal = signal;
- d->maybeRegister();
- emit signalChanged(QPrivateSignal());
-}
-
-/*!
- \reimp
-
- The default implementation returns \c true if the \a event is a
- QStateMachine::SignalEvent object and the event's sender and signal index
- match this transition, and returns \c false otherwise.
-*/
-bool QSignalTransition::eventTest(QEvent *event)
-{
- Q_D(const QSignalTransition);
- if (event->type() == QEvent::StateMachineSignal) {
- if (d->signalIndex == -1)
- return false;
- QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event);
- return (se->sender() == d->sender)
- && (se->signalIndex() == d->signalIndex);
- }
- return false;
-}
-
-/*!
- \reimp
-*/
-void QSignalTransition::onTransition(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-bool QSignalTransition::event(QEvent *e)
-{
- return QAbstractTransition::event(e);
-}
-
-/*!
- \fn QSignalTransition::senderObjectChanged()
- \since 5.4
-
- This signal is emitted when the senderObject property is changed.
-
- \sa QSignalTransition::senderObject
-*/
-
-/*!
- \fn QSignalTransition::signalChanged()
- \since 5.4
-
- This signal is emitted when the signal property is changed.
-
- \sa QSignalTransition::signal
-*/
-
-void QSignalTransitionPrivate::callOnTransition(QEvent *e)
-{
- Q_Q(QSignalTransition);
-
- if (e->type() == QEvent::StateMachineSignal) {
- QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent *>(e);
- int savedSignalIndex = se->m_signalIndex;
- se->m_signalIndex = originalSignalIndex;
- q->onTransition(e);
- se->m_signalIndex = savedSignalIndex;
- } else {
- q->onTransition(e);
- }
-}
-
-
-QT_END_NAMESPACE
-
-#include "moc_qsignaltransition.cpp"
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
deleted file mode 100644
index e785a18c73..0000000000
--- a/src/corelib/statemachine/qsignaltransition.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSIGNALTRANSITION_H
-#define QSIGNALTRANSITION_H
-
-#include <QtCore/qabstracttransition.h>
-#include <QtCore/qmetaobject.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QSignalTransitionPrivate;
-class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition
-{
- Q_OBJECT
- Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject NOTIFY senderObjectChanged)
- Q_PROPERTY(QByteArray signal READ signal WRITE setSignal NOTIFY signalChanged)
-
-public:
- QSignalTransition(QState *sourceState = nullptr);
- QSignalTransition(const QObject *sender, const char *signal,
- QState *sourceState = nullptr);
-#ifdef Q_QDOC
- template<typename PointerToMemberFunction>
- QSignalTransition(const QObject *object, PointerToMemberFunction signal,
- QState *sourceState = nullptr);
-#elif defined(Q_COMPILER_DELEGATING_CONSTRUCTORS)
- template <typename Func>
- QSignalTransition(const typename QtPrivate::FunctionPointer<Func>::Object *obj,
- Func sig, QState *srcState = nullptr)
- : QSignalTransition(obj, QMetaMethod::fromSignal(sig).methodSignature().constData(), srcState)
- {
- }
-#endif
-
- ~QSignalTransition();
-
- QObject *senderObject() const;
- void setSenderObject(const QObject *sender);
-
- QByteArray signal() const;
- void setSignal(const QByteArray &signal);
-
-protected:
- bool eventTest(QEvent *event) override;
- void onTransition(QEvent *event) override;
-
- bool event(QEvent *e) override;
-
-Q_SIGNALS:
- void senderObjectChanged(QPrivateSignal);
- void signalChanged(QPrivateSignal);
-
-private:
- Q_DISABLE_COPY(QSignalTransition)
- Q_DECLARE_PRIVATE(QSignalTransition)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h
deleted file mode 100644
index b3de334677..0000000000
--- a/src/corelib/statemachine/qsignaltransition_p.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSIGNALTRANSITION_P_H
-#define QSIGNALTRANSITION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "private/qabstracttransition_p.h"
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QSignalTransition;
-class QSignalTransitionPrivate : public QAbstractTransitionPrivate
-{
- Q_DECLARE_PUBLIC(QSignalTransition)
-public:
- QSignalTransitionPrivate();
-
- static QSignalTransitionPrivate *get(QSignalTransition *q)
- { return q->d_func(); }
-
- void unregister();
- void maybeRegister();
-
- void callOnTransition(QEvent *e) override;
-
- const QObject *sender;
- QByteArray signal;
- int signalIndex;
- int originalSignalIndex;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
deleted file mode 100644
index f641d25a96..0000000000
--- a/src/corelib/statemachine/qstate.cpp
+++ /dev/null
@@ -1,603 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qstate_p.h"
-#include "qhistorystate.h"
-#include "qhistorystate_p.h"
-#include "qabstracttransition.h"
-#include "qabstracttransition_p.h"
-#include "qsignaltransition.h"
-#include "qstatemachine.h"
-#include "qstatemachine_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QState
- \inmodule QtCore
-
- \brief The QState class provides a general-purpose state for QStateMachine.
-
- \since 4.6
- \ingroup statemachine
-
- QState objects can have child states, and can have transitions to other
- states. QState is part of \l{The State Machine Framework}.
-
- The addTransition() function adds a transition. The removeTransition()
- function removes a transition. The transitions() function returns the
- state's outgoing transitions.
-
- The assignProperty() function is used for defining property assignments that
- should be performed when a state is entered.
-
- Top-level states must be passed a QStateMachine object as their parent
- state, or added to a state machine using QStateMachine::addState().
-
- \section1 States with Child States
-
- The childMode property determines how child states are treated. For
- non-parallel state groups, the setInitialState() function must be called to
- set the initial state. The child states are mutually exclusive states, and
- the state machine needs to know which child state to enter when the parent
- state is the target of a transition.
-
- The state emits the QState::finished() signal when a final child state
- (QFinalState) is entered.
-
- The setErrorState() sets the state's error state. The error state is the
- state that the state machine will transition to if an error is detected when
- attempting to enter the state (e.g. because no initial state has been set).
-
-*/
-
-/*!
- \property QState::initialState
-
- \brief the initial state of this state (one of its child states)
-*/
-
-/*!
- \property QState::errorState
-
- \brief the error state of this state
-*/
-
-/*!
- \property QState::childMode
-
- \brief the child mode of this state
-
- The default value of this property is QState::ExclusiveStates.
-*/
-
-/*!
- \enum QState::ChildMode
-
- This enum specifies how a state's child states are treated.
-
- \value ExclusiveStates The child states are mutually exclusive and an
- initial state must be set by calling QState::setInitialState().
-
- \value ParallelStates The child states are parallel. When the parent state
- is entered, all its child states are entered in parallel.
-*/
-
-/*!
- \enum QState::RestorePolicy
-
- This enum specifies the restore policy type. The restore policy
- takes effect when the machine enters a state which sets one or more
- properties. If the restore policy is set to RestoreProperties,
- the state machine will save the original value of the property before the
- new value is set.
-
- Later, when the machine either enters a state which does not set
- a value for the given property, the property will automatically be restored
- to its initial value.
-
- Only one initial value will be saved for any given property. If a value for a property has
- already been saved by the state machine, it will not be overwritten until the property has been
- successfully restored.
-
- \value DontRestoreProperties The state machine should not save the initial values of properties
- and restore them later.
- \value RestoreProperties The state machine should save the initial values of properties
- and restore them later.
-
- \sa QStateMachine::globalRestorePolicy, QState::assignProperty()
-*/
-
-QStatePrivate::QStatePrivate()
- : QAbstractStatePrivate(StandardState),
- errorState(nullptr), initialState(nullptr), childMode(QState::ExclusiveStates),
- childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true)
-{
-}
-
-QStatePrivate::~QStatePrivate()
-{
-}
-
-void QStatePrivate::emitFinished()
-{
- Q_Q(QState);
- emit q->finished(QState::QPrivateSignal());
-}
-
-void QStatePrivate::emitPropertiesAssigned()
-{
- Q_Q(QState);
- emit q->propertiesAssigned(QState::QPrivateSignal());
-}
-
-/*!
- Constructs a new state with the given \a parent state.
-*/
-QState::QState(QState *parent)
- : QAbstractState(*new QStatePrivate, parent)
-{
-}
-
-/*!
- Constructs a new state with the given \a childMode and the given \a parent
- state.
-*/
-QState::QState(ChildMode childMode, QState *parent)
- : QAbstractState(*new QStatePrivate, parent)
-{
- Q_D(QState);
- d->childMode = childMode;
-}
-
-/*!
- \internal
-*/
-QState::QState(QStatePrivate &dd, QState *parent)
- : QAbstractState(dd, parent)
-{
-}
-
-/*!
- Destroys this state.
-*/
-QState::~QState()
-{
-}
-
-QList<QAbstractState*> QStatePrivate::childStates() const
-{
- if (childStatesListNeedsRefresh) {
- childStatesList.clear();
- QList<QObject*>::const_iterator it;
- for (it = children.constBegin(); it != children.constEnd(); ++it) {
- QAbstractState *s = qobject_cast<QAbstractState*>(*it);
- if (!s || qobject_cast<QHistoryState*>(s))
- continue;
- childStatesList.append(s);
- }
- childStatesListNeedsRefresh = false;
- }
- return childStatesList;
-}
-
-QList<QHistoryState*> QStatePrivate::historyStates() const
-{
- QList<QHistoryState*> result;
- QList<QObject*>::const_iterator it;
- for (it = children.constBegin(); it != children.constEnd(); ++it) {
- QHistoryState *h = qobject_cast<QHistoryState*>(*it);
- if (h)
- result.append(h);
- }
- return result;
-}
-
-QList<QAbstractTransition*> QStatePrivate::transitions() const
-{
- if (transitionsListNeedsRefresh) {
- transitionsList.clear();
- QList<QObject*>::const_iterator it;
- for (it = children.constBegin(); it != children.constEnd(); ++it) {
- QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it);
- if (t)
- transitionsList.append(t);
- }
- transitionsListNeedsRefresh = false;
- }
- return transitionsList;
-}
-
-#ifndef QT_NO_PROPERTIES
-
-/*!
- Instructs this state to set the property with the given \a name of the given
- \a object to the given \a value when the state is entered.
-
- \sa propertiesAssigned()
-*/
-void QState::assignProperty(QObject *object, const char *name,
- const QVariant &value)
-{
- Q_D(QState);
- if (!object) {
- qWarning("QState::assignProperty: cannot assign property '%s' of null object", name);
- return;
- }
- for (int i = 0; i < d->propertyAssignments.size(); ++i) {
- QPropertyAssignment &assn = d->propertyAssignments[i];
- if (assn.hasTarget(object, name)) {
- assn.value = value;
- return;
- }
- }
- d->propertyAssignments.append(QPropertyAssignment(object, name, value));
-}
-
-#endif // QT_NO_PROPERTIES
-
-/*!
- Returns this state's error state.
-
- \sa QStateMachine::error()
-*/
-QAbstractState *QState::errorState() const
-{
- Q_D(const QState);
- return d->errorState;
-}
-
-/*!
- Sets this state's error state to be the given \a state. If the error state
- is not set, or if it is set to \nullptr, the state will inherit its parent's error
- state recursively. If no error state is set for the state itself or any of
- its ancestors, an error will cause the machine to stop executing and an error
- will be printed to the console.
-*/
-void QState::setErrorState(QAbstractState *state)
-{
- Q_D(QState);
- if (state != nullptr && qobject_cast<QStateMachine*>(state)) {
- qWarning("QStateMachine::setErrorState: root state cannot be error state");
- return;
- }
- if (state != nullptr && (!state->machine() || ((state->machine() != machine()) && !qobject_cast<QStateMachine*>(this)))) {
- qWarning("QState::setErrorState: error state cannot belong "
- "to a different state machine");
- return;
- }
-
- if (d->errorState != state) {
- d->errorState = state;
- emit errorStateChanged(QState::QPrivateSignal());
- }
-}
-
-/*!
- Adds the given \a transition. The transition has this state as the source.
- This state takes ownership of the transition.
-*/
-void QState::addTransition(QAbstractTransition *transition)
-{
- Q_D(QState);
- if (!transition) {
- qWarning("QState::addTransition: cannot add null transition");
- return ;
- }
-
- transition->setParent(this);
- const QVector<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
- for (int i = 0; i < targets.size(); ++i) {
- QAbstractState *t = targets.at(i).data();
- if (!t) {
- qWarning("QState::addTransition: cannot add transition to null state");
- return ;
- }
- if ((QAbstractStatePrivate::get(t)->machine() != d->machine())
- && QAbstractStatePrivate::get(t)->machine() && d->machine()) {
- qWarning("QState::addTransition: cannot add transition "
- "to a state in a different state machine");
- return ;
- }
- }
- if (QStateMachine *mach = machine())
- QStateMachinePrivate::get(mach)->maybeRegisterTransition(transition);
-}
-
-/*!
- \fn template <typename PointerToMemberFunction> QState::addTransition(const QObject *sender, PointerToMemberFunction signal, QAbstractState *target);
- \since 5.5
- \overload
-
- Adds a transition associated with the given \a signal of the given \a sender
- object, and returns the new QSignalTransition object. The transition has
- this state as the source, and the given \a target as the target state.
-*/
-
-/*!
- Adds a transition associated with the given \a signal of the given \a sender
- object, and returns the new QSignalTransition object. The transition has
- this state as the source, and the given \a target as the target state.
-*/
-QSignalTransition *QState::addTransition(const QObject *sender, const char *signal,
- QAbstractState *target)
-{
- if (!sender) {
- qWarning("QState::addTransition: sender cannot be null");
- return nullptr;
- }
- if (!signal) {
- qWarning("QState::addTransition: signal cannot be null");
- return nullptr;
- }
- if (!target) {
- qWarning("QState::addTransition: cannot add transition to null state");
- return nullptr;
- }
- int offset = (*signal == '0'+QSIGNAL_CODE) ? 1 : 0;
- const QMetaObject *meta = sender->metaObject();
- if (meta->indexOfSignal(signal+offset) == -1) {
- if (meta->indexOfSignal(QMetaObject::normalizedSignature(signal+offset)) == -1) {
- qWarning("QState::addTransition: no such signal %s::%s",
- meta->className(), signal+offset);
- return nullptr;
- }
- }
- QSignalTransition *trans = new QSignalTransition(sender, signal);
- trans->setTargetState(target);
- addTransition(trans);
- return trans;
-}
-
-namespace {
-
-// ### Make public?
-class UnconditionalTransition : public QAbstractTransition
-{
-public:
- UnconditionalTransition(QAbstractState *target)
- : QAbstractTransition()
- { setTargetState(target); }
-protected:
- void onTransition(QEvent *) override {}
- bool eventTest(QEvent *) override { return true; }
-};
-
-} // namespace
-
-/*!
- Adds an unconditional transition from this state to the given \a target
- state, and returns then new transition object.
-*/
-QAbstractTransition *QState::addTransition(QAbstractState *target)
-{
- if (!target) {
- qWarning("QState::addTransition: cannot add transition to null state");
- return nullptr;
- }
- UnconditionalTransition *trans = new UnconditionalTransition(target);
- addTransition(trans);
- return trans;
-}
-
-/*!
- Removes the given \a transition from this state. The state releases
- ownership of the transition.
-
- \sa addTransition()
-*/
-void QState::removeTransition(QAbstractTransition *transition)
-{
- Q_D(QState);
- if (!transition) {
- qWarning("QState::removeTransition: cannot remove null transition");
- return;
- }
- if (transition->sourceState() != this) {
- qWarning("QState::removeTransition: transition %p's source state (%p)"
- " is different from this state (%p)",
- transition, transition->sourceState(), this);
- return;
- }
- QStateMachinePrivate *mach = QStateMachinePrivate::get(d->machine());
- if (mach)
- mach->unregisterTransition(transition);
- transition->setParent(nullptr);
-}
-
-/*!
- \since 4.7
-
- Returns this state's outgoing transitions (i.e. transitions where
- this state is the \l{QAbstractTransition::sourceState()}{source
- state}), or an empty list if this state has no outgoing transitions.
-
- \sa addTransition()
-*/
-QList<QAbstractTransition*> QState::transitions() const
-{
- Q_D(const QState);
- return d->transitions();
-}
-
-/*!
- \reimp
-*/
-void QState::onEntry(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
-*/
-void QState::onExit(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- Returns this state's initial state, or \nullptr if the state has no
- initial state.
-*/
-QAbstractState *QState::initialState() const
-{
- Q_D(const QState);
- return d->initialState;
-}
-
-/*!
- Sets this state's initial state to be the given \a state.
- \a state has to be a child of this state.
-*/
-void QState::setInitialState(QAbstractState *state)
-{
- Q_D(QState);
- if (d->childMode == QState::ParallelStates) {
- qWarning("QState::setInitialState: ignoring attempt to set initial state "
- "of parallel state group %p", this);
- return;
- }
- if (state && (state->parentState() != this)) {
- qWarning("QState::setInitialState: state %p is not a child of this state (%p)",
- state, this);
- return;
- }
- if (d->initialState != state) {
- d->initialState = state;
- emit initialStateChanged(QState::QPrivateSignal());
- }
-}
-
-/*!
- Returns the child mode of this state.
-*/
-QState::ChildMode QState::childMode() const
-{
- Q_D(const QState);
- return d->childMode;
-}
-
-/*!
- Sets the child \a mode of this state.
-*/
-void QState::setChildMode(ChildMode mode)
-{
- Q_D(QState);
-
- if (mode == QState::ParallelStates && d->initialState) {
- qWarning("QState::setChildMode: setting the child-mode of state %p to "
- "parallel removes the initial state", this);
- d->initialState = nullptr;
- emit initialStateChanged(QState::QPrivateSignal());
- }
-
- if (d->childMode != mode) {
- d->childMode = mode;
- emit childModeChanged(QState::QPrivateSignal());
- }
-}
-
-/*!
- \reimp
-*/
-bool QState::event(QEvent *e)
-{
- Q_D(QState);
- if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved)) {
- d->childStatesListNeedsRefresh = true;
- d->transitionsListNeedsRefresh = true;
- if ((e->type() == QEvent::ChildRemoved) && (static_cast<QChildEvent *>(e)->child() == d->initialState))
- d->initialState = nullptr;
- }
- return QAbstractState::event(e);
-}
-
-/*!
- \fn QState::finished()
-
- This signal is emitted when a final child state of this state is entered.
-
- \sa QFinalState
-*/
-
-/*!
- \fn QState::propertiesAssigned()
-
- This signal is emitted when all properties have been assigned their final value. If the state
- assigns a value to one or more properties for which an animation exists (either set on the
- transition or as a default animation on the state machine), then the signal will not be emitted
- until all such animations have finished playing.
-
- If there are no relevant animations, or no property assignments defined for the state, then
- the signal will be emitted immediately before the state is entered.
-
- \sa QState::assignProperty(), QAbstractTransition::addAnimation()
-*/
-
-/*!
- \fn QState::childModeChanged()
- \since 5.4
-
- This signal is emitted when the childMode property is changed.
-
- \sa QState::childMode
-*/
-
-/*!
- \fn QState::initialStateChanged()
- \since 5.4
-
- This signal is emitted when the initialState property is changed.
-
- \sa QState::initialState
-*/
-
-/*!
- \fn QState::errorStateChanged()
- \since 5.4
-
- This signal is emitted when the errorState property is changed.
-
- \sa QState::errorState
-*/
-
-QT_END_NAMESPACE
-
-#include "moc_qstate.cpp"
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
deleted file mode 100644
index 9f1f07dfcc..0000000000
--- a/src/corelib/statemachine/qstate.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSTATE_H
-#define QSTATE_H
-
-#include <QtCore/qabstractstate.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qmetaobject.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QAbstractTransition;
-class QSignalTransition;
-
-class QStatePrivate;
-class Q_CORE_EXPORT QState : public QAbstractState
-{
- Q_OBJECT
- Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState NOTIFY initialStateChanged)
- Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState NOTIFY errorStateChanged)
- Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode NOTIFY childModeChanged)
-public:
- enum ChildMode {
- ExclusiveStates,
- ParallelStates
- };
- Q_ENUM(ChildMode)
-
- enum RestorePolicy {
- DontRestoreProperties,
- RestoreProperties
- };
- Q_ENUM(RestorePolicy)
-
- QState(QState *parent = nullptr);
- QState(ChildMode childMode, QState *parent = nullptr);
- ~QState();
-
- QAbstractState *errorState() const;
- void setErrorState(QAbstractState *state);
-
- void addTransition(QAbstractTransition *transition);
- QSignalTransition *addTransition(const QObject *sender, const char *signal, QAbstractState *target);
-#ifdef Q_QDOC
- template<typename PointerToMemberFunction>
- QSignalTransition *addTransition(const QObject *sender, PointerToMemberFunction signal,
- QAbstractState *target);
-#else
- template <typename Func>
- QSignalTransition *addTransition(const typename QtPrivate::FunctionPointer<Func>::Object *obj,
- Func signal, QAbstractState *target)
- {
- const QMetaMethod signalMetaMethod = QMetaMethod::fromSignal(signal);
- return addTransition(obj, signalMetaMethod.methodSignature().constData(), target);
- }
-#endif // Q_QDOC
- QAbstractTransition *addTransition(QAbstractState *target);
- void removeTransition(QAbstractTransition *transition);
- QList<QAbstractTransition*> transitions() const;
-
- QAbstractState *initialState() const;
- void setInitialState(QAbstractState *state);
-
- ChildMode childMode() const;
- void setChildMode(ChildMode mode);
-
-#ifndef QT_NO_PROPERTIES
- void assignProperty(QObject *object, const char *name,
- const QVariant &value);
-#endif
-
-Q_SIGNALS:
- void finished(QPrivateSignal);
- void propertiesAssigned(QPrivateSignal);
- void childModeChanged(QPrivateSignal);
- void initialStateChanged(QPrivateSignal);
- void errorStateChanged(QPrivateSignal);
-
-protected:
- void onEntry(QEvent *event) override;
- void onExit(QEvent *event) override;
-
- bool event(QEvent *e) override;
-
-protected:
- QState(QStatePrivate &dd, QState *parent);
-
-private:
- Q_DISABLE_COPY(QState)
- Q_DECLARE_PRIVATE(QState)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h
deleted file mode 100644
index ec746caae1..0000000000
--- a/src/corelib/statemachine/qstate_p.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSTATE_P_H
-#define QSTATE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qstate.h"
-#include "private/qabstractstate_p.h"
-
-#include <QtCore/qlist.h>
-#include <QtCore/qbytearray.h>
-#include <QtCore/qpointer.h>
-#include <QtCore/qvariant.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_PROPERTIES
-
-struct QPropertyAssignment
-{
- QPropertyAssignment()
- : object(nullptr), explicitlySet(true) {}
- QPropertyAssignment(QObject *o, const QByteArray &n,
- const QVariant &v, bool es = true)
- : object(o), propertyName(n), value(v), explicitlySet(es)
- {}
-
- bool objectDeleted() const { return !object; }
- void write() const { Q_ASSERT(object != nullptr); object->setProperty(propertyName, value); }
- bool hasTarget(QObject *o, const QByteArray &pn) const
- { return object == o && propertyName == pn; }
-
- QPointer<QObject> object;
- QByteArray propertyName;
- QVariant value;
- bool explicitlySet; // false means the property is being restored to its old value
-};
-Q_DECLARE_TYPEINFO(QPropertyAssignment, Q_MOVABLE_TYPE);
-
-#endif // QT_NO_PROPERTIES
-
-class QAbstractTransition;
-class QHistoryState;
-
-class QState;
-class Q_CORE_EXPORT QStatePrivate : public QAbstractStatePrivate
-{
- Q_DECLARE_PUBLIC(QState)
-public:
- QStatePrivate();
- ~QStatePrivate();
-
- static QStatePrivate *get(QState *q) { return q ? q->d_func() : nullptr; }
- static const QStatePrivate *get(const QState *q) { return q? q->d_func() : nullptr; }
-
- QList<QAbstractState*> childStates() const;
- QList<QHistoryState*> historyStates() const;
- QList<QAbstractTransition*> transitions() const;
-
- void emitFinished();
- void emitPropertiesAssigned();
-
- QAbstractState *errorState;
- QAbstractState *initialState;
- QState::ChildMode childMode;
- mutable bool childStatesListNeedsRefresh;
- mutable bool transitionsListNeedsRefresh;
- mutable QList<QAbstractState*> childStatesList;
- mutable QList<QAbstractTransition*> transitionsList;
-
-#ifndef QT_NO_PROPERTIES
- QVector<QPropertyAssignment> propertyAssignments;
-#endif
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
deleted file mode 100644
index c1fa700959..0000000000
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ /dev/null
@@ -1,3211 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qstatemachine.h"
-#include "qstate.h"
-#include "qstate_p.h"
-#include "qstatemachine_p.h"
-#include "qabstracttransition.h"
-#include "qabstracttransition_p.h"
-#include "qsignaltransition.h"
-#include "qsignaltransition_p.h"
-#include "qsignaleventgenerator_p.h"
-#include "qabstractstate.h"
-#include "qabstractstate_p.h"
-#include "qfinalstate.h"
-#include "qhistorystate.h"
-#include "qhistorystate_p.h"
-#include "private/qobject_p.h"
-#include "private/qthread_p.h"
-
-#if QT_CONFIG(qeventtransition)
-#include "qeventtransition.h"
-#include "qeventtransition_p.h"
-#endif
-
-#if QT_CONFIG(animation)
-#include "qpropertyanimation.h"
-#include "qanimationgroup.h"
-#include <private/qvariantanimation_p.h>
-#endif
-
-#include <QtCore/qmetaobject.h>
-#include <qdebug.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QStateMachine
- \inmodule QtCore
- \reentrant
-
- \brief The QStateMachine class provides a hierarchical finite state machine.
-
- \since 4.6
- \ingroup statemachine
-
- QStateMachine is based on the concepts and notation of
- \l{http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf}{Statecharts}.
- QStateMachine is part of \l{The State Machine Framework}.
-
- A state machine manages a set of states (classes that inherit from
- QAbstractState) and transitions (descendants of
- QAbstractTransition) between those states; these states and
- transitions define a state graph. Once a state graph has been
- built, the state machine can execute it. QStateMachine's
- execution algorithm is based on the \l{http://www.w3.org/TR/scxml/}{State Chart XML (SCXML)}
- algorithm. The framework's \l{The State Machine
- Framework}{overview} gives several state graphs and the code to
- build them.
-
- Use the addState() function to add a top-level state to the state machine.
- States are removed with the removeState() function. Removing states while
- the machine is running is discouraged.
-
- Before the machine can be started, the \l{initialState}{initial
- state} must be set. The initial state is the state that the
- machine enters when started. You can then start() the state
- machine. The started() signal is emitted when the initial state is
- entered.
-
- The machine is event driven and keeps its own event loop. Events
- are posted to the machine through postEvent(). Note that this
- means that it executes asynchronously, and that it will not
- progress without a running event loop. You will normally not have
- to post events to the machine directly as Qt's transitions, e.g.,
- QEventTransition and its subclasses, handle this. But for custom
- transitions triggered by events, postEvent() is useful.
-
- The state machine processes events and takes transitions until a
- top-level final state is entered; the state machine then emits the
- finished() signal. You can also stop() the state machine
- explicitly. The stopped() signal is emitted in this case.
-
- The following snippet shows a state machine that will finish when a button
- is clicked:
-
- \snippet code/src_corelib_statemachine_qstatemachine.cpp simple state machine
-
- This code example uses QState, which inherits QAbstractState. The
- QState class provides a state that you can use to set properties
- and invoke methods on \l{QObject}s when the state is entered or
- exited. It also contains convenience functions for adding
- transitions, e.g., \l{QSignalTransition}s as in this example. See
- the QState class description for further details.
-
- If an error is encountered, the machine will look for an
- \l{errorState}{error state}, and if one is available, it will
- enter this state. The types of errors possible are described by the
- \l{QStateMachine::}{Error} enum. After the error state is entered,
- the type of the error can be retrieved with error(). The execution
- of the state graph will not stop when the error state is entered. If
- no error state applies to the erroneous state, the machine will stop
- executing and an error message will be printed to the console.
-
- \note Important: setting the \l{ChildMode} of a state machine to parallel (\l{ParallelStates})
- results in an invalid state machine. It can only be set to (or kept as)
- \l{ExclusiveStates}.
-
- \sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework}
-*/
-
-/*!
- \property QStateMachine::errorString
-
- \brief the error string of this state machine
-*/
-
-/*!
- \property QStateMachine::globalRestorePolicy
-
- \brief the restore policy for states of this state machine.
-
- The default value of this property is
- QState::DontRestoreProperties.
-*/
-
-/*!
- \property QStateMachine::running
- \since 5.4
-
- \brief the running state of this state machine
-
- \sa start(), stop(), started(), stopped(), runningChanged()
-*/
-
-#if QT_CONFIG(animation)
-/*!
- \property QStateMachine::animated
-
- \brief whether animations are enabled
-
- The default value of this property is \c true.
-
- \sa QAbstractTransition::addAnimation()
-*/
-#endif
-
-// #define QSTATEMACHINE_DEBUG
-// #define QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
-
-struct CalculationCache {
- struct TransitionInfo {
- QList<QAbstractState*> effectiveTargetStates;
- QSet<QAbstractState*> exitSet;
- QAbstractState *transitionDomain;
-
- bool effectiveTargetStatesIsKnown: 1;
- bool exitSetIsKnown : 1;
- bool transitionDomainIsKnown : 1;
-
- TransitionInfo()
- : transitionDomain(nullptr)
- , effectiveTargetStatesIsKnown(false)
- , exitSetIsKnown(false)
- , transitionDomainIsKnown(false)
- {}
- };
-
- typedef QHash<QAbstractTransition *, TransitionInfo> TransitionInfoCache;
- TransitionInfoCache cache;
-
- bool effectiveTargetStates(QAbstractTransition *t, QList<QAbstractState *> *targets) const
- {
- Q_ASSERT(targets);
-
- TransitionInfoCache::const_iterator cacheIt = cache.find(t);
- if (cacheIt == cache.end() || !cacheIt->effectiveTargetStatesIsKnown)
- return false;
-
- *targets = cacheIt->effectiveTargetStates;
- return true;
- }
-
- void insert(QAbstractTransition *t, const QList<QAbstractState *> &targets)
- {
- TransitionInfoCache::iterator cacheIt = cache.find(t);
- TransitionInfo &ti = cacheIt == cache.end()
- ? *cache.insert(t, TransitionInfo())
- : *cacheIt;
-
- Q_ASSERT(!ti.effectiveTargetStatesIsKnown);
- ti.effectiveTargetStates = targets;
- ti.effectiveTargetStatesIsKnown = true;
- }
-
- bool exitSet(QAbstractTransition *t, QSet<QAbstractState *> *exits) const
- {
- Q_ASSERT(exits);
-
- TransitionInfoCache::const_iterator cacheIt = cache.find(t);
- if (cacheIt == cache.end() || !cacheIt->exitSetIsKnown)
- return false;
-
- *exits = cacheIt->exitSet;
- return true;
- }
-
- void insert(QAbstractTransition *t, const QSet<QAbstractState *> &exits)
- {
- TransitionInfoCache::iterator cacheIt = cache.find(t);
- TransitionInfo &ti = cacheIt == cache.end()
- ? *cache.insert(t, TransitionInfo())
- : *cacheIt;
-
- Q_ASSERT(!ti.exitSetIsKnown);
- ti.exitSet = exits;
- ti.exitSetIsKnown = true;
- }
-
- bool transitionDomain(QAbstractTransition *t, QAbstractState **domain) const
- {
- Q_ASSERT(domain);
-
- TransitionInfoCache::const_iterator cacheIt = cache.find(t);
- if (cacheIt == cache.end() || !cacheIt->transitionDomainIsKnown)
- return false;
-
- *domain = cacheIt->transitionDomain;
- return true;
- }
-
- void insert(QAbstractTransition *t, QAbstractState *domain)
- {
- TransitionInfoCache::iterator cacheIt = cache.find(t);
- TransitionInfo &ti = cacheIt == cache.end()
- ? *cache.insert(t, TransitionInfo())
- : *cacheIt;
-
- Q_ASSERT(!ti.transitionDomainIsKnown);
- ti.transitionDomain = domain;
- ti.transitionDomainIsKnown = true;
- }
-};
-
-/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-function isDescendant(state1, state2)
-
-Returns 'true' if state1 is a descendant of state2 (a child, or a child of a child, or a child of a
-child of a child, etc.) Otherwise returns 'false'.
-*/
-static inline bool isDescendant(const QAbstractState *state1, const QAbstractState *state2)
-{
- Q_ASSERT(state1 != nullptr);
-
- for (QAbstractState *it = state1->parentState(); it != nullptr; it = it->parentState()) {
- if (it == state2)
- return true;
- }
-
- return false;
-}
-
-static bool containsDecendantOf(const QSet<QAbstractState *> &states, const QAbstractState *node)
-{
- for (QAbstractState *s : states)
- if (isDescendant(s, node))
- return true;
-
- return false;
-}
-
-static int descendantDepth(const QAbstractState *state, const QAbstractState *ancestor)
-{
- int depth = 0;
- for (const QAbstractState *it = state; it != nullptr; it = it->parentState()) {
- if (it == ancestor)
- break;
- ++depth;
- }
- return depth;
-}
-
-/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-function getProperAncestors(state1, state2)
-
-If state2 is null, returns the set of all ancestors of state1 in ancestry order (state1's parent
-followed by the parent's parent, etc. up to an including the <scxml> element). If state2 is
-non-null, returns in ancestry order the set of all ancestors of state1, up to but not including
-state2. (A "proper ancestor" of a state is its parent, or the parent's parent, or the parent's
-parent's parent, etc.))If state2 is state1's parent, or equal to state1, or a descendant of state1,
-this returns the empty set.
-*/
-static QVector<QState*> getProperAncestors(const QAbstractState *state, const QAbstractState *upperBound)
-{
- Q_ASSERT(state != nullptr);
- QVector<QState*> result;
- result.reserve(16);
- for (QState *it = state->parentState(); it && it != upperBound; it = it->parentState()) {
- result.append(it);
- }
- return result;
-}
-
-/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-function getEffectiveTargetStates(transition)
-
-Returns the states that will be the target when 'transition' is taken, dereferencing any history states.
-
-function getEffectiveTargetStates(transition)
- targets = new OrderedSet()
- for s in transition.target
- if isHistoryState(s):
- if historyValue[s.id]:
- targets.union(historyValue[s.id])
- else:
- targets.union(getEffectiveTargetStates(s.transition))
- else:
- targets.add(s)
- return targets
-*/
-static QList<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *transition, CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- QList<QAbstractState *> targetsList;
- if (cache->effectiveTargetStates(transition, &targetsList))
- return targetsList;
-
- QSet<QAbstractState *> targets;
- const auto targetStates = transition->targetStates();
- for (QAbstractState *s : targetStates) {
- if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) {
- QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration;
- if (!historyConfiguration.isEmpty()) {
- // There is a saved history, so apply that.
- targets.unite(QSet<QAbstractState *>(historyConfiguration.constBegin(), historyConfiguration.constEnd()));
- } else if (QAbstractTransition *defaultTransition = historyState->defaultTransition()) {
- // No saved history, take all default transition targets.
- const auto &targetStates = defaultTransition->targetStates();
- targets.unite(QSet<QAbstractState *>(targetStates.constBegin(), targetStates.constEnd()));
- } else {
- // Woops, we found a history state without a default state. That's not valid!
- QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine());
- m->setError(QStateMachine::NoDefaultStateInHistoryStateError, historyState);
- }
- } else {
- targets.insert(s);
- }
- }
-
- targetsList = targets.values();
- cache->insert(transition, targetsList);
- return targetsList;
-}
-
-QStateMachinePrivate::QStateMachinePrivate()
-{
- isMachine = true;
-
- state = NotRunning;
- processing = false;
- processingScheduled = false;
- stop = false;
- stopProcessingReason = EventQueueEmpty;
- error = QStateMachine::NoError;
- globalRestorePolicy = QState::DontRestoreProperties;
- signalEventGenerator = nullptr;
-#if QT_CONFIG(animation)
- animated = true;
-#endif
-}
-
-QStateMachinePrivate::~QStateMachinePrivate()
-{
- qDeleteAll(internalEventQueue);
- qDeleteAll(externalEventQueue);
-
- for (QHash<int, DelayedEvent>::const_iterator it = delayedEvents.cbegin(), eit = delayedEvents.cend(); it != eit; ++it) {
- delete it.value().event;
- }
-}
-
-QState *QStateMachinePrivate::rootState() const
-{
- return const_cast<QStateMachine*>(q_func());
-}
-
-static QEvent *cloneEvent(QEvent *e)
-{
- switch (e->type()) {
- case QEvent::None:
- return new QEvent(*e);
- case QEvent::Timer:
- return new QTimerEvent(*static_cast<QTimerEvent*>(e));
- default:
- Q_ASSERT_X(false, "cloneEvent()", "not implemented");
- break;
- }
- return nullptr;
-}
-
-const QStateMachinePrivate::Handler qt_kernel_statemachine_handler = {
- cloneEvent
-};
-
-const QStateMachinePrivate::Handler *QStateMachinePrivate::handler = &qt_kernel_statemachine_handler;
-
-Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler()
-{
- return &qt_kernel_statemachine_handler;
-}
-
-static int indexOfDescendant(QState *s, QAbstractState *desc)
-{
- QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates();
- for (int i = 0; i < childStates.size(); ++i) {
- QAbstractState *c = childStates.at(i);
- if ((c == desc) || isDescendant(desc, c)) {
- return i;
- }
- }
- return -1;
-}
-
-bool QStateMachinePrivate::transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2)
-{
- QState *s1 = t1->sourceState(), *s2 = t2->sourceState();
- if (s1 == s2) {
- QList<QAbstractTransition*> transitions = QStatePrivate::get(s1)->transitions();
- return transitions.indexOf(t1) < transitions.indexOf(t2);
- } else if (isDescendant(s1, s2)) {
- return true;
- } else if (isDescendant(s2, s1)) {
- return false;
- } else {
- Q_ASSERT(s1->machine() != nullptr);
- QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
- QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
- Q_ASSERT(lca != nullptr);
- int s1Depth = descendantDepth(s1, lca);
- int s2Depth = descendantDepth(s2, lca);
- if (s1Depth == s2Depth)
- return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
- else
- return s1Depth > s2Depth;
- }
-}
-
-bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
-{
- if (s1->parent() == s2->parent()) {
- return s1->parent()->children().indexOf(s1)
- < s2->parent()->children().indexOf(s2);
- } else if (isDescendant(s1, s2)) {
- return false;
- } else if (isDescendant(s2, s1)) {
- return true;
- } else {
- Q_ASSERT(s1->machine() != nullptr);
- QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
- QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
- Q_ASSERT(lca != nullptr);
- return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
- }
-}
-
-bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState *s2)
-{
- if (s1->parent() == s2->parent()) {
- return s2->parent()->children().indexOf(s2)
- < s1->parent()->children().indexOf(s1);
- } else if (isDescendant(s1, s2)) {
- return true;
- } else if (isDescendant(s2, s1)) {
- return false;
- } else {
- Q_ASSERT(s1->machine() != nullptr);
- QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
- QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
- Q_ASSERT(lca != nullptr);
- return (indexOfDescendant(lca, s2) < indexOfDescendant(lca, s1));
- }
-}
-
-QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states, bool onlyCompound)
-{
- if (states.isEmpty())
- return nullptr;
- QVector<QState*> ancestors = getProperAncestors(states.at(0), rootState()->parentState());
- for (int i = 0; i < ancestors.size(); ++i) {
- QState *anc = ancestors.at(i);
- if (onlyCompound && !isCompound(anc))
- continue;
-
- bool ok = true;
- for (int j = states.size() - 1; (j > 0) && ok; --j) {
- const QAbstractState *s = states.at(j);
- if (!isDescendant(s, anc))
- ok = false;
- }
- if (ok)
- return anc;
- }
-
- // Oops, this should never happen! The state machine itself is a common ancestor of all states,
- // no matter what. But, for the onlyCompound case: we probably have a state machine whose
- // childMode is set to parallel, which is illegal. However, we're stuck with it (and with
- // exposing this invalid/dangerous API to users), so recover in the least horrible way.
- setError(QStateMachine::StateMachineChildModeSetToParallelError, q_func());
- return q_func(); // make the statemachine the LCA/LCCA (which it should have been anyway)
-}
-
-QState *QStateMachinePrivate::findLCCA(const QList<QAbstractState*> &states)
-{
- return findLCA(states, true);
-}
-
-QList<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event, CalculationCache *cache)
-{
- Q_ASSERT(cache);
- Q_Q(const QStateMachine);
-
- QVarLengthArray<QAbstractState *> configuration_sorted;
- for (QAbstractState *s : qAsConst(configuration)) {
- if (isAtomic(s))
- configuration_sorted.append(s);
- }
- std::sort(configuration_sorted.begin(), configuration_sorted.end(), stateEntryLessThan);
-
- QList<QAbstractTransition*> enabledTransitions;
- const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
- for (QAbstractState *state : qAsConst(configuration_sorted)) {
- QVector<QState*> lst = getProperAncestors(state, nullptr);
- if (QState *grp = toStandardState(state))
- lst.prepend(grp);
- bool found = false;
- for (int j = 0; (j < lst.size()) && !found; ++j) {
- QState *s = lst.at(j);
- QList<QAbstractTransition*> transitions = QStatePrivate::get(s)->transitions();
- for (int k = 0; k < transitions.size(); ++k) {
- QAbstractTransition *t = transitions.at(k);
- if (QAbstractTransitionPrivate::get(t)->callEventTest(event)) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": selecting transition" << t;
-#endif
- enabledTransitions.append(t);
- found = true;
- break;
- }
- }
- }
- }
-
- if (!enabledTransitions.isEmpty()) {
- removeConflictingTransitions(enabledTransitions, cache);
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": enabled transitions after removing conflicts:" << enabledTransitions;
-#endif
- }
- const_cast<QStateMachine*>(q)->endSelectTransitions(event);
- return enabledTransitions;
-}
-
-/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-function removeConflictingTransitions(enabledTransitions):
- filteredTransitions = new OrderedSet()
- // toList sorts the transitions in the order of the states that selected them
- for t1 in enabledTransitions.toList():
- t1Preempted = false;
- transitionsToRemove = new OrderedSet()
- for t2 in filteredTransitions.toList():
- if computeExitSet([t1]).hasIntersection(computeExitSet([t2])):
- if isDescendant(t1.source, t2.source):
- transitionsToRemove.add(t2)
- else:
- t1Preempted = true
- break
- if not t1Preempted:
- for t3 in transitionsToRemove.toList():
- filteredTransitions.delete(t3)
- filteredTransitions.add(t1)
-
- return filteredTransitions
-
-Note: the implementation below does not build the transitionsToRemove, but removes them in-place.
-*/
-void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- if (enabledTransitions.size() < 2)
- return; // There is no transition to conflict with.
-
- QList<QAbstractTransition*> filteredTransitions;
- filteredTransitions.reserve(enabledTransitions.size());
- std::sort(enabledTransitions.begin(), enabledTransitions.end(), transitionStateEntryLessThan);
-
- for (QAbstractTransition *t1 : qAsConst(enabledTransitions)) {
- bool t1Preempted = false;
- const QSet<QAbstractState*> exitSetT1 = computeExitSet_Unordered(t1, cache);
- QList<QAbstractTransition*>::iterator t2It = filteredTransitions.begin();
- while (t2It != filteredTransitions.end()) {
- QAbstractTransition *t2 = *t2It;
- if (t1 == t2) {
- // Special case: someone added the same transition object to a state twice. In this
- // case, t2 (which is already in the list) "preempts" t1.
- t1Preempted = true;
- break;
- }
-
- QSet<QAbstractState*> exitSetT2 = computeExitSet_Unordered(t2, cache);
- if (!exitSetT1.intersects(exitSetT2)) {
- // No conflict, no cry. Next patient please.
- ++t2It;
- } else {
- // Houston, we have a conflict. Check which transition can be removed.
- if (isDescendant(t1->sourceState(), t2->sourceState())) {
- // t1 preempts t2, so we can remove t2
- t2It = filteredTransitions.erase(t2It);
- } else {
- // t2 preempts t1, so there's no use in looking further and we don't need to add
- // t1 to the list.
- t1Preempted = true;
- break;
- }
- }
- }
- if (!t1Preempted)
- filteredTransitions.append(t1);
- }
-
- enabledTransitions = filteredTransitions;
-}
-
-void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions,
- CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
- qDebug() << q_func() << ": configuration before exiting states:" << configuration;
-#endif
- QList<QAbstractState*> exitedStates = computeExitSet(enabledTransitions, cache);
- QHash<RestorableId, QVariant> pendingRestorables = computePendingRestorables(exitedStates);
-
- QSet<QAbstractState*> statesForDefaultEntry;
- QList<QAbstractState*> enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry, cache);
-
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": computed exit set:" << exitedStates;
- qDebug() << q_func() << ": computed entry set:" << enteredStates;
-#endif
-
- QHash<QAbstractState*, QVector<QPropertyAssignment> > assignmentsForEnteredStates =
- computePropertyAssignments(enteredStates, pendingRestorables);
- if (!pendingRestorables.isEmpty()) {
- // Add "implicit" assignments for restored properties to the first
- // (outermost) entered state
- Q_ASSERT(!enteredStates.isEmpty());
- QAbstractState *s = enteredStates.constFirst();
- assignmentsForEnteredStates[s] << restorablesToPropertyList(pendingRestorables);
- }
-
- exitStates(event, exitedStates, assignmentsForEnteredStates);
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": configuration after exiting states:" << configuration;
-#endif
-
- executeTransitionContent(event, enabledTransitions);
-
-#if QT_CONFIG(animation)
- QList<QAbstractAnimation *> selectedAnimations = selectAnimations(enabledTransitions);
-#endif
-
- enterStates(event, exitedStates, enteredStates, statesForDefaultEntry, assignmentsForEnteredStates
-#if QT_CONFIG(animation)
- , selectedAnimations
-#endif
- );
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": configuration after entering states:" << configuration;
- qDebug() << q_func() << ": end microstep";
-#endif
-}
-
-/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-procedure computeExitSet(enabledTransitions)
-
-For each transition t in enabledTransitions, if t is targetless then do nothing, else compute the
-transition's domain. (This will be the source state in the case of internal transitions) or the
-least common compound ancestor state of the source state and target states of t (in the case of
-external transitions. Add to the statesToExit set all states in the configuration that are
-descendants of the domain.
-
-function computeExitSet(transitions)
- statesToExit = new OrderedSet
- for t in transitions:
- if (t.target):
- domain = getTransitionDomain(t)
- for s in configuration:
- if isDescendant(s,domain):
- statesToExit.add(s)
- return statesToExit
-*/
-QList<QAbstractState*> QStateMachinePrivate::computeExitSet(const QList<QAbstractTransition*> &enabledTransitions,
- CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).values();
- std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
- return statesToExit_sorted;
-}
-
-QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions,
- CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- QSet<QAbstractState*> statesToExit;
- for (QAbstractTransition *t : enabledTransitions)
- statesToExit.unite(computeExitSet_Unordered(t, cache));
- return statesToExit;
-}
-
-QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(QAbstractTransition *t,
- CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- QSet<QAbstractState*> statesToExit;
- if (cache->exitSet(t, &statesToExit))
- return statesToExit;
-
- QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t, cache);
- QAbstractState *domain = getTransitionDomain(t, effectiveTargetStates, cache);
- if (domain == nullptr && !t->targetStates().isEmpty()) {
- // So we didn't find the least common ancestor for the source and target states of the
- // transition. If there were not target states, that would be fine: then the transition
- // will fire any events or signals, but not exit the state.
- //
- // However, there are target states, so it's either a node without a parent (or parent's
- // parent, etc), or the state belongs to a different state machine. Either way, this
- // makes the state machine invalid.
- if (error == QStateMachine::NoError)
- setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
- QList<QAbstractState *> lst = pendingErrorStates.values();
- lst.prepend(t->sourceState());
-
- domain = findLCCA(lst);
- Q_ASSERT(domain != nullptr);
- }
-
- for (QAbstractState* s : qAsConst(configuration)) {
- if (isDescendant(s, domain))
- statesToExit.insert(s);
- }
-
- cache->insert(t, statesToExit);
- return statesToExit;
-}
-
-void QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractState*> &statesToExit_sorted,
- const QHash<QAbstractState*, QVector<QPropertyAssignment> > &assignmentsForEnteredStates)
-{
- for (int i = 0; i < statesToExit_sorted.size(); ++i) {
- QAbstractState *s = statesToExit_sorted.at(i);
- if (QState *grp = toStandardState(s)) {
- QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
- for (int j = 0; j < hlst.size(); ++j) {
- QHistoryState *h = hlst.at(j);
- QHistoryStatePrivate::get(h)->configuration.clear();
- QSet<QAbstractState*>::const_iterator it;
- for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
- QAbstractState *s0 = *it;
- if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) {
- if (isAtomic(s0) && isDescendant(s0, s))
- QHistoryStatePrivate::get(h)->configuration.append(s0);
- } else if (s0->parentState() == s) {
- QHistoryStatePrivate::get(h)->configuration.append(s0);
- }
- }
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
- << "history for" << s << "in" << h << ':' << QHistoryStatePrivate::get(h)->configuration;
-#endif
- }
- }
- }
- for (int i = 0; i < statesToExit_sorted.size(); ++i) {
- QAbstractState *s = statesToExit_sorted.at(i);
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": exiting" << s;
-#endif
- QAbstractStatePrivate::get(s)->callOnExit(event);
-
-#if QT_CONFIG(animation)
- terminateActiveAnimations(s, assignmentsForEnteredStates);
-#else
- Q_UNUSED(assignmentsForEnteredStates);
-#endif
-
- configuration.remove(s);
- QAbstractStatePrivate::get(s)->emitExited();
- }
-}
-
-void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
-{
- for (int i = 0; i < enabledTransitions.size(); ++i) {
- QAbstractTransition *t = enabledTransitions.at(i);
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": triggering" << t;
-#endif
- QAbstractTransitionPrivate::get(t)->callOnTransition(event);
- QAbstractTransitionPrivate::get(t)->emitTriggered();
- }
-}
-
-QList<QAbstractState*> QStateMachinePrivate::computeEntrySet(const QList<QAbstractTransition *> &enabledTransitions,
- QSet<QAbstractState *> &statesForDefaultEntry,
- CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- QSet<QAbstractState*> statesToEnter;
- if (pendingErrorStates.isEmpty()) {
- for (QAbstractTransition *t : enabledTransitions) {
- const auto targetStates = t->targetStates();
- for (QAbstractState *s : targetStates)
- addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
-
- const QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t, cache);
- QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates, cache);
- for (QAbstractState *s : effectiveTargetStates)
- addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry);
- }
- }
-
- // Did an error occur while selecting transitions? Then we enter the error state.
- if (!pendingErrorStates.isEmpty()) {
- statesToEnter.clear();
- statesToEnter = pendingErrorStates;
- statesForDefaultEntry = pendingErrorStatesForDefaultEntry;
- pendingErrorStates.clear();
- pendingErrorStatesForDefaultEntry.clear();
- }
-
- QList<QAbstractState*> statesToEnter_sorted = statesToEnter.values();
- std::sort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
- return statesToEnter_sorted;
-}
-
-/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-function getTransitionDomain(transition)
-
-Return the compound state such that 1) all states that are exited or entered as a result of taking
-'transition' are descendants of it 2) no descendant of it has this property.
-
-function getTransitionDomain(t)
- tstates = getEffectiveTargetStates(t)
- if not tstates:
- return null
- elif t.type == "internal" and isCompoundState(t.source) and tstates.every(lambda s: isDescendant(s,t.source)):
- return t.source
- else:
- return findLCCA([t.source].append(tstates))
-*/
-QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t,
- const QList<QAbstractState *> &effectiveTargetStates,
- CalculationCache *cache)
-{
- Q_ASSERT(cache);
-
- if (effectiveTargetStates.isEmpty())
- return nullptr;
-
- QAbstractState *domain = nullptr;
- if (cache->transitionDomain(t, &domain))
- return domain;
-
- if (t->transitionType() == QAbstractTransition::InternalTransition) {
- if (QState *tSource = t->sourceState()) {
- if (isCompound(tSource)) {
- bool allDescendants = true;
- for (QAbstractState *s : effectiveTargetStates) {
- if (!isDescendant(s, tSource)) {
- allDescendants = false;
- break;
- }
- }
-
- if (allDescendants)
- return tSource;
- }
- }
- }
-
- QList<QAbstractState *> states(effectiveTargetStates);
- if (QAbstractState *src = t->sourceState())
- states.prepend(src);
- domain = findLCCA(states);
- cache->insert(t, domain);
- return domain;
-}
-
-void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted,
- const QList<QAbstractState*> &statesToEnter_sorted,
- const QSet<QAbstractState*> &statesForDefaultEntry,
- QHash<QAbstractState*, QVector<QPropertyAssignment> > &propertyAssignmentsForState
-#if QT_CONFIG(animation)
- , const QList<QAbstractAnimation *> &selectedAnimations
-#endif
- )
-{
-#ifdef QSTATEMACHINE_DEBUG
- Q_Q(QStateMachine);
-#endif
- for (int i = 0; i < statesToEnter_sorted.size(); ++i) {
- QAbstractState *s = statesToEnter_sorted.at(i);
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": entering" << s;
-#endif
- configuration.insert(s);
- registerTransitions(s);
-
-#if QT_CONFIG(animation)
- initializeAnimations(s, selectedAnimations, exitedStates_sorted, propertyAssignmentsForState);
-#endif
-
- // Immediately set the properties that are not animated.
- {
- QVector<QPropertyAssignment> assignments = propertyAssignmentsForState.value(s);
- for (int i = 0; i < assignments.size(); ++i) {
- const QPropertyAssignment &assn = assignments.at(i);
- if (globalRestorePolicy == QState::RestoreProperties) {
- if (assn.explicitlySet) {
- if (!hasRestorable(s, assn.object, assn.propertyName)) {
- QVariant value = savedValueForRestorable(exitedStates_sorted, assn.object, assn.propertyName);
- unregisterRestorables(exitedStates_sorted, assn.object, assn.propertyName);
- registerRestorable(s, assn.object, assn.propertyName, value);
- }
- } else {
- // The property is being restored, hence no need to
- // save the current value. Discard any saved values in
- // exited states, since those are now stale.
- unregisterRestorables(exitedStates_sorted, assn.object, assn.propertyName);
- }
- }
- assn.write();
- }
- }
-
- QAbstractStatePrivate::get(s)->callOnEntry(event);
- QAbstractStatePrivate::get(s)->emitEntered();
-
- // FIXME:
- // See the "initial transitions" comment in addDescendantStatesToEnter first, then implement:
-// if (statesForDefaultEntry.contains(s)) {
-// // ### executeContent(s.initial.transition.children())
-// }
- Q_UNUSED(statesForDefaultEntry);
-
- if (QHistoryState *h = toHistoryState(s))
- QAbstractTransitionPrivate::get(h->defaultTransition())->callOnTransition(event);
-
- // Emit propertiesAssigned signal if the state has no animated properties.
- {
- QState *ss = toStandardState(s);
- if (ss
- #if QT_CONFIG(animation)
- && !animationsForState.contains(s)
- #endif
- )
- QStatePrivate::get(ss)->emitPropertiesAssigned();
- }
-
- if (isFinal(s)) {
- QState *parent = s->parentState();
- if (parent) {
- if (parent != rootState()) {
- QFinalState *finalState = qobject_cast<QFinalState *>(s);
- Q_ASSERT(finalState);
- emitStateFinished(parent, finalState);
- }
- QState *grandparent = parent->parentState();
- if (grandparent && isParallel(grandparent)) {
- bool allChildStatesFinal = true;
- QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates();
- for (int j = 0; j < childStates.size(); ++j) {
- QAbstractState *cs = childStates.at(j);
- if (!isInFinalState(cs)) {
- allChildStatesFinal = false;
- break;
- }
- }
- if (allChildStatesFinal && (grandparent != rootState())) {
- QFinalState *finalState = qobject_cast<QFinalState *>(s);
- Q_ASSERT(finalState);
- emitStateFinished(grandparent, finalState);
- }
- }
- }
- }
- }
- {
- QSet<QAbstractState*>::const_iterator it;
- for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
- if (isFinal(*it)) {
- QState *parent = (*it)->parentState();
- if (((parent == rootState())
- && (rootState()->childMode() == QState::ExclusiveStates))
- || ((parent->parentState() == rootState())
- && (rootState()->childMode() == QState::ParallelStates)
- && isInFinalState(rootState()))) {
- processing = false;
- stopProcessingReason = Finished;
- break;
- }
- }
- }
- }
-// qDebug() << "configuration:" << configuration.toList();
-}
-
-/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ has a bug. See
- * QTBUG-44963 for details. The algorithm here is as described in
- * http://www.w3.org/Voice/2013/scxml-irp/SCXML.htm as of Friday March 13, 2015.
-
-procedure addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry, defaultHistoryContent):
- if isHistoryState(state):
- if historyValue[state.id]:
- for s in historyValue[state.id]:
- addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
- for s in historyValue[state.id]:
- addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
- else:
- defaultHistoryContent[state.parent.id] = state.transition.content
- for s in state.transition.target:
- addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
- for s in state.transition.target:
- addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
- else:
- statesToEnter.add(state)
- if isCompoundState(state):
- statesForDefaultEntry.add(state)
- for s in state.initial.transition.target:
- addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
- for s in state.initial.transition.target:
- addAncestorStatesToEnter(s, state, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
- else:
- if isParallelState(state):
- for child in getChildStates(state):
- if not statesToEnter.some(lambda s: isDescendant(s,child)):
- addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
-*/
-void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state,
- QSet<QAbstractState*> &statesToEnter,
- QSet<QAbstractState*> &statesForDefaultEntry)
-{
- if (QHistoryState *h = toHistoryState(state)) {
- const QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(h)->configuration;
- if (!historyConfiguration.isEmpty()) {
- for (QAbstractState *s : historyConfiguration)
- addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
- for (QAbstractState *s : historyConfiguration)
- addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry);
-
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": restoring"
- << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
- << "history from" << state << ':' << historyConfiguration;
-#endif
- } else {
- QList<QAbstractState*> defaultHistoryContent;
- if (QAbstractTransition *t = QHistoryStatePrivate::get(h)->defaultTransition)
- defaultHistoryContent = t->targetStates();
-
- if (defaultHistoryContent.isEmpty()) {
- setError(QStateMachine::NoDefaultStateInHistoryStateError, h);
- } else {
- for (QAbstractState *s : qAsConst(defaultHistoryContent))
- addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
- for (QAbstractState *s : qAsConst(defaultHistoryContent))
- addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry);
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": initial history targets for" << state << ':' << defaultHistoryContent;
-#endif
- }
- }
- } else {
- if (state == rootState()) {
- // Error has already been set by exitStates().
- Q_ASSERT(error != QStateMachine::NoError);
- return;
- }
- statesToEnter.insert(state);
- if (isCompound(state)) {
- statesForDefaultEntry.insert(state);
- if (QAbstractState *initial = toStandardState(state)->initialState()) {
- Q_ASSERT(initial->machine() == q_func());
-
- // FIXME:
- // Qt does not support initial transitions (which is a problem for parallel states).
- // The way it simulates this for other states, is by having a single initial state.
- // See also the FIXME in enterStates.
- statesForDefaultEntry.insert(initial);
-
- addDescendantStatesToEnter(initial, statesToEnter, statesForDefaultEntry);
- addAncestorStatesToEnter(initial, state, statesToEnter, statesForDefaultEntry);
- } else {
- setError(QStateMachine::NoInitialStateError, state);
- return;
- }
- } else if (isParallel(state)) {
- QState *grp = toStandardState(state);
- const auto childStates = QStatePrivate::get(grp)->childStates();
- for (QAbstractState *child : childStates) {
- if (!containsDecendantOf(statesToEnter, child))
- addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry);
- }
- }
- }
-}
-
-
-/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
-
-procedure addAncestorStatesToEnter(state, ancestor, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
- for anc in getProperAncestors(state,ancestor):
- statesToEnter.add(anc)
- if isParallelState(anc):
- for child in getChildStates(anc):
- if not statesToEnter.some(lambda s: isDescendant(s,child)):
- addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
-*/
-void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor,
- QSet<QAbstractState*> &statesToEnter,
- QSet<QAbstractState*> &statesForDefaultEntry)
-{
- const auto properAncestors = getProperAncestors(s, ancestor);
- for (QState *anc : properAncestors) {
- if (!anc->parentState())
- continue;
- statesToEnter.insert(anc);
- if (isParallel(anc)) {
- const auto childStates = QStatePrivate::get(anc)->childStates();
- for (QAbstractState *child : childStates) {
- if (!containsDecendantOf(statesToEnter, child))
- addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry);
- }
- }
- }
-}
-
-bool QStateMachinePrivate::isFinal(const QAbstractState *s)
-{
- return s && (QAbstractStatePrivate::get(s)->stateType == QAbstractStatePrivate::FinalState);
-}
-
-bool QStateMachinePrivate::isParallel(const QAbstractState *s)
-{
- const QState *ss = toStandardState(s);
- return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
-}
-
-bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
-{
- const QState *group = toStandardState(s);
- if (!group)
- return false;
- bool isMachine = QStatePrivate::get(group)->isMachine;
- // Don't treat the machine as compound if it's a sub-state of this machine
- if (isMachine && (group != rootState()))
- return false;
- return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty());
-}
-
-bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
-{
- const QState *ss = toStandardState(s);
- return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
- || isFinal(s)
- // Treat the machine as atomic if it's a sub-state of this machine
- || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState()));
-}
-
-QState *QStateMachinePrivate::toStandardState(QAbstractState *state)
-{
- if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
- return static_cast<QState*>(state);
- return nullptr;
-}
-
-const QState *QStateMachinePrivate::toStandardState(const QAbstractState *state)
-{
- if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
- return static_cast<const QState*>(state);
- return nullptr;
-}
-
-QFinalState *QStateMachinePrivate::toFinalState(QAbstractState *state)
-{
- if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::FinalState))
- return static_cast<QFinalState*>(state);
- return nullptr;
-}
-
-QHistoryState *QStateMachinePrivate::toHistoryState(QAbstractState *state)
-{
- if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::HistoryState))
- return static_cast<QHistoryState*>(state);
- return nullptr;
-}
-
-bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
-{
- if (isCompound(s)) {
- QState *grp = toStandardState(s);
- QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
- for (int i = 0; i < lst.size(); ++i) {
- QAbstractState *cs = lst.at(i);
- if (isFinal(cs) && configuration.contains(cs))
- return true;
- }
- return false;
- } else if (isParallel(s)) {
- QState *grp = toStandardState(s);
- QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
- for (int i = 0; i < lst.size(); ++i) {
- QAbstractState *cs = lst.at(i);
- if (!isInFinalState(cs))
- return false;
- }
- return true;
- }
- else
- return false;
-}
-
-#ifndef QT_NO_PROPERTIES
-
-/*!
- \internal
- Returns \c true if the given state has saved the value of the given property,
- otherwise returns \c false.
-*/
-bool QStateMachinePrivate::hasRestorable(QAbstractState *state, QObject *object,
- const QByteArray &propertyName) const
-{
- RestorableId id(object, propertyName);
- return registeredRestorablesForState.value(state).contains(id);
-}
-
-/*!
- \internal
- Returns the value to save for the property identified by \a id.
- If an exited state (member of \a exitedStates_sorted) has saved a value for
- the property, the saved value from the last (outermost) state that will be
- exited is returned (in practice carrying the saved value on to the next
- state). Otherwise, the current value of the property is returned.
-*/
-QVariant QStateMachinePrivate::savedValueForRestorable(const QList<QAbstractState*> &exitedStates_sorted,
- QObject *object, const QByteArray &propertyName) const
-{
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": savedValueForRestorable(" << exitedStates_sorted << object << propertyName << ')';
-#endif
- for (int i = exitedStates_sorted.size() - 1; i >= 0; --i) {
- QAbstractState *s = exitedStates_sorted.at(i);
- QHash<RestorableId, QVariant> restorables = registeredRestorablesForState.value(s);
- QHash<RestorableId, QVariant>::const_iterator it = restorables.constFind(RestorableId(object, propertyName));
- if (it != restorables.constEnd()) {
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": using" << it.value() << "from" << s;
-#endif
- return it.value();
- }
- }
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": falling back to current value";
-#endif
- return object->property(propertyName);
-}
-
-void QStateMachinePrivate::registerRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName,
- const QVariant &value)
-{
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": registerRestorable(" << state << object << propertyName << value << ')';
-#endif
- RestorableId id(object, propertyName);
- QHash<RestorableId, QVariant> &restorables = registeredRestorablesForState[state];
- if (!restorables.contains(id))
- restorables.insert(id, value);
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- else
- qDebug() << q_func() << ": (already registered)";
-#endif
-}
-
-void QStateMachinePrivate::unregisterRestorables(const QList<QAbstractState *> &states, QObject *object,
- const QByteArray &propertyName)
-{
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": unregisterRestorables(" << states << object << propertyName << ')';
-#endif
- RestorableId id(object, propertyName);
- for (int i = 0; i < states.size(); ++i) {
- QAbstractState *s = states.at(i);
- QHash<QAbstractState*, QHash<RestorableId, QVariant> >::iterator it;
- it = registeredRestorablesForState.find(s);
- if (it == registeredRestorablesForState.end())
- continue;
- QHash<RestorableId, QVariant> &restorables = it.value();
- const auto it2 = restorables.constFind(id);
- if (it2 == restorables.cend())
- continue;
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": unregistered for" << s;
-#endif
- restorables.erase(it2);
- if (restorables.isEmpty())
- registeredRestorablesForState.erase(it);
- }
-}
-
-QVector<QPropertyAssignment> QStateMachinePrivate::restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const
-{
- QVector<QPropertyAssignment> result;
- QHash<RestorableId, QVariant>::const_iterator it;
- for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) {
- const RestorableId &id = it.key();
- if (!id.object()) {
- // Property object was deleted
- continue;
- }
-#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
- qDebug() << q_func() << ": restoring" << id.object() << id.proertyName() << "to" << it.value();
-#endif
- result.append(QPropertyAssignment(id.object(), id.propertyName(), it.value(), /*explicitlySet=*/false));
- }
- return result;
-}
-
-/*!
- \internal
- Computes the set of properties whose values should be restored given that
- the states \a statesToExit_sorted will be exited.
-
- If a particular (object, propertyName) pair occurs more than once (i.e.,
- because nested states are being exited), the value from the last (outermost)
- exited state takes precedence.
-
- The result of this function must be filtered according to the explicit
- property assignments (QState::assignProperty()) of the entered states
- before the property restoration is actually performed; i.e., if an entered
- state assigns to a property that would otherwise be restored, that property
- should not be restored after all, but the saved value from the exited state
- should be remembered by the entered state (see registerRestorable()).
-*/
-QHash<QStateMachinePrivate::RestorableId, QVariant> QStateMachinePrivate::computePendingRestorables(
- const QList<QAbstractState*> &statesToExit_sorted) const
-{
- QHash<QStateMachinePrivate::RestorableId, QVariant> restorables;
- for (int i = statesToExit_sorted.size() - 1; i >= 0; --i) {
- QAbstractState *s = statesToExit_sorted.at(i);
- QHash<QStateMachinePrivate::RestorableId, QVariant> rs = registeredRestorablesForState.value(s);
- QHash<QStateMachinePrivate::RestorableId, QVariant>::const_iterator it;
- for (it = rs.constBegin(); it != rs.constEnd(); ++it) {
- if (!restorables.contains(it.key()))
- restorables.insert(it.key(), it.value());
- }
- }
- return restorables;
-}
-
-/*!
- \internal
- Computes the ordered sets of property assignments for the states to be
- entered, \a statesToEnter_sorted. Also filters \a pendingRestorables (removes
- properties that should not be restored because they are assigned by an
- entered state).
-*/
-QHash<QAbstractState*, QVector<QPropertyAssignment> > QStateMachinePrivate::computePropertyAssignments(
- const QList<QAbstractState*> &statesToEnter_sorted, QHash<RestorableId, QVariant> &pendingRestorables) const
-{
- QHash<QAbstractState*, QVector<QPropertyAssignment> > assignmentsForState;
- for (int i = 0; i < statesToEnter_sorted.size(); ++i) {
- QState *s = toStandardState(statesToEnter_sorted.at(i));
- if (!s)
- continue;
-
- QVector<QPropertyAssignment> &assignments = QStatePrivate::get(s)->propertyAssignments;
- for (int j = 0; j < assignments.size(); ++j) {
- const QPropertyAssignment &assn = assignments.at(j);
- if (assn.objectDeleted()) {
- assignments.removeAt(j--);
- } else {
- pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
- assignmentsForState[s].append(assn);
- }
- }
- }
- return assignmentsForState;
-}
-
-#endif // QT_NO_PROPERTIES
-
-QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
-{
- // Find error state recursively in parent hierarchy if not set explicitly for context state
- QAbstractState *errorState = nullptr;
- if (context != nullptr) {
- QState *s = toStandardState(context);
- if (s != nullptr)
- errorState = s->errorState();
-
- if (errorState == nullptr)
- errorState = findErrorState(context->parentState());
- }
-
- return errorState;
-}
-
-void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext)
-{
- Q_Q(QStateMachine);
-
- error = errorCode;
- switch (errorCode) {
- case QStateMachine::NoInitialStateError:
- Q_ASSERT(currentContext != nullptr);
-
- errorString = QStateMachine::tr("Missing initial state in compound state '%1'")
- .arg(currentContext->objectName());
-
- break;
- case QStateMachine::NoDefaultStateInHistoryStateError:
- Q_ASSERT(currentContext != nullptr);
-
- errorString = QStateMachine::tr("Missing default state in history state '%1'")
- .arg(currentContext->objectName());
- break;
-
- case QStateMachine::NoCommonAncestorForTransitionError:
- Q_ASSERT(currentContext != nullptr);
-
- errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
- .arg(currentContext->objectName());
- break;
-
- case QStateMachine::StateMachineChildModeSetToParallelError:
- Q_ASSERT(currentContext != nullptr);
-
- errorString = QStateMachine::tr("Child mode of state machine '%1' is not 'ExclusiveStates'.")
- .arg(currentContext->objectName());
- break;
-
- default:
- errorString = QStateMachine::tr("Unknown error");
- };
-
- pendingErrorStates.clear();
- pendingErrorStatesForDefaultEntry.clear();
-
- QAbstractState *currentErrorState = findErrorState(currentContext);
-
- // Avoid infinite loop if the error state itself has an error
- if (currentContext == currentErrorState)
- currentErrorState = nullptr;
-
- Q_ASSERT(currentErrorState != rootState());
-
- if (currentErrorState != nullptr) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": entering error state" << currentErrorState << "from" << currentContext;
-#endif
- pendingErrorStates.insert(currentErrorState);
- addDescendantStatesToEnter(currentErrorState, pendingErrorStates, pendingErrorStatesForDefaultEntry);
- addAncestorStatesToEnter(currentErrorState, rootState(), pendingErrorStates, pendingErrorStatesForDefaultEntry);
- pendingErrorStates -= configuration;
- } else {
- qWarning("Unrecoverable error detected in running state machine: %ls",
- qUtf16Printable(errorString));
- q->stop();
- }
-}
-
-#if QT_CONFIG(animation)
-
-QStateMachinePrivate::InitializeAnimationResult
-QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation,
- const QPropertyAssignment &prop)
-{
- InitializeAnimationResult result;
- QAnimationGroup *group = qobject_cast<QAnimationGroup*>(abstractAnimation);
- if (group) {
- for (int i = 0; i < group->animationCount(); ++i) {
- QAbstractAnimation *animationChild = group->animationAt(i);
- const auto ret = initializeAnimation(animationChild, prop);
- result.handledAnimations << ret.handledAnimations;
- result.localResetEndValues << ret.localResetEndValues;
- }
- } else {
- QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(abstractAnimation);
- if (animation != nullptr
- && prop.object == animation->targetObject()
- && prop.propertyName == animation->propertyName()) {
-
- // Only change end value if it is undefined
- if (!animation->endValue().isValid()) {
- animation->setEndValue(prop.value);
- result.localResetEndValues.append(animation);
- }
- result.handledAnimations.append(animation);
- }
- }
- return result;
-}
-
-void QStateMachinePrivate::_q_animationFinished()
-{
- Q_Q(QStateMachine);
- QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender());
- Q_ASSERT(anim != nullptr);
- QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
- if (resetAnimationEndValues.contains(anim)) {
- qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
- resetAnimationEndValues.remove(anim);
- }
-
- QAbstractState *state = stateForAnimation.take(anim);
- Q_ASSERT(state != nullptr);
-
-#ifndef QT_NO_PROPERTIES
- // Set the final property value.
- QPropertyAssignment assn = propertyForAnimation.take(anim);
- assn.write();
- if (!assn.explicitlySet)
- unregisterRestorables(QList<QAbstractState*>() << state, assn.object, assn.propertyName);
-#endif
-
- QHash<QAbstractState*, QList<QAbstractAnimation*> >::iterator it;
- it = animationsForState.find(state);
- Q_ASSERT(it != animationsForState.end());
- QList<QAbstractAnimation*> &animations = it.value();
- animations.removeOne(anim);
- if (animations.isEmpty()) {
- animationsForState.erase(it);
- QStatePrivate::get(toStandardState(state))->emitPropertiesAssigned();
- }
-}
-
-QList<QAbstractAnimation *> QStateMachinePrivate::selectAnimations(const QList<QAbstractTransition *> &transitionList) const
-{
- QList<QAbstractAnimation *> selectedAnimations;
- if (animated) {
- for (int i = 0; i < transitionList.size(); ++i) {
- QAbstractTransition *transition = transitionList.at(i);
-
- selectedAnimations << transition->animations();
- selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
-
- QList<QAbstractState *> targetStates = transition->targetStates();
- for (int j=0; j<targetStates.size(); ++j)
- selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j));
- }
- selectedAnimations << defaultAnimations;
- }
- return selectedAnimations;
-}
-
-void QStateMachinePrivate::terminateActiveAnimations(QAbstractState *state,
- const QHash<QAbstractState*, QVector<QPropertyAssignment> > &assignmentsForEnteredStates)
-{
- Q_Q(QStateMachine);
- QList<QAbstractAnimation*> animations = animationsForState.take(state);
- for (int i = 0; i < animations.size(); ++i) {
- QAbstractAnimation *anim = animations.at(i);
- QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
- stateForAnimation.remove(anim);
-
- // Stop the (top-level) animation.
- // ### Stopping nested animation has weird behavior.
- QAbstractAnimation *topLevelAnim = anim;
- while (QAnimationGroup *group = topLevelAnim->group())
- topLevelAnim = group;
- topLevelAnim->stop();
-
- if (resetAnimationEndValues.contains(anim)) {
- qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
- resetAnimationEndValues.remove(anim);
- }
- QPropertyAssignment assn = propertyForAnimation.take(anim);
- Q_ASSERT(assn.object != nullptr);
- // If there is no property assignment that sets this property,
- // set the property to its target value.
- bool found = false;
- QHash<QAbstractState*, QVector<QPropertyAssignment> >::const_iterator it;
- for (it = assignmentsForEnteredStates.constBegin(); it != assignmentsForEnteredStates.constEnd(); ++it) {
- const QVector<QPropertyAssignment> &assignments = it.value();
- for (int j = 0; j < assignments.size(); ++j) {
- if (assignments.at(j).hasTarget(assn.object, assn.propertyName)) {
- found = true;
- break;
- }
- }
- }
- if (!found) {
- assn.write();
- if (!assn.explicitlySet)
- unregisterRestorables(QList<QAbstractState*>() << state, assn.object, assn.propertyName);
- }
- }
-}
-
-void QStateMachinePrivate::initializeAnimations(QAbstractState *state, const QList<QAbstractAnimation *> &selectedAnimations,
- const QList<QAbstractState*> &exitedStates_sorted,
- QHash<QAbstractState*, QVector<QPropertyAssignment> > &assignmentsForEnteredStates)
-{
- Q_Q(QStateMachine);
- if (!assignmentsForEnteredStates.contains(state))
- return;
- QVector<QPropertyAssignment> &assignments = assignmentsForEnteredStates[state];
- for (int i = 0; i < selectedAnimations.size(); ++i) {
- QAbstractAnimation *anim = selectedAnimations.at(i);
- QVector<QPropertyAssignment>::iterator it;
- for (it = assignments.begin(); it != assignments.end(); ) {
- const QPropertyAssignment &assn = *it;
- const auto ret = initializeAnimation(anim, assn);
- if (!ret.handledAnimations.isEmpty()) {
- for (int j = 0; j < ret.handledAnimations.size(); ++j) {
- QAbstractAnimation *a = ret.handledAnimations.at(j);
- propertyForAnimation.insert(a, assn);
- stateForAnimation.insert(a, state);
- animationsForState[state].append(a);
- // ### connect to just the top-level animation?
- QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()), Qt::UniqueConnection);
- }
- if ((globalRestorePolicy == QState::RestoreProperties)
- && !hasRestorable(state, assn.object, assn.propertyName)) {
- QVariant value = savedValueForRestorable(exitedStates_sorted, assn.object, assn.propertyName);
- unregisterRestorables(exitedStates_sorted, assn.object, assn.propertyName);
- registerRestorable(state, assn.object, assn.propertyName, value);
- }
- it = assignments.erase(it);
- } else {
- ++it;
- }
- for (int j = 0; j < ret.localResetEndValues.size(); ++j)
- resetAnimationEndValues.insert(ret.localResetEndValues.at(j));
- }
- // We require that at least one animation is valid.
- // ### generalize
- QList<QVariantAnimation*> variantAnims = anim->findChildren<QVariantAnimation*>();
- if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim))
- variantAnims.append(va);
-
- bool hasValidEndValue = false;
- for (int j = 0; j < variantAnims.size(); ++j) {
- if (variantAnims.at(j)->endValue().isValid()) {
- hasValidEndValue = true;
- break;
- }
- }
-
- if (hasValidEndValue) {
- if (anim->state() == QAbstractAnimation::Running) {
- // The animation is still running. This can happen if the
- // animation is a group, and one of its children just finished,
- // and that caused a state to emit its propertiesAssigned() signal, and
- // that triggered a transition in the machine.
- // Just stop the animation so it is correctly restarted again.
- anim->stop();
- }
- anim->start();
- }
-
- if (assignments.isEmpty()) {
- assignmentsForEnteredStates.remove(state);
- break;
- }
- }
-}
-
-#endif // animation
-
-QAbstractTransition *QStateMachinePrivate::createInitialTransition() const
-{
- class InitialTransition : public QAbstractTransition
- {
- public:
- InitialTransition(const QList<QAbstractState *> &targets)
- : QAbstractTransition()
- { setTargetStates(targets); }
- protected:
- bool eventTest(QEvent *) override { return true; }
- void onTransition(QEvent *) override {}
- };
-
- QState *root = rootState();
- Q_ASSERT(root != nullptr);
- QList<QAbstractState *> targets;
- switch (root->childMode()) {
- case QState::ExclusiveStates:
- targets.append(root->initialState());
- break;
- case QState::ParallelStates:
- targets = QStatePrivate::get(root)->childStates();
- break;
- }
- return new InitialTransition(targets);
-}
-
-void QStateMachinePrivate::clearHistory()
-{
- Q_Q(QStateMachine);
- QList<QHistoryState*> historyStates = q->findChildren<QHistoryState*>();
- for (int i = 0; i < historyStates.size(); ++i) {
- QHistoryState *h = historyStates.at(i);
- QHistoryStatePrivate::get(h)->configuration.clear();
- }
-}
-
-/*!
- \internal
-
- Registers all signal transitions whose sender object lives in another thread.
-
- Normally, signal transitions are lazily registered (when a state becomes
- active). But if the sender is in a different thread, the transition must be
- registered early to keep the state machine from "dropping" signals; e.g.,
- a second (transition-bound) signal could be emitted on the sender thread
- before the state machine gets to process the first signal.
-*/
-void QStateMachinePrivate::registerMultiThreadedSignalTransitions()
-{
- Q_Q(QStateMachine);
- QList<QSignalTransition*> transitions = rootState()->findChildren<QSignalTransition*>();
- for (int i = 0; i < transitions.size(); ++i) {
- QSignalTransition *t = transitions.at(i);
- if ((t->machine() == q) && t->senderObject() && (t->senderObject()->thread() != q->thread()))
- registerSignalTransition(t);
- }
-}
-
-void QStateMachinePrivate::_q_start()
-{
- Q_Q(QStateMachine);
- Q_ASSERT(state == Starting);
- // iterate over a copy, since we emit signals which may cause
- // 'configuration' to change, resulting in undefined behavior when
- // iterating at the same time:
- const auto config = configuration;
- for (QAbstractState *state : config) {
- QAbstractStatePrivate *abstractStatePrivate = QAbstractStatePrivate::get(state);
- abstractStatePrivate->active = false;
- emit state->activeChanged(false);
- }
- configuration.clear();
- qDeleteAll(internalEventQueue);
- internalEventQueue.clear();
- qDeleteAll(externalEventQueue);
- externalEventQueue.clear();
- clearHistory();
-
- registerMultiThreadedSignalTransitions();
-
- startupHook();
-
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": starting";
-#endif
- state = Running;
- processingScheduled = true; // we call _q_process() below
-
- QList<QAbstractTransition*> transitions;
- CalculationCache calculationCache;
- QAbstractTransition *initialTransition = createInitialTransition();
- transitions.append(initialTransition);
-
- QEvent nullEvent(QEvent::None);
- executeTransitionContent(&nullEvent, transitions);
- QList<QAbstractState*> exitedStates = QList<QAbstractState*>();
- QSet<QAbstractState*> statesForDefaultEntry;
- QList<QAbstractState*> enteredStates = computeEntrySet(transitions, statesForDefaultEntry, &calculationCache);
- QHash<RestorableId, QVariant> pendingRestorables;
- QHash<QAbstractState*, QVector<QPropertyAssignment> > assignmentsForEnteredStates =
- computePropertyAssignments(enteredStates, pendingRestorables);
-#if QT_CONFIG(animation)
- QList<QAbstractAnimation*> selectedAnimations = selectAnimations(transitions);
-#endif
- // enterStates() will set stopProcessingReason to Finished if a final
- // state is entered.
- stopProcessingReason = EventQueueEmpty;
- enterStates(&nullEvent, exitedStates, enteredStates, statesForDefaultEntry,
- assignmentsForEnteredStates
-#if QT_CONFIG(animation)
- , selectedAnimations
-#endif
- );
- delete initialTransition;
-
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": initial configuration:" << configuration;
-#endif
-
- emit q->started(QStateMachine::QPrivateSignal());
- emit q->runningChanged(true);
-
- if (stopProcessingReason == Finished) {
- // The state machine immediately reached a final state.
- processingScheduled = false;
- state = NotRunning;
- unregisterAllTransitions();
- emitFinished();
- emit q->runningChanged(false);
- exitInterpreter();
- } else {
- _q_process();
- }
-}
-
-void QStateMachinePrivate::_q_process()
-{
- Q_Q(QStateMachine);
- Q_ASSERT(state == Running);
- Q_ASSERT(!processing);
- processing = true;
- processingScheduled = false;
- beginMacrostep();
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": starting the event processing loop";
-#endif
- bool didChange = false;
- while (processing) {
- if (stop) {
- processing = false;
- break;
- }
- QList<QAbstractTransition*> enabledTransitions;
- CalculationCache calculationCache;
-
- QEvent *e = new QEvent(QEvent::None);
- enabledTransitions = selectTransitions(e, &calculationCache);
- if (enabledTransitions.isEmpty()) {
- delete e;
- e = nullptr;
- }
- while (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != nullptr)) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
-#endif
- enabledTransitions = selectTransitions(e, &calculationCache);
- if (enabledTransitions.isEmpty()) {
- delete e;
- e = nullptr;
- }
- }
- while (enabledTransitions.isEmpty() && ((e = dequeueExternalEvent()) != nullptr)) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
-#endif
- enabledTransitions = selectTransitions(e, &calculationCache);
- if (enabledTransitions.isEmpty()) {
- delete e;
- e = nullptr;
- }
- }
- if (enabledTransitions.isEmpty()) {
- if (isInternalEventQueueEmpty()) {
- processing = false;
- stopProcessingReason = EventQueueEmpty;
- noMicrostep();
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": no transitions enabled";
-#endif
- }
- } else {
- didChange = true;
- q->beginMicrostep(e);
- microstep(e, enabledTransitions, &calculationCache);
- q->endMicrostep(e);
- }
- delete e;
- }
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": finished the event processing loop";
-#endif
- if (stop) {
- stop = false;
- stopProcessingReason = Stopped;
- }
-
- switch (stopProcessingReason) {
- case EventQueueEmpty:
- processedPendingEvents(didChange);
- break;
- case Finished:
- state = NotRunning;
- cancelAllDelayedEvents();
- unregisterAllTransitions();
- emitFinished();
- emit q->runningChanged(false);
- break;
- case Stopped:
- state = NotRunning;
- cancelAllDelayedEvents();
- unregisterAllTransitions();
- emit q->stopped(QStateMachine::QPrivateSignal());
- emit q->runningChanged(false);
- break;
- }
- endMacrostep(didChange);
- if (stopProcessingReason == Finished)
- exitInterpreter();
-}
-
-void QStateMachinePrivate::_q_startDelayedEventTimer(int id, int delay)
-{
- Q_Q(QStateMachine);
- QMutexLocker locker(&delayedEventsMutex);
- QHash<int, DelayedEvent>::iterator it = delayedEvents.find(id);
- if (it != delayedEvents.end()) {
- DelayedEvent &e = it.value();
- Q_ASSERT(!e.timerId);
- e.timerId = q->startTimer(delay);
- if (!e.timerId) {
- qWarning("QStateMachine::postDelayedEvent: failed to start timer (id=%d, delay=%d)", id, delay);
- delete e.event;
- delayedEvents.erase(it);
- delayedEventIdFreeList.release(id);
- } else {
- timerIdToDelayedEventId.insert(e.timerId, id);
- }
- } else {
- // It's been cancelled already
- delayedEventIdFreeList.release(id);
- }
-}
-
-void QStateMachinePrivate::_q_killDelayedEventTimer(int id, int timerId)
-{
- Q_Q(QStateMachine);
- q->killTimer(timerId);
- QMutexLocker locker(&delayedEventsMutex);
- delayedEventIdFreeList.release(id);
-}
-
-void QStateMachinePrivate::postInternalEvent(QEvent *e)
-{
- QMutexLocker locker(&internalEventMutex);
- internalEventQueue.append(e);
-}
-
-void QStateMachinePrivate::postExternalEvent(QEvent *e)
-{
- QMutexLocker locker(&externalEventMutex);
- externalEventQueue.append(e);
-}
-
-QEvent *QStateMachinePrivate::dequeueInternalEvent()
-{
- QMutexLocker locker(&internalEventMutex);
- if (internalEventQueue.isEmpty())
- return nullptr;
- return internalEventQueue.takeFirst();
-}
-
-QEvent *QStateMachinePrivate::dequeueExternalEvent()
-{
- QMutexLocker locker(&externalEventMutex);
- if (externalEventQueue.isEmpty())
- return nullptr;
- return externalEventQueue.takeFirst();
-}
-
-bool QStateMachinePrivate::isInternalEventQueueEmpty()
-{
- QMutexLocker locker(&internalEventMutex);
- return internalEventQueue.isEmpty();
-}
-
-bool QStateMachinePrivate::isExternalEventQueueEmpty()
-{
- QMutexLocker locker(&externalEventMutex);
- return externalEventQueue.isEmpty();
-}
-
-void QStateMachinePrivate::processEvents(EventProcessingMode processingMode)
-{
- Q_Q(QStateMachine);
- if ((state != Running) || processing || processingScheduled)
- return;
- switch (processingMode) {
- case DirectProcessing:
- if (QThread::currentThread() == q->thread()) {
- _q_process();
- break;
- }
- // processing must be done in the machine thread, so:
- Q_FALLTHROUGH();
- case QueuedProcessing:
- processingScheduled = true;
- QMetaObject::invokeMethod(q, "_q_process", Qt::QueuedConnection);
- break;
- }
-}
-
-void QStateMachinePrivate::cancelAllDelayedEvents()
-{
- Q_Q(QStateMachine);
- QMutexLocker locker(&delayedEventsMutex);
- QHash<int, DelayedEvent>::const_iterator it;
- for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) {
- const DelayedEvent &e = it.value();
- if (e.timerId) {
- timerIdToDelayedEventId.remove(e.timerId);
- q->killTimer(e.timerId);
- delayedEventIdFreeList.release(it.key());
- } else {
- // Cancellation will be detected in pending _q_startDelayedEventTimer() call
- }
- delete e.event;
- }
- delayedEvents.clear();
-}
-
-/*
- This function is called when the state machine is performing no
- microstep because no transition is enabled (i.e. an event is ignored).
-
- The default implementation does nothing.
-*/
-void QStateMachinePrivate::noMicrostep()
-{ }
-
-/*
- This function is called when the state machine has reached a stable
- state (no pending events), and has not finished yet.
- For each event the state machine receives it is guaranteed that
- 1) beginMacrostep is called
- 2) selectTransition is called at least once
- 3) begin/endMicrostep is called at least once or noMicrostep is called
- at least once (possibly both, but at least one)
- 4) the state machine either enters an infinite loop, or stops (runningChanged(false),
- and either finished or stopped are emitted), or processedPendingEvents() is called.
- 5) if the machine is not in an infinite loop endMacrostep is called
- 6) when the machine is finished and all processing (like signal emission) is done,
- exitInterpreter() is called. (This is the same name as the SCXML specification uses.)
-
- didChange is set to true if at least one microstep was performed, it is possible
- that the machine returned to exactly the same state as before, but some transitions
- were triggered.
-
- The default implementation does nothing.
-*/
-void QStateMachinePrivate::processedPendingEvents(bool didChange)
-{
- Q_UNUSED(didChange);
-}
-
-void QStateMachinePrivate::beginMacrostep()
-{ }
-
-void QStateMachinePrivate::endMacrostep(bool didChange)
-{
- Q_UNUSED(didChange);
-}
-
-void QStateMachinePrivate::exitInterpreter()
-{
-}
-
-void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guiltyState)
-{
- Q_UNUSED(guiltyState);
- Q_ASSERT(guiltyState);
-
-#ifdef QSTATEMACHINE_DEBUG
- Q_Q(QStateMachine);
- qDebug() << q << ": emitting finished signal for" << forState;
-#endif
-
- QStatePrivate::get(forState)->emitFinished();
-}
-
-void QStateMachinePrivate::startupHook()
-{
-}
-
-namespace _QStateMachine_Internal{
-
-class GoToStateTransition : public QAbstractTransition
-{
- Q_OBJECT
-public:
- GoToStateTransition(QAbstractState *target)
- : QAbstractTransition()
- { setTargetState(target); }
-protected:
- void onTransition(QEvent *) override { deleteLater(); }
- bool eventTest(QEvent *) override { return true; }
-};
-
-} // namespace
-// mingw compiler tries to export QObject::findChild<GoToStateTransition>(),
-// which doesn't work if its in an anonymous namespace.
-using namespace _QStateMachine_Internal;
-/*!
- \internal
-
- Causes this state machine to unconditionally transition to the given
- \a targetState.
-
- Provides a backdoor for using the state machine "imperatively"; i.e. rather
- than defining explicit transitions, you drive the machine's execution by
- calling this function. It breaks the whole integrity of the
- transition-driven model, but is provided for pragmatic reasons.
-*/
-void QStateMachinePrivate::goToState(QAbstractState *targetState)
-{
- if (!targetState) {
- qWarning("QStateMachine::goToState(): cannot go to null state");
- return;
- }
-
- if (configuration.contains(targetState))
- return;
-
- Q_ASSERT(state == Running);
- QState *sourceState = nullptr;
- QSet<QAbstractState*>::const_iterator it;
- for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
- sourceState = toStandardState(*it);
- if (sourceState != nullptr)
- break;
- }
-
- Q_ASSERT(sourceState != nullptr);
- // Reuse previous GoToStateTransition in case of several calls to
- // goToState() in a row.
- GoToStateTransition *trans = sourceState->findChild<GoToStateTransition*>();
- if (!trans) {
- trans = new GoToStateTransition(targetState);
- sourceState->addTransition(trans);
- } else {
- trans->setTargetState(targetState);
- }
-
- processEvents(QueuedProcessing);
-}
-
-void QStateMachinePrivate::registerTransitions(QAbstractState *state)
-{
- QState *group = toStandardState(state);
- if (!group)
- return;
- QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
- for (int i = 0; i < transitions.size(); ++i) {
- QAbstractTransition *t = transitions.at(i);
- registerTransition(t);
- }
-}
-
-void QStateMachinePrivate::maybeRegisterTransition(QAbstractTransition *transition)
-{
- if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
- maybeRegisterSignalTransition(st);
- }
-#if QT_CONFIG(qeventtransition)
- else if (QEventTransition *et = qobject_cast<QEventTransition*>(transition)) {
- maybeRegisterEventTransition(et);
- }
-#endif
-}
-
-void QStateMachinePrivate::registerTransition(QAbstractTransition *transition)
-{
- if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
- registerSignalTransition(st);
- }
-#if QT_CONFIG(qeventtransition)
- else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
- registerEventTransition(oet);
- }
-#endif
-}
-
-void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
-{
- if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
- unregisterSignalTransition(st);
- }
-#if QT_CONFIG(qeventtransition)
- else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
- unregisterEventTransition(oet);
- }
-#endif
-}
-
-void QStateMachinePrivate::maybeRegisterSignalTransition(QSignalTransition *transition)
-{
- Q_Q(QStateMachine);
- if ((state == Running) && (configuration.contains(transition->sourceState())
- || (transition->senderObject() && (transition->senderObject()->thread() != q->thread())))) {
- registerSignalTransition(transition);
- }
-}
-
-void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition)
-{
- Q_Q(QStateMachine);
- if (QSignalTransitionPrivate::get(transition)->signalIndex != -1)
- return; // already registered
- const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
- if (!sender)
- return;
- QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
- if (signal.isEmpty())
- return;
- if (signal.startsWith('0'+QSIGNAL_CODE))
- signal.remove(0, 1);
- const QMetaObject *meta = sender->metaObject();
- int signalIndex = meta->indexOfSignal(signal);
- int originalSignalIndex = signalIndex;
- if (signalIndex == -1) {
- signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal));
- if (signalIndex == -1) {
- qWarning("QSignalTransition: no such signal: %s::%s",
- meta->className(), signal.constData());
- return;
- }
- originalSignalIndex = signalIndex;
- }
- // The signal index we actually want to connect to is the one
- // that is going to be sent, i.e. the non-cloned original index.
- while (meta->method(signalIndex).attributes() & QMetaMethod::Cloned)
- --signalIndex;
-
- connectionsMutex.lock();
- QVector<int> &connectedSignalIndexes = connections[sender];
- if (connectedSignalIndexes.size() <= signalIndex)
- connectedSignalIndexes.resize(signalIndex+1);
- if (connectedSignalIndexes.at(signalIndex) == 0) {
- if (!signalEventGenerator)
- signalEventGenerator = new QSignalEventGenerator(q);
- static const int generatorMethodOffset = QSignalEventGenerator::staticMetaObject.methodOffset();
- bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator, generatorMethodOffset);
- if (!ok) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": FAILED to add signal transition from" << transition->sourceState()
- << ": ( sender =" << sender << ", signal =" << signal
- << ", targets =" << transition->targetStates() << ')';
-#endif
- return;
- }
- }
- ++connectedSignalIndexes[signalIndex];
- connectionsMutex.unlock();
-
- QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex;
- QSignalTransitionPrivate::get(transition)->originalSignalIndex = originalSignalIndex;
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": added signal transition from" << transition->sourceState()
- << ": ( sender =" << sender << ", signal =" << signal
- << ", targets =" << transition->targetStates() << ')';
-#endif
-}
-
-void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transition)
-{
- int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex;
- if (signalIndex == -1)
- return; // not registered
- const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
- QSignalTransitionPrivate::get(transition)->signalIndex = -1;
-
- connectionsMutex.lock();
- QVector<int> &connectedSignalIndexes = connections[sender];
- Q_ASSERT(connectedSignalIndexes.size() > signalIndex);
- Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
- if (--connectedSignalIndexes[signalIndex] == 0) {
- Q_ASSERT(signalEventGenerator != nullptr);
- static const int generatorMethodOffset = QSignalEventGenerator::staticMetaObject.methodOffset();
- QMetaObject::disconnect(sender, signalIndex, signalEventGenerator, generatorMethodOffset);
- int sum = 0;
- for (int i = 0; i < connectedSignalIndexes.size(); ++i)
- sum += connectedSignalIndexes.at(i);
- if (sum == 0)
- connections.remove(sender);
- }
- connectionsMutex.unlock();
-}
-
-void QStateMachinePrivate::unregisterAllTransitions()
-{
- Q_Q(QStateMachine);
- {
- QList<QSignalTransition*> transitions = rootState()->findChildren<QSignalTransition*>();
- for (int i = 0; i < transitions.size(); ++i) {
- QSignalTransition *t = transitions.at(i);
- if (t->machine() == q)
- unregisterSignalTransition(t);
- }
- }
-#if QT_CONFIG(qeventtransition)
- {
- QList<QEventTransition*> transitions = rootState()->findChildren<QEventTransition*>();
- for (int i = 0; i < transitions.size(); ++i) {
- QEventTransition *t = transitions.at(i);
- if (t->machine() == q)
- unregisterEventTransition(t);
- }
- }
-#endif
-}
-
-#if QT_CONFIG(qeventtransition)
-void QStateMachinePrivate::maybeRegisterEventTransition(QEventTransition *transition)
-{
- if ((state == Running) && configuration.contains(transition->sourceState()))
- registerEventTransition(transition);
-}
-
-void QStateMachinePrivate::registerEventTransition(QEventTransition *transition)
-{
- Q_Q(QStateMachine);
- if (QEventTransitionPrivate::get(transition)->registered)
- return;
- if (transition->eventType() >= QEvent::User) {
- qWarning("QObject event transitions are not supported for custom types");
- return;
- }
- QObject *object = QEventTransitionPrivate::get(transition)->object;
- if (!object)
- return;
- QObjectPrivate *od = QObjectPrivate::get(object);
- if (!od->extraData || !od->extraData->eventFilters.contains(q))
- object->installEventFilter(q);
- ++qobjectEvents[object][transition->eventType()];
- QEventTransitionPrivate::get(transition)->registered = true;
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": added event transition from" << transition->sourceState()
- << ": ( object =" << object << ", event =" << transition->eventType()
- << ", targets =" << transition->targetStates() << ')';
-#endif
-}
-
-void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transition)
-{
- Q_Q(QStateMachine);
- if (!QEventTransitionPrivate::get(transition)->registered)
- return;
- QObject *object = QEventTransitionPrivate::get(transition)->object;
- QHash<QEvent::Type, int> &events = qobjectEvents[object];
- Q_ASSERT(events.value(transition->eventType()) > 0);
- if (--events[transition->eventType()] == 0) {
- events.remove(transition->eventType());
- int sum = 0;
- QHash<QEvent::Type, int>::const_iterator it;
- for (it = events.constBegin(); it != events.constEnd(); ++it)
- sum += it.value();
- if (sum == 0) {
- qobjectEvents.remove(object);
- object->removeEventFilter(q);
- }
- }
- QEventTransitionPrivate::get(transition)->registered = false;
-}
-
-void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event)
-{
- if (qobjectEvents.value(watched).contains(event->type())) {
- postInternalEvent(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event)));
- processEvents(DirectProcessing);
- }
-}
-#endif
-
-void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex,
- void **argv)
-{
-#ifndef QT_NO_DEBUG
- connectionsMutex.lock();
- Q_ASSERT(connections[sender].at(signalIndex) != 0);
- connectionsMutex.unlock();
-#endif
- const QMetaObject *meta = sender->metaObject();
- QMetaMethod method = meta->method(signalIndex);
- int argc = method.parameterCount();
- QList<QVariant> vargs;
- vargs.reserve(argc);
- for (int i = 0; i < argc; ++i) {
- int type = method.parameterType(i);
- vargs.append(QVariant(type, argv[i+1]));
- }
-
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ": sending signal event ( sender =" << sender
- << ", signal =" << method.methodSignature().constData() << ')';
-#endif
- postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
- processEvents(DirectProcessing);
-}
-
-/*!
- Constructs a new state machine with the given \a parent.
-*/
-QStateMachine::QStateMachine(QObject *parent)
- : QState(*new QStateMachinePrivate, /*parentState=*/nullptr)
-{
- // Can't pass the parent to the QState constructor, as it expects a QState
- // But this works as expected regardless of whether parent is a QState or not
- setParent(parent);
-}
-
-/*!
- \since 5.0
- \deprecated
-
- Constructs a new state machine with the given \a childMode
- and \a parent.
-
- \warning Do not set the \a childMode to anything else than \l{ExclusiveStates}, otherwise the
- state machine is invalid, and might work incorrectly.
-*/
-QStateMachine::QStateMachine(QState::ChildMode childMode, QObject *parent)
- : QState(*new QStateMachinePrivate, /*parentState=*/nullptr)
-{
- Q_D(QStateMachine);
- d->childMode = childMode;
- setParent(parent); // See comment in constructor above
-
- if (childMode != ExclusiveStates) {
- //### FIXME for Qt6: remove this constructor completely, and hide the childMode property.
- // Yes, the StateMachine itself is conceptually a state, but it should only expose a limited
- // number of properties. The execution algorithm (in the URL below) treats a state machine
- // as a state, but from an API point of view, it's questionable if the QStateMachine should
- // inherit from QState.
- //
- // See function findLCCA in https://www.w3.org/TR/2014/WD-scxml-20140529/#AlgorithmforSCXMLInterpretation
- // to see where setting childMode to parallel will break down.
- qWarning() << "Invalid childMode for QStateMachine" << this;
- }
-}
-
-/*!
- \internal
-*/
-QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
- : QState(dd, /*parentState=*/nullptr)
-{
- setParent(parent);
-}
-
-/*!
- Destroys this state machine.
-*/
-QStateMachine::~QStateMachine()
-{
-}
-
-/*!
- \enum QStateMachine::EventPriority
-
- This enum type specifies the priority of an event posted to the state
- machine using postEvent().
-
- Events of high priority are processed before events of normal priority.
-
- \value NormalPriority The event has normal priority.
- \value HighPriority The event has high priority.
-*/
-
-/*! \enum QStateMachine::Error
-
- This enum type defines errors that can occur in the state machine at run time. When the state
- machine encounters an unrecoverable error at run time, it will set the error code returned
- by error(), the error message returned by errorString(), and enter an error state based on
- the context of the error.
-
- \value NoError No error has occurred.
- \value NoInitialStateError The machine has entered a QState with children which does not have an
- initial state set. The context of this error is the state which is missing an initial
- state.
- \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have
- a default state set. The context of this error is the QHistoryState which is missing a
- default state.
- \value NoCommonAncestorForTransitionError The machine has selected a transition whose source
- and targets are not part of the same tree of states, and thus are not part of the same
- state machine. Commonly, this could mean that one of the states has not been given
- any parent or added to any machine. The context of this error is the source state of
- the transition.
- \value StateMachineChildModeSetToParallelError The machine's \l childMode
- property was set to \l{QState::ParallelStates}. This is illegal.
- Only states may be declared as parallel, not the state machine
- itself. This enum value was added in Qt 5.14.
-
- \sa setErrorState()
-*/
-
-/*!
- Returns the error code of the last error that occurred in the state machine.
-*/
-QStateMachine::Error QStateMachine::error() const
-{
- Q_D(const QStateMachine);
- return d->error;
-}
-
-/*!
- Returns the error string of the last error that occurred in the state machine.
-*/
-QString QStateMachine::errorString() const
-{
- Q_D(const QStateMachine);
- return d->errorString;
-}
-
-/*!
- Clears the error string and error code of the state machine.
-*/
-void QStateMachine::clearError()
-{
- Q_D(QStateMachine);
- d->errorString.clear();
- d->error = NoError;
-}
-
-/*!
- Returns the restore policy of the state machine.
-
- \sa setGlobalRestorePolicy()
-*/
-QState::RestorePolicy QStateMachine::globalRestorePolicy() const
-{
- Q_D(const QStateMachine);
- return d->globalRestorePolicy;
-}
-
-/*!
- Sets the restore policy of the state machine to \a restorePolicy. The default
- restore policy is QState::DontRestoreProperties.
-
- \sa globalRestorePolicy()
-*/
-void QStateMachine::setGlobalRestorePolicy(QState::RestorePolicy restorePolicy)
-{
- Q_D(QStateMachine);
- d->globalRestorePolicy = restorePolicy;
-}
-
-/*!
- Adds the given \a state to this state machine. The state becomes a top-level
- state and the state machine takes ownership of the state.
-
- If the state is already in a different machine, it will first be removed
- from its old machine, and then added to this machine.
-
- \sa removeState(), setInitialState()
-*/
-void QStateMachine::addState(QAbstractState *state)
-{
- if (!state) {
- qWarning("QStateMachine::addState: cannot add null state");
- return;
- }
- if (QAbstractStatePrivate::get(state)->machine() == this) {
- qWarning("QStateMachine::addState: state has already been added to this machine");
- return;
- }
- state->setParent(this);
-}
-
-/*!
- Removes the given \a state from this state machine. The state machine
- releases ownership of the state.
-
- \sa addState()
-*/
-void QStateMachine::removeState(QAbstractState *state)
-{
- if (!state) {
- qWarning("QStateMachine::removeState: cannot remove null state");
- return;
- }
- if (QAbstractStatePrivate::get(state)->machine() != this) {
- qWarning("QStateMachine::removeState: state %p's machine (%p)"
- " is different from this machine (%p)",
- state, QAbstractStatePrivate::get(state)->machine(), this);
- return;
- }
- state->setParent(nullptr);
-}
-
-bool QStateMachine::isRunning() const
-{
- Q_D(const QStateMachine);
- return (d->state == QStateMachinePrivate::Running);
-}
-
-/*!
- Starts this state machine. The machine will reset its configuration and
- transition to the initial state. When a final top-level state (QFinalState)
- is entered, the machine will emit the finished() signal.
-
- \note A state machine will not run without a running event loop, such as
- the main application event loop started with QCoreApplication::exec() or
- QApplication::exec().
-
- \sa started(), finished(), stop(), initialState(), setRunning()
-*/
-void QStateMachine::start()
-{
- Q_D(QStateMachine);
-
- if ((childMode() == QState::ExclusiveStates) && (initialState() == nullptr)) {
- qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
- return;
- }
-
- switch (d->state) {
- case QStateMachinePrivate::NotRunning:
- d->state = QStateMachinePrivate::Starting;
- QMetaObject::invokeMethod(this, "_q_start", Qt::QueuedConnection);
- break;
- case QStateMachinePrivate::Starting:
- break;
- case QStateMachinePrivate::Running:
- qWarning("QStateMachine::start(): already running");
- break;
- }
-}
-
-/*!
- Stops this state machine. The state machine will stop processing events and
- then emit the stopped() signal.
-
- \sa stopped(), start(), setRunning()
-*/
-void QStateMachine::stop()
-{
- Q_D(QStateMachine);
- switch (d->state) {
- case QStateMachinePrivate::NotRunning:
- break;
- case QStateMachinePrivate::Starting:
- // the machine will exit as soon as it enters the event processing loop
- d->stop = true;
- break;
- case QStateMachinePrivate::Running:
- d->stop = true;
- d->processEvents(QStateMachinePrivate::QueuedProcessing);
- break;
- }
-}
-
-void QStateMachine::setRunning(bool running)
-{
- if (running)
- start();
- else
- stop();
-}
-
-/*!
- \threadsafe
-
- Posts the given \a event of the given \a priority for processing by this
- state machine.
-
- This function returns immediately. The event is added to the state machine's
- event queue. Events are processed in the order posted. The state machine
- takes ownership of the event and deletes it once it has been processed.
-
- You can only post events when the state machine is running or when it is starting up.
-
- \sa postDelayedEvent()
-*/
-void QStateMachine::postEvent(QEvent *event, EventPriority priority)
-{
- Q_D(QStateMachine);
- switch (d->state) {
- case QStateMachinePrivate::Running:
- case QStateMachinePrivate::Starting:
- break;
- default:
- qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running");
- return;
- }
- if (!event) {
- qWarning("QStateMachine::postEvent: cannot post null event");
- return;
- }
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << this << ": posting event" << event;
-#endif
- switch (priority) {
- case NormalPriority:
- d->postExternalEvent(event);
- break;
- case HighPriority:
- d->postInternalEvent(event);
- break;
- }
- d->processEvents(QStateMachinePrivate::QueuedProcessing);
-}
-
-/*!
- \threadsafe
-
- Posts the given \a event for processing by this state machine, with the
- given \a delay in milliseconds. Returns an identifier associated with the
- delayed event, or -1 if the event could not be posted.
-
- This function returns immediately. When the delay has expired, the event
- will be added to the state machine's event queue for processing. The state
- machine takes ownership of the event and deletes it once it has been
- processed.
-
- You can only post events when the state machine is running.
-
- \sa cancelDelayedEvent(), postEvent()
-*/
-int QStateMachine::postDelayedEvent(QEvent *event, int delay)
-{
- Q_D(QStateMachine);
- if (d->state != QStateMachinePrivate::Running) {
- qWarning("QStateMachine::postDelayedEvent: cannot post event when the state machine is not running");
- return -1;
- }
- if (!event) {
- qWarning("QStateMachine::postDelayedEvent: cannot post null event");
- return -1;
- }
- if (delay < 0) {
- qWarning("QStateMachine::postDelayedEvent: delay cannot be negative");
- return -1;
- }
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << this << ": posting event" << event << "with delay" << delay;
-#endif
- QMutexLocker locker(&d->delayedEventsMutex);
- int id = d->delayedEventIdFreeList.next();
- bool inMachineThread = (QThread::currentThread() == thread());
- int timerId = inMachineThread ? startTimer(delay) : 0;
- if (inMachineThread && !timerId) {
- qWarning("QStateMachine::postDelayedEvent: failed to start timer with interval %d", delay);
- d->delayedEventIdFreeList.release(id);
- return -1;
- }
- QStateMachinePrivate::DelayedEvent delayedEvent(event, timerId);
- d->delayedEvents.insert(id, delayedEvent);
- if (timerId) {
- d->timerIdToDelayedEventId.insert(timerId, id);
- } else {
- Q_ASSERT(!inMachineThread);
- QMetaObject::invokeMethod(this, "_q_startDelayedEventTimer",
- Qt::QueuedConnection,
- Q_ARG(int, id),
- Q_ARG(int, delay));
- }
- return id;
-}
-
-/*!
- \threadsafe
-
- Cancels the delayed event identified by the given \a id. The id should be a
- value returned by a call to postDelayedEvent(). Returns \c true if the event
- was successfully cancelled, otherwise returns \c false.
-
- \sa postDelayedEvent()
-*/
-bool QStateMachine::cancelDelayedEvent(int id)
-{
- Q_D(QStateMachine);
- if (d->state != QStateMachinePrivate::Running) {
- qWarning("QStateMachine::cancelDelayedEvent: the machine is not running");
- return false;
- }
- QMutexLocker locker(&d->delayedEventsMutex);
- QStateMachinePrivate::DelayedEvent e = d->delayedEvents.take(id);
- if (!e.event)
- return false;
- if (e.timerId) {
- d->timerIdToDelayedEventId.remove(e.timerId);
- bool inMachineThread = (QThread::currentThread() == thread());
- if (inMachineThread) {
- killTimer(e.timerId);
- d->delayedEventIdFreeList.release(id);
- } else {
- QMetaObject::invokeMethod(this, "_q_killDelayedEventTimer",
- Qt::QueuedConnection,
- Q_ARG(int, id),
- Q_ARG(int, e.timerId));
- }
- } else {
- // Cancellation will be detected in pending _q_startDelayedEventTimer() call
- }
- delete e.event;
- return true;
-}
-
-/*!
- Returns the maximal consistent set of states (including parallel and final
- states) that this state machine is currently in. If a state \c s is in the
- configuration, it is always the case that the parent of \c s is also in
- c. Note, however, that the machine itself is not an explicit member of the
- configuration.
-*/
-QSet<QAbstractState*> QStateMachine::configuration() const
-{
- Q_D(const QStateMachine);
- return d->configuration;
-}
-
-/*!
- \fn QStateMachine::started()
-
- This signal is emitted when the state machine has entered its initial state
- (QStateMachine::initialState).
-
- \sa QStateMachine::finished(), QStateMachine::start()
-*/
-
-/*!
- \fn QStateMachine::stopped()
-
- This signal is emitted when the state machine has stopped.
-
- \sa QStateMachine::stop(), QStateMachine::finished()
-*/
-
-/*!
- \reimp
-*/
-bool QStateMachine::event(QEvent *e)
-{
- Q_D(QStateMachine);
- if (e->type() == QEvent::Timer) {
- QTimerEvent *te = static_cast<QTimerEvent*>(e);
- int tid = te->timerId();
- if (d->state != QStateMachinePrivate::Running) {
- // This event has been cancelled already
- QMutexLocker locker(&d->delayedEventsMutex);
- Q_ASSERT(!d->timerIdToDelayedEventId.contains(tid));
- return true;
- }
- d->delayedEventsMutex.lock();
- int id = d->timerIdToDelayedEventId.take(tid);
- QStateMachinePrivate::DelayedEvent ee = d->delayedEvents.take(id);
- if (ee.event != nullptr) {
- Q_ASSERT(ee.timerId == tid);
- killTimer(tid);
- d->delayedEventIdFreeList.release(id);
- d->delayedEventsMutex.unlock();
- d->postExternalEvent(ee.event);
- d->processEvents(QStateMachinePrivate::DirectProcessing);
- return true;
- } else {
- d->delayedEventsMutex.unlock();
- }
- }
- return QState::event(e);
-}
-
-#if QT_CONFIG(qeventtransition)
-/*!
- \reimp
-*/
-bool QStateMachine::eventFilter(QObject *watched, QEvent *event)
-{
- Q_D(QStateMachine);
- d->handleFilteredEvent(watched, event);
- return false;
-}
-#endif
-
-/*!
- \internal
-
- This function is called when the state machine is about to select
- transitions based on the given \a event.
-
- The default implementation does nothing.
-*/
-void QStateMachine::beginSelectTransitions(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \internal
-
- This function is called when the state machine has finished selecting
- transitions based on the given \a event.
-
- The default implementation does nothing.
-*/
-void QStateMachine::endSelectTransitions(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \internal
-
- This function is called when the state machine is about to do a microstep.
-
- The default implementation does nothing.
-*/
-void QStateMachine::beginMicrostep(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \internal
-
- This function is called when the state machine has finished doing a
- microstep.
-
- The default implementation does nothing.
-*/
-void QStateMachine::endMicrostep(QEvent *event)
-{
- Q_UNUSED(event);
-}
-
-/*!
- \reimp
- This function will call start() to start the state machine.
-*/
-void QStateMachine::onEntry(QEvent *event)
-{
- start();
- QState::onEntry(event);
-}
-
-/*!
- \reimp
- This function will call stop() to stop the state machine and
- subsequently emit the stopped() signal.
-*/
-void QStateMachine::onExit(QEvent *event)
-{
- stop();
- QState::onExit(event);
-}
-
-#if QT_CONFIG(animation)
-
-/*!
- Returns whether animations are enabled for this state machine.
-*/
-bool QStateMachine::isAnimated() const
-{
- Q_D(const QStateMachine);
- return d->animated;
-}
-
-/*!
- Sets whether animations are \a enabled for this state machine.
-*/
-void QStateMachine::setAnimated(bool enabled)
-{
- Q_D(QStateMachine);
- d->animated = enabled;
-}
-
-/*!
- Adds a default \a animation to be considered for any transition.
-*/
-void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation)
-{
- Q_D(QStateMachine);
- d->defaultAnimations.append(animation);
-}
-
-/*!
- Returns the list of default animations that will be considered for any transition.
-*/
-QList<QAbstractAnimation*> QStateMachine::defaultAnimations() const
-{
- Q_D(const QStateMachine);
- return d->defaultAnimations;
-}
-
-/*!
- Removes \a animation from the list of default animations.
-*/
-void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation)
-{
- Q_D(QStateMachine);
- d->defaultAnimations.removeAll(animation);
-}
-
-#endif // animation
-
-void QSignalEventGenerator::execute(QMethodRawArguments a)
-{
- auto machinePrivate = QStateMachinePrivate::get(qobject_cast<QStateMachine*>(parent()));
- if (machinePrivate->state != QStateMachinePrivate::Running)
- return;
- int signalIndex = senderSignalIndex();
- Q_ASSERT(signalIndex != -1);
- machinePrivate->handleTransitionSignal(sender(), signalIndex, a.arguments);
-}
-
-QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
- : QObject(parent)
-{
-}
-
-/*!
- \class QStateMachine::SignalEvent
- \inmodule QtCore
-
- \brief The SignalEvent class represents a Qt signal event.
-
- \since 4.6
- \ingroup statemachine
-
- A signal event is generated by a QStateMachine in response to a Qt
- signal. The QSignalTransition class provides a transition associated with a
- signal event. QStateMachine::SignalEvent is part of \l{The State Machine Framework}.
-
- The sender() function returns the object that generated the signal. The
- signalIndex() function returns the index of the signal. The arguments()
- function returns the arguments of the signal.
-
- \sa QSignalTransition
-*/
-
-/*!
- \internal
-
- Constructs a new SignalEvent object with the given \a sender, \a
- signalIndex and \a arguments.
-*/
-QStateMachine::SignalEvent::SignalEvent(QObject *sender, int signalIndex,
- const QList<QVariant> &arguments)
- : QEvent(QEvent::StateMachineSignal), m_sender(sender),
- m_signalIndex(signalIndex), m_arguments(arguments)
-{
-}
-
-/*!
- Destroys this SignalEvent.
-*/
-QStateMachine::SignalEvent::~SignalEvent()
-{
-}
-
-/*!
- \fn QStateMachine::SignalEvent::sender() const
-
- Returns the object that emitted the signal.
-
- \sa QObject::sender()
-*/
-
-/*!
- \fn QStateMachine::SignalEvent::signalIndex() const
-
- Returns the index of the signal.
-
- \sa QMetaObject::indexOfSignal(), QMetaObject::method()
-*/
-
-/*!
- \fn QStateMachine::SignalEvent::arguments() const
-
- Returns the arguments of the signal.
-*/
-
-
-/*!
- \class QStateMachine::WrappedEvent
- \inmodule QtCore
-
- \brief The WrappedEvent class inherits QEvent and holds a clone of an event associated with a QObject.
-
- \since 4.6
- \ingroup statemachine
-
- A wrapped event is generated by a QStateMachine in response to a Qt
- event. The QEventTransition class provides a transition associated with a
- such an event. QStateMachine::WrappedEvent is part of \l{The State Machine
- Framework}.
-
- The object() function returns the object that generated the event. The
- event() function returns a clone of the original event.
-
- \sa QEventTransition
-*/
-
-/*!
- \internal
-
- Constructs a new WrappedEvent object with the given \a object
- and \a event.
-
- The WrappedEvent object takes ownership of \a event.
-*/
-QStateMachine::WrappedEvent::WrappedEvent(QObject *object, QEvent *event)
- : QEvent(QEvent::StateMachineWrapped), m_object(object), m_event(event)
-{
-}
-
-/*!
- Destroys this WrappedEvent.
-*/
-QStateMachine::WrappedEvent::~WrappedEvent()
-{
- delete m_event;
-}
-
-/*!
- \fn QStateMachine::WrappedEvent::object() const
-
- Returns the object that the event is associated with.
-*/
-
-/*!
- \fn QStateMachine::WrappedEvent::event() const
-
- Returns a clone of the original event.
-*/
-
-/*!
- \fn QStateMachine::runningChanged(bool running)
- \since 5.4
-
- This signal is emitted when the running property is changed with \a running as argument.
-
- \sa QStateMachine::running
-*/
-
-/*!
- \fn QStateMachine::postDelayedEvent(QEvent *event, std::chrono::milliseconds delay)
- \since 5.15
- \overload
- \threadsafe
-
- Posts the given \a event for processing by this state machine, with the
- given \a delay in milliseconds. Returns an identifier associated with the
- delayed event, or -1 if the event could not be posted.
-
- This function returns immediately. When the delay has expired, the event
- will be added to the state machine's event queue for processing. The state
- machine takes ownership of the event and deletes it once it has been
- processed.
-
- You can only post events when the state machine is running.
-
- \sa cancelDelayedEvent(), postEvent()
-*/
-
-QT_END_NAMESPACE
-
-#include "qstatemachine.moc"
-#include "moc_qstatemachine.cpp"
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
deleted file mode 100644
index b3c87a959b..0000000000
--- a/src/corelib/statemachine/qstatemachine.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSTATEMACHINE_H
-#define QSTATEMACHINE_H
-
-#include <QtCore/qstate.h>
-
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qset.h>
-#include <QtCore/qvariant.h>
-
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QStateMachinePrivate;
-class QAbstractAnimation;
-class Q_CORE_EXPORT QStateMachine : public QState
-{
- Q_OBJECT
- Q_PROPERTY(QString errorString READ errorString)
- Q_PROPERTY(QState::RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy)
- Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
-#if QT_CONFIG(animation)
- Q_PROPERTY(bool animated READ isAnimated WRITE setAnimated)
-#endif
-public:
- class Q_CORE_EXPORT SignalEvent : public QEvent
- {
- public:
- SignalEvent(QObject *sender, int signalIndex,
- const QList<QVariant> &arguments);
- ~SignalEvent();
-
- inline QObject *sender() const { return m_sender; }
- inline int signalIndex() const { return m_signalIndex; }
- inline QList<QVariant> arguments() const { return m_arguments; }
-
- private:
- QObject *m_sender;
- int m_signalIndex;
- QList<QVariant> m_arguments;
-
- friend class QSignalTransitionPrivate;
- };
-
- class Q_CORE_EXPORT WrappedEvent : public QEvent
- {
- public:
- WrappedEvent(QObject *object, QEvent *event);
- ~WrappedEvent();
-
- inline QObject *object() const { return m_object; }
- inline QEvent *event() const { return m_event; }
-
- private:
- QObject *m_object;
- QEvent *m_event;
- };
-
- enum EventPriority {
- NormalPriority,
- HighPriority
- };
-
- enum Error {
- NoError,
- NoInitialStateError,
- NoDefaultStateInHistoryStateError,
- NoCommonAncestorForTransitionError,
- StateMachineChildModeSetToParallelError
- };
-
- explicit QStateMachine(QObject *parent = nullptr);
- explicit QStateMachine(QState::ChildMode childMode, QObject *parent = nullptr);
- ~QStateMachine();
-
- void addState(QAbstractState *state);
- void removeState(QAbstractState *state);
-
- Error error() const;
- QString errorString() const;
- void clearError();
-
- bool isRunning() const;
-
-#if QT_CONFIG(animation)
- bool isAnimated() const;
- void setAnimated(bool enabled);
-
- void addDefaultAnimation(QAbstractAnimation *animation);
- QList<QAbstractAnimation *> defaultAnimations() const;
- void removeDefaultAnimation(QAbstractAnimation *animation);
-#endif // animation
-
- QState::RestorePolicy globalRestorePolicy() const;
- void setGlobalRestorePolicy(QState::RestorePolicy restorePolicy);
-
- void postEvent(QEvent *event, EventPriority priority = NormalPriority);
- int postDelayedEvent(QEvent *event, int delay);
- bool cancelDelayedEvent(int id);
-
- QSet<QAbstractState*> configuration() const;
-
-#if QT_CONFIG(qeventtransition)
- bool eventFilter(QObject *watched, QEvent *event) override;
-#endif
-
-#if __has_include(<chrono>) || defined(Q_QDOC)
- int postDelayedEvent(QEvent *event, std::chrono::milliseconds delay)
- {
- return postDelayedEvent(event, int(delay.count()));
- }
-#endif
-
-public Q_SLOTS:
- void start();
- void stop();
- void setRunning(bool running);
-
-Q_SIGNALS:
- void started(QPrivateSignal);
- void stopped(QPrivateSignal);
- void runningChanged(bool running);
-
-
-protected:
- void onEntry(QEvent *event) override;
- void onExit(QEvent *event) override;
-
- virtual void beginSelectTransitions(QEvent *event);
- virtual void endSelectTransitions(QEvent *event);
-
- virtual void beginMicrostep(QEvent *event);
- virtual void endMicrostep(QEvent *event);
-
- bool event(QEvent *e) override;
-
-protected:
- QStateMachine(QStateMachinePrivate &dd, QObject *parent);
-
-private:
- Q_DISABLE_COPY(QStateMachine)
- Q_DECLARE_PRIVATE(QStateMachine)
- Q_PRIVATE_SLOT(d_func(), void _q_start())
- Q_PRIVATE_SLOT(d_func(), void _q_process())
-#if QT_CONFIG(animation)
- Q_PRIVATE_SLOT(d_func(), void _q_animationFinished())
-#endif
- Q_PRIVATE_SLOT(d_func(), void _q_startDelayedEventTimer(int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_killDelayedEventTimer(int, int))
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
deleted file mode 100644
index 7018926bd3..0000000000
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSTATEMACHINE_P_H
-#define QSTATEMACHINE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "private/qstate_p.h"
-
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qpair.h>
-#include <QtCore/qpointer.h>
-#include <QtCore/qset.h>
-#include <QtCore/qvector.h>
-#include <private/qfreelist_p.h>
-
-QT_REQUIRE_CONFIG(statemachine);
-
-QT_BEGIN_NAMESPACE
-
-class QEvent;
-#if QT_CONFIG(qeventtransition)
-class QEventTransition;
-#endif
-class QSignalEventGenerator;
-class QSignalTransition;
-class QAbstractState;
-class QAbstractTransition;
-class QFinalState;
-class QHistoryState;
-class QState;
-
-#if QT_CONFIG(animation)
-class QAbstractAnimation;
-#endif
-
-struct CalculationCache;
-class QStateMachine;
-class Q_CORE_EXPORT QStateMachinePrivate : public QStatePrivate
-{
- Q_DECLARE_PUBLIC(QStateMachine)
-public:
- enum State {
- NotRunning,
- Starting,
- Running
- };
- enum EventProcessingMode {
- DirectProcessing,
- QueuedProcessing
- };
- enum StopProcessingReason {
- EventQueueEmpty,
- Finished,
- Stopped
- };
-
- QStateMachinePrivate();
- ~QStateMachinePrivate();
-
- static QStateMachinePrivate *get(QStateMachine *q)
- { return q ? q->d_func() : nullptr; }
-
- QState *findLCA(const QList<QAbstractState*> &states, bool onlyCompound = false);
- QState *findLCCA(const QList<QAbstractState*> &states);
-
- static bool transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2);
- static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2);
- static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2);
-
- QAbstractState *findErrorState(QAbstractState *context);
- void setError(QStateMachine::Error error, QAbstractState *currentContext);
-
- // private slots
- void _q_start();
- void _q_process();
-#if QT_CONFIG(animation)
- void _q_animationFinished();
-#endif
- void _q_startDelayedEventTimer(int id, int delay);
- void _q_killDelayedEventTimer(int id, int timerId);
-
- QState *rootState() const;
-
- void clearHistory();
- QAbstractTransition *createInitialTransition() const;
-
- void removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
- void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList, CalculationCache *cache);
- QList<QAbstractTransition *> selectTransitions(QEvent *event, CalculationCache *cache);
- virtual void noMicrostep();
- virtual void processedPendingEvents(bool didChange);
- virtual void beginMacrostep();
- virtual void endMacrostep(bool didChange);
- virtual void exitInterpreter();
- virtual void exitStates(QEvent *event, const QList<QAbstractState *> &statesToExit_sorted,
- const QHash<QAbstractState*, QVector<QPropertyAssignment> > &assignmentsForEnteredStates);
- QList<QAbstractState*> computeExitSet(const QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
- QSet<QAbstractState*> computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
- QSet<QAbstractState*> computeExitSet_Unordered(QAbstractTransition *t, CalculationCache *cache);
- void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList);
- virtual void enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted,
- const QList<QAbstractState*> &statesToEnter_sorted,
- const QSet<QAbstractState*> &statesForDefaultEntry,
- QHash<QAbstractState *, QVector<QPropertyAssignment> > &propertyAssignmentsForState
-#if QT_CONFIG(animation)
- , const QList<QAbstractAnimation*> &selectedAnimations
-#endif
- );
- QList<QAbstractState*> computeEntrySet(const QList<QAbstractTransition*> &enabledTransitions,
- QSet<QAbstractState*> &statesForDefaultEntry, CalculationCache *cache);
- QAbstractState *getTransitionDomain(QAbstractTransition *t,
- const QList<QAbstractState *> &effectiveTargetStates,
- CalculationCache *cache);
- void addDescendantStatesToEnter(QAbstractState *state,
- QSet<QAbstractState*> &statesToEnter,
- QSet<QAbstractState*> &statesForDefaultEntry);
- void addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor,
- QSet<QAbstractState*> &statesToEnter,
- QSet<QAbstractState*> &statesForDefaultEntry);
-
- static QState *toStandardState(QAbstractState *state);
- static const QState *toStandardState(const QAbstractState *state);
- static QFinalState *toFinalState(QAbstractState *state);
- static QHistoryState *toHistoryState(QAbstractState *state);
-
- bool isInFinalState(QAbstractState *s) const;
- static bool isFinal(const QAbstractState *s);
- static bool isParallel(const QAbstractState *s);
- bool isCompound(const QAbstractState *s) const;
- bool isAtomic(const QAbstractState *s) const;
-
- void goToState(QAbstractState *targetState);
-
- void registerTransitions(QAbstractState *state);
- void maybeRegisterTransition(QAbstractTransition *transition);
- void registerTransition(QAbstractTransition *transition);
- void maybeRegisterSignalTransition(QSignalTransition *transition);
- void registerSignalTransition(QSignalTransition *transition);
- void unregisterSignalTransition(QSignalTransition *transition);
- void registerMultiThreadedSignalTransitions();
-#if QT_CONFIG(qeventtransition)
- void maybeRegisterEventTransition(QEventTransition *transition);
- void registerEventTransition(QEventTransition *transition);
- void unregisterEventTransition(QEventTransition *transition);
- void handleFilteredEvent(QObject *watched, QEvent *event);
-#endif
- void unregisterTransition(QAbstractTransition *transition);
- void unregisterAllTransitions();
- void handleTransitionSignal(QObject *sender, int signalIndex,
- void **args);
-
- void postInternalEvent(QEvent *e);
- void postExternalEvent(QEvent *e);
- QEvent *dequeueInternalEvent();
- QEvent *dequeueExternalEvent();
- bool isInternalEventQueueEmpty();
- bool isExternalEventQueueEmpty();
- void processEvents(EventProcessingMode processingMode);
- void cancelAllDelayedEvents();
-
- virtual void emitStateFinished(QState *forState, QFinalState *guiltyState);
- virtual void startupHook();
-
-#ifndef QT_NO_PROPERTIES
- class RestorableId {
- QPointer<QObject> guard;
- QObject *obj;
- QByteArray prop;
- friend size_t qHash(const RestorableId &key, size_t seed)
- noexcept(noexcept(qHash(std::declval<QByteArray>())))
- { return qHash(qMakePair(key.obj, key.prop), seed); }
- friend bool operator==(const RestorableId &lhs, const RestorableId &rhs) noexcept
- { return lhs.obj == rhs.obj && lhs.prop == rhs.prop; }
- friend bool operator!=(const RestorableId &lhs, const RestorableId &rhs) noexcept
- { return !operator==(lhs, rhs); }
- public:
- explicit RestorableId(QObject *o, QByteArray p) noexcept : guard(o), obj(o), prop(std::move(p)) {}
- QObject *object() const noexcept { return guard; }
- QByteArray propertyName() const noexcept { return prop; }
- };
- QHash<QAbstractState*, QHash<RestorableId, QVariant> > registeredRestorablesForState;
- bool hasRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName) const;
- QVariant savedValueForRestorable(const QList<QAbstractState*> &exitedStates_sorted,
- QObject *object, const QByteArray &propertyName) const;
- void registerRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName,
- const QVariant &value);
- void unregisterRestorables(const QList<QAbstractState*> &states, QObject *object,
- const QByteArray &propertyName);
- QVector<QPropertyAssignment> restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const;
- QHash<RestorableId, QVariant> computePendingRestorables(const QList<QAbstractState*> &statesToExit_sorted) const;
- QHash<QAbstractState*, QVector<QPropertyAssignment> > computePropertyAssignments(
- const QList<QAbstractState*> &statesToEnter_sorted,
- QHash<RestorableId, QVariant> &pendingRestorables) const;
-#endif
-
- State state;
- bool processing;
- bool processingScheduled;
- bool stop;
- StopProcessingReason stopProcessingReason;
- QSet<QAbstractState*> configuration;
- QList<QEvent*> internalEventQueue;
- QList<QEvent*> externalEventQueue;
- QMutex internalEventMutex;
- QMutex externalEventMutex;
-
- QStateMachine::Error error;
- QState::RestorePolicy globalRestorePolicy;
-
- QString errorString;
- QSet<QAbstractState *> pendingErrorStates;
- QSet<QAbstractState *> pendingErrorStatesForDefaultEntry;
-
-#if QT_CONFIG(animation)
- bool animated;
-
- struct InitializeAnimationResult {
- QList<QAbstractAnimation*> handledAnimations;
- QList<QAbstractAnimation*> localResetEndValues;
-
- void swap(InitializeAnimationResult &other) noexcept
- {
- qSwap(handledAnimations, other.handledAnimations);
- qSwap(localResetEndValues, other.localResetEndValues);
- }
- };
-
- InitializeAnimationResult
- initializeAnimation(QAbstractAnimation *abstractAnimation,
- const QPropertyAssignment &prop);
-
- QHash<QAbstractState*, QList<QAbstractAnimation*> > animationsForState;
- QHash<QAbstractAnimation*, QPropertyAssignment> propertyForAnimation;
- QHash<QAbstractAnimation*, QAbstractState*> stateForAnimation;
- QSet<QAbstractAnimation*> resetAnimationEndValues;
-
- QList<QAbstractAnimation *> defaultAnimations;
- QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForSource;
- QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForTarget;
-
- QList<QAbstractAnimation *> selectAnimations(const QList<QAbstractTransition *> &transitionList) const;
- void terminateActiveAnimations(QAbstractState *state,
- const QHash<QAbstractState*, QVector<QPropertyAssignment> > &assignmentsForEnteredStates);
- void initializeAnimations(QAbstractState *state, const QList<QAbstractAnimation*> &selectedAnimations,
- const QList<QAbstractState *> &exitedStates_sorted,
- QHash<QAbstractState *, QVector<QPropertyAssignment> > &assignmentsForEnteredStates);
-#endif // animation
-
- QSignalEventGenerator *signalEventGenerator;
-
- QHash<const QObject*, QVector<int> > connections;
- QMutex connectionsMutex;
-#if QT_CONFIG(qeventtransition)
- QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents;
-#endif
- QFreeList<void> delayedEventIdFreeList;
- struct DelayedEvent {
- QEvent *event;
- int timerId;
- DelayedEvent(QEvent *e, int tid)
- : event(e), timerId(tid) {}
- DelayedEvent()
- : event(nullptr), timerId(0) {}
- };
- QHash<int, DelayedEvent> delayedEvents;
- QHash<int, int> timerIdToDelayedEventId;
- QMutex delayedEventsMutex;
-
- typedef QEvent* (*f_cloneEvent)(QEvent*);
- struct Handler {
- f_cloneEvent cloneEvent;
- };
-
- static const Handler *handler;
-};
-#if QT_CONFIG(animation)
-Q_DECLARE_SHARED(QStateMachinePrivate::InitializeAnimationResult)
-#endif
-
-Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler();
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri
deleted file mode 100644
index ee701ebc37..0000000000
--- a/src/corelib/statemachine/statemachine.pri
+++ /dev/null
@@ -1,33 +0,0 @@
-!qtConfig(statemachine): return()
-
-HEADERS += $$PWD/qstatemachine.h \
- $$PWD/qstatemachine_p.h \
- $$PWD/qsignaleventgenerator_p.h \
- $$PWD/qabstractstate.h \
- $$PWD/qabstractstate_p.h \
- $$PWD/qstate.h \
- $$PWD/qstate_p.h \
- $$PWD/qfinalstate.h \
- $$PWD/qfinalstate_p.h \
- $$PWD/qhistorystate.h \
- $$PWD/qhistorystate_p.h \
- $$PWD/qabstracttransition.h \
- $$PWD/qabstracttransition_p.h \
- $$PWD/qsignaltransition.h \
- $$PWD/qsignaltransition_p.h
-
-SOURCES += $$PWD/qstatemachine.cpp \
- $$PWD/qabstractstate.cpp \
- $$PWD/qstate.cpp \
- $$PWD/qfinalstate.cpp \
- $$PWD/qhistorystate.cpp \
- $$PWD/qabstracttransition.cpp \
- $$PWD/qsignaltransition.cpp
-
-qtConfig(qeventtransition) {
- HEADERS += \
- $$PWD/qeventtransition.h \
- $$PWD/qeventtransition_p.h
- SOURCES += \
- $$PWD/qeventtransition.cpp
-}
diff --git a/src/corelib/text/UNICODE_LICENSE.txt b/src/corelib/text/UNICODE_LICENSE.txt
deleted file mode 100644
index 567fda24dd..0000000000
--- a/src/corelib/text/UNICODE_LICENSE.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
-
-See Terms of Use for definitions of Unicode Inc.'s
-Data Files and Software.
-
-NOTICE TO USER: Carefully read the following legal agreement.
-BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
-DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
-YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
-TERMS AND CONDITIONS OF THIS AGREEMENT.
-IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
-THE DATA FILES OR SOFTWARE.
-
-COPYRIGHT AND PERMISSION NOTICE
-
-Copyright © 1991-2019 Unicode, Inc. All rights reserved.
-Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Unicode data files and any associated documentation
-(the "Data Files") or Unicode software and any associated documentation
-(the "Software") to deal in the Data Files or Software
-without restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, and/or sell copies of
-the Data Files or Software, and to permit persons to whom the Data Files
-or Software are furnished to do so, provided that either
-(a) this copyright and permission notice appear with all copies
-of the Data Files or Software, or
-(b) this copyright and permission notice appear in associated
-Documentation.
-
-THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
-NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
-DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THE DATA FILES OR SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder
-shall not be used in advertising or otherwise to promote the sale,
-use or other dealings in these Data Files or Software without prior
-written authorization of the copyright holder.
diff --git a/src/corelib/text/qanystringview.cpp b/src/corelib/text/qanystringview.cpp
new file mode 100644
index 0000000000..4129257c02
--- /dev/null
+++ b/src/corelib/text/qanystringview.cpp
@@ -0,0 +1,660 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qanystringview.h"
+#include "qdebug.h"
+#include "qttypetraits.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAnyStringView
+ \inmodule QtCore
+ \since 6.0
+ \brief The QAnyStringView class provides a unified view on Latin-1, UTF-8,
+ or UTF-16 strings with a read-only subset of the QString API.
+ \reentrant
+ \ingroup tools
+ \ingroup string-processing
+
+ \compares strong
+ \compareswith strong char16_t QChar {const char16_t *} {const char *} \
+ QByteArray QByteArrayView QString QStringView QUtf8StringView \
+ QLatin1StringView
+ \endcompareswith
+
+ A QAnyStringView references a contiguous portion of a string it does
+ not own. It acts as an interface type to all kinds of strings,
+ without the need to construct a QString first.
+
+ Unlike QStringView and QUtf8StringView, QAnyStringView can hold
+ strings of any of the following encodings: UTF-8, UTF-16, and
+ Latin-1. The latter is supported because Latin-1, unlike UTF-8,
+ can be efficiently compared to UTF-16 data: a length mismatch
+ already means the strings cannot be equal. This is not true for
+ UTF-8/UTF-16 comparisons, because UTF-8 is a variable-length
+ encoding.
+
+ The string may be represented as an array (or an array-compatible
+ data-structure such as QString, std::basic_string, etc.) of \c
+ char, \c char8_t, QChar, \c ushort, \c char16_t or (on platforms,
+ such as Windows, where it is a 16-bit type) \c wchar_t.
+
+ QAnyStringView is designed as an interface type; its main use-case
+ is as a function parameter type. When QAnyStringViews are used as
+ automatic variables or data members, care must be taken to ensure
+ that the referenced string data (for example, owned by a QString)
+ outlives the QAnyStringView on all code paths, lest the string
+ view ends up referencing deleted data.
+
+ When used as an interface type, QAnyStringView allows a single
+ function to accept a wide variety of string data sources. One
+ function accepting QAnyStringView thus replaces five function
+ overloads (taking QString, \c{(const QChar*, qsizetype)},
+ QUtf8StringView, QLatin1StringView (but see above), and QChar), while
+ at the same time enabling even more string data sources to be
+ passed to the function, such as \c{u8"Hello World"}, a \c char8_t
+ string literal.
+
+ Like elsewhere in Qt, QAnyStringView assumes \c char data is encoded
+ in UTF-8, unless it is presented as a QLatin1StringView.
+
+ Since Qt 6.4, however, UTF-8 string literals that are pure US-ASCII are
+ automatically stored as Latin-1. This is a compile-time check with no
+ runtime overhead. The feature requires compiling in C++20, or with a recent
+ GCC.
+
+ QAnyStringViews should be passed by value, not by reference-to-const:
+ \snippet code/src_corelib_text_qanystringview.cpp 0
+
+ QAnyStringView can also be used as the return value of a function,
+ but this is not recommended. QUtf8StringView or QStringView are
+ better suited as function return values. If you call a function
+ returning QAnyStringView, take extra care to not keep the
+ QAnyStringView around longer than the function promises to keep
+ the referenced string data alive. If in doubt, obtain a strong
+ reference to the data by calling toString() to convert the
+ QAnyStringView into a QString.
+
+ QAnyStringView is a \e{Literal Type}.
+
+ \section2 Compatible Character Types
+
+ QAnyStringView accepts strings over a variety of character types:
+
+ \list
+ \li \c char (both signed and unsigned)
+ \li \c char8_t (C++20 only)
+ \li \c char16_t
+ \li \c wchar_t (where it's a 16-bit type, e.g. Windows)
+ \li \c ushort
+ \li \c QChar
+ \endlist
+
+ The 8-bit character types are interpreted as UTF-8 data (except when
+ presented as a QLatin1StringView) while the 16-bit character types are
+ interpreted as UTF-16 data in host byte order (the same as QString).
+
+ \section2 Sizes and Sub-Strings
+
+ All sizes and positions in QAnyStringView functions are in the
+ encoding's code units (that is, UTF-16 surrogate pairs count as
+ two for the purposes of these functions, the same as in QString,
+ and UTF-8 multibyte sequences count as two, three or four,
+ depending on their length).
+
+ \sa QUtf8StringView, QStringView
+*/
+
+/*!
+ \typedef QAnyStringView::difference_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QAnyStringView::size_type
+
+ Alias for qsizetype. Provided for compatibility with the STL.
+*/
+
+/*!
+ \fn QAnyStringView::QAnyStringView()
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QAnyStringView::QAnyStringView(std::nullptr_t)
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn template <typename Char, QAnyStringView::if_compatible_char<Char> = true> QAnyStringView::QAnyStringView(const Char *str, qsizetype len)
+
+ Constructs a string view on \a str with length \a len.
+
+ The range \c{[str,len)} must remain valid for the lifetime of this string view object.
+
+ Passing \nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
+
+ The behavior is undefined if \a len is negative or, when positive, if \a str is \nullptr.
+
+ This constructor only participates in overload resolution if \c Char is a compatible
+ character type.
+
+ \sa isNull(), {Compatible Character Types}
+*/
+
+/*!
+ \fn template <typename Char, QAnyStringView::if_compatible_char<Char> = true> QAnyStringView::QAnyStringView(const Char *first, const Char *last)
+
+ Constructs a string view on \a first with length (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this string view object.
+
+ Passing \nullptr as \a first is safe if \a last is \nullptr, too,
+ and results in a null string view.
+
+ The behavior is undefined if \a last precedes \a first, or \a first
+ is \nullptr and \a last is not.
+
+ This constructor only participates in overload resolution if \c Char
+ is a compatible character type.
+
+ \sa isNull(), {Compatible Character Types}
+*/
+
+/*!
+ \fn template <typename Char> QAnyStringView::QAnyStringView(const Char *str)
+
+ Constructs a string view on \a str. The length is determined
+ by scanning for the first \c{Char(0)}.
+
+ \a str must remain valid for the lifetime of this string view object.
+
+ Passing \nullptr as \a str is safe and results in a null string view.
+
+ This constructor only participates in overload resolution if \a
+ str is not an array and if \c Char is a compatible character
+ type.
+
+ \sa isNull(), {Compatible Character Types}
+*/
+
+/*!
+ \fn template <typename Char, size_t N> QAnyStringView::QAnyStringView(const Char (&string)[N])
+
+ Constructs a string view on the character string literal \a string.
+ The view covers the array until the first \c{Char(0)} is encountered,
+ or \c N, whichever comes first.
+ If you need the full array, use fromArray() instead.
+
+ \a string must remain valid for the lifetime of this string view
+ object.
+
+ This constructor only participates in overload resolution if \a
+ string is an actual array and \c Char is a compatible character
+ type.
+
+ \sa {Compatible Character Types}
+*/
+
+/*!
+ \fn QAnyStringView::QAnyStringView(const QString &str)
+
+ Constructs a string view on \a str.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ The string view will be null if and only if \c{str.isNull()}.
+*/
+
+/*!
+ \fn QAnyStringView::QAnyStringView(const QByteArray &str)
+
+ Constructs a string view on \a str. The data in \a str is interpreted as UTF-8.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ The string view will be null if and only if \c{str.isNull()}.
+*/
+
+/*!
+ \fn template <typename Container, QAnyStringView::if_compatible_container<Container>> QAnyStringView::QAnyStringView(const Container &str)
+
+ Constructs a string view on \a str. The length is taken from \c{std::size(str)}.
+
+ \c{std::data(str)} must remain valid for the lifetime of this string view object.
+
+ This constructor only participates in overload resolution if \c Container is a
+ container with a compatible character type as \c{value_type}.
+
+ The string view will be empty if and only if \c{std::size(str) == 0}. It is unspecified
+ whether this constructor can result in a null string view (\c{std::data(str)} would
+ have to return \nullptr for this).
+
+ \sa isNull(), isEmpty()
+*/
+
+/*!
+ \fn template <typename Char, size_t Size> static QAnyStringView fromArray(const Char (&string)[Size]) noexcept
+
+ Constructs a string view on the full character string literal \a string,
+ including any trailing \c{Char(0)}. If you don't want the
+ null-terminator included in the view then you can use the constructor
+ overload taking a pointer and a size:
+
+ \snippet code/src_corelib_text_qanystringview.cpp 2
+
+ Alternatively you can use the constructor overload taking an
+ array literal which will create a view up to, but not including,
+ the first null-terminator in the data.
+
+ \a string must remain valid for the lifetime of this string view
+ object.
+
+ This function will work with any array literal if \c Char is a
+ compatible character type.
+*/
+
+/*!
+ \fn QString QAnyStringView::toString() const
+
+ Returns a deep copy of this string view's data as a QString.
+
+ The return value will be a null QString if and only if this string view is null.
+*/
+
+/*!
+ \fn const void *QAnyStringView::data() const
+
+ Returns a const pointer to the first character in the string view.
+
+ \note The character array represented by the return value is \e not null-terminated.
+
+ \sa size_bytes()
+*/
+
+/*!
+ \fn bool QAnyStringView::empty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn bool QAnyStringView::isEmpty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa empty(), isNull(), size()
+*/
+
+/*!
+ \fn bool QAnyStringView::isNull() const
+
+ Returns whether this string view is null - that is, whether \c{data() == nullptr}.
+
+ This functions is provided for compatibility with other Qt containers.
+
+ \sa empty(), isEmpty(), size()
+*/
+
+/*!
+ \fn qsizetype QAnyStringView::size() const
+
+ Returns the size of this string view, in the encoding's code points.
+
+ \sa empty(), isEmpty(), isNull(), size_bytes(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::size_bytes() const
+
+ Returns the size of this string view, but in bytes, not code-points.
+
+ You can use this function together with data() for hashing or serialization.
+
+ This function is provided for STL compatibility.
+
+ \sa size(), data()
+*/
+
+/*!
+ \fn QAnyStringView::length() const
+
+ Same as size().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa size()
+*/
+
+/*!
+ \fn QChar QAnyStringView::front() const
+
+ Returns the first character in the string view.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa back(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QChar QAnyStringView::back() const
+
+ Returns the last character in the string view.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa front(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::mid(qsizetype pos, qsizetype n) const
+ \since 6.5
+
+ Returns the substring of length \a n starting at position
+ \a pos in this object.
+
+ \deprecated Use sliced() instead in new code.
+
+ Returns an empty string view if \a n exceeds the
+ length of the string view. If there are less than \a n code points
+ available in the string view starting at \a pos, or if
+ \a n is negative (default), the function returns all code points that
+ are available from \a pos.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::left(qsizetype n) const
+ \since 6.5
+
+ \deprecated Use first() instead in new code.
+
+ Returns the substring of length \a n starting at position
+ 0 in this object.
+
+ The entire string view is returned if \a n is greater than or equal
+ to size(), or less than zero.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::right(qsizetype n) const
+ \since 6.5
+
+ \deprecated Use last() instead in new code.
+
+ Returns the substring of length \a n starting at position
+ size() - \a n in this object.
+
+ The entire string view is returned if \a n is greater than or equal
+ to size(), or less than zero.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::first(qsizetype n) const
+ \since 6.5
+
+ Returns a string view that contains the first \a n code points
+ of this string view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa last(), sliced(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::last(qsizetype n) const
+ \since 6.5
+
+ Returns a string view that contains the last \a n code points of this string view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa first(), sliced(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::sliced(qsizetype pos, qsizetype n) const
+ \since 6.5
+
+ Returns a string view containing \a n code points of this string view,
+ starting at position \a pos.
+
+//! [UB-sliced-index-length]
+ \note The behavior is undefined when \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+//! [UB-sliced-index-length]
+
+ \sa first(), last(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::sliced(qsizetype pos) const
+ \since 6.5
+
+ Returns a string view starting at position \a pos in this object,
+ and extending to its end.
+
+//! [UB-sliced-index-only]
+ \note The behavior is undefined when \a pos < 0 or \a pos > size().
+//! [UB-sliced-index-only]
+
+ \sa first(), last(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::chopped(qsizetype n) const
+ \since 6.5
+
+ Returns the substring of length size() - \a n starting at the
+ beginning of this object.
+
+ Same as \c{first(size() - n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa sliced(), first(), last(), chop(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::truncate(qsizetype n)
+ \since 6.5
+
+ Truncates this string view to \a n code points.
+
+ Same as \c{*this = first(n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa sliced(), first(), last(), chopped(), chop(), {Sizes and Sub-Strings}
+*/
+
+/*!
+ \fn QAnyStringView::chop(qsizetype n)
+ \since 6.5
+
+ Truncates this string view by \a n code points.
+
+ Same as \c{*this = first(size() - n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa sliced(), first(), last(), chopped(), truncate(), {Sizes and Sub-Strings}
+*/
+
+/*! \fn template <typename Visitor> decltype(auto) QAnyStringView::visit(Visitor &&v) const
+
+ Calls \a v with either a QUtf8StringView, QLatin1String, or QStringView, depending
+ on the encoding of the string data this string-view references.
+
+ This is how most functions taking QAnyStringView fork off into per-encoding
+ functions:
+
+ \code
+ void processImpl(QLatin1String s) { ~~~ }
+ void processImpl(QUtf8StringView s) { ~~~ }
+ void processImpl(QStringView s) { ~~~ }
+
+ void process(QAnyStringView s)
+ {
+ s.visit([](auto s) { processImpl(s); });
+ }
+ \endcode
+
+ Here, we're reusing the same name, \c s, for both the QAnyStringView
+ object, as well as the lambda's parameter. This is idiomatic code and helps
+ track the identity of the objects through visit() calls, for example in more
+ complex situations such as
+
+ \code
+ bool equal(QAnyStringView lhs, QAnyStringView rhs)
+ {
+ // assuming operator==(QAnyStringView, QAnyStringView) didn't, yet, exist:
+ return lhs.visit([rhs](auto lhs) {
+ rhs.visit([lhs](auto rhs) {
+ return lhs == rhs;
+ });
+ });
+ }
+ \endcode
+
+ visit() requires that all lambda instantiations have the same return type.
+ If they differ, you get a compile error, even if there is a common type. To
+ fix, you can use explicit return types on the lambda, or cast in the return
+ statements:
+
+ \code
+ // wrong:
+ QAnyStringView firstHalf(QAnyStringView input)
+ {
+ return input.visit([](auto input) { // ERROR: lambdas return different types
+ return input.sliced(0, input.size() / 2);
+ });
+ }
+ // correct:
+ QAnyStringView firstHalf(QAnyStringView input)
+ {
+ return input.visit([](auto input) -> QAnyStringView { // OK, explicit return type
+ return input.sliced(0, input.size() / 2);
+ });
+ }
+ // also correct:
+ QAnyStringView firstHalf(QAnyStringView input)
+ {
+ return input.visit([](auto input) {
+ return QAnyStringView(input.sliced(0, input.size() / 2)); // OK, cast to common type
+ });
+ }
+ \endcode
+*/
+
+/*!
+ \fn QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs)
+
+ Compares the string view \a lhs with the string view \a rhs and returns a
+ negative integer if \a lhs is less than \a rhs, a positive integer if it is
+ greater than \a rhs, and zero if they are equal.
+
+ If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
+ otherwise the comparison is case-insensitive.
+
+ \sa operator==(), operator<(), operator>()
+*/
+
+/*!
+ \fn bool QAnyStringView::operator==(const QAnyStringView &lhs, const QAnyStringView & rhs)
+ \fn bool QAnyStringView::operator!=(const QAnyStringView & lhs, const QAnyStringView & rhs)
+ \fn bool QAnyStringView::operator<=(const QAnyStringView & lhs, const QAnyStringView & rhs)
+ \fn bool QAnyStringView::operator>=(const QAnyStringView & lhs, const QAnyStringView & rhs)
+ \fn bool QAnyStringView::operator<(const QAnyStringView & lhs, const QAnyStringView & rhs)
+ \fn bool QAnyStringView::operator>(const QAnyStringView & lhs, const QAnyStringView & rhs)
+
+ Operators that compare \a lhs to \a rhs.
+
+ \sa compare()
+*/
+
+/*!
+ \fn template <typename QStringLike> qToAnyStringViewIgnoringNull(const QStringLike &s);
+ \since 6.0
+ \internal
+
+ Convert \a s to a QAnyStringView ignoring \c{s.isNull()}.
+
+ Returns a string view that references \a{s}'s data, but is never null.
+
+ This is a faster way to convert a QString or QByteArray to a QAnyStringView,
+ if null QStrings or QByteArrays can legitimately be treated as empty ones.
+
+ \sa QString::isNull(), QAnyStringView
+*/
+
+/*!
+ \fn QAnyStringView::operator<<(QDebug d, QAnyStringView s)
+ \since 6.7
+ \relates QDebug
+
+ Outputs \a s to debug stream \a d.
+
+ If \c{d.quotedString()} is \c true, indicates which encoding the string is
+ in. If you just want the string data, use visit() like this:
+
+ \code
+ s.visit([&d) (auto s) { d << s; });
+ \endcode
+
+ \sa QAnyStringView::visit()
+*/
+QDebug operator<<(QDebug d, QAnyStringView s)
+{
+ struct S { const char *prefix, *suffix; };
+ const auto affixes = s.visit([](auto s) {
+ using View = decltype(s);
+ if constexpr (std::is_same_v<View, QLatin1StringView>) {
+ return S{"", "_L1"};
+ } else if constexpr (std::is_same_v<View, QUtf8StringView>) {
+ return S{"u8", ""};
+ } else if constexpr (std::is_same_v<View, QStringView>) {
+ return S{"u", ""};
+ } else {
+ static_assert(QtPrivate::type_dependent_false<View>());
+ }
+ });
+ const QDebugStateSaver saver(d);
+ d.nospace();
+ if (d.quoteStrings())
+ d << affixes.prefix;
+ s.visit([&d](auto s) { d << s; });
+ if (d.quoteStrings())
+ d << affixes.suffix;
+ return d;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/text/qanystringview.h b/src/corelib/text/qanystringview.h
new file mode 100644
index 0000000000..01efd83743
--- /dev/null
+++ b/src/corelib/text/qanystringview.h
@@ -0,0 +1,351 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QANYSTRINGVIEW_H
+#define QANYSTRINGVIEW_H
+
+#include <QtCore/qcompare.h>
+#include <QtCore/qlatin1stringview.h>
+#include <QtCore/qstringview.h>
+#include <QtCore/qutf8stringview.h>
+
+#ifdef __cpp_impl_three_way_comparison
+#include <compare>
+#endif
+#include <QtCore/q20type_traits.h>
+#include <limits>
+
+class tst_QAnyStringView;
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+template <typename Tag, typename Result>
+struct wrapped { using type = Result; };
+
+template <typename Tag, typename Result>
+using wrapped_t = typename wrapped<Tag, Result>::type;
+
+} // namespace QtPrivate
+
+class QAnyStringView
+{
+public:
+ typedef qptrdiff difference_type;
+ typedef qsizetype size_type;
+private:
+ static constexpr size_t SizeMask = (std::numeric_limits<size_t>::max)() / 4;
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+ static constexpr int SizeShift = 2;
+ static constexpr size_t Latin1Flag = 1;
+#else
+ static constexpr int SizeShift = 0;
+ static constexpr size_t Latin1Flag = SizeMask + 1;
+#endif
+ static constexpr size_t TwoByteCodePointFlag = Latin1Flag << 1;
+ static constexpr size_t TypeMask = ~(SizeMask << SizeShift);
+ static_assert(TypeMask == (Latin1Flag|TwoByteCodePointFlag));
+
+ // Tag bits
+ // 0 0 Utf8
+ // 0 1 Latin1
+ // 1 0 Utf16
+ // 1 1 Unused
+ // ^ ^ latin1
+ // | sizeof code-point == 2
+ enum Tag : size_t {
+ Utf8 = 0,
+ Latin1 = Latin1Flag,
+ Utf16 = TwoByteCodePointFlag,
+ Unused = TypeMask,
+ };
+
+ template <typename Char>
+ using if_compatible_char = std::enable_if_t<std::disjunction_v<
+ QtPrivate::IsCompatibleCharType<Char>,
+ QtPrivate::IsCompatibleChar8Type<Char>
+ >, bool>;
+
+ template <typename Pointer>
+ using if_compatible_pointer = std::enable_if_t<std::disjunction_v<
+ QtPrivate::IsCompatiblePointer<Pointer>,
+ QtPrivate::IsCompatiblePointer8<Pointer>
+ >, bool>;
+
+
+ template <typename T>
+ using if_compatible_container = std::enable_if_t<std::disjunction_v<
+ QtPrivate::IsContainerCompatibleWithQStringView<T>,
+ QtPrivate::IsContainerCompatibleWithQUtf8StringView<T>
+ >, bool>;
+
+ template <typename QStringOrQByteArray, typename T>
+ using if_convertible_to = std::enable_if_t<std::conjunction_v<
+ // need to exclude a bunch of stuff, because we take by universal reference:
+ std::negation<std::disjunction<
+ std::is_same<q20::remove_cvref_t<T>, QAnyStringView::Tag>,
+ std::is_same<q20::remove_cvref_t<T>, QAnyStringView>, // don't make a copy/move ctor
+ std::is_pointer<std::decay_t<T>>, // const char*, etc
+ std::is_same<q20::remove_cvref_t<T>, QByteArray>,
+ std::is_same<q20::remove_cvref_t<T>, QString>
+ >>,
+ // this is what we're really after:
+ std::is_convertible<T, QStringOrQByteArray>
+ >, bool>;
+
+ // confirm we don't make an accidental copy constructor:
+ static_assert(QtPrivate::IsContainerCompatibleWithQStringView<QAnyStringView>::value == false);
+ static_assert(QtPrivate::IsContainerCompatibleWithQUtf8StringView<QAnyStringView>::value == false);
+
+ template<typename Char>
+ static constexpr bool isAsciiOnlyCharsAtCompileTime(Char *str, qsizetype sz) noexcept
+ {
+ // do not perform check if not at compile time
+ if (!q20::is_constant_evaluated())
+ return false;
+ if constexpr (sizeof(Char) != sizeof(char)) {
+ Q_UNUSED(str);
+ Q_UNUSED(sz);
+ return false;
+ } else {
+ for (qsizetype i = 0; i < sz; ++i) {
+ if (uchar(str[i]) > 0x7f)
+ return false;
+ }
+ return true;
+ }
+ }
+
+ template<typename Char>
+ static constexpr std::size_t encodeType(const Char *str, qsizetype sz) noexcept
+ {
+ // Utf16 if 16 bit, Latin1 if ASCII, else Utf8
+ Q_ASSERT(sz >= 0);
+ Q_ASSERT(sz <= qsizetype(SizeMask));
+ Q_ASSERT(str || !sz);
+ return (std::size_t(sz) << SizeShift)
+ | uint(sizeof(Char) == sizeof(char16_t)) * Tag::Utf16
+ | uint(isAsciiOnlyCharsAtCompileTime(str, sz)) * Tag::Latin1;
+ }
+
+ template <typename Char>
+ static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
+ {
+ if (q20::is_constant_evaluated())
+ return qsizetype(std::char_traits<Char>::length(str));
+ if constexpr (sizeof(Char) == sizeof(char16_t))
+ return QtPrivate::qustrlen(reinterpret_cast<const char16_t*>(str));
+ else
+ return qsizetype(strlen(reinterpret_cast<const char*>(str)));
+ }
+
+ static QChar toQChar(char ch) noexcept { return toQChar(QLatin1Char{ch}); } // we don't handle UTF-8 multibytes
+ static QChar toQChar(QChar ch) noexcept { return ch; }
+ static QChar toQChar(QLatin1Char ch) noexcept { return ch; }
+
+ explicit constexpr QAnyStringView(const void *d, qsizetype n, std::size_t sizeAndType) noexcept
+ : m_data{d}, m_size{std::size_t(n) | (sizeAndType & TypeMask)} {}
+public:
+ constexpr QAnyStringView() noexcept
+ : m_data{nullptr}, m_size{0} {}
+ constexpr QAnyStringView(std::nullptr_t) noexcept
+ : QAnyStringView() {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ constexpr QAnyStringView(const Char *str, qsizetype len)
+ : m_data{str}, m_size{encodeType<Char>(str, len)}
+ {
+ }
+
+ template <typename Char, if_compatible_char<Char> = true>
+ constexpr QAnyStringView(const Char *f, const Char *l)
+ : QAnyStringView(f, l - f) {}
+
+#ifdef Q_QDOC
+ template <typename Char, size_t N>
+ constexpr QAnyStringView(const Char (&array)[N]) noexcept;
+
+ template <typename Char>
+ constexpr QAnyStringView(const Char *str) noexcept;
+#else
+
+ template <typename Pointer, if_compatible_pointer<Pointer> = true>
+ constexpr QAnyStringView(const Pointer &str) noexcept
+ : QAnyStringView{str, str ? lengthHelperPointer(str) : 0} {}
+#endif
+
+ // defined in qstring.h
+ inline QAnyStringView(const QByteArray &str) noexcept; // TODO: Should we have this at all? Remove?
+ inline QAnyStringView(const QString &str) noexcept;
+ inline constexpr QAnyStringView(QLatin1StringView str) noexcept;
+
+ template <typename Container, if_compatible_container<Container> = true>
+ constexpr Q_ALWAYS_INLINE QAnyStringView(const Container &c) noexcept
+ : QAnyStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {}
+
+ template <typename Container, if_convertible_to<QString, Container> = true>
+ constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QString> &&capacity = {})
+ //noexcept(std::is_nothrow_constructible_v<QString, Container>)
+ : QAnyStringView(capacity = std::forward<Container>(c)) {}
+
+ template <typename Container, if_convertible_to<QByteArray, Container> = true>
+ constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QByteArray> &&capacity = {})
+ //noexcept(std::is_nothrow_constructible_v<QByteArray, Container>)
+ : QAnyStringView(capacity = std::forward<Container>(c)) {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ constexpr QAnyStringView(const Char &c) noexcept
+ : QAnyStringView{&c, 1} {}
+ constexpr QAnyStringView(const QChar &c) noexcept
+ : QAnyStringView{&c, 1} {}
+
+ template <typename Char, typename Container = decltype(QChar::fromUcs4(U'x')),
+ std::enable_if_t<std::is_same_v<Char, char32_t>, bool> = true>
+ constexpr QAnyStringView(Char c, Container &&capacity = {})
+ : QAnyStringView(capacity = QChar::fromUcs4(c)) {}
+
+ constexpr QAnyStringView(QStringView v) noexcept
+ : QAnyStringView(std::data(v), QtPrivate::lengthHelperContainer(v)) {}
+
+ template <bool UseChar8T>
+ constexpr QAnyStringView(QBasicUtf8StringView<UseChar8T> v) noexcept
+ : QAnyStringView(std::data(v), QtPrivate::lengthHelperContainer(v)) {}
+
+ template <typename Char, size_t Size, if_compatible_char<Char> = true>
+ [[nodiscard]] constexpr static QAnyStringView fromArray(const Char (&string)[Size]) noexcept
+ { return QAnyStringView(string, Size); }
+
+ // defined in qstring.h:
+ template <typename Visitor>
+ inline constexpr decltype(auto) visit(Visitor &&v) const;
+
+ [[nodiscard]]
+ constexpr QAnyStringView mid(qsizetype pos, qsizetype n = -1) const
+ {
+ using namespace QtPrivate;
+ auto result = QContainerImplHelper::mid(size(), &pos, &n);
+ return result == QContainerImplHelper::Null ? QAnyStringView() : sliced(pos, n);
+ }
+ [[nodiscard]]
+ constexpr QAnyStringView left(qsizetype n) const
+ {
+ if (size_t(n) >= size_t(size()))
+ n = size();
+ return sliced(0, n);
+ }
+ [[nodiscard]]
+ constexpr QAnyStringView right(qsizetype n) const
+ {
+ if (size_t(n) >= size_t(size()))
+ n = size();
+ return sliced(size() - n, n);
+ }
+
+ [[nodiscard]] constexpr QAnyStringView sliced(qsizetype pos) const
+ { verify(pos, 0); auto r = *this; r.advanceData(pos); r.setSize(size() - pos); return r; }
+ [[nodiscard]] constexpr QAnyStringView sliced(qsizetype pos, qsizetype n) const
+ { verify(pos, n); auto r = *this; r.advanceData(pos); r.setSize(n); return r; }
+ [[nodiscard]] constexpr QAnyStringView first(qsizetype n) const
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] constexpr QAnyStringView last(qsizetype n) const
+ { verify(0, n); return sliced(size() - n, n); }
+ [[nodiscard]] constexpr QAnyStringView chopped(qsizetype n) const
+ { verify(0, n); return sliced(0, size() - n); }
+
+ constexpr void truncate(qsizetype n)
+ { verify(0, n); setSize(n); }
+ constexpr void chop(qsizetype n)
+ { verify(0, n); setSize(size() - n); }
+
+
+ [[nodiscard]] inline QString toString() const; // defined in qstring.h
+
+ [[nodiscard]] constexpr qsizetype size() const noexcept
+ { return qsizetype((m_size >> SizeShift) & SizeMask); }
+ [[nodiscard]] constexpr const void *data() const noexcept { return m_data; }
+
+ [[nodiscard]] Q_CORE_EXPORT static int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+ [[nodiscard]] Q_CORE_EXPORT static bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept;
+
+ static constexpr inline bool detects_US_ASCII_at_compile_time =
+#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
+ true
+#else
+ false
+#endif
+ ;
+
+ //
+ // STL compatibility API:
+ //
+ [[nodiscard]] constexpr QChar front() const; // NOT noexcept!
+ [[nodiscard]] constexpr QChar back() const; // NOT noexcept!
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+ [[nodiscard]] constexpr qsizetype size_bytes() const noexcept
+ { return size() * charSize(); }
+
+ //
+ // Qt compatibility API:
+ //
+ [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
+ [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
+ [[nodiscard]] constexpr qsizetype length() const noexcept
+ { return size(); }
+
+private:
+ friend bool comparesEqual(const QAnyStringView &lhs, const QAnyStringView &rhs) noexcept
+ { return QAnyStringView::equal(lhs, rhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QAnyStringView &lhs, const QAnyStringView &rhs) noexcept
+ {
+ const int res = QAnyStringView::compare(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QAnyStringView)
+
+#ifndef QT_NO_DEBUG_STREAM
+ Q_CORE_EXPORT friend QDebug operator<<(QDebug d, QAnyStringView s);
+#endif
+
+ [[nodiscard]] constexpr Tag tag() const noexcept { return Tag{m_size & TypeMask}; }
+ [[nodiscard]] constexpr bool isUtf16() const noexcept { return tag() == Tag::Utf16; }
+ [[nodiscard]] constexpr bool isUtf8() const noexcept { return tag() == Tag::Utf8; }
+ [[nodiscard]] constexpr bool isLatin1() const noexcept { return tag() == Tag::Latin1; }
+ [[nodiscard]] constexpr QStringView asStringView() const
+ { return Q_ASSERT(isUtf16()), QStringView{m_data_utf16, size()}; }
+ [[nodiscard]] constexpr q_no_char8_t::QUtf8StringView asUtf8StringView() const
+ { return Q_ASSERT(isUtf8()), q_no_char8_t::QUtf8StringView{m_data_utf8, size()}; }
+ [[nodiscard]] inline constexpr QLatin1StringView asLatin1StringView() const;
+ [[nodiscard]] constexpr size_t charSize() const noexcept { return isUtf16() ? 2 : 1; }
+ constexpr void setSize(qsizetype sz) noexcept { m_size = size_t(sz) | tag(); }
+ constexpr void advanceData(qsizetype delta) noexcept
+ { m_data_utf8 += delta * charSize(); }
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+ union {
+ const void *m_data;
+ const char *m_data_utf8;
+ const char16_t *m_data_utf16;
+ };
+ size_t m_size;
+ friend class ::tst_QAnyStringView;
+};
+Q_DECLARE_TYPEINFO(QAnyStringView, Q_PRIMITIVE_TYPE);
+
+template <typename QStringLike, std::enable_if_t<std::disjunction_v<
+ std::is_same<QStringLike, QString>,
+ std::is_same<QStringLike, QByteArray>
+ >, bool> = true>
+[[nodiscard]] inline QAnyStringView qToAnyStringViewIgnoringNull(const QStringLike &s) noexcept
+{ return QAnyStringView(s.begin(), s.size()); }
+
+QT_END_NAMESPACE
+
+#endif /* QANYSTRINGVIEW_H */
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 77f4110601..e6387e4bed 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbytearray.h"
#include "qbytearraymatcher.h"
@@ -50,23 +14,37 @@
#include "private/qsimd_p.h"
#include "qstringalgorithms_p.h"
#include "qscopedpointer.h"
-#include "qbytearray_p.h"
+#include "qstringconverter_p.h"
#include <qdatastream.h>
#include <qmath.h>
+#if defined(Q_OS_WASM)
+#include "private/qstdweb_p.h"
+#endif
#ifndef QT_NO_COMPRESS
#include <zconf.h>
#include <zlib.h>
+#include <qxpfunctional.h>
#endif
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
-#define IS_RAW_DATA(d) ((d)->flags() & QArrayData::RawDataType)
+#include <algorithm>
+
+#ifdef Q_OS_WIN
+# if !defined(QT_BOOTSTRAPPED) && (defined(QT_NO_CAST_FROM_ASCII) || defined(QT_NO_CAST_FROM_BYTEARRAY))
+// MSVC requires this, but let's apply it to MinGW compilers too, just in case
+# error "This file cannot be compiled with QT_NO_CAST_{TO,FROM}_ASCII, " \
+ "otherwise some QByteArray functions will not get exported."
+# endif
+#endif
QT_BEGIN_NAMESPACE
+Q_CONSTINIT const char QByteArray::_empty = '\0';
+
// ASCII case system, used by QByteArray::to{Upper,Lower}() and qstr(n)icmp():
static constexpr inline uchar asciiUpper(uchar c)
{
@@ -125,7 +103,7 @@ char *qstrcpy(char *dst, const char *src)
if (!src)
return nullptr;
#ifdef Q_CC_MSVC
- const int len = int(strlen(src));
+ const size_t len = strlen(src);
// This is actually not secure!!! It will be fixed
// properly in a later release!
if (len >= 0 && strcpy_s(dst, len+1, src) == 0)
@@ -141,34 +119,33 @@ char *qstrcpy(char *dst, const char *src)
A safe \c strncpy() function.
Copies at most \a len bytes from \a src (stopping at \a len or the
- terminating '\\0' whichever comes first) into \a dst and returns a
- pointer to \a dst. Guarantees that \a dst is '\\0'-terminated. If
- \a src or \a dst is \nullptr, returns \nullptr immediately.
+ terminating '\\0' whichever comes first) into \a dst. Guarantees that \a
+ dst is '\\0'-terminated, except when \a dst is \nullptr or \a len is 0. If
+ \a src is \nullptr, returns \nullptr, otherwise returns \a dst.
This function assumes that \a dst is at least \a len characters
long.
\note If \a dst and \a src overlap, the behavior is undefined.
+ \note Unlike strncpy(), this function does \e not write '\\0' to all \a
+ len bytes of \a dst, but stops after the terminating '\\0'. In this sense,
+ it's similar to C11's strncpy_s().
+
\sa qstrcpy()
*/
-char *qstrncpy(char *dst, const char *src, uint len)
+char *qstrncpy(char *dst, const char *src, size_t len)
{
- if (!src || !dst)
- return nullptr;
- if (len > 0) {
-#ifdef Q_CC_MSVC
- strncpy_s(dst, len, src, len - 1);
-#else
- strncpy(dst, src, len);
-#endif
- dst[len-1] = '\0';
+ if (dst && len > 0) {
+ *dst = '\0';
+ if (src)
+ std::strncat(dst, src, len - 1);
}
- return dst;
+ return src ? dst : nullptr;
}
-/*! \fn uint qstrlen(const char *str)
+/*! \fn size_t qstrlen(const char *str)
\relates QByteArray
A safe \c strlen() function.
@@ -179,7 +156,7 @@ char *qstrncpy(char *dst, const char *src, uint len)
\sa qstrnlen()
*/
-/*! \fn uint qstrnlen(const char *str, uint maxlen)
+/*! \fn size_t qstrnlen(const char *str, size_t maxlen)
\relates QByteArray
\since 4.2
@@ -204,7 +181,8 @@ char *qstrncpy(char *dst, const char *src, uint len)
\nullptr, it is treated as less than the other (even if the other is an
empty string).
- \sa qstrncmp(), qstricmp(), qstrnicmp(), {Character Case}, QByteArray::compare()
+ \sa qstrncmp(), qstricmp(), qstrnicmp(), {Character Case},
+ QByteArray::compare()
*/
int qstrcmp(const char *str1, const char *str2)
{
@@ -212,7 +190,7 @@ int qstrcmp(const char *str1, const char *str2)
: (str1 ? 1 : (str2 ? -1 : 0));
}
-/*! \fn int qstrncmp(const char *str1, const char *str2, uint len);
+/*! \fn int qstrncmp(const char *str1, const char *str2, size_t len);
\relates QByteArray
@@ -228,7 +206,8 @@ int qstrcmp(const char *str1, const char *str2)
\nullptr, it is treated as less than the other (even if the other is an
empty string or \a len is 0).
- \sa qstrcmp(), qstricmp(), qstrnicmp(), {Character Case}, QByteArray::compare()
+ \sa qstrcmp(), qstricmp(), qstrnicmp(), {Character Case},
+ QByteArray::compare()
*/
/*! \relates QByteArray
@@ -246,7 +225,8 @@ int qstrcmp(const char *str1, const char *str2)
\nullptr, it is treated as less than the other (even if the other is an
empty string).
- \sa qstrcmp(), qstrncmp(), qstrnicmp(), {Character Case}, QByteArray::compare()
+ \sa qstrcmp(), qstrncmp(), qstrnicmp(), {Character Case},
+ QByteArray::compare()
*/
int qstricmp(const char *str1, const char *str2)
@@ -264,7 +244,7 @@ int qstricmp(const char *str1, const char *str2)
max += offset;
do {
uchar c = s1[offset];
- if (int res = asciiLower(c) - asciiLower(s2[offset]))
+ if (int res = QtMiscUtils::caseCompareAscii(c, s2[offset]))
return res;
if (!c)
return 0;
@@ -282,7 +262,7 @@ int qstricmp(const char *str1, const char *str2)
// very quick.
quintptr u1 = quintptr(s1 + offset);
quintptr u2 = quintptr(s2 + offset);
- uint n = PageSize - ((u1 | u2) & PageMask);
+ size_t n = PageSize - ((u1 | u2) & PageMask);
qptrdiff maxoffset = offset + n;
for ( ; offset + 16 <= maxoffset; offset += sizeof(__m128i)) {
@@ -290,7 +270,7 @@ int qstricmp(const char *str1, const char *str2)
__m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s1 + offset));
__m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s2 + offset));
- // compare the two against each oher
+ // compare the two against each other
__m128i cmp = _mm_cmpeq_epi8(a, b);
// find NUL terminators too
@@ -303,7 +283,7 @@ int qstricmp(const char *str1, const char *str2)
// yes, find out where
uint start = qCountTrailingZeroBits(mask);
uint end = sizeof(mask) * 8 - qCountLeadingZeroBits(mask);
- Q_ASSUME(end >= start);
+ Q_ASSERT(end >= start);
offset += start;
n = end - start;
break;
@@ -335,10 +315,11 @@ int qstricmp(const char *str1, const char *str2)
\nullptr, it is treated as less than the other (even if the other is an
empty string or \a len is 0).
- \sa qstrcmp(), qstrncmp(), qstricmp(), {Character Case}, QByteArray::compare()
+ \sa qstrcmp(), qstrncmp(), qstricmp(), {Character Case},
+ QByteArray::compare()
*/
-int qstrnicmp(const char *str1, const char *str2, uint len)
+int qstrnicmp(const char *str1, const char *str2, size_t len)
{
const uchar *s1 = reinterpret_cast<const uchar *>(str1);
const uchar *s2 = reinterpret_cast<const uchar *>(str2);
@@ -346,7 +327,7 @@ int qstrnicmp(const char *str1, const char *str2, uint len)
return s1 ? 1 : (s2 ? -1 : 0);
for (; len--; ++s1, ++s2) {
const uchar c = *s1;
- if (int res = asciiLower(c) - asciiLower(*s2))
+ if (int res = QtMiscUtils::caseCompareAscii(c, *s2))
return res;
if (!c) // strings are equal
break;
@@ -364,11 +345,18 @@ int qstrnicmp(const char *str1, const char *str2, uint len)
*/
int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2)
{
- Q_ASSERT(str1);
Q_ASSERT(len1 >= 0);
Q_ASSERT(len2 >= -1);
const uchar *s1 = reinterpret_cast<const uchar *>(str1);
const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ if (!s1 || !len1) {
+ if (len2 == 0)
+ return 0;
+ if (len2 == -1)
+ return (!s2 || !*s2) ? 0 : -1;
+ Q_ASSERT(s2);
+ return -1;
+ }
if (!s2)
return len1 == 0 ? 0 : 1;
@@ -380,7 +368,7 @@ int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2
if (!c)
return 1;
- if (int res = asciiLower(s1[i]) - asciiLower(c))
+ if (int res = QtMiscUtils::caseCompareAscii(s1[i], c))
return res;
}
return s2[i] ? -1 : 0;
@@ -388,7 +376,7 @@ int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2
// not null-terminated
const qsizetype len = qMin(len1, len2);
for (qsizetype i = 0; i < len; ++i) {
- if (int res = asciiLower(s1[i]) - asciiLower(s2[i]))
+ if (int res = QtMiscUtils::caseCompareAscii(s1[i], s2[i]))
return res;
}
if (len1 == len2)
@@ -399,47 +387,26 @@ int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2
/*!
\internal
- ### Qt6: replace the QByteArray parameter with [pointer,len] pair
*/
-int qstrcmp(const QByteArray &str1, const char *str2)
+int QtPrivate::compareMemory(QByteArrayView lhs, QByteArrayView rhs)
{
- if (!str2)
- return str1.isEmpty() ? 0 : +1;
-
- const char *str1data = str1.constData();
- const char *str1end = str1data + str1.length();
- for ( ; str1data < str1end && *str2; ++str1data, ++str2) {
- int diff = int(uchar(*str1data)) - uchar(*str2);
- if (diff)
- // found a difference
- return diff;
+ if (!lhs.isNull() && !rhs.isNull()) {
+ int ret = memcmp(lhs.data(), rhs.data(), qMin(lhs.size(), rhs.size()));
+ if (ret != 0)
+ return ret;
}
- // Why did we stop?
- if (*str2 != '\0')
- // not the null, so we stopped because str1 is shorter
- return -1;
- if (str1data < str1end)
- // we haven't reached the end, so str1 must be longer
- return +1;
- return 0;
+ // they matched qMin(l1, l2) bytes
+ // so the longer one is lexically after the shorter one
+ return lhs.size() == rhs.size() ? 0 : lhs.size() > rhs.size() ? 1 : -1;
}
/*!
\internal
- ### Qt6: replace the QByteArray parameter with [pointer,len] pair
- */
-int qstrcmp(const QByteArray &str1, const QByteArray &str2)
+*/
+bool QtPrivate::isValidUtf8(QByteArrayView s) noexcept
{
- int l1 = str1.length();
- int l2 = str2.length();
- int ret = memcmp(str1.constData(), str2.constData(), qMin(l1, l2));
- if (ret != 0)
- return ret;
-
- // they matched qMin(l1, l2) bytes
- // so the longer one is lexically after the shorter one
- return l1 - l2;
+ return QUtf8::isValidUtf8(s).isValidUtf8;
}
// the CRC table below is created by the following piece of code
@@ -490,7 +457,7 @@ static const quint16 crc_tbl[16] = {
\relates QByteArray
\since 5.9
- Returns the CRC-16 checksum of the first \a len bytes of \a data.
+ Returns the CRC-16 checksum of \a data.
The checksum is independent of the byte order (endianness) and will
be calculated accorded to the algorithm published in \a standard.
@@ -499,7 +466,7 @@ static const quint16 crc_tbl[16] = {
\note This function is a 16-bit cache conserving (16 entry table)
implementation of the CRC-16-CCITT algorithm.
*/
-quint16 qChecksum(const char *data, uint len, Qt::ChecksumType standard)
+quint16 qChecksum(QByteArrayView data, Qt::ChecksumType standard)
{
quint16 crc = 0x0000;
switch (standard) {
@@ -511,7 +478,8 @@ quint16 qChecksum(const char *data, uint len, Qt::ChecksumType standard)
break;
}
uchar c;
- const uchar *p = reinterpret_cast<const uchar *>(data);
+ const uchar *p = reinterpret_cast<const uchar *>(data.data());
+ qsizetype len = data.size();
while (len--) {
c = *p++;
crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
@@ -545,10 +513,12 @@ quint16 qChecksum(const char *data, uint len, Qt::ChecksumType standard)
The default value is -1, which specifies zlib's default
compression.
- \sa qUncompress()
+ \sa qUncompress(const QByteArray &data)
*/
-/*! \relates QByteArray
+/*!
+ \fn QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
+ \relates QByteArray
\overload
@@ -557,44 +527,196 @@ quint16 qChecksum(const char *data, uint len, Qt::ChecksumType standard)
*/
#ifndef QT_NO_COMPRESS
-QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
+using CompressSizeHint_t = quint32; // 32-bit BE, historically
+
+enum class ZLibOp : bool { Compression, Decompression };
+
+Q_DECL_COLD_FUNCTION
+static const char *zlibOpAsString(ZLibOp op)
{
- if (nbytes == 0) {
- return QByteArray(4, '\0');
+ switch (op) {
+ case ZLibOp::Compression: return "qCompress";
+ case ZLibOp::Decompression: return "qUncompress";
}
- if (!data) {
- qWarning("qCompress: Data is null");
- return QByteArray();
+ Q_UNREACHABLE_RETURN(nullptr);
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray zlibError(ZLibOp op, const char *what)
+{
+ qWarning("%s: %s", zlibOpAsString(op), what);
+ return QByteArray();
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray dataIsNull(ZLibOp op)
+{
+ return zlibError(op, "Data is null");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray lengthIsNegative(ZLibOp op)
+{
+ return zlibError(op, "Input length is negative");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray tooMuchData(ZLibOp op)
+{
+ return zlibError(op, "Not enough memory");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray invalidCompressedData()
+{
+ return zlibError(ZLibOp::Decompression, "Input data is corrupted");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray unexpectedZlibError(ZLibOp op, int err, const char *msg)
+{
+ qWarning("%s unexpected zlib error: %s (%d)",
+ zlibOpAsString(op),
+ msg ? msg : "",
+ err);
+ return QByteArray();
+}
+
+static QByteArray xxflate(ZLibOp op, QArrayDataPointer<char> out, QByteArrayView input,
+ qxp::function_ref<int(z_stream *) const> init,
+ qxp::function_ref<int(z_stream *, size_t) const> processChunk,
+ qxp::function_ref<void(z_stream *) const> deinit)
+{
+ if (out.data() == nullptr) // allocation failed
+ return tooMuchData(op);
+ qsizetype capacity = out.allocatedCapacity();
+
+ const auto initalSize = out.size;
+
+ z_stream zs = {};
+ zs.next_in = reinterpret_cast<uchar *>(const_cast<char *>(input.data())); // 1980s C API...
+ if (const int err = init(&zs); err != Z_OK)
+ return unexpectedZlibError(op, err, zs.msg);
+ const auto sg = qScopeGuard([&] { deinit(&zs); });
+
+ using ZlibChunkSize_t = decltype(zs.avail_in);
+ static_assert(!std::is_signed_v<ZlibChunkSize_t>);
+ static_assert(std::is_same_v<ZlibChunkSize_t, decltype(zs.avail_out)>);
+ constexpr auto MaxChunkSize = std::numeric_limits<ZlibChunkSize_t>::max();
+ [[maybe_unused]]
+ constexpr auto MaxStatisticsSize = std::numeric_limits<decltype(zs.total_out)>::max();
+
+ size_t inputLeft = size_t(input.size());
+
+ int res;
+ do {
+ Q_ASSERT(out.freeSpaceAtBegin() == 0); // ensure prepend optimization stays out of the way
+ Q_ASSERT(capacity == out.allocatedCapacity());
+
+ if (zs.avail_out == 0) {
+ Q_ASSERT(size_t(out.size) - initalSize > MaxStatisticsSize || // total_out overflow
+ size_t(out.size) - initalSize == zs.total_out);
+ Q_ASSERT(out.size <= capacity);
+
+ qsizetype avail_out = capacity - out.size;
+ if (avail_out == 0) {
+ out->reallocateAndGrow(QArrayData::GrowsAtEnd, 1); // grow to next natural capacity
+ if (out.data() == nullptr) // reallocation failed
+ return tooMuchData(op);
+ capacity = out.allocatedCapacity();
+ avail_out = capacity - out.size;
+ }
+ zs.next_out = reinterpret_cast<uchar *>(out.data()) + out.size;
+ zs.avail_out = size_t(avail_out) > size_t(MaxChunkSize) ? MaxChunkSize
+ : ZlibChunkSize_t(avail_out);
+ out.size += zs.avail_out;
+
+ Q_ASSERT(zs.avail_out > 0);
+ }
+
+ if (zs.avail_in == 0) {
+ // zs.next_in is kept up-to-date by processChunk(), so nothing to do
+ zs.avail_in = inputLeft > MaxChunkSize ? MaxChunkSize : ZlibChunkSize_t(inputLeft);
+ inputLeft -= zs.avail_in;
+ }
+
+ res = processChunk(&zs, inputLeft);
+ } while (res == Z_OK);
+
+ switch (res) {
+ case Z_STREAM_END:
+ out.size -= zs.avail_out;
+ Q_ASSERT(size_t(out.size) - initalSize > MaxStatisticsSize || // total_out overflow
+ size_t(out.size) - initalSize == zs.total_out);
+ Q_ASSERT(out.size <= out.allocatedCapacity());
+ out.data()[out.size] = '\0';
+ return QByteArray(std::move(out));
+
+ case Z_MEM_ERROR:
+ return tooMuchData(op);
+
+ case Z_BUF_ERROR:
+ Q_UNREACHABLE(); // cannot happen - we supply a buffer that can hold the result,
+ // or else error out early
+
+ case Z_DATA_ERROR: // can only happen on decompression
+ Q_ASSERT(op == ZLibOp::Decompression);
+ return invalidCompressedData();
+
+ default:
+ return unexpectedZlibError(op, res, zs.msg);
+ }
+}
+
+QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
+{
+ constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t);
+ if (nbytes == 0) {
+ return QByteArray(HeaderSize, '\0');
}
+ if (!data)
+ return dataIsNull(ZLibOp::Compression);
+
+ if (nbytes < 0)
+ return lengthIsNegative(ZLibOp::Compression);
+
if (compressionLevel < -1 || compressionLevel > 9)
compressionLevel = -1;
- ulong len = nbytes + nbytes / 100 + 13;
- QByteArray bazip;
- int res;
- do {
- bazip.resize(len + 4);
- res = ::compress2((uchar*)bazip.data()+4, &len, data, nbytes, compressionLevel);
-
- switch (res) {
- case Z_OK:
- bazip.resize(len + 4);
- bazip[0] = (nbytes & 0xff000000) >> 24;
- bazip[1] = (nbytes & 0x00ff0000) >> 16;
- bazip[2] = (nbytes & 0x0000ff00) >> 8;
- bazip[3] = (nbytes & 0x000000ff);
- break;
- case Z_MEM_ERROR:
- qWarning("qCompress: Z_MEM_ERROR: Not enough memory");
- bazip.resize(0);
- break;
- case Z_BUF_ERROR:
- len *= 2;
- break;
+ QArrayDataPointer out = [&] {
+ constexpr qsizetype SingleAllocLimit = 256 * 1024; // the maximum size for which we use
+ // zlib's compressBound() to guarantee
+ // the output buffer size is sufficient
+ // to hold result
+ qsizetype capacity = HeaderSize;
+ if (nbytes < SingleAllocLimit) {
+ // use maximum size
+ capacity += compressBound(uLong(nbytes)); // cannot overflow (both times)!
+ return QArrayDataPointer<char>(capacity);
}
- } while (res == Z_BUF_ERROR);
- return bazip;
+ // for larger buffers, assume it compresses optimally, and
+ // grow geometrically from there:
+ constexpr qsizetype MaxCompressionFactor = 1024; // max theoretical factor is 1032
+ // cf. http://www.zlib.org/zlib_tech.html,
+ // but use a nearby power-of-two (faster)
+ capacity += std::max(qsizetype(compressBound(uLong(SingleAllocLimit))),
+ nbytes / MaxCompressionFactor);
+ return QArrayDataPointer<char>(capacity, 0, QArrayData::Grow);
+ }();
+
+ if (out.data() == nullptr) // allocation failed
+ return tooMuchData(ZLibOp::Compression);
+
+ qToBigEndian(qt_saturate<CompressSizeHint_t>(nbytes), out.data());
+ out.size = HeaderSize;
+
+ return xxflate(ZLibOp::Compression, std::move(out), {data, nbytes},
+ [=] (z_stream *zs) { return deflateInit(zs, compressionLevel); },
+ [] (z_stream *zs, size_t inputLeft) {
+ return deflate(zs, inputLeft ? Z_NO_FLUSH : Z_FINISH);
+ },
+ [] (z_stream *zs) { deflateEnd(zs); });
}
#endif
@@ -616,18 +738,21 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
data that was compressed using zlib, you first need to prepend a four
byte header to the byte array containing the data. The header must
contain the expected length (in bytes) of the uncompressed data,
- expressed as an unsigned, big-endian, 32-bit integer.
+ expressed as an unsigned, big-endian, 32-bit integer. This number is
+ just a hint for the initial size of the output buffer size,
+ though. If the indicated size is too small to hold the result, the
+ output buffer size will still be increased until either the output
+ fits or the system runs out of memory. So, despite the 32-bit
+ header, this function, on 64-bit platforms, can produce more than
+ 4GiB of output.
+
+ \note In Qt versions prior to Qt 6.5, more than 2GiB of data
+ worked unreliably; in Qt versions prior to Qt 6.0, not at all.
\sa qCompress()
*/
#ifndef QT_NO_COMPRESS
-static QByteArray invalidCompressedData()
-{
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
-}
-
/*! \relates QByteArray
\overload
@@ -635,66 +760,41 @@ static QByteArray invalidCompressedData()
Uncompresses the first \a nbytes of \a data and returns a new byte
array with the uncompressed data.
*/
-QByteArray qUncompress(const uchar* data, int nbytes)
+QByteArray qUncompress(const uchar* data, qsizetype nbytes)
{
- if (!data) {
- qWarning("qUncompress: Data is null");
- return QByteArray();
- }
- if (nbytes <= 4) {
- if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0))
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
- }
- ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) |
- (data[2] << 8) | (data[3] ));
- ulong len = qMax(expectedSize, 1ul);
- const ulong maxPossibleSize = MaxAllocSize - sizeof(QByteArray::Data);
- if (Q_UNLIKELY(len >= maxPossibleSize)) {
- // QByteArray does not support that huge size anyway.
- return invalidCompressedData();
- }
+ if (!data)
+ return dataIsNull(ZLibOp::Decompression);
- QByteArray::DataPointer d(QByteArray::Data::allocate(expectedSize + 1));
- if (Q_UNLIKELY(d.data() == nullptr))
+ if (nbytes < 0)
+ return lengthIsNegative(ZLibOp::Decompression);
+
+ constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t);
+ if (nbytes < HeaderSize)
return invalidCompressedData();
- forever {
- ulong alloc = len;
- int res = ::uncompress((uchar*)d.data(), &len,
- data+4, nbytes-4);
-
- switch (res) {
- case Z_OK: {
- Q_ASSERT(len <= alloc);
- Q_UNUSED(alloc)
- d.data()[len] = '\0';
- d.size = len;
- return QByteArray(d);
- }
+ const auto expectedSize = qFromBigEndian<CompressSizeHint_t>(data);
+ if (nbytes == HeaderSize) {
+ if (expectedSize != 0)
+ return invalidCompressedData();
+ return QByteArray();
+ }
- case Z_MEM_ERROR:
- qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
- return QByteArray();
+ constexpr auto MaxDecompressedSize = size_t(QByteArray::max_size());
+ if constexpr (MaxDecompressedSize < std::numeric_limits<CompressSizeHint_t>::max()) {
+ if (expectedSize > MaxDecompressedSize)
+ return tooMuchData(ZLibOp::Decompression);
+ }
- case Z_BUF_ERROR:
- len *= 2;
- if (Q_UNLIKELY(len >= maxPossibleSize)) {
- // QByteArray does not support that huge size anyway.
- return invalidCompressedData();
- } else {
- // grow the block
- d->reallocate(d->allocatedCapacity()*2, QByteArray::Data::GrowsForward);
- if (Q_UNLIKELY(d.data() == nullptr))
- return invalidCompressedData();
- }
- continue;
+ // expectedSize may be truncated, so always use at least nbytes
+ // (larger by at most 1%, according to zlib docs)
+ qsizetype capacity = std::max(qsizetype(expectedSize), // cannot overflow!
+ nbytes);
- case Z_DATA_ERROR:
- qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
- return QByteArray();
- }
- }
+ QArrayDataPointer<char> d(capacity);
+ return xxflate(ZLibOp::Decompression, std::move(d), {data + HeaderSize, nbytes - HeaderSize},
+ [] (z_stream *zs) { return inflateInit(zs); },
+ [] (z_stream *zs, size_t) { return inflate(zs, Z_NO_FLUSH); },
+ [] (z_stream *zs) { inflateEnd(zs); });
}
#endif
@@ -709,6 +809,14 @@ QByteArray qUncompress(const uchar* data, int nbytes)
\reentrant
+ \compares strong
+ \compareswith strong {const char *} QByteArrayView
+ \endcompareswith
+ \compareswith strong QChar char16_t QString QStringView QLatin1StringView \
+ QUtf8StringView
+ When comparing with string types, the content is interpreted as utf-8.
+ \endcompareswith
+
QByteArray can be used to store both raw bytes (including '\\0's)
and traditional 8-bit '\\0'-terminated strings. Using QByteArray
is much more convenient than using \c{const char *}. Behind the
@@ -756,7 +864,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
at() can be faster than operator[](), because it never causes a
\l{deep copy} to occur.
- To extract many bytes at a time, use left(), right(), or mid().
+ To extract many bytes at a time, use first(), last(), or sliced().
A QByteArray can embed '\\0' bytes. The size() function always
returns the size of the whole array, including embedded '\\0'
@@ -785,16 +893,48 @@ QByteArray qUncompress(const uchar* data, int nbytes)
\snippet code/src_corelib_text_qbytearray.cpp 3
- The replace() and remove() functions' first two arguments are the
- position from which to start erasing and the number of bytes that
- should be erased.
+ In the above example the replace() function's first two arguments are the
+ position from which to start replacing and the number of bytes that
+ should be replaced.
+
+ When data-modifying functions increase the size of the array,
+ they may lead to reallocation of memory for the QByteArray object. When
+ this happens, QByteArray expands by more than it immediately needs so as
+ to have space for further expansion without reallocation until the size
+ of the array has greatly increased.
+
+ The insert(), remove() and, when replacing a sub-array with one of
+ different size, replace() functions can be slow (\l{linear time}) for
+ large arrays, because they require moving many bytes in the array by
+ at least one position in memory.
- When you append() data to a non-empty array, the array will be
- reallocated and the new data copied to it. You can avoid this
- behavior by calling reserve(), which preallocates a certain amount
+ If you are building a QByteArray gradually and know in advance
+ approximately how many bytes the QByteArray will contain, you
+ can call reserve(), asking QByteArray to preallocate a certain amount
of memory. You can also call capacity() to find out how much
- memory QByteArray actually allocated. Data appended to an empty
- array is not copied.
+ memory the QByteArray actually has allocated.
+
+ Note that using non-const operators and functions can cause
+ QByteArray to do a deep copy of the data, due to \l{implicit sharing}.
+
+ QByteArray provides \l{STL-style iterators} (QByteArray::const_iterator and
+ QByteArray::iterator). In practice, iterators are handy when working with
+ generic algorithms provided by the C++ standard library.
+
+ \note Iterators and references to individual QByteArray elements are subject
+ to stability issues. They are often invalidated when a QByteArray-modifying
+ operation (e.g. insert() or remove()) is called. When stability and
+ iterator-like functionality is required, you should use indexes instead of
+ iterators as they are not tied to QByteArray's internal state and thus do
+ not get invalidated.
+
+ \note Iterators over a QByteArray, and references to individual bytes
+ within one, cannot be relied on to remain valid when any non-const method
+ of the QByteArray is called. Accessing such an iterator or reference after
+ the call to a non-const method leads to undefined behavior. When stability
+ for iterator-like functionality is required, you should use indexes instead
+ of iterators as they are not tied to QByteArray's internal state and thus do
+ not get invalidated.
If you want to find all occurrences of a particular byte or sequence of
bytes in a QByteArray, use indexOf() or lastIndexOf(). The former searches
@@ -836,15 +976,19 @@ QByteArray qUncompress(const uchar* data, int nbytes)
\section1 Maximum size and out-of-memory conditions
- The current version of QByteArray is limited to just under 2 GB (2^31
- bytes) in size. The exact value is architecture-dependent, since it depends
- on the overhead required for managing the data block, but is no more than
- 32 bytes. Raw data blocks are also limited by the use of \c int type in the
- current version to 2 GB minus 1 byte.
+ The maximum size of QByteArray depends on the architecture. Most 64-bit
+ systems can allocate more than 2 GB of memory, with a typical limit
+ of 2^63 bytes. The actual value also depends on the overhead required for
+ managing the data block. As a result, you can expect the maximum size
+ of 2 GB minus overhead on 32-bit platforms, and 2^63 bytes minus overhead
+ on 64-bit platforms. The number of elements that can be stored in a
+ QByteArray is this maximum size.
- In case memory allocation fails, QByteArray will throw a \c std::bad_alloc
- exception. Out of memory conditions in the Qt containers are the only case
- where Qt will throw exceptions.
+ When memory allocation fails, QByteArray throws a \c std::bad_alloc
+ exception if the application is being compiled with exception support.
+ Out of memory conditions in Qt containers are the only case where Qt
+ will throw exceptions. If exceptions are disabled, then running out of
+ memory is undefined behavior.
Note that the operating system may impose further limits on applications
holding a lot of allocated memory, especially large, contiguous blocks.
@@ -878,17 +1022,18 @@ QByteArray qUncompress(const uchar* data, int nbytes)
\section2 Spacing Characters
A frequent requirement is to remove spacing characters from a byte array
- ('\\n', '\\t', ' ', etc.). If you want to remove spacing from both ends of a
- QByteArray, use trimmed(). If you want to also replace each run of spacing
- characters with a single space character within the byte array, use
+ (\c{'\n'}, \c{'\t'}, \c{' '}, etc.). If you want to remove spacing from both
+ ends of a QByteArray, use trimmed(). If you want to also replace each run of
+ spacing characters with a single space character within the byte array, use
simplified(). Only ASCII spacing characters are recognized for these
purposes.
\section2 Number-String Conversions
- Functions that perform conversions between numeric data types and strings
- are performed in the C locale, regardless of the user's locale settings. Use
- QLocale to perform locale-aware conversions between numbers and strings.
+ Functions that perform conversions between numeric data types and string
+ representations are performed in the C locale, regardless of the user's
+ locale settings. Use QLocale to perform locale-aware conversions between
+ numbers and strings.
\section2 Character Case
@@ -896,13 +1041,13 @@ QByteArray qUncompress(const uchar* data, int nbytes)
comparison is limited to ASCII. Non-ASCII characters are treated as
caseless, since their case depends on encoding. This affects functions that
support a case insensitive option or that change the case of their
- arguments. Functions that this affects include contains(), indexOf(),
- lastIndexOf(), isLower(), isUpper(), toLower() and toUpper().
+ arguments. Functions that this affects include compare(), isLower(),
+ isUpper(), toLower() and toUpper().
This issue does not apply to \l{QString}s since they represent characters
using Unicode.
- \sa QString, QBitArray
+ \sa QByteArrayView, QString, QBitArray
*/
/*!
@@ -941,6 +1086,11 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first
byte in the byte-array.
+//! [iterator-invalidation-func-desc]
+ \warning The returned iterator is invalidated on detachment or when the
+ QByteArray is modified.
+//! [iterator-invalidation-func-desc]
+
\sa constBegin(), end()
*/
@@ -955,6 +1105,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
first byte in the byte-array.
+ \include qbytearray.cpp iterator-invalidation-func-desc
+
\sa begin(), cend()
*/
@@ -963,6 +1115,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
first byte in the byte-array.
+ \include qbytearray.cpp iterator-invalidation-func-desc
+
\sa begin(), constEnd()
*/
@@ -971,6 +1125,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after
the last byte in the byte-array.
+ \include qbytearray.cpp iterator-invalidation-func-desc
+
\sa begin(), constEnd()
*/
@@ -985,6 +1141,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
after the last byte in the byte-array.
+ \include qbytearray.cpp iterator-invalidation-func-desc
+
\sa cbegin(), end()
*/
@@ -993,14 +1151,18 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
after the last byte in the byte-array.
+ \include qbytearray.cpp iterator-invalidation-func-desc
+
\sa constBegin(), end()
*/
/*! \fn QByteArray::reverse_iterator QByteArray::rbegin()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- byte in the byte-array, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to
+ the first byte in the byte-array, in reverse order.
+
+ \include qbytearray.cpp iterator-invalidation-func-desc
\sa begin(), crbegin(), rend()
*/
@@ -1013,8 +1175,10 @@ QByteArray qUncompress(const uchar* data, int nbytes)
/*! \fn QByteArray::const_reverse_iterator QByteArray::crbegin() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- byte in the byte-array, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to the first byte in the byte-array, in reverse order.
+
+ \include qbytearray.cpp iterator-invalidation-func-desc
\sa begin(), rbegin(), rend()
*/
@@ -1022,8 +1186,10 @@ QByteArray qUncompress(const uchar* data, int nbytes)
/*! \fn QByteArray::reverse_iterator QByteArray::rend()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last byte in the byte-array, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing just
+ after the last byte in the byte-array, in reverse order.
+
+ \include qbytearray.cpp iterator-invalidation-func-desc
\sa end(), crend(), rbegin()
*/
@@ -1036,8 +1202,10 @@ QByteArray qUncompress(const uchar* data, int nbytes)
/*! \fn QByteArray::const_reverse_iterator QByteArray::crend() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last byte in the byte-array, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ just after the last byte in the byte-array, in reverse order.
+
+ \include qbytearray.cpp iterator-invalidation-func-desc
\sa end(), rend(), rbegin()
*/
@@ -1048,6 +1216,13 @@ QByteArray qUncompress(const uchar* data, int nbytes)
to append(\a other).
*/
+/*! \fn void QByteArray::push_back(QByteArrayView str)
+ \since 6.0
+ \overload
+
+ Same as append(\a str).
+*/
+
/*! \fn void QByteArray::push_back(const char *str)
\overload
@@ -1068,6 +1243,13 @@ QByteArray qUncompress(const uchar* data, int nbytes)
to prepend(\a other).
*/
+/*! \fn void QByteArray::push_front(QByteArrayView str)
+ \since 6.0
+ \overload
+
+ Same as prepend(\a str).
+*/
+
/*! \fn void QByteArray::push_front(const char *str)
\overload
@@ -1089,6 +1271,37 @@ QByteArray qUncompress(const uchar* data, int nbytes)
squeeze().
*/
+/*!
+ \since 6.1
+
+ Removes from the byte array the characters in the half-open range
+ [ \a first , \a last ). Returns an iterator to the character
+ referred to by \a last before the erase.
+*/
+QByteArray::iterator QByteArray::erase(QByteArray::const_iterator first, QByteArray::const_iterator last)
+{
+ const auto start = std::distance(cbegin(), first);
+ const auto len = std::distance(first, last);
+ remove(start, len);
+ return begin() + start;
+}
+
+/*!
+ \fn QByteArray::iterator QByteArray::erase(QByteArray::const_iterator it)
+
+ \overload
+ \since 6.5
+
+ Removes the character denoted by \c it from the byte array.
+ Returns an iterator to the character immediately after the
+ erased character.
+
+ \code
+ QByteArray ba = "abcdefg";
+ auto it = ba.erase(ba.cbegin()); // ba is now "bcdefg" and it points to "b"
+ \endcode
+*/
+
/*! \fn QByteArray::QByteArray(const QByteArray &other)
Constructs a copy of \a other.
@@ -1136,24 +1349,19 @@ QByteArray &QByteArray::operator=(const QByteArray & other) noexcept
\overload
Assigns \a str to this byte array.
+
+ \a str is assumed to point to a null-terminated string, and its length is
+ determined dynamically.
*/
QByteArray &QByteArray::operator=(const char *str)
{
- if (!str || !*str) {
- if (!str) {
- d.clear();
- } else {
- d = QByteArrayData(Data::allocate(0), 0);
- }
+ if (!str) {
+ d.clear();
+ } else if (!*str) {
+ d = DataPointer::fromRawData(&_empty, 0);
} else {
- const int len = int(strlen(str));
- const uint fullLen = uint(len) + 1;
- if (d->needsDetach() || fullLen > d->allocatedCapacity()
- || (len < size() && fullLen < (d->allocatedCapacity() >> 1)))
- reallocData(fullLen, d->detachFlags());
- memcpy(d.data(), str, fullLen); // include null terminator
- d.size = len;
+ assign(str);
}
return *this;
}
@@ -1173,7 +1381,7 @@ QByteArray &QByteArray::operator=(const char *str)
fast and never fails.
*/
-/*! \fn int QByteArray::size() const
+/*! \fn qsizetype QByteArray::size() const
Returns the number of bytes in this byte array.
@@ -1182,7 +1390,7 @@ QByteArray &QByteArray::operator=(const char *str)
you can use the return value of data() and constData() as arguments to
functions that expect '\\0'-terminated strings. If the QByteArray object was
created from a \l{fromRawData()}{raw data} that didn't include the trailing
- '\\0'-termination byte, then QByteArray doesn't add it automaticall unless a
+ '\\0'-termination byte, then QByteArray doesn't add it automatically unless a
\l{deep copy} is created.
Example:
@@ -1191,6 +1399,15 @@ QByteArray &QByteArray::operator=(const char *str)
\sa isEmpty(), resize()
*/
+/*! \fn qsizetype QByteArray::max_size()
+ \since 6.8
+
+ This function is provided for STL compatibility.
+ It returns the maximum number of elements that the byte array can
+ theoretically hold. In practice, the number can be much smaller,
+ limited by the amount of memory available to the system.
+*/
+
/*! \fn bool QByteArray::isEmpty() const
Returns \c true if the byte array has size 0; otherwise returns \c false.
@@ -1201,7 +1418,7 @@ QByteArray &QByteArray::operator=(const char *str)
\sa size()
*/
-/*! \fn int QByteArray::capacity() const
+/*! \fn qsizetype QByteArray::capacity() const
Returns the maximum number of bytes that can be stored in the
byte array without forcing a reallocation.
@@ -1214,21 +1431,36 @@ QByteArray &QByteArray::operator=(const char *str)
\note a statically allocated byte array will report a capacity of 0,
even if it's not empty.
+ \note The free space position in the allocated memory block is undefined. In
+ other words, one should not assume that the free memory is always located
+ after the initialized elements.
+
\sa reserve(), squeeze()
*/
-/*! \fn void QByteArray::reserve(int size)
+/*! \fn void QByteArray::reserve(qsizetype size)
+
+ Attempts to allocate memory for at least \a size bytes.
- Attempts to allocate memory for at least \a size bytes. If you
- know in advance how large the byte array will be, you can call
+ If you know in advance how large the byte array will be, you can call
this function, and if you call resize() often you are likely to
- get better performance. If \a size is an underestimate, the worst
- that will happen is that the QByteArray will be a bit slower.
+ get better performance.
+
+ If in doubt about how much space shall be needed, it is usually better to
+ use an upper bound as \a size, or a high estimate of the most likely size,
+ if a strict upper bound would be much bigger than this. If \a size is an
+ underestimate, the array will grow as needed once the reserved size is
+ exceeded, which may lead to a larger allocation than your best overestimate
+ would have and will slow the operation that triggers it.
+
+ \warning reserve() reserves memory but does not change the size of the byte
+ array. Accessing data beyond the end of the byte array is undefined
+ behavior. If you need to access memory beyond the current end of the array,
+ use resize().
The sole purpose of this function is to provide a means of fine
tuning QByteArray's memory usage. In general, you will rarely
- ever need to call this function. If you want to change the size
- of the byte array, call resize().
+ ever need to call this function.
\sa squeeze(), capacity()
*/
@@ -1247,12 +1479,16 @@ QByteArray &QByteArray::operator=(const char *str)
/*! \fn QByteArray::operator const char *() const
\fn QByteArray::operator const void *() const
- \obsolete Use constData() instead.
+ \note Use constData() instead in new code.
Returns a pointer to the data stored in the byte array. The
pointer can be used to access the bytes that compose the array.
- The data is '\\0'-terminated. The pointer remains valid as long
- as the array isn't reallocated or destroyed.
+ The data is '\\0'-terminated.
+
+//! [pointer-invalidation-desc]
+ The pointer remains valid as long as no detach happens and the QByteArray
+ is not modified.
+//! [pointer-invalidation-desc]
This operator is mostly useful to pass a byte array to a function
that accepts a \c{const char *}.
@@ -1287,9 +1523,10 @@ QByteArray &QByteArray::operator=(const char *str)
Example:
\snippet code/src_corelib_text_qbytearray.cpp 8
- The pointer remains valid as long as the byte array isn't
- reallocated or destroyed. For read-only access, constData() is
- faster because it never causes a \l{deep copy} to occur.
+ \include qbytearray.cpp pointer-invalidation-desc
+
+ For read-only access, constData() is faster because it never
+ causes a \l{deep copy} to occur.
This function is mostly useful to pass a byte array to a function
that accepts a \c{const char *}.
@@ -1318,11 +1555,11 @@ QByteArray &QByteArray::operator=(const char *str)
/*! \fn const char *QByteArray::constData() const
- Returns a pointer to the data stored in the byte array. The pointer can be
- used to access the bytes that compose the array. The data is
+ Returns a pointer to the const data stored in the byte array. The pointer
+ can be used to access the bytes that compose the array. The data is
'\\0'-terminated unless the QByteArray object was created from raw data.
- The pointer remains valid as long as the byte array isn't reallocated or
- destroyed.
+
+ \include qbytearray.cpp pointer-invalidation-desc
This function is mostly useful to pass a byte array to a function
that accepts a \c{const char *}.
@@ -1349,7 +1586,7 @@ QByteArray &QByteArray::operator=(const char *str)
\internal
*/
-/*! \fn char QByteArray::at(int i) const
+/*! \fn char QByteArray::at(qsizetype i) const
Returns the byte at index position \a i in the byte array.
@@ -1359,7 +1596,7 @@ QByteArray &QByteArray::operator=(const char *str)
\sa operator[]()
*/
-/*! \fn char &QByteArray::operator[](int i)
+/*! \fn char &QByteArray::operator[](qsizetype i)
Returns the byte at index position \a i as a modifiable reference.
@@ -1372,7 +1609,7 @@ QByteArray &QByteArray::operator=(const char *str)
\sa at()
*/
-/*! \fn char QByteArray::operator[](int i) const
+/*! \fn char QByteArray::operator[](qsizetype i) const
\overload
@@ -1439,22 +1676,15 @@ QByteArray &QByteArray::operator=(const char *str)
\sa front(), at(), operator[]()
*/
-/*! \fn bool QByteArray::contains(const QByteArray &ba) const
+/*! \fn bool QByteArray::contains(QByteArrayView bv) const
+ \since 6.0
- Returns \c true if the byte array contains an occurrence of the byte
- array \a ba; otherwise returns \c false.
+ Returns \c true if this byte array contains an occurrence of the
+ sequence of bytes viewed by \a bv; otherwise returns \c false.
\sa indexOf(), count()
*/
-/*! \fn bool QByteArray::contains(const char *str) const
-
- \overload
-
- Returns \c true if the byte array contains the '\\0'-terminated string \a
- str; otherwise returns \c false.
-*/
-
/*! \fn bool QByteArray::contains(char ch) const
\overload
@@ -1472,9 +1702,9 @@ QByteArray &QByteArray::operator=(const char *str)
Example:
\snippet code/src_corelib_text_qbytearray.cpp 10
- \sa chop(), resize(), left()
+ \sa chop(), resize(), first()
*/
-void QByteArray::truncate(int pos)
+void QByteArray::truncate(qsizetype pos)
{
if (pos < size())
resize(pos);
@@ -1490,10 +1720,10 @@ void QByteArray::truncate(int pos)
Example:
\snippet code/src_corelib_text_qbytearray.cpp 11
- \sa truncate(), resize(), left()
+ \sa truncate(), resize(), first()
*/
-void QByteArray::chop(int n)
+void QByteArray::chop(qsizetype n)
{
if (n > 0)
resize(size() - n);
@@ -1540,7 +1770,7 @@ void QByteArray::chop(int n)
reference to this byte array.
*/
-/*! \fn int QByteArray::length() const
+/*! \fn qsizetype QByteArray::length() const
Same as size().
*/
@@ -1581,16 +1811,21 @@ void QByteArray::chop(int n)
\sa fromRawData()
*/
-QByteArray::QByteArray(const char *data, int size)
+QByteArray::QByteArray(const char *data, qsizetype size)
{
if (!data) {
d = DataPointer();
} else {
if (size < 0)
- size = int(strlen(data));
- d = DataPointer(Data::allocate(uint(size) + 1u), size);
- memcpy(d.data(), data, size);
- d.data()[size] = '\0';
+ size = qstrlen(data);
+ if (!size) {
+ d = DataPointer::fromRawData(&_empty, 0);
+ } else {
+ d = DataPointer(size, size);
+ Q_CHECK_PTR(d.data());
+ memcpy(d.data(), data, size);
+ d.data()[size] = '\0';
+ }
}
}
@@ -1600,27 +1835,31 @@ QByteArray::QByteArray(const char *data, int size)
\sa fill()
*/
-QByteArray::QByteArray(int size, char ch)
+QByteArray::QByteArray(qsizetype size, char ch)
{
if (size <= 0) {
- d = DataPointer(Data::allocate(0), 0);
+ d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(uint(size) + 1u), size);
+ d = DataPointer(size, size);
+ Q_CHECK_PTR(d.data());
memset(d.data(), ch, size);
d.data()[size] = '\0';
}
}
/*!
- \internal
-
Constructs a byte array of size \a size with uninitialized contents.
*/
-QByteArray::QByteArray(int size, Qt::Initialization)
+QByteArray::QByteArray(qsizetype size, Qt::Initialization)
{
- d = DataPointer(Data::allocate(uint(size) + 1u), size);
- d.data()[size] = '\0';
+ if (size <= 0) {
+ d = DataPointer::fromRawData(&_empty, 0);
+ } else {
+ d = DataPointer(size, size);
+ Q_CHECK_PTR(d.data());
+ d.data()[size] = '\0';
+ }
}
/*!
@@ -1630,24 +1869,68 @@ QByteArray::QByteArray(int size, Qt::Initialization)
extended to make it \a size bytes with the extra bytes added to
the end. The new bytes are uninitialized.
- If \a size is less than the current size, bytes are removed from
- the end.
+ If \a size is less than the current size, bytes beyond position
+ \a size are excluded from the byte array.
+
+ \note While resize() will grow the capacity if needed, it never shrinks
+ capacity. To shed excess capacity, use squeeze().
- \sa size(), truncate()
+ \sa size(), truncate(), squeeze()
*/
-void QByteArray::resize(int size)
+void QByteArray::resize(qsizetype size)
{
if (size < 0)
size = 0;
- if (d->needsDetach() || size > capacity())
- reallocData(uint(size) + 1u, d->detachFlags() | Data::GrowsForward);
+ const auto capacityAtEnd = capacity() - d.freeSpaceAtBegin();
+ if (d->needsDetach() || size > capacityAtEnd)
+ reallocData(size, QArrayData::Grow);
d.size = size;
if (d->allocatedCapacity())
d.data()[size] = 0;
}
/*!
+ \since 6.4
+
+ Sets the size of the byte array to \a newSize bytes.
+
+ If \a newSize is greater than the current size, the byte array is
+ extended to make it \a newSize bytes with the extra bytes added to
+ the end. The new bytes are initialized to \a c.
+
+ If \a newSize is less than the current size, bytes beyond position
+ \a newSize are excluded from the byte array.
+
+ \note While resize() will grow the capacity if needed, it never shrinks
+ capacity. To shed excess capacity, use squeeze().
+
+ \sa size(), truncate(), squeeze()
+*/
+void QByteArray::resize(qsizetype newSize, char c)
+{
+ const auto old = d.size;
+ resize(newSize);
+ if (old < d.size)
+ memset(d.data() + old, c, d.size - old);
+}
+
+/*!
+ \since 6.8
+
+ Resizes the byte array to \a size bytes. If the size of the
+ byte array grows, the new bytes are uninitialized.
+
+ The behavior is identical to \c{resize(size)}.
+
+ \sa resize()
+*/
+void QByteArray::resizeForOverwrite(qsizetype size)
+{
+ resize(size);
+}
+
+/*!
Sets every byte in the byte array to \a ch. If \a size is different from -1
(the default), the byte array is resized to size \a size beforehand.
@@ -1657,7 +1940,7 @@ void QByteArray::resize(int size)
\sa resize()
*/
-QByteArray &QByteArray::fill(char ch, int size)
+QByteArray &QByteArray::fill(char ch, qsizetype size)
{
resize(size < 0 ? this->size() : size);
if (this->size())
@@ -1665,88 +1948,90 @@ QByteArray &QByteArray::fill(char ch, int size)
return *this;
}
-void QByteArray::reallocData(uint alloc, Data::ArrayOptions options)
+void QByteArray::reallocData(qsizetype alloc, QArrayData::AllocationOption option)
{
- if (d->needsDetach()) {
- DataPointer dd(Data::allocate(alloc, options), qMin(int(alloc) - 1, d.size));
- ::memcpy(dd.data(), d.data(), dd.size);
+ if (!alloc) {
+ d = DataPointer::fromRawData(&_empty, 0);
+ return;
+ }
+
+ // don't use reallocate path when reducing capacity and there's free space
+ // at the beginning: might shift data pointer outside of allocated space
+ const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0;
+
+ if (d->needsDetach() || cannotUseReallocate) {
+ DataPointer dd(alloc, qMin(alloc, d.size), option);
+ Q_CHECK_PTR(dd.data());
+ if (dd.size > 0)
+ ::memcpy(dd.data(), d.data(), dd.size);
dd.data()[dd.size] = 0;
d = dd;
} else {
- d.reallocate(alloc, options);
+ d->reallocate(alloc, option);
}
}
-void QByteArray::expand(int i)
+void QByteArray::reallocGrowData(qsizetype n)
{
- resize(qMax(i + 1, size()));
-}
+ if (!n) // expected to always allocate
+ n = 1;
-/*!
- \internal
- Return a QByteArray that is sure to be '\\0'-terminated.
+ if (d->needsDetach()) {
+ DataPointer dd(DataPointer::allocateGrow(d, n, QArrayData::GrowsAtEnd));
+ Q_CHECK_PTR(dd.data());
+ dd->copyAppend(d.data(), d.data() + d.size);
+ dd.data()[dd.size] = 0;
+ d = dd;
+ } else {
+ d->reallocate(d.constAllocatedCapacity() + n, QArrayData::Grow);
+ }
+}
- By default, all QByteArray have an extra NUL at the end,
- guaranteeing that assumption. However, if QByteArray::fromRawData
- is used, then the NUL is there only if the user put it there. We
- can't be sure.
-*/
-QByteArray QByteArray::nulTerminated() const
+void QByteArray::expand(qsizetype i)
{
- // is this fromRawData?
- if (!IS_RAW_DATA(d))
- return *this; // no, then we're sure we're zero terminated
-
- QByteArray copy(*this);
- copy.detach();
- return copy;
+ resize(qMax(i + 1, size()));
}
/*!
- Prepends the byte array \a ba to this byte array and returns a
+ \fn QByteArray &QByteArray::prepend(QByteArrayView ba)
+
+ Prepends the byte array view \a ba to this byte array and returns a
reference to this byte array.
+ This operation is typically very fast (\l{constant time}), because
+ QByteArray preallocates extra space at the beginning of the data,
+ so it can grow without reallocating the entire array each time.
+
Example:
\snippet code/src_corelib_text_qbytearray.cpp 15
This is the same as insert(0, \a ba).
- Note: QByteArray is an \l{implicitly shared} class. Consequently,
- if you prepend to an empty byte array, then the byte array will just
- share the data held in \a ba. In this case, no copying of data is done,
- taking \l{constant time}. If a shared instance is modified, it will
- be copied (copy-on-write), taking \l{linear time}.
-
- If the byte array being prepended to is not empty, a deep copy of the
- data is performed, taking \l{linear time}.
-
\sa append(), insert()
*/
+/*!
+ \fn QByteArray &QByteArray::prepend(const QByteArray &ba)
+ \overload
+
+ Prepends \a ba to this byte array.
+*/
QByteArray &QByteArray::prepend(const QByteArray &ba)
{
- if (size() == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) {
- *this = ba;
- } else if (ba.size() != 0) {
- QByteArray tmp = *this;
- *this = ba;
- append(tmp);
- }
- return *this;
+ if (size() == 0 && ba.size() > d.constAllocatedCapacity() && ba.d.isMutable())
+ return (*this = ba);
+ return prepend(QByteArrayView(ba));
}
/*!
+ \fn QByteArray &QByteArray::prepend(const char *str)
\overload
Prepends the '\\0'-terminated string \a str to this byte array.
*/
-QByteArray &QByteArray::prepend(const char *str)
-{
- return prepend(str, qstrlen(str));
-}
-
/*!
+ \fn QByteArray &QByteArray::prepend(const char *str, qsizetype len)
\overload
\since 4.6
@@ -1754,20 +2039,7 @@ QByteArray &QByteArray::prepend(const char *str)
The bytes prepended may include '\\0' bytes.
*/
-QByteArray &QByteArray::prepend(const char *str, int len)
-{
- if (str) {
- if (d->needsDetach() || size() + len > capacity())
- reallocData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward);
- memmove(d.data()+len, d.data(), d.size);
- memcpy(d.data(), str, len);
- d.size += len;
- d.data()[d.size] = '\0';
- }
- return *this;
-}
-
-/*! \fn QByteArray &QByteArray::prepend(int count, char ch)
+/*! \fn QByteArray &QByteArray::prepend(qsizetype count, char ch)
\overload
\since 5.7
@@ -1776,22 +2048,12 @@ QByteArray &QByteArray::prepend(const char *str, int len)
*/
/*!
+ \fn QByteArray &QByteArray::prepend(char ch)
\overload
Prepends the byte \a ch to this byte array.
*/
-QByteArray &QByteArray::prepend(char ch)
-{
- if (d->needsDetach() || size() + 1 > capacity())
- reallocData(uint(size()) + 2u, d->detachFlags() | Data::GrowsForward);
- memmove(d.data()+1, d.data(), d.size);
- d.data()[0] = ch;
- ++d.size;
- d.data()[d.size] = '\0';
- return *this;
-}
-
/*!
Appends the byte array \a ba onto the end of this byte array.
@@ -1809,47 +2071,45 @@ QByteArray &QByteArray::prepend(char ch)
If the byte array being appended to is not empty, a deep copy of the
data is performed, taking \l{linear time}.
- This operation typically does not suffer from allocation overhead,
- because QByteArray preallocates extra space at the end of the data
- so that it may grow without reallocating for each append operation.
+ The append() function is typically very fast (\l{constant time}),
+ because QByteArray preallocates extra space at the end of the data,
+ so it can grow without reallocating the entire array each time.
\sa operator+=(), prepend(), insert()
*/
QByteArray &QByteArray::append(const QByteArray &ba)
{
- if (size() == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) {
- *this = ba;
- } else if (ba.size() != 0) {
- if (d->needsDetach() || size() + ba.size() > capacity())
- reallocData(uint(size() + ba.size()) + 1u, d->detachFlags() | Data::GrowsForward);
- memcpy(d.data() + d.size, ba.data(), ba.size());
- d.size += ba.size();
- d.data()[d.size] = '\0';
+ if (!ba.isNull()) {
+ if (isNull()) {
+ if (Q_UNLIKELY(!ba.d.isMutable()))
+ assign(ba); // fromRawData, so we do a deep copy
+ else
+ operator=(ba);
+ } else if (ba.size()) {
+ append(QByteArrayView(ba));
+ }
}
return *this;
}
/*!
+ \fn QByteArray &QByteArray::append(QByteArrayView data)
\overload
- Appends the '\\0'-terminated string \a str to this byte array.
+ Appends \a data to this byte array.
*/
-QByteArray& QByteArray::append(const char *str)
-{
- if (str) {
- const int len = int(strlen(str));
- if (d->needsDetach() || size() + len > capacity())
- reallocData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward);
- memcpy(d.data() + d.size, str, len + 1); // include null terminator
- d.size += len;
- }
- return *this;
-}
+/*!
+ \fn QByteArray& QByteArray::append(const char *str)
+ \overload
+
+ Appends the '\\0'-terminated string \a str to this byte array.
+*/
/*!
- \overload append()
+ \fn QByteArray &QByteArray::append(const char *str, qsizetype len)
+ \overload
Appends the first \a len bytes starting at \a str to this byte array and
returns a reference to this byte array. The bytes appended may include '\\0'
@@ -1863,21 +2123,7 @@ QByteArray& QByteArray::append(const char *str)
array. Ensure that \a len is \e not longer than \a str.
*/
-QByteArray &QByteArray::append(const char *str, int len)
-{
- if (len < 0)
- len = qstrlen(str);
- if (str && len) {
- if (d->needsDetach() || size() + len > capacity())
- reallocData(uint(size() + len) + 1u, d->detachFlags() | Data::GrowsForward);
- memcpy(d.data() + d.size, str, len);
- d.size += len;
- d.data()[d.size] = '\0';
- }
- return *this;
-}
-
-/*! \fn QByteArray &QByteArray::append(int count, char ch)
+/*! \fn QByteArray &QByteArray::append(qsizetype count, char ch)
\overload
\since 5.7
@@ -1896,95 +2142,174 @@ QByteArray &QByteArray::append(const char *str, int len)
QByteArray& QByteArray::append(char ch)
{
- if (d->needsDetach() || size() + 1 > capacity())
- reallocData(uint(size()) + 2u, d->detachFlags() | Data::GrowsForward);
- d.data()[d.size++] = ch;
+ d.detachAndGrow(QArrayData::GrowsAtEnd, 1, nullptr, nullptr);
+ d->copyAppend(1, ch);
d.data()[d.size] = '\0';
return *this;
}
/*!
- \internal
- Inserts \a len bytes from the array \a arr at position \a pos and returns a
- reference the modified byte array.
+ \fn QByteArray &QByteArray::assign(QByteArrayView v)
+ \since 6.6
+
+ Replaces the contents of this byte array with a copy of \a v and returns a
+ reference to this byte array.
+
+ The size of this byte array will be equal to the size of \a v.
+
+ This function only allocates memory if the size of \a v exceeds the capacity
+ of this byte array or this byte array is shared.
*/
-static inline QByteArray &qbytearray_insert(QByteArray *ba,
- int pos, const char *arr, int len)
+
+/*!
+ \fn QByteArray &QByteArray::assign(qsizetype n, char c)
+ \since 6.6
+
+ Replaces the contents of this byte array with \a n copies of \a c and
+ returns a reference to this byte array.
+
+ The size of this byte array will be equal to \a n, which has to be non-negative.
+
+ This function will only allocate memory if \a n exceeds the capacity of this
+ byte array or this byte array is shared.
+
+ \sa fill()
+*/
+
+/*!
+ \fn template <typename InputIterator, QByteArray::if_input_iterator<InputIterator>> QByteArray &QByteArray::assign(InputIterator first, InputIterator last)
+ \since 6.6
+
+ Replaces the contents of this byte array with a copy of the elements in the
+ iterator range [\a first, \a last) and returns a reference to this
+ byte array.
+
+ The size of this byte array will be equal to the number of elements in the
+ range [\a first, \a last).
+
+ This function will only allocate memory if the number of elements in the
+ range exceeds the capacity of this byte array or this byte array is shared.
+
+ \note This function overload only participates in overload resolution if
+ \c InputIterator meets the requirements of a
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}.
+
+ \note The behavior is undefined if either argument is an iterator into *this or
+ [\a first, \a last) is not a valid range.
+*/
+
+QByteArray &QByteArray::assign(QByteArrayView v)
{
- if (pos < 0 || len <= 0 || arr == nullptr)
- return *ba;
-
- int oldsize = ba->size();
- ba->resize(qMax(pos, oldsize) + len);
- char *dst = ba->data();
- if (pos > oldsize)
- ::memset(dst + oldsize, 0x20, pos - oldsize);
- else
- ::memmove(dst + pos + len, dst + pos, oldsize - pos);
- memcpy(dst + pos, arr, len);
- return *ba;
+ const auto len = v.size();
+
+ if (len <= capacity() && isDetached()) {
+ const auto offset = d.freeSpaceAtBegin();
+ if (offset)
+ d.setBegin(d.begin() - offset);
+ std::memcpy(d.begin(), v.data(), len);
+ d.size = len;
+ d.data()[d.size] = '\0';
+ } else {
+ *this = v.toByteArray();
+ }
+ return *this;
}
/*!
- Inserts the byte array \a ba at index position \a i and returns a
+ Inserts \a data at index position \a i and returns a
reference to this byte array.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 17
+ \since 6.0
+
+ For large byte arrays, this operation can be slow (\l{linear time}),
+ because it requires moving all the bytes at indexes \a i and
+ above by at least one position further in memory.
+
+//! [array-grow-at-insertion]
+ This array grows to accommodate the insertion. If \a i is beyond
+ the end of the array, the array is first extended with space characters
+ to reach this \a i.
+//! [array-grow-at-insertion]
\sa append(), prepend(), replace(), remove()
*/
-
-QByteArray &QByteArray::insert(int i, const QByteArray &ba)
+QByteArray &QByteArray::insert(qsizetype i, QByteArrayView data)
{
- QByteArray copy(ba);
- return qbytearray_insert(this, i, copy.constData(), copy.size());
+ const char *str = data.data();
+ qsizetype size = data.size();
+ if (i < 0 || size <= 0)
+ return *this;
+
+ // handle this specially, as QArrayDataOps::insert() doesn't handle out of
+ // bounds positions
+ if (i >= d->size) {
+ // In case when data points into the range or is == *this, we need to
+ // defer a call to free() so that it comes after we copied the data from
+ // the old memory:
+ DataPointer detached{}; // construction is free
+ d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + size, &str, &detached);
+ Q_CHECK_PTR(d.data());
+ d->copyAppend(i - d->size, ' ');
+ d->copyAppend(str, str + size);
+ d.data()[d.size] = '\0';
+ return *this;
+ }
+
+ if (!d->needsDetach() && QtPrivate::q_points_into_range(str, d)) {
+ QVarLengthArray a(str, str + size);
+ return insert(i, a);
+ }
+
+ d->insert(i, str, size);
+ d.data()[d.size] = '\0';
+ return *this;
}
/*!
- \overload
+ \fn QByteArray &QByteArray::insert(qsizetype i, const QByteArray &data)
+ Inserts \a data at index position \a i and returns a
+ reference to this byte array.
- Inserts the '\\0'-terminated string \a str at position \a i in the byte
- array.
+ \include qbytearray.cpp array-grow-at-insertion
- If \a i is greater than size(), the array is first extended using
- resize().
+ \sa append(), prepend(), replace(), remove()
*/
-QByteArray &QByteArray::insert(int i, const char *str)
-{
- return qbytearray_insert(this, i, str, qstrlen(str));
-}
+/*!
+ \fn QByteArray &QByteArray::insert(qsizetype i, const char *s)
+ Inserts \a s at index position \a i and returns a
+ reference to this byte array.
+
+ \include qbytearray.cpp array-grow-at-insertion
+
+ The function is equivalent to \c{insert(i, QByteArrayView(s))}
+
+ \sa append(), prepend(), replace(), remove()
+*/
/*!
+ \fn QByteArray &QByteArray::insert(qsizetype i, const char *data, qsizetype len)
\overload
\since 4.6
- Inserts \a len bytes, starting at \a str, at position \a i in the byte
+ Inserts \a len bytes, starting at \a data, at position \a i in the byte
array.
- If \a i is greater than size(), the array is first extended using
- resize().
+ \include qbytearray.cpp array-grow-at-insertion
*/
-QByteArray &QByteArray::insert(int i, const char *str, int len)
-{
- return qbytearray_insert(this, i, str, len);
-}
-
/*!
+ \fn QByteArray &QByteArray::insert(qsizetype i, char ch)
\overload
- Inserts byte \a ch at index position \a i in the byte array. If \a i is
- greater than size(), the array is first extended using resize().
-*/
+ Inserts byte \a ch at index position \a i in the byte array.
-QByteArray &QByteArray::insert(int i, char ch)
-{
- return qbytearray_insert(this, i, &ch, 1);
-}
+ \include qbytearray.cpp array-grow-at-insertion
+*/
-/*! \fn QByteArray &QByteArray::insert(int i, int count, char ch)
+/*! \fn QByteArray &QByteArray::insert(qsizetype i, qsizetype count, char ch)
\overload
\since 5.7
@@ -1992,22 +2317,26 @@ QByteArray &QByteArray::insert(int i, char ch)
Inserts \a count copies of byte \a ch at index position \a i in the byte
array.
- If \a i is greater than size(), the array is first extended using resize().
+ \include qbytearray.cpp array-grow-at-insertion
*/
-QByteArray &QByteArray::insert(int i, int count, char ch)
+QByteArray &QByteArray::insert(qsizetype i, qsizetype count, char ch)
{
if (i < 0 || count <= 0)
return *this;
- int oldsize = size();
- resize(qMax(i, oldsize) + count);
- char *dst = d.data();
- if (i > oldsize)
- ::memset(dst + oldsize, 0x20, i - oldsize);
- else if (i < oldsize)
- ::memmove(dst + i + count, dst + i, oldsize - i);
- ::memset(dst + i, ch, count);
+ if (i >= d->size) {
+ // handle this specially, as QArrayDataOps::insert() doesn't handle out of bounds positions
+ d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + count, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
+ d->copyAppend(i - d->size, ' ');
+ d->copyAppend(count, ch);
+ d.data()[d.size] = '\0';
+ return *this;
+ }
+
+ d->insert(i, count, ch);
+ d.data()[d.size] = '\0';
return *this;
}
@@ -2022,24 +2351,77 @@ QByteArray &QByteArray::insert(int i, int count, char ch)
Example:
\snippet code/src_corelib_text_qbytearray.cpp 18
- \sa insert(), replace()
+ Element removal will preserve the array's capacity and not reduce the
+ amount of allocated memory. To shed extra capacity and free as much memory
+ as possible, call squeeze() after the last change to the array's size.
+
+ \sa insert(), replace(), squeeze()
*/
-QByteArray &QByteArray::remove(int pos, int len)
+QByteArray &QByteArray::remove(qsizetype pos, qsizetype len)
{
- if (len <= 0 || uint(pos) >= uint(size()))
+ if (len <= 0 || pos < 0 || size_t(pos) >= size_t(size()))
return *this;
- detach();
- if (len >= size() - pos) {
- resize(pos);
+ if (pos + len > d->size)
+ len = d->size - pos;
+
+ auto begin = d.begin();
+ if (!d->isShared()) {
+ d->erase(begin + pos, len);
+ d.data()[d.size] = '\0';
} else {
- memmove(d.data() + pos, d.data() + pos + len, size() - pos - len);
- resize(size() - len);
+ QByteArray copy{size() - len, Qt::Uninitialized};
+ const auto toRemove_start = d.begin() + pos;
+ copy.d->copyRanges({{d.begin(), toRemove_start},
+ {toRemove_start + len, d.end()}});
+ swap(copy);
}
return *this;
}
/*!
+ \fn QByteArray &QByteArray::removeAt(qsizetype pos)
+
+ \since 6.5
+
+ Removes the character at index \a pos. If \a pos is out of bounds
+ (i.e. \a pos >= size()) this function does nothing.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::removeFirst()
+
+ \since 6.5
+
+ Removes the first character in this byte array. If the byte array is empty,
+ this function does nothing.
+
+ \sa remove()
+*/
+/*!
+ \fn QByteArray &QByteArray::removeLast()
+
+ \since 6.5
+
+ Removes the last character in this byte array. If the byte array is empty,
+ this function does nothing.
+
+ \sa remove()
+*/
+
+/*!
+ \fn template <typename Predicate> QByteArray &QByteArray::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all bytes for which the predicate \a pred returns true
+ from the byte array. Returns a reference to the byte array.
+
+ \sa remove()
+*/
+
+/*!
Replaces \a len bytes from index position \a pos with the byte
array \a after, and returns a reference to this byte array.
@@ -2049,35 +2431,27 @@ QByteArray &QByteArray::remove(int pos, int len)
\sa insert(), remove()
*/
-QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
+QByteArray &QByteArray::replace(qsizetype pos, qsizetype len, QByteArrayView after)
{
+ if (QtPrivate::q_points_into_range(after.data(), d)) {
+ QVarLengthArray copy(after.data(), after.data() + after.size());
+ return replace(pos, len, QByteArrayView{copy});
+ }
if (len == after.size() && (pos + len <= size())) {
- detach();
- memmove(d.data() + pos, after.data(), len*sizeof(char));
+ // same size: in-place replacement possible
+ if (len > 0) {
+ detach();
+ memcpy(d.data() + pos, after.data(), len*sizeof(char));
+ }
return *this;
} else {
- QByteArray copy(after);
// ### optimize me
remove(pos, len);
- return insert(pos, copy);
+ return insert(pos, after);
}
}
-/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after)
-
- \overload
-
- Replaces \a len bytes from index position \a pos with the
- '\\0'-terminated string \a after.
-
- Notice: this can change the length of the byte array.
-*/
-QByteArray &QByteArray::replace(int pos, int len, const char *after)
-{
- return replace(pos,len,after,qstrlen(after));
-}
-
-/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
+/*! \fn QByteArray &QByteArray::replace(qsizetype pos, qsizetype len, const char *after, qsizetype alen)
\overload
@@ -2086,83 +2460,51 @@ QByteArray &QByteArray::replace(int pos, int len, const char *after)
\since 4.7
*/
-QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
-{
- if (len == alen && (pos + len <= size())) {
- detach();
- memcpy(d.data() + pos, after, len*sizeof(char));
- return *this;
- } else {
- remove(pos, len);
- return qbytearray_insert(this, pos, after, alen);
- }
-}
-
-// ### optimize all other replace method, by offering
-// QByteArray::replace(const char *before, int blen, const char *after, int alen)
/*!
+ \fn QByteArray &QByteArray::replace(const char *before, qsizetype bsize, const char *after, qsizetype asize)
\overload
- Replaces every occurrence of the byte array \a before with the
- byte array \a after.
-
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 20
+ Replaces every occurrence of the \a bsize bytes starting at \a before with
+ the \a asize bytes starting at \a after. Since the sizes of the strings are
+ given by \a bsize and \a asize, they may contain '\\0' bytes and do not need
+ to be '\\0'-terminated.
*/
-QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &after)
-{
- return replace(before.constData(), before.size(), after.constData(), after.size());
-}
-
/*!
- \fn QByteArray &QByteArray::replace(const char *before, const QByteArray &after)
\overload
+ \since 6.0
- Replaces every occurrence of the '\\0'-terminated string \a before with the
+ Replaces every occurrence of the byte array \a before with the
byte array \a after.
-*/
-
-QByteArray &QByteArray::replace(const char *c, const QByteArray &after)
-{
- return replace(c, qstrlen(c), after.constData(), after.size());
-}
-/*!
- \fn QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
- \overload
-
- Replaces every occurrence of the \a bsize bytes starting at \a before with
- the \asize bytes starting at \a after. Since the sizes of the strings are
- given by \a bsize and \a asize, they may contain '\\0' bytes and do not need
- to be '\\0'-terminated.
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 20
*/
-QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
+QByteArray &QByteArray::replace(QByteArrayView before, QByteArrayView after)
{
- if (isNull() || (before == after && bsize == asize))
+ const char *b = before.data();
+ qsizetype bsize = before.size();
+ const char *a = after.data();
+ qsizetype asize = after.size();
+
+ if (isNull() || (b == a && bsize == asize))
return *this;
// protect against before or after being part of this
- const char *a = after;
- const char *b = before;
- if (after >= constBegin() && after < constEnd()) {
- char *copy = (char *)malloc(asize);
- Q_CHECK_PTR(copy);
- memcpy(copy, after, asize);
- a = copy;
+ if (QtPrivate::q_points_into_range(a, d)) {
+ QVarLengthArray copy(a, a + asize);
+ return replace(before, QByteArrayView{copy});
}
- if (before >= constBegin() && before < constEnd()) {
- char *copy = (char *)malloc(bsize);
- Q_CHECK_PTR(copy);
- memcpy(copy, before, bsize);
- b = copy;
+ if (QtPrivate::q_points_into_range(b, d)) {
+ QVarLengthArray copy(b, b + bsize);
+ return replace(QByteArrayView{copy}, after);
}
- QByteArrayMatcher matcher(before, bsize);
- int index = 0;
- int len = size();
+ QByteArrayMatcher matcher(b, bsize);
+ qsizetype index = 0;
+ qsizetype len = size();
char *d = data(); // detaches
if (bsize == asize) {
@@ -2173,12 +2515,12 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
}
}
} else if (asize < bsize) {
- uint to = 0;
- uint movestart = 0;
- uint num = 0;
+ size_t to = 0;
+ size_t movestart = 0;
+ size_t num = 0;
while ((index = matcher.indexIn(*this, index)) != -1) {
if (num) {
- int msize = index - movestart;
+ qsizetype msize = index - movestart;
if (msize > 0) {
memmove(d + to, d + movestart, msize);
to += msize;
@@ -2195,7 +2537,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
num++;
}
if (num) {
- int msize = len - movestart;
+ qsizetype msize = len - movestart;
if (msize > 0)
memmove(d + to, d + movestart, msize);
resize(len - num*(bsize-asize));
@@ -2204,8 +2546,8 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
// the most complex case. We don't want to lose performance by doing repeated
// copies and reallocs of the data.
while (index != -1) {
- uint indices[4096];
- uint pos = 0;
+ size_t indices[4096];
+ size_t pos = 0;
while(pos < 4095) {
index = matcher.indexIn(*this, index);
if (index == -1)
@@ -2220,12 +2562,12 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
break;
// we have a table of replacement positions, use them for fast replacing
- int adjust = pos*(asize-bsize);
+ qsizetype adjust = pos*(asize-bsize);
// index has to be adjusted in case we get back into the loop above.
if (index != -1)
index += adjust;
- int newlen = len + adjust;
- int moveend = len;
+ qsizetype newlen = len + adjust;
+ qsizetype moveend = len;
if (newlen > len) {
resize(newlen);
len = newlen;
@@ -2234,9 +2576,9 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
while(pos) {
pos--;
- int movestart = indices[pos] + bsize;
- int insertstart = indices[pos] + pos*(asize-bsize);
- int moveto = insertstart + asize;
+ qsizetype movestart = indices[pos] + bsize;
+ qsizetype insertstart = indices[pos] + pos*(asize-bsize);
+ qsizetype moveto = insertstart + asize;
memmove(d + moveto, d + movestart, (moveend - movestart));
if (asize)
memcpy(d + insertstart, a, asize);
@@ -2244,54 +2586,17 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
}
}
}
-
- if (a != after)
- ::free(const_cast<char *>(a));
- if (b != before)
- ::free(const_cast<char *>(b));
-
-
return *this;
}
-
-/*!
- \fn QByteArray &QByteArray::replace(const QByteArray &before, const char *after)
- \overload
-
- Replaces every occurrence of the byte in \a before with the '\\0'-terminated
- string \a after.
-*/
-
-/*! \fn QByteArray &QByteArray::replace(const char *before, const char *after)
-
- \overload
-
- Replaces every occurrence of the '\\0'-terminated string \a before with the
- '\\0'-terminated string \a after.
-*/
-
/*!
+ \fn QByteArray &QByteArray::replace(char before, QByteArrayView after)
\overload
Replaces every occurrence of the byte \a before with the byte array \a
after.
*/
-QByteArray &QByteArray::replace(char before, const QByteArray &after)
-{
- char b[2] = { before, '\0' };
- return replace(b, 1, after.constData(), after.size());
-}
-
-/*! \fn QByteArray &QByteArray::replace(char before, const char *after)
-
- \overload
-
- Replaces every occurrence of the byte \a before with the '\\0'-terminated
- string \a after.
-*/
-
/*!
\overload
@@ -2300,12 +2605,11 @@ QByteArray &QByteArray::replace(char before, const QByteArray &after)
QByteArray &QByteArray::replace(char before, char after)
{
- if (!isEmpty()) {
- char *i = data();
- char *e = i + size();
- for (; i != e; ++i)
- if (*i == before)
- * i = after;
+ if (before != after) {
+ if (const auto pos = indexOf(before); pos >= 0) {
+ const auto detachedData = data();
+ std::replace(detachedData + pos, detachedData + size(), before, after);
+ }
}
return *this;
}
@@ -2320,8 +2624,8 @@ QByteArray &QByteArray::replace(char before, char after)
QList<QByteArray> QByteArray::split(char sep) const
{
QList<QByteArray> list;
- int start = 0;
- int end;
+ qsizetype start = 0;
+ qsizetype end;
while ((end = indexOf(sep, start)) != -1) {
list.append(mid(start, end - start));
start = end + 1;
@@ -2341,7 +2645,7 @@ QList<QByteArray> QByteArray::split(char sep) const
\snippet code/src_corelib_text_qbytearray.cpp 49
*/
-QByteArray QByteArray::repeated(int times) const
+QByteArray QByteArray::repeated(qsizetype times) const
{
if (isEmpty())
return *this;
@@ -2352,7 +2656,7 @@ QByteArray QByteArray::repeated(int times) const
return QByteArray();
}
- const int resultSize = times * size();
+ const qsizetype resultSize = times * size();
QByteArray result;
result.reserve(resultSize);
@@ -2361,10 +2665,10 @@ QByteArray QByteArray::repeated(int times) const
memcpy(result.d.data(), data(), size());
- int sizeSoFar = size();
+ qsizetype sizeSoFar = size();
char *end = result.d.data() + sizeSoFar;
- const int halfResultSize = resultSize >> 1;
+ const qsizetype halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
memcpy(end, result.d.data(), sizeSoFar);
end += sizeSoFar;
@@ -2378,64 +2682,49 @@ QByteArray QByteArray::repeated(int times) const
#define REHASH(a) \
if (ol_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= (a) << ol_minus_1; \
+ hashHaystack -= std::size_t(a) << ol_minus_1; \
hashHaystack <<= 1
-/*!
- Returns the index position of the first occurrence of the byte
- array \a ba in this byte array, searching forward from index
- position \a from. Returns -1 if \a ba could not be found.
-
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 21
-
- \sa lastIndexOf(), contains(), count()
-*/
-
-int QByteArray::indexOf(const QByteArray &ba, int from) const
+qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
- const int ol = ba.size();
- if (ol == 0)
- return from;
+ const auto ol = needle.size();
+ const auto l = haystack.size();
+ if (ol == 0) {
+ if (from < 0)
+ return qMax(from + l, 0);
+ else
+ return from > l ? -1 : from;
+ }
+
if (ol == 1)
- return indexOf(ba[0], from);
+ return findByteArray(haystack, from, needle.front());
- const int l = size();
if (from > l || ol + from > l)
return -1;
- return static_cast<int>(qFindByteArray(data(), size(), from, ba.data(), ol));
+ return qFindByteArray(haystack.data(), haystack.size(), from, needle.data(), ol);
}
-/*! \fn int QByteArray::indexOf(const char *str, int from) const
-
- \overload
+/*! \fn qsizetype QByteArray::indexOf(QByteArrayView bv, qsizetype from) const
+ \since 6.0
- Returns the index position of the first occurrence of the '\\0'-terminated
- string \a str in the byte array, searching forward from index position \a
- from. Returns -1 if \a str could not be found.
-*/
-int QByteArray::indexOf(const char *c, int from) const
-{
- const int ol = qstrlen(c);
- if (ol == 1)
- return indexOf(*c, from);
+ Returns the index position of the start of the first occurrence of the
+ sequence of bytes viewed by \a bv in this byte array, searching forward
+ from index position \a from. Returns -1 if no match is found.
- const int l = size();
- if (from > l || ol + from > l)
- return -1;
- if (ol == 0)
- return from;
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 21
- return static_cast<int>(qFindByteArray(data(), size(), from, c, ol));
-}
+ \sa lastIndexOf(), contains(), count()
+*/
/*!
+ \fn qsizetype QByteArray::indexOf(char ch, qsizetype from) const
\overload
- Returns the index position of the first occurrence of the byte \a ch in the
- byte array, searching forward from index position \a from. Returns -1 if \a
- ch could not be found.
+ Returns the index position of the start of the first occurrence of the
+ byte \a ch in this byte array, searching forward from index position \a from.
+ Returns -1 if no match is found.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 22
@@ -2443,20 +2732,6 @@ int QByteArray::indexOf(const char *c, int from) const
\sa lastIndexOf(), contains()
*/
-int QByteArray::indexOf(char ch, int from) const
-{
- if (from < 0)
- from = qMax(from + size(), 0);
- if (from < size()) {
- const char *n = data() + from - 1;
- const char *e = end();
- while (++n != e)
- if (*n == ch)
- return n - data();
- }
- return -1;
-}
-
static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char *needle,
qsizetype ol, qsizetype from)
{
@@ -2491,53 +2766,90 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
}
-/*!
- \fn int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
+static inline qsizetype lastIndexOfCharHelper(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ if (haystack.size() == 0)
+ return -1;
+ if (from < 0)
+ from += haystack.size();
+ else if (from > haystack.size())
+ from = haystack.size() - 1;
+ if (from >= 0) {
+ const char *b = haystack.data();
+ const char *n = b + from + 1;
+ while (n-- != b) {
+ if (*n == needle)
+ return n - b;
+ }
+ }
+ return -1;
+}
- Returns the index position of the last occurrence of the byte array \a ba in
- this byte array, searching backward from index position \a from. If \a from
- is -1 (the default), the search starts at the last byte (at index size() -
- 1). Returns -1 if \a ba could not be found.
+qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ return lastIndexOfCharHelper(haystack, from, needle);
+}
+
+qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
+{
+ if (haystack.isEmpty()) {
+ if (needle.isEmpty() && from == 0)
+ return 0;
+ return -1;
+ }
+ const auto ol = needle.size();
+ if (ol == 1)
+ return lastIndexOfCharHelper(haystack, from, needle.front());
+
+ return lastIndexOfHelper(haystack.data(), haystack.size(), needle.data(), ol, from);
+}
+
+/*! \fn qsizetype QByteArray::lastIndexOf(QByteArrayView bv, qsizetype from) const
+ \since 6.0
+
+ Returns the index position of the start of the last occurrence of the
+ sequence of bytes viewed by \a bv in this byte array, searching backward
+ from index position \a from.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if no match is found.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 23
+ \note When searching for a 0-length \a bv, the match at the end of
+ the data is excluded from the search by a negative \a from, even
+ though \c{-1} is normally thought of as searching from the end of
+ the byte array: the match at the end is \e after the last character, so
+ it is excluded. To include such a final empty match, either give a
+ positive value for \a from or omit the \a from parameter entirely.
+
\sa indexOf(), contains(), count()
*/
-int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
-{
- const int ol = ba.size();
- if (ol == 1)
- return lastIndexOf(ba[0], from);
+/*! \fn qsizetype QByteArray::lastIndexOf(QByteArrayView bv) const
+ \since 6.2
+ \overload
- return lastIndexOfHelper(data(), size(), ba.data(), ol, from);
-}
+ Returns the index position of the start of the last occurrence of the
+ sequence of bytes viewed by \a bv in this byte array, searching backward
+ from the end of the byte array. Returns -1 if no match is found.
-/*! \fn int QByteArray::lastIndexOf(const char *str, int from) const
- \overload
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 23
- Returns the index position of the last occurrence of the '\\0'-terminated
- string \a str in the byte array, searching backward from index position \a
- from. If \a from is -1 (the default), the search starts at the last byte (at
- index size() - 1). Returns -1 if \a str could not be found.
+ \sa indexOf(), contains(), count()
*/
-int QByteArray::lastIndexOf(const char *str, int from) const
-{
- const int ol = qstrlen(str);
- if (ol == 1)
- return lastIndexOf(*str, from);
-
- return lastIndexOfHelper(data(), size(), str, ol, from);
-}
/*!
+ \fn qsizetype QByteArray::lastIndexOf(char ch, qsizetype from) const
\overload
- Returns the index position of the last occurrence of byte \a ch in the byte
- array, searching backward from index position \a from. If \a from is -1 (the
- default), the search starts at the last byte (at index size() - 1). Returns
- -1 if \a ch could not be found.
+ Returns the index position of the start of the last occurrence of byte \a ch
+ in this byte array, searching backward from index position \a from.
+ If \a from is -1 (the default), the search starts at the last byte
+ (at index size() - 1). Returns -1 if no match is found.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 24
@@ -2545,55 +2857,45 @@ int QByteArray::lastIndexOf(const char *str, int from) const
\sa indexOf(), contains()
*/
-int QByteArray::lastIndexOf(char ch, int from) const
+static inline qsizetype countCharHelper(QByteArrayView haystack, char needle) noexcept
{
- if (from < 0)
- from += size();
- else if (from > size())
- from = size()-1;
- if (from >= 0) {
- const char *b = data();
- const char *n = b + from + 1;
- while (n-- != b)
- if (*n == ch)
- return n - b;
+ qsizetype num = 0;
+ for (char ch : haystack) {
+ if (ch == needle)
+ ++num;
}
- return -1;
+ return num;
}
-/*!
- Returns the number of (potentially overlapping) occurrences of
- byte array \a ba in this byte array.
+qsizetype QtPrivate::count(QByteArrayView haystack, QByteArrayView needle) noexcept
+{
+ if (needle.size() == 0)
+ return haystack.size() + 1;
- \sa contains(), indexOf()
-*/
+ if (needle.size() == 1)
+ return countCharHelper(haystack, needle[0]);
-int QByteArray::count(const QByteArray &ba) const
-{
- int num = 0;
- int i = -1;
- if (size() > 500 && ba.size() > 5) {
- QByteArrayMatcher matcher(ba);
- while ((i = matcher.indexIn(*this, i + 1)) != -1)
+ qsizetype num = 0;
+ qsizetype i = -1;
+ if (haystack.size() > 500 && needle.size() > 5) {
+ QByteArrayMatcher matcher(needle);
+ while ((i = matcher.indexIn(haystack, i + 1)) != -1)
++num;
} else {
- while ((i = indexOf(ba, i + 1)) != -1)
+ while ((i = haystack.indexOf(needle, i + 1)) != -1)
++num;
}
return num;
}
-/*!
- \overload
+/*! \fn qsizetype QByteArray::count(QByteArrayView bv) const
+ \since 6.0
- Returns the number of (potentially overlapping) occurrences of
- '\\0'-terminated string \a str in the byte array.
-*/
+ Returns the number of (potentially overlapping) occurrences of the
+ sequence of bytes viewed by \a bv in this byte array.
-int QByteArray::count(const char *str) const
-{
- return count(fromRawData(str, qstrlen(str)));
-}
+ \sa contains(), indexOf()
+*/
/*!
\overload
@@ -2603,138 +2905,90 @@ int QByteArray::count(const char *str) const
\sa contains(), indexOf()
*/
-int QByteArray::count(char ch) const
+qsizetype QByteArray::count(char ch) const
{
- int num = 0;
- const char *i = end();
- const char *b = begin();
- while (i != b)
- if (*--i == ch)
- ++num;
- return num;
+ return countCharHelper(*this, ch);
}
-/*! \fn int QByteArray::count() const
-
+#if QT_DEPRECATED_SINCE(6, 4)
+/*! \fn qsizetype QByteArray::count() const
+ \deprecated [6.4] Use size() or length() instead.
\overload
Same as size().
*/
+#endif
/*!
- \fn int QByteArray::compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 5.12
+ \fn int QByteArray::compare(QByteArrayView bv, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.0
Returns an integer less than, equal to, or greater than zero depending on
whether this QByteArray sorts before, at the same position as, or after the
- '\\0'-terminated string \a c. The comparison is performed according to case
+ QByteArrayView \a bv. The comparison is performed according to case
sensitivity \a cs.
- \sa operator==
+ \sa operator==, {Character Case}
*/
-/*!
- \fn int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \overload
- \since 5.12
-
- Returns an integer less than, equal to, or greater than zero depending on
- whether this QByteArray sorts before, at the same position as, or after the
- QByteArray \a a. The comparison is performed according to case sensitivity
- \a cs.
+bool QtPrivate::startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
+{
+ if (haystack.size() < needle.size())
+ return false;
+ if (haystack.data() == needle.data() || needle.size() == 0)
+ return true;
+ return memcmp(haystack.data(), needle.data(), needle.size()) == 0;
+}
- \sa operator==
-*/
+/*! \fn bool QByteArray::startsWith(QByteArrayView bv) const
+ \since 6.0
-/*!
- Returns \c true if this byte array starts with byte array \a ba;
- otherwise returns \c false.
+ Returns \c true if this byte array starts with the sequence of bytes
+ viewed by \a bv; otherwise returns \c false.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 25
- \sa endsWith(), left()
+ \sa endsWith(), first()
*/
-bool QByteArray::startsWith(const QByteArray &ba) const
-{
- if (size() < ba.size())
- return false;
- if (data() == ba.data() || ba.size() == 0)
- return true;
- return memcmp(data(), ba.data(), ba.size()) == 0;
-}
-/*! \overload
-
- Returns \c true if this byte array starts with '\\0'-terminated string \a
- str; otherwise returns \c false.
-*/
-bool QByteArray::startsWith(const char *str) const
-{
- if (!str || !*str)
- return true;
- const int len = int(strlen(str));
- if (size() < len)
- return false;
- return qstrncmp(data(), str, len) == 0;
-}
-
-/*! \overload
+/*!
+ \fn bool QByteArray::startsWith(char ch) const
+ \overload
Returns \c true if this byte array starts with byte \a ch; otherwise returns
\c false.
*/
-bool QByteArray::startsWith(char ch) const
+
+bool QtPrivate::endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
{
- if (size() == 0)
+ if (haystack.size() < needle.size())
return false;
- return data()[0] == ch;
+ if (haystack.end() == needle.end() || needle.size() == 0)
+ return true;
+ return memcmp(haystack.end() - needle.size(), needle.data(), needle.size()) == 0;
}
/*!
- Returns \c true if this byte array ends with byte array \a ba;
- otherwise returns \c false.
+ \fn bool QByteArray::endsWith(QByteArrayView bv) const
+ \since 6.0
+
+ Returns \c true if this byte array ends with the sequence of bytes
+ viewed by \a bv; otherwise returns \c false.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 26
- \sa startsWith(), right()
-*/
-bool QByteArray::endsWith(const QByteArray &ba) const
-{
- if (size() < ba.size())
- return false;
- if (end() == ba.end() || ba.size() == 0)
- return true;
- return memcmp(end() - ba.size(), ba.data(), ba.size()) == 0;
-}
-
-/*! \overload
-
- Returns \c true if this byte array ends with '\\0'-terminated string \a str;
- otherwise returns \c false.
+ \sa startsWith(), last()
*/
-bool QByteArray::endsWith(const char *str) const
-{
- if (!str || !*str)
- return true;
- const int len = int(strlen(str));
- if (size() < len)
- return false;
- return qstrncmp(end() - len, str, len) == 0;
-}
-/*! \overload
+/*!
+ \fn bool QByteArray::endsWith(char ch) const
+ \overload
Returns \c true if this byte array ends with byte \a ch;
otherwise returns \c false.
*/
-bool QByteArray::endsWith(char ch) const
-{
- if (size() == 0)
- return false;
- return data()[size() - 1] == ch;
-}
/*
Returns true if \a c is an uppercase ASCII letter.
@@ -2744,125 +2998,108 @@ static constexpr inline bool isUpperCaseAscii(char c)
return c >= 'A' && c <= 'Z';
}
+/*
+ Returns true if \a c is an lowercase ASCII letter.
+ */
+static constexpr inline bool isLowerCaseAscii(char c)
+{
+ return c >= 'a' && c <= 'z';
+}
+
/*!
- Returns \c true if this byte array contains only ASCII uppercase letters,
- otherwise returns \c false.
+ Returns \c true if this byte array is uppercase, that is, if
+ it's identical to its toUpper() folding.
+
+ Note that this does \e not mean that the byte array only contains
+ uppercase letters; only that it contains no ASCII lowercase letters.
+
\since 5.12
\sa isLower(), toUpper()
*/
bool QByteArray::isUpper() const
{
- if (isEmpty())
- return false;
-
- const char *d = data();
-
- for (int i = 0, max = size(); i < max; ++i) {
- if (!isUpperCaseAscii(d[i]))
- return false;
- }
-
- return true;
-}
-
-/*
- Returns true if \a c is an lowercase ASCII letter.
- */
-static constexpr inline bool isLowerCaseAscii(char c)
-{
- return c >= 'a' && c <= 'z';
+ return std::none_of(begin(), end(), isLowerCaseAscii);
}
/*!
- Returns \c true if this byte array contains only lowercase ASCII letters,
- otherwise returns \c false.
+ Returns \c true if this byte array is lowercase, that is, if
+ it's identical to its toLower() folding.
+
+ Note that this does \e not mean that the byte array only contains
+ lowercase letters; only that it contains no ASCII uppercase letters.
+
\since 5.12
\sa isUpper(), toLower()
*/
bool QByteArray::isLower() const
{
- if (isEmpty())
- return false;
+ return std::none_of(begin(), end(), isUpperCaseAscii);
+}
- const char *d = data();
+/*!
+ \fn QByteArray::isValidUtf8() const
- for (int i = 0, max = size(); i < max; ++i) {
- if (!isLowerCaseAscii(d[i]))
- return false;
- }
+ Returns \c true if this byte array contains valid UTF-8 encoded data,
+ or \c false otherwise.
- return true;
-}
+ \since 6.3
+*/
/*!
+ \fn QByteArray QByteArray::left(qsizetype len) const &
+ \fn QByteArray QByteArray::left(qsizetype len) &&
+
Returns a byte array that contains the first \a len bytes of this byte
array.
- \obsolete Use first() instead in new code.
+ If you know that \a len cannot be out of bounds, use first() instead in new
+ code, because it is faster.
The entire byte array is returned if \a len is greater than
size().
Returns an empty QByteArray if \a len is smaller than 0.
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 27
-
\sa first(), last(), startsWith(), chopped(), chop(), truncate()
*/
-QByteArray QByteArray::left(int len) const
-{
- if (len >= size())
- return *this;
- if (len < 0)
- len = 0;
- return QByteArray(data(), len);
-}
-
/*!
+ \fn QByteArray QByteArray::right(qsizetype len) const &
+ \fn QByteArray QByteArray::right(qsizetype len) &&
+
Returns a byte array that contains the last \a len bytes of this byte array.
- \obsolete Use last() instead in new code.
+ If you know that \a len cannot be out of bounds, use last() instead in new
+ code, because it is faster.
The entire byte array is returned if \a len is greater than
size().
Returns an empty QByteArray if \a len is smaller than 0.
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 28
-
- \sa endsWith(), last(), first(), sliced(), chopped(), chop(), truncate()
+ \sa endsWith(), last(), first(), sliced(), chopped(), chop(), truncate(), slice()
*/
-QByteArray QByteArray::right(int len) const
-{
- if (len >= size())
- return *this;
- if (len < 0)
- len = 0;
- return QByteArray(end() - len, len);
-}
/*!
+ \fn QByteArray QByteArray::mid(qsizetype pos, qsizetype len) const &
+ \fn QByteArray QByteArray::mid(qsizetype pos, qsizetype len) &&
+
Returns a byte array containing \a len bytes from this byte array,
starting at position \a pos.
- \obsolete Use sliced() instead in new code.
+ If you know that \a pos and \a len cannot be out of bounds, use sliced()
+ instead in new code, because it is faster.
If \a len is -1 (the default), or \a pos + \a len >= size(),
returns a byte array containing all bytes starting at position \a
pos until the end of the byte array.
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 29
-
- \sa first(), last(), sliced(), chopped(), chop(), truncate()
+ \sa first(), last(), sliced(), chopped(), chop(), truncate(), slice()
*/
-QByteArray QByteArray::mid(int pos, int len) const
+QByteArray QByteArray::mid(qsizetype pos, qsizetype len) const &
{
qsizetype p = pos;
qsizetype l = len;
@@ -2872,43 +3109,68 @@ QByteArray QByteArray::mid(int pos, int len) const
return QByteArray();
case QContainerImplHelper::Empty:
{
- auto alloc = Data::allocate(0);
- QByteArray::DataPointer empty = { alloc.first, alloc.second, 0 };
- return QByteArray(empty);
+ return QByteArray(DataPointer::fromRawData(&_empty, 0));
}
case QContainerImplHelper::Full:
return *this;
case QContainerImplHelper::Subset:
- return QByteArray(d.data() + p, l);
+ return sliced(p, l);
}
- Q_UNREACHABLE();
- return QByteArray();
+ Q_UNREACHABLE_RETURN(QByteArray());
+}
+
+QByteArray QByteArray::mid(qsizetype pos, qsizetype len) &&
+{
+ qsizetype p = pos;
+ qsizetype l = len;
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &p, &l)) {
+ case QContainerImplHelper::Null:
+ return QByteArray();
+ case QContainerImplHelper::Empty:
+ resize(0); // keep capacity if we've reserve()d
+ [[fallthrough]];
+ case QContainerImplHelper::Full:
+ return std::move(*this);
+ case QContainerImplHelper::Subset:
+ return std::move(*this).sliced(p, l);
+ }
+ Q_UNREACHABLE_RETURN(QByteArray());
}
/*!
- \fn QByteArray QByteArray::first(qsizetype n) const
+ \fn QByteArray QByteArray::first(qsizetype n) const &
+ \fn QByteArray QByteArray::first(qsizetype n) &&
\since 6.0
Returns the first \a n bytes of the byte array.
\note The behavior is undefined when \a n < 0 or \a n > size().
- \sa last(), sliced(), from(), startsWith(), chopped(), chop(), truncate()
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 27
+
+ \sa last(), sliced(), startsWith(), chopped(), chop(), truncate(), slice()
*/
/*!
- \fn QByteArray QByteArray::last(qsizetype n) const
+ \fn QByteArray QByteArray::last(qsizetype n) const &
+ \fn QByteArray QByteArray::last(qsizetype n) &&
\since 6.0
Returns the last \a n bytes of the byte array.
\note The behavior is undefined when \a n < 0 or \a n > size().
- \sa first(), sliced(), from(), endsWith(), chopped(), chop(), truncate()
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 28
+
+ \sa first(), sliced(), endsWith(), chopped(), chop(), truncate(), slice()
*/
/*!
- \fn QByteArray QByteArray::sliced(qsizetype pos, qsizetype n) const
+ \fn QByteArray QByteArray::sliced(qsizetype pos, qsizetype n) const &
+ \fn QByteArray QByteArray::sliced(qsizetype pos, qsizetype n) &&
\since 6.0
Returns a byte array containing the \a n bytes of this object starting
@@ -2917,23 +3179,66 @@ QByteArray QByteArray::mid(int pos, int len) const
\note The behavior is undefined when \a pos < 0, \a n < 0,
or \a pos + \a n > size().
- \sa first(), last(), from(), chopped(), chop(), truncate()
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 29
+
+ \sa first(), last(), chopped(), chop(), truncate(), slice()
*/
+QByteArray QByteArray::sliced_helper(QByteArray &a, qsizetype pos, qsizetype n)
+{
+ if (n == 0)
+ return fromRawData(&_empty, 0);
+ DataPointer d = std::move(a.d).sliced(pos, n);
+ d.data()[n] = 0;
+ return QByteArray(std::move(d));
+}
/*!
- \fn QByteArray QByteArray::from(qsizetype pos) const
+ \fn QByteArray QByteArray::sliced(qsizetype pos) const &
+ \fn QByteArray QByteArray::sliced(qsizetype pos) &&
\since 6.0
+ \overload
Returns a byte array containing the bytes starting at position \a pos
in this object, and extending to the end of this object.
\note The behavior is undefined when \a pos < 0 or \a pos > size().
- \sa first(), last(), sliced(), chopped(), chop(), truncate()
+ \sa first(), last(), chopped(), chop(), truncate(), slice()
+*/
+
+/*!
+ \fn QByteArray &QByteArray::slice(qsizetype pos, qsizetype n)
+ \since 6.8
+
+ Modifies this byte array to start at position \a pos, extending for \a n
+ bytes, and returns a reference to this byte array.
+
+ \note The behavior is undefined if \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 57
+
+ \sa sliced(), first(), last(), chopped(), chop(), truncate()
*/
/*!
- \fn QByteArray::chopped(int len) const
+ \fn QByteArray &QByteArray::slice(qsizetype pos)
+ \since 6.8
+ \overload
+
+ Modifies this byte array to start at position \a pos, extending to its
+ end, and returns a reference to this byte array.
+
+ \note The behavior is undefined if \a pos < 0 or \a pos > size().
+
+ \sa sliced(), first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArray QByteArray::chopped(qsizetype len) const &
+ \fn QByteArray QByteArray::chopped(qsizetype len) &&
\since 5.10
Returns a byte array that contains the leftmost size() - \a len bytes of
@@ -2941,7 +3246,7 @@ QByteArray QByteArray::mid(int pos, int len) const
\note The behavior is undefined if \a len is negative or greater than size().
- \sa endsWith(), left(), right(), mid(), chop(), truncate()
+ \sa endsWith(), first(), last(), sliced(), chop(), truncate(), slice()
*/
/*!
@@ -2956,11 +3261,7 @@ QByteArray QByteArray::mid(int pos, int len) const
\sa isLower(), toUpper(), {Character Case}
*/
-// prevent the compiler from inlining the function in each of
-// toLower and toUpper when the only difference is the table being used
-// (even with constant propagation, there's no gain in performance).
template <typename T>
-Q_NEVER_INLINE
static QByteArray toCase_template(T &input, uchar (*lookup)(uchar))
{
// find the first bad character in input
@@ -3031,7 +3332,7 @@ void QByteArray::clear()
d.clear();
}
-#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+#if !defined(QT_NO_DATASTREAM)
/*! \relates QByteArray
@@ -3044,7 +3345,7 @@ void QByteArray::clear()
QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
{
if (ba.isNull() && out.version() >= 6) {
- out << (quint32)0xffffffff;
+ QDataStream::writeQSizeType(out, -1);
return out;
}
return out.writeBytes(ba.constData(), ba.size());
@@ -3061,16 +3362,24 @@ QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
QDataStream &operator>>(QDataStream &in, QByteArray &ba)
{
ba.clear();
- quint32 len;
- in >> len;
- if (len == 0xffffffff)
+
+ qint64 size = QDataStream::readQSizeType(in);
+ qsizetype len = size;
+ if (size != len || size < -1) {
+ ba.clear();
+ in.setStatus(QDataStream::SizeLimitExceeded);
+ return in;
+ }
+ if (len == -1) { // null byte-array
+ ba = QByteArray();
return in;
+ }
- const quint32 Step = 1024 * 1024;
- quint32 allocated = 0;
+ constexpr qsizetype Step = 1024 * 1024;
+ qsizetype allocated = 0;
do {
- int blockSize = qMin(Step, len - allocated);
+ qsizetype blockSize = qMin(Step, len - allocated);
ba.resize(allocated + blockSize);
if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) {
ba.clear();
@@ -3084,205 +3393,169 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
}
#endif // QT_NO_DATASTREAM
-/*! \fn bool operator==(const QByteArray &a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator==(const QByteArray &lhs, const QByteArray &rhs)
\overload
- Returns \c true if byte array \a a1 is equal to byte array \a a2;
+ Returns \c true if byte array \a lhs is equal to byte array \a rhs;
otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator==(const QByteArray &a1, const char *a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator==(const QByteArray &lhs, const char * const &rhs)
\overload
- Returns \c true if byte array \a a1 is equal to the '\\0'-terminated string
- \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is equal to the '\\0'-terminated string
+ \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator==(const char *a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator==(const char * const &lhs, const QByteArray &rhs)
\overload
- Returns \c true if '\\0'-terminated string \a a1 is equal to byte array \a
- a2; otherwise returns \c false.
+ Returns \c true if '\\0'-terminated string \a lhs is equal to byte array \a
+ rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator!=(const QByteArray &a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator!=(const QByteArray &lhs, const QByteArray &rhs)
\overload
- Returns \c true if byte array \a a1 is not equal to byte array \a a2;
+ Returns \c true if byte array \a lhs is not equal to byte array \a rhs;
otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator!=(const QByteArray &a1, const char *a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator!=(const QByteArray &lhs, const char * const &rhs)
\overload
- Returns \c true if byte array \a a1 is not equal to the '\\0'-terminated
- string \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is not equal to the '\\0'-terminated
+ string \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator!=(const char *a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator!=(const char * const &lhs, const QByteArray &rhs)
\overload
- Returns \c true if '\\0'-terminated string \a a1 is not equal to byte array
- \a a2; otherwise returns \c false.
+ Returns \c true if '\\0'-terminated string \a lhs is not equal to byte array
+ \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator<(const QByteArray &a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator<(const QByteArray &lhs, const QByteArray &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically less than byte array
- \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically less than byte array
+ \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn inline bool operator<(const QByteArray &a1, const char *a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator<(const QByteArray &lhs, const char * const &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically less than the
- '\\0'-terminated string \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically less than the
+ '\\0'-terminated string \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator<(const char *a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator<(const char * const &lhs, const QByteArray &rhs)
\overload
- Returns \c true if '\\0'-terminated string \a a1 is lexically less than byte
- array \a a2; otherwise returns \c false.
+ Returns \c true if '\\0'-terminated string \a lhs is lexically less than byte
+ array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator<=(const QByteArray &a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator<=(const QByteArray &lhs, const QByteArray &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically less than or equal
- to byte array \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically less than or equal
+ to byte array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator<=(const QByteArray &a1, const char *a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator<=(const QByteArray &lhs, const char * const &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically less than or equal to the
- '\\0'-terminated string \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically less than or equal to the
+ '\\0'-terminated string \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator<=(const char *a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator<=(const char * const &lhs, const QByteArray &rhs)
\overload
- Returns \c true if '\\0'-terminated string \a a1 is lexically less than or
- equal to byte array \a a2; otherwise returns \c false.
+ Returns \c true if '\\0'-terminated string \a lhs is lexically less than or
+ equal to byte array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator>(const QByteArray &a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator>(const QByteArray &lhs, const QByteArray &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically greater than byte
- array \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically greater than byte
+ array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator>(const QByteArray &a1, const char *a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator>(const QByteArray &lhs, const char * const &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically greater than the
- '\\0'-terminated string \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically greater than the
+ '\\0'-terminated string \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator>(const char *a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator>(const char * const &lhs, const QByteArray &rhs)
\overload
- Returns \c true if '\\0'-terminated string \a a1 is lexically greater than
- byte array \a a2; otherwise returns \c false.
+ Returns \c true if '\\0'-terminated string \a lhs is lexically greater than
+ byte array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator>=(const QByteArray &a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator>=(const QByteArray &lhs, const QByteArray &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically greater than or
- equal to byte array \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically greater than or
+ equal to byte array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator>=(const QByteArray &a1, const char *a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator>=(const QByteArray &lhs, const char * const &rhs)
\overload
- Returns \c true if byte array \a a1 is lexically greater than or equal to
- the '\\0'-terminated string \a a2; otherwise returns \c false.
+ Returns \c true if byte array \a lhs is lexically greater than or equal to
+ the '\\0'-terminated string \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn bool operator>=(const char *a1, const QByteArray &a2)
- \relates QByteArray
-
+/*! \fn bool QByteArray::operator>=(const char * const &lhs, const QByteArray &rhs)
\overload
- Returns \c true if '\\0'-terminated string \a a1 is lexically greater than
- or equal to byte array \a a2; otherwise returns \c false.
+ Returns \c true if '\\0'-terminated string \a lhs is lexically greater than
+ or equal to byte array \a rhs; otherwise returns \c false.
\sa QByteArray::compare()
*/
-/*! \fn const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
+/*! \fn QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
\relates QByteArray
Returns a byte array that is the result of concatenating byte
@@ -3291,7 +3564,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
\sa QByteArray::operator+=()
*/
-/*! \fn const QByteArray operator+(const QByteArray &a1, const char *a2)
+/*! \fn QByteArray operator+(const QByteArray &a1, const char *a2)
\relates QByteArray
\overload
@@ -3300,7 +3573,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
and '\\0'-terminated string \a a2.
*/
-/*! \fn const QByteArray operator+(const QByteArray &a1, char a2)
+/*! \fn QByteArray operator+(const QByteArray &a1, char a2)
\relates QByteArray
\overload
@@ -3309,7 +3582,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
array \a a1 and byte \a a2.
*/
-/*! \fn const QByteArray operator+(const char *a1, const QByteArray &a2)
+/*! \fn QByteArray operator+(const char *a1, const QByteArray &a2)
\relates QByteArray
\overload
@@ -3318,7 +3591,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
string \a a1 and byte array \a a2.
*/
-/*! \fn const QByteArray operator+(char a1, const QByteArray &a2)
+/*! \fn QByteArray operator+(char a1, const QByteArray &a2)
\relates QByteArray
\overload
@@ -3383,6 +3656,11 @@ QByteArray QByteArray::trimmed_helper(QByteArray &a)
return QStringAlgorithms<QByteArray>::trimmed_helper(a);
}
+QByteArrayView QtPrivate::trimmed(QByteArrayView view) noexcept
+{
+ const auto [start, stop] = QStringAlgorithms<QByteArrayView>::trimmed_helper_positions(view);
+ return QByteArrayView(start, stop);
+}
/*!
Returns a byte array of size \a width that contains this byte array padded
@@ -3402,11 +3680,11 @@ QByteArray QByteArray::trimmed_helper(QByteArray &a)
\sa rightJustified()
*/
-QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
+QByteArray QByteArray::leftJustified(qsizetype width, char fill, bool truncate) const
{
QByteArray result;
- int len = size();
- int padlen = width - len;
+ qsizetype len = size();
+ qsizetype padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
if (len)
@@ -3439,11 +3717,11 @@ QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
\sa leftJustified()
*/
-QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
+QByteArray QByteArray::rightJustified(qsizetype width, char fill, bool truncate) const
{
QByteArray result;
- int len = size();
- int padlen = width - len;
+ qsizetype len = size();
+ qsizetype padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
if (len)
@@ -3458,41 +3736,38 @@ QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
return result;
}
-bool QByteArray::isNull() const
+auto QtPrivate::toSignedInteger(QByteArrayView data, int base) -> ParsedNumber<qlonglong>
{
- return d->isNull();
-}
-
-static qlonglong toIntegral_helper(const char *data, bool *ok, int base, qlonglong)
-{
- return QLocaleData::bytearrayToLongLong(data, base, ok);
-}
+#if defined(QT_CHECK_RANGE)
+ if (base != 0 && (base < 2 || base > 36)) {
+ qWarning("QByteArray::toIntegral: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ if (data.isEmpty())
+ return {};
-static qulonglong toIntegral_helper(const char *data, bool *ok, int base, qulonglong)
-{
- return QLocaleData::bytearrayToUnsLongLong(data, base, ok);
+ const QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(data, base);
+ if (r.ok())
+ return ParsedNumber(r.result);
+ return {};
}
-template <typename T> static inline
-T toIntegral_helper(const char *data, bool *ok, int base)
+auto QtPrivate::toUnsignedInteger(QByteArrayView data, int base) -> ParsedNumber<qulonglong>
{
- using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
-
#if defined(QT_CHECK_RANGE)
if (base != 0 && (base < 2 || base > 36)) {
qWarning("QByteArray::toIntegral: Invalid base %d", base);
base = 10;
}
#endif
+ if (data.isEmpty())
+ return {};
- // we select the right overload by the last, unused parameter
- Int64 val = toIntegral_helper(data, ok, base, Int64());
- if (T(val) != val) {
- if (ok)
- *ok = false;
- val = 0;
- }
- return T(val);
+ const QSimpleParsedNumber r = QLocaleData::bytearrayToUnsLongLong(data, base);
+ if (r.ok())
+ return ParsedNumber(r.result);
+ return {};
}
/*!
@@ -3502,8 +3777,9 @@ T toIntegral_helper(const char *data, bool *ok, int base)
If \a base is 0, the base is determined automatically using the following
rules: If the byte array begins with "0x", it is assumed to be hexadecimal
- (base 16); otherwise, if it begins with "0", it is assumed to be octal (base
- 8); otherwise it is assumed to be decimal.
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3514,12 +3790,14 @@ T toIntegral_helper(const char *data, bool *ok, int base)
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
qlonglong QByteArray::toLongLong(bool *ok, int base) const
{
- return toIntegral_helper<qlonglong>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<qlonglong>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3529,8 +3807,9 @@ qlonglong QByteArray::toLongLong(bool *ok, int base) const
If \a base is 0, the base is determined automatically using the following
rules: If the byte array begins with "0x", it is assumed to be hexadecimal
- (base 16); otherwise, if it begins with "0", it is assumed to be octal (base
- 8); otherwise it is assumed to be decimal.
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3541,12 +3820,14 @@ qlonglong QByteArray::toLongLong(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
qulonglong QByteArray::toULongLong(bool *ok, int base) const
{
- return toIntegral_helper<qulonglong>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<qulonglong>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3556,8 +3837,9 @@ qulonglong QByteArray::toULongLong(bool *ok, int base) const
If \a base is 0, the base is determined automatically using the following
rules: If the byte array begins with "0x", it is assumed to be hexadecimal
- (base 16); otherwise, if it begins with "0", it is assumed to be octal (base
- 8); otherwise it is assumed to be decimal.
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3570,12 +3852,14 @@ qulonglong QByteArray::toULongLong(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
int QByteArray::toInt(bool *ok, int base) const
{
- return toIntegral_helper<int>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<int>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3585,8 +3869,9 @@ int QByteArray::toInt(bool *ok, int base) const
If \a base is 0, the base is determined automatically using the following
rules: If the byte array begins with "0x", it is assumed to be hexadecimal
- (base 16); otherwise, if it begins with "0", it is assumed to be octal (base
- 8); otherwise it is assumed to be decimal.
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3597,12 +3882,14 @@ int QByteArray::toInt(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
uint QByteArray::toUInt(bool *ok, int base) const
{
- return toIntegral_helper<uint>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<uint>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3614,8 +3901,9 @@ uint QByteArray::toUInt(bool *ok, int base) const
If \a base is 0, the base is determined automatically using the following
rules: If the byte array begins with "0x", it is assumed to be hexadecimal
- (base 16); otherwise, if it begins with "0", it is assumed to be octal (base
- 8); otherwise it is assumed to be decimal.
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3628,11 +3916,13 @@ uint QByteArray::toUInt(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
long QByteArray::toLong(bool *ok, int base) const
{
- return toIntegral_helper<long>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<long>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3644,8 +3934,9 @@ long QByteArray::toLong(bool *ok, int base) const
If \a base is 0, the base is determined automatically using the following
rules: If the byte array begins with "0x", it is assumed to be hexadecimal
- (base 16); otherwise, if it begins with "0", it is assumed to be octal (base
- 8); otherwise it is assumed to be decimal.
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3656,11 +3947,13 @@ long QByteArray::toLong(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
ulong QByteArray::toULong(bool *ok, int base) const
{
- return toIntegral_helper<ulong>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<ulong>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3669,9 +3962,10 @@ ulong QByteArray::toULong(bool *ok, int base) const
digits beyond 9; A is ten, B is eleven and so on.
If \a base is 0, the base is determined automatically using the following
- rules: If the byte array begins with "0x", it is assumed to be hexadecimal;
- otherwise, if it begins with "0", it is assumed to be octal; otherwise it is
- assumed to be decimal.
+ rules: If the byte array begins with "0x", it is assumed to be hexadecimal
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3682,12 +3976,14 @@ ulong QByteArray::toULong(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
short QByteArray::toShort(bool *ok, int base) const
{
- return toIntegral_helper<short>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<short>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
/*!
@@ -3696,9 +3992,10 @@ short QByteArray::toShort(bool *ok, int base) const
letters for digits beyond 9; A is ten, B is eleven and so on.
If \a base is 0, the base is determined automatically using the following
- rules: If the byte array begins with "0x", it is assumed to be hexadecimal;
- otherwise, if it begins with "0", it is assumed to be octal; otherwise it is
- assumed to be decimal.
+ rules: If the byte array begins with "0x", it is assumed to be hexadecimal
+ (base 16); otherwise, if it begins with "0b", it is assumed to be binary
+ (base 2); otherwise, if it begins with "0", it is assumed to be octal
+ (base 8); otherwise it is assumed to be decimal.
Returns 0 if the conversion fails.
@@ -3709,15 +4006,16 @@ short QByteArray::toShort(bool *ok, int base) const
regardless of the user's locale. Use QLocale to perform locale-aware
conversions between numbers and strings.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number()
*/
ushort QByteArray::toUShort(bool *ok, int base) const
{
- return toIntegral_helper<ushort>(nulTerminated().constData(), ok, base);
+ return QtPrivate::toIntegral<ushort>(qToByteArrayViewIgnoringNull(*this), ok, base);
}
-
/*!
Returns the byte array converted to a \c double value.
@@ -3745,13 +4043,16 @@ ushort QByteArray::toUShort(bool *ok, int base) const
double QByteArray::toDouble(bool *ok) const
{
- bool nonNullOk = false;
- int processed = 0;
- double d = qt_asciiToDouble(constData(), size(),
- nonNullOk, processed, WhitespacesAllowed);
- if (ok)
- *ok = nonNullOk;
- return d;
+ return QByteArrayView(*this).toDouble(ok);
+}
+
+auto QtPrivate::toDouble(QByteArrayView a) noexcept -> ParsedNumber<double>
+{
+ auto r = qt_asciiToDouble(a.data(), a.size(), WhitespacesAllowed);
+ if (r.ok())
+ return ParsedNumber{r.result};
+ else
+ return {};
}
/*!
@@ -3784,6 +4085,17 @@ float QByteArray::toFloat(bool *ok) const
return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
}
+auto QtPrivate::toFloat(QByteArrayView a) noexcept -> ParsedNumber<float>
+{
+ if (const auto r = toDouble(a)) {
+ bool ok = true;
+ const auto f = QLocaleData::convertDoubleToFloat(*r, &ok);
+ if (ok)
+ return ParsedNumber(f);
+ }
+ return {};
+}
+
/*!
\since 5.2
@@ -3797,27 +4109,29 @@ float QByteArray::toFloat(bool *ok) const
*/
QByteArray QByteArray::toBase64(Base64Options options) const
{
- const char alphabet_base64[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
- "ghijklmn" "opqrstuv" "wxyz0123" "456789+/";
- const char alphabet_base64url[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
- "ghijklmn" "opqrstuv" "wxyz0123" "456789-_";
+ constexpr char alphabet_base64[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
+ "ghijklmn" "opqrstuv" "wxyz0123" "456789+/";
+ constexpr char alphabet_base64url[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
+ "ghijklmn" "opqrstuv" "wxyz0123" "456789-_";
const char *const alphabet = options & Base64UrlEncoding ? alphabet_base64url : alphabet_base64;
- const char padchar = '=';
- int padlen = 0;
+ constexpr char padchar = '=';
+ qsizetype padlen = 0;
- QByteArray tmp((size() + 2) / 3 * 4, Qt::Uninitialized);
+ const qsizetype sz = size();
- int i = 0;
+ QByteArray tmp((sz + 2) / 3 * 4, Qt::Uninitialized);
+
+ qsizetype i = 0;
char *out = tmp.data();
- while (i < size()) {
+ while (i < sz) {
// encode 3 bytes at a time
int chunk = 0;
chunk |= int(uchar(data()[i++])) << 16;
- if (i == size()) {
+ if (i == sz) {
padlen = 2;
} else {
chunk |= int(uchar(data()[i++])) << 8;
- if (i == size())
+ if (i == sz)
padlen = 1;
else
chunk |= int(uchar(data()[i++]));
@@ -3852,10 +4166,12 @@ QByteArray QByteArray::toBase64(Base64Options options) const
/*!
\fn QByteArray &QByteArray::setNum(int n, int base)
- Sets the byte array to the printed value of \a n in base \a base (ten by
- default) and returns a reference to the byte array. Bases 2 through 36 are
+ Represent the whole number \a n as text.
+
+ Sets this byte array to a string representing \a n in base \a base (ten by
+ default) and returns a reference to this byte array. Bases 2 through 36 are
supported, using letters for digits beyond 9; A is ten, B is eleven and so
- on. For bases other than ten, n is treated as an unsigned integer.
+ on.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 40
@@ -3910,7 +4226,7 @@ static char *qulltoa2(char *p, qulonglong n, int base)
base = 10;
}
#endif
- const char b = 'a' - 10;
+ constexpr char b = 'a' - 10;
do {
const int c = n % base;
n /= base;
@@ -3927,11 +4243,12 @@ static char *qulltoa2(char *p, qulonglong n, int base)
*/
QByteArray &QByteArray::setNum(qlonglong n, int base)
{
- const int buffsize = 66; // big enough for MAX_ULLONG in base 2
+ constexpr int buffsize = 66; // big enough for MAX_ULLONG in base 2
char buff[buffsize];
char *p;
- if (n < 0 && base == 10) {
+ if (n < 0) {
+ // Take care to avoid overflow on negating min value:
p = qulltoa2(buff + buffsize, qulonglong(-(1 + n)) + 1, base);
*--p = '-';
} else {
@@ -3951,7 +4268,7 @@ QByteArray &QByteArray::setNum(qlonglong n, int base)
QByteArray &QByteArray::setNum(qulonglong n, int base)
{
- const int buffsize = 66; // big enough for MAX_ULLONG in base 2
+ constexpr int buffsize = 66; // big enough for MAX_ULLONG in base 2
char buff[buffsize];
char *p = qulltoa2(buff + buffsize, n, base);
@@ -3963,82 +4280,39 @@ QByteArray &QByteArray::setNum(qulonglong n, int base)
/*!
\overload
- Sets the byte array to the printed value of \a n, formatted in format
- \a f with precision \a prec, and returns a reference to the
- byte array.
-
- The format \a f can be any of the following:
-
- \table
- \header \li Format \li Meaning
- \row \li \c e \li format as [-]9.9e[+|-]999
- \row \li \c E \li format as [-]9.9E[+|-]999
- \row \li \c f \li format as [-]9.9
- \row \li \c g \li use \c e or \c f format, whichever is the most concise
- \row \li \c G \li use \c E or \c f format, whichever is the most concise
- \endtable
+ Represent the floating-point number \a n as text.
- With 'e', 'E', and 'f', \a prec is the number of digits after the
- decimal point. With 'g' and 'G', \a prec is the maximum number of
- significant digits (trailing zeroes are omitted).
+ Sets this byte array to a string representing \a n, with a given \a format
+ and \a precision (with the same meanings as for \l {QString::number(double,
+ char, int)}), and returns a reference to this byte array.
- \note The format of the number is not localized; the default C locale is
- used regardless of the user's locale. Use QLocale to perform locale-aware
- conversions between numbers and strings.
-
- \sa toDouble()
+ \sa toDouble(), QLocale::FloatingPointPrecisionOption
*/
-QByteArray &QByteArray::setNum(double n, char f, int prec)
+QByteArray &QByteArray::setNum(double n, char format, int precision)
{
- QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
- uint flags = QLocaleData::ZeroPadExponent;
-
- char lower = asciiLower(uchar(f));
- if (f != lower)
- flags |= QLocaleData::CapitalEorX;
- f = lower;
-
- switch (f) {
- case 'f':
- form = QLocaleData::DFDecimal;
- break;
- case 'e':
- form = QLocaleData::DFExponent;
- break;
- case 'g':
- form = QLocaleData::DFSignificantDigits;
- break;
- default:
-#if defined(QT_CHECK_RANGE)
- qWarning("QByteArray::setNum: Invalid format char '%c'", f);
-#endif
- break;
- }
-
- *this = QLocaleData::c()->doubleToString(n, prec, form, -1, flags).toUtf8();
- return *this;
+ return *this = QByteArray::number(n, format, precision);
}
/*!
- \fn QByteArray &QByteArray::setNum(float n, char f, int prec)
+ \fn QByteArray &QByteArray::setNum(float n, char format, int precision)
\overload
- Sets the byte array to the printed value of \a n, formatted in format
- \a f with precision \a prec, and returns a reference to the
- byte array.
+ Represent the floating-point number \a n as text.
- \note The format of the number is not localized; the default C locale is
- used regardless of the user's locale. Use QLocale to perform locale-aware
- conversions between numbers and strings.
+ Sets this byte array to a string representing \a n, with a given \a format
+ and \a precision (with the same meanings as for \l {QString::number(double,
+ char, int)}), and returns a reference to this byte array.
\sa toFloat()
*/
/*!
- Returns a byte array containing the printed value of the number \a n to base
- \a base (ten by default). Bases 2 through 36 are supported, using letters
- for digits beyond 9: A is ten, B is eleven and so on.
+ Returns a byte-array representing the whole number \a n as text.
+
+ Returns a byte array containing a string representing \a n, using the
+ specified \a base (ten by default). Bases 2 through 36 are supported, using
+ letters for digits beyond 9: A is ten, B is eleven and so on.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 41
@@ -4118,42 +4392,43 @@ QByteArray QByteArray::number(qulonglong n, int base)
/*!
\overload
+ Returns a byte-array representing the floating-point number \a n as text.
- Returns a byte array that contains the printed value of \a n,
- formatted in format \a f with precision \a prec.
-
- Argument \a n is formatted according to the \a f format specified,
- which is \c g by default, and can be any of the following:
-
- \table
- \header \li Format \li Meaning
- \row \li \c e \li format as [-]9.9e[+|-]999
- \row \li \c E \li format as [-]9.9E[+|-]999
- \row \li \c f \li format as [-]9.9
- \row \li \c g \li use \c e or \c f format, whichever is the most concise
- \row \li \c G \li use \c E or \c f format, whichever is the most concise
- \endtable
-
- With 'e', 'E', and 'f', \a prec is the number of digits after the
- decimal point. With 'g' and 'G', \a prec is the maximum number of
- significant digits (trailing zeroes are omitted).
+ Returns a byte array containing a string representing \a n, with a given \a
+ format and \a precision, with the same meanings as for \l
+ {QString::number(double, char, int)}. For example:
\snippet code/src_corelib_text_qbytearray.cpp 42
- \note The format of the number is not localized; the default C locale is
- used regardless of the user's locale. Use QLocale to perform locale-aware
- conversions between numbers and strings.
-
- \sa toDouble()
+ \sa toDouble(), QLocale::FloatingPointPrecisionOption
*/
-QByteArray QByteArray::number(double n, char f, int prec)
+QByteArray QByteArray::number(double n, char format, int precision)
{
- QByteArray s;
- s.setNum(n, f, prec);
- return s;
+ QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
+
+ switch (QtMiscUtils::toAsciiLower(format)) {
+ case 'f':
+ form = QLocaleData::DFDecimal;
+ break;
+ case 'e':
+ form = QLocaleData::DFExponent;
+ break;
+ case 'g':
+ form = QLocaleData::DFSignificantDigits;
+ break;
+ default:
+#if defined(QT_CHECK_RANGE)
+ qWarning("QByteArray::setNum: Invalid format char '%c'", format);
+#endif
+ break;
+ }
+
+ return qdtoAscii(n, form, precision, isUpperCaseAscii(format));
}
/*!
+ \fn QByteArray QByteArray::fromRawData(const char *data, qsizetype size) constexpr
+
Constructs a QByteArray that uses the first \a size bytes of the
\a data array. The bytes are \e not copied. The QByteArray will
contain the \a data pointer. The caller guarantees that \a data
@@ -4187,18 +4462,6 @@ QByteArray QByteArray::number(double n, char f, int prec)
\sa setRawData(), data(), constData()
*/
-QByteArray QByteArray::fromRawData(const char *data, int size)
-{
- QByteArray::DataPointer x;
- if (!data) {
- } else if (!size) {
- x = DataPointer(Data::allocate(0), 0);
- } else {
- x = Data::fromRawData(data, size);
- }
- return QByteArray(x);
-}
-
/*!
\since 4.7
@@ -4213,17 +4476,12 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
\sa fromRawData(), data(), constData()
*/
-QByteArray &QByteArray::setRawData(const char *data, uint size)
+QByteArray &QByteArray::setRawData(const char *data, qsizetype size)
{
- if (!data || !size) {
+ if (!data || !size)
clear();
- }
-// else if (d->isShared() || (d->flags() & Data::RawDataType) == 0) {
+ else
*this = fromRawData(data, size);
-// } else {
-// d.size = size;
-// d.data() = const_cast<char *>(data);
-// }
return *this;
}
@@ -4338,7 +4596,7 @@ QByteArray::FromBase64Result QByteArray::fromBase64Encoding(QByteArray &&base64,
base64.size(),
base64.data(), // in-place
options);
- base64.truncate(int(base64result.decodedLength));
+ base64.truncate(base64result.decodedLength);
return { std::move(base64), base64result.status };
}
@@ -4354,7 +4612,7 @@ QByteArray::FromBase64Result QByteArray::fromBase64Encoding(const QByteArray &ba
base64Size,
const_cast<char *>(result.constData()),
options);
- result.truncate(int(base64result.decodedLength));
+ result.truncate(base64result.decodedLength);
return { std::move(result), base64result.status };
}
@@ -4390,9 +4648,9 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64, Base64Options option
}
/*!
- Returns a decoded copy of the hex encoded array \a hexEncoded. Input is not checked
- for validity; invalid characters in the input are skipped, enabling the
- decoding process to continue with subsequent characters.
+ Returns a decoded copy of the hex encoded array \a hexEncoded. Input is not
+ checked for validity; invalid characters in the input are skipped, enabling
+ the decoding process to continue with subsequent characters.
For example:
@@ -4406,7 +4664,7 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
uchar *result = (uchar *)res.data() + res.size();
bool odd_digit = true;
- for (int i = hexEncoded.size() - 1; i >= 0; --i) {
+ for (qsizetype i = hexEncoded.size() - 1; i >= 0; --i) {
uchar ch = uchar(hexEncoded.at(i));
int tmp = QtMiscUtils::fromHex(ch);
if (tmp == -1)
@@ -4425,10 +4683,13 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded)
return res;
}
-/*! Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and
- the letters a-f.
+/*!
+ Returns a hex encoded copy of the byte array.
+
+ The hex encoding uses the numbers 0-9 and the letters a-f.
- If \a separator is not '\0', the separator character is inserted between the hex bytes.
+ If \a separator is not '\0', the separator character is inserted between
+ the hex bytes.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 50
@@ -4441,11 +4702,11 @@ QByteArray QByteArray::toHex(char separator) const
if (isEmpty())
return QByteArray();
- const int length = separator ? (size() * 3 - 1) : (size() * 2);
+ const qsizetype length = separator ? (size() * 3 - 1) : (size() * 2);
QByteArray hex(length, Qt::Uninitialized);
char *hexData = hex.data();
const uchar *data = (const uchar *)this->data();
- for (int i = 0, o = 0; i < size(); ++i) {
+ for (qsizetype i = 0, o = 0; i < size(); ++i) {
hexData[o++] = QtMiscUtils::toHexLower(data[i] >> 4);
hexData[o++] = QtMiscUtils::toHexLower(data[i] & 0xf);
@@ -4463,9 +4724,9 @@ static void q_fromPercentEncoding(QByteArray *ba, char percent)
char *data = ba->data();
const char *inputPtr = data;
- int i = 0;
- int len = ba->count();
- int outlen = 0;
+ qsizetype i = 0;
+ qsizetype len = ba->size();
+ qsizetype outlen = 0;
int a, b;
char c;
while (i < len) {
@@ -4495,20 +4756,17 @@ static void q_fromPercentEncoding(QByteArray *ba, char percent)
ba->truncate(outlen);
}
-void q_fromPercentEncoding(QByteArray *ba)
-{
- q_fromPercentEncoding(ba, '%');
-}
-
/*!
- \since 4.4
+ \since 6.4
- Returns a decoded copy of the URI/URL-style percent-encoded \a input.
- The \a percent parameter allows you to replace the '%' character for
- another (for instance, '_' or '=').
+ Decodes URI/URL-style percent-encoding.
+
+ Returns a byte array containing the decoded text. The \a percent parameter
+ allows use of a different character than '%' (for instance, '_' or '=') as
+ the escape character.
For example:
- \snippet code/src_corelib_text_qbytearray.cpp 51
+ \snippet code/src_corelib_text_qbytearray.cpp 54
\note Given invalid input (such as a string containing the sequence "%G5",
which is not a valid hexadecimal number) the output will be invalid as
@@ -4516,18 +4774,35 @@ void q_fromPercentEncoding(QByteArray *ba)
\sa toPercentEncoding(), QUrl::fromPercentEncoding()
*/
-QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent)
+QByteArray QByteArray::percentDecoded(char percent) const
{
- if (input.isNull())
- return QByteArray(); // preserve null
- if (input.isEmpty())
- return QByteArray(input.data(), 0);
+ if (isEmpty())
+ return *this; // Preserves isNull().
- QByteArray tmp = input;
+ QByteArray tmp = *this;
q_fromPercentEncoding(&tmp, percent);
return tmp;
}
+/*!
+ \since 4.4
+
+ Decodes \a input from URI/URL-style percent-encoding.
+
+ Returns a byte array containing the decoded text. The \a percent parameter
+ allows use of a different character than '%' (for instance, '_' or '=') as
+ the escape character. Equivalent to input.percentDecoded(percent).
+
+ For example:
+ \snippet code/src_corelib_text_qbytearray.cpp 51
+
+ \sa percentDecoded()
+*/
+QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent)
+{
+ return input.percentDecoded(percent);
+}
+
/*! \fn QByteArray QByteArray::fromStdString(const std::string &str)
\since 5.4
@@ -4535,6 +4810,10 @@ QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent
\sa toStdString(), QString::fromStdString()
*/
+QByteArray QByteArray::fromStdString(const std::string &s)
+{
+ return QByteArray(s.data(), qsizetype(s.size()));
+}
/*!
\fn std::string QByteArray::toStdString() const
@@ -4548,68 +4827,9 @@ QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent
\sa fromStdString(), QString::toStdString()
*/
-
-static inline bool q_strchr(const char str[], char chr)
+std::string QByteArray::toStdString() const
{
- if (!str) return false;
-
- const char *ptr = str;
- char c;
- while ((c = *ptr++))
- if (c == chr)
- return true;
- return false;
-}
-
-static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const char *alsoEncode, char percent)
-{
- if (ba->isEmpty())
- return;
-
- QByteArray input = *ba;
- int len = input.count();
- const char *inputData = input.constData();
- char *output = nullptr;
- int length = 0;
-
- for (int i = 0; i < len; ++i) {
- unsigned char c = *inputData++;
- if (((c >= 0x61 && c <= 0x7A) // ALPHA
- || (c >= 0x41 && c <= 0x5A) // ALPHA
- || (c >= 0x30 && c <= 0x39) // DIGIT
- || c == 0x2D // -
- || c == 0x2E // .
- || c == 0x5F // _
- || c == 0x7E // ~
- || q_strchr(dontEncode, c))
- && !q_strchr(alsoEncode, c)) {
- if (output)
- output[length] = c;
- ++length;
- } else {
- if (!output) {
- // detach now
- ba->resize(len*3); // worst case
- output = ba->data();
- }
- output[length++] = percent;
- output[length++] = QtMiscUtils::toHexUpper((c & 0xf0) >> 4);
- output[length++] = QtMiscUtils::toHexUpper(c & 0xf);
- }
- }
- if (output)
- ba->truncate(length);
-}
-
-void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include)
-{
- q_toPercentEncoding(ba, exclude, include, '%');
-}
-
-void q_normalizePercentEncoding(QByteArray *ba, const char *exclude)
-{
- q_fromPercentEncoding(ba, '%');
- q_toPercentEncoding(ba, exclude, nullptr, '%');
+ return std::string(data(), size_t(size()));
}
/*!
@@ -4644,23 +4864,100 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
if (isEmpty())
return QByteArray(data(), 0);
- QByteArray include2 = include;
- if (percent != '%') // the default
- if ((percent >= 0x61 && percent <= 0x7A) // ALPHA
- || (percent >= 0x41 && percent <= 0x5A) // ALPHA
- || (percent >= 0x30 && percent <= 0x39) // DIGIT
- || percent == 0x2D // -
- || percent == 0x2E // .
- || percent == 0x5F // _
- || percent == 0x7E) // ~
- include2 += percent;
+ const auto contains = [](const QByteArray &view, char c) {
+ // As view.contains(c), but optimised to bypass a lot of overhead:
+ return view.size() > 0 && memchr(view.data(), c, view.size()) != nullptr;
+ };
QByteArray result = *this;
- q_toPercentEncoding(&result, exclude.nulTerminated().constData(), include2.nulTerminated().constData(), percent);
+ char *output = nullptr;
+ qsizetype length = 0;
+
+ for (unsigned char c : *this) {
+ if (char(c) != percent
+ && ((c >= 0x61 && c <= 0x7A) // ALPHA
+ || (c >= 0x41 && c <= 0x5A) // ALPHA
+ || (c >= 0x30 && c <= 0x39) // DIGIT
+ || c == 0x2D // -
+ || c == 0x2E // .
+ || c == 0x5F // _
+ || c == 0x7E // ~
+ || contains(exclude, c))
+ && !contains(include, c)) {
+ if (output)
+ output[length] = c;
+ ++length;
+ } else {
+ if (!output) {
+ // detach now
+ result.resize(size() * 3); // worst case
+ output = result.data();
+ }
+ output[length++] = percent;
+ output[length++] = QtMiscUtils::toHexUpper((c & 0xf0) >> 4);
+ output[length++] = QtMiscUtils::toHexUpper(c & 0xf);
+ }
+ }
+ if (output)
+ result.truncate(length);
return result;
}
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+
+/*!
+ Constructs a new QByteArray containing a copy of the Uint8Array \a uint8array.
+
+ This function transfers data from a JavaScript data buffer - which
+ is not addressable from C++ code - to heap memory owned by a QByteArray.
+ The Uint8Array can be released once this function returns and a copy
+ has been made.
+
+ The \a uint8array argument must an emscripten::val referencing an Uint8Array
+ object, e.g. obtained from a global JavaScript variable:
+
+ \snippet code/src_corelib_text_qbytearray.cpp 55
+
+ This function returns a null QByteArray if the size of the Uint8Array
+ exceeds the maximum capacity of QByteArray, or if the \a uint8array
+ argument is not of the Uint8Array type.
+
+ \since 6.5
+ \ingroup platform-type-conversions
+
+ \sa toEcmaUint8Array()
+*/
+
+QByteArray QByteArray::fromEcmaUint8Array(emscripten::val uint8array)
+{
+ return qstdweb::Uint8Array(uint8array).copyToQByteArray();
+}
+
+/*!
+ Creates a Uint8Array from a QByteArray.
+
+ This function transfers data from heap memory owned by a QByteArray
+ to a JavaScript data buffer. The function allocates and copies into an
+ ArrayBuffer, and returns a Uint8Array view to that buffer.
+
+ The JavaScript objects own a copy of the data, and this
+ QByteArray can be safely deleted after the copy has been made.
+
+ \snippet code/src_corelib_text_qbytearray.cpp 56
+
+ \since 6.5
+ \ingroup platform-type-conversions
+
+ \sa toEcmaUint8Array()
+*/
+emscripten::val QByteArray::toEcmaUint8Array()
+{
+ return qstdweb::Uint8Array::copyFrom(*this).val();
+}
+
+#endif
+
/*! \typedef QByteArray::ConstIterator
\internal
*/
@@ -4757,6 +5054,57 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
\sa QStringLiteral
*/
+#if QT_DEPRECATED_SINCE(6, 8)
+/*!
+ \fn QtLiterals::operator""_qba(const char *str, size_t size)
+
+ \relates QByteArray
+ \since 6.2
+ \deprecated [6.8] Use \c _ba from Qt::StringLiterals namespace instead.
+
+ Literal operator that creates a QByteArray out of the first \a size characters
+ in the char string literal \a str.
+
+ The QByteArray is created at compile time, and the generated string data is stored
+ in the read-only segment of the compiled object file. Duplicate literals may share
+ the same read-only memory. This functionality is interchangeable with
+ QByteArrayLiteral, but saves typing when many string literals are present in the
+ code.
+
+ The following code creates a QByteArray:
+ \code
+ auto str = "hello"_qba;
+ \endcode
+
+ \sa QByteArrayLiteral, QtLiterals::operator""_qs(const char16_t *str, size_t size)
+*/
+#endif // QT_DEPRECATED_SINCE(6, 8)
+
+/*!
+ \fn Qt::Literals::StringLiterals::operator""_ba(const char *str, size_t size)
+
+ \relates QByteArray
+ \since 6.4
+
+ Literal operator that creates a QByteArray out of the first \a size characters
+ in the char string literal \a str.
+
+ The QByteArray is created at compile time, and the generated string data is stored
+ in the read-only segment of the compiled object file. Duplicate literals may share
+ the same read-only memory. This functionality is interchangeable with
+ QByteArrayLiteral, but saves typing when many string literals are present in the
+ code.
+
+ The following code creates a QByteArray:
+ \code
+ using namespace Qt::Literals::StringLiterals;
+
+ auto str = "hello"_ba;
+ \endcode
+
+ \sa Qt::Literals::StringLiterals
+*/
+
/*!
\class QByteArray::FromBase64Result
\inmodule QtCore
@@ -4809,8 +5157,7 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
*/
/*!
- \fn bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
- \relates QByteArray::FromBase64Result
+ \fn bool QByteArray::FromBase64Result::operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns \c true if \a lhs and \a rhs are equal, otherwise returns \c false.
@@ -4820,10 +5167,10 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
*/
/*!
- \fn bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
- \relates QByteArray::FromBase64Result
+ \fn bool QByteArray::FromBase64Result::operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
- Returns \c true if \a lhs and \a rhs are different, otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are different, otherwise
+ returns \c false.
*/
/*!
@@ -4837,4 +5184,27 @@ size_t qHash(const QByteArray::FromBase64Result &key, size_t seed) noexcept
return qHashMulti(seed, key.decoded, static_cast<int>(key.decodingStatus));
}
+/*! \fn template <typename T> qsizetype erase(QByteArray &ba, const T &t)
+ \relates QByteArray
+ \since 6.1
+
+ Removes all elements that compare equal to \a t from the
+ byte array \a ba. Returns the number of elements removed, if any.
+
+ \sa erase_if
+*/
+
+/*! \fn template <typename Predicate> qsizetype erase_if(QByteArray &ba, Predicate pred)
+ \relates QByteArray
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the byte array \a ba. Returns the number of elements removed, if
+ any.
+
+ \sa erase
+*/
+
QT_END_NAMESPACE
+
+#undef REHASH
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 5cbcecb956..3c8a3bba45 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBYTEARRAY_H
#define QBYTEARRAY_H
@@ -45,15 +9,22 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qarraydata.h>
#include <QtCore/qarraydatapointer.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qbytearrayalgorithms.h>
+#include <QtCore/qbytearrayview.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
#include <string>
#include <iterator>
+#ifndef QT5_NULL_STRINGS
+// Would ideally be off, but in practice breaks too much (Qt 6.0).
+#define QT5_NULL_STRINGS 1
+#endif
+
#ifdef truncate
#error qbytearray.h must be included before any header file that defines truncate
#endif
@@ -63,53 +34,15 @@ Q_FORWARD_DECLARE_CF_TYPE(CFData);
Q_FORWARD_DECLARE_OBJC_CLASS(NSData);
#endif
-QT_BEGIN_NAMESPACE
-
-
-/*****************************************************************************
- Safe and portable C string functions; extensions to standard string.h
- *****************************************************************************/
-
-Q_CORE_EXPORT char *qstrdup(const char *);
-
-inline uint qstrlen(const char *str)
-{ return str ? uint(strlen(str)) : 0; }
-
-inline uint qstrnlen(const char *str, uint maxlen)
-{
- uint length = 0;
- if (str) {
- while (length < maxlen && *str++)
- length++;
- }
- return length;
-}
-
-Q_CORE_EXPORT char *qstrcpy(char *dst, const char *src);
-Q_CORE_EXPORT char *qstrncpy(char *dst, const char *src, uint len);
-
-Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2);
-Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const QByteArray &str2);
-Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const char *str2);
-static inline int qstrcmp(const char *str1, const QByteArray &str2)
-{ return -qstrcmp(str2, str1); }
-
-inline int qstrncmp(const char *str1, const char *str2, uint len)
-{
- return (str1 && str2) ? strncmp(str1, str2, len)
- : (str1 ? 1 : (str2 ? -1 : 0));
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+namespace emscripten {
+ class val;
}
-Q_CORE_EXPORT int qstricmp(const char *, const char *);
-Q_CORE_EXPORT int qstrnicmp(const char *, const char *, uint len);
-Q_CORE_EXPORT int qstrnicmp(const char *, qsizetype, const char *, qsizetype = -1);
+#endif
-// implemented in qvsnprintf.cpp
-Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
-Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
+class tst_QByteArray;
-// qChecksum: Internet checksum
-Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len,
- Qt::ChecksumType standard = Qt::ChecksumIso3309);
+QT_BEGIN_NAMESPACE
class QString;
class QDataStream;
@@ -117,16 +50,7 @@ class QDataStream;
using QByteArrayData = QArrayDataPointer<char>;
# define QByteArrayLiteral(str) \
- ([]() -> QByteArray { \
- enum { Size = sizeof(str) - 1 }; \
- static const QArrayData qbytearray_literal = { \
- Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }; \
- QByteArrayData holder = { \
- static_cast<QTypedArrayData<char> *>(const_cast<QArrayData *>(&qbytearray_literal)), \
- const_cast<char *>(str), \
- Size }; \
- return QByteArray(holder); \
- }()) \
+ (QByteArray(QByteArrayData(nullptr, const_cast<char *>(str), sizeof(str) - 1))) \
/**/
class Q_CORE_EXPORT QByteArray
@@ -137,6 +61,12 @@ private:
typedef QTypedArrayData<char> Data;
DataPointer d;
+ static const char _empty;
+
+ friend class ::tst_QByteArray;
+
+ template <typename InputIterator>
+ using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>;
public:
enum Base64Option {
@@ -158,29 +88,31 @@ public:
IllegalPadding,
};
- inline QByteArray() noexcept;
- QByteArray(const char *, int size = -1);
- QByteArray(int size, char c);
- QByteArray(int size, Qt::Initialization);
+ inline constexpr QByteArray() noexcept;
+ QByteArray(const char *, qsizetype size = -1);
+ QByteArray(qsizetype size, char c);
+ QByteArray(qsizetype size, Qt::Initialization);
+ explicit QByteArray(QByteArrayView v) : QByteArray(v.data(), v.size()) {}
inline QByteArray(const QByteArray &) noexcept;
inline ~QByteArray();
QByteArray &operator=(const QByteArray &) noexcept;
QByteArray &operator=(const char *str);
inline QByteArray(QByteArray && other) noexcept
- { qSwap(d, other.d); }
- inline QByteArray &operator=(QByteArray &&other) noexcept
- { qSwap(d, other.d); return *this; }
+ = default;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QByteArray)
inline void swap(QByteArray &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
- inline bool isEmpty() const;
- void resize(int size);
+ bool isEmpty() const noexcept { return size() == 0; }
+ void resize(qsizetype size);
+ void resize(qsizetype size, char c);
+ void resizeForOverwrite(qsizetype size);
- QByteArray &fill(char c, int size = -1);
+ QByteArray &fill(char c, qsizetype size = -1);
- inline int capacity() const;
- inline void reserve(int size);
+ inline qsizetype capacity() const;
+ inline void reserve(qsizetype size);
inline void squeeze();
#ifndef QT_NO_CAST_FROM_BYTEARRAY
@@ -188,139 +120,255 @@ public:
inline operator const void *() const;
#endif
inline char *data();
- inline const char *data() const;
- inline const char *constData() const;
+ inline const char *data() const noexcept;
+ const char *constData() const noexcept { return data(); }
inline void detach();
inline bool isDetached() const;
- inline bool isSharedWith(const QByteArray &other) const
+ inline bool isSharedWith(const QByteArray &other) const noexcept
{ return data() == other.data() && size() == other.size(); }
void clear();
- inline char at(int i) const;
- inline char operator[](int i) const;
- Q_REQUIRED_RESULT inline char &operator[](int i);
- Q_REQUIRED_RESULT char front() const { return at(0); }
- Q_REQUIRED_RESULT inline char &front();
- Q_REQUIRED_RESULT char back() const { return at(size() - 1); }
- Q_REQUIRED_RESULT inline char &back();
-
- int indexOf(char c, int from = 0) const;
- int indexOf(const char *c, int from = 0) const;
- int indexOf(const QByteArray &a, int from = 0) const;
- int lastIndexOf(char c, int from = -1) const;
- int lastIndexOf(const char *c, int from = -1) const;
- int lastIndexOf(const QByteArray &a, int from = -1) const;
+ inline char at(qsizetype i) const;
+ inline char operator[](qsizetype i) const;
+ [[nodiscard]] inline char &operator[](qsizetype i);
+ [[nodiscard]] char front() const { return at(0); }
+ [[nodiscard]] inline char &front();
+ [[nodiscard]] char back() const { return at(size() - 1); }
+ [[nodiscard]] inline char &back();
+
+ QT_CORE_INLINE_SINCE(6, 7)
+ qsizetype indexOf(char c, qsizetype from = 0) const;
+ qsizetype indexOf(QByteArrayView bv, qsizetype from = 0) const
+ { return QtPrivate::findByteArray(qToByteArrayViewIgnoringNull(*this), from, bv); }
+
+ QT_CORE_INLINE_SINCE(6, 7)
+ qsizetype lastIndexOf(char c, qsizetype from = -1) const;
+ qsizetype lastIndexOf(QByteArrayView bv) const
+ { return lastIndexOf(bv, size()); }
+ qsizetype lastIndexOf(QByteArrayView bv, qsizetype from) const
+ { return QtPrivate::lastIndexOf(qToByteArrayViewIgnoringNull(*this), from, bv); }
inline bool contains(char c) const;
- inline bool contains(const char *a) const;
- inline bool contains(const QByteArray &a) const;
- int count(char c) const;
- int count(const char *a) const;
- int count(const QByteArray &a) const;
-
- inline int compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- inline int compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
-
- Q_REQUIRED_RESULT QByteArray left(int len) const;
- Q_REQUIRED_RESULT QByteArray right(int len) const;
- Q_REQUIRED_RESULT QByteArray mid(int index, int len = -1) const;
-
- Q_REQUIRED_RESULT QByteArray first(qsizetype n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QByteArray(data(), int(n)); }
- Q_REQUIRED_RESULT QByteArray last(qsizetype n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QByteArray(data() + size() - n, int(n)); }
- Q_REQUIRED_RESULT QByteArray from(qsizetype pos) const
- { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QByteArray(data() + pos, size() - int(pos)); }
- Q_REQUIRED_RESULT QByteArray sliced(qsizetype pos, qsizetype n) const
- { Q_ASSERT(pos >= 0); Q_ASSERT(n >= 0); Q_ASSERT(size_t(pos) + size_t(n) <= size_t(size())); return QByteArray(data() + pos, int(n)); }
- Q_REQUIRED_RESULT QByteArray chopped(int len) const
- { Q_ASSERT(len >= 0); Q_ASSERT(len <= size()); return first(size() - len); }
-
- bool startsWith(const QByteArray &a) const;
- bool startsWith(char c) const;
- bool startsWith(const char *c) const;
-
- bool endsWith(const QByteArray &a) const;
- bool endsWith(char c) const;
- bool endsWith(const char *c) const;
+ inline bool contains(QByteArrayView bv) const;
+ qsizetype count(char c) const;
+ qsizetype count(QByteArrayView bv) const
+ { return QtPrivate::count(qToByteArrayViewIgnoringNull(*this), bv); }
+
+ inline int compare(QByteArrayView a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ QByteArray left(qsizetype len) const;
+ QByteArray right(qsizetype len) const;
+ QByteArray mid(qsizetype index, qsizetype len = -1) const;
+ QByteArray first(qsizetype n) const;
+ QByteArray last(qsizetype n) const;
+ QByteArray sliced(qsizetype pos) const;
+ QByteArray sliced(qsizetype pos, qsizetype n) const;
+ QByteArray chopped(qsizetype len) const;
+#else
+ [[nodiscard]] QByteArray left(qsizetype n) const &
+ {
+ if (n >= size())
+ return *this;
+ return first(qMax(n, 0));
+ }
+ [[nodiscard]] QByteArray left(qsizetype n) &&
+ {
+ if (n >= size())
+ return std::move(*this);
+ return std::move(*this).first(qMax(n, 0));
+ }
+ [[nodiscard]] QByteArray right(qsizetype n) const &
+ {
+ if (n >= size())
+ return *this;
+ return last(qMax(n, 0));
+ }
+ [[nodiscard]] QByteArray right(qsizetype n) &&
+ {
+ if (n >= size())
+ return std::move(*this);
+ return std::move(*this).last(qMax(n, 0));
+ }
+ [[nodiscard]] QByteArray mid(qsizetype index, qsizetype len = -1) const &;
+ [[nodiscard]] QByteArray mid(qsizetype index, qsizetype len = -1) &&;
+
+ [[nodiscard]] QByteArray first(qsizetype n) const &
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] QByteArray last(qsizetype n) const &
+ { verify(0, n); return sliced(size() - n, n); }
+ [[nodiscard]] QByteArray sliced(qsizetype pos) const &
+ { verify(pos, 0); return sliced(pos, size() - pos); }
+ [[nodiscard]] QByteArray sliced(qsizetype pos, qsizetype n) const &
+ { verify(pos, n); return QByteArray(d.data() + pos, n); }
+ [[nodiscard]] QByteArray chopped(qsizetype len) const &
+ { verify(0, len); return sliced(0, size() - len); }
+
+ [[nodiscard]] QByteArray first(qsizetype n) &&
+ {
+ verify(0, n);
+ resize(n); // may detach and allocate memory
+ return std::move(*this);
+ }
+ [[nodiscard]] QByteArray last(qsizetype n) &&
+ { verify(0, n); return sliced_helper(*this, size() - n, n); }
+ [[nodiscard]] QByteArray sliced(qsizetype pos) &&
+ { verify(pos, 0); return sliced_helper(*this, pos, size() - pos); }
+ [[nodiscard]] QByteArray sliced(qsizetype pos, qsizetype n) &&
+ { verify(pos, n); return sliced_helper(*this, pos, n); }
+ [[nodiscard]] QByteArray chopped(qsizetype len) &&
+ { verify(0, len); return std::move(*this).first(size() - len); }
+#endif
+
+ bool startsWith(QByteArrayView bv) const
+ { return QtPrivate::startsWith(qToByteArrayViewIgnoringNull(*this), bv); }
+ bool startsWith(char c) const { return size() > 0 && front() == c; }
+
+ bool endsWith(char c) const { return size() > 0 && back() == c; }
+ bool endsWith(QByteArrayView bv) const
+ { return QtPrivate::endsWith(qToByteArrayViewIgnoringNull(*this), bv); }
bool isUpper() const;
bool isLower() const;
- void truncate(int pos);
- void chop(int n);
-
-#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
-# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_cpp_attribute(nodiscard)
- // required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
-# pragma push_macro("Q_REQUIRED_RESULT")
-# undef Q_REQUIRED_RESULT
-# define Q_REQUIRED_RESULT
-# define Q_REQUIRED_RESULT_pushed
-# endif
- Q_REQUIRED_RESULT QByteArray toLower() const &
+ [[nodiscard]] bool isValidUtf8() const noexcept
+ {
+ return QtPrivate::isValidUtf8(qToByteArrayViewIgnoringNull(*this));
+ }
+
+ void truncate(qsizetype pos);
+ void chop(qsizetype n);
+
+ QByteArray &slice(qsizetype pos)
+ { verify(pos, 0); return remove(0, pos); }
+ QByteArray &slice(qsizetype pos, qsizetype n)
+ {
+ verify(pos, n);
+ if (isNull())
+ return *this;
+ resize(pos + n);
+ return remove(0, pos);
+ }
+
+#if !defined(Q_QDOC)
+ [[nodiscard]] QByteArray toLower() const &
{ return toLower_helper(*this); }
- Q_REQUIRED_RESULT QByteArray toLower() &&
+ [[nodiscard]] QByteArray toLower() &&
{ return toLower_helper(*this); }
- Q_REQUIRED_RESULT QByteArray toUpper() const &
+ [[nodiscard]] QByteArray toUpper() const &
{ return toUpper_helper(*this); }
- Q_REQUIRED_RESULT QByteArray toUpper() &&
+ [[nodiscard]] QByteArray toUpper() &&
{ return toUpper_helper(*this); }
- Q_REQUIRED_RESULT QByteArray trimmed() const &
+ [[nodiscard]] QByteArray trimmed() const &
{ return trimmed_helper(*this); }
- Q_REQUIRED_RESULT QByteArray trimmed() &&
+ [[nodiscard]] QByteArray trimmed() &&
{ return trimmed_helper(*this); }
- Q_REQUIRED_RESULT QByteArray simplified() const &
+ [[nodiscard]] QByteArray simplified() const &
{ return simplified_helper(*this); }
- Q_REQUIRED_RESULT QByteArray simplified() &&
+ [[nodiscard]] QByteArray simplified() &&
{ return simplified_helper(*this); }
-# ifdef Q_REQUIRED_RESULT_pushed
-# pragma pop_macro("Q_REQUIRED_RESULT")
-# endif
#else
- Q_REQUIRED_RESULT QByteArray toLower() const;
- Q_REQUIRED_RESULT QByteArray toUpper() const;
- Q_REQUIRED_RESULT QByteArray trimmed() const;
- Q_REQUIRED_RESULT QByteArray simplified() const;
+ [[nodiscard]] QByteArray toLower() const;
+ [[nodiscard]] QByteArray toUpper() const;
+ [[nodiscard]] QByteArray trimmed() const;
+ [[nodiscard]] QByteArray simplified() const;
#endif
- Q_REQUIRED_RESULT QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const;
- Q_REQUIRED_RESULT QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const;
+ [[nodiscard]] QByteArray leftJustified(qsizetype width, char fill = ' ', bool truncate = false) const;
+ [[nodiscard]] QByteArray rightJustified(qsizetype width, char fill = ' ', bool truncate = false) const;
- QByteArray &prepend(char c);
- inline QByteArray &prepend(int count, char c);
- QByteArray &prepend(const char *s);
- QByteArray &prepend(const char *s, int len);
+ QByteArray &prepend(char c)
+ { return insert(0, QByteArrayView(&c, 1)); }
+ inline QByteArray &prepend(qsizetype count, char c);
+ QByteArray &prepend(const char *s)
+ { return insert(0, QByteArrayView(s, qsizetype(qstrlen(s)))); }
+ QByteArray &prepend(const char *s, qsizetype len)
+ { return insert(0, QByteArrayView(s, len)); }
QByteArray &prepend(const QByteArray &a);
+ QByteArray &prepend(QByteArrayView a)
+ { return insert(0, a); }
+
QByteArray &append(char c);
- inline QByteArray &append(int count, char c);
- QByteArray &append(const char *s);
- QByteArray &append(const char *s, int len);
+ inline QByteArray &append(qsizetype count, char c);
+ QByteArray &append(const char *s)
+ { return append(s, -1); }
+ QByteArray &append(const char *s, qsizetype len)
+ { return append(QByteArrayView(s, len < 0 ? qsizetype(qstrlen(s)) : len)); }
QByteArray &append(const QByteArray &a);
- QByteArray &insert(int i, char c);
- QByteArray &insert(int i, int count, char c);
- QByteArray &insert(int i, const char *s);
- QByteArray &insert(int i, const char *s, int len);
- QByteArray &insert(int i, const QByteArray &a);
- QByteArray &remove(int index, int len);
- QByteArray &replace(int index, int len, const char *s);
- QByteArray &replace(int index, int len, const char *s, int alen);
- QByteArray &replace(int index, int len, const QByteArray &s);
- inline QByteArray &replace(char before, const char *after);
- QByteArray &replace(char before, const QByteArray &after);
- inline QByteArray &replace(const char *before, const char *after);
- QByteArray &replace(const char *before, int bsize, const char *after, int asize);
- QByteArray &replace(const QByteArray &before, const QByteArray &after);
- inline QByteArray &replace(const QByteArray &before, const char *after);
- QByteArray &replace(const char *before, const QByteArray &after);
+ QByteArray &append(QByteArrayView a)
+ { return insert(size(), a); }
+
+ QByteArray &assign(QByteArrayView v);
+ QByteArray &assign(qsizetype n, char c)
+ {
+ Q_ASSERT(n >= 0);
+ return fill(c, n);
+ }
+ template <typename InputIterator, if_input_iterator<InputIterator> = true>
+ QByteArray &assign(InputIterator first, InputIterator last)
+ {
+ d.assign(first, last);
+ d.data()[d.size] = '\0';
+ return *this;
+ }
+
+ QByteArray &insert(qsizetype i, QByteArrayView data);
+ inline QByteArray &insert(qsizetype i, const char *s)
+ { return insert(i, QByteArrayView(s)); }
+ inline QByteArray &insert(qsizetype i, const QByteArray &data)
+ { return insert(i, QByteArrayView(data)); }
+ QByteArray &insert(qsizetype i, qsizetype count, char c);
+ QByteArray &insert(qsizetype i, char c)
+ { return insert(i, QByteArrayView(&c, 1)); }
+ QByteArray &insert(qsizetype i, const char *s, qsizetype len)
+ { return insert(i, QByteArrayView(s, len)); }
+
+ QByteArray &remove(qsizetype index, qsizetype len);
+ QByteArray &removeAt(qsizetype pos)
+ { return size_t(pos) < size_t(size()) ? remove(pos, 1) : *this; }
+ QByteArray &removeFirst() { return !isEmpty() ? remove(0, 1) : *this; }
+ QByteArray &removeLast() { return !isEmpty() ? remove(size() - 1, 1) : *this; }
+
+ template <typename Predicate>
+ QByteArray &removeIf(Predicate pred)
+ {
+ removeIf_helper(pred);
+ return *this;
+ }
+
+ QByteArray &replace(qsizetype index, qsizetype len, const char *s, qsizetype alen)
+ { return replace(index, len, QByteArrayView(s, alen)); }
+ QByteArray &replace(qsizetype index, qsizetype len, QByteArrayView s);
+ QByteArray &replace(char before, QByteArrayView after)
+ { return replace(QByteArrayView(&before, 1), after); }
+ QByteArray &replace(const char *before, qsizetype bsize, const char *after, qsizetype asize)
+ { return replace(QByteArrayView(before, bsize), QByteArrayView(after, asize)); }
+ QByteArray &replace(QByteArrayView before, QByteArrayView after);
QByteArray &replace(char before, char after);
- inline QByteArray &operator+=(char c);
- inline QByteArray &operator+=(const char *s);
- inline QByteArray &operator+=(const QByteArray &a);
+
+ QByteArray &operator+=(char c)
+ { return append(c); }
+ QByteArray &operator+=(const char *s)
+ { return append(s); }
+ QByteArray &operator+=(const QByteArray &a)
+ { return append(a); }
+ QByteArray &operator+=(QByteArrayView a)
+ { return append(a); }
QList<QByteArray> split(char sep) const;
- Q_REQUIRED_RESULT QByteArray repeated(int times) const;
+ [[nodiscard]] QByteArray repeated(qsizetype times) const;
+
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ QT_ASCII_CAST_WARN inline bool operator==(const QString &s2) const;
+ QT_ASCII_CAST_WARN inline bool operator!=(const QString &s2) const;
+ QT_ASCII_CAST_WARN inline bool operator<(const QString &s2) const;
+ QT_ASCII_CAST_WARN inline bool operator>(const QString &s2) const;
+ QT_ASCII_CAST_WARN inline bool operator<=(const QString &s2) const;
+ QT_ASCII_CAST_WARN inline bool operator>=(const QString &s2) const;
+#endif // QT_CORE_REMOVED_SINCE(6, 8)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
short toShort(bool *ok = nullptr, int base = 10) const;
ushort toUShort(bool *ok = nullptr, int base = 10) const;
@@ -337,6 +385,7 @@ public:
QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(),
const QByteArray &include = QByteArray(),
char percent = '%') const;
+ [[nodiscard]] QByteArray percentDecoded(char percent = '%') const;
inline QByteArray &setNum(short, int base = 10);
inline QByteArray &setNum(ushort, int base = 10);
@@ -346,25 +395,28 @@ public:
inline QByteArray &setNum(ulong, int base = 10);
QByteArray &setNum(qlonglong, int base = 10);
QByteArray &setNum(qulonglong, int base = 10);
- inline QByteArray &setNum(float, char f = 'g', int prec = 6);
- QByteArray &setNum(double, char f = 'g', int prec = 6);
- QByteArray &setRawData(const char *a, uint n); // ### Qt 6: use an int
-
- Q_REQUIRED_RESULT static QByteArray number(int, int base = 10);
- Q_REQUIRED_RESULT static QByteArray number(uint, int base = 10);
- Q_REQUIRED_RESULT static QByteArray number(long, int base = 10);
- Q_REQUIRED_RESULT static QByteArray number(ulong, int base = 10);
- Q_REQUIRED_RESULT static QByteArray number(qlonglong, int base = 10);
- Q_REQUIRED_RESULT static QByteArray number(qulonglong, int base = 10);
- Q_REQUIRED_RESULT static QByteArray number(double, char f = 'g', int prec = 6);
- Q_REQUIRED_RESULT static QByteArray fromRawData(const char *, int size);
+ inline QByteArray &setNum(float, char format = 'g', int precision = 6);
+ QByteArray &setNum(double, char format = 'g', int precision = 6);
+ QByteArray &setRawData(const char *a, qsizetype n);
+
+ [[nodiscard]] static QByteArray number(int, int base = 10);
+ [[nodiscard]] static QByteArray number(uint, int base = 10);
+ [[nodiscard]] static QByteArray number(long, int base = 10);
+ [[nodiscard]] static QByteArray number(ulong, int base = 10);
+ [[nodiscard]] static QByteArray number(qlonglong, int base = 10);
+ [[nodiscard]] static QByteArray number(qulonglong, int base = 10);
+ [[nodiscard]] static QByteArray number(double, char format = 'g', int precision = 6);
+ [[nodiscard]] static QByteArray fromRawData(const char *data, qsizetype size)
+ {
+ return QByteArray(DataPointer(nullptr, const_cast<char *>(data), size));
+ }
class FromBase64Result;
- Q_REQUIRED_RESULT static FromBase64Result fromBase64Encoding(QByteArray &&base64, Base64Options options = Base64Encoding);
- Q_REQUIRED_RESULT static FromBase64Result fromBase64Encoding(const QByteArray &base64, Base64Options options = Base64Encoding);
- Q_REQUIRED_RESULT static QByteArray fromBase64(const QByteArray &base64, Base64Options options = Base64Encoding);
- Q_REQUIRED_RESULT static QByteArray fromHex(const QByteArray &hexEncoded);
- Q_REQUIRED_RESULT static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
+ [[nodiscard]] static FromBase64Result fromBase64Encoding(QByteArray &&base64, Base64Options options = Base64Encoding);
+ [[nodiscard]] static FromBase64Result fromBase64Encoding(const QByteArray &base64, Base64Options options = Base64Encoding);
+ [[nodiscard]] static QByteArray fromBase64(const QByteArray &base64, Base64Options options = Base64Encoding);
+ [[nodiscard]] static QByteArray fromHex(const QByteArray &hexEncoded);
+ [[nodiscard]] static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
static QByteArray fromCFData(CFDataRef data);
@@ -377,63 +429,145 @@ public:
NSData *toRawNSData() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+ static QByteArray fromEcmaUint8Array(emscripten::val uint8array);
+ emscripten::val toEcmaUint8Array();
+#endif
+
typedef char *iterator;
typedef const char *const_iterator;
typedef iterator Iterator;
typedef const_iterator ConstIterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- inline iterator begin();
- inline const_iterator begin() const;
- inline const_iterator cbegin() const;
- inline const_iterator constBegin() const;
- inline iterator end();
- inline const_iterator end() const;
- inline const_iterator cend() const;
- inline const_iterator constEnd() const;
+ iterator begin() { return data(); }
+ const_iterator begin() const noexcept { return d.data(); }
+ const_iterator cbegin() const noexcept { return begin(); }
+ const_iterator constBegin() const noexcept { return begin(); }
+ iterator end() { return begin() + size(); }
+ const_iterator end() const noexcept { return begin() + size(); }
+ const_iterator cend() const noexcept { return end(); }
+ const_iterator constEnd() const noexcept { return end(); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
- const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
- const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ const_reverse_iterator crend() const noexcept { return rend(); }
// stl compatibility
- typedef int size_type;
+ typedef qsizetype size_type;
typedef qptrdiff difference_type;
typedef const char & const_reference;
typedef char & reference;
typedef char *pointer;
typedef const char *const_pointer;
typedef char value_type;
- inline void push_back(char c);
- inline void push_back(const char *c);
- inline void push_back(const QByteArray &a);
- inline void push_front(char c);
- inline void push_front(const char *c);
- inline void push_front(const QByteArray &a);
+ void push_back(char c)
+ { append(c); }
+ void push_back(const char *s)
+ { append(s); }
+ void push_back(const QByteArray &a)
+ { append(a); }
+ void push_back(QByteArrayView a)
+ { append(a); }
+ void push_front(char c)
+ { prepend(c); }
+ void push_front(const char *c)
+ { prepend(c); }
+ void push_front(const QByteArray &a)
+ { prepend(a); }
+ void push_front(QByteArrayView a)
+ { prepend(a); }
void shrink_to_fit() { squeeze(); }
+ iterator erase(const_iterator first, const_iterator last);
+ inline iterator erase(const_iterator it) { return erase(it, it + 1); }
+ static constexpr qsizetype max_size() noexcept
+ {
+ // -1 to deal with the NUL terminator
+ return Data::max_size() - 1;
+ }
- static inline QByteArray fromStdString(const std::string &s);
- inline std::string toStdString() const;
+ static QByteArray fromStdString(const std::string &s);
+ std::string toStdString() const;
- inline int size() const { return d->size; }
- inline int count() const { return size(); }
- inline int length() const { return size(); }
- bool isNull() const;
+ inline qsizetype size() const noexcept { return d->size; }
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use size() or length() instead.")
+ inline qsizetype count() const noexcept { return size(); }
+#endif
+ inline qsizetype length() const noexcept { return size(); }
+ QT_CORE_INLINE_SINCE(6, 4)
+ bool isNull() const noexcept;
+ inline const DataPointer &data_ptr() const { return d; }
inline DataPointer &data_ptr() { return d; }
- explicit inline QByteArray(const DataPointer &dd)
- : d(dd)
- {
- }
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ explicit inline QByteArray(const DataPointer &dd) : d(dd) {}
+#endif
+ explicit inline QByteArray(DataPointer &&dd) : d(std::move(dd)) {}
private:
- operator QNoImplicitBoolCast() const;
- void reallocData(uint alloc, Data::ArrayOptions options);
- void expand(int i);
- QByteArray nulTerminated() const;
+ friend bool comparesEqual(const QByteArray &lhs, const QByteArrayView &rhs) noexcept
+ { return QByteArrayView(lhs) == rhs; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QByteArray &lhs, const QByteArrayView &rhs) noexcept
+ {
+ const int res = QtPrivate::compareMemory(QByteArrayView(lhs), rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QByteArray)
+ Q_DECLARE_STRONGLY_ORDERED(QByteArray, QByteArrayView)
+ Q_DECLARE_STRONGLY_ORDERED(QByteArray, const char *)
+#if defined(__GLIBCXX__) && defined(__cpp_lib_three_way_comparison)
+ // libstdc++ has a bug [0] when `operator const void *()` is preferred over
+ // `operator<=>()` when calling std::less<> and other similar methods.
+ // Fix it by explicitly providing relational operators in such case.
+ // [0]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114153
+ friend bool operator<(const QByteArray &lhs, const QByteArray &rhs) noexcept
+ { return is_lt(compareThreeWay(lhs, rhs)); }
+ friend bool operator<=(const QByteArray &lhs, const QByteArray &rhs) noexcept
+ { return is_lteq(compareThreeWay(lhs, rhs)); }
+ friend bool operator>(const QByteArray &lhs, const QByteArray &rhs) noexcept
+ { return is_gt(compareThreeWay(lhs, rhs)); }
+ friend bool operator>=(const QByteArray &lhs, const QByteArray &rhs) noexcept
+ { return is_gteq(compareThreeWay(lhs, rhs)); }
+#endif // defined(__GLIBCXX__) && defined(__cpp_lib_three_way_comparison)
+
+ // Check isEmpty() instead of isNull() for backwards compatibility.
+ friend bool comparesEqual(const QByteArray &lhs, std::nullptr_t) noexcept
+ { return lhs.isEmpty(); }
+ friend Qt::strong_ordering compareThreeWay(const QByteArray &lhs, std::nullptr_t) noexcept
+ { return lhs.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; }
+ Q_DECLARE_STRONGLY_ORDERED(QByteArray, std::nullptr_t)
+
+ // defined in qstring.cpp
+ friend Q_CORE_EXPORT bool comparesEqual(const QByteArray &lhs, const QChar &rhs) noexcept;
+ friend Q_CORE_EXPORT Qt::strong_ordering
+ compareThreeWay(const QByteArray &lhs, const QChar &rhs) noexcept;
+ friend Q_CORE_EXPORT bool comparesEqual(const QByteArray &lhs, char16_t rhs) noexcept;
+ friend Q_CORE_EXPORT Qt::strong_ordering
+ compareThreeWay(const QByteArray &lhs, char16_t rhs) noexcept;
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ Q_DECLARE_STRONGLY_ORDERED(QByteArray, QChar, QT_ASCII_CAST_WARN)
+ Q_DECLARE_STRONGLY_ORDERED(QByteArray, char16_t, QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+
+
+ void reallocData(qsizetype alloc, QArrayData::AllocationOption option);
+ void reallocGrowData(qsizetype n);
+ void expand(qsizetype i);
+
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= d.size);
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= d.size - pos);
+ }
+ static QByteArray sliced_helper(QByteArray &a, qsizetype pos, qsizetype n);
static QByteArray toLower_helper(const QByteArray &a);
static QByteArray toLower_helper(QByteArray &a);
static QByteArray toUpper_helper(const QByteArray &a);
@@ -442,23 +576,32 @@ private:
static QByteArray trimmed_helper(QByteArray &a);
static QByteArray simplified_helper(const QByteArray &a);
static QByteArray simplified_helper(QByteArray &a);
+ template <typename Predicate>
+ qsizetype removeIf_helper(Predicate pred)
+ {
+ const qsizetype result = d->eraseIf(pred);
+ if (result > 0)
+ d.data()[d.size] = '\0';
+ return result;
+ }
friend class QString;
- friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes);
+ friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, qsizetype nbytes);
+
+ template <typename T> friend qsizetype erase(QByteArray &ba, const T &t);
+ template <typename Predicate> friend qsizetype erase_if(QByteArray &ba, Predicate pred);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options)
-inline QByteArray::QByteArray() noexcept {}
+inline constexpr QByteArray::QByteArray() noexcept {}
inline QByteArray::~QByteArray() {}
-inline char QByteArray::at(int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d.data()[i]; }
-inline char QByteArray::operator[](int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d.data()[i]; }
+inline char QByteArray::at(qsizetype i) const
+{ verify(i, 1); return d.data()[i]; }
+inline char QByteArray::operator[](qsizetype i) const
+{ verify(i, 1); return d.data()[i]; }
-inline bool QByteArray::isEmpty() const
-{ return size() == 0; }
#ifndef QT_NO_CAST_FROM_BYTEARRAY
inline QByteArray::operator const char *() const
{ return data(); }
@@ -466,183 +609,122 @@ inline QByteArray::operator const void *() const
{ return data(); }
#endif
inline char *QByteArray::data()
-{ detach(); return d.data(); }
-inline const char *QByteArray::data() const
-{ return d.data(); }
-inline const char *QByteArray::constData() const
-{ return d.data(); }
+{
+ detach();
+ Q_ASSERT(d.data());
+ return d.data();
+}
+inline const char *QByteArray::data() const noexcept
+{
+#if QT5_NULL_STRINGS == 1
+ return d.data() ? d.data() : &_empty;
+#else
+ return d.data();
+#endif
+}
inline void QByteArray::detach()
-{ if (d->needsDetach()) reallocData(uint(size()) + 1u, d->detachFlags()); }
+{ if (d->needsDetach()) reallocData(size(), QArrayData::KeepSize); }
inline bool QByteArray::isDetached() const
{ return !d->isShared(); }
inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d)
{}
-inline int QByteArray::capacity() const
-{ const auto realCapacity = d->constAllocatedCapacity(); return realCapacity ? int(realCapacity) - 1 : 0; }
+inline qsizetype QByteArray::capacity() const { return qsizetype(d->constAllocatedCapacity()); }
-inline void QByteArray::reserve(int asize)
+inline void QByteArray::reserve(qsizetype asize)
{
- if (d->needsDetach() || asize > capacity()) {
- reallocData(qMax(uint(size()), uint(asize)) + 1u, d->detachFlags() | Data::CapacityReserved);
- } else {
- d->flags() |= Data::CapacityReserved;
- }
+ if (d->needsDetach() || asize > capacity() - d->freeSpaceAtBegin())
+ reallocData(qMax(size(), asize), QArrayData::KeepSize);
+ if (d->constAllocatedCapacity())
+ d->setFlag(Data::CapacityReserved);
}
inline void QByteArray::squeeze()
{
- if ((d->flags() & Data::CapacityReserved) == 0)
+ if (!d.isMutable())
return;
- if (d->needsDetach() || size() < capacity()) {
- reallocData(uint(size()) + 1u, d->detachFlags() & ~Data::CapacityReserved);
- } else {
- d->flags() &= uint(~Data::CapacityReserved);
- }
+ if (d->needsDetach() || size() < capacity())
+ reallocData(size(), QArrayData::KeepSize);
+ if (d->constAllocatedCapacity())
+ d->clearFlag(Data::CapacityReserved);
}
-inline char &QByteArray::operator[](int i)
-{ Q_ASSERT(i >= 0 && i < size()); return data()[i]; }
+inline char &QByteArray::operator[](qsizetype i)
+{ verify(i, 1); return data()[i]; }
inline char &QByteArray::front() { return operator[](0); }
inline char &QByteArray::back() { return operator[](size() - 1); }
-inline QByteArray::iterator QByteArray::begin()
-{ return data(); }
-inline QByteArray::const_iterator QByteArray::begin() const
-{ return data(); }
-inline QByteArray::const_iterator QByteArray::cbegin() const
-{ return data(); }
-inline QByteArray::const_iterator QByteArray::constBegin() const
-{ return data(); }
-inline QByteArray::iterator QByteArray::end()
-{ return data() + size(); }
-inline QByteArray::const_iterator QByteArray::end() const
-{ return data() + size(); }
-inline QByteArray::const_iterator QByteArray::cend() const
-{ return data() + size(); }
-inline QByteArray::const_iterator QByteArray::constEnd() const
-{ return data() + size(); }
-inline QByteArray &QByteArray::append(int n, char ch)
+inline QByteArray &QByteArray::append(qsizetype n, char ch)
{ return insert(size(), n, ch); }
-inline QByteArray &QByteArray::prepend(int n, char ch)
+inline QByteArray &QByteArray::prepend(qsizetype n, char ch)
{ return insert(0, n, ch); }
-inline QByteArray &QByteArray::operator+=(char c)
-{ return append(c); }
-inline QByteArray &QByteArray::operator+=(const char *s)
-{ return append(s); }
-inline QByteArray &QByteArray::operator+=(const QByteArray &a)
-{ return append(a); }
-inline void QByteArray::push_back(char c)
-{ append(c); }
-inline void QByteArray::push_back(const char *c)
-{ append(c); }
-inline void QByteArray::push_back(const QByteArray &a)
-{ append(a); }
-inline void QByteArray::push_front(char c)
-{ prepend(c); }
-inline void QByteArray::push_front(const char *c)
-{ prepend(c); }
-inline void QByteArray::push_front(const QByteArray &a)
-{ prepend(a); }
-inline bool QByteArray::contains(const QByteArray &a) const
-{ return indexOf(a) != -1; }
inline bool QByteArray::contains(char c) const
{ return indexOf(c) != -1; }
-inline int QByteArray::compare(const char *c, Qt::CaseSensitivity cs) const noexcept
-{
- return cs == Qt::CaseSensitive ? qstrcmp(*this, c) :
- qstrnicmp(data(), size(), c, -1);
-}
-inline int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs) const noexcept
+inline bool QByteArray::contains(QByteArrayView bv) const
+{ return indexOf(bv) != -1; }
+inline int QByteArray::compare(QByteArrayView a, Qt::CaseSensitivity cs) const noexcept
{
- return cs == Qt::CaseSensitive ? qstrcmp(*this, a) :
+ return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(*this, a) :
qstrnicmp(data(), size(), a.data(), a.size());
}
-inline bool operator==(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); }
-inline bool operator==(const QByteArray &a1, const char *a2) noexcept
-{ return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); }
-inline bool operator==(const char *a1, const QByteArray &a2) noexcept
-{ return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); }
-inline bool operator!=(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return !(a1==a2); }
-inline bool operator!=(const QByteArray &a1, const char *a2) noexcept
-{ return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); }
-inline bool operator!=(const char *a1, const QByteArray &a2) noexcept
-{ return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); }
-inline bool operator<(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) < 0; }
- inline bool operator<(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) < 0; }
-inline bool operator<(const char *a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) < 0; }
-inline bool operator<=(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) <= 0; }
-inline bool operator<=(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) <= 0; }
-inline bool operator<=(const char *a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) <= 0; }
-inline bool operator>(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) > 0; }
-inline bool operator>(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) > 0; }
-inline bool operator>(const char *a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) > 0; }
-inline bool operator>=(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) >= 0; }
-inline bool operator>=(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) >= 0; }
-inline bool operator>=(const char *a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) >= 0; }
#if !defined(QT_USE_QSTRINGBUILDER)
-inline const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
+inline QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
{ return QByteArray(a1) += a2; }
-inline const QByteArray operator+(const QByteArray &a1, const char *a2)
+inline QByteArray operator+(QByteArray &&lhs, const QByteArray &rhs)
+{ return std::move(lhs += rhs); }
+inline QByteArray operator+(const QByteArray &a1, const char *a2)
{ return QByteArray(a1) += a2; }
-inline const QByteArray operator+(const QByteArray &a1, char a2)
+inline QByteArray operator+(QByteArray &&lhs, const char *rhs)
+{ return std::move(lhs += rhs); }
+inline QByteArray operator+(const QByteArray &a1, char a2)
{ return QByteArray(a1) += a2; }
-inline const QByteArray operator+(const char *a1, const QByteArray &a2)
+inline QByteArray operator+(QByteArray &&lhs, char rhs)
+{ return std::move(lhs += rhs); }
+inline QByteArray operator+(const char *a1, const QByteArray &a2)
{ return QByteArray(a1) += a2; }
-inline const QByteArray operator+(char a1, const QByteArray &a2)
+inline QByteArray operator+(char a1, const QByteArray &a2)
{ return QByteArray(&a1, 1) += a2; }
#endif // QT_USE_QSTRINGBUILDER
-inline bool QByteArray::contains(const char *c) const
-{ return indexOf(c) != -1; }
-inline QByteArray &QByteArray::replace(char before, const char *c)
-{ return replace(&before, 1, c, qstrlen(c)); }
-inline QByteArray &QByteArray::replace(const QByteArray &before, const char *c)
-{ return replace(before.constData(), before.size(), c, qstrlen(c)); }
-inline QByteArray &QByteArray::replace(const char *before, const char *after)
-{ return replace(before, qstrlen(before), after, qstrlen(after)); }
inline QByteArray &QByteArray::setNum(short n, int base)
-{ return base == 10 ? setNum(qlonglong(n), base) : setNum(qulonglong(ushort(n)), base); }
+{ return setNum(qlonglong(n), base); }
inline QByteArray &QByteArray::setNum(ushort n, int base)
{ return setNum(qulonglong(n), base); }
inline QByteArray &QByteArray::setNum(int n, int base)
-{ return base == 10 ? setNum(qlonglong(n), base) : setNum(qulonglong(uint(n)), base); }
+{ return setNum(qlonglong(n), base); }
inline QByteArray &QByteArray::setNum(uint n, int base)
{ return setNum(qulonglong(n), base); }
inline QByteArray &QByteArray::setNum(long n, int base)
-{ return base == 10 ? setNum(qlonglong(n), base) : setNum(qulonglong(ulong(n)), base); }
+{ return setNum(qlonglong(n), base); }
inline QByteArray &QByteArray::setNum(ulong n, int base)
{ return setNum(qulonglong(n), base); }
-inline QByteArray &QByteArray::setNum(float n, char f, int prec)
-{ return setNum(double(n),f,prec); }
+inline QByteArray &QByteArray::setNum(float n, char format, int precision)
+{ return setNum(double(n), format, precision); }
-inline std::string QByteArray::toStdString() const
-{ return std::string(constData(), length()); }
-
-inline QByteArray QByteArray::fromStdString(const std::string &s)
-{ return QByteArray(s.data(), int(s.size())); }
+#if QT_CORE_INLINE_IMPL_SINCE(6, 4)
+bool QByteArray::isNull() const noexcept
+{
+ return d->isNull();
+}
+#endif
+#if QT_CORE_INLINE_IMPL_SINCE(6, 7)
+qsizetype QByteArray::indexOf(char ch, qsizetype from) const
+{
+ return qToByteArrayViewIgnoringNull(*this).indexOf(ch, from);
+}
+qsizetype QByteArray::lastIndexOf(char ch, qsizetype from) const
+{
+ return qToByteArrayViewIgnoringNull(*this).lastIndexOf(ch, from);
+}
+#endif
-#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);
#endif
#ifndef QT_NO_COMPRESS
-Q_CORE_EXPORT QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel = -1);
-Q_CORE_EXPORT QByteArray qUncompress(const uchar* data, int nbytes);
+Q_CORE_EXPORT QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel = -1);
+Q_CORE_EXPORT QByteArray qUncompress(const uchar* data, qsizetype nbytes);
inline QByteArray qCompress(const QByteArray& data, int compressionLevel = -1)
{ return qCompress(reinterpret_cast<const uchar *>(data.constData()), data.size(), compressionLevel); }
inline QByteArray qUncompress(const QByteArray& data)
@@ -659,8 +741,8 @@ public:
void swap(QByteArray::FromBase64Result &other) noexcept
{
- qSwap(decoded, other.decoded);
- qSwap(decodingStatus, other.decodingStatus);
+ decoded.swap(other.decoded);
+ std::swap(decodingStatus, other.decodingStatus);
}
explicit operator bool() const noexcept { return decodingStatus == QByteArray::Base64DecodingStatus::Ok; }
@@ -673,27 +755,73 @@ public:
QByteArray &operator*() noexcept { return decoded; }
const QByteArray &operator*() const noexcept { return decoded; }
#endif
+
+ friend inline bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
+ {
+ if (lhs.decodingStatus != rhs.decodingStatus)
+ return false;
+
+ if (lhs.decodingStatus == QByteArray::Base64DecodingStatus::Ok && lhs.decoded != rhs.decoded)
+ return false;
+
+ return true;
+ }
+
+ friend inline bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
};
Q_DECLARE_SHARED(QByteArray::FromBase64Result)
-inline bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
+
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray::FromBase64Result &key, size_t seed = 0) noexcept;
+
+template <typename T>
+qsizetype erase(QByteArray &ba, const T &t)
+{
+ return ba.removeIf_helper([&t](const auto &e) { return t == e; });
+}
+
+template <typename Predicate>
+qsizetype erase_if(QByteArray &ba, Predicate pred)
+{
+ return ba.removeIf_helper(pred);
+}
+
+//
+// QByteArrayView members that require QByteArray:
+//
+QByteArray QByteArrayView::toByteArray() const
{
- if (lhs.decodingStatus != rhs.decodingStatus)
- return false;
+ return QByteArray(*this);
+}
- if (lhs.decodingStatus == QByteArray::Base64DecodingStatus::Ok && lhs.decoded != rhs.decoded)
- return false;
+namespace Qt {
+inline namespace Literals {
+inline namespace StringLiterals {
- return true;
+inline QByteArray operator""_ba(const char *str, size_t size) noexcept
+{
+ return QByteArray(QByteArrayData(nullptr, const_cast<char *>(str), qsizetype(size)));
}
-inline bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
+} // StringLiterals
+} // Literals
+} // Qt
+
+inline namespace QtLiterals {
+#if QT_DEPRECATED_SINCE(6, 8)
+
+QT_DEPRECATED_VERSION_X_6_8("Use _ba from Qt::StringLiterals namespace instead.")
+inline QByteArray operator""_qba(const char *str, size_t size) noexcept
{
- return !operator==(lhs, rhs);
+ return Qt::StringLiterals::operator""_ba(str, size);
}
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray::FromBase64Result &key, size_t seed = 0) noexcept;
+#endif // QT_DEPRECATED_SINCE(6, 8)
+} // QtLiterals
QT_END_NAMESPACE
diff --git a/src/corelib/text/qbytearray_p.h b/src/corelib/text/qbytearray_p.h
deleted file mode 100644
index 90552cb442..0000000000
--- a/src/corelib/text/qbytearray_p.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBYTEARRAY_P_H
-#define QBYTEARRAY_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qbytearray.h>
-#include "private/qtools_p.h"
-
-QT_BEGIN_NAMESPACE
-
-// -1 because of the terminating NUL
-constexpr qsizetype MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPointer>::type) - 1;
-constexpr qsizetype MaxStringSize = (MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPointer>::type)) / 2 - 1;
-
-QT_END_NAMESPACE
-
-#endif // QBYTEARRAY_P_H
diff --git a/src/corelib/text/qbytearrayalgorithms.h b/src/corelib/text/qbytearrayalgorithms.h
new file mode 100644
index 0000000000..7060161bb4
--- /dev/null
+++ b/src/corelib/text/qbytearrayalgorithms.h
@@ -0,0 +1,148 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QBYTEARRAYALGORITHMS_H
+#define QBYTEARRAYALGORITHMS_H
+
+#include <QtCore/qnamespace.h>
+
+#include <string.h>
+#include <stdarg.h>
+
+#if 0
+#pragma qt_class(QByteArrayAlgorithms)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QByteArrayView;
+
+namespace QtPrivate {
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+bool endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept;
+
+[[nodiscard]] inline
+qsizetype findByteArray(QByteArrayView haystack, qsizetype from, char needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype count(QByteArrayView haystack, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT int compareMemory(QByteArrayView lhs, QByteArrayView rhs);
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QByteArrayView trimmed(QByteArrayView s) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf8(QByteArrayView s) noexcept;
+
+template <typename T>
+class ParsedNumber
+{
+ T m_value;
+ quint32 m_error : 1;
+ quint32 m_reserved : 31;
+ void *m_reserved2 = nullptr;
+public:
+ constexpr ParsedNumber() noexcept : m_value(), m_error(true), m_reserved(0) {}
+ constexpr explicit ParsedNumber(T v) : m_value(v), m_error(false), m_reserved(0) {}
+
+ // minimal optional-like API:
+ explicit operator bool() const noexcept { return !m_error; }
+ T &operator*() { Q_ASSERT(*this); return m_value; }
+ const T &operator*() const { Q_ASSERT(*this); return m_value; }
+ T *operator->() noexcept { return *this ? &m_value : nullptr; }
+ const T *operator->() const noexcept { return *this ? &m_value : nullptr; }
+ template <typename U> // not = T, as that'd allow calls that are incompatible with std::optional
+ T value_or(U &&u) const { return *this ? m_value : T(std::forward<U>(u)); }
+};
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<double> toDouble(QByteArrayView a) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<float> toFloat(QByteArrayView a) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<qlonglong> toSignedInteger(QByteArrayView data, int base);
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber<qulonglong> toUnsignedInteger(QByteArrayView data, int base);
+
+// QByteArrayView has incomplete type here, and we can't include qbytearrayview.h,
+// since it includes qbytearrayalgorithms.h. Use the ByteArrayView template type as
+// a workaround.
+template <typename T, typename ByteArrayView,
+ typename = std::enable_if_t<std::is_same_v<ByteArrayView, QByteArrayView>>>
+static inline T toIntegral(ByteArrayView data, bool *ok, int base)
+{
+ const auto val = [&] {
+ if constexpr (std::is_unsigned_v<T>)
+ return toUnsignedInteger(data, base);
+ else
+ return toSignedInteger(data, base);
+ }();
+ const bool failed = !val || T(*val) != *val;
+ if (ok)
+ *ok = !failed;
+ if (failed)
+ return 0;
+ return T(*val);
+}
+
+} // namespace QtPrivate
+
+/*****************************************************************************
+ Safe and portable C string functions; extensions to standard string.h
+ *****************************************************************************/
+
+Q_CORE_EXPORT char *qstrdup(const char *);
+
+inline size_t qstrlen(const char *str)
+{
+ QT_WARNING_PUSH
+#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 900 && Q_CC_GNU < 1000
+ // spurious compiler warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91490#c6)
+ // when Q_DECLARE_METATYPE_TEMPLATE_1ARG is used
+ QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
+#endif
+ return str ? strlen(str) : 0;
+ QT_WARNING_POP
+}
+
+inline size_t qstrnlen(const char *str, size_t maxlen)
+{
+ if (!str)
+ return 0;
+ auto end = static_cast<const char *>(memchr(str, '\0', maxlen));
+ return end ? end - str : maxlen;
+}
+
+// implemented in qbytearray.cpp
+Q_CORE_EXPORT char *qstrcpy(char *dst, const char *src);
+Q_CORE_EXPORT char *qstrncpy(char *dst, const char *src, size_t len);
+
+Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2);
+
+inline int qstrncmp(const char *str1, const char *str2, size_t len)
+{
+ return (str1 && str2) ? strncmp(str1, str2, len)
+ : (str1 ? 1 : (str2 ? -1 : 0));
+}
+Q_CORE_EXPORT int qstricmp(const char *, const char *);
+Q_CORE_EXPORT int qstrnicmp(const char *, const char *, size_t len);
+Q_CORE_EXPORT int qstrnicmp(const char *, qsizetype, const char *, qsizetype = -1);
+
+// implemented in qvsnprintf.cpp
+Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
+Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
+
+// qChecksum: Internet checksum
+Q_CORE_EXPORT quint16 qChecksum(QByteArrayView data, Qt::ChecksumType standard = Qt::ChecksumIso3309);
+
+QT_END_NAMESPACE
+
+#endif // QBYTEARRAYALGORITHMS_H
diff --git a/src/corelib/text/qbytearraylist.cpp b/src/corelib/text/qbytearraylist.cpp
index d04555ed4d..81bb54dfe4 100644
--- a/src/corelib/text/qbytearraylist.cpp
+++ b/src/corelib/text/qbytearraylist.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 by Southwest Research Institute (R)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 by Southwest Research Institute (R)
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qbytearraylist.h>
@@ -103,16 +67,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QByteArray QByteArrayList::join() const
+ \fn QByteArray QByteArrayList::join(const QByteArray &separator) const
- Joins all the byte arrays into a single byte array.
+ Joins all the byte arrays into a single byte array with each
+ element separated by the given \a separator.
*/
/*!
- \fn QByteArray QByteArrayList::join(const QByteArray &separator) const
+ \fn QByteArray QByteArrayList::join(QByteArrayView separator) const
+ \since 6.3
Joins all the byte arrays into a single byte array with each
- element separated by the given \a separator.
+ element separated by the given \a separator, if any.
*/
/*!
@@ -122,12 +88,12 @@ QT_BEGIN_NAMESPACE
element separated by the given \a separator.
*/
-static int QByteArrayList_joinedSize(const QByteArrayList *that, int seplen)
+static qsizetype QByteArrayList_joinedSize(const QByteArrayList *that, qsizetype seplen)
{
- int totalLength = 0;
- const int size = that->size();
+ qsizetype totalLength = 0;
+ const qsizetype size = that->size();
- for (int i = 0; i < size; ++i)
+ for (qsizetype i = 0; i < size; ++i)
totalLength += that->at(i).size();
if (size > 0)
@@ -136,13 +102,13 @@ static int QByteArrayList_joinedSize(const QByteArrayList *that, int seplen)
return totalLength;
}
-QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char *sep, int seplen)
+QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char *sep, qsizetype seplen)
{
QByteArray res;
- if (const int joinedSize = QByteArrayList_joinedSize(that, seplen))
+ if (const qsizetype joinedSize = QByteArrayList_joinedSize(that, seplen))
res.reserve(joinedSize); // don't call reserve(0) - it allocates one byte for the NUL
- const int size = that->size();
- for (int i = 0; i < size; ++i) {
+ const qsizetype size = that->size();
+ for (qsizetype i = 0; i < size; ++i) {
if (i)
res.append(sep, seplen);
res += that->at(i);
@@ -150,26 +116,4 @@ QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char
return res;
}
-/*!
- \fn int QByteArrayList::indexOf(const char *needle, int from) const
-
- Returns the index position of the first occurrence of \a needle in
- the list, searching forward from index position \a from. Returns
- -1 if no item matched.
-
- \a needle must be NUL-terminated.
-
- This overload doesn't require creating a QByteArray, thus saving a
- memory allocation and some CPU time.
-
- \since 5.13
- \overload
-*/
-
-int QtPrivate::QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from)
-{
- const auto it = std::find_if(that->begin() + from, that->end(), [needle](const QByteArray &item) { return item == needle; });
- return it == that->end() ? -1 : int(std::distance(that->begin(), it));
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/text/qbytearraylist.h b/src/corelib/text/qbytearraylist.h
index 3f85a24329..f5302884f1 100644
--- a/src/corelib/text/qbytearraylist.h
+++ b/src/corelib/text/qbytearraylist.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2014 by Southwest Research Institute (R)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2014 by Southwest Research Institute (R)
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qlist.h>
@@ -46,6 +10,8 @@
#include <QtCore/qbytearray.h>
+#include <limits>
+
QT_BEGIN_NAMESPACE
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
@@ -53,37 +19,40 @@ typedef QListIterator<QByteArray> QByteArrayListIterator;
typedef QMutableListIterator<QByteArray> QMutableByteArrayListIterator;
#endif
-#ifndef Q_CLANG_QDOC
-typedef QList<QByteArray> QByteArrayList;
+#ifndef Q_QDOC
namespace QtPrivate {
+#if QT_CORE_REMOVED_SINCE(6, 3) && QT_POINTER_SIZE != 4
QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength);
- int Q_CORE_EXPORT QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from);
+#endif
+ QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *sep, qsizetype len);
}
#endif
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
class QByteArrayList : public QList<QByteArray>
#else
-template <> struct QListSpecialMethods<QByteArray>
+template <> struct QListSpecialMethods<QByteArray> : QListSpecialMethodsBase<QByteArray>
#endif
{
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
protected:
~QListSpecialMethods() = default;
#endif
public:
- inline QByteArray join() const
- { return QtPrivate::QByteArrayList_join(self(), nullptr, 0); }
+ using QListSpecialMethodsBase<QByteArray>::indexOf;
+ using QListSpecialMethodsBase<QByteArray>::lastIndexOf;
+ using QListSpecialMethodsBase<QByteArray>::contains;
+
+ QByteArray join(QByteArrayView sep = {}) const
+ {
+ return QtPrivate::QByteArrayList_join(self(), sep.data(), sep.size());
+ }
+ Q_WEAK_OVERLOAD
inline QByteArray join(const QByteArray &sep) const
- { return QtPrivate::QByteArrayList_join(self(), sep.constData(), sep.size()); }
+ { return join(qToByteArrayViewIgnoringNull(sep)); }
inline QByteArray join(char sep) const
- { return QtPrivate::QByteArrayList_join(self(), &sep, 1); }
-
-private:
- typedef QList<QByteArray> Self;
- Self *self() { return static_cast<Self *>(this); }
- const Self *self() const { return static_cast<const Self *>(this); }
+ { return join({&sep, 1}); }
};
QT_END_NAMESPACE
diff --git a/src/corelib/text/qbytearraymatcher.cpp b/src/corelib/text/qbytearraymatcher.cpp
index 650b51d48e..ae38fb584b 100644
--- a/src/corelib/text/qbytearraymatcher.cpp
+++ b/src/corelib/text/qbytearraymatcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbytearraymatcher.h"
@@ -124,15 +88,19 @@ QByteArrayMatcher::QByteArrayMatcher()
}
/*!
- Constructs a byte array matcher from \a pattern. \a pattern
- has the given \a length. \a pattern must remain in scope, but
- the destructor does not delete \a pattern.
- */
-QByteArrayMatcher::QByteArrayMatcher(const char *pattern, int length)
- : d(nullptr)
+ Constructs a byte array matcher from \a pattern. \a pattern
+ has the given \a length. Call indexIn() to perform a search.
+
+ \note the data that \a pattern is referencing must remain valid while this
+ object is used.
+*/
+QByteArrayMatcher::QByteArrayMatcher(const char *pattern, qsizetype length) : d(nullptr)
{
p.p = reinterpret_cast<const uchar *>(pattern);
- p.l = length;
+ if (length < 0)
+ p.l = qstrlen(pattern);
+ else
+ p.l = length;
bm_init_skiptable(p.p, p.l, p.q_skiptable);
}
@@ -149,6 +117,18 @@ QByteArrayMatcher::QByteArrayMatcher(const QByteArray &pattern)
}
/*!
+ \fn QByteArrayMatcher::QByteArrayMatcher(QByteArrayView pattern)
+ \since 6.3
+ \overload
+
+ Constructs a byte array matcher that will search for \a pattern.
+ Call indexIn() to perform a search.
+
+ \note the data that \a pattern is referencing must remain valid while this
+ object is used.
+*/
+
+/*!
Copies the \a other byte array matcher to this byte array matcher.
*/
QByteArrayMatcher::QByteArrayMatcher(const QByteArrayMatcher &other)
@@ -190,32 +170,36 @@ void QByteArrayMatcher::setPattern(const QByteArray &pattern)
}
/*!
- Searches the byte array \a ba, from byte position \a from (default
- 0, i.e. from the first byte), for the byte array pattern() that
- was set in the constructor or in the most recent call to
- setPattern(). Returns the position where the pattern() matched in
- \a ba, or -1 if no match was found.
+ Searches the char string \a str, which has length \a len, from
+ byte position \a from (default 0, i.e. from the first byte), for
+ the byte array pattern() that was set in the constructor or in the
+ most recent call to setPattern(). Returns the position where the
+ pattern() matched in \a str, or -1 if no match was found.
*/
-int QByteArrayMatcher::indexIn(const QByteArray &ba, int from) const
+qsizetype QByteArrayMatcher::indexIn(const char *str, qsizetype len, qsizetype from) const
{
if (from < 0)
from = 0;
- return bm_find(reinterpret_cast<const uchar *>(ba.constData()), ba.size(), from,
+ return bm_find(reinterpret_cast<const uchar *>(str), len, from,
p.p, p.l, p.q_skiptable);
}
/*!
- Searches the char string \a str, which has length \a len, from
- byte position \a from (default 0, i.e. from the first byte), for
- the byte array pattern() that was set in the constructor or in the
- most recent call to setPattern(). Returns the position where the
- pattern() matched in \a str, or -1 if no match was found.
+ \fn qsizetype QByteArrayMatcher::indexIn(QByteArrayView data, qsizetype from) const
+ \since 6.3
+ \overload
+
+ Searches the byte array \a data, from byte position \a from (default
+ 0, i.e. from the first byte), for the byte array pattern() that
+ was set in the constructor or in the most recent call to
+ setPattern(). Returns the position where the pattern() matched in
+ \a data, or -1 if no match was found.
*/
-int QByteArrayMatcher::indexIn(const char *str, int len, int from) const
+qsizetype QByteArrayMatcher::indexIn(QByteArrayView data, qsizetype from) const
{
if (from < 0)
from = 0;
- return bm_find(reinterpret_cast<const uchar *>(str), len, from,
+ return bm_find(reinterpret_cast<const uchar *>(data.data()), data.size(), from,
p.p, p.l, p.q_skiptable);
}
@@ -347,8 +331,7 @@ qsizetype qFindByteArray(
QByteArray::indexOf(), in particular if repeated matching takes place.
Unlike QByteArrayMatcher, this class calculates the internal
- representation at \e{compile-time}, if your compiler supports
- C++14-level \c{constexpr} (C++11 is not sufficient), so it can
+ representation at \e{compile-time}, so it can
even benefit if you are doing one-off byte array matches.
Create the QStaticByteArrayMatcher by calling qMakeStaticByteArrayMatcher(),
@@ -364,16 +347,11 @@ qsizetype qFindByteArray(
Since this class is designed to do all the up-front calculations at compile-time,
it does not offer a setPattern() method.
- \note Qt detects the necessary C++14 compiler support by way of the feature
- test recommendations from
- \l{https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations}
- {C++ Committee's Standing Document 6}.
-
\sa QByteArrayMatcher, QStringMatcher
*/
/*!
- \fn template <uint N> int QStaticByteArrayMatcher<N>::indexIn(const char *haystack, int hlen, int from = 0) const
+ \fn template <size_t N> qsizetype QStaticByteArrayMatcher<N>::indexIn(const char *haystack, qsizetype hlen, qsizetype from = 0) const
Searches the char string \a haystack, which has length \a hlen, from
byte position \a from (default 0, i.e. from the first byte), for
@@ -383,7 +361,7 @@ qsizetype qFindByteArray(
*/
/*!
- \fn template <uint N> int QStaticByteArrayMatcher<N>::indexIn(const QByteArray &haystack, int from = 0) const
+ \fn template <size_t N> qsizetype QStaticByteArrayMatcher<N>::indexIn(const QByteArray &haystack, qsizetype from = 0) const
Searches the char string \a haystack, from byte position \a from
(default 0, i.e. from the first byte), for the byte array pattern()
@@ -393,7 +371,7 @@ qsizetype qFindByteArray(
*/
/*!
- \fn template <uint N> QByteArray QStaticByteArrayMatcher<N>::pattern() const
+ \fn template <size_t N> QByteArray QStaticByteArrayMatcher<N>::pattern() const
Returns the byte array pattern that this byte array matcher will
search for.
@@ -404,7 +382,7 @@ qsizetype qFindByteArray(
/*!
\internal
*/
-int QStaticByteArrayMatcherBase::indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept
+qsizetype QStaticByteArrayMatcherBase::indexOfIn(const char *needle, size_t nlen, const char *haystack, qsizetype hlen, qsizetype from) const noexcept
{
if (from < 0)
from = 0;
@@ -413,12 +391,12 @@ int QStaticByteArrayMatcherBase::indexOfIn(const char *needle, uint nlen, const
}
/*!
- \fn template <uint N> QStaticByteArrayMatcher<N>::QStaticByteArrayMatcher(const char (&pattern)[N])
+ \fn template <size_t N> QStaticByteArrayMatcher<N>::QStaticByteArrayMatcher(const char (&pattern)[N])
\internal
*/
/*!
- \fn template <uint N> QStaticByteArrayMatcher qMakeStaticByteArrayMatcher(const char (&pattern)[N])
+ \fn template <size_t N> QStaticByteArrayMatcher qMakeStaticByteArrayMatcher(const char (&pattern)[N])
\since 5.9
\relates QStaticByteArrayMatcher
@@ -433,3 +411,5 @@ int QStaticByteArrayMatcherBase::indexOfIn(const char *needle, uint nlen, const
QT_END_NAMESPACE
+
+#undef REHASH
diff --git a/src/corelib/text/qbytearraymatcher.h b/src/corelib/text/qbytearraymatcher.h
index c923bd15d5..1de9c23f10 100644
--- a/src/corelib/text/qbytearraymatcher.h
+++ b/src/corelib/text/qbytearraymatcher.h
@@ -1,47 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBYTEARRAYMATCHER_H
#define QBYTEARRAYMATCHER_H
#include <QtCore/qbytearray.h>
+#include <QtCore/q20algorithm.h>
+#include <iterator>
+#include <limits>
+
QT_BEGIN_NAMESPACE
@@ -52,7 +20,10 @@ class Q_CORE_EXPORT QByteArrayMatcher
public:
QByteArrayMatcher();
explicit QByteArrayMatcher(const QByteArray &pattern);
- explicit QByteArrayMatcher(const char *pattern, int length);
+ explicit QByteArrayMatcher(QByteArrayView pattern)
+ : QByteArrayMatcher(pattern.data(), pattern.size())
+ {}
+ explicit QByteArrayMatcher(const char *pattern, qsizetype length = -1);
QByteArrayMatcher(const QByteArrayMatcher &other);
~QByteArrayMatcher();
@@ -60,8 +31,15 @@ public:
void setPattern(const QByteArray &pattern);
- int indexIn(const QByteArray &ba, int from = 0) const;
- int indexIn(const char *str, int len, int from = 0) const;
+#if QT_CORE_REMOVED_SINCE(6, 3)
+ qsizetype indexIn(const QByteArray &ba, qsizetype from = 0) const;
+#else
+ Q_WEAK_OVERLOAD
+ qsizetype indexIn(const QByteArray &ba, qsizetype from = 0) const
+ { return indexIn(QByteArrayView{ba}, from); }
+#endif
+ qsizetype indexIn(const char *str, qsizetype len, qsizetype from = 0) const;
+ qsizetype indexIn(QByteArrayView data, qsizetype from = 0) const;
inline QByteArray pattern() const
{
if (q_pattern.isNull())
@@ -75,7 +53,7 @@ private:
struct Data {
uchar q_skiptable[256];
const uchar *p;
- int l;
+ qsizetype l;
};
union {
uint dummy[256];
@@ -90,43 +68,25 @@ class QStaticByteArrayMatcherBase
uchar data[256];
} m_skiptable;
protected:
- explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcherBase(const char *pattern, uint n) noexcept
+ explicit constexpr QStaticByteArrayMatcherBase(const char *pattern, size_t n) noexcept
: m_skiptable(generate(pattern, n)) {}
// compiler-generated copy/more ctors/assignment operators are ok!
- // compiler-generated dtor is ok!
+ ~QStaticByteArrayMatcherBase() = default;
+#if QT_CORE_REMOVED_SINCE(6, 3) && QT_POINTER_SIZE != 4
Q_CORE_EXPORT int indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept;
+#endif
+ Q_CORE_EXPORT qsizetype indexOfIn(const char *needle, size_t nlen,
+ const char *haystack, qsizetype hlen,
+ qsizetype from) const noexcept;
private:
- static Q_DECL_RELAXED_CONSTEXPR Skiptable generate(const char *pattern, uint n) noexcept
+ static constexpr Skiptable generate(const char *pattern, size_t n) noexcept
{
const auto uchar_max = (std::numeric_limits<uchar>::max)();
uchar max = n > uchar_max ? uchar_max : uchar(n);
- Skiptable table = {
- // this verbose initialization code aims to avoid some opaque error messages
- // even on powerful compilers such as GCC 5.3. Even though for GCC a loop
- // format can be found that v5.3 groks, it's probably better to go with this
- // for the time being:
- {
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
-
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
- }
- };
+ Skiptable table = {};
+ q20::fill(std::begin(table.data), std::end(table.data), max);
pattern += n - max;
while (max--)
table.data[uchar(*pattern++)] = max;
@@ -134,29 +94,33 @@ private:
}
};
-template <uint N>
+template <size_t N>
class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase
{
char m_pattern[N];
+ // N includes the terminating '\0'!
static_assert(N > 2, "QStaticByteArrayMatcher makes no sense for finding a single-char pattern");
public:
- explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher(const char (&patternToMatch)[N]) noexcept
+ explicit constexpr QStaticByteArrayMatcher(const char (&patternToMatch)[N]) noexcept
: QStaticByteArrayMatcherBase(patternToMatch, N - 1), m_pattern()
{
- for (uint i = 0; i < N; ++i)
+ for (size_t i = 0; i < N; ++i)
m_pattern[i] = patternToMatch[i];
}
- int indexIn(const QByteArray &haystack, int from = 0) const noexcept
+ Q_WEAK_OVERLOAD
+ qsizetype indexIn(const QByteArray &haystack, qsizetype from = 0) const noexcept
{ return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
- int indexIn(const char *haystack, int hlen, int from = 0) const noexcept
+ qsizetype indexIn(const char *haystack, qsizetype hlen, qsizetype from = 0) const noexcept
{ return this->indexOfIn(m_pattern, N - 1, haystack, hlen, from); }
+ qsizetype indexIn(QByteArrayView haystack, qsizetype from = 0) const noexcept
+ { return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
- QByteArray pattern() const { return QByteArray(m_pattern, int(N - 1)); }
+ QByteArray pattern() const { return QByteArray(m_pattern, qsizetype(N - 1)); }
};
-template <uint N>
-Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) noexcept
+template <size_t N>
+constexpr QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) noexcept
{ return QStaticByteArrayMatcher<N>(pattern); }
QT_END_NAMESPACE
diff --git a/src/corelib/text/qbytearrayview.h b/src/corelib/text/qbytearrayview.h
new file mode 100644
index 0000000000..45ebc812cd
--- /dev/null
+++ b/src/corelib/text/qbytearrayview.h
@@ -0,0 +1,406 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QBYTEARRAYVIEW_H
+#define QBYTEARRAYVIEW_H
+
+#include <QtCore/qbytearrayalgorithms.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qstringfwd.h>
+#include <QtCore/qarraydata.h>
+
+#include <string>
+#include <string_view>
+#include <QtCore/q20type_traits.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+template <typename Byte>
+struct IsCompatibleByteTypeHelper
+ : std::integral_constant<bool,
+ std::is_same_v<Byte, char> ||
+ std::is_same_v<Byte, uchar> ||
+ std::is_same_v<Byte, signed char> ||
+ std::is_same_v<Byte, std::byte>> {};
+
+template <typename Byte>
+struct IsCompatibleByteType
+ : IsCompatibleByteTypeHelper<q20::remove_cvref_t<Byte>> {};
+
+template <typename Pointer>
+struct IsCompatibleByteArrayPointerHelper : std::false_type {};
+template <typename Byte>
+struct IsCompatibleByteArrayPointerHelper<Byte *>
+ : IsCompatibleByteType<Byte> {};
+template<typename Pointer>
+struct IsCompatibleByteArrayPointer
+ : IsCompatibleByteArrayPointerHelper<q20::remove_cvref_t<Pointer>> {};
+
+template <typename T, typename Enable = void>
+struct IsContainerCompatibleWithQByteArrayView : std::false_type {};
+
+template <typename T>
+struct IsContainerCompatibleWithQByteArrayView<T, std::enable_if_t<
+ std::conjunction_v<
+ // lacking concepts and ranges, we accept any T whose std::data yields a suitable
+ // pointer ...
+ IsCompatibleByteArrayPointer<decltype(std::data(std::declval<const T &>()))>,
+ // ... and that has a suitable size ...
+ std::is_convertible<decltype(std::size(std::declval<const T &>())), qsizetype>,
+ // ... and it's a range as it defines an iterator-like API
+ IsCompatibleByteType<typename std::iterator_traits<decltype(
+ std::begin(std::declval<const T &>()))>::value_type>,
+ std::is_convertible<decltype(std::begin(std::declval<const T &>())
+ != std::end(std::declval<const T &>())),
+ bool>,
+
+ // This needs to be treated specially due to the empty vs null distinction
+ std::negation<std::is_same<std::decay_t<T>, QByteArray>>,
+
+ // We handle array literals specially for source compat reasons
+ std::negation<std::is_array<T>>,
+
+ // Don't make an accidental copy constructor
+ std::negation<std::is_same<std::decay_t<T>, QByteArrayView>>>>> : std::true_type {};
+
+// Used by QLatin1StringView too
+template <typename Char>
+static constexpr qsizetype lengthHelperPointer(const Char *data) noexcept
+{
+ return qsizetype(std::char_traits<Char>::length(data));
+}
+
+} // namespace QtPrivate
+
+class Q_CORE_EXPORT QByteArrayView
+{
+public:
+ typedef char storage_type;
+ typedef const char value_type;
+ typedef qptrdiff difference_type;
+ typedef qsizetype size_type;
+ typedef value_type &reference;
+ typedef value_type &const_reference;
+ typedef value_type *pointer;
+ typedef value_type *const_pointer;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+private:
+ template <typename Byte>
+ using if_compatible_byte =
+ typename std::enable_if_t<QtPrivate::IsCompatibleByteType<Byte>::value, bool>;
+
+ template <typename Pointer>
+ using if_compatible_pointer =
+ typename std::enable_if_t<QtPrivate::IsCompatibleByteArrayPointer<Pointer>::value,
+ bool>;
+
+ template <typename T>
+ using if_compatible_qbytearray_like =
+ typename std::enable_if_t<std::is_same_v<T, QByteArray>, bool>;
+
+ template <typename T>
+ using if_compatible_container =
+ typename std::enable_if_t<QtPrivate::IsContainerCompatibleWithQByteArrayView<T>::value,
+ bool>;
+
+ template <typename Container>
+ static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
+ {
+ return qsizetype(std::size(c));
+ }
+
+ static constexpr qsizetype lengthHelperCharArray(const char *data, size_t size) noexcept
+ {
+ const auto it = std::char_traits<char>::find(data, size, '\0');
+ const auto end = it ? it : std::next(data, size);
+ return qsizetype(std::distance(data, end));
+ }
+
+ template <typename Byte>
+ static const storage_type *castHelper(const Byte *data) noexcept
+ { return reinterpret_cast<const storage_type*>(data); }
+ static constexpr const storage_type *castHelper(const storage_type *data) noexcept
+ { return data; }
+
+public:
+ constexpr QByteArrayView() noexcept
+ : m_size(0), m_data(nullptr) {}
+ constexpr QByteArrayView(std::nullptr_t) noexcept
+ : QByteArrayView() {}
+
+ template <typename Byte, if_compatible_byte<Byte> = true>
+ constexpr QByteArrayView(const Byte *data, qsizetype len)
+ : m_size((Q_ASSERT(len >= 0), Q_ASSERT(data || !len), len)),
+ m_data(castHelper(data)) {}
+
+ template <typename Byte, if_compatible_byte<Byte> = true>
+ constexpr QByteArrayView(const Byte *first, const Byte *last)
+ : QByteArrayView(first, last - first) {}
+
+#ifdef Q_QDOC
+ template <typename Byte>
+ constexpr QByteArrayView(const Byte *data) noexcept;
+#else
+ template <typename Pointer, if_compatible_pointer<Pointer> = true>
+ constexpr QByteArrayView(const Pointer &data) noexcept
+ : QByteArrayView(
+ data, data ? QtPrivate::lengthHelperPointer(data) : 0) {}
+#endif
+
+#ifdef Q_QDOC
+ QByteArrayView(const QByteArray &data) noexcept;
+#else
+ template <typename ByteArray, if_compatible_qbytearray_like<ByteArray> = true>
+ QByteArrayView(const ByteArray &ba) noexcept
+ : QByteArrayView(ba.isNull() ? nullptr : ba.data(), qsizetype(ba.size())) {}
+#endif
+
+ template <typename Container, if_compatible_container<Container> = true>
+ constexpr QByteArrayView(const Container &c) noexcept
+ : QByteArrayView(std::data(c), lengthHelperContainer(c)) {}
+ template <size_t Size>
+ constexpr QByteArrayView(const char (&data)[Size]) noexcept
+ : QByteArrayView(data, lengthHelperCharArray(data, Size)) {}
+
+ constexpr QByteArrayView(QLatin1StringView v) noexcept; // defined in qlatin1stringview.h
+ constexpr QByteArrayView(QUtf8StringView v) noexcept; // defined in qutf8stringview.h
+
+#ifdef Q_QDOC
+ template <typename Byte, size_t Size>
+#else
+ template <typename Byte, size_t Size, if_compatible_byte<Byte> = true>
+#endif
+ [[nodiscard]] constexpr static QByteArrayView fromArray(const Byte (&data)[Size]) noexcept
+ { return QByteArrayView(data, Size); }
+ [[nodiscard]] inline QByteArray toByteArray() const; // defined in qbytearray.h
+
+ [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
+ [[nodiscard]] constexpr const_pointer data() const noexcept { return m_data; }
+ [[nodiscard]] constexpr const_pointer constData() const noexcept { return data(); }
+
+ [[nodiscard]] constexpr char operator[](qsizetype n) const
+ { verify(n, 1); return m_data[n]; }
+
+ //
+ // QByteArray API
+ //
+ [[nodiscard]] constexpr char at(qsizetype n) const { return (*this)[n]; }
+
+ [[nodiscard]] constexpr QByteArrayView first(qsizetype n) const
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] constexpr QByteArrayView last(qsizetype n) const
+ { verify(0, n); return sliced(size() - n, n); }
+ [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos) const
+ { verify(pos, 0); return QByteArrayView(data() + pos, size() - pos); }
+ [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos, qsizetype n) const
+ { verify(pos, n); return QByteArrayView(data() + pos, n); }
+ [[nodiscard]] constexpr QByteArrayView chopped(qsizetype len) const
+ { verify(0, len); return sliced(0, size() - len); }
+
+ [[nodiscard]] constexpr QByteArrayView left(qsizetype n) const
+ { if (n < 0 || n > size()) n = size(); return QByteArrayView(data(), n); }
+ [[nodiscard]] constexpr QByteArrayView right(qsizetype n) const
+ { if (n < 0 || n > size()) n = size(); if (n < 0) n = 0; return QByteArrayView(data() + size() - n, n); }
+ [[nodiscard]] constexpr QByteArrayView mid(qsizetype pos, qsizetype n = -1) const
+ {
+ using namespace QtPrivate;
+ auto result = QContainerImplHelper::mid(size(), &pos, &n);
+ return result == QContainerImplHelper::Null ? QByteArrayView()
+ : QByteArrayView(m_data + pos, n);
+ }
+
+ constexpr void truncate(qsizetype n)
+ { verify(0, n); m_size = n; }
+ constexpr void chop(qsizetype n)
+ { verify(0, n); m_size -= n; }
+
+ // Defined in qbytearray.cpp:
+ [[nodiscard]] QByteArrayView trimmed() const noexcept
+ { return QtPrivate::trimmed(*this); }
+ [[nodiscard]] short toShort(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<short>(*this, ok, base); }
+ [[nodiscard]] ushort toUShort(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<ushort>(*this, ok, base); }
+ [[nodiscard]] int toInt(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<int>(*this, ok, base); }
+ [[nodiscard]] uint toUInt(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<uint>(*this, ok, base); }
+ [[nodiscard]] long toLong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<long>(*this, ok, base); }
+ [[nodiscard]] ulong toULong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<ulong>(*this, ok, base); }
+ [[nodiscard]] qlonglong toLongLong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<qlonglong>(*this, ok, base); }
+ [[nodiscard]] qulonglong toULongLong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<qulonglong>(*this, ok, base); }
+ [[nodiscard]] float toFloat(bool *ok = nullptr) const
+ {
+ const auto r = QtPrivate::toFloat(*this);
+ if (ok)
+ *ok = bool(r);
+ return r.value_or(0.0f);
+ }
+ [[nodiscard]] double toDouble(bool *ok = nullptr) const
+ {
+ const auto r = QtPrivate::toDouble(*this);
+ if (ok)
+ *ok = bool(r);
+ return r.value_or(0.0);
+ }
+
+ [[nodiscard]] bool startsWith(QByteArrayView other) const noexcept
+ { return QtPrivate::startsWith(*this, other); }
+ [[nodiscard]] constexpr bool startsWith(char c) const noexcept
+ { return !empty() && front() == c; }
+
+ [[nodiscard]] bool endsWith(QByteArrayView other) const noexcept
+ { return QtPrivate::endsWith(*this, other); }
+ [[nodiscard]] constexpr bool endsWith(char c) const noexcept
+ { return !empty() && back() == c; }
+
+ [[nodiscard]] qsizetype indexOf(QByteArrayView a, qsizetype from = 0) const noexcept
+ { return QtPrivate::findByteArray(*this, from, a); }
+ [[nodiscard]] qsizetype indexOf(char ch, qsizetype from = 0) const noexcept
+ { return QtPrivate::findByteArray(*this, from, ch); }
+
+ [[nodiscard]] bool contains(QByteArrayView a) const noexcept
+ { return indexOf(a) != qsizetype(-1); }
+ [[nodiscard]] bool contains(char c) const noexcept
+ { return indexOf(c) != qsizetype(-1); }
+
+ [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a) const noexcept
+ { return lastIndexOf(a, size()); }
+ [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a, qsizetype from) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, a); }
+ [[nodiscard]] qsizetype lastIndexOf(char ch, qsizetype from = -1) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, ch); }
+
+ [[nodiscard]] qsizetype count(QByteArrayView a) const noexcept
+ { return QtPrivate::count(*this, a); }
+ [[nodiscard]] qsizetype count(char ch) const noexcept
+ { return QtPrivate::count(*this, QByteArrayView(&ch, 1)); }
+
+ inline int compare(QByteArrayView a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+
+ [[nodiscard]] inline bool isValidUtf8() const noexcept { return QtPrivate::isValidUtf8(*this); }
+
+ //
+ // STL compatibility API:
+ //
+ [[nodiscard]] constexpr const_iterator begin() const noexcept { return data(); }
+ [[nodiscard]] constexpr const_iterator end() const noexcept { return data() + size(); }
+ [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
+
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+ [[nodiscard]] constexpr char front() const { Q_ASSERT(!empty()); return m_data[0]; }
+ [[nodiscard]] constexpr char back() const { Q_ASSERT(!empty()); return m_data[m_size - 1]; }
+
+ [[nodiscard]] constexpr Q_IMPLICIT operator std::string_view() const noexcept
+ { return std::string_view(m_data, size_t(m_size)); }
+
+ //
+ // Qt compatibility API:
+ //
+ [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
+ [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
+ [[nodiscard]] constexpr qsizetype length() const noexcept
+ { return size(); }
+ [[nodiscard]] constexpr char first() const { return front(); }
+ [[nodiscard]] constexpr char last() const { return back(); }
+
+private:
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+
+ friend bool
+ comparesEqual(const QByteArrayView &lhs, const QByteArrayView &rhs) noexcept
+ {
+ return lhs.size() == rhs.size()
+ && (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
+ }
+ friend Qt::strong_ordering
+ compareThreeWay(const QByteArrayView &lhs, const QByteArrayView &rhs) noexcept
+ {
+ const int res = QtPrivate::compareMemory(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QByteArrayView)
+
+ friend bool comparesEqual(const QByteArrayView &lhs, const char *rhs) noexcept
+ { return comparesEqual(lhs, QByteArrayView(rhs)); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QByteArrayView &lhs, const char *rhs) noexcept
+ { return compareThreeWay(lhs, QByteArrayView(rhs)); }
+ Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, const char *)
+
+ // defined in qstring.cpp
+ friend Q_CORE_EXPORT bool
+ comparesEqual(const QByteArrayView &lhs, const QChar &rhs) noexcept;
+ friend Q_CORE_EXPORT Qt::strong_ordering
+ compareThreeWay(const QByteArrayView &lhs, const QChar &rhs) noexcept;
+ friend Q_CORE_EXPORT bool
+ comparesEqual(const QByteArrayView &lhs, char16_t rhs) noexcept;
+ friend Q_CORE_EXPORT Qt::strong_ordering
+ compareThreeWay(const QByteArrayView &lhs, char16_t rhs) noexcept;
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, QChar, QT_ASCII_CAST_WARN)
+ Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, char16_t, QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+
+ qsizetype m_size;
+ const storage_type *m_data;
+};
+Q_DECLARE_TYPEINFO(QByteArrayView, Q_PRIMITIVE_TYPE);
+
+template<typename QByteArrayLike,
+ std::enable_if_t<std::is_same_v<QByteArrayLike, QByteArray>, bool> = true>
+[[nodiscard]] inline QByteArrayView qToByteArrayViewIgnoringNull(const QByteArrayLike &b) noexcept
+{ return QByteArrayView(b.begin(), b.size()); }
+
+inline int QByteArrayView::compare(QByteArrayView a, Qt::CaseSensitivity cs) const noexcept
+{
+ return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(*this, a) :
+ qstrnicmp(data(), size(), a.data(), a.size());
+}
+
+#if QT_DEPRECATED_SINCE(6, 0)
+QT_DEPRECATED_VERSION_X_6_0("Use the QByteArrayView overload.")
+inline quint16 qChecksum(const char *s, qsizetype len,
+ Qt::ChecksumType standard = Qt::ChecksumIso3309)
+{ return qChecksum(QByteArrayView(s, len), standard); }
+#endif
+
+qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ if (from < 0)
+ from = qMax(from + haystack.size(), qsizetype(0));
+ if (from < haystack.size()) {
+ const char *const b = haystack.data();
+ if (const auto n = static_cast<const char *>(
+ memchr(b + from, needle, static_cast<size_t>(haystack.size() - from)))) {
+ return n - b;
+ }
+ }
+ return -1;
+}
+
+QT_END_NAMESPACE
+
+#endif // QBYTEARRAYVIEW_H
diff --git a/src/corelib/text/qbytearrayview.qdoc b/src/corelib/text/qbytearrayview.qdoc
new file mode 100644
index 0000000000..eb890917eb
--- /dev/null
+++ b/src/corelib/text/qbytearrayview.qdoc
@@ -0,0 +1,1056 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \class QByteArrayView
+ \inmodule QtCore
+ \brief The QByteArrayView class provides a view on an array of bytes with a read-only
+ subset of the QByteArray API.
+ \since 6.0
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+ \reentrant
+
+ \compares strong
+ \compareswith strong QByteArray {const char *}
+ \endcompareswith
+ \compareswith strong QString QStringView QUtf8StringView QLatin1StringView \
+ QChar char16_t
+ When comparing with string and Unicode character types, the content is
+ interpreted as UTF-8.
+ \endcompareswith
+
+ A QByteArrayView references a contiguous portion of raw bytes it does
+ not own. It acts as an interface type to all kinds of byte-array-like data,
+ without the need to construct a QByteArray first.
+
+ The byte array data may be represented as an array (or an array-compatible
+ data-structure such as QByteArray, std::basic_string, etc.) of \c char,
+ \c{signed char}, \c{unsigned char} or \c std::byte.
+
+ QByteArrayView is designed as an interface type; its main use-case is
+ as a function parameter type. When QByteArrayViews are used as automatic
+ variables or data members, care must be taken to ensure that the referenced
+ data (for example, owned by a QByteArray) outlives the QByteArrayView on all
+ code paths, lest the byte array view ends up referencing deleted data.
+
+ When used as an interface type, QByteArrayView allows a single function to accept
+ a wide variety of byte-array-like data sources. One function accepting QByteArrayView
+ thus replaces several function overloads (taking, for example, QByteArray, const char *,
+ etc.) while at the same time enabling even more byte array data sources to be passed
+ to the function.
+
+ QByteArrayView should be passed by value, not by reference-to-const:
+ \snippet code/src_corelib_text_qbytearrayview.cpp 0
+
+ If you want to give your users maximum freedom in what type of data they
+ can pass to your function, accompany the QByteArrayView overload with
+ overloads for
+
+ \list
+ \li \e char: this overload can delegate to the QByteArrayView version:
+ \snippet code/src_corelib_text_qbytearrayview.cpp 1
+ even though, for technical reasons, QByteArrayView cannot provide a
+ char constructor by itself.
+ \li \e QByteArray: if you store an unmodified copy of the byte array and
+ thus would like to take advantage of QByteArray's implicit sharing.
+ \endlist
+
+ QByteArrayView can also be used as the return value of a function. If you call a
+ function returning QByteArrayView, take extra care to not keep the QByteArrayView
+ around longer than the function promises to keep the referenced data alive.
+ If in doubt, obtain a strong reference to the data by calling toByteArray() to convert
+ the QByteArrayView into a QByteArray.
+
+ The methods supported by QByteArrayView reflect those of \l QByteArray. In
+ particular, to the limited degree that it ascribes semantics (such as
+ character case, spacing, digits of numbers) to the character data viewed, it
+ uses the C locale and ASCII encoding. See \l {C locale and ASCII functions}
+ for details and the limitations on these methods.
+
+ \section1 Compatible Byte Types
+
+ QByteArrayView can be constructed on any container of bytes, where the byte type
+ is one of:
+
+ \list
+ \li \c char (both signed and unsigned)
+ \li \c std::byte
+ \endlist
+
+ \sa QByteArray, QStringView
+*/
+
+/*!
+ \typedef QByteArrayView::storage_type
+
+ Alias for \c char.
+*/
+
+/*!
+ \typedef QByteArrayView::value_type
+
+ Alias for \c{const char}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::difference_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::size_type
+
+ Alias for qsizetype. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+
+ QByteArrayView does not support mutable references, so this is the same
+ as const_reference.
+*/
+
+/*!
+ \typedef QByteArrayView::const_reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+
+ QByteArrayView does not support mutable pointers, so this is the same
+ as const_pointer.
+*/
+
+/*!
+ \typedef QByteArrayView::const_pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::iterator
+
+ This typedef provides an STL-style const iterator for QByteArrayView.
+
+ QByteArrayView does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QByteArrayView::const_iterator
+
+ This typedef provides an STL-style const iterator for QByteArrayView.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QByteArrayView::reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QByteArrayView.
+
+ QByteArrayView does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QByteArrayView::const_reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QByteArrayView.
+
+ \sa reverse_iterator, const_iterator
+*/
+
+/*!
+ \fn QByteArrayView::QByteArrayView()
+
+ Constructs a null byte array view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QByteArrayView::QByteArrayView(std::nullptr_t)
+
+ Constructs a null byte array view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn template <typename Byte, QByteArrayView::if_compatible_byte<Byte> = true> QByteArrayView::QByteArrayView(const Byte *data, qsizetype len)
+
+ Constructs a byte array view on \a data with length \a len.
+
+ The range \c{[data,len)} must remain valid for the lifetime of this QByteArrayView.
+
+ Passing \nullptr as \a data is safe if \a len is 0, too, and results in a null
+ byte array view.
+
+ The behavior is undefined if \a len is negative or, when positive, if \a data is \nullptr.
+
+ This constructor only participates in overload resolution if \c Byte is a compatible
+ byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <typename Byte, QByteArrayView::if_compatible_byte<Byte> = true> QByteArrayView::QByteArrayView(const Byte *first, const Byte *last)
+
+ Constructs a byte array view on \a first with length (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this QByteArrayView.
+
+ Passing \c \nullptr as \a first is safe if \a last is \nullptr, too,
+ and results in a null byte array view.
+
+ The behavior is undefined if \a last precedes \a first, or \a first
+ is \nullptr and \a last is not.
+
+ This constructor only participates in overload resolution if \c Byte is
+ a compatible byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <typename Byte> QByteArrayView::QByteArrayView(const Byte *data)
+
+ Constructs a byte array view on \a data. The length is determined
+ by scanning for the first \c{Byte(0)}.
+
+ \a data must remain valid for the lifetime of this byte array view object.
+
+ Passing \nullptr as \a data is safe and results in a null byte array view.
+
+ This constructor only participates in overload resolution if \a data is not
+ an array and if \c Byte is a compatible byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <size_t Size> QByteArrayView::QByteArrayView(const char (&data)[Size])
+
+ Constructs a byte array view on the char array \a data.
+ The view covers the array until the first \c{'\0'} is encountered,
+ or \c Size, whichever comes first.
+ If you need the full array, use fromArray() instead.
+
+ \a data must remain valid for the lifetime of this byte array view
+ object.
+
+ \note This constructor is only available for char array literals.
+ The reasoning behind that is for compatibility with C-libraries
+ which predefine "large-enough" arrays, but only use some of the
+ preallocated space. To support this in an intuitive way in an
+ implicit constructor overload, we need to stop at the first
+ \c{char(0)}. This is logical for a char array, but not
+ for a \c{std::byte} array.
+
+ \sa fromArray
+*/
+
+/*!
+ \fn QByteArrayView::QByteArrayView(const QByteArray &byteArray)
+
+ Constructs a byte array view on \a byteArray.
+
+ \c{byteArray.data()} must remain valid for the lifetime of this byte array view object.
+
+ The byte array view will be null if and only if \c{byteArray.isNull()}.
+*/
+
+/*!
+ \fn template <typename Container, QByteArrayView::if_compatible_container<Container> = true> QByteArrayView::QByteArrayView(const Container &c)
+
+ Constructs a byte array view on the array-like container \a c. The length and data
+ are set via \c{std::size(c)} and \c{std::data(c)} respectively.
+
+ The container's data must remain valid for the lifetime of this byte array view object.
+
+ This constructor participates in overload resolution if \a c is any contiguous
+ container with elements of a compatible byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <typename Byte, size_t Size> QByteArrayView QByteArrayView::fromArray(const Byte (&data)[Size])
+
+ Constructs a byte array view on the array literal \a data. The view covers the full
+ array. That includes the trailing null-terminator of \c{char} array literals.
+ If you don't want the null-terminator included in the view, you can chop() it off
+ when you are certain it is at the end. Alternatively you can use the constructor
+ overload taking a char array literal which will create a view up to, but not including,
+ the first null-terminator in the data.
+
+ This function will work with any array literal of a compatible byte type.
+
+ \sa {Compatible Byte Types}, QByteArrayView
+*/
+
+/*!
+ \fn QByteArray QByteArrayView::toByteArray() const
+
+ Returns a deep copy of this byte array view's data as a QByteArray.
+
+ The return value will be a null QByteArray if and only if this byte array
+ view is null.
+*/
+
+/*!
+ \fn const char *QByteArrayView::data() const
+
+ Returns a const \c char pointer to the first byte in the byte array view.
+
+ \note The character array represented by the return value is \e not guaranteed
+ to be null-terminated. The returned pointer is only safe to use for accessing
+ bytes at indices that are less than this byte array view's size().
+
+ \sa begin(), end()
+*/
+
+/*!
+ \fn const char *QByteArrayView::constData() const
+
+ Returns a const \c char pointer to the first byte in the byte array view.
+
+ \note The character array represented by the return value is \e not guaranteed
+ to be null-terminated. The returned pointer is only safe to use for accessing
+ bytes at indices that are less than this byte array view's size().
+
+ \sa data(), begin(), end()
+*/
+
+/*! //! friend
+ \fn int QByteArrayView::operator==(const QByteArrayView &lhs, const QByteArrayView &rhs)
+ \fn int QByteArrayView::operator!=(const QByteArrayView &lhs, const QByteArrayView &rhs)
+ \fn int QByteArrayView::operator< (const QByteArrayView &lhs, const QByteArrayView &rhs)
+ \fn int QByteArrayView::operator<=(const QByteArrayView &lhs, const QByteArrayView &rhs)
+ \fn int QByteArrayView::operator> (const QByteArrayView &lhs, const QByteArrayView &rhs)
+ \fn int QByteArrayView::operator>=(const QByteArrayView &lhs, const QByteArrayView &rhs)
+
+ Comparison operators for QByteArrayView.
+*/
+
+/*!
+ \fn int QByteArrayView::compare(QByteArrayView bv, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.2
+
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether this QByteArrayView sorts before, at the same position as, or after
+ the QByteArrayView \a bv. The comparison is performed according to case
+ sensitivity \a cs.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QByteArrayView::isValidUtf8() const
+
+ Returns \c true if this byte array view contains valid UTF-8 encoded data,
+ or \c false otherwise.
+
+ \since 6.3
+*/
+
+/*!
+ \fn QByteArrayView::const_iterator QByteArrayView::begin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first byte in the byte array view.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QByteArrayView::const_iterator QByteArrayView::cbegin() const
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QByteArrayView::const_iterator QByteArrayView::end() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing
+ just after the last byte in the byte array view.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QByteArrayView::const_iterator QByteArrayView::cend() const
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::rbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to the first byte in the byte array view, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::crbegin() const
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::rend() const
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last byte in the byte array view, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::crend() const
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
+/*!
+ \fn bool QByteArrayView::empty() const
+
+ Returns \c true if this byte array view is empty - that is, \c{size() == 0}.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn bool QByteArrayView::isEmpty() const
+
+ Returns \c true if this byte array view is empty - that is, \c{size() == 0}.
+
+ \sa empty(), isNull(), size()
+*/
+
+/*!
+ \fn bool QByteArrayView::isNull() const
+
+ Returns \c true if this byte array view is null - that is, \c{data() == nullptr}.
+
+ \sa empty(), isEmpty(), size()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::size() const
+
+ Returns the number of bytes in this byte array view.
+
+ \sa empty(), isEmpty(), isNull()
+*/
+
+/*!
+ \fn QByteArrayView::length() const
+
+ Same as size().
+
+ \sa empty(), isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn char QByteArrayView::operator[](qsizetype n) const
+
+ Returns the character at position \a n in this byte array view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa at(), front(), back()
+*/
+
+/*!
+ \fn char QByteArrayView::at(qsizetype n) const
+
+ Returns the character at position \a n in this byte array view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa operator[](), front(), back()
+*/
+
+/*!
+ \fn char QByteArrayView::front() const
+
+ Returns the first byte in the byte array view.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array view constitutes
+ undefined behavior.
+
+ \sa back()
+*/
+
+/*!
+ \fn char QByteArrayView::back() const
+
+ Returns the last byte in the byte array view.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array view constitutes
+ undefined behavior.
+
+ \sa front()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::first(qsizetype n) const
+
+ Returns a byte array view that points to the first \a n bytes
+ of this byte array view. Equivalent to \c{sliced(0, n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa last(), startsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::last(qsizetype n) const
+
+ Returns a byte array view that points to the last \a n bytes
+ of this byte array view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa first(), endsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::sliced(qsizetype pos, qsizetype n) const
+
+ Returns a byte array view that points to \a n bytes of this byte array
+ view, starting at position \a pos.
+
+//! [UB-sliced-index-length]
+ \note The behavior is undefined when \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+//! [UB-sliced-index-length]
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::sliced(qsizetype pos) const
+
+ Returns a byte array view starting at position \a pos in this object,
+ and extending to its end.
+
+//! [UB-sliced-index-only]
+ \note The behavior is undefined when \a pos < 0 or \a pos > size().
+//! [UB-sliced-index-only]
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::chopped(qsizetype length) const
+
+ Returns a copy of this byte array view that omits its last \a length bytes.
+ In other words, returns a byte array view of length size() - \a length starting
+ at the beginning of this object.
+
+ Same as \c{first(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa first(), last(), sliced(), chop(), truncate()
+*/
+
+/*!
+ \fn void QByteArrayView::truncate(qsizetype length)
+
+ Truncates this byte array view to length \a length.
+
+ Same as \c{*this = first(length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa first(), last(), sliced(), chopped(), chop()
+*/
+
+/*!
+ \fn void QByteArrayView::chop(qsizetype length)
+
+ Truncates this byte array view by \a length characters.
+
+ Same as \c{*this = first(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa sliced(), first(), last(), chopped(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::mid(qsizetype start, qsizetype length) const
+ \since 6.5
+
+ \deprecated Use sliced() instead in new code.
+
+ Returns the subarray of length \a length starting at position
+ \a start in this object.
+
+ Returns an empty byte array view if \a start exceeds the
+ length of the byte array view. If there are less than \a length characters
+ available in the byte array view starting at \a start, or if
+ \a length is negative (default), the function returns all characters that
+ are available from \a start.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::left(qsizetype length) const
+ \since 6.5
+
+ \deprecated Use first() instead in new code.
+
+ Returns the subarray of length \a length starting at position
+ 0 in this object.
+
+ The entire byte array view is returned if \a length is greater than or equal
+ to size(), or less than zero.
+
+ \sa first(), last(), sliced(), startsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::right(qsizetype length) const
+ \since 6.5
+
+ \deprecated Use last() instead in new code.
+
+ Returns the subarray of length \a length starting at position
+ size() - \a length in this object.
+
+ The entire byte array view is returned if \a length is greater than or equal
+ to size(), or less than zero.
+
+ \sa first(), last(), sliced(), endsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::trimmed() const noexcept
+ \since 6.3
+
+ Returns a copy of this byte array view with spacing characters
+ removed from the start and end.
+
+ The spacing characters are those for which the standard C++ \c isspace()
+ function returns \c true in the C locale; these are the ASCII characters
+ tabulation '\\t', line feed '\\n', carriage return '\\r', vertical
+ tabulation '\\v', form feed '\\f', and space ' '.
+
+ \sa QChar::SpecialCharacter, {QByteArray#Spacing Characters}{Spacing Characters}
+*/
+
+/*!
+ \fn qlonglong QByteArrayView::toLongLong(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to a \c {long long} using base \a
+ base, which is ten by default. Bases 0 and 2 through 36 are supported, using
+ letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn qulonglong QByteArrayView::toULongLong(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to an \c {unsigned long long} using
+ base \a base, which is ten by default. Bases 0 and 2 through 36 are
+ supported, using letters for digits beyond 9; A is ten, B is eleven and so
+ on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn int QByteArrayView::toInt(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to an \c int using base \a base,
+ which is ten by default. Bases 0 and 2 through 36 are supported, using
+ letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \snippet code/src_corelib_text_qbytearrayview.cpp 2
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn uint QByteArrayView::toUInt(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to an \c {unsigned int} using base \a
+ base, which is ten by default. Bases 0 and 2 through 36 are supported, using
+ letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn long QByteArrayView::toLong(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to a \c long int using base \a base,
+ which is ten by default. Bases 0 and 2 through 36 are supported, using
+ letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \snippet code/src_corelib_text_qbytearrayview.cpp 3
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn ulong QByteArrayView::toULong(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to an \c {unsigned long int} using
+ base \a base, which is ten by default. Bases 0 and 2 through 36 are
+ supported, using letters for digits beyond 9; A is ten, B is eleven and so
+ on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn short QByteArrayView::toShort(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to a \c short using base \a base,
+ which is ten by default. Bases 0 and 2 through 36 are supported, using
+ letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn ushort QByteArrayView::toUShort(bool *ok, int base) const
+ \since 6.3
+
+ Returns this byte array view converted to an \c {unsigned short} using base
+ \a base, which is ten by default. Bases 0 and 2 through 36 are supported,
+ using letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules: if the byte array view begins with "0x", the rest of it is read as
+ hexadecimal (base 16); otherwise, if it begins with "0", the rest of it is
+ read as octal (base 8); otherwise it is read as decimal.
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+*/
+
+/*!
+ \fn double QByteArrayView::toDouble(bool *ok) const
+ \since 6.3
+
+ Returns this byte array view converted to a \c double value.
+
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for other reasons (e.g. underflow).
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \warning The QByteArrayView content may only contain valid numerical
+ characters which includes the plus/minus sign, the character e used in
+ scientific notation, and the decimal point. Including the unit or additional
+ characters leads to a conversion error.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+
+ This function ignores leading and trailing spacing characters.
+*/
+
+/*!
+ \fn float QByteArrayView::toFloat(bool *ok) const
+ \since 6.3
+
+ Returns this byte array view converted to a \c float value.
+
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for other reasons (e.g. underflow).
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \snippet code/src_corelib_text_qbytearrayview.cpp 4
+
+ \warning The QByteArrayView content may only contain valid numerical
+ characters which includes the plus/minus sign, the character e used in
+ scientific notation, and the decimal point. Including the unit or additional
+ characters leads to a conversion error.
+
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+
+ This function ignores leading and trailing whitespace.
+*/
+
+/*!
+ \fn bool QByteArrayView::startsWith(QByteArrayView bv) const
+ \fn bool QByteArrayView::startsWith(char ch) const
+
+ Returns \c true if this byte array view starts with byte array view \a bv
+ or character \a ch, respectively; otherwise returns \c false.
+
+ \sa endsWith()
+*/
+
+/*!
+ \fn bool QByteArrayView::endsWith(QByteArrayView bv) const
+ \fn bool QByteArrayView::endsWith(char ch) const
+
+ Returns \c true if this byte array view ends with byte array view \a bv
+ or character \a ch, respectively; otherwise returns \c false.
+
+ \sa startsWith()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::indexOf(QByteArrayView bv, qsizetype from = 0) const
+ \fn qsizetype QByteArrayView::indexOf(char ch, qsizetype from = 0) const
+
+ Returns the index position of either the start of the first occurrence of
+ the sequence of bytes viewed by \a bv or the first occurrence of byte \a ch,
+ respectively, in this byte array view, searching forward from index position
+ \a from.Returns -1 if no match is found.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ \sa lastIndexOf(), contains()
+*/
+
+/*!
+ \fn bool QByteArrayView::contains(QByteArrayView bv) const
+ \fn bool QByteArrayView::contains(char ch) const
+
+ Returns \c true if this byte array view contains an occurrence of the sequence
+ of bytes viewed by \a bv or character \a ch, respectively; otherwise returns
+ \c false.
+
+ \sa indexOf(), lastIndexOf()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::lastIndexOf(QByteArrayView bv, qsizetype from) const
+ \fn qsizetype QByteArrayView::lastIndexOf(char ch, qsizetype from = -1) const
+
+ Returns the index position of either the start of the last occurrence of
+ the sequence of bytes viewed by \a bv or the last occurrence of byte \a ch,
+ respectively, in this byte array view, searching backward from index position
+ \a from.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if no match is found.
+
+ \note When searching for a 0-length \a bv, the match at the end of
+ the data is excluded from the search by a negative \a from, even
+ though \c{-1} is normally thought of as searching from the end of
+ the view: the match at the end is \e after the last character, so
+ it is excluded. To include such a final empty match, either give a
+ positive value for \a from or omit the \a from parameter entirely.
+
+ \sa indexOf(), contains()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::lastIndexOf(QByteArrayView bv) const
+ \since 6.2
+ \overload
+
+ Returns the index position of the start of the last
+ occurrence of the sequence of bytes viewed by \a bv in this byte
+ array view, searching backward from the end of this byte array
+ view. Returns -1 if no match is found.
+
+ \sa indexOf(), contains()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::count(QByteArrayView bv) const
+
+ Returns the number of (potentially overlapping) occurrences of the
+ sequence of bytes viewed by \a bv in this byte array view.
+
+ \sa contains(), indexOf()
+*/
+
+/*!
+ \fn bool QByteArrayView::count(char ch) const
+ \overload
+
+ Returns the number of occurrences of byte \a ch in this byte array view.
+
+ \sa contains(), indexOf()
+*/
+
+/*!
+ \fn QByteArrayView qToByteArrayViewIgnoringNull(const QByteArray &b);
+ \internal
+
+ Convert \a b to a QByteArrayView ignoring \c{b.isNull()}.
+
+ Returns a byte array view that references \a{b}'s data, but is never null.
+
+ This is a faster way to convert a QByteArray to a QByteArrayView,
+ if null QByteArray can legitimately be treated as empty ones.
+
+ \sa QByteArray::isNull(), QByteArrayView
+*/
+
+/*!
+ \fn QByteArrayView::operator std::string_view() const
+ \since 6.7
+
+ Converts this QByteArrayView object to a \c{std::string_view} object.
+ The returned view will have the same data pointer and length of
+ this view.
+*/
diff --git a/src/corelib/text/qbytedata_p.h b/src/corelib/text/qbytedata_p.h
index 108aec72ac..fcbf82d6ce 100644
--- a/src/corelib/text/qbytedata_p.h
+++ b/src/corelib/text/qbytedata_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBYTEDATA_P_H
#define QBYTEDATA_P_H
@@ -53,6 +17,9 @@
#include <QtCore/private/qglobal_p.h>
#include <qbytearray.h>
+#include <QtCore/qlist.h>
+
+#include <climits>
QT_BEGIN_NAMESPACE
@@ -90,31 +57,55 @@ public:
popFront(buffers[bufferCount() - other.bufferCount()], other.firstPos);
}
+ inline void append(QByteDataBuffer &&other)
+ {
+ if (other.isEmpty())
+ return;
+
+ auto otherBufferCount = other.bufferCount();
+ auto otherByteAmount = other.byteAmount();
+ buffers.append(std::move(other.buffers));
+ bufferCompleteSize += otherByteAmount;
+
+ if (other.firstPos > 0)
+ popFront(buffers[bufferCount() - otherBufferCount], other.firstPos);
+ }
inline void append(const QByteArray& bd)
{
+ append(QByteArray(bd));
+ }
+
+ inline void append(QByteArray &&bd)
+ {
if (bd.isEmpty())
return;
- buffers.append(bd);
bufferCompleteSize += bd.size();
+ buffers.append(std::move(bd));
}
inline void prepend(const QByteArray& bd)
{
+ prepend(QByteArray(bd));
+ }
+
+ inline void prepend(QByteArray &&bd)
+ {
if (bd.isEmpty())
return;
squeezeFirst();
- buffers.prepend(bd);
bufferCompleteSize += bd.size();
+ buffers.prepend(std::move(bd));
}
// return the first QByteData. User of this function has to free() its .data!
// preferably use this function to read data.
inline QByteArray read()
{
+ Q_ASSERT(!isEmpty());
squeezeFirst();
bufferCompleteSize -= buffers.first().size();
return buffers.takeFirst();
@@ -132,8 +123,15 @@ public:
inline QByteArray read(qint64 amount)
{
amount = qMin(byteAmount(), amount);
+ if constexpr (sizeof(qsizetype) == sizeof(int)) { // 32-bit
+ // While we cannot overall have more than INT_MAX memory allocated,
+ // the QByteArrays we hold may be shared copies of each other,
+ // causing byteAmount() to exceed INT_MAX.
+ if (amount > INT_MAX)
+ qBadAlloc(); // what resize() would do if it saw past the truncation
+ }
QByteArray byteData;
- byteData.resize(amount);
+ byteData.resize(qsizetype(amount));
read(byteData.data(), byteData.size());
return byteData;
}
@@ -169,8 +167,59 @@ public:
return originalAmount;
}
+ /*!
+ \internal
+ Returns a view into the first QByteArray contained inside,
+ ignoring any already read data. Call advanceReadPointer()
+ to advance the view forward. When a QByteArray is exhausted
+ the view returned by this function will view into another
+ QByteArray if any. Returns a default constructed view if
+ no data is available.
+
+ \sa advanceReadPointer
+ */
+ QByteArrayView readPointer() const
+ {
+ if (isEmpty())
+ return {};
+ return { buffers.first().constData() + qsizetype(firstPos),
+ buffers.first().size() - qsizetype(firstPos) };
+ }
+
+ /*!
+ \internal
+ Advances the read pointer by \a distance.
+
+ \sa readPointer
+ */
+ void advanceReadPointer(qint64 distance)
+ {
+ qint64 newPos = firstPos + distance;
+ if (isEmpty()) {
+ newPos = 0;
+ } else if (auto size = buffers.first().size(); newPos >= size) {
+ while (newPos >= size) {
+ bufferCompleteSize -= (size - firstPos);
+ newPos -= size;
+ buffers.pop_front();
+ if (isEmpty()) {
+ size = 0;
+ newPos = 0;
+ break;
+ }
+ size = buffers.front().size();
+ }
+ bufferCompleteSize -= newPos;
+ } else {
+ bufferCompleteSize -= newPos - firstPos;
+ }
+ firstPos = newPos;
+ }
+
inline char getChar()
{
+ Q_ASSERT_X(!isEmpty(), "QByteDataBuffer::getChar",
+ "Cannot read a char from an empty buffer!");
char c;
read(&c, 1);
return c;
@@ -190,9 +239,9 @@ public:
}
// the number of QByteArrays
- inline int bufferCount() const
+ qsizetype bufferCount() const
{
- return buffers.length();
+ return buffers.size();
}
inline bool isEmpty() const
@@ -202,13 +251,13 @@ public:
inline qint64 sizeNextBlock() const
{
- if(buffers.isEmpty())
+ if (buffers.isEmpty())
return 0;
else
return buffers.first().size() - firstPos;
}
- inline QByteArray& operator[](int i)
+ QByteArray &operator[](qsizetype i)
{
if (i == 0)
squeezeFirst();
@@ -217,13 +266,13 @@ public:
}
inline bool canReadLine() const {
- int i = 0;
- if (i < buffers.length()) {
+ qsizetype i = 0;
+ if (i < buffers.size()) {
if (buffers.at(i).indexOf('\n', firstPos) != -1)
return true;
++i;
- for (; i < buffers.length(); i++)
+ for (; i < buffers.size(); i++)
if (buffers.at(i).contains('\n'))
return true;
}
diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp
index 628d4ab370..63296a92de 100644
--- a/src/corelib/text/qchar.cpp
+++ b/src/corelib/text/qchar.cpp
@@ -1,50 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// Don't define it while compiling this module, or USERS of Qt will
-// not be able to link.
-#ifdef QT_NO_CAST_FROM_ASCII
-# undef QT_NO_CAST_FROM_ASCII
-#endif
-#ifdef QT_NO_CAST_TO_ASCII
-# undef QT_NO_CAST_TO_ASCII
-#endif
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
#include "qchar.h"
#include "qdatastream.h"
@@ -68,7 +24,7 @@ QT_BEGIN_NAMESPACE
This class is only useful to construct a QChar with 8-bit character.
- \sa QChar, QLatin1String, QString
+ \sa QChar, QLatin1StringView, QString
*/
/*!
@@ -99,6 +55,13 @@ QT_BEGIN_NAMESPACE
\ingroup string-processing
\reentrant
+ \compares strong
+ \compareswith strong char16_t QString QStringView QLatin1StringView QUtf8StringView
+ \endcompareswith
+ \compareswith strong {const char *} QByteArray QByteArrayView
+ The contents of the byte array is interpreted as utf-8.
+ \endcompareswith
+
In Qt, Unicode characters are 16-bit entities without any markup
or structure. This class represents such an entity. It is
lightweight, so it can be used everywhere. Most compilers treat
@@ -158,8 +121,14 @@ QT_BEGIN_NAMESPACE
to construct a QChar from an 8-bit \c char, and you will need to
call toLatin1() to get the 8-bit value back.
+ Starting with Qt 6.0, most QChar constructors are \c explicit. This
+ is done to avoid dangerous mistakes when accidentally mixing
+ integral types and strings. You can opt-out (and make these
+ constructors implicit) by defining the macro \c
+ QT_IMPLICIT_QCHAR_CONSTRUCTION.
+
For more information see
- \l{http://www.unicode.org/ucd/}{"About the Unicode Character Database"}.
+ \l{https://www.unicode.org/ucd/}{"About the Unicode Character Database"}.
\sa Unicode, QString, QLatin1Char
*/
@@ -167,8 +136,8 @@ QT_BEGIN_NAMESPACE
/*!
\enum QChar::UnicodeVersion
- Specifies which version of the \l{http://www.unicode.org/}{Unicode standard}
- introduced a certain character.
+ Specifies which version of the \l{Unicode standard} introduced a certain
+ character.
\value Unicode_1_1 Version 1.1
\value Unicode_2_0 Version 2.0
@@ -184,15 +153,18 @@ QT_BEGIN_NAMESPACE
\value Unicode_6_0 Version 6.0
\value Unicode_6_1 Version 6.1
\value Unicode_6_2 Version 6.2
- \value Unicode_6_3 Version 6.3 Since Qt 5.3
- \value Unicode_7_0 Version 7.0 Since Qt 5.5
- \value Unicode_8_0 Version 8.0 Since Qt 5.6
- \value Unicode_9_0 Version 9.0 Since Qt 5.11
- \value Unicode_10_0 Version 10.0 Since Qt 5.11
- \value Unicode_11_0 Version 11.0 Since Qt 5.15
- \value Unicode_12_0 Version 12.0 Since Qt 5.15
- \value Unicode_12_1 Version 12.1 Since Qt 5.15
- \value Unicode_13_0 Version 13.0 Since Qt 5.15
+ \value [since 5.3] Unicode_6_3 Version 6.3
+ \value [since 5.5] Unicode_7_0 Version 7.0
+ \value [since 5.6] Unicode_8_0 Version 8.0
+ \value [since 5.11] Unicode_9_0 Version 9.0
+ \value [since 5.11] Unicode_10_0 Version 10.0
+ \value [since 5.15] Unicode_11_0 Version 11.0
+ \value [since 5.15] Unicode_12_0 Version 12.0
+ \value [since 5.15] Unicode_12_1 Version 12.1
+ \value [since 5.15] Unicode_13_0 Version 13.0
+ \value [since 6.3] Unicode_14_0 Version 14.0
+ \value [since 6.5] Unicode_15_0 Version 15.0
+ \value [since 6.8] Unicode_15_1 Version 15.1
\value Unicode_Unassigned The value is not assigned to any character
in version 8.0 of Unicode.
@@ -279,7 +251,7 @@ QT_BEGIN_NAMESPACE
This enum type defines the Unicode script property values.
For details about the Unicode script property values see
- \l{http://www.unicode.org/reports/tr24/}{Unicode Standard Annex #24}.
+ \l{https://www.unicode.org/reports/tr24/}{Unicode Standard Annex #24}.
In order to conform to C/C++ naming conventions "Script_" is prepended
to the codes used in the Unicode Standard.
@@ -292,18 +264,18 @@ QT_BEGIN_NAMESPACE
\value Script_Common For characters that may be used with multiple scripts
and that do not inherit their script from the preceding characters.
- \value Script_Adlam Since Qt 5.11
- \value Script_Ahom Since Qt 5.6
- \value Script_AnatolianHieroglyphs Since Qt 5.6
+ \value [since 5.11] Script_Adlam
+ \value [since 5.6] Script_Ahom
+ \value [since 5.6] Script_AnatolianHieroglyphs
\value Script_Arabic
\value Script_Armenian
\value Script_Avestan
\value Script_Balinese
\value Script_Bamum
- \value Script_BassaVah Since Qt 5.5
+ \value [since 5.5] Script_BassaVah
\value Script_Batak
\value Script_Bengali
- \value Script_Bhaiksuki Since Qt 5.11
+ \value [since 5.11] Script_Bhaiksuki
\value Script_Bopomofo
\value Script_Brahmi
\value Script_Braille
@@ -311,37 +283,38 @@ QT_BEGIN_NAMESPACE
\value Script_Buhid
\value Script_CanadianAboriginal
\value Script_Carian
- \value Script_CaucasianAlbanian Since Qt 5.5
+ \value [since 5.5] Script_CaucasianAlbanian
\value Script_Chakma
\value Script_Cham
\value Script_Cherokee
- \value Script_Chorasmian Since Qt 5.15
+ \value [since 5.15] Script_Chorasmian
\value Script_Coptic
\value Script_Cuneiform
\value Script_Cypriot
+ \value [since 6.3] Script_CyproMinoan
\value Script_Cyrillic
\value Script_Deseret
\value Script_Devanagari
- \value Script_DivesAkuru Since Qt 5.15
- \value Script_Dogra Since Qt 5.15
- \value Script_Duployan Since Qt 5.5
+ \value [since 5.15] Script_DivesAkuru
+ \value [since 5.15] Script_Dogra
+ \value [since 5.5] Script_Duployan
\value Script_EgyptianHieroglyphs
- \value Script_Elbasan Since Qt 5.5
- \value Script_Elymaic Since Qt 5.15
+ \value [since 5.5] Script_Elbasan
+ \value [since 5.15] Script_Elymaic
\value Script_Ethiopic
\value Script_Georgian
\value Script_Glagolitic
\value Script_Gothic
- \value Script_Grantha Since Qt 5.5
+ \value [since 5.5] Script_Grantha
\value Script_Greek
\value Script_Gujarati
- \value Script_GunjalaGondi Since Qt 5.15
+ \value [since 5.15] Script_GunjalaGondi
\value Script_Gurmukhi
\value Script_Han
\value Script_Hangul
- \value Script_HanifiRohingya Since Qt 5.15
+ \value [since 5.15] Script_HanifiRohingya
\value Script_Hanunoo
- \value Script_Hatran Since Qt 5.6
+ \value [since 5.6] Script_Hatran
\value Script_Hebrew
\value Script_Hiragana
\value Script_ImperialAramaic
@@ -351,77 +324,80 @@ QT_BEGIN_NAMESPACE
\value Script_Kaithi
\value Script_Kannada
\value Script_Katakana
+ \value [since 6.5] Script_Kawi
\value Script_KayahLi
\value Script_Kharoshthi
- \value Script_KhitanSmallScript Since Qt 5.15
+ \value [since 5.15] Script_KhitanSmallScript
\value Script_Khmer
- \value Script_Khojki Since Qt 5.5
- \value Script_Khudawadi Since Qt 5.5
+ \value [since 5.5] Script_Khojki
+ \value [since 5.5] Script_Khudawadi
\value Script_Lao
\value Script_Latin
\value Script_Lepcha
\value Script_Limbu
- \value Script_LinearA Since Qt 5.5
+ \value [since 5.5] Script_LinearA
\value Script_LinearB
\value Script_Lisu
\value Script_Lycian
\value Script_Lydian
- \value Script_Mahajani Since Qt 5.5
- \value Script_Makasar Since Qt 5.15
+ \value [since 5.5] Script_Mahajani
+ \value [since 5.15] Script_Makasar
\value Script_Malayalam
\value Script_Mandaic
- \value Script_Manichaean Since Qt 5.5
- \value Script_Marchen Since Qt 5.11
- \value Script_MasaramGondi Since Qt 5.11
- \value Script_Medefaidrin Since Qt 5.15
+ \value [since 5.5] Script_Manichaean
+ \value [since 5.11] Script_Marchen
+ \value [since 5.11] Script_MasaramGondi
+ \value [since 5.15] Script_Medefaidrin
\value Script_MeeteiMayek
- \value Script_MendeKikakui Since Qt 5.5
+ \value [since 5.5] Script_MendeKikakui
\value Script_MeroiticCursive
\value Script_MeroiticHieroglyphs
\value Script_Miao
- \value Script_Modi Since Qt 5.5
+ \value [since 5.5] Script_Modi
\value Script_Mongolian
- \value Script_Mro Since Qt 5.5
- \value Script_Multani Since Qt 5.6
+ \value [since 5.5] Script_Mro
+ \value [since 5.6] Script_Multani
\value Script_Myanmar
- \value Script_Nabataean Since Qt 5.5
- \value Script_Nandinagari Since Qt 5.15
- \value Script_Newa Since Qt 5.11
+ \value [since 5.5] Script_Nabataean
+ \value [since 6.3] Script_NagMundari
+ \value [since 5.15] Script_Nandinagari
+ \value [since 5.11] Script_Newa
\value Script_NewTaiLue
\value Script_Nko
- \value Script_Nushu Since Qt 5.11
- \value Script_NyiakengPuachueHmong Since Qt 5.15
+ \value [since 5.11] Script_Nushu
+ \value [since 5.15] Script_NyiakengPuachueHmong
\value Script_Ogham
\value Script_OlChiki
- \value Script_OldHungarian Since Qt 5.6
+ \value [since 5.6] Script_OldHungarian
\value Script_OldItalic
- \value Script_OldNorthArabian Since Qt 5.5
- \value Script_OldPermic Since Qt 5.5
+ \value [since 5.5] Script_OldNorthArabian
+ \value [since 5.5] Script_OldPermic
\value Script_OldPersian
- \value Script_OldSogdian Since Qt 5.15
+ \value [since 5.15] Script_OldSogdian
\value Script_OldSouthArabian
\value Script_OldTurkic
+ \value [since 6.3] Script_OldUyghur
\value Script_Oriya
- \value Script_Osage Since Qt 5.11
+ \value [since 5.11] Script_Osage
\value Script_Osmanya
- \value Script_PahawhHmong Since Qt 5.5
- \value Script_Palmyrene Since Qt 5.5
- \value Script_PauCinHau Since Qt 5.5
+ \value [since 5.5] Script_PahawhHmong
+ \value [since 5.5] Script_Palmyrene
+ \value [since 5.5] Script_PauCinHau
\value Script_PhagsPa
\value Script_Phoenician
- \value Script_PsalterPahlavi Since Qt 5.5
+ \value [since 5.5] Script_PsalterPahlavi
\value Script_Rejang
\value Script_Runic
\value Script_Samaritan
\value Script_Saurashtra
\value Script_Sharada
\value Script_Shavian
- \value Script_Siddham Since Qt 5.5
- \value Script_SignWriting Since Qt 5.6
+ \value [since 5.5] Script_Siddham
+ \value [since 5.6] Script_SignWriting
\value Script_Sinhala
- \value Script_Sogdian Since Qt 5.15
+ \value [since 5.15] Script_Sogdian
\value Script_SoraSompeng
- \value Script_Soyombo Since Qt 5.11
+ \value [since 5.11] Script_Soyombo
\value Script_Sundanese
\value Script_SylotiNagri
\value Script_Syriac
@@ -432,20 +408,23 @@ QT_BEGIN_NAMESPACE
\value Script_TaiViet
\value Script_Takri
\value Script_Tamil
- \value Script_Tangut Since Qt 5.11
+ \value [since 5.11] Script_Tangut
+ \value [since 6.3] Script_Tangsa
\value Script_Telugu
\value Script_Thaana
\value Script_Thai
\value Script_Tibetan
\value Script_Tifinagh
- \value Script_Tirhuta Since Qt 5.5
+ \value [since 5.5] Script_Tirhuta
+ \value [since 6.3] Script_Toto
\value Script_Ugaritic
\value Script_Vai
- \value Script_Wancho Since Qt 5.15
- \value Script_WarangCiti Since Qt 5.5
- \value Script_Yezidi Since Qt 5.15
+ \value [since 6.3] Script_Vithkuqi
+ \value [since 5.15] Script_Wancho
+ \value [since 5.5] Script_WarangCiti
+ \value [since 5.15] Script_Yezidi
\value Script_Yi
- \value Script_ZanabazarSquare Since Qt 5.11
+ \value [since 5.11] Script_ZanabazarSquare
\omitvalue ScriptCount
@@ -456,8 +435,8 @@ QT_BEGIN_NAMESPACE
\enum QChar::Direction
This enum type defines the Unicode direction attributes. See the
- \l{http://www.unicode.org/reports/tr9/tr9-35.html#Table_Bidirectional_Character_Types}{Unicode Standard} for a description
- of the values.
+ \l{https://www.unicode.org/reports/tr9/tr9-35.html#Table_Bidirectional_Character_Types}{Unicode
+ Standard} for a description of the values.
In order to conform to C/C++ naming conventions "Dir" is prepended
to the codes used in the Unicode Standard.
@@ -470,18 +449,18 @@ QT_BEGIN_NAMESPACE
\value DirEN
\value DirES
\value DirET
- \value DirFSI Since Qt 5.3
+ \value [since 5.3] DirFSI
\value DirL
\value DirLRE
- \value DirLRI Since Qt 5.3
+ \value [since 5.3] DirLRI
\value DirLRO
\value DirNSM
\value DirON
\value DirPDF
- \value DirPDI Since Qt 5.3
+ \value [since 5.3] DirPDI
\value DirR
\value DirRLE
- \value DirRLI Since Qt 5.3
+ \value [since 5.3] DirRLI
\value DirRLO
\value DirS
\value DirWS
@@ -493,8 +472,7 @@ QT_BEGIN_NAMESPACE
\enum QChar::Decomposition
This enum type defines the Unicode decomposition attributes. See
- the \l{http://www.unicode.org/}{Unicode Standard} for a
- description of the values.
+ the \l{Unicode standard} for a description of the values.
\value NoDecomposition
\value Canonical
@@ -523,7 +501,7 @@ QT_BEGIN_NAMESPACE
since 5.3
This enum type defines the Unicode joining type attributes. See the
- \l{http://www.unicode.org/}{Unicode Standard} for a description of the values.
+ \l{Unicode standard} for a description of the values.
In order to conform to C/C++ naming conventions "Joining_" is prepended
to the codes used in the Unicode Standard.
@@ -538,32 +516,13 @@ QT_BEGIN_NAMESPACE
\sa joiningType()
*/
-#if QT_DEPRECATED_SINCE(5, 3)
-/*!
- \enum QChar::Joining
- \deprecated in 5.3, use JoiningType instead.
-
- This enum type defines the Unicode joining attributes. See the
- \l{http://www.unicode.org/}{Unicode Standard} for a description
- of the values.
-
- \value Center
- \value Dual
- \value OtherJoining
- \value Right
-
- \sa joining()
-*/
-#endif
-
/*!
\enum QChar::CombiningClass
\internal
This enum type defines names for some of the Unicode combining
- classes. See the \l{http://www.unicode.org/}{Unicode Standard}
- for a description of the values.
+ classes. See the \l{Unicode Standard} for a description of the values.
\value Combining_Above
\value Combining_AboveAttached
@@ -607,6 +566,7 @@ QT_BEGIN_NAMESPACE
\value ByteOrderSwapped
\value ParagraphSeparator
\value LineSeparator
+ \value [since 6.2] VisualTabCharacter Used to represent a tabulation as a horizontal arrow.
\value LastValidCodePoint
*/
@@ -1270,38 +1230,6 @@ QChar::JoiningType QChar::joiningType(char32_t ucs4) noexcept
return QChar::JoiningType(qGetProp(ucs4)->joining);
}
-#if QT_DEPRECATED_SINCE(5, 3)
-/*!
- \fn QChar::Joining QChar::joining() const
- \deprecated in 5.3, use joiningType() instead.
-
- Returns information about the joining properties of the character
- (needed for certain languages such as Arabic).
-*/
-
-/*!
- \overload
- \deprecated in 5.3, use joiningType() instead.
-
- Returns information about the joining properties of the UCS-4-encoded
- character specified by \a ucs4 (needed for certain languages such as Arabic).
-
- \note Before Qt 6, this function took a \c uint argument.
-*/
-QChar::Joining QChar::joining(char32_t ucs4) noexcept
-{
- if (ucs4 > LastValidCodePoint)
- return QChar::OtherJoining;
- switch (qGetProp(ucs4)->joining) {
- case QChar::Joining_Causing: return QChar::Center;
- case QChar::Joining_Dual: return QChar::Dual;
- case QChar::Joining_Right: return QChar::Right;
- default: break;
- }
- return QChar::OtherJoining;
-}
-#endif
-
/*!
\fn bool QChar::hasMirrored() const
@@ -1423,31 +1351,28 @@ char32_t QChar::mirroredChar(char32_t ucs4) noexcept
return ucs4 + qGetProp(ucs4)->mirrorDiff;
}
-
-// constants for Hangul (de)composition, see UAX #15
-enum {
- Hangul_SBase = 0xac00,
- Hangul_LBase = 0x1100,
- Hangul_VBase = 0x1161,
- Hangul_TBase = 0x11a7,
- Hangul_LCount = 19,
- Hangul_VCount = 21,
- Hangul_TCount = 28,
- Hangul_NCount = Hangul_VCount * Hangul_TCount,
- Hangul_SCount = Hangul_LCount * Hangul_NCount
-};
+// Constants for Hangul (de)composition, see UAX #15:
+static constexpr char32_t Hangul_SBase = 0xac00;
+static constexpr char32_t Hangul_LBase = 0x1100;
+static constexpr char32_t Hangul_VBase = 0x1161;
+static constexpr char32_t Hangul_TBase = 0x11a7;
+static constexpr quint32 Hangul_LCount = 19;
+static constexpr quint32 Hangul_VCount = 21;
+static constexpr quint32 Hangul_TCount = 28;
+static constexpr quint32 Hangul_NCount = Hangul_VCount * Hangul_TCount;
+static constexpr quint32 Hangul_SCount = Hangul_LCount * Hangul_NCount;
// buffer has to have a length of 3. It's needed for Hangul decomposition
-static const unsigned short * QT_FASTCALL decompositionHelper
- (uint ucs4, int *length, int *tag, unsigned short *buffer)
+static const QChar * QT_FASTCALL decompositionHelper(
+ char32_t ucs4, qsizetype *length, QChar::Decomposition *tag, QChar *buffer)
{
if (ucs4 >= Hangul_SBase && ucs4 < Hangul_SBase + Hangul_SCount) {
// compute Hangul syllable decomposition as per UAX #15
- const uint SIndex = ucs4 - Hangul_SBase;
- buffer[0] = Hangul_LBase + SIndex / Hangul_NCount; // L
- buffer[1] = Hangul_VBase + (SIndex % Hangul_NCount) / Hangul_TCount; // V
- buffer[2] = Hangul_TBase + SIndex % Hangul_TCount; // T
- *length = buffer[2] == Hangul_TBase ? 2 : 3;
+ const char32_t SIndex = ucs4 - Hangul_SBase;
+ buffer[0] = QChar(Hangul_LBase + SIndex / Hangul_NCount); // L
+ buffer[1] = QChar(Hangul_VBase + (SIndex % Hangul_NCount) / Hangul_TCount); // V
+ buffer[2] = QChar(Hangul_TBase + SIndex % Hangul_TCount); // T
+ *length = buffer[2].unicode() == Hangul_TBase ? 2 : 3;
*tag = QChar::Canonical;
return buffer;
}
@@ -1460,9 +1385,9 @@ static const unsigned short * QT_FASTCALL decompositionHelper
}
const unsigned short *decomposition = uc_decomposition_map+index;
- *tag = (*decomposition) & 0xff;
+ *tag = QChar::Decomposition((*decomposition) & 0xff);
*length = (*decomposition) >> 8;
- return decomposition+1;
+ return reinterpret_cast<const QChar *>(decomposition + 1);
}
/*!
@@ -1483,11 +1408,11 @@ QString QChar::decomposition() const
*/
QString QChar::decomposition(char32_t ucs4)
{
- unsigned short buffer[3];
- int length;
- int tag;
- const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer);
- return QString(reinterpret_cast<const QChar *>(d), length);
+ QChar buffer[3];
+ qsizetype length;
+ QChar::Decomposition tag;
+ const QChar *d = decompositionHelper(ucs4, &length, &tag, buffer);
+ return QString(d, length);
}
/*!
@@ -1603,6 +1528,7 @@ static auto fullConvertCase(char32_t uc, QUnicodeTables::Case which) noexcept
auto data() const { return chars; }
auto size() const { return sz; }
} result;
+ Q_ASSERT(uc <= QChar::LastValidCodePoint);
auto pp = result.chars;
@@ -1615,7 +1541,7 @@ static auto fullConvertCase(char32_t uc, QUnicodeTables::Case which) noexcept
while (length--)
*pp++ = *specialCase++;
} else {
- // so far, case convertion never changes planes (guaranteed by the qunicodetables generator)
+ // so far, case conversion never changes planes (guaranteed by the qunicodetables generator)
for (char16_t c : QChar::fromUcs4(uc + caseDiff))
*pp++ = c;
}
@@ -1774,38 +1700,6 @@ char32_t QChar::toCaseFolded(char32_t ucs4) noexcept
\sa toLatin1(), unicode()
*/
-/*!
- \fn char QChar::toAscii() const
- \deprecated
-
- Returns the Latin-1 character value of the QChar, or 0 if the character is not
- representable.
-
- The main purpose of this function is to preserve ASCII characters used
- in C strings. This is mainly useful for developers of non-internationalized
- software.
-
- \note It is not possible to distinguish a non-Latin 1 character from an ASCII 0
- (NUL) character. Prefer to use unicode(), which does not have this ambiguity.
-
- \note This function does not check whether the character value is inside
- the valid range of US-ASCII.
-
- \sa toLatin1(), unicode()
-*/
-
-/*!
- \fn QChar QChar::fromAscii(char)
- \deprecated
-
- Converts the ASCII character \a c to it's equivalent QChar. This
- is mainly useful for non-internationalized software.
-
- An alternative is to use QLatin1Char.
-
- \sa fromLatin1(), unicode()
-*/
-
#ifndef QT_NO_DATASTREAM
/*!
\relates QChar
@@ -1853,75 +1747,80 @@ QDataStream &operator>>(QDataStream &in, QChar &chr)
*****************************************************************************/
/*!
- \fn bool operator==(QChar c1, QChar c2)
-
- \relates QChar
+ \fn bool QChar::operator==(const QChar &c1, const QChar &c2)
Returns \c true if \a c1 and \a c2 are the same Unicode character;
otherwise returns \c false.
*/
/*!
- \fn int operator!=(QChar c1, QChar c2)
-
- \relates QChar
+ \fn bool QChar::operator!=(const QChar &c1, const QChar &c2)
Returns \c true if \a c1 and \a c2 are not the same Unicode
character; otherwise returns \c false.
*/
/*!
- \fn int operator<=(QChar c1, QChar c2)
-
- \relates QChar
+ \fn bool QChar::operator<=(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is less than
or equal to that of \a c2; otherwise returns \c false.
*/
/*!
- \fn int operator>=(QChar c1, QChar c2)
-
- \relates QChar
+ \fn bool QChar::operator>=(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is greater than
or equal to that of \a c2; otherwise returns \c false.
*/
/*!
- \fn int operator<(QChar c1, QChar c2)
-
- \relates QChar
+ \fn bool QChar::operator<(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is less than
that of \a c2; otherwise returns \c false.
*/
/*!
- \fn int operator>(QChar c1, QChar c2)
-
- \relates QChar
+ \fn bool QChar::operator>(const QChar &c1, const QChar &c2)
Returns \c true if the numeric Unicode value of \a c1 is greater than
that of \a c2; otherwise returns \c false.
*/
+/*!
+ \fn Qt::Literals::StringLiterals::operator""_L1(char ch)
+
+ \relates QLatin1Char
+ \since 6.4
+
+ Literal operator that creates a QLatin1Char out of \a ch.
+
+ The following code creates a QLatin1Char:
+ \code
+ using namespace Qt::Literals::StringLiterals;
+
+ auto ch = 'a'_L1;
+ \endcode
+
+ \sa Qt::Literals::StringLiterals
+*/
// ---------------------------------------------------------------------------
-static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, int from)
+static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, qsizetype from)
{
- int length;
- int tag;
- unsigned short buffer[3];
+ qsizetype length;
+ QChar::Decomposition tag;
+ QChar buffer[3];
QString &s = *str;
const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data());
- const unsigned short *uc = utf16 + s.length();
+ const unsigned short *uc = utf16 + s.size();
while (uc != utf16 + from) {
- uint ucs4 = *(--uc);
+ char32_t ucs4 = *(--uc);
if (QChar(ucs4).isLowSurrogate() && uc != utf16) {
ushort high = *(uc - 1);
if (QChar(high).isHighSurrogate()) {
@@ -1933,12 +1832,12 @@ static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion
if (QChar::unicodeVersion(ucs4) > version)
continue;
- const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer);
+ const QChar *d = decompositionHelper(ucs4, &length, &tag, buffer);
if (!d || (canonical && tag != QChar::Canonical))
continue;
- int pos = uc - utf16;
- s.replace(pos, QChar::requiresSurrogates(ucs4) ? 2 : 1, reinterpret_cast<const QChar *>(d), length);
+ qsizetype pos = uc - utf16;
+ s.replace(pos, QChar::requiresSurrogates(ucs4) ? 2 : 1, d, length);
// since the replace invalidates the pointers and we do decomposition recursive
utf16 = reinterpret_cast<unsigned short *>(s.data());
uc = utf16 + pos + length;
@@ -1965,27 +1864,27 @@ struct UCS2SurrogatePair {
inline bool operator<(const UCS2SurrogatePair &ligature1, const UCS2SurrogatePair &ligature2)
{ return QChar::surrogateToUcs4(ligature1.p1.u1, ligature1.p1.u2) < QChar::surrogateToUcs4(ligature2.p1.u1, ligature2.p1.u2); }
-inline bool operator<(uint u1, const UCS2SurrogatePair &ligature)
+inline bool operator<(char32_t u1, const UCS2SurrogatePair &ligature)
{ return u1 < QChar::surrogateToUcs4(ligature.p1.u1, ligature.p1.u2); }
-inline bool operator<(const UCS2SurrogatePair &ligature, uint u1)
+inline bool operator<(const UCS2SurrogatePair &ligature, char32_t u1)
{ return QChar::surrogateToUcs4(ligature.p1.u1, ligature.p1.u2) < u1; }
-static uint inline ligatureHelper(uint u1, uint u2)
+static char32_t inline ligatureHelper(char32_t u1, char32_t u2)
{
- if (u1 >= Hangul_LBase && u1 <= Hangul_SBase + Hangul_SCount) {
+ if (u1 >= Hangul_LBase && u1 < Hangul_SBase + Hangul_SCount) {
// compute Hangul syllable composition as per UAX #15
// hangul L-V pair
- const uint LIndex = u1 - Hangul_LBase;
+ const char32_t LIndex = u1 - Hangul_LBase;
if (LIndex < Hangul_LCount) {
- const uint VIndex = u2 - Hangul_VBase;
+ const char32_t VIndex = u2 - Hangul_VBase;
if (VIndex < Hangul_VCount)
return Hangul_SBase + (LIndex * Hangul_VCount + VIndex) * Hangul_TCount;
}
// hangul LV-T pair
- const uint SIndex = u1 - Hangul_SBase;
+ const char32_t SIndex = u1 - Hangul_SBase;
if (SIndex < Hangul_SCount && (SIndex % Hangul_TCount) == 0) {
- const uint TIndex = u2 - Hangul_TBase;
- if (TIndex <= Hangul_TCount)
+ const char32_t TIndex = u2 - Hangul_TBase;
+ if (TIndex < Hangul_TCount && TIndex)
return u1 + TIndex;
}
}
@@ -2010,23 +1909,23 @@ static uint inline ligatureHelper(uint u1, uint u2)
return 0;
}
-static void composeHelper(QString *str, QChar::UnicodeVersion version, int from)
+static void composeHelper(QString *str, QChar::UnicodeVersion version, qsizetype from)
{
QString &s = *str;
- if (from < 0 || s.length() - from < 2)
+ if (from < 0 || s.size() - from < 2)
return;
- uint stcode = 0; // starter code point
- int starter = -1; // starter position
- int next = -1; // to prevent i == next
+ char32_t stcode = 0; // starter code point
+ qsizetype starter = -1; // starter position
+ qsizetype next = -1; // to prevent i == next
int lastCombining = 255; // to prevent combining > lastCombining
- int pos = from;
- while (pos < s.length()) {
- int i = pos;
+ qsizetype pos = from;
+ while (pos < s.size()) {
+ qsizetype i = pos;
char32_t uc = s.at(pos).unicode();
- if (QChar(uc).isHighSurrogate() && pos < s.length()-1) {
+ if (QChar(uc).isHighSurrogate() && pos < s.size()-1) {
ushort low = s.at(pos+1).unicode();
if (QChar(low).isLowSurrogate()) {
uc = QChar::surrogateToUcs4(uc, low);
@@ -2046,12 +1945,12 @@ static void composeHelper(QString *str, QChar::UnicodeVersion version, int from)
int combining = p->combiningClass;
if ((i == next || combining > lastCombining) && starter >= from) {
// allowed to form ligature with S
- uint ligature = ligatureHelper(stcode, uc);
+ char32_t ligature = ligatureHelper(stcode, uc);
if (ligature) {
stcode = ligature;
QChar *d = s.data();
// ligatureHelper() never changes planes
- int j = 0;
+ qsizetype j = 0;
for (QChar ch : QChar::fromUcs4(ligature))
d[starter + j++] = ch;
s.remove(i, j);
@@ -2070,17 +1969,17 @@ static void composeHelper(QString *str, QChar::UnicodeVersion version, int from)
}
-static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, int from)
+static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, qsizetype from)
{
QString &s = *str;
- const int l = s.length()-1;
+ const qsizetype l = s.size()-1;
char32_t u1, u2;
char16_t c1, c2;
- int pos = from;
+ qsizetype pos = from;
while (pos < l) {
- int p2 = pos+1;
+ qsizetype p2 = pos+1;
u1 = s.at(pos).unicode();
if (QChar::isHighSurrogate(u1)) {
const char16_t low = s.at(p2).unicode();
@@ -2122,7 +2021,7 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in
if (c1 > c2) {
QChar *uc = s.data();
- int p = pos;
+ qsizetype p = pos;
// exchange characters
for (QChar ch : QChar::fromUcs4(u2))
uc[p++] = ch;
@@ -2152,7 +2051,7 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in
// returns true if the text is in a desired Normalization Form already; false otherwise.
// sets lastStable to the position of the last stable code point
-static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationForm mode, int from, int *lastStable)
+static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationForm mode, qsizetype from, qsizetype *lastStable)
{
static_assert(QString::NormalizationForm_D == 0);
static_assert(QString::NormalizationForm_C == 1);
@@ -2161,16 +2060,16 @@ static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationFo
enum { NFQC_YES = 0, NFQC_NO = 1, NFQC_MAYBE = 3 };
- const ushort *string = reinterpret_cast<const ushort *>(str->constData());
- int length = str->length();
+ const auto *string = reinterpret_cast<const char16_t *>(str->constData());
+ qsizetype length = str->size();
// this avoids one out of bounds check in the loop
while (length > from && QChar::isHighSurrogate(string[length - 1]))
--length;
uchar lastCombining = 0;
- for (int i = from; i < length; ++i) {
- int pos = i;
+ for (qsizetype i = from; i < length; ++i) {
+ qsizetype pos = i;
char32_t uc = string[i];
if (uc < 0x80) {
// ASCII characters are stable code points
@@ -2205,10 +2104,57 @@ static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationFo
*lastStable = pos;
}
- if (length != str->length()) // low surrogate parts at the end of text
- *lastStable = str->length() - 1;
+ if (length != str->size()) // low surrogate parts at the end of text
+ *lastStable = str->size() - 1;
return true;
}
+/*!
+ \macro QT_IMPLICIT_QCHAR_CONSTRUCTION
+ \since 6.0
+ \relates QChar
+
+ Defining this macro makes certain QChar constructors implicit
+ rather than explicit. This is done to enforce safe conversions:
+
+ \badcode
+
+ QString str = getString();
+ if (str == 123) {
+ // Oops, meant str == "123". By default does not compile,
+ // *unless* this macro is defined, in which case, it's interpreted
+ // as `if (str == QChar(123))`, that is, `if (str == '{')`.
+ // Likely, not what we meant.
+ }
+
+ \endcode
+
+ This macro is provided to keep existing code working; it is
+ recommended to instead use explicit conversions and/or QLatin1Char.
+ For instance:
+
+ \code
+
+ QChar c1 = 'x'; // OK, unless QT_NO_CAST_FROM_ASCII is defined
+ QChar c2 = u'x'; // always OK, recommended
+ QChar c3 = QLatin1Char('x'); // always OK, recommended
+
+ // from int to 1 UTF-16 code unit: must guarantee that the input is <= 0xFFFF
+ QChar c4 = 120; // compile error, unless QT_IMPLICIT_QCHAR_CONSTRUCTION is defined
+ QChar c5(120); // OK (direct initialization)
+ auto c6 = QChar(120); // ditto
+
+ // from int/char32_t to 1/2 UTF-16 code units:
+ // 𝄞 'MUSICAL SYMBOL G CLEF' (U+1D11E)
+ auto c7 = QChar(0x1D11E); // compiles, but undefined behavior at runtime
+ auto c8 = QChar::fromUcs4(0x1D11E); // always OK
+ auto c9 = QChar::fromUcs4(U'\U0001D11E'); // always OK
+ // => use c8/c9 as QStringView objects
+
+ \endcode
+
+ \sa QLatin1Char, QChar::fromUcs4, QT_NO_CAST_FROM_ASCII
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h
index 056101325e..c0c53664c2 100644
--- a/src/corelib/text/qchar.h
+++ b/src/corelib/text/qchar.h
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCHAR_H
#define QCHAR_H
#include <QtCore/qglobal.h>
+#include <QtCore/qcompare.h>
#include <functional> // for std::hash
@@ -52,29 +17,31 @@ class QString;
struct QLatin1Char
{
public:
- Q_DECL_CONSTEXPR inline explicit QLatin1Char(char c) noexcept : ch(c) {}
- Q_DECL_CONSTEXPR inline char toLatin1() const noexcept { return ch; }
- Q_DECL_CONSTEXPR inline char16_t unicode() const noexcept { return char16_t(uchar(ch)); }
+ constexpr inline explicit QLatin1Char(char c) noexcept : ch(c) {}
+ constexpr inline char toLatin1() const noexcept { return ch; }
+ constexpr inline char16_t unicode() const noexcept { return char16_t(uchar(ch)); }
+
+ friend constexpr bool
+ comparesEqual(const QLatin1Char &lhs, const QLatin1Char &rhs) noexcept
+ { return lhs.ch == rhs.ch; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QLatin1Char &lhs, const QLatin1Char &rhs) noexcept
+ { return Qt::compareThreeWay(uchar(lhs.ch), uchar(rhs.ch)); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QLatin1Char)
+
+ friend constexpr bool comparesEqual(const QLatin1Char &lhs, char rhs) noexcept
+ { return lhs.toLatin1() == rhs; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QLatin1Char &lhs, char rhs) noexcept
+ { return Qt::compareThreeWay(uchar(lhs.toLatin1()), uchar(rhs)); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QLatin1Char, char)
private:
char ch;
};
-Q_DECL_CONSTEXPR inline bool operator==(char lhs, QLatin1Char rhs) noexcept { return lhs == rhs.toLatin1(); }
-Q_DECL_CONSTEXPR inline bool operator!=(char lhs, QLatin1Char rhs) noexcept { return lhs != rhs.toLatin1(); }
-Q_DECL_CONSTEXPR inline bool operator<=(char lhs, QLatin1Char rhs) noexcept { return lhs <= rhs.toLatin1(); }
-Q_DECL_CONSTEXPR inline bool operator>=(char lhs, QLatin1Char rhs) noexcept { return lhs >= rhs.toLatin1(); }
-Q_DECL_CONSTEXPR inline bool operator< (char lhs, QLatin1Char rhs) noexcept { return lhs < rhs.toLatin1(); }
-Q_DECL_CONSTEXPR inline bool operator> (char lhs, QLatin1Char rhs) noexcept { return lhs > rhs.toLatin1(); }
-
-Q_DECL_CONSTEXPR inline bool operator==(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() == rhs; }
-Q_DECL_CONSTEXPR inline bool operator!=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() != rhs; }
-Q_DECL_CONSTEXPR inline bool operator<=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() <= rhs; }
-Q_DECL_CONSTEXPR inline bool operator>=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() >= rhs; }
-Q_DECL_CONSTEXPR inline bool operator< (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() < rhs; }
-Q_DECL_CONSTEXPR inline bool operator> (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() > rhs; }
-
-class Q_CORE_EXPORT QChar {
+#define QT_CHAR_FASTCALL QT7_ONLY(Q_CORE_EXPORT) QT_FASTCALL
+class QT6_ONLY(Q_CORE_EXPORT) QChar {
public:
enum SpecialCharacter {
Null = 0x0000,
@@ -91,36 +58,39 @@ public:
ByteOrderSwapped = 0xfffe,
ParagraphSeparator = 0x2029,
LineSeparator = 0x2028,
+ VisualTabCharacter = 0x2192,
LastValidCodePoint = 0x10ffff
};
- Q_DECL_CONSTEXPR QChar() noexcept : ucs(0) {}
- Q_DECL_CONSTEXPR QChar(ushort rc) noexcept : ucs(rc) {}
- Q_DECL_CONSTEXPR QChar(uchar c, uchar r) noexcept : ucs(char16_t((r << 8) | c)) {}
- Q_DECL_CONSTEXPR QChar(short rc) noexcept : ucs(char16_t(rc)) {}
- Q_DECL_CONSTEXPR QChar(uint rc) noexcept : ucs(char16_t(rc & 0xffff)) {}
- Q_DECL_CONSTEXPR QChar(int rc) noexcept : ucs(char16_t(rc & 0xffff)) {}
- Q_DECL_CONSTEXPR QChar(SpecialCharacter s) noexcept : ucs(char16_t(s)) {} // implicit
- Q_DECL_CONSTEXPR QChar(QLatin1Char ch) noexcept : ucs(ch.unicode()) {} // implicit
-#if defined(Q_COMPILER_UNICODE_STRINGS)
- Q_DECL_CONSTEXPR QChar(char16_t ch) noexcept : ucs(ch) {} // implicit
+#ifdef QT_IMPLICIT_QCHAR_CONSTRUCTION
+#define QCHAR_MAYBE_IMPLICIT Q_IMPLICIT
+#else
+#define QCHAR_MAYBE_IMPLICIT explicit
#endif
-#if defined(Q_OS_WIN)
- static_assert(sizeof(wchar_t) == sizeof(char16_t));
-#endif
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
-# if !defined(_WCHAR_T_DEFINED) || defined(_NATIVE_WCHAR_T_DEFINED)
- Q_DECL_CONSTEXPR QChar(wchar_t ch) noexcept : ucs(char16_t(ch)) {} // implicit
-# endif
+
+ constexpr Q_IMPLICIT QChar() noexcept : ucs(0) {}
+ constexpr Q_IMPLICIT QChar(ushort rc) noexcept : ucs(rc) {}
+ constexpr QCHAR_MAYBE_IMPLICIT QChar(uchar c, uchar r) noexcept : ucs(char16_t((r << 8) | c)) {}
+ constexpr Q_IMPLICIT QChar(short rc) noexcept : ucs(char16_t(rc)) {}
+ constexpr QCHAR_MAYBE_IMPLICIT QChar(uint rc) noexcept : ucs((Q_ASSERT(rc <= 0xffff), char16_t(rc))) {}
+ constexpr QCHAR_MAYBE_IMPLICIT QChar(int rc) noexcept : QChar(uint(rc)) {}
+ constexpr Q_IMPLICIT QChar(SpecialCharacter s) noexcept : ucs(char16_t(s)) {}
+ constexpr Q_IMPLICIT QChar(QLatin1Char ch) noexcept : ucs(ch.unicode()) {}
+ constexpr Q_IMPLICIT QChar(char16_t ch) noexcept : ucs(ch) {}
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+ constexpr Q_IMPLICIT QChar(wchar_t ch) noexcept : ucs(char16_t(ch)) {}
#endif
#ifndef QT_NO_CAST_FROM_ASCII
- QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR QChar(char c) noexcept : ucs(uchar(c)) { }
+ // Always implicit -- allow for 'x' => QChar conversions
+ QT_ASCII_CAST_WARN constexpr Q_IMPLICIT QChar(char c) noexcept : ucs(uchar(c)) { }
#ifndef QT_RESTRICTED_CAST_FROM_ASCII
- QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR QChar(uchar c) noexcept : ucs(c) { }
+ QT_ASCII_CAST_WARN constexpr QCHAR_MAYBE_IMPLICIT QChar(uchar c) noexcept : ucs(c) { }
#endif
#endif
+#undef QCHAR_MAYBE_IMPLICIT
+
static constexpr QChar fromUcs2(char16_t c) noexcept { return QChar{c}; }
static constexpr inline auto fromUcs4(char32_t c) noexcept;
@@ -353,6 +323,17 @@ public:
Script_KhitanSmallScript,
Script_Yezidi,
+ // Unicode 14.0 additions
+ Script_CyproMinoan,
+ Script_OldUyghur,
+ Script_Tangsa,
+ Script_Toto,
+ Script_Vithkuqi,
+
+ // Unicode 15.0 additions
+ Script_Kawi,
+ Script_NagMundari,
+
ScriptCount
};
@@ -394,13 +375,6 @@ public:
Joining_Transparent
};
-#if QT_DEPRECATED_SINCE(5, 3)
- enum Joining
- {
- OtherJoining, Dual, Right, Center
- };
-#endif
-
enum CombiningClass
{
Combining_BelowLeftAttached = 200,
@@ -450,26 +424,15 @@ public:
Unicode_11_0,
Unicode_12_0,
Unicode_12_1,
- Unicode_13_0
+ Unicode_13_0,
+ Unicode_14_0,
+ Unicode_15_0,
+ Unicode_15_1,
};
inline Category category() const noexcept { return QChar::category(ucs); }
inline Direction direction() const noexcept { return QChar::direction(ucs); }
inline JoiningType joiningType() const noexcept { return QChar::joiningType(ucs); }
-#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED inline Joining joining() const noexcept
- {
- switch (QChar::joiningType(ucs)) {
- case QChar::Joining_Causing: return QChar::Center;
- case QChar::Joining_Dual: return QChar::Dual;
- case QChar::Joining_Right: return QChar::Right;
- case QChar::Joining_None:
- case QChar::Joining_Left:
- case QChar::Joining_Transparent:
- default: return QChar::OtherJoining;
- }
- }
-#endif
inline unsigned char combiningClass() const noexcept { return QChar::combiningClass(ucs); }
inline QChar mirroredChar() const noexcept { return QChar(QChar::mirroredChar(ucs)); }
@@ -488,186 +451,199 @@ public:
inline UnicodeVersion unicodeVersion() const noexcept { return QChar::unicodeVersion(ucs); }
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED Q_DECL_CONSTEXPR inline char toAscii() const noexcept { return toLatin1(); }
-#endif
- Q_DECL_CONSTEXPR inline char toLatin1() const noexcept { return ucs > 0xff ? '\0' : char(ucs); }
- Q_DECL_CONSTEXPR inline char16_t unicode() const noexcept { return ucs; }
- Q_DECL_RELAXED_CONSTEXPR inline char16_t &unicode() noexcept { return ucs; }
+ constexpr inline char toLatin1() const noexcept { return ucs > 0xff ? '\0' : char(ucs); }
+ constexpr inline char16_t unicode() const noexcept { return ucs; }
+ constexpr inline char16_t &unicode() noexcept { return ucs; }
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED static Q_DECL_CONSTEXPR inline QChar fromAscii(char c) noexcept
- { return fromLatin1(c); }
-#endif
- static Q_DECL_CONSTEXPR QChar fromLatin1(char c) noexcept { return QLatin1Char(c); }
+ static constexpr QChar fromLatin1(char c) noexcept { return QLatin1Char(c); }
- Q_DECL_CONSTEXPR inline bool isNull() const noexcept { return ucs == 0; }
+ constexpr inline bool isNull() const noexcept { return ucs == 0; }
inline bool isPrint() const noexcept { return QChar::isPrint(ucs); }
- Q_DECL_CONSTEXPR inline bool isSpace() const noexcept { return QChar::isSpace(ucs); }
+ constexpr inline bool isSpace() const noexcept { return QChar::isSpace(ucs); }
inline bool isMark() const noexcept { return QChar::isMark(ucs); }
inline bool isPunct() const noexcept { return QChar::isPunct(ucs); }
inline bool isSymbol() const noexcept { return QChar::isSymbol(ucs); }
- Q_DECL_CONSTEXPR inline bool isLetter() const noexcept { return QChar::isLetter(ucs); }
- Q_DECL_CONSTEXPR inline bool isNumber() const noexcept { return QChar::isNumber(ucs); }
- Q_DECL_CONSTEXPR inline bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(ucs); }
- Q_DECL_CONSTEXPR inline bool isDigit() const noexcept { return QChar::isDigit(ucs); }
- Q_DECL_CONSTEXPR inline bool isLower() const noexcept { return QChar::isLower(ucs); }
- Q_DECL_CONSTEXPR inline bool isUpper() const noexcept { return QChar::isUpper(ucs); }
- Q_DECL_CONSTEXPR inline bool isTitleCase() const noexcept { return QChar::isTitleCase(ucs); }
-
- Q_DECL_CONSTEXPR inline bool isNonCharacter() const noexcept { return QChar::isNonCharacter(ucs); }
- Q_DECL_CONSTEXPR inline bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(ucs); }
- Q_DECL_CONSTEXPR inline bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(ucs); }
- Q_DECL_CONSTEXPR inline bool isSurrogate() const noexcept { return QChar::isSurrogate(ucs); }
-
- Q_DECL_CONSTEXPR inline uchar cell() const noexcept { return uchar(ucs & 0xff); }
- Q_DECL_CONSTEXPR inline uchar row() const noexcept { return uchar((ucs>>8)&0xff); }
- Q_DECL_RELAXED_CONSTEXPR inline void setCell(uchar acell) noexcept { ucs = char16_t((ucs & 0xff00) + acell); }
- Q_DECL_RELAXED_CONSTEXPR inline void setRow(uchar arow) noexcept { ucs = char16_t((char16_t(arow)<<8) + (ucs&0xff)); }
-
- static Q_DECL_CONSTEXPR inline bool isNonCharacter(char32_t ucs4) noexcept
+ constexpr inline bool isLetter() const noexcept { return QChar::isLetter(ucs); }
+ constexpr inline bool isNumber() const noexcept { return QChar::isNumber(ucs); }
+ constexpr inline bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(ucs); }
+ constexpr inline bool isDigit() const noexcept { return QChar::isDigit(ucs); }
+ constexpr inline bool isLower() const noexcept { return QChar::isLower(ucs); }
+ constexpr inline bool isUpper() const noexcept { return QChar::isUpper(ucs); }
+ constexpr inline bool isTitleCase() const noexcept { return QChar::isTitleCase(ucs); }
+
+ constexpr inline bool isNonCharacter() const noexcept { return QChar::isNonCharacter(ucs); }
+ constexpr inline bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(ucs); }
+ constexpr inline bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(ucs); }
+ constexpr inline bool isSurrogate() const noexcept { return QChar::isSurrogate(ucs); }
+
+ constexpr inline uchar cell() const noexcept { return uchar(ucs & 0xff); }
+ constexpr inline uchar row() const noexcept { return uchar((ucs>>8)&0xff); }
+ constexpr inline void setCell(uchar acell) noexcept { ucs = char16_t((ucs & 0xff00) + acell); }
+ constexpr inline void setRow(uchar arow) noexcept { ucs = char16_t((char16_t(arow)<<8) + (ucs&0xff)); }
+
+ static constexpr inline bool isNonCharacter(char32_t ucs4) noexcept
{
return ucs4 >= 0xfdd0 && (ucs4 <= 0xfdef || (ucs4 & 0xfffe) == 0xfffe);
}
- static Q_DECL_CONSTEXPR inline bool isHighSurrogate(char32_t ucs4) noexcept
+ static constexpr inline bool isHighSurrogate(char32_t ucs4) noexcept
{
- return ((ucs4 & 0xfffffc00) == 0xd800);
+ return (ucs4 & 0xfffffc00) == 0xd800; // 0xd800 + up to 1023 (0x3ff)
}
- static Q_DECL_CONSTEXPR inline bool isLowSurrogate(char32_t ucs4) noexcept
+ static constexpr inline bool isLowSurrogate(char32_t ucs4) noexcept
{
- return ((ucs4 & 0xfffffc00) == 0xdc00);
+ return (ucs4 & 0xfffffc00) == 0xdc00; // 0xdc00 + up to 1023 (0x3ff)
}
- static Q_DECL_CONSTEXPR inline bool isSurrogate(char32_t ucs4) noexcept
+ static constexpr inline bool isSurrogate(char32_t ucs4) noexcept
{
return (ucs4 - 0xd800u < 2048u);
}
- static Q_DECL_CONSTEXPR inline bool requiresSurrogates(char32_t ucs4) noexcept
+ static constexpr inline bool requiresSurrogates(char32_t ucs4) noexcept
{
return (ucs4 >= 0x10000);
}
- static Q_DECL_CONSTEXPR inline char32_t surrogateToUcs4(char16_t high, char16_t low) noexcept
+ static constexpr inline char32_t surrogateToUcs4(char16_t high, char16_t low) noexcept
{
+ // 0x010000 through 0x10ffff, provided params are actual high, low surrogates.
+ // 0x010000 + ((high - 0xd800) << 10) + (low - 0xdc00), optimized:
return (char32_t(high)<<10) + low - 0x35fdc00;
}
- static Q_DECL_CONSTEXPR inline char32_t surrogateToUcs4(QChar high, QChar low) noexcept
+ static constexpr inline char32_t surrogateToUcs4(QChar high, QChar low) noexcept
{
return surrogateToUcs4(high.ucs, low.ucs);
}
- static Q_DECL_CONSTEXPR inline char16_t highSurrogate(char32_t ucs4) noexcept
+ static constexpr inline char16_t highSurrogate(char32_t ucs4) noexcept
{
return char16_t((ucs4>>10) + 0xd7c0);
}
- static Q_DECL_CONSTEXPR inline char16_t lowSurrogate(char32_t ucs4) noexcept
+ static constexpr inline char16_t lowSurrogate(char32_t ucs4) noexcept
{
return char16_t(ucs4%0x400 + 0xdc00);
}
- static Category QT_FASTCALL category(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static Direction QT_FASTCALL direction(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static JoiningType QT_FASTCALL joiningType(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
-#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED static Joining QT_FASTCALL joining(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
-#endif
- static unsigned char QT_FASTCALL combiningClass(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static Category QT_CHAR_FASTCALL category(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static Direction QT_CHAR_FASTCALL direction(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static JoiningType QT_CHAR_FASTCALL joiningType(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static unsigned char QT_CHAR_FASTCALL combiningClass(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static char32_t QT_FASTCALL mirroredChar(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL hasMirrored(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static char32_t QT_CHAR_FASTCALL mirroredChar(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL hasMirrored(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static QString QT_FASTCALL decomposition(char32_t ucs4);
- static Decomposition QT_FASTCALL decompositionTag(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static QString QT_CHAR_FASTCALL decomposition(char32_t ucs4);
+ static Decomposition QT_CHAR_FASTCALL decompositionTag(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static int QT_FASTCALL digitValue(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static char32_t QT_FASTCALL toLower(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static char32_t QT_FASTCALL toUpper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static char32_t QT_FASTCALL toTitleCase(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static char32_t QT_FASTCALL toCaseFolded(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static int QT_CHAR_FASTCALL digitValue(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static char32_t QT_CHAR_FASTCALL toLower(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static char32_t QT_CHAR_FASTCALL toUpper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static char32_t QT_CHAR_FASTCALL toTitleCase(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static char32_t QT_CHAR_FASTCALL toCaseFolded(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static Script QT_FASTCALL script(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static Script QT_CHAR_FASTCALL script(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL unicodeVersion(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static UnicodeVersion QT_CHAR_FASTCALL unicodeVersion(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL currentUnicodeVersion() noexcept Q_DECL_CONST_FUNCTION;
+ static UnicodeVersion QT_CHAR_FASTCALL currentUnicodeVersion() noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isPrint(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static Q_DECL_CONSTEXPR inline bool isSpace(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static bool QT_CHAR_FASTCALL isPrint(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static constexpr inline bool isSpace(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{
// note that [0x09..0x0d] + 0x85 are exceptional Cc-s and must be handled explicitly
return ucs4 == 0x20 || (ucs4 <= 0x0d && ucs4 >= 0x09)
|| (ucs4 > 127 && (ucs4 == 0x85 || ucs4 == 0xa0 || QChar::isSpace_helper(ucs4)));
}
- static bool QT_FASTCALL isMark(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isPunct(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isSymbol(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static Q_DECL_CONSTEXPR inline bool isLetter(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static bool QT_CHAR_FASTCALL isMark(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL isPunct(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL isSymbol(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static constexpr inline bool isLetter(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{
return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z'))
|| (ucs4 > 127 && QChar::isLetter_helper(ucs4));
}
- static Q_DECL_CONSTEXPR inline bool isNumber(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static constexpr inline bool isNumber(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::isNumber_helper(ucs4)); }
- static Q_DECL_CONSTEXPR inline bool isLetterOrNumber(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static constexpr inline bool isLetterOrNumber(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{
return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z'))
|| (ucs4 >= '0' && ucs4 <= '9')
|| (ucs4 > 127 && QChar::isLetterOrNumber_helper(ucs4));
}
- static Q_DECL_CONSTEXPR inline bool isDigit(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static constexpr inline bool isDigit(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::category(ucs4) == Number_DecimalDigit); }
- static Q_DECL_CONSTEXPR inline bool isLower(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static constexpr inline bool isLower(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= 'z' && ucs4 >= 'a') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Lowercase); }
- static Q_DECL_CONSTEXPR inline bool isUpper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static constexpr inline bool isUpper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= 'Z' && ucs4 >= 'A') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Uppercase); }
- static Q_DECL_CONSTEXPR inline bool isTitleCase(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
+ static constexpr inline bool isTitleCase(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return ucs4 > 127 && QChar::category(ucs4) == Letter_Titlecase; }
+ friend constexpr bool comparesEqual(const QChar &lhs, const QChar &rhs) noexcept
+ { return lhs.ucs == rhs.ucs; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QChar &lhs, const QChar &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.ucs, rhs.ucs); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QChar)
+
+ friend constexpr bool comparesEqual(const QChar &lhs, std::nullptr_t) noexcept
+ { return lhs.isNull(); }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QChar &lhs, std::nullptr_t) noexcept
+ { return lhs.isNull() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QChar, std::nullptr_t)
+
private:
- static bool QT_FASTCALL isSpace_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isLetter_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isNumber_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isLetterOrNumber_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL isSpace_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL isLetter_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL isNumber_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_CHAR_FASTCALL isLetterOrNumber_helper(char32_t ucs4) noexcept Q_DECL_CONST_FUNCTION;
+
+ // defined in qstring.cpp, because we need to go via QUtf8StringView
+ static bool QT_CHAR_FASTCALL
+ equal_helper(QChar lhs, const char *rhs) noexcept Q_DECL_CONST_FUNCTION;
+ static int QT_CHAR_FASTCALL
+ compare_helper(QChar lhs, const char *rhs) noexcept Q_DECL_CONST_FUNCTION;
+
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ Q_WEAK_OVERLOAD
+ friend bool comparesEqual(const QChar &lhs, const char *rhs) noexcept
+ { return equal_helper(lhs, rhs); }
+ Q_WEAK_OVERLOAD
+ friend Qt::strong_ordering compareThreeWay(const QChar &lhs, const char *rhs) noexcept
+ {
+ const int res = compare_helper(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QChar, const char *, Q_WEAK_OVERLOAD QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
#ifdef QT_NO_CAST_FROM_ASCII
- QChar(char c) noexcept;
- QChar(uchar c) noexcept;
+ QChar(char c) = delete;
+ QChar(uchar c) = delete;
#endif
- friend Q_DECL_CONSTEXPR bool operator==(QChar, QChar) noexcept;
- friend Q_DECL_CONSTEXPR bool operator< (QChar, QChar) noexcept;
char16_t ucs;
};
+#undef QT_CHAR_FASTCALL
-Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE);
-
-Q_DECL_CONSTEXPR inline bool operator==(QChar c1, QChar c2) noexcept { return c1.ucs == c2.ucs; }
-Q_DECL_CONSTEXPR inline bool operator< (QChar c1, QChar c2) noexcept { return c1.ucs < c2.ucs; }
-
-Q_DECL_CONSTEXPR inline bool operator!=(QChar c1, QChar c2) noexcept { return !operator==(c1, c2); }
-Q_DECL_CONSTEXPR inline bool operator>=(QChar c1, QChar c2) noexcept { return !operator< (c1, c2); }
-Q_DECL_CONSTEXPR inline bool operator> (QChar c1, QChar c2) noexcept { return operator< (c2, c1); }
-Q_DECL_CONSTEXPR inline bool operator<=(QChar c1, QChar c2) noexcept { return !operator< (c2, c1); }
-
-
-Q_DECL_CONSTEXPR inline bool operator==(QChar lhs, std::nullptr_t) noexcept { return lhs.isNull(); }
-Q_DECL_CONSTEXPR inline bool operator< (QChar, std::nullptr_t) noexcept { return false; }
-Q_DECL_CONSTEXPR inline bool operator==(std::nullptr_t, QChar rhs) noexcept { return rhs.isNull(); }
-Q_DECL_CONSTEXPR inline bool operator< (std::nullptr_t, QChar rhs) noexcept { return !rhs.isNull(); }
-
-Q_DECL_CONSTEXPR inline bool operator!=(QChar lhs, std::nullptr_t) noexcept { return !operator==(lhs, nullptr); }
-Q_DECL_CONSTEXPR inline bool operator>=(QChar lhs, std::nullptr_t) noexcept { return !operator< (lhs, nullptr); }
-Q_DECL_CONSTEXPR inline bool operator> (QChar lhs, std::nullptr_t) noexcept { return operator< (nullptr, lhs); }
-Q_DECL_CONSTEXPR inline bool operator<=(QChar lhs, std::nullptr_t) noexcept { return !operator< (nullptr, lhs); }
-
-Q_DECL_CONSTEXPR inline bool operator!=(std::nullptr_t, QChar rhs) noexcept { return !operator==(nullptr, rhs); }
-Q_DECL_CONSTEXPR inline bool operator>=(std::nullptr_t, QChar rhs) noexcept { return !operator< (nullptr, rhs); }
-Q_DECL_CONSTEXPR inline bool operator> (std::nullptr_t, QChar rhs) noexcept { return operator< (rhs, nullptr); }
-Q_DECL_CONSTEXPR inline bool operator<=(std::nullptr_t, QChar rhs) noexcept { return !operator< (rhs, nullptr); }
+Q_DECLARE_TYPEINFO(QChar, Q_PRIMITIVE_TYPE);
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QChar);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QChar &);
#endif
+namespace Qt {
+inline namespace Literals {
+inline namespace StringLiterals {
+
+constexpr inline QLatin1Char operator""_L1(char ch) noexcept
+{
+ return QLatin1Char(ch);
+}
+
+} // StringLiterals
+} // Literals
+} // Qt
+
QT_END_NAMESPACE
namespace std {
diff --git a/src/corelib/text/qcollator.cpp b/src/corelib/text/qcollator.cpp
index 4bef356044..1f7e7459e7 100644
--- a/src/corelib/text/qcollator.cpp
+++ b/src/corelib/text/qcollator.cpp
@@ -1,50 +1,39 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcollator_p.h"
#include "qstringlist.h"
#include "qstring.h"
#include "qdebug.h"
+#include "qlocale_p.h"
+#include "qthreadstorage.h"
QT_BEGIN_NAMESPACE
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCollatorSortKeyPrivate)
+
+namespace {
+struct GenerationalCollator
+{
+ QCollator theCollator;
+ int generation = QLocalePrivate::s_generation.loadRelaxed();
+public:
+ GenerationalCollator() = default;
+ GenerationalCollator(const QCollator &copy) : theCollator(copy) {}
+ QCollator &collator()
+ {
+ int currentGeneration = QLocalePrivate::s_generation.loadRelaxed();
+ if (Q_UNLIKELY(generation != currentGeneration)) {
+ // reinitialize the collator
+ generation = currentGeneration;
+ theCollator = QCollator();
+ }
+ return theCollator;
+ }
+};
+}
+Q_GLOBAL_STATIC(QThreadStorage<GenerationalCollator>, defaultCollator)
/*!
\class QCollator
@@ -58,35 +47,60 @@ QT_BEGIN_NAMESPACE
\ingroup string-processing
\ingroup shared
- QCollator is initialized with a QLocale and an optional collation strategy.
- It tries to initialize the collator with the specified values. The collator
- can then be used to compare and sort strings in a locale dependent fashion.
+ QCollator is initialized with a QLocale. It can then be used to compare and
+ sort strings by using the ordering appropriate for that locale.
+
+ A QCollator object can be used together with template-based sorting
+ algorithms, such as std::sort(), to sort a list with QString entries.
+
+ \snippet code/src_corelib_text_qcollator.cpp 0
+
+ In addition to the locale, several optional flags can be set that influence
+ the result of the collation.
+
+ \section1 POSIX fallback implementation
+
+ On Unix systems, Qt is normally compiled to use ICU (except for \macos,
+ where Qt defaults to using an equivalent Apple API). However, if ICU was
+ not available at compile time or explicitly disabled, Qt will use a
+ fallback backend that uses the POSIX API only. This backend has several
+ limitations:
- A QCollator object can be used together with template based sorting
- algorithms such as std::sort to sort a list of QStrings.
+ \list
+ \li Only the QLocale::c() and QLocale::system() locales are supported.
+ Consult the POSIX and C Standard Library manuals for the
+ \c{<locale.h>} header for more information on the system locale.
+ \li caseSensitivity() is not supported: only case-sensitive collation
+ can be performed.
+ \li numericMode() and ignorePunctuation() are not supported.
+ \endlist
- In addition to the locale and collation strategy, several optional flags can
- be set that influence the result of the collation.
+ The use of any of the unsupported options will cause a warning to be
+ printed to the application's output.
*/
/*!
\since 5.13
- Constructs a QCollator using the system's default collation locale.
+ Constructs a QCollator using the default locale's collation locale.
- \sa setLocale(), QLocale::collation()
+ The system locale, when used as default locale, may have a collation locale
+ other than itself (e.g. on Unix, if LC_COLLATE is set differently to LANG in
+ the environment). All other locales are their own collation locales.
+
+ \sa setLocale(), QLocale::collation(), QLocale::setDefault()
*/
QCollator::QCollator()
- : d(new QCollatorPrivate(QLocale::system().collation()))
+ : d(new QCollatorPrivate(QLocale().collation()))
{
d->init();
}
/*!
- Constructs a QCollator from \a locale.
+ Constructs a QCollator using the given \a locale.
\sa setLocale()
- */
+*/
QCollator::QCollator(const QLocale &locale)
: d(new QCollatorPrivate(locale))
{
@@ -94,21 +108,20 @@ QCollator::QCollator(const QLocale &locale)
/*!
Creates a copy of \a other.
- */
+*/
QCollator::QCollator(const QCollator &other)
: d(other.d)
{
if (d) {
// Ensure clean, lest both copies try to init() at the same time:
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
d->ref.ref();
}
}
/*!
- Destroys the collator.
- */
+ Destroys this collator.
+*/
QCollator::~QCollator()
{
if (d && !d->ref.deref())
@@ -117,7 +130,7 @@ QCollator::~QCollator()
/*!
Assigns \a other to this collator.
- */
+*/
QCollator &QCollator::operator=(const QCollator &other)
{
if (this != &other) {
@@ -126,8 +139,7 @@ QCollator &QCollator::operator=(const QCollator &other)
d = other.d;
if (d) {
// Ensure clean, lest both copies try to init() at the same time:
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
d->ref.ref();
}
}
@@ -139,19 +151,19 @@ QCollator &QCollator::operator=(const QCollator &other)
Move constructor. Moves from \a other into this collator.
- Note that a moved-from QCollator can only be destroyed or assigned to.
- The effect of calling other functions than the destructor or one of the
- assignment operators is undefined.
+//! [partially-formed]
+ \note The moved-from object \a other is placed in a partially-formed state,
+ in which the only valid operations are destruction and assignment of a new
+ value.
+//! [partially-formed]
*/
/*!
\fn QCollator & QCollator::operator=(QCollator && other)
- Move-assigns from \a other to this collator.
+ Move-assigns \a other to this QCollator instance.
- Note that a moved-from QCollator can only be destroyed or assigned to.
- The effect of calling other functions than the destructor or one of the
- assignment operators is undefined.
+ \include qcollator.cpp partially-formed
*/
/*!
@@ -163,7 +175,7 @@ QCollator &QCollator::operator=(const QCollator &other)
/*!
\internal
- */
+*/
void QCollator::detach()
{
if (d->ref.loadRelaxed() != 1) {
@@ -178,7 +190,9 @@ void QCollator::detach()
/*!
Sets the locale of the collator to \a locale.
- */
+
+ \sa locale()
+*/
void QCollator::setLocale(const QLocale &locale)
{
if (locale == d->locale)
@@ -190,19 +204,22 @@ void QCollator::setLocale(const QLocale &locale)
/*!
Returns the locale of the collator.
- */
+
+ Unless supplied to the constructor or by calling setLocale(), the system's
+ default collation locale is used.
+
+ \sa setLocale(), QLocale::collation()
+*/
QLocale QCollator::locale() const
{
return d->locale;
}
/*!
- \fn void QCollator::setCaseSensitivity(Qt::CaseSensitivity sensitivity)
-
- Sets the case \a sensitivity of the collator.
+ Sets the case-sensitivity of the collator to \a cs.
\sa caseSensitivity()
- */
+*/
void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
{
if (d->caseSensitivity == cs)
@@ -213,29 +230,27 @@ void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
}
/*!
- \fn Qt::CaseSensitivity QCollator::caseSensitivity() const
-
Returns case sensitivity of the collator.
+ This defaults to case-sensitive until set.
+
+ \note In the C locale, when case-sensitive, all lower-case letters sort
+ after all upper-case letters, where most locales sort each lower-case letter
+ either immediately before or immediately after its upper-case partner. Thus
+ "Zap" sorts before "ape" in the C locale but after in most others.
+
\sa setCaseSensitivity()
- */
+*/
Qt::CaseSensitivity QCollator::caseSensitivity() const
{
return d->caseSensitivity;
}
/*!
- \fn void QCollator::setNumericMode(bool on)
-
- Enables numeric sorting mode when \a on is set to true.
-
- This will enable proper sorting of numeric digits, so that e.g. 100 sorts
- after 99.
-
- By default this mode is off.
+ Enables numeric sorting mode when \a on is \c true.
\sa numericMode()
- */
+*/
void QCollator::setNumericMode(bool on)
{
if (d->numericMode == on)
@@ -246,30 +261,25 @@ void QCollator::setNumericMode(bool on)
}
/*!
- \fn bool QCollator::numericMode() const
+ Returns \c true if numeric sorting is enabled, \c false otherwise.
- Returns \c true if numeric sorting is enabled, false otherwise.
+ When \c true, numerals are recognized as numbers and sorted in arithmetic
+ order; for example, 100 sortes after 99. When \c false, numbers are sorted
+ in lexical order, so that 100 sorts before 99 (because 1 is before 9). By
+ default, this option is disabled.
\sa setNumericMode()
- */
+*/
bool QCollator::numericMode() const
{
return d->numericMode;
}
/*!
- \fn void QCollator::setIgnorePunctuation(bool on)
-
- If \a on is set to true, punctuation characters and symbols are ignored when
- determining sort order.
-
- The default is locale dependent.
-
- \note This method is not currently supported if Qt is configured to not use
- ICU on Linux.
+ Ignores punctuation and symbols if \a on is \c true, attends to them if \c false.
\sa ignorePunctuation()
- */
+*/
void QCollator::setIgnorePunctuation(bool on)
{
if (d->ignorePunctuation == on)
@@ -280,13 +290,13 @@ void QCollator::setIgnorePunctuation(bool on)
}
/*!
- \fn bool QCollator::ignorePunctuation() const
+ Returns whether punctuation and symbols are ignored when collating.
- Returns \c true if punctuation characters and symbols are ignored when
- determining sort order.
+ When \c true, strings are compared as if all punctuation and symbols were
+ removed from each string.
\sa setIgnorePunctuation()
- */
+*/
bool QCollator::ignorePunctuation() const
{
return d->ignorePunctuation;
@@ -295,7 +305,11 @@ bool QCollator::ignorePunctuation() const
/*!
\since 5.13
\fn bool QCollator::operator()(QStringView s1, QStringView s2) const
- \internal
+
+ A QCollator can be used as the comparison function of a sorting algorithm.
+ It returns \c true if \a s1 sorts before \a s2, otherwise \c false.
+
+ \sa compare()
*/
/*!
@@ -304,42 +318,64 @@ bool QCollator::ignorePunctuation() const
Compares \a s1 with \a s2.
- Returns an integer less than, equal to, or greater than zero depending on
- whether \a s1 sorts before, with or after \a s2.
+ Returns a negative integer if \a s1 is less than \a s2, a positive integer
+ if it is greater than \a s2, and zero if they are equal.
*/
-#if QT_STRINGVIEW_LEVEL < 2
+
/*!
\fn bool QCollator::operator()(const QString &s1, const QString &s2) const
- \internal
+ \overload
+ \since 5.2
*/
/*!
+ \fn int QCollator::compare(const QString &s1, const QString &s2) const
\overload
+ \since 5.2
+*/
- Compares \a s1 with \a s2.
+/*!
+ \fn int QCollator::compare(const QChar *s1, qsizetype len1, const QChar *s2, qsizetype len2) const
+ \overload
+ \since 5.2
- Returns an integer less than, equal to, or greater than zero depending on
- whether \a s1 sorts before, with or after \a s2.
+ Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
+ QChar arrays pointed to by \a s1 and \a s2.
+
+ Returns a negative integer if \a s1 is less than \a s2, a positive integer
+ if it is greater than \a s2, and zero if they are equal.
+
+
+ \note In Qt versions prior to 6.4, the length arguments were of type
+ \c{int}, not \c{qsizetype}.
*/
-int QCollator::compare(const QString &s1, const QString &s2) const
+
+/*!
+ \since 6.3
+
+ Compares the strings \a s1 and \a s2, returning their sorting order. This
+ function performs the same operation as compare() on a default-constructed
+ QCollator object.
+
+ \sa compare(), defaultSortKey()
+*/
+int QCollator::defaultCompare(QStringView s1, QStringView s2)
{
- return compare(QStringView(s1), QStringView(s2));
+ return defaultCollator->localData().collator().compare(s1, s2);
}
/*!
- \overload
+ \since 6.3
- Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
- QChar arrays pointed to by \a s1 and \a s2.
+ Returns the sort key for the string \a key. This function performs the same
+ operation as sortKey() on a default-constructed QCollator object.
- Returns an integer less than, equal to, or greater than zero depending on
- whether \a s1 sorts before, with or after \a s2.
+ \sa sortKey(), defaultCompare()
*/
-int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+QCollatorSortKey QCollator::defaultSortKey(QStringView key)
{
- return compare(QStringView(s1, len1), QStringView(s2, len2));
+ return defaultCollator->localData().collator().sortKey(key.toString());
}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\fn QCollatorSortKey QCollator::sortKey(const QString &string) const
@@ -352,7 +388,7 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con
keys for each string and then sort using the keys.
\note Not supported with the C (a.k.a. POSIX) locale on Darwin.
- */
+*/
/*!
\class QCollatorSortKey
@@ -369,12 +405,12 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con
\ingroup string-processing
\ingroup shared
- \sa QCollator, QCollator::sortKey()
+ \sa QCollator, QCollator::sortKey(), compare()
*/
/*!
\internal
- */
+*/
QCollatorSortKey::QCollatorSortKey(QCollatorSortKeyPrivate *d)
: d(d)
{
@@ -389,15 +425,23 @@ QCollatorSortKey::QCollatorSortKey(const QCollatorSortKey &other)
}
/*!
+ \since 6.8
+ \fn QCollatorSortKey::QCollatorSortKey(QCollatorSortKey &&other)
+ Move-constructs a new QCollatorSortKey from \a other.
+
+ \include qcollator.cpp partially-formed
+*/
+
+/*!
Destroys the collator key.
- */
+*/
QCollatorSortKey::~QCollatorSortKey()
{
}
/*!
Assigns \a other to this collator key.
- */
+*/
QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
{
if (this != &other) {
@@ -409,18 +453,20 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
/*!
\fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other)
- Move-assigns \a other to this collator key.
+ Move-assigns \a other to this QCollatorSortKey instance.
+
+ \include qcollator.cpp partially-formed
*/
/*!
- \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
- \relates QCollatorSortKey
+ \fn bool QCollatorSortKey::operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
- According to the QCollator that created the keys, returns \c true if \a lhs
- should be sorted before \a rhs; otherwise returns \c false.
+ Both keys must have been created by the same QCollator's sortKey(). Returns
+ \c true if \a lhs should be sorted before \a rhs, according to the QCollator
+ that created them; otherwise returns \c false.
\sa QCollatorSortKey::compare()
- */
+*/
/*!
\fn void QCollatorSortKey::swap(QCollatorSortKey & other)
@@ -431,13 +477,14 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
/*!
\fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
- Compares this key to \a otherKey.
+ Compares this key to \a otherKey, which must have been created by the same
+ QCollator's sortKey() as this key. The comparison is performed in accordance
+ with that QCollator's sort order.
- Returns a negative value if the key is less than \a otherKey, 0 if the key
- is equal to \a otherKey or a positive value if the key is greater than \a
- otherKey.
+ Returns a negative value if this key sorts before \a otherKey, 0 if the two
+ keys are equal or a positive value if this key sorts after \a otherKey.
\sa operator<()
- */
+*/
QT_END_NAMESPACE
diff --git a/src/corelib/text/qcollator.h b/src/corelib/text/qcollator.h
index de8c8b7e3c..9f61cfc22a 100644
--- a/src/corelib/text/qcollator.h
+++ b/src/corelib/text/qcollator.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLLATOR_H
#define QCOLLATOR_H
@@ -49,20 +13,23 @@ QT_BEGIN_NAMESPACE
class QCollatorPrivate;
class QCollatorSortKeyPrivate;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QCollatorSortKeyPrivate, Q_CORE_EXPORT)
class Q_CORE_EXPORT QCollatorSortKey
{
friend class QCollator;
public:
QCollatorSortKey(const QCollatorSortKey &other);
+ QCollatorSortKey(QCollatorSortKey &&other) noexcept = default;
~QCollatorSortKey();
QCollatorSortKey &operator=(const QCollatorSortKey &other);
- inline QCollatorSortKey &operator=(QCollatorSortKey &&other) noexcept
- { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCollatorSortKey)
void swap(QCollatorSortKey &other) noexcept
{ d.swap(other.d); }
int compare(const QCollatorSortKey &key) const;
+ friend bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
+ { return lhs.compare(rhs) < 0; }
protected:
QCollatorSortKey(QCollatorSortKeyPrivate*);
@@ -73,11 +40,6 @@ private:
QCollatorSortKey();
};
-inline bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
-{
- return lhs.compare(rhs) < 0;
-}
-
class Q_CORE_EXPORT QCollator
{
public:
@@ -88,11 +50,10 @@ public:
QCollator &operator=(const QCollator &);
QCollator(QCollator &&other) noexcept
: d(other.d) { other.d = nullptr; }
- QCollator &operator=(QCollator &&other) noexcept
- { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCollator)
void swap(QCollator &other) noexcept
- { qSwap(d, other.d); }
+ { qt_ptr_swap(d, other.d); }
void setLocale(const QLocale &locale);
QLocale locale() const;
@@ -106,13 +67,17 @@ public:
void setIgnorePunctuation(bool on);
bool ignorePunctuation() const;
-#if QT_STRINGVIEW_LEVEL < 2
- int compare(const QString &s1, const QString &s2) const;
- int compare(const QChar *s1, int len1, const QChar *s2, int len2) const;
+ int compare(const QString &s1, const QString &s2) const
+ { return compare(QStringView(s1), QStringView(s2)); }
+#if QT_CORE_REMOVED_SINCE(6, 4) && QT_POINTER_SIZE != 4
+ int compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+ { return compare(QStringView(s1, len1), QStringView(s2, len2)); }
+#endif
+ int compare(const QChar *s1, qsizetype len1, const QChar *s2, qsizetype len2) const
+ { return compare(QStringView(s1, len1), QStringView(s2, len2)); }
bool operator()(const QString &s1, const QString &s2) const
{ return compare(s1, s2) < 0; }
-#endif
int compare(QStringView s1, QStringView s2) const;
bool operator()(QStringView s1, QStringView s2) const
@@ -120,6 +85,9 @@ public:
QCollatorSortKey sortKey(const QString &string) const;
+ static int defaultCompare(QStringView s1, QStringView s2);
+ static QCollatorSortKey defaultSortKey(QStringView key);
+
private:
QCollatorPrivate *d;
diff --git a/src/corelib/text/qcollator_icu.cpp b/src/corelib/text/qcollator_icu.cpp
index 0dca1ee9c9..84f9c51537 100644
--- a/src/corelib/text/qcollator_icu.cpp
+++ b/src/corelib/text/qcollator_icu.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcollator_p.h"
#include "qlocale_p.h"
@@ -114,29 +78,28 @@ int QCollator::compare(QStringView s1, QStringView s2) const
if (!s2.size())
return +1;
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
if (d->collator) {
+ // truncating sizes (QTBUG-105038)
return ucol_strcoll(d->collator,
reinterpret_cast<const UChar *>(s1.data()), s1.size(),
reinterpret_cast<const UChar *>(s2.data()), s2.size());
}
- return QString::compare_helper(s1.data(), s1.size(),
- s2.data(), s2.size(),
- d->caseSensitivity);
+ return QtPrivate::compareStrings(s1, s2, d->caseSensitivity);
}
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
+
if (d->isC())
return QCollatorSortKey(new QCollatorSortKeyPrivate(string.toUtf8()));
if (d->collator) {
QByteArray result(16 + string.size() + (string.size() >> 2), Qt::Uninitialized);
+ // truncating sizes (QTBUG-105038)
int size = ucol_getSortKey(d->collator, (const UChar *)string.constData(),
string.size(), (uint8_t *)result.data(), result.size());
if (size > result.size()) {
diff --git a/src/corelib/text/qcollator_macx.cpp b/src/corelib/text/qcollator_macx.cpp
index 62b3a904a0..23c23bd53a 100644
--- a/src/corelib/text/qcollator_macx.cpp
+++ b/src/corelib/text/qcollator_macx.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcollator_p.h"
#include "qlocale_p.h"
@@ -99,8 +63,8 @@ int QCollator::compare(QStringView s1, QStringView s2) const
if (!s2.size())
return +1;
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
+
if (!d->collator)
return s1.compare(s2, caseSensitivity());
@@ -118,25 +82,27 @@ int QCollator::compare(QStringView s1, QStringView s2) const
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
+
if (!d->collator) {
// What should (or even *can*) we do here ? (See init()'s comment.)
qWarning("QCollator doesn't support sort keys for the C locale on Darwin");
return QCollatorSortKey(nullptr);
}
- //Documentation recommends having it 5 times as big as the input
+ auto text = reinterpret_cast<const UniChar *>(string.constData());
+ // Documentation recommends having it 5 times as big as the input
QList<UCCollationValue> ret(string.size() * 5);
ItemCount actualSize;
- int status = UCGetCollationKey(d->collator,
- reinterpret_cast<const UniChar *>(string.constData()),
- string.count(), ret.size(), &actualSize, ret.data());
+ int status = UCGetCollationKey(d->collator, text, string.size(),
+ ret.size(), &actualSize, ret.data());
ret.resize(actualSize + 1);
if (status == kUCOutputBufferTooSmall) {
- UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()),
- string.count(), ret.size(), &actualSize, ret.data());
+ status = UCGetCollationKey(d->collator, text, string.size(),
+ ret.size(), &actualSize, ret.data());
+ Q_ASSERT(status != kUCOutputBufferTooSmall);
+ Q_ASSERT(ret.size() == qsizetype(actualSize + 1));
}
ret[actualSize] = 0;
return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(ret)));
@@ -150,7 +116,7 @@ int QCollatorSortKey::compare(const QCollatorSortKey &key) const
SInt32 order;
UCCompareCollationKeys(d->m_key.data(), d->m_key.size(),
key.d->m_key.data(), key.d->m_key.size(),
- 0, &order);
+ nullptr, &order);
return order;
}
diff --git a/src/corelib/text/qcollator_p.h b/src/corelib/text/qcollator_p.h
index b1a483c4e2..b96cdbaa32 100644
--- a/src/corelib/text/qcollator_p.h
+++ b/src/corelib/text/qcollator_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLLATOR_P_H
#define QCOLLATOR_P_H
@@ -92,12 +56,8 @@ public:
QAtomicInt ref = 1;
QLocale locale;
#if defined(Q_OS_WIN) && !QT_CONFIG(icu)
-#ifdef USE_COMPARESTRINGEX
- QString localeName;
-#else
LCID localeID;
#endif
-#endif
Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
bool numericMode = false;
bool ignorePunctuation = false;
@@ -114,6 +74,12 @@ public:
collator = NoCollator;
}
+ void ensureInitialized()
+ {
+ if (dirty)
+ init();
+ }
+
// Implemented by each back-end, in its own way:
void init();
void cleanup();
diff --git a/src/corelib/text/qcollator_posix.cpp b/src/corelib/text/qcollator_posix.cpp
index 92148fa315..5ed80c1b8e 100644
--- a/src/corelib/text/qcollator_posix.cpp
+++ b/src/corelib/text/qcollator_posix.cpp
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcollator_p.h"
#include "qstringlist.h"
#include "qstring.h"
+#include "qvarlengtharray.h"
#include <cstring>
#include <cwchar>
@@ -49,8 +15,10 @@ QT_BEGIN_NAMESPACE
void QCollatorPrivate::init()
{
if (!isC()) {
- if (locale != QLocale())
- qWarning("Only C and default locale supported with the posix collation implementation");
+ if (locale != QLocale::system().collation()) {
+ qWarning("Only the C and system collation locales are supported "
+ "with the POSIX collation implementation");
+ }
if (caseSensitivity != Qt::CaseSensitive)
qWarning("Case insensitive sorting unsupported in the posix collation implementation");
}
@@ -68,7 +36,7 @@ void QCollatorPrivate::cleanup()
static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, QStringView string)
{
ret.resize(string.length());
- int len = string.toWCharArray(ret.data());
+ qsizetype len = string.toWCharArray(ret.data());
ret.resize(len+1);
ret[len] = 0;
}
@@ -82,8 +50,8 @@ int QCollator::compare(QStringView s1, QStringView s2) const
if (d->isC())
return s1.compare(s2, caseSensitivity());
- if (d->dirty)
- d->init();
+
+ d->ensureInitialized();
QVarLengthArray<wchar_t> array1, array2;
stringToWCharArray(array1, s1);
@@ -93,8 +61,7 @@ int QCollator::compare(QStringView s1, QStringView s2) const
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
QVarLengthArray<wchar_t> original;
stringToWCharArray(original, string);
@@ -102,13 +69,19 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const
if (d->isC()) {
std::copy(original.cbegin(), original.cend(), result.begin());
} else {
- size_t size = std::wcsxfrm(result.data(), original.constData(), string.size());
- if (size > uint(result.size())) {
- result.resize(size+1);
- size = std::wcsxfrm(result.data(), original.constData(), string.size());
+ auto availableSizeIncludingNullTerminator = result.size();
+ size_t neededSizeExcludingNullTerminator = std::wcsxfrm(
+ result.data(), original.constData(), availableSizeIncludingNullTerminator);
+ if (neededSizeExcludingNullTerminator > size_t(availableSizeIncludingNullTerminator - 1)) {
+ result.resize(neededSizeExcludingNullTerminator + 1);
+ availableSizeIncludingNullTerminator = result.size();
+ neededSizeExcludingNullTerminator = std::wcsxfrm(result.data(), original.constData(),
+ availableSizeIncludingNullTerminator);
+ Q_ASSERT(neededSizeExcludingNullTerminator
+ == size_t(availableSizeIncludingNullTerminator - 1));
}
- result.resize(size+1);
- result[size] = 0;
+ result.resize(neededSizeExcludingNullTerminator + 1);
+ result[neededSizeExcludingNullTerminator] = 0;
}
return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(result)));
}
diff --git a/src/corelib/text/qcollator_win.cpp b/src/corelib/text/qcollator_win.cpp
index 54f57f1d24..b588f5ff46 100644
--- a/src/corelib/text/qcollator_win.cpp
+++ b/src/corelib/text/qcollator_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcollator_p.h"
#include "qlocale_p.h"
@@ -63,11 +27,7 @@ void QCollatorPrivate::init()
if (isC())
return;
-#ifndef USE_COMPARESTRINGEX
localeID = qt_inIsoNametoLCID(QLocalePrivate::get(locale)->bcp47Name().constData());
-#else
- localeName = locale.bcp47Name();
-#endif
if (caseSensitivity == Qt::CaseInsensitive)
collator |= NORM_IGNORECASE;
@@ -97,8 +57,7 @@ int QCollator::compare(QStringView s1, QStringView s2) const
if (d->isC())
return s1.compare(s2, d->caseSensitivity);
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
//* from Windows documentation *
// Returns one of the following values if successful. To maintain the C
@@ -108,16 +67,9 @@ int QCollator::compare(QStringView s1, QStringView s2) const
// [...] The function returns 0 if it does not succeed.
// https://docs.microsoft.com/en-us/windows/desktop/api/stringapiset/nf-stringapiset-comparestringex#return-value
-#ifndef USE_COMPARESTRINGEX
const int ret = CompareString(d->localeID, d->collator,
reinterpret_cast<const wchar_t *>(s1.data()), s1.size(),
reinterpret_cast<const wchar_t *>(s2.data()), s2.size());
-#else
- const int ret = CompareStringEx(LPCWSTR(d->localeName.utf16()), d->collator,
- reinterpret_cast<LPCWSTR>(s1.data()), s1.size(),
- reinterpret_cast<LPCWSTR>(s2.data()), s2.size(),
- nullptr, nullptr, 0);
-#endif
if (Q_LIKELY(ret))
return ret - 2;
@@ -139,31 +91,20 @@ int QCollator::compare(QStringView s1, QStringView s2) const
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
- if (d->dirty)
- d->init();
+ d->ensureInitialized();
+
if (d->isC())
return QCollatorSortKey(new QCollatorSortKeyPrivate(string));
-#ifndef USE_COMPARESTRINGEX
+ // truncating sizes (QTBUG-105038)
int size = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator,
reinterpret_cast<const wchar_t*>(string.constData()), string.size(),
0, 0);
-#else
- int size = LCMapStringEx(LPCWSTR(d->localeName.utf16()), LCMAP_SORTKEY | d->collator,
- reinterpret_cast<LPCWSTR>(string.constData()), string.size(),
- 0, 0, NULL, NULL, 0);
-#endif
+
QString ret(size, Qt::Uninitialized);
-#ifndef USE_COMPARESTRINGEX
int finalSize = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator,
reinterpret_cast<const wchar_t*>(string.constData()), string.size(),
reinterpret_cast<wchar_t*>(ret.data()), ret.size());
-#else
- int finalSize = LCMapStringEx(LPCWSTR(d->localeName.utf16()), LCMAP_SORTKEY | d->collator,
- reinterpret_cast<LPCWSTR>(string.constData()), string.size(),
- reinterpret_cast<LPWSTR>(ret.data()), ret.size(),
- NULL, NULL, 0);
-#endif
if (finalSize == 0) {
qWarning()
<< "there were problems when generating the ::sortKey by LCMapStringW with error:"
diff --git a/src/corelib/text/qdoublescanprint_p.h b/src/corelib/text/qdoublescanprint_p.h
index 3865c69a99..b098cc4082 100644
--- a/src/corelib/text/qdoublescanprint_p.h
+++ b/src/corelib/text/qdoublescanprint_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDOUBLESCANPRINT_P_H
#define QDOUBLESCANPRINT_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <qglobal.h>
+#include <private/qglobal_p.h>
#if defined(Q_CC_MSVC) && (defined(QT_BOOTSTRAPPED) || defined(QT_NO_DOUBLECONVERSION))
# include <stdio.h>
diff --git a/src/corelib/text/qlatin1stringmatcher.cpp b/src/corelib/text/qlatin1stringmatcher.cpp
new file mode 100644
index 0000000000..9036048fff
--- /dev/null
+++ b/src/corelib/text/qlatin1stringmatcher.cpp
@@ -0,0 +1,233 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qlatin1stringmatcher.h"
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+/*! \class QLatin1StringMatcher
+ \inmodule QtCore
+ \brief Optimized search for substring in Latin-1 text.
+
+ A QLatin1StringMatcher can search for one QLatin1StringView
+ as a substring of another, either ignoring case or taking it into
+ account.
+
+ \since 6.5
+ \ingroup tools
+ \ingroup string-processing
+
+ This class is useful when you have a Latin-1 encoded string that
+ you want to repeatedly search for in some QLatin1StringViews
+ (perhaps in a loop), or when you want to search for all
+ instances of it in a given QLatin1StringView. Using a matcher
+ object and indexIn() is faster than matching a plain
+ QLatin1StringView with QLatin1StringView::indexOf() if repeated
+ matching takes place. This class offers no benefit if you are
+ doing one-off matches. The string to be searched for must not
+ be destroyed or changed before the matcher object is destroyed,
+ as the matcher accesses the string when searching for it.
+
+ Create a QLatin1StringMatcher for the QLatin1StringView
+ you want to search for and the case sensitivity. Then call
+ indexIn() with the QLatin1StringView that you want to search
+ within.
+
+ \sa QLatin1StringView, QStringMatcher, QByteArrayMatcher
+*/
+
+/*!
+ Construct an empty Latin-1 string matcher.
+ This will match at each position in any string.
+ \sa setPattern(), setCaseSensitivity(), indexIn()
+*/
+QLatin1StringMatcher::QLatin1StringMatcher() noexcept
+ : m_pattern(),
+ m_cs(Qt::CaseSensitive),
+ m_caseSensitiveSearcher(m_pattern.data(), m_pattern.data())
+{
+}
+
+/*!
+ Constructs a Latin-1 string matcher that searches for the given \a pattern
+ with given case sensitivity \a cs. The \a pattern argument must
+ not be destroyed before this matcher object. Call indexIn()
+ to find the \a pattern in the given QLatin1StringView.
+*/
+QLatin1StringMatcher::QLatin1StringMatcher(QLatin1StringView pattern,
+ Qt::CaseSensitivity cs) noexcept
+ : m_pattern(pattern), m_cs(cs)
+{
+ setSearcher();
+}
+
+/*!
+ Destroys the Latin-1 string matcher.
+*/
+QLatin1StringMatcher::~QLatin1StringMatcher() noexcept
+{
+ freeSearcher();
+}
+
+/*!
+ \internal
+*/
+void QLatin1StringMatcher::setSearcher() noexcept
+{
+ if (m_cs == Qt::CaseSensitive) {
+ new (&m_caseSensitiveSearcher) CaseSensitiveSearcher(m_pattern.data(), m_pattern.end());
+ } else {
+ QtPrivate::QCaseInsensitiveLatin1Hash foldCase;
+ qsizetype bufferSize = std::min(m_pattern.size(), qsizetype(sizeof m_foldBuffer));
+ for (qsizetype i = 0; i < bufferSize; ++i)
+ m_foldBuffer[i] = static_cast<char>(foldCase(m_pattern[i].toLatin1()));
+
+ new (&m_caseInsensitiveSearcher)
+ CaseInsensitiveSearcher(m_foldBuffer, &m_foldBuffer[bufferSize]);
+ }
+}
+
+/*!
+ \internal
+*/
+void QLatin1StringMatcher::freeSearcher() noexcept
+{
+ if (m_cs == Qt::CaseSensitive)
+ m_caseSensitiveSearcher.~CaseSensitiveSearcher();
+ else
+ m_caseInsensitiveSearcher.~CaseInsensitiveSearcher();
+}
+
+/*!
+ Sets the \a pattern to search for. The string pointed to by the
+ QLatin1StringView must not be destroyed before the matcher is
+ destroyed, unless it is set to point to a different \a pattern
+ with longer lifetime first.
+
+ \sa pattern(), indexIn()
+*/
+void QLatin1StringMatcher::setPattern(QLatin1StringView pattern) noexcept
+{
+ if (m_pattern.latin1() == pattern.latin1() && m_pattern.size() == pattern.size())
+ return; // Same address and size
+
+ freeSearcher();
+ m_pattern = pattern;
+ setSearcher();
+}
+
+/*!
+ Returns the Latin-1 pattern that the matcher searches for.
+
+ \sa setPattern(), indexIn()
+*/
+QLatin1StringView QLatin1StringMatcher::pattern() const noexcept
+{
+ return m_pattern;
+}
+
+/*!
+ Sets the case sensitivity to \a cs.
+
+ \sa caseSensitivity(), indexIn()
+*/
+void QLatin1StringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs) noexcept
+{
+ if (m_cs == cs)
+ return;
+
+ freeSearcher();
+ m_cs = cs;
+ setSearcher();
+}
+
+/*!
+ Returns the case sensitivity the matcher uses.
+
+ \sa setCaseSensitivity(), indexIn()
+*/
+Qt::CaseSensitivity QLatin1StringMatcher::caseSensitivity() const noexcept
+{
+ return m_cs;
+}
+
+/*!
+ Searches for the pattern in the given \a haystack starting from
+ \a from.
+
+ \sa caseSensitivity(), pattern()
+*/
+qsizetype QLatin1StringMatcher::indexIn(QLatin1StringView haystack, qsizetype from) const noexcept
+{
+ return indexIn_helper(haystack, from);
+}
+
+/*!
+ \since 6.8
+ \overload
+
+ Searches for the pattern in the given \a haystack starting from index
+ position \a from.
+
+ \sa caseSensitivity(), pattern()
+*/
+qsizetype QLatin1StringMatcher::indexIn(QStringView haystack, qsizetype from) const noexcept
+{
+ return indexIn_helper(haystack, from);
+}
+
+/*!
+ \internal
+*/
+template <typename String>
+qsizetype QLatin1StringMatcher::indexIn_helper(String haystack, qsizetype from) const noexcept
+{
+ static_assert(QtPrivate::isLatin1OrUtf16View<String>);
+
+ if (m_pattern.isEmpty() && from == haystack.size())
+ return from;
+ if (from < 0) // Historical behavior (see QString::indexOf and co.)
+ from += haystack.size();
+ if (from >= haystack.size())
+ return -1;
+
+ const auto start = [haystack] {
+ if constexpr (std::is_same_v<String, QStringView>)
+ return haystack.utf16();
+ else
+ return haystack.begin();
+ }();
+
+ auto begin = start + from;
+ auto end = start + haystack.size();
+ auto found = begin;
+ if (m_cs == Qt::CaseSensitive) {
+ found = m_caseSensitiveSearcher(begin, end, m_pattern.begin(), m_pattern.end()).begin;
+ if (found == end)
+ return -1;
+ } else {
+ const qsizetype bufferSize = std::min(m_pattern.size(), qsizetype(sizeof m_foldBuffer));
+ const QLatin1StringView restNeedle = m_pattern.sliced(bufferSize);
+ const bool needleLongerThanBuffer = restNeedle.size() > 0;
+ String restHaystack = haystack;
+ do {
+ found = m_caseInsensitiveSearcher(found, end, m_foldBuffer, &m_foldBuffer[bufferSize])
+ .begin;
+ if (found == end) {
+ return -1;
+ } else if (!needleLongerThanBuffer) {
+ break;
+ }
+ restHaystack = haystack.sliced(
+ qMin(haystack.size(),
+ bufferSize + qsizetype(std::distance(start, found))));
+ if (restHaystack.startsWith(restNeedle, Qt::CaseInsensitive))
+ break;
+ ++found;
+ } while (true);
+ }
+ return std::distance(start, found);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/text/qlatin1stringmatcher.h b/src/corelib/text/qlatin1stringmatcher.h
new file mode 100644
index 0000000000..dd3414fc6d
--- /dev/null
+++ b/src/corelib/text/qlatin1stringmatcher.h
@@ -0,0 +1,181 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QLATIN1STRINGMATCHER_H
+#define QLATIN1STRINGMATCHER_H
+
+#include <functional>
+#include <iterator>
+#include <limits>
+
+#include <QtCore/q20algorithm.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+template <typename T>
+constexpr inline bool isLatin1OrUtf16View =
+ std::disjunction_v<std::is_same<T, QLatin1StringView>, std::is_same<T, QStringView>>;
+
+template<class RandomIt1,
+ class Hash = std::hash<typename std::iterator_traits<RandomIt1>::value_type>,
+ class BinaryPredicate = std::equal_to<>>
+class q_boyer_moore_searcher_hashed_needle
+{
+public:
+ constexpr q_boyer_moore_searcher_hashed_needle(RandomIt1 pat_first, RandomIt1 pat_last)
+ : m_skiptable{}
+ {
+ const size_t n = std::distance(pat_first, pat_last);
+ constexpr auto uchar_max = (std::numeric_limits<uchar>::max)();
+ uchar max = n > uchar_max ? uchar_max : uchar(n);
+ q20::fill(std::begin(m_skiptable), std::end(m_skiptable), max);
+
+ RandomIt1 pattern = pat_first;
+ pattern += n - max;
+ while (max--)
+ m_skiptable[uchar(*pattern++)] = max;
+ }
+
+ template<class RandomIt2>
+ constexpr auto operator()(RandomIt2 first, RandomIt2 last, RandomIt1 pat_first,
+ RandomIt1 pat_last) const
+ {
+ struct R
+ {
+ RandomIt2 begin, end;
+ };
+ Hash hf;
+ BinaryPredicate pred;
+ auto pat_length = std::distance(pat_first, pat_last);
+ if (pat_length == 0)
+ return R{ first, first };
+
+ const qsizetype pl_minus_one = qsizetype(pat_length - 1);
+ RandomIt2 current = first + pl_minus_one;
+
+ while (current < last) {
+ qsizetype skip = m_skiptable[hf(*current)];
+ if (!skip) {
+ // possible match
+ while (skip < pat_length) {
+ if (!pred(hf(*(current - skip)), uchar(pat_first[pl_minus_one - skip])))
+ break;
+ skip++;
+ }
+ if (skip > pl_minus_one) { // we have a match
+ auto match = current - skip + 1;
+ return R{ match, match + pat_length };
+ }
+
+ // If we don't have a match we are a bit inefficient as we only skip by one
+ // when we have the non matching char in the string.
+ if (m_skiptable[hf(*(current - skip))] == pat_length)
+ skip = pat_length - skip;
+ else
+ skip = 1;
+ }
+ current += skip;
+ }
+
+ return R{ last, last };
+ }
+
+private:
+ alignas(16) uchar m_skiptable[256];
+};
+
+struct QCaseSensitiveLatin1Hash
+{
+ constexpr QCaseSensitiveLatin1Hash() = default;
+
+ constexpr std::size_t operator()(char c) const noexcept { return std::size_t(uchar(c)); }
+};
+
+struct QCaseInsensitiveLatin1Hash
+{
+ constexpr QCaseInsensitiveLatin1Hash() = default;
+
+ constexpr std::size_t operator()(char c) const noexcept
+ {
+ return std::size_t(latin1Lower[uchar(c)]);
+ }
+
+ static int difference(char lhs, char rhs)
+ {
+ return int(latin1Lower[uchar(lhs)]) - int(latin1Lower[uchar(rhs)]);
+ }
+
+ static auto matcher(char ch)
+ {
+ return [sought = latin1Lower[uchar(ch)]](char other) {
+ return latin1Lower[uchar(other)] == sought;
+ };
+ }
+
+private:
+ static constexpr uchar latin1Lower[256] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+ 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
+ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
+ // 0xd7 (multiplication sign) and 0xdf (sz ligature) complicate life
+ 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
+ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xd7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xdf,
+ 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
+ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+ };
+};
+}
+
+class QLatin1StringMatcher
+{
+public:
+ Q_CORE_EXPORT QLatin1StringMatcher() noexcept;
+ Q_CORE_EXPORT explicit QLatin1StringMatcher(
+ QLatin1StringView pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+ Q_CORE_EXPORT ~QLatin1StringMatcher() noexcept;
+
+ Q_CORE_EXPORT void setPattern(QLatin1StringView pattern) noexcept;
+ Q_CORE_EXPORT QLatin1StringView pattern() const noexcept;
+ Q_CORE_EXPORT void setCaseSensitivity(Qt::CaseSensitivity cs) noexcept;
+ Q_CORE_EXPORT Qt::CaseSensitivity caseSensitivity() const noexcept;
+
+ Q_CORE_EXPORT qsizetype indexIn(QLatin1StringView haystack, qsizetype from = 0) const noexcept;
+ Q_CORE_EXPORT qsizetype indexIn(QStringView haystack, qsizetype from = 0) const noexcept;
+
+private:
+ void setSearcher() noexcept;
+ void freeSearcher() noexcept;
+
+ QLatin1StringView m_pattern;
+ Qt::CaseSensitivity m_cs;
+ typedef QtPrivate::q_boyer_moore_searcher_hashed_needle<const char *,
+ QtPrivate::QCaseSensitiveLatin1Hash>
+ CaseSensitiveSearcher;
+ typedef QtPrivate::q_boyer_moore_searcher_hashed_needle<const char *,
+ QtPrivate::QCaseInsensitiveLatin1Hash>
+ CaseInsensitiveSearcher;
+ union {
+ CaseSensitiveSearcher m_caseSensitiveSearcher;
+ CaseInsensitiveSearcher m_caseInsensitiveSearcher;
+ };
+
+ template <typename String>
+ qsizetype indexIn_helper(String haystack, qsizetype from) const noexcept;
+
+ char m_foldBuffer[256];
+};
+
+QT_END_NAMESPACE
+
+#endif // QLATIN1MATCHER_H
diff --git a/src/corelib/text/qlatin1stringview.h b/src/corelib/text/qlatin1stringview.h
new file mode 100644
index 0000000000..91392d9540
--- /dev/null
+++ b/src/corelib/text/qlatin1stringview.h
@@ -0,0 +1,375 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// Copyright (C) 2019 Mail.ru Group.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QLATIN1STRINGVIEW_H
+#define QLATIN1STRINGVIEW_H
+
+#include <QtCore/qchar.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qtversionchecks.h>
+#include <QtCore/qstringview.h>
+
+#if 0
+// Workaround for generating forward headers
+#pragma qt_class(QLatin1String)
+#pragma qt_class(QLatin1StringView)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || defined(Q_QDOC)
+# define Q_L1S_VIEW_IS_PRIMARY
+class QLatin1StringView
+#else
+class QLatin1String
+#endif
+{
+public:
+#ifdef Q_L1S_VIEW_IS_PRIMARY
+ constexpr QLatin1StringView() noexcept {}
+ constexpr QLatin1StringView(std::nullptr_t) noexcept : QLatin1StringView() {}
+ constexpr explicit QLatin1StringView(const char *s) noexcept
+ : QLatin1StringView(s, s ? qsizetype(QtPrivate::lengthHelperPointer(s)) : 0) {}
+ constexpr QLatin1StringView(const char *f, const char *l)
+ : QLatin1StringView(f, qsizetype(l - f)) {}
+ constexpr QLatin1StringView(const char *s, qsizetype sz) noexcept : m_data(s), m_size(sz) {}
+ explicit QLatin1StringView(const QByteArray &s) noexcept
+ : QLatin1StringView(s.constData(), s.size()) {}
+ constexpr explicit QLatin1StringView(QByteArrayView s) noexcept
+ : QLatin1StringView(s.constData(), s.size()) {}
+#else
+ constexpr QLatin1String() noexcept : m_size(0), m_data(nullptr) {}
+ Q_WEAK_OVERLOAD
+ constexpr QLatin1String(std::nullptr_t) noexcept : QLatin1String() {}
+ constexpr explicit QLatin1String(const char *s) noexcept
+ : m_size(s ? qsizetype(QtPrivate::lengthHelperPointer(s)) : 0), m_data(s) {}
+ constexpr QLatin1String(const char *f, const char *l)
+ : QLatin1String(f, qsizetype(l - f)) {}
+ constexpr QLatin1String(const char *s, qsizetype sz) noexcept : m_size(sz), m_data(s) {}
+ explicit QLatin1String(const QByteArray &s) noexcept : m_size(s.size()), m_data(s.constData()) {}
+ constexpr explicit QLatin1String(QByteArrayView s) noexcept : m_size(s.size()), m_data(s.data()) {}
+#endif // !Q_L1S_VIEW_IS_PRIMARY
+
+ inline QString toString() const;
+
+ constexpr const char *latin1() const noexcept { return m_data; }
+ constexpr qsizetype size() const noexcept { return m_size; }
+ constexpr const char *data() const noexcept { return m_data; }
+ [[nodiscard]] constexpr const char *constData() const noexcept { return data(); }
+ [[nodiscard]] constexpr const char *constBegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr const char *constEnd() const noexcept { return end(); }
+
+ [[nodiscard]] constexpr QLatin1Char first() const { return front(); }
+ [[nodiscard]] constexpr QLatin1Char last() const { return back(); }
+
+ [[nodiscard]] constexpr qsizetype length() const noexcept { return size(); }
+
+ constexpr bool isNull() const noexcept { return !data(); }
+ constexpr bool isEmpty() const noexcept { return !size(); }
+
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+
+ template <typename...Args>
+ [[nodiscard]] inline QString arg(Args &&...args) const;
+
+ [[nodiscard]] constexpr QLatin1Char at(qsizetype i) const
+ {
+ Q_ASSERT(i >= 0);
+ Q_ASSERT(i < size());
+ return QLatin1Char(m_data[i]);
+ }
+ [[nodiscard]] constexpr QLatin1Char operator[](qsizetype i) const { return at(i); }
+
+ [[nodiscard]] constexpr QLatin1Char front() const { return at(0); }
+ [[nodiscard]] constexpr QLatin1Char back() const { return at(size() - 1); }
+
+ [[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::compareStrings(*this, other, cs); }
+ [[nodiscard]] int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::compareStrings(*this, other, cs); }
+ [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] constexpr int compare(QChar c) const noexcept
+ { return isEmpty() ? -1 : front() == c ? int(size() > 1) : uchar(m_data[0]) - c.unicode(); }
+ [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
+ { return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
+
+ [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::startsWith(*this, s, cs); }
+ [[nodiscard]] bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::startsWith(*this, s, cs); }
+ [[nodiscard]] constexpr bool startsWith(QChar c) const noexcept
+ { return !isEmpty() && front() == c; }
+ [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
+ { return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
+
+ [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::endsWith(*this, s, cs); }
+ [[nodiscard]] bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::endsWith(*this, s, cs); }
+ [[nodiscard]] constexpr bool endsWith(QChar c) const noexcept
+ { return !isEmpty() && back() == c; }
+ [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
+ { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
+
+ [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, s, cs); }
+ [[nodiscard]] qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, s, cs); }
+ [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); }
+
+ [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(s, 0, cs) != -1; }
+ [[nodiscard]] bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(s, 0, cs) != -1; }
+ [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(QStringView(&c, 1), 0, cs) != -1; }
+
+ [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(s, size(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, s, cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(s, size(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, s, cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(c, -1, cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); }
+
+ [[nodiscard]] qsizetype count(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return QtPrivate::count(*this, str, cs); }
+ [[nodiscard]] qsizetype count(QLatin1StringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return QtPrivate::count(*this, str, cs); }
+ [[nodiscard]] qsizetype count(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::count(*this, ch, cs); }
+
+ [[nodiscard]] short toShort(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<short>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] ushort toUShort(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<ushort>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] int toInt(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<int>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] uint toUInt(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<uint>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] long toLong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<long>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] ulong toULong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<ulong>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] qlonglong toLongLong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<qlonglong>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] qulonglong toULongLong(bool *ok = nullptr, int base = 10) const
+ { return QtPrivate::toIntegral<qulonglong>(QByteArrayView(*this), ok, base); }
+ [[nodiscard]] float toFloat(bool *ok = nullptr) const
+ {
+ const auto r = QtPrivate::toFloat(*this);
+ if (ok)
+ *ok = bool(r);
+ return r.value_or(0.0f);
+ }
+ [[nodiscard]] double toDouble(bool *ok = nullptr) const
+ {
+ const auto r = QtPrivate::toDouble(*this);
+ if (ok)
+ *ok = bool(r);
+ return r.value_or(0.0);
+ }
+
+ using value_type = const char;
+ using pointer = value_type*;
+ using const_pointer = pointer;
+ using reference = value_type&;
+ using const_reference = reference;
+ using iterator = value_type*;
+ using const_iterator = iterator;
+ using difference_type = qsizetype; // violates Container concept requirements
+ using size_type = qsizetype; // violates Container concept requirements
+
+ constexpr const_iterator begin() const noexcept { return data(); }
+ constexpr const_iterator cbegin() const noexcept { return data(); }
+ constexpr const_iterator end() const noexcept { return data() + size(); }
+ constexpr const_iterator cend() const noexcept { return data() + size(); }
+
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = reverse_iterator;
+
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
+
+ [[nodiscard]] constexpr QLatin1StringView mid(qsizetype pos, qsizetype n = -1) const
+ {
+ using namespace QtPrivate;
+ auto result = QContainerImplHelper::mid(size(), &pos, &n);
+ return result == QContainerImplHelper::Null ? QLatin1StringView()
+ : QLatin1StringView(m_data + pos, n);
+ }
+ [[nodiscard]] constexpr QLatin1StringView left(qsizetype n) const
+ {
+ if (size_t(n) >= size_t(size()))
+ n = size();
+ return {m_data, n};
+ }
+ [[nodiscard]] constexpr QLatin1StringView right(qsizetype n) const
+ {
+ if (size_t(n) >= size_t(size()))
+ n = size();
+ return {m_data + m_size - n, n};
+ }
+
+ [[nodiscard]] constexpr QLatin1StringView sliced(qsizetype pos) const
+ { verify(pos, 0); return {m_data + pos, m_size - pos}; }
+ [[nodiscard]] constexpr QLatin1StringView sliced(qsizetype pos, qsizetype n) const
+ { verify(pos, n); return {m_data + pos, n}; }
+ [[nodiscard]] constexpr QLatin1StringView first(qsizetype n) const
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] constexpr QLatin1StringView last(qsizetype n) const
+ { verify(0, n); return sliced(size() - n, n); }
+ [[nodiscard]] constexpr QLatin1StringView chopped(qsizetype n) const
+ { verify(0, n); return sliced(0, size() - n); }
+
+ constexpr void chop(qsizetype n)
+ { verify(0, n); m_size -= n; }
+ constexpr void truncate(qsizetype n)
+ { verify(0, n); m_size = n; }
+
+ [[nodiscard]] QLatin1StringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
+
+ template <typename Needle, typename...Flags>
+ [[nodiscard]] constexpr auto tokenize(Needle &&needle, Flags...flags) const
+ noexcept(noexcept(qTokenize(std::declval<const QLatin1StringView &>(),
+ std::forward<Needle>(needle), flags...)))
+ -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
+ { return qTokenize(*this, std::forward<Needle>(needle), flags...); }
+
+ friend bool comparesEqual(const QLatin1StringView &s1, const QLatin1StringView &s2) noexcept
+ { return s1.size() == s2.size() && QtPrivate::equalStrings(s1, s2); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QLatin1StringView &s1, const QLatin1StringView &s2) noexcept
+ {
+ const int res = QtPrivate::compareStrings(s1, s2);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView)
+
+ // QChar <> QLatin1StringView
+ friend bool comparesEqual(const QLatin1StringView &lhs, QChar rhs) noexcept
+ { return lhs.size() == 1 && rhs == lhs.front(); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QLatin1StringView &lhs, QChar rhs) noexcept
+ {
+ // negate, as the helper function expects QChar as lhs
+ const int res = -compare_helper(&rhs, 1, lhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QChar)
+
+ // QStringView <> QLatin1StringView
+ friend bool comparesEqual(const QLatin1StringView &lhs, const QStringView &rhs) noexcept
+ { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QLatin1StringView &lhs, const QStringView &rhs) noexcept
+ {
+ const int res = QtPrivate::compareStrings(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QStringView)
+
+ // Reversed helper methods for QStringView <> QLatin1StringView comparison.
+ // If we do not provide them explicitly, QStringView <> QByteArrayView
+ // overloads will be selected, which will provide wrong results, because
+ // they will convert from utf-8
+ friend bool comparesEqual(const QStringView &lhs, const QLatin1StringView &rhs) noexcept
+ { return comparesEqual(rhs, lhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QStringView &lhs, const QLatin1StringView &rhs) noexcept
+ { return QtOrderingPrivate::reversed(compareThreeWay(rhs, lhs)); }
+
+private:
+ friend bool comparesEqual(const QLatin1StringView &lhs, const QByteArrayView &rhs) noexcept
+ { return equal_helper(lhs, rhs.data(), rhs.size()); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QLatin1StringView &lhs, const QByteArrayView &rhs) noexcept
+ {
+ const int res = compare_helper(lhs, rhs.data(), rhs.size());
+ return Qt::compareThreeWay(res, 0);
+ }
+
+ // Reversed helper methods for QByteArrayView <> QLatin1StringView comparison.
+ // If we do not provide them explicitly, QByteArrayView <> QByteArrayView
+ // overloads will be selected, which will provide wrong results
+ friend bool comparesEqual(const QByteArrayView &lhs, const QLatin1StringView &rhs) noexcept
+ { return comparesEqual(rhs, lhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QByteArrayView &lhs, const QLatin1StringView &rhs) noexcept
+ { return QtOrderingPrivate::reversed(compareThreeWay(rhs, lhs)); }
+
+public:
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QByteArrayView, QT_ASCII_CAST_WARN)
+ Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QByteArray, QT_ASCII_CAST_WARN)
+ Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, const char *, QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+
+private:
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+ static int compare_helper(const QLatin1StringView &s1, const char *s2) noexcept
+ { return compare_helper(s1, s2, qstrlen(s2)); }
+ Q_CORE_EXPORT static bool equal_helper(QLatin1StringView s1, const char *s2, qsizetype len) noexcept;
+ Q_CORE_EXPORT static int compare_helper(const QLatin1StringView &s1, const char *s2, qsizetype len) noexcept;
+ Q_CORE_EXPORT static int compare_helper(const QChar *data1, qsizetype length1,
+ QLatin1StringView s2,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+ const char *m_data = nullptr;
+ qsizetype m_size = 0;
+#else
+ qsizetype m_size;
+ const char *m_data;
+#endif
+};
+#ifdef Q_L1S_VIEW_IS_PRIMARY
+Q_DECLARE_TYPEINFO(QLatin1StringView, Q_RELOCATABLE_TYPE);
+#else
+Q_DECLARE_TYPEINFO(QLatin1String, Q_RELOCATABLE_TYPE);
+#endif
+
+constexpr QByteArrayView::QByteArrayView(QLatin1StringView v) noexcept
+ : QByteArrayView(v.data(), v.size())
+{}
+
+namespace Qt {
+inline namespace Literals {
+inline namespace StringLiterals {
+
+constexpr inline QLatin1StringView operator""_L1(const char *str, size_t size) noexcept
+{
+ return {str, qsizetype(size)};
+}
+
+} // StringLiterals
+} // Literals
+} // Qt
+
+QT_END_NAMESPACE
+
+#ifdef Q_L1S_VIEW_IS_PRIMARY
+# undef Q_L1S_VIEW_IS_PRIMARY
+#endif
+
+#endif // QLATIN1STRINGVIEW_H
diff --git a/src/corelib/text/qlatin1stringview.qdoc b/src/corelib/text/qlatin1stringview.qdoc
new file mode 100644
index 0000000000..711057767b
--- /dev/null
+++ b/src/corelib/text/qlatin1stringview.qdoc
@@ -0,0 +1,1295 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// Copyright (C) 2019 Mail.ru Group.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*! \class QLatin1StringView
+ \inmodule QtCore
+ \brief The QLatin1StringView class provides a thin wrapper around
+ a US-ASCII/Latin-1 encoded string literal.
+
+ \ingroup string-processing
+ \reentrant
+
+ \compares strong
+ \compareswith strong char16_t QChar QStringView QUtf8StringView QString \
+ {const char16_t *}
+ \endcompareswith
+ \compareswith strong {const char *} QByteArray QByteArrayView
+ The byte array data is interpreted as utf-8.
+ \endcompareswith
+
+ Many of QString's member functions are overloaded to accept
+ \c{const char *} instead of QString. This includes the copy
+ constructor, the assignment operator, the comparison operators,
+ and various other functions such as \l{QString::insert()}{insert()},
+ \l{QString::append()}{append()}, and \l{QString::prepend()}{prepend()}.
+ Some of these functions are optimized to avoid constructing a
+ QString object for the \c{const char *} data. For example,
+ assuming \c str is a QString,
+
+ \snippet code/src_corelib_text_qstring.cpp 3
+
+ is much faster than
+
+ \snippet code/src_corelib_text_qstring.cpp 4
+
+ because it doesn't construct four temporary QString objects and
+ make a deep copy of the character data.
+
+ However, that is not true for all QString member functions that take
+ \c{const char *} and therefore applications should assume a temporary will
+ be created, such as in
+
+ \snippet code/src_corelib_text_qstring.cpp 4bis
+
+ Applications that define \l QT_NO_CAST_FROM_ASCII (as explained
+ in the QString documentation) don't have access to QString's
+ \c{const char *} API. To provide an efficient way of specifying
+ constant Latin-1 strings, Qt provides the QLatin1StringView, which is
+ just a very thin wrapper around a \c{const char *}. Using
+ QLatin1StringView, the example code above becomes
+
+ \snippet code/src_corelib_text_qstring.cpp 5
+
+ This is a bit longer to type, but it provides exactly the same
+ benefits as the first version of the code, and is faster than
+ converting the Latin-1 strings using QString::fromLatin1().
+
+ Thanks to the QString(QLatin1StringView) constructor,
+ QLatin1StringView can be used everywhere a QString is expected. For
+ example:
+
+ \snippet code/src_corelib_text_qstring.cpp 6
+
+ \note If the function you're calling with a QLatin1StringView
+ argument isn't actually overloaded to take QLatin1StringView, the
+ implicit conversion to QString will trigger a memory allocation,
+ which is usually what you want to avoid by using QLatin1StringView
+ in the first place. In those cases, using QStringLiteral may be
+ the better option.
+
+ \sa QString, QLatin1Char, {QStringLiteral()}{QStringLiteral},
+ QT_NO_CAST_FROM_ASCII
+*/
+
+/*!
+ \class QLatin1String
+ \inmodule QtCore
+ \brief QLatin1String is the same as QLatin1StringView.
+
+ QLatin1String is a view to a Latin-1 string. It's the same as
+ QLatin1StringView and is kept for compatibility reasons. It is
+ recommended to use QLatin1StringView instead.
+
+ Please see the QLatin1StringView documentation for details.
+*/
+
+/*!
+ \typedef QLatin1StringView::value_type
+ \since 5.10
+
+ Alias for \c{const char}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1StringView::difference_type
+ \since 5.10
+
+ Alias for \c{qsizetype}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1StringView::size_type
+ \since 5.10
+
+ Alias for \c{qsizetype}. Provided for compatibility with the STL.
+
+ \note In version prior to Qt 6, this was an alias for \c{int},
+ restricting the amount of data that could be held in a QLatin1StringView
+ on 64-bit architectures.
+*/
+
+/*!
+ \typedef QLatin1StringView::pointer
+ \typedef QLatin1StringView::const_pointer
+ \since 6.7
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1StringView::reference
+ \since 5.10
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1StringView::const_reference
+ \since 5.11
+
+ Alias for \c{reference}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1StringView::iterator
+ \since 5.10
+
+ QLatin1StringView does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QLatin1StringView::const_iterator
+ \since 5.10
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QLatin1StringView::reverse_iterator
+ \since 5.10
+
+ QLatin1StringView does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QLatin1StringView::const_reverse_iterator
+ \since 5.10
+
+ \sa reverse_iterator, const_iterator
+*/
+
+/*! \fn QLatin1StringView::QLatin1StringView()
+ \since 5.6
+
+ Constructs a QLatin1StringView object that stores a \nullptr.
+
+ \sa data(), isEmpty(), isNull(), {Distinction Between Null and Empty Strings}
+*/
+
+/*! \fn QLatin1StringView::QLatin1StringView(std::nullptr_t)
+ \since 6.4
+
+ Constructs a QLatin1StringView object that stores a \nullptr.
+
+ \sa data(), isEmpty(), isNull(), {Distinction Between Null and Empty Strings}
+*/
+
+/*! \fn QLatin1StringView::QLatin1StringView(const char *str)
+
+ Constructs a QLatin1StringView object that stores \a str.
+
+ The string data is \e not copied. The caller must be able to
+ guarantee that \a str will not be deleted or modified as long as
+ the QLatin1StringView object exists.
+
+ \sa latin1()
+*/
+
+/*! \fn QLatin1StringView::QLatin1StringView(const char *str, qsizetype size)
+
+ Constructs a QLatin1StringView object that stores \a str with \a size.
+
+ The string data is \e not copied. The caller must be able to
+ guarantee that \a str will not be deleted or modified as long as
+ the QLatin1StringView object exists.
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, which will be converted to Unicode null characters (U+0000) if this
+ string is used by QString. This behavior is different from Qt 5.x.
+
+ \sa latin1()
+*/
+
+/*!
+ \fn QLatin1StringView::QLatin1StringView(const char *first, const char *last)
+ \since 5.10
+
+ Constructs a QLatin1StringView object that stores \a first with length
+ (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this Latin-1 string object.
+
+ Passing \nullptr as \a first is safe if \a last is \nullptr,
+ too, and results in a null Latin-1 string.
+
+ The behavior is undefined if \a last precedes \a first, \a first
+ is \nullptr and \a last is not, or if \c{last - first >
+ INT_MAX}.
+*/
+
+/*! \fn QLatin1StringView::QLatin1StringView(const QByteArray &str)
+
+ Constructs a QLatin1StringView object as a view on \a str.
+
+ The string data is \e not copied. The caller must be able to
+ guarantee that \a str will not be deleted or modified as long as
+ the QLatin1StringView object exists.
+
+ \sa latin1()
+*/
+
+/*! \fn QLatin1StringView::QLatin1StringView(QByteArrayView str)
+ \since 6.3
+
+ Constructs a QLatin1StringView object as a view on \a str.
+
+ The string data is \e not copied. The caller must be able to
+ guarantee that the data which \a str is pointing to will not
+ be deleted or modified as long as the QLatin1StringView object
+ exists. The size is obtained from \a str as-is, without checking
+ for a null-terminator.
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, which will be converted to Unicode null characters (U+0000) if this
+ string is used by QString.
+
+ \sa latin1()
+*/
+
+/*!
+ \fn QString QLatin1StringView::toString() const
+ \since 6.0
+
+ Converts this Latin-1 string into a QString. Equivalent to
+ \code
+ return QString(*this);
+ \endcode
+*/
+
+/*! \fn const char *QLatin1StringView::latin1() const
+
+ Returns the start of the Latin-1 string referenced by this object.
+*/
+
+/*! \fn const char *QLatin1StringView::data() const
+
+ Returns the start of the Latin-1 string referenced by this object.
+*/
+
+/*! \fn const char *QLatin1StringView::constData() const
+ \since 6.4
+
+ Returns the start of the Latin-1 string referenced by this object.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa data()
+*/
+
+/*! \fn qsizetype QLatin1StringView::size() const
+
+ Returns the size of the Latin-1 string referenced by this object.
+
+ \note In version prior to Qt 6, this function returned \c{int},
+ restricting the amount of data that could be held in a QLatin1StringView
+ on 64-bit architectures.
+*/
+
+/*! \fn qsizetype QLatin1StringView::length() const
+ \since 6.4
+
+ Same as size().
+
+ This function is provided for compatibility with other Qt containers.
+*/
+
+/*! \fn bool QLatin1StringView::isNull() const
+ \since 5.10
+
+ Returns whether the Latin-1 string referenced by this object is null
+ (\c{data() == nullptr}) or not.
+
+ \sa isEmpty(), data()
+*/
+
+/*! \fn bool QLatin1StringView::isEmpty() const
+ \since 5.10
+
+ Returns whether the Latin-1 string referenced by this object is empty
+ (\c{size() == 0}) or not.
+
+ \sa isNull(), size()
+*/
+
+/*! \fn bool QLatin1StringView::empty() const
+ \since 6.4
+
+ Returns whether the Latin-1 string referenced by this object is empty
+ (\c{size() == 0}) or not.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size()
+*/
+
+/*! \fn QLatin1Char QLatin1StringView::at(qsizetype pos) const
+ \since 5.8
+
+ Returns the character at position \a pos in this object.
+
+ \note This function performs no error checking.
+ The behavior is undefined when \a pos < 0 or \a pos >= size().
+
+ \sa operator[]()
+*/
+
+/*! \fn QLatin1Char QLatin1StringView::operator[](qsizetype pos) const
+ \since 5.8
+
+ Returns the character at position \a pos in this object.
+
+ \note This function performs no error checking.
+ The behavior is undefined when \a pos < 0 or \a pos >= size().
+
+ \sa at()
+*/
+
+/*!
+ \fn QLatin1Char QLatin1StringView::front() const
+ \since 5.10
+
+ Returns the first character in the string.
+ Same as \c{at(0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn QLatin1Char QLatin1StringView::first() const
+ \since 6.4
+
+ Returns the first character in the string.
+ Same as \c{at(0)} or front().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa last(), front(), back()
+*/
+
+/*!
+ \fn QLatin1Char QLatin1StringView::back() const
+ \since 5.10
+
+ Returns the last character in the string.
+ Same as \c{at(size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
+/*!
+ \fn QLatin1Char QLatin1StringView::last() const
+ \since 6.4
+
+ Returns the last character in the string.
+ Same as \c{at(size() - 1)} or back().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa first(), back(), front()
+*/
+
+/*!
+ \fn int QLatin1StringView::compare(QStringView str, Qt::CaseSensitivity cs) const
+ \fn int QLatin1StringView::compare(QLatin1StringView l1, Qt::CaseSensitivity cs) const
+ \fn int QLatin1StringView::compare(QChar ch) const
+ \fn int QLatin1StringView::compare(QChar ch, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Compares this string view with UTF-16 string view \a str, Latin-1 string view \a l1,
+ or the character \a ch, respectively. Returns a negative integer if this
+ string is less than \a str, \a l1 or \a ch, returns a positive integer if it
+ is greater than \a str, \a l1 or \a ch, and zero if they are equal.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa operator==(), operator<(), operator>()
+*/
+
+/*!
+ \fn int QLatin1StringView::compare(QUtf8StringView str, Qt::CaseSensitivity cs) const
+ \since 6.5
+
+ Compares this string view with \a str and returns a negative integer if
+ this string view is less than \a str, a positive integer if it is greater than
+ \a str, and zero if they are equal.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
+
+ \sa operator==(), operator<(), operator>()
+*/
+
+
+/*!
+ \fn bool QLatin1StringView::startsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1StringView::startsWith(QLatin1StringView l1, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1StringView::startsWith(QChar ch) const
+ \since 5.10
+ \fn bool QLatin1StringView::startsWith(QChar ch, Qt::CaseSensitivity cs) const
+ \since 5.10
+
+ Returns \c true if this Latin-1 string view starts with the UTF-16
+ string viewed by \a str, the Latin-1 string viewed by \a l1, or the
+ character \a ch, respectively; otherwise returns \c false.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa endsWith()
+*/
+
+/*!
+ \fn bool QLatin1StringView::endsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1StringView::endsWith(QLatin1StringView l1, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1StringView::endsWith(QChar ch) const
+ \since 5.10
+ \fn bool QLatin1StringView::endsWith(QChar ch, Qt::CaseSensitivity cs) const
+ \since 5.10
+
+ Returns \c true if this Latin-1 string view ends with the UTF-16 string
+ viewed \a str, the Latin-1 string viewed by \a l1, or the character \a ch,
+ respectively; otherwise returns \c false.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa startsWith()
+*/
+
+/*!
+ \fn qsizetype QLatin1StringView::indexOf(QStringView str, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QLatin1StringView::indexOf(QLatin1StringView l1, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QLatin1StringView::indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 5.14
+
+ Returns the index position in this Latin-1 string view of the first
+ occurrence of the UTF-16 string viewed by \a str, the Latin-1 string
+ viewed by \a l1, or the character \a ch, respectively, searching forward
+ from index position \a from. Returns -1 if \a str, \a l1 or \a c is not
+ found, respectively.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ \sa QString::indexOf()
+*/
+
+/*!
+ \fn bool QLatin1StringView::contains(QStringView str, Qt::CaseSensitivity cs) const
+ \fn bool QLatin1StringView::contains(QLatin1StringView l1, Qt::CaseSensitivity cs) const
+ \fn bool QLatin1StringView::contains(QChar c, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Returns \c true if this Latin-1 string view contains an occurrence of the
+ UTF-16 string viewed by \a str, the Latin-1 string viewed by \a l1, or the
+ character \a ch, respectively; otherwise returns \c false.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa indexOf(), QStringView::contains(), QStringView::indexOf(),
+ QString::indexOf()
+*/
+
+/*!
+ \fn qsizetype QLatin1StringView::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QLatin1StringView::lastIndexOf(QLatin1StringView l1, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QLatin1StringView::lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Returns the index position in this Latin-1 string view of the last
+ occurrence of the UTF-16 string viewed by \a str, the Latin-1 string
+ viewed by \a l1, or the character \a ch, respectively, searching backward
+ from index position \a from; returns -1 if \a str, \a l1 or \a ch is not
+ found, respectively.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \note When searching for a 0-length \a str or \a l1, the match at
+ the end of the data is excluded from the search by a negative \a
+ from, even though \c{-1} is normally thought of as searching from
+ the end of the string: the match at the end is \e after the last
+ character, so it is excluded. To include such a final empty match,
+ either give a positive value for \a from or omit the \a from
+ parameter entirely.
+
+ \sa indexOf(), QStringView::lastIndexOf(), QStringView::indexOf(),
+ QString::indexOf()
+*/
+
+/*!
+ \fn qsizetype QLatin1StringView::lastIndexOf(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QLatin1StringView::lastIndexOf(QLatin1StringView l1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.2
+ \overload lastIndexOf()
+
+ Returns the index position in this Latin-1 string view of the last
+ occurrence of the UTF-16 string viewed by \a str or the Latin-1 string
+ viewed by \a l1, respectively. Returns -1 if \a str or \a l1 is not found,
+ respectively.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+*/
+
+/*!
+ \fn qsizetype QLatin1StringView::lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const
+ \since 6.3
+ \overload
+*/
+
+/*!
+ \fn qsizetype QLatin1StringView::count(QStringView str, Qt::CaseSensitivity cs) const
+ \fn qsizetype QLatin1StringView::count(QLatin1StringView l1, Qt::CaseSensitivity cs) const
+ \fn qsizetype QLatin1StringView::count(QChar ch, Qt::CaseSensitivity cs) const
+ \since 6.4
+
+ Returns the number of (potentially overlapping) occurrences of the
+ UTF-16 string viewed by \a str, the Latin-1 string viewed by \a l1,
+ or the character \a ch, respectively, in this string view.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa contains(), indexOf()
+*/
+
+/*!
+ \fn QLatin1StringView::const_iterator QLatin1StringView::begin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first character in the string.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QLatin1StringView::const_iterator QLatin1StringView::cbegin() const
+ \since 5.10
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QLatin1StringView::const_iterator QLatin1StringView::constBegin() const
+ \since 6.4
+
+ Same as begin().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa constEnd(), begin(), cbegin(), data()
+*/
+
+/*!
+ \fn QLatin1StringView::const_iterator QLatin1StringView::end() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
+ after the last character in the string.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QLatin1StringView::const_iterator QLatin1StringView::cend() const
+ \since 5.10
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*! \fn QLatin1StringView::const_iterator QLatin1StringView::constEnd() const
+ \since 6.4
+
+ Same as end().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa constBegin(), end(), cend(), crend()
+*/
+
+/*!
+ \fn QLatin1StringView::const_reverse_iterator QLatin1StringView::rbegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to the first character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QLatin1StringView::const_reverse_iterator QLatin1StringView::crbegin() const
+ \since 5.10
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QLatin1StringView::const_reverse_iterator QLatin1StringView::rend() const
+ \since 5.10
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing just
+ after the last character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QLatin1StringView::const_reverse_iterator QLatin1StringView::crend() const
+ \since 5.10
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::mid(qsizetype start, qsizetype length) const
+ \since 5.8
+
+ Returns the substring of length \a length starting at position
+ \a start in this Latin-1 string view.
+
+ If you know that \a start and \a length cannot be out of bounds, use
+ sliced() instead in new code, because it is faster.
+
+ Returns an empty Latin-1 string view if \a start exceeds the length
+ of this string view. If there are less than \a length characters available
+ in this string view starting at \a start, or if \a length is negative
+ (default), the function returns all characters that are available from
+ \a start.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::left(qsizetype length) const
+ \since 5.8
+
+ If you know that \a length cannot be out of bounds, use first() instead in
+ new code, because it is faster.
+
+ Returns the substring of length \a length starting at position
+ 0 in this Latin-1 string view.
+
+ The entire Latin-1 string view is returned if \a length is greater
+ than or equal to size(), or less than zero.
+
+ \sa first(), last(), sliced(), startsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::right(qsizetype length) const
+ \since 5.8
+
+ If you know that \a length cannot be out of bounds, use last() instead in
+ new code, because it is faster.
+
+ Returns the substring of length \a length starting at position
+ size() - \a length in this Latin-1 string view.
+
+ The entire Latin-1 string view is returned if \a length is greater
+ than or equal to size(), or less than zero.
+
+ \sa first(), last(), sliced(), endsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::first(qsizetype n) const
+ \since 6.0
+
+ Returns a Latin-1 string view that contains the first \a n characters
+ of this string view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa last(), startsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::last(qsizetype n) const
+ \since 6.0
+
+ Returns a Latin-1 string view that contains the last \a n characters
+ of this string view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa first(), endsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::sliced(qsizetype pos, qsizetype n) const
+ \since 6.0
+
+ Returns a Latin-1 string view that points to \a n characters of this
+ string view, starting at position \a pos.
+
+//! [UB-sliced-index-length]
+ \note The behavior is undefined when \a pos < 0, \a n < 0,
+ or \c{pos + n > size()}.
+//! [UB-sliced-index-length]
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::sliced(qsizetype pos) const
+ \since 6.0
+
+ Returns a Latin-1 string view starting at position \a pos in this
+ string view, and extending to its end.
+
+//! [UB-sliced-index-only]
+ \note The behavior is undefined when \a pos < 0 or \a pos > size().
+//! [UB-sliced-index-only]
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::chopped(qsizetype length) const
+ \since 5.10
+
+ Returns the substring of length size() - \a length starting at the
+ beginning of this object.
+
+ Same as \c{left(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa sliced(), first(), last(), chop(), truncate()
+*/
+
+/*!
+ \fn void QLatin1StringView::truncate(qsizetype length)
+ \since 5.10
+
+ Truncates this string to length \a length.
+
+ Same as \c{*this = left(length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa sliced(), first(), last(), chopped(), chop()
+*/
+
+/*!
+ \fn void QLatin1StringView::chop(qsizetype length)
+ \since 5.10
+
+ Truncates this string by \a length characters.
+
+ Same as \c{*this = left(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa sliced(), first(), last(), chopped(), truncate()
+*/
+
+/*!
+ \fn QLatin1StringView QLatin1StringView::trimmed() const
+ \since 5.10
+
+ Strips leading and trailing whitespace and returns the result.
+
+ Whitespace means any character for which QChar::isSpace() returns
+ \c true. This includes the ASCII characters '\\t', '\\n', '\\v',
+ '\\f', '\\r', and ' '.
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator==(const QLatin1StringView &lhs, const char * const &rhs)
+ \since 4.3
+
+ Returns \c true if the string \a lhs is equal to const char pointer \a rhs;
+ otherwise returns \c false.
+
+ The \a rhs const char pointer is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+
+ \sa {Comparing Strings}
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator==(const QLatin1StringView &lhs, const QByteArray &rhs)
+ \since 5.0
+ \overload
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator!=(const QLatin1StringView &lhs, const char * const &rhs)
+ \since 4.3
+
+ Returns \c true if the string \a lhs is not equal to const char pointer \a rhs;
+ otherwise returns \c false.
+
+ The \a rhs const char pointer is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+
+ \sa {Comparing Strings}
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator!=(const QLatin1StringView &lhs, const QByteArray &rhs)
+ \since 5.0
+ \overload operator!=()
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator>(const QLatin1StringView &lhs, const char * const &rhs)
+ \since 4.3
+
+ Returns \c true if the string \a lhs is lexically greater than const char pointer
+ \a rhs; otherwise returns \c false.
+
+ The \a rhs const char pointer is converted to a QUtf8StringView.
+
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
+ when you compile your applications. This can be useful if you want
+ to ensure that all user-visible strings go through QObject::tr(),
+ for example.
+
+ \sa {Comparing Strings}
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator>(const QLatin1StringView &lhs, const QByteArray &rhs)
+ \since 5.0
+ \overload
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
+ when you compile your applications. This can be useful if you want
+ to ensure that all user-visible strings go through QObject::tr(),
+ for example.
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator<(const QLatin1StringView &lhs, const char * const &rhs)
+ \since 4.3
+
+ Returns \c true if the string \a lhs is lexically less than const char pointer
+ \a rhs; otherwise returns \c false.
+
+ The \a rhs const char pointer is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+
+ \sa {Comparing Strings}
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator<(const QLatin1StringView &lhs, const QByteArray &rhs)
+ \since 5.0
+ \overload
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator>=(const QLatin1StringView &lhs, const char * const &rhs)
+ \since 4.3
+
+ Returns \c true if the string \a lhs is lexically greater than or equal to
+ const char pointer \a rhs; otherwise returns \c false.
+
+ The \a rhs const char pointer is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+
+ \sa {Comparing Strings}
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator>=(const QLatin1StringView &lhs, const QByteArray &rhs)
+ \since 5.0
+ \overload
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator<=(const QLatin1StringView &lhs, const char * const &rhs)
+ \since 4.3
+
+ Returns \c true if the string \a lhs is lexically less than or equal to
+ const char pointer \a rhs; otherwise returns \c false.
+
+ The \a rhs const char pointer is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+
+ \sa {Comparing Strings}
+*/
+
+/*!
+ \fn bool QLatin1StringView::operator<=(const QLatin1StringView &lhs, const QByteArray &rhs)
+ \since 5.0
+ \overload
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
+/*! \fn bool QLatin1StringView::operator==(const QLatin1StringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string \a lhs is lexically equal to string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator!=(const QLatin1StringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string \a lhs is lexically not equal to string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<(const QLatin1StringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string \a lhs is lexically less than string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<=(const QLatin1StringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string \a lhs is lexically less than or equal to
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>(const QLatin1StringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string \a lhs is lexically greater than string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>=(const QLatin1StringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string \a lhs is lexically greater than or equal
+ to string \a rhs; otherwise returns \c false.
+*/
+
+/*! \fn bool QLatin1StringView::operator==(const QChar &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if char \a lhs is lexically equal to string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<(const QChar &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if char \a lhs is lexically less than string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>(const QChar &lhs, const QLatin1StringView &rhs)
+ Returns \c true if char \a lhs is lexically greater than string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator!=(const QChar &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if char \a lhs is lexically not equal to string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<=(const QChar &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if char \a lhs is lexically less than or equal to
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>=(const QChar &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if char \a lhs is lexically greater than or equal to
+ string \a rhs; otherwise returns \c false.
+*/
+
+/*! \fn bool QLatin1StringView::operator==(const QLatin1StringView &lhs, const QChar &rhs)
+
+ Returns \c true if string \a lhs is lexically equal to char \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<(const QLatin1StringView &lhs, const QChar &rhs)
+
+ Returns \c true if string \a lhs is lexically less than char \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>(const QLatin1StringView &lhs, const QChar &rhs)
+
+ Returns \c true if string \a lhs is lexically greater than char \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator!=(const QLatin1StringView &lhs, const QChar &rhs)
+
+ Returns \c true if string \a lhs is lexically not equal to char \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<=(const QLatin1StringView &lhs, const QChar &rhs)
+
+ Returns \c true if string \a lhs is lexically less than or equal to
+ char \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>=(const QLatin1StringView &lhs, const QChar &rhs)
+
+ Returns \c true if string \a lhs is lexically greater than or equal to
+ char \a rhs; otherwise returns \c false.
+*/
+
+/*! \fn bool QLatin1StringView::operator==(const QStringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string view \a lhs is lexically equal to string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<(const QStringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string view \a lhs is lexically less than string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>(const QStringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string view \a lhs is lexically greater than string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator!=(const QStringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string view \a lhs is lexically not equal to string \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<=(const QStringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string view \a lhs is lexically less than or equal to
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>=(const QStringView &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if string view \a lhs is lexically greater than or equal to
+ string \a rhs; otherwise returns \c false.
+*/
+
+/*! \fn bool QLatin1StringView::operator==(const QLatin1StringView &lhs, const QStringView &rhs)
+
+ Returns \c true if string \a lhs is lexically equal to string view \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<(const QLatin1StringView &lhs, const QStringView &rhs)
+
+ Returns \c true if string \a lhs is lexically less than string view \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>(const QLatin1StringView &lhs, const QStringView &rhs)
+
+ Returns \c true if string \a lhs is lexically greater than string view \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator!=(const QLatin1StringView &lhs, const QStringView &rhs)
+
+ Returns \c true if string \a lhs is lexically not equal to string view \a rhs;
+ otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<=(const QLatin1StringView &lhs, const QStringView &rhs)
+
+ Returns \c true if string \a lhs is lexically less than or equal to
+ string view \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>=(const QLatin1StringView &lhs, const QStringView &rhs)
+
+ Returns \c true if string \a lhs is lexically greater than or equal to
+ string view \a rhs; otherwise returns \c false.
+*/
+
+/*! \fn bool QLatin1StringView::operator==(const char * const &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if const char pointer \a lhs is lexically equal to
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<(const char * const &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if const char pointer \a lhs is lexically less than
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>(const char * const &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if const char pointer \a lhs is lexically greater than
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator!=(const char * const &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if const char pointer \a lhs is lexically not equal to
+ string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator<=(const char * const &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if const char pointer \a lhs is lexically less than or
+ equal to string \a rhs; otherwise returns \c false.
+*/
+/*! \fn bool QLatin1StringView::operator>=(const char * const &lhs, const QLatin1StringView &rhs)
+
+ Returns \c true if const char pointer \a lhs is lexically greater than or
+ equal to string \a rhs; otherwise returns \c false.
+*/
+
+/*!
+ \fn qlonglong QLatin1StringView::toLongLong(bool *ok, int base) const
+ \fn qulonglong QLatin1StringView::toULongLong(bool *ok, int base) const
+ \fn int QLatin1StringView::toInt(bool *ok, int base) const
+ \fn uint QLatin1StringView::toUInt(bool *ok, int base) const
+ \fn long QLatin1StringView::toLong(bool *ok, int base) const
+ \fn ulong QLatin1StringView::toULong(bool *ok, int base) const
+ \fn short QLatin1StringView::toShort(bool *ok, int base) const
+ \fn ushort QLatin1StringView::toUShort(bool *ok, int base) const
+
+ \since 6.4
+
+ Returns this QLatin1StringView converted to a corresponding numeric value using
+ base \a base, which is ten by default. Bases 0 and 2 through 36 are supported,
+ using letters for digits beyond 9; A is ten, B is eleven and so on.
+
+ If \a base is 0, the base is determined automatically using the following
+ rules (in this order), if the Latin-1 string view begins with:
+
+ \list
+ \li \c "0x", the rest of it is read as hexadecimal (base 16)
+ \li \c "0b", the rest of it is read as binary (base 2)
+ \li \c "0", the rest of it is read as octal (base 8)
+ \li otherwise it is read as decimal
+ \endlist
+
+ Returns 0 if the conversion fails.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+//! [latin1-numeric-conversion-note]
+ \note The conversion of the number is performed in the default C locale,
+ regardless of the user's locale. Use QLocale to perform locale-aware
+ conversions between numbers and strings.
+
+ This function ignores leading and trailing spacing characters.
+//! [latin1-numeric-conversion-note]
+
+ \note Support for the "0b" prefix was added in Qt 6.4.
+*/
+
+/*!
+ \fn double QLatin1StringView::toDouble(bool *ok) const
+ \fn float QLatin1StringView::toFloat(bool *ok) const
+ \since 6.4
+
+ Returns this QLatin1StringView converted to a corresponding floating-point value.
+
+ Returns an infinity if the conversion overflows or 0.0 if the
+ conversion fails for other reasons (e.g. underflow).
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ \warning The QLatin1StringView content may only contain valid numerical
+ characters which includes the plus/minus sign, the character e used in
+ scientific notation, and the decimal point. Including the unit or additional
+ characters leads to a conversion error.
+
+ \include qlatin1stringview.qdoc latin1-numeric-conversion-note
+*/
+
+/*!
+ \fn Qt::Literals::StringLiterals::operator""_L1(const char *str, size_t size)
+
+ \relates QLatin1StringView
+ \since 6.4
+
+ Literal operator that creates a QLatin1StringView out of the first \a size
+ characters in the char string literal \a str.
+
+ The following code creates a QLatin1StringView:
+ \code
+ using namespace Qt::Literals::StringLiterals;
+
+ auto str = "hello"_L1;
+ \endcode
+
+ \sa Qt::Literals::StringLiterals
+*/
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index 40defe386f..ab95b300eb 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -1,46 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
-#if !defined(QWS) && defined(Q_OS_MAC)
+#if (defined(QT_STATIC) || defined(QT_BOOTSTRAPPED)) && defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1000
+QT_WARNING_DISABLE_GCC("-Wfree-nonheap-object") // false positive tracking
+#endif
+
+#if defined(Q_OS_MACOS)
# include "private/qcore_mac_p.h"
# include <CoreFoundation/CoreFoundation.h>
#endif
@@ -54,6 +22,7 @@
#include "qlocale.h"
#include "qlocale_p.h"
#include "qlocale_tools_p.h"
+#include <private/qtools_p.h>
#if QT_CONFIG(datetimeparser)
#include "private/qdatetimeparser_p.h"
#endif
@@ -61,8 +30,13 @@
#include "qdatetime.h"
#include "qstringlist.h"
#include "qvariant.h"
+#include "qvarlengtharray.h"
#include "qstringbuilder.h"
+#if QT_CONFIG(timezone)
+# include "qtimezone.h"
+#endif
#include "private/qnumeric_p.h"
+#include "private/qtools_p.h"
#include <cmath>
#ifndef QT_NO_SYSTEMLOCALE
# include "qmutex.h"
@@ -76,20 +50,40 @@
#include "private/qgregoriancalendar_p.h"
#include "qcalendar.h"
+#include <q20iterator.h>
+
QT_BEGIN_NAMESPACE
+constexpr int QLocale::DefaultTwoDigitBaseYear;
+
+QT_IMPL_METATYPE_EXTERN_TAGGED(QList<Qt::DayOfWeek>, QList_Qt__DayOfWeek)
#ifndef QT_NO_SYSTEMLOCALE
-static QSystemLocale *_systemLocale = nullptr;
-class QSystemLocaleSingleton: public QSystemLocale
-{
-public:
- QSystemLocaleSingleton() : QSystemLocale(true) {}
-};
+QT_IMPL_METATYPE_EXTERN_TAGGED(QSystemLocale::CurrencyToStringArgument,
+ QSystemLocale__CurrencyToStringArgument)
+#endif
+
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
-Q_GLOBAL_STATIC(QSystemLocaleSingleton, QSystemLocale_globalSystemLocale)
-static QLocaleData globalLocaleData;
+#ifndef QT_NO_SYSTEMLOCALE
+Q_CONSTINIT static QSystemLocale *_systemLocale = nullptr;
+Q_CONSTINIT static QLocaleData systemLocaleData = {};
#endif
+static_assert(ascii_isspace(' '));
+static_assert(ascii_isspace('\t'));
+static_assert(ascii_isspace('\n'));
+static_assert(ascii_isspace('\v'));
+static_assert(ascii_isspace('\f'));
+static_assert(ascii_isspace('\r'));
+static_assert(!ascii_isspace('\0'));
+static_assert(!ascii_isspace('\a'));
+static_assert(!ascii_isspace('a'));
+static_assert(!ascii_isspace('\177'));
+static_assert(!ascii_isspace(uchar('\200')));
+static_assert(!ascii_isspace(uchar('\xA0'))); // NBSP (is a space but Latin 1, not ASCII)
+static_assert(!ascii_isspace(uchar('\377')));
+
/******************************************************************************
** Helpers for accessing Qt locale database
*/
@@ -98,39 +92,67 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qlocale_data_p.h"
QT_END_INCLUDE_NAMESPACE
-QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) noexcept
+QLocale::Language QLocalePrivate::codeToLanguage(QStringView code,
+ QLocale::LanguageCodeTypes codeTypes) noexcept
{
const auto len = code.size();
if (len != 2 && len != 3)
- return QLocale::C;
- ushort uc1 = code[0].toLower().unicode();
- ushort uc2 = code[1].toLower().unicode();
- ushort uc3 = len > 2 ? code[2].toLower().unicode() : 0;
+ return QLocale::AnyLanguage;
- const unsigned char *c = language_code_list;
- for (; *c != 0; c += 3) {
- if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
- return QLocale::Language((c - language_code_list)/3);
+ const char16_t uc1 = code[0].toLower().unicode();
+ const char16_t uc2 = code[1].toLower().unicode();
+ const char16_t uc3 = len > 2 ? code[2].toLower().unicode() : 0;
+
+ // All language codes are ASCII.
+ if (uc1 > 0x7F || uc2 > 0x7F || uc3 > 0x7F)
+ return QLocale::AnyLanguage;
+
+ const AlphaCode codeBuf = { char(uc1), char(uc2), char(uc3) };
+
+ auto searchCode = [codeBuf](auto f) {
+ return std::find_if(languageCodeList.begin(), languageCodeList.end(),
+ [=](LanguageCodeEntry i) { return f(i) == codeBuf; });
+ };
+
+ if (codeTypes.testFlag(QLocale::ISO639Part1) && uc3 == 0) {
+ auto i = searchCode([](LanguageCodeEntry i) { return i.part1; });
+ if (i != languageCodeList.end())
+ return QLocale::Language(std::distance(languageCodeList.begin(), i));
}
- if (uc3 == 0) {
- // legacy codes
- if (uc1 == 'n' && uc2 == 'o') { // no -> nb
- static_assert(QLocale::Norwegian == QLocale::NorwegianBokmal);
- return QLocale::Norwegian;
+ if (uc3 != 0) {
+ if (codeTypes.testFlag(QLocale::ISO639Part2B)) {
+ auto i = searchCode([](LanguageCodeEntry i) { return i.part2B; });
+ if (i != languageCodeList.end())
+ return QLocale::Language(std::distance(languageCodeList.begin(), i));
}
- if (uc1 == 't' && uc2 == 'l') { // tl -> fil
- static_assert(QLocale::Tagalog == QLocale::Filipino);
- return QLocale::Tagalog;
- }
- if (uc1 == 's' && uc2 == 'h') { // sh -> sr[_Latn]
- static_assert(QLocale::SerboCroatian == QLocale::Serbian);
- return QLocale::SerboCroatian;
+
+ // Optimization: Part 2T code if present is always the same as Part 3 code.
+ // This is asserted in iso639_3.LanguageCodeData.
+ if (codeTypes.testFlag(QLocale::ISO639Part2T)
+ && !codeTypes.testFlag(QLocale::ISO639Part3)) {
+ auto i = searchCode([](LanguageCodeEntry i) { return i.part2T; });
+ if (i != languageCodeList.end())
+ return QLocale::Language(std::distance(languageCodeList.begin(), i));
}
- if (uc1 == 'm' && uc2 == 'o') { // mo -> ro
- static_assert(QLocale::Moldavian == QLocale::Romanian);
- return QLocale::Moldavian;
+
+ if (codeTypes.testFlag(QLocale::ISO639Part3)) {
+ auto i = searchCode([](LanguageCodeEntry i) { return i.part3; });
+ if (i != languageCodeList.end())
+ return QLocale::Language(std::distance(languageCodeList.begin(), i));
}
+ }
+
+ if (codeTypes.testFlag(QLocale::LegacyLanguageCode) && uc3 == 0) {
+ // legacy codes
+ if (uc1 == 'n' && uc2 == 'o') // no -> nb
+ return QLocale::NorwegianBokmal;
+ if (uc1 == 't' && uc2 == 'l') // tl -> fil
+ return QLocale::Filipino;
+ if (uc1 == 's' && uc2 == 'h') // sh -> sr[_Latn]
+ return QLocale::Serbian;
+ if (uc1 == 'm' && uc2 == 'o') // mo -> ro
+ return QLocale::Romanian;
// Android uses the following deprecated codes
if (uc1 == 'i' && uc2 == 'w') // iw -> he
return QLocale::Hebrew;
@@ -139,7 +161,7 @@ QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) noexcept
if (uc1 == 'j' && uc2 == 'i') // ji -> yi
return QLocale::Yiddish;
}
- return QLocale::C;
+ return QLocale::AnyLanguage;
}
QLocale::Script QLocalePrivate::codeToScript(QStringView code) noexcept
@@ -155,118 +177,203 @@ QLocale::Script QLocalePrivate::codeToScript(QStringView code) noexcept
unsigned char c3 = code[3].toLower().toLatin1();
const unsigned char *c = script_code_list;
- for (int i = 0; i < QLocale::LastScript; ++i, c += 4) {
+ for (qsizetype i = 0; i < QLocale::LastScript; ++i, c += 4) {
if (c0 == c[0] && c1 == c[1] && c2 == c[2] && c3 == c[3])
return QLocale::Script(i);
}
return QLocale::AnyScript;
}
-QLocale::Country QLocalePrivate::codeToCountry(QStringView code) noexcept
+QLocale::Territory QLocalePrivate::codeToTerritory(QStringView code) noexcept
{
const auto len = code.size();
if (len != 2 && len != 3)
- return QLocale::AnyCountry;
+ return QLocale::AnyTerritory;
- ushort uc1 = code[0].toUpper().unicode();
- ushort uc2 = code[1].toUpper().unicode();
- ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
+ char16_t uc1 = code[0].toUpper().unicode();
+ char16_t uc2 = code[1].toUpper().unicode();
+ char16_t uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
- const unsigned char *c = country_code_list;
+ const unsigned char *c = territory_code_list;
for (; *c != 0; c += 3) {
if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
- return QLocale::Country((c - country_code_list)/3);
+ return QLocale::Territory((c - territory_code_list)/3);
}
- return QLocale::AnyCountry;
+ return QLocale::AnyTerritory;
}
-QLatin1String QLocalePrivate::languageToCode(QLocale::Language language)
+std::array<char, 4> QLocalePrivate::languageToCode(QLocale::Language language,
+ QLocale::LanguageCodeTypes codeTypes)
{
- if (language == QLocale::AnyLanguage)
- return QLatin1String();
+ if (language == QLocale::AnyLanguage || language > QLocale::LastLanguage)
+ return {};
if (language == QLocale::C)
- return QLatin1String("C");
+ return {'C'};
+
+ const LanguageCodeEntry &i = languageCodeList[language];
+
+ if (codeTypes.testFlag(QLocale::ISO639Part1) && i.part1.isValid())
+ return i.part1.decode();
- const unsigned char *c = language_code_list + 3*(uint(language));
+ if (codeTypes.testFlag(QLocale::ISO639Part2B) && i.part2B.isValid())
+ return i.part2B.decode();
- return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
+ if (codeTypes.testFlag(QLocale::ISO639Part2T) && i.part2T.isValid())
+ return i.part2T.decode();
+ if (codeTypes.testFlag(QLocale::ISO639Part3))
+ return i.part3.decode();
+
+ return {};
}
-QLatin1String QLocalePrivate::scriptToCode(QLocale::Script script)
+QLatin1StringView QLocalePrivate::scriptToCode(QLocale::Script script)
{
if (script == QLocale::AnyScript || script > QLocale::LastScript)
- return QLatin1String();
- const unsigned char *c = script_code_list + 4*(uint(script));
- return QLatin1String(reinterpret_cast<const char *>(c), 4);
+ return {};
+ const unsigned char *c = script_code_list + 4 * script;
+ return {reinterpret_cast<const char *>(c), 4};
}
-QLatin1String QLocalePrivate::countryToCode(QLocale::Country country)
+QLatin1StringView QLocalePrivate::territoryToCode(QLocale::Territory territory)
{
- if (country == QLocale::AnyCountry)
- return QLatin1String();
-
- const unsigned char *c = country_code_list + 3*(uint(country));
+ if (territory == QLocale::AnyTerritory || territory > QLocale::LastTerritory)
+ return {};
- return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
+ const unsigned char *c = territory_code_list + 3 * territory;
+ return {reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3};
}
-// http://www.unicode.org/reports/tr35/#Likely_Subtags
-static bool addLikelySubtags(QLocaleId &localeId)
+namespace {
+struct LikelyPair
{
- // ### optimize with bsearch
- const int likely_subtags_count = sizeof(likely_subtags) / sizeof(likely_subtags[0]);
- const QLocaleId *p = likely_subtags;
- const QLocaleId *const e = p + likely_subtags_count;
- for ( ; p < e; p += 2) {
- if (localeId == p[0]) {
- localeId = p[1];
- return true;
- }
- }
- return false;
-}
+ QLocaleId key; // Search key.
+ QLocaleId value = QLocaleId { 0, 0, 0 };
+};
+
+bool operator<(LikelyPair lhs, LikelyPair rhs)
+{
+ // Must match the comparison LocaleDataWriter.likelySubtags() uses when
+ // sorting, see qtbase/util/locale_database.qlocalexml2cpp.py
+ const auto compare = [](int lhs, int rhs) {
+ // 0 sorts after all other values; lhs and rhs are passed ushort values.
+ const int huge = 0x10000;
+ return (lhs ? lhs : huge) - (rhs ? rhs : huge);
+ };
+ const auto &left = lhs.key;
+ const auto &right = rhs.key;
+ // Comparison order: language, region, script:
+ if (int cmp = compare(left.language_id, right.language_id))
+ return cmp < 0;
+ if (int cmp = compare(left.territory_id, right.territory_id))
+ return cmp < 0;
+ return compare(left.script_id, right.script_id) < 0;
+}
+} // anonymous namespace
+/*!
+ Fill in blank fields of a locale ID.
+
+ An ID in which some fields are zero stands for any locale that agrees with
+ it in its non-zero fields. CLDR's likely-subtag data is meant to help us
+ chose which candidate to prefer. (Note, however, that CLDR does have some
+ cases where it maps an ID to a "best match" for which CLDR does not provide
+ data, even though there are locales for which CLDR does provide data that do
+ match the given ID. It's telling us, unhelpfully but truthfully, what
+ locale would (most likely) be meant by (someone using) the combination
+ requested, even when that locale isn't yet supported.) It may also map an
+ obsolete or generic tag to a modern or more specific replacement, possibly
+ filling in some of the other fields in the process (presently only for
+ countries). Note that some fields of the result may remain blank, but there
+ is no more specific recommendation available.
+
+ For the formal specification, see
+ https://www.unicode.org/reports/tr35/#Likely_Subtags
+
+ \note We also search und_script_region and und_region; they're not mentioned
+ in the spec, but the examples clearly presume them and CLDR does provide
+ such likely matches.
+*/
QLocaleId QLocaleId::withLikelySubtagsAdded() const
{
- // language_script_region
- if (language_id || script_id || country_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, script_id, country_id);
- if (addLikelySubtags(id))
- return id;
- }
- // language_region
- if (script_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
- if (addLikelySubtags(id)) {
- id.script_id = script_id;
- return id;
+ /* Each pattern that appears in a comments below, language_script_region and
+ similar, indicates which of this's fields (even if blank) are being
+ attended to in a given search; for fields left out of the pattern, the
+ search uses 0 regardless of whether this has specified the field.
+
+ If a key matches what we're searching for (possibly with a wildcard in
+ the key matching a non-wildcard in our search), the tags from this that
+ are specified in the key are replaced by the match (even if different);
+ but the other tags of this replace what's in the match (even when the
+ match does specify a value).
+ */
+ static_assert(std::size(likely_subtags) % 2 == 0);
+ auto *pairs = reinterpret_cast<const LikelyPair *>(likely_subtags);
+ auto *const afterPairs = pairs + std::size(likely_subtags) / 2;
+ LikelyPair sought { *this };
+ // Our array is sorted in the order that puts all candidate matches in the
+ // order we would want them; ones we should prefer appear before the others.
+ if (language_id) {
+ // language_script_region, language_region, language_script, language:
+ pairs = std::lower_bound(pairs, afterPairs, sought);
+ // Single language's block isn't long enough to warrant more binary
+ // chopping within it - just traverse it all:
+ for (; pairs < afterPairs && pairs->key.language_id == language_id; ++pairs) {
+ const QLocaleId &key = pairs->key;
+ if (key.territory_id && key.territory_id != territory_id)
+ continue;
+ if (key.script_id && key.script_id != script_id)
+ continue;
+ QLocaleId value = pairs->value;
+ if (territory_id && !key.territory_id)
+ value.territory_id = territory_id;
+ if (script_id && !key.script_id)
+ value.script_id = script_id;
+ return value;
}
}
- // language_script
- if (country_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
- if (addLikelySubtags(id)) {
- id.country_id = country_id;
- return id;
+ // und_script_region or und_region (in that order):
+ if (territory_id) {
+ sought.key = QLocaleId { 0, script_id, territory_id };
+ pairs = std::lower_bound(pairs, afterPairs, sought);
+ // Again, individual und_?_region block isn't long enough to make binary
+ // chop a win:
+ for (; pairs < afterPairs && pairs->key.territory_id == territory_id; ++pairs) {
+ const QLocaleId &key = pairs->key;
+ Q_ASSERT(!key.language_id);
+ if (key.script_id && key.script_id != script_id)
+ continue;
+ QLocaleId value = pairs->value;
+ if (language_id)
+ value.language_id = language_id;
+ if (script_id && !key.script_id)
+ value.script_id = script_id;
+ return value;
}
}
- // language
- if (script_id && country_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
- if (addLikelySubtags(id)) {
- id.script_id = script_id;
- id.country_id = country_id;
- return id;
+ // und_script:
+ if (script_id) {
+ sought.key = QLocaleId { 0, script_id, 0 };
+ pairs = std::lower_bound(pairs, afterPairs, sought);
+ if (pairs < afterPairs && pairs->key.script_id == script_id) {
+ Q_ASSERT(!pairs->key.language_id && !pairs->key.territory_id);
+ QLocaleId value = pairs->value;
+ if (language_id)
+ value.language_id = language_id;
+ if (territory_id)
+ value.territory_id = territory_id;
+ return value;
}
}
- // und_script
- if (language_id) {
- QLocaleId id = QLocaleId::fromIds(0, script_id, 0);
- if (addLikelySubtags(id)) {
- id.language_id = language_id;
- return id;
+ if (matchesAll()) { // Skipped all of the above.
+ // CLDR has no match-all at v37, but might get one some day ...
+ pairs = std::lower_bound(pairs, afterPairs, sought);
+ if (pairs < afterPairs) {
+ // All other keys are < match-all.
+ Q_ASSERT(pairs + 1 == afterPairs);
+ Q_ASSERT(pairs->key.matchesAll());
+ return pairs->value;
}
}
return *this;
@@ -277,19 +384,19 @@ QLocaleId QLocaleId::withLikelySubtagsRemoved() const
QLocaleId max = withLikelySubtagsAdded();
// language
{
- QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
+ QLocaleId id { language_id, 0, 0 };
if (id.withLikelySubtagsAdded() == max)
return id;
}
// language_region
- if (country_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
+ if (territory_id) {
+ QLocaleId id { language_id, 0, territory_id };
if (id.withLikelySubtagsAdded() == max)
return id;
}
// language_script
if (script_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
+ QLocaleId id { language_id, script_id, 0 };
if (id.withLikelySubtagsAdded() == max)
return id;
}
@@ -303,19 +410,34 @@ QByteArray QLocaleId::name(char separator) const
if (language_id == QLocale::C)
return QByteArrayLiteral("C");
- const unsigned char *lang = language_code_list + 3 * language_id;
+ const LanguageCodeEntry &language = languageCodeList[language_id];
+ AlphaCode lang;
+ qsizetype langLen;
+
+ if (language.part1.isValid()) {
+ lang = language.part1;
+ langLen = 2;
+ } else {
+ lang = language.part2B.isValid() ? language.part2B : language.part3;
+ langLen = 3;
+ }
+
const unsigned char *script =
(script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : nullptr);
const unsigned char *country =
- (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : nullptr);
- char len = (lang[2] != 0 ? 3 : 2) + (script ? 4 + 1 : 0)
- + (country ? (country[2] != 0 ? 3 : 2) + 1 : 0);
+ (territory_id != QLocale::AnyTerritory
+ ? territory_code_list + 3 * territory_id : nullptr);
+ qsizetype len = langLen + (script ? 4 + 1 : 0) + (country ? (country[2] != 0 ? 3 : 2) + 1 : 0);
QByteArray name(len, Qt::Uninitialized);
char *uc = name.data();
- *uc++ = lang[0];
- *uc++ = lang[1];
- if (lang[2] != 0)
- *uc++ = lang[2];
+
+ auto langArray = lang.decode();
+
+ *uc++ = langArray[0];
+ *uc++ = langArray[1];
+ if (langLen > 2)
+ *uc++ = langArray[2];
+
if (script) {
*uc++ = separator;
*uc++ = script[0];
@@ -340,275 +462,186 @@ QByteArray QLocalePrivate::bcp47Name(char separator) const
if (m_data->m_language_id == QLocale::C)
return QByteArrayLiteral("en");
- QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id,
- m_data->m_country_id);
- return localeId.withLikelySubtagsRemoved().name(separator);
+ return m_data->id().withLikelySubtagsRemoved().name(separator);
}
-/*!
- \internal
- */
-QByteArray QLocalePrivate::rawName(char separator) const
+static qsizetype findLocaleIndexById(QLocaleId localeId)
{
- QByteArrayList parts;
- if (m_data->m_language_id != QLocale::AnyLanguage)
- parts.append(languageCode().latin1());
- if (m_data->m_script_id != QLocale::AnyScript)
- parts.append(scriptCode().latin1());
- if (m_data->m_country_id != QLocale::AnyCountry)
- parts.append(countryCode().latin1());
-
- return parts.join(separator);
-}
-
-
-static const QLocaleData *findLocaleDataById(const QLocaleId &lid)
-{
- QLocaleId localeId = lid.withLikelySubtagsAdded();
-
- const uint idx = locale_index[localeId.language_id];
-
- const QLocaleData *data = locale_data + idx;
-
- if (idx == 0) // default language has no associated script or country
- return data;
+ qsizetype idx = locale_index[localeId.language_id];
+ // If there are no locales for specified language (so we we've got the
+ // default language, which has no associated script or country), give up:
+ if (localeId.language_id && idx == 0)
+ return idx;
- Q_ASSERT(data->m_language_id == localeId.language_id);
+ Q_ASSERT(localeId.acceptLanguage(locale_data[idx].m_language_id));
- if (localeId.script_id == QLocale::AnyScript && localeId.country_id == QLocale::AnyCountry)
- return data;
+ do {
+ if (localeId.acceptScriptTerritory(locale_data[idx].id()))
+ return idx;
+ ++idx;
+ } while (localeId.acceptLanguage(locale_data[idx].m_language_id));
- if (localeId.script_id == QLocale::AnyScript) {
- do {
- if (data->m_country_id == localeId.country_id)
- return data;
- ++data;
- } while (data->m_language_id && data->m_language_id == localeId.language_id);
- } else if (localeId.country_id == QLocale::AnyCountry) {
- do {
- if (data->m_script_id == localeId.script_id)
- return data;
- ++data;
- } while (data->m_language_id && data->m_language_id == localeId.language_id);
- } else {
- do {
- if (data->m_script_id == localeId.script_id
- && data->m_country_id == localeId.country_id) {
- return data;
- }
- ++data;
- } while (data->m_language_id && data->m_language_id == localeId.language_id);
- }
-
- return nullptr;
+ return -1;
}
-const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script,
- QLocale::Country country)
+qsizetype QLocaleData::findLocaleIndex(QLocaleId lid)
{
- QLocaleId localeId = QLocaleId::fromIds(language, script, country);
+ QLocaleId localeId = lid;
QLocaleId likelyId = localeId.withLikelySubtagsAdded();
-
- const uint idx = locale_index[likelyId.language_id];
+ const ushort fallback = likelyId.language_id;
// Try a straight match with the likely data:
- if (const QLocaleData *const data = findLocaleDataById(likelyId))
- return data;
- QList<QLocaleId> tried;
+ qsizetype index = findLocaleIndexById(likelyId);
+ if (index >= 0)
+ return index;
+ QVarLengthArray<QLocaleId, 6> tried;
tried.push_back(likelyId);
+#define CheckCandidate(id) do { \
+ if (!tried.contains(id)) { \
+ index = findLocaleIndexById(id); \
+ if (index >= 0) \
+ return index; \
+ tried.push_back(id); \
+ } \
+ } while (false) // end CheckCandidate
+
// No match; try again with raw data:
- if (!tried.contains(localeId)) {
- if (const QLocaleData *const data = findLocaleDataById(localeId))
- return data;
- tried.push_back(localeId);
- }
+ CheckCandidate(localeId);
- // No match; try again with likely country
- if (country != QLocale::AnyCountry
- && (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) {
- localeId = QLocaleId::fromIds(language, script, QLocale::AnyCountry);
+ // No match; try again with likely country for language_script
+ if (lid.territory_id && (lid.language_id || lid.script_id)) {
+ localeId.territory_id = 0;
likelyId = localeId.withLikelySubtagsAdded();
- if (!tried.contains(likelyId)) {
- if (const QLocaleData *const data = findLocaleDataById(likelyId))
- return data;
- tried.push_back(likelyId);
- }
+ CheckCandidate(likelyId);
// No match; try again with any country
- if (!tried.contains(localeId)) {
- if (const QLocaleData *const data = findLocaleDataById(localeId))
- return data;
- tried.push_back(localeId);
- }
+ CheckCandidate(localeId);
}
- // No match; try again with likely script
- if (script != QLocale::AnyScript
- && (language != QLocale::AnyLanguage || country != QLocale::AnyCountry)) {
- localeId = QLocaleId::fromIds(language, QLocale::AnyScript, country);
+ // No match; try again with likely script for language_region
+ if (lid.script_id && (lid.language_id || lid.territory_id)) {
+ localeId = QLocaleId { lid.language_id, 0, lid.territory_id };
likelyId = localeId.withLikelySubtagsAdded();
- if (!tried.contains(likelyId)) {
- if (const QLocaleData *const data = findLocaleDataById(likelyId))
- return data;
- tried.push_back(likelyId);
- }
+ CheckCandidate(likelyId);
// No match; try again with any script
- if (!tried.contains(localeId)) {
- if (const QLocaleData *const data = findLocaleDataById(localeId))
- return data;
- tried.push_back(localeId);
- }
+ CheckCandidate(localeId);
}
+#undef CheckCandidate
- // No match; return data at original index
- return locale_data + idx;
+ // No match; return base index for initial likely language:
+ return locale_index[fallback];
}
-uint QLocaleData::findLocaleOffset(QLocale::Language language, QLocale::Script script,
- QLocale::Country country)
+static QStringView findTag(QStringView name) noexcept
{
- return findLocaleData(language, script, country) - locale_data;
+ const std::u16string_view v(name.utf16(), size_t(name.size()));
+ const auto i = v.find_first_of(u"_-.@");
+ if (i == std::string_view::npos)
+ return name;
+ return name.first(qsizetype(i));
}
-static bool parse_locale_tag(const QString &input, int &i, QString *result,
- const QString &separators)
+static bool validTag(QStringView tag)
{
- *result = QString(8, Qt::Uninitialized); // worst case according to BCP47
- QChar *pch = result->data();
- const QChar *uc = input.data() + i;
- const int l = input.length();
- int size = 0;
- for (; i < l && size < 8; ++i, ++size) {
- if (separators.contains(*uc))
- break;
- if (! ((uc->unicode() >= 'a' && uc->unicode() <= 'z') ||
- (uc->unicode() >= 'A' && uc->unicode() <= 'Z') ||
- (uc->unicode() >= '0' && uc->unicode() <= '9')) ) // latin only
+ // Is tag is a non-empty sequence of ASCII letters and/or digits ?
+ for (QChar uc : tag) {
+ const char16_t ch = uc.unicode();
+ if (!isAsciiLetterOrNumber(ch))
return false;
- *pch++ = *uc++;
}
- result->truncate(size);
- return true;
+ return tag.size() > 0;
}
-bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry)
+static bool isScript(QStringView tag)
{
- const int length = name.length();
-
- lang = script = cntry = QString();
+ // Every script name is 4 characters, a capital followed by three lower-case;
+ // so a search for tag in allScripts *can* only match if it's aligned.
+ static const QString allScripts =
+ QString::fromLatin1(reinterpret_cast<const char *>(script_code_list),
+ sizeof(script_code_list) - 1);
+ return tag.size() == 4 && allScripts.indexOf(tag) % 4 == 0;
+}
- const QString separators = QStringLiteral("_-.@");
+bool qt_splitLocaleName(QStringView name, QStringView *lang, QStringView *script, QStringView *land)
+{
+ // Assume each of lang, script and land is nullptr or points to an empty QStringView.
enum ParserState { NoState, LangState, ScriptState, CountryState };
ParserState state = LangState;
- for (int i = 0; i < length && state != NoState; ) {
- QString value;
- if (!parse_locale_tag(name, i, &value, separators) ||value.isEmpty())
+ while (name.size() && state != NoState) {
+ const QStringView tag = findTag(name);
+ if (!validTag(tag))
break;
- QChar sep = i < length ? name.at(i) : QChar();
+ name = name.sliced(tag.size());
+ const bool sep = name.size() > 0;
+ if (sep) // tag wasn't all that remained; there was a separator
+ name = name.sliced(1);
+
switch (state) {
case LangState:
- if (!sep.isNull() && !separators.contains(sep)) {
- state = NoState;
- break;
- }
- lang = value;
- if (i == length) {
- // just language was specified
- state = NoState;
- break;
- }
- state = ScriptState;
+ if (tag.size() != 2 && tag.size() != 3)
+ return false;
+ if (lang)
+ *lang = tag;
+ state = sep ? ScriptState : NoState;
break;
- case ScriptState: {
- QString scripts = QString::fromLatin1((const char *)script_code_list,
- sizeof(script_code_list) - 1);
- if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) {
- // script name is always 4 characters
- script = value;
- state = CountryState;
- } else {
- // it wasn't a script, maybe it is a country then?
- cntry = value;
- state = NoState;
+ case ScriptState:
+ if (isScript(tag)) {
+ if (script)
+ *script = tag;
+ state = sep ? CountryState : NoState;
+ break;
}
- break;
- }
+ // It wasn't a script, assume it's a country.
+ Q_FALLTHROUGH();
case CountryState:
- cntry = value;
+ if (land)
+ *land = tag;
state = NoState;
break;
- case NoState:
- // shouldn't happen
- qWarning("QLocale: This should never happen");
+ case NoState: // Precluded by loop condition !
+ Q_UNREACHABLE();
break;
}
- ++i;
}
- return lang.length() == 2 || lang.length() == 3;
+ return state != LangState;
}
-void QLocalePrivate::getLangAndCountry(const QString &name, QLocale::Language &lang,
- QLocale::Script &script, QLocale::Country &cntry)
+QLocaleId QLocaleId::fromName(QStringView name)
{
- lang = QLocale::C;
- script = QLocale::AnyScript;
- cntry = QLocale::AnyCountry;
+ QStringView lang;
+ QStringView script;
+ QStringView land;
+ if (!qt_splitLocaleName(name, &lang, &script, &land))
+ return { QLocale::C, 0, 0 };
- QString lang_code;
- QString script_code;
- QString cntry_code;
- if (!qt_splitLocaleName(name, lang_code, script_code, cntry_code))
- return;
-
- lang = QLocalePrivate::codeToLanguage(lang_code);
- if (lang == QLocale::C)
- return;
- script = QLocalePrivate::codeToScript(script_code);
- cntry = QLocalePrivate::codeToCountry(cntry_code);
+ QLocale::Language langId = QLocalePrivate::codeToLanguage(lang);
+ if (langId == QLocale::AnyLanguage)
+ return { QLocale::C, 0, 0 };
+ return { langId, QLocalePrivate::codeToScript(script), QLocalePrivate::codeToTerritory(land) };
}
-static const QLocaleData *findLocaleData(const QString &name)
+QString qt_readEscapedFormatString(QStringView format, qsizetype *idx)
{
- QLocale::Language lang;
- QLocale::Script script;
- QLocale::Country cntry;
- QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
-
- return QLocaleData::findLocaleData(lang, script, cntry);
-}
+ qsizetype &i = *idx;
-static uint findLocaleOffset(const QString &name)
-{
- QLocale::Language lang;
- QLocale::Script script;
- QLocale::Country cntry;
- QLocalePrivate::getLangAndCountry(name, lang, script, cntry);
-
- return QLocaleData::findLocaleOffset(lang, script, cntry);
-}
-
-QString qt_readEscapedFormatString(QStringView format, int *idx)
-{
- int &i = *idx;
-
- Q_ASSERT(format.at(i) == QLatin1Char('\''));
+ Q_ASSERT(format.at(i) == u'\'');
++i;
if (i == format.size())
return QString();
- if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng
+ if (format.at(i).unicode() == '\'') { // "''" outside of a quoted string
++i;
- return QLatin1String("'");
+ return "'"_L1;
}
QString result;
while (i < format.size()) {
if (format.at(i).unicode() == '\'') {
- if (format.mid(i + 1).startsWith(QLatin1Char('\''))) {
+ if (format.mid(i + 1).startsWith(u'\'')) {
// "''" inside a quoted string
- result.append(QLatin1Char('\''));
+ result.append(u'\'');
i += 2;
} else {
break;
@@ -639,7 +672,7 @@ QString qt_readEscapedFormatString(QStringView format, int *idx)
qt_repeatCount(u"aab"); // == 2
\endcode
*/
-int qt_repeatCount(QStringView s)
+qsizetype qt_repeatCount(QStringView s)
{
if (s.isEmpty())
return 0;
@@ -647,60 +680,66 @@ int qt_repeatCount(QStringView s)
qsizetype j = 1;
while (j < s.size() && s.at(j) == c)
++j;
- return int(j);
+ return j;
}
-static const QLocaleData *default_data = nullptr;
+Q_CONSTINIT static const QLocaleData *default_data = nullptr;
+Q_CONSTINIT QBasicAtomicInt QLocalePrivate::s_generation = Q_BASIC_ATOMIC_INITIALIZER(0);
-static const QLocaleData *const c_data = locale_data;
static QLocalePrivate *c_private()
{
- static QLocalePrivate c_locale{
- c_data, Q_BASIC_ATOMIC_INITIALIZER(1), 0, QLocale::OmitGroupSeparator };
+ static QLocalePrivate c_locale(locale_data, 0, QLocale::OmitGroupSeparator, 1);
return &c_locale;
}
-static const QLocaleData *systemData();
-Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
- (QLocalePrivate::create(systemData())))
-
#ifndef QT_NO_SYSTEMLOCALE
/******************************************************************************
** Default system locale behavior
*/
/*!
- Constructs a QSystemLocale object.
-
- The constructor will automatically install this object as the system locale,
- if there's not one active. It also resets the flag that'll prompt
- QLocale::system() to re-initialize its data, so that instantiating a
- QSystemLocale transiently (doesn't install the transient as system locale if
- there was one already and) triggers an update to the system locale's data.
+ \internal
+ Constructs a QSystemLocale object.
+
+ The constructor will automatically install this object as the system locale.
+ It and the destructor maintain a stack of system locales, with the
+ most-recently-created instance (that hasn't yet been deleted) used as the
+ system locale. This is only intended as a way to let a platform plugin
+ install its own system locale, overriding what might otherwise be provided
+ for its class of platform (as Android does, differing from Linux), and to
+ let tests transiently override the system or plugin-supplied one. As such,
+ there should not be diverse threads creating and destroying QSystemLocale
+ instances concurrently, so no attempt is made at thread-safety in managing
+ the stack.
+
+ This constructor also resets the flag that'll prompt QLocale::system() to
+ re-initialize its data, so that instantiating a QSystemLocale (even
+ transiently) triggers a refresh of the system locale's data. This is
+ exploited by some test code.
*/
-QSystemLocale::QSystemLocale()
+QSystemLocale::QSystemLocale() : next(_systemLocale)
{
- if (!_systemLocale)
- _systemLocale = this;
+ _systemLocale = this;
- globalLocaleData.m_language_id = 0;
+ systemLocaleData.m_language_id = 0;
}
/*!
\internal
-*/
-QSystemLocale::QSystemLocale(bool)
-{ }
-
-/*!
- Deletes the object.
+ Deletes the object.
*/
QSystemLocale::~QSystemLocale()
{
if (_systemLocale == this) {
- _systemLocale = nullptr;
+ _systemLocale = next;
- globalLocaleData.m_language_id = 0;
+ // Change to system locale => force refresh.
+ systemLocaleData.m_language_id = 0;
+ } else {
+ for (QSystemLocale *p = _systemLocale; p; p = p->next) {
+ if (p->next == this)
+ p->next = next;
+ }
}
}
@@ -708,7 +747,12 @@ static const QSystemLocale *systemLocale()
{
if (_systemLocale)
return _systemLocale;
- return QSystemLocale_globalSystemLocale();
+
+ // As this is only ever instantiated with _systemLocale null, it is
+ // necessarily the ->next-most in any chain that may subsequently develop;
+ // and it won't be destructed until exit()-time.
+ static QSystemLocale globalInstance;
+ return &globalInstance;
}
static void updateSystemPrivate()
@@ -719,48 +763,69 @@ static void updateSystemPrivate()
const QSystemLocale *sys_locale = systemLocale();
// tell the object that the system locale has changed.
- sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
+ sys_locale->query(QSystemLocale::LocaleChanged);
- // Populate global with fallback as basis:
- globalLocaleData = *sys_locale->fallbackUiLocaleData();
+ // Populate system locale with fallback as basis
+ systemLocaleData = locale_data[sys_locale->fallbackLocaleIndex()];
- QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
+ QVariant res = sys_locale->query(QSystemLocale::LanguageId);
if (!res.isNull()) {
- globalLocaleData.m_language_id = res.toInt();
- globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
+ systemLocaleData.m_language_id = res.toInt();
+ systemLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
}
- res = sys_locale->query(QSystemLocale::CountryId, QVariant());
+ res = sys_locale->query(QSystemLocale::TerritoryId);
if (!res.isNull()) {
- globalLocaleData.m_country_id = res.toInt();
- globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
+ systemLocaleData.m_territory_id = res.toInt();
+ systemLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
}
- res = sys_locale->query(QSystemLocale::ScriptId, QVariant());
+ res = sys_locale->query(QSystemLocale::ScriptId);
if (!res.isNull())
- globalLocaleData.m_script_id = res.toInt();
+ systemLocaleData.m_script_id = res.toInt();
// Should we replace Any values based on likely sub-tags ?
+
+ // If system locale is default locale, update the default collator's generation:
+ if (default_data == &systemLocaleData)
+ QLocalePrivate::s_generation.fetchAndAddRelaxed(1);
}
#endif // !QT_NO_SYSTEMLOCALE
-static const QLocaleData *systemData()
+static const QLocaleData *systemData(qsizetype *sysIndex = nullptr)
{
#ifndef QT_NO_SYSTEMLOCALE
/*
Copy over the information from the fallback locale and modify.
- This modifies (cross-thread) global state, so take care to only call it in
- one thread.
+ If sysIndex is passed, it should be the m_index of the system locale's
+ QLocalePrivate, which we'll update if it needs it.
+
+ This modifies (cross-thread) global state, so is mutex-protected.
*/
{
- static QBasicMutex systemDataMutex;
+ Q_CONSTINIT static QLocaleId sysId;
+ bool updated = false;
+
+ Q_CONSTINIT static QBasicMutex systemDataMutex;
systemDataMutex.lock();
- if (globalLocaleData.m_language_id == 0)
+ if (systemLocaleData.m_language_id == 0) {
updateSystemPrivate();
+ updated = true;
+ }
+ // Initialization of system private has *sysIndex == -1 to hit this.
+ if (sysIndex && (updated || *sysIndex < 0)) {
+ const QLocaleId nowId = systemLocaleData.id();
+ if (sysId != nowId || *sysIndex < 0) {
+ // This look-up may be expensive:
+ *sysIndex = QLocaleData::findLocaleIndex(nowId);
+ sysId = nowId;
+ }
+ }
systemDataMutex.unlock();
}
- return &globalLocaleData;
+ return &systemLocaleData;
#else
+ Q_UNUSED(sysIndex);
return locale_data;
#endif
}
@@ -772,10 +837,26 @@ static const QLocaleData *defaultData()
return default_data;
}
+static qsizetype defaultIndex()
+{
+ const QLocaleData *const data = defaultData();
+#ifndef QT_NO_SYSTEMLOCALE
+ if (data == &systemLocaleData) {
+ // Work out a suitable index matching the system data, for use when
+ // accessing calendar data, when not fetched from system.
+ return QLocaleData::findLocaleIndex(data->id());
+ }
+#endif
+
+ using QtPrivate::q_points_into_range;
+ Q_ASSERT(q_points_into_range(data, locale_data));
+ return data - locale_data;
+}
+
const QLocaleData *QLocaleData::c()
{
Q_ASSERT(locale_index[QLocale::C] == 0);
- return c_data;
+ return locale_data;
}
#ifndef QT_NO_DATASTREAM
@@ -794,66 +875,79 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
}
#endif // QT_NO_DATASTREAM
+static constexpr qsizetype locale_data_size = q20::ssize(locale_data) - 1; // trailing guard
-static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
+Q_GLOBAL_STATIC(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
+ new QLocalePrivate(defaultData(), defaultIndex()))
-Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
- (QLocalePrivate::create(defaultData())))
-
-static QLocalePrivate *localePrivateByName(const QString &name)
+static QLocalePrivate *localePrivateByName(QStringView name)
{
- if (name == QLatin1String("C"))
+ if (name == u"C")
return c_private();
- // TODO: Remove this version, and use offset everywhere
- const QLocaleData *data = findLocaleData(name);
- return QLocalePrivate::create(data, findLocaleOffset(name),
- data->m_language_id == QLocale::C
- ? QLocale::OmitGroupSeparator : QLocale::DefaultNumberOptions);
+ const qsizetype index = QLocaleData::findLocaleIndex(QLocaleId::fromName(name));
+ Q_ASSERT(index >= 0 && index < locale_data_size);
+ return new QLocalePrivate(locale_data + index, index,
+ locale_data[index].m_language_id == QLocale::C
+ ? QLocale::OmitGroupSeparator : QLocale::DefaultNumberOptions);
}
static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Script script,
- QLocale::Country country)
+ QLocale::Territory territory)
{
if (language == QLocale::C)
return c_private();
- // TODO: Remove pointer, use index instead
- const QLocaleData *data = QLocaleData::findLocaleData(language, script, country);
- const uint offset = QLocaleData::findLocaleOffset(language, script, country);
+ qsizetype index = QLocaleData::findLocaleIndex(QLocaleId { language, script, territory });
+ Q_ASSERT(index >= 0 && index < locale_data_size);
+ const QLocaleData *data = locale_data + index;
QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions;
- // If not found, should default to system
+ // If not found, should use default locale:
if (data->m_language_id == QLocale::C) {
if (defaultLocalePrivate.exists())
numberOptions = defaultLocalePrivate->data()->m_numberOptions;
data = defaultData();
+ index = defaultIndex();
}
- return QLocalePrivate::create(data, offset, numberOptions);
+ return new QLocalePrivate(data, index, numberOptions);
}
-QString QLocaleData::decimalPoint() const
+static std::optional<QString>
+systemLocaleString(const QLocaleData *that, QSystemLocale::QueryType type)
{
#ifndef QT_NO_SYSTEMLOCALE
- if (this == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::DecimalPoint, QVariant());
- if (!res.isNull())
- return res.toString();
- }
+ if (that != &systemLocaleData)
+ return std::nullopt;
+
+ QVariant v = systemLocale()->query(type);
+ if (v.metaType() != QMetaType::fromType<QString>())
+ return std::nullopt;
+
+ return v.toString();
+#else
+ Q_UNUSED(that)
+ Q_UNUSED(type)
+ return std::nullopt;
#endif
- return decimalSeparator().getData(single_character_data);
+}
+
+static QString localeString(const QLocaleData *that, QSystemLocale::QueryType type,
+ QLocaleData::DataRange range)
+{
+ if (auto opt = systemLocaleString(that, type))
+ return *opt;
+ return range.getData(single_character_data);
+}
+
+QString QLocaleData::decimalPoint() const
+{
+ return localeString(this, QSystemLocale::DecimalPoint, decimalSeparator());
}
QString QLocaleData::groupSeparator() const
{
-#ifndef QT_NO_SYSTEMLOCALE
- if (this == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::GroupSeparator, QVariant());
- if (!res.isNull())
- return res.toString();
- }
-#endif
- return groupDelim().getData(single_character_data);
+ return localeString(this, QSystemLocale::GroupSeparator, groupDelim());
}
QString QLocaleData::percentSign() const
@@ -868,23 +962,15 @@ QString QLocaleData::listSeparator() const
QString QLocaleData::zeroDigit() const
{
-#ifndef QT_NO_SYSTEMLOCALE
- if (this == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::ZeroDigit, QVariant());
- if (!res.isNull())
- return res.toString();
- }
-#endif
- return zero().getData(single_character_data);
+ return localeString(this, QSystemLocale::ZeroDigit, zero());
}
-uint QLocaleData::zeroUcs() const
+char32_t QLocaleData::zeroUcs() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (this == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::ZeroDigit, QVariant());
- if (!res.isNull()) {
- const QString text = res.toString();
+ if (this == &systemLocaleData) {
+ const auto text = systemLocale()->query(QSystemLocale::ZeroDigit).toString();
+ if (!text.isEmpty()) {
if (text.size() == 1 && !text.at(0).isSurrogate())
return text.at(0).unicode();
if (text.size() == 2 && text.at(0).isHighSurrogate())
@@ -897,26 +983,12 @@ uint QLocaleData::zeroUcs() const
QString QLocaleData::negativeSign() const
{
-#ifndef QT_NO_SYSTEMLOCALE
- if (this == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::NegativeSign, QVariant());
- if (!res.isNull())
- return res.toString();
- }
-#endif
- return minus().getData(single_character_data);
+ return localeString(this, QSystemLocale::NegativeSign, minus());
}
QString QLocaleData::positiveSign() const
{
-#ifndef QT_NO_SYSTEMLOCALE
- if (this == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::PositiveSign, QVariant());
- if (!res.isNull())
- return res.toString();
- }
-#endif
- return plus().getData(single_character_data);
+ return localeString(this, QSystemLocale::PositiveSign, plus());
}
QString QLocaleData::exponentSeparator() const
@@ -931,108 +1003,115 @@ QLocale::QLocale(QLocalePrivate &dd)
: d(&dd)
{}
+/*!
+ \variable QLocale::DefaultTwoDigitBaseYear
+ \since 6.7
+
+ \brief The default start year of the century within which a format taking
+ a two-digit year will select. The value of the constant is \c {1900}.
+
+ Some locales use, particularly for ShortFormat, only the last two digits of
+ the year. Proir to 6.7 the year 1900 was always used as a base year for
+ such cases. Now various QLocale and QDate functions have the overloads that
+ allow callers to specify the base year, and this constant is used as its
+ default value.
+
+ \sa toDate(), toDateTime(), QDate::fromString(), QDateTime::fromString()
+*/
/*!
- Constructs a QLocale object with the specified \a name,
- which has the format
- "language[_script][_country][.codeset][@modifier]" or "C", where:
+ \since 6.3
- \list
- \li language is a lowercase, two-letter, ISO 639 language code (also some
- three-letter codes),
- \li script is a titlecase, four-letter, ISO 15924 script code,
- \li country is an uppercase, two-letter, ISO 3166 country code
- (also "419" as defined by United Nations),
- \li and codeset and modifier are ignored.
- \endlist
+ Constructs a QLocale object with the specified \a name.
- The separator can be either underscore or a minus sign.
+ The name has the format "language[_script][_territory][.codeset][@modifier]"
+ or "C", where:
- If the string violates the locale format, or language is not
- a valid ISO 639 code, the "C" locale is used instead. If country
- is not present, or is not a valid ISO 3166 code, the most
- appropriate country is chosen for the specified language.
+ \list
+ \li language is a lowercase, two-letter, ISO 639 language code (some
+ three-letter codes are also recognized),
+ \li script is a capitalized, four-letter, ISO 15924 script code,
+ \li territory is an uppercase, two-letter, ISO 3166 territory code
+ (some numeric codes are also recognized), and
+ \li codeset and modifier are ignored.
+ \endlist
- The language, script and country codes are converted to their respective
- \c Language, \c Script and \c Country enums. After this conversion is
- performed, the constructor behaves exactly like QLocale(Country, Script,
- Language).
+ The separator can be either underscore \c{'_'} (U+005F, "low line") or a
+ dash \c{'-'} (U+002D, "hyphen-minus"). If QLocale has no data for the
+ specified combination of language, script, and territory, then it uses the
+ most suitable match it can find instead. If the string violates the locale
+ format, or no suitable data can be found for the specified keys, the "C"
+ locale is used instead.
- This constructor is much slower than QLocale(Country, Script, Language).
+ This constructor is much slower than QLocale(Language, Script, Territory) or
+ QLocale(Language, Territory).
- \sa bcp47Name()
+ \sa bcp47Name(), {Matching combinations of language, script and territory}
*/
-
-QLocale::QLocale(const QString &name)
+QLocale::QLocale(QStringView name)
: d(localePrivateByName(name))
{
}
/*!
- Constructs a QLocale object initialized with the default locale. If
- no default locale was set using setDefault(), this locale will
- be the same as the one returned by system().
+ \fn QLocale::QLocale(const QString &name)
+ \overload
+*/
+
+/*!
+ Constructs a QLocale object initialized with the default locale.
- \sa setDefault()
+ If no default locale was set using setDefault(), this locale will be the
+ same as the one returned by system().
+
+ \sa setDefault(), system()
*/
QLocale::QLocale()
: d(*defaultLocalePrivate)
{
- // Make sure system data is up to date
+ // Make sure system data is up to date:
systemData();
}
/*!
- Constructs a QLocale object with the specified \a language and \a
- country.
+ Constructs a QLocale object for the specified \a language and \a territory.
- \list
- \li If the language/country pair is found in the database, it is used.
- \li If the language is found but the country is not, or if the country
- is \c AnyCountry, the language is used with the most
- appropriate available country (for example, Germany for German),
- \li If neither the language nor the country are found, QLocale
- defaults to the default locale (see setDefault()).
- \endlist
-
- The language and country that are actually used can be queried
- using language() and country().
+ If there is more than one script in use for this combination, a likely
+ script will be selected. If QLocale has no data for the specified \a
+ language, the default locale is used. If QLocale has no data for the
+ specified combination of \a language and \a territory, an alternative
+ territory may be used instead.
- \sa setDefault(), language(), country()
+ \sa setDefault(), {Matching combinations of language, script and territory}
*/
-QLocale::QLocale(Language language, Country country)
- : d(findLocalePrivate(language, QLocale::AnyScript, country))
+QLocale::QLocale(Language language, Territory territory)
+ : d(findLocalePrivate(language, AnyScript, territory))
{
}
/*!
\since 4.8
- Constructs a QLocale object with the specified \a language, \a script and
- \a country.
+ Constructs a QLocale object for the specified \a language, \a script and \a
+ territory.
+
+ If QLocale does not have data for the given combination, it will find data
+ for as good a match as it can. It falls back on the default locale if
\list
- \li If the language/script/country is found in the database, it is used.
- \li If both \a script is AnyScript and \a country is AnyCountry, the
- language is used with the most appropriate available script and country
- (for example, Germany for German),
- \li If either \a script is AnyScript or \a country is AnyCountry, the
- language is used with the first locale that matches the given \a script
- and \a country.
- \li If neither the language nor the country are found, QLocale
- defaults to the default locale (see setDefault()).
+ \li \a language is \c AnyLanguage and no language can be inferred from \a
+ script and \a territory
+ \li QLocale has no data for the language, either given as \a language or
+ inferred as above.
\endlist
- The language, script and country that are actually used can be queried
- using language(), script() and country().
-
- \sa setDefault(), language(), script(), country()
+ \sa setDefault(), {Matching combinations of language, script and territory}
*/
-QLocale::QLocale(Language language, Script script, Country country)
- : d(findLocalePrivate(language, script, country))
+QLocale::QLocale(Language language, Script script, Territory territory)
+ : d(findLocalePrivate(language, script, territory))
{
}
@@ -1040,10 +1119,7 @@ QLocale::QLocale(Language language, Script script, Country country)
Constructs a QLocale object as a copy of \a other.
*/
-QLocale::QLocale(const QLocale &other)
-{
- d = other.d;
-}
+QLocale::QLocale(const QLocale &other) noexcept = default;
/*!
Destructor
@@ -1058,20 +1134,16 @@ QLocale::~QLocale()
to this QLocale object.
*/
-QLocale &QLocale::operator=(const QLocale &other)
-{
- d = other.d;
- return *this;
-}
+QLocale &QLocale::operator=(const QLocale &other) noexcept = default;
-bool QLocale::operator==(const QLocale &other) const
-{
- return d->m_data == other.d->m_data && d->m_numberOptions == other.d->m_numberOptions;
-}
+/*!
+ \internal
+ Equality comparison.
+*/
-bool QLocale::operator!=(const QLocale &other) const
+bool QLocale::equals(const QLocale &other) const
{
- return d->m_data != other.d->m_data || d->m_numberOptions != other.d->m_numberOptions;
+ return d->m_data == other.d->m_data && d->m_numberOptions == other.d->m_numberOptions;
}
/*!
@@ -1100,7 +1172,7 @@ size_t qHash(const QLocale &key, size_t seed) noexcept
Sets the \a options related to number conversions for this
QLocale instance.
- \sa numberOptions()
+ \sa numberOptions(), FloatingPointPrecisionOption
*/
void QLocale::setNumberOptions(NumberOptions options)
{
@@ -1116,7 +1188,7 @@ void QLocale::setNumberOptions(NumberOptions options)
By default, no options are set for the standard locales, except
for the "C" locale, which has OmitGroupSeparator set by default.
- \sa setNumberOptions(), toString(), groupSeparator()
+ \sa setNumberOptions(), toString(), groupSeparator(), FloatingPointPrecisionOption
*/
QLocale::NumberOptions QLocale::numberOptions() const
{
@@ -1140,12 +1212,12 @@ QLocale::NumberOptions QLocale::numberOptions() const
QString QLocale::quoteString(QStringView str, QuotationStyle style) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res;
- if (style == QLocale::AlternateQuotation)
+ if (style == AlternateQuotation)
res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation,
QVariant::fromValue(str));
- if (res.isNull() || style == QLocale::StandardQuotation)
+ if (res.isNull() || style == StandardQuotation)
res = systemLocale()->query(QSystemLocale::StringToStandardQuotation,
QVariant::fromValue(str));
if (!res.isNull())
@@ -1154,7 +1226,7 @@ QString QLocale::quoteString(QStringView str, QuotationStyle style) const
#endif
QLocaleData::DataRange start, end;
- if (style == QLocale::StandardQuotation) {
+ if (style == StandardQuotation) {
start = d->m_data->quoteStart();
end = d->m_data->quoteEnd();
} else {
@@ -1173,8 +1245,9 @@ QString QLocale::quoteString(QStringView str, QuotationStyle style) const
*/
QString QLocale::createSeparatedList(const QStringList &list) const
{
+ // May be empty if list is empty or sole entry is empty.
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res =
systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list));
@@ -1183,7 +1256,7 @@ QString QLocale::createSeparatedList(const QStringList &list) const
}
#endif
- const int size = list.size();
+ const qsizetype size = list.size();
if (size < 1)
return QString();
@@ -1198,7 +1271,7 @@ QString QLocale::createSeparatedList(const QStringList &list) const
QStringView formatMid = d->m_data->midListPattern().viewData(list_pattern_part_data);
QStringView formatEnd = d->m_data->endListPattern().viewData(list_pattern_part_data);
QString result = formatStart.arg(list.at(0), list.at(1));
- for (int i = 2; i < size - 1; ++i)
+ for (qsizetype i = 2; i < size - 1; ++i)
result = formatMid.arg(result, list.at(i));
result = formatEnd.arg(result, list.at(size - 1));
return result;
@@ -1233,12 +1306,13 @@ void QLocale::setDefault(const QLocale &locale)
// update the cached private
*defaultLocalePrivate = locale.d;
+ QLocalePrivate::s_generation.fetchAndAddRelaxed(1);
}
/*!
Returns the language of this locale.
- \sa script(), country(), languageToString(), bcp47Name()
+ \sa script(), territory(), languageToString(), bcp47Name()
*/
QLocale::Language QLocale::language() const
{
@@ -1250,7 +1324,7 @@ QLocale::Language QLocale::language() const
Returns the script of this locale.
- \sa language(), country(), languageToString(), scriptToString(), bcp47Name()
+ \sa language(), territory(), languageToString(), scriptToString(), bcp47Name()
*/
QLocale::Script QLocale::script() const
{
@@ -1258,61 +1332,120 @@ QLocale::Script QLocale::script() const
}
/*!
- Returns the country of this locale.
+ \since 6.2
- \sa language(), script(), countryToString(), bcp47Name()
+ Returns the territory of this locale.
+
+ \sa language(), script(), territoryToString(), bcp47Name()
*/
-QLocale::Country QLocale::country() const
+QLocale::Territory QLocale::territory() const
{
- return Country(d->countryId());
+ return Territory(d->territoryId());
}
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
- Returns the language and country of this locale as a
- string of the form "language_country", where
- language is a lowercase, two-letter ISO 639 language code,
- and country is an uppercase, two- or three-letter ISO 3166 country code.
+ \deprecated [6.6] Use \l territory() instead.
- Note that even if QLocale object was constructed with an explicit script,
- name() will not contain it for compatibility reasons. Use bcp47Name() instead
- if you need a full locale name.
+ Returns the territory of this locale.
- \sa QLocale(), language(), script(), country(), bcp47Name()
+ \sa language(), script(), territoryToString(), bcp47Name()
*/
-
-QString QLocale::name() const
+QLocale::Country QLocale::country() const
{
- Language l = language();
- if (l == C)
- return d->languageCode();
-
- Country c = country();
- if (c == AnyCountry)
- return d->languageCode();
-
- return d->languageCode() + QLatin1Char('_') + d->countryCode();
+ return territory();
}
+#endif
-static qlonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
- QLocale::NumberOptions mode, qlonglong)
+/*!
+ \since 6.7
+ \enum QLocale::TagSeparator
+
+ Indicate how to combine the parts that make up a locale identifier.
+
+ A locale identifier may be made up of several tags, indicating language,
+ script and territory (plus, potentially, other details), joined together to
+ form the identifier. Various standards and conventional forms use either a
+ dash (the Unicode HYPHEN-MINUS, U+002D) or an underscore (LOW LINE, U+005F).
+ Different clients of QLocale may thus need one or the other.
+
+ \value Dash Use \c{'-'}, the dash or hyphen character.
+ \value Underscore Use \c{'_'}, the underscore character.
+
+ \note Although dash and underscore are the only separators used in public
+ standards (as at 2023), it is possible to cast any \l
+ {https://en.cppreference.com/w/cpp/language/ascii} {ASCII} character to this
+ type if a non-standard ASCII separator is needed. Casting a non-ASCII
+ character (with decimal value above 127) is not supported: such values are
+ reserved for future use as enum members if some public standard ever uses a
+ non-ASCII separator. It is, of course, possible to use QString::replace() to
+ replace the separator used by a function taking a parameter of this type
+ with an arbitrary Unicode character or string.
+*/
+
+Q_DECL_COLD_FUNCTION static void badSeparatorWarning(const char *method, char sep)
{
- return d->stringToLongLong(str, 10, ok, mode);
+ qWarning("QLocale::%s(): Using non-ASCII separator '%c' (%02x) is unsupported",
+ method, sep, uint(uchar(sep)));
}
-static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
- QLocale::NumberOptions mode, qulonglong)
+/*!
+ \brief The short name of this locale.
+
+ Returns the language and territory of this locale as a string of the form
+ "language_territory", where language is a lowercase, two-letter ISO 639
+ language code, and territory is an uppercase, two- or three-letter ISO 3166
+ territory code. If the locale has no specified territory, only the language
+ name is returned. Since Qt 6.7 an optional \a separator parameter can be
+ supplied to override the default underscore character separating the two
+ tags.
+
+ Even if the QLocale object was constructed with an explicit script, name()
+ will not contain it for compatibility reasons. Use \l bcp47Name() instead if
+ you need a full locale name, or construct the string you want to identify a
+ locale by from those returned by passing its \l language() to \l
+ languageToCode() and similar for the script and territory.
+
+ \sa QLocale(), language(), script(), territory(), bcp47Name(), uiLanguages()
+*/
+
+QString QLocale::name(TagSeparator separator) const
{
- return d->stringToUnsLongLong(str, 10, ok, mode);
+ const char sep = char(separator);
+ if (uchar(sep) > 0x7f) {
+ badSeparatorWarning("name", sep);
+ return {};
+ }
+ const auto code = d->languageCode();
+ QLatin1StringView view{code.data()};
+
+ Language l = language();
+ if (l == C)
+ return view;
+
+ Territory c = territory();
+ if (c == AnyTerritory)
+ return view;
+
+ return view + QLatin1Char(sep) + d->territoryCode();
}
template <typename T> static inline
T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
{
- using Int64 =
- typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
+ constexpr bool isUnsigned = std::is_unsigned_v<T>;
+ using Int64 = typename std::conditional_t<isUnsigned, quint64, qint64>;
+
+ QSimpleParsedNumber<Int64> r{};
+ if constexpr (isUnsigned)
+ r = d->m_data->stringToUnsLongLong(str, 10, d->m_numberOptions);
+ else
+ r = d->m_data->stringToLongLong(str, 10, d->m_numberOptions);
- // we select the right overload by the last, unused parameter
- Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64());
+ if (ok)
+ *ok = r.ok();
+
+ Int64 val = r.result;
if (T(val) != val) {
if (ok != nullptr)
*ok = false;
@@ -1325,64 +1458,229 @@ T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
/*!
\since 4.8
- Returns the dash-separated language, script and country (and possibly other
- BCP47 fields) of this locale as a string.
+ \brief Returns the BCP47 field names joined with dashes.
+
+ This combines as many of language, script and territory (and possibly other
+ BCP47 fields) for this locale as are needed to uniquely specify it. Note
+ that fields may be omitted if the Unicode consortium's \l {Matching
+ combinations of language, script and territory}{Likely Subtag Rules} imply
+ the omitted fields when given those retained. See \l name() for how to
+ construct a string from individual fields, if some other format is needed.
+
+ Unlike uiLanguages(), the value returned by bcp47Name() represents the
+ locale name of the QLocale data; this need not be the language the
+ user-interface should be in.
+
+ This function tries to conform the locale name to the IETF Best Common
+ Practice 47, defined by RFC 5646. Since Qt 6.7, it supports an optional \a
+ separator parameter which can be used to override the BCP47-specified use of
+ a hyphen to separate the tags. For use in IETF-defined protocols, however,
+ the default, QLocale::TagSeparator::Dash, should be retained.
+
+ \sa name(), language(), territory(), script(), uiLanguages()
+*/
+QString QLocale::bcp47Name(TagSeparator separator) const
+{
+ const char sep = char(separator);
+ if (uchar(sep) > 0x7f) {
+ badSeparatorWarning("bcp47Name", sep);
+ return {};
+ }
+ return QString::fromLatin1(d->bcp47Name(sep));
+}
+
+/*!
+ Returns the two- or three-letter language code for \a language, as defined
+ in the ISO 639 standards.
+
+ If specified, \a codeTypes selects which set of codes to consider. The first
+ code from the set that is defined for \a language is returned. Otherwise,
+ all ISO-639 codes are considered. The codes are considered in the following
+ order: \c ISO639Part1, \c ISO639Part2B, \c ISO639Part2T, \c ISO639Part3.
+ \c LegacyLanguageCode is ignored by this function.
+
+ \note For \c{QLocale::C} the function returns \c{"C"}.
+ For \c QLocale::AnyLanguage an empty string is returned.
+ If the language has no code in any selected code set, an empty string
+ is returned.
+
+ \since 6.3
+ \sa codeToLanguage(), language(), name(), bcp47Name(), territoryToCode(), scriptToCode()
+*/
+QString QLocale::languageToCode(Language language, LanguageCodeTypes codeTypes)
+{
+ const auto code = QLocalePrivate::languageToCode(language, codeTypes);
+ return QLatin1StringView{code.data()};
+}
+
+/*!
+ Returns the QLocale::Language enum corresponding to the two- or three-letter
+ \a languageCode, as defined in the ISO 639 standards.
+
+ If specified, \a codeTypes selects which set of codes to consider for
+ conversion. By default all codes known to Qt are considered. The codes are
+ matched in the following order: \c ISO639Part1, \c ISO639Part2B,
+ \c ISO639Part2T, \c ISO639Part3, \c LegacyLanguageCode.
+
+ If the code is invalid or not known \c QLocale::AnyLanguage is returned.
+
+ \since 6.3
+ \sa languageToCode(), codeToTerritory(), codeToScript()
+*/
+QLocale::Language QLocale::codeToLanguage(QStringView languageCode,
+ LanguageCodeTypes codeTypes) noexcept
+{
+ return QLocalePrivate::codeToLanguage(languageCode, codeTypes);
+}
+
+/*!
+ \since 6.2
+
+ Returns the two-letter territory code for \a territory, as defined
+ in the ISO 3166 standard.
+
+ \note For \c{QLocale::AnyTerritory} an empty string is returned.
+
+ \sa codeToTerritory(), territory(), name(), bcp47Name(), languageToCode(), scriptToCode()
+*/
+QString QLocale::territoryToCode(QLocale::Territory territory)
+{
+ return QLocalePrivate::territoryToCode(territory);
+}
+
+/*!
+ \since 6.2
+
+ Returns the QLocale::Territory enum corresponding to the two-letter or
+ three-digit \a territoryCode, as defined in the ISO 3166 standard.
+
+ If the code is invalid or not known QLocale::AnyTerritory is returned.
+
+ \sa territoryToCode(), codeToLanguage(), codeToScript()
+*/
+QLocale::Territory QLocale::codeToTerritory(QStringView territoryCode) noexcept
+{
+ return QLocalePrivate::codeToTerritory(territoryCode);
+}
+
+#if QT_DEPRECATED_SINCE(6, 6)
+/*!
+ \deprecated [6.6] Use \l territoryToCode() instead.
- Unlike the uiLanguages() the returned value of the bcp47Name() represents
- the locale name of the QLocale data but not the language the user-interface
- should be in.
+ Returns the two-letter territory code for \a country, as defined
+ in the ISO 3166 standard.
- This function tries to conform the locale name to BCP47.
+ \note For \c{QLocale::AnyTerritory} or \c{QLocale::AnyCountry} an empty string is returned.
- \sa language(), country(), script(), uiLanguages()
+ \sa codeToTerritory(), territory(), name(), bcp47Name(), languageToCode(), scriptToCode()
*/
-QString QLocale::bcp47Name() const
+QString QLocale::countryToCode(Country country)
{
- return QString::fromLatin1(d->bcp47Name());
+ return territoryToCode(country);
+}
+
+/*!
+ Returns the QLocale::Territory enum corresponding to the two-letter or
+ three-digit \a countryCode, as defined in the ISO 3166 standard.
+
+ If the code is invalid or not known QLocale::AnyTerritory is returned.
+
+ \deprecated [6.6] Use codeToTerritory(QStringView) instead.
+ \since 6.1
+ \sa territoryToCode(), codeToLanguage(), codeToScript()
+*/
+QLocale::Country QLocale::codeToCountry(QStringView countryCode) noexcept
+{
+ return QLocalePrivate::codeToTerritory(countryCode);
+}
+#endif
+
+/*!
+ Returns the four-letter script code for \a script, as defined in the
+ ISO 15924 standard.
+
+ \note For \c{QLocale::AnyScript} an empty string is returned.
+
+ \since 6.1
+ \sa script(), name(), bcp47Name(), languageToCode(), territoryToCode()
+*/
+QString QLocale::scriptToCode(Script script)
+{
+ return QLocalePrivate::scriptToCode(script);
+}
+
+/*!
+ Returns the QLocale::Script enum corresponding to the four-letter script
+ \a scriptCode, as defined in the ISO 15924 standard.
+
+ If the code is invalid or not known QLocale::AnyScript is returned.
+
+ \since 6.1
+ \sa scriptToCode(), codeToLanguage(), codeToTerritory()
+*/
+QLocale::Script QLocale::codeToScript(QStringView scriptCode) noexcept
+{
+ return QLocalePrivate::codeToScript(scriptCode);
}
/*!
Returns a QString containing the name of \a language.
- \sa countryToString(), scriptToString(), bcp47Name()
+ \sa territoryToString(), scriptToString(), bcp47Name()
*/
QString QLocale::languageToString(Language language)
{
- if (uint(language) > uint(QLocale::LastLanguage))
- return QLatin1String("Unknown");
- return QLatin1String(language_name_list + language_name_index[language]);
+ if (language > LastLanguage)
+ return "Unknown"_L1;
+ return QString::fromUtf8(language_name_list + language_name_index[language]);
}
/*!
- Returns a QString containing the name of \a country.
+ \since 6.2
+
+ Returns a QString containing the name of \a territory.
- \sa languageToString(), scriptToString(), country(), bcp47Name()
+ \sa languageToString(), scriptToString(), territory(), bcp47Name()
*/
+QString QLocale::territoryToString(Territory territory)
+{
+ if (territory > LastTerritory)
+ return "Unknown"_L1;
+ return QString::fromUtf8(territory_name_list + territory_name_index[territory]);
+}
+
+#if QT_DEPRECATED_SINCE(6, 6)
+/*!
+ \deprecated [6.6] Use \l territoryToString() instead.
+
+ Returns a QString containing the name of \a country.
+ \sa languageToString(), scriptToString(), territory(), bcp47Name()
+*/
QString QLocale::countryToString(Country country)
{
- if (uint(country) > uint(QLocale::LastCountry))
- return QLatin1String("Unknown");
- return QLatin1String(country_name_list + country_name_index[country]);
+ return territoryToString(country);
}
+#endif
/*!
\since 4.8
Returns a QString containing the name of \a script.
- \sa languageToString(), countryToString(), script(), bcp47Name()
+ \sa languageToString(), territoryToString(), script(), bcp47Name()
*/
-QString QLocale::scriptToString(QLocale::Script script)
+QString QLocale::scriptToString(Script script)
{
- if (uint(script) > uint(QLocale::LastScript))
- return QLatin1String("Unknown");
- return QLatin1String(script_name_list + script_name_index[script]);
+ if (script > LastScript)
+ return "Unknown"_L1;
+ return QString::fromUtf8(script_name_list + script_name_index[script]);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
+ \fn short QLocale::toShort(const QString &s, bool *ok) const
+
Returns the short int represented by the localized string \a s.
If the conversion fails the function returns 0.
@@ -1395,12 +1693,9 @@ QString QLocale::scriptToString(QLocale::Script script)
\sa toUShort(), toString()
*/
-short QLocale::toShort(const QString &s, bool *ok) const
-{
- return toIntegral_helper<short>(d, s, ok);
-}
-
/*!
+ \fn ushort QLocale::toUShort(const QString &s, bool *ok) const
+
Returns the unsigned short int represented by the localized string \a s.
If the conversion fails the function returns 0.
@@ -1413,12 +1708,8 @@ short QLocale::toShort(const QString &s, bool *ok) const
\sa toShort(), toString()
*/
-ushort QLocale::toUShort(const QString &s, bool *ok) const
-{
- return toIntegral_helper<ushort>(d, s, ok);
-}
-
/*!
+ \fn int QLocale::toInt(const QString &s, bool *ok) const
Returns the int represented by the localized string \a s.
If the conversion fails the function returns 0.
@@ -1431,12 +1722,8 @@ ushort QLocale::toUShort(const QString &s, bool *ok) const
\sa toUInt(), toString()
*/
-int QLocale::toInt(const QString &s, bool *ok) const
-{
- return toIntegral_helper<int>(d, s, ok);
-}
-
/*!
+ \fn uint QLocale::toUInt(const QString &s, bool *ok) const
Returns the unsigned int represented by the localized string \a s.
If the conversion fails the function returns 0.
@@ -1449,54 +1736,41 @@ int QLocale::toInt(const QString &s, bool *ok) const
\sa toInt(), toString()
*/
-uint QLocale::toUInt(const QString &s, bool *ok) const
-{
- return toIntegral_helper<uint>(d, s, ok);
-}
-
/*!
- Returns the long int represented by the localized string \a s.
-
- If the conversion fails the function returns 0.
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ \since 5.13
+ \fn long QLocale::toLong(const QString &s, bool *ok) const
- This function ignores leading and trailing whitespace.
+ Returns the long int represented by the localized string \a s.
- \sa toInt(), toULong(), toDouble(), toString()
+ If the conversion fails the function returns 0.
- \since 5.13
- */
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+ This function ignores leading and trailing whitespace.
-long QLocale::toLong(const QString &s, bool *ok) const
-{
- return toIntegral_helper<long>(d, s, ok);
-}
+ \sa toInt(), toULong(), toDouble(), toString()
+*/
/*!
- Returns the unsigned long int represented by the localized
- string \a s.
+ \since 5.13
+ \fn ulong QLocale::toULong(const QString &s, bool *ok) const
- If the conversion fails the function returns 0.
+ Returns the unsigned long int represented by the localized
+ string \a s.
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ If the conversion fails the function returns 0.
- This function ignores leading and trailing whitespace.
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
- \sa toLong(), toInt(), toDouble(), toString()
+ This function ignores leading and trailing whitespace.
- \since 5.13
+ \sa toLong(), toInt(), toDouble(), toString()
*/
-ulong QLocale::toULong(const QString &s, bool *ok) const
-{
- return toIntegral_helper<ulong>(d, s, ok);
-}
-
/*!
+ \fn qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
Returns the long long int represented by the localized string \a s.
If the conversion fails the function returns 0.
@@ -1509,13 +1783,9 @@ ulong QLocale::toULong(const QString &s, bool *ok) const
\sa toInt(), toULongLong(), toDouble(), toString()
*/
-
-qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
-{
- return toIntegral_helper<qlonglong>(d, s, ok);
-}
-
/*!
+ \fn qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
+
Returns the unsigned long long int represented by the localized
string \a s.
@@ -1529,12 +1799,9 @@ qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
\sa toLongLong(), toInt(), toDouble(), toString()
*/
-qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
-{
- return toIntegral_helper<qulonglong>(d, s, ok);
-}
-
/*!
+ \fn float QLocale::toFloat(const QString &s, bool *ok) const
+
Returns the float represented by the localized string \a s.
Returns an infinity if the conversion overflows or 0.0 if the
@@ -1543,20 +1810,13 @@ qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- This function does not fall back to the 'C' locale if the string
- cannot be interpreted in this locale.
-
This function ignores leading and trailing whitespace.
\sa toDouble(), toInt(), toString()
*/
-float QLocale::toFloat(const QString &s, bool *ok) const
-{
- return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
-}
-
/*!
+ \fn double QLocale::toDouble(const QString &s, bool *ok) const
Returns the double represented by the localized string \a s.
Returns an infinity if the conversion overflows or 0.0 if the
@@ -1565,9 +1825,6 @@ float QLocale::toFloat(const QString &s, bool *ok) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- This function does not fall back to the 'C' locale if the string
- cannot be interpreted in this locale.
-
\snippet code/src_corelib_text_qlocale.cpp 3
Notice that the last conversion returns 1234.0, because '.' is the
@@ -1578,12 +1835,6 @@ float QLocale::toFloat(const QString &s, bool *ok) const
\sa toFloat(), toInt(), toString()
*/
-double QLocale::toDouble(const QString &s, bool *ok) const
-{
- return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
-
/*!
Returns the short int represented by the localized string \a s.
@@ -1665,20 +1916,18 @@ uint QLocale::toUInt(QStringView s, bool *ok) const
}
/*!
- Returns the long int represented by the localized string \a s.
-
- If the conversion fails the function returns 0.
+ \since 5.13
+ Returns the long int represented by the localized string \a s.
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- This function ignores leading and trailing whitespace.
+ If the conversion fails the function returns 0.
- \sa toInt(), toULong(), toDouble(), toString()
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
- \since 5.13
- */
+ This function ignores leading and trailing whitespace.
+ \sa toInt(), toULong(), toDouble(), toString()
+*/
long QLocale::toLong(QStringView s, bool *ok) const
{
@@ -1686,20 +1935,19 @@ long QLocale::toLong(QStringView s, bool *ok) const
}
/*!
- Returns the unsigned long int represented by the localized
- string \a s.
-
- If the conversion fails the function returns 0.
+ \since 5.13
+ Returns the unsigned long int represented by the localized
+ string \a s.
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ If the conversion fails the function returns 0.
- This function ignores leading and trailing whitespace.
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
- \sa toLong(), toInt(), toDouble(), toString()
+ This function ignores leading and trailing whitespace.
- \since 5.13
- */
+ \sa toLong(), toInt(), toDouble(), toString()
+*/
ulong QLocale::toULong(QStringView s, bool *ok) const
{
@@ -1778,10 +2026,6 @@ float QLocale::toFloat(QStringView s, bool *ok) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- Unlike QString::toDouble(), this function does not fall back to
- the "C" locale if the string cannot be interpreted in this
- locale.
-
\snippet code/src_corelib_text_qlocale.cpp 3-qstringview
Notice that the last conversion returns 1234.0, because '.' is the
@@ -1807,10 +2051,8 @@ double QLocale::toDouble(QStringView s, bool *ok) const
QString QLocale::toString(qlonglong i) const
{
- int flags = d->m_numberOptions & OmitGroupSeparator
- ? 0
- : (d->m_data->m_country_id == Country::India)
- ? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
+ int flags = (d->m_numberOptions & OmitGroupSeparator
+ ? 0 : QLocaleData::GroupDigits);
return d->m_data->longLongToString(i, -1, 10, -1, flags);
}
@@ -1823,15 +2065,12 @@ QString QLocale::toString(qlonglong i) const
QString QLocale::toString(qulonglong i) const
{
- int flags = d->m_numberOptions & OmitGroupSeparator
- ? 0
- : (d->m_data->m_country_id == Country::India)
- ? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
+ int flags = (d->m_numberOptions & OmitGroupSeparator
+ ? 0 : QLocaleData::GroupDigits);
return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a localized string representation of the given \a date in the
specified \a format.
@@ -1842,39 +2081,97 @@ QString QLocale::toString(qulonglong i) const
QString QLocale::toString(QDate date, const QString &format) const
{
- return QCalendar().dateTimeToString(format, QDateTime(), date, QTime(), *this);
+ return toString(date, qToStringViewIgnoringNull(format));
}
-#endif
/*!
- \since 5.10
+ Returns a localized string representation of the given \a time according
+ to the specified \a format.
+ If \a format is an empty string, an empty string is returned.
+
+ \sa QTime::toString()
+*/
+
+QString QLocale::toString(QTime time, const QString &format) const
+{
+ return toString(time, qToStringViewIgnoringNull(format));
+}
+
+/*!
+ \since 4.4
+ \fn QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
+
+ Returns a localized string representation of the given \a dateTime according
+ to the specified \a format.
+ If \a format is an empty string, an empty string is returned.
+
+ \sa QDateTime::toString(), QDate::toString(), QTime::toString()
+*/
+
+/*!
+ \since 5.14
Returns a localized string representation of the given \a date in the
- specified \a format.
+ specified \a format, optionally for a specified calendar \a cal.
If \a format is an empty string, an empty string is returned.
\sa QDate::toString()
*/
+QString QLocale::toString(QDate date, QStringView format, QCalendar cal) const
+{
+ return cal.dateTimeToString(format, QDateTime(), date, QTime(), *this);
+}
+
+/*!
+ \since 5.10
+ \overload
+*/
QString QLocale::toString(QDate date, QStringView format) const
{
return QCalendar().dateTimeToString(format, QDateTime(), date, QTime(), *this);
}
/*!
+ \since 5.14
+
Returns a localized string representation of the given \a date according
- to the specified \a format (see dateFormat()).
+ to the specified \a format (see dateFormat()), optionally for a specified
+ calendar \a cal.
\note Some locales may use formats that limit the range of years they can
represent.
*/
+QString QLocale::toString(QDate date, FormatType format, QCalendar cal) const
+{
+ if (!date.isValid())
+ return QString();
+#ifndef QT_NO_SYSTEMLOCALE
+ if (cal.isGregorian() && d->m_data == &systemLocaleData) {
+ QVariant res = systemLocale()->query(format == LongFormat
+ ? QSystemLocale::DateToStringLong
+ : QSystemLocale::DateToStringShort,
+ date);
+ if (!res.isNull())
+ return res.toString();
+ }
+#endif
+
+ QString format_str = dateFormat(format);
+ return toString(date, format_str, cal);
+}
+
+/*!
+ \since 4.5
+ \overload
+*/
QString QLocale::toString(QDate date, FormatType format) const
{
if (!date.isValid())
return QString();
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::DateToStringLong
: QSystemLocale::DateToStringShort,
@@ -1890,7 +2187,7 @@ QString QLocale::toString(QDate date, FormatType format) const
static bool timeFormatContainsAP(QStringView format)
{
- int i = 0;
+ qsizetype i = 0;
while (i < format.size()) {
if (format.at(i).unicode() == '\'') {
qt_readEscapedFormatString(format, &i);
@@ -1905,22 +2202,8 @@ static bool timeFormatContainsAP(QStringView format)
return false;
}
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
- Returns a localized string representation of the given \a time according
- to the specified \a format.
- If \a format is an empty string, an empty string is returned.
-
- \sa QTime::toString()
-*/
-QString QLocale::toString(QTime time, const QString &format) const
-{
- return QCalendar().dateTimeToString(format, QDateTime(), QDate(), time, *this);
-}
-#endif
-
/*!
- \since 5.10
+ \since 4.5
Returns a localized string representation of the given \a time according
to the specified \a format.
@@ -1933,70 +2216,46 @@ QString QLocale::toString(QTime time, QStringView format) const
return QCalendar().dateTimeToString(format, QDateTime(), QDate(), time, *this);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
- \since 4.4
+ \since 5.14
Returns a localized string representation of the given \a dateTime according
- to the specified \a format.
+ to the specified \a format, optionally for a specified calendar \a cal.
If \a format is an empty string, an empty string is returned.
\sa QDateTime::toString(), QDate::toString(), QTime::toString()
*/
-
-QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
+QString QLocale::toString(const QDateTime &dateTime, QStringView format, QCalendar cal) const
{
- return QCalendar().dateTimeToString(format, dateTime, QDate(), QTime(), *this);
+ return cal.dateTimeToString(format, dateTime, QDate(), QTime(), *this);
}
-#endif
/*!
\since 5.10
-
- Returns a localized string representation of the given \a dateTime according
- to the specified \a format.
- If \a format is an empty string, an empty string is returned.
-
- \sa QDateTime::toString(), QDate::toString(), QTime::toString()
+ \overload
*/
QString QLocale::toString(const QDateTime &dateTime, QStringView format) const
{
return QCalendar().dateTimeToString(format, dateTime, QDate(), QTime(), *this);
}
-QString QLocale::toString(QDate date, QStringView format, QCalendar cal) const
-{
- return cal.dateTimeToString(format, QDateTime(), date, QTime(), *this);
-}
-
-QString QLocale::toString(QDate date, QLocale::FormatType format, QCalendar cal) const
-{
- if (!date.isValid())
- return QString();
-
-#ifndef QT_NO_SYSTEMLOCALE
- if (cal.isGregorian() && d->m_data == systemData()) {
- QVariant res = systemLocale()->query(format == LongFormat
- ? QSystemLocale::DateToStringLong
- : QSystemLocale::DateToStringShort,
- date);
- if (!res.isNull())
- return res.toString();
- }
-#endif
+/*!
+ \since 5.14
- QString format_str = dateFormat(format);
- return toString(date, format_str, cal);
-}
+ Returns a localized string representation of the given \a dateTime according
+ to the specified \a format (see dateTimeFormat()), optionally for a
+ specified calendar \a cal.
-QString QLocale::toString(const QDateTime &dateTime, QLocale::FormatType format,
- QCalendar cal) const
+ \note Some locales may use formats that limit the range of years they can
+ represent.
+*/
+QString QLocale::toString(const QDateTime &dateTime, FormatType format, QCalendar cal) const
{
if (!dateTime.isValid())
return QString();
#ifndef QT_NO_SYSTEMLOCALE
- if (cal.isGregorian() && d->m_data == systemData()) {
+ if (cal.isGregorian() && d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::DateTimeToStringLong
: QSystemLocale::DateTimeToStringShort,
@@ -2010,28 +2269,17 @@ QString QLocale::toString(const QDateTime &dateTime, QLocale::FormatType format,
return toString(dateTime, format_str, cal);
}
-QString QLocale::toString(const QDateTime &dateTime, QStringView format, QCalendar cal) const
-{
- return cal.dateTimeToString(format, dateTime, QDate(), QTime(), *this);
-}
-
/*!
\since 4.4
-
- Returns a localized string representation of the given \a dateTime according
- to the specified \a format (see dateTimeFormat()).
-
- \note Some locales may use formats that limit the range of years they can
- represent.
+ \overload
*/
-
QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
{
if (!dateTime.isValid())
return QString();
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::DateTimeToStringLong
: QSystemLocale::DateTimeToStringShort,
@@ -2057,7 +2305,7 @@ QString QLocale::toString(QTime time, FormatType format) const
return QString();
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::TimeToStringLong
: QSystemLocale::TimeToStringShort,
@@ -2086,7 +2334,7 @@ QString QLocale::toString(QTime time, FormatType format) const
QString QLocale::dateFormat(FormatType format) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::DateFormatLong
: QSystemLocale::DateFormatShort,
@@ -2117,7 +2365,7 @@ QString QLocale::dateFormat(FormatType format) const
QString QLocale::timeFormat(FormatType format) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::TimeFormatLong
: QSystemLocale::TimeFormatShort,
@@ -2148,7 +2396,7 @@ QString QLocale::timeFormat(FormatType format) const
QString QLocale::dateTimeFormat(FormatType format) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QVariant res = systemLocale()->query(format == LongFormat
? QSystemLocale::DateTimeFormatLong
: QSystemLocale::DateTimeFormatShort,
@@ -2158,16 +2406,20 @@ QString QLocale::dateTimeFormat(FormatType format) const
}
}
#endif
- return dateFormat(format) + QLatin1Char(' ') + timeFormat(format);
+ return dateFormat(format) + u' ' + timeFormat(format);
}
#if QT_CONFIG(datestring)
/*!
\since 4.4
- Parses the time string given in \a string and returns the
- time. The format of the time string is chosen according to the
- \a format parameter (see timeFormat()).
+ Reads \a string as a time in a locale-specific \a format.
+
+ Parses \a string and returns the time it represents. The format of the time
+ string is chosen according to the \a format parameter (see timeFormat()).
+
+ \note Any am/pm indicators used must match \l amText() or \l pmText(),
+ ignoring case.
If the time could not be parsed, returns an invalid time.
@@ -2178,76 +2430,89 @@ QTime QLocale::toTime(const QString &string, FormatType format) const
return toTime(string, timeFormat(format));
}
-#if QT_DEPRECATED_SINCE(5, 15)
-/*!
- \since 5.14
- \overload
- \deprecated
-*/
-QTime QLocale::toTime(const QString &string, FormatType format, QCalendar cal) const
-{
-QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
- return toTime(string, timeFormat(format), cal);
-QT_WARNING_POP
-}
-#endif
-
/*!
\since 4.4
- Parses the date string given in \a string and returns the
- date. The format of the date string is chosen according to the
- \a format parameter (see dateFormat()).
+ Reads \a string as a date in a locale-specific \a format.
+
+ Parses \a string and returns the date it represents. The format of the date
+ string is chosen according to the \a format parameter (see dateFormat()).
+
+//! [base-year-for-short]
+ Some locales use, particularly for ShortFormat, only the last two digits of
+ the year. In such a case, the 100 years starting at \a baseYear are the
+ candidates first considered. Prior to 6.7 there was no \a baseYear parameter
+ and 1900 was always used. This is the default for \a baseYear, selecting a
+ year from then to 1999. In some cases, other fields may lead to the next or
+ previous century being selected, to get a result consistent with all fields
+ given. See \l QDate::fromString() for details.
+//! [base-year-for-short]
+
+ \note Month and day names, where used, must be given in the locale's
+ language.
If the date could not be parsed, returns an invalid date.
\sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
*/
-QDate QLocale::toDate(const QString &string, FormatType format) const
+QDate QLocale::toDate(const QString &string, FormatType format, int baseYear) const
{
- return toDate(string, dateFormat(format));
+ return toDate(string, dateFormat(format), baseYear);
}
/*!
\since 5.14
\overload
*/
-QDate QLocale::toDate(const QString &string, FormatType format, QCalendar cal) const
+QDate QLocale::toDate(const QString &string, FormatType format, QCalendar cal, int baseYear) const
{
- return toDate(string, dateFormat(format), cal);
+ return toDate(string, dateFormat(format), cal, baseYear);
}
/*!
\since 4.4
- Parses the date/time string given in \a string and returns the
- time. The format of the date/time string is chosen according to the
- \a format parameter (see dateTimeFormat()).
+ Reads \a string as a date-time in a locale-specific \a format.
+
+ Parses \a string and returns the date-time it represents. The format of the
+ date string is chosen according to the \a format parameter (see
+ dateFormat()).
+
+ \include qlocale.cpp base-year-for-short
+
+ \note Month and day names, where used, must be given in the locale's
+ language. Any am/pm indicators used must match \l amText() or \l pmText(),
+ ignoring case.
If the string could not be parsed, returns an invalid QDateTime.
\sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
*/
-QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
+QDateTime QLocale::toDateTime(const QString &string, FormatType format, int baseYear) const
{
- return toDateTime(string, dateTimeFormat(format));
+ return toDateTime(string, dateTimeFormat(format), baseYear);
}
/*!
\since 5.14
\overload
*/
-QDateTime QLocale::toDateTime(const QString &string, FormatType format, QCalendar cal) const
+QDateTime QLocale::toDateTime(const QString &string, FormatType format, QCalendar cal,
+ int baseYear) const
{
- return toDateTime(string, dateTimeFormat(format), cal);
+ return toDateTime(string, dateTimeFormat(format), cal, baseYear);
}
/*!
\since 4.4
- Parses the time string given in \a string and returns the
- time. See QTime::fromString() for information on what is a valid
- format string.
+ Reads \a string as a time in the given \a format.
+
+ Parses \a string and returns the time it represents. See QTime::fromString()
+ for the interpretation of \a format.
+
+ \note Any am/pm indicators used must match \l amText() or \l pmText(),
+ ignoring case.
If the time could not be parsed, returns an invalid time.
@@ -2268,63 +2533,52 @@ QTime QLocale::toTime(const QString &string, const QString &format) const
return time;
}
-#if QT_DEPRECATED_SINCE(5, 15)
-/*!
- \since 5.14
- \overload
- \deprecated
-*/
-QTime QLocale::toTime(const QString &string, const QString &format, QCalendar cal) const
-{
- QTime time;
-#if QT_CONFIG(datetimeparser)
- QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, cal);
- dt.setDefaultLocale(*this);
- if (dt.parseFormat(format))
- dt.fromString(string, nullptr, &time);
-#else
- Q_UNUSED(cal);
- Q_UNUSED(string);
- Q_UNUSED(format);
-#endif
- return time;
-}
-#endif
-
/*!
\since 4.4
- Parses the date string given in \a string and returns the
- date. See QDate::fromString() for information on the expressions
- that can be used with this function.
+ Reads \a string as a date in the given \a format.
- This function searches month names and the names of the days of
- the week in the current locale.
+ Parses \a string and returns the date it represents. See QDate::fromString()
+ for the interpretation of \a format.
+
+//! [base-year-for-two-digit]
+ When \a format only specifies the last two digits of a year, the 100 years
+ starting at \a baseYear are the candidates first considered. Prior to 6.7
+ there was no \a baseYear parameter and 1900 was always used. This is the
+ default for \a baseYear, selecting a year from then to 1999. In some cases,
+ other fields may lead to the next or previous century being selected, to get
+ a result consistent with all fields given. See \l QDate::fromString() for
+ details.
+//! [base-year-for-two-digit]
+
+ \note Month and day names, where used, must be given in the locale's
+ language.
If the date could not be parsed, returns an invalid date.
\sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
*/
-QDate QLocale::toDate(const QString &string, const QString &format) const
+QDate QLocale::toDate(const QString &string, const QString &format, int baseYear) const
{
- return toDate(string, format, QCalendar());
+ return toDate(string, format, QCalendar(), baseYear);
}
/*!
\since 5.14
\overload
*/
-QDate QLocale::toDate(const QString &string, const QString &format, QCalendar cal) const
+QDate QLocale::toDate(const QString &string, const QString &format, QCalendar cal, int baseYear) const
{
QDate date;
#if QT_CONFIG(datetimeparser)
QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
dt.setDefaultLocale(*this);
if (dt.parseFormat(format))
- dt.fromString(string, &date, nullptr);
+ dt.fromString(string, &date, nullptr, baseYear);
#else
Q_UNUSED(string);
Q_UNUSED(format);
+ Q_UNUSED(baseYear);
Q_UNUSED(cal);
#endif
return date;
@@ -2333,38 +2587,51 @@ QDate QLocale::toDate(const QString &string, const QString &format, QCalendar ca
/*!
\since 4.4
- Parses the date/time string given in \a string and returns the
- time. See QDateTime::fromString() for information on the expressions
- that can be used with this function.
+ Reads \a string as a date-time in the given \a format.
- \note The month and day names used must be given in the user's local
- language.
+ Parses \a string and returns the date-time it represents. See
+ QDateTime::fromString() for the interpretation of \a format.
- If the string could not be parsed, returns an invalid QDateTime.
+ \include qlocale.cpp base-year-for-two-digit
+
+ \note Month and day names, where used, must be given in the locale's
+ language. Any am/pm indicators used must match \l amText() or \l pmText(),
+ ignoring case.
+
+ If the string could not be parsed, returns an invalid QDateTime. If the
+ string can be parsed and represents an invalid date-time (e.g. in a gap
+ skipped by a time-zone transition), an invalid QDateTime is returned, whose
+ toMSecsSinceEpoch() represents a near-by date-time that is valid. Passing
+ that to fromMSecsSinceEpoch() will produce a valid date-time that isn't
+ faithfully represented by the string parsed.
\sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
*/
-QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
+QDateTime QLocale::toDateTime(const QString &string, const QString &format, int baseYear) const
{
- return toDateTime(string, format, QCalendar());
+ return toDateTime(string, format, QCalendar(), baseYear);
}
/*!
\since 5.14
\overload
*/
-QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCalendar cal) const
+QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCalendar cal,
+ int baseYear) const
{
#if QT_CONFIG(datetimeparser)
QDateTime datetime;
QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
dt.setDefaultLocale(*this);
- if (dt.parseFormat(format) && dt.fromString(string, &datetime))
+ if (dt.parseFormat(format) && (dt.fromString(string, &datetime, baseYear)
+ || !datetime.isValid())) {
return datetime;
+ }
#else
Q_UNUSED(string);
Q_UNUSED(format);
+ Q_UNUSED(baseYear);
Q_UNUSED(cal);
#endif
return QDateTime();
@@ -2374,7 +2641,14 @@ QDateTime QLocale::toDateTime(const QString &string, const QString &format, QCal
/*!
\since 4.1
- Returns the decimal point character of this locale.
+ Returns the fractional part separator for this locale.
+
+ This is the token that separates the whole number part from the fracional
+ part in the representation of a number which has a fractional part. This is
+ commonly called the "decimal point character" - even though, in many
+ locales, it is not a "point" (or similar dot). It is (since Qt 6.0) returned
+ as a string in case some locale needs more than one UTF-16 code-point to
+ represent its separator.
\sa groupSeparator(), toString()
*/
@@ -2386,7 +2660,14 @@ QString QLocale::decimalPoint() const
/*!
\since 4.1
- Returns the group separator character of this locale.
+ Returns the digit-grouping separator for this locale.
+
+ This is a token used to break up long sequences of digits, in the
+ representation of a number, to make it easier to read. In some locales it
+ may be empty, indicating that digits should not be broken up into groups in
+ this way. In others it may be a spacing character. It is (since Qt 6.0)
+ returned as a string in case some locale needs more than one UTF-16
+ code-point to represent its separator.
\sa decimalPoint(), toString()
*/
@@ -2398,7 +2679,12 @@ QString QLocale::groupSeparator() const
/*!
\since 4.1
- Returns the percent character of this locale.
+ Returns the percent marker of this locale.
+
+ This is a token presumed to be appended to a number to indicate a
+ percentage. It is (since Qt 6.0) returned as a string because, in some
+ locales, it is not a single character - for example, because it includes a
+ text-direction-control character.
\sa toString()
*/
@@ -2412,6 +2698,13 @@ QString QLocale::percent() const
Returns the zero digit character of this locale.
+ This is a single Unicode character but may be encoded as a surrogate pair,
+ so is (since Qt 6.0) returned as a string. In most locales, other digits
+ follow it in Unicode ordering - however, some number systems, notably those
+ using U+3007 as zero, do not have contiguous digits. Use toString() to
+ obtain suitable representations of numbers, rather than trying to construct
+ them from this zero digit.
+
\sa toString()
*/
QString QLocale::zeroDigit() const
@@ -2422,7 +2715,12 @@ QString QLocale::zeroDigit() const
/*!
\since 4.1
- Returns the negative sign character of this locale.
+ Returns the negative sign indicator of this locale.
+
+ This is a token presumed to be used as a prefix to a number to indicate that
+ it is negative. It is (since Qt 6.0) returned as a string because, in some
+ locales, it is not a single character - for example, because it includes a
+ text-direction-control character.
\sa positiveSign(), toString()
*/
@@ -2434,7 +2732,12 @@ QString QLocale::negativeSign() const
/*!
\since 4.5
- Returns the positive sign character of this locale.
+ Returns the positive sign indicator of this locale.
+
+ This is a token presumed to be used as a prefix to a number to indicate that
+ it is positive. It is (since Qt 6.0) returned as a string because, in some
+ locales, it is not a single character - for example, because it includes a
+ text-direction-control character.
\sa negativeSign(), toString()
*/
@@ -2446,8 +2749,13 @@ QString QLocale::positiveSign() const
/*!
\since 4.1
- Returns the exponential character of this locale, used to separate exponent
- from mantissa in some floating-point numeric representations.
+ Returns the exponent separator for this locale.
+
+ This is a token used to separate mantissa from exponent in some
+ floating-point numeric representations. It is (since Qt 6.0) returned as a
+ string because, in some locales, it is not a single character - for example,
+ it may consist of a multiplication sign and a representation of the "ten to
+ the power" operator.
\sa toString(double, char, int)
*/
@@ -2456,57 +2764,66 @@ QString QLocale::exponential() const
return d->m_data->exponentSeparator();
}
-static bool qIsUpper(char c)
-{
- return c >= 'A' && c <= 'Z';
-}
-
-static char qToLower(char c)
-{
- if (c >= 'A' && c <= 'Z')
- return c - 'A' + 'a';
- else
- return c;
-}
-
/*!
\overload
-
- \a f and \a prec have the same meaning as in QString::number(double, char, int).
-
- \sa toDouble(), numberOptions(), exponential(), decimalPoint(), zeroDigit(), positiveSign(), percent()
+ Returns a string representing the floating-point number \a f.
+
+ The form of the representation is controlled by the \a format and \a
+ precision parameters.
+
+ The \a format defaults to \c{'g'}. It can be any of the following:
+
+ \table
+ \header \li Format \li Meaning \li Meaning of \a precision
+ \row \li \c 'e' \li format as [-]9.9e[+|-]999 \li number of digits \e after the decimal point
+ \row \li \c 'E' \li format as [-]9.9E[+|-]999 \li "
+ \row \li \c 'f' \li format as [-]9.9 \li "
+ \row \li \c 'F' \li same as \c 'f' except for INF and NAN (see below) \li "
+ \row \li \c 'g' \li use \c 'e' or \c 'f' format, whichever is more concise \li maximum number of significant digits (trailing zeroes are omitted)
+ \row \li \c 'G' \li use \c 'E' or \c 'F' format, whichever is more concise \li "
+ \endtable
+
+ The special \a precision value QLocale::FloatingPointShortest selects the
+ shortest representation that, when read as a number, gets back the original floating-point
+ value. Aside from that, any negative \a precision is ignored in favor of the
+ default, 6.
+
+ For the \c 'e', \c 'f' and \c 'g' formats, positive infinity is represented
+ as "inf", negative infinity as "-inf" and floating-point NaN (not-a-number)
+ values are represented as "nan". For the \c 'E', \c 'F' and \c 'G' formats,
+ "INF" and "NAN" are used instead. This does not vary with locale.
+
+ \sa toDouble(), numberOptions(), exponential(), decimalPoint(), zeroDigit(),
+ positiveSign(), percent(), toCurrencyString(), formattedDataSize(),
+ QLocale::FloatingPointPrecisionOption
*/
-QString QLocale::toString(double i, char f, int prec) const
+QString QLocale::toString(double f, char format, int precision) const
{
QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
- uint flags = 0;
+ uint flags = isAsciiUpper(format) ? QLocaleData::CapitalEorX : 0;
- if (qIsUpper(f))
- flags = QLocaleData::CapitalEorX;
- f = qToLower(f);
-
- switch (f) {
- case 'f':
- form = QLocaleData::DFDecimal;
- break;
- case 'e':
- form = QLocaleData::DFExponent;
- break;
- case 'g':
- form = QLocaleData::DFSignificantDigits;
- break;
- default:
- break;
+ switch (QtMiscUtils::toAsciiLower(format)) {
+ case 'f':
+ form = QLocaleData::DFDecimal;
+ break;
+ case 'e':
+ form = QLocaleData::DFExponent;
+ break;
+ case 'g':
+ form = QLocaleData::DFSignificantDigits;
+ break;
+ default:
+ break;
}
if (!(d->m_numberOptions & OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
+ flags |= QLocaleData::GroupDigits;
if (!(d->m_numberOptions & OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
if (d->m_numberOptions & IncludeTrailingZeroesAfterDot)
flags |= QLocaleData::AddTrailingZeroes;
- return d->m_data->doubleToString(i, prec, form, -1, flags);
+ return d->m_data->doubleToString(f, precision, form, -1, flags);
}
/*!
@@ -2531,66 +2848,87 @@ QString QLocale::toString(double i, char f, int prec) const
/*!
Returns a QLocale object initialized to the system locale.
- On Windows and Mac, this locale will use the decimal/grouping characters and
- date/time formats specified in the system configuration panel.
+ The system locale may use system-specific sources for locale data, where
+ available, otherwise falling back on QLocale's built-in database entry for
+ the language, script and territory the system reports.
+
+ For example, on Windows and Mac, this locale will use the decimal/grouping
+ characters and date/time formats specified in the system configuration
+ panel.
\sa c()
*/
QLocale QLocale::system()
{
- QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary
- if (systemLocalePrivate.isDestroyed())
- return QLocale(QLocale::C);
- return QLocale(*systemLocalePrivate->data());
-}
+ constexpr auto sysData = []() {
+ // Same return as systemData(), but leave the setup to the actual call to it.
+#ifdef QT_NO_SYSTEMLOCALE
+ return locale_data;
+#else
+ return &systemLocaleData;
+#endif
+ };
+ Q_CONSTINIT static QLocalePrivate locale(sysData(), -1, DefaultNumberOptions, 1);
+ // Calling systemData() ensures system data is up to date; we also need it
+ // to ensure that locale's index stays up to date:
+ systemData(&locale.m_index);
+ Q_ASSERT(locale.m_index >= 0 && locale.m_index < locale_data_size);
+ return QLocale(locale);
+}
/*!
- \since 4.8
-
Returns a list of valid locale objects that match the given \a language, \a
- script and \a country.
+ script and \a territory.
Getting a list of all locales:
QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript,
- QLocale::AnyCountry);
+ QLocale::AnyTerritory);
Getting a list of locales suitable for Russia:
QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript,
QLocale::Russia);
*/
-QList<QLocale> QLocale::matchingLocales(QLocale::Language language,
- QLocale::Script script,
- QLocale::Country country)
+QList<QLocale> QLocale::matchingLocales(Language language, Script script, Territory territory)
{
- if (uint(language) > QLocale::LastLanguage || uint(script) > QLocale::LastScript ||
- uint(country) > QLocale::LastCountry)
+ const QLocaleId filter { language, script, territory };
+ if (!filter.isValid())
return QList<QLocale>();
- if (language == QLocale::C)
- return QList<QLocale>() << QLocale(QLocale::C);
+ if (language == C)
+ return QList<QLocale>{QLocale(C)};
QList<QLocale> result;
- if (language == QLocale::AnyLanguage && script == QLocale::AnyScript
- && country == QLocale::AnyCountry) {
+ if (filter.matchesAll())
result.reserve(locale_data_size);
- }
- const QLocaleData *data = locale_data + locale_index[language];
- while ( (data != locale_data + locale_data_size)
- && (language == QLocale::AnyLanguage || data->m_language_id == uint(language))) {
- if ((script == QLocale::AnyScript || data->m_script_id == uint(script))
- && (country == QLocale::AnyCountry || data->m_country_id == uint(country))) {
- result.append(QLocale(*(data->m_language_id == C ? c_private()
- : QLocalePrivate::create(data))));
+
+ quint16 index = locale_index[language];
+ // There may be no matches, for some languages (e.g. Abkhazian at CLDR v39).
+ while (filter.acceptLanguage(locale_data[index].m_language_id)) {
+ const QLocaleId id = locale_data[index].id();
+ if (filter.acceptScriptTerritory(id)) {
+ result.append(QLocale(*(id.language_id == C ? c_private()
+ : new QLocalePrivate(locale_data + index, index))));
}
- ++data;
+ ++index;
}
+
+ // Add current system locale, if it matches
+ const auto syslocaledata = systemData();
+
+ if (filter.acceptLanguage(syslocaledata->m_language_id)) {
+ const QLocaleId id = syslocaledata->id();
+ if (filter.acceptScriptTerritory(id))
+ result.append(system());
+ }
+
return result;
}
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
- \obsolete
+ \deprecated [6.6] Use \l matchingLocales() instead and consult the \l territory() of each.
\since 4.3
Returns the list of countries that have entries for \a language in Qt's locale
@@ -2601,23 +2939,14 @@ QList<QLocale> QLocale::matchingLocales(QLocale::Language language,
*/
QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
{
+ const auto locales = matchingLocales(language, AnyScript, AnyCountry);
QList<Country> result;
- if (language == C) {
- result << AnyCountry;
- return result;
- }
-
- unsigned language_id = language;
- const QLocaleData *data = locale_data + locale_index[language_id];
- while (data->m_language_id == language_id) {
- const QLocale::Country country = static_cast<Country>(data->m_country_id);
- if (!result.contains(country))
- result.append(country);
- ++data;
- }
-
+ result.reserve(locales.size());
+ for (const auto &locale : locales)
+ result.append(locale.territory());
return result;
}
+#endif
/*!
\since 4.2
@@ -2689,6 +3018,14 @@ QString QLocale::standaloneDayName(int day, FormatType type) const
// Calendar look-up of month and day names:
+// Only used in assertions
+[[maybe_unused]] static bool sameLocale(const QLocaleData *locale, const QCalendarLocale &calendar)
+{
+ return locale->m_language_id == calendar.m_language_id
+ && locale->m_script_id == calendar.m_script_id
+ && locale->m_territory_id == calendar.m_territory_id;
+}
+
/*!
\internal
*/
@@ -2797,20 +3134,30 @@ QString QCalendarBackend::monthName(const QLocale &locale, int month, int,
QLocale::FormatType format) const
{
Q_ASSERT(month >= 1 && month <= maximumMonthsInYear());
- return rawMonthName(localeMonthIndexData()[locale.d->m_data_offset],
- localeMonthData(), month, format);
+ const QCalendarLocale &monthly = localeMonthIndexData()[locale.d->m_index];
+ Q_ASSERT(sameLocale(locale.d->m_data, monthly));
+ return rawMonthName(monthly, localeMonthData(), month, format);
}
-QString QGregorianCalendar::monthName(const QLocale &locale, int month, int year,
- QLocale::FormatType format) const
+QString QRomanCalendar::monthName(const QLocale &locale, int month, int year,
+ QLocale::FormatType format) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (locale.d->m_data == systemData()) {
+ if (locale.d->m_data == &systemLocaleData) {
Q_ASSERT(month >= 1 && month <= 12);
- QVariant res = systemLocale()->query(format == QLocale::LongFormat
- ? QSystemLocale::MonthNameLong
- : QSystemLocale::MonthNameShort,
- month);
+ QSystemLocale::QueryType queryType = QSystemLocale::MonthNameLong;
+ switch (format) {
+ case QLocale::LongFormat:
+ queryType = QSystemLocale::MonthNameLong;
+ break;
+ case QLocale::ShortFormat:
+ queryType = QSystemLocale::MonthNameShort;
+ break;
+ case QLocale::NarrowFormat:
+ queryType = QSystemLocale::MonthNameNarrow;
+ break;
+ }
+ QVariant res = systemLocale()->query(queryType, month);
if (!res.isNull())
return res.toString();
}
@@ -2823,20 +3170,30 @@ QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month,
QLocale::FormatType format) const
{
Q_ASSERT(month >= 1 && month <= maximumMonthsInYear());
- return rawStandaloneMonthName(localeMonthIndexData()[locale.d->m_data_offset],
- localeMonthData(), month, format);
+ const QCalendarLocale &monthly = localeMonthIndexData()[locale.d->m_index];
+ Q_ASSERT(sameLocale(locale.d->m_data, monthly));
+ return rawStandaloneMonthName(monthly, localeMonthData(), month, format);
}
-QString QGregorianCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
- QLocale::FormatType format) const
+QString QRomanCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
+ QLocale::FormatType format) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (locale.d->m_data == systemData()) {
+ if (locale.d->m_data == &systemLocaleData) {
Q_ASSERT(month >= 1 && month <= 12);
- QVariant res = systemLocale()->query(format == QLocale::LongFormat
- ? QSystemLocale::StandaloneMonthNameLong
- : QSystemLocale::StandaloneMonthNameShort,
- month);
+ QSystemLocale::QueryType queryType = QSystemLocale::StandaloneMonthNameLong;
+ switch (format) {
+ case QLocale::LongFormat:
+ queryType = QSystemLocale::StandaloneMonthNameLong;
+ break;
+ case QLocale::ShortFormat:
+ queryType = QSystemLocale::StandaloneMonthNameShort;
+ break;
+ case QLocale::NarrowFormat:
+ queryType = QSystemLocale::StandaloneMonthNameNarrow;
+ break;
+ }
+ QVariant res = systemLocale()->query(queryType, month);
if (!res.isNull())
return res.toString();
}
@@ -2854,11 +3211,20 @@ QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
return QString();
#ifndef QT_NO_SYSTEMLOCALE
- if (locale.d->m_data == systemData()) {
- QVariant res = systemLocale()->query(format == QLocale::LongFormat
- ? QSystemLocale::DayNameLong
- : QSystemLocale::DayNameShort,
- day);
+ if (locale.d->m_data == &systemLocaleData) {
+ QSystemLocale::QueryType queryType = QSystemLocale::DayNameLong;
+ switch (format) {
+ case QLocale::LongFormat:
+ queryType = QSystemLocale::DayNameLong;
+ break;
+ case QLocale::ShortFormat:
+ queryType = QSystemLocale::DayNameShort;
+ break;
+ case QLocale::NarrowFormat:
+ queryType = QSystemLocale::DayNameNarrow;
+ break;
+ }
+ QVariant res = systemLocale()->query(queryType, day);
if (!res.isNull())
return res.toString();
}
@@ -2874,11 +3240,20 @@ QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
return QString();
#ifndef QT_NO_SYSTEMLOCALE
- if (locale.d->m_data == systemData()) {
- QVariant res = systemLocale()->query(format == QLocale::LongFormat
- ? QSystemLocale::DayNameLong
- : QSystemLocale::DayNameShort,
- day);
+ if (locale.d->m_data == &systemLocaleData) {
+ QSystemLocale::QueryType queryType = QSystemLocale::StandaloneDayNameLong;
+ switch (format) {
+ case QLocale::LongFormat:
+ queryType = QSystemLocale::StandaloneDayNameLong;
+ break;
+ case QLocale::ShortFormat:
+ queryType = QSystemLocale::StandaloneDayNameShort;
+ break;
+ case QLocale::NarrowFormat:
+ queryType = QSystemLocale::StandaloneDayNameNarrow;
+ break;
+ }
+ QVariant res = systemLocale()->query(queryType, day);
if (!res.isNull())
return res.toString();
}
@@ -2897,8 +3272,8 @@ QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
Qt::DayOfWeek QLocale::firstDayOfWeek() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::FirstDayOfWeek, QVariant());
+ if (d->m_data == &systemLocaleData) {
+ const auto res = systemLocale()->query(QSystemLocale::FirstDayOfWeek);
if (!res.isNull())
return static_cast<Qt::DayOfWeek>(res.toUInt());
}
@@ -2908,10 +3283,10 @@ Qt::DayOfWeek QLocale::firstDayOfWeek() const
QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
{
- for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) {
- if (ImperialMeasurementSystems[i].languageId == m_data->m_language_id
- && ImperialMeasurementSystems[i].countryId == m_data->m_country_id) {
- return ImperialMeasurementSystems[i].system;
+ for (const auto &system : ImperialMeasurementSystems) {
+ if (system.languageId == m_data->m_language_id
+ && system.territoryId == m_data->m_territory_id) {
+ return system.system;
}
}
return QLocale::MetricSystem;
@@ -2925,10 +3300,11 @@ QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
QList<Qt::DayOfWeek> QLocale::weekdays() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant());
- if (!res.isNull())
- return static_cast<QList<Qt::DayOfWeek> >(qvariant_cast<QList<Qt::DayOfWeek> >(res));
+ if (d->m_data == &systemLocaleData) {
+ auto res
+ = qvariant_cast<QList<Qt::DayOfWeek> >(systemLocale()->query(QSystemLocale::Weekdays));
+ if (!res.isEmpty())
+ return res;
}
#endif
QList<Qt::DayOfWeek> weekdays;
@@ -2950,8 +3326,8 @@ QList<Qt::DayOfWeek> QLocale::weekdays() const
QLocale::MeasurementSystem QLocale::measurementSystem() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant());
+ if (d->m_data == &systemLocaleData) {
+ const auto res = systemLocale()->query(QSystemLocale::MeasurementSystem);
if (!res.isNull())
return MeasurementSystem(res.toInt());
}
@@ -2968,34 +3344,34 @@ QLocale::MeasurementSystem QLocale::measurementSystem() const
Qt::LayoutDirection QLocale::textDirection() const
{
switch (script()) {
- case QLocale::AdlamScript:
- case QLocale::ArabicScript:
- case QLocale::AvestanScript:
- case QLocale::CypriotScript:
- case QLocale::HatranScript:
- case QLocale::HebrewScript:
- case QLocale::ImperialAramaicScript:
- case QLocale::InscriptionalPahlaviScript:
- case QLocale::InscriptionalParthianScript:
- case QLocale::KharoshthiScript:
- case QLocale::LydianScript:
- case QLocale::MandaeanScript:
- case QLocale::ManichaeanScript:
- case QLocale::MendeKikakuiScript:
- case QLocale::MeroiticCursiveScript:
- case QLocale::MeroiticScript:
- case QLocale::NabataeanScript:
- case QLocale::NkoScript:
- case QLocale::OldHungarianScript:
- case QLocale::OldNorthArabianScript:
- case QLocale::OldSouthArabianScript:
- case QLocale::OrkhonScript:
- case QLocale::PalmyreneScript:
- case QLocale::PhoenicianScript:
- case QLocale::PsalterPahlaviScript:
- case QLocale::SamaritanScript:
- case QLocale::SyriacScript:
- case QLocale::ThaanaScript:
+ case AdlamScript:
+ case ArabicScript:
+ case AvestanScript:
+ case CypriotScript:
+ case HatranScript:
+ case HebrewScript:
+ case ImperialAramaicScript:
+ case InscriptionalPahlaviScript:
+ case InscriptionalParthianScript:
+ case KharoshthiScript:
+ case LydianScript:
+ case MandaeanScript:
+ case ManichaeanScript:
+ case MendeKikakuiScript:
+ case MeroiticCursiveScript:
+ case MeroiticScript:
+ case NabataeanScript:
+ case NkoScript:
+ case OldHungarianScript:
+ case OldNorthArabianScript:
+ case OldSouthArabianScript:
+ case OrkhonScript:
+ case PalmyreneScript:
+ case PhoenicianScript:
+ case PsalterPahlaviScript:
+ case SamaritanScript:
+ case SyriacScript:
+ case ThaanaScript:
return Qt::RightToLeft;
default:
break;
@@ -3063,10 +3439,10 @@ QString QLocale::toLower(const QString &str) const
QString QLocale::amText() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant());
- if (!res.isNull())
- return res.toString();
+ if (d->m_data == &systemLocaleData) {
+ auto res = systemLocale()->query(QSystemLocale::AMText).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
return d->m_data->anteMeridiem().getData(am_data);
@@ -3083,10 +3459,10 @@ QString QLocale::amText() const
QString QLocale::pmText() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant());
- if (!res.isNull())
- return res.toString();
+ if (d->m_data == &systemLocaleData) {
+ auto res = systemLocale()->query(QSystemLocale::PMText).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
return d->m_data->postMeridiem().getData(pm_data);
@@ -3128,7 +3504,19 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
day = parts.day;
}
- int i = 0;
+ auto appendToResult = [&](int t, int repeat) {
+ auto data = locale.d->m_data;
+ if (repeat > 1)
+ result.append(data->longLongToString(t, -1, 10, repeat, QLocaleData::ZeroPadded));
+ else
+ result.append(data->longLongToString(t));
+ };
+
+ auto formatType = [](int repeat) {
+ return repeat == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
+ };
+
+ qsizetype i = 0;
while (i < format.size()) {
if (format.at(i).unicode() == '\'') {
result.append(qt_readEscapedFormatString(format, &i));
@@ -3136,7 +3524,9 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
}
const QChar c = format.at(i);
- int repeat = qt_repeatCount(format.mid(i));
+ qsizetype rep = qt_repeatCount(format.mid(i));
+ Q_ASSERT(rep < std::numeric_limits<int>::max());
+ int repeat = int(rep);
bool used = false;
if (formatDate) {
switch (c.unicode()) {
@@ -3148,15 +3538,11 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
repeat = 2;
switch (repeat) {
- case 4: {
- const int len = (year < 0) ? 5 : 4;
- result.append(locale.d->m_data->longLongToString(year, -1, 10, len,
- QLocaleData::ZeroPadded));
+ case 4:
+ appendToResult(year, (year < 0) ? 5 : 4);
break;
- }
case 2:
- result.append(locale.d->m_data->longLongToString(year % 100, -1, 10, 2,
- QLocaleData::ZeroPadded));
+ appendToResult(year % 100, 2);
break;
default:
repeat = 1;
@@ -3168,43 +3554,20 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
case 'M':
used = true;
repeat = qMin(repeat, 4);
- switch (repeat) {
- case 1:
- result.append(locale.d->m_data->longLongToString(month));
- break;
- case 2:
- result.append(locale.d->m_data->longLongToString(month, -1, 10, 2,
- QLocaleData::ZeroPadded));
- break;
- case 3:
- result.append(monthName(locale, month, year, QLocale::ShortFormat));
- break;
- case 4:
- result.append(monthName(locale, month, year, QLocale::LongFormat));
- break;
- }
+ if (repeat <= 2)
+ appendToResult(month, repeat);
+ else
+ result.append(monthName(locale, month, year, formatType(repeat)));
break;
case 'd':
used = true;
repeat = qMin(repeat, 4);
- switch (repeat) {
- case 1:
- result.append(locale.d->m_data->longLongToString(day));
- break;
- case 2:
- result.append(locale.d->m_data->longLongToString(day, -1, 10, 2,
- QLocaleData::ZeroPadded));
- break;
- case 3:
- result.append(locale.dayName(
- dayOfWeek(date.toJulianDay()), QLocale::ShortFormat));
- break;
- case 4:
- result.append(locale.dayName(
- dayOfWeek(date.toJulianDay()), QLocale::LongFormat));
- break;
- }
+ if (repeat <= 2)
+ appendToResult(day, repeat);
+ else
+ result.append(
+ locale.dayName(dayOfWeek(date.toJulianDay()), formatType(repeat)));
break;
default:
@@ -3223,83 +3586,51 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
else if (hour == 0)
hour = 12;
}
-
- switch (repeat) {
- case 1:
- result.append(locale.d->m_data->longLongToString(hour));
- break;
- case 2:
- result.append(locale.d->m_data->longLongToString(hour, -1, 10, 2,
- QLocaleData::ZeroPadded));
- break;
- }
+ appendToResult(hour, repeat);
break;
}
case 'H':
used = true;
repeat = qMin(repeat, 2);
- switch (repeat) {
- case 1:
- result.append(locale.d->m_data->longLongToString(time.hour()));
- break;
- case 2:
- result.append(locale.d->m_data->longLongToString(time.hour(), -1, 10, 2,
- QLocaleData::ZeroPadded));
- break;
- }
+ appendToResult(time.hour(), repeat);
break;
case 'm':
used = true;
repeat = qMin(repeat, 2);
- switch (repeat) {
- case 1:
- result.append(locale.d->m_data->longLongToString(time.minute()));
- break;
- case 2:
- result.append(locale.d->m_data->longLongToString(time.minute(), -1, 10, 2,
- QLocaleData::ZeroPadded));
- break;
- }
+ appendToResult(time.minute(), repeat);
break;
case 's':
used = true;
repeat = qMin(repeat, 2);
- switch (repeat) {
- case 1:
- result.append(locale.d->m_data->longLongToString(time.second()));
- break;
- case 2:
- result.append(locale.d->m_data->longLongToString(time.second(), -1, 10, 2,
- QLocaleData::ZeroPadded));
- break;
- }
- break;
-
- case 'a':
- used = true;
- repeat = format.mid(i + 1).startsWith(QLatin1Char('p')) ? 2 : 1;
- result.append(time.hour() < 12 ? locale.amText().toLower()
- : locale.pmText().toLower());
+ appendToResult(time.second(), repeat);
break;
case 'A':
+ case 'a': {
+ QString text = time.hour() < 12 ? locale.amText() : locale.pmText();
used = true;
- repeat = format.mid(i + 1).startsWith(QLatin1Char('P')) ? 2 : 1;
- result.append(time.hour() < 12 ? locale.amText().toUpper()
- : locale.pmText().toUpper());
+ repeat = 1;
+ if (format.mid(i + 1).startsWith(u'p', Qt::CaseInsensitive))
+ ++repeat;
+ if (c.unicode() == 'A' && (repeat == 1 || format.at(i + 1).unicode() == 'P'))
+ text = std::move(text).toUpper();
+ else if (c.unicode() == 'a' && (repeat == 1 || format.at(i + 1).unicode() == 'p'))
+ text = std::move(text).toLower();
+ // else 'Ap' or 'aP' => use CLDR text verbatim, preserving case
+ result.append(text);
break;
+ }
case 'z':
used = true;
- repeat = (repeat >= 3) ? 3 : 1;
+ repeat = qMin(repeat, 3);
// note: the millisecond component is treated like the decimal part of the seconds
// so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200"
- result.append(locale.d->m_data->longLongToString(time.msec(), -1, 10, 3,
- QLocaleData::ZeroPadded));
- if (repeat == 1) {
+ appendToResult(time.msec(), 3);
+ if (repeat != 3) {
if (result.endsWith(locale.zeroDigit()))
result.chop(1);
if (result.endsWith(locale.zeroDigit()))
@@ -3307,20 +3638,63 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
}
break;
- case 't':
+ case 't': {
+ enum AbbrType { Long, Offset, Short };
+ const auto tzAbbr = [locale](const QDateTime &when, AbbrType type) {
+#if QT_CONFIG(timezone)
+ if (type != Short || locale != QLocale::system()) {
+ QTimeZone::NameType mode =
+ type == Short ? QTimeZone::ShortName
+ : type == Long ? QTimeZone::LongName : QTimeZone::OffsetName;
+ return when.timeRepresentation().displayName(when, mode, locale);
+ } // else: prefer QDateTime's abbreviation, for backwards-compatibility.
+#endif // else, make do with non-localized abbreviation:
+ if (type != Offset)
+ return when.timeZoneAbbreviation();
+ // For Offset, we can coerce to a UTC-based zone's abbreviation:
+ return when.toOffsetFromUtc(when.offsetFromUtc()).timeZoneAbbreviation();
+ };
used = true;
- repeat = 1;
- // If we have a QDateTime use the time spec otherwise use the current system tzname
- result.append(formatDate ? datetime.timeZoneAbbreviation()
- : QDateTime::currentDateTime().timeZoneAbbreviation());
+ repeat = qMin(repeat, 4);
+ // If we don't have a date-time, use the current system time:
+ const QDateTime when = formatDate ? datetime : QDateTime::currentDateTime();
+ QString text;
+ switch (repeat) {
+ case 4:
+ text = tzAbbr(when, Long);
+ break;
+ case 3: // ±hh:mm
+ case 2: // ±hhmm (we'll remove the ':' at the end)
+ text = tzAbbr(when, Offset);
+ Q_ASSERT(text.startsWith("UTC"_L1)); // Need to strip this.
+ // The Qt::UTC case omits the zero offset:
+ text = (text.size() == 3
+ ? u"+00:00"_s
+ : (text.size() <= 6
+ // Whole-hour offsets may lack the zero minutes:
+ ? QStringView{text}.sliced(3) + ":00"_L1
+ : std::move(text).sliced(3)));
+ if (repeat == 2)
+ text = text.remove(u':');
+ break;
+ default:
+ text = tzAbbr(when, Short);
+ // UTC-offset zones only include minutes if non-zero.
+ if (text.startsWith("UTC"_L1) && text.size() == 6)
+ text += ":00"_L1;
+ break;
+ }
+ if (!text.isEmpty())
+ result.append(text);
break;
+ }
default:
break;
}
}
if (!used)
- result.append(QString(repeat, c));
+ result.resize(result.size() + repeat, c);
i += repeat;
}
@@ -3332,53 +3706,50 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &
QString QLocaleData::doubleToString(double d, int precision, DoubleForm form,
int width, unsigned flags) const
{
- return doubleToString(zeroDigit(), positiveSign(), negativeSign(),
- exponentSeparator(), groupSeparator(), decimalPoint(),
- d, precision, form, width, flags);
-}
-
-QString QLocaleData::doubleToString(const QString &zero, const QString &plus, const QString &minus,
- const QString &exponential,
- const QString &group, const QString &decimal,
- double d, int precision, DoubleForm form, int width,
- unsigned flags)
-{
+ // Although the special handling of F.P.Shortest below is limited to
+ // DFSignificantDigits, the double-conversion library does treat it
+ // specially for the other forms, shedding trailing zeros for DFDecimal and
+ // using the shortest mantissa that faithfully represents the value for
+ // DFExponent.
if (precision != QLocale::FloatingPointShortest && precision < 0)
precision = 6;
if (width < 0)
width = 0;
- bool negative = false;
- QString num_str;
-
int decpt;
- int bufSize = 1;
+ qsizetype bufSize = 1;
if (precision == QLocale::FloatingPointShortest)
- bufSize += DoubleMaxSignificant;
- else if (form == DFDecimal) // optimize for numbers between -512k and 512k
- bufSize += ((d > (1 << 19) || d < -(1 << 19)) ? DoubleMaxDigitsBeforeDecimal : 6) +
- precision;
- else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit.
- bufSize += qMax(2, precision) + 1;
+ bufSize += std::numeric_limits<double>::max_digits10;
+ else if (form == DFDecimal && qt_is_finite(d))
+ bufSize += wholePartSpace(qAbs(d)) + precision;
+ else // Add extra digit due to different interpretations of precision.
+ bufSize += qMax(2, precision) + 1; // Must also be big enough for "nan" or "inf"
QVarLengthArray<char> buf(bufSize);
int length;
-
+ bool negative = false;
qt_doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt);
- if (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0) {
- num_str = QString::fromLatin1(buf.data(), length);
- } else { // Handle normal numbers
+ const QString prefix = signPrefix(negative && !isZero(d), flags);
+ QString numStr;
+
+ if (length == 3
+ && (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0)) {
+ numStr = QString::fromLatin1(buf.data(), length);
+ } else { // Handle finite values
+ const QString zero = zeroDigit();
QString digits = QString::fromLatin1(buf.data(), length);
if (zero == u"0") {
// No need to convert digits.
+ Q_ASSERT(std::all_of(buf.cbegin(), buf.cbegin() + length, isAsciiDigit));
+ // That check is taken care of in unicodeForDigits, below.
} else if (zero.size() == 2 && zero.at(0).isHighSurrogate()) {
- const uint zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
+ const char32_t zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
QString converted;
converted.reserve(2 * digits.size());
- for (int i = 0; i < digits.length(); ++i) {
- const uint digit = zeroUcs4 - '0' + digits.at(i).unicode();
+ for (QChar ch : std::as_const(digits)) {
+ const char32_t digit = unicodeForDigit(ch.unicode() - '0', zeroUcs4);
Q_ASSERT(QChar::requiresSurrogates(digit));
converted.append(QChar::highSurrogate(digit));
converted.append(QChar::lowSurrogate(digit));
@@ -3387,329 +3758,527 @@ QString QLocaleData::doubleToString(const QString &zero, const QString &plus, co
} else {
Q_ASSERT(zero.size() == 1);
Q_ASSERT(!zero.at(0).isSurrogate());
- ushort z = zero.at(0).unicode() - '0';
- for (int i = 0; i < digits.length(); ++i)
- reinterpret_cast<ushort *>(digits.data())[i] += z;
+ char16_t z = zero.at(0).unicode();
+ char16_t *const value = reinterpret_cast<char16_t *>(digits.data());
+ for (qsizetype i = 0; i < digits.size(); ++i)
+ value[i] = unicodeForDigit(value[i] - '0', z);
}
- bool always_show_decpt = (flags & ForcePoint);
+ const bool mustMarkDecimal = flags & ForcePoint;
+ const bool groupDigits = flags & GroupDigits;
+ const int minExponentDigits = flags & ZeroPadExponent ? 2 : 1;
switch (form) {
- case DFExponent: {
- num_str = exponentForm(zero, decimal, exponential, group, plus, minus,
- digits, decpt, precision, PMDecimalDigits,
- always_show_decpt, flags & ZeroPadExponent);
- break;
- }
- case DFDecimal: {
- num_str = decimalForm(zero, decimal, group,
- digits, decpt, precision, PMDecimalDigits,
- always_show_decpt, flags & ThousandsGroup);
- break;
- }
- case DFSignificantDigits: {
- PrecisionMode mode = (flags & AddTrailingZeroes) ?
- PMSignificantDigits : PMChopTrailingZeros;
-
- const auto digitWidth = zero.size();
- int cutoff = precision < 0 ? 6 : precision;
- // Find out which representation is shorter
- if (precision == QLocale::FloatingPointShortest && decpt > 0) {
- cutoff = digits.length() / digitWidth + 4; // 'e', '+'/'-', one digit exponent
- if (decpt <= 10)
- ++cutoff;
- else
- cutoff += decpt > 100 ? 2 : 1;
- if (!always_show_decpt && digits.length() / digitWidth > decpt)
- ++cutoff; // decpt shown in exponent form, but not in decimal form
+ case DFExponent:
+ numStr = exponentForm(std::move(digits), decpt, precision, PMDecimalDigits,
+ mustMarkDecimal, minExponentDigits);
+ break;
+ case DFDecimal:
+ numStr = decimalForm(std::move(digits), decpt, precision, PMDecimalDigits,
+ mustMarkDecimal, groupDigits);
+ break;
+ case DFSignificantDigits: {
+ PrecisionMode mode
+ = (flags & AddTrailingZeroes) ? PMSignificantDigits : PMChopTrailingZeros;
+
+ /* POSIX specifies sprintf() to follow fprintf(), whose 'g/G' format
+ says; with P = 6 if precision unspecified else 1 if precision is
+ 0 else precision; when 'e/E' would have exponent X, use:
+ * 'f/F' if P > X >= -4, with precision P-1-X
+ * 'e/E' otherwise, with precision P-1
+ Helpfully, we already have mapped precision < 0 to 6 - except for
+ F.P.Shortest mode, which is its own story - and those of our
+ callers with unspecified precision either used 6 or -1 for it.
+ */
+ bool useDecimal;
+ if (precision == QLocale::FloatingPointShortest) {
+ // Find out which representation is shorter.
+ // Set bias to everything added to exponent form but not
+ // decimal, minus the converse.
+
+ // Exponent adds separator, sign and digits:
+ int bias = 2 + minExponentDigits;
+ // Decimal form may get grouping separators inserted:
+ if (groupDigits && decpt >= m_grouping_top + m_grouping_least)
+ bias -= (decpt - m_grouping_least) / m_grouping_higher + 1;
+ // X = decpt - 1 needs two digits if decpt > 10:
+ if (decpt > 10 && minExponentDigits == 1)
+ ++bias;
+ // Assume digitCount < 95, so we can ignore the 3-digit
+ // exponent case (we'll set useDecimal false anyway).
+
+ const qsizetype digitCount = digits.size() / zero.size();
+ if (!mustMarkDecimal) {
+ // Decimal separator is skipped if at end; adjust if
+ // that happens for only one form:
+ if (digitCount <= decpt && digitCount > 1)
+ ++bias; // decimal but not exponent
+ else if (digitCount == 1 && decpt <= 0)
+ --bias; // exponent but not decimal
}
-
- if (decpt != digits.length() / digitWidth && (decpt <= -4 || decpt > cutoff))
- num_str = exponentForm(zero, decimal, exponential, group, plus, minus,
- digits, decpt, precision, mode,
- always_show_decpt, flags & ZeroPadExponent);
- else
- num_str = decimalForm(zero, decimal, group,
- digits, decpt, precision, mode,
- always_show_decpt, flags & ThousandsGroup);
- break;
+ // When 0 < decpt <= digitCount, the forms have equal digit
+ // counts, plus things bias has taken into account; otherwise
+ // decimal form's digit count is right-padded with zeros to
+ // decpt, when decpt is positive, otherwise it's left-padded
+ // with 1 - decpt zeros.
+ useDecimal = (decpt <= 0 ? 1 - decpt <= bias
+ : decpt <= digitCount ? 0 <= bias : decpt <= digitCount + bias);
+ } else {
+ // X == decpt - 1, POSIX's P; -4 <= X < P iff -4 < decpt <= P
+ Q_ASSERT(precision >= 0);
+ useDecimal = decpt > -4 && decpt <= (precision ? precision : 1);
}
+
+ numStr = useDecimal
+ ? decimalForm(std::move(digits), decpt, precision, mode,
+ mustMarkDecimal, groupDigits)
+ : exponentForm(std::move(digits), decpt, precision, mode,
+ mustMarkDecimal, minExponentDigits);
+ break;
+ }
}
- if (isZero(d))
- negative = false;
-
- // pad with zeros. LeftAdjusted overrides this flag. Also, we don't
- // pad special numbers
- if (flags & QLocaleData::ZeroPadded && !(flags & QLocaleData::LeftAdjusted)) {
- int num_pad_chars = width - num_str.length() / zero.length();
- // leave space for the sign
- if (negative
- || flags & QLocaleData::AlwaysShowSign
- || flags & QLocaleData::BlankBeforePositive)
- --num_pad_chars;
-
- for (int i = 0; i < num_pad_chars; ++i)
- num_str.prepend(zero);
+ // Pad with zeros. LeftAdjusted overrides ZeroPadded.
+ if (flags & ZeroPadded && !(flags & LeftAdjusted)) {
+ for (qsizetype i = numStr.size() / zero.size() + prefix.size(); i < width; ++i)
+ numStr.prepend(zero);
}
}
- // add sign
- if (negative)
- num_str.prepend(minus);
- else if (flags & QLocaleData::AlwaysShowSign)
- num_str.prepend(plus);
- else if (flags & QLocaleData::BlankBeforePositive)
- num_str.prepend(QLatin1Char(' '));
-
- if (flags & QLocaleData::CapitalEorX)
- num_str = std::move(num_str).toUpper();
-
- return num_str;
+ return prefix + (flags & CapitalEorX ? std::move(numStr).toUpper() : numStr);
}
-QString QLocaleData::longLongToString(qlonglong l, int precision,
- int base, int width, unsigned flags) const
+QString QLocaleData::decimalForm(QString &&digits, int decpt, int precision,
+ PrecisionMode pm, bool mustMarkDecimal,
+ bool groupDigits) const
{
- return longLongToString(zeroDigit(), groupSeparator(), positiveSign(), negativeSign(),
- l, precision, base, width, flags);
-}
+ const QString zero = zeroDigit();
+ const auto digitWidth = zero.size();
+ Q_ASSERT(digitWidth == 1 || digitWidth == 2);
+ Q_ASSERT(digits.size() % digitWidth == 0);
-QString QLocaleData::longLongToString(const QString &zero, const QString &group,
- const QString &plus, const QString &minus,
- qlonglong l, int precision,
- int base, int width, unsigned flags)
-{
- bool precision_not_specified = false;
- if (precision == -1) {
- precision_not_specified = true;
- precision = 1;
+ // Separator needs to go at index decpt: so add zeros before or after the
+ // given digits, if they don't reach that position already:
+ if (decpt < 0) {
+ for (; decpt < 0; ++decpt)
+ digits.prepend(zero);
+ } else {
+ for (qsizetype i = digits.size() / digitWidth; i < decpt; ++i)
+ digits.append(zero);
}
- bool negative = l < 0;
- if (base != 10) {
- // these are not supported by sprintf for octal and hex
- flags &= ~AlwaysShowSign;
- flags &= ~BlankBeforePositive;
- negative = false; // neither are negative numbers
+ switch (pm) {
+ case PMDecimalDigits:
+ for (qsizetype i = digits.size() / digitWidth - decpt; i < precision; ++i)
+ digits.append(zero);
+ break;
+ case PMSignificantDigits:
+ for (qsizetype i = digits.size() / digitWidth; i < precision; ++i)
+ digits.append(zero);
+ break;
+ case PMChopTrailingZeros:
+ Q_ASSERT(digits.size() / digitWidth <= qMax(decpt, 1) || !digits.endsWith(zero));
+ break;
}
-QT_WARNING_PUSH
- /* "unary minus operator applied to unsigned type, result still unsigned" */
-QT_WARNING_DISABLE_MSVC(4146)
- /*
- Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
- taking an absolute value has to cast to unsigned to change sign.
- */
- QString num_str = qulltoa(negative ? -qulonglong(l) : qulonglong(l), base, zero);
-QT_WARNING_POP
-
- const QString resultZero = base == 10 ? zero : QStringLiteral("0");
- const auto digitWidth = resultZero.size();
- uint cnt_thousand_sep = 0;
- if (base == 10) {
- if (flags & ThousandsGroup) {
- for (int i = num_str.length() / digitWidth - 3; i > 0; i -= 3) {
- num_str.insert(i * digitWidth, group);
- ++cnt_thousand_sep;
- }
- } else if (flags & IndianNumberGrouping) {
- const int size = num_str.length();
- if (size > 3 * digitWidth)
- num_str.insert(size - 3 * digitWidth , group);
- for (int i = size / digitWidth - 5; i > 0; i -= 2) {
- num_str.insert(i * digitWidth, group);
- ++cnt_thousand_sep;
- }
+ if (mustMarkDecimal || decpt < digits.size() / digitWidth)
+ digits.insert(decpt * digitWidth, decimalPoint());
+
+ if (groupDigits) {
+ const QString group = groupSeparator();
+ qsizetype i = decpt - m_grouping_least;
+ if (i >= m_grouping_top) {
+ digits.insert(i * digitWidth, group);
+ while ((i -= m_grouping_higher) > 0)
+ digits.insert(i * digitWidth, group);
}
}
- for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
- num_str.prepend(resultZero);
-
- if ((flags & ShowBase)
- && base == 8
- && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
- num_str.prepend(QLatin1Char('0'));
-
- // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
- // when precision is not specified in the format string
- bool zero_padded = flags & ZeroPadded
- && !(flags & LeftAdjusted)
- && precision_not_specified;
-
- if (zero_padded) {
- int num_pad_chars = width - num_str.length() / digitWidth;
-
- // leave space for the sign
- if (negative
- || flags & AlwaysShowSign
- || flags & BlankBeforePositive)
- --num_pad_chars;
-
- // leave space for optional '0x' in hex form
- if (base == 16 && (flags & ShowBase))
- num_pad_chars -= 2;
- // leave space for optional '0b' in binary form
- else if (base == 2 && (flags & ShowBase))
- num_pad_chars -= 2;
-
- while (num_pad_chars-- > 0)
- num_str.prepend(resultZero);
+ if (decpt == 0)
+ digits.prepend(zero);
+
+ return std::move(digits);
+}
+
+QString QLocaleData::exponentForm(QString &&digits, int decpt, int precision,
+ PrecisionMode pm, bool mustMarkDecimal,
+ int minExponentDigits) const
+{
+ const QString zero = zeroDigit();
+ const auto digitWidth = zero.size();
+ Q_ASSERT(digitWidth == 1 || digitWidth == 2);
+ Q_ASSERT(digits.size() % digitWidth == 0);
+
+ switch (pm) {
+ case PMDecimalDigits:
+ for (qsizetype i = digits.size() / digitWidth; i < precision + 1; ++i)
+ digits.append(zero);
+ break;
+ case PMSignificantDigits:
+ for (qsizetype i = digits.size() / digitWidth; i < precision; ++i)
+ digits.append(zero);
+ break;
+ case PMChopTrailingZeros:
+ Q_ASSERT(digits.size() / digitWidth <= 1 || !digits.endsWith(zero));
+ break;
}
- if (flags & CapitalEorX)
- num_str = std::move(num_str).toUpper();
+ if (mustMarkDecimal || digits.size() > digitWidth)
+ digits.insert(digitWidth, decimalPoint());
- if (base == 16 && (flags & ShowBase))
- num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
- if (base == 2 && (flags & ShowBase))
- num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
+ digits.append(exponentSeparator());
+ digits.append(longLongToString(decpt - 1, minExponentDigits, 10, -1, AlwaysShowSign));
+
+ return std::move(digits);
+}
- // add sign
+QString QLocaleData::signPrefix(bool negative, unsigned flags) const
+{
if (negative)
- num_str.prepend(minus);
- else if (flags & AlwaysShowSign)
- num_str.prepend(plus);
- else if (flags & BlankBeforePositive)
- num_str.prepend(QLatin1Char(' '));
+ return negativeSign();
+ if (flags & AlwaysShowSign)
+ return positiveSign();
+ if (flags & BlankBeforePositive)
+ return QStringView(u" ").toString();
+ return {};
+}
- return num_str;
+QString QLocaleData::longLongToString(qlonglong n, int precision,
+ int base, int width, unsigned flags) const
+{
+ bool negative = n < 0;
+
+ /*
+ Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
+ taking an absolute value has to take a slight detour.
+ */
+ QString numStr = qulltoa(negative ? 1u + qulonglong(-(n + 1)) : qulonglong(n),
+ base, zeroDigit());
+
+ return applyIntegerFormatting(std::move(numStr), negative, precision, base, width, flags);
}
QString QLocaleData::unsLongLongToString(qulonglong l, int precision,
int base, int width, unsigned flags) const
{
- return unsLongLongToString(zeroDigit(), groupSeparator(), positiveSign(),
- l, precision, base, width, flags);
+ const QString zero = zeroDigit();
+ QString resultZero = base == 10 ? zero : QStringLiteral("0");
+ return applyIntegerFormatting(l ? qulltoa(l, base, zero) : resultZero,
+ false, precision, base, width, flags);
}
-QString QLocaleData::unsLongLongToString(const QString &zero, const QString &group,
- const QString &plus,
- qulonglong l, int precision,
- int base, int width, unsigned flags)
+QString QLocaleData::applyIntegerFormatting(QString &&numStr, bool negative, int precision,
+ int base, int width, unsigned flags) const
{
- const QString resultZero = base == 10 ? zero : QStringLiteral("0");
- QString num_str = l ? qulltoa(l, base, zero) : resultZero;
+ const QString zero = base == 10 ? zeroDigit() : QStringLiteral("0");
+ const auto digitWidth = zero.size();
+ const auto digitCount = numStr.size() / digitWidth;
- bool precision_not_specified = false;
- if (precision == -1) {
- if (flags == NoFlags)
- return num_str; // fast-path: nothing below applies, so we're done.
+ const auto basePrefix = [&] () -> QStringView {
+ if (flags & ShowBase) {
+ const bool upper = flags & UppercaseBase;
+ if (base == 16)
+ return upper ? u"0X" : u"0x";
+ if (base == 2)
+ return upper ? u"0B" : u"0b";
+ if (base == 8 && !numStr.startsWith(zero))
+ return zero;
+ }
+ return {};
+ }();
+
+ const QString prefix = signPrefix(negative, flags) + basePrefix;
+ // Count how much of width we've used up. Each digit counts as one
+ qsizetype usedWidth = digitCount + prefix.size();
+
+ if (base == 10 && flags & GroupDigits) {
+ const QString group = groupSeparator();
+ qsizetype i = digitCount - m_grouping_least;
+ if (i >= m_grouping_top) {
+ numStr.insert(i * digitWidth, group);
+ ++usedWidth;
+ while ((i -= m_grouping_higher) > 0) {
+ numStr.insert(i * digitWidth, group);
+ ++usedWidth;
+ }
+ }
+ // TODO: should we group any zero-padding we add later ?
+ }
- precision_not_specified = true;
+ const bool noPrecision = precision == -1;
+ if (noPrecision)
precision = 1;
+
+ for (qsizetype i = numStr.size(); i < precision; ++i) {
+ numStr.prepend(zero);
+ usedWidth++;
}
- const auto digitWidth = resultZero.size();
- uint cnt_thousand_sep = 0;
- if (base == 10) {
- if (flags & ThousandsGroup) {
- for (int i = num_str.length() / digitWidth - 3; i > 0; i -= 3) {
- num_str.insert(i * digitWidth, group);
- ++cnt_thousand_sep;
- }
- } else if (flags & IndianNumberGrouping) {
- const int size = num_str.length();
- if (size > 3 * digitWidth)
- num_str.insert(size - 3 * digitWidth , group);
- for (int i = size / digitWidth - 5; i > 0; i -= 2) {
- num_str.insert(i * digitWidth, group);
- ++cnt_thousand_sep;
+ // LeftAdjusted overrides ZeroPadded; and sprintf() only pads when
+ // precision is not specified in the format string.
+ if (noPrecision && flags & ZeroPadded && !(flags & LeftAdjusted)) {
+ for (qsizetype i = usedWidth; i < width; ++i)
+ numStr.prepend(zero);
+ }
+
+ QString result(flags & CapitalEorX ? std::move(numStr).toUpper() : std::move(numStr));
+ if (prefix.size())
+ result.prepend(prefix);
+ return result;
+}
+
+inline QLocaleData::NumericData QLocaleData::numericData(QLocaleData::NumberMode mode) const
+{
+ NumericData result;
+ if (this == c()) {
+ result.isC = true;
+ return result;
+ }
+ result.setZero(zero().viewData(single_character_data));
+ result.group = groupDelim().viewData(single_character_data);
+ // Note: minus, plus and exponent might not actually be single characters.
+ result.minus = minus().viewData(single_character_data);
+ result.plus = plus().viewData(single_character_data);
+ if (mode != IntegerMode)
+ result.decimal = decimalSeparator().viewData(single_character_data);
+ if (mode == DoubleScientificMode) {
+ result.exponent = exponential().viewData(single_character_data);
+ // exponentCyrillic means "apply the Cyrrilic-specific exponent hack"
+ result.exponentCyrillic = m_script_id == QLocale::CyrillicScript;
+ }
+#ifndef QT_NO_SYSTEMLOCALE
+ if (this == &systemLocaleData) {
+ const auto getString = [sys = systemLocale()](QSystemLocale::QueryType query) {
+ return sys->query(query).toString();
+ };
+ if (mode != IntegerMode) {
+ result.sysDecimal = getString(QSystemLocale::DecimalPoint);
+ if (result.sysDecimal.size())
+ result.decimal = QStringView{result.sysDecimal};
+ }
+ result.sysGroup = getString(QSystemLocale::GroupSeparator);
+ if (result.sysGroup.size())
+ result.group = QStringView{result.sysGroup};
+ result.sysMinus = getString(QSystemLocale::NegativeSign);
+ if (result.sysMinus.size())
+ result.minus = QStringView{result.sysMinus};
+ result.sysPlus = getString(QSystemLocale::PositiveSign);
+ if (result.sysPlus.size())
+ result.plus = QStringView{result.sysPlus};
+ result.setZero(getString(QSystemLocale::ZeroDigit));
+ }
+#endif
+
+ return result;
+}
+
+namespace {
+// A bit like QStringIterator but rather specialized ... and some of the tokens
+// it recognizes aren't single Unicode code-points (but it does map each to a
+// single character).
+class NumericTokenizer
+{
+ // TODO: use deterministic finite-state-automata.
+ // TODO QTBUG-95460: CLDR has Inf/NaN representations per locale.
+ static constexpr char lettersInfNaN[] = "afin"; // Letters of Inf, NaN
+ static constexpr auto matchInfNaN = QtPrivate::makeCharacterSetMatch<lettersInfNaN>();
+ const QStringView m_text;
+ const QLocaleData::NumericData m_guide;
+ qsizetype m_index = 0;
+ const QLocaleData::NumberMode m_mode;
+ static_assert('+' + 1 == ',' && ',' + 1 == '-' && '-' + 1 == '.');
+ char lastMark; // C locale accepts '+' through lastMark.
+public:
+ NumericTokenizer(QStringView text, QLocaleData::NumericData &&guide,
+ QLocaleData::NumberMode mode)
+ : m_text(text), m_guide(guide), m_mode(mode),
+ lastMark(mode == QLocaleData::IntegerMode ? '-' : '.')
+ {
+ Q_ASSERT(m_guide.isValid(mode));
+ }
+ bool done() const { return !(m_index < m_text.size()); }
+ qsizetype index() const { return m_index; }
+ inline int asBmpDigit(char16_t digit) const;
+ char nextToken();
+};
+
+int NumericTokenizer::asBmpDigit(char16_t digit) const
+{
+ // If digit *is* a digit, result will be in range 0 through 9; otherwise not.
+ // Must match qlocale_tools.h's unicodeForDigit()
+ if (m_guide.zeroUcs != u'\u3007' || digit == m_guide.zeroUcs)
+ return digit - m_guide.zeroUcs;
+
+ // QTBUG-85409: Suzhou's digits aren't contiguous !
+ if (digit == u'\u3020') // U+3020 POSTAL MARK FACE is not a digit.
+ return -1;
+ // ... but is followed by digits 1 through 9.
+ return digit - u'\u3020';
+}
+
+char NumericTokenizer::nextToken()
+{
+ // As long as caller stops iterating on a zero return, those don't need to
+ // keep m_index correctly updated.
+ Q_ASSERT(!done());
+ // Mauls non-letters above 'Z' but we don't care:
+ const auto asciiLower = [](unsigned char c) { return c >= 'A' ? c | 0x20 : c; };
+ const QStringView tail = m_text.sliced(m_index);
+ const QChar ch = tail.front();
+ if (ch == u'\u2212') {
+ // Special case: match the "proper" minus sign, for all locales.
+ ++m_index;
+ return '-';
+ }
+ if (m_guide.isC) {
+ // "Conversion" to C locale is just a filter:
+ ++m_index;
+ if (Q_LIKELY(ch.unicode() < 256)) {
+ unsigned char ascii = asciiLower(ch.toLatin1());
+ if (Q_LIKELY(isAsciiDigit(ascii) || ('+' <= ascii && ascii <= lastMark)
+ // No caller presently (6.5) passes DoubleStandardMode,
+ // so !IntegerMode implies scientific, for now.
+ || (m_mode != QLocaleData::IntegerMode
+ && matchInfNaN.matches(ascii))
+ || (m_mode == QLocaleData::DoubleScientificMode
+ && ascii == 'e'))) {
+ return ascii;
}
}
+ return 0;
+ }
+ if (ch.unicode() < 256) {
+ // Accept the C locale's digits and signs in all locales:
+ char ascii = asciiLower(ch.toLatin1());
+ if (isAsciiDigit(ascii) || ascii == '-' || ascii == '+'
+ // Also its Inf and NaN letters:
+ || (m_mode != QLocaleData::IntegerMode && matchInfNaN.matches(ascii))) {
+ ++m_index;
+ return ascii;
+ }
}
- int zeroPadding = precision - num_str.length() / digitWidth /* + cnt_thousand_sep*/;
- while (zeroPadding-- > 0)
- num_str.prepend(resultZero);
-
- if ((flags & ShowBase)
- && base == 8
- && (num_str.isEmpty() || num_str.at(0).unicode() != QLatin1Char('0')))
- num_str.prepend(QLatin1Char('0'));
-
- // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
- // when precision is not specified in the format string
- bool zero_padded = flags & ZeroPadded
- && !(flags & LeftAdjusted)
- && precision_not_specified;
-
- if (zero_padded) {
- int num_pad_chars = width - num_str.length() / digitWidth;
-
- // leave space for optional '0x' in hex form
- if (base == 16 && flags & ShowBase)
- num_pad_chars -= 2;
- // leave space for optional '0b' in binary form
- else if (base == 2 && flags & ShowBase)
- num_pad_chars -= 2;
-
- while (num_pad_chars-- > 0)
- num_str.prepend(resultZero);
+ // Other locales may be trickier:
+ if (tail.startsWith(m_guide.minus)) {
+ m_index += m_guide.minus.size();
+ return '-';
+ }
+ if (tail.startsWith(m_guide.plus)) {
+ m_index += m_guide.plus.size();
+ return '+';
+ }
+ if (!m_guide.group.isEmpty() && tail.startsWith(m_guide.group)) {
+ m_index += m_guide.group.size();
+ return ',';
+ }
+ if (m_mode != QLocaleData::IntegerMode && tail.startsWith(m_guide.decimal)) {
+ m_index += m_guide.decimal.size();
+ return '.';
+ }
+ if (m_mode == QLocaleData::DoubleScientificMode
+ && tail.startsWith(m_guide.exponent, Qt::CaseInsensitive)) {
+ m_index += m_guide.exponent.size();
+ return 'e';
}
- if (flags & CapitalEorX)
- num_str = std::move(num_str).toUpper();
+ // Must match qlocale_tools.h's unicodeForDigit()
+ if (m_guide.zeroLen == 1) {
+ if (!ch.isSurrogate()) {
+ const uint gap = asBmpDigit(ch.unicode());
+ if (gap < 10u) {
+ ++m_index;
+ return '0' + gap;
+ }
+ } else if (ch.isHighSurrogate() && tail.size() > 1 && tail.at(1).isLowSurrogate()) {
+ return 0;
+ }
+ } else if (ch.isHighSurrogate()) {
+ // None of the corner cases below matches a surrogate, so (update
+ // already and) return early if we don't have a digit.
+ if (tail.size() > 1) {
+ QChar low = tail.at(1);
+ if (low.isLowSurrogate()) {
+ m_index += 2;
+ const uint gap = QChar::surrogateToUcs4(ch, low) - m_guide.zeroUcs;
+ return gap < 10u ? '0' + gap : 0;
+ }
+ }
+ return 0;
+ }
- if (base == 16 && flags & ShowBase)
- num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
- else if (base == 2 && flags & ShowBase)
- num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
+ // All cases where tail starts with properly-matched surrogate pair
+ // have been handled by this point.
+ Q_ASSERT(!(ch.isHighSurrogate() && tail.size() > 1 && tail.at(1).isLowSurrogate()));
- // add sign
- if (flags & AlwaysShowSign)
- num_str.prepend(plus);
- else if (flags & BlankBeforePositive)
- num_str.prepend(QLatin1Char(' '));
+ // Weird corner cases follow (code above assumes these match no surrogates).
+
+ // Some locales use a non-breaking space (U+00A0) or its thin version
+ // (U+202f) for grouping. These look like spaces, so people (and thus some
+ // of our tests) use a regular space instead and complain if it doesn't
+ // work.
+ // Should this be extended generally to any case where group is a space ?
+ if ((m_guide.group == u"\u00a0" || m_guide.group == u"\u202f") && tail.startsWith(u' ')) {
+ ++m_index;
+ return ',';
+ }
- return num_str;
+ // Cyrillic has its own E, used by Ukrainian as exponent; but others
+ // writing Cyrillic may well use that; and Ukrainians might well use E.
+ // All other Cyrillic locales (officially) use plain ASCII E.
+ if (m_guide.exponentCyrillic // Only true in scientific float mode.
+ && (tail.startsWith(u"\u0415", Qt::CaseInsensitive)
+ || tail.startsWith(u"E", Qt::CaseInsensitive))) {
+ ++m_index;
+ return 'e';
+ }
+
+ return 0;
}
+} // namespace with no name
/*
- Converts a number in locale to its representation in the C locale.
- Only has to guarantee that a string that is a correct representation of
- a number will be converted. If junk is passed in, junk will be passed
- out and the error will be detected during the actual conversion to a
- number. We can't detect junk here, since we don't even know the base
- of the number.
+ Converts a number in locale representation to the C locale equivalent.
+
+ Only has to guarantee that a string that is a correct representation of a
+ number will be converted. Checks signs, separators and digits appear in all
+ the places they should, and nowhere else.
+
+ Returns true precisely if the number appears to be well-formed, modulo
+ things a parser for C Locale strings (without digit-grouping separators;
+ they're stripped) will catch. When it returns true, it records (and
+ '\0'-terminates) the C locale representation in *result.
+
+ Note: only QString integer-parsing methods have a base parameter (hence need
+ to cope with letters as possible digits); but these are now all routed via
+ byteArrayToU?LongLong(), so no longer come via here. The QLocale
+ number-parsers only work in decimal, so don't have to cope with any digits
+ other than 0 through 9.
*/
bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
- CharBuff *result) const
+ NumberMode mode, CharBuff *result) const
{
s = s.trimmed();
if (s.size() < 1)
return false;
+ NumericTokenizer tokens(s, numericData(mode), mode);
+
+ // Digit-grouping details (all modes):
+ qsizetype digitsInGroup = 0;
+ qsizetype last_separator_idx = -1;
+ qsizetype start_of_digits_idx = -1;
+
+ // Floating-point details (non-integer modes):
+ qsizetype decpt_idx = -1;
+ qsizetype exponent_idx = -1;
+
+ char last = '\0';
+ while (!tokens.done()) {
+ qsizetype idx = tokens.index(); // before nextToken() advances
+ char out = tokens.nextToken();
+ if (out == 0)
+ return false;
+ Q_ASSERT(tokens.index() > idx); // it always *should* advance (except on zero return)
- const QChar *uc = s.data();
- auto length = s.size();
- decltype(length) idx = 0;
-
- const int leadingGroupWidth = (m_country_id == QLocale::India ? 2 : 3);
- int digitsInGroup = 0;
- int group_cnt = 0; // counts number of group chars
- int decpt_idx = -1;
- int last_separator_idx = -1;
- int start_of_digits_idx = -1;
- int exponent_idx = -1;
-
- while (idx < length) {
- const QStringView in = QStringView(uc + idx, uc[idx].isHighSurrogate() ? 2 : 1);
-
- char out = numericToCLocale(in);
- if (out == 0) {
- const QChar simple = in.size() == 1 ? in.front() : QChar::Null;
- if (in == listSeparator())
- out = ';';
- else if (in == percentSign())
- out = '%';
- // for handling base-x numbers
- else if (simple.toLatin1() >= 'A' && simple.toLatin1() <= 'Z')
- out = simple.toLower().toLatin1();
- else if (simple.toLatin1() >= 'a' && simple.toLatin1() <= 'z')
- out = simple.toLatin1();
- else
- break;
- } else if (out == '.') {
+ if (out == '.') {
// Fail if more than one decimal point or point after e
if (decpt_idx != -1 || exponent_idx != -1)
return false;
@@ -3718,309 +4287,246 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
exponent_idx = idx;
}
- if (number_options & QLocale::RejectLeadingZeroInExponent) {
- if (exponent_idx != -1 && out == '0' && idx < length - 1) {
- // After the exponent there can only be '+', '-' or digits.
- // If we find a '0' directly after some non-digit, then that is a leading zero.
- if (result->last() < '0' || result->last() > '9')
- return false;
- }
+ if (number_options.testFlag(QLocale::RejectLeadingZeroInExponent)
+ && exponent_idx != -1 && out == '0') {
+ // After the exponent there can only be '+', '-' or digits.
+ // If we find a '0' directly after some non-digit, then that is a
+ // leading zero, acceptable only if it is the whole exponent.
+ if (!tokens.done() && !isAsciiDigit(last))
+ return false;
}
- if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
- // If we've seen a decimal point and the last character after the exponent is 0, then
- // that is a trailing zero.
- if (decpt_idx >= 0 && idx == exponent_idx && result->last() == '0')
- return false;
+ if (number_options.testFlag(QLocale::RejectTrailingZeroesAfterDot) && decpt_idx >= 0) {
+ // In a fractional part, a 0 just before the exponent is trailing:
+ if (idx == exponent_idx && last == '0')
+ return false;
}
- if (!(number_options & QLocale::RejectGroupSeparator)) {
- if (start_of_digits_idx == -1 && out >= '0' && out <= '9') {
- start_of_digits_idx = idx;
- digitsInGroup++;
+ if (!number_options.testFlag(QLocale::RejectGroupSeparator)) {
+ if (isAsciiDigit(out)) {
+ if (start_of_digits_idx == -1)
+ start_of_digits_idx = idx;
+ ++digitsInGroup;
} else if (out == ',') {
// Don't allow group chars after the decimal point or exponent
if (decpt_idx != -1 || exponent_idx != -1)
return false;
if (last_separator_idx == -1) {
- if (start_of_digits_idx == -1 || digitsInGroup > leadingGroupWidth)
+ // Check distance from the beginning of the digits:
+ if (start_of_digits_idx == -1 || m_grouping_top > digitsInGroup
+ || digitsInGroup >= m_grouping_least + m_grouping_top) {
return false;
+ }
} else {
- // check distance from the last separator or from the beginning of the digits
- // ### FIXME: Some locales allow other groupings!
- // See https://en.wikipedia.org/wiki/Thousands_separator
- if (digitsInGroup != leadingGroupWidth)
+ // Check distance from the last separator:
+ if (digitsInGroup != m_grouping_higher)
return false;
}
last_separator_idx = idx;
- ++group_cnt;
digitsInGroup = 0;
-
- // don't add the group separator
- idx += in.size();
- continue;
- } else if (out == '.' || idx == exponent_idx) {
- // check distance from the last separator
- // ### FIXME: Some locales allow other groupings!
- // See https://en.wikipedia.org/wiki/Thousands_separator
- if (last_separator_idx != -1 && digitsInGroup != 3)
+ } else if (mode != IntegerMode && (out == '.' || idx == exponent_idx)
+ && last_separator_idx != -1) {
+ // Were there enough digits since the last group separator?
+ if (digitsInGroup != m_grouping_least)
return false;
// stop processing separators
last_separator_idx = -1;
- } else if (out >= '0' && out <= '9') {
- digitsInGroup++;
}
+ } else if (out == ',') {
+ return false;
}
- result->append(out);
- idx += in.size();
+ last = out;
+ if (out != ',') // Leave group separators out of the result.
+ result->append(out);
}
- if (!(number_options & QLocale::RejectGroupSeparator)) {
- // group separator post-processing
- // did we end in a separator?
- if (last_separator_idx + 1 == idx)
- return false;
- // were there enough digits since the last separator?
- if (last_separator_idx != -1 && digitsInGroup != 3)
+ if (!number_options.testFlag(QLocale::RejectGroupSeparator) && last_separator_idx != -1) {
+ // Were there enough digits since the last group separator?
+ if (digitsInGroup != m_grouping_least)
return false;
}
- if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
- // In decimal form, the last character can be a trailing zero if we've seen a decpt.
- if (decpt_idx != -1 && exponent_idx == -1 && result->last() == '0')
+ if (number_options.testFlag(QLocale::RejectTrailingZeroesAfterDot)
+ && decpt_idx != -1 && exponent_idx == -1) {
+ // In the fractional part, a final zero is trailing:
+ if (last == '0')
return false;
}
result->append('\0');
- return idx == length;
+ return true;
}
-bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray *buff,
- int decDigits, QLocale::NumberOptions number_options) const
+ParsingResult
+QLocaleData::validateChars(QStringView str, NumberMode numMode, int decDigits,
+ QLocale::NumberOptions number_options) const
{
- buff->clear();
- buff->reserve(str.length());
+ ParsingResult result;
+ result.buff.reserve(str.size());
+ enum { Whole, Fractional, Exponent } state = Whole;
const bool scientific = numMode == DoubleScientificMode;
- bool lastWasE = false;
- bool lastWasDigit = false;
- int eCnt = 0;
- int decPointCnt = 0;
- bool dec = false;
- int decDigitCnt = 0;
-
- for (qsizetype i = 0; i < str.size();) {
- const QStringView in = str.mid(i, str.at(i).isHighSurrogate() ? 2 : 1);
- char c = numericToCLocale(in);
-
- if (c >= '0' && c <= '9') {
- if (numMode != IntegerMode) {
- // If a double has too many digits after decpt, it shall be Invalid.
- if (dec && decDigits != -1 && decDigits < ++decDigitCnt)
- return false;
- }
+ NumericTokenizer tokens(str, numericData(numMode), numMode);
+ char last = '\0';
- // The only non-digit character after the 'e' can be '+' or '-'.
- // If a zero is directly after that, then the exponent is zero-padded.
- if ((number_options & QLocale::RejectLeadingZeroInExponent)
- && c == '0' && eCnt > 0 && !lastWasDigit) {
- return false;
+ while (!tokens.done()) {
+ char c = tokens.nextToken();
+
+ if (isAsciiDigit(c)) {
+ switch (state) {
+ case Whole:
+ // Nothing special to do (unless we want to check grouping sizes).
+ break;
+ case Fractional:
+ // If a double has too many digits in its fractional part it is Invalid.
+ if (decDigits-- == 0)
+ return {};
+ break;
+ case Exponent:
+ if (!isAsciiDigit(last)) {
+ // This is the first digit in the exponent (there may have beena '+'
+ // or '-' in before). If it's a zero, the exponent is zero-padded.
+ if (c == '0' && (number_options & QLocale::RejectLeadingZeroInExponent))
+ return {};
+ }
+ break;
}
- lastWasDigit = true;
} else {
switch (c) {
- case '.':
- if (numMode == IntegerMode) {
- // If an integer has a decimal point, it shall be Invalid.
- return false;
- } else {
- // If a double has more than one decimal point, it shall be Invalid.
- if (++decPointCnt > 1)
- return false;
-#if 0
- // If a double with no decimal digits has a decimal point, it shall be
- // Invalid.
- if (decDigits == 0)
- return false;
-#endif // On second thoughts, it shall be Valid.
-
- dec = true;
- }
- break;
+ case '.':
+ // If an integer has a decimal point, it is Invalid.
+ // A double can only have one, at the end of its whole-number part.
+ if (numMode == IntegerMode || state != Whole)
+ return {};
+ // Even when decDigits is 0, we do allow the decimal point to be
+ // present - just as long as no digits follow it.
+
+ state = Fractional;
+ break;
- case '+':
- case '-':
- if (scientific) {
- // If a scientific has a sign that's not at the beginning or after
- // an 'e', it shall be Invalid.
- if (i != 0 && !lastWasE)
- return false;
- } else {
- // If a non-scientific has a sign that's not at the beginning,
- // it shall be Invalid.
- if (i != 0)
- return false;
- }
- break;
+ case '+':
+ case '-':
+ // A sign can only appear at the start or after the e of scientific:
+ if (last != '\0' && !(scientific && last == 'e'))
+ return {};
+ break;
- case ',':
- //it can only be placed after a digit which is before the decimal point
- if ((number_options & QLocale::RejectGroupSeparator) || !lastWasDigit ||
- decPointCnt > 0)
- return false;
- break;
+ case ',':
+ // Grouping is only allowed after a digit in the whole-number portion:
+ if ((number_options & QLocale::RejectGroupSeparator) || state != Whole
+ || !isAsciiDigit(last)) {
+ return {};
+ }
+ // We could check grouping sizes are correct, but fixup()s are
+ // probably better off correcting any misplacement instead.
+ break;
- case 'e':
- if (scientific) {
- // If a scientific has more than one 'e', it shall be Invalid.
- if (++eCnt > 1)
- return false;
- dec = false;
- } else {
- // If a non-scientific has an 'e', it shall be Invalid.
- return false;
- }
- break;
+ case 'e':
+ // Only one e is allowed and only in scientific:
+ if (!scientific || state == Exponent)
+ return {};
+ state = Exponent;
+ break;
- default:
- // If it's not a valid digit, it shall be Invalid.
- return false;
+ default:
+ // Nothing else can validly appear in a number.
+ // NumericTokenizer allows letters of "inf" and "nan", but
+ // validators don't accept those values.
+ // For anything else, tokens.nextToken() must have returned 0.
+ Q_ASSERT(!c || c == 'a' || c == 'f' || c == 'i' || c == 'n');
+ return {};
}
- lastWasDigit = false;
}
- lastWasE = c == 'e';
- if (c != ',')
- buff->append(c);
-
- i += in.size();
+ last = c;
+ if (c != ',') // Skip grouping
+ result.buff.append(c);
}
- return true;
+ result.state = ParsingResult::Acceptable;
+
+ // Intermediate if it ends with any character that requires a digit after
+ // it to be valid e.g. group separator, sign, or exponent
+ if (last == ',' || last == '-' || last == '+' || last == 'e')
+ result.state = ParsingResult::Intermediate;
+
+ return result;
}
double QLocaleData::stringToDouble(QStringView str, bool *ok,
QLocale::NumberOptions number_options) const
{
CharBuff buff;
- if (!numberToCLocale(str, number_options, &buff)) {
+ if (!numberToCLocale(str, number_options, DoubleScientificMode, &buff)) {
if (ok != nullptr)
*ok = false;
return 0.0;
}
- int processed = 0;
- bool nonNullOk = false;
- double d = qt_asciiToDouble(buff.constData(), buff.length() - 1, nonNullOk, processed);
+ auto r = qt_asciiToDouble(buff.constData(), buff.size() - 1);
if (ok != nullptr)
- *ok = nonNullOk;
- return d;
+ *ok = r.ok();
+ return r.result;
}
-qlonglong QLocaleData::stringToLongLong(QStringView str, int base, bool *ok,
- QLocale::NumberOptions number_options) const
+QSimpleParsedNumber<qint64>
+QLocaleData::stringToLongLong(QStringView str, int base,
+ QLocale::NumberOptions number_options) const
{
CharBuff buff;
- if (!numberToCLocale(str, number_options, &buff)) {
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
+ if (!numberToCLocale(str, number_options, IntegerMode, &buff))
+ return {};
- return bytearrayToLongLong(buff.constData(), base, ok);
+ return bytearrayToLongLong(QByteArrayView(buff), base);
}
-qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok,
- QLocale::NumberOptions number_options) const
+QSimpleParsedNumber<quint64>
+QLocaleData::stringToUnsLongLong(QStringView str, int base,
+ QLocale::NumberOptions number_options) const
{
CharBuff buff;
- if (!numberToCLocale(str, number_options, &buff)) {
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
+ if (!numberToCLocale(str, number_options, IntegerMode, &buff))
+ return {};
- return bytearrayToUnsLongLong(buff.constData(), base, ok);
+ return bytearrayToUnsLongLong(QByteArrayView(buff), base);
}
-double QLocaleData::bytearrayToDouble(const char *num, bool *ok)
+static bool checkParsed(QByteArrayView num, qsizetype used)
{
- bool nonNullOk = false;
- int len = static_cast<int>(strlen(num));
- Q_ASSERT(len >= 0);
- int processed = 0;
- double d = qt_asciiToDouble(num, len, nonNullOk, processed);
- if (ok != nullptr)
- *ok = nonNullOk;
- return d;
-}
-
-qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok)
-{
- bool _ok;
- const char *endptr;
-
- if (*num == '\0') {
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
-
- qlonglong l = qstrtoll(num, &endptr, base, &_ok);
-
- if (!_ok) {
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
+ if (used <= 0)
+ return false;
- if (*endptr != '\0') {
- while (ascii_isspace(*endptr))
- ++endptr;
+ const qsizetype len = num.size();
+ if (used < len && num[used] != '\0') {
+ while (used < len && ascii_isspace(num[used]))
+ ++used;
}
- if (*endptr != '\0') {
+ if (used < len && num[used] != '\0')
// we stopped at a non-digit character after converting some digits
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
+ return false;
- if (ok != nullptr)
- *ok = true;
- return l;
+ return true;
}
-qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool *ok)
+QSimpleParsedNumber<qint64> QLocaleData::bytearrayToLongLong(QByteArrayView num, int base)
{
- bool _ok;
- const char *endptr;
- qulonglong l = qstrtoull(num, &endptr, base, &_ok);
-
- if (!_ok) {
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
-
- if (*endptr != '\0') {
- while (ascii_isspace(*endptr))
- ++endptr;
- }
-
- if (*endptr != '\0') {
- if (ok != nullptr)
- *ok = false;
- return 0;
- }
+ auto r = qstrntoll(num.data(), num.size(), base);
+ if (!checkParsed(num, r.used))
+ return {};
+ return r;
+}
- if (ok != nullptr)
- *ok = true;
- return l;
+QSimpleParsedNumber<quint64> QLocaleData::bytearrayToUnsLongLong(QByteArrayView num, int base)
+{
+ auto r = qstrntoull(num.data(), num.size(), base);
+ if (!checkParsed(num, r.used))
+ return {};
+ return r;
}
/*!
@@ -4039,24 +4545,24 @@ qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool *
\since 4.8
Returns a currency symbol according to the \a format.
*/
-QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
+QString QLocale::currencySymbol(CurrencySymbolFormat format) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::CurrencySymbol, format);
- if (!res.isNull())
- return res.toString();
+ if (d->m_data == &systemLocaleData) {
+ auto res = systemLocale()->query(QSystemLocale::CurrencySymbol, format).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
switch (format) {
case CurrencySymbol:
return d->m_data->currencySymbol().getData(currency_symbol_data);
case CurrencyDisplayName:
- return d->m_data->currencyDisplayName().getListEntry(currency_display_name_data, 0);
+ return d->m_data->currencyDisplayName().getData(currency_display_name_data);
case CurrencyIsoCode: {
const char *code = d->m_data->m_currency_iso_code;
- if (int len = qstrnlen(code, 3))
- return QString::fromLatin1(code, len);
+ if (auto len = qstrnlen(code, 3))
+ return QString::fromLatin1(code, qsizetype(len));
break;
}
}
@@ -4074,12 +4580,12 @@ QString QLocale::currencySymbol(QLocale::CurrencySymbolFormat format) const
QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QSystemLocale::CurrencyToStringArgument arg(value, symbol);
- QVariant res =
- systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
- if (!res.isNull())
- return res.toString();
+ auto res = systemLocale()->query(QSystemLocale::CurrencyToString,
+ QVariant::fromValue(arg)).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
@@ -4090,8 +4596,8 @@ QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
QString str = toString(value);
QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty())
- sym = currencySymbol(QLocale::CurrencyIsoCode);
- return range.getData(currency_format_data).arg(str, sym);
+ sym = currencySymbol(CurrencyIsoCode);
+ return range.viewData(currency_format_data).arg(str, sym);
}
/*!
@@ -4101,32 +4607,21 @@ QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const
QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QSystemLocale::CurrencyToStringArgument arg(value, symbol);
- QVariant res =
- systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
- if (!res.isNull())
- return res.toString();
+ auto res = systemLocale()->query(QSystemLocale::CurrencyToString,
+ QVariant::fromValue(arg)).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
QString str = toString(value);
QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty())
- sym = currencySymbol(QLocale::CurrencyIsoCode);
+ sym = currencySymbol(CurrencyIsoCode);
return d->m_data->currencyFormat().getData(currency_format_data).arg(str, sym);
}
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-/*!
- \since 4.8
- \overload
-*/
-QString QLocale::toCurrencyString(double value, const QString &symbol) const
-{
- return toCurrencyString(value, symbol, d->m_data->m_currency_digits);
-}
-#endif
-
/*!
\since 5.7
\overload toCurrencyString()
@@ -4140,12 +4635,12 @@ QString QLocale::toCurrencyString(double value, const QString &symbol) const
QString QLocale::toCurrencyString(double value, const QString &symbol, int precision) const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
+ if (d->m_data == &systemLocaleData) {
QSystemLocale::CurrencyToStringArgument arg(value, symbol);
- QVariant res =
- systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg));
- if (!res.isNull())
- return res.toString();
+ auto res = systemLocale()->query(QSystemLocale::CurrencyToString,
+ QVariant::fromValue(arg)).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
QLocaleData::DataRange range = d->m_data->currencyFormatNegative();
@@ -4156,12 +4651,11 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision);
QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty())
- sym = currencySymbol(QLocale::CurrencyIsoCode);
- return range.getData(currency_format_data).arg(str, sym);
+ sym = currencySymbol(CurrencyIsoCode);
+ return range.viewData(currency_format_data).arg(str, sym);
}
/*!
- \fn QString QLocale::toCurrencyString(float i, const QString &symbol) const
\fn QString QLocale::toCurrencyString(float i, const QString &symbol, int precision) const
\overload toCurrencyString()
*/
@@ -4182,19 +4676,6 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
\sa formattedDataSize()
*/
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- \obsolete
-
- Use the const version instead.
-*/
-QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
-{
- const auto *that = this;
- return that->formattedDataSize(bytes, precision, format);
-}
-#endif
-
/*!
\since 5.10
@@ -4230,94 +4711,139 @@ QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats
// We don't support sizes in units larger than exbibytes because
// the number of bytes would not fit into qint64.
Q_ASSERT(power <= 6 && power >= 0);
- QString unit;
+ QStringView unit;
if (power > 0) {
QLocaleData::DataRange range = (format & DataSizeSIQuantifiers)
? d->m_data->byteAmountSI() : d->m_data->byteAmountIEC();
- unit = range.getListEntry(byte_unit_data, power - 1);
+ unit = range.viewListEntry(byte_unit_data, power - 1);
} else {
- unit = d->m_data->byteCount().getData(byte_unit_data);
+ unit = d->m_data->byteCount().viewData(byte_unit_data);
}
- return number + QLatin1Char(' ') + unit;
+ return number + u' ' + unit;
}
/*!
\since 4.8
-
- Returns an ordered list of locale names for translation purposes in
- preference order (like "en-Latn-US", "en-US", "en").
-
- The return value represents locale names that the user expects to see the
- UI translation in.
-
- Most like you do not need to use this function directly, but just pass the
+ \brief List of locale names for use in selecting translations
+
+ Each entry in the returned list is the name of a locale suitable to the
+ user's preferences for what to translate the UI into. Where a name in the
+ list is composed of several tags, they are joined as indicated by \a
+ separator. Prior to Qt 6.7 a dash was used as separator.
+
+ For example, using the default separator QLocale::TagSeparator::Dash, if the
+ user has configured their system to use English as used in the USA, the list
+ would be "en-Latn-US", "en-US", "en". The order of entries is the order in
+ which to check for translations; earlier items in the list are to be
+ preferred over later ones. If your translation files use underscores, rather
+ than dashes, to separate locale tags, pass QLocale::TagSeparator::Underscore
+ as \a separator.
+
+ Most likely you do not need to use this function directly, but just pass the
QLocale object to the QTranslator::load() function.
- The first item in the list is the most preferred one.
-
\sa QTranslator, bcp47Name()
*/
-QStringList QLocale::uiLanguages() const
+QStringList QLocale::uiLanguages(TagSeparator separator) const
{
+ const char sep = char(separator);
QStringList uiLanguages;
- QList<QLocale> locales;
-#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::UILanguages, QVariant());
- if (!res.isNull()) {
- uiLanguages = res.toStringList();
- // ... but we need to include likely-adjusted forms of each of those, too:
- for (const auto &entry : qAsConst(uiLanguages))
- locales.append(QLocale(entry));
+ if (uchar(sep) > 0x7f) {
+ badSeparatorWarning("uiLanguages", sep);
+ return uiLanguages;
+ }
+ QList<QLocaleId> localeIds;
+#ifdef QT_NO_SYSTEMLOCALE
+ constexpr bool isSystem = false;
+#else
+ const bool isSystem = d->m_data == &systemLocaleData;
+ if (isSystem) {
+ uiLanguages = systemLocale()->query(QSystemLocale::UILanguages).toStringList();
+ // ... but we need to include likely-adjusted forms of each of those, too.
+ // For now, collect up locale Ids representing the entries, for later processing:
+ for (const auto &entry : std::as_const(uiLanguages))
+ localeIds.append(QLocaleId::fromName(entry));
+ if (localeIds.isEmpty())
+ localeIds.append(systemLocale()->fallbackLocale().d->m_data->id());
+ // If the system locale (isn't C and) didn't include itself in the list,
+ // or as fallback, presume to know better than it and put its name
+ // first. (Known issue, QTBUG-104930, on some macOS versions when in
+ // locale en_DE.) Our translation system might have a translation for a
+ // locale the platform doesn't believe in.
+ const QString name = bcp47Name(separator);
+ if (!name.isEmpty() && language() != C && !uiLanguages.contains(name)) {
+ // That uses contains(name) as a cheap pre-test, but there may be an
+ // entry that matches this on purging likely subtags.
+ const QLocaleId mine = d->m_data->id().withLikelySubtagsRemoved();
+ const auto isMine = [mine](const QString &entry) {
+ return QLocaleId::fromName(entry).withLikelySubtagsRemoved() == mine;
+ };
+ if (std::none_of(uiLanguages.constBegin(), uiLanguages.constEnd(), isMine)) {
+ localeIds.prepend(d->m_data->id());
+ uiLanguages.prepend(name);
+ }
}
- if (locales.isEmpty())
- locales.append(systemLocale()->fallbackUiLocale());
} else
#endif
{
- locales.append(*this);
+ localeIds.append(d->m_data->id());
}
- for (int i = locales.size(); i-- > 0; ) {
- const QLocale &locale = locales.at(i);
- int j;
+ for (qsizetype i = localeIds.size(); i-- > 0; ) {
+ QLocaleId id = localeIds.at(i);
+ qsizetype j;
QByteArray prior;
- if (i < uiLanguages.size()) {
+ if (isSystem && i < uiLanguages.size()) {
// Adding likely-adjusted forms to system locale's list.
// Name the locale is derived from:
- const QString &name = uiLanguages.at(i);
- prior = name.toLatin1();
- // Don't try to likely-adjust if construction's likely-adjustments
- // were so drastic the result doesn't match the prior name:
- if (locale.name() != name && locale.d->rawName() != prior)
- continue;
- // Insert just after prior:
+ prior = uiLanguages.at(i).toLatin1();
+ // Insert just after the entry we're supplementing:
j = i + 1;
+ } else if (id.language_id == C) {
+ // Attempt no likely sub-tag amendments to C:
+ uiLanguages.append(QString::fromLatin1(id.name(sep)));
+ continue;
} else {
- // Plain locale, not system locale; just append.
+ // Plain locale or empty system uiLanguages; just append.
+ prior = id.name(sep);
+ uiLanguages.append(QString::fromLatin1(prior));
j = uiLanguages.size();
}
- const auto data = locale.d->m_data;
- QLocaleId id
- = QLocaleId::fromIds(data->m_language_id, data->m_script_id, data->m_country_id);
const QLocaleId max = id.withLikelySubtagsAdded();
const QLocaleId min = max.withLikelySubtagsRemoved();
- id.script_id = 0; // For re-use as script-less variant.
- // Include version with all likely sub-tags (last) if distinct from the rest:
- if (max != min && max != id && max.name() != prior)
- uiLanguages.insert(j, QString::fromLatin1(max.name()));
+ // Include minimal version (last) unless it's what our locale is derived from:
+ if (auto name = min.name(sep); name != prior)
+ uiLanguages.insert(j, QString::fromLatin1(name));
+ else if (!isSystem)
+ --j; // bcp47Name() matches min(): put more specific forms *before* it.
+
+ if (id.script_id) {
+ // Include scriptless version if likely-equivalent and distinct:
+ id.script_id = 0;
+ if (id != min && id.withLikelySubtagsAdded() == max) {
+ if (auto name = id.name(sep); name != prior)
+ uiLanguages.insert(j, QString::fromLatin1(name));
+ }
+ }
- // Include scriptless version if likely-equivalent and distinct:
- if (data->m_script_id && id != min && id.name() != prior
- && id.withLikelySubtagsAdded() == max) {
- uiLanguages.insert(j, QString::fromLatin1(id.name()));
+ if (!id.territory_id) {
+ Q_ASSERT(!min.territory_id);
+ Q_ASSERT(!id.script_id); // because we just cleared it.
+ // Include version with territory if it likely-equivalent and distinct:
+ id.territory_id = max.territory_id;
+ if (id != max && id.withLikelySubtagsAdded() == max) {
+ if (auto name = id.name(sep); name != prior)
+ uiLanguages.insert(j, QString::fromLatin1(name));
+ }
}
- // Include minimal version (first) unless it's what our locale is derived from:
- if (min.name() != prior)
- uiLanguages.insert(j, QString::fromLatin1(min.name()));
+ // Include version with all likely sub-tags (first) if distinct from the rest:
+ if (max != min && max != id) {
+ if (auto name = max.name(sep); name != prior)
+ uiLanguages.insert(j, QString::fromLatin1(name));
+ }
}
return uiLanguages;
}
@@ -4336,8 +4862,8 @@ QStringList QLocale::uiLanguages() const
QLocale QLocale::collation() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QString res = systemLocale()->query(QSystemLocale::Collation, QVariant()).toString();
+ if (d->m_data == &systemLocaleData) {
+ const auto res = systemLocale()->query(QSystemLocale::Collation).toString();
if (!res.isEmpty())
return QLocale(res);
}
@@ -4349,41 +4875,57 @@ QLocale QLocale::collation() const
\since 4.8
Returns a native name of the language for the locale. For example
- "Schwiizertüütsch" for Swiss-German locale.
+ "Schweizer Hochdeutsch" for the Swiss-German locale.
- \sa nativeCountryName(), languageToString()
+ \sa nativeTerritoryName(), languageToString()
*/
QString QLocale::nativeLanguageName() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::NativeLanguageName, QVariant());
- if (!res.isNull())
- return res.toString();
+ if (d->m_data == &systemLocaleData) {
+ auto res = systemLocale()->query(QSystemLocale::NativeLanguageName).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
return d->m_data->endonymLanguage().getData(endonyms_data);
}
/*!
- \since 4.8
+ \since 6.2
- Returns a native name of the country for the locale. For example
+ Returns a native name of the territory for the locale. For example
"España" for Spanish/Spain locale.
- \sa nativeLanguageName(), countryToString()
+ \sa nativeLanguageName(), territoryToString()
*/
-QString QLocale::nativeCountryName() const
+QString QLocale::nativeTerritoryName() const
{
#ifndef QT_NO_SYSTEMLOCALE
- if (d->m_data == systemData()) {
- QVariant res = systemLocale()->query(QSystemLocale::NativeCountryName, QVariant());
- if (!res.isNull())
- return res.toString();
+ if (d->m_data == &systemLocaleData) {
+ auto res = systemLocale()->query(QSystemLocale::NativeTerritoryName).toString();
+ if (!res.isEmpty())
+ return res;
}
#endif
- return d->m_data->endonymCountry().getData(endonyms_data);
+ return d->m_data->endonymTerritory().getData(endonyms_data);
+}
+
+#if QT_DEPRECATED_SINCE(6, 6)
+/*!
+ \deprecated [6.6] Use \l nativeTerritoryName() instead.
+ \since 4.8
+
+ Returns a native name of the territory for the locale. For example
+ "España" for Spanish/Spain locale.
+
+ \sa nativeLanguageName(), territoryToString()
+*/
+QString QLocale::nativeCountryName() const
+{
+ return nativeTerritoryName();
}
+#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QLocale &l)
@@ -4392,7 +4934,7 @@ QDebug operator<<(QDebug dbg, const QLocale &l)
dbg.nospace().noquote()
<< "QLocale(" << QLocale::languageToString(l.language())
<< ", " << QLocale::scriptToString(l.script())
- << ", " << QLocale::countryToString(l.country()) << ')';
+ << ", " << QLocale::territoryToString(l.territory()) << ')';
return dbg;
}
#endif
diff --git a/src/corelib/text/qlocale.h b/src/corelib/text/qlocale.h
index ee7e978e48..abef24ea0e 100644
--- a/src/corelib/text/qlocale.h
+++ b/src/corelib/text/qlocale.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOCALE_H
#define QLOCALE_H
@@ -65,7 +29,6 @@ class Q_CORE_EXPORT QLocale
{
Q_GADGET
friend class QString;
- friend class QStringRef;
friend class QByteArray;
friend class QIntValidator;
friend class QDoubleValidatorPrivate;
@@ -73,826 +36,830 @@ class Q_CORE_EXPORT QLocale
friend class QTextStreamPrivate;
public:
+ static constexpr int DefaultTwoDigitBaseYear = 1900;
+
// see qlocale_data_p.h for more info on generated data
// GENERATED PART STARTS HERE
- enum Language {
+ enum Language : ushort {
AnyLanguage = 0,
C = 1,
Abkhazian = 2,
- Oromo = 3,
- Afar = 4,
- Afrikaans = 5,
- Albanian = 6,
- Amharic = 7,
- Arabic = 8,
- Armenian = 9,
- Assamese = 10,
- Aymara = 11,
- Azerbaijani = 12,
- Bashkir = 13,
- Basque = 14,
- Bengali = 15,
- Dzongkha = 16,
- Bihari = 17,
- Bislama = 18,
- Breton = 19,
- Bulgarian = 20,
- Burmese = 21,
- Belarusian = 22,
- Khmer = 23,
- Catalan = 24,
- Chinese = 25,
- Corsican = 26,
- Croatian = 27,
- Czech = 28,
- Danish = 29,
- Dutch = 30,
- English = 31,
- Esperanto = 32,
- Estonian = 33,
- Faroese = 34,
- Fijian = 35,
- Finnish = 36,
- French = 37,
- WesternFrisian = 38,
- Gaelic = 39,
- Galician = 40,
- Georgian = 41,
- German = 42,
- Greek = 43,
- Greenlandic = 44,
- Guarani = 45,
- Gujarati = 46,
- Hausa = 47,
- Hebrew = 48,
- Hindi = 49,
- Hungarian = 50,
- Icelandic = 51,
- Indonesian = 52,
- Interlingua = 53,
- Interlingue = 54,
- Inuktitut = 55,
- Inupiak = 56,
- Irish = 57,
- Italian = 58,
- Japanese = 59,
- Javanese = 60,
- Kannada = 61,
- Kashmiri = 62,
- Kazakh = 63,
- Kinyarwanda = 64,
- Kirghiz = 65,
- Korean = 66,
- Kurdish = 67,
- Rundi = 68,
- Lao = 69,
- Latin = 70,
- Latvian = 71,
- Lingala = 72,
- Lithuanian = 73,
- Macedonian = 74,
- Malagasy = 75,
- Malay = 76,
- Malayalam = 77,
- Maltese = 78,
- Maori = 79,
- Marathi = 80,
- Marshallese = 81,
- Mongolian = 82,
- NauruLanguage = 83,
- Nepali = 84,
- NorwegianBokmal = 85,
- Occitan = 86,
- Oriya = 87,
- Pashto = 88,
- Persian = 89,
- Polish = 90,
- Portuguese = 91,
- Punjabi = 92,
- Quechua = 93,
- Romansh = 94,
- Romanian = 95,
- Russian = 96,
- Samoan = 97,
- Sango = 98,
- Sanskrit = 99,
- Serbian = 100,
- Ossetic = 101,
- SouthernSotho = 102,
- Tswana = 103,
- Shona = 104,
- Sindhi = 105,
- Sinhala = 106,
- Swati = 107,
- Slovak = 108,
- Slovenian = 109,
- Somali = 110,
- Spanish = 111,
- Sundanese = 112,
- Swahili = 113,
- Swedish = 114,
- Sardinian = 115,
- Tajik = 116,
- Tamil = 117,
- Tatar = 118,
- Telugu = 119,
- Thai = 120,
- Tibetan = 121,
- Tigrinya = 122,
- Tongan = 123,
- Tsonga = 124,
- Turkish = 125,
- Turkmen = 126,
- Tahitian = 127,
- Uighur = 128,
- Ukrainian = 129,
- Urdu = 130,
- Uzbek = 131,
- Vietnamese = 132,
- Volapuk = 133,
- Welsh = 134,
- Wolof = 135,
- Xhosa = 136,
- Yiddish = 137,
- Yoruba = 138,
- Zhuang = 139,
- Zulu = 140,
- NorwegianNynorsk = 141,
- Bosnian = 142,
- Divehi = 143,
- Manx = 144,
- Cornish = 145,
- Akan = 146,
- Konkani = 147,
- Ga = 148,
- Igbo = 149,
- Kamba = 150,
- Syriac = 151,
- Blin = 152,
- Geez = 153,
- Koro = 154,
- Sidamo = 155,
- Atsam = 156,
- Tigre = 157,
- Jju = 158,
- Friulian = 159,
- Venda = 160,
- Ewe = 161,
- Walamo = 162,
- Hawaiian = 163,
- Tyap = 164,
- Nyanja = 165,
- Filipino = 166,
- SwissGerman = 167,
- SichuanYi = 168,
- Kpelle = 169,
- LowGerman = 170,
- SouthNdebele = 171,
- NorthernSotho = 172,
- NorthernSami = 173,
- Taroko = 174,
- Gusii = 175,
- Taita = 176,
- Fulah = 177,
- Kikuyu = 178,
- Samburu = 179,
- Sena = 180,
- NorthNdebele = 181,
- Rombo = 182,
- Tachelhit = 183,
- Kabyle = 184,
- Nyankole = 185,
- Bena = 186,
- Vunjo = 187,
- Bambara = 188,
- Embu = 189,
- Cherokee = 190,
- Morisyen = 191,
- Makonde = 192,
- Langi = 193,
- Ganda = 194,
- Bemba = 195,
- Kabuverdianu = 196,
- Meru = 197,
- Kalenjin = 198,
- Nama = 199,
- Machame = 200,
- Colognian = 201,
- Masai = 202,
- Soga = 203,
- Luyia = 204,
- Asu = 205,
- Teso = 206,
- Saho = 207,
- KoyraChiini = 208,
- Rwa = 209,
- Luo = 210,
- Chiga = 211,
- CentralMoroccoTamazight = 212,
- KoyraboroSenni = 213,
- Shambala = 214,
- Bodo = 215,
- Avaric = 216,
- Chamorro = 217,
- Chechen = 218,
- Church = 219,
- Chuvash = 220,
- Cree = 221,
- Haitian = 222,
- Herero = 223,
- HiriMotu = 224,
- Kanuri = 225,
- Komi = 226,
- Kongo = 227,
- Kwanyama = 228,
- Limburgish = 229,
- LubaKatanga = 230,
- Luxembourgish = 231,
- Navaho = 232,
- Ndonga = 233,
- Ojibwa = 234,
- Pali = 235,
- Walloon = 236,
- Aghem = 237,
- Basaa = 238,
- Zarma = 239,
- Duala = 240,
- JolaFonyi = 241,
- Ewondo = 242,
- Bafia = 243,
- MakhuwaMeetto = 244,
- Mundang = 245,
- Kwasio = 246,
- Nuer = 247,
- Sakha = 248,
- Sangu = 249,
- CongoSwahili = 250,
- Tasawaq = 251,
- Vai = 252,
- Walser = 253,
- Yangben = 254,
- Avestan = 255,
- Asturian = 256,
- Ngomba = 257,
- Kako = 258,
- Meta = 259,
- Ngiemboon = 260,
- Aragonese = 261,
- Akkadian = 262,
- AncientEgyptian = 263,
- AncientGreek = 264,
- Aramaic = 265,
- Balinese = 266,
- Bamun = 267,
- BatakToba = 268,
- Buginese = 269,
- Buhid = 270,
- Carian = 271,
- Chakma = 272,
- ClassicalMandaic = 273,
- Coptic = 274,
- Dogri = 275,
- EasternCham = 276,
- EasternKayah = 277,
- Etruscan = 278,
- Gothic = 279,
- Hanunoo = 280,
- Ingush = 281,
- LargeFloweryMiao = 282,
- Lepcha = 283,
- Limbu = 284,
- Lisu = 285,
- Lu = 286,
- Lycian = 287,
- Lydian = 288,
- Mandingo = 289,
- Manipuri = 290,
- Meroitic = 291,
- NorthernThai = 292,
- OldIrish = 293,
- OldNorse = 294,
- OldPersian = 295,
- OldTurkish = 296,
- Pahlavi = 297,
- Parthian = 298,
- Phoenician = 299,
- PrakritLanguage = 300,
- Rejang = 301,
- Sabaean = 302,
- Samaritan = 303,
- Santali = 304,
- Saurashtra = 305,
- Sora = 306,
- Sylheti = 307,
- Tagbanwa = 308,
- TaiDam = 309,
- TaiNua = 310,
- Ugaritic = 311,
- Akoose = 312,
- Lakota = 313,
- StandardMoroccanTamazight = 314,
- Mapuche = 315,
- CentralKurdish = 316,
- LowerSorbian = 317,
- UpperSorbian = 318,
- Kenyang = 319,
- Mohawk = 320,
- Nko = 321,
- Prussian = 322,
- Kiche = 323,
- SouthernSami = 324,
- LuleSami = 325,
- InariSami = 326,
- SkoltSami = 327,
- Warlpiri = 328,
- ManichaeanMiddlePersian = 329,
- Mende = 330,
- AncientNorthArabian = 331,
- LinearA = 332,
- HmongNjua = 333,
- Ho = 334,
- Lezghian = 335,
- Bassa = 336,
- Mono = 337,
- TedimChin = 338,
- Maithili = 339,
- Ahom = 340,
- AmericanSignLanguage = 341,
- ArdhamagadhiPrakrit = 342,
- Bhojpuri = 343,
- HieroglyphicLuwian = 344,
- LiteraryChinese = 345,
- Mazanderani = 346,
- Mru = 347,
- Newari = 348,
- NorthernLuri = 349,
- Palauan = 350,
- Papiamento = 351,
- Saraiki = 352,
- TokelauLanguage = 353,
- TokPisin = 354,
- TuvaluLanguage = 355,
- UncodedLanguages = 356,
- Cantonese = 357,
- Osage = 358,
- Tangut = 359,
- Ido = 360,
- Lojban = 361,
- Sicilian = 362,
- SouthernKurdish = 363,
- WesternBalochi = 364,
- Cebuano = 365,
- Erzya = 366,
- Chickasaw = 367,
- Muscogee = 368,
- Silesian = 369,
+ Afar = 3,
+ Afrikaans = 4,
+ Aghem = 5,
+ Akan = 6,
+ Akkadian = 7,
+ Akoose = 8,
+ Albanian = 9,
+ AmericanSignLanguage = 10,
+ Amharic = 11,
+ AncientEgyptian = 12,
+ AncientGreek = 13,
+ Arabic = 14,
+ Aragonese = 15,
+ Aramaic = 16,
+ Armenian = 17,
+ Assamese = 18,
+ Asturian = 19,
+ Asu = 20,
+ Atsam = 21,
+ Avaric = 22,
+ Avestan = 23,
+ Aymara = 24,
+ Azerbaijani = 25,
+ Bafia = 26,
+ Balinese = 27,
+ Bambara = 28,
+ Bamun = 29,
+ Bangla = 30,
+ Basaa = 31,
+ Bashkir = 32,
+ Basque = 33,
+ BatakToba = 34,
+ Belarusian = 35,
+ Bemba = 36,
+ Bena = 37,
+ Bhojpuri = 38,
+ Bislama = 39,
+ Blin = 40,
+ Bodo = 41,
+ Bosnian = 42,
+ Breton = 43,
+ Buginese = 44,
+ Bulgarian = 45,
+ Burmese = 46,
+ Cantonese = 47,
+ Catalan = 48,
+ Cebuano = 49,
+ CentralAtlasTamazight = 50,
+ CentralKurdish = 51,
+ Chakma = 52,
+ Chamorro = 53,
+ Chechen = 54,
+ Cherokee = 55,
+ Chickasaw = 56,
+ Chiga = 57,
+ Chinese = 58,
+ Church = 59,
+ Chuvash = 60,
+ Colognian = 61,
+ Coptic = 62,
+ Cornish = 63,
+ Corsican = 64,
+ Cree = 65,
+ Croatian = 66,
+ Czech = 67,
+ Danish = 68,
+ Divehi = 69,
+ Dogri = 70,
+ Duala = 71,
+ Dutch = 72,
+ Dzongkha = 73,
+ Embu = 74,
+ English = 75,
+ Erzya = 76,
+ Esperanto = 77,
+ Estonian = 78,
+ Ewe = 79,
+ Ewondo = 80,
+ Faroese = 81,
+ Fijian = 82,
+ Filipino = 83,
+ Finnish = 84,
+ French = 85,
+ Friulian = 86,
+ Fulah = 87,
+ Gaelic = 88,
+ Ga = 89,
+ Galician = 90,
+ Ganda = 91,
+ Geez = 92,
+ Georgian = 93,
+ German = 94,
+ Gothic = 95,
+ Greek = 96,
+ Guarani = 97,
+ Gujarati = 98,
+ Gusii = 99,
+ Haitian = 100,
+ Hausa = 101,
+ Hawaiian = 102,
+ Hebrew = 103,
+ Herero = 104,
+ Hindi = 105,
+ HiriMotu = 106,
+ Hungarian = 107,
+ Icelandic = 108,
+ Ido = 109,
+ Igbo = 110,
+ InariSami = 111,
+ Indonesian = 112,
+ Ingush = 113,
+ Interlingua = 114,
+ Interlingue = 115,
+ Inuktitut = 116,
+ Inupiaq = 117,
+ Irish = 118,
+ Italian = 119,
+ Japanese = 120,
+ Javanese = 121,
+ Jju = 122,
+ JolaFonyi = 123,
+ Kabuverdianu = 124,
+ Kabyle = 125,
+ Kako = 126,
+ Kalaallisut = 127,
+ Kalenjin = 128,
+ Kamba = 129,
+ Kannada = 130,
+ Kanuri = 131,
+ Kashmiri = 132,
+ Kazakh = 133,
+ Kenyang = 134,
+ Khmer = 135,
+ Kiche = 136,
+ Kikuyu = 137,
+ Kinyarwanda = 138,
+ Komi = 139,
+ Kongo = 140,
+ Konkani = 141,
+ Korean = 142,
+ Koro = 143,
+ KoyraboroSenni = 144,
+ KoyraChiini = 145,
+ Kpelle = 146,
+ Kuanyama = 147,
+ Kurdish = 148,
+ Kwasio = 149,
+ Kyrgyz = 150,
+ Lakota = 151,
+ Langi = 152,
+ Lao = 153,
+ Latin = 154,
+ Latvian = 155,
+ Lezghian = 156,
+ Limburgish = 157,
+ Lingala = 158,
+ LiteraryChinese = 159,
+ Lithuanian = 160,
+ Lojban = 161,
+ LowerSorbian = 162,
+ LowGerman = 163,
+ LubaKatanga = 164,
+ LuleSami = 165,
+ Luo = 166,
+ Luxembourgish = 167,
+ Luyia = 168,
+ Macedonian = 169,
+ Machame = 170,
+ Maithili = 171,
+ MakhuwaMeetto = 172,
+ Makonde = 173,
+ Malagasy = 174,
+ Malayalam = 175,
+ Malay = 176,
+ Maltese = 177,
+ Mandingo = 178,
+ Manipuri = 179,
+ Manx = 180,
+ Maori = 181,
+ Mapuche = 182,
+ Marathi = 183,
+ Marshallese = 184,
+ Masai = 185,
+ Mazanderani = 186,
+ Mende = 187,
+ Meru = 188,
+ Meta = 189,
+ Mohawk = 190,
+ Mongolian = 191,
+ Morisyen = 192,
+ Mundang = 193,
+ Muscogee = 194,
+ Nama = 195,
+ NauruLanguage = 196,
+ Navajo = 197,
+ Ndonga = 198,
+ Nepali = 199,
+ Newari = 200,
+ Ngiemboon = 201,
+ Ngomba = 202,
+ NigerianPidgin = 203,
+ Nko = 204,
+ NorthernLuri = 205,
+ NorthernSami = 206,
+ NorthernSotho = 207,
+ NorthNdebele = 208,
+ NorwegianBokmal = 209,
+ NorwegianNynorsk = 210,
+ Nuer = 211,
+ Nyanja = 212,
+ Nyankole = 213,
+ Occitan = 214,
+ Odia = 215,
+ Ojibwa = 216,
+ OldIrish = 217,
+ OldNorse = 218,
+ OldPersian = 219,
+ Oromo = 220,
+ Osage = 221,
+ Ossetic = 222,
+ Pahlavi = 223,
+ Palauan = 224,
+ Pali = 225,
+ Papiamento = 226,
+ Pashto = 227,
+ Persian = 228,
+ Phoenician = 229,
+ Polish = 230,
+ Portuguese = 231,
+ Prussian = 232,
+ Punjabi = 233,
+ Quechua = 234,
+ Romanian = 235,
+ Romansh = 236,
+ Rombo = 237,
+ Rundi = 238,
+ Russian = 239,
+ Rwa = 240,
+ Saho = 241,
+ Sakha = 242,
+ Samburu = 243,
+ Samoan = 244,
+ Sango = 245,
+ Sangu = 246,
+ Sanskrit = 247,
+ Santali = 248,
+ Sardinian = 249,
+ Saurashtra = 250,
+ Sena = 251,
+ Serbian = 252,
+ Shambala = 253,
+ Shona = 254,
+ SichuanYi = 255,
+ Sicilian = 256,
+ Sidamo = 257,
+ Silesian = 258,
+ Sindhi = 259,
+ Sinhala = 260,
+ SkoltSami = 261,
+ Slovak = 262,
+ Slovenian = 263,
+ Soga = 264,
+ Somali = 265,
+ SouthernKurdish = 266,
+ SouthernSami = 267,
+ SouthernSotho = 268,
+ SouthNdebele = 269,
+ Spanish = 270,
+ StandardMoroccanTamazight = 271,
+ Sundanese = 272,
+ Swahili = 273,
+ Swati = 274,
+ Swedish = 275,
+ SwissGerman = 276,
+ Syriac = 277,
+ Tachelhit = 278,
+ Tahitian = 279,
+ TaiDam = 280,
+ Taita = 281,
+ Tajik = 282,
+ Tamil = 283,
+ Taroko = 284,
+ Tasawaq = 285,
+ Tatar = 286,
+ Telugu = 287,
+ Teso = 288,
+ Thai = 289,
+ Tibetan = 290,
+ Tigre = 291,
+ Tigrinya = 292,
+ TokelauLanguage = 293,
+ TokPisin = 294,
+ Tongan = 295,
+ Tsonga = 296,
+ Tswana = 297,
+ Turkish = 298,
+ Turkmen = 299,
+ TuvaluLanguage = 300,
+ Tyap = 301,
+ Ugaritic = 302,
+ Ukrainian = 303,
+ UpperSorbian = 304,
+ Urdu = 305,
+ Uyghur = 306,
+ Uzbek = 307,
+ Vai = 308,
+ Venda = 309,
+ Vietnamese = 310,
+ Volapuk = 311,
+ Vunjo = 312,
+ Walloon = 313,
+ Walser = 314,
+ Warlpiri = 315,
+ Welsh = 316,
+ WesternBalochi = 317,
+ WesternFrisian = 318,
+ Wolaytta = 319,
+ Wolof = 320,
+ Xhosa = 321,
+ Yangben = 322,
+ Yiddish = 323,
+ Yoruba = 324,
+ Zarma = 325,
+ Zhuang = 326,
+ Zulu = 327,
+ Kaingang = 328,
+ Nheengatu = 329,
+ Haryanvi = 330,
+ NorthernFrisian = 331,
+ Rajasthani = 332,
+ Moksha = 333,
+ TokiPona = 334,
+ Pijin = 335,
+ Obolo = 336,
+ Baluchi = 337,
+ Ligurian = 338,
+ Rohingya = 339,
+ Torwali = 340,
+ Anii = 341,
+ Kangri = 342,
+ Venetian = 343,
Afan = Oromo,
+ Bengali = Bangla,
Bhutani = Dzongkha,
Byelorussian = Belarusian,
Cambodian = Khmer,
+ CentralMoroccoTamazight = CentralAtlasTamazight,
Chewa = Nyanja,
Frisian = WesternFrisian,
+ Greenlandic = Kalaallisut,
+ Inupiak = Inupiaq,
+ Kirghiz = Kyrgyz,
Kurundi = Rundi,
- Moldavian = Romanian,
- Norwegian = NorwegianBokmal,
+ Kwanyama = Kuanyama,
+ Navaho = Navajo,
+ Oriya = Odia,
RhaetoRomance = Romansh,
- SerboCroatian = Serbian,
- Tagalog = Filipino,
- Twi = Akan,
- Uigur = Uighur,
+ Uighur = Uyghur,
+ Uigur = Uyghur,
+ Walamo = Wolaytta,
- LastLanguage = Silesian
+ LastLanguage = Venetian
};
- enum Script {
+ enum Script : ushort {
AnyScript = 0,
- ArabicScript = 1,
- CyrillicScript = 2,
- DeseretScript = 3,
- GurmukhiScript = 4,
- SimplifiedHanScript = 5,
- TraditionalHanScript = 6,
- LatinScript = 7,
- MongolianScript = 8,
- TifinaghScript = 9,
- ArmenianScript = 10,
- BengaliScript = 11,
- CherokeeScript = 12,
- DevanagariScript = 13,
- EthiopicScript = 14,
- GeorgianScript = 15,
- GreekScript = 16,
- GujaratiScript = 17,
- HebrewScript = 18,
- JapaneseScript = 19,
- KhmerScript = 20,
- KannadaScript = 21,
- KoreanScript = 22,
- LaoScript = 23,
- MalayalamScript = 24,
- MyanmarScript = 25,
- OriyaScript = 26,
- TamilScript = 27,
- TeluguScript = 28,
- ThaanaScript = 29,
- ThaiScript = 30,
- TibetanScript = 31,
- SinhalaScript = 32,
- SyriacScript = 33,
- YiScript = 34,
- VaiScript = 35,
- AvestanScript = 36,
- BalineseScript = 37,
- BamumScript = 38,
- BatakScript = 39,
- BopomofoScript = 40,
- BrahmiScript = 41,
- BugineseScript = 42,
- BuhidScript = 43,
- CanadianAboriginalScript = 44,
- CarianScript = 45,
- ChakmaScript = 46,
- ChamScript = 47,
- CopticScript = 48,
- CypriotScript = 49,
- EgyptianHieroglyphsScript = 50,
- FraserScript = 51,
- GlagoliticScript = 52,
- GothicScript = 53,
- HanScript = 54,
- HangulScript = 55,
- HanunooScript = 56,
- ImperialAramaicScript = 57,
- InscriptionalPahlaviScript = 58,
- InscriptionalParthianScript = 59,
- JavaneseScript = 60,
- KaithiScript = 61,
- KatakanaScript = 62,
- KayahLiScript = 63,
- KharoshthiScript = 64,
- LannaScript = 65,
- LepchaScript = 66,
- LimbuScript = 67,
- LinearBScript = 68,
- LycianScript = 69,
- LydianScript = 70,
- MandaeanScript = 71,
- MeiteiMayekScript = 72,
- MeroiticScript = 73,
- MeroiticCursiveScript = 74,
- NkoScript = 75,
- NewTaiLueScript = 76,
- OghamScript = 77,
- OlChikiScript = 78,
- OldItalicScript = 79,
- OldPersianScript = 80,
- OldSouthArabianScript = 81,
- OrkhonScript = 82,
- OsmanyaScript = 83,
- PhagsPaScript = 84,
- PhoenicianScript = 85,
- PollardPhoneticScript = 86,
- RejangScript = 87,
- RunicScript = 88,
- SamaritanScript = 89,
- SaurashtraScript = 90,
- SharadaScript = 91,
- ShavianScript = 92,
- SoraSompengScript = 93,
- CuneiformScript = 94,
- SundaneseScript = 95,
- SylotiNagriScript = 96,
- TagalogScript = 97,
- TagbanwaScript = 98,
- TaiLeScript = 99,
- TaiVietScript = 100,
- TakriScript = 101,
- UgariticScript = 102,
- BrailleScript = 103,
- HiraganaScript = 104,
- CaucasianAlbanianScript = 105,
- BassaVahScript = 106,
- DuployanScript = 107,
- ElbasanScript = 108,
- GranthaScript = 109,
- PahawhHmongScript = 110,
- KhojkiScript = 111,
- LinearAScript = 112,
- MahajaniScript = 113,
- ManichaeanScript = 114,
- MendeKikakuiScript = 115,
- ModiScript = 116,
- MroScript = 117,
- OldNorthArabianScript = 118,
- NabataeanScript = 119,
- PalmyreneScript = 120,
- PauCinHauScript = 121,
- OldPermicScript = 122,
- PsalterPahlaviScript = 123,
- SiddhamScript = 124,
- KhudawadiScript = 125,
- TirhutaScript = 126,
- VarangKshitiScript = 127,
- AhomScript = 128,
- AnatolianHieroglyphsScript = 129,
- HatranScript = 130,
- MultaniScript = 131,
- OldHungarianScript = 132,
- SignWritingScript = 133,
- AdlamScript = 134,
- BhaiksukiScript = 135,
- MarchenScript = 136,
- NewaScript = 137,
- OsageScript = 138,
- TangutScript = 139,
- HanWithBopomofoScript = 140,
- JamoScript = 141,
+ AdlamScript = 1,
+ AhomScript = 2,
+ AnatolianHieroglyphsScript = 3,
+ ArabicScript = 4,
+ ArmenianScript = 5,
+ AvestanScript = 6,
+ BalineseScript = 7,
+ BamumScript = 8,
+ BanglaScript = 9,
+ BassaVahScript = 10,
+ BatakScript = 11,
+ BhaiksukiScript = 12,
+ BopomofoScript = 13,
+ BrahmiScript = 14,
+ BrailleScript = 15,
+ BugineseScript = 16,
+ BuhidScript = 17,
+ CanadianAboriginalScript = 18,
+ CarianScript = 19,
+ CaucasianAlbanianScript = 20,
+ ChakmaScript = 21,
+ ChamScript = 22,
+ CherokeeScript = 23,
+ CopticScript = 24,
+ CuneiformScript = 25,
+ CypriotScript = 26,
+ CyrillicScript = 27,
+ DeseretScript = 28,
+ DevanagariScript = 29,
+ DuployanScript = 30,
+ EgyptianHieroglyphsScript = 31,
+ ElbasanScript = 32,
+ EthiopicScript = 33,
+ FraserScript = 34,
+ GeorgianScript = 35,
+ GlagoliticScript = 36,
+ GothicScript = 37,
+ GranthaScript = 38,
+ GreekScript = 39,
+ GujaratiScript = 40,
+ GurmukhiScript = 41,
+ HangulScript = 42,
+ HanScript = 43,
+ HanunooScript = 44,
+ HanWithBopomofoScript = 45,
+ HatranScript = 46,
+ HebrewScript = 47,
+ HiraganaScript = 48,
+ ImperialAramaicScript = 49,
+ InscriptionalPahlaviScript = 50,
+ InscriptionalParthianScript = 51,
+ JamoScript = 52,
+ JapaneseScript = 53,
+ JavaneseScript = 54,
+ KaithiScript = 55,
+ KannadaScript = 56,
+ KatakanaScript = 57,
+ KayahLiScript = 58,
+ KharoshthiScript = 59,
+ KhmerScript = 60,
+ KhojkiScript = 61,
+ KhudawadiScript = 62,
+ KoreanScript = 63,
+ LannaScript = 64,
+ LaoScript = 65,
+ LatinScript = 66,
+ LepchaScript = 67,
+ LimbuScript = 68,
+ LinearAScript = 69,
+ LinearBScript = 70,
+ LycianScript = 71,
+ LydianScript = 72,
+ MahajaniScript = 73,
+ MalayalamScript = 74,
+ MandaeanScript = 75,
+ ManichaeanScript = 76,
+ MarchenScript = 77,
+ MeiteiMayekScript = 78,
+ MendeScript = 79,
+ MeroiticCursiveScript = 80,
+ MeroiticScript = 81,
+ ModiScript = 82,
+ MongolianScript = 83,
+ MroScript = 84,
+ MultaniScript = 85,
+ MyanmarScript = 86,
+ NabataeanScript = 87,
+ NewaScript = 88,
+ NewTaiLueScript = 89,
+ NkoScript = 90,
+ OdiaScript = 91,
+ OghamScript = 92,
+ OlChikiScript = 93,
+ OldHungarianScript = 94,
+ OldItalicScript = 95,
+ OldNorthArabianScript = 96,
+ OldPermicScript = 97,
+ OldPersianScript = 98,
+ OldSouthArabianScript = 99,
+ OrkhonScript = 100,
+ OsageScript = 101,
+ OsmanyaScript = 102,
+ PahawhHmongScript = 103,
+ PalmyreneScript = 104,
+ PauCinHauScript = 105,
+ PhagsPaScript = 106,
+ PhoenicianScript = 107,
+ PollardPhoneticScript = 108,
+ PsalterPahlaviScript = 109,
+ RejangScript = 110,
+ RunicScript = 111,
+ SamaritanScript = 112,
+ SaurashtraScript = 113,
+ SharadaScript = 114,
+ ShavianScript = 115,
+ SiddhamScript = 116,
+ SignWritingScript = 117,
+ SimplifiedHanScript = 118,
+ SinhalaScript = 119,
+ SoraSompengScript = 120,
+ SundaneseScript = 121,
+ SylotiNagriScript = 122,
+ SyriacScript = 123,
+ TagalogScript = 124,
+ TagbanwaScript = 125,
+ TaiLeScript = 126,
+ TaiVietScript = 127,
+ TakriScript = 128,
+ TamilScript = 129,
+ TangutScript = 130,
+ TeluguScript = 131,
+ ThaanaScript = 132,
+ ThaiScript = 133,
+ TibetanScript = 134,
+ TifinaghScript = 135,
+ TirhutaScript = 136,
+ TraditionalHanScript = 137,
+ UgariticScript = 138,
+ VaiScript = 139,
+ VarangKshitiScript = 140,
+ YiScript = 141,
+ HanifiScript = 142,
+ BengaliScript = BanglaScript,
+ MendeKikakuiScript = MendeScript,
+ OriyaScript = OdiaScript,
SimplifiedChineseScript = SimplifiedHanScript,
TraditionalChineseScript = TraditionalHanScript,
- LastScript = JamoScript
+ LastScript = HanifiScript
};
- enum Country {
- AnyCountry = 0,
+ // ### Qt 7: Rename to Territory
+ enum Country : ushort {
+ AnyTerritory = 0,
Afghanistan = 1,
- Albania = 2,
- Algeria = 3,
- AmericanSamoa = 4,
- Andorra = 5,
- Angola = 6,
- Anguilla = 7,
- Antarctica = 8,
- AntiguaAndBarbuda = 9,
- Argentina = 10,
- Armenia = 11,
- Aruba = 12,
- Australia = 13,
- Austria = 14,
- Azerbaijan = 15,
- Bahamas = 16,
- Bahrain = 17,
- Bangladesh = 18,
- Barbados = 19,
- Belarus = 20,
- Belgium = 21,
- Belize = 22,
- Benin = 23,
- Bermuda = 24,
- Bhutan = 25,
- Bolivia = 26,
- BosniaAndHerzegowina = 27,
- Botswana = 28,
- BouvetIsland = 29,
- Brazil = 30,
- BritishIndianOceanTerritory = 31,
- Brunei = 32,
- Bulgaria = 33,
- BurkinaFaso = 34,
- Burundi = 35,
- Cambodia = 36,
- Cameroon = 37,
- Canada = 38,
- CapeVerde = 39,
- CaymanIslands = 40,
- CentralAfricanRepublic = 41,
- Chad = 42,
- Chile = 43,
- China = 44,
- ChristmasIsland = 45,
- CocosIslands = 46,
- Colombia = 47,
- Comoros = 48,
- CongoKinshasa = 49,
- CongoBrazzaville = 50,
- CookIslands = 51,
- CostaRica = 52,
- IvoryCoast = 53,
- Croatia = 54,
- Cuba = 55,
- Cyprus = 56,
- CzechRepublic = 57,
- Denmark = 58,
- Djibouti = 59,
- Dominica = 60,
- DominicanRepublic = 61,
- EastTimor = 62,
- Ecuador = 63,
- Egypt = 64,
- ElSalvador = 65,
- EquatorialGuinea = 66,
- Eritrea = 67,
- Estonia = 68,
- Ethiopia = 69,
- FalklandIslands = 70,
- FaroeIslands = 71,
- Fiji = 72,
- Finland = 73,
- France = 74,
- Guernsey = 75,
- FrenchGuiana = 76,
- FrenchPolynesia = 77,
- FrenchSouthernTerritories = 78,
- Gabon = 79,
- Gambia = 80,
- Georgia = 81,
- Germany = 82,
- Ghana = 83,
- Gibraltar = 84,
- Greece = 85,
- Greenland = 86,
- Grenada = 87,
- Guadeloupe = 88,
- Guam = 89,
- Guatemala = 90,
- Guinea = 91,
- GuineaBissau = 92,
- Guyana = 93,
- Haiti = 94,
- HeardAndMcDonaldIslands = 95,
- Honduras = 96,
- HongKong = 97,
- Hungary = 98,
- Iceland = 99,
- India = 100,
- Indonesia = 101,
- Iran = 102,
- Iraq = 103,
- Ireland = 104,
- Israel = 105,
- Italy = 106,
- Jamaica = 107,
- Japan = 108,
- Jordan = 109,
- Kazakhstan = 110,
- Kenya = 111,
- Kiribati = 112,
- NorthKorea = 113,
- SouthKorea = 114,
- Kuwait = 115,
- Kyrgyzstan = 116,
- Laos = 117,
- Latvia = 118,
- Lebanon = 119,
- Lesotho = 120,
- Liberia = 121,
- Libya = 122,
- Liechtenstein = 123,
- Lithuania = 124,
- Luxembourg = 125,
- Macau = 126,
- Macedonia = 127,
- Madagascar = 128,
- Malawi = 129,
- Malaysia = 130,
- Maldives = 131,
- Mali = 132,
- Malta = 133,
- MarshallIslands = 134,
- Martinique = 135,
- Mauritania = 136,
- Mauritius = 137,
- Mayotte = 138,
- Mexico = 139,
- Micronesia = 140,
- Moldova = 141,
- Monaco = 142,
- Mongolia = 143,
- Montserrat = 144,
- Morocco = 145,
- Mozambique = 146,
- Myanmar = 147,
- Namibia = 148,
- NauruCountry = 149,
- Nepal = 150,
- Netherlands = 151,
- CuraSao = 152,
- NewCaledonia = 153,
- NewZealand = 154,
- Nicaragua = 155,
- Niger = 156,
- Nigeria = 157,
- Niue = 158,
- NorfolkIsland = 159,
- NorthernMarianaIslands = 160,
- Norway = 161,
- Oman = 162,
- Pakistan = 163,
- Palau = 164,
- PalestinianTerritories = 165,
- Panama = 166,
- PapuaNewGuinea = 167,
- Paraguay = 168,
- Peru = 169,
- Philippines = 170,
- Pitcairn = 171,
- Poland = 172,
- Portugal = 173,
- PuertoRico = 174,
- Qatar = 175,
- Reunion = 176,
- Romania = 177,
- Russia = 178,
- Rwanda = 179,
- SaintKittsAndNevis = 180,
- SaintLucia = 181,
- SaintVincentAndTheGrenadines = 182,
- Samoa = 183,
- SanMarino = 184,
- SaoTomeAndPrincipe = 185,
- SaudiArabia = 186,
- Senegal = 187,
- Seychelles = 188,
- SierraLeone = 189,
- Singapore = 190,
- Slovakia = 191,
- Slovenia = 192,
- SolomonIslands = 193,
- Somalia = 194,
- SouthAfrica = 195,
- SouthGeorgiaAndTheSouthSandwichIslands = 196,
- Spain = 197,
- SriLanka = 198,
- SaintHelena = 199,
+ AlandIslands = 2,
+ Albania = 3,
+ Algeria = 4,
+ AmericanSamoa = 5,
+ Andorra = 6,
+ Angola = 7,
+ Anguilla = 8,
+ Antarctica = 9,
+ AntiguaAndBarbuda = 10,
+ Argentina = 11,
+ Armenia = 12,
+ Aruba = 13,
+ AscensionIsland = 14,
+ Australia = 15,
+ Austria = 16,
+ Azerbaijan = 17,
+ Bahamas = 18,
+ Bahrain = 19,
+ Bangladesh = 20,
+ Barbados = 21,
+ Belarus = 22,
+ Belgium = 23,
+ Belize = 24,
+ Benin = 25,
+ Bermuda = 26,
+ Bhutan = 27,
+ Bolivia = 28,
+ BosniaAndHerzegovina = 29,
+ Botswana = 30,
+ BouvetIsland = 31,
+ Brazil = 32,
+ BritishIndianOceanTerritory = 33,
+ BritishVirginIslands = 34,
+ Brunei = 35,
+ Bulgaria = 36,
+ BurkinaFaso = 37,
+ Burundi = 38,
+ Cambodia = 39,
+ Cameroon = 40,
+ Canada = 41,
+ CanaryIslands = 42,
+ CapeVerde = 43,
+ CaribbeanNetherlands = 44,
+ CaymanIslands = 45,
+ CentralAfricanRepublic = 46,
+ CeutaAndMelilla = 47,
+ Chad = 48,
+ Chile = 49,
+ China = 50,
+ ChristmasIsland = 51,
+ ClippertonIsland = 52,
+ CocosIslands = 53,
+ Colombia = 54,
+ Comoros = 55,
+ CongoBrazzaville = 56,
+ CongoKinshasa = 57,
+ CookIslands = 58,
+ CostaRica = 59,
+ Croatia = 60,
+ Cuba = 61,
+ Curacao = 62,
+ Cyprus = 63,
+ Czechia = 64,
+ Denmark = 65,
+ DiegoGarcia = 66,
+ Djibouti = 67,
+ Dominica = 68,
+ DominicanRepublic = 69,
+ Ecuador = 70,
+ Egypt = 71,
+ ElSalvador = 72,
+ EquatorialGuinea = 73,
+ Eritrea = 74,
+ Estonia = 75,
+ Eswatini = 76,
+ Ethiopia = 77,
+ Europe = 78,
+ EuropeanUnion = 79,
+ FalklandIslands = 80,
+ FaroeIslands = 81,
+ Fiji = 82,
+ Finland = 83,
+ France = 84,
+ FrenchGuiana = 85,
+ FrenchPolynesia = 86,
+ FrenchSouthernTerritories = 87,
+ Gabon = 88,
+ Gambia = 89,
+ Georgia = 90,
+ Germany = 91,
+ Ghana = 92,
+ Gibraltar = 93,
+ Greece = 94,
+ Greenland = 95,
+ Grenada = 96,
+ Guadeloupe = 97,
+ Guam = 98,
+ Guatemala = 99,
+ Guernsey = 100,
+ GuineaBissau = 101,
+ Guinea = 102,
+ Guyana = 103,
+ Haiti = 104,
+ HeardAndMcDonaldIslands = 105,
+ Honduras = 106,
+ HongKong = 107,
+ Hungary = 108,
+ Iceland = 109,
+ India = 110,
+ Indonesia = 111,
+ Iran = 112,
+ Iraq = 113,
+ Ireland = 114,
+ IsleOfMan = 115,
+ Israel = 116,
+ Italy = 117,
+ IvoryCoast = 118,
+ Jamaica = 119,
+ Japan = 120,
+ Jersey = 121,
+ Jordan = 122,
+ Kazakhstan = 123,
+ Kenya = 124,
+ Kiribati = 125,
+ Kosovo = 126,
+ Kuwait = 127,
+ Kyrgyzstan = 128,
+ Laos = 129,
+ LatinAmerica = 130,
+ Latvia = 131,
+ Lebanon = 132,
+ Lesotho = 133,
+ Liberia = 134,
+ Libya = 135,
+ Liechtenstein = 136,
+ Lithuania = 137,
+ Luxembourg = 138,
+ Macao = 139,
+ Macedonia = 140,
+ Madagascar = 141,
+ Malawi = 142,
+ Malaysia = 143,
+ Maldives = 144,
+ Mali = 145,
+ Malta = 146,
+ MarshallIslands = 147,
+ Martinique = 148,
+ Mauritania = 149,
+ Mauritius = 150,
+ Mayotte = 151,
+ Mexico = 152,
+ Micronesia = 153,
+ Moldova = 154,
+ Monaco = 155,
+ Mongolia = 156,
+ Montenegro = 157,
+ Montserrat = 158,
+ Morocco = 159,
+ Mozambique = 160,
+ Myanmar = 161,
+ Namibia = 162,
+ NauruTerritory = 163,
+ Nepal = 164,
+ Netherlands = 165,
+ NewCaledonia = 166,
+ NewZealand = 167,
+ Nicaragua = 168,
+ Nigeria = 169,
+ Niger = 170,
+ Niue = 171,
+ NorfolkIsland = 172,
+ NorthernMarianaIslands = 173,
+ NorthKorea = 174,
+ Norway = 175,
+ Oman = 176,
+ OutlyingOceania = 177,
+ Pakistan = 178,
+ Palau = 179,
+ PalestinianTerritories = 180,
+ Panama = 181,
+ PapuaNewGuinea = 182,
+ Paraguay = 183,
+ Peru = 184,
+ Philippines = 185,
+ Pitcairn = 186,
+ Poland = 187,
+ Portugal = 188,
+ PuertoRico = 189,
+ Qatar = 190,
+ Reunion = 191,
+ Romania = 192,
+ Russia = 193,
+ Rwanda = 194,
+ SaintBarthelemy = 195,
+ SaintHelena = 196,
+ SaintKittsAndNevis = 197,
+ SaintLucia = 198,
+ SaintMartin = 199,
SaintPierreAndMiquelon = 200,
- Sudan = 201,
- Suriname = 202,
- SvalbardAndJanMayenIslands = 203,
- Swaziland = 204,
- Sweden = 205,
- Switzerland = 206,
- Syria = 207,
- Taiwan = 208,
- Tajikistan = 209,
- Tanzania = 210,
- Thailand = 211,
- Togo = 212,
- TokelauCountry = 213,
- Tonga = 214,
- TrinidadAndTobago = 215,
- Tunisia = 216,
- Turkey = 217,
- Turkmenistan = 218,
- TurksAndCaicosIslands = 219,
- TuvaluCountry = 220,
- Uganda = 221,
- Ukraine = 222,
- UnitedArabEmirates = 223,
- UnitedKingdom = 224,
- UnitedStates = 225,
- UnitedStatesMinorOutlyingIslands = 226,
- Uruguay = 227,
- Uzbekistan = 228,
- Vanuatu = 229,
- VaticanCityState = 230,
- Venezuela = 231,
- Vietnam = 232,
- BritishVirginIslands = 233,
- UnitedStatesVirginIslands = 234,
- WallisAndFutunaIslands = 235,
- WesternSahara = 236,
- Yemen = 237,
- CanaryIslands = 238,
- Zambia = 239,
- Zimbabwe = 240,
- ClippertonIsland = 241,
- Montenegro = 242,
- Serbia = 243,
- SaintBarthelemy = 244,
- SaintMartin = 245,
- LatinAmerica = 246,
- AscensionIsland = 247,
- AlandIslands = 248,
- DiegoGarcia = 249,
- CeutaAndMelilla = 250,
- IsleOfMan = 251,
- Jersey = 252,
- TristanDaCunha = 253,
- SouthSudan = 254,
- Bonaire = 255,
- SintMaarten = 256,
- Kosovo = 257,
- EuropeanUnion = 258,
- OutlyingOceania = 259,
- World = 260,
- Europe = 261,
+ SaintVincentAndGrenadines = 201,
+ Samoa = 202,
+ SanMarino = 203,
+ SaoTomeAndPrincipe = 204,
+ SaudiArabia = 205,
+ Senegal = 206,
+ Serbia = 207,
+ Seychelles = 208,
+ SierraLeone = 209,
+ Singapore = 210,
+ SintMaarten = 211,
+ Slovakia = 212,
+ Slovenia = 213,
+ SolomonIslands = 214,
+ Somalia = 215,
+ SouthAfrica = 216,
+ SouthGeorgiaAndSouthSandwichIslands = 217,
+ SouthKorea = 218,
+ SouthSudan = 219,
+ Spain = 220,
+ SriLanka = 221,
+ Sudan = 222,
+ Suriname = 223,
+ SvalbardAndJanMayen = 224,
+ Sweden = 225,
+ Switzerland = 226,
+ Syria = 227,
+ Taiwan = 228,
+ Tajikistan = 229,
+ Tanzania = 230,
+ Thailand = 231,
+ TimorLeste = 232,
+ Togo = 233,
+ TokelauTerritory = 234,
+ Tonga = 235,
+ TrinidadAndTobago = 236,
+ TristanDaCunha = 237,
+ Tunisia = 238,
+ Turkey = 239,
+ Turkmenistan = 240,
+ TurksAndCaicosIslands = 241,
+ TuvaluTerritory = 242,
+ Uganda = 243,
+ Ukraine = 244,
+ UnitedArabEmirates = 245,
+ UnitedKingdom = 246,
+ UnitedStatesOutlyingIslands = 247,
+ UnitedStates = 248,
+ UnitedStatesVirginIslands = 249,
+ Uruguay = 250,
+ Uzbekistan = 251,
+ Vanuatu = 252,
+ VaticanCity = 253,
+ Venezuela = 254,
+ Vietnam = 255,
+ WallisAndFutuna = 256,
+ WesternSahara = 257,
+ World = 258,
+ Yemen = 259,
+ Zambia = 260,
+ Zimbabwe = 261,
+ AnyCountry = AnyTerritory,
+ Bonaire = CaribbeanNetherlands,
+ BosniaAndHerzegowina = BosniaAndHerzegovina,
+ CuraSao = Curacao,
+ CzechRepublic = Czechia,
DemocraticRepublicOfCongo = CongoKinshasa,
DemocraticRepublicOfKorea = NorthKorea,
+ EastTimor = TimorLeste,
LatinAmericaAndTheCaribbean = LatinAmerica,
+ Macau = Macao,
+ NauruCountry = NauruTerritory,
PeoplesRepublicOfCongo = CongoBrazzaville,
RepublicOfKorea = SouthKorea,
RussianFederation = Russia,
+ SaintVincentAndTheGrenadines = SaintVincentAndGrenadines,
+ SouthGeorgiaAndTheSouthSandwichIslands = SouthGeorgiaAndSouthSandwichIslands,
+ SvalbardAndJanMayenIslands = SvalbardAndJanMayen,
+ Swaziland = Eswatini,
SyrianArabRepublic = Syria,
- Tokelau = TokelauCountry,
- Tuvalu = TuvaluCountry,
+ TokelauCountry = TokelauTerritory,
+ TuvaluCountry = TuvaluTerritory,
+ UnitedStatesMinorOutlyingIslands = UnitedStatesOutlyingIslands,
+ VaticanCityState = VaticanCity,
+ WallisAndFutunaIslands = WallisAndFutuna,
- LastCountry = Europe
+ LastTerritory = Zimbabwe,
+ LastCountry = LastTerritory
};
// GENERATED PART ENDS HERE
+ using Territory = Country; // ### Qt 7: reverse
+
Q_ENUM(Language)
Q_ENUM(Country)
Q_ENUM(Script)
@@ -906,6 +873,7 @@ public:
Q_ENUM(MeasurementSystem)
enum FormatType { LongFormat, ShortFormat, NarrowFormat };
+ Q_ENUM(FormatType)
enum NumberOption {
DefaultNumberOptions = 0x0,
OmitGroupSeparator = 0x01,
@@ -916,16 +884,21 @@ public:
RejectTrailingZeroesAfterDot = 0x20
};
Q_DECLARE_FLAGS(NumberOptions, NumberOption)
+ Q_FLAG(NumberOptions)
enum FloatingPointPrecisionOption {
FloatingPointShortest = -128
};
+ enum class TagSeparator : char { Dash = '-', Underscore = '_' };
+ Q_ENUM(TagSeparator)
+
enum CurrencySymbolFormat {
CurrencyIsoCode,
CurrencySymbol,
CurrencyDisplayName
};
+ Q_ENUM(CurrencySymbolFormat)
enum DataSizeFormat {
// Single-bit values, for internal use.
@@ -941,38 +914,61 @@ public:
Q_FLAG(DataSizeFormats)
QLocale();
+ QT_CORE_INLINE_SINCE(6, 4)
explicit QLocale(const QString &name);
- QLocale(Language language, Country country = AnyCountry);
- QLocale(Language language, Script script, Country country);
- QLocale(const QLocale &other);
- QLocale &operator=(QLocale &&other) noexcept { swap(other); return *this; }
- QLocale &operator=(const QLocale &other);
+ explicit QLocale(QStringView name);
+ QLocale(Language language, Territory territory);
+ QLocale(Language language, Script script = AnyScript, Territory territory = AnyTerritory);
+ QLocale(const QLocale &other) noexcept;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QLocale)
+ QLocale &operator=(const QLocale &other) noexcept;
~QLocale();
- void swap(QLocale &other) noexcept { qSwap(d, other.d); }
+ void swap(QLocale &other) noexcept { d.swap(other.d); }
Language language() const;
Script script() const;
+ Territory territory() const;
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use territory() instead")
Country country() const;
- QString name() const;
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ QString name() const;
QString bcp47Name() const;
+#endif
+ QString name(TagSeparator separator = TagSeparator::Underscore) const;
+ QString bcp47Name(TagSeparator separator = TagSeparator::Dash) const;
+
QString nativeLanguageName() const;
+ QString nativeTerritoryName() const;
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use nativeTerritoryName() instead")
QString nativeCountryName() const;
-
-#if QT_STRINGVIEW_LEVEL < 2
- short toShort(const QString &s, bool *ok = nullptr) const;
- ushort toUShort(const QString &s, bool *ok = nullptr) const;
- int toInt(const QString &s, bool *ok = nullptr) const;
- uint toUInt(const QString &s, bool *ok = nullptr) const;
- long toLong(const QString &s, bool *ok = nullptr) const;
- ulong toULong(const QString &s, bool *ok = nullptr) const;
- qlonglong toLongLong(const QString &s, bool *ok = nullptr) const;
- qulonglong toULongLong(const QString &s, bool *ok = nullptr) const;
- float toFloat(const QString &s, bool *ok = nullptr) const;
- double toDouble(const QString &s, bool *ok = nullptr) const;
#endif
+ short toShort(const QString &s, bool *ok = nullptr) const
+ { return toShort(qToStringViewIgnoringNull(s), ok); }
+ ushort toUShort(const QString &s, bool *ok = nullptr) const
+ { return toUShort(qToStringViewIgnoringNull(s), ok); }
+ int toInt(const QString &s, bool *ok = nullptr) const
+ { return toInt(qToStringViewIgnoringNull(s), ok); }
+ uint toUInt(const QString &s, bool *ok = nullptr) const
+ { return toUInt(qToStringViewIgnoringNull(s), ok); }
+ long toLong(const QString &s, bool *ok = nullptr) const
+ { return toLong(qToStringViewIgnoringNull(s), ok); }
+ ulong toULong(const QString &s, bool *ok = nullptr) const
+ { return toULong(qToStringViewIgnoringNull(s), ok); }
+ qlonglong toLongLong(const QString &s, bool *ok = nullptr) const
+ { return toLongLong(qToStringViewIgnoringNull(s), ok); }
+ qulonglong toULongLong(const QString &s, bool *ok = nullptr) const
+ { return toULongLong(qToStringViewIgnoringNull(s), ok); }
+ float toFloat(const QString &s, bool *ok = nullptr) const
+ { return toFloat(qToStringViewIgnoringNull(s), ok); }
+ double toDouble(const QString &s, bool *ok = nullptr) const
+ { return toDouble(qToStringViewIgnoringNull(s), ok); }
+
short toShort(QStringView s, bool *ok = nullptr) const;
ushort toUShort(QStringView s, bool *ok = nullptr) const;
int toInt(QStringView s, bool *ok = nullptr) const;
@@ -986,56 +982,73 @@ public:
QString toString(qlonglong i) const;
QString toString(qulonglong i) const;
- inline QString toString(long i) const;
- inline QString toString(ulong i) const;
- inline QString toString(short i) const;
- inline QString toString(ushort i) const;
- inline QString toString(int i) const;
- inline QString toString(uint i) const;
- QString toString(double i, char f = 'g', int prec = 6) const;
- inline QString toString(float i, char f = 'g', int prec = 6) const;
+ QString toString(long i) const { return toString(qlonglong(i)); }
+ QString toString(ulong i) const { return toString(qulonglong(i)); }
+ QString toString(short i) const { return toString(qlonglong(i)); }
+ QString toString(ushort i) const { return toString(qulonglong(i)); }
+ QString toString(int i) const { return toString(qlonglong(i)); }
+ QString toString(uint i) const { return toString(qulonglong(i)); }
+ QString toString(double f, char format = 'g', int precision = 6) const;
+ QString toString(float f, char format = 'g', int precision = 6) const
+ { return toString(double(f), format, precision); }
-#if QT_STRINGVIEW_LEVEL < 2
- QString toString(QDate date, const QString &formatStr) const;
- QString toString(QTime time, const QString &formatStr) const;
- QString toString(const QDateTime &dateTime, const QString &format) const;
-#endif
- QString toString(QDate date, QStringView formatStr) const;
- QString toString(QTime time, QStringView formatStr) const;
+ // (Can't inline first two: passing by value doesn't work when only forward-declared.)
+ QString toString(QDate date, const QString &format) const;
+ QString toString(QTime time, const QString &format) const;
+ QString toString(const QDateTime &dateTime, const QString &format) const
+ { return toString(dateTime, qToStringViewIgnoringNull(format)); }
+ QString toString(QDate date, QStringView format) const;
+ QString toString(QTime time, QStringView format) const;
QString toString(const QDateTime &dateTime, QStringView format) const;
QString toString(QDate date, FormatType format = LongFormat) const;
QString toString(QTime time, FormatType format = LongFormat) const;
QString toString(const QDateTime &dateTime, FormatType format = LongFormat) const;
- /* Removing default value for `format' is done intentionally,
- * after all tests we will remove non-calendar-aware version of these functions,
- * and add a default value for both calendar instance, and format
+ /* We can't pass a default for QCalendar (its declaration mentions
+ * QLocale::FormatType, so it has to #include this header, which thus can't
+ * #include its, so we can't instantiate QCalendar() as default). This
+ * precludes any default for format, too.
*/
- QString toString(QDate date, QStringView formatStr, QCalendar cal) const;
+ QString toString(QDate date, QStringView format, QCalendar cal) const;
QString toString(QDate date, FormatType format, QCalendar cal) const;
QString toString(const QDateTime &dateTime, FormatType format, QCalendar cal) const;
- QString toString(const QDateTime &dateTime, QStringView formatStr, QCalendar cal) const;
+ QString toString(const QDateTime &dateTime, QStringView format, QCalendar cal) const;
QString dateFormat(FormatType format = LongFormat) const;
QString timeFormat(FormatType format = LongFormat) const;
QString dateTimeFormat(FormatType format = LongFormat) const;
+ // QCalendar's header has to #include QLocale's, preventing the reverse, so
+ // QCalendar parameters can't have defaults here.
#if QT_CONFIG(datestring)
- QDate toDate(const QString &string, FormatType = LongFormat) const;
QTime toTime(const QString &string, FormatType = LongFormat) const;
- QDateTime toDateTime(const QString &string, FormatType format = LongFormat) const;
- QDate toDate(const QString &string, const QString &format) const;
QTime toTime(const QString &string, const QString &format) const;
+# if QT_CORE_REMOVED_SINCE(6, 7)
+ QDate toDate(const QString &string, FormatType = LongFormat) const;
+ QDate toDate(const QString &string, const QString &format) const;
+ QDateTime toDateTime(const QString &string, FormatType format = LongFormat) const;
QDateTime toDateTime(const QString &string, const QString &format) const;
// Calendar-aware API
QDate toDate(const QString &string, FormatType format, QCalendar cal) const;
- QDateTime toDateTime(const QString &string, FormatType format, QCalendar cal) const;
QDate toDate(const QString &string, const QString &format, QCalendar cal) const;
+ QDateTime toDateTime(const QString &string, FormatType format, QCalendar cal) const;
QDateTime toDateTime(const QString &string, const QString &format, QCalendar cal) const;
-# if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Calendar is ignored when parsing times")
- QTime toTime(const QString &string, FormatType format, QCalendar cal) const;
- QT_DEPRECATED_X("Calendar is ignored when parsing times")
- QTime toTime(const QString &string, const QString &format, QCalendar cal) const;
-# endif // 5.15
+# endif
+ QDate toDate(const QString &string, FormatType = LongFormat,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ QDate toDate(const QString &string, const QString &format,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ QDateTime toDateTime(const QString &string, FormatType format = LongFormat,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ QDateTime toDateTime(const QString &string, const QString &format,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ // Calendar-aware API
+ QDate toDate(const QString &string, FormatType format, QCalendar cal,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ QDate toDate(const QString &string, const QString &format, QCalendar cal,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ QDateTime toDateTime(const QString &string, FormatType format, QCalendar cal,
+ int baseYear = DefaultTwoDigitBaseYear) const;
+ QDateTime toDateTime(const QString &string, const QString &format, QCalendar cal,
+ int baseYear = DefaultTwoDigitBaseYear) const;
#endif
QString decimalPoint() const;
@@ -1067,48 +1080,84 @@ public:
QString currencySymbol(CurrencySymbolFormat = CurrencySymbol) const;
QString toCurrencyString(qlonglong, const QString &symbol = QString()) const;
QString toCurrencyString(qulonglong, const QString &symbol = QString()) const;
- inline QString toCurrencyString(short, const QString &symbol = QString()) const;
- inline QString toCurrencyString(ushort, const QString &symbol = QString()) const;
- inline QString toCurrencyString(int, const QString &symbol = QString()) const;
- inline QString toCurrencyString(uint, const QString &symbol = QString()) const;
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ QString toCurrencyString(short i, const QString &symbol = QString()) const
+ { return toCurrencyString(qlonglong(i), symbol); }
+ QString toCurrencyString(ushort i, const QString &symbol = QString()) const
+ { return toCurrencyString(qulonglong(i), symbol); }
+ QString toCurrencyString(int i, const QString &symbol = QString()) const
+ { return toCurrencyString(qlonglong(i), symbol); }
+ QString toCurrencyString(uint i, const QString &symbol = QString()) const
+ { return toCurrencyString(qulonglong(i), symbol); }
QString toCurrencyString(double, const QString &symbol = QString(), int precision = -1) const;
- inline QString toCurrencyString(float i, const QString &symbol = QString(), int precision = -1) const
+ QString toCurrencyString(float i, const QString &symbol = QString(), int precision = -1) const
{ return toCurrencyString(double(i), symbol, precision); }
-#else
- QString toCurrencyString(double, const QString &symbol = QString()) const;
- QString toCurrencyString(double, const QString &symbol, int precision) const;
- inline QString toCurrencyString(float i, const QString &symbol = QString()) const
- { return toCurrencyString(double(i), symbol); }
- inline QString toCurrencyString(float i, const QString &symbol, int precision) const
- { return toCurrencyString(double(i), symbol, precision); }
-#endif
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat);
-#endif
QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat) const;
+#if QT_CORE_REMOVED_SINCE(6, 7)
QStringList uiLanguages() const;
+#endif
+ QStringList uiLanguages(TagSeparator separator = TagSeparator::Dash) const;
+
+ enum LanguageCodeType {
+ ISO639Part1 = 1 << 0,
+ ISO639Part2B = 1 << 1,
+ ISO639Part2T = 1 << 2,
+ ISO639Part3 = 1 << 3,
+ LegacyLanguageCode = 1 << 15,
+
+ ISO639Part2 = ISO639Part2B | ISO639Part2T,
+ ISO639Alpha2 = ISO639Part1,
+ ISO639Alpha3 = ISO639Part2 | ISO639Part3,
+ ISO639 = ISO639Alpha2 | ISO639Alpha3,
+
+ AnyLanguageCode = -1
+ };
+ Q_DECLARE_FLAGS(LanguageCodeTypes, LanguageCodeType)
+ Q_FLAG(LanguageCodeTypes)
- bool operator==(const QLocale &other) const;
- bool operator!=(const QLocale &other) const;
+#if QT_CORE_REMOVED_SINCE(6, 3)
+ static QString languageToCode(Language language);
+ static Language codeToLanguage(QStringView languageCode) noexcept;
+#endif
+ static QString languageToCode(Language language, LanguageCodeTypes codeTypes = AnyLanguageCode);
+ static Language codeToLanguage(QStringView languageCode,
+ LanguageCodeTypes codeTypes = AnyLanguageCode) noexcept;
+ static QString territoryToCode(Territory territory);
+ static Territory codeToTerritory(QStringView territoryCode) noexcept;
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use territoryToCode(Territory) instead")
+ static QString countryToCode(Country country);
+ QT_DEPRECATED_VERSION_X_6_6("Use codeToTerritory(QStringView) instead")
+ static Country codeToCountry(QStringView countryCode) noexcept;
+#endif
+ static QString scriptToCode(Script script);
+ static Script codeToScript(QStringView scriptCode) noexcept;
static QString languageToString(Language language);
+ static QString territoryToString(Territory territory);
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use territoryToString(Territory) instead")
static QString countryToString(Country country);
+#endif
static QString scriptToString(Script script);
static void setDefault(const QLocale &locale);
static QLocale c() { return QLocale(C); }
static QLocale system();
- static QList<QLocale> matchingLocales(QLocale::Language language, QLocale::Script script, QLocale::Country country);
+ static QList<QLocale> matchingLocales(QLocale::Language language, QLocale::Script script,
+ QLocale::Territory territory);
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Query territory() on each entry from matchingLocales() instead")
static QList<Country> countriesForLanguage(Language lang);
+#endif
void setNumberOptions(NumberOptions options);
NumberOptions numberOptions() const;
enum QuotationStyle { StandardQuotation, AlternateQuotation };
+ Q_ENUM(QuotationStyle)
QString quoteString(const QString &str, QuotationStyle style = StandardQuotation) const
{ return quoteString(QStringView(str), style); }
QString quoteString(QStringView str, QuotationStyle style = StandardQuotation) const;
@@ -1117,40 +1166,29 @@ public:
private:
QLocale(QLocalePrivate &dd);
+ bool equals(const QLocale &other) const;
friend class QLocalePrivate;
friend class QSystemLocale;
friend class QCalendarBackend;
- friend class QGregorianCalendar;
+ friend class QRomanCalendar;
friend Q_CORE_EXPORT size_t qHash(const QLocale &key, size_t seed) noexcept;
+ friend bool comparesEqual(const QLocale &lhs, const QLocale &rhs) noexcept
+ {
+ return lhs.equals(rhs);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QLocale)
+
QSharedDataPointer<QLocalePrivate> d;
};
Q_DECLARE_SHARED(QLocale)
Q_DECLARE_OPERATORS_FOR_FLAGS(QLocale::NumberOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QLocale::LanguageCodeTypes)
-inline QString QLocale::toString(long i) const
- { return toString(qlonglong(i)); }
-inline QString QLocale::toString(ulong i) const
- { return toString(qulonglong(i)); }
-inline QString QLocale::toString(short i) const
- { return toString(qlonglong(i)); }
-inline QString QLocale::toString(ushort i) const
- { return toString(qulonglong(i)); }
-inline QString QLocale::toString(int i) const
- { return toString(qlonglong(i)); }
-inline QString QLocale::toString(uint i) const
- { return toString(qulonglong(i)); }
-inline QString QLocale::toString(float i, char f, int prec) const
- { return toString(double(i), f, prec); }
-
-inline QString QLocale::toCurrencyString(short i, const QString &symbol) const
- { return toCurrencyString(qlonglong(i), symbol); }
-inline QString QLocale::toCurrencyString(ushort i, const QString &symbol) const
- { return toCurrencyString(qulonglong(i), symbol); }
-inline QString QLocale::toCurrencyString(int i, const QString &symbol) const
-{ return toCurrencyString(qlonglong(i), symbol); }
-inline QString QLocale::toCurrencyString(uint i, const QString &symbol) const
-{ return toCurrencyString(qulonglong(i), symbol); }
+#if QT_CORE_INLINE_IMPL_SINCE(6, 4)
+QLocale::QLocale(const QString &name)
+ : QLocale(qToStringViewIgnoringNull(name)) {}
+#endif
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLocale &);
diff --git a/src/corelib/text/qlocale.qdoc b/src/corelib/text/qlocale.qdoc
index eb497d9386..0cdacfd8e5 100644
--- a/src/corelib/text/qlocale.qdoc
+++ b/src/corelib/text/qlocale.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QLocale
@@ -31,15 +7,15 @@
\brief The QLocale class converts between numbers and their
string representations in various languages.
+ \compares equality
\reentrant
\ingroup i18n
\ingroup string-processing
\ingroup shared
-
- QLocale is initialized with a language/country pair in its
- constructor and offers number-to-string and string-to-number
- conversion functions similar to those in QString.
+ QLocale is constructed for a specified language, optional script and
+ territory. It offers various facilities for formatting data as text,
+ localized appropriately, and for reading data out of localized text.
Example:
@@ -54,9 +30,6 @@
\list
\li If a QLocale object is constructed with the default constructor,
it will use the default locale's settings.
- \li QString::toInt(), QString::toDouble(), etc., interpret the
- string according to the default locale. If this fails, it
- falls back on the "C" locale.
\li QString::arg() uses the default locale to format a number when
its position specifier in the format string contains an 'L',
e.g. "%L1".
@@ -66,36 +39,47 @@
\snippet code/src_corelib_text_qlocale.cpp 1
- When a language/country pair is specified in the constructor, one
- of three things can happen:
-
- \list
- \li If the language/country pair is found in the database, it is used.
- \li If the language is found but the country is not, or if the country
- is \c AnyCountry, the language is used with the most
- appropriate available country (for example, Germany for German),
- \li If neither the language nor the country are found, QLocale
- defaults to the default locale (see setDefault()).
- \endlist
-
- Use language() and country() to determine the actual language and
- country values used.
-
An alternative method for constructing a QLocale object is by
specifying the locale name.
\snippet code/src_corelib_text_qlocale.cpp 2
- This constructor converts the locale name to a language/country
- pair; it does not use the system locale database.
+ This constructor reads the language, script and/or territory from the given
+ name, accepting either uderscore or dash as separator (and ignoring any
+ trailing \c{.codeset} or \c{@variant} suffix).
\note For the current keyboard input locale take a look at
QInputMethod::locale().
- QLocale's data is based on Common Locale Data Repository v36.
+ QLocale's data is based on Common Locale Data Repository v44.1.
+
+ \section1 Matching combinations of language, script and territory
+
+ QLocale has data, derived from CLDR, for many combinations of language,
+ script and territory, but not all. If it is constructed with all three of
+ these key values specified (treating \c AnyLanguage, \c AnyScript or \c
+ AnyTerritory as unspecified) and QLocale has data for the given combination,
+ this data is used. Otherwise, QLocale does its best to find a sensible
+ combination of language, script and territory, for which it does have data,
+ that matches those that were specified.
+
+ The CLDR provides tables of likely combinations, which are used to fill in
+ any unspecified key or keys; if QLocale has data for the result of such a
+ likely combination, that is used. If no language is specified, and none can
+ be determined from script and territory, or if QLocale has no data for the
+ language, the "C" locale (when reading the keys from a string) or default
+ locale (otherwise) is used.
+
+ When QLocale has no data for the keys specified, with likely keys filled in
+ where unspecified, but does have data for the resulting language, a
+ fall-back is sought, based on ignoring either territory, script or both (in
+ that order). This results in a QLocale which may not match what was asked
+ for, but provides localization that's as suitable as the available data
+ permits, for the keys specified.
+
+ Use language(), script() and territory() to determine the actual keys used.
- \sa QString::arg(), QString::toInt(), QString::toDouble(),
- QInputMethod::locale()
+ \sa QString::arg(), QInputMethod::locale()
*/
/*!
@@ -111,20 +95,18 @@
\value Afar
\value Afrikaans
\value Aghem
- \value Ahom Since Qt 5.7
\value Akan
- \value Akkadian Since Qt 5.1
- \value Akoose Since Qt 5.3
+ \value [since 5.1] Akkadian
+ \value [since 5.3] Akoose
\value Albanian
- \value AmericanSignLanguage Since Qt 5.7
+ \value [since 5.7] AmericanSignLanguage
\value Amharic
- \value AncientEgyptian Since Qt 5.1
- \value AncientGreek Since Qt 5.1
- \value AncientNorthArabian Since Qt 5.5
+ \value [since 5.1] AncientEgyptian
+ \value [since 5.1] AncientGreek
+ \value [since 6.7] Anii
\value Arabic
- \value Aragonese Since Qt 5.1
- \value Aramaic Since Qt 5.1
- \value ArdhamagadhiPrakrit Since Qt 5.7
+ \value [since 5.1] Aragonese
+ \value [since 5.1] Aramaic
\value Armenian
\value Assamese
\value Asturian
@@ -135,52 +117,49 @@
\value Aymara
\value Azerbaijani
\value Bafia
- \value Balinese Since Qt 5.1
+ \value [since 5.1] Balinese
+ \value [since 6.6] Baluchi
\value Bambara
- \value Bamun Since Qt 5.1
+ \value [since 5.1] Bamun
+ \value [since 6.0] Bangla
\value Basaa
\value Bashkir
\value Basque
- \value Bassa Since Qt 5.5
- \value BatakToba Since Qt 5.1
+ \value [since 5.1] BatakToba
\value Belarusian
\value Bemba
\value Bena
- \value Bengali
- \value Bhojpuri Since Qt 5.7
+ \value Bengali Obsolete, please use Bangla
+ \value [since 5.7] Bhojpuri
\value Bhutani Obsolete, please use Dzongkha
- \value Bihari
\value Bislama
\value Blin
\value Bodo
\value Bosnian
\value Breton
- \value Buginese Since Qt 5.1
- \value Buhid Since Qt 5.1
+ \value [since 5.1] Buginese
\value Bulgarian
\value Burmese
\value Byelorussian Obsolete, please use Belarusian
\value Cambodian Obsolete, please use Khmer
- \value Cantonese Since Qt 5.7
- \value Carian Since Qt 5.1
+ \value [since 5.7] Cantonese
\value Catalan
- \value Cebuano Since Qt 5.14
- \value CentralKurdish Since Qt 5.5
- \value CentralMoroccoTamazight
- \value Chakma Since Qt 5.1
+ \value [since 5.14] Cebuano
+ \value [since 6.0] CentralAtlasTamazight
+ \value [since 5.5] CentralKurdish
+ \value CentralMoroccoTamazight Obsolete, please use CentralAtlasTamazight
+ \value [since 5.1] Chakma
\value Chamorro
\value Chechen
\value Cherokee
\value Chewa Obsolete, please use Nyanja
- \value Chickasaw Since Qt 5.14
+ \value [since 5.14] Chickasaw
\value Chiga
\value Chinese (Mandarin)
\value Church
\value Chuvash
- \value ClassicalMandaic Since Qt 5.1
\value Colognian
- \value CongoSwahili
- \value Coptic Since Qt 5.1
+ \value [since 5.1] Coptic
\value Cornish
\value Corsican
\value Cree
@@ -188,18 +167,15 @@
\value Czech
\value Danish
\value Divehi
- \value Dogri Since Qt 5.1
+ \value [since 5.1] Dogri
\value Duala
\value Dutch
\value Dzongkha
- \value EasternCham Since Qt 5.1
- \value EasternKayah Since Qt 5.1
\value Embu
\value English
- \value Erzya Since Qt 5.14
+ \value [since 5.14] Erzya
\value Esperanto
\value Estonian
- \value Etruscan Since Qt 5.1
\value Ewe
\value Ewondo
\value Faroese
@@ -217,34 +193,32 @@
\value Geez
\value Georgian
\value German
- \value Gothic Since Qt 5.1
+ \value [since 5.1] Gothic
\value Greek
- \value Greenlandic
+ \value Greenlandic Obsolete, please use Kalaallisut
\value Guarani
\value Gujarati
\value Gusii
\value Haitian
- \value Hanunoo Since Qt 5.1
+ \value [since 6.5] Haryanvi
\value Hausa
\value Hawaiian
\value Hebrew
\value Herero
- \value HieroglyphicLuwian Since Qt 5.7
\value Hindi
\value HiriMotu
- \value HmongNjua Since Qt 5.5
- \value Ho Since Qt 5.5
\value Hungarian
\value Icelandic
- \value Ido Since Qt 5.12
+ \value [since 5.12] Ido
\value Igbo
- \value InariSami Since Qt 5.5
+ \value [since 5.5] InariSami
\value Indonesian
- \value Ingush Since Qt 5.1
+ \value [since 5.1] Ingush
\value Interlingua
\value Interlingue
\value Inuktitut
- \value Inupiak
+ \value Inupiak Obsolete, please use Inupiaq
+ \value [since 6.0] Inupiaq
\value Irish
\value Italian
\value Japanese
@@ -253,19 +227,22 @@
\value JolaFonyi
\value Kabuverdianu
\value Kabyle
+ \value [since 6.3] Kaingang
\value Kako
+ \value [since 6.0] Kalaallisut
\value Kalenjin
\value Kamba
+ \value [since 6.7] Kangri
\value Kannada
\value Kanuri
\value Kashmiri
\value Kazakh
- \value Kenyang Since Qt 5.5
+ \value [since 5.5] Kenyang
\value Khmer
- \value Kiche Since Qt 5.5
+ \value [since 5.5] Kiche
\value Kikuyu
\value Kinyarwanda
- \value Kirghiz
+ \value Kirghiz Obsolete, please use Kyrgyz
\value Komi
\value Kongo
\value Konkani
@@ -274,212 +251,198 @@
\value KoyraboroSenni
\value KoyraChiini
\value Kpelle
+ \value [since 6.0] Kuanyama
\value Kurdish
\value Kurundi Obsolete, please use Rundi
- \value Kwanyama
+ \value Kwanyama Obsolete, please use Kuanyama
\value Kwasio
- \value Lakota Since Qt 5.3
+ \value [since 6.0] Kyrgyz
+ \value [since 5.3] Lakota
\value Langi
\value Lao
- \value LargeFloweryMiao Since Qt 5.1
\value Latin
\value Latvian
- \value Lepcha Since Qt 5.1
- \value Lezghian Since Qt 5.5
+ \value [since 5.5] Lezghian
\value Limburgish
- \value Limbu Since Qt 5.1
- \value LinearA Since Qt 5.5
\value Lingala
- \value Lisu Since Qt 5.1
- \value LiteraryChinese Since Qt 5.7
+ \value [since 6.6] Ligurian
+ \value [since 5.7] LiteraryChinese
\value Lithuanian
- \value Lojban Since Qt 5.12
- \value LowerSorbian Since Qt 5.5
+ \value [since 5.12] Lojban
+ \value [since 5.5] LowerSorbian
\value LowGerman
\value LubaKatanga
- \value LuleSami Since Qt 5.5
+ \value [since 5.5] LuleSami
\value Luo
- \value Lu Since Qt 5.1
\value Luxembourgish
\value Luyia
- \value Lycian Since Qt 5.1
- \value Lydian Since Qt 5.1
\value Macedonian
\value Machame
- \value Maithili Since Qt 5.5
+ \value [since 5.5] Maithili
\value MakhuwaMeetto
\value Makonde
\value Malagasy
\value Malay
\value Malayalam
\value Maltese
- \value Mandingo Since Qt 5.1
- \value ManichaeanMiddlePersian Since Qt 5.5
- \value Manipuri Since Qt 5.1
+ \value [since 5.1] Mandingo
+ \value [since 5.1] Manipuri
\value Manx
\value Maori
- \value Mapuche Since Qt 5.5
+ \value [since 5.5] Mapuche
\value Marathi
\value Marshallese
\value Masai
- \value Mazanderani Since Qt 5.7
- \value Mende Since Qt 5.5
- \value Meroitic Since Qt 5.1
+ \value [since 5.7] Mazanderani
+ \value [since 5.5] Mende
\value Meru
\value Meta
- \value Mohawk Since Qt 5.5
- \value Moldavian Obsolete, please use Romanian
+ \value [since 5.5] Mohawk
+ \value [since 6.5] Moksha
\value Mongolian
- \value Mono Since Qt 5.5
\value Morisyen
- \value Mru Since Qt 5.7
\value Mundang
- \value Muscogee Since Qt 5.14
+ \value [since 5.14] Muscogee
\value Nama
\value NauruLanguage
- \value Navaho
+ \value Navaho Obsolete, please use Navajo
+ \value [since 6.0] Navajo
\value Ndonga
\value Nepali
- \value Newari Since Qt 5.7
+ \value [since 5.7] Newari
\value Ngiemboon
+ \value [since 6.3] Nheengatu
+ \value [since 6.0] NigerianPidgin
\value Ngomba
- \value Nko Since Qt 5.5
- \value NorthernLuri Since Qt 5.7
+ \value [since 5.5] Nko
+ \value [since 6.5] NorthernFrisian
+ \value [since 5.7] NorthernLuri
\value NorthernSami
\value NorthernSotho
- \value NorthernThai Since Qt 5.1
\value NorthNdebele
- \value NorwegianBokmal same as Norwegian
+ \value NorwegianBokmal
\value NorwegianNynorsk
- \value Norwegian same as NorwegianBokmal
\value Nuer
\value Nyanja
\value Nyankole
+ \value [since 6.5] Obolo
\value Occitan
+ \value [since 6.0] Odia
\value Ojibwa
- \value OldIrish Since Qt 5.1
- \value OldNorse Since Qt 5.1
- \value OldPersian Since Qt 5.1
- \value OldTurkish Since Qt 5.1
- \value Oriya
+ \value [since 5.1] OldIrish
+ \value [since 5.1] OldNorse
+ \value [since 5.1] OldPersian
+ \value Oriya Obsolete, please use Odia
\value Oromo
- \value Osage Since Qt 5.7
+ \value [since 5.7] Osage
\value Ossetic
- \value Pahlavi Since Qt 5.1
- \value Palauan Since Qt 5.7
+ \value [since 5.1] Pahlavi
+ \value [since 5.7] Palauan
\value Pali
- \value Papiamento Since Qt 5.7
- \value Parthian Since Qt 5.1
+ \value [since 5.7] Papiamento
\value Pashto
\value Persian
- \value Phoenician Since Qt 5.1
+ \value [since 5.1] Phoenician
+ \value [since 6.5] Pijin
\value Polish
\value Portuguese
- \value PrakritLanguage Since Qt 5.1
- \value Prussian Since Qt 5.5
+ \value [since 5.5] Prussian
\value Punjabi
\value Quechua
- \value Rejang Since Qt 5.1
+ \value [since 6.5] Rajasthani
\value RhaetoRomance Obsolete, please use Romansh
+ \value [since 6.6] Rohingya
\value Romanian
\value Romansh
\value Rombo
\value Rundi
\value Russian
\value Rwa
- \value Sabaean Since Qt 5.1
\value Saho
\value Sakha
- \value Samaritan Since Qt 5.1
\value Samburu
\value Samoan
\value Sango
\value Sangu
\value Sanskrit
- \value Santali Since Qt 5.1
- \value Saraiki Since Qt 5.7
+ \value [since 5.1] Santali
\value Sardinian
- \value Saurashtra Since Qt 5.1
+ \value [since 5.1] Saurashtra
\value Sena
\value Serbian
- \value SerboCroatian Obsolete, please use Serbian
\value Shambala
\value Shona
\value SichuanYi
- \value Sicilian Since Qt 5.12
+ \value [since 5.12] Sicilian
\value Sidamo
- \value Silesian Since Qt 5.14
+ \value [since 5.14] Silesian
\value Sindhi
\value Sinhala
- \value SkoltSami Since Qt 5.5
+ \value [since 5.5] SkoltSami
\value Slovak
\value Slovenian
\value Soga
\value Somali
- \value Sora Since Qt 5.1
- \value SouthernKurdish Since Qt 5.12
- \value SouthernSami Since Qt 5.5
+ \value [since 5.12] SouthernKurdish
+ \value [since 5.5] SouthernSami
\value SouthernSotho
\value SouthNdebele
\value Spanish
- \value StandardMoroccanTamazight Since Qt 5.3
+ \value [since 5.3] StandardMoroccanTamazight
\value Sundanese
\value Swahili
\value Swati
\value Swedish
\value SwissGerman
- \value Sylheti Since Qt 5.1
\value Syriac
\value Tachelhit
- \value Tagalog Obsolete, please use Filipino
- \value Tagbanwa Since Qt 5.1
\value Tahitian
- \value TaiDam Since Qt 5.1
- \value TaiNua Since Qt 5.1
+ \value [since 5.1] TaiDam
\value Taita
\value Tajik
\value Tamil
- \value Tangut Since Qt 5.7
\value Taroko
\value Tasawaq
\value Tatar
- \value TedimChin Since Qt 5.5
\value Telugu
\value Teso
\value Thai
\value Tibetan
\value Tigre
\value Tigrinya
- \value TokelauLanguage Since Qt 5.7
- \value TokPisin Since Qt 5.7
+ \value [since 5.7] TokelauLanguage
+ \value [since 6.5] TokiPona
+ \value [since 5.7] TokPisin
\value Tongan
+ \value [since 6.6] Torwali
\value Tsonga
\value Tswana
\value Turkish
\value Turkmen
- \value TuvaluLanguage Since Qt 5.7
- \value Twi Obsolete, please use Akan
+ \value [since 5.7] TuvaluLanguage
\value Tyap
- \value Ugaritic Since Qt 5.1
- \value Uighur
- \value Uigur Obsolete, please use Uighur
+ \value [since 5.1] Ugaritic
+ \value Uighur Obsolete, please use Uyghur
+ \value Uigur Obsolete, please use Uyghur
\value Ukrainian
- \value UncodedLanguages Since Qt 5.7
- \value UpperSorbian Since Qt 5.5
+ \value [since 5.5] UpperSorbian
\value Urdu
+ \value [since 6.0] Uyghur
\value Uzbek
\value Vai
\value Venda
+ \value [since 6.7] Venetian
\value Vietnamese
\value Volapuk
\value Vunjo
- \value Walamo
+ \value Walamo Obsolete, please use Wolaytta
\value Walloon
\value Walser
- \value Warlpiri Since Qt 5.5
+ \value [since 5.5] Warlpiri
\value Welsh
- \value WesternBalochi Since Qt 5.12
+ \value [since 5.12] WesternBalochi
\value WesternFrisian same as Frisian
+ \value [since 6.0] Wolaytta
\value Wolof
\value Xhosa
\value Yangben
@@ -495,11 +458,25 @@
*/
/*!
+ \typealias QLocale::Territory
+
+ This enumeration type is an alias for \l Country,
+ which shall be renamed to Territory at a future release.
+
+ \sa territory(), territoryToString()
+*/
+
+/*!
\enum QLocale::Country
- This enumerated type is used to specify a country.
+ This enumerated type is used to identify a territory.
+
+ An individual territory may be a province of a country, a country (by far the
+ most common case) or a larger geographic entity, to which some localization
+ details are specific.
- \value AnyCountry
+ \value AnyCountry Osbolete alias for \c AnyTerritory
+ \value [since 6.2] AnyTerritory
\value Afghanistan
\value AlandIslands
@@ -530,7 +507,8 @@
\value Bhutan
\value Bolivia
\value Bonaire
- \value BosniaAndHerzegowina
+ \value BosniaAndHerzegowina Obsolete, use \c BosniaAndHerzegovina instead
+ \value [since 6.0] BosniaAndHerzegovina
\value Botswana
\value BouvetIsland
\value Brazil
@@ -544,6 +522,7 @@
\value Cameroon
\value Canada
\value CanaryIslands
+ \value CaribbeanNetherlands
\value CapeVerde
\value CaymanIslands
\value CentralAfricanRepublic
@@ -562,11 +541,13 @@
\value CostaRica
\value Croatia
\value Cuba
- \value CuraSao
+ \value [since 6.0] Curacao
+ \value CuraSao Obsolete, use \c Curacao instead
\value Cyprus
- \value CzechRepublic
- \value DemocraticRepublicOfCongo Obsolete, please use CongoKinshasa
- \value DemocraticRepublicOfKorea Obsolete, please use NorthKorea
+ \value [since 6.0] Czechia
+ \value CzechRepublic Obsolete, use \c Czechia instead
+ \value DemocraticRepublicOfCongo Obsolete, use \c CongoKinshasa instead
+ \value DemocraticRepublicOfKorea Obsolete, use \c NorthKorea instead
\value Denmark
\value DiegoGarcia
\value Djibouti
@@ -579,9 +560,10 @@
\value EquatorialGuinea
\value Eritrea
\value Estonia
+ \value Eswatini
\value Ethiopia
- \value EuropeanUnion Since Qt 5.7
- \value Europe Since Qt 5.12
+ \value [since 5.7] EuropeanUnion
+ \value [since 5.12] Europe
\value FalklandIslands
\value FaroeIslands
\value Fiji
@@ -628,12 +610,12 @@
\value Kazakhstan
\value Kenya
\value Kiribati
- \value Kosovo Since Qt 5.2
+ \value [since 5.2] Kosovo
\value Kuwait
\value Kyrgyzstan
\value Laos
\value LatinAmerica
- \value LatinAmericaAndTheCaribbean Obsolete, please use LatinAmerica
+ \value LatinAmericaAndTheCaribbean Obsolete, use \c LatinAmerica instead
\value Latvia
\value Lebanon
\value Lesotho
@@ -642,6 +624,7 @@
\value Liechtenstein
\value Lithuania
\value Luxembourg
+ \value Macao
\value Macau
\value Macedonia
\value Madagascar
@@ -666,7 +649,8 @@
\value Mozambique
\value Myanmar
\value Namibia
- \value NauruCountry
+ \value NauruCountry Osbolete alias for \c NauruTerritory
+ \value [since 6.2] NauruTerritory
\value Nepal
\value Netherlands
\value NewCaledonia
@@ -680,14 +664,14 @@
\value NorthKorea
\value Norway
\value Oman
- \value OutlyingOceania Since Qt 5.7
+ \value [since 5.7] OutlyingOceania
\value Pakistan
\value Palau
\value PalestinianTerritories
\value Panama
\value PapuaNewGuinea
\value Paraguay
- \value PeoplesRepublicOfCongo Obsolete, please use CongoBrazzaville
+ \value PeoplesRepublicOfCongo Obsolete, use \c CongoBrazzaville instead
\value Peru
\value Philippines
\value Pitcairn
@@ -695,11 +679,11 @@
\value Portugal
\value PuertoRico
\value Qatar
- \value RepublicOfKorea Obsolete, please use SouthKorea
+ \value RepublicOfKorea Obsolete, use \c SouthKorea instead
\value Reunion
\value Romania
- \value RussianFederation same as Russia
- \value Russia same as RussianFederation
+ \value RussianFederation
+ \value Russia
\value Rwanda
\value SaintBarthelemy
\value SaintHelena
@@ -707,6 +691,7 @@
\value SaintLucia
\value SaintMartin
\value SaintPierreAndMiquelon
+ \value SaintVincentAndGrenadines
\value SaintVincentAndTheGrenadines
\value Samoa
\value SanMarino
@@ -723,6 +708,7 @@
\value SolomonIslands
\value Somalia
\value SouthAfrica
+ \value SouthGeorgiaAndSouthSandwichIslands
\value SouthGeorgiaAndTheSouthSandwichIslands
\value SouthKorea
\value SouthSudan
@@ -730,19 +716,21 @@
\value SriLanka
\value Sudan
\value Suriname
+ \value SvalbardAndJanMayen
\value SvalbardAndJanMayenIslands
\value Swaziland
\value Sweden
\value Switzerland
\value Syria
- \value SyrianArabRepublic Obsolete, please use Syria
+ \value SyrianArabRepublic Obsolete, use \c Syria instead
\value Taiwan
\value Tajikistan
\value Tanzania
\value Thailand
+ \value TimorLeste
\value Togo
- \value TokelauCountry
- \value Tokelau Obsolete, please use TokelauCountry
+ \value TokelauCountry Osbolete alias for \c TokelauTerritory
+ \value [since 6.2] TokelauTerritory
\value Tonga
\value TrinidadAndTobago
\value TristanDaCunha
@@ -750,31 +738,38 @@
\value Turkey
\value Turkmenistan
\value TurksAndCaicosIslands
- \value TuvaluCountry
- \value Tuvalu Obsolete, please use TuvaluCountry
+ \value TuvaluCountry Osbolete alias for \c TuvaluTerritory
+ \value [since 6.2] TuvaluTerritory
\value Uganda
\value Ukraine
\value UnitedArabEmirates
\value UnitedKingdom
\value UnitedStates
+ \value UnitedStatesOutlyingIslands
\value UnitedStatesMinorOutlyingIslands
\value UnitedStatesVirginIslands
\value Uruguay
\value Uzbekistan
\value Vanuatu
+ \value VaticanCity
\value VaticanCityState
\value Venezuela
\value Vietnam
+ \value WallisAndFutuna
\value WallisAndFutunaIslands
\value WesternSahara
- \value World Since Qt 5.12
+ \value [since 5.12] World
\value Yemen
\value Zambia
\value Zimbabwe
- \omitvalue LastCountry
+ \omitvalue LastCountry Osbolete alias for \c LastTerritory
+ \omitvalue LastTerritory
- \sa country(), countryToString()
+ \note Use the Territory alias for this enumeration where possible.
+ The Country enum shall be renamed to Territory at a later release.
+
+ \sa territory(), territoryToString(), codeToTerritory(), territoryToCode()
*/
/*!
@@ -784,148 +779,152 @@
\value AnyScript
- \value AdlamScript Since Qt 5.7
- \value AhomScript Since Qt 5.7
- \value AnatolianHieroglyphsScript Since Qt 5.7
+ \value [since 5.7] AdlamScript
+ \value [since 5.7] AhomScript
+ \value [since 5.7] AnatolianHieroglyphsScript
\value ArabicScript
\value ArmenianScript
- \value AvestanScript Since Qt 5.1
- \value BalineseScript Since Qt 5.1
- \value BamumScript Since Qt 5.1
- \value BassaVahScript Since Qt 5.5
- \value BatakScript Since Qt 5.1
- \value BengaliScript
- \value BhaiksukiScript Since Qt 5.7
- \value BopomofoScript Since Qt 5.1
- \value BrahmiScript Since Qt 5.1
- \value BrailleScript Since Qt 5.1
- \value BugineseScript Since Qt 5.1
- \value BuhidScript Since Qt 5.1
- \value CanadianAboriginalScript Since Qt 5.1
- \value CarianScript Since Qt 5.1
- \value CaucasianAlbanianScript Since Qt 5.5
- \value ChakmaScript Since Qt 5.1
- \value ChamScript Since Qt 5.1
+ \value [since 5.1] AvestanScript
+ \value [since 5.1] BalineseScript
+ \value [since 5.1] BamumScript
+ \value [since 6.0] BanglaScript
+ \value [since 5.5] BassaVahScript
+ \value [since 5.1] BatakScript
+ \value BengaliScript Obsolete, please use BanglaScript
+ \value [since 5.7] BhaiksukiScript
+ \value [since 5.1] BopomofoScript
+ \value [since 5.1] BrahmiScript
+ \value [since 5.1] BrailleScript
+ \value [since 5.1] BugineseScript
+ \value [since 5.1] BuhidScript
+ \value [since 5.1] CanadianAboriginalScript
+ \value [since 5.1] CarianScript
+ \value [since 5.5] CaucasianAlbanianScript
+ \value [since 5.1] ChakmaScript
+ \value [since 5.1] ChamScript
\value CherokeeScript
- \value CopticScript Since Qt 5.1
- \value CuneiformScript Since Qt 5.1
- \value CypriotScript Since Qt 5.1
+ \value [since 5.1] CopticScript
+ \value [since 5.1] CuneiformScript
+ \value [since 5.1] CypriotScript
\value CyrillicScript
- \value DeseretScript Since Qt 5.1
+ \value [since 5.1] DeseretScript
\value DevanagariScript
- \value DuployanScript Since Qt 5.5
- \value EgyptianHieroglyphsScript Since Qt 5.1
- \value ElbasanScript Since Qt 5.5
+ \value [since 5.5] DuployanScript
+ \value [since 5.1] EgyptianHieroglyphsScript
+ \value [since 5.5] ElbasanScript
\value EthiopicScript
- \value FraserScript Since Qt 5.1
+ \value [since 5.1] FraserScript
\value GeorgianScript
- \value GlagoliticScript Since Qt 5.1
- \value GothicScript Since Qt 5.1
- \value GranthaScript Since Qt 5.5
+ \value [since 5.1] GlagoliticScript
+ \value [since 5.1] GothicScript
+ \value [since 5.5] GranthaScript
\value GreekScript
\value GujaratiScript
\value GurmukhiScript
- \value HangulScript Since Qt 5.1
- \value HanScript Since Qt 5.1
- \value HanunooScript Since Qt 5.1
- \value HanWithBopomofoScript Since Qt 5.7
- \value HatranScript Since Qt 5.7
+ \value [since 5.1] HangulScript
+ \value [since 6.6] HanifiScript
+ \value [since 5.1] HanScript
+ \value [since 5.1] HanunooScript
+ \value [since 5.7] HanWithBopomofoScript
+ \value [since 5.7] HatranScript
\value HebrewScript
- \value HiraganaScript Since Qt 5.1
- \value ImperialAramaicScript Since Qt 5.1
- \value InscriptionalPahlaviScript Since Qt 5.1
- \value InscriptionalParthianScript Since Qt 5.1
- \value JamoScript Since Qt 5.7
+ \value [since 5.1] HiraganaScript
+ \value [since 5.1] ImperialAramaicScript
+ \value [since 5.1] InscriptionalPahlaviScript
+ \value [since 5.1] InscriptionalParthianScript
+ \value [since 5.7] JamoScript
\value JapaneseScript
- \value JavaneseScript Since Qt 5.1
- \value KaithiScript Since Qt 5.1
+ \value [since 5.1] JavaneseScript
+ \value [since 5.1] KaithiScript
\value KannadaScript
- \value KatakanaScript Since Qt 5.1
- \value KayahLiScript Since Qt 5.1
- \value KharoshthiScript Since Qt 5.1
- \value KhmerScript Since Qt 5.1
- \value KhojkiScript Since Qt 5.5
- \value KhudawadiScript Since Qt 5.5
+ \value [since 5.1] KatakanaScript
+ \value [since 5.1] KayahLiScript
+ \value [since 5.1] KharoshthiScript
+ \value [since 5.1] KhmerScript
+ \value [since 5.5] KhojkiScript
+ \value [since 5.5] KhudawadiScript
\value KoreanScript
- \value LannaScript Since Qt 5.1
+ \value [since 5.1] LannaScript
\value LaoScript
\value LatinScript
- \value LepchaScript Since Qt 5.1
- \value LimbuScript Since Qt 5.1
- \value LinearAScript Since Qt 5.5
- \value LinearBScript Since Qt 5.1
- \value LycianScript Since Qt 5.1
- \value LydianScript Since Qt 5.1
- \value MahajaniScript Since Qt 5.5
+ \value [since 5.1] LepchaScript
+ \value [since 5.1] LimbuScript
+ \value [since 5.5] LinearAScript
+ \value [since 5.1] LinearBScript
+ \value [since 5.1] LycianScript
+ \value [since 5.1] LydianScript
+ \value [since 5.5] MahajaniScript
\value MalayalamScript
- \value MandaeanScript Since Qt 5.1
- \value ManichaeanScript Since Qt 5.5
- \value MarchenScript Since Qt 5.7
- \value MeiteiMayekScript Since Qt 5.1
- \value MendeKikakuiScript Since Qt 5.5
- \value MeroiticCursiveScript Since Qt 5.1
- \value MeroiticScript Since Qt 5.1
- \value ModiScript Since Qt 5.5
+ \value [since 5.1] MandaeanScript
+ \value [since 5.5] ManichaeanScript
+ \value [since 5.7] MarchenScript
+ \value [since 5.1] MeiteiMayekScript
+ \value [since 6.0] MendeScript
+ \value MendeKikakuiScript Obsolete, please use MendeScript
+ \value [since 5.1] MeroiticCursiveScript
+ \value [since 5.1] MeroiticScript
+ \value [since 5.5] ModiScript
\value MongolianScript
- \value MroScript Since Qt 5.5
- \value MultaniScript Since Qt 5.7
+ \value [since 5.5] MroScript
+ \value [since 5.7] MultaniScript
\value MyanmarScript
- \value NabataeanScript Since Qt 5.5
- \value NewaScript Since Qt 5.7
- \value NewTaiLueScript Since Qt 5.1
- \value NkoScript Since Qt 5.1
- \value OghamScript Since Qt 5.1
- \value OlChikiScript Since Qt 5.1
- \value OldHungarianScript Since Qt 5.7
- \value OldItalicScript Since Qt 5.1
- \value OldNorthArabianScript Since Qt 5.5
- \value OldPermicScript Since Qt 5.5
- \value OldPersianScript Since Qt 5.1
- \value OldSouthArabianScript Since Qt 5.1
- \value OriyaScript
- \value OrkhonScript Since Qt 5.1
- \value OsageScript Since Qt 5.7
- \value OsmanyaScript Since Qt 5.1
- \value PahawhHmongScript Since Qt 5.5
- \value PalmyreneScript Since Qt 5.5
- \value PauCinHauScript Since Qt 5.5
- \value PhagsPaScript Since Qt 5.1
- \value PhoenicianScript Since Qt 5.1
- \value PollardPhoneticScript Since Qt 5.1
- \value PsalterPahlaviScript Since Qt 5.5
- \value RejangScript Since Qt 5.1
- \value RunicScript Since Qt 5.1
- \value SamaritanScript Since Qt 5.1
- \value SaurashtraScript Since Qt 5.1
- \value SharadaScript Since Qt 5.1
- \value ShavianScript Since Qt 5.1
- \value SiddhamScript Since Qt 5.5
- \value SignWritingScript Since Qt 5.7
+ \value [since 5.5] NabataeanScript
+ \value [since 5.7] NewaScript
+ \value [since 5.1] NewTaiLueScript
+ \value [since 5.1] NkoScript
+ \value [since 5.1] OghamScript
+ \value [since 5.1] OlChikiScript
+ \value [since 5.7] OldHungarianScript
+ \value [since 5.1] OldItalicScript
+ \value [since 5.5] OldNorthArabianScript
+ \value [since 5.5] OldPermicScript
+ \value [since 5.1] OldPersianScript
+ \value [since 5.1] OldSouthArabianScript
+ \value [since 6.0] OdiaScript
+ \value OriyaScript Obsolete, please use OdiaScript
+ \value [since 5.1] OrkhonScript
+ \value [since 5.7] OsageScript
+ \value [since 5.1] OsmanyaScript
+ \value [since 5.5] PahawhHmongScript
+ \value [since 5.5] PalmyreneScript
+ \value [since 5.5] PauCinHauScript
+ \value [since 5.1] PhagsPaScript
+ \value [since 5.1] PhoenicianScript
+ \value [since 5.1] PollardPhoneticScript
+ \value [since 5.5] PsalterPahlaviScript
+ \value [since 5.1] RejangScript
+ \value [since 5.1] RunicScript
+ \value [since 5.1] SamaritanScript
+ \value [since 5.1] SaurashtraScript
+ \value [since 5.1] SharadaScript
+ \value [since 5.1] ShavianScript
+ \value [since 5.5] SiddhamScript
+ \value [since 5.7] SignWritingScript
\value SimplifiedChineseScript same as SimplifiedHanScript
\value SimplifiedHanScript same as SimplifiedChineseScript
\value SinhalaScript
- \value SoraSompengScript Since Qt 5.1
- \value SundaneseScript Since Qt 5.1
- \value SylotiNagriScript Since Qt 5.1
+ \value [since 5.1] SoraSompengScript
+ \value [since 5.1] SundaneseScript
+ \value [since 5.1] SylotiNagriScript
\value SyriacScript
- \value TagalogScript Since Qt 5.1
- \value TagbanwaScript Since Qt 5.1
- \value TaiLeScript Since Qt 5.1
- \value TaiVietScript Since Qt 5.1
- \value TakriScript Since Qt 5.1
+ \value [since 5.1] TagalogScript
+ \value [since 5.1] TagbanwaScript
+ \value [since 5.1] TaiLeScript
+ \value [since 5.1] TaiVietScript
+ \value [since 5.1] TakriScript
\value TamilScript
- \value TangutScript Since Qt 5.7
+ \value [since 5.7] TangutScript
\value TeluguScript
\value ThaanaScript
\value ThaiScript
\value TibetanScript
\value TifinaghScript
- \value TirhutaScript Since Qt 5.5
+ \value [since 5.5] TirhutaScript
\value TraditionalChineseScript same as TraditionalHanScript
\value TraditionalHanScript same as TraditionalChineseScript
- \value UgariticScript Since Qt 5.1
+ \value [since 5.1] UgariticScript
\value VaiScript
- \value VarangKshitiScript Since Qt 5.5
+ \value [since 5.5] VarangKshitiScript
\value YiScript
\omitvalue LastScript
@@ -990,23 +989,23 @@
dot when parsing a number in scientific or decimal representation. The
default is to accept trailing zeroes.
- \sa setNumberOptions(), numberOptions()
+ \sa setNumberOptions(), numberOptions(), FloatingPointPrecisionOption
*/
/*!
\enum QLocale::FloatingPointPrecisionOption
- This enum defines constants that can be given as precision to QString::number(),
+ This enum defines a constant that can be given as precision to QString::number(),
QByteArray::number(), and QLocale::toString() when converting floats or doubles,
in order to express a variable number of digits as precision.
\value FloatingPointShortest The conversion algorithm will try to find the
- shortest accurate representation for the given number. "Accurate" means
- that you get the exact same number back from an inverse conversion on
- the generated string representation.
-
- \sa toString(), QString, QByteArray
+ shortest accurate representation for the given number. "Accurate" means
+ that you get the exact same number back from an inverse conversion on
+ the generated string representation. In particular, trailing zeros are
+ omitted (from the mantissa, in exponent formats).
+ \sa toString(), QString::number(), QByteArray::number()
\since 5.7
*/
@@ -1026,19 +1025,50 @@
\since 4.4
*/
+/*!
+ \enum QLocale::LanguageCodeType
+
+ This enum defines language code types that can be used to restrict set
+ of language codes considered by \c codeToLanguage and \c languageToCode.
+
+ \value ISO639Part1 ISO 639 Part 1 Alpha 2 code.
+ \value ISO639Part2B ISO 639 Part 2 bibliographic Alpha 3 code.
+ \value ISO639Part2T ISO 639 Part 2 terminological Alpha 3 code.
+ \value ISO639Part3 ISO 639 Part 3 Alpha 3 code.
+ \value LegacyLanguageCode Codes that are not part of the above set, but that
+ were supported by Qt in the past. This value can only be used by
+ codeToLanguage(). It is ignored when passed to languageToCode().
+ \value ISO639Part2 Any ISO 639 Part 2 code.
+ \value ISO639Alpha2 Any ISO-639 2-letter code.
+ \value ISO639Alpha3 Any ISO-639 3-letter code.
+ \value ISO639 Any ISO 639 code.
+ \value AnyLanguageCode Specifies that any code can be used.
+*/
/*!
- \fn bool QLocale::operator==(const QLocale &other) const
+ \fn bool QLocale::operator==(const QLocale &lhs, const QLocale &rhs)
+
+ Returns \c true if the two QLocale objects, \a lhs and \a rhs, are the same;
+ otherwise returns \c false.
- Returns \c true if the QLocale object is the same as the \a other
- locale specified; otherwise returns \c false.
+ \note The system locale is not equal to the QLocale object constructed from
+ its language(), script() and territory(), even if the two agree in all data
+ fields. Nor are two locales with different number options equal.
+
+ \sa operator!=(), setNumberOptions()
*/
/*!
- \fn bool QLocale::operator!=(const QLocale &other) const
+ \fn bool QLocale::operator!=(const QLocale &lhs, const QLocale &rhs)
+
+ Returns \c true if the two QLocale objects, \a lhs and \a rhs, differ;
+ otherwise returns \c false.
+
+ \note The system locale is not equal to the QLocale object constructed from
+ its language(), script() and territory(), even if the two agree in all data
+ fields. Nor are two locales with different number options equal.
- Returns \c true if the QLocale object is not the same as the \a other
- locale specified; otherwise returns \c false.
+ \sa operator==(), setNumberOptions()
*/
/*!
@@ -1083,7 +1113,7 @@
\value LanguageId a uint specifying the language.
\value ScriptId a uint specifying the script.
- \value CountryId a uint specifying the country.
+ \value TerritoryId a uint specifying the territory.
\value DecimalPoint a QString specifying the decimal point.
\value GroupSeparator a QString specifying the group separator.
\value ZeroDigit a QString specifying the zero digit.
@@ -1108,7 +1138,7 @@
\value MeasurementSystem a QLocale::MeasurementSystem enum specifying the measurement system
\value AMText a string that represents the system AM designator associated with a 12-hour clock.
\value PMText a string that represents the system PM designator associated with a 12-hour clock.
- \value FirstDayOfWeek a Qt::DayOfWeek enum specifiying the first day of the week
+ \value FirstDayOfWeek a Qt::DayOfWeek enum specifying the first day of the week
\value CurrencySymbol a string that represents a currency in a format QLocale::CurrencyFormat.
\value CurrencyToString a localized string representation of a number with a currency symbol. Converts a QSystemLocale::CurrencyToStringArgument stored in the in variant to a QString.
\value UILanguages a list of strings representing locale names that could be used for UI translation.
@@ -1118,20 +1148,13 @@
\value LocaleChanged this type is queried whenever the system locale is changed.
\value ListToSeparatedString a string that represents a join of a given QStringList with a locale-defined separator.
\value NativeLanguageName a string that represents the name of the native language.
- \value NativeCountryName a string that represents the name of the native country.
+ \value NativeTerritoryName a string that represents the name of the native territory.
\sa FormatType
*/
/*!
- \fn QLocale QSystemLocale::fallbackUiLocale() const
-
- \since 4.6
- Returns the fallback locale obtained from the system.
-*/
-
-/*!
- \fn QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
+ \fn QVariant QSystemLocale::query(QueryType type, QVariant &&in = QVariant()) const
Generic query method for locale data. Provides indirection.
Denotes the \a type of the query
@@ -1141,6 +1164,17 @@
*/
/*!
+ \fn QLocale QSystemLocale::fallbackLocale() const
+
+ \since 4.6
+
+ Returns the locale used if the system locale is not able to answer a query.
+
+ Must be a QLocale instance based on the built-in CLDR data, and should
+ match what the system locale is using as closely as that data supports.
+*/
+
+/*!
\class QSystemLocale::CurrencyToStringArgument
\inmodule QtCore
@@ -1159,7 +1193,7 @@
\variable QSystemLocale::CurrencyToStringArgument::value
An input value that should be converted to its string representation.
- Contains one of QVariant::LongLong, QVariant::ULongLong or QVariant::Double
+ Contains one of QMetaType::LongLong, QMetaType::ULongLong or QMetaType::Double
types.
*/
/*!
@@ -1235,13 +1269,17 @@
*/
/*!
-\fn QString QLocale::toString(float i, char f = 'g', int prec = 6) const
-
+\fn QString QLocale::toString(float f, char format = 'g', int precision = 6) const
\overload
-\a f and \a prec have the same meaning as in QString::number(double, char, int).
+Returns a string representing the floating-point number \a f.
-\sa toDouble()
+The \a format and \a precision have the same meanings as described in \l
+{toString(double, char, int)}.
+
+\sa toFloat(), toDouble(), numberOptions(), exponential(), decimalPoint(), zeroDigit(),
+ positiveSign(), percent(), toCurrencyString(), formattedDataSize(),
+ QLocale::FloatingPointPrecisionOption
*/
/*!
@@ -1267,8 +1305,3 @@
\since 4.8
\overload
*/
-/*!
- \fn QString QLocale::toCurrencyString(float value, const QString &symbol) const
- \since 4.8
- \overload
-*/
diff --git a/src/corelib/text/qlocale_data_p.h b/src/corelib/text/qlocale_data_p.h
index 0501c59e1a..6175398dd9 100644
--- a/src/corelib/text/qlocale_data_p.h
+++ b/src/corelib/text/qlocale_data_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-3.0
#ifndef QLOCALE_DATA_P_H
#define QLOCALE_DATA_P_H
@@ -51,34 +15,71 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qendian.h>
+#include <QtCore/private/qlocale_p.h>
+
+#include <array>
+#include <cstring> // std::memcmp
QT_BEGIN_NAMESPACE
-/* This part of the file isn't generated, but written by hand since
- * Unicode CLDR doesn't contain measurement system information.
- */
-struct CountryLanguage
+/* This part of the file isn't generated, but written by hand. Unicode CLDR's
+ information about measurement systems doesn't say which to use by default in
+ each locale. Even if it did, adding another entry in every locale's row of
+ locale_data[] would take up much more memory than the small table below.
+*/
+struct TerritoryLanguage
{
quint16 languageId;
- quint16 countryId;
+ quint16 territoryId;
QLocale::MeasurementSystem system;
};
-static const CountryLanguage ImperialMeasurementSystems[] = {
+static constexpr TerritoryLanguage ImperialMeasurementSystems[] = {
{ QLocale::English, QLocale::UnitedStates, QLocale::ImperialUSSystem },
{ QLocale::English, QLocale::UnitedStatesMinorOutlyingIslands, QLocale::ImperialUSSystem },
{ QLocale::Spanish, QLocale::UnitedStates, QLocale::ImperialUSSystem },
{ QLocale::Hawaiian, QLocale::UnitedStates, QLocale::ImperialUSSystem },
{ QLocale::English, QLocale::UnitedKingdom, QLocale::ImperialUKSystem }
};
-static const int ImperialMeasurementSystemsCount =
- sizeof(ImperialMeasurementSystems)/sizeof(ImperialMeasurementSystems[0]);
+
+/*
+ Storage for alpha codes with length of up to 4 allowing efficient comparison.
+*/
+struct AlphaCode {
+ constexpr AlphaCode(char c1 = 0, char c2 = 0, char c3 = 0)
+ : c1(c2m(c1)), c2(c2m(c2)), c3(c2m(c3)), reserved(0) { }
+
+ uint16_t c1: 5, c2:5, c3: 5, reserved:1;
+
+ bool isValid() const noexcept { return c1 != 0; }
+
+ std::array<char, 4> decode() const { return {m2c(c1), m2c(c2), m2c(c3), 0}; }
+
+private:
+ static constexpr uint16_t c2m(char c) { return c ? c - 'a' + 1 : 0; }
+ static constexpr char m2c (uint16_t c) { return c ? c + 'a' - 1 : 0; }
+
+ friend bool operator==(AlphaCode lhs, AlphaCode rhs) noexcept
+ {
+ static_assert(std::has_unique_object_representations_v<AlphaCode>,
+ "memcmp() cannot be used to implement equality on "
+ "types that don't have unique object representations");
+ return std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
+ }
+};
+
+struct LanguageCodeEntry {
+ AlphaCode part1;
+ AlphaCode part2B;
+ AlphaCode part2T;
+ AlphaCode part3;
+};
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-04-07 from the
- Common Locale Data Repository v36
+ This part of the file was generated on 2024-04-04 from the
+ Common Locale Data Repository v44.1
http://www.unicode.org/cldr/
@@ -87,5412 +88,7101 @@ static const int ImperialMeasurementSystemsCount =
edited) CLDR data; see qtbase/util/locale_database/.
*/
-static const QLocaleId likely_subtags[] = {
- { 4, 0, 0 }, { 4, 7, 69 }, // aa -> aa_Latn_ET
- { 2, 0, 0 }, { 2, 2, 81 }, // ab -> ab_Cyrl_GE
- { 255, 0, 0 }, { 255, 36, 102 }, // ae -> ae_Avst_IR
- { 5, 0, 0 }, { 5, 7, 195 }, // af -> af_Latn_ZA
- { 237, 0, 0 }, { 237, 7, 37 }, // agq -> agq_Latn_CM
- { 340, 0, 0 }, { 340, 128, 100 }, // aho -> aho_Ahom_IN
- { 146, 0, 0 }, { 146, 7, 83 }, // ak -> ak_Latn_GH
- { 262, 0, 0 }, { 262, 94, 103 }, // akk -> akk_Xsux_IQ
- { 7, 0, 0 }, { 7, 14, 69 }, // am -> am_Ethi_ET
- { 261, 0, 0 }, { 261, 7, 197 }, // an -> an_Latn_ES
- { 8, 0, 0 }, { 8, 1, 64 }, // ar -> ar_Arab_EG
- { 265, 0, 0 }, { 265, 57, 102 }, // arc -> arc_Armi_IR
- { 265, 119, 0 }, { 265, 119, 109 }, // arc_Nbat -> arc_Nbat_JO
- { 265, 120, 0 }, { 265, 120, 207 }, // arc_Palm -> arc_Palm_SY
- { 315, 0, 0 }, { 315, 7, 43 }, // arn -> arn_Latn_CL
- { 10, 0, 0 }, { 10, 11, 100 }, // as -> as_Beng_IN
- { 205, 0, 0 }, { 205, 7, 210 }, // asa -> asa_Latn_TZ
- { 341, 0, 0 }, { 341, 133, 225 }, // ase -> ase_Sgnw_US
- { 256, 0, 0 }, { 256, 7, 197 }, // ast -> ast_Latn_ES
- { 216, 0, 0 }, { 216, 2, 178 }, // av -> av_Cyrl_RU
- { 11, 0, 0 }, { 11, 7, 26 }, // ay -> ay_Latn_BO
- { 12, 0, 0 }, { 12, 7, 15 }, // az -> az_Latn_AZ
- { 12, 0, 103 }, { 12, 1, 103 }, // az_IQ -> az_Arab_IQ
- { 12, 0, 102 }, { 12, 1, 102 }, // az_IR -> az_Arab_IR
- { 12, 0, 178 }, { 12, 2, 178 }, // az_RU -> az_Cyrl_RU
- { 12, 1, 0 }, { 12, 1, 102 }, // az_Arab -> az_Arab_IR
- { 13, 0, 0 }, { 13, 2, 178 }, // ba -> ba_Cyrl_RU
- { 266, 0, 0 }, { 266, 7, 101 }, // ban -> ban_Latn_ID
- { 238, 0, 0 }, { 238, 7, 37 }, // bas -> bas_Latn_CM
- { 267, 0, 0 }, { 267, 38, 37 }, // bax -> bax_Bamu_CM
- { 268, 0, 0 }, { 268, 7, 101 }, // bbc -> bbc_Latn_ID
- { 22, 0, 0 }, { 22, 2, 20 }, // be -> be_Cyrl_BY
- { 195, 0, 0 }, { 195, 7, 239 }, // bem -> bem_Latn_ZM
- { 186, 0, 0 }, { 186, 7, 210 }, // bez -> bez_Latn_TZ
- { 20, 0, 0 }, { 20, 2, 33 }, // bg -> bg_Cyrl_BG
- { 364, 0, 0 }, { 364, 1, 163 }, // bgn -> bgn_Arab_PK
- { 343, 0, 0 }, { 343, 13, 100 }, // bho -> bho_Deva_IN
- { 18, 0, 0 }, { 18, 7, 229 }, // bi -> bi_Latn_VU
- { 270, 0, 0 }, { 270, 7, 170 }, // bku -> bku_Latn_PH
- { 309, 0, 0 }, { 309, 100, 232 }, // blt -> blt_Tavt_VN
- { 188, 0, 0 }, { 188, 7, 132 }, // bm -> bm_Latn_ML
- { 15, 0, 0 }, { 15, 11, 18 }, // bn -> bn_Beng_BD
- { 121, 0, 0 }, { 121, 31, 44 }, // bo -> bo_Tibt_CN
- { 19, 0, 0 }, { 19, 7, 74 }, // br -> br_Latn_FR
- { 215, 0, 0 }, { 215, 13, 100 }, // brx -> brx_Deva_IN
- { 142, 0, 0 }, { 142, 7, 27 }, // bs -> bs_Latn_BA
- { 336, 0, 0 }, { 336, 106, 121 }, // bsq -> bsq_Bass_LR
- { 312, 0, 0 }, { 312, 7, 37 }, // bss -> bss_Latn_CM
- { 269, 0, 0 }, { 269, 7, 101 }, // bug -> bug_Latn_ID
- { 152, 0, 0 }, { 152, 14, 67 }, // byn -> byn_Ethi_ER
- { 24, 0, 0 }, { 24, 7, 197 }, // ca -> ca_Latn_ES
- { 156, 0, 0 }, { 156, 7, 157 }, // cch -> cch_Latn_NG
- { 272, 0, 0 }, { 272, 46, 18 }, // ccp -> ccp_Cakm_BD
- { 218, 0, 0 }, { 218, 2, 178 }, // ce -> ce_Cyrl_RU
- { 365, 0, 0 }, { 365, 7, 170 }, // ceb -> ceb_Latn_PH
- { 211, 0, 0 }, { 211, 7, 221 }, // cgg -> cgg_Latn_UG
- { 217, 0, 0 }, { 217, 7, 89 }, // ch -> ch_Latn_GU
- { 190, 0, 0 }, { 190, 12, 225 }, // chr -> chr_Cher_US
- { 367, 0, 0 }, { 367, 7, 225 }, // cic -> cic_Latn_US
- { 276, 0, 0 }, { 276, 47, 232 }, // cjm -> cjm_Cham_VN
- { 316, 0, 0 }, { 316, 1, 103 }, // ckb -> ckb_Arab_IQ
- { 26, 0, 0 }, { 26, 7, 74 }, // co -> co_Latn_FR
- { 274, 0, 0 }, { 274, 48, 64 }, // cop -> cop_Copt_EG
- { 221, 0, 0 }, { 221, 44, 38 }, // cr -> cr_Cans_CA
- { 28, 0, 0 }, { 28, 7, 57 }, // cs -> cs_Latn_CZ
- { 338, 0, 0 }, { 338, 121, 147 }, // ctd -> ctd_Pauc_MM
- { 219, 0, 0 }, { 219, 2, 178 }, // cu -> cu_Cyrl_RU
- { 219, 52, 0 }, { 219, 52, 33 }, // cu_Glag -> cu_Glag_BG
- { 220, 0, 0 }, { 220, 2, 178 }, // cv -> cv_Cyrl_RU
- { 134, 0, 0 }, { 134, 7, 224 }, // cy -> cy_Latn_GB
- { 29, 0, 0 }, { 29, 7, 58 }, // da -> da_Latn_DK
- { 176, 0, 0 }, { 176, 7, 111 }, // dav -> dav_Latn_KE
- { 42, 0, 0 }, { 42, 7, 82 }, // de -> de_Latn_DE
- { 239, 0, 0 }, { 239, 7, 156 }, // dje -> dje_Latn_NE
- { 275, 0, 0 }, { 275, 1, 100 }, // doi -> doi_Arab_IN
- { 317, 0, 0 }, { 317, 7, 82 }, // dsb -> dsb_Latn_DE
- { 240, 0, 0 }, { 240, 7, 37 }, // dua -> dua_Latn_CM
- { 143, 0, 0 }, { 143, 29, 131 }, // dv -> dv_Thaa_MV
- { 241, 0, 0 }, { 241, 7, 187 }, // dyo -> dyo_Latn_SN
- { 16, 0, 0 }, { 16, 31, 25 }, // dz -> dz_Tibt_BT
- { 189, 0, 0 }, { 189, 7, 111 }, // ebu -> ebu_Latn_KE
- { 161, 0, 0 }, { 161, 7, 83 }, // ee -> ee_Latn_GH
- { 263, 0, 0 }, { 263, 50, 64 }, // egy -> egy_Egyp_EG
- { 277, 0, 0 }, { 277, 63, 147 }, // eky -> eky_Kali_MM
- { 43, 0, 0 }, { 43, 16, 85 }, // el -> el_Grek_GR
- { 31, 0, 0 }, { 31, 7, 225 }, // en -> en_Latn_US
- { 31, 92, 0 }, { 31, 92, 224 }, // en_Shaw -> en_Shaw_GB
- { 32, 0, 0 }, { 32, 7, 260 }, // eo -> eo_Latn_001
- { 111, 0, 0 }, { 111, 7, 197 }, // es -> es_Latn_ES
- { 33, 0, 0 }, { 33, 7, 68 }, // et -> et_Latn_EE
- { 278, 0, 0 }, { 278, 79, 106 }, // ett -> ett_Ital_IT
- { 14, 0, 0 }, { 14, 7, 197 }, // eu -> eu_Latn_ES
- { 242, 0, 0 }, { 242, 7, 37 }, // ewo -> ewo_Latn_CM
- { 89, 0, 0 }, { 89, 1, 102 }, // fa -> fa_Arab_IR
- { 177, 0, 0 }, { 177, 7, 187 }, // ff -> ff_Latn_SN
- { 177, 134, 0 }, { 177, 134, 91 }, // ff_Adlm -> ff_Adlm_GN
- { 36, 0, 0 }, { 36, 7, 73 }, // fi -> fi_Latn_FI
- { 166, 0, 0 }, { 166, 7, 170 }, // fil -> fil_Latn_PH
- { 35, 0, 0 }, { 35, 7, 72 }, // fj -> fj_Latn_FJ
- { 34, 0, 0 }, { 34, 7, 71 }, // fo -> fo_Latn_FO
- { 37, 0, 0 }, { 37, 7, 74 }, // fr -> fr_Latn_FR
- { 159, 0, 0 }, { 159, 7, 106 }, // fur -> fur_Latn_IT
- { 38, 0, 0 }, { 38, 7, 151 }, // fy -> fy_Latn_NL
- { 57, 0, 0 }, { 57, 7, 104 }, // ga -> ga_Latn_IE
- { 148, 0, 0 }, { 148, 7, 83 }, // gaa -> gaa_Latn_GH
- { 39, 0, 0 }, { 39, 7, 224 }, // gd -> gd_Latn_GB
- { 153, 0, 0 }, { 153, 14, 69 }, // gez -> gez_Ethi_ET
- { 40, 0, 0 }, { 40, 7, 197 }, // gl -> gl_Latn_ES
- { 45, 0, 0 }, { 45, 7, 168 }, // gn -> gn_Latn_PY
- { 279, 0, 0 }, { 279, 53, 222 }, // got -> got_Goth_UA
- { 264, 0, 0 }, { 264, 49, 56 }, // grc -> grc_Cprt_CY
- { 264, 68, 0 }, { 264, 68, 85 }, // grc_Linb -> grc_Linb_GR
- { 167, 0, 0 }, { 167, 7, 206 }, // gsw -> gsw_Latn_CH
- { 46, 0, 0 }, { 46, 17, 100 }, // gu -> gu_Gujr_IN
- { 175, 0, 0 }, { 175, 7, 111 }, // guz -> guz_Latn_KE
- { 144, 0, 0 }, { 144, 7, 251 }, // gv -> gv_Latn_IM
- { 47, 0, 0 }, { 47, 7, 157 }, // ha -> ha_Latn_NG
- { 47, 0, 37 }, { 47, 1, 37 }, // ha_CM -> ha_Arab_CM
- { 47, 0, 201 }, { 47, 1, 201 }, // ha_SD -> ha_Arab_SD
- { 163, 0, 0 }, { 163, 7, 225 }, // haw -> haw_Latn_US
- { 48, 0, 0 }, { 48, 18, 105 }, // he -> he_Hebr_IL
- { 49, 0, 0 }, { 49, 13, 100 }, // hi -> hi_Deva_IN
- { 344, 0, 0 }, { 344, 129, 217 }, // hlu -> hlu_Hluw_TR
- { 282, 0, 0 }, { 282, 86, 44 }, // hmd -> hmd_Plrd_CN
- { 333, 0, 0 }, { 333, 110, 117 }, // hnj -> hnj_Hmng_LA
- { 280, 0, 0 }, { 280, 7, 170 }, // hnn -> hnn_Latn_PH
- { 224, 0, 0 }, { 224, 7, 167 }, // ho -> ho_Latn_PG
- { 334, 0, 0 }, { 334, 13, 100 }, // hoc -> hoc_Deva_IN
- { 27, 0, 0 }, { 27, 7, 54 }, // hr -> hr_Latn_HR
- { 318, 0, 0 }, { 318, 7, 82 }, // hsb -> hsb_Latn_DE
- { 222, 0, 0 }, { 222, 7, 94 }, // ht -> ht_Latn_HT
- { 50, 0, 0 }, { 50, 7, 98 }, // hu -> hu_Latn_HU
- { 9, 0, 0 }, { 9, 10, 11 }, // hy -> hy_Armn_AM
- { 223, 0, 0 }, { 223, 7, 148 }, // hz -> hz_Latn_NA
- { 53, 0, 0 }, { 53, 7, 260 }, // ia -> ia_Latn_001
- { 52, 0, 0 }, { 52, 7, 101 }, // id -> id_Latn_ID
- { 149, 0, 0 }, { 149, 7, 157 }, // ig -> ig_Latn_NG
- { 168, 0, 0 }, { 168, 34, 44 }, // ii -> ii_Yiii_CN
- { 56, 0, 0 }, { 56, 7, 225 }, // ik -> ik_Latn_US
- { 281, 0, 0 }, { 281, 2, 178 }, // inh -> inh_Cyrl_RU
- { 360, 0, 0 }, { 360, 7, 260 }, // io -> io_Latn_001
- { 51, 0, 0 }, { 51, 7, 99 }, // is -> is_Latn_IS
- { 58, 0, 0 }, { 58, 7, 106 }, // it -> it_Latn_IT
- { 55, 0, 0 }, { 55, 44, 38 }, // iu -> iu_Cans_CA
- { 59, 0, 0 }, { 59, 19, 108 }, // ja -> ja_Jpan_JP
- { 361, 0, 0 }, { 361, 7, 260 }, // jbo -> jbo_Latn_001
- { 257, 0, 0 }, { 257, 7, 37 }, // jgo -> jgo_Latn_CM
- { 200, 0, 0 }, { 200, 7, 210 }, // jmc -> jmc_Latn_TZ
- { 60, 0, 0 }, { 60, 7, 101 }, // jv -> jv_Latn_ID
- { 41, 0, 0 }, { 41, 15, 81 }, // ka -> ka_Geor_GE
- { 184, 0, 0 }, { 184, 7, 3 }, // kab -> kab_Latn_DZ
- { 158, 0, 0 }, { 158, 7, 157 }, // kaj -> kaj_Latn_NG
- { 150, 0, 0 }, { 150, 7, 111 }, // kam -> kam_Latn_KE
- { 164, 0, 0 }, { 164, 7, 157 }, // kcg -> kcg_Latn_NG
- { 192, 0, 0 }, { 192, 7, 210 }, // kde -> kde_Latn_TZ
- { 196, 0, 0 }, { 196, 7, 39 }, // kea -> kea_Latn_CV
- { 319, 0, 0 }, { 319, 7, 37 }, // ken -> ken_Latn_CM
- { 154, 0, 0 }, { 154, 7, 53 }, // kfo -> kfo_Latn_CI
- { 227, 0, 0 }, { 227, 7, 49 }, // kg -> kg_Latn_CD
- { 286, 0, 0 }, { 286, 76, 44 }, // khb -> khb_Talu_CN
- { 208, 0, 0 }, { 208, 7, 132 }, // khq -> khq_Latn_ML
- { 178, 0, 0 }, { 178, 7, 111 }, // ki -> ki_Latn_KE
- { 228, 0, 0 }, { 228, 7, 148 }, // kj -> kj_Latn_NA
- { 63, 0, 0 }, { 63, 2, 110 }, // kk -> kk_Cyrl_KZ
- { 63, 0, 1 }, { 63, 1, 1 }, // kk_AF -> kk_Arab_AF
- { 63, 0, 44 }, { 63, 1, 44 }, // kk_CN -> kk_Arab_CN
- { 63, 0, 102 }, { 63, 1, 102 }, // kk_IR -> kk_Arab_IR
- { 63, 0, 143 }, { 63, 1, 143 }, // kk_MN -> kk_Arab_MN
- { 63, 1, 0 }, { 63, 1, 44 }, // kk_Arab -> kk_Arab_CN
- { 258, 0, 0 }, { 258, 7, 37 }, // kkj -> kkj_Latn_CM
- { 44, 0, 0 }, { 44, 7, 86 }, // kl -> kl_Latn_GL
- { 198, 0, 0 }, { 198, 7, 111 }, // kln -> kln_Latn_KE
- { 23, 0, 0 }, { 23, 20, 36 }, // km -> km_Khmr_KH
- { 61, 0, 0 }, { 61, 21, 100 }, // kn -> kn_Knda_IN
- { 66, 0, 0 }, { 66, 22, 114 }, // ko -> ko_Kore_KR
- { 147, 0, 0 }, { 147, 13, 100 }, // kok -> kok_Deva_IN
- { 169, 0, 0 }, { 169, 7, 121 }, // kpe -> kpe_Latn_LR
- { 225, 0, 0 }, { 225, 7, 0 }, // kr -> kr_Latn
- { 62, 0, 0 }, { 62, 1, 100 }, // ks -> ks_Arab_IN
- { 214, 0, 0 }, { 214, 7, 210 }, // ksb -> ksb_Latn_TZ
- { 243, 0, 0 }, { 243, 7, 37 }, // ksf -> ksf_Latn_CM
- { 201, 0, 0 }, { 201, 7, 82 }, // ksh -> ksh_Latn_DE
- { 67, 0, 0 }, { 67, 7, 217 }, // ku -> ku_Latn_TR
- { 67, 0, 119 }, { 67, 1, 119 }, // ku_LB -> ku_Arab_LB
- { 67, 1, 0 }, { 67, 1, 103 }, // ku_Arab -> ku_Arab_IQ
- { 226, 0, 0 }, { 226, 2, 178 }, // kv -> kv_Cyrl_RU
- { 145, 0, 0 }, { 145, 7, 224 }, // kw -> kw_Latn_GB
- { 65, 0, 0 }, { 65, 2, 116 }, // ky -> ky_Cyrl_KG
- { 65, 0, 44 }, { 65, 1, 44 }, // ky_CN -> ky_Arab_CN
- { 65, 0, 217 }, { 65, 7, 217 }, // ky_TR -> ky_Latn_TR
- { 65, 1, 0 }, { 65, 1, 44 }, // ky_Arab -> ky_Arab_CN
- { 65, 7, 0 }, { 65, 7, 217 }, // ky_Latn -> ky_Latn_TR
- { 70, 0, 0 }, { 70, 7, 230 }, // la -> la_Latn_VA
- { 332, 0, 0 }, { 332, 112, 85 }, // lab -> lab_Lina_GR
- { 193, 0, 0 }, { 193, 7, 210 }, // lag -> lag_Latn_TZ
- { 231, 0, 0 }, { 231, 7, 125 }, // lb -> lb_Latn_LU
- { 283, 0, 0 }, { 283, 66, 100 }, // lep -> lep_Lepc_IN
- { 335, 0, 0 }, { 335, 2, 178 }, // lez -> lez_Cyrl_RU
- { 194, 0, 0 }, { 194, 7, 221 }, // lg -> lg_Latn_UG
- { 229, 0, 0 }, { 229, 7, 151 }, // li -> li_Latn_NL
- { 284, 0, 0 }, { 284, 13, 150 }, // lif -> lif_Deva_NP
- { 284, 67, 0 }, { 284, 67, 100 }, // lif_Limb -> lif_Limb_IN
- { 285, 0, 0 }, { 285, 51, 44 }, // lis -> lis_Lisu_CN
- { 313, 0, 0 }, { 313, 7, 225 }, // lkt -> lkt_Latn_US
- { 72, 0, 0 }, { 72, 7, 49 }, // ln -> ln_Latn_CD
- { 69, 0, 0 }, { 69, 23, 117 }, // lo -> lo_Laoo_LA
- { 349, 0, 0 }, { 349, 1, 102 }, // lrc -> lrc_Arab_IR
- { 73, 0, 0 }, { 73, 7, 124 }, // lt -> lt_Latn_LT
- { 230, 0, 0 }, { 230, 7, 49 }, // lu -> lu_Latn_CD
- { 210, 0, 0 }, { 210, 7, 111 }, // luo -> luo_Latn_KE
- { 204, 0, 0 }, { 204, 7, 111 }, // luy -> luy_Latn_KE
- { 71, 0, 0 }, { 71, 7, 118 }, // lv -> lv_Latn_LV
- { 345, 0, 0 }, { 345, 5, 44 }, // lzh -> lzh_Hans_CN
- { 339, 0, 0 }, { 339, 13, 100 }, // mai -> mai_Deva_IN
- { 289, 0, 0 }, { 289, 7, 80 }, // man -> man_Latn_GM
- { 289, 0, 91 }, { 289, 75, 91 }, // man_GN -> man_Nkoo_GN
- { 289, 75, 0 }, { 289, 75, 91 }, // man_Nkoo -> man_Nkoo_GN
- { 202, 0, 0 }, { 202, 7, 111 }, // mas -> mas_Latn_KE
- { 330, 0, 0 }, { 330, 7, 189 }, // men -> men_Latn_SL
- { 197, 0, 0 }, { 197, 7, 111 }, // mer -> mer_Latn_KE
- { 191, 0, 0 }, { 191, 7, 137 }, // mfe -> mfe_Latn_MU
- { 75, 0, 0 }, { 75, 7, 128 }, // mg -> mg_Latn_MG
- { 244, 0, 0 }, { 244, 7, 146 }, // mgh -> mgh_Latn_MZ
- { 259, 0, 0 }, { 259, 7, 37 }, // mgo -> mgo_Latn_CM
- { 81, 0, 0 }, { 81, 7, 134 }, // mh -> mh_Latn_MH
- { 79, 0, 0 }, { 79, 7, 154 }, // mi -> mi_Latn_NZ
- { 356, 0, 0 }, { 356, 130, 103 }, // mis -> mis_Hatr_IQ
- { 74, 0, 0 }, { 74, 2, 127 }, // mk -> mk_Cyrl_MK
- { 77, 0, 0 }, { 77, 24, 100 }, // ml -> ml_Mlym_IN
- { 82, 0, 0 }, { 82, 2, 143 }, // mn -> mn_Cyrl_MN
- { 82, 0, 44 }, { 82, 8, 44 }, // mn_CN -> mn_Mong_CN
- { 82, 8, 0 }, { 82, 8, 44 }, // mn_Mong -> mn_Mong_CN
- { 290, 0, 0 }, { 290, 11, 100 }, // mni -> mni_Beng_IN
- { 320, 0, 0 }, { 320, 7, 38 }, // moh -> moh_Latn_CA
- { 80, 0, 0 }, { 80, 13, 100 }, // mr -> mr_Deva_IN
- { 347, 0, 0 }, { 347, 117, 18 }, // mro -> mro_Mroo_BD
- { 76, 0, 0 }, { 76, 7, 130 }, // ms -> ms_Latn_MY
- { 76, 0, 46 }, { 76, 1, 46 }, // ms_CC -> ms_Arab_CC
- { 76, 0, 101 }, { 76, 1, 101 }, // ms_ID -> ms_Arab_ID
- { 78, 0, 0 }, { 78, 7, 133 }, // mt -> mt_Latn_MT
- { 245, 0, 0 }, { 245, 7, 37 }, // mua -> mua_Latn_CM
- { 368, 0, 0 }, { 368, 7, 225 }, // mus -> mus_Latn_US
- { 21, 0, 0 }, { 21, 25, 147 }, // my -> my_Mymr_MM
- { 366, 0, 0 }, { 366, 2, 178 }, // myv -> myv_Cyrl_RU
- { 273, 0, 0 }, { 273, 71, 102 }, // myz -> myz_Mand_IR
- { 346, 0, 0 }, { 346, 1, 102 }, // mzn -> mzn_Arab_IR
- { 83, 0, 0 }, { 83, 7, 149 }, // na -> na_Latn_NR
- { 199, 0, 0 }, { 199, 7, 148 }, // naq -> naq_Latn_NA
- { 85, 0, 0 }, { 85, 7, 161 }, // nb -> nb_Latn_NO
- { 181, 0, 0 }, { 181, 7, 240 }, // nd -> nd_Latn_ZW
- { 170, 0, 0 }, { 170, 7, 82 }, // nds -> nds_Latn_DE
- { 84, 0, 0 }, { 84, 13, 150 }, // ne -> ne_Deva_NP
- { 348, 0, 0 }, { 348, 13, 150 }, // new -> new_Deva_NP
- { 233, 0, 0 }, { 233, 7, 148 }, // ng -> ng_Latn_NA
- { 30, 0, 0 }, { 30, 7, 151 }, // nl -> nl_Latn_NL
- { 246, 0, 0 }, { 246, 7, 37 }, // nmg -> nmg_Latn_CM
- { 141, 0, 0 }, { 141, 7, 161 }, // nn -> nn_Latn_NO
- { 260, 0, 0 }, { 260, 7, 37 }, // nnh -> nnh_Latn_CM
- { 292, 0, 0 }, { 292, 65, 211 }, // nod -> nod_Lana_TH
- { 294, 0, 0 }, { 294, 88, 205 }, // non -> non_Runr_SE
- { 321, 0, 0 }, { 321, 75, 91 }, // nqo -> nqo_Nkoo_GN
- { 171, 0, 0 }, { 171, 7, 195 }, // nr -> nr_Latn_ZA
- { 172, 0, 0 }, { 172, 7, 195 }, // nso -> nso_Latn_ZA
- { 247, 0, 0 }, { 247, 7, 254 }, // nus -> nus_Latn_SS
- { 232, 0, 0 }, { 232, 7, 225 }, // nv -> nv_Latn_US
- { 165, 0, 0 }, { 165, 7, 129 }, // ny -> ny_Latn_MW
- { 185, 0, 0 }, { 185, 7, 221 }, // nyn -> nyn_Latn_UG
- { 86, 0, 0 }, { 86, 7, 74 }, // oc -> oc_Latn_FR
- { 3, 0, 0 }, { 3, 7, 69 }, // om -> om_Latn_ET
- { 87, 0, 0 }, { 87, 26, 100 }, // or -> or_Orya_IN
- { 101, 0, 0 }, { 101, 2, 81 }, // os -> os_Cyrl_GE
- { 358, 0, 0 }, { 358, 138, 225 }, // osa -> osa_Osge_US
- { 296, 0, 0 }, { 296, 82, 143 }, // otk -> otk_Orkh_MN
- { 92, 0, 0 }, { 92, 4, 100 }, // pa -> pa_Guru_IN
- { 92, 0, 163 }, { 92, 1, 163 }, // pa_PK -> pa_Arab_PK
- { 92, 1, 0 }, { 92, 1, 163 }, // pa_Arab -> pa_Arab_PK
- { 297, 0, 0 }, { 297, 58, 102 }, // pal -> pal_Phli_IR
- { 297, 123, 0 }, { 297, 123, 44 }, // pal_Phlp -> pal_Phlp_CN
- { 351, 0, 0 }, { 351, 7, 12 }, // pap -> pap_Latn_AW
- { 350, 0, 0 }, { 350, 7, 164 }, // pau -> pau_Latn_PW
- { 295, 0, 0 }, { 295, 80, 102 }, // peo -> peo_Xpeo_IR
- { 299, 0, 0 }, { 299, 85, 119 }, // phn -> phn_Phnx_LB
- { 342, 0, 0 }, { 342, 41, 100 }, // pka -> pka_Brah_IN
- { 90, 0, 0 }, { 90, 7, 172 }, // pl -> pl_Latn_PL
- { 300, 0, 0 }, { 300, 64, 163 }, // pra -> pra_Khar_PK
- { 322, 0, 0 }, { 322, 7, 260 }, // prg -> prg_Latn_001
- { 88, 0, 0 }, { 88, 1, 1 }, // ps -> ps_Arab_AF
- { 91, 0, 0 }, { 91, 7, 30 }, // pt -> pt_Latn_BR
- { 93, 0, 0 }, { 93, 7, 169 }, // qu -> qu_Latn_PE
- { 323, 0, 0 }, { 323, 7, 90 }, // quc -> quc_Latn_GT
- { 301, 0, 0 }, { 301, 7, 101 }, // rej -> rej_Latn_ID
- { 94, 0, 0 }, { 94, 7, 206 }, // rm -> rm_Latn_CH
- { 68, 0, 0 }, { 68, 7, 35 }, // rn -> rn_Latn_BI
- { 95, 0, 0 }, { 95, 7, 177 }, // ro -> ro_Latn_RO
- { 182, 0, 0 }, { 182, 7, 210 }, // rof -> rof_Latn_TZ
- { 96, 0, 0 }, { 96, 2, 178 }, // ru -> ru_Cyrl_RU
- { 64, 0, 0 }, { 64, 7, 179 }, // rw -> rw_Latn_RW
- { 209, 0, 0 }, { 209, 7, 210 }, // rwk -> rwk_Latn_TZ
- { 99, 0, 0 }, { 99, 13, 100 }, // sa -> sa_Deva_IN
- { 248, 0, 0 }, { 248, 2, 178 }, // sah -> sah_Cyrl_RU
- { 179, 0, 0 }, { 179, 7, 111 }, // saq -> saq_Latn_KE
- { 304, 0, 0 }, { 304, 7, 100 }, // sat -> sat_Latn_IN
- { 305, 0, 0 }, { 305, 90, 100 }, // saz -> saz_Saur_IN
- { 249, 0, 0 }, { 249, 7, 210 }, // sbp -> sbp_Latn_TZ
- { 115, 0, 0 }, { 115, 7, 106 }, // sc -> sc_Latn_IT
- { 362, 0, 0 }, { 362, 7, 106 }, // scn -> scn_Latn_IT
- { 105, 0, 0 }, { 105, 1, 163 }, // sd -> sd_Arab_PK
- { 105, 13, 0 }, { 105, 13, 100 }, // sd_Deva -> sd_Deva_IN
- { 105, 111, 0 }, { 105, 111, 100 }, // sd_Khoj -> sd_Khoj_IN
- { 105, 125, 0 }, { 105, 125, 100 }, // sd_Sind -> sd_Sind_IN
- { 363, 0, 0 }, { 363, 1, 102 }, // sdh -> sdh_Arab_IR
- { 173, 0, 0 }, { 173, 7, 161 }, // se -> se_Latn_NO
- { 180, 0, 0 }, { 180, 7, 146 }, // seh -> seh_Latn_MZ
- { 213, 0, 0 }, { 213, 7, 132 }, // ses -> ses_Latn_ML
- { 98, 0, 0 }, { 98, 7, 41 }, // sg -> sg_Latn_CF
- { 293, 0, 0 }, { 293, 77, 104 }, // sga -> sga_Ogam_IE
- { 183, 0, 0 }, { 183, 9, 145 }, // shi -> shi_Tfng_MA
- { 106, 0, 0 }, { 106, 32, 198 }, // si -> si_Sinh_LK
- { 155, 0, 0 }, { 155, 7, 69 }, // sid -> sid_Latn_ET
- { 108, 0, 0 }, { 108, 7, 191 }, // sk -> sk_Latn_SK
- { 352, 0, 0 }, { 352, 1, 163 }, // skr -> skr_Arab_PK
- { 109, 0, 0 }, { 109, 7, 192 }, // sl -> sl_Latn_SI
- { 97, 0, 0 }, { 97, 7, 183 }, // sm -> sm_Latn_WS
- { 324, 0, 0 }, { 324, 7, 205 }, // sma -> sma_Latn_SE
- { 325, 0, 0 }, { 325, 7, 205 }, // smj -> smj_Latn_SE
- { 326, 0, 0 }, { 326, 7, 73 }, // smn -> smn_Latn_FI
- { 303, 0, 0 }, { 303, 89, 105 }, // smp -> smp_Samr_IL
- { 327, 0, 0 }, { 327, 7, 73 }, // sms -> sms_Latn_FI
- { 104, 0, 0 }, { 104, 7, 240 }, // sn -> sn_Latn_ZW
- { 110, 0, 0 }, { 110, 7, 194 }, // so -> so_Latn_SO
- { 6, 0, 0 }, { 6, 7, 2 }, // sq -> sq_Latn_AL
- { 100, 0, 0 }, { 100, 2, 243 }, // sr -> sr_Cyrl_RS
- { 100, 0, 242 }, { 100, 7, 242 }, // sr_ME -> sr_Latn_ME
- { 100, 0, 177 }, { 100, 7, 177 }, // sr_RO -> sr_Latn_RO
- { 100, 0, 178 }, { 100, 7, 178 }, // sr_RU -> sr_Latn_RU
- { 100, 0, 217 }, { 100, 7, 217 }, // sr_TR -> sr_Latn_TR
- { 306, 0, 0 }, { 306, 93, 100 }, // srb -> srb_Sora_IN
- { 107, 0, 0 }, { 107, 7, 195 }, // ss -> ss_Latn_ZA
- { 207, 0, 0 }, { 207, 7, 67 }, // ssy -> ssy_Latn_ER
- { 102, 0, 0 }, { 102, 7, 195 }, // st -> st_Latn_ZA
- { 112, 0, 0 }, { 112, 7, 101 }, // su -> su_Latn_ID
- { 114, 0, 0 }, { 114, 7, 205 }, // sv -> sv_Latn_SE
- { 113, 0, 0 }, { 113, 7, 210 }, // sw -> sw_Latn_TZ
- { 250, 0, 0 }, { 250, 7, 49 }, // swc -> swc_Latn_CD
- { 307, 0, 0 }, { 307, 11, 18 }, // syl -> syl_Beng_BD
- { 151, 0, 0 }, { 151, 33, 103 }, // syr -> syr_Syrc_IQ
- { 369, 0, 0 }, { 369, 7, 172 }, // szl -> szl_Latn_PL
- { 117, 0, 0 }, { 117, 27, 100 }, // ta -> ta_Taml_IN
- { 308, 0, 0 }, { 308, 7, 170 }, // tbw -> tbw_Latn_PH
- { 310, 0, 0 }, { 310, 99, 44 }, // tdd -> tdd_Tale_CN
- { 119, 0, 0 }, { 119, 28, 100 }, // te -> te_Telu_IN
- { 206, 0, 0 }, { 206, 7, 221 }, // teo -> teo_Latn_UG
- { 116, 0, 0 }, { 116, 2, 209 }, // tg -> tg_Cyrl_TJ
- { 116, 0, 163 }, { 116, 1, 163 }, // tg_PK -> tg_Arab_PK
- { 116, 1, 0 }, { 116, 1, 163 }, // tg_Arab -> tg_Arab_PK
- { 120, 0, 0 }, { 120, 30, 211 }, // th -> th_Thai_TH
- { 122, 0, 0 }, { 122, 14, 69 }, // ti -> ti_Ethi_ET
- { 157, 0, 0 }, { 157, 14, 67 }, // tig -> tig_Ethi_ER
- { 126, 0, 0 }, { 126, 7, 218 }, // tk -> tk_Latn_TM
- { 353, 0, 0 }, { 353, 7, 213 }, // tkl -> tkl_Latn_TK
- { 103, 0, 0 }, { 103, 7, 195 }, // tn -> tn_Latn_ZA
- { 123, 0, 0 }, { 123, 7, 214 }, // to -> to_Latn_TO
- { 354, 0, 0 }, { 354, 7, 167 }, // tpi -> tpi_Latn_PG
- { 125, 0, 0 }, { 125, 7, 217 }, // tr -> tr_Latn_TR
- { 174, 0, 0 }, { 174, 7, 208 }, // trv -> trv_Latn_TW
- { 124, 0, 0 }, { 124, 7, 195 }, // ts -> ts_Latn_ZA
- { 118, 0, 0 }, { 118, 2, 178 }, // tt -> tt_Cyrl_RU
- { 355, 0, 0 }, { 355, 7, 220 }, // tvl -> tvl_Latn_TV
- { 251, 0, 0 }, { 251, 7, 156 }, // twq -> twq_Latn_NE
- { 359, 0, 0 }, { 359, 139, 44 }, // txg -> txg_Tang_CN
- { 127, 0, 0 }, { 127, 7, 77 }, // ty -> ty_Latn_PF
- { 212, 0, 0 }, { 212, 7, 145 }, // tzm -> tzm_Latn_MA
- { 128, 0, 0 }, { 128, 1, 44 }, // ug -> ug_Arab_CN
- { 128, 0, 110 }, { 128, 2, 110 }, // ug_KZ -> ug_Cyrl_KZ
- { 128, 0, 143 }, { 128, 2, 143 }, // ug_MN -> ug_Cyrl_MN
- { 128, 2, 0 }, { 128, 2, 110 }, // ug_Cyrl -> ug_Cyrl_KZ
- { 311, 0, 0 }, { 311, 102, 207 }, // uga -> uga_Ugar_SY
- { 129, 0, 0 }, { 129, 2, 222 }, // uk -> uk_Cyrl_UA
- { 130, 0, 0 }, { 130, 1, 163 }, // ur -> ur_Arab_PK
- { 131, 0, 0 }, { 131, 7, 228 }, // uz -> uz_Latn_UZ
- { 131, 0, 1 }, { 131, 1, 1 }, // uz_AF -> uz_Arab_AF
- { 131, 0, 44 }, { 131, 2, 44 }, // uz_CN -> uz_Cyrl_CN
- { 131, 1, 0 }, { 131, 1, 1 }, // uz_Arab -> uz_Arab_AF
- { 252, 0, 0 }, { 252, 35, 121 }, // vai -> vai_Vaii_LR
- { 160, 0, 0 }, { 160, 7, 195 }, // ve -> ve_Latn_ZA
- { 132, 0, 0 }, { 132, 7, 232 }, // vi -> vi_Latn_VN
- { 133, 0, 0 }, { 133, 7, 260 }, // vo -> vo_Latn_001
- { 187, 0, 0 }, { 187, 7, 210 }, // vun -> vun_Latn_TZ
- { 236, 0, 0 }, { 236, 7, 21 }, // wa -> wa_Latn_BE
- { 253, 0, 0 }, { 253, 7, 206 }, // wae -> wae_Latn_CH
- { 162, 0, 0 }, { 162, 14, 69 }, // wal -> wal_Ethi_ET
- { 328, 0, 0 }, { 328, 7, 13 }, // wbp -> wbp_Latn_AU
- { 135, 0, 0 }, { 135, 7, 187 }, // wo -> wo_Latn_SN
- { 271, 0, 0 }, { 271, 45, 217 }, // xcr -> xcr_Cari_TR
- { 136, 0, 0 }, { 136, 7, 195 }, // xh -> xh_Latn_ZA
- { 287, 0, 0 }, { 287, 69, 217 }, // xlc -> xlc_Lyci_TR
- { 288, 0, 0 }, { 288, 70, 217 }, // xld -> xld_Lydi_TR
- { 329, 0, 0 }, { 329, 114, 44 }, // xmn -> xmn_Mani_CN
- { 291, 0, 0 }, { 291, 74, 201 }, // xmr -> xmr_Merc_SD
- { 331, 0, 0 }, { 331, 118, 186 }, // xna -> xna_Narb_SA
- { 203, 0, 0 }, { 203, 7, 221 }, // xog -> xog_Latn_UG
- { 298, 0, 0 }, { 298, 59, 102 }, // xpr -> xpr_Prti_IR
- { 302, 0, 0 }, { 302, 81, 237 }, // xsa -> xsa_Sarb_YE
- { 254, 0, 0 }, { 254, 7, 37 }, // yav -> yav_Latn_CM
- { 137, 0, 0 }, { 137, 18, 260 }, // yi -> yi_Hebr_001
- { 138, 0, 0 }, { 138, 7, 157 }, // yo -> yo_Latn_NG
- { 357, 0, 0 }, { 357, 6, 97 }, // yue -> yue_Hant_HK
- { 357, 0, 44 }, { 357, 5, 44 }, // yue_CN -> yue_Hans_CN
- { 357, 5, 0 }, { 357, 5, 44 }, // yue_Hans -> yue_Hans_CN
- { 139, 0, 0 }, { 139, 7, 44 }, // za -> za_Latn_CN
- { 314, 0, 0 }, { 314, 9, 145 }, // zgh -> zgh_Tfng_MA
- { 25, 0, 0 }, { 25, 5, 44 }, // zh -> zh_Hans_CN
- { 25, 0, 13 }, { 25, 6, 13 }, // zh_AU -> zh_Hant_AU
- { 25, 0, 32 }, { 25, 6, 32 }, // zh_BN -> zh_Hant_BN
- { 25, 0, 224 }, { 25, 6, 224 }, // zh_GB -> zh_Hant_GB
- { 25, 0, 76 }, { 25, 6, 76 }, // zh_GF -> zh_Hant_GF
- { 25, 0, 97 }, { 25, 6, 97 }, // zh_HK -> zh_Hant_HK
- { 25, 0, 101 }, { 25, 6, 101 }, // zh_ID -> zh_Hant_ID
- { 25, 0, 126 }, { 25, 6, 126 }, // zh_MO -> zh_Hant_MO
- { 25, 0, 130 }, { 25, 6, 130 }, // zh_MY -> zh_Hant_MY
- { 25, 0, 166 }, { 25, 6, 166 }, // zh_PA -> zh_Hant_PA
- { 25, 0, 77 }, { 25, 6, 77 }, // zh_PF -> zh_Hant_PF
- { 25, 0, 170 }, { 25, 6, 170 }, // zh_PH -> zh_Hant_PH
- { 25, 0, 202 }, { 25, 6, 202 }, // zh_SR -> zh_Hant_SR
- { 25, 0, 211 }, { 25, 6, 211 }, // zh_TH -> zh_Hant_TH
- { 25, 0, 208 }, { 25, 6, 208 }, // zh_TW -> zh_Hant_TW
- { 25, 0, 225 }, { 25, 6, 225 }, // zh_US -> zh_Hant_US
- { 25, 0, 232 }, { 25, 6, 232 }, // zh_VN -> zh_Hant_VN
- { 25, 40, 0 }, { 25, 40, 208 }, // zh_Bopo -> zh_Bopo_TW
- { 25, 140, 0 }, { 25, 140, 208 }, // zh_Hanb -> zh_Hanb_TW
- { 25, 6, 0 }, { 25, 6, 208 }, // zh_Hant -> zh_Hant_TW
- { 140, 0, 0 }, { 140, 7, 195 }, // zu -> zu_Latn_ZA
- { 0, 0, 261 }, { 96, 2, 178 }, // und_150 -> ru_Cyrl_RU
- { 0, 0, 246 }, { 111, 7, 246 }, // und_419 -> es_Latn_419
- { 0, 0, 5 }, { 24, 7, 5 }, // und_AD -> ca_Latn_AD
- { 0, 0, 223 }, { 8, 1, 223 }, // und_AE -> ar_Arab_AE
- { 0, 0, 1 }, { 89, 1, 1 }, // und_AF -> fa_Arab_AF
- { 0, 0, 2 }, { 6, 7, 2 }, // und_AL -> sq_Latn_AL
- { 0, 0, 11 }, { 9, 10, 11 }, // und_AM -> hy_Armn_AM
- { 0, 0, 6 }, { 91, 7, 6 }, // und_AO -> pt_Latn_AO
- { 0, 0, 8 }, { 0, 7, 8 }, // und_AQ -> und_Latn_AQ
- { 0, 0, 10 }, { 111, 7, 10 }, // und_AR -> es_Latn_AR
- { 0, 0, 4 }, { 97, 7, 4 }, // und_AS -> sm_Latn_AS
- { 0, 0, 14 }, { 42, 7, 14 }, // und_AT -> de_Latn_AT
- { 0, 0, 12 }, { 30, 7, 12 }, // und_AW -> nl_Latn_AW
- { 0, 0, 248 }, { 114, 7, 248 }, // und_AX -> sv_Latn_AX
- { 0, 0, 15 }, { 12, 7, 15 }, // und_AZ -> az_Latn_AZ
- { 0, 0, 27 }, { 142, 7, 27 }, // und_BA -> bs_Latn_BA
- { 0, 0, 18 }, { 15, 11, 18 }, // und_BD -> bn_Beng_BD
- { 0, 0, 21 }, { 30, 7, 21 }, // und_BE -> nl_Latn_BE
- { 0, 0, 34 }, { 37, 7, 34 }, // und_BF -> fr_Latn_BF
- { 0, 0, 33 }, { 20, 2, 33 }, // und_BG -> bg_Cyrl_BG
- { 0, 0, 17 }, { 8, 1, 17 }, // und_BH -> ar_Arab_BH
- { 0, 0, 35 }, { 68, 7, 35 }, // und_BI -> rn_Latn_BI
- { 0, 0, 23 }, { 37, 7, 23 }, // und_BJ -> fr_Latn_BJ
- { 0, 0, 244 }, { 37, 7, 244 }, // und_BL -> fr_Latn_BL
- { 0, 0, 32 }, { 76, 7, 32 }, // und_BN -> ms_Latn_BN
- { 0, 0, 26 }, { 111, 7, 26 }, // und_BO -> es_Latn_BO
- { 0, 0, 255 }, { 351, 7, 255 }, // und_BQ -> pap_Latn_BQ
- { 0, 0, 30 }, { 91, 7, 30 }, // und_BR -> pt_Latn_BR
- { 0, 0, 25 }, { 16, 31, 25 }, // und_BT -> dz_Tibt_BT
- { 0, 0, 29 }, { 0, 7, 29 }, // und_BV -> und_Latn_BV
- { 0, 0, 20 }, { 22, 2, 20 }, // und_BY -> be_Cyrl_BY
- { 0, 0, 49 }, { 113, 7, 49 }, // und_CD -> sw_Latn_CD
- { 0, 0, 41 }, { 37, 7, 41 }, // und_CF -> fr_Latn_CF
- { 0, 0, 50 }, { 37, 7, 50 }, // und_CG -> fr_Latn_CG
- { 0, 0, 206 }, { 42, 7, 206 }, // und_CH -> de_Latn_CH
- { 0, 0, 53 }, { 37, 7, 53 }, // und_CI -> fr_Latn_CI
- { 0, 0, 43 }, { 111, 7, 43 }, // und_CL -> es_Latn_CL
- { 0, 0, 37 }, { 37, 7, 37 }, // und_CM -> fr_Latn_CM
- { 0, 0, 44 }, { 25, 5, 44 }, // und_CN -> zh_Hans_CN
- { 0, 0, 47 }, { 111, 7, 47 }, // und_CO -> es_Latn_CO
- { 0, 0, 241 }, { 0, 7, 241 }, // und_CP -> und_Latn_CP
- { 0, 0, 52 }, { 111, 7, 52 }, // und_CR -> es_Latn_CR
- { 0, 0, 55 }, { 111, 7, 55 }, // und_CU -> es_Latn_CU
- { 0, 0, 39 }, { 91, 7, 39 }, // und_CV -> pt_Latn_CV
- { 0, 0, 152 }, { 351, 7, 152 }, // und_CW -> pap_Latn_CW
- { 0, 0, 56 }, { 43, 16, 56 }, // und_CY -> el_Grek_CY
- { 0, 0, 57 }, { 28, 7, 57 }, // und_CZ -> cs_Latn_CZ
- { 0, 0, 82 }, { 42, 7, 82 }, // und_DE -> de_Latn_DE
- { 0, 0, 59 }, { 4, 7, 59 }, // und_DJ -> aa_Latn_DJ
- { 0, 0, 58 }, { 29, 7, 58 }, // und_DK -> da_Latn_DK
- { 0, 0, 61 }, { 111, 7, 61 }, // und_DO -> es_Latn_DO
- { 0, 0, 3 }, { 8, 1, 3 }, // und_DZ -> ar_Arab_DZ
- { 0, 0, 250 }, { 111, 7, 250 }, // und_EA -> es_Latn_EA
- { 0, 0, 63 }, { 111, 7, 63 }, // und_EC -> es_Latn_EC
- { 0, 0, 68 }, { 33, 7, 68 }, // und_EE -> et_Latn_EE
- { 0, 0, 64 }, { 8, 1, 64 }, // und_EG -> ar_Arab_EG
- { 0, 0, 236 }, { 8, 1, 236 }, // und_EH -> ar_Arab_EH
- { 0, 0, 67 }, { 122, 14, 67 }, // und_ER -> ti_Ethi_ER
- { 0, 0, 197 }, { 111, 7, 197 }, // und_ES -> es_Latn_ES
- { 0, 0, 69 }, { 7, 14, 69 }, // und_ET -> am_Ethi_ET
- { 0, 0, 258 }, { 31, 7, 224 }, // und_EU -> en_Latn_GB
- { 0, 0, 73 }, { 36, 7, 73 }, // und_FI -> fi_Latn_FI
- { 0, 0, 71 }, { 34, 7, 71 }, // und_FO -> fo_Latn_FO
- { 0, 0, 74 }, { 37, 7, 74 }, // und_FR -> fr_Latn_FR
- { 0, 0, 79 }, { 37, 7, 79 }, // und_GA -> fr_Latn_GA
- { 0, 0, 81 }, { 41, 15, 81 }, // und_GE -> ka_Geor_GE
- { 0, 0, 76 }, { 37, 7, 76 }, // und_GF -> fr_Latn_GF
- { 0, 0, 83 }, { 146, 7, 83 }, // und_GH -> ak_Latn_GH
- { 0, 0, 86 }, { 44, 7, 86 }, // und_GL -> kl_Latn_GL
- { 0, 0, 91 }, { 37, 7, 91 }, // und_GN -> fr_Latn_GN
- { 0, 0, 88 }, { 37, 7, 88 }, // und_GP -> fr_Latn_GP
- { 0, 0, 66 }, { 111, 7, 66 }, // und_GQ -> es_Latn_GQ
- { 0, 0, 85 }, { 43, 16, 85 }, // und_GR -> el_Grek_GR
- { 0, 0, 196 }, { 0, 7, 196 }, // und_GS -> und_Latn_GS
- { 0, 0, 90 }, { 111, 7, 90 }, // und_GT -> es_Latn_GT
- { 0, 0, 92 }, { 91, 7, 92 }, // und_GW -> pt_Latn_GW
- { 0, 0, 97 }, { 25, 6, 97 }, // und_HK -> zh_Hant_HK
- { 0, 0, 95 }, { 0, 7, 95 }, // und_HM -> und_Latn_HM
- { 0, 0, 96 }, { 111, 7, 96 }, // und_HN -> es_Latn_HN
- { 0, 0, 54 }, { 27, 7, 54 }, // und_HR -> hr_Latn_HR
- { 0, 0, 94 }, { 222, 7, 94 }, // und_HT -> ht_Latn_HT
- { 0, 0, 98 }, { 50, 7, 98 }, // und_HU -> hu_Latn_HU
- { 0, 0, 238 }, { 111, 7, 238 }, // und_IC -> es_Latn_IC
- { 0, 0, 101 }, { 52, 7, 101 }, // und_ID -> id_Latn_ID
- { 0, 0, 105 }, { 48, 18, 105 }, // und_IL -> he_Hebr_IL
- { 0, 0, 100 }, { 49, 13, 100 }, // und_IN -> hi_Deva_IN
- { 0, 0, 103 }, { 8, 1, 103 }, // und_IQ -> ar_Arab_IQ
- { 0, 0, 102 }, { 89, 1, 102 }, // und_IR -> fa_Arab_IR
- { 0, 0, 99 }, { 51, 7, 99 }, // und_IS -> is_Latn_IS
- { 0, 0, 106 }, { 58, 7, 106 }, // und_IT -> it_Latn_IT
- { 0, 0, 109 }, { 8, 1, 109 }, // und_JO -> ar_Arab_JO
- { 0, 0, 108 }, { 59, 19, 108 }, // und_JP -> ja_Jpan_JP
- { 0, 0, 111 }, { 113, 7, 111 }, // und_KE -> sw_Latn_KE
- { 0, 0, 116 }, { 65, 2, 116 }, // und_KG -> ky_Cyrl_KG
- { 0, 0, 36 }, { 23, 20, 36 }, // und_KH -> km_Khmr_KH
- { 0, 0, 48 }, { 8, 1, 48 }, // und_KM -> ar_Arab_KM
- { 0, 0, 113 }, { 66, 22, 113 }, // und_KP -> ko_Kore_KP
- { 0, 0, 114 }, { 66, 22, 114 }, // und_KR -> ko_Kore_KR
- { 0, 0, 115 }, { 8, 1, 115 }, // und_KW -> ar_Arab_KW
- { 0, 0, 110 }, { 96, 2, 110 }, // und_KZ -> ru_Cyrl_KZ
- { 0, 0, 117 }, { 69, 23, 117 }, // und_LA -> lo_Laoo_LA
- { 0, 0, 119 }, { 8, 1, 119 }, // und_LB -> ar_Arab_LB
- { 0, 0, 123 }, { 42, 7, 123 }, // und_LI -> de_Latn_LI
- { 0, 0, 198 }, { 106, 32, 198 }, // und_LK -> si_Sinh_LK
- { 0, 0, 120 }, { 102, 7, 120 }, // und_LS -> st_Latn_LS
- { 0, 0, 124 }, { 73, 7, 124 }, // und_LT -> lt_Latn_LT
- { 0, 0, 125 }, { 37, 7, 125 }, // und_LU -> fr_Latn_LU
- { 0, 0, 118 }, { 71, 7, 118 }, // und_LV -> lv_Latn_LV
- { 0, 0, 122 }, { 8, 1, 122 }, // und_LY -> ar_Arab_LY
- { 0, 0, 145 }, { 8, 1, 145 }, // und_MA -> ar_Arab_MA
- { 0, 0, 142 }, { 37, 7, 142 }, // und_MC -> fr_Latn_MC
- { 0, 0, 141 }, { 95, 7, 141 }, // und_MD -> ro_Latn_MD
- { 0, 0, 242 }, { 100, 7, 242 }, // und_ME -> sr_Latn_ME
- { 0, 0, 245 }, { 37, 7, 245 }, // und_MF -> fr_Latn_MF
- { 0, 0, 128 }, { 75, 7, 128 }, // und_MG -> mg_Latn_MG
- { 0, 0, 127 }, { 74, 2, 127 }, // und_MK -> mk_Cyrl_MK
- { 0, 0, 132 }, { 188, 7, 132 }, // und_ML -> bm_Latn_ML
- { 0, 0, 147 }, { 21, 25, 147 }, // und_MM -> my_Mymr_MM
- { 0, 0, 143 }, { 82, 2, 143 }, // und_MN -> mn_Cyrl_MN
- { 0, 0, 126 }, { 25, 6, 126 }, // und_MO -> zh_Hant_MO
- { 0, 0, 135 }, { 37, 7, 135 }, // und_MQ -> fr_Latn_MQ
- { 0, 0, 136 }, { 8, 1, 136 }, // und_MR -> ar_Arab_MR
- { 0, 0, 133 }, { 78, 7, 133 }, // und_MT -> mt_Latn_MT
- { 0, 0, 137 }, { 191, 7, 137 }, // und_MU -> mfe_Latn_MU
- { 0, 0, 131 }, { 143, 29, 131 }, // und_MV -> dv_Thaa_MV
- { 0, 0, 139 }, { 111, 7, 139 }, // und_MX -> es_Latn_MX
- { 0, 0, 130 }, { 76, 7, 130 }, // und_MY -> ms_Latn_MY
- { 0, 0, 146 }, { 91, 7, 146 }, // und_MZ -> pt_Latn_MZ
- { 0, 0, 148 }, { 5, 7, 148 }, // und_NA -> af_Latn_NA
- { 0, 0, 153 }, { 37, 7, 153 }, // und_NC -> fr_Latn_NC
- { 0, 0, 156 }, { 47, 7, 156 }, // und_NE -> ha_Latn_NE
- { 0, 0, 155 }, { 111, 7, 155 }, // und_NI -> es_Latn_NI
- { 0, 0, 151 }, { 30, 7, 151 }, // und_NL -> nl_Latn_NL
- { 0, 0, 161 }, { 85, 7, 161 }, // und_NO -> nb_Latn_NO
- { 0, 0, 150 }, { 84, 13, 150 }, // und_NP -> ne_Deva_NP
- { 0, 0, 162 }, { 8, 1, 162 }, // und_OM -> ar_Arab_OM
- { 0, 0, 166 }, { 111, 7, 166 }, // und_PA -> es_Latn_PA
- { 0, 0, 169 }, { 111, 7, 169 }, // und_PE -> es_Latn_PE
- { 0, 0, 77 }, { 37, 7, 77 }, // und_PF -> fr_Latn_PF
- { 0, 0, 167 }, { 354, 7, 167 }, // und_PG -> tpi_Latn_PG
- { 0, 0, 170 }, { 166, 7, 170 }, // und_PH -> fil_Latn_PH
- { 0, 0, 163 }, { 130, 1, 163 }, // und_PK -> ur_Arab_PK
- { 0, 0, 172 }, { 90, 7, 172 }, // und_PL -> pl_Latn_PL
- { 0, 0, 200 }, { 37, 7, 200 }, // und_PM -> fr_Latn_PM
- { 0, 0, 174 }, { 111, 7, 174 }, // und_PR -> es_Latn_PR
- { 0, 0, 165 }, { 8, 1, 165 }, // und_PS -> ar_Arab_PS
- { 0, 0, 173 }, { 91, 7, 173 }, // und_PT -> pt_Latn_PT
- { 0, 0, 164 }, { 350, 7, 164 }, // und_PW -> pau_Latn_PW
- { 0, 0, 168 }, { 45, 7, 168 }, // und_PY -> gn_Latn_PY
- { 0, 0, 175 }, { 8, 1, 175 }, // und_QA -> ar_Arab_QA
- { 0, 0, 259 }, { 31, 7, 249 }, // und_QO -> en_Latn_DG
- { 0, 0, 176 }, { 37, 7, 176 }, // und_RE -> fr_Latn_RE
- { 0, 0, 177 }, { 95, 7, 177 }, // und_RO -> ro_Latn_RO
- { 0, 0, 243 }, { 100, 2, 243 }, // und_RS -> sr_Cyrl_RS
- { 0, 0, 178 }, { 96, 2, 178 }, // und_RU -> ru_Cyrl_RU
- { 0, 0, 179 }, { 64, 7, 179 }, // und_RW -> rw_Latn_RW
- { 0, 0, 186 }, { 8, 1, 186 }, // und_SA -> ar_Arab_SA
- { 0, 0, 188 }, { 37, 7, 188 }, // und_SC -> fr_Latn_SC
- { 0, 0, 201 }, { 8, 1, 201 }, // und_SD -> ar_Arab_SD
- { 0, 0, 205 }, { 114, 7, 205 }, // und_SE -> sv_Latn_SE
- { 0, 0, 192 }, { 109, 7, 192 }, // und_SI -> sl_Latn_SI
- { 0, 0, 203 }, { 85, 7, 203 }, // und_SJ -> nb_Latn_SJ
- { 0, 0, 191 }, { 108, 7, 191 }, // und_SK -> sk_Latn_SK
- { 0, 0, 184 }, { 58, 7, 184 }, // und_SM -> it_Latn_SM
- { 0, 0, 187 }, { 37, 7, 187 }, // und_SN -> fr_Latn_SN
- { 0, 0, 194 }, { 110, 7, 194 }, // und_SO -> so_Latn_SO
- { 0, 0, 202 }, { 30, 7, 202 }, // und_SR -> nl_Latn_SR
- { 0, 0, 185 }, { 91, 7, 185 }, // und_ST -> pt_Latn_ST
- { 0, 0, 65 }, { 111, 7, 65 }, // und_SV -> es_Latn_SV
- { 0, 0, 207 }, { 8, 1, 207 }, // und_SY -> ar_Arab_SY
- { 0, 0, 42 }, { 37, 7, 42 }, // und_TD -> fr_Latn_TD
- { 0, 0, 78 }, { 37, 7, 78 }, // und_TF -> fr_Latn_TF
- { 0, 0, 212 }, { 37, 7, 212 }, // und_TG -> fr_Latn_TG
- { 0, 0, 211 }, { 120, 30, 211 }, // und_TH -> th_Thai_TH
- { 0, 0, 209 }, { 116, 2, 209 }, // und_TJ -> tg_Cyrl_TJ
- { 0, 0, 213 }, { 353, 7, 213 }, // und_TK -> tkl_Latn_TK
- { 0, 0, 62 }, { 91, 7, 62 }, // und_TL -> pt_Latn_TL
- { 0, 0, 218 }, { 126, 7, 218 }, // und_TM -> tk_Latn_TM
- { 0, 0, 216 }, { 8, 1, 216 }, // und_TN -> ar_Arab_TN
- { 0, 0, 214 }, { 123, 7, 214 }, // und_TO -> to_Latn_TO
- { 0, 0, 217 }, { 125, 7, 217 }, // und_TR -> tr_Latn_TR
- { 0, 0, 220 }, { 355, 7, 220 }, // und_TV -> tvl_Latn_TV
- { 0, 0, 208 }, { 25, 6, 208 }, // und_TW -> zh_Hant_TW
- { 0, 0, 210 }, { 113, 7, 210 }, // und_TZ -> sw_Latn_TZ
- { 0, 0, 222 }, { 129, 2, 222 }, // und_UA -> uk_Cyrl_UA
- { 0, 0, 221 }, { 113, 7, 221 }, // und_UG -> sw_Latn_UG
- { 0, 0, 227 }, { 111, 7, 227 }, // und_UY -> es_Latn_UY
- { 0, 0, 228 }, { 131, 7, 228 }, // und_UZ -> uz_Latn_UZ
- { 0, 0, 230 }, { 58, 7, 230 }, // und_VA -> it_Latn_VA
- { 0, 0, 231 }, { 111, 7, 231 }, // und_VE -> es_Latn_VE
- { 0, 0, 232 }, { 132, 7, 232 }, // und_VN -> vi_Latn_VN
- { 0, 0, 229 }, { 18, 7, 229 }, // und_VU -> bi_Latn_VU
- { 0, 0, 235 }, { 37, 7, 235 }, // und_WF -> fr_Latn_WF
- { 0, 0, 183 }, { 97, 7, 183 }, // und_WS -> sm_Latn_WS
- { 0, 0, 257 }, { 6, 7, 257 }, // und_XK -> sq_Latn_XK
- { 0, 0, 237 }, { 8, 1, 237 }, // und_YE -> ar_Arab_YE
- { 0, 0, 138 }, { 37, 7, 138 }, // und_YT -> fr_Latn_YT
- { 0, 0, 240 }, { 104, 7, 240 }, // und_ZW -> sn_Latn_ZW
- { 0, 134, 0 }, { 177, 134, 91 }, // und_Adlm -> ff_Adlm_GN
- { 0, 105, 0 }, { 335, 105, 178 }, // und_Aghb -> lez_Aghb_RU
- { 0, 128, 0 }, { 340, 128, 100 }, // und_Ahom -> aho_Ahom_IN
- { 0, 1, 0 }, { 8, 1, 64 }, // und_Arab -> ar_Arab_EG
- { 0, 1, 46 }, { 76, 1, 46 }, // und_Arab_CC -> ms_Arab_CC
- { 0, 1, 44 }, { 128, 1, 44 }, // und_Arab_CN -> ug_Arab_CN
- { 0, 1, 224 }, { 62, 1, 224 }, // und_Arab_GB -> ks_Arab_GB
- { 0, 1, 101 }, { 76, 1, 101 }, // und_Arab_ID -> ms_Arab_ID
- { 0, 1, 100 }, { 130, 1, 100 }, // und_Arab_IN -> ur_Arab_IN
- { 0, 1, 143 }, { 63, 1, 143 }, // und_Arab_MN -> kk_Arab_MN
- { 0, 1, 137 }, { 130, 1, 137 }, // und_Arab_MU -> ur_Arab_MU
- { 0, 1, 157 }, { 47, 1, 157 }, // und_Arab_NG -> ha_Arab_NG
- { 0, 1, 163 }, { 130, 1, 163 }, // und_Arab_PK -> ur_Arab_PK
- { 0, 1, 209 }, { 89, 1, 209 }, // und_Arab_TJ -> fa_Arab_TJ
- { 0, 1, 217 }, { 12, 1, 217 }, // und_Arab_TR -> az_Arab_TR
- { 0, 57, 0 }, { 265, 57, 102 }, // und_Armi -> arc_Armi_IR
- { 0, 10, 0 }, { 9, 10, 11 }, // und_Armn -> hy_Armn_AM
- { 0, 36, 0 }, { 255, 36, 102 }, // und_Avst -> ae_Avst_IR
- { 0, 37, 0 }, { 266, 37, 101 }, // und_Bali -> ban_Bali_ID
- { 0, 38, 0 }, { 267, 38, 37 }, // und_Bamu -> bax_Bamu_CM
- { 0, 106, 0 }, { 336, 106, 121 }, // und_Bass -> bsq_Bass_LR
- { 0, 39, 0 }, { 268, 39, 101 }, // und_Batk -> bbc_Batk_ID
- { 0, 11, 0 }, { 15, 11, 18 }, // und_Beng -> bn_Beng_BD
- { 0, 135, 0 }, { 99, 135, 100 }, // und_Bhks -> sa_Bhks_IN
- { 0, 40, 0 }, { 25, 40, 208 }, // und_Bopo -> zh_Bopo_TW
- { 0, 41, 0 }, { 342, 41, 100 }, // und_Brah -> pka_Brah_IN
- { 0, 103, 0 }, { 37, 103, 74 }, // und_Brai -> fr_Brai_FR
- { 0, 42, 0 }, { 269, 42, 101 }, // und_Bugi -> bug_Bugi_ID
- { 0, 43, 0 }, { 270, 43, 170 }, // und_Buhd -> bku_Buhd_PH
- { 0, 46, 0 }, { 272, 46, 18 }, // und_Cakm -> ccp_Cakm_BD
- { 0, 44, 0 }, { 221, 44, 38 }, // und_Cans -> cr_Cans_CA
- { 0, 45, 0 }, { 271, 45, 217 }, // und_Cari -> xcr_Cari_TR
- { 0, 47, 0 }, { 276, 47, 232 }, // und_Cham -> cjm_Cham_VN
- { 0, 12, 0 }, { 190, 12, 225 }, // und_Cher -> chr_Cher_US
- { 0, 48, 0 }, { 274, 48, 64 }, // und_Copt -> cop_Copt_EG
- { 0, 49, 0 }, { 264, 49, 56 }, // und_Cprt -> grc_Cprt_CY
- { 0, 2, 0 }, { 96, 2, 178 }, // und_Cyrl -> ru_Cyrl_RU
- { 0, 2, 2 }, { 74, 2, 2 }, // und_Cyrl_AL -> mk_Cyrl_AL
- { 0, 2, 27 }, { 100, 2, 27 }, // und_Cyrl_BA -> sr_Cyrl_BA
- { 0, 2, 81 }, { 2, 2, 81 }, // und_Cyrl_GE -> ab_Cyrl_GE
- { 0, 2, 85 }, { 74, 2, 85 }, // und_Cyrl_GR -> mk_Cyrl_GR
- { 0, 2, 141 }, { 129, 2, 141 }, // und_Cyrl_MD -> uk_Cyrl_MD
- { 0, 2, 177 }, { 20, 2, 177 }, // und_Cyrl_RO -> bg_Cyrl_RO
- { 0, 2, 191 }, { 129, 2, 191 }, // und_Cyrl_SK -> uk_Cyrl_SK
- { 0, 2, 257 }, { 100, 2, 257 }, // und_Cyrl_XK -> sr_Cyrl_XK
- { 0, 13, 0 }, { 49, 13, 100 }, // und_Deva -> hi_Deva_IN
- { 0, 13, 25 }, { 84, 13, 25 }, // und_Deva_BT -> ne_Deva_BT
- { 0, 13, 137 }, { 343, 13, 137 }, // und_Deva_MU -> bho_Deva_MU
- { 0, 107, 0 }, { 37, 107, 74 }, // und_Dupl -> fr_Dupl_FR
- { 0, 50, 0 }, { 263, 50, 64 }, // und_Egyp -> egy_Egyp_EG
- { 0, 108, 0 }, { 6, 108, 2 }, // und_Elba -> sq_Elba_AL
- { 0, 14, 0 }, { 7, 14, 69 }, // und_Ethi -> am_Ethi_ET
- { 0, 15, 0 }, { 41, 15, 81 }, // und_Geor -> ka_Geor_GE
- { 0, 52, 0 }, { 219, 52, 33 }, // und_Glag -> cu_Glag_BG
- { 0, 53, 0 }, { 279, 53, 222 }, // und_Goth -> got_Goth_UA
- { 0, 109, 0 }, { 99, 109, 100 }, // und_Gran -> sa_Gran_IN
- { 0, 16, 0 }, { 43, 16, 85 }, // und_Grek -> el_Grek_GR
- { 0, 17, 0 }, { 46, 17, 100 }, // und_Gujr -> gu_Gujr_IN
- { 0, 4, 0 }, { 92, 4, 100 }, // und_Guru -> pa_Guru_IN
- { 0, 140, 0 }, { 25, 140, 208 }, // und_Hanb -> zh_Hanb_TW
- { 0, 55, 0 }, { 66, 55, 114 }, // und_Hang -> ko_Hang_KR
- { 0, 54, 0 }, { 25, 54, 44 }, // und_Hani -> zh_Hani_CN
- { 0, 56, 0 }, { 280, 56, 170 }, // und_Hano -> hnn_Hano_PH
- { 0, 5, 0 }, { 25, 5, 44 }, // und_Hans -> zh_Hans_CN
- { 0, 6, 0 }, { 25, 6, 208 }, // und_Hant -> zh_Hant_TW
- { 0, 130, 0 }, { 356, 130, 103 }, // und_Hatr -> mis_Hatr_IQ
- { 0, 18, 0 }, { 48, 18, 105 }, // und_Hebr -> he_Hebr_IL
- { 0, 18, 38 }, { 137, 18, 38 }, // und_Hebr_CA -> yi_Hebr_CA
- { 0, 18, 224 }, { 137, 18, 224 }, // und_Hebr_GB -> yi_Hebr_GB
- { 0, 18, 205 }, { 137, 18, 205 }, // und_Hebr_SE -> yi_Hebr_SE
- { 0, 18, 222 }, { 137, 18, 222 }, // und_Hebr_UA -> yi_Hebr_UA
- { 0, 18, 225 }, { 137, 18, 225 }, // und_Hebr_US -> yi_Hebr_US
- { 0, 104, 0 }, { 59, 104, 108 }, // und_Hira -> ja_Hira_JP
- { 0, 129, 0 }, { 344, 129, 217 }, // und_Hluw -> hlu_Hluw_TR
- { 0, 110, 0 }, { 333, 110, 117 }, // und_Hmng -> hnj_Hmng_LA
- { 0, 132, 0 }, { 50, 132, 98 }, // und_Hung -> hu_Hung_HU
- { 0, 79, 0 }, { 278, 79, 106 }, // und_Ital -> ett_Ital_IT
- { 0, 141, 0 }, { 66, 141, 114 }, // und_Jamo -> ko_Jamo_KR
- { 0, 60, 0 }, { 60, 60, 101 }, // und_Java -> jv_Java_ID
- { 0, 19, 0 }, { 59, 19, 108 }, // und_Jpan -> ja_Jpan_JP
- { 0, 63, 0 }, { 277, 63, 147 }, // und_Kali -> eky_Kali_MM
- { 0, 62, 0 }, { 59, 62, 108 }, // und_Kana -> ja_Kana_JP
- { 0, 64, 0 }, { 300, 64, 163 }, // und_Khar -> pra_Khar_PK
- { 0, 20, 0 }, { 23, 20, 36 }, // und_Khmr -> km_Khmr_KH
- { 0, 111, 0 }, { 105, 111, 100 }, // und_Khoj -> sd_Khoj_IN
- { 0, 21, 0 }, { 61, 21, 100 }, // und_Knda -> kn_Knda_IN
- { 0, 22, 0 }, { 66, 22, 114 }, // und_Kore -> ko_Kore_KR
- { 0, 61, 0 }, { 343, 61, 100 }, // und_Kthi -> bho_Kthi_IN
- { 0, 65, 0 }, { 292, 65, 211 }, // und_Lana -> nod_Lana_TH
- { 0, 23, 0 }, { 69, 23, 117 }, // und_Laoo -> lo_Laoo_LA
- { 0, 7, 1 }, { 126, 7, 1 }, // und_Latn_AF -> tk_Latn_AF
- { 0, 7, 11 }, { 67, 7, 11 }, // und_Latn_AM -> ku_Latn_AM
- { 0, 7, 44 }, { 139, 7, 44 }, // und_Latn_CN -> za_Latn_CN
- { 0, 7, 56 }, { 125, 7, 56 }, // und_Latn_CY -> tr_Latn_CY
- { 0, 7, 3 }, { 37, 7, 3 }, // und_Latn_DZ -> fr_Latn_DZ
- { 0, 7, 69 }, { 31, 7, 69 }, // und_Latn_ET -> en_Latn_ET
- { 0, 7, 81 }, { 67, 7, 81 }, // und_Latn_GE -> ku_Latn_GE
- { 0, 7, 102 }, { 126, 7, 102 }, // und_Latn_IR -> tk_Latn_IR
- { 0, 7, 48 }, { 37, 7, 48 }, // und_Latn_KM -> fr_Latn_KM
- { 0, 7, 145 }, { 37, 7, 145 }, // und_Latn_MA -> fr_Latn_MA
- { 0, 7, 127 }, { 6, 7, 127 }, // und_Latn_MK -> sq_Latn_MK
- { 0, 7, 126 }, { 91, 7, 126 }, // und_Latn_MO -> pt_Latn_MO
- { 0, 7, 136 }, { 37, 7, 136 }, // und_Latn_MR -> fr_Latn_MR
- { 0, 7, 207 }, { 37, 7, 207 }, // und_Latn_SY -> fr_Latn_SY
- { 0, 7, 216 }, { 37, 7, 216 }, // und_Latn_TN -> fr_Latn_TN
- { 0, 7, 208 }, { 174, 7, 208 }, // und_Latn_TW -> trv_Latn_TW
- { 0, 7, 222 }, { 90, 7, 222 }, // und_Latn_UA -> pl_Latn_UA
- { 0, 66, 0 }, { 283, 66, 100 }, // und_Lepc -> lep_Lepc_IN
- { 0, 67, 0 }, { 284, 67, 100 }, // und_Limb -> lif_Limb_IN
- { 0, 112, 0 }, { 332, 112, 85 }, // und_Lina -> lab_Lina_GR
- { 0, 68, 0 }, { 264, 68, 85 }, // und_Linb -> grc_Linb_GR
- { 0, 51, 0 }, { 285, 51, 44 }, // und_Lisu -> lis_Lisu_CN
- { 0, 69, 0 }, { 287, 69, 217 }, // und_Lyci -> xlc_Lyci_TR
- { 0, 70, 0 }, { 288, 70, 217 }, // und_Lydi -> xld_Lydi_TR
- { 0, 113, 0 }, { 49, 113, 100 }, // und_Mahj -> hi_Mahj_IN
- { 0, 71, 0 }, { 273, 71, 102 }, // und_Mand -> myz_Mand_IR
- { 0, 114, 0 }, { 329, 114, 44 }, // und_Mani -> xmn_Mani_CN
- { 0, 136, 0 }, { 121, 136, 44 }, // und_Marc -> bo_Marc_CN
- { 0, 115, 0 }, { 330, 115, 189 }, // und_Mend -> men_Mend_SL
- { 0, 74, 0 }, { 291, 74, 201 }, // und_Merc -> xmr_Merc_SD
- { 0, 73, 0 }, { 291, 73, 201 }, // und_Mero -> xmr_Mero_SD
- { 0, 24, 0 }, { 77, 24, 100 }, // und_Mlym -> ml_Mlym_IN
- { 0, 116, 0 }, { 80, 116, 100 }, // und_Modi -> mr_Modi_IN
- { 0, 8, 0 }, { 82, 8, 44 }, // und_Mong -> mn_Mong_CN
- { 0, 117, 0 }, { 347, 117, 18 }, // und_Mroo -> mro_Mroo_BD
- { 0, 72, 0 }, { 290, 72, 100 }, // und_Mtei -> mni_Mtei_IN
- { 0, 131, 0 }, { 352, 131, 163 }, // und_Mult -> skr_Mult_PK
- { 0, 25, 0 }, { 21, 25, 147 }, // und_Mymr -> my_Mymr_MM
- { 0, 118, 0 }, { 331, 118, 186 }, // und_Narb -> xna_Narb_SA
- { 0, 119, 0 }, { 265, 119, 109 }, // und_Nbat -> arc_Nbat_JO
- { 0, 137, 0 }, { 348, 137, 150 }, // und_Newa -> new_Newa_NP
- { 0, 75, 0 }, { 289, 75, 91 }, // und_Nkoo -> man_Nkoo_GN
- { 0, 77, 0 }, { 293, 77, 104 }, // und_Ogam -> sga_Ogam_IE
- { 0, 78, 0 }, { 304, 78, 100 }, // und_Olck -> sat_Olck_IN
- { 0, 82, 0 }, { 296, 82, 143 }, // und_Orkh -> otk_Orkh_MN
- { 0, 26, 0 }, { 87, 26, 100 }, // und_Orya -> or_Orya_IN
- { 0, 138, 0 }, { 358, 138, 225 }, // und_Osge -> osa_Osge_US
- { 0, 83, 0 }, { 110, 83, 194 }, // und_Osma -> so_Osma_SO
- { 0, 120, 0 }, { 265, 120, 207 }, // und_Palm -> arc_Palm_SY
- { 0, 121, 0 }, { 338, 121, 147 }, // und_Pauc -> ctd_Pauc_MM
- { 0, 122, 0 }, { 226, 122, 178 }, // und_Perm -> kv_Perm_RU
- { 0, 84, 0 }, { 345, 84, 44 }, // und_Phag -> lzh_Phag_CN
- { 0, 58, 0 }, { 297, 58, 102 }, // und_Phli -> pal_Phli_IR
- { 0, 123, 0 }, { 297, 123, 44 }, // und_Phlp -> pal_Phlp_CN
- { 0, 85, 0 }, { 299, 85, 119 }, // und_Phnx -> phn_Phnx_LB
- { 0, 86, 0 }, { 282, 86, 44 }, // und_Plrd -> hmd_Plrd_CN
- { 0, 59, 0 }, { 298, 59, 102 }, // und_Prti -> xpr_Prti_IR
- { 0, 87, 0 }, { 301, 87, 101 }, // und_Rjng -> rej_Rjng_ID
- { 0, 88, 0 }, { 294, 88, 205 }, // und_Runr -> non_Runr_SE
- { 0, 89, 0 }, { 303, 89, 105 }, // und_Samr -> smp_Samr_IL
- { 0, 81, 0 }, { 302, 81, 237 }, // und_Sarb -> xsa_Sarb_YE
- { 0, 90, 0 }, { 305, 90, 100 }, // und_Saur -> saz_Saur_IN
- { 0, 133, 0 }, { 341, 133, 225 }, // und_Sgnw -> ase_Sgnw_US
- { 0, 92, 0 }, { 31, 92, 224 }, // und_Shaw -> en_Shaw_GB
- { 0, 91, 0 }, { 99, 91, 100 }, // und_Shrd -> sa_Shrd_IN
- { 0, 124, 0 }, { 99, 124, 100 }, // und_Sidd -> sa_Sidd_IN
- { 0, 125, 0 }, { 105, 125, 100 }, // und_Sind -> sd_Sind_IN
- { 0, 32, 0 }, { 106, 32, 198 }, // und_Sinh -> si_Sinh_LK
- { 0, 93, 0 }, { 306, 93, 100 }, // und_Sora -> srb_Sora_IN
- { 0, 95, 0 }, { 112, 95, 101 }, // und_Sund -> su_Sund_ID
- { 0, 96, 0 }, { 307, 96, 18 }, // und_Sylo -> syl_Sylo_BD
- { 0, 33, 0 }, { 151, 33, 103 }, // und_Syrc -> syr_Syrc_IQ
- { 0, 98, 0 }, { 308, 98, 170 }, // und_Tagb -> tbw_Tagb_PH
- { 0, 101, 0 }, { 275, 101, 100 }, // und_Takr -> doi_Takr_IN
- { 0, 99, 0 }, { 310, 99, 44 }, // und_Tale -> tdd_Tale_CN
- { 0, 76, 0 }, { 286, 76, 44 }, // und_Talu -> khb_Talu_CN
- { 0, 27, 0 }, { 117, 27, 100 }, // und_Taml -> ta_Taml_IN
- { 0, 139, 0 }, { 359, 139, 44 }, // und_Tang -> txg_Tang_CN
- { 0, 100, 0 }, { 309, 100, 232 }, // und_Tavt -> blt_Tavt_VN
- { 0, 28, 0 }, { 119, 28, 100 }, // und_Telu -> te_Telu_IN
- { 0, 9, 0 }, { 314, 9, 145 }, // und_Tfng -> zgh_Tfng_MA
- { 0, 97, 0 }, { 166, 97, 170 }, // und_Tglg -> fil_Tglg_PH
- { 0, 29, 0 }, { 143, 29, 131 }, // und_Thaa -> dv_Thaa_MV
- { 0, 30, 0 }, { 120, 30, 211 }, // und_Thai -> th_Thai_TH
- { 0, 31, 0 }, { 121, 31, 44 }, // und_Tibt -> bo_Tibt_CN
- { 0, 126, 0 }, { 339, 126, 100 }, // und_Tirh -> mai_Tirh_IN
- { 0, 102, 0 }, { 311, 102, 207 }, // und_Ugar -> uga_Ugar_SY
- { 0, 35, 0 }, { 252, 35, 121 }, // und_Vaii -> vai_Vaii_LR
- { 0, 127, 0 }, { 334, 127, 100 }, // und_Wara -> hoc_Wara_IN
- { 0, 80, 0 }, { 295, 80, 102 }, // und_Xpeo -> peo_Xpeo_IR
- { 0, 94, 0 }, { 262, 94, 103 }, // und_Xsux -> akk_Xsux_IQ
- { 0, 34, 0 }, { 168, 34, 44 } // und_Yiii -> ii_Yiii_CN
+static constexpr QLocaleId likely_subtags[] = {
+ { 2, 0, 0 }, { 2, 27, 90 }, // ab -> ab_Cyrl_GE
+ { 3, 0, 0 }, { 3, 66, 77 }, // aa -> aa_Latn_ET
+ { 4, 0, 0 }, { 4, 66, 216 }, // af -> af_Latn_ZA
+ { 5, 0, 0 }, { 5, 66, 40 }, // agq -> agq_Latn_CM
+ { 6, 0, 0 }, { 6, 66, 92 }, // ak -> ak_Latn_GH
+ { 7, 0, 0 }, { 7, 25, 113 }, // akk -> akk_Xsux_IQ
+ { 8, 0, 0 }, { 8, 66, 40 }, // bss -> bss_Latn_CM
+ { 9, 0, 0 }, { 9, 66, 3 }, // sq -> sq_Latn_AL
+ { 10, 0, 0 }, { 10, 117, 248 }, // ase -> ase_Sgnw_US
+ { 11, 0, 0 }, { 11, 33, 77 }, // am -> am_Ethi_ET
+ { 12, 0, 0 }, { 12, 31, 71 }, // egy -> egy_Egyp_EG
+ { 13, 70, 0 }, { 13, 70, 94 }, // grc_Linb -> grc_Linb_GR
+ { 13, 0, 0 }, { 13, 26, 63 }, // grc -> grc_Cprt_CY
+ { 14, 0, 0 }, { 14, 4, 71 }, // ar -> ar_Arab_EG
+ { 15, 0, 0 }, { 15, 66, 220 }, // an -> an_Latn_ES
+ { 16, 87, 0 }, { 16, 87, 122 }, // arc_Nbat -> arc_Nbat_JO
+ { 16, 104, 0 }, { 16, 104, 227 }, // arc_Palm -> arc_Palm_SY
+ { 16, 0, 0 }, { 16, 49, 112 }, // arc -> arc_Armi_IR
+ { 17, 0, 0 }, { 17, 5, 12 }, // hy -> hy_Armn_AM
+ { 18, 0, 0 }, { 18, 9, 110 }, // as -> as_Beng_IN
+ { 19, 0, 0 }, { 19, 66, 220 }, // ast -> ast_Latn_ES
+ { 20, 0, 0 }, { 20, 66, 230 }, // asa -> asa_Latn_TZ
+ { 21, 0, 0 }, { 21, 66, 169 }, // cch -> cch_Latn_NG
+ { 22, 0, 0 }, { 22, 27, 193 }, // av -> av_Cyrl_RU
+ { 23, 0, 0 }, { 23, 6, 112 }, // ae -> ae_Avst_IR
+ { 24, 0, 0 }, { 24, 66, 28 }, // ay -> ay_Latn_BO
+ { 25, 0, 112 }, { 25, 4, 112 }, // az_IR -> az_Arab_IR
+ { 25, 0, 113 }, { 25, 4, 113 }, // az_IQ -> az_Arab_IQ
+ { 25, 0, 193 }, { 25, 27, 193 }, // az_RU -> az_Cyrl_RU
+ { 25, 4, 0 }, { 25, 4, 112 }, // az_Arab -> az_Arab_IR
+ { 25, 0, 0 }, { 25, 66, 17 }, // az -> az_Latn_AZ
+ { 26, 0, 0 }, { 26, 66, 40 }, // ksf -> ksf_Latn_CM
+ { 27, 0, 0 }, { 27, 66, 111 }, // ban -> ban_Latn_ID
+ { 28, 0, 0 }, { 28, 66, 145 }, // bm -> bm_Latn_ML
+ { 29, 0, 0 }, { 29, 8, 40 }, // bax -> bax_Bamu_CM
+ { 30, 0, 0 }, { 30, 9, 20 }, // bn -> bn_Beng_BD
+ { 31, 0, 0 }, { 31, 66, 40 }, // bas -> bas_Latn_CM
+ { 32, 0, 0 }, { 32, 27, 193 }, // ba -> ba_Cyrl_RU
+ { 33, 0, 0 }, { 33, 66, 220 }, // eu -> eu_Latn_ES
+ { 34, 0, 0 }, { 34, 66, 111 }, // bbc -> bbc_Latn_ID
+ { 35, 0, 0 }, { 35, 27, 22 }, // be -> be_Cyrl_BY
+ { 36, 0, 0 }, { 36, 66, 260 }, // bem -> bem_Latn_ZM
+ { 37, 0, 0 }, { 37, 66, 230 }, // bez -> bez_Latn_TZ
+ { 38, 0, 0 }, { 38, 29, 110 }, // bho -> bho_Deva_IN
+ { 39, 0, 0 }, { 39, 66, 252 }, // bi -> bi_Latn_VU
+ { 40, 0, 0 }, { 40, 33, 74 }, // byn -> byn_Ethi_ER
+ { 41, 0, 0 }, { 41, 29, 110 }, // brx -> brx_Deva_IN
+ { 42, 0, 0 }, { 42, 66, 29 }, // bs -> bs_Latn_BA
+ { 43, 0, 0 }, { 43, 66, 84 }, // br -> br_Latn_FR
+ { 44, 0, 0 }, { 44, 66, 111 }, // bug -> bug_Latn_ID
+ { 45, 0, 0 }, { 45, 27, 36 }, // bg -> bg_Cyrl_BG
+ { 46, 0, 0 }, { 46, 86, 161 }, // my -> my_Mymr_MM
+ { 47, 0, 50 }, { 47, 118, 50 }, // yue_CN -> yue_Hans_CN
+ { 47, 118, 0 }, { 47, 118, 50 }, // yue_Hans -> yue_Hans_CN
+ { 47, 0, 0 }, { 47, 137, 107 }, // yue -> yue_Hant_HK
+ { 48, 0, 0 }, { 48, 66, 220 }, // ca -> ca_Latn_ES
+ { 49, 0, 0 }, { 49, 66, 185 }, // ceb -> ceb_Latn_PH
+ { 50, 0, 0 }, { 50, 66, 159 }, // tzm -> tzm_Latn_MA
+ { 51, 0, 0 }, { 51, 4, 113 }, // ckb -> ckb_Arab_IQ
+ { 52, 0, 0 }, { 52, 21, 20 }, // ccp -> ccp_Cakm_BD
+ { 53, 0, 0 }, { 53, 66, 98 }, // ch -> ch_Latn_GU
+ { 54, 0, 0 }, { 54, 27, 193 }, // ce -> ce_Cyrl_RU
+ { 55, 0, 0 }, { 55, 23, 248 }, // chr -> chr_Cher_US
+ { 56, 0, 0 }, { 56, 66, 248 }, // cic -> cic_Latn_US
+ { 57, 0, 0 }, { 57, 66, 243 }, // cgg -> cgg_Latn_UG
+ { 58, 0, 15 }, { 58, 137, 15 }, // zh_AU -> zh_Hant_AU
+ { 58, 0, 35 }, { 58, 137, 35 }, // zh_BN -> zh_Hant_BN
+ { 58, 0, 85 }, { 58, 137, 85 }, // zh_GF -> zh_Hant_GF
+ { 58, 0, 86 }, { 58, 137, 86 }, // zh_PF -> zh_Hant_PF
+ { 58, 0, 107 }, { 58, 137, 107 }, // zh_HK -> zh_Hant_HK
+ { 58, 0, 111 }, { 58, 137, 111 }, // zh_ID -> zh_Hant_ID
+ { 58, 0, 139 }, { 58, 137, 139 }, // zh_MO -> zh_Hant_MO
+ { 58, 0, 181 }, { 58, 137, 181 }, // zh_PA -> zh_Hant_PA
+ { 58, 0, 185 }, { 58, 137, 185 }, // zh_PH -> zh_Hant_PH
+ { 58, 0, 223 }, { 58, 137, 223 }, // zh_SR -> zh_Hant_SR
+ { 58, 0, 228 }, { 58, 137, 228 }, // zh_TW -> zh_Hant_TW
+ { 58, 0, 231 }, { 58, 137, 231 }, // zh_TH -> zh_Hant_TH
+ { 58, 0, 246 }, { 58, 137, 246 }, // zh_GB -> zh_Hant_GB
+ { 58, 0, 248 }, { 58, 137, 248 }, // zh_US -> zh_Hant_US
+ { 58, 0, 255 }, { 58, 137, 255 }, // zh_VN -> zh_Hant_VN
+ { 58, 13, 0 }, { 58, 13, 228 }, // zh_Bopo -> zh_Bopo_TW
+ { 58, 45, 0 }, { 58, 45, 228 }, // zh_Hanb -> zh_Hanb_TW
+ { 58, 137, 0 }, { 58, 137, 228 }, // zh_Hant -> zh_Hant_TW
+ { 58, 0, 0 }, { 58, 118, 50 }, // zh -> zh_Hans_CN
+ { 59, 36, 0 }, { 59, 36, 36 }, // cu_Glag -> cu_Glag_BG
+ { 59, 0, 0 }, { 59, 27, 193 }, // cu -> cu_Cyrl_RU
+ { 60, 0, 0 }, { 60, 27, 193 }, // cv -> cv_Cyrl_RU
+ { 61, 0, 0 }, { 61, 66, 91 }, // ksh -> ksh_Latn_DE
+ { 62, 0, 0 }, { 62, 24, 71 }, // cop -> cop_Copt_EG
+ { 63, 0, 0 }, { 63, 66, 246 }, // kw -> kw_Latn_GB
+ { 64, 0, 0 }, { 64, 66, 84 }, // co -> co_Latn_FR
+ { 65, 0, 0 }, { 65, 18, 41 }, // cr -> cr_Cans_CA
+ { 66, 0, 0 }, { 66, 66, 60 }, // hr -> hr_Latn_HR
+ { 67, 0, 0 }, { 67, 66, 64 }, // cs -> cs_Latn_CZ
+ { 68, 0, 0 }, { 68, 66, 65 }, // da -> da_Latn_DK
+ { 69, 0, 0 }, { 69, 132, 144 }, // dv -> dv_Thaa_MV
+ { 70, 0, 0 }, { 70, 29, 110 }, // doi -> doi_Deva_IN
+ { 71, 0, 0 }, { 71, 66, 40 }, // dua -> dua_Latn_CM
+ { 72, 0, 0 }, { 72, 66, 165 }, // nl -> nl_Latn_NL
+ { 73, 0, 0 }, { 73, 134, 27 }, // dz -> dz_Tibt_BT
+ { 74, 0, 0 }, { 74, 66, 124 }, // ebu -> ebu_Latn_KE
+ { 75, 115, 0 }, { 75, 115, 246 }, // en_Shaw -> en_Shaw_GB
+ { 75, 0, 0 }, { 75, 66, 248 }, // en -> en_Latn_US
+ { 76, 0, 0 }, { 76, 27, 193 }, // myv -> myv_Cyrl_RU
+ { 77, 0, 0 }, { 77, 66, 258 }, // eo -> eo_Latn_001
+ { 78, 0, 0 }, { 78, 66, 75 }, // et -> et_Latn_EE
+ { 79, 0, 0 }, { 79, 66, 92 }, // ee -> ee_Latn_GH
+ { 80, 0, 0 }, { 80, 66, 40 }, // ewo -> ewo_Latn_CM
+ { 81, 0, 0 }, { 81, 66, 81 }, // fo -> fo_Latn_FO
+ { 82, 0, 0 }, { 82, 66, 82 }, // fj -> fj_Latn_FJ
+ { 83, 0, 0 }, { 83, 66, 185 }, // fil -> fil_Latn_PH
+ { 84, 0, 0 }, { 84, 66, 83 }, // fi -> fi_Latn_FI
+ { 85, 0, 0 }, { 85, 66, 84 }, // fr -> fr_Latn_FR
+ { 86, 0, 0 }, { 86, 66, 117 }, // fur -> fur_Latn_IT
+ { 87, 1, 0 }, { 87, 1, 102 }, // ff_Adlm -> ff_Adlm_GN
+ { 87, 0, 0 }, { 87, 66, 206 }, // ff -> ff_Latn_SN
+ { 88, 0, 0 }, { 88, 66, 246 }, // gd -> gd_Latn_GB
+ { 89, 0, 0 }, { 89, 66, 92 }, // gaa -> gaa_Latn_GH
+ { 90, 0, 0 }, { 90, 66, 220 }, // gl -> gl_Latn_ES
+ { 91, 0, 0 }, { 91, 66, 243 }, // lg -> lg_Latn_UG
+ { 92, 0, 0 }, { 92, 33, 77 }, // gez -> gez_Ethi_ET
+ { 93, 0, 0 }, { 93, 35, 90 }, // ka -> ka_Geor_GE
+ { 94, 0, 0 }, { 94, 66, 91 }, // de -> de_Latn_DE
+ { 95, 0, 0 }, { 95, 37, 244 }, // got -> got_Goth_UA
+ { 96, 0, 0 }, { 96, 39, 94 }, // el -> el_Grek_GR
+ { 97, 0, 0 }, { 97, 66, 183 }, // gn -> gn_Latn_PY
+ { 98, 0, 0 }, { 98, 40, 110 }, // gu -> gu_Gujr_IN
+ { 99, 0, 0 }, { 99, 66, 124 }, // guz -> guz_Latn_KE
+ { 100, 0, 0 }, { 100, 66, 104 }, // ht -> ht_Latn_HT
+ { 101, 0, 40 }, { 101, 4, 40 }, // ha_CM -> ha_Arab_CM
+ { 101, 0, 222 }, { 101, 4, 222 }, // ha_SD -> ha_Arab_SD
+ { 101, 0, 0 }, { 101, 66, 169 }, // ha -> ha_Latn_NG
+ { 102, 0, 0 }, { 102, 66, 248 }, // haw -> haw_Latn_US
+ { 103, 0, 0 }, { 103, 47, 116 }, // he -> he_Hebr_IL
+ { 104, 0, 0 }, { 104, 66, 162 }, // hz -> hz_Latn_NA
+ { 105, 0, 0 }, { 105, 29, 110 }, // hi -> hi_Deva_IN
+ { 106, 0, 0 }, { 106, 66, 182 }, // ho -> ho_Latn_PG
+ { 107, 0, 0 }, { 107, 66, 108 }, // hu -> hu_Latn_HU
+ { 108, 0, 0 }, { 108, 66, 109 }, // is -> is_Latn_IS
+ { 109, 0, 0 }, { 109, 66, 258 }, // io -> io_Latn_001
+ { 110, 0, 0 }, { 110, 66, 169 }, // ig -> ig_Latn_NG
+ { 111, 0, 0 }, { 111, 66, 83 }, // smn -> smn_Latn_FI
+ { 112, 0, 0 }, { 112, 66, 111 }, // id -> id_Latn_ID
+ { 113, 0, 0 }, { 113, 27, 193 }, // inh -> inh_Cyrl_RU
+ { 114, 0, 0 }, { 114, 66, 258 }, // ia -> ia_Latn_001
+ { 115, 0, 0 }, { 115, 66, 75 }, // ie -> ie_Latn_EE
+ { 116, 0, 0 }, { 116, 18, 41 }, // iu -> iu_Cans_CA
+ { 117, 0, 0 }, { 117, 66, 248 }, // ik -> ik_Latn_US
+ { 118, 0, 0 }, { 118, 66, 114 }, // ga -> ga_Latn_IE
+ { 119, 0, 0 }, { 119, 66, 117 }, // it -> it_Latn_IT
+ { 120, 0, 0 }, { 120, 53, 120 }, // ja -> ja_Jpan_JP
+ { 121, 0, 0 }, { 121, 66, 111 }, // jv -> jv_Latn_ID
+ { 122, 0, 0 }, { 122, 66, 169 }, // kaj -> kaj_Latn_NG
+ { 123, 0, 0 }, { 123, 66, 206 }, // dyo -> dyo_Latn_SN
+ { 124, 0, 0 }, { 124, 66, 43 }, // kea -> kea_Latn_CV
+ { 125, 0, 0 }, { 125, 66, 4 }, // kab -> kab_Latn_DZ
+ { 126, 0, 0 }, { 126, 66, 40 }, // kkj -> kkj_Latn_CM
+ { 127, 0, 0 }, { 127, 66, 95 }, // kl -> kl_Latn_GL
+ { 128, 0, 0 }, { 128, 66, 124 }, // kln -> kln_Latn_KE
+ { 129, 0, 0 }, { 129, 66, 124 }, // kam -> kam_Latn_KE
+ { 130, 0, 0 }, { 130, 56, 110 }, // kn -> kn_Knda_IN
+ { 131, 4, 0 }, { 131, 4, 169 }, // kr_Arab -> kr_Arab_NG
+ { 131, 0, 0 }, { 131, 66, 169 }, // kr -> kr_Latn_NG
+ { 132, 0, 0 }, { 132, 4, 110 }, // ks -> ks_Arab_IN
+ { 133, 0, 1 }, { 133, 4, 1 }, // kk_AF -> kk_Arab_AF
+ { 133, 0, 50 }, { 133, 4, 50 }, // kk_CN -> kk_Arab_CN
+ { 133, 0, 112 }, { 133, 4, 112 }, // kk_IR -> kk_Arab_IR
+ { 133, 0, 156 }, { 133, 4, 156 }, // kk_MN -> kk_Arab_MN
+ { 133, 4, 0 }, { 133, 4, 50 }, // kk_Arab -> kk_Arab_CN
+ { 133, 0, 0 }, { 133, 27, 123 }, // kk -> kk_Cyrl_KZ
+ { 134, 0, 0 }, { 134, 66, 40 }, // ken -> ken_Latn_CM
+ { 135, 0, 0 }, { 135, 60, 39 }, // km -> km_Khmr_KH
+ { 136, 0, 0 }, { 136, 66, 99 }, // quc -> quc_Latn_GT
+ { 137, 0, 0 }, { 137, 66, 124 }, // ki -> ki_Latn_KE
+ { 138, 0, 0 }, { 138, 66, 194 }, // rw -> rw_Latn_RW
+ { 139, 0, 0 }, { 139, 27, 193 }, // kv -> kv_Cyrl_RU
+ { 140, 0, 0 }, { 140, 66, 57 }, // kg -> kg_Latn_CD
+ { 141, 0, 0 }, { 141, 29, 110 }, // kok -> kok_Deva_IN
+ { 142, 0, 0 }, { 142, 63, 218 }, // ko -> ko_Kore_KR
+ { 143, 0, 0 }, { 143, 66, 118 }, // kfo -> kfo_Latn_CI
+ { 144, 0, 0 }, { 144, 66, 145 }, // ses -> ses_Latn_ML
+ { 145, 0, 0 }, { 145, 66, 145 }, // khq -> khq_Latn_ML
+ { 146, 0, 0 }, { 146, 66, 134 }, // kpe -> kpe_Latn_LR
+ { 147, 0, 0 }, { 147, 66, 162 }, // kj -> kj_Latn_NA
+ { 148, 0, 132 }, { 148, 4, 132 }, // ku_LB -> ku_Arab_LB
+ { 148, 4, 0 }, { 148, 4, 113 }, // ku_Arab -> ku_Arab_IQ
+ { 148, 0, 0 }, { 148, 66, 239 }, // ku -> ku_Latn_TR
+ { 149, 0, 0 }, { 149, 66, 40 }, // nmg -> nmg_Latn_CM
+ { 150, 0, 50 }, { 150, 4, 50 }, // ky_CN -> ky_Arab_CN
+ { 150, 0, 239 }, { 150, 66, 239 }, // ky_TR -> ky_Latn_TR
+ { 150, 4, 0 }, { 150, 4, 50 }, // ky_Arab -> ky_Arab_CN
+ { 150, 66, 0 }, { 150, 66, 239 }, // ky_Latn -> ky_Latn_TR
+ { 150, 0, 0 }, { 150, 27, 128 }, // ky -> ky_Cyrl_KG
+ { 151, 0, 0 }, { 151, 66, 248 }, // lkt -> lkt_Latn_US
+ { 152, 0, 0 }, { 152, 66, 230 }, // lag -> lag_Latn_TZ
+ { 153, 0, 0 }, { 153, 65, 129 }, // lo -> lo_Laoo_LA
+ { 154, 0, 0 }, { 154, 66, 253 }, // la -> la_Latn_VA
+ { 155, 0, 0 }, { 155, 66, 131 }, // lv -> lv_Latn_LV
+ { 156, 0, 0 }, { 156, 27, 193 }, // lez -> lez_Cyrl_RU
+ { 157, 0, 0 }, { 157, 66, 165 }, // li -> li_Latn_NL
+ { 158, 0, 0 }, { 158, 66, 57 }, // ln -> ln_Latn_CD
+ { 159, 0, 0 }, { 159, 118, 50 }, // lzh -> lzh_Hans_CN
+ { 160, 0, 0 }, { 160, 66, 137 }, // lt -> lt_Latn_LT
+ { 161, 0, 0 }, { 161, 66, 258 }, // jbo -> jbo_Latn_001
+ { 162, 0, 0 }, { 162, 66, 91 }, // dsb -> dsb_Latn_DE
+ { 163, 0, 0 }, { 163, 66, 91 }, // nds -> nds_Latn_DE
+ { 164, 0, 0 }, { 164, 66, 57 }, // lu -> lu_Latn_CD
+ { 165, 0, 0 }, { 165, 66, 225 }, // smj -> smj_Latn_SE
+ { 166, 0, 0 }, { 166, 66, 124 }, // luo -> luo_Latn_KE
+ { 167, 0, 0 }, { 167, 66, 138 }, // lb -> lb_Latn_LU
+ { 168, 0, 0 }, { 168, 66, 124 }, // luy -> luy_Latn_KE
+ { 169, 0, 0 }, { 169, 27, 140 }, // mk -> mk_Cyrl_MK
+ { 170, 0, 0 }, { 170, 66, 230 }, // jmc -> jmc_Latn_TZ
+ { 171, 0, 0 }, { 171, 29, 110 }, // mai -> mai_Deva_IN
+ { 172, 0, 0 }, { 172, 66, 160 }, // mgh -> mgh_Latn_MZ
+ { 173, 0, 0 }, { 173, 66, 230 }, // kde -> kde_Latn_TZ
+ { 174, 0, 0 }, { 174, 66, 141 }, // mg -> mg_Latn_MG
+ { 175, 0, 0 }, { 175, 74, 110 }, // ml -> ml_Mlym_IN
+ { 176, 0, 53 }, { 176, 4, 53 }, // ms_CC -> ms_Arab_CC
+ { 176, 0, 0 }, { 176, 66, 143 }, // ms -> ms_Latn_MY
+ { 177, 0, 0 }, { 177, 66, 146 }, // mt -> mt_Latn_MT
+ { 178, 0, 102 }, { 178, 90, 102 }, // man_GN -> man_Nkoo_GN
+ { 178, 90, 0 }, { 178, 90, 102 }, // man_Nkoo -> man_Nkoo_GN
+ { 178, 0, 0 }, { 178, 66, 89 }, // man -> man_Latn_GM
+ { 179, 0, 0 }, { 179, 9, 110 }, // mni -> mni_Beng_IN
+ { 180, 0, 0 }, { 180, 66, 115 }, // gv -> gv_Latn_IM
+ { 181, 0, 0 }, { 181, 66, 167 }, // mi -> mi_Latn_NZ
+ { 182, 0, 0 }, { 182, 66, 49 }, // arn -> arn_Latn_CL
+ { 183, 0, 0 }, { 183, 29, 110 }, // mr -> mr_Deva_IN
+ { 184, 0, 0 }, { 184, 66, 147 }, // mh -> mh_Latn_MH
+ { 185, 0, 0 }, { 185, 66, 124 }, // mas -> mas_Latn_KE
+ { 186, 0, 0 }, { 186, 4, 112 }, // mzn -> mzn_Arab_IR
+ { 187, 0, 0 }, { 187, 66, 209 }, // men -> men_Latn_SL
+ { 188, 0, 0 }, { 188, 66, 124 }, // mer -> mer_Latn_KE
+ { 189, 0, 0 }, { 189, 66, 40 }, // mgo -> mgo_Latn_CM
+ { 190, 0, 0 }, { 190, 66, 41 }, // moh -> moh_Latn_CA
+ { 191, 0, 50 }, { 191, 83, 50 }, // mn_CN -> mn_Mong_CN
+ { 191, 83, 0 }, { 191, 83, 50 }, // mn_Mong -> mn_Mong_CN
+ { 191, 0, 0 }, { 191, 27, 156 }, // mn -> mn_Cyrl_MN
+ { 192, 0, 0 }, { 192, 66, 150 }, // mfe -> mfe_Latn_MU
+ { 193, 0, 0 }, { 193, 66, 40 }, // mua -> mua_Latn_CM
+ { 194, 0, 0 }, { 194, 66, 248 }, // mus -> mus_Latn_US
+ { 195, 0, 0 }, { 195, 66, 162 }, // naq -> naq_Latn_NA
+ { 196, 0, 0 }, { 196, 66, 163 }, // na -> na_Latn_NR
+ { 197, 0, 0 }, { 197, 66, 248 }, // nv -> nv_Latn_US
+ { 198, 0, 0 }, { 198, 66, 162 }, // ng -> ng_Latn_NA
+ { 199, 0, 0 }, { 199, 29, 164 }, // ne -> ne_Deva_NP
+ { 200, 0, 0 }, { 200, 29, 164 }, // new -> new_Deva_NP
+ { 201, 0, 0 }, { 201, 66, 40 }, // nnh -> nnh_Latn_CM
+ { 202, 0, 0 }, { 202, 66, 40 }, // jgo -> jgo_Latn_CM
+ { 203, 0, 0 }, { 203, 66, 169 }, // pcm -> pcm_Latn_NG
+ { 204, 0, 0 }, { 204, 90, 102 }, // nqo -> nqo_Nkoo_GN
+ { 205, 0, 0 }, { 205, 4, 112 }, // lrc -> lrc_Arab_IR
+ { 206, 0, 0 }, { 206, 66, 175 }, // se -> se_Latn_NO
+ { 207, 0, 0 }, { 207, 66, 216 }, // nso -> nso_Latn_ZA
+ { 208, 0, 0 }, { 208, 66, 261 }, // nd -> nd_Latn_ZW
+ { 209, 0, 0 }, { 209, 66, 175 }, // nb -> nb_Latn_NO
+ { 210, 0, 0 }, { 210, 66, 175 }, // nn -> nn_Latn_NO
+ { 211, 0, 0 }, { 211, 66, 219 }, // nus -> nus_Latn_SS
+ { 212, 0, 0 }, { 212, 66, 142 }, // ny -> ny_Latn_MW
+ { 213, 0, 0 }, { 213, 66, 243 }, // nyn -> nyn_Latn_UG
+ { 214, 0, 0 }, { 214, 66, 84 }, // oc -> oc_Latn_FR
+ { 215, 0, 0 }, { 215, 91, 110 }, // or -> or_Orya_IN
+ { 216, 0, 0 }, { 216, 18, 41 }, // oj -> oj_Cans_CA
+ { 217, 0, 0 }, { 217, 92, 114 }, // sga -> sga_Ogam_IE
+ { 218, 0, 0 }, { 218, 111, 225 }, // non -> non_Runr_SE
+ { 219, 0, 0 }, { 219, 98, 112 }, // peo -> peo_Xpeo_IR
+ { 220, 0, 0 }, { 220, 66, 77 }, // om -> om_Latn_ET
+ { 221, 0, 0 }, { 221, 101, 248 }, // osa -> osa_Osge_US
+ { 222, 0, 0 }, { 222, 27, 90 }, // os -> os_Cyrl_GE
+ { 223, 109, 0 }, { 223, 109, 50 }, // pal_Phlp -> pal_Phlp_CN
+ { 223, 0, 0 }, { 223, 50, 112 }, // pal -> pal_Phli_IR
+ { 224, 0, 0 }, { 224, 66, 179 }, // pau -> pau_Latn_PW
+ { 225, 14, 0 }, { 225, 14, 110 }, // pi_Brah -> pi_Brah_IN
+ { 225, 29, 0 }, { 225, 29, 110 }, // pi_Deva -> pi_Deva_IN
+ { 225, 59, 0 }, { 225, 59, 110 }, // pi_Khar -> pi_Khar_IN
+ { 225, 60, 0 }, { 225, 60, 110 }, // pi_Khmr -> pi_Khmr_IN
+ { 225, 86, 0 }, { 225, 86, 110 }, // pi_Mymr -> pi_Mymr_IN
+ { 225, 133, 0 }, { 225, 133, 110 }, // pi_Thai -> pi_Thai_IN
+ { 225, 0, 0 }, { 225, 119, 110 }, // pi -> pi_Sinh_IN
+ { 226, 0, 0 }, { 226, 66, 62 }, // pap -> pap_Latn_CW
+ { 227, 0, 0 }, { 227, 4, 1 }, // ps -> ps_Arab_AF
+ { 228, 0, 0 }, { 228, 4, 112 }, // fa -> fa_Arab_IR
+ { 229, 0, 0 }, { 229, 107, 132 }, // phn -> phn_Phnx_LB
+ { 230, 0, 0 }, { 230, 66, 187 }, // pl -> pl_Latn_PL
+ { 231, 0, 0 }, { 231, 66, 32 }, // pt -> pt_Latn_BR
+ { 232, 0, 0 }, { 232, 66, 187 }, // prg -> prg_Latn_PL
+ { 233, 0, 178 }, { 233, 4, 178 }, // pa_PK -> pa_Arab_PK
+ { 233, 4, 0 }, { 233, 4, 178 }, // pa_Arab -> pa_Arab_PK
+ { 233, 0, 0 }, { 233, 41, 110 }, // pa -> pa_Guru_IN
+ { 234, 0, 0 }, { 234, 66, 184 }, // qu -> qu_Latn_PE
+ { 235, 0, 0 }, { 235, 66, 192 }, // ro -> ro_Latn_RO
+ { 236, 0, 0 }, { 236, 66, 226 }, // rm -> rm_Latn_CH
+ { 237, 0, 0 }, { 237, 66, 230 }, // rof -> rof_Latn_TZ
+ { 238, 0, 0 }, { 238, 66, 38 }, // rn -> rn_Latn_BI
+ { 239, 0, 0 }, { 239, 27, 193 }, // ru -> ru_Cyrl_RU
+ { 240, 0, 0 }, { 240, 66, 230 }, // rwk -> rwk_Latn_TZ
+ { 241, 0, 0 }, { 241, 66, 74 }, // ssy -> ssy_Latn_ER
+ { 242, 0, 0 }, { 242, 27, 193 }, // sah -> sah_Cyrl_RU
+ { 243, 0, 0 }, { 243, 66, 124 }, // saq -> saq_Latn_KE
+ { 244, 0, 0 }, { 244, 66, 202 }, // sm -> sm_Latn_WS
+ { 245, 0, 0 }, { 245, 66, 46 }, // sg -> sg_Latn_CF
+ { 246, 0, 0 }, { 246, 66, 230 }, // sbp -> sbp_Latn_TZ
+ { 247, 0, 0 }, { 247, 29, 110 }, // sa -> sa_Deva_IN
+ { 248, 0, 0 }, { 248, 93, 110 }, // sat -> sat_Olck_IN
+ { 249, 0, 0 }, { 249, 66, 117 }, // sc -> sc_Latn_IT
+ { 250, 0, 0 }, { 250, 113, 110 }, // saz -> saz_Saur_IN
+ { 251, 0, 0 }, { 251, 66, 160 }, // seh -> seh_Latn_MZ
+ { 252, 0, 157 }, { 252, 66, 157 }, // sr_ME -> sr_Latn_ME
+ { 252, 0, 192 }, { 252, 66, 192 }, // sr_RO -> sr_Latn_RO
+ { 252, 0, 193 }, { 252, 66, 193 }, // sr_RU -> sr_Latn_RU
+ { 252, 0, 239 }, { 252, 66, 239 }, // sr_TR -> sr_Latn_TR
+ { 252, 0, 0 }, { 252, 27, 207 }, // sr -> sr_Cyrl_RS
+ { 253, 0, 0 }, { 253, 66, 230 }, // ksb -> ksb_Latn_TZ
+ { 254, 0, 0 }, { 254, 66, 261 }, // sn -> sn_Latn_ZW
+ { 255, 0, 0 }, { 255, 141, 50 }, // ii -> ii_Yiii_CN
+ { 256, 0, 0 }, { 256, 66, 117 }, // scn -> scn_Latn_IT
+ { 257, 0, 0 }, { 257, 66, 77 }, // sid -> sid_Latn_ET
+ { 258, 0, 0 }, { 258, 66, 187 }, // szl -> szl_Latn_PL
+ { 259, 0, 110 }, { 259, 29, 110 }, // sd_IN -> sd_Deva_IN
+ { 259, 29, 0 }, { 259, 29, 110 }, // sd_Deva -> sd_Deva_IN
+ { 259, 61, 0 }, { 259, 61, 110 }, // sd_Khoj -> sd_Khoj_IN
+ { 259, 62, 0 }, { 259, 62, 110 }, // sd_Sind -> sd_Sind_IN
+ { 259, 0, 0 }, { 259, 4, 178 }, // sd -> sd_Arab_PK
+ { 260, 0, 0 }, { 260, 119, 221 }, // si -> si_Sinh_LK
+ { 261, 0, 0 }, { 261, 66, 83 }, // sms -> sms_Latn_FI
+ { 262, 0, 0 }, { 262, 66, 212 }, // sk -> sk_Latn_SK
+ { 263, 0, 0 }, { 263, 66, 213 }, // sl -> sl_Latn_SI
+ { 264, 0, 0 }, { 264, 66, 243 }, // xog -> xog_Latn_UG
+ { 265, 0, 0 }, { 265, 66, 215 }, // so -> so_Latn_SO
+ { 266, 0, 0 }, { 266, 4, 112 }, // sdh -> sdh_Arab_IR
+ { 267, 0, 0 }, { 267, 66, 225 }, // sma -> sma_Latn_SE
+ { 268, 0, 0 }, { 268, 66, 216 }, // st -> st_Latn_ZA
+ { 269, 0, 0 }, { 269, 66, 216 }, // nr -> nr_Latn_ZA
+ { 270, 0, 0 }, { 270, 66, 220 }, // es -> es_Latn_ES
+ { 271, 0, 0 }, { 271, 135, 159 }, // zgh -> zgh_Tfng_MA
+ { 272, 0, 0 }, { 272, 66, 111 }, // su -> su_Latn_ID
+ { 273, 0, 0 }, { 273, 66, 230 }, // sw -> sw_Latn_TZ
+ { 274, 0, 0 }, { 274, 66, 216 }, // ss -> ss_Latn_ZA
+ { 275, 0, 0 }, { 275, 66, 225 }, // sv -> sv_Latn_SE
+ { 276, 0, 0 }, { 276, 66, 226 }, // gsw -> gsw_Latn_CH
+ { 277, 0, 0 }, { 277, 123, 113 }, // syr -> syr_Syrc_IQ
+ { 278, 0, 0 }, { 278, 135, 159 }, // shi -> shi_Tfng_MA
+ { 279, 0, 0 }, { 279, 66, 86 }, // ty -> ty_Latn_PF
+ { 280, 0, 0 }, { 280, 127, 255 }, // blt -> blt_Tavt_VN
+ { 281, 0, 0 }, { 281, 66, 124 }, // dav -> dav_Latn_KE
+ { 282, 0, 178 }, { 282, 4, 178 }, // tg_PK -> tg_Arab_PK
+ { 282, 4, 0 }, { 282, 4, 178 }, // tg_Arab -> tg_Arab_PK
+ { 282, 0, 0 }, { 282, 27, 229 }, // tg -> tg_Cyrl_TJ
+ { 283, 0, 0 }, { 283, 129, 110 }, // ta -> ta_Taml_IN
+ { 284, 0, 0 }, { 284, 66, 228 }, // trv -> trv_Latn_TW
+ { 285, 0, 0 }, { 285, 66, 170 }, // twq -> twq_Latn_NE
+ { 286, 0, 0 }, { 286, 27, 193 }, // tt -> tt_Cyrl_RU
+ { 287, 0, 0 }, { 287, 131, 110 }, // te -> te_Telu_IN
+ { 288, 0, 0 }, { 288, 66, 243 }, // teo -> teo_Latn_UG
+ { 289, 0, 0 }, { 289, 133, 231 }, // th -> th_Thai_TH
+ { 290, 0, 0 }, { 290, 134, 50 }, // bo -> bo_Tibt_CN
+ { 291, 0, 0 }, { 291, 33, 74 }, // tig -> tig_Ethi_ER
+ { 292, 0, 0 }, { 292, 33, 77 }, // ti -> ti_Ethi_ET
+ { 293, 0, 0 }, { 293, 66, 234 }, // tkl -> tkl_Latn_TK
+ { 294, 0, 0 }, { 294, 66, 182 }, // tpi -> tpi_Latn_PG
+ { 295, 0, 0 }, { 295, 66, 235 }, // to -> to_Latn_TO
+ { 296, 0, 0 }, { 296, 66, 216 }, // ts -> ts_Latn_ZA
+ { 297, 0, 0 }, { 297, 66, 216 }, // tn -> tn_Latn_ZA
+ { 298, 0, 0 }, { 298, 66, 239 }, // tr -> tr_Latn_TR
+ { 299, 0, 0 }, { 299, 66, 240 }, // tk -> tk_Latn_TM
+ { 300, 0, 0 }, { 300, 66, 242 }, // tvl -> tvl_Latn_TV
+ { 301, 0, 0 }, { 301, 66, 169 }, // kcg -> kcg_Latn_NG
+ { 302, 0, 0 }, { 302, 138, 227 }, // uga -> uga_Ugar_SY
+ { 303, 0, 0 }, { 303, 27, 244 }, // uk -> uk_Cyrl_UA
+ { 304, 0, 0 }, { 304, 66, 91 }, // hsb -> hsb_Latn_DE
+ { 305, 0, 0 }, { 305, 4, 178 }, // ur -> ur_Arab_PK
+ { 306, 0, 123 }, { 306, 27, 123 }, // ug_KZ -> ug_Cyrl_KZ
+ { 306, 0, 156 }, { 306, 27, 156 }, // ug_MN -> ug_Cyrl_MN
+ { 306, 27, 0 }, { 306, 27, 123 }, // ug_Cyrl -> ug_Cyrl_KZ
+ { 306, 0, 0 }, { 306, 4, 50 }, // ug -> ug_Arab_CN
+ { 307, 0, 1 }, { 307, 4, 1 }, // uz_AF -> uz_Arab_AF
+ { 307, 0, 50 }, { 307, 27, 50 }, // uz_CN -> uz_Cyrl_CN
+ { 307, 4, 0 }, { 307, 4, 1 }, // uz_Arab -> uz_Arab_AF
+ { 307, 0, 0 }, { 307, 66, 251 }, // uz -> uz_Latn_UZ
+ { 308, 0, 0 }, { 308, 139, 134 }, // vai -> vai_Vaii_LR
+ { 309, 0, 0 }, { 309, 66, 216 }, // ve -> ve_Latn_ZA
+ { 310, 0, 0 }, { 310, 66, 255 }, // vi -> vi_Latn_VN
+ { 311, 0, 0 }, { 311, 66, 258 }, // vo -> vo_Latn_001
+ { 312, 0, 0 }, { 312, 66, 230 }, // vun -> vun_Latn_TZ
+ { 313, 0, 0 }, { 313, 66, 23 }, // wa -> wa_Latn_BE
+ { 314, 0, 0 }, { 314, 66, 226 }, // wae -> wae_Latn_CH
+ { 315, 0, 0 }, { 315, 66, 15 }, // wbp -> wbp_Latn_AU
+ { 316, 0, 0 }, { 316, 66, 246 }, // cy -> cy_Latn_GB
+ { 317, 0, 0 }, { 317, 4, 178 }, // bgn -> bgn_Arab_PK
+ { 318, 0, 0 }, { 318, 66, 165 }, // fy -> fy_Latn_NL
+ { 319, 0, 0 }, { 319, 33, 77 }, // wal -> wal_Ethi_ET
+ { 320, 0, 0 }, { 320, 66, 206 }, // wo -> wo_Latn_SN
+ { 321, 0, 0 }, { 321, 66, 216 }, // xh -> xh_Latn_ZA
+ { 322, 0, 0 }, { 322, 66, 40 }, // yav -> yav_Latn_CM
+ { 323, 0, 0 }, { 323, 47, 244 }, // yi -> yi_Hebr_UA
+ { 324, 0, 0 }, { 324, 66, 169 }, // yo -> yo_Latn_NG
+ { 325, 0, 0 }, { 325, 66, 170 }, // dje -> dje_Latn_NE
+ { 326, 0, 0 }, { 326, 66, 50 }, // za -> za_Latn_CN
+ { 327, 0, 0 }, { 327, 66, 216 }, // zu -> zu_Latn_ZA
+ { 328, 0, 0 }, { 328, 66, 32 }, // kgp -> kgp_Latn_BR
+ { 329, 0, 0 }, { 329, 66, 32 }, // yrl -> yrl_Latn_BR
+ { 330, 0, 0 }, { 330, 29, 110 }, // bgc -> bgc_Deva_IN
+ { 331, 0, 0 }, { 331, 66, 91 }, // frr -> frr_Latn_DE
+ { 332, 0, 0 }, { 332, 29, 110 }, // raj -> raj_Deva_IN
+ { 333, 0, 0 }, { 333, 27, 193 }, // mdf -> mdf_Cyrl_RU
+ { 334, 0, 0 }, { 334, 66, 258 }, // tok -> tok_Latn_001
+ { 335, 0, 0 }, { 335, 66, 214 }, // pis -> pis_Latn_SB
+ { 336, 0, 0 }, { 336, 66, 169 }, // ann -> ann_Latn_NG
+ { 337, 0, 0 }, { 337, 4, 178 }, // bal -> bal_Arab_PK
+ { 338, 0, 0 }, { 338, 66, 117 }, // lij -> lij_Latn_IT
+ { 339, 0, 0 }, { 339, 142, 161 }, // rhg -> rhg_Rohg_MM
+ { 340, 0, 0 }, { 340, 4, 178 }, // trw -> trw_Arab_PK
+ { 341, 0, 0 }, { 341, 66, 25 }, // blo -> blo_Latn_BJ
+ { 342, 0, 0 }, { 342, 29, 110 }, // xnr -> xnr_Deva_IN
+ { 343, 0, 0 }, { 343, 66, 117 }, // vec -> vec_Latn_IT
+ { 0, 4, 1 }, { 228, 4, 1 }, // und_Arab_AF -> fa_Arab_AF
+ { 0, 66, 1 }, { 299, 66, 1 }, // und_Latn_AF -> tk_Latn_AF
+ { 0, 0, 1 }, { 228, 4, 1 }, // und_AF -> fa_Arab_AF
+ { 0, 66, 2 }, { 275, 66, 2 }, // und_Latn_AX -> sv_Latn_AX
+ { 0, 0, 2 }, { 275, 66, 2 }, // und_AX -> sv_Latn_AX
+ { 0, 27, 3 }, { 169, 27, 3 }, // und_Cyrl_AL -> mk_Cyrl_AL
+ { 0, 66, 3 }, { 9, 66, 3 }, // und_Latn_AL -> sq_Latn_AL
+ { 0, 0, 3 }, { 9, 66, 3 }, // und_AL -> sq_Latn_AL
+ { 0, 66, 4 }, { 85, 66, 4 }, // und_Latn_DZ -> fr_Latn_DZ
+ { 0, 0, 4 }, { 14, 4, 4 }, // und_DZ -> ar_Arab_DZ
+ { 0, 66, 5 }, { 244, 66, 5 }, // und_Latn_AS -> sm_Latn_AS
+ { 0, 0, 5 }, { 244, 66, 5 }, // und_AS -> sm_Latn_AS
+ { 0, 66, 6 }, { 48, 66, 6 }, // und_Latn_AD -> ca_Latn_AD
+ { 0, 0, 6 }, { 48, 66, 6 }, // und_AD -> ca_Latn_AD
+ { 0, 66, 7 }, { 231, 66, 7 }, // und_Latn_AO -> pt_Latn_AO
+ { 0, 0, 7 }, { 231, 66, 7 }, // und_AO -> pt_Latn_AO
+ { 0, 0, 8 }, { 75, 66, 8 }, // und_AI -> en_Latn_AI
+ { 0, 0, 9 }, { 75, 66, 9 }, // und_AQ -> en_Latn_AQ
+ { 0, 0, 10 }, { 75, 66, 10 }, // und_AG -> en_Latn_AG
+ { 0, 66, 11 }, { 270, 66, 11 }, // und_Latn_AR -> es_Latn_AR
+ { 0, 0, 11 }, { 270, 66, 11 }, // und_AR -> es_Latn_AR
+ { 0, 66, 12 }, { 148, 66, 12 }, // und_Latn_AM -> ku_Latn_AM
+ { 0, 0, 12 }, { 17, 5, 12 }, // und_AM -> hy_Armn_AM
+ { 0, 66, 13 }, { 72, 66, 13 }, // und_Latn_AW -> nl_Latn_AW
+ { 0, 0, 13 }, { 72, 66, 13 }, // und_AW -> nl_Latn_AW
+ { 0, 0, 14 }, { 75, 66, 14 }, // und_AC -> en_Latn_AC
+ { 0, 0, 15 }, { 75, 66, 15 }, // und_AU -> en_Latn_AU
+ { 0, 66, 16 }, { 94, 66, 16 }, // und_Latn_AT -> de_Latn_AT
+ { 0, 0, 16 }, { 94, 66, 16 }, // und_AT -> de_Latn_AT
+ { 0, 66, 17 }, { 25, 66, 17 }, // und_Latn_AZ -> az_Latn_AZ
+ { 0, 0, 17 }, { 25, 66, 17 }, // und_AZ -> az_Latn_AZ
+ { 0, 0, 18 }, { 75, 66, 18 }, // und_BS -> en_Latn_BS
+ { 0, 0, 19 }, { 14, 4, 19 }, // und_BH -> ar_Arab_BH
+ { 0, 0, 20 }, { 30, 9, 20 }, // und_BD -> bn_Beng_BD
+ { 0, 0, 21 }, { 75, 66, 21 }, // und_BB -> en_Latn_BB
+ { 0, 27, 22 }, { 35, 27, 22 }, // und_Cyrl_BY -> be_Cyrl_BY
+ { 0, 0, 22 }, { 35, 27, 22 }, // und_BY -> be_Cyrl_BY
+ { 0, 66, 23 }, { 72, 66, 23 }, // und_Latn_BE -> nl_Latn_BE
+ { 0, 0, 23 }, { 72, 66, 23 }, // und_BE -> nl_Latn_BE
+ { 0, 0, 24 }, { 75, 66, 24 }, // und_BZ -> en_Latn_BZ
+ { 0, 66, 25 }, { 85, 66, 25 }, // und_Latn_BJ -> fr_Latn_BJ
+ { 0, 0, 25 }, { 85, 66, 25 }, // und_BJ -> fr_Latn_BJ
+ { 0, 0, 26 }, { 75, 66, 26 }, // und_BM -> en_Latn_BM
+ { 0, 29, 27 }, { 199, 29, 27 }, // und_Deva_BT -> ne_Deva_BT
+ { 0, 134, 27 }, { 73, 134, 27 }, // und_Tibt_BT -> dz_Tibt_BT
+ { 0, 0, 27 }, { 73, 134, 27 }, // und_BT -> dz_Tibt_BT
+ { 0, 66, 28 }, { 270, 66, 28 }, // und_Latn_BO -> es_Latn_BO
+ { 0, 0, 28 }, { 270, 66, 28 }, // und_BO -> es_Latn_BO
+ { 0, 27, 29 }, { 252, 27, 29 }, // und_Cyrl_BA -> sr_Cyrl_BA
+ { 0, 66, 29 }, { 42, 66, 29 }, // und_Latn_BA -> bs_Latn_BA
+ { 0, 0, 29 }, { 42, 66, 29 }, // und_BA -> bs_Latn_BA
+ { 0, 0, 30 }, { 75, 66, 30 }, // und_BW -> en_Latn_BW
+ { 0, 0, 31 }, { 75, 66, 31 }, // und_BV -> en_Latn_BV
+ { 0, 66, 32 }, { 231, 66, 32 }, // und_Latn_BR -> pt_Latn_BR
+ { 0, 0, 32 }, { 231, 66, 32 }, // und_BR -> pt_Latn_BR
+ { 0, 0, 33 }, { 75, 66, 33 }, // und_IO -> en_Latn_IO
+ { 0, 0, 34 }, { 75, 66, 34 }, // und_VG -> en_Latn_VG
+ { 0, 66, 35 }, { 176, 66, 35 }, // und_Latn_BN -> ms_Latn_BN
+ { 0, 0, 35 }, { 176, 66, 35 }, // und_BN -> ms_Latn_BN
+ { 0, 27, 36 }, { 45, 27, 36 }, // und_Cyrl_BG -> bg_Cyrl_BG
+ { 0, 0, 36 }, { 45, 27, 36 }, // und_BG -> bg_Cyrl_BG
+ { 0, 66, 37 }, { 85, 66, 37 }, // und_Latn_BF -> fr_Latn_BF
+ { 0, 0, 37 }, { 85, 66, 37 }, // und_BF -> fr_Latn_BF
+ { 0, 66, 38 }, { 238, 66, 38 }, // und_Latn_BI -> rn_Latn_BI
+ { 0, 0, 38 }, { 238, 66, 38 }, // und_BI -> rn_Latn_BI
+ { 0, 0, 39 }, { 135, 60, 39 }, // und_KH -> km_Khmr_KH
+ { 0, 66, 40 }, { 85, 66, 40 }, // und_Latn_CM -> fr_Latn_CM
+ { 0, 0, 40 }, { 85, 66, 40 }, // und_CM -> fr_Latn_CM
+ { 0, 137, 41 }, { 47, 137, 41 }, // und_Hant_CA -> yue_Hant_CA
+ { 0, 0, 41 }, { 75, 66, 41 }, // und_CA -> en_Latn_CA
+ { 0, 66, 42 }, { 270, 66, 42 }, // und_Latn_IC -> es_Latn_IC
+ { 0, 0, 42 }, { 270, 66, 42 }, // und_IC -> es_Latn_IC
+ { 0, 66, 43 }, { 231, 66, 43 }, // und_Latn_CV -> pt_Latn_CV
+ { 0, 0, 43 }, { 231, 66, 43 }, // und_CV -> pt_Latn_CV
+ { 0, 66, 44 }, { 226, 66, 44 }, // und_Latn_BQ -> pap_Latn_BQ
+ { 0, 0, 44 }, { 226, 66, 44 }, // und_BQ -> pap_Latn_BQ
+ { 0, 0, 45 }, { 75, 66, 45 }, // und_KY -> en_Latn_KY
+ { 0, 66, 46 }, { 85, 66, 46 }, // und_Latn_CF -> fr_Latn_CF
+ { 0, 0, 46 }, { 85, 66, 46 }, // und_CF -> fr_Latn_CF
+ { 0, 66, 47 }, { 270, 66, 47 }, // und_Latn_EA -> es_Latn_EA
+ { 0, 0, 47 }, { 270, 66, 47 }, // und_EA -> es_Latn_EA
+ { 0, 66, 48 }, { 85, 66, 48 }, // und_Latn_TD -> fr_Latn_TD
+ { 0, 0, 48 }, { 85, 66, 48 }, // und_TD -> fr_Latn_TD
+ { 0, 66, 49 }, { 270, 66, 49 }, // und_Latn_CL -> es_Latn_CL
+ { 0, 0, 49 }, { 270, 66, 49 }, // und_CL -> es_Latn_CL
+ { 0, 4, 50 }, { 306, 4, 50 }, // und_Arab_CN -> ug_Arab_CN
+ { 0, 66, 50 }, { 326, 66, 50 }, // und_Latn_CN -> za_Latn_CN
+ { 0, 0, 50 }, { 58, 118, 50 }, // und_CN -> zh_Hans_CN
+ { 0, 0, 51 }, { 75, 66, 51 }, // und_CX -> en_Latn_CX
+ { 0, 0, 52 }, { 75, 66, 52 }, // und_CP -> en_Latn_CP
+ { 0, 4, 53 }, { 176, 4, 53 }, // und_Arab_CC -> ms_Arab_CC
+ { 0, 0, 53 }, { 176, 4, 53 }, // und_CC -> ms_Arab_CC
+ { 0, 66, 54 }, { 270, 66, 54 }, // und_Latn_CO -> es_Latn_CO
+ { 0, 0, 54 }, { 270, 66, 54 }, // und_CO -> es_Latn_CO
+ { 0, 66, 55 }, { 85, 66, 55 }, // und_Latn_KM -> fr_Latn_KM
+ { 0, 0, 55 }, { 14, 4, 55 }, // und_KM -> ar_Arab_KM
+ { 0, 66, 56 }, { 85, 66, 56 }, // und_Latn_CG -> fr_Latn_CG
+ { 0, 0, 56 }, { 85, 66, 56 }, // und_CG -> fr_Latn_CG
+ { 0, 66, 57 }, { 273, 66, 57 }, // und_Latn_CD -> sw_Latn_CD
+ { 0, 0, 57 }, { 273, 66, 57 }, // und_CD -> sw_Latn_CD
+ { 0, 0, 58 }, { 75, 66, 58 }, // und_CK -> en_Latn_CK
+ { 0, 66, 59 }, { 270, 66, 59 }, // und_Latn_CR -> es_Latn_CR
+ { 0, 0, 59 }, { 270, 66, 59 }, // und_CR -> es_Latn_CR
+ { 0, 66, 60 }, { 66, 66, 60 }, // und_Latn_HR -> hr_Latn_HR
+ { 0, 0, 60 }, { 66, 66, 60 }, // und_HR -> hr_Latn_HR
+ { 0, 66, 61 }, { 270, 66, 61 }, // und_Latn_CU -> es_Latn_CU
+ { 0, 0, 61 }, { 270, 66, 61 }, // und_CU -> es_Latn_CU
+ { 0, 66, 62 }, { 226, 66, 62 }, // und_Latn_CW -> pap_Latn_CW
+ { 0, 0, 62 }, { 226, 66, 62 }, // und_CW -> pap_Latn_CW
+ { 0, 66, 63 }, { 298, 66, 63 }, // und_Latn_CY -> tr_Latn_CY
+ { 0, 0, 63 }, { 96, 39, 63 }, // und_CY -> el_Grek_CY
+ { 0, 66, 64 }, { 67, 66, 64 }, // und_Latn_CZ -> cs_Latn_CZ
+ { 0, 0, 64 }, { 67, 66, 64 }, // und_CZ -> cs_Latn_CZ
+ { 0, 66, 65 }, { 68, 66, 65 }, // und_Latn_DK -> da_Latn_DK
+ { 0, 0, 65 }, { 68, 66, 65 }, // und_DK -> da_Latn_DK
+ { 0, 0, 66 }, { 75, 66, 66 }, // und_DG -> en_Latn_DG
+ { 0, 66, 67 }, { 3, 66, 67 }, // und_Latn_DJ -> aa_Latn_DJ
+ { 0, 0, 67 }, { 3, 66, 67 }, // und_DJ -> aa_Latn_DJ
+ { 0, 0, 68 }, { 75, 66, 68 }, // und_DM -> en_Latn_DM
+ { 0, 66, 69 }, { 270, 66, 69 }, // und_Latn_DO -> es_Latn_DO
+ { 0, 0, 69 }, { 270, 66, 69 }, // und_DO -> es_Latn_DO
+ { 0, 66, 70 }, { 270, 66, 70 }, // und_Latn_EC -> es_Latn_EC
+ { 0, 0, 70 }, { 270, 66, 70 }, // und_EC -> es_Latn_EC
+ { 0, 0, 71 }, { 14, 4, 71 }, // und_EG -> ar_Arab_EG
+ { 0, 66, 72 }, { 270, 66, 72 }, // und_Latn_SV -> es_Latn_SV
+ { 0, 0, 72 }, { 270, 66, 72 }, // und_SV -> es_Latn_SV
+ { 0, 66, 73 }, { 270, 66, 73 }, // und_Latn_GQ -> es_Latn_GQ
+ { 0, 0, 73 }, { 270, 66, 73 }, // und_GQ -> es_Latn_GQ
+ { 0, 33, 74 }, { 292, 33, 74 }, // und_Ethi_ER -> ti_Ethi_ER
+ { 0, 0, 74 }, { 292, 33, 74 }, // und_ER -> ti_Ethi_ER
+ { 0, 66, 75 }, { 78, 66, 75 }, // und_Latn_EE -> et_Latn_EE
+ { 0, 0, 75 }, { 78, 66, 75 }, // und_EE -> et_Latn_EE
+ { 0, 0, 76 }, { 75, 66, 76 }, // und_SZ -> en_Latn_SZ
+ { 0, 66, 77 }, { 75, 66, 77 }, // und_Latn_ET -> en_Latn_ET
+ { 0, 0, 77 }, { 11, 33, 77 }, // und_ET -> am_Ethi_ET
+ { 0, 0, 80 }, { 75, 66, 80 }, // und_FK -> en_Latn_FK
+ { 0, 66, 81 }, { 81, 66, 81 }, // und_Latn_FO -> fo_Latn_FO
+ { 0, 0, 81 }, { 81, 66, 81 }, // und_FO -> fo_Latn_FO
+ { 0, 0, 82 }, { 75, 66, 82 }, // und_FJ -> en_Latn_FJ
+ { 0, 66, 83 }, { 84, 66, 83 }, // und_Latn_FI -> fi_Latn_FI
+ { 0, 0, 83 }, { 84, 66, 83 }, // und_FI -> fi_Latn_FI
+ { 0, 66, 84 }, { 85, 66, 84 }, // und_Latn_FR -> fr_Latn_FR
+ { 0, 0, 84 }, { 85, 66, 84 }, // und_FR -> fr_Latn_FR
+ { 0, 66, 85 }, { 85, 66, 85 }, // und_Latn_GF -> fr_Latn_GF
+ { 0, 0, 85 }, { 85, 66, 85 }, // und_GF -> fr_Latn_GF
+ { 0, 66, 86 }, { 85, 66, 86 }, // und_Latn_PF -> fr_Latn_PF
+ { 0, 0, 86 }, { 85, 66, 86 }, // und_PF -> fr_Latn_PF
+ { 0, 66, 87 }, { 85, 66, 87 }, // und_Latn_TF -> fr_Latn_TF
+ { 0, 0, 87 }, { 85, 66, 87 }, // und_TF -> fr_Latn_TF
+ { 0, 66, 88 }, { 85, 66, 88 }, // und_Latn_GA -> fr_Latn_GA
+ { 0, 0, 88 }, { 85, 66, 88 }, // und_GA -> fr_Latn_GA
+ { 0, 0, 89 }, { 75, 66, 89 }, // und_GM -> en_Latn_GM
+ { 0, 27, 90 }, { 2, 27, 90 }, // und_Cyrl_GE -> ab_Cyrl_GE
+ { 0, 66, 90 }, { 148, 66, 90 }, // und_Latn_GE -> ku_Latn_GE
+ { 0, 0, 90 }, { 93, 35, 90 }, // und_GE -> ka_Geor_GE
+ { 0, 66, 91 }, { 94, 66, 91 }, // und_Latn_DE -> de_Latn_DE
+ { 0, 0, 91 }, { 94, 66, 91 }, // und_DE -> de_Latn_DE
+ { 0, 66, 92 }, { 6, 66, 92 }, // und_Latn_GH -> ak_Latn_GH
+ { 0, 0, 92 }, { 6, 66, 92 }, // und_GH -> ak_Latn_GH
+ { 0, 0, 93 }, { 75, 66, 93 }, // und_GI -> en_Latn_GI
+ { 0, 27, 94 }, { 169, 27, 94 }, // und_Cyrl_GR -> mk_Cyrl_GR
+ { 0, 0, 94 }, { 96, 39, 94 }, // und_GR -> el_Grek_GR
+ { 0, 66, 95 }, { 127, 66, 95 }, // und_Latn_GL -> kl_Latn_GL
+ { 0, 0, 95 }, { 127, 66, 95 }, // und_GL -> kl_Latn_GL
+ { 0, 0, 96 }, { 75, 66, 96 }, // und_GD -> en_Latn_GD
+ { 0, 66, 97 }, { 85, 66, 97 }, // und_Latn_GP -> fr_Latn_GP
+ { 0, 0, 97 }, { 85, 66, 97 }, // und_GP -> fr_Latn_GP
+ { 0, 0, 98 }, { 75, 66, 98 }, // und_GU -> en_Latn_GU
+ { 0, 66, 99 }, { 270, 66, 99 }, // und_Latn_GT -> es_Latn_GT
+ { 0, 0, 99 }, { 270, 66, 99 }, // und_GT -> es_Latn_GT
+ { 0, 0, 100 }, { 75, 66, 100 }, // und_GG -> en_Latn_GG
+ { 0, 66, 101 }, { 231, 66, 101 }, // und_Latn_GW -> pt_Latn_GW
+ { 0, 0, 101 }, { 231, 66, 101 }, // und_GW -> pt_Latn_GW
+ { 0, 66, 102 }, { 85, 66, 102 }, // und_Latn_GN -> fr_Latn_GN
+ { 0, 0, 102 }, { 85, 66, 102 }, // und_GN -> fr_Latn_GN
+ { 0, 0, 103 }, { 75, 66, 103 }, // und_GY -> en_Latn_GY
+ { 0, 66, 104 }, { 100, 66, 104 }, // und_Latn_HT -> ht_Latn_HT
+ { 0, 0, 104 }, { 100, 66, 104 }, // und_HT -> ht_Latn_HT
+ { 0, 0, 105 }, { 75, 66, 105 }, // und_HM -> en_Latn_HM
+ { 0, 66, 106 }, { 270, 66, 106 }, // und_Latn_HN -> es_Latn_HN
+ { 0, 0, 106 }, { 270, 66, 106 }, // und_HN -> es_Latn_HN
+ { 0, 0, 107 }, { 58, 137, 107 }, // und_HK -> zh_Hant_HK
+ { 0, 66, 108 }, { 107, 66, 108 }, // und_Latn_HU -> hu_Latn_HU
+ { 0, 0, 108 }, { 107, 66, 108 }, // und_HU -> hu_Latn_HU
+ { 0, 66, 109 }, { 108, 66, 109 }, // und_Latn_IS -> is_Latn_IS
+ { 0, 0, 109 }, { 108, 66, 109 }, // und_IS -> is_Latn_IS
+ { 0, 4, 110 }, { 305, 4, 110 }, // und_Arab_IN -> ur_Arab_IN
+ { 0, 0, 110 }, { 105, 29, 110 }, // und_IN -> hi_Deva_IN
+ { 0, 4, 111 }, { 176, 4, 111 }, // und_Arab_ID -> ms_Arab_ID
+ { 0, 66, 111 }, { 112, 66, 111 }, // und_Latn_ID -> id_Latn_ID
+ { 0, 0, 111 }, { 112, 66, 111 }, // und_ID -> id_Latn_ID
+ { 0, 4, 112 }, { 228, 4, 112 }, // und_Arab_IR -> fa_Arab_IR
+ { 0, 66, 112 }, { 299, 66, 112 }, // und_Latn_IR -> tk_Latn_IR
+ { 0, 0, 112 }, { 228, 4, 112 }, // und_IR -> fa_Arab_IR
+ { 0, 0, 113 }, { 14, 4, 113 }, // und_IQ -> ar_Arab_IQ
+ { 0, 0, 114 }, { 75, 66, 114 }, // und_IE -> en_Latn_IE
+ { 0, 0, 115 }, { 75, 66, 115 }, // und_IM -> en_Latn_IM
+ { 0, 0, 116 }, { 103, 47, 116 }, // und_IL -> he_Hebr_IL
+ { 0, 66, 117 }, { 119, 66, 117 }, // und_Latn_IT -> it_Latn_IT
+ { 0, 0, 117 }, { 119, 66, 117 }, // und_IT -> it_Latn_IT
+ { 0, 66, 118 }, { 85, 66, 118 }, // und_Latn_CI -> fr_Latn_CI
+ { 0, 0, 118 }, { 85, 66, 118 }, // und_CI -> fr_Latn_CI
+ { 0, 0, 119 }, { 75, 66, 119 }, // und_JM -> en_Latn_JM
+ { 0, 0, 120 }, { 120, 53, 120 }, // und_JP -> ja_Jpan_JP
+ { 0, 0, 121 }, { 75, 66, 121 }, // und_JE -> en_Latn_JE
+ { 0, 0, 122 }, { 14, 4, 122 }, // und_JO -> ar_Arab_JO
+ { 0, 0, 123 }, { 239, 27, 123 }, // und_KZ -> ru_Cyrl_KZ
+ { 0, 66, 124 }, { 273, 66, 124 }, // und_Latn_KE -> sw_Latn_KE
+ { 0, 0, 124 }, { 273, 66, 124 }, // und_KE -> sw_Latn_KE
+ { 0, 0, 125 }, { 75, 66, 125 }, // und_KI -> en_Latn_KI
+ { 0, 27, 126 }, { 252, 27, 126 }, // und_Cyrl_XK -> sr_Cyrl_XK
+ { 0, 66, 126 }, { 9, 66, 126 }, // und_Latn_XK -> sq_Latn_XK
+ { 0, 0, 126 }, { 9, 66, 126 }, // und_XK -> sq_Latn_XK
+ { 0, 0, 127 }, { 14, 4, 127 }, // und_KW -> ar_Arab_KW
+ { 0, 27, 128 }, { 150, 27, 128 }, // und_Cyrl_KG -> ky_Cyrl_KG
+ { 0, 0, 128 }, { 150, 27, 128 }, // und_KG -> ky_Cyrl_KG
+ { 0, 0, 129 }, { 153, 65, 129 }, // und_LA -> lo_Laoo_LA
+ { 0, 66, 130 }, { 270, 66, 130 }, // und_Latn_419 -> es_Latn_419
+ { 0, 0, 130 }, { 270, 66, 130 }, // und_419 -> es_Latn_419
+ { 0, 66, 131 }, { 155, 66, 131 }, // und_Latn_LV -> lv_Latn_LV
+ { 0, 0, 131 }, { 155, 66, 131 }, // und_LV -> lv_Latn_LV
+ { 0, 0, 132 }, { 14, 4, 132 }, // und_LB -> ar_Arab_LB
+ { 0, 66, 133 }, { 268, 66, 133 }, // und_Latn_LS -> st_Latn_LS
+ { 0, 0, 133 }, { 268, 66, 133 }, // und_LS -> st_Latn_LS
+ { 0, 0, 134 }, { 75, 66, 134 }, // und_LR -> en_Latn_LR
+ { 0, 0, 135 }, { 14, 4, 135 }, // und_LY -> ar_Arab_LY
+ { 0, 66, 136 }, { 94, 66, 136 }, // und_Latn_LI -> de_Latn_LI
+ { 0, 0, 136 }, { 94, 66, 136 }, // und_LI -> de_Latn_LI
+ { 0, 66, 137 }, { 160, 66, 137 }, // und_Latn_LT -> lt_Latn_LT
+ { 0, 0, 137 }, { 160, 66, 137 }, // und_LT -> lt_Latn_LT
+ { 0, 66, 138 }, { 85, 66, 138 }, // und_Latn_LU -> fr_Latn_LU
+ { 0, 0, 138 }, { 85, 66, 138 }, // und_LU -> fr_Latn_LU
+ { 0, 66, 139 }, { 231, 66, 139 }, // und_Latn_MO -> pt_Latn_MO
+ { 0, 0, 139 }, { 58, 137, 139 }, // und_MO -> zh_Hant_MO
+ { 0, 27, 140 }, { 169, 27, 140 }, // und_Cyrl_MK -> mk_Cyrl_MK
+ { 0, 66, 140 }, { 9, 66, 140 }, // und_Latn_MK -> sq_Latn_MK
+ { 0, 0, 140 }, { 169, 27, 140 }, // und_MK -> mk_Cyrl_MK
+ { 0, 66, 141 }, { 174, 66, 141 }, // und_Latn_MG -> mg_Latn_MG
+ { 0, 0, 141 }, { 174, 66, 141 }, // und_MG -> mg_Latn_MG
+ { 0, 0, 142 }, { 75, 66, 142 }, // und_MW -> en_Latn_MW
+ { 0, 66, 143 }, { 176, 66, 143 }, // und_Latn_MY -> ms_Latn_MY
+ { 0, 0, 143 }, { 176, 66, 143 }, // und_MY -> ms_Latn_MY
+ { 0, 0, 144 }, { 69, 132, 144 }, // und_MV -> dv_Thaa_MV
+ { 0, 66, 145 }, { 28, 66, 145 }, // und_Latn_ML -> bm_Latn_ML
+ { 0, 0, 145 }, { 28, 66, 145 }, // und_ML -> bm_Latn_ML
+ { 0, 66, 146 }, { 177, 66, 146 }, // und_Latn_MT -> mt_Latn_MT
+ { 0, 0, 146 }, { 177, 66, 146 }, // und_MT -> mt_Latn_MT
+ { 0, 0, 147 }, { 75, 66, 147 }, // und_MH -> en_Latn_MH
+ { 0, 66, 148 }, { 85, 66, 148 }, // und_Latn_MQ -> fr_Latn_MQ
+ { 0, 0, 148 }, { 85, 66, 148 }, // und_MQ -> fr_Latn_MQ
+ { 0, 66, 149 }, { 85, 66, 149 }, // und_Latn_MR -> fr_Latn_MR
+ { 0, 0, 149 }, { 14, 4, 149 }, // und_MR -> ar_Arab_MR
+ { 0, 4, 150 }, { 305, 4, 150 }, // und_Arab_MU -> ur_Arab_MU
+ { 0, 29, 150 }, { 38, 29, 150 }, // und_Deva_MU -> bho_Deva_MU
+ { 0, 66, 150 }, { 192, 66, 150 }, // und_Latn_MU -> mfe_Latn_MU
+ { 0, 0, 150 }, { 192, 66, 150 }, // und_MU -> mfe_Latn_MU
+ { 0, 66, 151 }, { 85, 66, 151 }, // und_Latn_YT -> fr_Latn_YT
+ { 0, 0, 151 }, { 85, 66, 151 }, // und_YT -> fr_Latn_YT
+ { 0, 66, 152 }, { 270, 66, 152 }, // und_Latn_MX -> es_Latn_MX
+ { 0, 0, 152 }, { 270, 66, 152 }, // und_MX -> es_Latn_MX
+ { 0, 0, 153 }, { 75, 66, 153 }, // und_FM -> en_Latn_FM
+ { 0, 27, 154 }, { 303, 27, 154 }, // und_Cyrl_MD -> uk_Cyrl_MD
+ { 0, 66, 154 }, { 235, 66, 154 }, // und_Latn_MD -> ro_Latn_MD
+ { 0, 0, 154 }, { 235, 66, 154 }, // und_MD -> ro_Latn_MD
+ { 0, 66, 155 }, { 85, 66, 155 }, // und_Latn_MC -> fr_Latn_MC
+ { 0, 0, 155 }, { 85, 66, 155 }, // und_MC -> fr_Latn_MC
+ { 0, 4, 156 }, { 133, 4, 156 }, // und_Arab_MN -> kk_Arab_MN
+ { 0, 27, 156 }, { 191, 27, 156 }, // und_Cyrl_MN -> mn_Cyrl_MN
+ { 0, 0, 156 }, { 191, 27, 156 }, // und_MN -> mn_Cyrl_MN
+ { 0, 66, 157 }, { 252, 66, 157 }, // und_Latn_ME -> sr_Latn_ME
+ { 0, 0, 157 }, { 252, 66, 157 }, // und_ME -> sr_Latn_ME
+ { 0, 0, 158 }, { 75, 66, 158 }, // und_MS -> en_Latn_MS
+ { 0, 66, 159 }, { 85, 66, 159 }, // und_Latn_MA -> fr_Latn_MA
+ { 0, 0, 159 }, { 14, 4, 159 }, // und_MA -> ar_Arab_MA
+ { 0, 66, 160 }, { 231, 66, 160 }, // und_Latn_MZ -> pt_Latn_MZ
+ { 0, 0, 160 }, { 231, 66, 160 }, // und_MZ -> pt_Latn_MZ
+ { 0, 4, 161 }, { 339, 4, 161 }, // und_Arab_MM -> rhg_Arab_MM
+ { 0, 0, 161 }, { 46, 86, 161 }, // und_MM -> my_Mymr_MM
+ { 0, 66, 162 }, { 4, 66, 162 }, // und_Latn_NA -> af_Latn_NA
+ { 0, 0, 162 }, { 4, 66, 162 }, // und_NA -> af_Latn_NA
+ { 0, 0, 163 }, { 75, 66, 163 }, // und_NR -> en_Latn_NR
+ { 0, 29, 164 }, { 199, 29, 164 }, // und_Deva_NP -> ne_Deva_NP
+ { 0, 0, 164 }, { 199, 29, 164 }, // und_NP -> ne_Deva_NP
+ { 0, 66, 165 }, { 72, 66, 165 }, // und_Latn_NL -> nl_Latn_NL
+ { 0, 0, 165 }, { 72, 66, 165 }, // und_NL -> nl_Latn_NL
+ { 0, 66, 166 }, { 85, 66, 166 }, // und_Latn_NC -> fr_Latn_NC
+ { 0, 0, 166 }, { 85, 66, 166 }, // und_NC -> fr_Latn_NC
+ { 0, 0, 167 }, { 75, 66, 167 }, // und_NZ -> en_Latn_NZ
+ { 0, 66, 168 }, { 270, 66, 168 }, // und_Latn_NI -> es_Latn_NI
+ { 0, 0, 168 }, { 270, 66, 168 }, // und_NI -> es_Latn_NI
+ { 0, 4, 169 }, { 101, 4, 169 }, // und_Arab_NG -> ha_Arab_NG
+ { 0, 0, 169 }, { 75, 66, 169 }, // und_NG -> en_Latn_NG
+ { 0, 66, 170 }, { 101, 66, 170 }, // und_Latn_NE -> ha_Latn_NE
+ { 0, 0, 170 }, { 101, 66, 170 }, // und_NE -> ha_Latn_NE
+ { 0, 0, 171 }, { 75, 66, 171 }, // und_NU -> en_Latn_NU
+ { 0, 0, 172 }, { 75, 66, 172 }, // und_NF -> en_Latn_NF
+ { 0, 0, 173 }, { 75, 66, 173 }, // und_MP -> en_Latn_MP
+ { 0, 0, 174 }, { 142, 63, 174 }, // und_KP -> ko_Kore_KP
+ { 0, 66, 175 }, { 209, 66, 175 }, // und_Latn_NO -> nb_Latn_NO
+ { 0, 0, 175 }, { 209, 66, 175 }, // und_NO -> nb_Latn_NO
+ { 0, 0, 176 }, { 14, 4, 176 }, // und_OM -> ar_Arab_OM
+ { 0, 4, 178 }, { 305, 4, 178 }, // und_Arab_PK -> ur_Arab_PK
+ { 0, 0, 178 }, { 305, 4, 178 }, // und_PK -> ur_Arab_PK
+ { 0, 66, 179 }, { 224, 66, 179 }, // und_Latn_PW -> pau_Latn_PW
+ { 0, 0, 179 }, { 224, 66, 179 }, // und_PW -> pau_Latn_PW
+ { 0, 0, 180 }, { 14, 4, 180 }, // und_PS -> ar_Arab_PS
+ { 0, 66, 181 }, { 270, 66, 181 }, // und_Latn_PA -> es_Latn_PA
+ { 0, 0, 181 }, { 270, 66, 181 }, // und_PA -> es_Latn_PA
+ { 0, 66, 182 }, { 294, 66, 182 }, // und_Latn_PG -> tpi_Latn_PG
+ { 0, 0, 182 }, { 294, 66, 182 }, // und_PG -> tpi_Latn_PG
+ { 0, 66, 183 }, { 97, 66, 183 }, // und_Latn_PY -> gn_Latn_PY
+ { 0, 0, 183 }, { 97, 66, 183 }, // und_PY -> gn_Latn_PY
+ { 0, 66, 184 }, { 270, 66, 184 }, // und_Latn_PE -> es_Latn_PE
+ { 0, 0, 184 }, { 270, 66, 184 }, // und_PE -> es_Latn_PE
+ { 0, 66, 185 }, { 83, 66, 185 }, // und_Latn_PH -> fil_Latn_PH
+ { 0, 0, 185 }, { 83, 66, 185 }, // und_PH -> fil_Latn_PH
+ { 0, 0, 186 }, { 75, 66, 186 }, // und_PN -> en_Latn_PN
+ { 0, 66, 187 }, { 230, 66, 187 }, // und_Latn_PL -> pl_Latn_PL
+ { 0, 0, 187 }, { 230, 66, 187 }, // und_PL -> pl_Latn_PL
+ { 0, 66, 188 }, { 231, 66, 188 }, // und_Latn_PT -> pt_Latn_PT
+ { 0, 0, 188 }, { 231, 66, 188 }, // und_PT -> pt_Latn_PT
+ { 0, 66, 189 }, { 270, 66, 189 }, // und_Latn_PR -> es_Latn_PR
+ { 0, 0, 189 }, { 270, 66, 189 }, // und_PR -> es_Latn_PR
+ { 0, 0, 190 }, { 14, 4, 190 }, // und_QA -> ar_Arab_QA
+ { 0, 66, 191 }, { 85, 66, 191 }, // und_Latn_RE -> fr_Latn_RE
+ { 0, 0, 191 }, { 85, 66, 191 }, // und_RE -> fr_Latn_RE
+ { 0, 27, 192 }, { 45, 27, 192 }, // und_Cyrl_RO -> bg_Cyrl_RO
+ { 0, 66, 192 }, { 235, 66, 192 }, // und_Latn_RO -> ro_Latn_RO
+ { 0, 0, 192 }, { 235, 66, 192 }, // und_RO -> ro_Latn_RO
+ { 0, 0, 193 }, { 239, 27, 193 }, // und_RU -> ru_Cyrl_RU
+ { 0, 66, 194 }, { 138, 66, 194 }, // und_Latn_RW -> rw_Latn_RW
+ { 0, 0, 194 }, { 138, 66, 194 }, // und_RW -> rw_Latn_RW
+ { 0, 66, 195 }, { 85, 66, 195 }, // und_Latn_BL -> fr_Latn_BL
+ { 0, 0, 195 }, { 85, 66, 195 }, // und_BL -> fr_Latn_BL
+ { 0, 0, 196 }, { 75, 66, 196 }, // und_SH -> en_Latn_SH
+ { 0, 0, 197 }, { 75, 66, 197 }, // und_KN -> en_Latn_KN
+ { 0, 0, 198 }, { 75, 66, 198 }, // und_LC -> en_Latn_LC
+ { 0, 66, 199 }, { 85, 66, 199 }, // und_Latn_MF -> fr_Latn_MF
+ { 0, 0, 199 }, { 85, 66, 199 }, // und_MF -> fr_Latn_MF
+ { 0, 66, 200 }, { 85, 66, 200 }, // und_Latn_PM -> fr_Latn_PM
+ { 0, 0, 200 }, { 85, 66, 200 }, // und_PM -> fr_Latn_PM
+ { 0, 0, 201 }, { 75, 66, 201 }, // und_VC -> en_Latn_VC
+ { 0, 66, 202 }, { 244, 66, 202 }, // und_Latn_WS -> sm_Latn_WS
+ { 0, 0, 202 }, { 244, 66, 202 }, // und_WS -> sm_Latn_WS
+ { 0, 66, 203 }, { 119, 66, 203 }, // und_Latn_SM -> it_Latn_SM
+ { 0, 0, 203 }, { 119, 66, 203 }, // und_SM -> it_Latn_SM
+ { 0, 66, 204 }, { 231, 66, 204 }, // und_Latn_ST -> pt_Latn_ST
+ { 0, 0, 204 }, { 231, 66, 204 }, // und_ST -> pt_Latn_ST
+ { 0, 0, 205 }, { 14, 4, 205 }, // und_SA -> ar_Arab_SA
+ { 0, 66, 206 }, { 85, 66, 206 }, // und_Latn_SN -> fr_Latn_SN
+ { 0, 0, 206 }, { 85, 66, 206 }, // und_SN -> fr_Latn_SN
+ { 0, 27, 207 }, { 252, 27, 207 }, // und_Cyrl_RS -> sr_Cyrl_RS
+ { 0, 66, 207 }, { 252, 66, 207 }, // und_Latn_RS -> sr_Latn_RS
+ { 0, 0, 207 }, { 252, 27, 207 }, // und_RS -> sr_Cyrl_RS
+ { 0, 66, 208 }, { 85, 66, 208 }, // und_Latn_SC -> fr_Latn_SC
+ { 0, 0, 208 }, { 85, 66, 208 }, // und_SC -> fr_Latn_SC
+ { 0, 0, 210 }, { 75, 66, 210 }, // und_SG -> en_Latn_SG
+ { 0, 0, 211 }, { 75, 66, 211 }, // und_SX -> en_Latn_SX
+ { 0, 27, 212 }, { 303, 27, 212 }, // und_Cyrl_SK -> uk_Cyrl_SK
+ { 0, 66, 212 }, { 262, 66, 212 }, // und_Latn_SK -> sk_Latn_SK
+ { 0, 0, 212 }, { 262, 66, 212 }, // und_SK -> sk_Latn_SK
+ { 0, 66, 213 }, { 263, 66, 213 }, // und_Latn_SI -> sl_Latn_SI
+ { 0, 0, 213 }, { 263, 66, 213 }, // und_SI -> sl_Latn_SI
+ { 0, 0, 214 }, { 75, 66, 214 }, // und_SB -> en_Latn_SB
+ { 0, 66, 215 }, { 265, 66, 215 }, // und_Latn_SO -> so_Latn_SO
+ { 0, 0, 215 }, { 265, 66, 215 }, // und_SO -> so_Latn_SO
+ { 0, 0, 216 }, { 75, 66, 216 }, // und_ZA -> en_Latn_ZA
+ { 0, 0, 217 }, { 75, 66, 217 }, // und_GS -> en_Latn_GS
+ { 0, 0, 218 }, { 142, 63, 218 }, // und_KR -> ko_Kore_KR
+ { 0, 0, 219 }, { 14, 4, 219 }, // und_SS -> ar_Arab_SS
+ { 0, 66, 220 }, { 270, 66, 220 }, // und_Latn_ES -> es_Latn_ES
+ { 0, 0, 220 }, { 270, 66, 220 }, // und_ES -> es_Latn_ES
+ { 0, 0, 221 }, { 260, 119, 221 }, // und_LK -> si_Sinh_LK
+ { 0, 0, 222 }, { 14, 4, 222 }, // und_SD -> ar_Arab_SD
+ { 0, 66, 223 }, { 72, 66, 223 }, // und_Latn_SR -> nl_Latn_SR
+ { 0, 0, 223 }, { 72, 66, 223 }, // und_SR -> nl_Latn_SR
+ { 0, 66, 224 }, { 209, 66, 224 }, // und_Latn_SJ -> nb_Latn_SJ
+ { 0, 0, 224 }, { 209, 66, 224 }, // und_SJ -> nb_Latn_SJ
+ { 0, 47, 225 }, { 323, 47, 225 }, // und_Hebr_SE -> yi_Hebr_SE
+ { 0, 66, 225 }, { 275, 66, 225 }, // und_Latn_SE -> sv_Latn_SE
+ { 0, 0, 225 }, { 275, 66, 225 }, // und_SE -> sv_Latn_SE
+ { 0, 66, 226 }, { 94, 66, 226 }, // und_Latn_CH -> de_Latn_CH
+ { 0, 0, 226 }, { 94, 66, 226 }, // und_CH -> de_Latn_CH
+ { 0, 66, 227 }, { 85, 66, 227 }, // und_Latn_SY -> fr_Latn_SY
+ { 0, 0, 227 }, { 14, 4, 227 }, // und_SY -> ar_Arab_SY
+ { 0, 66, 228 }, { 284, 66, 228 }, // und_Latn_TW -> trv_Latn_TW
+ { 0, 0, 228 }, { 58, 137, 228 }, // und_TW -> zh_Hant_TW
+ { 0, 4, 229 }, { 228, 4, 229 }, // und_Arab_TJ -> fa_Arab_TJ
+ { 0, 27, 229 }, { 282, 27, 229 }, // und_Cyrl_TJ -> tg_Cyrl_TJ
+ { 0, 0, 229 }, { 282, 27, 229 }, // und_TJ -> tg_Cyrl_TJ
+ { 0, 66, 230 }, { 273, 66, 230 }, // und_Latn_TZ -> sw_Latn_TZ
+ { 0, 0, 230 }, { 273, 66, 230 }, // und_TZ -> sw_Latn_TZ
+ { 0, 0, 231 }, { 289, 133, 231 }, // und_TH -> th_Thai_TH
+ { 0, 66, 232 }, { 231, 66, 232 }, // und_Latn_TL -> pt_Latn_TL
+ { 0, 0, 232 }, { 231, 66, 232 }, // und_TL -> pt_Latn_TL
+ { 0, 66, 233 }, { 85, 66, 233 }, // und_Latn_TG -> fr_Latn_TG
+ { 0, 0, 233 }, { 85, 66, 233 }, // und_TG -> fr_Latn_TG
+ { 0, 66, 234 }, { 293, 66, 234 }, // und_Latn_TK -> tkl_Latn_TK
+ { 0, 0, 234 }, { 293, 66, 234 }, // und_TK -> tkl_Latn_TK
+ { 0, 66, 235 }, { 295, 66, 235 }, // und_Latn_TO -> to_Latn_TO
+ { 0, 0, 235 }, { 295, 66, 235 }, // und_TO -> to_Latn_TO
+ { 0, 0, 236 }, { 75, 66, 236 }, // und_TT -> en_Latn_TT
+ { 0, 0, 237 }, { 75, 66, 237 }, // und_TA -> en_Latn_TA
+ { 0, 66, 238 }, { 85, 66, 238 }, // und_Latn_TN -> fr_Latn_TN
+ { 0, 0, 238 }, { 14, 4, 238 }, // und_TN -> ar_Arab_TN
+ { 0, 66, 239 }, { 298, 66, 239 }, // und_Latn_TR -> tr_Latn_TR
+ { 0, 0, 239 }, { 298, 66, 239 }, // und_TR -> tr_Latn_TR
+ { 0, 66, 240 }, { 299, 66, 240 }, // und_Latn_TM -> tk_Latn_TM
+ { 0, 0, 240 }, { 299, 66, 240 }, // und_TM -> tk_Latn_TM
+ { 0, 0, 241 }, { 75, 66, 241 }, // und_TC -> en_Latn_TC
+ { 0, 66, 242 }, { 300, 66, 242 }, // und_Latn_TV -> tvl_Latn_TV
+ { 0, 0, 242 }, { 300, 66, 242 }, // und_TV -> tvl_Latn_TV
+ { 0, 66, 243 }, { 273, 66, 243 }, // und_Latn_UG -> sw_Latn_UG
+ { 0, 0, 243 }, { 273, 66, 243 }, // und_UG -> sw_Latn_UG
+ { 0, 27, 244 }, { 303, 27, 244 }, // und_Cyrl_UA -> uk_Cyrl_UA
+ { 0, 47, 244 }, { 323, 47, 244 }, // und_Hebr_UA -> yi_Hebr_UA
+ { 0, 66, 244 }, { 230, 66, 244 }, // und_Latn_UA -> pl_Latn_UA
+ { 0, 0, 244 }, { 303, 27, 244 }, // und_UA -> uk_Cyrl_UA
+ { 0, 0, 245 }, { 14, 4, 245 }, // und_AE -> ar_Arab_AE
+ { 0, 4, 246 }, { 305, 4, 246 }, // und_Arab_GB -> ur_Arab_GB
+ { 0, 0, 246 }, { 75, 66, 246 }, // und_GB -> en_Latn_GB
+ { 0, 0, 247 }, { 75, 66, 247 }, // und_UM -> en_Latn_UM
+ { 0, 47, 248 }, { 323, 47, 248 }, // und_Hebr_US -> yi_Hebr_US
+ { 0, 0, 248 }, { 75, 66, 248 }, // und_US -> en_Latn_US
+ { 0, 0, 249 }, { 75, 66, 249 }, // und_VI -> en_Latn_VI
+ { 0, 66, 250 }, { 270, 66, 250 }, // und_Latn_UY -> es_Latn_UY
+ { 0, 0, 250 }, { 270, 66, 250 }, // und_UY -> es_Latn_UY
+ { 0, 66, 251 }, { 307, 66, 251 }, // und_Latn_UZ -> uz_Latn_UZ
+ { 0, 0, 251 }, { 307, 66, 251 }, // und_UZ -> uz_Latn_UZ
+ { 0, 66, 252 }, { 39, 66, 252 }, // und_Latn_VU -> bi_Latn_VU
+ { 0, 0, 252 }, { 39, 66, 252 }, // und_VU -> bi_Latn_VU
+ { 0, 66, 253 }, { 119, 66, 253 }, // und_Latn_VA -> it_Latn_VA
+ { 0, 0, 253 }, { 119, 66, 253 }, // und_VA -> it_Latn_VA
+ { 0, 66, 254 }, { 270, 66, 254 }, // und_Latn_VE -> es_Latn_VE
+ { 0, 0, 254 }, { 270, 66, 254 }, // und_VE -> es_Latn_VE
+ { 0, 66, 255 }, { 310, 66, 255 }, // und_Latn_VN -> vi_Latn_VN
+ { 0, 0, 255 }, { 310, 66, 255 }, // und_VN -> vi_Latn_VN
+ { 0, 66, 256 }, { 85, 66, 256 }, // und_Latn_WF -> fr_Latn_WF
+ { 0, 0, 256 }, { 85, 66, 256 }, // und_WF -> fr_Latn_WF
+ { 0, 0, 257 }, { 14, 4, 257 }, // und_EH -> ar_Arab_EH
+ { 0, 0, 259 }, { 14, 4, 259 }, // und_YE -> ar_Arab_YE
+ { 0, 66, 260 }, { 36, 66, 260 }, // und_Latn_ZM -> bem_Latn_ZM
+ { 0, 0, 260 }, { 36, 66, 260 }, // und_ZM -> bem_Latn_ZM
+ { 0, 66, 261 }, { 254, 66, 261 }, // und_Latn_ZW -> sn_Latn_ZW
+ { 0, 0, 261 }, { 254, 66, 261 }, // und_ZW -> sn_Latn_ZW
+ { 0, 1, 0 }, { 87, 1, 102 }, // und_Adlm -> ff_Adlm_GN
+ { 0, 4, 0 }, { 14, 4, 71 }, // und_Arab -> ar_Arab_EG
+ { 0, 5, 0 }, { 17, 5, 12 }, // und_Armn -> hy_Armn_AM
+ { 0, 6, 0 }, { 23, 6, 112 }, // und_Avst -> ae_Avst_IR
+ { 0, 7, 0 }, { 27, 7, 111 }, // und_Bali -> ban_Bali_ID
+ { 0, 8, 0 }, { 29, 8, 40 }, // und_Bamu -> bax_Bamu_CM
+ { 0, 9, 0 }, { 30, 9, 20 }, // und_Beng -> bn_Beng_BD
+ { 0, 11, 0 }, { 34, 11, 111 }, // und_Batk -> bbc_Batk_ID
+ { 0, 12, 0 }, { 247, 12, 110 }, // und_Bhks -> sa_Bhks_IN
+ { 0, 13, 0 }, { 58, 13, 228 }, // und_Bopo -> zh_Bopo_TW
+ { 0, 15, 0 }, { 85, 15, 84 }, // und_Brai -> fr_Brai_FR
+ { 0, 16, 0 }, { 44, 16, 111 }, // und_Bugi -> bug_Bugi_ID
+ { 0, 18, 0 }, { 116, 18, 41 }, // und_Cans -> iu_Cans_CA
+ { 0, 21, 0 }, { 52, 21, 20 }, // und_Cakm -> ccp_Cakm_BD
+ { 0, 23, 0 }, { 55, 23, 248 }, // und_Cher -> chr_Cher_US
+ { 0, 24, 0 }, { 62, 24, 71 }, // und_Copt -> cop_Copt_EG
+ { 0, 25, 0 }, { 7, 25, 113 }, // und_Xsux -> akk_Xsux_IQ
+ { 0, 26, 0 }, { 13, 26, 63 }, // und_Cprt -> grc_Cprt_CY
+ { 0, 27, 0 }, { 239, 27, 193 }, // und_Cyrl -> ru_Cyrl_RU
+ { 0, 29, 0 }, { 105, 29, 110 }, // und_Deva -> hi_Deva_IN
+ { 0, 30, 0 }, { 85, 30, 84 }, // und_Dupl -> fr_Dupl_FR
+ { 0, 31, 0 }, { 12, 31, 71 }, // und_Egyp -> egy_Egyp_EG
+ { 0, 32, 0 }, { 9, 32, 3 }, // und_Elba -> sq_Elba_AL
+ { 0, 33, 0 }, { 11, 33, 77 }, // und_Ethi -> am_Ethi_ET
+ { 0, 35, 0 }, { 93, 35, 90 }, // und_Geor -> ka_Geor_GE
+ { 0, 36, 0 }, { 59, 36, 36 }, // und_Glag -> cu_Glag_BG
+ { 0, 37, 0 }, { 95, 37, 244 }, // und_Goth -> got_Goth_UA
+ { 0, 38, 0 }, { 247, 38, 110 }, // und_Gran -> sa_Gran_IN
+ { 0, 39, 0 }, { 96, 39, 94 }, // und_Grek -> el_Grek_GR
+ { 0, 40, 0 }, { 98, 40, 110 }, // und_Gujr -> gu_Gujr_IN
+ { 0, 41, 0 }, { 233, 41, 110 }, // und_Guru -> pa_Guru_IN
+ { 0, 42, 0 }, { 142, 42, 218 }, // und_Hang -> ko_Hang_KR
+ { 0, 43, 0 }, { 58, 43, 50 }, // und_Hani -> zh_Hani_CN
+ { 0, 45, 0 }, { 58, 45, 228 }, // und_Hanb -> zh_Hanb_TW
+ { 0, 47, 0 }, { 103, 47, 116 }, // und_Hebr -> he_Hebr_IL
+ { 0, 48, 0 }, { 120, 48, 120 }, // und_Hira -> ja_Hira_JP
+ { 0, 49, 0 }, { 16, 49, 112 }, // und_Armi -> arc_Armi_IR
+ { 0, 50, 0 }, { 223, 50, 112 }, // und_Phli -> pal_Phli_IR
+ { 0, 52, 0 }, { 142, 52, 218 }, // und_Jamo -> ko_Jamo_KR
+ { 0, 53, 0 }, { 120, 53, 120 }, // und_Jpan -> ja_Jpan_JP
+ { 0, 54, 0 }, { 121, 54, 111 }, // und_Java -> jv_Java_ID
+ { 0, 55, 0 }, { 38, 55, 110 }, // und_Kthi -> bho_Kthi_IN
+ { 0, 56, 0 }, { 130, 56, 110 }, // und_Knda -> kn_Knda_IN
+ { 0, 57, 0 }, { 120, 57, 120 }, // und_Kana -> ja_Kana_JP
+ { 0, 60, 0 }, { 135, 60, 39 }, // und_Khmr -> km_Khmr_KH
+ { 0, 61, 0 }, { 259, 61, 110 }, // und_Khoj -> sd_Khoj_IN
+ { 0, 62, 0 }, { 259, 62, 110 }, // und_Sind -> sd_Sind_IN
+ { 0, 63, 0 }, { 142, 63, 218 }, // und_Kore -> ko_Kore_KR
+ { 0, 65, 0 }, { 153, 65, 129 }, // und_Laoo -> lo_Laoo_LA
+ { 0, 66, 0 }, { 75, 66, 248 }, // und_Latn -> en_Latn_US
+ { 0, 70, 0 }, { 13, 70, 94 }, // und_Linb -> grc_Linb_GR
+ { 0, 73, 0 }, { 105, 73, 110 }, // und_Mahj -> hi_Mahj_IN
+ { 0, 74, 0 }, { 175, 74, 110 }, // und_Mlym -> ml_Mlym_IN
+ { 0, 77, 0 }, { 290, 77, 50 }, // und_Marc -> bo_Marc_CN
+ { 0, 78, 0 }, { 179, 78, 110 }, // und_Mtei -> mni_Mtei_IN
+ { 0, 79, 0 }, { 187, 79, 209 }, // und_Mend -> men_Mend_SL
+ { 0, 82, 0 }, { 183, 82, 110 }, // und_Modi -> mr_Modi_IN
+ { 0, 83, 0 }, { 191, 83, 50 }, // und_Mong -> mn_Mong_CN
+ { 0, 86, 0 }, { 46, 86, 161 }, // und_Mymr -> my_Mymr_MM
+ { 0, 87, 0 }, { 16, 87, 122 }, // und_Nbat -> arc_Nbat_JO
+ { 0, 88, 0 }, { 200, 88, 164 }, // und_Newa -> new_Newa_NP
+ { 0, 90, 0 }, { 178, 90, 102 }, // und_Nkoo -> man_Nkoo_GN
+ { 0, 91, 0 }, { 215, 91, 110 }, // und_Orya -> or_Orya_IN
+ { 0, 92, 0 }, { 217, 92, 114 }, // und_Ogam -> sga_Ogam_IE
+ { 0, 93, 0 }, { 248, 93, 110 }, // und_Olck -> sat_Olck_IN
+ { 0, 94, 0 }, { 107, 94, 108 }, // und_Hung -> hu_Hung_HU
+ { 0, 97, 0 }, { 139, 97, 193 }, // und_Perm -> kv_Perm_RU
+ { 0, 98, 0 }, { 219, 98, 112 }, // und_Xpeo -> peo_Xpeo_IR
+ { 0, 101, 0 }, { 221, 101, 248 }, // und_Osge -> osa_Osge_US
+ { 0, 102, 0 }, { 265, 102, 215 }, // und_Osma -> so_Osma_SO
+ { 0, 104, 0 }, { 16, 104, 227 }, // und_Palm -> arc_Palm_SY
+ { 0, 106, 0 }, { 159, 106, 50 }, // und_Phag -> lzh_Phag_CN
+ { 0, 107, 0 }, { 229, 107, 132 }, // und_Phnx -> phn_Phnx_LB
+ { 0, 109, 0 }, { 223, 109, 50 }, // und_Phlp -> pal_Phlp_CN
+ { 0, 111, 0 }, { 218, 111, 225 }, // und_Runr -> non_Runr_SE
+ { 0, 113, 0 }, { 250, 113, 110 }, // und_Saur -> saz_Saur_IN
+ { 0, 114, 0 }, { 247, 114, 110 }, // und_Shrd -> sa_Shrd_IN
+ { 0, 115, 0 }, { 75, 115, 246 }, // und_Shaw -> en_Shaw_GB
+ { 0, 116, 0 }, { 247, 116, 110 }, // und_Sidd -> sa_Sidd_IN
+ { 0, 117, 0 }, { 10, 117, 248 }, // und_Sgnw -> ase_Sgnw_US
+ { 0, 118, 0 }, { 58, 118, 50 }, // und_Hans -> zh_Hans_CN
+ { 0, 119, 0 }, { 260, 119, 221 }, // und_Sinh -> si_Sinh_LK
+ { 0, 121, 0 }, { 272, 121, 111 }, // und_Sund -> su_Sund_ID
+ { 0, 123, 0 }, { 277, 123, 113 }, // und_Syrc -> syr_Syrc_IQ
+ { 0, 124, 0 }, { 83, 124, 185 }, // und_Tglg -> fil_Tglg_PH
+ { 0, 127, 0 }, { 280, 127, 255 }, // und_Tavt -> blt_Tavt_VN
+ { 0, 128, 0 }, { 70, 128, 110 }, // und_Takr -> doi_Takr_IN
+ { 0, 129, 0 }, { 283, 129, 110 }, // und_Taml -> ta_Taml_IN
+ { 0, 131, 0 }, { 287, 131, 110 }, // und_Telu -> te_Telu_IN
+ { 0, 132, 0 }, { 69, 132, 144 }, // und_Thaa -> dv_Thaa_MV
+ { 0, 133, 0 }, { 289, 133, 231 }, // und_Thai -> th_Thai_TH
+ { 0, 134, 0 }, { 290, 134, 50 }, // und_Tibt -> bo_Tibt_CN
+ { 0, 135, 0 }, { 271, 135, 159 }, // und_Tfng -> zgh_Tfng_MA
+ { 0, 136, 0 }, { 171, 136, 110 }, // und_Tirh -> mai_Tirh_IN
+ { 0, 137, 0 }, { 58, 137, 228 }, // und_Hant -> zh_Hant_TW
+ { 0, 138, 0 }, { 302, 138, 227 }, // und_Ugar -> uga_Ugar_SY
+ { 0, 139, 0 }, { 308, 139, 134 }, // und_Vaii -> vai_Vaii_LR
+ { 0, 141, 0 }, { 255, 141, 50 }, // und_Yiii -> ii_Yiii_CN
+ { 0, 142, 0 }, { 339, 142, 161 } // und_Rohg -> rhg_Rohg_MM
};
-static const quint16 locale_index[] = {
+static constexpr quint16 locale_index[] = {
0, // AnyLanguage
0, // C
- 0, // Abkhazian
- 1, // Oromo
- 3, // Afar
- 4, // Afrikaans
- 6, // Albanian
- 9, // Amharic
- 10, // Arabic
- 38, // Armenian
- 39, // Assamese
+ 1, // Abkhazian
+ 2, // Afar
+ 5, // Afrikaans
+ 7, // Aghem
+ 8, // Akan
+ 0, // Akkadian
+ 9, // Akoose
+ 10, // Albanian
+ 0, // American Sign Language
+ 13, // Amharic
+ 0, // Ancient Egyptian
+ 0, // Ancient Greek
+ 14, // Arabic
+ 42, // Aragonese
+ 0, // Aramaic
+ 43, // Armenian
+ 44, // Assamese
+ 45, // Asturian
+ 46, // Asu
+ 47, // Atsam
+ 0, // Avaric
+ 0, // Avestan
0, // Aymara
- 40, // Azerbaijani
- 43, // Bashkir
- 44, // Basque
- 45, // Bengali
- 47, // Dzongkha
- 0, // Bihari
+ 48, // Azerbaijani
+ 53, // Bafia
+ 0, // Balinese
+ 54, // Bambara
+ 0, // Bamun
+ 56, // Bangla
+ 58, // Basaa
+ 59, // Bashkir
+ 60, // Basque
+ 0, // Batak Toba
+ 61, // Belarusian
+ 62, // Bemba
+ 63, // Bena
+ 64, // Bhojpuri
0, // Bislama
- 48, // Breton
- 49, // Bulgarian
- 50, // Burmese
- 51, // Belarusian
- 52, // Khmer
- 53, // Catalan
- 57, // Chinese
- 64, // Corsican
- 65, // Croatian
- 67, // Czech
- 68, // Danish
- 70, // Dutch
- 77, // English
- 183, // Esperanto
- 184, // Estonian
- 185, // Faroese
- 0, // Fijian
- 187, // Finnish
- 188, // French
- 234, // Western Frisian
- 235, // Gaelic
- 236, // Galician
- 237, // Georgian
- 238, // German
- 245, // Greek
- 247, // Greenlandic
- 248, // Guarani
- 249, // Gujarati
- 250, // Hausa
- 254, // Hebrew
- 255, // Hindi
- 256, // Hungarian
- 257, // Icelandic
- 258, // Indonesian
- 259, // Interlingua
- 0, // Interlingue
- 260, // Inuktitut
- 0, // Inupiak
- 262, // Irish
- 264, // Italian
- 268, // Japanese
- 269, // Javanese
- 270, // Kannada
- 271, // Kashmiri
- 272, // Kazakh
- 273, // Kinyarwanda
- 274, // Kirghiz
- 275, // Korean
- 277, // Kurdish
- 278, // Rundi
- 279, // Lao
- 0, // Latin
- 280, // Latvian
- 281, // Lingala
- 285, // Lithuanian
- 286, // Macedonian
- 287, // Malagasy
- 288, // Malay
- 292, // Malayalam
- 293, // Maltese
- 294, // Maori
- 295, // Marathi
- 0, // Marshallese
- 296, // Mongolian
- 0, // Nauru
- 298, // Nepali
- 300, // Norwegian Bokmal
- 302, // Occitan
- 303, // Oriya
- 304, // Pashto
- 306, // Persian
- 308, // Polish
- 309, // Portuguese
- 321, // Punjabi
- 323, // Quechua
- 326, // Romansh
- 327, // Romanian
- 329, // Russian
- 0, // Samoan
- 335, // Sango
- 336, // Sanskrit
- 337, // Serbian
- 345, // Ossetic
- 347, // Southern Sotho
- 348, // Tswana
- 349, // Shona
- 350, // Sindhi
- 351, // Sinhala
- 352, // Swati
- 353, // Slovak
- 354, // Slovenian
- 355, // Somali
- 359, // Spanish
- 387, // Sundanese
- 388, // Swahili
- 392, // Swedish
- 395, // Sardinian
- 396, // Tajik
- 397, // Tamil
- 401, // Tatar
- 402, // Telugu
- 403, // Thai
- 404, // Tibetan
- 406, // Tigrinya
- 408, // Tongan
- 409, // Tsonga
- 410, // Turkish
- 412, // Turkmen
- 0, // Tahitian
- 413, // Uighur
- 414, // Ukrainian
- 415, // Urdu
- 417, // Uzbek
- 420, // Vietnamese
- 421, // Volapuk
- 422, // Welsh
- 423, // Wolof
- 424, // Xhosa
- 425, // Yiddish
- 426, // Yoruba
- 0, // Zhuang
- 428, // Zulu
- 429, // Norwegian Nynorsk
- 430, // Bosnian
- 432, // Divehi
- 433, // Manx
- 434, // Cornish
- 435, // Akan
- 436, // Konkani
- 437, // Ga
- 438, // Igbo
- 439, // Kamba
- 440, // Syriac
- 441, // Blin
- 442, // Geez
- 0, // Koro
- 443, // Sidamo
- 444, // Atsam
- 445, // Tigre
- 446, // Jju
- 447, // Friulian
- 448, // Venda
- 449, // Ewe
- 451, // Walamo
- 452, // Hawaiian
- 453, // Tyap
- 454, // Nyanja
- 455, // Filipino
- 456, // Swiss German
- 459, // Sichuan Yi
- 460, // Kpelle
- 461, // Low German
- 463, // South Ndebele
- 464, // Northern Sotho
- 465, // Northern Sami
- 468, // Taroko
- 469, // Gusii
- 470, // Taita
- 471, // Fulah
- 484, // Kikuyu
- 485, // Samburu
- 486, // Sena
- 487, // North Ndebele
- 488, // Rombo
- 489, // Tachelhit
- 491, // Kabyle
- 492, // Nyankole
- 493, // Bena
- 494, // Vunjo
- 495, // Bambara
- 497, // Embu
- 498, // Cherokee
- 499, // Morisyen
- 500, // Makonde
- 501, // Langi
- 502, // Ganda
- 503, // Bemba
- 504, // Kabuverdianu
- 505, // Meru
- 506, // Kalenjin
- 507, // Nama
- 508, // Machame
- 509, // Colognian
- 510, // Masai
- 512, // Soga
- 513, // Luyia
- 514, // Asu
- 515, // Teso
- 517, // Saho
- 518, // Koyra Chiini
- 519, // Rwa
- 520, // Luo
- 521, // Chiga
- 522, // Central Morocco Tamazight
- 523, // Koyraboro Senni
- 524, // Shambala
- 525, // Bodo
- 0, // Avaric
+ 65, // Blin
+ 66, // Bodo
+ 67, // Bosnian
+ 69, // Breton
+ 0, // Buginese
+ 70, // Bulgarian
+ 71, // Burmese
+ 72, // Cantonese
+ 74, // Catalan
+ 78, // Cebuano
+ 79, // Central Atlas Tamazight
+ 80, // Central Kurdish
+ 82, // Chakma
0, // Chamorro
- 526, // Chechen
- 527, // Church
- 528, // Chuvash
+ 84, // Chechen
+ 85, // Cherokee
+ 86, // Chickasaw
+ 87, // Chiga
+ 88, // Chinese
+ 95, // Church
+ 96, // Chuvash
+ 97, // Colognian
+ 0, // Coptic
+ 98, // Cornish
+ 99, // Corsican
0, // Cree
+ 100, // Croatian
+ 102, // Czech
+ 103, // Danish
+ 105, // Divehi
+ 106, // Dogri
+ 107, // Duala
+ 108, // Dutch
+ 115, // Dzongkha
+ 116, // Embu
+ 117, // English
+ 226, // Erzya
+ 227, // Esperanto
+ 228, // Estonian
+ 229, // Ewe
+ 231, // Ewondo
+ 232, // Faroese
+ 0, // Fijian
+ 234, // Filipino
+ 235, // Finnish
+ 236, // French
+ 282, // Friulian
+ 283, // Fulah
+ 307, // Gaelic
+ 308, // Ga
+ 309, // Galician
+ 310, // Ganda
+ 311, // Geez
+ 313, // Georgian
+ 314, // German
+ 0, // Gothic
+ 321, // Greek
+ 323, // Guarani
+ 324, // Gujarati
+ 325, // Gusii
0, // Haitian
+ 326, // Hausa
+ 331, // Hawaiian
+ 332, // Hebrew
0, // Herero
+ 333, // Hindi
0, // Hiri Motu
+ 335, // Hungarian
+ 336, // Icelandic
+ 337, // Ido
+ 338, // Igbo
+ 339, // Inari Sami
+ 340, // Indonesian
+ 0, // Ingush
+ 341, // Interlingua
+ 342, // Interlingue
+ 343, // Inuktitut
+ 0, // Inupiaq
+ 345, // Irish
+ 347, // Italian
+ 351, // Japanese
+ 352, // Javanese
+ 353, // Jju
+ 354, // Jola-Fonyi
+ 355, // Kabuverdianu
+ 356, // Kabyle
+ 357, // Kako
+ 358, // Kalaallisut
+ 359, // Kalenjin
+ 360, // Kamba
+ 361, // Kannada
0, // Kanuri
+ 362, // Kashmiri
+ 364, // Kazakh
+ 365, // Kenyang
+ 366, // Khmer
+ 367, // Kiche
+ 368, // Kikuyu
+ 369, // Kinyarwanda
0, // Komi
0, // Kongo
- 0, // Kwanyama
+ 370, // Konkani
+ 371, // Korean
+ 0, // Koro
+ 374, // Koyraboro Senni
+ 375, // Koyra Chiini
+ 376, // Kpelle
+ 0, // Kuanyama
+ 378, // Kurdish
+ 379, // Kwasio
+ 380, // Kyrgyz
+ 381, // Lakota
+ 382, // Langi
+ 383, // Lao
+ 384, // Latin
+ 385, // Latvian
+ 0, // Lezghian
0, // Limburgish
- 529, // Luba Katanga
- 530, // Luxembourgish
- 0, // Navaho
+ 386, // Lingala
+ 0, // Literary Chinese
+ 390, // Lithuanian
+ 391, // Lojban
+ 392, // Lower Sorbian
+ 393, // Low German
+ 395, // Luba-Katanga
+ 396, // Lule Sami
+ 398, // Luo
+ 399, // Luxembourgish
+ 400, // Luyia
+ 401, // Macedonian
+ 402, // Machame
+ 403, // Maithili
+ 404, // Makhuwa-Meetto
+ 405, // Makonde
+ 406, // Malagasy
+ 407, // Malayalam
+ 408, // Malay
+ 414, // Maltese
+ 0, // Mandingo
+ 415, // Manipuri
+ 417, // Manx
+ 418, // Maori
+ 419, // Mapuche
+ 420, // Marathi
+ 0, // Marshallese
+ 421, // Masai
+ 423, // Mazanderani
+ 0, // Mende
+ 424, // Meru
+ 425, // Meta
+ 426, // Mohawk
+ 427, // Mongolian
+ 430, // Morisyen
+ 431, // Mundang
+ 432, // Muscogee
+ 433, // Nama
+ 0, // Nauru
+ 434, // Navajo
0, // Ndonga
+ 435, // Nepali
+ 0, // Newari
+ 437, // Ngiemboon
+ 438, // Ngomba
+ 439, // Nigerian Pidgin
+ 440, // Nko
+ 441, // Northern Luri
+ 443, // Northern Sami
+ 446, // Northern Sotho
+ 447, // North Ndebele
+ 448, // Norwegian Bokmal
+ 450, // Norwegian Nynorsk
+ 451, // Nuer
+ 452, // Nyanja
+ 453, // Nyankole
+ 454, // Occitan
+ 456, // Odia
0, // Ojibwa
- 0, // Pali
- 531, // Walloon
- 532, // Aghem
- 533, // Basaa
- 534, // Zarma
- 535, // Duala
- 536, // Jola Fonyi
- 537, // Ewondo
- 538, // Bafia
- 539, // Makhuwa Meetto
- 540, // Mundang
- 541, // Kwasio
- 542, // Nuer
- 543, // Sakha
- 544, // Sangu
- 0, // Congo Swahili
- 545, // Tasawaq
- 546, // Vai
- 548, // Walser
- 549, // Yangben
- 0, // Avestan
- 550, // Asturian
- 551, // Ngomba
- 552, // Kako
- 553, // Meta
- 554, // Ngiemboon
- 555, // Aragonese
- 0, // Akkadian
- 0, // Ancient Egyptian
- 0, // Ancient Greek
- 0, // Aramaic
- 0, // Balinese
- 0, // Bamun
- 0, // Batak Toba
- 0, // Buginese
- 0, // Buhid
- 0, // Carian
- 556, // Chakma
- 0, // Classical Mandaic
- 0, // Coptic
- 0, // Dogri
- 0, // Eastern Cham
- 0, // Eastern Kayah
- 0, // Etruscan
- 0, // Gothic
- 0, // Hanunoo
- 0, // Ingush
- 0, // Large Flowery Miao
- 0, // Lepcha
- 0, // Limbu
- 0, // Lisu
- 0, // Lu
- 0, // Lycian
- 0, // Lydian
- 0, // Mandingo
- 558, // Manipuri
- 0, // Meroitic
- 0, // Northern Thai
0, // Old Irish
0, // Old Norse
0, // Old Persian
- 0, // Old Turkish
+ 457, // Oromo
+ 459, // Osage
+ 460, // Ossetic
0, // Pahlavi
- 0, // Parthian
+ 0, // Palauan
+ 0, // Pali
+ 462, // Papiamento
+ 464, // Pashto
+ 466, // Persian
0, // Phoenician
- 0, // Prakrit Language
- 0, // Rejang
- 0, // Sabaean
- 0, // Samaritan
- 0, // Santali
+ 468, // Polish
+ 469, // Portuguese
+ 481, // Prussian
+ 482, // Punjabi
+ 484, // Quechua
+ 487, // Romanian
+ 489, // Romansh
+ 490, // Rombo
+ 491, // Rundi
+ 492, // Russian
+ 498, // Rwa
+ 499, // Saho
+ 500, // Sakha
+ 501, // Samburu
+ 0, // Samoan
+ 502, // Sango
+ 503, // Sangu
+ 504, // Sanskrit
+ 505, // Santali
+ 507, // Sardinian
0, // Saurashtra
- 0, // Sora
- 0, // Sylheti
- 0, // Tagbanwa
- 559, // Tai Dam
- 0, // Tai Nua
- 0, // Ugaritic
- 560, // Akoose
- 561, // Lakota
- 562, // Standard Moroccan Tamazight
- 563, // Mapuche
- 564, // Central Kurdish
- 566, // Lower Sorbian
- 567, // Upper Sorbian
- 568, // Kenyang
- 569, // Mohawk
- 570, // Nko
- 571, // Prussian
- 572, // Kiche
- 573, // Southern Sami
- 574, // Lule Sami
- 575, // Inari Sami
- 576, // Skolt Sami
- 577, // Warlpiri
- 0, // Manichaean Middle Persian
- 0, // Mende
- 0, // Ancient North Arabian
- 0, // Linear A
- 0, // Hmong Njua
- 0, // Ho
- 0, // Lezghian
- 0, // Bassa
- 0, // Mono
- 0, // Tedim Chin
- 0, // Maithili
- 0, // Ahom
- 0, // American Sign Language
- 0, // Ardhamagadhi Prakrit
- 0, // Bhojpuri
- 0, // Hieroglyphic Luwian
- 0, // Literary Chinese
- 578, // Mazanderani
- 0, // Mru
- 0, // Newari
- 579, // Northern Luri
- 0, // Palauan
- 0, // Papiamento
- 0, // Saraiki
+ 508, // Sena
+ 509, // Serbian
+ 517, // Shambala
+ 518, // Shona
+ 519, // Sichuan Yi
+ 520, // Sicilian
+ 521, // Sidamo
+ 522, // Silesian
+ 523, // Sindhi
+ 525, // Sinhala
+ 526, // Skolt Sami
+ 527, // Slovak
+ 528, // Slovenian
+ 529, // Soga
+ 530, // Somali
+ 534, // Southern Kurdish
+ 536, // Southern Sami
+ 538, // Southern Sotho
+ 540, // South Ndebele
+ 541, // Spanish
+ 569, // Standard Moroccan Tamazight
+ 570, // Sundanese
+ 571, // Swahili
+ 575, // Swati
+ 577, // Swedish
+ 580, // Swiss German
+ 583, // Syriac
+ 585, // Tachelhit
+ 0, // Tahitian
+ 587, // Tai Dam
+ 588, // Taita
+ 589, // Tajik
+ 590, // Tamil
+ 594, // Taroko
+ 595, // Tasawaq
+ 596, // Tatar
+ 597, // Telugu
+ 598, // Teso
+ 600, // Thai
+ 601, // Tibetan
+ 603, // Tigre
+ 604, // Tigrinya
0, // Tokelau
- 0, // Tok Pisin
+ 606, // Tok Pisin
+ 607, // Tongan
+ 608, // Tsonga
+ 609, // Tswana
+ 611, // Turkish
+ 613, // Turkmen
0, // Tuvalu
- 0, // Uncoded Languages
- 581, // Cantonese
- 583, // Osage
- 0, // Tangut
- 584, // Ido
- 585, // Lojban
- 586, // Sicilian
- 587, // Southern Kurdish
- 588, // Western Balochi
- 589, // Cebuano
- 590, // Erzya
- 591, // Chickasaw
- 592, // Muscogee
- 593, // Silesian
+ 614, // Tyap
+ 0, // Ugaritic
+ 615, // Ukrainian
+ 616, // Upper Sorbian
+ 617, // Urdu
+ 619, // Uyghur
+ 620, // Uzbek
+ 623, // Vai
+ 625, // Venda
+ 626, // Vietnamese
+ 627, // Volapuk
+ 628, // Vunjo
+ 629, // Walloon
+ 630, // Walser
+ 631, // Warlpiri
+ 632, // Welsh
+ 633, // Western Balochi
+ 638, // Western Frisian
+ 639, // Wolaytta
+ 640, // Wolof
+ 641, // Xhosa
+ 642, // Yangben
+ 643, // Yiddish
+ 644, // Yoruba
+ 646, // Zarma
+ 647, // Zhuang
+ 648, // Zulu
+ 649, // Kaingang
+ 650, // Nheengatu
+ 653, // Haryanvi
+ 654, // Northern Frisian
+ 655, // Rajasthani
+ 656, // Moksha
+ 657, // Toki Pona
+ 658, // Pijin
+ 659, // Obolo
+ 660, // Baluchi
+ 662, // Ligurian
+ 663, // Rohingya
+ 665, // Torwali
+ 666, // Anii
+ 667, // Kangri
+ 668, // Venetian
0 // trailing 0
};
-static const QLocaleData locale_data[] = {
- // lang script terr lStrt lpMid lpEnd lPair lDelm dec group prcnt zero minus plus exp qtOpn qtEnd altQO altQE lDFmt sDFmt lTFmt sTFmt slDay lDays ssDys sDays snDay nDays am pm byte siQnt iecQn crSym crDsp crFmt crFNg ntLng ntTer currISO curDgt curRnd dow1st wknd+ wknd-
- { 1, 0, 0, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 8, 0, 17, 0, 0, 0, 0, 56, 56, 83, 96, 0, 0, 0, 5, 22, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 8, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 4, 0, 0, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // C/AnyScript/AnyCountry
- { 3, 7, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 45, 10, 22, 109, 109, 163, 163, 83, 83, 2, 2, 0, 5, 22, 0, 0, 4, 0, 0, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 17, 4, 0, 6, 10, {69,84,66}, 2, 1, 7, 6, 7 }, // Oromo/Latin/Ethiopia
- { 3, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 45, 0, 0, 109, 109, 163, 163, 190, 190, 2, 2, 0, 5, 22, 2, 0, 4, 0, 0, 16, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 6, 8, {75,69,83}, 2, 1, 7, 6, 7 }, // Oromo/Latin/Kenya
- { 4, 7, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Afar/Latin/Ethiopia
- { 5, 7, 195, 0, 0, 7, 7, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 80, 70, 0, 0, 203, 203, 260, 260, 287, 287, 4, 4, 45, 5, 22, 5, 17, 4, 13, 24, 33, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 66, 4, 6, 9, 11, {90,65,82}, 2, 1, 7, 6, 7 }, // Afrikaans/Latin/South Africa
- { 5, 7, 148, 0, 0, 7, 7, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 70, 10, 22, 203, 203, 260, 260, 287, 287, 4, 4, 45, 5, 22, 6, 83, 4, 13, 24, 44, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 54, 4, 6, 9, 7, {78,65,68}, 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia
- { 6, 7, 2, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 29, 22, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 7, 137, 19, 24, 51, 56, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 7, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 4, 44, 5, 7, 5, 8, {65,76,76}, 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania
- { 6, 7, 127, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 0, 0, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 11, 181, 19, 24, 51, 64, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 3, 53, 5, 7, 5, 18, {77,75,68}, 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia
- { 6, 7, 257, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 0, 0, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 14, 234, 19, 24, 51, 82, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 1, 20, 5, 7, 5, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo
- { 7, 14, 69, 24, 24, 30, 39, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 17, 18, 53, 45, 10, 22, 425, 425, 452, 452, 478, 478, 18, 17, 54, 57, 22, 15, 254, 4, 13, 88, 92, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 26, 26, 13, 13, 3, 4, 3, 23, 23, 2, 33, 4, 6, 4, 5, {69,84,66}, 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia
- { 8, 1, 64, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 17, 287, 19, 0, 97, 104, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 80, 5, 0, 7, 3, {69,71,80}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt
- { 8, 1, 3, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 22, 367, 4, 13, 97, 107, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5,101, 4, 6, 7, 7, {68,90,68}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria
- { 8, 1, 17, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 27, 468, 19, 0, 97, 114, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 90, 5, 0, 7, 7, {66,72,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain
- { 8, 1, 42, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 32, 558, 19, 0, 97, 121, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4,111, 5, 0, 7, 4, {88,65,70}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad
- { 8, 1, 48, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 0, 0, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 33, 669, 19, 0, 97, 125, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 10, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 2,104, 5, 0, 7, 9, {75,77,70}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros
- { 8, 1, 59, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 36, 773, 19, 0, 97, 134, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 3, 83, 5, 0, 7, 6, {68,74,70}, 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti
- { 8, 1, 67, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 39, 856, 19, 0, 97, 140, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 3, 90, 5, 0, 7, 7, {69,82,78}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea
- { 8, 1, 103, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 42, 946, 19, 0, 97, 147, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {73,81,68}, 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq
- { 8, 1, 105, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 1, 1, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 47, 1029, 19, 0, 97, 153, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 9, 4, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,132, 5, 0, 7, 7, {73,76,83}, 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel
- { 8, 1, 109, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 48, 1161, 19, 0, 97, 160, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {74,79,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan
- { 8, 1, 115, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 53, 1244, 19, 0, 97, 166, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {75,87,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait
- { 8, 1, 119, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 58, 1327, 19, 0, 97, 172, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 5, {76,66,80}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon
- { 8, 1, 122, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 63, 1410, 4, 13, 97, 177, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 87, 4, 6, 7, 5, {76,89,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya
- { 8, 1, 136, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 68, 1497, 19, 0, 97, 182, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4,111, 5, 0, 7, 9, {77,82,85}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Mauritania
- { 8, 1, 145, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 0, 0, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 72, 1608, 4, 13, 97, 191, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 10, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 86, 4, 6, 7, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Morocco
- { 8, 1, 162, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 77, 1694, 19, 0, 97, 197, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 5, {79,77,82}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman
- { 8, 1, 165, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 47, 1029, 19, 0, 97, 202, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,132, 5, 0, 7, 18, {73,76,83}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Palestinian Territories
- { 8, 1, 175, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 82, 1770, 19, 0, 97, 220, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 69, 5, 0, 7, 3, {81,65,82}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar
- { 8, 1, 186, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 87, 1839, 19, 0, 97, 223, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 24, {83,65,82}, 2, 1, 7, 5, 6 }, // Arabic/Arabic/Saudi Arabia
- { 8, 1, 194, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 92, 1915, 19, 0, 97, 247, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1, 76, 5, 0, 7, 7, {83,79,83}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia
- { 8, 1, 201, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 93, 1991, 19, 0, 97, 254, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4, 90, 5, 0, 7, 7, {83,68,71}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan
- { 8, 1, 207, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 97, 2081, 19, 0, 97, 261, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 5, {83,89,80}, 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria
- { 8, 1, 216, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 102, 2157, 4, 13, 97, 266, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 94, 4, 6, 7, 4, {84,78,68}, 3, 0, 1, 6, 7 }, // Arabic/Arabic/Tunisia
- { 8, 1, 223, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 107, 2251, 19, 0, 97, 270, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 90, 5, 0, 7, 24, {65,69,68}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/United Arab Emirates
- { 8, 1, 236, 47, 47, 47, 47, 6, 0, 1, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 72, 1608, 4, 13, 97, 294, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 86, 4, 6, 7, 15, {77,65,68}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Western Sahara
- { 8, 1, 237, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 112, 2341, 19, 0, 97, 309, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 69, 5, 0, 7, 5, {89,69,82}, 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen
- { 8, 1, 254, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 117, 2410, 19, 0, 97, 314, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,131, 5, 0, 7, 12, {83,83,80}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/South Sudan
- { 8, 1, 260, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 0, 0, 19, 0, 326, 348, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 0, 0, 5, 0, 22, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/World
- { 9, 10, 11, 0, 0, 54, 54, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 15, 16, 146, 166, 0, 0, 555, 555, 616, 616, 643, 643, 0, 0, 131, 137, 22, 118, 2541, 19, 0, 354, 361, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 8, 10, 5, 61, 61, 27, 27, 13, 13, 2, 2, 6, 17, 23, 1, 45, 5, 0, 7, 8, {65,77,68}, 2, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia
- { 10, 11, 100, 0, 0, 61, 61, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 192, 42, 42, 656, 656, 713, 713, 744, 744, 22, 22, 154, 158, 22, 119, 2586, 8, 0, 369, 376, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 57, 57, 31, 31, 13, 13, 9, 7, 4, 37, 23, 1, 42, 5, 0, 7, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Assamese/Bengali/India
- { 12, 7, 15, 0, 0, 70, 70, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 200, 166, 0, 0, 757, 757, 823, 849, 96, 96, 0, 0, 195, 5, 22, 120, 2628, 19, 0, 380, 390, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 57, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan
- { 12, 1, 102, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {73,82,82}, 0, 0, 6, 5, 5 }, // Azerbaijani/Arabic/Iran
- { 12, 2, 15, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 200, 166, 0, 0, 875, 875, 941, 941, 96, 96, 31, 29, 0, 5, 22, 120, 2685, 19, 0, 400, 410, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 5, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan
- { 13, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 121, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {82,85,66}, 2, 1, 1, 6, 7 }, // Bashkir/Cyrillic/Russia
- { 14, 7, 197, 0, 0, 78, 78, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 10, 11, 217, 253, 54, 0, 967, 967, 1034, 1034, 1061, 1061, 0, 0, 199, 5, 22, 14, 2690, 19, 24, 420, 427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36, 6, 12, 5, 67, 67, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 19, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Basque/Latin/Spain
- { 15, 11, 18, 0, 0, 87, 87, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 1074, 1074, 1131, 1131, 1167, 1167, 0, 0, 154, 5, 22, 122, 2709, 0, 31, 435, 440, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 48, 4, 6, 5, 8, {66,68,84}, 2, 1, 7, 6, 7 }, // Bengali/Bengali/Bangladesh
- { 15, 11, 100, 0, 0, 87, 87, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 1074, 1074, 1131, 1131, 1167, 1167, 0, 0, 154, 5, 22, 119, 2757, 0, 31, 435, 448, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 42, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Bengali/Bengali/India
- { 16, 31, 25, 96, 96, 96, 96, 6, 0, 1, 2, 39, 4, 5, 9, 10, 11, 12, 13, 265, 70, 66, 93, 1184, 1184, 1262, 1262, 1295, 1295, 33, 31, 0, 5, 22, 123, 2799, 4, 0, 452, 458, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 10, 27, 22, 78, 78, 33, 33, 26, 26, 5, 6, 4, 17, 23, 3, 8, 4, 0, 6, 5, {66,84,78}, 2, 1, 7, 6, 7 }, // Dzongkha/Tibetan/Bhutan
- { 19, 7, 74, 0, 0, 105, 105, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 1321, 1321, 1363, 1363, 1395, 1395, 38, 37, 206, 213, 230, 14, 2807, 19, 0, 463, 472, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 42, 42, 32, 32, 17, 17, 4, 4, 7, 17, 23, 1, 35, 5, 0, 9, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Breton/Latin/France
- { 20, 2, 33, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 40, 10, 295, 317, 1, 1, 1412, 1412, 1466, 1466, 1486, 1486, 42, 41, 253, 5, 22, 126, 2842, 19, 24, 477, 486, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 12, 9, 4, 54, 54, 20, 20, 13, 13, 6, 6, 7, 17, 23, 3, 46, 5, 7, 9, 8, {66,71,78}, 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria
- { 21, 25, 147, 120, 120, 125, 125, 135, 0, 1, 2, 41, 4, 5, 9, 10, 11, 12, 13, 329, 347, 115, 125, 1499, 1499, 1499, 1499, 1552, 1552, 48, 47, 260, 5, 22, 2, 2888, 8, 0, 494, 494, 5, 5, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 6, 53, 53, 53, 53, 13, 13, 5, 3, 5, 17, 23, 1, 28, 5, 0, 6, 6, {77,77,75}, 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar
- { 22, 2, 20, 0, 0, 136, 136, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 167, 131, 0, 1565, 1565, 1620, 1620, 1640, 1640, 0, 0, 265, 270, 22, 0, 2916, 19, 0, 500, 510, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 7, 11, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 2, 88, 5, 0, 10, 8, {66,89,78}, 2, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus
- { 23, 20, 36, 0, 0, 143, 152, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 259, 10, 22, 1653, 1698, 1744, 1744, 1783, 1783, 0, 0, 287, 5, 22, 129, 3004, 0, 31, 518, 523, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 45, 46, 39, 39, 13, 13, 2, 2, 2, 17, 23, 1, 28, 4, 6, 5, 7, {75,72,82}, 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia
- { 24, 7, 197, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 536, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain
- { 24, 7, 5, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 543, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra
- { 24, 7, 74, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 550, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/France
- { 24, 7, 106, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 556, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy
- { 25, 5, 44, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 390, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 130, 3051, 4, 13, 562, 566, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 1, 12, 4, 6, 4, 2, {67,78,89}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China
- { 25, 5, 97, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 259, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 131, 3063, 4, 13, 562, 568, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 3, 10, 4, 6, 4, 9, {72,75,68}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Hong Kong
- { 25, 5, 126, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 259, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 134, 3073, 4, 13, 562, 577, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 4, 12, 4, 6, 4, 9, {77,79,80}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau
- { 25, 5, 190, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 45, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 6, 3085, 4, 13, 562, 586, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 1, 14, 4, 6, 4, 3, {83,71,68}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore
- { 25, 6, 97, 168, 168, 178, 178, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 398, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 312, 5, 22, 131, 3063, 4, 13, 589, 593, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 3, 10, 4, 6, 4, 9, {72,75,68}, 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Hong Kong
- { 25, 6, 126, 168, 168, 178, 178, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 398, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 312, 5, 22, 134, 3099, 4, 13, 589, 602, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 4, 12, 4, 6, 4, 9, {77,79,80}, 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
- { 25, 6, 208, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 406, 390, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 0, 5, 22, 6, 3111, 4, 13, 589, 611, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 12, 4, 6, 4, 2, {84,87,68}, 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
- { 26, 7, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Corsican/Latin/France
- { 27, 7, 54, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 439, 54, 0, 1982, 1982, 2039, 2039, 2066, 2079, 0, 0, 315, 5, 22, 138, 3123, 19, 0, 613, 621, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 12, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 3, 59, 5, 0, 8, 8, {72,82,75}, 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
- { 27, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 452, 54, 0, 1982, 1982, 2039, 2039, 2079, 2079, 0, 0, 315, 5, 22, 141, 3182, 19, 0, 613, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 12, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 2, 84, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Croatian/Latin/Bosnia And Herzegowina
- { 28, 7, 57, 0, 0, 183, 183, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 46, 12, 461, 166, 1, 1, 2092, 2092, 2140, 2140, 2160, 2160, 60, 57, 322, 5, 22, 143, 3266, 19, 0, 648, 655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 9, 4, 48, 48, 20, 20, 13, 13, 4, 4, 5, 17, 23, 2, 67, 5, 0, 7, 5, {67,90,75}, 2, 0, 1, 6, 7 }, // Czech/Latin/Czech Republic
- { 29, 7, 58, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 478, 501, 166, 166, 2173, 2173, 2223, 2250, 2284, 2284, 0, 0, 0, 5, 22, 145, 3333, 19, 0, 660, 665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 50, 50, 27, 34, 13, 13, 2, 2, 5, 17, 23, 3, 41, 5, 0, 5, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Danish/Latin/Denmark
- { 29, 7, 86, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 478, 501, 166, 166, 2173, 2173, 2223, 2250, 2284, 2284, 0, 0, 0, 5, 22, 145, 3333, 19, 0, 660, 672, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 50, 50, 27, 34, 13, 13, 2, 2, 5, 17, 23, 3, 41, 5, 0, 5, 8, {68,75,75}, 2, 0, 1, 6, 7 }, // Danish/Latin/Greenland
- { 30, 7, 151, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 14, 3374, 8, 37, 680, 680, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 7, 10, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands
- { 30, 7, 12, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 148, 3392, 8, 37, 680, 690, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 54, 5, 7, 10, 5, {65,87,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba
- { 30, 7, 21, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 46, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 14, 3374, 8, 37, 680, 695, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 7, 10, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium
- { 30, 7, 152, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 152, 3446, 8, 37, 680, 701, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 96, 5, 7, 10, 7, {65,78,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Cura Sao
- { 30, 7, 202, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 6, 3542, 8, 37, 680, 708, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 57, 5, 7, 10, 8, {83,82,68}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname
- { 30, 7, 255, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 6, 3599, 8, 37, 680, 716, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 60, 5, 7, 10, 19, {85,83,68}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire
- { 30, 7, 256, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 152, 3446, 8, 37, 680, 735, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 96, 5, 7, 10, 12, {65,78,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Sint Maarten
- { 31, 7, 225, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 747, 763, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 16, 13, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States
- { 31, 3, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Deseret/United States
- { 31, 7, 4, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 776, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 14, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/American Samoa
- { 31, 7, 7, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 790, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 8, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Anguilla
- { 31, 7, 9, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 798, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 17, {88,67,68}, 2, 1, 7, 6, 7 }, // English/Latin/Antigua And Barbuda
- { 31, 7, 13, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 2388, 2388, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 815, 815, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 24, 24, 2, 2, 5, 17, 23, 1, 58, 4, 6, 18, 9, {65,85,68}, 2, 1, 7, 6, 7 }, // English/Latin/Australia
- { 31, 7, 14, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 8, 0, 756, 833, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Austria
- { 31, 7, 16, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3840, 4, 13, 756, 840, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {66,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Bahamas
- { 31, 7, 19, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3892, 4, 13, 756, 847, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 6, 7, 8, {66,66,68}, 2, 1, 1, 6, 7 }, // English/Latin/Barbados
- { 31, 7, 21, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 0, 756, 855, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Belgium
- { 31, 7, 22, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3947, 4, 13, 756, 862, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 6, 7, 6, {66,90,68}, 2, 1, 7, 6, 7 }, // English/Latin/Belize
- { 31, 7, 24, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3993, 4, 13, 756, 868, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {66,77,68}, 2, 1, 1, 6, 7 }, // English/Latin/Bermuda
- { 31, 7, 28, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 136, 4045, 4, 13, 756, 875, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 8, {66,87,80}, 2, 1, 7, 6, 7 }, // English/Latin/Botswana
- { 31, 7, 31, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 883, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 30, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/British Indian Ocean Territory
- { 31, 7, 35, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 0, 0, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 159, 4094, 4, 13, 756, 913, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 52, 4, 6, 7, 7, {66,73,70}, 0, 0, 1, 6, 7 }, // English/Latin/Burundi
- { 31, 7, 37, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 32, 4146, 4, 13, 756, 920, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 82, 4, 6, 7, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // English/Latin/Cameroon
- { 31, 7, 38, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 27, 70, 10, 22, 0, 0, 2412, 2412, 83, 83, 64, 61, 0, 5, 22, 6, 4228, 4, 13, 928, 944, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 12, 7, 56, 56, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 52, 4, 6, 16, 6, {67,65,68}, 2, 0, 7, 6, 7 }, // English/Latin/Canada
- { 31, 7, 40, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4280, 4, 13, 756, 950, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 14, {75,89,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cayman Islands
- { 31, 7, 45, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 964, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 16, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Christmas Island
- { 31, 7, 46, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 980, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 23, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cocos Islands
- { 31, 7, 51, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1003, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 12, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cook Islands
- { 31, 7, 56, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 4, 13, 756, 1015, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 4, 6, 7, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Cyprus
- { 31, 7, 58, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 166, 166, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 145, 4411, 19, 0, 756, 1021, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 43, 5, 0, 7, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // English/Latin/Denmark
- { 31, 7, 60, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1028, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 8, {88,67,68}, 2, 1, 7, 6, 7 }, // English/Latin/Dominica
- { 31, 7, 67, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 39, 4454, 4, 13, 756, 1036, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 49, 4, 6, 7, 7, {69,82,78}, 2, 1, 1, 6, 7 }, // English/Latin/Eritrea
- { 31, 7, 70, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4503, 4, 13, 756, 1043, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 73, 4, 6, 7, 16, {70,75,80}, 2, 1, 1, 6, 7 }, // English/Latin/Falkland Islands
- { 31, 7, 72, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4576, 4, 13, 756, 1059, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 6, 7, 4, {70,74,68}, 2, 1, 1, 6, 7 }, // English/Latin/Fiji
- { 31, 7, 73, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 176, 167, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 0, 756, 1063, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Finland
- { 31, 7, 75, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 13, 756, 1070, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 6, 7, 8, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Guernsey
- { 31, 7, 80, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 162, 4653, 4, 13, 756, 1078, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 6, {71,77,68}, 2, 1, 1, 6, 7 }, // English/Latin/Gambia
- { 31, 7, 82, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 0, 756, 1084, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Germany
- { 31, 7, 83, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 163, 4702, 4, 13, 756, 1091, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 46, 4, 6, 7, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // English/Latin/Ghana
- { 31, 7, 84, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4748, 4, 13, 756, 1096, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 9, {71,73,80}, 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar
- { 31, 7, 87, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1105, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 7, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Grenada
- { 31, 7, 89, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1112, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 4, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Guam
- { 31, 7, 93, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4800, 4, 13, 756, 1116, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 6, 7, 6, {71,89,68}, 2, 0, 1, 6, 7 }, // English/Latin/Guyana
- { 31, 7, 97, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 398, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 131, 4855, 4, 13, 756, 1122, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 55, 4, 6, 7, 19, {72,75,68}, 2, 1, 7, 6, 7 }, // English/Latin/Hong Kong
- { 31, 7, 100, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 119, 4910, 4, 13, 756, 891, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 43, 4, 6, 7, 5, {73,78,82}, 2, 1, 7, 7, 7 }, // English/Latin/India
- { 31, 7, 104, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 0, 0, 56, 56, 83, 83, 64, 61, 0, 5, 22, 14, 3821, 4, 13, 756, 1141, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 56, 56, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 19, 4, 6, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Ireland
- { 31, 7, 105, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 1, 1, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 47, 4953, 4, 13, 756, 1148, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 6, {73,76,83}, 2, 1, 7, 5, 6 }, // English/Latin/Israel
- { 31, 7, 107, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5014, 4, 13, 756, 1154, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {74,77,68}, 2, 1, 7, 6, 7 }, // English/Latin/Jamaica
- { 31, 7, 111, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 5066, 4, 13, 756, 1161, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 52, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // English/Latin/Kenya
- { 31, 7, 112, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1166, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 8, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Kiribati
- { 31, 7, 120, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 5, 5118, 4, 13, 756, 1174, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 60, 4, 6, 7, 7, {90,65,82}, 2, 1, 1, 6, 7 }, // English/Latin/Lesotho
- { 31, 7, 121, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5178, 4, 13, 756, 1181, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {76,82,68}, 2, 1, 1, 6, 7 }, // English/Latin/Liberia
- { 31, 7, 126, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 134, 5230, 4, 13, 756, 1188, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 52, 4, 6, 7, 15, {77,79,80}, 2, 1, 7, 6, 7 }, // English/Latin/Macau
- { 31, 7, 128, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 166, 5282, 4, 13, 756, 1203, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 53, 4, 6, 7, 10, {77,71,65}, 0, 0, 1, 6, 7 }, // English/Latin/Madagascar
- { 31, 7, 129, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 142, 5335, 4, 13, 756, 1213, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 6, 7, 6, {77,87,75}, 2, 1, 1, 6, 7 }, // English/Latin/Malawi
- { 31, 7, 130, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 168, 5387, 4, 13, 756, 1219, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 58, 4, 6, 7, 8, {77,89,82}, 2, 1, 1, 6, 7 }, // English/Latin/Malaysia
- { 31, 7, 133, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 4, 13, 756, 1227, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 4, 6, 7, 5, {69,85,82}, 2, 1, 7, 6, 7 }, // English/Latin/Malta
- { 31, 7, 134, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1232, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 16, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Marshall Islands
- { 31, 7, 137, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 170, 5445, 4, 13, 756, 1248, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 6, 7, 9, {77,85,82}, 2, 0, 1, 6, 7 }, // English/Latin/Mauritius
- { 31, 7, 140, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1257, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 10, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Micronesia
- { 31, 7, 144, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1267, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 10, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Montserrat
- { 31, 7, 148, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5497, 4, 13, 756, 1277, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {78,65,68}, 2, 1, 1, 6, 7 }, // English/Latin/Namibia
- { 31, 7, 149, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1284, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 5, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Nauru
- { 31, 7, 151, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 8, 37, 756, 1289, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 7, 7, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Netherlands
- { 31, 7, 154, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1300, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 11, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/New Zealand
- { 31, 7, 157, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 172, 5549, 4, 13, 756, 1311, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 7, {78,71,78}, 2, 1, 1, 6, 7 }, // English/Latin/Nigeria
- { 31, 7, 158, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1318, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 4, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Niue
- { 31, 7, 159, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1322, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 14, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Norfolk Island
- { 31, 7, 160, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1336, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 24, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Northern Mariana Islands
- { 31, 7, 163, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 170, 5598, 4, 13, 756, 1360, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 6, 7, 8, {80,75,82}, 2, 0, 7, 6, 7 }, // English/Latin/Pakistan
- { 31, 7, 164, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1368, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 5, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Palau
- { 31, 7, 167, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 5650, 4, 13, 756, 1373, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 72, 4, 6, 7, 16, {80,71,75}, 2, 1, 1, 6, 7 }, // English/Latin/Papua New Guinea
- { 31, 7, 170, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 173, 5722, 4, 13, 756, 1389, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 11, {80,72,80}, 2, 1, 7, 6, 7 }, // English/Latin/Philippines
- { 31, 7, 171, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1400, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 16, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn
- { 31, 7, 174, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1416, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Puerto Rico
- { 31, 7, 179, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 174, 5774, 4, 13, 756, 1427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 46, 4, 6, 7, 6, {82,87,70}, 0, 0, 1, 6, 7 }, // English/Latin/Rwanda
- { 31, 7, 180, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1433, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 16, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Kitts And Nevis
- { 31, 7, 181, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1449, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 8, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Lucia
- { 31, 7, 182, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1457, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 23, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Vincent And The Grenadines
- { 31, 7, 183, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 176, 5820, 4, 13, 756, 785, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 39, 4, 6, 7, 5, {87,83,84}, 2, 1, 7, 6, 7 }, // English/Latin/Samoa
- { 31, 7, 188, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 179, 5859, 4, 13, 756, 1480, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 58, 4, 6, 7, 10, {83,67,82}, 2, 1, 1, 6, 7 }, // English/Latin/Seychelles
- { 31, 7, 189, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 7, 5917, 4, 13, 756, 1490, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 67, 4, 6, 7, 12, {83,76,76}, 0, 0, 1, 6, 7 }, // English/Latin/Sierra Leone
- { 31, 7, 190, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5984, 4, 13, 756, 1502, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 6, 7, 9, {83,71,68}, 2, 1, 7, 6, 7 }, // English/Latin/Singapore
- { 31, 7, 192, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 6, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 24, 756, 1511, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Slovenia
- { 31, 7, 193, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 6039, 4, 13, 756, 1519, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 73, 4, 6, 7, 15, {83,66,68}, 2, 1, 1, 6, 7 }, // English/Latin/Solomon Islands
- { 31, 7, 195, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 545, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 5, 5118, 4, 13, 756, 1534, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 60, 4, 6, 7, 12, {90,65,82}, 2, 1, 7, 6, 7 }, // English/Latin/South Africa
- { 31, 7, 199, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6112, 4, 13, 756, 1546, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 9, {83,72,80}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Helena
- { 31, 7, 201, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 6164, 4, 13, 756, 1555, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 49, 4, 6, 7, 5, {83,68,71}, 2, 1, 6, 5, 6 }, // English/Latin/Sudan
- { 31, 7, 204, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 181, 6213, 4, 13, 756, 1560, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 8, {83,90,76}, 2, 1, 1, 6, 7 }, // English/Latin/Swaziland
- { 31, 7, 205, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 47, 10, 11, 12, 13, 0, 70, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 145, 6265, 19, 0, 756, 1568, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 46, 5, 0, 7, 6, {83,69,75}, 2, 0, 1, 6, 7 }, // English/Latin/Sweden
- { 31, 7, 206, 0, 0, 208, 208, 6, 0, 13, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 6311, 8, 44, 756, 1574, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 40, 5, 5, 7, 11, {67,72,70}, 2, 0, 1, 6, 7 }, // English/Latin/Switzerland
- { 31, 7, 210, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 182, 6351, 4, 13, 756, 1585, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 61, 4, 6, 7, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // English/Latin/Tanzania
- { 31, 7, 213, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1593, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 7, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Tokelau
- { 31, 7, 214, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 185, 6412, 4, 13, 756, 1600, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 48, 4, 6, 7, 5, {84,79,80}, 2, 1, 1, 6, 7 }, // English/Latin/Tonga
- { 31, 7, 215, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 6460, 4, 13, 756, 1605, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 79, 4, 6, 7, 17, {84,84,68}, 2, 1, 7, 6, 7 }, // English/Latin/Trinidad And Tobago
- { 31, 7, 219, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1622, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 22, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Turks And Caicos Islands
- { 31, 7, 220, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1644, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 6, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu
- { 31, 7, 221, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 187, 6539, 4, 13, 756, 1650, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 55, 4, 6, 7, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // English/Latin/Uganda
- { 31, 7, 223, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 190, 6594, 4, 13, 756, 1656, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 54, 4, 6, 7, 20, {65,69,68}, 2, 1, 6, 5, 6 }, // English/Latin/United Arab Emirates
- { 31, 7, 224, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6648, 4, 13, 1676, 1691, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 6, 15, 14, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/United Kingdom
- { 31, 7, 226, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1705, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 21, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States Minor Outlying Islands
- { 31, 7, 229, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 193, 6694, 4, 13, 756, 1726, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 43, 4, 6, 7, 7, {86,85,86}, 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu
- { 31, 7, 233, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1733, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 22, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/British Virgin Islands
- { 31, 7, 234, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1755, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 19, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States Virgin Islands
- { 31, 7, 239, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 6737, 4, 13, 756, 1774, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 6, {90,77,87}, 2, 1, 1, 6, 7 }, // English/Latin/Zambia
- { 31, 7, 240, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 398, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1780, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe
- { 31, 7, 249, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1788, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 12, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Diego Garcia
- { 31, 7, 251, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 13, 756, 1800, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 6, 7, 11, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Isle Of Man
- { 31, 7, 252, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 13, 756, 1811, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 6, 7, 6, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Jersey
- { 31, 7, 254, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6786, 4, 13, 756, 1817, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 67, 4, 6, 7, 11, {83,83,80}, 2, 1, 1, 6, 7 }, // English/Latin/South Sudan
- { 31, 7, 256, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 152, 6853, 4, 13, 756, 1828, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 94, 4, 6, 7, 12, {65,78,71}, 2, 1, 1, 6, 7 }, // English/Latin/Sint Maarten
- { 31, 7, 260, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 0, 4, 13, 756, 1840, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 4, 6, 7, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // English/Latin/World
- { 31, 7, 261, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 0, 19, 0, 756, 1845, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 0, 7, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // English/Latin/Europe
- { 32, 7, 260, 0, 0, 217, 217, 6, 1, 14, 2, 3, 38, 5, 9, 10, 11, 12, 13, 555, 72, 185, 0, 2446, 2446, 2496, 2496, 2516, 2516, 70, 67, 327, 5, 22, 0, 0, 8, 0, 1851, 1860, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 25, 5, 50, 50, 20, 20, 13, 13, 3, 3, 6, 17, 23, 0, 0, 5, 0, 9, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Esperanto/Latin/World
- { 33, 7, 68, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 46, 12, 420, 166, 0, 0, 2529, 2529, 2591, 2591, 2591, 2591, 0, 0, 333, 5, 22, 14, 6947, 19, 24, 1865, 1870, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 13, 13, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 5, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia
- { 34, 7, 71, 0, 0, 190, 190, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 12, 13, 420, 166, 0, 0, 2604, 2604, 2677, 2704, 2738, 2738, 0, 0, 339, 5, 22, 145, 6966, 19, 24, 1875, 1883, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 2, 42, 5, 7, 8, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Faroese/Latin/Faroe Islands
- { 34, 7, 58, 0, 0, 190, 190, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 12, 13, 420, 166, 0, 0, 2604, 2604, 2677, 2704, 2738, 2738, 0, 0, 339, 5, 22, 145, 6966, 19, 24, 1875, 665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 3, 42, 5, 7, 8, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Faroese/Latin/Denmark
- { 36, 7, 73, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 9, 11, 11, 13, 13, 461, 581, 176, 167, 2751, 2817, 2897, 2897, 2917, 2917, 73, 70, 342, 347, 364, 14, 7008, 19, 0, 1890, 1895, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 9, 4, 66, 80, 20, 20, 13, 13, 3, 3, 5, 17, 23, 1, 19, 5, 0, 5, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland
- { 37, 7, 74, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 1908, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/France
- { 37, 7, 3, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 195, 7027, 19, 24, 1900, 1914, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {68,90,68}, 2, 1, 6, 5, 6 }, // French/Latin/Algeria
- { 37, 7, 21, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 46, 210, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 1921, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 7, 23, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Belgium
- { 37, 7, 23, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 1929, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Benin
- { 37, 7, 34, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 1934, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Burkina Faso
- { 37, 7, 35, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 159, 7135, 19, 24, 1900, 913, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 52, 5, 7, 8, 7, {66,73,70}, 0, 0, 1, 6, 7 }, // French/Latin/Burundi
- { 37, 7, 37, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 76, 73, 387, 213, 230, 32, 7187, 19, 24, 1900, 1946, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 5, 4, 6, 17, 23, 4, 55, 5, 7, 8, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Cameroon
- { 37, 7, 38, 0, 0, 234, 234, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 11, 10, 97, 70, 233, 233, 2930, 2930, 2981, 2981, 3015, 3015, 64, 61, 387, 213, 230, 6, 7242, 19, 24, 1954, 944, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 24, 9, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 1, 53, 5, 7, 17, 6, {67,65,68}, 2, 0, 7, 6, 7 }, // French/Latin/Canada
- { 37, 7, 41, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 1971, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 25, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Central African Republic
- { 37, 7, 42, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 1996, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Chad
- { 37, 7, 48, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7295, 19, 24, 1900, 2001, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {75,77,70}, 0, 0, 1, 6, 7 }, // French/Latin/Comoros
- { 37, 7, 49, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7345, 19, 24, 1900, 2008, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 52, 5, 7, 8, 14, {67,68,70}, 2, 1, 1, 6, 7 }, // French/Latin/Congo Kinshasa
- { 37, 7, 50, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 2022, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 17, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Congo Brazzaville
- { 37, 7, 53, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2039, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 13, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Ivory Coast
- { 37, 7, 59, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 36, 7397, 19, 24, 1900, 2052, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 56, 5, 7, 8, 8, {68,74,70}, 0, 0, 6, 6, 7 }, // French/Latin/Djibouti
- { 37, 7, 66, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 2060, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 18, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Equatorial Guinea
- { 37, 7, 76, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2078, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 16, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/French Guiana
- { 37, 7, 77, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 19, 24, 1900, 2094, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 7, 8, 19, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/French Polynesia
- { 37, 7, 79, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 2113, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Gabon
- { 37, 7, 88, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2118, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe
- { 37, 7, 91, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 201, 7487, 19, 24, 1900, 2060, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 47, 5, 7, 8, 6, {71,78,70}, 0, 0, 1, 6, 7 }, // French/Latin/Guinea
- { 37, 7, 94, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 163, 7534, 19, 24, 1900, 2128, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 56, 5, 7, 8, 5, {72,84,71}, 2, 1, 1, 6, 7 }, // French/Latin/Haiti
- { 37, 7, 125, 0, 0, 234, 234, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2133, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg
- { 37, 7, 128, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 166, 7590, 19, 24, 1900, 1203, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 53, 5, 7, 8, 10, {77,71,65}, 0, 0, 1, 6, 7 }, // French/Latin/Madagascar
- { 37, 7, 132, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2143, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Mali
- { 37, 7, 135, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2147, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Martinique
- { 37, 7, 136, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 203, 7643, 19, 24, 1900, 2157, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 65, 5, 7, 8, 10, {77,82,85}, 2, 1, 1, 6, 7 }, // French/Latin/Mauritania
- { 37, 7, 137, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 170, 7708, 19, 24, 1900, 2167, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 62, 5, 7, 8, 7, {77,85,82}, 2, 0, 1, 6, 7 }, // French/Latin/Mauritius
- { 37, 7, 138, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2174, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Mayotte
- { 37, 7, 142, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2181, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Monaco
- { 37, 7, 145, 0, 0, 234, 234, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 64, 61, 387, 213, 230, 205, 7770, 19, 24, 1900, 2187, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 3, 53, 5, 7, 8, 5, {77,65,68}, 2, 1, 1, 6, 7 }, // French/Latin/Morocco
- { 37, 7, 153, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 19, 24, 1900, 2192, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 7, 8, 18, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/New Caledonia
- { 37, 7, 156, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 1311, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Niger
- { 37, 7, 176, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2210, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Reunion
- { 37, 7, 179, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 174, 7823, 19, 24, 1900, 1427, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 49, 5, 7, 8, 6, {82,87,70}, 0, 0, 1, 6, 7 }, // French/Latin/Rwanda
- { 37, 7, 187, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2220, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 7, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Senegal
- { 37, 7, 188, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 179, 7872, 19, 24, 1900, 1480, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 70, 5, 7, 8, 10, {83,67,82}, 2, 1, 1, 6, 7 }, // French/Latin/Seychelles
- { 37, 7, 200, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2227, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 24, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Pierre And Miquelon
- { 37, 7, 206, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 17, 18, 0, 166, 257, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 208, 7942, 19, 24, 2251, 2266, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 14, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 44, 5, 7, 15, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // French/Latin/Switzerland
- { 37, 7, 207, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 211, 7986, 19, 24, 1900, 2272, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 5, {83,89,80}, 0, 0, 6, 5, 6 }, // French/Latin/Syria
- { 37, 7, 212, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2277, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Togo
- { 37, 7, 216, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 213, 8036, 19, 24, 1900, 2281, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {84,78,68}, 3, 0, 1, 6, 7 }, // French/Latin/Tunisia
- { 37, 7, 229, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 193, 8086, 19, 24, 1900, 1726, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {86,85,86}, 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu
- { 37, 7, 235, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 19, 24, 1900, 2288, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 7, 8, 16, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/Wallis And Futuna Islands
- { 37, 7, 244, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2304, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 16, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy
- { 37, 7, 245, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2320, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 12, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin
- { 38, 7, 151, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 347, 0, 0, 3028, 3028, 3081, 3081, 83, 83, 0, 0, 0, 5, 22, 14, 3374, 8, 37, 2332, 2337, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 7, 5, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands
- { 39, 7, 224, 0, 0, 242, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 589, 45, 0, 0, 3101, 3101, 3169, 3169, 3196, 3196, 5, 77, 393, 5, 22, 117, 8136, 4, 13, 2345, 2353, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 10, 10, 5, 68, 68, 27, 27, 13, 13, 1, 1, 6, 17, 23, 1, 85, 4, 6, 8, 22, {71,66,80}, 2, 1, 1, 6, 7 }, // Gaelic/Latin/United Kingdom
- { 40, 7, 197, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 0, 0, 3209, 3257, 3305, 3339, 3373, 3386, 64, 61, 0, 5, 22, 14, 3032, 19, 0, 2375, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 48, 48, 34, 34, 13, 20, 4, 4, 5, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Galician/Latin/Spain
- { 41, 15, 81, 0, 0, 259, 259, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 15, 16, 637, 166, 0, 0, 3406, 3406, 3467, 3467, 3494, 3494, 0, 0, 399, 404, 22, 215, 8221, 19, 0, 2387, 2394, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 61, 61, 27, 27, 13, 13, 2, 2, 5, 37, 23, 1, 42, 5, 0, 7, 10, {71,69,76}, 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia
- { 42, 7, 82, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2411, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Germany
- { 42, 7, 14, 0, 0, 267, 267, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2422, 2422, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 24, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Austria
- { 42, 7, 21, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2446, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Belgium
- { 42, 7, 106, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2453, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Italy
- { 42, 7, 123, 0, 0, 267, 267, 6, 0, 13, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 208, 8281, 19, 0, 2404, 2460, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 3, 57, 5, 0, 7, 13, {67,72,70}, 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein
- { 42, 7, 125, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2473, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg
- { 42, 7, 206, 0, 0, 267, 267, 6, 0, 13, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 208, 8281, 19, 0, 2482, 2482, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 3, 57, 5, 0, 21, 7, {67,72,70}, 2, 0, 1, 6, 7 }, // German/Latin/Switzerland
- { 43, 16, 85, 0, 0, 276, 276, 6, 1, 0, 2, 3, 4, 5, 6, 15, 16, 10, 11, 0, 259, 10, 22, 3626, 3626, 3680, 3680, 3707, 3707, 81, 78, 0, 5, 22, 14, 8338, 19, 0, 2503, 2511, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Greek/Greek/Greece
- { 43, 16, 56, 0, 0, 276, 276, 6, 1, 0, 2, 3, 4, 5, 6, 15, 16, 10, 11, 0, 259, 10, 22, 3626, 3626, 3680, 3680, 3707, 3707, 81, 78, 0, 5, 22, 14, 8338, 19, 0, 2503, 2517, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus
- { 44, 7, 86, 0, 0, 285, 285, 6, 1, 0, 2, 3, 38, 5, 47, 16, 15, 18, 17, 80, 70, 166, 166, 3720, 3720, 3817, 3817, 3844, 3844, 0, 0, 0, 5, 22, 145, 8356, 4, 49, 2523, 2534, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 97, 97, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 61, 4, 5, 11, 16, {68,75,75}, 2, 0, 1, 6, 7 }, // Greenlandic/Latin/Greenland
- { 45, 7, 168, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 216, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {80,89,71}, 0, 0, 7, 6, 7 }, // Guarani/Latin/Paraguay
- { 46, 17, 100, 0, 0, 296, 296, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 271, 284, 3857, 3857, 3909, 3909, 3940, 3940, 0, 0, 446, 450, 22, 119, 8417, 4, 13, 2550, 2557, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 8, 52, 52, 31, 31, 18, 18, 2, 2, 4, 19, 23, 1, 45, 4, 6, 7, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India
- { 47, 7, 157, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 0, 0, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 172, 8462, 8, 0, 2561, 2566, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 1, 53, 5, 0, 5, 8, {78,71,78}, 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria
- { 47, 1, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria
- { 47, 7, 83, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 10, 22, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 163, 0, 8, 0, 2561, 2574, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 3, 0, 5, 0, 5, 4, {71,72,83}, 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana
- { 47, 7, 156, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 0, 0, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 33, 8515, 8, 0, 2561, 2578, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 3, 29, 5, 0, 5, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger
- { 48, 18, 105, 0, 0, 313, 313, 6, 0, 1, 2, 3, 33, 35, 9, 11, 11, 13, 13, 673, 581, 1, 1, 4049, 4049, 4113, 4113, 4158, 4158, 91, 87, 469, 5, 22, 47, 8544, 19, 0, 2583, 2588, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 8, 9, 4, 64, 64, 45, 45, 20, 20, 6, 5, 4, 17, 23, 1, 53, 5, 0, 5, 5, {73,76,83}, 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel
- { 49, 13, 100, 0, 0, 319, 328, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 4178, 4178, 4230, 4230, 4261, 4261, 68, 65, 473, 5, 22, 119, 8597, 4, 0, 2593, 2599, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 52, 52, 31, 31, 18, 18, 2, 2, 4, 17, 23, 1, 41, 4, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Hindi/Devanagari/India
- { 50, 7, 98, 0, 0, 336, 336, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 16, 15, 691, 710, 1, 1, 4279, 4279, 4330, 4330, 4348, 4348, 97, 92, 477, 5, 22, 217, 8638, 19, 0, 2603, 2609, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 9, 4, 51, 51, 18, 18, 16, 16, 3, 3, 4, 17, 23, 2, 45, 5, 0, 6, 12, {72,85,70}, 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary
- { 51, 7, 99, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 581, 0, 0, 4364, 4364, 4444, 4444, 4478, 4478, 100, 95, 481, 5, 22, 219, 8683, 19, 0, 2621, 2629, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 80, 80, 34, 34, 13, 13, 4, 4, 4, 17, 23, 3, 48, 5, 0, 8, 6, {73,83,75}, 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland
- { 52, 7, 101, 0, 0, 344, 354, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 166, 166, 4491, 4491, 4533, 4533, 4560, 4560, 0, 0, 0, 5, 22, 222, 8731, 4, 0, 2635, 2635, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 42, 42, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 38, 4, 0, 9, 9, {73,68,82}, 2, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia
- { 53, 7, 260, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 723, 511, 0, 0, 4573, 4573, 4629, 4629, 4656, 4656, 0, 0, 0, 5, 22, 0, 0, 8, 37, 2644, 2655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 7, 11, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Interlingua/Latin/World
- { 55, 44, 38, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 224, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7 }, // Inuktitut/Canadian Aboriginal/Canada
- { 55, 7, 38, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 224, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada
- { 57, 7, 104, 0, 0, 363, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 4669, 4669, 4743, 4743, 4779, 4779, 104, 99, 485, 5, 22, 14, 8769, 4, 13, 2660, 2667, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 30, 4, 6, 7, 4, {69,85,82}, 2, 1, 1, 6, 7 }, // Irish/Latin/Ireland
- { 57, 7, 224, 0, 0, 363, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 4669, 4669, 4743, 4743, 4779, 4779, 104, 99, 485, 5, 22, 117, 8799, 4, 13, 2660, 2671, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 94, 4, 6, 7, 19, {71,66,80}, 2, 1, 1, 6, 7 }, // Irish/Latin/United Kingdom
- { 58, 7, 106, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 19, 0, 2690, 2698, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/Italy
- { 58, 7, 184, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 19, 0, 2690, 2704, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/San Marino
- { 58, 7, 206, 0, 0, 252, 252, 6, 0, 13, 2, 3, 4, 5, 9, 15, 16, 17, 18, 0, 166, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 0, 8893, 19, 0, 2690, 2714, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 52, 5, 0, 8, 8, {67,72,70}, 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland
- { 58, 7, 230, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 19, 0, 2690, 2722, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 18, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/Vatican City State
- { 59, 19, 108, 168, 168, 168, 168, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 545, 292, 1, 4888, 4888, 4915, 4915, 4915, 4915, 108, 103, 491, 494, 22, 227, 8945, 4, 13, 2740, 2740, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 10, 10, 4, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 10, 4, 6, 3, 2, {74,80,89}, 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan
- { 60, 7, 101, 0, 0, 374, 384, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 511, 0, 0, 4928, 4928, 4968, 4968, 4996, 4996, 110, 105, 511, 5, 22, 222, 8731, 8, 0, 2743, 2747, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 40, 40, 28, 28, 13, 13, 4, 5, 4, 17, 23, 2, 38, 5, 0, 4, 9, {73,68,82}, 2, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia
- { 61, 21, 100, 0, 0, 393, 405, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 259, 271, 284, 5009, 5009, 5062, 5062, 5094, 5094, 114, 110, 515, 523, 22, 119, 8955, 4, 13, 2756, 2761, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 8, 53, 53, 32, 32, 19, 19, 9, 7, 8, 35, 23, 1, 48, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Kannada/Kannada/India
- { 62, 1, 100, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 27, 521, 10, 22, 5113, 5113, 5164, 5164, 5213, 5213, 0, 0, 0, 5, 22, 119, 9003, 8, 0, 2765, 2770, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 12, 7, 51, 51, 49, 49, 13, 13, 2, 2, 4, 17, 23, 1, 16, 5, 0, 5, 9, {73,78,82}, 2, 1, 7, 7, 7 }, // Kashmiri/Arabic/India
- { 63, 2, 110, 0, 0, 0, 416, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 749, 166, 0, 0, 5226, 5226, 5281, 5281, 5301, 5301, 0, 0, 253, 558, 575, 228, 9019, 19, 0, 2779, 2789, 6, 6, 6, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 10, 5, 55, 55, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 57, 5, 0, 10, 9, {75,90,84}, 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan
- { 64, 7, 179, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 12, 13, 53, 70, 0, 0, 5314, 5314, 5397, 5397, 83, 83, 0, 0, 0, 5, 22, 174, 0, 8, 0, 2798, 2809, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 83, 83, 34, 34, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 11, 8, {82,87,70}, 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda
- { 65, 2, 116, 0, 0, 426, 426, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 771, 259, 0, 0, 5431, 5431, 5487, 5487, 5524, 5524, 123, 117, 253, 598, 22, 229, 9076, 19, 0, 2817, 2825, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 10, 5, 56, 56, 37, 37, 13, 13, 5, 14, 4, 18, 23, 3, 51, 5, 0, 8, 10, {75,71,83}, 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan
- { 66, 22, 114, 0, 0, 436, 436, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 794, 810, 302, 315, 5537, 5537, 5564, 5564, 5564, 5564, 128, 131, 616, 5, 22, 232, 9127, 4, 13, 2835, 2838, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 18, 4, 6, 3, 4, {75,82,87}, 0, 0, 7, 6, 7 }, // Korean/Korean/South Korea
- { 66, 22, 113, 0, 0, 436, 436, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 794, 810, 302, 315, 5537, 5537, 5564, 5564, 5564, 5564, 128, 131, 616, 5, 22, 233, 9145, 4, 13, 2835, 2842, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 3, 38, 4, 6, 3, 11, {75,80,87}, 0, 0, 1, 6, 7 }, // Korean/Korean/North Korea
- { 67, 7, 217, 0, 0, 443, 443, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 5577, 5577, 5618, 5618, 5637, 5637, 130, 133, 0, 5, 22, 236, 0, 19, 24, 2853, 2858, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 41, 41, 19, 19, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 7, 5, 7, {84,82,89}, 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey
- { 68, 7, 35, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 11, 11, 13, 13, 97, 398, 0, 0, 5650, 5650, 5738, 5738, 83, 83, 132, 135, 0, 5, 22, 159, 9183, 0, 0, 2865, 2873, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 88, 88, 33, 33, 13, 13, 5, 5, 4, 17, 23, 3, 20, 4, 0, 8, 8, {66,73,70}, 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi
- { 69, 23, 117, 0, 0, 0, 450, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 819, 398, 322, 1, 5771, 5771, 5827, 5827, 5862, 5862, 137, 140, 0, 5, 22, 237, 9203, 4, 44, 2881, 2881, 6, 6, 6, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 24, 4, 56, 56, 35, 35, 16, 16, 8, 8, 4, 17, 23, 1, 20, 4, 5, 3, 3, {76,65,75}, 0, 0, 7, 6, 7 }, // Lao/Lao/Laos
- { 71, 7, 118, 0, 0, 459, 459, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 838, 166, 0, 0, 5878, 5949, 6020, 6070, 6120, 6120, 145, 148, 619, 5, 22, 14, 9223, 19, 0, 2884, 2892, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 10, 5, 71, 71, 50, 50, 13, 13, 14, 11, 5, 17, 23, 1, 22, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia
- { 72, 7, 49, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9245, 19, 0, 2899, 2906, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 30, {67,68,70}, 2, 1, 1, 6, 7 }, // Lingala/Latin/Congo Kinshasa
- { 72, 7, 6, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 238, 9261, 19, 0, 2899, 2936, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 6, {65,79,65}, 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola
- { 72, 7, 41, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9277, 19, 0, 2899, 2942, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 26, {88,65,70}, 0, 0, 1, 6, 7 }, // Lingala/Latin/Central African Republic
- { 72, 7, 50, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9277, 19, 0, 2899, 2968, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // Lingala/Latin/Congo Brazzaville
- { 73, 7, 124, 0, 0, 476, 476, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 40, 10, 864, 70, 0, 0, 6272, 6272, 6360, 6360, 6380, 6380, 167, 165, 624, 5, 22, 14, 9293, 19, 0, 2973, 2981, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 27, 10, 10, 5, 88, 88, 20, 20, 13, 13, 9, 6, 6, 17, 23, 1, 29, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania
- { 74, 2, 127, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 0, 113, 0, 0, 6393, 6393, 6446, 6480, 1486, 1486, 176, 171, 630, 5, 22, 240, 9322, 19, 0, 2988, 2998, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 34, 33, 13, 13, 10, 8, 5, 17, 23, 4, 55, 5, 0, 10, 18, {77,75,68}, 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia
- { 75, 7, 128, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 70, 0, 0, 6513, 6513, 6572, 6572, 6605, 6605, 0, 0, 0, 5, 22, 166, 5291, 4, 0, 3016, 3024, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 59, 59, 33, 33, 13, 13, 2, 2, 4, 17, 23, 2, 6, 4, 0, 8, 12, {77,71,65}, 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar
- { 76, 7, 130, 0, 0, 354, 354, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 168, 9377, 4, 13, 3036, 1219, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 2, 38, 4, 6, 6, 8, {77,89,82}, 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia
- { 76, 1, 130, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 168, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {77,89,82}, 2, 1, 1, 6, 7 }, // Malay/Arabic/Malaysia
- { 76, 7, 32, 0, 0, 354, 354, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 85, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 6, 9415, 4, 13, 3036, 3042, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 30, 4, 6, 6, 6, {66,78,68}, 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei
- { 76, 7, 190, 0, 0, 354, 354, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 6, 9445, 4, 13, 3036, 3048, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 36, 4, 6, 6, 9, {83,71,68}, 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore
- { 77, 24, 100, 0, 0, 484, 497, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 891, 259, 10, 22, 6700, 6776, 6851, 6851, 6891, 6912, 0, 0, 635, 641, 22, 119, 9481, 4, 13, 3057, 3063, 6, 6, 13, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 76, 75, 40, 40, 21, 20, 2, 2, 6, 27, 23, 1, 39, 4, 6, 6, 6, {73,78,82}, 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India
- { 78, 7, 133, 0, 0, 509, 517, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 909, 45, 0, 0, 6932, 6932, 6994, 6994, 7021, 7041, 0, 0, 0, 5, 22, 14, 9520, 4, 0, 3069, 1227, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 62, 62, 27, 27, 20, 19, 2, 2, 4, 17, 23, 1, 26, 4, 0, 5, 5, {69,85,82}, 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta
- { 79, 7, 154, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 511, 10, 22, 7060, 7060, 7106, 7106, 7132, 7132, 0, 0, 0, 5, 22, 6, 9546, 8, 0, 3074, 3079, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 46, 46, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 36, 5, 0, 5, 8, {78,90,68}, 2, 1, 1, 6, 7 }, // Maori/Latin/New Zealand
- { 80, 13, 100, 0, 0, 524, 524, 6, 0, 1, 2, 60, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 7145, 7145, 7197, 7197, 4261, 4261, 188, 182, 473, 5, 22, 119, 9582, 4, 13, 3087, 2599, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 52, 52, 31, 31, 18, 18, 5, 4, 4, 17, 23, 1, 42, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India
- { 82, 2, 143, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 932, 967, 54, 0, 7228, 7270, 7312, 7312, 7312, 7312, 193, 186, 253, 668, 22, 244, 9624, 8, 0, 3092, 3098, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35, 10, 12, 5, 42, 42, 20, 20, 20, 20, 4, 4, 4, 17, 23, 1, 45, 5, 0, 6, 6, {77,78,84}, 2, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia
- { 82, 8, 44, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 245, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,78,89}, 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China
- { 84, 13, 150, 533, 0, 538, 538, 6, 0, 1, 2, 60, 4, 5, 9, 10, 11, 12, 13, 53, 253, 0, 0, 7332, 7332, 7385, 7385, 7417, 7417, 197, 190, 473, 685, 22, 248, 9669, 8, 0, 3104, 3104, 5, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 32, 32, 17, 17, 9, 7, 4, 19, 23, 4, 48, 5, 0, 6, 5, {78,80,82}, 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal
- { 84, 13, 100, 533, 0, 538, 538, 6, 0, 1, 2, 60, 4, 5, 9, 10, 11, 12, 13, 53, 253, 10, 22, 7332, 7332, 7385, 7385, 7417, 7417, 197, 190, 473, 685, 22, 119, 9717, 8, 0, 3104, 2599, 5, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 53, 53, 32, 32, 17, 17, 9, 7, 4, 19, 23, 1, 48, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Nepali/Devanagari/India
- { 85, 7, 161, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 0, 0, 2173, 2173, 2250, 2250, 2284, 2284, 64, 61, 0, 5, 22, 145, 9765, 8, 0, 3110, 3122, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 34, 34, 13, 13, 4, 4, 4, 17, 23, 2, 43, 5, 0, 12, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Norway
- { 85, 7, 203, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 0, 0, 2173, 2173, 2250, 2250, 2284, 2284, 64, 61, 0, 5, 22, 145, 9765, 8, 0, 3110, 3127, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 34, 34, 13, 13, 4, 4, 4, 17, 23, 2, 43, 5, 0, 12, 21, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands
- { 86, 7, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Occitan/Latin/France
- { 87, 26, 100, 0, 0, 545, 553, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 7434, 7434, 7487, 7487, 7519, 7519, 0, 0, 704, 5, 22, 119, 9808, 4, 13, 3148, 3153, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 53, 53, 32, 32, 17, 17, 2, 2, 5, 17, 23, 1, 42, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Oriya/Oriya/India
- { 88, 1, 1, 560, 560, 566, 575, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 977, 390, 55, 1, 7536, 7536, 7536, 7536, 83, 83, 206, 197, 709, 5, 22, 252, 9850, 4, 13, 3157, 3161, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 11, 4, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 1, 24, 4, 6, 4, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan
- { 88, 1, 163, 560, 560, 566, 575, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 977, 390, 10, 22, 7536, 7536, 7536, 7536, 83, 83, 206, 197, 709, 5, 22, 170, 9874, 4, 13, 3157, 3170, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 12, 7, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 2, 51, 4, 6, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Pashto/Arabic/Pakistan
- { 89, 1, 102, 583, 583, 590, 598, 53, 19, 20, 21, 52, 61, 35, 56, 15, 16, 17, 18, 97, 390, 55, 1, 7574, 7574, 7574, 7574, 7622, 7622, 210, 201, 714, 718, 22, 253, 9925, 54, 60, 3177, 3182, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 11, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 44, 23, 4, 36, 6, 8, 5, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran
- { 89, 1, 1, 583, 583, 590, 598, 53, 19, 20, 21, 52, 61, 35, 56, 15, 16, 17, 18, 97, 390, 55, 1, 7574, 7574, 7574, 7574, 7622, 7622, 210, 201, 714, 718, 22, 252, 9961, 8, 60, 3187, 3161, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 11, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 44, 23, 1, 54, 5, 8, 3, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan
- { 90, 7, 172, 0, 0, 161, 161, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 7635, 7635, 7693, 7693, 7726, 7739, 0, 0, 322, 5, 22, 257,10015, 19, 24, 3190, 3196, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 58, 58, 33, 33, 13, 13, 2, 2, 5, 17, 23, 2, 76, 5, 7, 6, 6, {80,76,78}, 2, 1, 1, 6, 7 }, // Polish/Latin/Poland
- { 91, 7, 30, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 0, 0, 7752, 7752, 7830, 7830, 7864, 7864, 0, 0, 0, 5, 22, 5,10091, 8, 0, 3202, 3211, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 10, 5, 78, 78, 34, 34, 13, 13, 2, 2, 5, 17, 23, 2, 53, 5, 0, 9, 6, {66,82,76}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil
- { 91, 7, 6, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 238,10144, 19, 24, 3202, 3217, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 53, 5, 7, 9, 6, {65,79,65}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola
- { 91, 7, 39, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 259,10197, 19, 24, 3202, 3223, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 68, 5, 7, 9, 10, {67,86,69}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Cape Verde
- { 91, 7, 62, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 156,10265, 19, 24, 3202, 3233, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 80, 5, 7, 9, 11, {85,83,68}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/East Timor
- { 91, 7, 66, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 32,10345, 19, 24, 3202, 3244, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 58, 5, 7, 9, 16, {88,65,70}, 0, 0, 1, 6, 7 }, // Portuguese/Latin/Equatorial Guinea
- { 91, 7, 92, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 33,10403, 19, 24, 3202, 3260, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 61, 5, 7, 9, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // Portuguese/Latin/Guinea Bissau
- { 91, 7, 125, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 14, 3032, 19, 24, 3202, 3272, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 19, 5, 7, 9, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg
- { 91, 7, 126, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 10, 22, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 134,10464, 19, 24, 3202, 3282, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 53, 5, 7, 9, 19, {77,79,80}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau
- { 91, 7, 146, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 260,10517, 19, 24, 3202, 3301, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 65, 5, 7, 9, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique
- { 91, 7, 173, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 14, 3032, 19, 24, 3311, 3328, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 19, 5, 7, 17, 8, {69,85,82}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Portugal
- { 91, 7, 185, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 263,10582, 19, 24, 3202, 3336, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 91, 5, 7, 9, 19, {83,84,78}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Sao Tome And Principe
- { 91, 7, 206, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 208,10673, 19, 24, 3202, 3355, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 44, 5, 7, 9, 5, {67,72,70}, 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland
- { 92, 4, 100, 0, 0, 605, 605, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 7925, 7925, 7981, 7981, 8016, 8016, 227, 217, 762, 5, 22, 119,10717, 8, 0, 3360, 3366, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 35, 35, 22, 22, 6, 6, 4, 17, 23, 1, 38, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India
- { 92, 1, 163, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 527, 45, 10, 22, 8038, 8038, 8038, 8038, 83, 83, 0, 0, 0, 5, 22, 77,10755, 8, 0, 3370, 3170, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 10, 12, 7, 36, 36, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan
- { 93, 7, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 265,10761, 8, 0, 3376, 3384, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 28, 5, 0, 8, 4, {80,69,78}, 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru
- { 93, 7, 26, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 267,10789, 8, 0, 3376, 3388, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 24, 5, 0, 8, 7, {66,79,66}, 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia
- { 93, 7, 63, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 6,10813, 8, 0, 3376, 3395, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 36, 5, 0, 8, 7, {85,83,68}, 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador
- { 94, 7, 206, 0, 0, 0, 0, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 997, 347, 0, 0, 8166, 8166, 8221, 8221, 8243, 8243, 0, 0, 0, 5, 22, 208,10849, 19, 0, 3402, 3411, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 55, 55, 22, 22, 13, 13, 2, 2, 4, 17, 23, 3, 45, 5, 0, 9, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland
- { 95, 7, 177, 0, 0, 614, 614, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 8256, 8256, 8303, 8303, 3015, 3015, 64, 61, 766, 5, 22, 269,10894, 19, 24, 3417, 3423, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 33, 33, 13, 13, 4, 4, 4, 17, 23, 3, 56, 5, 7, 6, 7, {82,79,78}, 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania
- { 95, 7, 141, 0, 0, 614, 614, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 8256, 8256, 8336, 8336, 8363, 8363, 64, 61, 766, 5, 22, 7,10950, 19, 24, 3417, 3430, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 27, 27, 15, 15, 4, 4, 4, 17, 23, 1, 68, 5, 7, 6, 17, {77,68,76}, 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova
- { 96, 2, 178, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 121,11018, 19, 0, 3447, 3454, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 88, 5, 0, 7, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia
- { 96, 2, 20, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 0,11106, 19, 0, 3447, 510, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 2, 93, 5, 0, 7, 8, {66,89,78}, 2, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus
- { 96, 2, 110, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 228,11199, 19, 0, 3447, 3460, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 82, 5, 0, 7, 9, {75,90,84}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan
- { 96, 2, 116, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 229,11281, 19, 0, 3447, 3469, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 3, 81, 5, 0, 7, 8, {75,71,83}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan
- { 96, 2, 141, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 7,11362, 19, 0, 3447, 3477, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 78, 5, 0, 7, 7, {77,68,76}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova
- { 96, 2, 222, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 272,11440, 19, 0, 3447, 3484, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 91, 5, 0, 7, 7, {85,65,72}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine
- { 98, 7, 41, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0, 8472, 8472, 8537, 8537, 8564, 8564, 233, 223, 0, 5, 22, 32,11531, 4, 44, 3491, 3496, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 4, 5, 5, 22, {88,65,70}, 0, 0, 1, 6, 7 }, // Sango/Latin/Central African Republic
- { 99, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 119, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {73,78,82}, 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India
- { 100, 2, 243, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8577, 8577, 8628, 8628, 8655, 8655, 235, 225, 770, 5, 22, 273,11549, 19, 24, 3518, 3524, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 51, 51, 27, 27, 13, 13, 9, 8, 7, 17, 23, 3, 57, 5, 7, 6, 6, {82,83,68}, 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia
- { 100, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8668, 8668, 8724, 8724, 2066, 2066, 244, 233, 315, 5, 22, 141,11606, 19, 24, 3530, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 56, 56, 25, 25, 13, 13, 11, 8, 7, 17, 23, 2,173, 5, 7, 6, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Bosnia And Herzegowina
- { 100, 7, 242, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8668, 8668, 8749, 8749, 2066, 2066, 244, 233, 315, 5, 22, 14,11779, 19, 24, 3530, 3536, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 56, 56, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 22, 5, 7, 6, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro
- { 100, 7, 243, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8776, 8776, 8749, 8749, 2066, 2066, 255, 233, 315, 5, 22, 273,11801, 19, 24, 3530, 3545, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 53, 53, 27, 27, 13, 13, 9, 8, 7, 17, 23, 3, 57, 5, 7, 6, 6, {82,83,68}, 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia
- { 100, 2, 27, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8829, 8829, 8883, 8883, 8655, 8655, 264, 225, 770, 5, 22, 276,11858, 19, 24, 3518, 3551, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 54, 54, 25, 25, 13, 13, 11, 8, 7, 17, 23, 2,173, 5, 7, 6, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Bosnia And Herzegowina
- { 100, 2, 242, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8829, 8829, 8628, 8628, 8655, 8655, 264, 225, 770, 5, 22, 14,12031, 19, 24, 3518, 3570, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 54, 54, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 22, 5, 7, 6, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro
- { 100, 2, 257, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8577, 8577, 8628, 8628, 8655, 8655, 235, 225, 770, 5, 22, 14,12031, 19, 24, 3518, 3579, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 51, 51, 27, 27, 13, 13, 9, 8, 7, 17, 23, 1, 22, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo
- { 100, 7, 257, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8776, 8776, 8749, 8749, 2066, 2066, 255, 233, 315, 5, 22, 14,11779, 19, 24, 3530, 3585, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 53, 53, 27, 27, 13, 13, 9, 8, 7, 17, 23, 1, 22, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo
- { 101, 2, 81, 0, 0, 622, 622, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1047, 166, 0, 0, 8908, 8968, 9028, 9055, 9082, 9082, 275, 241, 0, 5, 22, 215,12053, 8, 0, 3591, 3595, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 16, 5, 0, 4, 11, {71,69,76}, 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia
- { 101, 2, 178, 0, 0, 622, 622, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1047, 166, 0, 0, 8908, 8968, 9028, 9055, 9082, 9082, 275, 241, 0, 5, 22, 121,12069, 8, 0, 3591, 3606, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 16, 5, 0, 4, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia
- { 102, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/South Africa
- { 103, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Tswana/Latin/South Africa
- { 104, 7, 240, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 53, 70, 0, 0, 9095, 9095, 9149, 9149, 9176, 9176, 0, 0, 0, 5, 22, 156,12085, 4, 13, 3612, 1780, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 15, 4, 6, 8, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe
- { 105, 1, 163, 0, 0, 631, 639, 53, 19, 20, 21, 23, 24, 26, 28, 10, 11, 12, 13, 53, 70, 10, 22, 9189, 9189, 9189, 9189, 9223, 9223, 290, 256, 777, 783, 22, 170,12100, 19, 0, 3620, 3624, 6, 6, 8, 7, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 34, 34, 34, 34, 30, 30, 11, 11, 6, 61, 23, 2, 42, 5, 0, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan
- { 106, 32, 198, 0, 0, 646, 655, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 166, 166, 9253, 9253, 9314, 9314, 9352, 9352, 301, 267, 844, 849, 22, 278,12142, 4, 13, 3631, 3636, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 38, 38, 18, 18, 5, 4, 5, 42, 23, 3, 57, 4, 6, 5, 11, {76,75,82}, 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/Sri Lanka
- { 107, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Swati/Latin/South Africa
- { 108, 7, 191, 0, 0, 183, 663, 6, 1, 14, 2, 3, 4, 5, 6, 40, 10, 46, 12, 461, 1070, 1, 1, 9370, 9370, 9421, 9421, 9441, 9441, 0, 0, 322, 5, 22, 14,12199, 19, 24, 3647, 3657, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 51, 51, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 25, 5, 7, 10, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia
- { 109, 7, 192, 0, 0, 670, 670, 6, 1, 0, 2, 3, 38, 5, 6, 40, 10, 46, 12, 1020, 440, 0, 0, 9454, 9454, 9505, 9505, 9539, 9539, 60, 271, 50, 5, 22, 14,12224, 19, 24, 3666, 3677, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 10, 5, 51, 51, 34, 34, 13, 13, 4, 4, 4, 17, 23, 1, 27, 5, 7, 11, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia
- { 110, 7, 194, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 92,12251, 4, 13, 3686, 3694, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 1, 20, 4, 6, 8, 10, {83,79,83}, 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia
- { 110, 7, 59, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 36,12271, 4, 13, 3686, 3704, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 49, 4, 6, 8, 7, {68,74,70}, 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti
- { 110, 7, 69, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 0,12320, 4, 13, 3686, 3711, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 2, 51, 4, 6, 8, 8, {69,84,66}, 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia
- { 110, 7, 111, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 0, 0, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 2,12371, 4, 13, 3686, 1161, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 51, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya
- { 111, 7, 197, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 19, 0, 3719, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 17, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain
- { 111, 7, 10, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,12422, 8, 37, 3719, 3736, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 50, 5, 7, 7, 9, {65,82,83}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Argentina
- { 111, 7, 22, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 6,12472, 4, 0, 3719, 3745, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 51, 4, 0, 7, 6, {66,90,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Belize
- { 111, 7, 26, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 267,12523, 4, 0, 3719, 3388, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 34, 4, 0, 7, 7, {66,79,66}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia
- { 111, 7, 30, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 5,12557, 4, 0, 3719, 3211, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 2, 51, 4, 0, 7, 6, {66,82,76}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil
- { 111, 7, 43, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 347, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12608, 4, 0, 3719, 3751, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 44, 4, 0, 7, 5, {67,76,80}, 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile
- { 111, 7, 47, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 10, 22, 9643, 9643, 9695, 9695, 4656, 3015, 53, 50, 0, 5, 22, 6,12652, 4, 0, 3719, 3756, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 53, 4, 0, 7, 8, {67,79,80}, 2, 0, 7, 6, 7 }, // Spanish/Latin/Colombia
- { 111, 7, 52, 0, 0, 687, 687, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 281,12705, 4, 0, 3719, 3764, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 66, 4, 0, 7, 10, {67,82,67}, 2, 0, 1, 6, 7 }, // Spanish/Latin/Costa Rica
- { 111, 7, 55, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 6,12771, 4, 0, 3719, 3774, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 41, 4, 0, 7, 4, {67,85,80}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba
- { 111, 7, 61, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 282,12812, 4, 13, 3719, 3778, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 53, 4, 6, 7, 20, {68,79,80}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Dominican Republic
- { 111, 7, 63, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3395, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 7, {85,83,68}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador
- { 111, 7, 65, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3798, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/El Salvador
- { 111, 7, 66, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 32,12934, 19, 0, 3719, 3809, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 4, 91, 5, 0, 7, 17, {88,65,70}, 0, 0, 1, 6, 7 }, // Spanish/Latin/Equatorial Guinea
- { 111, 7, 90, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 285,13025, 4, 0, 3719, 3826, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 29, 4, 0, 7, 9, {71,84,81}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala
- { 111, 7, 96, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1099, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 7,13054, 4, 0, 3719, 3835, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 59, 4, 0, 7, 8, {72,78,76}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras
- { 111, 7, 139, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 1, 1, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,13113, 4, 0, 3843, 3860, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 9, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 4, 0, 17, 6, {77,88,78}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico
- { 111, 7, 155, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 286,13160, 4, 0, 3719, 3866, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 68, 4, 0, 7, 9, {78,73,79}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua
- { 111, 7, 166, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 1126, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 288,13228, 4, 0, 3719, 3875, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 53, 4, 0, 7, 6, {80,65,66}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama
- { 111, 7, 168, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 291,13281, 4, 0, 3719, 3881, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 60, 4, 0, 7, 8, {80,89,71}, 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay
- { 111, 7, 169, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 265,13341, 4, 0, 3719, 3384, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 42, 4, 0, 7, 4, {80,69,78}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru
- { 111, 7, 170, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 173,13383, 19, 0, 3719, 3889, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 5, 0, 7, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines
- { 111, 7, 174, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 1126, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 1416, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Puerto Rico
- { 111, 7, 225, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 398, 10, 22, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3898, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 14, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/United States
- { 111, 7, 227, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,13430, 8, 37, 3719, 3912, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 5, 7, 7, 7, {85,89,85}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay
- { 111, 7, 231, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 294,13477, 4, 0, 3719, 3919, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 4, 57, 4, 0, 7, 9, {86,69,83}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela
- { 111, 7, 238, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 19, 0, 3719, 3928, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Canary Islands
- { 111, 7, 246, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 0, 0, 4, 0, 3936, 3959, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 0, 0, 4, 0, 23, 13, {0,0,0}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Latin America
- { 111, 7, 250, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 19, 0, 3719, 3972, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 7, 15, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Ceuta And Melilla
- { 112, 7, 101, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 222, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {73,68,82}, 2, 0, 7, 6, 7 }, // Sundanese/Latin/Indonesia
- { 113, 7, 210, 0, 0, 694, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 182,13534, 8, 0, 3987, 1585, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 66, 5, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania
- { 113, 7, 49, 0, 0, 694, 694, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 32,13600, 8, 0, 3987, 3996, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 2, 54, 5, 0, 9, 32, {67,68,70}, 2, 1, 1, 6, 7 }, // Swahili/Latin/Congo Kinshasa
- { 113, 7, 111, 0, 0, 694, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 2,13654, 8, 0, 3987, 1161, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 57, 5, 0, 9, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya
- { 113, 7, 221, 0, 0, 694, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 187,13711, 8, 0, 3987, 1650, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 60, 5, 0, 9, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Swahili/Latin/Uganda
- { 114, 7, 205, 0, 0, 702, 702, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 145,13771, 19, 0, 4028, 4035, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 2, 44, 5, 0, 7, 7, {83,69,75}, 2, 0, 1, 6, 7 }, // Swedish/Latin/Sweden
- { 114, 7, 73, 0, 0, 702, 702, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 14, 3032, 19, 0, 4028, 1063, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland
- { 114, 7, 248, 0, 0, 702, 702, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 14, 3032, 19, 0, 4028, 4042, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 7, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Swedish/Latin/Aland Islands
- { 115, 7, 106, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Sardinian/Latin/Italy
- { 116, 2, 209, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 9865, 9865, 9919, 9919, 9946, 9946, 0, 0, 0, 5, 22, 298,13815, 19, 0, 4047, 4053, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 5, 0, 6, 10, {84,74,83}, 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan
- { 117, 27, 100, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 119,13833, 4, 13, 4063, 4068, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 1, 48, 4, 6, 5, 7, {73,78,82}, 2, 1, 7, 7, 7 }, // Tamil/Tamil/India
- { 117, 27, 130, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 168,13881, 4, 13, 4063, 4075, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 2, 60, 4, 6, 5, 7, {77,89,82}, 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia
- { 117, 27, 190, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 6,13941, 4, 13, 4063, 4082, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 1, 60, 4, 6, 5, 11, {83,71,68}, 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore
- { 117, 27, 198, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 0, 0, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 302,14001, 4, 13, 4063, 4093, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 3, 48, 4, 6, 5, 6, {76,75,82}, 2, 1, 1, 6, 7 }, // Tamil/Tamil/Sri Lanka
- { 118, 2, 178, 0, 0, 724, 724, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1134, 501, 1, 1,10064,10064,10119,10119,10154,10154, 0, 0, 0, 5, 22, 121,14049, 19, 0, 4099, 3454, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 9, 4, 55, 55, 35, 35, 13, 13, 2, 2, 4, 17, 23, 1, 20, 5, 0, 5, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia
- { 119, 28, 100, 0, 0, 733, 733, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1157, 347, 10, 22,10167,10167,10226,10226,10257,10257, 0, 0, 972, 979, 22, 119,14069, 4, 13, 4104, 4110, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 59, 59, 31, 31, 17, 17, 2, 2, 7, 29, 23, 1, 25, 4, 6, 6, 8, {73,78,82}, 2, 1, 7, 7, 7 }, // Telugu/Telugu/India
- { 120, 30, 211, 120, 120, 744, 752, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1175, 259, 374, 0,10274,10274,10341,10341,10363,10363, 318, 287, 1008, 5, 22, 305,14094, 4, 13, 4118, 4118, 5, 5, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 6, 28, 5, 67, 67, 22, 22, 15, 15, 10, 10, 4, 17, 23, 1, 15, 4, 6, 3, 3, {84,72,66}, 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand
- { 121, 31, 44, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1194, 70, 10, 22,10378,10378,10456,10456,10506,10506, 328, 297, 0, 5, 22, 130,14109, 8, 0, 4121, 4129, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 12, 7, 78, 78, 50, 50, 26, 26, 7, 8, 4, 17, 23, 1, 6, 5, 0, 8, 6, {67,78,89}, 2, 1, 7, 6, 7 }, // Tibetan/Tibetan/China
- { 121, 31, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1194, 70, 10, 22,10378,10378,10456,10456,10506,10506, 328, 297, 0, 5, 22, 119,14115, 8, 0, 4121, 4135, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 12, 7, 78, 78, 50, 50, 26, 26, 7, 8, 4, 17, 23, 1, 12, 5, 0, 8, 7, {73,78,82}, 2, 1, 7, 7, 7 }, // Tibetan/Tibetan/India
- { 122, 14, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1217, 45, 10, 22,10532,10532,10560,10560,10580,10593, 335, 305, 0, 5, 22, 0, 254, 4, 0, 4142, 92, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 12, 7, 28, 28, 20, 20, 13, 13, 7, 7, 4, 17, 23, 2, 9, 4, 0, 4, 5, {69,84,66}, 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia
- { 122, 14, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 12, 13, 10, 11, 1217, 45, 10, 22,10532,10532,10560,10560,10593,10593, 335, 305, 0, 5, 22, 39, 0, 4, 0, 4142, 4146, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 12, 7, 28, 28, 20, 20, 13, 13, 7, 7, 4, 17, 23, 3, 0, 4, 0, 4, 4, {69,82,78}, 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea
- { 123, 7, 214, 759, 759, 759, 759, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 259, 10, 22,10606,10606,10665,10665,10693,10693, 342, 312, 1012, 1017, 1076, 185,14127, 8, 0, 4150, 1600, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 59, 59, 28, 28, 13, 13, 10, 6, 5, 59, 65, 2, 40, 5, 0, 13, 5, {84,79,80}, 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga
- { 124, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Tsonga/Latin/South Africa
- { 125, 7, 217, 0, 0, 767, 767, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1240, 502, 0, 0,10706,10706,10759,10759,10786,10786, 352, 318, 195, 5, 22, 236,14167, 4, 13, 4163, 4169, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 10, 5, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 39, 4, 6, 6, 7, {84,82,89}, 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey
- { 125, 7, 56, 0, 0, 767, 767, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1240, 502, 10, 22,10706,10706,10759,10759,10786,10786, 352, 318, 195, 5, 22, 14, 8263, 4, 13, 4163, 4176, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 12, 7, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 4, 6, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus
- { 126, 7, 218, 0, 0, 775, 775, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 10, 11, 1240, 501, 0, 0,10799,10852,10905,10932,10959,10959, 354, 320, 1141, 5, 22, 306,14206, 19, 0, 4182, 4194, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 53, 53, 27, 27, 13, 13, 13, 14, 4, 17, 23, 3, 48, 5, 0, 12, 12, {84,77,84}, 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan
- { 128, 1, 44, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 16, 15, 18, 17, 1256, 70, 10, 22,10972,10972,11026,11026,11046,11046, 367, 334, 0, 5, 22, 227,14254, 4, 13, 4206, 4214, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 54, 54, 20, 20, 13, 13, 12, 12, 4, 17, 23, 1, 39, 4, 6, 8, 5, {67,78,89}, 2, 1, 7, 6, 7 }, // Uighur/Arabic/China
- { 129, 2, 222, 0, 0, 136, 136, 6, 1, 14, 2, 3, 4, 5, 63, 15, 16, 40, 10, 1273, 166, 0, 0,11059,11059, 1466, 1466,11114,11114, 379, 346, 1145, 668, 22, 272,14293, 19, 0, 4219, 4229, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 10, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 48, 5, 0, 10, 7, {85,65,72}, 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine
- { 130, 1, 163, 560, 560, 783, 793, 6, 0, 1, 2, 3, 33, 35, 9, 11, 10, 13, 12, 1295, 259, 10, 22,11127,11127,11127,11127, 83, 83, 0, 0, 1150, 1154, 22, 170,14341, 4, 13, 4236, 3170, 6, 6, 10, 9, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 6, 12, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 2, 48, 4, 6, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan
- { 130, 1, 100, 560, 560, 783, 793, 6, 19, 20, 2, 52, 33, 53, 56, 11, 10, 13, 12, 1295, 259, 10, 22,11127,11127,11127,11127, 83, 83, 0, 0, 1150, 1154, 22, 119,14389, 4, 13, 4236, 4240, 6, 6, 10, 9, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 12, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 1, 41, 4, 6, 4, 5, {73,78,82}, 2, 1, 7, 7, 7 }, // Urdu/Arabic/India
- { 131, 7, 228, 0, 0, 802, 802, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 13, 12, 1313, 45, 55, 0,11162,11162,11222,11222,11253,11253, 381, 348, 195, 5, 22, 309,14430, 19, 0, 4245, 4251, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 11, 5, 60, 60, 31, 31, 13, 13, 2, 2, 4, 17, 23, 4, 57, 5, 0, 6, 11, {85,90,83}, 2, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan
- { 131, 1, 1, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 1331, 390, 55, 1, 7574, 7574,11266,11266, 83, 83, 0, 0, 0, 5, 22, 252, 9961, 19, 0, 4262, 3161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 33, 8, 11, 4, 48, 48, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan
- { 131, 2, 228, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 637, 45, 54, 0,11286,11286,11338,11338,11365,11365, 383, 350, 0, 5, 22, 313,14487, 19, 0, 4268, 4275, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 48, 5, 0, 7, 10, {85,90,83}, 2, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan
- { 132, 7, 232, 0, 0, 810, 810, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0,11378,11378,11432,11432,11464,11464, 385, 352, 0, 5, 22, 316,14535, 19, 0, 4285, 4295, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 54, 54, 32, 32, 20, 20, 2, 2, 4, 17, 23, 1, 32, 5, 0, 10, 8, {86,78,68}, 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam
- { 133, 7, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1364, 70, 0, 0,11484,11484,11526,11546,11573,11573, 0, 0, 0, 5, 22, 0, 0, 8, 0, 4303, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 42, 42, 20, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 7, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // Volapuk/Latin/World
- { 134, 7, 224, 0, 0, 818, 829, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,11586,11586,11662,11690,11719,11719, 387, 354, 1174, 5, 22, 117,14567, 4, 13, 4310, 4317, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 76, 76, 28, 29, 14, 14, 2, 2, 7, 17, 23, 1, 90, 4, 6, 7, 16, {71,66,80}, 2, 1, 1, 6, 7 }, // Welsh/Latin/United Kingdom
- { 135, 7, 187, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1387, 511, 0, 0,11733,11733,11782,11782,11782,11782, 389, 356, 0, 5, 22, 33,14657, 8, 0, 4333, 4338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 49, 49, 27, 27, 27, 27, 3, 3, 4, 17, 23, 3, 64, 5, 0, 5, 8, {88,79,70}, 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal
- { 136, 7, 195, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 12, 13, 10, 11, 53, 70, 0, 0,11809,11809,11869,11869, 83, 83, 0, 0, 0, 5, 22, 5,14721, 4, 0, 4346, 4354, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 60, 60, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 78, 4, 0, 8, 15, {90,65,82}, 2, 1, 7, 6, 7 }, // Xhosa/Latin/South Africa
- { 137, 18, 260, 0, 0, 839, 839, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 1404, 45, 0, 0,11896,11896,11896,11896, 83, 83, 392, 359, 0, 5, 22, 0, 0, 8, 0, 4369, 4375, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 53, 53, 53, 53, 13, 13, 11, 10, 4, 17, 23, 0, 0, 5, 0, 6, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Yiddish/Hebrew/World
- { 138, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1423, 398, 0, 1,11949,11992,12060,12060,12092,12092, 403, 369, 0, 5, 22, 172,14799, 4, 13, 4380, 4390, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 3, 43, 68, 32, 32, 13, 13, 5, 5, 4, 17, 23, 1, 48, 4, 6, 10, 19, {78,71,78}, 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria
- { 138, 7, 23, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1423, 398, 0, 1,12105,12148,12216,12216,12248,12248, 408, 374, 0, 5, 22, 33,14847, 4, 13, 4380, 4409, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 3, 43, 68, 32, 32, 13, 13, 5, 5, 4, 17, 23, 3, 27, 4, 6, 10, 16, {88,79,70}, 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin
- { 140, 7, 195, 0, 0, 848, 857, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 0, 0,12261,12261,12334,12334,12361,12361, 0, 0, 0, 5, 22, 5,14874, 4, 13, 4425, 4432, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 66, 4, 6, 7, 17, {90,65,82}, 2, 1, 7, 6, 7 }, // Zulu/Latin/South Africa
- { 141, 7, 161, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 346, 0,12374,12374,12424,12451, 2284, 2284, 413, 379, 0, 5, 22, 145, 9765, 19, 0, 4449, 4456, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 16, 5, 50, 50, 27, 27, 13, 13, 9, 11, 4, 17, 23, 2, 43, 5, 0, 7, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Nynorsk/Latin/Norway
- { 142, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 12, 13, 420, 1439, 0, 0, 1982, 1982, 2039, 2039, 2066, 2079, 422, 390, 315, 5, 22, 141,14940, 19, 0, 4461, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 11, 10, 5, 57, 57, 27, 27, 13, 13, 10, 7, 7, 17, 23, 2,169, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Bosnian/Latin/Bosnia And Herzegowina
- { 142, 2, 27, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1020, 1040, 0, 0,12478,12478,12533,12533, 8655, 8655, 264, 397, 0, 5, 22, 276,15109, 19, 0, 4469, 3551, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 55, 55, 27, 27, 13, 13, 11, 13, 4, 17, 23, 2,151, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/Bosnia And Herzegowina
- { 143, 29, 131, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {77,86,82}, 2, 1, 5, 6, 7 }, // Divehi/Thaana/Maldives
- { 144, 7, 251, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 80, 45, 0, 0,12560,12560,12616,12616, 83, 83, 64, 61, 0, 5, 22, 117, 0, 4, 0, 4477, 4482, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 29, 29, 13, 13, 4, 4, 4, 17, 23, 1, 0, 4, 0, 5, 12, {71,66,80}, 2, 1, 1, 6, 7 }, // Manx/Latin/Isle Of Man
- { 145, 7, 224, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0,12645,12645,12705,12705, 83, 83, 64, 61, 0, 5, 22, 117, 0, 4, 0, 4494, 4502, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 60, 60, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 0, 4, 0, 8, 14, {71,66,80}, 2, 1, 1, 6, 7 }, // Cornish/Latin/United Kingdom
- { 146, 7, 83, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1450, 547, 10, 22,12732,12732,12780,12780,12807,12807, 432, 410, 0, 5, 22, 163,15260, 4, 0, 4516, 4520, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 48, 48, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 0, 4, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana
- { 147, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 192, 10, 22,12820,12820,12820,12820,12868,12868, 0, 0, 1181, 5, 22, 119,15270, 4, 13, 4525, 2599, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 48, 48, 48, 48, 19, 19, 2, 2, 4, 17, 23, 1, 30, 4, 6, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India
- { 148, 7, 83, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {71,72,83}, 2, 1, 1, 6, 7 }, // Ga/Latin/Ghana
- { 149, 7, 157, 0, 0, 865, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 0, 0,12887,12887,12940,12940, 83, 83, 434, 412, 0, 5, 22, 172,15300, 4, 13, 4531, 4541, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 28, 28, 13, 13, 7, 7, 4, 17, 23, 1, 5, 4, 6, 10, 8, {78,71,78}, 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria
- { 150, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,12968,12968,13041,13041,13068,13068, 441, 419, 0, 5, 22, 2,15305, 4, 13, 4549, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 9, 7, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya
- { 151, 33, 103, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {73,81,68}, 0, 0, 6, 5, 6 }, // Syriac/Syriac/Iraq
- { 152, 14, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,82,78}, 2, 1, 1, 6, 7 }, // Blin/Ethiopic/Eritrea
- { 153, 14, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Geez/Ethiopic/Ethiopia
- { 155, 7, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Sidamo/Latin/Ethiopia
- { 156, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Atsam/Latin/Nigeria
- { 157, 14, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,82,78}, 2, 1, 1, 6, 7 }, // Tigre/Ethiopic/Eritrea
- { 158, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria
- { 159, 7, 106, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 1468, 45, 0, 0,13081,13081,13130,13130, 3015, 3015, 53, 50, 0, 5, 22, 14, 3032, 8, 0, 4556, 2453, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy
- { 160, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Venda/Latin/South Africa
- { 161, 7, 83, 0, 0, 874, 885, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1495, 521, 402, 402,13157,13157,13200,13200,13227,13227, 450, 426, 0, 5, 22, 163,15321, 4, 13, 4562, 4568, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 17, 12, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3, 36, 4, 6, 6, 12, {71,72,83}, 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana
- { 161, 7, 212, 0, 0, 874, 885, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1495, 521, 0, 0,13157,13157,13200,13200,13227,13227, 450, 426, 0, 5, 22, 33,15357, 4, 13, 4562, 4580, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 10, 5, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3,105, 4, 6, 6, 11, {88,79,70}, 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo
- { 162, 14, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Walamo/Ethiopic/Ethiopia
- { 163, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22,13240,13240,13296,13296, 83, 83, 0, 0, 0, 5, 22, 6, 0, 4, 13, 4591, 4605, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 6, 14, 19, {85,83,68}, 2, 1, 7, 6, 7 }, // Hawaiian/Latin/United States
- { 164, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria
- { 165, 7, 129, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {77,87,75}, 2, 1, 1, 6, 7 }, // Nyanja/Latin/Malawi
- { 166, 7, 170, 0, 0, 895, 904, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,13316,13316,13370,13370,13370,13370, 0, 0, 0, 5, 22, 173,15462, 4, 13, 4624, 4632, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 54, 54, 27, 27, 27, 27, 2, 2, 5, 17, 23, 1, 57, 4, 6, 8, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines
- { 167, 7, 206, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 208,15519, 19, 0, 4641, 4641, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 3, 54, 5, 0, 16, 7, {67,72,70}, 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland
- { 167, 7, 74, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 14, 8263, 19, 0, 4641, 4657, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 1, 18, 5, 0, 16, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Swiss German/Latin/France
- { 167, 7, 123, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 208,15519, 19, 0, 4641, 4667, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 3, 54, 5, 0, 16, 13, {67,72,70}, 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein
- { 168, 34, 44, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 10, 22,13486,13486,13513,13513,13533,13533, 465, 442, 0, 5, 22, 130, 0, 8, 0, 4680, 4683, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 3, 2, {67,78,89}, 2, 1, 7, 6, 7 }, // Sichuan Yi/Yi/China
- { 169, 7, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {76,82,68}, 2, 1, 1, 6, 7 }, // Kpelle/Latin/Liberia
- { 170, 7, 82, 0, 0, 459, 459, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1518, 167, 419, 438,13546,13546,13610,13610, 3613, 3613, 0, 0, 0, 5, 22, 14,15573, 19, 0, 4685, 4699, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 19, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 14, 5, 0, 14, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // Low German/Latin/Germany
- { 170, 7, 151, 0, 0, 459, 459, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1518, 167, 419, 438,13546,13546,13610,13610, 3613, 3613, 0, 0, 0, 5, 22, 14,15573, 19, 0, 4685, 4710, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 19, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 14, 5, 0, 14, 12, {69,85,82}, 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands
- { 171, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // South Ndebele/Latin/South Africa
- { 172, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/South Africa
- { 173, 7, 161, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 53, 70, 0, 0,13637,13637,13711,13711,13743,13743, 467, 444, 0, 5, 22, 145,15587, 19, 0, 4722, 4737, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 62, 5, 0, 15, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Norway
- { 173, 7, 73, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 97, 501, 0, 0,13756,13756,13825,13825,13845,13845, 478, 457, 0, 5, 22, 14,15649, 19, 0, 4722, 4742, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 10, 5, 69, 69, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 22, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland
- { 173, 7, 205, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 53, 70, 0, 0,13637,13637,13711,13711,13743,13743, 467, 444, 0, 5, 22, 145,15671, 19, 0, 4722, 4748, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 62, 5, 0, 15, 6, {83,69,75}, 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Sweden
- { 174, 7, 208, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 317, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {84,87,68}, 2, 0, 7, 6, 7 }, // Taroko/Latin/Taiwan
- { 175, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,13858,13858,13919,13919,13946,13946, 480, 459, 0, 5, 22, 2,13654, 4, 13, 4754, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 6, 3, 4, 17, 23, 3, 17, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya
- { 176, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,13959,13959,14063,14063,14090,14090, 486, 462, 0, 5, 22, 2,13654, 4, 13, 4762, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,104,104, 27, 27, 13, 13, 10, 10, 4, 17, 23, 3, 17, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya
- { 177, 7, 187, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 8, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal
- { 177, 7, 34, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4775, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 14, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Burkina Faso
- { 177, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 32,15752, 19, 0, 4769, 4789, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 4, 18, 5, 0, 6, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon
- { 177, 7, 80, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 162,15770, 19, 0, 4769, 4797, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 13, 5, 0, 6, 6, {71,77,68}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Gambia
- { 177, 7, 83, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 163, 0, 19, 0, 4769, 4803, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 0, 5, 0, 6, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Ghana
- { 177, 7, 91, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 201, 0, 19, 0, 4769, 4808, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 0, 5, 0, 6, 4, {71,78,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea
- { 177, 7, 92, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4812, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea Bissau
- { 177, 7, 121, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 6,15783, 19, 0, 4769, 4824, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {76,82,68}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Liberia
- { 177, 7, 136, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 203,15799, 19, 0, 4769, 4833, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 15, 5, 0, 6, 8, {77,82,85}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Mauritania
- { 177, 7, 156, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4841, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 6, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Niger
- { 177, 7, 157, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 172,15814, 19, 0, 4769, 4847, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {78,71,78}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Nigeria
- { 177, 7, 189, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 7,15830, 19, 0, 4769, 4856, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 18, 5, 0, 6, 11, {83,76,76}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Sierra Leone
- { 177, 134, 91, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 201, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {71,78,70}, 0, 0, 1, 6, 7 }, // Fulah/Adlam/Guinea
- { 178, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14201,14201,14263,14263,14290,14290, 502, 479, 0, 5, 22, 2,15848, 4, 13, 4867, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 27, 27, 13, 13, 6, 8, 4, 17, 23, 3, 16, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya
- { 179, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14303,14303,14407,14407,14434,14434, 508, 487, 0, 5, 22, 2,15864, 4, 13, 4873, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,104,104, 27, 27, 13, 13, 7, 5, 4, 17, 23, 3, 18, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya
- { 180, 7, 146, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 398, 0, 0,14447,14447,14501,14501,14528,14528, 0, 0, 0, 5, 22, 260,15882, 0, 0, 4881, 3301, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 21, 4, 0, 4, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Sena/Latin/Mozambique
- { 181, 7, 240, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14541,14541,14590,14590,14617,14617, 0, 0, 0, 5, 22, 156,15903, 4, 13, 4885, 1780, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 10, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe
- { 182, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14630,14630,14694,14694,14722,14722, 515, 492, 0, 5, 22, 182,15920, 4, 0, 4895, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 64, 64, 28, 28, 13, 13, 8, 7, 4, 17, 23, 3, 18, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Rombo/Latin/Tanzania
- { 183, 9, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 11, 97, 398, 0, 0,14735,14735,14781,14781, 83, 83, 523, 499, 0, 5, 22, 0,15938, 0, 0, 4904, 4911, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 46, 46, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 7, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Tachelhit/Tifinagh/Morocco
- { 183, 7, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 11, 97, 398, 0, 0,14810,14810,14857,14857, 83, 83, 529, 507, 0, 5, 22, 0,15952, 0, 0, 4917, 4927, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 10, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Tachelhit/Latin/Morocco
- { 184, 7, 3, 0, 0, 912, 924, 6, 1, 14, 2, 3, 4, 5, 68, 15, 16, 10, 11, 97, 398, 10, 22,14886,14919,14969,14996,15025,15038, 535, 515, 1185, 1192, 22, 195,15966, 0, 0, 4933, 4942, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 33, 50, 27, 29, 13, 13, 7, 9, 7, 21, 23, 2, 52, 4, 0, 9, 8, {68,90,68}, 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria
- { 185, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15051,15051,15124,15124,15151,15151, 0, 0, 0, 5, 22, 187,16018, 4, 0, 4950, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 10, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Nyankole/Latin/Uganda
- { 186, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15164,15164,15245,15245,15272,15272, 542, 524, 0, 5, 22, 182,16037, 0, 0, 4960, 4966, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 81, 81, 27, 27, 13, 13, 7, 7, 4, 17, 23, 3, 22, 4, 0, 6, 10, {84,90,83}, 2, 0, 1, 6, 7 }, // Bena/Latin/Tanzania
- { 187, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15285,15285,15346,15346,15373,15373, 549, 531, 0, 5, 22, 182,13534, 4, 0, 4976, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 8, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Vunjo/Latin/Tanzania
- { 188, 7, 132, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,15386,15386,15429,15429,15456,15456, 0, 0, 0, 5, 22, 33,16059, 4, 13, 4984, 2143, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 43, 43, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 9, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali
- { 188, 75, 132, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 33, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {88,79,70}, 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali
- { 189, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15469,15469,15532,15532,15559,15559, 554, 540, 0, 5, 22, 2,13654, 4, 13, 4993, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 63, 63, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya
- { 190, 12, 225, 0, 0, 935, 944, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,15572,15572,15620,15620,15647,15647, 556, 542, 1213, 5, 22, 6,16076, 4, 13, 4999, 5002, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 27, 27, 13, 13, 3, 6, 6, 17, 23, 1, 24, 4, 6, 3, 15, {85,83,68}, 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/United States
- { 191, 7, 137, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,15660,15660,15707,15707,15733,15733, 0, 0, 0, 5, 22, 170,16100, 8, 0, 5017, 5031, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 26, 26, 13, 13, 2, 2, 4, 17, 23, 2, 14, 5, 0, 14, 5, {77,85,82}, 2, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius
- { 192, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15746,15746,15878,15878,14722,14722, 559, 548, 0, 5, 22, 182,13534, 4, 13, 5036, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,132,132, 27, 27, 13, 13, 4, 5, 4, 17, 23, 3, 20, 4, 6, 10, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania
- { 193, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 0, 45, 0, 0,15905,15905,15967,15967,16002,16002, 563, 553, 0, 5, 22, 182,16114, 8, 0, 5046, 5054, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 35, 35, 13, 13, 3, 3, 4, 17, 23, 3, 22, 5, 0, 8, 9, {84,90,83}, 2, 0, 1, 6, 7 }, // Langi/Latin/Tanzania
- { 194, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16015,16015,16080,16080,16107,16107, 0, 0, 0, 5, 22, 187,16136, 0, 0, 5063, 5070, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7 }, // Ganda/Latin/Uganda
- { 195, 7, 239, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,16120,16120,16120,16120, 83, 83, 566, 556, 0, 5, 22, 2, 0, 4, 13, 5077, 1774, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 79, 79, 79, 79, 13, 13, 8, 7, 4, 17, 23, 1, 0, 4, 6, 9, 6, {90,77,87}, 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia
- { 196, 7, 39, 0, 0, 161, 161, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1541, 45, 0, 0,16199,16271,16343,16343,16370,16370, 68, 65, 0, 5, 22, 259,16155, 19, 24, 5086, 5098, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 10, 5, 72, 72, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 42, 5, 7, 12, 10, {67,86,69}, 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/Cape Verde
- { 197, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16383,16383,16433,16433,16460,16460, 574, 563, 0, 5, 22, 2,13654, 4, 13, 5108, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya
- { 198, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16473,16473,16525,16525,16552,16552, 576, 565, 0, 5, 22, 2,16197, 4, 13, 5114, 5122, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 52, 52, 27, 27, 13, 13, 6, 10, 4, 17, 23, 3, 19, 4, 6, 8, 12, {75,69,83}, 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya
- { 199, 7, 148, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,16565,16565,16656,16656,16678,16678, 582, 575, 0, 5, 22, 6,16216, 4, 0, 5134, 5147, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 91, 91, 22, 22, 13, 13, 7, 5, 4, 17, 23, 1, 15, 4, 0, 13, 8, {78,65,68}, 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia
- { 200, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15285,15285,15346,15346,15373,15373, 549, 531, 0, 5, 22, 182,13534, 4, 0, 5155, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Machame/Latin/Tanzania
- { 201, 7, 82, 0, 0, 459, 459, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 46, 12, 1568, 1070, 0, 0,16691,16691,16762,16762, 3613, 3613, 589, 580, 0, 5, 22, 14, 234, 19, 0, 5164, 5170, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 23, 10, 10, 5, 71, 71, 27, 27, 13, 13, 16, 16, 4, 17, 23, 1, 4, 5, 0, 6, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany
- { 202, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16789,16789,15346,15346,14722,14722, 605, 596, 0, 5, 22, 2,16231, 4, 13, 740, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 18, 4, 6, 3, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya
- { 202, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16789,16789,15346,15346,14722,14722, 605, 596, 0, 5, 22, 182,16249, 4, 13, 740, 5181, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 6, 3, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Masai/Latin/Tanzania
- { 203, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16846,16846,16910,16910,16944,16944, 614, 602, 0, 5, 22, 187,16136, 19, 0, 5189, 5070, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 64, 64, 34, 34, 13, 13, 6, 6, 4, 17, 23, 3, 19, 5, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7 }, // Soga/Latin/Uganda
- { 204, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 40, 10, 46, 12, 0, 45, 0, 0,16957,16957,17031,17031, 83, 83, 64, 61, 0, 5, 22, 2,16270, 4, 68, 5196, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 20, 20, 13, 13, 4, 4, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya
- { 205, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729,17051,17051,15373,15373, 620, 608, 0, 5, 22, 182,16286, 19, 0, 5203, 5209, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 27, 27, 13, 13, 9, 8, 4, 17, 23, 3, 21, 5, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Asu/Latin/Tanzania
- { 206, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17078,17078,17146,17146,17173,17173, 629, 616, 0, 5, 22, 187,16307, 4, 13, 5217, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 6, 6, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Teso/Latin/Uganda
- { 206, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17078,17078,17146,17146,17173,17173, 629, 616, 0, 5, 22, 2,16328, 4, 13, 5217, 5223, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 20, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya
- { 207, 7, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,82,78}, 2, 1, 1, 6, 7 }, // Saho/Latin/Eritrea
- { 208, 7, 132, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17186,17186,17238,17238,17265,17265, 638, 622, 0, 5, 22, 33,16348, 0, 0, 5228, 5239, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 52, 52, 27, 27, 13, 13, 6, 6, 4, 17, 23, 3, 16, 4, 0, 11, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Koyra Chiini/Latin/Mali
- { 209, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15285,15285,15346,15346,15373,15373, 549, 531, 0, 5, 22, 182,13534, 0, 0, 5244, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Rwa/Latin/Tanzania
- { 210, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17278,17278,17346,17346,17373,17373, 644, 628, 0, 5, 22, 2,16364, 0, 0, 5250, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 16, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Luo/Latin/Kenya
- { 211, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15051,15051,15124,15124,15151,15151, 0, 0, 0, 5, 22, 187,16018, 4, 0, 5256, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 6, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Chiga/Latin/Uganda
- { 212, 7, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17386,17386,17433,17433,17460,17460, 646, 630, 0, 5, 22, 0,16380, 19, 0, 5262, 5279, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 27, 27, 13, 13, 9, 10, 4, 17, 23, 0, 15, 5, 0, 17, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Central Morocco Tamazight/Latin/Morocco
- { 213, 7, 132, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17473,17473,17526,17526,17265,17265, 638, 622, 0, 5, 22, 33,16348, 0, 0, 5285, 5239, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 27, 27, 13, 13, 6, 6, 4, 17, 23, 3, 16, 4, 0, 15, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Koyraboro Senni/Latin/Mali
- { 214, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17553,17553,17615,17615,17642,17642, 655, 640, 0, 5, 22, 182,13556, 0, 0, 5300, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 27, 27, 13, 13, 5, 8, 4, 17, 23, 3, 20, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Shambala/Latin/Tanzania
- { 215, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,17655,17655,17708,17708,17740,17740, 660, 648, 0, 5, 22, 119,16395, 8, 0, 5309, 2599, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 53, 53, 32, 32, 18, 18, 3, 6, 4, 17, 23, 1, 3, 5, 0, 4, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Bodo/Devanagari/India
- { 218, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0,17758,17758,17802,17802,17826,17802, 0, 0, 0, 5, 22, 121,16398, 19, 0, 5313, 3454, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 44, 44, 24, 24, 16, 24, 2, 2, 4, 17, 23, 1, 42, 5, 0, 7, 5, {82,85,66}, 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia
- { 219, 2, 178, 0, 0, 952, 952, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1591, 967, 0, 0,17842,17842,17909,17909,11114,11114, 0, 0, 0, 5, 22, 121,16440, 19, 0, 5320, 5339, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 67, 67, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 43, 5, 0, 19, 7, {82,85,66}, 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia
- { 220, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 121, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {82,85,66}, 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia
- { 230, 7, 49, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17945,17945,17994,17994,18021,18021, 663, 654, 0, 5, 22, 32,16483, 0, 0, 5346, 5354, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 49, 49, 27, 27, 13, 13, 5, 6, 4, 17, 23, 2, 17, 4, 0, 8, 16, {67,68,70}, 2, 1, 1, 6, 7 }, // Luba Katanga/Latin/Congo Kinshasa
- { 231, 7, 125, 0, 0, 960, 960, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0,18034,18034,18098,18125, 3613, 3613, 668, 660, 441, 5, 22, 14, 8263, 19, 0, 5370, 5370, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 64, 64, 27, 34, 13, 13, 5, 8, 5, 17, 23, 1, 18, 5, 0, 14, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg
- { 236, 7, 21, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Walloon/Latin/Belgium
- { 237, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,18159,18159,18230,18230,18257,18257, 673, 668, 0, 5, 22, 32,16500, 0, 0, 5384, 5389, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 71, 71, 27, 27, 13, 13, 3, 3, 4, 17, 23, 4, 14, 4, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon
- { 238, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 97, 398, 0, 0,18270,18270,18339,18339,18366,18366, 676, 671, 0, 5, 22, 32,16514, 19, 0, 5396, 5401, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 69, 69, 27, 27, 13, 13, 10, 9, 4, 17, 23, 4, 15, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon
- { 239, 7, 156, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,18379,18379,17526,17526,18431,18431, 686, 680, 0, 5, 22, 33,16348, 0, 0, 5409, 5419, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 52, 52, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 16, 4, 0, 10, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger
- { 240, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 12, 13, 97, 398, 0, 0,18444,18444,18488,18488,18515,18515, 694, 690, 0, 5, 22, 32, 0, 19, 0, 5424, 1946, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 44, 44, 27, 27, 13, 13, 5, 6, 4, 17, 23, 4, 0, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon
- { 241, 7, 187, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18528,18528,18577,18577,18604,18604, 0, 0, 0, 5, 22, 33,16529, 19, 0, 5429, 5434, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 16, 5, 0, 5, 7, {88,79,70}, 0, 0, 1, 6, 7 }, // Jola Fonyi/Latin/Senegal
- { 242, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18617,18617,18701,18701,18730,18730, 699, 696, 0, 5, 22, 32,16545, 19, 0, 5441, 5447, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 84, 84, 29, 29, 13, 13, 7, 9, 4, 17, 23, 4, 16, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon
- { 243, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 12, 13, 97, 398, 0, 0,18743,18743,18787,18787,18815,18815, 706, 705, 0, 5, 22, 32,16561, 19, 0, 5454, 5459, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 44, 44, 28, 28, 13, 13, 6, 7, 4, 17, 23, 4, 4, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon
- { 244, 7, 146, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,18828,18828,18886,18886,18913,18913, 712, 712, 0, 5, 22, 260, 0, 8, 0, 5466, 5471, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 58, 58, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 0, 5, 0, 5, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Makhuwa Meetto/Latin/Mozambique
- { 245, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18926,18926,18999,18999,19026,19026, 720, 722, 0, 5, 22, 32,16565, 4, 13, 5481, 5487, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 73, 73, 27, 27, 13, 13, 5, 5, 4, 17, 23, 4, 10, 4, 6, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon
- { 246, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 15, 16, 97, 398, 0, 0,19039,19039,19127,19127,19156,19156, 725, 727, 0, 5, 22, 32,16575, 19, 0, 5494, 5500, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 88, 88, 29, 29, 13, 13, 4, 4, 4, 17, 23, 4, 13, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon
- { 247, 7, 254, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 46, 448, 22,19169,19169,19247,19247,19284,19284, 729, 731, 0, 5, 22, 117, 0, 4, 13, 5507, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 12, 7, 78, 78, 37, 37, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 6, 9, 0, {83,83,80}, 2, 1, 1, 6, 7 }, // Nuer/Latin/South Sudan
- { 248, 2, 178, 0, 0, 970, 970, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1614, 253, 0, 0,19297,19297,19367,19367,19387,19387, 731, 733, 1219, 1224, 22, 121,16588, 19, 0, 5516, 5525, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 6, 10, 5, 70, 70, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 46, 5, 0, 9, 9, {82,85,66}, 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia
- { 249, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,19400,19400,19459,19459,19486,19486, 733, 735, 0, 5, 22, 182,16634, 0, 0, 5534, 5543, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 27, 27, 13, 13, 9, 9, 4, 17, 23, 3, 18, 4, 0, 9, 9, {84,90,83}, 2, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania
- { 251, 7, 156, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17473,17473,17526,17526,17265,17265, 686, 680, 0, 5, 22, 33,16348, 0, 0, 5552, 5419, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 16, 4, 0, 13, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger
- { 252, 35, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,19499,19499,19499,19499, 83, 83, 0, 0, 0, 5, 22, 6,16652, 4, 13, 5565, 5567, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 29, 29, 29, 29, 13, 13, 2, 2, 4, 17, 23, 1, 8, 4, 6, 2, 4, {76,82,68}, 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia
- { 252, 7, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,19528,19528,19528,19528, 83, 83, 0, 0, 0, 5, 22, 6,16660, 4, 13, 5571, 5574, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 47, 47, 47, 47, 13, 13, 2, 2, 4, 17, 23, 1, 13, 4, 6, 3, 8, {76,82,68}, 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia
- { 253, 7, 206, 0, 0, 267, 267, 6, 1, 13, 2, 3, 4, 5, 9, 15, 16, 17, 18, 420, 70, 0, 0,19575,19575,19627,19627,19654,19654, 0, 0, 0, 5, 22, 0, 0, 8, 0, 5582, 5588, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 6, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland
- { 254, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 398, 0, 0,19667,19667,19737,19737,19757,19757, 742, 744, 0, 5, 22, 32, 0, 19, 24, 5594, 5600, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 70, 70, 20, 20, 13, 13, 8, 8, 4, 17, 23, 4, 0, 5, 7, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon
- { 256, 7, 197, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 0, 0,19770,19770,19823,19823, 3373, 3373, 750, 752, 0, 5, 22, 14, 3032, 19, 0, 5607, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 10, 5, 53, 53, 27, 27, 13, 13, 12, 11, 5, 17, 23, 1, 19, 5, 0, 9, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain
- { 257, 7, 37, 981, 981, 992, 1008, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 1450, 70, 0, 0,19850,19850,19850,19850,19909,19909, 762, 763, 0, 5, 22, 32,16673, 8, 0, 5616, 5621, 11, 11, 16, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 59, 59, 59, 59, 24, 24, 8, 13, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon
- { 258, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 80, 1644, 0, 0,19933,19933,19933,19933,19986,19986, 0, 0, 0, 5, 22, 32,14657, 8, 0, 5628, 5632, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 53, 53, 53, 53, 20, 20, 2, 2, 4, 17, 23, 4, 9, 5, 0, 4, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon
- { 259, 7, 37, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1450, 70, 0, 0,20006,20006,20006,20006,20054,20054, 0, 0, 0, 5, 22, 32,16678, 8, 0, 5639, 5644, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 48, 48, 48, 48, 20, 20, 2, 2, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon
- { 260, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 1654, 45, 0, 0,20074,20074,20074,20074, 83, 83, 770, 776, 0, 5, 22, 32,16683, 8, 0, 5651, 5667, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 32, 8, 10, 5,110,110,110,110, 13, 13, 9, 8, 4, 17, 23, 4, 9, 5, 0, 16, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon
- { 261, 7, 197, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Aragonese/Latin/Spain
- { 272, 46, 18, 0, 0, 1017, 1017, 6, 0, 1, 2, 69, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22,20184,20184,20310,20310,20394,20394, 0, 0, 1241, 5, 22, 122,16692, 0, 31, 5674, 5686, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 69, 4, 6, 12, 14, {66,68,84}, 2, 1, 7, 6, 7 }, // Chakma/Chakma/Bangladesh
- { 272, 46, 100, 0, 0, 1017, 1017, 6, 0, 1, 2, 69, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22,20184,20184,20310,20310,20394,20394, 0, 0, 1241, 5, 22, 119,16761, 0, 31, 5674, 5700, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 87, 4, 6, 12, 10, {73,78,82}, 2, 1, 7, 7, 7 }, // Chakma/Chakma/India
- { 290, 11, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 119, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {73,78,82}, 2, 1, 7, 7, 7 }, // Manipuri/Bengali/India
- { 309, 100, 232, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 316, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {86,78,68}, 0, 0, 1, 6, 7 }, // Tai Dam/Tai Viet/Vietnam
- { 312, 7, 37, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 32, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 0, 5, 0, 0, 0, {88,65,70}, 0, 0, 1, 6, 7 }, // Akoose/Latin/Cameroon
- { 313, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,20432,20432,20432,20432, 83,20518, 0, 0, 0, 5, 22, 6, 0, 8, 0, 5710, 5722, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 86, 86, 86, 86, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 12, 22, {85,83,68}, 2, 1, 7, 6, 7 }, // Lakota/Latin/United States
- { 314, 9, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 11, 97, 398, 0, 0,20531,20531,14781,14781, 83, 83, 523, 499, 0, 5, 22, 0,15938, 0, 0, 5744, 4911, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 8, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Standard Moroccan Tamazight/Tifinagh/Morocco
- { 315, 7, 43, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {67,76,80}, 0, 0, 1, 6, 7 }, // Mapuche/Latin/Chile
- { 316, 1, 103, 0, 0, 0, 0, 53, 19, 20, 21, 23, 71, 73, 28, 10, 11, 12, 13, 53, 70, 10, 22,20578,20578,20578,20578,20635,20635, 779, 784, 0, 5, 22, 42,16848, 19, 0, 5752, 5766, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 5, 13, 5, 0, 14, 5, {73,81,68}, 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq
- { 316, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 23, 71, 73, 28, 10, 11, 12, 13, 53, 70, 0, 0,20578,20578,20578,20578,20635,20635, 779, 784, 0, 5, 22, 0,16861, 19, 0, 5752, 5771, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 0, 12, 5, 0, 14, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran
- { 317, 7, 82, 0, 0, 183, 183, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 113, 1, 1,20648,20648,20700,20700,20727,20727, 782, 787, 0, 5, 22, 14,16873, 19, 0, 5776, 5790, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 9, 4, 52, 52, 27, 27, 13, 13, 9, 10, 4, 17, 23, 1, 26, 5, 0, 14, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Lower Sorbian/Latin/Germany
- { 318, 7, 82, 0, 0, 183, 183, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 113, 1, 460,20740,20740,20792,20792,20819,20819, 782, 797, 1249, 5, 22, 14,16899, 19, 0, 5796, 5811, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 9, 12, 52, 52, 27, 27, 13, 13, 9, 9, 5, 17, 23, 1, 28, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Upper Sorbian/Latin/Germany
- { 319, 7, 37, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 32, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 0, 5, 0, 0, 0, {88,65,70}, 0, 0, 1, 6, 7 }, // Kenyang/Latin/Cameroon
- { 320, 7, 38, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 224, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada
- { 321, 75, 91, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 201, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {71,78,70}, 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea
- { 322, 7, 260, 0, 0, 1029, 1029, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 40, 10, 1686, 166, 0, 0,20832,20832,20900,20900,20927,20927, 0, 0, 0, 5, 22, 0, 0, 19, 0, 5817, 5826, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 68, 68, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 9, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // Prussian/Latin/World
- { 323, 7, 90, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 285, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {71,84,81}, 2, 1, 7, 6, 7 }, // Kiche/Latin/Guatemala
- { 324, 7, 205, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 145, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {83,69,75}, 2, 0, 1, 6, 7 }, // Southern Sami/Latin/Sweden
- { 325, 7, 205, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 145, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {83,69,75}, 2, 0, 1, 6, 7 }, // Lule Sami/Latin/Sweden
- { 326, 7, 73, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1713, 581, 176, 167,20940,21009,21081,21081, 83,21108, 791, 806, 0, 5, 22, 14, 242, 19, 0, 5832, 5843, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 9, 4, 69, 72, 27, 27, 13, 13, 3, 3, 4, 17, 23, 1, 4, 5, 0, 11, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland
- { 327, 7, 73, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Skolt Sami/Latin/Finland
- { 328, 7, 13, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 225, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {65,85,68}, 2, 1, 7, 6, 7 }, // Warlpiri/Latin/Australia
- { 346, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 15, 16, 17, 18, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 714, 1254, 22, 320,16927, 8, 0, 5848, 3182, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 39, 23, 3, 26, 5, 0, 7, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran
- { 349, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 5855, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 11, 0, {73,82,82}, 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran
- { 349, 1, 103, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 53, 70, 10, 22, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 42, 0, 8, 0, 5855, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 5, 0, 5, 0, 11, 0, {73,81,68}, 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq
- { 357, 6, 97, 168, 168, 1037, 1037, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 406, 390, 153, 27, 1902, 1902, 1902, 1902, 1949, 1949, 58, 55, 0, 5, 22, 131,16953, 4, 13, 5866, 5868, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 13, 6, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 6, 2, 14, {72,75,68}, 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/Hong Kong
- { 357, 5, 44, 168, 168, 1037, 1037, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 390, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 0, 5, 22, 227, 3051, 4, 13, 5882, 5884, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 12, 4, 6, 2, 7, {67,78,89}, 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China
- { 358, 138, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // Osage/Osage/United States
- { 360, 7, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // Ido/Latin/World
- { 361, 7, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // Lojban/Latin/World
- { 362, 7, 106, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Sicilian/Latin/Italy
- { 363, 1, 102, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {73,82,82}, 0, 0, 6, 5, 5 }, // Southern Kurdish/Arabic/Iran
- { 364, 1, 163, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 170, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {80,75,82}, 2, 0, 7, 6, 7 }, // Western Balochi/Arabic/Pakistan
- { 365, 7, 170, 0, 0, 895, 904, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,21121,21121,21176,21176,21200,21200, 0, 0, 1293, 5, 22, 173,16963, 4, 13, 5891, 4632, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 55, 55, 24, 24, 13, 13, 2, 2, 8, 17, 23, 1, 55, 4, 6, 8, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Cebuano/Latin/Philippines
- { 366, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 121, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {82,85,66}, 2, 1, 1, 6, 7 }, // Erzya/Cyrillic/Russia
- { 367, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // Chickasaw/Latin/United States
- { 368, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // Muscogee/Latin/United States
- { 369, 7, 172, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 257, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {80,76,78}, 2, 1, 1, 6, 7 }, // Silesian/Latin/Poland
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0,0,0}, 0, 0, 0, 0, 0 } // trailing zeros
+static constexpr QLocaleData locale_data[] = {
+ // lang script terr lStrt lpMid lpEnd lPair lDelm dec group prcnt zero minus plus exp qtOpn qtEnd altQO altQE lDFmt sDFmt lTFmt sTFmt slDay lDays ssDys sDays snDay nDays am pm byte siQnt iecQn crSym crDsp crFmt crFNg ntLng ntTer currISO curDgt curRnd dow1st wknd+ wknd- grpTop grpMid grpEnd
+ { 1, 0, 0, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 8, 0, 17, 0, 0, 0, 0, 56, 56, 83, 96, 0, 0, 0, 5, 22, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 8, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 4, 0, 0, 0, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // C/AnyScript/AnyTerritory
+ { 2, 27, 90, 0, 0, 7, 7, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 27, 49, 10, 0, 109, 109, 157, 157, 179, 179, 0, 0, 0, 5, 22, 0, 0, 4, 0, 0, 6, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 48, 48, 22, 22, 15, 15, 2, 2, 4, 17, 23, 1, 0, 5, 0, 6, 9, {71,69,76}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Abkhazian/Cyrillic/Georgia
+ { 3, 66, 77, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 59, 78, 23, 38, 194, 194, 245, 245, 272, 272, 0, 0, 0, 5, 22, 1, 0, 2, 0, 15, 20, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 15, 7, 51, 51, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 4, 0, 5, 7, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Afar/Latin/Ethiopia
+ { 3, 66, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 59, 78, 23, 38, 194, 194, 245, 245, 272, 272, 0, 0, 0, 5, 22, 3, 0, 2, 0, 15, 27, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 15, 7, 51, 51, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 5, 7, {68,74,70}, 0, 0, 6, 6, 7, 1, 3, 3 }, // Afar/Latin/Djibouti
+ { 3, 66, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 59, 78, 23, 38, 194, 194, 245, 245, 272, 272, 0, 0, 0, 5, 22, 6, 0, 2, 0, 15, 34, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 15, 7, 51, 51, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 5, 7, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Afar/Latin/Eritrea
+ { 4, 66, 216, 0, 0, 16, 16, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 86, 103, 10, 0, 285, 285, 342, 342, 369, 369, 2, 2, 45, 5, 22, 9, 0, 2, 9, 41, 50, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 20, 4, 6, 9, 11, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Afrikaans/Latin/South Africa
+ { 4, 66, 162, 0, 0, 16, 16, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 103, 23, 38, 285, 285, 342, 342, 369, 369, 2, 2, 45, 5, 22, 10, 20, 2, 9, 41, 61, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 16, 4, 6, 9, 7, {78,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Afrikaans/Latin/Namibia
+ { 5, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 382, 382, 453, 453, 480, 480, 5, 5, 0, 5, 22, 11, 36, 0, 0, 68, 73, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 71, 71, 27, 27, 13, 13, 3, 3, 4, 17, 23, 4, 14, 4, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Aghem/Latin/Cameroon
+ { 6, 66, 92, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 137, 155, 23, 38, 493, 493, 541, 541, 568, 568, 8, 8, 0, 5, 22, 15, 50, 2, 0, 80, 84, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 48, 48, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 0, 4, 5, {71,72,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Akan/Latin/Ghana
+ { 8, 66, 40, 0, 0, 24, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 11, 60, 15, 0, 89, 95, 6, 6, 5, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 10, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Akoose/Latin/Cameroon
+ { 9, 66, 3, 0, 0, 29, 29, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 0, 180, 45, 38, 581, 581, 638, 638, 665, 665, 10, 10, 50, 5, 22, 18, 70, 4, 20, 102, 107, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 16, 7, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 4, 13, 5, 7, 5, 8, {65,76,76}, 0, 0, 1, 6, 7, 2, 3, 3 }, // Albanian/Latin/Albania
+ { 9, 66, 126, 0, 0, 29, 29, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 0, 180, 10, 0, 581, 581, 638, 638, 665, 665, 10, 10, 50, 5, 22, 22, 83, 4, 20, 102, 115, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 1, 6, 5, 7, 5, 6, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Albanian/Latin/Kosovo
+ { 9, 66, 140, 0, 0, 29, 29, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 0, 180, 10, 0, 581, 581, 638, 638, 665, 665, 10, 10, 50, 5, 22, 23, 89, 4, 20, 102, 121, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 3, 16, 5, 7, 5, 18, {77,75,68}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Albanian/Latin/Macedonia
+ { 11, 33, 77, 38, 38, 44, 53, 6, 0, 1, 2, 3, 4, 5, 10, 11, 12, 19, 20, 163, 186, 61, 76, 679, 679, 706, 706, 732, 732, 21, 20, 54, 57, 22, 26, 105, 2, 9, 139, 143, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 27, 27, 26, 26, 13, 13, 3, 4, 3, 23, 23, 2, 9, 4, 6, 4, 5, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Amharic/Ethiopic/Ethiopia
+ { 14, 4, 71, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 28, 114, 27, 0, 148, 155, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 9, 6, 0, 7, 3, {69,71,80}, 2, 1, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Egypt
+ { 14, 4, 4, 61, 61, 61, 61, 6, 1, 0, 32, 3, 35, 37, 10, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 33, 123, 33, 38, 148, 158, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 12, 5, 7, 7, 7, {68,90,68}, 2, 1, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Algeria
+ { 14, 4, 19, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 38, 135, 27, 0, 148, 165, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 12, 6, 0, 7, 7, {66,72,68}, 3, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Bahrain
+ { 14, 4, 48, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 11, 147, 27, 0, 148, 172, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 4, 15, 6, 0, 7, 4, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Chad
+ { 14, 4, 55, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 10, 0, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 12, 162, 27, 0, 148, 176, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 13, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 2, 14, 6, 0, 7, 9, {75,77,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Comoros
+ { 14, 4, 67, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 3, 176, 27, 0, 148, 185, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 3, 11, 6, 0, 7, 6, {68,74,70}, 0, 0, 6, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Djibouti
+ { 14, 4, 74, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 6, 187, 27, 0, 148, 191, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 3, 12, 6, 0, 7, 7, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Eritrea
+ { 14, 4, 113, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 43, 199, 27, 0, 148, 198, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 11, 6, 0, 7, 6, {73,81,68}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Iraq
+ { 14, 4, 116, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 11, 1, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 48, 210, 27, 0, 148, 204, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 4, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 1, 18, 6, 0, 7, 7, {73,76,83}, 2, 1, 7, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Israel
+ { 14, 4, 122, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 49, 228, 27, 0, 148, 211, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 11, 6, 0, 7, 6, {74,79,68}, 3, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Jordan
+ { 14, 4, 127, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 54, 239, 27, 0, 148, 217, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 11, 6, 0, 7, 6, {75,87,68}, 3, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Kuwait
+ { 14, 4, 132, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 59, 250, 27, 0, 148, 223, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 11, 6, 0, 7, 5, {76,66,80}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Lebanon
+ { 14, 4, 135, 61, 61, 61, 61, 6, 1, 0, 32, 3, 35, 37, 10, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 64, 261, 33, 38, 148, 228, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 10, 5, 7, 7, 5, {76,89,68}, 3, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Libya
+ { 14, 4, 149, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 69, 271, 27, 0, 148, 233, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 4, 15, 6, 0, 7, 9, {77,82,85}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Mauritania
+ { 14, 4, 159, 61, 61, 61, 61, 6, 1, 0, 32, 3, 35, 37, 10, 15, 14, 17, 16, 196, 213, 10, 0, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 73, 286, 33, 38, 148, 242, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 13, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 10, 5, 7, 7, 6, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Morocco
+ { 14, 4, 176, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 78, 296, 27, 0, 148, 248, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 10, 6, 0, 7, 5, {79,77,82}, 3, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Oman
+ { 14, 4, 180, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 48, 210, 27, 0, 148, 253, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 1, 18, 6, 0, 7, 18, {73,76,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Palestinian Territories
+ { 14, 4, 190, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 83, 306, 27, 0, 148, 271, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 9, 6, 0, 7, 3, {81,65,82}, 2, 1, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Qatar
+ { 14, 4, 205, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 88, 315, 27, 0, 148, 274, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 10, 6, 0, 7, 24, {83,65,82}, 2, 1, 7, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Saudi Arabia
+ { 14, 4, 215, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 93, 325, 27, 0, 148, 298, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 1, 10, 6, 0, 7, 7, {83,79,83}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Somalia
+ { 14, 4, 219, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 94, 335, 27, 0, 148, 305, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 1, 17, 6, 0, 7, 12, {83,83,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/South Sudan
+ { 14, 4, 222, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 95, 352, 27, 0, 148, 317, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 4, 11, 6, 0, 7, 7, {83,68,71}, 2, 1, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Sudan
+ { 14, 4, 227, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 99, 363, 27, 0, 148, 324, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 10, 6, 0, 7, 5, {83,89,80}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Syria
+ { 14, 4, 238, 61, 61, 61, 61, 6, 1, 0, 32, 3, 35, 37, 10, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 104, 373, 33, 38, 148, 329, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 11, 5, 7, 7, 4, {84,78,68}, 3, 0, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Tunisia
+ { 14, 4, 245, 61, 61, 61, 61, 6, 0, 1, 32, 3, 35, 37, 10, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 109, 384, 33, 38, 148, 333, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 12, 5, 7, 7, 24, {65,69,68}, 2, 1, 6, 6, 7, 1, 3, 3 }, // Arabic/Arabic/United Arab Emirates
+ { 14, 4, 257, 61, 61, 61, 61, 6, 0, 1, 32, 3, 35, 37, 10, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 73, 286, 33, 38, 148, 357, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 10, 5, 7, 7, 15, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/Western Sahara
+ { 14, 4, 258, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 0, 0, 27, 0, 372, 394, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 0, 0, 6, 0, 22, 6, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Arabic/Arabic/world
+ { 14, 4, 259, 61, 61, 61, 61, 67, 21, 22, 23, 25, 26, 28, 30, 15, 14, 17, 16, 196, 213, 61, 76, 745, 745, 745, 745, 796, 796, 24, 24, 80, 84, 22, 114, 396, 27, 0, 148, 400, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 37, 23, 5, 9, 6, 0, 7, 5, {89,69,82}, 0, 0, 7, 5, 6, 1, 3, 3 }, // Arabic/Arabic/Yemen
+ { 15, 66, 220, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 15, 15, 223, 129, 11, 1, 809, 809, 860, 860, 887, 887, 0, 0, 0, 5, 22, 22, 405, 2, 9, 405, 413, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 12, 4, 51, 51, 27, 27, 16, 16, 2, 2, 4, 17, 23, 1, 4, 4, 6, 8, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Aragonese/Latin/Spain
+ { 17, 5, 12, 0, 0, 75, 75, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 11, 12, 245, 49, 10, 0, 903, 903, 964, 964, 991, 991, 0, 0, 121, 127, 22, 119, 409, 4, 0, 420, 427, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 8, 13, 5, 61, 61, 27, 27, 13, 13, 2, 2, 6, 17, 23, 1, 13, 5, 0, 7, 8, {65,77,68}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Armenian/Armenian/Armenia
+ { 18, 9, 110, 0, 0, 82, 82, 6, 0, 1, 2, 39, 4, 5, 10, 14, 15, 16, 17, 265, 283, 83, 83, 1004, 1004, 1061, 1061, 1092, 1092, 25, 25, 144, 148, 22, 120, 422, 2, 9, 435, 442, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 57, 57, 31, 31, 13, 13, 9, 7, 4, 37, 23, 1, 12, 4, 6, 7, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Assamese/Bangla/India
+ { 19, 66, 220, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 223, 129, 10, 0, 1105, 1105, 1158, 1158, 1185, 1185, 34, 32, 0, 5, 22, 22, 405, 4, 0, 446, 455, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 13, 5, 53, 53, 27, 27, 13, 13, 12, 11, 5, 17, 23, 1, 4, 5, 0, 9, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Asturian/Latin/Spain
+ { 20, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 1198, 1198, 1257, 1257, 1284, 1284, 46, 43, 0, 5, 22, 121, 434, 4, 0, 461, 467, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 59, 59, 27, 27, 13, 13, 9, 8, 4, 17, 23, 3, 21, 5, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Asu/Latin/Tanzania
+ { 21, 66, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 137, 155, 10, 0, 1297, 1297, 1383, 1383, 83, 83, 0, 0, 0, 5, 22, 124, 455, 15, 0, 475, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 86, 86, 33, 33, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 5, 0, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Atsam/Latin/Nigeria
+ { 25, 66, 17, 0, 0, 91, 91, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 291, 49, 10, 0, 1416, 1416, 1482, 1508, 96, 96, 0, 0, 185, 5, 22, 125, 459, 4, 0, 480, 490, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 17, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Azerbaijani/Latin/Azerbaijan
+ { 25, 4, 112, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 11, 12, 19, 20, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 500, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 6, 0, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Azerbaijani/Arabic/Iran
+ { 25, 4, 113, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 11, 12, 19, 20, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 500, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 6, 0, {73,81,68}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Azerbaijani/Arabic/Iraq
+ { 25, 4, 239, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 11, 12, 19, 20, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 126, 0, 15, 0, 500, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 6, 0, {84,82,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Azerbaijani/Arabic/Turkey
+ { 25, 27, 17, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 19, 20, 291, 49, 10, 0, 1534, 1534, 1600, 1600, 96, 96, 55, 51, 0, 5, 22, 125, 476, 4, 0, 506, 516, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 5, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Azerbaijani/Cyrillic/Azerbaijan
+ { 26, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 16, 17, 113, 129, 10, 0, 1626, 1626, 1670, 1670, 1698, 1698, 57, 53, 0, 5, 22, 11, 481, 4, 0, 526, 531, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 44, 44, 28, 28, 13, 13, 6, 7, 4, 17, 23, 4, 4, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Bafia/Latin/Cameroon
+ { 28, 66, 145, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 129, 10, 0, 1711, 1711, 1754, 1754, 1781, 1781, 0, 0, 0, 5, 22, 127, 485, 2, 9, 538, 547, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 43, 43, 27, 27, 13, 13, 2, 2, 4, 17, 23, 5, 17, 4, 6, 9, 4, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Bambara/Latin/Mali
+ { 28, 90, 145, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 127, 0, 2, 9, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 5, 0, 4, 6, 0, 0, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Bambara/Nko/Mali
+ { 30, 9, 20, 0, 0, 99, 99, 6, 0, 1, 2, 39, 4, 5, 10, 14, 15, 16, 17, 265, 129, 61, 76, 1794, 1794, 1851, 1851, 1887, 1887, 0, 0, 144, 5, 22, 132, 502, 0, 45, 551, 556, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 14, 4, 6, 5, 8, {66,68,84}, 2, 1, 7, 6, 7, 1, 2, 3 }, // Bangla/Bangla/Bangladesh
+ { 30, 9, 110, 0, 0, 99, 99, 6, 0, 1, 2, 39, 4, 5, 10, 14, 15, 16, 17, 265, 129, 61, 76, 1794, 1794, 1851, 1851, 1887, 1887, 0, 0, 144, 5, 22, 120, 516, 2, 9, 551, 564, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 12, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Bangla/Bangla/India
+ { 31, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 113, 129, 10, 0, 1904, 1904, 1973, 1973, 2000, 2000, 63, 60, 0, 5, 22, 11, 528, 4, 0, 568, 573, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 69, 69, 27, 27, 13, 13, 10, 9, 4, 17, 23, 4, 15, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Basaa/Latin/Cameroon
+ { 32, 27, 193, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 133, 0, 15, 0, 581, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 12, 0, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Bashkir/Cyrillic/Russia
+ { 33, 66, 220, 0, 0, 108, 108, 6, 1, 0, 2, 3, 48, 5, 10, 11, 12, 14, 15, 308, 344, 98, 0, 2013, 2013, 2080, 2080, 2107, 2107, 0, 0, 189, 5, 22, 22, 543, 4, 20, 593, 600, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36, 6, 15, 5, 67, 67, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 5, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Basque/Latin/Spain
+ { 35, 27, 22, 0, 0, 117, 117, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 50, 113, 0, 2120, 2120, 2175, 2175, 2195, 2195, 0, 0, 196, 201, 22, 1, 548, 4, 0, 608, 618, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 7, 14, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 2, 16, 5, 0, 10, 8, {66,89,78}, 2, 0, 1, 6, 7, 2, 3, 3 }, // Belarusian/Cyrillic/Belarus
+ { 36, 66, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 2208, 2208, 2208, 2208, 83, 83, 73, 69, 0, 5, 22, 134, 0, 2, 9, 626, 635, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 79, 79, 79, 79, 13, 13, 8, 7, 4, 17, 23, 1, 0, 4, 6, 9, 6, {90,77,87}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Bemba/Latin/Zambia
+ { 37, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 2287, 2287, 2368, 2368, 2395, 2395, 81, 76, 0, 5, 22, 121, 564, 0, 0, 641, 647, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 81, 81, 27, 27, 13, 13, 7, 7, 4, 17, 23, 3, 22, 4, 0, 6, 10, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Bena/Latin/Tanzania
+ { 38, 29, 110, 0, 0, 0, 0, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 163, 103, 61, 76, 2408, 2408, 2408, 2408, 83, 83, 88, 83, 0, 5, 22, 120, 0, 2, 0, 657, 664, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 55, 55, 55, 55, 13, 13, 3, 4, 4, 17, 23, 1, 0, 4, 0, 7, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Bhojpuri/Devanagari/India
+ { 40, 33, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 372, 78, 61, 76, 2463, 2463, 2505, 2505, 2530, 2530, 0, 0, 0, 5, 22, 6, 0, 2, 0, 668, 671, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 15, 7, 42, 42, 25, 25, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 3, 4, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Blin/Ethiopic/Eritrea
+ { 41, 29, 110, 0, 0, 124, 134, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 291, 394, 127, 142, 2543, 2597, 2650, 2650, 2682, 2682, 91, 87, 0, 5, 22, 120, 586, 2, 9, 675, 664, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 10, 54, 53, 32, 32, 17, 17, 3, 6, 4, 17, 23, 1, 11, 4, 6, 3, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Bodo/Devanagari/India
+ { 42, 66, 29, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 13, 15, 16, 17, 404, 423, 10, 0, 2699, 2699, 2756, 2756, 2783, 2796, 94, 93, 218, 5, 22, 135, 597, 4, 0, 678, 686, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 11, 13, 5, 57, 57, 27, 27, 13, 13, 10, 7, 7, 17, 23, 2, 40, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Bosnian/Latin/Bosnia and Herzegovina
+ { 42, 27, 29, 0, 0, 150, 150, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 434, 454, 10, 0, 2809, 2809, 2864, 2864, 2891, 2891, 104, 100, 0, 5, 22, 137, 637, 4, 0, 705, 713, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 13, 5, 55, 55, 27, 27, 13, 13, 11, 13, 4, 17, 23, 2, 19, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Bosnian/Cyrillic/Bosnia and Herzegovina
+ { 43, 66, 84, 0, 0, 157, 157, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 186, 10, 0, 2904, 2904, 2946, 2946, 2978, 2978, 115, 113, 225, 232, 249, 22, 405, 4, 0, 732, 741, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 42, 42, 32, 32, 17, 17, 4, 4, 7, 17, 23, 1, 4, 5, 0, 9, 5, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Breton/Latin/France
+ { 45, 27, 36, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 13, 14, 13, 14, 350, 461, 152, 1, 2995, 2995, 3049, 3049, 3069, 3069, 119, 117, 272, 5, 22, 139, 656, 4, 20, 746, 755, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 12, 17, 4, 54, 54, 20, 20, 13, 13, 6, 6, 7, 17, 23, 3, 13, 5, 7, 9, 8, {66,71,78}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Bulgarian/Cyrillic/Bulgaria
+ { 46, 86, 161, 165, 165, 172, 172, 182, 0, 1, 2, 50, 4, 5, 10, 14, 15, 16, 17, 473, 129, 169, 1, 3082, 3082, 3082, 3082, 3135, 3135, 125, 123, 279, 5, 22, 134, 669, 15, 0, 763, 763, 7, 7, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 4, 53, 53, 53, 53, 13, 13, 5, 3, 5, 17, 23, 1, 11, 5, 0, 6, 6, {77,77,75}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Burmese/Myanmar/Myanmar
+ { 47, 137, 107, 183, 183, 188, 188, 6, 0, 1, 2, 3, 4, 5, 10, 51, 52, 53, 54, 491, 505, 182, 43, 3148, 3148, 3148, 3148, 3175, 3175, 130, 126, 0, 5, 22, 142, 680, 2, 9, 769, 771, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 16, 6, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 2, 4, 6, 2, 14, {72,75,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Cantonese/Traditional Han/Hong Kong
+ { 47, 118, 50, 183, 183, 188, 188, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 513, 505, 169, 0, 3148, 3148, 3188, 3188, 3175, 3175, 130, 126, 0, 5, 22, 145, 682, 2, 9, 785, 787, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 5, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 3, 4, 6, 2, 7, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Cantonese/Simplified Han/China
+ { 48, 66, 220, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 526, 129, 99, 1, 3208, 3208, 3267, 3267, 3267, 3267, 132, 128, 0, 5, 22, 22, 405, 4, 20, 794, 413, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 14, 4, 59, 59, 27, 27, 27, 27, 5, 5, 5, 17, 23, 1, 4, 5, 7, 6, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Catalan/Latin/Spain
+ { 48, 66, 6, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 526, 129, 99, 1, 3208, 3208, 3267, 3267, 3267, 3267, 132, 128, 0, 5, 22, 22, 405, 4, 20, 794, 800, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 14, 4, 59, 59, 27, 27, 27, 27, 5, 5, 5, 17, 23, 1, 4, 5, 7, 6, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Catalan/Latin/Andorra
+ { 48, 66, 84, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 526, 129, 99, 1, 3208, 3208, 3267, 3267, 3267, 3267, 132, 128, 0, 5, 22, 22, 405, 4, 20, 794, 807, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 14, 4, 59, 59, 27, 27, 27, 27, 5, 5, 5, 17, 23, 1, 4, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Catalan/Latin/France
+ { 48, 66, 117, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 526, 129, 99, 1, 3208, 3208, 3267, 3267, 3267, 3267, 132, 128, 0, 5, 22, 22, 405, 4, 20, 794, 813, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 14, 4, 59, 59, 27, 27, 27, 27, 5, 5, 5, 17, 23, 1, 4, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Catalan/Latin/Italy
+ { 49, 66, 185, 0, 0, 193, 202, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 3294, 3294, 3349, 3349, 3376, 3376, 0, 0, 284, 5, 22, 146, 685, 2, 9, 819, 826, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 55, 55, 27, 27, 13, 13, 2, 2, 8, 17, 23, 1, 15, 4, 6, 7, 9, {80,72,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Cebuano/Latin/Philippines
+ { 50, 66, 159, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 3389, 3389, 3436, 3436, 3463, 3463, 137, 133, 0, 5, 22, 0, 700, 4, 0, 835, 852, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 47, 47, 27, 27, 13, 13, 9, 10, 4, 17, 23, 0, 15, 5, 0, 17, 6, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Central Atlas Tamazight/Latin/Morocco
+ { 51, 4, 113, 0, 0, 0, 0, 67, 21, 22, 23, 25, 55, 57, 59, 14, 15, 16, 17, 163, 103, 61, 76, 3476, 3476, 3476, 3476, 3533, 3533, 146, 143, 0, 5, 22, 43, 715, 4, 0, 858, 872, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 15, 7, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 5, 13, 5, 0, 14, 5, {73,81,68}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Central Kurdish/Arabic/Iraq
+ { 51, 4, 112, 0, 0, 0, 0, 67, 21, 22, 23, 25, 55, 57, 59, 14, 15, 16, 17, 163, 103, 10, 0, 3476, 3476, 3476, 3476, 3533, 3533, 146, 143, 0, 5, 22, 0, 728, 4, 0, 858, 877, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 13, 5, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 0, 12, 5, 0, 14, 5, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Central Kurdish/Arabic/Iran
+ { 52, 21, 20, 0, 0, 210, 210, 6, 0, 1, 2, 61, 4, 5, 10, 14, 15, 16, 17, 265, 129, 61, 76, 3546, 3546, 3672, 3672, 3756, 3756, 0, 0, 292, 5, 22, 132, 740, 0, 45, 882, 894, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 21, 4, 6, 12, 14, {66,68,84}, 2, 1, 7, 6, 7, 1, 2, 3 }, // Chakma/Chakma/Bangladesh
+ { 52, 21, 110, 0, 0, 210, 210, 6, 0, 1, 2, 61, 4, 5, 10, 14, 15, 16, 17, 265, 129, 61, 76, 3546, 3546, 3672, 3672, 3756, 3756, 0, 0, 292, 5, 22, 120, 761, 0, 45, 882, 908, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 27, 4, 6, 12, 10, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Chakma/Chakma/India
+ { 54, 27, 193, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 3794, 3794, 3838, 3838, 3862, 3838, 0, 0, 0, 5, 22, 133, 788, 4, 0, 918, 925, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 44, 44, 24, 24, 16, 24, 2, 2, 4, 17, 23, 1, 11, 5, 0, 7, 5, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Chechen/Cyrillic/Russia
+ { 55, 23, 248, 0, 0, 222, 231, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 61, 76, 3878, 3878, 3926, 3926, 3953, 3953, 149, 146, 300, 5, 22, 10, 799, 2, 9, 930, 933, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 48, 48, 27, 27, 13, 13, 3, 6, 6, 17, 23, 1, 6, 4, 6, 3, 15, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Cherokee/Cherokee/United States
+ { 56, 66, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 3966, 3966, 3966, 3966, 83, 83, 0, 0, 0, 5, 22, 10, 0, 15, 0, 948, 964, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 87, 87, 87, 87, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 16, 13, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Chickasaw/Latin/United States
+ { 57, 66, 243, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 4053, 4053, 4126, 4126, 4153, 4153, 0, 0, 0, 5, 22, 147, 805, 2, 0, 977, 983, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 73, 73, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 6, 6, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // Chiga/Latin/Uganda
+ { 58, 118, 50, 183, 183, 239, 239, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 513, 505, 169, 0, 3148, 3148, 3188, 3188, 3175, 3175, 130, 126, 306, 5, 22, 150, 682, 2, 9, 989, 993, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 5, 27, 27, 20, 20, 13, 13, 2, 2, 2, 17, 23, 1, 3, 4, 6, 4, 2, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Chinese/Simplified Han/China
+ { 58, 118, 107, 183, 183, 239, 239, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 513, 129, 198, 43, 3148, 3148, 3188, 3188, 3175, 3175, 130, 126, 306, 5, 22, 142, 824, 2, 9, 989, 995, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 14, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 17, 23, 3, 2, 4, 6, 4, 9, {72,75,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Chinese/Simplified Han/Hong Kong
+ { 58, 118, 139, 183, 183, 239, 239, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 513, 129, 198, 43, 3148, 3148, 3188, 3188, 3175, 3175, 130, 126, 306, 5, 22, 151, 826, 2, 9, 989, 1004, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 14, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 17, 23, 4, 3, 4, 6, 4, 9, {77,79,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Chinese/Simplified Han/Macao
+ { 58, 118, 210, 183, 183, 239, 239, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 513, 78, 198, 43, 3148, 3148, 3188, 3188, 3175, 3175, 130, 126, 306, 5, 22, 10, 829, 2, 9, 989, 1013, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 14, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 17, 23, 1, 4, 4, 6, 4, 3, {83,71,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Chinese/Simplified Han/Singapore
+ { 58, 137, 107, 183, 183, 244, 244, 6, 0, 1, 2, 3, 4, 5, 10, 51, 52, 53, 54, 513, 129, 182, 43, 3148, 3148, 4166, 4166, 3175, 3175, 130, 126, 308, 5, 22, 142, 824, 2, 9, 1016, 1020, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 16, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 3, 2, 4, 6, 4, 9, {72,75,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Chinese/Traditional Han/Hong Kong
+ { 58, 137, 139, 183, 183, 244, 244, 6, 0, 1, 2, 3, 4, 5, 10, 51, 52, 53, 54, 513, 129, 182, 43, 3148, 3148, 4166, 4166, 3175, 3175, 130, 126, 308, 5, 22, 151, 833, 2, 9, 1016, 1029, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 16, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 4, 3, 4, 6, 4, 9, {77,79,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Chinese/Traditional Han/Macao
+ { 58, 137, 228, 183, 183, 239, 239, 6, 0, 1, 2, 3, 4, 5, 10, 51, 52, 53, 54, 491, 505, 182, 43, 3148, 3148, 4166, 4166, 3175, 3175, 130, 126, 0, 5, 22, 10, 836, 2, 9, 1016, 1038, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 16, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 3, 4, 6, 4, 2, {84,87,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Chinese/Traditional Han/Taiwan
+ { 59, 27, 193, 0, 0, 249, 249, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 573, 596, 10, 0, 4186, 4186, 4253, 4253, 4289, 4289, 0, 0, 0, 5, 22, 133, 839, 4, 0, 1040, 1059, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 67, 67, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 19, 7, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Church/Cyrillic/Russia
+ { 60, 27, 193, 0, 0, 257, 257, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 606, 49, 10, 0, 4302, 4302, 4367, 4367, 4399, 4399, 0, 0, 0, 5, 22, 133, 857, 4, 0, 1066, 1071, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 65, 65, 32, 32, 13, 13, 2, 2, 4, 17, 23, 1, 12, 5, 0, 5, 6, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Chuvash/Cyrillic/Russia
+ { 61, 66, 91, 0, 0, 267, 267, 6, 1, 9, 2, 3, 48, 5, 63, 13, 14, 18, 16, 628, 423, 10, 0, 4412, 4412, 4483, 4483, 4510, 4510, 152, 152, 0, 5, 22, 22, 83, 4, 0, 1077, 1083, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 23, 10, 13, 5, 71, 71, 27, 27, 13, 13, 16, 16, 4, 17, 23, 1, 4, 5, 0, 6, 11, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Colognian/Latin/Germany
+ { 63, 66, 246, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 186, 10, 0, 4523, 4523, 4583, 4583, 83, 83, 168, 168, 0, 5, 22, 94, 0, 2, 0, 1094, 1102, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 60, 60, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 0, 4, 0, 8, 14, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Cornish/Latin/United Kingdom
+ { 64, 66, 84, 0, 0, 275, 275, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 11, 12, 651, 186, 10, 0, 4610, 4610, 4660, 4660, 4694, 4694, 0, 0, 0, 5, 22, 155, 405, 4, 51, 1116, 1121, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 10, 13, 5, 50, 50, 34, 34, 13, 13, 2, 2, 4, 17, 23, 3, 4, 5, 7, 5, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Corsican/Latin/France
+ { 66, 66, 60, 0, 0, 143, 143, 6, 1, 0, 2, 3, 48, 5, 10, 13, 14, 18, 16, 404, 676, 98, 0, 2699, 2699, 2756, 2756, 2783, 2796, 0, 0, 218, 5, 22, 22, 405, 4, 0, 1128, 1136, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 15, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 4, 5, 0, 8, 8, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Croatian/Latin/Croatia
+ { 66, 66, 29, 0, 0, 143, 143, 6, 1, 0, 2, 3, 48, 5, 10, 13, 14, 18, 16, 404, 689, 98, 0, 2699, 2699, 2756, 2756, 2796, 2796, 0, 0, 218, 5, 22, 135, 618, 4, 0, 1128, 686, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 15, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 2, 19, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Croatian/Latin/Bosnia and Herzegovina
+ { 67, 66, 64, 0, 0, 282, 282, 6, 1, 9, 2, 3, 4, 5, 10, 13, 14, 18, 16, 698, 49, 114, 1, 4707, 4707, 4755, 4755, 4775, 4775, 172, 172, 311, 5, 22, 158, 869, 4, 0, 1144, 1151, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 4, 48, 48, 20, 20, 13, 13, 4, 4, 5, 17, 23, 2, 12, 5, 0, 7, 5, {67,90,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Czech/Latin/Czechia
+ { 68, 66, 65, 0, 0, 289, 289, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 715, 49, 212, 212, 4788, 4788, 4838, 4838, 4874, 4874, 0, 0, 0, 5, 22, 160, 881, 4, 0, 1156, 1161, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 50, 50, 36, 36, 13, 13, 2, 2, 5, 17, 23, 3, 11, 5, 0, 5, 7, {68,75,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Danish/Latin/Denmark
+ { 68, 66, 95, 0, 0, 289, 289, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 715, 49, 212, 212, 4788, 4788, 4838, 4838, 4874, 4874, 0, 0, 0, 5, 22, 160, 881, 4, 0, 1156, 1168, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 50, 50, 36, 36, 13, 13, 2, 2, 5, 17, 23, 3, 11, 5, 0, 5, 8, {68,75,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Danish/Latin/Greenland
+ { 69, 132, 144, 0, 0, 0, 0, 2, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 283, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 163, 0, 15, 0, 1176, 1186, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 10, 13, {77,86,82}, 2, 1, 5, 6, 7, 1, 3, 3 }, // Divehi/Thaana/Maldives
+ { 70, 29, 110, 0, 0, 297, 306, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 738, 129, 61, 76, 4887, 4887, 4937, 4937, 4966, 4988, 176, 176, 0, 5, 22, 120, 892, 2, 0, 1199, 664, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 50, 50, 29, 29, 22, 24, 4, 9, 4, 17, 23, 1, 10, 4, 0, 5, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Dogri/Devanagari/India
+ { 71, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 16, 17, 113, 129, 10, 0, 5012, 5012, 5056, 5056, 5083, 5083, 180, 185, 0, 5, 22, 11, 0, 4, 0, 1204, 1209, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 44, 44, 27, 27, 13, 13, 5, 6, 4, 17, 23, 4, 0, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Duala/Latin/Cameroon
+ { 72, 66, 165, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 394, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 22, 83, 15, 58, 1217, 1217, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 4, 5, 7, 10, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Netherlands
+ { 72, 66, 13, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 394, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 165, 902, 15, 58, 1217, 1227, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 16, 5, 7, 10, 5, {65,87,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Aruba
+ { 72, 66, 23, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 187, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 22, 83, 15, 58, 1232, 1238, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 4, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Belgium
+ { 72, 66, 44, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 394, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 10, 918, 15, 58, 1217, 1244, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 7, 10, 19, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Caribbean Netherlands
+ { 72, 66, 62, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 394, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 169, 936, 15, 58, 1217, 1263, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 30, 5, 7, 10, 7, {65,78,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Curacao
+ { 72, 66, 211, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 394, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 169, 936, 15, 58, 1217, 1270, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 30, 5, 7, 10, 12, {65,78,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Sint Maarten
+ { 72, 66, 223, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 16, 17, 113, 394, 10, 0, 5096, 5096, 5154, 5154, 5174, 5174, 168, 168, 0, 5, 22, 10, 966, 15, 58, 1217, 1282, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 17, 5, 7, 10, 8, {83,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Dutch/Latin/Suriname
+ { 73, 134, 27, 314, 314, 314, 314, 6, 0, 1, 2, 67, 4, 5, 10, 14, 15, 16, 17, 756, 103, 225, 255, 5187, 5187, 5265, 5265, 5298, 5298, 185, 191, 0, 5, 22, 173, 983, 2, 0, 1290, 1296, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 10, 30, 22, 78, 78, 33, 33, 26, 26, 5, 6, 4, 17, 23, 3, 8, 4, 0, 6, 5, {66,84,78}, 2, 1, 7, 6, 7, 1, 2, 3 }, // Dzongkha/Tibetan/Bhutan
+ { 74, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 5324, 5324, 5387, 5387, 5414, 5414, 190, 197, 0, 5, 22, 176, 991, 2, 9, 1301, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 63, 63, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Embu/Latin/Kenya
+ { 75, 66, 248, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1312, 964, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 16, 13, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/United States
+ { 75, 28, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 5427, 5427, 5511, 5511, 5559, 5559, 192, 199, 0, 5, 22, 10, 0, 15, 0, 1328, 1338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 84, 84, 48, 48, 20, 20, 4, 4, 4, 17, 23, 1, 0, 5, 0, 10, 25, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Deseret/United States
+ { 75, 66, 5, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 1363, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 14, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/American Samoa
+ { 75, 66, 8, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 1377, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 8, {88,67,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Anguilla
+ { 75, 66, 10, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 1385, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 17, {88,67,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Antigua and Barbuda
+ { 75, 66, 15, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 113, 129, 23, 38, 0, 0, 56, 56, 83, 5579, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1402, 1402, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 15, 7, 56, 56, 27, 27, 13, 24, 2, 2, 5, 17, 23, 1, 17, 4, 6, 18, 9, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Australia
+ { 75, 66, 16, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 15, 0, 1321, 1420, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Austria
+ { 75, 66, 18, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1055, 2, 9, 1321, 1427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 7, {66,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Bahamas
+ { 75, 66, 21, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1070, 2, 9, 1321, 1434, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 16, 4, 6, 7, 8, {66,66,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Barbados
+ { 75, 66, 23, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 78, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 4, 0, 1321, 1442, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Belgium
+ { 75, 66, 24, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 786, 78, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1086, 2, 9, 1321, 1449, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 13, 4, 6, 7, 6, {66,90,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Belize
+ { 75, 66, 26, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1099, 2, 9, 1321, 1455, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 16, 4, 6, 7, 7, {66,77,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Bermuda
+ { 75, 66, 30, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 786, 78, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 153, 1115, 2, 9, 1321, 1462, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 14, 4, 6, 7, 8, {66,87,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Botswana
+ { 75, 66, 33, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 1470, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 30, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/British Indian Ocean Territory
+ { 75, 66, 34, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 1500, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 22, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/British Virgin Islands
+ { 75, 66, 38, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 10, 0, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 182, 1129, 2, 9, 1321, 1522, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 15, 4, 6, 7, 7, {66,73,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Burundi
+ { 75, 66, 40, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 11, 1144, 2, 9, 1321, 1529, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 25, 4, 6, 7, 8, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Cameroon
+ { 75, 66, 41, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 103, 23, 38, 0, 0, 56, 56, 83, 83, 168, 168, 0, 5, 22, 10, 1169, 2, 9, 1537, 1553, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 15, 7, 56, 56, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 15, 4, 6, 16, 6, {67,65,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // English/Latin/Canada
+ { 75, 66, 45, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1184, 2, 9, 1321, 1559, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 14, {75,89,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Cayman Islands
+ { 75, 66, 51, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1321, 1573, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 17, 4, 6, 7, 16, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Christmas Island
+ { 75, 66, 53, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1321, 1589, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 17, 4, 6, 7, 23, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Cocos Islands
+ { 75, 66, 58, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1205, 2, 9, 1321, 1612, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 12, {78,90,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Cook Islands
+ { 75, 66, 63, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 2, 9, 1321, 1624, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 4, 6, 7, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Cyprus
+ { 75, 66, 65, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 212, 212, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 160, 1223, 4, 0, 1321, 1630, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 12, 5, 0, 7, 7, {68,75,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Denmark
+ { 75, 66, 66, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 1637, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 12, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Diego Garcia
+ { 75, 66, 68, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 1649, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 8, {88,67,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Dominica
+ { 75, 66, 74, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 6, 1235, 2, 9, 1321, 1657, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 14, 4, 6, 7, 7, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Eritrea
+ { 75, 66, 76, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 155, 1249, 2, 9, 1321, 1664, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 8, {83,90,76}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Eswatini
+ { 75, 66, 78, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 0, 0, 4, 0, 1321, 1672, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 0, 7, 6, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Europe
+ { 75, 66, 80, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1264, 2, 9, 1321, 1678, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 22, 4, 6, 7, 16, {70,75,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Falkland Islands
+ { 75, 66, 82, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1286, 2, 9, 1321, 1694, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 13, 4, 6, 7, 4, {70,74,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Fiji
+ { 75, 66, 83, 0, 0, 333, 333, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 213, 213, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 4, 0, 1321, 1698, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Finland
+ { 75, 66, 89, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 185, 1299, 2, 9, 1321, 1705, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 14, 4, 6, 7, 6, {71,77,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Gambia
+ { 75, 66, 91, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 4, 0, 1321, 1711, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Germany
+ { 75, 66, 92, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 15, 1313, 2, 9, 1321, 1718, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 13, 4, 6, 7, 5, {71,72,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Ghana
+ { 75, 66, 93, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1326, 2, 9, 1321, 1723, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 9, {71,73,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Gibraltar
+ { 75, 66, 96, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 1732, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 7, {88,67,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Grenada
+ { 75, 66, 98, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 1739, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 4, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Guam
+ { 75, 66, 100, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1341, 2, 9, 1321, 1743, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 8, 4, 6, 7, 8, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Guernsey
+ { 75, 66, 103, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1349, 2, 9, 1321, 1751, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 16, 4, 6, 7, 6, {71,89,68}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Guyana
+ { 75, 66, 107, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 142, 1365, 2, 9, 1321, 1757, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 16, 4, 6, 7, 19, {72,75,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Hong Kong
+ { 75, 66, 110, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 804, 78, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 120, 1381, 2, 9, 1321, 1478, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 12, 4, 6, 7, 5, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // English/Latin/India
+ { 75, 66, 111, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 212, 212, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 186, 1393, 2, 9, 1321, 1776, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 17, 4, 6, 7, 9, {73,68,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // English/Latin/Indonesia
+ { 75, 66, 114, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 186, 10, 0, 0, 0, 56, 56, 83, 83, 168, 168, 0, 5, 22, 22, 83, 2, 9, 1321, 1785, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 56, 56, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 4, 4, 6, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Ireland
+ { 75, 66, 115, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1341, 2, 9, 1321, 1792, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 8, 4, 6, 7, 11, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Isle of Man
+ { 75, 66, 116, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 11, 1, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 48, 1410, 2, 9, 1321, 1803, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 6, {73,76,83}, 2, 1, 7, 5, 6, 1, 3, 3 }, // English/Latin/Israel
+ { 75, 66, 119, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1428, 2, 9, 1321, 1809, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 7, {74,77,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Jamaica
+ { 75, 66, 121, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1341, 2, 9, 1321, 1816, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 8, 4, 6, 7, 6, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Jersey
+ { 75, 66, 124, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 176, 1443, 2, 9, 1321, 1307, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 15, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Kenya
+ { 75, 66, 125, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1321, 1822, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 17, 4, 6, 7, 8, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Kiribati
+ { 75, 66, 133, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 9, 1458, 2, 9, 1321, 1830, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 7, {90,65,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Lesotho
+ { 75, 66, 134, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1476, 2, 9, 1321, 1837, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 7, {76,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Liberia
+ { 75, 66, 139, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 151, 1491, 2, 9, 1321, 1844, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 15, 4, 6, 7, 15, {77,79,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Macao
+ { 75, 66, 141, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 188, 1506, 2, 9, 1321, 1859, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 15, 4, 6, 7, 10, {77,71,65}, 0, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Madagascar
+ { 75, 66, 142, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 190, 1521, 2, 9, 1321, 1869, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 15, 4, 6, 7, 6, {77,87,75}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Malawi
+ { 75, 66, 143, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 192, 1536, 2, 9, 1321, 1875, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 17, 4, 6, 7, 8, {77,89,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Malaysia
+ { 75, 66, 144, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 283, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 194, 1553, 15, 0, 1321, 1883, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 17, 5, 0, 7, 8, {77,86,82}, 2, 1, 5, 6, 7, 1, 3, 3 }, // English/Latin/Maldives
+ { 75, 66, 146, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 2, 9, 1321, 1891, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 4, 6, 7, 5, {69,85,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Malta
+ { 75, 66, 147, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 1896, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 16, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Marshall Islands
+ { 75, 66, 150, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 196, 1570, 2, 9, 1321, 1912, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 15, 4, 6, 7, 9, {77,85,82}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Mauritius
+ { 75, 66, 153, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 1921, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 10, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Micronesia
+ { 75, 66, 158, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 1931, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 10, {88,67,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Montserrat
+ { 75, 66, 162, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1585, 2, 9, 1321, 1941, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 7, {78,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Namibia
+ { 75, 66, 163, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1321, 1948, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 17, 4, 6, 7, 5, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Nauru
+ { 75, 66, 165, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 15, 58, 1321, 1953, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 7, 7, 11, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Netherlands
+ { 75, 66, 167, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1205, 2, 9, 1321, 1964, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 11, {78,90,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/New Zealand
+ { 75, 66, 169, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 124, 1600, 2, 9, 1321, 1975, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 14, 4, 6, 7, 7, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Nigeria
+ { 75, 66, 171, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1205, 2, 9, 1321, 1982, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 4, {78,90,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Niue
+ { 75, 66, 172, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1321, 1986, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 17, 4, 6, 7, 14, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Norfolk Island
+ { 75, 66, 173, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 2000, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 24, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Northern Mariana Islands
+ { 75, 66, 178, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 196, 1614, 2, 9, 1321, 2024, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 15, 4, 6, 7, 8, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // English/Latin/Pakistan
+ { 75, 66, 179, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 2032, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 5, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Palau
+ { 75, 66, 182, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 134, 1629, 2, 9, 1321, 2037, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 22, 4, 6, 7, 16, {80,71,75}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Papua New Guinea
+ { 75, 66, 185, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 146, 685, 2, 9, 1321, 2053, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 11, {80,72,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Philippines
+ { 75, 66, 186, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1205, 2, 9, 1321, 2064, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 16, {78,90,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Pitcairn
+ { 75, 66, 189, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 2080, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 11, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Puerto Rico
+ { 75, 66, 194, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 198, 1651, 2, 9, 1321, 2091, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 13, 4, 6, 7, 6, {82,87,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Rwanda
+ { 75, 66, 196, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1664, 2, 9, 1321, 2097, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 15, 4, 6, 7, 9, {83,72,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Saint Helena
+ { 75, 66, 197, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 2106, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 16, {88,67,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Saint Kitts and Nevis
+ { 75, 66, 198, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 2122, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 8, {88,67,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Saint Lucia
+ { 75, 66, 201, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1017, 2, 9, 1321, 2130, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 21, 4, 6, 7, 27, {88,67,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Saint Vincent and Grenadines
+ { 75, 66, 202, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 200, 1679, 2, 9, 1321, 1372, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 11, 4, 6, 7, 5, {87,83,84}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Samoa
+ { 75, 66, 208, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 203, 1690, 2, 9, 1321, 2157, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 17, 4, 6, 7, 10, {83,67,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Seychelles
+ { 75, 66, 209, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 18, 1707, 2, 9, 1321, 2167, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 20, 4, 6, 7, 12, {83,76,69}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Sierra Leone
+ { 75, 66, 210, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1727, 2, 9, 1321, 2179, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 16, 4, 6, 7, 9, {83,71,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Singapore
+ { 75, 66, 211, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 169, 1743, 2, 9, 1321, 2188, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 29, 4, 6, 7, 12, {65,78,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Sint Maarten
+ { 75, 66, 213, 0, 0, 333, 333, 6, 1, 0, 2, 3, 4, 5, 6, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 22, 83, 4, 20, 1321, 2200, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Slovenia
+ { 75, 66, 214, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1772, 2, 9, 1321, 2208, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 22, 4, 6, 7, 15, {83,66,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Solomon Islands
+ { 75, 66, 216, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 786, 821, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 9, 1458, 2, 9, 1321, 2223, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 12, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/South Africa
+ { 75, 66, 219, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1794, 2, 9, 1321, 2235, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 20, 4, 6, 7, 11, {83,83,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/South Sudan
+ { 75, 66, 222, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 0, 1814, 2, 9, 1321, 2246, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 14, 4, 6, 7, 5, {83,68,71}, 2, 1, 6, 5, 6, 1, 3, 3 }, // English/Latin/Sudan
+ { 75, 66, 225, 0, 0, 333, 333, 6, 1, 9, 2, 3, 4, 5, 63, 14, 15, 16, 17, 0, 103, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 160, 1828, 4, 0, 1321, 2251, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 13, 5, 0, 7, 6, {83,69,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Sweden
+ { 75, 66, 226, 0, 0, 333, 333, 6, 0, 17, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 49, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 0, 1841, 15, 65, 1321, 2257, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 11, 5, 5, 7, 11, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Switzerland
+ { 75, 66, 230, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 121, 1852, 2, 9, 1321, 2268, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 18, 4, 6, 7, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Tanzania
+ { 75, 66, 234, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1205, 2, 9, 1321, 2276, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 4, 6, 7, 7, {78,90,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Tokelau
+ { 75, 66, 235, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 205, 1870, 2, 9, 1321, 2283, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 14, 4, 6, 7, 5, {84,79,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Tonga
+ { 75, 66, 236, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1884, 2, 9, 1321, 2288, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 24, 4, 6, 7, 17, {84,84,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Trinidad and Tobago
+ { 75, 66, 241, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 2305, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 22, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Turks and Caicos Islands
+ { 75, 66, 242, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 10, 1038, 2, 9, 1321, 2327, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 17, 4, 6, 7, 6, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Tuvalu
+ { 75, 66, 243, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 147, 1908, 2, 9, 1321, 983, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 16, 4, 6, 7, 6, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // English/Latin/Uganda
+ { 75, 66, 245, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 1924, 2, 9, 1321, 2333, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 27, 4, 6, 7, 20, {65,69,68}, 2, 1, 6, 6, 7, 1, 3, 3 }, // English/Latin/United Arab Emirates
+ { 75, 66, 246, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 186, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 94, 1951, 2, 9, 2353, 2368, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 13, 4, 6, 15, 14, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/United Kingdom
+ { 75, 66, 247, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 2382, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 21, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/United States Outlying Islands
+ { 75, 66, 249, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 1008, 2, 9, 1321, 2403, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 9, 4, 6, 7, 19, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/United States Virgin Islands
+ { 75, 66, 252, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 207, 1964, 2, 9, 1321, 2422, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 12, 4, 6, 7, 7, {86,85,86}, 0, 0, 1, 6, 7, 1, 3, 3 }, // English/Latin/Vanuatu
+ { 75, 66, 258, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 0, 0, 2, 9, 1321, 2429, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 4, 6, 7, 5, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/world
+ { 75, 66, 260, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 134, 1976, 2, 9, 1321, 635, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 14, 4, 6, 7, 6, {90,77,87}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Latin/Zambia
+ { 75, 66, 261, 0, 0, 333, 333, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 786, 129, 10, 0, 0, 0, 56, 56, 83, 83, 82, 203, 0, 5, 22, 179, 1008, 2, 9, 1321, 2434, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 9, 4, 6, 7, 8, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // English/Latin/Zimbabwe
+ { 75, 115, 246, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 5603, 5603, 5690, 5690, 5731, 5731, 196, 205, 0, 5, 22, 94, 0, 15, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 87, 87, 41, 41, 20, 20, 4, 4, 4, 17, 23, 1, 0, 5, 0, 0, 0, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // English/Shavian/United Kingdom
+ { 76, 27, 193, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 5751, 5811, 5892, 5892, 83, 83, 0, 0, 0, 5, 22, 133, 0, 15, 0, 2442, 2453, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 60, 81, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 11, 13, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Erzya/Cyrillic/Russia
+ { 77, 66, 258, 0, 0, 342, 342, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 831, 105, 10, 0, 5919, 5919, 5969, 5969, 5989, 5989, 200, 209, 316, 5, 22, 0, 0, 4, 0, 2466, 2475, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 31, 8, 13, 5, 50, 50, 20, 20, 13, 13, 3, 3, 6, 17, 23, 0, 0, 5, 0, 9, 5, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Esperanto/Latin/world
+ { 78, 66, 75, 0, 0, 351, 351, 6, 1, 9, 2, 3, 48, 5, 63, 13, 14, 18, 16, 404, 49, 10, 0, 6002, 6002, 6064, 6064, 6064, 6064, 0, 0, 322, 5, 22, 22, 405, 4, 20, 2480, 2485, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 18, 8, 13, 5, 62, 62, 13, 13, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 5, 5, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Estonian/Latin/Estonia
+ { 79, 66, 92, 0, 0, 359, 370, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 862, 567, 277, 277, 6077, 6077, 6120, 6120, 6147, 6147, 203, 212, 0, 5, 22, 15, 1990, 2, 9, 2490, 2496, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 20, 12, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3, 10, 4, 6, 6, 12, {71,72,83}, 2, 1, 1, 6, 7, 3, 3, 3 }, // Ewe/Latin/Ghana
+ { 79, 66, 233, 0, 0, 359, 370, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 862, 567, 10, 0, 6077, 6077, 6120, 6120, 6147, 6147, 203, 212, 0, 5, 22, 127, 2000, 2, 9, 2490, 2508, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 13, 5, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 5, 33, 4, 6, 6, 11, {88,79,70}, 0, 0, 1, 6, 7, 3, 3, 3 }, // Ewe/Latin/Togo
+ { 80, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 129, 10, 0, 6160, 6160, 6244, 6244, 6273, 6273, 206, 217, 0, 5, 22, 11, 2033, 4, 0, 2519, 2525, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 84, 84, 29, 29, 13, 13, 7, 9, 4, 17, 23, 4, 16, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Ewondo/Latin/Cameroon
+ { 81, 66, 81, 0, 0, 380, 289, 6, 1, 0, 2, 3, 48, 5, 10, 14, 15, 16, 17, 404, 49, 10, 0, 6286, 6286, 6359, 6386, 6420, 6420, 0, 0, 328, 5, 22, 160, 2049, 4, 20, 2532, 2540, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 2, 11, 5, 7, 8, 7, {68,75,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Faroese/Latin/Faroe Islands
+ { 81, 66, 65, 0, 0, 380, 289, 6, 1, 0, 2, 3, 48, 5, 10, 14, 15, 16, 17, 404, 49, 10, 0, 6286, 6286, 6359, 6386, 6420, 6420, 0, 0, 328, 5, 22, 160, 2049, 4, 20, 2532, 1161, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 3, 11, 5, 7, 8, 7, {68,75,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Faroese/Latin/Denmark
+ { 83, 66, 185, 0, 0, 389, 398, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 6433, 6433, 6487, 6487, 6487, 6487, 0, 0, 0, 5, 22, 146, 2060, 2, 9, 2547, 826, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 54, 54, 27, 27, 27, 27, 2, 2, 5, 17, 23, 1, 17, 4, 6, 8, 9, {80,72,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Filipino/Latin/Philippines
+ { 84, 66, 83, 0, 0, 351, 351, 6, 1, 9, 2, 3, 48, 5, 10, 15, 15, 17, 17, 698, 885, 213, 213, 6514, 6580, 6660, 6660, 6680, 6680, 213, 226, 331, 336, 353, 22, 405, 4, 0, 2555, 2560, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 12, 4, 66, 80, 20, 20, 13, 13, 3, 3, 5, 17, 23, 1, 4, 5, 0, 5, 5, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Finnish/Latin/Finland
+ { 85, 66, 84, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2573, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/France
+ { 85, 66, 4, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 209, 2077, 4, 20, 2565, 2579, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 14, 5, 7, 8, 7, {68,90,68}, 2, 1, 6, 5, 6, 1, 3, 3 }, // French/Latin/Algeria
+ { 85, 66, 23, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 79, 297, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2586, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 7, 26, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 8, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Belgium
+ { 85, 66, 25, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 2594, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Benin
+ { 85, 66, 37, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 2599, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 12, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Burkina Faso
+ { 85, 66, 38, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 182, 2108, 4, 20, 2565, 1522, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 15, 5, 7, 8, 7, {66,73,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Burundi
+ { 85, 66, 40, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 216, 229, 376, 232, 249, 11, 2123, 4, 20, 2565, 1209, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 5, 4, 6, 17, 23, 4, 16, 5, 7, 8, 8, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Cameroon
+ { 85, 66, 41, 0, 0, 406, 406, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 15, 14, 113, 103, 323, 323, 6693, 6693, 6744, 6744, 6778, 6778, 168, 168, 376, 232, 249, 10, 2139, 4, 20, 2611, 1553, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 27, 9, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 1, 15, 5, 7, 17, 6, {67,65,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // French/Latin/Canada
+ { 85, 66, 46, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 11, 2123, 4, 20, 2565, 2628, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 16, 5, 7, 8, 25, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Central African Republic
+ { 85, 66, 48, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 11, 2123, 4, 20, 2565, 2653, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 16, 5, 7, 8, 5, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Chad
+ { 85, 66, 55, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 12, 2154, 4, 20, 2565, 2658, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 14, 5, 7, 8, 7, {75,77,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Comoros
+ { 85, 66, 56, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 11, 2123, 4, 20, 2565, 2665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 16, 5, 7, 8, 17, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Congo - Brazzaville
+ { 85, 66, 57, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 11, 2168, 4, 20, 2565, 2682, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 15, 5, 7, 8, 14, {67,68,70}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Congo - Kinshasa
+ { 85, 66, 67, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 3, 2183, 4, 20, 2565, 2696, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 16, 5, 7, 8, 8, {68,74,70}, 0, 0, 6, 6, 7, 1, 3, 3 }, // French/Latin/Djibouti
+ { 85, 66, 73, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 11, 2123, 4, 20, 2565, 2704, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 16, 5, 7, 8, 18, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Equatorial Guinea
+ { 85, 66, 85, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2722, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 16, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/French Guiana
+ { 85, 66, 86, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 211, 2199, 4, 20, 2565, 2738, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 9, 5, 7, 8, 19, {88,80,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/French Polynesia
+ { 85, 66, 88, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 11, 2123, 4, 20, 2565, 2757, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 16, 5, 7, 8, 5, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Gabon
+ { 85, 66, 97, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2762, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Guadeloupe
+ { 85, 66, 102, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 215, 2208, 4, 20, 2565, 2704, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 13, 5, 7, 8, 6, {71,78,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Guinea
+ { 85, 66, 104, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 15, 2221, 4, 20, 2565, 2772, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 16, 5, 7, 8, 5, {72,84,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Haiti
+ { 85, 66, 118, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 2777, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 13, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Ivory Coast
+ { 85, 66, 138, 0, 0, 406, 406, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2790, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Luxembourg
+ { 85, 66, 141, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 188, 2237, 4, 20, 2565, 1859, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 15, 5, 7, 8, 10, {77,71,65}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Madagascar
+ { 85, 66, 145, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 547, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 4, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Mali
+ { 85, 66, 148, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2800, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Martinique
+ { 85, 66, 149, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 217, 2252, 4, 20, 2565, 2810, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 19, 5, 7, 8, 10, {77,82,85}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Mauritania
+ { 85, 66, 150, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 196, 2271, 4, 20, 2565, 2820, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 18, 5, 7, 8, 7, {77,85,82}, 2, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Mauritius
+ { 85, 66, 151, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2827, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Mayotte
+ { 85, 66, 155, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2834, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Monaco
+ { 85, 66, 159, 0, 0, 406, 406, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 168, 168, 376, 232, 249, 0, 2289, 4, 20, 2565, 2840, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 0, 15, 5, 7, 8, 5, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Morocco
+ { 85, 66, 166, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 211, 2199, 4, 20, 2565, 2845, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 9, 5, 7, 8, 18, {88,80,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/New Caledonia
+ { 85, 66, 170, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 1975, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Niger
+ { 85, 66, 191, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2863, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Reunion
+ { 85, 66, 194, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 198, 2304, 4, 20, 2565, 2091, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 14, 5, 7, 8, 6, {82,87,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Rwanda
+ { 85, 66, 195, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2873, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 16, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Saint Barthelemy
+ { 85, 66, 199, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2889, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 12, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Saint Martin
+ { 85, 66, 200, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 22, 405, 4, 20, 2565, 2901, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 4, 5, 7, 8, 24, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Saint Pierre and Miquelon
+ { 85, 66, 206, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 2925, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 7, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Senegal
+ { 85, 66, 208, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 203, 2318, 4, 20, 2565, 2157, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 21, 5, 7, 8, 10, {83,67,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // French/Latin/Seychelles
+ { 85, 66, 226, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 19, 20, 0, 49, 350, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 0, 2339, 4, 20, 2932, 2947, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 17, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 0, 12, 5, 7, 15, 6, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Switzerland
+ { 85, 66, 227, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 219, 2351, 4, 20, 2565, 2953, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 14, 5, 7, 8, 5, {83,89,80}, 0, 0, 6, 5, 6, 1, 3, 3 }, // French/Latin/Syria
+ { 85, 66, 233, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 127, 2091, 4, 20, 2565, 2508, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 5, 17, 5, 7, 8, 4, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Togo
+ { 85, 66, 238, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 221, 2365, 4, 20, 2565, 2958, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 14, 5, 7, 8, 7, {84,78,68}, 3, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Tunisia
+ { 85, 66, 252, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 23, 38, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 207, 2379, 4, 20, 2565, 2422, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 15, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 14, 5, 7, 8, 7, {86,85,86}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Vanuatu
+ { 85, 66, 256, 0, 0, 406, 406, 6, 1, 68, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 186, 10, 0, 6693, 6693, 6744, 6744, 6778, 6778, 0, 0, 376, 232, 249, 211, 2199, 4, 20, 2565, 2965, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 9, 5, 7, 8, 16, {88,80,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // French/Latin/Wallis and Futuna
+ { 86, 66, 117, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 14, 15, 893, 78, 10, 0, 6791, 6791, 6840, 6840, 6778, 6778, 5, 128, 0, 5, 22, 22, 405, 15, 0, 2981, 2987, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Friulian/Latin/Italy
+ { 87, 66, 206, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 127, 2393, 4, 0, 2993, 2999, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 5, 19, 5, 0, 6, 8, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Senegal
+ { 87, 1, 37, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 223, 2412, 15, 0, 3007, 3017, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 6, 51, 5, 0, 10, 25, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Burkina Faso
+ { 87, 1, 40, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 229, 2463, 15, 0, 3007, 3042, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 8, 44, 5, 0, 10, 16, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Cameroon
+ { 87, 1, 89, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 61, 76, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 185, 2507, 15, 0, 3007, 3058, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 15, 7,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 1, 29, 5, 0, 10, 14, {71,77,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Gambia
+ { 87, 1, 92, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 61, 76, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 15, 2536, 15, 0, 3007, 3072, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 15, 7,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 3, 23, 5, 0, 10, 8, {71,72,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Ghana
+ { 87, 1, 101, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 223, 2412, 15, 0, 3007, 3080, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 6, 51, 5, 0, 10, 23, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Guinea-Bissau
+ { 87, 1, 102, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 215, 2559, 15, 0, 3007, 3080, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 2, 25, 5, 0, 10, 8, {71,78,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Guinea
+ { 87, 1, 134, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 61, 76, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 10, 2584, 15, 0, 3007, 3103, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 15, 7,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 1, 31, 5, 0, 10, 18, {76,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Liberia
+ { 87, 1, 149, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 61, 76, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 217, 2615, 15, 0, 3007, 3121, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 15, 7,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 2, 37, 5, 0, 10, 16, {77,82,85}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Mauritania
+ { 87, 1, 169, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 124, 2652, 15, 0, 3007, 3137, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 1, 33, 5, 0, 10, 18, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Nigeria
+ { 87, 1, 170, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 223, 2412, 15, 0, 3007, 3155, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 6, 51, 5, 0, 10, 12, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Niger
+ { 87, 1, 206, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 10, 0, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 223, 2412, 15, 0, 3007, 3167, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 13, 5,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 6, 51, 5, 0, 10, 16, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Senegal
+ { 87, 1, 209, 421, 421, 427, 436, 444, 0, 69, 2, 70, 4, 5, 72, 14, 15, 16, 17, 920, 283, 61, 76, 6965, 6965, 7083, 7083, 7135, 7135, 227, 240, 382, 394, 22, 18, 2685, 15, 0, 3007, 3183, 6, 6, 9, 8, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 17, 8, 15, 7,118,118, 52, 52, 22, 22, 4, 4, 12, 27, 23, 2, 33, 5, 0, 10, 14, {83,76,69}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Adlam/Sierra Leone
+ { 87, 66, 37, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 127, 2393, 4, 0, 2993, 3197, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 5, 19, 5, 0, 6, 14, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Burkina Faso
+ { 87, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 11, 2718, 4, 0, 2993, 3211, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 4, 18, 5, 0, 6, 8, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Cameroon
+ { 87, 66, 89, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 23, 38, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 185, 2736, 4, 0, 2993, 3219, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 15, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 13, 5, 0, 6, 6, {71,77,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Gambia
+ { 87, 66, 92, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 23, 38, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 15, 0, 4, 0, 2993, 3225, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 15, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 0, 5, 0, 6, 5, {71,72,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Ghana
+ { 87, 66, 101, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 127, 2393, 4, 0, 2993, 3230, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 5, 19, 5, 0, 6, 12, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Guinea-Bissau
+ { 87, 66, 102, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 215, 0, 4, 0, 2993, 3230, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 0, 5, 0, 6, 4, {71,78,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Guinea
+ { 87, 66, 134, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 23, 38, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 10, 2749, 4, 0, 2993, 3242, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 15, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {76,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Liberia
+ { 87, 66, 149, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 23, 38, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 217, 2765, 4, 0, 2993, 3251, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 15, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 15, 5, 0, 6, 8, {77,82,85}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Mauritania
+ { 87, 66, 169, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 124, 2780, 4, 0, 2993, 3259, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Nigeria
+ { 87, 66, 170, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 10, 0, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 127, 2393, 4, 0, 2993, 3268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 5, 19, 5, 0, 6, 6, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Niger
+ { 87, 66, 209, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 18, 17, 113, 129, 23, 38, 6867, 6867, 6925, 6925, 6952, 6952, 221, 233, 0, 5, 22, 18, 2796, 4, 0, 2993, 3274, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 15, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 18, 5, 0, 6, 11, {83,76,69}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Fulah/Latin/Sierra Leone
+ { 88, 66, 246, 0, 0, 445, 445, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 937, 186, 10, 0, 7157, 7157, 7225, 7225, 7252, 7252, 3, 135, 421, 5, 22, 94, 2814, 2, 9, 3285, 3293, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 10, 13, 5, 68, 68, 27, 27, 13, 13, 1, 1, 6, 17, 23, 1, 15, 4, 6, 8, 22, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Gaelic/Latin/United Kingdom
+ { 89, 66, 92, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38, 7265, 7265, 7297, 7297, 7323, 7323, 0, 0, 0, 5, 22, 15, 50, 2, 9, 3315, 1718, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 32, 32, 26, 26, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 6, 2, 5, {71,72,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Ga/Latin/Ghana
+ { 90, 66, 220, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 78, 10, 0, 7336, 7336, 7384, 7384, 1185, 7418, 168, 168, 0, 5, 22, 22, 405, 4, 0, 3317, 455, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 48, 48, 34, 34, 13, 20, 4, 4, 5, 17, 23, 1, 4, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Galician/Latin/Spain
+ { 91, 66, 243, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 7438, 7438, 7503, 7503, 7530, 7530, 0, 0, 0, 5, 22, 147, 2829, 0, 0, 3323, 3330, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // Ganda/Latin/Uganda
+ { 92, 33, 77, 0, 0, 0, 0, 6, 0, 74, 2, 3, 4, 5, 10, 14, 15, 16, 17, 985, 78, 61, 76, 7543, 7543, 7543, 7543, 7571, 7571, 0, 0, 0, 5, 22, 0, 105, 15, 0, 3337, 143, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 15, 7, 28, 28, 28, 28, 13, 13, 2, 2, 4, 17, 23, 0, 9, 5, 0, 4, 5, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Geez/Ethiopic/Ethiopia
+ { 92, 33, 74, 0, 0, 0, 0, 6, 0, 74, 2, 3, 4, 5, 10, 14, 15, 16, 17, 985, 78, 61, 76, 7543, 7543, 7543, 7543, 7571, 7571, 0, 0, 0, 5, 22, 6, 0, 15, 0, 3337, 671, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 15, 7, 28, 28, 28, 28, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 4, 4, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Geez/Ethiopic/Eritrea
+ { 93, 35, 90, 0, 0, 455, 455, 6, 1, 9, 2, 3, 4, 5, 10, 13, 14, 11, 12, 1008, 49, 10, 0, 7584, 7584, 7645, 7645, 7672, 7672, 0, 0, 427, 432, 22, 0, 2848, 4, 0, 3341, 3348, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 13, 5, 61, 61, 27, 27, 13, 13, 2, 2, 5, 29, 23, 1, 12, 5, 0, 7, 10, {71,69,76}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Georgian/Georgian/Georgia
+ { 94, 66, 91, 0, 0, 463, 463, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 22, 83, 4, 0, 3358, 3365, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 11, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // German/Latin/Germany
+ { 94, 66, 16, 0, 0, 463, 463, 6, 1, 9, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 22, 83, 15, 0, 3376, 3376, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 24, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // German/Latin/Austria
+ { 94, 66, 23, 0, 0, 463, 463, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 22, 83, 4, 0, 3358, 3400, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // German/Latin/Belgium
+ { 94, 66, 117, 0, 0, 463, 463, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 22, 83, 4, 0, 3358, 3407, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // German/Latin/Italy
+ { 94, 66, 136, 0, 0, 463, 463, 6, 0, 17, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 0, 2860, 15, 0, 3358, 3414, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 0, 17, 5, 0, 7, 13, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // German/Latin/Liechtenstein
+ { 94, 66, 138, 0, 0, 463, 463, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 22, 83, 4, 0, 3358, 3427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 7, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // German/Latin/Luxembourg
+ { 94, 66, 226, 0, 0, 463, 463, 6, 0, 17, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0, 7685, 7685, 7744, 7764, 4510, 4510, 0, 0, 461, 5, 22, 0, 2860, 15, 65, 3436, 3436, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 0, 17, 5, 5, 21, 7, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // German/Latin/Switzerland
+ { 96, 39, 94, 0, 0, 472, 472, 6, 1, 0, 2, 3, 4, 5, 6, 11, 12, 14, 15, 113, 129, 23, 38, 7791, 7791, 7845, 7845, 7872, 7872, 231, 244, 0, 5, 22, 22, 2877, 4, 0, 3457, 3465, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 15, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 4, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Greek/Greek/Greece
+ { 96, 39, 63, 0, 0, 472, 472, 6, 1, 0, 2, 3, 4, 5, 6, 11, 12, 14, 15, 113, 129, 23, 38, 7791, 7791, 7845, 7845, 7872, 7872, 231, 244, 0, 5, 22, 22, 2877, 4, 0, 3457, 3471, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 15, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 4, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Greek/Greek/Cyprus
+ { 97, 66, 183, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 7885, 7885, 7885, 7885, 83, 83, 0, 0, 0, 5, 22, 237, 0, 15, 0, 3477, 3484, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 53, 53, 53, 53, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 7, 8, {80,89,71}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Guarani/Latin/Paraguay
+ { 98, 40, 110, 0, 0, 481, 481, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 367, 383, 7938, 7938, 7990, 7990, 8021, 8021, 0, 0, 466, 5, 22, 120, 2881, 2, 9, 3492, 3499, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 16, 8, 52, 52, 31, 31, 18, 18, 2, 2, 4, 17, 23, 1, 13, 4, 6, 7, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Gujarati/Gujarati/India
+ { 99, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 8039, 8039, 8100, 8100, 8127, 8127, 235, 248, 0, 5, 22, 176, 991, 2, 9, 3503, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 61, 61, 27, 27, 13, 13, 6, 3, 4, 17, 23, 3, 17, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Gusii/Latin/Kenya
+ { 101, 66, 169, 0, 0, 490, 499, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 804, 129, 10, 0, 8140, 8140, 8191, 8191, 8218, 8218, 241, 251, 0, 470, 511, 124, 2894, 15, 0, 3511, 3259, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 51, 51, 27, 27, 13, 13, 6, 5, 5, 41, 47, 1, 15, 5, 0, 5, 8, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Hausa/Latin/Nigeria
+ { 101, 4, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 8231, 8231, 8287, 8287, 83, 83, 0, 0, 0, 5, 22, 124, 2909, 15, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 30, 30, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Hausa/Arabic/Nigeria
+ { 101, 4, 222, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 8231, 8231, 8287, 8287, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 56, 56, 30, 30, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {83,68,71}, 2, 1, 6, 5, 6, 1, 3, 3 }, // Hausa/Arabic/Sudan
+ { 101, 66, 92, 0, 0, 490, 499, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 804, 129, 23, 38, 8140, 8140, 8191, 8191, 8218, 8218, 241, 251, 0, 470, 511, 15, 2915, 15, 0, 3511, 3225, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 51, 51, 27, 27, 13, 13, 6, 5, 5, 41, 47, 3, 13, 5, 0, 5, 4, {71,72,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Hausa/Latin/Ghana
+ { 101, 66, 170, 0, 0, 490, 499, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 804, 129, 10, 0, 8140, 8140, 8191, 8191, 8218, 8218, 241, 251, 0, 470, 511, 127, 2928, 15, 0, 3511, 3516, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 51, 51, 27, 27, 13, 13, 6, 5, 5, 41, 47, 5, 29, 5, 0, 5, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Hausa/Latin/Niger
+ { 102, 66, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 23, 38, 8317, 8317, 8373, 8373, 83, 83, 0, 0, 0, 5, 22, 10, 0, 2, 9, 3521, 3535, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 56, 56, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 6, 14, 19, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Hawaiian/Latin/United States
+ { 103, 47, 116, 0, 0, 507, 507, 6, 0, 1, 2, 3, 35, 37, 10, 15, 15, 17, 17, 1027, 885, 11, 1, 8393, 8393, 8457, 8457, 8502, 8502, 247, 256, 558, 5, 22, 48, 2957, 70, 77, 3554, 3559, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 8, 12, 4, 64, 64, 45, 45, 20, 20, 6, 5, 4, 17, 23, 1, 7, 7, 9, 5, 5, {73,76,83}, 2, 1, 7, 5, 6, 1, 3, 3 }, // Hebrew/Hebrew/Israel
+ { 105, 29, 110, 0, 0, 513, 522, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76, 8522, 8522, 8574, 8574, 8605, 8605, 82, 203, 562, 5, 22, 120, 2964, 2, 0, 3564, 664, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 52, 52, 31, 31, 18, 18, 2, 2, 4, 17, 23, 1, 12, 4, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Hindi/Devanagari/India
+ { 105, 66, 110, 0, 0, 530, 540, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 804, 186, 23, 38, 8623, 8623, 8689, 8689, 8727, 8727, 0, 0, 0, 5, 22, 120, 1381, 2, 0, 3570, 1478, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 66, 66, 38, 38, 21, 21, 2, 2, 5, 17, 23, 1, 12, 4, 0, 13, 5, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Hindi/Latin/India
+ { 107, 66, 108, 0, 0, 549, 549, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 12, 11, 1045, 1064, 11, 1, 8748, 8748, 8799, 8799, 8817, 8817, 253, 261, 566, 5, 22, 238, 2976, 4, 0, 3583, 3589, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 12, 4, 51, 51, 18, 18, 16, 16, 3, 3, 4, 17, 23, 2, 13, 5, 0, 6, 12, {72,85,70}, 2, 0, 1, 6, 7, 2, 3, 3 }, // Hungarian/Latin/Hungary
+ { 108, 66, 109, 0, 0, 289, 289, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 885, 10, 0, 8833, 8833, 8913, 8913, 8947, 8947, 256, 264, 570, 5, 22, 160, 2989, 4, 0, 3601, 3609, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 80, 80, 34, 34, 13, 13, 4, 4, 4, 17, 23, 3, 13, 5, 0, 8, 6, {73,83,75}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Icelandic/Latin/Iceland
+ { 109, 66, 258, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 3615, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 3, 0, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Ido/Latin/world
+ { 110, 66, 169, 0, 0, 557, 566, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 10, 0, 8960, 8960, 9013, 9013, 83, 83, 260, 268, 0, 5, 22, 124, 3002, 2, 9, 3618, 3622, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 53, 53, 28, 28, 13, 13, 7, 7, 4, 17, 23, 1, 5, 4, 6, 4, 8, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Igbo/Latin/Nigeria
+ { 111, 66, 83, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1077, 885, 213, 213, 9041, 9110, 9182, 9182, 83, 9209, 267, 275, 0, 5, 22, 22, 405, 4, 0, 3630, 3641, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 4, 69, 72, 27, 27, 13, 13, 3, 3, 4, 17, 23, 1, 4, 5, 0, 11, 5, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Inari Sami/Latin/Finland
+ { 112, 66, 111, 0, 0, 574, 584, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 786, 78, 212, 212, 9222, 9222, 9264, 9264, 9291, 9291, 0, 0, 0, 5, 22, 186, 3007, 2, 0, 1776, 1776, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 42, 42, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 16, 4, 0, 9, 9, {73,68,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Indonesian/Latin/Indonesia
+ { 114, 66, 258, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 16, 17, 14, 15, 1095, 394, 10, 0, 9304, 9304, 9360, 9360, 9387, 9387, 0, 0, 0, 5, 22, 0, 0, 15, 58, 3646, 3657, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 10, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 7, 11, 5, {0,0,0}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Interlingua/Latin/world
+ { 115, 66, 75, 0, 0, 0, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 180, 10, 0, 9400, 9400, 9451, 9451, 9485, 9485, 270, 278, 574, 232, 249, 22, 405, 15, 86, 3662, 3673, 6, 6, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 13, 5, 51, 51, 34, 34, 13, 13, 9, 8, 7, 17, 23, 1, 4, 5, 6, 11, 7, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Interlingue/Latin/Estonia
+ { 116, 18, 41, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 1121, 61, 76, 9498, 9498, 9498, 9498, 83, 83, 0, 0, 0, 5, 22, 240, 0, 15, 0, 3680, 3686, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 15, 7, 54, 54, 54, 54, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 6, 4, {67,65,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Inuktitut/Canadian Aboriginal/Canada
+ { 116, 66, 41, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 240, 0, 15, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Inuktitut/Latin/Canada
+ { 118, 66, 114, 0, 0, 445, 445, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 186, 10, 0, 9552, 9552, 9626, 9626, 9662, 9662, 279, 286, 581, 5, 22, 22, 83, 2, 9, 3690, 3697, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 4, 4, 6, 7, 4, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Irish/Latin/Ireland
+ { 118, 66, 246, 0, 0, 445, 445, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 186, 10, 0, 9552, 9552, 9626, 9626, 9662, 9662, 279, 286, 581, 5, 22, 94, 3023, 2, 9, 3690, 3701, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 14, 4, 6, 7, 19, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Irish/Latin/United Kingdom
+ { 119, 66, 117, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 78, 10, 0, 9675, 9675, 9731, 9731, 4694, 4694, 0, 0, 0, 5, 22, 22, 405, 4, 0, 3720, 3728, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Italian/Latin/Italy
+ { 119, 66, 203, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 78, 10, 0, 9675, 9675, 9731, 9731, 4694, 4694, 0, 0, 0, 5, 22, 22, 405, 4, 0, 3720, 3734, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Italian/Latin/San Marino
+ { 119, 66, 226, 0, 0, 414, 414, 6, 0, 17, 2, 3, 4, 5, 10, 11, 12, 19, 20, 0, 49, 10, 0, 9675, 9675, 9731, 9731, 4694, 4694, 0, 0, 0, 5, 22, 0, 3037, 15, 65, 3720, 3744, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 15, 5, 5, 8, 8, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Italian/Latin/Switzerland
+ { 119, 66, 253, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 78, 10, 0, 9675, 9675, 9731, 9731, 4694, 4694, 0, 0, 0, 5, 22, 22, 405, 4, 0, 3720, 3752, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 8, 18, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Italian/Latin/Vatican City
+ { 120, 53, 120, 183, 183, 183, 183, 6, 0, 1, 2, 3, 4, 5, 10, 51, 52, 53, 54, 513, 821, 391, 1, 9758, 9758, 9785, 9785, 9785, 9785, 283, 290, 587, 590, 22, 145, 3052, 2, 9, 3770, 3770, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 10, 13, 4, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 3, 4, 6, 3, 2, {74,80,89}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Japanese/Japanese/Japan
+ { 121, 66, 111, 0, 0, 593, 603, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 394, 10, 0, 9798, 9798, 9838, 9838, 9866, 9866, 285, 292, 607, 5, 22, 186, 3007, 15, 0, 3773, 3777, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 40, 40, 28, 28, 13, 13, 4, 5, 4, 17, 23, 2, 16, 5, 0, 4, 9, {73,68,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Javanese/Latin/Indonesia
+ { 122, 66, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 137, 155, 10, 0, 9879, 9879, 9922, 9922, 83, 83, 0, 0, 0, 5, 22, 124, 3055, 15, 0, 3786, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 43, 43, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 7, 5, 0, 4, 0, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Jju/Latin/Nigeria
+ { 123, 66, 206, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 129, 10, 0, 9949, 9949, 9998, 9998,10025,10025, 0, 0, 0, 5, 22, 127, 3062, 4, 0, 3790, 3795, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 5, 16, 5, 0, 5, 7, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Jola-Fonyi/Latin/Senegal
+ { 124, 66, 43, 0, 0, 143, 143, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1131, 186, 10, 0,10038,10038,10110,10110,10137,10137, 82, 203, 0, 5, 22, 243, 3078, 4, 20, 3802, 3814, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 13, 5, 72, 72, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 7, 12, 10, {67,86,69}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Kabuverdianu/Latin/Cape Verde
+ { 125, 66, 4, 0, 0, 612, 620, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 129, 23, 38,10150,10183,10233,10260,10289,10302, 289, 297, 611, 618, 22, 209, 3096, 0, 0, 3824, 3833, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 15, 7, 33, 50, 27, 29, 13, 13, 7, 9, 7, 21, 23, 2, 14, 4, 0, 9, 8, {68,90,68}, 2, 1, 6, 5, 6, 1, 3, 3 }, // Kabyle/Latin/Algeria
+ { 126, 66, 40, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 19, 20, 86, 1158, 10, 0,10315,10315,10315,10315,10368,10368, 0, 0, 0, 5, 22, 11, 3110, 15, 0, 3841, 3845, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 53, 53, 53, 53, 20, 20, 2, 2, 4, 17, 23, 4, 9, 5, 0, 4, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Kako/Latin/Cameroon
+ { 127, 66, 95, 0, 0, 627, 627, 6, 1, 0, 2, 3, 48, 5, 63, 12, 11, 20, 19, 86, 103, 212, 212,10388,10388,10485,10485,10512,10512, 0, 0, 0, 5, 22, 160, 3119, 2, 92, 3852, 3863, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 13, 5, 97, 97, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 5, 11, 16, {68,75,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Kalaallisut/Latin/Greenland
+ { 128, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,10525,10525,10577,10577,10604,10604, 296, 306, 0, 5, 22, 176, 3138, 2, 9, 3879, 3887, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 52, 52, 27, 27, 13, 13, 6, 10, 4, 17, 23, 3, 19, 4, 6, 8, 12, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Kalenjin/Latin/Kenya
+ { 129, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,10617,10617,10690,10690,10717,10717, 302, 316, 0, 5, 22, 176, 3157, 2, 9, 3899, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 73, 73, 27, 27, 13, 13, 9, 7, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Kamba/Latin/Kenya
+ { 130, 56, 110, 0, 0, 638, 650, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 129, 367, 383,10730,10730,10783,10783,10815,10815, 311, 323, 639, 647, 22, 120, 3173, 2, 9, 3906, 3911, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 16, 8, 53, 53, 32, 32, 19, 19, 9, 7, 8, 35, 23, 1, 13, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Kannada/Kannada/India
+ { 132, 4, 110, 661, 661, 667, 677, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 549, 567, 61, 76,10834,10834,10885,10885,10934,10934, 320, 330, 0, 5, 22, 120, 3186, 2, 0, 3915, 3920, 6, 6, 10, 9, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 15, 7, 51, 51, 49, 49, 13, 13, 6, 6, 4, 17, 23, 1, 16, 4, 0, 5, 9, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Kashmiri/Arabic/India
+ { 132, 29, 110, 0, 0, 686, 695, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 127, 127,10947,10996,10947,11045,11092,11092, 326, 336, 0, 5, 22, 120, 3202, 15, 0, 3929, 3934, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 49, 49, 49, 47, 13, 13, 5, 5, 4, 17, 23, 1, 11, 5, 0, 5, 10, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Kashmiri/Devanagari/India
+ { 133, 27, 123, 0, 0, 0, 703, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 1168, 49, 10, 0,11105,11105,11160,11160,11180,11180, 0, 0, 196, 682, 699, 244, 3213, 4, 0, 3944, 3954, 6, 6, 6, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 13, 5, 55, 55, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 17, 5, 0, 10, 9, {75,90,84}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Kazakh/Cyrillic/Kazakhstan
+ { 134, 66, 40, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 11, 0, 15, 0, 3963, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 0, 5, 0, 6, 0, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Kenyang/Latin/Cameroon
+ { 135, 60, 39, 0, 0, 713, 722, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 61, 76,11193,11238,11284,11284,11323,11323, 0, 0, 722, 5, 22, 245, 3230, 0, 45, 3969, 3974, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 15, 7, 45, 46, 39, 39, 13, 13, 2, 2, 2, 17, 23, 1, 11, 4, 6, 5, 7, {75,72,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Khmer/Khmer/Cambodia
+ { 136, 66, 99, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 246, 0, 15, 0, 3981, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 7, 0, {71,84,81}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Kiche/Latin/Guatemala
+ { 137, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,11336,11336,11398,11398,11425,11425, 331, 341, 0, 5, 22, 176, 3241, 2, 9, 3988, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 62, 62, 27, 27, 13, 13, 6, 8, 4, 17, 23, 3, 16, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Kikuyu/Latin/Kenya
+ { 138, 66, 194, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 16, 17, 163, 103, 10, 0,11438,11438,11521,11521, 83, 83, 0, 0, 0, 5, 22, 198, 0, 15, 0, 3994, 4005, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 83, 83, 34, 34, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 11, 8, {82,87,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Kinyarwanda/Latin/Rwanda
+ { 141, 29, 110, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 283, 61, 76,11555,11555,11555,11555,11605,11623, 337, 349, 724, 5, 22, 120, 2964, 2, 9, 4013, 664, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 15, 7, 50, 50, 50, 50, 18, 19, 4, 4, 4, 17, 23, 1, 12, 4, 6, 6, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Konkani/Devanagari/India
+ { 142, 63, 218, 0, 0, 731, 731, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1190, 1208, 404, 127,11642,11642,11669,11669,11669,11669, 341, 353, 728, 5, 22, 247, 3257, 2, 9, 4019, 4022, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 9, 16, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 6, 4, 6, 3, 4, {75,82,87}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Korean/Korean/South Korea
+ { 142, 63, 50, 0, 0, 731, 731, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1190, 1208, 169, 0,11642,11642,11669,11669,11669,11669, 341, 353, 728, 5, 22, 248, 3263, 2, 9, 4019, 4026, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 9, 13, 5, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 3, 6, 4, 6, 3, 2, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Korean/Korean/China
+ { 142, 63, 174, 0, 0, 731, 731, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1190, 1208, 404, 127,11642,11642,11669,11669,11669,11669, 341, 353, 728, 5, 22, 247, 3269, 2, 9, 4019, 4028, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 9, 16, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 16, 4, 6, 3, 11, {75,80,87}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Korean/Korean/North Korea
+ { 144, 66, 145, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,11682,11682,11735,11735,11762,11762, 343, 355, 0, 5, 22, 127, 3285, 0, 0, 4039, 4054, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 53, 53, 27, 27, 13, 13, 6, 6, 4, 17, 23, 5, 16, 4, 0, 15, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Koyraboro Senni/Latin/Mali
+ { 145, 66, 145, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,11775,11775,11827,11827,11762,11762, 343, 355, 0, 5, 22, 127, 3285, 0, 0, 4059, 4054, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 52, 52, 27, 27, 13, 13, 6, 6, 4, 17, 23, 5, 16, 4, 0, 11, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Koyra Chiini/Latin/Mali
+ { 146, 66, 134, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 23, 38, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 0, 15, 0, 4070, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 6, 0, {76,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Kpelle/Latin/Liberia
+ { 146, 66, 102, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 215, 0, 15, 0, 4070, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 6, 0, {71,78,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Kpelle/Latin/Guinea
+ { 148, 66, 239, 0, 0, 738, 738, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1217, 49, 10, 0,11854,11854,11896,11896,11923,11923, 349, 361, 0, 5, 22, 126, 3301, 4, 20, 4076, 4092, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 13, 5, 42, 42, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 12, 5, 7, 16, 7, {84,82,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Kurdish/Latin/Turkey
+ { 149, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 11, 12, 113, 129, 10, 0,11936,11936,12024,12024,12053,12053, 351, 363, 0, 5, 22, 11, 3313, 4, 0, 4099, 4105, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 88, 88, 29, 29, 13, 13, 4, 4, 4, 17, 23, 4, 13, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Kwasio/Latin/Cameroon
+ { 150, 27, 128, 0, 0, 745, 745, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 1244, 129, 10, 0,12066,12066,12122,12122,12159,12159, 355, 367, 196, 731, 22, 251, 3326, 4, 0, 4112, 4120, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 13, 5, 56, 56, 37, 37, 13, 13, 5, 14, 4, 18, 23, 3, 15, 5, 0, 8, 10, {75,71,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Kyrgyz/Cyrillic/Kyrgyzstan
+ { 151, 66, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38,12172,12172,12172,12172, 83,12258, 0, 0, 0, 5, 22, 10, 0, 15, 0, 4130, 4142, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 86, 86, 86, 86, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 12, 22, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Lakota/Latin/United States
+ { 152, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 15, 15, 17, 17, 0, 186, 10, 0,12271,12271,12333,12333,12368,12368, 360, 381, 0, 5, 22, 121, 3341, 15, 0, 4164, 4172, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 62, 62, 35, 35, 13, 13, 3, 3, 4, 17, 23, 3, 22, 5, 0, 8, 9, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Langi/Latin/Tanzania
+ { 153, 65, 129, 0, 0, 0, 755, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1267, 129, 420, 1,12381,12381,12437,12437,12472,12472, 363, 384, 0, 5, 22, 254, 3363, 2, 65, 4181, 4181, 6, 6, 6, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 27, 4, 56, 56, 35, 35, 16, 16, 8, 8, 4, 17, 23, 1, 7, 4, 5, 3, 3, {76,65,75}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Lao/Lao/Laos
+ { 154, 66, 253, 0, 0, 406, 406, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1286, 1309, 10, 0,12488,12488,12572,12572, 83, 83, 0, 0, 0, 5, 22, 22, 83, 15, 0, 4184, 4190, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 13, 5, 84, 84, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 6, 16, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Latin/Latin/Vatican City
+ { 155, 66, 131, 0, 0, 267, 267, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1317, 49, 10, 0,12599,12670,12741,12791,12841,12841, 371, 392, 749, 5, 22, 22, 3370, 4, 0, 4206, 4214, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 13, 5, 71, 71, 50, 50, 13, 13, 14, 11, 5, 17, 23, 1, 4, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Latvian/Latin/Latvia
+ { 158, 66, 57, 0, 0, 764, 764, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,12854,12854,12953,12953,12980,12980, 385, 403, 0, 5, 22, 11, 3374, 4, 0, 4221, 4228, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 30, {67,68,70}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Lingala/Latin/Congo - Kinshasa
+ { 158, 66, 7, 0, 0, 764, 764, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,12854,12854,12953,12953,12980,12980, 385, 403, 0, 5, 22, 255, 3390, 4, 0, 4221, 4258, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 6, {65,79,65}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Lingala/Latin/Angola
+ { 158, 66, 46, 0, 0, 764, 764, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,12854,12854,12953,12953,12980,12980, 385, 403, 0, 5, 22, 11, 3406, 4, 0, 4221, 4264, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 26, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Lingala/Latin/Central African Republic
+ { 158, 66, 56, 0, 0, 764, 764, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,12854,12854,12953,12953,12980,12980, 385, 403, 0, 5, 22, 11, 3406, 4, 0, 4221, 4290, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 5, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Lingala/Latin/Congo - Brazzaville
+ { 160, 66, 137, 0, 0, 773, 773, 6, 1, 9, 2, 3, 48, 5, 63, 13, 14, 13, 14, 1343, 103, 10, 0,12993,12993,13081,13081,13101,13101, 393, 409, 754, 5, 22, 22, 3422, 4, 0, 4295, 4303, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 27, 10, 13, 5, 88, 88, 20, 20, 13, 13, 9, 6, 6, 17, 23, 1, 5, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Lithuanian/Latin/Lithuania
+ { 161, 66, 258, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 4310, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 11, 0, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Lojban/Latin/world
+ { 162, 66, 91, 0, 0, 781, 781, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 180, 11, 1,13114,13114,13166,13166,13193,13193, 402, 415, 0, 5, 22, 22, 405, 4, 0, 4321, 4335, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 4, 52, 52, 27, 27, 13, 13, 9, 10, 4, 17, 23, 1, 4, 5, 0, 14, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Lower Sorbian/Latin/Germany
+ { 163, 66, 91, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 1370, 50, 447, 469,13206,13206,13270,13270, 4510, 4510, 0, 0, 0, 5, 22, 22, 83, 4, 0, 4341, 4355, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 22, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 14, 11, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Low German/Latin/Germany
+ { 163, 66, 165, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 1370, 50, 447, 469,13206,13206,13270,13270, 4510, 4510, 0, 0, 0, 5, 22, 22, 83, 4, 0, 4341, 4366, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 22, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 14, 12, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Low German/Latin/Netherlands
+ { 164, 66, 57, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,13297,13297,13346,13346,13373,13373, 411, 425, 0, 5, 22, 11, 3427, 0, 0, 4378, 4386, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 49, 49, 27, 27, 13, 13, 5, 6, 4, 17, 23, 2, 17, 4, 0, 8, 16, {67,68,70}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Luba-Katanga/Latin/Congo - Kinshasa
+ { 165, 66, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 160, 0, 15, 0, 4402, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 15, 0, {83,69,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Lule Sami/Latin/Sweden
+ { 165, 66, 175, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 160, 0, 15, 0, 4402, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 15, 0, {78,79,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Lule Sami/Latin/Norway
+ { 166, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,13386,13386,13454,13454,13481,13481, 416, 431, 0, 5, 22, 176, 3444, 0, 0, 4417, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 68, 68, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 16, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Luo/Latin/Kenya
+ { 167, 66, 138, 0, 0, 788, 788, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 49, 10, 0,13494,13494,13558,13585, 4510, 4510, 418, 433, 461, 5, 22, 22, 83, 4, 0, 4423, 4423, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 64, 64, 27, 34, 13, 13, 5, 8, 5, 17, 23, 1, 4, 5, 0, 14, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Luxembourgish/Latin/Luxembourg
+ { 168, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 13, 14, 18, 16, 0, 186, 10, 0,13619,13619,13693,13693, 83, 83, 168, 168, 0, 5, 22, 176, 3460, 2, 97, 4437, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 74, 74, 20, 20, 13, 13, 4, 4, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Luyia/Latin/Kenya
+ { 169, 27, 140, 0, 0, 150, 150, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 0, 180, 10, 0,13713,13713,13766,13766, 3069, 3069, 423, 441, 760, 5, 22, 257, 3476, 4, 0, 4444, 4454, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 53, 53, 34, 34, 13, 13, 7, 5, 5, 17, 23, 4, 16, 5, 0, 10, 18, {77,75,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Macedonian/Cyrillic/Macedonia
+ { 170, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,13800,13800,13861,13861, 1284, 1284, 430, 446, 0, 5, 22, 121, 3492, 2, 0, 4472, 2268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Machame/Latin/Tanzania
+ { 171, 29, 110, 0, 0, 513, 522, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76,13888,13888, 8574, 8574, 8605, 8605, 88, 83, 0, 5, 22, 120, 2964, 15, 0, 4481, 664, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 63, 63, 31, 31, 18, 18, 3, 4, 4, 17, 23, 1, 12, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Maithili/Devanagari/India
+ { 172, 66, 160, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,13951,13951,14009,14009,14036,14036, 435, 455, 0, 5, 22, 261, 0, 15, 0, 4487, 4492, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 58, 58, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 0, 5, 0, 5, 10, {77,90,78}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Makhuwa-Meetto/Latin/Mozambique
+ { 173, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,14049,14049,14181,14181,14208,14208, 443, 465, 0, 5, 22, 121, 3492, 2, 9, 4502, 2268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5,132,132, 27, 27, 13, 13, 4, 5, 4, 17, 23, 3, 20, 4, 6, 10, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Makonde/Latin/Tanzania
+ { 174, 66, 141, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 103, 10, 0,14221,14221,14280,14280,14313,14313, 0, 0, 0, 5, 22, 188, 1515, 2, 0, 4512, 4520, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 59, 59, 33, 33, 13, 13, 2, 2, 4, 17, 23, 2, 6, 4, 0, 8, 12, {77,71,65}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Malagasy/Latin/Madagascar
+ { 175, 74, 110, 0, 0, 798, 811, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1393, 129, 61, 76,14326,14402,14477,14477,14517,14538, 0, 0, 765, 771, 22, 120, 3512, 2, 9, 4532, 4538, 6, 6, 13, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 76, 75, 40, 40, 21, 20, 2, 2, 6, 27, 23, 1, 11, 4, 6, 6, 6, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Malayalam/Malayalam/India
+ { 176, 66, 143, 0, 0, 584, 584, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 79, 23, 38,14558,14558,14600,14600,14627,14627, 447, 470, 749, 5, 22, 192, 3523, 2, 9, 4544, 1875, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 15, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 2, 16, 4, 6, 6, 8, {77,89,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Malay/Latin/Malaysia
+ { 176, 4, 35, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 15, 14, 17, 16, 91, 79, 61, 76,14640,14640,14640,14640, 83, 83, 0, 0, 0, 5, 22, 10, 3539, 2, 9, 4550, 4560, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 7, 15, 7, 34, 34, 34, 34, 13, 13, 2, 2, 4, 17, 23, 1, 10, 4, 6, 10, 5, {66,78,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Malay/Arabic/Brunei
+ { 176, 4, 143, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 15, 14, 17, 16, 196, 79, 61, 76,14640,14640,14640,14640, 83, 83, 0, 0, 0, 5, 22, 192, 3549, 2, 9, 4550, 4565, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 15, 7, 34, 34, 34, 34, 13, 13, 2, 2, 4, 17, 23, 2, 13, 4, 6, 10, 6, {77,89,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Malay/Arabic/Malaysia
+ { 176, 66, 35, 0, 0, 584, 584, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 91, 79, 23, 38,14558,14558,14600,14600,14627,14627, 447, 470, 749, 5, 22, 10, 3562, 2, 9, 4544, 4571, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 7, 15, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 12, 4, 6, 6, 6, {66,78,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Malay/Latin/Brunei
+ { 176, 66, 111, 0, 0, 584, 584, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 786, 78, 212, 212,14558,14558,14600,14600,14627,14627, 447, 470, 749, 5, 22, 186, 3007, 2, 0, 4544, 1776, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 2, 16, 4, 0, 6, 9, {73,68,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Malay/Latin/Indonesia
+ { 176, 66, 210, 0, 0, 584, 584, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 79, 23, 38,14558,14558,14600,14600,14627,14627, 447, 470, 749, 5, 22, 10, 3574, 2, 9, 4544, 4577, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 15, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 15, 4, 6, 6, 9, {83,71,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Malay/Latin/Singapore
+ { 177, 66, 146, 0, 0, 823, 831, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1411, 186, 10, 0,14674,14674,14736,14736,14763,14783, 0, 0, 0, 5, 22, 22, 3589, 2, 0, 4586, 1891, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 62, 62, 27, 27, 20, 19, 2, 2, 4, 17, 23, 1, 4, 4, 0, 5, 5, {69,85,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Maltese/Latin/Malta
+ { 179, 9, 110, 0, 0, 838, 838, 6, 0, 1, 2, 39, 4, 5, 10, 14, 15, 16, 17, 1434, 129, 61, 76,14802,14802,14802,14802,14860,14885, 449, 473, 0, 5, 22, 120, 3593, 15, 0, 4591, 4599, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 58, 58, 58, 58, 25, 29, 4, 5, 4, 17, 23, 1, 14, 5, 0, 8, 8, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Manipuri/Bangla/India
+ { 179, 78, 110, 0, 0, 0, 0, 6, 0, 1, 2, 75, 4, 5, 10, 14, 15, 16, 17, 265, 283, 479, 494, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 120, 0, 15, 0, 4607, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 8, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 7, 0, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Manipuri/Meitei Mayek/India
+ { 180, 66, 115, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 86, 78, 10, 0,14914,14914,14970,14970, 83, 83, 168, 168, 0, 5, 22, 94, 0, 2, 0, 4614, 4619, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 56, 56, 29, 29, 13, 13, 4, 4, 4, 17, 23, 1, 0, 4, 0, 5, 12, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Manx/Latin/Isle of Man
+ { 181, 66, 167, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 394, 23, 38,14999,14999,15046,15046,15073,15073, 0, 0, 0, 5, 22, 10, 3607, 15, 0, 4631, 4636, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 47, 47, 27, 27, 15, 15, 2, 2, 4, 17, 23, 1, 15, 5, 0, 5, 8, {78,90,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Maori/Latin/New Zealand
+ { 182, 66, 49, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 10, 0, 15, 0, 4644, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 10, 0, {67,76,80}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Mapuche/Latin/Chile
+ { 183, 29, 110, 0, 0, 849, 849, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 265, 129, 61, 76,15088,15088,15140,15140, 8605, 8605, 0, 0, 562, 5, 22, 120, 2964, 2, 9, 4654, 664, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 52, 52, 31, 31, 18, 18, 2, 2, 4, 17, 23, 1, 12, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Marathi/Devanagari/India
+ { 185, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,15171,15171,13861,13861,14208,14208, 453, 478, 0, 5, 22, 176, 3622, 2, 9, 1275, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 18, 4, 6, 3, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Masai/Latin/Kenya
+ { 185, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,15171,15171,13861,13861,14208,14208, 453, 478, 0, 5, 22, 121, 3640, 2, 9, 1275, 4659, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 6, 3, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Masai/Latin/Tanzania
+ { 186, 4, 112, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 11, 12, 19, 20, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 798, 802, 22, 0, 3661, 15, 0, 4667, 4674, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 39, 23, 0, 10, 5, 0, 7, 5, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Mazanderani/Arabic/Iran
+ { 188, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,15228,15228,15278,15278,15305,15305, 462, 484, 0, 5, 22, 176, 991, 2, 9, 4679, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 50, 50, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Meru/Latin/Kenya
+ { 189, 66, 40, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 137, 103, 10, 0,15318,15318,15318,15318,15366,15366, 0, 0, 0, 5, 22, 11, 3671, 15, 0, 4685, 4690, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 13, 5, 48, 48, 48, 48, 20, 20, 2, 2, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Meta/Latin/Cameroon
+ { 190, 66, 41, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 23, 38, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 240, 0, 15, 0, 4697, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 11, 0, {67,65,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Mohawk/Latin/Canada
+ { 191, 27, 156, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1452, 596, 98, 0,15386,15428,15470,15470,15470,15470, 464, 486, 196, 841, 22, 264, 3676, 15, 0, 4708, 4714, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35, 10, 15, 5, 42, 42, 20, 20, 20, 20, 4, 4, 4, 17, 23, 1, 13, 5, 0, 6, 6, {77,78,84}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Mongolian/Cyrillic/Mongolia
+ { 191, 83, 50, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 248, 3689, 15, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 4, 5, 0, 0, 0, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Mongolian/Mongolian/China
+ { 191, 83, 156, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1487, 596, 98, 0,15490,15490,15532,15555,15578,15578, 468, 490, 0, 5, 22, 264, 3693, 2, 0, 4720, 4720, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36, 10, 15, 5, 42, 42, 23, 23, 23, 22, 4, 5, 4, 17, 23, 1, 8, 4, 0, 6, 6, {77,78,84}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Mongolian/Mongolian/Mongolia
+ { 192, 66, 150, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,15601,15601,15648,15648,15674,15674, 0, 0, 0, 5, 22, 196, 3701, 15, 0, 4726, 4740, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 47, 47, 26, 26, 13, 13, 2, 2, 4, 17, 23, 2, 14, 5, 0, 14, 5, {77,85,82}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Morisyen/Latin/Mauritius
+ { 193, 66, 40, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 129, 10, 0,15687,15687,15760,15760,15787,15787, 472, 495, 0, 5, 22, 11, 3715, 2, 9, 4745, 4751, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 73, 73, 27, 27, 13, 13, 5, 5, 4, 17, 23, 4, 10, 4, 6, 6, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Mundang/Latin/Cameroon
+ { 194, 66, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 23, 38,15800,15800,15800,15800, 83, 83, 0, 0, 0, 5, 22, 10, 0, 15, 0, 4758, 964, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7,106,106,106,106, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 7, 13, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Muscogee/Latin/United States
+ { 195, 66, 162, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38,15906,15906,15997,15997,16019,16019, 477, 500, 0, 5, 22, 10, 3725, 2, 0, 4765, 4778, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 91, 91, 22, 22, 13, 13, 7, 5, 4, 17, 23, 1, 15, 4, 0, 13, 8, {78,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Nama/Latin/Namibia
+ { 197, 66, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 179, 0, 15, 0, 4786, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 11, 0, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Navajo/Latin/United States
+ { 199, 29, 164, 858, 0, 863, 863, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 163, 344, 10, 0,16032,16032,16085,16085,16117,16117, 484, 505, 562, 858, 22, 265, 3740, 15, 0, 4797, 4797, 5, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 5, 53, 53, 32, 32, 17, 17, 9, 7, 4, 19, 23, 4, 14, 5, 0, 6, 5, {78,80,82}, 2, 1, 7, 6, 7, 1, 2, 3 }, // Nepali/Devanagari/Nepal
+ { 199, 29, 110, 858, 0, 863, 863, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 163, 344, 61, 76,16032,16032,16085,16085,16117,16117, 484, 505, 562, 858, 22, 120, 3754, 15, 0, 4797, 664, 5, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 53, 53, 32, 32, 17, 17, 9, 7, 4, 19, 23, 1, 14, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Nepali/Devanagari/India
+ { 201, 66, 40, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 1523, 78, 10, 0,16134,16134,16134,16134, 83, 83, 493, 512, 0, 5, 22, 11, 3768, 15, 0, 4803, 4819, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 32, 8, 13, 5,110,110,110,110, 13, 13, 9, 8, 4, 17, 23, 4, 9, 5, 0, 16, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Ngiemboon/Latin/Cameroon
+ { 202, 66, 40, 870, 870, 881, 897, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 19, 20, 137, 103, 10, 0,16244,16244,16244,16244,16303,16303, 502, 520, 0, 5, 22, 11, 3777, 15, 0, 4826, 4831, 11, 11, 16, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 13, 5, 59, 59, 59, 59, 24, 24, 8, 13, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Ngomba/Latin/Cameroon
+ { 203, 66, 169, 0, 0, 906, 915, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,16327,16327,16378,16378, 83, 83, 510, 533, 877, 5, 22, 124, 3782, 2, 0, 4838, 4852, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 51, 51, 32, 32, 13, 13, 9, 8, 8, 17, 23, 1, 14, 4, 0, 14, 8, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Nigerian Pidgin/Latin/Nigeria
+ { 204, 90, 102, 0, 0, 0, 0, 6, 0, 76, 2, 77, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0,16410,16410,16470,16502,16536,16536, 519, 541, 0, 5, 22, 269, 3796, 15, 0, 4860, 4863, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 60, 60, 32, 34, 13, 13, 1, 1, 4, 17, 23, 1, 22, 5, 0, 3, 6, {71,78,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Nko/Nko/Guinea
+ { 205, 4, 112, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 4869, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 11, 0, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Northern Luri/Arabic/Iran
+ { 205, 4, 113, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 61, 76, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 43, 0, 15, 0, 4869, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 15, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 5, 0, 5, 0, 11, 0, {73,81,68}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Northern Luri/Arabic/Iraq
+ { 206, 66, 175, 0, 0, 351, 351, 6, 1, 9, 2, 3, 48, 5, 78, 15, 15, 17, 17, 163, 103, 10, 0,16549,16549,16623,16623,16655,16655, 520, 542, 0, 5, 22, 160, 3818, 4, 0, 4880, 4895, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 13, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 14, 5, 0, 15, 5, {78,79,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Northern Sami/Latin/Norway
+ { 206, 66, 83, 0, 0, 351, 351, 6, 1, 9, 2, 3, 48, 5, 78, 15, 15, 17, 17, 113, 49, 10, 0,16668,16668,16737,16737,16757,16757, 531, 185, 0, 5, 22, 22, 405, 4, 0, 4880, 4900, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 13, 5, 69, 69, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Northern Sami/Latin/Finland
+ { 206, 66, 225, 0, 0, 351, 351, 6, 1, 9, 2, 3, 48, 5, 78, 15, 15, 17, 17, 163, 103, 10, 0,16549,16549,16623,16623,16655,16655, 520, 542, 0, 5, 22, 160, 3832, 4, 0, 4880, 4906, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 13, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 14, 5, 0, 15, 6, {83,69,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Northern Sami/Latin/Sweden
+ { 207, 66, 216, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,16770,16770,16833,16833,16859,16859, 0, 0, 0, 5, 22, 9, 0, 2, 0, 4912, 4928, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 63, 63, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 16, 12, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Northern Sotho/Latin/South Africa
+ { 208, 66, 261, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,16872,16872,16921,16921,16948,16948, 0, 0, 0, 5, 22, 179, 3846, 2, 9, 4940, 2434, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 10, 8, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // North Ndebele/Latin/Zimbabwe
+ { 209, 66, 175, 0, 0, 289, 289, 6, 1, 9, 2, 3, 48, 5, 10, 11, 12, 16, 17, 698, 49, 10, 0, 4788, 4788,16961,16961, 4874, 4874, 168, 168, 0, 5, 22, 160, 3863, 15, 58, 4950, 4962, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 50, 50, 34, 34, 13, 13, 4, 4, 4, 17, 23, 2, 13, 5, 7, 12, 5, {78,79,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Norwegian Bokmal/Latin/Norway
+ { 209, 66, 224, 0, 0, 289, 289, 6, 1, 9, 2, 3, 48, 5, 10, 11, 12, 16, 17, 698, 49, 10, 0, 4788, 4788,16961,16961, 4874, 4874, 168, 168, 0, 5, 22, 160, 3863, 15, 58, 4950, 4967, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 50, 50, 34, 34, 13, 13, 4, 4, 4, 17, 23, 2, 13, 5, 7, 12, 21, {78,79,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Norwegian Bokmal/Latin/Svalbard and Jan Mayen
+ { 210, 66, 175, 0, 0, 289, 289, 6, 1, 9, 2, 3, 48, 5, 10, 11, 12, 16, 17, 698, 49, 502, 0,16995,16995,17045,17072, 4874, 4874, 533, 555, 0, 5, 22, 160, 3863, 4, 0, 4988, 5001, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 19, 5, 50, 50, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 13, 5, 0, 13, 5, {78,79,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Norwegian Nynorsk/Latin/Norway
+ { 211, 66, 219, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 187, 521, 38,17099,17099,17177,17177,17214,17214, 537, 559, 0, 5, 22, 94, 0, 2, 9, 5006, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 15, 7, 78, 78, 37, 37, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 6, 9, 0, {83,83,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Nuer/Latin/South Sudan
+ { 212, 66, 142, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 23, 38,17227,17227,17293,17293, 83, 83, 0, 0, 0, 5, 22, 0, 1521, 15, 0, 5015, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 66, 66, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 15, 5, 0, 6, 0, {77,87,75}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Nyanja/Latin/Malawi
+ { 213, 66, 243, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 4053, 4053, 4126, 4126, 4153, 4153, 0, 0, 0, 5, 22, 147, 805, 2, 0, 5021, 983, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 73, 73, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 10, 6, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // Nyankole/Latin/Uganda
+ { 214, 66, 84, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 11, 12, 1555, 79, 10, 536,17320,17320,17320,17320,17376,17376, 0, 0, 376, 232, 249, 22, 405, 0, 45, 5031, 807, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 7, 13, 6, 56, 56, 56, 56, 20, 20, 2, 2, 6, 17, 23, 1, 4, 4, 6, 7, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Occitan/Latin/France
+ { 214, 66, 220, 0, 0, 414, 414, 6, 0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 79, 99, 1,17396,17396,17453,17453,17480,17480, 0, 0, 376, 232, 249, 22, 405, 0, 0, 5031, 5038, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 14, 4, 57, 57, 27, 27, 13, 13, 2, 2, 6, 17, 23, 1, 4, 4, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Occitan/Latin/Spain
+ { 215, 91, 110, 0, 0, 923, 931, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 61, 76,17493,17493,17546,17546,17578,17578, 0, 0, 885, 5, 22, 120, 3876, 2, 9, 5045, 5050, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 53, 53, 32, 32, 17, 17, 2, 2, 5, 17, 23, 1, 12, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Odia/Odia/India
+ { 220, 66, 77, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 78, 23, 38,17595,17595,17649,17649, 83, 83, 539, 561, 0, 5, 22, 1, 3888, 2, 0, 5054, 5060, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 17, 4, 0, 6, 10, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Oromo/Latin/Ethiopia
+ { 220, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 78, 10, 0,17595,17595,17649,17649,17676,17676, 539, 561, 0, 5, 22, 176, 0, 2, 0, 5054, 5070, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 6, 8, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Oromo/Latin/Kenya
+ { 221, 101, 248, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 61, 76,17689,17689,17689,17689, 83,17869, 0, 0, 0, 5, 22, 10, 0, 15, 0, 5078, 964, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7,180,180,180,180, 13, 20, 2, 2, 4, 17, 23, 1, 0, 5, 0, 12, 13, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Osage/Osage/United States
+ { 222, 27, 90, 0, 0, 938, 938, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 1576, 49, 10, 0,17889,17949,18009,18036,18063,18063, 541, 563, 0, 5, 22, 0, 3905, 15, 0, 5090, 5094, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 13, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 3, 5, 0, 4, 11, {71,69,76}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Ossetic/Cyrillic/Georgia
+ { 222, 27, 193, 0, 0, 938, 938, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 1576, 49, 10, 0,17889,17949,18009,18036,18063,18063, 541, 563, 0, 5, 22, 133, 3908, 15, 0, 5090, 5105, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 13, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 3, 5, 0, 4, 6, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Ossetic/Cyrillic/Russia
+ { 226, 66, 62, 0, 0, 143, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 394, 10, 0,18076,18076,18076,18076,18138,18138, 0, 0, 0, 5, 22, 0, 3911, 15, 0, 5111, 5121, 6, 6, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 62, 62, 62, 62, 20, 20, 2, 2, 4, 17, 23, 0, 6, 5, 0, 10, 6, {65,78,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Papiamento/Latin/Curacao
+ { 226, 66, 13, 0, 0, 143, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 394, 10, 0,18076,18076,18076,18076,18138,18138, 0, 0, 0, 5, 22, 0, 3917, 15, 0, 5111, 1227, 6, 6, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 62, 62, 62, 62, 20, 20, 2, 2, 4, 17, 23, 0, 15, 5, 0, 10, 5, {65,87,71}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Papiamento/Latin/Aruba
+ { 227, 4, 1, 661, 661, 947, 956, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 1599, 505, 99, 1,18158,18158,18158,18158, 83, 83, 556, 578, 890, 5, 22, 270, 3932, 2, 9, 5127, 5131, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 14, 4, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 1, 6, 4, 6, 4, 9, {65,70,78}, 0, 0, 6, 4, 5, 1, 3, 3 }, // Pashto/Arabic/Afghanistan
+ { 227, 4, 178, 661, 661, 947, 956, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 1599, 505, 61, 76,18158,18158,18158,18158, 83, 83, 556, 578, 890, 5, 22, 196, 3938, 2, 9, 5127, 5140, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 15, 7, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 2, 15, 4, 6, 4, 7, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Pashto/Arabic/Pakistan
+ { 228, 4, 112, 964, 964, 971, 979, 67, 21, 22, 23, 40, 82, 37, 44, 11, 12, 19, 20, 113, 505, 99, 1,18196,18196,18196,18196,18244,18244, 560, 582, 798, 5, 22, 271, 3953, 103, 109, 5147, 4674, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 14, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 17, 23, 4, 10, 6, 8, 5, 5, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Persian/Arabic/Iran
+ { 228, 4, 1, 964, 964, 971, 979, 67, 21, 22, 23, 40, 82, 37, 44, 11, 12, 19, 20, 113, 505, 99, 1,18196,18196,18196,18196,18244,18244, 560, 582, 798, 5, 22, 270, 3963, 15, 109, 5152, 5131, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 14, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 17, 23, 1, 16, 5, 8, 3, 9, {65,70,78}, 0, 0, 6, 4, 5, 1, 3, 3 }, // Persian/Arabic/Afghanistan
+ { 230, 66, 187, 0, 0, 143, 143, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 11, 12, 0, 50, 10, 0,18257,18257,18315,18315,18348,18361, 0, 0, 311, 5, 22, 275, 3979, 4, 20, 5155, 5161, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 9, 13, 5, 58, 58, 33, 33, 13, 13, 2, 2, 5, 17, 23, 2, 12, 5, 7, 6, 6, {80,76,78}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Polish/Latin/Poland
+ { 231, 66, 32, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 186, 10, 0,18374,18374,18452,18452,18486,18486, 0, 0, 0, 5, 22, 9, 3991, 15, 0, 5167, 5176, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 13, 5, 78, 78, 34, 34, 13, 13, 2, 2, 5, 17, 23, 2, 15, 5, 0, 9, 6, {66,82,76}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Portuguese/Latin/Brazil
+ { 231, 66, 7, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 255, 4006, 4, 20, 5167, 5182, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 15, 5, 7, 9, 6, {65,79,65}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Portuguese/Latin/Angola
+ { 231, 66, 43, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 243, 4021, 4, 20, 5167, 5188, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 20, 5, 7, 9, 10, {67,86,69}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Cape Verde
+ { 231, 66, 73, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 11, 4041, 4, 20, 5167, 5198, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 17, 5, 7, 9, 16, {88,65,70}, 0, 0, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Equatorial Guinea
+ { 231, 66, 101, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 127, 4058, 4, 20, 5167, 5214, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 5, 18, 5, 7, 9, 12, {88,79,70}, 0, 0, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Guinea-Bissau
+ { 231, 66, 138, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 22, 405, 4, 20, 5167, 5226, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 4, 5, 7, 9, 10, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Luxembourg
+ { 231, 66, 139, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 23, 38,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 151, 4076, 4, 20, 5167, 5236, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 15, 7, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 15, 5, 7, 9, 19, {77,79,80}, 2, 1, 7, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Macao
+ { 231, 66, 160, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 261, 4091, 4, 20, 5167, 5255, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 19, 5, 7, 9, 10, {77,90,78}, 2, 1, 7, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Mozambique
+ { 231, 66, 188, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 22, 405, 4, 20, 5265, 5282, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 4, 5, 7, 17, 8, {69,85,82}, 2, 1, 7, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Portugal
+ { 231, 66, 204, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 277, 4110, 4, 20, 5167, 5290, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 28, 5, 7, 9, 19, {83,84,78}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Sao Tome and Principe
+ { 231, 66, 226, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 0, 4138, 4, 20, 5167, 5309, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 0, 12, 5, 7, 9, 5, {67,72,70}, 2, 0, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Switzerland
+ { 231, 66, 232, 0, 0, 414, 414, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 78, 10, 0,18374,18374,18499,18499,18486,18486, 569, 590, 0, 5, 22, 179, 4150, 4, 20, 5167, 5314, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 24, 5, 7, 9, 11, {85,83,68}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Portuguese/Latin/Timor-Leste
+ { 232, 66, 187, 0, 0, 986, 986, 6, 1, 9, 2, 3, 4, 5, 10, 13, 14, 13, 14, 1619, 49, 10, 0,18547,18547,18615,18615,18642,18642, 577, 598, 0, 5, 22, 275, 0, 4, 0, 5325, 5334, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 68, 68, 27, 27, 13, 13, 10, 14, 4, 17, 23, 2, 0, 5, 0, 9, 4, {80,76,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Prussian/Latin/Poland
+ { 233, 41, 110, 0, 0, 994, 994, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76,18655,18655,18711,18711,18746,18746, 587, 612, 895, 5, 22, 120, 4174, 15, 0, 5338, 5344, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 56, 56, 35, 35, 22, 22, 6, 6, 4, 17, 23, 1, 11, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Punjabi/Gurmukhi/India
+ { 233, 4, 178, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 786, 186, 61, 76,18768,18768,18768,18768, 83, 83, 0, 0, 0, 5, 22, 78, 4185, 15, 0, 5348, 5140, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 10, 15, 7, 36, 36, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 7, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Punjabi/Arabic/Pakistan
+ { 234, 66, 184, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 23, 38,18804,18804,18856,18856,18883,18883, 168, 168, 0, 5, 22, 279, 4191, 15, 0, 5354, 5362, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 11, 5, 0, 8, 4, {80,69,78}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Quechua/Latin/Peru
+ { 234, 66, 28, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 23, 38,18804,18804,18856,18856,18883,18883, 168, 168, 0, 5, 22, 281, 4202, 15, 0, 5354, 5366, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 9, 5, 0, 8, 7, {66,79,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Quechua/Latin/Bolivia
+ { 234, 66, 70, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 23, 38,18804,18804,18856,18856,18883,18883, 168, 168, 0, 5, 22, 10, 4211, 15, 0, 5354, 5373, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 15, 5, 0, 8, 7, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Quechua/Latin/Ecuador
+ { 235, 66, 192, 0, 0, 1003, 1003, 6, 1, 0, 2, 3, 4, 5, 10, 13, 15, 11, 12, 0, 49, 10, 0,18896,18896,18943,18943, 6778, 6778, 168, 168, 899, 5, 22, 283, 4226, 4, 20, 5380, 5386, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 47, 47, 33, 33, 13, 13, 4, 4, 4, 17, 23, 3, 12, 5, 7, 6, 7, {82,79,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Romanian/Latin/Romania
+ { 235, 66, 154, 0, 0, 1003, 1003, 6, 1, 0, 2, 3, 4, 5, 10, 13, 15, 11, 12, 0, 49, 10, 0,18896,18896,18976,18976,19003,19003, 168, 168, 899, 5, 22, 18, 4238, 4, 20, 5380, 5393, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 47, 47, 27, 27, 15, 15, 4, 4, 4, 17, 23, 1, 15, 5, 7, 6, 17, {77,68,76}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Romanian/Latin/Moldova
+ { 236, 66, 226, 0, 0, 414, 414, 6, 0, 17, 2, 3, 48, 5, 10, 11, 12, 19, 20, 1646, 394, 10, 0,19018,19018,19073,19073,19095,19095, 0, 0, 0, 5, 22, 0, 4253, 4, 0, 5410, 5419, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 13, 5, 55, 55, 22, 22, 13, 13, 2, 2, 5, 17, 23, 0, 13, 5, 0, 9, 6, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Romansh/Latin/Switzerland
+ { 237, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,19108,19108,19172,19172,14208,14208, 593, 618, 0, 5, 22, 121, 4266, 2, 0, 5425, 2268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 64, 64, 28, 28, 13, 13, 8, 7, 4, 17, 23, 3, 18, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Rombo/Latin/Tanzania
+ { 238, 66, 38, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 15, 15, 17, 17, 113, 129, 10, 0,19200,19200,19288,19288, 83, 83, 601, 625, 0, 5, 22, 182, 4284, 0, 0, 5434, 5442, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 88, 88, 33, 33, 13, 13, 5, 5, 4, 17, 23, 3, 20, 4, 0, 8, 8, {66,73,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Rundi/Latin/Burundi
+ { 239, 27, 193, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 49, 10, 0,19321,19321,19382,19382,19402,19402, 0, 0, 196, 841, 22, 133, 4304, 4, 0, 5450, 5457, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 61, 61, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 16, 5, 0, 7, 6, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Russian/Cyrillic/Russia
+ { 239, 27, 22, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 49, 10, 0,19321,19321,19382,19382,19402,19402, 0, 0, 196, 841, 22, 1, 4320, 4, 0, 5450, 618, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 61, 61, 20, 20, 13, 13, 2, 2, 5, 17, 23, 2, 17, 5, 0, 7, 8, {66,89,78}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Russian/Cyrillic/Belarus
+ { 239, 27, 123, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 49, 10, 0,19321,19321,19382,19382,19402,19402, 0, 0, 196, 841, 22, 244, 4337, 4, 0, 5450, 5463, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 61, 61, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 15, 5, 0, 7, 9, {75,90,84}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Russian/Cyrillic/Kazakhstan
+ { 239, 27, 128, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 49, 10, 0,19321,19321,19382,19382,19402,19402, 0, 0, 196, 841, 22, 251, 4352, 4, 0, 5450, 5472, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 61, 61, 20, 20, 13, 13, 2, 2, 5, 17, 23, 3, 14, 5, 0, 7, 8, {75,71,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Russian/Cyrillic/Kyrgyzstan
+ { 239, 27, 154, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 49, 10, 0,19321,19321,19382,19382,19402,19402, 0, 0, 196, 841, 22, 18, 4366, 4, 0, 5450, 5480, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 61, 61, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 14, 5, 0, 7, 7, {77,68,76}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Russian/Cyrillic/Moldova
+ { 239, 27, 244, 0, 0, 150, 150, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 350, 49, 10, 0,19321,19321,19382,19382,19402,19402, 0, 0, 196, 841, 22, 286, 4380, 4, 0, 5450, 5487, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 13, 5, 61, 61, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 17, 5, 0, 7, 7, {85,65,72}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Russian/Cyrillic/Ukraine
+ { 240, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,13800,13800,13861,13861, 1284, 1284, 430, 446, 0, 5, 22, 121, 3492, 0, 0, 5494, 2268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Rwa/Latin/Tanzania
+ { 241, 66, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 59, 78, 23, 38,19415,19415,19470,19470,19497,19497, 0, 0, 0, 5, 22, 6, 0, 2, 0, 5500, 34, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 15, 7, 55, 55, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 4, 7, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Saho/Latin/Eritrea
+ { 242, 27, 193, 0, 0, 1011, 1011, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 14, 1669, 344, 10, 0,19510,19510,19580,19580,19600,19600, 606, 630, 903, 908, 22, 133, 4397, 4, 0, 5504, 5513, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 6, 13, 5, 70, 70, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 20, 5, 0, 9, 9, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Sakha/Cyrillic/Russia
+ { 243, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,19613,19613,19717,19717,19744,19744, 608, 632, 0, 5, 22, 176, 4417, 2, 9, 5522, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5,104,104, 27, 27, 13, 13, 7, 5, 4, 17, 23, 3, 18, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Samburu/Latin/Kenya
+ { 245, 66, 46, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 113, 129, 10, 0,19757,19757,19822,19822,19849,19849, 615, 637, 0, 5, 22, 11, 4435, 2, 65, 5530, 5535, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 4, 5, 5, 22, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Sango/Latin/Central African Republic
+ { 246, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,19862,19862,19921,19921,19948,19948, 617, 639, 0, 5, 22, 121, 4453, 0, 0, 5557, 5566, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 59, 59, 27, 27, 13, 13, 9, 9, 4, 17, 23, 3, 18, 4, 0, 9, 9, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Sangu/Latin/Tanzania
+ { 247, 29, 110, 0, 0, 1022, 1032, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76,19961,19961, 8574, 8574, 8605, 8605, 484, 505, 0, 5, 22, 120, 4471, 15, 0, 5575, 5587, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 66, 66, 31, 31, 18, 18, 9, 7, 4, 17, 23, 1, 15, 5, 0, 12, 5, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Sanskrit/Devanagari/India
+ { 248, 93, 110, 0, 0, 0, 0, 6, 0, 1, 2, 84, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76,20027,20027,20068,20068,20093,20093, 626, 648, 0, 5, 22, 120, 4486, 15, 0, 5592, 5599, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 41, 41, 25, 25, 13, 13, 5, 5, 4, 17, 23, 1, 16, 5, 0, 7, 6, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Santali/Ol Chiki/India
+ { 248, 29, 110, 0, 0, 0, 0, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 120, 0, 15, 0, 5605, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 8, 0, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Santali/Devanagari/India
+ { 249, 66, 117, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 1699, 186, 10, 0,20106,20106,20160,20160,20187,20187, 0, 0, 0, 5, 22, 22, 4502, 4, 0, 5613, 813, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 31, 10, 13, 5, 54, 54, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 0, 5, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Sardinian/Latin/Italy
+ { 251, 66, 160, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 10, 0,20200,20200,20254,20254,20281,20281, 0, 0, 0, 5, 22, 261, 4506, 0, 0, 5618, 5255, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 13, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 21, 4, 0, 4, 10, {77,90,78}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Sena/Latin/Mozambique
+ { 252, 27, 207, 0, 0, 150, 150, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0,20294,20294,20345,20345, 2891, 2891, 0, 0, 925, 5, 22, 0, 4527, 4, 20, 5622, 5628, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 51, 51, 27, 27, 13, 13, 2, 2, 7, 17, 23, 0, 12, 5, 7, 6, 6, {82,83,68}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Serbian/Cyrillic/Serbia
+ { 252, 27, 29, 0, 0, 150, 150, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0, 2809, 2809, 2864, 2864, 2891, 2891, 104, 653, 925, 5, 22, 137, 4539, 4, 20, 5622, 713, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 55, 55, 27, 27, 13, 13, 11, 8, 7, 17, 23, 2, 40, 5, 7, 6, 19, {66,65,77}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Serbian/Cyrillic/Bosnia and Herzegovina
+ { 252, 27, 126, 0, 0, 150, 150, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0,20294,20294,20345,20345, 2891, 2891, 0, 0, 925, 5, 22, 22, 4579, 4, 20, 5622, 5634, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 51, 51, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 4, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Serbian/Cyrillic/Kosovo
+ { 252, 27, 157, 0, 0, 150, 150, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0,20372,20372,20345,20345, 2891, 2891, 104, 653, 925, 5, 22, 22, 4579, 4, 20, 5622, 5640, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 54, 54, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 4, 5, 7, 6, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Serbian/Cyrillic/Montenegro
+ { 252, 66, 29, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0, 2699, 2699, 2756, 2756, 2783, 2783, 631, 661, 218, 5, 22, 135, 597, 4, 20, 5649, 686, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 57, 57, 27, 27, 13, 13, 11, 8, 7, 17, 23, 2, 40, 5, 7, 6, 19, {66,65,77}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Serbian/Latin/Bosnia and Herzegovina
+ { 252, 66, 126, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0,20426,20426,20479,20479, 2783, 2783, 0, 0, 218, 5, 22, 22, 4583, 4, 20, 5649, 5655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 53, 53, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 4, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Serbian/Latin/Kosovo
+ { 252, 66, 157, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0,20506,20506,20479,20479, 2783, 2783, 631, 661, 218, 5, 22, 22, 4583, 4, 20, 5649, 5661, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 56, 56, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 4, 5, 7, 6, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Serbian/Latin/Montenegro
+ { 252, 66, 207, 0, 0, 143, 143, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 16, 16, 404, 454, 10, 0,20426,20426,20479,20479, 2783, 2783, 0, 0, 218, 5, 22, 0, 4587, 4, 20, 5649, 5670, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 7, 13, 5, 53, 53, 27, 27, 13, 13, 2, 2, 7, 17, 23, 0, 12, 5, 7, 6, 6, {82,83,68}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Serbian/Latin/Serbia
+ { 253, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,20562,20562,20624,20624,20651,20651, 642, 669, 0, 5, 22, 121, 4599, 0, 0, 5676, 2268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 62, 62, 27, 27, 13, 13, 5, 8, 4, 17, 23, 3, 20, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Shambala/Latin/Tanzania
+ { 254, 66, 261, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 15, 15, 17, 17, 163, 103, 10, 0,20664,20664,20718,20718,20745,20745, 0, 0, 0, 5, 22, 179, 4619, 2, 9, 5685, 2434, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 15, 4, 6, 8, 8, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Shona/Latin/Zimbabwe
+ { 255, 141, 50, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0,20758,20758,20785,20785,20805,20805, 647, 677, 0, 5, 22, 150, 0, 15, 0, 5693, 5696, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 3, 2, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Sichuan Yi/Yi/China
+ { 256, 66, 117, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0,20818,20818,20818,20818, 83, 83, 0, 0, 0, 5, 22, 22, 0, 15, 0, 5698, 3728, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 62, 62, 62, 62, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 9, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Sicilian/Latin/Italy
+ { 257, 66, 77, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 59, 78, 23, 38,20880,20880,20930,20930,20957,20957, 0, 0, 0, 5, 22, 1, 0, 2, 0, 5707, 5718, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 15, 7, 50, 50, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 4, 0, 11, 11, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Sidamo/Latin/Ethiopia
+ { 258, 66, 187, 0, 0, 143, 143, 6, 1, 9, 2, 3, 4, 5, 10, 13, 15, 12, 11, 0, 49, 10, 0,20970,20970,21030,21030,13193,13193, 649, 679, 311, 5, 22, 275, 0, 15, 0, 5729, 5161, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 60, 60, 27, 27, 13, 13, 11, 11, 5, 17, 23, 2, 0, 5, 0, 7, 6, {80,76,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Silesian/Latin/Poland
+ { 259, 4, 178, 0, 0, 1041, 1049, 67, 21, 22, 23, 25, 26, 28, 59, 14, 15, 16, 17, 549, 103, 61, 76,21057,21057,21057,21057,21091,21091, 660, 690, 932, 938, 22, 196, 4634, 4, 0, 5736, 5740, 6, 6, 8, 7, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 18, 10, 15, 7, 34, 34, 34, 34, 30, 30, 11, 11, 6, 25, 23, 2, 12, 5, 0, 4, 7, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Sindhi/Arabic/Pakistan
+ { 259, 29, 110, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 61, 76,21121,21148,21189,21211,21239,21239, 671, 701, 0, 5, 22, 120, 4646, 15, 0, 5747, 664, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 27, 41, 22, 28, 20, 20, 8, 6, 4, 17, 23, 1, 17, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Sindhi/Devanagari/India
+ { 260, 119, 221, 0, 0, 1056, 1065, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 212, 212,21259,21259,21320,21320,21358,21358, 679, 707, 963, 968, 22, 287, 4663, 2, 9, 5753, 5758, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 61, 61, 38, 38, 18, 18, 5, 4, 5, 42, 23, 3, 17, 4, 6, 5, 11, {76,75,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Sinhala/Sinhala/Sri Lanka
+ { 261, 66, 83, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 22, 0, 15, 0, 5769, 5779, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 10, 12, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Skolt Sami/Latin/Finland
+ { 262, 66, 212, 0, 0, 781, 282, 6, 1, 9, 2, 3, 4, 5, 6, 13, 14, 18, 16, 698, 423, 11, 1,21376,21376,21427,21427,21447,21447, 0, 0, 311, 5, 22, 22, 405, 4, 20, 5791, 5801, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 4, 51, 51, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 4, 5, 7, 10, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Slovak/Latin/Slovakia
+ { 263, 66, 213, 0, 0, 1073, 1073, 6, 1, 0, 2, 3, 48, 5, 6, 13, 14, 18, 16, 404, 423, 10, 0,21460,21460,21511,21511,21545,21545, 172, 711, 50, 5, 22, 22, 4680, 4, 20, 5810, 5821, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 51, 51, 34, 34, 13, 13, 4, 4, 4, 17, 23, 1, 4, 5, 7, 11, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Slovenian/Latin/Slovenia
+ { 264, 66, 243, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,21558,21558,21622,21622,21656,21656, 684, 715, 0, 5, 22, 147, 2829, 4, 0, 5830, 3330, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 64, 64, 34, 34, 13, 13, 6, 6, 4, 17, 23, 3, 19, 5, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // Soga/Latin/Uganda
+ { 265, 66, 215, 0, 0, 1081, 1081, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 78, 23, 38,21669,21669,21715,21715,21746,21746, 690, 721, 1010, 1016, 22, 93, 4684, 2, 9, 5837, 5845, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 1, 20, 4, 6, 8, 10, {83,79,83}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Somali/Latin/Somalia
+ { 265, 66, 67, 0, 0, 1081, 1081, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 78, 23, 38,21669,21669,21715,21715,21746,21746, 690, 721, 1010, 1016, 22, 3, 4704, 2, 9, 5837, 5855, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 13, 4, 6, 8, 7, {68,74,70}, 0, 0, 6, 6, 7, 1, 3, 3 }, // Somali/Latin/Djibouti
+ { 265, 66, 77, 0, 0, 1081, 1081, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 78, 23, 38,21669,21669,21715,21715,21746,21746, 690, 721, 1010, 1016, 22, 1, 4717, 2, 9, 5837, 5862, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 2, 15, 4, 6, 8, 8, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Somali/Latin/Ethiopia
+ { 265, 66, 124, 0, 0, 1081, 1081, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 78, 10, 0,21669,21669,21715,21715,21746,21746, 690, 721, 1010, 1016, 22, 176, 4732, 2, 9, 5837, 1307, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 15, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Somali/Latin/Kenya
+ { 266, 4, 112, 0, 0, 0, 0, 67, 21, 22, 23, 25, 26, 28, 59, 11, 12, 19, 20, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 4, 0, 5870, 0, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 11, 0, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Southern Kurdish/Arabic/Iran
+ { 266, 4, 113, 0, 0, 0, 0, 67, 21, 22, 23, 25, 26, 28, 59, 11, 12, 19, 20, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 4, 0, 5870, 0, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 11, 0, {73,81,68}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Southern Kurdish/Arabic/Iraq
+ { 267, 66, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 160, 0, 15, 0, 5881, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 19, 0, {83,69,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Southern Sami/Latin/Sweden
+ { 267, 66, 175, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 160, 0, 15, 0, 5881, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 19, 0, {78,79,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Southern Sami/Latin/Norway
+ { 268, 66, 216, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,21760,21760,21820,21820, 83, 83, 0, 0, 0, 5, 22, 9, 0, 2, 0, 4912, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 60, 60, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 7, 0, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Southern Sotho/Latin/South Africa
+ { 268, 66, 133, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 23, 38,21760,21760,21820,21820, 83, 83, 0, 0, 0, 5, 22, 9, 0, 2, 0, 4912, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 60, 60, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 7, 0, {90,65,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Southern Sotho/Latin/Lesotho
+ { 269, 66, 216, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,21846,21846,21911,21911, 83, 83, 0, 0, 0, 5, 22, 9, 0, 2, 0, 4940, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 65, 65, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 10, 0, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // South Ndebele/Latin/South Africa
+ { 270, 66, 220, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 99, 1,21937,21937,21989,21989,18883,18883, 132, 128, 0, 5, 22, 22, 405, 4, 0, 5900, 455, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 14, 4, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 4, 5, 0, 17, 6, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Spanish/Latin/Spain
+ { 270, 66, 11, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 10, 4747, 15, 58, 5900, 5917, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 14, 5, 7, 7, 9, {65,82,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Argentina
+ { 270, 66, 24, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 10, 0,21937,21937,21989,21989, 6778, 6778, 168, 168, 0, 5, 22, 10, 4761, 2, 0, 5900, 5926, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 13, 5, 52, 52, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 14, 4, 0, 7, 6, {66,90,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Belize
+ { 270, 66, 28, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 281, 4775, 2, 0, 5900, 5366, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 2, 9, 4, 0, 7, 7, {66,79,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Bolivia
+ { 270, 66, 32, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 10, 0,21937,21937,21989,21989, 6778, 6778, 168, 168, 0, 5, 22, 9, 4784, 2, 0, 5900, 5176, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 13, 5, 52, 52, 27, 27, 13, 13, 4, 4, 5, 17, 23, 2, 14, 4, 0, 7, 6, {66,82,76}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Brazil
+ { 270, 66, 42, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 99, 1,21937,21937,21989,21989,18883,18883, 132, 128, 0, 5, 22, 22, 405, 4, 0, 5900, 5932, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 14, 4, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 4, 5, 0, 7, 8, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Spanish/Latin/Canary Islands
+ { 270, 66, 47, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 99, 1,21937,21937,21989,21989,18883,18883, 132, 128, 0, 5, 22, 22, 405, 4, 0, 5900, 5940, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 14, 4, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 4, 5, 0, 7, 15, {69,85,82}, 2, 1, 1, 6, 7, 2, 3, 3 }, // Spanish/Latin/Ceuta and Melilla
+ { 270, 66, 49, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 394, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 10, 4798, 2, 65, 5900, 5955, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 12, 4, 5, 7, 5, {67,76,80}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Chile
+ { 270, 66, 54, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 79, 23, 38,21937,21937,21989,21989, 9387,22016, 132, 128, 0, 5, 22, 10, 4810, 15, 0, 5900, 5960, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 15, 5, 0, 7, 8, {67,79,80}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Colombia
+ { 270, 66, 59, 0, 0, 68, 68, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 290, 4825, 2, 0, 5900, 5968, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 19, 4, 0, 7, 10, {67,82,67}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Costa Rica
+ { 270, 66, 61, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 168, 168, 0, 5, 22, 10, 4844, 2, 0, 5900, 5978, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 11, 4, 0, 7, 4, {67,85,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Cuba
+ { 270, 66, 69, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 291, 4855, 2, 9, 5900, 5982, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 3, 15, 4, 6, 7, 20, {68,79,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Dominican Republic
+ { 270, 66, 70, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 10, 4870, 2, 65, 5900, 5373, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 20, 4, 5, 7, 7, {85,83,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Ecuador
+ { 270, 66, 72, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 10, 4870, 2, 0, 5900, 6002, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 20, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/El Salvador
+ { 270, 66, 73, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 99, 1,21937,21937,21989,21989,18883,18883, 132, 128, 0, 5, 22, 11, 4890, 2, 0, 5900, 6013, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 14, 4, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 4, 28, 4, 0, 7, 17, {88,65,70}, 0, 0, 1, 6, 7, 2, 3, 3 }, // Spanish/Latin/Equatorial Guinea
+ { 270, 66, 99, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 79, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 246, 4918, 2, 0, 5900, 6030, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 7, 4, 0, 7, 9, {71,84,81}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Guatemala
+ { 270, 66, 106, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1730, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 18, 4925, 2, 0, 5900, 6039, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 17, 4, 0, 7, 8, {72,78,76}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Honduras
+ { 270, 66, 130, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 168, 168, 0, 5, 22, 0, 0, 2, 0, 6047, 6070, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 5, 17, 23, 0, 0, 4, 0, 23, 13, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Latin America
+ { 270, 66, 152, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 78, 23, 38,21937,21937,21989,21989, 6778, 6778, 168, 168, 0, 5, 22, 10, 4942, 2, 0, 6083, 6100, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 13, 4, 0, 17, 6, {77,88,78}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Mexico
+ { 270, 66, 168, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 294, 4955, 2, 0, 5900, 6106, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 2, 20, 4, 0, 7, 9, {78,73,79}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Nicaragua
+ { 270, 66, 181, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 1121, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 296, 4975, 2, 0, 5900, 6115, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 3, 15, 4, 0, 7, 6, {80,65,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Panama
+ { 270, 66, 183, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 299, 4990, 15, 86, 5900, 6121, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 3, 17, 5, 6, 7, 8, {80,89,71}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Paraguay
+ { 270, 66, 184, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 79, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 279, 5007, 15, 0, 5900, 5362, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 2, 11, 5, 0, 7, 4, {80,69,78}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Peru
+ { 270, 66, 185, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989,18883,18883, 132, 128, 0, 5, 22, 146, 5018, 4, 0, 5900, 6129, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 13, 5, 0, 7, 9, {80,72,80}, 2, 1, 7, 6, 7, 2, 3, 3 }, // Spanish/Latin/Philippines
+ { 270, 66, 189, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 1121, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 10, 4870, 2, 0, 5900, 2080, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 20, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Puerto Rico
+ { 270, 66, 248, 0, 0, 68, 68, 6, 0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 168, 168, 0, 5, 22, 10, 4870, 2, 0, 5900, 6138, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 15, 7, 52, 52, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 20, 4, 0, 7, 14, {85,83,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/United States
+ { 270, 66, 250, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 10, 5031, 15, 58, 5900, 6152, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 1, 13, 5, 7, 7, 7, {85,89,85}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Spanish/Latin/Uruguay
+ { 270, 66, 254, 0, 0, 68, 68, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 958, 129, 23, 38,21937,21937,21989,21989, 6778, 6778, 132, 128, 0, 5, 22, 302, 5044, 2, 65, 5900, 6159, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 15, 7, 52, 52, 27, 27, 13, 13, 5, 5, 5, 17, 23, 4, 16, 4, 5, 7, 9, {86,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Spanish/Latin/Venezuela
+ { 271, 135, 159, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 15, 113, 129, 10, 0,22029,22029,22076,22076, 83, 83, 692, 723, 0, 5, 22, 0, 5060, 0, 0, 6168, 6176, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 47, 47, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 8, 6, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Standard Moroccan Tamazight/Tifinagh/Morocco
+ { 272, 66, 111, 0, 0, 1090, 1103, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 213, 213,22105,22105,22148,22148, 9291, 9291, 0, 0, 0, 5, 22, 186, 5074, 2, 0, 6182, 1776, 6, 6, 13, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 4, 43, 43, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 15, 4, 0, 10, 9, {73,68,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Sundanese/Latin/Indonesia
+ { 273, 66, 230, 0, 0, 566, 566, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 1198, 1198, 1198, 1198, 83, 83, 0, 0, 749, 1033, 22, 121, 3492, 15, 0, 6192, 2268, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 20, 5, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Swahili/Latin/Tanzania
+ { 273, 66, 57, 0, 0, 566, 566, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 1198, 1198, 1198, 1198, 83, 83, 0, 0, 749, 1033, 22, 11, 5089, 15, 0, 6192, 6201, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 2, 16, 5, 0, 9, 32, {67,68,70}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Swahili/Latin/Congo - Kinshasa
+ { 273, 66, 124, 0, 0, 566, 566, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 1198, 1198, 1198, 1198, 83, 83, 0, 0, 749, 1033, 22, 176, 991, 15, 0, 6192, 1307, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 17, 5, 0, 9, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Swahili/Latin/Kenya
+ { 273, 66, 243, 0, 0, 566, 566, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0, 1198, 1198, 1198, 1198, 83, 83, 0, 0, 749, 1033, 22, 147, 5105, 15, 0, 6192, 983, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 18, 5, 0, 9, 6, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // Swahili/Latin/Uganda
+ { 274, 66, 216, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,22175,22175,22242,22242, 83, 83, 0, 0, 0, 5, 22, 9, 0, 2, 0, 6233, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 67, 67, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 7, 0, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Swati/Latin/South Africa
+ { 274, 66, 76, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 23, 38,22175,22175,22242,22242, 83, 83, 0, 0, 0, 5, 22, 155, 0, 2, 0, 6233, 6240, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 67, 67, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 7, 8, {83,90,76}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Swati/Latin/Eswatini
+ { 275, 66, 225, 0, 0, 1115, 1115, 6, 1, 9, 2, 3, 48, 5, 63, 15, 15, 17, 17, 113, 103, 10, 0,22268,22268,22317,22317, 4874, 4874, 698, 731, 0, 5, 22, 160, 5123, 4, 0, 6248, 6255, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 13, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 2, 12, 5, 0, 7, 7, {83,69,75}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Swedish/Latin/Sweden
+ { 275, 66, 2, 0, 0, 1115, 1115, 6, 1, 9, 2, 3, 48, 5, 63, 15, 15, 17, 17, 113, 103, 10, 0,22268,22268,22317,22317, 4874, 4874, 698, 731, 0, 5, 22, 22, 405, 4, 0, 6248, 6262, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 13, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 7, 5, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Swedish/Latin/Aland Islands
+ { 275, 66, 83, 0, 0, 1115, 1115, 6, 1, 9, 2, 3, 48, 5, 63, 15, 15, 17, 17, 113, 103, 10, 0,22268,22268,22317,22317, 4874, 4874, 698, 731, 0, 5, 22, 22, 405, 4, 0, 6248, 1698, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 13, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Swedish/Latin/Finland
+ { 276, 66, 226, 0, 0, 463, 463, 6, 0, 17, 2, 3, 48, 5, 10, 11, 12, 19, 20, 404, 49, 10, 0,22345,22345,22407,22407, 4510, 4510, 700, 733, 0, 5, 22, 0, 5135, 4, 0, 6267, 6267, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 0, 16, 5, 0, 16, 7, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Swiss German/Latin/Switzerland
+ { 276, 66, 84, 0, 0, 463, 463, 6, 0, 17, 2, 3, 48, 5, 10, 11, 12, 19, 20, 404, 49, 10, 0,22345,22345,22407,22407, 4510, 4510, 700, 733, 0, 5, 22, 22, 83, 4, 0, 6267, 6283, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 1, 4, 5, 0, 16, 10, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Swiss German/Latin/France
+ { 276, 66, 136, 0, 0, 463, 463, 6, 0, 17, 2, 3, 48, 5, 10, 11, 12, 19, 20, 404, 49, 10, 0,22345,22345,22407,22407, 4510, 4510, 700, 733, 0, 5, 22, 0, 5135, 4, 0, 6267, 6293, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 0, 16, 5, 0, 16, 13, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Swiss German/Latin/Liechtenstein
+ { 277, 123, 113, 1124, 1124, 1124, 1124, 6, 0, 1, 2, 3, 4, 5, 10, 15, 14, 17, 16, 1757, 395, 61, 76,22434,22434,22486,22486,22515,22515, 712, 744, 1084, 5, 22, 0, 0, 15, 0, 6306, 6312, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 9, 15, 7, 52, 52, 29, 29, 13, 13, 4, 4, 4, 17, 23, 0, 0, 5, 0, 6, 4, {73,81,68}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Syriac/Syriac/Iraq
+ { 277, 123, 227, 1124, 1124, 1124, 1124, 6, 0, 1, 2, 3, 4, 5, 10, 15, 14, 17, 16, 1757, 395, 61, 76,22434,22434,22486,22486,22515,22515, 712, 744, 1084, 5, 22, 99, 0, 15, 0, 6306, 6316, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 9, 15, 7, 52, 52, 29, 29, 13, 13, 4, 4, 4, 17, 23, 5, 0, 5, 0, 6, 5, {83,89,80}, 0, 0, 6, 5, 6, 1, 3, 3 }, // Syriac/Syriac/Syria
+ { 278, 135, 159, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 15, 113, 129, 10, 0,22528,22528,22076,22076, 83, 83, 692, 723, 0, 5, 22, 0, 5060, 0, 0, 6321, 6176, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 46, 46, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 7, 6, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tachelhit/Tifinagh/Morocco
+ { 278, 66, 159, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 13, 15, 113, 129, 10, 0,22574,22574,22621,22621, 83, 83, 716, 748, 0, 5, 22, 0, 5151, 0, 0, 6328, 6338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 47, 47, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 10, 6, {77,65,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tachelhit/Latin/Morocco
+ { 280, 127, 255, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 306, 0, 15, 0, 6344, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 4, 0, {86,78,68}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Tai Dam/Tai Viet/Vietnam
+ { 281, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,22650,22650,22754,22754,22781,22781, 722, 756, 0, 5, 22, 176, 991, 2, 9, 6348, 1307, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5,104,104, 27, 27, 13, 13, 10, 10, 4, 17, 23, 3, 17, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Taita/Latin/Kenya
+ { 282, 27, 229, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 12, 11, 16, 17, 786, 78, 10, 0,22794,22794,22848,22848,22875,22875, 0, 0, 0, 5, 22, 307, 5165, 4, 0, 6355, 6361, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 6, 5, 0, 6, 10, {84,74,83}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tajik/Cyrillic/Tajikistan
+ { 283, 129, 110, 0, 0, 1130, 1130, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 127, 127,22888,22888,22936,22936,22974,22974, 0, 766, 1088, 5, 22, 120, 5171, 2, 9, 6371, 6376, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 48, 48, 38, 38, 19, 19, 2, 8, 7, 17, 23, 1, 13, 4, 6, 5, 7, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Tamil/Tamil/India
+ { 283, 129, 143, 0, 0, 1130, 1130, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 127, 127,22888,22888,22936,22936,22974,22974, 0, 766, 1088, 5, 22, 192, 5184, 2, 9, 6371, 6383, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 48, 48, 38, 38, 19, 19, 2, 8, 7, 17, 23, 2, 17, 4, 6, 5, 7, {77,89,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tamil/Tamil/Malaysia
+ { 283, 129, 210, 0, 0, 1130, 1130, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 127, 127,22888,22888,22936,22936,22974,22974, 0, 766, 1088, 5, 22, 10, 5201, 2, 9, 6371, 6390, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 48, 48, 38, 38, 19, 19, 2, 8, 7, 17, 23, 1, 17, 4, 6, 5, 11, {83,71,68}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Tamil/Tamil/Singapore
+ { 283, 129, 221, 0, 0, 1130, 1130, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 10, 0,22888,22888,22936,22936,22974,22974, 0, 766, 1088, 5, 22, 311, 5218, 2, 9, 6371, 6401, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 5, 48, 48, 38, 38, 19, 19, 2, 8, 7, 17, 23, 3, 13, 4, 6, 5, 6, {76,75,82}, 2, 1, 1, 6, 7, 1, 2, 3 }, // Tamil/Tamil/Sri Lanka
+ { 284, 66, 228, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 137, 103, 23, 38,22993,22993,23164,23164,23191,23191, 0, 0, 0, 5, 22, 314, 5231, 15, 0, 6407, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 15, 7,171,171, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 11, 5, 0, 12, 0, {84,87,68}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Taroko/Latin/Taiwan
+ { 285, 66, 170, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,11682,11682,11735,11735,11762,11762, 732, 774, 0, 5, 22, 127, 3285, 0, 0, 6419, 6432, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 53, 53, 27, 27, 13, 13, 8, 10, 4, 17, 23, 5, 16, 4, 0, 13, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Tasawaq/Latin/Niger
+ { 286, 27, 193, 0, 0, 1143, 1143, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1775, 49, 11, 1,23204,23204,23259,23259,23294,23294, 0, 0, 0, 5, 22, 133, 5242, 4, 0, 6437, 5457, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 12, 4, 55, 55, 35, 35, 13, 13, 2, 2, 4, 17, 23, 1, 11, 5, 0, 5, 6, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tatar/Cyrillic/Russia
+ { 287, 131, 110, 0, 0, 1152, 1152, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1798, 394, 61, 76,23307,23307,23366,23366,23397,23397, 0, 0, 1095, 1102, 22, 120, 5253, 2, 9, 6442, 6448, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 15, 7, 59, 59, 31, 31, 17, 17, 2, 2, 7, 29, 23, 1, 14, 4, 6, 6, 8, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Telugu/Telugu/India
+ { 288, 66, 243, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,23414,23414,23482,23482,23509,23509, 740, 784, 0, 5, 22, 147, 5267, 2, 9, 6456, 983, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 6, 6, 6, {85,71,88}, 0, 0, 1, 7, 7, 1, 3, 3 }, // Teso/Latin/Uganda
+ { 288, 66, 124, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,23414,23414,23482,23482,23509,23509, 740, 784, 0, 5, 22, 176, 5288, 2, 9, 6456, 6462, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 20, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Teso/Latin/Kenya
+ { 289, 133, 231, 24, 24, 1163, 1171, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1816, 129, 542, 0,23522,23522,23589,23589,23611,23611, 749, 790, 1131, 5, 22, 317, 5308, 2, 9, 6467, 6467, 5, 5, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 6, 31, 5, 67, 67, 22, 22, 15, 15, 10, 10, 4, 17, 23, 1, 3, 4, 6, 3, 3, {84,72,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Thai/Thai/Thailand
+ { 290, 134, 50, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1835, 103, 10, 0,23626,23626,23704,23704,23754,23754, 759, 800, 0, 5, 22, 150, 5311, 15, 0, 6470, 6478, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 78, 78, 50, 50, 26, 26, 7, 8, 4, 17, 23, 1, 6, 5, 0, 8, 6, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tibetan/Tibetan/China
+ { 290, 134, 110, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1835, 103, 61, 76,23626,23626,23704,23704,23754,23754, 759, 800, 0, 5, 22, 120, 5317, 15, 0, 6470, 6484, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 15, 7, 78, 78, 50, 50, 26, 26, 7, 8, 4, 17, 23, 1, 12, 5, 0, 8, 7, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Tibetan/Tibetan/India
+ { 291, 33, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1858, 78, 61, 76,23780,23780,23820,23820,23846,23846, 0, 0, 0, 5, 22, 6, 0, 2, 0, 6491, 671, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 8, 15, 7, 40, 40, 26, 26, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 3, 4, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tigre/Ethiopic/Eritrea
+ { 292, 33, 77, 38, 38, 1178, 1178, 6, 0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 1879, 78, 61, 76,23859,23859,23887,23887,23907,23907, 766, 808, 0, 5, 22, 1, 112, 2, 0, 6494, 143, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 15, 7, 28, 28, 20, 20, 13, 13, 4, 4, 4, 17, 23, 2, 2, 4, 0, 4, 5, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Tigrinya/Ethiopic/Ethiopia
+ { 292, 33, 74, 38, 38, 1178, 1178, 6, 0, 1, 2, 3, 4, 5, 10, 16, 17, 14, 15, 1879, 78, 61, 76,23859,23859,23887,23887,23907,23907, 766, 808, 0, 5, 22, 6, 5329, 2, 0, 6494, 671, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 15, 7, 28, 28, 20, 20, 13, 13, 4, 4, 4, 17, 23, 3, 3, 4, 0, 4, 4, {69,82,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tigrinya/Ethiopic/Eritrea
+ { 294, 66, 182, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 787, 78, 573, 589,23920,23920,23964,23964, 83, 83, 0, 0, 0, 5, 22, 0, 0, 4, 0, 6498, 6507, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 16, 8, 44, 44, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 9, 13, {80,71,75}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tok Pisin/Latin/Papua New Guinea
+ { 295, 66, 235, 1185, 1185, 1185, 1185, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 23, 38,23991,23991,24050,24050,24078,24078, 770, 812, 1135, 1140, 1199, 205, 5332, 15, 0, 6520, 2283, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 15, 7, 59, 59, 28, 28, 13, 13, 10, 6, 5, 59, 65, 2, 17, 5, 0, 13, 5, {84,79,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tongan/Latin/Tonga
+ { 296, 66, 216, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,24091,24091,24162,24162, 83, 83, 0, 0, 0, 5, 22, 9, 0, 15, 0, 6533, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 71, 71, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 8, 0, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Tsonga/Latin/South Africa
+ { 297, 66, 216, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,24188,24188,24251,24251, 83, 83, 0, 0, 0, 5, 22, 9, 0, 2, 0, 6541, 6549, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 63, 63, 31, 31, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 8, 13, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Tswana/Latin/South Africa
+ { 297, 66, 30, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,24188,24188,24251,24251, 83, 83, 0, 0, 0, 5, 22, 153, 0, 2, 0, 6541, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 63, 63, 31, 31, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 8, 0, {66,87,80}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Tswana/Latin/Botswana
+ { 298, 66, 239, 0, 0, 1193, 1193, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1896, 50, 10, 0,24282,24282,24335,24335,24362,24362, 780, 818, 185, 5, 22, 126, 5349, 2, 9, 6562, 6568, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 5, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 11, 4, 6, 6, 7, {84,82,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Turkish/Latin/Turkey
+ { 298, 66, 63, 0, 0, 1193, 1193, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1896, 50, 23, 38,24282,24282,24335,24335,24362,24362, 780, 818, 185, 5, 22, 22, 83, 2, 9, 6562, 6575, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 15, 7, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 4, 6, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Turkish/Latin/Cyprus
+ { 299, 66, 240, 0, 0, 1201, 1201, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 14, 15, 1896, 49, 10, 0,24375,24428,24481,24508,24535,24535, 782, 820, 1264, 5, 22, 0, 5360, 4, 0, 6581, 6593, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 13, 5, 53, 53, 27, 27, 13, 13, 13, 14, 4, 17, 23, 0, 14, 5, 0, 12, 12, {84,77,84}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Turkmen/Latin/Turkmenistan
+ { 301, 66, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 137, 155, 10, 0,24548,24548,24589,24589, 83, 83, 0, 0, 0, 5, 22, 124, 5374, 15, 0, 6605, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 41, 41, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 5, 0, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Tyap/Latin/Nigeria
+ { 303, 27, 244, 0, 0, 117, 117, 6, 1, 9, 2, 3, 4, 5, 85, 11, 12, 13, 14, 1912, 49, 10, 0,24616,24671, 3049, 3049, 4289, 4289, 795, 834, 1268, 841, 22, 286, 5378, 4, 0, 6610, 6620, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 13, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 17, 5, 0, 10, 7, {85,65,72}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Ukrainian/Cyrillic/Ukraine
+ { 304, 66, 91, 0, 0, 781, 781, 6, 1, 0, 2, 3, 4, 5, 10, 13, 14, 18, 16, 404, 180, 11, 597,24726,24726,24778,24778,24805,24805, 402, 836, 1273, 5, 22, 22, 405, 4, 0, 6627, 6642, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 12, 52, 52, 27, 27, 13, 13, 9, 9, 5, 17, 23, 1, 4, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Upper Sorbian/Latin/Germany
+ { 305, 4, 178, 661, 661, 1209, 1219, 6, 0, 1, 2, 3, 35, 37, 10, 15, 14, 17, 16, 1934, 129, 61, 76,24818,24818,24818,24818, 83, 83, 0, 0, 1278, 1282, 22, 196, 5395, 2, 9, 6648, 5140, 6, 6, 10, 9, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 6, 15, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 2, 14, 4, 6, 4, 7, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Urdu/Arabic/Pakistan
+ { 305, 4, 110, 661, 661, 1209, 1219, 6, 21, 22, 2, 40, 35, 41, 44, 15, 14, 17, 16, 1934, 129, 61, 76,24818,24818,24818,24818, 83, 83, 0, 0, 1278, 1282, 22, 120, 5409, 2, 9, 6648, 6652, 6, 6, 10, 9, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 15, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 1, 12, 4, 6, 4, 5, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Urdu/Arabic/India
+ { 306, 4, 50, 0, 0, 323, 333, 6, 0, 1, 2, 3, 4, 5, 10, 12, 11, 20, 19, 1952, 103, 10, 0,24853,24853,24907,24907,24927,24927, 797, 845, 0, 5, 22, 145, 5421, 2, 9, 6657, 6665, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 54, 54, 20, 20, 13, 13, 12, 12, 4, 17, 23, 1, 11, 4, 6, 8, 5, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Uyghur/Arabic/China
+ { 307, 66, 251, 0, 0, 1228, 1228, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 17, 16, 1969, 78, 99, 0,24940,24940,25000,25000,25031,25031, 360, 857, 185, 5, 22, 318, 5432, 2, 9, 6670, 6676, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 14, 5, 60, 60, 31, 31, 13, 13, 2, 2, 4, 17, 23, 4, 17, 4, 6, 6, 11, {85,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Uzbek/Latin/Uzbekistan
+ { 307, 4, 1, 0, 0, 0, 0, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 1987, 505, 99, 1,18196,18196,25044,25044, 83, 83, 0, 0, 0, 5, 22, 270, 3963, 4, 0, 6687, 5131, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 33, 8, 14, 4, 48, 48, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 9, {65,70,78}, 0, 0, 6, 4, 5, 1, 3, 3 }, // Uzbek/Arabic/Afghanistan
+ { 307, 27, 251, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1008, 78, 98, 0,25064,25064,25116,25116,25143,25143, 809, 859, 0, 5, 22, 322, 5449, 4, 0, 6693, 6700, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 15, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 14, 5, 0, 7, 10, {85,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Uzbek/Cyrillic/Uzbekistan
+ { 308, 139, 134, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 61, 76,25156,25156,25156,25156, 83, 83, 0, 0, 0, 5, 22, 10, 5463, 2, 9, 6710, 6712, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 29, 29, 29, 29, 13, 13, 2, 2, 4, 17, 23, 1, 8, 4, 6, 2, 4, {76,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Vai/Vai/Liberia
+ { 308, 66, 134, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38,25185,25185,25185,25185, 83, 83, 0, 0, 0, 5, 22, 10, 5471, 2, 9, 6716, 6719, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 47, 47, 47, 47, 13, 13, 2, 2, 4, 17, 23, 1, 13, 4, 6, 3, 8, {76,82,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Vai/Latin/Liberia
+ { 309, 66, 216, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 16, 17, 14, 15, 163, 103, 10, 0,25232,25232,25301,25301, 83, 83, 0, 0, 0, 5, 22, 9, 0, 2, 0, 6727, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 69, 69, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 9, 0, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Venda/Latin/South Africa
+ { 310, 66, 255, 0, 0, 1236, 1236, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 10, 0,25327,25327,25381,25381,25413,25413, 811, 861, 0, 5, 22, 306, 5484, 4, 0, 6736, 6746, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 5, 54, 54, 32, 32, 20, 20, 2, 2, 4, 17, 23, 1, 13, 5, 0, 10, 8, {86,78,68}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Vietnamese/Latin/Vietnam
+ { 311, 66, 258, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 2020, 103, 10, 0,25433,25433,25475,25495,25522,25522, 0, 0, 0, 5, 22, 0, 0, 15, 0, 6754, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 42, 42, 20, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 7, 0, {0,0,0}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Volapuk/Latin/world
+ { 312, 66, 230, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,13800,13800,13861,13861, 1284, 1284, 430, 446, 0, 5, 22, 121, 3492, 2, 0, 6761, 2268, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 8, 8, {84,90,83}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Vunjo/Latin/Tanzania
+ { 313, 66, 23, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 22, 0, 15, 0, 6769, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 5, 0, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Walloon/Latin/Belgium
+ { 314, 66, 226, 0, 0, 463, 463, 6, 1, 17, 2, 3, 4, 5, 10, 11, 12, 19, 20, 404, 103, 10, 0,25535,25535,25587,25587,25614,25614, 0, 0, 0, 5, 22, 0, 0, 15, 0, 6774, 6780, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 13, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 6, 6, {67,72,70}, 2, 0, 1, 6, 7, 1, 3, 3 }, // Walser/Latin/Switzerland
+ { 315, 66, 15, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 241, 0, 15, 0, 6786, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 8, 0, {65,85,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Warlpiri/Latin/Australia
+ { 316, 66, 246, 0, 0, 1244, 1255, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 78, 10, 0,25627,25627,25703,25731,25760,25760, 813, 863, 1302, 5, 22, 94, 5497, 2, 9, 6794, 6801, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 76, 76, 28, 29, 14, 14, 2, 2, 7, 17, 23, 1, 12, 4, 6, 7, 16, {71,66,80}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Welsh/Latin/United Kingdom
+ { 317, 4, 178, 661, 661, 971, 979, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 196, 5509, 15, 0, 6817, 0, 6, 6, 8, 7, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 13, 5, 0, 14, 0, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Western Balochi/Arabic/Pakistan
+ { 317, 4, 1, 661, 661, 971, 979, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 270, 5522, 15, 0, 6817, 0, 6, 6, 8, 7, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 17, 5, 0, 14, 0, {65,70,78}, 0, 0, 6, 4, 5, 1, 3, 3 }, // Western Balochi/Arabic/Afghanistan
+ { 317, 4, 112, 661, 661, 971, 979, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 271, 5539, 15, 0, 6817, 0, 6, 6, 8, 7, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 11, 5, 0, 14, 0, {73,82,82}, 0, 0, 6, 5, 5, 1, 3, 3 }, // Western Balochi/Arabic/Iran
+ { 317, 4, 176, 661, 661, 971, 979, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 6817, 6831, 6, 6, 8, 7, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 14, 5, {79,77,82}, 3, 0, 6, 5, 6, 1, 3, 3 }, // Western Balochi/Arabic/Oman
+ { 317, 4, 245, 661, 661, 971, 979, 67, 21, 22, 23, 40, 35, 41, 44, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 15, 0, 6817, 6836, 6, 6, 8, 7, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 14, 19, {65,69,68}, 2, 1, 6, 6, 7, 1, 3, 3 }, // Western Balochi/Arabic/United Arab Emirates
+ { 318, 66, 165, 0, 0, 16, 16, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 394, 10, 0,25774,25774,25827,25827, 83, 83, 0, 0, 0, 5, 22, 22, 83, 15, 58, 6855, 6860, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 53, 53, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 7, 5, 8, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Western Frisian/Latin/Netherlands
+ { 319, 33, 77, 0, 0, 0, 0, 6, 0, 17, 2, 3, 4, 5, 10, 14, 15, 16, 17, 2043, 78, 61, 76,25847,25847,25847,25847,25873,25873, 0, 0, 0, 5, 22, 1, 105, 2, 0, 6868, 143, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 15, 7, 26, 26, 26, 26, 13, 13, 2, 2, 4, 17, 23, 2, 9, 4, 0, 5, 5, {69,84,66}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Wolaytta/Ethiopic/Ethiopia
+ { 320, 66, 206, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 2065, 394, 10, 0,25886,25886,25935,25935,25935,25935, 732, 865, 0, 5, 22, 127, 5550, 15, 0, 6873, 2999, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 49, 49, 27, 27, 27, 27, 3, 3, 4, 17, 23, 5, 29, 5, 0, 5, 8, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Wolof/Latin/Senegal
+ { 321, 66, 216, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 10, 0,25962,25962,26022,26049,26078,26098, 0, 0, 0, 5, 22, 9, 5579, 2, 0, 6878, 6886, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 5, 60, 60, 27, 29, 20, 21, 2, 2, 4, 17, 23, 1, 25, 4, 0, 8, 15, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Xhosa/Latin/South Africa
+ { 322, 66, 40, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 11, 12, 113, 129, 10, 0,26119,26119,26189,26189,26209,26209, 815, 868, 0, 5, 22, 11, 0, 4, 20, 6901, 6907, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 70, 70, 20, 20, 13, 13, 8, 8, 4, 17, 23, 4, 0, 5, 7, 6, 7, {88,65,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Yangben/Latin/Cameroon
+ { 323, 47, 244, 0, 0, 1265, 1265, 6, 0, 1, 2, 3, 4, 5, 10, 15, 15, 17, 17, 2082, 78, 10, 0,26222,26222,26222,26222, 83, 83, 823, 876, 0, 5, 22, 286, 0, 15, 0, 6914, 6920, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 13, 5, 53, 53, 53, 53, 13, 13, 11, 10, 4, 17, 23, 1, 0, 5, 0, 6, 9, {85,65,72}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Yiddish/Hebrew/Ukraine
+ { 324, 66, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 2101, 129, 10, 1,26275,26318,26386,26386,26418,26418, 834, 886, 1309, 1320, 22, 124, 5604, 2, 9, 6929, 6939, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 3, 43, 68, 32, 32, 13, 13, 5, 5, 11, 37, 23, 1, 14, 4, 6, 10, 8, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Yoruba/Latin/Nigeria
+ { 324, 66, 25, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 2101, 129, 10, 1,26431,26474,26542,26542,26574,26574, 839, 891, 1357, 1320, 22, 127, 5618, 2, 9, 6929, 6947, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 3, 43, 68, 32, 32, 13, 13, 5, 5, 11, 37, 23, 5, 26, 4, 6, 10, 6, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Yoruba/Latin/Benin
+ { 325, 66, 170, 0, 0, 0, 0, 6, 0, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 129, 10, 0,26587,26587,11735,11735,26639,26639, 732, 774, 0, 5, 22, 127, 3285, 0, 0, 6953, 6432, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 52, 52, 27, 27, 13, 13, 8, 10, 4, 17, 23, 5, 16, 4, 0, 10, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Zarma/Latin/Niger
+ { 326, 66, 50, 0, 0, 1274, 1274, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0,26652,26652,26652,26652, 83, 83, 844, 896, 0, 5, 22, 150, 5644, 15, 0, 6963, 6972, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 89, 89, 89, 89, 13, 13, 7, 12, 4, 17, 23, 1, 10, 5, 0, 9, 8, {67,78,89}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Zhuang/Latin/China
+ { 327, 66, 216, 0, 0, 1285, 1294, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 549, 567, 10, 0,26741,26741,26814,26814,26841,26841, 0, 0, 0, 5, 22, 9, 5654, 2, 9, 6980, 6987, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 5, 73, 73, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 20, 4, 6, 7, 17, {90,65,82}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Zulu/Latin/South Africa
+ { 328, 66, 32, 0, 0, 1302, 1302, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 2117, 186, 10, 0,26854,26854,26940,26940,26974,26974, 0, 0, 1368, 5, 22, 9, 5674, 15, 0, 7004, 7011, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 13, 5, 86, 86, 34, 34, 20, 20, 2, 2, 7, 17, 23, 2, 12, 5, 0, 7, 6, {66,82,76}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Kaingang/Latin/Brazil
+ { 329, 66, 32, 0, 0, 1311, 1311, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 10, 0,26994,26994,27058,27058,27085,27085, 0, 0, 1375, 5, 22, 9, 5686, 15, 0, 7017, 7025, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 64, 64, 27, 27, 13, 13, 2, 2, 8, 17, 23, 2, 15, 5, 0, 8, 6, {66,82,76}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Nheengatu/Latin/Brazil
+ { 329, 66, 54, 0, 0, 1311, 1311, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38,26994,26994,27058,27058,27085,27085, 132, 128, 1375, 5, 22, 10, 5701, 15, 0, 7031, 7038, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 64, 64, 27, 27, 13, 13, 5, 5, 8, 17, 23, 1, 17, 5, 0, 7, 8, {67,79,80}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Nheengatu/Latin/Colombia
+ { 329, 66, 254, 0, 0, 1311, 1311, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 186, 23, 38,26994,26994,27058,27058,27085,27085, 132, 128, 1375, 5, 22, 302, 5718, 15, 0, 7031, 7046, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 64, 64, 27, 27, 13, 13, 5, 5, 8, 17, 23, 4, 22, 5, 0, 7, 9, {86,69,83}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Nheengatu/Latin/Venezuela
+ { 330, 29, 110, 0, 0, 0, 0, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 163, 103, 61, 76,27098,27098,27098,27098, 83, 83, 851, 83, 0, 5, 22, 120, 0, 15, 0, 7055, 664, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 54, 54, 54, 54, 13, 13, 4, 4, 4, 17, 23, 1, 0, 5, 0, 8, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Haryanvi/Devanagari/India
+ { 331, 66, 91, 0, 0, 915, 915, 6, 1, 0, 2, 3, 4, 5, 10, 14, 15, 16, 17, 404, 78, 10, 0,27152,27152,27208,27208, 83, 83, 0, 0, 0, 5, 22, 22, 83, 15, 0, 7063, 7073, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 13, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 0, 10, 9, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Northern Frisian/Latin/Germany
+ { 332, 29, 110, 0, 0, 0, 0, 6, 0, 1, 2, 49, 4, 5, 10, 14, 15, 16, 17, 163, 103, 61, 76, 8522, 8522, 8522, 8522, 83, 83, 855, 908, 0, 5, 22, 120, 0, 15, 0, 7082, 664, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 52, 52, 52, 52, 13, 13, 5, 4, 4, 17, 23, 1, 0, 5, 0, 9, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 3, 3 }, // Rajasthani/Devanagari/India
+ { 333, 27, 193, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 133, 0, 15, 0, 7091, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 12, 0, {82,85,66}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Moksha/Cyrillic/Russia
+ { 334, 66, 258, 0, 0, 0, 0, 6, 1, 9, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0,27235,27235,27235,27235, 83, 83, 860, 912, 0, 5, 22, 0, 0, 2, 0, 7103, 7112, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 90, 90, 90, 90, 13, 13, 12, 12, 4, 17, 23, 0, 0, 4, 0, 9, 6, {0,0,0}, 2, 1, 1, 6, 7, 1, 2, 2 }, // Toki Pona/Latin/world
+ { 335, 66, 214, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0,27325,27325,27325,27325, 83, 83, 0, 0, 0, 5, 22, 10, 0, 15, 0, 7118, 7123, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 46, 46, 46, 46, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 5, 13, {83,66,68}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Pijin/Latin/Solomon Islands
+ { 336, 66, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 124, 0, 15, 0, 7136, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 5, 0, {78,71,78}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Obolo/Latin/Nigeria
+ { 337, 4, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 367, 383,27371,27371,27417,27417, 83, 83, 0, 0, 0, 5, 22, 196, 5395, 15, 0, 7141, 5140, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 16, 8, 46, 46, 24, 24, 13, 13, 2, 2, 4, 17, 23, 2, 13, 5, 0, 5, 7, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Baluchi/Arabic/Pakistan
+ { 337, 66, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 265, 129, 573, 589,27441,27441,27511,27511, 83, 83, 0, 0, 0, 5, 22, 196, 5740, 15, 0, 7146, 7153, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 16, 8, 70, 70, 26, 26, 13, 13, 2, 2, 4, 17, 23, 2, 14, 5, 0, 7, 8, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Baluchi/Latin/Pakistan
+ { 338, 66, 117, 0, 0, 414, 414, 6, 1, 0, 2, 3, 4, 5, 10, 11, 12, 14, 15, 2140, 78, 10, 0,27537,27537,27591,27591,27625,27625, 0, 0, 0, 5, 22, 22, 405, 4, 20, 7161, 3728, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 8, 13, 5, 54, 54, 34, 34, 13, 13, 2, 2, 4, 17, 23, 1, 4, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Ligurian/Latin/Italy
+ { 339, 142, 161, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 10, 1, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 134, 0, 15, 0, 7167, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 13, 4, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 18, 0, {77,77,75}, 0, 0, 7, 6, 7, 1, 3, 3 }, // Rohingya/Hanifi/Myanmar
+ { 339, 142, 20, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 163, 103, 61, 76, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 132, 0, 15, 0, 7167, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 15, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 18, 0, {66,68,84}, 2, 1, 7, 6, 7, 1, 3, 3 }, // Rohingya/Hanifi/Bangladesh
+ { 340, 4, 178, 1321, 1321, 1326, 1335, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 1934, 129, 61, 76,27638,27638,27638,27638,27695,27695, 0, 0, 1278, 1282, 22, 196, 5395, 15, 0, 7185, 5140, 5, 5, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 15, 7, 57, 57, 57, 57, 13, 13, 2, 2, 4, 20, 23, 2, 14, 5, 0, 7, 7, {80,75,82}, 2, 0, 7, 6, 7, 1, 3, 3 }, // Torwali/Arabic/Pakistan
+ { 341, 66, 25, 0, 0, 566, 566, 6, 1, 9, 2, 3, 4, 5, 10, 11, 12, 14, 15, 2161, 2178, 10, 0,27708,27708,27766,27766,27800,27800, 872, 924, 0, 5, 22, 127, 5754, 15, 86, 7192, 7203, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 13, 5, 58, 58, 34, 34, 20, 20, 13, 13, 4, 17, 23, 5, 33, 5, 6, 11, 5, {88,79,70}, 0, 0, 1, 6, 7, 1, 3, 3 }, // Anii/Latin/Benin
+ { 342, 29, 110, 0, 0, 1343, 1353, 6, 0, 1, 2, 3, 4, 5, 10, 14, 15, 16, 17, 0, 129, 61, 76,27820,27820,27872,27872,27905,27905, 885, 937, 0, 5, 22, 120, 5787, 2, 0, 7208, 664, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 15, 7, 52, 52, 33, 33, 18, 18, 6, 11, 4, 17, 23, 1, 14, 4, 0, 7, 4, {73,78,82}, 2, 1, 7, 7, 7, 1, 2, 3 }, // Kangri/Devanagari/India
+ { 343, 66, 117, 0, 0, 414, 414, 6, 1, 68, 2, 3, 4, 5, 10, 14, 15, 16, 17, 113, 78, 10, 0,27923,27923,27967,27967,27625,27625, 0, 0, 0, 5, 22, 155, 405, 117, 0, 7215, 3728, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 13, 5, 44, 44, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 4, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7, 1, 3, 3 }, // Venetian/Latin/Italy
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0 } // trailing zeros
};
-static const char16_t list_pattern_part_data[] = {
-0x25, 0x31, 0x2c, 0x20, 0x25, 0x32, 0x3b, 0x25, 0x31, 0x20, 0x65, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x68,
-0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x1363, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x25, 0x32, 0x61b, 0x25, 0x31, 0x20, 0x587, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x20, 0x986, 0x9f0, 0x9c1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x259, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x65, 0x74, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xf51,
-0xf44, 0xf0b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x68, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0x25, 0x32, 0x25, 0x31, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x20, 0x25, 0x32, 0x104a, 0x25, 0x31, 0x20, 0x456,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x200b, 0x25,
-0x32, 0x25, 0x31, 0x20, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x548c, 0x25, 0x32, 0x25, 0x31,
-0x53ca, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x6b, 0x61, 0x6a, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6a, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x74, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x10d3, 0x10d0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x3ba,
-0x3b1, 0x3b9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xa85,
-0xaa8, 0xac7, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d5, 0x25, 0x32, 0x25,
-0x31, 0x2c, 0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe9,
-0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x6e,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6c, 0x61,
-0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6c, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xcae, 0xca4, 0xccd,
-0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436,
-0x4d9, 0x43d, 0x435, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x430, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbc0f,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xfb, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xec1, 0xea5, 0xeb0, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x75, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6d, 0x70, 0xe9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69,
-0x72, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x25, 0x32, 0x20, 0xd0e, 0xd28, 0xd4d, 0xd28, 0xd3f, 0xd35, 0x25, 0x31, 0x20,
-0xd15, 0xd42, 0xd1f, 0xd3e, 0xd24, 0xd46, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x906, 0x923, 0x93f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xb13, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xb13, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x60c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xa05, 0xa24, 0xa47, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, 0xdc4,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0xa0, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x69, 0x79, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x61, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, 0xbae,
-0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4bb, 0x4d9, 0x43c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f,
-0xc41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, 0x65,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0xe0, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x2c, 0x20, 0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x5d0, 0x5d5, 0x5df, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6b, 0x70,
-0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61,
-0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x6b, 0x6b, 0x65,
-0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6b, 0x6b, 0x65, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x13a0,
-0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x486, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0x61, 0x28, 0x6e, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x443, 0x43e, 0x43d, 0x43d, 0x430, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b, 0x6e,
-0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, 0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0xd804, 0xdd03, 0xd804, 0xdd33, 0xd804, 0xdd03, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x62, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c,
-0x25, 0x32
+static constexpr char16_t list_pattern_part_data[] = {
+0x25, 0x31, 0x2c, 0x20, 0x25, 0x32, 0x3b, 0x25, 0x31, 0x2d, 0x438, 0x20,
+0x25, 0x32, 0x2d, 0x438, 0x25, 0x31, 0x20, 0x65, 0x6e, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x68, 0x65, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x1363, 0x20, 0x25, 0x32, 0x25, 0x31, 0x1363, 0x20,
+0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x12a5, 0x1293, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x648, 0x25, 0x32, 0x61b, 0x25, 0x31, 0x20, 0x79,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x587, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x986, 0x9f0, 0x9c1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x259,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x65, 0x74, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x456, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x906, 0x930, 0x94b, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x906, 0x930, 0x94b, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x68, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x2d, 0x20, 0x25, 0x32, 0x25, 0x31, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x20,
+0x25, 0x32, 0x104a, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x540c, 0x25,
+0x32, 0x25, 0x31, 0x2c, 0x20, 0x75, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x75, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xd804, 0xdd03, 0xd804,
+0xdd33, 0xd804, 0xdd03, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x13a0, 0x13b4,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x548c, 0x25, 0x32, 0x25, 0x31, 0x53ca, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x438, 0x486, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x442, 0x430, 0x442, 0x430,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0xe8, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0xa0, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x6f, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c,
+0x20, 0x924, 0x947, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x924, 0x947, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0xf51, 0xf44, 0xf0b, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x61, 0x6a,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6a, 0x61, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20,
+0x6f, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x74, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x65, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x2e41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2e41, 0x20, 0xd83a,
+0xdd2b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xd83a, 0xdd2b, 0x20, 0x25, 0x32,
+0x204f, 0x25, 0x31, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x10d3, 0x10d0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e,
+0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x3ba, 0x3b1, 0x3b9, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0xa85, 0xaa8, 0xac7, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x2c, 0x20, 0x64, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d5, 0x25, 0x32, 0x25, 0x31, 0x2c,
+0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x914, 0x930, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x75, 0x72, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x61, 0x75, 0x72, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0xe9, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x61, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64,
+0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6c, 0x61, 0x6e,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6c, 0x61, 0x6e, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x60c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x62a,
+0x655, 0x6c1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x62a, 0x655, 0x6c1, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x924, 0x93f, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x924, 0x93f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x4d9,
+0x43d, 0x435, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x200b, 0x25, 0x32, 0x25,
+0x31, 0x20, 0xbc0f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xfb, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x436, 0x430, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0xec1, 0xea5, 0xeb0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6d,
+0x70, 0xe9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x72, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61,
+0x28, 0x6e, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x25, 0x32,
+0x20, 0xd0e, 0xd28, 0xd4d, 0xd28, 0xd3f, 0xd35, 0x25, 0x31, 0x20, 0xd15, 0xd42,
+0xd1f, 0xd3e, 0xd24, 0xd46, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x75,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x985, 0x9ae, 0x9b8, 0x9c1, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x906, 0x923, 0x93f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b, 0x301,
+0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b,
+0x6e, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x70, 0x254, 0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x6e,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0xb13, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xb13, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x60c, 0x20, 0x627, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627,
+0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x62, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0xa05, 0xa24, 0xa47, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x443, 0x43e, 0x43d, 0x43d, 0x430, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x924, 0x925, 0x93e, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x924, 0x925, 0x93e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c,
+0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6fd, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x2c, 0x20, 0x73, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x73, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x718,
+0x25, 0x32, 0x25, 0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, 0xbae, 0xbcd,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4bb, 0x4d9, 0x43c, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, 0xc41, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30,
+0x25, 0x32, 0x25, 0x31, 0x1295, 0x20, 0x25, 0x32, 0x1295, 0x25, 0x31, 0x20,
+0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x77, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c,
+0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648,
+0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x76, 0xe0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20,
+0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28,
+0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d0, 0x5d5, 0x5df, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x63, 0x61, 0x65, 0x75, 0x71, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x61, 0x72,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x73, 0x75, 0xed, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x60c, 0x25, 0x32, 0x25, 0x31, 0x20, 0x60c, 0x622, 0x6ba,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x622, 0x6ba, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0x915, 0x928, 0x947, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x915, 0x928, 0x947, 0x20, 0x25, 0x32
};
-static const char16_t single_character_data[] = {
-0x2e, 0x2c, 0x25, 0x30, 0x2d, 0x2b, 0x65, 0x22, 0x27, 0x45, 0x201c, 0x201d, 0x2018, 0x2019, 0xa0, 0xab, 0xbb, 0x2039, 0x203a, 0x66b,
-0x66c, 0x66a, 0x61c, 0x660, 0x61c, 0x2d, 0x61c, 0x2b, 0x627, 0x633, 0x200e, 0x25, 0x200e, 0x200e, 0x2d, 0x200e, 0x2b, 0x9e6, 0x2212, 0xf20,
-0x201e, 0x1040, 0x300c, 0x300d, 0x300e, 0x300f, 0x201a, 0xd7, 0x31, 0x30, 0x5e, 0x202f, 0x6f0, 0x200e, 0x2b, 0x200e, 0xd7, 0x6f1, 0x6f0, 0x5e,
-0x966, 0x200e, 0x2212, 0x415, 0xb7, 0x31, 0x30, 0x5e, 0x5a, 0xd804, 0xdd36, 0x200f, 0x2d, 0x200f, 0x2b
+static constexpr char16_t single_character_data[] = {
+0x2e, 0x2c, 0x25, 0x30, 0x2d, 0x2b, 0x65, 0x22, 0x27, 0xa0, 0x45, 0xab,
+0xbb, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2039, 0x203a, 0x66b, 0x66c, 0x66a,
+0x61c, 0x660, 0x61c, 0x2d, 0x61c, 0x2b, 0x623, 0x633, 0x200e, 0x25, 0x200e, 0x200e,
+0x2d, 0x200e, 0x2b, 0x9e6, 0x6f0, 0x200e, 0x2b, 0x200e, 0xd7, 0x6f1, 0x6f0, 0x5e,
+0x2212, 0x966, 0x1040, 0x300c, 0x300d, 0x300e, 0x300f, 0x200f, 0x2d, 0x200f, 0x2b, 0x627,
+0x633, 0xd804, 0xdd36, 0xd7, 0x31, 0x30, 0x5e, 0xf20, 0x202f, 0x2e41, 0xd83a, 0xdd50,
+0xd83a, 0xdd09, 0x12c8, 0xabf0, 0x60c, 0x7c0, 0xb7, 0x31, 0x30, 0x5e, 0x200e, 0x2212,
+0x1c50, 0x415
};
-static const char16_t date_format_data[] = {
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d,
-0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
-0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64,
-0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x200f, 0x2f, 0x4d,
-0x200f, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x569, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64,
-0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
-0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79,
-0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79,
-0x79, 0x28, 0x27, 0x65, 0x27, 0x29, 0x27, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x72, 0x65, 0x6e, 0x27,
-0x20, 0x64, 0x28, 0x27, 0x61, 0x27, 0x29, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x64,
-0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x79,
-0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c,
-0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x2e, 0x4d,
-0x4d, 0x2e, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x104a, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
-0x64, 0x104a, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
-0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
-0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x64, 0x2f,
-0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x20, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64,
-0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79,
-0x2e, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79,
-0x79, 0x4d, 0x2f, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c,
-0x20, 0x64, 0x2d, 0x27, 0x61, 0x27, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x27, 0x6d, 0x68, 0x27,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64,
-0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
-0x64, 0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
-0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
-0x20, 0x5d1, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0x20, 0x64, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20,
-0x64, 0x64, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x6c, 0x65, 0x27, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e, 0x20, 0x64,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x27, 0x436, 0x27, 0x2e,
-0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20,
-0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x64,
-0x64, 0x64, 0x64, 0x20, 0xe97, 0xeb5, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x27, 0x67, 0x61, 0x64, 0x61, 0x27, 0x20, 0x64, 0x2e, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64,
-0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x74, 0x61,
-0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x43e, 0x43d,
-0x44b, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x44b, 0x43d, 0x27, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x20,
-0x27, 0x433, 0x430, 0x440, 0x430, 0x433, 0x27, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d, 0x4d, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x20, 0x62f, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x62f, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x2c, 0x20, 0x27, 0x69, 0x6c, 0x73, 0x27, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e,
-0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x430, 0x437, 0x27, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64,
-0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65,
-0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
-0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x435, 0x43b, 0x27, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe17,
-0xe35, 0xe48, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d,
-0x4d, 0x4d, 0x4d, 0xf60, 0xf72, 0xf0b, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x1363, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79,
-0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x440, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x60c,
-0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
-0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x646, 0x686, 0x6cc, 0x20,
-0x6cc, 0x6cc, 0x644, 0x20, 0x64, 0x20, 0x646, 0x686, 0x6cc, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x20,
-0x6a9, 0x648, 0x646, 0x6cc, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x61, 0x27, 0x20, 0x27, 0x64, 0x27,
-0x2e, 0x20, 0x64, 0x27, 0x69, 0x64, 0x27, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x2c, 0x20,
-0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x5d8, 0x5df, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
-0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64,
-0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x61, 0x6c, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x6c, 0x69, 0x61, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27,
-0x64, 0x69, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0xe4, 0x27, 0x20, 0x64,
-0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d,
-0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x43b, 0x27, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27,
-0x441, 0x44b, 0x43b, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x43a, 0x4af, 0x43d, 0x44d, 0x27, 0x2c, 0x20,
-0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x2c,
-0x20, 0x27, 0x6c, 0x79, 0x25b, 0x27, 0x30c, 0x2bc, 0x20, 0x64, 0x20, 0x27, 0x6e, 0x61, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
-0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x6d, 0x65,
-0x74, 0x74, 0x61, 0x73, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d,
-0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79
+static constexpr char16_t date_format_data[] = {
+0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x448, 0x27,
+0x2e, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64,
+0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64,
+0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2d,
+0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2f, 0x4d,
+0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x79,
+0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f,
+0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x200f, 0x2f,
+0x4d, 0x200f, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x569, 0x2e,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79,
+0x28, 0x27, 0x65, 0x27, 0x29, 0x27, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x27, 0x72, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x28, 0x27, 0x61,
+0x27, 0x29, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d,
+0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x202f, 0x27, 0x433, 0x27, 0x2e,
+0x64, 0x64, 0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x130d, 0x122d, 0x130b, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
+0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
+0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x2e, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2e,
+0x4d, 0x2e, 0x79, 0x79, 0x2e, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79,
+0x202f, 0x27, 0x433, 0x27, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x104a, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x104a, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79,
+0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x20, 0x64, 0x64, 0x64,
+0x64, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79,
+0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27,
+0x64, 0x65, 0x6c, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x4d, 0x2f, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x43b,
+0x27, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x79, 0x79, 0x79, 0x79,
+0x2e, 0x4d, 0x4d, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x202f,
+0x27, 0x4ab, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64,
+0xe4, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x27, 0x75, 0x27, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79,
+0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20,
+0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63,
+0xf7c, 0xf0b, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d,
+0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x6c, 0x61,
+0x27, 0x20, 0x64, 0x2d, 0x27, 0x61, 0x27, 0x20, 0x27, 0x64, 0x65, 0x27,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
+0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27,
+0x6c, 0x69, 0x61, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d,
+0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20,
+0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64,
+0x61, 0x6c, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
+0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2e41, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x27, 0x6d, 0x68, 0x27,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
+0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x1365, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1275, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x64, 0x20, 0x5d1, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x64, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79,
+0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x64, 0x64, 0x2e, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x6c, 0x65, 0x27,
+0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27,
+0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x69,
+0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x202f, 0x27, 0x436, 0x27,
+0x2e, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64,
+0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2e, 0x20,
+0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
+0x27, 0xea, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x61, 0x27, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x27, 0x61, 0x6e, 0x27, 0x79, 0x79, 0x79, 0x79,
+0x2d, 0x27, 0x436, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d,
+0x4d, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20,
+0xe97, 0xeb5, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0x69, 0x65,
+0x27, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x20, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x27, 0x67, 0x61,
+0x64, 0x61, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x64, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0x65, 0x27,
+0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x64, 0x20, 0x27, 0x74, 0x61, 0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64,
+0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64,
+0x79, 0x79, 0x79, 0x79, 0x202f, 0x27, 0x43e, 0x43d, 0x44b, 0x27, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x27, 0x44b, 0x43d, 0x27, 0x20, 0x64, 0x2c, 0x20, 0x64,
+0x64, 0x64, 0x64, 0x20, 0x27, 0x433, 0x430, 0x440, 0x430, 0x433, 0x27, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x1823, 0x1828, 0x20, 0x180e, 0x180e, 0x180e, 0x1824, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x180e, 0x180e, 0x1822, 0x1822, 0x1828, 0x64, 0x2e, 0x20,
+0x64, 0x64, 0x64, 0x64, 0x20, 0x180b, 0x182d, 0x1820, 0x1837, 0x1820, 0x182d, 0x64,
+0x64, 0x64, 0x64, 0x20, 0x2c, 0x20, 0x27, 0x6c, 0x79, 0x25b, 0x27, 0x30c,
+0x2bc, 0x20, 0x64, 0x20, 0x27, 0x6e, 0x61, 0x27, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20,
+0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x202f, 0x27,
+0x430, 0x437, 0x27, 0x64, 0x64, 0x64, 0x64, 0x20, 0x62f, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x20, 0x62f, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x6d,
+0x65, 0x74, 0x74, 0x61, 0x73, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x69, 0x6c, 0x73,
+0x27, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x202f, 0x27, 0x441, 0x44b, 0x43b, 0x27, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x43a, 0x4af, 0x43d, 0x44d,
+0x27, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20,
+0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x27, 0x64, 0x65, 0x27, 0x20, 0x27, 0x73, 0x75, 0x27, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x27, 0x64,
+0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x60c, 0x20, 0x64,
+0x20, 0x712, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x202f,
+0x27, 0x435, 0x43b, 0x27, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48, 0x20,
+0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0xf60, 0xf72, 0xf0b, 0xf5a,
+0xf7a, 0xf66, 0xf0b, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x12ee, 0x121d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1363,
+0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x202f, 0x27, 0x440,
+0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d,
+0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20,
+0x646, 0x686, 0x6cc, 0x20, 0x6cc, 0x6cc, 0x644, 0x20, 0x64, 0x20, 0x646, 0x686,
+0x6cc, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x20,
+0x6a9, 0x648, 0x646, 0x6cc, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x27, 0x61, 0x27, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x20, 0x64, 0x27,
+0x69, 0x64, 0x27, 0x64, 0x64, 0x64, 0x64, 0x1365, 0x20, 0x64, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x130b, 0x120b, 0x1233, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
+0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x5d8, 0x5df, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
+0x20, 0x27, 0x6e, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x6f, 0x27, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x64, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x2f, 0x64, 0x2f, 0x79, 0x79,
+0x79, 0x79
};
-static const char16_t time_format_data[] = {
-0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50,
-0x20, 0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x2c,
-0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a,
-0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b,
-0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b,
-0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x74, 0x20, 0x48, 0x48, 0x3a,
-0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x42, 0x20, 0x48, 0x3a, 0x6d, 0x6d, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x2c,
-0x20, 0x74, 0x74, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a,
-0x73, 0x73, 0x20, 0x5b, 0x74, 0x5d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x2e, 0x6d, 0x6d,
-0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x2d, 0x27, 0x61, 0x27, 0x20, 0x27, 0x68, 0x6f, 0x72, 0x6f, 0x27, 0x20, 0x27, 0x6b,
-0x61, 0x6a, 0x27, 0x20, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x20, 0x27,
-0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20,
-0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48, 0x2e,
-0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27, 0x20, 0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20,
-0x41, 0x50, 0x20, 0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x48, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2,
-0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a,
-0x6d, 0x6d, 0x48, 0x20, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0x20, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4,
-0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x74, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73,
-0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0xe19, 0xe32, 0xe2c, 0xe34,
-0xe01, 0xe32, 0x20, 0x6d, 0x6d, 0x20, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17, 0xe35,
-0x20, 0x74, 0x41, 0x50, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x27,
-0x4b, 0x6c, 0x6f, 0x63, 0x6b, 0x27, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0x27, 0x4b,
-0x6c, 0x27, 0x2e, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x74, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50,
-0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x27, 0x68, 0x6f, 0x64, 0x17a, 0x27, 0x2e
+static constexpr char16_t time_format_data[] = {
+0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x48,
+0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x74, 0x74, 0x74, 0x68,
+0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x202f, 0x41, 0x70, 0x20, 0x74, 0x74,
+0x74, 0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x202f, 0x41, 0x70, 0x68, 0x3a, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x202f, 0x41, 0x70, 0x2c, 0x20, 0x74, 0x74, 0x74,
+0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x70, 0x20,
+0x74, 0x74, 0x74, 0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x70, 0x41,
+0x70, 0x20, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x74,
+0x74, 0x74, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28,
+0x74, 0x74, 0x74, 0x74, 0x29, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73,
+0x73, 0x2c, 0x20, 0x74, 0x74, 0x74, 0x74, 0x41, 0x70, 0x20, 0x68, 0x3a,
+0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x74, 0x74, 0x74, 0x41, 0x70,
+0x20, 0x928, 0x93f, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x48, 0x3a, 0x6d, 0x6d,
+0x3a, 0x73, 0x73, 0x20, 0x27, 0x447, 0x27, 0x2e, 0x20, 0x74, 0x74, 0x74,
+0x74, 0x74, 0x74, 0x74, 0x74, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a,
+0x73, 0x73, 0x41, 0x70, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20,
+0x5b, 0x74, 0x74, 0x74, 0x74, 0x5d, 0x74, 0x74, 0x74, 0x74, 0x20, 0x41,
+0x70, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48, 0x48, 0x2e, 0x6d,
+0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x74, 0x74, 0x74, 0xf46, 0xf74, 0xf0b,
+0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58,
+0xf0b, 0x20, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x70, 0x20, 0x74,
+0x74, 0x74, 0x74, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68,
+0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0x41,
+0x70, 0x41, 0x70, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x74, 0x74, 0x74, 0x48, 0x20, 0x27,
+0x68, 0x27, 0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20,
+0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x74, 0x74, 0x74, 0x48,
+0x48, 0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69,
+0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x74,
+0x74, 0x74, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27,
+0x68, 0x27, 0x20, 0x74, 0x74, 0x74, 0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d,
+0x3a, 0x73, 0x73, 0x20, 0x41, 0x70, 0x20, 0x74, 0x74, 0x74, 0x74, 0x68,
+0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x70, 0x48, 0x6642, 0x6d, 0x6d, 0x5206,
+0x73, 0x73, 0x79d2, 0x20, 0x74, 0x74, 0x74, 0x74, 0x41, 0x70, 0x20, 0x68,
+0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08, 0x20, 0x74, 0x74, 0x74, 0x74,
+0x48, 0x20, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0x20, 0xe99, 0xeb2, 0xe97, 0xeb5,
+0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x74,
+0x74, 0x74, 0x74, 0x27, 0x4b, 0x6c, 0x6f, 0x63, 0x6b, 0x27, 0x20, 0x48,
+0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x74, 0x74, 0x74,
+0x29, 0x27, 0x4b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x68,
+0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x41, 0x70, 0x20, 0x74, 0x74,
+0x74, 0x74, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x20, 0x41, 0x70, 0x27, 0x6b,
+0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73,
+0x20, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x20, 0x68, 0x3a,
+0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x202f, 0x41, 0x70, 0x48, 0x27, 0x68, 0x27,
+0x6d, 0x6d, 0x48, 0x20, 0xe19, 0xe32, 0xe2c, 0xe34, 0xe01, 0xe32, 0x20, 0x6d,
+0x6d, 0x20, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34,
+0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x74, 0x74, 0x74, 0x74, 0x68, 0x68, 0x3a,
+0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x202f, 0x41, 0x70, 0x20, 0x74, 0x74, 0x74,
+0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x202f, 0x41, 0x70, 0x48, 0x3a, 0x6d,
+0x6d, 0x20, 0x27, 0x68, 0x6f, 0x64, 0x17a, 0x27, 0x2e
};
-static const char16_t days_data[] = {
-0x53, 0x75, 0x6e, 0x64, 0x61, 0x79, 0x3b, 0x4d, 0x6f, 0x6e, 0x64, 0x61, 0x79, 0x3b, 0x54, 0x75, 0x65, 0x73, 0x64, 0x61,
-0x79, 0x3b, 0x57, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x64, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x75, 0x72, 0x73, 0x64, 0x61, 0x79,
-0x3b, 0x46, 0x72, 0x69, 0x64, 0x61, 0x79, 0x3b, 0x53, 0x61, 0x74, 0x75, 0x72, 0x64, 0x61, 0x79, 0x53, 0x75, 0x6e, 0x3b,
-0x4d, 0x6f, 0x6e, 0x3b, 0x54, 0x75, 0x65, 0x3b, 0x57, 0x65, 0x64, 0x3b, 0x54, 0x68, 0x75, 0x3b, 0x46, 0x72, 0x69, 0x3b,
-0x53, 0x61, 0x74, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x53, 0x37, 0x3b, 0x31, 0x3b,
-0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x44, 0x69, 0x6c, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x57, 0x69, 0x69,
-0x78, 0x61, 0x74, 0x61, 0x3b, 0x51, 0x69, 0x62, 0x78, 0x61, 0x74, 0x61, 0x3b, 0x52, 0x6f, 0x6f, 0x62, 0x69, 0x69, 0x3b,
-0x4b, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x6e, 0x62,
-0x61, 0x74, 0x61, 0x44, 0x69, 0x6c, 0x3b, 0x57, 0x69, 0x78, 0x3b, 0x51, 0x69, 0x62, 0x3b, 0x52, 0x6f, 0x62, 0x3b, 0x4b,
-0x61, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x6e, 0x44, 0x3b, 0x57, 0x3b, 0x51, 0x3b, 0x52, 0x3b, 0x4b, 0x3b,
-0x4a, 0x3b, 0x53, 0x53, 0x6f, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69,
-0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x57, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65,
-0x72, 0x64, 0x61, 0x67, 0x3b, 0x56, 0x72, 0x79, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, 0x67,
-0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x61, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x57, 0x6f, 0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b,
-0x56, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x53,
-0x65, 0x20, 0x64, 0x69, 0x65, 0x6c, 0x3b, 0x65, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x74,
-0xeb, 0x3b, 0x65, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb, 0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b,
-0x65, 0x20, 0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x64, 0x69, 0x65,
-0x3b, 0x68, 0xeb, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0xeb, 0x72, 0x3b, 0x65, 0x6e, 0x6a, 0x3b, 0x70, 0x72, 0x65,
-0x3b, 0x73, 0x68, 0x74, 0x44, 0x69, 0x65, 0x3b, 0x48, 0xeb, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0xeb, 0x72, 0x3b,
-0x45, 0x6e, 0x6a, 0x3b, 0x50, 0x72, 0x65, 0x3b, 0x53, 0x68, 0x74, 0x64, 0x3b, 0x68, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x65,
-0x3b, 0x70, 0x3b, 0x73, 0x68, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x129e, 0x3b, 0x1228, 0x1261, 0x12d5,
-0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b,
-0x12ad, 0x1230, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x12a5, 0x3b,
-0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1245, 0x627, 0x644, 0x623, 0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627,
-0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x627, 0x644, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x623, 0x631, 0x628, 0x639,
-0x627, 0x621, 0x3b, 0x627, 0x644, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x627, 0x644, 0x633,
-0x628, 0x62a, 0x62d, 0x3b, 0x646, 0x3b, 0x62b, 0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c, 0x3b, 0x633, 0x56f, 0x56b, 0x580, 0x561, 0x56f,
-0x56b, 0x3b, 0x565, 0x580, 0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x565, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562,
-0x569, 0x56b, 0x3b, 0x579, 0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x570, 0x56b, 0x576, 0x563, 0x577, 0x561,
-0x562, 0x569, 0x56b, 0x3b, 0x578, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x577, 0x561, 0x562, 0x561, 0x569, 0x56f, 0x56b, 0x580, 0x3b,
-0x565, 0x580, 0x56f, 0x3b, 0x565, 0x580, 0x584, 0x3b, 0x579, 0x580, 0x584, 0x3b, 0x570, 0x576, 0x563, 0x3b, 0x578, 0x582, 0x580, 0x3b,
-0x577, 0x562, 0x569, 0x53f, 0x3b, 0x535, 0x3b, 0x535, 0x3b, 0x549, 0x3b, 0x540, 0x3b, 0x548, 0x3b, 0x547, 0x9a6, 0x9c7, 0x993, 0x9ac,
-0x9be, 0x9f0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac,
-0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1,
-0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x9a6, 0x9c7, 0x993, 0x3b, 0x9b8, 0x9cb, 0x9ae,
-0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0,
-0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9a6, 0x3b, 0x9b8, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x3b, 0x9ac, 0x3b, 0x9b6, 0x3b, 0x9b6, 0x62, 0x61, 0x7a,
-0x61, 0x72, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72, 0x20, 0x65, 0x72, 0x74, 0x259, 0x73, 0x69, 0x3b, 0xe7, 0x259, 0x72, 0x15f,
-0x259, 0x6e, 0x62, 0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259,
-0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x3b, 0x15f, 0x259,
-0x6e, 0x62, 0x259, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43,
-0x2e, 0x41, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x65, 0x2e, 0x3b, 0xc7, 0x2e, 0x61,
-0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e, 0x61, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x431, 0x430, 0x437, 0x430, 0x440,
-0x3b, 0x431, 0x430, 0x437, 0x430, 0x440, 0x20, 0x435, 0x440, 0x442, 0x4d9, 0x441, 0x438, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43d,
-0x431, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x4b9,
-0x4af, 0x43c, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x4b9, 0x4af, 0x43c, 0x4d9, 0x3b, 0x448, 0x4d9, 0x43d, 0x431,
-0x4d9, 0x411, 0x2e, 0x3b, 0x411, 0x2e, 0x415, 0x2e, 0x3b, 0x427, 0x2e, 0x410, 0x2e, 0x3b, 0x427, 0x2e, 0x3b, 0x4b8, 0x2e, 0x410,
-0x2e, 0x3b, 0x4b8, 0x2e, 0x3b, 0x428, 0x2e, 0x69, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x6c,
-0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65,
-0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x69,
-0x72, 0x61, 0x6c, 0x61, 0x3b, 0x6c, 0x61, 0x72, 0x75, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x69, 0x67, 0x2e, 0x3b, 0x61, 0x6c,
-0x2e, 0x3b, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x2e, 0x3b, 0x6f, 0x67, 0x2e, 0x3b, 0x6f, 0x72, 0x2e, 0x3b, 0x6c, 0x72,
-0x2e, 0x49, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x4c, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0,
-0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7,
-0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd,
-0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x9b0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae,
-0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1,
-0x995, 0x9cd, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x9c1, 0x3b, 0x9ac, 0x9c3, 0x3b,
-0x9b6, 0x9c1, 0x3b, 0x9b6, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72,
-0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f,
-0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b,
-0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b,
-0xf58, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b,
-0x3b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72,
-0xf62, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xfb6, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0xf49,
-0xf72, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x4d, 0x65, 0x72, 0x63,
-0x2bc, 0x68, 0x65, 0x72, 0x3b, 0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x53, 0x61, 0x64,
-0x6f, 0x72, 0x6e, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x2e, 0x3b, 0x4d, 0x65, 0x72, 0x2e,
-0x3b, 0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x64, 0x2e, 0x53, 0x75, 0x3b, 0x4c, 0x3b,
-0x4d, 0x7a, 0x3b, 0x4d, 0x63, 0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53, 0x61, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44f, 0x3b, 0x43f,
-0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440,
-0x44f, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x44a, 0x440, 0x442, 0x44a, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x44a, 0x43a, 0x3b,
-0x441, 0x44a, 0x431, 0x43e, 0x442, 0x430, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442,
-0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x43d, 0x3b, 0x43f, 0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x1010,
-0x1014, 0x1004, 0x103a, 0x1039, 0x1002, 0x1014, 0x103d, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x101c, 0x102c, 0x3b, 0x1021, 0x1004, 0x103a,
-0x1039, 0x1002, 0x102b, 0x3b, 0x1017, 0x102f, 0x1012, 0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c, 0x101e, 0x1015, 0x1010, 0x1031,
-0x1038, 0x3b, 0x101e, 0x1031, 0x102c, 0x1000, 0x103c, 0x102c, 0x3b, 0x1005, 0x1014, 0x1031, 0x1010, 0x3b, 0x1010, 0x3b, 0x1021, 0x3b, 0x1017, 0x3b,
-0x1000, 0x3b, 0x101e, 0x3b, 0x1005, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437, 0x435,
-0x43b, 0x430, 0x43a, 0x3b, 0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x435, 0x440, 0x430, 0x434, 0x430, 0x3b, 0x447,
-0x430, 0x446, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430,
-0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431,
-0x43d, 0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799,
-0x3b, 0x1785, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a,
-0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x17a2, 0x17b6,
-0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796,
-0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b,
-0x179f, 0x17c5, 0x179a, 0x17cd, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2,
-0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x179f,
-0x17c5, 0x179a, 0x17cd, 0x17a2, 0x3b, 0x1785, 0x3b, 0x17a2, 0x3b, 0x1796, 0x3b, 0x1796, 0x3b, 0x179f, 0x3b, 0x179f, 0x64, 0x69, 0x75, 0x6d,
-0x65, 0x6e, 0x67, 0x65, 0x3b, 0x64, 0x69, 0x6c, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72, 0x74, 0x73,
-0x3b, 0x64, 0x69, 0x6d, 0x65, 0x63, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76,
-0x65, 0x6e, 0x64, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x73, 0x73, 0x61, 0x62, 0x74, 0x65, 0x64, 0x67, 0x2e, 0x3b, 0x64,
-0x6c, 0x2e, 0x3b, 0x64, 0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64, 0x6a, 0x2e, 0x3b, 0x64, 0x76, 0x2e, 0x3b, 0x64,
-0x73, 0x2e, 0x64, 0x67, 0x3b, 0x64, 0x6c, 0x3b, 0x64, 0x74, 0x3b, 0x64, 0x63, 0x3b, 0x64, 0x6a, 0x3b, 0x64, 0x76, 0x3b,
-0x64, 0x73, 0x661f, 0x671f, 0x65e5, 0x3b, 0x661f, 0x671f, 0x4e00, 0x3b, 0x661f, 0x671f, 0x4e8c, 0x3b, 0x661f, 0x671f, 0x4e09, 0x3b, 0x661f, 0x671f,
-0x56db, 0x3b, 0x661f, 0x671f, 0x4e94, 0x3b, 0x661f, 0x671f, 0x516d, 0x5468, 0x65e5, 0x3b, 0x5468, 0x4e00, 0x3b, 0x5468, 0x4e8c, 0x3b, 0x5468, 0x4e09,
-0x3b, 0x5468, 0x56db, 0x3b, 0x5468, 0x4e94, 0x3b, 0x5468, 0x516d, 0x65e5, 0x3b, 0x4e00, 0x3b, 0x4e8c, 0x3b, 0x4e09, 0x3b, 0x56db, 0x3b, 0x4e94,
-0x3b, 0x516d, 0x9031, 0x65e5, 0x3b, 0x9031, 0x4e00, 0x3b, 0x9031, 0x4e8c, 0x3b, 0x9031, 0x4e09, 0x3b, 0x9031, 0x56db, 0x3b, 0x9031, 0x4e94, 0x3b,
-0x9031, 0x516d, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a,
-0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65,
-0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x6e,
-0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x69, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70,
-0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x4e,
-0x3b, 0x50, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53, 0x6e, 0x65, 0x64, 0x11b, 0x6c, 0x65, 0x3b, 0x70,
-0x6f, 0x6e, 0x64, 0x11b, 0x6c, 0xed, 0x3b, 0xfa, 0x74, 0x65, 0x72, 0xfd, 0x3b, 0x73, 0x74, 0x159, 0x65, 0x64, 0x61, 0x3b,
-0x10d, 0x74, 0x76, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0xe1, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61,
-0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0xfa, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x10d, 0x74, 0x3b, 0x70, 0xe1, 0x3b, 0x73, 0x6f,
-0x4e, 0x3b, 0x50, 0x3b, 0xda, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b,
-0x6d, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61,
-0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf8, 0x72,
-0x64, 0x61, 0x67, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0x61, 0x6e, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74,
-0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf8, 0x72, 0x73, 0xf8, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x6e, 0x2e, 0x3b,
-0x74, 0x69, 0x72, 0x2e, 0x3b, 0x6f, 0x6e, 0x73, 0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b,
-0x6c, 0xf8, 0x72, 0x2e, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x4c, 0x7a, 0x6f, 0x6e,
-0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x69, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b,
-0x77, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x76,
-0x72, 0x69, 0x6a, 0x64, 0x61, 0x67, 0x3b, 0x7a, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x7a, 0x6f, 0x3b, 0x6d, 0x61,
-0x3b, 0x64, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x64, 0x6f, 0x3b, 0x76, 0x72, 0x3b, 0x7a, 0x61, 0x5a, 0x3b, 0x4d, 0x3b, 0x44,
-0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x5a, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x2e, 0x3b, 0x54, 0x75, 0x2e, 0x3b, 0x57,
-0x2e, 0x3b, 0x54, 0x68, 0x2e, 0x3b, 0x46, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x53, 0x75, 0x6e, 0x2e, 0x3b, 0x4d, 0x6f, 0x6e,
-0x2e, 0x3b, 0x54, 0x75, 0x65, 0x2e, 0x3b, 0x57, 0x65, 0x64, 0x2e, 0x3b, 0x54, 0x68, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x69,
-0x2e, 0x3b, 0x53, 0x61, 0x74, 0x2e, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x109, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x6f, 0x3b,
-0x6d, 0x61, 0x72, 0x64, 0x6f, 0x3b, 0x6d, 0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x6f, 0x3b, 0x135, 0x61, 0x16d, 0x64, 0x6f,
-0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x6f, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x64, 0x69, 0x3b, 0x6c,
-0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x135, 0x61, 0x3b, 0x76, 0x65, 0x3b, 0x73, 0x61, 0x44, 0x3b, 0x4c, 0x3b,
-0x4d, 0x3b, 0x4d, 0x3b, 0x134, 0x3b, 0x56, 0x3b, 0x53, 0x70, 0xfc, 0x68, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65, 0x73,
-0x6d, 0x61, 0x73, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x74, 0x65, 0x69, 0x73, 0x69, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b, 0x6f,
-0x6c, 0x6d, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x72, 0x65,
-0x65, 0x64, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x70, 0xe4, 0x65, 0x76, 0x50, 0x3b, 0x45, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4e,
-0x3b, 0x52, 0x3b, 0x4c, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x61, 0x64,
-0x61, 0x67, 0x75, 0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b, 0x75, 0x64, 0x61,
-0x67, 0x75, 0x72, 0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x72, 0xed, 0x67, 0x67, 0x6a, 0x61,
-0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x65, 0x79, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x73, 0x75, 0x6e,
-0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d, 0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66, 0x72, 0xed,
-0x3b, 0x6c, 0x65, 0x79, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0x74, 0xfd, 0x73, 0x2e, 0x3b, 0x6d,
-0x69, 0x6b, 0x2e, 0x3b, 0x68, 0xf3, 0x73, 0x2e, 0x3b, 0x66, 0x72, 0xed, 0x2e, 0x3b, 0x6c, 0x65, 0x79, 0x2e, 0x53, 0x3b,
-0x4d, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46, 0x3b, 0x4c, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69,
-0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x6b,
-0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x70,
-0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x73, 0x75, 0x6e,
-0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61,
-0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b,
-0x6b, 0x6f, 0x6e, 0x61, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61,
-0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x73, 0x75, 0x3b,
-0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70, 0x65, 0x3b, 0x6c, 0x61, 0x53, 0x3b, 0x4d,
-0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c,
-0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x72, 0x65, 0x64, 0x69, 0x3b,
-0x6a, 0x65, 0x75, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64,
-0x69, 0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e,
-0x3b, 0x6a, 0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x6d, 0x2e, 0x44, 0x3b, 0x4c, 0x3b, 0x4d,
-0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x73, 0x6e, 0x65, 0x69, 0x6e, 0x3b, 0x6d, 0x6f, 0x61, 0x6e, 0x64, 0x65,
-0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x77, 0x6f, 0x61, 0x6e, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x74,
-0x6f, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x66, 0x72, 0x65, 0x65, 0x64, 0x3b, 0x73, 0x6e, 0x65, 0x6f,
-0x6e, 0x73, 0x69, 0x3b, 0x6d, 0x6f, 0x3b, 0x74, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x74, 0x6f, 0x3b, 0x66, 0x72, 0x3b, 0x73,
-0x6f, 0x44, 0x69, 0x44, 0xf2, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x4c, 0x75, 0x61, 0x69, 0x6e,
-0x3b, 0x44, 0x69, 0x4d, 0xe0, 0x69, 0x72, 0x74, 0x3b, 0x44, 0x69, 0x43, 0x69, 0x61, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x44,
-0x69, 0x61, 0x72, 0x44, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0x69,
-0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x65, 0x44, 0x69, 0x44, 0x3b, 0x44, 0x69, 0x4c, 0x3b, 0x44, 0x69, 0x4d,
-0x3b, 0x44, 0x69, 0x43, 0x3b, 0x44, 0x69, 0x61, 0x3b, 0x44, 0x69, 0x68, 0x3b, 0x44, 0x69, 0x53, 0x44, 0x3b, 0x4c, 0x3b,
-0x4d, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x53, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e,
-0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x58, 0x6f,
-0x76, 0x65, 0x73, 0x3b, 0x56, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d,
-0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0xe9, 0x72,
-0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x78, 0x6f, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73,
-0xe1, 0x62, 0x61, 0x64, 0x6f, 0x44, 0x6f, 0x6d, 0x2e, 0x3b, 0x4c, 0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b,
-0x4d, 0xe9, 0x72, 0x2e, 0x3b, 0x58, 0x6f, 0x76, 0x2e, 0x3b, 0x56, 0x65, 0x6e, 0x2e, 0x3b, 0x53, 0xe1, 0x62, 0x2e, 0x64,
-0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0xe9, 0x72, 0x2e, 0x3b, 0x78,
-0x6f, 0x76, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d,
-0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x64, 0x2e, 0x3b, 0x6c, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e,
-0x3b, 0x76, 0x2e, 0x3b, 0x73, 0x2e, 0x10d9, 0x10d5, 0x10d8, 0x10e0, 0x10d0, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8,
-0x3b, 0x10e1, 0x10d0, 0x10db, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8,
-0x3b, 0x10ee, 0x10e3, 0x10d7, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x10d0, 0x10e1, 0x10d9, 0x10d4, 0x10d5, 0x10d8,
-0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x10d9, 0x10d5, 0x10d8, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x3b, 0x10dd,
-0x10d7, 0x10ee, 0x3b, 0x10ee, 0x10e3, 0x10d7, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d9, 0x3b, 0x10dd, 0x3b, 0x10e1, 0x3b,
-0x10dd, 0x3b, 0x10ee, 0x3b, 0x10de, 0x3b, 0x10e8, 0x53, 0x6f, 0x6e, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x6f, 0x6e, 0x74, 0x61,
-0x67, 0x3b, 0x44, 0x69, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b,
-0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53,
-0x61, 0x6d, 0x73, 0x74, 0x61, 0x67, 0x53, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x44, 0x69, 0x3b, 0x4d, 0x69, 0x3b, 0x44, 0x6f,
-0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69,
-0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x4d,
-0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x53, 0x39a, 0x3c5, 0x3c1, 0x3b9, 0x3b1, 0x3ba, 0x3ae, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3c4, 0x3ad, 0x3c1,
-0x3b1, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3c4, 0x3b7, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3ac, 0x3c1, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3c0,
-0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b1, 0x3c3, 0x3ba, 0x3b5, 0x3c5, 0x3ae, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x3b2, 0x3b1, 0x3c4, 0x3bf,
-0x39a, 0x3c5, 0x3c1, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3b,
-0x3a0, 0x3b1, 0x3c1, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x39a, 0x3b, 0x394, 0x3b, 0x3a4, 0x3b, 0x3a4, 0x3b, 0x3a0, 0x3b, 0x3a0, 0x3b, 0x3a3,
-0x73, 0x61, 0x70, 0x61, 0x61, 0x74, 0x3b, 0x61, 0x74, 0x61, 0x61, 0x73, 0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65,
-0x71, 0x3b, 0x6d, 0x61, 0x72, 0x6c, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x70, 0x69, 0x6e, 0x67,
-0x61, 0x73, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x73, 0x69, 0x73, 0x61, 0x6d, 0x61, 0x6e, 0x6e,
-0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x74, 0x61, 0x6c, 0x6c, 0x69, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e,
-0x65, 0x71, 0x3b, 0x61, 0x72, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x73, 0x61, 0x70,
-0x3b, 0x61, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x69, 0x6e, 0x3b, 0x73, 0x69, 0x73, 0x3b, 0x74, 0x61, 0x6c,
-0x3b, 0x61, 0x72, 0x66, 0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x41, 0xab0, 0xab5, 0xabf,
-0xab5, 0xabe, 0xab0, 0x3b, 0xab8, 0xacb, 0xaae, 0xab5, 0xabe, 0xab0, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0xab5, 0xabe, 0xab0, 0x3b, 0xaac,
-0xac1, 0xaa7, 0xab5, 0xabe, 0xab0, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0xab5,
-0xabe, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0xab5, 0xabe, 0xab0, 0xab0, 0xab5, 0xabf, 0x3b, 0xab8, 0xacb, 0xaae, 0x3b, 0xaae, 0xa82, 0xa97,
-0xab3, 0x3b, 0xaac, 0xac1, 0xaa7, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf,
-0xab0, 0x3b, 0xab8, 0xacb, 0x3b, 0xaae, 0xa82, 0x3b, 0xaac, 0xac1, 0x3b, 0xa97, 0xac1, 0x3b, 0xab6, 0xac1, 0x3b, 0xab6, 0x4c, 0x61,
-0x68, 0x61, 0x64, 0x69, 0x3b, 0x4c, 0x69, 0x74, 0x69, 0x6e, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b,
-0x4c, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d, 0x61,
-0x2bc, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, 0x4c, 0x61, 0x68, 0x3b, 0x4c, 0x69, 0x74, 0x3b, 0x54, 0x61, 0x6c,
-0x3b, 0x4c, 0x61, 0x72, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x4c, 0x3b, 0x4c, 0x3b,
-0x54, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x41, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9, 0x5d5, 0x5df, 0x3b, 0x5d9,
-0x5d5, 0x5dd, 0x20, 0x5e9, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd,
-0x20, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d7, 0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd,
-0x20, 0x5e9, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d1, 0x5ea, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d0, 0x5f3, 0x3b,
-0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d2, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d3, 0x5f3,
-0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d4, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0x5d0, 0x5f3,
-0x3b, 0x5d1, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x3b, 0x5d3, 0x5f3, 0x3b, 0x5d4, 0x5f3, 0x3b, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5f3, 0x930, 0x935,
-0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b,
-0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930,
-0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902,
-0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928,
-0x93f, 0x930, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x76,
-0x61, 0x73, 0xe1, 0x72, 0x6e, 0x61, 0x70, 0x3b, 0x68, 0xe9, 0x74, 0x66, 0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b, 0x73,
-0x7a, 0x65, 0x72, 0x64, 0x61, 0x3b, 0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72, 0x74, 0xf6, 0x6b, 0x3b, 0x70, 0xe9, 0x6e, 0x74,
-0x65, 0x6b, 0x3b, 0x73, 0x7a, 0x6f, 0x6d, 0x62, 0x61, 0x74, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x65, 0x3b,
-0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x3b, 0x43, 0x73, 0x3b,
-0x50, 0x3b, 0x53, 0x7a, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x75, 0x64,
-0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe, 0x72, 0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0xf0,
-0x76, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x69, 0x6d, 0x6d, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75,
-0x72, 0x3b, 0x66, 0xf6, 0x73, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x61, 0x75, 0x67, 0x61, 0x72, 0x64,
-0x61, 0x67, 0x75, 0x72, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0xfe, 0x72, 0x69, 0x2e, 0x3b, 0x6d,
-0x69, 0xf0, 0x2e, 0x3b, 0x66, 0x69, 0x6d, 0x2e, 0x3b, 0x66, 0xf6, 0x73, 0x2e, 0x3b, 0x6c, 0x61, 0x75, 0x2e, 0x53, 0x3b,
-0x4d, 0x3b, 0xde, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x4c, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75, 0x3b, 0x53, 0x65,
-0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69,
-0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x4d, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e,
-0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62,
-0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63,
-0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72,
-0x63, 0x75, 0x72, 0x69, 0x64, 0x69, 0x3b, 0x6a, 0x6f, 0x76, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64,
-0x69, 0x3b, 0x73, 0x61, 0x62, 0x62, 0x61, 0x74, 0x6f, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72,
-0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x6a, 0x6f, 0x76, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x64, 0x3b, 0x6c, 0x3b,
-0x6d, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x76, 0x3b, 0x73, 0x44, 0xe9, 0x20, 0x44, 0x6f, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x67,
-0x68, 0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b,
-0x44, 0xe9, 0x20, 0x43, 0xe9, 0x61, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x64, 0x61, 0x6f, 0x69,
-0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0xe9, 0x20, 0x53, 0x61, 0x74, 0x68, 0x61,
-0x69, 0x72, 0x6e, 0x44, 0x6f, 0x6d, 0x68, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x3b, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43,
-0xe9, 0x61, 0x64, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x3b, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x68, 0x44,
-0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x53, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61,
-0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x65, 0x72, 0x63,
-0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x67, 0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64,
-0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
-0x6d, 0x65, 0x72, 0x3b, 0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x44, 0x3b, 0x4c, 0x3b, 0x4d,
-0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x65e5, 0x66dc, 0x65e5, 0x3b, 0x6708, 0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc, 0x65e5, 0x3b,
-0x6c34, 0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc, 0x65e5, 0x3b, 0x91d1, 0x66dc, 0x65e5, 0x3b, 0x571f, 0x66dc, 0x65e5, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b,
-0x3b, 0x6c34, 0x3b, 0x6728, 0x3b, 0x91d1, 0x3b, 0x571f, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53,
-0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d,
-0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65, 0x6c,
-0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x41, 0x3b, 0x53, 0x3b,
-0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0xcad, 0xcbe, 0xca8, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb, 0xcae,
-0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xc97,
-0xcc1, 0xcb0, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0xcb5,
-0xcbe, 0xcb0, 0xcad, 0xcbe, 0xca8, 0xcc1, 0x3b, 0xcb8, 0xccb, 0xcae, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0x3b, 0xcac, 0xcc1, 0xca7, 0x3b,
-0xc97, 0xcc1, 0xcb0, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0xcad, 0xcbe, 0x3b, 0xcb8, 0xccb, 0x3b,
-0xcae, 0xc82, 0x3b, 0xcac, 0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b, 0xcb6, 0x627, 0x64e, 0x62a, 0x6be, 0x648, 0x627, 0x631,
-0x3b, 0x698, 0x654, 0x646, 0x62f, 0x631, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x6c6, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628,
-0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x620, 0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628,
-0x679, 0x648, 0x627, 0x631, 0x622, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x62f, 0x655, 0x631, 0x648, 0x627, 0x631,
-0x3b, 0x628, 0x6c6, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x620, 0x633, 0x648,
-0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627, 0x631, 0x627, 0x3b, 0x698, 0x3b, 0x628, 0x3b, 0x628,
-0x3b, 0x628, 0x3b, 0x62c, 0x3b, 0x628, 0x436, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x434, 0x4af, 0x439, 0x441, 0x435,
-0x43d, 0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x441, 0x435, 0x43d, 0x431,
-0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x431,
-0x456, 0x436, 0x441, 0x3b, 0x434, 0x441, 0x3b, 0x441, 0x441, 0x3b, 0x441, 0x440, 0x3b, 0x431, 0x441, 0x3b, 0x436, 0x43c, 0x3b, 0x441,
-0x431, 0x416, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x421, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x421, 0x4b, 0x75, 0x20, 0x63, 0x79, 0x75,
-0x6d, 0x77, 0x65, 0x72, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x77,
-0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75,
-0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61,
-0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x75, 0x63, 0x79, 0x75,
-0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e,
-0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x436, 0x435, 0x43a, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b,
-0x434, 0x4af, 0x439, 0x448, 0x4e9, 0x43c, 0x431, 0x4af, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x448, 0x430,
-0x440, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x436, 0x443, 0x43c, 0x430,
-0x3b, 0x438, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x436, 0x435, 0x43a, 0x2e, 0x3b, 0x434, 0x4af, 0x439, 0x2e, 0x3b, 0x448, 0x435, 0x439,
-0x448, 0x2e, 0x3b, 0x448, 0x430, 0x440, 0x448, 0x2e, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b,
-0x438, 0x448, 0x43c, 0x2e, 0x416, 0x3b, 0x414, 0x3b, 0x428, 0x3b, 0x428, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x418, 0xc77c, 0xc694, 0xc77c,
-0x3b, 0xc6d4, 0xc694, 0xc77c, 0x3b, 0xd654, 0xc694, 0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c, 0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, 0xc694, 0xc77c,
-0x3b, 0xd1a0, 0xc694, 0xc77c, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9, 0x3b, 0xae08, 0x3b, 0xd1a0, 0x79, 0x65, 0x6b,
-0x15f, 0x65, 0x6d, 0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6d, 0x3b, 0x73, 0xea, 0x15f, 0x65, 0x6d, 0x3b, 0xe7, 0x61, 0x72, 0x15f,
-0x65, 0x6d, 0x3b, 0x70, 0xea, 0x6e, 0x63, 0x15f, 0x65, 0x6d, 0x3b, 0xee, 0x6e, 0x3b, 0x15f, 0x65, 0x6d, 0xee, 0x79, 0x15f,
-0x3b, 0x64, 0x15f, 0x3b, 0x73, 0x15f, 0x3b, 0xe7, 0x15f, 0x3b, 0x70, 0x15f, 0x3b, 0xee, 0x6e, 0x3b, 0x15f, 0x59, 0x3b, 0x44,
-0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0xce, 0x3b, 0x15e, 0x4b, 0x75, 0x20, 0x77, 0x2019, 0x69, 0x6e, 0x64, 0x77, 0x69,
-0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b,
-0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b,
-0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61,
-0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x75, 0x63, 0x75,
-0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e,
-0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b,
-0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99,
-0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81, 0x3b,
-0xea7, 0xeb1, 0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xe88, 0xeb1, 0xe99, 0x3b, 0xead, 0xeb1, 0xe87,
-0xe84, 0xeb2, 0xe99, 0x3b, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xec0, 0xeaa,
-0xebb, 0xeb2, 0xead, 0xeb2, 0x3b, 0xe88, 0x3b, 0xead, 0x3b, 0xe9e, 0x3b, 0xe9e, 0xeab, 0x3b, 0xeaa, 0xeb8, 0x3b, 0xeaa, 0x53, 0x76,
-0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x74,
-0x72, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x43, 0x65, 0x74,
-0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b,
-0x53, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x73, 0x76, 0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70,
-0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x74, 0x72,
-0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b,
-0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61,
-0x53, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b, 0x4f, 0x74, 0x72, 0x64, 0x2e, 0x3b,
-0x54, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x65, 0x6b,
-0x74, 0x64, 0x2e, 0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x2e, 0x73, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69, 0x72,
-0x6d, 0x64, 0x2e, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x2e, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x63, 0x65, 0x74,
-0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64, 0x2e,
-0x53, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b,
-0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b,
-0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c,
-0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20,
-0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d,
-0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x6d, 0x70, 0x254, 0x301, 0x73, 0x254, 0x65, 0x79, 0x65, 0x3b, 0x79, 0x62, 0x6f, 0x3b,
-0x6d, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x6e, 0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x70, 0x73, 0x65,
-0x3b, 0x79, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x70, 0x73, 0x65, 0x6b, 0x6d, 0x61, 0x64, 0x69, 0x65,
-0x6e, 0x69, 0x73, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x61, 0x6e, 0x74, 0x72,
-0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x74, 0x72, 0x65, 0x10d, 0x69, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
-0x3b, 0x6b, 0x65, 0x74, 0x76, 0x69, 0x72, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x65, 0x6e, 0x6b,
-0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
-0x73, 0x6b, 0x3b, 0x70, 0x72, 0x3b, 0x61, 0x6e, 0x3b, 0x74, 0x72, 0x3b, 0x6b, 0x74, 0x3b, 0x70, 0x6e, 0x3b, 0x161, 0x74,
-0x53, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x430, 0x3b,
-0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441,
-0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x43e, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e, 0x43a, 0x3b,
-0x441, 0x430, 0x431, 0x43e, 0x442, 0x430, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x43e, 0x2e,
-0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e,
-0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447,
-0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x79,
-0x3b, 0x41, 0x6c, 0x61, 0x74, 0x73, 0x69, 0x6e, 0x61, 0x69, 0x6e, 0x79, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b,
-0x41, 0x6c, 0x61, 0x72, 0x6f, 0x62, 0x69, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x61, 0x6d, 0x69, 0x73, 0x79, 0x3b, 0x5a,
-0x6f, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x6f, 0x74, 0x73, 0x79, 0x41, 0x6c, 0x61, 0x68, 0x3b, 0x41, 0x6c, 0x61,
-0x74, 0x73, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x3b, 0x5a, 0x6f, 0x6d,
-0x3b, 0x41, 0x73, 0x61, 0x62, 0x41, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x5a, 0x3b, 0x41, 0x41, 0x68,
-0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75,
-0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75,
-0x41, 0x68, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b,
-0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x41, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53,
-0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c,
-0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d,
-0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f,
-0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0xd1e, 0xd3e, 0xd2f, 0xd31,
-0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a,
-0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d,
-0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c,
-0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0xd1e, 0xd3e, 0xd2f, 0xd7c, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d,
-0xd15, 0xd7e, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd7b, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd02,
-0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd1e, 0xd3e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b,
-0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0xd1e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b,
-0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x64, 0x64, 0x3b,
-0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65, 0x6a, 0x6e, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6c, 0x69, 0x65, 0x74, 0x61, 0x3b, 0x4c,
-0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c, 0x2d,
-0x120, 0x69, 0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x73, 0x2d, 0x53, 0x69, 0x62, 0x74, 0x126, 0x61, 0x64, 0x3b, 0x54, 0x6e,
-0x65, 0x3b, 0x54, 0x6c, 0x69, 0x3b, 0x45, 0x72, 0x62, 0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b, 0x53, 0x69,
-0x62, 0x126, 0x64, 0x3b, 0x54, 0x6e, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53,
-0x62, 0x126, 0x64, 0x3b, 0x54, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62,
-0x52, 0x101, 0x74, 0x61, 0x70, 0x75, 0x3b, 0x52, 0x101, 0x68, 0x69, 0x6e, 0x61, 0x3b, 0x52, 0x101, 0x74, 0x16b, 0x3b, 0x52,
-0x101, 0x61, 0x70, 0x61, 0x3b, 0x52, 0x101, 0x70, 0x61, 0x72, 0x65, 0x3b, 0x52, 0x101, 0x6d, 0x65, 0x72, 0x65, 0x3b, 0x52,
-0x101, 0x68, 0x6f, 0x72, 0x6f, 0x69, 0x54, 0x61, 0x70, 0x3b, 0x48, 0x69, 0x6e, 0x3b, 0x54, 0x16b, 0x3b, 0x41, 0x70, 0x61,
-0x3b, 0x50, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x48, 0x6f, 0x72, 0x54, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b,
-0x50, 0x3b, 0x4d, 0x3b, 0x48, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e,
-0x902, 0x917, 0x933, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e,
-0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x930, 0x935, 0x93f,
-0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936,
-0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x41d, 0x44f, 0x43c, 0x3b, 0x414, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x41c, 0x44f,
-0x433, 0x43c, 0x430, 0x440, 0x3b, 0x41b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x41f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x411, 0x430,
-0x430, 0x441, 0x430, 0x43d, 0x3b, 0x411, 0x44f, 0x43c, 0x431, 0x430, 0x43d, 0x44f, 0x43c, 0x3b, 0x434, 0x430, 0x432, 0x430, 0x430, 0x3b,
-0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b, 0x43b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, 0x44d, 0x432, 0x3b,
-0x431, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b, 0x431, 0x44f, 0x43c, 0x431, 0x430, 0x41d, 0x44f, 0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f,
-0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b, 0x411, 0x44f, 0x906, 0x907, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938,
-0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e,
-0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936,
-0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x3b, 0x92c,
-0x941, 0x927, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x906, 0x3b, 0x938,
-0x94b, 0x3b, 0x92e, 0x3b, 0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0xb30, 0xb2c, 0xb3f, 0xb2c, 0xb3e, 0xb30,
-0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e, 0xb19, 0xb4d, 0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27,
-0xb2c, 0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30,
-0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b, 0xb2e, 0xb19, 0xb4d, 0xb17, 0xb33,
-0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb30,
-0x3b, 0xb38, 0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36, 0xb41, 0x3b, 0xb36, 0x64a, 0x648, 0x646, 0x6cd,
-0x3b, 0x62f, 0x648, 0x646, 0x6cd, 0x3b, 0x62f, 0x631, 0x6d0, 0x646, 0x6cd, 0x3b, 0x685, 0x644, 0x631, 0x646, 0x6cd, 0x3b, 0x67e, 0x64a,
-0x646, 0x681, 0x646, 0x6cd, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b, 0x627, 0x648, 0x646, 0x6cd, 0x6cc, 0x6a9, 0x634, 0x646, 0x628, 0x647,
-0x3b, 0x62f, 0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x686, 0x647, 0x627, 0x631,
-0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b, 0x634, 0x646,
-0x628, 0x647, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x6e, 0x69, 0x65, 0x64, 0x7a,
-0x69, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61, 0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74,
-0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x15b, 0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65, 0x6b, 0x3b,
-0x70, 0x69, 0x105, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x2e, 0x3b,
-0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b, 0x63, 0x7a, 0x77, 0x2e, 0x3b, 0x70, 0x74,
-0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x6e,
-0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x15b, 0x3b, 0x63, 0x3b, 0x70, 0x3b, 0x73, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b,
-0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x2d,
-0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71,
-0x75, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x2d, 0x66, 0x65,
-0x69, 0x72, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x73, 0x65, 0x67, 0x2e, 0x3b,
-0x74, 0x65, 0x72, 0x2e, 0x3b, 0x71, 0x75, 0x61, 0x2e, 0x3b, 0x71, 0x75, 0x69, 0x2e, 0x3b, 0x73, 0x65, 0x78, 0x2e, 0x3b,
-0x73, 0xe1, 0x62, 0x2e, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53, 0x64, 0x6f, 0x6d,
-0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x3b, 0x71,
-0x75, 0x61, 0x72, 0x74, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x3b, 0x73,
-0xe1, 0x62, 0x61, 0x64, 0x6f, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e, 0xa70,
-0xa17, 0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa35, 0xa40, 0xa30, 0xa35, 0xa3e, 0xa30,
-0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0xa35, 0xa3e,
-0xa30, 0xa10, 0xa24, 0x3b, 0xa38, 0xa4b, 0xa2e, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0x3b, 0xa35, 0xa40,
-0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0xa10, 0x3b, 0xa38, 0xa4b,
-0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41, 0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0x3b, 0xa38, 0xa3c, 0x627, 0x62a,
-0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x64f, 0x62f, 0x6be, 0x3b, 0x62c, 0x645,
-0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
-0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0xe9, 0x72, 0x63,
-0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x4a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b,
-0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69,
-0xe9, 0x3b, 0x4a, 0x75, 0x65, 0x3b, 0x56, 0x69, 0x65, 0x3b, 0x53, 0x61, 0x62, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x58,
-0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x64, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x69, 0x61, 0x3b, 0x67, 0x6c, 0x69, 0x6e, 0x64,
-0x65, 0x73, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x73, 0x65, 0x6d, 0x6e, 0x61, 0x3b, 0x67,
-0x69, 0x65, 0x76, 0x67, 0x69, 0x61, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x69, 0x3b, 0x73, 0x6f, 0x6e, 0x64,
-0x61, 0x64, 0x75, 0x3b, 0x67, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69, 0x65, 0x3b, 0x76, 0x65,
-0x3b, 0x73, 0x6f, 0x44, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x64, 0x75, 0x6d, 0x69,
-0x6e, 0x69, 0x63, 0x103, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72,
-0x63, 0x75, 0x72, 0x69, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x3b, 0x73, 0xe2, 0x6d, 0x62,
-0x103, 0x74, 0x103, 0x64, 0x75, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69,
-0x65, 0x2e, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x2e, 0x3b, 0x73, 0xe2, 0x6d, 0x2e, 0x44, 0x75, 0x6d, 0x3b,
-0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x65, 0x3b, 0x4a, 0x6f, 0x69, 0x3b, 0x56, 0x69, 0x6e, 0x3b,
-0x53, 0xe2, 0x6d, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x432, 0x43e,
-0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438,
-0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432,
-0x435, 0x440, 0x433, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x431, 0x43e, 0x442, 0x430, 0x432,
-0x441, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x412,
-0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x42, 0x69, 0x6b, 0x75, 0x61, 0x2d, 0xf4, 0x6b,
-0x6f, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0xfb, 0x73, 0x65, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x70, 0x74,
-0xe2, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x75, 0x73, 0xef, 0xf6, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x6f,
-0x6b, 0xfc, 0x3b, 0x4c, 0xe2, 0x70, 0xf4, 0x73, 0xf6, 0x3b, 0x4c, 0xe2, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x42, 0x6b, 0x31,
-0x3b, 0x42, 0x6b, 0x32, 0x3b, 0x42, 0x6b, 0x33, 0x3b, 0x42, 0x6b, 0x34, 0x3b, 0x42, 0x6b, 0x35, 0x3b, 0x4c, 0xe2, 0x70,
-0x3b, 0x4c, 0xe2, 0x79, 0x4b, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x59, 0x43d, 0x435, 0x434,
-0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a,
-0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430,
-0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b,
-0x441, 0x440, 0x435, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x43d, 0x3b, 0x43f, 0x3b, 0x443,
-0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e,
-0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65,
-0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75,
-0x62, 0x6f, 0x74, 0x61, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x72, 0x3b, 0x10d, 0x65,
-0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f,
-0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x64, 0x65,
-0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61,
-0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74,
-0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
-0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434,
-0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431,
-0x43e, 0x442, 0x430, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x435, 0x442,
-0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x425, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x41a, 0x44a,
-0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x44b, 0x446,
-0x446, 0x4d5, 0x433, 0x3b, 0x426, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431,
-0x43e, 0x43d, 0x3b, 0x421, 0x430, 0x431, 0x430, 0x442, 0x445, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x43a, 0x44a,
-0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x434, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x44b, 0x446,
-0x446, 0x4d5, 0x433, 0x3b, 0x446, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x43c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431,
-0x43e, 0x43d, 0x3b, 0x441, 0x430, 0x431, 0x430, 0x442, 0x425, 0x446, 0x431, 0x3b, 0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b,
-0x4d4, 0x440, 0x442, 0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b, 0x421, 0x431, 0x442, 0x445, 0x446, 0x431, 0x3b, 0x43a,
-0x440, 0x441, 0x3b, 0x434, 0x446, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x3b, 0x446, 0x43f, 0x440, 0x3b, 0x43c, 0x440, 0x431, 0x3b, 0x441,
-0x431, 0x442, 0x425, 0x3b, 0x41a, 0x3b, 0x414, 0x3b, 0x4d4, 0x3b, 0x426, 0x3b, 0x41c, 0x3b, 0x421, 0x53, 0x76, 0x6f, 0x6e, 0x64,
-0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x68, 0x75, 0x72, 0x6f, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68,
-0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e, 0x75,
-0x3b, 0x4d, 0x75, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x53, 0x76, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x3b, 0x43, 0x68, 0x70,
-0x3b, 0x43, 0x68, 0x74, 0x3b, 0x43, 0x68, 0x6e, 0x3b, 0x43, 0x68, 0x73, 0x3b, 0x4d, 0x75, 0x67, 0x53, 0x3b, 0x4d, 0x3b,
-0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4d, 0x622, 0x686, 0x631, 0x3b, 0x633, 0x648, 0x645, 0x631, 0x3b, 0x627, 0x6b1,
-0x627, 0x631, 0x648, 0x3b, 0x627, 0x631, 0x628, 0x639, 0x3b, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x62c, 0x645, 0x639, 0x648, 0x3b, 0x687,
-0x646, 0x687, 0x631, 0x622, 0x686, 0x631, 0x3b, 0x633, 0x648, 0x3b, 0x627, 0x6b1, 0x627, 0x631, 0x648, 0x3b, 0x627, 0x631, 0x628, 0x639,
-0x3b, 0x62e, 0x645, 0x3b, 0x62c, 0x645, 0x639, 0x648, 0x3b, 0x687, 0x646, 0x687, 0x631, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3,
-0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb, 0xdd4, 0xdc0, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf,
-0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4, 0xdad, 0xdd2, 0xdb1, 0xdca, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4,
-0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xdc3, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b,
-0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb,
-0xdc4, 0xdc3, 0xdca, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xd89, 0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b,
-0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3, 0xdd2, 0x3b, 0xdc3, 0xdd9, 0x6e, 0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x70, 0x6f, 0x6e,
-0x64, 0x65, 0x6c, 0x6f, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x6f, 0x6b, 0x3b, 0x73, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b,
-0x161, 0x74, 0x76, 0x72, 0x74, 0x6f, 0x6b, 0x3b, 0x70, 0x69, 0x61, 0x74, 0x6f, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74,
-0x61, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b, 0x70, 0x69, 0x3b, 0x73,
-0x6f, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a,
-0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x65, 0x6b, 0x3b, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73,
-0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b, 0x3b, 0x73,
-0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b,
-0x73, 0x72, 0x65, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x6e,
-0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x41, 0x78, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e,
-0x69, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x6f, 0x3b, 0x41, 0x72, 0x62, 0x61, 0x63, 0x6f, 0x3b, 0x4b,
-0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d, 0x63, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x41, 0x78,
-0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x54, 0x6c, 0x64, 0x6f, 0x3b, 0x41, 0x72, 0x62, 0x63, 0x3b, 0x4b, 0x68, 0x6d, 0x73,
-0x3b, 0x4a, 0x6d, 0x63, 0x3b, 0x53, 0x62, 0x74, 0x69, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x68, 0x3b,
-0x4a, 0x3b, 0x53, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72,
-0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x6a, 0x75, 0x65, 0x76, 0x65, 0x73,
-0x3b, 0x76, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d, 0x2e, 0x3b,
-0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69, 0xe9, 0x2e, 0x3b, 0x6a, 0x75, 0x65, 0x2e, 0x3b,
-0x76, 0x69, 0x65, 0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b,
-0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x73, 0xf6, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61,
-0x67, 0x3b, 0x74, 0x69, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73,
-0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf6, 0x72, 0x64, 0x61, 0x67, 0x73, 0xf6, 0x6e,
-0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x66, 0x72,
-0x65, 0x3b, 0x6c, 0xf6, 0x72, 0x42f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x414, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x435,
-0x3b, 0x421, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x427, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x41f, 0x430,
-0x43d, 0x4b7, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x4b6, 0x443, 0x43c, 0x44a, 0x430, 0x3b, 0x428, 0x430, 0x43d, 0x431, 0x435, 0x42f,
-0x448, 0x431, 0x3b, 0x414, 0x448, 0x431, 0x3b, 0x421, 0x448, 0x431, 0x3b, 0x427, 0x448, 0x431, 0x3b, 0x41f, 0x448, 0x431, 0x3b, 0x4b6,
-0x43c, 0x44a, 0x3b, 0x428, 0x43d, 0x431, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x4b6, 0x3b, 0x428, 0xb9e,
-0xbbe, 0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0xbb5, 0xbbe,
-0xbaf, 0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0xbb4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbc6, 0xbb3,
-0xbcd, 0xbb3, 0xbbf, 0x3b, 0xb9a, 0xba9, 0xbbf, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0x2e, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0x2e, 0x3b, 0xb9a,
-0xbc6, 0xbb5, 0xbcd, 0x2e, 0x3b, 0xbaa, 0xbc1, 0xba4, 0x2e, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0x2e, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd,
-0x2e, 0x3b, 0xb9a, 0xba9, 0xbbf, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5, 0xbbf, 0x3b,
-0xbb5, 0xbc6, 0x3b, 0xb9a, 0x44f, 0x43a, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x434, 0x4af, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b,
-0x441, 0x438, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x43f, 0x4d9, 0x43d,
-0x497, 0x435, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x497, 0x43e, 0x43c, 0x433, 0x430, 0x3b, 0x448, 0x438, 0x43c, 0x431, 0x4d9, 0x44f,
-0x43a, 0x448, 0x2e, 0x3b, 0x434, 0x4af, 0x448, 0x2e, 0x3b, 0x441, 0x438, 0x448, 0x2e, 0x3b, 0x447, 0x4d9, 0x440, 0x2e, 0x3b, 0x43f,
-0x4d9, 0x43d, 0x497, 0x2e, 0x3b, 0x497, 0x43e, 0x43c, 0x2e, 0x3b, 0x448, 0x438, 0x43c, 0x2e, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b,
-0x427, 0x3b, 0x41f, 0x3b, 0x496, 0x3b, 0x428, 0xc06, 0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38, 0xc4b, 0xc2e, 0xc35, 0xc3e,
-0xc30, 0xc02, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b,
-0xc17, 0xc41, 0xc30, 0xc41, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36,
-0xc28, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0xc06, 0xc26, 0xc3f, 0x3b, 0xc38, 0xc4b, 0xc2e, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0x3b, 0xc2c,
-0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0x3b, 0xc36, 0xc28, 0xc3f, 0xc06, 0x3b, 0xc38,
-0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2c, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36, 0xc41, 0x3b, 0xc36, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17,
-0xe34, 0xe15, 0xe22, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe08, 0xe31, 0xe19, 0xe17, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe31,
-0xe07, 0xe04, 0xe32, 0xe23, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe38, 0xe18, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a,
-0xe1a, 0xe14, 0xe35, 0x3b, 0xe27, 0xe31, 0xe19, 0xe28, 0xe38, 0xe01, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23,
-0xe4c, 0xe2d, 0xe32, 0x2e, 0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24, 0x2e, 0x3b, 0xe28, 0x2e,
-0x3b, 0xe2a, 0x2e, 0xe2d, 0xe32, 0x3b, 0xe08, 0x3b, 0xe2d, 0x3b, 0xe1e, 0x3b, 0xe1e, 0xe24, 0x3b, 0xe28, 0x3b, 0xe2a, 0xf42, 0xf5f,
-0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f,
-0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54,
-0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b,
-0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58,
-0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66,
-0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0xf49, 0xf72, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf42, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b,
-0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xf66, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed,
-0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d,
-0x1230, 0x1295, 0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x1209, 0x3b, 0x1228, 0x1261, 0x3b, 0x1213, 0x1219, 0x3b, 0x12d3, 0x122d, 0x3b, 0x1240, 0x12f3,
-0x1230, 0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x1230, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1228,
-0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x53, 0x101, 0x70, 0x61, 0x74, 0x65, 0x3b, 0x4d, 0x14d, 0x6e, 0x69, 0x74, 0x65, 0x3b,
-0x54, 0x16b, 0x73, 0x69, 0x74, 0x65, 0x3b, 0x50, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x54, 0x75, 0x2bb, 0x61,
-0x70, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x46, 0x61, 0x6c, 0x61, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x6f, 0x6b,
-0x6f, 0x6e, 0x61, 0x6b, 0x69, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e, 0x3b, 0x54, 0x16b, 0x73, 0x3b, 0x50, 0x75, 0x6c,
-0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x3b, 0x46, 0x61, 0x6c, 0x3b, 0x54, 0x6f, 0x6b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x50,
-0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x54, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x74, 0x65, 0x73,
-0x69, 0x3b, 0x53, 0x61, 0x6c, 0x131, 0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x50, 0x65, 0x72, 0x15f,
-0x65, 0x6d, 0x62, 0x65, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x50,
-0x61, 0x7a, 0x3b, 0x50, 0x7a, 0x74, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0xc7, 0x61, 0x72, 0x3b, 0x50, 0x65, 0x72, 0x3b, 0x43,
-0x75, 0x6d, 0x3b, 0x43, 0x6d, 0x74, 0x50, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x43, 0xdd,
-0x65, 0x6b, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x44, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x53, 0x69, 0x15f, 0x65,
-0x6e, 0x62, 0x65, 0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x50, 0x65, 0x6e, 0x15f, 0x65, 0x6e, 0x62,
-0x65, 0x3b, 0x41, 0x6e, 0x6e, 0x61, 0x3b, 0x15e, 0x65, 0x6e, 0x62, 0x65, 0xfd, 0x65, 0x6b, 0x15f, 0x65, 0x6e, 0x62, 0x65,
-0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x73, 0x69, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0xe7, 0x61, 0x72,
-0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x70, 0x65, 0x6e, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x61, 0x6e, 0x6e, 0x61, 0x3b,
-0x15f, 0x65, 0x6e, 0x62, 0x65, 0xdd, 0x65, 0x6b, 0x3b, 0x44, 0x75, 0x15f, 0x3b, 0x53, 0x69, 0x15f, 0x3b, 0xc7, 0x61, 0x72,
-0x3b, 0x50, 0x65, 0x6e, 0x3b, 0x41, 0x6e, 0x6e, 0x3b, 0x15e, 0x65, 0x6e, 0xfd, 0x65, 0x6b, 0x3b, 0x64, 0x75, 0x15f, 0x3b,
-0x73, 0x69, 0x15f, 0x3b, 0xe7, 0x61, 0x72, 0x3b, 0x70, 0x65, 0x6e, 0x3b, 0x61, 0x6e, 0x6e, 0x3b, 0x15f, 0x65, 0x6e, 0xdd,
-0x3b, 0x44, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x15e, 0x64a, 0x6d5, 0x643, 0x634, 0x6d5, 0x646, 0x628, 0x6d5,
-0x3b, 0x62f, 0x6c8, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x633, 0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x686, 0x627,
-0x631, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x67e, 0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62c, 0x6c8, 0x645, 0x6d5,
-0x3b, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x64a, 0x6d5, 0x3b, 0x62f, 0x6c8, 0x3b, 0x633, 0x6d5, 0x3b, 0x686, 0x627, 0x3b, 0x67e, 0x6d5,
-0x3b, 0x62c, 0x6c8, 0x3b, 0x634, 0x6d5, 0x64a, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x43d,
-0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432, 0x442,
-0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x441, 0x435, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x43f,
-0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44f, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b,
-0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af,
-0x644, 0x3b, 0x628, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641,
-0x62a, 0x6c1, 0x79, 0x61, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x64, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61,
-0x3b, 0x73, 0x65, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61,
-0x3b, 0x70, 0x61, 0x79, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x68, 0x61, 0x6e,
-0x62, 0x61, 0x59, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0x73, 0x68, 0x3b, 0x53, 0x65, 0x73, 0x68, 0x3b, 0x43, 0x68, 0x6f, 0x72,
-0x3b, 0x50, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x68, 0x61, 0x6e, 0x59, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x43,
-0x3b, 0x50, 0x3b, 0x4a, 0x3b, 0x53, 0x6cc, 0x2e, 0x3b, 0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e, 0x3b, 0x67e, 0x2e,
-0x3b, 0x62c, 0x2e, 0x3b, 0x634, 0x2e, 0x44f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, 0x430, 0x43d, 0x431,
-0x430, 0x3b, 0x441, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x43f,
-0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x44f, 0x43a,
-0x448, 0x3b, 0x434, 0x443, 0x448, 0x3b, 0x441, 0x435, 0x448, 0x3b, 0x447, 0x43e, 0x440, 0x3b, 0x43f, 0x430, 0x439, 0x3b, 0x436, 0x443,
-0x43c, 0x3b, 0x448, 0x430, 0x43d, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x416, 0x3b, 0x428, 0x43, 0x68,
-0x1ee7, 0x20, 0x4e, 0x68, 0x1ead, 0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x48, 0x61, 0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42,
-0x61, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x54, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x4e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9,
-0x20, 0x53, 0xe1, 0x75, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x1ea3, 0x79, 0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32, 0x3b,
-0x54, 0x68, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x20, 0x34, 0x3b, 0x54, 0x68, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x20, 0x36, 0x3b,
-0x54, 0x68, 0x20, 0x37, 0x43, 0x4e, 0x3b, 0x54, 0x32, 0x3b, 0x54, 0x33, 0x3b, 0x54, 0x34, 0x3b, 0x54, 0x35, 0x3b, 0x54,
-0x36, 0x3b, 0x54, 0x37, 0x73, 0x75, 0x64, 0x65, 0x6c, 0x3b, 0x6d, 0x75, 0x64, 0x65, 0x6c, 0x3b, 0x74, 0x75, 0x64, 0x65,
-0x6c, 0x3b, 0x76, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x64, 0xf6, 0x64, 0x65, 0x6c, 0x3b, 0x66, 0x72, 0x69, 0x64, 0x65, 0x6c,
-0x3b, 0x7a, 0xe4, 0x64, 0x65, 0x6c, 0x53, 0x75, 0x3b, 0x4d, 0x75, 0x3b, 0x54, 0x75, 0x3b, 0x56, 0x65, 0x3b, 0x44, 0xf6,
-0x3b, 0x46, 0x72, 0x3b, 0x5a, 0xe4, 0x73, 0x75, 0x2e, 0x3b, 0x6d, 0x75, 0x2e, 0x3b, 0x74, 0x75, 0x2e, 0x3b, 0x76, 0x65,
-0x2e, 0x3b, 0x64, 0xf6, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x7a, 0xe4, 0x2e, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x56,
-0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x5a, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20,
-0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x44, 0x79, 0x64,
-0x64, 0x20, 0x4d, 0x65, 0x72, 0x63, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x49, 0x61, 0x75, 0x3b, 0x44,
-0x79, 0x64, 0x64, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x61, 0x64, 0x77,
-0x72, 0x6e, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49,
-0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d,
-0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x64, 0x53,
-0x3b, 0x4c, 0x6c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53, 0x44, 0x69, 0x62, 0xe9, 0x65, 0x72, 0x3b,
-0x41, 0x6c, 0x74, 0x69, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0xc0, 0x6c, 0x61, 0x72, 0x62,
-0x61, 0x3b, 0x41, 0x6c, 0x78, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0xc0, 0x6a, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x65,
-0x65, 0x72, 0x44, 0x69, 0x62, 0x3b, 0x41, 0x6c, 0x74, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0xc0, 0x6c, 0x61, 0x3b, 0x41, 0x6c,
-0x78, 0x3b, 0xc0, 0x6a, 0x6a, 0x3b, 0x41, 0x73, 0x65, 0x43, 0x61, 0x77, 0x65, 0x3b, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b,
-0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6e, 0x69, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68,
-0x75, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75,
-0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x43, 0x61, 0x77, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x42, 0x69, 0x6e,
-0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x5d6, 0x5d5, 0x5e0, 0x5d8,
-0x5d9, 0x5e7, 0x3b, 0x5de, 0x5d0, 0x5b8, 0x5e0, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5d3, 0x5d9, 0x5e0, 0x5e1, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5de,
-0x5d9, 0x5d8, 0x5d5, 0x5d5, 0x5d0, 0x5da, 0x3b, 0x5d3, 0x5d0, 0x5e0, 0x5e2, 0x5e8, 0x5e9, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5e4, 0x5bf, 0x5e8,
-0x5f2, 0x5b7, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73,
-0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b,
-0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0xec, 0x6b,
-0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xcc, 0x73, 0x1eb9, 0x301,
-0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b, 0x1ecc, 0x6a,
-0x1ecd, 0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61,
-0xc0, 0xec, 0x6b, 0x3b, 0x41, 0x6a, 0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0x3b, 0x1ecc,
-0x6a, 0x1ecd, 0x301, 0x62, 0x3b, 0x1eb8, 0x74, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0xc0, 0x3b, 0x41, 0x3b, 0xcc, 0x3b, 0x1ecc, 0x3b,
-0x1ecc, 0x3b, 0x1eb8, 0x3b, 0xc0, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75,
-0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b, 0x190, 0x74, 0xec, 0x3b,
-0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x186, 0x6a,
-0x254, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b,
-0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0x190,
-0x74, 0xec, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0xc0, 0xec, 0x6b, 0x3b,
-0x41, 0x6a, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62,
-0x3b, 0x190, 0x74, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0xc0, 0x3b, 0x41, 0x3b, 0xcc, 0x3b, 0x186, 0x3b, 0x186, 0x3b, 0x190, 0x3b,
-0xc0, 0x49, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x55, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b,
-0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61,
-0x74, 0x68, 0x75, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x68,
-0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x55, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73,
-0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67,
-0x71, 0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b, 0x4d, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67,
-0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x79, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61,
-0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61, 0x75,
-0x72, 0x64, 0x61, 0x67, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x79, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b,
-0x74, 0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x73, 0xf8, 0x2e, 0x3b, 0x6d, 0xe5, 0x2e, 0x3b, 0x74,
-0x79, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c, 0x61, 0x2e, 0x43d, 0x435,
-0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e,
-0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a,
-0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d,
-0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x438, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431,
-0x4a, 0x65, 0x64, 0x6f, 0x6f, 0x6e, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x6d,
-0x61, 0x79, 0x72, 0x74, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65, 0x69, 0x6e,
-0x3b, 0x4a, 0x65, 0x68, 0x65, 0x69, 0x6e, 0x65, 0x79, 0x3b, 0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x4a, 0x65, 0x64, 0x3b,
-0x4a, 0x65, 0x6c, 0x3b, 0x4a, 0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65,
-0x68, 0x3b, 0x4a, 0x65, 0x73, 0x64, 0x79, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x64, 0x79, 0x20, 0x4c, 0x75, 0x6e, 0x3b, 0x64,
-0x79, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b, 0x64,
-0x79, 0x20, 0x59, 0x6f, 0x77, 0x3b, 0x64, 0x79, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20, 0x53,
-0x61, 0x64, 0x6f, 0x72, 0x6e, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x74, 0x68, 0x3b, 0x4d, 0x68, 0x72,
-0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x4b, 0x77, 0x65, 0x73, 0x69, 0x64, 0x61, 0x3b,
-0x44, 0x77, 0x6f, 0x77, 0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x3b, 0x57, 0x75, 0x6b, 0x75, 0x64, 0x61,
-0x3b, 0x59, 0x61, 0x77, 0x64, 0x61, 0x3b, 0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x65, 0x6e, 0x65, 0x64, 0x61,
-0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, 0x65, 0x6e, 0x3b, 0x57, 0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77, 0x3b,
-0x46, 0x69, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x4b, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d,
-0x906, 0x92f, 0x924, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x93e, 0x930, 0x3b, 0x92c,
-0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x93e,
-0x930, 0x3b, 0x936, 0x947, 0x928, 0x935, 0x93e, 0x930, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917,
-0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x947, 0x53, 0x1ecd, 0x6e, 0x64, 0x65, 0x65, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b,
-0x54, 0x69, 0x75, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd,
-0x7a, 0x64, 0x65, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x64, 0x65, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x1ecd, 0x64, 0x65, 0x65,
-0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x3b, 0x54, 0x69, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x3b,
-0x46, 0x72, 0x61, 0x1ecb, 0x3b, 0x53, 0x61, 0x74, 0x57, 0x61, 0x20, 0x6b, 0x79, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x57, 0x61,
-0x20, 0x6b, 0x77, 0x61, 0x6d, 0x62, 0x129, 0x6c, 0x129, 0x6c, 0x79, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129,
-0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x57,
-0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x57, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74,
-0x169, 0x57, 0x6b, 0x79, 0x3b, 0x57, 0x6b, 0x77, 0x3b, 0x57, 0x6b, 0x6c, 0x3b, 0x57, 0x74, 0x169, 0x3b, 0x57, 0x6b, 0x6e,
-0x3b, 0x57, 0x74, 0x6e, 0x3b, 0x57, 0x74, 0x68, 0x59, 0x3b, 0x57, 0x3b, 0x45, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b,
-0x41, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x61,
-0x72, 0x73, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x73, 0x3b, 0x6a, 0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76, 0x69, 0x6e,
-0x61, 0x72, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x69, 0x64, 0x65, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61,
-0x72, 0x3b, 0x6d, 0x69, 0x65, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x6b, 0x254, 0x73,
-0x69, 0x256, 0x61, 0x3b, 0x64, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x62, 0x6c, 0x61, 0x256, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x61,
-0x3b, 0x79, 0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b, 0x66, 0x69, 0x256, 0x61, 0x3b, 0x6d, 0x65, 0x6d, 0x6c, 0x65, 0x256, 0x61,
-0x6b, 0x254, 0x73, 0x3b, 0x64, 0x7a, 0x6f, 0x3b, 0x62, 0x6c, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x3b, 0x79, 0x61, 0x77, 0x3b,
-0x66, 0x69, 0x256, 0x3b, 0x6d, 0x65, 0x6d, 0x6b, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6b, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d,
-0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x61, 0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61,
-0x6c, 0x75, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x6f, 0x6c, 0x75, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x68, 0x101, 0x3b,
-0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6f, 0x6e, 0x6f, 0x4c, 0x50, 0x3b, 0x50,
-0x31, 0x3b, 0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, 0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x4c, 0x69, 0x6e, 0x67,
-0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65,
-0x72, 0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65, 0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79, 0x65, 0x72,
-0x6e, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x4c, 0x69, 0x6e, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61,
-0x72, 0x3b, 0x4d, 0x69, 0x79, 0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x69, 0x79, 0x3b, 0x53, 0x61, 0x62, 0x53, 0x75, 0x6e,
-0x6e, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0xe4, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x5a, 0x69, 0x69, 0x73, 0x63, 0x68, 0x74,
-0x69, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75, 0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x73, 0x63, 0x68, 0x74, 0x69,
-0x67, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x74, 0x69, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x53,
-0x75, 0x2e, 0x3b, 0x4d, 0xe4, 0x2e, 0x3b, 0x5a, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46,
-0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0xa46d, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa2cd, 0x3b, 0xa18f, 0xa282, 0xa44d, 0x3b, 0xa18f, 0xa282,
-0xa315, 0x3b, 0xa18f, 0xa282, 0xa1d6, 0x3b, 0xa18f, 0xa282, 0xa26c, 0x3b, 0xa18f, 0xa282, 0xa0d8, 0xa46d, 0xa18f, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f,
-0xa44d, 0x3b, 0xa18f, 0xa315, 0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f, 0xa26c, 0x3b, 0xa18f, 0xa0d8, 0xa18f, 0x3b, 0xa2cd, 0x3b, 0xa44d, 0x3b, 0xa315,
-0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b, 0xa0d8, 0x53, 0xfc, 0x6e, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61,
-0x67, 0x3b, 0x44, 0x69, 0x6e, 0x67, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x64, 0x64, 0x65, 0x77, 0x65, 0x6b, 0x65,
-0x6e, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x65, 0x64, 0x61, 0x67,
-0x3b, 0x53, 0xfc, 0x6e, 0x6e, 0x61, 0x76, 0x65, 0x6e, 0x64, 0x53, 0xfc, 0x2e, 0x3b, 0x4d, 0x61, 0x2e, 0x3b, 0x44, 0x69,
-0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x73, 0x6f, 0x74,
-0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x6d,
-0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x6b,
-0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x64, 0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61,
-0x74, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72, 0x64, 0x61, 0x74, 0x73, 0x6f, 0x74, 0x6e, 0x3b, 0x76, 0x75, 0x6f, 0x73,
-0x3b, 0x6d, 0x61, 0x14b, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x3b,
-0x6c, 0xe1, 0x76, 0x53, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x73, 0x6f, 0x74, 0x6e,
-0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x6d, 0xe1, 0x6e, 0x6e, 0x6f, 0x64, 0x61, 0x74, 0x3b, 0x64, 0x69, 0x73,
-0x64, 0x61, 0x74, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72,
-0x61, 0x73, 0x74, 0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x74, 0x3b, 0x6c, 0xe1, 0x76, 0x76,
-0x6f, 0x72, 0x64, 0x61, 0x74, 0x73, 0x6f, 0x3b, 0x6d, 0xe1, 0x3b, 0x64, 0x69, 0x3b, 0x67, 0x61, 0x3b, 0x64, 0x75, 0x3b,
-0x62, 0x65, 0x3b, 0x6c, 0xe1, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x43, 0x68,
-0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x68,
-0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61,
-0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x63, 0x68, 0x75, 0x6d, 0x61, 0x3b, 0x45, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x43,
-0x70, 0x72, 0x3b, 0x43, 0x74, 0x74, 0x3b, 0x43, 0x6d, 0x6e, 0x3b, 0x43, 0x6d, 0x74, 0x3b, 0x41, 0x72, 0x73, 0x3b, 0x49,
-0x63, 0x6d, 0x3b, 0x45, 0x73, 0x74, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x45, 0x49,
-0x74, 0x75, 0x6b, 0x75, 0x20, 0x6a, 0x61, 0x20, 0x6a, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75,
-0x6b, 0x61, 0x20, 0x6a, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20,
-0x6b, 0x61, 0x77, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75,
-0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d,
-0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x69, 0x66, 0x75, 0x6c, 0x61, 0x20, 0x6e, 0x67,
-0x75, 0x77, 0x6f, 0x4a, 0x75, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b,
-0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4e, 0x67, 0x75, 0x4a, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
-0x4b, 0x3b, 0x4e, 0x64, 0x65, 0x77, 0x6f, 0x3b, 0x61, 0x61, 0x253, 0x6e, 0x64, 0x65, 0x3b, 0x6d, 0x61, 0x77, 0x62, 0x61,
-0x61, 0x72, 0x65, 0x3b, 0x6e, 0x6a, 0x65, 0x73, 0x6c, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x6e, 0x61, 0x61, 0x73, 0x61, 0x61,
-0x6e, 0x64, 0x65, 0x3b, 0x6d, 0x61, 0x77, 0x6e, 0x64, 0x65, 0x3b, 0x68, 0x6f, 0x6f, 0x72, 0x65, 0x2d, 0x62, 0x69, 0x69,
-0x72, 0x64, 0x65, 0x77, 0x3b, 0x61, 0x61, 0x253, 0x3b, 0x6d, 0x61, 0x77, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x6e, 0x61, 0x61,
-0x3b, 0x6d, 0x77, 0x64, 0x3b, 0x68, 0x62, 0x69, 0x64, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x6d, 0x3b,
-0x68, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4e, 0x6a,
-0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x61, 0x3b, 0x41, 0x72, 0x61,
-0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f,
-0x74, 0x68, 0x69, 0x4b, 0x4d, 0x41, 0x3b, 0x4e, 0x54, 0x54, 0x3b, 0x4e, 0x4d, 0x4e, 0x3b, 0x4e, 0x4d, 0x54, 0x3b, 0x41,
-0x52, 0x54, 0x3b, 0x4e, 0x4d, 0x41, 0x3b, 0x4e, 0x4d, 0x4d, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b,
-0x4e, 0x3b, 0x4e, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x61, 0x72, 0x65, 0x3b, 0x4d, 0x64, 0x65,
-0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65,
-0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20,
-0x69, 0x6e, 0x65, 0x74, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b, 0x4d,
-0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74,
-0x20, 0x65, 0x65, 0x20, 0x6b, 0x77, 0x65, 0x41, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x6e, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49,
-0x6e, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x4b, 0x77, 0x65, 0x41, 0x3b, 0x4b, 0x3b, 0x4f, 0x3b,
-0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x4b, 0x44, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x6f,
-0x73, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43,
-0x68, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x53, 0x61, 0x62, 0x75, 0x64,
-0x75, 0x44, 0x69, 0x6d, 0x3b, 0x50, 0x6f, 0x73, 0x3b, 0x50, 0x69, 0x72, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x69,
-0x3b, 0x53, 0x68, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x44, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x53, 0x3b,
-0x53, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b,
-0x53, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x53, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x68, 0x6c, 0x61, 0x6e,
-0x75, 0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x53, 0x69,
-0x62, 0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x53, 0x69, 0x68, 0x3b, 0x4d, 0x67, 0x71, 0x53, 0x3b, 0x4d,
-0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4d, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b,
-0x49, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x49,
-0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a,
-0x75, 0x6d, 0x61, 0x61, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x49, 0x6a, 0x70, 0x3b, 0x49, 0x6a,
-0x74, 0x3b, 0x49, 0x6a, 0x6e, 0x3b, 0x49, 0x6a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x49,
-0x6a, 0x6d, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x31, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30,
-0x2d59, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59,
-0x3b, 0x2d30, 0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30,
-0x2d59, 0x2d30, 0x2d59, 0x2d30, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x3b, 0x2d30, 0x2d3d, 0x2d61,
-0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x61, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b, 0x61, 0x79, 0x6e,
-0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x1e5b, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x77, 0x61,
-0x73, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73, 0x61, 0x73, 0x61,
-0x3b, 0x61, 0x79, 0x6e, 0x3b, 0x61, 0x73, 0x69, 0x3b, 0x61, 0x6b, 0x1e5b, 0x3b, 0x61, 0x6b, 0x77, 0x3b, 0x61, 0x73, 0x69,
-0x6d, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x41, 0x63, 0x65, 0x72, 0x3b, 0x41, 0x72, 0x69, 0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6d,
-0x3b, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x41, 0x6d, 0x68, 0x61, 0x64, 0x3b, 0x53, 0x65, 0x6d, 0x3b, 0x53, 0x65, 0x64, 0x59,
-0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x61, 0x73, 0x73,
-0x3b, 0x4b, 0x75, 0x1e93, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6d, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x61,
-0x73, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x61, 0x73, 0x73, 0x41, 0x63, 0x65, 0x3b, 0x41, 0x72, 0x69, 0x3b, 0x41, 0x72, 0x61,
-0x3b, 0x41, 0x68, 0x61, 0x3b, 0x41, 0x6d, 0x68, 0x3b, 0x53, 0x65, 0x6d, 0x3b, 0x53, 0x65, 0x64, 0x59, 0x61, 0x6e, 0x3b,
-0x53, 0x61, 0x6e, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x3b, 0x4b, 0x75, 0x1e93, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x1e0d, 0x69,
-0x73, 0x3b, 0x53, 0x61, 0x79, 0x59, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x43, 0x3b,
-0x52, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x44, 0x53, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x4f, 0x72, 0x77,
-0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b,
-0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61,
-0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6d, 0x75, 0x6b,
-0x61, 0x61, 0x67, 0x61, 0x53, 0x41, 0x4e, 0x3b, 0x4f, 0x52, 0x4b, 0x3b, 0x4f, 0x4b, 0x42, 0x3b, 0x4f, 0x4b, 0x53, 0x3b,
-0x4f, 0x4b, 0x4e, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4f, 0x4d, 0x4b, 0x53, 0x3b, 0x4b, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4e,
-0x3b, 0x54, 0x3b, 0x4d, 0x70, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68,
-0x61, 0x68, 0x75, 0x76, 0x69, 0x6c, 0x75, 0x68, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b,
-0x70, 0x61, 0x20, 0x68, 0x69, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x74, 0x61, 0x79, 0x69, 0x3b,
-0x70, 0x61, 0x20, 0x68, 0x69, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x6c, 0x65,
-0x6d, 0x62, 0x65, 0x6c, 0x61, 0x4d, 0x75, 0x6c, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x48, 0x69, 0x76, 0x3b, 0x48, 0x69, 0x64,
-0x3b, 0x48, 0x69, 0x74, 0x3b, 0x48, 0x69, 0x68, 0x3b, 0x4c, 0x65, 0x6d, 0x4d, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x48, 0x3b,
-0x48, 0x3b, 0x57, 0x3b, 0x4a, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x74, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e,
-0x75, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74,
-0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a,
-0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x6b, 0x61, 0x72, 0x69, 0x3b, 0x6e, 0x74, 0x25b, 0x6e, 0x25b, 0x3b, 0x74, 0x61, 0x72,
-0x61, 0x74, 0x61, 0x3b, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x6a, 0x75,
-0x6d, 0x61, 0x3b, 0x73, 0x69, 0x62, 0x69, 0x72, 0x69, 0x6b, 0x61, 0x72, 0x3b, 0x6e, 0x74, 0x25b, 0x3b, 0x74, 0x61, 0x72,
-0x3b, 0x61, 0x72, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x62, 0x4b, 0x3b, 0x4e, 0x3b,
-0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x53, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d,
-0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61,
-0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61,
-0x3b, 0x4e, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x69, 0x4b, 0x6d, 0x61, 0x3b, 0x54, 0x61, 0x74, 0x3b,
-0x49, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x41, 0x72, 0x6d, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4e, 0x4d, 0x4d, 0x4b,
-0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4e, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c6, 0x13cd, 0x13ac, 0x3b,
-0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e6, 0x13a2, 0x13c1, 0x13a2, 0x13a6, 0x3b,
-0x13c5, 0x13a9, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x13b6, 0x13cd, 0x13d7, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c8, 0x13d5, 0x13be,
-0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x3b, 0x13e6, 0x13a2, 0x13c1, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x3b,
-0x13e7, 0x13be, 0x13a9, 0x3b, 0x13c8, 0x13d5, 0x13be, 0x13c6, 0x3b, 0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6, 0x3b, 0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4,
-0x64, 0x69, 0x6d, 0x61, 0x6e, 0x73, 0x3b, 0x6c, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d,
-0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x7a, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x6e, 0x64, 0x72, 0x65, 0x64,
-0x69, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x69, 0x64, 0x69, 0x6d, 0x3b, 0x6c, 0x69, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d,
-0x65, 0x72, 0x3b, 0x7a, 0x65, 0x3b, 0x76, 0x61, 0x6e, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d,
-0x3b, 0x7a, 0x3b, 0x76, 0x3b, 0x73, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x70, 0x69, 0x6c, 0x69,
-0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x69, 0x64, 0x75,
-0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61,
-0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79,
-0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6c, 0x69, 0x6e, 0x6a, 0x69, 0x3b, 0x4c, 0x69, 0x64,
-0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x76,
-0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x4c, 0x6c,
-0x32, 0x3b, 0x4c, 0x6c, 0x33, 0x3b, 0x4c, 0x6c, 0x34, 0x3b, 0x4c, 0x6c, 0x35, 0x3b, 0x4c, 0x6c, 0x36, 0x3b, 0x4c, 0x6c,
-0x37, 0x3b, 0x4c, 0x6c, 0x31, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0xed, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x61, 0x6e,
-0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x6d, 0xed, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x6d, 0xf3, 0x6f, 0x73, 0x69, 0x50, 0xed, 0x69, 0x6c, 0x69, 0x3b, 0x54, 0xe1, 0x61, 0x74, 0x75, 0x3b, 0xcd,
-0x6e, 0x65, 0x3b, 0x54, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4d, 0xf3, 0x6f,
-0x73, 0x69, 0x50, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4d, 0x53, 0x61, 0x62, 0x62, 0x69,
-0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x62, 0x69, 0x72, 0x69,
-0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4c,
-0x77, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61,
-0x53, 0x61, 0x62, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x4c, 0x77, 0x32, 0x3b, 0x4c, 0x77, 0x33, 0x3b, 0x4c, 0x77, 0x34, 0x3b,
-0x4c, 0x77, 0x35, 0x3b, 0x4c, 0x77, 0x36, 0x53, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c,
-0x50, 0x61, 0x20, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6d, 0x6f,
-0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x62, 0x75, 0x6c, 0x69, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69,
-0x74, 0x61, 0x74, 0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63,
-0x68, 0x69, 0x73, 0x61, 0x6e, 0x6f, 0x3b, 0x50, 0x61, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6c, 0x75, 0x73, 0x68, 0x69, 0x64,
-0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b,
-0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65,
-0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d,
-0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73,
-0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65,
-0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61,
-0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x61, 0x62,
-0x61, 0x64, 0x75, 0x64, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x6b, 0x75, 0x61, 0x3b, 0x6b,
-0x69, 0x6e, 0x3b, 0x73, 0x65, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
-0x53, 0x3b, 0x53, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4d, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x6f, 0x3b, 0x57,
-0x61, 0x69, 0x72, 0x69, 0x3b, 0x57, 0x65, 0x74, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x61, 0x3b, 0x57, 0x65,
-0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4b, 0x49, 0x55, 0x3b, 0x4d, 0x52, 0x41,
-0x3b, 0x57, 0x41, 0x49, 0x3b, 0x57, 0x45, 0x54, 0x3b, 0x57, 0x45, 0x4e, 0x3b, 0x57, 0x54, 0x4e, 0x3b, 0x4a, 0x55, 0x4d,
-0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x4b, 0x6f, 0x74, 0x69, 0x73, 0x61, 0x70,
-0x3b, 0x4b, 0x6f, 0x74, 0x61, 0x61, 0x69, 0x3b, 0x4b, 0x6f, 0x61, 0x65, 0x6e, 0x67, 0x2019, 0x3b, 0x4b, 0x6f, 0x73, 0x6f,
-0x6d, 0x6f, 0x6b, 0x3b, 0x4b, 0x6f, 0x61, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d, 0x75, 0x75, 0x74,
-0x3b, 0x4b, 0x6f, 0x6c, 0x6f, 0x4b, 0x74, 0x73, 0x3b, 0x4b, 0x6f, 0x74, 0x3b, 0x4b, 0x6f, 0x6f, 0x3b, 0x4b, 0x6f, 0x73,
-0x3b, 0x4b, 0x6f, 0x61, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x4b, 0x6f, 0x6c, 0x54, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x53, 0x3b,
-0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6e,
-0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
-0x73, 0x3b, 0x57, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65,
-0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x46, 0x72, 0x61, 0x69, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65,
-0x65, 0x73, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x53, 0x6f, 0x6e, 0x3b,
-0x4d, 0x61, 0x3b, 0x44, 0x65, 0x3b, 0x57, 0x75, 0x3b, 0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x74, 0x53, 0x3b,
-0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x41, 0x53, 0x75, 0x6e, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68,
-0x3b, 0x4d, 0x6f, 0x68, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x6e, 0x6e, 0x73, 0x64, 0x61, 0x61, 0x63,
-0x68, 0x3b, 0x4d, 0x65, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x61,
-0x63, 0x68, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x64, 0x61, 0x61,
-0x63, 0x68, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x65, 0x2e, 0x3b, 0x44, 0x75,
-0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x6c, 0xed, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1,
-0x6e, 0x254, 0x3b, 0x41, 0x6c, 0x61, 0xe1, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x6d, 0xf3, 0x73, 0x69, 0x53, 0x61, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61,
-0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x73, 0x61, 0x74, 0x75,
-0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e, 0x75, 0x3b,
-0x4f, 0x6c, 0x6f, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x53, 0x61, 0x62, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x3b,
-0x4b, 0x75, 0x62, 0x69, 0x3b, 0x4b, 0x75, 0x73, 0x61, 0x3b, 0x4b, 0x75, 0x6e, 0x61, 0x3b, 0x4b, 0x75, 0x74, 0x61, 0x3b,
-0x4d, 0x75, 0x6b, 0x61, 0x53, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x4a, 0x75, 0x6d,
-0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e,
-0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61,
-0x20, 0x4b, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x74, 0x61,
-0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b,
-0x4a, 0x35, 0x3b, 0x41, 0x6c, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a,
-0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x6f, 0x4e, 0x61,
-0x6b, 0x61, 0x65, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x65, 0x62, 0x61, 0x72, 0x61, 0x73, 0x61, 0x3b,
-0x4e, 0x61, 0x6b, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x61, 0x6b, 0x61,
-0x75, 0x6e, 0x67, 0x2019, 0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x79, 0x3b, 0x4e, 0x61, 0x6b, 0x61,
-0x73, 0x61, 0x62, 0x69, 0x74, 0x69, 0x4a, 0x75, 0x6d, 0x3b, 0x42, 0x61, 0x72, 0x3b, 0x41, 0x61, 0x72, 0x3b, 0x55, 0x6e,
-0x69, 0x3b, 0x55, 0x6e, 0x67, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x53, 0x61, 0x62, 0x4a, 0x3b, 0x42, 0x3b, 0x41, 0x3b, 0x55,
-0x3b, 0x55, 0x3b, 0x4b, 0x3b, 0x53, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x69, 0x3b, 0x41,
-0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69,
-0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x73, 0x61, 0x62, 0x64, 0x75, 0x41, 0x6c,
-0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41, 0x6c,
-0x6a, 0x3b, 0x41, 0x73, 0x73, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x53, 0x4a, 0x75,
-0x6d, 0x61, 0x70, 0x69, 0x6c, 0x3b, 0x57, 0x75, 0x6f, 0x6b, 0x20, 0x54, 0x69, 0x63, 0x68, 0x3b, 0x54, 0x69, 0x63, 0x68,
-0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x54, 0x69, 0x63,
-0x68, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68,
-0x3b, 0x4e, 0x67, 0x65, 0x73, 0x6f, 0x4a, 0x4d, 0x50, 0x3b, 0x57, 0x55, 0x54, 0x3b, 0x54, 0x41, 0x52, 0x3b, 0x54, 0x41,
-0x44, 0x3b, 0x54, 0x41, 0x4e, 0x3b, 0x54, 0x41, 0x42, 0x3b, 0x4e, 0x47, 0x53, 0x4a, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x54,
-0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4e, 0x41, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b, 0x41, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x41,
-0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x72, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73,
-0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73, 0x41, 0x73, 0x61, 0x3b, 0x41, 0x79, 0x6e,
-0x3b, 0x41, 0x73, 0x6e, 0x3b, 0x41, 0x6b, 0x72, 0x3b, 0x41, 0x6b, 0x77, 0x3b, 0x41, 0x73, 0x6d, 0x3b, 0x41, 0x73, 0x1e0d,
-0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b,
-0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72,
-0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61, 0x3b,
-0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x41, 0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c,
-0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x7a, 0x3b, 0x41, 0x73, 0x69, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x70, 0x69,
-0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6e, 0x65, 0x3b,
-0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49,
-0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4a, 0x70, 0x69, 0x3b, 0x4a,
-0x74, 0x74, 0x3b, 0x4a, 0x6d, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a,
-0x6d, 0x6f, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x31, 0x930, 0x92c, 0x93f, 0x92c, 0x93e,
-0x930, 0x3b, 0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x926, 0x92c,
-0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x92c, 0x93e, 0x930,
-0x3b, 0x938, 0x941, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x930, 0x92c, 0x93f, 0x3b, 0x938, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b,
-0x92c, 0x941, 0x926, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f,
-0x930, 0x3b, 0x938, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x938, 0x941, 0x3b, 0x938, 0x941, 0x43a, 0x4c0,
-0x438, 0x440, 0x430, 0x3b, 0x43e, 0x440, 0x448, 0x43e, 0x442, 0x3b, 0x448, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x43a, 0x445, 0x430,
-0x430, 0x440, 0x430, 0x3b, 0x435, 0x430, 0x440, 0x430, 0x3b, 0x43f, 0x4c0, 0x435, 0x440, 0x430, 0x441, 0x43a, 0x430, 0x3b, 0x448, 0x443,
-0x43e, 0x442, 0x43a, 0x4c0, 0x438, 0x3b, 0x43e, 0x440, 0x3b, 0x448, 0x438, 0x3b, 0x43a, 0x445, 0x430, 0x3b, 0x435, 0x430, 0x3b, 0x43f,
-0x4c0, 0x435, 0x3b, 0x448, 0x443, 0x43e, 0x43a, 0x4c0, 0x3b, 0x43e, 0x3b, 0x448, 0x3b, 0x43a, 0x445, 0x3b, 0x435, 0x3b, 0x43f, 0x4c0,
-0x3b, 0x448, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x467, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x44c, 0x43d,
-0x438, 0x43a, 0x44a, 0x3b, 0x432, 0x442, 0x43e, 0x301, 0x440, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x300,
-0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x442, 0x43e, 0x301, 0x43a, 0x44a, 0x3b, 0x43f, 0x467, 0x442, 0x43e, 0x301, 0x43a, 0x44a,
-0x3b, 0x441, 0xa64b, 0x431, 0x431, 0x461, 0x301, 0x442, 0x430, 0x43d, 0x434, 0x2de7, 0x487, 0x467, 0x3b, 0x43f, 0x43d, 0x2de3, 0x435, 0x3b,
-0x432, 0x442, 0x43e, 0x2dec, 0x487, 0x3b, 0x441, 0x440, 0x2de3, 0x435, 0x3b, 0x447, 0x435, 0x2de6, 0x487, 0x3b, 0x43f, 0x467, 0x2de6, 0x487,
-0x3b, 0x441, 0xa64b, 0x2de0, 0x487, 0x4c, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4e, 0x6b, 0x6f, 0x64, 0x79, 0x61, 0x3b,
-0x4e, 0x64, 0xe0, 0x61, 0x79, 0xe0, 0x3b, 0x4e, 0x64, 0x61, 0x6e, 0x67, 0xf9, 0x3b, 0x4e, 0x6a, 0xf2, 0x77, 0x61, 0x3b,
-0x4e, 0x67, 0xf2, 0x76, 0x79, 0x61, 0x3b, 0x4c, 0x75, 0x62, 0x69, 0x6e, 0x67, 0x75, 0x4c, 0x75, 0x6d, 0x3b, 0x4e, 0x6b,
-0x6f, 0x3b, 0x4e, 0x64, 0x79, 0x3b, 0x4e, 0x64, 0x67, 0x3b, 0x4e, 0x6a, 0x77, 0x3b, 0x4e, 0x67, 0x76, 0x3b, 0x4c, 0x75,
-0x62, 0x4c, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4c, 0x53, 0x6f, 0x6e, 0x6e, 0x64, 0x65,
-0x67, 0x3b, 0x4d, 0xe9, 0x69, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x44, 0xeb, 0x6e, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b,
-0x4d, 0xeb, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67,
-0x3b, 0x46, 0x72, 0x65, 0x69, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x53, 0x6f,
-0x6e, 0x3b, 0x4d, 0xe9, 0x69, 0x3b, 0x44, 0xeb, 0x6e, 0x3b, 0x4d, 0xeb, 0x74, 0x3b, 0x44, 0x6f, 0x6e, 0x3b, 0x46, 0x72,
-0x65, 0x3b, 0x53, 0x61, 0x6d, 0x53, 0x6f, 0x6e, 0x2e, 0x3b, 0x4d, 0xe9, 0x69, 0x2e, 0x3b, 0x44, 0xeb, 0x6e, 0x2e, 0x3b,
-0x4d, 0xeb, 0x74, 0x2e, 0x3b, 0x44, 0x6f, 0x6e, 0x2e, 0x3b, 0x46, 0x72, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x6d, 0x2e, 0x74,
-0x73, 0x75, 0x294, 0x6e, 0x74, 0x73, 0x268, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x6b, 0x70, 0xe0, 0x3b, 0x74, 0x73, 0x75,
-0x294, 0x75, 0x67, 0x68, 0x254, 0x65, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x74, 0x254, 0x300, 0x6d, 0x6c, 0xf2, 0x3b, 0x74,
-0x73, 0x75, 0x294, 0x75, 0x6d, 0xe8, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67, 0x68, 0x268, 0x302, 0x6d, 0x3b, 0x74, 0x73,
-0x75, 0x294, 0x6e, 0x64, 0x7a, 0x268, 0x6b, 0x254, 0x294, 0x254, 0x6e, 0x74, 0x73, 0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x67, 0x68,
-0x254, 0x3b, 0x74, 0x254, 0x6d, 0x3b, 0x75, 0x6d, 0x65, 0x3b, 0x67, 0x68, 0x268, 0x3b, 0x64, 0x7a, 0x6b, 0x6e, 0x3b, 0x6b,
-0x3b, 0x67, 0x3b, 0x74, 0x3b, 0x75, 0x3b, 0x67, 0x3b, 0x64, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x254, 0x302, 0x79, 0x3b,
-0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x6a, 0x61, 0x14b, 0x67, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20,
-0xfb, 0x6d, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x14b, 0x67, 0xea, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6d, 0x62, 0x254,
-0x6b, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6b, 0x254, 0x254, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6a, 0xf4, 0x6e, 0x6e,
-0x254, 0x79, 0x3b, 0x6e, 0x6a, 0x61, 0x3b, 0x75, 0x75, 0x6d, 0x3b, 0x14b, 0x67, 0x65, 0x3b, 0x6d, 0x62, 0x254, 0x3b, 0x6b,
-0x254, 0x254, 0x3b, 0x6a, 0x6f, 0x6e, 0x6e, 0x3b, 0x6e, 0x3b, 0x75, 0x3b, 0x14b, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6a, 0x41,
-0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74,
-0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x6c,
-0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4d,
-0x3b, 0x5a, 0x3b, 0x53, 0xe9, 0x74, 0x69, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x6b, 0x77, 0x61, 0x73, 0xfa, 0x3b,
-0x6d, 0x75, 0x6b, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x14b, 0x67, 0x69, 0x73, 0xfa, 0x3b, 0x257, 0xf3, 0x6e, 0x25b, 0x73, 0xfa,
-0x3b, 0x65, 0x73, 0x61, 0x253, 0x61, 0x73, 0xfa, 0xe9, 0x74, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0x3b, 0x6b, 0x77, 0x61, 0x3b,
-0x6d, 0x75, 0x6b, 0x3b, 0x14b, 0x67, 0x69, 0x3b, 0x257, 0xf3, 0x6e, 0x3b, 0x65, 0x73, 0x61, 0x65, 0x3b, 0x6d, 0x3b, 0x6b,
-0x3b, 0x6d, 0x3b, 0x14b, 0x3b, 0x257, 0x3b, 0x65, 0x44, 0x69, 0x6d, 0x61, 0x73, 0x3b, 0x54, 0x65, 0x6e, 0x65, 0x14b, 0x3b,
-0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69,
-0x73, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x74, 0x69, 0x44, 0x69, 0x6d,
-0x3b, 0x54, 0x65, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x72, 0x6a,
-0x3b, 0x53, 0x69, 0x62, 0x44, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x53, 0x73, 0x254, 0x301,
-0x6e, 0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259,
-0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x62, 0x25b, 0x30c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c,
-0xfa, 0x20, 0x6d, 0x259, 0x301, 0x6c, 0x25b, 0x301, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa,
-0x20, 0x6d, 0x259, 0x301, 0x6e, 0x79, 0x69, 0x3b, 0x66, 0xfa, 0x6c, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0xe9, 0x72, 0x61, 0x64,
-0xe9, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73,
-0x6d, 0x6e, 0x3b, 0x66, 0xfa, 0x6c, 0x3b, 0x73, 0xe9, 0x72, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b,
-0x66, 0x3b, 0x73, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x1dd, 0x3b, 0x6c, 0x1dd, 0x6e, 0x64, 0xed, 0x3b, 0x6d, 0x61, 0x61, 0x64,
-0xed, 0x3b, 0x6d, 0x25b, 0x6b, 0x72, 0x25b, 0x64, 0xed, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x64, 0xed, 0x3b, 0x6a, 0xfa, 0x6d, 0x62,
-0xe1, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0xed, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6c, 0x1dd, 0x6e, 0x3b, 0x6d, 0x61, 0x61, 0x3b,
-0x6d, 0x25b, 0x6b, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x3b, 0x6a, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x6d, 0x73, 0x3b, 0x6c, 0x3b, 0x6d,
-0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x73, 0x53, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f,
-0x3b, 0x41, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x53, 0x61, 0x62, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74,
-0x6e, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x53, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a,
-0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x43, 0x6f, 0x6d, 0x2019, 0x79, 0x61, 0x6b, 0x6b, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6c,
-0x61, 0x61, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x69, 0x69, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d,
-0x6b, 0x6f, 0x6c, 0x6c, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6b, 0x61, 0x6c, 0x64, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x43,
-0x6f, 0x6d, 0x67, 0x61, 0x69, 0x73, 0x75, 0x75, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x65, 0x253, 0x73, 0x75, 0x75, 0x43,
-0x79, 0x61, 0x3b, 0x43, 0x6c, 0x61, 0x3b, 0x43, 0x7a, 0x69, 0x3b, 0x43, 0x6b, 0x6f, 0x3b, 0x43, 0x6b, 0x61, 0x3b, 0x43,
-0x67, 0x61, 0x3b, 0x43, 0x7a, 0x65, 0x59, 0x3b, 0x4c, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x47, 0x3b, 0x45, 0x73,
-0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20,
-0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x62, 0x61, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66,
-0xfa, 0x20, 0x6d, 0xe1, 0x6c, 0x61, 0x6c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20,
-0x6d, 0xe1, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x62, 0xe1, 0x67, 0xe1, 0x20, 0x6d, 0xe1, 0x20, 0x73, 0x75, 0x6b, 0x75, 0x6c,
-0x3b, 0x73, 0xe1, 0x73, 0x61, 0x64, 0x69, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62,
-0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x6d, 0x62, 0x73, 0x3b, 0x73, 0x61, 0x73, 0x73, 0x3b, 0x6d, 0x3b,
-0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x43, 0xe4, 0x14b, 0x20, 0x6b, 0x75, 0x254, 0x74, 0x68, 0x3b, 0x4a,
-0x69, 0x65, 0x63, 0x20, 0x6c, 0x61, 0x331, 0x74, 0x3b, 0x52, 0x25b, 0x77, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44,
-0x69, 0x254, 0x331, 0x6b, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x20, 0x6c, 0xe4, 0x74,
-0x6e, 0x69, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x42, 0xe4, 0x6b, 0x25b,
-0x6c, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x43, 0xe4, 0x14b, 0x3b, 0x4a, 0x69, 0x65, 0x63, 0x3b, 0x52, 0x25b, 0x77, 0x3b,
-0x44, 0x69, 0x254, 0x331, 0x6b, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x3b, 0x42,
-0xe4, 0x6b, 0x25b, 0x6c, 0x43, 0x3b, 0x4a, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x14a, 0x3b, 0x44, 0x3b, 0x42, 0x431, 0x430, 0x441,
-0x43a, 0x44b, 0x4bb, 0x44b, 0x430, 0x43d, 0x43d, 0x44c, 0x430, 0x3b, 0x431, 0x44d, 0x43d, 0x438, 0x434, 0x438, 0x44d, 0x43d, 0x43d, 0x44c,
-0x438, 0x43a, 0x3b, 0x43e, 0x43f, 0x442, 0x443, 0x43e, 0x440, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x43a, 0x3b, 0x441, 0x44d, 0x440, 0x44d,
-0x434, 0x44d, 0x3b, 0x447, 0x44d, 0x43f, 0x43f, 0x438, 0x44d, 0x440, 0x3b, 0x411, 0x44d, 0x44d, 0x442, 0x438, 0x4a5, 0x441, 0x44d, 0x3b,
-0x441, 0x443, 0x431, 0x443, 0x43e, 0x442, 0x430, 0x431, 0x441, 0x3b, 0x431, 0x43d, 0x3b, 0x43e, 0x43f, 0x3b, 0x441, 0x44d, 0x3b, 0x447,
-0x43f, 0x3b, 0x431, 0x44d, 0x3b, 0x441, 0x431, 0x411, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x411, 0x3b, 0x421,
-0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d,
-0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x6d,
-0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4d,
-0x75, 0x6c, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49,
-0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0xa55e,
-0xa54c, 0xa535, 0x3b, 0xa5f3, 0xa5e1, 0xa609, 0x3b, 0xa55a, 0xa55e, 0xa55a, 0x3b, 0xa549, 0xa55e, 0xa552, 0x3b, 0xa549, 0xa524, 0xa546, 0xa562, 0x3b,
-0xa549, 0xa524, 0xa540, 0xa56e, 0x3b, 0xa53b, 0xa52c, 0xa533, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x74, 0x25b, 0x25b, 0x6e, 0x25b,
-0x25b, 0x3b, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x69, 0x6d, 0x69, 0x73,
-0x61, 0x3b, 0x61, 0x69, 0x6a, 0x69, 0x6d, 0x61, 0x3b, 0x73, 0x69, 0x253, 0x69, 0x74, 0x69, 0x53, 0x75, 0x6e, 0x6e, 0x74,
-0x61, 0x67, 0x3b, 0x4d, 0xe4, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x5a, 0x69, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74,
-0x74, 0x77, 0x75, 0x10d, 0x3b, 0x46, 0x72, 0xf3, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x69, 0x74, 0x61, 0x67, 0x3b,
-0x53, 0x61, 0x6d, 0x161, 0x74, 0x61, 0x67, 0x53, 0x75, 0x6e, 0x3b, 0x4d, 0xe4, 0x6e, 0x3b, 0x5a, 0x69, 0x161, 0x3b, 0x4d,
-0x69, 0x74, 0x3b, 0x46, 0x72, 0xf3, 0x3b, 0x46, 0x72, 0x69, 0x3b, 0x53, 0x61, 0x6d, 0x53, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b,
-0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x53, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x25b, 0x3b, 0x6d, 0xf3, 0x6e, 0x64, 0x69,
-0x65, 0x3b, 0x6d, 0x75, 0xe1, 0x6e, 0x79, 0xe1, 0x14b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x65, 0x74, 0xfa,
-0x6b, 0x70, 0xed, 0xe1, 0x70, 0x25b, 0x3b, 0x6b, 0xfa, 0x70, 0xe9, 0x6c, 0x69, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0x69,
-0x61, 0x70, 0x25b, 0x3b, 0x66, 0x65, 0x6c, 0xe9, 0x74, 0x65, 0x3b, 0x73, 0xe9, 0x73, 0x65, 0x6c, 0xe9, 0x73, 0x64, 0x3b,
-0x6d, 0x64, 0x3b, 0x6d, 0x77, 0x3b, 0x65, 0x74, 0x3b, 0x6b, 0x6c, 0x3b, 0x66, 0x6c, 0x3b, 0x73, 0x73, 0x73, 0x3b, 0x6d,
-0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x73, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x6c, 0x6c,
-0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65,
-0x73, 0x3b, 0x78, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62,
-0x61, 0x64, 0x75, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0xe9, 0x3b, 0x78,
-0x75, 0x65, 0x3b, 0x76, 0x69, 0x65, 0x3b, 0x73, 0xe1, 0x62, 0x53, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x254, 0x301,
-0x6e, 0x64, 0x69, 0x3b, 0xc1, 0x70, 0x74, 0x61, 0x20, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x57, 0x25b, 0x301, 0x6e,
-0x25b, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x54, 0x254, 0x301, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x79, 0x25b,
-0x64, 0x25b, 0x3b, 0x53, 0xe1, 0x73, 0x69, 0x64, 0x25b, 0x53, 0x254, 0x301, 0x3b, 0x4d, 0x254, 0x301, 0x3b, 0xc1, 0x4d, 0x3b,
-0x57, 0x25b, 0x301, 0x3b, 0x54, 0x254, 0x301, 0x3b, 0x46, 0x25b, 0x3b, 0x53, 0xe1, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x6c,
-0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x25b, 0x72, 0x6b, 0x25b, 0x72, 0x25b, 0x64, 0x69,
-0x3b, 0x79, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x14b, 0x64, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x6d, 0x254, 0x6e, 0x254,
-0x20, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x73, 0x6f, 0x3b, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x25b, 0x3b, 0x79, 0x65,
-0x3b, 0x76, 0x61, 0x3b, 0x6d, 0x73, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x31, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x32, 0x3b,
-0x41, 0x6e, 0x65, 0x67, 0x20, 0x33, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x34, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x35,
-0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x36, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x37, 0x41, 0x31, 0x3b, 0x41, 0x32, 0x3b,
-0x41, 0x33, 0x3b, 0x41, 0x34, 0x3b, 0x41, 0x35, 0x3b, 0x41, 0x36, 0x3b, 0x41, 0x37, 0x6c, 0x79, 0x25b, 0x2bc, 0x25b, 0x301,
-0x20, 0x73, 0x1e85, 0xed, 0x14b, 0x74, 0xe8, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d,
-0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x74,
-0x73, 0xe8, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e,
-0x74, 0xe8, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x76,
-0x66, 0xf2, 0x20, 0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c,
-0x79, 0x25b, 0x30c, 0x2bc, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd28, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804,
-0xdd25, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd27, 0xd804, 0xdd01,
-0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd23, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd2a, 0xd804,
-0xdd16, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd25,
-0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2a, 0xd804, 0xdd07, 0xd804,
-0xdd34, 0xd804, 0xdd07, 0xd804, 0xdd2e, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd27,
-0xd804, 0xdd1a, 0xd804, 0xdd28, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd28, 0x3b, 0xd804,
-0xdd25, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd27, 0xd804, 0xdd01, 0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd23,
-0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd2a, 0xd804, 0xdd16, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28,
-0xd804, 0xdd25, 0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2a, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd07, 0xd804,
-0xdd2e, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd27, 0xd804, 0xdd1a, 0xd804, 0xdd28, 0xd804, 0xdd22, 0xd804, 0xdd27, 0x3b, 0xd804,
-0xdd25, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22,
-0xd804, 0xdd28, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd27, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61,
-0x6b, 0x21f, 0x61, 0x14b, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x14b, 0x17e, 0x69, 0x3b, 0x41, 0x14b, 0x70,
-0xe9, 0x74, 0x75, 0x6e, 0x75, 0x14b, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x79, 0x61, 0x6d, 0x6e, 0x69,
-0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x7a, 0x61,
-0x70, 0x74, 0x61, 0x14b, 0x3b, 0x4f, 0x77, 0xe1, 0x14b, 0x67, 0x79, 0x75, 0x17e, 0x61, 0x17e, 0x61, 0x70, 0x69, 0x41, 0x3b,
-0x57, 0x3b, 0x4e, 0x3b, 0x59, 0x3b, 0x54, 0x3b, 0x5a, 0x3b, 0x4f, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d62,
-0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d61,
-0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x6cc, 0x6d5,
-0x6a9, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x62f, 0x648, 0x648, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x633, 0x6ce, 0x634, 0x6d5,
-0x645, 0x645, 0x6d5, 0x3b, 0x686, 0x648, 0x627, 0x631, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x67e, 0x6ce, 0x646, 0x62c, 0x634, 0x6d5,
-0x645, 0x645, 0x6d5, 0x3b, 0x6be, 0x6d5, 0x6cc, 0x646, 0x6cc, 0x3b, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633,
-0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x6be, 0x3b, 0x634, 0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x6a,
-0x65, 0x17a, 0x65, 0x6c, 0x65, 0x3b, 0x77, 0x61, 0x142, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x6f, 0x64, 0x61,
-0x3b, 0x73, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b, 0x70, 0x11b, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61,
-0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x61, 0x142, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x73, 0x74, 0x77, 0x3b,
-0x70, 0x11b, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x73,
-0x6e, 0x6a, 0x65, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x77, 0x75,
-0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b,
-0x70, 0x6a, 0x61, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b,
-0x77, 0x75, 0x74, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x161, 0x74, 0x77, 0x3b, 0x70, 0x6a, 0x61, 0x3b, 0x73, 0x6f, 0x62, 0x6e,
-0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x6e, 0x61, 0x64, 0x12b, 0x6c, 0x69, 0x3b, 0x70,
-0x61, 0x6e, 0x61, 0x64, 0x12b, 0x6c, 0x69, 0x3b, 0x77, 0x69, 0x73, 0x61, 0x73, 0x12b, 0x64, 0x69, 0x73, 0x3b, 0x70, 0x75,
-0x73, 0x73, 0x69, 0x73, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x74, 0x77, 0x69, 0x72, 0x74, 0x69, 0x6b,
-0x73, 0x3b, 0x70, 0x113, 0x6e, 0x74, 0x6e, 0x69, 0x6b, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x74, 0x69, 0x6b, 0x61,
-0x6e, 0x61, 0x64, 0x3b, 0x70, 0x61, 0x6e, 0x3b, 0x77, 0x69, 0x73, 0x3b, 0x70, 0x75, 0x73, 0x3b, 0x6b, 0x65, 0x74, 0x3b,
-0x70, 0x113, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x53,
-0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x72, 0x67, 0xe2, 0x3b,
-0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6b, 0x6f, 0x73, 0x6b, 0x6f, 0x6b, 0x6b, 0x6f, 0x3b, 0x74,
-0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0xe2, 0x68, 0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70, 0x65, 0x69, 0x76, 0x69,
-0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0xe2, 0x68, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x65, 0x69, 0x76, 0x69, 0x3b,
-0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x61, 0x72, 0x67,
-0xe2, 0x3b, 0x6b, 0x6f, 0x73, 0x6b, 0x6f, 0x68, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0x75, 0x76, 0x3b,
-0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70, 0x65, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0x75,
-0x76, 0x70, 0x61, 0x73, 0x3b, 0x76, 0x75, 0x6f, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6b, 0x6f, 0x73, 0x3b, 0x74, 0x75, 0x6f,
-0x3b, 0x76, 0xe1, 0x73, 0x3b, 0x6c, 0xe1, 0x76, 0x70, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x56, 0x3b,
-0x4c, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65,
-0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65, 0x72, 0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65, 0x62, 0x65, 0x73,
-0x3b, 0x42, 0x69, 0x79, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x44, 0x6f, 0x6d, 0x3b,
-0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x6b, 0x73, 0x3b, 0x48, 0x75, 0x3b, 0x42, 0x69, 0x3b, 0x53, 0x61,
-0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x42, 0x3b, 0x53
+static constexpr char16_t days_data[] = {
+0x53, 0x75, 0x6e, 0x64, 0x61, 0x79, 0x3b, 0x4d, 0x6f, 0x6e, 0x64, 0x61,
+0x79, 0x3b, 0x54, 0x75, 0x65, 0x73, 0x64, 0x61, 0x79, 0x3b, 0x57, 0x65,
+0x64, 0x6e, 0x65, 0x73, 0x64, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x75, 0x72,
+0x73, 0x64, 0x61, 0x79, 0x3b, 0x46, 0x72, 0x69, 0x64, 0x61, 0x79, 0x3b,
+0x53, 0x61, 0x74, 0x75, 0x72, 0x64, 0x61, 0x79, 0x53, 0x75, 0x6e, 0x3b,
+0x4d, 0x6f, 0x6e, 0x3b, 0x54, 0x75, 0x65, 0x3b, 0x57, 0x65, 0x64, 0x3b,
+0x54, 0x68, 0x75, 0x3b, 0x46, 0x72, 0x69, 0x3b, 0x53, 0x61, 0x74, 0x53,
+0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x53,
+0x37, 0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b,
+0x36, 0x410, 0x43c, 0x4bd, 0x44b, 0x448, 0x430, 0x3b, 0x410, 0x448, 0x4d9, 0x430,
+0x445, 0x44c, 0x430, 0x3b, 0x410, 0x4a9, 0x430, 0x448, 0x430, 0x3b, 0x410, 0x445,
+0x430, 0x448, 0x430, 0x3b, 0x410, 0x525, 0x448, 0x44c, 0x430, 0x448, 0x430, 0x3b,
+0x410, 0x445, 0x4d9, 0x430, 0x448, 0x430, 0x3b, 0x410, 0x441, 0x430, 0x431, 0x448,
+0x430, 0x410, 0x43c, 0x3b, 0x410, 0x448, 0x4d9, 0x3b, 0x410, 0x4a9, 0x3b, 0x410,
+0x445, 0x3b, 0x410, 0x525, 0x3b, 0x410, 0x445, 0x4d9, 0x3b, 0x410, 0x441, 0x41c,
+0x3b, 0x428, 0x4d9, 0x3b, 0x4a8, 0x3b, 0x425, 0x3b, 0x524, 0x3b, 0x425, 0x4d9,
+0x3b, 0x421, 0x41, 0x63, 0x61, 0x61, 0x64, 0x61, 0x3b, 0x45, 0x74, 0x6c,
+0x65, 0x65, 0x6e, 0x69, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61,
+0x3b, 0x41, 0x72, 0x62, 0x61, 0x71, 0x61, 0x3b, 0x4b, 0x61, 0x6d, 0x69,
+0x69, 0x73, 0x69, 0x3b, 0x47, 0x75, 0x6d, 0x71, 0x61, 0x74, 0x61, 0x3b,
+0x53, 0x61, 0x62, 0x74, 0x69, 0x41, 0x63, 0x61, 0x3b, 0x45, 0x74, 0x6c,
+0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x61, 0x6d,
+0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x41, 0x3b, 0x45, 0x3b,
+0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x53, 0x6f, 0x6e,
+0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b,
+0x44, 0x69, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x57, 0x6f, 0x65, 0x6e,
+0x73, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64,
+0x61, 0x67, 0x3b, 0x56, 0x72, 0x79, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x61,
+0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x61,
+0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x57, 0x6f, 0x2e, 0x3b, 0x44, 0x6f,
+0x2e, 0x3b, 0x56, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x53, 0x3b, 0x4d,
+0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x53, 0x74, 0x73,
+0x75, 0x294, 0x6e, 0x74, 0x73, 0x268, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75,
+0x6b, 0x70, 0xe0, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67, 0x68, 0x254,
+0x65, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x74, 0x254, 0x300, 0x6d, 0x6c,
+0xf2, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x6d, 0xe8, 0x3b, 0x74, 0x73,
+0x75, 0x294, 0x75, 0x67, 0x68, 0x268, 0x302, 0x6d, 0x3b, 0x74, 0x73, 0x75,
+0x294, 0x6e, 0x64, 0x7a, 0x268, 0x6b, 0x254, 0x294, 0x254, 0x6e, 0x74, 0x73,
+0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x67, 0x68, 0x254, 0x3b, 0x74, 0x254, 0x6d,
+0x3b, 0x75, 0x6d, 0x65, 0x3b, 0x67, 0x68, 0x268, 0x3b, 0x64, 0x7a, 0x6b,
+0x6e, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x74, 0x3b, 0x75, 0x3b, 0x67, 0x3b,
+0x64, 0x4b, 0x77, 0x65, 0x73, 0x69, 0x64, 0x61, 0x3b, 0x44, 0x77, 0x6f,
+0x77, 0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x3b, 0x57,
+0x75, 0x6b, 0x75, 0x64, 0x61, 0x3b, 0x59, 0x61, 0x77, 0x64, 0x61, 0x3b,
+0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x65, 0x6e, 0x65, 0x64,
+0x61, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, 0x65, 0x6e,
+0x3b, 0x57, 0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77, 0x3b, 0x46, 0x69, 0x61,
+0x3b, 0x4d, 0x65, 0x6d, 0x4b, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x57, 0x3b,
+0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x65, 0x20, 0x64, 0x69, 0x65, 0x6c, 0x3b,
+0x65, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0x74, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb,
+0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x70,
+0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x73, 0x68, 0x74, 0x75,
+0x6e, 0xeb, 0x64, 0x69, 0x65, 0x3b, 0x68, 0xeb, 0x6e, 0x3b, 0x6d, 0x61,
+0x72, 0x3b, 0x6d, 0xeb, 0x72, 0x3b, 0x65, 0x6e, 0x6a, 0x3b, 0x70, 0x72,
+0x65, 0x3b, 0x73, 0x68, 0x74, 0x64, 0x3b, 0x68, 0x3b, 0x6d, 0x3b, 0x6d,
+0x3b, 0x65, 0x3b, 0x70, 0x3b, 0x73, 0x68, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230,
+0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x129e, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210,
+0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x12a5, 0x1211,
+0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x3b, 0x1228, 0x1261, 0x12d5,
+0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c,
+0x12a5, 0x3b, 0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b,
+0x1245, 0x627, 0x644, 0x623, 0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627, 0x62b, 0x646,
+0x64a, 0x646, 0x3b, 0x627, 0x644, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b,
+0x627, 0x644, 0x623, 0x631, 0x628, 0x639, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x62e,
+0x645, 0x64a, 0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x627,
+0x644, 0x633, 0x628, 0x62a, 0x62d, 0x3b, 0x646, 0x3b, 0x62b, 0x3b, 0x631, 0x3b,
+0x62e, 0x3b, 0x62c, 0x3b, 0x633, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x63, 0x68,
+0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x7a,
+0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x72, 0x65, 0x73, 0x3b, 0x63, 0x68,
+0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x72, 0x6e, 0x65,
+0x73, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d, 0x3b,
+0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0x65, 0x3b,
+0x63, 0x68, 0x75, 0x3b, 0x76, 0x69, 0x65, 0x3b, 0x73, 0x61, 0x62, 0x44,
+0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x43, 0x68, 0x3b,
+0x56, 0x3b, 0x53, 0x56f, 0x56b, 0x580, 0x561, 0x56f, 0x56b, 0x3b, 0x565, 0x580,
+0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x565, 0x580, 0x565,
+0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x579, 0x578, 0x580, 0x565, 0x584,
+0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x570, 0x56b, 0x576, 0x563, 0x577, 0x561,
+0x562, 0x569, 0x56b, 0x3b, 0x578, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x577,
+0x561, 0x562, 0x561, 0x569, 0x56f, 0x56b, 0x580, 0x3b, 0x565, 0x580, 0x56f, 0x3b,
+0x565, 0x580, 0x584, 0x3b, 0x579, 0x580, 0x584, 0x3b, 0x570, 0x576, 0x563, 0x3b,
+0x578, 0x582, 0x580, 0x3b, 0x577, 0x562, 0x569, 0x53f, 0x3b, 0x535, 0x3b, 0x535,
+0x3b, 0x549, 0x3b, 0x540, 0x3b, 0x548, 0x3b, 0x547, 0x9a6, 0x9c7, 0x993, 0x9ac,
+0x9be, 0x9f0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999,
+0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be,
+0x9f0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be,
+0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6,
+0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x9a6, 0x9c7, 0x993, 0x3b, 0x9b8, 0x9cb, 0x9ae,
+0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac,
+0x9c3, 0x9b9, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf,
+0x9a6, 0x3b, 0x9b8, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x3b, 0x9ac, 0x3b, 0x9b6, 0x3b,
+0x9b6, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x6c, 0x6c, 0x75,
+0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d,
+0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x78, 0x75, 0x65,
+0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b,
+0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x6c,
+0x75, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0xe9, 0x3b, 0x78, 0x75,
+0x65, 0x3b, 0x76, 0x69, 0x65, 0x3b, 0x73, 0xe1, 0x62, 0x44, 0x3b, 0x4c,
+0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x4a, 0x75,
+0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
+0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68,
+0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4a, 0x70, 0x69,
+0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e,
+0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x6f,
+0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b,
+0x4a, 0x57, 0x61, 0x69, 0x20, 0x59, 0x6f, 0x6b, 0x61, 0x20, 0x42, 0x61,
+0x77, 0x61, 0x69, 0x3b, 0x57, 0x61, 0x69, 0x20, 0x54, 0x75, 0x6e, 0x67,
+0x61, 0x3b, 0x54, 0x6f, 0x6b, 0x69, 0x20, 0x47, 0x69, 0x74, 0x75, 0x6e,
+0x67, 0x3b, 0x54, 0x73, 0x61, 0x6d, 0x20, 0x4b, 0x61, 0x73, 0x75, 0x77,
+0x61, 0x3b, 0x57, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x20, 0x4e, 0x61, 0x73,
+0x3b, 0x57, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x20, 0x54, 0x69, 0x79, 0x6f,
+0x6e, 0x3b, 0x57, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x20, 0x43, 0x68, 0x69,
+0x72, 0x69, 0x6d, 0x59, 0x6f, 0x6b, 0x3b, 0x54, 0x75, 0x6e, 0x67, 0x3b,
+0x47, 0x69, 0x74, 0x75, 0x6e, 0x67, 0x3b, 0x54, 0x73, 0x61, 0x6e, 0x3b,
+0x4e, 0x61, 0x73, 0x3b, 0x4e, 0x61, 0x74, 0x3b, 0x43, 0x68, 0x69, 0x72,
+0x62, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72, 0x20,
+0x65, 0x72, 0x74, 0x259, 0x73, 0x69, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259,
+0x6e, 0x62, 0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0xe7,
+0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x3b, 0x63, 0xfc, 0x6d, 0x259,
+0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0x63, 0xfc, 0x6d, 0x259,
+0x3b, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45,
+0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e,
+0x41, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x42, 0x2e, 0x3b, 0x42,
+0x2e, 0x65, 0x2e, 0x3b, 0xc7, 0x2e, 0x61, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b,
+0x43, 0x2e, 0x61, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x431, 0x430,
+0x437, 0x430, 0x440, 0x3b, 0x431, 0x430, 0x437, 0x430, 0x440, 0x20, 0x435, 0x440,
+0x442, 0x4d9, 0x441, 0x438, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43d, 0x431,
+0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x447, 0x4d9, 0x440,
+0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x4b9, 0x4af, 0x43c, 0x4d9, 0x20, 0x430,
+0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x4b9, 0x4af, 0x43c, 0x4d9, 0x3b, 0x448,
+0x4d9, 0x43d, 0x431, 0x4d9, 0x411, 0x2e, 0x3b, 0x411, 0x2e, 0x415, 0x2e, 0x3b,
+0x427, 0x2e, 0x410, 0x2e, 0x3b, 0x427, 0x2e, 0x3b, 0x4b8, 0x2e, 0x410, 0x2e,
+0x3b, 0x4b8, 0x2e, 0x3b, 0x428, 0x2e, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x1dd,
+0x3b, 0x6c, 0x1dd, 0x6e, 0x64, 0xed, 0x3b, 0x6d, 0x61, 0x61, 0x64, 0xed,
+0x3b, 0x6d, 0x25b, 0x6b, 0x72, 0x25b, 0x64, 0xed, 0x3b, 0x6a, 0x1dd, 0x1dd,
+0x64, 0xed, 0x3b, 0x6a, 0xfa, 0x6d, 0x62, 0xe1, 0x3b, 0x73, 0x61, 0x6d,
+0x64, 0xed, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6c, 0x1dd, 0x6e, 0x3b, 0x6d,
+0x61, 0x61, 0x3b, 0x6d, 0x25b, 0x6b, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x3b, 0x6a,
+0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x6d, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b,
+0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x73, 0x6b, 0x61, 0x72, 0x69, 0x3b,
+0x6e, 0x74, 0x25b, 0x6e, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x61, 0x74, 0x61,
+0x3b, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x69,
+0x73, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x69, 0x62, 0x69,
+0x72, 0x69, 0x6b, 0x61, 0x72, 0x3b, 0x6e, 0x74, 0x25b, 0x3b, 0x74, 0x61,
+0x72, 0x3b, 0x61, 0x72, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x3b, 0x6a, 0x75,
+0x6d, 0x3b, 0x73, 0x69, 0x62, 0x4b, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x41,
+0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x53, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0,
+0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997,
+0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b,
+0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b,
+0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf,
+0x9ac, 0x9be, 0x9b0, 0x9b0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae,
+0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9,
+0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x3b,
+0x9b6, 0x9a8, 0x9bf, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x9c1,
+0x3b, 0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6, 0x14b, 0x67, 0x77, 0xe0,
+0x20, 0x6e, 0x254, 0x302, 0x79, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e,
+0x6a, 0x61, 0x14b, 0x67, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x14b, 0x67, 0x77,
+0xe0, 0x20, 0xfb, 0x6d, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x14b, 0x67,
+0xea, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6d, 0x62, 0x254, 0x6b, 0x3b,
+0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6b, 0x254, 0x254, 0x3b, 0x14b, 0x67, 0x77,
+0xe0, 0x20, 0x6a, 0xf4, 0x6e, 0x6e, 0x254, 0x79, 0x3b, 0x6e, 0x6a, 0x61,
+0x3b, 0x75, 0x75, 0x6d, 0x3b, 0x14b, 0x67, 0x65, 0x3b, 0x6d, 0x62, 0x254,
+0x3b, 0x6b, 0x254, 0x254, 0x3b, 0x6a, 0x6f, 0x6e, 0x6e, 0x3b, 0x6e, 0x3b,
+0x75, 0x3b, 0x14b, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6a, 0x69, 0x67, 0x61,
+0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68,
+0x65, 0x6e, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x72, 0x74, 0x65,
+0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61,
+0x3b, 0x6f, 0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73,
+0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x6c, 0x61, 0x72, 0x75, 0x6e,
+0x62, 0x61, 0x74, 0x61, 0x69, 0x67, 0x2e, 0x3b, 0x61, 0x6c, 0x2e, 0x3b,
+0x61, 0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x2e, 0x3b, 0x6f, 0x67, 0x2e, 0x3b,
+0x6f, 0x72, 0x2e, 0x3b, 0x6c, 0x72, 0x2e, 0x49, 0x3b, 0x41, 0x3b, 0x41,
+0x3b, 0x41, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x4c, 0x43d, 0x44f, 0x434, 0x437,
+0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b,
+0x430, 0x43a, 0x3b, 0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441,
+0x435, 0x440, 0x430, 0x434, 0x430, 0x3b, 0x447, 0x430, 0x446, 0x432, 0x435, 0x440,
+0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431,
+0x43e, 0x442, 0x430, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b,
+0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x43d,
+0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441,
+0x50, 0x61, 0x20, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x50,
+0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6d, 0x6f, 0x3b, 0x50, 0x61, 0x6c,
+0x69, 0x63, 0x68, 0x69, 0x62, 0x75, 0x6c, 0x69, 0x3b, 0x50, 0x61, 0x6c,
+0x69, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x50, 0x61, 0x6c,
+0x69, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63,
+0x68, 0x69, 0x73, 0x61, 0x6e, 0x6f, 0x3b, 0x50, 0x61, 0x63, 0x68, 0x69,
+0x62, 0x65, 0x6c, 0x75, 0x73, 0x68, 0x69, 0x70, 0x61, 0x20, 0x6d, 0x75,
+0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61,
+0x68, 0x75, 0x76, 0x69, 0x6c, 0x75, 0x68, 0x61, 0x3b, 0x70, 0x61, 0x20,
+0x68, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69,
+0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x74, 0x61,
+0x79, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x68, 0x61, 0x6e, 0x75,
+0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x6c, 0x65, 0x6d,
+0x62, 0x65, 0x6c, 0x61, 0x4d, 0x75, 0x6c, 0x3b, 0x56, 0x69, 0x6c, 0x3b,
+0x48, 0x69, 0x76, 0x3b, 0x48, 0x69, 0x64, 0x3b, 0x48, 0x69, 0x74, 0x3b,
+0x48, 0x69, 0x68, 0x3b, 0x4c, 0x65, 0x6d, 0x4d, 0x3b, 0x4a, 0x3b, 0x48,
+0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x4a, 0x930, 0x92c, 0x940, 0x92c,
+0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902,
+0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930,
+0x3b, 0x92c, 0x943, 0x939, 0x938, 0x94d, 0x92a, 0x924, 0x93f, 0x92c, 0x93e, 0x930,
+0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x928,
+0x940, 0x91a, 0x930, 0x1230, 0x1295, 0x1260, 0x122d, 0x20, 0x1245, 0x12f3, 0x12c5, 0x3b,
+0x1230, 0x1291, 0x3b, 0x1230, 0x120a, 0x131d, 0x3b, 0x1208, 0x1313, 0x20, 0x12c8, 0x122a,
+0x20, 0x1208, 0x1265, 0x12cb, 0x3b, 0x12a3, 0x121d, 0x12f5, 0x3b, 0x12a3, 0x122d, 0x1265,
+0x3b, 0x1230, 0x1295, 0x1260, 0x122d, 0x20, 0x123d, 0x1313, 0x12c5, 0x1230, 0x2f, 0x1245,
+0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x120a, 0x131d, 0x3b, 0x1208, 0x1313, 0x3b, 0x12a3,
+0x121d, 0x12f5, 0x3b, 0x12a3, 0x122d, 0x1265, 0x3b, 0x1230, 0x2f, 0x123d, 0x1230, 0x3b,
+0x1230, 0x3b, 0x1230, 0x3b, 0x1208, 0x3b, 0x12a3, 0x3b, 0x12a3, 0x3b, 0x1230, 0x930,
+0x92c, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b,
+0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c,
+0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938, 0x94d, 0x925, 0x93f, 0x92c, 0x93e, 0x930,
+0x3b, 0x938, 0x941, 0x941, 0x916, 0x941, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x938,
+0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x930, 0x92c, 0x93f, 0x92c, 0x93e, 0x930, 0x3b,
+0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e,
+0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938,
+0x94d, 0x925, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930,
+0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x930, 0x92c,
+0x93f, 0x3b, 0x938, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941,
+0x927, 0x3b, 0x92c, 0x93f, 0x938, 0x94d, 0x925, 0x93f, 0x3b, 0x938, 0x941, 0x916,
+0x941, 0x930, 0x3b, 0x938, 0x928, 0x93f, 0x930, 0x3b, 0x938, 0x3b, 0x92e, 0x902,
+0x3b, 0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x938, 0x941, 0x3b, 0x938, 0x6e,
+0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65,
+0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72,
+0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d,
+0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61,
+0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x65, 0x64, 0x3b,
+0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x69, 0x3b,
+0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x6e,
+0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73,
+0x4e, 0x3b, 0x50, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b,
+0x53, 0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
+0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440,
+0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447,
+0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430,
+0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x43d, 0x435, 0x434, 0x3b,
+0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x438, 0x3b,
+0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x43d,
+0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441,
+0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x72,
+0x7a, 0x68, 0x3b, 0x4d, 0x65, 0x72, 0x63, 0x2bc, 0x68, 0x65, 0x72, 0x3b,
+0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b,
+0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75,
+0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x2e, 0x3b, 0x4d, 0x65, 0x72, 0x2e, 0x3b,
+0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x2e, 0x3b, 0x53, 0x61,
+0x64, 0x2e, 0x53, 0x75, 0x3b, 0x4c, 0x3b, 0x4d, 0x7a, 0x3b, 0x4d, 0x63,
+0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53, 0x61, 0x43d, 0x435, 0x434, 0x435, 0x43b,
+0x44f, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a,
+0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x44f,
+0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x44a, 0x440, 0x442, 0x44a, 0x43a,
+0x3b, 0x43f, 0x435, 0x442, 0x44a, 0x43a, 0x3b, 0x441, 0x44a, 0x431, 0x43e, 0x442,
+0x430, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440,
+0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x43d, 0x3b, 0x43f,
+0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x1010, 0x1014,
+0x1004, 0x103a, 0x1039, 0x1002, 0x1014, 0x103d, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a,
+0x1039, 0x101c, 0x102c, 0x3b, 0x1021, 0x1004, 0x103a, 0x1039, 0x1002, 0x102b, 0x3b, 0x1017,
+0x102f, 0x1012, 0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c, 0x101e,
+0x1015, 0x1010, 0x1031, 0x1038, 0x3b, 0x101e, 0x1031, 0x102c, 0x1000, 0x103c, 0x102c, 0x3b,
+0x1005, 0x1014, 0x1031, 0x1010, 0x3b, 0x1010, 0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000,
+0x3b, 0x101e, 0x3b, 0x1005, 0x661f, 0x671f, 0x65e5, 0x3b, 0x661f, 0x671f, 0x4e00, 0x3b,
+0x661f, 0x671f, 0x4e8c, 0x3b, 0x661f, 0x671f, 0x4e09, 0x3b, 0x661f, 0x671f, 0x56db, 0x3b,
+0x661f, 0x671f, 0x4e94, 0x3b, 0x661f, 0x671f, 0x516d, 0x65e5, 0x3b, 0x4e00, 0x3b, 0x4e8c,
+0x3b, 0x4e09, 0x3b, 0x56db, 0x3b, 0x4e94, 0x3b, 0x516d, 0x5468, 0x65e5, 0x3b, 0x5468,
+0x4e00, 0x3b, 0x5468, 0x4e8c, 0x3b, 0x5468, 0x4e09, 0x3b, 0x5468, 0x56db, 0x3b, 0x5468,
+0x4e94, 0x3b, 0x5468, 0x516d, 0x64, 0x69, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x65,
+0x3b, 0x64, 0x69, 0x6c, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d,
+0x61, 0x72, 0x74, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x65, 0x63, 0x72, 0x65,
+0x73, 0x3b, 0x64, 0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76,
+0x65, 0x6e, 0x64, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x73, 0x73, 0x61,
+0x62, 0x74, 0x65, 0x64, 0x67, 0x2e, 0x3b, 0x64, 0x6c, 0x2e, 0x3b, 0x64,
+0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64, 0x6a, 0x2e, 0x3b, 0x64,
+0x76, 0x2e, 0x3b, 0x64, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
+0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74,
+0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65, 0x72, 0x6b, 0x75, 0x6c, 0x65,
+0x73, 0x3b, 0x48, 0x75, 0x77, 0x65, 0x62, 0x65, 0x73, 0x3b, 0x42, 0x69,
+0x79, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64,
+0x6f, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72,
+0x3b, 0x4d, 0x69, 0x79, 0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x69, 0x79,
+0x3b, 0x53, 0x61, 0x62, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b,
+0x48, 0x3b, 0x42, 0x3b, 0x53, 0x41, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b,
+0x41, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6e, 0x61, 0x73,
+0x3b, 0x41, 0x6b, 0x72, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x77, 0x61, 0x73,
+0x3b, 0x41, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69,
+0x1e0d, 0x79, 0x61, 0x73, 0x41, 0x73, 0x61, 0x3b, 0x41, 0x79, 0x6e, 0x3b,
+0x41, 0x73, 0x6e, 0x3b, 0x41, 0x6b, 0x72, 0x3b, 0x41, 0x6b, 0x77, 0x3b,
+0x41, 0x73, 0x6d, 0x3b, 0x41, 0x73, 0x1e0d, 0x41, 0x3b, 0x41, 0x3b, 0x41,
+0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x6cc, 0x6d5, 0x6a9, 0x634,
+0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x62f, 0x648, 0x648, 0x634, 0x6d5, 0x645, 0x645,
+0x6d5, 0x3b, 0x633, 0x6ce, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x686, 0x648,
+0x627, 0x631, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x67e, 0x6ce, 0x646, 0x62c,
+0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6be, 0x6d5, 0x6cc, 0x646, 0x6cc, 0x3b,
+0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686,
+0x3b, 0x67e, 0x3b, 0x6be, 0x3b, 0x634, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1d,
+0xd804, 0xdd28, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804,
+0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd1f, 0xd804, 0xdd27, 0xd804, 0xdd01, 0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd23,
+0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804,
+0xdd2a, 0xd804, 0xdd16, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd25, 0xd804, 0xdd2a,
+0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804,
+0xdd25, 0xd804, 0xdd2a, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd07, 0xd804, 0xdd2e, 0xd804,
+0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25,
+0xd804, 0xdd27, 0xd804, 0xdd1a, 0xd804, 0xdd28, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34,
+0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd25, 0xd804,
+0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd27, 0xd804, 0xdd01,
+0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804,
+0xdd2a, 0xd804, 0xdd16, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22,
+0xd804, 0xdd28, 0xd804, 0xdd25, 0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0x3b, 0xd804,
+0xdd25, 0xd804, 0xdd2a, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd07, 0xd804, 0xdd2e, 0xd804,
+0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd27, 0xd804, 0xdd1a, 0xd804, 0xdd28,
+0xd804, 0xdd22, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd1f,
+0xd804, 0xdd27, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd33,
+0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd25,
+0xd804, 0xdd27, 0x43a, 0x4c0, 0x438, 0x440, 0x430, 0x3b, 0x43e, 0x440, 0x448, 0x43e,
+0x442, 0x3b, 0x448, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x43a, 0x445, 0x430,
+0x430, 0x440, 0x430, 0x3b, 0x435, 0x430, 0x440, 0x430, 0x3b, 0x43f, 0x4c0, 0x435,
+0x440, 0x430, 0x441, 0x43a, 0x430, 0x3b, 0x448, 0x443, 0x43e, 0x442, 0x43a, 0x4c0,
+0x438, 0x3b, 0x43e, 0x440, 0x3b, 0x448, 0x438, 0x3b, 0x43a, 0x445, 0x430, 0x3b,
+0x435, 0x430, 0x3b, 0x43f, 0x4c0, 0x435, 0x3b, 0x448, 0x443, 0x43e, 0x43a, 0x4c0,
+0x3b, 0x43e, 0x3b, 0x448, 0x3b, 0x43a, 0x445, 0x3b, 0x435, 0x3b, 0x43f, 0x4c0,
+0x3b, 0x448, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13a4, 0x13be,
+0x13d9, 0x13d3, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x13a2, 0x13a6, 0x3b,
+0x13e6, 0x13a2, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x13a2, 0x13a6, 0x3b,
+0x13e7, 0x13be, 0x13a9, 0x13b6, 0x13cd, 0x13d7, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c8,
+0x13d5, 0x13be, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5,
+0x13c1, 0x3b, 0x13e6, 0x13a2, 0x13c1, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x3b, 0x13e7, 0x13be,
+0x13a9, 0x3b, 0x13c8, 0x13d5, 0x13be, 0x13c6, 0x3b, 0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6,
+0x3b, 0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4, 0x4e, 0x69, 0x74, 0x74, 0x61, 0x6b,
+0x20, 0x48, 0x6f, 0x6c, 0x6c, 0x6f, 0x2bc, 0x3b, 0x4d, 0x61, 0x6e, 0x74,
+0x69, 0x2bc, 0x3b, 0x43, 0x68, 0x6f, 0x73, 0x74, 0x69, 0x2bc, 0x3b, 0x57,
+0x69, 0x6e, 0x73, 0x74, 0x69, 0x2bc, 0x3b, 0x53, 0x6f, 0x69, 0x73, 0x74,
+0x69, 0x2bc, 0x3b, 0x4e, 0x61, 0x6e, 0x6e, 0x61, 0x6c, 0x68, 0x63, 0x68,
+0x69, 0x66, 0x61, 0x2bc, 0x20, 0x4e, 0x69, 0x74, 0x74, 0x61, 0x6b, 0x3b,
+0x4e, 0x69, 0x74, 0x74, 0x61, 0x6b, 0x20, 0x48, 0x6f, 0x6c, 0x6c, 0x6f,
+0x2bc, 0x20, 0x4e, 0x61, 0x6b, 0x66, 0x69, 0x73, 0x68, 0x53, 0x61, 0x6e,
+0x64, 0x65, 0x3b, 0x4f, 0x72, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e,
+0x7a, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72,
+0x69, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74,
+0x75, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f,
+0x72, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4f,
+0x72, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x53, 0x41,
+0x4e, 0x3b, 0x4f, 0x52, 0x4b, 0x3b, 0x4f, 0x4b, 0x42, 0x3b, 0x4f, 0x4b,
+0x53, 0x3b, 0x4f, 0x4b, 0x4e, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4f, 0x4d,
+0x4b, 0x53, 0x3b, 0x4b, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54,
+0x3b, 0x4d, 0x9031, 0x65e5, 0x3b, 0x9031, 0x4e00, 0x3b, 0x9031, 0x4e8c, 0x3b, 0x9031,
+0x4e09, 0x3b, 0x9031, 0x56db, 0x3b, 0x9031, 0x4e94, 0x3b, 0x9031, 0x516d, 0x43d, 0x435,
+0x434, 0x463, 0x301, 0x43b, 0x467, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x463,
+0x301, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x432, 0x442, 0x43e, 0x301,
+0x440, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x300,
+0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x442, 0x43e, 0x301, 0x43a, 0x44a,
+0x3b, 0x43f, 0x467, 0x442, 0x43e, 0x301, 0x43a, 0x44a, 0x3b, 0x441, 0xa64b, 0x431,
+0x431, 0x461, 0x301, 0x442, 0x430, 0x43d, 0x434, 0x2de7, 0x487, 0x467, 0x3b, 0x43f,
+0x43d, 0x2de3, 0x435, 0x3b, 0x432, 0x442, 0x43e, 0x2dec, 0x487, 0x3b, 0x441, 0x440,
+0x2de3, 0x435, 0x3b, 0x447, 0x435, 0x2de6, 0x487, 0x3b, 0x43f, 0x467, 0x2de6, 0x487,
+0x3b, 0x441, 0xa64b, 0x2de0, 0x487, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421,
+0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x432, 0x44b, 0x440, 0x441, 0x430, 0x440,
+0x43d, 0x438, 0x43a, 0x443, 0x43d, 0x3b, 0x442, 0x443, 0x43d, 0x442, 0x438, 0x43a,
+0x443, 0x43d, 0x3b, 0x44b, 0x442, 0x43b, 0x430, 0x440, 0x438, 0x43a, 0x443, 0x43d,
+0x3b, 0x44e, 0x43d, 0x43a, 0x443, 0x43d, 0x3b, 0x43a, 0x4d7, 0x4ab, 0x43d, 0x435,
+0x440, 0x43d, 0x438, 0x43a, 0x443, 0x43d, 0x3b, 0x44d, 0x440, 0x43d, 0x435, 0x43a,
+0x443, 0x43d, 0x3b, 0x448, 0x4d1, 0x43c, 0x430, 0x442, 0x43a, 0x443, 0x43d, 0x432,
+0x44b, 0x440, 0x2e, 0x3b, 0x442, 0x443, 0x43d, 0x2e, 0x3b, 0x44b, 0x442, 0x43b,
+0x2e, 0x3b, 0x44e, 0x43d, 0x2e, 0x3b, 0x43a, 0x4d7, 0x4ab, 0x2e, 0x3b, 0x44d,
+0x440, 0x2e, 0x3b, 0x448, 0x4d1, 0x43c, 0x2e, 0x412, 0x3b, 0x422, 0x3b, 0x42b,
+0x3b, 0x42e, 0x3b, 0x41a, 0x3b, 0x42d, 0x3b, 0x428, 0x53, 0x75, 0x6e, 0x6e,
+0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x6f, 0x68, 0x6e, 0x64, 0x61,
+0x61, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x6e, 0x6e, 0x73, 0x64, 0x61, 0x61,
+0x63, 0x68, 0x3b, 0x4d, 0x65, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44,
+0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b,
+0x46, 0x72, 0x69, 0x69, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x53, 0x61,
+0x6d, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x53, 0x75, 0x2e, 0x3b, 0x4d,
+0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x65, 0x2e, 0x3b, 0x44,
+0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x53, 0x3b,
+0x4d, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x53, 0x64,
+0x79, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x64, 0x79, 0x20, 0x4c, 0x75, 0x6e,
+0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x64,
+0x79, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20,
+0x59, 0x6f, 0x77, 0x3b, 0x64, 0x79, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65,
+0x72, 0x3b, 0x64, 0x79, 0x20, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x53,
+0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x74, 0x68, 0x3b, 0x4d,
+0x68, 0x72, 0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53,
+0x61, 0x64, 0x64, 0x75, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x6c,
+0x75, 0x6e, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x3b, 0x6d, 0x65,
+0x72, 0x63, 0x75, 0x72, 0x69, 0x3b, 0x67, 0x68, 0x6a, 0x6f, 0x76, 0x69,
+0x3b, 0x76, 0x65, 0x6e, 0x6e, 0x65, 0x72, 0x69, 0x3b, 0x73, 0x61, 0x62,
+0x62, 0x61, 0x74, 0x75, 0x64, 0x75, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e,
+0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e, 0x3b,
+0x67, 0x68, 0x6a, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61,
+0x62, 0x2e, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b,
+0x56, 0x3b, 0x53, 0x6e, 0x65, 0x64, 0x11b, 0x6c, 0x65, 0x3b, 0x70, 0x6f,
+0x6e, 0x64, 0x11b, 0x6c, 0xed, 0x3b, 0xfa, 0x74, 0x65, 0x72, 0xfd, 0x3b,
+0x73, 0x74, 0x159, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x74, 0x76, 0x72, 0x74,
+0x65, 0x6b, 0x3b, 0x70, 0xe1, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62,
+0x6f, 0x74, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0xfa, 0x74, 0x3b,
+0x73, 0x74, 0x3b, 0x10d, 0x74, 0x3b, 0x70, 0xe1, 0x3b, 0x73, 0x6f, 0x4e,
+0x3b, 0x50, 0x3b, 0xda, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53,
+0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x6e, 0x64, 0x61,
+0x67, 0x3b, 0x74, 0x69, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e,
+0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67,
+0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf8, 0x72, 0x64,
+0x61, 0x67, 0x73, 0xf8, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x6e, 0x2e, 0x3b,
+0x74, 0x69, 0x72, 0x73, 0x2e, 0x3b, 0x6f, 0x6e, 0x73, 0x2e, 0x3b, 0x74,
+0x6f, 0x72, 0x73, 0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b, 0x6c, 0xf8,
+0x72, 0x2e, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x54, 0x3b,
+0x46, 0x3b, 0x4c, 0x910, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e,
+0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b,
+0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x940, 0x930, 0x92c, 0x93e,
+0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936,
+0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x910, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b,
+0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x92c, 0x940, 0x930,
+0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x910, 0x3b,
+0x938, 0x94b, 0x3b, 0x92e, 0x2e, 0x3b, 0x92c, 0x941, 0x2e, 0x3b, 0x92c, 0x940,
+0x2e, 0x3b, 0x936, 0x941, 0x2e, 0x3b, 0x936, 0x2e, 0x910, 0x2e, 0x3b, 0x938,
+0x94b, 0x2e, 0x3b, 0x92e, 0x2e, 0x3b, 0x92c, 0x941, 0x2e, 0x3b, 0x92c, 0x940,
+0x2e, 0x3b, 0x936, 0x941, 0x2e, 0x3b, 0x936, 0x2e, 0xe9, 0x74, 0x69, 0x3b,
+0x6d, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x6b, 0x77, 0x61, 0x73, 0xfa, 0x3b,
+0x6d, 0x75, 0x6b, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x14b, 0x67, 0x69, 0x73,
+0xfa, 0x3b, 0x257, 0xf3, 0x6e, 0x25b, 0x73, 0xfa, 0x3b, 0x65, 0x73, 0x61,
+0x253, 0x61, 0x73, 0xfa, 0xe9, 0x74, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0x3b,
+0x6b, 0x77, 0x61, 0x3b, 0x6d, 0x75, 0x6b, 0x3b, 0x14b, 0x67, 0x69, 0x3b,
+0x257, 0xf3, 0x6e, 0x3b, 0x65, 0x73, 0x61, 0x65, 0x3b, 0x6d, 0x3b, 0x6b,
+0x3b, 0x6d, 0x3b, 0x14b, 0x3b, 0x257, 0x3b, 0x65, 0x7a, 0x6f, 0x6e, 0x64,
+0x61, 0x67, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x64,
+0x69, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x77, 0x6f, 0x65, 0x6e, 0x73,
+0x64, 0x61, 0x67, 0x3b, 0x64, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x61,
+0x67, 0x3b, 0x76, 0x72, 0x69, 0x6a, 0x64, 0x61, 0x67, 0x3b, 0x7a, 0x61,
+0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x7a, 0x6f, 0x3b, 0x6d, 0x61, 0x3b,
+0x64, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x64, 0x6f, 0x3b, 0x76, 0x72, 0x3b,
+0x7a, 0x61, 0x5a, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b,
+0x56, 0x3b, 0x5a, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62,
+0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b,
+0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b,
+0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0xf5f, 0xfb3, 0xf0b,
+0x3b, 0xf58, 0xf72, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0x3b, 0xf55,
+0xf74, 0xf62, 0xf0b, 0x3b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a,
+0xf53, 0xf0b, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf62,
+0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xfb6,
+0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0xf49, 0xf72, 0x4b, 0x69, 0x75, 0x6d,
+0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75,
+0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a,
+0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d,
+0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b,
+0x4e, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x69, 0x4b,
+0x6d, 0x61, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x49, 0x6e, 0x65, 0x3b, 0x54,
+0x61, 0x6e, 0x3b, 0x41, 0x72, 0x6d, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4e,
+0x4d, 0x4d, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x4e, 0xd801, 0xdc1d, 0xd801, 0xdc32, 0xd801, 0xdc4c, 0xd801, 0xdc3c, 0xd801,
+0xdc29, 0x3b, 0xd801, 0xdc23, 0xd801, 0xdc32, 0xd801, 0xdc4c, 0xd801, 0xdc3c, 0xd801, 0xdc29,
+0x3b, 0xd801, 0xdc13, 0xd801, 0xdc2d, 0xd801, 0xdc46, 0xd801, 0xdc3c, 0xd801, 0xdc29, 0x3b,
+0xd801, 0xdc0e, 0xd801, 0xdc2f, 0xd801, 0xdc4c, 0xd801, 0xdc46, 0xd801, 0xdc3c, 0xd801, 0xdc29,
+0x3b, 0xd801, 0xdc1b, 0xd801, 0xdc32, 0xd801, 0xdc49, 0xd801, 0xdc46, 0xd801, 0xdc3c, 0xd801,
+0xdc29, 0x3b, 0xd801, 0xdc19, 0xd801, 0xdc49, 0xd801, 0xdc34, 0xd801, 0xdc3c, 0xd801, 0xdc29,
+0x3b, 0xd801, 0xdc1d, 0xd801, 0xdc30, 0xd801, 0xdc3b, 0xd801, 0xdc32, 0xd801, 0xdc49, 0xd801,
+0xdc3c, 0xd801, 0xdc29, 0xd801, 0xdc1d, 0xd801, 0xdc32, 0xd801, 0xdc4c, 0x3b, 0xd801, 0xdc23,
+0xd801, 0xdc32, 0xd801, 0xdc4c, 0x3b, 0xd801, 0xdc13, 0xd801, 0xdc2d, 0xd801, 0xdc46, 0x3b,
+0xd801, 0xdc0e, 0xd801, 0xdc2f, 0xd801, 0xdc4c, 0x3b, 0xd801, 0xdc1b, 0xd801, 0xdc32, 0xd801,
+0xdc49, 0x3b, 0xd801, 0xdc19, 0xd801, 0xdc49, 0xd801, 0xdc34, 0x3b, 0xd801, 0xdc1d, 0xd801,
+0xdc30, 0xd801, 0xdc3b, 0xd801, 0xdc1d, 0x3b, 0xd801, 0xdc23, 0x3b, 0xd801, 0xdc13, 0x3b,
+0xd801, 0xdc0e, 0x3b, 0xd801, 0xdc1b, 0x3b, 0xd801, 0xdc19, 0x3b, 0xd801, 0xdc1d, 0x53,
+0x75, 0x2e, 0x3b, 0x4d, 0x2e, 0x3b, 0x54, 0x75, 0x2e, 0x3b, 0x57, 0x2e,
+0x3b, 0x54, 0x68, 0x2e, 0x3b, 0x46, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0xb7,
+0xd801, 0xdc55, 0xd801, 0xdc6d, 0xd801, 0xdc59, 0xd801, 0xdc5b, 0xd801, 0xdc71, 0x3b, 0xb7,
+0xd801, 0xdc65, 0xd801, 0xdc6d, 0xd801, 0xdc59, 0xd801, 0xdc5b, 0xd801, 0xdc71, 0x3b, 0xb7,
+0xd801, 0xdc51, 0xd801, 0xdc75, 0xd801, 0xdc5f, 0xd801, 0xdc5b, 0xd801, 0xdc71, 0x3b, 0xb7,
+0xd801, 0xdc62, 0xd801, 0xdc67, 0xd801, 0xdc59, 0xd801, 0xdc5f, 0xd801, 0xdc5b, 0xd801, 0xdc71,
+0x3b, 0xb7, 0xd801, 0xdc54, 0xd801, 0xdc7b, 0xd801, 0xdc5f, 0xd801, 0xdc5b, 0xd801, 0xdc71,
+0x3b, 0xb7, 0xd801, 0xdc53, 0xd801, 0xdc6e, 0xd801, 0xdc72, 0xd801, 0xdc5b, 0xd801, 0xdc71,
+0x3b, 0xb7, 0xd801, 0xdc55, 0xd801, 0xdc68, 0xd801, 0xdc5b, 0xd801, 0xdc7b, 0xd801, 0xdc5b,
+0xd801, 0xdc71, 0xb7, 0xd801, 0xdc55, 0xd801, 0xdc6d, 0x3b, 0xb7, 0xd801, 0xdc65, 0xd801,
+0xdc6d, 0x3b, 0xb7, 0xd801, 0xdc51, 0xd801, 0xdc75, 0x3b, 0xb7, 0xd801, 0xdc62, 0xd801,
+0xdc67, 0x3b, 0xb7, 0xd801, 0xdc54, 0xd801, 0xdc7b, 0x3b, 0xb7, 0xd801, 0xdc53, 0xd801,
+0xdc6e, 0x3b, 0xb7, 0xd801, 0xdc55, 0xd801, 0xdc68, 0xd801, 0xdc55, 0x3b, 0xd801, 0xdc65,
+0x3b, 0xd801, 0xdc51, 0x3b, 0xd801, 0xdc62, 0x3b, 0xd801, 0xdc54, 0x3b, 0xd801, 0xdc53,
+0x3b, 0xd801, 0xdc55, 0x442, 0x430, 0x440, 0x433, 0x43e, 0x447, 0x438, 0x3b, 0x430,
+0x442, 0x44f, 0x43d, 0x44c, 0x447, 0x438, 0x3b, 0x432, 0x430, 0x441, 0x442, 0x430,
+0x43d, 0x44c, 0x447, 0x438, 0x3b, 0x43a, 0x443, 0x43d, 0x448, 0x43a, 0x430, 0x447,
+0x438, 0x3b, 0x43a, 0x430, 0x43b, 0x43e, 0x43d, 0x44c, 0x447, 0x438, 0x3b, 0x441,
+0x44e, 0x43a, 0x43e, 0x43d, 0x44c, 0x447, 0x438, 0x3b, 0x448, 0x43b, 0x44f, 0x43c,
+0x43e, 0x447, 0x438, 0x442, 0x430, 0x440, 0x433, 0x43e, 0x447, 0x438, 0x441, 0x442,
+0x44d, 0x3b, 0x430, 0x442, 0x44f, 0x43d, 0x44c, 0x447, 0x438, 0x441, 0x442, 0x44d,
+0x3b, 0x432, 0x430, 0x441, 0x442, 0x430, 0x43d, 0x44c, 0x447, 0x438, 0x441, 0x442,
+0x44d, 0x3b, 0x43a, 0x443, 0x43d, 0x448, 0x43a, 0x430, 0x447, 0x438, 0x441, 0x442,
+0x44d, 0x3b, 0x43a, 0x430, 0x43b, 0x43e, 0x43d, 0x44c, 0x447, 0x438, 0x441, 0x442,
+0x44d, 0x3b, 0x441, 0x44e, 0x43a, 0x43e, 0x43d, 0x44c, 0x447, 0x438, 0x441, 0x442,
+0x44d, 0x3b, 0x448, 0x43b, 0x44f, 0x43c, 0x43e, 0x447, 0x438, 0x441, 0x442, 0x44d,
+0x442, 0x430, 0x440, 0x3b, 0x430, 0x442, 0x44f, 0x3b, 0x432, 0x430, 0x441, 0x3b,
+0x43a, 0x443, 0x43d, 0x3b, 0x43a, 0x430, 0x43b, 0x3b, 0x441, 0x44e, 0x43a, 0x3b,
+0x448, 0x43b, 0x44f, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x109, 0x6f, 0x3b, 0x6c,
+0x75, 0x6e, 0x64, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x6f, 0x3b, 0x6d,
+0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x6f, 0x3b, 0x135, 0x61, 0x16d, 0x64,
+0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x6f, 0x3b, 0x73,
+0x61, 0x62, 0x61, 0x74, 0x6f, 0x64, 0x69, 0x3b, 0x6c, 0x75, 0x3b, 0x6d,
+0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x135, 0x61, 0x3b, 0x76, 0x65, 0x3b, 0x73,
+0x61, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x135, 0x3b, 0x76,
+0x3b, 0x73, 0x70, 0xfc, 0x68, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65,
+0x73, 0x6d, 0x61, 0x73, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x74, 0x65, 0x69,
+0x73, 0x69, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b, 0x6f, 0x6c, 0x6d, 0x61,
+0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61, 0x70, 0xe4,
+0x65, 0x76, 0x3b, 0x72, 0x65, 0x65, 0x64, 0x65, 0x3b, 0x6c, 0x61, 0x75,
+0x70, 0xe4, 0x65, 0x76, 0x50, 0x3b, 0x45, 0x3b, 0x54, 0x3b, 0x4b, 0x3b,
+0x4e, 0x3b, 0x52, 0x3b, 0x4c, 0x6b, 0x254, 0x73, 0x69, 0x256, 0x61, 0x3b,
+0x64, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x62, 0x6c, 0x61, 0x256, 0x61, 0x3b,
+0x6b, 0x75, 0x256, 0x61, 0x3b, 0x79, 0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b,
+0x66, 0x69, 0x256, 0x61, 0x3b, 0x6d, 0x65, 0x6d, 0x6c, 0x65, 0x256, 0x61,
+0x6b, 0x254, 0x73, 0x3b, 0x64, 0x7a, 0x6f, 0x3b, 0x62, 0x6c, 0x61, 0x3b,
+0x6b, 0x75, 0x256, 0x3b, 0x79, 0x61, 0x77, 0x3b, 0x66, 0x69, 0x256, 0x3b,
+0x6d, 0x65, 0x6d, 0x6b, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6b, 0x3b, 0x79,
+0x3b, 0x66, 0x3b, 0x6d, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x6d,
+0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254,
+0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x62, 0x25b, 0x30c,
+0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa,
+0x20, 0x6d, 0x259, 0x301, 0x6c, 0x25b, 0x301, 0x3b, 0x73, 0x254, 0x301, 0x6e,
+0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x6e,
+0x79, 0x69, 0x3b, 0x66, 0xfa, 0x6c, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0xe9,
+0x72, 0x61, 0x64, 0xe9, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301,
+0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d,
+0x6e, 0x3b, 0x66, 0xfa, 0x6c, 0x3b, 0x73, 0xe9, 0x72, 0x73, 0x3b, 0x6d,
+0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x66, 0x3b, 0x73, 0x73, 0x75,
+0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e,
+0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64, 0x61,
+0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75,
+0x72, 0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66,
+0x72, 0xed, 0x67, 0x67, 0x6a, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b,
+0x6c, 0x65, 0x79, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x73,
+0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d,
+0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66, 0x72, 0xed, 0x3b, 0x6c,
+0x65, 0x79, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b,
+0x74, 0xfd, 0x73, 0x2e, 0x3b, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0xf3,
+0x73, 0x2e, 0x3b, 0x66, 0x72, 0xed, 0x2e, 0x3b, 0x6c, 0x65, 0x79, 0x2e,
+0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46, 0x3b,
+0x4c, 0x4c, 0x69, 0x6e, 0x67, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65,
+0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79,
+0x65, 0x72, 0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65,
+0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79, 0x65, 0x72, 0x6e, 0x65, 0x73,
+0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x4c, 0x69, 0x6e, 0x3b, 0x4c,
+0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x79, 0x3b, 0x48,
+0x75, 0x77, 0x3b, 0x42, 0x69, 0x79, 0x3b, 0x53, 0x61, 0x62, 0x73, 0x75,
+0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6e,
+0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61,
+0x69, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b,
+0x6f, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x65,
+0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6c, 0x61, 0x75, 0x61,
+0x6e, 0x74, 0x61, 0x69, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61,
+0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61,
+0x69, 0x6e, 0x61, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x6e,
+0x61, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b,
+0x6f, 0x6e, 0x61, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x6e,
+0x61, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e,
+0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61,
+0x73, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x3b,
+0x74, 0x6f, 0x3b, 0x70, 0x65, 0x3b, 0x6c, 0x61, 0x53, 0x3b, 0x4d, 0x3b,
+0x54, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x64, 0x69, 0x6d,
+0x61, 0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b,
+0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x72, 0x65,
+0x64, 0x69, 0x3b, 0x6a, 0x65, 0x75, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e,
+0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64, 0x69,
+0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61,
+0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e, 0x3b, 0x6a, 0x65, 0x75, 0x2e,
+0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x6d, 0x2e, 0x44, 0x3b,
+0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x64,
+0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x73,
+0x3b, 0x6d, 0x61, 0x72, 0x74, 0x61, 0x72, 0x73, 0x3b, 0x6d, 0x69, 0x65,
+0x72, 0x63, 0x75, 0x73, 0x3b, 0x6a, 0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76,
+0x69, 0x6e, 0x61, 0x72, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x69, 0x64, 0x65,
+0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x6d, 0x69, 0x65, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x3b,
+0x73, 0x61, 0x62, 0x64, 0x65, 0x77, 0x6f, 0x3b, 0x61, 0x61, 0x253, 0x6e,
+0x64, 0x65, 0x3b, 0x6d, 0x61, 0x77, 0x62, 0x61, 0x61, 0x72, 0x65, 0x3b,
+0x6e, 0x6a, 0x65, 0x73, 0x6c, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x6e, 0x61,
+0x61, 0x73, 0x61, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x6d, 0x61, 0x77, 0x6e,
+0x64, 0x65, 0x3b, 0x68, 0x6f, 0x6f, 0x72, 0x65, 0x2d, 0x62, 0x69, 0x69,
+0x72, 0x64, 0x65, 0x77, 0x3b, 0x61, 0x61, 0x253, 0x3b, 0x6d, 0x61, 0x77,
+0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x6e, 0x61, 0x61, 0x3b, 0x6d, 0x77, 0x64,
+0x3b, 0x68, 0x62, 0x69, 0x64, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6e, 0x3b,
+0x6e, 0x3b, 0x6d, 0x3b, 0x68, 0xd83a, 0xdd08, 0xd83a, 0xdd2b, 0xd83a, 0xdd2c, 0xd83a,
+0xdd26, 0xd83a, 0xdd2d, 0xd83a, 0xdd2a, 0xd83a, 0xdd46, 0xd83a, 0xdd2b, 0x3b, 0xd83a, 0xdd00,
+0xd83a, 0xdd44, 0xd83a, 0xdd29, 0xd83a, 0xdd35, 0xd83a, 0xdd32, 0xd83a, 0xdd4b, 0xd83a, 0xdd23,
+0xd83a, 0xdd2b, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd22, 0xd83a, 0xdd31, 0xd83a, 0xdd26, 0xd83a,
+0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd2a, 0xd83a, 0xdd2b, 0x3b, 0xd83a, 0xdd10, 0xd83a, 0xdd36,
+0xd83a, 0xdd2b, 0xd83a, 0xdd27, 0xd83a, 0xdd24, 0xd83a, 0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd2a,
+0xd83a, 0xdd2b, 0x3b, 0xd83a, 0xdd10, 0xd83a, 0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd27, 0xd83a,
+0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd32, 0xd83a, 0xdd23, 0xd83a, 0xdd2b, 0x3b, 0xd83a, 0xdd03,
+0xd83a, 0xdd22, 0xd83a, 0xdd31, 0xd83a, 0xdd32, 0xd83a, 0xdd23, 0xd83a, 0xdd2b, 0x3b, 0xd83a,
+0xdd16, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd26, 0xd83a, 0xdd2d, 0xd83a, 0xdd2a, 0xd83a,
+0xdd46, 0xd83a, 0xdd2b, 0xd83a, 0xdd08, 0xd83a, 0xdd2b, 0xd83a, 0xdd2c, 0x3b, 0xd83a, 0xdd00,
+0xd83a, 0xdd44, 0xd83a, 0xdd29, 0xd83a, 0xdd35, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd22, 0xd83a,
+0xdd26, 0x3b, 0xd83a, 0xdd14, 0xd83a, 0xdd2b, 0xd83a, 0xdd27, 0x3b, 0xd83a, 0xdd10, 0xd83a,
+0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd27, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd22, 0xd83a, 0xdd23,
+0x3b, 0xd83a, 0xdd16, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd08, 0x3b, 0xd83a, 0xdd00,
+0xd83a, 0xdd44, 0x3b, 0xd83a, 0xdd03, 0x3b, 0xd83a, 0xdd14, 0x3b, 0xd83a, 0xdd10, 0x3b,
+0xd83a, 0xdd03, 0x3b, 0xd83a, 0xdd16, 0x44, 0x69, 0x44, 0xf2, 0x6d, 0x68, 0x6e,
+0x61, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x4c, 0x75, 0x61, 0x69, 0x6e,
+0x3b, 0x44, 0x69, 0x4d, 0xe0, 0x69, 0x72, 0x74, 0x3b, 0x44, 0x69, 0x43,
+0x69, 0x61, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x61, 0x72, 0x44,
+0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x68, 0x41, 0x6f, 0x69, 0x6e,
+0x65, 0x3b, 0x44, 0x69, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e,
+0x65, 0x44, 0x69, 0x44, 0x3b, 0x44, 0x69, 0x4c, 0x3b, 0x44, 0x69, 0x4d,
+0x3b, 0x44, 0x69, 0x43, 0x3b, 0x44, 0x69, 0x61, 0x3b, 0x44, 0x69, 0x68,
+0x3b, 0x44, 0x69, 0x53, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b,
+0x41, 0x3b, 0x48, 0x3b, 0x53, 0x48, 0x254, 0x67, 0x62, 0x61, 0x61, 0x3b,
+0x4a, 0x75, 0x3b, 0x4a, 0x75, 0x66, 0x254, 0x3b, 0x53, 0x68, 0x254, 0x3b,
+0x53, 0x6f, 0x6f, 0x3b, 0x53, 0x6f, 0x68, 0x61, 0x61, 0x3b, 0x48, 0x254,
+0x254, 0x48, 0x254, 0x67, 0x3b, 0x4a, 0x75, 0x3b, 0x4a, 0x75, 0x66, 0x3b,
+0x53, 0x68, 0x254, 0x3b, 0x53, 0x6f, 0x6f, 0x3b, 0x53, 0x6f, 0x68, 0x3b,
+0x48, 0x254, 0x254, 0x48, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x53,
+0x3b, 0x53, 0x3b, 0x48, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b,
+0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b,
+0x6d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x78, 0x6f, 0x76,
+0x65, 0x73, 0x3b, 0x76, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1,
+0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e,
+0x73, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0xe9, 0x72, 0x2e, 0x3b,
+0x78, 0x6f, 0x76, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0xe1,
+0x62, 0x2e, 0x64, 0x2e, 0x3b, 0x6c, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x6d,
+0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x76, 0x2e, 0x3b, 0x73, 0x2e, 0x53, 0x61,
+0x62, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a,
+0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x62, 0x69, 0x72, 0x69, 0x3b,
+0x4c, 0x77, 0x61, 0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x77,
+0x61, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x74,
+0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61,
+0x61, 0x67, 0x61, 0x53, 0x61, 0x62, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x4c,
+0x77, 0x32, 0x3b, 0x4c, 0x77, 0x33, 0x3b, 0x4c, 0x77, 0x34, 0x3b, 0x4c,
+0x77, 0x35, 0x3b, 0x4c, 0x77, 0x36, 0x53, 0x3b, 0x42, 0x3b, 0x4c, 0x3b,
+0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x12a5, 0x1281, 0x12f5, 0x3b, 0x1230,
+0x1291, 0x12ed, 0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x122b, 0x1265, 0x12d5, 0x3b, 0x1210,
+0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1260, 0x3b, 0x1240, 0x12f3, 0x121a, 0x1275, 0x12a5,
+0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x122b, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1240,
+0x10d9, 0x10d5, 0x10d8, 0x10e0, 0x10d0, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x10d0, 0x10d1, 0x10d0,
+0x10d7, 0x10d8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8,
+0x3b, 0x10dd, 0x10d7, 0x10ee, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10ee,
+0x10e3, 0x10d7, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10de, 0x10d0, 0x10e0,
+0x10d0, 0x10e1, 0x10d9, 0x10d4, 0x10d5, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7,
+0x10d8, 0x10d9, 0x10d5, 0x10d8, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x3b, 0x10e1, 0x10d0, 0x10db,
+0x3b, 0x10dd, 0x10d7, 0x10ee, 0x3b, 0x10ee, 0x10e3, 0x10d7, 0x3b, 0x10de, 0x10d0, 0x10e0,
+0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d9, 0x3b, 0x10dd, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b,
+0x10ee, 0x3b, 0x10de, 0x3b, 0x10e8, 0x53, 0x6f, 0x6e, 0x6e, 0x74, 0x61, 0x67,
+0x3b, 0x4d, 0x6f, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x65, 0x6e,
+0x73, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x6f, 0x63,
+0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x74, 0x61, 0x67,
+0x3b, 0x46, 0x72, 0x65, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d,
+0x73, 0x74, 0x61, 0x67, 0x53, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x44, 0x69,
+0x3b, 0x4d, 0x69, 0x3b, 0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61,
+0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b,
+0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b,
+0x53, 0x61, 0x2e, 0x39a, 0x3c5, 0x3c1, 0x3b9, 0x3b1, 0x3ba, 0x3ae, 0x3b, 0x394,
+0x3b5, 0x3c5, 0x3c4, 0x3ad, 0x3c1, 0x3b1, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3c4, 0x3b7,
+0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3ac, 0x3c1, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3ad, 0x3bc,
+0x3c0, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b1, 0x3c3, 0x3ba, 0x3b5, 0x3c5,
+0x3ae, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x3b2, 0x3b1, 0x3c4, 0x3bf, 0x39a, 0x3c5, 0x3c1,
+0x3b, 0x394, 0x3b5, 0x3c5, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3b, 0x3a4, 0x3b5, 0x3c4,
+0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b, 0x3a3, 0x3ac, 0x3b2,
+0x39a, 0x3b, 0x394, 0x3b, 0x3a4, 0x3b, 0x3a4, 0x3b, 0x3a0, 0x3b, 0x3a0, 0x3b,
+0x3a3, 0x41, 0x72, 0x61, 0x74, 0x65, 0x129, 0x3b, 0x41, 0x72, 0x61, 0x6b,
+0xf5, 0x69, 0x3b, 0x41, 0x72, 0x61, 0x61, 0x70, 0x79, 0x3b, 0x41, 0x72,
+0x61, 0x72, 0x75, 0x6e, 0x64, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x70, 0x6f,
+0x3b, 0x41, 0x72, 0x61, 0x70, 0x6f, 0x74, 0x65, 0x129, 0x3b, 0x41, 0x72,
+0x61, 0x70, 0x6f, 0x6b, 0xf5, 0x69, 0xab0, 0xab5, 0xabf, 0xab5, 0xabe, 0xab0,
+0x3b, 0xab8, 0xacb, 0xaae, 0xab5, 0xabe, 0xab0, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3,
+0xab5, 0xabe, 0xab0, 0x3b, 0xaac, 0xac1, 0xaa7, 0xab5, 0xabe, 0xab0, 0x3b, 0xa97,
+0xac1, 0xab0, 0xac1, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0,
+0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0xab5, 0xabe, 0xab0, 0xab0, 0xab5,
+0xabf, 0x3b, 0xab8, 0xacb, 0xaae, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0x3b, 0xaac,
+0xac1, 0xaa7, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd,
+0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0xab0, 0x3b, 0xab8, 0xacb, 0x3b, 0xaae, 0xa82,
+0x3b, 0xaac, 0xac1, 0x3b, 0xa97, 0xac1, 0x3b, 0xab6, 0xac1, 0x3b, 0xab6, 0x43,
+0x68, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x75,
+0x6d, 0x61, 0x74, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61,
+0x69, 0x6e, 0x65, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e,
+0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x63,
+0x68, 0x75, 0x6d, 0x61, 0x3b, 0x45, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f,
+0x43, 0x70, 0x72, 0x3b, 0x43, 0x74, 0x74, 0x3b, 0x43, 0x6d, 0x6e, 0x3b,
+0x43, 0x6d, 0x74, 0x3b, 0x41, 0x72, 0x73, 0x3b, 0x49, 0x63, 0x6d, 0x3b,
+0x45, 0x73, 0x74, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x41,
+0x3b, 0x49, 0x3b, 0x45, 0x4c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x4c,
+0x69, 0x74, 0x69, 0x6e, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74,
+0x61, 0x3b, 0x4c, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68,
+0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d, 0x61, 0x2bc, 0x61,
+0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, 0x4c, 0x61, 0x68, 0x3b, 0x4c,
+0x69, 0x74, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x72, 0x3b, 0x41,
+0x6c, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x4c, 0x3b,
+0x4c, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x41, 0x644,
+0x64e, 0x62d, 0x64e, 0x62f, 0x650, 0x3b, 0x644, 0x650, 0x62a, 0x650, 0x646, 0x650,
+0x646, 0x652, 0x3b, 0x62a, 0x64e, 0x644, 0x64e, 0x62a, 0x64e, 0x3b, 0x644, 0x64e,
+0x631, 0x64e, 0x628, 0x64e, 0x3b, 0x623, 0x64e, 0x644, 0x652, 0x62d, 0x64e, 0x645,
+0x650, 0x633, 0x652, 0x3b, 0x62c, 0x64f, 0x645, 0x64e, 0x639, 0x64e, 0x3b, 0x623,
+0x64e, 0x633, 0x64e, 0x628, 0x64e, 0x631, 0x652, 0x644, 0x64e, 0x62d, 0x3b, 0x644,
+0x650, 0x62a, 0x3b, 0x62a, 0x64e, 0x644, 0x3b, 0x644, 0x64e, 0x631, 0x3b, 0x623,
+0x64e, 0x644, 0x652, 0x62d, 0x3b, 0x62c, 0x64f, 0x645, 0x3b, 0x623, 0x64e, 0x633,
+0x64e, 0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b, 0x50, 0x6f, 0x2bb, 0x61,
+0x6b, 0x61, 0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x75, 0x61,
+0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x6f, 0x6c, 0x75, 0x3b, 0x50, 0x6f,
+0x2bb, 0x61, 0x68, 0x101, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d,
+0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6f, 0x6e, 0x6f, 0x4c, 0x50, 0x3b,
+0x50, 0x31, 0x3b, 0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, 0x3b,
+0x50, 0x35, 0x3b, 0x50, 0x36, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9,
+0x5d5, 0x5df, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5e0, 0x5d9, 0x3b, 0x5d9,
+0x5d5, 0x5dd, 0x20, 0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd,
+0x20, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d7,
+0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d9, 0x5e9,
+0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d1, 0x5ea, 0x5d9, 0x5d5, 0x5dd,
+0x20, 0x5d0, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d9,
+0x5d5, 0x5dd, 0x20, 0x5d2, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d3, 0x5f3,
+0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d4, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20,
+0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0x5d0, 0x5f3, 0x3b, 0x5d1, 0x5f3, 0x3b,
+0x5d2, 0x5f3, 0x3b, 0x5d3, 0x5f3, 0x3b, 0x5d4, 0x5f3, 0x3b, 0x5d5, 0x5f3, 0x3b,
+0x5e9, 0x5f3, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e,
+0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b,
+0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935,
+0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b,
+0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b,
+0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917,
+0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928,
+0x93f, 0x930, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b,
+0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x52, 0x61, 0x76, 0x69, 0x77,
+0x61, 0x61, 0x72, 0x3b, 0x53, 0x6f, 0x6d, 0x77, 0x61, 0x61, 0x72, 0x3b,
+0x4d, 0x61, 0x6e, 0x67, 0x61, 0x6c, 0x77, 0x61, 0x61, 0x72, 0x3b, 0x42,
+0x75, 0x64, 0x68, 0x77, 0x61, 0x61, 0x72, 0x3b, 0x47, 0x75, 0x72, 0x75,
+0x77, 0x61, 0x61, 0x72, 0x3b, 0x53, 0x68, 0x75, 0x6b, 0x72, 0x61, 0x77,
+0x61, 0x61, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x6e, 0x69, 0x77, 0x61, 0x61,
+0x72, 0x52, 0x61, 0x76, 0x69, 0x3b, 0x53, 0x6f, 0x6d, 0x3b, 0x4d, 0x61,
+0x6e, 0x67, 0x61, 0x6c, 0x3b, 0x42, 0x75, 0x64, 0x68, 0x3b, 0x47, 0x75,
+0x72, 0x75, 0x3b, 0x53, 0x68, 0x75, 0x6b, 0x72, 0x61, 0x3b, 0x53, 0x68,
+0x61, 0x6e, 0x69, 0x52, 0x61, 0x3b, 0x53, 0x6f, 0x3b, 0x4d, 0x61, 0x3b,
+0x42, 0x75, 0x3b, 0x47, 0x75, 0x3b, 0x53, 0x68, 0x3b, 0x53, 0x68, 0x61,
+0x76, 0x61, 0x73, 0xe1, 0x72, 0x6e, 0x61, 0x70, 0x3b, 0x68, 0xe9, 0x74,
+0x66, 0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b, 0x73, 0x7a, 0x65, 0x72,
+0x64, 0x61, 0x3b, 0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72, 0x74, 0xf6, 0x6b,
+0x3b, 0x70, 0xe9, 0x6e, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x7a, 0x6f, 0x6d,
+0x62, 0x61, 0x74, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x65,
+0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x56, 0x3b, 0x48,
+0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53,
+0x7a, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b,
+0x6d, 0xe1, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe, 0x72,
+0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69,
+0xf0, 0x76, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66,
+0x69, 0x6d, 0x6d, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66,
+0xf6, 0x73, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x61,
+0x75, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x73, 0x75, 0x6e,
+0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0xfe, 0x72, 0x69, 0x2e, 0x3b,
+0x6d, 0x69, 0xf0, 0x2e, 0x3b, 0x66, 0x69, 0x6d, 0x2e, 0x3b, 0x66, 0xf6,
+0x73, 0x2e, 0x3b, 0x6c, 0x61, 0x75, 0x2e, 0x53, 0x3b, 0x4d, 0x3b, 0xde,
+0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x4c, 0x53, 0x1ecd, 0x6e, 0x64,
+0x65, 0x65, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x69, 0x75,
+0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65, 0x7a, 0x64, 0x65,
+0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x46, 0x72,
+0x61, 0x1ecb, 0x64, 0x65, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x1ecd, 0x64, 0x65,
+0x65, 0x53, 0x1ecd, 0x6e, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x3b, 0x54, 0x69, 0x75,
+0x3b, 0x57, 0x65, 0x6e, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x3b, 0x46, 0x72, 0x61,
+0x1ecb, 0x3b, 0x53, 0x61, 0x74, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x69,
+0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x72, 0x67, 0xe2,
+0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6b,
+0x6f, 0x73, 0x6b, 0x6f, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72,
+0xe2, 0x73, 0x74, 0xe2, 0x68, 0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70,
+0x70, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64,
+0xe2, 0x68, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x65, 0x69, 0x76, 0x69,
+0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x61, 0x72, 0x67, 0xe2, 0x3b,
+0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6b,
+0x6f, 0x73, 0x6b, 0x6f, 0x68, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2,
+0x73, 0x74, 0x75, 0x76, 0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70,
+0x65, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64,
+0x75, 0x76, 0x70, 0x61, 0x73, 0x3b, 0x76, 0x75, 0x6f, 0x3b, 0x6d, 0x61,
+0x6a, 0x3b, 0x6b, 0x6f, 0x73, 0x3b, 0x74, 0x75, 0x6f, 0x3b, 0x76, 0xe1,
+0x73, 0x3b, 0x6c, 0xe1, 0x76, 0x70, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x4b,
+0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x4c, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75,
+0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73,
+0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75,
+0x4d, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b,
+0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b,
+0x53, 0x61, 0x62, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b,
+0x3b, 0x4a, 0x3b, 0x53, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61,
+0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74,
+0x65, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69, 0x64,
+0x69, 0x3b, 0x6a, 0x6f, 0x76, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e,
+0x65, 0x72, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x62, 0x62, 0x61, 0x74, 0x6f,
+0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x6d, 0x65, 0x72, 0x3b, 0x6a, 0x6f, 0x76, 0x3b, 0x76, 0x65, 0x6e, 0x3b,
+0x73, 0x61, 0x62, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6a,
+0x3b, 0x76, 0x3b, 0x73, 0x73, 0x6f, 0x6c, 0x65, 0x64, 0xed, 0x3b, 0x6c,
+0x75, 0x6e, 0x65, 0x64, 0xed, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0xed, 0x3b,
+0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x64, 0xed, 0x3b, 0x6a, 0x6f, 0x76,
+0x65, 0x64, 0xed, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64, 0xed, 0x3b,
+0x73, 0x61, 0x74, 0x75, 0x72, 0x64, 0xed, 0x73, 0x6f, 0x6c, 0x2e, 0x3b,
+0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x65,
+0x72, 0x2e, 0x3b, 0x6a, 0x6f, 0x76, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e,
+0x3b, 0x73, 0x61, 0x74, 0x2e, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d,
+0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x14c8, 0x1466, 0x144f, 0x1591, 0x152d, 0x1585,
+0x3b, 0x14c7, 0x14a1, 0x1490, 0x153e, 0x152d, 0x1405, 0x3b, 0x14c7, 0x14a1, 0x1490, 0x153e,
+0x152d, 0x1405, 0x14d5, 0x1585, 0x146d, 0x3b, 0x1431, 0x1593, 0x1466, 0x14ef, 0x1585, 0x3b,
+0x14ef, 0x1455, 0x14bb, 0x14a5, 0x1585, 0x3b, 0x1455, 0x14ea, 0x14d5, 0x14bb, 0x14a5, 0x1405,
+0x1466, 0x3b, 0x14c8, 0x1466, 0x14f0, 0x1591, 0x152d, 0x14db, 0x1550, 0x14c2, 0x140a, 0x1585,
+0x44, 0xe9, 0x20, 0x44, 0x6f, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x67, 0x68,
+0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0xe9,
+0x20, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x44, 0xe9, 0x20, 0x43, 0xe9,
+0x61, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x64,
+0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69,
+0x6e, 0x65, 0x3b, 0x44, 0xe9, 0x20, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69,
+0x72, 0x6e, 0x44, 0x6f, 0x6d, 0x68, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x3b,
+0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43, 0xe9, 0x61, 0x64, 0x3b, 0x44,
+0xe9, 0x61, 0x72, 0x3b, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x61,
+0x74, 0x68, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b,
+0x41, 0x3b, 0x53, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b,
+0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65,
+0x64, 0xec, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec,
+0x3b, 0x67, 0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76, 0x65, 0x6e,
+0x65, 0x72, 0x64, 0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x64,
+0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d,
+0x65, 0x72, 0x3b, 0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73,
+0x61, 0x62, 0x65e5, 0x66dc, 0x65e5, 0x3b, 0x6708, 0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc,
+0x65e5, 0x3b, 0x6c34, 0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc, 0x65e5, 0x3b, 0x91d1, 0x66dc,
+0x65e5, 0x3b, 0x571f, 0x66dc, 0x65e5, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34,
+0x3b, 0x6728, 0x3b, 0x91d1, 0x3b, 0x571f, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x53,
+0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b,
+0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a,
+0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x41, 0x68,
+0x61, 0x64, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52,
+0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53,
+0x61, 0x62, 0x41, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b,
+0x4a, 0x3b, 0x53, 0x4c, 0x61, 0x64, 0x69, 0x3b, 0x4c, 0x69, 0x6e, 0x74,
+0x61, 0x6e, 0x69, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c,
+0x61, 0x72, 0x62, 0x61, 0x3b, 0x4c, 0x61, 0x6d, 0x69, 0x74, 0x3b, 0x4a,
+0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, 0x4c, 0x61,
+0x64, 0x3b, 0x4c, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x4c, 0x61,
+0x72, 0x3b, 0x4c, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73,
+0x61, 0x44, 0x69, 0x6d, 0x61, 0x73, 0x3b, 0x54, 0x65, 0x6e, 0x65, 0x14b,
+0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72,
+0x62, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x79,
+0x3b, 0x41, 0x72, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x53, 0x69, 0x62, 0x69,
+0x74, 0x69, 0x44, 0x69, 0x6d, 0x3b, 0x54, 0x65, 0x6e, 0x3b, 0x54, 0x61,
+0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x72,
+0x6a, 0x3b, 0x53, 0x69, 0x62, 0x44, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x41,
+0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x53, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x67,
+0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65,
+0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72,
+0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72,
+0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61,
+0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b,
+0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x64, 0x75, 0x6d, 0x3b, 0x73, 0x69,
+0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x6b, 0x75, 0x61, 0x3b, 0x6b, 0x69,
+0x6e, 0x3b, 0x73, 0x65, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x44, 0x3b, 0x53,
+0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x41, 0x63,
+0x65, 0x72, 0x3b, 0x41, 0x72, 0x69, 0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6d,
+0x3b, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x41, 0x6d, 0x68, 0x61, 0x64, 0x3b,
+0x53, 0x65, 0x6d, 0x3b, 0x53, 0x65, 0x64, 0x59, 0x61, 0x6e, 0x61, 0x73,
+0x73, 0x3b, 0x53, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x72, 0x61,
+0x1e0d, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x75, 0x1e93, 0x61, 0x73, 0x73, 0x3b,
+0x53, 0x61, 0x6d, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x61,
+0x73, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x61, 0x73, 0x73, 0x41, 0x63, 0x65,
+0x3b, 0x41, 0x72, 0x69, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x68, 0x61,
+0x3b, 0x41, 0x6d, 0x68, 0x3b, 0x53, 0x65, 0x6d, 0x3b, 0x53, 0x65, 0x64,
+0x59, 0x61, 0x6e, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d,
+0x3b, 0x4b, 0x75, 0x1e93, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x1e0d, 0x69,
+0x73, 0x3b, 0x53, 0x61, 0x79, 0x59, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x43, 0x3b, 0x52, 0x3b, 0x52, 0x3b,
+0x48, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x73, 0x254, 0x6e, 0x64, 0x69,
+0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69,
+0x3b, 0x6d, 0x25b, 0x72, 0x6b, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x79,
+0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x14b, 0x64, 0x25b, 0x72, 0x25b, 0x64,
+0x69, 0x3b, 0x6d, 0x254, 0x6e, 0x254, 0x20, 0x73, 0x254, 0x6e, 0x64, 0x69,
+0x73, 0x6f, 0x3b, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x25b, 0x3b,
+0x79, 0x65, 0x3b, 0x76, 0x61, 0x3b, 0x6d, 0x73, 0x73, 0x61, 0x70, 0x61,
+0x61, 0x74, 0x3b, 0x61, 0x74, 0x61, 0x61, 0x73, 0x69, 0x6e, 0x6e, 0x67,
+0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x6d, 0x61, 0x72, 0x6c, 0x75, 0x6e,
+0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x70, 0x69, 0x6e, 0x67,
+0x61, 0x73, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b,
+0x73, 0x69, 0x73, 0x61, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e,
+0x65, 0x71, 0x3b, 0x74, 0x61, 0x6c, 0x6c, 0x69, 0x6d, 0x61, 0x6e, 0x6e,
+0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x61, 0x72, 0x66, 0x69, 0x6e,
+0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x73, 0x61, 0x70,
+0x3b, 0x61, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x69, 0x6e,
+0x3b, 0x73, 0x69, 0x73, 0x3b, 0x74, 0x61, 0x6c, 0x3b, 0x61, 0x72, 0x66,
+0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b,
+0x41, 0x4b, 0x6f, 0x74, 0x69, 0x73, 0x61, 0x70, 0x3b, 0x4b, 0x6f, 0x74,
+0x61, 0x61, 0x69, 0x3b, 0x4b, 0x6f, 0x61, 0x65, 0x6e, 0x67, 0x2019, 0x3b,
+0x4b, 0x6f, 0x73, 0x6f, 0x6d, 0x6f, 0x6b, 0x3b, 0x4b, 0x6f, 0x61, 0x6e,
+0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d, 0x75, 0x75, 0x74,
+0x3b, 0x4b, 0x6f, 0x6c, 0x6f, 0x4b, 0x74, 0x73, 0x3b, 0x4b, 0x6f, 0x74,
+0x3b, 0x4b, 0x6f, 0x6f, 0x3b, 0x4b, 0x6f, 0x73, 0x3b, 0x4b, 0x6f, 0x61,
+0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x4b, 0x6f, 0x6c, 0x54, 0x3b, 0x54, 0x3b,
+0x4f, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x57, 0x61, 0x20,
+0x6b, 0x79, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x77,
+0x61, 0x6d, 0x62, 0x129, 0x6c, 0x129, 0x6c, 0x79, 0x61, 0x3b, 0x57, 0x61,
+0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x74,
+0x61, 0x74, 0x169, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b,
+0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x57, 0x61,
+0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169, 0x57, 0x6b,
+0x79, 0x3b, 0x57, 0x6b, 0x77, 0x3b, 0x57, 0x6b, 0x6c, 0x3b, 0x57, 0x74,
+0x169, 0x3b, 0x57, 0x6b, 0x6e, 0x3b, 0x57, 0x74, 0x6e, 0x3b, 0x57, 0x74,
+0x68, 0x59, 0x3b, 0x57, 0x3b, 0x45, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41,
+0x3b, 0x41, 0xcad, 0xcbe, 0xca8, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb,
+0xcae, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0,
+0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1,
+0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0xcb5, 0xcbe, 0xcb0,
+0x3b, 0xcb6, 0xca8, 0xcbf, 0xcb5, 0xcbe, 0xcb0, 0xcad, 0xcbe, 0xca8, 0xcc1, 0x3b,
+0xcb8, 0xccb, 0xcae, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0x3b, 0xcac, 0xcc1, 0xca7,
+0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0x3b,
+0xcb6, 0xca8, 0xcbf, 0xcad, 0xcbe, 0x3b, 0xcb8, 0xccb, 0x3b, 0xcae, 0xc82, 0x3b,
+0xcac, 0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b, 0xcb6, 0x627, 0x64e,
+0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x62f, 0x631, 0x655,
+0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x6c6, 0x645, 0x648, 0x627, 0x631, 0x3b,
+0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x620, 0x633, 0x648,
+0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627,
+0x631, 0x622, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x62f,
+0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x6c6, 0x645, 0x648, 0x627, 0x631,
+0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x620, 0x633,
+0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648,
+0x627, 0x631, 0x627, 0x3b, 0x698, 0x3b, 0x628, 0x3b, 0x628, 0x3b, 0x628, 0x3b,
+0x62c, 0x3b, 0x628, 0x906, 0x925, 0x935, 0x93e, 0x930, 0x3b, 0x91a, 0x902, 0x926,
+0x93f, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x935, 0x93e, 0x930, 0x3b,
+0x92c, 0x94b, 0x926, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x94d, 0x930, 0x947, 0x938,
+0x935, 0x93e, 0x930, 0x3b, 0x91c, 0x941, 0x92e, 0x94d, 0x92e, 0x93e, 0x3b, 0x92c,
+0x91f, 0x935, 0x93e, 0x930, 0x906, 0x925, 0x935, 0x93e, 0x930, 0x3b, 0x91a, 0x93c,
+0x902, 0x926, 0x93f, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x94b, 0x92e, 0x935,
+0x93e, 0x930, 0x3b, 0x92c, 0x94b, 0x926, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x94d,
+0x930, 0x947, 0x938, 0x935, 0x93e, 0x930, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x3b,
+0x92c, 0x91f, 0x935, 0x93e, 0x930, 0x906, 0x925, 0x935, 0x93e, 0x930, 0x3b, 0x91a,
+0x902, 0x926, 0x93f, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x935, 0x93e,
+0x930, 0x3b, 0x92c, 0x94b, 0x926, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x94d, 0x930,
+0x947, 0x938, 0x935, 0x93e, 0x930, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x3b, 0x92c,
+0x91f, 0x935, 0x93e, 0x930, 0x905, 0x3b, 0x91a, 0x3b, 0x92c, 0x3b, 0x92c, 0x3b,
+0x92c, 0x3b, 0x91c, 0x3b, 0x92c, 0x436, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x431,
+0x456, 0x3b, 0x434, 0x4af, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441,
+0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x441,
+0x435, 0x43d, 0x431, 0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431,
+0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x431, 0x456,
+0x436, 0x441, 0x3b, 0x434, 0x441, 0x3b, 0x441, 0x441, 0x3b, 0x441, 0x440, 0x3b,
+0x431, 0x441, 0x3b, 0x436, 0x43c, 0x3b, 0x441, 0x431, 0x416, 0x3b, 0x414, 0x3b,
+0x421, 0x3b, 0x421, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x421, 0x17a2, 0x17b6, 0x1791,
+0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784,
+0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a,
+0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2,
+0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2,
+0x1799, 0x3b, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782,
+0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f,
+0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b,
+0x179f, 0x17c5, 0x179a, 0x17cd, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b,
+0x1785, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b,
+0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x3b, 0x179f, 0x17bb, 0x1780,
+0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x17a2, 0x3b, 0x1785, 0x3b, 0x17a2,
+0x3b, 0x1796, 0x3b, 0x1796, 0x3b, 0x179f, 0x3b, 0x179f, 0x4b, 0x69, 0x75, 0x6d,
+0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x169,
+0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a,
+0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x6d,
+0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b,
+0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x4b, 0x4d,
+0x41, 0x3b, 0x4e, 0x54, 0x54, 0x3b, 0x4e, 0x4d, 0x4e, 0x3b, 0x4e, 0x4d,
+0x54, 0x3b, 0x41, 0x52, 0x54, 0x3b, 0x4e, 0x4d, 0x41, 0x3b, 0x4e, 0x4d,
+0x4d, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4e,
+0x3b, 0x4e, 0x4b, 0x75, 0x20, 0x63, 0x79, 0x75, 0x6d, 0x77, 0x65, 0x72,
+0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65,
+0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69,
+0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75,
+0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b,
+0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b,
+0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74,
+0x75, 0x63, 0x79, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b,
+0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e,
+0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x906,
+0x92f, 0x924, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x93e, 0x930, 0x3b, 0x92e,
+0x902, 0x917, 0x933, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930,
+0x3b, 0x92c, 0x93f, 0x930, 0x947, 0x938, 0x94d, 0x924, 0x93e, 0x930, 0x3b, 0x936,
+0x941, 0x915, 0x94d, 0x930, 0x93e, 0x930, 0x3b, 0x936, 0x947, 0x928, 0x935, 0x93e,
+0x930, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b,
+0x92c, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x947, 0x906, 0x3b, 0x938, 0x94b, 0x3b,
+0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x936, 0x941, 0x3b,
+0x936, 0x947, 0xc77c, 0xc694, 0xc77c, 0x3b, 0xc6d4, 0xc694, 0xc77c, 0x3b, 0xd654, 0xc694,
+0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c, 0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, 0xc694,
+0xc77c, 0x3b, 0xd1a0, 0xc694, 0xc77c, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218,
+0x3b, 0xbaa9, 0x3b, 0xae08, 0x3b, 0xd1a0, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69,
+0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c,
+0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b,
+0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c,
+0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x41,
+0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41,
+0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x7a, 0x3b, 0x41,
+0x73, 0x69, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b,
+0x4c, 0x3b, 0x53, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74,
+0x69, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b,
+0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d,
+0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x6a, 0x75, 0x6d, 0x61, 0x3b,
+0x41, 0x73, 0x73, 0x61, 0x62, 0x64, 0x75, 0x41, 0x6c, 0x68, 0x3b, 0x41,
+0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41,
+0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x6a, 0x3b, 0x41, 0x73, 0x73, 0x79, 0x65,
+0x6b, 0x15f, 0x65, 0x6d, 0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6d, 0x3b, 0x73,
+0xea, 0x15f, 0x65, 0x6d, 0x3b, 0xe7, 0x61, 0x72, 0x15f, 0x65, 0x6d, 0x3b,
+0x70, 0xea, 0x6e, 0x63, 0x15f, 0x65, 0x6d, 0x3b, 0xee, 0x6e, 0xee, 0x3b,
+0x15f, 0x65, 0x6d, 0xee, 0x79, 0x15f, 0x6d, 0x3b, 0x64, 0x15f, 0x6d, 0x3b,
+0x73, 0x15f, 0x6d, 0x3b, 0xe7, 0x15f, 0x6d, 0x3b, 0x70, 0x15f, 0x6d, 0x3b,
+0xee, 0x6e, 0xee, 0x3b, 0x15f, 0x65, 0x6d, 0x59, 0x3b, 0x44, 0x3b, 0x53,
+0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0xce, 0x3b, 0x15e, 0x73, 0x254, 0x301, 0x6e,
+0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x73, 0x254,
+0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1,
+0x62, 0x61, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61,
+0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6c, 0x61, 0x6c, 0x3b, 0x73, 0x254, 0x301,
+0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6e,
+0x61, 0x3b, 0x6d, 0x61, 0x62, 0xe1, 0x67, 0xe1, 0x20, 0x6d, 0xe1, 0x20,
+0x73, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x73, 0xe1, 0x73, 0x61, 0x64, 0x69,
+0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d,
+0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x6d, 0x62,
+0x73, 0x3b, 0x73, 0x61, 0x73, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x73,
+0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x436, 0x435, 0x43a, 0x448, 0x435, 0x43c,
+0x431, 0x438, 0x3b, 0x434, 0x4af, 0x439, 0x448, 0x4e9, 0x43c, 0x431, 0x4af, 0x3b,
+0x448, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x448, 0x430, 0x440,
+0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x435, 0x43c,
+0x431, 0x438, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x435, 0x43c,
+0x431, 0x438, 0x436, 0x435, 0x43a, 0x2e, 0x3b, 0x434, 0x4af, 0x439, 0x2e, 0x3b,
+0x448, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x448, 0x430, 0x440, 0x448, 0x2e, 0x3b,
+0x431, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438,
+0x448, 0x43c, 0x2e, 0x416, 0x3b, 0x414, 0x3b, 0x428, 0x3b, 0x428, 0x3b, 0x411,
+0x3b, 0x416, 0x3b, 0x418, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61,
+0x6b, 0x21f, 0x61, 0x14b, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77,
+0x61, 0x14b, 0x17e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x6e,
+0x75, 0x14b, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x79,
+0x61, 0x6d, 0x6e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x74,
+0x6f, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x7a, 0x61,
+0x70, 0x74, 0x61, 0x14b, 0x3b, 0x4f, 0x77, 0xe1, 0x14b, 0x67, 0x79, 0x75,
+0x17e, 0x61, 0x17e, 0x61, 0x70, 0x69, 0x41, 0x3b, 0x57, 0x3b, 0x4e, 0x3b,
+0x59, 0x3b, 0x54, 0x3b, 0x5a, 0x3b, 0x4f, 0x4a, 0x75, 0x6d, 0x61, 0x70,
+0xed, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74,
+0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0xed, 0x6e, 0x65, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x74, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x6d,
+0xed, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0xe1, 0x61, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x6f, 0x73, 0x69, 0x50, 0xed, 0x69,
+0x6c, 0x69, 0x3b, 0x54, 0xe1, 0x61, 0x74, 0x75, 0x3b, 0xcd, 0x6e, 0x65,
+0x3b, 0x54, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49,
+0x6a, 0x6d, 0x3b, 0x4d, 0xf3, 0x6f, 0x73, 0x69, 0x50, 0x3b, 0x54, 0x3b,
+0x45, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4d, 0xea7, 0xeb1, 0xe99,
+0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99,
+0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7,
+0xeb1, 0xe99, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0, 0xeab,
+0xeb1, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xea7, 0xeb1,
+0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xe88,
+0xeb1, 0xe99, 0x3b, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xe9e, 0xeb8,
+0xe94, 0x3b, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xeaa, 0xeb8, 0xe81, 0x3b,
+0xec0, 0xeaa, 0xebb, 0xeb2, 0xead, 0xeb2, 0x3b, 0xe88, 0x3b, 0xead, 0x3b, 0xe9e,
+0x3b, 0xe9e, 0xeab, 0x3b, 0xeaa, 0xeb8, 0x3b, 0xeaa, 0x64, 0x69, 0x65, 0x73,
+0x20, 0x53, 0x6f, 0x6c, 0x69, 0x73, 0x3b, 0x64, 0x69, 0x65, 0x73, 0x20,
+0x4c, 0x75, 0x6e, 0x61, 0x65, 0x3b, 0x64, 0x69, 0x65, 0x73, 0x20, 0x4d,
+0x61, 0x72, 0x74, 0x69, 0x73, 0x3b, 0x64, 0x69, 0x65, 0x73, 0x20, 0x4d,
+0x65, 0x72, 0x63, 0x75, 0x72, 0x69, 0x69, 0x3b, 0x64, 0x69, 0x65, 0x73,
+0x20, 0x49, 0x6f, 0x76, 0x69, 0x73, 0x3b, 0x64, 0x69, 0x65, 0x73, 0x20,
+0x56, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x73, 0x3b, 0x64, 0x69, 0x65, 0x73,
+0x20, 0x53, 0x61, 0x74, 0x75, 0x72, 0x6e, 0x69, 0x53, 0x6f, 0x6c, 0x3b,
+0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x72, 0x3b,
+0x49, 0x6f, 0x76, 0x3b, 0x56, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x74, 0x53,
+0x76, 0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x72,
+0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x74, 0x72, 0x64, 0x69,
+0x65, 0x6e, 0x61, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e,
+0x61, 0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e,
+0x61, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61,
+0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x73, 0x76,
+0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x72, 0x6d,
+0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x69, 0x65,
+0x6e, 0x61, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61,
+0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61,
+0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b,
+0x73, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x53, 0x76, 0x113,
+0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b, 0x4f,
+0x74, 0x72, 0x64, 0x2e, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b,
+0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x65,
+0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x2e, 0x73,
+0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x2e,
+0x3b, 0x6f, 0x74, 0x72, 0x64, 0x2e, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64,
+0x2e, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x70,
+0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64,
+0x2e, 0x53, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50,
+0x3b, 0x53, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x6d, 0x6f, 0x6b,
+0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62,
+0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61,
+0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254,
+0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74,
+0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20,
+0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254,
+0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x6d,
+0x70, 0x254, 0x301, 0x73, 0x254, 0x65, 0x79, 0x65, 0x3b, 0x79, 0x62, 0x6f,
+0x3b, 0x6d, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x6e,
+0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x70, 0x73, 0x65, 0x3b, 0x79, 0x3b,
+0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x70, 0x73, 0x65, 0x6b,
+0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x69, 0x72,
+0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x61, 0x6e, 0x74,
+0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x74, 0x72, 0x65,
+0x10d, 0x69, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6b, 0x65,
+0x74, 0x76, 0x69, 0x72, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
+0x3b, 0x70, 0x65, 0x6e, 0x6b, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69,
+0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69,
+0x73, 0x73, 0x6b, 0x3b, 0x70, 0x72, 0x3b, 0x61, 0x6e, 0x3b, 0x74, 0x72,
+0x3b, 0x6b, 0x74, 0x3b, 0x70, 0x6e, 0x3b, 0x161, 0x74, 0x53, 0x3b, 0x50,
+0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x6e, 0x6a,
+0x65, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x6a, 0x65, 0x17a,
+0x65, 0x6c, 0x65, 0x3b, 0x77, 0x61, 0x142, 0x74, 0x6f, 0x72, 0x61, 0x3b,
+0x73, 0x72, 0x6a, 0x6f, 0x64, 0x61, 0x3b, 0x73, 0x74, 0x77, 0xf3, 0x72,
+0x74, 0x6b, 0x3b, 0x70, 0x11b, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f,
+0x74, 0x61, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x61,
+0x142, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x73, 0x74, 0x77, 0x3b, 0x70, 0x11b,
+0x74, 0x3b, 0x73, 0x6f, 0x62, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73,
+0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x73, 0x53, 0xfc, 0x6e, 0x6e, 0x64, 0x61,
+0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69,
+0x6e, 0x67, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x64, 0x64, 0x65,
+0x77, 0x65, 0x6b, 0x65, 0x6e, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72,
+0x73, 0x64, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x65, 0x64, 0x61, 0x67,
+0x3b, 0x53, 0xfc, 0x6e, 0x6e, 0x61, 0x76, 0x65, 0x6e, 0x64, 0x53, 0xfc,
+0x2e, 0x3b, 0x4d, 0x61, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69,
+0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61,
+0x2e, 0x4c, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4e, 0x6b, 0x6f,
+0x64, 0x79, 0x61, 0x3b, 0x4e, 0x64, 0xe0, 0x61, 0x79, 0xe0, 0x3b, 0x4e,
+0x64, 0x61, 0x6e, 0x67, 0xf9, 0x3b, 0x4e, 0x6a, 0xf2, 0x77, 0x61, 0x3b,
+0x4e, 0x67, 0xf2, 0x76, 0x79, 0x61, 0x3b, 0x4c, 0x75, 0x62, 0x69, 0x6e,
+0x67, 0x75, 0x4c, 0x75, 0x6d, 0x3b, 0x4e, 0x6b, 0x6f, 0x3b, 0x4e, 0x64,
+0x79, 0x3b, 0x4e, 0x64, 0x67, 0x3b, 0x4e, 0x6a, 0x77, 0x3b, 0x4e, 0x67,
+0x76, 0x3b, 0x4c, 0x75, 0x62, 0x4c, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e,
+0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4c, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69,
+0x6c, 0x3b, 0x57, 0x75, 0x6f, 0x6b, 0x20, 0x54, 0x69, 0x63, 0x68, 0x3b,
+0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x54,
+0x69, 0x63, 0x68, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x54, 0x69, 0x63,
+0x68, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69,
+0x63, 0x68, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x4e, 0x67, 0x65,
+0x73, 0x6f, 0x4a, 0x4d, 0x50, 0x3b, 0x57, 0x55, 0x54, 0x3b, 0x54, 0x41,
+0x52, 0x3b, 0x54, 0x41, 0x44, 0x3b, 0x54, 0x41, 0x4e, 0x3b, 0x54, 0x41,
+0x42, 0x3b, 0x4e, 0x47, 0x53, 0x4a, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x54,
+0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4e, 0x53, 0x6f, 0x6e, 0x6e, 0x64, 0x65,
+0x67, 0x3b, 0x4d, 0xe9, 0x69, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x44, 0xeb,
+0x6e, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x4d, 0xeb, 0x74, 0x74,
+0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x73, 0x63,
+0x68, 0x64, 0x65, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x64, 0x65, 0x67,
+0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x53, 0x6f,
+0x6e, 0x3b, 0x4d, 0xe9, 0x69, 0x3b, 0x44, 0xeb, 0x6e, 0x3b, 0x4d, 0xeb,
+0x74, 0x3b, 0x44, 0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, 0x61,
+0x6d, 0x53, 0x6f, 0x6e, 0x2e, 0x3b, 0x4d, 0xe9, 0x69, 0x2e, 0x3b, 0x44,
+0xeb, 0x6e, 0x2e, 0x3b, 0x4d, 0xeb, 0x74, 0x2e, 0x3b, 0x44, 0x6f, 0x6e,
+0x2e, 0x3b, 0x46, 0x72, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x6d, 0x2e, 0x4a,
+0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x75,
+0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x6e, 0x6e, 0x65,
+0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61,
+0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73,
+0x69, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35,
+0x3b, 0x41, 0x6c, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x43d, 0x435, 0x434,
+0x435, 0x43b, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d,
+0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441,
+0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x43e,
+0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e, 0x43a, 0x3b, 0x441, 0x430, 0x431, 0x43e,
+0x442, 0x430, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b,
+0x432, 0x442, 0x43e, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435,
+0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e,
+0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x75,
+0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a,
+0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73,
+0x69, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e,
+0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75,
+0x3b, 0x4a, 0x6d, 0x6f, 0x930, 0x935, 0x93f, 0x20, 0x926, 0x93f, 0x928, 0x3b,
+0x938, 0x94b, 0x92e, 0x20, 0x926, 0x93f, 0x928, 0x3b, 0x92e, 0x902, 0x917, 0x932,
+0x20, 0x926, 0x93f, 0x928, 0x3b, 0x92c, 0x941, 0x927, 0x20, 0x926, 0x93f, 0x928,
+0x3b, 0x92c, 0x943, 0x939, 0x938, 0x94d, 0x92a, 0x924, 0x93f, 0x20, 0x926, 0x93f,
+0x928, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x20, 0x926, 0x93f, 0x928, 0x3b,
+0x936, 0x928, 0x93f, 0x20, 0x926, 0x93f, 0x928, 0x53, 0x61, 0x62, 0x61, 0x74,
+0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a,
+0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
+0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73,
+0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x6d, 0x6f, 0x73, 0x69, 0x53, 0x61, 0x62, 0x3b, 0x4a, 0x74, 0x74,
+0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x72, 0x61,
+0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x53, 0x3b, 0x4a, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x4c, 0x69, 0x64,
+0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b,
+0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x74, 0x61,
+0x74, 0x75, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79,
+0x61, 0x6e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4c, 0x69, 0x64,
+0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e,
+0x6f, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61,
+0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6c, 0x69,
+0x6e, 0x6a, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c,
+0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20,
+0x6d, 0x61, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76,
+0x61, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x4c, 0x6c, 0x32,
+0x3b, 0x4c, 0x6c, 0x33, 0x3b, 0x4c, 0x6c, 0x34, 0x3b, 0x4c, 0x6c, 0x35,
+0x3b, 0x4c, 0x6c, 0x36, 0x3b, 0x4c, 0x6c, 0x37, 0x3b, 0x4c, 0x6c, 0x31,
+0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b,
+0x31, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x79, 0x3b, 0x41, 0x6c, 0x61,
+0x74, 0x73, 0x69, 0x6e, 0x61, 0x69, 0x6e, 0x79, 0x3b, 0x54, 0x61, 0x6c,
+0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x6f, 0x62, 0x69, 0x61,
+0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x61, 0x6d, 0x69, 0x73, 0x79, 0x3b, 0x5a,
+0x6f, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x6f, 0x74, 0x73, 0x79,
+0x41, 0x6c, 0x61, 0x68, 0x3b, 0x41, 0x6c, 0x61, 0x74, 0x73, 0x3b, 0x54,
+0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x3b, 0x41, 0x6c, 0x61, 0x6b,
+0x3b, 0x5a, 0x6f, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x41, 0x3b, 0x41,
+0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x5a, 0x3b, 0x41, 0xd1e, 0xd3e,
+0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d,
+0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d,
+0xd35, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e,
+0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34,
+0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e,
+0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d,
+0x200c, 0xd1a, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b,
+0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b,
+0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd2c, 0xd41,
+0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e,
+0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33,
+0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f,
+0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0xd1e, 0xd3e, 0xd2f, 0xd7c, 0x3b, 0xd24, 0xd3f,
+0xd19, 0xd4d, 0xd15, 0xd7e, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c,
+0xd41, 0xd27, 0xd7b, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd02, 0x3b, 0xd35,
+0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd1e, 0xd3e, 0x3b,
+0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f,
+0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0xd1e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a,
+0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46,
+0x3b, 0xd36, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x6e,
+0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75,
+0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x41, 0x68, 0x64, 0x3b,
+0x49, 0x73, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b,
+0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x41,
+0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53,
+0x627, 0x62d, 0x62f, 0x3b, 0x627, 0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x62b, 0x644,
+0x627, 0x62b, 0x3b, 0x631, 0x627, 0x628, 0x648, 0x3b, 0x62e, 0x645, 0x64a, 0x633,
+0x3b, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x633, 0x628, 0x62a, 0x648, 0x49, 0x6c,
+0x2d, 0x126, 0x61, 0x64, 0x64, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65,
+0x6a, 0x6e, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6c, 0x69, 0x65, 0x74, 0x61,
+0x3b, 0x4c, 0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x6c,
+0x2d, 0x126, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c, 0x2d, 0x120, 0x69,
+0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x73, 0x2d, 0x53, 0x69, 0x62, 0x74,
+0x126, 0x61, 0x64, 0x3b, 0x54, 0x6e, 0x65, 0x3b, 0x54, 0x6c, 0x69, 0x3b,
+0x45, 0x72, 0x62, 0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b,
+0x53, 0x69, 0x62, 0x126, 0x64, 0x3b, 0x54, 0x6e, 0x3b, 0x54, 0x6c, 0x3b,
+0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62, 0x126,
+0x64, 0x3b, 0x54, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d,
+0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62, 0x9a8, 0x9cb, 0x982, 0x9ae, 0x9be, 0x987,
+0x99c, 0x9bf, 0x982, 0x3b, 0x9a8, 0x9bf, 0x982, 0x9a5, 0x9cc, 0x995, 0x9be, 0x9ac,
+0x9be, 0x3b, 0x9b2, 0x9c8, 0x9ac, 0x9be, 0x995, 0x9aa, 0x9cb, 0x995, 0x9aa, 0x9be,
+0x3b, 0x9af, 0x9bc, 0x9c1, 0x9ae, 0x9b6, 0x995, 0x9c8, 0x9b6, 0x9be, 0x3b, 0x9b6,
+0x997, 0x9cb, 0x9b2, 0x9b6, 0x9c7, 0x9a8, 0x3b, 0x987, 0x9b0, 0x9be, 0x987, 0x3b,
+0x9a5, 0x9be, 0x982, 0x99c, 0x9a8, 0x9cb, 0x3b, 0x9a8, 0x9bf, 0x982, 0x3b, 0x9b2,
+0x9c8, 0x3b, 0x9af, 0x9bc, 0x9c1, 0x9ae, 0x3b, 0x9b6, 0x997, 0x3b, 0x987, 0x9b0,
+0x9be, 0x3b, 0x9a5, 0x9be, 0x982, 0x9a8, 0x9cb, 0x982, 0x3b, 0x9a8, 0x9bf, 0x982,
+0x3b, 0x9b2, 0x9c8, 0x9ac, 0x9be, 0x3b, 0x9af, 0x9bc, 0x9c1, 0x9ae, 0x3b, 0x9b6,
+0x997, 0x9cb, 0x3b, 0x987, 0x9b0, 0x9be, 0x3b, 0x9a5, 0x9be, 0x982, 0x4a, 0x65,
+0x64, 0x6f, 0x6f, 0x6e, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65,
+0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x6d, 0x61, 0x79, 0x72, 0x74, 0x3b, 0x4a,
+0x65, 0x72, 0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65,
+0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x68, 0x65, 0x69, 0x6e, 0x65, 0x79, 0x3b,
+0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x4a, 0x65, 0x64, 0x3b, 0x4a, 0x65,
+0x6c, 0x3b, 0x4a, 0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x3b, 0x4a,
+0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65, 0x68, 0x3b, 0x4a, 0x65, 0x73, 0x52,
+0x101, 0x74, 0x61, 0x70, 0x75, 0x3b, 0x4d, 0x61, 0x6e, 0x65, 0x3b, 0x54,
+0x16b, 0x72, 0x65, 0x69, 0x3b, 0x57, 0x65, 0x6e, 0x65, 0x72, 0x65, 0x69,
+0x3b, 0x54, 0x101, 0x69, 0x74, 0x65, 0x3b, 0x50, 0x61, 0x72, 0x61, 0x69,
+0x72, 0x65, 0x3b, 0x52, 0x101, 0x68, 0x6f, 0x72, 0x6f, 0x69, 0x52, 0x101,
+0x74, 0x3b, 0x4d, 0x61, 0x6e, 0x3b, 0x54, 0x16b, 0x72, 0x3b, 0x57, 0x65,
+0x6e, 0x3b, 0x54, 0x101, 0x69, 0x3b, 0x50, 0x61, 0x72, 0x3b, 0x52, 0x101,
+0x68, 0x52, 0x74, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x57, 0x3b, 0x54, 0x3b,
+0x50, 0x3b, 0x52, 0x68, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938,
+0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x935, 0x93e,
+0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930,
+0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e,
+0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x930, 0x935, 0x93f, 0x3b,
+0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, 0x92c, 0x941, 0x927,
+0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b,
+0x936, 0x928, 0x93f, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x6c, 0xed, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x6e, 0x254,
+0x3b, 0x41, 0x6c, 0x61, 0xe1, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x4a, 0x75,
+0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x73, 0x69,
+0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4d, 0x75, 0x72, 0x61, 0x6d,
+0x75, 0x6b, 0x6f, 0x3b, 0x57, 0x61, 0x69, 0x72, 0x69, 0x3b, 0x57, 0x65,
+0x74, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x61, 0x3b, 0x57,
+0x65, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f,
+0x73, 0x69, 0x4b, 0x49, 0x55, 0x3b, 0x4d, 0x52, 0x41, 0x3b, 0x57, 0x41,
+0x49, 0x3b, 0x57, 0x45, 0x54, 0x3b, 0x57, 0x45, 0x4e, 0x3b, 0x57, 0x54,
+0x4e, 0x3b, 0x4a, 0x55, 0x4d, 0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x57,
+0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x31,
+0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x32, 0x3b, 0x41, 0x6e, 0x65, 0x67,
+0x20, 0x33, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x34, 0x3b, 0x41, 0x6e,
+0x65, 0x67, 0x20, 0x35, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x36, 0x3b,
+0x41, 0x6e, 0x65, 0x67, 0x20, 0x37, 0x41, 0x31, 0x3b, 0x41, 0x32, 0x3b,
+0x41, 0x33, 0x3b, 0x41, 0x34, 0x3b, 0x41, 0x35, 0x3b, 0x41, 0x36, 0x3b,
+0x41, 0x37, 0x41d, 0x44f, 0x43c, 0x3b, 0x414, 0x430, 0x432, 0x430, 0x430, 0x3b,
+0x41c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b, 0x41b, 0x445, 0x430, 0x433, 0x432,
+0x430, 0x3b, 0x41f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x411, 0x430, 0x430, 0x441,
+0x430, 0x43d, 0x3b, 0x411, 0x44f, 0x43c, 0x431, 0x430, 0x43d, 0x44f, 0x43c, 0x3b,
+0x434, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440,
+0x3b, 0x43b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, 0x44d,
+0x432, 0x3b, 0x431, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b, 0x431, 0x44f, 0x43c,
+0x431, 0x430, 0x41d, 0x44f, 0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f, 0x3b, 0x41b,
+0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b, 0x411, 0x44f, 0x1828, 0x1822,
+0x182e, 0x180e, 0x1820, 0x3b, 0x1833, 0x1820, 0x1838, 0x1820, 0x3b, 0x182e, 0x1822, 0x1820,
+0x1820, 0x182e, 0x1820, 0x1837, 0x3b, 0x1840, 0x1820, 0x182d, 0x182a, 0x1820, 0x3b, 0x182b,
+0x1826, 0x1837, 0x182a, 0x1826, 0x3b, 0x182a, 0x1820, 0x1830, 0x1820, 0x1829, 0x3b, 0x182a,
+0x1822, 0x182e, 0x182a, 0x1820, 0x1828, 0x1822, 0x3b, 0x1833, 0x1820, 0x3b, 0x182e, 0x1822,
+0x182d, 0x3b, 0x1840, 0x1820, 0x3b, 0x182b, 0x1826, 0x1837, 0x3b, 0x182a, 0x1820, 0x3b,
+0x182a, 0x1822, 0x182e, 0x1828, 0x1822, 0x3b, 0x1832, 0x1820, 0x3b, 0x182e, 0x1822, 0x182d,
+0x3b, 0x1840, 0x1820, 0x3b, 0x182b, 0x1825, 0x1837, 0x3b, 0x182a, 0x1820, 0x3b, 0x182a,
+0x1822, 0x182e, 0x1828, 0x1822, 0x3b, 0x1833, 0x1820, 0x3b, 0x182e, 0x1822, 0x182d, 0x3b,
+0x1840, 0x1820, 0x3b, 0x182b, 0x1825, 0x1837, 0x3b, 0x182a, 0x1820, 0x3b, 0x182a, 0x1822,
+0x182e, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x73, 0x3b, 0x6c, 0x69, 0x6e, 0x64,
+0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x6b,
+0x72, 0x65, 0x64, 0x69, 0x3b, 0x7a, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61,
+0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x69,
+0x64, 0x69, 0x6d, 0x3b, 0x6c, 0x69, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x6d, 0x65, 0x72, 0x3b, 0x7a, 0x65, 0x3b, 0x76, 0x61, 0x6e, 0x3b, 0x73,
+0x61, 0x6d, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b,
+0x76, 0x3b, 0x73, 0x43, 0x6f, 0x6d, 0x2019, 0x79, 0x61, 0x6b, 0x6b, 0x65,
+0x3b, 0x43, 0x6f, 0x6d, 0x6c, 0x61, 0x61, 0x257, 0x69, 0x69, 0x3b, 0x43,
+0x6f, 0x6d, 0x7a, 0x79, 0x69, 0x69, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f,
+0x6d, 0x6b, 0x6f, 0x6c, 0x6c, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6b, 0x61,
+0x6c, 0x64, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x67,
+0x61, 0x69, 0x73, 0x75, 0x75, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x65,
+0x253, 0x73, 0x75, 0x75, 0x43, 0x79, 0x61, 0x3b, 0x43, 0x6c, 0x61, 0x3b,
+0x43, 0x7a, 0x69, 0x3b, 0x43, 0x6b, 0x6f, 0x3b, 0x43, 0x6b, 0x61, 0x3b,
+0x43, 0x67, 0x61, 0x3b, 0x43, 0x7a, 0x65, 0x59, 0x3b, 0x4c, 0x3b, 0x5a,
+0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x47, 0x3b, 0x45, 0x4e, 0x65, 0x74, 0x74,
+0x76, 0x20, 0x43, 0x61, 0x6b, 0x6f, 0x3b, 0x45, 0x6e, 0x68, 0x76, 0x74,
+0x65, 0x63, 0x65, 0x73, 0x6b, 0x76, 0x3b, 0x45, 0x6e, 0x68, 0x76, 0x74,
+0x65, 0x63, 0x65, 0x73, 0x6b, 0x76, 0x20, 0x45, 0x6e, 0x68, 0x76, 0x79,
+0x76, 0x74, 0x6b, 0x65, 0x3b, 0x45, 0x6e, 0x6e, 0x76, 0x72, 0x6b, 0x76,
+0x70, 0x76, 0x3b, 0x45, 0x6e, 0x6e, 0x76, 0x72, 0x6b, 0x76, 0x70, 0x76,
+0x20, 0x45, 0x6e, 0x68, 0x76, 0x79, 0x76, 0x74, 0x6b, 0x65, 0x3b, 0x4e,
+0x61, 0x6b, 0x20, 0x4f, 0x6b, 0x6b, 0x6f, 0x73, 0x6b, 0x76, 0x20, 0x4e,
+0x65, 0x74, 0x74, 0x76, 0x3b, 0x4e, 0x65, 0x74, 0x74, 0x76, 0x20, 0x43,
+0x61, 0x6b, 0x63, 0x75, 0x73, 0x65, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x78,
+0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6e, 0x74, 0x61, 0x78,
+0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x65, 0x6e, 0x73, 0x74, 0x61,
+0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x57, 0x75, 0x6e, 0x73, 0x74,
+0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x6f, 0x6e, 0x64,
+0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x46,
+0x72, 0x61, 0x69, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b,
+0x53, 0x61, 0x74, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
+0x73, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x65, 0x3b, 0x57,
+0x75, 0x3b, 0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x74, 0x53,
+0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x41,
+0x906, 0x907, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e,
+0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c,
+0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x92c, 0x93e,
+0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936,
+0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e,
+0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x92c,
+0x93f, 0x939, 0x93f, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928,
+0x93f, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x3b, 0x92c, 0x941, 0x3b, 0x92c,
+0x93f, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x6c, 0x79, 0x25b, 0x2bc, 0x25b, 0x301,
+0x20, 0x73, 0x1e85, 0xed, 0x14b, 0x74, 0xe8, 0x3b, 0x6d, 0x76, 0x66, 0xf2,
+0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254,
+0x6e, 0x74, 0xe8, 0x20, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b,
+0x30c, 0x2bc, 0x3b, 0x74, 0x73, 0xe8, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20,
+0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e,
+0x74, 0xe8, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20,
+0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6d,
+0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0xe0,
+0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x53, 0x254, 0x301, 0x6e,
+0x64, 0x69, 0x3b, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0xc1, 0x70,
+0x74, 0x61, 0x20, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x57, 0x25b,
+0x301, 0x6e, 0x25b, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x54, 0x254, 0x301, 0x73,
+0x25b, 0x64, 0x25b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x79, 0x25b, 0x64, 0x25b,
+0x3b, 0x53, 0xe1, 0x73, 0x69, 0x64, 0x25b, 0x53, 0x254, 0x301, 0x3b, 0x4d,
+0x254, 0x301, 0x3b, 0xc1, 0x4d, 0x3b, 0x57, 0x25b, 0x301, 0x3b, 0x54, 0x254,
+0x301, 0x3b, 0x46, 0x25b, 0x3b, 0x53, 0xe1, 0x53, 0x1ecd, 0x301, 0x6e, 0x64,
+0xe8, 0x3b, 0x4d, 0x1ecd, 0x301, 0x6e, 0x64, 0xe8, 0x3b, 0x54, 0x69, 0xfa,
+0x7a, 0x64, 0xe8, 0x3b, 0x57, 0x1eb9, 0x301, 0x6e, 0x1eb9, 0x301, 0x7a, 0x64,
+0xe8, 0x3b, 0x54, 0x1ecd, 0x301, 0x7a, 0x64, 0xe8, 0x3b, 0x46, 0x72, 0x61,
+0xed, 0x64, 0xe8, 0x3b, 0x53, 0xe1, 0x74, 0x1ecd, 0x64, 0xe8, 0x53, 0x1ecd,
+0x301, 0x6e, 0x3b, 0x4d, 0x1ecd, 0x301, 0x6e, 0x3b, 0x54, 0x69, 0xfa, 0x3b,
+0x57, 0x1eb9, 0x301, 0x6e, 0x3b, 0x54, 0x1ecd, 0x301, 0x7a, 0x3b, 0x46, 0x72,
+0x61, 0xed, 0x3b, 0x53, 0xe1, 0x74, 0x7de, 0x7ca, 0x7ef, 0x7d9, 0x7cc, 0x7df,
+0x7cf, 0x7f2, 0x3b, 0x7de, 0x7d0, 0x7ec, 0x7d3, 0x7ca, 0x7ec, 0x7df, 0x7cf, 0x7f2,
+0x3b, 0x7de, 0x7d0, 0x7ec, 0x7df, 0x7cf, 0x7f2, 0x3b, 0x7de, 0x7ce, 0x7e3, 0x7ce,
+0x7f2, 0x7df, 0x7cf, 0x7f2, 0x3b, 0x7d3, 0x7cc, 0x7df, 0x7cf, 0x7f2, 0x3b, 0x7db,
+0x7cc, 0x7ec, 0x7e3, 0x7cc, 0x7f2, 0x7ec, 0x7df, 0x7cf, 0x7f2, 0x3b, 0x7de, 0x7cd,
+0x7f2, 0x7d8, 0x7cd, 0x7df, 0x7cf, 0x7f2, 0x7de, 0x7ca, 0x7ef, 0x7d9, 0x3b, 0x7de,
+0x7d0, 0x7ec, 0x7d3, 0x3b, 0x7de, 0x7d0, 0x7ec, 0x7df, 0x3b, 0x7de, 0x7ce, 0x7e3,
+0x3b, 0x7d3, 0x7cc, 0x7df, 0x3b, 0x7db, 0x7cc, 0x7ec, 0x7e3, 0x3b, 0x7de, 0x7cd,
+0x7f2, 0x7d8, 0x7de, 0x7ca, 0x7ef, 0x7d9, 0x3b, 0x7de, 0x7d0, 0x7ec, 0x7d3, 0x3b,
+0x7de, 0x7d0, 0x7ec, 0x7df, 0x7cf, 0x7f2, 0x3b, 0x7de, 0x7ce, 0x7e3, 0x3b, 0x7d3,
+0x7cc, 0x7df, 0x3b, 0x7db, 0x7cc, 0x7ec, 0x7e3, 0x3b, 0x7de, 0x7cd, 0x7f2, 0x7d8,
+0x7de, 0x3b, 0x7de, 0x3b, 0x7de, 0x3b, 0x7de, 0x3b, 0x7d3, 0x3b, 0x7db, 0x3b,
+0x7de, 0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69,
+0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x6d,
+0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x67, 0x61,
+0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75,
+0x6f, 0x72, 0x61, 0x73, 0x64, 0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72,
+0x6a, 0x61, 0x64, 0x61, 0x74, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72,
+0x64, 0x61, 0x74, 0x73, 0x6f, 0x74, 0x6e, 0x3b, 0x76, 0x75, 0x6f, 0x73,
+0x3b, 0x6d, 0x61, 0x14b, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x3b, 0x64, 0x75,
+0x6f, 0x72, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x3b, 0x6c, 0xe1, 0x76, 0x53,
+0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c,
+0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b,
+0x6d, 0xe1, 0x6e, 0x6e, 0x6f, 0x64, 0x61, 0x74, 0x3b, 0x64, 0x69, 0x73,
+0x64, 0x61, 0x74, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61, 0x68,
+0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x74, 0x61,
+0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x74, 0x3b,
+0x6c, 0xe1, 0x76, 0x76, 0x6f, 0x72, 0x64, 0x61, 0x74, 0x73, 0x6f, 0x3b,
+0x6d, 0xe1, 0x3b, 0x64, 0x69, 0x3b, 0x67, 0x61, 0x3b, 0x64, 0x75, 0x3b,
+0x62, 0x65, 0x3b, 0x6c, 0xe1, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x47,
+0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x4c, 0x61, 0x6d, 0x6f, 0x72, 0x65,
+0x6e, 0x61, 0x3b, 0x4d, 0x75, 0x73, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67,
+0x6f, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x62, 0x65, 0x64, 0x69, 0x3b, 0x4c,
+0x61, 0x62, 0x6f, 0x72, 0x61, 0x72, 0x6f, 0x3b, 0x4c, 0x61, 0x62, 0x6f,
+0x6e, 0x65, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x68, 0x6c, 0x61, 0x6e, 0x6f,
+0x3b, 0x4d, 0x6f, 0x6b, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x4c, 0x61, 0x6d,
+0x3b, 0x4d, 0x6f, 0x73, 0x3b, 0x42, 0x65, 0x64, 0x3b, 0x52, 0x61, 0x72,
+0x3b, 0x4e, 0x65, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x6f, 0x6b, 0x4c,
+0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x52, 0x3b, 0x4e, 0x3b, 0x48, 0x3b, 0x4d,
+0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b,
+0x53, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x53, 0x69, 0x74, 0x68, 0x61,
+0x74, 0x68, 0x75, 0x3b, 0x53, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x68,
+0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c,
+0x6f, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x53, 0x69, 0x62,
+0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x53, 0x69, 0x68,
+0x3b, 0x4d, 0x67, 0x71, 0x53, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b,
+0x53, 0x3b, 0x53, 0x3b, 0x4d, 0x73, 0xf8, 0x6e, 0x2e, 0x3b, 0x6d, 0x61,
+0x6e, 0x2e, 0x3b, 0x74, 0x69, 0x72, 0x2e, 0x3b, 0x6f, 0x6e, 0x73, 0x2e,
+0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b, 0x6c,
+0xf8, 0x72, 0x2e, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5,
+0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x79, 0x73, 0x64, 0x61, 0x67, 0x3b,
+0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64,
+0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61,
+0x75, 0x72, 0x64, 0x61, 0x67, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e,
+0x3b, 0x74, 0x79, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72,
+0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x73, 0xf8, 0x2e, 0x3b,
+0x6d, 0xe5, 0x2e, 0x3b, 0x74, 0x79, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b,
+0x74, 0x6f, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c, 0x61, 0x2e, 0x43,
+0xe4, 0x14b, 0x20, 0x6b, 0x75, 0x254, 0x74, 0x68, 0x3b, 0x4a, 0x69, 0x65,
+0x63, 0x20, 0x6c, 0x61, 0x331, 0x74, 0x3b, 0x52, 0x25b, 0x77, 0x20, 0x6c,
+0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x20, 0x6c,
+0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x20, 0x6c,
+0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x20,
+0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x20,
+0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x43, 0xe4, 0x14b, 0x3b, 0x4a, 0x69, 0x65,
+0x63, 0x3b, 0x52, 0x25b, 0x77, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x3b,
+0x14a, 0x75, 0x61, 0x61, 0x6e, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63,
+0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x43, 0x3b, 0x4a, 0x3b, 0x52, 0x3b,
+0x44, 0x3b, 0x14a, 0x3b, 0x44, 0x3b, 0x42, 0x4c, 0x61, 0x6d, 0x75, 0x6c,
+0x75, 0x6e, 0x67, 0x75, 0x3b, 0x4c, 0x6f, 0x6c, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x4c, 0x61, 0x63, 0x68, 0x69, 0x77, 0x69, 0x72, 0x69, 0x3b, 0x4c,
+0x61, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x61, 0x63,
+0x68, 0x69, 0x6e, 0x61, 0x79, 0x69, 0x3b, 0x4c, 0x61, 0x63, 0x68, 0x69,
+0x73, 0x61, 0x6e, 0x75, 0x3b, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x75, 0x6b,
+0x61, 0x4d, 0x75, 0x6c, 0x3b, 0x4c, 0x65, 0x6d, 0x3b, 0x57, 0x69, 0x72,
+0x3b, 0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x69, 0x3b, 0x53, 0x61, 0x6e,
+0x3b, 0x57, 0x65, 0x72, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x67, 0x65, 0x3b,
+0x64, 0x69, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72,
+0x73, 0x3b, 0x64, 0x69, 0x6d, 0xe8, 0x63, 0x72, 0x65, 0x73, 0x3b, 0x64,
+0x69, 0x6a, 0xf2, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76, 0x65, 0x6e, 0x64,
+0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x73, 0x73, 0x61, 0x62, 0x74, 0x65,
+0x44, 0x67, 0x3b, 0x44, 0x6c, 0x3b, 0x44, 0x6d, 0x3b, 0x44, 0x63, 0x3b,
+0x44, 0x6a, 0x3b, 0x44, 0x76, 0x3b, 0x44, 0x73, 0x64, 0x69, 0x6d, 0x65,
+0x6e, 0x67, 0x65, 0x3b, 0x64, 0x65, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64,
+0x69, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0xe8, 0x72, 0x63,
+0x6c, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6a, 0x61, 0x75, 0x73, 0x3b, 0x64,
+0x69, 0x75, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x73,
+0x73, 0x61, 0x62, 0x74, 0x65, 0x64, 0x69, 0x6d, 0x3b, 0x64, 0x65, 0x6c,
+0x3b, 0x64, 0x6d, 0x61, 0x3b, 0x64, 0x6d, 0xe8, 0x3b, 0x64, 0x69, 0x6a,
+0x3b, 0x64, 0x69, 0x75, 0x3b, 0x64, 0x69, 0x73, 0x44, 0x3b, 0x4c, 0x3b,
+0x4d, 0x3b, 0x58, 0x3b, 0x4a, 0x3b, 0x55, 0x3b, 0x53, 0xb30, 0xb2c, 0xb3f,
+0xb2c, 0xb3e, 0xb30, 0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e,
+0xb19, 0xb4d, 0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27, 0xb2c,
+0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36,
+0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c,
+0xb3e, 0xb30, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b, 0xb2e, 0xb19,
+0xb4d, 0xb17, 0xb33, 0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41,
+0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb30, 0x3b,
+0xb38, 0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36,
+0xb41, 0x3b, 0xb36, 0x44, 0x69, 0x6c, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x57,
+0x69, 0x69, 0x78, 0x61, 0x74, 0x61, 0x3b, 0x51, 0x69, 0x62, 0x78, 0x61,
+0x74, 0x61, 0x3b, 0x52, 0x6f, 0x6f, 0x62, 0x69, 0x69, 0x3b, 0x4b, 0x61,
+0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x61, 0x61, 0x74,
+0x61, 0x3b, 0x53, 0x61, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x44, 0x69, 0x6c,
+0x3b, 0x57, 0x69, 0x78, 0x3b, 0x51, 0x69, 0x62, 0x3b, 0x52, 0x6f, 0x62,
+0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x6e,
+0x44, 0x3b, 0x57, 0x3b, 0x51, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b,
+0x53, 0xd801, 0xdcb9, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801,
+0xdccf, 0xd801, 0xdcd8, 0xd801, 0xdce4, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcf0, 0xd801, 0xdcd8,
+0xd801, 0xdce4, 0xd801, 0xdce3, 0x3b, 0xd801, 0xdcb9, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x20, 0xd801, 0xdcc4, 0xd801, 0xdcd8, 0xd801, 0xdce1, 0xd801, 0xdcdb, 0x358,
+0xd801, 0xdce7, 0xd801, 0xdce3, 0x3b, 0xd801, 0xdcb9, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801, 0xdcf5, 0xd801, 0xdcea, 0x358,
+0xd801, 0xdcec, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcb9, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801, 0xdcf5, 0xd801, 0xdcd8, 0xd801,
+0xdcdc, 0xd801, 0xdce3, 0x3b, 0xd801, 0xdcb9, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcec, 0xd801,
+0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801, 0xdcf0, 0xd801, 0xdcea, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcb9, 0xd801, 0xdcd8, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8,
+0x20, 0xd801, 0xdcc8, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdcf5, 0xd801, 0xdcd8, 0xd801, 0xdcf2,
+0xd801, 0xdcd8, 0x20, 0xd801, 0xdcfb, 0xd801, 0xdce3, 0x358, 0x3b, 0xd801, 0xdcb9, 0xd801,
+0xdcd8, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdcc2, 0xd801, 0xdce4, 0xd801,
+0xdcd8, 0xd801, 0xdcf8, 0xd801, 0xdcdf, 0x20, 0xd801, 0xdce3, 0x358, 0xd801, 0xdce4, 0xd801,
+0xdcdf, 0xd801, 0xdccf, 0x3b, 0xd801, 0xdcc4, 0x3b, 0xd801, 0xdccd, 0x3b, 0xd801, 0xdcb4,
+0x3b, 0xd801, 0xdcc8, 0x3b, 0xd801, 0xdcca, 0x3b, 0xd801, 0xdcf8, 0x425, 0x443, 0x44b,
+0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x41a, 0x44a, 0x443, 0x44b, 0x440,
+0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b,
+0x4d4, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x426, 0x44b, 0x43f,
+0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c, 0x430, 0x439, 0x440, 0x4d5, 0x43c,
+0x431, 0x43e, 0x43d, 0x3b, 0x421, 0x430, 0x431, 0x430, 0x442, 0x445, 0x443, 0x44b,
+0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x43a, 0x44a, 0x443, 0x44b, 0x440,
+0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x434, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b,
+0x4d5, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x446, 0x44b, 0x43f,
+0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x43c, 0x430, 0x439, 0x440, 0x4d5, 0x43c,
+0x431, 0x43e, 0x43d, 0x3b, 0x441, 0x430, 0x431, 0x430, 0x442, 0x425, 0x446, 0x431,
+0x3b, 0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440, 0x442,
+0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b, 0x421, 0x431, 0x442,
+0x445, 0x446, 0x431, 0x3b, 0x43a, 0x440, 0x441, 0x3b, 0x434, 0x446, 0x433, 0x3b,
+0x4d5, 0x440, 0x442, 0x3b, 0x446, 0x43f, 0x440, 0x3b, 0x43c, 0x440, 0x431, 0x3b,
+0x441, 0x431, 0x442, 0x425, 0x3b, 0x41a, 0x3b, 0x414, 0x3b, 0x4d4, 0x3b, 0x426,
+0x3b, 0x41c, 0x3b, 0x421, 0x64, 0x6a, 0x61, 0x64, 0x75, 0x6d, 0x69, 0x6e,
+0x67, 0x75, 0x3b, 0x64, 0x6a, 0x61, 0x6c, 0x75, 0x6e, 0x61, 0x3b, 0x64,
+0x6a, 0x61, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x64, 0x6a, 0x61, 0x72, 0x61,
+0x73, 0x6f, 0x6e, 0x3b, 0x64, 0x6a, 0x61, 0x77, 0x65, 0x70, 0x73, 0x3b,
+0x64, 0x6a, 0x61, 0x62, 0x69, 0xe8, 0x72, 0x6e, 0xe8, 0x3b, 0x64, 0x6a,
+0x61, 0x73, 0x61, 0x62, 0x72, 0x61, 0x64, 0x64, 0x3b, 0x64, 0x6c, 0x3b,
+0x64, 0x6d, 0x3b, 0x64, 0x72, 0x3b, 0x64, 0x77, 0x3b, 0x64, 0x62, 0x3b,
+0x64, 0x73, 0x64a, 0x648, 0x646, 0x6cd, 0x3b, 0x62f, 0x648, 0x646, 0x6cd, 0x3b,
+0x62f, 0x631, 0x6d0, 0x646, 0x6cd, 0x3b, 0x685, 0x644, 0x631, 0x646, 0x6cd, 0x3b,
+0x67e, 0x64a, 0x646, 0x681, 0x646, 0x6cd, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b,
+0x627, 0x648, 0x646, 0x6cd, 0x6cc, 0x6a9, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62f,
+0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628,
+0x647, 0x3b, 0x686, 0x647, 0x627, 0x631, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e,
+0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b,
+0x634, 0x646, 0x628, 0x647, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b,
+0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x65,
+0x6c, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61,
+0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x15b,
+0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65,
+0x6b, 0x3b, 0x70, 0x69, 0x105, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62,
+0x6f, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x2e, 0x3b, 0x70, 0x6f,
+0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b, 0x63,
+0x7a, 0x77, 0x2e, 0x3b, 0x70, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e,
+0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a, 0x3b, 0x43, 0x3b, 0x50, 0x3b,
+0x53, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x15b, 0x3b, 0x63, 0x3b, 0x70,
+0x3b, 0x73, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65,
+0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b,
+0x74, 0x65, 0x72, 0xe7, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b,
+0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61,
+0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72,
+0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72,
+0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d, 0x2e,
+0x3b, 0x73, 0x65, 0x67, 0x2e, 0x3b, 0x74, 0x65, 0x72, 0x2e, 0x3b, 0x71,
+0x75, 0x61, 0x2e, 0x3b, 0x71, 0x75, 0x69, 0x2e, 0x3b, 0x73, 0x65, 0x78,
+0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b,
+0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53, 0x64, 0x6f, 0x6d, 0x69, 0x6e,
+0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x3b, 0x74,
+0x65, 0x72, 0xe7, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x3b,
+0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61,
+0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x6e, 0x61, 0x64, 0x12b, 0x6c,
+0x69, 0x3b, 0x70, 0x61, 0x6e, 0x61, 0x64, 0x12b, 0x6c, 0x69, 0x3b, 0x77,
+0x69, 0x73, 0x61, 0x73, 0x12b, 0x64, 0x69, 0x73, 0x3b, 0x70, 0x75, 0x73,
+0x73, 0x69, 0x73, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x3b, 0x6b, 0x65,
+0x74, 0x77, 0x69, 0x72, 0x74, 0x69, 0x6b, 0x73, 0x3b, 0x70, 0x113, 0x6e,
+0x74, 0x6e, 0x69, 0x6b, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x74,
+0x69, 0x6b, 0x61, 0x6e, 0x61, 0x64, 0x3b, 0x70, 0x61, 0x6e, 0x3b, 0x77,
+0x69, 0x73, 0x3b, 0x70, 0x75, 0x73, 0x3b, 0x6b, 0x65, 0x74, 0x3b, 0x70,
+0x113, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b,
+0x50, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x53, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30,
+0x3b, 0xa38, 0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32,
+0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0xa35, 0xa3e, 0xa30, 0x3b,
+0xa35, 0xa40, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15,
+0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30,
+0xa35, 0xa3e, 0xa30, 0xa10, 0xa24, 0x3b, 0xa38, 0xa4b, 0xa2e, 0x3b, 0xa2e, 0xa70,
+0xa17, 0xa32, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0x3b, 0xa35, 0xa40, 0xa30, 0x3b,
+0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71,
+0xa1a, 0xa30, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41,
+0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0x3b, 0xa38, 0xa3c,
+0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646,
+0x6af, 0x644, 0x3b, 0x628, 0x64f, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631,
+0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1,
+0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65,
+0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0xe9,
+0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x4a, 0x75, 0x65, 0x76, 0x65,
+0x73, 0x3b, 0x56, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0xe1,
+0x62, 0x61, 0x64, 0x6f, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0xe9, 0x3b, 0x4a, 0x75, 0x65, 0x3b,
+0x56, 0x69, 0x65, 0x3b, 0x53, 0x61, 0x62, 0x44, 0x3b, 0x4c, 0x3b, 0x4d,
+0x3b, 0x58, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x64, 0x75, 0x6d, 0x69,
+0x6e, 0x69, 0x63, 0x103, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d, 0x61,
+0x72, 0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69,
+0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x3b,
+0x73, 0xe2, 0x6d, 0x62, 0x103, 0x74, 0x103, 0x64, 0x75, 0x6d, 0x2e, 0x3b,
+0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69,
+0x65, 0x2e, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x2e, 0x3b,
+0x73, 0xe2, 0x6d, 0x2e, 0x44, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x65, 0x3b, 0x4a, 0x6f, 0x69, 0x3b,
+0x56, 0x69, 0x6e, 0x3b, 0x53, 0xe2, 0x6d, 0x44, 0x3b, 0x4c, 0x3b, 0x4d,
+0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x64, 0x75,
+0x6d, 0x65, 0x6e, 0x67, 0x69, 0x61, 0x3b, 0x67, 0x6c, 0x69, 0x6e, 0x64,
+0x65, 0x73, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d,
+0x65, 0x73, 0x65, 0x6d, 0x6e, 0x61, 0x3b, 0x67, 0x69, 0x65, 0x76, 0x67,
+0x69, 0x61, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x69, 0x3b,
+0x73, 0x6f, 0x6e, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x67, 0x6c, 0x69, 0x3b,
+0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69, 0x65, 0x3b, 0x76, 0x65,
+0x3b, 0x73, 0x6f, 0x44, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47,
+0x3b, 0x56, 0x3b, 0x53, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c,
+0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b,
+0x49, 0x6a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x49, 0x6a, 0x75,
+0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d,
+0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x49,
+0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x49, 0x6a, 0x70, 0x3b,
+0x49, 0x6a, 0x74, 0x3b, 0x49, 0x6a, 0x6e, 0x3b, 0x49, 0x6a, 0x74, 0x6e,
+0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x49, 0x6a, 0x6d,
+0x4b, 0x75, 0x20, 0x77, 0x2019, 0x69, 0x6e, 0x64, 0x77, 0x69, 0x3b, 0x4b,
+0x75, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b,
+0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b,
+0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75,
+0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b,
+0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75,
+0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x74, 0x75, 0x63, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e,
+0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b,
+0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64,
+0x2e, 0x432, 0x43e, 0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435,
+0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438, 0x43a,
+0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435,
+0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0x3b, 0x43f,
+0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x431, 0x43e,
+0x442, 0x430, 0x432, 0x441, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441,
+0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x412, 0x3b,
+0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x4e,
+0x61, 0x62, 0x61, 0x20, 0x53, 0x61, 0x6d, 0x62, 0x61, 0x74, 0x3b, 0x53,
+0x61, 0x6e, 0x69, 0x3b, 0x53, 0x61, 0x6c, 0x75, 0x73, 0x3b, 0x52, 0x61,
+0x62, 0x75, 0x71, 0x3b, 0x43, 0x61, 0x6d, 0x75, 0x73, 0x3b, 0x4a, 0x75,
+0x6d, 0x71, 0x61, 0x74, 0x61, 0x3b, 0x51, 0x75, 0x6e, 0x78, 0x61, 0x20,
+0x53, 0x61, 0x6d, 0x62, 0x61, 0x74, 0x4e, 0x61, 0x62, 0x3b, 0x53, 0x61,
+0x6e, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x43, 0x61,
+0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x51, 0x75, 0x6e, 0x4e, 0x3b, 0x53,
+0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x43, 0x3b, 0x4a, 0x3b, 0x51, 0x431, 0x430,
+0x441, 0x43a, 0x44b, 0x4bb, 0x44b, 0x430, 0x43d, 0x43d, 0x44c, 0x430, 0x3b, 0x431,
+0x44d, 0x43d, 0x438, 0x434, 0x438, 0x44d, 0x43d, 0x43d, 0x44c, 0x438, 0x43a, 0x3b,
+0x43e, 0x43f, 0x442, 0x443, 0x43e, 0x440, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x43a,
+0x3b, 0x441, 0x44d, 0x440, 0x44d, 0x434, 0x44d, 0x3b, 0x447, 0x44d, 0x43f, 0x43f,
+0x438, 0x44d, 0x440, 0x3b, 0x411, 0x44d, 0x44d, 0x442, 0x438, 0x4a5, 0x441, 0x44d,
+0x3b, 0x441, 0x443, 0x431, 0x443, 0x43e, 0x442, 0x430, 0x431, 0x441, 0x3b, 0x431,
+0x43d, 0x3b, 0x43e, 0x43f, 0x3b, 0x441, 0x44d, 0x3b, 0x447, 0x43f, 0x3b, 0x431,
+0x44d, 0x3b, 0x441, 0x431, 0x411, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x421, 0x3b,
+0x427, 0x3b, 0x411, 0x3b, 0x421, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20,
+0x65, 0x65, 0x20, 0x61, 0x72, 0x65, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f,
+0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4d, 0x64,
+0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019,
+0x77, 0x61, 0x6e, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65,
+0x65, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f,
+0x74, 0x20, 0x65, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b, 0x4d, 0x64, 0x65,
+0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61, 0x3b,
+0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x77,
+0x65, 0x41, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x6e, 0x3b, 0x4f, 0x6e, 0x67,
+0x3b, 0x49, 0x6e, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70,
+0x3b, 0x4b, 0x77, 0x65, 0x41, 0x3b, 0x4b, 0x3b, 0x4f, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x53, 0x3b, 0x4b, 0x42, 0x69, 0x6b, 0x75, 0x61, 0x2d, 0xf4,
+0x6b, 0x6f, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0xfb, 0x73, 0x65,
+0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x70, 0x74, 0xe2, 0x3b, 0x42,
+0xef, 0x6b, 0x75, 0x61, 0x2d, 0x75, 0x73, 0xef, 0xf6, 0x3b, 0x42, 0xef,
+0x6b, 0x75, 0x61, 0x2d, 0x6f, 0x6b, 0xfc, 0x3b, 0x4c, 0xe2, 0x70, 0xf4,
+0x73, 0xf6, 0x3b, 0x4c, 0xe2, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x42, 0x6b,
+0x31, 0x3b, 0x42, 0x6b, 0x32, 0x3b, 0x42, 0x6b, 0x33, 0x3b, 0x42, 0x6b,
+0x34, 0x3b, 0x42, 0x6b, 0x35, 0x3b, 0x4c, 0xe2, 0x70, 0x3b, 0x4c, 0xe2,
+0x79, 0x4b, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50,
+0x3b, 0x59, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e,
+0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b,
+0x41, 0x6c, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a,
+0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73,
+0x69, 0x4d, 0x75, 0x6c, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e,
+0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75,
+0x3b, 0x4a, 0x6d, 0x6f, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b,
+0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x938, 0x930,
+0x903, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x938, 0x930, 0x903, 0x3b, 0x92e,
+0x902, 0x917, 0x932, 0x935, 0x93e, 0x938, 0x930, 0x903, 0x3b, 0x92c, 0x941, 0x927,
+0x935, 0x93e, 0x938, 0x930, 0x903, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e,
+0x938, 0x930, 0x3a, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x938,
+0x930, 0x903, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x938, 0x930, 0x903, 0x1c65,
+0x1c64, 0x1c78, 0x1c5c, 0x1c6e, 0x3b, 0x1c5a, 0x1c5b, 0x1c6e, 0x3b, 0x1c75, 0x1c5f, 0x1c5e,
+0x1c6e, 0x3b, 0x1c65, 0x1c5f, 0x1c79, 0x1c5c, 0x1c69, 0x1c71, 0x3b, 0x1c65, 0x1c5f, 0x1c79,
+0x1c68, 0x1c6b, 0x1c64, 0x3b, 0x1c61, 0x1c5f, 0x1c79, 0x1c68, 0x1c69, 0x1c62, 0x3b, 0x1c67,
+0x1c69, 0x1c66, 0x1c69, 0x1c62, 0x1c65, 0x1c64, 0x1c78, 0x3b, 0x1c5a, 0x1c5b, 0x3b, 0x1c75,
+0x1c5f, 0x3b, 0x1c65, 0x1c5f, 0x1c79, 0x3b, 0x1c65, 0x1c5f, 0x1c79, 0x1c68, 0x3b, 0x1c61,
+0x1c5f, 0x1c79, 0x3b, 0x1c67, 0x1c69, 0x1c65, 0x3b, 0x1c5a, 0x3b, 0x1c75, 0x3b, 0x1c65,
+0x3b, 0x1c65, 0x3b, 0x1c61, 0x3b, 0x1c67, 0x64, 0x6f, 0x6d, 0xec, 0x6e, 0x69,
+0x67, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72,
+0x74, 0x69, 0x73, 0x3b, 0x6d, 0xe8, 0x72, 0x63, 0x75, 0x72, 0x69, 0x73,
+0x3b, 0x67, 0x69, 0xf2, 0x62, 0x69, 0x61, 0x3b, 0x63, 0x68, 0x65, 0x6e,
+0xe0, 0x62, 0x75, 0x72, 0x61, 0x3b, 0x73, 0xe0, 0x62, 0x61, 0x64, 0x75,
+0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x6d, 0xe8, 0x72, 0x3b, 0x67, 0x69, 0xf2, 0x3b, 0x63, 0x68, 0x65, 0x3b,
+0x73, 0xe0, 0x62, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47,
+0x3b, 0x43, 0x3b, 0x53, 0x44, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b,
+0x43, 0x68, 0x69, 0x70, 0x6f, 0x73, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x70,
+0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b,
+0x43, 0x68, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68,
+0x61, 0x6e, 0x75, 0x3b, 0x53, 0x61, 0x62, 0x75, 0x64, 0x75, 0x44, 0x69,
+0x6d, 0x3b, 0x50, 0x6f, 0x73, 0x3b, 0x50, 0x69, 0x72, 0x3b, 0x54, 0x61,
+0x74, 0x3b, 0x4e, 0x61, 0x69, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x53, 0x61,
+0x62, 0x44, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x53,
+0x3b, 0x53, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
+0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430,
+0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432,
+0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441,
+0x443, 0x431, 0x43e, 0x442, 0x430, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d,
+0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x435, 0x3b, 0x447, 0x435, 0x442,
+0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x43d, 0x435, 0x434, 0x458,
+0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430,
+0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438,
+0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430,
+0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e,
+0x442, 0x430, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f,
+0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f,
+0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65,
+0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b,
+0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x65, 0x64, 0x3b, 0x70,
+0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d,
+0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x6e, 0x65,
+0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64,
+0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b,
+0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74,
+0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b,
+0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x70,
+0x69, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x74, 0x75,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d,
+0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a,
+0x75, 0x6d, 0x61, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x4a, 0x70, 0x69, 0x3b,
+0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6d, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b,
+0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x32,
+0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x31,
+0x53, 0x76, 0x6f, 0x6e, 0x64, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x68, 0x75,
+0x72, 0x6f, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43,
+0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x61,
+0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x75,
+0x67, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x53, 0x76, 0x6f, 0x3b, 0x4d, 0x75,
+0x76, 0x3b, 0x43, 0x68, 0x70, 0x3b, 0x43, 0x68, 0x74, 0x3b, 0x43, 0x68,
+0x6e, 0x3b, 0x43, 0x68, 0x73, 0x3b, 0x4d, 0x75, 0x67, 0x53, 0x3b, 0x4d,
+0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4d, 0xa46d, 0xa18f,
+0xa44d, 0x3b, 0xa18f, 0xa282, 0xa2cd, 0x3b, 0xa18f, 0xa282, 0xa44d, 0x3b, 0xa18f, 0xa282,
+0xa315, 0x3b, 0xa18f, 0xa282, 0xa1d6, 0x3b, 0xa18f, 0xa282, 0xa26c, 0x3b, 0xa18f, 0xa282,
+0xa0d8, 0xa46d, 0xa18f, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa315,
+0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f, 0xa26c, 0x3b, 0xa18f, 0xa0d8, 0xa18f, 0x3b, 0xa2cd,
+0x3b, 0xa44d, 0x3b, 0xa315, 0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b, 0xa0d8, 0x64, 0x75,
+0x6d, 0xec, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x6e, 0x69,
+0x64, 0xec, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x64, 0xec, 0x61,
+0x3b, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69, 0x64, 0xec, 0x61, 0x3b,
+0x6a, 0x6f, 0x76, 0x69, 0x64, 0xec, 0x61, 0x3b, 0x76, 0x65, 0x6e, 0x6e,
+0x69, 0x64, 0xec, 0x61, 0x3b, 0x73, 0xe0, 0x62, 0x62, 0x61, 0x74, 0x75,
+0x53, 0x61, 0x6d, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x6e, 0x79,
+0x6f, 0x3b, 0x4d, 0x61, 0x61, 0x6b, 0x69, 0x73, 0x61, 0x6e, 0x79, 0x6f,
+0x3b, 0x52, 0x6f, 0x6f, 0x77, 0x65, 0x3b, 0x48, 0x61, 0x6d, 0x75, 0x73,
+0x65, 0x3b, 0x41, 0x72, 0x62, 0x65, 0x3b, 0x51, 0x69, 0x64, 0x61, 0x61,
+0x6d, 0x65, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x4d, 0x61,
+0x6b, 0x3b, 0x52, 0x6f, 0x77, 0x3b, 0x48, 0x61, 0x6d, 0x3b, 0x41, 0x72,
+0x62, 0x3b, 0x51, 0x69, 0x64, 0x53, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x52,
+0x3b, 0x48, 0x3b, 0x41, 0x3b, 0x51, 0x6e, 0x69, 0x79, 0x64, 0x7a, 0x69,
+0x65, 0x6c, 0x61, 0x3b, 0x70, 0x79, 0x144, 0x64, 0x7a, 0x69, 0x61, 0x142,
+0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73, 0x74,
+0x72, 0x7a, 0x6f, 0x64, 0x61, 0x3b, 0x73, 0x7a, 0x74, 0x77, 0x6f, 0x72,
+0x74, 0x65, 0x6b, 0x3b, 0x70, 0x69, 0x14d, 0x6e, 0x74, 0x65, 0x6b, 0x3b,
+0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x69, 0x79, 0x3b, 0x70, 0x79,
+0x144, 0x3b, 0x77, 0x74, 0x6f, 0x3b, 0x73, 0x74, 0x72, 0x3b, 0x73, 0x7a,
+0x74, 0x3b, 0x70, 0x69, 0x14d, 0x3b, 0x73, 0x6f, 0x62, 0x622, 0x686, 0x631,
+0x3b, 0x633, 0x648, 0x645, 0x631, 0x3b, 0x627, 0x6b1, 0x627, 0x631, 0x648, 0x3b,
+0x627, 0x631, 0x628, 0x639, 0x3b, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x62c, 0x645,
+0x639, 0x648, 0x3b, 0x687, 0x646, 0x687, 0x631, 0x622, 0x686, 0x631, 0x3b, 0x633,
+0x648, 0x3b, 0x627, 0x6b1, 0x627, 0x631, 0x648, 0x3b, 0x627, 0x631, 0x628, 0x639,
+0x3b, 0x62e, 0x645, 0x3b, 0x62c, 0x645, 0x639, 0x648, 0x3b, 0x687, 0x646, 0x687,
+0x631, 0x906, 0x930, 0x94d, 0x924, 0x3b, 0x938, 0x942, 0x3b, 0x92e, 0x902, 0x3b,
+0x92c, 0x941, 0x952, 0x927, 0x3b, 0x935, 0x93f, 0x938, 0x3b, 0x91c, 0x941, 0x92e,
+0x3b, 0x91b, 0x902, 0x91b, 0x906, 0x930, 0x94d, 0x924, 0x935, 0x93e, 0x930, 0x3b,
+0x938, 0x942, 0x92e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x941, 0x3b, 0x92c,
+0x941, 0x952, 0x927, 0x930, 0x3b, 0x935, 0x93f, 0x938, 0x94d, 0x92a, 0x924, 0x3b,
+0x91c, 0x941, 0x92e, 0x94b, 0x3b, 0x91b, 0x902, 0x91b, 0x930, 0x906, 0x3b, 0x938,
+0x942, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x935, 0x93f, 0x938,
+0x3b, 0x91c, 0x941, 0x3b, 0x91b, 0x902, 0x91b, 0x906, 0x930, 0x94d, 0x924, 0x3b,
+0x938, 0x942, 0x3b, 0x92e, 0x902, 0x917, 0x3b, 0x92c, 0x941, 0x952, 0x927, 0x3b,
+0x935, 0x93f, 0x938, 0x3b, 0x91c, 0x941, 0x92e, 0x3b, 0x91b, 0x902, 0x91b, 0x906,
+0x3b, 0x938, 0x942, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x952, 0x3b, 0x935,
+0x93f, 0x3b, 0x91c, 0x941, 0x3b, 0x91b, 0x902, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf,
+0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb, 0xdd4,
+0xdc0, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6,
+0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4, 0xdad, 0xdd2, 0xdb1, 0xdca, 0xdaf,
+0xdcf, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdc3,
+0xdd9, 0xdb1, 0xdc3, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0xd89, 0xdbb, 0xdd2, 0xdaf,
+0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0x3b,
+0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3,
+0xdca, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xd89, 0x3b,
+0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3,
+0xdd2, 0x3b, 0xdc3, 0xdd9, 0x6e, 0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x70,
+0x6f, 0x6e, 0x64, 0x65, 0x6c, 0x6f, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72,
+0x6f, 0x6b, 0x3b, 0x73, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74,
+0x76, 0x72, 0x74, 0x6f, 0x6b, 0x3b, 0x70, 0x69, 0x61, 0x74, 0x6f, 0x6b,
+0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x6f,
+0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b, 0x70, 0x69,
+0x3b, 0x73, 0x6f, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x161,
+0x3b, 0x70, 0x3b, 0x73, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b,
+0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x65, 0x6b, 0x3b, 0x74,
+0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d,
+0x65, 0x74, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b,
+0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x65, 0x64, 0x2e, 0x3b,
+0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x73, 0x72,
+0x65, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e,
+0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x6e, 0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73,
+0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x53, 0x61, 0x62, 0x69, 0x69, 0x74,
+0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b, 0x4f, 0x77, 0x6f,
+0x6b, 0x75, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75,
+0x73, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x6e, 0x61,
+0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e, 0x75, 0x3b,
+0x4f, 0x6c, 0x6f, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x53, 0x61,
+0x62, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x3b, 0x4b, 0x75, 0x62, 0x69,
+0x3b, 0x4b, 0x75, 0x73, 0x61, 0x3b, 0x4b, 0x75, 0x6e, 0x61, 0x3b, 0x4b,
+0x75, 0x74, 0x61, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x53, 0x3b, 0x42, 0x3b,
+0x42, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x41, 0x78, 0x61,
+0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c,
+0x61, 0x61, 0x64, 0x6f, 0x3b, 0x41, 0x72, 0x62, 0x61, 0x63, 0x6f, 0x3b,
+0x4b, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d, 0x63,
+0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x41, 0x78, 0x64, 0x3b, 0x49,
+0x73, 0x6e, 0x3b, 0x54, 0x6c, 0x64, 0x6f, 0x3b, 0x41, 0x72, 0x62, 0x63,
+0x3b, 0x4b, 0x68, 0x6d, 0x73, 0x3b, 0x4a, 0x6d, 0x63, 0x3b, 0x53, 0x62,
+0x74, 0x69, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x68,
+0x3b, 0x4a, 0x3b, 0x53, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x68, 0x61, 0x3b,
+0x4d, 0x6d, 0x61, 0x6e, 0x74, 0x61, 0x68, 0x61, 0x3b, 0x4c, 0x61, 0x62,
+0x6f, 0x62, 0x65, 0x64, 0x69, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x72, 0x61,
+0x72, 0x75, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x6e, 0x65, 0x3b, 0x4c, 0x61,
+0x62, 0x6f, 0x68, 0x6c, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x6f, 0x71, 0x65,
+0x62, 0x65, 0x6c, 0x6f, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x6d, 0x61, 0x3b,
+0x42, 0x65, 0x64, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4e, 0x65, 0x3b, 0x48,
+0x6c, 0x61, 0x3b, 0x4d, 0x6f, 0x71, 0x75, 0x53, 0x6f, 0x6e, 0x74, 0x6f,
+0x3b, 0x75, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b, 0x75, 0x4c, 0x65, 0x73,
+0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x65, 0x73, 0x69, 0x74, 0x68,
+0x61, 0x74, 0x68, 0x75, 0x3b, 0x75, 0x4c, 0x65, 0x73, 0x69, 0x6e, 0x65,
+0x3b, 0x6e, 0x67, 0x6f, 0x4c, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e,
+0x75, 0x3b, 0x75, 0x6d, 0x47, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x53,
+0x6f, 0x6e, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54,
+0x68, 0x61, 0x3b, 0x4e, 0x65, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x47, 0x71,
+0x69, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e,
+0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69,
+0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x6a, 0x75, 0x65, 0x76,
+0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x73,
+0xe1, 0x62, 0x61, 0x64, 0x6f, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e,
+0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0xe9, 0x3b, 0x6a, 0x75, 0x65,
+0x3b, 0x76, 0x69, 0x65, 0x3b, 0x73, 0xe1, 0x62, 0x44, 0x3b, 0x4c, 0x3b,
+0x4d, 0x3b, 0x6d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x2d30, 0x2d59, 0x2d30,
+0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59,
+0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30,
+0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59,
+0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x2d30, 0x2d59, 0x2d30, 0x3b,
+0x2d30, 0x2d62, 0x2d4f, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x3b,
+0x2d30, 0x2d3d, 0x2d61, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x3b, 0x2d30, 0x2d59, 0x2d49,
+0x2d39, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x6e, 0xe9,
+0x6e, 0x3b, 0x53, 0x61, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x65, 0x62,
+0x6f, 0x3b, 0x4b, 0x65, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x61, 0x68, 0x3b, 0x53, 0x61, 0x70, 0x74, 0x75, 0x4d, 0x6e, 0x67, 0x3b,
+0x53, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0x52, 0x65, 0x62, 0x3b,
+0x4b, 0x65, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x70, 0x4c,
+0x69, 0x73, 0x6f, 0x6e, 0x74, 0x66, 0x6f, 0x3b, 0x75, 0x4d, 0x73, 0x6f,
+0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x4c, 0x65, 0x73, 0x69,
+0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x65, 0x73, 0x69, 0x74, 0x73, 0x61,
+0x74, 0x66, 0x75, 0x3b, 0x4c, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c,
+0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x75, 0x4d, 0x67,
+0x63, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73,
+0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x73, 0x61, 0x3b, 0x4e, 0x65,
+0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x63, 0x73, 0xf6, 0x6e, 0x64,
+0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69,
+0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b,
+0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64,
+0x61, 0x67, 0x3b, 0x6c, 0xf6, 0x72, 0x64, 0x61, 0x67, 0x73, 0xf6, 0x6e,
+0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f, 0x6e, 0x73,
+0x3b, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf6,
+0x72, 0x53, 0x75, 0x6e, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0xe4,
+0x6e, 0x74, 0x69, 0x67, 0x3b, 0x5a, 0x69, 0x69, 0x73, 0x63, 0x68, 0x74,
+0x69, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75, 0x63, 0x68, 0x3b,
+0x44, 0x75, 0x6e, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x46, 0x72,
+0x69, 0x69, 0x74, 0x69, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68,
+0x74, 0x69, 0x67, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0xe4, 0x2e, 0x3b, 0x5a,
+0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46,
+0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x71a, 0x715, 0x712, 0x72b, 0x712, 0x710,
+0x3b, 0x72c, 0x72a, 0x71d, 0x722, 0x712, 0x72b, 0x712, 0x710, 0x3b, 0x72c, 0x720,
+0x72c, 0x712, 0x72b, 0x712, 0x710, 0x3b, 0x710, 0x72a, 0x712, 0x725, 0x712, 0x72b,
+0x712, 0x710, 0x3b, 0x71a, 0x721, 0x72b, 0x712, 0x72b, 0x712, 0x710, 0x3b, 0x725,
+0x72a, 0x718, 0x712, 0x72c, 0x710, 0x3b, 0x72b, 0x712, 0x72c, 0x710, 0x71a, 0x715,
+0x3b, 0x72c, 0x72a, 0x71d, 0x722, 0x3b, 0x72c, 0x720, 0x72c, 0x3b, 0x710, 0x72a,
+0x712, 0x725, 0x3b, 0x71a, 0x721, 0x72b, 0x3b, 0x725, 0x72a, 0x718, 0x3b, 0x72b,
+0x712, 0x72c, 0x710, 0x71a, 0x3b, 0x72c, 0x3b, 0x72c, 0x3b, 0x710, 0x3b, 0x71a,
+0x3b, 0x725, 0x3b, 0x72b, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30,
+0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b,
+0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b,
+0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62,
+0x2d30, 0x2d59, 0x61, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b, 0x61, 0x79, 0x6e,
+0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x61, 0x6b,
+0x1e5b, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73,
+0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x79, 0x61,
+0x73, 0x61, 0x73, 0x61, 0x3b, 0x61, 0x79, 0x6e, 0x3b, 0x61, 0x73, 0x69,
+0x3b, 0x61, 0x6b, 0x1e5b, 0x3b, 0x61, 0x6b, 0x77, 0x3b, 0x61, 0x73, 0x69,
+0x6d, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x49, 0x74, 0x75, 0x6b, 0x75, 0x20,
+0x6a, 0x61, 0x20, 0x6a, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x4b, 0x75, 0x72,
+0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6a, 0x69, 0x6d, 0x77, 0x65, 0x72,
+0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b,
+0x61, 0x77, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61,
+0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4b, 0x75, 0x72, 0x61,
+0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4b, 0x75,
+0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e,
+0x75, 0x3b, 0x4b, 0x69, 0x66, 0x75, 0x6c, 0x61, 0x20, 0x6e, 0x67, 0x75,
+0x77, 0x6f, 0x4a, 0x75, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x4b, 0x61,
+0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61,
+0x73, 0x3b, 0x4e, 0x67, 0x75, 0x4a, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4e, 0x42f, 0x43a, 0x448, 0x430, 0x43d, 0x431,
+0x435, 0x3b, 0x414, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x421, 0x435,
+0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x427, 0x43e, 0x440, 0x448, 0x430, 0x43d,
+0x431, 0x435, 0x3b, 0x41f, 0x430, 0x43d, 0x4b7, 0x448, 0x430, 0x43d, 0x431, 0x435,
+0x3b, 0x4b6, 0x443, 0x43c, 0x44a, 0x430, 0x3b, 0x428, 0x430, 0x43d, 0x431, 0x435,
+0x42f, 0x448, 0x431, 0x3b, 0x414, 0x448, 0x431, 0x3b, 0x421, 0x448, 0x431, 0x3b,
+0x427, 0x448, 0x431, 0x3b, 0x41f, 0x448, 0x431, 0x3b, 0x4b6, 0x43c, 0x44a, 0x3b,
+0x428, 0x43d, 0x431, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f,
+0x3b, 0x4b6, 0x3b, 0x428, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4,
+0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0xbb5,
+0xbbe, 0xbaf, 0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf,
+0xbaf, 0xbbe, 0xbb4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0xbb3, 0xbbf,
+0x3b, 0xb9a, 0xba9, 0xbbf, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0x2e, 0x3b, 0xba4, 0xbbf,
+0xb99, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0x2e, 0x3b, 0xbaa, 0xbc1,
+0xba4, 0x2e, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0x2e, 0x3b, 0xbb5, 0xbc6, 0xbb3,
+0xbcd, 0x2e, 0x3b, 0xb9a, 0xba9, 0xbbf, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b,
+0xb9a, 0xbc6, 0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5, 0xbbf, 0x3b, 0xbb5, 0xbc6, 0x3b,
+0xb9a, 0x4a, 0x69, 0x79, 0x61, 0x78, 0x20, 0x73, 0x6e, 0x67, 0x61, 0x79,
+0x61, 0x6e, 0x3b, 0x74, 0x67, 0x4b, 0x69, 0x6e, 0x67, 0x61, 0x6c, 0x20,
+0x6a, 0x69, 0x79, 0x61, 0x78, 0x20, 0x69, 0x79, 0x61, 0x78, 0x20, 0x73,
+0x6e, 0x67, 0x61, 0x79, 0x61, 0x6e, 0x3b, 0x74, 0x67, 0x44, 0x68, 0x61,
+0x20, 0x6a, 0x69, 0x79, 0x61, 0x78, 0x20, 0x69, 0x79, 0x61, 0x78, 0x20,
+0x73, 0x6e, 0x67, 0x61, 0x79, 0x61, 0x6e, 0x3b, 0x74, 0x67, 0x54, 0x72,
+0x75, 0x20, 0x6a, 0x69, 0x79, 0x61, 0x78, 0x20, 0x69, 0x79, 0x61, 0x78,
+0x20, 0x73, 0x6e, 0x67, 0x61, 0x79, 0x61, 0x6e, 0x3b, 0x74, 0x67, 0x53,
+0x70, 0x61, 0x63, 0x20, 0x6a, 0x69, 0x79, 0x61, 0x78, 0x20, 0x69, 0x79,
+0x61, 0x78, 0x20, 0x73, 0x6e, 0x67, 0x61, 0x79, 0x61, 0x6e, 0x3b, 0x74,
+0x67, 0x52, 0x69, 0x6d, 0x61, 0x20, 0x6a, 0x69, 0x79, 0x61, 0x78, 0x20,
+0x69, 0x79, 0x61, 0x78, 0x20, 0x73, 0x6e, 0x67, 0x61, 0x79, 0x61, 0x6e,
+0x3b, 0x74, 0x67, 0x4d, 0x61, 0x74, 0x61, 0x72, 0x75, 0x20, 0x6a, 0x69,
+0x79, 0x61, 0x78, 0x20, 0x69, 0x79, 0x61, 0x78, 0x20, 0x73, 0x6e, 0x67,
+0x61, 0x79, 0x61, 0x6e, 0x45, 0x6d, 0x70, 0x3b, 0x4b, 0x69, 0x6e, 0x3b,
+0x44, 0x68, 0x61, 0x3b, 0x54, 0x72, 0x75, 0x3b, 0x53, 0x70, 0x61, 0x3b,
+0x52, 0x69, 0x6d, 0x3b, 0x4d, 0x61, 0x74, 0x45, 0x3b, 0x4b, 0x3b, 0x44,
+0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4d, 0x44f, 0x43a, 0x448, 0x4d9,
+0x43c, 0x431, 0x435, 0x3b, 0x434, 0x4af, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b,
+0x441, 0x438, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x447, 0x4d9, 0x440, 0x448,
+0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x43f, 0x4d9, 0x43d, 0x497, 0x435, 0x448, 0x4d9,
+0x43c, 0x431, 0x435, 0x3b, 0x497, 0x43e, 0x43c, 0x433, 0x430, 0x3b, 0x448, 0x438,
+0x43c, 0x431, 0x4d9, 0x44f, 0x43a, 0x448, 0x2e, 0x3b, 0x434, 0x4af, 0x448, 0x2e,
+0x3b, 0x441, 0x438, 0x448, 0x2e, 0x3b, 0x447, 0x4d9, 0x440, 0x2e, 0x3b, 0x43f,
+0x4d9, 0x43d, 0x497, 0x2e, 0x3b, 0x497, 0x43e, 0x43c, 0x2e, 0x3b, 0x448, 0x438,
+0x43c, 0x2e, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b,
+0x496, 0x3b, 0x428, 0xc06, 0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38,
+0xc4b, 0xc2e, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0xc35,
+0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b,
+0xc17, 0xc41, 0xc30, 0xc41, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc41, 0xc15,
+0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc28, 0xc3f, 0xc35, 0xc3e,
+0xc30, 0xc02, 0xc06, 0xc26, 0xc3f, 0x3b, 0xc38, 0xc4b, 0xc2e, 0x3b, 0xc2e, 0xc02,
+0xc17, 0xc33, 0x3b, 0xc2c, 0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b,
+0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0x3b, 0xc36, 0xc28, 0xc3f, 0xc06, 0x3b, 0xc38,
+0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2c, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36, 0xc41,
+0x3b, 0xc36, 0x4e, 0x61, 0x6b, 0x61, 0x65, 0x6a, 0x75, 0x6d, 0x61, 0x3b,
+0x4e, 0x61, 0x6b, 0x61, 0x65, 0x62, 0x61, 0x72, 0x61, 0x73, 0x61, 0x3b,
+0x4e, 0x61, 0x6b, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x6b, 0x61,
+0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e, 0x67, 0x2019,
+0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x79, 0x3b,
+0x4e, 0x61, 0x6b, 0x61, 0x73, 0x61, 0x62, 0x69, 0x74, 0x69, 0x4a, 0x75,
+0x6d, 0x3b, 0x42, 0x61, 0x72, 0x3b, 0x41, 0x61, 0x72, 0x3b, 0x55, 0x6e,
+0x69, 0x3b, 0x55, 0x6e, 0x67, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x53, 0x61,
+0x62, 0x4a, 0x3b, 0x42, 0x3b, 0x41, 0x3b, 0x55, 0x3b, 0x55, 0x3b, 0x4b,
+0x3b, 0x53, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17, 0xe34, 0xe15, 0xe22, 0xe4c,
+0x3b, 0xe27, 0xe31, 0xe19, 0xe08, 0xe31, 0xe19, 0xe17, 0xe23, 0xe4c, 0x3b, 0xe27,
+0xe31, 0xe19, 0xe2d, 0xe31, 0xe07, 0xe04, 0xe32, 0xe23, 0x3b, 0xe27, 0xe31, 0xe19,
+0xe1e, 0xe38, 0xe18, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a,
+0xe1a, 0xe14, 0xe35, 0x3b, 0xe27, 0xe31, 0xe19, 0xe28, 0xe38, 0xe01, 0xe23, 0xe4c,
+0x3b, 0xe27, 0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23, 0xe4c, 0xe2d, 0xe32, 0x2e,
+0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24,
+0x2e, 0x3b, 0xe28, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe2d, 0xe32, 0x3b, 0xe08, 0x3b,
+0xe2d, 0x3b, 0xe1e, 0x3b, 0xe1e, 0xe24, 0x3b, 0xe28, 0x3b, 0xe2a, 0xf42, 0xf5f,
+0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72,
+0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63,
+0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74,
+0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b,
+0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a,
+0xf53, 0xf0b, 0xf54, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b,
+0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b,
+0xf56, 0xf74, 0xf0b, 0x3b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66,
+0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0xf49, 0xf72, 0x3b, 0xf5f, 0xfb3, 0x3b,
+0xf58, 0xf72, 0xf42, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b,
+0xf66, 0xf44, 0xf66, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x1230, 0x1295, 0x1260, 0x1275,
+0x20, 0x12d3, 0x1263, 0x12ed, 0x3b, 0x1230, 0x1296, 0x3b, 0x1273, 0x120b, 0x1238, 0x1296,
+0x3b, 0x12a3, 0x1228, 0x122d, 0x1263, 0x12d3, 0x3b, 0x12a8, 0x121a, 0x123d, 0x3b, 0x1305,
+0x121d, 0x12d3, 0x1275, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x20, 0x1295, 0x12a2, 0x123d,
+0x1230, 0x2f, 0x12d3, 0x3b, 0x1230, 0x1296, 0x3b, 0x1273, 0x120b, 0x1238, 0x3b, 0x12a3,
+0x1228, 0x122d, 0x3b, 0x12a8, 0x121a, 0x123d, 0x3b, 0x1305, 0x121d, 0x12d3, 0x3b, 0x1230,
+0x2f, 0x1295, 0x1230, 0x3b, 0x1230, 0x3b, 0x1273, 0x3b, 0x12a3, 0x3b, 0x12a8, 0x3b,
+0x1305, 0x3b, 0x1230, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b,
+0x1230, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1213, 0x1219, 0x1235, 0x3b,
+0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x1230, 0x1295, 0x3b, 0x1230, 0x1291,
+0x3b, 0x1230, 0x1209, 0x3b, 0x1228, 0x1261, 0x3b, 0x1213, 0x1219, 0x3b, 0x12d3, 0x122d,
+0x3b, 0x1240, 0x12f3, 0x1230, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1228, 0x3b, 0x1213,
+0x3b, 0x12d3, 0x3b, 0x1240, 0x53, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x61,
+0x6e, 0x64, 0x65, 0x3b, 0x54, 0x75, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x72,
+0x69, 0x6e, 0x64, 0x65, 0x3b, 0x46, 0x6f, 0x6e, 0x64, 0x65, 0x3b, 0x46,
+0x72, 0x61, 0x69, 0x64, 0x65, 0x3b, 0x53, 0x61, 0x72, 0x65, 0x72, 0x65,
+0x53, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x6e, 0x3b, 0x54, 0x75, 0x6e, 0x3b,
+0x54, 0x72, 0x69, 0x3b, 0x46, 0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b,
+0x53, 0x61, 0x72, 0x53, 0x101, 0x70, 0x61, 0x74, 0x65, 0x3b, 0x4d, 0x14d,
+0x6e, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x16b, 0x73, 0x69, 0x74, 0x65, 0x3b,
+0x50, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x54, 0x75, 0x2bb,
+0x61, 0x70, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x46, 0x61,
+0x6c, 0x61, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x6f, 0x6b, 0x6f, 0x6e, 0x61,
+0x6b, 0x69, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e, 0x3b, 0x54, 0x16b,
+0x73, 0x3b, 0x50, 0x75, 0x6c, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x3b, 0x46,
+0x61, 0x6c, 0x3b, 0x54, 0x6f, 0x6b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b,
+0x50, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x54, 0x53, 0x6f, 0x6e, 0x74, 0x61,
+0x3b, 0x4d, 0x75, 0x73, 0x75, 0x6d, 0x62, 0x68, 0x75, 0x6e, 0x75, 0x6b,
+0x75, 0x3b, 0x52, 0x61, 0x76, 0x75, 0x6d, 0x62, 0x69, 0x72, 0x68, 0x69,
+0x3b, 0x52, 0x61, 0x76, 0x75, 0x6e, 0x68, 0x61, 0x72, 0x68, 0x75, 0x3b,
+0x52, 0x61, 0x76, 0x75, 0x6d, 0x75, 0x6e, 0x65, 0x3b, 0x52, 0x61, 0x76,
+0x75, 0x6e, 0x74, 0x6c, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x75, 0x67,
+0x71, 0x69, 0x76, 0x65, 0x6c, 0x61, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x75,
+0x73, 0x3b, 0x42, 0x69, 0x72, 0x3b, 0x48, 0x61, 0x72, 0x3b, 0x4e, 0x65,
+0x3b, 0x54, 0x6c, 0x68, 0x3b, 0x4d, 0x75, 0x67, 0x54, 0x73, 0x68, 0x69,
+0x70, 0x69, 0x3b, 0x4d, 0x6f, 0x73, 0x6f, 0x70, 0x75, 0x6c, 0x6f, 0x67,
+0x6f, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x62, 0x65, 0x64, 0x69, 0x3b, 0x4c,
+0x61, 0x62, 0x6f, 0x72, 0x61, 0x72, 0x6f, 0x3b, 0x4c, 0x61, 0x62, 0x6f,
+0x6e, 0x65, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x74, 0x6c, 0x68, 0x61, 0x6e,
+0x6f, 0x3b, 0x4d, 0x61, 0x74, 0x6c, 0x68, 0x61, 0x74, 0x73, 0x6f, 0x54,
+0x73, 0x68, 0x3b, 0x4d, 0x6f, 0x73, 0x3b, 0x4c, 0x61, 0x62, 0x62, 0x3b,
+0x4c, 0x61, 0x62, 0x72, 0x3b, 0x4c, 0x61, 0x62, 0x6e, 0x3b, 0x4c, 0x61,
+0x62, 0x74, 0x3b, 0x4d, 0x61, 0x74, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x3b,
+0x50, 0x61, 0x7a, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x3b, 0x53, 0x61,
+0x6c, 0x131, 0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x61, 0x6d, 0x62, 0x61, 0x3b,
+0x50, 0x65, 0x72, 0x15f, 0x65, 0x6d, 0x62, 0x65, 0x3b, 0x43, 0x75, 0x6d,
+0x61, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x50,
+0x61, 0x7a, 0x3b, 0x50, 0x7a, 0x74, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0xc7,
+0x61, 0x72, 0x3b, 0x50, 0x65, 0x72, 0x3b, 0x43, 0x75, 0x6d, 0x3b, 0x43,
+0x6d, 0x74, 0x50, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b,
+0x43, 0x3b, 0x43, 0xdd, 0x65, 0x6b, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b,
+0x44, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x53, 0x69, 0x15f, 0x65,
+0x6e, 0x62, 0x65, 0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x65, 0x6e, 0x62, 0x65,
+0x3b, 0x50, 0x65, 0x6e, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x41, 0x6e,
+0x6e, 0x61, 0x3b, 0x15e, 0x65, 0x6e, 0x62, 0x65, 0xfd, 0x65, 0x6b, 0x15f,
+0x65, 0x6e, 0x62, 0x65, 0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65,
+0x3b, 0x73, 0x69, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0xe7, 0x61, 0x72,
+0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x70, 0x65, 0x6e, 0x15f, 0x65, 0x6e,
+0x62, 0x65, 0x3b, 0x61, 0x6e, 0x6e, 0x61, 0x3b, 0x15f, 0x65, 0x6e, 0x62,
+0x65, 0xdd, 0x65, 0x6b, 0x3b, 0x44, 0x75, 0x15f, 0x3b, 0x53, 0x69, 0x15f,
+0x3b, 0xc7, 0x61, 0x72, 0x3b, 0x50, 0x65, 0x6e, 0x3b, 0x41, 0x6e, 0x6e,
+0x3b, 0x15e, 0x65, 0x6e, 0xfd, 0x65, 0x6b, 0x3b, 0x64, 0x75, 0x15f, 0x3b,
+0x73, 0x69, 0x15f, 0x3b, 0xe7, 0x61, 0x72, 0x3b, 0x70, 0x65, 0x6e, 0x3b,
+0x61, 0x6e, 0x6e, 0x3b, 0x15f, 0x65, 0x6e, 0xdd, 0x3b, 0x44, 0x3b, 0x53,
+0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x15e, 0x4c, 0x61, 0x64, 0x69,
+0x3b, 0x54, 0x61, 0x6e, 0x69, 0x69, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74,
+0x61, 0x3b, 0x4c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x4c, 0x61, 0x6d, 0x69,
+0x74, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61,
+0x74, 0x4c, 0x61, 0x64, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x54, 0x61, 0x6c,
+0x3b, 0x4c, 0x61, 0x72, 0x3b, 0x4c, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d,
+0x3b, 0x41, 0x73, 0x61, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x43f,
+0x43e, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432,
+0x442, 0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x441, 0x435, 0x440, 0x435, 0x434, 0x430,
+0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x2bc, 0x44f, 0x442,
+0x43d, 0x438, 0x446, 0x44f, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x43d,
+0x435, 0x434, 0x456, 0x43b, 0x44e, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x456,
+0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432, 0x442, 0x43e, 0x440, 0x43e, 0x43a,
+0x3b, 0x441, 0x435, 0x440, 0x435, 0x434, 0x443, 0x3b, 0x447, 0x435, 0x442, 0x432,
+0x435, 0x440, 0x3b, 0x43f, 0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44e, 0x3b,
+0x441, 0x443, 0x431, 0x43e, 0x442, 0x443, 0x6e, 0x6a, 0x65, 0x64, 0x17a, 0x65,
+0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b,
+0x77, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x65, 0x64,
+0x61, 0x3b, 0x161, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b, 0x70, 0x6a,
+0x61, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x6a,
+0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x75, 0x74, 0x3b, 0x73, 0x72,
+0x6a, 0x3b, 0x161, 0x74, 0x77, 0x3b, 0x70, 0x6a, 0x61, 0x3b, 0x73, 0x6f,
+0x62, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70,
+0x3b, 0x73, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b,
+0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639,
+0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a,
+0x6c1, 0x64a, 0x6d5, 0x643, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62f, 0x6c8,
+0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x633, 0x6d5, 0x64a, 0x634, 0x6d5, 0x646,
+0x628, 0x6d5, 0x3b, 0x686, 0x627, 0x631, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b,
+0x67e, 0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62c, 0x6c8, 0x645,
+0x6d5, 0x3b, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x64a, 0x6d5, 0x3b, 0x62f, 0x6c8,
+0x3b, 0x633, 0x6d5, 0x3b, 0x686, 0x627, 0x3b, 0x67e, 0x6d5, 0x3b, 0x62c, 0x6c8,
+0x3b, 0x634, 0x6d5, 0x64a, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e,
+0x3b, 0x62c, 0x3b, 0x634, 0x79, 0x61, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x62,
+0x61, 0x3b, 0x64, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x73,
+0x65, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x63, 0x68, 0x6f, 0x72,
+0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x79, 0x73, 0x68,
+0x61, 0x6e, 0x62, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x68,
+0x61, 0x6e, 0x62, 0x61, 0x59, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0x73, 0x68,
+0x3b, 0x53, 0x65, 0x73, 0x68, 0x3b, 0x43, 0x68, 0x6f, 0x72, 0x3b, 0x50,
+0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x68, 0x61, 0x6e, 0x59,
+0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x4a, 0x3b, 0x53,
+0x6cc, 0x2e, 0x3b, 0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e, 0x3b,
+0x67e, 0x2e, 0x3b, 0x62c, 0x2e, 0x3b, 0x634, 0x2e, 0x44f, 0x43a, 0x448, 0x430,
+0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
+0x441, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448,
+0x430, 0x43d, 0x431, 0x430, 0x3b, 0x43f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431,
+0x430, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, 0x430,
+0x44f, 0x43a, 0x448, 0x3b, 0x434, 0x443, 0x448, 0x3b, 0x441, 0x435, 0x448, 0x3b,
+0x447, 0x43e, 0x440, 0x3b, 0x43f, 0x430, 0x439, 0x3b, 0x436, 0x443, 0x43c, 0x3b,
+0x448, 0x430, 0x43d, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f,
+0x3b, 0x416, 0x3b, 0x428, 0xa55e, 0xa54c, 0xa535, 0x3b, 0xa5f3, 0xa5e1, 0xa609, 0x3b,
+0xa55a, 0xa55e, 0xa55a, 0x3b, 0xa549, 0xa55e, 0xa552, 0x3b, 0xa549, 0xa524, 0xa546, 0xa562,
+0x3b, 0xa549, 0xa524, 0xa540, 0xa56e, 0x3b, 0xa53b, 0xa52c, 0xa533, 0x6c, 0x61, 0x68,
+0x61, 0x64, 0x69, 0x3b, 0x74, 0x25b, 0x25b, 0x6e, 0x25b, 0x25b, 0x3b, 0x74,
+0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x62, 0x61, 0x3b,
+0x61, 0x69, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x61, 0x69, 0x6a, 0x69, 0x6d,
+0x61, 0x3b, 0x73, 0x69, 0x253, 0x69, 0x74, 0x69, 0x53, 0x77, 0x6f, 0x6e,
+0x64, 0x61, 0x68, 0x61, 0x3b, 0x4d, 0x75, 0x73, 0x75, 0x6d, 0x62, 0x75,
+0x6c, 0x75, 0x77, 0x6f, 0x3b, 0x1e3c, 0x61, 0x76, 0x68, 0x75, 0x76, 0x68,
+0x69, 0x6c, 0x69, 0x3b, 0x1e3c, 0x61, 0x76, 0x68, 0x75, 0x72, 0x61, 0x72,
+0x75, 0x3b, 0x1e3c, 0x61, 0x76, 0x68, 0x75, 0x1e4b, 0x61, 0x3b, 0x1e3c, 0x61,
+0x76, 0x68, 0x75, 0x1e71, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x75, 0x67, 0x69,
+0x76, 0x68, 0x65, 0x6c, 0x61, 0x53, 0x77, 0x6f, 0x3b, 0x4d, 0x75, 0x73,
+0x3b, 0x56, 0x68, 0x69, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x1e4a, 0x61, 0x3b,
+0x1e70, 0x61, 0x6e, 0x3b, 0x4d, 0x75, 0x67, 0x43, 0x68, 0x1ee7, 0x20, 0x4e,
+0x68, 0x1ead, 0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x48, 0x61, 0x69, 0x3b,
+0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x61, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x54,
+0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x4e, 0x103, 0x6d, 0x3b, 0x54, 0x68,
+0x1ee9, 0x20, 0x53, 0xe1, 0x75, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x1ea3,
+0x79, 0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x20,
+0x33, 0x3b, 0x54, 0x68, 0x20, 0x34, 0x3b, 0x54, 0x68, 0x20, 0x35, 0x3b,
+0x54, 0x68, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x20, 0x37, 0x43, 0x4e, 0x3b,
+0x54, 0x32, 0x3b, 0x54, 0x33, 0x3b, 0x54, 0x34, 0x3b, 0x54, 0x35, 0x3b,
+0x54, 0x36, 0x3b, 0x54, 0x37, 0x73, 0x75, 0x64, 0x65, 0x6c, 0x3b, 0x6d,
+0x75, 0x64, 0x65, 0x6c, 0x3b, 0x74, 0x75, 0x64, 0x65, 0x6c, 0x3b, 0x76,
+0x65, 0x64, 0x65, 0x6c, 0x3b, 0x64, 0xf6, 0x64, 0x65, 0x6c, 0x3b, 0x66,
+0x72, 0x69, 0x64, 0x65, 0x6c, 0x3b, 0x7a, 0xe4, 0x64, 0x65, 0x6c, 0x53,
+0x75, 0x3b, 0x4d, 0x75, 0x3b, 0x54, 0x75, 0x3b, 0x56, 0x65, 0x3b, 0x44,
+0xf6, 0x3b, 0x46, 0x72, 0x3b, 0x5a, 0xe4, 0x73, 0x75, 0x2e, 0x3b, 0x6d,
+0x75, 0x2e, 0x3b, 0x74, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x2e, 0x3b, 0x64,
+0xf6, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x7a, 0xe4, 0x2e, 0x53, 0x3b,
+0x4d, 0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x5a, 0x53,
+0x75, 0x6e, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0xe4, 0x6e, 0x74, 0x61,
+0x67, 0x3b, 0x5a, 0x69, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74,
+0x74, 0x77, 0x75, 0x10d, 0x3b, 0x46, 0x72, 0xf3, 0x6e, 0x74, 0x61, 0x67,
+0x3b, 0x46, 0x72, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x161,
+0x74, 0x61, 0x67, 0x53, 0x75, 0x6e, 0x3b, 0x4d, 0xe4, 0x6e, 0x3b, 0x5a,
+0x69, 0x161, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x46, 0x72, 0xf3, 0x3b, 0x46,
+0x72, 0x69, 0x3b, 0x53, 0x61, 0x6d, 0x53, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b,
+0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x53, 0x44, 0x79, 0x64, 0x64, 0x20,
+0x53, 0x75, 0x6c, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4c, 0x6c, 0x75,
+0x6e, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74,
+0x68, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x65, 0x72, 0x63, 0x68,
+0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x49, 0x61, 0x75, 0x3b,
+0x44, 0x79, 0x64, 0x64, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b,
+0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x61, 0x64, 0x77, 0x72, 0x6e, 0x53,
+0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b,
+0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x3b,
+0x53, 0x61, 0x64, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b,
+0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b,
+0x47, 0x77, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x64, 0x53, 0x3b, 0x4c, 0x6c,
+0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53, 0x73, 0x6e,
+0x65, 0x69, 0x6e, 0x3b, 0x6d, 0x6f, 0x61, 0x6e, 0x64, 0x65, 0x69, 0x3b,
+0x74, 0x69, 0x69, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x77, 0x6f, 0x61, 0x6e,
+0x73, 0x64, 0x65, 0x69, 0x3b, 0x74, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x73,
+0x64, 0x65, 0x69, 0x3b, 0x66, 0x72, 0x65, 0x65, 0x64, 0x3b, 0x73, 0x6e,
+0x65, 0x6f, 0x6e, 0x73, 0x69, 0x3b, 0x6d, 0x6f, 0x3b, 0x74, 0x69, 0x3b,
+0x77, 0x6f, 0x3b, 0x74, 0x6f, 0x3b, 0x66, 0x72, 0x3b, 0x73, 0x6f, 0x12c8,
+0x130b, 0x3b, 0x1233, 0x12ed, 0x1296, 0x3b, 0x121b, 0x1246, 0x1233, 0x129b, 0x3b, 0x12a0,
+0x1229, 0x12cb, 0x3b, 0x1203, 0x1219, 0x1233, 0x3b, 0x12a0, 0x122d, 0x1263, 0x3b, 0x1244,
+0x122b, 0x12c8, 0x3b, 0x1233, 0x3b, 0x121b, 0x3b, 0x12a0, 0x3b, 0x1203, 0x3b, 0x12a0,
+0x3b, 0x1244, 0x44, 0x69, 0x62, 0xe9, 0x65, 0x72, 0x3b, 0x41, 0x6c, 0x74,
+0x69, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b,
+0xc0, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x78, 0x61, 0x6d,
+0x69, 0x73, 0x3b, 0xc0, 0x6a, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73,
+0x65, 0x65, 0x72, 0x44, 0x69, 0x62, 0x3b, 0x41, 0x6c, 0x74, 0x3b, 0x54,
+0x61, 0x6c, 0x3b, 0xc0, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x78, 0x3b, 0xc0,
+0x6a, 0x6a, 0x3b, 0x41, 0x73, 0x65, 0x43, 0x61, 0x77, 0x65, 0x3b, 0x4d,
+0x76, 0x75, 0x6c, 0x6f, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69,
+0x6e, 0x69, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74,
+0x68, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c,
+0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x67,
+0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x43, 0x61, 0x77, 0x3b, 0x4d, 0x76,
+0x75, 0x3b, 0x42, 0x69, 0x6e, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69,
+0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x43, 0x61, 0x77,
+0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x62, 0x3b, 0x54,
+0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d,
+0x67, 0x71, 0x43, 0x3b, 0x4d, 0x3b, 0x53, 0x62, 0x3b, 0x53, 0x74, 0x3b,
+0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x3b, 0x4d, 0x67, 0x71, 0x43, 0x3b,
+0x4d, 0x3b, 0x53, 0x62, 0x3b, 0x54, 0x68, 0x74, 0x3b, 0x53, 0x69, 0x6e,
+0x3b, 0x48, 0x6c, 0x3b, 0x4d, 0x67, 0x71, 0x73, 0x254, 0x301, 0x6e, 0x64,
+0x69, 0x25b, 0x3b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x75,
+0xe1, 0x6e, 0x79, 0xe1, 0x14b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b,
+0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0xed, 0xe1, 0x70, 0x25b, 0x3b, 0x6b,
+0xfa, 0x70, 0xe9, 0x6c, 0x69, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0x69,
+0x61, 0x70, 0x25b, 0x3b, 0x66, 0x65, 0x6c, 0xe9, 0x74, 0x65, 0x3b, 0x73,
+0xe9, 0x73, 0x65, 0x6c, 0xe9, 0x73, 0x64, 0x3b, 0x6d, 0x64, 0x3b, 0x6d,
+0x77, 0x3b, 0x65, 0x74, 0x3b, 0x6b, 0x6c, 0x3b, 0x66, 0x6c, 0x3b, 0x73,
+0x73, 0x73, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x6b, 0x3b, 0x66,
+0x3b, 0x73, 0x5d6, 0x5d5, 0x5e0, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5de, 0x5d0, 0x5b8,
+0x5e0, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5d3, 0x5d9, 0x5e0, 0x5e1, 0x5d8, 0x5d9, 0x5e7,
+0x3b, 0x5de, 0x5d9, 0x5d8, 0x5d5, 0x5d5, 0x5d0, 0x5da, 0x3b, 0x5d3, 0x5d0, 0x5e0,
+0x5e2, 0x5e8, 0x5e9, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5e4, 0x5bf, 0x5e8, 0x5f2, 0x5b7,
+0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0xc0, 0xec, 0x6b, 0xfa, 0x3b,
+0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b,
+0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62,
+0x1ecd, 0x3b, 0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301,
+0x74, 0x61, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b,
+0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd,
+0x301, 0x20, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a,
+0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b,
+0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc, 0x6a, 0x1ecd,
+0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0xc0, 0xec,
+0x6b, 0x3b, 0x41, 0x6a, 0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x3b, 0x1ecc,
+0x6a, 0x1ecd, 0x301, 0x72, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x3b, 0x1eb8,
+0x74, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0xc0, 0x3b, 0x41, 0x3b, 0xcc, 0x3b,
+0x1ecc, 0x3b, 0x1ecc, 0x3b, 0x1eb8, 0x3b, 0xc0, 0xc0, 0xec, 0x6b, 0xfa, 0x3b,
+0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b,
+0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62,
+0x254, 0x3b, 0x190, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301,
+0x74, 0x61, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b,
+0x186, 0x6a, 0x254, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x186, 0x6a, 0x254,
+0x301, 0x20, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x186, 0x6a,
+0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b,
+0x186, 0x6a, 0x254, 0x301, 0x20, 0x190, 0x74, 0xec, 0x3b, 0x186, 0x6a, 0x254,
+0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0xc0, 0xec,
+0x6b, 0x3b, 0x41, 0x6a, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x3b, 0x186,
+0x6a, 0x254, 0x301, 0x72, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x3b, 0x190,
+0x74, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0xc0, 0x3b, 0x41, 0x3b, 0xcc, 0x3b,
+0x186, 0x3b, 0x186, 0x3b, 0x190, 0x3b, 0xc0, 0x41, 0x6c, 0x68, 0x61, 0x64,
+0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61,
+0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61,
+0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x6c,
+0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x48,
+0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x53,
+0x6e, 0x67, 0x6f, 0x65, 0x6e, 0x7a, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67,
+0x69, 0x7a, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67, 0x69, 0x7a, 0x69,
+0x74, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67, 0x69, 0x7a, 0x6e, 0x67,
+0x65, 0x69, 0x68, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67, 0x69, 0x7a,
+0x73, 0x61, 0x6d, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67, 0x69, 0x7a,
+0x73, 0x65, 0x69, 0x71, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67, 0x69,
+0x7a, 0x68, 0x61, 0x6a, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x68, 0x67, 0x69,
+0x7a, 0x72, 0x6f, 0x65, 0x6b, 0x49, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b,
+0x55, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b,
+0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x55,
+0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b,
+0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x55, 0x4c, 0x77,
+0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x55, 0x4d, 0x67,
+0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73,
+0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69,
+0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x53, 0x3b, 0x4d,
+0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b, 0x4d, 0x6e, 0x75,
+0x6d, 0x129, 0x67, 0x67, 0x75, 0x3b, 0x70, 0x69, 0x72, 0x2d, 0x6b, 0x75,
+0x72, 0xe3, 0x2d, 0x68, 0xe1, 0x3b, 0x72, 0xe9, 0x67, 0x72, 0x65, 0x2d,
+0x6b, 0x75, 0x72, 0xe3, 0x2d, 0x68, 0xe1, 0x3b, 0x74, 0x1ebd, 0x67, 0x74,
+0x169, 0x2d, 0x6b, 0x75, 0x72, 0xe3, 0x2d, 0x68, 0xe1, 0x3b, 0x76, 0x1ebd,
+0x6e, 0x68, 0x6b, 0xe3, 0x67, 0x72, 0x61, 0x2d, 0x6b, 0x75, 0x72, 0xe3,
+0x2d, 0x68, 0xe1, 0x3b, 0x70, 0xe9, 0x6e, 0x6b, 0x61, 0x72, 0x2d, 0x6b,
+0x75, 0x72, 0xe3, 0x2d, 0x68, 0xe1, 0x3b, 0x73, 0x61, 0x76, 0x6e, 0x75,
+0x6e, 0x75, 0x6d, 0x2e, 0x3b, 0x70, 0x69, 0x72, 0x2e, 0x3b, 0x72, 0xe9,
+0x67, 0x2e, 0x3b, 0x74, 0x1ebd, 0x67, 0x2e, 0x3b, 0x76, 0x1ebd, 0x6e, 0x2e,
+0x3b, 0x70, 0xe9, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x76, 0x2e, 0x4e, 0x2e,
+0x3b, 0x50, 0x2e, 0x3b, 0x52, 0x2e, 0x3b, 0x54, 0x2e, 0x3b, 0x56, 0x2e,
+0x3b, 0x50, 0x2e, 0x3b, 0x53, 0x2e, 0x6d, 0x69, 0x74, 0x75, 0xfa, 0x3b,
+0x6d, 0x75, 0x72, 0x61, 0x6b, 0x69, 0x70, 0xed, 0x3b, 0x6d, 0x75, 0x72,
+0x61, 0x6b, 0xed, 0x2d, 0x6d, 0x75, 0x6b, 0x169, 0x69, 0x3b, 0x6d, 0x75,
+0x72, 0x61, 0x6b, 0xed, 0x2d, 0x6d, 0x75, 0x73, 0x61, 0x70, 0xed, 0x72,
+0x69, 0x3b, 0x73, 0x75, 0x70, 0x61, 0x70, 0xe1, 0x3b, 0x79, 0x75, 0x6b,
+0x75, 0x61, 0x6b, 0xfa, 0x3b, 0x73, 0x61, 0x75, 0x72, 0xfa, 0x6d, 0x69,
+0x74, 0x3b, 0x6d, 0x75, 0x72, 0x3b, 0x6d, 0x6d, 0x6b, 0x3b, 0x6d, 0x6d,
+0x73, 0x3b, 0x73, 0x75, 0x70, 0x3b, 0x79, 0x75, 0x6b, 0x3b, 0x73, 0x61,
+0x75, 0x4d, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x59,
+0x3b, 0x53, 0x910, 0x924, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935,
+0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c,
+0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x943, 0x939, 0x938, 0x94d, 0x92a,
+0x924, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e,
+0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x53, 0xf6, 0x6e, 0x64,
+0x61, 0x69, 0x3b, 0x4d, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x3b, 0x54, 0x65,
+0x69, 0x73, 0x64, 0x61, 0x69, 0x3b, 0x57, 0x65, 0x65, 0x64, 0x65, 0x6e,
+0x73, 0x64, 0x61, 0x69, 0x3b, 0x54, 0xfc, 0xfc, 0x72, 0x73, 0x64, 0x61,
+0x69, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x64, 0x61, 0x69, 0x3b, 0x53, 0x61,
+0x6e, 0x69, 0x6e, 0x6a, 0x53, 0xf6, 0x6e, 0x3b, 0x4d, 0x75, 0x6e, 0x3b,
+0x54, 0x65, 0x69, 0x3b, 0x57, 0x65, 0x64, 0x3b, 0x54, 0xfc, 0x72, 0x3b,
+0x46, 0x72, 0x65, 0x3b, 0x53, 0x61, 0x6e, 0x73, 0x75, 0x6e, 0x6f, 0x20,
+0x65, 0x73, 0x75, 0x6e, 0x20, 0x23, 0x37, 0x3b, 0x73, 0x75, 0x6e, 0x6f,
+0x20, 0x65, 0x73, 0x75, 0x6e, 0x20, 0x23, 0x31, 0x3b, 0x73, 0x75, 0x6e,
+0x6f, 0x20, 0x65, 0x73, 0x75, 0x6e, 0x20, 0x23, 0x32, 0x3b, 0x73, 0x75,
+0x6e, 0x6f, 0x20, 0x65, 0x73, 0x75, 0x6e, 0x20, 0x23, 0x33, 0x3b, 0x73,
+0x75, 0x6e, 0x6f, 0x20, 0x65, 0x73, 0x75, 0x6e, 0x20, 0x23, 0x34, 0x3b,
+0x73, 0x75, 0x6e, 0x6f, 0x20, 0x65, 0x73, 0x75, 0x6e, 0x20, 0x23, 0x35,
+0x3b, 0x73, 0x75, 0x6e, 0x6f, 0x20, 0x65, 0x73, 0x75, 0x6e, 0x20, 0x23,
+0x36, 0x53, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x61, 0x6e, 0x64, 0x65,
+0x3b, 0x54, 0x69, 0x75, 0x73, 0x64, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65,
+0x73, 0x64, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x64, 0x65, 0x3b, 0x46, 0x72,
+0x61, 0x65, 0x64, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x61, 0x64, 0x65, 0x6cc,
+0x6a9, 0x634, 0x645, 0x628, 0x647, 0x3b, 0x62f, 0x648, 0x634, 0x645, 0x628, 0x647,
+0x3b, 0x633, 0x626, 0x6cc, 0x634, 0x645, 0x628, 0x647, 0x3b, 0x686, 0x627, 0x631,
+0x634, 0x645, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x686, 0x634, 0x645, 0x628, 0x647,
+0x3b, 0x62c, 0x645, 0x647, 0x3b, 0x634, 0x645, 0x628, 0x647, 0x6cc, 0x6a9, 0x3b,
+0x62f, 0x648, 0x3b, 0x633, 0x626, 0x6d2, 0x3b, 0x686, 0x627, 0x631, 0x3b, 0x67e,
+0x646, 0x686, 0x3b, 0x62c, 0x645, 0x647, 0x3b, 0x634, 0x645, 0x59, 0x61, 0x6b,
+0x73, 0x68, 0x61, 0x6d, 0x62, 0x65, 0x68, 0x3b, 0x44, 0x6f, 0x73, 0x68,
+0x61, 0x6d, 0x62, 0x65, 0x68, 0x3b, 0x53, 0x61, 0x79, 0x73, 0x68, 0x61,
+0x6d, 0x62, 0x65, 0x68, 0x3b, 0x43, 0x68, 0xe1, 0x72, 0x73, 0x68, 0x61,
+0x6d, 0x62, 0x65, 0x68, 0x3b, 0x50, 0x61, 0x6e, 0x63, 0x68, 0x73, 0x68,
+0x61, 0x6d, 0x62, 0x65, 0x68, 0x3b, 0x4a, 0x6f, 0x6d, 0x61, 0x68, 0x3b,
+0x53, 0x68, 0x61, 0x6d, 0x62, 0x65, 0x68, 0x59, 0x61, 0x6b, 0x3b, 0x44,
+0x6f, 0x3b, 0x53, 0x61, 0x79, 0x3b, 0x43, 0x68, 0xe1, 0x3b, 0x50, 0x61,
+0x6e, 0x3b, 0x4a, 0x6f, 0x6d, 0x3b, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x6d,
+0x65, 0x6e, 0x65, 0x67, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x64,
+0xec, 0x3b, 0x6d, 0xe4, 0x74, 0x65, 0x73, 0x64, 0xec, 0x3b, 0x6d, 0xe4,
+0x63, 0x6f, 0x72, 0x64, 0xec, 0x3b, 0x7a, 0x65, 0x75, 0x67, 0x67, 0x69,
+0x61, 0x3b, 0x76, 0x65, 0x6e, 0x61, 0x72, 0x64, 0xec, 0x3b, 0x73, 0x61,
+0x62, 0x62, 0x6f, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e,
+0x3b, 0x6d, 0xe4, 0x74, 0x2e, 0x3b, 0x6d, 0xe4, 0x63, 0x2e, 0x3b, 0x7a,
+0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x62,
+0x2e, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x56,
+0x3b, 0x53, 0x627, 0x6cc, 0x6a9, 0x634, 0x6cc, 0x645, 0x6d2, 0x3b, 0x62f, 0x64f,
+0x648, 0x634, 0x6cc, 0x645, 0x6d2, 0x3b, 0x6af, 0x6be, 0x646, 0x20, 0x622, 0x646,
+0x6af, 0x627, 0x3b, 0x686, 0x627, 0x631, 0x634, 0x6cc, 0x645, 0x6d2, 0x3b, 0x67e,
+0x64e, 0x626, 0x20, 0x634, 0x6cc, 0x645, 0x6d2, 0x3b, 0x634, 0x64f, 0x648, 0x6af,
+0x627, 0x631, 0x3b, 0x644, 0x64e, 0x648, 0x20, 0x622, 0x646, 0x6af, 0x627, 0x627,
+0x3b, 0x62f, 0x3b, 0x6af, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x634, 0x3b, 0x644,
+0x61, 0x6c, 0x61, 0x68, 0x61, 0x256, 0x269, 0x3b, 0x61, 0x256, 0x269, 0x74,
+0x25b, 0x6e, 0x25b, 0x25b, 0x3b, 0x61, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74,
+0x61, 0x3b, 0x61, 0x6c, 0x61, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x61, 0x6c,
+0x61, 0x61, 0x6d, 0x269, 0x73, 0x68, 0x269, 0x3b, 0x61, 0x72, 0x269, 0x73,
+0x1dd, 0x6d, 0x61, 0x3b, 0x61, 0x73, 0x69, 0x69, 0x62, 0x69, 0x61, 0x6c,
+0x61, 0x68, 0x3b, 0x61, 0x256, 0x269, 0x74, 0x3b, 0x61, 0x74, 0x61, 0x6c,
+0x3b, 0x61, 0x6c, 0x61, 0x72, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x3b, 0x61,
+0x72, 0x269, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x62, 0x6c, 0x68, 0x3b, 0x256,
+0x74, 0x3b, 0x74, 0x6c, 0x3b, 0x6c, 0x72, 0x3b, 0x6c, 0x6d, 0x3b, 0x72,
+0x73, 0x3b, 0x73, 0x62, 0x924, 0x94b, 0x906, 0x930, 0x3b, 0x938, 0x94b, 0x906,
+0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941,
+0x927, 0x935, 0x93e, 0x930, 0x3b, 0x935, 0x940, 0x930, 0x935, 0x93e, 0x930, 0x3b,
+0x936, 0x941, 0x915, 0x94d, 0x915, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928,
+0x93f, 0x91a, 0x94d, 0x91a, 0x930, 0x935, 0x93e, 0x930, 0x924, 0x94b, 0x906, 0x930,
+0x3b, 0x938, 0x94b, 0x906, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c,
+0x941, 0x927, 0x3b, 0x935, 0x940, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x915,
+0x930, 0x3b, 0x936, 0x928, 0x93f, 0x924, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902,
+0x3b, 0x92c, 0x941, 0x3b, 0x935, 0x940, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x64,
+0x6f, 0x6d, 0xe9, 0x6e, 0x65, 0x67, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x69,
+0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x3b, 0x6d, 0xe8, 0x72, 0x63, 0x6f,
+0x72, 0x65, 0x3b, 0x7a, 0x6f, 0x62, 0x61, 0x3b, 0x76, 0xe8, 0x6e, 0x61,
+0x72, 0x65, 0x3b, 0x73, 0x61, 0x62, 0x6f, 0x64, 0x6f, 0x6d, 0x3b, 0x6c,
+0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x7a,
+0x6f, 0x62, 0x3b, 0x76, 0xe8, 0x6e, 0x3b, 0x73, 0x61, 0x62
};
-static const char16_t byte_unit_data[] = {
-0x62, 0x79, 0x74, 0x65, 0x73, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b,
-0x45, 0x42, 0x4b, 0x69, 0x42, 0x3b, 0x4d, 0x69, 0x42, 0x3b, 0x47, 0x69, 0x42, 0x3b, 0x54, 0x69, 0x42, 0x3b, 0x50, 0x69,
-0x42, 0x3b, 0x45, 0x69, 0x42, 0x67, 0x72, 0x65, 0x65, 0x70, 0x62, 0x61, 0x6a, 0x74, 0x1263, 0x12ed, 0x1275, 0x12aa, 0x1263, 0x3b,
-0x121c, 0x130b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x130a, 0x1263, 0x3b, 0x1274, 0x122b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x1354, 0x1263, 0x3b, 0x45, 0x42,
-0x628, 0x627, 0x64a, 0x62a, 0x643, 0x64a, 0x644, 0x648, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x645, 0x64a, 0x63a, 0x627, 0x628, 0x627, 0x64a,
-0x62a, 0x3b, 0x63a, 0x64a, 0x63a, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x62a, 0x64a, 0x631, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b,
-0x628, 0x64a, 0x62a, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x45, 0x42, 0x562, 0x561, 0x575, 0x569, 0x565, 0x580, 0x56f, 0x532, 0x3b,
-0x544, 0x532, 0x3b, 0x533, 0x532, 0x3b, 0x54f, 0x532, 0x3b, 0x54a, 0x532, 0x3b, 0x45, 0x42, 0x9ac, 0x9be, 0x987, 0x99f, 0x995, 0x9bf,
-0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x9ae, 0x9c7, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x997, 0x9bf, 0x983, 0x20, 0x9ac, 0x9be,
-0x983, 0x3b, 0x99f, 0x9c7, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x61, 0x79, 0x74, 0x62,
-0x79, 0x74, 0x65, 0x2d, 0x61, 0x6b, 0x6f, 0x6b, 0x74, 0x65, 0x64, 0x6f, 0xf9, 0x6b, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x47,
-0x6f, 0x3b, 0x54, 0x6f, 0x3b, 0x50, 0x6f, 0x3b, 0x45, 0x6f, 0x4b, 0x69, 0x6f, 0x3b, 0x4d, 0x69, 0x6f, 0x3b, 0x47, 0x69,
-0x6f, 0x3b, 0x54, 0x69, 0x6f, 0x3b, 0x50, 0x69, 0x6f, 0x3b, 0x45, 0x69, 0x6f, 0x431, 0x430, 0x439, 0x442, 0x43e, 0x432, 0x435,
-0x1018, 0x102d, 0x102f, 0x1000, 0x103a, 0x431, 0x430, 0x439, 0x442, 0x44b, 0x41a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422,
-0x411, 0x3b, 0x41f, 0x411, 0x3b, 0x45, 0x42, 0x1794, 0x17c3, 0x5b57, 0x8282, 0x5343, 0x5b57, 0x8282, 0x3b, 0x5146, 0x5b57, 0x8282, 0x3b, 0x5409,
-0x5b57, 0x8282, 0x3b, 0x592a, 0x5b57, 0x8282, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x4f4d, 0x5143, 0x7d44, 0x62, 0x61, 0x6a, 0x74, 0x6f,
-0x76, 0x69, 0x62, 0x61, 0x6a, 0x74, 0x79, 0x62, 0x61, 0x6a, 0x74, 0x6f, 0x6a, 0x62, 0x61, 0x69, 0x64, 0x69, 0x64, 0x62,
-0xfd, 0x74, 0x74, 0x61, 0x76, 0x75, 0x74, 0x6b, 0x74, 0x3b, 0x4d, 0x74, 0x3b, 0x47, 0x74, 0x3b, 0x54, 0x74, 0x3b, 0x50,
-0x74, 0x3b, 0x45, 0x74, 0x4b, 0x69, 0x74, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x47, 0x69, 0x74, 0x3b, 0x54, 0x69, 0x74, 0x3b,
-0x50, 0x69, 0x74, 0x3b, 0x45, 0x69, 0x74, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x73, 0x62, 0x61, 0x69, 0x64, 0x68, 0x74, 0x10d1,
-0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x10d9, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10db, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10d2, 0x10d1,
-0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10e2, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10de, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x45,
-0x42, 0x42, 0x79, 0x74, 0x65, 0x73, 0xaac, 0xabe, 0xa87, 0xa9f, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54,
-0x42, 0x3b, 0xaaa, 0xac0, 0xaac, 0xac0, 0x3b, 0x45, 0x42, 0x5d1, 0x5d9, 0x5d9, 0x5d8, 0x92c, 0x93e, 0x907, 0x91f, 0x62, 0xe1, 0x6a,
-0x74, 0x62, 0xe6, 0x74, 0x69, 0x62, 0x65, 0x61, 0x72, 0x74, 0x61, 0x30d0, 0x30a4, 0x30c8, 0x4b, 0x42, 0x3b, 0x4d, 0x42, 0x3b,
-0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x69, 0x74, 0x65, 0xcac, 0xcc8, 0xc9f, 0xccd, 0x200c,
-0xc97, 0xcb3, 0xcc1, 0xc95, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcae, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc97, 0xcbf, 0x2e,
-0xcac, 0xcc8, 0x2e, 0x3b, 0xc9f, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcaa, 0xcc6, 0xcac, 0xcc8, 0x3b, 0x45, 0x42, 0x43a, 0x411,
-0x3b, 0x4d, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x54, 0x411, 0x3b, 0x41f, 0x411, 0x3b, 0x45, 0x411, 0x4b, 0x69, 0x411, 0x3b, 0x4d,
-0x69, 0x411, 0x3b, 0x47, 0x69, 0x411, 0x3b, 0x54, 0x69, 0x411, 0x3b, 0x50, 0x69, 0x411, 0x3b, 0x45, 0x69, 0x411, 0x43a, 0x411,
-0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b, 0x41f, 0x442, 0x431, 0x3b, 0x45, 0x42, 0xbc14, 0xc774, 0xd2b8, 0x62,
-0x61, 0x69, 0x74, 0x69, 0x62, 0x61, 0x69, 0x74, 0x61, 0x69, 0x431, 0x430, 0x458, 0x442, 0x438, 0xd2c, 0xd48, 0xd31, 0xd4d, 0xd31,
-0xd4d, 0xd15, 0xd46, 0xd2c, 0xd3f, 0x3b, 0xd0e, 0xd02, 0xd2c, 0xd3f, 0x3b, 0xd1c, 0xd3f, 0xd2c, 0xd3f, 0x3b, 0xd1f, 0xd3f, 0xd2c, 0xd3f,
-0x3b, 0xd2a, 0xd3f, 0xd2c, 0xd3f, 0x3b, 0x45, 0x42, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b,
-0x41f, 0x411, 0x3b, 0x45, 0x42, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x92a, 0x93f, 0x91f,
-0x93e, 0x3b, 0x45, 0x42, 0xb2c, 0xb3e, 0xb07, 0xb1f, 0xb4d, 0x628, 0x627, 0x64a, 0x67c, 0x633, 0x628, 0x627, 0x6cc, 0x62a, 0x6a9, 0x6cc,
-0x644, 0x648, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x645, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628,
-0x627, 0x6cc, 0x62a, 0x3b, 0x62a, 0x631, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x67e, 0x62a, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b,
-0x45, 0x42, 0xa2c, 0xa3e, 0xa07, 0xa1f, 0x62, 0x79, 0x21b, 0x69, 0x431, 0x430, 0x458, 0x442, 0x43e, 0x432, 0x438, 0x628, 0x627, 0x626,
-0x64a, 0x67d, 0x632, 0x6aa, 0x644, 0x648, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x645, 0x64a, 0x6af, 0x627, 0x20, 0x628,
-0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x6af, 0x64a, 0x6af, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x67d, 0x64a,
-0x631, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x67e, 0x64a, 0x631, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d,
-0x633, 0x3b, 0x45, 0x42, 0xdb6, 0xdba, 0xdd2, 0xda7, 0xdca, 0xd9a, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xdb8, 0xdd9, 0xdb6,
-0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xd9c, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xda7, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d,
-0x3b, 0xdb4, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x42, 0x62, 0x65, 0x79, 0x74, 0x69, 0x73, 0x6b, 0x42, 0x3b,
-0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x42, 0x42, 0x3b, 0x45, 0x42, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x61,
-0x69, 0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x7b, 0x30,
-0x7d, 0x3b, 0x74, 0x65, 0x72, 0x61, 0x62, 0x61, 0x69, 0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20, 0x7b,
-0x30, 0x7d, 0x3b, 0x45, 0x42, 0xbaa, 0xbc8, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0xc2c, 0xc48, 0xc1f, 0xc4d, 0x200c, 0xc32, 0xc41, 0xc15,
-0xc47, 0xc2c, 0xc40, 0x3b, 0xc0e, 0xc2e, 0xc4d, 0x200c, 0xc2c, 0xc3f, 0x3b, 0xc1c, 0xc40, 0xc2c, 0xc40, 0x3b, 0xc1f, 0xc40, 0xc2c, 0xc40,
-0x3b, 0xc2a, 0xc40, 0xc2c, 0xc40, 0x3b, 0x45, 0x42, 0xe44, 0xe1a, 0xe15, 0xe4c, 0x70, 0x61, 0x69, 0x74, 0x69, 0x6b, 0x42, 0x20,
-0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20,
-0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20,
-0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x4b, 0x69, 0x42, 0x20,
-0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x69,
-0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b,
-0x50, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
-0x7d, 0x62, 0x61, 0xfd, 0x74, 0x431, 0x430, 0x439, 0x442, 0x438, 0x628, 0x627, 0x626, 0x679, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b,
-0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x67e, 0x6cc, 0x20, 0x628, 0x6cc, 0x3b, 0x45, 0x42, 0x62, 0x65, 0x69, 0x74, 0x69, 0x61,
-0x75, 0x92c, 0x93e, 0x92f, 0x91f, 0x61, 0x1e6d, 0x61, 0x6d, 0x1e0d, 0x61, 0x6e, 0x6b, 0x41, 0x1e6c, 0x3b, 0x4d, 0x41, 0x1e6c, 0x3b,
-0x47, 0x41, 0x1e6c, 0x3b, 0x54, 0x41, 0x1e6c, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x13d7, 0x13d3, 0x13cd, 0x13a6, 0x13b5, 0x13a9, 0x431,
-0x430, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45,
-0x42, 0xd804, 0xdd1d, 0xd804, 0xdd2d, 0xd804, 0xdd16, 0xd804, 0xdd34, 0x62, 0x79, 0x74, 0x65, 0x79, 0x6a9, 0x6cc, 0x644, 0x648, 0x628, 0x627,
-0x6cc, 0x62a, 0x3b, 0x645, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b,
-0x62a, 0x631, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x6d, 0x67, 0x61, 0x20, 0x62, 0x79, 0x74,
-0x65
+static constexpr char16_t byte_unit_data[] = {
+0x62, 0x79, 0x74, 0x65, 0x73, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47,
+0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x4b, 0x69,
+0x42, 0x3b, 0x4d, 0x69, 0x42, 0x3b, 0x47, 0x69, 0x42, 0x3b, 0x54, 0x69,
+0x42, 0x3b, 0x50, 0x69, 0x42, 0x3b, 0x45, 0x69, 0x42, 0x67, 0x72, 0x65,
+0x65, 0x70, 0x62, 0x61, 0x6a, 0x74, 0x1263, 0x12ed, 0x1275, 0x12aa, 0x1263, 0x3b,
+0x121c, 0x130b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x130a, 0x1263, 0x3b, 0x1274, 0x122b, 0x1263,
+0x12ed, 0x1275, 0x3b, 0x1354, 0x1263, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x64a, 0x62a,
+0x643, 0x64a, 0x644, 0x648, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x645, 0x2e, 0x628,
+0x3b, 0x63a, 0x2e, 0x628, 0x3b, 0x62a, 0x64a, 0x631, 0x627, 0x628, 0x627, 0x64a,
+0x62a, 0x3b, 0x628, 0x64a, 0x62a, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x45,
+0x42, 0x562, 0x561, 0x575, 0x569, 0x565, 0x580, 0x56f, 0x532, 0x3b, 0x544, 0x532,
+0x3b, 0x533, 0x532, 0x3b, 0x54f, 0x532, 0x3b, 0x54a, 0x532, 0x3b, 0x45, 0x42,
+0x9ac, 0x9be, 0x987, 0x99f, 0x995, 0x9bf, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b,
+0x9ae, 0x9c7, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x997, 0x9bf, 0x983, 0x20,
+0x9ac, 0x9be, 0x983, 0x3b, 0x99f, 0x9c7, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b,
+0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x61, 0x79, 0x74, 0x62, 0x79, 0x74,
+0x65, 0x2d, 0x61, 0x6b, 0x431, 0x430, 0x439, 0x442, 0x44b, 0x41a, 0x411, 0x3b,
+0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b, 0x41f, 0x411, 0x3b,
+0x45, 0x42, 0x62, 0x61, 0x6a, 0x74, 0x6f, 0x76, 0x69, 0x6f, 0x6b, 0x74,
+0x65, 0x64, 0x6f, 0xf9, 0x6b, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x47, 0x6f,
+0x3b, 0x54, 0x6f, 0x3b, 0x50, 0x6f, 0x3b, 0x45, 0x6f, 0x4b, 0x69, 0x6f,
+0x3b, 0x4d, 0x69, 0x6f, 0x3b, 0x47, 0x69, 0x6f, 0x3b, 0x54, 0x69, 0x6f,
+0x3b, 0x50, 0x69, 0x6f, 0x3b, 0x45, 0x69, 0x6f, 0x431, 0x430, 0x439, 0x442,
+0x43e, 0x432, 0x435, 0x1018, 0x102d, 0x102f, 0x1000, 0x103a, 0x6d, 0x67, 0x61, 0x20,
+0x62, 0x79, 0x74, 0x65, 0xd804, 0xdd1d, 0xd804, 0xdd2d, 0xd804, 0xdd16, 0xd804, 0xdd34,
+0x13d7, 0x13d3, 0x13cd, 0x13a6, 0x13b5, 0x13a9, 0x5b57, 0x8282, 0x4f4d, 0x5143, 0x7d44, 0x62,
+0x61, 0x6a, 0x74, 0x79, 0x62, 0x61, 0x6a, 0x74, 0x6f, 0x6a, 0x62, 0x61,
+0x69, 0x64, 0x69, 0x64, 0x62, 0xfd, 0x74, 0x74, 0x61, 0x76, 0x75, 0x74,
+0x6b, 0x74, 0x3b, 0x4d, 0x74, 0x3b, 0x47, 0x74, 0x3b, 0x54, 0x74, 0x3b,
+0x50, 0x74, 0x3b, 0x45, 0x74, 0x4b, 0x69, 0x74, 0x3b, 0x4d, 0x69, 0x74,
+0x3b, 0x47, 0x69, 0x74, 0x3b, 0x54, 0x69, 0x74, 0x3b, 0x50, 0x69, 0x74,
+0x3b, 0x45, 0x69, 0x74, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x73, 0xd83a, 0xdd36,
+0xd83a, 0xdd2b, 0xd83a, 0xdd45, 0xd83a, 0xdd3c, 0xd83a, 0xdd46, 0xd83a, 0xdd2d, 0xd83a, 0xdd33,
+0xd83a, 0xdd14, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd14, 0x3b, 0xd83a, 0xdd18, 0xd83a, 0xdd14,
+0x3b, 0xd83a, 0xdd1a, 0xd83a, 0xdd14, 0x3b, 0xd83a, 0xdd06, 0xd83a, 0xdd14, 0x3b, 0x45,
+0x42, 0x62, 0x61, 0x69, 0x64, 0x68, 0x74, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8,
+0x10d9, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42,
+0x3b, 0x10e2, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10de, 0x10d1, 0x10d0, 0x10d8,
+0x10e2, 0x10d8, 0x3b, 0x45, 0x42, 0x42, 0x79, 0x74, 0x65, 0x73, 0xaac, 0xabe,
+0xa87, 0xa9f, 0x6b, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x42, 0x20,
+0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54,
+0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20, 0x7b, 0x30, 0x7d,
+0x3b, 0x45, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x4b, 0x69, 0x42, 0x20, 0x7b,
+0x30, 0x7d, 0x3b, 0x4d, 0x69, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47,
+0x69, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x69, 0x42, 0x20, 0x7b,
+0x30, 0x7d, 0x3b, 0x50, 0x69, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45,
+0x69, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x5d1, 0x5d9, 0x5d9, 0x5d8, 0x92c, 0x93e,
+0x907, 0x91f, 0x62, 0xe1, 0x6a, 0x74, 0x62, 0xe6, 0x74, 0x69, 0x6f, 0x63,
+0x74, 0x65, 0x74, 0x65, 0x73, 0x62, 0x65, 0x61, 0x72, 0x74, 0x61, 0x30d0,
+0x30a4, 0x30c8, 0x4b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54,
+0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x69, 0x74, 0x65, 0x61,
+0x1e6d, 0x61, 0x6d, 0x1e0d, 0x61, 0x6e, 0x6b, 0x41, 0x1e6c, 0x3b, 0x4d, 0x41,
+0x1e6c, 0x3b, 0x47, 0x41, 0x1e6c, 0x3b, 0x54, 0x41, 0x1e6c, 0x3b, 0x50, 0x42,
+0x3b, 0x45, 0x42, 0xcac, 0xcc8, 0xc9f, 0xccd, 0x200c, 0xc97, 0xcb3, 0xcc1, 0xc95,
+0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcae, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e,
+0x3b, 0xc97, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc9f, 0xcc6, 0x2e, 0xcac,
+0xcc8, 0x2e, 0x3b, 0xcaa, 0xcc6, 0xcac, 0xcc8, 0x3b, 0x45, 0x42, 0x43a, 0x411,
+0x3b, 0x4d, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x54, 0x411, 0x3b, 0x41f, 0x411,
+0x3b, 0x45, 0x411, 0x4b, 0x69, 0x411, 0x3b, 0x4d, 0x69, 0x411, 0x3b, 0x47,
+0x69, 0x411, 0x3b, 0x54, 0x69, 0x411, 0x3b, 0x50, 0x69, 0x411, 0x3b, 0x45,
+0x69, 0x411, 0x1794, 0x17c3, 0x92c, 0x93e, 0x92f, 0x91f, 0xbc14, 0xc774, 0xd2b8, 0x43a,
+0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b, 0x41f,
+0x442, 0x431, 0x3b, 0x45, 0x42, 0x62, 0x61, 0x69, 0x74, 0x69, 0x62, 0x61,
+0x69, 0x74, 0x61, 0x69, 0x431, 0x430, 0x458, 0x442, 0x438, 0xd2c, 0xd48, 0xd31,
+0xd4d, 0xd31, 0xd4d, 0xd15, 0xd46, 0xd2c, 0xd3f, 0x3b, 0xd0e, 0xd02, 0xd2c, 0xd3f,
+0x3b, 0xd1c, 0xd3f, 0xd2c, 0xd3f, 0x3b, 0xd1f, 0xd3f, 0xd2c, 0xd3f, 0x3b, 0xd2a,
+0xd3f, 0xd2c, 0xd3f, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x6cc, 0x62a, 0x6a9, 0x6cc,
+0x644, 0x648, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x645, 0x6af, 0x627, 0x628, 0x627,
+0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b,
+0x62a, 0x631, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45,
+0x42, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411,
+0x3b, 0x41f, 0x411, 0x3b, 0x45, 0x42, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b,
+0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x92a, 0x93f, 0x91f, 0x93e, 0x3b, 0x45,
+0x42, 0x42, 0x61, 0x69, 0x74, 0x2d, 0x64, 0x1eb9, 0x6d, 0xb2c, 0xb3e, 0xb07,
+0xb1f, 0xb4d, 0x628, 0x627, 0x64a, 0x67c, 0x633, 0xa2c, 0xa3e, 0xa07, 0xa1f, 0x62,
+0x79, 0x21b, 0x69, 0x431, 0x430, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x41c,
+0x411, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45,
+0x42, 0x431, 0x430, 0x458, 0x442, 0x43e, 0x432, 0x438, 0x628, 0x627, 0x626, 0x64a,
+0x67d, 0x632, 0x6aa, 0x644, 0x648, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632,
+0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42,
+0x3b, 0x45, 0x42, 0xdb6, 0xdba, 0xdd2, 0xda7, 0xdca, 0xd9a, 0xdd2, 0xdb6, 0x20,
+0x7b, 0x30, 0x7d, 0x3b, 0xdb8, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b,
+0xd9c, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xda7, 0xdd9, 0xdb6, 0x20,
+0x7b, 0x30, 0x7d, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b,
+0x45, 0x42, 0x62, 0x65, 0x79, 0x74, 0x69, 0x73, 0x6b, 0x42, 0x3b, 0x4d,
+0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x42, 0x42, 0x3b, 0x45,
+0x42, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x61, 0x69, 0x74, 0x69, 0x20, 0x7b,
+0x30, 0x7d, 0x3b, 0x4d, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42,
+0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x74, 0x65, 0x72, 0x61, 0x62, 0x61, 0x69,
+0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20, 0x7b, 0x30,
+0x7d, 0x3b, 0x45, 0x42, 0x712, 0x710, 0x71d, 0x72c, 0xbaa, 0xbc8, 0xb9f, 0xbcd,
+0xb95, 0xbb3, 0xbcd, 0xc2c, 0xc48, 0xc1f, 0xc4d, 0x200c, 0xc32, 0xc41, 0xc15, 0xc47,
+0xc2c, 0xc40, 0x3b, 0xc0e, 0xc2e, 0xc4d, 0x200c, 0xc2c, 0xc3f, 0x3b, 0xc1c, 0xc40,
+0xc2c, 0xc40, 0x3b, 0xc1f, 0xc40, 0xc2c, 0xc40, 0x3b, 0xc2a, 0xc40, 0xc2c, 0xc40,
+0x3b, 0x45, 0x42, 0xe44, 0xe1a, 0xe15, 0xe4c, 0x70, 0x61, 0x69, 0x74, 0x69,
+0x6b, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x42,
+0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x2bb,
+0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x42, 0x20, 0x2bb, 0x65, 0x20,
+0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
+0x7d, 0x3b, 0x45, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x4b,
+0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x69,
+0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x69, 0x42,
+0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x69, 0x42, 0x20,
+0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x69, 0x42, 0x20, 0x2bb,
+0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x69, 0x42, 0x20, 0x2bb, 0x65,
+0x20, 0x7b, 0x30, 0x7d, 0x62, 0x61, 0xfd, 0x74, 0x431, 0x430, 0x439, 0x442,
+0x438, 0x62, 0x79, 0x74, 0x65, 0x79, 0x628, 0x627, 0x626, 0x679, 0x6b, 0x42,
+0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x67e, 0x6cc,
+0x20, 0x628, 0x6cc, 0x3b, 0x45, 0x42, 0x62, 0x65, 0x69, 0x74, 0x69, 0x61,
+0x75, 0xe0, 0x77, 0x1ecd, 0x301, 0x6e, 0x20, 0x62, 0xe1, 0xec, 0x74, 0xec,
+0x6b, 0xe9, 0x62, 0xe1, 0xec, 0x74, 0xec, 0x3b, 0x4d, 0x42, 0x3b, 0x6a,
+0xed, 0x62, 0xe1, 0xec, 0x74, 0xec, 0x3b, 0x54, 0xed, 0x62, 0xe1, 0xec,
+0x74, 0xec, 0x3b, 0x50, 0xed, 0x62, 0xe1, 0xec, 0x74, 0xec, 0x3b, 0x45,
+0x42, 0xe0, 0x77, 0x254, 0x301, 0x6e, 0x20, 0x62, 0xe1, 0xec, 0x74, 0xec,
+0x62, 0x79, 0x74, 0x65, 0x20, 0x61, 0x67, 0x62, 0x79, 0x74, 0x65, 0x2d,
+0x69, 0x74, 0x61
};
-static const char16_t am_data[] = {
-0x41, 0x4d, 0x57, 0x44, 0x76, 0x6d, 0x2e, 0x65, 0x20, 0x70, 0x61, 0x72, 0x61, 0x64, 0x69, 0x74, 0x65, 0x73, 0x1325, 0x12cb,
-0x1275, 0x635, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a8, 0x410, 0x41c, 0xf66, 0xf94, 0xf0b, 0xf46, 0xf0b, 0x41, 0x2e,
-0x4d, 0x2e, 0x43f, 0x440, 0x2e, 0x43e, 0x431, 0x2e, 0x1014, 0x1036, 0x1014, 0x1000, 0x103a, 0x61, 0x2e, 0xa0, 0x6d, 0x2e, 0x4e0a, 0x5348,
-0x64, 0x6f, 0x70, 0x2e, 0x61, 0x2e, 0x6d, 0x2e, 0x61, 0x6d, 0x61, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x6d, 0x61, 0x74, 0x69,
-0x6e, 0x3c0, 0x2e, 0x3bc, 0x2e, 0x53, 0x61, 0x66, 0x69, 0x79, 0x61, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4, 0x5e6, 0x64, 0x65, 0x2e,
-0x66, 0x2e, 0x68, 0x2e, 0x72, 0x2e, 0x6e, 0x2e, 0x5348, 0x524d, 0x49, 0x73, 0x75, 0x6b, 0xcaa, 0xcc2, 0xcb0, 0xccd, 0xcb5, 0xcbe,
-0xcb9, 0xccd, 0xca8, 0x442, 0x430, 0x4a3, 0x43a, 0x44b, 0xc624, 0xc804, 0x42, 0x4e, 0x5a, 0x2e, 0x4d, 0x55, 0x2e, 0xe81, 0xec8, 0xead,
-0xe99, 0xe97, 0xec8, 0xebd, 0xe87, 0x70, 0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6e,
-0x74, 0x254, 0x301, 0x6e, 0x67, 0x254, 0x301, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440, 0x435, 0x442,
-0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50, 0x47, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x4af, 0x2e, 0x4e9, 0x2e, 0x92a, 0x942, 0x930,
-0x94d, 0x935, 0x93e, 0x939, 0x94d, 0x928, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c, 0x627, 0x632, 0x638, 0x647, 0x631, 0x64,
-0x61, 0x20, 0x6d, 0x61, 0x6e, 0x68, 0xe3, 0xa2a, 0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f,
-0x43e, 0x434, 0x43d, 0x435, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x70, 0x72, 0x65, 0x20, 0x70,
-0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x440, 0x438, 0x458, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x4d5, 0x43c, 0x431, 0x438, 0x441,
-0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430, 0x437, 0x43c, 0x4d5, 0x635, 0x628, 0x62d, 0x60c, 0x20, 0x645, 0x646, 0x62c, 0x647, 0x646,
-0x62f, 0xdb4, 0xdd9, 0x2e, 0xdc0, 0x2e, 0x47, 0x48, 0x66, 0x6d, 0xbae, 0xbc1, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe01, 0xe48,
-0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x1295, 0x1309, 0x1206, 0x20, 0x1230,
-0x12d3, 0x1270, 0x68, 0x65, 0x6e, 0x67, 0x69, 0x68, 0x65, 0x6e, 0x67, 0x69, 0xd6, 0xd6, 0x67, 0xfc, 0x6e, 0x6f, 0x72, 0x74,
-0x61, 0x64, 0x61, 0x6e, 0x20, 0xf6, 0x148, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20, 0x628, 0x6c7, 0x631, 0x6c7, 0x646, 0x434,
-0x43f, 0x54, 0x4f, 0x422, 0x41e, 0x53, 0x41, 0x79, 0x62, 0x53, 0x75, 0x62, 0x5e4, 0x5bf, 0x5d0, 0x5b7, 0x5e8, 0x5de, 0x5d9, 0x5d8,
-0x5d0, 0x5b8, 0x5d2, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0xc0, 0xe1, 0x72, 0x254, 0x300, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x64, 0x64,
-0x61, 0x67, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x41, 0x4e, 0x4e, 0x2019, 0x1ee5, 0x74, 0x1ee5, 0x74,
-0x1ee5, 0x128, 0x79, 0x61, 0x6b, 0x77, 0x61, 0x6b, 0x79, 0x61, 0x14b, 0x64, 0x69, 0x61, 0x6d, 0x20, 0x56, 0x6f, 0x72, 0x6d,
-0x69, 0x74, 0x74, 0x61, 0x67, 0xa3b8, 0xa111, 0x69, 0x111, 0x69, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x69, 0x62,
-0x4d, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x4c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x4b, 0x73, 0x75, 0x62, 0x61,
-0x6b, 0x61, 0x4b, 0x69, 0x72, 0x6f, 0x6b, 0x6f, 0x54, 0x65, 0x73, 0x69, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x6e, 0x67, 0x2019,
-0x61, 0x6d, 0x61, 0x2d5c, 0x2d49, 0x2d3c, 0x2d30, 0x2d61, 0x2d5c, 0x74, 0x69, 0x66, 0x61, 0x77, 0x74, 0x6e, 0x20, 0x74, 0x75, 0x66,
-0x61, 0x74, 0x70, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x75, 0x75, 0x74, 0x75, 0x6b, 0x6f, 0x4b, 0x49, 0x13cc, 0x13be, 0x13b4, 0x4d,
-0x75, 0x68, 0x69, 0x54, 0x4f, 0x4f, 0x75, 0x6c, 0x75, 0x63, 0x68, 0x65, 0x6c, 0x6f, 0x52, 0x168, 0x6b, 0x61, 0x72, 0x6f,
-0x6f, 0x6e, 0x1c1, 0x67, 0x6f, 0x61, 0x67, 0x61, 0x73, 0x55, 0x68, 0x72, 0x20, 0x76, 0xf6, 0x72, 0x6d, 0x69, 0x64, 0x64,
-0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x6b, 0x61, 0x6b, 0x25b, 0x6e, 0x79, 0xe1, 0x4d, 0x75, 0x6e, 0x6b, 0x79, 0x6f,
-0x69, 0x63, 0x68, 0x65, 0x68, 0x65, 0x61, 0x76, 0x6f, 0x54, 0x61, 0x70, 0x61, 0x72, 0x61, 0x63, 0x68, 0x75, 0x41, 0x64,
-0x64, 0x75, 0x68, 0x61, 0x4f, 0x44, 0x5a, 0x64, 0x61, 0x74, 0x20, 0x61, 0x7a, 0x61, 0x6c, 0x6d, 0x61, 0x6b, 0x65, 0x6f,
-0x92b, 0x941, 0x902, 0x44, 0x69, 0x6e, 0x64, 0x61, 0x6d, 0x6f, 0x69, 0x65, 0x73, 0x61, 0x2e, 0x67, 0x49, 0x20, 0x62, 0x69,
-0x6b, 0x25b, 0x302, 0x67, 0x6c, 0xe0, 0x53, 0x75, 0x62, 0x62, 0x61, 0x61, 0x68, 0x69, 0x69, 0x64, 0x69, 0x253, 0x61, 0x6b,
-0xed, 0x6b, 0xed, 0x72, 0xed, 0x67, 0x73, 0xe1, 0x72, 0xfa, 0x77, 0xe1, 0x77, 0x69, 0x63, 0x68, 0x69, 0x73, 0x68, 0x75,
-0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6d, 0x61, 0x6e, 0xe1, 0x52, 0x57, 0x42d, 0x418, 0x4c, 0x77, 0x61, 0x6d, 0x69, 0x6c, 0x61,
-0x77, 0x75, 0x6b, 0x69, 0x25b, 0x6d, 0x25b, 0x301, 0x25b, 0x6d, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x6d, 0x61, 0xf1, 0x61,
-0x6e, 0x61, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61, 0x2bc, 0xe1, 0x6d, 0x62, 0x61, 0x2bc, 0x628,
-0x2e, 0x646, 0x64, 0x6f, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x69, 0x70, 0x2e
+static constexpr char16_t am_data[] = {
+0x41, 0x4d, 0x76, 0x6d, 0x2e, 0x61, 0x2e, 0x67, 0x41, 0x4e, 0x65, 0x20,
+0x70, 0x61, 0x72, 0x61, 0x64, 0x69, 0x74, 0x65, 0x73, 0x1325, 0x12cb, 0x1275,
+0x635, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a8, 0x64, 0x65,
+0x20, 0x6c, 0x61, 0x20, 0x6d, 0x61, 0xf1, 0x61, 0x6e, 0x61, 0x69, 0x63,
+0x68, 0x65, 0x68, 0x65, 0x61, 0x76, 0x6f, 0x410, 0x41c, 0x73, 0xe1, 0x72,
+0xfa, 0x77, 0xe1, 0x49, 0x20, 0x62, 0x69, 0x6b, 0x25b, 0x302, 0x67, 0x6c,
+0xe0, 0x75, 0x6c, 0x75, 0x63, 0x68, 0x65, 0x6c, 0x6f, 0x70, 0x61, 0x6d,
+0x69, 0x6c, 0x61, 0x75, 0x92d, 0x94b, 0x930, 0x92b, 0x941, 0x902, 0x70, 0x72,
+0x69, 0x6a, 0x65, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x440, 0x438, 0x458,
+0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x41, 0x2e, 0x4d, 0x2e, 0x43f,
+0x440, 0x2e, 0x43e, 0x431, 0x2e, 0x1014, 0x1036, 0x1014, 0x1000, 0x103a, 0x4e0a, 0x5348,
+0x61, 0x2e, 0xa0, 0x6d, 0x2e, 0x5a, 0x64, 0x61, 0x74, 0x20, 0x61, 0x7a,
+0x61, 0x6c, 0x628, 0x2e, 0x646, 0x13cc, 0x13be, 0x13b4, 0x55, 0x68, 0x72, 0x20,
+0x76, 0xf6, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73,
+0x61, 0x2e, 0x6d, 0x2e, 0x64, 0x6f, 0x70, 0x2e, 0x938, 0x935, 0x947, 0x930,
+0x69, 0x64, 0x69, 0x253, 0x61, 0xf66, 0xf94, 0xf0b, 0xf46, 0xf0b, 0x4b, 0x49,
+0xd801, 0xdc08, 0xd801, 0xdc23, 0xd801, 0xdc68, 0xd801, 0xdc65, 0x61, 0x74, 0x6d, 0x14b,
+0x64, 0x69, 0x6b, 0xed, 0x6b, 0xed, 0x72, 0xed, 0x67, 0x61, 0x70, 0x2e,
+0x6d, 0x61, 0x74, 0x69, 0x6e, 0x73, 0x75, 0x62, 0x61, 0x6b, 0x61, 0xd83a,
+0xdd00, 0xd83a, 0xdd0e, 0x3c0, 0x2e, 0x3bc, 0x2e, 0x4d, 0x61, 0x6d, 0x62, 0x69,
+0x61, 0x53, 0x61, 0x66, 0x69, 0x79, 0x61, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4,
+0x5e6, 0x64, 0x65, 0x2e, 0x66, 0x2e, 0x68, 0x2e, 0x4e, 0x2019, 0x1ee5, 0x74,
+0x1ee5, 0x74, 0x1ee5, 0x69, 0x70, 0x2e, 0x61, 0x6e, 0x74, 0x65, 0x20, 0x6d,
+0x69, 0x64, 0xed, 0x72, 0x2e, 0x6e, 0x2e, 0x5348, 0x524d, 0x49, 0x73, 0x75,
+0x6b, 0x6e, 0x20, 0x74, 0x75, 0x66, 0x61, 0x74, 0x6b, 0x61, 0x72, 0x6f,
+0x6f, 0x6e, 0x128, 0x79, 0x61, 0x6b, 0x77, 0x61, 0x6b, 0x79, 0x61, 0xcaa,
+0xcc2, 0xcb0, 0xccd, 0xcb5, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x627, 0x6d2, 0x20, 0x627,
+0x6cc, 0x645, 0x92f, 0x947, 0x20, 0x90f, 0x92e, 0x4b, 0x69, 0x72, 0x6f, 0x6b,
+0x6f, 0x938, 0x915, 0x93e, 0x933, 0xc624, 0xc804, 0x41, 0x64, 0x64, 0x75, 0x68,
+0x61, 0x42, 0x4e, 0x6d, 0x61, 0x6e, 0xe1, 0x442, 0x430, 0x4a3, 0x43a, 0x44b,
+0x54, 0x4f, 0x4f, 0xe81, 0xec8, 0xead, 0xe99, 0xe97, 0xec8, 0xebd, 0xe87, 0x70,
+0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e,
+0x101, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x67, 0x254, 0x301, 0x70, 0x72, 0x69,
+0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x64, 0x6f, 0x70, 0x6f, 0x142, 0x64,
+0x6e, 0x6a, 0x61, 0x44, 0x69, 0x6e, 0x64, 0x61, 0x4f, 0x44, 0x6d, 0x6f,
+0x69, 0x65, 0x73, 0x43f, 0x440, 0x435, 0x442, 0x43f, 0x43b, 0x2e, 0x75, 0x74,
+0x75, 0x6b, 0x6f, 0x77, 0x69, 0x63, 0x68, 0x69, 0x73, 0x68, 0x75, 0x4d,
+0x75, 0x68, 0x69, 0x50, 0x47, 0x98f, 0x20, 0x98f, 0x9ae, 0x190, 0x6e, 0x6b,
+0x61, 0x6b, 0x25b, 0x6e, 0x79, 0xe1, 0x52, 0x168, 0x4af, 0x2e, 0x4e9, 0x2e,
+0x1826, 0x1802, 0x20, 0x1825, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x1c1, 0x67, 0x6f,
+0x61, 0x67, 0x61, 0x73, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e, 0x939, 0x94d,
+0x928, 0x6d, 0x62, 0x61, 0x2bc, 0xe1, 0x6d, 0x62, 0x61, 0x2bc, 0x6d, 0x62,
+0x61, 0xa78c, 0x6d, 0x62, 0x61, 0xa78c, 0x46, 0x1ecd, 0x20, 0x6d, 0x1ecd, 0x301,
+0x6e, 0x69, 0x6e, 0x7db, 0x69, 0x111, 0x69, 0x74, 0x62, 0x65, 0x61, 0x69,
+0x76, 0x65, 0x74, 0x69, 0x62, 0x66, 0x2e, 0x6d, 0x2e, 0x52, 0x57, 0x57,
+0x44, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440,
+0x430, 0x437, 0x43c, 0x4d5, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c,
+0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x68,
+0xe3, 0x61, 0x6e, 0x6b, 0x73, 0x74, 0x101, 0x69, 0x6e, 0x61, 0x6e, 0xa2a,
+0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x6b, 0x61, 0x6e, 0x67, 0x2019, 0x61, 0x6d,
+0x61, 0x5a, 0x2e, 0x4d, 0x55, 0x2e, 0x42d, 0x418, 0x54, 0x65, 0x73, 0x69,
+0x72, 0x61, 0x6e, 0x4e, 0x44, 0x4c, 0x77, 0x61, 0x6d, 0x69, 0x6c, 0x61,
+0x77, 0x75, 0x1c65, 0x1c6e, 0x1c5b, 0x1c5f, 0x1c5c, 0x70, 0x72, 0x69, 0x6a, 0x65,
+0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x6d, 0x61, 0x6b, 0x65, 0x6f, 0xa3b8,
+0xa111, 0x64, 0x6f, 0x20, 0x70, 0x6f, 0x142, 0x65, 0x64, 0x6e, 0x69, 0x14f,
+0x635, 0x628, 0x62d, 0x60c, 0x20, 0x645, 0x646, 0x62c, 0x647, 0x646, 0x62f, 0x938,
+0x941, 0x92c, 0x941, 0x939, 0x20, 0x91c, 0x93e, 0xdb4, 0xdd9, 0x2e, 0xdc0, 0x2e,
+0x4d, 0x75, 0x6e, 0x6b, 0x79, 0x6f, 0x47, 0x48, 0x2d5c, 0x2d49, 0x2d3c, 0x2d30,
+0x2d61, 0x2d5c, 0x66, 0x6d, 0x61, 0x6d, 0x20, 0x56, 0x6f, 0x72, 0x6d, 0x69,
+0x74, 0x74, 0x61, 0x67, 0x70f, 0x729, 0x71b, 0x200c, 0x74, 0x69, 0x66, 0x61,
+0x77, 0x74, 0x4c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x4b,
+0x53, 0x75, 0x62, 0x62, 0x61, 0x61, 0x68, 0x69, 0x54, 0x61, 0x70, 0x61,
+0x72, 0x61, 0x63, 0x68, 0x75, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35,
+0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x1245, 0x2e,
+0x1240, 0x2e, 0x68, 0x65, 0x6e, 0x67, 0x69, 0x68, 0x65, 0x6e, 0x67, 0x69,
+0xd6, 0xd6, 0x67, 0xfc, 0x6e, 0x6f, 0x72, 0x74, 0x61, 0x64, 0x61, 0x6e,
+0x20, 0xf6, 0x148, 0x434, 0x43f, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20,
+0x628, 0x6c7, 0x631, 0x6c7, 0x646, 0x422, 0x41e, 0x53, 0x41, 0x79, 0x62, 0x6b,
+0x69, 0x25b, 0x6d, 0x25b, 0x301, 0x25b, 0x6d, 0x5e4, 0x5bf, 0x5d0, 0x5b7, 0x5e8,
+0x5de, 0x5d9, 0x5d8, 0x5d0, 0x5b8, 0x5d2, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0xc0,
+0xe1, 0x72, 0x254, 0x300, 0x62, 0x61, 0x6e, 0x68, 0x61, 0x65, 0x74, 0x924,
+0x921, 0x915, 0x947, 0x938, 0x92c, 0x947, 0x930, 0x947, 0x70, 0x69, 0x20, 0x6f,
+0x70, 0x65, 0x6e, 0x20, 0x73, 0x75, 0x6e, 0x6f, 0x28a, 0x73, 0x68, 0x69,
+0x6c, 0xe8, 0x20, 0x6b, 0x28a, 0x62, 0x6f, 0x256, 0x75, 0x92d, 0x94d, 0x92f,
+0x93e, 0x917, 0x93e
};
-static const char16_t pm_data[] = {
-0x50, 0x4d, 0x57, 0x42, 0x6e, 0x6d, 0x2e, 0x65, 0x20, 0x70, 0x61, 0x73, 0x64, 0x69, 0x74, 0x65, 0x73, 0x12a8, 0x1230, 0x12d3,
-0x1275, 0x645, 0x985, 0x9aa, 0x9f0, 0x9be, 0x9b9, 0x9cd, 0x9a8, 0x41f, 0x41c, 0xf55, 0xfb1, 0xf72, 0xf0b, 0xf46, 0xf0b, 0x47, 0x2e, 0x4d,
-0x2e, 0x441, 0x43b, 0x2e, 0x43e, 0x431, 0x2e, 0x100a, 0x1014, 0x1031, 0x70, 0x2e, 0xa0, 0x6d, 0x2e, 0x4e0b, 0x5348, 0x6f, 0x64, 0x70,
-0x2e, 0x70, 0x2e, 0x6d, 0x2e, 0x70, 0x6d, 0x70, 0x74, 0x6d, 0x69, 0x70, 0x2e, 0x73, 0x6f, 0x69, 0x72, 0x66, 0x3bc, 0x2e,
-0x3bc, 0x2e, 0x59, 0x61, 0x6d, 0x6d, 0x61, 0x5d0, 0x5d7, 0x5d4, 0x5f4, 0x5e6, 0x64, 0x75, 0x2e, 0x65, 0x2e, 0x68, 0x2e, 0x69,
-0x2e, 0x6e, 0x2e, 0x5348, 0x5f8c, 0x57, 0x65, 0x6e, 0x67, 0x69, 0xc85, 0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442, 0x4af, 0x448,
-0x442, 0x4e9, 0x43d, 0x20, 0x43a, 0x438, 0x439, 0x438, 0x43d, 0x43a, 0x438, 0xc624, 0xd6c4, 0x50, 0x4e, 0x5a, 0x2e, 0x4d, 0x57, 0x2e,
-0xeab, 0xebc, 0xeb1, 0xe87, 0xe97, 0xec8, 0xebd, 0xe87, 0x70, 0x113, 0x63, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6d,
-0x70, 0xf3, 0x6b, 0x77, 0x61, 0x70, 0x6f, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x43e, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50,
-0x54, 0x47, 0x92e, 0x2e, 0x909, 0x2e, 0x4af, 0x2e, 0x445, 0x2e, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x63a, 0x2e, 0x648,
-0x2e, 0x628, 0x639, 0x62f, 0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0xa2c, 0xa3e, 0x2e,
-0xa26, 0xa41, 0x2e, 0x4c, 0x4b, 0x43f, 0x43e, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x6f, 0x20, 0x70, 0x6f, 0x64, 0x6e,
-0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x444, 0x4d5, 0x441, 0x442, 0x4d5, 0x645, 0x646, 0x62c, 0x647,
-0x646, 0x62f, 0x60c, 0x20, 0x634, 0x627, 0x645, 0xdb4, 0x2e, 0xdc0, 0x2e, 0x70, 0x6f, 0x70, 0x2e, 0x47, 0x44, 0x65, 0x6d, 0xbaa,
-0xbbf, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe2b, 0xe25, 0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf55, 0xfb1, 0xf72,
-0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x12f5, 0x1215, 0x122d, 0x20, 0x1230, 0x12d3, 0x1275, 0x65, 0x66, 0x69, 0x61, 0x66, 0x69, 0xd6, 0x53,
-0x67, 0xfc, 0x6e, 0x6f, 0x72, 0x74, 0x61, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x6f, 0x148, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646,
-0x20, 0x643, 0x6d0, 0x64a, 0x649, 0x646, 0x43f, 0x43f, 0x54, 0x4b, 0x422, 0x41a, 0x43, 0x48, 0x79, 0x68, 0x4e, 0x67, 0x6f, 0x5e0,
-0x5d0, 0x5b8, 0x5db, 0x5de, 0x5d9, 0x5d8, 0x5d0, 0x5b8, 0x5d2, 0x1ecc, 0x300, 0x73, 0xe1, 0x6e, 0x186, 0x300, 0x73, 0xe1, 0x6e, 0x65,
-0x74, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67, 0x70, 0x6f, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x43e, 0x441,
-0x43b, 0x438, 0x458, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x45, 0x57, 0x4e, 0x2019, 0x61, 0x62, 0x61, 0x6c, 0x69, 0x128,
-0x79, 0x61, 0x77, 0x129, 0x6f, 0x6f, 0x263, 0x65, 0x74, 0x72, 0x254, 0x61, 0x6d, 0x20, 0x4e, 0x61, 0x6d, 0x69, 0x74, 0x74,
-0x61, 0x67, 0xa06f, 0xa2d2, 0x65, 0x61, 0x68, 0x6b, 0x65, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x65, 0x62, 0x4d,
-0x6f, 0x67, 0x6c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x70, 0x6b, 0x69, 0x6b, 0x69, 0x69, 0x257, 0x65, 0x48,
-0x77, 0x61, 0x129, 0x2d, 0x69, 0x6e, 0x129, 0x54, 0x65, 0x69, 0x70, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x74, 0x6f, 0x2d5c,
-0x2d30, 0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c, 0x74, 0x61, 0x64, 0x67, 0x67, 0x2b7, 0x61, 0x74, 0x6e, 0x20, 0x74, 0x6d, 0x65,
-0x64, 0x64, 0x69, 0x74, 0x70, 0x61, 0x6d, 0x75, 0x6e, 0x79, 0x69, 0x6b, 0x79, 0x69, 0x75, 0x6b, 0x6f, 0x6e, 0x79, 0x69,
-0x55, 0x54, 0x13d2, 0x13af, 0x13f1, 0x13a2, 0x13d7, 0x13e2, 0x43, 0x68, 0x69, 0x6c, 0x6f, 0x4d, 0x55, 0x55, 0x61, 0x6b, 0x61, 0x73,
-0x75, 0x62, 0x61, 0x168, 0x47, 0x6b, 0x6f, 0x6f, 0x73, 0x6b, 0x6f, 0x6c, 0x69, 0x6e, 0x79, 0x1c3, 0x75, 0x69, 0x61, 0x73,
-0x55, 0x68, 0x72, 0x20, 0x6e, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x64, 0xe1,
-0x6d, 0xe2, 0x45, 0x69, 0x67, 0x75, 0x6c, 0x6f, 0x69, 0x63, 0x68, 0x61, 0x6d, 0x74, 0x68, 0x69, 0x45, 0x62, 0x6f, 0x6e,
-0x67, 0x69, 0x41, 0x6c, 0x75, 0x75, 0x6c, 0x61, 0x4f, 0x54, 0x1e0c, 0x65, 0x66, 0x66, 0x69, 0x72, 0x20, 0x61, 0x7a, 0x61,
-0x6e, 0x79, 0x69, 0x61, 0x67, 0x68, 0x75, 0x6f, 0x92c, 0x947, 0x932, 0x93e, 0x938, 0x947, 0x44, 0x69, 0x6c, 0x6f, 0x6c, 0x6f,
-0x6e, 0x6f, 0x6d, 0xeb, 0x74, 0x74, 0x65, 0x73, 0x61, 0x2e, 0x6b, 0x49, 0x20, 0x253, 0x75, 0x67, 0x61, 0x6a, 0x254, 0x70,
-0x5a, 0x61, 0x61, 0x72, 0x69, 0x6b, 0x61, 0x79, 0x20, 0x62, 0x65, 0x62, 0x79, 0xe1, 0x6d, 0x75, 0x6e, 0x67, 0x259, 0x67,
-0xf3, 0x67, 0x259, 0x6c, 0x65, 0x63, 0x25b, 0x25b, 0x301, 0x6e, 0x6b, 0x6f, 0x6d, 0x63, 0x68, 0x6f, 0x63, 0x68, 0x69, 0x6c,
-0x2019, 0x6c, 0x6c, 0x69, 0x6c, 0x6c, 0x69, 0x6b, 0x75, 0x67, 0xfa, 0x54, 0x14a, 0x42d, 0x41a, 0x50, 0x61, 0x73, 0x68, 0x61,
-0x6d, 0x69, 0x68, 0x65, 0x6b, 0x69, 0x73, 0x25b, 0x301, 0x6e, 0x64, 0x25b, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x74, 0x61,
-0x72, 0x64, 0x65, 0x14b, 0x6b, 0x61, 0x20, 0x6d, 0x62, 0x254, 0x301, 0x74, 0x20, 0x6e, 0x6a, 0x69, 0x6e, 0x63, 0x77, 0xf2,
-0x6e, 0x7a, 0xe9, 0x6d, 0x62f, 0x2e, 0x646, 0x77, 0xf3, 0x74, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x70, 0x6f, 0x70,
-0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x75, 0x65, 0x70, 0x2e
+static constexpr char16_t pm_data[] = {
+0x50, 0x4d, 0x6e, 0x6d, 0x2e, 0x61, 0x2e, 0x6b, 0x45, 0x57, 0x65, 0x20,
+0x70, 0x61, 0x73, 0x64, 0x69, 0x74, 0x65, 0x73, 0x12a8, 0x1230, 0x12d3, 0x1275,
+0x645, 0x985, 0x9aa, 0x9f0, 0x9be, 0x9b9, 0x9cd, 0x9a8, 0x64, 0x65, 0x20, 0x6c,
+0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0x69, 0x63, 0x68, 0x61, 0x6d,
+0x74, 0x68, 0x69, 0x41f, 0x41c, 0x63, 0x25b, 0x25b, 0x301, 0x6e, 0x6b, 0x6f,
+0x49, 0x20, 0x253, 0x75, 0x67, 0x61, 0x6a, 0x254, 0x70, 0x61, 0x6b, 0x61,
+0x73, 0x75, 0x62, 0x61, 0x70, 0x61, 0x6d, 0x75, 0x6e, 0x79, 0x69, 0x938,
+0x93e, 0x902, 0x91d, 0x92c, 0x947, 0x932, 0x93e, 0x938, 0x947, 0x70, 0x6f, 0x70,
+0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x43e, 0x441, 0x43b, 0x438, 0x458, 0x435, 0x20,
+0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x47, 0x2e, 0x4d, 0x2e, 0x441, 0x43b, 0x2e,
+0x43e, 0x431, 0x2e, 0x100a, 0x1014, 0x1031, 0x4e0b, 0x5348, 0x70, 0x2e, 0xa0, 0x6d,
+0x2e, 0x1e0c, 0x65, 0x66, 0x66, 0x69, 0x72, 0x20, 0x61, 0x7a, 0x61, 0x62f,
+0x2e, 0x646, 0x13d2, 0x13af, 0x13f1, 0x13a2, 0x13d7, 0x13e2, 0x55, 0x68, 0x72, 0x20,
+0x6e, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73,
+0x70, 0x2e, 0x6d, 0x2e, 0x6f, 0x64, 0x70, 0x2e, 0x926, 0x92a, 0x948, 0x939,
+0x930, 0x20, 0x92c, 0x93e, 0x926, 0x65, 0x62, 0x79, 0xe1, 0x6d, 0x75, 0xf55,
+0xfb1, 0xf72, 0xf0b, 0xf46, 0xf0b, 0x55, 0x54, 0xd801, 0xdc11, 0xd801, 0xdc23, 0x70,
+0x6d, 0xd801, 0xdc50, 0xd801, 0xdc65, 0x70, 0x74, 0x6d, 0x263, 0x65, 0x74, 0x72,
+0x254, 0x6e, 0x67, 0x259, 0x67, 0xf3, 0x67, 0x259, 0x6c, 0x65, 0x69, 0x70,
+0x2e, 0x73, 0x6f, 0x69, 0x72, 0x6b, 0x69, 0x6b, 0x69, 0x69, 0x257, 0x65,
+0xd83a, 0xdd07, 0xd83a, 0xdd0e, 0x3bc, 0x2e, 0x3bc, 0x2e, 0x4d, 0x6f, 0x67, 0x59,
+0x61, 0x6d, 0x6d, 0x61, 0x5d0, 0x5d7, 0x5d4, 0x5f4, 0x5e6, 0x64, 0x75, 0x2e,
+0x65, 0x2e, 0x68, 0x2e, 0x4e, 0x2019, 0x61, 0x62, 0x61, 0x6c, 0x69, 0x65,
+0x70, 0x2e, 0x70, 0x6f, 0x73, 0x20, 0x6d, 0x69, 0x64, 0xed, 0x69, 0x2e,
+0x6e, 0x2e, 0x5348, 0x5f8c, 0x57, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x20, 0x74,
+0x6d, 0x65, 0x64, 0x64, 0x69, 0x74, 0x6b, 0x6f, 0x6f, 0x73, 0x6b, 0x6f,
+0x6c, 0x69, 0x6e, 0x79, 0x128, 0x79, 0x61, 0x77, 0x129, 0x6f, 0x6f, 0xc85,
+0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x67e, 0x6cc, 0x20, 0x627, 0x6cc, 0x645,
+0x92a, 0x940, 0x20, 0x90f, 0x92e, 0x48, 0x77, 0x61, 0x129, 0x2d, 0x69, 0x6e,
+0x129, 0x938, 0x93e, 0x902, 0x91c, 0xc624, 0xd6c4, 0x41, 0x6c, 0x75, 0x75, 0x6c,
+0x61, 0x50, 0x4e, 0x6b, 0x75, 0x67, 0xfa, 0x442, 0x4af, 0x448, 0x442, 0x4e9,
+0x43d, 0x20, 0x43a, 0x438, 0x439, 0x438, 0x43d, 0x43a, 0x438, 0x4d, 0x55, 0x55,
+0xeab, 0xebc, 0xeb1, 0xe87, 0xe97, 0xec8, 0xebd, 0xe87, 0x70, 0x113, 0x63, 0x70,
+0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6d, 0x70, 0xf3, 0x6b, 0x77,
+0x61, 0x70, 0x6f, 0x70, 0x69, 0x65, 0x74, 0x77, 0xf3, 0x74, 0x70, 0x6f,
+0x142, 0x64, 0x6e, 0x6a, 0x61, 0x44, 0x69, 0x6c, 0x6f, 0x6c, 0x6f, 0x4f,
+0x54, 0x6e, 0x6f, 0x6d, 0xeb, 0x74, 0x74, 0x65, 0x73, 0x43f, 0x43e, 0x43f,
+0x43b, 0x2e, 0x6b, 0x79, 0x69, 0x75, 0x6b, 0x6f, 0x6e, 0x79, 0x69, 0x6d,
+0x63, 0x68, 0x6f, 0x63, 0x68, 0x69, 0x6c, 0x2019, 0x6c, 0x43, 0x68, 0x69,
+0x6c, 0x6f, 0x50, 0x54, 0x47, 0x9aa, 0x9bf, 0x20, 0x98f, 0x9ae, 0x190, 0x6e,
+0x64, 0xe1, 0x6d, 0xe2, 0x168, 0x47, 0x4af, 0x2e, 0x445, 0x2e, 0x1826, 0x1802,
+0x20, 0x182c, 0x1823, 0x6c, 0x69, 0x6c, 0x6c, 0x69, 0x1c3, 0x75, 0x69, 0x61,
+0x73, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x6e, 0x63, 0x77, 0xf2,
+0x6e, 0x7a, 0xe9, 0x6d, 0x14b, 0x6b, 0x61, 0x20, 0x6d, 0x62, 0x254, 0x301,
+0x74, 0x20, 0x6e, 0x6a, 0x69, 0x46, 0x1ecd, 0x20, 0xed, 0x76, 0x6e, 0x69,
+0x6e, 0x7e5, 0x65, 0x61, 0x68, 0x6b, 0x65, 0x74, 0x62, 0x65, 0x61, 0x69,
+0x76, 0x65, 0x74, 0x65, 0x2e, 0x6d, 0x2e, 0x54, 0x14a, 0x57, 0x42, 0x4d5,
+0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x444, 0x4d5, 0x441,
+0x442, 0x4d5, 0x63a, 0x2e, 0x648, 0x2e, 0x628, 0x639, 0x62f, 0x627, 0x632, 0x638,
+0x647, 0x631, 0x64, 0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0x70, 0x61,
+0x20, 0x70, 0x75, 0x73, 0x73, 0x69, 0x64, 0x65, 0x69, 0x6e, 0x61, 0x6e,
+0xa2c, 0xa3e, 0x2e, 0xa26, 0xa41, 0x2e, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x74,
+0x6f, 0x5a, 0x2e, 0x4d, 0x57, 0x2e, 0x42d, 0x41a, 0x54, 0x65, 0x69, 0x70,
+0x61, 0x4c, 0x4b, 0x50, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x69, 0x68, 0x65,
+0x1c67, 0x1c64, 0x1c6b, 0x1c5f, 0x1c79, 0x43f, 0x43e, 0x20, 0x43f, 0x43e, 0x434, 0x43d,
+0x435, 0x70, 0x6f, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x6e, 0x79, 0x69,
+0x61, 0x67, 0x68, 0x75, 0x6f, 0xa06f, 0xa2d2, 0x70, 0x6f, 0x20, 0x70, 0x6f,
+0x142, 0x65, 0x64, 0x6e, 0x69, 0x75, 0x645, 0x646, 0x62c, 0x647, 0x646, 0x62f,
+0x60c, 0x20, 0x634, 0x627, 0x645, 0x936, 0x93e, 0x92e, 0x20, 0x91c, 0x93e, 0xdb4,
+0x2e, 0xdc0, 0x2e, 0x70, 0x6f, 0x70, 0x2e, 0x45, 0x69, 0x67, 0x75, 0x6c,
+0x6f, 0x47, 0x44, 0x2d5c, 0x2d30, 0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c, 0x65,
+0x6d, 0x61, 0x6d, 0x20, 0x4e, 0x61, 0x6d, 0x69, 0x74, 0x74, 0x61, 0x67,
+0x70f, 0x712, 0x71b, 0x200c, 0x74, 0x61, 0x64, 0x67, 0x67, 0x2b7, 0x61, 0x74,
+0x6c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x70, 0xbaa, 0xbbf,
+0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0x5a, 0x61, 0x61, 0x72, 0x69, 0x6b,
+0x61, 0x79, 0x20, 0x62, 0x45, 0x62, 0x6f, 0x6e, 0x67, 0x69, 0xe2b, 0xe25,
+0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf55, 0xfb1, 0xf72, 0xf0b,
+0xf51, 0xfb2, 0xf7c, 0xf0b, 0x12f5, 0x2e, 0x1240, 0x2e, 0x65, 0x66, 0x69, 0x61,
+0x66, 0x69, 0xd6, 0x53, 0x67, 0xfc, 0x6e, 0x6f, 0x72, 0x74, 0x61, 0x64,
+0x61, 0x6e, 0x20, 0x73, 0x6f, 0x148, 0x43f, 0x43f, 0x70, 0x6f, 0x70, 0x6f,
+0x142, 0x64, 0x6e, 0x6a, 0x75, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20,
+0x643, 0x6d0, 0x64a, 0x649, 0x646, 0x54, 0x4b, 0x422, 0x41a, 0x43, 0x48, 0x79,
+0x68, 0x4e, 0x67, 0x6f, 0x6b, 0x69, 0x73, 0x25b, 0x301, 0x6e, 0x64, 0x25b,
+0x5e0, 0x5d0, 0x5b8, 0x5db, 0x5de, 0x5d9, 0x5d8, 0x5d0, 0x5b8, 0x5d2, 0x1ecc, 0x300,
+0x73, 0xe1, 0x6e, 0x186, 0x300, 0x73, 0xe1, 0x6e, 0x62, 0x61, 0x6e, 0x72,
+0x69, 0x6e, 0x67, 0x7a, 0x67, 0x76, 0x61, 0x71, 0x938, 0x93e, 0x902, 0x92e,
+0x70, 0x69, 0x20, 0x70, 0x69, 0x6e, 0x69, 0x20, 0x73, 0x75, 0x6e, 0x6f,
+0x28a, 0x73, 0x68, 0x69, 0x6c, 0xe8, 0x20, 0x6b, 0x28a, 0x73, 0x61, 0x73,
+0x28a, 0x926, 0x92a, 0x947, 0x939, 0x930, 0x93e, 0x2f, 0x938, 0x902, 0x91c, 0x93e
};
-static const char16_t currency_symbol_data[] = {
-0x42, 0x72, 0x4b, 0x73, 0x68, 0x52, 0x24, 0x4c, 0x65, 0x6b, 0xeb, 0x64, 0x65, 0x6e, 0x20ac, 0x1265, 0x122d, 0x62c, 0x2e, 0x645,
-0x2e, 0x200f, 0x62f, 0x2e, 0x62c, 0x2e, 0x200f, 0x62f, 0x2e, 0x628, 0x2e, 0x200f, 0x46, 0x43, 0x46, 0x41, 0x46, 0x64, 0x6a, 0x4e,
-0x66, 0x6b, 0x62f, 0x2e, 0x639, 0x2e, 0x200f, 0x20aa, 0x62f, 0x2e, 0x623, 0x2e, 0x200f, 0x62f, 0x2e, 0x643, 0x2e, 0x200f, 0x644, 0x2e,
-0x644, 0x2e, 0x200f, 0x62f, 0x2e, 0x644, 0x2e, 0x200f, 0x623, 0x2e, 0x645, 0x2e, 0x62f, 0x2e, 0x645, 0x2e, 0x200f, 0x631, 0x2e, 0x639,
-0x2e, 0x200f, 0x631, 0x2e, 0x642, 0x2e, 0x200f, 0x631, 0x2e, 0x633, 0x2e, 0x200f, 0x53, 0x62c, 0x2e, 0x633, 0x2e, 0x644, 0x2e, 0x633,
-0x2e, 0x200f, 0x62f, 0x2e, 0x62a, 0x2e, 0x200f, 0x62f, 0x2e, 0x625, 0x2e, 0x200f, 0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0xa3, 0x58f, 0x20b9,
-0x20bc, 0x20bd, 0x9f3, 0x4e, 0x75, 0x2e, 0x43b, 0x432, 0x2e, 0x17db, 0xa5, 0x48, 0x4b, 0x24, 0x4d, 0x4f, 0x50, 0x24, 0x48, 0x52,
-0x4b, 0x4b, 0x4d, 0x4b, 0x10d, 0x6b, 0x72, 0x2e, 0x41, 0x66, 0x6c, 0x2e, 0x4e, 0x41, 0x66, 0x2e, 0x55, 0x53, 0x24, 0x46,
-0x42, 0x75, 0x44, 0x47, 0x48, 0x20b5, 0x41, 0x72, 0x52, 0x4d, 0x52, 0x73, 0x20a6, 0x20b1, 0x52, 0x46, 0x57, 0x53, 0x24, 0x53,
-0x52, 0x45, 0x54, 0x53, 0x68, 0x54, 0x24, 0x55, 0x53, 0x68, 0x41, 0x45, 0x44, 0x56, 0x54, 0x44, 0x41, 0x46, 0x43, 0x46,
-0x50, 0x46, 0x47, 0x55, 0x4d, 0x4d, 0x41, 0x44, 0x43, 0x48, 0x46, 0x4c, 0x53, 0x44, 0x54, 0x20be, 0x20b2, 0x46, 0x74, 0x49,
-0x53, 0x4b, 0x52, 0x70, 0x43, 0x41, 0x24, 0xffe5, 0x20b8, 0x441, 0x43e, 0x43c, 0x20a9, 0x4b, 0x50, 0x57, 0x20ba, 0x20ad, 0x4b, 0x7a,
-0x434, 0x435, 0x43d, 0x2e, 0x20ae, 0x43, 0x4e, 0xa5, 0x928, 0x947, 0x930, 0x942, 0x60b, 0x631, 0x6cc, 0x627, 0x644, 0x7a, 0x142, 0x200b,
-0x4d, 0x54, 0x6e, 0x44, 0x62, 0x53, 0x2f, 0x42, 0x73, 0x52, 0x4f, 0x4e, 0x20b4, 0x52, 0x53, 0x44, 0x41a, 0x41c, 0xdbb, 0xdd4,
-0x2e, 0x20a1, 0x52, 0x44, 0x24, 0x51, 0x43, 0x24, 0x42, 0x2f, 0x2e, 0x47, 0x73, 0x2e, 0x42, 0x73, 0x2e, 0x53, 0x441, 0x43e,
-0x43c, 0x2e, 0x52, 0x73, 0x2e, 0xe3f, 0x54, 0x4d, 0x54, 0x73, 0x6f, 0x2bb, 0x6d, 0x441, 0x45e, 0x43c, 0x20ab, 0x4e, 0x54, 0x24,
-0x49, 0x52, 0x52
+static constexpr char16_t currency_symbol_data[] = {
+0x20be, 0x42, 0x72, 0x46, 0x64, 0x6a, 0x4e, 0x66, 0x6b, 0x52, 0x24, 0x46,
+0x43, 0x46, 0x41, 0x47, 0x48, 0x20b5, 0x4c, 0x65, 0x6b, 0xeb, 0x20ac, 0x64,
+0x65, 0x6e, 0x1265, 0x122d, 0x62c, 0x2e, 0x645, 0x2e, 0x200f, 0x62f, 0x2e, 0x62c,
+0x2e, 0x200f, 0x62f, 0x2e, 0x628, 0x2e, 0x200f, 0x62f, 0x2e, 0x639, 0x2e, 0x200f,
+0x20aa, 0x62f, 0x2e, 0x623, 0x2e, 0x200f, 0x62f, 0x2e, 0x643, 0x2e, 0x200f, 0x644,
+0x2e, 0x644, 0x2e, 0x200f, 0x62f, 0x2e, 0x644, 0x2e, 0x200f, 0x623, 0x2e, 0x645,
+0x2e, 0x62f, 0x2e, 0x645, 0x2e, 0x200f, 0x631, 0x2e, 0x639, 0x2e, 0x200f, 0x631,
+0x2e, 0x642, 0x2e, 0x200f, 0x631, 0x2e, 0x633, 0x2e, 0x200f, 0x53, 0xa3, 0x62c,
+0x2e, 0x633, 0x2e, 0x644, 0x2e, 0x633, 0x2e, 0x200f, 0x62f, 0x2e, 0x62a, 0x2e,
+0x200f, 0x62f, 0x2e, 0x625, 0x2e, 0x200f, 0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0x58f,
+0x20b9, 0x54, 0x53, 0x68, 0x20a6, 0x20bc, 0x20ba, 0x46, 0x202f, 0x43, 0x46, 0x41,
+0x9f3, 0x20bd, 0x4b, 0x4b, 0x4d, 0x41a, 0x41c, 0x43b, 0x432, 0x2e, 0x48, 0x4b,
+0x24, 0xffe5, 0x20b1, 0x55, 0x53, 0x68, 0xa5, 0x4d, 0x4f, 0x50, 0x24, 0x45,
+0x55, 0x52, 0x4b, 0x10d, 0x6b, 0x72, 0x2e, 0x783, 0x2e, 0x41, 0x66, 0x6c,
+0x2e, 0x4e, 0x41, 0x66, 0x2e, 0x4e, 0x75, 0x2e, 0x4b, 0x73, 0x68, 0x55,
+0x53, 0x24, 0x46, 0x42, 0x75, 0x44, 0x52, 0x70, 0x41, 0x72, 0x4d, 0x4b,
+0x52, 0x4d, 0x52, 0x66, 0x52, 0x73, 0x52, 0x46, 0x57, 0x53, 0x24, 0x53,
+0x52, 0x54, 0x24, 0x56, 0x54, 0x44, 0x41, 0x46, 0x43, 0x46, 0x50, 0x46,
+0x47, 0x55, 0x4d, 0x4c, 0x53, 0x44, 0x54, 0xd83a, 0xdd05, 0xd83a, 0xdd0a, 0xd83a,
+0xdd00, 0xd83a, 0xdd0a, 0xd83a, 0xdd05, 0xd83a, 0xdd0a, 0xd83a, 0xdd00, 0x20b2, 0x46, 0x74,
+0x43, 0x41, 0x24, 0x200b, 0x20b8, 0x17db, 0x51, 0x20a9, 0x43, 0x4e, 0xa5, 0x441,
+0x43e, 0x43c, 0x20ad, 0x4b, 0x7a, 0x434, 0x435, 0x43d, 0x2e, 0x4d, 0x54, 0x6e,
+0x20ae, 0x928, 0x947, 0x930, 0x942, 0x7ff, 0x60b, 0x631, 0x6cc, 0x627, 0x644, 0x7a,
+0x142, 0x44, 0x62, 0x53, 0x2f, 0x42, 0x73, 0x6c, 0x65, 0x69, 0x20b4, 0xdbb,
+0xdd4, 0x2e, 0x20a1, 0x52, 0x44, 0x24, 0x43, 0x24, 0x42, 0x2f, 0x2e, 0x47,
+0x73, 0x2e, 0x42, 0x73, 0x2e, 0x53, 0x20ab, 0x441, 0x43e, 0x43c, 0x2e, 0x52,
+0x73, 0x2e, 0x4e, 0x54, 0x24, 0xe3f, 0x73, 0x6f, 0x2bb, 0x6d, 0x441, 0x45e,
+0x43c
};
-static const char16_t currency_display_name_data[] = {
-0x49, 0x74, 0x6f, 0x6f, 0x70, 0x68, 0x69, 0x79, 0x61, 0x61, 0x20, 0x42, 0x69, 0x72, 0x72, 0x69, 0x69, 0x53, 0x75, 0x69,
-0x64, 0x2d, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x53,
-0x75, 0x69, 0x64, 0x2d, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b,
-0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x69, 0x64, 0x2d, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x72,
-0x61, 0x6e, 0x64, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x4c, 0x65, 0x6b,
-0x75, 0x20, 0x73, 0x68, 0x71, 0x69, 0x70, 0x74, 0x61, 0x72, 0x3b, 0x3b, 0x6c, 0x65, 0x6b, 0x20, 0x73, 0x68, 0x71, 0x69,
-0x70, 0x74, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x65, 0x6b, 0xeb, 0x20, 0x73, 0x68, 0x71, 0x69, 0x70, 0x74, 0x61,
-0x72, 0x44, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x20, 0x6d, 0x61, 0x71, 0x65, 0x64, 0x6f, 0x6e, 0x61, 0x73, 0x3b, 0x3b, 0x64,
-0x65, 0x6e, 0x61, 0x72, 0x20, 0x6d, 0x61, 0x71, 0x65, 0x64, 0x6f, 0x6e, 0x61, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x65,
-0x6e, 0x61, 0x72, 0xeb, 0x20, 0x6d, 0x61, 0x71, 0x65, 0x64, 0x6f, 0x6e, 0x61, 0x73, 0x45, 0x75, 0x72, 0x6f, 0x6a, 0x61,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x12e8, 0x12a2, 0x1275, 0x12ee, 0x1335, 0x12eb,
-0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x12e8, 0x12a2, 0x1275, 0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x3b, 0x3b, 0x12e8, 0x12a2,
-0x1275, 0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a,
-0x647, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x3b, 0x62c, 0x646, 0x64a,
-0x647, 0x627, 0x646, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x645, 0x635,
-0x631, 0x64a, 0x629, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x64b, 0x627, 0x3b, 0x62c, 0x646,
-0x64a, 0x647, 0x20, 0x645, 0x635, 0x631, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62c,
-0x632, 0x627, 0x626, 0x631, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x646, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a,
-0x627, 0x646, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a, 0x629, 0x3b, 0x62f,
-0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627,
-0x631, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a,
-0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20,
-0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628,
-0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x641, 0x631,
-0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648,
-0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623,
-0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642,
-0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631,
-0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648,
-0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644,
-0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641,
-0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c,
-0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644,
-0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641,
-0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a,
-0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646,
-0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a,
-0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a,
-0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x646, 0x627, 0x643, 0x641,
-0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631,
-0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627,
-0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a,
-0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20,
-0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a,
-0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642,
-0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20,
-0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a,
-0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a,
-0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644,
-0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a,
-0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20,
-0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c,
-0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f,
-0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a,
-0x62f, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623,
-0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646,
-0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a,
-0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623,
-0x631, 0x62f, 0x646, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627,
-0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648,
-0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627,
-0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c,
-0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627,
-0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20,
-0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c,
-0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a,
-0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a,
-0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x646, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x64a,
-0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20,
-0x644, 0x64a, 0x628, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x623, 0x648, 0x642,
-0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645,
-0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a,
-0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629,
-0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642,
-0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645,
-0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x62f,
-0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a,
-0x3b, 0x62f, 0x631, 0x647, 0x645, 0x627, 0x646, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x631, 0x627, 0x647,
-0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x629, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x64b, 0x627, 0x20, 0x645, 0x63a, 0x631, 0x628,
-0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639,
-0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644,
-0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a,
-0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x631,
-0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648,
-0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633,
-0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x634, 0x644, 0x646, 0x20, 0x635,
-0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646,
-0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634,
-0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a,
-0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627,
-0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20,
-0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c,
-0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627,
-0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x64b, 0x627, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646,
-0x64a, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631,
-0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633,
-0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629,
-0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x62f, 0x64a, 0x646,
-0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a,
-0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x646,
-0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x62a, 0x648, 0x646,
-0x633, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x64b, 0x627, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631,
-0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647,
-0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627,
-0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645,
-0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a,
-0x64a, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
-0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644,
-0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648,
-0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x646, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648,
-0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648,
-0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648,
-0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627,
-0x646, 0x570, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x3b, 0x570, 0x561, 0x575, 0x56f,
-0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x3b, 0x3b, 0x3b, 0x570, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561,
-0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9f0, 0x9c1, 0x9aa, 0x9c0, 0x3b, 0x3b,
-0x9ad, 0x9be, 0x9f0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9f0, 0x9c1, 0x9aa, 0x9c0, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9f0, 0x9a4,
-0x9c0, 0x9af, 0x9bc, 0x20, 0x9f0, 0x9c1, 0x9aa, 0x9c0, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x4d,
-0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x61,
-0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d,
-0x61, 0x6e, 0x61, 0x74, 0x131, 0x43c, 0x430, 0x43d, 0x430, 0x442, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f,
-0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b,
-0x3b, 0x3b, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x9ad, 0x9be, 0x9b0,
-0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0,
-0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0xf51,
-0xf44, 0xf74, 0xf63, 0xf0b, 0xf40, 0xfb2, 0xf58, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x61, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x69, 0x6f, 0xf9, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b, 0x431, 0x44a, 0x43b,
-0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b, 0x3b, 0x3b, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440,
-0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x430, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x20, 0x1000, 0x103b, 0x1015, 0x103a, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x20, 0x1000, 0x103b, 0x1015, 0x103a, 0x431, 0x435, 0x43b, 0x430,
-0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443,
-0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a,
-0x456, 0x44f, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x456, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x445, 0x20,
-0x440, 0x443, 0x431, 0x43b, 0x451, 0x45e, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x433, 0x430, 0x20, 0x440,
-0x443, 0x431, 0x43b, 0x44f, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x4eba, 0x6c11, 0x5e01, 0x6e2f, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e2f, 0x5143, 0x6fb3, 0x95e8, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x6fb3,
-0x9580, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x65b0, 0x53f0, 0x5e63, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72,
-0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b,
-0x65, 0x20, 0x6b, 0x75, 0x6e, 0x65, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x75,
-0x6e, 0x61, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
-0x61, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72,
-0x6b, 0x61, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61,
-0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20,
-0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b,
-0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20,
-0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b,
-0x10d, 0x65, 0x73, 0x6b, 0xfd, 0x63, 0x68, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b,
-0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b,
-0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73,
-0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
-0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
-0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74,
-0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x4e, 0x65,
-0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73,
-0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e,
-0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64,
-0x65, 0x6e, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
-0x3b, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x55,
-0x53, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61,
-0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x45, 0x61, 0x73, 0x74,
-0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x73, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x73, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73,
-0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x61, 0x68,
-0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61,
-0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61,
-0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20,
-0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20,
-0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42,
-0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61,
-0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x73, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x50, 0x75, 0x6c, 0x61, 0x3b,
-0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x70, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x42,
-0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x70, 0x75, 0x6c, 0x61, 0x73, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64,
-0x69, 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e,
-0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20,
-0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c,
-0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b,
-0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46,
-0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
-0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x3b, 0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e,
-0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e,
-0x64, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e,
-0x64, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c,
-0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72,
-0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b,
-0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65,
-0x61, 0x6e, 0x20, 0x4e, 0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e,
-0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x6b,
-0x66, 0x61, 0x73, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20,
-0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61,
-0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e,
-0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x46, 0x69, 0x6a, 0x69,
-0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x73, 0x55, 0x4b, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64,
-0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e,
-0x20, 0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6c,
-0x61, 0x73, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6c, 0x61, 0x73,
-0x69, 0x73, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x47, 0x68, 0x61,
-0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69,
-0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x73, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x50, 0x6f,
-0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64,
-0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73,
-0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x47, 0x75,
-0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x75,
-0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x48, 0x6f, 0x6e, 0x67, 0x20,
-0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f,
-0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f,
-0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70,
-0x65, 0x65, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b,
-0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69,
-0x20, 0x4e, 0x65, 0x77, 0x20, 0x53, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x3b, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69,
-0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65,
-0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x73, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63,
-0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20,
-0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e,
-0x67, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b,
-0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x6f,
-0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f,
-0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
-0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x4c, 0x69,
-0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72,
-0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69,
-0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50,
-0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61,
-0x63, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63,
-0x61, 0x73, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x4d,
-0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61,
-0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x61, 0x72, 0x69, 0x61, 0x72, 0x69, 0x65, 0x73, 0x4d, 0x61, 0x6c, 0x61, 0x77,
-0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e,
-0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20,
-0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x69, 0x6e,
-0x67, 0x67, 0x69, 0x74, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67,
-0x67, 0x69, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e,
-0x67, 0x67, 0x69, 0x74, 0x73, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65,
-0x3b, 0x3b, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b,
-0x3b, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x4e, 0x61, 0x6d,
-0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69,
-0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
-0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x4e, 0x61,
-0x69, 0x72, 0x61, 0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x3b,
-0x3b, 0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x73, 0x50, 0x61,
-0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73,
-0x74, 0x61, 0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74,
-0x61, 0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20,
-0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20,
-0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
-0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69,
-0x6e, 0x61, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x3b, 0x3b, 0x50,
-0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x69, 0x73, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x68,
-0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x69, 0x73, 0x6f, 0x73, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61,
-0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73,
-0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x54, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20,
-0x74, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6c, 0x61, 0x53,
-0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x53, 0x65,
-0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
-0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x53, 0x69, 0x65,
-0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x53,
-0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x3b,
-0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6c, 0x65,
-0x6f, 0x6e, 0x65, 0x73, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
-0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x53,
-0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c,
-0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x53, 0x74, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e,
-0x61, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x74, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70,
-0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x74, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f,
-0x75, 0x6e, 0x64, 0x73, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b,
-0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75,
-0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x4c,
-0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x6c, 0x69, 0x6c, 0x61,
-0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x65, 0x6d, 0x61, 0x6c, 0x61,
-0x6e, 0x67, 0x65, 0x6e, 0x69, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b,
-0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x65,
-0x64, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x46, 0x72, 0x61,
-0x6e, 0x63, 0x3b, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
-0x77, 0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e,
-0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e,
-0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69,
-0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x50,
-0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e,
-0x67, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61,
-0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x44, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62,
-0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64,
-0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x55,
-0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x55, 0x67, 0x61,
-0x6e, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x67, 0x61,
-0x6e, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64,
-0x20, 0x41, 0x72, 0x61, 0x62, 0x20, 0x45, 0x6d, 0x69, 0x72, 0x61, 0x74, 0x65, 0x73, 0x20, 0x44, 0x69, 0x72, 0x68, 0x61,
-0x6d, 0x3b, 0x3b, 0x55, 0x41, 0x45, 0x20, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x41, 0x45,
-0x20, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x73, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x50, 0x6f, 0x75, 0x6e,
-0x64, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
-0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74,
-0x75, 0x20, 0x56, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x74, 0x75,
-0x3b, 0x3b, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x74, 0x75, 0x73, 0x5a, 0x61, 0x6d,
-0x62, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e,
-0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b,
-0x77, 0x61, 0x63, 0x68, 0x61, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65,
-0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65,
-0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75,
-0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c,
-0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x47, 0x75, 0x69, 0x6c, 0x64,
-0x65, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69,
-0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x74,
-0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67,
-0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x73, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x65, 0x75, 0x72, 0x6f, 0x74, 0x64, 0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x64,
-0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x61,
-0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75, 0x72, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65,
-0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b,
-0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e,
-0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75,
-0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x62, 0x75,
-0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45,
-0x41, 0x43, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43,
-0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41,
-0x43, 0x29, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6d,
-0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6f,
-0x72, 0x69, 0x65, 0x6e, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73,
-0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x73, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43,
-0x46, 0x50, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x50, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e,
-0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66,
-0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x73, 0x67, 0x6f, 0x75, 0x72, 0x64, 0x65,
-0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x20, 0x68,
-0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x73, 0x20,
-0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c,
-0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63,
-0x68, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x73, 0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63,
-0x68, 0x65, 0x73, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69,
-0x65, 0x6e, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e,
-0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72,
-0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x73, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69,
-0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69,
-0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6d, 0x61,
-0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72,
-0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61,
-0x69, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x73, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61,
-0x69, 0x6e, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66,
-0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x73, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64,
-0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69,
-0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x3b, 0x3b,
-0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c,
-0x65, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e,
-0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x73,
-0x75, 0x69, 0x73, 0x73, 0x65, 0x73, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65,
-0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b,
-0x6c, 0x69, 0x76, 0x72, 0x65, 0x73, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x64, 0x69, 0x6e, 0x61,
-0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75,
-0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x74, 0x75, 0x6e,
-0x69, 0x73, 0x69, 0x65, 0x6e, 0x73, 0x76, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e,
-0x3b, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b,
-0x76, 0x61, 0x74, 0x75, 0x73, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x73, 0x50, 0x75, 0x6e, 0x6e,
-0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20,
-0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73,
-0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x70, 0x75, 0x69, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x61, 0x73, 0x61, 0x6e,
-0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63,
-0x68, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3,
-0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da,
-0x10d0, 0x10e0, 0x10d8, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72,
-0x6f, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b,
-0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x3b,
-0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x395, 0x3c5,
-0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x64, 0x61, 0x6e, 0x6d,
-0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x64, 0x61, 0x6e,
-0x73, 0x6b, 0x69, 0x6e, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61,
-0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0xaad, 0xabe, 0xab0,
-0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0,
-0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf,
-0xaaf, 0xabe, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x72, 0x20, 0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x4e,
-0x61, 0x69, 0x72, 0x61, 0x72, 0x20, 0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61,
-0x69, 0x72, 0x6f, 0x72, 0x69, 0x6e, 0x20, 0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x4b, 0x75, 0x257, 0x69, 0x6e,
-0x20, 0x53, 0x65, 0x66, 0x61, 0x20, 0x6e, 0x61, 0x20, 0x41, 0x66, 0x69, 0x72, 0x6b, 0x61, 0x20, 0x54, 0x61, 0x20, 0x59,
-0x61, 0x6d, 0x6d, 0x61, 0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9,
-0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20,
-0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x92d, 0x93e, 0x930,
-0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941,
-0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x90f, 0x6d, 0x61,
-0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20,
-0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72,
-0x69, 0x6e, 0x74, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0xed, 0x73,
-0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e,
-0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75, 0x72, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e,
-0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20,
-0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x50,
-0x75, 0x6e, 0x74, 0x20, 0x53, 0x74, 0x65, 0x69, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x74,
-0x20, 0x73, 0x74, 0x65, 0x69, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x65,
-0x69, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x65, 0x69, 0x72, 0x6c, 0x69,
-0x6e, 0x67, 0x3b, 0x62, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x65, 0x69, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x70,
-0x75, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x65, 0x69, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20,
-0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76, 0x69,
-0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x69, 0x20, 0x73, 0x76, 0x69,
-0x7a, 0x7a, 0x65, 0x72, 0x69, 0x65e5, 0x672c, 0x5186, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5186, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0,
-0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa,
-0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf,
-0xc97, 0xcb3, 0xcc1, 0x6c1, 0x650, 0x646, 0x62f, 0x64f, 0x633, 0x62a, 0x672, 0x646, 0x6cd, 0x20, 0x631, 0x6c4, 0x67e, 0x64e, 0x6d2, 0x49a,
-0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x49a, 0x430,
-0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a,
-0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x41a, 0x44b, 0x440, 0x433,
-0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441,
-0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0x3b, 0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442,
-0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xb300,
-0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0xc870, 0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20,
-0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xc870, 0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654,
-0xad6d, 0x20, 0xc6d0, 0x49, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x72, 0x79, 0x2019, 0x55, 0x62, 0x75, 0x72, 0x75,
-0x6e, 0x64, 0x69, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20,
-0xe81, 0xeb5, 0xe9a, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x65, 0x69, 0x72, 0x6f, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67,
-0xf3, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x79, 0x61, 0x20, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x46, 0x61, 0x6c,
-0xe1, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x45, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b,
-0x65, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x69, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75,
-0x72, 0x173, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x3b, 0x3b,
-0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b,
-0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x438, 0x52, 0x69, 0x6e,
-0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52,
-0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x44, 0x6f, 0x6c, 0x61, 0x72,
-0x20, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x42,
-0x72, 0x75, 0x6e, 0x65, 0x69, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72,
-0x61, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f,
-0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a,
-0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x65, 0x77, 0x72,
-0x6f, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x54, 0x101, 0x72, 0x61, 0x20, 0x6f, 0x20, 0x41, 0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f,
-0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x74, 0x101, 0x72, 0x61, 0x20, 0x6f, 0x20, 0x41, 0x6f, 0x74, 0x65, 0x61, 0x72,
-0x6f, 0x61, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924,
-0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930,
-0x941, 0x92a, 0x92f, 0x947, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x20, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x41c,
-0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x20, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x3b, 0x3b, 0x41c, 0x43e, 0x43d, 0x433,
-0x43e, 0x43b, 0x20, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948,
-0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b,
-0x3b, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x92d, 0x93e, 0x930,
-0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20,
-0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942,
-0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x3b,
-0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b,
-0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0xb2d, 0xb3e, 0xb30, 0xb24, 0xb40, 0xb5f, 0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e,
-0x3b, 0x3b, 0xb2d, 0xb3e, 0xb30, 0xb24, 0xb40, 0xb5f, 0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e, 0x3b, 0x3b, 0x3b, 0x3b, 0xb2d, 0xb3e,
-0xb30, 0xb24, 0xb40, 0xb5f, 0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x627, 0x641,
-0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627,
-0x646, 0x6cd, 0x20, 0x6a9, 0x644, 0x62f, 0x627, 0x631, 0x647, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cd, 0x20,
-0x6a9, 0x644, 0x62f, 0x627, 0x631, 0x647, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cd, 0x20, 0x6a9,
-0x644, 0x62f, 0x627, 0x631, 0x6d2, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x631, 0x6cc, 0x627,
-0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627,
-0x646, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x627,
-0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x627,
-0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x7a, 0x142, 0x6f, 0x74, 0x79,
-0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b,
-0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x3b, 0x7a, 0x142, 0x6f,
-0x74, 0x79, 0x63, 0x68, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x63, 0x68, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x67,
-0x6f, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x67, 0x6f, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73,
-0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65,
-0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x65, 0x61, 0x69, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65,
-0x69, 0x72, 0x6f, 0x73, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b,
-0x3b, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x73, 0x63,
-0x75, 0x64, 0x6f, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x65,
-0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b,
-0x3b, 0x3b, 0x3b, 0x65, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x73, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64,
-0x69, 0x61, 0x6e, 0x6f, 0x73, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64,
-0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73,
-0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x64,
-0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55,
-0x6e, 0x69, 0x64, 0x6f, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41,
-0x43, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43,
-0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45,
-0x41, 0x43, 0x29, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f,
-0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f,
-0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43,
-0x45, 0x41, 0x4f, 0x29, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x6d, 0x61, 0x63, 0x61, 0x65, 0x6e, 0x73, 0x65, 0x3b,
-0x3b, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x6d, 0x61, 0x63, 0x61, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b,
-0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x63, 0x61, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x6d, 0x65, 0x74,
-0x69, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x6d, 0x65,
-0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x63, 0x61, 0x6e,
-0x6f, 0x73, 0x64, 0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20,
-0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x64, 0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65,
-0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65,
-0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x6f, 0x62, 0x72, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f,
-0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20,
-0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b,
-0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x73, 0xa2d, 0xa3e, 0xa30,
-0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07,
-0xa06, 0x3b, 0x3b, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa0f, 0x631, 0x648, 0x67e, 0x626, 0x6cc,
-0x6c1, 0x53, 0x6f, 0x6c, 0x20, 0x50, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f,
-0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20,
-0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a,
-0x65, 0x72, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f,
-0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63,
-0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69,
-0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76,
-0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65,
-0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69,
-0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x440, 0x43e,
-0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441,
-0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439,
-0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438,
-0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x43e, 0x433, 0x43e,
-0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443,
-0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431,
-0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b,
-0x44f, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439,
-0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x43a,
-0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430,
-0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a,
-0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442,
-0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x442, 0x435, 0x43d, 0x433,
-0x435, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440,
-0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441,
-0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20,
-0x441, 0x43e, 0x43c, 0x43e, 0x432, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x441, 0x43e,
-0x43c, 0x430, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e,
-0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432,
-0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20,
-0x43b, 0x435, 0x435, 0x432, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x43b, 0x435, 0x44f,
-0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443,
-0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a,
-0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438, 0x435, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x443, 0x43a, 0x440, 0x430,
-0x438, 0x43d, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d,
-0x441, 0x43a, 0x43e, 0x439, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x66, 0x61, 0x72, 0xe2, 0x6e, 0x67, 0x61, 0x20, 0x43,
-0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430,
-0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f,
-0x441, 0x43a, 0x430, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x445, 0x20,
-0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65,
-0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e,
-0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65,
-0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62,
-0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f,
-0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72,
-0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e,
-0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f,
-0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x45,
-0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x76, 0x72,
-0x61, 0x53, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b,
-0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64, 0x69, 0x6e, 0x61,
-0x72, 0x61, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x411, 0x43e,
-0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20,
-0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b,
-0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447,
-0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440,
-0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e,
-0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20,
-0x43c, 0x430, 0x440, 0x43a, 0x65, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446,
-0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438,
-0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x415, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440,
-0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b, 0x430,
-0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x44b, 0x421, 0x43e, 0x43c, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x3b,
-0x3b, 0x441, 0x43e, 0x43c, 0x44b, 0x44, 0x6f, 0x72, 0x61, 0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61,
-0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631, 0x67e, 0x64a, 0x3b, 0x3b, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627,
-0x646, 0x64a, 0x20, 0x631, 0x67e, 0x64a, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631,
-0x67e, 0x64a, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b,
-0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b,
-0x3b, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x65,
-0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0xe1, 0x3b, 0x65, 0x75, 0x72, 0x61,
-0x3b, 0x65, 0x75, 0x72, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b,
-0x65, 0x76, 0x72, 0x69, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x76, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61,
-0x20, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x79, 0x61, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61, 0x62,
-0x75, 0x75, 0x74, 0x69, 0x3b, 0x3b, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74,
-0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69,
-0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x62, 0x69, 0x72,
-0x74, 0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x69, 0x72, 0x74,
-0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61,
-0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61, 0x20, 0x4b, 0x65,
-0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61, 0x20, 0x4b, 0x65, 0x6e,
-0x79, 0x61, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65,
-0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f,
-0x73, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x73, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65,
-0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65,
-0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65,
-0xf1, 0x6f, 0x73, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69,
-0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x72, 0x65, 0x61,
-0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72,
-0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x72,
-0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x73, 0x50, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f,
-0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65,
-0x73, 0x6f, 0x73, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x73, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c,
-0x6f, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62,
-0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62,
-0x69, 0x61, 0x6e, 0x6f, 0x73, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63,
-0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69,
-0x63, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x73,
-0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61,
-0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70,
-0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x73, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d,
-0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69,
-0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69,
-0x63, 0x61, 0x6e, 0x6f, 0x73, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69,
-0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75,
-0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x65,
-0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f,
-0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72,
-0x61, 0x6c, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e,
-0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x43, 0x65,
-0x6e, 0x74, 0x72, 0x61, 0x6c, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61,
-0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x65, 0x73, 0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72,
-0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x61,
-0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72,
-0x61, 0x73, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x73, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x6d, 0x65,
-0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e,
-0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x73,
-0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65,
-0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e,
-0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x73, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72,
-0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d,
-0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x73, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f,
-0x73, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b,
-0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x65, 0x73, 0x20, 0x70, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f,
-0x73, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65,
-0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61,
-0x6e, 0x6f, 0x73, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65,
-0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73,
-0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x73, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75,
-0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b,
-0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x62, 0x6f, 0x6c,
-0xed, 0x76, 0x61, 0x72, 0x20, 0x73, 0x6f, 0x62, 0x65, 0x72, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76,
-0x61, 0x72, 0x20, 0x73, 0x6f, 0x62, 0x65, 0x72, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76,
-0x61, 0x72, 0x65, 0x73, 0x20, 0x73, 0x6f, 0x62, 0x65, 0x72, 0x61, 0x6e, 0x6f, 0x73, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c,
-0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
-0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61,
-0x46, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x66, 0x61,
-0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x61,
-0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67,
-0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20,
-0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20,
-0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67,
-0x69, 0x20, 0x7a, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72,
-0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b,
-0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x421, 0x43e, 0x43c, 0x43e, 0x43d,
-0x4e3, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x421, 0x43e, 0x43c, 0x43e, 0x43d, 0x4e3, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20,
-0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf,
-0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3,
-0xbcd, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b,
-0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0x3b,
-0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0xb95, 0xbb3,
-0xbcd, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b,
-0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0x3b,
-0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0xb95, 0xbb3,
-0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd,
-0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20,
-0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f, 0x20, 0x441, 0x443, 0x43c, 0x44b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x443, 0x43c, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a,
-0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc32, 0xc41, 0xe1a, 0xe32, 0xe17, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42,
-0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62, 0xf0b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74,
-0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x66, 0x61,
-0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x4c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b,
-0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20,
-0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79,
-0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79, 0x3b, 0x3b, 0x3b, 0x3b,
-0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20,
-0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b,
-0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441,
-0x44c, 0x43a, 0x430, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b,
-0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d,
-0x456, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9,
-0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a,
-0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc,
-0x6c1, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x628,
-0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6d2, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f,
-0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e,
-0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f,
-0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e,
-0x43c, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x3b,
-0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x110, 0x1ed3, 0x6e, 0x67, 0x20,
-0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56,
-0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x50, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b,
-0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72,
-0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70,
-0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79,
-0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
-0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x62, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x20, 0x53, 0x6f, 0x77, 0x77,
-0x75, 0x2d, 0x6a, 0x61, 0x6e, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46,
-0x41, 0x20, 0x79, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x20, 0x53, 0x6f, 0x77, 0x77, 0x75, 0x2d, 0x6a, 0x61, 0x6e,
-0x74, 0x69, 0x52, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x79, 0x61, 0x73, 0x65, 0x4d, 0x7a, 0x61, 0x6e, 0x7a, 0x69, 0x20, 0x41,
-0x66, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x69, 0x52, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x59, 0x61, 0x73, 0x65, 0x4d, 0x7a,
-0x61, 0x6e, 0x7a, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x52, 0x61, 0x6e, 0x64,
-0x69, 0x20, 0x79, 0x61, 0x73, 0x65, 0x4d, 0x7a, 0x61, 0x6e, 0x7a, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x4e,
-0xe1, 0xec, 0x72, 0xe0, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x300, 0x2d, 0xe8, 0x64, 0xe8, 0x20, 0x4e,
-0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0xe1, 0xed, 0x72, 0xe0, 0x20, 0x4e,
-0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72,
-0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x42, 0x49, 0x4b, 0x45, 0x41, 0x4f, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74,
-0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f,
-0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
-0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64,
-0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61,
-0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61,
-0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d,
-0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72,
-0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76,
-0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d,
-0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67,
-0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e,
-0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x41a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b,
-0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445,
-0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438,
-0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a,
-0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435,
-0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x435, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430,
-0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a,
-0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430,
-0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x53, 0x69, 0x64, 0x69, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a,
-0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e,
-0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79,
-0x61, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73,
-0x69, 0x256, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x263, 0x65, 0x74,
-0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66,
-0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65,
-0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
-0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66,
-0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45,
-0x41, 0x4f, 0x50, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b,
-0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x3b,
-0x3b, 0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x53,
-0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x53, 0x63, 0x68,
-0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63, 0x68,
-0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e,
-0x6f, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x6e, 0x6f,
-0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67,
-0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72,
-0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e,
-0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x72,
-0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75, 0x20,
-0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x69, 0x20, 0x53,
-0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x45, 0x41, 0x43, 0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x20, 0x47, 0x61, 0x6d,
-0x6d, 0x62, 0x69, 0x44, 0x6f, 0x6c, 0x61, 0x61, 0x72, 0x20, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x55,
-0x67, 0x69, 0x79, 0x79, 0x61, 0x20, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x4e, 0x61, 0x79, 0x72, 0x61, 0x61,
-0x20, 0x4e, 0x69, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x4c, 0x65, 0x77, 0x6f, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x72,
-0x61, 0x61, 0x20, 0x4c, 0x69, 0x79, 0x6f, 0x6e, 0x43, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b,
-0x65, 0x6e, 0x79, 0x61, 0x4e, 0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x65, 0x6c, 0x20, 0x4b, 0x65, 0x6e,
-0x79, 0x61, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69,
-0x71, 0x75, 0x65, 0x44, 0x6f, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x73, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61,
-0x68, 0x65, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x73, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x2d30, 0x2d37,
-0x2d54, 0x2d49, 0x2d4e, 0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x61, 0x64, 0x72, 0x69, 0x6d, 0x20, 0x6e, 0x20,
-0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61, 0x79, 0x72, 0x69,
-0x3b, 0x3b, 0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x6e, 0x20, 0x5a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x49, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x65, 0x6e, 0x20, 0x6e, 0x20, 0x5a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x45, 0x73,
-0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x68, 0x69,
-0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x73,
-0x65, 0x66, 0x61, 0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x55, 0x53, 0x20, 0x13a0,
-0x13d5, 0x13b3, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3,
-0x72, 0x6f, 0x75, 0x70, 0x69, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x53, 0x68, 0x69, 0x6c, 0xed, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x53, 0x69, 0x6c, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x65, 0x79, 0x61, 0x20, 0x59, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x6b, 0x75, 0x64, 0x75,
-0x20, 0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
-0x6b, 0x75, 0x64, 0x75, 0x20, 0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x53, 0x69, 0x6c,
-0x69, 0x6e, 0x67, 0x69, 0x74, 0x61, 0x62, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4e, 0x61, 0x6d, 0x69,
-0x62, 0x69, 0x61, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x69, 0x49, 0x72, 0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e,
-0xed, 0x20, 0x65, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x49, 0x72, 0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e, 0xed, 0x20,
-0x65, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x53, 0x69, 0x72, 0x69, 0x6e, 0x6a, 0x69, 0x20, 0x79, 0x61,
-0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61,
-0x6e, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x41, 0x6e, 0x67, 0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b,
-0x2019, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x41, 0x6e, 0x67, 0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f,
-0x6b, 0x2019, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x43, 0x46, 0x41, 0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43,
-0x45, 0x41, 0x4f, 0x29, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61,
-0x44, 0x65, 0x72, 0x68, 0x65, 0x6d, 0x20, 0x55, 0x6d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x69, 0x930, 0x93e, 0x902, 0x420, 0x43e,
-0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441,
-0x43e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x44c, 0x43c, 0x430, 0x448,
-0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x457, 0x439, 0x20, 0x440, 0xa64b, 0x301, 0x431, 0x43b, 0x44c, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x430, 0x433, 0x461, 0x20, 0x440, 0xa64b, 0x431,
-0x43b, 0x467, 0x300, 0x4e, 0x66, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x75,
-0x43, 0x46, 0x41, 0x20, 0x46, 0xe0, 0x6c, 0xe2, 0x14b, 0x20, 0x42, 0x45, 0x41, 0x43, 0x46, 0x72, 0x1ce, 0x14b, 0x20, 0x43,
-0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x73, 0x65, 0x65, 0x66, 0x61, 0x20, 0x79, 0x61, 0x74, 0x69, 0x20,
-0x42, 0x43, 0x45, 0x41, 0x4f, 0x46, 0x259, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43,
-0x29, 0x66, 0x72, 0xe1, 0x14b, 0x73, 0x6f, 0x6c, 0x61, 0x69, 0x20, 0x42, 0x45, 0x41, 0x43, 0x46, 0x72, 0x61, 0x14b, 0x20,
-0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x20, 0x441, 0x43e,
-0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b,
-0x44b, 0x439, 0x430, 0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439, 0x430, 0x49, 0x68, 0x65, 0x6c, 0x61, 0x20,
-0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x20, 0xa55c, 0xa55e, 0xa54c,
-0x4c, 0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x20, 0x44, 0x61, 0x6c, 0x61, 0x46, 0x25b, 0x6c, 0xe2, 0x14b, 0x73, 0x68,
-0x69, 0x72, 0xe8, 0x66, 0x65, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46, 0x41, 0xd804, 0xdd1d, 0xd804, 0xdd01, 0xd804, 0xdd23, 0xd804, 0xdd18,
-0xd804, 0xdd2c, 0xd804, 0xdd25, 0xd804, 0xdd28, 0x20, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804, 0xdd0b, 0x3b, 0x3b, 0xd804, 0xdd1d, 0xd804, 0xdd01, 0xd804,
-0xdd23, 0xd804, 0xdd18, 0xd804, 0xdd2c, 0xd804, 0xdd25, 0xd804, 0xdd28, 0x20, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804, 0xdd0b, 0x3b, 0x3b, 0x3b, 0x3b,
-0xd804, 0xdd1d, 0xd804, 0xdd01, 0xd804, 0xdd23, 0xd804, 0xdd18, 0xd804, 0xdd2c, 0xd804, 0xdd25, 0xd804, 0xdd28, 0x20, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804,
-0xdd0b, 0xd804, 0xdd03, 0xd804, 0xdd28, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd20, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x20,
-0xd804, 0xdd22, 0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd28, 0x3b, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd28, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0xd804, 0xdd18,
-0xd804, 0xdd28, 0xd804, 0xdd20, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x20, 0xd804, 0xdd22, 0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd28, 0x3b, 0x3b, 0x3b,
-0x3b, 0xd804, 0xdd03, 0xd804, 0xdd28, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd20, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x20,
-0xd804, 0xdd22, 0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd28, 0x62f, 0x6cc, 0x646, 0x627, 0x631, 0x6cc, 0x20, 0x639, 0x6ce, 0x631, 0x627, 0x642,
-0x6cc, 0x695, 0x6cc, 0x627, 0x6b5, 0x6cc, 0x20, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x6cc, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
-0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x65,
-0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x6a, 0x3b, 0x65, 0x75, 0x72, 0x61,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x77, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x6e2f, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x6e2f, 0x5e63, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x3b, 0x3b,
-0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x69, 0x73, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d,
-0x67, 0x61, 0x20, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x69, 0x73, 0x6f
+static constexpr char16_t currency_display_name_data[] = {
+0x53, 0x75, 0x69, 0x64, 0x2d, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61,
+0x6e, 0x73, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x4e, 0x61, 0x6d, 0x69,
+0x62, 0x69, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x43, 0x46, 0x41, 0x20, 0x46, 0xe0, 0x6c, 0xe2, 0x14b, 0x20, 0x42, 0x45,
+0x41, 0x43, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x53, 0x69, 0x64, 0x69,
+0x46, 0x72, 0xe2, 0x6e, 0x6b, 0x65, 0x20, 0x43, 0x46, 0x41, 0x4c, 0x65,
+0x6b, 0x75, 0x20, 0x73, 0x68, 0x71, 0x69, 0x70, 0x74, 0x61, 0x72, 0x45,
+0x75, 0x72, 0x6f, 0x6a, 0x61, 0x44, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x20,
+0x6d, 0x61, 0x71, 0x65, 0x64, 0x6f, 0x6e, 0x61, 0x73, 0x12e8, 0x12a2, 0x1275,
+0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x645,
+0x635, 0x631, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62c, 0x632, 0x627,
+0x626, 0x631, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631,
+0x64a, 0x646, 0x64a, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20,
+0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c,
+0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x641, 0x631, 0x646, 0x643,
+0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x646, 0x627, 0x643, 0x641, 0x627,
+0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x62f, 0x64a, 0x646, 0x627, 0x631,
+0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625,
+0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f,
+0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x62f,
+0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x62c, 0x646,
+0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x62f, 0x64a, 0x646,
+0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x623, 0x648, 0x642, 0x64a, 0x629,
+0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x62f, 0x631,
+0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x631, 0x64a, 0x627, 0x644,
+0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642,
+0x637, 0x631, 0x64a, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f,
+0x64a, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x62c,
+0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633,
+0x648, 0x62f, 0x627, 0x646, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f,
+0x627, 0x646, 0x64a, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a,
+0x629, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a,
+0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a,
+0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x65, 0x75, 0x72,
+0x6f, 0x570, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580,
+0x561, 0x574, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9f0, 0x9c1,
+0x9aa, 0x9c0, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79,
+0x61, 0x20, 0x54, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x41,
+0x6d, 0x61, 0x6e, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61,
+0x6e, 0x20, 0x4d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x43c, 0x430, 0x43d, 0x430,
+0x442, 0x66, 0x72, 0xe1, 0x14b, 0x73, 0x65, 0x66, 0x61, 0x20, 0x46, 0x72,
+0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x9ac, 0x9be,
+0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be,
+0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf,
+0x46, 0x72, 0x1ce, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45,
+0x41, 0x43, 0x29, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x431, 0x435, 0x43b, 0x430,
+0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c,
+0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x92d, 0x93e,
+0x930, 0x924, 0x928, 0x93f, 0x20, 0x930, 0x941, 0x92a, 0x940, 0x42, 0x6f, 0x73,
+0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f,
+0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72,
+0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
+0x61, 0x41a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b,
+0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x411, 0x44a, 0x43b, 0x433,
+0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x1019, 0x103c, 0x1014,
+0x103a, 0x1019, 0x102c, 0x20, 0x1000, 0x103b, 0x1015, 0x103a, 0x6e2f, 0x5e63, 0x4eba, 0x6c11,
+0x5e01, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20,
+0x50, 0x65, 0x73, 0x6f, 0x44, 0x65, 0x72, 0x68, 0x65, 0x6d, 0x20, 0x55,
+0x6d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x69, 0x62f, 0x6cc, 0x646, 0x627, 0x631,
+0x6cc, 0x20, 0x639, 0x6ce, 0x631, 0x627, 0x642, 0x6cc, 0x695, 0x6cc, 0x627, 0x6b5,
+0x6cc, 0x20, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x6cc, 0xd804, 0xdd1d, 0xd804, 0xdd01,
+0xd804, 0xdd23, 0xd804, 0xdd18, 0xd804, 0xdd2c, 0xd804, 0xdd25, 0xd804, 0xdd28, 0x20, 0xd804,
+0xdd11, 0xd804, 0xdd2c, 0xd804, 0xdd0b, 0xd804, 0xdd03, 0xd804, 0xdd28, 0xd804, 0xdd1a, 0xd804,
+0xdd34, 0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd20, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x20,
+0xd804, 0xdd22, 0xd804, 0xdd2a, 0xd804, 0xdd1b, 0xd804, 0xdd28, 0x420, 0x43e, 0x441, 0x441,
+0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x55, 0x53, 0x20, 0x13a0, 0x13d5,
+0x13b3, 0x45, 0x73, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79,
+0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e2f, 0x5143, 0x6fb3, 0x95e8,
+0x5e01, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x6fb3, 0x9580, 0x5143, 0x65b0, 0x53f0, 0x5e63, 0x440,
+0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x457, 0x439, 0x20, 0x440,
+0xa64b, 0x301, 0x431, 0x43b, 0x44c, 0x420, 0x430, 0x4ab, 0x4ab, 0x435, 0x439, 0x20,
+0x442, 0x435, 0x43d, 0x43a, 0x4d7, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b,
+0x6f, 0x72, 0x75, 0x6e, 0x61, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b,
+0x72, 0x6f, 0x6e, 0x65, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x20, 0x930, 0x92a,
+0x947, 0x93d, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
+0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b,
+0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41,
+0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
+0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61,
+0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0xf51,
+0xf44, 0xf74, 0xf63, 0xf0b, 0xf40, 0xfb2, 0xf58, 0x53, 0x68, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61,
+0x55, 0x53, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x45, 0x61, 0x73,
+0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20,
+0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
+0x6c, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x42,
+0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20,
+0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65,
+0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x42, 0x65, 0x72, 0x6d, 0x75,
+0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x42,
+0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x50, 0x75, 0x6c,
+0x61, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x46,
+0x72, 0x61, 0x6e, 0x63, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20,
+0x46, 0x72, 0x61, 0x6e, 0x63, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61,
+0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x61, 0x79, 0x6d,
+0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61,
+0x6c, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x44,
+0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x65, 0x45,
+0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x4e, 0x61, 0x6b, 0x66,
+0x61, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x4c, 0x69, 0x6c, 0x61, 0x6e,
+0x67, 0x65, 0x6e, 0x69, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64,
+0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x50, 0x6f, 0x75,
+0x6e, 0x64, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x44,
+0x61, 0x6c, 0x61, 0x73, 0x69, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61,
+0x6e, 0x20, 0x43, 0x65, 0x64, 0x69, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c,
+0x74, 0x61, 0x72, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x4b, 0x20,
+0x50, 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65,
+0x73, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x48, 0x6f, 0x6e,
+0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65,
+0x65, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x6e, 0x20,
+0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c,
+0x69, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x53, 0x68, 0x65, 0x6b, 0x65, 0x6c,
+0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x53, 0x68,
+0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64,
+0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20,
+0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61,
+0x73, 0x79, 0x20, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x4d, 0x61, 0x6c,
+0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61,
+0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x69,
+0x6e, 0x67, 0x67, 0x69, 0x74, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x69,
+0x61, 0x6e, 0x20, 0x52, 0x75, 0x66, 0x69, 0x79, 0x61, 0x61, 0x4d, 0x61,
+0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65,
+0x65, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e,
+0x20, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74,
+0x61, 0x6e, 0x69, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x50, 0x61, 0x70,
+0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65,
+0x61, 0x6e, 0x20, 0x4b, 0x69, 0x6e, 0x61, 0x52, 0x77, 0x61, 0x6e, 0x64,
+0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x53, 0x74, 0x20, 0x48,
+0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x53,
+0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x54, 0x61, 0x6c, 0x61, 0x53, 0x65,
+0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x52, 0x75,
+0x70, 0x65, 0x65, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65,
+0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x53,
+0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x44, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e,
+0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e,
+0x20, 0x47, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x6f, 0x6c, 0x6f,
+0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20,
+0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
+0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75,
+0x6e, 0x64, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50,
+0x6f, 0x75, 0x6e, 0x64, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20,
+0x4b, 0x72, 0x6f, 0x6e, 0x61, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x46,
+0x72, 0x61, 0x6e, 0x63, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61,
+0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x54, 0x6f,
+0x6e, 0x67, 0x61, 0x6e, 0x20, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61,
+0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54,
+0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c,
+0x6c, 0x69, 0x6e, 0x67, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x41,
+0x72, 0x61, 0x62, 0x20, 0x45, 0x6d, 0x69, 0x72, 0x61, 0x74, 0x65, 0x73,
+0x20, 0x44, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x42, 0x72, 0x69, 0x74, 0x69,
+0x73, 0x68, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6e, 0x75,
+0x61, 0x74, 0x75, 0x20, 0x56, 0x61, 0x74, 0x75, 0x5a, 0x61, 0x6d, 0x62,
+0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x67, 0x68,
+0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x263, 0x65, 0x74, 0x6f,
+0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67,
+0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
+0x42, 0x43, 0x45, 0x41, 0x4f, 0x46, 0x259, 0x6c, 0xe1, 0x14b, 0x20, 0x43,
+0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x64, 0x6f, 0x6e,
+0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x50, 0x69, 0x73, 0x6f,
+0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61,
+0x73, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72,
+0x69, 0x65, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41,
+0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45,
+0x41, 0x43, 0x29, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61,
+0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
+0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74,
+0x69, 0x65, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65,
+0x6e, 0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74,
+0x69, 0x65, 0x6e, 0x6e, 0x65, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x20,
+0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x6f, 0x75, 0x67, 0x75,
+0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e,
+0x69, 0x65, 0x6e, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x6d, 0x61,
+0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x64, 0x69, 0x72,
+0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61,
+0x69, 0x73, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73,
+0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x6c,
+0x69, 0x76, 0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e,
+0x65, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73,
+0x69, 0x65, 0x6e, 0x76, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75,
+0x61, 0x74, 0x75, 0x61, 0x6e, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75, 0x20,
+0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f,
+0xd83a, 0xdd0a, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0x20, 0xd83a,
+0xdd05, 0xd83a, 0xdd0a, 0xd83a, 0xdd00, 0x20, 0xd83a, 0xdd16, 0xd83a, 0xdd2d, 0xd83a, 0xdd45,
+0xd83a, 0xdd2a, 0xd83a, 0xdd32, 0xd83a, 0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd32, 0xd83a, 0xdd3a,
+0xd83a, 0xdd2b, 0x20, 0xd83a, 0xdd00, 0xd83a, 0xdd2c, 0xd83a, 0xdd2a, 0xd83a, 0xdd2d, 0xd83a,
+0xdd33, 0xd83a, 0xdd22, 0xd83a, 0xdd0a, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a,
+0xdd32, 0x20, 0xd83a, 0xdd1a, 0xd83a, 0xdd35, 0xd83a, 0xdd26, 0xd83a, 0xdd2e, 0xd83a, 0xdd45,
+0xd83a, 0xdd2a, 0xd83a, 0xdd2d, 0x20, 0xd83a, 0xdd00, 0xd83a, 0xdd2c, 0xd83a, 0xdd2a, 0xd83a,
+0xdd2d, 0xd83a, 0xdd33, 0xd83a, 0xdd2d, 0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0xd83a,
+0xdd01, 0xd83a, 0xdd22, 0xd83a, 0xdd24, 0xd83a, 0xdd22, 0xd83a, 0xdd27, 0xd83a, 0xdd2d, 0x20,
+0xd83a, 0xdd18, 0xd83a, 0xdd22, 0xd83a, 0xdd25, 0xd83a, 0xdd26, 0xd83a, 0xdd2d, 0xd83a, 0xdd32,
+0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0xd83a, 0xdd05, 0xd83a, 0xdd2d, 0xd83a, 0xdd23, 0xd83a, 0xdd2d,
+0x20, 0xd83a, 0xdd18, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0xd83a,
+0xdd33, 0xd83a, 0xdd2e, 0xd83a, 0xdd0a, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a,
+0xdd32, 0x20, 0xd83a, 0xdd18, 0xd83a, 0xdd2d, 0xd83a, 0xdd32, 0xd83a, 0xdd2b, 0xd83a, 0xdd32,
+0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0xd83a, 0xdd01, 0xd83a, 0xdd22, 0xd83a, 0xdd24, 0xd83a, 0xdd22,
+0x20, 0xd83a, 0xdd02, 0xd83a, 0xdd2d, 0xd83a, 0xdd26, 0xd83a, 0xdd2b, 0xd83a, 0xdd2a, 0xd83a,
+0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0xd83a,
+0xdd13, 0xd83a, 0xdd3a, 0xd83a, 0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22, 0x20, 0xd83a, 0xdd03,
+0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd2d, 0xd83a, 0xdd3c, 0xd83a, 0xdd22, 0xd83a, 0xdd32,
+0xd83a, 0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a, 0xdd2e,
+0xd83a, 0xdd10, 0xd83a, 0xdd22, 0xd83a, 0xdd34, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0x20, 0xd83a,
+0xdd10, 0xd83a, 0xdd22, 0xd83a, 0xdd36, 0xd83a, 0xdd2d, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a,
+0xdd34, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0xd83a, 0xdd02, 0xd83a,
+0xdd2b, 0xd83a, 0xdd34, 0xd83a, 0xdd2e, 0xd83a, 0xdd32, 0x20, 0xd83a, 0xdd05, 0xd83a, 0xdd2b,
+0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a, 0xdd24, 0xd83a, 0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22,
+0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x69,
+0x20, 0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x45, 0x41, 0x43,
+0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x20, 0x47, 0x61, 0x6d, 0x6d, 0x62,
+0x69, 0x44, 0x6f, 0x6c, 0x61, 0x61, 0x72, 0x20, 0x4c, 0x69, 0x62, 0x65,
+0x72, 0x69, 0x79, 0x61, 0x61, 0x55, 0x67, 0x69, 0x79, 0x79, 0x61, 0x20,
+0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x4e, 0x61, 0x79, 0x72,
+0x61, 0x61, 0x20, 0x4e, 0x69, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61,
+0x4c, 0x65, 0x77, 0x6f, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x72, 0x61, 0x61,
+0x20, 0x4c, 0x69, 0x79, 0x6f, 0x6e, 0x50, 0x75, 0x6e, 0x6e, 0x64, 0x20,
+0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x53, 0x69, 0x6c,
+0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x79, 0x61, 0x20, 0x59, 0x75, 0x67,
+0x61, 0x6e, 0x64, 0x61, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20,
+0x10da, 0x10d0, 0x10e0, 0x10d8, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65,
+0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x395, 0x3c5, 0x3c1,
+0x3ce, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf,
+0xaaf, 0xabe, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x72, 0x20, 0x4e, 0x61, 0x6a,
+0x65, 0x72, 0x69, 0x79, 0x61, 0x646, 0x64e, 0x64a, 0x652, 0x631, 0x64e, 0x53,
+0x69, 0x64, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x47, 0x68, 0x61, 0x6e, 0x61,
+0x4b, 0x75, 0x257, 0x69, 0x6e, 0x20, 0x53, 0x65, 0x66, 0x61, 0x20, 0x6e,
+0x61, 0x20, 0x41, 0x66, 0x69, 0x72, 0x6b, 0x61, 0x20, 0x54, 0x61, 0x20,
+0x59, 0x61, 0x6d, 0x6d, 0x61, 0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9,
+0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e,
+0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e,
+0x74, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3,
+0x6e, 0x61, 0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x52, 0x75, 0x70, 0x69, 0x61,
+0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x50,
+0x75, 0x6e, 0x74, 0x20, 0x53, 0x74, 0x65, 0x69, 0x72, 0x6c, 0x69, 0x6e,
+0x67, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76, 0x69, 0x7a,
+0x7a, 0x65, 0x72, 0x6f, 0x65e5, 0x672c, 0x5186, 0x41, 0x331, 0x6e, 0x61, 0x69,
+0x72, 0x61, 0x73, 0x65, 0x65, 0x66, 0x61, 0x20, 0x79, 0x61, 0x74, 0x69,
+0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x53, 0x6b, 0x75, 0x64, 0x75, 0x20,
+0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75,
+0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61, 0x79,
+0x72, 0x69, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x64,
+0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b,
+0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67,
+0x69, 0x74, 0x61, 0x62, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79,
+0x61, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x65, 0x6e, 0x79, 0x61, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20,
+0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x6c1, 0x650, 0x646, 0x62f, 0x64f, 0x633,
+0x62a, 0x672, 0x646, 0x6cd, 0x20, 0x631, 0x6c4, 0x67e, 0x64e, 0x6d2, 0x907, 0x902,
+0x921, 0x93f, 0x92f, 0x928, 0x20, 0x930, 0x942, 0x92a, 0x940, 0x49a, 0x430, 0x437,
+0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435,
+0x441, 0x456, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787,
+0x17b6, 0x43, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x65, 0x6e, 0x79, 0x61, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0xc911,
+0xad6d, 0x20, 0xc704, 0xc548, 0xd654, 0xc870, 0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758,
+0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x43, 0x46, 0x41,
+0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f,
+0x29, 0x6c, 0xee, 0x72, 0x65, 0x79, 0xea, 0x20, 0x74, 0x69, 0x72, 0x6b,
+0xee, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45,
+0x41, 0x43, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d,
+0x20, 0x441, 0x43e, 0x43c, 0x443, 0x53, 0x68, 0x69, 0x6c, 0xed, 0x69, 0x6e,
+0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61,
+0x6e, 0xed, 0x61, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x65, 0x69,
+0x72, 0x6f, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61,
+0x20, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61,
+0x20, 0x79, 0x61, 0x20, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x46, 0x61,
+0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45,
+0x41, 0x43, 0x45, 0x75, 0x72, 0x61, 0x73, 0x4e, 0x66, 0x61, 0x6c, 0x61,
+0x6e, 0x67, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x75,
+0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4b,
+0x65, 0x6e, 0x79, 0x61, 0x53, 0x69, 0x72, 0x69, 0x6e, 0x6a, 0x69, 0x20,
+0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x41c, 0x430, 0x43a, 0x435,
+0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440,
+0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0xd07, 0xd28, 0xd4d, 0xd24,
+0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x52, 0x69, 0x6e, 0x67, 0x67,
+0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x62f,
+0x648, 0x644, 0x631, 0x20, 0x628, 0x631, 0x648, 0x646, 0x64a, 0x631, 0x64a, 0x6a0,
+0x762, 0x64a, 0x62a, 0x20, 0x645, 0x644, 0x64a, 0x633, 0x64a, 0x627, 0x44, 0x6f,
+0x6c, 0x61, 0x72, 0x20, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x44, 0x6f,
+0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72,
+0x61, 0x65, 0x77, 0x72, 0x6f, 0x987, 0x9a8, 0x9cd, 0x9a6, 0x9bf, 0x9af, 0x9bc,
+0x9be, 0x9a8, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9c0, 0x54, 0x101, 0x72, 0x61, 0x20,
+0x6f, 0x20, 0x41, 0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f, 0x61, 0x49, 0x72,
+0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x4b,
+0x65, 0x6e, 0x79, 0x61, 0x49, 0x72, 0x6f, 0x70, 0x69, 0x79, 0x69, 0x61,
+0x6e, 0xed, 0x20, 0x65, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69,
+0x61, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x73,
+0x68, 0x69, 0x72, 0xe8, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x20, 0x442,
+0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x44e, 0x430, 0x43d, 0x44c, 0x1833, 0x1825, 0x182c,
+0x1825, 0x1837, 0x1822, 0x182d, 0x180c, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x20, 0x6d,
+0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x73, 0x6f, 0x6c, 0x61, 0x69,
+0x20, 0x42, 0x45, 0x41, 0x43, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
+0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x69, 0x928, 0x947, 0x92a, 0x93e,
+0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x92d, 0x93e,
+0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e,
+0x66, 0x65, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x46, 0x25b, 0x6c,
+0xe2, 0x14b, 0x4e, 0x61, 0x69, 0x6a, 0xed, 0x72, 0x69, 0xe1, 0x20, 0x4e,
+0x61, 0xed, 0x72, 0x61, 0x7d6, 0x7cc, 0x7ec, 0x7e3, 0x7cd, 0x7ec, 0x7de, 0x7ca,
+0x20, 0x7df, 0x7ce, 0x7ec, 0x20, 0x7df, 0x7ca, 0x7eb, 0x20, 0x7dd, 0x7ca, 0x7d9,
+0x7ca, 0x7f2, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75,
+0x76, 0x64, 0x6e, 0x6f, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b,
+0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x44, 0x6f, 0x6c, 0x61, 0x20, 0x79,
+0x61, 0x73, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x6e,
+0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72,
+0xb2d, 0xb3e, 0xb30, 0xb24, 0xb40, 0xb5f, 0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e,
+0x49, 0x74, 0x6f, 0x6f, 0x70, 0x68, 0x69, 0x79, 0x61, 0x61, 0x20, 0x42,
+0x69, 0x72, 0x72, 0x69, 0x69, 0x41b, 0x430, 0x440, 0x421, 0x43e, 0x43c, 0x46,
+0x6c, 0x6f, 0x72, 0x69, 0x6e, 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x6e, 0x20,
+0x64, 0x69, 0x20, 0x41, 0x72, 0x75, 0x62, 0x61, 0x627, 0x641, 0x63a, 0x627,
+0x646, 0x6cd, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cd, 0x20, 0x6a9,
+0x644, 0x62f, 0x627, 0x631, 0x647, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc,
+0x631, 0x627, 0x646, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641,
+0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x7a, 0x142, 0x6f, 0x74, 0x79,
+0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x52, 0x65, 0x61, 0x6c, 0x20,
+0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x6b, 0x77,
+0x61, 0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e,
+0x6f, 0x65, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61, 0x62, 0x6f,
+0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x66, 0x72, 0x61,
+0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41,
+0x43, 0x29, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41,
+0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x70, 0x61, 0x74, 0x61,
+0x63, 0x61, 0x20, 0x6d, 0x61, 0x63, 0x61, 0x65, 0x6e, 0x73, 0x65, 0x6d,
+0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d,
+0x62, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x64, 0x6f, 0x62, 0x72, 0x61, 0x20,
+0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20,
+0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x64, 0xf3,
+0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61,
+0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0xa2d, 0xa3e,
+0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x631, 0x648, 0x67e,
+0x626, 0x6cc, 0x6c1, 0x53, 0x6f, 0x6c, 0x20, 0x50, 0x65, 0x72, 0x75, 0x61,
+0x6e, 0x6f, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x44,
+0xf3, 0x6c, 0x61, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x6e, 0x6f, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65,
+0x73, 0x63, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76,
+0x65, 0x6e, 0x65, 0x73, 0x63, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73,
+0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x68, 0x65, 0x6c, 0x65, 0x72, 0x69,
+0x20, 0x73, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61,
+0x49, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x72, 0x79, 0x2019,
+0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x440, 0x43e, 0x441, 0x441,
+0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c,
+0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20,
+0x440, 0x443, 0x431, 0x43b, 0x44c, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a,
+0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x43a, 0x438, 0x440, 0x433,
+0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x43c, 0x43e,
+0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439,
+0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433,
+0x440, 0x438, 0x432, 0x43d, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b,
+0x439, 0x430, 0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439,
+0x430, 0x4e, 0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x65,
+0x6c, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x66, 0x61, 0x72, 0xe2, 0x6e,
+0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43,
+0x29, 0x49, 0x68, 0x65, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61,
+0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x92d, 0x93e, 0x930, 0x924, 0x940,
+0x92f, 0x20, 0x930, 0x942, 0x92a, 0x94d, 0x92f, 0x915, 0x92e, 0x94d, 0x1c65, 0x1c64,
+0x1c67, 0x1c5a, 0x1c5b, 0x20, 0x1c68, 0x1c6e, 0x1c71, 0x1c5f, 0x1c5c, 0x20, 0x1c74, 0x1c5f,
+0x1c60, 0x1c5f, 0xe8, 0x75, 0x72, 0x6f, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61,
+0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69,
+0x71, 0x75, 0x65, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438,
+0x43d, 0x430, 0x440, 0x411, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x445,
+0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20,
+0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d,
+0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x415, 0x432, 0x440, 0x43e, 0x45,
+0x76, 0x72, 0x6f, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69,
+0x6e, 0x61, 0x72, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20,
+0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x44,
+0x6f, 0x72, 0x61, 0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x6b, 0x61, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631,
+0x67e, 0x64a, 0x939, 0x93f, 0x902, 0x926, 0x941, 0x938, 0x94d, 0x924, 0x93e, 0x928,
+0x940, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x94b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3,
+0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd,
+0x65, 0x76, 0x72, 0x6f, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b,
+0x61, 0x20, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x79, 0x61,
+0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74,
+0x69, 0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62,
+0x62, 0x69, 0x79, 0x61, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b,
+0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x70, 0x65, 0x73, 0x6f, 0x20,
+0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x64, 0xf3, 0x6c,
+0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x62,
+0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x72, 0x65, 0x61, 0x6c,
+0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x50, 0x65,
+0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x70, 0x65,
+0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x6e,
+0x6f, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61,
+0x72, 0x72, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x70, 0x65, 0x73, 0x6f,
+0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x70, 0x65, 0x73, 0x6f, 0x20,
+0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x64, 0xf3,
+0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e,
+0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f,
+0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x71, 0x75,
+0x65, 0x74, 0x7a, 0x61, 0x6c, 0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x61,
+0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x70, 0x65,
+0x73, 0x6f, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x63,
+0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72,
+0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x62, 0x61, 0x6c, 0x62, 0x6f,
+0x61, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x67, 0x75,
+0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72, 0x61, 0x67, 0x75,
+0x61, 0x79, 0x6f, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61,
+0x6e, 0x6f, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70,
+0x69, 0x6e, 0x6f, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67,
+0x75, 0x61, 0x79, 0x6f, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20,
+0x73, 0x6f, 0x62, 0x65, 0x72, 0x61, 0x6e, 0x6f, 0x2d30, 0x2d37, 0x2d54, 0x2d49,
+0x2d4e, 0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x52, 0x75,
+0x70, 0x65, 0x65, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0xe9, 0x73, 0x69,
+0x61, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67,
+0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x73,
+0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x53,
+0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61,
+0x6e, 0x6b, 0x65, 0x61, 0x64, 0x72, 0x69, 0x6d, 0x20, 0x6e, 0x20, 0x6c,
+0x6d, 0x263, 0x72, 0x69, 0x62, 0x421, 0x43e, 0x43c, 0x43e, 0x43d, 0x4e3, 0xb87,
+0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd,
+0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99,
+0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd,
+0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0xb87, 0xbb2,
+0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x70,
+0x69, 0x6c, 0x61, 0x20, 0x54, 0x61, 0x69, 0x77, 0x61, 0x6e, 0x420, 0x43e,
+0x441, 0x441, 0x438, 0x44f, 0x20, 0x441, 0x443, 0x43c, 0x44b, 0xc2d, 0xc3e, 0xc30,
+0xc24, 0xc26, 0xc47, 0xc36, 0x20, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x41,
+0x6e, 0x67, 0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b,
+0x2019, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x41, 0x6e, 0x67, 0x6f,
+0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b, 0x2019, 0x20, 0x4b,
+0x65, 0x6e, 0x79, 0x61, 0xe1a, 0xe32, 0xe17, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53,
+0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62,
+0xf0b, 0x1293, 0x1255, 0x134b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x20,
+0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72,
+0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x54, 0xfc, 0x72, 0x6b,
+0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79, 0x4e, 0x65,
+0x72, 0x61, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430,
+0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x67e, 0x627, 0x6a9, 0x633, 0x62a,
+0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x628, 0x6be, 0x627,
+0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x62c, 0x6c7, 0x6ad,
+0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x4f, 0x2018, 0x7a, 0x62,
+0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d,
+0x69, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20,
+0x441, 0x45e, 0x43c, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x20, 0xa55c, 0xa55e, 0xa54c, 0x4c,
+0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x20, 0x44, 0x61, 0x6c, 0x61,
+0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61,
+0x6d, 0x50, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69,
+0x6e, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x626, 0x20, 0x631, 0x648,
+0x67e, 0x6cc, 0x627, 0x648, 0x6af, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x626,
+0x20, 0x627, 0x648, 0x6af, 0x627, 0x646, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646,
+0x626, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20,
+0x43, 0x46, 0x41, 0x20, 0x62, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b,
+0x20, 0x53, 0x6f, 0x77, 0x77, 0x75, 0x2d, 0x6a, 0x61, 0x6e, 0x74, 0x49,
+0x52, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x79, 0x61, 0x73, 0x65, 0x4d, 0x7a,
+0x61, 0x6e, 0x74, 0x73, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61,
+0x4e, 0xe1, 0xed, 0x72, 0xe0, 0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72,
+0xed, 0xe0, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x73, 0xec, 0x20, 0xec, 0x77,
+0x254, 0x300, 0x2d, 0x6f, 0x6f, 0x72, 0xf9, 0x6e, 0x20, 0x41, 0x66, 0xed,
+0x72, 0xed, 0x6b, 0xe0, 0x79, 0x69, 0x6e, 0x7a, 0x6d, 0x69, 0x6e, 0x7a,
+0x62, 0x69, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x4d, 0x72,
+0x61, 0x73, 0x69, 0x72, 0x20, 0x52, 0x65, 0x6a, 0x61, 0x72, 0x52, 0x65,
+0x61, 0x75, 0x20, 0x42, 0x72, 0x61, 0x73, 0x69, 0x75, 0x77, 0x61, 0x72,
+0x61, 0x50, 0x65, 0x73, 0x6f, 0x20, 0x4b, 0x75, 0x72, 0x169, 0x62, 0x69,
+0x79, 0x61, 0x77, 0x61, 0x72, 0x61, 0x42, 0x75, 0x72, 0x69, 0x77, 0x61,
+0x72, 0x69, 0x20, 0x57, 0x65, 0x6e, 0x65, 0x73, 0x75, 0x65, 0x72, 0x61,
+0x77, 0x61, 0x72, 0x61, 0x50, 0xe1, 0x6b, 0x65, 0x73, 0x74, 0xe1, 0x6e,
+0x69, 0x20, 0x72, 0x75, 0x70, 0x69, 0x47, 0x61, 0x72, 0x269, 0x256, 0x6f,
+0x6e, 0x74, 0x1dd, 0x6e, 0x61, 0x20, 0x67, 0x269, 0x74, 0x65, 0x14b, 0x73,
+0x68, 0x69, 0x6c, 0x65, 0x6c, 0x61, 0x14b, 0x20, 0x6b, 0x61, 0x73, 0x25b,
+0x25b, 0x66, 0x61, 0x92d, 0x93e, 0x930, 0x924, 0x947, 0x20, 0x926, 0x93e, 0x20,
+0x930, 0x941, 0x92a, 0x92f, 0x93e
};
-static const char16_t currency_format_data[] = {
-0x25, 0x31, 0x25, 0x32, 0x25, 0x32, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25,
-0x31, 0xa0, 0x25, 0x32, 0x28, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x29, 0x28, 0x25, 0x31, 0x25, 0x32, 0x29, 0x28, 0x25, 0x32,
-0xa0, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0x25, 0x31, 0x25, 0x32, 0x2212, 0x25, 0x31, 0x200e, 0x25, 0x32, 0xa0, 0x25, 0x31,
-0x200e, 0x28, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31
+static constexpr char16_t currency_format_data[] = {
+0x25, 0x31, 0x25, 0x32, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x28, 0x25, 0x32,
+0x25, 0x31, 0x29, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x28, 0x25, 0x31, 0xa0,
+0x25, 0x32, 0x29, 0x200f, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x61c, 0x25, 0x31,
+0x25, 0x32, 0x28, 0x61c, 0x25, 0x31, 0x25, 0x32, 0x29, 0x28, 0x25, 0x31,
+0x25, 0x32, 0x29, 0x28, 0x25, 0x31, 0x29, 0xa0, 0x25, 0x32, 0x28, 0x25,
+0x32, 0xa0, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0x25, 0x31, 0x200f, 0x25,
+0x31, 0xa0, 0x200f, 0x25, 0x32, 0x200f, 0x200e, 0x2d, 0x25, 0x31, 0xa0, 0x200f,
+0x25, 0x32, 0x25, 0x32, 0xa0, 0x2d, 0x25, 0x31, 0x25, 0x32, 0x2212, 0x25,
+0x31, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31, 0x200e, 0x25, 0x32, 0xa0, 0x25,
+0x31, 0x200e, 0x28, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x29, 0x25, 0x31, 0x202f,
+0x25, 0x32
};
-static const char16_t endonyms_data[] = {
-0x4f, 0x72, 0x6f, 0x6d, 0x6f, 0x6f, 0x49, 0x74, 0x6f, 0x6f, 0x70, 0x68, 0x69, 0x79, 0x61, 0x61, 0x4b, 0x65, 0x65, 0x6e,
-0x69, 0x79, 0x61, 0x61, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x53, 0x75, 0x69, 0x64, 0x2d, 0x41, 0x66,
-0x72, 0x69, 0x6b, 0x61, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0xeb, 0x73, 0x68, 0x71, 0x69, 0x70, 0x53, 0x68, 0x71, 0x69,
-0x70, 0xeb, 0x72, 0x69, 0x4d, 0x61, 0x71, 0x65, 0x64, 0x6f, 0x6e, 0x69, 0x61, 0x20, 0x65, 0x20, 0x56, 0x65, 0x72, 0x69,
-0x75, 0x74, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0xeb, 0x12a0, 0x121b, 0x122d, 0x129b, 0x12a2, 0x1275, 0x12ee, 0x1335, 0x12eb, 0x627, 0x644, 0x639,
-0x631, 0x628, 0x64a, 0x629, 0x645, 0x635, 0x631, 0x627, 0x644, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x627, 0x644, 0x628, 0x62d, 0x631, 0x64a,
-0x646, 0x62a, 0x634, 0x627, 0x62f, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a,
-0x625, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x627, 0x627, 0x644, 0x639, 0x631, 0x627, 0x642, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644,
-0x627, 0x644, 0x623, 0x631, 0x62f, 0x646, 0x627, 0x644, 0x643, 0x648, 0x64a, 0x62a, 0x644, 0x628, 0x646, 0x627, 0x646, 0x644, 0x64a, 0x628,
-0x64a, 0x627, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x627, 0x627, 0x644, 0x645, 0x63a, 0x631, 0x628, 0x639, 0x64f, 0x645,
-0x627, 0x646, 0x627, 0x644, 0x623, 0x631, 0x627, 0x636, 0x64a, 0x20, 0x627, 0x644, 0x641, 0x644, 0x633, 0x637, 0x64a, 0x646, 0x64a, 0x629,
-0x642, 0x637, 0x631, 0x627, 0x644, 0x645, 0x645, 0x644, 0x643, 0x629, 0x20, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x627,
-0x644, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x629, 0x627, 0x644, 0x635, 0x648, 0x645, 0x627, 0x644, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627,
-0x646, 0x633, 0x648, 0x631, 0x64a, 0x627, 0x62a, 0x648, 0x646, 0x633, 0x627, 0x644, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x627,
-0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x645, 0x62a, 0x62d, 0x62f, 0x629, 0x627, 0x644, 0x635, 0x62d, 0x631, 0x627,
-0x621, 0x20, 0x627, 0x644, 0x63a, 0x631, 0x628, 0x64a, 0x629, 0x627, 0x644, 0x64a, 0x645, 0x646, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627,
-0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x641, 0x635, 0x62d, 0x649,
-0x20, 0x627, 0x644, 0x62d, 0x62f, 0x64a, 0x62b, 0x629, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645, 0x570, 0x561, 0x575, 0x565, 0x580, 0x565,
-0x576, 0x540, 0x561, 0x575, 0x561, 0x57d, 0x57f, 0x561, 0x576, 0x985, 0x9b8, 0x9ae, 0x9c0, 0x9af, 0x9bc, 0x9be, 0x9ad, 0x9be, 0x9f0, 0x9a4,
-0x61, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e,
-0x430, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x410, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d,
-0x65, 0x75, 0x73, 0x6b, 0x61, 0x72, 0x61, 0x45, 0x73, 0x70, 0x61, 0x69, 0x6e, 0x69, 0x61, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be,
-0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0xf62, 0xfab, 0xf7c, 0xf44, 0xf0b, 0xf41, 0xf60, 0xf56,
-0xfb2, 0xf74, 0xf42, 0x62, 0x72, 0x65, 0x7a, 0x68, 0x6f, 0x6e, 0x65, 0x67, 0x46, 0x72, 0x61, 0xf1, 0x73, 0x431, 0x44a, 0x43b,
-0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x438, 0x44f, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c,
-0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x44f, 0x411, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x44c, 0x1781, 0x17d2,
-0x1798, 0x17c2, 0x179a, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x63, 0x61, 0x74, 0x61, 0x6c, 0xe0, 0x45, 0x73, 0x70, 0x61,
-0x6e, 0x79, 0x61, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x49, 0x74, 0xe0, 0x6c,
-0x69, 0x61, 0x7b80, 0x4f53, 0x4e2d, 0x6587, 0x4e2d, 0x56fd, 0x4e2d, 0x56fd, 0x9999, 0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d, 0x56fd, 0x6fb3,
-0x95e8, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x65b0, 0x52a0, 0x5761, 0x7e41, 0x9ad4, 0x4e2d, 0x6587, 0x4e2d, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c,
-0x653f, 0x5340, 0x4e2d, 0x570b, 0x6fb3, 0x9580, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x53f0, 0x7063, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b,
-0x69, 0x48, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20, 0x69, 0x20, 0x48, 0x65, 0x72,
-0x63, 0x65, 0x67, 0x6f, 0x76, 0x69, 0x6e, 0x61, 0x10d, 0x65, 0x161, 0x74, 0x69, 0x6e, 0x61, 0x10c, 0x65, 0x73, 0x6b, 0x6f,
-0x64, 0x61, 0x6e, 0x73, 0x6b, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x47, 0x72, 0xf8, 0x6e, 0x6c, 0x61, 0x6e, 0x64,
-0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x41, 0x72, 0x75, 0x62, 0x61, 0x42, 0x65, 0x6c, 0x67, 0x69,
-0xeb, 0x43, 0x75, 0x72, 0x61, 0xe7, 0x61, 0x6f, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x61, 0x72, 0x69,
-0x62, 0x69, 0x73, 0x63, 0x68, 0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x2d,
-0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c,
-0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x6e, 0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x41, 0x6e,
-0x74, 0x69, 0x67, 0x75, 0x61, 0x20, 0x26, 0x20, 0x42, 0x61, 0x72, 0x62, 0x75, 0x64, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72,
-0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x75, 0x73, 0x74, 0x72, 0x69, 0x61,
-0x42, 0x61, 0x68, 0x61, 0x6d, 0x61, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69,
-0x75, 0x6d, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x42, 0x6f, 0x74, 0x73, 0x77,
-0x61, 0x6e, 0x61, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x4f, 0x63,
-0x65, 0x61, 0x6e, 0x20, 0x54, 0x65, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69,
-0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67,
-0x6c, 0x69, 0x73, 0x68, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c,
-0x61, 0x6e, 0x64, 0x73, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64,
-0x43, 0x6f, 0x63, 0x6f, 0x73, 0x20, 0x28, 0x4b, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x49, 0x73, 0x6c, 0x61,
-0x6e, 0x64, 0x73, 0x43, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x79, 0x70, 0x72, 0x75,
-0x73, 0x44, 0x65, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x45, 0x72, 0x69, 0x74,
-0x72, 0x65, 0x61, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x46,
-0x69, 0x6a, 0x69, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x47, 0x61,
-0x6d, 0x62, 0x69, 0x61, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x79, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x47, 0x69, 0x62, 0x72,
-0x61, 0x6c, 0x74, 0x61, 0x72, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x47, 0x75, 0x61, 0x6d, 0x47, 0x75, 0x79, 0x61,
-0x6e, 0x61, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e,
-0x61, 0x49, 0x72, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63,
-0x61, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b, 0x69, 0x72, 0x69, 0x62, 0x61, 0x74, 0x69, 0x4c, 0x65, 0x73, 0x6f, 0x74, 0x68,
-0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x4d, 0x61, 0x63, 0x61, 0x6f, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68,
-0x69, 0x6e, 0x61, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x4d,
-0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x6c,
-0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x4d, 0x69, 0x63,
-0x72, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x4e, 0x61, 0x6d,
-0x69, 0x62, 0x69, 0x61, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x4e, 0x69,
-0x75, 0x65, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x6f, 0x72, 0x74,
-0x68, 0x65, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x61, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e,
-0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73,
-0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x75, 0x65, 0x72,
-0x74, 0x6f, 0x20, 0x52, 0x69, 0x63, 0x6f, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x74, 0x20, 0x4b, 0x69, 0x74, 0x74,
-0x73, 0x20, 0x26, 0x20, 0x4e, 0x65, 0x76, 0x69, 0x73, 0x53, 0x74, 0x20, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x53, 0x74, 0x20,
-0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x20, 0x26, 0x20, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73,
-0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f,
-0x6e, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x61, 0x53,
-0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
-0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x53, 0x74, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x53, 0x75, 0x64, 0x61, 0x6e,
-0x45, 0x73, 0x77, 0x61, 0x74, 0x69, 0x6e, 0x69, 0x53, 0x77, 0x65, 0x64, 0x65, 0x6e, 0x53, 0x77, 0x69, 0x74, 0x7a, 0x65,
-0x72, 0x6c, 0x61, 0x6e, 0x64, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x54, 0x6f, 0x6b, 0x65, 0x6c, 0x61, 0x75,
-0x54, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61,
-0x67, 0x6f, 0x54, 0x75, 0x72, 0x6b, 0x73, 0x20, 0x26, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x49, 0x73, 0x6c,
-0x61, 0x6e, 0x64, 0x73, 0x54, 0x75, 0x76, 0x61, 0x6c, 0x75, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x55, 0x6e, 0x69, 0x74,
-0x65, 0x64, 0x20, 0x41, 0x72, 0x61, 0x62, 0x20, 0x45, 0x6d, 0x69, 0x72, 0x61, 0x74, 0x65, 0x73, 0x42, 0x72, 0x69, 0x74,
-0x69, 0x73, 0x68, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x4b, 0x69,
-0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x4f, 0x75, 0x74, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x49,
-0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68,
-0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x55, 0x2e, 0x53, 0x2e, 0x20,
-0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61,
-0x5a, 0x69, 0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x20, 0x47, 0x61, 0x72, 0x63, 0x69, 0x61,
-0x49, 0x73, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6e, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x53, 0x6f, 0x75,
-0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53, 0x69, 0x6e, 0x74, 0x20, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e,
-0x57, 0x6f, 0x72, 0x6c, 0x64, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x65, 0x73, 0x70, 0x65, 0x72, 0x61, 0x6e, 0x74, 0x6f,
-0x4d, 0x6f, 0x6e, 0x64, 0x6f, 0x65, 0x65, 0x73, 0x74, 0x69, 0x45, 0x65, 0x73, 0x74, 0x69, 0x66, 0xf8, 0x72, 0x6f, 0x79,
-0x73, 0x6b, 0x74, 0x46, 0xf8, 0x72, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x75, 0x6f, 0x6d, 0x69, 0x53, 0x75, 0x6f, 0x6d, 0x69,
-0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x6c, 0x67, 0xe9, 0x72, 0x69,
-0x65, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x71, 0x75, 0x65, 0x42, 0xe9, 0x6e, 0x69, 0x6e, 0x42, 0x75, 0x72, 0x6b, 0x69, 0x6e,
-0x61, 0x20, 0x46, 0x61, 0x73, 0x6f, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x75, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61,
-0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x52, 0xe9, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x71, 0x75,
-0x65, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x69, 0x6e, 0x65, 0x54, 0x63, 0x68, 0x61,
-0x64, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61,
-0x73, 0x61, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x43,
-0xf4, 0x74, 0x65, 0x20, 0x64, 0x2019, 0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69,
-0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x20, 0xe9, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x65, 0x47, 0x75,
-0x79, 0x61, 0x6e, 0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x79, 0x6e, 0xe9,
-0x73, 0x69, 0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x47, 0x61, 0x62, 0x6f, 0x6e, 0x47, 0x75,
-0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x48, 0x61, 0xef, 0x74, 0x69, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f,
-0x75, 0x72, 0x67, 0x4d, 0x61, 0x6c, 0x69, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4d, 0x61, 0x75,
-0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74,
-0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4d, 0x61, 0x72, 0x6f, 0x63, 0x4e, 0x6f, 0x75, 0x76, 0x65, 0x6c, 0x6c, 0x65,
-0x2d, 0x43, 0x61, 0x6c, 0xe9, 0x64, 0x6f, 0x6e, 0x69, 0x65, 0x4c, 0x61, 0x20, 0x52, 0xe9, 0x75, 0x6e, 0x69, 0x6f, 0x6e,
-0x53, 0xe9, 0x6e, 0xe9, 0x67, 0x61, 0x6c, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x2d,
-0x65, 0x74, 0x2d, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20,
-0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x79, 0x72, 0x69, 0x65, 0x54, 0x6f, 0x67,
-0x6f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x2d, 0x65, 0x74, 0x2d, 0x46, 0x75,
-0x74, 0x75, 0x6e, 0x61, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42, 0x61, 0x72, 0x74, 0x68, 0xe9, 0x6c, 0x65, 0x6d, 0x79,
-0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x46, 0x72, 0x79, 0x73, 0x6b, 0x4e, 0x65, 0x64,
-0x65, 0x72, 0x6c, 0xe2, 0x6e, 0x47, 0xe0, 0x69, 0x64, 0x68, 0x6c, 0x69, 0x67, 0x41, 0x6e, 0x20, 0x52, 0xec, 0x6f, 0x67,
-0x68, 0x61, 0x63, 0x68, 0x64, 0x20, 0x41, 0x6f, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x74, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x67,
-0x6f, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x10e1, 0x10d0, 0x10e5, 0x10d0, 0x10e0, 0x10d7,
-0x10d5, 0x10d4, 0x10da, 0x10dd, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61,
-0x6e, 0x64, 0xd6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68, 0x69, 0x73, 0x63, 0x68, 0x65, 0x73, 0x20, 0x44,
-0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x65, 0x6e, 0x49, 0x74, 0x61, 0x6c, 0x69, 0x65, 0x6e,
-0x4c, 0x69, 0x65, 0x63, 0x68, 0x74, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75,
-0x72, 0x67, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x48, 0x6f, 0x63, 0x68, 0x64, 0x65, 0x75, 0x74,
-0x73, 0x63, 0x68, 0x395, 0x3bb, 0x3bb, 0x3b7, 0x3bd, 0x3b9, 0x3ba, 0x3ac, 0x395, 0x3bb, 0x3bb, 0x3ac, 0x3b4, 0x3b1, 0x39a, 0x3cd, 0x3c0,
-0x3c1, 0x3bf, 0x3c2, 0x6b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x75, 0x74, 0x4b, 0x61, 0x6c, 0x61, 0x61, 0x6c,
-0x6c, 0x69, 0x74, 0x20, 0x4e, 0x75, 0x6e, 0x61, 0x61, 0x74, 0xa97, 0xac1, 0xa9c, 0xab0, 0xabe, 0xaa4, 0xac0, 0xaad, 0xabe, 0xab0,
-0xaa4, 0x48, 0x61, 0x75, 0x73, 0x61, 0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x47, 0x61, 0x6e, 0x61, 0x4e, 0x69,
-0x6a, 0x61, 0x72, 0x5e2, 0x5d1, 0x5e8, 0x5d9, 0x5ea, 0x5d9, 0x5e9, 0x5e8, 0x5d0, 0x5dc, 0x939, 0x93f, 0x928, 0x94d, 0x926, 0x940, 0x92d,
-0x93e, 0x930, 0x924, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x4d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x6f, 0x72, 0x73, 0x7a, 0xe1,
-0x67, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0xcd, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x6e, 0x64, 0x6f, 0x6e,
-0x65, 0x73, 0x69, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x75, 0x61, 0x4d, 0x75, 0x6e, 0x64, 0x6f,
-0x47, 0x61, 0x65, 0x69, 0x6c, 0x67, 0x65, 0xc9, 0x69, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x52, 0xed, 0x6f, 0x63, 0x68, 0x74,
-0x20, 0x41, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x74, 0x68, 0x65, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x6f, 0x49, 0x74,
-0x61, 0x6c, 0x69, 0x61, 0x53, 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65,
-0x72, 0x61, 0x43, 0x69, 0x74, 0x74, 0xe0, 0x20, 0x64, 0x65, 0x6c, 0x20, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x6f,
-0x65e5, 0x672c, 0x8a9e, 0x4a, 0x61, 0x77, 0x61, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0xe9, 0x73, 0x69, 0x61, 0xc95, 0xca8, 0xccd, 0xca8,
-0xca1, 0xcad, 0xcbe, 0xcb0, 0xca4, 0x6a9, 0x672, 0x634, 0x64f, 0x631, 0x6c1, 0x650, 0x646, 0x62f, 0x648, 0x633, 0x62a, 0x627, 0x646, 0x49b,
-0x430, 0x437, 0x430, 0x49b, 0x20, 0x442, 0x456, 0x43b, 0x456, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x4b, 0x69,
-0x6e, 0x79, 0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x55, 0x20, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x43a, 0x44b, 0x440,
-0x433, 0x44b, 0x437, 0x447, 0x430, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0xd55c, 0xad6d, 0xc5b4, 0xb300, 0xd55c,
-0xbbfc, 0xad6d, 0xc870, 0xc120, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0xc778, 0xbbfc, 0xacf5, 0xd654, 0xad6d, 0x6b, 0x75, 0x72, 0x64, 0xee, 0x54, 0x69,
-0x72, 0x6b, 0x69, 0x79, 0x65, 0x49, 0x6b, 0x69, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64,
-0x69, 0xea5, 0xeb2, 0xea7, 0x6c, 0x61, 0x74, 0x76, 0x69, 0x65, 0x161, 0x75, 0x4c, 0x61, 0x74, 0x76, 0x69, 0x6a, 0x61, 0x6c,
-0x69, 0x6e, 0x67, 0xe1, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0xed, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b,
-0x6f, 0x6e, 0x67, 0xf3, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x74, 0xed, 0x6b, 0x69, 0x41, 0x6e, 0x67, 0xf3,
-0x6c, 0x61, 0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x41, 0x66, 0x72, 0xed, 0x6b, 0x61,
-0x20, 0x79, 0x61, 0x20, 0x4b, 0xe1, 0x74, 0x69, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x69,
-0x173, 0x4c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x61, 0x43c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x421, 0x435,
-0x432, 0x435, 0x440, 0x43d, 0x430, 0x20, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x438, 0x458, 0x430, 0x4d, 0x61, 0x6c, 0x61,
-0x67, 0x61, 0x73, 0x79, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x69, 0x6b, 0x61, 0x72, 0x61, 0x4d, 0x65, 0x6c, 0x61,
-0x79, 0x75, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61, 0xd2e, 0xd32, 0xd2f,
-0xd3e, 0xd33, 0xd02, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d, 0x61, 0x6c, 0x74, 0x69, 0x4d, 0x101, 0x6f, 0x72, 0x69, 0x41,
-0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f, 0x61, 0x92e, 0x930, 0x93e, 0x920, 0x940, 0x43c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x41c, 0x43e,
-0x43d, 0x433, 0x43e, 0x43b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x62, 0x6f, 0x6b, 0x6d,
-0xe5, 0x6c, 0x4e, 0x6f, 0x72, 0x67, 0x65, 0x53, 0x76, 0x61, 0x6c, 0x62, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x67, 0x20, 0x4a,
-0x61, 0x6e, 0x20, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0xb13, 0xb21, 0xb3c, 0xb3f, 0xb06, 0xb2d, 0xb3e, 0xb30, 0xb24, 0x67e, 0x69a, 0x62a,
-0x648, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x641, 0x627, 0x631,
-0x633, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x62f, 0x631, 0x6cc, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x50, 0x6f, 0x6c, 0x73,
-0x6b, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x41, 0x6e, 0x67,
-0x6f, 0x6c, 0x61, 0x43, 0x61, 0x62, 0x6f, 0x20, 0x56, 0x65, 0x72, 0x64, 0x65, 0x54, 0x69, 0x6d, 0x6f, 0x72, 0x2d, 0x4c,
-0x65, 0x73, 0x74, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c,
-0x47, 0x75, 0x69, 0x6e, 0xe9, 0x2d, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75, 0x72,
-0x67, 0x6f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x2c, 0x20, 0x52, 0x41, 0x45, 0x20, 0x64, 0x61, 0x20, 0x43, 0x68, 0x69, 0x6e,
-0x61, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73,
-0x20, 0x65, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x75, 0x50, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x6c, 0x53, 0xe3, 0x6f, 0x20,
-0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x53, 0x75, 0xed, 0xe7, 0x61,
-0xa2a, 0xa70, 0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e, 0x646, 0x62c, 0x627, 0x628, 0x6cc, 0x52, 0x75, 0x6e, 0x61,
-0x73, 0x69, 0x6d, 0x69, 0x50, 0x65, 0x72, 0xfa, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x45, 0x63, 0x75, 0x61, 0x64,
-0x6f, 0x72, 0x72, 0x75, 0x6d, 0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76, 0x69, 0x7a, 0x72, 0x61, 0x72, 0x6f, 0x6d,
-0xe2, 0x6e, 0x103, 0x52, 0x6f, 0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20,
-0x4d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x61, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f,
-0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x442, 0x430, 0x43d, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b,
-0x434, 0x43e, 0x432, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430, 0x53, 0xe4, 0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6,
-0x72, 0xf6, 0x73, 0xea, 0x73, 0x65, 0x20, 0x74, 0xee, 0x20, 0x42, 0xea, 0x61, 0x66, 0x72, 0xee, 0x6b, 0x61, 0x441, 0x440,
-0x43f, 0x441, 0x43a, 0x438, 0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x43, 0x72, 0x6e, 0x61,
-0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x411, 0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425,
-0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x438, 0x43d, 0x430, 0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a,
-0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f, 0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434,
-0x437, 0x44b, 0x441, 0x442, 0x43e, 0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441, 0x435, 0x63, 0x68, 0x69, 0x53, 0x68, 0x6f, 0x6e, 0x61,
-0x633, 0x646, 0x68c, 0x64a, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb,
-0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0xdc0, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f,
-0x76, 0x65, 0x6e, 0x73, 0x6b, 0x6f, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x161, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f,
-0x76, 0x65, 0x6e, 0x69, 0x6a, 0x61, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61,
-0x6c, 0x69, 0x79, 0x61, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x69, 0x79, 0x61, 0x65,
-0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61, 0x41, 0x72, 0x67, 0x65,
-0x6e, 0x74, 0x69, 0x6e, 0x61, 0x42, 0x65, 0x6c, 0x69, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6f,
-0x6d, 0x62, 0x69, 0x61, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x20, 0x52, 0x69, 0x63, 0x61, 0x43, 0x75, 0x62, 0x61, 0x52, 0x65,
-0x70, 0xfa, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x61, 0x45, 0x6c,
-0x20, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x20, 0x45, 0x63, 0x75, 0x61,
-0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x48, 0x6f, 0x6e, 0x64, 0x75,
-0x72, 0x61, 0x73, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f,
-0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x50, 0x61, 0x6e, 0x61, 0x6d,
-0xe1, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x45, 0x73,
-0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x55, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x56,
-0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x61, 0x73, 0x65, 0x73, 0x70, 0x61,
-0xf1, 0x6f, 0x6c, 0x20, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x4c,
-0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0xe9, 0x72, 0x69, 0x63, 0x61, 0x43, 0x65, 0x75, 0x74, 0x61, 0x20, 0x79, 0x20,
-0x4d, 0x65, 0x6c, 0x69, 0x6c, 0x6c, 0x61, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69, 0x6c, 0x69, 0x4a, 0x61, 0x6d, 0x68,
-0x75, 0x72, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x69, 0x64, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x73, 0x69, 0x61, 0x20,
-0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x53, 0x76, 0x65, 0x72, 0x69,
-0x67, 0x65, 0xc5, 0x6c, 0x61, 0x6e, 0x64, 0x442, 0x43e, 0x4b7, 0x438, 0x43a, 0x4e3, 0x422, 0x43e, 0x4b7, 0x438, 0x43a, 0x438, 0x441,
-0x442, 0x43e, 0x43d, 0xba4, 0xbae, 0xbbf, 0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xbae, 0xbb2, 0xbc7, 0xb9a, 0xbbf,
-0xbaf, 0xbbe, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x442,
-0x430, 0x442, 0x430, 0x440, 0xc24, 0xc46, 0xc32, 0xc41, 0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0xc26, 0xc47, 0xc36, 0xc02, 0xe44, 0xe17,
-0xe22, 0xf56, 0xf7c, 0xf51, 0xf0b, 0xf66, 0xf90, 0xf51, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42,
-0xf62, 0xf0b, 0x1275, 0x130d, 0x122d, 0x129b, 0x12a4, 0x122d, 0x1275, 0x122b, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f,
-0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72, 0x6b, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b, 0x131, 0x62, 0x72,
-0x131, 0x73, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x64, 0x69, 0x6c, 0x69, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65,
-0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x626, 0x6c7, 0x64a, 0x63a, 0x6c7, 0x631, 0x686, 0x6d5, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x443,
-0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x430, 0x627, 0x631, 0x62f, 0x648,
-0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74,
-0x6f, 0x6e, 0x627, 0x648, 0x632, 0x628, 0x6cc, 0x6a9, 0x45e, 0x437, 0x431, 0x435, 0x43a, 0x447, 0x430, 0x40e, 0x437, 0x431, 0x435, 0x43a,
-0x438, 0x441, 0x442, 0x43e, 0x43d, 0x54, 0x69, 0x1ebf, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x56, 0x69, 0x1ec7, 0x74, 0x20,
-0x4e, 0x61, 0x6d, 0x56, 0x6f, 0x6c, 0x61, 0x70, 0xfc, 0x6b, 0x43, 0x79, 0x6d, 0x72, 0x61, 0x65, 0x67, 0x59, 0x20, 0x44,
-0x65, 0x79, 0x72, 0x6e, 0x61, 0x73, 0x20, 0x55, 0x6e, 0x65, 0x64, 0x69, 0x67, 0x57, 0x6f, 0x6c, 0x6f, 0x66, 0x53, 0x65,
-0x6e, 0x65, 0x67, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x69, 0x58, 0x68, 0x6f, 0x73, 0x61, 0x65, 0x4d, 0x7a, 0x61, 0x6e, 0x74,
-0x73, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x5d9, 0x5d9, 0x5b4, 0x5d3, 0x5d9, 0x5e9, 0x5d5, 0x5d5, 0x5e2, 0x5dc, 0x5d8,
-0xc8, 0x64, 0xe8, 0x20, 0x59, 0x6f, 0x72, 0xf9, 0x62, 0xe1, 0x4f, 0x72, 0x69, 0x6c, 0x1eb9, 0x300, 0x2d, 0xe8, 0x64, 0xe8,
-0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x42,
-0x25b, 0x300, 0x6e, 0x25b, 0x300, 0x69, 0x73, 0x69, 0x5a, 0x75, 0x6c, 0x75, 0x69, 0x4e, 0x69, 0x6e, 0x67, 0x69, 0x7a, 0x69,
-0x6d, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x6e, 0x79, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x4e, 0x6f, 0x72, 0x65,
-0x67, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x69, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x438, 0x47, 0x61, 0x65,
-0x6c, 0x67, 0x45, 0x6c, 0x6c, 0x61, 0x6e, 0x20, 0x56, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x77,
-0x65, 0x6b, 0x52, 0x79, 0x77, 0x76, 0x61, 0x6e, 0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73, 0x41, 0x6b, 0x61, 0x6e,
-0x47, 0x61, 0x61, 0x6e, 0x61, 0x915, 0x94b, 0x902, 0x915, 0x923, 0x940, 0x41, 0x73, 0x1ee5, 0x73, 0x1ee5, 0x20, 0x49, 0x67, 0x62,
-0x6f, 0x4e, 0x61, 0x1ecb, 0x6a, 0x1ecb, 0x72, 0x1ecb, 0x61, 0x4b, 0x69, 0x6b, 0x61, 0x6d, 0x62, 0x61, 0x66, 0x75, 0x72, 0x6c,
-0x61, 0x6e, 0x45, 0x28b, 0x65, 0x67, 0x62, 0x65, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65,
-0x54, 0x6f, 0x67, 0x6f, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65, 0x2bb, 0x14c, 0x6c, 0x65, 0x6c, 0x6f, 0x20, 0x48, 0x61,
-0x77, 0x61, 0x69, 0x2bb, 0x69, 0x2bb, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x75, 0x69, 0x20, 0x50, 0x16b,
-0x20, 0x2bb, 0x49, 0x61, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61,
-0x73, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x74, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x46, 0x72, 0x61,
-0x6e, 0x6b, 0x72, 0x69, 0x69, 0x63, 0x68, 0x4c, 0x69, 0xe4, 0x63, 0x68, 0x74, 0x65, 0x73, 0x63, 0x68, 0x74, 0xe4, 0x69,
-0xa188, 0xa320, 0xa259, 0xa34f, 0xa1e9, 0x4e, 0x65, 0x64, 0x64, 0x65, 0x72, 0x73, 0x61, 0x73, 0x73, 0x2019, 0x73, 0x63, 0x68, 0x44,
-0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x65, 0x64, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x6e,
-0x65, 0x6e, 0x64, 0x61, 0x76, 0x76, 0x69, 0x73, 0xe1, 0x6d, 0x65, 0x67, 0x69, 0x65, 0x6c, 0x6c, 0x61, 0x4e, 0x6f, 0x72,
-0x67, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x52, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x45, 0x6b, 0x65, 0x67, 0x75, 0x73,
-0x69, 0x69, 0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61, 0x50, 0x75, 0x6c, 0x61, 0x61, 0x72, 0x42, 0x75, 0x72, 0x6b, 0x69,
-0x62, 0x61, 0x61, 0x20, 0x46, 0x61, 0x61, 0x73, 0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x75, 0x6e, 0x47, 0x61, 0x6d,
-0x6d, 0x62, 0x69, 0x47, 0x61, 0x6e, 0x61, 0x61, 0x47, 0x69, 0x6e, 0x65, 0x47, 0x69, 0x6e, 0x65, 0x2d, 0x42, 0x69, 0x73,
-0x61, 0x61, 0x77, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e,
-0x69, 0x4e, 0x69, 0x6a, 0x65, 0x65, 0x72, 0x4e, 0x69, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x53, 0x65, 0x72, 0x61,
-0x61, 0x20, 0x6c, 0x69, 0x79, 0x6f, 0x6e, 0x47, 0x69, 0x6b, 0x75, 0x79, 0x75, 0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75,
-0x72, 0x73, 0x65, 0x6e, 0x61, 0x69, 0x73, 0x69, 0x4e, 0x64, 0x65, 0x62, 0x65, 0x6c, 0x65, 0x4b, 0x69, 0x68, 0x6f, 0x72,
-0x6f, 0x6d, 0x62, 0x6f, 0x2d5c, 0x2d30, 0x2d5b, 0x2d4d, 0x2d43, 0x2d49, 0x2d5c, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x54, 0x61, 0x73,
-0x68, 0x65, 0x6c, 0x1e25, 0x69, 0x79, 0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x54, 0x61, 0x71, 0x62, 0x61, 0x79, 0x6c,
-0x69, 0x74, 0x4c, 0x65, 0x7a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x6b, 0x6f, 0x72, 0x65,
-0x48, 0x69, 0x62, 0x65, 0x6e, 0x61, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x79, 0x69, 0x76,
-0x75, 0x6e, 0x6a, 0x6f, 0x62, 0x61, 0x6d, 0x61, 0x6e, 0x61, 0x6b, 0x61, 0x6e, 0x4b, 0x129, 0x65, 0x6d, 0x62, 0x75, 0x13e3,
-0x13b3, 0x13a9, 0x13cc, 0x13ca, 0x20, 0x13a2, 0x13f3, 0x13be, 0x13b5, 0x13cd, 0x13d4, 0x13c5, 0x20, 0x13cd, 0x13a6, 0x13da, 0x13a9, 0x6b, 0x72, 0x65,
-0x6f, 0x6c, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x4d, 0x6f, 0x72, 0x69, 0x73, 0x43, 0x68, 0x69, 0x6d,
-0x61, 0x6b, 0x6f, 0x6e, 0x64, 0x65, 0x4b, 0x268, 0x6c, 0x61, 0x61, 0x6e, 0x67, 0x69, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61,
-0x6e, 0xed, 0x61, 0x4c, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x59, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x49, 0x63, 0x68,
-0x69, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x6b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x4b, 0x61,
-0x62, 0x75, 0x20, 0x56, 0x65, 0x72, 0x64, 0x69, 0x4b, 0x129, 0x6d, 0x129, 0x72, 0x169, 0x4b, 0x61, 0x6c, 0x65, 0x6e, 0x6a,
-0x69, 0x6e, 0x45, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b, 0x68, 0x6f, 0x65, 0x6b, 0x68,
-0x6f, 0x65, 0x67, 0x6f, 0x77, 0x61, 0x62, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x62, 0x4b, 0x69, 0x6d, 0x61, 0x63,
-0x68, 0x61, 0x6d, 0x65, 0x4b, 0xf6, 0x6c, 0x73, 0x63, 0x68, 0x44, 0x6f, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e,
-0x64, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x61, 0x4f, 0x6c, 0x75, 0x73, 0x6f, 0x67, 0x61, 0x4c, 0x75, 0x6c, 0x75,
-0x68, 0x69, 0x61, 0x4b, 0x69, 0x70, 0x61, 0x72, 0x65, 0x54, 0x61, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x69, 0x74,
-0x65, 0x73, 0x6f, 0x4b, 0x65, 0x6e, 0x69, 0x61, 0x4b, 0x6f, 0x79, 0x72, 0x61, 0x20, 0x63, 0x69, 0x69, 0x6e, 0x69, 0x4d,
-0x61, 0x61, 0x6c, 0x69, 0x4b, 0x69, 0x72, 0x75, 0x77, 0x61, 0x44, 0x68, 0x6f, 0x6c, 0x75, 0x6f, 0x52, 0x75, 0x6b, 0x69,
-0x67, 0x61, 0x54, 0x61, 0x6d, 0x61, 0x7a, 0x69, 0x263, 0x74, 0x20, 0x6e, 0x20, 0x6c, 0x61, 0x1e6d, 0x6c, 0x61, 0x1e63, 0x4d,
-0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x4b, 0x6f, 0x79, 0x72, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69,
-0x4b, 0x69, 0x73, 0x68, 0x61, 0x6d, 0x62, 0x61, 0x61, 0x92c, 0x921, 0x93c, 0x94b, 0x43d, 0x43e, 0x445, 0x447, 0x438, 0x439, 0x43d,
-0x446, 0x435, 0x440, 0x43a, 0x43e, 0x432, 0x43d, 0x43e, 0x441, 0x43b, 0x43e, 0x432, 0x435, 0x301, 0x43d, 0x441, 0x43a, 0x457, 0x439, 0x440,
-0x461, 0x441, 0x441, 0x456, 0x301, 0x430, 0x54, 0x73, 0x68, 0x69, 0x6c, 0x75, 0x62, 0x61, 0x44, 0x69, 0x74, 0x75, 0x6e, 0x67,
-0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x75, 0x4c, 0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67,
-0x65, 0x73, 0x63, 0x68, 0x41, 0x67, 0x68, 0x65, 0x6d, 0x4b, 0xe0, 0x6d, 0xe0, 0x6c, 0xfb, 0x14b, 0x181, 0xe0, 0x73, 0xe0,
-0x61, 0x4b, 0xe0, 0x6d, 0x25b, 0x300, 0x72, 0xfb, 0x6e, 0x5a, 0x61, 0x72, 0x6d, 0x61, 0x63, 0x69, 0x69, 0x6e, 0x65, 0x4e,
-0x69, 0x17e, 0x65, 0x72, 0x64, 0x75, 0xe1, 0x6c, 0xe1, 0x6a, 0x6f, 0x6f, 0x6c, 0x61, 0x53, 0x65, 0x6e, 0x65, 0x67, 0x61,
-0x6c, 0x65, 0x77, 0x6f, 0x6e, 0x64, 0x6f, 0x4b, 0x61, 0x6d, 0x259, 0x72, 0xfa, 0x6e, 0x72, 0x69, 0x6b, 0x70, 0x61, 0x6b,
-0x61, 0x6d, 0x25b, 0x72, 0xfa, 0x6e, 0x4d, 0x61, 0x6b, 0x75, 0x61, 0x55, 0x6d, 0x6f, 0x7a, 0x61, 0x6d, 0x62, 0x69, 0x6b,
-0x69, 0x4d, 0x55, 0x4e, 0x44, 0x41, 0x14a, 0x6b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x14b, 0x4b, 0x77, 0x61, 0x73, 0x69, 0x6f,
-0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x6f, 0x6b, 0x20, 0x4e, 0x61, 0x74, 0x68, 0x441, 0x430, 0x445, 0x430,
-0x20, 0x442, 0x44b, 0x43b, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x49, 0x73, 0x68, 0x69, 0x73, 0x61,
-0x6e, 0x67, 0x75, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x54, 0x61, 0x73, 0x61, 0x77, 0x61, 0x71, 0x20,
-0x73, 0x65, 0x6e, 0x6e, 0x69, 0xa559, 0xa524, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x56, 0x61, 0x69, 0x4c, 0x61, 0x69, 0x62, 0x68, 0x69,
-0x79, 0x61, 0x57, 0x61, 0x6c, 0x73, 0x65, 0x72, 0x53, 0x63, 0x68, 0x77, 0x69, 0x7a, 0x6e, 0x75, 0x61, 0x73, 0x75, 0x65,
-0x4b, 0x65, 0x6d, 0x65, 0x6c, 0xfa, 0x6e, 0x61, 0x73, 0x74, 0x75, 0x72, 0x69, 0x61, 0x6e, 0x75, 0x4e, 0x64, 0x61, 0xa78c,
-0x61, 0x4b, 0x61, 0x6d, 0x25b, 0x6c, 0xfb, 0x6e, 0x6b, 0x61, 0x6b, 0x254, 0x4b, 0x61, 0x6d, 0x25b, 0x72, 0x75, 0x6e, 0x6d,
-0x65, 0x74, 0x61, 0x2bc, 0x4b, 0x61, 0x6d, 0x61, 0x6c, 0x75, 0x6e, 0x53, 0x68, 0x77, 0xf3, 0x14b, 0xf2, 0x20, 0x6e, 0x67,
-0x69, 0x65, 0x6d, 0x62, 0x254, 0x254, 0x6e, 0x4b, 0xe0, 0x6d, 0x61, 0x6c, 0xfb, 0x6d, 0xd804, 0xdd0c, 0xd804, 0xdd0b, 0xd804, 0xdd34,
-0xd804, 0xdd1f, 0xd804, 0xdd33, 0xd804, 0xdd26, 0xd804, 0xdd1d, 0xd804, 0xdd01, 0xd804, 0xdd23, 0xd804, 0xdd18, 0xd804, 0xdd2c, 0xd804, 0xdd0c, 0xd804, 0xdd34,
-0xd804, 0xdd1e, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd16, 0xd804, 0xdd34, 0x4c, 0x61, 0x6b, 0x21f, 0xf3, 0x6c, 0x2bc, 0x69, 0x79, 0x61,
-0x70, 0x69, 0x4d, 0xed, 0x6c, 0x61, 0x68, 0x61, 0x14b, 0x73, 0x6b, 0x61, 0x20, 0x54, 0x21f, 0x61, 0x6d, 0xe1, 0x6b, 0x21f,
-0x6f, 0x10d, 0x68, 0x65, 0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49, 0x2d56, 0x2d5c, 0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x6cc, 0x20, 0x646,
-0x627, 0x648, 0x6d5, 0x646, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627, 0x642, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x64, 0x6f, 0x6c, 0x6e,
-0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e, 0x69, 0x6d, 0x73, 0x6b, 0x61, 0x68, 0x6f, 0x72, 0x6e,
-0x6a, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e, 0x11b, 0x6d, 0x73, 0x6b, 0x61, 0x70, 0x72, 0x16b,
-0x73, 0x69, 0x73, 0x6b, 0x61, 0x6e, 0x73, 0x77, 0x12b, 0x74, 0x61, 0x69, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161, 0x6b, 0x69,
-0x65, 0x6c, 0xe2, 0x53, 0x75, 0x6f, 0x6d, 0xe2, 0x645, 0x627, 0x632, 0x631, 0x648, 0x646, 0x6cc, 0x644, 0x6ca, 0x631, 0x6cc, 0x20,
-0x634, 0x648, 0x645, 0x627, 0x644, 0x6cc, 0x7cb5, 0x8a9e, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c,
-0x653f, 0x5340, 0x7ca4, 0x8bed, 0x4e2d, 0x534e, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x56fd, 0x42, 0x69, 0x6e, 0x69, 0x73, 0x61, 0x79, 0x61
+static constexpr char16_t endonyms_data[] = {
+0x410, 0x525, 0x441, 0x448, 0x4d9, 0x430, 0x49a, 0x44b, 0x440, 0x4ad, 0x442, 0x4d9,
+0x44b, 0x43b, 0x430, 0x51, 0x61, 0x66, 0x61, 0x72, 0x4f, 0x74, 0x6f, 0x62,
+0x62, 0x69, 0x61, 0x59, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x45, 0x72,
+0x65, 0x74, 0x72, 0x69, 0x61, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61,
+0x6e, 0x73, 0x53, 0x75, 0x69, 0x64, 0x2d, 0x41, 0x66, 0x72, 0x69, 0x6b,
+0x61, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0xeb, 0x41, 0x67, 0x68, 0x65,
+0x6d, 0x4b, 0xe0, 0x6d, 0xe0, 0x6c, 0xfb, 0x14b, 0x41, 0x6b, 0x61, 0x6e,
+0x47, 0x61, 0x61, 0x6e, 0x61, 0x41, 0x6b, 0x6f, 0x6f, 0x73, 0x65, 0x4b,
+0x61, 0x6d, 0x65, 0x72, 0xfb, 0x6e, 0x73, 0x68, 0x71, 0x69, 0x70, 0x53,
+0x68, 0x71, 0x69, 0x70, 0xeb, 0x72, 0x69, 0x4b, 0x6f, 0x73, 0x6f, 0x76,
+0xeb, 0x4d, 0x61, 0x71, 0x65, 0x64, 0x6f, 0x6e, 0x69, 0x61, 0x20, 0x65,
+0x20, 0x56, 0x65, 0x72, 0x69, 0x75, 0x74, 0x12a0, 0x121b, 0x122d, 0x129b, 0x12a2,
+0x1275, 0x12ee, 0x1335, 0x12eb, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x645,
+0x635, 0x631, 0x627, 0x644, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x627, 0x644, 0x628,
+0x62d, 0x631, 0x64a, 0x646, 0x62a, 0x634, 0x627, 0x62f, 0x62c, 0x632, 0x631, 0x20,
+0x627, 0x644, 0x642, 0x645, 0x631, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x625,
+0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x627, 0x627, 0x644, 0x639, 0x631, 0x627, 0x642,
+0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x627, 0x644, 0x623, 0x631, 0x62f,
+0x646, 0x627, 0x644, 0x643, 0x648, 0x64a, 0x62a, 0x644, 0x628, 0x646, 0x627, 0x646,
+0x644, 0x64a, 0x628, 0x64a, 0x627, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646,
+0x64a, 0x627, 0x627, 0x644, 0x645, 0x63a, 0x631, 0x628, 0x639, 0x64f, 0x645, 0x627,
+0x646, 0x627, 0x644, 0x623, 0x631, 0x627, 0x636, 0x64a, 0x20, 0x627, 0x644, 0x641,
+0x644, 0x633, 0x637, 0x64a, 0x646, 0x64a, 0x629, 0x642, 0x637, 0x631, 0x627, 0x644,
+0x645, 0x645, 0x644, 0x643, 0x629, 0x20, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a,
+0x629, 0x20, 0x627, 0x644, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x629, 0x627, 0x644,
+0x635, 0x648, 0x645, 0x627, 0x644, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644,
+0x633, 0x648, 0x62f, 0x627, 0x646, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646,
+0x633, 0x648, 0x631, 0x64a, 0x627, 0x62a, 0x648, 0x646, 0x633, 0x627, 0x644, 0x625,
+0x645, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a,
+0x629, 0x20, 0x627, 0x644, 0x645, 0x62a, 0x62d, 0x62f, 0x629, 0x627, 0x644, 0x635,
+0x62d, 0x631, 0x627, 0x621, 0x20, 0x627, 0x644, 0x63a, 0x631, 0x628, 0x64a, 0x629,
+0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x641, 0x635,
+0x62d, 0x649, 0x20, 0x627, 0x644, 0x62d, 0x62f, 0x64a, 0x62b, 0x629, 0x627, 0x644,
+0x639, 0x627, 0x644, 0x645, 0x627, 0x644, 0x64a, 0x645, 0x646, 0x61, 0x72, 0x61,
+0x67, 0x6f, 0x6e, 0xe9, 0x73, 0x45, 0x73, 0x70, 0x61, 0x6e, 0x79, 0x61,
+0x570, 0x561, 0x575, 0x565, 0x580, 0x565, 0x576, 0x540, 0x561, 0x575, 0x561, 0x57d,
+0x57f, 0x561, 0x576, 0x985, 0x9b8, 0x9ae, 0x9c0, 0x9af, 0x9bc, 0x9be, 0x9ad, 0x9be,
+0x9f0, 0x9a4, 0x61, 0x73, 0x74, 0x75, 0x72, 0x69, 0x61, 0x6e, 0x75, 0x45,
+0x73, 0x70, 0x61, 0xf1, 0x61, 0x4b, 0x69, 0x70, 0x61, 0x72, 0x65, 0x54,
+0x61, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x41, 0x74, 0x73, 0x61, 0x6d,
+0x61, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x41, 0x7a,
+0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x62a, 0x6c6, 0x631, 0x6a9,
+0x62c, 0x647, 0x430, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d,
+0x410, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x72, 0x69,
+0x6b, 0x70, 0x61, 0x6b, 0x61, 0x6d, 0x25b, 0x72, 0xfa, 0x6e, 0x62, 0x61,
+0x6d, 0x61, 0x6e, 0x61, 0x6b, 0x61, 0x6e, 0x4d, 0x61, 0x6c, 0x69, 0x9ac,
+0x9be, 0x982, 0x9b2, 0x9be, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6,
+0x9ad, 0x9be, 0x9b0, 0x9a4, 0x181, 0xe0, 0x73, 0xe0, 0x61, 0x4b, 0xe0, 0x6d,
+0x25b, 0x300, 0x72, 0xfb, 0x6e, 0x431, 0x430, 0x448, 0x4a1, 0x43e, 0x440, 0x442,
+0x20, 0x442, 0x435, 0x43b, 0x435, 0x65, 0x75, 0x73, 0x6b, 0x61, 0x72, 0x61,
+0x45, 0x73, 0x70, 0x61, 0x69, 0x6e, 0x69, 0x61, 0x431, 0x435, 0x43b, 0x430,
+0x440, 0x443, 0x441, 0x43a, 0x430, 0x44f, 0x411, 0x435, 0x43b, 0x430, 0x440, 0x443,
+0x441, 0x44c, 0x49, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x5a,
+0x61, 0x6d, 0x62, 0x69, 0x61, 0x48, 0x69, 0x62, 0x65, 0x6e, 0x61, 0x48,
+0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x92d, 0x94b, 0x91c,
+0x92a, 0x941, 0x930, 0x940, 0x92d, 0x93e, 0x930, 0x924, 0x1265, 0x120a, 0x1295, 0x12a4,
+0x122d, 0x1275, 0x122b, 0x92c, 0x930, 0x2019, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73,
+0x6b, 0x69, 0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20, 0x69, 0x20, 0x48, 0x65,
+0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x69, 0x6e, 0x61, 0x431, 0x43e, 0x441,
+0x430, 0x43d, 0x441, 0x43a, 0x438, 0x411, 0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438,
+0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x438, 0x43d, 0x430,
+0x62, 0x72, 0x65, 0x7a, 0x68, 0x6f, 0x6e, 0x65, 0x67, 0x46, 0x72, 0x61,
+0xf1, 0x73, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411,
+0x44a, 0x43b, 0x433, 0x430, 0x440, 0x438, 0x44f, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019,
+0x102c, 0x7cb5, 0x8a9e, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f,
+0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x7ca4, 0x8bed, 0x4e2d, 0x534e, 0x4eba, 0x6c11, 0x5171,
+0x548c, 0x56fd, 0x63, 0x61, 0x74, 0x61, 0x6c, 0xe0, 0x41, 0x6e, 0x64, 0x6f,
+0x72, 0x72, 0x61, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x49, 0x74, 0xe0,
+0x6c, 0x69, 0x61, 0x43, 0x65, 0x62, 0x75, 0x61, 0x6e, 0x6f, 0x50, 0x69,
+0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x54, 0x61, 0x6d, 0x61, 0x7a,
+0x69, 0x263, 0x74, 0x20, 0x6e, 0x20, 0x6c, 0x61, 0x1e6d, 0x6c, 0x61, 0x1e63,
+0x4d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x6cc,
+0x20, 0x646, 0x627, 0x648, 0x6d5, 0x646, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627,
+0x642, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0xd804, 0xdd0c, 0xd804, 0xdd0b, 0xd804, 0xdd34,
+0xd804, 0xdd1f, 0xd804, 0xdd33, 0xd804, 0xdd26, 0xd804, 0xdd1d, 0xd804, 0xdd01, 0xd804, 0xdd23,
+0xd804, 0xdd18, 0xd804, 0xdd2c, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804, 0xdd1e, 0xd804, 0xdd22,
+0xd804, 0xdd27, 0xd804, 0xdd16, 0xd804, 0xdd34, 0x43d, 0x43e, 0x445, 0x447, 0x438, 0x439,
+0x43d, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x13e3, 0x13b3, 0x13a9, 0x13cc, 0x13ca, 0x20,
+0x13a2, 0x13f3, 0x13be, 0x13b5, 0x13cd, 0x13d4, 0x13c5, 0x20, 0x13cd, 0x13a6, 0x13da, 0x13a9,
+0x43, 0x68, 0x69, 0x6b, 0x61, 0x73, 0x68, 0x73, 0x68, 0x61, 0x6e, 0x6f,
+0x6d, 0x70, 0x61, 0x2bc, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x53,
+0x74, 0x61, 0x74, 0x65, 0x73, 0x52, 0x75, 0x6b, 0x69, 0x67, 0x61, 0x55,
+0x67, 0x61, 0x6e, 0x64, 0x61, 0x7b80, 0x4f53, 0x4e2d, 0x6587, 0x4e2d, 0x56fd, 0x4e2d,
+0x56fd, 0x9999, 0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d, 0x56fd, 0x6fb3, 0x95e8,
+0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x65b0, 0x52a0, 0x5761, 0x7e41, 0x9ad4, 0x4e2d, 0x6587,
+0x4e2d, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x4e2d, 0x570b, 0x6fb3,
+0x9580, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x53f0, 0x7063, 0x446, 0x435, 0x440, 0x43a,
+0x43e, 0x432, 0x43d, 0x43e, 0x441, 0x43b, 0x43e, 0x432, 0x435, 0x301, 0x43d, 0x441,
+0x43a, 0x457, 0x439, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x430, 0x447, 0x4d1,
+0x432, 0x430, 0x448, 0x420, 0x430, 0x4ab, 0x4ab, 0x435, 0x439, 0x4b, 0xf6, 0x6c,
+0x73, 0x63, 0x68, 0x44, 0x6f, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61,
+0x6e, 0x64, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x77, 0x65, 0x6b, 0x52, 0x79,
+0x77, 0x76, 0x61, 0x6e, 0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73,
+0x63, 0x6f, 0x72, 0x73, 0x75, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x61,
+0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x48, 0x72, 0x76, 0x61,
+0x74, 0x73, 0x6b, 0x61, 0x10d, 0x65, 0x161, 0x74, 0x69, 0x6e, 0x61, 0x10c,
+0x65, 0x73, 0x6b, 0x6f, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x44, 0x61, 0x6e,
+0x6d, 0x61, 0x72, 0x6b, 0x47, 0x72, 0xf8, 0x6e, 0x6c, 0x61, 0x6e, 0x64,
+0x78b, 0x7a8, 0x788, 0x7ac, 0x780, 0x7a8, 0x784, 0x7a6, 0x790, 0x7b0, 0x78b, 0x7a8,
+0x788, 0x7ac, 0x780, 0x7a8, 0x20, 0x783, 0x7a7, 0x787, 0x7b0, 0x796, 0x7ac, 0x921,
+0x94b, 0x917, 0x930, 0x940, 0x64, 0x75, 0xe1, 0x6c, 0xe1, 0x43, 0x61, 0x6d,
+0x65, 0x72, 0x6f, 0x75, 0x6e, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61,
+0x6e, 0x64, 0x73, 0x41, 0x72, 0x75, 0x62, 0x61, 0x56, 0x6c, 0x61, 0x61,
+0x6d, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0xeb, 0x43, 0x61, 0x72, 0x69,
+0x62, 0x69, 0x73, 0x63, 0x68, 0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c,
+0x61, 0x6e, 0x64, 0x43, 0x75, 0x72, 0x61, 0xe7, 0x61, 0x6f, 0x53, 0x69,
+0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x53, 0x75,
+0x72, 0x69, 0x6e, 0x61, 0x6d, 0x65, 0xf62, 0xfab, 0xf7c, 0xf44, 0xf0b, 0xf41,
+0xf60, 0xf56, 0xfb2, 0xf74, 0xf42, 0x4b, 0x129, 0x65, 0x6d, 0x62, 0x75, 0x4b,
+0x65, 0x6e, 0x79, 0x61, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e,
+0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0xd801, 0xdc00, 0xd801, 0xdc4d,
+0xd801, 0xdc4a, 0xd801, 0xdc2e, 0xd801, 0xdc47, 0xd801, 0xdc0f, 0xd801, 0xdc2d, 0xd801, 0xdc4c,
+0xd801, 0xdc34, 0xd801, 0xdc3b, 0xd801, 0xdc32, 0xd801, 0xdc3c, 0x20, 0xd801, 0xdc1d, 0xd801,
+0xdc3b, 0xd801, 0xdc29, 0xd801, 0xdc3b, 0xd801, 0xdc45, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x6e, 0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x6e, 0x67,
+0x75, 0x69, 0x6c, 0x6c, 0x61, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61,
+0x20, 0x26, 0x20, 0x42, 0x61, 0x72, 0x62, 0x75, 0x64, 0x61, 0x41, 0x75,
+0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67,
+0x6c, 0x69, 0x73, 0x68, 0x41, 0x75, 0x73, 0x74, 0x72, 0x69, 0x61, 0x42,
+0x61, 0x68, 0x61, 0x6d, 0x61, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64,
+0x6f, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x75, 0x6d, 0x42, 0x65, 0x6c,
+0x69, 0x7a, 0x65, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x42, 0x6f,
+0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73,
+0x68, 0x20, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x4f, 0x63, 0x65,
+0x61, 0x6e, 0x20, 0x54, 0x65, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x72, 0x79,
+0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x56, 0x69, 0x72, 0x67,
+0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x42, 0x75,
+0x72, 0x75, 0x6e, 0x64, 0x69, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x6f,
+0x6e, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e,
+0x67, 0x6c, 0x69, 0x73, 0x68, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x43,
+0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64,
+0x73, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x20, 0x49,
+0x73, 0x6c, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x20, 0x28,
+0x4b, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x49, 0x73, 0x6c,
+0x61, 0x6e, 0x64, 0x73, 0x43, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x6c,
+0x61, 0x6e, 0x64, 0x73, 0x43, 0x79, 0x70, 0x72, 0x75, 0x73, 0x44, 0x65,
+0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x20, 0x47,
+0x61, 0x72, 0x63, 0x69, 0x61, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63,
+0x61, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x45, 0x73, 0x77, 0x61,
+0x74, 0x69, 0x6e, 0x69, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x46, 0x61,
+0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e,
+0x64, 0x73, 0x46, 0x69, 0x6a, 0x69, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e,
+0x64, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x47, 0x65, 0x72, 0x6d, 0x61,
+0x6e, 0x79, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x47, 0x69, 0x62, 0x72, 0x61,
+0x6c, 0x74, 0x61, 0x72, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x47,
+0x75, 0x61, 0x6d, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x47,
+0x75, 0x79, 0x61, 0x6e, 0x61, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f,
+0x6e, 0x67, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61,
+0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x49, 0x72, 0x65,
+0x6c, 0x61, 0x6e, 0x64, 0x49, 0x73, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20,
+0x4d, 0x61, 0x6e, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x4a, 0x61, 0x6d,
+0x61, 0x69, 0x63, 0x61, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x4b, 0x69,
+0x72, 0x69, 0x62, 0x61, 0x74, 0x69, 0x4c, 0x65, 0x73, 0x6f, 0x74, 0x68,
+0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x4d, 0x61, 0x63, 0x61,
+0x6f, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d,
+0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c,
+0x61, 0x77, 0x69, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x4d,
+0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x4d, 0x61, 0x6c, 0x74, 0x61,
+0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x73, 0x6c,
+0x61, 0x6e, 0x64, 0x73, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75,
+0x73, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x4d,
+0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x4e, 0x61, 0x6d,
+0x69, 0x62, 0x69, 0x61, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x4e, 0x65, 0x74,
+0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x77, 0x20,
+0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x69, 0x67, 0x65, 0x72,
+0x69, 0x61, 0x4e, 0x69, 0x75, 0x65, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c,
+0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x6f, 0x72, 0x74,
+0x68, 0x65, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x61,
+0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x61, 0x6b, 0x69,
+0x73, 0x74, 0x61, 0x6e, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x50, 0x61, 0x70,
+0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65,
+0x61, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73,
+0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x20, 0x49, 0x73, 0x6c,
+0x61, 0x6e, 0x64, 0x73, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x20, 0x52,
+0x69, 0x63, 0x6f, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x74, 0x20,
+0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x53, 0x74, 0x20, 0x4b, 0x69, 0x74,
+0x74, 0x73, 0x20, 0x26, 0x20, 0x4e, 0x65, 0x76, 0x69, 0x73, 0x53, 0x74,
+0x20, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x53, 0x74, 0x20, 0x56, 0x69, 0x6e,
+0x63, 0x65, 0x6e, 0x74, 0x20, 0x26, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47,
+0x72, 0x65, 0x6e, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x53, 0x65, 0x79,
+0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x53, 0x69, 0x65, 0x72, 0x72,
+0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x61,
+0x70, 0x6f, 0x72, 0x65, 0x53, 0x69, 0x6e, 0x74, 0x20, 0x4d, 0x61, 0x61,
+0x72, 0x74, 0x65, 0x6e, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x61,
+0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61,
+0x6e, 0x64, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64,
+0x61, 0x6e, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53, 0x77, 0x65, 0x64, 0x65,
+0x6e, 0x53, 0x77, 0x69, 0x74, 0x7a, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64,
+0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x54, 0x6f, 0x6b, 0x65,
+0x6c, 0x61, 0x75, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x72, 0x69, 0x6e,
+0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67,
+0x6f, 0x54, 0x75, 0x72, 0x6b, 0x73, 0x20, 0x26, 0x20, 0x43, 0x61, 0x69,
+0x63, 0x6f, 0x73, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x54,
+0x75, 0x76, 0x61, 0x6c, 0x75, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20,
+0x41, 0x72, 0x61, 0x62, 0x20, 0x45, 0x6d, 0x69, 0x72, 0x61, 0x74, 0x65,
+0x73, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x45, 0x6e, 0x67,
+0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x4b,
+0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x4f,
+0x75, 0x74, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x49, 0x73, 0x6c, 0x61,
+0x6e, 0x64, 0x73, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x56, 0x69, 0x72, 0x67,
+0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x56, 0x61,
+0x6e, 0x75, 0x61, 0x74, 0x75, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x5a, 0x69,
+0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 0x44d, 0x440, 0x437, 0x44f, 0x43d, 0x44c,
+0x20, 0x43a, 0x435, 0x43b, 0x44c, 0x420, 0x443, 0x437, 0x43e, 0x43d, 0x44c, 0x20,
+0x43c, 0x430, 0x441, 0x442, 0x43e, 0x440, 0x45, 0x73, 0x70, 0x65, 0x72, 0x61,
+0x6e, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x64, 0x6f, 0x65, 0x65, 0x73, 0x74,
+0x69, 0x45, 0x65, 0x73, 0x74, 0x69, 0x45, 0x28b, 0x65, 0x67, 0x62, 0x65,
+0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65,
+0x54, 0x6f, 0x67, 0x6f, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65, 0x65,
+0x77, 0x6f, 0x6e, 0x64, 0x6f, 0x4b, 0x61, 0x6d, 0x259, 0x72, 0xfa, 0x6e,
+0x66, 0xf8, 0x72, 0x6f, 0x79, 0x73, 0x6b, 0x74, 0x46, 0xf8, 0x72, 0x6f,
+0x79, 0x61, 0x72, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x73,
+0x75, 0x6f, 0x6d, 0x69, 0x53, 0x75, 0x6f, 0x6d, 0x69, 0x66, 0x72, 0x61,
+0x6e, 0xe7, 0x61, 0x69, 0x73, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x41,
+0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x71,
+0x75, 0x65, 0x42, 0xe9, 0x6e, 0x69, 0x6e, 0x42, 0x75, 0x72, 0x6b, 0x69,
+0x6e, 0x61, 0x20, 0x46, 0x61, 0x73, 0x6f, 0x66, 0x72, 0x61, 0x6e, 0xe7,
+0x61, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e,
+0x52, 0xe9, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x71, 0x75, 0x65, 0x20, 0x63,
+0x65, 0x6e, 0x74, 0x72, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x69, 0x6e,
+0x65, 0x54, 0x63, 0x68, 0x61, 0x64, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x65,
+0x73, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a,
+0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d,
+0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x44, 0x6a, 0x69, 0x62,
+0x6f, 0x75, 0x74, 0x69, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x20, 0xe9,
+0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x65, 0x47, 0x75,
+0x79, 0x61, 0x6e, 0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69,
+0x73, 0x65, 0x50, 0x6f, 0x6c, 0x79, 0x6e, 0xe9, 0x73, 0x69, 0x65, 0x20,
+0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x47, 0x61, 0x62,
+0x6f, 0x6e, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65,
+0x48, 0x61, 0xef, 0x74, 0x69, 0x43, 0xf4, 0x74, 0x65, 0x20, 0x64, 0x2019,
+0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62,
+0x6f, 0x75, 0x72, 0x67, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71,
+0x75, 0x65, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65,
+0x4d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x79, 0x6f, 0x74,
+0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4d, 0x61, 0x72, 0x6f,
+0x63, 0x4e, 0x6f, 0x75, 0x76, 0x65, 0x6c, 0x6c, 0x65, 0x2d, 0x43, 0x61,
+0x6c, 0xe9, 0x64, 0x6f, 0x6e, 0x69, 0x65, 0x4c, 0x61, 0x20, 0x52, 0xe9,
+0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42,
+0x61, 0x72, 0x74, 0x68, 0xe9, 0x6c, 0x65, 0x6d, 0x79, 0x53, 0x61, 0x69,
+0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x53, 0x61, 0x69,
+0x6e, 0x74, 0x2d, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x2d, 0x65, 0x74,
+0x2d, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x53, 0xe9, 0x6e,
+0xe9, 0x67, 0x61, 0x6c, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73,
+0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x75, 0x69, 0x73, 0x73,
+0x65, 0x53, 0x79, 0x72, 0x69, 0x65, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x69,
+0x65, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x2d, 0x65, 0x74, 0x2d, 0x46,
+0x75, 0x74, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x72, 0x6c, 0x61, 0x6e, 0x49,
+0x74, 0x61, 0x6c, 0x69, 0x65, 0x50, 0x75, 0x6c, 0x61, 0x61, 0x72, 0x53,
+0x65, 0x6e, 0x65, 0x67, 0x61, 0x61, 0x6c, 0xd83a, 0xdd06, 0xd83a, 0xdd35, 0xd83a,
+0xdd24, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd04, 0xd83a, 0xdd35, 0xd83a, 0xdd2a, 0xd83a,
+0xdd33, 0xd83a, 0xdd2d, 0xd83a, 0xdd32, 0xd83a, 0xdd22, 0x20, 0xd83a, 0xdd0a, 0xd83a, 0xdd22,
+0xd83a, 0xdd27, 0xd83a, 0xdd2e, 0xd83a, 0xdd45, 0xd83a, 0xdd11, 0xd83a, 0xdd22, 0xd83a, 0xdd25,
+0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd35, 0xd83a, 0xdd45, 0xd83a, 0xdd32, 0xd83a, 0xdd18,
+0xd83a, 0xdd22, 0xd83a, 0xdd25, 0xd83a, 0xdd26, 0xd83a, 0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22,
+0xd83a, 0xdd18, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0xd83a, 0xdd22, 0xd83a, 0xdd18, 0xd83a, 0xdd2d,
+0xd83a, 0xdd32, 0xd83a, 0xdd2b, 0x2d, 0xd83a, 0xdd04, 0xd83a, 0xdd2d, 0xd83a, 0xdd27, 0xd83a,
+0xdd22, 0xd83a, 0xdd31, 0xd83a, 0xdd2e, 0xd83a, 0xdd45, 0xd83a, 0xdd02, 0xd83a, 0xdd22, 0xd83a,
+0xdd26, 0xd83a, 0xdd2d, 0xd83a, 0xdd2a, 0xd83a, 0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22, 0xd83a,
+0xdd44, 0xd83a, 0xdd03, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd3c, 0xd83a, 0xdd22, 0xd83a,
+0xdd32, 0xd83a, 0xdd2d, 0xd83a, 0xdd45, 0xd83a, 0xdd10, 0xd83a, 0xdd22, 0xd83a, 0xdd36, 0xd83a,
+0xdd2b, 0xd83a, 0xdd2a, 0xd83a, 0xdd2d, 0xd83a, 0xdd34, 0xd83a, 0xdd22, 0xd83a, 0xdd44, 0xd83a,
+0xdd10, 0xd83a, 0xdd2d, 0xd83a, 0xdd45, 0xd83a, 0xdd36, 0xd83a, 0xdd2b, 0xd83a, 0xdd2a, 0xd83a,
+0xdd05, 0xd83a, 0xdd2b, 0xd83a, 0xdd32, 0xd83a, 0xdd2b, 0xd83a, 0xdd3a, 0xd83a, 0xdd22, 0xd83a,
+0xdd44, 0xd83a, 0xdd24, 0xd83a, 0xdd05, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a,
+0xdd24, 0xd83a, 0xdd2e, 0xd83a, 0xdd32, 0x42, 0x75, 0x72, 0x6b, 0x69, 0x62, 0x61,
+0x61, 0x20, 0x46, 0x61, 0x61, 0x73, 0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72,
+0x75, 0x75, 0x6e, 0x47, 0x61, 0x6d, 0x6d, 0x62, 0x69, 0x47, 0x61, 0x6e,
+0x61, 0x61, 0x47, 0x69, 0x6e, 0x65, 0x2d, 0x42, 0x69, 0x73, 0x61, 0x61,
+0x77, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x4d,
+0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x4e, 0x69, 0x6a, 0x65, 0x72,
+0x69, 0x79, 0x61, 0x61, 0x4e, 0x69, 0x6a, 0x65, 0x65, 0x72, 0x53, 0x65,
+0x72, 0x61, 0x61, 0x20, 0x6c, 0x69, 0x79, 0x6f, 0x6e, 0x47, 0xe0, 0x69,
+0x64, 0x68, 0x6c, 0x69, 0x67, 0x41, 0x6e, 0x20, 0x52, 0xec, 0x6f, 0x67,
+0x68, 0x61, 0x63, 0x68, 0x64, 0x20, 0x41, 0x6f, 0x6e, 0x61, 0x69, 0x63,
+0x68, 0x74, 0x65, 0x47, 0xe3, 0x67, 0x61, 0x6c, 0x65, 0x67, 0x6f, 0x4c,
+0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x59, 0x75, 0x67, 0x61, 0x6e, 0x64,
+0x61, 0x130d, 0x12d5, 0x12dd, 0x129b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8,
+0x10e1, 0x10d0, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10d5, 0x10d4, 0x10da, 0x10dd, 0x44, 0x65,
+0x75, 0x74, 0x73, 0x63, 0x68, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68,
+0x6c, 0x61, 0x6e, 0x64, 0xd6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69,
+0x63, 0x68, 0x69, 0x73, 0x63, 0x68, 0x65, 0x73, 0x20, 0x44, 0x65, 0x75,
+0x74, 0x73, 0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x65, 0x6e, 0x49,
+0x74, 0x61, 0x6c, 0x69, 0x65, 0x6e, 0x4c, 0x69, 0x65, 0x63, 0x68, 0x74,
+0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x4c, 0x75, 0x78, 0x65, 0x6d,
+0x62, 0x75, 0x72, 0x67, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65,
+0x72, 0x20, 0x48, 0x6f, 0x63, 0x68, 0x64, 0x65, 0x75, 0x74, 0x73, 0x63,
+0x68, 0x395, 0x3bb, 0x3bb, 0x3b7, 0x3bd, 0x3b9, 0x3ba, 0x3ac, 0x395, 0x3bb, 0x3bb,
+0x3ac, 0x3b4, 0x3b1, 0x39a, 0x3cd, 0x3c0, 0x3c1, 0x3bf, 0x3c2, 0x61, 0x76, 0x61,
+0xf1, 0x65, 0x2019, 0x1ebd, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69,
+0xa97, 0xac1, 0xa9c, 0xab0, 0xabe, 0xaa4, 0xac0, 0xaad, 0xabe, 0xab0, 0xaa4, 0x45,
+0x6b, 0x65, 0x67, 0x75, 0x73, 0x69, 0x69, 0x48, 0x61, 0x75, 0x73, 0x61,
+0x4e, 0x69, 0x6a, 0x61, 0x72, 0x2bb, 0x14c, 0x6c, 0x65, 0x6c, 0x6f, 0x20,
+0x48, 0x61, 0x77, 0x61, 0x69, 0x2bb, 0x69, 0x2bb, 0x41, 0x6d, 0x65, 0x6c,
+0x69, 0x6b, 0x61, 0x20, 0x48, 0x75, 0x69, 0x20, 0x50, 0x16b, 0x20, 0x2bb,
+0x49, 0x61, 0x5e2, 0x5d1, 0x5e8, 0x5d9, 0x5ea, 0x5d9, 0x5e9, 0x5e8, 0x5d0, 0x5dc,
+0x939, 0x93f, 0x928, 0x94d, 0x926, 0x940, 0x48, 0x69, 0x6e, 0x64, 0x69, 0x20,
+0x28, 0x4c, 0x61, 0x74, 0x69, 0x6e, 0x29, 0x6d, 0x61, 0x67, 0x79, 0x61,
+0x72, 0x4d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x6f, 0x72, 0x73, 0x7a, 0xe1,
+0x67, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0xcd, 0x73, 0x6c,
+0x61, 0x6e, 0x64, 0x49, 0x64, 0x6f, 0x49, 0x67, 0x62, 0x6f, 0x4e, 0x61,
+0x1ecb, 0x6a, 0x1ecb, 0x72, 0x1ecb, 0x61, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161,
+0x6b, 0x69, 0x65, 0x6c, 0xe2, 0x53, 0x75, 0x6f, 0x6d, 0xe2, 0x69, 0x6e,
+0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x75, 0x61, 0x4d, 0x75, 0x6e,
+0x64, 0x6f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x75,
+0x65, 0x45, 0x73, 0x74, 0x6f, 0x6e, 0x69, 0x61, 0x1403, 0x14c4, 0x1483, 0x144e,
+0x1450, 0x1466, 0x1472, 0x14c7, 0x1455, 0x14a5, 0x47, 0x61, 0x65, 0x69, 0x6c, 0x67,
+0x65, 0xc9, 0x69, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x52, 0xed, 0x6f, 0x63,
+0x68, 0x74, 0x20, 0x41, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x74, 0x68, 0x65,
+0x69, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x6f, 0x49, 0x74, 0x61, 0x6c,
+0x69, 0x61, 0x53, 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f,
+0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x61, 0x43, 0x69, 0x74, 0x74,
+0xe0, 0x20, 0x64, 0x65, 0x6c, 0x20, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61,
+0x6e, 0x6f, 0x65e5, 0x672c, 0x8a9e, 0x4a, 0x61, 0x77, 0x61, 0x49, 0x6e, 0x64,
+0x6f, 0x6e, 0xe9, 0x73, 0x69, 0x61, 0x4b, 0x61, 0x6a, 0x65, 0x6a, 0x6f,
+0x6f, 0x6c, 0x61, 0x53, 0x65, 0x6e, 0x65, 0x67, 0x61, 0x6c, 0x6b, 0x61,
+0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x4b, 0x61,
+0x62, 0x75, 0x20, 0x56, 0x65, 0x72, 0x64, 0x69, 0x54, 0x61, 0x71, 0x62,
+0x61, 0x79, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x7a, 0x7a, 0x61, 0x79, 0x65,
+0x72, 0x6b, 0x61, 0x6b, 0x254, 0x4b, 0x61, 0x6d, 0x25b, 0x72, 0x75, 0x6e,
+0x6b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x75, 0x74, 0x4b,
+0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x74, 0x20, 0x4e, 0x75, 0x6e,
+0x61, 0x61, 0x74, 0x4b, 0x61, 0x6c, 0x65, 0x6e, 0x6a, 0x69, 0x6e, 0x45,
+0x6d, 0x65, 0x74, 0x61, 0x62, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b,
+0x69, 0x6b, 0x61, 0x6d, 0x62, 0x61, 0xc95, 0xca8, 0xccd, 0xca8, 0xca1, 0xcad,
+0xcbe, 0xcb0, 0xca4, 0x6a9, 0x672, 0x634, 0x64f, 0x631, 0x6c1, 0x650, 0x646, 0x62f,
+0x648, 0x633, 0x62a, 0x627, 0x646, 0x915, 0x949, 0x936, 0x941, 0x930, 0x939, 0x93f,
+0x902, 0x926, 0x94b, 0x938, 0x94d, 0x924, 0x93e, 0x928, 0x49b, 0x430, 0x437, 0x430,
+0x49b, 0x20, 0x442, 0x456, 0x43b, 0x456, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441,
+0x442, 0x430, 0x43d, 0x4b, 0x25b, 0x6e, 0x79, 0x61, 0x14b, 0x1781, 0x17d2, 0x1798,
+0x17c2, 0x179a, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x4b, 0x2bc, 0x69,
+0x63, 0x68, 0x65, 0x2bc, 0x47, 0x69, 0x6b, 0x75, 0x79, 0x75, 0x4b, 0x69,
+0x6e, 0x79, 0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x55, 0x20, 0x52,
+0x77, 0x61, 0x6e, 0x64, 0x61, 0x915, 0x94b, 0x902, 0x915, 0x923, 0x940, 0xd55c,
+0xad6d, 0xc5b4, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0xc911, 0xad6d, 0xc870, 0xc120, 0xbbfc, 0xc8fc,
+0xc8fc, 0xc758, 0xc778, 0xbbfc, 0xacf5, 0xd654, 0xad6d, 0x4b, 0x6f, 0x79, 0x72, 0x61,
+0x62, 0x6f, 0x72, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0x4d, 0x61,
+0x61, 0x6c, 0x69, 0x4b, 0x6f, 0x79, 0x72, 0x61, 0x20, 0x63, 0x69, 0x69,
+0x6e, 0x69, 0x4b, 0x70, 0x25b, 0x6c, 0x25b, 0x25b, 0x6b, 0x75, 0x72, 0x64,
+0xee, 0x20, 0x28, 0x6b, 0x75, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0xee, 0x29,
+0x54, 0x69, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b, 0x77, 0x61, 0x73, 0x69,
+0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x6e, 0x43a, 0x44b, 0x440, 0x433,
+0x44b, 0x437, 0x447, 0x430, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442,
+0x430, 0x43d, 0x4c, 0x61, 0x6b, 0x21f, 0xf3, 0x6c, 0x2bc, 0x69, 0x79, 0x61,
+0x70, 0x69, 0x4d, 0xed, 0x6c, 0x61, 0x68, 0x61, 0x14b, 0x73, 0x6b, 0x61,
+0x20, 0x54, 0x21f, 0x61, 0x6d, 0xe1, 0x6b, 0x21f, 0x6f, 0x10d, 0x68, 0x65,
+0x4b, 0x268, 0x6c, 0x61, 0x61, 0x6e, 0x67, 0x69, 0x54, 0x61, 0x61, 0x6e,
+0x73, 0x61, 0x6e, 0xed, 0x61, 0xea5, 0xeb2, 0xea7, 0x4c, 0x61, 0x74, 0x69,
+0x6e, 0x61, 0x43, 0x69, 0x76, 0x69, 0x74, 0x61, 0x73, 0x20, 0x56, 0x61,
+0x74, 0x69, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x61, 0x74, 0x76, 0x69, 0x65,
+0x161, 0x75, 0x4c, 0x61, 0x74, 0x76, 0x69, 0x6a, 0x61, 0x6c, 0x69, 0x6e,
+0x67, 0xe1, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0xed, 0x6b,
+0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x20, 0x44,
+0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x74, 0xed, 0x6b, 0x69, 0x41, 0x6e,
+0x67, 0xf3, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69,
+0x20, 0x79, 0x61, 0x20, 0x41, 0x66, 0x72, 0xed, 0x6b, 0x61, 0x20, 0x79,
+0x61, 0x20, 0x4b, 0xe1, 0x74, 0x69, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c,
+0x69, 0x65, 0x74, 0x75, 0x76, 0x69, 0x173, 0x4c, 0x69, 0x65, 0x74, 0x75,
+0x76, 0x61, 0x6c, 0x61, 0x20, 0x2e, 0x6c, 0x6f, 0x6a, 0x62, 0x61, 0x6e,
+0x2e, 0x64, 0x6f, 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107,
+0x69, 0x6e, 0x61, 0x4e, 0x69, 0x6d, 0x73, 0x6b, 0x61, 0x4e, 0x65, 0x64,
+0x64, 0x65, 0x72, 0x73, 0x61, 0x73, 0x73, 0x2019, 0x73, 0x63, 0x68, 0x44,
+0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x65,
+0x64, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x6e, 0x54, 0x73,
+0x68, 0x69, 0x6c, 0x75, 0x62, 0x61, 0x44, 0x69, 0x74, 0x75, 0x6e, 0x67,
+0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x75, 0x6a, 0x75,
+0x6c, 0x65, 0x76, 0x73, 0xe1, 0x6d, 0x65, 0x67, 0x69, 0x65, 0x6c, 0x6c,
+0x61, 0x44, 0x68, 0x6f, 0x6c, 0x75, 0x6f, 0x4c, 0xeb, 0x74, 0x7a, 0x65,
+0x62, 0x75, 0x65, 0x72, 0x67, 0x65, 0x73, 0x63, 0x68, 0x4c, 0x75, 0x6c,
+0x75, 0x68, 0x69, 0x61, 0x43c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441,
+0x43a, 0x438, 0x421, 0x435, 0x432, 0x435, 0x440, 0x43d, 0x430, 0x20, 0x41c, 0x430,
+0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x438, 0x458, 0x430, 0x4b, 0x69, 0x6d, 0x61,
+0x63, 0x68, 0x61, 0x6d, 0x65, 0x92e, 0x948, 0x925, 0x93f, 0x932, 0x940, 0x4d,
+0x61, 0x6b, 0x75, 0x61, 0x55, 0x6d, 0x6f, 0x7a, 0x61, 0x6d, 0x62, 0x69,
+0x6b, 0x69, 0x43, 0x68, 0x69, 0x6d, 0x61, 0x6b, 0x6f, 0x6e, 0x64, 0x65,
+0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x4d, 0x61, 0x64, 0x61,
+0x67, 0x61, 0x73, 0x69, 0x6b, 0x61, 0x72, 0x61, 0xd2e, 0xd32, 0xd2f, 0xd3e,
+0xd33, 0xd02, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d, 0x65, 0x6c, 0x61,
+0x79, 0x75, 0x628, 0x647, 0x627, 0x633, 0x20, 0x645, 0x644, 0x627, 0x64a, 0x648,
+0x628, 0x631, 0x648, 0x646, 0x64a, 0x645, 0x644, 0x64a, 0x633, 0x64a, 0x627, 0x42,
+0x72, 0x75, 0x6e, 0x65, 0x69, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75,
+0x72, 0x61, 0x4d, 0x61, 0x6c, 0x74, 0x69, 0x9ae, 0x9c8, 0x9a4, 0x9c8, 0x9b2,
+0x9cb, 0x9a8, 0x9cd, 0x987, 0x9a8, 0x9cd, 0x9a6, 0x9bf, 0x9af, 0x9bc, 0x9be, 0xabc3,
+0xabe4, 0xabc7, 0xabe9, 0xabc2, 0xabe3, 0xabdf, 0x47, 0x61, 0x65, 0x6c, 0x67, 0x45,
+0x6c, 0x6c, 0x61, 0x6e, 0x20, 0x56, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x4d,
+0x101, 0x6f, 0x72, 0x69, 0x41, 0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f, 0x61,
+0x4d, 0x61, 0x70, 0x75, 0x64, 0x75, 0x6e, 0x67, 0x75, 0x6e, 0x92e, 0x930,
+0x93e, 0x920, 0x940, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x61, 0x645,
+0x627, 0x632, 0x631, 0x648, 0x646, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x4b,
+0x129, 0x6d, 0x129, 0x72, 0x169, 0x6d, 0x65, 0x74, 0x61, 0x2bc, 0x4b, 0x61,
+0x6d, 0x61, 0x6c, 0x75, 0x6e, 0x4b, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x2bc,
+0x6b, 0xe9, 0x68, 0x61, 0x43c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x41c, 0x43e,
+0x43d, 0x433, 0x43e, 0x43b, 0x182e, 0x1823, 0x1829, 0x182d, 0x1823, 0x182f, 0x6b, 0x72,
+0x65, 0x6f, 0x6c, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e,
+0x4d, 0x6f, 0x72, 0x69, 0x73, 0x4d, 0x55, 0x4e, 0x44, 0x41, 0x14a, 0x6b,
+0x61, 0x6d, 0x65, 0x72, 0x75, 0x14b, 0x4d, 0x76, 0x73, 0x6b, 0x6f, 0x6b,
+0x65, 0x4b, 0x68, 0x6f, 0x65, 0x6b, 0x68, 0x6f, 0x65, 0x67, 0x6f, 0x77,
+0x61, 0x62, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x62, 0x44, 0x69,
+0x6e, 0xe9, 0x20, 0x42, 0x69, 0x7a, 0x61, 0x61, 0x64, 0x928, 0x947, 0x92a,
+0x93e, 0x932, 0x940, 0x53, 0x68, 0x77, 0xf3, 0x14b, 0xf2, 0x20, 0x6e, 0x67,
+0x69, 0x65, 0x6d, 0x62, 0x254, 0x254, 0x6e, 0x4b, 0xe0, 0x6d, 0x61, 0x6c,
+0xfb, 0x6d, 0x4e, 0x64, 0x61, 0xa78c, 0x61, 0x4b, 0x61, 0x6d, 0x25b, 0x6c,
+0xfb, 0x6e, 0x4e, 0x61, 0x69, 0x6a, 0xed, 0x72, 0x69, 0xe1, 0x20, 0x50,
+0xed, 0x6a, 0x69, 0x6e, 0x4e, 0x61, 0x69, 0x6a, 0xed, 0x72, 0x69, 0x61,
+0x7d2, 0x7de, 0x7cf, 0x7d6, 0x7cc, 0x7ec, 0x7e3, 0x7cd, 0x7eb, 0x644, 0x6ca, 0x631,
+0x6cc, 0x20, 0x634, 0x648, 0x645, 0x627, 0x644, 0x6cc, 0x64, 0x61, 0x76, 0x76,
+0x69, 0x73, 0xe1, 0x6d, 0x65, 0x67, 0x69, 0x65, 0x6c, 0x6c, 0x61, 0x4e,
+0x6f, 0x72, 0x67, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x52, 0x75,
+0x6f, 0x167, 0x167, 0x61, 0x53, 0x65, 0x73, 0x6f, 0x74, 0x68, 0x6f, 0x20,
+0x73, 0x61, 0x20, 0x4c, 0x65, 0x62, 0x6f, 0x61, 0x41, 0x66, 0x72, 0x69,
+0x6b, 0x61, 0x20, 0x42, 0x6f, 0x72, 0x77, 0x61, 0x69, 0x73, 0x69, 0x4e,
+0x64, 0x65, 0x62, 0x65, 0x6c, 0x65, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20,
+0x62, 0x6f, 0x6b, 0x6d, 0xe5, 0x6c, 0x4e, 0x6f, 0x72, 0x67, 0x65, 0x53,
+0x76, 0x61, 0x6c, 0x62, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x67, 0x20, 0x4a,
+0x61, 0x6e, 0x20, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x6f, 0x72, 0x73,
+0x6b, 0x20, 0x6e, 0x79, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x4e, 0x6f, 0x72,
+0x65, 0x67, 0x54, 0x68, 0x6f, 0x6b, 0x20, 0x4e, 0x61, 0x74, 0x68, 0x4e,
+0x79, 0x61, 0x6e, 0x6a, 0x61, 0x52, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x6b,
+0x6f, 0x72, 0x65, 0x6f, 0x63, 0x63, 0x69, 0x74, 0x61, 0x6e, 0x45, 0x73,
+0x70, 0x61, 0x6e, 0x68, 0x61, 0xb13, 0xb21, 0xb3c, 0xb3f, 0xb06, 0xb2d, 0xb3e,
+0xb30, 0xb24, 0x4f, 0x72, 0x6f, 0x6d, 0x6f, 0x6f, 0x49, 0x74, 0x6f, 0x6f,
+0x70, 0x68, 0x69, 0x79, 0x61, 0x61, 0x4b, 0x65, 0x65, 0x6e, 0x69, 0x79,
+0x61, 0x61, 0xd801, 0xdccf, 0xd801, 0xdcd8, 0xd801, 0xdcfb, 0xd801, 0xdcd8, 0xd801, 0xdcfb,
+0xd801, 0xdcdf, 0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434, 0x437,
+0x44b, 0x441, 0x442, 0x43e, 0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441, 0x435, 0x50,
+0x61, 0x70, 0x69, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x75, 0x4b, 0xf2, 0x72,
+0x73, 0x6f, 0x75, 0x67e, 0x69a, 0x62a, 0x648, 0x627, 0x641, 0x63a, 0x627, 0x646,
+0x633, 0x62a, 0x627, 0x646, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x641,
+0x627, 0x631, 0x633, 0x6cc, 0x62f, 0x631, 0x6cc, 0x70, 0x6f, 0x6c, 0x73, 0x6b,
+0x69, 0x50, 0x6f, 0x6c, 0x73, 0x6b, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x75,
+0x67, 0x75, 0xea, 0x73, 0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x41, 0x6e,
+0x67, 0x6f, 0x6c, 0x61, 0x43, 0x61, 0x62, 0x6f, 0x20, 0x56, 0x65, 0x72,
+0x64, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x45, 0x71, 0x75, 0x61,
+0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x2d,
+0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62,
+0x75, 0x72, 0x67, 0x6f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x2c, 0x20, 0x52,
+0x41, 0x45, 0x20, 0x64, 0x61, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d,
+0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x70, 0x6f, 0x72,
+0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x75, 0x50, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x6c, 0x53, 0xe3,
+0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed,
+0x6e, 0x63, 0x69, 0x70, 0x65, 0x53, 0x75, 0xed, 0xe7, 0x61, 0x54, 0x69,
+0x6d, 0x6f, 0x72, 0x2d, 0x4c, 0x65, 0x73, 0x74, 0x65, 0x70, 0x72, 0x16b,
+0x73, 0x69, 0x73, 0x6b, 0x61, 0x6e, 0x50, 0x14d, 0x6c, 0x69, 0xa2a, 0xa70,
+0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e, 0x646, 0x62c, 0x627,
+0x628, 0x6cc, 0x52, 0x75, 0x6e, 0x61, 0x73, 0x69, 0x6d, 0x69, 0x50, 0x65,
+0x72, 0xfa, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x45, 0x63, 0x75,
+0x61, 0x64, 0x6f, 0x72, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x103, 0x52, 0x6f,
+0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69,
+0x63, 0x61, 0x20, 0x4d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x61, 0x72, 0x75,
+0x6d, 0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76, 0x69, 0x7a, 0x72,
+0x61, 0x4b, 0x69, 0x68, 0x6f, 0x72, 0x6f, 0x6d, 0x62, 0x6f, 0x49, 0x6b,
+0x69, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e,
+0x64, 0x69, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x420, 0x43e, 0x441,
+0x441, 0x438, 0x44f, 0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x442, 0x430, 0x43d,
+0x41a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b, 0x434,
+0x43e, 0x432, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430, 0x4b, 0x69,
+0x72, 0x75, 0x77, 0x61, 0x53, 0x61, 0x68, 0x6f, 0x441, 0x430, 0x445, 0x430,
+0x20, 0x442, 0x44b, 0x43b, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b,
+0x439, 0x430, 0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75, 0x72, 0x53, 0xe4,
+0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6, 0x72, 0xf6, 0x73, 0xea, 0x73,
+0x65, 0x20, 0x74, 0xee, 0x20, 0x42, 0xea, 0x61, 0x66, 0x72, 0xee, 0x6b,
+0x61, 0x49, 0x73, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x67, 0x75, 0x54, 0x61,
+0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x938, 0x902, 0x938, 0x94d, 0x915,
+0x943, 0x924, 0x20, 0x92d, 0x93e, 0x937, 0x93e, 0x92d, 0x93e, 0x930, 0x924, 0x903,
+0x1c65, 0x1c5f, 0x1c71, 0x1c5b, 0x1c5f, 0x1c72, 0x1c64, 0x1c64, 0x1c71, 0x1c70, 0x1c64, 0x1c6d,
+0x1c5f, 0x938, 0x93e, 0x928, 0x924, 0x93e, 0x921, 0x93c, 0x940, 0x73, 0x61, 0x72,
+0x64, 0x75, 0x73, 0x65, 0x6e, 0x61, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438,
+0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x41a, 0x43e, 0x441, 0x43e, 0x432, 0x43e,
+0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x73, 0x72, 0x70,
+0x73, 0x6b, 0x69, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f, 0x43, 0x72, 0x6e,
+0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61,
+0x4b, 0x69, 0x73, 0x68, 0x61, 0x6d, 0x62, 0x61, 0x61, 0x63, 0x68, 0x69,
+0x53, 0x68, 0x6f, 0x6e, 0x61, 0xa188, 0xa320, 0xa259, 0xa34f, 0xa1e9, 0x73, 0x69,
+0x63, 0x69, 0x6c, 0x69, 0x61, 0x6e, 0x75, 0x53, 0x69, 0x64, 0x61, 0x61,
+0x6d, 0x75, 0x20, 0x41, 0x66, 0x6f, 0x49, 0x74, 0x69, 0x79, 0x6f, 0x6f,
+0x70, 0x68, 0x69, 0x79, 0x61, 0x15b, 0x6c, 0x14d, 0x6e, 0x73, 0x6b, 0x69,
+0x633, 0x646, 0x68c, 0x64a, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x938,
+0x93f, 0x928, 0x94d, 0x927, 0x940, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca,
+0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0xdc0, 0x73, 0xe4, 0xe4,
+0x2b9, 0x6d, 0x1e9, 0x69, 0xf5, 0x6c, 0x6c, 0x4c, 0xe4, 0xe4, 0x2b9, 0x64,
+0x64, 0x6a, 0xe2, 0x6e, 0x6e, 0x61, 0x6d, 0x73, 0x6c, 0x6f, 0x76, 0x65,
+0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x73,
+0x6b, 0x6f, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x161, 0x10d, 0x69, 0x6e,
+0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x6a, 0x61, 0x4f, 0x6c,
+0x75, 0x73, 0x6f, 0x67, 0x61, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c,
+0x69, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x79, 0x61, 0x4a,
+0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x69,
+0x79, 0x61, 0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x20, 0x62e, 0x648, 0x627, 0x631,
+0x6af, 0xc5, 0x61, 0x72, 0x6a, 0x65, 0x6c, 0x73, 0x61, 0x65, 0x6d, 0x69,
+0x65, 0x6e, 0x20, 0x67, 0xef, 0x65, 0x6c, 0x65, 0x65, 0x73, 0x70, 0x61,
+0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1,
+0x61, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x42, 0x65,
+0x6c, 0x69, 0x63, 0x65, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x61, 0x73,
+0x43, 0x65, 0x75, 0x74, 0x61, 0x20, 0x79, 0x20, 0x4d, 0x65, 0x6c, 0x69,
+0x6c, 0x6c, 0x61, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6f,
+0x6d, 0x62, 0x69, 0x61, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x20, 0x52, 0x69,
+0x63, 0x61, 0x43, 0x75, 0x62, 0x61, 0x52, 0x65, 0x70, 0xfa, 0x62, 0x6c,
+0x69, 0x63, 0x61, 0x20, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61,
+0x6e, 0x61, 0x45, 0x6c, 0x20, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f,
+0x72, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x20, 0x45, 0x63, 0x75, 0x61,
+0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d,
+0x61, 0x6c, 0x61, 0x48, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x61, 0x73, 0x65,
+0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x6c, 0x61, 0x74, 0x69, 0x6e,
+0x6f, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x4c, 0x61,
+0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0xe9, 0x72, 0x69, 0x63, 0x61, 0x65,
+0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0xe9,
+0x78, 0x69, 0x63, 0x6f, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4e, 0x69,
+0x63, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x50, 0x61, 0x6e, 0x61, 0x6d,
+0xe1, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x46, 0x69, 0x6c,
+0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f,
+0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x55, 0x72, 0x75, 0x67,
+0x75, 0x61, 0x79, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61,
+0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49, 0x2d56, 0x2d5c, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54,
+0x2d49, 0x2d31, 0x42, 0x61, 0x73, 0x61, 0x20, 0x53, 0x75, 0x6e, 0x64, 0x61,
+0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69, 0x6c, 0x69, 0x4a, 0x61, 0x6d,
+0x68, 0x75, 0x72, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x69, 0x64, 0x65,
+0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x73, 0x69, 0x61, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x73, 0x69, 0x53, 0x77, 0x61, 0x74, 0x69,
+0x65, 0x53, 0x77, 0x61, 0x74, 0x69, 0x6e, 0x69, 0x73, 0x76, 0x65, 0x6e,
+0x73, 0x6b, 0x61, 0x53, 0x76, 0x65, 0x72, 0x69, 0x67, 0x65, 0xc5, 0x6c,
+0x61, 0x6e, 0x64, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72,
+0x74, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x46, 0x72, 0x61, 0x6e, 0x6b,
+0x72, 0x69, 0x69, 0x63, 0x68, 0x4c, 0x69, 0xe4, 0x63, 0x68, 0x74, 0x65,
+0x73, 0x63, 0x68, 0x74, 0xe4, 0x69, 0x723, 0x718, 0x72a, 0x71d, 0x71d, 0x710,
+0x725, 0x71d, 0x72a, 0x729, 0x723, 0x718, 0x72a, 0x71d, 0x710, 0x2d5c, 0x2d30, 0x2d5b,
+0x2d4d, 0x2d43, 0x2d49, 0x2d5c, 0x54, 0x61, 0x73, 0x68, 0x65, 0x6c, 0x1e25, 0x69,
+0x79, 0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0xaabc, 0xaa95, 0xaa92, 0xaabe,
+0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61, 0x442, 0x43e, 0x4b7, 0x438, 0x43a,
+0x4e3, 0x422, 0x43e, 0x4b7, 0x438, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0xba4,
+0xbae, 0xbbf, 0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xbae,
+0xbb2, 0xbc7, 0xb9a, 0xbbf, 0xbaf, 0xbbe, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa,
+0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x70,
+0x61, 0x74, 0x61, 0x73, 0x20, 0x54, 0x61, 0x72, 0x6f, 0x6b, 0x6f, 0x54,
+0x61, 0x73, 0x61, 0x77, 0x61, 0x71, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69,
+0x4e, 0x69, 0x17e, 0x65, 0x72, 0x442, 0x430, 0x442, 0x430, 0x440, 0xc24, 0xc46,
+0xc32, 0xc41, 0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0xc26, 0xc47, 0xc36, 0xc02,
+0x4b, 0x69, 0x74, 0x65, 0x73, 0x6f, 0x4b, 0x65, 0x6e, 0x69, 0x61, 0xe44,
+0xe17, 0xe22, 0xf56, 0xf7c, 0xf51, 0xf0b, 0xf66, 0xf90, 0xf51, 0xf0b, 0xf62, 0xf92,
+0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0x1275,
+0x130d, 0x1228, 0x1275, 0x130d, 0x122d, 0x129b, 0x54, 0x6f, 0x6b, 0x20, 0x50, 0x69,
+0x73, 0x69, 0x6e, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x69, 0x75,
+0x67, 0x69, 0x6e, 0x69, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61,
+0x74, 0x6f, 0x6e, 0x67, 0x61, 0x58, 0x69, 0x74, 0x73, 0x6f, 0x6e, 0x67,
+0x61, 0x53, 0x65, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x41, 0x66, 0x6f,
+0x72, 0x69, 0x6b, 0x61, 0x20, 0x42, 0x6f, 0x72, 0x77, 0x61, 0x54, 0xfc,
+0x72, 0x6b, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b,
+0x131, 0x62, 0x72, 0x131, 0x73, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e,
+0x20, 0x64, 0x69, 0x6c, 0x69, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e,
+0x69, 0x73, 0x74, 0x61, 0x6e, 0x4b, 0x61, 0x74, 0x61, 0x62, 0x443, 0x43a,
+0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x423, 0x43a, 0x440, 0x430,
+0x457, 0x43d, 0x430, 0x68, 0x6f, 0x72, 0x6e, 0x6a, 0x6f, 0x73, 0x65, 0x72,
+0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e, 0x11b, 0x6d, 0x73, 0x6b, 0x61,
+0x627, 0x631, 0x62f, 0x648, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x626, 0x6c7, 0x64a,
+0x63a, 0x6c7, 0x631, 0x686, 0x6d5, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x6f, 0x2018,
+0x7a, 0x62, 0x65, 0x6b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73,
+0x74, 0x6f, 0x6e, 0x627, 0x648, 0x632, 0x628, 0x6cc, 0x6a9, 0x45e, 0x437, 0x431,
+0x435, 0x43a, 0x447, 0x430, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442,
+0x43e, 0x43d, 0xa559, 0xa524, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x56, 0x61, 0x69, 0x4c,
+0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x54, 0x73, 0x68, 0x69, 0x76,
+0x65, 0x6e, 0x1e13, 0x61, 0x54, 0x69, 0x1ebf, 0x6e, 0x67, 0x20, 0x56, 0x69,
+0x1ec7, 0x74, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x56, 0x6f,
+0x6c, 0x61, 0x70, 0xfc, 0x6b, 0x4b, 0x79, 0x69, 0x76, 0x75, 0x6e, 0x6a,
+0x6f, 0x77, 0x61, 0x6c, 0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x73, 0x65, 0x72,
+0x53, 0x63, 0x68, 0x77, 0x69, 0x7a, 0x57, 0x61, 0x72, 0x6c, 0x70, 0x69,
+0x72, 0x69, 0x43, 0x79, 0x6d, 0x72, 0x61, 0x65, 0x67, 0x59, 0x20, 0x44,
+0x65, 0x79, 0x72, 0x6e, 0x61, 0x73, 0x20, 0x55, 0x6e, 0x65, 0x64, 0x69,
+0x67, 0x628, 0x644, 0x648, 0x686, 0x6cc, 0x20, 0x28, 0x631, 0x62e, 0x634, 0x627,
+0x646, 0x6cc, 0x29, 0x626, 0x648, 0x645, 0x627, 0x646, 0x645, 0x62a, 0x62d, 0x62f,
+0x6cc, 0x646, 0x20, 0x639, 0x631, 0x628, 0x6cc, 0x646, 0x20, 0x627, 0x645, 0x627,
+0x631, 0x627, 0x62a, 0x46, 0x72, 0x79, 0x73, 0x6b, 0x4e, 0x65, 0x64, 0x65,
+0x72, 0x6c, 0xe2, 0x6e, 0x12c8, 0x120b, 0x12ed, 0x1273, 0x1271, 0x57, 0x6f, 0x6c,
+0x6f, 0x66, 0x49, 0x73, 0x69, 0x58, 0x68, 0x6f, 0x73, 0x61, 0x45, 0x4d,
+0x7a, 0x61, 0x6e, 0x74, 0x73, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b,
+0x61, 0x6e, 0x75, 0x61, 0x73, 0x75, 0x65, 0x4b, 0x65, 0x6d, 0x65, 0x6c,
+0xfa, 0x6e, 0x5d9, 0x5d9, 0x5b4, 0x5d3, 0x5d9, 0x5e9, 0x5d0, 0x5d5, 0x5e7, 0x5e8,
+0x5d0, 0x5b7, 0x5d9, 0x5e0, 0x5e2, 0xc8, 0x64, 0xe8, 0x20, 0x59, 0x6f, 0x72,
+0xf9, 0x62, 0xe1, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x42,
+0x25b, 0x300, 0x6e, 0x25b, 0x300, 0x5a, 0x61, 0x72, 0x6d, 0x61, 0x63, 0x69,
+0x69, 0x6e, 0x65, 0x56, 0x61, 0x68, 0x63, 0x75, 0x65, 0x6e, 0x67, 0x68,
+0x43, 0x75, 0x6e, 0x67, 0x68, 0x67, 0x6f, 0x7a, 0x69, 0x73, 0x69, 0x5a,
+0x75, 0x6c, 0x75, 0x69, 0x4e, 0x69, 0x6e, 0x67, 0x69, 0x7a, 0x69, 0x6d,
+0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x68,
+0x67, 0xe1, 0x67, 0x4d, 0x72, 0x61, 0x73, 0x69, 0x72, 0x6e, 0x68, 0x65,
+0x1ebd, 0x67, 0x61, 0x74, 0x75, 0x42, 0x72, 0x61, 0x73, 0x69, 0x75, 0xf1,
+0x65, 0x6e, 0x67, 0x61, 0x74, 0xfa, 0x4b, 0x75, 0x72, 0x169, 0x62, 0x69,
+0x79, 0x61, 0x57, 0x65, 0x6e, 0x65, 0x73, 0x75, 0x65, 0x72, 0x61, 0x939,
+0x930, 0x93f, 0x92f, 0x93e, 0x923, 0x935, 0x940, 0x4e, 0x6f, 0x72, 0x64, 0x66,
+0x72, 0x69, 0x69, 0x73, 0x6b, 0x54, 0x6a, 0x69, 0x69, 0x73, 0x6b, 0x6c,
+0x75, 0x6e, 0x930, 0x93e, 0x91c, 0x938, 0x94d, 0x925, 0x93e, 0x928, 0x940, 0x43c,
+0x43e, 0x43a, 0x448, 0x435, 0x43d, 0x44c, 0x20, 0x43a, 0x44f, 0x43b, 0x44c, 0x74,
+0x6f, 0x6b, 0x69, 0x20, 0x70, 0x6f, 0x6e, 0x61, 0x6d, 0x61, 0x20, 0x61,
+0x6c, 0x65, 0x50, 0x69, 0x6a, 0x69, 0x6e, 0x53, 0x6f, 0x6c, 0x6f, 0x6d,
+0x6f, 0x6e, 0x20, 0x41, 0x65, 0x6c, 0x61, 0x6e, 0x4f, 0x62, 0x6f, 0x6c,
+0x6f, 0x628, 0x644, 0x6c6, 0x686, 0x6cc, 0x42, 0x61, 0x6c, 0xf3, 0x63, 0x68,
+0x69, 0x50, 0xe1, 0x6b, 0x65, 0x73, 0x74, 0xe1, 0x6e, 0x6c, 0x69, 0x67,
+0x75, 0x72, 0x65, 0xd803, 0xdd0c, 0xd803, 0xdd17, 0xd803, 0xdd25, 0xd803, 0xdd1d, 0xd803,
+0xdd19, 0xd803, 0xdd1a, 0xd803, 0xdd12, 0xd803, 0xdd19, 0xd803, 0xdd1d, 0x62a, 0x648, 0x631,
+0x648, 0x627, 0x644, 0x6cc, 0x61, 0x6e, 0x69, 0x69, 0x20, 0x6b, 0x61, 0x67,
+0x269, 0x6a, 0x61, 0x42, 0x65, 0x6e, 0x25b, 0x25b, 0x915, 0x93e, 0x902, 0x917,
+0x921, 0x93c, 0x940, 0x76, 0x65, 0x6e, 0x65, 0x74, 0x6f
};
-static const char language_name_list[] =
+static constexpr char language_name_list[] =
"Default\0"
"C\0"
"Abkhazian\0"
-"Oromo\0"
"Afar\0"
"Afrikaans\0"
+"Aghem\0"
+"Akan\0"
+"Akkadian\0"
+"Akoose\0"
"Albanian\0"
+"American Sign Language\0"
"Amharic\0"
+"Ancient Egyptian\0"
+"Ancient Greek\0"
"Arabic\0"
+"Aragonese\0"
+"Aramaic\0"
"Armenian\0"
"Assamese\0"
+"Asturian\0"
+"Asu\0"
+"Atsam\0"
+"Avaric\0"
+"Avestan\0"
"Aymara\0"
"Azerbaijani\0"
+"Bafia\0"
+"Balinese\0"
+"Bambara\0"
+"Bamun\0"
+"Bangla\0"
+"Basaa\0"
"Bashkir\0"
"Basque\0"
-"Bengali\0"
-"Dzongkha\0"
-"Bihari\0"
+"Batak Toba\0"
+"Belarusian\0"
+"Bemba\0"
+"Bena\0"
+"Bhojpuri\0"
"Bislama\0"
+"Blin\0"
+"Bodo\0"
+"Bosnian\0"
"Breton\0"
+"Buginese\0"
"Bulgarian\0"
"Burmese\0"
-"Belarusian\0"
-"Khmer\0"
+"Cantonese\0"
"Catalan\0"
+"Cebuano\0"
+"Central Atlas Tamazight\0"
+"Central Kurdish\0"
+"Chakma\0"
+"Chamorro\0"
+"Chechen\0"
+"Cherokee\0"
+"Chickasaw\0"
+"Chiga\0"
"Chinese\0"
+"Church Slavic\0"
+"Chuvash\0"
+"Colognian\0"
+"Coptic\0"
+"Cornish\0"
"Corsican\0"
+"Cree\0"
"Croatian\0"
"Czech\0"
"Danish\0"
+"Divehi\0"
+"Dogri\0"
+"Duala\0"
"Dutch\0"
+"Dzongkha\0"
+"Embu\0"
"English\0"
+"Erzya\0"
"Esperanto\0"
"Estonian\0"
+"Ewe\0"
+"Ewondo\0"
"Faroese\0"
"Fijian\0"
+"Filipino\0"
"Finnish\0"
"French\0"
-"Western Frisian\0"
-"Gaelic\0"
+"Friulian\0"
+"Fula\0" // Fulah
+"Scottish Gaelic\0"
+"Ga\0"
"Galician\0"
+"Ganda\0"
+"Geez\0"
"Georgian\0"
"German\0"
+"Gothic\0"
"Greek\0"
-"Greenlandic\0"
"Guarani\0"
"Gujarati\0"
+"Gusii\0"
+"Haitian Creole\0"
"Hausa\0"
+"Hawaiian\0"
"Hebrew\0"
+"Herero\0"
"Hindi\0"
+"Hiri Motu\0"
"Hungarian\0"
"Icelandic\0"
+"Ido\0"
+"Igbo\0"
+"Inari Sami\0"
"Indonesian\0"
+"Ingush\0"
"Interlingua\0"
"Interlingue\0"
"Inuktitut\0"
-"Inupiak\0"
+"Inupiaq\0"
"Irish\0"
"Italian\0"
"Japanese\0"
"Javanese\0"
+"Jju\0"
+"Jola-Fonyi\0"
+"Kabuverdianu\0"
+"Kabyle\0"
+"Kako\0"
+"Kalaallisut\0"
+"Kalenjin\0"
+"Kamba\0"
"Kannada\0"
+"Kanuri\0"
"Kashmiri\0"
"Kazakh\0"
+"Kenyang\0"
+"Khmer\0"
+"Kʼicheʼ\0"
+"Kikuyu\0"
"Kinyarwanda\0"
-"Kirghiz\0"
+"Komi\0"
+"Kongo\0"
+"Konkani\0"
"Korean\0"
+"Koro\0"
+"Koyraboro Senni\0"
+"Koyra Chiini\0"
+"Kpelle\0"
+"Kuanyama\0"
"Kurdish\0"
-"Rundi\0"
+"Kwasio\0"
+"Kyrgyz\0"
+"Lakota\0"
+"Langi\0"
"Lao\0"
"Latin\0"
"Latvian\0"
+"Lezghian\0"
+"Limburgish\0"
"Lingala\0"
+"Literary Chinese\0"
"Lithuanian\0"
+"Lojban\0"
+"Lower Sorbian\0"
+"Low German\0"
+"Luba-Katanga\0"
+"Lule Sami\0"
+"Luo\0"
+"Luxembourgish\0"
+"Luyia\0"
"Macedonian\0"
+"Machame\0"
+"Maithili\0"
+"Makhuwa-Meetto\0"
+"Makonde\0"
"Malagasy\0"
-"Malay\0"
"Malayalam\0"
+"Malay\0"
"Maltese\0"
-"Maori\0"
+"Mandingo\0"
+"Manipuri\0"
+"Manx\0"
+"Māori\0"
+"Mapuche\0"
"Marathi\0"
"Marshallese\0"
+"Masai\0"
+"Mazanderani\0"
+"Mende\0"
+"Meru\0"
+"Metaʼ\0"
+"Mohawk\0"
"Mongolian\0"
+"Morisyen\0"
+"Mundang\0"
+"Muscogee\0"
+"Nama\0"
"Nauru\0"
+"Navajo\0"
+"Ndonga\0"
"Nepali\0"
-"Norwegian Bokmal\0"
+"Newari\0"
+"Ngiemboon\0"
+"Ngomba\0"
+"Nigerian Pidgin\0"
+"N’Ko\0"
+"Northern Luri\0"
+"Northern Sami\0"
+"Northern Sotho\0"
+"North Ndebele\0"
+"Norwegian Bokmål\0"
+"Norwegian Nynorsk\0"
+"Nuer\0"
+"Nyanja\0"
+"Nyankole\0"
"Occitan\0"
-"Oriya\0"
+"Odia\0"
+"Ojibwa\0"
+"Old Irish\0"
+"Old Norse\0"
+"Old Persian\0"
+"Oromo\0"
+"Osage\0"
+"Ossetic\0"
+"Pahlavi\0"
+"Palauan\0"
+"Pali\0"
+"Papiamento\0"
"Pashto\0"
"Persian\0"
+"Phoenician\0"
"Polish\0"
"Portuguese\0"
+"Prussian\0"
"Punjabi\0"
"Quechua\0"
-"Romansh\0"
"Romanian\0"
+"Romansh\0"
+"Rombo\0"
+"Rundi\0"
"Russian\0"
+"Rwa\0"
+"Saho\0"
+"Yakut\0" // Sakha
+"Samburu\0"
"Samoan\0"
"Sango\0"
+"Sangu\0"
"Sanskrit\0"
+"Santali\0"
+"Sardinian\0"
+"Saurashtra\0"
+"Sena\0"
"Serbian\0"
-"Ossetic\0"
-"Southern Sotho\0"
-"Tswana\0"
+"Shambala\0"
"Shona\0"
+"Sichuan Yi\0"
+"Sicilian\0"
+"Sidamo\0"
+"Silesian\0"
"Sindhi\0"
"Sinhala\0"
-"Swati\0"
+"Skolt Sami\0"
"Slovak\0"
"Slovenian\0"
+"Soga\0"
"Somali\0"
+"Southern Kurdish\0"
+"Southern Sami\0"
+"Southern Sotho\0"
+"South Ndebele\0"
"Spanish\0"
+"Standard Moroccan Tamazight\0"
"Sundanese\0"
"Swahili\0"
+"Swati\0"
"Swedish\0"
-"Sardinian\0"
+"Swiss German\0"
+"Syriac\0"
+"Tachelhit\0"
+"Tahitian\0"
+"Tai Dam\0"
+"Taita\0"
"Tajik\0"
"Tamil\0"
+"Taroko\0"
+"Tasawaq\0"
"Tatar\0"
"Telugu\0"
+"Teso\0"
"Thai\0"
"Tibetan\0"
+"Tigre\0"
"Tigrinya\0"
+"Tokelau\0"
+"Tok Pisin\0"
"Tongan\0"
"Tsonga\0"
+"Tswana\0"
"Turkish\0"
"Turkmen\0"
-"Tahitian\0"
-"Uighur\0"
+"Tuvalu\0"
+"Tyap\0"
+"Ugaritic\0"
"Ukrainian\0"
+"Upper Sorbian\0"
"Urdu\0"
+"Uyghur\0"
"Uzbek\0"
+"Vai\0"
+"Venda\0"
"Vietnamese\0"
-"Volapuk\0"
+"Volapük\0"
+"Vunjo\0"
+"Walloon\0"
+"Walser\0"
+"Warlpiri\0"
"Welsh\0"
+"Western Balochi\0"
+"Western Frisian\0"
+"Wolaytta\0"
"Wolof\0"
"Xhosa\0"
+"Yangben\0"
"Yiddish\0"
"Yoruba\0"
+"Zarma\0"
"Zhuang\0"
"Zulu\0"
-"Norwegian Nynorsk\0"
-"Bosnian\0"
-"Divehi\0"
-"Manx\0"
-"Cornish\0"
-"Akan\0"
-"Konkani\0"
-"Ga\0"
-"Igbo\0"
-"Kamba\0"
-"Syriac\0"
-"Blin\0"
-"Geez\0"
-"Koro\0"
-"Sidamo\0"
-"Atsam\0"
-"Tigre\0"
-"Jju\0"
-"Friulian\0"
-"Venda\0"
-"Ewe\0"
-"Walamo\0"
-"Hawaiian\0"
-"Tyap\0"
-"Nyanja\0"
-"Filipino\0"
-"Swiss German\0"
-"Sichuan Yi\0"
-"Kpelle\0"
-"Low German\0"
-"South Ndebele\0"
-"Northern Sotho\0"
-"Northern Sami\0"
-"Taroko\0"
-"Gusii\0"
-"Taita\0"
-"Fulah\0"
-"Kikuyu\0"
-"Samburu\0"
-"Sena\0"
-"North Ndebele\0"
-"Rombo\0"
-"Tachelhit\0"
-"Kabyle\0"
-"Nyankole\0"
-"Bena\0"
-"Vunjo\0"
-"Bambara\0"
-"Embu\0"
-"Cherokee\0"
-"Morisyen\0"
-"Makonde\0"
-"Langi\0"
-"Ganda\0"
-"Bemba\0"
-"Kabuverdianu\0"
-"Meru\0"
-"Kalenjin\0"
-"Nama\0"
-"Machame\0"
-"Colognian\0"
-"Masai\0"
-"Soga\0"
-"Luyia\0"
-"Asu\0"
-"Teso\0"
-"Saho\0"
-"Koyra Chiini\0"
-"Rwa\0"
-"Luo\0"
-"Chiga\0"
-"Central Morocco Tamazight\0"
-"Koyraboro Senni\0"
-"Shambala\0"
-"Bodo\0"
-"Avaric\0"
-"Chamorro\0"
-"Chechen\0"
-"Church\0"
-"Chuvash\0"
-"Cree\0"
-"Haitian\0"
-"Herero\0"
-"Hiri Motu\0"
-"Kanuri\0"
-"Komi\0"
-"Kongo\0"
-"Kwanyama\0"
-"Limburgish\0"
-"Luba Katanga\0"
-"Luxembourgish\0"
-"Navaho\0"
-"Ndonga\0"
-"Ojibwa\0"
-"Pali\0"
-"Walloon\0"
-"Aghem\0"
-"Basaa\0"
-"Zarma\0"
-"Duala\0"
-"Jola Fonyi\0"
-"Ewondo\0"
-"Bafia\0"
-"Makhuwa Meetto\0"
-"Mundang\0"
-"Kwasio\0"
-"Nuer\0"
-"Sakha\0"
-"Sangu\0"
-"Congo Swahili\0"
-"Tasawaq\0"
-"Vai\0"
-"Walser\0"
-"Yangben\0"
-"Avestan\0"
-"Asturian\0"
-"Ngomba\0"
-"Kako\0"
-"Meta\0"
-"Ngiemboon\0"
-"Aragonese\0"
-"Akkadian\0"
-"Ancient Egyptian\0"
-"Ancient Greek\0"
-"Aramaic\0"
-"Balinese\0"
-"Bamun\0"
-"Batak Toba\0"
-"Buginese\0"
-"Buhid\0"
-"Carian\0"
-"Chakma\0"
-"Classical Mandaic\0"
-"Coptic\0"
-"Dogri\0"
-"Eastern Cham\0"
-"Eastern Kayah\0"
-"Etruscan\0"
-"Gothic\0"
-"Hanunoo\0"
-"Ingush\0"
-"Large Flowery Miao\0"
-"Lepcha\0"
-"Limbu\0"
-"Lisu\0"
-"Lu\0"
-"Lycian\0"
-"Lydian\0"
-"Mandingo\0"
-"Manipuri\0"
-"Meroitic\0"
-"Northern Thai\0"
-"Old Irish\0"
-"Old Norse\0"
-"Old Persian\0"
-"Old Turkish\0"
-"Pahlavi\0"
-"Parthian\0"
-"Phoenician\0"
-"Prakrit Language\0"
-"Rejang\0"
-"Sabaean\0"
-"Samaritan\0"
-"Santali\0"
-"Saurashtra\0"
-"Sora\0"
-"Sylheti\0"
-"Tagbanwa\0"
-"Tai Dam\0"
-"Tai Nua\0"
-"Ugaritic\0"
-"Akoose\0"
-"Lakota\0"
-"Standard Moroccan Tamazight\0"
-"Mapuche\0"
-"Central Kurdish\0"
-"Lower Sorbian\0"
-"Upper Sorbian\0"
-"Kenyang\0"
-"Mohawk\0"
-"Nko\0"
-"Prussian\0"
-"Kiche\0"
-"Southern Sami\0"
-"Lule Sami\0"
-"Inari Sami\0"
-"Skolt Sami\0"
-"Warlpiri\0"
-"Manichaean Middle Persian\0"
-"Mende\0"
-"Ancient North Arabian\0"
-"Linear A\0"
-"Hmong Njua\0"
-"Ho\0"
-"Lezghian\0"
-"Bassa\0"
-"Mono\0"
-"Tedim Chin\0"
-"Maithili\0"
-"Ahom\0"
-"American Sign Language\0"
-"Ardhamagadhi Prakrit\0"
-"Bhojpuri\0"
-"Hieroglyphic Luwian\0"
-"Literary Chinese\0"
-"Mazanderani\0"
-"Mru\0"
-"Newari\0"
-"Northern Luri\0"
-"Palauan\0"
-"Papiamento\0"
-"Saraiki\0"
-"Tokelau\0"
-"Tok Pisin\0"
-"Tuvalu\0"
-"Uncoded Languages\0"
-"Cantonese\0"
-"Osage\0"
-"Tangut\0"
-"Ido\0"
-"Lojban\0"
-"Sicilian\0"
-"Southern Kurdish\0"
-"Western Balochi\0"
-"Cebuano\0"
-"Erzya\0"
-"Chickasaw\0"
-"Muscogee\0"
-"Silesian\0"
+"Kaingang\0"
+"Nheengatu\0"
+"Haryanvi\0"
+"Northern Frisian\0"
+"Rajasthani\0"
+"Moksha\0"
+"Toki Pona\0"
+"Pijin\0"
+"Obolo\0"
+"Baluchi\0"
+"Ligurian\0"
+"Rohingya\0"
+"Torwali\0"
+"Anii\0"
+"Kangri\0"
+"Venetian\0"
;
-static const quint16 language_name_index[] = {
+static constexpr quint16 language_name_index[] = {
0, // AnyLanguage
8, // C
10, // Abkhazian
- 20, // Oromo
- 26, // Afar
- 31, // Afrikaans
- 41, // Albanian
- 50, // Amharic
- 58, // Arabic
- 65, // Armenian
- 74, // Assamese
- 83, // Aymara
- 90, // Azerbaijani
- 102, // Bashkir
- 110, // Basque
- 117, // Bengali
- 125, // Dzongkha
- 134, // Bihari
- 141, // Bislama
- 149, // Breton
- 156, // Bulgarian
- 166, // Burmese
- 174, // Belarusian
- 185, // Khmer
- 191, // Catalan
- 199, // Chinese
- 207, // Corsican
- 216, // Croatian
- 225, // Czech
- 231, // Danish
- 238, // Dutch
- 244, // English
- 252, // Esperanto
- 262, // Estonian
- 271, // Faroese
- 279, // Fijian
- 286, // Finnish
- 294, // French
- 301, // Western Frisian
- 317, // Gaelic
- 324, // Galician
- 333, // Georgian
- 342, // German
- 349, // Greek
- 355, // Greenlandic
- 367, // Guarani
- 375, // Gujarati
- 384, // Hausa
- 390, // Hebrew
- 397, // Hindi
- 403, // Hungarian
- 413, // Icelandic
- 423, // Indonesian
- 434, // Interlingua
- 446, // Interlingue
- 458, // Inuktitut
- 468, // Inupiak
- 476, // Irish
- 482, // Italian
- 490, // Japanese
- 499, // Javanese
- 508, // Kannada
- 516, // Kashmiri
- 525, // Kazakh
- 532, // Kinyarwanda
- 544, // Kirghiz
- 552, // Korean
- 559, // Kurdish
- 567, // Rundi
- 573, // Lao
- 577, // Latin
- 583, // Latvian
- 591, // Lingala
- 599, // Lithuanian
- 610, // Macedonian
- 621, // Malagasy
- 630, // Malay
- 636, // Malayalam
- 646, // Maltese
- 654, // Maori
- 660, // Marathi
- 668, // Marshallese
- 680, // Mongolian
- 690, // Nauru
- 696, // Nepali
- 703, // Norwegian Bokmal
- 720, // Occitan
- 728, // Oriya
- 734, // Pashto
- 741, // Persian
- 749, // Polish
- 756, // Portuguese
- 767, // Punjabi
- 775, // Quechua
- 783, // Romansh
- 791, // Romanian
- 800, // Russian
- 808, // Samoan
- 815, // Sango
- 821, // Sanskrit
- 830, // Serbian
- 838, // Ossetic
- 846, // Southern Sotho
- 861, // Tswana
- 868, // Shona
- 874, // Sindhi
- 881, // Sinhala
- 889, // Swati
- 895, // Slovak
- 902, // Slovenian
- 912, // Somali
- 919, // Spanish
- 927, // Sundanese
- 937, // Swahili
- 945, // Swedish
- 953, // Sardinian
- 963, // Tajik
- 969, // Tamil
- 975, // Tatar
- 981, // Telugu
- 988, // Thai
- 993, // Tibetan
- 1001, // Tigrinya
- 1010, // Tongan
- 1017, // Tsonga
- 1024, // Turkish
- 1032, // Turkmen
- 1040, // Tahitian
- 1049, // Uighur
- 1056, // Ukrainian
- 1066, // Urdu
- 1071, // Uzbek
- 1077, // Vietnamese
- 1088, // Volapuk
- 1096, // Welsh
- 1102, // Wolof
- 1108, // Xhosa
- 1114, // Yiddish
- 1122, // Yoruba
- 1129, // Zhuang
- 1136, // Zulu
- 1141, // Norwegian Nynorsk
- 1159, // Bosnian
- 1167, // Divehi
- 1174, // Manx
- 1179, // Cornish
- 1187, // Akan
- 1192, // Konkani
- 1200, // Ga
- 1203, // Igbo
- 1208, // Kamba
- 1214, // Syriac
- 1221, // Blin
- 1226, // Geez
- 1231, // Koro
- 1236, // Sidamo
- 1243, // Atsam
- 1249, // Tigre
- 1255, // Jju
- 1259, // Friulian
- 1268, // Venda
- 1274, // Ewe
- 1278, // Walamo
- 1285, // Hawaiian
- 1294, // Tyap
- 1299, // Nyanja
- 1306, // Filipino
- 1315, // Swiss German
- 1328, // Sichuan Yi
- 1339, // Kpelle
- 1346, // Low German
- 1357, // South Ndebele
- 1371, // Northern Sotho
- 1386, // Northern Sami
- 1400, // Taroko
- 1407, // Gusii
- 1413, // Taita
- 1419, // Fulah
- 1425, // Kikuyu
- 1432, // Samburu
- 1440, // Sena
- 1445, // North Ndebele
- 1459, // Rombo
- 1465, // Tachelhit
- 1475, // Kabyle
- 1482, // Nyankole
- 1491, // Bena
- 1496, // Vunjo
- 1502, // Bambara
- 1510, // Embu
- 1515, // Cherokee
- 1524, // Morisyen
- 1533, // Makonde
- 1541, // Langi
- 1547, // Ganda
- 1553, // Bemba
- 1559, // Kabuverdianu
- 1572, // Meru
- 1577, // Kalenjin
- 1586, // Nama
- 1591, // Machame
- 1599, // Colognian
- 1609, // Masai
- 1615, // Soga
- 1620, // Luyia
- 1626, // Asu
- 1630, // Teso
- 1635, // Saho
- 1640, // Koyra Chiini
- 1653, // Rwa
- 1657, // Luo
- 1661, // Chiga
- 1667, // Central Morocco Tamazight
- 1693, // Koyraboro Senni
- 1709, // Shambala
- 1718, // Bodo
- 1723, // Avaric
- 1730, // Chamorro
- 1739, // Chechen
- 1747, // Church
- 1754, // Chuvash
- 1762, // Cree
- 1767, // Haitian
- 1775, // Herero
- 1782, // Hiri Motu
- 1792, // Kanuri
- 1799, // Komi
- 1804, // Kongo
- 1810, // Kwanyama
- 1819, // Limburgish
- 1830, // Luba Katanga
- 1843, // Luxembourgish
- 1857, // Navaho
- 1864, // Ndonga
- 1871, // Ojibwa
- 1878, // Pali
- 1883, // Walloon
- 1891, // Aghem
- 1897, // Basaa
- 1903, // Zarma
- 1909, // Duala
- 1915, // Jola Fonyi
- 1926, // Ewondo
- 1933, // Bafia
- 1939, // Makhuwa Meetto
- 1954, // Mundang
- 1962, // Kwasio
- 1969, // Nuer
- 1974, // Sakha
- 1980, // Sangu
- 1986, // Congo Swahili
- 2000, // Tasawaq
- 2008, // Vai
- 2012, // Walser
- 2019, // Yangben
- 2027, // Avestan
- 2035, // Asturian
- 2044, // Ngomba
- 2051, // Kako
- 2056, // Meta
- 2061, // Ngiemboon
- 2071, // Aragonese
- 2081, // Akkadian
- 2090, // Ancient Egyptian
- 2107, // Ancient Greek
- 2121, // Aramaic
- 2129, // Balinese
- 2138, // Bamun
- 2144, // Batak Toba
- 2155, // Buginese
- 2164, // Buhid
- 2170, // Carian
- 2177, // Chakma
- 2184, // Classical Mandaic
- 2202, // Coptic
- 2209, // Dogri
- 2215, // Eastern Cham
- 2228, // Eastern Kayah
- 2242, // Etruscan
- 2251, // Gothic
- 2258, // Hanunoo
- 2266, // Ingush
- 2273, // Large Flowery Miao
- 2292, // Lepcha
- 2299, // Limbu
- 2305, // Lisu
- 2310, // Lu
- 2313, // Lycian
- 2320, // Lydian
- 2327, // Mandingo
- 2336, // Manipuri
- 2345, // Meroitic
- 2354, // Northern Thai
- 2368, // Old Irish
- 2378, // Old Norse
- 2388, // Old Persian
- 2400, // Old Turkish
- 2412, // Pahlavi
- 2420, // Parthian
- 2429, // Phoenician
- 2440, // Prakrit Language
- 2457, // Rejang
- 2464, // Sabaean
- 2472, // Samaritan
- 2482, // Santali
- 2490, // Saurashtra
- 2501, // Sora
- 2506, // Sylheti
- 2514, // Tagbanwa
- 2523, // Tai Dam
- 2531, // Tai Nua
- 2539, // Ugaritic
- 2548, // Akoose
- 2555, // Lakota
- 2562, // Standard Moroccan Tamazight
- 2590, // Mapuche
- 2598, // Central Kurdish
- 2614, // Lower Sorbian
- 2628, // Upper Sorbian
- 2642, // Kenyang
- 2650, // Mohawk
- 2657, // Nko
- 2661, // Prussian
- 2670, // Kiche
- 2676, // Southern Sami
- 2690, // Lule Sami
- 2700, // Inari Sami
- 2711, // Skolt Sami
- 2722, // Warlpiri
- 2731, // Manichaean Middle Persian
- 2757, // Mende
- 2763, // Ancient North Arabian
- 2785, // Linear A
- 2794, // Hmong Njua
- 2805, // Ho
- 2808, // Lezghian
- 2817, // Bassa
- 2823, // Mono
- 2828, // Tedim Chin
- 2839, // Maithili
- 2848, // Ahom
- 2853, // American Sign Language
- 2876, // Ardhamagadhi Prakrit
- 2897, // Bhojpuri
- 2906, // Hieroglyphic Luwian
- 2926, // Literary Chinese
- 2943, // Mazanderani
- 2955, // Mru
- 2959, // Newari
- 2966, // Northern Luri
- 2980, // Palauan
- 2988, // Papiamento
- 2999, // Saraiki
- 3007, // Tokelau
- 3015, // Tok Pisin
- 3025, // Tuvalu
- 3032, // Uncoded Languages
- 3050, // Cantonese
- 3060, // Osage
- 3066, // Tangut
- 3073, // Ido
- 3077, // Lojban
- 3084, // Sicilian
- 3093, // Southern Kurdish
- 3110, // Western Balochi
- 3126, // Cebuano
- 3134, // Erzya
- 3140, // Chickasaw
- 3150, // Muscogee
- 3159, // Silesian
+ 20, // Afar
+ 25, // Afrikaans
+ 35, // Aghem
+ 41, // Akan
+ 46, // Akkadian
+ 55, // Akoose
+ 62, // Albanian
+ 71, // American Sign Language
+ 94, // Amharic
+ 102, // Ancient Egyptian
+ 119, // Ancient Greek
+ 133, // Arabic
+ 140, // Aragonese
+ 150, // Aramaic
+ 158, // Armenian
+ 167, // Assamese
+ 176, // Asturian
+ 185, // Asu
+ 189, // Atsam
+ 195, // Avaric
+ 202, // Avestan
+ 210, // Aymara
+ 217, // Azerbaijani
+ 229, // Bafia
+ 235, // Balinese
+ 244, // Bambara
+ 252, // Bamun
+ 258, // Bangla
+ 265, // Basaa
+ 271, // Bashkir
+ 279, // Basque
+ 286, // Batak Toba
+ 297, // Belarusian
+ 308, // Bemba
+ 314, // Bena
+ 319, // Bhojpuri
+ 328, // Bislama
+ 336, // Blin
+ 341, // Bodo
+ 346, // Bosnian
+ 354, // Breton
+ 361, // Buginese
+ 370, // Bulgarian
+ 380, // Burmese
+ 388, // Cantonese
+ 398, // Catalan
+ 406, // Cebuano
+ 414, // Central Atlas Tamazight
+ 438, // Central Kurdish
+ 454, // Chakma
+ 461, // Chamorro
+ 470, // Chechen
+ 478, // Cherokee
+ 487, // Chickasaw
+ 497, // Chiga
+ 503, // Chinese
+ 511, // Church
+ 525, // Chuvash
+ 533, // Colognian
+ 543, // Coptic
+ 550, // Cornish
+ 558, // Corsican
+ 567, // Cree
+ 572, // Croatian
+ 581, // Czech
+ 587, // Danish
+ 594, // Divehi
+ 601, // Dogri
+ 607, // Duala
+ 613, // Dutch
+ 619, // Dzongkha
+ 628, // Embu
+ 633, // English
+ 641, // Erzya
+ 647, // Esperanto
+ 657, // Estonian
+ 666, // Ewe
+ 670, // Ewondo
+ 677, // Faroese
+ 685, // Fijian
+ 692, // Filipino
+ 701, // Finnish
+ 709, // French
+ 716, // Friulian
+ 725, // Fulah
+ 730, // Gaelic
+ 746, // Ga
+ 749, // Galician
+ 758, // Ganda
+ 764, // Geez
+ 769, // Georgian
+ 778, // German
+ 785, // Gothic
+ 792, // Greek
+ 798, // Guarani
+ 806, // Gujarati
+ 815, // Gusii
+ 821, // Haitian
+ 836, // Hausa
+ 842, // Hawaiian
+ 851, // Hebrew
+ 858, // Herero
+ 865, // Hindi
+ 871, // Hiri Motu
+ 881, // Hungarian
+ 891, // Icelandic
+ 901, // Ido
+ 905, // Igbo
+ 910, // Inari Sami
+ 921, // Indonesian
+ 932, // Ingush
+ 939, // Interlingua
+ 951, // Interlingue
+ 963, // Inuktitut
+ 973, // Inupiaq
+ 981, // Irish
+ 987, // Italian
+ 995, // Japanese
+ 1004, // Javanese
+ 1013, // Jju
+ 1017, // Jola-Fonyi
+ 1028, // Kabuverdianu
+ 1041, // Kabyle
+ 1048, // Kako
+ 1053, // Kalaallisut
+ 1065, // Kalenjin
+ 1074, // Kamba
+ 1080, // Kannada
+ 1088, // Kanuri
+ 1095, // Kashmiri
+ 1104, // Kazakh
+ 1111, // Kenyang
+ 1119, // Khmer
+ 1125, // Kiche
+ 1135, // Kikuyu
+ 1142, // Kinyarwanda
+ 1154, // Komi
+ 1159, // Kongo
+ 1165, // Konkani
+ 1173, // Korean
+ 1180, // Koro
+ 1185, // Koyraboro Senni
+ 1201, // Koyra Chiini
+ 1214, // Kpelle
+ 1221, // Kuanyama
+ 1230, // Kurdish
+ 1238, // Kwasio
+ 1245, // Kyrgyz
+ 1252, // Lakota
+ 1259, // Langi
+ 1265, // Lao
+ 1269, // Latin
+ 1275, // Latvian
+ 1283, // Lezghian
+ 1292, // Limburgish
+ 1303, // Lingala
+ 1311, // Literary Chinese
+ 1328, // Lithuanian
+ 1339, // Lojban
+ 1346, // Lower Sorbian
+ 1360, // Low German
+ 1371, // Luba-Katanga
+ 1384, // Lule Sami
+ 1394, // Luo
+ 1398, // Luxembourgish
+ 1412, // Luyia
+ 1418, // Macedonian
+ 1429, // Machame
+ 1437, // Maithili
+ 1446, // Makhuwa-Meetto
+ 1461, // Makonde
+ 1469, // Malagasy
+ 1478, // Malayalam
+ 1488, // Malay
+ 1494, // Maltese
+ 1502, // Mandingo
+ 1511, // Manipuri
+ 1520, // Manx
+ 1525, // Maori
+ 1532, // Mapuche
+ 1540, // Marathi
+ 1548, // Marshallese
+ 1560, // Masai
+ 1566, // Mazanderani
+ 1578, // Mende
+ 1584, // Meru
+ 1589, // Meta
+ 1596, // Mohawk
+ 1603, // Mongolian
+ 1613, // Morisyen
+ 1622, // Mundang
+ 1630, // Muscogee
+ 1639, // Nama
+ 1644, // Nauru
+ 1650, // Navajo
+ 1657, // Ndonga
+ 1664, // Nepali
+ 1671, // Newari
+ 1678, // Ngiemboon
+ 1688, // Ngomba
+ 1695, // Nigerian Pidgin
+ 1711, // Nko
+ 1718, // Northern Luri
+ 1732, // Northern Sami
+ 1746, // Northern Sotho
+ 1761, // North Ndebele
+ 1775, // Norwegian Bokmal
+ 1793, // Norwegian Nynorsk
+ 1811, // Nuer
+ 1816, // Nyanja
+ 1823, // Nyankole
+ 1832, // Occitan
+ 1840, // Odia
+ 1845, // Ojibwa
+ 1852, // Old Irish
+ 1862, // Old Norse
+ 1872, // Old Persian
+ 1884, // Oromo
+ 1890, // Osage
+ 1896, // Ossetic
+ 1904, // Pahlavi
+ 1912, // Palauan
+ 1920, // Pali
+ 1925, // Papiamento
+ 1936, // Pashto
+ 1943, // Persian
+ 1951, // Phoenician
+ 1962, // Polish
+ 1969, // Portuguese
+ 1980, // Prussian
+ 1989, // Punjabi
+ 1997, // Quechua
+ 2005, // Romanian
+ 2014, // Romansh
+ 2022, // Rombo
+ 2028, // Rundi
+ 2034, // Russian
+ 2042, // Rwa
+ 2046, // Saho
+ 2051, // Sakha
+ 2057, // Samburu
+ 2065, // Samoan
+ 2072, // Sango
+ 2078, // Sangu
+ 2084, // Sanskrit
+ 2093, // Santali
+ 2101, // Sardinian
+ 2111, // Saurashtra
+ 2122, // Sena
+ 2127, // Serbian
+ 2135, // Shambala
+ 2144, // Shona
+ 2150, // Sichuan Yi
+ 2161, // Sicilian
+ 2170, // Sidamo
+ 2177, // Silesian
+ 2186, // Sindhi
+ 2193, // Sinhala
+ 2201, // Skolt Sami
+ 2212, // Slovak
+ 2219, // Slovenian
+ 2229, // Soga
+ 2234, // Somali
+ 2241, // Southern Kurdish
+ 2258, // Southern Sami
+ 2272, // Southern Sotho
+ 2287, // South Ndebele
+ 2301, // Spanish
+ 2309, // Standard Moroccan Tamazight
+ 2337, // Sundanese
+ 2347, // Swahili
+ 2355, // Swati
+ 2361, // Swedish
+ 2369, // Swiss German
+ 2382, // Syriac
+ 2389, // Tachelhit
+ 2399, // Tahitian
+ 2408, // Tai Dam
+ 2416, // Taita
+ 2422, // Tajik
+ 2428, // Tamil
+ 2434, // Taroko
+ 2441, // Tasawaq
+ 2449, // Tatar
+ 2455, // Telugu
+ 2462, // Teso
+ 2467, // Thai
+ 2472, // Tibetan
+ 2480, // Tigre
+ 2486, // Tigrinya
+ 2495, // Tokelau
+ 2503, // Tok Pisin
+ 2513, // Tongan
+ 2520, // Tsonga
+ 2527, // Tswana
+ 2534, // Turkish
+ 2542, // Turkmen
+ 2550, // Tuvalu
+ 2557, // Tyap
+ 2562, // Ugaritic
+ 2571, // Ukrainian
+ 2581, // Upper Sorbian
+ 2595, // Urdu
+ 2600, // Uyghur
+ 2607, // Uzbek
+ 2613, // Vai
+ 2617, // Venda
+ 2623, // Vietnamese
+ 2634, // Volapuk
+ 2643, // Vunjo
+ 2649, // Walloon
+ 2657, // Walser
+ 2664, // Warlpiri
+ 2673, // Welsh
+ 2679, // Western Balochi
+ 2695, // Western Frisian
+ 2711, // Wolaytta
+ 2720, // Wolof
+ 2726, // Xhosa
+ 2732, // Yangben
+ 2740, // Yiddish
+ 2748, // Yoruba
+ 2755, // Zarma
+ 2761, // Zhuang
+ 2768, // Zulu
+ 2773, // Kaingang
+ 2782, // Nheengatu
+ 2792, // Haryanvi
+ 2801, // Northern Frisian
+ 2818, // Rajasthani
+ 2829, // Moksha
+ 2836, // Toki Pona
+ 2846, // Pijin
+ 2852, // Obolo
+ 2858, // Baluchi
+ 2866, // Ligurian
+ 2875, // Rohingya
+ 2884, // Torwali
+ 2892, // Anii
+ 2897, // Kangri
+ 2904, // Venetian
};
-static const char script_name_list[] =
+static constexpr char script_name_list[] =
"Default\0"
+"Adlam\0"
+"Ahom\0"
+"Anatolian Hieroglyphs\0"
"Arabic\0"
-"Cyrillic\0"
-"Deseret\0"
-"Gurmukhi\0"
-"Simplified Han\0"
-"Traditional Han\0"
-"Latin\0"
-"Mongolian\0"
-"Tifinagh\0"
"Armenian\0"
-"Bengali\0"
-"Cherokee\0"
-"Devanagari\0"
-"Ethiopic\0"
-"Georgian\0"
-"Greek\0"
-"Gujarati\0"
-"Hebrew\0"
-"Japanese\0"
-"Khmer\0"
-"Kannada\0"
-"Korean\0"
-"Lao\0"
-"Malayalam\0"
-"Myanmar\0"
-"Oriya\0"
-"Tamil\0"
-"Telugu\0"
-"Thaana\0"
-"Thai\0"
-"Tibetan\0"
-"Sinhala\0"
-"Syriac\0"
-"Yi\0"
-"Vai\0"
"Avestan\0"
"Balinese\0"
"Bamum\0"
+"Bangla\0"
+"Bassa Vah\0"
"Batak\0"
+"Bhaiksuki\0"
"Bopomofo\0"
"Brahmi\0"
+"Braille\0"
"Buginese\0"
"Buhid\0"
-"Canadian Aboriginal\0"
+"Unified Canadian Aboriginal Syllabics\0"
"Carian\0"
+"Caucasian Albanian\0"
"Chakma\0"
"Cham\0"
+"Cherokee\0"
"Coptic\0"
+"Sumero-Akkadian Cuneiform\0"
"Cypriot\0"
-"Egyptian Hieroglyphs\0"
+"Cyrillic\0"
+"Deseret\0"
+"Devanagari\0"
+"Duployan shorthand\0"
+"Egyptian hieroglyphs\0"
+"Elbasan\0"
+"Ethiopic\0"
"Fraser\0"
+"Georgian\0"
"Glagolitic\0"
"Gothic\0"
-"Han\0"
+"Grantha\0"
+"Greek\0"
+"Gujarati\0"
+"Gurmukhi\0"
"Hangul\0"
+"Han\0"
"Hanunoo\0"
+"Han with Bopomofo\0"
+"Hatran\0"
+"Hebrew\0"
+"Hiragana\0"
"Imperial Aramaic\0"
"Inscriptional Pahlavi\0"
"Inscriptional Parthian\0"
+"Jamo\0"
+"Japanese\0"
"Javanese\0"
"Kaithi\0"
+"Kannada\0"
"Katakana\0"
"Kayah Li\0"
"Kharoshthi\0"
+"Khmer\0"
+"Khojki\0"
+"Khudawadi\0"
+"Korean\0"
"Lanna\0"
+"Lao\0"
+"Latin\0"
"Lepcha\0"
"Limbu\0"
+"Linear A\0"
"Linear B\0"
"Lycian\0"
"Lydian\0"
+"Mahajani\0"
+"Malayalam\0"
"Mandaean\0"
+"Manichaean\0"
+"Marchen\0"
"Meitei Mayek\0"
-"Meroitic\0"
+"Mende\0"
"Meroitic Cursive\0"
-"Nko\0"
+"Meroitic\0"
+"Modi\0"
+"Mongolian\0"
+"Mro\0"
+"Multani\0"
+"Myanmar\0"
+"Nabataean\0"
+"Newa\0"
"New Tai Lue\0"
+"N’Ko\0"
+"Odia\0"
"Ogham\0"
"Ol Chiki\0"
+"Old Hungarian\0"
"Old Italic\0"
+"Old North Arabian\0"
+"Old Permic\0"
"Old Persian\0"
"Old South Arabian\0"
"Orkhon\0"
+"Osage\0"
"Osmanya\0"
-"Phags Pa\0"
+"Pahawh Hmong\0"
+"Palmyrene\0"
+"Pau Cin Hau\0"
+"Phags-pa\0"
"Phoenician\0"
"Pollard Phonetic\0"
+"Psalter Pahlavi\0"
"Rejang\0"
"Runic\0"
"Samaritan\0"
"Saurashtra\0"
"Sharada\0"
"Shavian\0"
+"Siddham\0"
+"SignWriting\0"
+"Simplified Han\0"
+"Sinhala\0"
"Sora Sompeng\0"
-"Cuneiform\0"
"Sundanese\0"
"Syloti Nagri\0"
+"Syriac\0"
"Tagalog\0"
"Tagbanwa\0"
"Tai Le\0"
"Tai Viet\0"
"Takri\0"
-"Ugaritic\0"
-"Braille\0"
-"Hiragana\0"
-"Caucasian Albanian\0"
-"Bassa Vah\0"
-"Duployan\0"
-"Elbasan\0"
-"Grantha\0"
-"Pahawh Hmong\0"
-"Khojki\0"
-"Linear A\0"
-"Mahajani\0"
-"Manichaean\0"
-"Mende Kikakui\0"
-"Modi\0"
-"Mro\0"
-"Old North Arabian\0"
-"Nabataean\0"
-"Palmyrene\0"
-"Pau Cin Hau\0"
-"Old Permic\0"
-"Psalter Pahlavi\0"
-"Siddham\0"
-"Khudawadi\0"
+"Tamil\0"
+"Tangut\0"
+"Telugu\0"
+"Thaana\0"
+"Thai\0"
+"Tibetan\0"
+"Tifinagh\0"
"Tirhuta\0"
+"Traditional Han\0"
+"Ugaritic\0"
+"Vai\0"
"Varang Kshiti\0"
-"Ahom\0"
-"Anatolian Hieroglyphs\0"
-"Hatran\0"
-"Multani\0"
-"Old Hungarian\0"
-"Sign Writing\0"
-"Adlam\0"
-"Bhaiksuki\0"
-"Marchen\0"
-"Newa\0"
-"Osage\0"
-"Tangut\0"
-"Han with Bopomofo\0"
-"Jamo\0"
+"Yi\0"
+"Hanifi Rohingya\0"
;
-static const quint16 script_name_index[] = {
+static constexpr quint16 script_name_index[] = {
0, // AnyScript
- 8, // Arabic
- 15, // Cyrillic
- 24, // Deseret
- 32, // Gurmukhi
- 41, // Simplified Han
- 56, // Traditional Han
- 72, // Latin
- 78, // Mongolian
- 88, // Tifinagh
- 97, // Armenian
- 106, // Bengali
- 114, // Cherokee
- 123, // Devanagari
- 134, // Ethiopic
- 143, // Georgian
- 152, // Greek
- 158, // Gujarati
- 167, // Hebrew
- 174, // Japanese
- 183, // Khmer
- 189, // Kannada
- 197, // Korean
- 204, // Lao
- 208, // Malayalam
- 218, // Myanmar
- 226, // Oriya
- 232, // Tamil
- 238, // Telugu
- 245, // Thaana
- 252, // Thai
- 257, // Tibetan
- 265, // Sinhala
- 273, // Syriac
- 280, // Yi
- 283, // Vai
- 287, // Avestan
- 295, // Balinese
- 304, // Bamum
- 310, // Batak
- 316, // Bopomofo
- 325, // Brahmi
- 332, // Buginese
- 341, // Buhid
- 347, // Canadian Aboriginal
- 367, // Carian
- 374, // Chakma
- 381, // Cham
- 386, // Coptic
- 393, // Cypriot
- 401, // Egyptian Hieroglyphs
- 422, // Fraser
- 429, // Glagolitic
- 440, // Gothic
- 447, // Han
- 451, // Hangul
- 458, // Hanunoo
- 466, // Imperial Aramaic
- 483, // Inscriptional Pahlavi
- 505, // Inscriptional Parthian
- 528, // Javanese
- 537, // Kaithi
- 544, // Katakana
- 553, // Kayah Li
- 562, // Kharoshthi
- 573, // Lanna
- 579, // Lepcha
- 586, // Limbu
- 592, // Linear B
- 601, // Lycian
- 608, // Lydian
- 615, // Mandaean
- 624, // Meitei Mayek
- 637, // Meroitic
- 646, // Meroitic Cursive
- 663, // Nko
- 667, // New Tai Lue
- 679, // Ogham
- 685, // Ol Chiki
- 694, // Old Italic
- 705, // Old Persian
- 717, // Old South Arabian
- 735, // Orkhon
- 742, // Osmanya
- 750, // Phags Pa
- 759, // Phoenician
- 770, // Pollard Phonetic
- 787, // Rejang
- 794, // Runic
- 800, // Samaritan
- 810, // Saurashtra
- 821, // Sharada
- 829, // Shavian
- 837, // Sora Sompeng
- 850, // Cuneiform
- 860, // Sundanese
- 870, // Syloti Nagri
- 883, // Tagalog
- 891, // Tagbanwa
- 900, // Tai Le
- 907, // Tai Viet
- 916, // Takri
- 922, // Ugaritic
- 931, // Braille
- 939, // Hiragana
- 948, // Caucasian Albanian
- 967, // Bassa Vah
- 977, // Duployan
- 986, // Elbasan
- 994, // Grantha
- 1002, // Pahawh Hmong
- 1015, // Khojki
- 1022, // Linear A
- 1031, // Mahajani
- 1040, // Manichaean
- 1051, // Mende Kikakui
- 1065, // Modi
- 1070, // Mro
- 1074, // Old North Arabian
- 1092, // Nabataean
- 1102, // Palmyrene
- 1112, // Pau Cin Hau
- 1124, // Old Permic
- 1135, // Psalter Pahlavi
- 1151, // Siddham
- 1159, // Khudawadi
- 1169, // Tirhuta
- 1177, // Varang Kshiti
- 1191, // Ahom
- 1196, // Anatolian Hieroglyphs
- 1218, // Hatran
- 1225, // Multani
- 1233, // Old Hungarian
- 1247, // Sign Writing
- 1260, // Adlam
- 1266, // Bhaiksuki
- 1276, // Marchen
- 1284, // Newa
- 1289, // Osage
- 1295, // Tangut
- 1302, // Han with Bopomofo
- 1320, // Jamo
+ 8, // Adlam
+ 14, // Ahom
+ 19, // Anatolian Hieroglyphs
+ 41, // Arabic
+ 48, // Armenian
+ 57, // Avestan
+ 65, // Balinese
+ 74, // Bamum
+ 80, // Bangla
+ 87, // Bassa Vah
+ 97, // Batak
+ 103, // Bhaiksuki
+ 113, // Bopomofo
+ 122, // Brahmi
+ 129, // Braille
+ 137, // Buginese
+ 146, // Buhid
+ 152, // Canadian Aboriginal
+ 190, // Carian
+ 197, // Caucasian Albanian
+ 216, // Chakma
+ 223, // Cham
+ 228, // Cherokee
+ 237, // Coptic
+ 244, // Cuneiform
+ 270, // Cypriot
+ 278, // Cyrillic
+ 287, // Deseret
+ 295, // Devanagari
+ 306, // Duployan
+ 325, // Egyptian hieroglyphs
+ 346, // Elbasan
+ 354, // Ethiopic
+ 363, // Fraser
+ 370, // Georgian
+ 379, // Glagolitic
+ 390, // Gothic
+ 397, // Grantha
+ 405, // Greek
+ 411, // Gujarati
+ 420, // Gurmukhi
+ 429, // Hangul
+ 436, // Han
+ 440, // Hanunoo
+ 448, // Han with Bopomofo
+ 466, // Hatran
+ 473, // Hebrew
+ 480, // Hiragana
+ 489, // Imperial Aramaic
+ 506, // Inscriptional Pahlavi
+ 528, // Inscriptional Parthian
+ 551, // Jamo
+ 556, // Japanese
+ 565, // Javanese
+ 574, // Kaithi
+ 581, // Kannada
+ 589, // Katakana
+ 598, // Kayah Li
+ 607, // Kharoshthi
+ 618, // Khmer
+ 624, // Khojki
+ 631, // Khudawadi
+ 641, // Korean
+ 648, // Lanna
+ 654, // Lao
+ 658, // Latin
+ 664, // Lepcha
+ 671, // Limbu
+ 677, // Linear A
+ 686, // Linear B
+ 695, // Lycian
+ 702, // Lydian
+ 709, // Mahajani
+ 718, // Malayalam
+ 728, // Mandaean
+ 737, // Manichaean
+ 748, // Marchen
+ 756, // Meitei Mayek
+ 769, // Mende
+ 775, // Meroitic Cursive
+ 792, // Meroitic
+ 801, // Modi
+ 806, // Mongolian
+ 816, // Mro
+ 820, // Multani
+ 828, // Myanmar
+ 836, // Nabataean
+ 846, // Newa
+ 851, // New Tai Lue
+ 863, // Nko
+ 870, // Odia
+ 875, // Ogham
+ 881, // Ol Chiki
+ 890, // Old Hungarian
+ 904, // Old Italic
+ 915, // Old North Arabian
+ 933, // Old Permic
+ 944, // Old Persian
+ 956, // Old South Arabian
+ 974, // Orkhon
+ 981, // Osage
+ 987, // Osmanya
+ 995, // Pahawh Hmong
+ 1008, // Palmyrene
+ 1018, // Pau Cin Hau
+ 1030, // Phags-pa
+ 1039, // Phoenician
+ 1050, // Pollard Phonetic
+ 1067, // Psalter Pahlavi
+ 1083, // Rejang
+ 1090, // Runic
+ 1096, // Samaritan
+ 1106, // Saurashtra
+ 1117, // Sharada
+ 1125, // Shavian
+ 1133, // Siddham
+ 1141, // SignWriting
+ 1153, // Simplified Han
+ 1168, // Sinhala
+ 1176, // Sora Sompeng
+ 1189, // Sundanese
+ 1199, // Syloti Nagri
+ 1212, // Syriac
+ 1219, // Tagalog
+ 1227, // Tagbanwa
+ 1236, // Tai Le
+ 1243, // Tai Viet
+ 1252, // Takri
+ 1258, // Tamil
+ 1264, // Tangut
+ 1271, // Telugu
+ 1278, // Thaana
+ 1285, // Thai
+ 1290, // Tibetan
+ 1298, // Tifinagh
+ 1307, // Tirhuta
+ 1315, // Traditional Han
+ 1331, // Ugaritic
+ 1340, // Vai
+ 1344, // Varang Kshiti
+ 1358, // Yi
+ 1361, // Hanifi
};
-static const char country_name_list[] =
+static constexpr char territory_name_list[] =
"Default\0"
"Afghanistan\0"
+"Åland Islands\0"
"Albania\0"
"Algeria\0"
"American Samoa\0"
@@ -5500,10 +7190,11 @@ static const char country_name_list[] =
"Angola\0"
"Anguilla\0"
"Antarctica\0"
-"Antigua And Barbuda\0"
+"Antigua & Barbuda\0"
"Argentina\0"
"Armenia\0"
"Aruba\0"
+"Ascension Island\0"
"Australia\0"
"Austria\0"
"Azerbaijan\0"
@@ -5518,11 +7209,12 @@ static const char country_name_list[] =
"Bermuda\0"
"Bhutan\0"
"Bolivia\0"
-"Bosnia And Herzegowina\0"
+"Bosnia & Herzegovina\0"
"Botswana\0"
"Bouvet Island\0"
"Brazil\0"
"British Indian Ocean Territory\0"
+"British Virgin Islands\0"
"Brunei\0"
"Bulgaria\0"
"Burkina Faso\0"
@@ -5530,43 +7222,49 @@ static const char country_name_list[] =
"Cambodia\0"
"Cameroon\0"
"Canada\0"
+"Canary Islands\0"
"Cape Verde\0"
+"Caribbean Netherlands\0"
"Cayman Islands\0"
"Central African Republic\0"
+"Ceuta & Melilla\0"
"Chad\0"
"Chile\0"
"China\0"
"Christmas Island\0"
-"Cocos Islands\0"
+"Clipperton Island\0"
+"Cocos (Keeling) Islands\0"
"Colombia\0"
"Comoros\0"
-"Congo Kinshasa\0"
-"Congo Brazzaville\0"
+"Congo - Brazzaville\0"
+"Congo - Kinshasa\0"
"Cook Islands\0"
"Costa Rica\0"
-"Ivory Coast\0"
"Croatia\0"
"Cuba\0"
+"Curaçao\0"
"Cyprus\0"
-"Czech Republic\0"
+"Czechia\0"
"Denmark\0"
+"Diego Garcia\0"
"Djibouti\0"
"Dominica\0"
"Dominican Republic\0"
-"East Timor\0"
"Ecuador\0"
"Egypt\0"
"El Salvador\0"
"Equatorial Guinea\0"
"Eritrea\0"
"Estonia\0"
+"Eswatini\0"
"Ethiopia\0"
+"Europe\0"
+"European Union\0"
"Falkland Islands\0"
"Faroe Islands\0"
"Fiji\0"
"Finland\0"
"France\0"
-"Guernsey\0"
"French Guiana\0"
"French Polynesia\0"
"French Southern Territories\0"
@@ -5582,13 +7280,14 @@ static const char country_name_list[] =
"Guadeloupe\0"
"Guam\0"
"Guatemala\0"
+"Guernsey\0"
+"Guinea-Bissau\0"
"Guinea\0"
-"Guinea Bissau\0"
"Guyana\0"
"Haiti\0"
-"Heard And McDonald Islands\0"
+"Heard & McDonald Islands\0"
"Honduras\0"
-"Hong Kong\0"
+"Hong Kong SAR China\0"
"Hungary\0"
"Iceland\0"
"India\0"
@@ -5596,19 +7295,22 @@ static const char country_name_list[] =
"Iran\0"
"Iraq\0"
"Ireland\0"
+"Isle of Man\0"
"Israel\0"
"Italy\0"
+"Côte d’Ivoire\0" // Ivory Coast
"Jamaica\0"
"Japan\0"
+"Jersey\0"
"Jordan\0"
"Kazakhstan\0"
"Kenya\0"
"Kiribati\0"
-"North Korea\0"
-"South Korea\0"
+"Kosovo\0"
"Kuwait\0"
"Kyrgyzstan\0"
"Laos\0"
+"Latin America\0"
"Latvia\0"
"Lebanon\0"
"Lesotho\0"
@@ -5617,8 +7319,8 @@ static const char country_name_list[] =
"Liechtenstein\0"
"Lithuania\0"
"Luxembourg\0"
-"Macau\0"
-"Macedonia\0"
+"Macao SAR China\0"
+"North Macedonia\0"
"Madagascar\0"
"Malawi\0"
"Malaysia\0"
@@ -5635,25 +7337,27 @@ static const char country_name_list[] =
"Moldova\0"
"Monaco\0"
"Mongolia\0"
+"Montenegro\0"
"Montserrat\0"
"Morocco\0"
"Mozambique\0"
-"Myanmar\0"
+"Myanmar (Burma)\0"
"Namibia\0"
"Nauru\0"
"Nepal\0"
"Netherlands\0"
-"Cura Sao\0"
"New Caledonia\0"
"New Zealand\0"
"Nicaragua\0"
-"Niger\0"
"Nigeria\0"
+"Niger\0"
"Niue\0"
"Norfolk Island\0"
"Northern Mariana Islands\0"
+"North Korea\0"
"Norway\0"
"Oman\0"
+"Outlying Oceania\0"
"Pakistan\0"
"Palau\0"
"Palestinian Territories\0"
@@ -5662,40 +7366,45 @@ static const char country_name_list[] =
"Paraguay\0"
"Peru\0"
"Philippines\0"
-"Pitcairn\0"
+"Pitcairn Islands\0"
"Poland\0"
"Portugal\0"
"Puerto Rico\0"
"Qatar\0"
-"Reunion\0"
+"Réunion\0"
"Romania\0"
"Russia\0"
"Rwanda\0"
-"Saint Kitts And Nevis\0"
-"Saint Lucia\0"
-"Saint Vincent And The Grenadines\0"
+"St. Barthélemy\0"
+"St. Helena\0"
+"St. Kitts & Nevis\0"
+"St. Lucia\0"
+"St. Martin\0"
+"St. Pierre & Miquelon\0"
+"St. Vincent & Grenadines\0"
"Samoa\0"
"San Marino\0"
-"Sao Tome And Principe\0"
+"São Tomé & Príncipe\0"
"Saudi Arabia\0"
"Senegal\0"
+"Serbia\0"
"Seychelles\0"
"Sierra Leone\0"
"Singapore\0"
+"Sint Maarten\0"
"Slovakia\0"
"Slovenia\0"
"Solomon Islands\0"
"Somalia\0"
"South Africa\0"
-"South Georgia And The South Sandwich Islands\0"
+"South Georgia & South Sandwich Islands\0"
+"South Korea\0"
+"South Sudan\0"
"Spain\0"
"Sri Lanka\0"
-"Saint Helena\0"
-"Saint Pierre And Miquelon\0"
"Sudan\0"
"Suriname\0"
-"Svalbard And Jan Mayen Islands\0"
-"Swaziland\0"
+"Svalbard & Jan Mayen\0"
"Sweden\0"
"Switzerland\0"
"Syria\0"
@@ -5703,844 +7412,800 @@ static const char country_name_list[] =
"Tajikistan\0"
"Tanzania\0"
"Thailand\0"
+"Timor-Leste\0"
"Togo\0"
"Tokelau\0"
"Tonga\0"
-"Trinidad And Tobago\0"
+"Trinidad & Tobago\0"
+"Tristan da Cunha\0"
"Tunisia\0"
-"Turkey\0"
+"Türkiye\0" // Turkey
"Turkmenistan\0"
-"Turks And Caicos Islands\0"
+"Turks & Caicos Islands\0"
"Tuvalu\0"
"Uganda\0"
"Ukraine\0"
"United Arab Emirates\0"
"United Kingdom\0"
+"U.S. Outlying Islands\0"
"United States\0"
-"United States Minor Outlying Islands\0"
+"U.S. Virgin Islands\0"
"Uruguay\0"
"Uzbekistan\0"
"Vanuatu\0"
-"Vatican City State\0"
+"Vatican City\0"
"Venezuela\0"
"Vietnam\0"
-"British Virgin Islands\0"
-"United States Virgin Islands\0"
-"Wallis And Futuna Islands\0"
+"Wallis & Futuna\0"
"Western Sahara\0"
+"world\0"
"Yemen\0"
-"Canary Islands\0"
"Zambia\0"
"Zimbabwe\0"
-"Clipperton Island\0"
-"Montenegro\0"
-"Serbia\0"
-"Saint Barthelemy\0"
-"Saint Martin\0"
-"Latin America\0"
-"Ascension Island\0"
-"Aland Islands\0"
-"Diego Garcia\0"
-"Ceuta And Melilla\0"
-"Isle Of Man\0"
-"Jersey\0"
-"Tristan Da Cunha\0"
-"South Sudan\0"
-"Bonaire\0"
-"Sint Maarten\0"
-"Kosovo\0"
-"European Union\0"
-"Outlying Oceania\0"
-"World\0"
-"Europe\0"
;
-static const quint16 country_name_index[] = {
- 0, // AnyCountry
+static constexpr quint16 territory_name_index[] = {
+ 0, // AnyTerritory
8, // Afghanistan
- 20, // Albania
- 28, // Algeria
- 36, // American Samoa
- 51, // Andorra
- 59, // Angola
- 66, // Anguilla
- 75, // Antarctica
- 86, // Antigua And Barbuda
- 106, // Argentina
- 116, // Armenia
- 124, // Aruba
- 130, // Australia
- 140, // Austria
- 148, // Azerbaijan
- 159, // Bahamas
- 167, // Bahrain
- 175, // Bangladesh
- 186, // Barbados
- 195, // Belarus
- 203, // Belgium
- 211, // Belize
- 218, // Benin
- 224, // Bermuda
- 232, // Bhutan
- 239, // Bolivia
- 247, // Bosnia And Herzegowina
- 270, // Botswana
- 279, // Bouvet Island
- 293, // Brazil
- 300, // British Indian Ocean Territory
- 331, // Brunei
- 338, // Bulgaria
- 347, // Burkina Faso
- 360, // Burundi
- 368, // Cambodia
- 377, // Cameroon
- 386, // Canada
- 393, // Cape Verde
- 404, // Cayman Islands
- 419, // Central African Republic
- 444, // Chad
- 449, // Chile
- 455, // China
- 461, // Christmas Island
- 478, // Cocos Islands
- 492, // Colombia
- 501, // Comoros
- 509, // Congo Kinshasa
- 524, // Congo Brazzaville
- 542, // Cook Islands
- 555, // Costa Rica
- 566, // Ivory Coast
- 578, // Croatia
- 586, // Cuba
- 591, // Cyprus
- 598, // Czech Republic
- 613, // Denmark
- 621, // Djibouti
- 630, // Dominica
- 639, // Dominican Republic
- 658, // East Timor
- 669, // Ecuador
- 677, // Egypt
- 683, // El Salvador
- 695, // Equatorial Guinea
- 713, // Eritrea
- 721, // Estonia
- 729, // Ethiopia
- 738, // Falkland Islands
- 755, // Faroe Islands
- 769, // Fiji
- 774, // Finland
- 782, // France
- 789, // Guernsey
- 798, // French Guiana
- 812, // French Polynesia
- 829, // French Southern Territories
- 857, // Gabon
- 863, // Gambia
- 870, // Georgia
- 878, // Germany
- 886, // Ghana
- 892, // Gibraltar
- 902, // Greece
- 909, // Greenland
- 919, // Grenada
- 927, // Guadeloupe
- 938, // Guam
- 943, // Guatemala
- 953, // Guinea
- 960, // Guinea Bissau
- 974, // Guyana
- 981, // Haiti
- 987, // Heard And McDonald Islands
- 1014, // Honduras
- 1023, // Hong Kong
- 1033, // Hungary
- 1041, // Iceland
- 1049, // India
- 1055, // Indonesia
- 1065, // Iran
- 1070, // Iraq
- 1075, // Ireland
- 1083, // Israel
- 1090, // Italy
- 1096, // Jamaica
- 1104, // Japan
- 1110, // Jordan
- 1117, // Kazakhstan
- 1128, // Kenya
- 1134, // Kiribati
- 1143, // North Korea
- 1155, // South Korea
- 1167, // Kuwait
- 1174, // Kyrgyzstan
- 1185, // Laos
- 1190, // Latvia
- 1197, // Lebanon
- 1205, // Lesotho
- 1213, // Liberia
- 1221, // Libya
- 1227, // Liechtenstein
- 1241, // Lithuania
- 1251, // Luxembourg
- 1262, // Macau
- 1268, // Macedonia
- 1278, // Madagascar
- 1289, // Malawi
- 1296, // Malaysia
- 1305, // Maldives
- 1314, // Mali
- 1319, // Malta
- 1325, // Marshall Islands
- 1342, // Martinique
- 1353, // Mauritania
- 1364, // Mauritius
- 1374, // Mayotte
- 1382, // Mexico
- 1389, // Micronesia
- 1400, // Moldova
- 1408, // Monaco
- 1415, // Mongolia
- 1424, // Montserrat
- 1435, // Morocco
- 1443, // Mozambique
- 1454, // Myanmar
- 1462, // Namibia
- 1470, // Nauru
- 1476, // Nepal
- 1482, // Netherlands
- 1494, // Cura Sao
- 1503, // New Caledonia
- 1517, // New Zealand
- 1529, // Nicaragua
- 1539, // Niger
- 1545, // Nigeria
- 1553, // Niue
- 1558, // Norfolk Island
- 1573, // Northern Mariana Islands
- 1598, // Norway
- 1605, // Oman
- 1610, // Pakistan
- 1619, // Palau
- 1625, // Palestinian Territories
- 1649, // Panama
- 1656, // Papua New Guinea
- 1673, // Paraguay
- 1682, // Peru
- 1687, // Philippines
- 1699, // Pitcairn
- 1708, // Poland
- 1715, // Portugal
- 1724, // Puerto Rico
- 1736, // Qatar
- 1742, // Reunion
- 1750, // Romania
- 1758, // Russia
- 1765, // Rwanda
- 1772, // Saint Kitts And Nevis
- 1794, // Saint Lucia
- 1806, // Saint Vincent And The Grenadines
- 1839, // Samoa
- 1845, // San Marino
- 1856, // Sao Tome And Principe
- 1878, // Saudi Arabia
- 1891, // Senegal
- 1899, // Seychelles
- 1910, // Sierra Leone
- 1923, // Singapore
- 1933, // Slovakia
- 1942, // Slovenia
- 1951, // Solomon Islands
- 1967, // Somalia
- 1975, // South Africa
- 1988, // South Georgia And The South Sandwich Islands
- 2033, // Spain
- 2039, // Sri Lanka
- 2049, // Saint Helena
- 2062, // Saint Pierre And Miquelon
- 2088, // Sudan
- 2094, // Suriname
- 2103, // Svalbard And Jan Mayen Islands
- 2134, // Swaziland
- 2144, // Sweden
- 2151, // Switzerland
- 2163, // Syria
- 2169, // Taiwan
- 2176, // Tajikistan
- 2187, // Tanzania
- 2196, // Thailand
- 2205, // Togo
- 2210, // Tokelau
- 2218, // Tonga
- 2224, // Trinidad And Tobago
- 2244, // Tunisia
- 2252, // Turkey
- 2259, // Turkmenistan
- 2272, // Turks And Caicos Islands
- 2297, // Tuvalu
- 2304, // Uganda
- 2311, // Ukraine
- 2319, // United Arab Emirates
- 2340, // United Kingdom
- 2355, // United States
- 2369, // United States Minor Outlying Islands
- 2406, // Uruguay
- 2414, // Uzbekistan
- 2425, // Vanuatu
- 2433, // Vatican City State
- 2452, // Venezuela
- 2462, // Vietnam
- 2470, // British Virgin Islands
- 2493, // United States Virgin Islands
- 2522, // Wallis And Futuna Islands
- 2548, // Western Sahara
- 2563, // Yemen
- 2569, // Canary Islands
- 2584, // Zambia
- 2591, // Zimbabwe
- 2600, // Clipperton Island
- 2618, // Montenegro
- 2629, // Serbia
- 2636, // Saint Barthelemy
- 2653, // Saint Martin
- 2666, // Latin America
- 2680, // Ascension Island
- 2697, // Aland Islands
- 2711, // Diego Garcia
- 2724, // Ceuta And Melilla
- 2742, // Isle Of Man
- 2754, // Jersey
- 2761, // Tristan Da Cunha
- 2778, // South Sudan
- 2790, // Bonaire
- 2798, // Sint Maarten
- 2811, // Kosovo
- 2818, // European Union
- 2833, // Outlying Oceania
- 2850, // World
- 2856, // Europe
+ 20, // Aland Islands
+ 35, // Albania
+ 43, // Algeria
+ 51, // American Samoa
+ 66, // Andorra
+ 74, // Angola
+ 81, // Anguilla
+ 90, // Antarctica
+ 101, // Antigua and Barbuda
+ 119, // Argentina
+ 129, // Armenia
+ 137, // Aruba
+ 143, // Ascension Island
+ 160, // Australia
+ 170, // Austria
+ 178, // Azerbaijan
+ 189, // Bahamas
+ 197, // Bahrain
+ 205, // Bangladesh
+ 216, // Barbados
+ 225, // Belarus
+ 233, // Belgium
+ 241, // Belize
+ 248, // Benin
+ 254, // Bermuda
+ 262, // Bhutan
+ 269, // Bolivia
+ 277, // Bosnia and Herzegovina
+ 298, // Botswana
+ 307, // Bouvet Island
+ 321, // Brazil
+ 328, // British Indian Ocean Territory
+ 359, // British Virgin Islands
+ 382, // Brunei
+ 389, // Bulgaria
+ 398, // Burkina Faso
+ 411, // Burundi
+ 419, // Cambodia
+ 428, // Cameroon
+ 437, // Canada
+ 444, // Canary Islands
+ 459, // Cape Verde
+ 470, // Caribbean Netherlands
+ 492, // Cayman Islands
+ 507, // Central African Republic
+ 532, // Ceuta and Melilla
+ 548, // Chad
+ 553, // Chile
+ 559, // China
+ 565, // Christmas Island
+ 582, // Clipperton Island
+ 600, // Cocos Islands
+ 624, // Colombia
+ 633, // Comoros
+ 641, // Congo - Brazzaville
+ 661, // Congo - Kinshasa
+ 678, // Cook Islands
+ 691, // Costa Rica
+ 702, // Croatia
+ 710, // Cuba
+ 715, // Curacao
+ 724, // Cyprus
+ 731, // Czechia
+ 739, // Denmark
+ 747, // Diego Garcia
+ 760, // Djibouti
+ 769, // Dominica
+ 778, // Dominican Republic
+ 797, // Ecuador
+ 805, // Egypt
+ 811, // El Salvador
+ 823, // Equatorial Guinea
+ 841, // Eritrea
+ 849, // Estonia
+ 857, // Eswatini
+ 866, // Ethiopia
+ 875, // Europe
+ 882, // European Union
+ 897, // Falkland Islands
+ 914, // Faroe Islands
+ 928, // Fiji
+ 933, // Finland
+ 941, // France
+ 948, // French Guiana
+ 962, // French Polynesia
+ 979, // French Southern Territories
+ 1007, // Gabon
+ 1013, // Gambia
+ 1020, // Georgia
+ 1028, // Germany
+ 1036, // Ghana
+ 1042, // Gibraltar
+ 1052, // Greece
+ 1059, // Greenland
+ 1069, // Grenada
+ 1077, // Guadeloupe
+ 1088, // Guam
+ 1093, // Guatemala
+ 1103, // Guernsey
+ 1112, // Guinea-Bissau
+ 1126, // Guinea
+ 1133, // Guyana
+ 1140, // Haiti
+ 1146, // Heard and McDonald Islands
+ 1171, // Honduras
+ 1180, // Hong Kong
+ 1200, // Hungary
+ 1208, // Iceland
+ 1216, // India
+ 1222, // Indonesia
+ 1232, // Iran
+ 1237, // Iraq
+ 1242, // Ireland
+ 1250, // Isle of Man
+ 1262, // Israel
+ 1269, // Italy
+ 1275, // Ivory Coast
+ 1292, // Jamaica
+ 1300, // Japan
+ 1306, // Jersey
+ 1313, // Jordan
+ 1320, // Kazakhstan
+ 1331, // Kenya
+ 1337, // Kiribati
+ 1346, // Kosovo
+ 1353, // Kuwait
+ 1360, // Kyrgyzstan
+ 1371, // Laos
+ 1376, // Latin America
+ 1390, // Latvia
+ 1397, // Lebanon
+ 1405, // Lesotho
+ 1413, // Liberia
+ 1421, // Libya
+ 1427, // Liechtenstein
+ 1441, // Lithuania
+ 1451, // Luxembourg
+ 1462, // Macao
+ 1478, // Macedonia
+ 1494, // Madagascar
+ 1505, // Malawi
+ 1512, // Malaysia
+ 1521, // Maldives
+ 1530, // Mali
+ 1535, // Malta
+ 1541, // Marshall Islands
+ 1558, // Martinique
+ 1569, // Mauritania
+ 1580, // Mauritius
+ 1590, // Mayotte
+ 1598, // Mexico
+ 1605, // Micronesia
+ 1616, // Moldova
+ 1624, // Monaco
+ 1631, // Mongolia
+ 1640, // Montenegro
+ 1651, // Montserrat
+ 1662, // Morocco
+ 1670, // Mozambique
+ 1681, // Myanmar
+ 1697, // Namibia
+ 1705, // Nauru
+ 1711, // Nepal
+ 1717, // Netherlands
+ 1729, // New Caledonia
+ 1743, // New Zealand
+ 1755, // Nicaragua
+ 1765, // Nigeria
+ 1773, // Niger
+ 1779, // Niue
+ 1784, // Norfolk Island
+ 1799, // Northern Mariana Islands
+ 1824, // North Korea
+ 1836, // Norway
+ 1843, // Oman
+ 1848, // Outlying Oceania
+ 1865, // Pakistan
+ 1874, // Palau
+ 1880, // Palestinian Territories
+ 1904, // Panama
+ 1911, // Papua New Guinea
+ 1928, // Paraguay
+ 1937, // Peru
+ 1942, // Philippines
+ 1954, // Pitcairn
+ 1971, // Poland
+ 1978, // Portugal
+ 1987, // Puerto Rico
+ 1999, // Qatar
+ 2005, // Reunion
+ 2014, // Romania
+ 2022, // Russia
+ 2029, // Rwanda
+ 2036, // Saint Barthelemy
+ 2052, // Saint Helena
+ 2063, // Saint Kitts and Nevis
+ 2081, // Saint Lucia
+ 2091, // Saint Martin
+ 2102, // Saint Pierre and Miquelon
+ 2124, // Saint Vincent and Grenadines
+ 2149, // Samoa
+ 2155, // San Marino
+ 2166, // Sao Tome and Principe
+ 2189, // Saudi Arabia
+ 2202, // Senegal
+ 2210, // Serbia
+ 2217, // Seychelles
+ 2228, // Sierra Leone
+ 2241, // Singapore
+ 2251, // Sint Maarten
+ 2264, // Slovakia
+ 2273, // Slovenia
+ 2282, // Solomon Islands
+ 2298, // Somalia
+ 2306, // South Africa
+ 2319, // South Georgia and South Sandwich Islands
+ 2358, // South Korea
+ 2370, // South Sudan
+ 2382, // Spain
+ 2388, // Sri Lanka
+ 2398, // Sudan
+ 2404, // Suriname
+ 2413, // Svalbard and Jan Mayen
+ 2434, // Sweden
+ 2441, // Switzerland
+ 2453, // Syria
+ 2459, // Taiwan
+ 2466, // Tajikistan
+ 2477, // Tanzania
+ 2486, // Thailand
+ 2495, // Timor-Leste
+ 2507, // Togo
+ 2512, // Tokelau
+ 2520, // Tonga
+ 2526, // Trinidad and Tobago
+ 2544, // Tristan da Cunha
+ 2561, // Tunisia
+ 2569, // Turkey
+ 2578, // Turkmenistan
+ 2591, // Turks and Caicos Islands
+ 2614, // Tuvalu
+ 2621, // Uganda
+ 2628, // Ukraine
+ 2636, // United Arab Emirates
+ 2657, // United Kingdom
+ 2672, // United States Outlying Islands
+ 2694, // United States
+ 2708, // United States Virgin Islands
+ 2728, // Uruguay
+ 2736, // Uzbekistan
+ 2747, // Vanuatu
+ 2755, // Vatican City
+ 2768, // Venezuela
+ 2778, // Vietnam
+ 2786, // Wallis and Futuna
+ 2802, // Western Sahara
+ 2817, // world
+ 2823, // Yemen
+ 2829, // Zambia
+ 2836, // Zimbabwe
};
-static const unsigned char language_code_list[] =
-" \0" // AnyLanguage
-" \0" // C
-"ab\0" // Abkhazian
-"om\0" // Oromo
-"aa\0" // Afar
-"af\0" // Afrikaans
-"sq\0" // Albanian
-"am\0" // Amharic
-"ar\0" // Arabic
-"hy\0" // Armenian
-"as\0" // Assamese
-"ay\0" // Aymara
-"az\0" // Azerbaijani
-"ba\0" // Bashkir
-"eu\0" // Basque
-"bn\0" // Bengali
-"dz\0" // Dzongkha
-"bh\0" // Bihari
-"bi\0" // Bislama
-"br\0" // Breton
-"bg\0" // Bulgarian
-"my\0" // Burmese
-"be\0" // Belarusian
-"km\0" // Khmer
-"ca\0" // Catalan
-"zh\0" // Chinese
-"co\0" // Corsican
-"hr\0" // Croatian
-"cs\0" // Czech
-"da\0" // Danish
-"nl\0" // Dutch
-"en\0" // English
-"eo\0" // Esperanto
-"et\0" // Estonian
-"fo\0" // Faroese
-"fj\0" // Fijian
-"fi\0" // Finnish
-"fr\0" // French
-"fy\0" // Western Frisian
-"gd\0" // Gaelic
-"gl\0" // Galician
-"ka\0" // Georgian
-"de\0" // German
-"el\0" // Greek
-"kl\0" // Greenlandic
-"gn\0" // Guarani
-"gu\0" // Gujarati
-"ha\0" // Hausa
-"he\0" // Hebrew
-"hi\0" // Hindi
-"hu\0" // Hungarian
-"is\0" // Icelandic
-"id\0" // Indonesian
-"ia\0" // Interlingua
-"ie\0" // Interlingue
-"iu\0" // Inuktitut
-"ik\0" // Inupiak
-"ga\0" // Irish
-"it\0" // Italian
-"ja\0" // Japanese
-"jv\0" // Javanese
-"kn\0" // Kannada
-"ks\0" // Kashmiri
-"kk\0" // Kazakh
-"rw\0" // Kinyarwanda
-"ky\0" // Kirghiz
-"ko\0" // Korean
-"ku\0" // Kurdish
-"rn\0" // Rundi
-"lo\0" // Lao
-"la\0" // Latin
-"lv\0" // Latvian
-"ln\0" // Lingala
-"lt\0" // Lithuanian
-"mk\0" // Macedonian
-"mg\0" // Malagasy
-"ms\0" // Malay
-"ml\0" // Malayalam
-"mt\0" // Maltese
-"mi\0" // Maori
-"mr\0" // Marathi
-"mh\0" // Marshallese
-"mn\0" // Mongolian
-"na\0" // Nauru
-"ne\0" // Nepali
-"nb\0" // Norwegian Bokmal
-"oc\0" // Occitan
-"or\0" // Oriya
-"ps\0" // Pashto
-"fa\0" // Persian
-"pl\0" // Polish
-"pt\0" // Portuguese
-"pa\0" // Punjabi
-"qu\0" // Quechua
-"rm\0" // Romansh
-"ro\0" // Romanian
-"ru\0" // Russian
-"sm\0" // Samoan
-"sg\0" // Sango
-"sa\0" // Sanskrit
-"sr\0" // Serbian
-"os\0" // Ossetic
-"st\0" // Southern Sotho
-"tn\0" // Tswana
-"sn\0" // Shona
-"sd\0" // Sindhi
-"si\0" // Sinhala
-"ss\0" // Swati
-"sk\0" // Slovak
-"sl\0" // Slovenian
-"so\0" // Somali
-"es\0" // Spanish
-"su\0" // Sundanese
-"sw\0" // Swahili
-"sv\0" // Swedish
-"sc\0" // Sardinian
-"tg\0" // Tajik
-"ta\0" // Tamil
-"tt\0" // Tatar
-"te\0" // Telugu
-"th\0" // Thai
-"bo\0" // Tibetan
-"ti\0" // Tigrinya
-"to\0" // Tongan
-"ts\0" // Tsonga
-"tr\0" // Turkish
-"tk\0" // Turkmen
-"ty\0" // Tahitian
-"ug\0" // Uighur
-"uk\0" // Ukrainian
-"ur\0" // Urdu
-"uz\0" // Uzbek
-"vi\0" // Vietnamese
-"vo\0" // Volapuk
-"cy\0" // Welsh
-"wo\0" // Wolof
-"xh\0" // Xhosa
-"yi\0" // Yiddish
-"yo\0" // Yoruba
-"za\0" // Zhuang
-"zu\0" // Zulu
-"nn\0" // Norwegian Nynorsk
-"bs\0" // Bosnian
-"dv\0" // Divehi
-"gv\0" // Manx
-"kw\0" // Cornish
-"ak\0" // Akan
-"kok" // Konkani
-"gaa" // Ga
-"ig\0" // Igbo
-"kam" // Kamba
-"syr" // Syriac
-"byn" // Blin
-"gez" // Geez
-"kfo" // Koro
-"sid" // Sidamo
-"cch" // Atsam
-"tig" // Tigre
-"kaj" // Jju
-"fur" // Friulian
-"ve\0" // Venda
-"ee\0" // Ewe
-"wal" // Walamo
-"haw" // Hawaiian
-"kcg" // Tyap
-"ny\0" // Nyanja
-"fil" // Filipino
-"gsw" // Swiss German
-"ii\0" // Sichuan Yi
-"kpe" // Kpelle
-"nds" // Low German
-"nr\0" // South Ndebele
-"nso" // Northern Sotho
-"se\0" // Northern Sami
-"trv" // Taroko
-"guz" // Gusii
-"dav" // Taita
-"ff\0" // Fulah
-"ki\0" // Kikuyu
-"saq" // Samburu
-"seh" // Sena
-"nd\0" // North Ndebele
-"rof" // Rombo
-"shi" // Tachelhit
-"kab" // Kabyle
-"nyn" // Nyankole
-"bez" // Bena
-"vun" // Vunjo
-"bm\0" // Bambara
-"ebu" // Embu
-"chr" // Cherokee
-"mfe" // Morisyen
-"kde" // Makonde
-"lag" // Langi
-"lg\0" // Ganda
-"bem" // Bemba
-"kea" // Kabuverdianu
-"mer" // Meru
-"kln" // Kalenjin
-"naq" // Nama
-"jmc" // Machame
-"ksh" // Colognian
-"mas" // Masai
-"xog" // Soga
-"luy" // Luyia
-"asa" // Asu
-"teo" // Teso
-"ssy" // Saho
-"khq" // Koyra Chiini
-"rwk" // Rwa
-"luo" // Luo
-"cgg" // Chiga
-"tzm" // Central Morocco Tamazight
-"ses" // Koyraboro Senni
-"ksb" // Shambala
-"brx" // Bodo
-"av\0" // Avaric
-"ch\0" // Chamorro
-"ce\0" // Chechen
-"cu\0" // Church
-"cv\0" // Chuvash
-"cr\0" // Cree
-"ht\0" // Haitian
-"hz\0" // Herero
-"ho\0" // Hiri Motu
-"kr\0" // Kanuri
-"kv\0" // Komi
-"kg\0" // Kongo
-"kj\0" // Kwanyama
-"li\0" // Limburgish
-"lu\0" // Luba Katanga
-"lb\0" // Luxembourgish
-"nv\0" // Navaho
-"ng\0" // Ndonga
-"oj\0" // Ojibwa
-"pi\0" // Pali
-"wa\0" // Walloon
-"agq" // Aghem
-"bas" // Basaa
-"dje" // Zarma
-"dua" // Duala
-"dyo" // Jola Fonyi
-"ewo" // Ewondo
-"ksf" // Bafia
-"mgh" // Makhuwa Meetto
-"mua" // Mundang
-"nmg" // Kwasio
-"nus" // Nuer
-"sah" // Sakha
-"sbp" // Sangu
-"swc" // Congo Swahili
-"twq" // Tasawaq
-"vai" // Vai
-"wae" // Walser
-"yav" // Yangben
-"ae\0" // Avestan
-"ast" // Asturian
-"jgo" // Ngomba
-"kkj" // Kako
-"mgo" // Meta
-"nnh" // Ngiemboon
-"an\0" // Aragonese
-"akk" // Akkadian
-"egy" // Ancient Egyptian
-"grc" // Ancient Greek
-"arc" // Aramaic
-"ban" // Balinese
-"bax" // Bamun
-"bbc" // Batak Toba
-"bug" // Buginese
-"bku" // Buhid
-"xcr" // Carian
-"ccp" // Chakma
-"myz" // Classical Mandaic
-"cop" // Coptic
-"doi" // Dogri
-"cjm" // Eastern Cham
-"eky" // Eastern Kayah
-"ett" // Etruscan
-"got" // Gothic
-"hnn" // Hanunoo
-"inh" // Ingush
-"hmd" // Large Flowery Miao
-"lep" // Lepcha
-"lif" // Limbu
-"lis" // Lisu
-"khb" // Lu
-"xlc" // Lycian
-"xld" // Lydian
-"man" // Mandingo
-"mni" // Manipuri
-"xmr" // Meroitic
-"nod" // Northern Thai
-"sga" // Old Irish
-"non" // Old Norse
-"peo" // Old Persian
-"otk" // Old Turkish
-"pal" // Pahlavi
-"xpr" // Parthian
-"phn" // Phoenician
-"pra" // Prakrit Language
-"rej" // Rejang
-"xsa" // Sabaean
-"smp" // Samaritan
-"sat" // Santali
-"saz" // Saurashtra
-"srb" // Sora
-"syl" // Sylheti
-"tbw" // Tagbanwa
-"blt" // Tai Dam
-"tdd" // Tai Nua
-"uga" // Ugaritic
-"bss" // Akoose
-"lkt" // Lakota
-"zgh" // Standard Moroccan Tamazight
-"arn" // Mapuche
-"ckb" // Central Kurdish
-"dsb" // Lower Sorbian
-"hsb" // Upper Sorbian
-"ken" // Kenyang
-"moh" // Mohawk
-"nqo" // Nko
-"prg" // Prussian
-"quc" // Kiche
-"sma" // Southern Sami
-"smj" // Lule Sami
-"smn" // Inari Sami
-"sms" // Skolt Sami
-"wbp" // Warlpiri
-"xmn" // Manichaean Middle Persian
-"men" // Mende
-"xna" // Ancient North Arabian
-"lab" // Linear A
-"hnj" // Hmong Njua
-"hoc" // Ho
-"lez" // Lezghian
-"bsq" // Bassa
-"mru" // Mono
-"ctd" // Tedim Chin
-"mai" // Maithili
-"aho" // Ahom
-"ase" // American Sign Language
-"pka" // Ardhamagadhi Prakrit
-"bho" // Bhojpuri
-"hlu" // Hieroglyphic Luwian
-"lzh" // Literary Chinese
-"mzn" // Mazanderani
-"mro" // Mru
-"new" // Newari
-"lrc" // Northern Luri
-"pau" // Palauan
-"pap" // Papiamento
-"skr" // Saraiki
-"tkl" // Tokelau
-"tpi" // Tok Pisin
-"tvl" // Tuvalu
-"mis" // Uncoded Languages
-"yue" // Cantonese
-"osa" // Osage
-"txg" // Tangut
-"io\0" // Ido
-"jbo" // Lojban
-"scn" // Sicilian
-"sdh" // Southern Kurdish
-"bgn" // Western Balochi
-"ceb" // Cebuano
-"myv" // Erzya
-"cic" // Chickasaw
-"mus" // Muscogee
-"szl" // Silesian
-;
+constexpr std::array<LanguageCodeEntry, 344> languageCodeList {
+ LanguageCodeEntry {{}, {'u', 'n', 'd'}, {'u', 'n', 'd'}, {'u', 'n', 'd'}}, // AnyLanguage
+ LanguageCodeEntry {{}, {'u', 'n', 'd'}, {'u', 'n', 'd'}, {'u', 'n', 'd'}}, // C
+ LanguageCodeEntry {{'a', 'b'}, {'a', 'b', 'k'}, {'a', 'b', 'k'}, {'a', 'b', 'k'}}, // Abkhazian
+ LanguageCodeEntry {{'a', 'a'}, {'a', 'a', 'r'}, {'a', 'a', 'r'}, {'a', 'a', 'r'}}, // Afar
+ LanguageCodeEntry {{'a', 'f'}, {'a', 'f', 'r'}, {'a', 'f', 'r'}, {'a', 'f', 'r'}}, // Afrikaans
+ LanguageCodeEntry {{}, {}, {}, {'a', 'g', 'q'}}, // Aghem
+ LanguageCodeEntry {{'a', 'k'}, {'a', 'k', 'a'}, {'a', 'k', 'a'}, {'a', 'k', 'a'}}, // Akan
+ LanguageCodeEntry {{}, {'a', 'k', 'k'}, {'a', 'k', 'k'}, {'a', 'k', 'k'}}, // Akkadian
+ LanguageCodeEntry {{}, {}, {}, {'b', 's', 's'}}, // Akoose
+ LanguageCodeEntry {{'s', 'q'}, {'a', 'l', 'b'}, {'s', 'q', 'i'}, {'s', 'q', 'i'}}, // Albanian
+ LanguageCodeEntry {{}, {}, {}, {'a', 's', 'e'}}, // American Sign Language
+ LanguageCodeEntry {{'a', 'm'}, {'a', 'm', 'h'}, {'a', 'm', 'h'}, {'a', 'm', 'h'}}, // Amharic
+ LanguageCodeEntry {{}, {'e', 'g', 'y'}, {'e', 'g', 'y'}, {'e', 'g', 'y'}}, // Ancient Egyptian
+ LanguageCodeEntry {{}, {'g', 'r', 'c'}, {'g', 'r', 'c'}, {'g', 'r', 'c'}}, // Ancient Greek
+ LanguageCodeEntry {{'a', 'r'}, {'a', 'r', 'a'}, {'a', 'r', 'a'}, {'a', 'r', 'a'}}, // Arabic
+ LanguageCodeEntry {{'a', 'n'}, {'a', 'r', 'g'}, {'a', 'r', 'g'}, {'a', 'r', 'g'}}, // Aragonese
+ LanguageCodeEntry {{}, {'a', 'r', 'c'}, {'a', 'r', 'c'}, {'a', 'r', 'c'}}, // Aramaic
+ LanguageCodeEntry {{'h', 'y'}, {'a', 'r', 'm'}, {'h', 'y', 'e'}, {'h', 'y', 'e'}}, // Armenian
+ LanguageCodeEntry {{'a', 's'}, {'a', 's', 'm'}, {'a', 's', 'm'}, {'a', 's', 'm'}}, // Assamese
+ LanguageCodeEntry {{}, {'a', 's', 't'}, {'a', 's', 't'}, {'a', 's', 't'}}, // Asturian
+ LanguageCodeEntry {{}, {}, {}, {'a', 's', 'a'}}, // Asu
+ LanguageCodeEntry {{}, {}, {}, {'c', 'c', 'h'}}, // Atsam
+ LanguageCodeEntry {{'a', 'v'}, {'a', 'v', 'a'}, {'a', 'v', 'a'}, {'a', 'v', 'a'}}, // Avaric
+ LanguageCodeEntry {{'a', 'e'}, {'a', 'v', 'e'}, {'a', 'v', 'e'}, {'a', 'v', 'e'}}, // Avestan
+ LanguageCodeEntry {{'a', 'y'}, {'a', 'y', 'm'}, {'a', 'y', 'm'}, {'a', 'y', 'm'}}, // Aymara
+ LanguageCodeEntry {{'a', 'z'}, {'a', 'z', 'e'}, {'a', 'z', 'e'}, {'a', 'z', 'e'}}, // Azerbaijani
+ LanguageCodeEntry {{}, {}, {}, {'k', 's', 'f'}}, // Bafia
+ LanguageCodeEntry {{}, {'b', 'a', 'n'}, {'b', 'a', 'n'}, {'b', 'a', 'n'}}, // Balinese
+ LanguageCodeEntry {{'b', 'm'}, {'b', 'a', 'm'}, {'b', 'a', 'm'}, {'b', 'a', 'm'}}, // Bambara
+ LanguageCodeEntry {{}, {}, {}, {'b', 'a', 'x'}}, // Bamun
+ LanguageCodeEntry {{'b', 'n'}, {'b', 'e', 'n'}, {'b', 'e', 'n'}, {'b', 'e', 'n'}}, // Bangla
+ LanguageCodeEntry {{}, {'b', 'a', 's'}, {'b', 'a', 's'}, {'b', 'a', 's'}}, // Basaa
+ LanguageCodeEntry {{'b', 'a'}, {'b', 'a', 'k'}, {'b', 'a', 'k'}, {'b', 'a', 'k'}}, // Bashkir
+ LanguageCodeEntry {{'e', 'u'}, {'b', 'a', 'q'}, {'e', 'u', 's'}, {'e', 'u', 's'}}, // Basque
+ LanguageCodeEntry {{}, {}, {}, {'b', 'b', 'c'}}, // Batak Toba
+ LanguageCodeEntry {{'b', 'e'}, {'b', 'e', 'l'}, {'b', 'e', 'l'}, {'b', 'e', 'l'}}, // Belarusian
+ LanguageCodeEntry {{}, {'b', 'e', 'm'}, {'b', 'e', 'm'}, {'b', 'e', 'm'}}, // Bemba
+ LanguageCodeEntry {{}, {}, {}, {'b', 'e', 'z'}}, // Bena
+ LanguageCodeEntry {{}, {'b', 'h', 'o'}, {'b', 'h', 'o'}, {'b', 'h', 'o'}}, // Bhojpuri
+ LanguageCodeEntry {{'b', 'i'}, {'b', 'i', 's'}, {'b', 'i', 's'}, {'b', 'i', 's'}}, // Bislama
+ LanguageCodeEntry {{}, {'b', 'y', 'n'}, {'b', 'y', 'n'}, {'b', 'y', 'n'}}, // Blin
+ LanguageCodeEntry {{}, {}, {}, {'b', 'r', 'x'}}, // Bodo
+ LanguageCodeEntry {{'b', 's'}, {'b', 'o', 's'}, {'b', 'o', 's'}, {'b', 'o', 's'}}, // Bosnian
+ LanguageCodeEntry {{'b', 'r'}, {'b', 'r', 'e'}, {'b', 'r', 'e'}, {'b', 'r', 'e'}}, // Breton
+ LanguageCodeEntry {{}, {'b', 'u', 'g'}, {'b', 'u', 'g'}, {'b', 'u', 'g'}}, // Buginese
+ LanguageCodeEntry {{'b', 'g'}, {'b', 'u', 'l'}, {'b', 'u', 'l'}, {'b', 'u', 'l'}}, // Bulgarian
+ LanguageCodeEntry {{'m', 'y'}, {'b', 'u', 'r'}, {'m', 'y', 'a'}, {'m', 'y', 'a'}}, // Burmese
+ LanguageCodeEntry {{}, {}, {}, {'y', 'u', 'e'}}, // Cantonese
+ LanguageCodeEntry {{'c', 'a'}, {'c', 'a', 't'}, {'c', 'a', 't'}, {'c', 'a', 't'}}, // Catalan
+ LanguageCodeEntry {{}, {'c', 'e', 'b'}, {'c', 'e', 'b'}, {'c', 'e', 'b'}}, // Cebuano
+ LanguageCodeEntry {{}, {}, {}, {'t', 'z', 'm'}}, // Central Atlas Tamazight
+ LanguageCodeEntry {{}, {}, {}, {'c', 'k', 'b'}}, // Central Kurdish
+ LanguageCodeEntry {{}, {}, {}, {'c', 'c', 'p'}}, // Chakma
+ LanguageCodeEntry {{'c', 'h'}, {'c', 'h', 'a'}, {'c', 'h', 'a'}, {'c', 'h', 'a'}}, // Chamorro
+ LanguageCodeEntry {{'c', 'e'}, {'c', 'h', 'e'}, {'c', 'h', 'e'}, {'c', 'h', 'e'}}, // Chechen
+ LanguageCodeEntry {{}, {'c', 'h', 'r'}, {'c', 'h', 'r'}, {'c', 'h', 'r'}}, // Cherokee
+ LanguageCodeEntry {{}, {}, {}, {'c', 'i', 'c'}}, // Chickasaw
+ LanguageCodeEntry {{}, {}, {}, {'c', 'g', 'g'}}, // Chiga
+ LanguageCodeEntry {{'z', 'h'}, {'c', 'h', 'i'}, {'z', 'h', 'o'}, {'z', 'h', 'o'}}, // Chinese
+ LanguageCodeEntry {{'c', 'u'}, {'c', 'h', 'u'}, {'c', 'h', 'u'}, {'c', 'h', 'u'}}, // Church
+ LanguageCodeEntry {{'c', 'v'}, {'c', 'h', 'v'}, {'c', 'h', 'v'}, {'c', 'h', 'v'}}, // Chuvash
+ LanguageCodeEntry {{}, {}, {}, {'k', 's', 'h'}}, // Colognian
+ LanguageCodeEntry {{}, {'c', 'o', 'p'}, {'c', 'o', 'p'}, {'c', 'o', 'p'}}, // Coptic
+ LanguageCodeEntry {{'k', 'w'}, {'c', 'o', 'r'}, {'c', 'o', 'r'}, {'c', 'o', 'r'}}, // Cornish
+ LanguageCodeEntry {{'c', 'o'}, {'c', 'o', 's'}, {'c', 'o', 's'}, {'c', 'o', 's'}}, // Corsican
+ LanguageCodeEntry {{'c', 'r'}, {'c', 'r', 'e'}, {'c', 'r', 'e'}, {'c', 'r', 'e'}}, // Cree
+ LanguageCodeEntry {{'h', 'r'}, {'h', 'r', 'v'}, {'h', 'r', 'v'}, {'h', 'r', 'v'}}, // Croatian
+ LanguageCodeEntry {{'c', 's'}, {'c', 'z', 'e'}, {'c', 'e', 's'}, {'c', 'e', 's'}}, // Czech
+ LanguageCodeEntry {{'d', 'a'}, {'d', 'a', 'n'}, {'d', 'a', 'n'}, {'d', 'a', 'n'}}, // Danish
+ LanguageCodeEntry {{'d', 'v'}, {'d', 'i', 'v'}, {'d', 'i', 'v'}, {'d', 'i', 'v'}}, // Divehi
+ LanguageCodeEntry {{}, {'d', 'o', 'i'}, {'d', 'o', 'i'}, {'d', 'o', 'i'}}, // Dogri
+ LanguageCodeEntry {{}, {'d', 'u', 'a'}, {'d', 'u', 'a'}, {'d', 'u', 'a'}}, // Duala
+ LanguageCodeEntry {{'n', 'l'}, {'d', 'u', 't'}, {'n', 'l', 'd'}, {'n', 'l', 'd'}}, // Dutch
+ LanguageCodeEntry {{'d', 'z'}, {'d', 'z', 'o'}, {'d', 'z', 'o'}, {'d', 'z', 'o'}}, // Dzongkha
+ LanguageCodeEntry {{}, {}, {}, {'e', 'b', 'u'}}, // Embu
+ LanguageCodeEntry {{'e', 'n'}, {'e', 'n', 'g'}, {'e', 'n', 'g'}, {'e', 'n', 'g'}}, // English
+ LanguageCodeEntry {{}, {'m', 'y', 'v'}, {'m', 'y', 'v'}, {'m', 'y', 'v'}}, // Erzya
+ LanguageCodeEntry {{'e', 'o'}, {'e', 'p', 'o'}, {'e', 'p', 'o'}, {'e', 'p', 'o'}}, // Esperanto
+ LanguageCodeEntry {{'e', 't'}, {'e', 's', 't'}, {'e', 's', 't'}, {'e', 's', 't'}}, // Estonian
+ LanguageCodeEntry {{'e', 'e'}, {'e', 'w', 'e'}, {'e', 'w', 'e'}, {'e', 'w', 'e'}}, // Ewe
+ LanguageCodeEntry {{}, {'e', 'w', 'o'}, {'e', 'w', 'o'}, {'e', 'w', 'o'}}, // Ewondo
+ LanguageCodeEntry {{'f', 'o'}, {'f', 'a', 'o'}, {'f', 'a', 'o'}, {'f', 'a', 'o'}}, // Faroese
+ LanguageCodeEntry {{'f', 'j'}, {'f', 'i', 'j'}, {'f', 'i', 'j'}, {'f', 'i', 'j'}}, // Fijian
+ LanguageCodeEntry {{}, {'f', 'i', 'l'}, {'f', 'i', 'l'}, {'f', 'i', 'l'}}, // Filipino
+ LanguageCodeEntry {{'f', 'i'}, {'f', 'i', 'n'}, {'f', 'i', 'n'}, {'f', 'i', 'n'}}, // Finnish
+ LanguageCodeEntry {{'f', 'r'}, {'f', 'r', 'e'}, {'f', 'r', 'a'}, {'f', 'r', 'a'}}, // French
+ LanguageCodeEntry {{}, {'f', 'u', 'r'}, {'f', 'u', 'r'}, {'f', 'u', 'r'}}, // Friulian
+ LanguageCodeEntry {{'f', 'f'}, {'f', 'u', 'l'}, {'f', 'u', 'l'}, {'f', 'u', 'l'}}, // Fulah
+ LanguageCodeEntry {{'g', 'd'}, {'g', 'l', 'a'}, {'g', 'l', 'a'}, {'g', 'l', 'a'}}, // Gaelic
+ LanguageCodeEntry {{}, {'g', 'a', 'a'}, {'g', 'a', 'a'}, {'g', 'a', 'a'}}, // Ga
+ LanguageCodeEntry {{'g', 'l'}, {'g', 'l', 'g'}, {'g', 'l', 'g'}, {'g', 'l', 'g'}}, // Galician
+ LanguageCodeEntry {{'l', 'g'}, {'l', 'u', 'g'}, {'l', 'u', 'g'}, {'l', 'u', 'g'}}, // Ganda
+ LanguageCodeEntry {{}, {'g', 'e', 'z'}, {'g', 'e', 'z'}, {'g', 'e', 'z'}}, // Geez
+ LanguageCodeEntry {{'k', 'a'}, {'g', 'e', 'o'}, {'k', 'a', 't'}, {'k', 'a', 't'}}, // Georgian
+ LanguageCodeEntry {{'d', 'e'}, {'g', 'e', 'r'}, {'d', 'e', 'u'}, {'d', 'e', 'u'}}, // German
+ LanguageCodeEntry {{}, {'g', 'o', 't'}, {'g', 'o', 't'}, {'g', 'o', 't'}}, // Gothic
+ LanguageCodeEntry {{'e', 'l'}, {'g', 'r', 'e'}, {'e', 'l', 'l'}, {'e', 'l', 'l'}}, // Greek
+ LanguageCodeEntry {{'g', 'n'}, {'g', 'r', 'n'}, {'g', 'r', 'n'}, {'g', 'r', 'n'}}, // Guarani
+ LanguageCodeEntry {{'g', 'u'}, {'g', 'u', 'j'}, {'g', 'u', 'j'}, {'g', 'u', 'j'}}, // Gujarati
+ LanguageCodeEntry {{}, {}, {}, {'g', 'u', 'z'}}, // Gusii
+ LanguageCodeEntry {{'h', 't'}, {'h', 'a', 't'}, {'h', 'a', 't'}, {'h', 'a', 't'}}, // Haitian
+ LanguageCodeEntry {{'h', 'a'}, {'h', 'a', 'u'}, {'h', 'a', 'u'}, {'h', 'a', 'u'}}, // Hausa
+ LanguageCodeEntry {{}, {'h', 'a', 'w'}, {'h', 'a', 'w'}, {'h', 'a', 'w'}}, // Hawaiian
+ LanguageCodeEntry {{'h', 'e'}, {'h', 'e', 'b'}, {'h', 'e', 'b'}, {'h', 'e', 'b'}}, // Hebrew
+ LanguageCodeEntry {{'h', 'z'}, {'h', 'e', 'r'}, {'h', 'e', 'r'}, {'h', 'e', 'r'}}, // Herero
+ LanguageCodeEntry {{'h', 'i'}, {'h', 'i', 'n'}, {'h', 'i', 'n'}, {'h', 'i', 'n'}}, // Hindi
+ LanguageCodeEntry {{'h', 'o'}, {'h', 'm', 'o'}, {'h', 'm', 'o'}, {'h', 'm', 'o'}}, // Hiri Motu
+ LanguageCodeEntry {{'h', 'u'}, {'h', 'u', 'n'}, {'h', 'u', 'n'}, {'h', 'u', 'n'}}, // Hungarian
+ LanguageCodeEntry {{'i', 's'}, {'i', 'c', 'e'}, {'i', 's', 'l'}, {'i', 's', 'l'}}, // Icelandic
+ LanguageCodeEntry {{'i', 'o'}, {'i', 'd', 'o'}, {'i', 'd', 'o'}, {'i', 'd', 'o'}}, // Ido
+ LanguageCodeEntry {{'i', 'g'}, {'i', 'b', 'o'}, {'i', 'b', 'o'}, {'i', 'b', 'o'}}, // Igbo
+ LanguageCodeEntry {{}, {'s', 'm', 'n'}, {'s', 'm', 'n'}, {'s', 'm', 'n'}}, // Inari Sami
+ LanguageCodeEntry {{'i', 'd'}, {'i', 'n', 'd'}, {'i', 'n', 'd'}, {'i', 'n', 'd'}}, // Indonesian
+ LanguageCodeEntry {{}, {'i', 'n', 'h'}, {'i', 'n', 'h'}, {'i', 'n', 'h'}}, // Ingush
+ LanguageCodeEntry {{'i', 'a'}, {'i', 'n', 'a'}, {'i', 'n', 'a'}, {'i', 'n', 'a'}}, // Interlingua
+ LanguageCodeEntry {{'i', 'e'}, {'i', 'l', 'e'}, {'i', 'l', 'e'}, {'i', 'l', 'e'}}, // Interlingue
+ LanguageCodeEntry {{'i', 'u'}, {'i', 'k', 'u'}, {'i', 'k', 'u'}, {'i', 'k', 'u'}}, // Inuktitut
+ LanguageCodeEntry {{'i', 'k'}, {'i', 'p', 'k'}, {'i', 'p', 'k'}, {'i', 'p', 'k'}}, // Inupiaq
+ LanguageCodeEntry {{'g', 'a'}, {'g', 'l', 'e'}, {'g', 'l', 'e'}, {'g', 'l', 'e'}}, // Irish
+ LanguageCodeEntry {{'i', 't'}, {'i', 't', 'a'}, {'i', 't', 'a'}, {'i', 't', 'a'}}, // Italian
+ LanguageCodeEntry {{'j', 'a'}, {'j', 'p', 'n'}, {'j', 'p', 'n'}, {'j', 'p', 'n'}}, // Japanese
+ LanguageCodeEntry {{'j', 'v'}, {'j', 'a', 'v'}, {'j', 'a', 'v'}, {'j', 'a', 'v'}}, // Javanese
+ LanguageCodeEntry {{}, {}, {}, {'k', 'a', 'j'}}, // Jju
+ LanguageCodeEntry {{}, {}, {}, {'d', 'y', 'o'}}, // Jola-Fonyi
+ LanguageCodeEntry {{}, {}, {}, {'k', 'e', 'a'}}, // Kabuverdianu
+ LanguageCodeEntry {{}, {'k', 'a', 'b'}, {'k', 'a', 'b'}, {'k', 'a', 'b'}}, // Kabyle
+ LanguageCodeEntry {{}, {}, {}, {'k', 'k', 'j'}}, // Kako
+ LanguageCodeEntry {{'k', 'l'}, {'k', 'a', 'l'}, {'k', 'a', 'l'}, {'k', 'a', 'l'}}, // Kalaallisut
+ LanguageCodeEntry {{}, {}, {}, {'k', 'l', 'n'}}, // Kalenjin
+ LanguageCodeEntry {{}, {'k', 'a', 'm'}, {'k', 'a', 'm'}, {'k', 'a', 'm'}}, // Kamba
+ LanguageCodeEntry {{'k', 'n'}, {'k', 'a', 'n'}, {'k', 'a', 'n'}, {'k', 'a', 'n'}}, // Kannada
+ LanguageCodeEntry {{'k', 'r'}, {'k', 'a', 'u'}, {'k', 'a', 'u'}, {'k', 'a', 'u'}}, // Kanuri
+ LanguageCodeEntry {{'k', 's'}, {'k', 'a', 's'}, {'k', 'a', 's'}, {'k', 'a', 's'}}, // Kashmiri
+ LanguageCodeEntry {{'k', 'k'}, {'k', 'a', 'z'}, {'k', 'a', 'z'}, {'k', 'a', 'z'}}, // Kazakh
+ LanguageCodeEntry {{}, {}, {}, {'k', 'e', 'n'}}, // Kenyang
+ LanguageCodeEntry {{'k', 'm'}, {'k', 'h', 'm'}, {'k', 'h', 'm'}, {'k', 'h', 'm'}}, // Khmer
+ LanguageCodeEntry {{}, {}, {}, {'q', 'u', 'c'}}, // Kiche
+ LanguageCodeEntry {{'k', 'i'}, {'k', 'i', 'k'}, {'k', 'i', 'k'}, {'k', 'i', 'k'}}, // Kikuyu
+ LanguageCodeEntry {{'r', 'w'}, {'k', 'i', 'n'}, {'k', 'i', 'n'}, {'k', 'i', 'n'}}, // Kinyarwanda
+ LanguageCodeEntry {{'k', 'v'}, {'k', 'o', 'm'}, {'k', 'o', 'm'}, {'k', 'o', 'm'}}, // Komi
+ LanguageCodeEntry {{'k', 'g'}, {'k', 'o', 'n'}, {'k', 'o', 'n'}, {'k', 'o', 'n'}}, // Kongo
+ LanguageCodeEntry {{}, {'k', 'o', 'k'}, {'k', 'o', 'k'}, {'k', 'o', 'k'}}, // Konkani
+ LanguageCodeEntry {{'k', 'o'}, {'k', 'o', 'r'}, {'k', 'o', 'r'}, {'k', 'o', 'r'}}, // Korean
+ LanguageCodeEntry {{}, {}, {}, {'k', 'f', 'o'}}, // Koro
+ LanguageCodeEntry {{}, {}, {}, {'s', 'e', 's'}}, // Koyraboro Senni
+ LanguageCodeEntry {{}, {}, {}, {'k', 'h', 'q'}}, // Koyra Chiini
+ LanguageCodeEntry {{}, {'k', 'p', 'e'}, {'k', 'p', 'e'}, {'k', 'p', 'e'}}, // Kpelle
+ LanguageCodeEntry {{'k', 'j'}, {'k', 'u', 'a'}, {'k', 'u', 'a'}, {'k', 'u', 'a'}}, // Kuanyama
+ LanguageCodeEntry {{'k', 'u'}, {'k', 'u', 'r'}, {'k', 'u', 'r'}, {'k', 'u', 'r'}}, // Kurdish
+ LanguageCodeEntry {{}, {}, {}, {'n', 'm', 'g'}}, // Kwasio
+ LanguageCodeEntry {{'k', 'y'}, {'k', 'i', 'r'}, {'k', 'i', 'r'}, {'k', 'i', 'r'}}, // Kyrgyz
+ LanguageCodeEntry {{}, {}, {}, {'l', 'k', 't'}}, // Lakota
+ LanguageCodeEntry {{}, {}, {}, {'l', 'a', 'g'}}, // Langi
+ LanguageCodeEntry {{'l', 'o'}, {'l', 'a', 'o'}, {'l', 'a', 'o'}, {'l', 'a', 'o'}}, // Lao
+ LanguageCodeEntry {{'l', 'a'}, {'l', 'a', 't'}, {'l', 'a', 't'}, {'l', 'a', 't'}}, // Latin
+ LanguageCodeEntry {{'l', 'v'}, {'l', 'a', 'v'}, {'l', 'a', 'v'}, {'l', 'a', 'v'}}, // Latvian
+ LanguageCodeEntry {{}, {'l', 'e', 'z'}, {'l', 'e', 'z'}, {'l', 'e', 'z'}}, // Lezghian
+ LanguageCodeEntry {{'l', 'i'}, {'l', 'i', 'm'}, {'l', 'i', 'm'}, {'l', 'i', 'm'}}, // Limburgish
+ LanguageCodeEntry {{'l', 'n'}, {'l', 'i', 'n'}, {'l', 'i', 'n'}, {'l', 'i', 'n'}}, // Lingala
+ LanguageCodeEntry {{}, {}, {}, {'l', 'z', 'h'}}, // Literary Chinese
+ LanguageCodeEntry {{'l', 't'}, {'l', 'i', 't'}, {'l', 'i', 't'}, {'l', 'i', 't'}}, // Lithuanian
+ LanguageCodeEntry {{}, {'j', 'b', 'o'}, {'j', 'b', 'o'}, {'j', 'b', 'o'}}, // Lojban
+ LanguageCodeEntry {{}, {'d', 's', 'b'}, {'d', 's', 'b'}, {'d', 's', 'b'}}, // Lower Sorbian
+ LanguageCodeEntry {{}, {'n', 'd', 's'}, {'n', 'd', 's'}, {'n', 'd', 's'}}, // Low German
+ LanguageCodeEntry {{'l', 'u'}, {'l', 'u', 'b'}, {'l', 'u', 'b'}, {'l', 'u', 'b'}}, // Luba-Katanga
+ LanguageCodeEntry {{}, {'s', 'm', 'j'}, {'s', 'm', 'j'}, {'s', 'm', 'j'}}, // Lule Sami
+ LanguageCodeEntry {{}, {'l', 'u', 'o'}, {'l', 'u', 'o'}, {'l', 'u', 'o'}}, // Luo
+ LanguageCodeEntry {{'l', 'b'}, {'l', 't', 'z'}, {'l', 't', 'z'}, {'l', 't', 'z'}}, // Luxembourgish
+ LanguageCodeEntry {{}, {}, {}, {'l', 'u', 'y'}}, // Luyia
+ LanguageCodeEntry {{'m', 'k'}, {'m', 'a', 'c'}, {'m', 'k', 'd'}, {'m', 'k', 'd'}}, // Macedonian
+ LanguageCodeEntry {{}, {}, {}, {'j', 'm', 'c'}}, // Machame
+ LanguageCodeEntry {{}, {'m', 'a', 'i'}, {'m', 'a', 'i'}, {'m', 'a', 'i'}}, // Maithili
+ LanguageCodeEntry {{}, {}, {}, {'m', 'g', 'h'}}, // Makhuwa-Meetto
+ LanguageCodeEntry {{}, {}, {}, {'k', 'd', 'e'}}, // Makonde
+ LanguageCodeEntry {{'m', 'g'}, {'m', 'l', 'g'}, {'m', 'l', 'g'}, {'m', 'l', 'g'}}, // Malagasy
+ LanguageCodeEntry {{'m', 'l'}, {'m', 'a', 'l'}, {'m', 'a', 'l'}, {'m', 'a', 'l'}}, // Malayalam
+ LanguageCodeEntry {{'m', 's'}, {'m', 'a', 'y'}, {'m', 's', 'a'}, {'m', 's', 'a'}}, // Malay
+ LanguageCodeEntry {{'m', 't'}, {'m', 'l', 't'}, {'m', 'l', 't'}, {'m', 'l', 't'}}, // Maltese
+ LanguageCodeEntry {{}, {'m', 'a', 'n'}, {'m', 'a', 'n'}, {'m', 'a', 'n'}}, // Mandingo
+ LanguageCodeEntry {{}, {'m', 'n', 'i'}, {'m', 'n', 'i'}, {'m', 'n', 'i'}}, // Manipuri
+ LanguageCodeEntry {{'g', 'v'}, {'g', 'l', 'v'}, {'g', 'l', 'v'}, {'g', 'l', 'v'}}, // Manx
+ LanguageCodeEntry {{'m', 'i'}, {'m', 'a', 'o'}, {'m', 'r', 'i'}, {'m', 'r', 'i'}}, // Maori
+ LanguageCodeEntry {{}, {'a', 'r', 'n'}, {'a', 'r', 'n'}, {'a', 'r', 'n'}}, // Mapuche
+ LanguageCodeEntry {{'m', 'r'}, {'m', 'a', 'r'}, {'m', 'a', 'r'}, {'m', 'a', 'r'}}, // Marathi
+ LanguageCodeEntry {{'m', 'h'}, {'m', 'a', 'h'}, {'m', 'a', 'h'}, {'m', 'a', 'h'}}, // Marshallese
+ LanguageCodeEntry {{}, {'m', 'a', 's'}, {'m', 'a', 's'}, {'m', 'a', 's'}}, // Masai
+ LanguageCodeEntry {{}, {}, {}, {'m', 'z', 'n'}}, // Mazanderani
+ LanguageCodeEntry {{}, {'m', 'e', 'n'}, {'m', 'e', 'n'}, {'m', 'e', 'n'}}, // Mende
+ LanguageCodeEntry {{}, {}, {}, {'m', 'e', 'r'}}, // Meru
+ LanguageCodeEntry {{}, {}, {}, {'m', 'g', 'o'}}, // Meta
+ LanguageCodeEntry {{}, {'m', 'o', 'h'}, {'m', 'o', 'h'}, {'m', 'o', 'h'}}, // Mohawk
+ LanguageCodeEntry {{'m', 'n'}, {'m', 'o', 'n'}, {'m', 'o', 'n'}, {'m', 'o', 'n'}}, // Mongolian
+ LanguageCodeEntry {{}, {}, {}, {'m', 'f', 'e'}}, // Morisyen
+ LanguageCodeEntry {{}, {}, {}, {'m', 'u', 'a'}}, // Mundang
+ LanguageCodeEntry {{}, {'m', 'u', 's'}, {'m', 'u', 's'}, {'m', 'u', 's'}}, // Muscogee
+ LanguageCodeEntry {{}, {}, {}, {'n', 'a', 'q'}}, // Nama
+ LanguageCodeEntry {{'n', 'a'}, {'n', 'a', 'u'}, {'n', 'a', 'u'}, {'n', 'a', 'u'}}, // Nauru
+ LanguageCodeEntry {{'n', 'v'}, {'n', 'a', 'v'}, {'n', 'a', 'v'}, {'n', 'a', 'v'}}, // Navajo
+ LanguageCodeEntry {{'n', 'g'}, {'n', 'd', 'o'}, {'n', 'd', 'o'}, {'n', 'd', 'o'}}, // Ndonga
+ LanguageCodeEntry {{'n', 'e'}, {'n', 'e', 'p'}, {'n', 'e', 'p'}, {'n', 'e', 'p'}}, // Nepali
+ LanguageCodeEntry {{}, {'n', 'e', 'w'}, {'n', 'e', 'w'}, {'n', 'e', 'w'}}, // Newari
+ LanguageCodeEntry {{}, {}, {}, {'n', 'n', 'h'}}, // Ngiemboon
+ LanguageCodeEntry {{}, {}, {}, {'j', 'g', 'o'}}, // Ngomba
+ LanguageCodeEntry {{}, {}, {}, {'p', 'c', 'm'}}, // Nigerian Pidgin
+ LanguageCodeEntry {{}, {'n', 'q', 'o'}, {'n', 'q', 'o'}, {'n', 'q', 'o'}}, // Nko
+ LanguageCodeEntry {{}, {}, {}, {'l', 'r', 'c'}}, // Northern Luri
+ LanguageCodeEntry {{'s', 'e'}, {'s', 'm', 'e'}, {'s', 'm', 'e'}, {'s', 'm', 'e'}}, // Northern Sami
+ LanguageCodeEntry {{}, {'n', 's', 'o'}, {'n', 's', 'o'}, {'n', 's', 'o'}}, // Northern Sotho
+ LanguageCodeEntry {{'n', 'd'}, {'n', 'd', 'e'}, {'n', 'd', 'e'}, {'n', 'd', 'e'}}, // North Ndebele
+ LanguageCodeEntry {{'n', 'b'}, {'n', 'o', 'b'}, {'n', 'o', 'b'}, {'n', 'o', 'b'}}, // Norwegian Bokmal
+ LanguageCodeEntry {{'n', 'n'}, {'n', 'n', 'o'}, {'n', 'n', 'o'}, {'n', 'n', 'o'}}, // Norwegian Nynorsk
+ LanguageCodeEntry {{}, {}, {}, {'n', 'u', 's'}}, // Nuer
+ LanguageCodeEntry {{'n', 'y'}, {'n', 'y', 'a'}, {'n', 'y', 'a'}, {'n', 'y', 'a'}}, // Nyanja
+ LanguageCodeEntry {{}, {'n', 'y', 'n'}, {'n', 'y', 'n'}, {'n', 'y', 'n'}}, // Nyankole
+ LanguageCodeEntry {{'o', 'c'}, {'o', 'c', 'i'}, {'o', 'c', 'i'}, {'o', 'c', 'i'}}, // Occitan
+ LanguageCodeEntry {{'o', 'r'}, {'o', 'r', 'i'}, {'o', 'r', 'i'}, {'o', 'r', 'i'}}, // Odia
+ LanguageCodeEntry {{'o', 'j'}, {'o', 'j', 'i'}, {'o', 'j', 'i'}, {'o', 'j', 'i'}}, // Ojibwa
+ LanguageCodeEntry {{}, {'s', 'g', 'a'}, {'s', 'g', 'a'}, {'s', 'g', 'a'}}, // Old Irish
+ LanguageCodeEntry {{}, {'n', 'o', 'n'}, {'n', 'o', 'n'}, {'n', 'o', 'n'}}, // Old Norse
+ LanguageCodeEntry {{}, {'p', 'e', 'o'}, {'p', 'e', 'o'}, {'p', 'e', 'o'}}, // Old Persian
+ LanguageCodeEntry {{'o', 'm'}, {'o', 'r', 'm'}, {'o', 'r', 'm'}, {'o', 'r', 'm'}}, // Oromo
+ LanguageCodeEntry {{}, {'o', 's', 'a'}, {'o', 's', 'a'}, {'o', 's', 'a'}}, // Osage
+ LanguageCodeEntry {{'o', 's'}, {'o', 's', 's'}, {'o', 's', 's'}, {'o', 's', 's'}}, // Ossetic
+ LanguageCodeEntry {{}, {'p', 'a', 'l'}, {'p', 'a', 'l'}, {'p', 'a', 'l'}}, // Pahlavi
+ LanguageCodeEntry {{}, {'p', 'a', 'u'}, {'p', 'a', 'u'}, {'p', 'a', 'u'}}, // Palauan
+ LanguageCodeEntry {{'p', 'i'}, {'p', 'l', 'i'}, {'p', 'l', 'i'}, {'p', 'l', 'i'}}, // Pali
+ LanguageCodeEntry {{}, {'p', 'a', 'p'}, {'p', 'a', 'p'}, {'p', 'a', 'p'}}, // Papiamento
+ LanguageCodeEntry {{'p', 's'}, {'p', 'u', 's'}, {'p', 'u', 's'}, {'p', 'u', 's'}}, // Pashto
+ LanguageCodeEntry {{'f', 'a'}, {'p', 'e', 'r'}, {'f', 'a', 's'}, {'f', 'a', 's'}}, // Persian
+ LanguageCodeEntry {{}, {'p', 'h', 'n'}, {'p', 'h', 'n'}, {'p', 'h', 'n'}}, // Phoenician
+ LanguageCodeEntry {{'p', 'l'}, {'p', 'o', 'l'}, {'p', 'o', 'l'}, {'p', 'o', 'l'}}, // Polish
+ LanguageCodeEntry {{'p', 't'}, {'p', 'o', 'r'}, {'p', 'o', 'r'}, {'p', 'o', 'r'}}, // Portuguese
+ LanguageCodeEntry {{}, {}, {}, {'p', 'r', 'g'}}, // Prussian
+ LanguageCodeEntry {{'p', 'a'}, {'p', 'a', 'n'}, {'p', 'a', 'n'}, {'p', 'a', 'n'}}, // Punjabi
+ LanguageCodeEntry {{'q', 'u'}, {'q', 'u', 'e'}, {'q', 'u', 'e'}, {'q', 'u', 'e'}}, // Quechua
+ LanguageCodeEntry {{'r', 'o'}, {'r', 'u', 'm'}, {'r', 'o', 'n'}, {'r', 'o', 'n'}}, // Romanian
+ LanguageCodeEntry {{'r', 'm'}, {'r', 'o', 'h'}, {'r', 'o', 'h'}, {'r', 'o', 'h'}}, // Romansh
+ LanguageCodeEntry {{}, {}, {}, {'r', 'o', 'f'}}, // Rombo
+ LanguageCodeEntry {{'r', 'n'}, {'r', 'u', 'n'}, {'r', 'u', 'n'}, {'r', 'u', 'n'}}, // Rundi
+ LanguageCodeEntry {{'r', 'u'}, {'r', 'u', 's'}, {'r', 'u', 's'}, {'r', 'u', 's'}}, // Russian
+ LanguageCodeEntry {{}, {}, {}, {'r', 'w', 'k'}}, // Rwa
+ LanguageCodeEntry {{}, {}, {}, {'s', 's', 'y'}}, // Saho
+ LanguageCodeEntry {{}, {'s', 'a', 'h'}, {'s', 'a', 'h'}, {'s', 'a', 'h'}}, // Sakha
+ LanguageCodeEntry {{}, {}, {}, {'s', 'a', 'q'}}, // Samburu
+ LanguageCodeEntry {{'s', 'm'}, {'s', 'm', 'o'}, {'s', 'm', 'o'}, {'s', 'm', 'o'}}, // Samoan
+ LanguageCodeEntry {{'s', 'g'}, {'s', 'a', 'g'}, {'s', 'a', 'g'}, {'s', 'a', 'g'}}, // Sango
+ LanguageCodeEntry {{}, {}, {}, {'s', 'b', 'p'}}, // Sangu
+ LanguageCodeEntry {{'s', 'a'}, {'s', 'a', 'n'}, {'s', 'a', 'n'}, {'s', 'a', 'n'}}, // Sanskrit
+ LanguageCodeEntry {{}, {'s', 'a', 't'}, {'s', 'a', 't'}, {'s', 'a', 't'}}, // Santali
+ LanguageCodeEntry {{'s', 'c'}, {'s', 'r', 'd'}, {'s', 'r', 'd'}, {'s', 'r', 'd'}}, // Sardinian
+ LanguageCodeEntry {{}, {}, {}, {'s', 'a', 'z'}}, // Saurashtra
+ LanguageCodeEntry {{}, {}, {}, {'s', 'e', 'h'}}, // Sena
+ LanguageCodeEntry {{'s', 'r'}, {'s', 'r', 'p'}, {'s', 'r', 'p'}, {'s', 'r', 'p'}}, // Serbian
+ LanguageCodeEntry {{}, {}, {}, {'k', 's', 'b'}}, // Shambala
+ LanguageCodeEntry {{'s', 'n'}, {'s', 'n', 'a'}, {'s', 'n', 'a'}, {'s', 'n', 'a'}}, // Shona
+ LanguageCodeEntry {{'i', 'i'}, {'i', 'i', 'i'}, {'i', 'i', 'i'}, {'i', 'i', 'i'}}, // Sichuan Yi
+ LanguageCodeEntry {{}, {'s', 'c', 'n'}, {'s', 'c', 'n'}, {'s', 'c', 'n'}}, // Sicilian
+ LanguageCodeEntry {{}, {'s', 'i', 'd'}, {'s', 'i', 'd'}, {'s', 'i', 'd'}}, // Sidamo
+ LanguageCodeEntry {{}, {}, {}, {'s', 'z', 'l'}}, // Silesian
+ LanguageCodeEntry {{'s', 'd'}, {'s', 'n', 'd'}, {'s', 'n', 'd'}, {'s', 'n', 'd'}}, // Sindhi
+ LanguageCodeEntry {{'s', 'i'}, {'s', 'i', 'n'}, {'s', 'i', 'n'}, {'s', 'i', 'n'}}, // Sinhala
+ LanguageCodeEntry {{}, {'s', 'm', 's'}, {'s', 'm', 's'}, {'s', 'm', 's'}}, // Skolt Sami
+ LanguageCodeEntry {{'s', 'k'}, {'s', 'l', 'o'}, {'s', 'l', 'k'}, {'s', 'l', 'k'}}, // Slovak
+ LanguageCodeEntry {{'s', 'l'}, {'s', 'l', 'v'}, {'s', 'l', 'v'}, {'s', 'l', 'v'}}, // Slovenian
+ LanguageCodeEntry {{}, {}, {}, {'x', 'o', 'g'}}, // Soga
+ LanguageCodeEntry {{'s', 'o'}, {'s', 'o', 'm'}, {'s', 'o', 'm'}, {'s', 'o', 'm'}}, // Somali
+ LanguageCodeEntry {{}, {}, {}, {'s', 'd', 'h'}}, // Southern Kurdish
+ LanguageCodeEntry {{}, {'s', 'm', 'a'}, {'s', 'm', 'a'}, {'s', 'm', 'a'}}, // Southern Sami
+ LanguageCodeEntry {{'s', 't'}, {'s', 'o', 't'}, {'s', 'o', 't'}, {'s', 'o', 't'}}, // Southern Sotho
+ LanguageCodeEntry {{'n', 'r'}, {'n', 'b', 'l'}, {'n', 'b', 'l'}, {'n', 'b', 'l'}}, // South Ndebele
+ LanguageCodeEntry {{'e', 's'}, {'s', 'p', 'a'}, {'s', 'p', 'a'}, {'s', 'p', 'a'}}, // Spanish
+ LanguageCodeEntry {{}, {'z', 'g', 'h'}, {'z', 'g', 'h'}, {'z', 'g', 'h'}}, // Standard Moroccan Tamazight
+ LanguageCodeEntry {{'s', 'u'}, {'s', 'u', 'n'}, {'s', 'u', 'n'}, {'s', 'u', 'n'}}, // Sundanese
+ LanguageCodeEntry {{'s', 'w'}, {'s', 'w', 'a'}, {'s', 'w', 'a'}, {'s', 'w', 'a'}}, // Swahili
+ LanguageCodeEntry {{'s', 's'}, {'s', 's', 'w'}, {'s', 's', 'w'}, {'s', 's', 'w'}}, // Swati
+ LanguageCodeEntry {{'s', 'v'}, {'s', 'w', 'e'}, {'s', 'w', 'e'}, {'s', 'w', 'e'}}, // Swedish
+ LanguageCodeEntry {{}, {'g', 's', 'w'}, {'g', 's', 'w'}, {'g', 's', 'w'}}, // Swiss German
+ LanguageCodeEntry {{}, {'s', 'y', 'r'}, {'s', 'y', 'r'}, {'s', 'y', 'r'}}, // Syriac
+ LanguageCodeEntry {{}, {}, {}, {'s', 'h', 'i'}}, // Tachelhit
+ LanguageCodeEntry {{'t', 'y'}, {'t', 'a', 'h'}, {'t', 'a', 'h'}, {'t', 'a', 'h'}}, // Tahitian
+ LanguageCodeEntry {{}, {}, {}, {'b', 'l', 't'}}, // Tai Dam
+ LanguageCodeEntry {{}, {}, {}, {'d', 'a', 'v'}}, // Taita
+ LanguageCodeEntry {{'t', 'g'}, {'t', 'g', 'k'}, {'t', 'g', 'k'}, {'t', 'g', 'k'}}, // Tajik
+ LanguageCodeEntry {{'t', 'a'}, {'t', 'a', 'm'}, {'t', 'a', 'm'}, {'t', 'a', 'm'}}, // Tamil
+ LanguageCodeEntry {{}, {}, {}, {'t', 'r', 'v'}}, // Taroko
+ LanguageCodeEntry {{}, {}, {}, {'t', 'w', 'q'}}, // Tasawaq
+ LanguageCodeEntry {{'t', 't'}, {'t', 'a', 't'}, {'t', 'a', 't'}, {'t', 'a', 't'}}, // Tatar
+ LanguageCodeEntry {{'t', 'e'}, {'t', 'e', 'l'}, {'t', 'e', 'l'}, {'t', 'e', 'l'}}, // Telugu
+ LanguageCodeEntry {{}, {}, {}, {'t', 'e', 'o'}}, // Teso
+ LanguageCodeEntry {{'t', 'h'}, {'t', 'h', 'a'}, {'t', 'h', 'a'}, {'t', 'h', 'a'}}, // Thai
+ LanguageCodeEntry {{'b', 'o'}, {'t', 'i', 'b'}, {'b', 'o', 'd'}, {'b', 'o', 'd'}}, // Tibetan
+ LanguageCodeEntry {{}, {'t', 'i', 'g'}, {'t', 'i', 'g'}, {'t', 'i', 'g'}}, // Tigre
+ LanguageCodeEntry {{'t', 'i'}, {'t', 'i', 'r'}, {'t', 'i', 'r'}, {'t', 'i', 'r'}}, // Tigrinya
+ LanguageCodeEntry {{}, {'t', 'k', 'l'}, {'t', 'k', 'l'}, {'t', 'k', 'l'}}, // Tokelau
+ LanguageCodeEntry {{}, {'t', 'p', 'i'}, {'t', 'p', 'i'}, {'t', 'p', 'i'}}, // Tok Pisin
+ LanguageCodeEntry {{'t', 'o'}, {'t', 'o', 'n'}, {'t', 'o', 'n'}, {'t', 'o', 'n'}}, // Tongan
+ LanguageCodeEntry {{'t', 's'}, {'t', 's', 'o'}, {'t', 's', 'o'}, {'t', 's', 'o'}}, // Tsonga
+ LanguageCodeEntry {{'t', 'n'}, {'t', 's', 'n'}, {'t', 's', 'n'}, {'t', 's', 'n'}}, // Tswana
+ LanguageCodeEntry {{'t', 'r'}, {'t', 'u', 'r'}, {'t', 'u', 'r'}, {'t', 'u', 'r'}}, // Turkish
+ LanguageCodeEntry {{'t', 'k'}, {'t', 'u', 'k'}, {'t', 'u', 'k'}, {'t', 'u', 'k'}}, // Turkmen
+ LanguageCodeEntry {{}, {'t', 'v', 'l'}, {'t', 'v', 'l'}, {'t', 'v', 'l'}}, // Tuvalu
+ LanguageCodeEntry {{}, {}, {}, {'k', 'c', 'g'}}, // Tyap
+ LanguageCodeEntry {{}, {'u', 'g', 'a'}, {'u', 'g', 'a'}, {'u', 'g', 'a'}}, // Ugaritic
+ LanguageCodeEntry {{'u', 'k'}, {'u', 'k', 'r'}, {'u', 'k', 'r'}, {'u', 'k', 'r'}}, // Ukrainian
+ LanguageCodeEntry {{}, {'h', 's', 'b'}, {'h', 's', 'b'}, {'h', 's', 'b'}}, // Upper Sorbian
+ LanguageCodeEntry {{'u', 'r'}, {'u', 'r', 'd'}, {'u', 'r', 'd'}, {'u', 'r', 'd'}}, // Urdu
+ LanguageCodeEntry {{'u', 'g'}, {'u', 'i', 'g'}, {'u', 'i', 'g'}, {'u', 'i', 'g'}}, // Uyghur
+ LanguageCodeEntry {{'u', 'z'}, {'u', 'z', 'b'}, {'u', 'z', 'b'}, {'u', 'z', 'b'}}, // Uzbek
+ LanguageCodeEntry {{}, {'v', 'a', 'i'}, {'v', 'a', 'i'}, {'v', 'a', 'i'}}, // Vai
+ LanguageCodeEntry {{'v', 'e'}, {'v', 'e', 'n'}, {'v', 'e', 'n'}, {'v', 'e', 'n'}}, // Venda
+ LanguageCodeEntry {{'v', 'i'}, {'v', 'i', 'e'}, {'v', 'i', 'e'}, {'v', 'i', 'e'}}, // Vietnamese
+ LanguageCodeEntry {{'v', 'o'}, {'v', 'o', 'l'}, {'v', 'o', 'l'}, {'v', 'o', 'l'}}, // Volapuk
+ LanguageCodeEntry {{}, {}, {}, {'v', 'u', 'n'}}, // Vunjo
+ LanguageCodeEntry {{'w', 'a'}, {'w', 'l', 'n'}, {'w', 'l', 'n'}, {'w', 'l', 'n'}}, // Walloon
+ LanguageCodeEntry {{}, {}, {}, {'w', 'a', 'e'}}, // Walser
+ LanguageCodeEntry {{}, {}, {}, {'w', 'b', 'p'}}, // Warlpiri
+ LanguageCodeEntry {{'c', 'y'}, {'w', 'e', 'l'}, {'c', 'y', 'm'}, {'c', 'y', 'm'}}, // Welsh
+ LanguageCodeEntry {{}, {}, {}, {'b', 'g', 'n'}}, // Western Balochi
+ LanguageCodeEntry {{'f', 'y'}, {'f', 'r', 'y'}, {'f', 'r', 'y'}, {'f', 'r', 'y'}}, // Western Frisian
+ LanguageCodeEntry {{}, {'w', 'a', 'l'}, {'w', 'a', 'l'}, {'w', 'a', 'l'}}, // Wolaytta
+ LanguageCodeEntry {{'w', 'o'}, {'w', 'o', 'l'}, {'w', 'o', 'l'}, {'w', 'o', 'l'}}, // Wolof
+ LanguageCodeEntry {{'x', 'h'}, {'x', 'h', 'o'}, {'x', 'h', 'o'}, {'x', 'h', 'o'}}, // Xhosa
+ LanguageCodeEntry {{}, {}, {}, {'y', 'a', 'v'}}, // Yangben
+ LanguageCodeEntry {{'y', 'i'}, {'y', 'i', 'd'}, {'y', 'i', 'd'}, {'y', 'i', 'd'}}, // Yiddish
+ LanguageCodeEntry {{'y', 'o'}, {'y', 'o', 'r'}, {'y', 'o', 'r'}, {'y', 'o', 'r'}}, // Yoruba
+ LanguageCodeEntry {{}, {}, {}, {'d', 'j', 'e'}}, // Zarma
+ LanguageCodeEntry {{'z', 'a'}, {'z', 'h', 'a'}, {'z', 'h', 'a'}, {'z', 'h', 'a'}}, // Zhuang
+ LanguageCodeEntry {{'z', 'u'}, {'z', 'u', 'l'}, {'z', 'u', 'l'}, {'z', 'u', 'l'}}, // Zulu
+ LanguageCodeEntry {{}, {}, {}, {'k', 'g', 'p'}}, // Kaingang
+ LanguageCodeEntry {{}, {}, {}, {'y', 'r', 'l'}}, // Nheengatu
+ LanguageCodeEntry {{}, {}, {}, {'b', 'g', 'c'}}, // Haryanvi
+ LanguageCodeEntry {{}, {'f', 'r', 'r'}, {'f', 'r', 'r'}, {'f', 'r', 'r'}}, // Northern Frisian
+ LanguageCodeEntry {{}, {'r', 'a', 'j'}, {'r', 'a', 'j'}, {'r', 'a', 'j'}}, // Rajasthani
+ LanguageCodeEntry {{}, {'m', 'd', 'f'}, {'m', 'd', 'f'}, {'m', 'd', 'f'}}, // Moksha
+ LanguageCodeEntry {{}, {}, {}, {'t', 'o', 'k'}}, // Toki Pona
+ LanguageCodeEntry {{}, {}, {}, {'p', 'i', 's'}}, // Pijin
+ LanguageCodeEntry {{}, {}, {}, {'a', 'n', 'n'}}, // Obolo
+ LanguageCodeEntry {{}, {'b', 'a', 'l'}, {'b', 'a', 'l'}, {'b', 'a', 'l'}}, // Baluchi
+ LanguageCodeEntry {{}, {}, {}, {'l', 'i', 'j'}}, // Ligurian
+ LanguageCodeEntry {{}, {}, {}, {'r', 'h', 'g'}}, // Rohingya
+ LanguageCodeEntry {{}, {}, {}, {'t', 'r', 'w'}}, // Torwali
+ LanguageCodeEntry {{}, {}, {}, {'b', 'l', 'o'}}, // Anii
+ LanguageCodeEntry {{}, {}, {}, {'x', 'n', 'r'}}, // Kangri
+ LanguageCodeEntry {{}, {}, {}, {'v', 'e', 'c'}}, // Venetian
+};
-static const unsigned char script_code_list[] =
+static constexpr unsigned char script_code_list[] =
"Zzzz" // AnyScript
+"Adlm" // Adlam
+"Ahom" // Ahom
+"Hluw" // Anatolian Hieroglyphs
"Arab" // Arabic
-"Cyrl" // Cyrillic
-"Dsrt" // Deseret
-"Guru" // Gurmukhi
-"Hans" // Simplified Han
-"Hant" // Traditional Han
-"Latn" // Latin
-"Mong" // Mongolian
-"Tfng" // Tifinagh
"Armn" // Armenian
-"Beng" // Bengali
-"Cher" // Cherokee
-"Deva" // Devanagari
-"Ethi" // Ethiopic
-"Geor" // Georgian
-"Grek" // Greek
-"Gujr" // Gujarati
-"Hebr" // Hebrew
-"Jpan" // Japanese
-"Khmr" // Khmer
-"Knda" // Kannada
-"Kore" // Korean
-"Laoo" // Lao
-"Mlym" // Malayalam
-"Mymr" // Myanmar
-"Orya" // Oriya
-"Taml" // Tamil
-"Telu" // Telugu
-"Thaa" // Thaana
-"Thai" // Thai
-"Tibt" // Tibetan
-"Sinh" // Sinhala
-"Syrc" // Syriac
-"Yiii" // Yi
-"Vaii" // Vai
"Avst" // Avestan
"Bali" // Balinese
"Bamu" // Bamum
+"Beng" // Bangla
+"Bass" // Bassa Vah
"Batk" // Batak
+"Bhks" // Bhaiksuki
"Bopo" // Bopomofo
"Brah" // Brahmi
+"Brai" // Braille
"Bugi" // Buginese
"Buhd" // Buhid
"Cans" // Canadian Aboriginal
"Cari" // Carian
+"Aghb" // Caucasian Albanian
"Cakm" // Chakma
"Cham" // Cham
+"Cher" // Cherokee
"Copt" // Coptic
+"Xsux" // Cuneiform
"Cprt" // Cypriot
-"Egyp" // Egyptian Hieroglyphs
+"Cyrl" // Cyrillic
+"Dsrt" // Deseret
+"Deva" // Devanagari
+"Dupl" // Duployan
+"Egyp" // Egyptian hieroglyphs
+"Elba" // Elbasan
+"Ethi" // Ethiopic
"Lisu" // Fraser
+"Geor" // Georgian
"Glag" // Glagolitic
"Goth" // Gothic
-"Hani" // Han
+"Gran" // Grantha
+"Grek" // Greek
+"Gujr" // Gujarati
+"Guru" // Gurmukhi
"Hang" // Hangul
+"Hani" // Han
"Hano" // Hanunoo
+"Hanb" // Han with Bopomofo
+"Hatr" // Hatran
+"Hebr" // Hebrew
+"Hira" // Hiragana
"Armi" // Imperial Aramaic
"Phli" // Inscriptional Pahlavi
"Prti" // Inscriptional Parthian
+"Jamo" // Jamo
+"Jpan" // Japanese
"Java" // Javanese
"Kthi" // Kaithi
+"Knda" // Kannada
"Kana" // Katakana
"Kali" // Kayah Li
"Khar" // Kharoshthi
+"Khmr" // Khmer
+"Khoj" // Khojki
+"Sind" // Khudawadi
+"Kore" // Korean
"Lana" // Lanna
+"Laoo" // Lao
+"Latn" // Latin
"Lepc" // Lepcha
"Limb" // Limbu
+"Lina" // Linear A
"Linb" // Linear B
"Lyci" // Lycian
"Lydi" // Lydian
+"Mahj" // Mahajani
+"Mlym" // Malayalam
"Mand" // Mandaean
+"Mani" // Manichaean
+"Marc" // Marchen
"Mtei" // Meitei Mayek
-"Mero" // Meroitic
+"Mend" // Mende
"Merc" // Meroitic Cursive
-"Nkoo" // Nko
+"Mero" // Meroitic
+"Modi" // Modi
+"Mong" // Mongolian
+"Mroo" // Mro
+"Mult" // Multani
+"Mymr" // Myanmar
+"Nbat" // Nabataean
+"Newa" // Newa
"Talu" // New Tai Lue
+"Nkoo" // Nko
+"Orya" // Odia
"Ogam" // Ogham
"Olck" // Ol Chiki
+"Hung" // Old Hungarian
"Ital" // Old Italic
+"Narb" // Old North Arabian
+"Perm" // Old Permic
"Xpeo" // Old Persian
"Sarb" // Old South Arabian
"Orkh" // Orkhon
+"Osge" // Osage
"Osma" // Osmanya
-"Phag" // Phags Pa
+"Hmng" // Pahawh Hmong
+"Palm" // Palmyrene
+"Pauc" // Pau Cin Hau
+"Phag" // Phags-pa
"Phnx" // Phoenician
"Plrd" // Pollard Phonetic
+"Phlp" // Psalter Pahlavi
"Rjng" // Rejang
"Runr" // Runic
"Samr" // Samaritan
"Saur" // Saurashtra
"Shrd" // Sharada
"Shaw" // Shavian
+"Sidd" // Siddham
+"Sgnw" // SignWriting
+"Hans" // Simplified Han
+"Sinh" // Sinhala
"Sora" // Sora Sompeng
-"Xsux" // Cuneiform
"Sund" // Sundanese
"Sylo" // Syloti Nagri
+"Syrc" // Syriac
"Tglg" // Tagalog
"Tagb" // Tagbanwa
"Tale" // Tai Le
"Tavt" // Tai Viet
"Takr" // Takri
-"Ugar" // Ugaritic
-"Brai" // Braille
-"Hira" // Hiragana
-"Aghb" // Caucasian Albanian
-"Bass" // Bassa Vah
-"Dupl" // Duployan
-"Elba" // Elbasan
-"Gran" // Grantha
-"Hmng" // Pahawh Hmong
-"Khoj" // Khojki
-"Lina" // Linear A
-"Mahj" // Mahajani
-"Mani" // Manichaean
-"Mend" // Mende Kikakui
-"Modi" // Modi
-"Mroo" // Mro
-"Narb" // Old North Arabian
-"Nbat" // Nabataean
-"Palm" // Palmyrene
-"Pauc" // Pau Cin Hau
-"Perm" // Old Permic
-"Phlp" // Psalter Pahlavi
-"Sidd" // Siddham
-"Sind" // Khudawadi
+"Taml" // Tamil
+"Tang" // Tangut
+"Telu" // Telugu
+"Thaa" // Thaana
+"Thai" // Thai
+"Tibt" // Tibetan
+"Tfng" // Tifinagh
"Tirh" // Tirhuta
+"Hant" // Traditional Han
+"Ugar" // Ugaritic
+"Vaii" // Vai
"Wara" // Varang Kshiti
-"Ahom" // Ahom
-"Hluw" // Anatolian Hieroglyphs
-"Hatr" // Hatran
-"Mult" // Multani
-"Hung" // Old Hungarian
-"Sgnw" // Sign Writing
-"Adlm" // Adlam
-"Bhks" // Bhaiksuki
-"Marc" // Marchen
-"Newa" // Newa
-"Osge" // Osage
-"Tang" // Tangut
-"Hanb" // Han with Bopomofo
-"Jamo" // Jamo
+"Yiii" // Yi
+"Rohg" // Hanifi
;
-static const unsigned char country_code_list[] =
-"ZZ\0" // AnyCountry
+static constexpr unsigned char territory_code_list[] =
+"ZZ\0" // AnyTerritory
"AF\0" // Afghanistan
+"AX\0" // Aland Islands
"AL\0" // Albania
"DZ\0" // Algeria
"AS\0" // American Samoa
@@ -6548,10 +8213,11 @@ static const unsigned char country_code_list[] =
"AO\0" // Angola
"AI\0" // Anguilla
"AQ\0" // Antarctica
-"AG\0" // Antigua And Barbuda
+"AG\0" // Antigua and Barbuda
"AR\0" // Argentina
"AM\0" // Armenia
"AW\0" // Aruba
+"AC\0" // Ascension Island
"AU\0" // Australia
"AT\0" // Austria
"AZ\0" // Azerbaijan
@@ -6566,11 +8232,12 @@ static const unsigned char country_code_list[] =
"BM\0" // Bermuda
"BT\0" // Bhutan
"BO\0" // Bolivia
-"BA\0" // Bosnia And Herzegowina
+"BA\0" // Bosnia and Herzegovina
"BW\0" // Botswana
"BV\0" // Bouvet Island
"BR\0" // Brazil
"IO\0" // British Indian Ocean Territory
+"VG\0" // British Virgin Islands
"BN\0" // Brunei
"BG\0" // Bulgaria
"BF\0" // Burkina Faso
@@ -6578,43 +8245,49 @@ static const unsigned char country_code_list[] =
"KH\0" // Cambodia
"CM\0" // Cameroon
"CA\0" // Canada
+"IC\0" // Canary Islands
"CV\0" // Cape Verde
+"BQ\0" // Caribbean Netherlands
"KY\0" // Cayman Islands
"CF\0" // Central African Republic
+"EA\0" // Ceuta and Melilla
"TD\0" // Chad
"CL\0" // Chile
"CN\0" // China
"CX\0" // Christmas Island
+"CP\0" // Clipperton Island
"CC\0" // Cocos Islands
"CO\0" // Colombia
"KM\0" // Comoros
-"CD\0" // Congo Kinshasa
-"CG\0" // Congo Brazzaville
+"CG\0" // Congo - Brazzaville
+"CD\0" // Congo - Kinshasa
"CK\0" // Cook Islands
"CR\0" // Costa Rica
-"CI\0" // Ivory Coast
"HR\0" // Croatia
"CU\0" // Cuba
+"CW\0" // Curacao
"CY\0" // Cyprus
-"CZ\0" // Czech Republic
+"CZ\0" // Czechia
"DK\0" // Denmark
+"DG\0" // Diego Garcia
"DJ\0" // Djibouti
"DM\0" // Dominica
"DO\0" // Dominican Republic
-"TL\0" // East Timor
"EC\0" // Ecuador
"EG\0" // Egypt
"SV\0" // El Salvador
"GQ\0" // Equatorial Guinea
"ER\0" // Eritrea
"EE\0" // Estonia
+"SZ\0" // Eswatini
"ET\0" // Ethiopia
+"150" // Europe
+"EU\0" // European Union
"FK\0" // Falkland Islands
"FO\0" // Faroe Islands
"FJ\0" // Fiji
"FI\0" // Finland
"FR\0" // France
-"GG\0" // Guernsey
"GF\0" // French Guiana
"PF\0" // French Polynesia
"TF\0" // French Southern Territories
@@ -6630,11 +8303,12 @@ static const unsigned char country_code_list[] =
"GP\0" // Guadeloupe
"GU\0" // Guam
"GT\0" // Guatemala
+"GG\0" // Guernsey
+"GW\0" // Guinea-Bissau
"GN\0" // Guinea
-"GW\0" // Guinea Bissau
"GY\0" // Guyana
"HT\0" // Haiti
-"HM\0" // Heard And McDonald Islands
+"HM\0" // Heard and McDonald Islands
"HN\0" // Honduras
"HK\0" // Hong Kong
"HU\0" // Hungary
@@ -6644,19 +8318,22 @@ static const unsigned char country_code_list[] =
"IR\0" // Iran
"IQ\0" // Iraq
"IE\0" // Ireland
+"IM\0" // Isle of Man
"IL\0" // Israel
"IT\0" // Italy
+"CI\0" // Ivory Coast
"JM\0" // Jamaica
"JP\0" // Japan
+"JE\0" // Jersey
"JO\0" // Jordan
"KZ\0" // Kazakhstan
"KE\0" // Kenya
"KI\0" // Kiribati
-"KP\0" // North Korea
-"KR\0" // South Korea
+"XK\0" // Kosovo
"KW\0" // Kuwait
"KG\0" // Kyrgyzstan
"LA\0" // Laos
+"419" // Latin America
"LV\0" // Latvia
"LB\0" // Lebanon
"LS\0" // Lesotho
@@ -6665,7 +8342,7 @@ static const unsigned char country_code_list[] =
"LI\0" // Liechtenstein
"LT\0" // Lithuania
"LU\0" // Luxembourg
-"MO\0" // Macau
+"MO\0" // Macao
"MK\0" // Macedonia
"MG\0" // Madagascar
"MW\0" // Malawi
@@ -6683,6 +8360,7 @@ static const unsigned char country_code_list[] =
"MD\0" // Moldova
"MC\0" // Monaco
"MN\0" // Mongolia
+"ME\0" // Montenegro
"MS\0" // Montserrat
"MA\0" // Morocco
"MZ\0" // Mozambique
@@ -6691,17 +8369,18 @@ static const unsigned char country_code_list[] =
"NR\0" // Nauru
"NP\0" // Nepal
"NL\0" // Netherlands
-"CW\0" // Cura Sao
"NC\0" // New Caledonia
"NZ\0" // New Zealand
"NI\0" // Nicaragua
-"NE\0" // Niger
"NG\0" // Nigeria
+"NE\0" // Niger
"NU\0" // Niue
"NF\0" // Norfolk Island
"MP\0" // Northern Mariana Islands
+"KP\0" // North Korea
"NO\0" // Norway
"OM\0" // Oman
+"QO\0" // Outlying Oceania
"PK\0" // Pakistan
"PW\0" // Palau
"PS\0" // Palestinian Territories
@@ -6719,31 +8398,36 @@ static const unsigned char country_code_list[] =
"RO\0" // Romania
"RU\0" // Russia
"RW\0" // Rwanda
-"KN\0" // Saint Kitts And Nevis
+"BL\0" // Saint Barthelemy
+"SH\0" // Saint Helena
+"KN\0" // Saint Kitts and Nevis
"LC\0" // Saint Lucia
-"VC\0" // Saint Vincent And The Grenadines
+"MF\0" // Saint Martin
+"PM\0" // Saint Pierre and Miquelon
+"VC\0" // Saint Vincent and Grenadines
"WS\0" // Samoa
"SM\0" // San Marino
-"ST\0" // Sao Tome And Principe
+"ST\0" // Sao Tome and Principe
"SA\0" // Saudi Arabia
"SN\0" // Senegal
+"RS\0" // Serbia
"SC\0" // Seychelles
"SL\0" // Sierra Leone
"SG\0" // Singapore
+"SX\0" // Sint Maarten
"SK\0" // Slovakia
"SI\0" // Slovenia
"SB\0" // Solomon Islands
"SO\0" // Somalia
"ZA\0" // South Africa
-"GS\0" // South Georgia And The South Sandwich Islands
+"GS\0" // South Georgia and South Sandwich Islands
+"KR\0" // South Korea
+"SS\0" // South Sudan
"ES\0" // Spain
"LK\0" // Sri Lanka
-"SH\0" // Saint Helena
-"PM\0" // Saint Pierre And Miquelon
"SD\0" // Sudan
"SR\0" // Suriname
-"SJ\0" // Svalbard And Jan Mayen Islands
-"SZ\0" // Swaziland
+"SJ\0" // Svalbard and Jan Mayen
"SE\0" // Sweden
"CH\0" // Switzerland
"SY\0" // Syria
@@ -6751,56 +8435,36 @@ static const unsigned char country_code_list[] =
"TJ\0" // Tajikistan
"TZ\0" // Tanzania
"TH\0" // Thailand
+"TL\0" // Timor-Leste
"TG\0" // Togo
"TK\0" // Tokelau
"TO\0" // Tonga
-"TT\0" // Trinidad And Tobago
+"TT\0" // Trinidad and Tobago
+"TA\0" // Tristan da Cunha
"TN\0" // Tunisia
"TR\0" // Turkey
"TM\0" // Turkmenistan
-"TC\0" // Turks And Caicos Islands
+"TC\0" // Turks and Caicos Islands
"TV\0" // Tuvalu
"UG\0" // Uganda
"UA\0" // Ukraine
"AE\0" // United Arab Emirates
"GB\0" // United Kingdom
+"UM\0" // United States Outlying Islands
"US\0" // United States
-"UM\0" // United States Minor Outlying Islands
+"VI\0" // United States Virgin Islands
"UY\0" // Uruguay
"UZ\0" // Uzbekistan
"VU\0" // Vanuatu
-"VA\0" // Vatican City State
+"VA\0" // Vatican City
"VE\0" // Venezuela
"VN\0" // Vietnam
-"VG\0" // British Virgin Islands
-"VI\0" // United States Virgin Islands
-"WF\0" // Wallis And Futuna Islands
+"WF\0" // Wallis and Futuna
"EH\0" // Western Sahara
+"001" // world
"YE\0" // Yemen
-"IC\0" // Canary Islands
"ZM\0" // Zambia
"ZW\0" // Zimbabwe
-"CP\0" // Clipperton Island
-"ME\0" // Montenegro
-"RS\0" // Serbia
-"BL\0" // Saint Barthelemy
-"MF\0" // Saint Martin
-"419" // Latin America
-"AC\0" // Ascension Island
-"AX\0" // Aland Islands
-"DG\0" // Diego Garcia
-"EA\0" // Ceuta And Melilla
-"IM\0" // Isle Of Man
-"JE\0" // Jersey
-"TA\0" // Tristan Da Cunha
-"SS\0" // South Sudan
-"BQ\0" // Bonaire
-"SX\0" // Sint Maarten
-"XK\0" // Kosovo
-"EU\0" // European Union
-"QO\0" // Outlying Oceania
-"001" // World
-"150" // Europe
;
// GENERATED PART ENDS HERE
diff --git a/src/corelib/text/qlocale_icu.cpp b/src/corelib/text/qlocale_icu.cpp
index afe0aae583..55231286a0 100644
--- a/src/corelib/text/qlocale_icu.cpp
+++ b/src/corelib/text/qlocale_icu.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qdebug.h"
diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm
index 95c8769096..89339be2eb 100644
--- a/src/corelib/text/qlocale_mac.mm
+++ b/src/corelib/text/qlocale_mac.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlocale_p.h"
@@ -43,95 +7,289 @@
#include "qvariant.h"
#include "qdatetime.h"
+#include "private/qstringiterator_p.h"
+#include "private/qgregoriancalendar_p.h"
#ifdef Q_OS_DARWIN
#include "private/qcore_mac_p.h"
#include <CoreFoundation/CoreFoundation.h>
#endif
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qcoreapplication.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/******************************************************************************
** Wrappers for Mac locale system functions
*/
-static QByteArray envVarLocale()
+Q_LOGGING_CATEGORY(lcLocale, "qt.core.locale")
+
+static void printLocalizationInformation()
{
- QByteArray
-#ifdef Q_OS_UNIX
- lang = qgetenv("LC_ALL");
- if (lang.isEmpty())
- lang = qgetenv("LC_NUMERIC");
- if (lang.isEmpty())
+ if (!lcLocale().isDebugEnabled())
+ return;
+
+#if defined(Q_OS_MACOS)
+ // Trigger initialization of standard user defaults, so that Foundation picks
+ // up -AppleLanguages and -AppleLocale passed on the command line.
+ Q_UNUSED(NSUserDefaults.standardUserDefaults);
#endif
- lang = qgetenv("LANG");
- return lang;
+
+ auto singleLineDescription = [](NSArray *array) {
+ NSString *str = [array description];
+ str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];
+ return [str stringByReplacingOccurrencesOfString:@" " withString:@""];
+ };
+
+ bool allowMixedLocalizations = [NSBundle.mainBundle.infoDictionary[@"CFBundleAllowMixedLocalizations"] boolValue];
+
+ NSBundle *foundation = [NSBundle bundleForClass:NSBundle.class];
+ qCDebug(lcLocale).nospace() << "Launched with locale \"" << NSLocale.currentLocale.localeIdentifier
+ << "\" based on user's preferred languages " << singleLineDescription(NSLocale.preferredLanguages)
+ << ", main bundle localizations " << singleLineDescription(NSBundle.mainBundle.localizations)
+ << ", and allowing mixed localizations " << allowMixedLocalizations
+ << "; resulting in main bundle preferred localizations "
+ << singleLineDescription(NSBundle.mainBundle.preferredLocalizations)
+ << " and Foundation preferred localizations "
+ << singleLineDescription(foundation.preferredLocalizations);
+ qCDebug(lcLocale) << "Reflected by Qt as system locale"
+ << QLocale::system() << "with UI languges " << QLocale::system().uiLanguages();
}
+Q_COREAPP_STARTUP_FUNCTION(printLocalizationInformation);
static QString getMacLocaleName()
{
- QString result = QString::fromLocal8Bit(envVarLocale());
-
- QString lang, script, cntry;
- if (result.isEmpty()
- || (result != QLatin1String("C") && !qt_splitLocaleName(result, lang, script, cntry))) {
- QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
- CFStringRef locale = CFLocaleGetIdentifier(l);
- result = QString::fromCFString(locale);
- }
- return result;
+ QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
+ CFStringRef locale = CFLocaleGetIdentifier(l);
+ return QString::fromCFString(locale);
}
-static QString macMonthName(int month, bool short_format)
+static QVariant macMonthName(int month, QSystemLocale::QueryType type)
{
month -= 1;
if (month < 0 || month > 11)
- return QString();
+ return {};
QCFType<CFDateFormatterRef> formatter
= CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
+
+ CFDateFormatterKey formatterType;
+ switch (type) {
+ case QSystemLocale::MonthNameLong:
+ formatterType = kCFDateFormatterMonthSymbols;
+ break;
+ case QSystemLocale::MonthNameShort:
+ formatterType = kCFDateFormatterShortMonthSymbols;
+ break;
+ case QSystemLocale::MonthNameNarrow:
+ formatterType = kCFDateFormatterVeryShortMonthSymbols;
+ break;
+ case QSystemLocale::StandaloneMonthNameLong:
+ formatterType = kCFDateFormatterStandaloneMonthSymbols;
+ break;
+ case QSystemLocale::StandaloneMonthNameShort:
+ formatterType = kCFDateFormatterShortStandaloneMonthSymbols;
+ break;
+ case QSystemLocale::StandaloneMonthNameNarrow:
+ formatterType = kCFDateFormatterVeryShortStandaloneMonthSymbols;
+ break;
+ default:
+ qWarning("macMonthName: Unsupported query type %d", type);
+ return {};
+ }
QCFType<CFArrayRef> values
- = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
- short_format ? kCFDateFormatterShortMonthSymbols
- : kCFDateFormatterMonthSymbols));
+ = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, formatterType));
+
if (values != 0) {
CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month));
return QString::fromCFString(cfstring);
}
- return QString();
+ return {};
}
-static QString macDayName(int day, bool short_format)
+static QVariant macDayName(int day, QSystemLocale::QueryType type)
{
if (day < 1 || day > 7)
- return QString();
+ return {};
QCFType<CFDateFormatterRef> formatter
= CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
- QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
- short_format ? kCFDateFormatterShortWeekdaySymbols
- : kCFDateFormatterWeekdaySymbols));
+
+ CFDateFormatterKey formatterType;
+ switch (type) {
+ case QSystemLocale::DayNameLong:
+ formatterType = kCFDateFormatterWeekdaySymbols;
+ break;
+ case QSystemLocale::DayNameShort:
+ formatterType = kCFDateFormatterShortWeekdaySymbols;
+ break;
+ case QSystemLocale::DayNameNarrow:
+ formatterType = kCFDateFormatterVeryShortWeekdaySymbols;
+ break;
+ case QSystemLocale::StandaloneDayNameLong:
+ formatterType = kCFDateFormatterStandaloneWeekdaySymbols;
+ break;
+ case QSystemLocale::StandaloneDayNameShort:
+ formatterType = kCFDateFormatterShortStandaloneWeekdaySymbols;
+ break;
+ case QSystemLocale::StandaloneDayNameNarrow:
+ formatterType = kCFDateFormatterVeryShortStandaloneWeekdaySymbols;
+ break;
+ default:
+ qWarning("macDayName: Unsupported query type %d", type);
+ return {};
+ }
+ QCFType<CFArrayRef> values =
+ static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, formatterType));
+
if (values != 0) {
CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7));
return QString::fromCFString(cfstring);
}
- return QString();
+ return {};
}
-static QString macDateToString(QDate date, bool short_format)
+static QString macZeroDigit()
{
- QCFType<CFDateRef> myDate = QDateTime(date, QTime()).toCFDate();
+ static QString cachedZeroDigit;
+
+ if (cachedZeroDigit.isNull()) {
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ QCFType<CFNumberFormatterRef> numberFormatter =
+ CFNumberFormatterCreate(nullptr, locale, kCFNumberFormatterNoStyle);
+ const int zeroDigit = 0;
+ QCFType<CFStringRef> value
+ = CFNumberFormatterCreateStringWithValue(nullptr, numberFormatter,
+ kCFNumberIntType, &zeroDigit);
+ cachedZeroDigit = QString::fromCFString(value);
+ }
+
+ static QMacNotificationObserver localeChangeObserver = QMacNotificationObserver(
+ nil, NSCurrentLocaleDidChangeNotification, [&] {
+ qCDebug(lcLocale) << "System locale changed";
+ cachedZeroDigit = QString();
+ });
+
+ return cachedZeroDigit;
+}
+
+static QString zeroPad(QString &&number, qsizetype minDigits, const QString &zero)
+{
+ // Need to pad with zeros, possibly after a sign.
+ qsizetype insert = -1, digits = 0;
+ auto it = QStringIterator(number);
+ while (it.hasNext()) {
+ qsizetype here = it.index();
+ if (QChar::isDigit(it.next())) {
+ if (insert < 0)
+ insert = here;
+ ++digits;
+ } // else: assume we're stepping over a sign (or maybe grouping separator)
+ }
+ Q_ASSERT(digits > 0);
+ Q_ASSERT(insert >= 0);
+ while (digits++ < minDigits)
+ number.insert(insert, zero);
+
+ return std::move(number);
+}
+
+static QString trimTwoDigits(QString &&number)
+{
+ // Retain any sign, but remove all but the last two digits.
+ // We know number has at least four digits - it came from fourDigitYear().
+ // Note that each digit might be a surrogate pair.
+ qsizetype first = -1, prev = -1, last = -1;
+ auto it = QStringIterator(number);
+ while (it.hasNext()) {
+ qsizetype here = it.index();
+ if (QChar::isDigit(it.next())) {
+ if (first == -1)
+ last = first = here;
+ else if (last != -1)
+ prev = std::exchange(last, here);
+ }
+ }
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(prev > first);
+ Q_ASSERT(last > prev);
+ number.remove(first, prev - first);
+ return std::move(number);
+}
+
+static QString fourDigitYear(int year, const QString &zero)
+{
+ // Return year formatted as an (at least) four digit number:
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ QCFType<CFNumberFormatterRef> numberFormatter =
+ CFNumberFormatterCreate(nullptr, locale, kCFNumberFormatterNoStyle);
+ QCFType<CFStringRef> value = CFNumberFormatterCreateStringWithValue(nullptr, numberFormatter,
+ kCFNumberIntType, &year);
+ auto text = QString::fromCFString(value);
+ if (year > -1000 && year < 1000)
+ text = zeroPad(std::move(text), 4, zero);
+ return text;
+}
+
+static QString macDateToStringImpl(QDate date, CFDateFormatterStyle style)
+{
+ // Use noon on the given date, to avoid complications that can arise for
+ // dates before 1900 (see QTBUG-54955) using different UTC offset than
+ // QDateTime extrapolates backwards from time_t functions that only work
+ // back to 1900. (Alaska and Phillipines may still be borked, though.)
+ QCFType<CFDateRef> myDate = QDateTime(date, QTime(12, 0)).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
- CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
QCFType<CFDateFormatterRef> myFormatter
- = CFDateFormatterCreate(kCFAllocatorDefault,
- mylocale, style,
+ = CFDateFormatterCreate(kCFAllocatorDefault, mylocale, style,
kCFDateFormatterNoStyle);
- return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
+ QCFType<CFStringRef> text = CFDateFormatterCreateStringWithDate(nullptr, myFormatter, myDate);
+ return QString::fromCFString(text);
}
-static QString macTimeToString(QTime time, bool short_format)
+static QVariant macDateToString(QDate date, bool short_format)
+{
+ const int year = date.year();
+ QString fakeYear, trueYear;
+ if (year < 1583) {
+ // System API (in macOS 11.0, at least) discards sign :-(
+ // Simply negating the year won't do as the resulting year typically has
+ // a different pattern of week-days.
+ // Furthermore (see QTBUG-54955), Darwin uses the Julian calendar for
+ // dates before 1582-10-15, leading to discrepancies.
+ int matcher = QGregorianCalendar::yearSharingWeekDays(date);
+ Q_ASSERT(matcher >= 1583);
+ Q_ASSERT(matcher % 100 != date.month());
+ Q_ASSERT(matcher % 100 != date.day());
+ // i.e. there can't be any confusion between the two-digit year and
+ // month or day-of-month in the formatted date.
+ QString zero = macZeroDigit();
+ fakeYear = fourDigitYear(matcher, zero);
+ trueYear = fourDigitYear(year, zero);
+ date = QDate(matcher, date.month(), date.day());
+ }
+ QString text = macDateToStringImpl(date, short_format
+ ? kCFDateFormatterShortStyle
+ : kCFDateFormatterLongStyle);
+ if (year < 1583) {
+ if (text.contains(fakeYear))
+ return std::move(text).replace(fakeYear, trueYear);
+ // Cope with two-digit year:
+ fakeYear = trimTwoDigits(std::move(fakeYear));
+ trueYear = trimTwoDigits(std::move(trueYear));
+ if (text.contains(fakeYear))
+ return std::move(text).replace(fakeYear, trueYear);
+ // That should have worked.
+ qWarning("Failed to fix up year when formatting a date in year %d", year);
+ }
+ return text;
+}
+
+static QVariant macTimeToString(QTime time, bool short_format)
{
QCFType<CFDateRef> myDate = QDateTime(QDate::currentDate(), time).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
@@ -140,7 +298,8 @@ static QString macTimeToString(QTime time, bool short_format)
mylocale,
kCFDateFormatterNoStyle,
style);
- return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
+ QCFType<CFStringRef> text = CFDateFormatterCreateStringWithDate(0, myFormatter, myDate);
+ return QString::fromCFString(text);
}
// Mac uses the Unicode CLDR format codes
@@ -148,126 +307,132 @@ static QString macTimeToString(QTime time, bool short_format)
// See also qtbase/util/locale_database/dateconverter.py
// Makes the assumption that input formats are always well formed and consecutive letters
// never exceed the maximum for the format code.
-static QString macToQtFormat(QStringView sys_fmt)
+static QVariant macToQtFormat(QStringView sys_fmt)
{
QString result;
- int i = 0;
+ qsizetype i = 0;
while (i < sys_fmt.size()) {
if (sys_fmt.at(i).unicode() == '\'') {
QString text = qt_readEscapedFormatString(sys_fmt, &i);
- if (text == QLatin1String("'"))
- result += QLatin1String("''");
+ if (text == "'"_L1)
+ result += "''"_L1;
else
- result += QLatin1Char('\'') + text + QLatin1Char('\'');
+ result += u'\'' + text + u'\'';
continue;
}
QChar c = sys_fmt.at(i);
- int repeat = qt_repeatCount(sys_fmt.mid(i));
+ qsizetype repeat = qt_repeatCount(sys_fmt.sliced(i));
switch (c.unicode()) {
// Qt does not support the following options
- case 'G': // Era (1..5): 4 = long, 1..3 = short, 5 = narrow
- case 'Y': // Year of Week (1..n): 1..n = padded number
- case 'U': // Cyclic Year Name (1..5): 4 = long, 1..3 = short, 5 = narrow
- case 'Q': // Quarter (1..4): 4 = long, 3 = short, 1..2 = padded number
- case 'q': // Standalone Quarter (1..4): 4 = long, 3 = short, 1..2 = padded number
- case 'w': // Week of Year (1..2): 1..2 = padded number
- case 'W': // Week of Month (1): 1 = number
- case 'D': // Day of Year (1..3): 1..3 = padded number
- case 'F': // Day of Week in Month (1): 1 = number
- case 'g': // Modified Julian Day (1..n): 1..n = padded number
- case 'A': // Milliseconds in Day (1..n): 1..n = padded number
- break;
-
- case 'y': // Year (1..n): 2 = short year, 1 & 3..n = padded number
- case 'u': // Extended Year (1..n): 2 = short year, 1 & 3..n = padded number
- // Qt only supports long (4) or short (2) year, use long for all others
- if (repeat == 2)
- result += QLatin1String("yy");
- else
- result += QLatin1String("yyyy");
- break;
- case 'M': // Month (1..5): 4 = long, 3 = short, 1..2 = number, 5 = narrow
- case 'L': // Standalone Month (1..5): 4 = long, 3 = short, 1..2 = number, 5 = narrow
- // Qt only supports long, short and number, use short for narrow
- if (repeat == 5)
- result += QLatin1String("MMM");
- else
- result += QString(repeat, QLatin1Char('M'));
- break;
- case 'd': // Day of Month (1..2): 1..2 padded number
- result += QString(repeat, c);
- break;
- case 'E': // Day of Week (1..6): 4 = long, 1..3 = short, 5..6 = narrow
- // Qt only supports long, short and padded number, use short for narrow
- if (repeat == 4)
- result += QLatin1String("dddd");
- else
- result += QLatin1String("ddd");
- break;
- case 'e': // Local Day of Week (1..6): 4 = long, 3 = short, 5..6 = narrow, 1..2 padded number
- case 'c': // Standalone Local Day of Week (1..6): 4 = long, 3 = short, 5..6 = narrow, 1..2 padded number
- // Qt only supports long, short and padded number, use short for narrow
- if (repeat >= 5)
- result += QLatin1String("ddd");
- else
- result += QString(repeat, QLatin1Char('d'));
- break;
- case 'a': // AM/PM (1): 1 = short
- // Translate to Qt uppercase AM/PM
- result += QLatin1String("AP");
- break;
- case 'h': // Hour [1..12] (1..2): 1..2 = padded number
- case 'K': // Hour [0..11] (1..2): 1..2 = padded number
- case 'j': // Local Hour [12 or 24] (1..2): 1..2 = padded number
- // Qt h is local hour
- result += QString(repeat, QLatin1Char('h'));
- break;
- case 'H': // Hour [0..23] (1..2): 1..2 = padded number
- case 'k': // Hour [1..24] (1..2): 1..2 = padded number
- // Qt H is 0..23 hour
- result += QString(repeat, QLatin1Char('H'));
- break;
- case 'm': // Minutes (1..2): 1..2 = padded number
- case 's': // Seconds (1..2): 1..2 = padded number
+ case 'A': // Milliseconds in Day (1..n): 1..n = padded number
+ case 'C': // Input skeleton symbol.
+ case 'D': // Day of Year (1..3): 1..3 = padded number
+ case 'F': // Day of Week in Month (1): 1 = number
+ case 'g': // Modified Julian Day (1..n): 1..n = padded number
+ case 'G': // Era (1..5): 4 = long, 1..3 = short, 5 = narrow
+ case 'j': // Input skeleton symbol.
+ case 'J': // Input skeleton symbol.
+ case 'l': // Deprecated Chinese leap month indicator.
+ case 'q': // Standalone Quarter (1..4): 4 = long, 3 = short, 1,2 = padded number
+ case 'Q': // Quarter (1..4): 4 = long, 3 = short, 1,2 = padded number
+ case 'U': // Cyclic Year Name (1..5): 4 = long, 1..3 = short, 5 = narrow
+ case 'w': // Week of Year (1,2): 1,2 = padded number
+ case 'W': // Week of Month (1): 1 = number
+ case 'Y': // Year for Week-of-year calendars (1..n): 1..n = padded number
+ break;
+
+ case 'u': // Extended Year (1..n), padded number.
+ // Explicitly has no special case for 'uu' as only the last two digits.
+ result += "yyyy"_L1;
+ break;
+ case 'y': // Year (1..n): 2 = short year, 1 & 3..n = padded number
+ // Qt only supports long (4) or short (2) year, use long for all others
+ if (repeat == 2)
+ result += "yy"_L1;
+ else
+ result += "yyyy"_L1;
+ break;
+ case 'L': // Standalone Month (1..5): 4 = long, 3 = short, 1,2 = number, 5 = narrow
+ case 'M': // Month (1..5): 4 = long, 3 = short, 1,2 = number, 5 = narrow
+ // Qt only supports long, short and number, use short for narrow
+ if (repeat == 5)
+ result += "MMM"_L1;
+ else
+ result += QString(repeat, u'M');
+ break;
+ case 'd': // Day of Month (1,2): 1,2 padded number
+ result += QString(repeat, c);
+ break;
+ case 'c': // Standalone version of 'e'
+ case 'e': // Local Day of Week (1..6): 4 = long, 3 = short, 5,6 = narrow, 1,2 padded number
+ // "Local" only affects numeric form: depends on locale's start-day of the week.
+ case 'E': // Day of Week (1..6): 4 = long, 1..3 = short, 5,6 = narrow
+ // Qt only supports long, short: use short for narrow and padded number.
+ if (repeat == 4)
+ result += "dddd"_L1;
+ else
+ result += "ddd"_L1;
+ break;
+ case 'a': // AM/PM (1..n): Qt supports no distinctions
+ case 'b': // Like a, but also distinguishing noon, midnight (ignore difference).
+ case 'B': // Flexible day period (at night, &c.)
+ // Translate to Qt AM/PM, using locale-appropriate case:
+ result += "Ap"_L1;
+ break;
+ case 'h': // Hour [1..12] (1,2): 1,2 = padded number
+ case 'K': // Hour [0..11] (1,2): 1,2 = padded number
+ result += QString(repeat, 'h'_L1);
+ break;
+ case 'H': // Hour [0..23] (1,2): 1,2 = padded number
+ case 'k': // Hour [1..24] (1,2): 1,2 = padded number
+ // Qt H is 0..23 hour
+ result += QString(repeat, 'H'_L1);
+ break;
+ case 'm': // Minutes (1,2): 1,2 = padded number
+ case 's': // Seconds (1,2): 1,2 = padded number
+ result += QString(repeat, c);
+ break;
+ case 'S': // Fractional second (1..n): 1..n = truncates to decimal places
+ // Qt uses msecs either unpadded or padded to 3 places
+ if (repeat < 3)
+ result += u'z';
+ else
+ result += "zzz"_L1;
+ break;
+ case 'O': // Time Zone (1, 4)
+ result += u't';
+ break;
+ case 'v': // Time Zone (1, 4)
+ case 'V': // Time Zone (1..4)
+ result += "tttt"_L1;
+ break;
+ case 'x': // Time Zone (1..5)
+ case 'X': // Time Zone (1..5)
+ result += (repeat > 1 && (repeat & 1)) ? "ttt"_L1 : "tt"_L1;
+ break;
+ case 'z': // Time Zone (1..4)
+ case 'Z': // Time Zone (1..5)
+ result += repeat < 4 ? "tt"_L1 : repeat > 4 ? "ttt"_L1 : "t"_L1;
+ break;
+ default:
+ // a..z and A..Z are reserved for format codes, so any occurrence of these not
+ // already processed are not known and so unsupported formats to be ignored.
+ // All other chars are allowed as literals.
+ if (c < u'A' || c > u'z' || (c > u'Z' && c < u'a'))
result += QString(repeat, c);
- break;
- case 'S': // Fractional second (1..n): 1..n = truncates to decimal places
- // Qt uses msecs either unpadded or padded to 3 places
- if (repeat < 3)
- result += QLatin1Char('z');
- else
- result += QLatin1String("zzz");
- break;
- case 'z': // Time Zone (1..4)
- case 'Z': // Time Zone (1..5)
- case 'O': // Time Zone (1, 4)
- case 'v': // Time Zone (1, 4)
- case 'V': // Time Zone (1..4)
- case 'X': // Time Zone (1..5)
- case 'x': // Time Zone (1..5)
- result += QLatin1Char('t');
- break;
- default:
- // a..z and A..Z are reserved for format codes, so any occurrence of these not
- // already processed are not known and so unsupported formats to be ignored.
- // All other chars are allowed as literals.
- if (c < QLatin1Char('A') || c > QLatin1Char('z') ||
- (c > QLatin1Char('Z') && c < QLatin1Char('a'))) {
- result += QString(repeat, c);
- }
- break;
+ break;
}
i += repeat;
}
- return result;
+ return !result.isEmpty() ? QVariant::fromValue(result) : QVariant();
}
-QString getMacDateFormat(CFDateFormatterStyle style)
+static QVariant getMacDateFormat(CFDateFormatterStyle style)
{
QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
@@ -275,7 +440,7 @@ QString getMacDateFormat(CFDateFormatterStyle style)
return macToQtFormat(QString::fromCFString(CFDateFormatterGetFormat(formatter)));
}
-static QString getMacTimeFormat(CFDateFormatterStyle style)
+static QVariant getMacTimeFormat(CFDateFormatterStyle style)
{
QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
@@ -292,11 +457,11 @@ static QVariant getCFLocaleValue(CFStringRef key)
return QString::fromCFString(CFStringRef(static_cast<CFTypeRef>(value)));
}
-static QLocale::MeasurementSystem macMeasurementSystem()
+static QVariant macMeasurementSystem()
{
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
CFStringRef system = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleMeasurementSystem));
- if (QString::fromCFString(system) == QLatin1String("Metric")) {
+ if (QString::fromCFString(system) == "Metric"_L1) {
return QLocale::MetricSystem;
} else {
return QLocale::ImperialSystem;
@@ -313,7 +478,7 @@ static quint8 macFirstDayOfWeek()
return day;
}
-static QString macCurrencySymbol(QLocale::CurrencySymbolFormat format)
+static QVariant macCurrencySymbol(QLocale::CurrencySymbolFormat format)
{
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
switch (format) {
@@ -329,44 +494,33 @@ static QString macCurrencySymbol(QLocale::CurrencySymbolFormat format)
default:
break;
}
- return QString();
-}
-
-static QString macZeroDigit()
-{
- QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
- QCFType<CFNumberFormatterRef> numberFormatter =
- CFNumberFormatterCreate(nullptr, locale, kCFNumberFormatterNoStyle);
- static const int zeroDigit = 0;
- QCFType<CFStringRef> value = CFNumberFormatterCreateStringWithValue(nullptr, numberFormatter,
- kCFNumberIntType, &zeroDigit);
- return QString::fromCFString(value);
+ return {};
}
#ifndef QT_NO_SYSTEMLOCALE
-static QString macFormatCurrency(const QSystemLocale::CurrencyToStringArgument &arg)
+static QVariant macFormatCurrency(const QSystemLocale::CurrencyToStringArgument &arg)
{
QCFType<CFNumberRef> value;
- switch (arg.value.type()) {
- case QVariant::Int:
- case QVariant::UInt: {
+ switch (arg.value.metaType().id()) {
+ case QMetaType::Int:
+ case QMetaType::UInt: {
int v = arg.value.toInt();
value = CFNumberCreate(NULL, kCFNumberIntType, &v);
break;
}
- case QVariant::Double: {
+ case QMetaType::Double: {
double v = arg.value.toDouble();
value = CFNumberCreate(NULL, kCFNumberDoubleType, &v);
break;
}
- case QVariant::LongLong:
- case QVariant::ULongLong: {
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong: {
qint64 v = arg.value.toLongLong();
value = CFNumberCreate(NULL, kCFNumberLongLongType, &v);
break;
}
default:
- return QString();
+ return {};
}
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
@@ -402,17 +556,42 @@ static QVariant macQuoteString(QSystemLocale::QueryType type, QStringView str)
#ifndef QT_NO_SYSTEMLOCALE
-QLocale QSystemLocale::fallbackUiLocale() const
+QLocale QSystemLocale::fallbackLocale() const
{
return QLocale(getMacLocaleName());
}
-QVariant QSystemLocale::query(QueryType type, QVariant in) const
+template <auto CodeToValueFunction>
+static QVariant getLocaleValue(CFStringRef key)
+{
+ if (auto code = getCFLocaleValue(key); !code.isNull()) {
+ // If an invalid locale is requested with -AppleLocale, the system APIs
+ // will report invalid or empty locale values back to us, which codeToLanguage()
+ // and friends will fail to parse, resulting in returning QLocale::Any{L/C/S}.
+ // If this is the case, we fall down and return a null-variant, which
+ // QLocale's updateSystemPrivate() will interpret to use fallback logic.
+ if (auto value = CodeToValueFunction(code.toString()))
+ return value;
+ }
+ return QVariant();
+}
+
+static QLocale::Language codeToLanguage(QStringView s)
+{
+ return QLocalePrivate::codeToLanguage(s);
+}
+
+QVariant QSystemLocale::query(QueryType type, QVariant &&in) const
{
QMacAutoReleasePool pool;
+
switch(type) {
-// case Name:
-// return getMacLocaleName();
+ case LanguageId:
+ return getLocaleValue<codeToLanguage>(kCFLocaleLanguageCode);
+ case TerritoryId:
+ return getLocaleValue<QLocalePrivate::codeToTerritory>(kCFLocaleCountryCode);
+ case ScriptId:
+ return getLocaleValue<QLocalePrivate::codeToScript>(kCFLocaleScriptCode);
case DecimalPoint:
return getCFLocaleValue(kCFLocaleDecimalSeparator);
case GroupSeparator:
@@ -429,12 +608,18 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
: kCFDateFormatterLongStyle);
case DayNameLong:
case DayNameShort:
- return macDayName(in.toInt(), (type == DayNameShort));
+ case DayNameNarrow:
+ case StandaloneDayNameLong:
+ case StandaloneDayNameShort:
+ case StandaloneDayNameNarrow:
+ return macDayName(in.toInt(), type);
case MonthNameLong:
case MonthNameShort:
+ case MonthNameNarrow:
case StandaloneMonthNameLong:
case StandaloneMonthNameShort:
- return macMonthName(in.toInt(), (type == MonthNameShort || type == StandaloneMonthNameShort));
+ case StandaloneMonthNameNarrow:
+ return macMonthName(in.toInt(), type);
case DateToStringShort:
case DateToStringLong:
return macDateToString(in.toDate(), (type == DateToStringShort));
@@ -446,10 +631,10 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
case PositiveSign:
break;
case ZeroDigit:
- return QVariant(macZeroDigit());
+ return macZeroDigit();
case MeasurementSystem:
- return QVariant(static_cast<int>(macMeasurementSystem()));
+ return macMeasurementSystem();
case AMText:
case PMText: {
@@ -462,33 +647,18 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
case FirstDayOfWeek:
return QVariant(macFirstDayOfWeek());
case CurrencySymbol:
- return QVariant(macCurrencySymbol(QLocale::CurrencySymbolFormat(in.toUInt())));
+ return macCurrencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
case CurrencyToString:
- return macFormatCurrency(in.value<QSystemLocale::CurrencyToStringArgument>());
+ return macFormatCurrency(in.value<CurrencyToStringArgument>());
case UILanguages: {
- QCFType<CFPropertyListRef> languages = CFPreferencesCopyValue(
- CFSTR("AppleLanguages"),
- kCFPreferencesAnyApplication,
- kCFPreferencesCurrentUser,
- kCFPreferencesAnyHost);
QStringList result;
- if (!languages)
- return QVariant(result);
-
- CFTypeID typeId = CFGetTypeID(languages);
- if (typeId == CFArrayGetTypeID()) {
- const int cnt = CFArrayGetCount(languages.as<CFArrayRef>());
- result.reserve(cnt);
- for (int i = 0; i < cnt; ++i) {
- const QString lang = QString::fromCFString(
- static_cast<CFStringRef>(CFArrayGetValueAtIndex(languages.as<CFArrayRef>(), i)));
- result.append(lang);
- }
- } else if (typeId == CFStringGetTypeID()) {
- result = QStringList(QString::fromCFString(languages.as<CFStringRef>()));
- } else {
- qWarning("QLocale::uiLanguages(): CFPreferencesCopyValue returned unhandled type \"%ls\"; please report to http://bugreports.qt.io",
- qUtf16Printable(QString::fromCFString(CFCopyTypeIDDescription(typeId))));
+ QCFType<CFArrayRef> languages = CFLocaleCopyPreferredLanguages();
+ const CFIndex cnt = CFArrayGetCount(languages);
+ result.reserve(cnt);
+ for (CFIndex i = 0; i < cnt; ++i) {
+ const QString lang = QString::fromCFString(
+ static_cast<CFStringRef>(CFArrayGetValueAtIndex(languages, i)));
+ result.append(lang);
}
return QVariant(result);
}
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h
index b4064d747b..3044d137b9 100644
--- a/src/corelib/text/qlocale_p.h
+++ b/src/corelib/text/qlocale_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOCALE_P_H
#define QLOCALE_P_H
@@ -52,24 +16,98 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-#include "QtCore/qstring.h"
-#include "QtCore/qvarlengtharray.h"
-#include "QtCore/qvariant.h"
-#include "QtCore/qnumeric.h"
-#include <QtCore/qcalendar.h>
-
#include "qlocale.h"
+#include <QtCore/qcalendar.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/private/qnumeric_p.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qvarlengtharray.h>
+#ifdef Q_OS_WASM
+#include <private/qstdweb_p.h>
+#endif
+
#include <limits>
#include <cmath>
+#include <string_view>
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_SYSTEMLOCALE
+template <typename T> struct QSimpleParsedNumber
+{
+ T result;
+ // When used < 0, -used is how much was used, but it was an error.
+ qsizetype used;
+ bool ok() const { return used > 0; }
+};
+
+template <typename MaskType, uchar Lowest> struct QCharacterSetMatch
+{
+ static constexpr int MaxRange = std::numeric_limits<MaskType>::digits;
+ MaskType mask;
+
+ constexpr QCharacterSetMatch(std::string_view set)
+ : mask(0)
+ {
+ for (char c : set) {
+ int idx = uchar(c) - Lowest;
+ mask |= MaskType(1) << idx;
+ }
+ }
+
+ constexpr bool matches(uchar c) const
+ {
+ unsigned idx = c - Lowest;
+ if (idx >= MaxRange)
+ return false;
+ return (mask >> idx) & 1;
+ }
+};
+
+namespace QtPrivate {
+inline constexpr char ascii_space_chars[] =
+ "\t" // 9: HT - horizontal tab
+ "\n" // 10: LF - line feed
+ "\v" // 11: VT - vertical tab
+ "\f" // 12: FF - form feed
+ "\r" // 13: CR - carriage return
+ " "; // 32: space
+
+template <const char *Set, int ForcedLowest = -1>
+inline constexpr auto makeCharacterSetMatch()
+{
+ constexpr auto view = std::string_view(Set);
+ constexpr uchar MinElement = *std::min_element(view.begin(), view.end());
+ constexpr uchar MaxElement = *std::max_element(view.begin(), view.end());
+ constexpr int Range = MaxElement - MinElement;
+ static_assert(Range < 64, "Characters in the set are 64 or more values apart");
+
+ if constexpr (ForcedLowest >= 0) {
+ // use the force
+ static_assert(ForcedLowest <= int(MinElement), "The force is not with you");
+ using MaskType = std::conditional_t<MaxElement - ForcedLowest < 32, quint32, quint64>;
+ return QCharacterSetMatch<MaskType, ForcedLowest>(view);
+ } else if constexpr (MaxElement < std::numeric_limits<qregisteruint>::digits) {
+ // if we can use a Lowest of zero, we can remove a subtraction
+ // from the matches() code at runtime
+ using MaskType = std::conditional_t<(MaxElement < 32), quint32, qregisteruint>;
+ return QCharacterSetMatch<MaskType, 0>(view);
+ } else {
+ using MaskType = std::conditional_t<(Range < 32), quint32, quint64>;
+ return QCharacterSetMatch<MaskType, MinElement>(view);
+ }
+}
+} // QtPrivate
+
struct QLocaleData;
+// Subclassed by Android platform plugin:
class Q_CORE_EXPORT QSystemLocale
{
+ Q_DISABLE_COPY_MOVE(QSystemLocale)
+ QSystemLocale *next = nullptr; // Maintains a stack.
+
public:
QSystemLocale();
virtual ~QSystemLocale();
@@ -85,7 +123,7 @@ public:
enum QueryType {
LanguageId, // uint
- CountryId, // uint
+ TerritoryId, // uint
DecimalPoint, // QString
GroupSeparator, // QString (empty QString means: don't group digits)
ZeroDigit, // QString
@@ -96,8 +134,10 @@ public:
TimeFormatShort, // QString
DayNameLong, // QString, in: int
DayNameShort, // QString, in: int
+ DayNameNarrow, // QString, in: int
MonthNameLong, // QString, in: int
MonthNameShort, // QString, in: int
+ MonthNameNarrow, // QString, in: int
DateToStringLong, // QString, in: QDate
DateToStringShort, // QString in: QDate
TimeToStringLong, // QString in: QTime
@@ -122,21 +162,21 @@ public:
ListToSeparatedString, // QString
LocaleChanged, // system locale changed
NativeLanguageName, // QString
- NativeCountryName, // QString
+ NativeTerritoryName, // QString
StandaloneMonthNameLong, // QString, in: int
- StandaloneMonthNameShort // QString, in: int
+ StandaloneMonthNameShort, // QString, in: int
+ StandaloneMonthNameNarrow, // QString, in: int
+ StandaloneDayNameLong, // QString, in: int
+ StandaloneDayNameShort, // QString, in: int
+ StandaloneDayNameNarrow // QString, in: int
};
- virtual QVariant query(QueryType type, QVariant in) const;
- virtual QLocale fallbackUiLocale() const;
+ virtual QVariant query(QueryType type, QVariant &&in = QVariant()) const;
- inline const QLocaleData *fallbackUiLocaleData() const;
-private:
- QSystemLocale(bool);
- friend class QSystemLocaleSingleton;
+ virtual QLocale fallbackLocale() const;
+ inline qsizetype fallbackLocaleIndex() const;
};
Q_DECLARE_TYPEINFO(QSystemLocale::QueryType, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(QSystemLocale::CurrencyToStringArgument, Q_MOVABLE_TYPE);
-#endif
+Q_DECLARE_TYPEINFO(QSystemLocale::CurrencyToStringArgument, Q_RELOCATABLE_TYPE);
#if QT_CONFIG(icu)
namespace QIcu {
@@ -148,50 +188,64 @@ namespace QIcu {
struct QLocaleId
{
- // bypass constructors
- static inline QLocaleId fromIds(ushort language, ushort script, ushort country)
+ [[nodiscard]] Q_AUTOTEST_EXPORT static QLocaleId fromName(QStringView name);
+ [[nodiscard]] inline bool operator==(QLocaleId other) const
+ { return language_id == other.language_id && script_id == other.script_id && territory_id == other.territory_id; }
+ [[nodiscard]] inline bool operator!=(QLocaleId other) const
+ { return !operator==(other); }
+ [[nodiscard]] inline bool isValid() const
{
- const QLocaleId localeId = { language, script, country };
- return localeId;
+ return language_id <= QLocale::LastLanguage && script_id <= QLocale::LastScript
+ && territory_id <= QLocale::LastTerritory;
+ }
+ [[nodiscard]] inline bool matchesAll() const
+ {
+ return !language_id && !script_id && !territory_id;
+ }
+ // Use as: filter.accept...(candidate)
+ [[nodiscard]] inline bool acceptLanguage(quint16 lang) const
+ {
+ // Always reject AnyLanguage (only used for last entry in locale_data array).
+ // So, when searching for AnyLanguage, accept everything *but* AnyLanguage.
+ return language_id ? lang == language_id : lang;
+ }
+ [[nodiscard]] inline bool acceptScriptTerritory(QLocaleId other) const
+ {
+ return (!territory_id || other.territory_id == territory_id)
+ && (!script_id || other.script_id == script_id);
}
- inline bool operator==(QLocaleId other) const
- { return language_id == other.language_id && script_id == other.script_id && country_id == other.country_id; }
- inline bool operator!=(QLocaleId other) const
- { return !operator==(other); }
-
- QLocaleId withLikelySubtagsAdded() const;
- QLocaleId withLikelySubtagsRemoved() const;
+ [[nodiscard]] QLocaleId withLikelySubtagsAdded() const;
+ [[nodiscard]] QLocaleId withLikelySubtagsRemoved() const;
- QByteArray name(char separator = '-') const;
+ [[nodiscard]] QByteArray name(char separator = '-') const;
- ushort language_id, script_id, country_id;
+ ushort language_id = 0, script_id = 0, territory_id = 0;
};
Q_DECLARE_TYPEINFO(QLocaleId, Q_PRIMITIVE_TYPE);
+
+using CharBuff = QVarLengthArray<char, 256>;
+
+struct ParsingResult
+{
+ enum State { // A duplicate of QValidator::State
+ Invalid,
+ Intermediate,
+ Acceptable
+ };
+
+ State state = Invalid;
+ CharBuff buff;
+};
+
struct QLocaleData
{
public:
- // TODO: Remove this?
- static const QLocaleData *findLocaleData(QLocale::Language language,
- QLocale::Script script,
- QLocale::Country country);
- // Having an offset of current locale, enables us to have multiple sources of data, i.e. user-provided calendar locales
- static uint findLocaleOffset(QLocale::Language language,
- QLocale::Script script,
- QLocale::Country country);
- static const QLocaleData *c();
-
- // Maximum number of significant digits needed to represent a double.
- // We cannot use std::numeric_limits here without constexpr.
- static const int DoubleMantissaBits = 53;
- static const int Log10_2_100000 = 30103; // log10(2) * 100000
- // same as C++11 std::numeric_limits<T>::max_digits10
- static const int DoubleMaxSignificant = (DoubleMantissaBits * Log10_2_100000) / 100000 + 2;
-
- // Maximum number of digits before decimal point to represent a double
- // Same as std::numeric_limits<double>::max_exponent10 + 1
- static const int DoubleMaxDigitsBeforeDecimal = 309;
+ // Having an index for each locale enables us to have diverse sources of
+ // data, e.g. calendar locales, as well as the main CLDR-derived data.
+ [[nodiscard]] static qsizetype findLocaleIndex(QLocaleId localeId);
+ [[nodiscard]] static const QLocaleData *c();
enum DoubleForm {
DFExponent = 0,
@@ -207,118 +261,164 @@ public:
LeftAdjusted = 0x04,
BlankBeforePositive = 0x08,
AlwaysShowSign = 0x10,
- ThousandsGroup = 0x20,
+ GroupDigits = 0x20,
CapitalEorX = 0x40,
ShowBase = 0x80,
UppercaseBase = 0x100,
ZeroPadExponent = 0x200,
- ForcePoint = 0x400,
- IndianNumberGrouping= 0x800
+ ForcePoint = 0x400
};
enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode };
- typedef QVarLengthArray<char, 256> CharBuff;
-
- static QString doubleToString(const QString &zero, const QString &plus,
- const QString &minus, const QString &exponent,
- const QString &group, const QString &decimal,
- double d, int precision, DoubleForm form,
- int width, unsigned flags);
- static QString longLongToString(const QString &zero, const QString &group,
- const QString &plus, const QString &minus,
- qint64 l, int precision, int base,
- int width, unsigned flags);
- static QString unsLongLongToString(const QString &zero, const QString &group,
- const QString &plus,
- quint64 l, int precision,
- int base, int width, unsigned flags);
-
- QString doubleToString(double d,
- int precision = -1,
- DoubleForm form = DFSignificantDigits,
- int width = -1,
- unsigned flags = NoFlags) const;
- QString longLongToString(qint64 l, int precision = -1,
- int base = 10,
- int width = -1,
- unsigned flags = NoFlags) const;
- QString unsLongLongToString(quint64 l, int precision = -1,
- int base = 10,
- int width = -1,
- unsigned flags = NoFlags) const;
+private:
+ enum PrecisionMode {
+ PMDecimalDigits = 0x01,
+ PMSignificantDigits = 0x02,
+ PMChopTrailingZeros = 0x03
+ };
+
+ [[nodiscard]] QString decimalForm(QString &&digits, int decpt, int precision,
+ PrecisionMode pm, bool mustMarkDecimal,
+ bool groupDigits) const;
+ [[nodiscard]] QString exponentForm(QString &&digits, int decpt, int precision,
+ PrecisionMode pm, bool mustMarkDecimal,
+ int minExponentDigits) const;
+ [[nodiscard]] QString signPrefix(bool negative, unsigned flags) const;
+ [[nodiscard]] QString applyIntegerFormatting(QString &&numStr, bool negative, int precision,
+ int base, int width, unsigned flags) const;
+
+public:
+ [[nodiscard]] QString doubleToString(double d,
+ int precision = -1,
+ DoubleForm form = DFSignificantDigits,
+ int width = -1,
+ unsigned flags = NoFlags) const;
+ [[nodiscard]] QString longLongToString(qint64 l, int precision = -1,
+ int base = 10,
+ int width = -1,
+ unsigned flags = NoFlags) const;
+ [[nodiscard]] QString unsLongLongToString(quint64 l, int precision = -1,
+ int base = 10,
+ int width = -1,
+ unsigned flags = NoFlags) const;
// this function is meant to be called with the result of stringToDouble or bytearrayToDouble
- static float convertDoubleToFloat(double d, bool *ok)
+ // so *ok must have been properly set (if not null)
+ [[nodiscard]] static float convertDoubleToFloat(double d, bool *ok)
{
- if (qIsInf(d))
- return float(d);
- if (std::fabs(d) > std::numeric_limits<float>::max()) {
- if (ok)
- *ok = false;
- const float huge = std::numeric_limits<float>::infinity();
- return d < 0 ? -huge : huge;
- }
- if (d != 0 && float(d) == 0) {
- // Values that underflow double already failed. Match them:
- if (ok)
- *ok = false;
- return 0;
- }
- return float(d);
+ float result;
+ bool b = convertDoubleTo<float>(d, &result);
+ if (ok && *ok)
+ *ok = b;
+ return result;
}
- double stringToDouble(QStringView str, bool *ok, QLocale::NumberOptions options) const;
- qint64 stringToLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const;
- quint64 stringToUnsLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const;
+ [[nodiscard]] double stringToDouble(QStringView str, bool *ok,
+ QLocale::NumberOptions options) const;
+ [[nodiscard]] QSimpleParsedNumber<qint64>
+ stringToLongLong(QStringView str, int base, QLocale::NumberOptions options) const;
+ [[nodiscard]] QSimpleParsedNumber<quint64>
+ stringToUnsLongLong(QStringView str, int base, QLocale::NumberOptions options) const;
- static double bytearrayToDouble(const char *num, bool *ok);
// this function is used in QIntValidator (QtGui)
- Q_CORE_EXPORT static qint64 bytearrayToLongLong(const char *num, int base, bool *ok);
- static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok);
+ [[nodiscard]] Q_CORE_EXPORT
+ static QSimpleParsedNumber<qint64> bytearrayToLongLong(QByteArrayView num, int base);
+ [[nodiscard]] static QSimpleParsedNumber<quint64>
+ bytearrayToUnsLongLong(QByteArrayView num, int base);
- bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
- CharBuff *result) const;
- inline char numericToCLocale(QStringView in) const;
+ [[nodiscard]] bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
+ NumberMode mode, CharBuff *result) const;
+
+ struct NumericData
+ {
+#ifndef QT_NO_SYSTEMLOCALE
+ // Only used for the system locale, to store data for the view to look at:
+ QString sysDecimal, sysGroup, sysMinus, sysPlus;
+#endif
+ QStringView decimal, group, minus, plus, exponent;
+ char32_t zeroUcs = 0;
+ qint8 zeroLen = 0;
+ bool isC = false; // C locale sets this and nothing else.
+ bool exponentCyrillic = false; // True only for floating-point parsing of Cyrillic.
+ void setZero(QStringView zero)
+ {
+ // No known locale has digits that are more than one Unicode
+ // code-point, so we can safely deal with digits as plain char32_t.
+ switch (zero.size()) {
+ case 1:
+ Q_ASSERT(!zero.at(0).isSurrogate());
+ zeroUcs = zero.at(0).unicode();
+ zeroLen = 1;
+ break;
+ case 2:
+ Q_ASSERT(zero.at(0).isHighSurrogate());
+ zeroUcs = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
+ zeroLen = 2;
+ break;
+ default:
+ Q_ASSERT(zero.size() == 0); // i.e. we got no value to use
+ break;
+ }
+ }
+ [[nodiscard]] bool isValid(NumberMode mode) const // Asserted as a sanity check.
+ {
+ if (isC)
+ return true;
+ if (exponentCyrillic && exponent != u"E" && exponent != u"\u0415")
+ return false;
+ return (zeroLen == 1 || zeroLen == 2) && zeroUcs > 0
+ && (mode == IntegerMode || !decimal.isEmpty())
+ // group may be empty (user config in system locale)
+ && !minus.isEmpty() && !plus.isEmpty()
+ && (mode != DoubleScientificMode || !exponent.isEmpty());
+ }
+ };
+ [[nodiscard]] inline NumericData numericData(NumberMode mode) const;
// this function is used in QIntValidator (QtGui)
- Q_CORE_EXPORT bool validateChars(QStringView str, NumberMode numMode, QByteArray *buff, int decDigits = -1,
- QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const;
-
- QString decimalPoint() const;
- QString groupSeparator() const;
- QString listSeparator() const;
- QString percentSign() const;
- QString zeroDigit() const;
- uint zeroUcs() const;
- QString positiveSign() const;
- QString negativeSign() const;
- QString exponentSeparator() const;
+ [[nodiscard]] Q_CORE_EXPORT ParsingResult
+ validateChars(QStringView str, NumberMode numMode, int decDigits = -1,
+ QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const;
+
+ // Access to assorted data members:
+ [[nodiscard]] QLocaleId id() const
+ { return QLocaleId { m_language_id, m_script_id, m_territory_id }; }
+
+ [[nodiscard]] QString decimalPoint() const;
+ [[nodiscard]] QString groupSeparator() const;
+ [[nodiscard]] QString listSeparator() const;
+ [[nodiscard]] QString percentSign() const;
+ [[nodiscard]] QString zeroDigit() const;
+ [[nodiscard]] char32_t zeroUcs() const;
+ [[nodiscard]] QString positiveSign() const;
+ [[nodiscard]] QString negativeSign() const;
+ [[nodiscard]] QString exponentSeparator() const;
struct DataRange
{
quint16 offset;
quint16 size;
- QString getData(const char16_t *table) const
+ [[nodiscard]] QString getData(const char16_t *table) const
{
return size > 0
? QString::fromRawData(reinterpret_cast<const QChar *>(table + offset), size)
: QString();
}
- QStringView viewData(const char16_t *table) const
+ [[nodiscard]] QStringView viewData(const char16_t *table) const
{
return { reinterpret_cast<const QChar *>(table + offset), size };
}
- QString getListEntry(const char16_t *table, int index) const
+ [[nodiscard]] QString getListEntry(const char16_t *table, qsizetype index) const
{
return listEntry(table, index).getData(table);
}
- QStringView viewListEntry(const char16_t *table, int index) const
+ [[nodiscard]] QStringView viewListEntry(const char16_t *table, qsizetype index) const
{
return listEntry(table, index).viewData(table);
}
- uint ucsFirst(const char16_t *table) const
+ [[nodiscard]] char32_t ucsFirst(const char16_t *table) const
{
if (size && !QChar::isSurrogate(table[offset]))
return table[offset];
@@ -327,7 +427,7 @@ public:
return 0;
}
private:
- DataRange listEntry(const char16_t *table, int index) const
+ [[nodiscard]] DataRange listEntry(const char16_t *table, qsizetype index) const
{
const char16_t separator = ';';
quint16 i = 0;
@@ -355,15 +455,15 @@ public:
X(byteCount) X(byteAmountSI) X(byteAmountIEC) \
X(currencySymbol) X(currencyDisplayName) \
X(currencyFormat) X(currencyFormatNegative) \
- X(endonymLanguage) X(endonymCountry)
+ X(endonymLanguage) X(endonymTerritory)
#define rangeGetter(name) \
- DataRange name() const { return { m_ ## name ## _idx, m_ ## name ## _size }; }
+ [[nodiscard]] DataRange name() const { return { m_ ## name ## _idx, m_ ## name ## _size }; }
ForEachQLocaleRange(rangeGetter)
#undef rangeGetter
public:
- quint16 m_language_id, m_script_id, m_country_id;
+ quint16 m_language_id, m_script_id, m_territory_id;
// Offsets, then sizes, for each range:
#define rangeIndex(name) quint16 m_ ## name ## _idx;
@@ -376,61 +476,66 @@ public:
#undef ForEachQLocaleRange
// Strays:
- char m_currency_iso_code[3];
- quint16 m_currency_digits : 2;
- quint16 m_currency_rounding : 3; // (not yet used !)
- quint16 m_first_day_of_week : 3;
- quint16 m_weekend_start : 3;
- quint16 m_weekend_end : 3;
+ char m_currency_iso_code[3];
+ quint8 m_currency_digits : 2;
+ quint8 m_currency_rounding : 3; // (not yet used !)
+ quint8 m_first_day_of_week : 3;
+ quint8 m_weekend_start : 3;
+ quint8 m_weekend_end : 3;
+ quint8 m_grouping_top : 2; // Don't group until more significant group has this many digits.
+ quint8 m_grouping_higher : 3; // Number of digits between grouping separators
+ quint8 m_grouping_least : 3; // Number of digits after last grouping separator (before decimal).
};
-class Q_CORE_EXPORT QLocalePrivate // A POD type
+class QLocalePrivate
{
public:
- static QLocalePrivate *create(
- const QLocaleData *data, const uint data_offset = 0,
- QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions)
- {
- auto *retval = new QLocalePrivate;
- retval->m_data = data;
- retval->ref.storeRelaxed(0);
- retval->m_data_offset = data_offset;
- retval->m_numberOptions = numberOptions;
- return retval;
- }
-
- static QLocalePrivate *get(QLocale &l) { return l.d; }
- static const QLocalePrivate *get(const QLocale &l) { return l.d; }
+ constexpr QLocalePrivate(const QLocaleData *data, qsizetype index,
+ QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions,
+ int refs = 0)
+ : m_data(data), ref Q_BASIC_ATOMIC_INITIALIZER(refs),
+ m_index(index), m_numberOptions(numberOptions) {}
- quint16 languageId() const { return m_data->m_language_id; }
- quint16 countryId() const { return m_data->m_country_id; }
+ [[nodiscard]] quint16 languageId() const { return m_data->m_language_id; }
+ [[nodiscard]] quint16 territoryId() const { return m_data->m_territory_id; }
- QByteArray bcp47Name(char separator = '-') const;
- QByteArray rawName(char separator = '-') const;
+ [[nodiscard]] QByteArray bcp47Name(char separator = '-') const;
- inline QLatin1String languageCode() const { return languageToCode(QLocale::Language(m_data->m_language_id)); }
- inline QLatin1String scriptCode() const { return scriptToCode(QLocale::Script(m_data->m_script_id)); }
- inline QLatin1String countryCode() const { return countryToCode(QLocale::Country(m_data->m_country_id)); }
-
- static QLatin1String languageToCode(QLocale::Language language);
- static QLatin1String scriptToCode(QLocale::Script script);
- static QLatin1String countryToCode(QLocale::Country country);
- static QLocale::Language codeToLanguage(QStringView code) noexcept;
- static QLocale::Script codeToScript(QStringView code) noexcept;
- static QLocale::Country codeToCountry(QStringView code) noexcept;
- static void getLangAndCountry(const QString &name, QLocale::Language &lang,
- QLocale::Script &script, QLocale::Country &cntry);
-
- QLocale::MeasurementSystem measurementSystem() const;
-
- const QLocaleData *m_data;
+ [[nodiscard]] inline std::array<char, 4>
+ languageCode(QLocale::LanguageCodeTypes codeTypes = QLocale::AnyLanguageCode) const
+ {
+ return languageToCode(QLocale::Language(m_data->m_language_id), codeTypes);
+ }
+ [[nodiscard]] inline QLatin1StringView scriptCode() const
+ { return scriptToCode(QLocale::Script(m_data->m_script_id)); }
+ [[nodiscard]] inline QLatin1StringView territoryCode() const
+ { return territoryToCode(QLocale::Territory(m_data->m_territory_id)); }
+
+ [[nodiscard]] static const QLocalePrivate *get(const QLocale &l) { return l.d; }
+ [[nodiscard]] static std::array<char, 4>
+ languageToCode(QLocale::Language language,
+ QLocale::LanguageCodeTypes codeTypes = QLocale::AnyLanguageCode);
+ [[nodiscard]] static QLatin1StringView scriptToCode(QLocale::Script script);
+ [[nodiscard]] static QLatin1StringView territoryToCode(QLocale::Territory territory);
+ [[nodiscard]] static QLocale::Language
+ codeToLanguage(QStringView code,
+ QLocale::LanguageCodeTypes codeTypes = QLocale::AnyLanguageCode) noexcept;
+ [[nodiscard]] static QLocale::Script codeToScript(QStringView code) noexcept;
+ [[nodiscard]] static QLocale::Territory codeToTerritory(QStringView code) noexcept;
+
+ [[nodiscard]] QLocale::MeasurementSystem measurementSystem() const;
+
+ // System locale has an m_data all its own; all others have m_data = locale_data + m_index
+ const QLocaleData *const m_data;
QBasicAtomicInt ref;
- uint m_data_offset;
+ qsizetype m_index; // System locale needs this updated when m_data->id() changes.
QLocale::NumberOptions m_numberOptions;
+
+ static QBasicAtomicInt s_generation;
};
#ifndef QT_NO_SYSTEMLOCALE
-const QLocaleData *QSystemLocale::fallbackUiLocaleData() const { return fallbackUiLocale().d->m_data; }
+qsizetype QSystemLocale::fallbackLocaleIndex() const { return fallbackLocale().d->m_index; }
#endif
template <>
@@ -438,87 +543,29 @@ inline QLocalePrivate *QSharedDataPointer<QLocalePrivate>::clone()
{
// cannot use QLocalePrivate's copy constructor
// since it is deleted in C++11
- return QLocalePrivate::create(d->m_data, d->m_data_offset, d->m_numberOptions);
+ return new QLocalePrivate(d->m_data, d->m_index, d->m_numberOptions);
}
-inline char QLocaleData::numericToCLocale(QStringView in) const
-{
- Q_ASSERT(in.size() == 1 || (in.size() == 2 && in.at(0).isHighSurrogate()));
-
- if (in == positiveSign() || in == u"+")
- return '+';
-
- if (in == negativeSign() || in == u"-" || in == u"\x2212")
- return '-';
-
- if (in == decimalPoint())
- return '.';
+// Also used to merely skip over an escape in a format string, advancint idx to
+// point after it (so not [[nodiscard]]):
+QString qt_readEscapedFormatString(QStringView format, qsizetype *idx);
+[[nodiscard]] bool qt_splitLocaleName(QStringView name, QStringView *lang = nullptr,
+ QStringView *script = nullptr, QStringView *cntry = nullptr);
+[[nodiscard]] qsizetype qt_repeatCount(QStringView s);
- if (in.compare(exponentSeparator(), Qt::CaseInsensitive) == 0)
- return 'e';
-
- const QString group = groupSeparator();
- if (in == group)
- return ',';
-
- // In several languages group() is a non-breaking space (U+00A0) or its thin
- // version (U+202f), which look like spaces. People (and thus some of our
- // tests) use a regular space instead and complain if it doesn't work.
- // Should this be extended generally to any case where group is a space ?
- if ((group == u"\xa0" || group == u"\x202f") && in == u" ")
- return ',';
-
- const uint zeroUcs4 = zeroUcs();
- const uint tenUcs4 = zeroUcs4 + 10;
- const uint inUcs4 = in.size() == 2
- ? QChar::surrogateToUcs4(in.at(0), in.at(1)) : in.at(0).unicode();
-
- if (zeroUcs4 <= inUcs4 && inUcs4 < tenUcs4)
- return '0' + inUcs4 - zeroUcs4;
-
- if ('0' <= inUcs4 && inUcs4 <= '9')
- return inUcs4;
-
- return 0;
-}
-
-QString qt_readEscapedFormatString(QStringView format, int *idx);
-bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry);
-int qt_repeatCount(QStringView s);
-
-enum { AsciiSpaceMask = (1u << (' ' - 1)) |
- (1u << ('\t' - 1)) | // 9: HT - horizontal tab
- (1u << ('\n' - 1)) | // 10: LF - line feed
- (1u << ('\v' - 1)) | // 11: VT - vertical tab
- (1u << ('\f' - 1)) | // 12: FF - form feed
- (1u << ('\r' - 1)) }; // 13: CR - carriage return
-Q_DECL_CONSTEXPR inline bool ascii_isspace(uchar c)
+[[nodiscard]] constexpr inline bool ascii_isspace(uchar c)
{
- return c >= 1u && c <= 32u && (AsciiSpaceMask >> uint(c - 1)) & 1u;
+ constexpr auto matcher = QtPrivate::makeCharacterSetMatch<QtPrivate::ascii_space_chars>();
+ return matcher.matches(c);
}
-#if defined(Q_COMPILER_CONSTEXPR)
-static_assert(ascii_isspace(' '));
-static_assert(ascii_isspace('\t'));
-static_assert(ascii_isspace('\n'));
-static_assert(ascii_isspace('\v'));
-static_assert(ascii_isspace('\f'));
-static_assert(ascii_isspace('\r'));
-static_assert(!ascii_isspace('\0'));
-static_assert(!ascii_isspace('\a'));
-static_assert(!ascii_isspace('a'));
-static_assert(!ascii_isspace('\177'));
-static_assert(!ascii_isspace(uchar('\200')));
-static_assert(!ascii_isspace(uchar('\xA0')));
-static_assert(!ascii_isspace(uchar('\377')));
-#endif
-
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QStringView)
-Q_DECLARE_METATYPE(QList<Qt::DayOfWeek>)
+// ### move to qnamespace.h
+QT_DECL_METATYPE_EXTERN_TAGGED(QList<Qt::DayOfWeek>, QList_Qt__DayOfWeek, Q_CORE_EXPORT)
#ifndef QT_NO_SYSTEMLOCALE
-Q_DECLARE_METATYPE(QSystemLocale::CurrencyToStringArgument)
+QT_DECL_METATYPE_EXTERN_TAGGED(QSystemLocale::CurrencyToStringArgument,
+ QSystemLocale__CurrencyToStringArgument, Q_CORE_EXPORT)
#endif
#endif // QLOCALE_P_H
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index a1838add72..b6639bcb71 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlocale_tools_p.h"
#include "qdoublescanprint_p.h"
#include "qlocale_p.h"
#include "qstring.h"
+#include <private/qtools_p.h>
#include <private/qnumeric_p.h>
#include <ctype.h>
@@ -53,6 +18,9 @@
#include <stdlib.h>
#include <time.h>
+#include <limits>
+#include <charconv>
+
#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
# include <fenv.h>
#endif
@@ -70,12 +38,12 @@
QT_BEGIN_NAMESPACE
-#include "../../3rdparty/freebsd/strtoull.c"
-#include "../../3rdparty/freebsd/strtoll.c"
+using namespace QtMiscUtils;
QT_CLOCALE_HOLDER
-void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
+void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
+ char *buf, qsizetype bufSize,
bool &sign, int &length, int &decpt)
{
if (bufSize == 0) {
@@ -86,9 +54,10 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
}
// Detect special numbers (nan, +/-inf)
- // We cannot use the high-level API of libdouble-conversion as we need to apply locale-specific
- // formatting, such as decimal points, thousands-separators, etc. Because of this, we have to
- // check for infinity and NaN before calling DoubleToAscii.
+ // We cannot use the high-level API of libdouble-conversion as we need to
+ // apply locale-specific formatting, such as decimal points, grouping
+ // separators, etc. Because of this, we have to check for infinity and NaN
+ // before calling DoubleToAscii.
if (qt_is_inf(d)) {
sign = d < 0;
if (bufSize >= 3) {
@@ -128,7 +97,12 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
} else {
mode = double_conversion::DoubleToStringConverter::FIXED;
}
- double_conversion::DoubleToStringConverter::DoubleToAscii(d, mode, precision, buf, bufSize,
+ // libDoubleConversion is limited to 32-bit lengths. It's ok to cap the buffer size,
+ // though, because the library will never write 2GiB of chars as output
+ // (the length out-parameter is just an int, too).
+ const auto boundedBufferSize = static_cast<int>((std::min)(bufSize, qsizetype(INT_MAX)));
+ double_conversion::DoubleToStringConverter::DoubleToAscii(d, mode, precision, buf,
+ boundedBufferSize,
&sign, &length, &decpt);
#else // QT_NO_DOUBLECONVERSION || QT_BOOTSTRAPPED
@@ -139,7 +113,7 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
if (precision > 999)
precision = 999;
else if (precision == QLocale::FloatingPointShortest)
- precision = QLocaleData::DoubleMaxSignificant; // "shortest" mode not supported by snprintf
+ precision = std::numeric_limits<double>::max_digits10; // snprintf lacks "shortest" mode
if (isZero(d)) {
// Negative zero is expected as simple "0", not "-0". We cannot do d < 0, though.
@@ -167,8 +141,8 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
switch (form) {
case QLocaleData::DFDecimal:
format[formatLength - 2] = 'f';
- // <anything> '.' <precision> '\0' - optimize for numbers smaller than 512k
- extraChars = (d > (1 << 19) ? QLocaleData::DoubleMaxDigitsBeforeDecimal : 6) + 2;
+ // <anything> '.' <precision> '\0'
+ extraChars = wholePartSpace(d) + 2;
break;
case QLocaleData::DFExponent:
format[formatLength - 2] = 'e';
@@ -220,11 +194,10 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
// which case the missing digits are zeroes. In the 'e' case decptInTarget is always 1,
// as variants of snprintf always generate numbers with one digit before the '.' then.
// This is why the final decimal point is offset by 1, relative to the number after 'e'.
- bool ok;
- const char *endptr;
- decpt = qstrtoll(target.data() + eSign + 1, &endptr, 10, &ok) + 1;
- Q_ASSERT(ok);
- Q_ASSERT(endptr - target.data() <= length);
+ auto r = qstrntoll(target.data() + eSign + 1, length - eSign - 1, 10);
+ decpt = r.result + 1;
+ Q_ASSERT(r.ok());
+ Q_ASSERT(r.used + eSign + 1 <= length);
} else {
// No 'e' found, so it's the 'f' form. Variants of snprintf generate numbers with
// potentially multiple digits before the '.', but without decimal exponent then. So we
@@ -277,43 +250,50 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
--length;
}
-double qt_asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
- StrayCharacterMode strayCharMode)
+QSimpleParsedNumber<double> qt_asciiToDouble(const char *num, qsizetype numLen,
+ StrayCharacterMode strayCharMode)
{
- if (*num == '\0') {
- ok = false;
- processed = 0;
- return 0.0;
- }
-
- ok = true;
+ if (numLen <= 0)
+ return {};
// We have to catch NaN before because we need NaN as marker for "garbage" in the
// libdouble-conversion case and, in contrast to libdouble-conversion or sscanf, we don't allow
// "-nan" or "+nan"
- if (qstrcmp(num, "nan") == 0) {
- processed = 3;
- return qt_qnan();
- } else if ((num[0] == '-' || num[0] == '+') && qstrcmp(num + 1, "nan") == 0) {
- processed = 0;
- ok = false;
- return 0.0;
- }
+ if (char c = *num; numLen >= 3
+ && (c == '-' || c == '+' || c == 'I' || c == 'i' || c == 'N' || c == 'n')) {
+ bool negative = (c == '-');
+ bool hasSign = negative || (c == '+');
+ qptrdiff offset = 0;
+ if (hasSign) {
+ offset = 1;
+ c = num[offset];
+ }
- // Infinity values are implementation defined in the sscanf case. In the libdouble-conversion
- // case we need infinity as overflow marker.
- if (qstrcmp(num, "+inf") == 0) {
- processed = 4;
- return qt_inf();
- } else if (qstrcmp(num, "inf") == 0) {
- processed = 3;
- return qt_inf();
- } else if (qstrcmp(num, "-inf") == 0) {
- processed = 4;
- return -qt_inf();
+ if (c > '9') {
+ auto lowered = [](char c) {
+ // this will mangle non-letters, but none can become a letter
+ return c | 0x20;
+ };
+
+ // Found a non-digit, so this MUST be either "inf", "+inf", "-inf"
+ // or "nan". Anything else is an invalid parse and we don't need to
+ // feed it to the converter below.
+ if (numLen != offset + 3)
+ return {};
+
+ c = lowered(c);
+ char c2 = lowered(num[offset + 1]);
+ char c3 = lowered(num[offset + 2]);
+ if (c == 'i' && c2 == 'n' && c3 == 'f')
+ return { negative ? -qt_inf() : qt_inf(), offset + 3 };
+ else if (c == 'n' && c2 == 'a' && c3 == 'n' && !hasSign)
+ return { qt_qnan(), 3 };
+ return {};
+ }
}
double d = 0.0;
+ int processed;
#if !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
int conv_flags = double_conversion::StringToDoubleConverter::NO_FLAGS;
if (strayCharMode == TrailingJunkAllowed) {
@@ -323,44 +303,49 @@ double qt_asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
| double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES;
}
double_conversion::StringToDoubleConverter conv(conv_flags, 0.0, qt_qnan(), nullptr, nullptr);
- d = conv.StringToDouble(num, numLen, &processed);
+ if (int(numLen) != numLen) {
+ // a number over 2 GB in length is silly, just assume it isn't valid
+ return {};
+ } else {
+ d = conv.StringToDouble(num, int(numLen), &processed);
+ }
- if (!qIsFinite(d)) {
- ok = false;
- if (qIsNaN(d)) {
+ if (!qt_is_finite(d)) {
+ if (qt_is_nan(d)) {
// Garbage found. We don't accept it and return 0.
- processed = 0;
- return 0.0;
+ return {};
} else {
// Overflow. That's not OK, but we still return infinity.
- return d;
+ return { d, -processed };
}
}
#else
- if (qDoubleSscanf(num, QT_CLOCALE, "%lf%n", &d, &processed) < 1)
+ // ::digits10 is 19, but ::max() is 18'446'744'073'709'551'615ULL - go, figure...
+ constexpr auto maxDigitsForULongLong = 1 + std::numeric_limits<unsigned long long>::digits10;
+ // need to ensure that we don't read more than numLen of input:
+ char fmt[1 + maxDigitsForULongLong + 4 + 1];
+ qsnprintf(fmt, sizeof fmt, "%s%llu%s", "%", static_cast<unsigned long long>(numLen), "lf%n");
+
+ if (qDoubleSscanf(num, QT_CLOCALE, fmt, &d, &processed) < 1)
processed = 0;
- if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) {
+ if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qt_is_nan(d)) {
// Implementation defined nan symbol or garbage found. We don't accept it.
- processed = 0;
- ok = false;
- return 0.0;
+ return {};
}
- if (!qIsFinite(d)) {
+ if (!qt_is_finite(d)) {
// Overflow. Check for implementation-defined infinity symbols and reject them.
// We assume that any infinity symbol has to contain a character that cannot be part of a
// "normal" number (that is 0-9, ., -, +, e).
- ok = false;
for (int i = 0; i < processed; ++i) {
char c = num[i];
if ((c < '0' || c > '9') && c != '.' && c != '-' && c != '+' && c != 'e' && c != 'E') {
// Garbage found
- processed = 0;
- return 0.0;
+ return {};
}
}
- return d;
+ return { d, -processed };
}
#endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
@@ -372,60 +357,164 @@ double qt_asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
for (int i = 0; i < processed; ++i) {
if (num[i] >= '1' && num[i] <= '9') {
// if a digit before any 'e' is not 0, then a non-zero number was intended.
- ok = false;
- return 0.0;
+ return {d, -processed};
} else if (num[i] == 'e' || num[i] == 'E') {
break;
}
}
}
- return d;
+ return { d, processed };
+}
+
+/* Detect base if 0 and, if base is hex or bin, skip over 0x/0b prefixes */
+static auto scanPrefix(const char *p, const char *stop, int base)
+{
+ struct R
+ {
+ const char *next;
+ int base;
+ };
+ if (p < stop && isAsciiDigit(*p)) {
+ if (*p == '0') {
+ const char *x_or_b = p + 1;
+ if (x_or_b < stop) {
+ switch (*x_or_b) {
+ case 'b':
+ case 'B':
+ if (base == 0)
+ base = 2;
+ if (base == 2)
+ p += 2;
+ return R{p, base};
+ case 'x':
+ case 'X':
+ if (base == 0)
+ base = 16;
+ if (base == 16)
+ p += 2;
+ return R{p, base};
+ }
+ }
+ if (base == 0)
+ base = 8;
+ } else if (base == 0) {
+ base = 10;
+ }
+ Q_ASSERT(base);
+ }
+ return R{p, base};
}
-unsigned long long
-qstrtoull(const char * nptr, const char **endptr, int base, bool *ok)
+static bool isDigitForBase(char d, int base)
{
- // strtoull accepts negative numbers. We don't.
- // Use a different variable so we pass the original nptr to strtoul
- // (we need that so endptr may be nptr in case of failure)
- const char *begin = nptr;
- while (ascii_isspace(*begin))
- ++begin;
- if (*begin == '-') {
- *ok = false;
- return 0;
+ if (d < '0')
+ return false;
+ if (d - '0' < qMin(base, 10))
+ return true;
+ if (base > 10) {
+ d |= 0x20; // tolower
+ return d >= 'a' && d < 'a' + base - 10;
}
+ return false;
+}
- *ok = true;
- errno = 0;
- char *endptr2 = nullptr;
- unsigned long long result = qt_strtoull(nptr, &endptr2, base);
- if (endptr)
- *endptr = endptr2;
- if ((result == 0 || result == std::numeric_limits<unsigned long long>::max())
- && (errno || endptr2 == nptr)) {
- *ok = false;
- return 0;
+QSimpleParsedNumber<qulonglong> qstrntoull(const char *begin, qsizetype size, int base)
+{
+ const char *p = begin, *const stop = begin + size;
+ while (p < stop && ascii_isspace(*p))
+ ++p;
+ unsigned long long result = 0;
+ if (p >= stop || *p == '-')
+ return { };
+ const auto prefix = scanPrefix(*p == '+' ? p + 1 : p, stop, base);
+ if (!prefix.base || prefix.next >= stop)
+ return { };
+
+ const auto res = std::from_chars(prefix.next, stop, result, prefix.base);
+ if (res.ec != std::errc{})
+ return { };
+ return { result, res.ptr == prefix.next ? 0 : res.ptr - begin };
+}
+
+QSimpleParsedNumber<qlonglong> qstrntoll(const char *begin, qsizetype size, int base)
+{
+ const char *p = begin, *const stop = begin + size;
+ while (p < stop && ascii_isspace(*p))
+ ++p;
+ // Frustratingly, std::from_chars() doesn't cope with a 0x prefix that might
+ // be between the sign and digits, so we have to handle that for it, which
+ // means we can't use its ability to read LLONG_MIN directly; see below.
+ const bool negate = p < stop && *p == '-';
+ if (negate || (p < stop && *p == '+'))
+ ++p;
+
+ const auto prefix = scanPrefix(p, stop, base);
+ // Must check for digit, as from_chars() will accept a sign, which would be
+ // a second sign, that we should reject.
+ if (!prefix.base || prefix.next >= stop || !isDigitForBase(*prefix.next, prefix.base))
+ return { };
+
+ long long result = 0;
+ auto res = std::from_chars(prefix.next, stop, result, prefix.base);
+ if (negate && res.ec == std::errc::result_out_of_range) {
+ // Maybe LLONG_MIN:
+ unsigned long long check = 0;
+ res = std::from_chars(prefix.next, stop, check, prefix.base);
+ if (res.ec == std::errc{} && check + std::numeric_limits<long long>::min() == 0)
+ return { std::numeric_limits<long long>::min(), res.ptr - begin };
+ return { };
}
- return result;
+ if (res.ec != std::errc{})
+ return { };
+ return { negate ? -result : result, res.ptr - begin };
}
-long long
-qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
+template <typename Char>
+static Q_ALWAYS_INLINE void qulltoString_helper(qulonglong number, int base, Char *&p)
{
- *ok = true;
- errno = 0;
- char *endptr2 = nullptr;
- long long result = qt_strtoll(nptr, &endptr2, base);
- if (endptr)
- *endptr = endptr2;
- if ((result == 0 || result == std::numeric_limits<long long>::min()
- || result == std::numeric_limits<long long>::max())
- && (errno || nptr == endptr2)) {
- *ok = false;
- return 0;
+ // Performance-optimized code. Compiler can generate faster code when base is known.
+ switch (base) {
+#define BIG_BASE_LOOP(b) \
+ do { \
+ const int r = number % b; \
+ *--p = Char((r < 10 ? '0' : 'a' - 10) + r); \
+ number /= b; \
+ } while (number)
+#ifndef __OPTIMIZE_SIZE__
+# define SMALL_BASE_LOOP(b) \
+ do { \
+ *--p = Char('0' + number % b); \
+ number /= b; \
+ } while (number)
+
+ case 2: SMALL_BASE_LOOP(2); break;
+ case 8: SMALL_BASE_LOOP(8); break;
+ case 10: SMALL_BASE_LOOP(10); break;
+ case 16: BIG_BASE_LOOP(16); break;
+#undef SMALL_BASE_LOOP
+#endif
+ default: BIG_BASE_LOOP(base); break;
+#undef BIG_BASE_LOOP
}
- return result;
+}
+
+// This is technically "qulonglong to ascii", but that name's taken
+QString qulltoBasicLatin(qulonglong number, int base, bool negative)
+{
+ if (number == 0)
+ return QStringLiteral("0");
+ // Length of MIN_LLONG with the sign in front is 65; we never need surrogate pairs.
+ // We do not need a terminator.
+ const unsigned maxlen = 65;
+ static_assert(CHAR_BIT * sizeof(number) + 1 <= maxlen);
+ char16_t buff[maxlen];
+ char16_t *const end = buff + maxlen, *p = end;
+
+ qulltoString_helper<char16_t>(number, base, p);
+ if (negative)
+ *--p = u'-';
+
+ return QString(reinterpret_cast<QChar *>(p), end - p);
}
QString qulltoa(qulonglong number, int base, const QStringView zero)
@@ -434,144 +523,50 @@ QString qulltoa(qulonglong number, int base, const QStringView zero)
// per digit. We do not need a terminator.
const unsigned maxlen = 128;
static_assert(CHAR_BIT * sizeof(number) <= maxlen);
- ushort buff[maxlen];
- ushort *const end = buff + maxlen, *p = end;
+ char16_t buff[maxlen];
+ char16_t *const end = buff + maxlen, *p = end;
if (base != 10 || zero == u"0") {
- while (number != 0) {
- int c = number % base;
- *--p = c < 10 ? '0' + c : c - 10 + 'a';
- number /= base;
- }
+ qulltoString_helper<char16_t>(number, base, p);
} else if (zero.size() && !zero.at(0).isSurrogate()) {
- const ushort zeroUcs4 = zero.at(0).unicode();
+ const char16_t zeroUcs2 = zero.at(0).unicode();
while (number != 0) {
- *(--p) = zeroUcs4 + number % base;
+ *(--p) = unicodeForDigit(number % base, zeroUcs2);
number /= base;
}
} else if (zero.size() == 2 && zero.at(0).isHighSurrogate()) {
- const uint zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
+ const char32_t zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
while (number != 0) {
- const uint digit = zeroUcs4 + number % base;
+ const char32_t digit = unicodeForDigit(number % base, zeroUcs4);
*(--p) = QChar::lowSurrogate(digit);
*(--p) = QChar::highSurrogate(digit);
number /= base;
}
- } else {
- return QString();
+ } else { // zero should always be either a non-surrogate or a surrogate pair:
+ Q_UNREACHABLE_RETURN(QString());
}
return QString(reinterpret_cast<QChar *>(p), end - p);
}
-QString &decimalForm(const QString &zero, const QString &decimal, const QString &group,
- QString &digits, int decpt, int precision,
- PrecisionMode pm,
- bool always_show_decpt,
- bool thousands_group)
-{
- const auto digitWidth = zero.size();
- Q_ASSERT(digitWidth == 1 || digitWidth == 2);
- Q_ASSERT(digits.size() % digitWidth == 0);
-
- if (decpt < 0) {
- for (int i = 0; i < -decpt; ++i)
- digits.prepend(zero);
- decpt = 0;
- } else {
- for (int i = digits.length() / digitWidth; i < decpt; ++i)
- digits.append(zero);
- }
-
- switch (pm) {
- case PMDecimalDigits:
- for (int i = digits.length() / digitWidth - decpt; i < precision; ++i)
- digits.append(zero);
- break;
- case PMSignificantDigits:
- for (int i = digits.length() / digitWidth; i < precision; ++i)
- digits.append(zero);
- break;
- case PMChopTrailingZeros:
- break;
- }
-
- if (always_show_decpt || decpt < digits.length() / digitWidth)
- digits.insert(decpt * digitWidth, decimal);
-
- // FIXME: they're not simply thousands separators !
- // Need to mirror IndianNumberGrouping code in QLocaleData::longLongToString()
- if (thousands_group) {
- for (int i = decpt - 3; i > 0; i -= 3)
- digits.insert(i * digitWidth, group);
- }
-
- if (decpt == 0)
- digits.prepend(zero);
-
- return digits;
-}
-
-QString &exponentForm(const QString &zero, const QString &decimal, const QString &exponential,
- const QString &group, const QString &plus, const QString &minus,
- QString &digits, int decpt, int precision,
- PrecisionMode pm,
- bool always_show_decpt,
- bool leading_zero_in_exponent)
-{
- const auto digitWidth = zero.size();
- Q_ASSERT(digitWidth == 1 || digitWidth == 2);
- Q_ASSERT(digits.size() % digitWidth == 0);
-
- switch (pm) {
- case PMDecimalDigits:
- for (int i = digits.length() / digitWidth; i < precision + 1; ++i)
- digits.append(zero);
- break;
- case PMSignificantDigits:
- for (int i = digits.length() / digitWidth; i < precision; ++i)
- digits.append(zero);
- break;
- case PMChopTrailingZeros:
- break;
- }
-
- if (always_show_decpt || digits.length() > digitWidth)
- digits.insert(digitWidth, decimal);
-
- digits.append(exponential);
- digits.append(QLocaleData::longLongToString(zero, group, plus, minus, decpt - 1,
- leading_zero_in_exponent ? 2 : 1,
- 10, -1, QLocaleData::AlwaysShowSign));
-
- return digits;
-}
-
-double qstrtod(const char *s00, const char **se, bool *ok)
-{
- const int len = static_cast<int>(strlen(s00));
- Q_ASSERT(len >= 0);
- return qstrntod(s00, len, se, ok);
-}
-
/*!
\internal
- Converts the initial portion of the string pointed to by \a s00 to a double, using the 'C' locale.
+ Converts the initial portion of the string pointed to by \a s00 to a double,
+ using the 'C' locale. The function sets the pointer pointed to by \a se to
+ point to the character past the last character converted.
*/
-double qstrntod(const char *s00, int len, const char **se, bool *ok)
+double qstrntod(const char *s00, qsizetype len, const char **se, bool *ok)
{
- int processed = 0;
- bool nonNullOk = false;
- double d = qt_asciiToDouble(s00, len, nonNullOk, processed, TrailingJunkAllowed);
+ auto r = qt_asciiToDouble(s00, len, TrailingJunkAllowed);
if (se)
- *se = s00 + processed;
+ *se = s00 + (r.used < 0 ? -r.used : r.used);
if (ok)
- *ok = nonNullOk;
- return d;
+ *ok = r.ok();
+ return r.result;
}
QString qdtoa(qreal d, int *decpt, int *sign)
@@ -581,16 +576,223 @@ QString qdtoa(qreal d, int *decpt, int *sign)
int length = 0;
// Some versions of libdouble-conversion like an extra digit, probably for '\0'
- char result[QLocaleData::DoubleMaxSignificant + 1];
- qt_doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest, result,
- QLocaleData::DoubleMaxSignificant + 1, nonNullSign, length, nonNullDecpt);
+ constexpr qsizetype digits = std::numeric_limits<double>::max_digits10 + 1;
+ char result[digits];
+ qt_doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest,
+ result, digits, nonNullSign, length, nonNullDecpt);
if (sign)
*sign = nonNullSign ? 1 : 0;
if (decpt)
*decpt = nonNullDecpt;
- return QLatin1String(result, length);
+ return QLatin1StringView(result, length);
+}
+
+static QLocaleData::DoubleForm resolveFormat(int precision, int decpt, qsizetype length)
+{
+ bool useDecimal;
+ if (precision == QLocale::FloatingPointShortest) {
+ // Find out which representation is shorter.
+ // Set bias to everything added to exponent form but not
+ // decimal, minus the converse.
+
+ // Exponent adds separator, sign and two exponents:
+ int bias = 2 + 2;
+ if (length <= decpt && length > 1)
+ ++bias;
+ else if (length == 1 && decpt <= 0)
+ --bias;
+
+ // When 0 < decpt <= length, the forms have equal digit
+ // counts, plus things bias has taken into account;
+ // otherwise decimal form's digit count is right-padded with
+ // zeros to decpt, when decpt is positive, otherwise it's
+ // left-padded with 1 - decpt zeros.
+ if (decpt <= 0)
+ useDecimal = 1 - decpt <= bias;
+ else if (decpt <= length)
+ useDecimal = true;
+ else
+ useDecimal = decpt <= length + bias;
+ } else {
+ // X == decpt - 1, POSIX's P; -4 <= X < P iff -4 < decpt <= P
+ Q_ASSERT(precision >= 0);
+ useDecimal = decpt > -4 && decpt <= (precision ? precision : 1);
+ }
+ return useDecimal ? QLocaleData::DFDecimal : QLocaleData::DFExponent;
+}
+
+static constexpr int digits(int number)
+{
+ Q_ASSERT(number >= 0);
+ if (Q_LIKELY(number < 1000))
+ return number < 10 ? 1 : number < 100 ? 2 : 3;
+ int i = 3;
+ for (number /= 1000; number; number /= 10)
+ ++i;
+ return i;
+}
+
+// Used generically for both QString and QByteArray
+template <typename T>
+static T dtoString(double d, QLocaleData::DoubleForm form, int precision, bool uppercase)
+{
+ // Undocumented: aside from F.P.Shortest, precision < 0 is treated as
+ // default, 6 - same as printf().
+ if (precision != QLocale::FloatingPointShortest && precision < 0)
+ precision = 6;
+
+ using D = std::numeric_limits<double>;
+ // 1 is for the null-terminator
+ constexpr int MaxDigits = 1 + qMax(D::max_exponent10, D::digits10 - D::min_exponent10);
+
+ // "maxDigits" above is a reasonable estimate, though we may need more due to extra precision
+ int bufSize = 1;
+ if (precision == QLocale::FloatingPointShortest)
+ bufSize += D::max_digits10;
+ else if (form == QLocaleData::DFDecimal && qt_is_finite(d))
+ bufSize += wholePartSpace(qAbs(d)) + precision;
+ else // Add extra digit due to different interpretations of precision.
+ bufSize += qMax(2, precision) + 1; // Must also be big enough for "nan" or "inf"
+
+ // Reserve `MaxDigits` on the stack, which is a reasonable estimate;
+ // but we may need more due to extra precision, which we cannot know at compile-time.
+ QVarLengthArray<char, MaxDigits> buffer(bufSize);
+ bool negative = false;
+ int length = 0;
+ int decpt = 0;
+ qt_doubleToAscii(d, form, precision, buffer.data(), buffer.size(), negative, length, decpt);
+ QLatin1StringView view(buffer.data(), length);
+ const bool succinct = form == QLocaleData::DFSignificantDigits;
+ qsizetype total = (negative ? 1 : 0) + length;
+ if (qt_is_finite(d)) {
+ if (succinct)
+ form = resolveFormat(precision, decpt, view.size());
+
+ switch (form) {
+ case QLocaleData::DFExponent:
+ total += 3; // (.e+) The '.' may not be needed, but we would only overestimate by 1 char
+ // Exponents: we guarantee at least 2
+ total += std::max(2, digits(std::abs(decpt - 1)));
+ // "length - 1" because one of the digits will always be before the decimal point
+ if (int extraPrecision = precision - (length - 1); extraPrecision > 0 && !succinct)
+ total += extraPrecision; // some requested zero-padding
+ break;
+ case QLocaleData::DFDecimal:
+ if (decpt <= 0) // leading "0." and zeros
+ total += 2 - decpt;
+ else if (decpt < length) // just the dot
+ total += 1;
+ else // trailing zeros (and no dot, unless we require extra precision):
+ total += decpt - length;
+
+ if (precision > 0 && !succinct) {
+ // May need trailing zeros to satisfy precision:
+ if (decpt < length)
+ total += std::max(0, precision - length + decpt);
+ else // and a dot to separate them:
+ total += 1 + precision;
+ }
+ break;
+ case QLocaleData::DFSignificantDigits:
+ Q_UNREACHABLE(); // Handled earlier
+ }
+ }
+
+ constexpr bool IsQString = std::is_same_v<T, QString>;
+ using Char = std::conditional_t<IsQString, char16_t, char>;
+
+ T result;
+ result.reserve(total);
+
+ if (negative && !isZero(d)) // We don't return "-0"
+ result.append(Char('-'));
+ if (!qt_is_finite(d)) {
+ result.append(view);
+ if (uppercase)
+ result = std::move(result).toUpper();
+ } else {
+ switch (form) {
+ case QLocaleData::DFExponent: {
+ result.append(view.first(1));
+ view = view.sliced(1);
+ if (!view.isEmpty() || (!succinct && precision > 0)) {
+ result.append(Char('.'));
+ result.append(view);
+ if (qsizetype pad = precision - view.size(); !succinct && pad > 0) {
+ for (int i = 0; i < pad; ++i)
+ result.append(Char('0'));
+ }
+ }
+ int exponent = decpt - 1;
+ result.append(Char(uppercase ? 'E' : 'e'));
+ result.append(Char(exponent < 0 ? '-' : '+'));
+ exponent = std::abs(exponent);
+ Q_ASSERT(exponent <= D::max_exponent10 + D::max_digits10);
+ int exponentDigits = digits(exponent);
+ // C's printf guarantees a two-digit exponent, and so do we:
+ if (exponentDigits == 1)
+ result.append(Char('0'));
+ result.resize(result.size() + exponentDigits);
+ auto location = reinterpret_cast<Char *>(result.end());
+ qulltoString_helper<Char>(exponent, 10, location);
+ break;
+ }
+ case QLocaleData::DFDecimal:
+ if (decpt < 0) {
+ if constexpr (IsQString)
+ result.append(u"0.0");
+ else
+ result.append("0.0");
+ while (++decpt < 0)
+ result.append(Char('0'));
+ result.append(view);
+ if (!succinct) {
+ auto numDecimals = result.size() - 2 - (negative ? 1 : 0);
+ for (qsizetype i = numDecimals; i < precision; ++i)
+ result.append(Char('0'));
+ }
+ } else {
+ if (decpt > view.size()) {
+ result.append(view);
+ const int sign = negative ? 1 : 0;
+ while (result.size() - sign < decpt)
+ result.append(Char('0'));
+ view = {};
+ } else if (decpt) {
+ result.append(view.first(decpt));
+ view = view.sliced(decpt);
+ } else {
+ result.append(Char('0'));
+ }
+ if (!view.isEmpty() || (!succinct && view.size() < precision)) {
+ result.append(Char('.'));
+ result.append(view);
+ if (!succinct) {
+ for (qsizetype i = view.size(); i < precision; ++i)
+ result.append(Char('0'));
+ }
+ }
+ }
+ break;
+ case QLocaleData::DFSignificantDigits:
+ Q_UNREACHABLE(); // taken care of earlier
+ break;
+ }
+ }
+ Q_ASSERT(total >= result.size()); // No reallocations are needed
+ return result;
+}
+
+QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, int precision, bool uppercase)
+{
+ return dtoString<QString>(d, form, precision, uppercase);
+}
+
+QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form, int precision, bool uppercase)
+{
+ return dtoString<QByteArray>(d, form, precision, uppercase);
}
QT_END_NAMESPACE
diff --git a/src/corelib/text/qlocale_tools_p.h b/src/corelib/text/qlocale_tools_p.h
index f04c4512c0..9b02403ea4 100644
--- a/src/corelib/text/qlocale_tools_p.h
+++ b/src/corelib/text/qlocale_tools_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOCALE_TOOLS_P_H
#define QLOCALE_TOOLS_P_H
@@ -62,46 +26,65 @@ enum StrayCharacterMode {
WhitespacesAllowed
};
-double qt_asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
- StrayCharacterMode strayCharMode = TrailingJunkProhibited);
-void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
+// API note: this function can't process a number with more than 2.1 billion digits
+[[nodiscard]] QSimpleParsedNumber<double>
+qt_asciiToDouble(const char *num, qsizetype numLen,
+ StrayCharacterMode strayCharMode = TrailingJunkProhibited);
+void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
+ char *buf, qsizetype bufSize,
bool &sign, int &length, int &decpt);
-QString qulltoa(qulonglong l, int base, const QStringView zero);
-Q_CORE_EXPORT QString qdtoa(qreal d, int *decpt, int *sign);
+[[nodiscard]] QString qulltoBasicLatin(qulonglong l, int base, bool negative);
+[[nodiscard]] QString qulltoa(qulonglong l, int base, const QStringView zero);
+[[nodiscard]] Q_CORE_EXPORT QString qdtoa(qreal d, int *decpt, int *sign);
+[[nodiscard]] QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form,
+ int precision, bool uppercase);
+[[nodiscard]] QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form,
+ int precision, bool uppercase);
-enum PrecisionMode {
- PMDecimalDigits = 0x01,
- PMSignificantDigits = 0x02,
- PMChopTrailingZeros = 0x03
-};
+[[nodiscard]] constexpr inline bool isZero(double d)
+{
+ return d == 0; // Amusingly, compilers do not grumble.
+}
+
+// Enough space for the digits before the decimal separator:
+[[nodiscard]] inline int wholePartSpace(double d)
+{
+ Q_ASSERT(d >= 0); // caller should call qAbs() if needed
+ // Optimize for numbers between -512k and 512k - otherwise, use the
+ // maximum number of digits in the whole number part of a double:
+ return d > (1 << 19) ? std::numeric_limits<double>::max_exponent10 + 1 : 6;
+}
+
+// Returns code-point of same kind (UCS2 or UCS4) as zero; digit is 0 through 9
+template <typename UcsInt>
+[[nodiscard]] inline UcsInt unicodeForDigit(uint digit, UcsInt zero)
+{
+ // Must match qlocale.cpp's NumberTokenizer's digit-digestion.
+ Q_ASSERT(digit < 10);
+ if (!digit)
+ return zero;
+
+ // See QTBUG-85409: Suzhou's digits are U+3007, U+3021, ..., U+3029
+ if (zero == u'\u3007')
+ return u'\u3020' + digit;
+ // In util/locale_database/ldml.py, LocaleScanner.numericData() asserts no
+ // other number system in CLDR has discontinuous digits.
+
+ return zero + digit;
+}
-QString &decimalForm(const QString &zero, const QString &decimal, const QString &group,
- QString &digits, int decpt, int precision,
- PrecisionMode pm,
- bool always_show_decpt,
- bool thousands_group);
-QString &exponentForm(const QString &zero, const QString &decimal, const QString &exponential,
- const QString &group, const QString &plus, const QString &minus,
- QString &digits, int decpt, int precision,
- PrecisionMode pm,
- bool always_show_decpt,
- bool leading_zero_in_exponent);
-
-inline bool isZero(double d)
+[[nodiscard]] Q_CORE_EXPORT double qstrntod(const char *s00, qsizetype len,
+ char const **se, bool *ok);
+[[nodiscard]] inline double qstrtod(const char *s00, char const **se, bool *ok)
{
- uchar *ch = (uchar *)&d;
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- return !(ch[0] & 0x7F || ch[1] || ch[2] || ch[3] || ch[4] || ch[5] || ch[6] || ch[7]);
- } else {
- return !(ch[7] & 0x7F || ch[6] || ch[5] || ch[4] || ch[3] || ch[2] || ch[1] || ch[0]);
- }
+ qsizetype len = qsizetype(strlen(s00));
+ return qstrntod(s00, len, se, ok);
}
-Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-Q_CORE_EXPORT double qstrntod(const char *s00, int len, char const **se, bool *ok);
-qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok);
-qulonglong qstrtoull(const char *nptr, const char **endptr, int base, bool *ok);
+[[nodiscard]] Q_AUTOTEST_EXPORT
+QSimpleParsedNumber<qlonglong> qstrntoll(const char *nptr, qsizetype size, int base);
+[[nodiscard]] QSimpleParsedNumber<qulonglong> qstrntoull(const char *nptr, qsizetype size, int base);
QT_END_NAMESPACE
diff --git a/src/corelib/text/qlocale_unix.cpp b/src/corelib/text/qlocale_unix.cpp
index 51b23f1559..a934f24c01 100644
--- a/src/corelib/text/qlocale_unix.cpp
+++ b/src/corelib/text/qlocale_unix.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlocale_p.h"
@@ -47,6 +11,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#ifndef QT_NO_SYSTEMLOCALE
struct QSystemLocaleData
{
@@ -77,6 +43,8 @@ void QSystemLocaleData::readEnvironment()
{
QWriteLocker locker(&lock);
+ // See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02
+ // for the semantics of each of these:
QByteArray all = qgetenv("LC_ALL");
QByteArray numeric = all.isEmpty() ? qgetenv("LC_NUMERIC") : all;
QByteArray time = all.isEmpty() ? qgetenv("LC_TIME") : all;
@@ -111,7 +79,7 @@ Q_GLOBAL_STATIC(QSystemLocaleData, qSystemLocaleData)
#ifndef QT_NO_SYSTEMLOCALE
-static bool contradicts(const QString &maybe, const QString &known)
+static bool contradicts(QStringView maybe, const QString &known)
{
if (maybe.isEmpty())
return false;
@@ -128,17 +96,12 @@ static bool contradicts(const QString &maybe, const QString &known)
Belarusian. There are many more such prefixings between two- and
three-letter codes.)
*/
- QLocale::Language langm, langk;
- QLocale::Script scriptm, scriptk;
- QLocale::Country landm, landk;
- QLocalePrivate::getLangAndCountry(maybe, langm, scriptm, landm);
- QLocalePrivate::getLangAndCountry(known, langk, scriptk, landk);
- return (langm != QLocale::AnyLanguage && langm != langk)
- || (scriptm != QLocale::AnyScript && scriptm != scriptk)
- || (landm != QLocale::AnyCountry && landm != landk);
+ QLocaleId knownId = QLocaleId::fromName(known);
+ QLocaleId maybeId = QLocaleId::fromName(maybe);
+ return !(maybeId.acceptLanguage(knownId.language_id) && maybeId.acceptScriptTerritory(knownId));
}
-QLocale QSystemLocale::fallbackUiLocale() const
+QLocale QSystemLocale::fallbackLocale() const
{
// See man 7 locale for precedence - LC_ALL beats LC_MESSAGES beats LANG:
QString lang = qEnvironmentVariable("LC_ALL");
@@ -147,22 +110,21 @@ QLocale QSystemLocale::fallbackUiLocale() const
if (lang.isEmpty())
lang = qEnvironmentVariable("LANG");
// if the locale is the "C" locale, then we can return the language we found here:
- if (lang.isEmpty() || lang == QLatin1String("C") || lang == QLatin1String("POSIX"))
+ if (lang.isEmpty() || lang == "C"_L1 || lang == "POSIX"_L1)
return QLocale(lang);
// ... otherwise, if the first part of LANGUAGE says more than or
// contradicts what we have, use that:
- QString language = qEnvironmentVariable("LANGUAGE");
- if (!language.isEmpty()) {
- language = language.split(QLatin1Char(':')).constFirst();
+ for (const auto &language : qEnvironmentVariable("LANGUAGE").tokenize(u':')) {
if (contradicts(language, lang))
return QLocale(language);
+ break; // We only look at the first entry.
}
return QLocale(lang);
}
-QVariant QSystemLocale::query(QueryType type, QVariant in) const
+QVariant QSystemLocale::query(QueryType type, QVariant &&in) const
{
QSystemLocaleData *d = qSystemLocaleData();
@@ -199,14 +161,26 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
return lc_time.dayName(in.toInt(), QLocale::LongFormat);
case DayNameShort:
return lc_time.dayName(in.toInt(), QLocale::ShortFormat);
+ case DayNameNarrow:
+ return lc_time.dayName(in.toInt(), QLocale::NarrowFormat);
+ case StandaloneDayNameLong:
+ return lc_time.standaloneDayName(in.toInt(), QLocale::LongFormat);
+ case StandaloneDayNameShort:
+ return lc_time.standaloneDayName(in.toInt(), QLocale::ShortFormat);
+ case StandaloneDayNameNarrow:
+ return lc_time.standaloneDayName(in.toInt(), QLocale::NarrowFormat);
case MonthNameLong:
return lc_time.monthName(in.toInt(), QLocale::LongFormat);
case MonthNameShort:
return lc_time.monthName(in.toInt(), QLocale::ShortFormat);
+ case MonthNameNarrow:
+ return lc_time.monthName(in.toInt(), QLocale::NarrowFormat);
case StandaloneMonthNameLong:
return lc_time.standaloneMonthName(in.toInt(), QLocale::LongFormat);
case StandaloneMonthNameShort:
return lc_time.standaloneMonthName(in.toInt(), QLocale::ShortFormat);
+ case StandaloneMonthNameNarrow:
+ return lc_time.standaloneMonthName(in.toInt(), QLocale::NarrowFormat);
case DateToStringLong:
return lc_time.toString(in.toDate(), QLocale::LongFormat);
case DateToStringShort:
@@ -252,9 +226,9 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
}
case MeasurementSystem: {
const QString meas_locale = QString::fromLatin1(d->lc_measurement_var);
- if (meas_locale.compare(QLatin1String("Metric"), Qt::CaseInsensitive) == 0)
+ if (meas_locale.compare("Metric"_L1, Qt::CaseInsensitive) == 0)
return QLocale::MetricSystem;
- if (meas_locale.compare(QLatin1String("Other"), Qt::CaseInsensitive) == 0)
+ if (meas_locale.compare("Other"_L1, Qt::CaseInsensitive) == 0)
return QLocale::MetricSystem;
return QVariant((int)QLocale(meas_locale).measurementSystem());
}
@@ -268,28 +242,31 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
if (languages.isEmpty())
lst.append(QString::fromLatin1(d->lc_messages_var));
else
- lst = languages.split(QLatin1Char(':'));
+ lst = languages.split(u':');
- for (int i = 0; i < lst.size(); ++i) {
- const QString &name = lst.at(i);
- QString lang, script, cntry;
- if (qt_splitLocaleName(name, lang, script, cntry)) {
- if (!cntry.length())
- d->uiLanguages.append(lang);
- else
- d->uiLanguages.append(lang % QLatin1Char('-') % cntry);
+ for (const QString &e : std::as_const(lst)) {
+ QStringView language, script, territory;
+ if (qt_splitLocaleName(e, &language, &script, &territory)) {
+ QString joined = language.isEmpty() ? u"und"_s : language.toString();
+ if (!script.isEmpty())
+ joined += u'-' + script;
+ if (!territory.isEmpty())
+ joined += u'-' + territory;
+ d->uiLanguages.append(joined);
}
}
return d->uiLanguages.isEmpty() ? QVariant() : QVariant(d->uiLanguages);
}
case StringToStandardQuotation:
- return lc_messages.quoteString(qvariant_cast<QStringView>(in));
+ return lc_messages.quoteString(qvariant_cast<QStringView>(std::move(in)));
case StringToAlternateQuotation:
- return lc_messages.quoteString(qvariant_cast<QStringView>(in), QLocale::AlternateQuotation);
+ return lc_messages.quoteString(qvariant_cast<QStringView>(std::move(in)),
+ QLocale::AlternateQuotation);
case ListToSeparatedString:
return lc_messages.createSeparatedList(in.toStringList());
case LocaleChanged:
Q_ASSERT(false);
+ [[fallthrough]];
default:
break;
}
diff --git a/src/corelib/text/qlocale_wasm.cpp b/src/corelib/text/qlocale_wasm.cpp
new file mode 100644
index 0000000000..6b011af4a7
--- /dev/null
+++ b/src/corelib/text/qlocale_wasm.cpp
@@ -0,0 +1,54 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qlocale_p.h"
+
+#include <emscripten/val.h>
+
+#include <string>
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMLOCALE
+
+namespace {
+
+QStringList navigatorLanguages()
+{
+ using emscripten::val;
+ const val navigator = val::global("navigator");
+ const auto languages = emscripten::vecFromJSArray<std::string>(navigator["languages"]);
+ QStringList qtLanguages;
+ for (const std::string& language : languages)
+ qtLanguages.append(QString::fromStdString(language));
+ return qtLanguages;
+}
+
+}
+
+QVariant QSystemLocale::query(QueryType query, QVariant &&in) const
+{
+ Q_UNUSED(in);
+
+ switch (query) {
+ case QSystemLocale::UILanguages:
+ return QVariant(navigatorLanguages());
+ default:
+ break;
+ }
+
+ return QVariant();
+}
+
+QLocale QSystemLocale::fallbackLocale() const
+{
+ const QStringList languages = navigatorLanguages();
+ if (languages.isEmpty())
+ return QLocale(u"en-US");
+ return QLocale(languages[0]);
+}
+
+#endif // QT_NO_SYSTEMLOCALE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp
index 9af37cb8d0..9fdb46a4c9 100644
--- a/src/corelib/text/qlocale_win.cpp
+++ b/src/corelib/text/qlocale_win.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlocale_p.h"
#include "qlocale_tools_p.h"
@@ -46,16 +10,62 @@
#include "qdatetime.h"
#include "qdebug.h"
-#ifdef Q_OS_WIN
-# include <qt_windows.h>
-# include <time.h>
-#endif
+#include "QtCore/private/qgregoriancalendar_p.h" // for yearSharingWeekDays()
+
+#include <q20algorithm.h>
+
+// TODO QTBUG-121193: port away from the use of LCID to always use names.
+#include <qt_windows.h>
+#include <time.h>
+
+#if QT_CONFIG(cpp_winrt)
+# include <QtCore/private/qt_winrtbase_p.h>
+
+# include <winrt/Windows.Foundation.h>
+# include <winrt/Windows.Foundation.Collections.h>
+# include <winrt/Windows.System.UserProfile.h>
+#endif // QT_CONFIG(cpp_winrt)
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+// Shared interpretation of %LANG%
+static auto scanLangEnv()
+{
+ struct R
+ {
+ QByteArray name; // empty means unknown; lookup from id may work
+ LCID id = 0; // 0 means unknown; lookup from name may work
+ } result;
+ const QByteArray lang = qgetenv("LANG");
+ if (lang.size() && (lang == "C" || qt_splitLocaleName(QString::fromLocal8Bit(lang)))) {
+ // See if we have a Windows locale code instead of a locale name:
+ const auto [id, used] = qstrntoll(lang.data(), lang.size(), 0);
+ if (used > 0 && id && INT_MIN <= id && id <= INT_MAX)
+ return R {QByteArray(), static_cast<LCID>(id)};
+ return R {lang, 0};
+ }
+ return R{};
+}
+
+static auto getDefaultWinId()
+{
+ const auto [name, id] = scanLangEnv();
+ if (id)
+ return id;
+
+ if (!name.isEmpty()) {
+ LCID id = LocaleNameToLCID(static_cast<LPCWSTR>(
+ QString::fromUtf8(name).toStdWString().data()), 0);
+ if (id)
+ return id;
+ }
+
+ return GetUserDefaultLCID();
+}
+
static QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT);
-static QString winIso639LangName(LCID id = LOCALE_USER_DEFAULT);
-static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT);
#ifndef QT_NO_SYSTEMLOCALE
@@ -81,6 +91,17 @@ static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT);
# define LOCALE_SSHORTTIME 0x00000079
#endif
+namespace {
+template <typename T>
+static QVariant nullIfEmpty(T &&value)
+{
+ // For use where we should fall back to CLDR if we got an empty value.
+ if (value.isEmpty())
+ return {};
+ return std::move(value);
+}
+}
+
struct QSystemLocalePrivate
{
QSystemLocalePrivate();
@@ -94,6 +115,7 @@ struct QSystemLocalePrivate
QVariant timeFormat(QLocale::FormatType);
QVariant dateTimeFormat(QLocale::FormatType);
QVariant dayName(int, QLocale::FormatType);
+ QVariant standaloneMonthName(int, QLocale::FormatType);
QVariant monthName(int, QLocale::FormatType);
QVariant toString(QDate, QLocale::FormatType);
QVariant toString(QTime, QLocale::FormatType);
@@ -107,7 +129,7 @@ struct QSystemLocalePrivate
QVariant toCurrencyString(const QSystemLocale::CurrencyToStringArgument &);
QVariant uiLanguages();
QVariant nativeLanguageName();
- QVariant nativeCountryName();
+ QVariant nativeTerritoryName();
void update();
@@ -121,21 +143,21 @@ private:
// cached values:
LCID lcid;
- SubstitutionType substitutionType;
+ SubstitutionType substitutionType = SUnknown;
QString zero; // cached value for zeroDigit()
int getLocaleInfo(LCTYPE type, LPWSTR data, int size);
- // Need to distinguish empty QString packaged as (non-null) QVariant from null QVariant:
- template <typename T = QString>
- T getLocaleInfo(LCTYPE type, int maxlen = 0);
- int getLocaleInfo_int(LCTYPE type, int maxlen = 0);
+ QVariant getLocaleInfo(LCTYPE type);
+ int getLocaleInfo_int(LCTYPE type);
int getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size);
int getDateFormat(DWORD flags, const SYSTEMTIME * date, LPCWSTR format, LPWSTR data, int size);
int getTimeFormat(DWORD flags, const SYSTEMTIME *date, LPCWSTR format, LPWSTR data, int size);
SubstitutionType substitution();
- QString &substituteDigits(QString &string);
+ QString substituteDigits(QString &&string);
+ QString correctDigits(QString &&string);
+ QString yearFix(int year, int fakeYear, QString &&formatted);
static QString winToQtFormat(QStringView sys_fmt);
@@ -143,9 +165,8 @@ private:
Q_GLOBAL_STATIC(QSystemLocalePrivate, systemLocalePrivate)
QSystemLocalePrivate::QSystemLocalePrivate()
- : substitutionType(SUnknown)
+ : lcid(getDefaultWinId())
{
- lcid = GetUserDefaultLCID();
}
inline int QSystemLocalePrivate::getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size)
@@ -168,15 +189,15 @@ inline int QSystemLocalePrivate::getLocaleInfo(LCTYPE type, LPWSTR data, int siz
return GetLocaleInfo(lcid, type, data, size);
}
-template<typename T>
-T QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen)
+QVariant QSystemLocalePrivate::getLocaleInfo(LCTYPE type)
{
// https://docs.microsoft.com/en-us/windows/win32/intl/locale-spositivesign
// says empty for LOCALE_SPOSITIVESIGN means "+", although GetLocaleInfo()
// is documented to return 0 only on failure, so it's not clear how it
// returns empty to mean this; hence the two checks for it below.
const QString plus = QStringLiteral("+");
- QVarLengthArray<wchar_t, 64> buf(maxlen ? maxlen : 64);
+ QVarLengthArray<wchar_t, 64> buf(64);
+ // Need to distinguish empty QString packaged as (non-null) QVariant from null QVariant:
if (!getLocaleInfo(type, buf.data(), buf.size())) {
const auto lastError = GetLastError();
if (type == LOCALE_SPOSITIVESIGN && lastError == ERROR_SUCCESS)
@@ -195,12 +216,13 @@ T QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen)
return QString::fromWCharArray(buf.data());
}
-int QSystemLocalePrivate::getLocaleInfo_int(LCTYPE type, int maxlen)
+int QSystemLocalePrivate::getLocaleInfo_int(LCTYPE type)
{
- QString str = getLocaleInfo(type, maxlen);
- bool ok = false;
- int v = str.toInt(&ok);
- return ok ? v : 0;
+ DWORD value;
+ int r = GetLocaleInfo(lcid, type | LOCALE_RETURN_NUMBER,
+ reinterpret_cast<wchar_t *>(&value),
+ sizeof(value) / sizeof(wchar_t));
+ return r == sizeof(value) / sizeof(wchar_t) ? value : 0;
}
QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution()
@@ -208,52 +230,53 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution()
if (substitutionType == SUnknown) {
wchar_t buf[8];
if (!getLocaleInfo(LOCALE_IDIGITSUBSTITUTION, buf, 8)) {
- substitutionType = QSystemLocalePrivate::SNever;
+ substitutionType = SNever;
return substitutionType;
}
if (buf[0] == '1')
- substitutionType = QSystemLocalePrivate::SNever;
+ substitutionType = SNever;
else if (buf[0] == '0')
- substitutionType = QSystemLocalePrivate::SContext;
+ substitutionType = SContext;
else if (buf[0] == '2')
- substitutionType = QSystemLocalePrivate::SAlways;
+ substitutionType = SAlways;
else {
wchar_t digits[11]; // See zeroDigit() for why 11.
if (!getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) {
- substitutionType = QSystemLocalePrivate::SNever;
+ substitutionType = SNever;
return substitutionType;
}
if (buf[0] == digits[0] + 2)
- substitutionType = QSystemLocalePrivate::SAlways;
+ substitutionType = SAlways;
else
- substitutionType = QSystemLocalePrivate::SNever;
+ substitutionType = SNever;
}
}
return substitutionType;
}
-QString &QSystemLocalePrivate::substituteDigits(QString &string)
+QString QSystemLocalePrivate::substituteDigits(QString &&string)
{
zeroDigit(); // Ensure zero is set.
switch (zero.size()) {
case 1: {
- const ushort offset = zero.at(0).unicode() - '0';
- if (!offset) // Nothing to do
+ ushort z = zero.at(0).unicode();
+ if (z == '0') // Nothing to do
break;
- Q_ASSERT(offset > 9);
+ Q_ASSERT(z > '9');
ushort *const qch = reinterpret_cast<ushort *>(string.data());
- for (int i = 0, stop = string.size(); i < stop; ++i) {
+ for (qsizetype i = 0, stop = string.size(); i < stop; ++i) {
ushort &ch = qch[i];
if (ch >= '0' && ch <= '9')
- ch += offset;
+ ch = unicodeForDigit(ch - '0', z);
}
break;
}
case 2: {
// Surrogate pair (high, low):
- uint digit = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
+ char32_t z = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
for (int i = 0; i < 10; i++) {
- const QChar s[2] = { QChar::highSurrogate(digit + i), QChar::lowSurrogate(digit + i) };
+ char32_t digit = unicodeForDigit(i, z);
+ const QChar s[2] = { QChar::highSurrogate(digit), QChar::lowSurrogate(digit) };
string.replace(QString(QLatin1Char('0' + i)), QString(s, 2));
}
break;
@@ -263,7 +286,12 @@ QString &QSystemLocalePrivate::substituteDigits(QString &string)
case 0: // Apparently this locale info was not available.
break;
}
- return string;
+ return std::move(string);
+}
+
+QString QSystemLocalePrivate::correctDigits(QString &&string)
+{
+ return substitution() == SAlways ? substituteDigits(std::move(string)) : std::move(string);
}
QVariant QSystemLocalePrivate::zeroDigit()
@@ -278,40 +306,41 @@ QVariant QSystemLocalePrivate::zeroDigit()
*/
wchar_t digits[11];
if (getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) {
- // assert all(digits[i] == i + digits[0] for i in range(1, 10)), assumed above
+ // assert all(digits[i] == i + digits[0] for i in range(1, 10)),
+ // assumed above (unless digits[0] is 0x3007; see QTBUG-85409).
zero = QString::fromWCharArray(digits, 1);
}
}
- return zero;
+ return nullIfEmpty(zero); // Do not std::move().
}
QVariant QSystemLocalePrivate::decimalPoint()
{
- return getLocaleInfo<QVariant>(LOCALE_SDECIMAL);
+ return nullIfEmpty(getLocaleInfo(LOCALE_SDECIMAL).toString());
}
QVariant QSystemLocalePrivate::groupSeparator()
{
- return getLocaleInfo<QVariant>(LOCALE_STHOUSAND);
+ return getLocaleInfo(LOCALE_STHOUSAND); // Empty means don't group digits.
}
QVariant QSystemLocalePrivate::negativeSign()
{
- return getLocaleInfo<QVariant>(LOCALE_SNEGATIVESIGN);
+ return nullIfEmpty(getLocaleInfo(LOCALE_SNEGATIVESIGN).toString());
}
QVariant QSystemLocalePrivate::positiveSign()
{
- return getLocaleInfo<QVariant>(LOCALE_SPOSITIVESIGN);
+ return nullIfEmpty(getLocaleInfo(LOCALE_SPOSITIVESIGN).toString());
}
QVariant QSystemLocalePrivate::dateFormat(QLocale::FormatType type)
{
switch (type) {
case QLocale::ShortFormat:
- return winToQtFormat(getLocaleInfo(LOCALE_SSHORTDATE));
+ return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_SSHORTDATE).toString()));
case QLocale::LongFormat:
- return winToQtFormat(getLocaleInfo(LOCALE_SLONGDATE));
+ return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_SLONGDATE).toString()));
case QLocale::NarrowFormat:
break;
}
@@ -322,96 +351,173 @@ QVariant QSystemLocalePrivate::timeFormat(QLocale::FormatType type)
{
switch (type) {
case QLocale::ShortFormat:
- return winToQtFormat(getLocaleInfo(LOCALE_SSHORTTIME));
+ return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_SSHORTTIME).toString()));
case QLocale::LongFormat:
- return winToQtFormat(getLocaleInfo(LOCALE_STIMEFORMAT));
+ return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_STIMEFORMAT).toString()));
case QLocale::NarrowFormat:
break;
}
- return QVariant();
+ return {};
}
QVariant QSystemLocalePrivate::dateTimeFormat(QLocale::FormatType type)
{
- return QString(dateFormat(type).toString() + QLatin1Char(' ') + timeFormat(type).toString());
+ QVariant d = dateFormat(type), t = timeFormat(type);
+ if (d.typeId() == QMetaType::QString && t.typeId() == QMetaType::QString)
+ return QString(d.toString() + u' ' + t.toString());
+ return {};
}
QVariant QSystemLocalePrivate::dayName(int day, QLocale::FormatType type)
{
if (day < 1 || day > 7)
- return QString();
+ return {};
- static const LCTYPE short_day_map[]
+ static constexpr LCTYPE short_day_map[]
= { LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
LOCALE_SABBREVDAYNAME6, LOCALE_SABBREVDAYNAME7 };
- static const LCTYPE long_day_map[]
+ static constexpr LCTYPE long_day_map[]
= { LOCALE_SDAYNAME1, LOCALE_SDAYNAME2,
LOCALE_SDAYNAME3, LOCALE_SDAYNAME4, LOCALE_SDAYNAME5,
LOCALE_SDAYNAME6, LOCALE_SDAYNAME7 };
- static const LCTYPE narrow_day_map[]
+ static constexpr LCTYPE narrow_day_map[]
= { LOCALE_SSHORTESTDAYNAME1, LOCALE_SSHORTESTDAYNAME2,
LOCALE_SSHORTESTDAYNAME3, LOCALE_SSHORTESTDAYNAME4,
LOCALE_SSHORTESTDAYNAME5, LOCALE_SSHORTESTDAYNAME6,
LOCALE_SSHORTESTDAYNAME7 };
- day -= 1;
-
- if (type == QLocale::LongFormat)
- return getLocaleInfo<QVariant>(long_day_map[day]);
- if (type == QLocale::NarrowFormat)
- return getLocaleInfo<QVariant>(narrow_day_map[day]);
- return getLocaleInfo<QVariant>(short_day_map[day]);
+ return nullIfEmpty(getLocaleInfo(
+ (type == QLocale::LongFormat ? long_day_map
+ : type == QLocale::NarrowFormat ? narrow_day_map
+ : short_day_map)[day - 1]).toString());
}
-QVariant QSystemLocalePrivate::monthName(int month, QLocale::FormatType type)
+QVariant QSystemLocalePrivate::standaloneMonthName(int month, QLocale::FormatType type)
{
- static const LCTYPE short_month_map[]
+ static constexpr LCTYPE short_month_map[]
= { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
- static const LCTYPE long_month_map[]
+ static constexpr LCTYPE long_month_map[]
= { LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3,
LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6,
LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9,
LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12 };
- month -= 1;
- if (month < 0 || month > 11)
- return QString();
+ if (month < 1 || month > 12)
+ return {};
+
+ // Month is Jan = 1, ... Dec = 12; adjust by 1 to match array indexing from 0:
+ return nullIfEmpty(getLocaleInfo(
+ (type == QLocale::LongFormat ? long_month_map : short_month_map)[month - 1]).toString());
+}
+
+QVariant QSystemLocalePrivate::monthName(int month, QLocale::FormatType type)
+{
+ SYSTEMTIME st = {};
+ st.wYear = 2001;
+ st.wMonth = month;
+ st.wDay = 10;
+
+ const DWORD flags{}; // Must be clear when passing a format string.
+ // MS's docs for the LOCALE_SMONTHNAME* say to include the day in a format.
+ // Educated guess: this works for the LOCALE_SABBREVMONTHNAME*, too, in so
+ // far as the abbreviated plain name might differ from abbreviated
+ // standalone one.
+ const wchar_t *const format = type == QLocale::LongFormat ? L"ddMMMM" : L"ddMMM";
+ wchar_t buf[255];
+ if (getDateFormat(flags, &st, format, buf, 255) > 2) {
+ // Elide the two digits of day number
+ return nullIfEmpty(correctDigits(QString::fromWCharArray(buf + 2)));
+ }
+ return {};
+}
+
+static QString fourDigitYear(int year)
+{
+ // Return year formatted as an (at least) four digit number:
+ return QStringLiteral("%1").arg(year, 4, 10, QChar(u'0'));
+}
- LCTYPE lctype = (type == QLocale::ShortFormat || type == QLocale::NarrowFormat)
- ? short_month_map[month] : long_month_map[month];
- return getLocaleInfo<QVariant>(lctype);
+QString QSystemLocalePrivate::yearFix(int year, int fakeYear, QString &&formatted)
+{
+ // Replace our ersatz fakeYear (that MS formats faithfully) with the correct
+ // form of year. We know the two-digit short form of fakeYear can not be
+ // mistaken for the month or day-of-month in the formatted date.
+ Q_ASSERT(fakeYear >= 1970 && fakeYear <= 2400);
+ const bool matchTwo = year >= 0 && year % 100 == fakeYear % 100;
+ auto yearUsed = fourDigitYear(fakeYear);
+ QString sign(year < 0 ? 1 : 0, u'-');
+ auto trueYear = fourDigitYear(year < 0 ? -year : year);
+ if (formatted.contains(yearUsed))
+ return std::move(formatted).replace(yearUsed, sign + trueYear);
+
+ auto tail = QStringView{yearUsed}.last(2);
+ Q_ASSERT(!matchTwo || tail == QString(sign + trueYear.last(2)));
+ if (formatted.contains(tail)) {
+ if (matchTwo)
+ return std::move(formatted);
+ return std::move(formatted).replace(tail.toString(), sign + trueYear.last(2));
+ }
+
+ // Localized digits (regardless of SAlways), perhaps ?
+ // First call to substituteDigits() ensures zero is initialized:
+ trueYear = substituteDigits(std::move(trueYear));
+ if (zero != u'0') {
+ yearUsed = substituteDigits(std::move(yearUsed));
+ if (year < 0)
+ sign = negativeSign().toString();
+
+ if (formatted.contains(yearUsed))
+ return std::move(formatted).replace(yearUsed, sign + trueYear);
+
+ const qsizetype twoDigits = 2 * zero.size();
+ tail = QStringView{yearUsed}.last(twoDigits);
+ if (formatted.contains(tail)) {
+ if (matchTwo)
+ return std::move(formatted);
+ return std::move(formatted).replace(tail.toString(), sign + trueYear.last(twoDigits));
+ }
+ }
+ qWarning("Failed to fix up year in formatted date-string using %d for %d", fakeYear, year);
+ return std::move(formatted);
}
QVariant QSystemLocalePrivate::toString(QDate date, QLocale::FormatType type)
{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- st.wYear = date.year();
+ SYSTEMTIME st = {};
+ const int year = date.year();
+ // st.wYear is unsigned; and GetDateFormat() is documented to not handle
+ // dates before 1601.
+ const bool fixup = year < 1601;
+ st.wYear = fixup ? QGregorianCalendar::yearSharingWeekDays(date) : year;
st.wMonth = date.month();
st.wDay = date.day();
+ Q_ASSERT(!fixup || st.wYear % 100 != st.wMonth);
+ Q_ASSERT(!fixup || st.wYear % 100 != st.wDay);
+ // i.e. yearFix() can trust a match of its fakeYear's last two digits to not
+ // be the month or day part of the formatted date.
+
DWORD flags = (type == QLocale::LongFormat ? DATE_LONGDATE : DATE_SHORTDATE);
wchar_t buf[255];
if (getDateFormat(flags, &st, NULL, buf, 255)) {
- QString format = QString::fromWCharArray(buf);
- if (substitution() == SAlways)
- substituteDigits(format);
- return format;
+ QString text = QString::fromWCharArray(buf);
+ if (fixup)
+ text = yearFix(year, st.wYear, std::move(text));
+ return nullIfEmpty(correctDigits(std::move(text)));
}
- return QString();
+ return {};
}
QVariant QSystemLocalePrivate::toString(QTime time, QLocale::FormatType type)
{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
+ SYSTEMTIME st = {};
st.wHour = time.hour();
st.wMinute = time.minute();
st.wSecond = time.second();
@@ -419,22 +525,23 @@ QVariant QSystemLocalePrivate::toString(QTime time, QLocale::FormatType type)
DWORD flags = 0;
// keep the same conditional as timeFormat() above
- if (type == QLocale::ShortFormat)
- flags = TIME_NOSECONDS;
+ const QString format = type == QLocale::ShortFormat
+ ? getLocaleInfo(LOCALE_SSHORTTIME).toString()
+ : QString();
+ auto formatStr = reinterpret_cast<const wchar_t *>(format.isEmpty() ? nullptr : format.utf16());
wchar_t buf[255];
- if (getTimeFormat(flags, &st, NULL, buf, 255)) {
- QString format = QString::fromWCharArray(buf);
- if (substitution() == SAlways)
- substituteDigits(format);
- return format;
- }
- return QString();
+ if (getTimeFormat(flags, &st, formatStr, buf, int(std::size(buf))))
+ return nullIfEmpty(correctDigits(QString::fromWCharArray(buf)));
+ return {};
}
QVariant QSystemLocalePrivate::toString(const QDateTime &dt, QLocale::FormatType type)
{
- return QString(toString(dt.date(), type).toString() + QLatin1Char(' ') + toString(dt.time(), type).toString());
+ QVariant d = toString(dt.date(), type), t = toString(dt.time(), type);
+ if (d.typeId() == QMetaType::QString && t.typeId() == QMetaType::QString)
+ return QString(d.toString() + u' ' + t.toString());
+ return {};
}
QVariant QSystemLocalePrivate::measurementSystem()
@@ -442,10 +549,8 @@ QVariant QSystemLocalePrivate::measurementSystem()
wchar_t output[2];
if (getLocaleInfo(LOCALE_IMEASURE, output, 2)) {
- QString iMeasure = QString::fromWCharArray(output);
- if (iMeasure == QLatin1String("1")) {
+ if (output[0] == L'1' && !output[1])
return QLocale::ImperialSystem;
- }
}
return QLocale::MetricSystem;
@@ -453,16 +558,15 @@ QVariant QSystemLocalePrivate::measurementSystem()
QVariant QSystemLocalePrivate::collation()
{
- return getLocaleInfo<QVariant>(LOCALE_SSORTLOCALE);
+ return getLocaleInfo(LOCALE_SSORTLOCALE);
}
QVariant QSystemLocalePrivate::amText()
{
wchar_t output[15]; // maximum length including terminating zero character for Win2003+
- if (getLocaleInfo(LOCALE_S1159, output, 15)) {
- return QString::fromWCharArray(output);
- }
+ if (getLocaleInfo(LOCALE_S1159, output, 15))
+ return nullIfEmpty(QString::fromWCharArray(output));
return QVariant();
}
@@ -471,9 +575,8 @@ QVariant QSystemLocalePrivate::pmText()
{
wchar_t output[15]; // maximum length including terminating zero character for Win2003+
- if (getLocaleInfo(LOCALE_S2359, output, 15)) {
- return QString::fromWCharArray(output);
- }
+ if (getLocaleInfo(LOCALE_S2359, output, 15))
+ return nullIfEmpty(QString::fromWCharArray(output));
return QVariant();
}
@@ -493,12 +596,14 @@ QVariant QSystemLocalePrivate::currencySymbol(QLocale::CurrencySymbolFormat form
wchar_t buf[13];
switch (format) {
case QLocale::CurrencySymbol:
+ // Some locales do have empty currency symbol. All the same, fall back
+ // to CLDR for confirmation if MS claims that applies.
if (getLocaleInfo(LOCALE_SCURRENCY, buf, 13))
- return QString::fromWCharArray(buf);
+ return nullIfEmpty(QString::fromWCharArray(buf));
break;
case QLocale::CurrencyIsoCode:
if (getLocaleInfo(LOCALE_SINTLSYMBOL, buf, 9))
- return QString::fromWCharArray(buf);
+ return nullIfEmpty(QString::fromWCharArray(buf));
break;
case QLocale::CurrencyDisplayName: {
QVarLengthArray<wchar_t, 64> buf(64);
@@ -509,7 +614,7 @@ QVariant QSystemLocalePrivate::currencySymbol(QLocale::CurrencySymbolFormat form
if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size()))
break;
}
- return QString::fromWCharArray(buf.data());
+ return nullIfEmpty(QString::fromWCharArray(buf.data()));
}
default:
break;
@@ -520,31 +625,25 @@ QVariant QSystemLocalePrivate::currencySymbol(QLocale::CurrencySymbolFormat form
QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToStringArgument &arg)
{
QString value;
- switch (arg.value.type()) {
- case QVariant::Int:
- value = QLocaleData::longLongToString(
- QStringLiteral("0"), QStringLiteral(","), QStringLiteral("+"), QStringLiteral("-"),
+ switch (arg.value.typeId()) {
+ case QMetaType::Int:
+ value = QLocaleData::c()->longLongToString(
arg.value.toInt(), -1, 10, -1, QLocale::OmitGroupSeparator);
break;
- case QVariant::UInt:
- value = QLocaleData::unsLongLongToString(
- QStringLiteral("0"), QStringLiteral(","), QStringLiteral("+"),
+ case QMetaType::UInt:
+ value = QLocaleData::c()->unsLongLongToString(
arg.value.toUInt(), -1, 10, -1, QLocale::OmitGroupSeparator);
break;
- case QVariant::Double:
- value = QLocaleData::doubleToString(
- QStringLiteral("0"), QStringLiteral("+"), QStringLiteral("-"),
- QStringLiteral(" "), QStringLiteral(","), QStringLiteral("."),
+ case QMetaType::Double:
+ value = QLocaleData::c()->doubleToString(
arg.value.toDouble(), -1, QLocaleData::DFDecimal, -1, QLocale::OmitGroupSeparator);
break;
- case QVariant::LongLong:
- value = QLocaleData::longLongToString(
- QStringLiteral("0"), QStringLiteral(","), QStringLiteral("+"), QStringLiteral("-"),
+ case QMetaType::LongLong:
+ value = QLocaleData::c()->longLongToString(
arg.value.toLongLong(), -1, 10, -1, QLocale::OmitGroupSeparator);
break;
- case QVariant::ULongLong:
- value = QLocaleData::unsLongLongToString(
- QStringLiteral("0"), QStringLiteral(","), QStringLiteral("+"),
+ case QMetaType::ULongLong:
+ value = QLocaleData::c()->unsLongLongToString(
arg.value.toULongLong(), -1, 10, -1, QLocale::OmitGroupSeparator);
break;
default:
@@ -560,9 +659,9 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS
if (!arg.symbol.isEmpty()) {
format.NumDigits = getLocaleInfo_int(LOCALE_ICURRDIGITS);
format.LeadingZero = getLocaleInfo_int(LOCALE_ILZERO);
- decimalSep = getLocaleInfo(LOCALE_SMONDECIMALSEP);
+ decimalSep = getLocaleInfo(LOCALE_SMONDECIMALSEP).toString();
format.lpDecimalSep = (wchar_t *)decimalSep.utf16();
- thousandSep = getLocaleInfo(LOCALE_SMONTHOUSANDSEP);
+ thousandSep = getLocaleInfo(LOCALE_SMONTHOUSANDSEP).toString();
format.lpThousandSep = (wchar_t *)thousandSep.utf16();
format.NegativeOrder = getLocaleInfo_int(LOCALE_INEGCURR);
format.PositiveOrder = getLocaleInfo_int(LOCALE_ICURRENCY);
@@ -574,8 +673,8 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS
// int(30) == "123456,789.00" == string("3;0;0")
// int(32) == "12,34,56,789.00" == string("3;2;0")
// int(320)== "1234,56,789.00" == string("3;2")
- QString groupingStr = getLocaleInfo(LOCALE_SMONGROUPING);
- format.Grouping = groupingStr.remove(QLatin1Char(';')).toInt();
+ QString groupingStr = getLocaleInfo(LOCALE_SMONGROUPING).toString();
+ format.Grouping = groupingStr.remove(u';').toInt();
if (format.Grouping % 10 == 0) // magic
format.Grouping /= 10;
else
@@ -593,17 +692,29 @@ QVariant QSystemLocalePrivate::toCurrencyString(const QSystemLocale::CurrencyToS
pformat, out.data(), out.size());
}
- value = QString::fromWCharArray(out.data());
- if (substitution() == SAlways)
- substituteDigits( value);
- return value;
+ return nullIfEmpty(correctDigits(QString::fromWCharArray(out.data())));
}
QVariant QSystemLocalePrivate::uiLanguages()
{
+ QStringList result;
+#if QT_CONFIG(cpp_winrt)
+ using namespace winrt;
+ using namespace Windows::System::UserProfile;
+ QT_TRY {
+ auto languages = GlobalizationPreferences::Languages();
+ for (const auto &lang : languages)
+ result << QString::fromStdString(winrt::to_string(lang));
+ } QT_CATCH(...) {
+ // pass, just fall back to WIN32 API implementation
+ }
+ if (!result.isEmpty())
+ return result; // else just fall back to WIN32 API implementation
+#endif // QT_CONFIG(cpp_winrt)
+ // mingw and clang still have to use Win32 API
unsigned long cnt = 0;
QVarLengthArray<wchar_t, 64> buf(64);
-# if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE) // Not present in MinGW 4.9/bootstrap builds.
+# if !defined(QT_BOOTSTRAPPED) // Not present in MinGW 4.9/bootstrap builds.
unsigned long size = buf.size();
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &cnt, buf.data(), &size)) {
size = 0;
@@ -611,11 +722,10 @@ QVariant QSystemLocalePrivate::uiLanguages()
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &cnt, NULL, &size)) {
buf.resize(size);
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &cnt, buf.data(), &size))
- return QStringList();
+ return {};
}
}
-# endif // !QT_BOOTSTRAPPED && !QT_BUILD_QMAKE
- QStringList result;
+# endif // !QT_BOOTSTRAPPED
result.reserve(cnt);
const wchar_t *str = buf.constData();
for (; cnt > 0; --cnt) {
@@ -625,23 +735,23 @@ QVariant QSystemLocalePrivate::uiLanguages()
result.append(s);
str += s.size() + 1;
}
- return result;
+ return nullIfEmpty(std::move(result));
}
QVariant QSystemLocalePrivate::nativeLanguageName()
{
- return getLocaleInfo<QVariant>(LOCALE_SNATIVELANGUAGENAME);
+ return getLocaleInfo(LOCALE_SNATIVELANGUAGENAME);
}
-QVariant QSystemLocalePrivate::nativeCountryName()
+QVariant QSystemLocalePrivate::nativeTerritoryName()
{
- return getLocaleInfo<QVariant>(LOCALE_SNATIVECOUNTRYNAME);
+ return getLocaleInfo(LOCALE_SNATIVECOUNTRYNAME);
}
void QSystemLocalePrivate::update()
{
- lcid = GetUserDefaultLCID();
+ lcid = getDefaultWinId();
substitutionType = SUnknown;
zero.resize(0);
}
@@ -649,20 +759,20 @@ void QSystemLocalePrivate::update()
QString QSystemLocalePrivate::winToQtFormat(QStringView sys_fmt)
{
QString result;
- int i = 0;
+ qsizetype i = 0;
while (i < sys_fmt.size()) {
- if (sys_fmt.at(i).unicode() == QLatin1Char('\'')) {
+ if (sys_fmt.at(i).unicode() == u'\'') {
QString text = qt_readEscapedFormatString(sys_fmt, &i);
- if (text == QLatin1String("'"))
- result += QLatin1String("''");
+ if (text == "'"_L1)
+ result += "''"_L1;
else
- result += QLatin1Char('\'') + text + QLatin1Char('\'');
+ result += u'\'' + text + u'\'';
continue;
}
QChar c = sys_fmt.at(i);
- int repeat = qt_repeatCount(sys_fmt.mid(i));
+ qsizetype repeat = qt_repeatCount(sys_fmt.mid(i));
switch (c.unicode()) {
// Date
@@ -673,13 +783,13 @@ QString QSystemLocalePrivate::winToQtFormat(QStringView sys_fmt)
repeat = 2;
switch (repeat) {
case 1:
- result += QLatin1String("yy"); // "y" unsupported by Qt, use "yy"
+ result += "yy"_L1; // "y" unsupported by Qt, use "yy"
break;
case 5:
- result += QLatin1String("yyyy"); // "yyyyy" same as "yyyy" on Windows
+ result += "yyyy"_L1; // "yyyyy" same as "yyyy" on Windows
break;
default:
- result += QString(repeat, QLatin1Char('y'));
+ result += QString(repeat, u'y');
break;
}
break;
@@ -690,14 +800,14 @@ QString QSystemLocalePrivate::winToQtFormat(QStringView sys_fmt)
case 2:
break; // no equivalent of "gg" in Qt
default:
- result += QLatin1Char('g');
+ result += u'g';
break;
}
break;
case 't':
if (repeat > 2)
repeat = 2;
- result += QLatin1String("AP"); // "t" unsupported, use "AP"
+ result += "AP"_L1; // "t" unsupported, use "AP"
break;
default:
result += QString(repeat, c);
@@ -710,12 +820,12 @@ QString QSystemLocalePrivate::winToQtFormat(QStringView sys_fmt)
return result;
}
-QLocale QSystemLocale::fallbackUiLocale() const
+QLocale QSystemLocale::fallbackLocale() const
{
return QLocale(QString::fromLatin1(getWinLocaleName()));
}
-QVariant QSystemLocale::query(QueryType type, QVariant in) const
+QVariant QSystemLocale::query(QueryType type, QVariant &&in) const
{
QSystemLocalePrivate *d = systemLocalePrivate();
switch(type) {
@@ -743,12 +853,25 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
return d->dayName(in.toInt(), QLocale::LongFormat);
case DayNameShort:
return d->dayName(in.toInt(), QLocale::ShortFormat);
+ case DayNameNarrow:
+ return d->dayName(in.toInt(), QLocale::NarrowFormat);
+ case StandaloneDayNameLong:
+ case StandaloneDayNameShort:
+ case StandaloneDayNameNarrow:
+ // Windows does not provide standalone day names, so fall back to CLDR
+ return QVariant();
case MonthNameLong:
- case StandaloneMonthNameLong:
return d->monthName(in.toInt(), QLocale::LongFormat);
+ case StandaloneMonthNameLong:
+ return d->standaloneMonthName(in.toInt(), QLocale::LongFormat);
case MonthNameShort:
- case StandaloneMonthNameShort:
return d->monthName(in.toInt(), QLocale::ShortFormat);
+ case StandaloneMonthNameShort:
+ return d->standaloneMonthName(in.toInt(), QLocale::ShortFormat);
+ case MonthNameNarrow:
+ case StandaloneMonthNameNarrow:
+ // Windows provides no narrow month names, so we fall back to CLDR
+ return QVariant();
case DateToStringShort:
return d->toString(in.toDate(), QLocale::ShortFormat);
case DateToStringLong:
@@ -765,17 +888,13 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
return d->zeroDigit();
case LanguageId:
case ScriptId:
- case CountryId: {
- QString locale = QString::fromLatin1(getWinLocaleName());
- QLocale::Language lang;
- QLocale::Script script;
- QLocale::Country cntry;
- QLocalePrivate::getLangAndCountry(locale, lang, script, cntry);
+ case TerritoryId: {
+ QLocaleId lid = QLocaleId::fromName(QString::fromLatin1(getWinLocaleName()));
if (type == LanguageId)
- return lang;
+ return lid.language_id;
if (type == ScriptId)
- return script == QLocale::AnyScript ? fallbackUiLocale().script() : script;
- return cntry == QLocale::AnyCountry ? fallbackUiLocale().country() : cntry;
+ return lid.script_id ? lid.script_id : ushort(fallbackLocale().script());
+ return lid.territory_id ? lid.territory_id : ushort(fallbackLocale().territory());
}
case MeasurementSystem:
return d->measurementSystem();
@@ -790,7 +909,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
case CurrencySymbol:
return d->currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
case CurrencyToString:
- return d->toCurrencyString(in.value<QSystemLocale::CurrencyToStringArgument>());
+ return d->toCurrencyString(in.value<CurrencyToStringArgument>());
case UILanguages:
return d->uiLanguages();
case LocaleChanged:
@@ -798,8 +917,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
break;
case NativeLanguageName:
return d->nativeLanguageName();
- case NativeCountryName:
- return d->nativeCountryName();
+ case NativeTerritoryName:
+ return d->nativeTerritoryName();
default:
break;
}
@@ -812,8 +931,18 @@ struct WindowsToISOListElt {
char iso_name[6];
};
-/* NOTE: This array should be sorted by the first column! */
-static const WindowsToISOListElt windows_to_iso_list[] = {
+namespace {
+struct ByWindowsCode {
+ constexpr bool operator()(int lhs, WindowsToISOListElt rhs) const noexcept
+ { return lhs < int(rhs.windows_code); }
+ constexpr bool operator()(WindowsToISOListElt lhs, int rhs) const noexcept
+ { return int(lhs.windows_code) < rhs; }
+ constexpr bool operator()(WindowsToISOListElt lhs, WindowsToISOListElt rhs) const noexcept
+ { return lhs.windows_code < rhs.windows_code; }
+};
+} // unnamed namespace
+
+static constexpr WindowsToISOListElt windows_to_iso_list[] = {
{ 0x0401, "ar_SA" },
{ 0x0402, "bg\0 " },
{ 0x0403, "ca\0 " },
@@ -924,40 +1053,33 @@ static const WindowsToISOListElt windows_to_iso_list[] = {
{ 0x500a, "es_PR" }
};
-static const int windows_to_iso_count
- = sizeof(windows_to_iso_list)/sizeof(WindowsToISOListElt);
+static_assert(q20::is_sorted(std::begin(windows_to_iso_list), std::end(windows_to_iso_list),
+ ByWindowsCode{}));
static const char *winLangCodeToIsoName(int code)
{
int cmp = code - windows_to_iso_list[0].windows_code;
if (cmp < 0)
- return 0;
+ return nullptr;
if (cmp == 0)
return windows_to_iso_list[0].iso_name;
- int begin = 0;
- int end = windows_to_iso_count;
+ const auto it = std::lower_bound(std::begin(windows_to_iso_list),
+ std::end(windows_to_iso_list),
+ code,
+ ByWindowsCode{});
+ if (it != std::end(windows_to_iso_list) && !ByWindowsCode{}(code, *it))
+ return it->iso_name;
- while (end - begin > 1) {
- uint mid = (begin + end)/2;
-
- const WindowsToISOListElt *elt = windows_to_iso_list + mid;
- int cmp = code - elt->windows_code;
- if (cmp < 0)
- end = mid;
- else if (cmp > 0)
- begin = mid;
- else
- return elt->iso_name;
- }
-
- return 0;
+ return nullptr;
}
LCID qt_inIsoNametoLCID(const char *name)
{
+ if (!name)
+ return LOCALE_USER_DEFAULT;
// handle norwegian manually, the list above will fail
if (!strncmp(name, "nb", 2))
return 0x0414;
@@ -994,14 +1116,12 @@ static QString winIso639LangName(LCID id)
lang_code = QString::fromWCharArray(out);
if (!lang_code.isEmpty()) {
- const char *endptr;
- bool ok;
- QByteArray latin1_lang_code = std::move(lang_code).toLatin1();
- int i = qstrtoull(latin1_lang_code, &endptr, 16, &ok);
- if (ok && *endptr == '\0') {
+ const QByteArray latin1 = std::move(lang_code).toLatin1();
+ const auto [i, used] = qstrntoull(latin1.data(), latin1.size(), 16);
+ if (used >= latin1.size() || (used > 0 && latin1[used] == '\0')) {
switch (i) {
case 0x814:
- result = QLatin1String("nn"); // Nynorsk
+ result = u"nn"_s; // Nynorsk
break;
default:
break;
@@ -1034,30 +1154,24 @@ static QByteArray getWinLocaleName(LCID id)
{
QByteArray result;
if (id == LOCALE_USER_DEFAULT) {
- static QByteArray langEnvVar = qgetenv("LANG");
- result = langEnvVar;
- QString lang, script, cntry;
- if ( result == "C" || (!result.isEmpty()
- && qt_splitLocaleName(QString::fromLocal8Bit(result), lang, script, cntry)) ) {
- long id = 0;
- bool ok = false;
- id = qstrtoll(result.data(), 0, 0, &ok);
- if ( !ok || id == 0 || id < INT_MIN || id > INT_MAX )
- return result;
- return winLangCodeToIsoName(int(id));
- }
- }
+ const auto [name, lcid] = scanLangEnv();
+ if (!name.isEmpty())
+ return name;
+ if (lcid)
+ return winLangCodeToIsoName(lcid);
- if (id == LOCALE_USER_DEFAULT)
id = GetUserDefaultLCID();
+ }
+
QString resultusage = winIso639LangName(id);
QString country = winIso3116CtryName(id);
if (!country.isEmpty())
- resultusage += QLatin1Char('_') + country;
+ resultusage += u'_' + country;
return std::move(resultusage).toLatin1();
}
+// Helper for plugins/platforms/windows/
Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id)
{
return QLocale(QString::fromLatin1(getWinLocaleName(id)));
diff --git a/src/corelib/text/qregexp.cpp b/src/corelib/text/qregexp.cpp
deleted file mode 100644
index d7a2434b52..0000000000
--- a/src/corelib/text/qregexp.cpp
+++ /dev/null
@@ -1,5039 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qregexp.h"
-
-#include "qalgorithms.h"
-#include "qbitarray.h"
-#include "qcache.h"
-#include "qdatastream.h"
-#include "qdebug.h"
-#include "qhashfunctions.h"
-#include "qlist.h"
-#include "qmap.h"
-#include "qmutex.h"
-#include "qstring.h"
-#include "qstringlist.h"
-#include "qstringmatcher.h"
-#include "private/qlocking_p.h"
-
-#include <limits.h>
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-// error strings for the regexp parser
-#define RXERR_OK QT_TRANSLATE_NOOP("QRegExp", "no error occurred")
-#define RXERR_DISABLED QT_TRANSLATE_NOOP("QRegExp", "disabled feature used")
-#define RXERR_CHARCLASS QT_TRANSLATE_NOOP("QRegExp", "bad char class syntax")
-#define RXERR_LOOKAHEAD QT_TRANSLATE_NOOP("QRegExp", "bad lookahead syntax")
-#define RXERR_LOOKBEHIND QT_TRANSLATE_NOOP("QRegExp", "lookbehinds not supported, see QTBUG-2371")
-#define RXERR_REPETITION QT_TRANSLATE_NOOP("QRegExp", "bad repetition syntax")
-#define RXERR_OCTAL QT_TRANSLATE_NOOP("QRegExp", "invalid octal value")
-#define RXERR_LEFTDELIM QT_TRANSLATE_NOOP("QRegExp", "missing left delim")
-#define RXERR_END QT_TRANSLATE_NOOP("QRegExp", "unexpected end")
-#define RXERR_LIMIT QT_TRANSLATE_NOOP("QRegExp", "met internal limit")
-#define RXERR_INTERVAL QT_TRANSLATE_NOOP("QRegExp", "invalid interval")
-#define RXERR_CATEGORY QT_TRANSLATE_NOOP("QRegExp", "invalid category")
-
-/*!
- \class QRegExp
- \inmodule QtCore
- \obsolete Use QRegularExpression instead
- \reentrant
- \brief The QRegExp class provides pattern matching using regular expressions.
-
- \ingroup tools
- \ingroup shared
-
- \keyword regular expression
-
- This class is deprecated in Qt 6. Please use QRegularExpression instead
- for all new code. For guidelines on porting old code from QRegExp to
- QRegularExpression, see {Porting to QRegularExpression}
-
- A regular expression, or "regexp", is a pattern for matching
- substrings in a text. This is useful in many contexts, e.g.,
-
- \table
- \row \li Validation
- \li A regexp can test whether a substring meets some criteria,
- e.g. is an integer or contains no whitespace.
- \row \li Searching
- \li A regexp provides more powerful pattern matching than
- simple substring matching, e.g., match one of the words
- \e{mail}, \e{letter} or \e{correspondence}, but none of the
- words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc.
- \row \li Search and Replace
- \li A regexp can replace all occurrences of a substring with a
- different substring, e.g., replace all occurrences of \e{&}
- with \e{\&amp;} except where the \e{&} is already followed by
- an \e{amp;}.
- \row \li String Splitting
- \li A regexp can be used to identify where a string should be
- split apart, e.g. splitting tab-delimited strings.
- \endtable
-
- A brief introduction to regexps is presented, a description of
- Qt's regexp language, some examples, and the function
- documentation itself. QRegExp is modeled on Perl's regexp
- language. It fully supports Unicode. QRegExp can also be used in a
- simpler, \e{wildcard mode} that is similar to the functionality
- found in command shells. The syntax rules used by QRegExp can be
- changed with setPatternSyntax(). In particular, the pattern syntax
- can be set to QRegExp::FixedString, which means the pattern to be
- matched is interpreted as a plain string, i.e., special characters
- (e.g., backslash) are not escaped.
-
- A good text on regexps is \e {Mastering Regular Expressions}
- (Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4.
-
- \note In Qt 5, the new QRegularExpression class provides a Perl
- compatible implementation of regular expressions and is recommended
- in place of QRegExp.
-
- \tableofcontents
-
- \section1 Introduction
-
- Regexps are built up from expressions, quantifiers, and
- assertions. The simplest expression is a character, e.g. \b{x}
- or \b{5}. An expression can also be a set of characters
- enclosed in square brackets. \b{[ABCD]} will match an \b{A}
- or a \b{B} or a \b{C} or a \b{D}. We can write this same
- expression as \b{[A-D]}, and an expression to match any
- capital letter in the English alphabet is written as
- \b{[A-Z]}.
-
- A quantifier specifies the number of occurrences of an expression
- that must be matched. \b{x{1,1}} means match one and only one
- \b{x}. \b{x{1,5}} means match a sequence of \b{x}
- characters that contains at least one \b{x} but no more than
- five.
-
- Note that in general regexps cannot be used to check for balanced
- brackets or tags. For example, a regexp can be written to match an
- opening html \c{<b>} and its closing \c{</b>}, if the \c{<b>} tags
- are not nested, but if the \c{<b>} tags are nested, that same
- regexp will match an opening \c{<b>} tag with the wrong closing
- \c{</b>}. For the fragment \c{<b>bold <b>bolder</b></b>}, the
- first \c{<b>} would be matched with the first \c{</b>}, which is
- not correct. However, it is possible to write a regexp that will
- match nested brackets or tags correctly, but only if the number of
- nesting levels is fixed and known. If the number of nesting levels
- is not fixed and known, it is impossible to write a regexp that
- will not fail.
-
- Suppose we want a regexp to match integers in the range 0 to 99.
- At least one digit is required, so we start with the expression
- \b{[0-9]{1,1}}, which matches a single digit exactly once. This
- regexp matches integers in the range 0 to 9. To match integers up
- to 99, increase the maximum number of occurrences to 2, so the
- regexp becomes \b{[0-9]{1,2}}. This regexp satisfies the
- original requirement to match integers from 0 to 99, but it will
- also match integers that occur in the middle of strings. If we
- want the matched integer to be the whole string, we must use the
- anchor assertions, \b{^} (caret) and \b{$} (dollar). When
- \b{^} is the first character in a regexp, it means the regexp
- must match from the beginning of the string. When \b{$} is the
- last character of the regexp, it means the regexp must match to
- the end of the string. The regexp becomes \b{^[0-9]{1,2}$}.
- Note that assertions, e.g. \b{^} and \b{$}, do not match
- characters but locations in the string.
-
- If you have seen regexps described elsewhere, they may have looked
- different from the ones shown here. This is because some sets of
- characters and some quantifiers are so common that they have been
- given special symbols to represent them. \b{[0-9]} can be
- replaced with the symbol \b{\\d}. The quantifier to match
- exactly one occurrence, \b{{1,1}}, can be replaced with the
- expression itself, i.e. \b{x{1,1}} is the same as \b{x}. So
- our 0 to 99 matcher could be written as \b{^\\d{1,2}$}. It can
- also be written \b{^\\d\\d{0,1}$}, i.e. \e{From the start of
- the string, match a digit, followed immediately by 0 or 1 digits}.
- In practice, it would be written as \b{^\\d\\d?$}. The \b{?}
- is shorthand for the quantifier \b{{0,1}}, i.e. 0 or 1
- occurrences. \b{?} makes an expression optional. The regexp
- \b{^\\d\\d?$} means \e{From the beginning of the string, match
- one digit, followed immediately by 0 or 1 more digit, followed
- immediately by end of string}.
-
- To write a regexp that matches one of the words 'mail' \e or
- 'letter' \e or 'correspondence' but does not match words that
- contain these words, e.g., 'email', 'mailman', 'mailer', and
- 'letterbox', start with a regexp that matches 'mail'. Expressed
- fully, the regexp is \b{m{1,1}a{1,1}i{1,1}l{1,1}}, but because
- a character expression is automatically quantified by
- \b{{1,1}}, we can simplify the regexp to \b{mail}, i.e., an
- 'm' followed by an 'a' followed by an 'i' followed by an 'l'. Now
- we can use the vertical bar \b{|}, which means \b{or}, to
- include the other two words, so our regexp for matching any of the
- three words becomes \b{mail|letter|correspondence}. Match
- 'mail' \b{or} 'letter' \b{or} 'correspondence'. While this
- regexp will match one of the three words we want to match, it will
- also match words we don't want to match, e.g., 'email'. To
- prevent the regexp from matching unwanted words, we must tell it
- to begin and end the match at word boundaries. First we enclose
- our regexp in parentheses, \b{(mail|letter|correspondence)}.
- Parentheses group expressions together, and they identify a part
- of the regexp that we wish to \l{capturing text}{capture}.
- Enclosing the expression in parentheses allows us to use it as a
- component in more complex regexps. It also allows us to examine
- which of the three words was actually matched. To force the match
- to begin and end on word boundaries, we enclose the regexp in
- \b{\\b} \e{word boundary} assertions:
- \b{\\b(mail|letter|correspondence)\\b}. Now the regexp means:
- \e{Match a word boundary, followed by the regexp in parentheses,
- followed by a word boundary}. The \b{\\b} assertion matches a
- \e position in the regexp, not a \e character. A word boundary is
- any non-word character, e.g., a space, newline, or the beginning
- or ending of a string.
-
- If we want to replace ampersand characters with the HTML entity
- \b{\&amp;}, the regexp to match is simply \b{\&}. But this
- regexp will also match ampersands that have already been converted
- to HTML entities. We want to replace only ampersands that are not
- already followed by \b{amp;}. For this, we need the negative
- lookahead assertion, \b{(?!}__\b{)}. The regexp can then be
- written as \b{\&(?!amp;)}, i.e. \e{Match an ampersand that is}
- \b{not} \e{followed by} \b{amp;}.
-
- If we want to count all the occurrences of 'Eric' and 'Eirik' in a
- string, two valid solutions are \b{\\b(Eric|Eirik)\\b} and
- \b{\\bEi?ri[ck]\\b}. The word boundary assertion '\\b' is
- required to avoid matching words that contain either name,
- e.g. 'Ericsson'. Note that the second regexp matches more
- spellings than we want: 'Eric', 'Erik', 'Eiric' and 'Eirik'.
-
- Some of the examples discussed above are implemented in the
- \l{#code-examples}{code examples} section.
-
- \target characters-and-abbreviations-for-sets-of-characters
- \section1 Characters and Abbreviations for Sets of Characters
-
- \table
- \header \li Element \li Meaning
- \row \li \b{c}
- \li A character represents itself unless it has a special
- regexp meaning. e.g. \b{c} matches the character \e c.
- \row \li \b{\\c}
- \li A character that follows a backslash matches the character
- itself, except as specified below. e.g., To match a literal
- caret at the beginning of a string, write \b{\\^}.
- \row \li \b{\\a}
- \li Matches the ASCII bell (BEL, 0x07).
- \row \li \b{\\f}
- \li Matches the ASCII form feed (FF, 0x0C).
- \row \li \b{\\n}
- \li Matches the ASCII line feed (LF, 0x0A, Unix newline).
- \row \li \b{\\r}
- \li Matches the ASCII carriage return (CR, 0x0D).
- \row \li \b{\\t}
- \li Matches the ASCII horizontal tab (HT, 0x09).
- \row \li \b{\\v}
- \li Matches the ASCII vertical tab (VT, 0x0B).
- \row \li \b{\\x\e{hhhh}}
- \li Matches the Unicode character corresponding to the
- hexadecimal number \e{hhhh} (between 0x0000 and 0xFFFF).
- \row \li \b{\\0\e{ooo}} (i.e., \\zero \e{ooo})
- \li matches the ASCII/Latin1 character for the octal number
- \e{ooo} (between 0 and 0377).
- \row \li \b{. (dot)}
- \li Matches any character (including newline).
- \row \li \b{\\d}
- \li Matches a digit (QChar::isDigit()).
- \row \li \b{\\D}
- \li Matches a non-digit.
- \row \li \b{\\s}
- \li Matches a whitespace character (QChar::isSpace()).
- \row \li \b{\\S}
- \li Matches a non-whitespace character.
- \row \li \b{\\w}
- \li Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_').
- \row \li \b{\\W}
- \li Matches a non-word character.
- \row \li \b{\\\e{n}}
- \li The \e{n}-th backreference, e.g. \\1, \\2, etc.
- \endtable
-
- \b{Note:} The C++ compiler transforms backslashes in strings.
- To include a \b{\\} in a regexp, enter it twice, i.e. \c{\\}.
- To match the backslash character itself, enter it four times, i.e.
- \c{\\\\}.
-
- \target sets-of-characters
- \section1 Sets of Characters
-
- Square brackets mean match any character contained in the square
- brackets. The character set abbreviations described above can
- appear in a character set in square brackets. Except for the
- character set abbreviations and the following two exceptions,
- characters do not have special meanings in square brackets.
-
- \table
- \row \li \b{^}
-
- \li The caret negates the character set if it occurs as the
- first character (i.e. immediately after the opening square
- bracket). \b{[abc]} matches 'a' or 'b' or 'c', but
- \b{[^abc]} matches anything \e but 'a' or 'b' or 'c'.
-
- \row \li \b{-}
-
- \li The dash indicates a range of characters. \b{[W-Z]}
- matches 'W' or 'X' or 'Y' or 'Z'.
-
- \endtable
-
- Using the predefined character set abbreviations is more portable
- than using character ranges across platforms and languages. For
- example, \b{[0-9]} matches a digit in Western alphabets but
- \b{\\d} matches a digit in \e any alphabet.
-
- Note: In other regexp documentation, sets of characters are often
- called "character classes".
-
- \target quantifiers
- \section1 Quantifiers
-
- By default, an expression is automatically quantified by
- \b{{1,1}}, i.e. it should occur exactly once. In the following
- list, \b{\e {E}} stands for expression. An expression is a
- character, or an abbreviation for a set of characters, or a set of
- characters in square brackets, or an expression in parentheses.
-
- \table
- \row \li \b{\e {E}?}
-
- \li Matches zero or one occurrences of \e E. This quantifier
- means \e{The previous expression is optional}, because it
- will match whether or not the expression is found. \b{\e
- {E}?} is the same as \b{\e {E}{0,1}}. e.g., \b{dents?}
- matches 'dent' or 'dents'.
-
- \row \li \b{\e {E}+}
-
- \li Matches one or more occurrences of \e E. \b{\e {E}+} is
- the same as \b{\e {E}{1,}}. e.g., \b{0+} matches '0',
- '00', '000', etc.
-
- \row \li \b{\e {E}*}
-
- \li Matches zero or more occurrences of \e E. It is the same
- as \b{\e {E}{0,}}. The \b{*} quantifier is often used
- in error where \b{+} should be used. For example, if
- \b{\\s*$} is used in an expression to match strings that
- end in whitespace, it will match every string because
- \b{\\s*$} means \e{Match zero or more whitespaces followed
- by end of string}. The correct regexp to match strings that
- have at least one trailing whitespace character is
- \b{\\s+$}.
-
- \row \li \b{\e {E}{n}}
-
- \li Matches exactly \e n occurrences of \e E. \b{\e {E}{n}}
- is the same as repeating \e E \e n times. For example,
- \b{x{5}} is the same as \b{xxxxx}. It is also the same
- as \b{\e {E}{n,n}}, e.g. \b{x{5,5}}.
-
- \row \li \b{\e {E}{n,}}
- \li Matches at least \e n occurrences of \e E.
-
- \row \li \b{\e {E}{,m}}
- \li Matches at most \e m occurrences of \e E. \b{\e {E}{,m}}
- is the same as \b{\e {E}{0,m}}.
-
- \row \li \b{\e {E}{n,m}}
- \li Matches at least \e n and at most \e m occurrences of \e E.
- \endtable
-
- To apply a quantifier to more than just the preceding character,
- use parentheses to group characters together in an expression. For
- example, \b{tag+} matches a 't' followed by an 'a' followed by
- at least one 'g', whereas \b{(tag)+} matches at least one
- occurrence of 'tag'.
-
- Note: Quantifiers are normally "greedy". They always match as much
- text as they can. For example, \b{0+} matches the first zero it
- finds and all the consecutive zeros after the first zero. Applied
- to '20005', it matches '2\underline{000}5'. Quantifiers can be made
- non-greedy, see setMinimal().
-
- \target capturing parentheses
- \target backreferences
- \section1 Capturing Text
-
- Parentheses allow us to group elements together so that we can
- quantify and capture them. For example if we have the expression
- \b{mail|letter|correspondence} that matches a string we know
- that \e one of the words matched but not which one. Using
- parentheses allows us to "capture" whatever is matched within
- their bounds, so if we used \b{(mail|letter|correspondence)}
- and matched this regexp against the string "I sent you some email"
- we can use the cap() or capturedTexts() functions to extract the
- matched characters, in this case 'mail'.
-
- We can use captured text within the regexp itself. To refer to the
- captured text we use \e backreferences which are indexed from 1,
- the same as for cap(). For example we could search for duplicate
- words in a string using \b{\\b(\\w+)\\W+\\1\\b} which means match a
- word boundary followed by one or more word characters followed by
- one or more non-word characters followed by the same text as the
- first parenthesized expression followed by a word boundary.
-
- If we want to use parentheses purely for grouping and not for
- capturing we can use the non-capturing syntax, e.g.
- \b{(?:green|blue)}. Non-capturing parentheses begin '(?:' and
- end ')'. In this example we match either 'green' or 'blue' but we
- do not capture the match so we only know whether or not we matched
- but not which color we actually found. Using non-capturing
- parentheses is more efficient than using capturing parentheses
- since the regexp engine has to do less book-keeping.
-
- Both capturing and non-capturing parentheses may be nested.
-
- \target greedy quantifiers
-
- For historical reasons, quantifiers (e.g. \b{*}) that apply to
- capturing parentheses are more "greedy" than other quantifiers.
- For example, \b{a*(a*)} will match "aaa" with cap(1) == "aaa".
- This behavior is different from what other regexp engines do
- (notably, Perl). To obtain a more intuitive capturing behavior,
- specify QRegExp::RegExp2 to the QRegExp constructor or call
- setPatternSyntax(QRegExp::RegExp2).
-
- \target cap_in_a_loop
-
- When the number of matches cannot be determined in advance, a
- common idiom is to use cap() in a loop. For example:
-
- \snippet code/src_corelib_text_qregexp.cpp 0
-
- \target assertions
- \section1 Assertions
-
- Assertions make some statement about the text at the point where
- they occur in the regexp but they do not match any characters. In
- the following list \b{\e {E}} stands for any expression.
-
- \table
- \row \li \b{^}
- \li The caret signifies the beginning of the string. If you
- wish to match a literal \c{^} you must escape it by
- writing \c{\\^}. For example, \b{^#include} will only
- match strings which \e begin with the characters '#include'.
- (When the caret is the first character of a character set it
- has a special meaning, see \l{#sets-of-characters}{Sets of Characters}.)
-
- \row \li \b{$}
- \li The dollar signifies the end of the string. For example
- \b{\\d\\s*$} will match strings which end with a digit
- optionally followed by whitespace. If you wish to match a
- literal \c{$} you must escape it by writing
- \c{\\$}.
-
- \row \li \b{\\b}
- \li A word boundary. For example the regexp
- \b{\\bOK\\b} means match immediately after a word
- boundary (e.g. start of string or whitespace) the letter 'O'
- then the letter 'K' immediately before another word boundary
- (e.g. end of string or whitespace). But note that the
- assertion does not actually match any whitespace so if we
- write \b{(\\bOK\\b)} and we have a match it will only
- contain 'OK' even if the string is "It's \underline{OK} now".
-
- \row \li \b{\\B}
- \li A non-word boundary. This assertion is true wherever
- \b{\\b} is false. For example if we searched for
- \b{\\Bon\\B} in "Left on" the match would fail (space
- and end of string aren't non-word boundaries), but it would
- match in "t\underline{on}ne".
-
- \row \li \b{(?=\e E)}
- \li Positive lookahead. This assertion is true if the
- expression matches at this point in the regexp. For example,
- \b{const(?=\\s+char)} matches 'const' whenever it is
- followed by 'char', as in 'static \underline{const} char *'.
- (Compare with \b{const\\s+char}, which matches 'static
- \underline{const char} *'.)
-
- \row \li \b{(?!\e E)}
- \li Negative lookahead. This assertion is true if the
- expression does not match at this point in the regexp. For
- example, \b{const(?!\\s+char)} matches 'const' \e except
- when it is followed by 'char'.
- \endtable
-
- \target QRegExp wildcard matching
- \section1 Wildcard Matching
-
- Most command shells such as \e bash or \e cmd.exe support "file
- globbing", the ability to identify a group of files by using
- wildcards. The setPatternSyntax() function is used to switch
- between regexp and wildcard mode. Wildcard matching is much
- simpler than full regexps and has only four features:
-
- \table
- \row \li \b{c}
- \li Any character represents itself apart from those mentioned
- below. Thus \b{c} matches the character \e c.
- \row \li \b{?}
- \li Matches any single character. It is the same as
- \b{.} in full regexps.
- \row \li \b{*}
- \li Matches zero or more of any characters. It is the
- same as \b{.*} in full regexps.
- \row \li \b{[...]}
- \li Sets of characters can be represented in square brackets,
- similar to full regexps. Within the character class, like
- outside, backslash has no special meaning.
- \endtable
-
- In the mode Wildcard, the wildcard characters cannot be
- escaped. In the mode WildcardUnix, the character '\\' escapes the
- wildcard.
-
- For example if we are in wildcard mode and have strings which
- contain filenames we could identify HTML files with \b{*.html}.
- This will match zero or more characters followed by a dot followed
- by 'h', 't', 'm' and 'l'.
-
- To test a string against a wildcard expression, use exactMatch().
- For example:
-
- \snippet code/src_corelib_text_qregexp.cpp 1
-
- \target perl-users
- \section1 Notes for Perl Users
-
- Most of the character class abbreviations supported by Perl are
- supported by QRegExp, see \l{#characters-and-abbreviations-for-sets-of-characters}
- {characters and abbreviations for sets of characters}.
-
- In QRegExp, apart from within character classes, \c{^} always
- signifies the start of the string, so carets must always be
- escaped unless used for that purpose. In Perl the meaning of caret
- varies automagically depending on where it occurs so escaping it
- is rarely necessary. The same applies to \c{$} which in
- QRegExp always signifies the end of the string.
-
- QRegExp's quantifiers are the same as Perl's greedy quantifiers
- (but see the \l{greedy quantifiers}{note above}). Non-greedy
- matching cannot be applied to individual quantifiers, but can be
- applied to all the quantifiers in the pattern. For example, to
- match the Perl regexp \b{ro+?m} requires:
-
- \snippet code/src_corelib_text_qregexp.cpp 2
-
- The equivalent of Perl's \c{/i} option is
- setCaseSensitivity(Qt::CaseInsensitive).
-
- Perl's \c{/g} option can be emulated using a \l{#cap_in_a_loop}{loop}.
-
- In QRegExp \b{.} matches any character, therefore all QRegExp
- regexps have the equivalent of Perl's \c{/s} option. QRegExp
- does not have an equivalent to Perl's \c{/m} option, but this
- can be emulated in various ways for example by splitting the input
- into lines or by looping with a regexp that searches for newlines.
-
- Because QRegExp is string oriented, there are no \\A, \\Z, or \\z
- assertions. The \\G assertion is not supported but can be emulated
- in a loop.
-
- Perl's $& is cap(0) or capturedTexts()[0]. There are no QRegExp
- equivalents for $`, $' or $+. Perl's capturing variables, $1, $2,
- ... correspond to cap(1) or capturedTexts()[1], cap(2) or
- capturedTexts()[2], etc.
-
- To substitute a pattern use QString::replace().
-
- Perl's extended \c{/x} syntax is not supported, nor are
- directives, e.g. (?i), or regexp comments, e.g. (?#comment). On
- the other hand, C++'s rules for literal strings can be used to
- achieve the same:
-
- \snippet code/src_corelib_text_qregexp.cpp 3
-
- Both zero-width positive and zero-width negative lookahead
- assertions (?=pattern) and (?!pattern) are supported with the same
- syntax as Perl. Perl's lookbehind assertions, "independent"
- subexpressions and conditional expressions are not supported.
-
- Non-capturing parentheses are also supported, with the same
- (?:pattern) syntax.
-
- See QString::split() and QStringList::join() for equivalents
- to Perl's split and join functions.
-
- Note: because C++ transforms \\'s they must be written \e twice in
- code, e.g. \b{\\b} must be written \b{\\\\b}.
-
- \target code-examples
- \section1 Code Examples
-
- \snippet code/src_corelib_text_qregexp.cpp 4
-
- The third string matches '\underline{6}'. This is a simple validation
- regexp for integers in the range 0 to 99.
-
- \snippet code/src_corelib_text_qregexp.cpp 5
-
- The second string matches '\underline{This_is-OK}'. We've used the
- character set abbreviation '\\S' (non-whitespace) and the anchors
- to match strings which contain no whitespace.
-
- In the following example we match strings containing 'mail' or
- 'letter' or 'correspondence' but only match whole words i.e. not
- 'email'
-
- \snippet code/src_corelib_text_qregexp.cpp 6
-
- The second string matches "Please write the \underline{letter}". The
- word 'letter' is also captured (because of the parentheses). We
- can see what text we've captured like this:
-
- \snippet code/src_corelib_text_qregexp.cpp 7
-
- This will capture the text from the first set of capturing
- parentheses (counting capturing left parentheses from left to
- right). The parentheses are counted from 1 since cap(0) is the
- whole matched regexp (equivalent to '&' in most regexp engines).
-
- \snippet code/src_corelib_text_qregexp.cpp 8
-
- Here we've passed the QRegExp to QString's replace() function to
- replace the matched text with new text.
-
- \snippet code/src_corelib_text_qregexp.cpp 9
-
- We've used the indexIn() function to repeatedly match the regexp in
- the string. Note that instead of moving forward by one character
- at a time \c pos++ we could have written \c {pos +=
- rx.matchedLength()} to skip over the already matched string. The
- count will equal 3, matching 'One \underline{Eric} another
- \underline{Eirik}, and an Ericsson. How many Eiriks, \underline{Eric}?'; it
- doesn't match 'Ericsson' or 'Eiriks' because they are not bounded
- by non-word boundaries.
-
- One common use of regexps is to split lines of delimited data into
- their component fields.
-
- \snippet code/src_corelib_text_qregexp.cpp 10
-
- In this example our input lines have the format company name, web
- address and country. Unfortunately the regexp is rather long and
- not very versatile -- the code will break if we add any more
- fields. A simpler and better solution is to look for the
- separator, '\\t' in this case, and take the surrounding text. The
- QString::split() function can take a separator string or regexp
- as an argument and split a string accordingly.
-
- \snippet code/src_corelib_text_qregexp.cpp 11
-
- Here field[0] is the company, field[1] the web address and so on.
-
- To imitate the matching of a shell we can use wildcard mode.
-
- \snippet code/src_corelib_text_qregexp.cpp 12
-
- Wildcard matching can be convenient because of its simplicity, but
- any wildcard regexp can be defined using full regexps, e.g.
- \b{.*\\.html$}. Notice that we can't match both \c .html and \c
- .htm files with a wildcard unless we use \b{*.htm*} which will
- also match 'test.html.bak'. A full regexp gives us the precision
- we need, \b{.*\\.html?$}.
-
- QRegExp can match case insensitively using setCaseSensitivity(),
- and can use non-greedy matching, see setMinimal(). By
- default QRegExp uses full regexps but this can be changed with
- setPatternSyntax(). Searching can be done forward with indexIn() or backward
- with lastIndexIn(). Captured text can be accessed using
- capturedTexts() which returns a string list of all captured
- strings, or using cap() which returns the captured string for the
- given index. The pos() function takes a match index and returns
- the position in the string where the match was made (or -1 if
- there was no match).
-
- \sa QString, QStringList, QSortFilterProxyModel,
- {tools/regexp}{Regular Expression Example}
-
-
- \section1 Porting to QRegularExpression
-
- The QRegularExpression class introduced in Qt 5 is a big improvement upon
- QRegExp, in terms of APIs offered, supported pattern syntax and speed of
- execution. The biggest difference is that QRegularExpression simply holds a
- regular expression, and it's \e{not} modified when a match is requested.
- Instead, a QRegularExpressionMatch object is returned, in order to check
- the result of a match and extract the captured substring. The same applies
- with global matching and QRegularExpressionMatchIterator.
-
- Other differences are outlined below.
-
- \section2 Different pattern syntax
-
- Porting a regular expression from QRegExp to QRegularExpression may require
- changes to the pattern itself.
-
- In certain scenarios, QRegExp was too lenient and accepted patterns that
- are simply invalid when using QRegularExpression. These are somehow easy
- to detect, because the QRegularExpression objects built with these patterns
- are not valid (cf. QRegularExpression::isValid()).
-
- In other cases, a pattern ported from QRegExp to QRegularExpression may
- silently change semantics. Therefore, it is necessary to review the
- patterns used. The most notable cases of silent incompatibility are:
-
- \list
-
- \li Curly braces are needed in order to use a hexadecimal escape like
- \c{\xHHHH} with more than 2 digits. A pattern like \c{\x2022} neeeds to
- be ported to \c{\x{2022}}, or it will match a space (\c{0x20}) followed
- by the string \c{"22"}. In general, it is highly recommended to always use
- curly braces with the \c{\x} escape, no matter the amount of digits
- specified.
-
- \li A 0-to-n quantification like \c{{,n}} needs to be ported to \c{{0,n}} to
- preserve semantics. Otherwise, a pattern such as \c{\d{,3}} would
- actually match a digit followed by the exact string \c{"{,3}"}.
-
- \li QRegExp by default does Unicode-aware matching, while
- QRegularExpression requires a separate option; see below for more details.
-
- \li c{.} in QRegExp does by default match all characters, including the
- newline character. QRegularExpression excludes the newline character by
- default. To include the newline character, set the
- QRegularExpression::DotMatchesEverythingOption pattern option.
-
- \endlist
-
- \section2 Porting from QRegExp::exactMatch()
-
- QRegExp::exactMatch() in Qt 4 served two purposes: it exactly matched
- a regular expression against a subject string, and it implemented partial
- matching.
-
- \section3 Porting from QRegExp's Exact Matching
-
- Exact matching indicates whether the regular expression matches the entire
- subject string. For example, the classes yield on the subject string \c{"abc123"}:
-
- \table
- \header \li \li QRegExp::exactMatch() \li QRegularExpressionMatch::hasMatch()
- \row \li \c{"\\d+"} \li \b false \li \b true
- \row \li \c{"[a-z]+\\d+"} \li \b true \li \b true
- \endtable
-
- Exact matching is not reflected in QRegularExpression. If you want
- to be sure that the subject string matches the regular expression
- exactly, you can wrap the pattern using the QRegularExpression::anchoredPattern()
- function:
-
- \snippet code/src_corelib_text_qregexp.cpp 21
-
- \section3 Porting from QRegExp's Partial Matching
-
- When using QRegExp::exactMatch(), if an exact match was not found, one
- could still find out how much of the subject string was matched by the
- regular expression by calling QRegExp::matchedLength(). If the returned length
- was equal to the subject string's length, then one could conclude that a partial
- match was found.
-
- QRegularExpression supports partial matching explicitly by means of the
- appropriate MatchType.
-
- \section2 Global matching
-
- Due to limitations of the QRegExp API it was impossible to implement global
- matching correctly (that is, like Perl does). In particular, patterns that
- can match 0 characters (like \c{"a*"}) are problematic.
-
- QRegularExpression::globalMatch() implements Perl global match correctly, and
- the returned iterator can be used to examine each result.
-
- \section2 Unicode properties support
-
- When using QRegExp, character classes such as \c{\w}, \c{\d}, etc. match
- characters with the corresponding Unicode property: for instance, \c{\d}
- matches any character with the Unicode Nd (decimal digit) property.
-
- Those character classes only match ASCII characters by default when using
- QRegularExpression: for instance, \c{\d} matches exactly a character in the
- \c{0-9} ASCII range. It is possible to change this behavior by using the
- UseUnicodePropertiesOption pattern option.
-
- \section2 Wildcard matching
-
- There is no direct way to do wildcard matching in QRegularExpression.
- However, the wildcardToRegularExpression method is provided to translate
- glob patterns into a Perl-compatible regular expression that can be used
- for that purpose.
-
- \section2 Other pattern syntaxes
-
- QRegularExpression supports only Perl-compatible regular expressions.
-
- \section2 Minimal matching
-
- QRegExp::setMinimal() implemented minimal matching by simply reversing the
- greediness of the quantifiers (QRegExp did not support lazy quantifiers,
- like \c{*?}, \c{+?}, etc.). QRegularExpression instead does support greedy,
- lazy and possessive quantifiers. The InvertedGreedinessOption
- pattern option can be useful to emulate the effects of QRegExp::setMinimal():
- if enabled, it inverts the greediness of quantifiers (greedy ones become
- lazy and vice versa).
-
- \section2 Caret modes
-
- The AnchorAtOffsetMatchOption match option can be used to emulate the
- QRegExp::CaretAtOffset behavior. There is no equivalent for the other
- QRegExp::CaretMode modes.
-*/
-
-#if defined(Q_OS_VXWORKS) && defined(EOS)
-# undef EOS
-#endif
-
-const int NumBadChars = 64;
-#define BadChar(ch) ((ch).unicode() % NumBadChars)
-
-const int NoOccurrence = INT_MAX;
-const int EmptyCapture = INT_MAX;
-const int InftyLen = INT_MAX;
-const int InftyRep = 1025;
-const int EOS = -1;
-
-static bool isWord(QChar ch)
-{
- return ch.isLetterOrNumber() || ch.isMark() || ch == QLatin1Char('_');
-}
-
-/*
- Merges two vectors of ints and puts the result into the first
- one.
-*/
-static void mergeInto(QList<int> *a, const QList<int> &b)
-{
- int asize = a->size();
- int bsize = b.size();
- if (asize == 0) {
- *a = b;
-#ifndef QT_NO_REGEXP_OPTIM
- } else if (bsize == 1 && a->at(asize - 1) < b.at(0)) {
- a->resize(asize + 1);
- (*a)[asize] = b.at(0);
-#endif
- } else if (bsize >= 1) {
- int csize = asize + bsize;
- QList<int> c(csize);
- int i = 0, j = 0, k = 0;
- while (i < asize) {
- if (j < bsize) {
- if (a->at(i) == b.at(j)) {
- ++i;
- --csize;
- } else if (a->at(i) < b.at(j)) {
- c[k++] = a->at(i++);
- } else {
- c[k++] = b.at(j++);
- }
- } else {
- memcpy(c.data() + k, a->constData() + i, (asize - i) * sizeof(int));
- break;
- }
- }
- c.resize(csize);
- if (j < bsize)
- memcpy(c.data() + k, b.constData() + j, (bsize - j) * sizeof(int));
- *a = c;
- }
-}
-
-#ifndef QT_NO_REGEXP_WILDCARD
-/*
- Translates a wildcard pattern to an equivalent regular expression
- pattern (e.g., *.cpp to .*\.cpp).
-
- If enableEscaping is true, it is possible to escape the wildcard
- characters with \
-*/
-static QString wc2rx(const QString &wc_str, const bool enableEscaping)
-{
- const int wclen = wc_str.length();
- QString rx;
- int i = 0;
- bool isEscaping = false; // the previous character is '\'
- const QChar *wc = wc_str.unicode();
-
- while (i < wclen) {
- const QChar c = wc[i++];
- switch (c.unicode()) {
- case '\\':
- if (enableEscaping) {
- if (isEscaping) {
- rx += QLatin1String("\\\\");
- } // we insert the \\ later if necessary
- if (i == wclen) { // the end
- rx += QLatin1String("\\\\");
- }
- } else {
- rx += QLatin1String("\\\\");
- }
- isEscaping = true;
- break;
- case '*':
- if (isEscaping) {
- rx += QLatin1String("\\*");
- isEscaping = false;
- } else {
- rx += QLatin1String(".*");
- }
- break;
- case '?':
- if (isEscaping) {
- rx += QLatin1String("\\?");
- isEscaping = false;
- } else {
- rx += QLatin1Char('.');
- }
-
- break;
- case '$':
- case '(':
- case ')':
- case '+':
- case '.':
- case '^':
- case '{':
- case '|':
- case '}':
- if (isEscaping) {
- isEscaping = false;
- rx += QLatin1String("\\\\");
- }
- rx += QLatin1Char('\\');
- rx += c;
- break;
- case '[':
- if (isEscaping) {
- isEscaping = false;
- rx += QLatin1String("\\[");
- } else {
- rx += c;
- if (wc[i] == QLatin1Char('^'))
- rx += wc[i++];
- if (i < wclen) {
- if (wc[i] == QLatin1Char(']'))
- rx += wc[i++];
- while (i < wclen && wc[i] != QLatin1Char(']')) {
- if (wc[i] == QLatin1Char('\\'))
- rx += QLatin1Char('\\');
- rx += wc[i++];
- }
- }
- }
- break;
-
- case ']':
- if(isEscaping){
- isEscaping = false;
- rx += QLatin1String("\\");
- }
- rx += c;
- break;
-
- default:
- if(isEscaping){
- isEscaping = false;
- rx += QLatin1String("\\\\");
- }
- rx += c;
- }
- }
- return rx;
-}
-#endif
-
-static int caretIndex(int offset, QRegExp::CaretMode caretMode)
-{
- if (caretMode == QRegExp::CaretAtZero) {
- return 0;
- } else if (caretMode == QRegExp::CaretAtOffset) {
- return offset;
- } else { // QRegExp::CaretWontMatch
- return -1;
- }
-}
-
-/*
- The QRegExpEngineKey struct uniquely identifies an engine.
-*/
-struct QRegExpEngineKey
-{
- QString pattern;
- QRegExp::PatternSyntax patternSyntax;
- Qt::CaseSensitivity cs;
-
- inline QRegExpEngineKey(const QString &pattern, QRegExp::PatternSyntax patternSyntax,
- Qt::CaseSensitivity cs)
- : pattern(pattern), patternSyntax(patternSyntax), cs(cs) {}
-
- inline void clear() {
- pattern.clear();
- patternSyntax = QRegExp::RegExp;
- cs = Qt::CaseSensitive;
- }
-};
-
-static bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2)
-{
- return key1.pattern == key2.pattern && key1.patternSyntax == key2.patternSyntax
- && key1.cs == key2.cs;
-}
-
-static size_t qHash(const QRegExpEngineKey &key, size_t seed = 0) noexcept
-{
- return qHashMulti(seed, key.pattern, key.patternSyntax, key.cs);
-}
-
-class QRegExpEngine;
-
-/*
- This is the engine state during matching.
-*/
-struct QRegExpMatchState
-{
- const QChar *in; // a pointer to the input string data
- int pos; // the current position in the string
- int caretPos;
- int len; // the length of the input string
- bool minimal; // minimal matching?
- int *bigArray; // big array holding the data for the next pointers
- int *inNextStack; // is state is nextStack?
- int *curStack; // stack of current states
- int *nextStack; // stack of next states
- int *curCapBegin; // start of current states' captures
- int *nextCapBegin; // start of next states' captures
- int *curCapEnd; // end of current states' captures
- int *nextCapEnd; // end of next states' captures
- int *tempCapBegin; // start of temporary captures
- int *tempCapEnd; // end of temporary captures
- int *capBegin; // start of captures for a next state
- int *capEnd; // end of captures for a next state
- int *slideTab; // bump-along slide table for bad-character heuristic
- int *captured; // what match() returned last
- int slideTabSize; // size of slide table
- int capturedSize;
-#ifndef QT_NO_REGEXP_BACKREF
- QList<QList<int>> sleeping; // list of back-reference sleepers
-#endif
- int matchLen; // length of match
- int oneTestMatchedLen; // length of partial match
-
- const QRegExpEngine *eng;
-
- inline QRegExpMatchState() : bigArray(nullptr), captured(nullptr) {}
- inline ~QRegExpMatchState() { free(bigArray); }
-
- void drain() { free(bigArray); bigArray = nullptr; captured = nullptr; } // to save memory
- void prepareForMatch(QRegExpEngine *eng);
- void match(const QChar *str, int len, int pos, bool minimal,
- bool oneTest, int caretIndex);
- bool matchHere();
- bool testAnchor(int i, int a, const int *capBegin);
-};
-
-/*
- The struct QRegExpAutomatonState represents one state in a modified NFA. The
- input characters matched are stored in the state instead of on
- the transitions, something possible for an automaton
- constructed from a regular expression.
-*/
-struct QRegExpAutomatonState
-{
-#ifndef QT_NO_REGEXP_CAPTURE
- int atom; // which atom does this state belong to?
-#endif
- int match; // what does it match? (see CharClassBit and BackRefBit)
- QList<int> outs; // out-transitions
- QMap<int, int> reenter; // atoms reentered when transiting out
- QMap<int, int> anchors; // anchors met when transiting out
-
- inline QRegExpAutomatonState() { }
-#ifndef QT_NO_REGEXP_CAPTURE
- inline QRegExpAutomatonState(int a, int m)
- : atom(a), match(m) { }
-#else
- inline QRegExpAutomatonState(int m)
- : match(m) { }
-#endif
-};
-
-Q_DECLARE_TYPEINFO(QRegExpAutomatonState, Q_MOVABLE_TYPE);
-
-/*
- The struct QRegExpCharClassRange represents a range of characters (e.g.,
- [0-9] denotes range 48 to 57).
-*/
-struct QRegExpCharClassRange
-{
- ushort from; // 48
- ushort len; // 10
-};
-
-Q_DECLARE_TYPEINFO(QRegExpCharClassRange, Q_PRIMITIVE_TYPE);
-
-#ifndef QT_NO_REGEXP_CAPTURE
-/*
- The struct QRegExpAtom represents one node in the hierarchy of regular
- expression atoms.
-*/
-struct QRegExpAtom
-{
- enum { NoCapture = -1, OfficialCapture = -2, UnofficialCapture = -3 };
-
- int parent; // index of parent in array of atoms
- int capture; // index of capture, from 1 to ncap - 1
-};
-
-Q_DECLARE_TYPEINFO(QRegExpAtom, Q_PRIMITIVE_TYPE);
-#endif
-
-struct QRegExpLookahead;
-
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
-/*
- The struct QRegExpAnchorAlternation represents a pair of anchors with
- OR semantics.
-*/
-struct QRegExpAnchorAlternation
-{
- int a; // this anchor...
- int b; // ...or this one
-};
-
-Q_DECLARE_TYPEINFO(QRegExpAnchorAlternation, Q_PRIMITIVE_TYPE);
-#endif
-
-#ifndef QT_NO_REGEXP_CCLASS
-
-#define FLAG(x) (1 << (x))
-/*
- The class QRegExpCharClass represents a set of characters, such as can
- be found in regular expressions (e.g., [a-z] denotes the set
- {a, b, ..., z}).
-*/
-class QRegExpCharClass
-{
-public:
- QRegExpCharClass();
-
- void clear();
- bool negative() const { return n; }
- void setNegative(bool negative);
- void addCategories(uint cats);
- void addRange(ushort from, ushort to);
- void addSingleton(ushort ch) { addRange(ch, ch); }
-
- bool in(QChar ch) const;
-#ifndef QT_NO_REGEXP_OPTIM
- const QList<int> &firstOccurrence() const { return occ1; }
-#endif
-
-#if defined(QT_DEBUG)
- void dump() const;
-#endif
-
-private:
- QList<QRegExpCharClassRange> r; // character ranges
-#ifndef QT_NO_REGEXP_OPTIM
- QList<int> occ1; // first-occurrence array
-#endif
- uint c; // character classes
- bool n; // negative?
-};
-#else
-struct QRegExpCharClass
-{
- int dummy;
-
-#ifndef QT_NO_REGEXP_OPTIM
- QRegExpCharClass() { occ1.fill(0, NumBadChars); }
-
- const QList<int> &firstOccurrence() const { return occ1; }
- QList<int> occ1;
-#endif
-};
-#endif
-
-Q_DECLARE_TYPEINFO(QRegExpCharClass, Q_MOVABLE_TYPE);
-
-/*
- The QRegExpEngine class encapsulates a modified nondeterministic
- finite automaton (NFA).
-*/
-class QRegExpEngine
-{
-public:
- QRegExpEngine(Qt::CaseSensitivity cs, bool greedyQuantifiers)
- : cs(cs), greedyQuantifiers(greedyQuantifiers) { setup(); }
-
- QRegExpEngine(const QRegExpEngineKey &key);
- ~QRegExpEngine();
-
- bool isValid() const { return valid; }
- const QString &errorString() const { return yyError; }
- int captureCount() const { return officialncap; }
-
- int createState(QChar ch);
- int createState(const QRegExpCharClass &cc);
-#ifndef QT_NO_REGEXP_BACKREF
- int createState(int bref);
-#endif
-
- void addCatTransitions(const QList<int> &from, const QList<int> &to);
-#ifndef QT_NO_REGEXP_CAPTURE
- void addPlusTransitions(const QList<int> &from, const QList<int> &to, int atom);
-#endif
-
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
- int anchorAlternation(int a, int b);
- int anchorConcatenation(int a, int b);
-#else
- int anchorAlternation(int a, int b) { return a & b; }
- int anchorConcatenation(int a, int b) { return a | b; }
-#endif
- void addAnchors(int from, int to, int a);
-
-#ifndef QT_NO_REGEXP_OPTIM
- void heuristicallyChooseHeuristic();
-#endif
-
-#if defined(QT_DEBUG)
- void dump() const;
-#endif
-
- QAtomicInt ref;
-
-private:
- enum { CharClassBit = 0x10000, BackRefBit = 0x20000 };
- enum { InitialState = 0, FinalState = 1 };
-
- void setup();
- int setupState(int match);
-
- /*
- Let's hope that 13 lookaheads and 14 back-references are
- enough.
- */
- enum { MaxLookaheads = 13, MaxBackRefs = 14 };
- enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, Anchor_Word = 0x00000004,
- Anchor_NonWord = 0x00000008, Anchor_FirstLookahead = 0x00000010,
- Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads,
- Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1,
- Anchor_Alternation = unsigned(Anchor_BackRef1Empty) << MaxBackRefs,
-
- Anchor_LookaheadMask = (Anchor_FirstLookahead - 1) ^
- ((Anchor_FirstLookahead << MaxLookaheads) - 1) };
-#ifndef QT_NO_REGEXP_CAPTURE
- int startAtom(bool officialCapture);
- void finishAtom(int atom, bool needCapture);
-#endif
-
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- int addLookahead(QRegExpEngine *eng, bool negative);
-#endif
-
-#ifndef QT_NO_REGEXP_OPTIM
- bool goodStringMatch(QRegExpMatchState &matchState) const;
- bool badCharMatch(QRegExpMatchState &matchState) const;
-#else
- bool bruteMatch(QRegExpMatchState &matchState) const;
-#endif
-
- QList<QRegExpAutomatonState> s; // array of states
-#ifndef QT_NO_REGEXP_CAPTURE
- QList<QRegExpAtom> f; // atom hierarchy
- int nf; // number of atoms
- int cf; // current atom
- QList<int> captureForOfficialCapture;
-#endif
- int officialncap; // number of captures, seen from the outside
- int ncap; // number of captures, seen from the inside
-#ifndef QT_NO_REGEXP_CCLASS
- QList<QRegExpCharClass> cl; // array of character classes
-#endif
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- QList<QRegExpLookahead *> ahead; // array of lookaheads
-#endif
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
- QList<QRegExpAnchorAlternation> aa; // array of (a, b) pairs of anchors
-#endif
-#ifndef QT_NO_REGEXP_OPTIM
- bool caretAnchored; // does the regexp start with ^?
- bool trivial; // is the good-string all that needs to match?
-#endif
- bool valid; // is the regular expression valid?
- Qt::CaseSensitivity cs; // case sensitive?
- bool greedyQuantifiers; // RegExp2?
- bool xmlSchemaExtensions;
-#ifndef QT_NO_REGEXP_BACKREF
- int nbrefs; // number of back-references
-#endif
-
-#ifndef QT_NO_REGEXP_OPTIM
- bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch
-
- int goodEarlyStart; // the index where goodStr can first occur in a match
- int goodLateStart; // the index where goodStr can last occur in a match
- QString goodStr; // the string that any match has to contain
-
- int minl; // the minimum length of a match
- QList<int> occ1; // first-occurrence array
-#endif
-
- /*
- The class Box is an abstraction for a regular expression
- fragment. It can also be seen as one node in the syntax tree of
- a regular expression with synthetized attributes.
-
- Its interface is ugly for performance reasons.
- */
- class Box
- {
- public:
- Box(QRegExpEngine *engine);
- Box(const Box &b) { operator=(b); }
-
- Box &operator=(const Box &b);
-
- void clear() { operator=(Box(eng)); }
- void set(QChar ch);
- void set(const QRegExpCharClass &cc);
-#ifndef QT_NO_REGEXP_BACKREF
- void set(int bref);
-#endif
-
- void cat(const Box &b);
- void orx(const Box &b);
- void plus(int atom);
- void opt();
- void catAnchor(int a);
-#ifndef QT_NO_REGEXP_OPTIM
- void setupHeuristics();
-#endif
-
-#if defined(QT_DEBUG)
- void dump() const;
-#endif
-
- private:
- void addAnchorsToEngine(const Box &to) const;
-
- QRegExpEngine *eng; // the automaton under construction
- QList<int> ls; // the left states (firstpos)
- QList<int> rs; // the right states (lastpos)
- QMap<int, int> lanchors; // the left anchors
- QMap<int, int> ranchors; // the right anchors
- int skipanchors; // the anchors to match if the box is skipped
-
-#ifndef QT_NO_REGEXP_OPTIM
- int earlyStart; // the index where str can first occur
- int lateStart; // the index where str can last occur
- QString str; // a string that has to occur in any match
- QString leftStr; // a string occurring at the left of this box
- QString rightStr; // a string occurring at the right of this box
- int maxl; // the maximum length of this box (possibly InftyLen)
-#endif
-
- int minl; // the minimum length of this box
-#ifndef QT_NO_REGEXP_OPTIM
- QList<int> occ1; // first-occurrence array
-#endif
- };
-
- friend class Box;
-
- /*
- This is the lexical analyzer for regular expressions.
- */
- enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen, Tok_PosLookahead,
- Tok_NegLookahead, Tok_RightParen, Tok_CharClass, Tok_Caret, Tok_Quantifier, Tok_Bar,
- Tok_Word, Tok_NonWord, Tok_Char = 0x10000, Tok_BackRef = 0x20000 };
- int getChar();
- int getEscape();
-#ifndef QT_NO_REGEXP_INTERVAL
- int getRep(int def);
-#endif
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- void skipChars(int n);
-#endif
- void error(const char *msg);
- void startTokenizer(const QChar *rx, int len);
- int getToken();
-
- const QChar *yyIn; // a pointer to the input regular expression pattern
- int yyPos0; // the position of yyTok in the input pattern
- int yyPos; // the position of the next character to read
- int yyLen; // the length of yyIn
- int yyCh; // the last character read
- QScopedPointer<QRegExpCharClass> yyCharClass; // attribute for Tok_CharClass tokens
- int yyMinRep; // attribute for Tok_Quantifier
- int yyMaxRep; // ditto
- QString yyError; // syntax error or overflow during parsing?
-
- /*
- This is the syntactic analyzer for regular expressions.
- */
- int parse(const QChar *rx, int len);
- void parseAtom(Box *box);
- void parseFactor(Box *box);
- void parseTerm(Box *box);
- void parseExpression(Box *box);
-
- int yyTok; // the last token read
- bool yyMayCapture; // set this to false to disable capturing
-
- friend struct QRegExpMatchState;
-};
-
-#ifndef QT_NO_REGEXP_LOOKAHEAD
-/*
- The struct QRegExpLookahead represents a lookahead a la Perl (e.g.,
- (?=foo) and (?!bar)).
-*/
-struct QRegExpLookahead
-{
- QRegExpEngine *eng; // NFA representing the embedded regular expression
- bool neg; // negative lookahead?
-
- inline QRegExpLookahead(QRegExpEngine *eng0, bool neg0)
- : eng(eng0), neg(neg0) { }
- inline ~QRegExpLookahead() { delete eng; }
-};
-#endif
-
-/*!
- \internal
- convert the pattern string to the RegExp syntax.
-
- This is also used by QScriptEngine::newRegExp to convert to a pattern that JavaScriptCore can understan
- */
-Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &pattern, QRegExp::PatternSyntax patternSyntax)
-{
- switch (patternSyntax) {
-#ifndef QT_NO_REGEXP_WILDCARD
- case QRegExp::Wildcard:
- return wc2rx(pattern, false);
- case QRegExp::WildcardUnix:
- return wc2rx(pattern, true);
-#endif
- case QRegExp::FixedString:
- return QRegExp::escape(pattern);
- case QRegExp::W3CXmlSchema11:
- default:
- return pattern;
- }
-}
-
-QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key)
- : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2),
- xmlSchemaExtensions(key.patternSyntax == QRegExp::W3CXmlSchema11)
-{
- setup();
-
- QString rx = qt_regexp_toCanonical(key.pattern, key.patternSyntax);
-
- valid = (parse(rx.unicode(), rx.length()) == rx.length());
- if (!valid) {
-#ifndef QT_NO_REGEXP_OPTIM
- trivial = false;
-#endif
- error(RXERR_LEFTDELIM);
- }
-}
-
-QRegExpEngine::~QRegExpEngine()
-{
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- qDeleteAll(ahead);
-#endif
-}
-
-void QRegExpMatchState::prepareForMatch(QRegExpEngine *eng)
-{
- /*
- We use one QList<int> for all the big data used a lot in
- matchHere() and friends.
- */
- int ns = eng->s.size(); // number of states
- int ncap = eng->ncap;
-#ifndef QT_NO_REGEXP_OPTIM
- int newSlideTabSize = qMax(eng->minl + 1, 16);
-#else
- int newSlideTabSize = 0;
-#endif
- int numCaptures = eng->captureCount();
- int newCapturedSize = 2 + 2 * numCaptures;
- bigArray = q_check_ptr((int *)realloc(bigArray, ((3 + 4 * ncap) * ns + 4 * ncap + newSlideTabSize + newCapturedSize)*sizeof(int)));
-
- // set all internal variables only _after_ bigArray is realloc'ed
- // to prevent a broken regexp in oom case
-
- slideTabSize = newSlideTabSize;
- capturedSize = newCapturedSize;
- inNextStack = bigArray;
- memset(inNextStack, -1, ns * sizeof(int));
- curStack = inNextStack + ns;
- nextStack = inNextStack + 2 * ns;
-
- curCapBegin = inNextStack + 3 * ns;
- nextCapBegin = curCapBegin + ncap * ns;
- curCapEnd = curCapBegin + 2 * ncap * ns;
- nextCapEnd = curCapBegin + 3 * ncap * ns;
-
- tempCapBegin = curCapBegin + 4 * ncap * ns;
- tempCapEnd = tempCapBegin + ncap;
- capBegin = tempCapBegin + 2 * ncap;
- capEnd = tempCapBegin + 3 * ncap;
-
- slideTab = tempCapBegin + 4 * ncap;
- captured = slideTab + slideTabSize;
- memset(captured, -1, capturedSize*sizeof(int));
- this->eng = eng;
-}
-
-/*
- Tries to match in str and returns an array of (begin, length) pairs
- for captured text. If there is no match, all pairs are (-1, -1).
-*/
-void QRegExpMatchState::match(const QChar *str0, int len0, int pos0,
- bool minimal0, bool oneTest, int caretIndex)
-{
- bool matched = false;
- QChar char_null;
-
-#ifndef QT_NO_REGEXP_OPTIM
- if (eng->trivial && !oneTest) {
- // ### Qt6: qsizetype
- pos = int(QtPrivate::findString(QStringView(str0, len0), pos0, QStringView(eng->goodStr.unicode(), eng->goodStr.length()), eng->cs));
- matchLen = eng->goodStr.length();
- matched = (pos != -1);
- } else
-#endif
- {
- in = str0;
- if (in == nullptr)
- in = &char_null;
- pos = pos0;
- caretPos = caretIndex;
- len = len0;
- minimal = minimal0;
- matchLen = 0;
- oneTestMatchedLen = 0;
-
- if (eng->valid && pos >= 0 && pos <= len) {
-#ifndef QT_NO_REGEXP_OPTIM
- if (oneTest) {
- matched = matchHere();
- } else {
- if (pos <= len - eng->minl) {
- if (eng->caretAnchored) {
- matched = matchHere();
- } else if (eng->useGoodStringHeuristic) {
- matched = eng->goodStringMatch(*this);
- } else {
- matched = eng->badCharMatch(*this);
- }
- }
- }
-#else
- matched = oneTest ? matchHere() : eng->bruteMatch(*this);
-#endif
- }
- }
-
- if (matched) {
- int *c = captured;
- *c++ = pos;
- *c++ = matchLen;
-
- int numCaptures = (capturedSize - 2) >> 1;
-#ifndef QT_NO_REGEXP_CAPTURE
- for (int i = 0; i < numCaptures; ++i) {
- int j = eng->captureForOfficialCapture.at(i);
- if (capBegin[j] != EmptyCapture) {
- int len = capEnd[j] - capBegin[j];
- *c++ = (len > 0) ? pos + capBegin[j] : 0;
- *c++ = len;
- } else {
- *c++ = -1;
- *c++ = -1;
- }
- }
-#endif
- } else {
- // we rely on 2's complement here
- memset(captured, -1, capturedSize * sizeof(int));
- }
-}
-
-/*
- The three following functions add one state to the automaton and
- return the number of the state.
-*/
-
-int QRegExpEngine::createState(QChar ch)
-{
- return setupState(ch.unicode());
-}
-
-int QRegExpEngine::createState(const QRegExpCharClass &cc)
-{
-#ifndef QT_NO_REGEXP_CCLASS
- int n = cl.size();
- cl += QRegExpCharClass(cc);
- return setupState(CharClassBit | n);
-#else
- Q_UNUSED(cc);
- return setupState(CharClassBit);
-#endif
-}
-
-#ifndef QT_NO_REGEXP_BACKREF
-int QRegExpEngine::createState(int bref)
-{
- if (bref > nbrefs) {
- nbrefs = bref;
- if (nbrefs > MaxBackRefs) {
- error(RXERR_LIMIT);
- return 0;
- }
- }
- return setupState(BackRefBit | bref);
-}
-#endif
-
-/*
- The two following functions add a transition between all pairs of
- states (i, j) where i is found in from, and j is found in to.
-
- Cat-transitions are distinguished from plus-transitions for
- capturing.
-*/
-
-void QRegExpEngine::addCatTransitions(const QList<int> &from, const QList<int> &to)
-{
- for (int i = 0; i < from.size(); i++)
- mergeInto(&s[from.at(i)].outs, to);
-}
-
-#ifndef QT_NO_REGEXP_CAPTURE
-void QRegExpEngine::addPlusTransitions(const QList<int> &from, const QList<int> &to, int atom)
-{
- for (int i = 0; i < from.size(); i++) {
- QRegExpAutomatonState &st = s[from.at(i)];
- const QList<int> oldOuts = st.outs;
- mergeInto(&st.outs, to);
- if (f.at(atom).capture != QRegExpAtom::NoCapture) {
- for (int j = 0; j < to.size(); j++) {
- // ### st.reenter.contains(to.at(j)) check looks suspicious
- if (!st.reenter.contains(to.at(j)) &&
- !std::binary_search(oldOuts.constBegin(), oldOuts.constEnd(), to.at(j)))
- st.reenter.insert(to.at(j), atom);
- }
- }
- }
-}
-#endif
-
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
-/*
- Returns an anchor that means a OR b.
-*/
-int QRegExpEngine::anchorAlternation(int a, int b)
-{
- if (((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0)
- return a & b;
-
- int n = aa.size();
-#ifndef QT_NO_REGEXP_OPTIM
- if (n > 0 && aa.at(n - 1).a == a && aa.at(n - 1).b == b)
- return Anchor_Alternation | (n - 1);
-#endif
-
- QRegExpAnchorAlternation element = {a, b};
- aa.append(element);
- return Anchor_Alternation | n;
-}
-
-/*
- Returns an anchor that means a AND b.
-*/
-int QRegExpEngine::anchorConcatenation(int a, int b)
-{
- if (((a | b) & Anchor_Alternation) == 0)
- return a | b;
- if ((b & Anchor_Alternation) != 0)
- qSwap(a, b);
-
- int aprime = anchorConcatenation(aa.at(a ^ Anchor_Alternation).a, b);
- int bprime = anchorConcatenation(aa.at(a ^ Anchor_Alternation).b, b);
- return anchorAlternation(aprime, bprime);
-}
-#endif
-
-/*
- Adds anchor a on a transition caracterised by its from state and
- its to state.
-*/
-void QRegExpEngine::addAnchors(int from, int to, int a)
-{
- QRegExpAutomatonState &st = s[from];
- if (st.anchors.contains(to))
- a = anchorAlternation(st.anchors.value(to), a);
- st.anchors.insert(to, a);
-}
-
-#ifndef QT_NO_REGEXP_OPTIM
-/*
- This function chooses between the good-string and the bad-character
- heuristics. It computes two scores and chooses the heuristic with
- the highest score.
-
- Here are some common-sense constraints on the scores that should be
- respected if the formulas are ever modified: (1) If goodStr is
- empty, the good-string heuristic scores 0. (2) If the regular
- expression is trivial, the good-string heuristic should be used.
- (3) If the search is case insensitive, the good-string heuristic
- should be used, unless it scores 0. (Case insensitivity turns all
- entries of occ1 to 0.) (4) If (goodLateStart - goodEarlyStart) is
- big, the good-string heuristic should score less.
-*/
-void QRegExpEngine::heuristicallyChooseHeuristic()
-{
- if (minl == 0) {
- useGoodStringHeuristic = false;
- } else if (trivial) {
- useGoodStringHeuristic = true;
- } else {
- /*
- Magic formula: The good string has to constitute a good
- proportion of the minimum-length string, and appear at a
- more-or-less known index.
- */
- int goodStringScore = (64 * goodStr.length() / minl) -
- (goodLateStart - goodEarlyStart);
- /*
- Less magic formula: We pick some characters at random, and
- check whether they are good or bad.
- */
- int badCharScore = 0;
- int step = qMax(1, NumBadChars / 32);
- for (int i = 1; i < NumBadChars; i += step) {
- if (occ1.at(i) == NoOccurrence)
- badCharScore += minl;
- else
- badCharScore += occ1.at(i);
- }
- badCharScore /= minl;
- useGoodStringHeuristic = (goodStringScore > badCharScore);
- }
-}
-#endif
-
-#if defined(QT_DEBUG)
-void QRegExpEngine::dump() const
-{
- int i, j;
- qDebug("Case %ssensitive engine", cs ? "" : "in");
- qDebug(" States");
- for (i = 0; i < s.size(); i++) {
- qDebug(" %d%s", i, i == InitialState ? " (initial)" : i == FinalState ? " (final)" : "");
-#ifndef QT_NO_REGEXP_CAPTURE
- if (nf > 0)
- qDebug(" in atom %d", s[i].atom);
-#endif
- int m = s[i].match;
- if ((m & CharClassBit) != 0) {
- qDebug(" match character class %d", m ^ CharClassBit);
-#ifndef QT_NO_REGEXP_CCLASS
- cl[m ^ CharClassBit].dump();
-#else
- qDebug(" negative character class");
-#endif
- } else if ((m & BackRefBit) != 0) {
- qDebug(" match back-reference %d", m ^ BackRefBit);
- } else if (m >= 0x20 && m <= 0x7e) {
- qDebug(" match 0x%.4x (%c)", m, m);
- } else {
- qDebug(" match 0x%.4x", m);
- }
- for (j = 0; j < s[i].outs.size(); j++) {
- int next = s[i].outs[j];
- qDebug(" -> %d", next);
- if (s[i].reenter.contains(next))
- qDebug(" [reenter %d]", s[i].reenter[next]);
- if (s[i].anchors.value(next) != 0)
- qDebug(" [anchors 0x%.8x]", s[i].anchors[next]);
- }
- }
-#ifndef QT_NO_REGEXP_CAPTURE
- if (nf > 0) {
- qDebug(" Atom Parent Capture");
- for (i = 0; i < nf; i++) {
- if (f[i].capture == QRegExpAtom::NoCapture) {
- qDebug(" %6d %6d nil", i, f[i].parent);
- } else {
- int cap = f[i].capture;
- bool official = captureForOfficialCapture.contains(cap);
- qDebug(" %6d %6d %6d %s", i, f[i].parent, f[i].capture,
- official ? "official" : "");
- }
- }
- }
-#endif
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
- for (i = 0; i < aa.size(); i++)
- qDebug(" Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, aa[i].b);
-#endif
-}
-#endif
-
-void QRegExpEngine::setup()
-{
- ref.storeRelaxed(1);
-#ifndef QT_NO_REGEXP_CAPTURE
- f.resize(32);
- nf = 0;
- cf = -1;
-#endif
- officialncap = 0;
- ncap = 0;
-#ifndef QT_NO_REGEXP_OPTIM
- caretAnchored = true;
- trivial = true;
-#endif
- valid = false;
-#ifndef QT_NO_REGEXP_BACKREF
- nbrefs = 0;
-#endif
-#ifndef QT_NO_REGEXP_OPTIM
- useGoodStringHeuristic = true;
- minl = 0;
- occ1.fill(0, NumBadChars);
-#endif
-}
-
-int QRegExpEngine::setupState(int match)
-{
-#ifndef QT_NO_REGEXP_CAPTURE
- s += QRegExpAutomatonState(cf, match);
-#else
- s += QRegExpAutomatonState(match);
-#endif
- return s.size() - 1;
-}
-
-#ifndef QT_NO_REGEXP_CAPTURE
-/*
- Functions startAtom() and finishAtom() should be called to delimit
- atoms. When a state is created, it is assigned to the current atom.
- The information is later used for capturing.
-*/
-int QRegExpEngine::startAtom(bool officialCapture)
-{
- if ((nf & (nf + 1)) == 0 && nf + 1 >= f.size())
- f.resize((nf + 1) << 1);
- f[nf].parent = cf;
- cf = nf++;
- f[cf].capture = officialCapture ? QRegExpAtom::OfficialCapture : QRegExpAtom::NoCapture;
- return cf;
-}
-
-void QRegExpEngine::finishAtom(int atom, bool needCapture)
-{
- if (greedyQuantifiers && needCapture && f[atom].capture == QRegExpAtom::NoCapture)
- f[atom].capture = QRegExpAtom::UnofficialCapture;
- cf = f.at(atom).parent;
-}
-#endif
-
-#ifndef QT_NO_REGEXP_LOOKAHEAD
-/*
- Creates a lookahead anchor.
-*/
-int QRegExpEngine::addLookahead(QRegExpEngine *eng, bool negative)
-{
- int n = ahead.size();
- if (n == MaxLookaheads) {
- error(RXERR_LIMIT);
- return 0;
- }
- ahead += new QRegExpLookahead(eng, negative);
- return Anchor_FirstLookahead << n;
-}
-#endif
-
-#ifndef QT_NO_REGEXP_CAPTURE
-/*
- We want the longest leftmost captures.
-*/
-static bool isBetterCapture(int ncap, const int *begin1, const int *end1, const int *begin2,
- const int *end2)
-{
- for (int i = 0; i < ncap; i++) {
- int delta = begin2[i] - begin1[i]; // it has to start early...
- if (delta == 0)
- delta = end1[i] - end2[i]; // ...and end late
-
- if (delta != 0)
- return delta > 0;
- }
- return false;
-}
-#endif
-
-/*
- Returns \c true if anchor a matches at position pos + i in the input
- string, otherwise false.
-*/
-bool QRegExpMatchState::testAnchor(int i, int a, const int *capBegin)
-{
- int j;
-
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
- if ((a & QRegExpEngine::Anchor_Alternation) != 0)
- return testAnchor(i, eng->aa.at(a ^ QRegExpEngine::Anchor_Alternation).a, capBegin)
- || testAnchor(i, eng->aa.at(a ^ QRegExpEngine::Anchor_Alternation).b, capBegin);
-#endif
-
- if ((a & QRegExpEngine::Anchor_Caret) != 0) {
- if (pos + i != caretPos)
- return false;
- }
- if ((a & QRegExpEngine::Anchor_Dollar) != 0) {
- if (pos + i != len)
- return false;
- }
-#ifndef QT_NO_REGEXP_ESCAPE
- if ((a & (QRegExpEngine::Anchor_Word | QRegExpEngine::Anchor_NonWord)) != 0) {
- bool before = false;
- bool after = false;
- if (pos + i != 0)
- before = isWord(in[pos + i - 1]);
- if (pos + i != len)
- after = isWord(in[pos + i]);
- if ((a & QRegExpEngine::Anchor_Word) != 0 && (before == after))
- return false;
- if ((a & QRegExpEngine::Anchor_NonWord) != 0 && (before != after))
- return false;
- }
-#endif
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- if ((a & QRegExpEngine::Anchor_LookaheadMask) != 0) {
- const QList<QRegExpLookahead *> &ahead = eng->ahead;
- for (j = 0; j < ahead.size(); j++) {
- if ((a & (QRegExpEngine::Anchor_FirstLookahead << j)) != 0) {
- QRegExpMatchState matchState;
- matchState.prepareForMatch(ahead[j]->eng);
- matchState.match(in + pos + i, len - pos - i, 0,
- true, true, caretPos - pos - i);
- if ((matchState.captured[0] == 0) == ahead[j]->neg)
- return false;
- }
- }
- }
-#endif
-#ifndef QT_NO_REGEXP_CAPTURE
-#ifndef QT_NO_REGEXP_BACKREF
- for (j = 0; j < eng->nbrefs; j++) {
- if ((a & (QRegExpEngine::Anchor_BackRef1Empty << j)) != 0) {
- int i = eng->captureForOfficialCapture.at(j);
- if (capBegin[i] != EmptyCapture)
- return false;
- }
- }
-#endif
-#endif
- return true;
-}
-
-#ifndef QT_NO_REGEXP_OPTIM
-/*
- The three following functions are what Jeffrey Friedl would call
- transmissions (or bump-alongs). Using one or the other should make
- no difference except in performance.
-*/
-
-bool QRegExpEngine::goodStringMatch(QRegExpMatchState &matchState) const
-{
- int k = matchState.pos + goodEarlyStart;
- QStringMatcher matcher(goodStr.unicode(), goodStr.length(), cs);
- while ((k = matcher.indexIn(matchState.in, matchState.len, k)) != -1) {
- int from = k - goodLateStart;
- int to = k - goodEarlyStart;
- if (from > matchState.pos)
- matchState.pos = from;
-
- while (matchState.pos <= to) {
- if (matchState.matchHere())
- return true;
- ++matchState.pos;
- }
- ++k;
- }
- return false;
-}
-
-bool QRegExpEngine::badCharMatch(QRegExpMatchState &matchState) const
-{
- int slideHead = 0;
- int slideNext = 0;
- int i;
- int lastPos = matchState.len - minl;
- memset(matchState.slideTab, 0, matchState.slideTabSize * sizeof(int));
-
- /*
- Set up the slide table, used for the bad-character heuristic,
- using the table of first occurrence of each character.
- */
- for (i = 0; i < minl; i++) {
- int sk = occ1[BadChar(matchState.in[matchState.pos + i])];
- if (sk == NoOccurrence)
- sk = i + 1;
- if (sk > 0) {
- int k = i + 1 - sk;
- if (k < 0) {
- sk = i + 1;
- k = 0;
- }
- if (sk > matchState.slideTab[k])
- matchState.slideTab[k] = sk;
- }
- }
-
- if (matchState.pos > lastPos)
- return false;
-
- for (;;) {
- if (++slideNext >= matchState.slideTabSize)
- slideNext = 0;
- if (matchState.slideTab[slideHead] > 0) {
- if (matchState.slideTab[slideHead] - 1 > matchState.slideTab[slideNext])
- matchState.slideTab[slideNext] = matchState.slideTab[slideHead] - 1;
- matchState.slideTab[slideHead] = 0;
- } else {
- if (matchState.matchHere())
- return true;
- }
-
- if (matchState.pos == lastPos)
- break;
-
- /*
- Update the slide table. This code has much in common with
- the initialization code.
- */
- int sk = occ1[BadChar(matchState.in[matchState.pos + minl])];
- if (sk == NoOccurrence) {
- matchState.slideTab[slideNext] = minl;
- } else if (sk > 0) {
- int k = slideNext + minl - sk;
- if (k >= matchState.slideTabSize)
- k -= matchState.slideTabSize;
- if (sk > matchState.slideTab[k])
- matchState.slideTab[k] = sk;
- }
- slideHead = slideNext;
- ++matchState.pos;
- }
- return false;
-}
-#else
-bool QRegExpEngine::bruteMatch(QRegExpMatchState &matchState) const
-{
- while (matchState.pos <= matchState.len) {
- if (matchState.matchHere())
- return true;
- ++matchState.pos;
- }
- return false;
-}
-#endif
-
-/*
- Here's the core of the engine. It tries to do a match here and now.
-*/
-bool QRegExpMatchState::matchHere()
-{
- int ncur = 1, nnext = 0;
- int i = 0, j, k, m;
- bool stop = false;
-
- matchLen = -1;
- oneTestMatchedLen = -1;
- curStack[0] = QRegExpEngine::InitialState;
-
- int ncap = eng->ncap;
-#ifndef QT_NO_REGEXP_CAPTURE
- if (ncap > 0) {
- for (j = 0; j < ncap; j++) {
- curCapBegin[j] = EmptyCapture;
- curCapEnd[j] = EmptyCapture;
- }
- }
-#endif
-
-#ifndef QT_NO_REGEXP_BACKREF
- while ((ncur > 0 || !sleeping.isEmpty()) && i <= len - pos && !stop)
-#else
- while (ncur > 0 && i <= len - pos && !stop)
-#endif
- {
- int ch = (i < len - pos) ? in[pos + i].unicode() : 0;
- for (j = 0; j < ncur; j++) {
- int cur = curStack[j];
- const QRegExpAutomatonState &scur = eng->s.at(cur);
- const QList<int> &outs = scur.outs;
- for (k = 0; k < outs.size(); k++) {
- int next = outs.at(k);
- const QRegExpAutomatonState &snext = eng->s.at(next);
- bool inside = true;
-#if !defined(QT_NO_REGEXP_BACKREF) && !defined(QT_NO_REGEXP_CAPTURE)
- int needSomeSleep = 0;
-#endif
-
- /*
- First, check if the anchors are anchored properly.
- */
- int a = scur.anchors.value(next);
- if (a != 0 && !testAnchor(i, a, curCapBegin + j * ncap))
- inside = false;
-
- /*
- If indeed they are, check if the input character is
- correct for this transition.
- */
- if (inside) {
- m = snext.match;
- if ((m & (QRegExpEngine::CharClassBit | QRegExpEngine::BackRefBit)) == 0) {
- if (eng->cs)
- inside = (m == ch);
- else
- inside = (QChar(m).toLower() == QChar(ch).toLower());
- } else if (next == QRegExpEngine::FinalState) {
- matchLen = i;
- stop = minimal;
- inside = true;
- } else if ((m & QRegExpEngine::CharClassBit) != 0) {
-#ifndef QT_NO_REGEXP_CCLASS
- const QRegExpCharClass &cc = eng->cl.at(m ^ QRegExpEngine::CharClassBit);
- if (eng->cs)
- inside = cc.in(QChar(ch));
- else if (cc.negative())
- inside = cc.in(QChar(ch).toLower()) &&
- cc.in(QChar(ch).toUpper());
- else
- inside = cc.in(QChar(ch).toLower()) ||
- cc.in(QChar(ch).toUpper());
-#endif
-#if !defined(QT_NO_REGEXP_BACKREF) && !defined(QT_NO_REGEXP_CAPTURE)
- } else { /* ((m & QRegExpEngine::BackRefBit) != 0) */
- int bref = m ^ QRegExpEngine::BackRefBit;
- int ell = j * ncap + eng->captureForOfficialCapture.at(bref - 1);
-
- inside = bref <= ncap && curCapBegin[ell] != EmptyCapture;
- if (inside) {
- if (eng->cs)
- inside = (in[pos + curCapBegin[ell]] == QChar(ch));
- else
- inside = (in[pos + curCapBegin[ell]].toLower()
- == QChar(ch).toLower());
- }
-
- if (inside) {
- int delta;
- if (curCapEnd[ell] == EmptyCapture)
- delta = i - curCapBegin[ell];
- else
- delta = curCapEnd[ell] - curCapBegin[ell];
-
- inside = (delta <= len - (pos + i));
- if (inside && delta > 1) {
- int n = 1;
- if (eng->cs) {
- while (n < delta) {
- if (in[pos + curCapBegin[ell] + n]
- != in[pos + i + n])
- break;
- ++n;
- }
- } else {
- while (n < delta) {
- QChar a = in[pos + curCapBegin[ell] + n];
- QChar b = in[pos + i + n];
- if (a.toLower() != b.toLower())
- break;
- ++n;
- }
- }
- inside = (n == delta);
- if (inside)
- needSomeSleep = delta - 1;
- }
- }
-#endif
- }
- }
-
- /*
- We must now update our data structures.
- */
- if (inside) {
-#ifndef QT_NO_REGEXP_CAPTURE
- int *capBegin, *capEnd;
-#endif
- /*
- If the next state was not encountered yet, all
- is fine.
- */
- if ((m = inNextStack[next]) == -1) {
- m = nnext++;
- nextStack[m] = next;
- inNextStack[next] = m;
-#ifndef QT_NO_REGEXP_CAPTURE
- capBegin = nextCapBegin + m * ncap;
- capEnd = nextCapEnd + m * ncap;
-
- /*
- Otherwise, we'll first maintain captures in
- temporary arrays, and decide at the end whether
- it's best to keep the previous capture zones or
- the new ones.
- */
- } else {
- capBegin = tempCapBegin;
- capEnd = tempCapEnd;
-#endif
- }
-
-#ifndef QT_NO_REGEXP_CAPTURE
- /*
- Updating the capture zones is much of a task.
- */
- if (ncap > 0) {
- memcpy(capBegin, curCapBegin + j * ncap, ncap * sizeof(int));
- memcpy(capEnd, curCapEnd + j * ncap, ncap * sizeof(int));
- int c = scur.atom, n = snext.atom;
- int p = -1, q = -1;
- int cap;
-
- /*
- Lemma 1. For any x in the range [0..nf), we
- have f[x].parent < x.
-
- Proof. By looking at startAtom(), it is
- clear that cf < nf holds all the time, and
- thus that f[nf].parent < nf.
- */
-
- /*
- If we are reentering an atom, we empty all
- capture zones inside it.
- */
- if ((q = scur.reenter.value(next)) != 0) {
- QBitArray b(eng->nf, false);
- b.setBit(q, true);
- for (int ell = q + 1; ell < eng->nf; ell++) {
- if (b.testBit(eng->f.at(ell).parent)) {
- b.setBit(ell, true);
- cap = eng->f.at(ell).capture;
- if (cap >= 0) {
- capBegin[cap] = EmptyCapture;
- capEnd[cap] = EmptyCapture;
- }
- }
- }
- p = eng->f.at(q).parent;
-
- /*
- Otherwise, close the capture zones we are
- leaving. We are leaving f[c].capture,
- f[f[c].parent].capture,
- f[f[f[c].parent].parent].capture, ...,
- until f[x].capture, with x such that
- f[x].parent is the youngest common ancestor
- for c and n.
-
- We go up along c's and n's ancestry until
- we find x.
- */
- } else {
- p = c;
- q = n;
- while (p != q) {
- if (p > q) {
- cap = eng->f.at(p).capture;
- if (cap >= 0) {
- if (capBegin[cap] == i) {
- capBegin[cap] = EmptyCapture;
- capEnd[cap] = EmptyCapture;
- } else {
- capEnd[cap] = i;
- }
- }
- p = eng->f.at(p).parent;
- } else {
- q = eng->f.at(q).parent;
- }
- }
- }
-
- /*
- In any case, we now open the capture zones
- we are entering. We work upwards from n
- until we reach p (the parent of the atom we
- reenter or the youngest common ancestor).
- */
- while (n > p) {
- cap = eng->f.at(n).capture;
- if (cap >= 0) {
- capBegin[cap] = i;
- capEnd[cap] = EmptyCapture;
- }
- n = eng->f.at(n).parent;
- }
- /*
- If the next state was already in
- nextStack, we must choose carefully which
- capture zones we want to keep.
- */
- if (capBegin == tempCapBegin &&
- isBetterCapture(ncap, capBegin, capEnd, nextCapBegin + m * ncap,
- nextCapEnd + m * ncap)) {
- memcpy(nextCapBegin + m * ncap, capBegin, ncap * sizeof(int));
- memcpy(nextCapEnd + m * ncap, capEnd, ncap * sizeof(int));
- }
- }
-#ifndef QT_NO_REGEXP_BACKREF
- /*
- We are done with updating the capture zones.
- It's now time to put the next state to sleep,
- if it needs to, and to remove it from
- nextStack.
- */
- if (needSomeSleep > 0) {
- QList<int> zzZ(2 + 2 * ncap);
- zzZ[0] = i + needSomeSleep;
- zzZ[1] = next;
- if (ncap > 0) {
- memcpy(zzZ.data() + 2, capBegin, ncap * sizeof(int));
- memcpy(zzZ.data() + 2 + ncap, capEnd, ncap * sizeof(int));
- }
- inNextStack[nextStack[--nnext]] = -1;
- sleeping.append(zzZ);
- }
-#endif
-#endif
- }
- }
- }
-#ifndef QT_NO_REGEXP_CAPTURE
- /*
- If we reached the final state, hurray! Copy the captured
- zone.
- */
- if (ncap > 0 && (m = inNextStack[QRegExpEngine::FinalState]) != -1) {
- memcpy(capBegin, nextCapBegin + m * ncap, ncap * sizeof(int));
- memcpy(capEnd, nextCapEnd + m * ncap, ncap * sizeof(int));
- }
-#ifndef QT_NO_REGEXP_BACKREF
- /*
- It's time to wake up the sleepers.
- */
- j = 0;
- while (j < sleeping.count()) {
- if (sleeping.at(j)[0] == i) {
- const QList<int> &zzZ = sleeping.at(j);
- int next = zzZ[1];
- const int *capBegin = zzZ.data() + 2;
- const int *capEnd = zzZ.data() + 2 + ncap;
- bool copyOver = true;
-
- if ((m = inNextStack[next]) == -1) {
- m = nnext++;
- nextStack[m] = next;
- inNextStack[next] = m;
- } else {
- copyOver = isBetterCapture(ncap, nextCapBegin + m * ncap, nextCapEnd + m * ncap,
- capBegin, capEnd);
- }
- if (copyOver) {
- memcpy(nextCapBegin + m * ncap, capBegin, ncap * sizeof(int));
- memcpy(nextCapEnd + m * ncap, capEnd, ncap * sizeof(int));
- }
-
- sleeping.removeAt(j);
- } else {
- ++j;
- }
- }
-#endif
-#endif
- for (j = 0; j < nnext; j++)
- inNextStack[nextStack[j]] = -1;
-
- // avoid needless iteration that confuses oneTestMatchedLen
- if (nnext == 1 && nextStack[0] == QRegExpEngine::FinalState
-#ifndef QT_NO_REGEXP_BACKREF
- && sleeping.isEmpty()
-#endif
- )
- stop = true;
-
- qSwap(curStack, nextStack);
-#ifndef QT_NO_REGEXP_CAPTURE
- qSwap(curCapBegin, nextCapBegin);
- qSwap(curCapEnd, nextCapEnd);
-#endif
- ncur = nnext;
- nnext = 0;
- ++i;
- }
-
-#ifndef QT_NO_REGEXP_BACKREF
- /*
- If minimal matching is enabled, we might have some sleepers
- left.
- */
- if (!sleeping.isEmpty())
- sleeping.clear();
-#endif
-
- oneTestMatchedLen = i - 1;
- return (matchLen >= 0);
-}
-
-#ifndef QT_NO_REGEXP_CCLASS
-
-QRegExpCharClass::QRegExpCharClass()
- : c(0), n(false)
-{
-#ifndef QT_NO_REGEXP_OPTIM
- occ1.fill(NoOccurrence, NumBadChars);
-#endif
-}
-
-void QRegExpCharClass::clear()
-{
- c = 0;
- r.clear();
- n = false;
-}
-
-void QRegExpCharClass::setNegative(bool negative)
-{
- n = negative;
-#ifndef QT_NO_REGEXP_OPTIM
- occ1.fill(0, NumBadChars);
-#endif
-}
-
-void QRegExpCharClass::addCategories(uint cats)
-{
- static const int all_cats = FLAG(QChar::Mark_NonSpacing) |
- FLAG(QChar::Mark_SpacingCombining) |
- FLAG(QChar::Mark_Enclosing) |
- FLAG(QChar::Number_DecimalDigit) |
- FLAG(QChar::Number_Letter) |
- FLAG(QChar::Number_Other) |
- FLAG(QChar::Separator_Space) |
- FLAG(QChar::Separator_Line) |
- FLAG(QChar::Separator_Paragraph) |
- FLAG(QChar::Other_Control) |
- FLAG(QChar::Other_Format) |
- FLAG(QChar::Other_Surrogate) |
- FLAG(QChar::Other_PrivateUse) |
- FLAG(QChar::Other_NotAssigned) |
- FLAG(QChar::Letter_Uppercase) |
- FLAG(QChar::Letter_Lowercase) |
- FLAG(QChar::Letter_Titlecase) |
- FLAG(QChar::Letter_Modifier) |
- FLAG(QChar::Letter_Other) |
- FLAG(QChar::Punctuation_Connector) |
- FLAG(QChar::Punctuation_Dash) |
- FLAG(QChar::Punctuation_Open) |
- FLAG(QChar::Punctuation_Close) |
- FLAG(QChar::Punctuation_InitialQuote) |
- FLAG(QChar::Punctuation_FinalQuote) |
- FLAG(QChar::Punctuation_Other) |
- FLAG(QChar::Symbol_Math) |
- FLAG(QChar::Symbol_Currency) |
- FLAG(QChar::Symbol_Modifier) |
- FLAG(QChar::Symbol_Other);
- c |= (all_cats & cats);
-#ifndef QT_NO_REGEXP_OPTIM
- occ1.fill(0, NumBadChars);
-#endif
-}
-
-void QRegExpCharClass::addRange(ushort from, ushort to)
-{
- if (from > to)
- qSwap(from, to);
- int m = r.size();
- r.resize(m + 1);
- r[m].from = from;
- r[m].len = to - from + 1;
-
-#ifndef QT_NO_REGEXP_OPTIM
- int i;
-
- if (to - from < NumBadChars) {
- if (from % NumBadChars <= to % NumBadChars) {
- for (i = from % NumBadChars; i <= to % NumBadChars; i++)
- occ1[i] = 0;
- } else {
- for (i = 0; i <= to % NumBadChars; i++)
- occ1[i] = 0;
- for (i = from % NumBadChars; i < NumBadChars; i++)
- occ1[i] = 0;
- }
- } else {
- occ1.fill(0, NumBadChars);
- }
-#endif
-}
-
-bool QRegExpCharClass::in(QChar ch) const
-{
-#ifndef QT_NO_REGEXP_OPTIM
- if (occ1.at(BadChar(ch)) == NoOccurrence)
- return n;
-#endif
-
- if (c != 0 && (c & FLAG(ch.category())) != 0)
- return !n;
-
- const int uc = ch.unicode();
- int size = r.size();
-
- for (int i = 0; i < size; ++i) {
- const QRegExpCharClassRange &range = r.at(i);
- if (uint(uc - range.from) < uint(r.at(i).len))
- return !n;
- }
- return n;
-}
-
-#if defined(QT_DEBUG)
-void QRegExpCharClass::dump() const
-{
- int i;
- qDebug(" %stive character class", n ? "nega" : "posi");
-#ifndef QT_NO_REGEXP_CCLASS
- if (c != 0)
- qDebug(" categories 0x%.8x", c);
-#endif
- for (i = 0; i < r.size(); i++)
- qDebug(" 0x%.4x through 0x%.4x", r[i].from, r[i].from + r[i].len - 1);
-}
-#endif
-#endif
-
-QRegExpEngine::Box::Box(QRegExpEngine *engine)
- : eng(engine), skipanchors(0)
-#ifndef QT_NO_REGEXP_OPTIM
- , earlyStart(0), lateStart(0), maxl(0)
-#endif
-{
-#ifndef QT_NO_REGEXP_OPTIM
- occ1.fill(NoOccurrence, NumBadChars);
-#endif
- minl = 0;
-}
-
-QRegExpEngine::Box &QRegExpEngine::Box::operator=(const Box &b)
-{
- eng = b.eng;
- ls = b.ls;
- rs = b.rs;
- lanchors = b.lanchors;
- ranchors = b.ranchors;
- skipanchors = b.skipanchors;
-#ifndef QT_NO_REGEXP_OPTIM
- earlyStart = b.earlyStart;
- lateStart = b.lateStart;
- str = b.str;
- leftStr = b.leftStr;
- rightStr = b.rightStr;
- maxl = b.maxl;
- occ1 = b.occ1;
-#endif
- minl = b.minl;
- return *this;
-}
-
-void QRegExpEngine::Box::set(QChar ch)
-{
- ls.resize(1);
- ls[0] = eng->createState(ch);
- rs = ls;
-#ifndef QT_NO_REGEXP_OPTIM
- str = ch;
- leftStr = ch;
- rightStr = ch;
- maxl = 1;
- occ1[BadChar(ch)] = 0;
-#endif
- minl = 1;
-}
-
-void QRegExpEngine::Box::set(const QRegExpCharClass &cc)
-{
- ls.resize(1);
- ls[0] = eng->createState(cc);
- rs = ls;
-#ifndef QT_NO_REGEXP_OPTIM
- maxl = 1;
- occ1 = cc.firstOccurrence();
-#endif
- minl = 1;
-}
-
-#ifndef QT_NO_REGEXP_BACKREF
-void QRegExpEngine::Box::set(int bref)
-{
- ls.resize(1);
- ls[0] = eng->createState(bref);
- rs = ls;
- if (bref >= 1 && bref <= MaxBackRefs)
- skipanchors = Anchor_BackRef0Empty << bref;
-#ifndef QT_NO_REGEXP_OPTIM
- maxl = InftyLen;
-#endif
- minl = 0;
-}
-#endif
-
-void QRegExpEngine::Box::cat(const Box &b)
-{
- eng->addCatTransitions(rs, b.ls);
- addAnchorsToEngine(b);
- if (minl == 0) {
- lanchors.insert(b.lanchors);
- if (skipanchors != 0) {
- for (int i = 0; i < b.ls.size(); i++) {
- int a = eng->anchorConcatenation(lanchors.value(b.ls.at(i), 0), skipanchors);
- lanchors.insert(b.ls.at(i), a);
- }
- }
- mergeInto(&ls, b.ls);
- }
- if (b.minl == 0) {
- ranchors.insert(b.ranchors);
- if (b.skipanchors != 0) {
- for (int i = 0; i < rs.size(); i++) {
- int a = eng->anchorConcatenation(ranchors.value(rs.at(i), 0), b.skipanchors);
- ranchors.insert(rs.at(i), a);
- }
- }
- mergeInto(&rs, b.rs);
- } else {
- ranchors = b.ranchors;
- rs = b.rs;
- }
-
-#ifndef QT_NO_REGEXP_OPTIM
- if (maxl != InftyLen) {
- if (rightStr.length() + b.leftStr.length() >
- qMax(str.length(), b.str.length())) {
- earlyStart = minl - rightStr.length();
- lateStart = maxl - rightStr.length();
- str = rightStr + b.leftStr;
- } else if (b.str.length() > str.length()) {
- earlyStart = minl + b.earlyStart;
- lateStart = maxl + b.lateStart;
- str = b.str;
- }
- }
-
- if (leftStr.length() == maxl)
- leftStr += b.leftStr;
-
- if (b.rightStr.length() == b.maxl) {
- rightStr += b.rightStr;
- } else {
- rightStr = b.rightStr;
- }
-
- if (maxl == InftyLen || b.maxl == InftyLen) {
- maxl = InftyLen;
- } else {
- maxl += b.maxl;
- }
-
- for (int i = 0; i < NumBadChars; i++) {
- if (b.occ1.at(i) != NoOccurrence && minl + b.occ1.at(i) < occ1.at(i))
- occ1[i] = minl + b.occ1.at(i);
- }
-#endif
-
- minl += b.minl;
- if (minl == 0)
- skipanchors = eng->anchorConcatenation(skipanchors, b.skipanchors);
- else
- skipanchors = 0;
-}
-
-void QRegExpEngine::Box::orx(const Box &b)
-{
- mergeInto(&ls, b.ls);
- lanchors.insert(b.lanchors);
- mergeInto(&rs, b.rs);
- ranchors.insert(b.ranchors);
-
- if (b.minl == 0) {
- if (minl == 0)
- skipanchors = eng->anchorAlternation(skipanchors, b.skipanchors);
- else
- skipanchors = b.skipanchors;
- }
-
-#ifndef QT_NO_REGEXP_OPTIM
- for (int i = 0; i < NumBadChars; i++) {
- if (occ1.at(i) > b.occ1.at(i))
- occ1[i] = b.occ1.at(i);
- }
- earlyStart = 0;
- lateStart = 0;
- str = QString();
- leftStr = QString();
- rightStr = QString();
- if (b.maxl > maxl)
- maxl = b.maxl;
-#endif
- if (b.minl < minl)
- minl = b.minl;
-}
-
-void QRegExpEngine::Box::plus(int atom)
-{
-#ifndef QT_NO_REGEXP_CAPTURE
- eng->addPlusTransitions(rs, ls, atom);
-#else
- Q_UNUSED(atom);
- eng->addCatTransitions(rs, ls);
-#endif
- addAnchorsToEngine(*this);
-#ifndef QT_NO_REGEXP_OPTIM
- maxl = InftyLen;
-#endif
-}
-
-void QRegExpEngine::Box::opt()
-{
-#ifndef QT_NO_REGEXP_OPTIM
- earlyStart = 0;
- lateStart = 0;
- str = QString();
- leftStr = QString();
- rightStr = QString();
-#endif
- skipanchors = 0;
- minl = 0;
-}
-
-void QRegExpEngine::Box::catAnchor(int a)
-{
- if (a != 0) {
- for (int i = 0; i < rs.size(); i++) {
- a = eng->anchorConcatenation(ranchors.value(rs.at(i), 0), a);
- ranchors.insert(rs.at(i), a);
- }
- if (minl == 0)
- skipanchors = eng->anchorConcatenation(skipanchors, a);
- }
-}
-
-#ifndef QT_NO_REGEXP_OPTIM
-void QRegExpEngine::Box::setupHeuristics()
-{
- eng->goodEarlyStart = earlyStart;
- eng->goodLateStart = lateStart;
- eng->goodStr = eng->cs ? str : str.toLower();
-
- eng->minl = minl;
- if (eng->cs) {
- /*
- A regular expression such as 112|1 has occ1['2'] = 2 and minl =
- 1 at this point. An entry of occ1 has to be at most minl or
- infinity for the rest of the algorithm to go well.
-
- We waited until here before normalizing these cases (instead of
- doing it in Box::orx()) because sometimes things improve by
- themselves. Consider for example (112|1)34.
- */
- for (int i = 0; i < NumBadChars; i++) {
- if (occ1.at(i) != NoOccurrence && occ1.at(i) >= minl)
- occ1[i] = minl;
- }
- eng->occ1 = occ1;
- } else {
- eng->occ1.fill(0, NumBadChars);
- }
-
- eng->heuristicallyChooseHeuristic();
-}
-#endif
-
-#if defined(QT_DEBUG)
-void QRegExpEngine::Box::dump() const
-{
- int i;
- qDebug("Box of at least %d character%s", minl, minl == 1 ? "" : "s");
- qDebug(" Left states:");
- for (i = 0; i < ls.size(); i++) {
- if (lanchors.value(ls[i], 0) == 0)
- qDebug(" %d", ls[i]);
- else
- qDebug(" %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]]);
- }
- qDebug(" Right states:");
- for (i = 0; i < rs.size(); i++) {
- if (ranchors.value(rs[i], 0) == 0)
- qDebug(" %d", rs[i]);
- else
- qDebug(" %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]]);
- }
- qDebug(" Skip anchors: 0x%.8x", skipanchors);
-}
-#endif
-
-void QRegExpEngine::Box::addAnchorsToEngine(const Box &to) const
-{
- for (int i = 0; i < to.ls.size(); i++) {
- for (int j = 0; j < rs.size(); j++) {
- int a = eng->anchorConcatenation(ranchors.value(rs.at(j), 0),
- to.lanchors.value(to.ls.at(i), 0));
- eng->addAnchors(rs[j], to.ls[i], a);
- }
- }
-}
-
-#ifndef QT_NO_REGEXP_CCLASS
-// fast lookup hash for xml schema extensions
-// sorted by name for b-search
-static const struct CategoriesRangeMapEntry {
- const char name[40];
- uint first, second;
-} categoriesRangeMap[] = {
- { "AegeanNumbers", 0x10100, 0x1013F },
- { "AlphabeticPresentationForms", 0xFB00, 0xFB4F },
- { "AncientGreekMusicalNotation", 0x1D200, 0x1D24F },
- { "AncientGreekNumbers", 0x10140, 0x1018F },
- { "Arabic", 0x0600, 0x06FF },
- { "ArabicPresentationForms-A", 0xFB50, 0xFDFF },
- { "ArabicPresentationForms-B", 0xFE70, 0xFEFF },
- { "ArabicSupplement", 0x0750, 0x077F },
- { "Armenian", 0x0530, 0x058F },
- { "Arrows", 0x2190, 0x21FF },
- { "BasicLatin", 0x0000, 0x007F },
- { "Bengali", 0x0980, 0x09FF },
- { "BlockElements", 0x2580, 0x259F },
- { "Bopomofo", 0x3100, 0x312F },
- { "BopomofoExtended", 0x31A0, 0x31BF },
- { "BoxDrawing", 0x2500, 0x257F },
- { "BraillePatterns", 0x2800, 0x28FF },
- { "Buginese", 0x1A00, 0x1A1F },
- { "Buhid", 0x1740, 0x175F },
- { "ByzantineMusicalSymbols", 0x1D000, 0x1D0FF },
- { "CJKCompatibility", 0x3300, 0x33FF },
- { "CJKCompatibilityForms", 0xFE30, 0xFE4F },
- { "CJKCompatibilityIdeographs", 0xF900, 0xFAFF },
- { "CJKCompatibilityIdeographsSupplement", 0x2F800, 0x2FA1F },
- { "CJKRadicalsSupplement", 0x2E80, 0x2EFF },
- { "CJKStrokes", 0x31C0, 0x31EF },
- { "CJKSymbolsandPunctuation", 0x3000, 0x303F },
- { "CJKUnifiedIdeographs", 0x4E00, 0x9FFF },
- { "CJKUnifiedIdeographsExtensionA", 0x3400, 0x4DB5 },
- { "CJKUnifiedIdeographsExtensionB", 0x20000, 0x2A6DF },
- { "Cherokee", 0x13A0, 0x13FF },
- { "CombiningDiacriticalMarks", 0x0300, 0x036F },
- { "CombiningDiacriticalMarksSupplement", 0x1DC0, 0x1DFF },
- { "CombiningHalfMarks", 0xFE20, 0xFE2F },
- { "CombiningMarksforSymbols", 0x20D0, 0x20FF },
- { "ControlPictures", 0x2400, 0x243F },
- { "Coptic", 0x2C80, 0x2CFF },
- { "CurrencySymbols", 0x20A0, 0x20CF },
- { "CypriotSyllabary", 0x10800, 0x1083F },
- { "Cyrillic", 0x0400, 0x04FF },
- { "CyrillicSupplement", 0x0500, 0x052F },
- { "Deseret", 0x10400, 0x1044F },
- { "Devanagari", 0x0900, 0x097F },
- { "Dingbats", 0x2700, 0x27BF },
- { "EnclosedAlphanumerics", 0x2460, 0x24FF },
- { "EnclosedCJKLettersandMonths", 0x3200, 0x32FF },
- { "Ethiopic", 0x1200, 0x137F },
- { "EthiopicExtended", 0x2D80, 0x2DDF },
- { "EthiopicSupplement", 0x1380, 0x139F },
- { "GeneralPunctuation", 0x2000, 0x206F },
- { "GeometricShapes", 0x25A0, 0x25FF },
- { "Georgian", 0x10A0, 0x10FF },
- { "GeorgianSupplement", 0x2D00, 0x2D2F },
- { "Glagolitic", 0x2C00, 0x2C5F },
- { "Gothic", 0x10330, 0x1034F },
- { "Greek", 0x0370, 0x03FF },
- { "GreekExtended", 0x1F00, 0x1FFF },
- { "Gujarati", 0x0A80, 0x0AFF },
- { "Gurmukhi", 0x0A00, 0x0A7F },
- { "HalfwidthandFullwidthForms", 0xFF00, 0xFFEF },
- { "HangulCompatibilityJamo", 0x3130, 0x318F },
- { "HangulJamo", 0x1100, 0x11FF },
- { "HangulSyllables", 0xAC00, 0xD7A3 },
- { "Hanunoo", 0x1720, 0x173F },
- { "Hebrew", 0x0590, 0x05FF },
- { "Hiragana", 0x3040, 0x309F },
- { "IPAExtensions", 0x0250, 0x02AF },
- { "IdeographicDescriptionCharacters", 0x2FF0, 0x2FFF },
- { "Kanbun", 0x3190, 0x319F },
- { "KangxiRadicals", 0x2F00, 0x2FDF },
- { "Kannada", 0x0C80, 0x0CFF },
- { "Katakana", 0x30A0, 0x30FF },
- { "KatakanaPhoneticExtensions", 0x31F0, 0x31FF },
- { "Kharoshthi", 0x10A00, 0x10A5F },
- { "Khmer", 0x1780, 0x17FF },
- { "KhmerSymbols", 0x19E0, 0x19FF },
- { "Lao", 0x0E80, 0x0EFF },
- { "Latin-1Supplement", 0x0080, 0x00FF },
- { "LatinExtended-A", 0x0100, 0x017F },
- { "LatinExtended-B", 0x0180, 0x024F },
- { "LatinExtendedAdditional", 0x1E00, 0x1EFF },
- { "LetterlikeSymbols", 0x2100, 0x214F },
- { "Limbu", 0x1900, 0x194F },
- { "LinearBIdeograms", 0x10080, 0x100FF },
- { "LinearBSyllabary", 0x10000, 0x1007F },
- { "Malayalam", 0x0D00, 0x0D7F },
- { "MathematicalAlphanumericSymbols", 0x1D400, 0x1D7FF },
- { "MathematicalOperators", 0x2200, 0x22FF },
- { "MiscellaneousMathematicalSymbols-A", 0x27C0, 0x27EF },
- { "MiscellaneousMathematicalSymbols-B", 0x2980, 0x29FF },
- { "MiscellaneousSymbols", 0x2600, 0x26FF },
- { "MiscellaneousSymbolsandArrows", 0x2B00, 0x2BFF },
- { "MiscellaneousTechnical", 0x2300, 0x23FF },
- { "ModifierToneLetters", 0xA700, 0xA71F },
- { "Mongolian", 0x1800, 0x18AF },
- { "MusicalSymbols", 0x1D100, 0x1D1FF },
- { "Myanmar", 0x1000, 0x109F },
- { "NewTaiLue", 0x1980, 0x19DF },
- { "NumberForms", 0x2150, 0x218F },
- { "Ogham", 0x1680, 0x169F },
- { "OldItalic", 0x10300, 0x1032F },
- { "OldPersian", 0x103A0, 0x103DF },
- { "OpticalCharacterRecognition", 0x2440, 0x245F },
- { "Oriya", 0x0B00, 0x0B7F },
- { "Osmanya", 0x10480, 0x104AF },
- { "PhoneticExtensions", 0x1D00, 0x1D7F },
- { "PhoneticExtensionsSupplement", 0x1D80, 0x1DBF },
- { "PrivateUse", 0xE000, 0xF8FF },
- { "Runic", 0x16A0, 0x16FF },
- { "Shavian", 0x10450, 0x1047F },
- { "Sinhala", 0x0D80, 0x0DFF },
- { "SmallFormVariants", 0xFE50, 0xFE6F },
- { "SpacingModifierLetters", 0x02B0, 0x02FF },
- { "Specials", 0xFFF0, 0xFFFF },
- { "SuperscriptsandSubscripts", 0x2070, 0x209F },
- { "SupplementalArrows-A", 0x27F0, 0x27FF },
- { "SupplementalArrows-B", 0x2900, 0x297F },
- { "SupplementalMathematicalOperators", 0x2A00, 0x2AFF },
- { "SupplementalPunctuation", 0x2E00, 0x2E7F },
- { "SupplementaryPrivateUseArea-A", 0xF0000, 0xFFFFF },
- { "SupplementaryPrivateUseArea-B", 0x100000, 0x10FFFF },
- { "SylotiNagri", 0xA800, 0xA82F },
- { "Syriac", 0x0700, 0x074F },
- { "Tagalog", 0x1700, 0x171F },
- { "Tagbanwa", 0x1760, 0x177F },
- { "Tags", 0xE0000, 0xE007F },
- { "TaiLe", 0x1950, 0x197F },
- { "TaiXuanJingSymbols", 0x1D300, 0x1D35F },
- { "Tamil", 0x0B80, 0x0BFF },
- { "Telugu", 0x0C00, 0x0C7F },
- { "Thaana", 0x0780, 0x07BF },
- { "Thai", 0x0E00, 0x0E7F },
- { "Tibetan", 0x0F00, 0x0FFF },
- { "Tifinagh", 0x2D30, 0x2D7F },
- { "Ugaritic", 0x10380, 0x1039F },
- { "UnifiedCanadianAboriginalSyllabics", 0x1400, 0x167F },
- { "VariationSelectors", 0xFE00, 0xFE0F },
- { "VariationSelectorsSupplement", 0xE0100, 0xE01EF },
- { "VerticalForms", 0xFE10, 0xFE1F },
- { "YiRadicals", 0xA490, 0xA4CF },
- { "YiSyllables", 0xA000, 0xA48F },
- { "YijingHexagramSymbols", 0x4DC0, 0x4DFF }
-};
-
-inline bool operator<(const CategoriesRangeMapEntry &entry1, const CategoriesRangeMapEntry &entry2)
-{ return qstrcmp(entry1.name, entry2.name) < 0; }
-inline bool operator<(const char *name, const CategoriesRangeMapEntry &entry)
-{ return qstrcmp(name, entry.name) < 0; }
-inline bool operator<(const CategoriesRangeMapEntry &entry, const char *name)
-{ return qstrcmp(entry.name, name) < 0; }
-#endif // QT_NO_REGEXP_CCLASS
-
-int QRegExpEngine::getChar()
-{
- return (yyPos == yyLen) ? EOS : yyIn[yyPos++].unicode();
-}
-
-int QRegExpEngine::getEscape()
-{
-#ifndef QT_NO_REGEXP_ESCAPE
- const char tab[] = "afnrtv"; // no b, as \b means word boundary
- const char backTab[] = "\a\f\n\r\t\v";
- ushort low;
- int i;
-#endif
- ushort val;
- int prevCh = yyCh;
-
- if (prevCh == EOS) {
- error(RXERR_END);
- return Tok_Char | '\\';
- }
- yyCh = getChar();
-#ifndef QT_NO_REGEXP_ESCAPE
- if ((prevCh & ~0xff) == 0) {
- const char *p = strchr(tab, prevCh);
- if (p != nullptr)
- return Tok_Char | backTab[p - tab];
- }
-#endif
-
- switch (prevCh) {
-#ifndef QT_NO_REGEXP_ESCAPE
- case '0':
- val = 0;
- for (i = 0; i < 3; i++) {
- if (yyCh >= '0' && yyCh <= '7')
- val = (val << 3) | (yyCh - '0');
- else
- break;
- yyCh = getChar();
- }
- if ((val & ~0377) != 0)
- error(RXERR_OCTAL);
- return Tok_Char | val;
-#endif
-#ifndef QT_NO_REGEXP_ESCAPE
- case 'B':
- return Tok_NonWord;
-#endif
-#ifndef QT_NO_REGEXP_CCLASS
- case 'D':
- // see QChar::isDigit()
- yyCharClass->addCategories(uint(-1) ^ FLAG(QChar::Number_DecimalDigit));
- return Tok_CharClass;
- case 'S':
- // see QChar::isSpace()
- yyCharClass->addCategories(uint(-1) ^ (FLAG(QChar::Separator_Space) |
- FLAG(QChar::Separator_Line) |
- FLAG(QChar::Separator_Paragraph) |
- FLAG(QChar::Other_Control)));
- yyCharClass->addRange(0x0000, 0x0008);
- yyCharClass->addRange(0x000e, 0x001f);
- yyCharClass->addRange(0x007f, 0x0084);
- yyCharClass->addRange(0x0086, 0x009f);
- return Tok_CharClass;
- case 'W':
- // see QChar::isLetterOrNumber() and QChar::isMark()
- yyCharClass->addCategories(uint(-1) ^ (FLAG(QChar::Mark_NonSpacing) |
- FLAG(QChar::Mark_SpacingCombining) |
- FLAG(QChar::Mark_Enclosing) |
- FLAG(QChar::Number_DecimalDigit) |
- FLAG(QChar::Number_Letter) |
- FLAG(QChar::Number_Other) |
- FLAG(QChar::Letter_Uppercase) |
- FLAG(QChar::Letter_Lowercase) |
- FLAG(QChar::Letter_Titlecase) |
- FLAG(QChar::Letter_Modifier) |
- FLAG(QChar::Letter_Other) |
- FLAG(QChar::Punctuation_Connector)));
- yyCharClass->addRange(0x203f, 0x2040);
- yyCharClass->addSingleton(0x2040);
- yyCharClass->addSingleton(0x2054);
- yyCharClass->addSingleton(0x30fb);
- yyCharClass->addRange(0xfe33, 0xfe34);
- yyCharClass->addRange(0xfe4d, 0xfe4f);
- yyCharClass->addSingleton(0xff3f);
- yyCharClass->addSingleton(0xff65);
- return Tok_CharClass;
-#endif
-#ifndef QT_NO_REGEXP_ESCAPE
- case 'b':
- return Tok_Word;
-#endif
-#ifndef QT_NO_REGEXP_CCLASS
- case 'd':
- // see QChar::isDigit()
- yyCharClass->addCategories(FLAG(QChar::Number_DecimalDigit));
- return Tok_CharClass;
- case 's':
- // see QChar::isSpace()
- yyCharClass->addCategories(FLAG(QChar::Separator_Space) |
- FLAG(QChar::Separator_Line) |
- FLAG(QChar::Separator_Paragraph));
- yyCharClass->addRange(0x0009, 0x000d);
- yyCharClass->addSingleton(0x0085);
- return Tok_CharClass;
- case 'w':
- // see QChar::isLetterOrNumber() and QChar::isMark()
- yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing) |
- FLAG(QChar::Mark_SpacingCombining) |
- FLAG(QChar::Mark_Enclosing) |
- FLAG(QChar::Number_DecimalDigit) |
- FLAG(QChar::Number_Letter) |
- FLAG(QChar::Number_Other) |
- FLAG(QChar::Letter_Uppercase) |
- FLAG(QChar::Letter_Lowercase) |
- FLAG(QChar::Letter_Titlecase) |
- FLAG(QChar::Letter_Modifier) |
- FLAG(QChar::Letter_Other));
- yyCharClass->addSingleton(0x005f); // '_'
- return Tok_CharClass;
- case 'I':
- if (!xmlSchemaExtensions)
- break;
- yyCharClass->setNegative(!yyCharClass->negative());
- Q_FALLTHROUGH();
- case 'i':
- if (xmlSchemaExtensions) {
- yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing) |
- FLAG(QChar::Mark_SpacingCombining) |
- FLAG(QChar::Mark_Enclosing) |
- FLAG(QChar::Number_DecimalDigit) |
- FLAG(QChar::Number_Letter) |
- FLAG(QChar::Number_Other) |
- FLAG(QChar::Letter_Uppercase) |
- FLAG(QChar::Letter_Lowercase) |
- FLAG(QChar::Letter_Titlecase) |
- FLAG(QChar::Letter_Modifier) |
- FLAG(QChar::Letter_Other));
- yyCharClass->addSingleton(0x003a); // ':'
- yyCharClass->addSingleton(0x005f); // '_'
- yyCharClass->addRange(0x0041, 0x005a); // [A-Z]
- yyCharClass->addRange(0x0061, 0x007a); // [a-z]
- yyCharClass->addRange(0xc0, 0xd6);
- yyCharClass->addRange(0xd8, 0xf6);
- yyCharClass->addRange(0xf8, 0x2ff);
- yyCharClass->addRange(0x370, 0x37d);
- yyCharClass->addRange(0x37f, 0x1fff);
- yyCharClass->addRange(0x200c, 0x200d);
- yyCharClass->addRange(0x2070, 0x218f);
- yyCharClass->addRange(0x2c00, 0x2fef);
- yyCharClass->addRange(0x3001, 0xd7ff);
- yyCharClass->addRange(0xf900, 0xfdcf);
- yyCharClass->addRange(0xfdf0, 0xfffd);
- yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff);
- return Tok_CharClass;
- } else {
- break;
- }
- case 'C':
- if (!xmlSchemaExtensions)
- break;
- yyCharClass->setNegative(!yyCharClass->negative());
- Q_FALLTHROUGH();
- case 'c':
- if (xmlSchemaExtensions) {
- yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing) |
- FLAG(QChar::Mark_SpacingCombining) |
- FLAG(QChar::Mark_Enclosing) |
- FLAG(QChar::Number_DecimalDigit) |
- FLAG(QChar::Number_Letter) |
- FLAG(QChar::Number_Other) |
- FLAG(QChar::Letter_Uppercase) |
- FLAG(QChar::Letter_Lowercase) |
- FLAG(QChar::Letter_Titlecase) |
- FLAG(QChar::Letter_Modifier) |
- FLAG(QChar::Letter_Other));
- yyCharClass->addSingleton(0x002d); // '-'
- yyCharClass->addSingleton(0x002e); // '.'
- yyCharClass->addSingleton(0x003a); // ':'
- yyCharClass->addSingleton(0x005f); // '_'
- yyCharClass->addSingleton(0xb7);
- yyCharClass->addRange(0x0030, 0x0039); // [0-9]
- yyCharClass->addRange(0x0041, 0x005a); // [A-Z]
- yyCharClass->addRange(0x0061, 0x007a); // [a-z]
- yyCharClass->addRange(0xc0, 0xd6);
- yyCharClass->addRange(0xd8, 0xf6);
- yyCharClass->addRange(0xf8, 0x2ff);
- yyCharClass->addRange(0x370, 0x37d);
- yyCharClass->addRange(0x37f, 0x1fff);
- yyCharClass->addRange(0x200c, 0x200d);
- yyCharClass->addRange(0x2070, 0x218f);
- yyCharClass->addRange(0x2c00, 0x2fef);
- yyCharClass->addRange(0x3001, 0xd7ff);
- yyCharClass->addRange(0xf900, 0xfdcf);
- yyCharClass->addRange(0xfdf0, 0xfffd);
- yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff);
- yyCharClass->addRange(0x0300, 0x036f);
- yyCharClass->addRange(0x203f, 0x2040);
- return Tok_CharClass;
- } else {
- break;
- }
- case 'P':
- if (!xmlSchemaExtensions)
- break;
- yyCharClass->setNegative(!yyCharClass->negative());
- Q_FALLTHROUGH();
- case 'p':
- if (xmlSchemaExtensions) {
- if (yyCh != '{') {
- error(RXERR_CHARCLASS);
- return Tok_CharClass;
- }
-
- QByteArray category;
- yyCh = getChar();
- while (yyCh != '}') {
- if (yyCh == EOS) {
- error(RXERR_END);
- return Tok_CharClass;
- }
- category.append(yyCh);
- yyCh = getChar();
- }
- yyCh = getChar(); // skip closing '}'
-
- int catlen = category.length();
- if (catlen == 1 || catlen == 2) {
- switch (category.at(0)) {
- case 'M':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing) |
- FLAG(QChar::Mark_SpacingCombining) |
- FLAG(QChar::Mark_Enclosing));
- } else {
- switch (category.at(1)) {
- case 'n': yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing)); break; // Mn
- case 'c': yyCharClass->addCategories(FLAG(QChar::Mark_SpacingCombining)); break; // Mc
- case 'e': yyCharClass->addCategories(FLAG(QChar::Mark_Enclosing)); break; // Me
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- case 'N':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Number_DecimalDigit) |
- FLAG(QChar::Number_Letter) |
- FLAG(QChar::Number_Other));
- } else {
- switch (category.at(1)) {
- case 'd': yyCharClass->addCategories(FLAG(QChar::Number_DecimalDigit)); break; // Nd
- case 'l': yyCharClass->addCategories(FLAG(QChar::Number_Letter)); break; // Hl
- case 'o': yyCharClass->addCategories(FLAG(QChar::Number_Other)); break; // No
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- case 'Z':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Separator_Space) |
- FLAG(QChar::Separator_Line) |
- FLAG(QChar::Separator_Paragraph));
- } else {
- switch (category.at(1)) {
- case 's': yyCharClass->addCategories(FLAG(QChar::Separator_Space)); break; // Zs
- case 'l': yyCharClass->addCategories(FLAG(QChar::Separator_Line)); break; // Zl
- case 'p': yyCharClass->addCategories(FLAG(QChar::Separator_Paragraph)); break; // Zp
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- case 'C':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Other_Control) |
- FLAG(QChar::Other_Format) |
- FLAG(QChar::Other_Surrogate) |
- FLAG(QChar::Other_PrivateUse) |
- FLAG(QChar::Other_NotAssigned));
- } else {
- switch (category.at(1)) {
- case 'c': yyCharClass->addCategories(FLAG(QChar::Other_Control)); break; // Cc
- case 'f': yyCharClass->addCategories(FLAG(QChar::Other_Format)); break; // Cf
- case 's': yyCharClass->addCategories(FLAG(QChar::Other_Surrogate)); break; // Cs
- case 'o': yyCharClass->addCategories(FLAG(QChar::Other_PrivateUse)); break; // Co
- case 'n': yyCharClass->addCategories(FLAG(QChar::Other_NotAssigned)); break; // Cn
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- case 'L':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Letter_Uppercase) |
- FLAG(QChar::Letter_Lowercase) |
- FLAG(QChar::Letter_Titlecase) |
- FLAG(QChar::Letter_Modifier) |
- FLAG(QChar::Letter_Other));
- } else {
- switch (category.at(1)) {
- case 'u': yyCharClass->addCategories(FLAG(QChar::Letter_Uppercase)); break; // Lu
- case 'l': yyCharClass->addCategories(FLAG(QChar::Letter_Lowercase)); break; // Ll
- case 't': yyCharClass->addCategories(FLAG(QChar::Letter_Titlecase)); break; // Lt
- case 'm': yyCharClass->addCategories(FLAG(QChar::Letter_Modifier)); break; // Lm
- case 'o': yyCharClass->addCategories(FLAG(QChar::Letter_Other)); break; // Lo
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- case 'P':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Punctuation_Connector) |
- FLAG(QChar::Punctuation_Dash) |
- FLAG(QChar::Punctuation_Open) |
- FLAG(QChar::Punctuation_Close) |
- FLAG(QChar::Punctuation_InitialQuote) |
- FLAG(QChar::Punctuation_FinalQuote) |
- FLAG(QChar::Punctuation_Other));
- } else {
- switch (category.at(1)) {
- case 'c': yyCharClass->addCategories(FLAG(QChar::Punctuation_Connector)); break; // Pc
- case 'd': yyCharClass->addCategories(FLAG(QChar::Punctuation_Dash)); break; // Pd
- case 's': yyCharClass->addCategories(FLAG(QChar::Punctuation_Open)); break; // Ps
- case 'e': yyCharClass->addCategories(FLAG(QChar::Punctuation_Close)); break; // Pe
- case 'i': yyCharClass->addCategories(FLAG(QChar::Punctuation_InitialQuote)); break; // Pi
- case 'f': yyCharClass->addCategories(FLAG(QChar::Punctuation_FinalQuote)); break; // Pf
- case 'o': yyCharClass->addCategories(FLAG(QChar::Punctuation_Other)); break; // Po
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- case 'S':
- if (catlen == 1) {
- yyCharClass->addCategories(FLAG(QChar::Symbol_Math) |
- FLAG(QChar::Symbol_Currency) |
- FLAG(QChar::Symbol_Modifier) |
- FLAG(QChar::Symbol_Other));
- } else {
- switch (category.at(1)) {
- case 'm': yyCharClass->addCategories(FLAG(QChar::Symbol_Math)); break; // Sm
- case 'c': yyCharClass->addCategories(FLAG(QChar::Symbol_Currency)); break; // Sc
- case 'k': yyCharClass->addCategories(FLAG(QChar::Symbol_Modifier)); break; // Sk
- case 'o': yyCharClass->addCategories(FLAG(QChar::Symbol_Other)); break; // So
- default: error(RXERR_CATEGORY); break;
- }
- }
- break;
- default:
- error(RXERR_CATEGORY);
- break;
- }
- } else if (catlen > 2 && category.at(0) == 'I' && category.at(1) == 's') {
- static const int N = sizeof(categoriesRangeMap) / sizeof(categoriesRangeMap[0]);
- const char * const categoryFamily = category.constData() + 2;
- const CategoriesRangeMapEntry *r = std::lower_bound(categoriesRangeMap, categoriesRangeMap + N, categoryFamily);
- if (r != categoriesRangeMap + N && qstrcmp(r->name, categoryFamily) == 0)
- yyCharClass->addRange(r->first, r->second);
- else
- error(RXERR_CATEGORY);
- } else {
- error(RXERR_CATEGORY);
- }
- return Tok_CharClass;
- } else {
- break;
- }
-#endif
-#ifndef QT_NO_REGEXP_ESCAPE
- case 'x':
- val = 0;
- for (i = 0; i < 4; i++) {
- low = QChar(yyCh).toLower().unicode();
- if (low >= '0' && low <= '9')
- val = (val << 4) | (low - '0');
- else if (low >= 'a' && low <= 'f')
- val = (val << 4) | (low - 'a' + 10);
- else
- break;
- yyCh = getChar();
- }
- return Tok_Char | val;
-#endif
- default:
- break;
- }
- if (prevCh >= '1' && prevCh <= '9') {
-#ifndef QT_NO_REGEXP_BACKREF
- val = prevCh - '0';
- while (yyCh >= '0' && yyCh <= '9') {
- val = (val * 10) + (yyCh - '0');
- yyCh = getChar();
- }
- return Tok_BackRef | val;
-#else
- error(RXERR_DISABLED);
-#endif
- }
- return Tok_Char | prevCh;
-}
-
-#ifndef QT_NO_REGEXP_INTERVAL
-int QRegExpEngine::getRep(int def)
-{
- if (yyCh >= '0' && yyCh <= '9') {
- int rep = 0;
- do {
- rep = 10 * rep + yyCh - '0';
- if (rep >= InftyRep) {
- error(RXERR_REPETITION);
- rep = def;
- }
- yyCh = getChar();
- } while (yyCh >= '0' && yyCh <= '9');
- return rep;
- } else {
- return def;
- }
-}
-#endif
-
-#ifndef QT_NO_REGEXP_LOOKAHEAD
-void QRegExpEngine::skipChars(int n)
-{
- if (n > 0) {
- yyPos += n - 1;
- yyCh = getChar();
- }
-}
-#endif
-
-void QRegExpEngine::error(const char *msg)
-{
- if (yyError.isEmpty())
- yyError = QLatin1String(msg);
-}
-
-void QRegExpEngine::startTokenizer(const QChar *rx, int len)
-{
- yyIn = rx;
- yyPos0 = 0;
- yyPos = 0;
- yyLen = len;
- yyCh = getChar();
- yyCharClass.reset(new QRegExpCharClass);
- yyMinRep = 0;
- yyMaxRep = 0;
- yyError = QString();
-}
-
-int QRegExpEngine::getToken()
-{
-#ifndef QT_NO_REGEXP_CCLASS
- ushort pendingCh = 0;
- bool charPending;
- bool rangePending;
- int tok;
-#endif
- int prevCh = yyCh;
-
- yyPos0 = yyPos - 1;
-#ifndef QT_NO_REGEXP_CCLASS
- yyCharClass->clear();
-#endif
- yyMinRep = 0;
- yyMaxRep = 0;
- yyCh = getChar();
-
- switch (prevCh) {
- case EOS:
- yyPos0 = yyPos;
- return Tok_Eos;
- case '$':
- return Tok_Dollar;
- case '(':
- if (yyCh == '?') {
- prevCh = getChar();
- yyCh = getChar();
- switch (prevCh) {
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- case '!':
- return Tok_NegLookahead;
- case '=':
- return Tok_PosLookahead;
-#endif
- case ':':
- return Tok_MagicLeftParen;
- case '<':
- error(RXERR_LOOKBEHIND);
- return Tok_MagicLeftParen;
- default:
- error(RXERR_LOOKAHEAD);
- return Tok_MagicLeftParen;
- }
- } else {
- return Tok_LeftParen;
- }
- case ')':
- return Tok_RightParen;
- case '*':
- yyMinRep = 0;
- yyMaxRep = InftyRep;
- return Tok_Quantifier;
- case '+':
- yyMinRep = 1;
- yyMaxRep = InftyRep;
- return Tok_Quantifier;
- case '.':
-#ifndef QT_NO_REGEXP_CCLASS
- yyCharClass->setNegative(true);
-#endif
- return Tok_CharClass;
- case '?':
- yyMinRep = 0;
- yyMaxRep = 1;
- return Tok_Quantifier;
- case '[':
-#ifndef QT_NO_REGEXP_CCLASS
- if (yyCh == '^') {
- yyCharClass->setNegative(true);
- yyCh = getChar();
- }
- charPending = false;
- rangePending = false;
- do {
- if (yyCh == '-' && charPending && !rangePending) {
- rangePending = true;
- yyCh = getChar();
- } else {
- if (charPending && !rangePending) {
- yyCharClass->addSingleton(pendingCh);
- charPending = false;
- }
- if (yyCh == '\\') {
- yyCh = getChar();
- tok = getEscape();
- if (tok == Tok_Word)
- tok = '\b';
- } else {
- tok = Tok_Char | yyCh;
- yyCh = getChar();
- }
- if (tok == Tok_CharClass) {
- if (rangePending) {
- yyCharClass->addSingleton('-');
- yyCharClass->addSingleton(pendingCh);
- charPending = false;
- rangePending = false;
- }
- } else if ((tok & Tok_Char) != 0) {
- if (rangePending) {
- yyCharClass->addRange(pendingCh, tok ^ Tok_Char);
- charPending = false;
- rangePending = false;
- } else {
- pendingCh = tok ^ Tok_Char;
- charPending = true;
- }
- } else {
- error(RXERR_CHARCLASS);
- }
- }
- } while (yyCh != ']' && yyCh != EOS);
- if (rangePending)
- yyCharClass->addSingleton('-');
- if (charPending)
- yyCharClass->addSingleton(pendingCh);
- if (yyCh == EOS)
- error(RXERR_END);
- else
- yyCh = getChar();
- return Tok_CharClass;
-#else
- error(RXERR_END);
- return Tok_Char | '[';
-#endif
- case '\\':
- return getEscape();
- case ']':
- error(RXERR_LEFTDELIM);
- return Tok_Char | ']';
- case '^':
- return Tok_Caret;
- case '{':
-#ifndef QT_NO_REGEXP_INTERVAL
- yyMinRep = getRep(0);
- yyMaxRep = yyMinRep;
- if (yyCh == ',') {
- yyCh = getChar();
- yyMaxRep = getRep(InftyRep);
- }
- if (yyMaxRep < yyMinRep)
- error(RXERR_INTERVAL);
- if (yyCh != '}')
- error(RXERR_REPETITION);
- yyCh = getChar();
- return Tok_Quantifier;
-#else
- error(RXERR_DISABLED);
- return Tok_Char | '{';
-#endif
- case '|':
- return Tok_Bar;
- case '}':
- error(RXERR_LEFTDELIM);
- return Tok_Char | '}';
- default:
- return Tok_Char | prevCh;
- }
-}
-
-int QRegExpEngine::parse(const QChar *pattern, int len)
-{
- valid = true;
- startTokenizer(pattern, len);
- yyTok = getToken();
-#ifndef QT_NO_REGEXP_CAPTURE
- yyMayCapture = true;
-#else
- yyMayCapture = false;
-#endif
-
-#ifndef QT_NO_REGEXP_CAPTURE
- int atom = startAtom(false);
-#endif
- QRegExpCharClass anything;
- Box box(this); // create InitialState
- box.set(anything);
- Box rightBox(this); // create FinalState
- rightBox.set(anything);
-
- Box middleBox(this);
- parseExpression(&middleBox);
-#ifndef QT_NO_REGEXP_CAPTURE
- finishAtom(atom, false);
-#endif
-#ifndef QT_NO_REGEXP_OPTIM
- middleBox.setupHeuristics();
-#endif
- box.cat(middleBox);
- box.cat(rightBox);
- yyCharClass.reset();
-
-#ifndef QT_NO_REGEXP_CAPTURE
- for (int i = 0; i < nf; ++i) {
- switch (f[i].capture) {
- case QRegExpAtom::NoCapture:
- break;
- case QRegExpAtom::OfficialCapture:
- f[i].capture = ncap;
- captureForOfficialCapture.append(ncap);
- ++ncap;
- ++officialncap;
- break;
- case QRegExpAtom::UnofficialCapture:
- f[i].capture = greedyQuantifiers ? ncap++ : QRegExpAtom::NoCapture;
- }
- }
-
-#ifndef QT_NO_REGEXP_BACKREF
-#ifndef QT_NO_REGEXP_OPTIM
- if (officialncap == 0 && nbrefs == 0) {
- ncap = nf = 0;
- f.clear();
- }
-#endif
- // handle the case where there's a \5 with no corresponding capture
- // (captureForOfficialCapture.size() != officialncap)
- for (int i = 0; i < nbrefs - officialncap; ++i) {
- captureForOfficialCapture.append(ncap);
- ++ncap;
- }
-#endif
-#endif
-
- if (!yyError.isEmpty())
- return -1;
-
-#ifndef QT_NO_REGEXP_OPTIM
- const QRegExpAutomatonState &sinit = s.at(InitialState);
- caretAnchored = !sinit.anchors.isEmpty();
- if (caretAnchored) {
- const QMap<int, int> &anchors = sinit.anchors;
- QMap<int, int>::const_iterator a;
- for (a = anchors.constBegin(); a != anchors.constEnd(); ++a) {
- if (
-#ifndef QT_NO_REGEXP_ANCHOR_ALT
- (*a & Anchor_Alternation) != 0 ||
-#endif
- (*a & Anchor_Caret) == 0)
- {
- caretAnchored = false;
- break;
- }
- }
- }
-#endif
-
- // cleanup anchors
- int numStates = s.count();
- for (int i = 0; i < numStates; ++i) {
- QRegExpAutomatonState &state = s[i];
- if (!state.anchors.isEmpty()) {
- QMap<int, int>::iterator a = state.anchors.begin();
- while (a != state.anchors.end()) {
- if (a.value() == 0)
- a = state.anchors.erase(a);
- else
- ++a;
- }
- }
- }
-
- return yyPos0;
-}
-
-void QRegExpEngine::parseAtom(Box *box)
-{
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- QRegExpEngine *eng = nullptr;
- bool neg;
- int len;
-#endif
-
- if ((yyTok & Tok_Char) != 0) {
- box->set(QChar(yyTok ^ Tok_Char));
- } else {
-#ifndef QT_NO_REGEXP_OPTIM
- trivial = false;
-#endif
- switch (yyTok) {
- case Tok_Dollar:
- box->catAnchor(Anchor_Dollar);
- break;
- case Tok_Caret:
- box->catAnchor(Anchor_Caret);
- break;
-#ifndef QT_NO_REGEXP_LOOKAHEAD
- case Tok_PosLookahead:
- case Tok_NegLookahead:
- neg = (yyTok == Tok_NegLookahead);
- eng = new QRegExpEngine(cs, greedyQuantifiers);
- len = eng->parse(yyIn + yyPos - 1, yyLen - yyPos + 1);
- if (len >= 0)
- skipChars(len);
- else
- error(RXERR_LOOKAHEAD);
- box->catAnchor(addLookahead(eng, neg));
- yyTok = getToken();
- if (yyTok != Tok_RightParen)
- error(RXERR_LOOKAHEAD);
- break;
-#endif
-#ifndef QT_NO_REGEXP_ESCAPE
- case Tok_Word:
- box->catAnchor(Anchor_Word);
- break;
- case Tok_NonWord:
- box->catAnchor(Anchor_NonWord);
- break;
-#endif
- case Tok_LeftParen:
- case Tok_MagicLeftParen:
- yyTok = getToken();
- parseExpression(box);
- if (yyTok != Tok_RightParen)
- error(RXERR_END);
- break;
- case Tok_CharClass:
- box->set(*yyCharClass);
- break;
- case Tok_Quantifier:
- error(RXERR_REPETITION);
- break;
- default:
-#ifndef QT_NO_REGEXP_BACKREF
- if ((yyTok & Tok_BackRef) != 0)
- box->set(yyTok ^ Tok_BackRef);
- else
-#endif
- error(RXERR_DISABLED);
- }
- }
- yyTok = getToken();
-}
-
-void QRegExpEngine::parseFactor(Box *box)
-{
-#ifndef QT_NO_REGEXP_CAPTURE
- int outerAtom = greedyQuantifiers ? startAtom(false) : -1;
- int innerAtom = startAtom(yyMayCapture && yyTok == Tok_LeftParen);
- bool magicLeftParen = (yyTok == Tok_MagicLeftParen);
-#else
- const int innerAtom = -1;
-#endif
-
-#ifndef QT_NO_REGEXP_INTERVAL
-#define YYREDO() \
- yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \
- *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok
-
- const QChar *in = yyIn;
- int pos0 = yyPos0;
- int pos = yyPos;
- int len = yyLen;
- int ch = yyCh;
- QRegExpCharClass charClass;
- if (yyTok == Tok_CharClass)
- charClass = *yyCharClass;
- int tok = yyTok;
- bool mayCapture = yyMayCapture;
-#endif
-
- parseAtom(box);
-#ifndef QT_NO_REGEXP_CAPTURE
- finishAtom(innerAtom, magicLeftParen);
-#endif
-
- bool hasQuantifier = (yyTok == Tok_Quantifier);
- if (hasQuantifier) {
-#ifndef QT_NO_REGEXP_OPTIM
- trivial = false;
-#endif
- if (yyMaxRep == InftyRep) {
- box->plus(innerAtom);
-#ifndef QT_NO_REGEXP_INTERVAL
- } else if (yyMaxRep == 0) {
- box->clear();
-#endif
- }
- if (yyMinRep == 0)
- box->opt();
-
-#ifndef QT_NO_REGEXP_INTERVAL
- yyMayCapture = false;
- int alpha = (yyMinRep == 0) ? 0 : yyMinRep - 1;
- int beta = (yyMaxRep == InftyRep) ? 0 : yyMaxRep - (alpha + 1);
-
- Box rightBox(this);
- int i;
-
- for (i = 0; i < beta; i++) {
- YYREDO();
- Box leftBox(this);
- parseAtom(&leftBox);
- leftBox.cat(rightBox);
- leftBox.opt();
- rightBox = leftBox;
- }
- for (i = 0; i < alpha; i++) {
- YYREDO();
- Box leftBox(this);
- parseAtom(&leftBox);
- leftBox.cat(rightBox);
- rightBox = leftBox;
- }
- rightBox.cat(*box);
- *box = rightBox;
-#endif
- yyTok = getToken();
-#ifndef QT_NO_REGEXP_INTERVAL
- yyMayCapture = mayCapture;
-#endif
- }
-#undef YYREDO
-#ifndef QT_NO_REGEXP_CAPTURE
- if (greedyQuantifiers)
- finishAtom(outerAtom, hasQuantifier);
-#endif
-}
-
-void QRegExpEngine::parseTerm(Box *box)
-{
-#ifndef QT_NO_REGEXP_OPTIM
- if (yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar)
- parseFactor(box);
-#endif
- while (yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar) {
- Box rightBox(this);
- parseFactor(&rightBox);
- box->cat(rightBox);
- }
-}
-
-void QRegExpEngine::parseExpression(Box *box)
-{
- parseTerm(box);
- while (yyTok == Tok_Bar) {
-#ifndef QT_NO_REGEXP_OPTIM
- trivial = false;
-#endif
- Box rightBox(this);
- yyTok = getToken();
- parseTerm(&rightBox);
- box->orx(rightBox);
- }
-}
-
-/*
- The struct QRegExpPrivate contains the private data of a regular
- expression other than the automaton. It makes it possible for many
- QRegExp objects to use the same QRegExpEngine object with different
- QRegExpPrivate objects.
-*/
-struct QRegExpPrivate
-{
- QRegExpEngine *eng;
- QRegExpEngineKey engineKey;
- bool minimal;
-#ifndef QT_NO_REGEXP_CAPTURE
- QString t; // last string passed to QRegExp::indexIn() or lastIndexIn()
- QStringList capturedCache; // what QRegExp::capturedTexts() returned last
-#endif
- QRegExpMatchState matchState;
-
- inline QRegExpPrivate()
- : eng(nullptr), engineKey(QString(), QRegExp::RegExp, Qt::CaseSensitive), minimal(false) { }
- inline QRegExpPrivate(const QRegExpEngineKey &key)
- : eng(nullptr), engineKey(key), minimal(false) {}
-};
-
-#if !defined(QT_NO_REGEXP_OPTIM)
-struct QRECache
-{
- typedef QHash<QRegExpEngineKey, QRegExpEngine *> EngineCache;
- typedef QCache<QRegExpEngineKey, QRegExpEngine> UnusedEngineCache;
- EngineCache usedEngines;
- UnusedEngineCache unusedEngines;
-};
-Q_GLOBAL_STATIC(QRECache, engineCache)
-static QBasicMutex engineCacheMutex;
-#endif // QT_NO_REGEXP_OPTIM
-
-static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key)
-{
-#if !defined(QT_NO_REGEXP_OPTIM)
- const auto locker = qt_scoped_lock(engineCacheMutex);
- if (!eng->ref.deref()) {
- if (QRECache *c = engineCache()) {
- c->unusedEngines.insert(key, eng, 4 + key.pattern.length() / 4);
- c->usedEngines.remove(key);
- } else {
- delete eng;
- }
- }
-#else
- Q_UNUSED(key);
- if (!eng->ref.deref())
- delete eng;
-#endif
-}
-
-static void prepareEngine_helper(QRegExpPrivate *priv)
-{
- Q_ASSERT(!priv->eng);
-
-#if !defined(QT_NO_REGEXP_OPTIM)
- const auto locker = qt_scoped_lock(engineCacheMutex);
- if (QRECache *c = engineCache()) {
- priv->eng = c->unusedEngines.take(priv->engineKey);
- if (!priv->eng)
- priv->eng = c->usedEngines.value(priv->engineKey);
- if (!priv->eng)
- priv->eng = new QRegExpEngine(priv->engineKey);
- else
- priv->eng->ref.ref();
-
- c->usedEngines.insert(priv->engineKey, priv->eng);
- return;
- }
-#endif // QT_NO_REGEXP_OPTIM
-
- priv->eng = new QRegExpEngine(priv->engineKey);
-}
-
-inline static void prepareEngine(QRegExpPrivate *priv)
-{
- if (priv->eng)
- return;
- prepareEngine_helper(priv);
- priv->matchState.prepareForMatch(priv->eng);
-}
-
-static void prepareEngineForMatch(QRegExpPrivate *priv, const QString &str)
-{
- prepareEngine(priv);
- priv->matchState.prepareForMatch(priv->eng);
-#ifndef QT_NO_REGEXP_CAPTURE
- priv->t = str;
- priv->capturedCache.clear();
-#else
- Q_UNUSED(str);
-#endif
-}
-
-static void invalidateEngine(QRegExpPrivate *priv)
-{
- if (priv->eng) {
- derefEngine(priv->eng, priv->engineKey);
- priv->eng = nullptr;
- priv->matchState.drain();
- }
-}
-
-/*!
- \enum QRegExp::CaretMode
-
- The CaretMode enum defines the different meanings of the caret
- (\b{^}) in a regular expression. The possible values are:
-
- \value CaretAtZero
- The caret corresponds to index 0 in the searched string.
-
- \value CaretAtOffset
- The caret corresponds to the start offset of the search.
-
- \value CaretWontMatch
- The caret never matches.
-*/
-
-/*!
- \enum QRegExp::PatternSyntax
-
- The syntax used to interpret the meaning of the pattern.
-
- \value RegExp A rich Perl-like pattern matching syntax. This is
- the default.
-
- \value RegExp2 Like RegExp, but with \l{greedy quantifiers}.
- (Introduced in Qt 4.2.)
-
- \value Wildcard This provides a simple pattern matching syntax
- similar to that used by shells (command interpreters) for "file
- globbing". See \l{QRegExp wildcard matching}.
-
- \value WildcardUnix This is similar to Wildcard but with the
- behavior of a Unix shell. The wildcard characters can be escaped
- with the character "\\".
-
- \value FixedString The pattern is a fixed string. This is
- equivalent to using the RegExp pattern on a string in
- which all metacharacters are escaped using escape().
-
- \value W3CXmlSchema11 The pattern is a regular expression as
- defined by the W3C XML Schema 1.1 specification.
-
- \sa setPatternSyntax()
-*/
-
-/*!
- Constructs an empty regexp.
-
- \sa isValid(), errorString()
-*/
-QRegExp::QRegExp()
-{
- priv = new QRegExpPrivate;
- prepareEngine(priv);
-}
-
-/*!
- Constructs a regular expression object for the given \a pattern
- string. The pattern must be given using wildcard notation if \a
- syntax is \l Wildcard; the default is \l RegExp. The pattern is
- case sensitive, unless \a cs is Qt::CaseInsensitive. Matching is
- greedy (maximal), but can be changed by calling
- setMinimal().
-
- \sa setPattern(), setCaseSensitivity(), setPatternSyntax()
-*/
-QRegExp::QRegExp(const QString &pattern, Qt::CaseSensitivity cs, PatternSyntax syntax)
-{
- priv = new QRegExpPrivate(QRegExpEngineKey(pattern, syntax, cs));
- prepareEngine(priv);
-}
-
-/*!
- Constructs a regular expression as a copy of \a rx.
-
- \sa operator=()
-*/
-QRegExp::QRegExp(const QRegExp &rx)
-{
- priv = new QRegExpPrivate;
- operator=(rx);
-}
-
-/*!
- Destroys the regular expression and cleans up its internal data.
-*/
-QRegExp::~QRegExp()
-{
- invalidateEngine(priv);
- delete priv;
-}
-
-/*!
- Copies the regular expression \a rx and returns a reference to the
- copy. The case sensitivity, wildcard, and minimal matching options
- are also copied.
-*/
-QRegExp &QRegExp::operator=(const QRegExp &rx)
-{
- prepareEngine(rx.priv); // to allow sharing
- QRegExpEngine *otherEng = rx.priv->eng;
- if (otherEng)
- otherEng->ref.ref();
- invalidateEngine(priv);
- priv->eng = otherEng;
- priv->engineKey = rx.priv->engineKey;
- priv->minimal = rx.priv->minimal;
-#ifndef QT_NO_REGEXP_CAPTURE
- priv->t = rx.priv->t;
- priv->capturedCache = rx.priv->capturedCache;
-#endif
- if (priv->eng)
- priv->matchState.prepareForMatch(priv->eng);
- priv->matchState.captured = rx.priv->matchState.captured;
- return *this;
-}
-
-/*!
- \fn QRegExp &QRegExp::operator=(QRegExp &&other)
-
- Move-assigns \a other to this QRegExp instance.
-
- \since 5.2
-*/
-
-/*!
- \fn void QRegExp::swap(QRegExp &other)
- \since 4.8
-
- Swaps regular expression \a other with this regular
- expression. This operation is very fast and never fails.
-*/
-
-/*!
- Returns \c true if this regular expression is equal to \a rx;
- otherwise returns \c false.
-
- Two QRegExp objects are equal if they have the same pattern
- strings and the same settings for case sensitivity, wildcard and
- minimal matching.
-*/
-bool QRegExp::operator==(const QRegExp &rx) const
-{
- return priv->engineKey == rx.priv->engineKey && priv->minimal == rx.priv->minimal;
-}
-
-/*!
- \since 5.6
- \relates QRegExp
-
- Returns the hash value for \a key, using
- \a seed to seed the calculation.
-*/
-size_t qHash(const QRegExp &key, size_t seed) noexcept
-{
- QtPrivate::QHashCombine hash;
- seed = hash(seed, key.priv->engineKey);
- seed = hash(seed, key.priv->minimal);
- return seed;
-}
-
-/*!
- \fn bool QRegExp::operator!=(const QRegExp &rx) const
-
- Returns \c true if this regular expression is not equal to \a rx;
- otherwise returns \c false.
-
- \sa operator==()
-*/
-
-/*!
- Returns \c true if the pattern string is empty; otherwise returns
- false.
-
- If you call exactMatch() with an empty pattern on an empty string
- it will return true; otherwise it returns \c false since it operates
- over the whole string. If you call indexIn() with an empty pattern
- on \e any string it will return the start offset (0 by default)
- because the empty pattern matches the 'emptiness' at the start of
- the string. In this case the length of the match returned by
- matchedLength() will be 0.
-
- See QString::isEmpty().
-*/
-
-bool QRegExp::isEmpty() const
-{
- return priv->engineKey.pattern.isEmpty();
-}
-
-/*!
- Returns \c true if the regular expression is valid; otherwise returns
- false. An invalid regular expression never matches.
-
- The pattern \b{[a-z} is an example of an invalid pattern, since
- it lacks a closing square bracket.
-
- Note that the validity of a regexp may also depend on the setting
- of the wildcard flag, for example \b{*.html} is a valid
- wildcard regexp but an invalid full regexp.
-
- \sa errorString()
-*/
-bool QRegExp::isValid() const
-{
- if (priv->engineKey.pattern.isEmpty()) {
- return true;
- } else {
- prepareEngine(priv);
- return priv->eng->isValid();
- }
-}
-
-/*!
- Returns the pattern string of the regular expression. The pattern
- has either regular expression syntax or wildcard syntax, depending
- on patternSyntax().
-
- \sa patternSyntax(), caseSensitivity()
-*/
-QString QRegExp::pattern() const
-{
- return priv->engineKey.pattern;
-}
-
-/*!
- Sets the pattern string to \a pattern. The case sensitivity,
- wildcard, and minimal matching options are not changed.
-
- \sa setPatternSyntax(), setCaseSensitivity()
-*/
-void QRegExp::setPattern(const QString &pattern)
-{
- if (priv->engineKey.pattern != pattern) {
- invalidateEngine(priv);
- priv->engineKey.pattern = pattern;
- }
-}
-
-/*!
- Returns Qt::CaseSensitive if the regexp is matched case
- sensitively; otherwise returns Qt::CaseInsensitive.
-
- \sa patternSyntax(), pattern(), isMinimal()
-*/
-Qt::CaseSensitivity QRegExp::caseSensitivity() const
-{
- return priv->engineKey.cs;
-}
-
-/*!
- Sets case sensitive matching to \a cs.
-
- If \a cs is Qt::CaseSensitive, \b{\\.txt$} matches
- \c{readme.txt} but not \c{README.TXT}.
-
- \sa setPatternSyntax(), setPattern(), setMinimal()
-*/
-void QRegExp::setCaseSensitivity(Qt::CaseSensitivity cs)
-{
- if ((bool)cs != (bool)priv->engineKey.cs) {
- invalidateEngine(priv);
- priv->engineKey.cs = cs;
- }
-}
-
-/*!
- Returns the syntax used by the regular expression. The default is
- QRegExp::RegExp.
-
- \sa pattern(), caseSensitivity()
-*/
-QRegExp::PatternSyntax QRegExp::patternSyntax() const
-{
- return priv->engineKey.patternSyntax;
-}
-
-/*!
- Sets the syntax mode for the regular expression. The default is
- QRegExp::RegExp.
-
- Setting \a syntax to QRegExp::Wildcard enables simple shell-like
- \l{QRegExp wildcard matching}. For example, \b{r*.txt} matches the
- string \c{readme.txt} in wildcard mode, but does not match
- \c{readme}.
-
- Setting \a syntax to QRegExp::FixedString means that the pattern
- is interpreted as a plain string. Special characters (e.g.,
- backslash) don't need to be escaped then.
-
- \sa setPattern(), setCaseSensitivity(), escape()
-*/
-void QRegExp::setPatternSyntax(PatternSyntax syntax)
-{
- if (syntax != priv->engineKey.patternSyntax) {
- invalidateEngine(priv);
- priv->engineKey.patternSyntax = syntax;
- }
-}
-
-/*!
- Returns \c true if minimal (non-greedy) matching is enabled;
- otherwise returns \c false.
-
- \sa caseSensitivity(), setMinimal()
-*/
-bool QRegExp::isMinimal() const
-{
- return priv->minimal;
-}
-
-/*!
- Enables or disables minimal matching. If \a minimal is false,
- matching is greedy (maximal) which is the default.
-
- For example, suppose we have the input string "We must be
- <b>bold</b>, very <b>bold</b>!" and the pattern
- \b{<b>.*</b>}. With the default greedy (maximal) matching,
- the match is "We must be \underline{<b>bold</b>, very
- <b>bold</b>}!". But with minimal (non-greedy) matching, the
- first match is: "We must be \underline{<b>bold</b>}, very
- <b>bold</b>!" and the second match is "We must be <b>bold</b>,
- very \underline{<b>bold</b>}!". In practice we might use the pattern
- \b{<b>[^<]*\</b>} instead, although this will still fail for
- nested tags.
-
- \sa setCaseSensitivity()
-*/
-void QRegExp::setMinimal(bool minimal)
-{
- priv->minimal = minimal;
-}
-
-// ### Qt 5: make non-const
-/*!
- Returns \c true if \a str is matched exactly by this regular
- expression; otherwise returns \c false. You can determine how much of
- the string was matched by calling matchedLength().
-
- For a given regexp string R, exactMatch("R") is the equivalent of
- indexIn("^R$") since exactMatch() effectively encloses the regexp
- in the start of string and end of string anchors, except that it
- sets matchedLength() differently.
-
- For example, if the regular expression is \b{blue}, then
- exactMatch() returns \c true only for input \c blue. For inputs \c
- bluebell, \c blutak and \c lightblue, exactMatch() returns \c false
- and matchedLength() will return 4, 3 and 0 respectively.
-
- Although const, this function sets matchedLength(),
- capturedTexts(), and pos().
-
- \sa indexIn(), lastIndexIn()
-*/
-bool QRegExp::exactMatch(const QString &str) const
-{
- prepareEngineForMatch(priv, str);
- priv->matchState.match(str.unicode(), str.length(), 0, priv->minimal, true, 0);
- if (priv->matchState.captured[1] == str.length()) {
- return true;
- } else {
- priv->matchState.captured[0] = 0;
- priv->matchState.captured[1] = priv->matchState.oneTestMatchedLen;
- return false;
- }
-}
-
-/*!
- Returns the regexp as a QVariant
-*/
-QRegExp::operator QVariant() const
-{
-QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
- QVariant v;
- v.setValue(*this);
- return v;
-QT_WARNING_POP
-}
-
-// ### Qt 5: make non-const
-/*!
- Attempts to find a match in \a str from position \a offset (0 by
- default). If \a offset is -1, the search starts at the last
- character; if -2, at the next to last character; etc.
-
- Returns the position of the first match, or -1 if there was no
- match.
-
- The \a caretMode parameter can be used to instruct whether \b{^}
- should match at index 0 or at \a offset.
-
- You might prefer to use QString::indexOf(), QString::contains(),
- or even QStringList::filter(). To replace matches use
- QString::replace().
-
- Example:
- \snippet code/src_corelib_text_qregexp.cpp 13
-
- Although const, this function sets matchedLength(),
- capturedTexts() and pos().
-
- If the QRegExp is a wildcard expression (see setPatternSyntax())
- and want to test a string against the whole wildcard expression,
- use exactMatch() instead of this function.
-
- \sa lastIndexIn(), exactMatch()
-*/
-
-int QRegExp::indexIn(const QString &str, int offset, CaretMode caretMode) const
-{
- prepareEngineForMatch(priv, str);
- if (offset < 0)
- offset += str.length();
- priv->matchState.match(str.unicode(), str.length(), offset,
- priv->minimal, false, caretIndex(offset, caretMode));
- return priv->matchState.captured[0];
-}
-
-// ### Qt 5: make non-const
-/*!
- Attempts to find a match backwards in \a str from position \a
- offset. If \a offset is -1 (the default), the search starts at the
- last character; if -2, at the next to last character; etc.
-
- Returns the position of the first match, or -1 if there was no
- match.
-
- The \a caretMode parameter can be used to instruct whether \b{^}
- should match at index 0 or at \a offset.
-
- Although const, this function sets matchedLength(),
- capturedTexts() and pos().
-
- \warning Searching backwards is much slower than searching
- forwards.
-
- \sa indexIn(), exactMatch()
-*/
-
-int QRegExp::lastIndexIn(const QString &str, int offset, CaretMode caretMode) const
-{
- prepareEngineForMatch(priv, str);
- if (offset < 0)
- offset += str.length();
- if (offset < 0 || offset > str.length()) {
- memset(priv->matchState.captured, -1, priv->matchState.capturedSize*sizeof(int));
- return -1;
- }
-
- while (offset >= 0) {
- priv->matchState.match(str.unicode(), str.length(), offset,
- priv->minimal, true, caretIndex(offset, caretMode));
- if (priv->matchState.captured[0] == offset)
- return offset;
- --offset;
- }
- return -1;
-}
-
-/*!
- Returns the length of the last matched string, or -1 if there was
- no match.
-
- \sa exactMatch(), indexIn(), lastIndexIn()
-*/
-int QRegExp::matchedLength() const
-{
- return priv->matchState.captured[1];
-}
-
-
-/*!
- Replaces every occurrence of this regular expression in
- \a str with \a after and returns the result.
-
- For regular expressions containing \l{capturing parentheses},
- occurrences of \b{\\1}, \b{\\2}, ..., in \a after are replaced
- with \a{rx}.cap(1), cap(2), ...
-
- \sa indexIn(), lastIndexIn(), QRegExp::cap()
-*/
-QString QRegExp::replaceIn(const QString &str, const QString &after) const
-{
- struct QStringCapture
- {
- int pos;
- int len;
- int no;
- };
-
- QRegExp rx2(*this);
-
- if (str.isEmpty() && rx2.indexIn(str) == -1)
- return str;
-
- QString s(str);
-
- int index = 0;
- int numCaptures = rx2.captureCount();
- int al = after.length();
- QRegExp::CaretMode caretMode = QRegExp::CaretAtZero;
-
- if (numCaptures > 0) {
- const QChar *uc = after.unicode();
- int numBackRefs = 0;
-
- for (int i = 0; i < al - 1; i++) {
- if (uc[i] == QLatin1Char('\\')) {
- int no = uc[i + 1].digitValue();
- if (no > 0 && no <= numCaptures)
- numBackRefs++;
- }
- }
-
- /*
- This is the harder case where we have back-references.
- */
- if (numBackRefs > 0) {
- QVarLengthArray<QStringCapture, 16> captures(numBackRefs);
- int j = 0;
-
- for (int i = 0; i < al - 1; i++) {
- if (uc[i] == QLatin1Char('\\')) {
- int no = uc[i + 1].digitValue();
- if (no > 0 && no <= numCaptures) {
- QStringCapture capture;
- capture.pos = i;
- capture.len = 2;
-
- if (i < al - 2) {
- int secondDigit = uc[i + 2].digitValue();
- if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) {
- no = (no * 10) + secondDigit;
- ++capture.len;
- }
- }
-
- capture.no = no;
- captures[j++] = capture;
- }
- }
- }
-
- while (index <= s.length()) {
- index = rx2.indexIn(s, index, caretMode);
- if (index == -1)
- break;
-
- QString after2(after);
- for (j = numBackRefs - 1; j >= 0; j--) {
- const QStringCapture &capture = captures[j];
- after2.replace(capture.pos, capture.len, rx2.cap(capture.no));
- }
-
- s.replace(index, rx2.matchedLength(), after2);
- index += after2.length();
-
- // avoid infinite loop on 0-length matches (e.g., QRegExp("[a-z]*"))
- if (rx2.matchedLength() == 0)
- ++index;
-
- caretMode = QRegExp::CaretWontMatch;
- }
- return s;
- }
- }
-
- /*
- This is the simple and optimized case where we don't have
- back-references.
- */
- while (index != -1) {
- struct {
- int pos;
- int length;
- } replacements[2048];
-
- int pos = 0;
- int adjust = 0;
- while (pos < 2047) {
- index = rx2.indexIn(s, index, caretMode);
- if (index == -1)
- break;
- int ml = rx2.matchedLength();
- replacements[pos].pos = index;
- replacements[pos++].length = ml;
- index += ml;
- adjust += al - ml;
- // avoid infinite loop
- if (!ml)
- index++;
- }
- if (!pos)
- break;
- replacements[pos].pos = s.size();
- int newlen = s.size() + adjust;
-
- // to continue searching at the right position after we did
- // the first round of replacements
- if (index != -1)
- index += adjust;
- QString newstring;
- newstring.reserve(newlen + 1);
- QChar *newuc = newstring.data();
- QChar *uc = newuc;
- int copystart = 0;
- int i = 0;
- while (i < pos) {
- int copyend = replacements[i].pos;
- int size = copyend - copystart;
- memcpy(static_cast<void*>(uc), static_cast<const void *>(s.constData() + copystart), size * sizeof(QChar));
- uc += size;
- memcpy(static_cast<void *>(uc), static_cast<const void *>(after.constData()), al * sizeof(QChar));
- uc += al;
- copystart = copyend + replacements[i].length;
- i++;
- }
- memcpy(static_cast<void *>(uc), static_cast<const void *>(s.constData() + copystart), (s.size() - copystart) * sizeof(QChar));
- newstring.resize(newlen);
- s = newstring;
- caretMode = QRegExp::CaretWontMatch;
- }
- return s;
-
-}
-
-
-/*!
- \fn QString QRegExp::removeIn(const QString &str)
-
- Removes every occurrence of this regular expression \a str, and
- returns the result
-
- Does the same as replaceIn(str, QString()).
-
- \sa indexIn(), lastIndexIn(), replaceIn()
-*/
-
-
-/*!
- \fn QString QRegExp::countIn(const QString &str)
-
- Returns the number of times this regular expression matches
- in \a str.
-
- \sa indexIn(), lastIndexIn(), replaceIn()
-*/
-
-int QRegExp::countIn(const QString &str) const
-{
- QRegExp rx2(*this);
- int count = 0;
- int index = -1;
- int len = str.length();
- while (index < len - 1) { // count overlapping matches
- index = rx2.indexIn(str, index + 1);
- if (index == -1)
- break;
- count++;
- }
- return count;
-}
-
-/*!
- Splits \a str into substrings wherever this regular expression
- matches, and returns the list of those strings. If this regular
- expression does not match anywhere in the string, split() returns a
- single-element list containing \a str.
-
- \sa QStringList::join(), section(), QString::split()
-*/
-QStringList QRegExp::splitString(const QString &str, Qt::SplitBehavior behavior) const
-{
- QRegExp rx2(*this);
- QStringList list;
- int start = 0;
- int extra = 0;
- int end;
- while ((end = rx2.indexIn(str, start + extra)) != -1) {
- int matchedLen = rx2.matchedLength();
- if (start != end || behavior == Qt::KeepEmptyParts)
- list.append(str.mid(start, end - start));
- start = end + matchedLen;
- extra = (matchedLen == 0) ? 1 : 0;
- }
- if (start != str.size() || behavior == Qt::KeepEmptyParts)
- list.append(str.mid(start, -1));
- return list;
-}
-
-/*!
- \fn QStringList QStringList::filter(const QRegExp &rx) const
-
- \overload
-
- Returns a list of all the strings that match the regular
- expression \a rx.
-*/
-QStringList QRegExp::filterList(const QStringList &stringList) const
-{
- QStringList res;
- for (const QString &s : stringList) {
- if (containedIn(s))
- res << s;
- }
- return res;
-}
-
-/*!
- Replaces every occurrence of the regexp \a rx, in each of the
- string lists's strings, with \a after. Returns a reference to the
- string list.
-*/
-QStringList QRegExp::replaceIn(const QStringList &stringList, const QString &after) const
-{
- QStringList list;
- for (const QString &s : stringList)
- list << replaceIn(s, after);
- return list;
-}
-
-/*!
- Returns the index position of the first exact match of this regexp in
- \a list, searching forward from index position \a from. Returns
- -1 if no item matched.
-
- \sa lastIndexIn(), contains(), exactMatch()
-*/
-int QRegExp::indexIn(const QStringList &list, int from) const
-{
- QRegExp rx2(*this);
- if (from < 0)
- from = qMax(from + list.size(), 0);
- for (int i = from; i < list.size(); ++i) {
- if (rx2.exactMatch(list.at(i)))
- return i;
- }
- return -1;
-}
-
-/*!
- Returns the index position of the last exact match of this regexp in
- \a list, searching backward from index position \a from. If \a
- from is -1 (the default), the search starts at the last item.
- Returns -1 if no item matched.
-
- \sa indexOf(), contains(), QRegExp::exactMatch()
-*/
-int QRegExp::lastIndexIn(const QStringList &list, int from) const
-{
- QRegExp rx2(*this);
- if (from < 0)
- from += list.size();
- else if (from >= list.size())
- from = list.size() - 1;
- for (int i = from; i >= 0; --i) {
- if (rx2.exactMatch(list.at(i)))
- return i;
- }
- return -1;
-}
-
-#ifndef QT_NO_REGEXP_CAPTURE
-
-/*!
- \since 4.6
- Returns the number of captures contained in the regular expression.
- */
-int QRegExp::captureCount() const
-{
- prepareEngine(priv);
- return priv->eng->captureCount();
-}
-
-/*!
- Returns a list of the captured text strings.
-
- The first string in the list is the entire matched string. Each
- subsequent list element contains a string that matched a
- (capturing) subexpression of the regexp.
-
- For example:
- \snippet code/src_corelib_text_qregexp.cpp 14
-
- The above example also captures elements that may be present but
- which we have no interest in. This problem can be solved by using
- non-capturing parentheses:
-
- \snippet code/src_corelib_text_qregexp.cpp 15
-
- Note that if you want to iterate over the list, you should iterate
- over a copy, e.g.
- \snippet code/src_corelib_text_qregexp.cpp 16
-
- Some regexps can match an indeterminate number of times. For
- example if the input string is "Offsets: 12 14 99 231 7" and the
- regexp, \c{rx}, is \b{(\\d+)+}, we would hope to get a list of
- all the numbers matched. However, after calling
- \c{rx.indexIn(str)}, capturedTexts() will return the list ("12",
- "12"), i.e. the entire match was "12" and the first subexpression
- matched was "12". The correct approach is to use cap() in a
- \l{QRegExp#cap_in_a_loop}{loop}.
-
- The order of elements in the string list is as follows. The first
- element is the entire matching string. Each subsequent element
- corresponds to the next capturing open left parentheses. Thus
- capturedTexts()[1] is the text of the first capturing parentheses,
- capturedTexts()[2] is the text of the second and so on
- (corresponding to $1, $2, etc., in some other regexp languages).
-
- \sa cap(), pos()
-*/
-QStringList QRegExp::capturedTexts() const
-{
- if (priv->capturedCache.isEmpty()) {
- prepareEngine(priv);
- const int *captured = priv->matchState.captured;
- int n = priv->matchState.capturedSize;
-
- for (int i = 0; i < n; i += 2) {
- QString m;
- if (captured[i + 1] == 0)
- m = QLatin1String(""); // ### Qt 5: don't distinguish between null and empty
- else if (captured[i] >= 0)
- m = priv->t.mid(captured[i], captured[i + 1]);
- priv->capturedCache.append(m);
- }
- priv->t.clear();
- }
- return priv->capturedCache;
-}
-
-/*!
- \internal
-*/
-QStringList QRegExp::capturedTexts()
-{
- return const_cast<const QRegExp *>(this)->capturedTexts();
-}
-
-/*!
- Returns the text captured by the \a nth subexpression. The entire
- match has index 0 and the parenthesized subexpressions have
- indexes starting from 1 (excluding non-capturing parentheses).
-
- \snippet code/src_corelib_text_qregexp.cpp 17
-
- The order of elements matched by cap() is as follows. The first
- element, cap(0), is the entire matching string. Each subsequent
- element corresponds to the next capturing open left parentheses.
- Thus cap(1) is the text of the first capturing parentheses, cap(2)
- is the text of the second, and so on.
-
- \sa capturedTexts(), pos()
-*/
-QString QRegExp::cap(int nth) const
-{
- return capturedTexts().value(nth);
-}
-
-/*!
- \internal
-*/
-QString QRegExp::cap(int nth)
-{
- return const_cast<const QRegExp *>(this)->cap(nth);
-}
-
-/*!
- Returns the position of the \a nth captured text in the searched
- string. If \a nth is 0 (the default), pos() returns the position
- of the whole match.
-
- Example:
- \snippet code/src_corelib_text_qregexp.cpp 18
-
- For zero-length matches, pos() always returns -1. (For example, if
- cap(4) would return an empty string, pos(4) returns -1.) This is
- a feature of the implementation.
-
- \sa cap(), capturedTexts()
-*/
-int QRegExp::pos(int nth) const
-{
- if (nth < 0 || nth >= priv->matchState.capturedSize / 2)
- return -1;
- else
- return priv->matchState.captured[2 * nth];
-}
-
-/*!
- \internal
-*/
-int QRegExp::pos(int nth)
-{
- return const_cast<const QRegExp *>(this)->pos(nth);
-}
-
-/*!
- Returns a text string that explains why a regexp pattern is
- invalid the case being; otherwise returns "no error occurred".
-
- \sa isValid()
-*/
-QString QRegExp::errorString() const
-{
- if (isValid()) {
- return QString::fromLatin1(RXERR_OK);
- } else {
- return priv->eng->errorString();
- }
-}
-
-/*!
- \internal
-*/
-QString QRegExp::errorString()
-{
- return const_cast<const QRegExp *>(this)->errorString();
-}
-
-#endif
-
-/*!
- Returns the string \a str with every regexp special character
- escaped with a backslash. The special characters are $, (,), *, +,
- ., ?, [, \,], ^, {, | and }.
-
- Example:
-
- \snippet code/src_corelib_text_qregexp.cpp 19
-
- This function is useful to construct regexp patterns dynamically:
-
- \snippet code/src_corelib_text_qregexp.cpp 20
-
- \sa setPatternSyntax()
-*/
-QString QRegExp::escape(const QString &str)
-{
- QString quoted;
- const int count = str.count();
- quoted.reserve(count * 2);
- const QLatin1Char backslash('\\');
- for (int i = 0; i < count; i++) {
- switch (str.at(i).toLatin1()) {
- case '$':
- case '(':
- case ')':
- case '*':
- case '+':
- case '.':
- case '?':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '{':
- case '|':
- case '}':
- quoted.append(backslash);
- }
- quoted.append(str.at(i));
- }
- return quoted;
-}
-
-
-#ifndef QT_NO_DATASTREAM
-/*!
- \relates QRegExp
-
- Writes the regular expression \a regExp to stream \a out.
-
- \sa {Serializing Qt Data Types}
-*/
-QDataStream &operator<<(QDataStream &out, const QRegExp &regExp)
-{
- return out << regExp.pattern() << (quint8)regExp.caseSensitivity()
- << (quint8)regExp.patternSyntax()
- << (quint8)!!regExp.isMinimal();
-}
-
-/*!
- \relates QRegExp
-
- Reads a regular expression from stream \a in into \a regExp.
-
- \sa {Serializing Qt Data Types}
-*/
-QDataStream &operator>>(QDataStream &in, QRegExp &regExp)
-{
- QString pattern;
- quint8 cs;
- quint8 patternSyntax;
- quint8 isMinimal;
-
- in >> pattern >> cs >> patternSyntax >> isMinimal;
-
- QRegExp newRegExp(pattern, Qt::CaseSensitivity(cs),
- QRegExp::PatternSyntax(patternSyntax));
-
- newRegExp.setMinimal(isMinimal);
- regExp = newRegExp;
- return in;
-}
-#endif // QT_NO_DATASTREAM
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRegExp &r)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QRegExp(patternSyntax=" << r.patternSyntax()
- << ", pattern='"<< r.pattern() << "')";
- return dbg;
-}
-#endif
-
-QT_END_NAMESPACE
diff --git a/src/corelib/text/qregexp.h b/src/corelib/text/qregexp.h
deleted file mode 100644
index 0c117fd17f..0000000000
--- a/src/corelib/text/qregexp.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QREGEXP_H
-#define QREGEXP_H
-
-#include <QtCore/qglobal.h>
-
-#ifndef QT_NO_REGEXP
-
-#include <QtCore/qstring.h>
-#include <QtCore/qvariant.h>
-
-QT_BEGIN_NAMESPACE
-
-
-struct QRegExpPrivate;
-class QStringList;
-class QRegExp;
-
-Q_CORE_EXPORT size_t qHash(const QRegExp &key, size_t seed = 0) noexcept;
-
-class Q_CORE_EXPORT QRegExp
-{
-public:
- enum PatternSyntax {
- RegExp,
- Wildcard,
- FixedString,
- RegExp2,
- WildcardUnix,
- W3CXmlSchema11 };
- enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch };
-
- QRegExp();
- explicit QRegExp(const QString &pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive,
- PatternSyntax syntax = RegExp);
- QRegExp(const QRegExp &rx);
- ~QRegExp();
- QRegExp &operator=(const QRegExp &rx);
- QRegExp &operator=(QRegExp &&other) noexcept { swap(other); return *this; }
- void swap(QRegExp &other) noexcept { qSwap(priv, other.priv); }
-
- bool operator==(const QRegExp &rx) const;
- inline bool operator!=(const QRegExp &rx) const { return !operator==(rx); }
-
- bool isEmpty() const;
- bool isValid() const;
- QString pattern() const;
- void setPattern(const QString &pattern);
- Qt::CaseSensitivity caseSensitivity() const;
- void setCaseSensitivity(Qt::CaseSensitivity cs);
- PatternSyntax patternSyntax() const;
- void setPatternSyntax(PatternSyntax syntax);
-
- bool isMinimal() const;
- void setMinimal(bool minimal);
-
- bool exactMatch(const QString &str) const;
-
- operator QVariant() const;
-
- int indexIn(const QString &str, int offset = 0, CaretMode caretMode = CaretAtZero) const;
- int lastIndexIn(const QString &str, int offset = -1, CaretMode caretMode = CaretAtZero) const;
- int matchedLength() const;
-#ifndef QT_NO_REGEXP_CAPTURE
- int captureCount() const;
- QStringList capturedTexts() const;
- QStringList capturedTexts();
- QString cap(int nth = 0) const;
- QString cap(int nth = 0);
- int pos(int nth = 0) const;
- int pos(int nth = 0);
- QString errorString() const;
- QString errorString();
-#endif
-
- QString replaceIn(const QString &str, const QString &after) const;
- QString removeIn(const QString &str) const
- { return replaceIn(str, QString()); }
- bool containedIn(const QString &str) const
- { return indexIn(str) != -1; }
- int countIn(const QString &str) const;
-
- QStringList splitString(const QString &str, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
-
- int indexIn(const QStringList &list, int from) const;
- int lastIndexIn(const QStringList &list, int from) const;
- QStringList replaceIn(const QStringList &stringList, const QString &after) const;
- QStringList filterList(const QStringList &stringList) const;
-
- static QString escape(const QString &str);
-
- friend Q_CORE_EXPORT size_t qHash(const QRegExp &key, size_t seed) noexcept;
-
-private:
- QRegExpPrivate *priv;
-};
-
-#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegExp &regExp);
-Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegExp &regExp);
-#endif
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_CORE_EXPORT QDebug operator<<(QDebug, const QRegExp &);
-#endif
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QRegExp)
-
-#endif // QT_NO_REGEXP
-
-#endif // QREGEXP_H
diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp
index 44bdc2e463..78261e14cb 100644
--- a/src/corelib/text/qregularexpression.cpp
+++ b/src/corelib/text/qregularexpression.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qregularexpression.h"
@@ -47,17 +11,22 @@
#include <QtCore/qmutex.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qthreadstorage.h>
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qdatastream.h>
+#if defined(Q_OS_MACOS)
+#include <QtCore/private/qcore_mac_p.h>
+#endif
+
#define PCRE2_CODE_UNIT_WIDTH 16
#include <pcre2.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QRegularExpression
\inmodule QtCore
@@ -73,6 +42,7 @@ QT_BEGIN_NAMESPACE
\keyword regular expression
+ \compares equality
Regular expressions, or \e{regexps}, are a very powerful tool to handle
strings and texts. This is useful in many contexts, e.g.,
@@ -105,9 +75,9 @@ QT_BEGIN_NAMESPACE
\list
\li \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F.
Friedl, ISBN 0-596-52812-4;
- \li the \l{http://pcre.org/pcre.txt} {pcrepattern(3)} man page, describing
- the pattern syntax supported by PCRE (the reference implementation of
- Perl-compatible regular expressions);
+ \li the \l{https://pcre.org/original/doc/html/pcrepattern.html}
+ {pcrepattern(3)} man page, describing the pattern syntax supported by PCRE
+ (the reference implementation of Perl-compatible regular expressions);
\li the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression
documentation} and the \l{http://perldoc.perl.org/perlretut.html} {Perl's
regular expression tutorial}.
@@ -140,6 +110,14 @@ QT_BEGIN_NAMESPACE
\snippet code/src_corelib_text_qregularexpression.cpp 2
+ Alternatively, you can use a
+ \l {https://en.cppreference.com/w/cpp/language/string_literal} {raw string literal},
+ in which case you don't need to escape backslashes in the pattern, all characters
+ between \c {R"(...)"} are considered raw characters. As you can see in the following
+ example, this simplifies writing patterns:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 35
+
The pattern() function returns the pattern that is currently set for a
QRegularExpression object:
@@ -260,6 +238,12 @@ QT_BEGIN_NAMESPACE
You can also use \l{QRegularExpressionMatchIterator::}{peekNext()} to get
the next result without advancing the iterator.
+ It is also possible to simply use the result of
+ QRegularExpression::globalMatch in a range-based for loop, for instance
+ like this:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 34
+
It is possible to pass a starting offset and one or more match options to
the globalMatch() function, exactly like normal matching with match().
@@ -535,6 +519,12 @@ QT_BEGIN_NAMESPACE
Moreover, QRegularExpressionMatchIterator offers a peekNext() function
to get the next result \e{without} advancing the iterator.
+ Starting with Qt 6.0, it is also possible to simply use the result of
+ QRegularExpression::globalMatch in a range-based for loop, for instance
+ like this:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 34
+
You can retrieve the QRegularExpression object the subject string was
matched against by calling the regularExpression() function; the
match type and the match options are available as well by calling
@@ -608,16 +598,6 @@ QT_BEGIN_NAMESPACE
\c{\w} to match any character with either the Unicode L (letter) or N
(digit) property, plus underscore, and so on. This option corresponds
to the \c{/u} modifier in Perl regular expressions.
-
- \value OptimizeOnFirstUsageOption
- This option is ignored. A regular expression is automatically optimized
- (including JIT compiling) the first time it is used. This enum value
- was introduced in Qt 5.4.
-
- \value DontAutomaticallyOptimizeOption
- This option is ignored. A regular expression is automatically optimized
- (including JIT compiling) the first time it is used. This enum value
- was introduced in Qt 5.4.
*/
/*!
@@ -738,11 +718,11 @@ struct QRegularExpressionPrivate : QSharedData
};
void doMatch(QRegularExpressionMatchPrivate *priv,
- int offset,
+ qsizetype offset,
CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
const QRegularExpressionMatchPrivate *previous = nullptr) const;
- int captureIndexForName(QStringView name) const;
+ int captureIndexForName(QAnyStringView name) const;
// sizeof(QSharedData) == 4, so start our members with an enum
QRegularExpression::PatternOptions patternOptions;
@@ -758,7 +738,7 @@ struct QRegularExpressionPrivate : QSharedData
// it is set to nullptr
pcre2_code_16 *compiledPattern;
int errorCode;
- int errorOffset;
+ qsizetype errorOffset;
int capturingCount;
bool usingCrLfNewlines;
bool isDirty;
@@ -787,7 +767,7 @@ struct QRegularExpressionMatchPrivate : QSharedData
// the capturedOffsets vector contains pairs of (start, end) positions
// for each captured substring
- QList<int> capturedOffsets;
+ QList<qsizetype> capturedOffsets;
int capturedCount = 0;
@@ -812,6 +792,24 @@ struct QRegularExpressionMatchIteratorPrivate : QSharedData
/*!
\internal
+
+ Used to centralize the warning about using an invalid QRegularExpression.
+ In case the pattern is an illegal UTF-16 string, we can't pass print it
+ (pass it to qUtf16Printable, etc.), so we need to check for that.
+*/
+Q_DECL_COLD_FUNCTION
+void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *where)
+{
+ if (pattern.isValidUtf16()) {
+ qWarning("%s(): called on an invalid QRegularExpression object "
+ "(pattern is '%ls')", where, qUtf16Printable(pattern));
+ } else {
+ qWarning("%s(): called on an invalid QRegularExpression object", where);
+ }
+}
+
+/*!
+ \internal
*/
QRegularExpression::QRegularExpression(QRegularExpressionPrivate &dd)
: d(&dd)
@@ -896,15 +894,15 @@ void QRegularExpressionPrivate::compilePattern()
options |= PCRE2_UTF;
PCRE2_SIZE patternErrorOffset;
- compiledPattern = pcre2_compile_16(reinterpret_cast<PCRE2_SPTR16>(pattern.utf16()),
- pattern.length(),
+ compiledPattern = pcre2_compile_16(reinterpret_cast<PCRE2_SPTR16>(pattern.constData()),
+ pattern.size(),
options,
&errorCode,
&patternErrorOffset,
nullptr);
if (!compiledPattern) {
- errorOffset = static_cast<int>(patternErrorOffset);
+ errorOffset = qsizetype(patternErrorOffset);
return;
} else {
// ignore whatever PCRE2 wrote into errorCode -- leave it to 0 to mean "no error"
@@ -948,43 +946,24 @@ void QRegularExpressionPrivate::getPatternInfo()
Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with
QThreadStorage.
*/
-class QPcreJitStackPointer
+namespace {
+struct PcreJitStackFree
{
- Q_DISABLE_COPY(QPcreJitStackPointer)
-
-public:
- /*!
- \internal
- */
- QPcreJitStackPointer()
- {
- // The default JIT stack size in PCRE is 32K,
- // we allocate from 32K up to 512K.
- stack = pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, nullptr);
- }
- /*!
- \internal
- */
- ~QPcreJitStackPointer()
+ void operator()(pcre2_jit_stack_16 *stack)
{
if (stack)
pcre2_jit_stack_free_16(stack);
}
-
- pcre2_jit_stack_16 *stack;
};
-
-Q_GLOBAL_STATIC(QThreadStorage<QPcreJitStackPointer *>, jitStacks)
+Q_CONSTINIT static thread_local std::unique_ptr<pcre2_jit_stack_16, PcreJitStackFree> jitStacks;
+}
/*!
\internal
*/
static pcre2_jit_stack_16 *qtPcreCallback(void *)
{
- if (jitStacks()->hasLocalData())
- return jitStacks()->localData()->stack;
-
- return nullptr;
+ return jitStacks.get();
}
/*!
@@ -1001,6 +980,8 @@ static bool isJitEnabled()
#ifdef QT_DEBUG
return false;
+#elif defined(Q_OS_MACOS)
+ return !qt_mac_runningUnderRosetta();
#else
return true;
#endif
@@ -1033,16 +1014,31 @@ void QRegularExpressionPrivate::optimizePattern()
Returns the capturing group number for the given name. Duplicated names for
capturing groups are not supported.
*/
-int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
+int QRegularExpressionPrivate::captureIndexForName(QAnyStringView name) const
{
Q_ASSERT(!name.isEmpty());
if (!compiledPattern)
return -1;
- int index = pcre2_substring_number_from_name_16(compiledPattern, reinterpret_cast<PCRE2_SPTR16>(name.utf16()));
- if (index >= 0)
- return index;
+ // See the other usages of pcre2_pattern_info_16 for more details about this
+ PCRE2_SPTR16 *namedCapturingTable;
+ unsigned int namedCapturingTableEntryCount;
+ unsigned int namedCapturingTableEntrySize;
+
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMETABLE, &namedCapturingTable);
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
+
+ for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
+ const auto currentNamedCapturingTableRow =
+ reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
+
+ if (name == (currentNamedCapturingTableRow + 1)) {
+ const int index = *currentNamedCapturingTableRow;
+ return index;
+ }
+ }
return -1;
}
@@ -1055,17 +1051,18 @@ int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
and re-run pcre2_match_16.
*/
static int safe_pcre2_match_16(const pcre2_code_16 *code,
- PCRE2_SPTR16 subject, int length,
- int startOffset, int options,
+ PCRE2_SPTR16 subject, qsizetype length,
+ qsizetype startOffset, int options,
pcre2_match_data_16 *matchData,
pcre2_match_context_16 *matchContext)
{
int result = pcre2_match_16(code, subject, length,
startOffset, options, matchData, matchContext);
- if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks()->hasLocalData()) {
- QPcreJitStackPointer *p = new QPcreJitStackPointer;
- jitStacks()->setLocalData(p);
+ if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks) {
+ // The default JIT stack size in PCRE is 32K,
+ // we allocate from 32K up to 512K.
+ jitStacks.reset(pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, NULL));
result = pcre2_match_16(code, subject, length,
startOffset, options, matchData, matchContext);
@@ -1103,14 +1100,14 @@ static int safe_pcre2_match_16(const pcre2_code_16 *code,
must advance over it.
*/
void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
- int offset,
+ qsizetype offset,
CheckSubjectStringOption checkSubjectStringOption,
const QRegularExpressionMatchPrivate *previous) const
{
Q_ASSERT(priv);
- Q_ASSUME(priv != previous);
+ Q_ASSERT(priv != previous);
- const int subjectLength = priv->subject.length();
+ const qsizetype subjectLength = priv->subject.size();
if (offset < 0)
offset += subjectLength;
@@ -1119,7 +1116,7 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
return;
if (Q_UNLIKELY(!compiledPattern)) {
- qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
+ qtWarnAboutInvalidRegularExpression(pattern, "QRegularExpressionPrivate::doMatch");
return;
}
@@ -1149,7 +1146,19 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
pcre2_jit_stack_assign_16(matchContext, &qtPcreCallback, nullptr);
pcre2_match_data_16 *matchData = pcre2_match_data_create_from_pattern_16(compiledPattern, nullptr);
- const char16_t * const subjectUtf16 = priv->subject.utf16();
+ // PCRE does not accept a null pointer as subject string, even if
+ // its length is zero. We however allow it in input: a QStringView
+ // subject may have data == nullptr. In this case, to keep PCRE
+ // happy, pass a pointer to a dummy character.
+ const char16_t dummySubject = 0;
+ const char16_t * const subjectUtf16 = [&]()
+ {
+ const auto subjectUtf16 = priv->subject.utf16();
+ if (subjectUtf16)
+ return subjectUtf16;
+ Q_ASSERT(subjectLength == 0);
+ return &dummySubject;
+ }();
int result;
@@ -1169,8 +1178,8 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
if (usingCrLfNewlines
&& offset < subjectLength
- && subjectUtf16[offset - 1] == QLatin1Char('\r')
- && subjectUtf16[offset] == QLatin1Char('\n')) {
+ && subjectUtf16[offset - 1] == u'\r'
+ && subjectUtf16[offset] == u'\n') {
++offset;
} else if (offset < subjectLength
&& QChar::isLowSurrogate(subjectUtf16[offset])) {
@@ -1220,10 +1229,16 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
// copy the captured substrings offsets, if any
if (priv->capturedCount) {
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(matchData);
- int * const capturedOffsets = priv->capturedOffsets.data();
+ qsizetype *const capturedOffsets = priv->capturedOffsets.data();
+
+ // We rely on the fact that capturing groups that did not
+ // capture anything have offset -1, but PCRE technically
+ // returns "PCRE2_UNSET". Test that out, better safe than
+ // sorry...
+ static_assert(qsizetype(PCRE2_UNSET) == qsizetype(-1), "Internal error: PCRE2 changed its API");
for (int i = 0; i < priv->capturedCount * 2; ++i)
- capturedOffsets[i] = static_cast<int>(ovector[i]);
+ capturedOffsets[i] = qsizetype(ovector[i]);
// For partial matches, PCRE2 and PCRE1 differ in behavior when lookbehinds
// are involved. PCRE2 reports the real begin of the match and the maximum
@@ -1340,10 +1355,21 @@ QRegularExpression::QRegularExpression(const QString &pattern, PatternOptions op
\sa operator=()
*/
-QRegularExpression::QRegularExpression(const QRegularExpression &re)
- : d(re.d)
-{
-}
+QRegularExpression::QRegularExpression(const QRegularExpression &re) noexcept = default;
+
+/*!
+ \fn QRegularExpression::QRegularExpression(QRegularExpression &&re)
+
+ \since 6.1
+
+ Constructs a QRegularExpression object by moving from \a re.
+
+ Note that a moved-from QRegularExpression can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
+
+ \sa operator=()
+*/
/*!
Destroys the QRegularExpression object.
@@ -1352,15 +1378,13 @@ QRegularExpression::~QRegularExpression()
{
}
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionPrivate)
+
/*!
Assigns the regular expression \a re to this object, and returns a reference
to the copy. Both the pattern and the pattern options are copied.
*/
-QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re)
-{
- d = re.d;
- return *this;
-}
+QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re) noexcept = default;
/*!
\fn void QRegularExpression::swap(QRegularExpression &other)
@@ -1387,6 +1411,8 @@ QString QRegularExpression::pattern() const
*/
void QRegularExpression::setPattern(const QString &pattern)
{
+ if (d->pattern == pattern)
+ return;
d.detach();
d->isDirty = true;
d->pattern = pattern;
@@ -1410,6 +1436,8 @@ QRegularExpression::PatternOptions QRegularExpression::patternOptions() const
*/
void QRegularExpression::setPatternOptions(PatternOptions options)
{
+ if (d->patternOptions == options)
+ return;
d.detach();
d->isDirty = true;
d->patternOptions = options;
@@ -1473,19 +1501,15 @@ QStringList QRegularExpression::namedCaptureGroups() const
pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
- QStringList result;
-
- // no QList::resize nor fill is available. The +1 is for the implicit group #0
- result.reserve(d->capturingCount + 1);
- for (int i = 0; i < d->capturingCount + 1; ++i)
- result.append(QString());
+ // The +1 is for the implicit group #0
+ QStringList result(d->capturingCount + 1);
for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
const auto currentNamedCapturingTableRow =
reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
const int index = *currentNamedCapturingTableRow;
- result[index] = QString::fromUtf16(currentNamedCapturingTableRow + 1);
+ result[index] = QStringView(currentNamedCapturingTableRow + 1).toString();
}
return result;
@@ -1517,10 +1541,10 @@ QString QRegularExpression::errorString() const
QString errorString;
int errorStringLength;
do {
- errorString.resize(errorString.length() + 64);
+ errorString.resize(errorString.size() + 64);
errorStringLength = pcre2_get_error_message_16(d->errorCode,
reinterpret_cast<ushort *>(errorString.data()),
- errorString.length());
+ errorString.size());
} while (errorStringLength < 0);
errorString.resize(errorStringLength);
@@ -1531,7 +1555,7 @@ QString QRegularExpression::errorString() const
#endif
}
#ifdef QT_NO_TRANSLATION
- return QLatin1String("no error");
+ return u"no error"_s;
#else
return QCoreApplication::translate("QRegularExpression", "no error");
#endif
@@ -1544,7 +1568,7 @@ QString QRegularExpression::errorString() const
\sa pattern(), isValid(), errorString()
*/
-int QRegularExpression::patternErrorOffset() const
+qsizetype QRegularExpression::patternErrorOffset() const
{
d.data()->compilePattern();
return d->errorOffset;
@@ -1561,23 +1585,40 @@ int QRegularExpression::patternErrorOffset() const
\sa QRegularExpressionMatch, {normal matching}
*/
QRegularExpressionMatch QRegularExpression::match(const QString &subject,
- int offset,
+ qsizetype offset,
MatchType matchType,
MatchOptions matchOptions) const
{
d.data()->compilePattern();
auto priv = new QRegularExpressionMatchPrivate(*this,
subject,
- qToStringViewIgnoringNull(subject),
+ QStringView(subject),
matchType,
matchOptions);
d->doMatch(priv, offset);
return QRegularExpressionMatch(*priv);
}
+#if QT_DEPRECATED_SINCE(6, 8)
/*!
\since 6.0
\overload
+ \obsolete
+
+ Use matchView() instead.
+*/
+QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
+ qsizetype offset,
+ MatchType matchType,
+ MatchOptions matchOptions) const
+{
+ return matchView(subjectView, offset, matchType, matchOptions);
+}
+#endif // QT_DEPRECATED_SINCE(6, 8)
+
+/*!
+ \since 6.5
+ \overload
Attempts to match the regular expression against the given \a subjectView
string view, starting at the position \a offset inside the subject, using a
@@ -1591,10 +1632,10 @@ QRegularExpressionMatch QRegularExpression::match(const QString &subject,
\sa QRegularExpressionMatch, {normal matching}
*/
-QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
- int offset,
- MatchType matchType,
- MatchOptions matchOptions) const
+QRegularExpressionMatch QRegularExpression::matchView(QStringView subjectView,
+ qsizetype offset,
+ MatchType matchType,
+ MatchOptions matchOptions) const
{
d.data()->compilePattern();
auto priv = new QRegularExpressionMatchPrivate(*this,
@@ -1618,7 +1659,7 @@ QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
\sa QRegularExpressionMatchIterator, {global matching}
*/
QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &subject,
- int offset,
+ qsizetype offset,
MatchType matchType,
MatchOptions matchOptions) const
{
@@ -1631,9 +1672,26 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
return QRegularExpressionMatchIterator(*priv);
}
+#if QT_DEPRECATED_SINCE(6, 8)
/*!
\since 6.0
\overload
+ \obsolete
+
+ Use globalMatchView() instead.
+*/
+QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView,
+ qsizetype offset,
+ MatchType matchType,
+ MatchOptions matchOptions) const
+{
+ return globalMatchView(subjectView, offset, matchType, matchOptions);
+}
+#endif // QT_DEPRECATED_SINCE(6, 8)
+
+/*!
+ \since 6.5
+ \overload
Attempts to perform a global match of the regular expression against the
given \a subjectView string view, starting at the position \a offset inside the
@@ -1649,16 +1707,16 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
\sa QRegularExpressionMatchIterator, {global matching}
*/
-QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView,
- int offset,
- MatchType matchType,
- MatchOptions matchOptions) const
+QRegularExpressionMatchIterator QRegularExpression::globalMatchView(QStringView subjectView,
+ qsizetype offset,
+ MatchType matchType,
+ MatchOptions matchOptions) const
{
QRegularExpressionMatchIteratorPrivate *priv =
new QRegularExpressionMatchIteratorPrivate(*this,
matchType,
matchOptions,
- match(subjectView, offset, matchType, matchOptions));
+ matchView(subjectView, offset, matchType, matchOptions));
return QRegularExpressionMatchIterator(*priv);
}
@@ -1677,29 +1735,35 @@ void QRegularExpression::optimize() const
}
/*!
- Returns \c true if the regular expression is equal to \a re, or false
+ \fn bool QRegularExpression::operator==(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
+
+ Returns \c true if the \a lhs regular expression is equal to the \a rhs, or false
otherwise. Two QRegularExpression objects are equal if they have
the same pattern string and the same pattern options.
\sa operator!=()
*/
-bool QRegularExpression::operator==(const QRegularExpression &re) const
+bool comparesEqual(const QRegularExpression &lhs,
+ const QRegularExpression &rhs) noexcept
{
- return (d == re.d) ||
- (d->pattern == re.d->pattern && d->patternOptions == re.d->patternOptions);
+ return (lhs.d == rhs.d) ||
+ (lhs.d->pattern == rhs.d->pattern && lhs.d->patternOptions == rhs.d->patternOptions);
}
-
/*!
\fn QRegularExpression & QRegularExpression::operator=(QRegularExpression && re)
- Move-assigns the regular expression \a re to this object, and returns a reference
- to the copy. Both the pattern and the pattern options are copied.
+ Move-assigns the regular expression \a re to this object, and returns a
+ reference to the result. Both the pattern and the pattern options are copied.
+
+ Note that a moved-from QRegularExpression can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
*/
/*!
- \fn bool QRegularExpression::operator!=(const QRegularExpression &re) const
+ \fn bool QRegularExpression::operator!=(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
- Returns \c true if the regular expression is different from \a re, or
+ Returns \c true if the \a lhs regular expression is different from the \a rhs, or
false otherwise.
\sa operator==()
@@ -1717,12 +1781,10 @@ size_t qHash(const QRegularExpression &key, size_t seed) noexcept
return qHashMulti(seed, key.d->pattern, key.d->patternOptions);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QString QRegularExpression::escape(const QString &str)
\overload
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.15
@@ -1747,26 +1809,25 @@ size_t qHash(const QRegularExpression &key, size_t seed) noexcept
QString QRegularExpression::escape(QStringView str)
{
QString result;
- const int count = str.size();
+ const qsizetype count = str.size();
result.reserve(count * 2);
// everything but [a-zA-Z0-9_] gets escaped,
// cf. perldoc -f quotemeta
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
const QChar current = str.at(i);
if (current == QChar::Null) {
// unlike Perl, a literal NUL must be escaped with
// "\\0" (backslash + 0) and not "\\\0" (backslash + NUL),
// because pcre16_compile uses a NUL-terminated string
- result.append(QLatin1Char('\\'));
- result.append(QLatin1Char('0'));
- } else if ( (current < QLatin1Char('a') || current > QLatin1Char('z')) &&
- (current < QLatin1Char('A') || current > QLatin1Char('Z')) &&
- (current < QLatin1Char('0') || current > QLatin1Char('9')) &&
- current != QLatin1Char('_') )
- {
- result.append(QLatin1Char('\\'));
+ result.append(u'\\');
+ result.append(u'0');
+ } else if ((current < u'a' || current > u'z') &&
+ (current < u'A' || current > u'Z') &&
+ (current < u'0' || current > u'9') &&
+ current != u'_') {
+ result.append(u'\\');
result.append(current);
if (current.isHighSurrogate() && i < (count - 1))
result.append(str.at(++i));
@@ -1779,13 +1840,11 @@ QString QRegularExpression::escape(QStringView str)
return result;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.12
- \fn QString QRegularExpression::wildcardToRegularExpression(const QString &pattern, WildcardConversionType type)
+ \fn QString QRegularExpression::wildcardToRegularExpression(const QString &pattern, WildcardConversionOptions options)
\overload
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 6.0
@@ -1800,22 +1859,30 @@ QString QRegularExpression::escape(QStringView str)
\value UnanchoredWildcardConversion
The conversion will not anchor the pattern. This allows for partial string matches of
wildcard expressions.
+
+ \value [since 6.6] NonPathWildcardConversion
+ The conversion will \e{not} interpret the pattern as filepath globbing.
+
+ \sa QRegularExpression::wildcardToRegularExpression
*/
/*!
\since 5.15
Returns a regular expression representation of the given glob \a pattern.
- The transformation is targeting file path globbing, which means in particular
- that path separators receive special treatment. This implies that it is not
- just a basic translation from "*" to ".*".
+
+ There are two transformations possible, one that targets file path
+ globbing, and another one which is more generic.
+
+ By default, the transformation is targeting file path globbing,
+ which means in particular that path separators receive special
+ treatment. This implies that it is not just a basic translation
+ from "*" to ".*" and similar.
\snippet code/src_corelib_text_qregularexpression.cpp 31
- By default, the returned regular expression is fully anchored. In other
- words, there is no need of calling anchoredPattern() again on the
- result. To get an a regular expression that is not anchored, pass
- UnanchoredWildcardConversion as the conversion \a option.
+ The more generic globbing transformation is available by passing
+ \c NonPathWildcardConversion in the conversion \a options.
This implementation follows closely the definition
of wildcard for glob patterns:
@@ -1824,10 +1891,12 @@ QString QRegularExpression::escape(QStringView str)
\li Any character represents itself apart from those mentioned
below. Thus \b{c} matches the character \e c.
\row \li \b{?}
- \li Matches any single character. It is the same as
- \b{.} in full regexps.
+ \li Matches any single character, except for a path separator
+ (in case file path globbing has been selected). It is the
+ same as b{.} in full regexps.
\row \li \b{*}
- \li Matches zero or more of any characters. It is the
+ \li Matches zero or more of any characters, except for path
+ separators (in case file path globbing has been selected). It is the
same as \b{.*} in full regexps.
\row \li \b{[abc]}
\li Matches one character given in the bracket.
@@ -1841,9 +1910,10 @@ QString QRegularExpression::escape(QStringView str)
bracket. It is the same as \b{[^a-c]} in full regexp.
\endtable
- \note The backslash (\\) character is \e not an escape char in this context.
- In order to match one of the special characters, place it in square brackets
- (for example, \c{[?]}).
+ \note For historical reasons, a backslash (\\) character is \e not
+ an escape char in this context. In order to match one of the
+ special characters, place it in square brackets (for example,
+ \c{[?]}).
More information about the implementation can be found in:
\list
@@ -1851,39 +1921,66 @@ QString QRegularExpression::escape(QStringView str)
\li \c {man 7 glob}
\endlist
+ By default, the returned regular expression is fully anchored. In other
+ words, there is no need of calling anchoredPattern() again on the
+ result. To get a regular expression that is not anchored, pass
+ UnanchoredWildcardConversion in the conversion \a options.
+
\sa escape()
*/
QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, WildcardConversionOptions options)
{
- const int wclen = pattern.length();
+ const qsizetype wclen = pattern.size();
QString rx;
rx.reserve(wclen + wclen / 16);
- int i = 0;
+ qsizetype i = 0;
const QChar *wc = pattern.data();
+ struct GlobSettings {
+ char16_t nativePathSeparator;
+ QStringView starEscape;
+ QStringView questionMarkEscape;
+ };
+
+ const GlobSettings settings = [options]() {
+ if (options.testFlag(NonPathWildcardConversion)) {
+ // using [\d\D] to mean "match everything";
+ // dot doesn't match newlines, unless in /s mode
+ return GlobSettings{ u'\0', u"[\\d\\D]*", u"[\\d\\D]" };
+ } else {
#ifdef Q_OS_WIN
- const QLatin1Char nativePathSeparator('\\');
- const QLatin1String starEscape("[^/\\\\]*");
- const QLatin1String questionMarkEscape("[^/\\\\]");
+ return GlobSettings{ u'\\', u"[^/\\\\]*", u"[^/\\\\]" };
#else
- const QLatin1Char nativePathSeparator('/');
- const QLatin1String starEscape("[^/]*");
- const QLatin1String questionMarkEscape("[^/]");
+ return GlobSettings{ u'/', u"[^/]*", u"[^/]" };
#endif
+ }
+ }();
while (i < wclen) {
const QChar c = wc[i++];
switch (c.unicode()) {
case '*':
- rx += starEscape;
+ rx += settings.starEscape;
break;
case '?':
- rx += questionMarkEscape;
+ rx += settings.questionMarkEscape;
break;
+ // When not using filepath globbing: \ is escaped, / is itself
+ // When using filepath globbing:
+ // * Unix: \ gets escaped. / is itself
+ // * Windows: \ and / can match each other -- they become [/\\] in regexp
case '\\':
#ifdef Q_OS_WIN
+ if (options.testFlag(NonPathWildcardConversion))
+ rx += u"\\\\";
+ else
+ rx += u"[/\\\\]";
+ break;
case '/':
- rx += QLatin1String("[/\\\\]");
+ if (options.testFlag(NonPathWildcardConversion))
+ rx += u'/';
+ else
+ rx += u"[/\\\\]";
break;
#endif
case '$':
@@ -1895,29 +1992,31 @@ QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, Wil
case '{':
case '|':
case '}':
- rx += QLatin1Char('\\');
+ rx += u'\\';
rx += c;
break;
case '[':
rx += c;
// Support for the [!abc] or [!a-c] syntax
if (i < wclen) {
- if (wc[i] == QLatin1Char('!')) {
- rx += QLatin1Char('^');
+ if (wc[i] == u'!') {
+ rx += u'^';
++i;
}
- if (i < wclen && wc[i] == QLatin1Char(']'))
+ if (i < wclen && wc[i] == u']')
rx += wc[i++];
- while (i < wclen && wc[i] != QLatin1Char(']')) {
- // The '/' appearing in a character class invalidates the
- // regular expression parsing. It also concerns '\\' on
- // Windows OS types.
- if (wc[i] == QLatin1Char('/') || wc[i] == nativePathSeparator)
- return rx;
- if (wc[i] == QLatin1Char('\\'))
- rx += QLatin1Char('\\');
+ while (i < wclen && wc[i] != u']') {
+ if (!options.testFlag(NonPathWildcardConversion)) {
+ // The '/' appearing in a character class invalidates the
+ // regular expression parsing. It also concerns '\\' on
+ // Windows OS types.
+ if (wc[i] == u'/' || wc[i] == settings.nativePathSeparator)
+ return rx;
+ }
+ if (wc[i] == u'\\')
+ rx += u'\\';
rx += wc[i++];
}
}
@@ -1936,7 +2035,9 @@ QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, Wil
/*!
\since 6.0
- Returns a regular expression of the glob pattern \a pattern.
+ Returns a regular expression of the glob pattern \a pattern. The regular expression
+ will be case sensitive if \a cs is \l{Qt::CaseSensitive}, and converted according to
+ \a options.
Equivalent to
\code
@@ -1945,21 +2046,19 @@ QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, Wil
return QRegularExpression(wildcardToRegularExpression(str, options), reOptions);
\endcode
*/
-QRegularExpression QRegularExpression::fromWildcard(QStringView str, Qt::CaseSensitivity cs,
+QRegularExpression QRegularExpression::fromWildcard(QStringView pattern, Qt::CaseSensitivity cs,
WildcardConversionOptions options)
{
auto reOptions = cs == Qt::CaseSensitive ? QRegularExpression::NoPatternOption :
QRegularExpression::CaseInsensitiveOption;
- return QRegularExpression(wildcardToRegularExpression(str, options), reOptions);
+ return QRegularExpression(wildcardToRegularExpression(pattern, options), reOptions);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QRegularExpression::anchoredPattern(const QString &expression)
\since 5.12
\overload
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 5.15
@@ -1970,9 +2069,9 @@ QRegularExpression QRegularExpression::fromWildcard(QStringView str, Qt::CaseSen
QString QRegularExpression::anchoredPattern(QStringView expression)
{
return QString()
- + QLatin1String("\\A(?:")
+ + "\\A(?:"_L1
+ expression
- + QLatin1String(")\\z");
+ + ")\\z"_L1;
}
/*!
@@ -2003,6 +2102,8 @@ QRegularExpressionMatch::~QRegularExpressionMatch()
{
}
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionMatchPrivate)
+
/*!
Constructs a match result by copying the result of the given \a match.
@@ -2014,6 +2115,20 @@ QRegularExpressionMatch::QRegularExpressionMatch(const QRegularExpressionMatch &
}
/*!
+ \fn QRegularExpressionMatch::QRegularExpressionMatch(QRegularExpressionMatch &&match)
+
+ \since 6.1
+
+ Constructs a match result by moving the result from the given \a match.
+
+ Note that a moved-from QRegularExpressionMatch can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
+
+ \sa operator=()
+*/
+
+/*!
Assigns the match result \a match to this object, and returns a reference
to the copy.
*/
@@ -2026,8 +2141,12 @@ QRegularExpressionMatch &QRegularExpressionMatch::operator=(const QRegularExpres
/*!
\fn QRegularExpressionMatch &QRegularExpressionMatch::operator=(QRegularExpressionMatch &&match)
- Move-assigns the match result \a match to this object, and returns a reference
- to the copy.
+ Move-assigns the match result \a match to this object, and returns a
+ reference to the result.
+
+ Note that a moved-from QRegularExpressionMatch can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
*/
/*!
@@ -2093,7 +2212,7 @@ QRegularExpression::MatchOptions QRegularExpressionMatch::matchOptions() const
If the regular expression did not match, this function returns -1.
- \sa captured(), capturedStart(), capturedEnd(), capturedLength()
+ \sa hasCaptured(), captured(), capturedStart(), capturedEnd(), capturedLength()
*/
int QRegularExpressionMatch::lastCapturedIndex() const
{
@@ -2101,6 +2220,65 @@ int QRegularExpressionMatch::lastCapturedIndex() const
}
/*!
+ \fn bool QRegularExpressionMatch::hasCaptured(QAnyStringView name) const
+ \since 6.3
+
+ Returns true if the capturing group named \a name captured something
+ in the subject string, and false otherwise (or if there is no
+ capturing group called \a name).
+
+ \note Some capturing groups in a regular expression may not have
+ captured anything even if the regular expression matched. This may
+ happen, for instance, if a conditional operator is used in the
+ pattern:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 36
+
+ Similarly, a capturing group may capture a substring of length 0;
+ this function will return \c{true} for such a capturing group.
+
+ \note In Qt versions prior to 6.8, this function took QString or
+ QStringView, not QAnyStringView.
+
+ \sa captured(), hasMatch()
+*/
+bool QRegularExpressionMatch::hasCaptured(QAnyStringView name) const
+{
+ const int nth = d->regularExpression.d->captureIndexForName(name);
+ return hasCaptured(nth);
+}
+
+/*!
+ \since 6.3
+
+ Returns true if the \a nth capturing group captured something
+ in the subject string, and false otherwise (or if there is no
+ such capturing group).
+
+ \note The implicit capturing group number 0 captures the substring
+ matched by the entire pattern.
+
+ \note Some capturing groups in a regular expression may not have
+ captured anything even if the regular expression matched. This may
+ happen, for instance, if a conditional operator is used in the
+ pattern:
+
+ \snippet code/src_corelib_text_qregularexpression.cpp 36
+
+ Similarly, a capturing group may capture a substring of length 0;
+ this function will return \c{true} for such a capturing group.
+
+ \sa captured(), lastCapturedIndex(), hasMatch()
+*/
+bool QRegularExpressionMatch::hasCaptured(int nth) const
+{
+ if (nth < 0 || nth > lastCapturedIndex())
+ return false;
+
+ return d->capturedOffsets.at(nth * 2) != -1;
+}
+
+/*!
Returns the substring captured by the \a nth capturing group.
If the \a nth capturing group did not capture a string, or if there is no
@@ -2133,10 +2311,10 @@ QString QRegularExpressionMatch::captured(int nth) const
*/
QStringView QRegularExpressionMatch::capturedView(int nth) const
{
- if (nth < 0 || nth > lastCapturedIndex())
+ if (!hasCaptured(nth))
return QStringView();
- int start = capturedStart(nth);
+ qsizetype start = capturedStart(nth);
if (start == -1) // didn't capture
return QStringView();
@@ -2144,22 +2322,6 @@ QStringView QRegularExpressionMatch::capturedView(int nth) const
return d->subject.mid(start, capturedLength(nth));
}
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
- Returns the substring captured by the capturing group named \a name.
-
- If the named capturing group \a name did not capture a string, or if
- there is no capturing group named \a name, returns a null QString.
-
- \sa capturedView(), capturedStart(), capturedEnd(), capturedLength(),
- QString::isNull()
-*/
-QString QRegularExpressionMatch::captured(const QString &name) const
-{
- return captured(qToStringViewIgnoringNull(name));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
-
/*!
\since 5.10
@@ -2168,10 +2330,13 @@ QString QRegularExpressionMatch::captured(const QString &name) const
If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QString.
+ \note In Qt versions prior to 6.8, this function took QString or
+ QStringView, not QAnyStringView.
+
\sa capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QString::isNull()
*/
-QString QRegularExpressionMatch::captured(QStringView name) const
+QString QRegularExpressionMatch::captured(QAnyStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::captured: empty capturing group name passed");
@@ -2190,10 +2355,13 @@ QString QRegularExpressionMatch::captured(QStringView name) const
If the named capturing group \a name did not capture a string, or if
there is no capturing group named \a name, returns a null QStringView.
+ \note In Qt versions prior to 6.8, this function took QString or
+ QStringView, not QAnyStringView.
+
\sa captured(), capturedStart(), capturedEnd(), capturedLength(),
- QStringRef::isNull()
+ QStringView::isNull()
*/
-QStringView QRegularExpressionMatch::capturedView(QStringView name) const
+QStringView QRegularExpressionMatch::capturedView(QAnyStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedView: empty capturing group name passed");
@@ -2228,9 +2396,9 @@ QStringList QRegularExpressionMatch::capturedTexts() const
\sa capturedEnd(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedStart(int nth) const
+qsizetype QRegularExpressionMatch::capturedStart(int nth) const
{
- if (nth < 0 || nth > lastCapturedIndex())
+ if (!hasCaptured(nth))
return -1;
return d->capturedOffsets.at(nth * 2);
@@ -2244,7 +2412,7 @@ int QRegularExpressionMatch::capturedStart(int nth) const
\sa capturedStart(), capturedEnd(), captured()
*/
-int QRegularExpressionMatch::capturedLength(int nth) const
+qsizetype QRegularExpressionMatch::capturedLength(int nth) const
{
// bound checking performed by these two functions
return capturedEnd(nth) - capturedStart(nth);
@@ -2257,56 +2425,14 @@ int QRegularExpressionMatch::capturedLength(int nth) const
\sa capturedStart(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedEnd(int nth) const
+qsizetype QRegularExpressionMatch::capturedEnd(int nth) const
{
- if (nth < 0 || nth > lastCapturedIndex())
+ if (!hasCaptured(nth))
return -1;
return d->capturedOffsets.at(nth * 2 + 1);
}
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
- Returns the offset inside the subject string corresponding to the starting
- position of the substring captured by the capturing group named \a name.
- If the capturing group named \a name did not capture a string or doesn't
- exist, returns -1.
-
- \sa capturedEnd(), capturedLength(), captured()
-*/
-int QRegularExpressionMatch::capturedStart(const QString &name) const
-{
- return capturedStart(qToStringViewIgnoringNull(name));
-}
-
-/*!
- Returns the length of the substring captured by the capturing group named
- \a name.
-
- \note This function returns 0 if the capturing group named \a name did not
- capture a string or doesn't exist.
-
- \sa capturedStart(), capturedEnd(), captured()
-*/
-int QRegularExpressionMatch::capturedLength(const QString &name) const
-{
- return capturedLength(qToStringViewIgnoringNull(name));
-}
-
-/*!
- Returns the offset inside the subject string immediately after the ending
- position of the substring captured by the capturing group named \a name. If
- the capturing group named \a name did not capture a string or doesn't
- exist, returns -1.
-
- \sa capturedStart(), capturedLength(), captured()
-*/
-int QRegularExpressionMatch::capturedEnd(const QString &name) const
-{
- return capturedEnd(qToStringViewIgnoringNull(name));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
-
/*!
\since 5.10
@@ -2315,9 +2441,12 @@ int QRegularExpressionMatch::capturedEnd(const QString &name) const
If the capturing group named \a name did not capture a string or doesn't
exist, returns -1.
+ \note In Qt versions prior to 6.8, this function took QString or
+ QStringView, not QAnyStringView.
+
\sa capturedEnd(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedStart(QStringView name) const
+qsizetype QRegularExpressionMatch::capturedStart(QAnyStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedStart: empty capturing group name passed");
@@ -2338,9 +2467,12 @@ int QRegularExpressionMatch::capturedStart(QStringView name) const
\note This function returns 0 if the capturing group named \a name did not
capture a string or doesn't exist.
+ \note In Qt versions prior to 6.8, this function took QString or
+ QStringView, not QAnyStringView.
+
\sa capturedStart(), capturedEnd(), captured()
*/
-int QRegularExpressionMatch::capturedLength(QStringView name) const
+qsizetype QRegularExpressionMatch::capturedLength(QAnyStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedLength: empty capturing group name passed");
@@ -2360,9 +2492,12 @@ int QRegularExpressionMatch::capturedLength(QStringView name) const
the capturing group named \a name did not capture a string or doesn't
exist, returns -1.
+ \note In Qt versions prior to 6.8, this function took QString or
+ QStringView, not QAnyStringView.
+
\sa capturedStart(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedEnd(QStringView name) const
+qsizetype QRegularExpressionMatch::capturedEnd(QAnyStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedEnd: empty capturing group name passed");
@@ -2447,6 +2582,8 @@ QRegularExpressionMatchIterator::~QRegularExpressionMatchIterator()
{
}
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionMatchIteratorPrivate)
+
/*!
Constructs a QRegularExpressionMatchIterator object as a copy of \a
iterator.
@@ -2459,6 +2596,20 @@ QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(const QRegularE
}
/*!
+ \fn QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(QRegularExpressionMatchIterator &&iterator)
+
+ \since 6.1
+
+ Constructs a QRegularExpressionMatchIterator object by moving from \a iterator.
+
+ Note that a moved-from QRegularExpressionMatchIterator can only be destroyed
+ or assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
+
+ \sa operator=()
+*/
+
+/*!
Assigns the iterator \a iterator to this object, and returns a reference to
the copy.
*/
@@ -2471,7 +2622,12 @@ QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(cons
/*!
\fn QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(QRegularExpressionMatchIterator &&iterator)
- Move-assigns the \a iterator to this object.
+ Move-assigns the \a iterator to this object, and returns a reference to the
+ result.
+
+ Note that a moved-from QRegularExpressionMatchIterator can only be destroyed
+ or assigned to. The effect of calling other functions than the destructor
+ or one of the assignment operators is undefined.
*/
/*!
@@ -2529,12 +2685,11 @@ QRegularExpressionMatch QRegularExpressionMatchIterator::next()
{
if (!hasNext()) {
qWarning("QRegularExpressionMatchIterator::next() called on an iterator already at end");
- return d->next;
+ return d.constData()->next;
}
- QRegularExpressionMatch current = d->next;
- d->next = d->next.d.constData()->nextMatch();
- return current;
+ d.detach();
+ return std::exchange(d->next, d->next.d.constData()->nextMatch());
}
/*!
@@ -2572,6 +2727,19 @@ QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions()
return d->matchOptions;
}
+/*!
+ \internal
+*/
+QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
+{
+ return QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator(iterator);
+}
+
+/*!
+ \fn QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &)
+ \internal
+*/
+
#ifndef QT_NO_DATASTREAM
/*!
\relates QRegularExpression
@@ -2582,7 +2750,7 @@ QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions()
*/
QDataStream &operator<<(QDataStream &out, const QRegularExpression &re)
{
- out << re.pattern() << quint32(re.patternOptions());
+ out << re.pattern() << quint32(re.patternOptions().toInt());
return out;
}
@@ -2599,7 +2767,7 @@ QDataStream &operator>>(QDataStream &in, QRegularExpression &re)
quint32 patternOptions;
in >> pattern >> patternOptions;
re.setPattern(pattern);
- re.setPatternOptions(QRegularExpression::PatternOptions(patternOptions));
+ re.setPatternOptions(QRegularExpression::PatternOptions::fromInt(patternOptions));
return in;
}
#endif
@@ -2651,13 +2819,6 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.append("DontCaptureOption|");
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
flags.append("UseUnicodePropertiesOption|");
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- if (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
- flags.append("OptimizeOnFirstUsageOption|");
- if (patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)
- flags.append("DontAutomaticallyOptimizeOption|");
-QT_WARNING_POP
flags.chop(1);
}
@@ -2917,7 +3078,8 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "heap limit exceeded"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid syntax"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error - duplicate substitution match"),
- QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching")
+ QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "INTERNAL ERROR: invalid substring offset")
};
#endif // #if 0
diff --git a/src/corelib/text/qregularexpression.h b/src/corelib/text/qregularexpression.h
index 30bdcdd4de..ab147b87d4 100644
--- a/src/corelib/text/qregularexpression.h
+++ b/src/corelib/text/qregularexpression.h
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QREGULAREXPRESSION_H
#define QREGULAREXPRESSION_H
@@ -47,18 +12,19 @@
#include <QtCore/qshareddata.h>
#include <QtCore/qvariant.h>
+#include <iterator>
+
QT_REQUIRE_CONFIG(regularexpression);
QT_BEGIN_NAMESPACE
-class QStringList;
-class QLatin1String;
-
class QRegularExpressionMatch;
class QRegularExpressionMatchIterator;
struct QRegularExpressionPrivate;
class QRegularExpression;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionPrivate, Q_CORE_EXPORT)
+
Q_CORE_EXPORT size_t qHash(const QRegularExpression &key, size_t seed = 0) noexcept;
class Q_CORE_EXPORT QRegularExpression
@@ -73,8 +39,9 @@ public:
InvertedGreedinessOption = 0x0010,
DontCaptureOption = 0x0020,
UseUnicodePropertiesOption = 0x0040,
- OptimizeOnFirstUsageOption Q_DECL_ENUMERATOR_DEPRECATED_X("This option does not have any effect since Qt 5.12") = 0x0080,
- DontAutomaticallyOptimizeOption Q_DECL_ENUMERATOR_DEPRECATED_X("This option does not have any effect since Qt 5.12") = 0x0100,
+ // Formerly (no-ops deprecated in 5.12, removed 6.0):
+ // OptimizeOnFirstUsageOption = 0x0080,
+ // DontAutomaticallyOptimizeOption = 0x0100,
};
Q_DECLARE_FLAGS(PatternOptions, PatternOption)
@@ -83,19 +50,20 @@ public:
QRegularExpression();
explicit QRegularExpression(const QString &pattern, PatternOptions options = NoPatternOption);
- QRegularExpression(const QRegularExpression &re);
+ QRegularExpression(const QRegularExpression &re) noexcept;
+ QRegularExpression(QRegularExpression &&re) = default;
~QRegularExpression();
- QRegularExpression &operator=(const QRegularExpression &re);
- QRegularExpression &operator=(QRegularExpression &&re) noexcept
- { d.swap(re.d); return *this; }
+ QRegularExpression &operator=(const QRegularExpression &re) noexcept;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegularExpression)
void swap(QRegularExpression &other) noexcept { d.swap(other.d); }
QString pattern() const;
void setPattern(const QString &pattern);
+ [[nodiscard]]
bool isValid() const;
- int patternErrorOffset() const;
+ qsizetype patternErrorOffset() const;
QString errorString() const;
int captureCount() const;
@@ -110,41 +78,64 @@ public:
enum MatchOption {
NoMatchOption = 0x0000,
- AnchoredMatchOption Q_DECL_ENUMERATOR_DEPRECATED_X("Use AnchorAtOffsetMatchOption instead") = 0x0001,
AnchorAtOffsetMatchOption = 0x0001,
+ AnchoredMatchOption Q_DECL_ENUMERATOR_DEPRECATED_X(
+ "Use AnchorAtOffsetMatchOption instead") = AnchorAtOffsetMatchOption, // Rename@Qt6.0
DontCheckSubjectStringMatchOption = 0x0002
};
Q_DECLARE_FLAGS(MatchOptions, MatchOption)
+ [[nodiscard]]
QRegularExpressionMatch match(const QString &subject,
- int offset = 0,
+ qsizetype offset = 0,
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+#if QT_DEPRECATED_SINCE(6, 8)
+ [[nodiscard]]
+ QT_DEPRECATED_VERSION_X_6_8("Use matchView instead.")
QRegularExpressionMatch match(QStringView subjectView,
- int offset = 0,
+ qsizetype offset = 0,
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+#endif
+
+ [[nodiscard]]
+ QRegularExpressionMatch matchView(QStringView subjectView,
+ qsizetype offset = 0,
+ MatchType matchType = NormalMatch,
+ MatchOptions matchOptions = NoMatchOption) const;
+ [[nodiscard]]
QRegularExpressionMatchIterator globalMatch(const QString &subject,
- int offset = 0,
+ qsizetype offset = 0,
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+#if QT_DEPRECATED_SINCE(6, 8)
+ [[nodiscard]]
+ QT_DEPRECATED_VERSION_X_6_8("Use globalMatchView instead.")
QRegularExpressionMatchIterator globalMatch(QStringView subjectView,
- int offset = 0,
+ qsizetype offset = 0,
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+#endif
+
+ [[nodiscard]]
+ QRegularExpressionMatchIterator globalMatchView(QStringView subjectView,
+ qsizetype offset = 0,
+ MatchType matchType = NormalMatch,
+ MatchOptions matchOptions = NoMatchOption) const;
void optimize() const;
enum WildcardConversionOption {
DefaultWildcardConversion = 0x0,
- UnanchoredWildcardConversion = 0x1
+ UnanchoredWildcardConversion = 0x1,
+ NonPathWildcardConversion = 0x2,
};
Q_DECLARE_FLAGS(WildcardConversionOptions, WildcardConversionOption)
-#if QT_STRINGVIEW_LEVEL < 2
static QString escape(const QString &str)
{
return escape(qToStringViewIgnoringNull(str));
@@ -159,19 +150,22 @@ public:
{
return anchoredPattern(qToStringViewIgnoringNull(expression));
}
-#endif
static QString escape(QStringView str);
static QString wildcardToRegularExpression(QStringView str, WildcardConversionOptions options = DefaultWildcardConversion);
static QString anchoredPattern(QStringView expression);
- static QRegularExpression fromWildcard(QStringView str, Qt::CaseSensitivity cs = Qt::CaseInsensitive,
+ static QRegularExpression fromWildcard(QStringView pattern, Qt::CaseSensitivity cs = Qt::CaseInsensitive,
WildcardConversionOptions options = DefaultWildcardConversion);
-
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QRegularExpression &re) const;
inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); }
-
+#endif
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QRegularExpression &lhs,
+ const QRegularExpression &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QRegularExpression)
+
friend struct QRegularExpressionPrivate;
friend class QRegularExpressionMatch;
friend struct QRegularExpressionMatchPrivate;
@@ -185,6 +179,7 @@ private:
Q_DECLARE_SHARED(QRegularExpression)
Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::PatternOptions)
Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::MatchOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::WildcardConversionOptions)
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegularExpression &re);
@@ -197,6 +192,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions
#endif
struct QRegularExpressionMatchPrivate;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionMatchPrivate, Q_CORE_EXPORT)
class Q_CORE_EXPORT QRegularExpressionMatch
{
@@ -204,6 +200,7 @@ public:
QRegularExpressionMatch();
~QRegularExpressionMatch();
QRegularExpressionMatch(const QRegularExpressionMatch &match);
+ QRegularExpressionMatch(QRegularExpressionMatch &&match) = default;
QRegularExpressionMatch &operator=(const QRegularExpressionMatch &match);
QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) noexcept
{ d.swap(match.d); return *this; }
@@ -220,31 +217,48 @@ public:
int lastCapturedIndex() const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ bool hasCaptured(const QString &name) const
+ { return hasCaptured(qToAnyStringViewIgnoringNull(name)); }
+ bool hasCaptured(QStringView name) const;
+#endif
+ bool hasCaptured(QAnyStringView name) const;
+ bool hasCaptured(int nth) const;
+
QString captured(int nth = 0) const;
QStringView capturedView(int nth = 0) const;
-#if QT_STRINGVIEW_LEVEL < 2
- QString captured(const QString &name) const;
-#endif
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ QString captured(const QString &name) const
+ { return captured(qToAnyStringViewIgnoringNull(name)); }
QString captured(QStringView name) const;
QStringView capturedView(QStringView name) const;
+#endif
+ QString captured(QAnyStringView name) const;
+ QStringView capturedView(QAnyStringView name) const;
QStringList capturedTexts() const;
- int capturedStart(int nth = 0) const;
- int capturedLength(int nth = 0) const;
- int capturedEnd(int nth = 0) const;
-
-#if QT_STRINGVIEW_LEVEL < 2
- int capturedStart(const QString &name) const;
- int capturedLength(const QString &name) const;
- int capturedEnd(const QString &name) const;
+ qsizetype capturedStart(int nth = 0) const;
+ qsizetype capturedLength(int nth = 0) const;
+ qsizetype capturedEnd(int nth = 0) const;
+
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ qsizetype capturedStart(const QString &name) const
+ { return capturedStart(qToAnyStringViewIgnoringNull(name)); }
+ qsizetype capturedLength(const QString &name) const
+ { return capturedLength(qToAnyStringViewIgnoringNull(name)); }
+ qsizetype capturedEnd(const QString &name) const
+ { return capturedEnd(qToAnyStringViewIgnoringNull(name)); }
+
+ qsizetype capturedStart(QStringView name) const;
+ qsizetype capturedLength(QStringView name) const;
+ qsizetype capturedEnd(QStringView name) const;
#endif
-
- int capturedStart(QStringView name) const;
- int capturedLength(QStringView name) const;
- int capturedEnd(QStringView name) const;
+ qsizetype capturedStart(QAnyStringView name) const;
+ qsizetype capturedLength(QAnyStringView name) const;
+ qsizetype capturedEnd(QAnyStringView name) const;
private:
friend class QRegularExpression;
@@ -252,7 +266,7 @@ private:
friend class QRegularExpressionMatchIterator;
QRegularExpressionMatch(QRegularExpressionMatchPrivate &dd);
- QSharedDataPointer<QRegularExpressionMatchPrivate> d;
+ QExplicitlySharedDataPointer<QRegularExpressionMatchPrivate> d;
};
Q_DECLARE_SHARED(QRegularExpressionMatch)
@@ -261,7 +275,13 @@ Q_DECLARE_SHARED(QRegularExpressionMatch)
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match);
#endif
+namespace QtPrivate {
+class QRegularExpressionMatchIteratorRangeBasedForIterator;
+class QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel {};
+}
+
struct QRegularExpressionMatchIteratorPrivate;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionMatchIteratorPrivate, Q_CORE_EXPORT)
class Q_CORE_EXPORT QRegularExpressionMatchIterator
{
@@ -269,6 +289,7 @@ public:
QRegularExpressionMatchIterator();
~QRegularExpressionMatchIterator();
QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator);
+ QRegularExpressionMatchIterator(QRegularExpressionMatchIterator &&iterator) = default;
QRegularExpressionMatchIterator &operator=(const QRegularExpressionMatchIterator &iterator);
QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) noexcept
{ d.swap(iterator.d); return *this; }
@@ -286,11 +307,94 @@ public:
private:
friend class QRegularExpression;
+ friend Q_CORE_EXPORT QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator);
+ friend QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &) { return {}; }
QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd);
- QSharedDataPointer<QRegularExpressionMatchIteratorPrivate> d;
+ QExplicitlySharedDataPointer<QRegularExpressionMatchIteratorPrivate> d;
};
+namespace QtPrivate {
+
+// support for range-based for loop
+class QRegularExpressionMatchIteratorRangeBasedForIterator
+{
+public:
+ using value_type = QRegularExpressionMatch;
+ using difference_type = int;
+ using reference_type = const QRegularExpressionMatch &;
+ using pointer_type = const QRegularExpressionMatch *;
+ using iterator_category = std::forward_iterator_tag;
+
+ QRegularExpressionMatchIteratorRangeBasedForIterator()
+ : m_atEnd(true)
+ {
+ }
+
+ explicit QRegularExpressionMatchIteratorRangeBasedForIterator(const QRegularExpressionMatchIterator &iterator)
+ : m_matchIterator(iterator),
+ m_currentMatch(),
+ m_atEnd(false)
+ {
+ ++*this;
+ }
+
+ const QRegularExpressionMatch &operator*() const
+ {
+ Q_ASSERT_X(!m_atEnd, Q_FUNC_INFO, "operator* called on an iterator already at the end");
+ return m_currentMatch;
+ }
+
+ QRegularExpressionMatchIteratorRangeBasedForIterator &operator++()
+ {
+ Q_ASSERT_X(!m_atEnd, Q_FUNC_INFO, "operator++ called on an iterator already at the end");
+ if (m_matchIterator.hasNext()) {
+ m_currentMatch = m_matchIterator.next();
+ } else {
+ m_currentMatch = QRegularExpressionMatch();
+ m_atEnd = true;
+ }
+
+ return *this;
+ }
+
+ QRegularExpressionMatchIteratorRangeBasedForIterator operator++(int)
+ {
+ QRegularExpressionMatchIteratorRangeBasedForIterator i = *this;
+ ++*this;
+ return i;
+ }
+
+private:
+ // [input.iterators] imposes operator== on us. Unfortunately, it's not
+ // trivial to implement, so just do the bare minimum to satifisfy
+ // Cpp17EqualityComparable.
+ friend bool comparesEqual(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
+ const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs)
+ noexcept
+ {
+ return (&lhs == &rhs);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QRegularExpressionMatchIteratorRangeBasedForIterator)
+
+ // This is what we really use in a range-based for.
+ friend bool comparesEqual(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
+ const QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel &rhs)
+ noexcept
+ {
+ Q_UNUSED(rhs);
+ return lhs.m_atEnd;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QRegularExpressionMatchIteratorRangeBasedForIterator,
+ QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel)
+
+ QRegularExpressionMatchIterator m_matchIterator;
+ QRegularExpressionMatch m_currentMatch;
+ bool m_atEnd;
+};
+
+} // namespace QtPrivate
+
Q_DECLARE_SHARED(QRegularExpressionMatchIterator)
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstaticlatin1stringmatcher.h b/src/corelib/text/qstaticlatin1stringmatcher.h
new file mode 100644
index 0000000000..bd6d9db08b
--- /dev/null
+++ b/src/corelib/text/qstaticlatin1stringmatcher.h
@@ -0,0 +1,157 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSTATICLATIN1STRINGMATCHER_H
+#define QSTATICLATIN1STRINGMATCHER_H
+
+#include <functional>
+#include <iterator>
+#include <limits>
+
+#include <QtCore/q20algorithm.h>
+#include <QtCore/qlatin1stringmatcher.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_CC_GHS
+# define QT_STATIC_BOYER_MOORE_NOT_SUPPORTED
+#else
+namespace QtPrivate {
+template <class RandomIt1,
+ class Hash = std::hash<typename std::iterator_traits<RandomIt1>::value_type>,
+ class BinaryPredicate = std::equal_to<>>
+class q_boyer_moore_searcher
+{
+public:
+ constexpr q_boyer_moore_searcher(RandomIt1 pat_first, RandomIt1 pat_last) : m_skiptable{}
+ {
+ const size_t n = std::distance(pat_first, pat_last);
+ constexpr auto uchar_max = (std::numeric_limits<uchar>::max)();
+ uchar max = n > uchar_max ? uchar_max : uchar(n);
+ q20::fill(std::begin(m_skiptable), std::end(m_skiptable), max);
+ Hash hf;
+ RandomIt1 pattern = std::next(pat_first, n - max);
+ while (max--)
+ m_skiptable[hf(*pattern++)] = max;
+ }
+
+ template <class RandomIt2>
+ constexpr auto operator()(RandomIt2 first, RandomIt2 last, RandomIt1 pat_first,
+ RandomIt1 pat_last) const
+ {
+ struct R
+ {
+ RandomIt2 begin, end;
+ };
+ Hash hf;
+ BinaryPredicate pred;
+ auto pat_length = std::distance(pat_first, pat_last);
+ if (pat_length == 0)
+ return R{ first, first };
+
+ auto haystack_length = std::distance(first, last);
+ if (haystack_length < pat_length)
+ return R{ last, last };
+
+ const qsizetype pl_minus_one = qsizetype(pat_length - 1);
+ RandomIt2 current = first + pl_minus_one;
+
+ qsizetype skip = 0;
+ while (current < last - skip) {
+ current += skip;
+ skip = m_skiptable[hf(*current)];
+ if (!skip) {
+ // possible match
+ while (skip < pat_length) {
+ if (!pred(hf(*(current - skip)), hf(pat_first[pl_minus_one - skip])))
+ break;
+ skip++;
+ }
+ if (skip > pl_minus_one) { // we have a match
+ auto match = current + 1 - skip;
+ return R{ match, match + pat_length };
+ }
+
+ // If we don't have a match we are a bit inefficient as we only skip by one
+ // when we have the non matching char in the string.
+ if (m_skiptable[hf(*(current - skip))] == pat_length)
+ skip = pat_length - skip;
+ else
+ skip = 1;
+ }
+ }
+
+ return R{ last, last };
+ }
+
+private:
+ alignas(16) uchar m_skiptable[256];
+};
+} // namespace QtPrivate
+
+template <Qt::CaseSensitivity CS, size_t N>
+class QStaticLatin1StringMatcher
+{
+ static_assert(N > 2,
+ "QStaticLatin1StringMatcher makes no sense for finding a single-char pattern");
+
+ QLatin1StringView m_pattern;
+ using Hasher = std::conditional_t<CS == Qt::CaseSensitive, QtPrivate::QCaseSensitiveLatin1Hash,
+ QtPrivate::QCaseInsensitiveLatin1Hash>;
+ QtPrivate::q_boyer_moore_searcher<const char *, Hasher> m_searcher;
+
+public:
+ explicit constexpr QStaticLatin1StringMatcher(QLatin1StringView patternToMatch) noexcept
+ : m_pattern(patternToMatch),
+ m_searcher(patternToMatch.begin(), patternToMatch.begin() + N - 1)
+ {
+ }
+
+ constexpr qsizetype indexIn(QLatin1StringView haystack, qsizetype from = 0) const noexcept
+ { return indexIn_helper(haystack, from); }
+
+ constexpr qsizetype indexIn(QStringView haystack, qsizetype from = 0) const noexcept
+ { return indexIn_helper(haystack, from); }
+
+private:
+ template <typename String>
+ constexpr qsizetype indexIn_helper(String haystack, qsizetype from = 0) const noexcept
+ {
+ static_assert(QtPrivate::isLatin1OrUtf16View<String>);
+
+ if (from >= haystack.size())
+ return -1;
+
+ const auto start = [haystack]() constexpr {
+ if constexpr (std::is_same_v<String, QStringView>)
+ return haystack.utf16();
+ else
+ return haystack.begin();
+ }();
+ const auto begin = start + from;
+ const auto end = start + haystack.size();
+ const auto r = m_searcher(begin, end, m_pattern.begin(), m_pattern.end());
+ return r.begin == end ? -1 : std::distance(start, r.begin);
+ }
+};
+
+template <size_t N>
+constexpr auto qMakeStaticCaseSensitiveLatin1StringMatcher(const char (&patternToMatch)[N]) noexcept
+{
+ return QStaticLatin1StringMatcher<Qt::CaseSensitive, N>(
+ QLatin1StringView(patternToMatch, qsizetype(N) - 1));
+}
+
+template <size_t N>
+constexpr auto
+qMakeStaticCaseInsensitiveLatin1StringMatcher(const char (&patternToMatch)[N]) noexcept
+{
+ return QStaticLatin1StringMatcher<Qt::CaseInsensitive, N>(
+ QLatin1StringView(patternToMatch, qsizetype(N) - 1));
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QSTATICLATIN1STRINGMATCHER_H
diff --git a/src/corelib/text/qstaticlatin1stringmatcher.qdoc b/src/corelib/text/qstaticlatin1stringmatcher.qdoc
new file mode 100644
index 0000000000..86edf69bc2
--- /dev/null
+++ b/src/corelib/text/qstaticlatin1stringmatcher.qdoc
@@ -0,0 +1,87 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*! \class QStaticLatin1StringMatcher
+ \inmodule QtCore
+ \brief The QStaticLatin1StringMatcher class is a compile-time version
+ of QLatin1StringMatcher.
+
+ \since 6.7
+ \ingroup tools
+ \ingroup string-processing
+
+ This class is useful when your code needs to search efficiently
+ in Latin-1 strings for a substring that's known at compile-time.
+ This is common, for example, in parsers. Using a matcher
+ object's indexIn() is faster than using the indexOf() member method of
+ the string you are searching in, especially when the string to
+ be found will be searched for repeatedly or within a large
+ Latin-1 string that may contain many matches to prefixes of the
+ substring to be found.
+
+ Unlike QLatin1StringMatcher, this class calculates the internal
+ representation at \e{compile-time}, so it can be beneficial even if you
+ are doing one-off Latin-1 string matches.
+
+ Create the QStaticLatin1StringMatcher by calling
+ qMakeStaticCaseSensitiveLatin1StringMatcher() or
+ qMakeStaticCaseInsensitiveLatin1StringMatcher() passing the Latin-1
+ string to search for as a C string literal. Store the return value of
+ that function in a \c{static constexpr auto} variable, so you don't
+ need to pass the \c{N} template parameter explicitly.
+
+ Then call indexIn() on the QLatin1StringView in which you want to search,
+ just like with QLatin1StringMatcher.
+
+ Since this class is designed to do all the up-front calculations at
+ compile-time, it does not offer setPattern() or setCaseSensitivity()
+ methods.
+
+ \note INTEGRITY operating system is currently not supported.
+
+ \sa QLatin1StringMatcher, QStaticByteArrayMatcher, QByteArrayMatcher
+*/
+
+/*!
+ \fn template<Qt::CaseSensitivity CS, size_t N> constexpr qsizetype QStaticLatin1StringMatcher<CS, N>::indexIn(QLatin1StringView haystack, qsizetype from) const
+ \fn template<Qt::CaseSensitivity CS, size_t N> constexpr qsizetype QStaticLatin1StringMatcher<CS, N>::indexIn(QStringView haystack, qsizetype from) const
+
+ Searches the QLatin1StringView \a haystack, from byte position \a from
+ (default 0, i.e. from the first byte), for QLatin1StringView pattern()
+ that was set in the constructor. Using the case sensitivity that was also
+ set in the constructor.
+
+ Returns the position where the pattern() matched in \a haystack, or -1 if no match was found.
+*/
+
+/*!
+ \fn template<size_t N> constexpr auto qMakeStaticCaseSensitiveLatin1StringMatcher(const char
+ (&patternToMatch)[N])
+
+ \since 6.7
+ \relates QStaticLatin1StringMatcher
+
+ Return a QStaticLatin1StringMatcher with the correct \c{N} determined
+ automatically from the \a patternToMatch passed, and with case sensitivity.
+
+ To take full advantage of this function, assign the result to a
+ \c{static constexpr auto} variable:
+
+ \snippet code/src_corelib_text_qstaticlatin1stringmatcher.cpp 0
+*/
+
+/*!
+ \fn template<size_t N> constexpr auto qMakeStaticCaseInsensitiveLatin1StringMatcher(const char
+ (&patternToMatch)[N])
+
+ \since 6.7
+ \relates QStaticLatin1StringMatcher
+
+ Return a QStaticLatin1StringMatcher with the correct \c{N} determined
+ automatically from the \a patternToMatch passed, and without case sensitivity.
+
+ To take full advantage of this function, assign the result to a
+ \c{static constexpr auto} variable:
+
+ \snippet code/src_corelib_text_qstaticlatin1stringmatcher.cpp 1
+*/
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 5bd063ee42..f0bf0c50a3 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2019 Mail.ru Group.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// Copyright (C) 2019 Mail.ru Group.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstringlist.h"
#if QT_CONFIG(regularexpression)
@@ -45,6 +9,7 @@
#endif
#include "qunicodetables_p.h"
#include <private/qstringconverter_p.h>
+#include <private/qtools_p.h>
#include "qlocale_tools_p.h"
#include "private/qsimd_p.h"
#include <qnumeric.h>
@@ -52,14 +17,16 @@
#include <qlist.h>
#include "qlocale.h"
#include "qlocale_p.h"
+#include "qspan.h"
#include "qstringbuilder.h"
#include "qstringmatcher.h"
#include "qvarlengtharray.h"
#include "qdebug.h"
#include "qendian.h"
#include "qcollator.h"
+#include "qttypetraits.h"
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
#include <private/qcore_mac_p.h>
#endif
@@ -73,38 +40,286 @@
#include <wchar.h>
#include "qchar.cpp"
+#include "qlatin1stringmatcher.h"
#include "qstringmatcher.cpp"
#include "qstringiterator_p.h"
#include "qstringalgorithms_p.h"
#include "qthreadstorage.h"
+#include <algorithm>
+#include <functional>
+
#ifdef Q_OS_WIN
# include <qt_windows.h>
+# if !defined(QT_BOOTSTRAPPED) && (defined(QT_NO_CAST_FROM_ASCII) || defined(QT_NO_CAST_TO_ASCII))
+// MSVC requires this, but let's apply it to MinGW compilers too, just in case
+# error "This file cannot be compiled with QT_NO_CAST_{TO,FROM}_ASCII, " \
+ "otherwise some QString functions will not get exported."
+# endif
#endif
#ifdef truncate
# undef truncate
#endif
-#ifndef LLONG_MAX
-#define LLONG_MAX qint64_C(9223372036854775807)
-#endif
-#ifndef LLONG_MIN
-#define LLONG_MIN (-LLONG_MAX - qint64_C(1))
-#endif
-#ifndef ULLONG_MAX
-#define ULLONG_MAX quint64_C(18446744073709551615)
-#endif
-
-#define IS_RAW_DATA(d) ((d.d)->flags & QArrayData::RawDataType)
+#define REHASH(a) \
+ if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
+ hashHaystack -= std::size_t(a) << sl_minus_1; \
+ hashHaystack <<= 1
QT_BEGIN_NAMESPACE
-template <typename T, typename Cmp = std::less<>>
-static constexpr bool points_into_range(const T *p, const T *b, const T *e, Cmp less = {}) noexcept
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
+const char16_t QString::_empty = 0;
+
+// in qstringmatcher.cpp
+qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
+
+namespace {
+enum StringComparisonMode {
+ CompareStringsForEquality,
+ CompareStringsForOrdering
+};
+
+template <typename Pointer>
+char32_t foldCaseHelper(Pointer ch, Pointer start) = delete;
+
+template <>
+char32_t foldCaseHelper<const QChar*>(const QChar* ch, const QChar* start)
+{
+ return foldCase(reinterpret_cast<const char16_t*>(ch),
+ reinterpret_cast<const char16_t*>(start));
+}
+
+template <>
+char32_t foldCaseHelper<const char*>(const char* ch, const char*)
+{
+ return foldCase(char16_t(uchar(*ch)));
+}
+
+template <typename T>
+char16_t valueTypeToUtf16(T t) = delete;
+
+template <>
+char16_t valueTypeToUtf16<QChar>(QChar t)
+{
+ return t.unicode();
+}
+
+template <>
+char16_t valueTypeToUtf16<char>(char t)
+{
+ return char16_t{uchar(t)};
+}
+
+template <typename T>
+static inline bool foldAndCompare(const T a, const T b)
+{
+ return foldCase(a) == b;
+}
+
+/*!
+ \internal
+
+ Returns the index position of the first occurrence of the
+ character \a ch in the string given by \a str and \a len,
+ searching forward from index
+ position \a from. Returns -1 if \a ch could not be found.
+*/
+template <typename Haystack>
+static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle,
+ qsizetype from, Qt::CaseSensitivity cs) noexcept
+{
+ if (haystack.size() == 0)
+ return -1;
+ if (from < 0)
+ from += haystack.size();
+ else if (std::size_t(from) > std::size_t(haystack.size()))
+ from = haystack.size() - 1;
+ if (from >= 0) {
+ char16_t c = needle.unicode();
+ const auto b = haystack.data();
+ auto n = b + from;
+ if (cs == Qt::CaseSensitive) {
+ for (; n >= b; --n)
+ if (valueTypeToUtf16(*n) == c)
+ return n - b;
+ } else {
+ c = foldCase(c);
+ for (; n >= b; --n)
+ if (foldCase(valueTypeToUtf16(*n)) == c)
+ return n - b;
+ }
+ }
+ return -1;
+}
+template <> qsizetype
+qLastIndexOf(QString, QChar, qsizetype, Qt::CaseSensitivity) noexcept = delete; // unwanted, would detach
+
+template<typename Haystack, typename Needle>
+static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
+ Needle needle0, Qt::CaseSensitivity cs) noexcept
+{
+ const qsizetype sl = needle0.size();
+ if (sl == 1)
+ return qLastIndexOf(haystack0, needle0.front(), from, cs);
+
+ const qsizetype l = haystack0.size();
+ if (from < 0)
+ from += l;
+ if (from == l && sl == 0)
+ return from;
+ const qsizetype delta = l - sl;
+ if (std::size_t(from) > std::size_t(l) || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ auto sv = [sl](const typename Haystack::value_type *v) { return Haystack(v, sl); };
+
+ auto haystack = haystack0.data();
+ const auto needle = needle0.data();
+ const auto *end = haystack;
+ haystack += from;
+ const std::size_t sl_minus_1 = sl ? sl - 1 : 0;
+ const auto *n = needle + sl_minus_1;
+ const auto *h = haystack + sl_minus_1;
+ std::size_t hashNeedle = 0, hashHaystack = 0;
+
+ if (cs == Qt::CaseSensitive) {
+ for (qsizetype idx = 0; idx < sl; ++idx) {
+ hashNeedle = (hashNeedle << 1) + valueTypeToUtf16(*(n - idx));
+ hashHaystack = (hashHaystack << 1) + valueTypeToUtf16(*(h - idx));
+ }
+ hashHaystack -= valueTypeToUtf16(*haystack);
+
+ while (haystack >= end) {
+ hashHaystack += valueTypeToUtf16(*haystack);
+ if (hashHaystack == hashNeedle
+ && QtPrivate::compareStrings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(valueTypeToUtf16(haystack[sl]));
+ }
+ } else {
+ for (qsizetype idx = 0; idx < sl; ++idx) {
+ hashNeedle = (hashNeedle << 1) + foldCaseHelper(n - idx, needle);
+ hashHaystack = (hashHaystack << 1) + foldCaseHelper(h - idx, end);
+ }
+ hashHaystack -= foldCaseHelper(haystack, end);
+
+ while (haystack >= end) {
+ hashHaystack += foldCaseHelper(haystack, end);
+ if (hashHaystack == hashNeedle
+ && QtPrivate::compareStrings(sv(haystack), needle0, Qt::CaseInsensitive) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(foldCaseHelper(haystack + sl, end));
+ }
+ }
+ return -1;
+}
+
+template <typename Haystack, typename Needle>
+bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) noexcept
+{
+ if (haystack.isNull())
+ return needle.isNull();
+ const auto haystackLen = haystack.size();
+ const auto needleLen = needle.size();
+ if (haystackLen == 0)
+ return needleLen == 0;
+ if (needleLen > haystackLen)
+ return false;
+
+ return QtPrivate::compareStrings(haystack.first(needleLen), needle, cs) == 0;
+}
+
+template <typename Haystack, typename Needle>
+bool qt_ends_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) noexcept
+{
+ if (haystack.isNull())
+ return needle.isNull();
+ const auto haystackLen = haystack.size();
+ const auto needleLen = needle.size();
+ if (haystackLen == 0)
+ return needleLen == 0;
+ if (haystackLen < needleLen)
+ return false;
+
+ return QtPrivate::compareStrings(haystack.last(needleLen), needle, cs) == 0;
+}
+
+template <typename T>
+static void append_helper(QString &self, T view)
+{
+ const auto strData = view.data();
+ const qsizetype strSize = view.size();
+ auto &d = self.data_ptr();
+ if (strData && strSize > 0) {
+ // the number of UTF-8 code units is always at a minimum equal to the number
+ // of equivalent UTF-16 code units
+ d.detachAndGrow(QArrayData::GrowsAtEnd, strSize, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
+ Q_ASSERT(strSize <= d.freeSpaceAtEnd());
+
+ auto dst = std::next(d.data(), d.size);
+ if constexpr (std::is_same_v<T, QUtf8StringView>) {
+ dst = QUtf8::convertToUnicode(dst, view);
+ } else if constexpr (std::is_same_v<T, QLatin1StringView>) {
+ QLatin1::convertToUnicode(dst, view);
+ dst += strSize;
+ } else {
+ static_assert(QtPrivate::type_dependent_false<T>(),
+ "Can only operate on UTF-8 and Latin-1");
+ }
+ self.resize(std::distance(d.begin(), dst));
+ } else if (d.isNull() && !view.isNull()) { // special case
+ self = QLatin1StringView("");
+ }
+}
+
+template <uint MaxCount> struct UnrollTailLoop
+{
+ template <typename RetType, typename Functor1, typename Functor2, typename Number>
+ static inline RetType exec(Number count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, Number i = 0)
+ {
+ /* equivalent to:
+ * while (count--) {
+ * if (loopCheck(i))
+ * return returnIfFailed(i);
+ * }
+ * return returnIfExited;
+ */
+
+ if (!count)
+ return returnIfExited;
+
+ bool check = loopCheck(i);
+ if (check)
+ return returnIfFailed(i);
+
+ return UnrollTailLoop<MaxCount - 1>::exec(count - 1, returnIfExited, loopCheck, returnIfFailed, i + 1);
+ }
+
+ template <typename Functor, typename Number>
+ static inline void exec(Number count, Functor code)
+ {
+ /* equivalent to:
+ * for (Number i = 0; i < count; ++i)
+ * code(i);
+ */
+ exec(count, 0, [=](Number i) -> bool { code(i); return false; }, [](Number) { return 0; });
+ }
+};
+template <> template <typename RetType, typename Functor1, typename Functor2, typename Number>
+inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1, Functor2, Number)
{
- return !less(p, b) && less(p, e);
+ return returnIfExited;
}
+} // unnamed namespace
/*
* Note on the use of SIMD in qstring.cpp:
@@ -143,32 +358,38 @@ extern "C" void qt_fromlatin1_mips_asm_unroll8 (char16_t*, const char*, uint);
extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const char16_t *src, int length);
#endif
-// internal
-qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
-static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept;
-template <typename Haystack>
-static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) noexcept;
-template <>
-inline qsizetype qLastIndexOf(QString haystack, QChar needle,
- qsizetype from, Qt::CaseSensitivity cs) noexcept = delete; // unwanted, would detach
-
-static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
-static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
-static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
-static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
-static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
-static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
-
-#if defined(__SSE2__) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+#if defined(__SSE2__) && defined(Q_CC_GNU)
// We may overrun the buffer, but that's a false positive:
// this won't crash nor produce incorrect results
-__attribute__((__no_sanitize_address__))
+# define ATTRIBUTE_NO_SANITIZE __attribute__((__no_sanitize_address__))
+#else
+# define ATTRIBUTE_NO_SANITIZE
#endif
-qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
+
+#ifdef __SSE2__
+static constexpr bool UseSse4_1 = bool(qCompilerCpuFeatures & CpuFeatureSSE4_1);
+static constexpr bool UseAvx2 = UseSse4_1 &&
+ (qCompilerCpuFeatures & CpuFeatureArchHaswell) == CpuFeatureArchHaswell;
+
+[[maybe_unused]]
+static Q_ALWAYS_INLINE __m128i mm_load8_zero_extend(const void *ptr)
{
- qsizetype result = 0;
+ const __m128i *dataptr = static_cast<const __m128i *>(ptr);
+ if constexpr (UseSse4_1) {
+ // use a MOVQ followed by PMOVZXBW
+ // if AVX2 is present, these should combine into a single VPMOVZXBW instruction
+ __m128i data = _mm_loadl_epi64(dataptr);
+ return _mm_cvtepu8_epi16(data);
+ }
+
+ // use MOVQ followed by PUNPCKLBW
+ __m128i data = _mm_loadl_epi64(dataptr);
+ return _mm_unpacklo_epi8(data, _mm_setzero_si128());
+}
-#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || QT_HAS_FEATURE(address_sanitizer))
+[[maybe_unused]] ATTRIBUTE_NO_SANITIZE
+static qsizetype qustrlen_sse2(const char16_t *str) noexcept
+{
// find the 16-byte alignment immediately prior or equal to str
quintptr misalignment = quintptr(str) & 0xf;
Q_ASSERT((misalignment & 1) == 0);
@@ -179,7 +400,7 @@ qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
const __m128i zeroes = _mm_setzero_si128();
__m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
__m128i comparison = _mm_cmpeq_epi16(data, zeroes);
- quint32 mask = _mm_movemask_epi8(comparison);
+ uint mask = _mm_movemask_epi8(comparison);
// ignore the result prior to the beginning of str
mask >>= misalignment;
@@ -187,71 +408,272 @@ qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
// Have we found something in the first block? Need to handle it now
// because of the left shift above.
if (mask)
- return qCountTrailingZeroBits(quint32(mask)) / 2;
+ return qCountTrailingZeroBits(mask) / sizeof(char16_t);
+
+ constexpr qsizetype Step = sizeof(__m128i) / sizeof(char16_t);
+ qsizetype size = Step - misalignment / sizeof(char16_t);
+ size -= Step;
do {
- ptr += 8;
- data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
+ size += Step;
+ data = _mm_load_si128(reinterpret_cast<const __m128i *>(str + size));
comparison = _mm_cmpeq_epi16(data, zeroes);
mask = _mm_movemask_epi8(comparison);
} while (mask == 0);
// found a null
- uint idx = qCountTrailingZeroBits(quint32(mask));
- return ptr - str + idx / 2;
-#endif
+ return size + qCountTrailingZeroBits(mask) / sizeof(char16_t);
+}
- if (sizeof(wchar_t) == sizeof(char16_t))
- return wcslen(reinterpret_cast<const wchar_t *>(str));
+// Scans from \a ptr to \a end until \a maskval is non-zero. Returns true if
+// the no non-zero was found. Returns false and updates \a ptr to point to the
+// first 16-bit word that has any bit set (note: if the input is 8-bit, \a ptr
+// may be updated to one byte short).
+static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
+{
+ auto updatePtr = [&](uint result) {
+ // found a character matching the mask
+ uint idx = qCountTrailingZeroBits(~result);
+ ptr += idx;
+ return false;
+ };
- while (*str++)
- ++result;
- return result;
+ if constexpr (UseSse4_1) {
+# ifndef Q_OS_QNX // compiler fails in the code below
+ __m128i mask;
+ auto updatePtrSimd = [&](__m128i data) -> bool {
+ __m128i masked = _mm_and_si128(mask, data);
+ __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
+ uint result = _mm_movemask_epi8(comparison);
+ return updatePtr(result);
+ };
+
+ if constexpr (UseAvx2) {
+ // AVX2 implementation: test 32 bytes at a time
+ const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval));
+ while (ptr + 32 <= end) {
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
+ if (!_mm256_testz_si256(mask256, data)) {
+ // found a character matching the mask
+ __m256i masked256 = _mm256_and_si256(mask256, data);
+ __m256i comparison256 = _mm256_cmpeq_epi16(masked256, _mm256_setzero_si256());
+ return updatePtr(_mm256_movemask_epi8(comparison256));
+ }
+ ptr += 32;
+ }
+
+ mask = _mm256_castsi256_si128(mask256);
+ } else {
+ // SSE 4.1 implementation: test 32 bytes at a time (two 16-byte
+ // comparisons, unrolled)
+ mask = _mm_set1_epi32(maskval);
+ while (ptr + 32 <= end) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
+ if (!_mm_testz_si128(mask, data1))
+ return updatePtrSimd(data1);
+
+ ptr += 16;
+ if (!_mm_testz_si128(mask, data2))
+ return updatePtrSimd(data2);
+ ptr += 16;
+ }
+ }
+
+ // AVX2 and SSE4.1: final 16-byte comparison
+ if (ptr + 16 <= end) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ if (!_mm_testz_si128(mask, data1))
+ return updatePtrSimd(data1);
+ ptr += 16;
+ }
+
+ // and final 8-byte comparison
+ if (ptr + 8 <= end) {
+ __m128i data1 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ if (!_mm_testz_si128(mask, data1))
+ return updatePtrSimd(data1);
+ ptr += 8;
+ }
+
+ return true;
+# endif // QNX
+ }
+
+ // SSE2 implementation: test 16 bytes at a time.
+ const __m128i mask = _mm_set1_epi32(maskval);
+ while (ptr + 16 <= end) {
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i masked = _mm_and_si128(mask, data);
+ __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
+ quint16 result = _mm_movemask_epi8(comparison);
+ if (result != 0xffff)
+ return updatePtr(result);
+ ptr += 16;
+ }
+
+ // and one 8-byte comparison
+ if (ptr + 8 <= end) {
+ __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ __m128i masked = _mm_and_si128(mask, data);
+ __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
+ quint8 result = _mm_movemask_epi8(comparison);
+ if (result != 0xff)
+ return updatePtr(result);
+ ptr += 8;
+ }
+
+ return true;
}
-#if !defined(__OPTIMIZE_SIZE__)
-namespace {
-template <uint MaxCount> struct UnrollTailLoop
+template <StringComparisonMode Mode, typename Char> [[maybe_unused]]
+static int ucstrncmp_sse2(const char16_t *a, const Char *b, size_t l)
{
- template <typename RetType, typename Functor1, typename Functor2, typename Number>
- static inline RetType exec(Number count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, Number i = 0)
- {
- /* equivalent to:
- * while (count--) {
- * if (loopCheck(i))
- * return returnIfFailed(i);
- * }
- * return returnIfExited;
- */
+ static_assert(std::is_unsigned_v<Char>);
- if (!count)
- return returnIfExited;
+ // Using the PMOVMSKB instruction, we get two bits for each UTF-16 character
+ // we compare. This lambda helps extract the code unit.
+ static const auto codeUnitAt = [](const auto *n, qptrdiff idx) -> int {
+ constexpr int Stride = 2;
+ // this is the same as:
+ // return n[idx / Stride];
+ // but using pointer arithmetic to avoid the compiler dividing by two
+ // and multiplying by two in the case of char16_t (we know idx is even,
+ // but the compiler does not). This is not UB.
- bool check = loopCheck(i);
- if (check)
- return returnIfFailed(i);
+ auto ptr = reinterpret_cast<const uchar *>(n);
+ ptr += idx / (Stride / sizeof(*n));
+ return *reinterpret_cast<decltype(n)>(ptr);
+ };
+ auto difference = [a, b](uint mask, qptrdiff offset) {
+ if (Mode == CompareStringsForEquality)
+ return 1;
+ uint idx = qCountTrailingZeroBits(mask);
+ return codeUnitAt(a + offset, idx) - codeUnitAt(b + offset, idx);
+ };
- return UnrollTailLoop<MaxCount - 1>::exec(count - 1, returnIfExited, loopCheck, returnIfFailed, i + 1);
- }
+ static const auto load8Chars = [](const auto *ptr) {
+ if (sizeof(*ptr) == 2)
+ return _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i chunk = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ return _mm_unpacklo_epi8(chunk, _mm_setzero_si128());
+ };
+ static const auto load4Chars = [](const auto *ptr) {
+ if (sizeof(*ptr) == 2)
+ return _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ __m128i chunk = _mm_cvtsi32_si128(qFromUnaligned<quint32>(ptr));
+ return _mm_unpacklo_epi8(chunk, _mm_setzero_si128());
+ };
- template <typename Functor, typename Number>
- static inline void exec(Number count, Functor code)
- {
- /* equivalent to:
- * for (Number i = 0; i < count; ++i)
- * code(i);
- */
- exec(count, 0, [=](Number i) -> bool { code(i); return false; }, [](Number) { return 0; });
+ // we're going to read a[0..15] and b[0..15] (32 bytes)
+ auto processChunk16Chars = [a, b](qptrdiff offset) -> uint {
+ if constexpr (UseAvx2) {
+ __m256i a_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(a + offset));
+ __m256i b_data;
+ if (sizeof(Char) == 1) {
+ // expand to UTF-16 via zero-extension
+ __m128i chunk = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset));
+ b_data = _mm256_cvtepu8_epi16(chunk);
+ } else {
+ b_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(b + offset));
+ }
+ __m256i result = _mm256_cmpeq_epi16(a_data, b_data);
+ return _mm256_movemask_epi8(result);
+ }
+
+ __m128i a_data1 = load8Chars(a + offset);
+ __m128i a_data2 = load8Chars(a + offset + 8);
+ __m128i b_data1, b_data2;
+ if (sizeof(Char) == 1) {
+ // expand to UTF-16 via unpacking
+ __m128i b_data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset));
+ b_data1 = _mm_unpacklo_epi8(b_data, _mm_setzero_si128());
+ b_data2 = _mm_unpackhi_epi8(b_data, _mm_setzero_si128());
+ } else {
+ b_data1 = load8Chars(b + offset);
+ b_data2 = load8Chars(b + offset + 8);
+ }
+ __m128i result1 = _mm_cmpeq_epi16(a_data1, b_data1);
+ __m128i result2 = _mm_cmpeq_epi16(a_data2, b_data2);
+ return _mm_movemask_epi8(result1) | _mm_movemask_epi8(result2) << 16;
+ };
+
+ if (l >= sizeof(__m256i) / sizeof(char16_t)) {
+ qptrdiff offset = 0;
+ for ( ; l >= offset + sizeof(__m256i) / sizeof(char16_t); offset += sizeof(__m256i) / sizeof(char16_t)) {
+ uint mask = ~processChunk16Chars(offset);
+ if (mask)
+ return difference(mask, offset);
+ }
+
+ // maybe overlap the last 32 bytes
+ if (size_t(offset) < l) {
+ offset = l - sizeof(__m256i) / sizeof(char16_t);
+ uint mask = ~processChunk16Chars(offset);
+ return mask ? difference(mask, offset) : 0;
+ }
+ } else if (l >= 4) {
+ __m128i a_data1, b_data1;
+ __m128i a_data2, b_data2;
+ int width;
+ if (l >= 8) {
+ width = 8;
+ a_data1 = load8Chars(a);
+ b_data1 = load8Chars(b);
+ a_data2 = load8Chars(a + l - width);
+ b_data2 = load8Chars(b + l - width);
+ } else {
+ // we're going to read a[0..3] and b[0..3] (8 bytes)
+ width = 4;
+ a_data1 = load4Chars(a);
+ b_data1 = load4Chars(b);
+ a_data2 = load4Chars(a + l - width);
+ b_data2 = load4Chars(b + l - width);
+ }
+
+ __m128i result = _mm_cmpeq_epi16(a_data1, b_data1);
+ ushort mask = ~_mm_movemask_epi8(result);
+ if (mask)
+ return difference(mask, 0);
+
+ result = _mm_cmpeq_epi16(a_data2, b_data2);
+ mask = ~_mm_movemask_epi8(result);
+ if (mask)
+ return difference(mask, l - width);
+ } else {
+ // reset l
+ l &= 3;
+
+ const auto lambda = [=](size_t i) -> int {
+ return a[i] - b[i];
+ };
+ return UnrollTailLoop<3>::exec(l, 0, lambda, lambda);
}
-};
-template <> template <typename RetType, typename Functor1, typename Functor2, typename Number>
-inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1, Functor2, Number)
+ return 0;
+}
+#endif
+
+Q_NEVER_INLINE
+qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
{
- return returnIfExited;
+#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
+ return qustrlen_sse2(str);
+#endif
+
+ if (sizeof(wchar_t) == sizeof(char16_t))
+ return wcslen(reinterpret_cast<const wchar_t *>(str));
+
+ qsizetype result = 0;
+ while (*str++)
+ ++result;
+ return result;
}
+
+qsizetype QtPrivate::qustrnlen(const char16_t *str, qsizetype maxlen) noexcept
+{
+ return qustrchr({ str, maxlen }, u'\0') - str;
}
-#endif
/*!
* \internal
@@ -261,6 +683,7 @@ inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1,
* character is not found, this function returns a pointer to the end of the
* string -- that is, \c{str.end()}.
*/
+Q_NEVER_INLINE
const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
{
const char16_t *n = str.utf16();
@@ -270,23 +693,24 @@ const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
bool loops = true;
// Using the PMOVMSKB instruction, we get two bits for each character
// we compare.
-# if defined(__AVX2__) && !defined(__OPTIMIZE_SIZE__)
- // we're going to read n[0..15] (32 bytes)
- __m256i mch256 = _mm256_set1_epi32(c | (c << 16));
- for (const char16_t *next = n + 16; next <= e; n = next, next += 16) {
- __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(n));
- __m256i result = _mm256_cmpeq_epi16(data, mch256);
- uint mask = uint(_mm256_movemask_epi8(result));
- if (mask) {
- uint idx = qCountTrailingZeroBits(mask);
- return n + idx / 2;
+ __m128i mch;
+ if constexpr (UseAvx2) {
+ // we're going to read n[0..15] (32 bytes)
+ __m256i mch256 = _mm256_set1_epi32(c | (c << 16));
+ for (const char16_t *next = n + 16; next <= e; n = next, next += 16) {
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(n));
+ __m256i result = _mm256_cmpeq_epi16(data, mch256);
+ uint mask = uint(_mm256_movemask_epi8(result));
+ if (mask) {
+ uint idx = qCountTrailingZeroBits(mask);
+ return n + idx / 2;
+ }
}
+ loops = false;
+ mch = _mm256_castsi256_si128(mch256);
+ } else {
+ mch = _mm_set1_epi32(c | (c << 16));
}
- loops = false;
- __m128i mch = _mm256_castsi256_si128(mch256);
-# else
- __m128i mch = _mm_set1_epi32(c | (c << 16));
-# endif
auto hasMatch = [mch, &n](__m128i data, ushort validityMask) {
__m128i result = _mm_cmpeq_epi16(data, mch);
@@ -321,10 +745,10 @@ const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
}
return UnrollTailLoop<3>::exec(e - n, e,
- [=](int i) { return n[i] == c; },
- [=](int i) { return n + i; });
+ [=](qsizetype i) { return n[i] == c; },
+ [=](qsizetype i) { return n + i; });
# endif
-#elif defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
+#elif defined(__ARM_NEON__)
const uint16x8_t vmask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
const uint16x8_t ch_vec = vdupq_n_u16(c);
for (const char16_t *next = n + 8; next <= e; n = next, next += 8) {
@@ -337,128 +761,25 @@ const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
}
#endif // aarch64
- --n;
- while (++n != e)
- if (*n == c)
- return n;
-
- return n;
+ return std::find(n, e, c);
}
-#ifdef __SSE2__
-// Scans from \a ptr to \a end until \a maskval is non-zero. Returns true if
-// the no non-zero was found. Returns false and updates \a ptr to point to the
-// first 16-bit word that has any bit set (note: if the input is 8-bit, \a ptr
-// may be updated to one byte short).
-static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
-{
- auto updatePtr = [&](uint result) {
- // found a character matching the mask
- uint idx = qCountTrailingZeroBits(~result);
- ptr += idx;
- return false;
- };
-
-# if defined(__SSE4_1__)
- __m128i mask;
- auto updatePtrSimd = [&](__m128i data) {
- __m128i masked = _mm_and_si128(mask, data);
- __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
- uint result = _mm_movemask_epi8(comparison);
- return updatePtr(result);
- };
-
-# if defined(__AVX2__)
- // AVX2 implementation: test 32 bytes at a time
- const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval));
- while (ptr + 32 <= end) {
- __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
- if (!_mm256_testz_si256(mask256, data)) {
- // found a character matching the mask
- __m256i masked256 = _mm256_and_si256(mask256, data);
- __m256i comparison256 = _mm256_cmpeq_epi16(masked256, _mm256_setzero_si256());
- return updatePtr(_mm256_movemask_epi8(comparison256));
- }
- ptr += 32;
- }
-
- mask = _mm256_castsi256_si128(mask256);
-# else
- // SSE 4.1 implementation: test 32 bytes at a time (two 16-byte
- // comparisons, unrolled)
- mask = _mm_set1_epi32(maskval);
- while (ptr + 32 <= end) {
- __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
- __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
- if (!_mm_testz_si128(mask, data1))
- return updatePtrSimd(data1);
-
- ptr += 16;
- if (!_mm_testz_si128(mask, data2))
- return updatePtrSimd(data2);
- ptr += 16;
- }
-# endif
-
- // AVX2 and SSE4.1: final 16-byte comparison
- if (ptr + 16 <= end) {
- __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
- if (!_mm_testz_si128(mask, data1))
- return updatePtrSimd(data1);
- ptr += 16;
- }
-
- // and final 8-byte comparison
- if (ptr + 8 <= end) {
- __m128i data1 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
- if (!_mm_testz_si128(mask, data1))
- return updatePtrSimd(data1);
- ptr += 8;
- }
-
-# else
- // SSE2 implementation: test 16 bytes at a time.
- const __m128i mask = _mm_set1_epi32(maskval);
- while (ptr + 16 <= end) {
- __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
- __m128i masked = _mm_and_si128(mask, data);
- __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
- quint16 result = _mm_movemask_epi8(comparison);
- if (result != 0xffff)
- return updatePtr(result);
- ptr += 16;
- }
-
- // and one 8-byte comparison
- if (ptr + 8 <= end) {
- __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
- __m128i masked = _mm_and_si128(mask, data);
- __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
- quint8 result = _mm_movemask_epi8(comparison);
- if (result != 0xff)
- return updatePtr(result);
- ptr += 8;
- }
-# endif
-
- return true;
-}
-
-static Q_ALWAYS_INLINE __m128i mm_load8_zero_extend(const void *ptr)
+/*!
+ * \internal
+ *
+ * Searches case-insensitively for character \a c in the string \a str and
+ * returns a pointer to it. Iif the character is not found, this function
+ * returns a pointer to the end of the string -- that is, \c{str.end()}.
+ */
+Q_NEVER_INLINE
+const char16_t *QtPrivate::qustrcasechr(QStringView str, char16_t c) noexcept
{
- const __m128i *dataptr = static_cast<const __m128i *>(ptr);
-#if defined(__SSE4_1__)
- // use a MOVQ followed by PMOVZXBW
- // if AVX2 is present, these should combine into a single VPMOVZXBW instruction
- __m128i data = _mm_loadl_epi64(dataptr);
- return _mm_cvtepu8_epi16(data);
-# else
- // use MOVQ followed by PUNPCKLBW
- __m128i data = _mm_loadl_epi64(dataptr);
- return _mm_unpacklo_epi8(data, _mm_setzero_si128());
-# endif
+ const QChar *n = str.begin();
+ const QChar *e = str.end();
+ c = foldCase(c);
+ auto it = std::find_if(n, e, [c](auto ch) { return foldAndCompare(ch, QChar(c)); });
+ return reinterpret_cast<const char16_t *>(it);
}
-#endif
// Note: ptr on output may be off by one and point to a preceding US-ASCII
// character. Usually harmless.
@@ -466,18 +787,21 @@ bool qt_is_ascii(const char *&ptr, const char *end) noexcept
{
#if defined(__SSE2__)
// Testing for the high bit can be done efficiently with just PMOVMSKB
-# if defined(__AVX2__)
- while (ptr + 32 <= end) {
- __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
- quint32 mask = _mm256_movemask_epi8(data);
- if (mask) {
- uint idx = qCountTrailingZeroBits(mask);
- ptr += idx;
- return false;
+ bool loops = true;
+ if constexpr (UseAvx2) {
+ while (ptr + 32 <= end) {
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
+ quint32 mask = _mm256_movemask_epi8(data);
+ if (mask) {
+ uint idx = qCountTrailingZeroBits(mask);
+ ptr += idx;
+ return false;
+ }
+ ptr += 32;
}
- ptr += 32;
+ loops = false;
}
-# endif
+
while (ptr + 16 <= end) {
__m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
quint32 mask = _mm_movemask_epi8(data);
@@ -487,6 +811,9 @@ bool qt_is_ascii(const char *&ptr, const char *end) noexcept
return false;
}
ptr += 16;
+
+ if (!loops)
+ break;
}
if (ptr + 8 <= end) {
__m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
@@ -503,11 +830,9 @@ bool qt_is_ascii(const char *&ptr, const char *end) noexcept
while (ptr + 4 <= end) {
quint32 data = qFromUnaligned<quint32>(ptr);
if (data &= 0x80808080U) {
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- uint idx = qCountLeadingZeroBits(data);
-#else
- uint idx = qCountTrailingZeroBits(data);
-#endif
+ uint idx = QSysInfo::ByteOrder == QSysInfo::BigEndian
+ ? qCountLeadingZeroBits(data)
+ : qCountTrailingZeroBits(data);
ptr += idx / 8;
return false;
}
@@ -522,7 +847,7 @@ bool qt_is_ascii(const char *&ptr, const char *end) noexcept
return true;
}
-bool QtPrivate::isAscii(QLatin1String s) noexcept
+bool QtPrivate::isAscii(QLatin1StringView s) noexcept
{
const char *ptr = s.begin();
const char *end = s.end();
@@ -530,19 +855,19 @@ bool QtPrivate::isAscii(QLatin1String s) noexcept
return qt_is_ascii(ptr, end);
}
-static bool isAscii(const QChar *&ptr, const QChar *end)
+static bool isAscii_helper(const char16_t *&ptr, const char16_t *end)
{
#ifdef __SSE2__
const char *ptr8 = reinterpret_cast<const char *>(ptr);
const char *end8 = reinterpret_cast<const char *>(end);
bool ok = simdTestMask(ptr8, end8, 0xff80ff80);
- ptr = reinterpret_cast<const QChar *>(ptr8);
+ ptr = reinterpret_cast<const char16_t *>(ptr8);
if (!ok)
return false;
#endif
while (ptr != end) {
- if (ptr->unicode() & 0xff80)
+ if (*ptr & 0xff80)
return false;
++ptr;
}
@@ -551,46 +876,27 @@ static bool isAscii(const QChar *&ptr, const QChar *end)
bool QtPrivate::isAscii(QStringView s) noexcept
{
- const QChar *ptr = s.begin();
- const QChar *end = s.end();
+ const char16_t *ptr = s.utf16();
+ const char16_t *end = ptr + s.size();
- return isAscii(ptr, end);
+ return isAscii_helper(ptr, end);
}
bool QtPrivate::isLatin1(QStringView s) noexcept
{
- const QChar *ptr = s.begin();
- const QChar *end = s.end();
+ const char16_t *ptr = s.utf16();
+ const char16_t *end = ptr + s.size();
-#if defined(__SSE4_1__)
+#ifdef __SSE2__
const char *ptr8 = reinterpret_cast<const char *>(ptr);
const char *end8 = reinterpret_cast<const char *>(end);
if (!simdTestMask(ptr8, end8, 0xff00ff00))
return false;
- ptr = reinterpret_cast<const QChar *>(ptr8);
-#elif defined(__SSE2__)
- // Testing if every other byte is non-zero can be done efficiently by
- // using PUNPCKHBW (unpack high order bytes) and comparing that to zero.
- while (ptr + 32 < end) {
- __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
- __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
- __m128i high = _mm_unpackhi_epi8(data1, data2);
- __m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128());
- if (_mm_movemask_epi8(comparison))
- return false;
- ptr += 16;
- }
- if (ptr + 16 < end) {
- __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
- __m128i high = _mm_unpackhi_epi8(data1, data1);
- __m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128());
- if (_mm_movemask_epi8(comparison))
- return false;
- }
+ ptr = reinterpret_cast<const char16_t *>(ptr8);
#endif
while (ptr != end) {
- if ((*ptr++).unicode() > 0xff)
+ if (*ptr++ > 0xff)
return false;
}
return true;
@@ -598,7 +904,7 @@ bool QtPrivate::isLatin1(QStringView s) noexcept
bool QtPrivate::isValidUtf16(QStringView s) noexcept
{
- Q_CONSTEXPR char32_t InvalidCodePoint = UINT_MAX;
+ constexpr char32_t InvalidCodePoint = UINT_MAX;
QStringIterator i(s);
while (i.hasNext()) {
@@ -619,46 +925,63 @@ Q_CORE_EXPORT void qt_from_latin1(char16_t *dst, const char *str, size_t size) n
* itself in exactly the same way as one would do it with intrinsics.
*/
#if defined(__SSE2__)
- const char *e = str + size;
- qptrdiff offset = 0;
-
// we're going to read str[offset..offset+15] (16 bytes)
- for ( ; str + offset + 15 < e; offset += 16) {
+ const __m128i nullMask = _mm_setzero_si128();
+ auto processOneChunk = [=](qptrdiff offset) {
const __m128i chunk = _mm_loadu_si128((const __m128i*)(str + offset)); // load
-#ifdef __AVX2__
- // zero extend to an YMM register
- const __m256i extended = _mm256_cvtepu8_epi16(chunk);
+ if constexpr (UseAvx2) {
+ // zero extend to an YMM register
+ const __m256i extended = _mm256_cvtepu8_epi16(chunk);
- // store
- _mm256_storeu_si256((__m256i*)(dst + offset), extended);
-#else
- const __m128i nullMask = _mm_set1_epi32(0);
-
- // unpack the first 8 bytes, padding with zeros
- const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
- _mm_storeu_si128((__m128i*)(dst + offset), firstHalf); // store
+ // store
+ _mm256_storeu_si256((__m256i*)(dst + offset), extended);
+ } else {
+ // unpack the first 8 bytes, padding with zeros
+ const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
+ _mm_storeu_si128((__m128i*)(dst + offset), firstHalf); // store
- // unpack the last 8 bytes, padding with zeros
- const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
- _mm_storeu_si128((__m128i*)(dst + offset + 8), secondHalf); // store
-#endif
- }
+ // unpack the last 8 bytes, padding with zeros
+ const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
+ _mm_storeu_si128((__m128i*)(dst + offset + 8), secondHalf); // store
+ }
+ };
- // we're going to read str[offset..offset+7] (8 bytes)
- if (str + offset + 7 < e) {
- const __m128i unpacked = mm_load8_zero_extend(str + offset);
- _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + offset), unpacked);
- offset += 8;
+ const char *e = str + size;
+ if (size >= sizeof(__m128i)) {
+ qptrdiff offset = 0;
+ for ( ; str + offset + sizeof(__m128i) <= e; offset += sizeof(__m128i))
+ processOneChunk(offset);
+ if (str + offset < e)
+ processOneChunk(size - sizeof(__m128i));
+ return;
}
- size = size % 8;
- dst += offset;
- str += offset;
# if !defined(__OPTIMIZE_SIZE__)
- return UnrollTailLoop<7>::exec(int(size), [=](int i) { dst[i] = (uchar)str[i]; });
+ if (size >= 4) {
+ // two overlapped loads & stores, of either 64-bit or of 32-bit
+ if (size >= 8) {
+ const __m128i unpacked1 = mm_load8_zero_extend(str);
+ const __m128i unpacked2 = mm_load8_zero_extend(str + size - 8);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), unpacked1);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + size - 8), unpacked2);
+ } else {
+ const __m128i chunk1 = _mm_cvtsi32_si128(qFromUnaligned<quint32>(str));
+ const __m128i chunk2 = _mm_cvtsi32_si128(qFromUnaligned<quint32>(str + size - 4));
+ const __m128i unpacked1 = _mm_unpacklo_epi8(chunk1, nullMask);
+ const __m128i unpacked2 = _mm_unpacklo_epi8(chunk2, nullMask);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(dst), unpacked1);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(dst + size - 4), unpacked2);
+ }
+ return;
+ } else {
+ size = size % 4;
+ return UnrollTailLoop<3>::exec(qsizetype(size), [=](qsizetype i) { dst[i] = uchar(str[i]); });
+ }
# endif
#endif
#if defined(__mips_dsp)
+ static_assert(sizeof(qsizetype) == sizeof(int),
+ "oops, the assembler implementation needs to be called in a loop");
if (size > 20)
qt_fromlatin1_mips_asm_unroll8(dst, str, size);
else
@@ -669,31 +992,51 @@ Q_CORE_EXPORT void qt_from_latin1(char16_t *dst, const char *str, size_t size) n
#endif
}
+static QVarLengthArray<char16_t> qt_from_latin1_to_qvla(QLatin1StringView str)
+{
+ const qsizetype len = str.size();
+ QVarLengthArray<char16_t> arr(len);
+ qt_from_latin1(arr.data(), str.data(), len);
+ return arr;
+}
+
template <bool Checked>
static void qt_to_latin1_internal(uchar *dst, const char16_t *src, qsizetype length)
{
#if defined(__SSE2__)
- uchar *e = dst + length;
- qptrdiff offset = 0;
-
-# ifdef __AVX2__
- const __m256i questionMark256 = _mm256_broadcastw_epi16(_mm_cvtsi32_si128('?'));
- const __m256i outOfRange256 = _mm256_broadcastw_epi16(_mm_cvtsi32_si128(0x100));
- const __m128i questionMark = _mm256_castsi256_si128(questionMark256);
- const __m128i outOfRange = _mm256_castsi256_si128(outOfRange256);
-# else
- const __m128i questionMark = _mm_set1_epi16('?');
- const __m128i outOfRange = _mm_set1_epi16(0x100);
-# endif
+ auto questionMark256 = []() {
+ if constexpr (UseAvx2)
+ return _mm256_broadcastw_epi16(_mm_cvtsi32_si128('?'));
+ else
+ return 0;
+ }();
+ auto outOfRange256 = []() {
+ if constexpr (UseAvx2)
+ return _mm256_broadcastw_epi16(_mm_cvtsi32_si128(0x100));
+ else
+ return 0;
+ }();
+ __m128i questionMark, outOfRange;
+ if constexpr (UseAvx2) {
+ questionMark = _mm256_castsi256_si128(questionMark256);
+ outOfRange = _mm256_castsi256_si128(outOfRange256);
+ } else {
+ questionMark = _mm_set1_epi16('?');
+ outOfRange = _mm_set1_epi16(0x100);
+ }
auto mergeQuestionMarks = [=](__m128i chunk) {
+ if (!Checked)
+ return chunk;
+
// SSE has no compare instruction for unsigned comparison.
-# ifdef __SSE4_1__
- // We use an unsigned uc = qMin(uc, 0x100) and then compare for equality.
- chunk = _mm_min_epu16(chunk, outOfRange);
- const __m128i offLimitMask = _mm_cmpeq_epi16(chunk, outOfRange);
- chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask);
-# else
+ if constexpr (UseSse4_1) {
+ // We use an unsigned uc = qMin(uc, 0x100) and then compare for equality.
+ chunk = _mm_min_epu16(chunk, outOfRange);
+ const __m128i offLimitMask = _mm_cmpeq_epi16(chunk, outOfRange);
+ chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask);
+ return chunk;
+ }
// The variables must be shiffted + 0x8000 to be compared
const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000));
const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000));
@@ -713,90 +1056,99 @@ static void qt_to_latin1_internal(uchar *dst, const char16_t *src, qsizetype len
chunk = _mm_or_si128(correctBytes, offLimitQuestionMark);
Q_UNUSED(outOfRange);
-# endif
return chunk;
};
- // we're going to write to dst[offset..offset+15] (16 bytes)
- for ( ; dst + offset + 15 < e; offset += 16) {
-# if defined(__AVX2__)
- __m256i chunk = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + offset));
- if (Checked) {
- // See mergeQuestionMarks lambda above for details
- chunk = _mm256_min_epu16(chunk, outOfRange256);
- const __m256i offLimitMask = _mm256_cmpeq_epi16(chunk, outOfRange256);
- chunk = _mm256_blendv_epi8(chunk, questionMark256, offLimitMask);
- }
+ // we're going to read to src[offset..offset+15] (16 bytes)
+ auto loadChunkAt = [=](qptrdiff offset) {
+ __m128i chunk1, chunk2;
+ if constexpr (UseAvx2) {
+ __m256i chunk = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + offset));
+ if (Checked) {
+ // See mergeQuestionMarks lambda above for details
+ chunk = _mm256_min_epu16(chunk, outOfRange256);
+ const __m256i offLimitMask = _mm256_cmpeq_epi16(chunk, outOfRange256);
+ chunk = _mm256_blendv_epi8(chunk, questionMark256, offLimitMask);
+ }
- const __m128i chunk2 = _mm256_extracti128_si256(chunk, 1);
- const __m128i chunk1 = _mm256_castsi256_si128(chunk);
-# else
- __m128i chunk1 = _mm_loadu_si128((const __m128i*)(src + offset)); // load
- if (Checked)
+ chunk2 = _mm256_extracti128_si256(chunk, 1);
+ chunk1 = _mm256_castsi256_si128(chunk);
+ } else {
+ chunk1 = _mm_loadu_si128((const __m128i*)(src + offset)); // load
chunk1 = mergeQuestionMarks(chunk1);
- __m128i chunk2 = _mm_loadu_si128((const __m128i*)(src + offset + 8)); // load
- if (Checked)
+ chunk2 = _mm_loadu_si128((const __m128i*)(src + offset + 8)); // load
chunk2 = mergeQuestionMarks(chunk2);
-# endif
+ }
// pack the two vector to 16 x 8bits elements
- const __m128i result = _mm_packus_epi16(chunk1, chunk2);
- _mm_storeu_si128((__m128i*)(dst + offset), result); // store
+ return _mm_packus_epi16(chunk1, chunk2);
+ };
+
+ if (size_t(length) >= sizeof(__m128i)) {
+ // because of possible overlapping, we won't process the last chunk in the loop
+ qptrdiff offset = 0;
+ for ( ; offset + 2 * sizeof(__m128i) < size_t(length); offset += sizeof(__m128i))
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + offset), loadChunkAt(offset));
+
+ // overlapped conversion of the last full chunk and the tail
+ __m128i last1 = loadChunkAt(offset);
+ __m128i last2 = loadChunkAt(length - sizeof(__m128i));
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + offset), last1);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + length - sizeof(__m128i)), last2);
+ return;
}
# if !defined(__OPTIMIZE_SIZE__)
- // we're going to write to dst[offset..offset+7] (8 bytes)
- if (dst + offset + 7 < e) {
- __m128i chunk = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + offset));
- if (Checked)
- chunk = mergeQuestionMarks(chunk);
-
- // pack, where the upper half is ignored
- const __m128i result = _mm_packus_epi16(chunk, chunk);
- _mm_storel_epi64(reinterpret_cast<__m128i *>(dst + offset), result);
- offset += 8;
- }
+ if (length >= 4) {
+ // this code is fine even for in-place conversion because we load both
+ // before any store
+ if (length >= 8) {
+ __m128i chunk1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src));
+ __m128i chunk2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + length - 8));
+ chunk1 = mergeQuestionMarks(chunk1);
+ chunk2 = mergeQuestionMarks(chunk2);
- // we're going to write to dst[offset..offset+3] (4 bytes)
- if (dst + offset + 3 < e) {
- __m128i chunk = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src + offset));
- if (Checked)
- chunk = mergeQuestionMarks(chunk);
+ // pack, where the upper half is ignored
+ const __m128i result1 = _mm_packus_epi16(chunk1, chunk1);
+ const __m128i result2 = _mm_packus_epi16(chunk2, chunk2);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(dst), result1);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(dst + length - 8), result2);
+ } else {
+ __m128i chunk1 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src));
+ __m128i chunk2 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src + length - 4));
+ chunk1 = mergeQuestionMarks(chunk1);
+ chunk2 = mergeQuestionMarks(chunk2);
- // pack, we'll the upper three quarters
- const __m128i result = _mm_packus_epi16(chunk, chunk);
- qToUnaligned(_mm_cvtsi128_si32(result), dst + offset);
- offset += 4;
+ // pack, we'll zero the upper three quarters
+ const __m128i result1 = _mm_packus_epi16(chunk1, chunk1);
+ const __m128i result2 = _mm_packus_epi16(chunk2, chunk2);
+ qToUnaligned(_mm_cvtsi128_si32(result1), dst);
+ qToUnaligned(_mm_cvtsi128_si32(result2), dst + length - 4);
+ }
+ return;
}
length = length % 4;
-# else
- length = length % 16;
-# endif // optimize size
-
- // advance dst, src for tail processing
- dst += offset;
- src += offset;
-
-# if !defined(__OPTIMIZE_SIZE__)
- return UnrollTailLoop<3>::exec(length, [=](int i) {
+ return UnrollTailLoop<3>::exec(length, [=](qsizetype i) {
if (Checked)
dst[i] = (src[i]>0xff) ? '?' : (uchar) src[i];
else
dst[i] = src[i];
});
-# endif
+# else
+ length = length % 16;
+# endif // optimize size
#elif defined(__ARM_NEON__)
- // Refer to the documentation of the SSE2 implementation
- // this use eactly the same method as for SSE except:
+ // Refer to the documentation of the SSE2 implementation.
+ // This uses exactly the same method as for SSE except:
// 1) neon has unsigned comparison
// 2) packing is done to 64 bits (8 x 8bits component).
if (length >= 16) {
- const int chunkCount = length >> 3; // divided by 8
+ const qsizetype chunkCount = length >> 3; // divided by 8
const uint16x8_t questionMark = vdupq_n_u16('?'); // set
const uint16x8_t thresholdMask = vdupq_n_u16(0xff); // set
- for (int i = 0; i < chunkCount; ++i) {
+ for (qsizetype i = 0; i < chunkCount; ++i) {
uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load
src += 8;
@@ -814,6 +1166,8 @@ static void qt_to_latin1_internal(uchar *dst, const char16_t *src, qsizetype len
}
#endif
#if defined(__mips_dsp)
+ static_assert(sizeof(qsizetype) == sizeof(int),
+ "oops, the assembler implementation needs to be called in a loop");
qt_toLatin1_mips_dsp_asm(dst, src, length);
#else
while (length--) {
@@ -826,7 +1180,7 @@ static void qt_to_latin1_internal(uchar *dst, const char16_t *src, qsizetype len
#endif
}
-static void qt_to_latin1(uchar *dst, const char16_t *src, qsizetype length)
+void qt_to_latin1(uchar *dst, const char16_t *src, qsizetype length)
{
qt_to_latin1_internal<true>(dst, src, length);
}
@@ -836,58 +1190,80 @@ void qt_to_latin1_unchecked(uchar *dst, const char16_t *src, qsizetype length)
qt_to_latin1_internal<false>(dst, src, length);
}
-// Unicode case-insensitive comparison
-static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QChar *be)
+// Unicode case-insensitive comparison (argument order matches QStringView)
+Q_NEVER_INLINE static int ucstricmp(qsizetype alen, const char16_t *a, qsizetype blen, const char16_t *b)
{
if (a == b)
- return (ae - be);
-
- const QChar *e = ae;
- if (be - b < ae - a)
- e = a + (be - b);
+ return qt_lencmp(alen, blen);
char32_t alast = 0;
char32_t blast = 0;
- while (a < e) {
+ qsizetype l = qMin(alen, blen);
+ qsizetype i;
+ for (i = 0; i < l; ++i) {
// qDebug() << Qt::hex << alast << blast;
// qDebug() << Qt::hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast);
// qDebug() << Qt::hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast);
- int diff = foldCase(a->unicode(), alast) - foldCase(b->unicode(), blast);
+ int diff = foldCase(a[i], alast) - foldCase(b[i], blast);
if ((diff))
return diff;
- ++a;
- ++b;
}
- if (a == ae) {
- if (b == be)
+ if (i == alen) {
+ if (i == blen)
return 0;
return -1;
}
return 1;
}
-// Case-insensitive comparison between a Unicode string and a QLatin1String
-static int ucstricmp(const QChar *a, const QChar *ae, const char *b, const char *be)
+// Case-insensitive comparison between a QStringView and a QLatin1StringView
+// (argument order matches those types)
+Q_NEVER_INLINE static int ucstricmp(qsizetype alen, const char16_t *a, qsizetype blen, const char *b)
{
- auto e = ae;
- if (be - b < ae - a)
- e = a + (be - b);
-
- while (a < e) {
- int diff = foldCase(a->unicode()) - foldCase(char16_t{uchar(*b)});
+ qsizetype l = qMin(alen, blen);
+ qsizetype i;
+ for (i = 0; i < l; ++i) {
+ int diff = foldCase(a[i]) - foldCase(char16_t{uchar(b[i])});
if ((diff))
return diff;
- ++a;
- ++b;
}
- if (a == ae) {
- if (b == be)
+ if (i == alen) {
+ if (i == blen)
return 0;
return -1;
}
return 1;
}
+// Case-insensitive comparison between a Unicode string and a UTF-8 string
+Q_NEVER_INLINE static int ucstricmp8(const char *utf8, const char *utf8end, const QChar *utf16, const QChar *utf16end)
+{
+ auto src1 = reinterpret_cast<const uchar *>(utf8);
+ auto end1 = reinterpret_cast<const uchar *>(utf8end);
+ QStringIterator src2(utf16, utf16end);
+
+ while (src1 < end1 && src2.hasNext()) {
+ char32_t uc1 = 0;
+ char32_t *output = &uc1;
+ uchar b = *src1++;
+ const qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src1, end1);
+ if (res < 0) {
+ // decoding error
+ uc1 = QChar::ReplacementCharacter;
+ } else {
+ uc1 = QChar::toCaseFolded(uc1);
+ }
+
+ char32_t uc2 = QChar::toCaseFolded(src2.next());
+ int diff = uc1 - uc2; // can't underflow
+ if (diff)
+ return diff;
+ }
+
+ // the shorter string sorts first
+ return (end1 > src1) - int(src2.hasNext());
+}
+
#if defined(__mips_dsp)
// From qstring_mips_dsp_asm.S
extern "C" int qt_ucstrncmp_mips_dsp_asm(const char16_t *a,
@@ -896,98 +1272,24 @@ extern "C" int qt_ucstrncmp_mips_dsp_asm(const char16_t *a,
#endif
// Unicode case-sensitive compare two same-sized strings
-static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
+template <StringComparisonMode Mode>
+static int ucstrncmp(const char16_t *a, const char16_t *b, size_t l)
{
-#ifdef __OPTIMIZE_SIZE__
- const QChar *end = a + l;
- while (a < end) {
- if (int diff = (int)a->unicode() - (int)b->unicode())
- return diff;
- ++a;
- ++b;
- }
- return 0;
-#else
-#if defined(__mips_dsp)
+ // This function isn't memcmp() because that can return the wrong sorting
+ // result in little-endian architectures: 0x00ff must sort before 0x0100,
+ // but the bytes in memory are FF 00 and 00 01.
+
+#ifndef __OPTIMIZE_SIZE__
+# if defined(__mips_dsp)
static_assert(sizeof(uint) == sizeof(size_t));
if (l >= 8) {
- return qt_ucstrncmp_mips_dsp_asm(reinterpret_cast<const char16_t*>(a),
- reinterpret_cast<const char16_t*>(b),
- l);
+ return qt_ucstrncmp_mips_dsp_asm(a, b, l);
}
-#endif // __mips_dsp
-#ifdef __SSE2__
- const QChar *end = a + l;
- qptrdiff offset = 0;
-
- // Using the PMOVMSKB instruction, we get two bits for each character
- // we compare.
- int retval;
- auto isDifferent = [a, b, &offset, &retval](__m128i a_data, __m128i b_data) {
- __m128i result = _mm_cmpeq_epi16(a_data, b_data);
- uint mask = ~uint(_mm_movemask_epi8(result));
- if (ushort(mask) == 0)
- return false;
- uint idx = qCountTrailingZeroBits(mask);
- retval = a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode();
- return true;
- };
-
- // we're going to read a[0..15] and b[0..15] (32 bytes)
- for ( ; end - a >= offset + 16; offset += 16) {
-#ifdef __AVX2__
- __m256i a_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(a + offset));
- __m256i b_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(b + offset));
- __m256i result = _mm256_cmpeq_epi16(a_data, b_data);
- uint mask = _mm256_movemask_epi8(result);
-#else
- __m128i a_data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(a + offset));
- __m128i a_data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(a + offset + 8));
- __m128i b_data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset));
- __m128i b_data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset + 8));
- __m128i result1 = _mm_cmpeq_epi16(a_data1, b_data1);
- __m128i result2 = _mm_cmpeq_epi16(a_data2, b_data2);
- uint mask = _mm_movemask_epi8(result1) | (_mm_movemask_epi8(result2) << 16);
-#endif
- mask = ~mask;
- if (mask) {
- // found a different character
- uint idx = qCountTrailingZeroBits(mask);
- return a[offset + idx / 2].unicode() - b[offset + idx / 2].unicode();
- }
- }
-
- // we're going to read a[0..7] and b[0..7] (16 bytes)
- if (end - a >= offset + 8) {
- __m128i a_data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(a + offset));
- __m128i b_data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset));
- if (isDifferent(a_data, b_data))
- return retval;
-
- offset += 8;
- }
-
- // we're going to read a[0..3] and b[0..3] (8 bytes)
- if (end - a >= offset + 4) {
- __m128i a_data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(a + offset));
- __m128i b_data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(b + offset));
- if (isDifferent(a_data, b_data))
- return retval;
-
- offset += 4;
- }
-
- // reset l
- l &= 3;
-
- const auto lambda = [=](size_t i) -> int {
- return a[offset + i].unicode() - b[offset + i].unicode();
- };
- return UnrollTailLoop<3>::exec(l, 0, lambda, lambda);
-#endif
-#if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
+# elif defined(__SSE2__)
+ return ucstrncmp_sse2<Mode>(a, b, l);
+# elif defined(__ARM_NEON__)
if (l >= 8) {
- const QChar *end = a + l;
+ const char16_t *end = a + l;
const uint16x8_t mask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
while (end - a > 7) {
uint16x8_t da = vld1q_u16(reinterpret_cast<const uint16_t *>(a));
@@ -996,8 +1298,10 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
uint8_t r = ~(uint8_t)vaddvq_u16(vandq_u16(vceqq_u16(da, db), mask));
if (r) {
// found a different QChar
+ if (Mode == CompareStringsForEquality)
+ return 1;
uint idx = qCountTrailingZeroBits(r);
- return (int)a[idx].unicode() - (int)b[idx].unicode();
+ return a[idx] - b[idx];
}
a += 8;
b += 8;
@@ -1005,156 +1309,31 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
l &= 7;
}
const auto lambda = [=](size_t i) -> int {
- return a[i].unicode() - b[i].unicode();
+ return a[i] - b[i];
};
return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
-#endif // __ARM_NEON__
- if (!l)
- return 0;
-
- // check alignment
- if ((reinterpret_cast<quintptr>(a) & 2) == (reinterpret_cast<quintptr>(b) & 2)) {
- // both addresses have the same alignment
- if (reinterpret_cast<quintptr>(a) & 2) {
- // both addresses are not aligned to 4-bytes boundaries
- // compare the first character
- if (*a != *b)
- return a->unicode() - b->unicode();
- --l;
- ++a;
- ++b;
-
- // now both addresses are 4-bytes aligned
- }
+# endif // MIPS DSP or __SSE2__ or __ARM_NEON__
+#endif // __OPTIMIZE_SIZE__
- // both addresses are 4-bytes aligned
- // do a fast 32-bit comparison
- const quint32 *da = reinterpret_cast<const quint32 *>(a);
- const quint32 *db = reinterpret_cast<const quint32 *>(b);
- const quint32 *e = da + (l >> 1);
- for ( ; da != e; ++da, ++db) {
- if (*da != *db) {
- a = reinterpret_cast<const QChar *>(da);
- b = reinterpret_cast<const QChar *>(db);
- if (*a != *b)
- return a->unicode() - b->unicode();
- return a[1].unicode() - b[1].unicode();
- }
- }
+ if (Mode == CompareStringsForEquality || QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ return memcmp(a, b, l * sizeof(char16_t));
- // do we have a tail?
- a = reinterpret_cast<const QChar *>(da);
- b = reinterpret_cast<const QChar *>(db);
- return (l & 1) ? a->unicode() - b->unicode() : 0;
- } else {
- // one of the addresses isn't 4-byte aligned but the other is
- const QChar *e = a + l;
- for ( ; a != e; ++a, ++b) {
- if (*a != *b)
- return a->unicode() - b->unicode();
- }
+ for (size_t i = 0; i < l; ++i) {
+ if (int diff = a[i] - b[i])
+ return diff;
}
return 0;
-#endif
}
-static int ucstrncmp(const QChar *a, const uchar *c, size_t l)
+template <StringComparisonMode Mode>
+static int ucstrncmp(const char16_t *a, const char *b, size_t l)
{
- const char16_t *uc = reinterpret_cast<const char16_t *>(a);
+ const uchar *c = reinterpret_cast<const uchar *>(b);
+ const char16_t *uc = a;
const char16_t *e = uc + l;
-#ifdef __SSE2__
- __m128i nullmask = _mm_setzero_si128();
- qptrdiff offset = 0;
-
-# if !defined(__OPTIMIZE_SIZE__)
- // Using the PMOVMSKB instruction, we get two bits for each character
- // we compare.
- int retval;
- auto isDifferent = [uc, c, &offset, &retval](__m128i a_data, __m128i b_data) {
- __m128i result = _mm_cmpeq_epi16(a_data, b_data);
- uint mask = ~uint(_mm_movemask_epi8(result));
- if (ushort(mask) == 0)
- return false;
- uint idx = qCountTrailingZeroBits(mask);
- retval = uc[offset + idx / 2] - c[offset + idx / 2];
- return true;
- };
-# endif
-
- // we're going to read uc[offset..offset+15] (32 bytes)
- // and c[offset..offset+15] (16 bytes)
- for ( ; uc + offset + 15 < e; offset += 16) {
- // similar to fromLatin1_helper:
- // load 16 bytes of Latin 1 data
- __m128i chunk = _mm_loadu_si128((const __m128i*)(c + offset));
-
-# ifdef __AVX2__
- // expand Latin 1 data via zero extension
- __m256i ldata = _mm256_cvtepu8_epi16(chunk);
-
- // load UTF-16 data and compare
- __m256i ucdata = _mm256_loadu_si256((const __m256i*)(uc + offset));
- __m256i result = _mm256_cmpeq_epi16(ldata, ucdata);
-
- uint mask = ~_mm256_movemask_epi8(result);
-# else
- // expand via unpacking
- __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullmask);
- __m128i secondHalf = _mm_unpackhi_epi8(chunk, nullmask);
-
- // load UTF-16 data and compare
- __m128i ucdata1 = _mm_loadu_si128((const __m128i*)(uc + offset));
- __m128i ucdata2 = _mm_loadu_si128((const __m128i*)(uc + offset + 8));
- __m128i result1 = _mm_cmpeq_epi16(firstHalf, ucdata1);
- __m128i result2 = _mm_cmpeq_epi16(secondHalf, ucdata2);
-
- uint mask = ~(_mm_movemask_epi8(result1) | _mm_movemask_epi8(result2) << 16);
-# endif
- if (mask) {
- // found a different character
- uint idx = qCountTrailingZeroBits(mask);
- return uc[offset + idx / 2] - c[offset + idx / 2];
- }
- }
-
-# if !defined(__OPTIMIZE_SIZE__)
- // we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes)
- if (uc + offset + 7 < e) {
- // same, but we're using an 8-byte load
- __m128i secondHalf = mm_load8_zero_extend(c + offset);
-
- __m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset));
- if (isDifferent(ucdata, secondHalf))
- return retval;
-
- // still matched
- offset += 8;
- }
-
- enum { MaxTailLength = 3 };
- // we'll read uc[offset..offset+3] (8 bytes) and c[offset..offset+3] (4 bytes)
- if (uc + offset + 3 < e) {
- __m128i chunk = _mm_cvtsi32_si128(qFromUnaligned<int>(c + offset));
- __m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
-
- __m128i ucdata = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(uc + offset));
- if (isDifferent(ucdata, secondHalf))
- return retval;
-
- // still matched
- offset += 4;
- }
-# endif // optimize size
-
- // reset uc and c
- uc += offset;
- c += offset;
-
-# if !defined(__OPTIMIZE_SIZE__)
- const auto lambda = [=](size_t i) { return uc[i] - char16_t(c[i]); };
- return UnrollTailLoop<MaxTailLength>::exec(e - uc, 0, lambda, lambda);
-# endif
+#if defined(__SSE2__) && !defined(__OPTIMIZE_SIZE__)
+ return ucstrncmp_sse2<Mode>(uc, c, l);
#endif
while (uc < e) {
@@ -1167,101 +1346,114 @@ static int ucstrncmp(const QChar *a, const uchar *c, size_t l)
return 0;
}
-template <typename Number>
-Q_DECL_CONSTEXPR int lencmp(Number lhs, Number rhs) noexcept
+// Unicode case-sensitive equality
+template <typename Char2>
+static bool ucstreq(const char16_t *a, size_t alen, const Char2 *b)
{
- return lhs == rhs ? 0 :
- lhs > rhs ? 1 :
- /* else */ -1 ;
+ if constexpr (std::is_same_v<decltype(a), decltype(b)>) {
+ if (a == b)
+ return true;
+ }
+ return ucstrncmp<CompareStringsForEquality>(a, b, alen) == 0;
}
// Unicode case-sensitive comparison
-static int ucstrcmp(const QChar *a, size_t alen, const QChar *b, size_t blen)
+template <typename Char2>
+static int ucstrcmp(const char16_t *a, size_t alen, const Char2 *b, size_t blen)
{
- if (a == b && alen == blen)
- return 0;
+ if constexpr (std::is_same_v<decltype(a), decltype(b)>) {
+ if (a == b && alen == blen)
+ return 0;
+ }
const size_t l = qMin(alen, blen);
- int cmp = ucstrncmp(a, b, l);
- return cmp ? cmp : lencmp(alen, blen);
+ int cmp = ucstrncmp<CompareStringsForOrdering>(a, b, l);
+ return cmp ? cmp : qt_lencmp(alen, blen);
}
-static int ucstrcmp(const QChar *a, size_t alen, const char *b, size_t blen)
+using CaseInsensitiveL1 = QtPrivate::QCaseInsensitiveLatin1Hash;
+
+static int latin1nicmp(const char *lhsChar, qsizetype lSize, const char *rhsChar, qsizetype rSize)
{
- const size_t l = qMin(alen, blen);
- const int cmp = ucstrncmp(a, reinterpret_cast<const uchar*>(b), l);
- return cmp ? cmp : lencmp(alen, blen);
-}
-
-static int latin1nicmp(const char *lhsChar, int lSize, const char *rhsChar, int rSize)
-{
- constexpr uchar latin1Lower[256] = {
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
- 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
- 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
- 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
- 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
- 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
- 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
- 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
- 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
- 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
- // 0xd7 (multiplication sign) and 0xdf (sz ligature) complicate life
- 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xd7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xdf,
- 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
- };
- // We're called with QLatin1String's .data() and .size():
+ // We're called with QLatin1StringView's .data() and .size():
Q_ASSERT(lSize >= 0 && rSize >= 0);
if (!lSize)
return rSize ? -1 : 0;
if (!rSize)
return 1;
- const int size = std::min(lSize, rSize);
-
- const uchar *lhs = reinterpret_cast<const uchar *>(lhsChar);
- const uchar *rhs = reinterpret_cast<const uchar *>(rhsChar);
- Q_ASSERT(lhs && rhs); // since both lSize and rSize are positive
- for (int i = 0; i < size; i++) {
- Q_ASSERT(lhs[i] && rhs[i]);
- if (int res = latin1Lower[lhs[i]] - latin1Lower[rhs[i]])
+ const qsizetype size = std::min(lSize, rSize);
+
+ Q_ASSERT(lhsChar && rhsChar); // since both lSize and rSize are positive
+ for (qsizetype i = 0; i < size; i++) {
+ if (int res = CaseInsensitiveL1::difference(lhsChar[i], rhsChar[i]))
return res;
}
- return lencmp(lSize, rSize);
+ return qt_lencmp(lSize, rSize);
}
-static int qt_compare_strings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::equalStrings(QStringView lhs, QStringView rhs) noexcept
{
- if (cs == Qt::CaseSensitive)
- return ucstrcmp(lhs.begin(), lhs.size(), rhs.begin(), rhs.size());
- else
- return ucstricmp(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+ Q_ASSERT(lhs.size() == rhs.size());
+ return ucstreq(lhs.utf16(), lhs.size(), rhs.utf16());
}
-static int qt_compare_strings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::equalStrings(QStringView lhs, QLatin1StringView rhs) noexcept
{
- if (cs == Qt::CaseSensitive)
- return ucstrcmp(lhs.begin(), lhs.size(), rhs.begin(), rhs.size());
- else
- return ucstricmp(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+ Q_ASSERT(lhs.size() == rhs.size());
+ return ucstreq(lhs.utf16(), lhs.size(), rhs.latin1());
}
-static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::equalStrings(QLatin1StringView lhs, QStringView rhs) noexcept
{
- return -qt_compare_strings(rhs, lhs, cs);
+ return QtPrivate::equalStrings(rhs, lhs);
}
-static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::equalStrings(QLatin1StringView lhs, QLatin1StringView rhs) noexcept
{
- if (lhs.isEmpty())
- return lencmp(0, rhs.size());
- if (cs == Qt::CaseInsensitive)
- return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
- const auto l = std::min(lhs.size(), rhs.size());
- int r = qstrncmp(lhs.data(), rhs.data(), l);
- return r ? r : lencmp(lhs.size(), rhs.size());
+ Q_ASSERT(lhs.size() == rhs.size());
+ return (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
+}
+
+bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QStringView rhs) noexcept
+{
+ return QUtf8::compareUtf8(lhs, rhs) == 0;
+}
+
+bool QtPrivate::equalStrings(QStringView lhs, QBasicUtf8StringView<false> rhs) noexcept
+{
+ return QtPrivate::equalStrings(rhs, lhs);
+}
+
+bool QtPrivate::equalStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs) noexcept
+{
+ return QUtf8::compareUtf8(QByteArrayView(rhs), lhs) == 0;
+}
+
+bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView rhs) noexcept
+{
+ return QtPrivate::equalStrings(rhs, lhs);
+}
+
+bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs) noexcept
+{
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC)
+ Q_ASSERT(lhs.size() == rhs.size());
+#else
+ // operator== didn't enforce size prior to Qt 6.2
+ if (lhs.size() != rhs.size())
+ return false;
+#endif
+ return (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
+}
+
+bool QAnyStringView::equal(QAnyStringView lhs, QAnyStringView rhs) noexcept
+{
+ if (lhs.size() != rhs.size() && lhs.isUtf8() == rhs.isUtf8())
+ return false;
+ return lhs.visit([rhs](auto lhs) {
+ return rhs.visit([lhs](auto rhs) {
+ return QtPrivate::equalStrings(lhs, rhs);
+ });
+ });
}
/*!
@@ -1271,16 +1463,19 @@ static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSens
Returns an integer that compares to 0 as \a lhs compares to \a rhs.
- If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
- otherwise the comparison is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
Case-sensitive comparison is based exclusively on the numeric Unicode values
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
+
+ \sa {Comparing Strings}
*/
int QtPrivate::compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
{
- return qt_compare_strings(lhs, rhs, cs);
+ if (cs == Qt::CaseSensitive)
+ return ucstrcmp(lhs.utf16(), lhs.size(), rhs.utf16(), rhs.size());
+ return ucstricmp(lhs.size(), lhs.utf16(), rhs.size(), rhs.utf16());
}
/*!
@@ -1291,36 +1486,41 @@ int QtPrivate::compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitiv
Returns an integer that compares to 0 as \a lhs compares to \a rhs.
- If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
- otherwise the comparison is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
Case-sensitive comparison is based exclusively on the numeric Unicode values
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
+
+ \sa {Comparing Strings}
*/
-int QtPrivate::compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
+int QtPrivate::compareStrings(QStringView lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs) noexcept
{
- return qt_compare_strings(lhs, rhs, cs);
+ if (cs == Qt::CaseSensitive)
+ return ucstrcmp(lhs.utf16(), lhs.size(), rhs.latin1(), rhs.size());
+ return ucstricmp(lhs.size(), lhs.utf16(), rhs.size(), rhs.latin1());
}
/*!
\relates QStringView
\internal
- \since 5.10
+ \since 6.0
\overload
+*/
+int QtPrivate::compareStrings(QStringView lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs) noexcept
+{
+ return -compareStrings(rhs, lhs, cs);
+}
- Returns an integer that compares to 0 as \a lhs compares to \a rhs.
-
- If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
- otherwise the comparison is case-insensitive.
-
- Case-sensitive comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would expect.
- Consider sorting user-visible strings with QString::localeAwareCompare().
+/*!
+ \relates QStringView
+ \internal
+ \since 5.10
+ \overload
*/
-int QtPrivate::compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
+int QtPrivate::compareStrings(QLatin1StringView lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
{
- return qt_compare_strings(lhs, rhs, cs);
+ return -compareStrings(rhs, lhs, cs);
}
/*!
@@ -1331,53 +1531,130 @@ int QtPrivate::compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensit
Returns an integer that compares to 0 as \a lhs compares to \a rhs.
- If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
- otherwise the comparison is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
Case-sensitive comparison is based exclusively on the numeric Latin-1 values
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
+
+ \sa {Comparing Strings}
*/
-int QtPrivate::compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
+int QtPrivate::compareStrings(QLatin1StringView lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs) noexcept
{
- return qt_compare_strings(lhs, rhs, cs);
+ if (lhs.isEmpty())
+ return qt_lencmp(qsizetype(0), rhs.size());
+ if (cs == Qt::CaseInsensitive)
+ return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
+ const auto l = std::min(lhs.size(), rhs.size());
+ int r = memcmp(lhs.data(), rhs.data(), l);
+ return r ? r : qt_lencmp(lhs.size(), rhs.size());
}
-#define REHASH(a) \
- if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << sl_minus_1; \
- hashHaystack <<= 1
+/*!
+ \relates QStringView
+ \internal
+ \since 6.0
+ \overload
+*/
+int QtPrivate::compareStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs) noexcept
+{
+ return -QUtf8::compareUtf8(QByteArrayView(rhs), lhs, cs);
+}
+
+/*!
+ \relates QStringView
+ \internal
+ \since 6.0
+ \overload
+*/
+int QtPrivate::compareStrings(QBasicUtf8StringView<false> lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
+{
+ if (cs == Qt::CaseSensitive)
+ return QUtf8::compareUtf8(lhs, rhs);
+ return ucstricmp8(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
-inline bool qIsUpper(char ch)
+/*!
+ \relates QStringView
+ \internal
+ \since 6.0
+ \overload
+*/
+int QtPrivate::compareStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs) noexcept
{
- return ch >= 'A' && ch <= 'Z';
+ return -compareStrings(rhs, lhs, cs);
}
-inline bool qIsDigit(char ch)
+/*!
+ \relates QStringView
+ \internal
+ \since 6.0
+ \overload
+*/
+int QtPrivate::compareStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs) noexcept
{
- return ch >= '0' && ch <= '9';
+ return QUtf8::compareUtf8(QByteArrayView(lhs), QByteArrayView(rhs), cs);
}
-inline char qToLower(char ch)
+int QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs) noexcept
{
- if (ch >= 'A' && ch <= 'Z')
- return ch - 'A' + 'a';
- else
- return ch;
+ return lhs.visit([rhs, cs](auto lhs) {
+ return rhs.visit([lhs, cs](auto rhs) {
+ return QtPrivate::compareStrings(lhs, rhs, cs);
+ });
+ });
}
+// ### Qt 7: do not allow anything but ASCII digits
+// in arg()'s replacements.
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+static bool supportUnicodeDigitValuesInArg()
+{
+ static const bool result = []() {
+ static const char supportUnicodeDigitValuesEnvVar[]
+ = "QT_USE_UNICODE_DIGIT_VALUES_IN_STRING_ARG";
+
+ if (qEnvironmentVariableIsSet(supportUnicodeDigitValuesEnvVar))
+ return qEnvironmentVariableIntValue(supportUnicodeDigitValuesEnvVar) != 0;
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) // keep it in sync with the test
+ return true;
+#else
+ return false;
+#endif
+ }();
+
+ return result;
+}
+#endif
+
+static int qArgDigitValue(QChar ch) noexcept
+{
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ if (supportUnicodeDigitValuesInArg())
+ return ch.digitValue();
+#endif
+ if (ch >= u'0' && ch <= u'9')
+ return int(ch.unicode() - u'0');
+ return -1;
+}
+
+#if QT_CONFIG(regularexpression)
+Q_DECL_COLD_FUNCTION
+void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *where);
+#endif
/*!
\macro QT_RESTRICTED_CAST_FROM_ASCII
\relates QString
- Defining this macro disables most automatic conversions from source
- literals and 8-bit data to unicode QStrings, but allows the use of
+ Disables most automatic conversions from source literals and 8-bit data
+ to unicode QStrings, but allows the use of
the \c{QChar(char)} and \c{QString(const char (&ch)[N]} constructors,
- and the \c{QString::operator=(const char (&ch)[N])} assignment operator
- giving most of the type-safety benefits of \c QT_NO_CAST_FROM_ASCII
+ and the \c{QString::operator=(const char (&ch)[N])} assignment operator.
+ This gives most of the type-safety benefits of \l QT_NO_CAST_FROM_ASCII
but does not require user code to wrap character and string literals
- with QLatin1Char, QLatin1String or similar.
+ with QLatin1Char, QLatin1StringView or similar.
Using this macro together with source strings outside the 7-bit range,
non-literals, or literals with embedded NUL characters is undefined.
@@ -1388,19 +1665,24 @@ inline char qToLower(char ch)
/*!
\macro QT_NO_CAST_FROM_ASCII
\relates QString
+ \relates QChar
- Disables automatic conversions from 8-bit strings (char *) to unicode QStrings
+ Disables automatic conversions from 8-bit strings (\c{char *}) to Unicode
+ QStrings, as well as from 8-bit \c{char} types (\c{char} and
+ \c{unsigned char}) to QChar.
- \sa QT_NO_CAST_TO_ASCII, QT_RESTRICTED_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY
+ \sa QT_NO_CAST_TO_ASCII, QT_RESTRICTED_CAST_FROM_ASCII,
+ QT_NO_CAST_FROM_BYTEARRAY
*/
/*!
\macro QT_NO_CAST_TO_ASCII
\relates QString
- disables automatic conversion from QString to 8-bit strings (char *)
+ Disables automatic conversion from QString to 8-bit strings (\c{char *}).
- \sa QT_NO_CAST_FROM_ASCII, QT_RESTRICTED_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY
+ \sa QT_NO_CAST_FROM_ASCII, QT_RESTRICTED_CAST_FROM_ASCII,
+ QT_NO_CAST_FROM_BYTEARRAY
*/
/*!
@@ -1428,10 +1710,18 @@ inline char qToLower(char ch)
\ingroup shared
\ingroup string-processing
+ \compares strong
+ \compareswith strong QChar QLatin1StringView {const char16_t *} \
+ QStringView QUtf8StringView
+ \endcompareswith
+ \compareswith strong QByteArray QByteArrayView {const char *}
+ When comparing with byte arrays, their content is interpreted as utf-8.
+ \endcompareswith
+
QString stores a string of 16-bit \l{QChar}s, where each QChar
corresponds to one UTF-16 code unit. (Unicode characters
with code values above 65535 are stored using surrogate pairs,
- i.e., two consecutive \l{QChar}s.)
+ that is, two consecutive \l{QChar}s.)
\l{Unicode} is an international standard that supports most of the
writing systems in use today. It is a superset of US-ASCII (ANSI
@@ -1447,17 +1737,15 @@ inline char qToLower(char ch)
store raw bytes and traditional 8-bit '\\0'-terminated strings.
For most purposes, QString is the class you want to use. It is
used throughout the Qt API, and the Unicode support ensures that
- your applications will be easy to translate if you want to expand
- your application's market at some point. The two main cases where
- QByteArray is appropriate are when you need to store raw binary
- data, and when memory conservation is critical (like in embedded
- systems).
-
- \tableofcontents
+ your applications are easy to translate if you want to expand
+ your application's market at some point. Two prominent cases
+ where QByteArray is appropriate are when you need to store raw
+ binary data, and when memory conservation is critical (like in
+ embedded systems).
- \section1 Initializing a String
+ \section1 Initializing a string
- One way to initialize a QString is simply to pass a \c{const char
+ One way to initialize a QString is to pass a \c{const char
*} to its constructor. For example, the following code creates a
QString of size 5 containing the data "Hello":
@@ -1468,23 +1756,24 @@ inline char qToLower(char ch)
In all of the QString functions that take \c{const char *}
parameters, the \c{const char *} is interpreted as a classic
- C-style '\\0'-terminated string encoded in UTF-8. It is legal for
- the \c{const char *} parameter to be \nullptr.
+ C-style \c{'\\0'}-terminated string. Except where the function's
+ name overtly indicates some other encoding, such \c{const char *}
+ parameters are assumed to be encoded in UTF-8.
You can also provide string data as an array of \l{QChar}s:
\snippet qstring/main.cpp 1
QString makes a deep copy of the QChar data, so you can modify it
- later without experiencing side effects. (If for performance
- reasons you don't want to take a deep copy of the character data,
- use QString::fromRawData() instead.)
+ later without experiencing side effects. You can avoid taking a
+ deep copy of the character data by using QStringView or
+ QString::fromRawData() instead.
Another approach is to set the size of the string using resize()
and to initialize the data character per character. QString uses
0-based indexes, just like C++ arrays. To access the character at
a particular index position, you can use \l operator[](). On
- non-const strings, \l operator[]() returns a reference to a
+ non-\c{const} strings, \l operator[]() returns a reference to a
character that can be used on the left side of an assignment. For
example:
@@ -1495,9 +1784,9 @@ inline char qToLower(char ch)
\snippet qstring/main.cpp 3
- The at() function can be faster than \l operator[](), because it
+ The at() function can be faster than \l operator[]() because it
never causes a \l{deep copy} to occur. Alternatively, use the
- left(), right(), or mid() functions to extract several characters
+ first(), last(), or sliced() functions to extract several characters
at a time.
A QString can embed '\\0' characters (QChar::Null). The size()
@@ -1517,11 +1806,11 @@ inline char qToLower(char ch)
You can also pass string literals to functions that take QStrings
as arguments, invoking the QString(const char *)
constructor. Similarly, you can pass a QString to a function that
- takes a \c{const char *} argument using the \l qPrintable() macro
+ takes a \c{const char *} argument using the \l qPrintable() macro,
which returns the given QString as a \c{const char *}. This is
equivalent to calling <QString>.toLocal8Bit().constData().
- \section1 Manipulating String Data
+ \section1 Manipulating string data
QString provides the following basic functions for modifying the
character data: append(), prepend(), insert(), replace(), and
@@ -1529,32 +1818,62 @@ inline char qToLower(char ch)
\snippet qstring/main.cpp 5
+ In the above example, the replace() function's first two arguments are the
+ position from which to start replacing and the number of characters that
+ should be replaced.
+
+ When data-modifying functions increase the size of the string,
+ QString may reallocate the memory in which it holds its data. When
+ this happens, QString expands by more than it immediately needs so as
+ to have space for further expansion without reallocation until the size
+ of the string has significantly increased.
+
+ The insert(), remove(), and, when replacing a sub-string with one of
+ different size, replace() functions can be slow (\l{linear time}) for
+ large strings because they require moving many characters in the string
+ by at least one position in memory.
+
If you are building a QString gradually and know in advance
approximately how many characters the QString will contain, you
can call reserve(), asking QString to preallocate a certain amount
of memory. You can also call capacity() to find out how much
- memory QString actually allocated.
-
- The replace() and remove() functions' first two arguments are the
- position from which to start erasing and the number of characters
- that should be erased. If you want to replace all occurrences of
- a particular substring with another, use one of the two-parameter
- replace() overloads.
-
- A frequent requirement is to remove whitespace characters from a
- string ('\\n', '\\t', ' ', etc.). If you want to remove whitespace
- from both ends of a QString, use the trimmed() function. If you
- want to remove whitespace from both ends and replace multiple
- consecutive whitespaces with a single space character within the
- string, use simplified().
+ memory the QString actually has allocated.
+
+ QString provides \l{STL-style iterators} (QString::const_iterator and
+ QString::iterator). In practice, iterators are handy when working with
+ generic algorithms provided by the C++ standard library.
+
+ \note Iterators over a QString, and references to individual characters
+ within one, cannot be relied on to remain valid when any non-\c{const}
+ method of the QString is called. Accessing such an iterator or reference
+ after the call to a non-\c{const} method leads to undefined behavior. When
+ stability for iterator-like functionality is required, you should use
+ indexes instead of iterators, as they are not tied to QString's internal
+ state and thus do not get invalidated.
+
+ \note Due to \l{implicit sharing}, the first non-\c{const} operator or
+ function used on a given QString may cause it to internally perform a deep
+ copy of its data. This invalidates all iterators over the string and
+ references to individual characters within it. Do not call non-const
+ functions while keeping iterators. Accessing an iterator or reference
+ after it has been invalidated leads to undefined behavior. See the
+ \l{Implicit sharing iterator problem} section for more information.
+
+ A frequent requirement is to remove or simplify the spacing between
+ visible characters in a string. The characters that make up that spacing
+ are those for which \l {QChar::}{isSpace()} returns \c true, such as
+ the simple space \c{' '}, the horizontal tab \c{'\\t'} and the newline \c{'\\n'}.
+ To obtain a copy of a string leaving out any spacing from its start and end,
+ use \l trimmed(). To also replace each sequence of spacing characters within
+ the string with a simple space, \c{' '}, use \l simplified().
If you want to find all occurrences of a particular character or
substring in a QString, use the indexOf() or lastIndexOf()
- functions. The former searches forward starting from a given index
- position, the latter searches backward. Both return the index
- position of the character or substring if they find it; otherwise,
- they return -1. For example, here is a typical loop that finds all
- occurrences of a particular substring:
+ functions.The former searches forward, the latter searches backward.
+ Either can be told an index position from which to start their search.
+ Each returns the index position of the character or substring if they
+ find it; otherwise, they return -1. For example, here is a typical loop
+ that finds all occurrences of a particular substring:
\snippet qstring/main.cpp 6
@@ -1563,41 +1882,57 @@ inline char qToLower(char ch)
setNum() functions, the number() static functions, and the
toInt(), toDouble(), and similar functions.
- To get an upper- or lowercase version of a string use toUpper() or
+ To get an uppercase or lowercase version of a string, use toUpper() or
toLower().
Lists of strings are handled by the QStringList class. You can
split a string into a list of strings using the split() function,
and join a list of strings into a single string with an optional
- separator using QStringList::join(). You can obtain a list of
- strings from a string list that contain a particular substring or
- that match a particular QRegularExpression using the QStringList::filter()
- function.
+ separator using QStringList::join(). You can obtain a filtered list
+ from a string list by selecting the entries in it that contain a
+ particular substring or match a particular QRegularExpression.
+ See QStringList::filter() for details.
- \section1 Querying String Data
+ \section1 Querying string data
- If you want to see if a QString starts or ends with a particular
- substring use startsWith() or endsWith(). If you simply want to
- check whether a QString contains a particular character or
- substring, use the contains() function. If you want to find out
- how many times a particular character or substring occurs in the
- string, use count().
-
- QStrings can be compared using overloaded operators such as \l
- operator<(), \l operator<=(), \l operator==(), \l operator>=(),
- and so on. Note that the comparison is based exclusively on the
- numeric Unicode values of the characters. It is very fast, but is
- not what a human would expect; the QString::localeAwareCompare()
- function is a better choice for sorting user-interface strings.
+ To see if a QString starts or ends with a particular substring, use
+ startsWith() or endsWith(). To check whether a QString contains a
+ specific character or substring, use the contains() function. To
+ find out how many times a particular character or substring occurs
+ in a string, use count().
To obtain a pointer to the actual character data, call data() or
constData(). These functions return a pointer to the beginning of
the QChar data. The pointer is guaranteed to remain valid until a
- non-const function is called on the QString.
+ non-\c{const} function is called on the QString.
+
+ \section2 Comparing strings
+
+ QStrings can be compared using overloaded operators such as \l
+ operator<(), \l operator<=(), \l operator==(), \l operator>=(),
+ and so on. The comparison is based exclusively on the lexicographical
+ order of the two strings, seen as sequences of UTF-16 code units.
+ It is very fast but is not what a human would expect; the
+ QString::localeAwareCompare() function is usually a better choice for
+ sorting user-interface strings, when such a comparison is available.
+
+ When Qt is linked with the ICU library (which it usually is), its
+ locale-aware sorting is used. Otherwise, platform-specific solutions
+ are used:
+ \list
+ \li On Windows, localeAwareCompare() uses the current user locale,
+ as set in the \uicontrol{regional} and \uicontrol{language}
+ options portion of \uicontrol{Control Panel}.
+ \li On \macos and iOS, \l localeAwareCompare() compares according
+ to the \uicontrol{Order for sorted lists} setting in the
+ \uicontrol{International preferences} panel.
+ \li On other Unix-like systems, the comparison falls back to the
+ system library's \c strcoll().
+ \endlist
- \section1 Converting Between encoded strings data and QString
+ \section1 Converting between encoded string data and QString
- QString provides the following three functions that return a
+ QString provides the following functions that return a
\c{const char *} version of the string as QByteArray: toUtf8(),
toLatin1(), and toLocal8Bit().
@@ -1622,26 +1957,21 @@ inline char qToLower(char ch)
Latin-1, but there is always the risk that an implicit conversion
from or to \c{const char *} is done using the wrong 8-bit
encoding. To minimize these risks, you can turn off these implicit
- conversions by defining the following two preprocessor symbols:
+ conversions by defining some of the following preprocessor symbols:
\list
- \li \c QT_NO_CAST_FROM_ASCII disables automatic conversions from
+ \li \l QT_NO_CAST_FROM_ASCII disables automatic conversions from
C string literals and pointers to Unicode.
- \li \c QT_RESTRICTED_CAST_FROM_ASCII allows automatic conversions
- from C characters and character arrays, but disables automatic
+ \li \l QT_RESTRICTED_CAST_FROM_ASCII allows automatic conversions
+ from C characters and character arrays but disables automatic
conversions from character pointers to Unicode.
- \li \c QT_NO_CAST_TO_ASCII disables automatic conversion from QString
+ \li \l QT_NO_CAST_TO_ASCII disables automatic conversion from QString
to C strings.
\endlist
- One way to define these preprocessor symbols globally for your
- application is to add the following entry to your \l {Creating Project Files}{qmake project file}:
-
- \snippet code/src_corelib_text_qstring.cpp 0
-
You then need to explicitly call fromUtf8(), fromLatin1(),
or fromLocal8Bit() to construct a QString from an
- 8-bit string, or use the lightweight QLatin1String class, for
+ 8-bit string, or use the lightweight QLatin1StringView class. For
example:
\snippet code/src_corelib_text_qstring.cpp 1
@@ -1662,7 +1992,7 @@ inline char qToLower(char ch)
\snippet qstring/main.cpp 7
- The \c result variable, is a normal variable allocated on the
+ The \c result variable is a normal variable allocated on the
stack. When \c return is called, and because we're returning by
value, the copy constructor is called and a copy of the string is
returned. No actual copying takes place thanks to the implicit
@@ -1670,12 +2000,12 @@ inline char qToLower(char ch)
\endtable
- \section1 Distinction Between Null and Empty Strings
+ \section1 Distinction between null and empty strings
- For historical reasons, QString distinguishes between a null
- string and an empty string. A \e null string is a string that is
+ For historical reasons, QString distinguishes between null
+ and empty strings. A \e null string is a string that is
initialized using QString's default constructor or by passing
- (const char *)0 to the constructor. An \e empty string is any
+ \nullptr to the constructor. An \e empty string is any
string with size 0. A null string is always empty, but an empty
string isn't necessarily null:
@@ -1683,43 +2013,46 @@ inline char qToLower(char ch)
All functions except isNull() treat null strings the same as empty
strings. For example, toUtf8().constData() returns a valid pointer
- (\e not nullptr) to a '\\0' character for a null string. We
+ (not \nullptr) to a '\\0' character for a null string. We
recommend that you always use the isEmpty() function and avoid isNull().
- \section1 Argument Formats
+ \section1 Number formats
- In member functions where an argument \e format can be specified
- (e.g., arg(), number()), the argument \e format can be one of the
- following:
+ When a QString::arg() \c{'%'} format specifier includes the \c{'L'} locale
+ qualifier, and the base is ten (its default), the default locale is
+ used. This can be set using \l{QLocale::setDefault()}. For more refined
+ control of localized string representations of numbers, see
+ QLocale::toString(). All other number formatting done by QString follows the
+ C locale's representation of numbers.
- \table
- \header \li Format \li Meaning
- \row \li \c e \li format as [-]9.9e[+|-]999
- \row \li \c E \li format as [-]9.9E[+|-]999
- \row \li \c f \li format as [-]9.9
- \row \li \c g \li use \c e or \c f format, whichever is the most concise
- \row \li \c G \li use \c E or \c f format, whichever is the most concise
- \endtable
+ When QString::arg() applies left-padding to numbers, the fill character
+ \c{'0'} is treated specially. If the number is negative, its minus sign
+ appears before the zero-padding. If the field is localized, the
+ locale-appropriate zero character is used in place of \c{'0'}. For
+ floating-point numbers, this special treatment only applies if the number is
+ finite.
- A \e precision is also specified with the argument \e format. For
- the 'e', 'E', and 'f' formats, the \e precision represents the
- number of digits \e after the decimal point. For the 'g' and 'G'
- formats, the \e precision represents the maximum number of
- significant digits (trailing zeroes are omitted).
+ \section2 Floating-point formats
- \section1 More Efficient String Construction
+ In member functions (for example, arg() and number()) that format floating-point
+ numbers (\c float or \c double) as strings, the representation used can be
+ controlled by a choice of \e format and \e precision, whose meanings are as
+ for \l {QLocale::toString(double, char, int)}.
- Many strings are known at compile time. But the trivial
- constructor QString("Hello"), will copy the contents of the string,
- treating the contents as Latin-1. To avoid this one can use the
- QStringLiteral macro to directly create the required data at compile
- time. Constructing a QString out of the literal does then not cause
- any overhead at runtime.
+ If the selected \e format includes an exponent, localized forms follow the
+ locale's convention on digits in the exponent. For non-localized formatting,
+ the exponent shows its sign and includes at least two digits, left-padding
+ with zero if needed.
- A slightly less efficient way is to use QLatin1String. This class wraps
- a C string literal, precalculates it length at compile time and can
- then be used for faster comparison with QStrings and conversion to
- QStrings than a regular C string literal.
+ \section1 More efficient string construction
+
+ Many strings are known at compile time. The QString constructor from
+ C++ string literals will copy the contents of the string,
+ treating the contents as UTF-8. This requires memory allocation and
+ re-encoding string data, operations that will happen at runtime.
+ If the string data is known at compile time, you can use the QStringLiteral
+ macro or similarly \c{operator""_s} to create QString's payload at compile
+ time instead.
Using the QString \c{'+'} operator, it is easy to construct a
complex string from multiple substrings. You will often write code
@@ -1728,16 +2061,15 @@ inline char qToLower(char ch)
\snippet qstring/stringbuilder.cpp 0
There is nothing wrong with either of these string constructions,
- but there are a few hidden inefficiencies. Beginning with Qt 4.6,
- you can eliminate them.
+ but there are a few hidden inefficiencies:
- First, multiple uses of the \c{'+'} operator usually means
+ First, repeated use of the \c{'+'} operator may lead to
multiple memory allocations. When concatenating \e{n} substrings,
where \e{n > 2}, there can be as many as \e{n - 1} calls to the
memory allocator.
- In 4.6, an internal template class \c{QStringBuilder} has been
- added along with a few helper functions. This class is marked
+ These allocations can be optimized by an internal class
+ \c{QStringBuilder}. This class is marked
internal and does not appear in the documentation, because you
aren't meant to instantiate it in your code. Its use will be
automatic, as described below. The class is found in
@@ -1753,61 +2085,59 @@ inline char qToLower(char ch)
then called \e{once} to get the required space, and the substrings
are copied into it one by one.
- Additional efficiency is gained by inlining and reduced reference
- counting (the QString created from a \c{QStringBuilder} typically
+ Additional efficiency is gained by inlining and reducing reference
+ counting (the QString created from a \c{QStringBuilder}
has a ref count of 1, whereas QString::append() needs an extra
test).
There are two ways you can access this improved method of string
construction. The straightforward way is to include
- \c{QStringBuilder} wherever you want to use it, and use the
+ \c{QStringBuilder} wherever you want to use it and use the
\c{'%'} operator instead of \c{'+'} when concatenating strings:
\snippet qstring/stringbuilder.cpp 5
- A more global approach which is the most convenient but
- not entirely source compatible, is to this define in your
- .pro file:
-
- \snippet qstring/stringbuilder.cpp 3
-
- and the \c{'+'} will automatically be performed as the
- \c{QStringBuilder} \c{'%'} everywhere.
-
- \section1 Maximum size and out-of-memory conditions
+ A more global approach, which is more convenient but not entirely
+ source-compatible, is to define \c QT_USE_QSTRINGBUILDER (by adding
+ it to the compiler flags) at build time. This will make concatenating
+ strings with \c{'+'} work the same way as \c{QStringBuilder's} \c{'%'}.
- The current version of QString is limited to just under 2 GB (2^31 bytes)
- in size. The exact value is architecture-dependent, since it depends on the
- overhead required for managing the data block, but is no more than 32
- bytes. Raw data blocks are also limited by the use of \c int type in the
- current version to 2 GB minus 1 byte. Since QString uses two bytes per
- character, that translates to just under 2^30 characters in one QString.
+ \note Using automatic type deduction (for example, by using the \c
+ auto keyword) with the result of string concatenation when QStringBuilder
+ is enabled will show that the concatenation is indeed an object of a
+ QStringBuilder specialization:
- In case memory allocation fails, QString will throw a \c std::bad_alloc
- exception. Out of memory conditions in the Qt containers are the only case
- where Qt will throw exceptions.
+ \snippet qstring/stringbuilder.cpp 6
- Note that the operating system may impose further limits on applications
- holding a lot of allocated memory, especially large, contiguous blocks.
- Such considerations, the configuration of such behavior or any mitigation
- are outside the scope of the Qt API.
+ This does not cause any harm, as QStringBuilder will implicitly convert to
+ QString when required. If this is undesirable, then one should specify
+ the necessary types instead of having the compiler deduce them:
- \sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef
-*/
+ \snippet qstring/stringbuilder.cpp 7
-/*!
- \enum QString::SplitBehavior
+ \section1 Maximum size and out-of-memory conditions
- \obsolete
- Use Qt::SplitBehavior instead.
+ The maximum size of QString depends on the architecture. Most 64-bit
+ systems can allocate more than 2 GB of memory, with a typical limit
+ of 2^63 bytes. The actual value also depends on the overhead required for
+ managing the data block. As a result, you can expect a maximum size
+ of 2 GB minus overhead on 32-bit platforms and 2^63 bytes minus overhead
+ on 64-bit platforms. The number of elements that can be stored in a
+ QString is this maximum size divided by the size of QChar.
- This enum specifies how the split() function should behave with
- respect to empty strings.
+ When memory allocation fails, QString throws a \c std::bad_alloc
+ exception if the application was compiled with exception support.
+ Out-of-memory conditions in Qt containers are the only cases where Qt
+ will throw exceptions. If exceptions are disabled, then running out of
+ memory is undefined behavior.
- \value KeepEmptyParts If a field is empty, keep it in the result.
- \value SkipEmptyParts If a field is empty, don't include it in the result.
+ \note Target operating systems may impose limits on how much memory an
+ application can allocate, in total, or on the size of individual allocations.
+ This may further restrict the size of string a QString can hold.
+ Mitigating or controlling the behavior these limits cause is beyond the
+ scope of the Qt API.
- \sa split()
+ \sa fromRawData(), QChar, QStringView, QLatin1StringView, QByteArray
*/
/*! \typedef QString::ConstIterator
@@ -1866,7 +2196,7 @@ inline char qToLower(char ch)
/*!
\typedef QString::pointer
- The QString::const_pointer typedef provides an STL-style
+ The QString::pointer typedef provides an STL-style
pointer to a QString element (QChar).
*/
@@ -1876,8 +2206,13 @@ inline char qToLower(char ch)
/*! \fn QString::iterator QString::begin()
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first character in
- the string.
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the
+ first character in the string.
+
+//! [iterator-invalidation-func-desc]
+ \warning The returned iterator is invalidated on detachment or when the
+ QString is modified.
+//! [iterator-invalidation-func-desc]
\sa constBegin(), end()
*/
@@ -1890,24 +2225,30 @@ inline char qToLower(char ch)
/*! \fn QString::const_iterator QString::cbegin() const
\since 5.0
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character
- in the string.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first character in the string.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa begin(), cend()
*/
/*! \fn QString::const_iterator QString::constBegin() const
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character
- in the string.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first character in the string.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa begin(), constEnd()
*/
/*! \fn QString::iterator QString::end()
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary character
- after the last character in the string.
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing just after
+ the last character in the string.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa begin(), constEnd()
*/
@@ -1920,16 +2261,20 @@ inline char qToLower(char ch)
/*! \fn QString::const_iterator QString::cend() const
\since 5.0
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- character after the last character in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
+ after the last character in the string.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa cbegin(), end()
*/
/*! \fn QString::const_iterator QString::constEnd() const
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- character after the last character in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
+ after the last character in the string.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa constBegin(), end()
*/
@@ -1937,8 +2282,10 @@ inline char qToLower(char ch)
/*! \fn QString::reverse_iterator QString::rbegin()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- character in the string, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to
+ the first character in the string, in reverse order.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa begin(), crbegin(), rend()
*/
@@ -1951,8 +2298,10 @@ inline char qToLower(char ch)
/*! \fn QString::const_reverse_iterator QString::crbegin() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- character in the string, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator
+ pointing to the first character in the string, in reverse order.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa begin(), rbegin(), rend()
*/
@@ -1960,8 +2309,10 @@ inline char qToLower(char ch)
/*! \fn QString::reverse_iterator QString::rend()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last character in the string, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing just
+ after the last character in the string, in reverse order.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa end(), crend(), rbegin()
*/
@@ -1974,8 +2325,10 @@ inline char qToLower(char ch)
/*! \fn QString::const_reverse_iterator QString::crend() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last character in the string, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator
+ pointing just after the last character in the string, in reverse order.
+
+ \include qstring.cpp iterator-invalidation-func-desc
\sa end(), rend(), rbegin()
*/
@@ -1983,9 +2336,9 @@ inline char qToLower(char ch)
/*!
\fn QString::QString()
- Constructs a null string. Null strings are also empty.
+ Constructs a null string. Null strings are also considered empty.
- \sa isEmpty()
+ \sa isEmpty(), isNull(), {Distinction Between Null and Empty Strings}
*/
/*!
@@ -2003,24 +2356,40 @@ inline char qToLower(char ch)
given const char pointer is converted to Unicode using the
fromUtf8() function.
- You can disable this constructor by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this constructor by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
- \note Defining \c QT_RESTRICTED_CAST_FROM_ASCII also disables
+ \note Defining \l QT_RESTRICTED_CAST_FROM_ASCII also disables
this constructor, but enables a \c{QString(const char (&ch)[N])}
constructor instead. Using non-literal input, or input with
embedded NUL characters, or non-7-bit characters is undefined
in this case.
- \sa fromLatin1(), fromLocal8Bit(), fromUtf8(), QT_NO_CAST_FROM_ASCII, QT_RESTRICTED_CAST_FROM_ASCII
+ \sa fromLatin1(), fromLocal8Bit(), fromUtf8()
+*/
+
+/*! \fn QString::QString(const char8_t *str)
+
+ Constructs a string initialized with the UTF-8 string \a str. The
+ given const char8_t pointer is converted to Unicode using the
+ fromUtf8() function.
+
+ \since 6.1
+ \sa fromLatin1(), fromLocal8Bit(), fromUtf8()
+*/
+
+/*
+//! [from-std-string]
+Returns a copy of the \a str string. The given string is assumed to be
+encoded in \1, and is converted to QString using the \2 function.
+//! [from-std-string]
*/
/*! \fn QString QString::fromStdString(const std::string &str)
- Returns a copy of the \a str string. The given string is converted
- to Unicode using the fromUtf8() function.
+ \include qstring.cpp {from-std-string} {UTF-8} {fromUtf8()}
\sa fromLatin1(), fromLocal8Bit(), fromUtf8(), QByteArray::fromStdString()
*/
@@ -2032,37 +2401,40 @@ inline char qToLower(char ch)
windows) and ucs4 if the size of wchar_t is 4 bytes (most Unix
systems).
- \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(), fromStdU16String(), fromStdU32String()
+ \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(),
+ fromStdU16String(), fromStdU32String()
*/
-/*! \fn QString QString::fromWCharArray(const wchar_t *string, int size)
+/*! \fn QString QString::fromWCharArray(const wchar_t *string, qsizetype size)
\since 4.2
Returns a copy of the \a string, where the encoding of \a string depends on
- the size of wchar. If wchar is 4 bytes, the \a string is interpreted as UCS-4,
- if wchar is 2 bytes it is interpreted as UTF-16.
+ the size of wchar. If wchar is 4 bytes, the \a string is interpreted as
+ UCS-4, if wchar is 2 bytes it is interpreted as UTF-16.
- If \a size is -1 (default), the \a string has to be \\0'-terminated.
+ If \a size is -1 (default), the \a string must be '\\0'-terminated.
- \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(), fromStdWString()
+ \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(),
+ fromStdWString()
*/
/*! \fn std::wstring QString::toStdWString() const
Returns a std::wstring object with the data contained in this
- QString. The std::wstring is encoded in utf16 on platforms where
- wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms
+ QString. The std::wstring is encoded in UTF-16 on platforms where
+ wchar_t is 2 bytes wide (for example, Windows) and in UTF-32 on platforms
where wchar_t is 4 bytes wide (most Unix systems).
This method is mostly useful to pass a QString to a function
that accepts a std::wstring object.
- \sa utf16(), toLatin1(), toUtf8(), toLocal8Bit(), toStdU16String(), toStdU32String()
+ \sa utf16(), toLatin1(), toUtf8(), toLocal8Bit(), toStdU16String(),
+ toStdU32String()
*/
-int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
+qsizetype QString::toUcs4_helper(const char16_t *uc, qsizetype length, char32_t *out)
{
- int count = 0;
+ qsizetype count = 0;
QStringIterator i(QStringView(uc, length));
while (i.hasNext())
@@ -2071,7 +2443,7 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
return count;
}
-/*! \fn int QString::toWCharArray(wchar_t *array) const
+/*! \fn qsizetype QString::toWCharArray(wchar_t *array) const
\since 4.2
Fills the \a array with the data contained in this QString object.
@@ -2087,7 +2459,8 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
\note This function does not append a null character to the array.
- \sa utf16(), toUcs4(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString(), QStringView::toWCharArray()
+ \sa utf16(), toUcs4(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString(),
+ QStringView::toWCharArray()
*/
/*! \fn QString::QString(const QString &other)
@@ -2117,20 +2490,18 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
\sa fromRawData()
*/
-QString::QString(const QChar *unicode, int size)
+QString::QString(const QChar *unicode, qsizetype size)
{
if (!unicode) {
d.clear();
} else {
- if (size < 0) {
- size = 0;
- while (!unicode[size].isNull())
- ++size;
- }
+ if (size < 0)
+ size = QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(unicode));
if (!size) {
- d = DataPointer(Data::allocate(0), 0);
+ d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(size + 1), size);
+ d = DataPointer(size, size);
+ Q_CHECK_PTR(d.data());
memcpy(d.data(), unicode, size * sizeof(QChar));
d.data()[size] = '\0';
}
@@ -2143,36 +2514,41 @@ QString::QString(const QChar *unicode, int size)
\sa fill()
*/
-QString::QString(int size, QChar ch)
+QString::QString(qsizetype size, QChar ch)
{
if (size <= 0) {
- d = DataPointer(Data::allocate(0), 0);
+ d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(size + 1), size);
+ d = DataPointer(size, size);
+ Q_CHECK_PTR(d.data());
d.data()[size] = '\0';
- char16_t *i = d.data() + size;
char16_t *b = d.data();
+ char16_t *e = d.data() + size;
const char16_t value = ch.unicode();
- while (i != b)
- *--i = value;
+ std::fill(b, e, value);
}
}
-/*! \fn QString::QString(int size, Qt::Initialization)
+/*! \fn QString::QString(qsizetype size, Qt::Initialization)
\internal
Constructs a string of the given \a size without initializing the
characters. This is only used in \c QStringBuilder::toString().
*/
-QString::QString(int size, Qt::Initialization)
+QString::QString(qsizetype size, Qt::Initialization)
{
- d = DataPointer(Data::allocate(size + 1), size);
- d.data()[size] = '\0';
+ if (size <= 0) {
+ d = DataPointer::fromRawData(&_empty, 0);
+ } else {
+ d = DataPointer(size, size);
+ Q_CHECK_PTR(d.data());
+ d.data()[size] = '\0';
+ }
}
-/*! \fn QString::QString(QLatin1String str)
+/*! \fn QString::QString(QLatin1StringView str)
- Constructs a copy of the Latin-1 string \a str.
+ Constructs a copy of the Latin-1 string viewed by \a str.
\sa fromLatin1()
*/
@@ -2182,7 +2558,8 @@ QString::QString(int size, Qt::Initialization)
*/
QString::QString(QChar ch)
{
- d = DataPointer(Data::allocate(2), 1);
+ d = DataPointer(1, 1);
+ Q_CHECK_PTR(d.data());
d.data()[0] = ch.unicode();
d.data()[1] = '\0';
}
@@ -2190,16 +2567,18 @@ QString::QString(QChar ch)
/*! \fn QString::QString(const QByteArray &ba)
Constructs a string initialized with the byte array \a ba. The
- given byte array is converted to Unicode using fromUtf8(). Stops
- copying at the first 0 character, otherwise copies the entire byte
- array.
+ given byte array is converted to Unicode using fromUtf8().
- You can disable this constructor by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this constructor by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
- \sa fromLatin1(), fromLocal8Bit(), fromUtf8(), QT_NO_CAST_FROM_ASCII
+ \note Any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000). This behavior is
+ different from Qt 5.x.
+
+ \sa fromLatin1(), fromLocal8Bit(), fromUtf8()
*/
/*! \fn QString::QString(const Null &)
@@ -2243,6 +2622,18 @@ QString::QString(QChar ch)
\internal
*/
+/*! \fn QString::operator std::u16string_view() const
+ \since 6.7
+
+ Converts this QString object to a \c{std::u16string_view} object.
+*/
+
+static bool needsReallocate(const QString &str, qsizetype newSize)
+{
+ const auto capacityAtEnd = str.capacity() - str.data_ptr().freeSpaceAtBegin();
+ return newSize > capacityAtEnd;
+}
+
/*!
Sets the size of the string to \a size characters.
@@ -2250,15 +2641,18 @@ QString::QString(QChar ch)
extended to make it \a size characters long with the extra
characters added to the end. The new characters are uninitialized.
- If \a size is less than the current size, characters are removed
- from the end.
+ If \a size is less than the current size, characters beyond position
+ \a size are excluded from the string.
+
+ \note While resize() will grow the capacity if needed, it never shrinks
+ capacity. To shed excess capacity, use squeeze().
Example:
\snippet qstring/main.cpp 45
If you want to append a certain number of identical characters to
- the string, use the \l {QString::}{resize(int, QChar)} overload.
+ the string, use the \l {QString::}{resize(qsizetype, QChar)} overload.
If you want to expand the string so that it reaches a certain
width and fill the new positions with a particular character, use
@@ -2268,41 +2662,59 @@ QString::QString(QChar ch)
\snippet qstring/main.cpp 47
- \sa truncate(), reserve()
+ \sa truncate(), reserve(), squeeze()
*/
-void QString::resize(int size)
+void QString::resize(qsizetype size)
{
if (size < 0)
size = 0;
- if (d->needsDetach() || size > capacity())
- reallocData(uint(size) + 1u, true);
+ if (d->needsDetach() || needsReallocate(*this, size))
+ reallocData(size, QArrayData::Grow);
d.size = size;
if (d->allocatedCapacity())
- d.data()[size] = 0;
+ d.data()[size] = u'\0';
}
/*!
\overload
\since 5.7
- Unlike \l {QString::}{resize(int)}, this overload
+ Unlike \l {QString::}{resize(qsizetype)}, this overload
initializes the new characters to \a fillChar:
\snippet qstring/main.cpp 46
*/
-void QString::resize(int size, QChar fillChar)
+void QString::resize(qsizetype newSize, QChar fillChar)
{
- const int oldSize = length();
- resize(size);
- const int difference = length() - oldSize;
+ const qsizetype oldSize = size();
+ resize(newSize);
+ const qsizetype difference = size() - oldSize;
if (difference > 0)
std::fill_n(d.data() + oldSize, difference, fillChar.unicode());
}
-/*! \fn int QString::capacity() const
+
+/*!
+ \since 6.8
+
+ Sets the size of the string to \a size characters. If the size of
+ the string grows, the new characters are uninitialized.
+
+ The behavior is identical to \c{resize(size)}.
+
+ \sa resize()
+*/
+
+void QString::resizeForOverwrite(qsizetype size)
+{
+ resize(size);
+}
+
+
+/*! \fn qsizetype QString::capacity() const
Returns the maximum number of characters that can be stored in
the string without forcing a reallocation.
@@ -2315,22 +2727,37 @@ void QString::resize(int size, QChar fillChar)
\note a statically allocated string will report a capacity of 0,
even if it's not empty.
+ \note The free space position in the allocated memory block is undefined. In
+ other words, one should not assume that the free memory is always located
+ after the initialized elements.
+
\sa reserve(), squeeze()
*/
/*!
- \fn void QString::reserve(int size)
+ \fn void QString::reserve(qsizetype size)
- Attempts to allocate memory for at least \a size characters. If
- you know in advance how large the string will be, you can call
- this function, and if you resize the string often you are likely
- to get better performance. If \a size is an underestimate, the
- worst that will happen is that the QString will be a bit slower.
+ Ensures the string has space for at least \a size characters.
- The sole purpose of this function is to provide a means of fine
- tuning QString's memory usage. In general, you will rarely ever
- need to call this function. If you want to change the size of the
- string, call resize().
+ If you know in advance how large a string will be, you can call this
+ function to save repeated reallocation while building it.
+ This can improve performance when building a string incrementally.
+ A long sequence of operations that add to a string may trigger several
+ reallocations, the last of which may leave you with significantly more
+ space than you need. This is less efficient than doing a single
+ allocation of the right size at the start.
+
+ If in doubt about how much space shall be needed, it is usually better to
+ use an upper bound as \a size, or a high estimate of the most likely size,
+ if a strict upper bound would be much bigger than this. If \a size is an
+ underestimate, the string will grow as needed once the reserved size is
+ exceeded, which may lead to a larger allocation than your best
+ overestimate would have and will slow the operation that triggers it.
+
+ \warning reserve() reserves memory but does not change the size of the
+ string. Accessing data beyond the end of the string is undefined behavior.
+ If you need to access memory beyond the current end of the string,
+ use resize().
This function is useful for code that needs to build up a long
string and wants to avoid repeated reallocation. In this example,
@@ -2340,7 +2767,7 @@ void QString::resize(int size, QChar fillChar)
\snippet qstring/main.cpp 44
- \sa squeeze(), capacity()
+ \sa squeeze(), capacity(), resize()
*/
/*!
@@ -2355,28 +2782,44 @@ void QString::resize(int size, QChar fillChar)
\sa reserve(), capacity()
*/
-void QString::reallocData(uint alloc, bool grow)
+void QString::reallocData(qsizetype alloc, QArrayData::AllocationOption option)
{
- auto allocOptions = d->detachFlags();
- if (grow)
- allocOptions |= QArrayData::GrowsForward;
+ if (!alloc) {
+ d = DataPointer::fromRawData(&_empty, 0);
+ return;
+ }
- if (d->needsDetach()) {
- DataPointer dd(Data::allocate(alloc, allocOptions), qMin(int(alloc) - 1, d.size));
- ::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
+ // don't use reallocate path when reducing capacity and there's free space
+ // at the beginning: might shift data pointer outside of allocated space
+ const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0;
+
+ if (d->needsDetach() || cannotUseReallocate) {
+ DataPointer dd(alloc, qMin(alloc, d.size), option);
+ Q_CHECK_PTR(dd.data());
+ if (dd.size > 0)
+ ::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
dd.data()[dd.size] = 0;
d = dd;
} else {
- d.reallocate(alloc, allocOptions);
+ d->reallocate(alloc, option);
}
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-void QString::expand(int i)
+void QString::reallocGrowData(qsizetype n)
{
- resize(qMax(i + 1, size()), QLatin1Char(' '));
+ if (!n) // expected to always allocate
+ n = 1;
+
+ if (d->needsDetach()) {
+ DataPointer dd(DataPointer::allocateGrow(d, n, QArrayData::GrowsAtEnd));
+ Q_CHECK_PTR(dd.data());
+ dd->copyAppend(d.data(), d.data() + d.size);
+ dd.data()[dd.size] = 0;
+ d = dd;
+ } else {
+ d->reallocate(d.constAllocatedCapacity() + n, QArrayData::Grow);
+ }
}
-#endif
/*! \fn void QString::clear()
@@ -2405,15 +2848,16 @@ QString &QString::operator=(const QString &other) noexcept
\since 5.2
*/
-/*! \fn QString &QString::operator=(QLatin1String str)
+/*! \fn QString &QString::operator=(QLatin1StringView str)
\overload operator=()
- Assigns the Latin-1 string \a str to this string.
+ Assigns the Latin-1 string viewed by \a str to this string.
*/
-QString &QString::operator=(QLatin1String other)
+QString &QString::operator=(QLatin1StringView other)
{
- if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 -> !isDetached() (sharedNull)
+ const qsizetype capacityAtEnd = capacity() - d.freeSpaceAtBegin();
+ if (isDetached() && other.size() <= capacityAtEnd) { // assumes d->alloc == 0 -> !isDetached() (sharedNull)
d.size = other.size();
d.data()[other.size()] = 0;
qt_from_latin1(d.data(), other.latin1(), other.size());
@@ -2428,15 +2872,12 @@ QString &QString::operator=(QLatin1String other)
\overload operator=()
Assigns \a ba to this string. The byte array is converted to Unicode
- using the fromUtf8() function. This function stops conversion at the
- first NUL character found, or the end of the \a ba byte array.
+ using the fromUtf8() function.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
/*! \fn QString &QString::operator=(const char *str)
@@ -2446,12 +2887,10 @@ QString &QString::operator=(QLatin1String other)
Assigns \a str to this string. The const char pointer is converted
to Unicode using the fromUtf8() function.
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
- or \c QT_RESTRICTED_CAST_FROM_ASCII when you compile your applications.
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
+ or \l QT_RESTRICTED_CAST_FROM_ASCII when you compile your applications.
This can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII, QT_RESTRICTED_CAST_FROM_ASCII
*/
/*!
@@ -2461,19 +2900,11 @@ QString &QString::operator=(QLatin1String other)
*/
QString &QString::operator=(QChar ch)
{
- if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 -> !isDetached() (sharedNull)
- // re-use existing capacity:
- d.data()[0] = ch.unicode();
- d.data()[1] = 0;
- d.size = 1;
- } else {
- operator=(QString(ch));
- }
- return *this;
+ return assign(1, ch);
}
/*!
- \fn QString& QString::insert(int position, const QString &str)
+ \fn QString& QString::insert(qsizetype position, const QString &str)
Inserts the string \a str at the given index \a position and
returns a reference to this string.
@@ -2482,144 +2913,227 @@ QString &QString::operator=(QChar ch)
\snippet qstring/main.cpp 26
- If the given \a position is greater than size(), the array is
- first extended using resize().
+//! [string-grow-at-insertion]
+ This string grows to accommodate the insertion. If \a position is beyond
+ the end of the string, space characters are appended to the string to reach
+ this \a position, followed by \a str.
+//! [string-grow-at-insertion]
\sa append(), prepend(), replace(), remove()
*/
-
/*!
- \fn QString& QString::insert(int position, const QStringRef &str)
- \since 5.5
- \overload insert()
-
- Inserts the string reference \a str at the given index \a position and
- returns a reference to this string.
-
- If the given \a position is greater than size(), the array is
- first extended using resize().
-*/
-
-
-/*!
- \fn QString& QString::insert(int position, QStringView str)
+ \fn QString& QString::insert(qsizetype position, QStringView str)
\since 6.0
\overload insert()
Inserts the string view \a str at the given index \a position and
returns a reference to this string.
- If the given \a position is greater than size(), the array is
- first extended using resize().
+ \include qstring.cpp string-grow-at-insertion
*/
/*!
- \fn QString& QString::insert(int position, const char *str)
+ \fn QString& QString::insert(qsizetype position, const char *str)
\since 5.5
\overload insert()
Inserts the C string \a str at the given index \a position and
returns a reference to this string.
- If the given \a position is greater than size(), the array is
- first extended using resize().
+ \include qstring.cpp string-grow-at-insertion
- This function is not available when \c QT_NO_CAST_FROM_ASCII is
+ This function is not available when \l QT_NO_CAST_FROM_ASCII is
defined.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-
/*!
- \fn QString& QString::insert(int position, const QByteArray &str)
+ \fn QString& QString::insert(qsizetype position, const QByteArray &str)
\since 5.5
\overload insert()
- Inserts the byte array \a str at the given index \a position and
- returns a reference to this string.
+ Interprets the contents of \a str as UTF-8, inserts the Unicode string
+ it encodes at the given index \a position and returns a reference to
+ this string.
- If the given \a position is greater than size(), the array is
- first extended using resize().
+ \include qstring.cpp string-grow-at-insertion
- This function is not available when \c QT_NO_CAST_FROM_ASCII is
+ This function is not available when \l QT_NO_CAST_FROM_ASCII is
defined.
+*/
- \sa QT_NO_CAST_FROM_ASCII
+/*! \internal
+ T is a view or a container on/of QChar, char16_t, or char
*/
+template <typename T>
+static void insert_helper(QString &str, qsizetype i, const T &toInsert)
+{
+ auto &str_d = str.data_ptr();
+ qsizetype difference = 0;
+ if (Q_UNLIKELY(i > str_d.size))
+ difference = i - str_d.size;
+ const qsizetype oldSize = str_d.size;
+ const qsizetype insert_size = toInsert.size();
+ const qsizetype newSize = str_d.size + difference + insert_size;
+ const auto side = i == 0 ? QArrayData::GrowsAtBeginning : QArrayData::GrowsAtEnd;
+
+ if (str_d.needsDetach() || needsReallocate(str, newSize)) {
+ const auto cbegin = str.cbegin();
+ const auto cend = str.cend();
+ const auto insert_start = difference == 0 ? std::next(cbegin, i) : cend;
+ QString other;
+ // Using detachAndGrow() so that prepend optimization works and QStringBuilder
+ // unittests pass
+ other.data_ptr().detachAndGrow(side, newSize, nullptr, nullptr);
+ other.append(QStringView(cbegin, insert_start));
+ other.resize(i, u' ');
+ other.append(toInsert);
+ other.append(QStringView(insert_start, cend));
+ str.swap(other);
+ return;
+ }
+
+ str_d.detachAndGrow(side, difference + insert_size, nullptr, nullptr);
+ Q_CHECK_PTR(str_d.data());
+ str.resize(newSize);
+ auto begin = str_d.begin();
+ auto old_end = std::next(begin, oldSize);
+ std::fill_n(old_end, difference, u' ');
+ auto insert_start = std::next(begin, i);
+ if (difference == 0)
+ std::move_backward(insert_start, old_end, str_d.end());
+
+ using Char = std::remove_cv_t<typename T::value_type>;
+ if constexpr(std::is_same_v<Char, QChar>)
+ std::copy_n(reinterpret_cast<const char16_t *>(toInsert.data()), insert_size, insert_start);
+ else if constexpr (std::is_same_v<Char, char16_t>)
+ std::copy_n(toInsert.data(), insert_size, insert_start);
+ else if constexpr (std::is_same_v<Char, char>)
+ qt_from_latin1(insert_start, toInsert.data(), insert_size);
+}
/*!
- \fn QString &QString::insert(int position, QLatin1String str)
+ \fn QString &QString::insert(qsizetype position, QLatin1StringView str)
\overload insert()
- Inserts the Latin-1 string \a str at the given index \a position.
+ Inserts the Latin-1 string viewed by \a str at the given index \a position.
+
+ \include qstring.cpp string-grow-at-insertion
*/
-QString &QString::insert(int i, QLatin1String str)
+QString &QString::insert(qsizetype i, QLatin1StringView str)
{
const char *s = str.latin1();
if (i < 0 || !s || !(*s))
return *this;
- int len = str.size();
- if (Q_UNLIKELY(i > size()))
- resize(i + len, QLatin1Char(' '));
- else
- resize(size() + len);
+ insert_helper(*this, i, str);
+ return *this;
+}
+
+/*!
+ \fn QString &QString::insert(qsizetype position, QUtf8StringView str)
+ \overload insert()
+ \since 6.5
+
+ Inserts the UTF-8 string view \a str at the given index \a position.
+
+ \note Inserting variable-width UTF-8-encoded string data is conceptually slower
+ than inserting fixed-width string data such as UTF-16 (QStringView) or Latin-1
+ (QLatin1StringView) and should thus be used sparingly.
+
+ \include qstring.cpp string-grow-at-insertion
+*/
+QString &QString::insert(qsizetype i, QUtf8StringView s)
+{
+ auto insert_size = s.size();
+ if (i < 0 || insert_size <= 0)
+ return *this;
+
+ qsizetype difference = 0;
+ if (Q_UNLIKELY(i > d.size))
+ difference = i - d.size;
+
+ const qsizetype newSize = d.size + difference + insert_size;
+
+ if (d.needsDetach() || needsReallocate(*this, newSize)) {
+ const auto cbegin = this->cbegin();
+ const auto insert_start = difference == 0 ? std::next(cbegin, i) : cend();
+ QString other;
+ other.reserve(newSize);
+ other.append(QStringView(cbegin, insert_start));
+ if (difference > 0)
+ other.resize(i, u' ');
+ other.append(s);
+ other.append(QStringView(insert_start, cend()));
+ swap(other);
+ return *this;
+ }
+
+ if (i >= d.size) {
+ d.detachAndGrow(QArrayData::GrowsAtEnd, difference + insert_size, nullptr, nullptr);
+ Q_CHECK_PTR(d.data());
+
+ if (difference > 0)
+ resize(i, u' ');
+ append(s);
+ } else {
+ // Optimal insertion of Utf8 data is at the end, anywhere else could
+ // potentially lead to moving characters twice if Utf8 data size
+ // (variable-width) is less than the equivalent Utf16 data size
+ QVarLengthArray<char16_t> buffer(insert_size); // ### optimize (QTBUG-108546)
+ char16_t *b = QUtf8::convertToUnicode(buffer.data(), s);
+ insert_helper(*this, i, QStringView(buffer.data(), b));
+ }
- ::memmove(d.data() + i + len, d.data() + i, (d.size - i - len) * sizeof(QChar));
- qt_from_latin1(d.data() + i, s, uint(len));
return *this;
}
/*!
- \fn QString& QString::insert(int position, const QChar *unicode, int size)
+ \fn QString& QString::insert(qsizetype position, const QChar *unicode, qsizetype size)
\overload insert()
Inserts the first \a size characters of the QChar array \a unicode
at the given index \a position in the string.
+
+ This string grows to accommodate the insertion. If \a position is beyond
+ the end of the string, space characters are appended to the string to reach
+ this \a position, followed by \a size characters of the QChar array
+ \a unicode.
*/
-QString& QString::insert(int i, const QChar *unicode, int size)
+QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size)
{
if (i < 0 || size <= 0)
return *this;
- const auto s = reinterpret_cast<const char16_t *>(unicode);
- if (points_into_range(s, d.data(), d.data() + d.size))
- return insert(i, QStringView{QVarLengthArray(s, s + size)});
-
- if (Q_UNLIKELY(i > int(d.size)))
- resize(i + size, QLatin1Char(' '));
- else
- resize(d.size + size);
+ // In case when data points into "this"
+ if (!d->needsDetach() && QtPrivate::q_points_into_range(unicode, *this)) {
+ QVarLengthArray copy(unicode, unicode + size);
+ insert(i, copy.data(), size);
+ } else {
+ insert_helper(*this, i, QStringView(unicode, size));
+ }
- ::memmove(d.data() + i + size, d.data() + i, (d.size - i - size) * sizeof(QChar));
- memcpy(d.data() + i, s, size * sizeof(QChar));
return *this;
}
/*!
- \fn QString& QString::insert(int position, QChar ch)
+ \fn QString& QString::insert(qsizetype position, QChar ch)
\overload insert()
Inserts \a ch at the given index \a position in the string.
+
+ This string grows to accommodate the insertion. If \a position is beyond
+ the end of the string, space characters are appended to the string to reach
+ this \a position, followed by \a ch.
*/
-QString& QString::insert(int i, QChar ch)
+QString& QString::insert(qsizetype i, QChar ch)
{
if (i < 0)
i += d.size;
- if (i < 0)
- return *this;
- if (Q_UNLIKELY(i > size()))
- resize(i + 1, QLatin1Char(' '));
- else
- resize(d.size + 1);
- ::memmove(d.data() + i + 1, d.data() + i, (d.size - i - 1) * sizeof(QChar));
- d.data()[i] = ch.unicode();
- return *this;
+ return insert(i, &ch, 1);
}
/*!
@@ -2644,32 +3158,39 @@ QString &QString::append(const QString &str)
{
if (!str.isNull()) {
if (isNull()) {
- operator=(str);
- } else {
- if (d->needsDetach() || size() + str.size() > capacity())
- reallocData(uint(size() + str.size()) + 1u, true);
- memcpy(d.data() + d.size, str.d.data(), str.d.size * sizeof(QChar));
- d.size += str.d.size;
- d.data()[d.size] = '\0';
+ if (Q_UNLIKELY(!str.d.isMutable()))
+ assign(str); // fromRawData, so we do a deep copy
+ else
+ operator=(str);
+ } else if (str.size()) {
+ append(str.constData(), str.size());
}
}
return *this;
}
/*!
+ \fn QString &QString::append(QStringView v)
+ \overload append()
+ \since 6.0
+
+ Appends the given string view \a v to this string and returns the result.
+*/
+
+/*!
\overload append()
\since 5.0
Appends \a len characters from the QChar array \a str to this string.
*/
-QString &QString::append(const QChar *str, int len)
+QString &QString::append(const QChar *str, qsizetype len)
{
if (str && len > 0) {
- if (d->needsDetach() || size() + len > capacity())
- reallocData(uint(size() + len) + 1u, true);
- memcpy(d.data() + d.size, str, len * sizeof(QChar));
- d.size += len;
- d.data()[d.size] = '\0';
+ static_assert(sizeof(QChar) == sizeof(char16_t), "Unexpected difference in sizes");
+ // the following should be safe as QChar uses char16_t as underlying data
+ const char16_t *char16String = reinterpret_cast<const char16_t *>(str);
+ d->growAppend(char16String, char16String + len);
+ d.data()[d.size] = u'\0';
}
return *this;
}
@@ -2677,20 +3198,23 @@ QString &QString::append(const QChar *str, int len)
/*!
\overload append()
- Appends the Latin-1 string \a str to this string.
+ Appends the Latin-1 string viewed by \a str to this string.
*/
-QString &QString::append(QLatin1String str)
+QString &QString::append(QLatin1StringView str)
{
- const char *s = str.latin1();
- if (s) {
- int len = str.size();
- if (d->needsDetach() || size() + len > capacity())
- reallocData(uint(size() + len) + 1u, true);
- char16_t *i = d.data() + d.size;
- qt_from_latin1(i, s, uint(len));
- i[len] = '\0';
- d.size += len;
- }
+ append_helper(*this, str);
+ return *this;
+}
+
+/*!
+ \overload append()
+ \since 6.5
+
+ Appends the UTF-8 string view \a str to this string.
+*/
+QString &QString::append(QUtf8StringView str)
+{
+ append_helper(*this, str);
return *this;
}
@@ -2701,12 +3225,10 @@ QString &QString::append(QLatin1String str)
Appends the byte array \a ba to this string. The given byte array
is converted to Unicode using the fromUtf8() function.
- You can disable this function by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this function by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
/*! \fn QString &QString::append(const char *str)
@@ -2716,12 +3238,10 @@ QString &QString::append(QLatin1String str)
Appends the string \a str to this string. The given const char
pointer is converted to Unicode using the fromUtf8() function.
- You can disable this function by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this function by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
/*!
@@ -2731,9 +3251,8 @@ QString &QString::append(QLatin1String str)
*/
QString &QString::append(QChar ch)
{
- if (d->needsDetach() || size() + 1 > capacity())
- reallocData(uint(d.size) + 2u, true);
- d.data()[d.size++] = ch.unicode();
+ d.detachAndGrow(QArrayData::GrowsAtEnd, 1, nullptr, nullptr);
+ d->copyAppend(1, ch.unicode());
d.data()[d.size] = '\0';
return *this;
}
@@ -2743,6 +3262,10 @@ QString &QString::append(QChar ch)
Prepends the string \a str to the beginning of this string and
returns a reference to this string.
+ This operation is typically very fast (\l{constant time}), because
+ QString preallocates extra space at the beginning of the string data,
+ so it can grow without reallocating the entire string each time.
+
Example:
\snippet qstring/main.cpp 36
@@ -2750,26 +3273,25 @@ QString &QString::append(QChar ch)
\sa append(), insert()
*/
-/*! \fn QString &QString::prepend(QLatin1String str)
+/*! \fn QString &QString::prepend(QLatin1StringView str)
\overload prepend()
- Prepends the Latin-1 string \a str to this string.
+ Prepends the Latin-1 string viewed by \a str to this string.
*/
-/*! \fn QString &QString::prepend(const QChar *str, int len)
- \since 5.5
+/*! \fn QString &QString::prepend(QUtf8StringView str)
+ \since 6.5
\overload prepend()
- Prepends \a len characters from the QChar array \a str to this string and
- returns a reference to this string.
+ Prepends the UTF-8 string view \a str to this string.
*/
-/*! \fn QString &QString::prepend(const QStringRef &str)
+/*! \fn QString &QString::prepend(const QChar *str, qsizetype len)
\since 5.5
\overload prepend()
- Prepends the string reference \a str to the beginning of this string and
+ Prepends \a len characters from the QChar array \a str to this string and
returns a reference to this string.
*/
@@ -2788,12 +3310,10 @@ QString &QString::append(QChar ch)
Prepends the byte array \a ba to this string. The byte array is
converted to Unicode using the fromUtf8() function.
- You can disable this function by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this function by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
/*! \fn QString &QString::prepend(const char *str)
@@ -2803,12 +3323,10 @@ QString &QString::append(QChar ch)
Prepends the string \a str to this string. The const char pointer
is converted to Unicode using the fromUtf8() function.
- You can disable this function by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this function by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
/*! \fn QString &QString::prepend(QChar ch)
@@ -2819,7 +3337,112 @@ QString &QString::append(QChar ch)
*/
/*!
- \fn QString &QString::remove(int position, int n)
+ \fn QString &QString::assign(QAnyStringView v)
+ \since 6.6
+
+ Replaces the contents of this string with a copy of \a v and returns a
+ reference to this string.
+
+ The size of this string will be equal to the size of \a v, converted to
+ UTF-16 as if by \c{v.toString()}. Unlike QAnyStringView::toString(), however,
+ this function only allocates memory if the estimated size exceeds the capacity
+ of this string or this string is shared.
+
+ \sa QAnyStringView::toString()
+*/
+
+/*!
+ \fn QString &QString::assign(qsizetype n, QChar c)
+ \since 6.6
+
+ Replaces the contents of this string with \a n copies of \a c and
+ returns a reference to this string.
+
+ The size of this string will be equal to \a n, which has to be non-negative.
+
+ This function will only allocate memory if \a n exceeds the capacity of this
+ string or this string is shared.
+
+ \sa fill()
+*/
+
+/*!
+ \fn template <typename InputIterator, QString::if_compatible_iterator<InputIterator>> QString &QString::assign(InputIterator first, InputIterator last)
+ \since 6.6
+
+ Replaces the contents of this string with a copy of the elements in the
+ iterator range [\a first, \a last) and returns a reference to this string.
+
+ The size of this string will be equal to the decoded length of the elements
+ in the range [\a first, \a last), which need not be the same as the length of
+ the range itself, because this function transparently recodes the input
+ character set to UTF-16.
+
+ This function will only allocate memory if the number of elements in the
+ range, or, for non-UTF-16-encoded input, the maximum possible size of the
+ resulting string, exceeds the capacity of this string, or if this string is
+ shared.
+
+ \note This function overload only participates in overload resolution if
+ \c InputIterator meets the requirements of a
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}
+ and the \c{value_type} of \c InputIterator is one of the following character types:
+ \list
+ \li QChar
+ \li QLatin1Char
+ \li \c {char}
+ \li \c {unsigned char}
+ \li \c {signed char}
+ \li \c {char8_t}
+ \li \c char16_t
+ \li (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t
+ \li \c char32_t
+ \endlist
+
+ \note The behavior is undefined if either argument is an iterator into *this or
+ [\a first, \a last) is not a valid range.
+*/
+
+QString &QString::assign(QAnyStringView s)
+{
+ if (s.size() <= capacity() && isDetached()) {
+ const auto offset = d.freeSpaceAtBegin();
+ if (offset)
+ d.setBegin(d.begin() - offset);
+ resize(0);
+ s.visit([this](auto input) {
+ this->append(input);
+ });
+ } else {
+ *this = s.toString();
+ }
+ return *this;
+}
+
+#ifndef QT_BOOTSTRAPPED
+QString &QString::assign_helper(const char32_t *data, qsizetype len)
+{
+ // worst case: each char32_t requires a surrogate pair, so
+ const auto requiredCapacity = len * 2;
+ if (requiredCapacity <= capacity() && isDetached()) {
+ const auto offset = d.freeSpaceAtBegin();
+ if (offset)
+ d.setBegin(d.begin() - offset);
+ auto begin = reinterpret_cast<QChar *>(d.begin());
+ auto ba = QByteArrayView(reinterpret_cast<const std::byte*>(data), len * sizeof(char32_t));
+ QStringConverter::State state;
+ const auto end = QUtf32::convertToUnicode(begin, ba, &state, DetectEndianness);
+ d.size = end - begin;
+ d.data()[d.size] = u'\0';
+ } else {
+ *this = QString::fromUcs4(data, len);
+ }
+ return *this;
+}
+#endif
+
+/*!
+ \fn QString &QString::remove(qsizetype position, qsizetype n)
Removes \a n characters from the string, starting at the given \a
position index, and returns a reference to the string.
@@ -2828,23 +3451,42 @@ QString &QString::append(QChar ch)
position + \a n is beyond the end of the string, the string is
truncated at the specified \a position.
+ If \a n is <= 0 nothing is changed.
+
\snippet qstring/main.cpp 37
+//! [shrinking-erase]
+ Element removal will preserve the string's capacity and not reduce the
+ amount of allocated memory. To shed extra capacity and free as much memory
+ as possible, call squeeze() after the last change to the string's size.
+//! [shrinking-erase]
+
\sa insert(), replace()
*/
-QString &QString::remove(int pos, int len)
+QString &QString::remove(qsizetype pos, qsizetype len)
{
if (pos < 0) // count from end of string
pos += size();
- if (uint(pos) >= uint(size())) {
- // range problems
- } else if (len >= size() - pos) {
- resize(pos); // truncate
- } else if (len > 0) {
- detach();
- memmove(d.data() + pos, d.data() + pos + len,
- (d.size - pos - len + 1) * sizeof(QChar));
- d.size -= len;
+
+ if (size_t(pos) >= size_t(size()) || len <= 0)
+ return *this;
+
+ len = std::min(len, size() - pos);
+
+ if (!d->isShared()) {
+ d->erase(d.begin() + pos, len);
+ d.data()[d.size] = u'\0';
+ } else {
+ // TODO: either reserve "size()", which is bigger than needed, or
+ // modify the shrinking-erase docs of this method (since the size
+ // of "copy" won't have any extra capacity any more)
+ const qsizetype sz = size() - len;
+ QString copy{sz, Qt::Uninitialized};
+ auto begin = d.begin();
+ auto toRemove_start = d.begin() + pos;
+ copy.d->copyRanges({{begin, toRemove_start},
+ {toRemove_start + len, d.end()}});
+ swap(copy);
}
return *this;
}
@@ -2857,42 +3499,55 @@ static void removeStringImpl(QString &s, const T &needle, Qt::CaseSensitivity cs
return;
// avoid detach if nothing to do:
- int i = s.indexOf(needle, 0, cs);
+ qsizetype i = s.indexOf(needle, 0, cs);
if (i < 0)
return;
- const auto beg = s.begin(); // detaches
- auto dst = beg + i;
- auto src = beg + i + needleSize;
- const auto end = s.end();
- // loop invariant: [beg, dst[ is partial result
- // [src, end[ still to be checked for needles
- while (src < end) {
- const auto i = s.indexOf(needle, src - beg, cs);
- const auto hit = i == -1 ? end : beg + i;
- const auto skipped = hit - src;
- memmove(dst, src, skipped * sizeof(QChar));
- dst += skipped;
- src = hit + needleSize;
+ QString::DataPointer &dptr = s.data_ptr();
+ auto begin = dptr.begin();
+ auto end = dptr.end();
+
+ auto copyFunc = [&](auto &dst) {
+ auto src = begin + i + needleSize;
+ while (src < end) {
+ i = s.indexOf(needle, std::distance(begin, src), cs);
+ auto hit = i == -1 ? end : begin + i;
+ dst = std::copy(src, hit, dst);
+ src = hit + needleSize;
+ }
+ return dst;
+ };
+
+ if (!dptr->needsDetach()) {
+ auto dst = begin + i;
+ dst = copyFunc(dst);
+ s.truncate(std::distance(begin, dst));
+ } else {
+ QString copy{s.size(), Qt::Uninitialized};
+ auto copy_begin = copy.begin();
+ auto dst = std::copy(begin, begin + i, copy_begin); // Chunk before the first hit
+ dst = copyFunc(dst);
+ copy.resize(std::distance(copy_begin, dst));
+ s.swap(copy);
}
- s.truncate(dst - beg);
}
/*!
Removes every occurrence of the given \a str string in this
string, and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
This is the same as \c replace(str, "", cs).
+ \include qstring.cpp shrinking-erase
+
\sa replace()
*/
QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
{
const auto s = str.d.data();
- if (points_into_range(s, d.data(), d.data() + d.size))
+ if (QtPrivate::q_points_into_range(s, d))
removeStringImpl(*this, QStringView{QVarLengthArray(s, s + str.size())}, cs);
else
removeStringImpl(*this, qToStringViewIgnoringNull(str), cs);
@@ -2903,28 +3558,61 @@ QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
\since 5.11
\overload
- Removes every occurrence of the given \a str string in this
- string, and returns a reference to this string.
+ Removes every occurrence of the given Latin-1 string viewed by \a str
+ from this string, and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
This is the same as \c replace(str, "", cs).
+ \include qstring.cpp shrinking-erase
+
\sa replace()
*/
-QString &QString::remove(QLatin1String str, Qt::CaseSensitivity cs)
+QString &QString::remove(QLatin1StringView str, Qt::CaseSensitivity cs)
{
removeStringImpl(*this, str, cs);
return *this;
}
/*!
+ \fn QString &QString::removeAt(qsizetype pos)
+
+ \since 6.5
+
+ Removes the character at index \a pos. If \a pos is out of bounds
+ (i.e. \a pos >= size()), this function does nothing.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QString &QString::removeFirst()
+
+ \since 6.5
+
+ Removes the first character in this string. If the string is empty,
+ this function does nothing.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QString &QString::removeLast()
+
+ \since 6.5
+
+ Removes the last character in this string. If the string is empty,
+ this function does nothing.
+
+ \sa remove()
+*/
+
+/*!
Removes every occurrence of the character \a ch in this string, and
returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
@@ -2932,24 +3620,41 @@ QString &QString::remove(QLatin1String str, Qt::CaseSensitivity cs)
This is the same as \c replace(ch, "", cs).
+ \include qstring.cpp shrinking-erase
+
\sa replace()
*/
QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
{
- const int idx = indexOf(ch, 0, cs);
- if (idx != -1) {
- const auto first = begin(); // implicit detach()
- auto last = end();
- if (cs == Qt::CaseSensitive) {
- last = std::remove(first + idx, last, ch);
- } else {
- const QChar c = ch.toCaseFolded();
- auto caseInsensEqual = [c](QChar x) {
- return c == x.toCaseFolded();
- };
- last = std::remove_if(first + idx, last, caseInsensEqual);
- }
- resize(last - first);
+ const qsizetype idx = indexOf(ch, 0, cs);
+ if (idx == -1)
+ return *this;
+
+ const bool isCase = cs == Qt::CaseSensitive;
+ ch = isCase ? ch : ch.toCaseFolded();
+ auto match = [ch, isCase](QChar x) {
+ return ch == (isCase ? x : x.toCaseFolded());
+ };
+
+
+ auto begin = d.begin();
+ auto first_match = begin + idx;
+ auto end = d.end();
+ if (!d->isShared()) {
+ auto it = std::remove_if(first_match, end, match);
+ d->erase(it, std::distance(it, end));
+ d.data()[d.size] = u'\0';
+ } else {
+ // Instead of detaching, create a new string and copy all characters except for
+ // the ones we're removing
+ // TODO: size() is more than the needed since "copy" would be shorter
+ QString copy{size(), Qt::Uninitialized};
+ auto dst = copy.d.begin();
+ auto it = std::copy(begin, first_match, dst); // Chunk before idx
+ it = std::remove_copy_if(first_match + 1, end, it, match);
+ copy.d.size = std::distance(dst, it);
+ copy.d.data()[copy.d.size] = u'\0';
+ *this = std::move(copy);
}
return *this;
}
@@ -2963,11 +3668,114 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
\snippet qstring/main.cpp 96
+ \include qstring.cpp shrinking-erase
+
\sa indexOf(), lastIndexOf(), replace()
*/
/*!
- \fn QString &QString::replace(int position, int n, const QString &after)
+ \fn template <typename Predicate> QString &QString::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the string. Returns a reference to the string.
+
+ \sa remove()
+*/
+
+
+/*! \internal
+ Instead of detaching, or reallocating if "before" is shorter than "after"
+ and there isn't enough capacity, create a new string, copy characters to it
+ as needed, then swap it with "str".
+*/
+static void replace_with_copy(QString &str, QSpan<size_t> indices, qsizetype blen,
+ QStringView after)
+{
+ const qsizetype alen = after.size();
+ const char16_t *after_b = after.utf16();
+
+ const QString::DataPointer &str_d = str.data_ptr();
+ auto src_start = str_d.begin();
+ const qsizetype newSize = str_d.size + indices.size() * (alen - blen);
+ QString copy{ newSize, Qt::Uninitialized };
+ QString::DataPointer &copy_d = copy.data_ptr();
+ auto dst = copy_d.begin();
+ for (size_t index : indices) {
+ auto hit = str_d.begin() + index;
+ dst = std::copy(src_start, hit, dst);
+ dst = std::copy_n(after_b, alen, dst);
+ src_start = hit + blen;
+ }
+ dst = std::copy(src_start, str_d.end(), dst);
+ str.swap(copy);
+}
+
+// No detaching or reallocation is needed
+static void replace_in_place(QString &str, QSpan<size_t> indices,
+ qsizetype blen, QStringView after)
+{
+ const qsizetype alen = after.size();
+ const char16_t *after_b = after.utf16();
+ const char16_t *after_e = after.utf16() + after.size();
+
+ if (blen == alen) { // Replace in place
+ for (size_t index : indices)
+ std::copy_n(after_b, alen, str.data_ptr().begin() + index);
+ } else if (blen > alen) { // Replace from front
+ char16_t *begin = str.data_ptr().begin();
+ char16_t *hit = begin + indices.front();
+ char16_t *to = hit;
+ to = std::copy_n(after_b, alen, to);
+ char16_t *movestart = hit + blen;
+ for (size_t index : indices.sliced(1)) {
+ hit = begin + index;
+ to = std::move(movestart, hit, to);
+ to = std::copy_n(after_b, alen, to);
+ movestart = hit + blen;
+ }
+ to = std::move(movestart, str.data_ptr().end(), to);
+ str.resize(std::distance(begin, to));
+ } else { // blen < alen, Replace from back
+ const qsizetype oldSize = str.data_ptr().size;
+ const qsizetype adjust = indices.size() * (alen - blen);
+ const qsizetype newSize = oldSize + adjust;
+
+ str.resize(newSize);
+ char16_t *begin = str.data_ptr().begin();
+ char16_t *moveend = begin + oldSize;
+ char16_t *to = str.data_ptr().end();
+
+ for (auto it = indices.rbegin(), end = indices.rend(); it != end; ++it) {
+ char16_t *hit = begin + *it;
+ char16_t *movestart = hit + blen;
+ to = std::move_backward(movestart, moveend, to);
+ to = std::copy_backward(after_b, after_e, to);
+ moveend = hit;
+ }
+ }
+}
+
+static void replace_helper(QString &str, QSpan<size_t> indices, qsizetype blen, QStringView after)
+{
+ const qsizetype oldSize = str.data_ptr().size;
+ const qsizetype adjust = indices.size() * (after.size() - blen);
+ const qsizetype newSize = oldSize + adjust;
+ if (str.data_ptr().needsDetach() || needsReallocate(str, newSize)) {
+ replace_with_copy(str, indices, blen, after);
+ return;
+ }
+
+ if (QtPrivate::q_points_into_range(after.begin(), str))
+ // Copy after if it lies inside our own d.b area (which we could
+ // possibly invalidate via a realloc or modify by replacement)
+ replace_in_place(str, indices, blen, QVarLengthArray(after.begin(), after.end()));
+ else
+ replace_in_place(str, indices, blen, after);
+}
+
+/*!
+ \fn QString &QString::replace(qsizetype position, qsizetype n, const QString &after)
Replaces \a n characters beginning at index \a position with
the string \a after and returns a reference to this string.
@@ -2982,38 +3790,38 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
\sa insert(), remove()
*/
-QString &QString::replace(int pos, int len, const QString &after)
+QString &QString::replace(qsizetype pos, qsizetype len, const QString &after)
{
- return replace(pos, len, after.constData(), after.length());
+ return replace(pos, len, after.constData(), after.size());
}
/*!
- \fn QString &QString::replace(int position, int n, const QChar *unicode, int size)
+ \fn QString &QString::replace(qsizetype position, qsizetype n, const QChar *after, qsizetype alen)
\overload replace()
Replaces \a n characters beginning at index \a position with the
- first \a size characters of the QChar array \a unicode and returns a
+ first \a alen characters of the QChar array \a after and returns a
reference to this string.
*/
-QString &QString::replace(int pos, int len, const QChar *unicode, int size)
+QString &QString::replace(qsizetype pos, qsizetype len, const QChar *after, qsizetype alen)
{
- if (uint(pos) > uint(this->size()))
+ if (size_t(pos) > size_t(this->size()))
return *this;
if (len > this->size() - pos)
len = this->size() - pos;
- uint index = pos;
- replace_helper(&index, 1, len, unicode, size);
+ size_t index = pos;
+ replace_helper(*this, QSpan(&index, 1), len, QStringView{after, alen});
return *this;
}
/*!
- \fn QString &QString::replace(int position, int n, QChar after)
+ \fn QString &QString::replace(qsizetype position, qsizetype n, QChar after)
\overload replace()
Replaces \a n characters beginning at index \a position with the
character \a after and returns a reference to this string.
*/
-QString &QString::replace(int pos, int len, QChar after)
+QString &QString::replace(qsizetype pos, qsizetype len, QChar after)
{
return replace(pos, len, &after, 1);
}
@@ -3023,8 +3831,7 @@ QString &QString::replace(int pos, int len, QChar after)
Replaces every occurrence of the string \a before with the string \a
after and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
@@ -3041,90 +3848,6 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS
return replace(before.constData(), before.size(), after.constData(), after.size(), cs);
}
-namespace { // helpers for replace and its helper:
-QChar *textCopy(const QChar *start, int len)
-{
- const size_t size = len * sizeof(QChar);
- QChar *const copy = static_cast<QChar *>(::malloc(size));
- Q_CHECK_PTR(copy);
- ::memcpy(copy, start, size);
- return copy;
-}
-
-static bool pointsIntoRange(const QChar *ptr, const char16_t *base, qsizetype len)
-{
- const QChar *const start = reinterpret_cast<const QChar *>(base);
- const std::less<const QChar *> less;
- return !less(ptr, start) && less(ptr, start + len);
-}
-} // end namespace
-
-/*!
- \internal
- */
-void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
-{
- // Copy after if it lies inside our own d.b area (which we could
- // possibly invalidate via a realloc or modify by replacement).
- QChar *afterBuffer = nullptr;
- if (pointsIntoRange(after, d.data(), d.size)) // Use copy in place of vulnerable original:
- after = afterBuffer = textCopy(after, alen);
-
- QT_TRY {
- if (blen == alen) {
- // replace in place
- detach();
- for (int i = 0; i < nIndices; ++i)
- memcpy(d.data() + indices[i], after, alen * sizeof(QChar));
- } else if (alen < blen) {
- // replace from front
- detach();
- uint to = indices[0];
- if (alen)
- memcpy(d.data()+to, after, alen*sizeof(QChar));
- to += alen;
- uint movestart = indices[0] + blen;
- for (int i = 1; i < nIndices; ++i) {
- int msize = indices[i] - movestart;
- if (msize > 0) {
- memmove(d.data() + to, d.data() + movestart, msize * sizeof(QChar));
- to += msize;
- }
- if (alen) {
- memcpy(d.data() + to, after, alen * sizeof(QChar));
- to += alen;
- }
- movestart = indices[i] + blen;
- }
- int msize = d.size - movestart;
- if (msize > 0)
- memmove(d.data() + to, d.data() + movestart, msize * sizeof(QChar));
- resize(d.size - nIndices*(blen-alen));
- } else {
- // replace from back
- int adjust = nIndices*(alen-blen);
- int newLen = d.size + adjust;
- int moveend = d.size;
- resize(newLen);
-
- while (nIndices) {
- --nIndices;
- int movestart = indices[nIndices] + blen;
- int insertstart = indices[nIndices] + nIndices*(alen-blen);
- int moveto = insertstart + alen;
- memmove(d.data() + moveto, d.data() + movestart,
- (moveend - movestart)*sizeof(QChar));
- memcpy(d.data() + insertstart, after, alen * sizeof(QChar));
- moveend = movestart-blen;
- }
- }
- } QT_CATCH(const std::bad_alloc &) {
- ::free(afterBuffer);
- QT_RETHROW;
- }
- ::free(afterBuffer);
-}
-
/*!
\since 4.5
\overload replace()
@@ -3133,11 +3856,10 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar
characters of \a before with the first \a alen characters of \a
after and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
*/
-QString &QString::replace(const QChar *before, int blen,
- const QChar *after, int alen,
+QString &QString::replace(const QChar *before, qsizetype blen,
+ const QChar *after, qsizetype alen,
Qt::CaseSensitivity cs)
{
if (d.size == 0) {
@@ -3149,51 +3871,25 @@ QString &QString::replace(const QChar *before, int blen,
}
if (alen == 0 && blen == 0)
return *this;
+ if (alen == 1 && blen == 1)
+ return replace(*before, *after, cs);
QStringMatcher matcher(before, blen, cs);
- QChar *beforeBuffer = nullptr, *afterBuffer = nullptr;
-
- int index = 0;
- while (1) {
- uint indices[1024];
- uint pos = 0;
- while (pos < 1024) {
- index = matcher.indexIn(*this, index);
- if (index == -1)
- break;
- indices[pos++] = index;
- if (blen) // Step over before:
- index += blen;
- else // Only count one instance of empty between any two characters:
- index++;
- }
- if (!pos) // Nothing to replace
- break;
-
- if (Q_UNLIKELY(index != -1)) {
- /*
- We're about to change data, that before and after might point
- into, and we'll need that data for our next batch of indices.
- */
- if (!afterBuffer && pointsIntoRange(after, d.data(), d.size))
- after = afterBuffer = textCopy(after, alen);
-
- if (!beforeBuffer && pointsIntoRange(before, d.data(), d.size)) {
- beforeBuffer = textCopy(before, blen);
- matcher = QStringMatcher(beforeBuffer, blen, cs);
- }
- }
- replace_helper(indices, pos, blen, after, alen);
+ qsizetype index = 0;
- if (Q_LIKELY(index == -1)) // Nothing left to replace
- break;
- // The call to replace_helper just moved what index points at:
- index += pos*(alen-blen);
+ QVarLengthArray<size_t> indices;
+ while ((index = matcher.indexIn(*this, index)) != -1) {
+ indices.push_back(index);
+ if (blen) // Step over before:
+ index += blen;
+ else // Only count one instance of empty between any two characters:
+ index++;
}
- ::free(afterBuffer);
- ::free(beforeBuffer);
+ if (indices.isEmpty())
+ return *this;
+ replace_helper(*this, indices, blen, QStringView{after, alen});
return *this;
}
@@ -3202,8 +3898,7 @@ QString &QString::replace(const QChar *before, int blen,
Replaces every occurrence of the character \a ch in the string with
\a after and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
*/
QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs)
{
@@ -3216,35 +3911,27 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
if (size() == 0)
return *this;
- char16_t cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode());
+ const char16_t cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode());
- int index = 0;
- while (1) {
- uint indices[1024];
- uint pos = 0;
- if (cs == Qt::CaseSensitive) {
- while (pos < 1024 && index < size()) {
- if (d.data()[index] == cc)
- indices[pos++] = index;
- index++;
- }
- } else {
- while (pos < 1024 && index < size()) {
- if (QChar::toCaseFolded(d.data()[index]) == cc)
- indices[pos++] = index;
- index++;
- }
+ QVarLengthArray<size_t> indices;
+ if (cs == Qt::CaseSensitive) {
+ const char16_t *begin = d.begin();
+ const char16_t *end = d.end();
+ QStringView view(begin, end);
+ const char16_t *hit = nullptr;
+ while ((hit = QtPrivate::qustrchr(view, cc)) != end) {
+ indices.push_back(std::distance(begin, hit));
+ view = QStringView(std::next(hit), end);
}
- if (!pos) // Nothing to replace
- break;
-
- replace_helper(indices, pos, 1, after.constData(), after.size());
-
- if (Q_LIKELY(index == -1)) // Nothing left to replace
- break;
- // The call to replace_helper just moved what index points at:
- index += pos*(after.size() - 1);
+ } else {
+ for (qsizetype i = 0; i < d.size; ++i)
+ if (QChar::toCaseFolded(d.data()[i]) == cc)
+ indices.push_back(i);
}
+ if (indices.isEmpty())
+ return *this;
+
+ replace_helper(*this, indices, 1, after);
return *this;
}
@@ -3253,34 +3940,43 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
Replaces every occurrence of the character \a before with the
character \a after and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
*/
QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
{
- if (d.size) {
- const int idx = indexOf(before, 0, cs);
- if (idx != -1) {
- detach();
- const char16_t a = after.unicode();
- char16_t *i = d.data();
- char16_t *const e = i + d.size;
- i += idx;
- *i = a;
- if (cs == Qt::CaseSensitive) {
- const char16_t b = before.unicode();
- while (++i != e) {
- if (*i == b)
- *i = a;
- }
- } else {
- const char16_t b = foldCase(before.unicode());
- while (++i != e) {
- if (foldCase(*i) == b)
- *i = a;
- }
- }
+ const qsizetype idx = indexOf(before, 0, cs);
+ if (idx == -1)
+ return *this;
+
+ const char16_t achar = after.unicode();
+ char16_t bchar = before.unicode();
+
+ auto matchesCIS = [](char16_t beforeChar) {
+ return [beforeChar](char16_t ch) { return foldAndCompare(ch, beforeChar); };
+ };
+
+ auto hit = d.begin() + idx;
+ if (!d.needsDetach()) {
+ *hit++ = achar;
+ if (cs == Qt::CaseSensitive) {
+ std::replace(hit, d.end(), bchar, achar);
+ } else {
+ bchar = foldCase(bchar);
+ std::replace_if(hit, d.end(), matchesCIS(bchar), achar);
}
+ } else {
+ QString other{ d.size, Qt::Uninitialized };
+ auto dest = std::copy(d.begin(), hit, other.d.begin());
+ *dest++ = achar;
+ ++hit;
+ if (cs == Qt::CaseSensitive) {
+ std::replace_copy(hit, d.end(), dest, bchar, achar);
+ } else {
+ bchar = foldCase(bchar);
+ std::replace_copy_if(hit, d.end(), dest, matchesCIS(bchar), achar);
+ }
+
+ swap(other);
}
return *this;
}
@@ -3289,22 +3985,23 @@ QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
\since 4.5
\overload replace()
- Replaces every occurrence of the string \a before with the string \a
- after and returns a reference to this string.
+ Replaces every occurrence in this string of the Latin-1 string viewed
+ by \a before with the Latin-1 string viewed by \a after, and returns a
+ reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\note The text is not rescanned after a replacement.
*/
-QString &QString::replace(QLatin1String before, QLatin1String after, Qt::CaseSensitivity cs)
+QString &QString::replace(QLatin1StringView before, QLatin1StringView after, Qt::CaseSensitivity cs)
{
- int alen = after.size();
- int blen = before.size();
- QVarLengthArray<char16_t> a(alen);
- QVarLengthArray<char16_t> b(blen);
- qt_from_latin1(a.data(), after.latin1(), alen);
- qt_from_latin1(b.data(), before.latin1(), blen);
+ const qsizetype alen = after.size();
+ const qsizetype blen = before.size();
+ if (blen == 1 && alen == 1)
+ return replace(before.front(), after.front(), cs);
+
+ QVarLengthArray<char16_t> a = qt_from_latin1_to_qvla(after);
+ QVarLengthArray<char16_t> b = qt_from_latin1_to_qvla(before);
return replace((const QChar *)b.data(), blen, (const QChar *)a.data(), alen, cs);
}
@@ -3312,19 +4009,21 @@ QString &QString::replace(QLatin1String before, QLatin1String after, Qt::CaseSen
\since 4.5
\overload replace()
- Replaces every occurrence of the string \a before with the string \a
- after and returns a reference to this string.
+ Replaces every occurrence in this string of the Latin-1 string viewed
+ by \a before with the string \a after, and returns a reference to this
+ string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\note The text is not rescanned after a replacement.
*/
-QString &QString::replace(QLatin1String before, const QString &after, Qt::CaseSensitivity cs)
+QString &QString::replace(QLatin1StringView before, const QString &after, Qt::CaseSensitivity cs)
{
- int blen = before.size();
- QVarLengthArray<char16_t> b(blen);
- qt_from_latin1(b.data(), before.latin1(), blen);
+ const qsizetype blen = before.size();
+ if (blen == 1 && after.size() == 1)
+ return replace(before.front(), after.front(), cs);
+
+ QVarLengthArray<char16_t> b = qt_from_latin1_to_qvla(before);
return replace((const QChar *)b.data(), blen, after.constData(), after.d.size, cs);
}
@@ -3335,16 +4034,17 @@ QString &QString::replace(QLatin1String before, const QString &after, Qt::CaseSe
Replaces every occurrence of the string \a before with the string \a
after and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\note The text is not rescanned after a replacement.
*/
-QString &QString::replace(const QString &before, QLatin1String after, Qt::CaseSensitivity cs)
+QString &QString::replace(const QString &before, QLatin1StringView after, Qt::CaseSensitivity cs)
{
- int alen = after.size();
- QVarLengthArray<char16_t> a(alen);
- qt_from_latin1(a.data(), after.latin1(), alen);
+ const qsizetype alen = after.size();
+ if (before.size() == 1 && alen == 1)
+ return replace(before.front(), after.front(), cs);
+
+ QVarLengthArray<char16_t> a = qt_from_latin1_to_qvla(after);
return replace(before.constData(), before.d.size, (const QChar *)a.data(), alen, cs);
}
@@ -3355,444 +4055,513 @@ QString &QString::replace(const QString &before, QLatin1String after, Qt::CaseSe
Replaces every occurrence of the character \a c with the string \a
after and returns a reference to this string.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\note The text is not rescanned after a replacement.
*/
-QString &QString::replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs)
+QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity cs)
{
- int alen = after.size();
- QVarLengthArray<char16_t> a(alen);
- qt_from_latin1(a.data(), after.latin1(), alen);
+ const qsizetype alen = after.size();
+ if (alen == 1)
+ return replace(c, after.front(), cs);
+
+ QVarLengthArray<char16_t> a = qt_from_latin1_to_qvla(after);
return replace(&c, 1, (const QChar *)a.data(), alen, cs);
}
-
/*!
- \relates QString
- Returns \c true if string \a s1 is equal to string \a s2; otherwise
- returns \c false.
+ \fn bool QString::operator==(const QString &lhs, const QString &rhs)
+ \overload operator==()
- The comparison is based exclusively on the numeric Unicode values of
- the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- localeAwareCompare().
-*/
-bool operator==(const QString &s1, const QString &s2) noexcept
-{
- if (s1.d.size != s2.d.size)
- return false;
+ Returns \c true if string \a lhs is equal to string \a rhs; otherwise
+ returns \c false.
- return qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
-}
+ \include qstring.cpp compare-isNull-vs-isEmpty
+
+ \sa {Comparing Strings}
+*/
/*!
+ \fn bool QString::operator==(const QString &lhs, const QLatin1StringView &rhs)
+
\overload operator==()
- Returns \c true if this string is equal to \a other; otherwise
+
+ Returns \c true if \a lhs is equal to \a rhs; otherwise
returns \c false.
*/
-bool QString::operator==(QLatin1String other) const noexcept
-{
- if (size() != other.size())
- return false;
- return qt_compare_strings(*this, other, Qt::CaseSensitive) == 0;
-}
+/*!
+ \fn bool QString::operator==(const QLatin1StringView &lhs, const QString &rhs)
+
+ \overload operator==()
+
+ Returns \c true if \a lhs is equal to \a rhs; otherwise
+ returns \c false.
+*/
-/*! \fn bool QString::operator==(const QByteArray &other) const
+/*! \fn bool QString::operator==(const QString &lhs, const QByteArray &rhs)
\overload operator==()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. This function stops conversion at the
- first NUL character found, or the end of the byte array.
+ The \a rhs byte array is converted to a QUtf8StringView.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
- Returns \c true if this string is lexically equal to the parameter
- string \a other. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
+ Returns \c true if string \a lhs is lexically equal to \a rhs.
+ Otherwise returns \c false.
*/
-/*! \fn bool QString::operator==(const char *other) const
+/*! \fn bool QString::operator==(const QString &lhs, const char * const &rhs)
\overload operator==()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
+*/
+
+/*!
+ \fn bool QString::operator<(const QString &lhs, const QString &rhs)
- \sa QT_NO_CAST_FROM_ASCII
+ \overload operator<()
+
+ Returns \c true if string \a lhs is lexically less than string
+ \a rhs; otherwise returns \c false.
+
+ \sa {Comparing Strings}
*/
/*!
- \relates QString
- Returns \c true if string \a s1 is lexically less than string
- \a s2; otherwise returns \c false.
+ \fn bool QString::operator<(const QString &lhs, const QLatin1StringView &rhs)
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
+ \overload operator<()
+
+ Returns \c true if \a lhs is lexically less than \a rhs;
+ otherwise returns \c false.
*/
-bool operator<(const QString &s1, const QString &s2) noexcept
-{
- return qt_compare_strings(s1, s2, Qt::CaseSensitive) < 0;
-}
/*!
- \overload operator<()
+ \fn bool QString::operator<(const QLatin1StringView &lhs, const QString &rhs)
+
+ \overload operator<()
- Returns \c true if this string is lexically less than the parameter
- string called \a other; otherwise returns \c false.
+ Returns \c true if \a lhs is lexically less than \a rhs;
+ otherwise returns \c false.
*/
-bool QString::operator<(QLatin1String other) const noexcept
-{
- return qt_compare_strings(*this, other, Qt::CaseSensitive) < 0;
-}
-/*! \fn bool QString::operator<(const QByteArray &other) const
+/*! \fn bool QString::operator<(const QString &lhs, const QByteArray &rhs)
\overload operator<()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool QString::operator<(const char *other) const
+/*! \fn bool QString::operator<(const QString &lhs, const char * const &rhs)
- Returns \c true if this string is lexically less than string \a other.
+ Returns \c true if string \a lhs is lexically less than string \a rhs.
Otherwise returns \c false.
\overload operator<()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool operator<=(const QString &s1, const QString &s2)
-
- \relates QString
+/*! \fn bool QString::operator<=(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is lexically less than or equal to
- string \a s2; otherwise returns \c false.
+ Returns \c true if string \a lhs is lexically less than or equal to
+ string \a rhs; otherwise returns \c false.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- localeAwareCompare().
+ \sa {Comparing Strings}
*/
-/*! \fn bool QString::operator<=(QLatin1String other) const
+/*!
+ \fn bool QString::operator<=(const QString &lhs, const QLatin1StringView &rhs)
- Returns \c true if this string is lexically less than or equal to
- parameter string \a other. Otherwise returns \c false.
+ \overload operator<=()
+
+ Returns \c true if \a lhs is lexically less than or equal to \a rhs;
+ otherwise returns \c false.
+*/
+
+/*!
+ \fn bool QString::operator<=(const QLatin1StringView &lhs, const QString &rhs)
\overload operator<=()
+
+ Returns \c true if \a lhs is lexically less than or equal to \a rhs;
+ otherwise returns \c false.
*/
-/*! \fn bool QString::operator<=(const QByteArray &other) const
+/*! \fn bool QString::operator<=(const QString &lhs, const QByteArray &rhs)
\overload operator<=()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool QString::operator<=(const char *other) const
+/*! \fn bool QString::operator<=(const QString &lhs, const char * const &rhs)
\overload operator<=()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool operator>(const QString &s1, const QString &s2)
- \relates QString
+/*! \fn bool QString::operator>(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is lexically greater than string \a s2;
+ Returns \c true if string \a lhs is lexically greater than string \a rhs;
otherwise returns \c false.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- localeAwareCompare().
+ \sa {Comparing Strings}
*/
/*!
- \overload operator>()
+ \fn bool QString::operator>(const QString &lhs, const QLatin1StringView &rhs)
+
+ \overload operator>()
- Returns \c true if this string is lexically greater than the parameter
- string \a other; otherwise returns \c false.
+ Returns \c true if \a lhs is lexically greater than \a rhs;
+ otherwise returns \c false.
*/
-bool QString::operator>(QLatin1String other) const noexcept
-{
- return qt_compare_strings(*this, other, Qt::CaseSensitive) > 0;
-}
-/*! \fn bool QString::operator>(const QByteArray &other) const
+/*!
+ \fn bool QString::operator>(const QLatin1StringView &lhs, const QString &rhs)
\overload operator>()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ Returns \c true if \a lhs is lexically greater than \a rhs;
+ otherwise returns \c false.
+*/
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+/*! \fn bool QString::operator>(const QString &lhs, const QByteArray &rhs)
+
+ \overload operator>()
+
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
+
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool QString::operator>(const char *other) const
+/*! \fn bool QString::operator>(const QString &lhs, const char * const &rhs)
\overload operator>()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool operator>=(const QString &s1, const QString &s2)
- \relates QString
+/*! \fn bool QString::operator>=(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is lexically greater than or equal to
- string \a s2; otherwise returns \c false.
+ Returns \c true if string \a lhs is lexically greater than or equal to
+ string \a rhs; otherwise returns \c false.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- localeAwareCompare().
+ \sa {Comparing Strings}
*/
-/*! \fn bool QString::operator>=(QLatin1String other) const
+/*!
+ \fn bool QString::operator>=(const QString &lhs, const QLatin1StringView &rhs)
+
+ \overload operator>=()
+
+ Returns \c true if \a lhs is lexically greater than or equal to \a rhs;
+ otherwise returns \c false.
+*/
- Returns \c true if this string is lexically greater than or equal to parameter
- string \a other. Otherwise returns \c false.
+/*!
+ \fn bool QString::operator>=(const QLatin1StringView &lhs, const QString &rhs)
\overload operator>=()
+
+ Returns \c true if \a lhs is lexically greater than or equal to \a rhs;
+ otherwise returns \c false.
*/
-/*! \fn bool QString::operator>=(const QByteArray &other) const
+/*! \fn bool QString::operator>=(const QString &lhs, const QByteArray &rhs)
\overload operator>=()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded in
- the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool QString::operator>=(const char *other) const
+/*! \fn bool QString::operator>=(const QString &lhs, const char * const &rhs)
\overload operator>=()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool operator!=(const QString &s1, const QString &s2)
- \relates QString
+/*! \fn bool QString::operator!=(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is not equal to string \a s2;
+ Returns \c true if string \a lhs is not equal to string \a rhs;
otherwise returns \c false.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- localeAwareCompare().
+ \sa {Comparing Strings}
*/
-/*! \fn bool QString::operator!=(QLatin1String other) const
+/*! \fn bool QString::operator!=(const QString &lhs, const QLatin1StringView &rhs)
- Returns \c true if this string is not equal to parameter string \a other.
+ Returns \c true if string \a lhs is not equal to string \a rhs.
Otherwise returns \c false.
\overload operator!=()
*/
-/*! \fn bool QString::operator!=(const QByteArray &other) const
+/*! \fn bool QString::operator!=(const QString &lhs, const QByteArray &rhs)
\overload operator!=()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
-/*! \fn bool QString::operator!=(const char *other) const
+/*! \fn bool QString::operator!=(const QString &lhs, const char * const &rhs)
\overload operator!=()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this operator by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
+*/
+
+/*! \fn bool QString::operator==(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is equal to the UTF-8 encoding of
+ \a rhs; otherwise returns \c false.
- \sa QT_NO_CAST_FROM_ASCII
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator!=(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is not equal to the UTF-8 encoding of
+ \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator<(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is lexically less than the UTF-8 encoding
+ of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator>(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is lexically greater than the UTF-8
+ encoding of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator<=(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is lexically less than or equal to the
+ UTF-8 encoding of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator>=(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is greater than or equal to the UTF-8
+ encoding of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
- Returns the index position of the first occurrence of the string \a
- str in this string, searching forward from index position \a
- from. Returns -1 if \a str is not found.
+ \include qstring.qdocinc {qstring-first-index-of} {string} {str}
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
\snippet qstring/main.cpp 24
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
+ \include qstring.qdocinc negative-index-start-search-from-end
\sa lastIndexOf(), contains(), count()
*/
-int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
+qsizetype QString::indexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
+ return QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs);
}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
- \fn int QString::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QString::indexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
\since 5.14
\overload indexOf()
- Returns the index position of the first occurrence of the string view \a str
- in this string, searching forward from index position \a from.
- Returns -1 if \a str is not found.
+ \include qstring.qdocinc {qstring-first-index-of} {string view} {str}
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
+ \include qstring.qdocinc negative-index-start-search-from-end
\sa QStringView::indexOf(), lastIndexOf(), contains(), count()
*/
/*!
\since 4.5
- Returns the index position of the first occurrence of the string \a
- str in this string, searching forward from index position \a
- from. Returns -1 if \a str is not found.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include {qstring.qdocinc} {qstring-first-index-of} {Latin-1 string viewed by} {str}
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
\snippet qstring/main.cpp 24
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
+ \include qstring.qdocinc negative-index-start-search-from-end
\sa lastIndexOf(), contains(), count()
*/
-int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
+qsizetype QString::indexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs));
+ return QtPrivate::findString(QStringView(unicode(), size()), from, str, cs);
}
/*!
+ \fn qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
\overload indexOf()
- Returns the index position of the first occurrence of the
- character \a ch in the string, searching forward from index
- position \a from. Returns -1 if \a ch could not be found.
+ \include qstring.qdocinc {qstring-first-index-of} {character} {ch}
+*/
+
+/*!
+ \include qstring.qdocinc {qstring-last-index-of} {string} {str}
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if \a str is not found.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ Example:
+
+ \snippet qstring/main.cpp 29
+
+ \note When searching for a 0-length \a str, the match at the end of
+ the data is excluded from the search by a negative \a from, even
+ though \c{-1} is normally thought of as searching from the end of the
+ string: the match at the end is \e after the last character, so it is
+ excluded. To include such a final empty match, either give a positive
+ value for \a from or omit the \a from parameter entirely.
+
+ \sa indexOf(), contains(), count()
*/
-int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
+qsizetype QString::lastIndexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(qFindChar(QStringView(unicode(), length()), ch, from, cs));
+ return QtPrivate::lastIndexOf(QStringView(*this), from, str, cs);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
+ \fn qsizetype QString::lastIndexOf(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.2
+ \overload lastIndexOf()
+
Returns the index position of the last occurrence of the string \a
- str in this string, searching backward from index position \a
- from. If \a from is -1 (default), the search starts at the last
- character; if \a from is -2, at the next to last character and so
- on. Returns -1 if \a str is not found.
+ str in this string. Returns -1 if \a str is not found.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
@@ -3800,74 +4569,109 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
\sa indexOf(), contains(), count()
*/
-int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::lastIndexOf(QStringView(*this), from, str, cs));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.5
\overload lastIndexOf()
- Returns the index position of the last occurrence of the string \a
- str in this string, searching backward from index position \a
- from. If \a from is -1 (default), the search starts at the last
- character; if \a from is -2, at the next to last character and so
- on. Returns -1 if \a str is not found.
+ \include qstring.qdocinc {qstring-last-index-of} {Latin-1 string viewed by} {str}
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if \a str is not found.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
\snippet qstring/main.cpp 29
+ \note When searching for a 0-length \a str, the match at the end of
+ the data is excluded from the search by a negative \a from, even
+ though \c{-1} is normally thought of as searching from the end of the
+ string: the match at the end is \e after the last character, so it is
+ excluded. To include such a final empty match, either give a positive
+ value for \a from or omit the \a from parameter entirely.
+
\sa indexOf(), contains(), count()
*/
-int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
+qsizetype QString::lastIndexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(QtPrivate::lastIndexOf(*this, from, str, cs));
+ return QtPrivate::lastIndexOf(*this, from, str, cs);
}
/*!
+ \fn qsizetype QString::lastIndexOf(QLatin1StringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.2
\overload lastIndexOf()
- Returns the index position of the last occurrence of the character
- \a ch, searching backward from position \a from.
+ Returns the index position of the last occurrence of the string \a
+ str in this string. Returns -1 if \a str is not found.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ Example:
+
+ \snippet qstring/main.cpp 29
+
+ \sa indexOf(), contains(), count()
*/
-int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(qLastIndexOf(QStringView(*this), ch, from, cs));
-}
/*!
- \fn int QString::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QString::lastIndexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
+ \overload lastIndexOf()
+
+ \include qstring.qdocinc {qstring-last-index-of} {character} {ch}
+*/
+
+/*!
+ \fn QString::lastIndexOf(QChar ch, Qt::CaseSensitivity) const
+ \since 6.3
+ \overload lastIndexOf()
+*/
+
+/*!
+ \fn qsizetype QString::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
\since 5.14
\overload lastIndexOf()
- Returns the index position of the last occurrence of the string view \a
- str in this string, searching backward from index position \a
- from. If \a from is -1 (default), the search starts at the last
- character; if \a from is -2, at the next to last character and so
- on. Returns -1 if \a str is not found.
+ \include qstring.qdocinc {qstring-last-index-of} {string view} {str}
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if \a str is not found.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \note When searching for a 0-length \a str, the match at the end of
+ the data is excluded from the search by a negative \a from, even
+ though \c{-1} is normally thought of as searching from the end of the
+ string: the match at the end is \e after the last character, so it is
+ excluded. To include such a final empty match, either give a positive
+ value for \a from or omit the \a from parameter entirely.
\sa indexOf(), contains(), count()
*/
+/*!
+ \fn qsizetype QString::lastIndexOf(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.2
+ \overload lastIndexOf()
+
+ Returns the index position of the last occurrence of the string view \a
+ str in this string. Returns -1 if \a str is not found.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa indexOf(), contains(), count()
+*/
#if QT_CONFIG(regularexpression)
struct QStringCapture
{
- int pos;
- int len;
+ qsizetype pos;
+ qsizetype len;
int no;
};
Q_DECLARE_TYPEINFO(QStringCapture, Q_PRIMITIVE_TYPE);
@@ -3893,7 +4697,7 @@ Q_DECLARE_TYPEINFO(QStringCapture, Q_PRIMITIVE_TYPE);
QString &QString::replace(const QRegularExpression &re, const QString &after)
{
if (!re.isValid()) {
- qWarning("QString::replace: invalid QRegularExpression object");
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString::replace");
return *this;
}
@@ -3902,18 +4706,18 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
if (!iterator.hasNext()) // no matches at all
return *this;
- reallocData(uint(d.size) + 1u);
+ reallocData(d.size, QArrayData::KeepSize);
- int numCaptures = re.captureCount();
+ qsizetype numCaptures = re.captureCount();
// 1. build the backreferences list, holding where the backreferences
// are in the replacement string
- QList<QStringCapture> backReferences;
- const int al = after.length();
+ QVarLengthArray<QStringCapture> backReferences;
+ const qsizetype al = after.size();
const QChar *ac = after.unicode();
- for (int i = 0; i < al - 1; i++) {
- if (ac[i] == QLatin1Char('\\')) {
+ for (qsizetype i = 0; i < al - 1; i++) {
+ if (ac[i] == u'\\') {
int no = ac[i + 1].digitValue();
if (no > 0 && no <= numCaptures) {
QStringCapture backReference;
@@ -3938,33 +4742,34 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
// - the part before the match
// - the after string, with the proper replacements for the backreferences
- int newLength = 0; // length of the new string, with all the replacements
- int lastEnd = 0;
- QList<QStringRef> chunks;
+ qsizetype newLength = 0; // length of the new string, with all the replacements
+ qsizetype lastEnd = 0;
+ QVarLengthArray<QStringView> chunks;
+ const QStringView copyView{ copy }, afterView{ after };
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
- int len;
+ qsizetype len;
// add the part before the match
len = match.capturedStart() - lastEnd;
if (len > 0) {
- chunks << copy.midRef(lastEnd, len);
+ chunks << copyView.mid(lastEnd, len);
newLength += len;
}
lastEnd = 0;
// add the after string, with replacements for the backreferences
- for (const QStringCapture &backReference : qAsConst(backReferences)) {
+ for (const QStringCapture &backReference : std::as_const(backReferences)) {
// part of "after" before the backreference
len = backReference.pos - lastEnd;
if (len > 0) {
- chunks << after.midRef(lastEnd, len);
+ chunks << afterView.mid(lastEnd, len);
newLength += len;
}
// backreference itself
len = match.capturedLength(backReference.no);
if (len > 0) {
- chunks << copy.midRef(match.capturedStart(backReference.no), len);
+ chunks << copyView.mid(match.capturedStart(backReference.no), len);
newLength += len;
}
@@ -3972,9 +4777,9 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
}
// add the last part of the after string
- len = after.length() - lastEnd;
+ len = afterView.size() - lastEnd;
if (len > 0) {
- chunks << after.midRef(lastEnd, len);
+ chunks << afterView.mid(lastEnd, len);
newLength += len;
}
@@ -3982,18 +4787,18 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
}
// 3. trailing string after the last match
- if (copy.length() > lastEnd) {
- chunks << copy.midRef(lastEnd);
- newLength += copy.length() - lastEnd;
+ if (copyView.size() > lastEnd) {
+ chunks << copyView.mid(lastEnd);
+ newLength += copyView.size() - lastEnd;
}
// 4. assemble the chunks together
resize(newLength);
- int i = 0;
+ qsizetype i = 0;
QChar *uc = data();
- for (const QStringRef &chunk : qAsConst(chunks)) {
- int len = chunk.length();
- memcpy(uc + i, chunk.unicode(), len * sizeof(QChar));
+ for (const QStringView &chunk : std::as_const(chunks)) {
+ qsizetype len = chunk.size();
+ memcpy(uc + i, chunk.constData(), len * sizeof(QChar));
i += len;
}
@@ -4005,16 +4810,14 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
Returns the number of (potentially overlapping) occurrences of
the string \a str in this string.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa contains(), indexOf()
*/
-int QString::count(const QString &str, Qt::CaseSensitivity cs) const
+qsizetype QString::count(const QString &str, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(QtPrivate::count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
+ return QtPrivate::count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs);
}
/*!
@@ -4022,52 +4825,45 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const
Returns the number of occurrences of character \a ch in the string.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa contains(), indexOf()
*/
-int QString::count(QChar ch, Qt::CaseSensitivity cs) const
+qsizetype QString::count(QChar ch, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(QtPrivate::count(QStringView(unicode(), size()), ch, cs));
+ return QtPrivate::count(QStringView(unicode(), size()), ch, cs);
}
/*!
\since 6.0
\overload count()
Returns the number of (potentially overlapping) occurrences of the
- string reference \a str in this string.
+ string view \a str in this string.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa contains(), indexOf()
*/
-int QString::count(QStringView str, Qt::CaseSensitivity cs) const
+qsizetype QString::count(QStringView str, Qt::CaseSensitivity cs) const
{
- // ### Qt6: qsizetype
- return int(QtPrivate::count(*this, str, cs));
+ return QtPrivate::count(*this, str, cs);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
Returns \c true if this string contains an occurrence of the string
\a str; otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
Example:
\snippet qstring/main.cpp 17
\sa indexOf(), count()
*/
-#endif // QT_STRINGVIEW_LEVEL < 2
-/*! \fn bool QString::contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+/*! \fn bool QString::contains(QLatin1StringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.3
\overload contains()
@@ -4084,20 +4880,6 @@ int QString::count(QStringView str, Qt::CaseSensitivity cs) const
character \a ch; otherwise returns \c false.
*/
-#if QT_STRINGVIEW_LEVEL < 2
-/*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 4.8
-
- Returns \c true if this string contains an occurrence of the string
- reference \a str; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), count()
-*/
-#endif // QT_STRINGVIEW_LEVEL < 2
-
/*! \fn bool QString::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.14
\overload contains()
@@ -4105,8 +4887,7 @@ int QString::count(QStringView str, Qt::CaseSensitivity cs) const
Returns \c true if this string contains an occurrence of the string view
\a str; otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa indexOf(), count()
*/
@@ -4127,22 +4908,9 @@ int QString::count(QStringView str, Qt::CaseSensitivity cs) const
\snippet qstring/main.cpp 93
*/
-int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
+qsizetype QString::indexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
{
- if (!re.isValid()) {
- qWarning("QString::indexOf: invalid QRegularExpression object");
- return -1;
- }
-
- QRegularExpressionMatch match = re.match(*this, from);
- if (match.hasMatch()) {
- const int ret = match.capturedStart();
- if (rmatch)
- *rmatch = std::move(match);
- return ret;
- }
-
- return -1;
+ return QtPrivate::indexOf(QStringView(*this), this, re, from, rmatch);
}
/*!
@@ -4150,7 +4918,11 @@ int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionM
Returns the index position of the last match of the regular
expression \a re in the string, which starts before the index
- position \a from. Returns -1 if \a re didn't match anywhere.
+ position \a from.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if \a re didn't match anywhere.
If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
@@ -4159,31 +4931,44 @@ int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionM
Example:
\snippet qstring/main.cpp 94
+
+ \note Due to how the regular expression matching algorithm works,
+ this function will actually match repeatedly from the beginning of
+ the string until the position \a from is reached.
+
+ \note When searching for a regular expression \a re that may match
+ 0 characters, the match at the end of the data is excluded from the
+ search by a negative \a from, even though \c{-1} is normally
+ thought of as searching from the end of the string: the match at
+ the end is \e after the last character, so it is excluded. To
+ include such a final empty match, either give a positive value for
+ \a from or omit the \a from parameter entirely.
*/
-int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
+qsizetype QString::lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
{
- if (!re.isValid()) {
- qWarning("QString::lastIndexOf: invalid QRegularExpression object");
- return -1;
- }
+ return QtPrivate::lastIndexOf(QStringView(*this), this, re, from, rmatch);
+}
- int endpos = (from < 0) ? (size() + from + 1) : (from + 1);
- QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
- int lastIndex = -1;
- while (iterator.hasNext()) {
- QRegularExpressionMatch match = iterator.next();
- int start = match.capturedStart();
- if (start < endpos) {
- lastIndex = start;
- if (rmatch)
- *rmatch = std::move(match);
- } else {
- break;
- }
- }
+/*!
+ \fn qsizetype QString::lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
+ \since 6.2
+ \overload lastIndexOf()
- return lastIndex;
-}
+ Returns the index position of the last match of the regular
+ expression \a re in the string. Returns -1 if \a re didn't match anywhere.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ Example:
+
+ \snippet qstring/main.cpp 94
+
+ \note Due to how the regular expression matching algorithm works,
+ this function will actually match repeatedly from the beginning of
+ the string until the end of the string is reached.
+*/
/*!
\since 5.1
@@ -4200,15 +4985,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpress
bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const
{
- if (!re.isValid()) {
- qWarning("QString::contains: invalid QRegularExpression object");
- return false;
- }
- QRegularExpressionMatch m = re.match(*this);
- bool hasMatch = m.hasMatch();
- if (hasMatch && rmatch)
- *rmatch = std::move(m);
- return hasMatch;
+ return QtPrivate::contains(QStringView(*this), this, re, rmatch);
}
/*!
@@ -4218,38 +4995,31 @@ bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *rm
Returns the number of times the regular expression \a re matches
in the string.
- This function counts overlapping matches, so in the example
- below, there are four instances of "ana" or "ama":
+ For historical reasons, this function counts overlapping matches,
+ so in the example below, there are four instances of "ana" or
+ "ama":
\snippet qstring/main.cpp 95
+
+ This behavior is different from simply iterating over the matches
+ in the string using QRegularExpressionMatchIterator.
+
+ \sa QRegularExpression::globalMatch()
*/
-int QString::count(const QRegularExpression &re) const
+qsizetype QString::count(const QRegularExpression &re) const
{
- if (!re.isValid()) {
- qWarning("QString::count: invalid QRegularExpression object");
- return 0;
- }
- int count = 0;
- int index = -1;
- int len = length();
- while (index < len - 1) {
- QRegularExpressionMatch match = re.match(*this, index + 1);
- if (!match.hasMatch())
- break;
- index = match.capturedStart();
- count++;
- }
- return count;
+ return QtPrivate::count(QStringView(*this), re);
}
#endif // QT_CONFIG(regularexpression)
-/*! \fn int QString::count() const
-
+#if QT_DEPRECATED_SINCE(6, 4)
+/*! \fn qsizetype QString::count() const
+ \deprecated [6.4] Use size() or length() instead.
\overload count()
Same as size().
*/
-
+#endif
/*!
\enum QString::SectionFlag
@@ -4279,7 +5049,7 @@ int QString::count(const QRegularExpression &re) const
*/
/*!
- \fn QString QString::section(QChar sep, int start, int end = -1, SectionFlags flags) const
+ \fn QString QString::section(QChar sep, qsizetype start, qsizetype end = -1, SectionFlags flags) const
This function returns a section of the string.
@@ -4315,19 +5085,19 @@ int QString::count(const QRegularExpression &re) const
\sa split()
*/
-QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const
+QString QString::section(const QString &sep, qsizetype start, qsizetype end, SectionFlags flags) const
{
- const QList<QStringRef> sections = splitRef(
+ const QList<QStringView> sections = QStringView{ *this }.split(
sep, Qt::KeepEmptyParts, (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
- const int sectionsSize = sections.size();
+ const qsizetype sectionsSize = sections.size();
if (!(flags & SectionSkipEmpty)) {
if (start < 0)
start += sectionsSize;
if (end < 0)
end += sectionsSize;
} else {
- int skip = 0;
- for (int k = 0; k < sectionsSize; ++k) {
+ qsizetype skip = 0;
+ for (qsizetype k = 0; k < sectionsSize; ++k) {
if (sections.at(k).isEmpty())
skip++;
}
@@ -4340,14 +5110,14 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
return QString();
QString ret;
- int first_i = start, last_i = end;
- for (int x = 0, i = 0; x <= end && i < sectionsSize; ++i) {
- const QStringRef &section = sections.at(i);
+ qsizetype first_i = start, last_i = end;
+ for (qsizetype x = 0, i = 0; x <= end && i < sectionsSize; ++i) {
+ const QStringView &section = sections.at(i);
const bool empty = section.isEmpty();
if (x >= start) {
- if(x == start)
+ if (x == start)
first_i = i;
- if(x == end)
+ if (x == end)
last_i = i;
if (x > start && i > 0)
ret += sep;
@@ -4363,19 +5133,20 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
return ret;
}
-#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression))
+#if QT_CONFIG(regularexpression)
class qt_section_chunk {
public:
qt_section_chunk() {}
- qt_section_chunk(int l, QStringRef s) : length(l), string(std::move(s)) {}
- int length;
- QStringRef string;
+ qt_section_chunk(qsizetype l, QStringView s) : length(l), string(std::move(s)) {}
+ qsizetype length;
+ QStringView string;
};
-Q_DECLARE_TYPEINFO(qt_section_chunk, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(qt_section_chunk, Q_RELOCATABLE_TYPE);
-static QString extractSections(const QList<qt_section_chunk> &sections, int start, int end, QString::SectionFlags flags)
+static QString extractSections(QSpan<qt_section_chunk> sections, qsizetype start, qsizetype end,
+ QString::SectionFlags flags)
{
- const int sectionsSize = sections.size();
+ const qsizetype sectionsSize = sections.size();
if (!(flags & QString::SectionSkipEmpty)) {
if (start < 0)
@@ -4383,10 +5154,10 @@ static QString extractSections(const QList<qt_section_chunk> &sections, int star
if (end < 0)
end += sectionsSize;
} else {
- int skip = 0;
- for (int k = 0; k < sectionsSize; ++k) {
- const qt_section_chunk &section = sections.at(k);
- if (section.length == section.string.length())
+ qsizetype skip = 0;
+ for (qsizetype k = 0; k < sectionsSize; ++k) {
+ const qt_section_chunk &section = sections[k];
+ if (section.length == section.string.size())
skip++;
}
if (start < 0)
@@ -4398,11 +5169,11 @@ static QString extractSections(const QList<qt_section_chunk> &sections, int star
return QString();
QString ret;
- int x = 0;
- int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sectionsSize; ++i) {
- const qt_section_chunk &section = sections.at(i);
- const bool empty = (section.length == section.string.length());
+ qsizetype x = 0;
+ qsizetype first_i = start, last_i = end;
+ for (qsizetype i = 0; x <= end && i < sectionsSize; ++i) {
+ const qt_section_chunk &section = sections[i];
+ const bool empty = (section.length == section.string.size());
if (x >= start) {
if (x == start)
first_i = i;
@@ -4418,21 +5189,19 @@ static QString extractSections(const QList<qt_section_chunk> &sections, int star
}
if ((flags & QString::SectionIncludeLeadingSep) && first_i >= 0) {
- const qt_section_chunk &section = sections.at(first_i);
+ const qt_section_chunk &section = sections[first_i];
ret.prepend(section.string.left(section.length));
}
if ((flags & QString::SectionIncludeTrailingSep)
&& last_i < sectionsSize - 1) {
- const qt_section_chunk &section = sections.at(last_i+1);
+ const qt_section_chunk &section = sections[last_i + 1];
ret += section.string.left(section.length);
}
return ret;
}
-#endif
-#if QT_CONFIG(regularexpression)
/*!
\overload section()
\since 5.0
@@ -4447,10 +5216,10 @@ static QString extractSections(const QList<qt_section_chunk> &sections, int star
\sa split(), simplified()
*/
-QString QString::section(const QRegularExpression &re, int start, int end, SectionFlags flags) const
+QString QString::section(const QRegularExpression &re, qsizetype start, qsizetype end, SectionFlags flags) const
{
if (!re.isValid()) {
- qWarning("QString::section: invalid QRegularExpression object");
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString::section");
return QString();
}
@@ -4462,67 +5231,63 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
if (flags & SectionCaseInsensitiveSeps)
sep.setPatternOptions(sep.patternOptions() | QRegularExpression::CaseInsensitiveOption);
- QList<qt_section_chunk> sections;
- int n = length(), m = 0, last_m = 0, last_len = 0;
+ QVarLengthArray<qt_section_chunk> sections;
+ qsizetype n = size(), m = 0, last_m = 0, last_len = 0;
QRegularExpressionMatchIterator iterator = sep.globalMatch(*this);
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
m = match.capturedStart();
- sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, m - last_m)));
+ sections.append(qt_section_chunk(last_len, QStringView{ *this }.sliced(last_m, m - last_m)));
last_m = m;
last_len = match.capturedLength();
}
- sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, n - last_m)));
+ sections.append(qt_section_chunk(last_len, QStringView{ *this }.sliced(last_m, n - last_m)));
return extractSections(sections, start, end, flags);
}
#endif // QT_CONFIG(regularexpression)
/*!
+ \fn QString QString::left(qsizetype n) const &
+ \fn QString QString::left(qsizetype n) &&
+
Returns a substring that contains the \a n leftmost characters
of the string.
- \obsolete Use first() instead in new code.
+ If you know that \a n cannot be out of bounds, use first() instead in new
+ code, because it is faster.
The entire string is returned if \a n is greater than or equal
to size(), or less than zero.
- \snippet qstring/main.cpp 31
-
\sa first(), last(), startsWith(), chopped(), chop(), truncate()
*/
-QString QString::left(int n) const
-{
- if (uint(n) >= uint(size()))
- return *this;
- return QString((const QChar*) d.data(), n);
-}
/*!
+ \fn QString QString::right(qsizetype n) const &
+ \fn QString QString::right(qsizetype n) &&
+
Returns a substring that contains the \a n rightmost characters
of the string.
- \obsolete Use last() instead in new code.
+ If you know that \a n cannot be out of bounds, use last() instead in new
+ code, because it is faster.
The entire string is returned if \a n is greater than or equal
to size(), or less than zero.
- \snippet qstring/main.cpp 48
-
- \sa endsWith(), last(), first(), sliced(), chopped(), chop(), truncate()
+ \sa endsWith(), last(), first(), sliced(), chopped(), chop(), truncate(), slice()
*/
-QString QString::right(int n) const
-{
- if (uint(n) >= uint(size()))
- return *this;
- return QString(constData() + size() - n, n);
-}
/*!
+ \fn QString QString::mid(qsizetype position, qsizetype n) const &
+ \fn QString QString::mid(qsizetype position, qsizetype n) &&
+
Returns a string that contains \a n characters of this string,
starting at the specified \a position index.
- \obsolete Use sliced() instead in new code.
+ If you know that \a position and \a n cannot be out of bounds, use sliced()
+ instead in new code, because it is faster.
Returns a null string if the \a position index exceeds the
length of the string. If there are less than \a n characters
@@ -4530,14 +5295,9 @@ QString QString::right(int n) const
\a n is -1 (default), the function returns all characters that
are available from the specified \a position.
- Example:
-
- \snippet qstring/main.cpp 34
-
- \sa first(), last(), sliced(), chopped(), chop(), truncate()
+ \sa first(), last(), sliced(), chopped(), chop(), truncate(), slice()
*/
-
-QString QString::mid(int position, int n) const
+QString QString::mid(qsizetype position, qsizetype n) const &
{
qsizetype p = position;
qsizetype l = n;
@@ -4546,22 +5306,37 @@ QString QString::mid(int position, int n) const
case QContainerImplHelper::Null:
return QString();
case QContainerImplHelper::Empty:
- {
- QPair<Data *, char16_t *> pair = Data::allocate(0);
- DataPointer empty = { pair.first, pair.second, 0 };
- return QString(empty);
- }
+ return QString(DataPointer::fromRawData(&_empty, 0));
case QContainerImplHelper::Full:
return *this;
case QContainerImplHelper::Subset:
- return QString(constData() + p, l);
+ return sliced(p, l);
+ }
+ Q_UNREACHABLE_RETURN(QString());
+}
+
+QString QString::mid(qsizetype position, qsizetype n) &&
+{
+ qsizetype p = position;
+ qsizetype l = n;
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &p, &l)) {
+ case QContainerImplHelper::Null:
+ return QString();
+ case QContainerImplHelper::Empty:
+ resize(0); // keep capacity if we've reserve()d
+ [[fallthrough]];
+ case QContainerImplHelper::Full:
+ return std::move(*this);
+ case QContainerImplHelper::Subset:
+ return std::move(*this).sliced(p, l);
}
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString());
}
/*!
- \fn QString QString::first(qsizetype n) const
+ \fn QString QString::first(qsizetype n) const &
+ \fn QString QString::first(qsizetype n) &&
\since 6.0
Returns a string that contains the first \a n characters
@@ -4569,22 +5344,28 @@ QString QString::mid(int position, int n) const
\note The behavior is undefined when \a n < 0 or \a n > size().
- \sa last(), sliced(), from(), startsWith(), chopped(), chop(), truncate()
+ \snippet qstring/main.cpp 31
+
+ \sa last(), sliced(), startsWith(), chopped(), chop(), truncate(), slice()
*/
/*!
- \fn QString QString::last(qsizetype n) const
+ \fn QString QString::last(qsizetype n) const &
+ \fn QString QString::last(qsizetype n) &&
\since 6.0
Returns the string that contains the last \a n characters of this string.
\note The behavior is undefined when \a n < 0 or \a n > size().
- \sa first(), sliced(), from(), endsWith(), chopped(), chop(), truncate()
+ \snippet qstring/main.cpp 48
+
+ \sa first(), sliced(), endsWith(), chopped(), chop(), truncate(), slice()
*/
/*!
- \fn QString QString::sliced(qsizetype pos, qsizetype n) const
+ \fn QString QString::sliced(qsizetype pos, qsizetype n) const &
+ \fn QString QString::sliced(qsizetype pos, qsizetype n) &&
\since 6.0
Returns a string that contains \a n characters of this string,
@@ -4593,23 +5374,64 @@ QString QString::mid(int position, int n) const
\note The behavior is undefined when \a pos < 0, \a n < 0,
or \a pos + \a n > size().
- \sa first(), last(), chopped(), chop(), truncate()
+ \snippet qstring/main.cpp 34
+
+ \sa first(), last(), chopped(), chop(), truncate(), slice()
*/
+QString QString::sliced_helper(QString &str, qsizetype pos, qsizetype n)
+{
+ if (n == 0)
+ return QString(DataPointer::fromRawData(&_empty, 0));
+ DataPointer d = std::move(str.d).sliced(pos, n);
+ d.data()[n] = 0;
+ return QString(std::move(d));
+}
/*!
- \fn QString QString::from(qsizetype pos) const
+ \fn QString QString::sliced(qsizetype pos) const &
+ \fn QString QString::sliced(qsizetype pos) &&
\since 6.0
+ \overload
Returns a string that contains the portion of this string starting at
position \a pos and extending to its end.
\note The behavior is undefined when \a pos < 0 or \a pos > size().
- \sa first(), last(), sliced(), chopped(), chop(), truncate()
+ \sa first(), last(), chopped(), chop(), truncate(), slice()
+*/
+
+/*!
+ \fn QString &QString::slice(qsizetype pos, qsizetype n)
+ \since 6.8
+
+ Modifies this string to start at position \a pos, extending for \a n
+ characters (code points), and returns a reference to this string.
+
+ \note The behavior is undefined if \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+
+ \snippet qstring/main.cpp 86
+
+ \sa sliced(), first(), last(), chopped(), chop(), truncate()
*/
/*!
- \fn QString QString::chopped(int len) const
+ \fn QString &QString::slice(qsizetype pos)
+ \since 6.8
+ \overload
+
+ Modifies this string to start at position \a pos and extending to its end,
+ and returns a reference to this string.
+
+ \note The behavior is undefined if \a pos < 0 or \a pos > size().
+
+ \sa sliced(), first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QString QString::chopped(qsizetype len) const &
+ \fn QString QString::chopped(qsizetype len) &&
\since 5.10
Returns a string that contains the size() - \a len leftmost characters
@@ -4617,16 +5439,14 @@ QString QString::mid(int position, int n) const
\note The behavior is undefined if \a len is negative or greater than size().
- \sa endsWith(), left(), right(), mid(), chop(), truncate()
+ \sa endsWith(), first(), last(), sliced(), chop(), truncate(), slice()
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns \c true if the string starts with \a s; otherwise returns
\c false.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\snippet qstring/main.cpp 65
@@ -4634,16 +5454,15 @@ QString QString::mid(int position, int n) const
*/
bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(*this, s, cs);
+ return qt_starts_with_impl(QStringView(*this), QStringView(s), cs);
}
-#endif
/*!
\overload startsWith()
*/
-bool QString::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const
+bool QString::startsWith(QLatin1StringView s, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(*this, s, cs);
+ return qt_starts_with_impl(QStringView(*this), s, cs);
}
/*!
@@ -4654,7 +5473,11 @@ bool QString::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const
*/
bool QString::startsWith(QChar c, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(*this, c, cs);
+ if (!size())
+ return false;
+ if (cs == Qt::CaseSensitive)
+ return at(0) == c;
+ return foldCase(at(0)) == foldCase(c);
}
/*!
@@ -4662,22 +5485,19 @@ bool QString::startsWith(QChar c, Qt::CaseSensitivity cs) const
\since 5.10
\overload
- Returns \c true if the string starts with the string-view \a str;
+ Returns \c true if the string starts with the string view \a str;
otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (default), the search is case-sensitive;
- otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa endsWith()
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns \c true if the string ends with \a s; otherwise returns
\c false.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\snippet qstring/main.cpp 20
@@ -4685,9 +5505,8 @@ bool QString::startsWith(QChar c, Qt::CaseSensitivity cs) const
*/
bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(*this, s, cs);
+ return qt_ends_with_impl(QStringView(*this), QStringView(s), cs);
}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\fn bool QString::endsWith(QStringView str, Qt::CaseSensitivity cs) const
@@ -4696,8 +5515,7 @@ bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
Returns \c true if the string ends with the string view \a str;
otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa startsWith()
*/
@@ -4705,9 +5523,9 @@ bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
/*!
\overload endsWith()
*/
-bool QString::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const
+bool QString::endsWith(QLatin1StringView s, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(*this, s, cs);
+ return qt_ends_with_impl(QStringView(*this), s, cs);
}
/*!
@@ -4718,7 +5536,32 @@ bool QString::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const
*/
bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(*this, c, cs);
+ if (!size())
+ return false;
+ if (cs == Qt::CaseSensitive)
+ return at(size() - 1) == c;
+ return foldCase(at(size() - 1)) == foldCase(c);
+}
+
+static bool checkCase(QStringView s, QUnicodeTables::Case c) noexcept
+{
+ QStringIterator it(s);
+ while (it.hasNext()) {
+ const char32_t uc = it.next();
+ if (qGetProp(uc)->cases[c].diff)
+ return false;
+ }
+ return true;
+}
+
+bool QtPrivate::isLower(QStringView s) noexcept
+{
+ return checkCase(s, QUnicodeTables::LowerCase);
+}
+
+bool QtPrivate::isUpper(QStringView s) noexcept
+{
+ return checkCase(s, QUnicodeTables::UpperCase);
}
/*!
@@ -4736,15 +5579,7 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const
*/
bool QString::isUpper() const
{
- QStringIterator it(*this);
-
- while (it.hasNext()) {
- const char32_t uc = it.nextUnchecked();
- if (qGetProp(uc)->cases[QUnicodeTables::UpperCase].diff)
- return false;
- }
-
- return true;
+ return QtPrivate::isUpper(qToStringViewIgnoringNull(*this));
}
/*!
@@ -4762,15 +5597,7 @@ bool QString::isUpper() const
*/
bool QString::isLower() const
{
- QStringIterator it(*this);
-
- while (it.hasNext()) {
- const char32_t uc = it.nextUnchecked();
- if (qGetProp(uc)->cases[QUnicodeTables::LowerCase].diff)
- return false;
- }
-
- return true;
+ return QtPrivate::isLower(qToStringViewIgnoringNull(*this));
}
static QByteArray qt_convert_to_latin1(QStringView string);
@@ -4781,6 +5608,21 @@ QByteArray QString::toLatin1_helper(const QString &string)
}
/*!
+ \since 6.0
+ \internal
+ \relates QAnyStringView
+
+ Returns a UTF-16 representation of \a string as a QString.
+
+ \sa QString::toLatin1(), QStringView::toLatin1(), QtPrivate::convertToUtf8(),
+ QtPrivate::convertToLocal8Bit(), QtPrivate::convertToUcs4()
+*/
+QString QtPrivate::convertToQString(QAnyStringView string)
+{
+ return string.visit([] (auto string) { return string.toString(); });
+}
+
+/*!
\since 5.10
\internal
\relates QStringView
@@ -4797,12 +5639,13 @@ QByteArray QtPrivate::convertToLatin1(QStringView string)
return qt_convert_to_latin1(string);
}
+Q_NEVER_INLINE
static QByteArray qt_convert_to_latin1(QStringView string)
{
if (Q_UNLIKELY(string.isNull()))
return QByteArray();
- QByteArray ba(string.length(), Qt::Uninitialized);
+ QByteArray ba(string.size(), Qt::Uninitialized);
// since we own the only copy, we're going to const_cast the constData;
// that avoids an unnecessary call to detach() and expansion code that will never get used
@@ -4818,27 +5661,41 @@ QByteArray QString::toLatin1_helper_inplace(QString &s)
// We can return our own buffer to the caller.
// Conversion to Latin-1 always shrinks the buffer by half.
- const char16_t *data = s.d.data();
- int length = s.d.size;
+ // This relies on the fact that we use QArrayData for everything behind the scenes
- // Move the d pointer over to the bytearray.
+ // First, do the in-place conversion. Since isDetached() == true, the data
+ // was allocated by QArrayData, so the null terminator must be there.
+ qsizetype length = s.size();
+ char16_t *sdata = s.d->data();
+ Q_ASSERT(sdata[length] == u'\0');
+ qt_to_latin1(reinterpret_cast<uchar *>(sdata), sdata, length + 1);
+
+ // Move the internals over to the byte array.
// Kids, avert your eyes. Don't try this at home.
+ auto ba_d = std::move(s.d).reinterpreted<char>();
- // this relies on the fact that we use QArrayData for everything behind the scenes which has the same layout
- static_assert(sizeof(QByteArray::DataPointer) == sizeof(QString::DataPointer), "sizes have to be equal");
- QByteArray::DataPointer ba_d(reinterpret_cast<QByteArray::Data *>(s.d.d_ptr()), reinterpret_cast<char *>(s.d.data()), length);
- ba_d.ref();
- s.clear();
+ // Some sanity checks
+ Q_ASSERT(ba_d.d->allocatedCapacity() >= ba_d.size);
+ Q_ASSERT(s.isNull());
+ Q_ASSERT(s.isEmpty());
+ Q_ASSERT(s.constData() == QString().constData());
- char *ddata = ba_d.data();
+ return QByteArray(std::move(ba_d));
+}
- // multiply the allocated capacity by sizeof(char16_t)
- ba_d.d_ptr()->alloc *= sizeof(char16_t);
+// QLatin1 methods that use helpers from qstring.cpp
+char16_t *QLatin1::convertToUnicode(char16_t *out, QLatin1StringView in) noexcept
+{
+ const qsizetype len = in.size();
+ qt_from_latin1(out, in.data(), len);
+ return std::next(out, len);
+}
- // do the in-place conversion
- qt_to_latin1(reinterpret_cast<uchar *>(ddata), data, length);
- ddata[length] = '\0';
- return QByteArray(ba_d);
+char *QLatin1::convertFromUnicode(char *out, QStringView in) noexcept
+{
+ const qsizetype len = in.size();
+ qt_to_latin1(reinterpret_cast<uchar *>(out), in.utf16(), len);
+ return out + len;
}
/*!
@@ -4859,20 +5716,18 @@ static QByteArray qt_convert_to_local_8bit(QStringView string);
\fn QByteArray QString::toLocal8Bit() const
Returns the local 8-bit representation of the string as a
- QByteArray. The returned byte array is undefined if the string
- contains characters not supported by the local 8-bit encoding.
+ QByteArray.
- On Unix systems this is equivalen to toUtf8(), on Windows the systems
- current code page is being used.
+ \include qstring.qdocinc {qstring-local-8-bit-equivalent} {toUtf8}
If this string contains any characters that cannot be encoded in the
- locale, the returned byte array is undefined. Those characters may be
- suppressed or replaced by another.
+ local 8-bit encoding, the returned byte array is undefined. Those
+ characters may be suppressed or replaced by another.
\sa fromLocal8Bit(), toLatin1(), toUtf8(), QStringEncoder
*/
-QByteArray QString::toLocal8Bit_helper(const QChar *data, int size)
+QByteArray QString::toLocal8Bit_helper(const QChar *data, qsizetype size)
{
return qt_convert_to_local_8bit(QStringView(data, size));
}
@@ -4892,7 +5747,7 @@ static QByteArray qt_convert_to_local_8bit(QStringView string)
Returns a local 8-bit representation of \a string as a QByteArray.
- On Unix systems this is equivalen to toUtf8(), on Windows the systems
+ On Unix systems this is equivalent to toUtf8(), on Windows the systems
current code page is being used.
The behavior is undefined if \a string contains characters not
@@ -4928,7 +5783,7 @@ static QByteArray qt_convert_to_utf8(QStringView str)
if (str.isNull())
return QByteArray();
- return QUtf8::convertFromUnicode(str.data(), str.length());
+ return QUtf8::convertFromUnicode(str);
}
/*!
@@ -4962,7 +5817,8 @@ static QList<uint> qt_convert_to_ucs4(QStringView string);
The returned list is not \\0'-terminated.
- \sa fromUtf8(), toUtf8(), toLatin1(), toLocal8Bit(), QStringEncoder, fromUcs4(), toWCharArray()
+ \sa fromUtf8(), toUtf8(), toLatin1(), toLocal8Bit(), QStringEncoder,
+ fromUcs4(), toWCharArray()
*/
QList<uint> QString::toUcs4() const
{
@@ -4971,7 +5827,7 @@ QList<uint> QString::toUcs4() const
static QList<uint> qt_convert_to_ucs4(QStringView string)
{
- QList<uint> v(string.length());
+ QList<uint> v(string.size());
uint *a = const_cast<uint*>(v.constData());
QStringIterator it(string);
while (it.hasNext())
@@ -5002,31 +5858,40 @@ QList<uint> QtPrivate::convertToUcs4(QStringView string)
return qt_convert_to_ucs4(string);
}
-QString::DataPointer QString::fromLatin1_helper(const char *str, int size)
+/*!
+ \fn QString QString::fromLatin1(QByteArrayView str)
+ \overload
+ \since 6.0
+
+ Returns a QString initialized with the Latin-1 string \a str.
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000).
+*/
+QString QString::fromLatin1(QByteArrayView ba)
{
DataPointer d;
- if (!str) {
+ if (!ba.data()) {
// nothing to do
- } else if (size == 0 || (!*str && size < 0)) {
- d = DataPointer(Data::allocate(0), 0);
+ } else if (ba.size() == 0) {
+ d = DataPointer::fromRawData(&_empty, 0);
} else {
- if (size < 0)
- size = qstrlen(str);
- d = DataPointer(Data::allocate(size + 1), size);
- d.data()[size] = '\0';
+ d = DataPointer(ba.size(), ba.size());
+ Q_CHECK_PTR(d.data());
+ d.data()[ba.size()] = '\0';
char16_t *dst = d.data();
- qt_from_latin1(dst, str, uint(size));
+ qt_from_latin1(dst, ba.data(), size_t(ba.size()));
}
- return d;
+ return QString(std::move(d));
}
-/*! \fn QString QString::fromLatin1(const char *str, int size)
+/*!
+ \fn QString QString::fromLatin1(const char *str, qsizetype size)
Returns a QString initialized with the first \a size characters
of the Latin-1 string \a str.
- If \a size is -1 (default), it is taken to be strlen(\a
- str).
+ If \a size is \c{-1}, \c{strlen(str)} is used instead.
\sa toLatin1(), fromUtf8(), fromLocal8Bit()
*/
@@ -5037,17 +5902,20 @@ QString::DataPointer QString::fromLatin1_helper(const char *str, int size)
\since 5.0
Returns a QString initialized with the Latin-1 string \a str.
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000). This behavior is
+ different from Qt 5.x.
*/
-/*! \fn QString QString::fromLocal8Bit(const char *str, int size)
+/*!
+ \fn QString QString::fromLocal8Bit(const char *str, qsizetype size)
Returns a QString initialized with the first \a size characters
of the 8-bit string \a str.
- If \a size is -1 (default), it is taken to be strlen(\a
- str).
+ If \a size is \c{-1}, \c{strlen(str)} is used instead.
- On Unix systems this is equivalen to fromUtf8(), on Windows the systems
- current code page is being used.
+ \include qstring.qdocinc {qstring-local-8-bit-equivalent} {fromUtf8}
\sa toLocal8Bit(), fromLatin1(), fromUtf8()
*/
@@ -5058,26 +5926,41 @@ QString::DataPointer QString::fromLatin1_helper(const char *str, int size)
\since 5.0
Returns a QString initialized with the 8-bit string \a str.
+
+ \include qstring.qdocinc {qstring-local-8-bit-equivalent} {fromUtf8}
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000). This behavior is
+ different from Qt 5.x.
+*/
+
+/*!
+ \fn QString QString::fromLocal8Bit(QByteArrayView str)
+ \overload
+ \since 6.0
+
+ Returns a QString initialized with the 8-bit string \a str.
+
+ \include qstring.qdocinc {qstring-local-8-bit-equivalent} {fromUtf8}
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000).
*/
-QString QString::fromLocal8Bit_helper(const char *str, int size)
+QString QString::fromLocal8Bit(QByteArrayView ba)
{
- if (!str)
+ if (ba.isNull())
return QString();
- if (size == 0 || (!*str && size < 0)) {
- QPair<Data *, char16_t *> pair = Data::allocate(0);
- QString::DataPointer empty = { pair.first, pair.second, 0 };
- return QString(empty);
- }
+ if (ba.isEmpty())
+ return QString(DataPointer::fromRawData(&_empty, 0));
QStringDecoder toUtf16(QStringDecoder::System, QStringDecoder::Flag::Stateless);
- return toUtf16(str, size);
+ return toUtf16(ba);
}
-/*! \fn QString QString::fromUtf8(const char *str, int size)
+/*! \fn QString QString::fromUtf8(const char *str, qsizetype size)
Returns a QString initialized with the first \a size bytes
of the UTF-8 string \a str.
- If \a size is -1 (default), it is taken to be strlen(\a
- str).
+ If \a size is \c{-1}, \c{strlen(str)} is used instead.
UTF-8 is a Unicode codec and can represent all characters in a Unicode
string like QString. However, invalid sequences are possible with UTF-8
@@ -5095,6 +5978,14 @@ QString QString::fromLocal8Bit_helper(const char *str, int size)
*/
/*!
+ \fn QString QString::fromUtf8(const char8_t *str)
+ \overload
+ \since 6.1
+
+ This overload is only available when compiling in C++20 mode.
+*/
+
+/*!
\fn QString QString::fromUtf8(const char8_t *str, qsizetype size)
\overload
\since 6.0
@@ -5108,16 +5999,32 @@ QString QString::fromLocal8Bit_helper(const char *str, int size)
\since 5.0
Returns a QString initialized with the UTF-8 string \a str.
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000). This behavior is
+ different from Qt 5.x.
*/
-QString QString::fromUtf8_helper(const char *str, int size)
+
+/*!
+ \fn QString QString::fromUtf8(QByteArrayView str)
+ \overload
+ \since 6.0
+
+ Returns a QString initialized with the UTF-8 string \a str.
+
+ \note: any null ('\\0') bytes in the byte array will be included in this
+ string, converted to Unicode null characters (U+0000).
+*/
+QString QString::fromUtf8(QByteArrayView ba)
{
- if (!str)
+ if (ba.isNull())
return QString();
-
- Q_ASSERT(size != -1);
- return QUtf8::convertToUnicode(str, size);
+ if (ba.isEmpty())
+ return QString(DataPointer::fromRawData(&_empty, 0));
+ return QUtf8::convertToUnicode(ba);
}
+#ifndef QT_BOOTSTRAPPED
/*!
\since 5.3
Returns a QString initialized with the first \a size characters
@@ -5129,38 +6036,31 @@ QString QString::fromUtf8_helper(const char *str, int size)
host byte order is assumed.
This function is slow compared to the other Unicode conversions.
- Use QString(const QChar *, int) or QString(const QChar *) if possible.
+ Use QString(const QChar *, qsizetype) or QString(const QChar *) if possible.
QString makes a deep copy of the Unicode data.
\sa utf16(), setUtf16(), fromStdU16String()
*/
-QString QString::fromUtf16(const char16_t *unicode, int size)
+QString QString::fromUtf16(const char16_t *unicode, qsizetype size)
{
if (!unicode)
return QString();
- if (size < 0) {
- size = 0;
- while (unicode[size] != 0)
- ++size;
- }
+ if (size < 0)
+ size = QtPrivate::qustrlen(unicode);
QStringDecoder toUtf16(QStringDecoder::Utf16, QStringDecoder::Flag::Stateless);
- return toUtf16(reinterpret_cast<const char *>(unicode), size*2);
+ return toUtf16(QByteArrayView(reinterpret_cast<const char *>(unicode), size * 2));
}
/*!
- \fn QString QString::fromUtf16(const ushort *str, int size)
- \obsolete
-
- Use the \c char16_t overload.
+ \fn QString QString::fromUtf16(const ushort *str, qsizetype size)
+ \deprecated [6.0] Use the \c char16_t overload instead.
*/
/*!
- \fn QString QString::fromUcs4(const uint *str, int size)
+ \fn QString QString::fromUcs4(const uint *str, qsizetype size)
\since 4.2
- \obsolete
-
- Use the \c char32_t overload instead.
+ \deprecated [6.0] Use the \c char32_t overload instead.
*/
/*!
@@ -5171,9 +6071,10 @@ QString QString::fromUtf16(const char16_t *unicode, int size)
If \a size is -1 (default), \a unicode must be \\0'-terminated.
- \sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray(), fromStdU32String()
+ \sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray(),
+ fromStdU32String()
*/
-QString QString::fromUcs4(const char32_t *unicode, int size)
+QString QString::fromUcs4(const char32_t *unicode, qsizetype size)
{
if (!unicode)
return QString();
@@ -5183,20 +6084,20 @@ QString QString::fromUcs4(const char32_t *unicode, int size)
++size;
}
QStringDecoder toUtf16(QStringDecoder::Utf32, QStringDecoder::Flag::Stateless);
- return toUtf16(reinterpret_cast<const char *>(unicode), size*4);
+ return toUtf16(QByteArrayView(reinterpret_cast<const char *>(unicode), size * 4));
}
-
+#endif // !QT_BOOTSTRAPPED
/*!
Resizes the string to \a size characters and copies \a unicode
into the string.
- If \a unicode is 0, nothing is copied, but the string is still
+ If \a unicode is \nullptr, nothing is copied, but the string is still
resized to \a size.
\sa unicode(), setUtf16()
*/
-QString& QString::setUnicode(const QChar *unicode, int size)
+QString& QString::setUnicode(const QChar *unicode, qsizetype size)
{
resize(size);
if (unicode && size)
@@ -5205,12 +6106,12 @@ QString& QString::setUnicode(const QChar *unicode, int size)
}
/*!
- \fn QString &QString::setUtf16(const ushort *unicode, int size)
+ \fn QString &QString::setUtf16(const ushort *unicode, qsizetype size)
Resizes the string to \a size characters and copies \a unicode
into the string.
- If \a unicode is 0, nothing is copied, but the string is still
+ If \a unicode is \nullptr, nothing is copied, but the string is still
resized to \a size.
Note that unlike fromUtf16(), this function does not consider BOMs and
@@ -5250,16 +6151,14 @@ namespace {
template <typename StringView>
StringView qt_trimmed(StringView s) noexcept
{
- auto begin = s.begin();
- auto end = s.end();
- QStringAlgorithms<const StringView>::trimmed_helper_positions(begin, end);
+ const auto [begin, end] = QStringAlgorithms<const StringView>::trimmed_helper_positions(s);
return StringView{begin, end};
}
}
/*!
\fn QStringView QtPrivate::trimmed(QStringView s)
- \fn QLatin1String QtPrivate::trimmed(QLatin1String s)
+ \fn QLatin1StringView QtPrivate::trimmed(QLatin1StringView s)
\internal
\relates QStringView
\since 5.10
@@ -5270,14 +6169,14 @@ namespace {
\c true. This includes the ASCII characters '\\t', '\\n', '\\v',
'\\f', '\\r', and ' '.
- \sa QString::trimmed(), QStringView::trimmed(), QLatin1String::trimmed()
+ \sa QString::trimmed(), QStringView::trimmed(), QLatin1StringView::trimmed()
*/
QStringView QtPrivate::trimmed(QStringView s) noexcept
{
return qt_trimmed(s);
}
-QLatin1String QtPrivate::trimmed(QLatin1String s) noexcept
+QLatin1StringView QtPrivate::trimmed(QLatin1StringView s) noexcept
{
return qt_trimmed(s);
}
@@ -5310,7 +6209,7 @@ QString QString::trimmed_helper(QString &str)
return QStringAlgorithms<QString>::trimmed_helper(str);
}
-/*! \fn const QChar QString::at(int position) const
+/*! \fn const QChar QString::at(qsizetype position) const
Returns the character at the given index \a position in the
string.
@@ -5322,7 +6221,7 @@ QString QString::trimmed_helper(QString &str)
*/
/*!
- \fn QChar &QString::operator[](int position)
+ \fn QChar &QString::operator[](qsizetype position)
Returns the character at the specified \a position in the string as a
modifiable reference.
@@ -5335,7 +6234,7 @@ QString QString::trimmed_helper(QString &str)
*/
/*!
- \fn const QChar QString::operator[](int position) const
+ \fn const QChar QString::operator[](qsizetype position) const
\overload operator[]()
*/
@@ -5401,7 +6300,7 @@ QString QString::trimmed_helper(QString &str)
*/
/*!
- \fn void QString::truncate(int position)
+ \fn void QString::truncate(qsizetype position)
Truncates the string at the given \a position index.
@@ -5414,10 +6313,10 @@ QString QString::trimmed_helper(QString &str)
If \a position is negative, it is equivalent to passing zero.
- \sa chop(), resize(), left(), QStringRef::truncate()
+ \sa chop(), resize(), first(), QStringView::truncate()
*/
-void QString::truncate(int pos)
+void QString::truncate(qsizetype pos)
{
if (pos < size())
resize(pos);
@@ -5436,9 +6335,9 @@ void QString::truncate(int pos)
If you want to remove characters from the \e beginning of the
string, use remove() instead.
- \sa truncate(), resize(), remove(), QStringRef::chop()
+ \sa truncate(), resize(), remove(), QStringView::chop()
*/
-void QString::chop(int n)
+void QString::chop(qsizetype n)
{
if (n > 0)
resize(d.size - n);
@@ -5456,20 +6355,16 @@ void QString::chop(int n)
\sa resize()
*/
-QString& QString::fill(QChar ch, int size)
+QString& QString::fill(QChar ch, qsizetype size)
{
resize(size < 0 ? d.size : size);
- if (d.size) {
- QChar *i = (QChar*)d.data() + d.size;
- QChar *b = (QChar*)d.data();
- while (i != b)
- *--i = ch;
- }
+ if (d.size)
+ std::fill(d.data(), d.data() + d.size, ch.unicode());
return *this;
}
/*!
- \fn int QString::length() const
+ \fn qsizetype QString::length() const
Returns the number of characters in this string. Equivalent to
size().
@@ -5478,7 +6373,7 @@ QString& QString::fill(QChar ch, int size)
*/
/*!
- \fn int QString::size() const
+ \fn qsizetype QString::size() const
Returns the number of characters in this string.
@@ -5490,6 +6385,16 @@ QString& QString::fill(QChar ch, int size)
\sa isEmpty(), resize()
*/
+/*!
+ \fn qsizetype QString::max_size()
+ \since 6.8
+
+ This function is provided for STL compatibility.
+ It returns the maximum number of elements that the string can
+ theoretically hold. In practice, the number can be much smaller,
+ limited by the amount of memory available to the system.
+*/
+
/*! \fn bool QString::isNull() const
Returns \c true if this string is null; otherwise returns \c false.
@@ -5535,11 +6440,18 @@ QString& QString::fill(QChar ch, int size)
\sa append(), prepend()
*/
-/*! \fn QString &QString::operator+=(QLatin1String str)
+/*! \fn QString &QString::operator+=(QLatin1StringView str)
\overload operator+=()
- Appends the Latin-1 string \a str to this string.
+ Appends the Latin-1 string viewed by \a str to this string.
+*/
+
+/*! \fn QString &QString::operator+=(QUtf8StringView str)
+ \since 6.5
+ \overload operator+=()
+
+ Appends the UTF-8 string view \a str to this string.
*/
/*! \fn QString &QString::operator+=(const QByteArray &ba)
@@ -5551,12 +6463,10 @@ QString& QString::fill(QChar ch, int size)
are embedded in the \a ba byte array, they will be included in the
transformation.
- You can disable this function by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ You can disable this function by defining
+ \l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
*/
/*! \fn QString &QString::operator+=(const char *str)
@@ -5566,19 +6476,10 @@ QString& QString::fill(QChar ch, int size)
Appends the string \a str to this string. The const char pointer
is converted to Unicode using the fromUtf8() function.
- You can disable this function by defining \c QT_NO_CAST_FROM_ASCII
+ You can disable this function by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
to ensure that all user-visible strings go through QObject::tr(),
for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*! \fn QString &QString::operator+=(const QStringRef &str)
-
- \overload operator+=()
-
- Appends the string section referenced by \a str to this string.
*/
/*! \fn QString &QString::operator+=(QStringView str)
@@ -5596,85 +6497,68 @@ QString& QString::fill(QChar ch, int size)
*/
/*!
- \fn bool operator==(const char *s1, const QString &s2)
+ \fn bool QString::operator==(const char * const &lhs, const QString &rhs)
- \overload operator==()
- \relates QString
+ \overload operator==()
- Returns \c true if \a s1 is equal to \a s2; otherwise returns \c false.
- Note that no string is equal to \a s1 being 0.
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
+ Note that no string is equal to \a lhs being 0.
- Equivalent to \c {s1 != 0 && compare(s1, s2) == 0}.
+ Equivalent to \c {lhs != 0 && compare(lhs, rhs) == 0}.
*/
/*!
- \fn bool operator!=(const char *s1, const QString &s2)
- \relates QString
+ \fn bool QString::operator!=(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is not equal to \a s2; otherwise returns
+ Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
\c false.
- For \a s1 != 0, this is equivalent to \c {compare(} \a s1, \a s2
- \c {) != 0}. Note that no string is equal to \a s1 being 0.
+ For \a lhs != 0, this is equivalent to \c {compare(} \a lhs, \a rhs
+ \c {) != 0}. Note that no string is equal to \a lhs being 0.
*/
/*!
- \fn bool operator<(const char *s1, const QString &s2)
- \relates QString
+ \fn bool QString::operator<(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically less than \a s2; otherwise
- returns \c false. For \a s1 != 0, this is equivalent to \c
- {compare(s1, s2) < 0}.
+ Returns \c true if \a lhs is lexically less than \a rhs; otherwise
+ returns \c false. For \a lhs != 0, this is equivalent to \c
+ {compare(lhs, rhs) < 0}.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
+ \sa {Comparing Strings}
*/
/*!
- \fn bool operator<=(const char *s1, const QString &s2)
- \relates QString
+ \fn bool QString::operator<=(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically less than or equal to \a s2;
- otherwise returns \c false. For \a s1 != 0, this is equivalent to \c
- {compare(s1, s2) <= 0}.
+ Returns \c true if \a lhs is lexically less than or equal to \a rhs;
+ otherwise returns \c false. For \a lhs != 0, this is equivalent to \c
+ {compare(lhs, rhs) <= 0}.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- QString::localeAwareCompare().
+ \sa {Comparing Strings}
*/
/*!
- \fn bool operator>(const char *s1, const QString &s2)
- \relates QString
+ \fn bool QString::operator>(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically greater than \a s2; otherwise
- returns \c false. Equivalent to \c {compare(s1, s2) > 0}.
+ Returns \c true if \a lhs is lexically greater than \a rhs; otherwise
+ returns \c false. Equivalent to \c {compare(lhs, rhs) > 0}.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
+ \sa {Comparing Strings}
*/
/*!
- \fn bool operator>=(const char *s1, const QString &s2)
- \relates QString
+ \fn bool QString::operator>=(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically greater than or equal to \a s2;
- otherwise returns \c false. For \a s1 != 0, this is equivalent to \c
- {compare(s1, s2) >= 0}.
+ Returns \c true if \a lhs is lexically greater than or equal to \a rhs;
+ otherwise returns \c false. For \a lhs != 0, this is equivalent to \c
+ {compare(lhs, rhs) >= 0}.
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
+ \sa {Comparing Strings}
*/
/*!
- \fn const QString operator+(const QString &s1, const QString &s2)
+ \fn QString operator+(const QString &s1, const QString &s2)
+ \fn QString operator+(QString &&s1, const QString &s2)
\relates QString
Returns a string which is the result of concatenating \a s1 and \a
@@ -5682,7 +6566,7 @@ QString& QString::fill(QChar ch, int size)
*/
/*!
- \fn const QString operator+(const QString &s1, const char *s2)
+ \fn QString operator+(const QString &s1, const char *s2)
\relates QString
Returns a string which is the result of concatenating \a s1 and \a
@@ -5693,7 +6577,7 @@ QString& QString::fill(QChar ch, int size)
*/
/*!
- \fn const QString operator+(const char *s1, const QString &s2)
+ \fn QString operator+(const char *s1, const QString &s2)
\relates QString
Returns a string which is the result of concatenating \a s1 and \a
@@ -5707,12 +6591,11 @@ QString& QString::fill(QChar ch, int size)
\fn int QString::compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
\since 4.2
- Compares \a s1 with \a s2 and returns an integer less than, equal
- to, or greater than zero if \a s1 is less than, equal to, or
- greater than \a s2.
+ Compares the string \a s1 with the string \a s2 and returns a negative integer
+ if \a s1 is less than \a s2, a positive integer if it is greater than \a s2,
+ and zero if they are equal.
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
Case sensitive comparison is based exclusively on the numeric
Unicode values of the characters and is very fast, but is not what
@@ -5721,11 +6604,16 @@ QString& QString::fill(QChar ch, int size)
\snippet qstring/main.cpp 16
- \sa operator==(), operator<(), operator>()
+//! [compare-isNull-vs-isEmpty]
+ \note This function treats null strings the same as empty strings,
+ for more details see \l {Distinction Between Null and Empty Strings}.
+//! [compare-isNull-vs-isEmpty]
+
+ \sa operator==(), operator<(), operator>(), {Comparing Strings}
*/
/*!
- \fn int QString::compare(const QString &s1, QLatin1String s2, Qt::CaseSensitivity cs)
+ \fn int QString::compare(const QString &s1, QLatin1StringView s2, Qt::CaseSensitivity cs)
\since 4.2
\overload compare()
@@ -5734,7 +6622,7 @@ QString& QString::fill(QChar ch, int size)
*/
/*!
- \fn int QString::compare(QLatin1String s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ \fn int QString::compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
\since 4.2
\overload compare()
@@ -5763,36 +6651,33 @@ QString& QString::fill(QChar ch, int size)
sensitivity setting \a cs.
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\overload compare()
\since 4.2
- Lexically compares this string with the \a other string and
- returns an integer less than, equal to, or greater than zero if
- this string is less than, equal to, or greater than the other
- string.
+ Lexically compares this string with the string \a other and returns
+ a negative integer if this string is less than \a other, a positive
+ integer if it is greater than \a other, and zero if they are equal.
Same as compare(*this, \a other, \a cs).
*/
int QString::compare(const QString &other, Qt::CaseSensitivity cs) const noexcept
{
- return qt_compare_strings(*this, other, cs);
+ return QtPrivate::compareStrings(*this, other, cs);
}
-#endif
/*!
\internal
\since 4.5
*/
-int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, int length2,
+int QString::compare_helper(const QChar *data1, qsizetype length1, const QChar *data2, qsizetype length2,
Qt::CaseSensitivity cs) noexcept
{
Q_ASSERT(length1 >= 0);
Q_ASSERT(length2 >= 0);
Q_ASSERT(data1 || length1 == 0);
Q_ASSERT(data2 || length2 == 0);
- return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2), cs);
+ return QtPrivate::compareStrings(QStringView(data1, length1), QStringView(data2, length2), cs);
}
/*!
@@ -5801,29 +6686,26 @@ int QString::compare_helper(const QChar *data1, int length1, const QChar *data2,
Same as compare(*this, \a other, \a cs).
*/
-int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const noexcept
+int QString::compare(QLatin1StringView other, Qt::CaseSensitivity cs) const noexcept
{
- return qt_compare_strings(*this, other, cs);
+ return QtPrivate::compareStrings(*this, other, cs);
}
/*!
\internal
\since 5.0
*/
-int QString::compare_helper(const QChar *data1, int length1, const char *data2, int length2,
- Qt::CaseSensitivity cs)
+int QString::compare_helper(const QChar *data1, qsizetype length1, const char *data2, qsizetype length2,
+ Qt::CaseSensitivity cs) noexcept
{
Q_ASSERT(length1 >= 0);
Q_ASSERT(data1 || length1 == 0);
if (!data2)
- return length1;
+ return qt_lencmp(length1, 0);
if (Q_UNLIKELY(length2 < 0))
- length2 = int(strlen(data2));
- // ### make me nothrow in all cases
- QVarLengthArray<ushort> s2(length2);
- const auto beg = reinterpret_cast<QChar *>(s2.data());
- const auto end = QUtf8::convertToUnicode(beg, data2, length2);
- return qt_compare_strings(QStringView(data1, length1), QStringView(beg, end - beg), cs);
+ length2 = qsizetype(strlen(data2));
+ return QtPrivate::compareStrings(QStringView(data1, length1),
+ QUtf8StringView(data2, length2), cs);
}
/*!
@@ -5836,16 +6718,120 @@ int QString::compare_helper(const QChar *data1, int length1, const char *data2,
\overload compare()
*/
+bool comparesEqual(const QByteArrayView &lhs, const QChar &rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArrayView &lhs, const QChar &rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+bool comparesEqual(const QByteArrayView &lhs, char16_t rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArrayView &lhs, char16_t rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+bool comparesEqual(const QByteArray &lhs, const QChar &rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArray &lhs, const QChar &rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+bool comparesEqual(const QByteArray &lhs, char16_t rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArray &lhs, char16_t rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+bool QT_FASTCALL QChar::equal_helper(QChar lhs, const char *rhs) noexcept
+{
+ return QtPrivate::equalStrings(QStringView(&lhs, 1), QUtf8StringView(rhs));
+}
+
+int QT_FASTCALL QChar::compare_helper(QChar lhs, const char *rhs) noexcept
+{
+ return QtPrivate::compareStrings(QStringView(&lhs, 1), QUtf8StringView(rhs));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+bool QStringView::equal_helper(QStringView sv, const char *data, qsizetype len)
+{
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(data || len == 0);
+ return QtPrivate::equalStrings(sv, QUtf8StringView(data, len));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+int QStringView::compare_helper(QStringView sv, const char *data, qsizetype len)
+{
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(data || len == 0);
+ return QtPrivate::compareStrings(sv, QUtf8StringView(data, len));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+bool QLatin1StringView::equal_helper(QLatin1StringView s1, const char *s2, qsizetype len) noexcept
+{
+ // because qlatin1stringview.h can't include qutf8stringview.h
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(s2 || len == 0);
+ return QtPrivate::equalStrings(s1, QUtf8StringView(s2, len));
+}
+
+/*!
+ \internal
+ \since 6.6
+*/
+int QLatin1StringView::compare_helper(const QLatin1StringView &s1, const char *s2, qsizetype len) noexcept
+{
+ // because qlatin1stringview.h can't include qutf8stringview.h
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(s2 || len == 0);
+ return QtPrivate::compareStrings(s1, QUtf8StringView(s2, len));
+}
+
/*!
\internal
\since 4.5
*/
-int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
- Qt::CaseSensitivity cs) noexcept
+int QLatin1StringView::compare_helper(const QChar *data1, qsizetype length1, QLatin1StringView s2,
+ Qt::CaseSensitivity cs) noexcept
{
Q_ASSERT(length1 >= 0);
Q_ASSERT(data1 || length1 == 0);
- return qt_compare_strings(QStringView(data1, length1), s2, cs);
+ return QtPrivate::compareStrings(QStringView(data1, length1), s2, cs);
}
/*!
@@ -5859,10 +6845,7 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
platform-dependent manner. Use this function to present sorted
lists of strings to the user.
- On \macos and iOS this function compares according the
- "Order for sorted lists" setting in the International preferences panel.
-
- \sa compare(), QLocale
+ \sa compare(), QLocale, {Comparing Strings}
*/
/*!
@@ -5879,6 +6862,8 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
lists of strings to the user.
Same as \c {localeAwareCompare(*this, other)}.
+
+ \sa {Comparing Strings}
*/
/*!
@@ -5893,6 +6878,8 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
The comparison is performed in a locale- and also
platform-dependent manner. Use this function to present sorted
lists of strings to the user.
+
+ \sa {Comparing Strings}
*/
@@ -5914,22 +6901,20 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
lists of strings to the user.
Same as \c {localeAwareCompare(*this, other)}.
+
+ \sa {Comparing Strings}
*/
int QString::localeAwareCompare(const QString &other) const
{
- return localeAwareCompare_helper(constData(), length(), other.constData(), other.length());
+ return localeAwareCompare_helper(constData(), size(), other.constData(), other.size());
}
-#if QT_CONFIG(icu)
-Q_GLOBAL_STATIC(QThreadStorage<QCollator>, defaultCollator)
-#endif
-
/*!
\internal
\since 4.5
*/
-int QString::localeAwareCompare_helper(const QChar *data1, int length1,
- const QChar *data2, int length2)
+int QString::localeAwareCompare_helper(const QChar *data1, qsizetype length1,
+ const QChar *data2, qsizetype length2)
{
Q_ASSERT(length1 >= 0);
Q_ASSERT(data1 || length1 == 0);
@@ -5938,13 +6923,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
// do the right thing for null and empty
if (length1 == 0 || length2 == 0)
- return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
+ return QtPrivate::compareStrings(QStringView(data1, length1), QStringView(data2, length2),
Qt::CaseSensitive);
#if QT_CONFIG(icu)
- if (!defaultCollator()->hasLocalData())
- defaultCollator()->setLocalData(QCollator());
- return defaultCollator()->localData().compare(data1, length1, data2, length2);
+ return QCollator::defaultCompare(QStringView(data1, length1), QStringView(data2, length2));
#else
const QString lhs = QString::fromRawData(data1, length1).normalized(QString::NormalizationForm_C);
const QString rhs = QString::fromRawData(data2, length2).normalized(QString::NormalizationForm_C);
@@ -5976,14 +6959,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
CFRelease(otherString);
return result;
# elif defined(Q_OS_UNIX)
- // declared in <string.h>
- int delta = strcoll(lhs.toLocal8Bit().constData(), rhs.toLocal8Bit().constData());
- if (delta == 0)
- delta = qt_compare_strings(lhs, rhs, Qt::CaseSensitive);
- return delta;
+ // declared in <string.h> (no better than QtPrivate::compareStrings() on Android, sadly)
+ return strcoll(lhs.toLocal8Bit().constData(), rhs.toLocal8Bit().constData());
# else
# error "This case shouldn't happen"
- return qt_compare_strings(lhs, rhs, Qt::CaseSensitive);
+ return QtPrivate::compareStrings(lhs, rhs, Qt::CaseSensitive);
# endif
#endif // !QT_CONFIG(icu)
}
@@ -6016,7 +6996,7 @@ const ushort *QString::utf16() const
{
if (!d->isMutable()) {
// ensure '\0'-termination for ::fromRawData strings
- const_cast<QString*>(this)->reallocData(uint(d.size) + 1u);
+ const_cast<QString*>(this)->reallocData(d.size, QArrayData::KeepSize);
}
return reinterpret_cast<const ushort *>(d.data());
}
@@ -6039,11 +7019,11 @@ const ushort *QString::utf16() const
\sa rightJustified()
*/
-QString QString::leftJustified(int width, QChar fill, bool truncate) const
+QString QString::leftJustified(qsizetype width, QChar fill, bool truncate) const
{
QString result;
- int len = length();
- int padlen = width - len;
+ qsizetype len = size();
+ qsizetype padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
if (len)
@@ -6078,11 +7058,11 @@ QString QString::leftJustified(int width, QChar fill, bool truncate) const
\sa leftJustified()
*/
-QString QString::rightJustified(int width, QChar fill, bool truncate) const
+QString QString::rightJustified(qsizetype width, QChar fill, bool truncate) const
{
QString result;
- int len = length();
- int padlen = width - len;
+ qsizetype len = size();
+ qsizetype padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
QChar *uc = (QChar*)result.d.data();
@@ -6106,8 +7086,8 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
\snippet qstring/main.cpp 75
- The case conversion will always happen in the 'C' locale. For locale dependent
- case folding use QLocale::toLower()
+ The case conversion will always happen in the 'C' locale. For
+ locale-dependent case folding use QLocale::toLower()
\sa toUpper(), QLocale::toLower()
*/
@@ -6130,9 +7110,9 @@ namespace QUnicodeTables {
\endlist
In copy-convert mode, the local variable \c{s} is detached from the input
- \a str. In the in-place convert mode, \a str is in moved-from state (which
- this function requires to be a valid, empty string) and \c{s} contains the
- only copy of the string, without reallocation (thus, \a it is still valid).
+ \a str. In the in-place convert mode, \a str is in moved-from state and
+ \c{s} contains the only copy of the string, without reallocation (thus,
+ \a it is still valid).
There is one pathological case left: when the in-place conversion needs to
reallocate memory to grow the buffer. In that case, we need to adjust the \a
@@ -6143,11 +7123,11 @@ Q_NEVER_INLINE
static QString detachAndConvertCase(T &str, QStringIterator it, QUnicodeTables::Case which)
{
Q_ASSERT(!str.isEmpty());
- QString s = std::move(str); // will copy if T is const QString
+ QString s = std::move(str); // will copy if T is const QString
QChar *pp = s.begin() + it.index(); // will detach if necessary
do {
- const auto folded = fullConvertCase(it.nextUnchecked(), which);
+ const auto folded = fullConvertCase(it.next(), which);
if (Q_UNLIKELY(folded.size() > 1)) {
if (folded.chars[0] == *pp && folded.size() == 2) {
// special case: only second actually changed (e.g. surrogate pairs),
@@ -6156,15 +7136,14 @@ static QString detachAndConvertCase(T &str, QStringIterator it, QUnicodeTables::
*pp++ = folded.chars[1];
} else {
// slow path: the string is growing
- int inpos = it.index() - 1;
- int outpos = pp - s.constBegin();
+ qsizetype inpos = it.index() - 1;
+ qsizetype outpos = pp - s.constBegin();
s.replace(outpos, 1, reinterpret_cast<const QChar *>(folded.data()), folded.size());
pp = const_cast<QChar *>(s.constBegin()) + outpos + folded.size();
- // do we need to adjust the input iterator too?
- // if it is pointing to s's data, str is empty
- if (str.isEmpty())
+ // Adjust the input iterator if we are performing an in-place conversion
+ if constexpr (!std::is_const<T>::value)
it = QStringIterator(s.constBegin(), inpos + folded.size(), s.constEnd());
}
} else {
@@ -6187,9 +7166,9 @@ static QString convertCase(T &str, QUnicodeTables::Case which)
QStringIterator it(p, e);
while (it.hasNext()) {
- const char32_t uc = it.nextUnchecked();
+ const char32_t uc = it.next();
if (qGetProp(uc)->cases[which].diff) {
- it.recedeUnchecked();
+ it.recede();
return detachAndConvertCase(str, it, which);
}
}
@@ -6231,8 +7210,8 @@ QString QString::toCaseFolded_helper(QString &str)
\snippet qstring/main.cpp 81
- The case conversion will always happen in the 'C' locale. For locale dependent
- case folding use QLocale::toUpper()
+ The case conversion will always happen in the 'C' locale. For
+ locale-dependent case folding use QLocale::toUpper()
\sa toLower(), QLocale::toLower()
*/
@@ -6247,7 +7226,6 @@ QString QString::toUpper_helper(QString &str)
return QUnicodeTables::convertCase(str, QUnicodeTables::UpperCase);
}
-// ### Qt 6: Consider whether this function shouldn't be removed See task 202871.
/*!
\since 5.5
@@ -6291,11 +7269,11 @@ QString QString::asprintf(const char *cformat, ...)
return s;
}
-static void append_utf8(QString &qs, const char *cs, int len)
+static void append_utf8(QString &qs, const char *cs, qsizetype len)
{
- const int oldSize = qs.size();
+ const qsizetype oldSize = qs.size();
qs.resize(oldSize + len);
- const QChar *newEnd = QUtf8::convertToUnicode(qs.data() + oldSize, cs, len);
+ const QChar *newEnd = QUtf8::convertToUnicode(qs.data() + oldSize, QByteArrayView(cs, len));
qs.resize(newEnd - qs.constData());
}
@@ -6312,26 +7290,28 @@ static uint parse_flag_characters(const char * &c) noexcept
case '-': flags |= QLocaleData::LeftAdjusted; break;
case ' ': flags |= QLocaleData::BlankBeforePositive; break;
case '+': flags |= QLocaleData::AlwaysShowSign; break;
- case '\'': flags |= QLocaleData::ThousandsGroup; break;
+ case '\'': flags |= QLocaleData::GroupDigits; break;
default: return flags;
}
++c;
}
}
-static int parse_field_width(const char * &c)
+static int parse_field_width(const char *&c, qsizetype size)
{
- Q_ASSERT(qIsDigit(*c));
+ Q_ASSERT(isAsciiDigit(*c));
+ const char *const stop = c + size;
// can't be negative - started with a digit
// contains at least one digit
- const char *endp;
- bool ok;
- const qulonglong result = qstrtoull(c, &endp, 10, &ok);
- c = endp;
- while (qIsDigit(*c)) // preserve Qt 5.5 behavior of consuming all digits, no matter how many
+ auto [result, used] = qstrntoull(c, size, 10);
+ c += used;
+ if (used <= 0)
+ return false;
+ // preserve Qt 5.5 behavior of consuming all digits, no matter how many
+ while (c < stop && isAsciiDigit(*c))
++c;
- return ok && result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0;
+ return result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0;
}
enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t };
@@ -6385,12 +7365,13 @@ QString QString::vasprintf(const char *cformat, va_list ap)
QString result;
const char *c = cformat;
+ const char *formatEnd = cformat + qstrlen(cformat);
for (;;) {
// Copy non-escape chars to result
const char *cb = c;
while (*c != '\0' && *c != '%')
c++;
- append_utf8(result, cb, int(c - cb));
+ append_utf8(result, cb, qsizetype(c - cb));
if (*c == '\0')
break;
@@ -6400,11 +7381,11 @@ QString QString::vasprintf(const char *cformat, va_list ap)
++c;
if (*c == '\0') {
- result.append(QLatin1Char('%')); // a % at the end of the string - treat as non-escape text
+ result.append(u'%'); // a % at the end of the string - treat as non-escape text
break;
}
if (*c == '%') {
- result.append(QLatin1Char('%')); // %%
+ result.append(u'%'); // %%
++c;
continue;
}
@@ -6412,14 +7393,14 @@ QString QString::vasprintf(const char *cformat, va_list ap)
uint flags = parse_flag_characters(c);
if (*c == '\0') {
- result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ result.append(QLatin1StringView(escape_start)); // incomplete escape, treat as non-escape text
break;
}
// Parse field width
int width = -1; // -1 means unspecified
- if (qIsDigit(*c)) {
- width = parse_field_width(c);
+ if (isAsciiDigit(*c)) {
+ width = parse_field_width(c, formatEnd - c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least
width = va_arg(ap, int);
if (width < 0)
@@ -6428,7 +7409,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
}
if (*c == '\0') {
- result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ result.append(QLatin1StringView(escape_start)); // incomplete escape, treat as non-escape text
break;
}
@@ -6436,8 +7417,9 @@ QString QString::vasprintf(const char *cformat, va_list ap)
int precision = -1; // -1 means unspecified
if (*c == '.') {
++c;
- if (qIsDigit(*c)) {
- precision = parse_field_width(c);
+ precision = 0;
+ if (isAsciiDigit(*c)) {
+ precision = parse_field_width(c, formatEnd - c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least
precision = va_arg(ap, int);
if (precision < 0)
@@ -6447,14 +7429,14 @@ QString QString::vasprintf(const char *cformat, va_list ap)
}
if (*c == '\0') {
- result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ result.append(QLatin1StringView(escape_start)); // incomplete escape, treat as non-escape text
break;
}
const LengthMod length_mod = parse_length_modifier(c);
if (*c == '\0') {
- result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
+ result.append(QLatin1StringView(escape_start)); // incomplete escape, treat as non-escape text
break;
}
@@ -6471,8 +7453,10 @@ QString QString::vasprintf(const char *cformat, va_list ap)
case lm_l: i = va_arg(ap, long int); break;
case lm_ll: i = va_arg(ap, qint64); break;
case lm_j: i = va_arg(ap, long int); break;
- case lm_z: i = va_arg(ap, size_t); break;
- case lm_t: i = va_arg(ap, int); break;
+
+ /* ptrdiff_t actually, but it should be the same for us */
+ case lm_z: i = va_arg(ap, qsizetype); break;
+ case lm_t: i = va_arg(ap, qsizetype); break;
default: i = 0; break;
}
subst = QLocaleData::c()->longLongToString(i, precision, 10, width, flags);
@@ -6490,15 +7474,16 @@ QString QString::vasprintf(const char *cformat, va_list ap)
case lm_h: u = va_arg(ap, uint); break;
case lm_l: u = va_arg(ap, ulong); break;
case lm_ll: u = va_arg(ap, quint64); break;
+ case lm_t: u = va_arg(ap, size_t); break;
case lm_z: u = va_arg(ap, size_t); break;
default: u = 0; break;
}
- if (qIsUpper(*c))
+ if (isAsciiUpper(*c))
flags |= QLocaleData::CapitalEorX;
int base = 10;
- switch (qToLower(*c)) {
+ switch (QtMiscUtils::toAsciiLower(*c)) {
case 'o':
base = 8; break;
case 'u':
@@ -6525,11 +7510,11 @@ QString QString::vasprintf(const char *cformat, va_list ap)
else
d = va_arg(ap, double);
- if (qIsUpper(*c))
+ if (isAsciiUpper(*c))
flags |= QLocaleData::CapitalEorX;
QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
- switch (qToLower(*c)) {
+ switch (QtMiscUtils::toAsciiLower(*c)) {
case 'e': form = QLocaleData::DFExponent; break;
case 'a': // not supported - decimal form used instead
case 'f': form = QLocaleData::DFDecimal; break;
@@ -6552,13 +7537,17 @@ QString QString::vasprintf(const char *cformat, va_list ap)
if (length_mod == lm_l) {
const ushort *buff = va_arg(ap, const ushort*);
const ushort *ch = buff;
- while (*ch != 0)
+ while (precision != 0 && *ch != 0) {
++ch;
+ --precision;
+ }
subst.setUtf16(buff, ch - buff);
- } else
+ } else if (precision == -1) {
subst = QString::fromUtf8(va_arg(ap, const char*));
- if (precision != -1)
- subst.truncate(precision);
+ } else {
+ const char *buff = va_arg(ap, const char*);
+ subst = QString::fromUtf8(buff, qstrnlen(buff, precision));
+ }
++c;
break;
}
@@ -6574,27 +7563,27 @@ QString QString::vasprintf(const char *cformat, va_list ap)
switch (length_mod) {
case lm_hh: {
signed char *n = va_arg(ap, signed char*);
- *n = result.length();
+ *n = result.size();
break;
}
case lm_h: {
short int *n = va_arg(ap, short int*);
- *n = result.length();
+ *n = result.size();
break;
}
case lm_l: {
long int *n = va_arg(ap, long int*);
- *n = result.length();
+ *n = result.size();
break;
}
case lm_ll: {
qint64 *n = va_arg(ap, qint64*);
- *n = result.length();
+ *n = result.size();
break;
}
default: {
int *n = va_arg(ap, int*);
- *n = result.length();
+ *n = int(result.size());
break;
}
}
@@ -6617,6 +7606,8 @@ QString QString::vasprintf(const char *cformat, va_list ap)
}
/*!
+ \fn QString::toLongLong(bool *ok, int base) const
+
Returns the string converted to a \c{long long} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
@@ -6624,12 +7615,13 @@ QString QString::vasprintf(const char *cformat, va_list ap)
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toLongLong()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toLongLong()
Example:
@@ -6637,28 +7629,41 @@ QString QString::vasprintf(const char *cformat, va_list ap)
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toULongLong(), toInt(), QLocale::toLongLong()
*/
-qint64 QString::toLongLong(bool *ok, int base) const
-{
- return toIntegral_helper<qlonglong>(*this, ok, base);
-}
-
-qlonglong QString::toIntegral_helper(QStringView string, bool *ok, int base)
+template <typename Int>
+static Int toIntegral(QStringView string, bool *ok, int base)
{
#if defined(QT_CHECK_RANGE)
if (base != 0 && (base < 2 || base > 36)) {
- qWarning("QString::toULongLong: Invalid base (%d)", base);
+ qWarning("QString::toIntegral: Invalid base (%d)", base);
base = 10;
}
#endif
- return QLocaleData::c()->stringToLongLong(string, base, ok, QLocale::RejectGroupSeparator);
+ QVarLengthArray<uchar> latin1(string.size());
+ qt_to_latin1(latin1.data(), string.utf16(), string.size());
+ QSimpleParsedNumber<Int> r;
+ if constexpr (std::is_signed_v<Int>)
+ r = QLocaleData::bytearrayToLongLong(latin1, base);
+ else
+ r = QLocaleData::bytearrayToUnsLongLong(latin1, base);
+ if (ok)
+ *ok = r.ok();
+ return r.result;
}
+qlonglong QString::toIntegral_helper(QStringView string, bool *ok, int base)
+{
+ return toIntegral<qlonglong>(string, ok, base);
+}
/*!
+ \fn QString::toULongLong(bool *ok, int base) const
+
Returns the string converted to an \c{unsigned long long} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
@@ -6666,12 +7671,13 @@ qlonglong QString::toIntegral_helper(QStringView string, bool *ok, int base)
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toULongLong()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toULongLong()
Example:
@@ -6679,24 +7685,14 @@ qlonglong QString::toIntegral_helper(QStringView string, bool *ok, int base)
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toLongLong(), QLocale::toULongLong()
*/
-quint64 QString::toULongLong(bool *ok, int base) const
-{
- return toIntegral_helper<qulonglong>(*this, ok, base);
-}
-
qulonglong QString::toIntegral_helper(QStringView string, bool *ok, uint base)
{
-#if defined(QT_CHECK_RANGE)
- if (base != 0 && (base < 2 || base > 36)) {
- qWarning("QString::toULongLong: Invalid base (%d)", base);
- base = 10;
- }
-#endif
-
- return QLocaleData::c()->stringToUnsLongLong(string, base, ok, QLocale::RejectGroupSeparator);
+ return toIntegral<qulonglong>(string, ok, base);
}
/*!
@@ -6709,12 +7705,13 @@ qulonglong QString::toIntegral_helper(QStringView string, bool *ok, uint base)
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toLongLong()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toLongLong()
Example:
@@ -6722,14 +7719,11 @@ qulonglong QString::toIntegral_helper(QStringView string, bool *ok, uint base)
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toULong(), toInt(), QLocale::toInt()
*/
-long QString::toLong(bool *ok, int base) const
-{
- return toIntegral_helper<long>(*this, ok, base);
-}
-
/*!
\fn ulong QString::toULong(bool *ok, int base) const
@@ -6740,12 +7734,13 @@ long QString::toLong(bool *ok, int base) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toULongLong()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toULongLong()
Example:
@@ -6753,16 +7748,13 @@ long QString::toLong(bool *ok, int base) const
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), QLocale::toUInt()
*/
-ulong QString::toULong(bool *ok, int base) const
-{
- return toIntegral_helper<ulong>(*this, ok, base);
-}
-
-
/*!
+ \fn int QString::toInt(bool *ok, int base) const
Returns the string converted to an \c int using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
@@ -6770,12 +7762,13 @@ ulong QString::toULong(bool *ok, int base) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toInt()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toInt()
Example:
@@ -6783,15 +7776,13 @@ ulong QString::toULong(bool *ok, int base) const
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toUInt(), toDouble(), QLocale::toInt()
*/
-int QString::toInt(bool *ok, int base) const
-{
- return toIntegral_helper<int>(*this, ok, base);
-}
-
/*!
+ \fn uint QString::toUInt(bool *ok, int base) const
Returns the string converted to an \c{unsigned int} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
@@ -6799,12 +7790,13 @@ int QString::toInt(bool *ok, int base) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toUInt()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toUInt()
Example:
@@ -6812,15 +7804,14 @@ int QString::toInt(bool *ok, int base) const
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toInt(), QLocale::toUInt()
*/
-uint QString::toUInt(bool *ok, int base) const
-{
- return toIntegral_helper<uint>(*this, ok, base);
-}
-
/*!
+ \fn short QString::toShort(bool *ok, int base) const
+
Returns the string converted to a \c short using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
@@ -6828,12 +7819,13 @@ uint QString::toUInt(bool *ok, int base) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toShort()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toShort()
Example:
@@ -6841,15 +7833,14 @@ uint QString::toUInt(bool *ok, int base) const
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toUShort(), toInt(), QLocale::toShort()
*/
-short QString::toShort(bool *ok, int base) const
-{
- return toIntegral_helper<short>(*this, ok, base);
-}
-
/*!
+ \fn ushort QString::toUShort(bool *ok, int base) const
+
Returns the string converted to an \c{unsigned short} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
@@ -6857,12 +7848,13 @@ short QString::toShort(bool *ok, int base) const
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If \a base is 0, the C language convention is used: if the string begins
+ with "0x", base 16 is used; otherwise, if the string begins with "0b", base
+ 2 is used; otherwise, if the string begins with "0", base 8 is used;
+ otherwise, base 10 is used.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toUShort()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toUShort()
Example:
@@ -6870,15 +7862,11 @@ short QString::toShort(bool *ok, int base) const
This function ignores leading and trailing whitespace.
+ \note Support for the "0b" prefix was added in Qt 6.4.
+
\sa number(), toShort(), QLocale::toUShort()
*/
-ushort QString::toUShort(bool *ok, int base) const
-{
- return toIntegral_helper<ushort>(*this, ok, base);
-}
-
-
/*!
Returns the string converted to a \c double value.
@@ -6897,8 +7885,8 @@ ushort QString::toUShort(bool *ok, int base) const
\snippet qstring/main.cpp 67
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toDouble()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toDouble()
\snippet qstring/main.cpp 68
@@ -6915,7 +7903,18 @@ ushort QString::toUShort(bool *ok, int base) const
double QString::toDouble(bool *ok) const
{
- return QLocaleData::c()->stringToDouble(*this, ok, QLocale::RejectGroupSeparator);
+ return QStringView(*this).toDouble(ok);
+}
+
+double QStringView::toDouble(bool *ok) const
+{
+ QStringView string = qt_trimmed(*this);
+ QVarLengthArray<uchar> latin1(string.size());
+ qt_to_latin1(latin1.data(), string.utf16(), string.size());
+ auto r = qt_asciiToDouble(reinterpret_cast<const char *>(latin1.data()), string.size());
+ if (ok != nullptr)
+ *ok = r.ok();
+ return r.result;
}
/*!
@@ -6932,8 +7931,8 @@ double QString::toDouble(bool *ok) const
notation, and the decimal point. Including the unit or additional characters
leads to a conversion error.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toFloat()
+ The string conversion will always happen in the 'C' locale. For
+ locale-dependent conversion use QLocale::toFloat()
For historical reasons, this function does not handle
thousands group separators. If you need to convert such numbers,
@@ -6953,13 +7952,17 @@ float QString::toFloat(bool *ok) const
return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
}
+float QStringView::toFloat(bool *ok) const
+{
+ return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
+}
+
/*! \fn QString &QString::setNum(int n, int base)
Sets the string to the printed value of \a n in the specified \a
base, and returns a reference to the string.
- The base is 10 by default and must be between 2 and 36. For bases
- other than 10, \a n is treated as an unsigned integer.
+ The base is 10 by default and must be between 2 and 36.
\snippet qstring/main.cpp 56
@@ -7012,26 +8015,17 @@ QString &QString::setNum(qulonglong n, int base)
*/
/*!
- \fn QString &QString::setNum(double n, char format, int precision)
\overload
- Sets the string to the printed value of \a n, formatted according
- to the given \a format and \a precision, and returns a reference
- to the string.
-
- The \a format can be 'e', 'E', 'f', 'g' or 'G' (see
- \l{Argument Formats} for an explanation of the formats).
-
- The formatting always uses QLocale::C, i.e., English/UnitedStates.
- To get a localized string representation of a number, use
- QLocale::toString() with the appropriate locale.
+ Sets the string to the printed value of \a n, formatted according to the
+ given \a format and \a precision, and returns a reference to the string.
- \sa number()
+ \sa number(), QLocale::FloatingPointPrecisionOption, {Number Formats}
*/
-QString &QString::setNum(double n, char f, int prec)
+QString &QString::setNum(double n, char format, int precision)
{
- return *this = number(n, f, prec);
+ return *this = number(n, format, precision);
}
/*!
@@ -7111,7 +8105,12 @@ QString QString::number(qlonglong n, int base)
base = 10;
}
#endif
- return QLocaleData::c()->longLongToString(n, -1, base);
+ bool negative = n < 0;
+ /*
+ Negating std::numeric_limits<qlonglong>::min() hits undefined behavior, so
+ taking an absolute value has to take a slight detour.
+ */
+ return qulltoBasicLatin(negative ? 1u + qulonglong(-(n + 1)) : qulonglong(n), base, negative);
}
/*!
@@ -7125,31 +8124,26 @@ QString QString::number(qulonglong n, int base)
base = 10;
}
#endif
- return QLocaleData::c()->unsLongLongToString(n, -1, base);
+ return qulltoBasicLatin(n, base, false);
}
/*!
- \fn QString QString::number(double n, char format, int precision)
+ Returns a string representing the floating-point number \a n.
- Returns a string equivalent of the number \a n, formatted
- according to the specified \a format and \a precision. See
- \l{Argument Formats} for details.
+ Returns a string that represents \a n, formatted according to the specified
+ \a format and \a precision.
- Unlike QLocale::toString(), this function does not honor the
- user's locale settings.
+ For formats with an exponent, the exponent will show its sign and have at
+ least two digits, left-padding the exponent with zero if needed.
- \sa setNum(), QLocale::toString()
+ \sa setNum(), QLocale::toString(), QLocale::FloatingPointPrecisionOption, {Number Formats}
*/
-QString QString::number(double n, char f, int prec)
+QString QString::number(double n, char format, int precision)
{
QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
- uint flags = QLocaleData::ZeroPadExponent;
- if (qIsUpper(f))
- flags |= QLocaleData::CapitalEorX;
-
- switch (qToLower(f)) {
+ switch (QtMiscUtils::toAsciiLower(format)) {
case 'f':
form = QLocaleData::DFDecimal;
break;
@@ -7161,12 +8155,12 @@ QString QString::number(double n, char f, int prec)
break;
default:
#if defined(QT_CHECK_RANGE)
- qWarning("QString::setNum: Invalid format char '%c'", f);
+ qWarning("QString::setNum: Invalid format char '%c'", format);
#endif
break;
}
- return QLocaleData::c()->doubleToString(n, prec, form, -1, flags);
+ return qdtoBasicLatin(n, form, precision, isAsciiUpper(format));
}
namespace {
@@ -7180,12 +8174,12 @@ static ResultList splitString(const StringSource &source, QStringView sep,
typename StringSource::size_type extra = 0;
while ((end = QtPrivate::findString(QStringView(source.constData(), source.size()), start + extra, sep, cs)) != -1) {
if (start != end || behavior == Qt::KeepEmptyParts)
- list.append(source.mid(start, end - start));
+ list.append(source.sliced(start, end - start));
start = end + sep.size();
extra = (sep.size() == 0 ? 1 : 0);
}
if (start != source.size() || behavior == Qt::KeepEmptyParts)
- list.append(source.mid(start));
+ list.append(source.sliced(start));
return list;
}
@@ -7200,7 +8194,7 @@ static ResultList splitString(const StringSource &source, QStringView sep,
\a cs specifies whether \a sep should be matched case
sensitively or case insensitively.
- If \a behavior is QString::SkipEmptyParts, empty entries don't
+ If \a behavior is Qt::SkipEmptyParts, empty entries don't
appear in the result. By default, empty entries are kept.
Example:
@@ -7227,24 +8221,6 @@ QStringList QString::split(const QString &sep, Qt::SplitBehavior behavior, Qt::C
}
/*!
- Splits the string into substring references wherever \a sep occurs, and
- returns the list of those strings.
-
- See QString::split() for how \a sep, \a behavior and \a cs interact to form
- the result.
-
- \note All references are valid as long this string is alive. Destroying this
- string will cause all references to be dangling pointers.
-
- \since 5.14
- \sa QStringRef split()
-*/
-QList<QStringRef> QString::splitRef(const QString &sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
-{
- return splitString<QList<QStringRef>>(QStringRef(this), sep, behavior, cs);
-}
-
-/*!
\overload
\since 5.14
*/
@@ -7254,53 +8230,19 @@ QStringList QString::split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensit
}
/*!
- \overload
- \since 5.14
-*/
-QList<QStringRef> QString::splitRef(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
-{
- return splitString<QList<QStringRef>>(QStringRef(this), QStringView(&sep, 1), behavior, cs);
-}
-
-/*!
- Splits the string into substrings references wherever \a sep occurs, and
- returns the list of those strings.
-
- See QString::split() for how \a sep, \a behavior and \a cs interact to form
- the result.
-
- \note All references are valid as long this string is alive. Destroying this
- string will cause all references to be dangling pointers.
-
- \since 5.14
-*/
-QList<QStringRef> QStringRef::split(const QString &sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
-{
- return splitString<QList<QStringRef>>(*this, sep, behavior, cs);
-}
-
-/*!
- \overload
- \since 5.14
-*/
-QList<QStringRef> QStringRef::split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
-{
- return splitString<QList<QStringRef>>(*this, QStringView(&sep, 1), behavior, cs);
-}
-
-/*!
\fn QList<QStringView> QStringView::split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
\fn QList<QStringView> QStringView::split(QStringView sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
- Splits the string into substring references wherever \a sep occurs, and
- returns the list of those strings.
+ Splits the view into substring views wherever \a sep occurs, and
+ returns the list of those string views.
See QString::split() for how \a sep, \a behavior and \a cs interact to form
the result.
- \note All references are valid as long this string is alive. Destroying this
- string will cause all references to be dangling pointers.
+ \note All the returned views are valid as long as the data referenced by
+ this string view is valid. Destroying the data will cause all views to
+ become dangling.
\since 6.0
*/
@@ -7316,29 +8258,30 @@ QList<QStringView> QStringView::split(QChar sep, Qt::SplitBehavior behavior, Qt:
#if QT_CONFIG(regularexpression)
namespace {
-template<class ResultList, typename String>
+template<class ResultList, typename String, typename MatchingFunction>
static ResultList splitString(const String &source, const QRegularExpression &re,
+ MatchingFunction matchingFunction,
Qt::SplitBehavior behavior)
{
ResultList list;
if (!re.isValid()) {
- qWarning("QString::split: invalid QRegularExpression object");
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString::split");
return list;
}
- int start = 0;
- int end = 0;
- QRegularExpressionMatchIterator iterator = re.globalMatch(source);
+ qsizetype start = 0;
+ qsizetype end = 0;
+ QRegularExpressionMatchIterator iterator = (re.*matchingFunction)(source, 0, QRegularExpression::NormalMatch, QRegularExpression::NoMatchOption);
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
end = match.capturedStart();
if (start != end || behavior == Qt::KeepEmptyParts)
- list.append(source.mid(start, end - start));
+ list.append(source.sliced(start, end - start));
start = match.capturedEnd();
}
if (start != source.size() || behavior == Qt::KeepEmptyParts)
- list.append(source.mid(start));
+ list.append(source.sliced(start));
return list;
}
@@ -7373,44 +8316,33 @@ static ResultList splitString(const String &source, const QRegularExpression &re
*/
QStringList QString::split(const QRegularExpression &re, Qt::SplitBehavior behavior) const
{
- return splitString<QStringList>(*this, re, behavior);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ const auto matchingFunction = qOverload<const QString &, qsizetype, QRegularExpression::MatchType, QRegularExpression::MatchOptions>(&QRegularExpression::globalMatch);
+#else
+ const auto matchingFunction = &QRegularExpression::globalMatch;
+#endif
+ return splitString<QStringList>(*this,
+ re,
+ matchingFunction,
+ behavior);
}
/*!
\overload
- \since 5.14
-
- Splits the string into substring references wherever the regular expression
- \a re matches, and returns the list of those strings. If \a re
- does not match anywhere in the string, splitRef() returns a
- single-element list containing this string reference.
-
- \note All references are valid as long this string is alive. Destroying this
- string will cause all references to be dangling pointers.
-
- \sa split() QStringRef
-*/
-QList<QStringRef> QString::splitRef(const QRegularExpression &re, Qt::SplitBehavior behavior) const
-{
- return splitString<QList<QStringRef>>(QStringRef(this), re, behavior);
-}
-
-/*!
\since 6.0
- Splits the string into substring views wherever the regular expression
- \a re matches, and returns the list of those strings. If \a re
- does not match anywhere in the string, splitRef() returns a
- single-element list containing this string reference.
-
- \note All references are valid as long this string is alive. Destroying this
- string will cause all references to be dangling pointers.
+ Splits the string into substring views wherever the regular expression \a re
+ matches, and returns the list of those strings. If \a re does not match
+ anywhere in the string, split() returns a single-element list containing
+ this string as view.
- \sa split() QStringRef
+ \note The views in the returned list are sub-views of this view; as such,
+ they reference the same data as it and only remain valid for as long as that
+ data remains live.
*/
QList<QStringView> QStringView::split(const QRegularExpression &re, Qt::SplitBehavior behavior) const
{
- return splitString<QList<QStringView>>(*this, re, behavior);
+ return splitString<QList<QStringView>>(*this, re, &QRegularExpression::globalMatchView, behavior);
}
#endif // QT_CONFIG(regularexpression)
@@ -7426,7 +8358,7 @@ QList<QStringView> QStringView::split(const QRegularExpression &re, Qt::SplitBeh
\value NormalizationForm_KC Compatibility Decomposition followed by Canonical Composition
\sa normalized(),
- {http://www.unicode.org/reports/tr15/}{Unicode Standard Annex #15}
+ {https://www.unicode.org/reports/tr15/}{Unicode Standard Annex #15}
*/
/*!
@@ -7440,7 +8372,7 @@ QList<QStringView> QStringView::split(const QRegularExpression &re, Qt::SplitBeh
\snippet code/src_corelib_text_qstring.cpp 8
*/
-QString QString::repeated(int times) const
+QString QString::repeated(qsizetype times) const
{
if (d.size == 0)
return *this;
@@ -7451,7 +8383,7 @@ QString QString::repeated(int times) const
return QString();
}
- const int resultSize = times * d.size;
+ const qsizetype resultSize = times * d.size;
QString result;
result.reserve(resultSize);
@@ -7460,10 +8392,10 @@ QString QString::repeated(int times) const
memcpy(result.d.data(), d.data(), d.size * sizeof(QChar));
- int sizeSoFar = d.size;
+ qsizetype sizeSoFar = d.size;
char16_t *end = result.d.data() + sizeSoFar;
- const int halfResultSize = resultSize >> 1;
+ const qsizetype halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
memcpy(end, result.d.data(), sizeSoFar * sizeof(QChar));
end += sizeSoFar;
@@ -7475,29 +8407,32 @@ QString QString::repeated(int times) const
return result;
}
-void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from)
+void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, qsizetype from)
{
- const QChar *p = data->constData() + from;
- if (isAscii(p, p + data->length() - from))
- return;
- if (p > data->constData() + from)
- from = p - data->constData() - 1; // need one before the non-ASCII to perform NFC
+ {
+ // check if it's fully ASCII first, because then we have no work
+ auto start = reinterpret_cast<const char16_t *>(data->constData());
+ const char16_t *p = start + from;
+ if (isAscii_helper(p, p + data->size() - from))
+ return;
+ if (p > start + from)
+ from = p - start - 1; // need one before the non-ASCII to perform NFC
+ }
if (version == QChar::Unicode_Unassigned) {
version = QChar::currentUnicodeVersion();
} else if (int(version) <= NormalizationCorrectionsVersionMax) {
const QString &s = *data;
QChar *d = nullptr;
- for (int i = 0; i < NumNormalizationCorrections; ++i) {
- const NormalizationCorrection &n = uc_normalization_corrections[i];
+ for (const NormalizationCorrection &n : uc_normalization_corrections) {
if (n.version > version) {
- int pos = from;
+ qsizetype pos = from;
if (QChar::requiresSurrogates(n.ucs4)) {
char16_t ucs4High = QChar::highSurrogate(n.ucs4);
char16_t ucs4Low = QChar::lowSurrogate(n.ucs4);
char16_t oldHigh = QChar::highSurrogate(n.old_mapping);
char16_t oldLow = QChar::lowSurrogate(n.old_mapping);
- while (pos < s.length() - 1) {
+ while (pos < s.size() - 1) {
if (s.at(pos).unicode() == ucs4High && s.at(pos + 1).unicode() == ucs4Low) {
if (!d)
d = data->data();
@@ -7507,7 +8442,7 @@ void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::
++pos;
}
} else {
- while (pos < s.length()) {
+ while (pos < s.size()) {
if (s.at(pos).unicode() == n.ucs4) {
if (!d)
d = data->data();
@@ -7544,14 +8479,42 @@ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersi
return copy;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+static void checkArgEscape(QStringView s)
+{
+ // If we're in here, it means that qArgDigitValue has accepted the
+ // digit. We can skip the check in case we already know it will
+ // succeed.
+ if (!supportUnicodeDigitValuesInArg())
+ return;
+
+ const auto isNonAsciiDigit = [](QChar c) {
+ return c.unicode() < u'0' || c.unicode() > u'9';
+ };
+
+ if (std::any_of(s.begin(), s.end(), isNonAsciiDigit)) {
+ const auto accumulateDigit = [](int partial, QChar digit) {
+ return partial * 10 + digit.digitValue();
+ };
+ const int parsedNumber = std::accumulate(s.begin(), s.end(), 0, accumulateDigit);
+
+ qWarning("QString::arg(): the replacement \"%%%ls\" contains non-ASCII digits;\n"
+ " it is currently being interpreted as the %d-th substitution.\n"
+ " This is deprecated; support for non-ASCII digits will be dropped\n"
+ " in a future version of Qt.",
+ qUtf16Printable(s.toString()),
+ parsedNumber);
+ }
+}
+#endif
struct ArgEscapeData
{
int min_escape; // lowest escape sequence number
- int occurrences; // number of occurrences of the lowest escape sequence number
- int locale_occurrences; // number of occurrences of the lowest escape sequence number that
- // contain 'L'
- int escape_len; // total length of escape sequences which will be replaced
+ qsizetype occurrences; // number of occurrences of the lowest escape sequence number
+ qsizetype locale_occurrences; // number of occurrences of the lowest escape sequence number that
+ // contain 'L'
+ qsizetype escape_len; // total length of escape sequences which will be replaced
};
static ArgEscapeData findArgEscapes(QStringView s)
@@ -7584,20 +8547,34 @@ static ArgEscapeData findArgEscapes(QStringView s)
break;
}
- int escape = c->digitValue();
+ int escape = qArgDigitValue(*c);
if (escape == -1)
continue;
+ // ### Qt 7: do not allow anything but ASCII digits
+ // in arg()'s replacements.
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ const QChar *escapeBegin = c;
+ const QChar *escapeEnd = escapeBegin + 1;
+#endif
+
++c;
if (c != uc_end) {
- int next_escape = c->digitValue();
+ const int next_escape = qArgDigitValue(*c);
if (next_escape != -1) {
escape = (10 * escape) + next_escape;
++c;
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ ++escapeEnd;
+#endif
}
}
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ checkArgEscape(QStringView(escapeBegin, escapeEnd));
+#endif
+
if (escape > d.min_escape)
continue;
@@ -7616,101 +8593,85 @@ static ArgEscapeData findArgEscapes(QStringView s)
return d;
}
-static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, int field_width,
+static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, qsizetype field_width,
QStringView arg, QStringView larg, QChar fillChar)
{
- const QChar *uc_begin = s.begin();
- const QChar *uc_end = s.end();
-
- int abs_field_width = qAbs(field_width);
- int result_len = s.length()
- - d.escape_len
- + (d.occurrences - d.locale_occurrences)
- *qMax(abs_field_width, arg.length())
- + d.locale_occurrences
- *qMax(abs_field_width, larg.length());
+ // Negative field-width for right-padding, positive for left-padding:
+ const qsizetype abs_field_width = qAbs(field_width);
+ const qsizetype result_len =
+ s.size() - d.escape_len
+ + (d.occurrences - d.locale_occurrences) * qMax(abs_field_width, arg.size())
+ + d.locale_occurrences * qMax(abs_field_width, larg.size());
QString result(result_len, Qt::Uninitialized);
- QChar *result_buff = (QChar*) result.unicode();
+ QChar *rc = const_cast<QChar *>(result.unicode());
+ QChar *const result_end = rc + result_len;
+ qsizetype repl_cnt = 0;
- QChar *rc = result_buff;
- const QChar *c = uc_begin;
- int repl_cnt = 0;
+ const QChar *c = s.begin();
+ const QChar *const uc_end = s.end();
while (c != uc_end) {
- /* We don't have to check if we run off the end of the string with c,
- because as long as d.occurrences > 0 we KNOW there are valid escape
- sequences. */
+ Q_ASSERT(d.occurrences > repl_cnt);
+ /* We don't have to check increments of c against uc_end because, as
+ long as d.occurrences > repl_cnt, we KNOW there are valid escape
+ sequences remaining. */
const QChar *text_start = c;
-
while (c->unicode() != '%')
++c;
const QChar *escape_start = c++;
-
- bool locale_arg = false;
- if (c->unicode() == 'L') {
- locale_arg = true;
+ const bool localize = c->unicode() == 'L';
+ if (localize)
++c;
- }
- int escape = c->digitValue();
- if (escape != -1) {
- if (c + 1 != uc_end && (c + 1)->digitValue() != -1) {
- escape = (10 * escape) + (c + 1)->digitValue();
+ int escape = qArgDigitValue(*c);
+ if (escape != -1 && c + 1 != uc_end) {
+ const int digit = qArgDigitValue(c[1]);
+ if (digit != -1) {
++c;
+ escape = 10 * escape + digit;
}
}
if (escape != d.min_escape) {
- memcpy(rc, text_start, (c - text_start)*sizeof(QChar));
+ memcpy(rc, text_start, (c - text_start) * sizeof(QChar));
rc += c - text_start;
- }
- else {
+ } else {
++c;
- memcpy(rc, text_start, (escape_start - text_start)*sizeof(QChar));
+ memcpy(rc, text_start, (escape_start - text_start) * sizeof(QChar));
rc += escape_start - text_start;
- uint pad_chars;
- if (locale_arg)
- pad_chars = qMax(abs_field_width, larg.length()) - larg.length();
- else
- pad_chars = qMax(abs_field_width, arg.length()) - arg.length();
+ const QStringView use = localize ? larg : arg;
+ const qsizetype pad_chars = abs_field_width - use.size();
+ // (If negative, relevant loops are no-ops: no need to check.)
if (field_width > 0) { // left padded
- for (uint i = 0; i < pad_chars; ++i)
- *rc++ = fillChar;
+ rc = std::fill_n(rc, pad_chars, fillChar);
}
- if (locale_arg) {
- memcpy(rc, larg.data(), larg.length()*sizeof(QChar));
- rc += larg.length();
- }
- else {
- memcpy(rc, arg.data(), arg.length()*sizeof(QChar));
- rc += arg.length();
- }
+ if (use.size())
+ memcpy(rc, use.data(), use.size() * sizeof(QChar));
+ rc += use.size();
if (field_width < 0) { // right padded
- for (uint i = 0; i < pad_chars; ++i)
- *rc++ = fillChar;
+ rc = std::fill_n(rc, pad_chars, fillChar);
}
if (++repl_cnt == d.occurrences) {
- memcpy(rc, c, (uc_end - c)*sizeof(QChar));
+ memcpy(rc, c, (uc_end - c) * sizeof(QChar));
rc += uc_end - c;
- Q_ASSERT(rc - result_buff == result_len);
+ Q_ASSERT(rc == result_end);
c = uc_end;
}
}
}
- Q_ASSERT(rc == result_buff + result_len);
+ Q_ASSERT(rc == result_end);
return result;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a copy of this string with the lowest numbered place marker
replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
@@ -7744,7 +8705,6 @@ QString QString::arg(const QString &a, int fieldWidth, QChar fillChar) const
{
return arg(qToStringViewIgnoringNull(a), fieldWidth, fillChar);
}
-#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\overload
@@ -7795,7 +8755,7 @@ QString QString::arg(QStringView a, int fieldWidth, QChar fillChar) const
\since 5.10
Returns a copy of this string with the lowest-numbered place-marker
- replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
+ replaced by the Latin-1 string viewed by \a a, i.e., \c %1, \c %2, ..., \c %99.
\a fieldWidth specifies the minimum amount of space that \a a
shall occupy. If \a a requires less space than \a fieldWidth, it
@@ -7814,109 +8774,12 @@ QString QString::arg(QStringView a, int fieldWidth, QChar fillChar) const
is printed and the result is undefined. Place-marker numbers must be
in the range 1 to 99.
*/
-QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
+QString QString::arg(QLatin1StringView a, int fieldWidth, QChar fillChar) const
{
- QVarLengthArray<char16_t> utf16(a.size());
- qt_from_latin1(utf16.data(), a.data(), a.size());
+ QVarLengthArray<char16_t> utf16 = qt_from_latin1_to_qvla(a);
return arg(QStringView(utf16.data(), utf16.size()), fieldWidth, fillChar);
}
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2) const
- \overload arg()
-
- This is the same as \c {str.arg(a1).arg(a2)}, except that the
- strings \a a1 and \a a2 are replaced in one pass. This can make a
- difference if \a a1 contains e.g. \c{%1}:
-
- \snippet qstring/main.cpp 13
-
- A similar problem occurs when the numbered place markers are not
- white space separated:
-
- \snippet qstring/main.cpp 12
- \snippet qstring/main.cpp 97
-
- Let's look at the substitutions:
- \list
- \li First, \c Hello replaces \c {%1} so the string becomes \c {"Hello%3%2"}.
- \li Then, \c 20 replaces \c {%2} so the string becomes \c {"Hello%320"}.
- \li Since the maximum numbered place marker value is 99, \c 50 replaces \c {%32}.
- \endlist
- Thus the string finally becomes \c {"Hello500"}.
-
- In such cases, the following yields the expected results:
-
- \snippet qstring/main.cpp 12
- \snippet qstring/main.cpp 98
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3) const
- \overload arg()
-
- This is the same as calling \c str.arg(a1).arg(a2).arg(a3), except
- that the strings \a a1, \a a2 and \a a3 are replaced in one pass.
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4) const
- \overload arg()
-
- This is the same as calling \c
- {str.arg(a1).arg(a2).arg(a3).arg(a4)}, except that the strings \a
- a1, \a a2, \a a3 and \a a4 are replaced in one pass.
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5) const
- \overload arg()
-
- This is the same as calling \c
- {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5)}, except that the strings
- \a a1, \a a2, \a a3, \a a4, and \a a5 are replaced in one pass.
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6) const
- \overload arg()
-
- This is the same as calling \c
- {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6))}, except that
- the strings \a a1, \a a2, \a a3, \a a4, \a a5, and \a a6 are
- replaced in one pass.
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6, const QString& a7) const
- \overload arg()
-
- This is the same as calling \c
- {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6).arg(a7)},
- except that the strings \a a1, \a a2, \a a3, \a a4, \a a5, \a a6,
- and \a a7 are replaced in one pass.
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6, const QString& a7, const QString& a8) const
- \overload arg()
-
- This is the same as calling \c
- {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6).arg(a7).arg(a8)},
- except that the strings \a a1, \a a2, \a a3, \a a4, \a a5, \a a6, \a
- a7, and \a a8 are replaced in one pass.
-*/
-
-/*!
- \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6, const QString& a7, const QString& a8, const QString& a9) const
- \overload arg()
-
- This is the same as calling \c
- {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6).arg(a7).arg(a8).arg(a9)},
- except that the strings \a a1, \a a2, \a a3, \a a4, \a a5, \a a6, \a
- a7, \a a8, and \a a9 are replaced in one pass.
-*/
-
/*! \fn QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const
\overload arg()
@@ -7932,15 +8795,13 @@ QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
The '%' can be followed by an 'L', in which case the sequence is
replaced with a localized representation of \a a. The conversion
uses the default locale, set by QLocale::setDefault(). If no default
- locale was specified, the "C" locale is used. The 'L' flag is
+ locale was specified, the system locale is used. The 'L' flag is
ignored if \a base is not 10.
\snippet qstring/main.cpp 12
\snippet qstring/main.cpp 14
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
/*! \fn QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const
@@ -7949,9 +8810,7 @@ QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
The \a base argument specifies the base to use when converting the
integer \a a into a string. The base must be between 2 and 36.
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
/*! \fn QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const
@@ -7975,12 +8834,11 @@ QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
\snippet qstring/main.cpp 12
\snippet qstring/main.cpp 14
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
-/*! \fn QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const
+/*!
+ \fn QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const
\overload arg()
\a fieldWidth specifies the minimum amount of space that \a a is
@@ -7992,9 +8850,7 @@ QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
integer \a a to a string. The base must be between 2 and 36, with 8
giving octal, 10 decimal, and 16 hexadecimal numbers.
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
/*!
@@ -8009,9 +8865,7 @@ QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
integer \a a into a string. The base must be between 2 and 36, with
8 giving octal, 10 decimal, and 16 hexadecimal numbers.
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
{
@@ -8023,22 +8877,26 @@ QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) cons
}
unsigned flags = QLocaleData::NoFlags;
- if (fillChar == QLatin1Char('0'))
+ // ZeroPadded sorts out left-padding when the fill is zero, to the right of sign:
+ if (fillChar == u'0')
flags = QLocaleData::ZeroPadded;
QString arg;
- if (d.occurrences > d.locale_occurrences)
+ if (d.occurrences > d.locale_occurrences) {
arg = QLocaleData::c()->longLongToString(a, -1, base, fieldWidth, flags);
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= arg.size());
+ }
- QString locale_arg;
+ QString localeArg;
if (d.locale_occurrences > 0) {
QLocale locale;
if (!(locale.numberOptions() & QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
- locale_arg = locale.d->m_data->longLongToString(a, -1, base, fieldWidth, flags);
+ flags |= QLocaleData::GroupDigits;
+ localeArg = locale.d->m_data->longLongToString(a, -1, base, fieldWidth, flags);
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= localeArg.size());
}
- return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
+ return replaceArgEscapes(*this, d, fieldWidth, arg, localeArg, fillChar);
}
/*!
@@ -8053,9 +8911,7 @@ QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) cons
integer \a a into a string. \a base must be between 2 and 36, with 8
giving octal, 10 decimal, and 16 hexadecimal numbers.
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
QString QString::arg(qulonglong a, int fieldWidth, int base, QChar fillChar) const
{
@@ -8067,22 +8923,26 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, QChar fillChar) con
}
unsigned flags = QLocaleData::NoFlags;
- if (fillChar == QLatin1Char('0'))
+ // ZeroPadded sorts out left-padding when the fill is zero, to the right of sign:
+ if (fillChar == u'0')
flags = QLocaleData::ZeroPadded;
QString arg;
- if (d.occurrences > d.locale_occurrences)
+ if (d.occurrences > d.locale_occurrences) {
arg = QLocaleData::c()->unsLongLongToString(a, -1, base, fieldWidth, flags);
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= arg.size());
+ }
- QString locale_arg;
+ QString localeArg;
if (d.locale_occurrences > 0) {
QLocale locale;
if (!(locale.numberOptions() & QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
- locale_arg = locale.d->m_data->unsLongLongToString(a, -1, base, fieldWidth, flags);
+ flags |= QLocaleData::GroupDigits;
+ localeArg = locale.d->m_data->unsLongLongToString(a, -1, base, fieldWidth, flags);
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= localeArg.size());
}
- return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
+ return replaceArgEscapes(*this, d, fieldWidth, arg, localeArg, fillChar);
}
/*!
@@ -8099,9 +8959,7 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, QChar fillChar) con
integer \a a into a string. The base must be between 2 and 36, with
8 giving octal, 10 decimal, and 16 hexadecimal numbers.
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
/*!
@@ -8117,9 +8975,7 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, QChar fillChar) con
integer \a a into a string. The base must be between 2 and 36, with
8 giving octal, 10 decimal, and 16 hexadecimal numbers.
- If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is
- used. For negative numbers, zero padding might appear before the
- minus sign.
+ \sa {Number Formats}
*/
/*!
@@ -8141,11 +8997,10 @@ QString QString::arg(char a, int fieldWidth, QChar fillChar) const
}
/*!
- \fn QString QString::arg(double a, int fieldWidth, char format, int precision, QChar fillChar) const
\overload arg()
Argument \a a is formatted according to the specified \a format and
- \a precision. See \l{Argument Formats} for details.
+ \a precision. See \l{Floating-point Formats} for details.
\a fieldWidth specifies the minimum amount of space that \a a is
padded to and filled with the character \a fillChar. A positive
@@ -8154,18 +9009,9 @@ QString QString::arg(char a, int fieldWidth, QChar fillChar) const
\snippet code/src_corelib_text_qstring.cpp 2
- The '%' can be followed by an 'L', in which case the sequence is
- replaced with a localized representation of \a a. The conversion
- uses the default locale, set by QLocale::setDefault(). If no
- default locale was specified, the "C" locale is used.
-
- If \a fillChar is '0' (the number 0, ASCII 48), this function will
- use the locale's zero to pad. For negative numbers, the zero padding
- will probably appear before the minus sign.
-
- \sa QLocale::toString()
+ \sa QLocale::toString(), QLocale::FloatingPointPrecisionOption, {Number Formats}
*/
-QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillChar) const
+QString QString::arg(double a, int fieldWidth, char format, int precision, QChar fillChar) const
{
ArgEscapeData d = findArgEscapes(*this);
@@ -8175,14 +9021,15 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha
}
unsigned flags = QLocaleData::NoFlags;
- if (fillChar == QLatin1Char('0'))
+ // ZeroPadded sorts out left-padding when the fill is zero, to the right of sign:
+ if (fillChar == u'0')
flags |= QLocaleData::ZeroPadded;
- if (qIsUpper(fmt))
+ if (isAsciiUpper(format))
flags |= QLocaleData::CapitalEorX;
QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
- switch (qToLower(fmt)) {
+ switch (QtMiscUtils::toAsciiLower(format)) {
case 'f':
form = QLocaleData::DFDecimal;
break;
@@ -8194,58 +9041,63 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha
break;
default:
#if defined(QT_CHECK_RANGE)
- qWarning("QString::arg: Invalid format char '%c'", fmt);
+ qWarning("QString::arg: Invalid format char '%c'", format);
#endif
break;
}
QString arg;
- if (d.occurrences > d.locale_occurrences)
- arg = QLocaleData::c()->doubleToString(a, prec, form, fieldWidth, flags | QLocaleData::ZeroPadExponent);
+ if (d.occurrences > d.locale_occurrences) {
+ arg = QLocaleData::c()->doubleToString(a, precision, form, fieldWidth,
+ flags | QLocaleData::ZeroPadExponent);
+ Q_ASSERT(fillChar != u'0' || !qt_is_finite(a)
+ || fieldWidth <= arg.size());
+ }
- QString locale_arg;
+ QString localeArg;
if (d.locale_occurrences > 0) {
QLocale locale;
const QLocale::NumberOptions numberOptions = locale.numberOptions();
if (!(numberOptions & QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
+ flags |= QLocaleData::GroupDigits;
if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
flags |= QLocaleData::AddTrailingZeroes;
- locale_arg = locale.d->m_data->doubleToString(a, prec, form, fieldWidth, flags);
+ localeArg = locale.d->m_data->doubleToString(a, precision, form, fieldWidth, flags);
+ Q_ASSERT(fillChar != u'0' || !qt_is_finite(a)
+ || fieldWidth <= localeArg.size());
}
- return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
+ return replaceArgEscapes(*this, d, fieldWidth, arg, localeArg, fillChar);
}
static inline char16_t to_unicode(const QChar c) { return c.unicode(); }
static inline char16_t to_unicode(const char c) { return QLatin1Char{c}.unicode(); }
template <typename Char>
-static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumber = 999)
+static int getEscape(const Char *uc, qsizetype *pos, qsizetype len)
{
- int i = *pos;
+ qsizetype i = *pos;
++i;
- if (i < len && uc[i] == QLatin1Char('L'))
+ if (i < len && uc[i] == u'L')
++i;
if (i < len) {
int escape = to_unicode(uc[i]) - '0';
if (uint(escape) >= 10U)
return -1;
++i;
- while (i < len) {
+ if (i < len) {
+ // there's a second digit
int digit = to_unicode(uc[i]) - '0';
- if (uint(digit) >= 10U)
- break;
- escape = (escape * 10) + digit;
- ++i;
- }
- if (escape <= maxNumber) {
- *pos = i;
- return escape;
+ if (uint(digit) < 10U) {
+ escape = (escape * 10) + digit;
+ ++i;
+ }
}
+ *pos = i;
+ return escape;
}
return -1;
}
@@ -8263,7 +9115,7 @@ static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumbe
the int contains the numerical number as parsed from the placeholder.
3. Next, collect all the non-negative ints found, sort them in ascending order and
remove duplicates.
- 3a. If the result has more entires than multiArg() was given replacement strings,
+ 3a. If the result has more entries than multiArg() was given replacement strings,
we have found placeholders we can't satisfy with replacement strings. That is
fine (there could be another .arg() call coming after this one), so just
truncate the result to the number of actual multiArg() replacement strings.
@@ -8288,13 +9140,13 @@ namespace {
struct Part
{
Part() = default; // for QVarLengthArray; do not use
- Q_DECL_CONSTEXPR Part(QStringView s, int num = -1)
+ constexpr Part(QStringView s, int num = -1)
: tag{QtPrivate::ArgBase::U16}, number{num}, data{s.utf16()}, size{s.size()} {}
- Q_DECL_CONSTEXPR Part(QLatin1String s, int num = -1)
+ constexpr Part(QLatin1StringView s, int num = -1)
: tag{QtPrivate::ArgBase::L1}, number{num}, data{s.data()}, size{s.size()} {}
void reset(QStringView s) noexcept { *this = {s, number}; }
- void reset(QLatin1String s) noexcept { *this = {s, number}; }
+ void reset(QLatin1StringView s) noexcept { *this = {s, number}; }
QtPrivate::ArgBase::Tag tag;
int number;
@@ -8324,13 +9176,13 @@ static ParseResult parseMultiArgFormatString(StringView s)
qsizetype last = 0;
while (i < end) {
- if (uc[i] == QLatin1Char('%')) {
+ if (uc[i] == u'%') {
qsizetype percent = i;
int number = getEscape(uc, &i, len);
if (number != -1) {
if (last != percent)
- result.push_back(Part{s.mid(last, percent - last)}); // literal text (incl. failed placeholders)
- result.push_back(Part{s.mid(percent, i - percent), number}); // parsed placeholder
+ result.push_back(Part{s.sliced(last, percent - last)}); // literal text (incl. failed placeholders)
+ result.push_back(Part{s.sliced(percent, i - percent), number}); // parsed placeholder
last = i;
continue;
}
@@ -8339,7 +9191,7 @@ static ParseResult parseMultiArgFormatString(StringView s)
}
if (last < len)
- result.push_back(Part{s.mid(last, len - last)}); // trailing literal text
+ result.push_back(Part{s.sliced(last, len - last)}); // trailing literal text
return result;
}
@@ -8348,7 +9200,7 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult &
{
ArgIndexToPlaceholderMap result;
- for (Part part : parts) {
+ for (const Part &part : parts) {
if (part.number >= 0)
result.push_back(part.number);
}
@@ -8389,7 +9241,7 @@ static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const A
} // unnamed namespace
-Q_ALWAYS_INLINE QString to_string(QLatin1String s) noexcept { return s; }
+Q_ALWAYS_INLINE QString to_string(QLatin1StringView s) noexcept { return s; }
Q_ALWAYS_INLINE QString to_string(QStringView s) noexcept { return s.toString(); }
template <typename StringView>
@@ -8402,7 +9254,7 @@ static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPriv
ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts);
if (static_cast<size_t>(argIndexToPlaceholderMap.size()) > numArgs) // 3a
- argIndexToPlaceholderMap.resize(int(numArgs));
+ argIndexToPlaceholderMap.resize(qsizetype(numArgs));
else if (Q_UNLIKELY(static_cast<size_t>(argIndexToPlaceholderMap.size()) < numArgs)) // 3b
qWarning("QString::arg: %d argument(s) missing in %ls",
int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(to_string(pattern)));
@@ -8414,7 +9266,7 @@ static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPriv
QString result(totalSize, Qt::Uninitialized);
auto out = const_cast<QChar*>(result.constData());
- for (Part part : parts) {
+ for (const Part &part : parts) {
switch (part.tag) {
case QtPrivate::ArgBase::L1:
if (part.size) {
@@ -8441,36 +9293,16 @@ QString QtPrivate::argToQString(QStringView pattern, size_t n, const ArgBase **a
return argToQStringImpl(pattern, n, args);
}
-QString QtPrivate::argToQString(QLatin1String pattern, size_t n, const ArgBase **args)
+QString QtPrivate::argToQString(QLatin1StringView pattern, size_t n, const ArgBase **args)
{
return argToQStringImpl(pattern, n, args);
}
-/*! \fn bool QString::isSimpleText() const
-
- \internal
-*/
-bool QString::isSimpleText() const
-{
- const char16_t *p = d.data();
- const char16_t * const end = p + d.size;
- while (p < end) {
- char16_t uc = *p;
- // sort out regions of complex text formatting
- if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) {
- return false;
- }
- p++;
- }
-
- return true;
-}
-
/*! \fn bool QString::isRightToLeft() const
Returns \c true if the string is read right to left.
- \sa QStringRef::isRightToLeft()
+ \sa QStringView::isRightToLeft()
*/
bool QString::isRightToLeft() const
{
@@ -8568,6 +9400,38 @@ bool QString::isRightToLeft() const
Appends the given \a ch character onto the end of this string.
*/
+/*!
+ \since 6.1
+
+ Removes from the string the characters in the half-open range
+ [ \a first , \a last ). Returns an iterator to the character
+ immediately after the last erased character (i.e. the character
+ referred to by \a last before the erase).
+*/
+QString::iterator QString::erase(QString::const_iterator first, QString::const_iterator last)
+{
+ const auto start = std::distance(cbegin(), first);
+ const auto len = std::distance(first, last);
+ remove(start, len);
+ return begin() + start;
+}
+
+/*!
+ \fn QString::iterator QString::erase(QString::const_iterator it)
+
+ \overload
+ \since 6.5
+
+ Removes the character denoted by \c it from the string.
+ Returns an iterator to the character immediately after the
+ erased character.
+
+ \code
+ QString c = "abcdefg";
+ auto it = c.erase(c.cbegin()); // c is now "bcdefg"; "it" points to "b"
+ \endcode
+*/
+
/*! \fn void QString::shrink_to_fit()
\since 5.10
@@ -8615,16 +9479,9 @@ bool QString::isRightToLeft() const
\sa fromUtf16(), setRawData()
*/
-QString QString::fromRawData(const QChar *unicode, int size)
+QString QString::fromRawData(const QChar *unicode, qsizetype size)
{
- QString::DataPointer x;
- if (!unicode) {
- } else if (!size) {
- x = DataPointer(Data::allocate(0), 0);
- } else {
- x = Data::fromRawData(reinterpret_cast<const char16_t *>(unicode), size);
- }
- return QString(x);
+ return QString(DataPointer::fromRawData(const_cast<char16_t *>(reinterpret_cast<const char16_t *>(unicode)), size));
}
/*!
@@ -8641,7 +9498,7 @@ QString QString::fromRawData(const QChar *unicode, int size)
\sa fromRawData()
*/
-QString &QString::setRawData(const QChar *unicode, int size)
+QString &QString::setRawData(const QChar *unicode, qsizetype size)
{
if (!unicode || !size) {
clear();
@@ -8653,8 +9510,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
/*! \fn QString QString::fromStdU16String(const std::u16string &str)
\since 5.5
- Returns a copy of the \a str string. The given string is assumed
- to be encoded in UTF-16.
+ \include qstring.cpp {from-std-string} {UTF-16} {fromUtf16()}
\sa fromUtf16(), fromStdWString(), fromStdU32String()
*/
@@ -8673,8 +9529,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
/*! \fn QString QString::fromStdU32String(const std::u32string &str)
\since 5.5
- Returns a copy of the \a str string. The given string is assumed
- to be encoded in UCS-4.
+ \include qstring.cpp {from-std-string} {UCS-4} {fromUcs4()}
\sa fromUcs4(), fromStdWString(), fromStdU16String()
*/
@@ -8690,872 +9545,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa toUcs4(), toStdWString(), toStdU16String()
*/
-/*! \class QLatin1String
- \inmodule QtCore
- \brief The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
-
- \ingroup string-processing
- \reentrant
-
- Many of QString's member functions are overloaded to accept
- \c{const char *} instead of QString. This includes the copy
- constructor, the assignment operator, the comparison operators,
- and various other functions such as \l{QString::insert()}{insert()}, \l{QString::replace()}{replace()},
- and \l{QString::indexOf()}{indexOf()}. These functions
- are usually optimized to avoid constructing a QString object for
- the \c{const char *} data. For example, assuming \c str is a
- QString,
-
- \snippet code/src_corelib_text_qstring.cpp 3
-
- is much faster than
-
- \snippet code/src_corelib_text_qstring.cpp 4
-
- because it doesn't construct four temporary QString objects and
- make a deep copy of the character data.
-
- Applications that define \c QT_NO_CAST_FROM_ASCII (as explained
- in the QString documentation) don't have access to QString's
- \c{const char *} API. To provide an efficient way of specifying
- constant Latin-1 strings, Qt provides the QLatin1String, which is
- just a very thin wrapper around a \c{const char *}. Using
- QLatin1String, the example code above becomes
-
- \snippet code/src_corelib_text_qstring.cpp 5
-
- This is a bit longer to type, but it provides exactly the same
- benefits as the first version of the code, and is faster than
- converting the Latin-1 strings using QString::fromLatin1().
-
- Thanks to the QString(QLatin1String) constructor,
- QLatin1String can be used everywhere a QString is expected. For
- example:
-
- \snippet code/src_corelib_text_qstring.cpp 6
-
- \note If the function you're calling with a QLatin1String
- argument isn't actually overloaded to take QLatin1String, the
- implicit conversion to QString will trigger a memory allocation,
- which is usually what you want to avoid by using QLatin1String
- in the first place. In those cases, using QStringLiteral may be
- the better option.
-
- \sa QString, QLatin1Char, {QStringLiteral()}{QStringLiteral}, QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \typedef QLatin1String::value_type
- \since 5.10
-
- Alias for \c{const char}. Provided for compatibility with the STL.
-*/
-
-/*!
- \typedef QLatin1String::difference_type
- \since 5.10
-
- Alias for \c{int}. Provided for compatibility with the STL.
-*/
-
-/*!
- \typedef QLatin1String::size_type
- \since 5.10
-
- Alias for \c{int}. Provided for compatibility with the STL.
-*/
-
-/*!
- \typedef QLatin1String::reference
- \since 5.10
-
- Alias for \c{value_type &}. Provided for compatibility with the STL.
-*/
-
-/*!
- \typedef QLatin1String::const_reference
- \since 5.11
-
- Alias for \c{reference}. Provided for compatibility with the STL.
-*/
-
-/*!
- \typedef QLatin1String::iterator
- \since 5.10
-
- QLatin1String does not support mutable iterators, so this is the same
- as const_iterator.
-
- \sa const_iterator, reverse_iterator
-*/
-
-/*!
- \typedef QLatin1String::const_iterator
- \since 5.10
-
- \sa iterator, const_reverse_iterator
-*/
-
-/*!
- \typedef QLatin1String::reverse_iterator
- \since 5.10
-
- QLatin1String does not support mutable reverse iterators, so this is the
- same as const_reverse_iterator.
-
- \sa const_reverse_iterator, iterator
-*/
-
-/*!
- \typedef QLatin1String::const_reverse_iterator
- \since 5.10
-
- \sa reverse_iterator, const_iterator
-*/
-
-/*! \fn QLatin1String::QLatin1String()
- \since 5.6
-
- Constructs a QLatin1String object that stores a nullptr.
-*/
-
-/*! \fn QLatin1String::QLatin1String(const char *str)
-
- Constructs a QLatin1String object that stores \a str.
-
- The string data is \e not copied. The caller must be able to
- guarantee that \a str will not be deleted or modified as long as
- the QLatin1String object exists.
-
- \sa latin1()
-*/
-
-/*! \fn QLatin1String::QLatin1String(const char *str, int size)
-
- Constructs a QLatin1String object that stores \a str with \a size.
-
- The string data is \e not copied. The caller must be able to
- guarantee that \a str will not be deleted or modified as long as
- the QLatin1String object exists.
-
- \sa latin1()
-*/
-
-/*!
- \fn QLatin1String::QLatin1String(const char *first, const char *last)
- \since 5.10
-
- Constructs a QLatin1String object that stores \a first with length
- (\a last - \a first).
-
- The range \c{[first,last)} must remain valid for the lifetime of
- this Latin-1 string object.
-
- Passing \nullptr as \a first is safe if \a last is \nullptr,
- too, and results in a null Latin-1 string.
-
- The behavior is undefined if \a last precedes \a first, \a first
- is \nullptr and \a last is not, or if \c{last - first >
- INT_MAX}.
-*/
-
-/*! \fn QLatin1String::QLatin1String(const QByteArray &str)
-
- Constructs a QLatin1String object that stores \a str.
-
- The string data is \e not copied. The caller must be able to
- guarantee that \a str will not be deleted or modified as long as
- the QLatin1String object exists.
-
- \sa latin1()
-*/
-
-/*!
- \fn QLatin1String::toString() const
- \since 6.0
-
- Converts this Latin-1 string into a QString. Equivalent to
- \code
- return QString(*this);
- \endcode
-*/
-
-/*! \fn const char *QLatin1String::latin1() const
-
- Returns the Latin-1 string stored in this object.
-*/
-
-/*! \fn const char *QLatin1String::data() const
-
- Returns the Latin-1 string stored in this object.
-*/
-
-/*! \fn int QLatin1String::size() const
-
- Returns the size of the Latin-1 string stored in this object.
-*/
-
-/*! \fn bool QLatin1String::isNull() const
- \since 5.10
-
- Returns whether the Latin-1 string stored in this object is null
- (\c{data() == nullptr}) or not.
-
- \sa isEmpty(), data()
-*/
-
-/*! \fn bool QLatin1String::isEmpty() const
- \since 5.10
-
- Returns whether the Latin-1 string stored in this object is empty
- (\c{size() == 0}) or not.
-
- \sa isNull(), size()
-*/
-
-/*! \fn QLatin1Char QLatin1String::at(int pos) const
- \since 5.8
-
- Returns the character at position \a pos in this object.
-
- \note This function performs no error checking.
- The behavior is undefined when \a pos < 0 or \a pos >= size().
-
- \sa operator[]()
-*/
-
-/*! \fn QLatin1Char QLatin1String::operator[](int pos) const
- \since 5.8
-
- Returns the character at position \a pos in this object.
-
- \note This function performs no error checking.
- The behavior is undefined when \a pos < 0 or \a pos >= size().
-
- \sa at()
-*/
-
-/*!
- \fn QLatin1Char QLatin1String::front() const
- \since 5.10
-
- Returns the first character in the string.
- Same as \c{at(0)}.
-
- This function is provided for STL compatibility.
-
- \warning Calling this function on an empty string constitutes
- undefined behavior.
-
- \sa back(), at(), operator[]()
-*/
-
-/*!
- \fn QLatin1Char QLatin1String::back() const
- \since 5.10
-
- Returns the last character in the string.
- Same as \c{at(size() - 1)}.
-
- This function is provided for STL compatibility.
-
- \warning Calling this function on an empty string constitutes
- undefined behavior.
-
- \sa front(), at(), operator[]()
-*/
-
-/*!
- \fn int QLatin1String::compare(QStringView str, Qt::CaseSensitivity cs) const
- \fn int QLatin1String::compare(QLatin1String l1, Qt::CaseSensitivity cs) const
- \fn int QLatin1String::compare(QChar ch) const
- \fn int QLatin1String::compare(QChar ch, Qt::CaseSensitivity cs) const
- \since 5.14
-
- Returns an integer that compares to zero as this Latin-1 string compares to the
- string-view \a str, Latin-1 string \a l1, or character \a ch, respectively.
-
- If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
- otherwise the comparison is case-insensitive.
-
- \sa operator==(), operator<(), operator>()
-*/
-
-
-/*!
- \fn bool QLatin1String::startsWith(QStringView str, Qt::CaseSensitivity cs) const
- \since 5.10
- \fn bool QLatin1String::startsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
- \since 5.10
- \fn bool QLatin1String::startsWith(QChar ch) const
- \since 5.10
- \fn bool QLatin1String::startsWith(QChar ch, Qt::CaseSensitivity cs) const
- \since 5.10
-
- Returns \c true if this Latin-1 string starts with string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively;
- otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
- otherwise the search is case-insensitive.
-
- \sa endsWith()
-*/
-
-/*!
- \fn bool QLatin1String::endsWith(QStringView str, Qt::CaseSensitivity cs) const
- \since 5.10
- \fn bool QLatin1String::endsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
- \since 5.10
- \fn bool QLatin1String::endsWith(QChar ch) const
- \since 5.10
- \fn bool QLatin1String::endsWith(QChar ch, Qt::CaseSensitivity cs) const
- \since 5.10
-
- Returns \c true if this Latin-1 string ends with string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively;
- otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
- otherwise the search is case-insensitive.
-
- \sa startsWith()
-*/
-
-/*!
- \fn int QLatin1String::indexOf(QStringView str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \fn int QLatin1String::indexOf(QLatin1String l1, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \fn int QLatin1String::indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 5.14
-
- Returns the index position of the first occurrence of the string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively, in this Latin-1 string,
- searching forward from index position \a from. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
-
- \sa QString::indexOf()
-*/
-
-/*!
- \fn bool QLatin1String::contains(QStringView str, Qt::CaseSensitivity cs) const
- \fn bool QLatin1String::contains(QLatin1String l1, Qt::CaseSensitivity cs) const
- \fn bool QLatin1String::contains(QChar c, Qt::CaseSensitivity cs) const
- \since 5.14
-
- Returns \c true if this Latin-1 string contains an occurrence of the string-view
- \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (the default), the search is
- case-sensitive; otherwise the search is case-insensitive.
-
- \sa indexOf(), QStringView::contains(), QStringView::indexOf(), QString::indexOf()
-*/
-
-/*!
- \fn int QLatin1String::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
- \fn int QLatin1String::lastIndexOf(QLatin1String l1, int from, Qt::CaseSensitivity cs) const
- \fn int QLatin1String::lastIndexOf(QChar c, int from, Qt::CaseSensitivity cs) const
- \since 5.14
-
- Returns the index position of the last occurrence of the string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively, in this Latin-1 string,
- searching backward from index position \a from. If \a from is -1 (default),
- the search starts at the last character; if \a from is -2, at the next to last
- character and so on. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), QStringView::lastIndexOf(), QStringView::indexOf(), QString::indexOf()
-*/
-
-/*!
- \fn QLatin1String::const_iterator QLatin1String::begin() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
- the string.
-
- This function is provided for STL compatibility.
-
- \sa end(), cbegin(), rbegin(), data()
-*/
-
-/*!
- \fn QLatin1String::const_iterator QLatin1String::cbegin() const
- \since 5.10
-
- Same as begin().
-
- This function is provided for STL compatibility.
-
- \sa cend(), begin(), crbegin(), data()
-*/
-
-/*!
- \fn QLatin1String::const_iterator QLatin1String::end() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- character after the last character in the list.
-
- This function is provided for STL compatibility.
-
- \sa begin(), cend(), rend()
-*/
-
-/*! \fn QLatin1String::const_iterator QLatin1String::cend() const
- \since 5.10
-
- Same as end().
-
- This function is provided for STL compatibility.
-
- \sa cbegin(), end(), crend()
-*/
-
-/*!
- \fn QLatin1String::const_reverse_iterator QLatin1String::rbegin() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- character in the string, in reverse order.
-
- This function is provided for STL compatibility.
-
- \sa rend(), crbegin(), begin()
-*/
-
-/*!
- \fn QLatin1String::const_reverse_iterator QLatin1String::crbegin() const
- \since 5.10
-
- Same as rbegin().
-
- This function is provided for STL compatibility.
-
- \sa crend(), rbegin(), cbegin()
-*/
-
-/*!
- \fn QLatin1String::const_reverse_iterator QLatin1String::rend() const
- \since 5.10
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last character in the string, in reverse order.
-
- This function is provided for STL compatibility.
-
- \sa rbegin(), crend(), end()
-*/
-
-/*!
- \fn QLatin1String::const_reverse_iterator QLatin1String::crend() const
- \since 5.10
-
- Same as rend().
-
- This function is provided for STL compatibility.
-
- \sa crbegin(), rend(), cend()
-*/
-
-/*! \fn QLatin1String QLatin1String::mid(int start, int length) const
- \since 5.8
-
- Returns the substring of length \a length starting at position
- \a start in this object.
-
- Returns a null string if the \a start index exceeds the
- length of the string. If there are less than \a length characters
- available in the string starting at \a start, or if
- \a length is negative (default), the function returns all characters
- that are available from \a start.
-
- \sa left(), right(), chopped(), chop(), truncate()
-*/
-
-/*! \fn QLatin1String QLatin1String::left(int length) const
- \since 5.8
-
- Returns the substring of length \a length starting at position
- 0 in this object.
-
- The entire string is returned if \a length is greater than or equal
- to size(), or less than zero.
-
- \sa mid(), right(), chopped(), chop(), truncate()
-*/
-
-/*! \fn QLatin1String QLatin1String::right(int length) const
- \since 5.8
-
- Returns the substring of length \a length starting at position
- size() - \a length in this object.
-
- The entire string is returned if \a length is greater than or equal
- to size(), or less than zero.
-
- \sa mid(), left(), chopped(), chop(), truncate()
-*/
-
-/*!
- \fn QLatin1String QLatin1String::chopped(int length) const
- \since 5.10
-
- Returns the substring of length size() - \a length starting at the
- beginning of this object.
-
- Same as \c{left(size() - length)}.
-
- \note The behavior is undefined when \a length < 0 or \a length > size().
-
- \sa mid(), left(), right(), chop(), truncate()
-*/
-
-/*!
- \fn void QLatin1String::truncate(int length)
- \since 5.10
-
- Truncates this string to length \a length.
-
- Same as \c{*this = left(length)}.
-
- \note The behavior is undefined when \a length < 0 or \a length > size().
-
- \sa mid(), left(), right(), chopped(), chop()
-*/
-
-/*!
- \fn void QLatin1String::chop(int length)
- \since 5.10
-
- Truncates this string by \a length characters.
-
- Same as \c{*this = left(size() - length)}.
-
- \note The behavior is undefined when \a length < 0 or \a length > size().
-
- \sa mid(), left(), right(), chopped(), truncate()
-*/
-
-/*!
- \fn QLatin1String QLatin1String::trimmed() const
- \since 5.10
-
- Strips leading and trailing whitespace and returns the result.
-
- Whitespace means any character for which QChar::isSpace() returns
- \c true. This includes the ASCII characters '\\t', '\\n', '\\v',
- '\\f', '\\r', and ' '.
-*/
-
-/*! \fn bool QLatin1String::operator==(const QString &other) const
-
- Returns \c true if this string is equal to string \a other;
- otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- QString::localeAwareCompare().
-*/
-
-/*!
- \fn bool QLatin1String::operator==(const char *other) const
- \since 4.3
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator==(const QByteArray &other) const
- \since 5.0
- \overload
-
- The \a other byte array is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*! \fn bool QLatin1String::operator!=(const QString &other) const
-
- Returns \c true if this string is not equal to string \a other;
- otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- QString::localeAwareCompare().
-*/
-
-/*!
- \fn bool QLatin1String::operator!=(const char *other) const
- \since 4.3
- \overload operator!=()
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator!=(const QByteArray &other) const
- \since 5.0
- \overload operator!=()
-
- The \a other byte array is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator>(const QString &other) const
-
- Returns \c true if this string is lexically greater than string \a
- other; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- QString::localeAwareCompare().
-*/
-
-/*!
- \fn bool QLatin1String::operator>(const char *other) const
- \since 4.3
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
- when you compile your applications. This can be useful if you want
- to ensure that all user-visible strings go through QObject::tr(),
- for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator>(const QByteArray &other) const
- \since 5.0
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
- when you compile your applications. This can be useful if you want
- to ensure that all user-visible strings go through QObject::tr(),
- for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator<(const QString &other) const
-
- Returns \c true if this string is lexically less than the \a other
- string; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
-*/
-
-/*!
- \fn bool QLatin1String::operator<(const char *other) const
- \since 4.3
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator<(const QByteArray &other) const
- \since 5.0
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator>=(const QString &other) const
-
- Returns \c true if this string is lexically greater than or equal
- to string \a other; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- QString::localeAwareCompare().
-*/
-
-/*!
- \fn bool QLatin1String::operator>=(const char *other) const
- \since 4.3
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator>=(const QByteArray &other) const
- \since 5.0
- \overload
-
- The \a other array is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*! \fn bool QLatin1String::operator<=(const QString &other) const
-
- Returns \c true if this string is lexically less than or equal
- to string \a other; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings with
- QString::localeAwareCompare().
-*/
-
-/*!
- \fn bool QLatin1String::operator<=(const char *other) const
- \since 4.3
- \overload
-
- The \a other const char pointer is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QLatin1String::operator<=(const QByteArray &other) const
- \since 5.0
- \overload
-
- The \a other array is converted to a QString using
- the QString::fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-
-/*! \fn bool operator==(QLatin1String s1, QLatin1String s2)
- \relates QLatin1String
-
- Returns \c true if string \a s1 is lexically equal to string \a s2; otherwise
- returns \c false.
-*/
-/*! \fn bool operator!=(QLatin1String s1, QLatin1String s2)
- \relates QLatin1String
-
- Returns \c true if string \a s1 is lexically unequal to string \a s2; otherwise
- returns \c false.
-*/
-/*! \fn bool operator<(QLatin1String s1, QLatin1String s2)
- \relates QLatin1String
-
- Returns \c true if string \a s1 is lexically smaller than string \a s2; otherwise
- returns \c false.
-*/
-/*! \fn bool operator<=(QLatin1String s1, QLatin1String s2)
- \relates QLatin1String
-
- Returns \c true if string \a s1 is lexically smaller than or equal to string \a s2; otherwise
- returns \c false.
-*/
-/*! \fn bool operator>(QLatin1String s1, QLatin1String s2)
- \relates QLatin1String
-
- Returns \c true if string \a s1 is lexically greater than string \a s2; otherwise
- returns \c false.
-*/
-/*! \fn bool operator>=(QLatin1String s1, QLatin1String s2)
- \relates QLatin1String
-
- Returns \c true if string \a s1 is lexically greater than or equal to
- string \a s2; otherwise returns \c false.
-*/
-
-
-#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+#if !defined(QT_NO_DATASTREAM)
/*!
\fn QDataStream &operator<<(QDataStream &stream, const QString &string)
\relates QString
@@ -9572,15 +9562,16 @@ QDataStream &operator<<(QDataStream &out, const QString &str)
} else {
if (!str.isNull() || out.version() < 3) {
if ((out.byteOrder() == QDataStream::BigEndian) == (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
- out.writeBytes(reinterpret_cast<const char *>(str.unicode()), uint(sizeof(QChar) * str.length()));
+ out.writeBytes(reinterpret_cast<const char *>(str.unicode()),
+ static_cast<qsizetype>(sizeof(QChar) * str.size()));
} else {
- QVarLengthArray<char16_t> buffer(str.length());
- qbswap<sizeof(char16_t)>(str.constData(), str.length(), buffer.data());
- out.writeBytes(reinterpret_cast<const char *>(buffer.data()), uint(sizeof(char16_t) * buffer.size()));
+ QVarLengthArray<char16_t> buffer(str.size());
+ qbswap<sizeof(char16_t)>(str.constData(), str.size(), buffer.data());
+ out.writeBytes(reinterpret_cast<const char *>(buffer.data()),
+ static_cast<qsizetype>(sizeof(char16_t) * buffer.size()));
}
} else {
- // write null marker
- out << (quint32)0xffffffff;
+ QDataStream::writeQSizeType(out, -1); // write null marker
}
}
return out;
@@ -9602,20 +9593,25 @@ QDataStream &operator>>(QDataStream &in, QString &str)
in >> l;
str = QString::fromLatin1(l);
} else {
- quint32 bytes = 0;
- in >> bytes; // read size of string
- if (bytes == 0xffffffff) { // null string
+ qint64 size = QDataStream::readQSizeType(in);
+ qsizetype bytes = size;
+ if (size != bytes || size < -1) {
str.clear();
- } else if (bytes > 0) { // not empty
+ in.setStatus(QDataStream::SizeLimitExceeded);
+ return in;
+ }
+ if (bytes == -1) { // null string
+ str = QString();
+ } else if (bytes > 0) {
if (bytes & 0x1) {
str.clear();
in.setStatus(QDataStream::ReadCorruptData);
return in;
}
- const quint32 Step = 1024 * 1024;
- quint32 len = bytes / 2;
- quint32 allocated = 0;
+ const qsizetype Step = 1024 * 1024;
+ qsizetype len = bytes / 2;
+ qsizetype allocated = 0;
while (allocated < len) {
int blockSize = qMin(Step, len - allocated);
@@ -9635,607 +9631,13 @@ QDataStream &operator>>(QDataStream &in, QString &str)
qbswap<sizeof(*data)>(data, len, data);
}
} else {
- str = QString(QLatin1String(""));
+ str = QString(QLatin1StringView(""));
}
}
return in;
}
#endif // QT_NO_DATASTREAM
-
-
-
-/*!
- \class QStringRef
- \inmodule QtCore
- \since 4.3
- \brief The QStringRef class provides a thin wrapper around QString substrings.
- \reentrant
- \ingroup tools
- \ingroup string-processing
-
- QStringRef provides a read-only subset of the QString API.
-
- A string reference explicitly references a portion of a string()
- with a given size(), starting at a specific position(). Calling
- toString() returns a copy of the data as a real QString instance.
-
- This class is designed to improve the performance of substring
- handling when manipulating substrings obtained from existing QString
- instances. QStringRef avoids the memory allocation and reference
- counting overhead of a standard QString by simply referencing a
- part of the original string. This can prove to be advantageous in
- low level code, such as that used in a parser, at the expense of
- potentially more complex code.
-
- For most users, there are no semantic benefits to using QStringRef
- instead of QString since QStringRef requires attention to be paid
- to memory management issues, potentially making code more complex
- to write and maintain.
-
- \warning A QStringRef is only valid as long as the referenced
- string exists. If the original string is deleted, the string
- reference points to an invalid memory location.
-
- We suggest that you only use this class in stable code where profiling
- has clearly identified that performance improvements can be made by
- replacing standard string operations with the optimized substring
- handling provided by this class.
-
- \sa {Implicitly Shared Classes}
-*/
-
-/*!
- \typedef QStringRef::size_type
- \internal
-*/
-
-/*!
- \typedef QStringRef::value_type
- \internal
-*/
-
-/*!
- \typedef QStringRef::const_pointer
- \internal
-*/
-
-/*!
- \typedef QStringRef::const_reference
- \internal
-*/
-
-/*!
- \typedef QStringRef::const_iterator
- \since 5.4
-
- \sa QStringRef::const_reverse_iterator
-*/
-
-/*!
- \typedef QStringRef::const_reverse_iterator
- \since 5.7
-
- \sa QStringRef::const_iterator
-*/
-
-/*!
- \fn QStringRef::QStringRef()
-
- Constructs an empty string reference.
-*/
-
-/*! \fn QStringRef::QStringRef(const QString *string, int position, int length)
-
-Constructs a string reference to the range of characters in the given
-\a string specified by the starting \a position and \a length in characters.
-
-\warning This function exists to improve performance as much as possible,
-and performs no bounds checking. For program correctness, \a position and
-\a length must describe a valid substring of \a string.
-
-This means that the starting \a position must be positive or 0 and smaller
-than \a string's length, and \a length must be positive or 0 but smaller than
-the string's length minus the starting \a position;
-i.e, 0 <= position < string->length() and
-0 <= length <= string->length() - position must both be satisfied.
-*/
-
-/*! \fn QStringRef::QStringRef(const QString *string)
-
-Constructs a string reference to the given \a string.
-*/
-
-/*! \fn QStringRef::QStringRef(const QStringRef &other)
-
-Constructs a copy of the \a other string reference.
- */
-/*!
-\fn QStringRef::~QStringRef()
-
-Destroys the string reference.
-
-Since this class is only used to refer to string data, and does not take
-ownership of it, no memory is freed when instances are destroyed.
-*/
-
-/*!
- \fn int QStringRef::position() const
-
- Returns the starting position in the referenced string that is referred to
- by the string reference.
-
- \sa size(), string()
-*/
-
-/*!
- \fn int QStringRef::size() const
-
- Returns the number of characters referred to by the string reference.
- Equivalent to length() and count().
-
- \sa position(), string()
-*/
-/*!
- \fn int QStringRef::count() const
- Returns the number of characters referred to by the string reference.
- Equivalent to size() and length().
-
- \sa position(), string()
-*/
-/*!
- \fn int QStringRef::length() const
- Returns the number of characters referred to by the string reference.
- Equivalent to size() and count().
-
- \sa position(), string()
-*/
-
-
-/*!
- \fn bool QStringRef::isEmpty() const
-
- Returns \c true if the string reference has no characters; otherwise returns
- \c false.
-
- A string reference is empty if its size is zero.
-
- \sa size()
-*/
-
-/*!
- \fn bool QStringRef::isNull() const
-
- Returns \c true if this string reference does not reference a string or if
- the string it references is null (i.e. QString::isNull() is true).
-
- \sa size()
-*/
-
-/*!
- \fn const QString *QStringRef::string() const
-
- Returns a pointer to the string referred to by the string reference, or
- 0 if it does not reference a string.
-
- \sa unicode()
-*/
-
-
-/*!
- \fn const QChar *QStringRef::unicode() const
-
- Returns a Unicode representation of the string reference. Since
- the data stems directly from the referenced string, it is not
- \\0'-terminated unless the string reference includes the string's
- null terminator.
-
- \sa string()
-*/
-
-/*!
- \fn const QChar *QStringRef::data() const
-
- Same as unicode().
-*/
-
-/*!
- \fn const QChar *QStringRef::constData() const
-
- Same as unicode().
-*/
-
-/*!
- \fn QStringRef::const_iterator QStringRef::begin() const
- \since 5.4
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
- the string.
-
- \sa cbegin(), constBegin(), end(), constEnd(), rbegin(), rend()
-*/
-
-/*!
- \fn QStringRef::const_iterator QStringRef::cbegin() const
- \since 5.4
-
- Same as begin().
-
- \sa begin(), constBegin(), cend(), constEnd(), rbegin(), rend()
-*/
-
-/*!
- \fn QStringRef::const_iterator QStringRef::constBegin() const
- \since 5.9
-
- Same as begin().
-
- \sa begin(), cend(), constEnd(), rbegin(), rend()
-*/
-
-/*!
- \fn QStringRef::const_iterator QStringRef::end() const
- \since 5.4
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- character after the last character in the list.
-
- \sa cbegin(), constBegin(), end(), constEnd(), rbegin(), rend()
-*/
-
-/*! \fn QStringRef::const_iterator QStringRef::cend() const
- \since 5.4
-
- Same as end().
-
- \sa end(), constEnd(), cbegin(), constBegin(), rbegin(), rend()
-*/
-
-/*! \fn QStringRef::const_iterator QStringRef::constEnd() const
- \since 5.9
-
- Same as end().
-
- \sa end(), cend(), cbegin(), constBegin(), rbegin(), rend()
-*/
-
-/*!
- \fn QStringRef::const_reverse_iterator QStringRef::rbegin() const
- \since 5.7
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- character in the string, in reverse order.
-
- \sa begin(), crbegin(), rend()
-*/
-
-/*!
- \fn QStringRef::const_reverse_iterator QStringRef::crbegin() const
- \since 5.7
-
- Same as rbegin().
-
- \sa begin(), rbegin(), rend()
-*/
-
-/*!
- \fn QStringRef::const_reverse_iterator QStringRef::rend() const
- \since 5.7
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last character in the string, in reverse order.
-
- \sa end(), crend(), rbegin()
-*/
-
-
-/*!
- \fn QStringRef::const_reverse_iterator QStringRef::crend() const
- \since 5.7
-
- Same as rend().
-
- \sa end(), rend(), rbegin()
-*/
-
-/*!
- Returns a copy of the string reference as a QString object.
-
- If the string reference is not a complete reference of the string
- (meaning that position() is 0 and size() equals string()->size()),
- this function will allocate a new string to return.
-
- \sa string()
-*/
-
-QString QStringRef::toString() const {
- if (isNull())
- return QString();
- if (m_size && m_position == 0 && m_size == m_string->size())
- return *m_string;
- return QString(m_string->unicode() + m_position, m_size);
-}
-
-
-/*! \relates QStringRef
-
- Returns \c true if string reference \a s1 is lexically equal to string reference \a s2; otherwise
- returns \c false.
-*/
-bool operator==(const QStringRef &s1,const QStringRef &s2) noexcept
-{
- return s1.size() == s2.size() && qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
-}
-
-/*! \relates QStringRef
-
- Returns \c true if string \a s1 is lexically equal to string reference \a s2; otherwise
- returns \c false.
-*/
-bool operator==(const QString &s1,const QStringRef &s2) noexcept
-{
- return s1.size() == s2.size() && qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
-}
-
-/*! \relates QStringRef
-
- Returns \c true if string \a s1 is lexically equal to string reference \a s2; otherwise
- returns \c false.
-*/
-bool operator==(QLatin1String s1, const QStringRef &s2) noexcept
-{
- if (s1.size() != s2.size())
- return false;
-
- return qt_compare_strings(s2, s1, Qt::CaseSensitive) == 0;
-}
-
-/*!
- \relates QStringRef
-
- Returns \c true if string reference \a s1 is lexically less than
- string reference \a s2; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
-*/
-bool operator<(const QStringRef &s1,const QStringRef &s2) noexcept
-{
- return qt_compare_strings(s1, s2, Qt::CaseSensitive) < 0;
-}
-
-/*!\fn bool operator<=(const QStringRef &s1,const QStringRef &s2)
-
- \relates QStringRef
-
- Returns \c true if string reference \a s1 is lexically less than
- or equal to string reference \a s2; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
-*/
-
-/*!\fn bool operator>=(const QStringRef &s1,const QStringRef &s2)
-
- \relates QStringRef
-
- Returns \c true if string reference \a s1 is lexically greater than
- or equal to string reference \a s2; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
-*/
-
-/*!\fn bool operator>(const QStringRef &s1,const QStringRef &s2)
-
- \relates QStringRef
-
- Returns \c true if string reference \a s1 is lexically greater than
- string reference \a s2; otherwise returns \c false.
-
- The comparison is based exclusively on the numeric Unicode values
- of the characters and is very fast, but is not what a human would
- expect. Consider sorting user-interface strings using the
- QString::localeAwareCompare() function.
-*/
-
-
-/*!
- \fn const QChar QStringRef::at(int position) const
-
- Returns the character at the given index \a position in the
- string reference.
-
- The \a position must be a valid index position in the string
- (i.e., 0 <= \a position < size()).
-*/
-
-/*!
- \fn QChar QStringRef::operator[](int position) const
- \since 5.7
-
- Returns the character at the given index \a position in the
- string reference.
-
- The \a position must be a valid index position in the string
- reference (i.e., 0 <= \a position < size()).
-
- \sa at()
-*/
-
-/*!
- \fn QChar QStringRef::front() const
- \since 5.10
-
- Returns the first character in the string.
- Same as \c{at(0)}.
-
- This function is provided for STL compatibility.
-
- \warning Calling this function on an empty string constitutes
- undefined behavior.
-
- \sa back(), at(), operator[]()
-*/
-
-/*!
- \fn QChar QStringRef::back() const
- \since 5.10
-
- Returns the last character in the string.
- Same as \c{at(size() - 1)}.
-
- This function is provided for STL compatibility.
-
- \warning Calling this function on an empty string constitutes
- undefined behavior.
-
- \sa front(), at(), operator[]()
-*/
-
-/*!
- \fn void QStringRef::clear()
-
- Clears the contents of the string reference by making it null and empty.
-
- \sa isEmpty(), isNull()
-*/
-
-/*!
- \fn QStringRef &QStringRef::operator=(const QStringRef &other)
-
- Assigns the \a other string reference to this string reference, and
- returns the result.
-*/
-
-/*!
- \fn QStringRef &QStringRef::operator=(const QString *string)
-
- Constructs a string reference to the given \a string and assigns it to
- this string reference, returning the result.
-*/
-
-/*!
- \fn bool QStringRef::operator==(const char * s) const
-
- \overload operator==()
-
- The \a s byte array is converted to a QStringRef using the
- fromUtf8() function. This function stops conversion at the
- first NUL character found, or the end of the byte array.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- Returns \c true if this string is lexically equal to the parameter
- string \a s. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QStringRef::operator!=(const char * s) const
-
- \overload operator!=()
-
- The \a s const char pointer is converted to a QStringRef using
- the fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- Returns \c true if this string is not lexically equal to the parameter
- string \a s. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QStringRef::operator<(const char * s) const
-
- \overload operator<()
-
- The \a s const char pointer is converted to a QStringRef using
- the fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- Returns \c true if this string is lexically smaller than the parameter
- string \a s. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QStringRef::operator<=(const char * s) const
-
- \overload operator<=()
-
- The \a s const char pointer is converted to a QStringRef using
- the fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- Returns \c true if this string is lexically smaller than or equal to the parameter
- string \a s. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QStringRef::operator>(const char * s) const
-
-
- \overload operator>()
-
- The \a s const char pointer is converted to a QStringRef using
- the fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- Returns \c true if this string is lexically greater than the parameter
- string \a s. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
-
-/*!
- \fn bool QStringRef::operator>= (const char * s) const
-
- \overload operator>=()
-
- The \a s const char pointer is converted to a QStringRef using
- the fromUtf8() function.
-
- You can disable this operator by defining \c
- QT_NO_CAST_FROM_ASCII when you compile your applications. This
- can be useful if you want to ensure that all user-visible strings
- go through QObject::tr(), for example.
-
- Returns \c true if this string is lexically greater than or equal to the
- parameter string \a s. Otherwise returns \c false.
-
- \sa QT_NO_CAST_FROM_ASCII
-*/
/*!
\typedef QString::Data
\internal
@@ -10251,631 +9653,6 @@ bool operator<(const QStringRef &s1,const QStringRef &s2) noexcept
\internal
*/
-
-
-/*! Appends the string reference to \a string, and returns a new
-reference to the combined string data.
- */
-QStringRef QStringRef::appendTo(QString *string) const
-{
- if (!string)
- return QStringRef();
- int pos = string->size();
- string->insert(pos, unicode(), size());
- return QStringRef(string, pos, size());
-}
-
-/*!
- \fn int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- \since 4.5
-
- Compares the string \a s1 with the string \a s2 and returns an
- integer less than, equal to, or greater than zero if \a s1
- is less than, equal to, or greater than \a s2.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-*/
-
-/*!
- \fn int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- \since 4.5
- \overload
-
- Compares the string \a s1 with the string \a s2 and returns an
- integer less than, equal to, or greater than zero if \a s1
- is less than, equal to, or greater than \a s2.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-*/
-
-/*!
- \fn int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- \since 4.5
- \overload
-
- Compares the string \a s1 with the string \a s2 and returns an
- integer less than, equal to, or greater than zero if \a s1
- is less than, equal to, or greater than \a s2.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-*/
-
-/*!
- \overload
- \fn int QStringRef::compare(const QString &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 4.5
-
- Compares this string with the \a other string and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than the \a other string.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-
- Equivalent to \c {compare(*this, other, cs)}.
-*/
-
-/*!
- \overload
- \fn int QStringRef::compare(const QStringRef &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 4.5
-
- Compares this string with the \a other string and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than the \a other string.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-
- Equivalent to \c {compare(*this, other, cs)}.
-*/
-
-/*!
- \overload
- \fn int QStringRef::compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 5.14
-
- Compares this string with \a ch and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than \a ch, interpreted as a string of length one.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-*/
-
-/*!
- \overload
- \fn int QStringRef::compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 4.5
-
- Compares this string with the \a other string and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than the \a other string.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-
- Equivalent to \c {compare(*this, other, cs)}.
-*/
-
-/*!
- \overload
- \fn int QStringRef::compare(const QByteArray &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 5.8
-
- Compares this string with \a other and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than the \a other byte array,
- interpreted as a UTF-8 sequence.
-
- If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
- otherwise the comparison is case insensitive.
-
- Equivalent to \c {compare(*this, other, cs)}.
-*/
-
-/*!
- \fn int QStringRef::localeAwareCompare(const QStringRef &s1, const QString & s2)
- \since 4.5
-
- Compares \a s1 with \a s2 and returns an integer less than, equal
- to, or greater than zero if \a s1 is less than, equal to, or
- greater than \a s2.
-
- The comparison is performed in a locale- and also
- platform-dependent manner. Use this function to present sorted
- lists of strings to the user.
-
- On \macos and iOS, this function compares according the
- "Order for sorted lists" setting in the International prefereces panel.
-
- \sa compare(), QLocale
-*/
-
-/*!
- \fn int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef & s2)
- \since 4.5
- \overload
-
- Compares \a s1 with \a s2 and returns an integer less than, equal
- to, or greater than zero if \a s1 is less than, equal to, or
- greater than \a s2.
-
- The comparison is performed in a locale- and also
- platform-dependent manner. Use this function to present sorted
- lists of strings to the user.
-
-*/
-
-/*!
- \fn int QStringRef::localeAwareCompare(const QString &other) const
- \since 4.5
- \overload
-
- Compares this string with the \a other string and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than the \a other string.
-
- The comparison is performed in a locale- and also
- platform-dependent manner. Use this function to present sorted
- lists of strings to the user.
-*/
-
-/*!
- \fn int QStringRef::localeAwareCompare(const QStringRef &other) const
- \since 4.5
- \overload
-
- Compares this string with the \a other string and returns an
- integer less than, equal to, or greater than zero if this string
- is less than, equal to, or greater than the \a other string.
-
- The comparison is performed in a locale- and also
- platform-dependent manner. Use this function to present sorted
- lists of strings to the user.
-*/
-
-/*!
- \fn QString &QString::append(QStringView str)
- \since 6.0
-
- Appends the given string view \a str to this string and returns the result.
-*/
-
-/*!
- \fn QStringRef::left(int n) const
- \since 5.2
-
- Returns a substring reference to the \a n leftmost characters
- of the string.
-
- If \a n is greater than or equal to size(), or less than zero,
- a reference to the entire string is returned.
-
- \sa right(), mid(), startsWith(), chopped(), chop(), truncate()
-*/
-QStringRef QStringRef::left(int n) const
-{
- if (uint(n) >= uint(m_size))
- return *this;
- return QStringRef(m_string, m_position, n);
-}
-
-/*!
- \since 4.4
-
- Returns a substring reference to the \a n leftmost characters
- of the string.
-
- If \a n is greater than or equal to size(), or less than zero,
- a reference to the entire string is returned.
-
- \snippet qstring/main.cpp leftRef
-
- \sa left(), rightRef(), midRef(), startsWith()
-*/
-QStringRef QString::leftRef(int n) const
-{
- return QStringRef(this).left(n);
-}
-
-/*!
- \fn QStringRef::right(int n) const
- \since 5.2
-
- Returns a substring reference to the \a n rightmost characters
- of the string.
-
- If \a n is greater than or equal to size(), or less than zero,
- a reference to the entire string is returned.
-
- \sa left(), mid(), endsWith(), chopped(), chop(), truncate()
-*/
-QStringRef QStringRef::right(int n) const
-{
- if (uint(n) >= uint(m_size))
- return *this;
- return QStringRef(m_string, m_size - n + m_position, n);
-}
-
-/*!
- \since 4.4
-
- Returns a substring reference to the \a n rightmost characters
- of the string.
-
- If \a n is greater than or equal to size(), or less than zero,
- a reference to the entire string is returned.
-
- \snippet qstring/main.cpp rightRef
-
- \sa right(), leftRef(), midRef(), endsWith()
-*/
-QStringRef QString::rightRef(int n) const
-{
- return QStringRef(this).right(n);
-}
-
-/*!
- \fn QStringRef QStringRef::mid(int position, int n = -1) const
- \since 5.2
-
- Returns a substring reference to \a n characters of this string,
- starting at the specified \a position.
-
- If the \a position exceeds the length of the string, a null
- reference is returned.
-
- If there are less than \a n characters available in the string,
- starting at the given \a position, or if \a n is -1 (default), the
- function returns all characters from the specified \a position
- onwards.
-
- \sa left(), right(), chopped(), chop(), truncate()
-*/
-QStringRef QStringRef::mid(int pos, int n) const
-{
- qsizetype p = pos;
- qsizetype l = n;
- using namespace QtPrivate;
- switch (QContainerImplHelper::mid(m_size, &p, &l)) {
- case QContainerImplHelper::Null:
- return QStringRef();
- case QContainerImplHelper::Empty:
- return QStringRef(m_string, 0, 0);
- case QContainerImplHelper::Full:
- return *this;
- case QContainerImplHelper::Subset:
- return QStringRef(m_string, p + m_position, l);
- }
- Q_UNREACHABLE();
- return QStringRef();
-}
-
-/*!
- \fn QStringRef QStringRef::chopped(int len) const
- \since 5.10
-
- Returns a substring reference to the size() - \a len leftmost characters
- of this string.
-
- \note The behavior is undefined if \a len is negative or greater than size().
-
- \sa endsWith(), left(), right(), mid(), chop(), truncate()
-*/
-
-/*!
- \since 4.4
-
- Returns a substring reference to \a n characters of this string,
- starting at the specified \a position.
-
- If the \a position exceeds the length of the string, a null
- reference is returned.
-
- If there are less than \a n characters available in the string,
- starting at the given \a position, or if \a n is -1 (default), the
- function returns all characters from the specified \a position
- onwards.
-
- Example:
-
- \snippet qstring/main.cpp midRef
-
- \sa mid(), leftRef(), rightRef()
-*/
-QStringRef QString::midRef(int position, int n) const
-{
- return QStringRef(this).mid(position, n);
-}
-
-/*!
- \fn void QStringRef::truncate(int position)
- \since 5.6
-
- Truncates the string at the given \a position index.
-
- If the specified \a position index is beyond the end of the
- string, nothing happens.
-
- If \a position is negative, it is equivalent to passing zero.
-
- \sa QString::truncate()
-*/
-
-/*!
- \fn void QStringRef::chop(int n)
- \since 5.8
-
- Removes \a n characters from the end of the string.
-
- If \a n is greater than or equal to size(), the result is an
- empty string; if \a n is negative, it is equivalent to passing zero.
-
- \sa QString::chop(), truncate()
-*/
-
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
- \since 4.8
-
- Returns the index position of the first occurrence of the string \a
- str in this string reference, searching forward from index position
- \a from. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
-
- \sa QString::indexOf(), lastIndexOf(), contains(), count()
-*/
-int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
-
-/*!
- \fn int QStringRef::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
- \since 5.14
- \overload indexOf()
-
- Returns the index position of the first occurrence of the string view \a str
- in this string reference, searching forward from index position \a from.
- Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
-
- \sa QString::indexOf(), QStringView::indexOf(), lastIndexOf(), contains(), count()
-*/
-
-/*!
- \since 4.8
- \overload indexOf()
-
- Returns the index position of the first occurrence of the
- character \a ch in the string reference, searching forward from
- index position \a from. Returns -1 if \a ch could not be found.
-
- \sa QString::indexOf(), lastIndexOf(), contains(), count()
-*/
-int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(qFindChar(QStringView(unicode(), length()), ch, from, cs));
-}
-
-/*!
- \since 4.8
-
- Returns the index position of the first occurrence of the string \a
- str in this string reference, searching forward from index position
- \a from. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
-
- \sa QString::indexOf(), lastIndexOf(), contains(), count()
-*/
-int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs));
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-/*!
- \since 4.8
-
- \overload indexOf()
-
- Returns the index position of the first occurrence of the string
- reference \a str in this string reference, searching forward from
- index position \a from. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::indexOf(), lastIndexOf(), contains(), count()
-*/
-int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs));
-}
-#endif // QT_STRINGVIEW_LEVEL < 2
-
-/*!
- \since 4.8
-
- Returns the index position of the last occurrence of the string \a
- str in this string reference, searching backward from index position
- \a from. If \a from is -1 (default), the search starts at the last
- character; if \a from is -2, at the next to last character and so
- on. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::lastIndexOf(), indexOf(), contains(), count()
-*/
-int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::lastIndexOf(*this, from, str, cs));
-}
-
-/*!
- \since 4.8
- \overload lastIndexOf()
-
- Returns the index position of the last occurrence of the character
- \a ch, searching backward from position \a from.
-
- \sa QString::lastIndexOf(), indexOf(), contains(), count()
-*/
-int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(qLastIndexOf(*this, ch, from, cs));
-}
-
-/*!
- \since 4.8
- \overload lastIndexOf()
-
- Returns the index position of the last occurrence of the string \a
- str in this string reference, searching backward from index position
- \a from. If \a from is -1 (default), the search starts at the last
- character; if \a from is -2, at the next to last character and so
- on. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::lastIndexOf(), indexOf(), contains(), count()
-*/
-int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::lastIndexOf(*this, from, str, cs));
-}
-
-/*!
- \since 4.8
- \overload lastIndexOf()
-
- Returns the index position of the last occurrence of the string
- reference \a str in this string reference, searching backward from
- index position \a from. If \a from is -1 (default), the search
- starts at the last character; if \a from is -2, at the next to last
- character and so on. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::lastIndexOf(), indexOf(), contains(), count()
-*/
-int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::lastIndexOf(*this, from, str, cs));
-}
-
-/*!
- \fn int QStringRef::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
- \since 5.14
- \overload lastIndexOf()
-
- Returns the index position of the last occurrence of the string view \a
- str in this string, searching backward from index position \a
- from. If \a from is -1 (default), the search starts at the last
- character; if \a from is -2, at the next to last character and so
- on. Returns -1 if \a str is not found.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), contains(), count()
-*/
-
-/*!
- \since 4.8
- Returns the number of (potentially overlapping) occurrences of
- the string \a str in this string reference.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa QString::count(), contains(), indexOf()
-*/
-int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
-}
-
-/*!
- \since 4.8
- \overload count()
-
- Returns the number of occurrences of the character \a ch in the
- string reference.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa QString::count(), contains(), indexOf()
-*/
-int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::count(QStringView(unicode(), size()), ch, cs));
-}
-
-/*!
- \since 4.8
- \overload count()
-
- Returns the number of (potentially overlapping) occurrences of the
- string reference \a str in this string reference.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa QString::count(), contains(), indexOf()
-*/
-int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const
-{
- // ### Qt6: qsizetype
- return int(QtPrivate::count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
-}
-
-/*!
- \since 5.9
-
- Returns \c true if the string is read right to left.
-
- \sa QString::isRightToLeft()
-*/
-bool QStringRef::isRightToLeft() const
-{
- return QtPrivate::isRightToLeft(QStringView(unicode(), size()));
-}
-
/*!
\since 5.11
\internal
@@ -10887,20 +9664,12 @@ bool QStringRef::isRightToLeft() const
*/
bool QtPrivate::isRightToLeft(QStringView string) noexcept
{
- const char16_t *p = string.utf16();
- const char16_t * const end = p + string.size();
int isolateLevel = 0;
- while (p < end) {
- uint ucs4 = *p;
- if (QChar::isHighSurrogate(ucs4) && p < end - 1) {
- char16_t low = p[1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++p;
- }
- }
- switch (QChar::direction(ucs4))
- {
+
+ for (QStringIterator i(string); i.hasNext();) {
+ const char32_t c = i.next();
+
+ switch (QChar::direction(c)) {
case QChar::DirRLI:
case QChar::DirLRI:
case QChar::DirFSI:
@@ -10919,201 +9688,28 @@ bool QtPrivate::isRightToLeft(QStringView string) noexcept
if (isolateLevel)
break;
return true;
- default:
+ case QChar::DirEN:
+ case QChar::DirES:
+ case QChar::DirET:
+ case QChar::DirAN:
+ case QChar::DirCS:
+ case QChar::DirB:
+ case QChar::DirS:
+ case QChar::DirWS:
+ case QChar::DirON:
+ case QChar::DirLRE:
+ case QChar::DirLRO:
+ case QChar::DirRLE:
+ case QChar::DirRLO:
+ case QChar::DirPDF:
+ case QChar::DirNSM:
+ case QChar::DirBN:
break;
}
- ++p;
}
return false;
}
-/*!
- \since 4.8
-
- Returns \c true if the string reference starts with \a str; otherwise
- returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa QString::startsWith(), endsWith()
-*/
-bool QStringRef::startsWith(const QString &str, Qt::CaseSensitivity cs) const
-{
- return qt_starts_with(*this, str, cs);
-}
-
-/*!
- \since 4.8
- \overload startsWith()
- \sa QString::startsWith(), endsWith()
-*/
-bool QStringRef::startsWith(QLatin1String str, Qt::CaseSensitivity cs) const
-{
- return qt_starts_with(*this, str, cs);
-}
-
-/*!
- \fn bool QStringRef::startsWith(QStringView str, Qt::CaseSensitivity cs) const
- \since 5.10
- \overload startsWith()
- \sa QString::startsWith(), endsWith()
-*/
-
-/*!
- \since 4.8
- \overload startsWith()
- \sa QString::startsWith(), endsWith()
-*/
-bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
-{
- return qt_starts_with(*this, str, cs);
-}
-
-/*!
- \since 4.8
- \overload startsWith()
-
- Returns \c true if the string reference starts with \a ch; otherwise
- returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::startsWith(), endsWith()
-*/
-bool QStringRef::startsWith(QChar ch, Qt::CaseSensitivity cs) const
-{
- return qt_starts_with(*this, ch, cs);
-}
-
-/*!
- \since 4.8
- Returns \c true if the string reference ends with \a str; otherwise
- returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::endsWith(), startsWith()
-*/
-bool QStringRef::endsWith(const QString &str, Qt::CaseSensitivity cs) const
-{
- return qt_ends_with(*this, str, cs);
-}
-
-/*!
- \since 4.8
- \overload endsWith()
-
- Returns \c true if the string reference ends with \a ch; otherwise
- returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
-
- \sa QString::endsWith(), endsWith()
-*/
-bool QStringRef::endsWith(QChar ch, Qt::CaseSensitivity cs) const
-{
- return qt_ends_with(*this, ch, cs);
-}
-
-/*!
- \since 4.8
- \overload endsWith()
- \sa QString::endsWith(), endsWith()
-*/
-bool QStringRef::endsWith(QLatin1String str, Qt::CaseSensitivity cs) const
-{
- return qt_ends_with(*this, str, cs);
-}
-
-/*!
- \fn bool QStringRef::endsWith(QStringView str, Qt::CaseSensitivity cs) const
- \since 5.10
- \overload endsWith()
- \sa QString::endsWith(), startsWith()
-*/
-
-/*!
- \since 4.8
- \overload endsWith()
- \sa QString::endsWith(), endsWith()
-*/
-bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
-{
- return qt_ends_with(*this, str, cs);
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-/*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
-
- \since 4.8
- Returns \c true if this string reference contains an occurrence of
- the string \a str; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), count()
-*/
-#endif // QT_STRINGVIEW_LEVEL < 2
-
-/*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
-
- \overload contains()
- \since 4.8
-
- Returns \c true if this string contains an occurrence of the
- character \a ch; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
-*/
-
-#if QT_STRINGVIEW_LEVEL < 2
-/*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \overload contains()
- \since 4.8
-
- Returns \c true if this string reference contains an occurrence of
- the string reference \a str; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), count()
-*/
-#endif // QT_STRINGVIEW_LEVEL < 2
-
-/*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const
- \since 4.8
- \overload contains()
-
- Returns \c true if this string reference contains an occurrence of
- the string \a str; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), count()
-*/
-
-/*! \fn bool QStringRef::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 5.14
- \overload contains()
-
- Returns \c true if this string reference contains an occurrence of
- the string view \a str; otherwise returns \c false.
-
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
-
- \sa indexOf(), count()
-*/
-
qsizetype QtPrivate::count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
qsizetype num = 0;
@@ -11129,64 +9725,81 @@ qsizetype QtPrivate::count(QStringView haystack, QStringView needle, Qt::CaseSen
return num;
}
-qsizetype QtPrivate::count(QStringView haystack, QChar ch, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs) noexcept
{
- qsizetype num = 0;
- if (cs == Qt::CaseSensitive) {
- for (QChar c : haystack) {
- if (c == ch)
- ++num;
- }
- } else {
- ch = foldCase(ch);
- for (QChar c : haystack) {
- if (foldCase(c) == ch)
- ++num;
- }
- }
- return num;
+ if (cs == Qt::CaseSensitive)
+ return std::count(haystack.cbegin(), haystack.cend(), needle);
+
+ needle = foldCase(needle);
+ return std::count_if(haystack.cbegin(), haystack.cend(),
+ [needle](const QChar c) { return foldAndCompare(c, needle); });
}
-template <typename Haystack, typename Needle>
-bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::count(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs)
{
- if (haystack.isNull())
- return needle.isNull(); // historical behavior, consider changing in ### Qt 6.
- const auto haystackLen = haystack.size();
- const auto needleLen = needle.size();
- if (haystackLen == 0)
- return needleLen == 0;
- if (needleLen > haystackLen)
- return false;
+ qsizetype num = 0;
+ qsizetype i = -1;
+
+ QLatin1StringMatcher matcher(needle, cs);
+ while ((i = matcher.indexIn(haystack, i + 1)) != -1)
+ ++num;
- return qt_compare_strings(haystack.left(needleLen), needle, cs) == 0;
+ return num;
}
-static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
+qsizetype QtPrivate::count(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs)
{
- return qt_starts_with_impl(haystack, needle, cs);
+ if (haystack.size() < needle.size())
+ return 0;
+
+ if (!QtPrivate::isLatin1(needle)) // won't find non-L1 UTF-16 needles in a L1 haystack!
+ return 0;
+
+ qsizetype num = 0;
+ qsizetype i = -1;
+
+ QVarLengthArray<uchar> s(needle.size());
+ qt_to_latin1_unchecked(s.data(), needle.utf16(), needle.size());
+
+ QLatin1StringMatcher matcher(QLatin1StringView(reinterpret_cast<char *>(s.data()), s.size()),
+ cs);
+ while ((i = matcher.indexIn(haystack, i + 1)) != -1)
+ ++num;
+
+ return num;
}
-static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+qsizetype QtPrivate::count(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs)
{
- return qt_starts_with_impl(haystack, needle, cs);
+ if (haystack.size() < needle.size())
+ return -1;
+
+ QVarLengthArray<char16_t> s = qt_from_latin1_to_qvla(needle);
+ return QtPrivate::count(haystack, QStringView(s.data(), s.size()), cs);
}
-static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs)
+qsizetype QtPrivate::count(QLatin1StringView haystack, QChar needle, Qt::CaseSensitivity cs) noexcept
{
- return haystack.size()
- && (cs == Qt::CaseSensitive ? haystack.front() == needle
- : foldCase(haystack.front()) == foldCase(needle));
+ // non-L1 needles cannot possibly match in L1-only haystacks
+ if (needle.unicode() > 0xff)
+ return 0;
+
+ if (cs == Qt::CaseSensitive) {
+ return std::count(haystack.cbegin(), haystack.cend(), needle.toLatin1());
+ } else {
+ return std::count_if(haystack.cbegin(), haystack.cend(),
+ CaseInsensitiveL1::matcher(needle.toLatin1()));
+ }
}
/*!
\fn bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\since 5.10
- \fn bool QtPrivate::startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \fn bool QtPrivate::startsWith(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs)
\since 5.10
- \fn bool QtPrivate::startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs)
+ \fn bool QtPrivate::startsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\since 5.10
- \fn bool QtPrivate::startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \fn bool QtPrivate::startsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs)
\since 5.10
\internal
\relates QStringView
@@ -11194,10 +9807,9 @@ static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSe
Returns \c true if \a haystack starts with \a needle,
otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
- otherwise the search is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
- \sa QtPrivate::endsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
+ \sa QtPrivate::endsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1StringView::endsWith()
*/
bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
@@ -11205,61 +9817,29 @@ bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSen
return qt_starts_with_impl(haystack, needle, cs);
}
-bool QtPrivate::startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::startsWith(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
-bool QtPrivate::startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::startsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
-bool QtPrivate::startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::startsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
-template <typename Haystack, typename Needle>
-bool qt_ends_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) noexcept
-{
- if (haystack.isNull())
- return needle.isNull(); // historical behavior, consider changing in ### Qt 6.
- const auto haystackLen = haystack.size();
- const auto needleLen = needle.size();
- if (haystackLen == 0)
- return needleLen == 0;
- if (haystackLen < needleLen)
- return false;
-
- return qt_compare_strings(haystack.right(needleLen), needle, cs) == 0;
-}
-
-static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
-{
- return qt_ends_with_impl(haystack, needle, cs);
-}
-
-static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
-{
- return qt_ends_with_impl(haystack, needle, cs);
-}
-
-static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs)
-{
- return haystack.size()
- && (cs == Qt::CaseSensitive ? haystack.back() == needle
- : foldCase(haystack.back()) == foldCase(needle));
-}
-
/*!
\fn bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\since 5.10
- \fn bool QtPrivate::endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \fn bool QtPrivate::endsWith(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs)
\since 5.10
- \fn bool QtPrivate::endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs)
+ \fn bool QtPrivate::endsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\since 5.10
- \fn bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \fn bool QtPrivate::endsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs)
\since 5.10
\internal
\relates QStringView
@@ -11267,10 +9847,9 @@ static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSens
Returns \c true if \a haystack ends with \a needle,
otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
- otherwise the search is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
- \sa QtPrivate::startsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
+ \sa QtPrivate::startsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1StringView::endsWith()
*/
bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
@@ -11278,91 +9857,27 @@ bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensi
return qt_ends_with_impl(haystack, needle, cs);
}
-bool QtPrivate::endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::endsWith(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
-bool QtPrivate::endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::endsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
-bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+bool QtPrivate::endsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
-namespace {
-template <typename Pointer>
-char32_t foldCaseHelper(Pointer ch, Pointer start) = delete;
-
-template <>
-char32_t foldCaseHelper<const QChar*>(const QChar* ch, const QChar* start)
-{
- return foldCase(reinterpret_cast<const char16_t*>(ch),
- reinterpret_cast<const char16_t*>(start));
-}
-
-template <>
-char32_t foldCaseHelper<const char*>(const char* ch, const char*)
-{
- return foldCase(char16_t(uchar(*ch)));
-}
-
-template <typename T>
-char16_t valueTypeToUtf16(T t) = delete;
-
-template <>
-char16_t valueTypeToUtf16<QChar>(QChar t)
-{
- return t.unicode();
-}
-
-template <>
-char16_t valueTypeToUtf16<char>(char t)
-{
- return char16_t{uchar(t)};
-}
-}
-
-/*!
- \internal
-
- Returns the index position of the first occurrence of the
- character \a ch in the string given by \a str and \a len,
- searching forward from index
- position \a from. Returns -1 if \a ch could not be found.
-*/
-
-static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept
-{
- if (from < 0)
- from = qMax(from + str.size(), qsizetype(0));
- if (from < str.size()) {
- const char16_t *s = str.utf16();
- char16_t c = ch.unicode();
- const char16_t *n = s + from;
- const char16_t *e = s + str.size();
- if (cs == Qt::CaseSensitive) {
- n = QtPrivate::qustrchr(QStringView(n, e), c);
- if (n != e)
- return n - s;
- } else {
- c = foldCase(c);
- --n;
- while (++n != e)
- if (foldCase(*n) == c)
- return n - s;
- }
- }
- return -1;
-}
-
qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringView needle0, Qt::CaseSensitivity cs) noexcept
{
const qsizetype l = haystack0.size();
const qsizetype sl = needle0.size();
+ if (sl == 1)
+ return findString(haystack0, from, needle0[0], cs);
if (from < 0)
from += l;
if (std::size_t(sl + from) > std::size_t(l))
@@ -11372,9 +9887,6 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
if (!l)
return -1;
- if (sl == 1)
- return qFindChar(haystack0, needle0[0], from, cs);
-
/*
We use the Boyer-Moore algorithm in cases where the overhead
for the skip table should pay off, otherwise we use a simple
@@ -11407,7 +9919,7 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
while (haystack <= end) {
hashHaystack += haystack[sl_minus_1];
if (hashHaystack == hashNeedle
- && qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
+ && QtPrivate::compareStrings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
return haystack - haystack0.utf16();
REHASH(*haystack);
@@ -11424,7 +9936,7 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
while (haystack <= end) {
hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
if (hashHaystack == hashNeedle
- && qt_compare_strings(needle0, sv(haystack), Qt::CaseInsensitive) == 0)
+ && QtPrivate::compareStrings(needle0, sv(haystack), Qt::CaseInsensitive) == 0)
return haystack - haystack0.utf16();
REHASH(foldCase(haystack, haystack_start));
@@ -11434,128 +9946,93 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
return -1;
}
-template <typename Haystack>
-static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle,
- qsizetype from, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
- if (from < 0)
- from += haystack.size();
- if (std::size_t(from) >= std::size_t(haystack.size()))
+ if (haystack.size() < needle.size())
return -1;
- if (from >= 0) {
- char16_t c = needle.unicode();
- const auto b = haystack.data();
- auto n = b + from;
- if (cs == Qt::CaseSensitive) {
- for (; n >= b; --n)
- if (valueTypeToUtf16(*n) == c)
- return n - b;
- } else {
- c = foldCase(c);
- for (; n >= b; --n)
- if (foldCase(valueTypeToUtf16(*n)) == c)
- return n - b;
- }
- }
- return -1;
+
+ QVarLengthArray<char16_t> s = qt_from_latin1_to_qvla(needle);
+ return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast<const QChar*>(s.constData()), s.size()), cs);
}
-template<typename Haystack, typename Needle>
-static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
- Needle needle0, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::findString(QLatin1StringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
- const qsizetype sl = needle0.size();
- if (sl == 1)
- return qLastIndexOf(haystack0, needle0.front(), from, cs);
-
- const qsizetype l = haystack0.size();
- if (from < 0)
- from += l;
- if (from == l && sl == 0)
- return from;
- const qsizetype delta = l - sl;
- if (std::size_t(from) >= std::size_t(l) || delta < 0)
+ if (haystack.size() < needle.size())
return -1;
- if (from > delta)
- from = delta;
-
- auto sv = [sl](const typename Haystack::value_type *v) { return Haystack(v, sl); };
- auto haystack = haystack0.data();
- const auto needle = needle0.data();
- const auto *end = haystack;
- haystack += from;
- const std::size_t sl_minus_1 = sl - 1;
- const auto *n = needle + sl_minus_1;
- const auto *h = haystack + sl_minus_1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
- qsizetype idx;
-
- if (cs == Qt::CaseSensitive) {
- for (idx = 0; idx < sl; ++idx) {
- hashNeedle = (hashNeedle << 1) + valueTypeToUtf16(*(n - idx));
- hashHaystack = (hashHaystack << 1) + valueTypeToUtf16(*(h - idx));
- }
- hashHaystack -= valueTypeToUtf16(*haystack);
-
- while (haystack >= end) {
- hashHaystack += valueTypeToUtf16(*haystack);
- if (hashHaystack == hashNeedle
- && qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
- return haystack - end;
- --haystack;
- REHASH(valueTypeToUtf16(haystack[sl]));
- }
- } else {
- for (idx = 0; idx < sl; ++idx) {
- hashNeedle = (hashNeedle << 1) + foldCaseHelper(n - idx, needle);
- hashHaystack = (hashHaystack << 1) + foldCaseHelper(h - idx, end);
- }
- hashHaystack -= foldCaseHelper(haystack, end);
+ if (!QtPrivate::isLatin1(needle)) // won't find non-L1 UTF-16 needles in a L1 haystack!
+ return -1;
- while (haystack >= end) {
- hashHaystack += foldCaseHelper(haystack, end);
- if (hashHaystack == hashNeedle
- && qt_compare_strings(sv(haystack), needle0, Qt::CaseInsensitive) == 0)
- return haystack - end;
- --haystack;
- REHASH(foldCaseHelper(haystack + sl, end));
- }
+ if (needle.size() == 1) {
+ const char n = needle.front().toLatin1();
+ return QtPrivate::findString(haystack, from, QLatin1StringView(&n, 1), cs);
}
- return -1;
+
+ QVarLengthArray<char> s(needle.size());
+ qt_to_latin1_unchecked(reinterpret_cast<uchar *>(s.data()), needle.utf16(), needle.size());
+ return QtPrivate::findString(haystack, from, QLatin1StringView(s.data(), s.size()), cs);
}
-qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::findString(QLatin1StringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
- if (haystack.size() < needle.size())
+ if (from < 0)
+ from += haystack.size();
+ if (from < 0)
+ return -1;
+ qsizetype adjustedSize = haystack.size() - from;
+ if (adjustedSize < needle.size())
return -1;
+ if (needle.size() == 0)
+ return from;
- QVarLengthArray<char16_t> s(needle.size());
- qt_from_latin1(s.data(), needle.latin1(), needle.size());
- return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast<const QChar*>(s.constData()), s.size()), cs);
-}
+ if (cs == Qt::CaseSensitive) {
-qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
-{
- if (haystack.size() < needle.size())
+ if (needle.size() == 1) {
+ Q_ASSERT(haystack.data() != nullptr); // see size check above
+ if (auto it = memchr(haystack.data() + from, needle.front().toLatin1(), adjustedSize))
+ return static_cast<const char *>(it) - haystack.data();
+ return -1;
+ }
+
+ const QLatin1StringMatcher matcher(needle, Qt::CaseSensitivity::CaseSensitive);
+ return matcher.indexIn(haystack, from);
+ }
+
+ // If the needle is sufficiently small we simply iteratively search through
+ // the haystack. When the needle is too long we use a boyer-moore searcher
+ // from the standard library, if available. If it is not available then the
+ // QLatin1Strings are converted to QString and compared as such. Though
+ // initialization is slower the boyer-moore search it employs still makes up
+ // for it when haystack and needle are sufficiently long.
+ // The needle size was chosen by testing various lengths using the
+ // qstringtokenizer benchmark with the
+ // "tokenize_qlatin1string_qlatin1string" test.
+#ifdef Q_CC_MSVC
+ const qsizetype threshold = 1;
+#else
+ const qsizetype threshold = 13;
+#endif
+ if (needle.size() <= threshold) {
+ const auto begin = haystack.begin();
+ const auto end = haystack.end() - needle.size() + 1;
+ auto ciMatch = CaseInsensitiveL1::matcher(needle[0].toLatin1());
+ const qsizetype nlen1 = needle.size() - 1;
+ for (auto it = std::find_if(begin + from, end, ciMatch); it != end;
+ it = std::find_if(it + 1, end, ciMatch)) {
+ // In this comparison we skip the first character because we know it's a match
+ if (!nlen1 || QLatin1StringView(it + 1, nlen1).compare(needle.sliced(1), cs) == 0)
+ return std::distance(begin, it);
+ }
return -1;
+ }
- QVarLengthArray<char16_t> s(haystack.size());
- qt_from_latin1(s.data(), haystack.latin1(), haystack.size());
- return QtPrivate::findString(QStringView(reinterpret_cast<const QChar*>(s.constData()), s.size()), from, needle, cs);
+ QLatin1StringMatcher matcher(needle, Qt::CaseSensitivity::CaseInsensitive);
+ return matcher.indexIn(haystack, from);
}
-qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, char16_t needle, Qt::CaseSensitivity cs) noexcept
{
- if (haystack.size() < needle.size())
- return -1;
-
- QVarLengthArray<char16_t> h(haystack.size());
- qt_from_latin1(h.data(), haystack.latin1(), haystack.size());
- QVarLengthArray<char16_t> n(needle.size());
- qt_from_latin1(n.data(), needle.latin1(), needle.size());
- return QtPrivate::findString(QStringView(reinterpret_cast<const QChar*>(h.constData()), h.size()), from,
- QStringView(reinterpret_cast<const QChar*>(n.constData()), n.size()), cs);
+ return qLastIndexOf(haystack, QChar(needle), from, cs);
}
qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
@@ -11563,470 +10040,349 @@ qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QStringVi
return qLastIndexOf(haystack, from, needle, cs);
}
-qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
return qLastIndexOf(haystack, from, needle, cs);
}
-qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::lastIndexOf(QLatin1StringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qLastIndexOf(haystack, from, needle, cs);
}
-qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+qsizetype QtPrivate::lastIndexOf(QLatin1StringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs) noexcept
{
return qLastIndexOf(haystack, from, needle, cs);
}
-/*!
- \since 4.8
-
- Returns a Latin-1 representation of the string as a QByteArray.
-
- The returned byte array is undefined if the string contains non-Latin1
- characters. Those characters may be suppressed or replaced with a
- question mark.
-
- \sa toUtf8(), toLocal8Bit(), QStringEncoder
-*/
-QByteArray QStringRef::toLatin1() const
+#if QT_CONFIG(regularexpression)
+qsizetype QtPrivate::indexOf(QStringView viewHaystack, const QString *stringHaystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
- return qt_convert_to_latin1(*this);
-}
-
-/*!
- \since 4.8
-
- Returns the local 8-bit representation of the string as a
- QByteArray. The returned byte array is undefined if the string
- contains characters not supported by the local 8-bit encoding.
-
- On Unix systems this is equivalen to toUtf8(), on Windows the systems
- current code page is being used.
+ if (!re.isValid()) {
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::indexOf");
+ return -1;
+ }
- If this string contains any characters that cannot be encoded in the
- locale, the returned byte array is undefined. Those characters may be
- suppressed or replaced by another.
+ QRegularExpressionMatch match = stringHaystack
+ ? re.match(*stringHaystack, from)
+ : re.matchView(viewHaystack, from);
+ if (match.hasMatch()) {
+ const qsizetype ret = match.capturedStart();
+ if (rmatch)
+ *rmatch = std::move(match);
+ return ret;
+ }
- \sa toLatin1(), toUtf8(), QStringEncoder
-*/
-QByteArray QStringRef::toLocal8Bit() const
-{
- return qt_convert_to_local_8bit(*this);
+ return -1;
}
-/*!
- \since 4.8
-
- Returns a UTF-8 representation of the string as a QByteArray.
-
- UTF-8 is a Unicode codec and can represent all characters in a Unicode
- string like QString.
-
- \sa toLatin1(), toLocal8Bit(), QStringEncoder
-*/
-QByteArray QStringRef::toUtf8() const
+qsizetype QtPrivate::indexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
- return qt_convert_to_utf8(*this);
+ return indexOf(haystack, nullptr, re, from, rmatch);
}
-/*!
- \since 4.8
-
- Returns a UCS-4/UTF-32 representation of the string as a QList<uint>.
-
- UCS-4 is a Unicode codec and therefore it is lossless. All characters from
- this string will be encoded in UCS-4. Any invalid sequence of code units in
- this string is replaced by the Unicode's replacement character
- (QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
-
- The returned list is not \\0'-terminated.
-
- \sa toUtf8(), toLatin1(), toLocal8Bit(), QStringEncoder
-*/
-QList<uint> QStringRef::toUcs4() const
+qsizetype QtPrivate::lastIndexOf(QStringView viewHaystack, const QString *stringHaystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
- return qt_convert_to_ucs4(*this);
-}
-
-/*!
- Returns a string that has whitespace removed from the start and
- the end.
-
- Whitespace means any character for which QChar::isSpace() returns
- \c true. This includes the ASCII characters '\\t', '\\n', '\\v',
- '\\f', '\\r', and ' '.
-
- Unlike QString::simplified(), trimmed() leaves internal whitespace alone.
+ if (!re.isValid()) {
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::lastIndexOf");
+ return -1;
+ }
- \since 5.1
+ qsizetype endpos = (from < 0) ? (viewHaystack.size() + from + 1) : (from + 1);
+ QRegularExpressionMatchIterator iterator = stringHaystack
+ ? re.globalMatch(*stringHaystack)
+ : re.globalMatchView(viewHaystack);
+ qsizetype lastIndex = -1;
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ qsizetype start = match.capturedStart();
+ if (start < endpos) {
+ lastIndex = start;
+ if (rmatch)
+ *rmatch = std::move(match);
+ } else {
+ break;
+ }
+ }
- \sa QString::trimmed()
-*/
-QStringRef QStringRef::trimmed() const
-{
- const QChar *begin = cbegin();
- const QChar *end = cend();
- QStringAlgorithms<const QStringRef>::trimmed_helper_positions(begin, end);
- if (begin == cbegin() && end == cend())
- return *this;
- int position = m_position + (begin - cbegin());
- return QStringRef(m_string, position, end - begin);
+ return lastIndex;
}
-/*!
- Returns the string converted to a \c{long long} using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
-
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toLongLong()
-
- \sa QString::toLongLong()
-
- \since 5.1
-*/
-
-qint64 QStringRef::toLongLong(bool *ok, int base) const
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
- return QString::toIntegral_helper<qint64>(*this, ok, base);
+ return lastIndexOf(haystack, nullptr, re, from, rmatch);
}
-/*!
- Returns the string converted to an \c{unsigned long long} using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
-
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toULongLong()
-
- \sa QString::toULongLong()
-
- \since 5.1
-*/
-
-quint64 QStringRef::toULongLong(bool *ok, int base) const
+bool QtPrivate::contains(QStringView viewHaystack, const QString *stringHaystack, const QRegularExpression &re, QRegularExpressionMatch *rmatch)
{
- return QString::toIntegral_helper<quint64>(*this, ok, base);
+ if (!re.isValid()) {
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::contains");
+ return false;
+ }
+ QRegularExpressionMatch m = stringHaystack
+ ? re.match(*stringHaystack)
+ : re.matchView(viewHaystack);
+ bool hasMatch = m.hasMatch();
+ if (hasMatch && rmatch)
+ *rmatch = std::move(m);
+ return hasMatch;
}
-/*!
- \fn long QStringRef::toLong(bool *ok, int base) const
-
- Returns the string converted to a \c long using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
-
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toLong()
-
- \sa QString::toLong()
-
- \since 5.1
-*/
-
-long QStringRef::toLong(bool *ok, int base) const
+bool QtPrivate::contains(QStringView haystack, const QRegularExpression &re, QRegularExpressionMatch *rmatch)
{
- return QString::toIntegral_helper<long>(*this, ok, base);
+ return contains(haystack, nullptr, re, rmatch);
}
-/*!
- \fn ulong QStringRef::toULong(bool *ok, int base) const
-
- Returns the string converted to an \c{unsigned long} using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
-
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toULongLong()
-
- \sa QString::toULong()
-
- \since 5.1
-*/
-
-ulong QStringRef::toULong(bool *ok, int base) const
+qsizetype QtPrivate::count(QStringView haystack, const QRegularExpression &re)
{
- return QString::toIntegral_helper<ulong>(*this, ok, base);
+ if (!re.isValid()) {
+ qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::count");
+ return 0;
+ }
+ qsizetype count = 0;
+ qsizetype index = -1;
+ qsizetype len = haystack.size();
+ while (index <= len - 1) {
+ QRegularExpressionMatch match = re.matchView(haystack, index + 1);
+ if (!match.hasMatch())
+ break;
+ count++;
+
+ // Search again, from the next character after the beginning of this
+ // capture. If the capture starts with a surrogate pair, both together
+ // count as "one character".
+ index = match.capturedStart();
+ if (index < len && haystack[index].isHighSurrogate())
+ ++index;
+ }
+ return count;
}
+#endif // QT_CONFIG(regularexpression)
/*!
- Returns the string converted to an \c int using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ \since 5.0
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toInt()
+ Converts a plain text string to an HTML string with
+ HTML metacharacters \c{<}, \c{>}, \c{&}, and \c{"} replaced by HTML
+ entities.
- \sa QString::toInt()
+ Example:
- \since 5.1
+ \snippet code/src_corelib_text_qstring.cpp 7
*/
-
-int QStringRef::toInt(bool *ok, int base) const
+QString QString::toHtmlEscaped() const
{
- return QString::toIntegral_helper<int>(*this, ok, base);
+ const auto pos = std::u16string_view(*this).find_first_of(u"<>&\"");
+ if (pos == std::u16string_view::npos)
+ return *this;
+ QString rich;
+ const qsizetype len = size();
+ rich.reserve(qsizetype(len * 1.1));
+ rich += qToStringViewIgnoringNull(*this).first(pos);
+ for (auto ch : qToStringViewIgnoringNull(*this).sliced(pos)) {
+ if (ch == u'<')
+ rich += "&lt;"_L1;
+ else if (ch == u'>')
+ rich += "&gt;"_L1;
+ else if (ch == u'&')
+ rich += "&amp;"_L1;
+ else if (ch == u'"')
+ rich += "&quot;"_L1;
+ else
+ rich += ch;
+ }
+ rich.squeeze();
+ return rich;
}
/*!
- Returns the string converted to an \c{unsigned int} using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
+ \macro QStringLiteral(str)
+ \relates QString
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ The macro generates the data for a QString out of the string literal \a str
+ at compile time. Creating a QString from it is free in this case, and the
+ generated string data is stored in the read-only segment of the compiled
+ object file.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ If you have code that looks like this:
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toUInt()
+ \snippet code/src_corelib_text_qstring.cpp 9
- \sa QString::toUInt()
+ then a temporary QString will be created to be passed as the \c{hasAttribute}
+ function parameter. This can be quite expensive, as it involves a memory
+ allocation and the copy/conversion of the data into QString's internal
+ encoding.
- \since 5.1
-*/
+ This cost can be avoided by using QStringLiteral instead:
-uint QStringRef::toUInt(bool *ok, int base) const
-{
- return QString::toIntegral_helper<uint>(*this, ok, base);
-}
+ \snippet code/src_corelib_text_qstring.cpp 10
-/*!
- Returns the string converted to a \c short using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
+ In this case, QString's internal data will be generated at compile time; no
+ conversion or allocation will occur at runtime.
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ Using QStringLiteral instead of a double quoted plain C++ string literal can
+ significantly speed up creation of QString instances from data known at
+ compile time.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ \note QLatin1StringView can still be more efficient than QStringLiteral
+ when the string is passed to a function that has an overload taking
+ QLatin1StringView and this overload avoids conversion to QString. For
+ instance, QString::operator==() can compare to a QLatin1StringView
+ directly:
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toShort()
+ \snippet code/src_corelib_text_qstring.cpp 11
- \sa QString::toShort()
+ \note Some compilers have bugs encoding strings containing characters outside
+ the US-ASCII character set. Make sure you prefix your string with \c{u} in
+ those cases. It is optional otherwise.
- \since 5.1
+ \sa QByteArrayLiteral
*/
-short QStringRef::toShort(bool *ok, int base) const
-{
- return QString::toIntegral_helper<short>(*this, ok, base);
-}
-
+#if QT_DEPRECATED_SINCE(6, 8)
/*!
- Returns the string converted to an \c{unsigned short} using base \a
- base, which is 10 by default and must be between 2 and 36, or 0.
- Returns 0 if the conversion fails.
+ \fn QtLiterals::operator""_qs(const char16_t *str, size_t size)
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ \relates QString
+ \since 6.2
+ \deprecated [6.8] Use \c _s from Qt::StringLiterals namespace instead.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
- base 8 is used; otherwise, base 10 is used.
+ Literal operator that creates a QString out of the first \a size characters in
+ the char16_t string literal \a str.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toUShort()
+ The QString is created at compile time, and the generated string data is stored
+ in the read-only segment of the compiled object file. Duplicate literals may
+ share the same read-only memory. This functionality is interchangeable with
+ QStringLiteral, but saves typing when many string literals are present in the
+ code.
- \sa QString::toUShort()
+ The following code creates a QString:
+ \code
+ auto str = u"hello"_qs;
+ \endcode
- \since 5.1
+ \sa QStringLiteral, QtLiterals::operator""_qba(const char *str, size_t size)
*/
-
-ushort QStringRef::toUShort(bool *ok, int base) const
-{
- return QString::toIntegral_helper<ushort>(*this, ok, base);
-}
-
+#endif // QT_DEPRECATED_SINCE(6, 8)
/*!
- Returns the string converted to a \c double value.
+ \fn Qt::Literals::StringLiterals::operator""_s(const char16_t *str, size_t size)
- Returns an infinity if the conversion overflows or 0.0 if the
- conversion fails for other reasons (e.g. underflow).
+ \relates QString
+ \since 6.4
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
+ Literal operator that creates a QString out of the first \a size characters in
+ the char16_t string literal \a str.
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toDouble()
+ The QString is created at compile time, and the generated string data is stored
+ in the read-only segment of the compiled object file. Duplicate literals may
+ share the same read-only memory. This functionality is interchangeable with
+ QStringLiteral, but saves typing when many string literals are present in the
+ code.
- For historic reasons, this function does not handle
- thousands group separators. If you need to convert such numbers,
- use QLocale::toDouble().
+ The following code creates a QString:
+ \code
+ using namespace Qt::Literals::StringLiterals;
- \sa QString::toDouble()
+ auto str = u"hello"_s;
+ \endcode
- \since 5.1
+ \sa Qt::Literals::StringLiterals
*/
-double QStringRef::toDouble(bool *ok) const
+/*!
+ \internal
+ */
+void QAbstractConcatenable::appendLatin1To(QLatin1StringView in, QChar *out) noexcept
{
- return QLocaleData::c()->stringToDouble(*this, ok, QLocale::RejectGroupSeparator);
+ qt_from_latin1(reinterpret_cast<char16_t *>(out), in.data(), size_t(in.size()));
}
/*!
- Returns the string converted to a \c float value.
-
- Returns an infinity if the conversion overflows or 0.0 if the
- conversion fails for other reasons (e.g. underflow).
-
- If \a ok is not \nullptr, failure is reported by setting *\a{ok}
- to \c false, and success by setting *\a{ok} to \c true.
-
- The string conversion will always happen in the 'C' locale. For locale
- dependent conversion use QLocale::toFloat()
+ \fn template <typename T> qsizetype erase(QString &s, const T &t)
+ \relates QString
+ \since 6.1
- \sa QString::toFloat()
+ Removes all elements that compare equal to \a t from the
+ string \a s. Returns the number of elements removed, if any.
- \since 5.1
+ \sa erase_if
*/
-float QStringRef::toFloat(bool *ok) const
-{
- return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
-}
-
/*!
- \obsolete
- \fn QString Qt::escape(const QString &plain)
+ \fn template <typename Predicate> qsizetype erase_if(QString &s, Predicate pred)
+ \relates QString
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the string \a s. Returns the number of elements removed, if
+ any.
- Use QString::toHtmlEscaped() instead.
+ \sa erase
*/
/*!
- \since 5.0
+ \macro const char *qPrintable(const QString &str)
+ \relates QString
- Converts a plain text string to an HTML string with
- HTML metacharacters \c{<}, \c{>}, \c{&}, and \c{"} replaced by HTML
- entities.
+ Returns \a str as a \c{const char *}. This is equivalent to
+ \a{str}.toLocal8Bit().constData().
- Example:
+ The char pointer will be invalid after the statement in which
+ qPrintable() is used. This is because the array returned by
+ QString::toLocal8Bit() will fall out of scope.
- \snippet code/src_corelib_text_qstring.cpp 7
+ \note qDebug(), qInfo(), qWarning(), qCritical(), qFatal() expect
+ %s arguments to be UTF-8 encoded, while qPrintable() converts to
+ local 8-bit encoding. Therefore qUtf8Printable() should be used
+ for logging strings instead of qPrintable().
+
+ \sa qUtf8Printable()
*/
-QString QString::toHtmlEscaped() const
-{
- QString rich;
- const int len = length();
- rich.reserve(int(len * 1.1));
- for (int i = 0; i < len; ++i) {
- if (at(i) == QLatin1Char('<'))
- rich += QLatin1String("&lt;");
- else if (at(i) == QLatin1Char('>'))
- rich += QLatin1String("&gt;");
- else if (at(i) == QLatin1Char('&'))
- rich += QLatin1String("&amp;");
- else if (at(i) == QLatin1Char('"'))
- rich += QLatin1String("&quot;");
- else
- rich += at(i);
- }
- rich.squeeze();
- return rich;
-}
/*!
- \macro QStringLiteral(str)
- \relates QString
+ \macro const char *qUtf8Printable(const QString &str)
+ \relates QString
+ \since 5.4
- The macro generates the data for a QString out of the string literal \a str
- at compile time. Creating a QString from it is free in this case, and the
- generated string data is stored in the read-only segment of the compiled
- object file.
+ Returns \a str as a \c{const char *}. This is equivalent to
+ \a{str}.toUtf8().constData().
- If you have code that looks like this:
+ The char pointer will be invalid after the statement in which
+ qUtf8Printable() is used. This is because the array returned by
+ QString::toUtf8() will fall out of scope.
- \snippet code/src_corelib_text_qstring.cpp 9
+ Example:
- then a temporary QString will be created to be passed as the \c{hasAttribute}
- function parameter. This can be quite expensive, as it involves a memory
- allocation and the copy/conversion of the data into QString's internal
- encoding.
+ \snippet code/src_corelib_text_qstring.cpp qUtf8Printable
- This cost can be avoided by using QStringLiteral instead:
+ \sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
+*/
- \snippet code/src_corelib_text_qstring.cpp 10
+/*!
+ \macro const wchar_t *qUtf16Printable(const QString &str)
+ \relates QString
+ \since 5.7
- In this case, QString's internal data will be generated at compile time; no
- conversion or allocation will occur at runtime.
+ Returns \a str as a \c{const ushort *}, but cast to a \c{const wchar_t *}
+ to avoid warnings. This is equivalent to \a{str}.utf16() plus some casting.
- Using QStringLiteral instead of a double quoted plain C++ string literal can
- significantly speed up creation of QString instances from data known at
- compile time.
+ The only useful thing you can do with the return value of this macro is to
+ pass it to QString::asprintf() for use in a \c{%ls} conversion. In particular,
+ the return value is \e{not} a valid \c{const wchar_t*}!
- \note QLatin1String can still be more efficient than QStringLiteral
- when the string is passed to a function that has an overload taking
- QLatin1String and this overload avoids conversion to QString. For
- instance, QString::operator==() can compare to a QLatin1String
- directly:
+ In general, the pointer will be invalid after the statement in which
+ qUtf16Printable() is used. This is because the pointer may have been
+ obtained from a temporary expression, which will fall out of scope.
- \snippet code/src_corelib_text_qstring.cpp 11
+ Example:
- \note Some compilers have bugs encoding strings containing characters outside
- the US-ASCII character set. Make sure you prefix your string with \c{u} in
- those cases. It is optional otherwise.
+ \snippet code/src_corelib_text_qstring.cpp qUtf16Printable
- \sa QByteArrayLiteral
+ \sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal()
*/
-/*!
- \internal
- */
-void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out) noexcept
-{
- qt_from_latin1(reinterpret_cast<char16_t *>(out), a, uint(len));
-}
-
-double QStringView::toDouble(bool *ok) const
-{
- return QLocaleData::c()->stringToDouble(*this, ok, QLocale::RejectGroupSeparator);
-}
-
-float QStringView::toFloat(bool *ok) const
-{
- return QLocaleData::convertDoubleToFloat(toDouble(ok), ok);
-}
-
QT_END_NAMESPACE
+
+#undef REHASH
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 95376f79c0..895ec4b5c0 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Copyright (C) 2019 Mail.ru Group.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// Copyright (C) 2019 Mail.ru Group.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRING_H
#define QSTRING_H
@@ -48,16 +12,21 @@
#endif
#include <QtCore/qchar.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qbytearrayview.h>
#include <QtCore/qarraydata.h>
+#include <QtCore/qlatin1stringview.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qstringliteral.h>
#include <QtCore/qstringalgorithms.h>
-#include <QtCore/qstringview.h>
+#include <QtCore/qanystringview.h>
#include <QtCore/qstringtokenizer.h>
#include <string>
#include <iterator>
+#include <QtCore/q20memory.h>
+#include <string_view>
#include <stdarg.h>
@@ -70,239 +39,178 @@ Q_FORWARD_DECLARE_CF_TYPE(CFString);
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
#endif
+class tst_QString;
+
QT_BEGIN_NAMESPACE
class QRegularExpression;
class QRegularExpressionMatch;
class QString;
-class QStringList;
-class QStringRef;
namespace QtPrivate {
template <bool...B> class BoolList;
-}
-
-class QLatin1String
-{
-public:
- Q_DECL_CONSTEXPR inline QLatin1String() noexcept : m_size(0), m_data(nullptr) {}
- Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) noexcept : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
- Q_DECL_CONSTEXPR explicit QLatin1String(const char *f, const char *l)
- : QLatin1String(f, int(l - f)) {}
- Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) noexcept : m_size(sz), m_data(s) {}
- inline explicit QLatin1String(const QByteArray &s) noexcept : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
-
- inline QString toString() const;
-
- Q_DECL_CONSTEXPR const char *latin1() const noexcept { return m_data; }
- Q_DECL_CONSTEXPR int size() const noexcept { return m_size; }
- Q_DECL_CONSTEXPR const char *data() const noexcept { return m_data; }
-
- Q_DECL_CONSTEXPR bool isNull() const noexcept { return !data(); }
- Q_DECL_CONSTEXPR bool isEmpty() const noexcept { return !size(); }
-
- template <typename...Args>
- Q_REQUIRED_RESULT inline QString arg(Args &&...args) const;
-
- Q_DECL_CONSTEXPR QLatin1Char at(int i) const
- { return Q_ASSERT(i >= 0), Q_ASSERT(i < size()), QLatin1Char(m_data[i]); }
- Q_DECL_CONSTEXPR QLatin1Char operator[](int i) const { return at(i); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char front() const { return at(0); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char back() const { return at(size() - 1); }
-
- Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::compareStrings(*this, other, cs); }
- Q_REQUIRED_RESULT int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::compareStrings(*this, other, cs); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int compare(QChar c) const noexcept
- { return isEmpty() || front() == c ? size() - 1 : uchar(m_data[0]) - c.unicode() ; }
- Q_REQUIRED_RESULT int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
- { return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
-
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::startsWith(*this, s, cs); }
- Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::startsWith(*this, s, cs); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool startsWith(QChar c) const noexcept
- { return !isEmpty() && front() == c; }
- Q_REQUIRED_RESULT inline bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
- { return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
-
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::endsWith(*this, s, cs); }
- Q_REQUIRED_RESULT bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::endsWith(*this, s, cs); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool endsWith(QChar c) const noexcept
- { return !isEmpty() && back() == c; }
- Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
- { return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
-
- Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsizetype
- Q_REQUIRED_RESULT int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsizetype
- Q_REQUIRED_RESULT inline int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::findString(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsizetype
-
- Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return indexOf(s, 0, cs) != -1; }
- Q_REQUIRED_RESULT bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return indexOf(s, 0, cs) != -1; }
- Q_REQUIRED_RESULT inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return indexOf(QStringView(&c, 1), 0, cs) != -1; }
-
- Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsizetype
- Q_REQUIRED_RESULT int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsizetype
- Q_REQUIRED_RESULT inline int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsizetype
-
- using value_type = const char;
- using reference = value_type&;
- using const_reference = reference;
- using iterator = value_type*;
- using const_iterator = iterator;
- using difference_type = int; // violates Container concept requirements
- using size_type = int; // violates Container concept requirements
-
- Q_DECL_CONSTEXPR const_iterator begin() const noexcept { return data(); }
- Q_DECL_CONSTEXPR const_iterator cbegin() const noexcept { return data(); }
- Q_DECL_CONSTEXPR const_iterator end() const noexcept { return data() + size(); }
- Q_DECL_CONSTEXPR const_iterator cend() const noexcept { return data() + size(); }
-
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = reverse_iterator;
-
- const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
- const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
- const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
-
- constexpr QLatin1String mid(int pos, int n = -1) const
- {
- qsizetype p = pos;
- qsizetype l = n;
- using namespace QtPrivate;
- auto result = QContainerImplHelper::mid(size(), &p, &l);
- return result == QContainerImplHelper::Null ? QLatin1String() : QLatin1String(m_data + p, l);
- }
- constexpr QLatin1String left(int n) const
- {
- if (size_t(n) >= size_t(size()))
- n = size();
- return QLatin1String(m_data, n);
- }
- constexpr QLatin1String right(int n) const
- {
- if (size_t(n) >= size_t(size()))
- n = size();
- return QLatin1String(m_data + m_size - n, n);
- }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1String chopped(int n) const
- { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, m_size - n); }
-
- Q_DECL_RELAXED_CONSTEXPR void chop(int n)
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
- Q_DECL_RELAXED_CONSTEXPR void truncate(int n)
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
-
- Q_REQUIRED_RESULT QLatin1String trimmed() const noexcept { return QtPrivate::trimmed(*this); }
-
- template <typename Needle, typename...Flags>
- Q_REQUIRED_RESULT inline constexpr auto tokenize(Needle &&needle, Flags...flags) const
- noexcept(noexcept(qTokenize(std::declval<const QLatin1String &>(), std::forward<Needle>(needle), flags...)))
- -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
- { return qTokenize(*this, std::forward<Needle>(needle), flags...); }
-
- inline bool operator==(const QString &s) const noexcept;
- inline bool operator!=(const QString &s) const noexcept;
- inline bool operator>(const QString &s) const noexcept;
- inline bool operator<(const QString &s) const noexcept;
- inline bool operator>=(const QString &s) const noexcept;
- inline bool operator<=(const QString &s) const noexcept;
-
-#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
- inline QT_ASCII_CAST_WARN bool operator==(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator<(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator>(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator<=(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const;
-
- inline QT_ASCII_CAST_WARN bool operator==(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator!=(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator<(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator>(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator<=(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator>=(const QByteArray &s) const;
-#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
-
-private:
- int m_size;
- const char *m_data;
-};
-Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE);
+template <typename Char>
+using IsCompatibleChar32TypeHelper =
+ std::is_same<Char, char32_t>;
+template <typename Char>
+using IsCompatibleChar32Type
+ = IsCompatibleChar32TypeHelper<q20::remove_cvref_t<Char>>;
+}
// Qt 4.x compatibility
//
-// QLatin1String inline implementations
+// QLatin1StringView inline implementations
//
-Q_DECL_CONSTEXPR bool QtPrivate::isLatin1(QLatin1String) noexcept
+constexpr bool QtPrivate::isLatin1(QLatin1StringView) noexcept
{ return true; }
//
-// QStringView members that require QLatin1String:
+// QStringView members that require QLatin1StringView:
//
-int QStringView::compare(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
+int QStringView::compare(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::compareStrings(*this, s, cs); }
-bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
+bool QStringView::startsWith(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
-bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
+bool QStringView::endsWith(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
-qsizetype QStringView::indexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
+qsizetype QStringView::indexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::findString(*this, from, s, cs); }
-bool QStringView::contains(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
+bool QStringView::contains(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
{ return indexOf(s, 0, cs) != qsizetype(-1); }
-qsizetype QStringView::lastIndexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
+qsizetype QStringView::lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
+{ return QtPrivate::lastIndexOf(*this, size(), s, cs); }
+qsizetype QStringView::lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
+qsizetype QStringView::count(QLatin1StringView s, Qt::CaseSensitivity cs) const
+{ return QtPrivate::count(*this, s, cs); }
+
+//
+// QAnyStringView members that require QLatin1StringView
+//
+
+constexpr QAnyStringView::QAnyStringView(QLatin1StringView str) noexcept
+ : m_data{str.data()}, m_size{size_t(str.size() << SizeShift) | Tag::Latin1} {}
+
+constexpr QLatin1StringView QAnyStringView::asLatin1StringView() const
+{
+ Q_ASSERT(isLatin1());
+ return {m_data_utf8, size()};
+}
+
+
+template <typename Visitor>
+constexpr decltype(auto) QAnyStringView::visit(Visitor &&v) const
+{
+ if (isUtf16())
+ return std::forward<Visitor>(v)(asStringView());
+ else if (isLatin1())
+ return std::forward<Visitor>(v)(asLatin1StringView());
+ else
+ return std::forward<Visitor>(v)(asUtf8StringView());
+}
+
+//
+// QAnyStringView members that require QAnyStringView::visit()
+//
+
+constexpr QChar QAnyStringView::front() const
+{
+ return visit([] (auto that) { return QAnyStringView::toQChar(that.front()); });
+}
+constexpr QChar QAnyStringView::back() const
+{
+ return visit([] (auto that) { return QAnyStringView::toQChar(that.back()); });
+}
+
class Q_CORE_EXPORT QString
{
typedef QTypedArrayData<char16_t> Data;
+
+ friend class ::tst_QString;
+
+ template <typename Iterator>
+ static constexpr bool is_contiguous_iterator_v =
+ // Can't use contiguous_iterator_tag here, as STL impls can't agree on feature macro.
+ // To avoid differences in C++20 and C++17 builds, treat only pointers as contiguous
+ // for now:
+ // std::contiguous_iterator<Iterator>;
+ std::is_pointer_v<Iterator>;
+
+ template <typename Char>
+ using is_compatible_char_helper = std::disjunction<
+ QtPrivate::IsCompatibleCharType<Char>,
+ QtPrivate::IsCompatibleChar32Type<Char>,
+ QtPrivate::IsCompatibleChar8Type<Char>,
+ std::is_same<Char, QLatin1Char> // special case
+ >;
+
+ template <typename Iterator>
+ static constexpr bool is_compatible_iterator_v = std::conjunction_v<
+ std::is_convertible<
+ typename std::iterator_traits<Iterator>::iterator_category,
+ std::input_iterator_tag
+ >,
+ is_compatible_char_helper<typename std::iterator_traits<Iterator>::value_type>
+ >;
+
+ template <typename Iterator>
+ using if_compatible_iterator = std::enable_if_t<is_compatible_iterator_v<Iterator>, bool>;
+
public:
typedef QStringPrivate DataPointer;
- inline QString() noexcept;
- explicit QString(const QChar *unicode, int size = -1);
+ constexpr QString() noexcept;
+ explicit QString(const QChar *unicode, qsizetype size = -1);
QString(QChar c);
- QString(int size, QChar c);
- inline QString(QLatin1String latin1);
+ QString(qsizetype size, QChar c);
+ inline QString(QLatin1StringView latin1);
+ explicit QString(QStringView sv) : QString(sv.data(), sv.size()) {}
+#if defined(__cpp_char8_t) || defined(Q_QDOC)
+ Q_WEAK_OVERLOAD
+ inline QString(const char8_t *str)
+ : QString(fromUtf8(str))
+ {}
+#endif
inline QString(const QString &) noexcept;
inline ~QString();
QString &operator=(QChar c);
QString &operator=(const QString &) noexcept;
- QString &operator=(QLatin1String latin1);
+ QString &operator=(QLatin1StringView latin1);
inline QString(QString &&other) noexcept
- { qSwap(d, other.d); }
- inline QString &operator=(QString &&other) noexcept
- { qSwap(d, other.d); return *this; }
- inline void swap(QString &other) noexcept { qSwap(d, other.d); }
- inline int size() const { return int(d.size); }
- inline int count() const { return int(d.size); }
- inline int length() const;
- inline bool isEmpty() const;
- void resize(int size);
- void resize(int size, QChar fillChar);
-
- QString &fill(QChar c, int size = -1);
- void truncate(int pos);
- void chop(int n);
-
- inline int capacity() const;
- inline void reserve(int size);
+ = default;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QString)
+ void swap(QString &other) noexcept { d.swap(other.d); }
+ inline qsizetype size() const noexcept { return d.size; }
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use size() or length() instead.")
+ inline qsizetype count() const { return d.size; }
+#endif
+ inline qsizetype length() const noexcept { return d.size; }
+ inline bool isEmpty() const noexcept { return d.size == 0; }
+ void resize(qsizetype size);
+ void resize(qsizetype size, QChar fillChar);
+ void resizeForOverwrite(qsizetype size);
+
+ QString &fill(QChar c, qsizetype size = -1);
+ void truncate(qsizetype pos);
+ void chop(qsizetype n);
+
+ QString &slice(qsizetype pos)
+ { verify(pos, 0); return remove(0, pos); }
+ QString &slice(qsizetype pos, qsizetype n)
+ {
+ verify(pos, n);
+ if (isNull())
+ return *this;
+ resize(pos + n);
+ return remove(0, pos);
+ }
+
+ inline qsizetype capacity() const;
+ inline void reserve(qsizetype size);
inline void squeeze();
inline const QChar *unicode() const;
@@ -313,61 +221,56 @@ public:
inline void detach();
inline bool isDetached() const;
inline bool isSharedWith(const QString &other) const { return d.isSharedWith(other.d); }
- void clear();
-
- inline const QChar at(int i) const;
- const QChar operator[](int i) const;
- Q_REQUIRED_RESULT QChar &operator[](int i);
-
- Q_REQUIRED_RESULT inline QChar front() const { return at(0); }
- Q_REQUIRED_RESULT inline QChar &front();
- Q_REQUIRED_RESULT inline QChar back() const { return at(size() - 1); }
- Q_REQUIRED_RESULT inline QChar &back();
-
- Q_REQUIRED_RESULT QString arg(qlonglong a, int fieldwidth=0, int base=10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(qulonglong a, int fieldwidth=0, int base=10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(long a, int fieldwidth=0, int base=10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(ulong a, int fieldwidth=0, int base=10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(int a, int fieldWidth = 0, int base = 10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(uint a, int fieldWidth = 0, int base = 10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(short a, int fieldWidth = 0, int base = 10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(ushort a, int fieldWidth = 0, int base = 10,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(double a, int fieldWidth = 0, char fmt = 'g', int prec = -1,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(char a, int fieldWidth = 0,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(QChar a, int fieldWidth = 0,
- QChar fillChar = QLatin1Char(' ')) const;
-#if QT_STRINGVIEW_LEVEL < 2
- Q_REQUIRED_RESULT QString arg(const QString &a, int fieldWidth = 0,
- QChar fillChar = QLatin1Char(' ')) const;
-#endif
- Q_REQUIRED_RESULT QString arg(QStringView a, int fieldWidth = 0,
- QChar fillChar = QLatin1Char(' ')) const;
- Q_REQUIRED_RESULT QString arg(QLatin1String a, int fieldWidth = 0,
- QChar fillChar = QLatin1Char(' ')) const;
+ inline void clear();
+
+ inline const QChar at(qsizetype i) const;
+ inline const QChar operator[](qsizetype i) const;
+ [[nodiscard]] inline QChar &operator[](qsizetype i);
+
+ [[nodiscard]] inline QChar front() const { return at(0); }
+ [[nodiscard]] inline QChar &front();
+ [[nodiscard]] inline QChar back() const { return at(size() - 1); }
+ [[nodiscard]] inline QChar &back();
+
+ [[nodiscard]] QString arg(qlonglong a, int fieldwidth=0, int base=10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(qulonglong a, int fieldwidth=0, int base=10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] inline QString arg(long a, int fieldwidth=0, int base=10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] inline QString arg(ulong a, int fieldwidth=0, int base=10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] inline QString arg(int a, int fieldWidth = 0, int base = 10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] inline QString arg(uint a, int fieldWidth = 0, int base = 10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] inline QString arg(short a, int fieldWidth = 0, int base = 10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] inline QString arg(ushort a, int fieldWidth = 0, int base = 10,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(double a, int fieldWidth = 0, char format = 'g', int precision = -1,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(char a, int fieldWidth = 0,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(QChar a, int fieldWidth = 0,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(const QString &a, int fieldWidth = 0,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(QStringView a, int fieldWidth = 0,
+ QChar fillChar = u' ') const;
+ [[nodiscard]] QString arg(QLatin1StringView a, int fieldWidth = 0,
+ QChar fillChar = u' ') const;
private:
template <typename T>
- struct is_convertible_to_view_or_qstring_helper
- : std::integral_constant<bool,
- std::is_convertible<T, QString>::value ||
- std::is_convertible<T, QStringView>::value ||
- std::is_convertible<T, QLatin1String>::value> {};
- template <typename T>
- struct is_convertible_to_view_or_qstring
- : is_convertible_to_view_or_qstring_helper<typename std::decay<T>::type> {};
+ using is_convertible_to_view_or_qstring = std::disjunction<
+ std::is_convertible<T, QString>,
+ std::is_convertible<T, QStringView>,
+ std::is_convertible<T, QLatin1StringView>
+ >;
public:
template <typename...Args>
- Q_REQUIRED_RESULT
-#ifdef Q_CLANG_QDOC
+ [[nodiscard]]
+#ifdef Q_QDOC
QString
#else
typename std::enable_if<
@@ -384,39 +287,51 @@ public:
static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1, 0);
static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
- int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
- int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsizetype
- int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
- int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
-
- Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsizetype
-
- inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
- inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] QT_CORE_INLINE_SINCE(6, 7)
+ qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype indexOf(const QString &s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, s, cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(c, -1, cs); }
+ [[nodiscard]] QT_CORE_INLINE_SINCE(6, 7)
+ qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return lastIndexOf(s, size(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype lastIndexOf(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return lastIndexOf(s, size(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(const QString &s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(s, size(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, s, cs); }
+
+ [[nodiscard]] inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#if QT_CONFIG(regularexpression)
- int indexOf(const QRegularExpression &re, int from = 0,
- QRegularExpressionMatch *rmatch = nullptr) const;
- int lastIndexOf(const QRegularExpression &re, int from = -1,
- QRegularExpressionMatch *rmatch = nullptr) const;
- bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
- int count(const QRegularExpression &re) const;
+ [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0,
+ QRegularExpressionMatch *rmatch = nullptr) const;
+#ifdef Q_QDOC
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
+#else
+ // prevent an ambiguity when called like this: lastIndexOf(re, 0)
+ template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
+ { return lastIndexOf(re, size(), rmatch); }
+#endif
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from,
+ QRegularExpressionMatch *rmatch = nullptr) const;
+ [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
+ [[nodiscard]] qsizetype count(const QRegularExpression &re) const;
#endif
enum SectionFlag {
@@ -428,147 +343,239 @@ public:
};
Q_DECLARE_FLAGS(SectionFlags, SectionFlag)
- QString section(QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault) const;
- QString section(const QString &in_sep, int start, int end = -1, SectionFlags flags = SectionDefault) const;
+ [[nodiscard]] inline QString section(QChar sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
+ [[nodiscard]] QString section(const QString &in_sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
#if QT_CONFIG(regularexpression)
- QString section(const QRegularExpression &re, int start, int end = -1, SectionFlags flags = SectionDefault) const;
+ [[nodiscard]] QString section(const QRegularExpression &re, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
#endif
- Q_REQUIRED_RESULT QString left(int n) const;
- Q_REQUIRED_RESULT QString right(int n) const;
- Q_REQUIRED_RESULT QString mid(int position, int n = -1) const;
-
- Q_REQUIRED_RESULT QString first(qsizetype n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QString(data(), int(n)); }
- Q_REQUIRED_RESULT QString last(qsizetype n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QString(data() + size() - n, int(n)); }
- Q_REQUIRED_RESULT QString from(qsizetype pos) const
- { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QString(data() + pos, size() - int(pos)); }
- Q_REQUIRED_RESULT QString sliced(qsizetype pos, qsizetype n) const
- { Q_ASSERT(pos >= 0); Q_ASSERT(n >= 0); Q_ASSERT(size_t(pos) + size_t(n) <= size_t(size())); return QString(data() + pos, int(n)); }
- Q_REQUIRED_RESULT QString chopped(int n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return first(size() - n); }
-
-
- Q_REQUIRED_RESULT QStringRef leftRef(int n) const;
- Q_REQUIRED_RESULT QStringRef rightRef(int n) const;
- Q_REQUIRED_RESULT QStringRef midRef(int position, int n = -1) const;
-
-#if QT_STRINGVIEW_LEVEL < 2
- bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ QString left(qsizetype n) const;
+ QString right(qsizetype n) const;
+ QString mid(qsizetype position, qsizetype n = -1) const;
+
+ QString first(qsizetype n) const;
+ QString last(qsizetype n) const;
+ QString sliced(qsizetype pos) const;
+ QString sliced(qsizetype pos, qsizetype n) const;
+ QString chopped(qsizetype n) const;
+#else
+ [[nodiscard]] QString left(qsizetype n) const &
+ {
+ if (size_t(n) >= size_t(size()))
+ return *this;
+ return first(n);
+ }
+ [[nodiscard]] QString left(qsizetype n) &&
+ {
+ if (size_t(n) >= size_t(size()))
+ return std::move(*this);
+ return std::move(*this).first(n);
+ }
+ [[nodiscard]] QString right(qsizetype n) const &
+ {
+ if (size_t(n) >= size_t(size()))
+ return *this;
+ return last(n);
+ }
+ [[nodiscard]] QString right(qsizetype n) &&
+ {
+ if (size_t(n) >= size_t(size()))
+ return std::move(*this);
+ return std::move(*this).last(n);
+ }
+ [[nodiscard]] QString mid(qsizetype position, qsizetype n = -1) const &;
+ [[nodiscard]] QString mid(qsizetype position, qsizetype n = -1) &&;
+
+ [[nodiscard]] QString first(qsizetype n) const &
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] QString last(qsizetype n) const &
+ { verify(0, n); return sliced(size() - n, n); }
+ [[nodiscard]] QString sliced(qsizetype pos) const &
+ { verify(pos, 0); return sliced(pos, size() - pos); }
+ [[nodiscard]] QString sliced(qsizetype pos, qsizetype n) const &
+ { verify(pos, n); return QString(begin() + pos, n); }
+ [[nodiscard]] QString chopped(qsizetype n) const &
+ { verify(0, n); return sliced(0, size() - n); }
+
+ [[nodiscard]] QString first(qsizetype n) &&
+ {
+ verify(0, n);
+ resize(n); // may detach and allocate memory
+ return std::move(*this);
+ }
+ [[nodiscard]] QString last(qsizetype n) &&
+ { verify(0, n); return sliced_helper(*this, size() - n, n); }
+ [[nodiscard]] QString sliced(qsizetype pos) &&
+ { verify(pos, 0); return sliced_helper(*this, pos, size() - pos); }
+ [[nodiscard]] QString sliced(qsizetype pos, qsizetype n) &&
+ { verify(pos, n); return sliced_helper(*this, pos, n); }
+ [[nodiscard]] QString chopped(qsizetype n) &&
+ { verify(0, n); return std::move(*this).first(size() - n); }
#endif
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
- bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
- bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool isUpper() const;
bool isLower() const;
- Q_REQUIRED_RESULT QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const;
- Q_REQUIRED_RESULT QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const;
-
-#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
-# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_cpp_attribute(nodiscard)
- // required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
-# pragma push_macro("Q_REQUIRED_RESULT")
-# undef Q_REQUIRED_RESULT
-# define Q_REQUIRED_RESULT
-# define Q_REQUIRED_RESULT_pushed
-# endif
- Q_REQUIRED_RESULT QString toLower() const &
+ [[nodiscard]] QString leftJustified(qsizetype width, QChar fill = u' ', bool trunc = false) const;
+ [[nodiscard]] QString rightJustified(qsizetype width, QChar fill = u' ', bool trunc = false) const;
+
+#if !defined(Q_QDOC)
+ [[nodiscard]] QString toLower() const &
{ return toLower_helper(*this); }
- Q_REQUIRED_RESULT QString toLower() &&
+ [[nodiscard]] QString toLower() &&
{ return toLower_helper(*this); }
- Q_REQUIRED_RESULT QString toUpper() const &
+ [[nodiscard]] QString toUpper() const &
{ return toUpper_helper(*this); }
- Q_REQUIRED_RESULT QString toUpper() &&
+ [[nodiscard]] QString toUpper() &&
{ return toUpper_helper(*this); }
- Q_REQUIRED_RESULT QString toCaseFolded() const &
+ [[nodiscard]] QString toCaseFolded() const &
{ return toCaseFolded_helper(*this); }
- Q_REQUIRED_RESULT QString toCaseFolded() &&
+ [[nodiscard]] QString toCaseFolded() &&
{ return toCaseFolded_helper(*this); }
- Q_REQUIRED_RESULT QString trimmed() const &
+ [[nodiscard]] QString trimmed() const &
{ return trimmed_helper(*this); }
- Q_REQUIRED_RESULT QString trimmed() &&
+ [[nodiscard]] QString trimmed() &&
{ return trimmed_helper(*this); }
- Q_REQUIRED_RESULT QString simplified() const &
+ [[nodiscard]] QString simplified() const &
{ return simplified_helper(*this); }
- Q_REQUIRED_RESULT QString simplified() &&
+ [[nodiscard]] QString simplified() &&
{ return simplified_helper(*this); }
-# ifdef Q_REQUIRED_RESULT_pushed
-# pragma pop_macro("Q_REQUIRED_RESULT")
-# endif
#else
- Q_REQUIRED_RESULT QString toLower() const;
- Q_REQUIRED_RESULT QString toUpper() const;
- Q_REQUIRED_RESULT QString toCaseFolded() const;
- Q_REQUIRED_RESULT QString trimmed() const;
- Q_REQUIRED_RESULT QString simplified() const;
+ [[nodiscard]] QString toLower() const;
+ [[nodiscard]] QString toUpper() const;
+ [[nodiscard]] QString toCaseFolded() const;
+ [[nodiscard]] QString trimmed() const;
+ [[nodiscard]] QString simplified() const;
#endif
- Q_REQUIRED_RESULT QString toHtmlEscaped() const;
+ [[nodiscard]] QString toHtmlEscaped() const;
- QString &insert(int i, QChar c);
- QString &insert(int i, const QChar *uc, int len);
-#if QT_STRINGVIEW_LEVEL < 2
- inline QString &insert(int i, const QString &s) { return insert(i, s.constData(), s.length()); }
-#endif
- inline QString &insert(int i, QStringView v) { return insert(i, v.data(), v.length()); }
- QString &insert(int i, QLatin1String s);
+ QString &insert(qsizetype i, QChar c);
+ QString &insert(qsizetype i, const QChar *uc, qsizetype len);
+ inline QString &insert(qsizetype i, const QString &s) { return insert(i, s.constData(), s.size()); }
+ inline QString &insert(qsizetype i, QStringView v) { return insert(i, v.data(), v.size()); }
+ QString &insert(qsizetype i, QLatin1StringView s);
+ QString &insert(qsizetype i, QUtf8StringView s);
QString &append(QChar c);
- QString &append(const QChar *uc, int len);
-#if QT_STRINGVIEW_LEVEL < 2
+ QString &append(const QChar *uc, qsizetype len);
QString &append(const QString &s);
-#endif
- inline QString &append(QStringView v) { return append(v.data(), v.length()); }
- QString &append(QLatin1String s);
+ inline QString &append(QStringView v) { return append(v.data(), v.size()); }
+ QString &append(QLatin1StringView s);
+ QString &append(QUtf8StringView s);
inline QString &prepend(QChar c) { return insert(0, c); }
- inline QString &prepend(const QChar *uc, int len) { return insert(0, uc, len); }
-#if QT_STRINGVIEW_LEVEL < 2
+ inline QString &prepend(const QChar *uc, qsizetype len) { return insert(0, uc, len); }
inline QString &prepend(const QString &s) { return insert(0, s); }
-#endif
- inline QString &prepend(QStringView v) { return prepend(v.data(), v.length()); }
- inline QString &prepend(QLatin1String s) { return insert(0, s); }
-
- inline QString &operator+=(QChar c) {
- if (d->needsDetach() || int(d.size + 1) > capacity())
- reallocData(uint(d.size) + 2u, true);
- d->data()[d.size++] = c.unicode();
- d->data()[d.size] = '\0';
- return *this;
+ inline QString &prepend(QStringView v) { return prepend(v.data(), v.size()); }
+ inline QString &prepend(QLatin1StringView s) { return insert(0, s); }
+ QString &prepend(QUtf8StringView s) { return insert(0, s); }
+
+ QString &assign(QAnyStringView s);
+ inline QString &assign(qsizetype n, QChar c)
+ {
+ Q_ASSERT(n >= 0);
+ return fill(c, n);
}
+ template <typename InputIterator, if_compatible_iterator<InputIterator> = true>
+ QString &assign(InputIterator first, InputIterator last)
+ {
+ using V = typename std::iterator_traits<InputIterator>::value_type;
+ constexpr bool IsL1C = std::is_same_v<std::remove_cv_t<V>, QLatin1Char>;
+ constexpr bool IsFwdIt = std::is_convertible_v<
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ std::forward_iterator_tag
+ >;
+
+ if constexpr (is_contiguous_iterator_v<InputIterator>) {
+ const auto p = q20::to_address(first);
+ const auto len = qsizetype(last - first);
+ if constexpr (IsL1C)
+ return assign(QLatin1StringView(reinterpret_cast<const char*>(p), len));
+ else if constexpr (sizeof(V) == 4)
+ return assign_helper(p, len);
+ else
+ return assign(QAnyStringView(p, len));
+ } else if constexpr (sizeof(V) == 4) { // non-contiguous iterator, feed data piecemeal
+ resize(0);
+ if constexpr (IsFwdIt) {
+ const qsizetype requiredCapacity = 2 * std::distance(first, last);
+ reserve(requiredCapacity);
+ }
+ while (first != last) {
+ append(QChar::fromUcs4(*first));
+ ++first;
+ }
+ return *this;
+ } else if constexpr (QtPrivate::IsCompatibleChar8Type<V>::value) {
+ assign_helper_char8(first, last);
+ d.data()[d.size] = u'\0';
+ return *this;
+ } else {
+ d.assign(first, last, [](QChar ch) -> char16_t { return ch.unicode(); });
+ d.data()[d.size] = u'\0';
+ return *this;
+ }
+ }
+
+ inline QString &operator+=(QChar c) { return append(c); }
-#if QT_STRINGVIEW_LEVEL < 2
inline QString &operator+=(const QString &s) { return append(s); }
-#endif
inline QString &operator+=(QStringView v) { return append(v); }
- inline QString &operator+=(QLatin1String s) { return append(s); }
+ inline QString &operator+=(QLatin1StringView s) { return append(s); }
+ QString &operator+=(QUtf8StringView s) { return append(s); }
- QString &remove(int i, int len);
+#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ template <qsizetype N>
+ QString &insert(qsizetype i, const char (&ch)[N]) { return insert(i, QUtf8StringView(ch)); }
+ template <qsizetype N>
+ QString &append(const char (&ch)[N]) { return append(QUtf8StringView(ch)); }
+ template <qsizetype N>
+ QString &prepend(const char (&ch)[N]) { return prepend(QUtf8StringView(ch)); }
+ template <qsizetype N>
+ QString &operator+=(const char (&ch)[N]) { return append(QUtf8StringView(ch)); }
+#endif
+
+ QString &remove(qsizetype i, qsizetype len);
QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &remove(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &remove(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &replace(int i, int len, QChar after);
- QString &replace(int i, int len, const QChar *s, int slen);
- QString &replace(int i, int len, const QString &after);
+
+ QString &removeAt(qsizetype pos)
+ { return size_t(pos) < size_t(size()) ? remove(pos, 1) : *this; }
+ QString &removeFirst() { return !isEmpty() ? remove(0, 1) : *this; }
+ QString &removeLast() { return !isEmpty() ? remove(size() - 1, 1) : *this; }
+
+ template <typename Predicate>
+ QString &removeIf(Predicate pred)
+ {
+ removeIf_helper(pred);
+ return *this;
+ }
+
+ QString &replace(qsizetype i, qsizetype len, QChar after);
+ QString &replace(qsizetype i, qsizetype len, const QChar *s, qsizetype slen);
+ QString &replace(qsizetype i, qsizetype len, const QString &after);
QString &replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &replace(const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &replace(QLatin1String before, QLatin1String after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &replace(QLatin1String before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &replace(const QString &before, QLatin1String after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(const QChar *before, qsizetype blen, const QChar *after, qsizetype alen, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(QLatin1StringView before, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(QLatin1StringView before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(const QString &before, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
QString &replace(const QString &before, const QString &after,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
QString &replace(QChar c, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QString &replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
#if QT_CONFIG(regularexpression)
QString &replace(const QRegularExpression &re, const QString &after);
inline QString &remove(const QRegularExpression &re)
@@ -576,40 +583,32 @@ public:
#endif
public:
- Q_REQUIRED_RESULT
+ [[nodiscard]]
QStringList split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- Q_REQUIRED_RESULT
- QList<QStringRef> splitRef(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- Q_REQUIRED_RESULT
+ [[nodiscard]]
QStringList split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- Q_REQUIRED_RESULT
- QList<QStringRef> splitRef(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#ifndef QT_NO_REGULAREXPRESSION
- Q_REQUIRED_RESULT
+ [[nodiscard]]
QStringList split(const QRegularExpression &sep,
Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
- Q_REQUIRED_RESULT
- QList<QStringRef> splitRef(const QRegularExpression &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
#endif
template <typename Needle, typename...Flags>
- Q_REQUIRED_RESULT inline auto tokenize(Needle &&needle, Flags...flags) const &
+ [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) const &
noexcept(noexcept(qTokenize(std::declval<const QString &>(), std::forward<Needle>(needle), flags...)))
-> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
{ return qTokenize(qToStringViewIgnoringNull(*this), std::forward<Needle>(needle), flags...); }
template <typename Needle, typename...Flags>
- Q_REQUIRED_RESULT inline auto tokenize(Needle &&needle, Flags...flags) const &&
+ [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) const &&
noexcept(noexcept(qTokenize(std::declval<const QString>(), std::forward<Needle>(needle), flags...)))
-> decltype(qTokenize(std::move(*this), std::forward<Needle>(needle), flags...))
{ return qTokenize(std::move(*this), std::forward<Needle>(needle), flags...); }
template <typename Needle, typename...Flags>
- Q_REQUIRED_RESULT inline auto tokenize(Needle &&needle, Flags...flags) &&
+ [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) &&
noexcept(noexcept(qTokenize(std::declval<QString>(), std::forward<Needle>(needle), flags...)))
-> decltype(qTokenize(std::move(*this), std::forward<Needle>(needle), flags...))
{ return qTokenize(std::move(*this), std::forward<Needle>(needle), flags...); }
@@ -621,80 +620,84 @@ public:
NormalizationForm_KD,
NormalizationForm_KC
};
- Q_REQUIRED_RESULT QString normalized(NormalizationForm mode, QChar::UnicodeVersion version = QChar::Unicode_Unassigned) const;
+ [[nodiscard]] QString normalized(NormalizationForm mode, QChar::UnicodeVersion version = QChar::Unicode_Unassigned) const;
- Q_REQUIRED_RESULT QString repeated(int times) const;
+ [[nodiscard]] QString repeated(qsizetype times) const;
- const ushort *utf16() const;
+ const ushort *utf16() const; // ### Qt 7 char16_t
-#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
- Q_REQUIRED_RESULT QByteArray toLatin1() const &
+#if !defined(Q_QDOC)
+ [[nodiscard]] QByteArray toLatin1() const &
{ return toLatin1_helper(*this); }
- Q_REQUIRED_RESULT QByteArray toLatin1() &&
+ [[nodiscard]] QByteArray toLatin1() &&
{ return toLatin1_helper_inplace(*this); }
- Q_REQUIRED_RESULT QByteArray toUtf8() const &
+ [[nodiscard]] QByteArray toUtf8() const &
{ return toUtf8_helper(*this); }
- Q_REQUIRED_RESULT QByteArray toUtf8() &&
+ [[nodiscard]] QByteArray toUtf8() &&
{ return toUtf8_helper(*this); }
- Q_REQUIRED_RESULT QByteArray toLocal8Bit() const &
+ [[nodiscard]] QByteArray toLocal8Bit() const &
{ return toLocal8Bit_helper(isNull() ? nullptr : constData(), size()); }
- Q_REQUIRED_RESULT QByteArray toLocal8Bit() &&
+ [[nodiscard]] QByteArray toLocal8Bit() &&
{ return toLocal8Bit_helper(isNull() ? nullptr : constData(), size()); }
#else
- Q_REQUIRED_RESULT QByteArray toLatin1() const;
- Q_REQUIRED_RESULT QByteArray toUtf8() const;
- Q_REQUIRED_RESULT QByteArray toLocal8Bit() const;
+ [[nodiscard]] QByteArray toLatin1() const;
+ [[nodiscard]] QByteArray toUtf8() const;
+ [[nodiscard]] QByteArray toLocal8Bit() const;
#endif
- Q_REQUIRED_RESULT QList<uint> toUcs4() const;
+ [[nodiscard]] QList<uint> toUcs4() const; // ### Qt 7 char32_t
// note - this are all inline so we can benefit from strlen() compile time optimizations
- static inline QString fromLatin1(const char *str, int size = -1)
+ static QString fromLatin1(QByteArrayView ba);
+ Q_WEAK_OVERLOAD
+ static inline QString fromLatin1(const QByteArray &ba) { return fromLatin1(QByteArrayView(ba)); }
+ static inline QString fromLatin1(const char *str, qsizetype size)
{
- return QString(fromLatin1_helper(str, (str && size == -1) ? int(strlen(str)) : size));
+ return fromLatin1(QByteArrayView(str, !str || size < 0 ? qstrlen(str) : size));
}
- static inline QString fromUtf8(const char *str, int size = -1)
+ static QString fromUtf8(QByteArrayView utf8);
+ Q_WEAK_OVERLOAD
+ static inline QString fromUtf8(const QByteArray &ba) { return fromUtf8(QByteArrayView(ba)); }
+ static inline QString fromUtf8(const char *utf8, qsizetype size)
{
- return fromUtf8_helper(str, (str && size == -1) ? int(strlen(str)) : size);
+ return fromUtf8(QByteArrayView(utf8, !utf8 || size < 0 ? qstrlen(utf8) : size));
}
-#ifdef __cpp_char8_t
+#if defined(__cpp_char8_t) || defined(Q_QDOC)
Q_WEAK_OVERLOAD
- static inline QString fromUtf8(const char8_t *str, qsizetype size = -1)
- { return fromUtf8(reinterpret_cast<const char *>(str), int(size)); }
+ static inline QString fromUtf8(const char8_t *str)
+ { return fromUtf8(reinterpret_cast<const char *>(str)); }
+ Q_WEAK_OVERLOAD
+ static inline QString fromUtf8(const char8_t *str, qsizetype size)
+ { return fromUtf8(reinterpret_cast<const char *>(str), size); }
#endif
- static inline QString fromLocal8Bit(const char *str, int size = -1)
+ static QString fromLocal8Bit(QByteArrayView ba);
+ Q_WEAK_OVERLOAD
+ static inline QString fromLocal8Bit(const QByteArray &ba) { return fromLocal8Bit(QByteArrayView(ba)); }
+ static inline QString fromLocal8Bit(const char *str, qsizetype size)
{
- return fromLocal8Bit_helper(str, (str && size == -1) ? int(strlen(str)) : size);
+ return fromLocal8Bit(QByteArrayView(str, !str || size < 0 ? qstrlen(str) : size));
}
- static inline QString fromLatin1(const QByteArray &str)
- { return str.isNull() ? QString() : fromLatin1(str.data(), qstrnlen(str.constData(), str.size())); }
- static inline QString fromUtf8(const QByteArray &str)
- { return str.isNull() ? QString() : fromUtf8(str.data(), qstrnlen(str.constData(), str.size())); }
- static inline QString fromLocal8Bit(const QByteArray &str)
- { return str.isNull() ? QString() : fromLocal8Bit(str.data(), qstrnlen(str.constData(), str.size())); }
- static QString fromUtf16(const char16_t *, int size = -1);
- static QString fromUcs4(const char32_t *, int size = -1);
- static QString fromRawData(const QChar *, int size);
+ static QString fromUtf16(const char16_t *, qsizetype size = -1);
+ static QString fromUcs4(const char32_t *, qsizetype size = -1);
+ static QString fromRawData(const QChar *, qsizetype size);
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_X_6_0("Use char16_t* overload.")
- static QString fromUtf16(const ushort *str, int size = -1)
+ static QString fromUtf16(const ushort *str, qsizetype size = -1)
{ return fromUtf16(reinterpret_cast<const char16_t *>(str), size); }
QT_DEPRECATED_VERSION_X_6_0("Use char32_t* overload.")
- static QString fromUcs4(const uint *str, int size = -1)
+ static QString fromUcs4(const uint *str, qsizetype size = -1)
{ return fromUcs4(reinterpret_cast<const char32_t *>(str), size); }
#endif
- inline int toWCharArray(wchar_t *array) const;
- Q_REQUIRED_RESULT static inline QString fromWCharArray(const wchar_t *string, int size = -1);
+ inline qsizetype toWCharArray(wchar_t *array) const;
+ [[nodiscard]] static inline QString fromWCharArray(const wchar_t *string, qsizetype size = -1);
- QString &setRawData(const QChar *unicode, int size);
- QString &setUnicode(const QChar *unicode, int size);
- inline QString &setUtf16(const ushort *utf16, int size);
+ QString &setRawData(const QChar *unicode, qsizetype size);
+ QString &setUnicode(const QChar *unicode, qsizetype size);
+ inline QString &setUtf16(const ushort *utf16, qsizetype size); // ### Qt 7 char16_t
-#if QT_STRINGVIEW_LEVEL < 2
int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
-#endif
- int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
int compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return compare(QStringView{&ch, 1}, cs); }
@@ -703,10 +706,10 @@ public:
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
{ return s1.compare(s2, cs); }
- static inline int compare(const QString &s1, QLatin1String s2,
+ static inline int compare(const QString &s1, QLatin1StringView s2,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
{ return s1.compare(s2, cs); }
- static inline int compare(QLatin1String s1, const QString &s2,
+ static inline int compare(QLatin1StringView s1, const QString &s2,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
{ return -s2.compare(s1, cs); }
static int compare(const QString &s1, QStringView s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
@@ -715,34 +718,41 @@ public:
{ return -s2.compare(s1, cs); }
int localeAwareCompare(const QString& s) const;
- int localeAwareCompare(QStringView s) const;
+ inline int localeAwareCompare(QStringView s) const;
static int localeAwareCompare(const QString& s1, const QString& s2)
{ return s1.localeAwareCompare(s2); }
- static int localeAwareCompare(QStringView s1, QStringView s2);
-
- // ### Qt6: make inline except for the long long versions
- short toShort(bool *ok=nullptr, int base=10) const;
- ushort toUShort(bool *ok=nullptr, int base=10) const;
- int toInt(bool *ok=nullptr, int base=10) const;
- uint toUInt(bool *ok=nullptr, int base=10) const;
- long toLong(bool *ok=nullptr, int base=10) const;
- ulong toULong(bool *ok=nullptr, int base=10) const;
+ static inline int localeAwareCompare(QStringView s1, QStringView s2);
+
+ short toShort(bool *ok=nullptr, int base=10) const
+ { return toIntegral_helper<short>(*this, ok, base); }
+ ushort toUShort(bool *ok=nullptr, int base=10) const
+ { return toIntegral_helper<ushort>(*this, ok, base); }
+ int toInt(bool *ok=nullptr, int base=10) const
+ { return toIntegral_helper<int>(*this, ok, base); }
+ uint toUInt(bool *ok=nullptr, int base=10) const
+ { return toIntegral_helper<uint>(*this, ok, base); }
+ long toLong(bool *ok=nullptr, int base=10) const
+ { return toIntegral_helper<long>(*this, ok, base); }
+ ulong toULong(bool *ok=nullptr, int base=10) const
+ { return toIntegral_helper<ulong>(*this, ok, base); }
+ QT_CORE_INLINE_SINCE(6, 5)
qlonglong toLongLong(bool *ok=nullptr, int base=10) const;
+ QT_CORE_INLINE_SINCE(6, 5)
qulonglong toULongLong(bool *ok=nullptr, int base=10) const;
float toFloat(bool *ok=nullptr) const;
double toDouble(bool *ok=nullptr) const;
- QString &setNum(short, int base=10);
- QString &setNum(ushort, int base=10);
- QString &setNum(int, int base=10);
- QString &setNum(uint, int base=10);
- QString &setNum(long, int base=10);
- QString &setNum(ulong, int base=10);
+ inline QString &setNum(short, int base=10);
+ inline QString &setNum(ushort, int base=10);
+ inline QString &setNum(int, int base=10);
+ inline QString &setNum(uint, int base=10);
+ inline QString &setNum(long, int base=10);
+ inline QString &setNum(ulong, int base=10);
QString &setNum(qlonglong, int base=10);
QString &setNum(qulonglong, int base=10);
- QString &setNum(float, char f='g', int prec=6);
- QString &setNum(double, char f='g', int prec=6);
+ inline QString &setNum(float, char format='g', int precision=6);
+ QString &setNum(double, char format='g', int precision=6);
static QString number(int, int base=10);
static QString number(uint, int base=10);
@@ -750,94 +760,170 @@ public:
static QString number(ulong, int base=10);
static QString number(qlonglong, int base=10);
static QString number(qulonglong, int base=10);
- static QString number(double, char f='g', int prec=6);
-
- friend Q_CORE_EXPORT bool operator==(const QString &s1, const QString &s2) noexcept;
- friend Q_CORE_EXPORT bool operator<(const QString &s1, const QString &s2) noexcept;
- friend inline bool operator>(const QString &s1, const QString &s2) noexcept { return s2 < s1; }
- friend inline bool operator!=(const QString &s1, const QString &s2) noexcept { return !(s1 == s2); }
- friend inline bool operator<=(const QString &s1, const QString &s2) noexcept { return !(s1 > s2); }
- friend inline bool operator>=(const QString &s1, const QString &s2) noexcept { return !(s1 < s2); }
-
- bool operator==(QLatin1String s) const noexcept;
- bool operator<(QLatin1String s) const noexcept;
- bool operator>(QLatin1String s) const noexcept;
- inline bool operator!=(QLatin1String s) const noexcept { return !operator==(s); }
- inline bool operator<=(QLatin1String s) const noexcept { return !operator>(s); }
- inline bool operator>=(QLatin1String s) const noexcept { return !operator<(s); }
+ static QString number(double, char format='g', int precision=6);
+
+ friend bool comparesEqual(const QString &s1, const QString &s2) noexcept
+ { return comparesEqual(QStringView(s1), QStringView(s2)); }
+ friend Qt::strong_ordering compareThreeWay(const QString &s1, const QString &s2) noexcept
+ { return compareThreeWay(QStringView(s1), QStringView(s2)); }
+ Q_DECLARE_STRONGLY_ORDERED(QString)
+
+ Q_WEAK_OVERLOAD
+ friend bool comparesEqual(const QString &s1, QUtf8StringView s2) noexcept
+ { return QtPrivate::equalStrings(s1, s2); }
+ Q_WEAK_OVERLOAD
+ friend Qt::strong_ordering compareThreeWay(const QString &s1, QUtf8StringView s2) noexcept
+ {
+ const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QString, QUtf8StringView, Q_WEAK_OVERLOAD)
+
+#ifdef __cpp_char8_t
+ friend bool comparesEqual(const QString &s1, const char8_t *s2) noexcept
+ { return comparesEqual(s1, QUtf8StringView(s2)); }
+ friend Qt::strong_ordering compareThreeWay(const QString &s1, const char8_t *s2) noexcept
+ { return compareThreeWay(s1, QUtf8StringView(s2)); }
+ Q_DECLARE_STRONGLY_ORDERED(QString, const char8_t *)
+#endif // __cpp_char8_t
+
+ friend bool comparesEqual(const QString &s1, QLatin1StringView s2) noexcept
+ { return (s1.size() == s2.size()) && QtPrivate::equalStrings(s1, s2); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QString &s1, QLatin1StringView s2) noexcept
+ {
+ const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QString, QLatin1StringView)
+
+ // Check isEmpty() instead of isNull() for backwards compatibility.
+ friend bool comparesEqual(const QString &s1, std::nullptr_t) noexcept
+ { return s1.isEmpty(); }
+ friend Qt::strong_ordering compareThreeWay(const QString &s1, std::nullptr_t) noexcept
+ { return s1.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; }
+ Q_DECLARE_STRONGLY_ORDERED(QString, std::nullptr_t)
+
+ friend bool comparesEqual(const QString &s1, const char16_t *s2) noexcept
+ { return comparesEqual(s1, QStringView(s2)); }
+ friend Qt::strong_ordering compareThreeWay(const QString &s1, const char16_t *s2) noexcept
+ { return compareThreeWay(s1, QStringView(s2)); }
+ Q_DECLARE_STRONGLY_ORDERED(QString, const char16_t *)
+
+ // QChar <> QString
+ friend bool comparesEqual(const QString &lhs, QChar rhs) noexcept
+ { return lhs.size() == 1 && rhs == lhs.front(); }
+ friend Qt::strong_ordering compareThreeWay(const QString &lhs, QChar rhs) noexcept
+ {
+ const int res = compare_helper(lhs.data(), lhs.size(), &rhs, 1);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QString, QChar)
// ASCII compatibility
#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
- template <int N>
+ template <qsizetype N>
inline QString(const char (&ch)[N])
: QString(fromUtf8(ch))
{}
- template <int N>
+ template <qsizetype N>
QString(char (&)[N]) = delete;
- template <int N>
+ template <qsizetype N>
inline QString &operator=(const char (&ch)[N])
{ return (*this = fromUtf8(ch, N - 1)); }
- template <int N>
+ template <qsizetype N>
QString &operator=(char (&)[N]) = delete;
#endif
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
- inline QT_ASCII_CAST_WARN QString(const char *ch)
+ QT_ASCII_CAST_WARN inline QString(const char *ch)
: QString(fromUtf8(ch))
{}
- inline QT_ASCII_CAST_WARN QString(const QByteArray &a)
+ QT_ASCII_CAST_WARN inline QString(const QByteArray &a)
: QString(fromUtf8(a))
{}
- inline QT_ASCII_CAST_WARN QString &operator=(const char *ch)
- { return (*this = fromUtf8(ch)); }
- inline QT_ASCII_CAST_WARN QString &operator=(const QByteArray &a)
- { return (*this = fromUtf8(a)); }
-
+ QT_ASCII_CAST_WARN inline QString &operator=(const char *ch)
+ {
+ if (!ch) {
+ clear();
+ return *this;
+ }
+ return assign(ch);
+ }
+ QT_ASCII_CAST_WARN inline QString &operator=(const QByteArray &a)
+ {
+ if (a.isNull()) {
+ clear();
+ return *this;
+ }
+ return assign(a);
+ }
// these are needed, so it compiles with STL support enabled
- inline QT_ASCII_CAST_WARN QString &prepend(const char *s)
- { return prepend(QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &prepend(const QByteArray &s)
- { return prepend(QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &append(const char *s)
- { return append(QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &append(const QByteArray &s)
- { return append(QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &insert(int i, const char *s)
- { return insert(i, QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &insert(int i, const QByteArray &s)
- { return insert(i, QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &operator+=(const char *s)
- { return append(QString::fromUtf8(s)); }
- inline QT_ASCII_CAST_WARN QString &operator+=(const QByteArray &s)
- { return append(QString::fromUtf8(s)); }
-
- inline QT_ASCII_CAST_WARN bool operator==(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator<(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator<=(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator>(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const;
-
- inline QT_ASCII_CAST_WARN bool operator==(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator!=(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator<(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator>(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator<=(const QByteArray &s) const;
- inline QT_ASCII_CAST_WARN bool operator>=(const QByteArray &s) const;
-
- friend inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QString &s2);
- friend inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QString &s2);
- friend inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QString &s2);
- friend inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QString &s2);
- friend inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QString &s2);
- friend inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QString &s2);
-
- friend inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QStringRef &s2);
- friend inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QStringRef &s2);
- friend inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QStringRef &s2);
- friend inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QStringRef &s2);
- friend inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QStringRef &s2);
- friend inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QStringRef &s2);
-#endif
+ QT_ASCII_CAST_WARN inline QString &prepend(const char *s)
+ { return prepend(QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &prepend(const QByteArray &s)
+ { return prepend(QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &append(const char *s)
+ { return append(QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &append(const QByteArray &s)
+ { return append(QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &insert(qsizetype i, const char *s)
+ { return insert(i, QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &insert(qsizetype i, const QByteArray &s)
+ { return insert(i, QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &operator+=(const char *s)
+ { return append(QUtf8StringView(s)); }
+ QT_ASCII_CAST_WARN inline QString &operator+=(const QByteArray &s)
+ { return append(QUtf8StringView(s)); }
+
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ QT_ASCII_CAST_WARN inline bool operator==(const char *s) const;
+ QT_ASCII_CAST_WARN inline bool operator!=(const char *s) const;
+ QT_ASCII_CAST_WARN inline bool operator<(const char *s) const;
+ QT_ASCII_CAST_WARN inline bool operator<=(const char *s) const;
+ QT_ASCII_CAST_WARN inline bool operator>(const char *s) const;
+ QT_ASCII_CAST_WARN inline bool operator>=(const char *s) const;
+
+ QT_ASCII_CAST_WARN inline bool operator==(const QByteArray &s) const;
+ QT_ASCII_CAST_WARN inline bool operator!=(const QByteArray &s) const;
+ QT_ASCII_CAST_WARN inline bool operator<(const QByteArray &s) const;
+ QT_ASCII_CAST_WARN inline bool operator>(const QByteArray &s) const;
+ QT_ASCII_CAST_WARN inline bool operator<=(const QByteArray &s) const;
+ QT_ASCII_CAST_WARN inline bool operator>=(const QByteArray &s) const;
+#else
+ friend bool comparesEqual(const QString &lhs, QByteArrayView rhs) noexcept
+ {
+ return QString::compare_helper(lhs.constData(), lhs.size(),
+ rhs.constData(), rhs.size()) == 0;
+ }
+ friend Qt::strong_ordering
+ compareThreeWay(const QString &lhs, QByteArrayView rhs) noexcept
+ {
+ const int res = QString::compare_helper(lhs.constData(), lhs.size(),
+ rhs.constData(), rhs.size());
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QString, QByteArrayView, QT_ASCII_CAST_WARN)
+
+ friend bool comparesEqual(const QString &lhs, const QByteArray &rhs) noexcept
+ { return comparesEqual(lhs, QByteArrayView(rhs)); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QString &lhs, const QByteArray &rhs) noexcept
+ {
+ return compareThreeWay(lhs, QByteArrayView(rhs));
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QString, QByteArray, QT_ASCII_CAST_WARN)
+
+ friend bool comparesEqual(const QString &lhs, const char *rhs) noexcept
+ { return comparesEqual(lhs, QByteArrayView(rhs)); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QString &lhs, const char *rhs) noexcept
+ {
+ return compareThreeWay(lhs, QByteArrayView(rhs));
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QString, const char *, QT_ASCII_CAST_WARN)
+#endif // QT_CORE_REMOVED_SINCE(6, 8)
+
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
typedef QChar *iterator;
typedef const QChar *const_iterator;
@@ -861,7 +947,7 @@ public:
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
// STL compatibility
- typedef int size_type;
+ typedef qsizetype size_type;
typedef qptrdiff difference_type;
typedef const QChar & const_reference;
typedef QChar & reference;
@@ -873,18 +959,25 @@ public:
inline void push_front(QChar c) { prepend(c); }
inline void push_front(const QString &s) { prepend(s); }
void shrink_to_fit() { squeeze(); }
+ iterator erase(const_iterator first, const_iterator last);
+ inline iterator erase(const_iterator it) { return erase(it, it + 1); }
+ static constexpr qsizetype max_size() noexcept
+ {
+ // -1 to deal with the NUL terminator
+ return Data::max_size() - 1;
+ }
static inline QString fromStdString(const std::string &s);
inline std::string toStdString() const;
static inline QString fromStdWString(const std::wstring &s);
inline std::wstring toStdWString() const;
-#if defined(Q_STDLIB_UNICODE_STRINGS) || defined(Q_QDOC)
static inline QString fromStdU16String(const std::u16string &s);
inline std::u16string toStdU16String() const;
static inline QString fromStdU32String(const std::u32string &s);
inline std::u32string toStdU32String() const;
-#endif
+
+ Q_IMPLICIT inline operator std::u16string_view() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
static QString fromCFString(CFStringRef string);
@@ -893,16 +986,19 @@ public:
NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
- inline bool isNull() const { return d->isNull(); }
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+ static QString fromEcmaString(emscripten::val jsString);
+ emscripten::val toEcmaString() const;
+#endif
+ inline bool isNull() const { return d->isNull(); }
- bool isSimpleText() const;
bool isRightToLeft() const;
- Q_REQUIRED_RESULT bool isValidUtf16() const noexcept
+ [[nodiscard]] bool isValidUtf16() const noexcept
{ return QStringView(*this).isValidUtf16(); }
- QString(int size, Qt::Initialization);
- explicit QString(DataPointer dd) : d(dd) {}
+ QString(qsizetype size, Qt::Initialization);
+ explicit QString(DataPointer &&dd) : d(std::move(dd)) {}
private:
#if defined(QT_NO_CAST_FROM_ASCII)
@@ -915,32 +1011,24 @@ private:
#endif
DataPointer d;
-
- friend inline bool operator==(QChar, const QString &) noexcept;
- friend inline bool operator< (QChar, const QString &) noexcept;
- friend inline bool operator> (QChar, const QString &) noexcept;
- friend inline bool operator==(QChar, const QStringRef &) noexcept;
- friend inline bool operator< (QChar, const QStringRef &) noexcept;
- friend inline bool operator> (QChar, const QStringRef &) noexcept;
- friend inline bool operator==(QChar, QLatin1String) noexcept;
- friend inline bool operator< (QChar, QLatin1String) noexcept;
- friend inline bool operator> (QChar, QLatin1String) noexcept;
-
- void reallocData(uint alloc, bool grow = false);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void expand(int i);
-#endif
- static int compare_helper(const QChar *data1, int length1,
- const QChar *data2, int length2,
+ static const char16_t _empty;
+
+ void reallocData(qsizetype alloc, QArrayData::AllocationOption option);
+ void reallocGrowData(qsizetype n);
+ // ### remove once QAnyStringView supports UTF-32:
+ QString &assign_helper(const char32_t *data, qsizetype len);
+ // Defined in qstringconverter.h
+ template <typename InputIterator>
+ void assign_helper_char8(InputIterator first, InputIterator last);
+ static int compare_helper(const QChar *data1, qsizetype length1,
+ const QChar *data2, qsizetype length2,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
- static int compare_helper(const QChar *data1, int length1,
- const char *data2, int length2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive);
- static int compare_helper(const QChar *data1, int length1,
- QLatin1String s2,
+ static int compare_helper(const QChar *data1, qsizetype length1,
+ const char *data2, qsizetype length2,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
- static int localeAwareCompare_helper(const QChar *data1, int length1,
- const QChar *data2, int length2);
+ static int localeAwareCompare_helper(const QChar *data1, qsizetype length1,
+ const QChar *data2, qsizetype length2);
+ static QString sliced_helper(QString &str, qsizetype pos, qsizetype n);
static QString toLower_helper(const QString &str);
static QString toLower_helper(QString &str);
static QString toUpper_helper(const QString &str);
@@ -951,22 +1039,30 @@ private:
static QString trimmed_helper(QString &str);
static QString simplified_helper(const QString &str);
static QString simplified_helper(QString &str);
- static DataPointer fromLatin1_helper(const char *str, int size = -1);
- static QString fromUtf8_helper(const char *str, int size);
- static QString fromLocal8Bit_helper(const char *, int size);
static QByteArray toLatin1_helper(const QString &);
static QByteArray toLatin1_helper_inplace(QString &);
static QByteArray toUtf8_helper(const QString &);
- static QByteArray toLocal8Bit_helper(const QChar *data, int size);
- static int toUcs4_helper(const ushort *uc, int length, uint *out);
+ static QByteArray toLocal8Bit_helper(const QChar *data, qsizetype size);
+#if QT_CORE_REMOVED_SINCE(6, 6)
+ static qsizetype toUcs4_helper(const ushort *uc, qsizetype length, uint *out);
+#endif
+ static qsizetype toUcs4_helper(const char16_t *uc, qsizetype length, char32_t *out);
static qlonglong toIntegral_helper(QStringView string, bool *ok, int base);
static qulonglong toIntegral_helper(QStringView string, bool *ok, uint base);
- void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen);
- friend class QStringRef;
+ template <typename Predicate>
+ qsizetype removeIf_helper(Predicate pred)
+ {
+ const qsizetype result = d->eraseIf(pred);
+ if (result > 0)
+ d.data()[d.size] = u'\0';
+ return result;
+ }
+
friend class QStringView;
friend class QByteArray;
- friend class QCollator;
friend struct QAbstractConcatenable;
+ template <typename T> friend qsizetype erase(QString &s, const T &t);
+ template <typename Predicate> friend qsizetype erase_if(QString &s, Predicate pred);
template <typename T> static
T toIntegral_helper(QStringView string, bool *ok, int base)
@@ -984,21 +1080,46 @@ private:
return T(val);
}
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= d.size);
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= d.size - pos);
+ }
+
public:
inline DataPointer &data_ptr() { return d; }
+ inline const DataPointer &data_ptr() const { return d; }
};
//
-// QLatin1String inline members that require QString:
+// QLatin1StringView inline members that require QUtf8StringView:
//
-QString QLatin1String::toString() const { return *this; }
+int QLatin1StringView::compare(QUtf8StringView other, Qt::CaseSensitivity cs) const noexcept
+{ return QtPrivate::compareStrings(*this, other, cs); }
+
+//
+// QLatin1StringView inline members that require QString:
+//
+
+QString QLatin1StringView::toString() const { return *this; }
+
+//
+// QStringView inline members that require QUtf8StringView:
+//
+
+int QStringView::compare(QUtf8StringView other, Qt::CaseSensitivity cs) const noexcept
+{ return QtPrivate::compareStrings(*this, other, cs); }
//
// QStringView inline members that require QString:
//
+
QString QStringView::toString() const
-{ return Q_ASSERT(size() == length()), QString(data(), length()); }
+{ return QString(*this); }
qint64 QStringView::toLongLong(bool *ok, int base) const
{ return QString::toIntegral_helper<qint64>(*this, ok, base); }
@@ -1018,324 +1139,349 @@ ushort QStringView::toUShort(bool *ok, int base) const
{ return QString::toIntegral_helper<ushort>(*this, ok, base); }
//
+// QUtf8StringView inline members that require QStringView:
+//
+
+template <bool UseChar8T>
+int QBasicUtf8StringView<UseChar8T>::compare(QChar other, Qt::CaseSensitivity cs) const noexcept
+{
+ return QtPrivate::compareStrings(*this, QStringView(&other, 1), cs);
+}
+
+template <bool UseChar8T>
+int QBasicUtf8StringView<UseChar8T>::compare(QStringView other, Qt::CaseSensitivity cs) const noexcept
+{
+ return QtPrivate::compareStrings(*this, other, cs);
+}
+
+template <bool UseChar8T>
+[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QChar other) const noexcept
+{
+ return QtPrivate::equalStrings(*this, QStringView(&other, 1));
+}
+
+template <bool UseChar8T>
+[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QStringView other) const noexcept
+{
+ return QtPrivate::equalStrings(*this, other);
+}
+
+//
+// QUtf8StringView inline members that require QString, QL1SV or QBA:
+//
+
+template <bool UseChar8T>
+QString QBasicUtf8StringView<UseChar8T>::toString() const
+{
+ return QString::fromUtf8(data(), size());
+}
+
+template<bool UseChar8T>
+[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(QLatin1StringView other,
+ Qt::CaseSensitivity cs) const noexcept
+{
+ return QtPrivate::compareStrings(*this, other, cs);
+}
+
+template<bool UseChar8T>
+[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(const QByteArray &other,
+ Qt::CaseSensitivity cs) const noexcept
+{
+ return QtPrivate::compareStrings(*this,
+ QBasicUtf8StringView<UseChar8T>(other.data(), other.size()),
+ cs);
+}
+
+template <bool UseChar8T>
+[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QLatin1StringView other) const noexcept
+{
+ return QtPrivate::equalStrings(*this, other);
+}
+
+template <bool UseChar8T>
+[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(const QByteArray &other) const noexcept
+{
+ return size() == other.size()
+ && QtPrivate::equalStrings(*this, QBasicUtf8StringView<UseChar8T>(other.data(),
+ other.size()));
+}
+
+//
+// QAnyStringView inline members that require QString:
+//
+
+QAnyStringView::QAnyStringView(const QByteArray &str) noexcept
+ : QAnyStringView{str.isNull() ? nullptr : str.data(), str.size()} {}
+QAnyStringView::QAnyStringView(const QString &str) noexcept
+ : QAnyStringView{str.isNull() ? nullptr : str.data(), str.size()} {}
+
+QString QAnyStringView::toString() const
+{ return QtPrivate::convertToQString(*this); }
+
+//
// QString inline members
//
-inline QString::QString(QLatin1String aLatin1) : d(fromLatin1_helper(aLatin1.latin1(), aLatin1.size()))
-{ }
-inline int QString::length() const
-{ return int(d.size); }
-inline const QChar QString::at(int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return QChar(d.data()[i]); }
-inline const QChar QString::operator[](int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return QChar(d.data()[i]); }
-inline bool QString::isEmpty() const
-{ return d.size == 0; }
-inline const QChar *QString::unicode() const
-{ return reinterpret_cast<const QChar*>(d.data()); }
-inline const QChar *QString::data() const
-{ return reinterpret_cast<const QChar*>(d.data()); }
-inline QChar *QString::data()
-{ detach(); return reinterpret_cast<QChar*>(d.data()); }
-inline const QChar *QString::constData() const
-{ return reinterpret_cast<const QChar*>(d.data()); }
-inline void QString::detach()
-{ if (d->needsDetach()) reallocData(d.size + 1u); }
-inline bool QString::isDetached() const
+QString::QString(QLatin1StringView latin1)
+{ *this = QString::fromLatin1(latin1.data(), latin1.size()); }
+const QChar QString::at(qsizetype i) const
+{ verify(i, 1); return QChar(d.data()[i]); }
+const QChar QString::operator[](qsizetype i) const
+{ verify(i, 1); return QChar(d.data()[i]); }
+const QChar *QString::unicode() const
+{ return data(); }
+const QChar *QString::data() const
+{
+#if QT5_NULL_STRINGS == 1
+ return reinterpret_cast<const QChar *>(d.data() ? d.data() : &_empty);
+#else
+ return reinterpret_cast<const QChar *>(d.data());
+#endif
+}
+QChar *QString::data()
+{
+ detach();
+ Q_ASSERT(d.data());
+ return reinterpret_cast<QChar *>(d.data());
+}
+const QChar *QString::constData() const
+{ return data(); }
+void QString::detach()
+{ if (d->needsDetach()) reallocData(d.size, QArrayData::KeepSize); }
+bool QString::isDetached() const
{ return !d->isShared(); }
-inline void QString::clear()
+void QString::clear()
{ if (!isNull()) *this = QString(); }
-inline QString::QString(const QString &other) noexcept : d(other.d)
+QString::QString(const QString &other) noexcept : d(other.d)
{ }
-inline int QString::capacity() const
-{ const auto realCapacity = d->constAllocatedCapacity(); return realCapacity ? int(realCapacity) - 1 : 0; }
-inline QString &QString::setNum(short n, int base)
+qsizetype QString::capacity() const { return qsizetype(d->constAllocatedCapacity()); }
+QString &QString::setNum(short n, int base)
{ return setNum(qlonglong(n), base); }
-inline QString &QString::setNum(ushort n, int base)
+QString &QString::setNum(ushort n, int base)
{ return setNum(qulonglong(n), base); }
-inline QString &QString::setNum(int n, int base)
+QString &QString::setNum(int n, int base)
{ return setNum(qlonglong(n), base); }
-inline QString &QString::setNum(uint n, int base)
+QString &QString::setNum(uint n, int base)
{ return setNum(qulonglong(n), base); }
-inline QString &QString::setNum(long n, int base)
+QString &QString::setNum(long n, int base)
{ return setNum(qlonglong(n), base); }
-inline QString &QString::setNum(ulong n, int base)
+QString &QString::setNum(ulong n, int base)
{ return setNum(qulonglong(n), base); }
-inline QString &QString::setNum(float n, char f, int prec)
+QString &QString::setNum(float n, char f, int prec)
{ return setNum(double(n),f,prec); }
-inline QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const
+QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
-inline QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const
+QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
-inline QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const
+QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
-inline QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const
+QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
-inline QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) const
+QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
-inline QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
+QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
-inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const
+QString QString::section(QChar asep, qsizetype astart, qsizetype aend, SectionFlags aflags) const
{ return section(QString(asep), astart, aend, aflags); }
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant"
QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable"
-inline int QString::toWCharArray(wchar_t *array) const
+qsizetype QString::toWCharArray(wchar_t *array) const
{
return qToStringViewIgnoringNull(*this).toWCharArray(array);
}
-int QStringView::toWCharArray(wchar_t *array) const
+qsizetype QStringView::toWCharArray(wchar_t *array) const
{
if (sizeof(wchar_t) == sizeof(QChar)) {
if (auto src = data())
memcpy(array, src, sizeof(QChar) * size());
- return int(size()); // ### q6sizetype
+ return size();
} else {
- return QString::toUcs4_helper(reinterpret_cast<const ushort *>(data()), int(size()),
- reinterpret_cast<uint *>(array));
+ return QString::toUcs4_helper(utf16(), size(), reinterpret_cast<char32_t *>(array));
}
}
QT_WARNING_POP
-inline QString QString::fromWCharArray(const wchar_t *string, int size)
+QString QString::fromWCharArray(const wchar_t *string, qsizetype size)
{
- return sizeof(wchar_t) == sizeof(QChar) ? fromUtf16(reinterpret_cast<const char16_t *>(string), size)
- : fromUcs4(reinterpret_cast<const char32_t *>(string), size);
+ if constexpr (sizeof(wchar_t) == sizeof(QChar)) {
+ return QString(reinterpret_cast<const QChar *>(string), size);
+ } else {
+#ifdef QT_BOOTSTRAPPED
+ Q_UNREACHABLE_RETURN(QString());
+#else
+ return fromUcs4(reinterpret_cast<const char32_t *>(string), size);
+#endif
+ }
}
-inline QString::QString() noexcept {}
-inline QString::~QString() {}
+constexpr QString::QString() noexcept {}
+QString::~QString() {}
-inline void QString::reserve(int asize)
+void QString::reserve(qsizetype asize)
{
- if (d->needsDetach() || asize >= capacity())
- reallocData(uint(qMax(asize, size())) + 1u);
-
- // we're not shared anymore, for sure
- d->flags() |= Data::CapacityReserved;
+ if (d->needsDetach() || asize >= capacity() - d.freeSpaceAtBegin())
+ reallocData(qMax(asize, size()), QArrayData::KeepSize);
+ if (d->constAllocatedCapacity())
+ d->setFlag(Data::CapacityReserved);
}
-inline void QString::squeeze()
+void QString::squeeze()
{
- if ((d->flags() & Data::CapacityReserved) == 0)
+ if (!d.isMutable())
return;
- if (d->needsDetach() || int(d.size) < capacity())
- reallocData(uint(d.size) + 1u);
-
- // we're not shared anymore, for sure
- d->flags() &= uint(~Data::CapacityReserved);
+ if (d->needsDetach() || size() < capacity())
+ reallocData(d.size, QArrayData::KeepSize);
+ if (d->constAllocatedCapacity())
+ d->clearFlag(Data::CapacityReserved);
}
-inline QString &QString::setUtf16(const ushort *autf16, int asize)
+QString &QString::setUtf16(const ushort *autf16, qsizetype asize)
{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
-inline QChar &QString::operator[](int i)
-{ Q_ASSERT(i >= 0 && i < size()); return data()[i]; }
-inline QChar &QString::front() { return operator[](0); }
-inline QChar &QString::back() { return operator[](size() - 1); }
-inline QString::iterator QString::begin()
+QChar &QString::operator[](qsizetype i)
+{ verify(i, 1); return data()[i]; }
+QChar &QString::front() { return operator[](0); }
+QChar &QString::back() { return operator[](size() - 1); }
+QString::iterator QString::begin()
{ detach(); return reinterpret_cast<QChar*>(d.data()); }
-inline QString::const_iterator QString::begin() const
+QString::const_iterator QString::begin() const
{ return reinterpret_cast<const QChar*>(d.data()); }
-inline QString::const_iterator QString::cbegin() const
+QString::const_iterator QString::cbegin() const
{ return reinterpret_cast<const QChar*>(d.data()); }
-inline QString::const_iterator QString::constBegin() const
+QString::const_iterator QString::constBegin() const
{ return reinterpret_cast<const QChar*>(d.data()); }
-inline QString::iterator QString::end()
+QString::iterator QString::end()
{ detach(); return reinterpret_cast<QChar*>(d.data() + d.size); }
-inline QString::const_iterator QString::end() const
+QString::const_iterator QString::end() const
{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
-inline QString::const_iterator QString::cend() const
+QString::const_iterator QString::cend() const
{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
-inline QString::const_iterator QString::constEnd() const
+QString::const_iterator QString::constEnd() const
{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
-#if QT_STRINGVIEW_LEVEL < 2
-inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
+bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
-#endif
-inline bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const
+bool QString::contains(QLatin1StringView s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
-inline bool QString::contains(QChar c, Qt::CaseSensitivity cs) const
+bool QString::contains(QChar c, Qt::CaseSensitivity cs) const
{ return indexOf(c, 0, cs) != -1; }
-inline bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
+bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
{ return indexOf(s, 0, cs) != -1; }
-inline bool operator==(QLatin1String s1, QLatin1String s2) noexcept
-{ return s1.size() == s2.size() && (!s1.size() || !memcmp(s1.latin1(), s2.latin1(), s1.size())); }
-inline bool operator!=(QLatin1String s1, QLatin1String s2) noexcept
-{ return !operator==(s1, s2); }
-inline bool operator<(QLatin1String s1, QLatin1String s2) noexcept
-{
- const int len = qMin(s1.size(), s2.size());
- const int r = len ? memcmp(s1.latin1(), s2.latin1(), len) : 0;
- return r < 0 || (r == 0 && s1.size() < s2.size());
-}
-inline bool operator>(QLatin1String s1, QLatin1String s2) noexcept
-{ return operator<(s2, s1); }
-inline bool operator<=(QLatin1String s1, QLatin1String s2) noexcept
-{ return !operator>(s1, s2); }
-inline bool operator>=(QLatin1String s1, QLatin1String s2) noexcept
-{ return !operator<(s1, s2); }
-
-inline bool QLatin1String::operator==(const QString &s) const noexcept
-{ return s == *this; }
-inline bool QLatin1String::operator!=(const QString &s) const noexcept
-{ return s != *this; }
-inline bool QLatin1String::operator>(const QString &s) const noexcept
-{ return s < *this; }
-inline bool QLatin1String::operator<(const QString &s) const noexcept
-{ return s > *this; }
-inline bool QLatin1String::operator>=(const QString &s) const noexcept
-{ return s <= *this; }
-inline bool QLatin1String::operator<=(const QString &s) const noexcept
-{ return s >= *this; }
-
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
-inline bool QString::operator==(const char *s) const
+#if QT_CORE_REMOVED_SINCE(6, 8)
+bool QString::operator==(const char *s) const
{ return QString::compare_helper(constData(), size(), s, -1) == 0; }
-inline bool QString::operator!=(const char *s) const
+bool QString::operator!=(const char *s) const
{ return QString::compare_helper(constData(), size(), s, -1) != 0; }
-inline bool QString::operator<(const char *s) const
+bool QString::operator<(const char *s) const
{ return QString::compare_helper(constData(), size(), s, -1) < 0; }
-inline bool QString::operator>(const char *s) const
+bool QString::operator>(const char *s) const
{ return QString::compare_helper(constData(), size(), s, -1) > 0; }
-inline bool QString::operator<=(const char *s) const
+bool QString::operator<=(const char *s) const
{ return QString::compare_helper(constData(), size(), s, -1) <= 0; }
-inline bool QString::operator>=(const char *s) const
+bool QString::operator>=(const char *s) const
{ return QString::compare_helper(constData(), size(), s, -1) >= 0; }
-inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QString &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) == 0; }
-inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QString &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) != 0; }
-inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QString &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) > 0; }
-inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QString &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) < 0; }
-inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QString &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) >= 0; }
-inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QString &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) <= 0; }
-
-inline QT_ASCII_CAST_WARN bool operator==(const char *s1, QLatin1String s2)
-{ return QString::fromUtf8(s1) == s2; }
-inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, QLatin1String s2)
-{ return QString::fromUtf8(s1) != s2; }
-inline QT_ASCII_CAST_WARN bool operator<(const char *s1, QLatin1String s2)
-{ return (QString::fromUtf8(s1) < s2); }
-inline QT_ASCII_CAST_WARN bool operator>(const char *s1, QLatin1String s2)
-{ return (QString::fromUtf8(s1) > s2); }
-inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, QLatin1String s2)
-{ return (QString::fromUtf8(s1) <= s2); }
-inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, QLatin1String s2)
-{ return (QString::fromUtf8(s1) >= s2); }
-
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator==(const char *s) const
-{ return QString::fromUtf8(s) == *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator!=(const char *s) const
-{ return QString::fromUtf8(s) != *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator<(const char *s) const
-{ return QString::fromUtf8(s) > *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator>(const char *s) const
-{ return QString::fromUtf8(s) < *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator<=(const char *s) const
-{ return QString::fromUtf8(s) >= *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const char *s) const
-{ return QString::fromUtf8(s) <= *this; }
-
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator==(const QByteArray &s) const
-{ return QString::fromUtf8(s) == *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator!=(const QByteArray &s) const
-{ return QString::fromUtf8(s) != *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator<(const QByteArray &s) const
-{ return QString::fromUtf8(s) > *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator>(const QByteArray &s) const
-{ return QString::fromUtf8(s) < *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator<=(const QByteArray &s) const
-{ return QString::fromUtf8(s) >= *this; }
-inline QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const QByteArray &s) const
-{ return QString::fromUtf8(s) <= *this; }
-
-inline QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const
-{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) == 0; }
-inline QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const
-{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) != 0; }
-inline QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const
+QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const
+{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; }
+QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const
+{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; }
+QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const
{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) < 0; }
-inline QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const
+QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const
{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) > 0; }
-inline QT_ASCII_CAST_WARN bool QString::operator<=(const QByteArray &s) const
+QT_ASCII_CAST_WARN bool QString::operator<=(const QByteArray &s) const
{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) <= 0; }
-inline QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const
+QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const
{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) >= 0; }
+bool QByteArray::operator==(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) == 0; }
+bool QByteArray::operator!=(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; }
+bool QByteArray::operator<(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; }
+bool QByteArray::operator>(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; }
+bool QByteArray::operator<=(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; }
+bool QByteArray::operator>=(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; }
+#endif // QT_CORE_REMOVED_SINCE(6, 8)
#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
#if !defined(QT_USE_FAST_OPERATOR_PLUS) && !defined(QT_USE_QSTRINGBUILDER)
-inline const QString operator+(const QString &s1, const QString &s2)
+inline QString operator+(const QString &s1, const QString &s2)
{ QString t(s1); t += s2; return t; }
-inline const QString operator+(const QString &s1, QChar s2)
+inline QString operator+(QString &&lhs, const QString &rhs)
+{ return std::move(lhs += rhs); }
+inline QString operator+(const QString &s1, QChar s2)
{ QString t(s1); t += s2; return t; }
-inline const QString operator+(QChar s1, const QString &s2)
+inline QString operator+(QString &&lhs, QChar rhs)
+{ return std::move(lhs += rhs); }
+inline QString operator+(QChar s1, const QString &s2)
{ QString t(s1); t += s2; return t; }
# if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
-inline QT_ASCII_CAST_WARN const QString operator+(const QString &s1, const char *s2)
-{ QString t(s1); t += QString::fromUtf8(s2); return t; }
-inline QT_ASCII_CAST_WARN const QString operator+(const char *s1, const QString &s2)
+QT_ASCII_CAST_WARN inline QString operator+(const QString &s1, const char *s2)
+{ QString t(s1); t += QUtf8StringView(s2); return t; }
+QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const char *rhs)
+{ QT_IGNORE_DEPRECATIONS(return std::move(lhs += rhs);) }
+QT_ASCII_CAST_WARN inline QString operator+(const char *s1, const QString &s2)
{ QString t = QString::fromUtf8(s1); t += s2; return t; }
-inline QT_ASCII_CAST_WARN const QString operator+(const QByteArray &ba, const QString &s)
+QT_ASCII_CAST_WARN inline QString operator+(const QByteArray &ba, const QString &s)
{ QString t = QString::fromUtf8(ba); t += s; return t; }
-inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteArray &ba)
-{ QString t(s); t += QString::fromUtf8(ba); return t; }
+QT_ASCII_CAST_WARN inline QString operator+(const QString &s, const QByteArray &ba)
+{ QString t(s); t += QUtf8StringView(ba); return t; }
+QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const QByteArray &rhs)
+{ QT_IGNORE_DEPRECATIONS(return std::move(lhs += rhs);) }
# endif // QT_NO_CAST_FROM_ASCII
#endif // QT_USE_QSTRINGBUILDER
-inline std::string QString::toStdString() const
+std::string QString::toStdString() const
{ return toUtf8().toStdString(); }
-inline QString QString::fromStdString(const std::string &s)
-{ return fromUtf8(s.data(), int(s.size())); }
+QString QString::fromStdString(const std::string &s)
+{ return fromUtf8(s.data(), qsizetype(s.size())); }
-inline std::wstring QString::toStdWString() const
+std::wstring QString::toStdWString() const
{
std::wstring str;
- str.resize(length());
-#if __cplusplus >= 201703L
+ str.resize(size());
str.resize(toWCharArray(str.data()));
-#else
- if (length())
- str.resize(toWCharArray(&str.front()));
-#endif
return str;
}
-inline QString QString::fromStdWString(const std::wstring &s)
-{ return fromWCharArray(s.data(), int(s.size())); }
+QString QString::fromStdWString(const std::wstring &s)
+{ return fromWCharArray(s.data(), qsizetype(s.size())); }
-#if defined(Q_STDLIB_UNICODE_STRINGS)
-inline QString QString::fromStdU16String(const std::u16string &s)
-{ return fromUtf16(s.data(), int(s.size())); }
+QString QString::fromStdU16String(const std::u16string &s)
+{ return fromUtf16(s.data(), qsizetype(s.size())); }
-inline std::u16string QString::toStdU16String() const
-{ return std::u16string(reinterpret_cast<const char16_t*>(utf16()), length()); }
+std::u16string QString::toStdU16String() const
+{ return std::u16string(reinterpret_cast<const char16_t*>(data()), size()); }
-inline QString QString::fromStdU32String(const std::u32string &s)
-{ return fromUcs4(s.data(), int(s.size())); }
+QString QString::fromStdU32String(const std::u32string &s)
+{ return fromUcs4(s.data(), qsizetype(s.size())); }
-inline std::u32string QString::toStdU32String() const
+std::u32string QString::toStdU32String() const
{
- std::u32string u32str(length(), char32_t(0));
- int len = toUcs4_helper(reinterpret_cast<const ushort *>(constData()), length(),
- reinterpret_cast<uint*>(&u32str[0]));
+ std::u32string u32str(size(), char32_t(0));
+ const qsizetype len = toUcs4_helper(reinterpret_cast<const char16_t *>(data()),
+ size(), u32str.data());
u32str.resize(len);
return u32str;
}
-#endif
-#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
+QString::operator std::u16string_view() const noexcept
+{
+ return std::u16string_view(d.data(), size_t(d.size));
+}
+
+#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QString &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &);
#endif
@@ -1343,454 +1489,60 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &);
Q_DECLARE_SHARED(QString)
Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags)
+int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept
+{ return -s.compare(*this, cs); }
-class Q_CORE_EXPORT QStringRef {
- const QString *m_string;
- int m_position;
- int m_size;
-public:
- typedef QString::size_type size_type;
- typedef QString::value_type value_type;
- typedef const QChar *const_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef QString::const_pointer const_pointer;
- typedef QString::const_reference const_reference;
-
- // ### Qt 6: make this constructor constexpr, after the destructor is made trivial
- inline QStringRef() : m_string(nullptr), m_position(0), m_size(0) {}
- inline QStringRef(const QString *string, int position, int size);
- inline QStringRef(const QString *string);
-
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- // ### Qt 6: remove all of these, the implicit ones are fine
- QStringRef(const QStringRef &other) noexcept
- :m_string(other.m_string), m_position(other.m_position), m_size(other.m_size)
- {}
- QStringRef(QStringRef &&other) noexcept : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
- QStringRef &operator=(QStringRef &&other) noexcept { return *this = other; }
- QStringRef &operator=(const QStringRef &other) noexcept
- {
- m_string = other.m_string; m_position = other.m_position;
- m_size = other.m_size; return *this;
- }
- inline ~QStringRef(){}
-#endif // Qt < 6.0.0
-
- inline const QString *string() const { return m_string; }
- inline int position() const { return m_position; }
- inline int size() const { return m_size; }
- inline int count() const { return m_size; }
- inline int length() const { return m_size; }
-
-#if QT_STRINGVIEW_LEVEL < 2
- int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsizetype
- int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
- int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsizetype
-
-#if QT_STRINGVIEW_LEVEL < 2
- inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- inline bool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
-
- int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-
- Q_REQUIRED_RESULT
- QList<QStringRef> split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- Q_REQUIRED_RESULT
- QList<QStringRef> split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-
- Q_REQUIRED_RESULT QStringRef left(int n) const;
- Q_REQUIRED_RESULT QStringRef right(int n) const;
- Q_REQUIRED_RESULT QStringRef mid(int pos, int n = -1) const;
- Q_REQUIRED_RESULT QStringRef chopped(int n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return left(size() - n); }
-
- void truncate(int pos) noexcept { m_size = qBound(0, pos, m_size); }
- void chop(int n) noexcept
- {
- if (n >= m_size)
- m_size = 0;
- else if (n > 0)
- m_size -= n;
- }
+int QString::localeAwareCompare(QStringView s) const
+{ return localeAwareCompare_helper(constData(), size(), s.constData(), s.size()); }
+int QString::localeAwareCompare(QStringView s1, QStringView s2)
+{ return localeAwareCompare_helper(s1.constData(), s1.size(), s2.constData(), s2.size()); }
+int QStringView::localeAwareCompare(QStringView other) const
+{ return QString::localeAwareCompare(*this, other); }
- bool isRightToLeft() const;
+#if QT_CORE_INLINE_IMPL_SINCE(6, 5)
+qint64 QString::toLongLong(bool *ok, int base) const
+{
+ return toIntegral_helper<qlonglong>(*this, ok, base);
+}
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::startsWith(*this, s, cs); }
- bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
- bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+quint64 QString::toULongLong(bool *ok, int base) const
+{
+ return toIntegral_helper<qulonglong>(*this, ok, base);
+}
#endif
-
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::endsWith(*this, s, cs); }
- bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#if QT_STRINGVIEW_LEVEL < 2
- bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- bool endsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_CORE_INLINE_IMPL_SINCE(6, 7)
+qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
+{
+ return qToStringViewIgnoringNull(*this).indexOf(ch, from, cs);
+}
+qsizetype QString::lastIndexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
+{
+ return qToStringViewIgnoringNull(*this).lastIndexOf(ch, from, cs);
+}
#endif
- inline QStringRef &operator=(const QString *string);
-
- inline const QChar *unicode() const
- {
- if (!m_string)
- return reinterpret_cast<const QChar *>(QString::Data::sharedNullData());
- return m_string->unicode() + m_position;
- }
- inline const QChar *data() const { return unicode(); }
- inline const QChar *constData() const { return unicode(); }
-
- inline const_iterator begin() const { return unicode(); }
- inline const_iterator cbegin() const { return unicode(); }
- inline const_iterator constBegin() const { return unicode(); }
- inline const_iterator end() const { return unicode() + size(); }
- inline const_iterator cend() const { return unicode() + size(); }
- inline const_iterator constEnd() const { return unicode() + size(); }
- inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
- inline const_reverse_iterator crbegin() const { return rbegin(); }
- inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
- inline const_reverse_iterator crend() const { return rend(); }
-
- Q_REQUIRED_RESULT QByteArray toLatin1() const;
- Q_REQUIRED_RESULT QByteArray toUtf8() const;
- Q_REQUIRED_RESULT QByteArray toLocal8Bit() const;
- Q_REQUIRED_RESULT QList<uint> toUcs4() const;
-
- inline void clear() { m_string = nullptr; m_position = m_size = 0; }
- QString toString() const;
- inline bool isEmpty() const { return m_size == 0; }
- inline bool isNull() const { return m_string == nullptr || m_string->isNull(); }
-
- QStringRef appendTo(QString *string) const;
-
- inline const QChar at(int i) const
- { Q_ASSERT(uint(i) < uint(size())); return m_string->at(i + m_position); }
- QChar operator[](int i) const { return at(i); }
- Q_REQUIRED_RESULT QChar front() const { return at(0); }
- Q_REQUIRED_RESULT QChar back() const { return at(size() - 1); }
+namespace QtPrivate {
+// used by qPrintable() and qUtf8Printable() macros
+inline const QString &asString(const QString &s) { return s; }
+inline QString &&asString(QString &&s) { return std::move(s); }
+}
-#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
- // ASCII compatibility
- inline QT_ASCII_CAST_WARN bool operator==(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator<(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator<=(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator>(const char *s) const;
- inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const;
+#ifndef qPrintable
+# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData()
#endif
- int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- int compare(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
- int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
-#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
- int compare(const QByteArray &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- { return QString::compare_helper(unicode(), size(), s.data(), qstrnlen(s.data(), s.size()), cs); }
+#ifndef qUtf8Printable
+# define qUtf8Printable(string) QtPrivate::asString(string).toUtf8().constData()
#endif
- static int compare(const QStringRef &s1, const QString &s2,
- Qt::CaseSensitivity = Qt::CaseSensitive) noexcept;
- static int compare(const QStringRef &s1, const QStringRef &s2,
- Qt::CaseSensitivity = Qt::CaseSensitive) noexcept;
- static int compare(const QStringRef &s1, QLatin1String s2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-
- int localeAwareCompare(const QString &s) const;
- int localeAwareCompare(const QStringRef &s) const;
- static int localeAwareCompare(const QStringRef &s1, const QString &s2);
- static int localeAwareCompare(const QStringRef &s1, const QStringRef &s2);
-
- Q_REQUIRED_RESULT QStringRef trimmed() const;
- short toShort(bool *ok = nullptr, int base = 10) const;
- ushort toUShort(bool *ok = nullptr, int base = 10) const;
- int toInt(bool *ok = nullptr, int base = 10) const;
- uint toUInt(bool *ok = nullptr, int base = 10) const;
- long toLong(bool *ok = nullptr, int base = 10) const;
- ulong toULong(bool *ok = nullptr, int base = 10) const;
- qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
- qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
- float toFloat(bool *ok = nullptr) const;
- double toDouble(bool *ok = nullptr) const;
-};
-Q_DECLARE_TYPEINFO(QStringRef, Q_PRIMITIVE_TYPE);
-
-inline QStringRef &QStringRef::operator=(const QString *aString)
-{ m_string = aString; m_position = 0; m_size = aString?aString->size():0; return *this; }
-
-inline QStringRef::QStringRef(const QString *aString, int aPosition, int aSize)
- :m_string(aString), m_position(aPosition), m_size(aSize){}
-
-inline QStringRef::QStringRef(const QString *aString)
- :m_string(aString), m_position(0), m_size(aString?aString->size() : 0){}
-
-// QStringRef <> QStringRef
-Q_CORE_EXPORT bool operator==(const QStringRef &s1, const QStringRef &s2) noexcept;
-inline bool operator!=(const QStringRef &s1, const QStringRef &s2) noexcept
-{ return !(s1 == s2); }
-Q_CORE_EXPORT bool operator<(const QStringRef &s1, const QStringRef &s2) noexcept;
-inline bool operator>(const QStringRef &s1, const QStringRef &s2) noexcept
-{ return s2 < s1; }
-inline bool operator<=(const QStringRef &s1, const QStringRef &s2) noexcept
-{ return !(s1 > s2); }
-inline bool operator>=(const QStringRef &s1, const QStringRef &s2) noexcept
-{ return !(s1 < s2); }
-
-// QString <> QStringRef
-Q_CORE_EXPORT bool operator==(const QString &lhs, const QStringRef &rhs) noexcept;
-inline bool operator!=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) != 0; }
-inline bool operator< (const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) < 0; }
-inline bool operator> (const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) > 0; }
-inline bool operator<=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) <= 0; }
-inline bool operator>=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) >= 0; }
-
-inline bool operator==(const QStringRef &lhs, const QString &rhs) noexcept { return rhs == lhs; }
-inline bool operator!=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs != lhs; }
-inline bool operator< (const QStringRef &lhs, const QString &rhs) noexcept { return rhs > lhs; }
-inline bool operator> (const QStringRef &lhs, const QString &rhs) noexcept { return rhs < lhs; }
-inline bool operator<=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs >= lhs; }
-inline bool operator>=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs <= lhs; }
-
-inline int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept
-{ return -s.compare(*this, cs); }
-inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const noexcept
-{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
-inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const noexcept
-{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
-inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
-{ return QString::compare_helper(constData(), length(), s, cs); }
-inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs) noexcept
-{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
-inline int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs) noexcept
-{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
-inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) noexcept
-{ return QString::compare_helper(s1.constData(), s1.length(), s2, cs); }
-
-// QLatin1String <> QStringRef
-Q_CORE_EXPORT bool operator==(QLatin1String lhs, const QStringRef &rhs) noexcept;
-inline bool operator!=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) != 0; }
-inline bool operator< (QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) > 0; }
-inline bool operator> (QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) < 0; }
-inline bool operator<=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) >= 0; }
-inline bool operator>=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) <= 0; }
-
-inline bool operator==(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs == lhs; }
-inline bool operator!=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs != lhs; }
-inline bool operator< (const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs > lhs; }
-inline bool operator> (const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs < lhs; }
-inline bool operator<=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs >= lhs; }
-inline bool operator>=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs <= lhs; }
-
-// QChar <> QString
-inline bool operator==(QChar lhs, const QString &rhs) noexcept
-{ return rhs.size() == 1 && lhs == rhs.front(); }
-inline bool operator< (QChar lhs, const QString &rhs) noexcept
-{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; }
-inline bool operator> (QChar lhs, const QString &rhs) noexcept
-{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) > 0; }
-
-inline bool operator!=(QChar lhs, const QString &rhs) noexcept { return !(lhs == rhs); }
-inline bool operator<=(QChar lhs, const QString &rhs) noexcept { return !(lhs > rhs); }
-inline bool operator>=(QChar lhs, const QString &rhs) noexcept { return !(lhs < rhs); }
-
-inline bool operator==(const QString &lhs, QChar rhs) noexcept { return rhs == lhs; }
-inline bool operator!=(const QString &lhs, QChar rhs) noexcept { return !(rhs == lhs); }
-inline bool operator< (const QString &lhs, QChar rhs) noexcept { return rhs > lhs; }
-inline bool operator> (const QString &lhs, QChar rhs) noexcept { return rhs < lhs; }
-inline bool operator<=(const QString &lhs, QChar rhs) noexcept { return !(rhs < lhs); }
-inline bool operator>=(const QString &lhs, QChar rhs) noexcept { return !(rhs > lhs); }
-
-// QChar <> QStringRef
-inline bool operator==(QChar lhs, const QStringRef &rhs) noexcept
-{ return rhs.size() == 1 && lhs == rhs.front(); }
-inline bool operator< (QChar lhs, const QStringRef &rhs) noexcept
-{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; }
-inline bool operator> (QChar lhs, const QStringRef &rhs) noexcept
-{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) > 0; }
-
-inline bool operator!=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs == rhs); }
-inline bool operator<=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs > rhs); }
-inline bool operator>=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs < rhs); }
-
-inline bool operator==(const QStringRef &lhs, QChar rhs) noexcept { return rhs == lhs; }
-inline bool operator!=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs == lhs); }
-inline bool operator< (const QStringRef &lhs, QChar rhs) noexcept { return rhs > lhs; }
-inline bool operator> (const QStringRef &lhs, QChar rhs) noexcept { return rhs < lhs; }
-inline bool operator<=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs < lhs); }
-inline bool operator>=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs > lhs); }
-
-// QChar <> QLatin1String
-inline bool operator==(QChar lhs, QLatin1String rhs) noexcept
-{ return rhs.size() == 1 && lhs == rhs.front(); }
-inline bool operator< (QChar lhs, QLatin1String rhs) noexcept
-{ return QString::compare_helper(&lhs, 1, rhs) < 0; }
-inline bool operator> (QChar lhs, QLatin1String rhs) noexcept
-{ return QString::compare_helper(&lhs, 1, rhs) > 0; }
-
-inline bool operator!=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs == rhs); }
-inline bool operator<=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs > rhs); }
-inline bool operator>=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs < rhs); }
-
-inline bool operator==(QLatin1String lhs, QChar rhs) noexcept { return rhs == lhs; }
-inline bool operator!=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs == lhs); }
-inline bool operator< (QLatin1String lhs, QChar rhs) noexcept { return rhs > lhs; }
-inline bool operator> (QLatin1String lhs, QChar rhs) noexcept { return rhs < lhs; }
-inline bool operator<=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs < lhs); }
-inline bool operator>=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs > lhs); }
-
-// QStringView <> QStringView
-inline bool operator==(QStringView lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
-inline bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
-inline bool operator< (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
-inline bool operator<=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
-inline bool operator> (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
-inline bool operator>=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
-
-// QStringView <> QChar
-inline bool operator==(QStringView lhs, QChar rhs) noexcept { return lhs == QStringView(&rhs, 1); }
-inline bool operator!=(QStringView lhs, QChar rhs) noexcept { return lhs != QStringView(&rhs, 1); }
-inline bool operator< (QStringView lhs, QChar rhs) noexcept { return lhs < QStringView(&rhs, 1); }
-inline bool operator<=(QStringView lhs, QChar rhs) noexcept { return lhs <= QStringView(&rhs, 1); }
-inline bool operator> (QStringView lhs, QChar rhs) noexcept { return lhs > QStringView(&rhs, 1); }
-inline bool operator>=(QStringView lhs, QChar rhs) noexcept { return lhs >= QStringView(&rhs, 1); }
-
-inline bool operator==(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) == rhs; }
-inline bool operator!=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) != rhs; }
-inline bool operator< (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) < rhs; }
-inline bool operator<=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <= rhs; }
-inline bool operator> (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) > rhs; }
-inline bool operator>=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >= rhs; }
-
-// QStringView <> QLatin1String
-inline bool operator==(QStringView lhs, QLatin1String rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
-inline bool operator!=(QStringView lhs, QLatin1String rhs) noexcept { return !(lhs == rhs); }
-inline bool operator< (QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
-inline bool operator<=(QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
-inline bool operator> (QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
-inline bool operator>=(QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
-
-inline bool operator==(QLatin1String lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
-inline bool operator!=(QLatin1String lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
-inline bool operator< (QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
-inline bool operator<=(QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
-inline bool operator> (QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
-inline bool operator>=(QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
-#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
-// QStringRef <> QByteArray
-inline QT_ASCII_CAST_WARN bool operator==(const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) == 0; }
-inline QT_ASCII_CAST_WARN bool operator!=(const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) != 0; }
-inline QT_ASCII_CAST_WARN bool operator< (const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) < 0; }
-inline QT_ASCII_CAST_WARN bool operator> (const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) > 0; }
-inline QT_ASCII_CAST_WARN bool operator<=(const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) <= 0; }
-inline QT_ASCII_CAST_WARN bool operator>=(const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) >= 0; }
-
-inline QT_ASCII_CAST_WARN bool operator==(const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) == 0; }
-inline QT_ASCII_CAST_WARN bool operator!=(const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) != 0; }
-inline QT_ASCII_CAST_WARN bool operator< (const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) > 0; }
-inline QT_ASCII_CAST_WARN bool operator> (const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) < 0; }
-inline QT_ASCII_CAST_WARN bool operator<=(const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) >= 0; }
-inline QT_ASCII_CAST_WARN bool operator>=(const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) <= 0; }
-
-// QStringRef <> const char *
-inline QT_ASCII_CAST_WARN bool QStringRef::operator==(const char *s) const
-{ return QString::compare_helper(constData(), size(), s, -1) == 0; }
-inline QT_ASCII_CAST_WARN bool QStringRef::operator!=(const char *s) const
-{ return QString::compare_helper(constData(), size(), s, -1) != 0; }
-inline QT_ASCII_CAST_WARN bool QStringRef::operator<(const char *s) const
-{ return QString::compare_helper(constData(), size(), s, -1) < 0; }
-inline QT_ASCII_CAST_WARN bool QStringRef::operator<=(const char *s) const
-{ return QString::compare_helper(constData(), size(), s, -1) <= 0; }
-inline QT_ASCII_CAST_WARN bool QStringRef::operator>(const char *s) const
-{ return QString::compare_helper(constData(), size(), s, -1) > 0; }
-inline QT_ASCII_CAST_WARN bool QStringRef::operator>=(const char *s) const
-{ return QString::compare_helper(constData(), size(), s, -1) >= 0; }
-
-inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QStringRef &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) == 0; }
-inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QStringRef &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) != 0; }
-inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QStringRef &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) > 0; }
-inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QStringRef &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) >= 0; }
-inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QStringRef &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) < 0; }
-inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QStringRef &s2)
-{ return QString::compare_helper(s2.constData(), s2.size(), s1, -1) <= 0; }
-#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
-
-inline int QString::localeAwareCompare(QStringView s) const
-{ return localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); }
-inline int QString::localeAwareCompare(QStringView s1, QStringView s2)
-{ return localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); }
-inline int QStringRef::localeAwareCompare(const QString &s) const
-{ return QString::localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); }
-inline int QStringRef::localeAwareCompare(const QStringRef &s) const
-{ return QString::localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); }
-inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s2)
-{ return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); }
-inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2)
-{ return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); }
-
-#if QT_STRINGVIEW_LEVEL < 2
-inline bool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const
-{ return indexOf(s, 0, cs) != -1; }
-inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
-{ return indexOf(s, 0, cs) != -1; }
+/*
+ Wrap QString::utf16() with enough casts to allow passing it
+ to QString::asprintf("%ls") without warnings.
+*/
+#ifndef qUtf16Printable
+# define qUtf16Printable(string) \
+ static_cast<const wchar_t*>(static_cast<const void*>(QtPrivate::asString(string).utf16()))
#endif
-inline bool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const
-{ return indexOf(s, 0, cs) != -1; }
-inline bool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const
-{ return indexOf(c, 0, cs) != -1; }
-inline bool QStringRef::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
-{ return indexOf(s, 0, cs) != -1; }
-
-#if !defined(QT_USE_FAST_OPERATOR_PLUS) && !defined(QT_USE_QSTRINGBUILDER)
-inline QString operator+(const QString &s1, const QStringRef &s2)
-{ QString t; t.reserve(s1.size() + s2.size()); t += s1; t += s2; return t; }
-inline QString operator+(const QStringRef &s1, const QString &s2)
-{ QString t; t.reserve(s1.size() + s2.size()); t += s1; t += s2; return t; }
-inline QString operator+(const QStringRef &s1, QLatin1String s2)
-{ QString t; t.reserve(s1.size() + s2.size()); t += s1; t += s2; return t; }
-inline QString operator+(QLatin1String s1, const QStringRef &s2)
-{ QString t; t.reserve(s1.size() + s2.size()); t += s1; t += s2; return t; }
-inline QString operator+(const QStringRef &s1, const QStringRef &s2)
-{ QString t; t.reserve(s1.size() + s2.size()); t += s1; t += s2; return t; }
-inline QString operator+(const QStringRef &s1, QChar s2)
-{ QString t; t.reserve(s1.size() + 1); t += s1; t += s2; return t; }
-inline QString operator+(QChar s1, const QStringRef &s2)
-{ QString t; t.reserve(1 + s2.size()); t += s1; t += s2; return t; }
-#endif // !(QT_USE_FAST_OPERATOR_PLUS || QT_USE_QSTRINGBUILDER)
-
-namespace QtPrivate {
-// used by qPrintable() and qUtf8Printable() macros
-inline const QString &asString(const QString &s) { return s; }
-inline QString &&asString(QString &&s) { return std::move(s); }
-}
//
// QStringView::arg() implementation
@@ -1805,29 +1557,29 @@ struct ArgBase {
struct QStringViewArg : ArgBase {
QStringView string;
QStringViewArg() = default;
- Q_DECL_CONSTEXPR explicit QStringViewArg(QStringView v) noexcept : ArgBase{U16}, string{v} {}
+ constexpr explicit QStringViewArg(QStringView v) noexcept : ArgBase{U16}, string{v} {}
};
struct QLatin1StringArg : ArgBase {
- QLatin1String string;
+ QLatin1StringView string;
QLatin1StringArg() = default;
- Q_DECL_CONSTEXPR explicit QLatin1StringArg(QLatin1String v) noexcept : ArgBase{L1}, string{v} {}
+ constexpr explicit QLatin1StringArg(QLatin1StringView v) noexcept : ArgBase{L1}, string{v} {}
};
-Q_REQUIRED_RESULT Q_CORE_EXPORT QString argToQString(QStringView pattern, size_t n, const ArgBase **args);
-Q_REQUIRED_RESULT Q_CORE_EXPORT QString argToQString(QLatin1String pattern, size_t n, const ArgBase **args);
+[[nodiscard]] Q_CORE_EXPORT QString argToQString(QStringView pattern, size_t n, const ArgBase **args);
+[[nodiscard]] Q_CORE_EXPORT QString argToQString(QLatin1StringView pattern, size_t n, const ArgBase **args);
template <typename StringView, typename...Args>
-Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString argToQStringDispatch(StringView pattern, const Args &...args)
+[[nodiscard]] Q_ALWAYS_INLINE QString argToQStringDispatch(StringView pattern, const Args &...args)
{
const ArgBase *argBases[] = {&args..., /* avoid zero-sized array */ nullptr};
return QtPrivate::argToQString(pattern, sizeof...(Args), argBases);
}
- inline QStringViewArg qStringLikeToArg(const QString &s) noexcept { return QStringViewArg{qToStringViewIgnoringNull(s)}; }
-Q_DECL_CONSTEXPR inline QStringViewArg qStringLikeToArg(QStringView s) noexcept { return QStringViewArg{s}; }
- inline QStringViewArg qStringLikeToArg(const QChar &c) noexcept { return QStringViewArg{QStringView{&c, 1}}; }
-Q_DECL_CONSTEXPR inline QLatin1StringArg qStringLikeToArg(QLatin1String s) noexcept { return QLatin1StringArg{s}; }
+ inline QStringViewArg qStringLikeToArg(const QString &s) noexcept { return QStringViewArg{qToStringViewIgnoringNull(s)}; }
+constexpr inline QStringViewArg qStringLikeToArg(QStringView s) noexcept { return QStringViewArg{s}; }
+ inline QStringViewArg qStringLikeToArg(const QChar &c) noexcept { return QStringViewArg{QStringView{&c, 1}}; }
+constexpr inline QLatin1StringArg qStringLikeToArg(QLatin1StringView s) noexcept { return QLatin1StringArg{s}; }
} // namespace QtPrivate
@@ -1840,15 +1592,54 @@ QString QStringView::arg(Args &&...args) const
template <typename...Args>
Q_ALWAYS_INLINE
-QString QLatin1String::arg(Args &&...args) const
+QString QLatin1StringView::arg(Args &&...args) const
{
return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
}
+template <typename T>
+qsizetype erase(QString &s, const T &t)
+{
+ return s.removeIf_helper([&t](const auto &e) { return t == e; });
+}
+
+template <typename Predicate>
+qsizetype erase_if(QString &s, Predicate pred)
+{
+ return s.removeIf_helper(pred);
+}
+
+namespace Qt {
+inline namespace Literals {
+inline namespace StringLiterals {
+inline QString operator""_s(const char16_t *str, size_t size) noexcept
+{
+ return QString(QStringPrivate(nullptr, const_cast<char16_t *>(str), qsizetype(size)));
+}
+
+} // StringLiterals
+} // Literals
+} // Qt
+
+inline namespace QtLiterals {
+#if QT_DEPRECATED_SINCE(6, 8)
+
+QT_DEPRECATED_VERSION_X_6_8("Use _s from Qt::StringLiterals namespace instead.")
+inline QString operator""_qs(const char16_t *str, size_t size) noexcept
+{
+ return Qt::StringLiterals::operator""_s(str, size);
+}
+
+#endif // QT_DEPRECATED_SINCE(6, 8)
+} // QtLiterals
+
QT_END_NAMESPACE
-#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
#include <QtCore/qstringbuilder.h>
+#include <QtCore/qstringconverter.h>
+
+#ifdef Q_L1S_VIEW_IS_PRIMARY
+# undef Q_L1S_VIEW_IS_PRIMARY
#endif
#endif // QSTRING_H
diff --git a/src/corelib/text/qstring_compat.cpp b/src/corelib/text/qstring_compat.cpp
deleted file mode 100644
index 45bb816e4b..0000000000
--- a/src/corelib/text/qstring_compat.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#if defined(QSTRING_H) || defined(QBYTEARRAY_H)
-# error "This file cannot be compiled with pre-compiled headers"
-#endif
-#define QT_COMPILING_QSTRING_COMPAT_CPP
-
-#include "qbytearray.h"
-#include "qstring.h"
-
-QT_BEGIN_NAMESPACE
-
-// all these implementations must be the same as the inline versions in qstring.h
-QString QString::trimmed() const
-{
- return trimmed_helper(*this);
-}
-
-QString QString::simplified() const
-{
- return simplified_helper(*this);
-}
-
-QString QString::toLower() const
-{
- return toLower_helper(*this);
-}
-
-QString QString::toCaseFolded() const
-{
- return toCaseFolded_helper(*this);
-}
-
-QString QString::toUpper() const
-{
- return toUpper_helper(*this);
-}
-
-QByteArray QString::toLatin1() const
-{
- return toLatin1_helper(*this);
-}
-
-QByteArray QString::toLocal8Bit() const
-{
- return toLocal8Bit_helper(isNull() ? nullptr : constData(), size());
-}
-
-QByteArray QString::toUtf8() const
-{
- return toUtf8_helper(*this);
-}
-
-// ditto, for qbytearray.h (because we're lazy)
-QByteArray QByteArray::toLower() const
-{
- return toLower_helper(*this);
-}
-
-QByteArray QByteArray::toUpper() const
-{
- return toUpper_helper(*this);
-}
-
-QByteArray QByteArray::trimmed() const
-{
- return trimmed_helper(*this);
-}
-
-QByteArray QByteArray::simplified() const
-{
- return simplified_helper(*this);
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/text/qstring_mips_dsp_asm.S b/src/corelib/text/qstring_mips_dsp_asm.S
index 202f322310..da764b2e9a 100644
--- a/src/corelib/text/qstring_mips_dsp_asm.S
+++ b/src/corelib/text/qstring_mips_dsp_asm.S
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "../../gui/painting/qt_mips_asm_dsp_p.h"
diff --git a/src/corelib/text/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h
index 4a0f7dce9a..71a1dbd526 100644
--- a/src/corelib/text/qstringalgorithms.h
+++ b/src/corelib/text/qstringalgorithms.h
@@ -1,109 +1,209 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGALGORITHMS_H
#define QSTRINGALGORITHMS_H
-#include <QtCore/qnamespace.h>
+#include <QtCore/qbytearrayalgorithms.h>
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qstringfwd.h>
#if 0
#pragma qt_class(QStringAlgorithms)
#endif
-QT_BEGIN_NAMESPACE
-
-class QByteArray;
-class QLatin1String;
-class QStringView;
-class QChar;
-
-namespace QtPrivate {
-
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const char16_t *str) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const char16_t *qustrchr(QStringView str, char16_t ch) noexcept;
-
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-
+#include <algorithm> // std::find
+#include <iterator> // std::size
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+#include <QtCore/q20type_traits.h> // q20::is_constant_evaluated
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+QT_BEGIN_NAMESPACE
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+namespace QtPrivate {
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const char16_t *str) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrnlen(const char16_t *str, qsizetype maxlen) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const char16_t *qustrchr(QStringView str, char16_t ch) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const char16_t *qustrcasechr(QStringView str, char16_t ch) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1StringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1StringView lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QBasicUtf8StringView<false> lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QStringView lhs, QStringView rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QStringView lhs, QLatin1StringView rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QStringView lhs, QBasicUtf8StringView<false> rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QLatin1StringView lhs, QStringView rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QLatin1StringView lhs, QLatin1StringView rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QLatin1StringView lhs, QBasicUtf8StringView<false> rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QBasicUtf8StringView<false> lhs, QStringView rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView rhs) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findStringInsensitive(QStringView haystack, qsizetype from, char16_t needle) noexcept;
+[[nodiscard]] inline qsizetype findString(QStringView str, qsizetype from, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1StringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1StringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, char16_t needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1StringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1StringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1StringView trimmed(QLatin1StringView s) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLower(QStringView s) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isUpper(QStringView s) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QLatin1StringView haystack, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+#if QT_CONFIG(regularexpression)
+// ### Qt 7: unify these overloads;
+// remove the ones taking only a QStringView, export the others, adjust callers
+[[nodiscard]] qsizetype indexOf(QStringView viewHaystack,
+ const QString *stringHaystack,
+ const QRegularExpression &re,
+ qsizetype from = 0,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT qsizetype indexOf(QStringView haystack,
+ const QRegularExpression &re,
+ qsizetype from = 0,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] qsizetype lastIndexOf(QStringView viewHaystack,
+ const QString *stringHaystack,
+ const QRegularExpression &re,
+ qsizetype from = -1,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT qsizetype lastIndexOf(QStringView haystack,
+ const QRegularExpression &re,
+ qsizetype from = -1,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] bool contains(QStringView viewHaystack,
+ const QString *stringHaystack,
+ const QRegularExpression &re,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT bool contains(QStringView haystack,
+ const QRegularExpression &re,
+ QRegularExpressionMatch *rmatch = nullptr);
+[[nodiscard]] Q_CORE_EXPORT qsizetype count(QStringView haystack, const QRegularExpression &re);
+#endif
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+[[nodiscard]] Q_CORE_EXPORT QString convertToQString(QAnyStringView s);
+
+[[nodiscard]] Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str);
+[[nodiscard]] Q_CORE_EXPORT QByteArray convertToUtf8(QStringView str);
+[[nodiscard]] Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str);
+[[nodiscard]] Q_CORE_EXPORT QList<uint> convertToUcs4(QStringView str); // ### Qt 7 char32_t
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isRightToLeft(QStringView string) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1StringView s) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QStringView s) noexcept;
+[[nodiscard]] constexpr inline bool isLatin1(QLatin1StringView s) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLatin1(QStringView s) noexcept;
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf16(QStringView s) noexcept;
+
+template <typename Char, size_t N> [[nodiscard]] constexpr Q_ALWAYS_INLINE
+qsizetype lengthHelperContainerLoop(const Char (&str)[N])
+{
+#if defined(__cpp_lib_constexpr_algorithms) && defined(Q_CC_GNU_ONLY)
+ // libstdc++'s std::find / std::find_if manages to execute more steps
+ // than the loop below
+ const auto it = std::find(str, str + N, Char(0));
+ return it - str;
+#else
+ // std::char_traits<C> is deprecated for C not one of the standard char
+ // types, so we have to roll out our own loop.
+ for (size_t i = 0; i < N; ++i) {
+ if (str[i] == Char(0))
+ return qsizetype(i);
+ }
+ return qsizetype(N);
+#endif
+}
+
+template <typename Char, size_t N> [[nodiscard]] constexpr Q_ALWAYS_INLINE
+std::enable_if_t<sizeof(Char) == sizeof(char16_t), qsizetype>
+lengthHelperContainer(const Char (&str)[N])
+{
+ // The following values were empirically determined to detect the threshold
+ // at which the compiler gives up pre-calculating the std::find() below and
+ // instead inserts code to be executed at runtime.
+ constexpr size_t RuntimeThreshold =
+#if defined(Q_CC_CLANG)
+ // tested on Clang 15, 16 & 17
+ 1023
+#elif defined(Q_CC_GNU)
+ // tested through GCC 13.1 at -O3 compilation level
+ // note: at -O2, GCC always generates a loop!
+ __cplusplus >= 202002L ? 39 : 17
+#else
+ 0
+#endif
+ ;
+ if constexpr (N == 1) {
+ return str[0] == Char(0) ? 0 : 1;
+ } else if constexpr (N > RuntimeThreshold) {
+#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
+ if (!q20::is_constant_evaluated())
+ return QtPrivate::qustrnlen(reinterpret_cast<const char16_t *>(str), N);
+#endif
+ }
-Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str);
-Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToUtf8(QStringView str);
-Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str);
-Q_REQUIRED_RESULT Q_CORE_EXPORT QList<uint> convertToUcs4(QStringView str);
+ return lengthHelperContainerLoop(str);
+}
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isRightToLeft(QStringView string) noexcept;
+inline qsizetype qstrnlen_helper(const char *str, size_t maxlen)
+{
+#if !defined(Q_COMPILER_SLOW_QSTRNLEN_COMPILATION)
+ return qstrnlen(str, maxlen);
+#else
+ return strnlen_s(str, maxlen);
+#endif
+}
+
+template <typename Char, size_t N> [[nodiscard]] constexpr inline
+std::enable_if_t<sizeof(Char) == 1, qsizetype> lengthHelperContainer(const Char (&str)[N])
+{
+#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
+ if (!q20::is_constant_evaluated())
+ return qstrnlen_helper(reinterpret_cast<const char *>(str), N);
+#endif
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1String s) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QStringView s) noexcept;
-Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline bool isLatin1(QLatin1String s) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLatin1(QStringView s) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf16(QStringView s) noexcept;
+ return lengthHelperContainerLoop(str);
+}
-} // namespace QtPRivate
+template <typename Container>
+constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
+{
+ return qsizetype(std::size(c));
+}
+} // namespace QtPrivate
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringalgorithms_p.h b/src/corelib/text/qstringalgorithms_p.h
index 64d9f2e676..f34acb01e8 100644
--- a/src/corelib/text/qstringalgorithms_p.h
+++ b/src/corelib/text/qstringalgorithms_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGALGORITHMS_P_H
#define QSTRINGALGORITHMS_P_H
@@ -83,26 +47,34 @@ template <typename StringType> struct QStringAlgorithms
static inline StringType trimmed_helper_inplace(const NakedStringType &, const Char *, const Char *)
{
// can't happen
- Q_UNREACHABLE();
- return StringType();
+ Q_UNREACHABLE_RETURN(StringType());
}
- static inline void trimmed_helper_positions(const Char *&begin, const Char *&end)
+ struct TrimPositions {
+ const Char *begin;
+ const Char *end;
+ };
+ // Returns {begin, end} where:
+ // - "begin" refers to the first non-space character
+ // - if there is a sequence of one or more space chacaters at the end,
+ // "end" refers to the first character in that sequence, otherwise
+ // "end" is str.cend()
+ [[nodiscard]] static TrimPositions trimmed_helper_positions(const StringType &str)
{
+ const Char *begin = str.cbegin();
+ const Char *end = str.cend();
// skip white space from end
while (begin < end && isSpace(end[-1]))
--end;
// skip white space from start
while (begin < end && isSpace(*begin))
begin++;
+ return {begin, end};
}
static inline StringType trimmed_helper(StringType &str)
{
- const Char *begin = str.cbegin();
- const Char *end = str.cend();
- trimmed_helper_positions(begin, end);
-
+ const auto [begin, end] = trimmed_helper_positions(str);
if (begin == str.cbegin() && end == str.cend())
return str;
if (!isConst && str.isDetached())
@@ -137,7 +109,7 @@ template <typename StringType> struct QStringAlgorithms
if (ptr != dst && ptr[-1] == QChar::Space)
--ptr;
- int newlen = ptr - dst;
+ qsizetype newlen = ptr - dst;
if (isConst && newlen == str.size() && unmodified) {
// nothing happened, return the original
return str;
diff --git a/src/corelib/text/qstringbuilder.cpp b/src/corelib/text/qstringbuilder.cpp
index 4e47ba0922..738ce833ef 100644
--- a/src/corelib/text/qstringbuilder.cpp
+++ b/src/corelib/text/qstringbuilder.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstringbuilder.h"
#include <private/qstringconverter_p.h>
@@ -72,9 +36,9 @@ QT_BEGIN_NAMESPACE
For building QStrings:
\list
- \li QString, QStringRef, (since 5.10:) QStringView
+ \li QString, (since 5.10:) QStringView
\li QChar, QLatin1Char, (since 5.10:) \c char16_t,
- \li QLatin1String,
+ \li QLatin1StringView,
\li (since 5.10:) \c{const char16_t[]} (\c{u"foo"}),
\li QByteArray, \c char, \c{const char[]}.
\endlist
@@ -93,45 +57,61 @@ QT_BEGIN_NAMESPACE
if there are three or more of them, and performs equally well in other
cases.
- \sa QLatin1String, QString
+ \note Defining \c QT_USE_QSTRINGBUILDER at build time (this is the
+ default when building Qt libraries and tools), will make using \c {'+'}
+ when concatenating strings work the same way as \c operator%().
+
+ \sa QLatin1StringView, QString
*/
-/*! \fn template <typename A, typename B> QStringBuilder<A, B>::QStringBuilder(const A &a, const B &b)
- Constructs a QStringBuilder from \a a and \a b.
+/*!
+ \internal
+ \fn template <typename A, typename B> QStringBuilder<A, B>::QStringBuilder(const A &a, const B &b)
+
+ Constructs a QStringBuilder from \a a and \a b.
*/
-/* \fn template <typename A, typename B> QStringBuilder<A, B>::operator%(const A &a, const B &b)
+/*!
+ \internal
+ \fn template <typename A, typename B> QStringBuilder<A, B>::operator%(const A &a, const B &b)
Returns a \c QStringBuilder object that is converted to a QString object
when assigned to a variable of QString type or passed to a function that
takes a QString parameter.
- This function is usable with arguments of type \c QString,
- \c QLatin1String, \c QStringRef,
- \c QChar, \c QLatin1Char, and \c char.
+ This function is usable with arguments of any of the following types:
+ \list
+ \li \c QAnyStringView,
+ \li \c QString, \c QStringView
+ \li \c QByteArray, \c QByteArrayView, \c QLatin1StringView
+ \li \c QChar, \c QLatin1Char, \c char, (since 5.10:) \c char16_t
+ \li (since 5.10:) \c{const char16_t[]} (\c{u"foo"}),
+ \endlist
*/
-/* \fn template <typename A, typename B> QByteArray QStringBuilder<A, B>::toLatin1() const
- Returns a Latin-1 representation of the string as a QByteArray. The
- returned byte array is undefined if the string contains non-Latin1
- characters.
- */
-/* \fn template <typename A, typename B> QByteArray QStringBuilder<A, B>::toUtf8() const
- Returns a UTF-8 representation of the string as a QByteArray.
+/*!
+ \internal
+ \fn template <typename A, typename B> QByteArray QStringBuilder<A, B>::toLatin1() const
+
+ Returns a Latin-1 representation of the string as a QByteArray. It
+ is undefined behavior if the string contains non-Latin1 characters.
*/
+/*!
+ \internal
+ \fn template <typename A, typename B> QByteArray QStringBuilder<A, B>::toUtf8() const
+
+ Returns a UTF-8 representation of the string as a QByteArray.
+ */
/*!
\internal
+ Converts the UTF-8 string viewed by \a in to UTF-16 and writes the result
+ to the buffer starting at \a out.
*/
-void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out) noexcept
+void QAbstractConcatenable::convertFromUtf8(QByteArrayView in, QChar *&out) noexcept
{
- if (Q_UNLIKELY(len == -1)) {
- if (!a)
- return;
- len = int(strlen(a));
- }
- out = QUtf8::convertToUnicode(out, a, len);
+ out = QUtf8::convertToUnicode(out, in);
}
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringbuilder.h b/src/corelib/text/qstringbuilder.h
index 6ba01c0e30..853033b2d9 100644
--- a/src/corelib/text/qstringbuilder.h
+++ b/src/corelib/text/qstringbuilder.h
@@ -1,41 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qstring.h>
#ifndef QSTRINGBUILDER_H
#define QSTRINGBUILDER_H
@@ -47,7 +13,6 @@
#pragma qt_sync_stop_processing
#endif
-#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
#include <string.h>
@@ -58,21 +23,33 @@ QT_BEGIN_NAMESPACE
struct Q_CORE_EXPORT QAbstractConcatenable
{
protected:
- static void convertFromAscii(const char *a, int len, QChar *&out) noexcept;
+ static void convertFromUtf8(QByteArrayView in, QChar *&out) noexcept;
static inline void convertFromAscii(char a, QChar *&out) noexcept
{
*out++ = QLatin1Char(a);
}
- static void appendLatin1To(const char *a, int len, QChar *out) noexcept;
+ static void appendLatin1To(QLatin1StringView in, QChar *out) noexcept;
};
-template <typename T> struct QConcatenable {};
+template <typename T> struct QConcatenable;
+
+template <typename T>
+using QConcatenableEx = QConcatenable<q20::remove_cvref_t<T>>;
namespace QtStringBuilder {
template <typename A, typename B> struct ConvertToTypeHelper
{ typedef A ConvertTo; };
template <typename T> struct ConvertToTypeHelper<T, QString>
{ typedef QString ConvertTo; };
+
+ template <typename T> using HasIsNull = decltype(std::declval<const T &>().isNull());
+ template <typename T> bool isNull(const T &t)
+ {
+ if constexpr (qxp::is_detected_v<HasIsNull, T>)
+ return t.isNull();
+ else
+ return false;
+ }
}
template<typename Builder, typename T>
@@ -99,28 +76,50 @@ struct QStringBuilderBase<Builder, QString> : public QStringBuilderCommon<Builde
};
template <typename A, typename B>
-class QStringBuilder : public QStringBuilderBase<QStringBuilder<A, B>, typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo>
+class QStringBuilder : public QStringBuilderBase<QStringBuilder<A, B>,
+ typename QtStringBuilder::ConvertToTypeHelper<
+ typename QConcatenableEx<A>::ConvertTo,
+ typename QConcatenableEx<B>::ConvertTo
+ >::ConvertTo
+ >
{
public:
- QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
+ QStringBuilder(A &&a_, B &&b_) : a(std::forward<A>(a_)), b(std::forward<B>(b_)) {}
+
+ QStringBuilder(QStringBuilder &&) = default;
+ QStringBuilder(const QStringBuilder &) = default;
+ ~QStringBuilder() = default;
+
private:
friend class QByteArray;
friend class QString;
template <typename T> T convertTo() const
{
- const uint len = QConcatenable< QStringBuilder<A, B> >::size(*this);
- T s(len, Qt::Uninitialized);
+ if (isNull()) {
+ // appending two null strings must give back a null string,
+ // so we're special casing this one out, QTBUG-114206
+ return T();
+ }
- // we abuse const_cast / constData here because we know we've just
- // allocated the data and we're the only reference count
- typename T::iterator d = const_cast<typename T::iterator>(s.constData());
- typename T::const_iterator const start = d;
- QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
+ const qsizetype len = Concatenable::size(*this);
+ T s(len, Qt::Uninitialized);
- if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(len) != d - start) {
- // this resize is necessary since we allocate a bit too much
- // when dealing with variable sized 8-bit encodings
- s.resize(int(d - start));
+ // Using data_ptr() here (private API) so we can bypass the
+ // isDetached() and the replacement of a null pointer with _empty in
+ // both QString and QByteArray's data() and constData(). The result is
+ // the same if len != 0.
+ auto d = reinterpret_cast<typename T::iterator>(s.data_ptr().data());
+ const auto start = d;
+ Concatenable::appendTo(*this, d);
+
+ if constexpr (Concatenable::ExactSize) {
+ Q_UNUSED(start)
+ } else {
+ if (len != d - start) {
+ // this resize is necessary since we allocate a bit too much
+ // when dealing with variable sized 8-bit encodings
+ s.resize(d - start);
+ }
}
return s;
}
@@ -130,55 +129,29 @@ public:
typedef typename Concatenable::ConvertTo ConvertTo;
operator ConvertTo() const { return convertTo<ConvertTo>(); }
- int size() const { return Concatenable::size(*this); }
-
- const A &a;
- const B &b;
-};
-
-template <>
-class QStringBuilder <QString, QString> : public QStringBuilderBase<QStringBuilder<QString, QString>, QString>
-{
- public:
- QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
- QStringBuilder(const QStringBuilder &other) : a(other.a), b(other.b) {}
-
- operator QString() const
- { QString r(a); r += b; return r; }
-
- const QString &a;
- const QString &b;
-
- private:
- QStringBuilder &operator=(const QStringBuilder &) = delete;
-};
+ qsizetype size() const { return Concatenable::size(*this); }
-template <>
-class QStringBuilder <QByteArray, QByteArray> : public QStringBuilderBase<QStringBuilder<QByteArray, QByteArray>, QByteArray>
-{
- public:
- QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
- QStringBuilder(const QStringBuilder &other) : a(other.a), b(other.b) {}
-
- operator QByteArray() const
- { QByteArray r(a); r += b; return r; }
+ bool isNull() const
+ {
+ return QtStringBuilder::isNull(a) && QtStringBuilder::isNull(b);
+ }
- const QByteArray &a;
- const QByteArray &b;
+ A a;
+ B b;
- private:
- QStringBuilder &operator=(const QStringBuilder &) = delete;
+private:
+ QStringBuilder &operator=(QStringBuilder &&) = delete;
+ QStringBuilder &operator=(const QStringBuilder &) = delete;
};
-
template <> struct QConcatenable<char> : private QAbstractConcatenable
{
typedef char type;
typedef QByteArray ConvertTo;
enum { ExactSize = true };
- static int size(const char) { return 1; }
+ static qsizetype size(const char) { return 1; }
#ifndef QT_NO_CAST_FROM_ASCII
- static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
+ QT_ASCII_CAST_WARN static inline void appendTo(const char c, QChar *&out)
{
QAbstractConcatenable::convertFromAscii(c, out);
}
@@ -187,24 +160,43 @@ template <> struct QConcatenable<char> : private QAbstractConcatenable
{ *out++ = c; }
};
-#if defined(Q_COMPILER_UNICODE_STRINGS)
+template <> struct QConcatenable<QByteArrayView> : private QAbstractConcatenable
+{
+ typedef QByteArrayView type;
+ typedef QByteArray ConvertTo;
+ enum { ExactSize = true };
+ static qsizetype size(QByteArrayView bav) { return bav.size(); }
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN static inline void appendTo(QByteArrayView bav, QChar *&out)
+ {
+ QAbstractConcatenable::convertFromUtf8(bav, out);
+ }
+#endif
+ static inline void appendTo(QByteArrayView bav, char *&out)
+ {
+ qsizetype n = bav.size();
+ if (n)
+ memcpy(out, bav.data(), n);
+ out += n;
+ }
+};
+
template <> struct QConcatenable<char16_t> : private QAbstractConcatenable
{
typedef char16_t type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static Q_DECL_CONSTEXPR int size(char16_t) { return 1; }
+ static constexpr qsizetype size(char16_t) { return 1; }
static inline void appendTo(char16_t c, QChar *&out)
{ *out++ = c; }
};
-#endif
template <> struct QConcatenable<QLatin1Char>
{
typedef QLatin1Char type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QLatin1Char) { return 1; }
+ static qsizetype size(const QLatin1Char) { return 1; }
static inline void appendTo(const QLatin1Char c, QChar *&out)
{ *out++ = c; }
static inline void appendTo(const QLatin1Char c, char *&out)
@@ -216,7 +208,7 @@ template <> struct QConcatenable<QChar> : private QAbstractConcatenable
typedef QChar type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QChar) { return 1; }
+ static qsizetype size(const QChar) { return 1; }
static inline void appendTo(const QChar c, QChar *&out)
{ *out++ = c; }
};
@@ -226,23 +218,23 @@ template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractCon
typedef QChar::SpecialCharacter type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QChar::SpecialCharacter) { return 1; }
+ static qsizetype size(const QChar::SpecialCharacter) { return 1; }
static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out)
{ *out++ = c; }
};
-template <> struct QConcatenable<QLatin1String> : private QAbstractConcatenable
+template <> struct QConcatenable<QLatin1StringView> : private QAbstractConcatenable
{
- typedef QLatin1String type;
+ typedef QLatin1StringView type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QLatin1String a) { return a.size(); }
- static inline void appendTo(const QLatin1String a, QChar *&out)
+ static qsizetype size(const QLatin1StringView a) { return a.size(); }
+ static inline void appendTo(const QLatin1StringView a, QChar *&out)
{
- appendLatin1To(a.latin1(), a.size(), out);
+ appendLatin1To(a, out);
out += a.size();
}
- static inline void appendTo(const QLatin1String a, char *&out)
+ static inline void appendTo(const QLatin1StringView a, char *&out)
{
if (const char *data = a.data()) {
memcpy(out, data, a.size());
@@ -256,25 +248,12 @@ template <> struct QConcatenable<QString> : private QAbstractConcatenable
typedef QString type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QString &a) { return a.size(); }
+ static qsizetype size(const QString &a) { return a.size(); }
static inline void appendTo(const QString &a, QChar *&out)
{
- const int n = a.size();
- memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
- out += n;
- }
-};
-
-template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
-{
- typedef QStringRef type;
- typedef QString ConvertTo;
- enum { ExactSize = true };
- static int size(const QStringRef &a) { return a.size(); }
- static inline void appendTo(const QStringRef &a, QChar *&out)
- {
- const int n = a.size();
- memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
+ const qsizetype n = a.size();
+ if (n)
+ memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
out += n;
}
};
@@ -284,25 +263,26 @@ template <> struct QConcatenable<QStringView> : private QAbstractConcatenable
typedef QStringView type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(QStringView a) { return a.length(); }
+ static qsizetype size(QStringView a) { return a.size(); }
static inline void appendTo(QStringView a, QChar *&out)
{
const auto n = a.size();
- memcpy(out, a.data(), sizeof(QChar) * n);
+ if (n)
+ memcpy(out, a.data(), sizeof(QChar) * n);
out += n;
}
};
-template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
+template <qsizetype N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
{
typedef const char type[N];
typedef QByteArray ConvertTo;
enum { ExactSize = false };
- static int size(const char[N]) { return N - 1; }
+ static qsizetype size(const char[N]) { return N - 1; }
#ifndef QT_NO_CAST_FROM_ASCII
- static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
+ QT_ASCII_CAST_WARN static inline void appendTo(const char a[N], QChar *&out)
{
- QAbstractConcatenable::convertFromAscii(a, N - 1, out);
+ QAbstractConcatenable::convertFromUtf8(QByteArrayView(a, N - 1), out);
}
#endif
static inline void appendTo(const char a[N], char *&out)
@@ -312,7 +292,7 @@ template <int N> struct QConcatenable<const char[N]> : private QAbstractConcaten
}
};
-template <int N> struct QConcatenable<char[N]> : QConcatenable<const char[N]>
+template <qsizetype N> struct QConcatenable<char[N]> : QConcatenable<const char[N]>
{
typedef char type[N];
};
@@ -322,10 +302,10 @@ template <> struct QConcatenable<const char *> : private QAbstractConcatenable
typedef const char *type;
typedef QByteArray ConvertTo;
enum { ExactSize = false };
- static int size(const char *a) { return qstrlen(a); }
+ static qsizetype size(const char *a) { return qstrlen(a); }
#ifndef QT_NO_CAST_FROM_ASCII
- static inline void QT_ASCII_CAST_WARN appendTo(const char *a, QChar *&out)
- { QAbstractConcatenable::convertFromAscii(a, -1, out); }
+ QT_ASCII_CAST_WARN static inline void appendTo(const char *a, QChar *&out)
+ { QAbstractConcatenable::convertFromUtf8(QByteArrayView(a), out); }
#endif
static inline void appendTo(const char *a, char *&out)
{
@@ -341,21 +321,20 @@ template <> struct QConcatenable<char *> : QConcatenable<const char*>
typedef char *type;
};
-#if defined(Q_COMPILER_UNICODE_STRINGS)
-template <int N> struct QConcatenable<const char16_t[N]> : private QAbstractConcatenable
+template <qsizetype N> struct QConcatenable<const char16_t[N]> : private QAbstractConcatenable
{
using type = const char16_t[N];
using ConvertTo = QString;
enum { ExactSize = true };
- static int size(const char16_t[N]) { return N - 1; }
+ static qsizetype size(const char16_t[N]) { return N - 1; }
static void appendTo(const char16_t a[N], QChar *&out)
{
- memcpy(out, a, (N - 1) * sizeof(char16_t));
+ memcpy(static_cast<void *>(out), a, (N - 1) * sizeof(char16_t));
out += N - 1;
}
};
-template <int N> struct QConcatenable<char16_t[N]> : QConcatenable<const char16_t[N]>
+template <qsizetype N> struct QConcatenable<char16_t[N]> : QConcatenable<const char16_t[N]>
{
using type = char16_t[N];
};
@@ -365,8 +344,8 @@ template <> struct QConcatenable<const char16_t *> : private QAbstractConcatenab
using type = const char16_t *;
using ConvertTo = QString;
enum { ExactSize = true };
- static int size(const char16_t *a) { return QStringView(a).length(); }
- static inline void QT_ASCII_CAST_WARN appendTo(const char16_t *a, QChar *&out)
+ static qsizetype size(const char16_t *a) { return QStringView(a).size(); }
+ QT_ASCII_CAST_WARN static inline void appendTo(const char16_t *a, QChar *&out)
{
if (!a)
return;
@@ -379,26 +358,25 @@ template <> struct QConcatenable<char16_t *> : QConcatenable<const char16_t*>
{
typedef char16_t *type;
};
-#endif // UNICODE_STRINGS
template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
{
typedef QByteArray type;
typedef QByteArray ConvertTo;
enum { ExactSize = false };
- static int size(const QByteArray &ba) { return ba.size(); }
+ static qsizetype size(const QByteArray &ba) { return ba.size(); }
#ifndef QT_NO_CAST_FROM_ASCII
- static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
+ QT_ASCII_CAST_WARN static inline void appendTo(const QByteArray &ba, QChar *&out)
{
- QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
+ QAbstractConcatenable::convertFromUtf8(ba, out);
}
#endif
static inline void appendTo(const QByteArray &ba, char *&out)
{
- const char *a = ba.constData();
- const char * const end = ba.end();
- while (a != end)
- *out++ = *a++;
+ const qsizetype n = ba.size();
+ if (n)
+ memcpy(out, ba.begin(), n);
+ out += n;
}
};
@@ -407,34 +385,37 @@ template <typename A, typename B>
struct QConcatenable< QStringBuilder<A, B> >
{
typedef QStringBuilder<A, B> type;
- typedef typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo ConvertTo;
- enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
- static int size(const type &p)
+ using ConvertTo = typename QtStringBuilder::ConvertToTypeHelper<
+ typename QConcatenableEx<A>::ConvertTo,
+ typename QConcatenableEx<B>::ConvertTo
+ >::ConvertTo;
+ enum { ExactSize = QConcatenableEx<A>::ExactSize && QConcatenableEx<B>::ExactSize };
+ static qsizetype size(const type &p)
{
- return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
+ return QConcatenableEx<A>::size(p.a) + QConcatenableEx<B>::size(p.b);
}
template<typename T> static inline void appendTo(const type &p, T *&out)
{
- QConcatenable<A>::appendTo(p.a, out);
- QConcatenable<B>::appendTo(p.b, out);
+ QConcatenableEx<A>::appendTo(p.a, out);
+ QConcatenableEx<B>::appendTo(p.b, out);
}
};
-template <typename A, typename B>
-QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
-operator%(const A &a, const B &b)
+template <typename A, typename B,
+ typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
+auto operator%(A &&a, B &&b)
{
- return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
+ return QStringBuilder<A, B>(std::forward<A>(a), std::forward<B>(b));
}
// QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
// QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
-template <typename A, typename B>
-QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
-operator+(const A &a, const B &b)
+template <typename A, typename B,
+ typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
+auto operator+(A &&a, B &&b)
{
- return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
+ return std::forward<A>(a) % std::forward<B>(b);
}
#endif
@@ -443,8 +424,10 @@ template <typename A, typename B>
QByteArray &appendToByteArray(QByteArray &a, const QStringBuilder<A, B> &b, char)
{
// append 8-bit data to a byte array
- int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
- a.reserve(len);
+ qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
+ a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
+ if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
+ a.reserve(qMax(len, 2 * a.capacity()));
char *it = a.data() + a.size();
QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
@@ -470,15 +453,17 @@ QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
template <typename A, typename B>
QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
{
- int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
- a.reserve(len);
+ qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
+ a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
+ if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
+ a.reserve(qMax(len, 2 * a.capacity()));
QChar *it = a.data() + a.size();
QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
- a.resize(int(it - a.constData())); //may be smaller than len if there was conversion from utf8
+ // we need to resize after the appendTo for the case str+=foo+str
+ a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
return a;
}
-
QT_END_NAMESPACE
#endif // QSTRINGBUILDER_H
diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp
index 30da0add8f..67c75d708e 100644
--- a/src/corelib/text/qstringconverter.cpp
+++ b/src/corelib/text/qstringconverter.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qstringconverter.h>
#include <private/qstringconverter_p.h>
@@ -44,33 +8,64 @@
#include "private/qsimd_p.h"
#include "private/qstringiterator_p.h"
+#include "private/qtools_p.h"
#include "qbytearraymatcher.h"
+#include "qcontainertools_impl.h"
+#include <QtCore/qbytearraylist.h>
+
+#if QT_CONFIG(icu)
+#include <unicode/ucnv.h>
+#include <unicode/ucnv_cb.h>
+#include <unicode/ucnv_err.h>
+#include <unicode/ustring.h>
+#endif
#ifdef Q_OS_WIN
#include <qt_windows.h>
+#ifndef QT_BOOTSTRAPPED
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/q20iterator.h>
+#include <QtCore/private/qnumeric_p.h>
+#endif // !QT_BOOTSTRAPPED
+#endif
+
+#include <array>
+
+#if __has_include(<bit>) && __cplusplus > 201703L
+#include <bit>
#endif
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
+static_assert(std::is_nothrow_move_constructible_v<QStringEncoder>);
+static_assert(std::is_nothrow_move_assignable_v<QStringEncoder>);
+static_assert(std::is_nothrow_move_constructible_v<QStringDecoder>);
+static_assert(std::is_nothrow_move_assignable_v<QStringDecoder>);
+
enum { Endian = 0, Data = 1 };
static const uchar utf8bom[] = { 0xef, 0xbb, 0xbf };
-#if (defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2)) \
- || (defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64))
+#if defined(__SSE2__) || defined(__ARM_NEON__)
static Q_ALWAYS_INLINE uint qBitScanReverse(unsigned v) noexcept
{
+#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
+ return std::bit_width(v) - 1;
+#else
uint result = qCountLeadingZeroBits(v);
// Now Invert the result: clz will count *down* from the msb to the lsb, so the msb index is 31
// and the lsb index is 0. The result for _bit_scan_reverse is expected to be the index when
// counting up: msb index is 0 (because it starts there), and the lsb index is 31.
result ^= sizeof(unsigned) * 8 - 1;
return result;
+#endif
}
#endif
-#if defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2)
-static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const ushort *&src, const ushort *end)
+#if defined(__SSE2__)
+static inline bool simdEncodeAscii(uchar *&dst, const char16_t *&nextAscii, const char16_t *&src, const char16_t *end)
{
// do sixteen characters at a time
for ( ; end - src >= 16; src += 16, dst += 16) {
@@ -134,7 +129,7 @@ static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const
return src == end;
}
-static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const uchar *&src, const uchar *end)
+static inline bool simdDecodeAscii(char16_t *&dst, const uchar *&nextAscii, const uchar *&src, const uchar *end)
{
// do sixteen characters at a time
for ( ; end - src >= 16; src += 16, dst += 16) {
@@ -206,14 +201,14 @@ static inline const uchar *simdFindNonAscii(const uchar *src, const uchar *end,
#ifdef __AVX2__
// do 32 characters at a time
// (this is similar to simdTestMask in qstring.cpp)
- const __m256i mask = _mm256_set1_epi8(0x80);
+ const __m256i mask = _mm256_set1_epi8(char(0x80));
for ( ; end - src >= 32; src += 32) {
__m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src));
if (_mm256_testz_si256(mask, data))
continue;
uint n = _mm256_movemask_epi8(data);
- Q_ASSUME(n);
+ Q_ASSERT(n);
// find the next probable ASCII character
// we don't want to load 32 bytes again in this loop if we know there are non-ASCII
@@ -260,8 +255,100 @@ static inline const uchar *simdFindNonAscii(const uchar *src, const uchar *end,
nextAscii = end;
return src;
}
-#elif defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
-static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const ushort *&src, const ushort *end)
+
+// Compare only the US-ASCII beginning of [src8, end8) and [src16, end16)
+// and advance src8 and src16 to the first character that could not be compared
+static void simdCompareAscii(const qchar8_t *&src8, const qchar8_t *end8, const char16_t *&src16, const char16_t *end16)
+{
+ int bitSpacing = 1;
+ qptrdiff len = qMin(end8 - src8, end16 - src16);
+ qptrdiff offset = 0;
+ uint mask = 0;
+
+ // do sixteen characters at a time
+ for ( ; offset + 16 < len; offset += 16) {
+ __m128i data8 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src8 + offset));
+#ifdef __AVX2__
+ // AVX2 version, use 256-bit registers and VPMOVXZBW
+ __m256i data16 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src16 + offset));
+
+ // expand US-ASCII as if it were Latin1 and confirm it's US-ASCII
+ __m256i datax8 = _mm256_cvtepu8_epi16(data8);
+ mask = _mm256_movemask_epi8(datax8);
+ if (mask)
+ break;
+
+ // compare Latin1 to UTF-16
+ __m256i latin1cmp = _mm256_cmpeq_epi16(datax8, data16);
+ mask = ~_mm256_movemask_epi8(latin1cmp);
+ if (mask)
+ break;
+#else
+ // non-AVX2 code
+ __m128i datalo16 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src16 + offset));
+ __m128i datahi16 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src16 + offset) + 1);
+
+ // expand US-ASCII as if it were Latin1, we'll confirm later
+ __m128i datalo8 = _mm_unpacklo_epi8(data8, _mm_setzero_si128());
+ __m128i datahi8 = _mm_unpackhi_epi8(data8, _mm_setzero_si128());
+
+ // compare Latin1 to UTF-16
+ __m128i latin1cmplo = _mm_cmpeq_epi16(datalo8, datalo16);
+ __m128i latin1cmphi = _mm_cmpeq_epi16(datahi8, datahi16);
+ mask = _mm_movemask_epi8(latin1cmphi) << 16;
+ mask |= ushort(_mm_movemask_epi8(latin1cmplo));
+ mask = ~mask;
+ if (mask)
+ break;
+
+ // confirm it was US-ASCII
+ mask = _mm_movemask_epi8(data8);
+ if (mask) {
+ bitSpacing = 0;
+ break;
+ }
+#endif
+ }
+
+ // helper for comparing 4 or 8 characters
+ auto cmp_lt_16 = [&mask, &offset](int n, __m128i data8, __m128i data16) {
+ // n = 4 -> sizemask = 0xff
+ // n = 8 -> sizemask = 0xffff
+ unsigned sizemask = (1U << (2 * n)) - 1;
+
+ // expand as if Latin1
+ data8 = _mm_unpacklo_epi8(data8, _mm_setzero_si128());
+
+ // compare and confirm it's US-ASCII
+ __m128i latin1cmp = _mm_cmpeq_epi16(data8, data16);
+ mask = ~_mm_movemask_epi8(latin1cmp) & sizemask;
+ mask |= _mm_movemask_epi8(data8);
+ if (mask == 0)
+ offset += n;
+ };
+
+ // do eight characters at a time
+ if (mask == 0 && offset + 8 < len) {
+ __m128i data8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src8 + offset));
+ __m128i data16 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src16 + offset));
+ cmp_lt_16(8, data8, data16);
+ }
+
+ // do four characters
+ if (mask == 0 && offset + 4 < len) {
+ __m128i data8 = _mm_cvtsi32_si128(qFromUnaligned<quint32>(src8 + offset));
+ __m128i data16 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src16 + offset));
+ cmp_lt_16(4, data8, data16);
+ }
+
+ // correct the source pointers to point to the first character we couldn't deal with
+ if (mask)
+ offset += qCountTrailingZeroBits(mask) >> bitSpacing;
+ src8 += offset;
+ src16 += offset;
+}
+#elif defined(__ARM_NEON__)
+static inline bool simdEncodeAscii(uchar *&dst, const char16_t *&nextAscii, const char16_t *&src, const char16_t *end)
{
uint16x8_t maxAscii = vdupq_n_u16(0x7f);
uint16x8_t mask1 = { 1, 1 << 2, 1 << 4, 1 << 6, 1 << 8, 1 << 10, 1 << 12, 1 << 14 };
@@ -270,7 +357,7 @@ static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const
// do sixteen characters at a time
for ( ; end - src >= 16; src += 16, dst += 16) {
// load 2 lanes (or: "load interleaved")
- uint16x8x2_t in = vld2q_u16(src);
+ uint16x8x2_t in = vld2q_u16(reinterpret_cast<const uint16_t *>(src));
// check if any of the elements > 0x7f, select 1 bit per element (element 0 -> bit 0, element 1 -> bit 1, etc),
// add those together into a scalar, and merge the scalars.
@@ -298,7 +385,7 @@ static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const
return src == end;
}
-static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const uchar *&src, const uchar *end)
+static inline bool simdDecodeAscii(char16_t *&dst, const uchar *&nextAscii, const uchar *&src, const uchar *end)
{
// do eight characters at a time
uint8x8_t msb_mask = vdup_n_u8(0x80);
@@ -308,7 +395,7 @@ static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const
uint8_t n = vaddv_u8(vand_u8(vcge_u8(c, msb_mask), add_mask));
if (!n) {
// store
- vst1q_u16(dst, vmovl_u8(c));
+ vst1q_u16(reinterpret_cast<uint16_t *>(dst), vmovl_u8(c));
continue;
}
@@ -356,13 +443,17 @@ static inline const uchar *simdFindNonAscii(const uchar *src, const uchar *end,
nextAscii = end;
return src;
}
+
+static void simdCompareAscii(const qchar8_t *&, const qchar8_t *, const char16_t *&, const char16_t *)
+{
+}
#else
-static inline bool simdEncodeAscii(uchar *, const ushort *, const ushort *, const ushort *)
+static inline bool simdEncodeAscii(uchar *, const char16_t *, const char16_t *, const char16_t *)
{
return false;
}
-static inline bool simdDecodeAscii(ushort *, const uchar *, const uchar *, const uchar *)
+static inline bool simdDecodeAscii(char16_t *, const uchar *, const uchar *, const uchar *)
{
return false;
}
@@ -372,26 +463,32 @@ static inline const uchar *simdFindNonAscii(const uchar *src, const uchar *end,
nextAscii = end;
return src;
}
+
+static void simdCompareAscii(const qchar8_t *&, const qchar8_t *, const char16_t *&, const char16_t *)
+{
+}
#endif
enum { HeaderDone = 1 };
-QByteArray QUtf8::convertFromUnicode(const QChar *uc, qsizetype len)
+QByteArray QUtf8::convertFromUnicode(QStringView in)
{
+ qsizetype len = in.size();
+
// create a QByteArray with the worst case scenario size
QByteArray result(len * 3, Qt::Uninitialized);
uchar *dst = reinterpret_cast<uchar *>(const_cast<char *>(result.constData()));
- const ushort *src = reinterpret_cast<const ushort *>(uc);
- const ushort *const end = src + len;
+ const char16_t *src = reinterpret_cast<const char16_t *>(in.data());
+ const char16_t *const end = src + len;
while (src != end) {
- const ushort *nextAscii = end;
+ const char16_t *nextAscii = end;
if (simdEncodeAscii(dst, nextAscii, src, end))
break;
do {
- ushort uc = *src++;
- int res = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, dst, src, end);
+ char16_t u = *src++;
+ int res = QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, dst, src, end);
if (res < 0) {
// encoding error - append '?'
*dst++ = '?';
@@ -403,10 +500,10 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, qsizetype len)
return result;
}
-QByteArray QUtf8::convertFromUnicode(const QChar *uc, qsizetype len, QStringConverterBase::State *state)
+QByteArray QUtf8::convertFromUnicode(QStringView in, QStringConverterBase::State *state)
{
- QByteArray ba(3*len +3, Qt::Uninitialized);
- char *end = convertFromUnicode(ba.data(), QStringView(uc, len), state);
+ QByteArray ba(3*in.size() +3, Qt::Uninitialized);
+ char *end = convertFromUnicode(ba.data(), in, state);
ba.truncate(end - ba.data());
return ba;
}
@@ -414,8 +511,7 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, qsizetype len, QStringConv
char *QUtf8::convertFromUnicode(char *out, QStringView in, QStringConverter::State *state)
{
Q_ASSERT(state);
- const QChar *uc = in.data();
- qsizetype len = in.length();
+ qsizetype len = in.size();
if (!len)
return out;
@@ -432,8 +528,8 @@ char *QUtf8::convertFromUnicode(char *out, QStringView in, QStringConverter::Sta
};
uchar *cursor = reinterpret_cast<uchar *>(out);
- const ushort *src = reinterpret_cast<const ushort *>(uc);
- const ushort *const end = src + len;
+ const char16_t *src = in.utf16();
+ const char16_t *const end = src + len;
if (!(state->flags & QStringDecoder::Flag::Stateless)) {
if (state->remainingChars) {
@@ -452,12 +548,12 @@ char *QUtf8::convertFromUnicode(char *out, QStringView in, QStringConverter::Sta
}
while (src != end) {
- const ushort *nextAscii = end;
+ const char16_t *nextAscii = end;
if (simdEncodeAscii(cursor, nextAscii, src, end))
break;
do {
- ushort uc = *src++;
+ char16_t uc = *src++;
int res = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, cursor, src, end);
if (Q_LIKELY(res >= 0))
continue;
@@ -482,7 +578,22 @@ char *QUtf8::convertFromUnicode(char *out, QStringView in, QStringConverter::Sta
return reinterpret_cast<char *>(cursor);
}
-QString QUtf8::convertToUnicode(const char *chars, qsizetype len)
+char *QUtf8::convertFromLatin1(char *out, QLatin1StringView in)
+{
+ // ### SIMD-optimize:
+ for (uchar ch : in) {
+ if (ch < 128) {
+ *out++ = ch;
+ } else {
+ // as per https://en.wikipedia.org/wiki/UTF-8#Encoding, 2nd row
+ *out++ = 0b110'0'0000u | (ch >> 6);
+ *out++ = 0b10'00'0000u | (ch & 0b0011'1111);
+ }
+ }
+ return out;
+}
+
+QString QUtf8::convertToUnicode(QByteArrayView in)
{
// UTF-8 to UTF-16 always needs the exact same number of words or less:
// UTF-8 UTF-16
@@ -496,21 +607,21 @@ QString QUtf8::convertToUnicode(const char *chars, qsizetype len)
//
// The table holds for invalid sequences too: we'll insert one replacement char
// per invalid byte.
- QString result(len, Qt::Uninitialized);
+ QString result(in.size(), Qt::Uninitialized);
QChar *data = const_cast<QChar*>(result.constData()); // we know we're not shared
- const QChar *end = convertToUnicode(data, chars, len);
+ const QChar *end = convertToUnicode(data, in);
result.truncate(end - data);
return result;
}
-/*!
- \since 5.7
+/*! \internal
+ \since 6.6
\overload
- Converts the UTF-8 sequence of \a len octets beginning at \a chars to
- a sequence of QChar starting at \a buffer. The buffer is expected to be
- large enough to hold the result. An upper bound for the size of the
- buffer is \a len QChars.
+ Converts the UTF-8 sequence of bytes viewed by \a in to a sequence of
+ QChar starting at \a dst in the destination buffer. The buffer is expected
+ to be large enough to hold the result. An upper bound for the size of the
+ buffer is \c in.size() QChars.
If, during decoding, an error occurs, a QChar::ReplacementCharacter is
written.
@@ -518,20 +629,22 @@ QString QUtf8::convertToUnicode(const char *chars, qsizetype len)
Returns a pointer to one past the last QChar written.
This function never throws.
-*/
-QChar *QUtf8::convertToUnicode(QChar *buffer, const char *chars, qsizetype len) noexcept
+ For QChar buffers, instead of casting manually, you can use the static
+ QUtf8::convertToUnicode(QChar *, QByteArrayView) directly.
+*/
+char16_t *QUtf8::convertToUnicode(char16_t *dst, QByteArrayView in) noexcept
{
- ushort *dst = reinterpret_cast<ushort *>(buffer);
- const uchar *src = reinterpret_cast<const uchar *>(chars);
- const uchar *end = src + len;
+ const uchar *const start = reinterpret_cast<const uchar *>(in.data());
+ const uchar *src = start;
+ const uchar *end = src + in.size();
// attempt to do a full decoding in SIMD
const uchar *nextAscii = end;
if (!simdDecodeAscii(dst, nextAscii, src, end)) {
// at least one non-ASCII entry
// check if we failed to decode the UTF-8 BOM; if so, skip it
- if (Q_UNLIKELY(src == reinterpret_cast<const uchar *>(chars))
+ if (Q_UNLIKELY(src == start)
&& end - src >= 3
&& Q_UNLIKELY(src[0] == utf8bom[0] && src[1] == utf8bom[1] && src[2] == utf8bom[2])) {
src += 3;
@@ -544,7 +657,7 @@ QChar *QUtf8::convertToUnicode(QChar *buffer, const char *chars, qsizetype len)
do {
uchar b = *src++;
- int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, dst, src, end);
+ const qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, dst, src, end);
if (res < 0) {
// decoding error
*dst++ = QChar::ReplacementCharacter;
@@ -553,10 +666,10 @@ QChar *QUtf8::convertToUnicode(QChar *buffer, const char *chars, qsizetype len)
}
}
- return reinterpret_cast<QChar *>(dst);
+ return dst;
}
-QString QUtf8::convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state)
+QString QUtf8::convertToUnicode(QByteArrayView in, QStringConverter::State *state)
{
// See above for buffer requirements for stateless decoding. However, that
// fails if the state is not empty. The following situations can add to the
@@ -568,28 +681,29 @@ QString QUtf8::convertToUnicode(const char *chars, qsizetype len, QStringConvert
// 1 of 2 bytes invalid continuation +1 (need to insert replacement and restart)
// 2 of 3 bytes same +1 (same)
// 3 of 4 bytes same +1 (same)
- QString result(len + 1, Qt::Uninitialized);
- QChar *end = convertToUnicode(result.data(), chars, len, state);
+ QString result(in.size() + 1, Qt::Uninitialized);
+ QChar *end = convertToUnicode(result.data(), in, state);
result.truncate(end - result.constData());
return result;
}
-QChar *QUtf8::convertToUnicode(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state)
+char16_t *QUtf8::convertToUnicode(char16_t *dst, QByteArrayView in, QStringConverter::State *state)
{
+ qsizetype len = in.size();
+
Q_ASSERT(state);
if (!len)
- return out;
+ return dst;
- ushort replacement = QChar::ReplacementCharacter;
+ char16_t replacement = QChar::ReplacementCharacter;
if (state->flags & QStringConverter::Flag::ConvertInvalidToNull)
replacement = QChar::Null;
- int res;
+ qsizetype res;
uchar ch = 0;
- ushort *dst = reinterpret_cast<ushort *>(out);
- const uchar *src = reinterpret_cast<const uchar *>(chars);
+ const uchar *src = reinterpret_cast<const uchar *>(in.data());
const uchar *end = src + len;
if (!(state->flags & QStringConverter::Flag::Stateless)) {
@@ -616,7 +730,7 @@ QChar *QUtf8::convertToUnicode(QChar *out, const char *chars, qsizetype len, QSt
// copy to our state and return
state->remainingChars = remainingCharsCount + newCharsToCopy;
memcpy(&state->state_data[0], remainingCharsData, state->remainingChars);
- return out;
+ return dst;
} else if (!headerdone) {
// eat the UTF-8 BOM
if (dst[-1] == 0xfeff)
@@ -672,20 +786,20 @@ QChar *QUtf8::convertToUnicode(QChar *out, const char *chars, qsizetype len, QSt
state->remainingChars = 0;
}
- return reinterpret_cast<QChar *>(dst);
+ return dst;
}
struct QUtf8NoOutputTraits : public QUtf8BaseTraitsNoAscii
{
struct NoOutput {};
- static void appendUtf16(const NoOutput &, ushort) {}
- static void appendUcs4(const NoOutput &, uint) {}
+ static void appendUtf16(const NoOutput &, char16_t) {}
+ static void appendUcs4(const NoOutput &, char32_t) {}
};
-QUtf8::ValidUtf8Result QUtf8::isValidUtf8(const char *chars, qsizetype len)
+QUtf8::ValidUtf8Result QUtf8::isValidUtf8(QByteArrayView in)
{
- const uchar *src = reinterpret_cast<const uchar *>(chars);
- const uchar *end = src + len;
+ const uchar *src = reinterpret_cast<const uchar *>(in.data());
+ const uchar *end = src + in.size();
const uchar *nextAscii = src;
bool isValidAscii = true;
@@ -702,7 +816,7 @@ QUtf8::ValidUtf8Result QUtf8::isValidUtf8(const char *chars, qsizetype len)
isValidAscii = false;
QUtf8NoOutputTraits::NoOutput output;
- int res = QUtf8Functions::fromUtf8<QUtf8NoOutputTraits>(b, output, src, end);
+ const qsizetype res = QUtf8Functions::fromUtf8<QUtf8NoOutputTraits>(b, output, src, end);
if (res < 0) {
// decoding error
return { false, false };
@@ -713,49 +827,113 @@ QUtf8::ValidUtf8Result QUtf8::isValidUtf8(const char *chars, qsizetype len)
return { true, isValidAscii };
}
-int QUtf8::compareUtf8(const char *utf8, qsizetype u8len, const QChar *utf16, qsizetype u16len)
+int QUtf8::compareUtf8(QByteArrayView utf8, QStringView utf16, Qt::CaseSensitivity cs) noexcept
{
- uint uc1, uc2;
- auto src1 = reinterpret_cast<const uchar *>(utf8);
- auto end1 = src1 + u8len;
- QStringIterator src2(utf16, utf16 + u16len);
+ auto src1 = reinterpret_cast<const qchar8_t *>(utf8.data());
+ auto end1 = src1 + utf8.size();
+ auto src2 = reinterpret_cast<const char16_t *>(utf16.data());
+ auto end2 = src2 + utf16.size();
+
+ do {
+ simdCompareAscii(src1, end1, src2, end2);
+
+ if (src1 < end1 && src2 < end2) {
+ char32_t uc1 = *src1++;
+ char32_t uc2 = *src2++;
+
+ if (uc1 >= 0x80) {
+ char32_t *output = &uc1;
+ qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraitsNoAscii>(uc1, output, src1, end1);
+ if (res < 0) {
+ // decoding error
+ uc1 = QChar::ReplacementCharacter;
+ }
- while (src1 < end1 && src2.hasNext()) {
+ // Only decode the UTF-16 surrogate pair if the UTF-8 code point
+ // wasn't US-ASCII (a surrogate cannot match US-ASCII).
+ if (QChar::isHighSurrogate(uc2) && src2 < end2 && QChar::isLowSurrogate(*src2))
+ uc2 = QChar::surrogateToUcs4(uc2, *src2++);
+ }
+ if (cs == Qt::CaseInsensitive) {
+ uc1 = QChar::toCaseFolded(uc1);
+ uc2 = QChar::toCaseFolded(uc2);
+ }
+ if (uc1 != uc2)
+ return int(uc1) - int(uc2);
+ }
+ } while (src1 < end1 && src2 < end2);
+
+ // the shorter string sorts first
+ return (end1 > src1) - int(end2 > src2);
+}
+
+int QUtf8::compareUtf8(QByteArrayView utf8, QLatin1StringView s, Qt::CaseSensitivity cs)
+{
+ char32_t uc1 = QChar::Null;
+ auto src1 = reinterpret_cast<const uchar *>(utf8.data());
+ auto end1 = src1 + utf8.size();
+ auto src2 = reinterpret_cast<const uchar *>(s.latin1());
+ auto end2 = src2 + s.size();
+
+ while (src1 < end1 && src2 < end2) {
uchar b = *src1++;
- uint *output = &uc1;
- int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src1, end1);
+ char32_t *output = &uc1;
+ const qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src1, end1);
if (res < 0) {
// decoding error
uc1 = QChar::ReplacementCharacter;
}
- uc2 = src2.next();
+ char32_t uc2 = *src2++;
+ if (cs == Qt::CaseInsensitive) {
+ uc1 = QChar::toCaseFolded(uc1);
+ uc2 = QChar::toCaseFolded(uc2);
+ }
if (uc1 != uc2)
return int(uc1) - int(uc2);
}
// the shorter string sorts first
- return (end1 > src1) - int(src2.hasNext());
+ return (end1 > src1) - (end2 > src2);
}
-int QUtf8::compareUtf8(const char *utf8, qsizetype u8len, QLatin1String s)
+int QUtf8::compareUtf8(QByteArrayView lhs, QByteArrayView rhs, Qt::CaseSensitivity cs) noexcept
{
- uint uc1;
- auto src1 = reinterpret_cast<const uchar *>(utf8);
- auto end1 = src1 + u8len;
- auto src2 = reinterpret_cast<const uchar *>(s.latin1());
- auto end2 = src2 + s.size();
+ if (lhs.isEmpty())
+ return qt_lencmp(0, rhs.size());
+
+ if (cs == Qt::CaseSensitive) {
+ const auto l = std::min(lhs.size(), rhs.size());
+ int r = memcmp(lhs.data(), rhs.data(), l);
+ return r ? r : qt_lencmp(lhs.size(), rhs.size());
+ }
+
+ char32_t uc1 = QChar::Null;
+ auto src1 = reinterpret_cast<const uchar *>(lhs.data());
+ auto end1 = src1 + lhs.size();
+ char32_t uc2 = QChar::Null;
+ auto src2 = reinterpret_cast<const uchar *>(rhs.data());
+ auto end2 = src2 + rhs.size();
while (src1 < end1 && src2 < end2) {
uchar b = *src1++;
- uint *output = &uc1;
- int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src1, end1);
+ char32_t *output = &uc1;
+ qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src1, end1);
if (res < 0) {
// decoding error
uc1 = QChar::ReplacementCharacter;
}
- uint uc2 = *src2++;
+ b = *src2++;
+ output = &uc2;
+ res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, output, src2, end2);
+ if (res < 0) {
+ // decoding error
+ uc2 = QChar::ReplacementCharacter;
+ }
+
+ uc1 = QChar::toCaseFolded(uc1);
+ uc2 = QChar::toCaseFolded(uc2);
if (uc1 != uc2)
return int(uc1) - int(uc2);
}
@@ -764,16 +942,17 @@ int QUtf8::compareUtf8(const char *utf8, qsizetype u8len, QLatin1String s)
return (end1 > src1) - (end2 > src2);
}
-QByteArray QUtf16::convertFromUnicode(const QChar *uc, qsizetype len, QStringConverter::State *state, DataEndianness endian)
+#ifndef QT_BOOTSTRAPPED
+QByteArray QUtf16::convertFromUnicode(QStringView in, QStringConverter::State *state, DataEndianness endian)
{
bool writeBom = !(state->internalState & HeaderDone) && state->flags & QStringConverter::Flag::WriteBom;
- qsizetype length = 2*len;
+ qsizetype length = 2 * in.size();
if (writeBom)
length += 2;
QByteArray d(length, Qt::Uninitialized);
- char *end = convertFromUnicode(d.data(), QStringView(uc, len), state, endian);
- Q_ASSERT(end - d.constData() == d.length());
+ char *end = convertFromUnicode(d.data(), in, state, endian);
+ Q_ASSERT(end - d.constData() == d.size());
Q_UNUSED(end);
return d;
}
@@ -787,6 +966,7 @@ char *QUtf16::convertFromUnicode(char *out, QStringView in, QStringConverter::St
endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
if (writeBom) {
+ // set them up the BOM
QChar bom(QChar::ByteOrderMark);
if (endian == BigEndianness)
qToBigEndian(bom.unicode(), out);
@@ -795,25 +975,28 @@ char *QUtf16::convertFromUnicode(char *out, QStringView in, QStringConverter::St
out += 2;
}
if (endian == BigEndianness)
- qToBigEndian<ushort>(in.data(), in.length(), out);
+ qToBigEndian<char16_t>(in.data(), in.size(), out);
else
- qToLittleEndian<ushort>(in.data(), in.length(), out);
+ qToLittleEndian<char16_t>(in.data(), in.size(), out);
state->remainingChars = 0;
state->internalState |= HeaderDone;
- return out + 2*in.length();
+ return out + 2*in.size();
}
-QString QUtf16::convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian)
+QString QUtf16::convertToUnicode(QByteArrayView in, QStringConverter::State *state, DataEndianness endian)
{
- QString result((len + 1) >> 1, Qt::Uninitialized); // worst case
- QChar *qch = convertToUnicode(result.data(), chars, len, state, endian);
+ QString result((in.size() + 1) >> 1, Qt::Uninitialized); // worst case
+ QChar *qch = convertToUnicode(result.data(), in, state, endian);
result.truncate(qch - result.constData());
return result;
}
-QChar *QUtf16::convertToUnicode(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian)
+QChar *QUtf16::convertToUnicode(QChar *out, QByteArrayView in, QStringConverter::State *state, DataEndianness endian)
{
+ qsizetype len = in.size();
+ const char *chars = in.data();
+
Q_ASSERT(state);
if (endian == DetectEndianness)
@@ -846,6 +1029,7 @@ QChar *QUtf16::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
state->internalState |= HeaderDone;
QChar ch(buf, *chars++);
if (endian == DetectEndianness) {
+ // someone set us up the BOM
if (ch == QChar::ByteOrderSwapped) {
endian = BigEndianness;
} else if (ch == QChar::ByteOrderMark) {
@@ -866,11 +1050,11 @@ QChar *QUtf16::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
}
- int nPairs = (end - chars) >> 1;
+ qsizetype nPairs = (end - chars) >> 1;
if (endian == BigEndianness)
- qFromBigEndian<ushort>(chars, nPairs, out);
+ qFromBigEndian<char16_t>(chars, nPairs, out);
else
- qFromLittleEndian<ushort>(chars, nPairs, out);
+ qFromLittleEndian<char16_t>(chars, nPairs, out);
out += nPairs;
state->state_data[Endian] = endian;
@@ -889,16 +1073,15 @@ QChar *QUtf16::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
return out;
}
-QByteArray QUtf32::convertFromUnicode(const QChar *uc, qsizetype len, QStringConverter::State *state, DataEndianness endian)
+QByteArray QUtf32::convertFromUnicode(QStringView in, QStringConverter::State *state, DataEndianness endian)
{
bool writeBom = !(state->internalState & HeaderDone) && state->flags & QStringConverter::Flag::WriteBom;
- int length = 4*len;
+ qsizetype length = 4*in.size();
if (writeBom)
length += 4;
QByteArray ba(length, Qt::Uninitialized);
- char *end = convertFromUnicode(ba.data(), QStringView(uc, len), state, endian);
- Q_ASSERT(end - ba.constData() == length);
- Q_UNUSED(end);
+ char *end = convertFromUnicode(ba.data(), in, state, endian);
+ ba.truncate(end - ba.constData());
return ba;
}
@@ -907,14 +1090,11 @@ char *QUtf32::convertFromUnicode(char *out, QStringView in, QStringConverter::St
Q_ASSERT(state);
bool writeBom = !(state->internalState & HeaderDone) && state->flags & QStringConverter::Flag::WriteBom;
- qsizetype length = 4*in.length();
- if (writeBom)
- length += 4;
-
if (endian == DetectEndianness)
endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness;
if (writeBom) {
+ // set them up the BOM
if (endian == BigEndianness) {
out[0] = 0;
out[1] = 0;
@@ -931,11 +1111,13 @@ char *QUtf32::convertFromUnicode(char *out, QStringView in, QStringConverter::St
}
const QChar *uc = in.data();
- const QChar *end = in.data() + in.length();
+ const QChar *end = in.data() + in.size();
QChar ch;
- uint ucs4;
+ char32_t ucs4;
if (state->remainingChars == 1) {
- ch = state->state_data[Data];
+ auto character = state->state_data[Data];
+ Q_ASSERT(character <= 0xFFFF);
+ ch = QChar(character);
// this is ugly, but shortcuts a whole lot of logic that would otherwise be required
state->remainingChars = 0;
goto decode_surrogate;
@@ -973,17 +1155,20 @@ decode_surrogate:
return out;
}
-QString QUtf32::convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian)
+QString QUtf32::convertToUnicode(QByteArrayView in, QStringConverter::State *state, DataEndianness endian)
{
QString result;
- result.resize((len + 7) >> 1); // worst case
- QChar *end = convertToUnicode(result.data(), chars, len, state, endian);
+ result.resize((in.size() + 7) >> 1); // worst case
+ QChar *end = convertToUnicode(result.data(), in, state, endian);
result.truncate(end - result.constData());
return result;
}
-QChar *QUtf32::convertToUnicode(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian)
+QChar *QUtf32::convertToUnicode(QChar *out, QByteArrayView in, QStringConverter::State *state, DataEndianness endian)
{
+ qsizetype len = in.size();
+ const char *chars = in.data();
+
Q_ASSERT(state);
if (endian == DetectEndianness)
endian = (DataEndianness)state->state_data[Endian];
@@ -1011,13 +1196,14 @@ QChar *QUtf32::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
if (state->flags & QStringConverter::Flag::ConvertInitialBom)
headerdone = true;
- int num = state->remainingChars;
+ qsizetype num = state->remainingChars;
state->remainingChars = 0;
if (!headerdone || endian == DetectEndianness || num) {
while (num < 4)
tuple[num++] = *chars++;
if (endian == DetectEndianness) {
+ // someone set us up the BOM?
if (tuple[0] == 0xff && tuple[1] == 0xfe && tuple[2] == 0 && tuple[3] == 0) {
endian = LittleEndianness;
} else if (tuple[0] == 0 && tuple[1] == 0 && tuple[2] == 0xfe && tuple[3] == 0xff) {
@@ -1028,7 +1214,7 @@ QChar *QUtf32::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
endian = LittleEndianness;
}
}
- uint code = (endian == BigEndianness) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple);
+ char32_t code = (endian == BigEndianness) ? qFromBigEndian<char32_t>(tuple) : qFromLittleEndian<char32_t>(tuple);
if (headerdone || code != QChar::ByteOrderMark) {
if (QChar::requiresSurrogates(code)) {
*out++ = QChar(QChar::highSurrogate(code));
@@ -1047,7 +1233,7 @@ QChar *QUtf32::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
while (chars < end) {
tuple[num++] = *chars++;
if (num == 4) {
- uint code = (endian == BigEndianness) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple);
+ char32_t code = (endian == BigEndianness) ? qFromBigEndian<char32_t>(tuple) : qFromLittleEndian<char32_t>(tuple);
for (char16_t c : QChar::fromUcs4(code))
*out++ = c;
num = 0;
@@ -1066,205 +1252,378 @@ QChar *QUtf32::convertToUnicode(QChar *out, const char *chars, qsizetype len, QS
return out;
}
+#endif // !QT_BOOTSTRAPPED
-QString qFromUtfEncoded(const QByteArray &ba)
+#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
+int QLocal8Bit::checkUtf8()
{
- const qsizetype arraySize = ba.size();
- const uchar *buf = reinterpret_cast<const uchar *>(ba.constData());
- const uint bom = 0xfeff;
-
- if (arraySize > 3) {
- uint uc = qFromUnaligned<uint>(buf);
- if (uc == qToBigEndian(bom) || uc == qToLittleEndian(bom))
- return QUtf32::convertToUnicode(ba.constData(), ba.length(), nullptr); // utf-32
- }
+ return GetACP() == CP_UTF8 ? 1 : -1;
+}
- if (arraySize > 1) {
- ushort uc = qFromUnaligned<ushort>(buf);
- if (uc == qToBigEndian(ushort(bom)) || qToLittleEndian(ushort(bom)))
- return QUtf16::convertToUnicode(ba.constData(), ba.length(), nullptr); // utf-16
- }
- return QUtf8::convertToUnicode(ba.constData(), ba.length());
+QString QLocal8Bit::convertToUnicode_sys(QByteArrayView in, QStringConverter::State *state)
+{
+ return convertToUnicode_sys(in, CP_ACP, state);
}
-#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
-static QString convertToUnicodeCharByChar(const char *chars, qsizetype length, QStringConverter::State *state)
+QString QLocal8Bit::convertToUnicode_sys(QByteArrayView in, quint32 codePage,
+ QStringConverter::State *state)
{
+ const char *mb = in.data();
+ qsizetype mblen = in.size();
+
Q_ASSERT(state);
- if (state->flags & QStringConverter::Flag::Stateless) // temporary
+ qsizetype &invalidChars = state->invalidChars;
+ using Flag = QStringConverter::Flag;
+ const bool useNullForReplacement = !!(state->flags & Flag::ConvertInvalidToNull);
+ const char16_t replacementCharacter = useNullForReplacement ? QChar::Null
+ : QChar::ReplacementCharacter;
+ if (state->flags & Flag::Stateless) {
+ Q_ASSERT(state->remainingChars == 0);
state = nullptr;
-
- if (!chars || !length)
- return QString();
-
- int copyLocation = 0;
- int extra = 2;
- if (state && state->remainingChars) {
- copyLocation = state->remainingChars;
- extra += copyLocation;
- }
- int newLength = length + extra;
- char *mbcs = new char[newLength];
- //ensure that we have a NULL terminated string
- mbcs[newLength-1] = 0;
- mbcs[newLength-2] = 0;
- memcpy(&(mbcs[copyLocation]), chars, length);
- if (copyLocation) {
- //copy the last character from the state
- mbcs[0] = (char)state->state_data[0];
- state->remainingChars = 0;
- }
- const char *mb = mbcs;
- const char *next = 0;
- QString s;
- while ((next = CharNextExA(CP_ACP, mb, 0)) != mb) {
- wchar_t wc[2] ={0};
- int charlength = next - mb;
- int len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, mb, charlength, wc, 2);
- if (len>0) {
- s.append(QChar(wc[0]));
- } else {
- int r = GetLastError();
- //check if the character being dropped is the last character
- if (r == ERROR_NO_UNICODE_TRANSLATION && mb == (mbcs+newLength -3) && state) {
- state->remainingChars = 1;
- state->state_data[0] = (char)*mb;
- }
- }
- mb = next;
}
- delete [] mbcs;
- return s;
-}
-
-
-QString QLocal8Bit::convertToUnicode(const char *chars, qsizetype length, QStringConverter::State *state)
-{
- Q_ASSERT(length < INT_MAX); // ### FIXME
- const char *mb = chars;
- int mblen = length;
if (!mb || !mblen)
return QString();
- QVarLengthArray<wchar_t, 4096> wc(4096);
- int len;
+ // Use a local stack-buffer at first to allow us a decently large container
+ // to avoid a lot of resizing, without also returning an overallocated
+ // QString to the user for small strings.
+ // Then we can be fast for small strings and take the hit of extra resizes
+ // and measuring how much storage is needed for large strings.
+ std::array<wchar_t, 4096> buf;
+ wchar_t *out = buf.data();
+ qsizetype outlen = buf.size();
+
QString sp;
- bool prepend = false;
- char state_data = 0;
- int remainingChars = 0;
-
- //save the current state information
- if (state) {
- state_data = (char)state->state_data[0];
- remainingChars = state->remainingChars;
- }
- //convert the pending character (if available)
- if (state && remainingChars) {
- char prev[3] = {0};
- prev[0] = state_data;
- prev[1] = mb[0];
- remainingChars = 0;
- len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
- prev, 2, wc.data(), wc.length());
- if (len) {
- sp.append(QChar(wc[0]));
- if (mblen == 1) {
- state->remainingChars = 0;
- return sp;
- }
- prepend = true;
- mb++;
- mblen--;
- wc[0] = 0;
+ // Return a pointer to storage where we have enough space for `size`
+ const auto growOut = [&](qsizetype size) -> std::tuple<wchar_t *, qsizetype> {
+ if (outlen >= size)
+ return {out, outlen};
+ const bool wasStackBuffer = sp.isEmpty();
+ const auto begin = wasStackBuffer ? buf.data() : reinterpret_cast<wchar_t *>(sp.data());
+ const qsizetype offset = qsizetype(std::distance(begin, out));
+ qsizetype newSize = 0;
+ if (Q_UNLIKELY(qAddOverflow(offset, size, &newSize))) {
+ Q_CHECK_PTR(false);
+ return {nullptr, 0};
}
+ sp.resize(newSize);
+ auto it = reinterpret_cast<wchar_t *>(sp.data());
+ if (wasStackBuffer)
+ it = std::copy_n(buf.data(), offset, it);
+ else
+ it += offset;
+ return {it, size};
+ };
+
+ // Convert the pending characters (if available)
+ while (state && state->remainingChars && mblen) {
+ QStringConverter::State localState;
+ localState.flags = state->flags;
+ // Use at most 6 characters as a guess for the longest encoded character
+ // in any multibyte encoding.
+ // Even with a total of 2 bytes of overhead that would leave around
+ // 2^(4 * 8) possible characters
+ std::array<char, 6> prev = {0};
+ Q_ASSERT(state->remainingChars <= q20::ssize(state->state_data));
+ qsizetype index = 0;
+ for (; index < state->remainingChars; ++index)
+ prev[index] = state->state_data[index];
+ const qsizetype toCopy = std::min(q20::ssize(prev) - index, mblen);
+ for (qsizetype i = 0; i < toCopy; ++i, ++index)
+ prev[index] = mb[i];
+ mb += toCopy;
+ mblen -= toCopy;
+
+ // Recursing:
+ // Since we are using a clean local state it will try to decode what was
+ // stored in our state + some extra octets from input (`prev`). If some
+ // part fails we will have those characters stored in the local state's
+ // storage, and we can extract those. It may also output some
+ // replacement characters, which we'll count in the invalidChars.
+ // In the best case we only do this once, but we will loop until we have
+ // resolved all the remaining characters or we have run out of new input
+ // in which case we may still have remaining characters.
+ const QString tmp = convertToUnicode_sys(QByteArrayView(prev.data(), index), codePage,
+ &localState);
+ std::tie(out, outlen) = growOut(tmp.size());
+ if (!out)
+ return {};
+ out = std::copy_n(reinterpret_cast<const wchar_t *>(tmp.constData()), tmp.size(), out);
+ outlen -= tmp.size();
+ const qsizetype tail = toCopy - localState.remainingChars;
+ if (tail >= 0) {
+ // Everything left to process comes from `in`, so we can stop
+ // looping. Adjust the window for `in` and unset remainingChars to
+ // signal that we're done.
+ mb -= localState.remainingChars;
+ mblen += localState.remainingChars;
+ localState.remainingChars = 0;
+ }
+ state->remainingChars = localState.remainingChars;
+ state->invalidChars += localState.invalidChars;
+ std::copy_n(localState.state_data, state->remainingChars, state->state_data);
}
- while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
- mb, mblen, wc.data(), wc.length()))) {
- int r = GetLastError();
- if (r == ERROR_INSUFFICIENT_BUFFER) {
- const int wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
- mb, mblen, 0, 0);
- wc.resize(wclen);
- } else if (r == ERROR_NO_UNICODE_TRANSLATION) {
- //find the last non NULL character
- while (mblen > 1 && !(mb[mblen-1]))
- mblen--;
- //check whether, we hit an invalid character in the middle
- if ((mblen <= 1) || (remainingChars && state_data))
- return convertToUnicodeCharByChar(chars, length, state);
- //Remove the last character and try again...
- state_data = mb[mblen-1];
- remainingChars = 1;
- mblen--;
+ Q_ASSERT(!state || state->remainingChars == 0 || mblen == 0);
+
+ // Need it in this scope, since we try to decrease our window size if we
+ // encounter an error
+ int nextIn = qt_saturate<int>(mblen);
+ while (mblen > 0) {
+ std::tie(out, outlen) = growOut(1); // Need space for at least one character
+ if (!out)
+ return {};
+ const int nextOut = qt_saturate<int>(outlen);
+ int len = MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, mb, nextIn, out, nextOut);
+ if (len) {
+ mb += nextIn;
+ mblen -= nextIn;
+ out += len;
+ outlen -= len;
} else {
- // Fail.
- qWarning("MultiByteToWideChar: Cannot convert multibyte text");
- break;
+ int r = GetLastError();
+ if (r == ERROR_INSUFFICIENT_BUFFER) {
+ const int wclen = MultiByteToWideChar(codePage, 0, mb, nextIn, 0, 0);
+ std::tie(out, outlen) = growOut(wclen);
+ if (!out)
+ return {};
+ } else if (r == ERROR_NO_UNICODE_TRANSLATION) {
+ // Can't decode the current window, so either store the state,
+ // reduce window size or output a replacement character.
+
+ // Check if we can store all remaining characters in the state
+ // to be used next time we're called:
+ if (state && mblen <= q20::ssize(state->state_data)) {
+ state->remainingChars = mblen;
+ std::copy_n(mb, mblen, state->state_data);
+ mb += mblen;
+ mblen = 0;
+ break;
+ }
+
+ // .. if not, try to find the last valid character in the window
+ // and try again with a shrunken window:
+ if (nextIn > 1) {
+ // There may be some incomplete data at the end of our current
+ // window, so decrease the window size and try again.
+ // In the worst case scenario there is gigs of undecodable
+ // garbage, but what are we supposed to do about that?
+ const auto it = CharPrevExA(codePage, mb, mb + nextIn, 0);
+ if (it != mb)
+ nextIn = int(it - mb);
+ else
+ --nextIn;
+ continue;
+ }
+
+ // Finally, we are forced to output a replacement character for
+ // the first byte in the window:
+ std::tie(out, outlen) = growOut(1);
+ if (!out)
+ return {};
+ *out = replacementCharacter;
+ ++invalidChars;
+ ++out;
+ --outlen;
+ ++mb;
+ --mblen;
+ } else {
+ // Fail.
+ qWarning("MultiByteToWideChar: Cannot convert multibyte text");
+ break;
+ }
}
+ nextIn = qt_saturate<int>(mblen);
}
- if (len <= 0)
- return QString();
+ if (sp.isEmpty()) {
+ // We must have only used the stack buffer
+ if (out != buf.data()) // else: we return null-string
+ sp = QStringView(buf.data(), out).toString();
+ } else{
+ const auto begin = reinterpret_cast<wchar_t *>(sp.data());
+ sp.truncate(std::distance(begin, out));
+ }
- if (wc[len-1] == 0) // len - 1: we don't want terminator
- --len;
+ if (sp.size() && sp.back().isNull())
+ sp.chop(1);
- //save the new state information
- if (state) {
- state->state_data[0] = (char)state_data;
- state->remainingChars = remainingChars;
+ if (!state && mblen > 0) {
+ // We have trailing character(s) that could not be converted, and
+ // nowhere to cache them
+ sp.resize(sp.size() + mblen, replacementCharacter);
+ invalidChars += mblen;
}
- QString s((QChar*)wc.data(), len);
- if (prepend) {
- return sp+s;
- }
- return s;
+ return sp;
+}
+
+QByteArray QLocal8Bit::convertFromUnicode_sys(QStringView in, QStringConverter::State *state)
+{
+ return convertFromUnicode_sys(in, CP_ACP, state);
}
-QByteArray QLocal8Bit::convertFromUnicode(const QChar *ch, qsizetype uclen, QStringConverter::State *state)
+QByteArray QLocal8Bit::convertFromUnicode_sys(QStringView in, quint32 codePage,
+ QStringConverter::State *state)
{
- Q_ASSERT(uclen < INT_MAX); // ### FIXME
+ const wchar_t *ch = reinterpret_cast<const wchar_t *>(in.data());
+ qsizetype uclen = in.size();
+
Q_ASSERT(state);
- Q_UNUSED(state); // ### Fixme
- if (state->flags & QStringConverter::Flag::Stateless) // temporary
+ // The Windows API has a *boolean* out-parameter that says if a replacement
+ // character was used, but it gives us no way to know _how many_ were used.
+ // Since we cannot simply scan the string for replacement characters
+ // (which is potentially a question mark, and thus a valid character),
+ // we simply do not track the number of invalid characters here.
+ // auto &invalidChars = state->invalidChars;
+
+ using Flag = QStringConverter::Flag;
+ if (state->flags & Flag::Stateless) { // temporary
+ Q_ASSERT(state->remainingChars == 0);
state = nullptr;
+ }
if (!ch)
return QByteArray();
if (uclen == 0)
return QByteArray("");
- BOOL used_def;
- QByteArray mb(4096, 0);
- int len;
- while (!(len=WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)ch, uclen,
- mb.data(), mb.size()-1, 0, &used_def)))
- {
- int r = GetLastError();
- if (r == ERROR_INSUFFICIENT_BUFFER) {
- mb.resize(1+WideCharToMultiByte(CP_ACP, 0,
- (const wchar_t*)ch, uclen,
- 0, 0, 0, &used_def));
- // and try again...
+
+ // Use a local stack-buffer at first to allow us a decently large container
+ // to avoid a lot of resizing, without also returning an overallocated
+ // QByteArray to the user for small strings.
+ // Then we can be fast for small strings and take the hit of extra resizes
+ // and measuring how much storage is needed for large strings.
+ std::array<char, 4096> buf;
+ char *out = buf.data();
+ qsizetype outlen = buf.size();
+ QByteArray mb;
+
+ if (state && state->remainingChars > 0) {
+ Q_ASSERT(state->remainingChars == 1);
+ // Let's try to decode the pending character
+ wchar_t wc[2] = { wchar_t(state->state_data[0]), ch[0] };
+ // Check if the second character is a valid low surrogate,
+ // otherwise we'll just decode the first character, for which windows
+ // will output a replacement character.
+ const bool validCodePoint = QChar::isLowSurrogate(wc[1]);
+ int len = WideCharToMultiByte(codePage, 0, wc, validCodePoint ? 2 : 1, out, outlen, nullptr,
+ nullptr);
+ if (!len)
+ return {}; // Cannot recover, and I refuse to believe it was a size limitation
+ out += len;
+ outlen -= len;
+ if (validCodePoint) {
+ ++ch;
+ --uclen;
+ }
+ state->remainingChars = 0;
+ state->state_data[0] = 0;
+ if (uclen == 0)
+ return QByteArrayView(buf.data(), len).toByteArray();
+ }
+
+ if (state && QChar::isHighSurrogate(ch[uclen - 1])) {
+ // We can handle a missing low surrogate at the end of the string,
+ // so if there is one, exclude it now and store it in the state.
+ state->remainingChars = 1;
+ state->state_data[0] = ch[uclen - 1];
+ --uclen;
+ if (uclen == 0)
+ return QByteArray();
+ }
+
+ Q_ASSERT(uclen > 0);
+
+ // Return a pointer to storage where we have enough space for `size`
+ const auto growOut = [&](qsizetype size) -> std::tuple<char *, qsizetype> {
+ if (outlen >= size)
+ return {out, outlen};
+ const bool wasStackBuffer = mb.isEmpty();
+ const auto begin = wasStackBuffer ? buf.data() : mb.data();
+ const qsizetype offset = qsizetype(std::distance(begin, out));
+ qsizetype newSize = 0;
+ if (Q_UNLIKELY(qAddOverflow(offset, size, &newSize))) {
+ Q_CHECK_PTR(false);
+ return {nullptr, 0};
+ }
+ mb.resize(newSize);
+ auto it = mb.data();
+ if (wasStackBuffer)
+ it = std::copy_n(buf.data(), offset, it);
+ else
+ it += offset;
+ return {it, size};
+ };
+
+ const auto getNextWindowSize = [&]() {
+ int nextIn = qt_saturate<int>(uclen);
+ // The Windows API has some issues if the current window ends in the
+ // middle of a surrogate pair, so we avoid that:
+ if (nextIn > 1 && QChar::isHighSurrogate(ch[nextIn - 1]))
+ --nextIn;
+ return nextIn;
+ };
+
+ int len = 0;
+ while (uclen > 0) {
+ const int nextIn = getNextWindowSize();
+ std::tie(out, outlen) = growOut(1); // We need at least one byte
+ if (!out)
+ return {};
+ const int nextOut = qt_saturate<int>(outlen);
+ len = WideCharToMultiByte(codePage, 0, ch, nextIn, out, nextOut, nullptr, nullptr);
+ if (len > 0) {
+ ch += nextIn;
+ uclen -= nextIn;
+ out += len;
+ outlen -= len;
} else {
- // Fail. Probably can't happen in fact (dwFlags is 0).
+ int r = GetLastError();
+ if (r == ERROR_INSUFFICIENT_BUFFER) {
+ int neededLength = WideCharToMultiByte(codePage, 0, ch, nextIn, nullptr, 0,
+ nullptr, nullptr);
+ if (neededLength <= 0) {
+ // Fail. Observed with UTF8 where the input window was max int and ended in an
+ // incomplete sequence, probably a Windows bug. We try to avoid that from
+ // happening by reducing the window size in that case. But let's keep this
+ // branch just in case of other bugs.
+#ifndef QT_NO_DEBUG
+ r = GetLastError();
+ fprintf(stderr,
+ "WideCharToMultiByte: Cannot convert multibyte text (error %d)\n", r);
+#endif // !QT_NO_DEBUG
+ break;
+ }
+ std::tie(out, outlen) = growOut(neededLength);
+ if (!out)
+ return {};
+ // and try again...
+ } else {
+ // Fail. Probably can't happen in fact (dwFlags is 0).
#ifndef QT_NO_DEBUG
- // Can't use qWarning(), as it'll recurse to handle %ls
- fprintf(stderr,
- "WideCharToMultiByte: Cannot convert multibyte text (error %d): %ls\n",
- r, reinterpret_cast<const wchar_t*>(QString(ch, uclen).utf16()));
+ // Can't use qWarning(), as it'll recurse to handle %ls
+ fprintf(stderr,
+ "WideCharToMultiByte: Cannot convert multibyte text (error %d): %ls\n", r,
+ reinterpret_cast<const wchar_t *>(
+ QStringView(ch, uclen).left(100).toString().utf16()));
#endif
- break;
+ break;
+ }
}
}
- mb.resize(len);
+ if (mb.isEmpty()) {
+ // We must have only used the stack buffer
+ if (out != buf.data()) // else: we return null-array
+ mb = QByteArrayView(buf.data(), out).toByteArray();
+ } else {
+ mb.truncate(std::distance(mb.data(), out));
+ }
return mb;
}
#endif
-void QStringConverter::State::clear()
+void QStringConverter::State::clear() noexcept
{
if (clearFn)
clearFn(this);
@@ -1275,9 +1634,25 @@ void QStringConverter::State::clear()
internalState = 0;
}
-static QChar *fromUtf16(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+void QStringConverter::State::reset() noexcept
{
- return QUtf16::convertToUnicode(out, in, length, state, DetectEndianness);
+ if (flags & Flag::UsesIcu) {
+#if QT_CONFIG(icu)
+ UConverter *converter = static_cast<UConverter *>(d[0]);
+ if (converter)
+ ucnv_reset(converter);
+#else
+ Q_UNREACHABLE();
+#endif
+ } else {
+ clear();
+ }
+}
+
+#ifndef QT_BOOTSTRAPPED
+static QChar *fromUtf16(QChar *out, QByteArrayView in, QStringConverter::State *state)
+{
+ return QUtf16::convertToUnicode(out, in, state, DetectEndianness);
}
static char *toUtf16(char *out, QStringView in, QStringConverter::State *state)
@@ -1285,9 +1660,9 @@ static char *toUtf16(char *out, QStringView in, QStringConverter::State *state)
return QUtf16::convertFromUnicode(out, in, state, DetectEndianness);
}
-static QChar *fromUtf16BE(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+static QChar *fromUtf16BE(QChar *out, QByteArrayView in, QStringConverter::State *state)
{
- return QUtf16::convertToUnicode(out, in, length, state, BigEndianness);
+ return QUtf16::convertToUnicode(out, in, state, BigEndianness);
}
static char *toUtf16BE(char *out, QStringView in, QStringConverter::State *state)
@@ -1295,9 +1670,9 @@ static char *toUtf16BE(char *out, QStringView in, QStringConverter::State *state
return QUtf16::convertFromUnicode(out, in, state, BigEndianness);
}
-static QChar *fromUtf16LE(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+static QChar *fromUtf16LE(QChar *out, QByteArrayView in, QStringConverter::State *state)
{
- return QUtf16::convertToUnicode(out, in, length, state, LittleEndianness);
+ return QUtf16::convertToUnicode(out, in, state, LittleEndianness);
}
static char *toUtf16LE(char *out, QStringView in, QStringConverter::State *state)
@@ -1305,9 +1680,9 @@ static char *toUtf16LE(char *out, QStringView in, QStringConverter::State *state
return QUtf16::convertFromUnicode(out, in, state, LittleEndianness);
}
-static QChar *fromUtf32(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+static QChar *fromUtf32(QChar *out, QByteArrayView in, QStringConverter::State *state)
{
- return QUtf32::convertToUnicode(out, in, length, state, DetectEndianness);
+ return QUtf32::convertToUnicode(out, in, state, DetectEndianness);
}
static char *toUtf32(char *out, QStringView in, QStringConverter::State *state)
@@ -1315,9 +1690,9 @@ static char *toUtf32(char *out, QStringView in, QStringConverter::State *state)
return QUtf32::convertFromUnicode(out, in, state, DetectEndianness);
}
-static QChar *fromUtf32BE(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+static QChar *fromUtf32BE(QChar *out, QByteArrayView in, QStringConverter::State *state)
{
- return QUtf32::convertToUnicode(out, in, length, state, BigEndianness);
+ return QUtf32::convertToUnicode(out, in, state, BigEndianness);
}
static char *toUtf32BE(char *out, QStringView in, QStringConverter::State *state)
@@ -1325,37 +1700,26 @@ static char *toUtf32BE(char *out, QStringView in, QStringConverter::State *state
return QUtf32::convertFromUnicode(out, in, state, BigEndianness);
}
-static QChar *fromUtf32LE(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+static QChar *fromUtf32LE(QChar *out, QByteArrayView in, QStringConverter::State *state)
{
- return QUtf32::convertToUnicode(out, in, length, state, LittleEndianness);
+ return QUtf32::convertToUnicode(out, in, state, LittleEndianness);
}
static char *toUtf32LE(char *out, QStringView in, QStringConverter::State *state)
{
return QUtf32::convertFromUnicode(out, in, state, LittleEndianness);
}
+#endif // !QT_BOOTSTRAPPED
-void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept;
-
-static QChar *fromLatin1(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state)
-{
- Q_ASSERT(state);
- Q_UNUSED(state);
-
- qt_from_latin1(reinterpret_cast<char16_t *>(out), chars, size_t(len));
- return out + len;
-}
-
-
-static char *toLatin1(char *out, QStringView in, QStringConverter::State *state)
+char *QLatin1::convertFromUnicode(char *out, QStringView in, QStringConverter::State *state) noexcept
{
Q_ASSERT(state);
if (state->flags & QStringConverter::Flag::Stateless) // temporary
state = nullptr;
const char replacement = (state && state->flags & QStringConverter::Flag::ConvertInvalidToNull) ? 0 : '?';
- int invalid = 0;
- for (qsizetype i = 0; i < in.length(); ++i) {
+ qsizetype invalid = 0;
+ for (qsizetype i = 0; i < in.size(); ++i) {
if (in[i] > QChar(0xff)) {
*out = replacement;
++invalid;
@@ -1369,29 +1733,31 @@ static char *toLatin1(char *out, QStringView in, QStringConverter::State *state)
return out;
}
-static QChar *fromLocal8Bit(QChar *out, const char *in, qsizetype length, QStringConverter::State *state)
+static QChar *fromLocal8Bit(QChar *out, QByteArrayView in, QStringConverter::State *state)
{
- QString s = QLocal8Bit::convertToUnicode(in, length, state);
- memcpy(out, s.constData(), s.length()*sizeof(QChar));
- return out + s.length();
+ QString s = QLocal8Bit::convertToUnicode(in, state);
+ memcpy(out, s.constData(), s.size()*sizeof(QChar));
+ return out + s.size();
}
static char *toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
{
- QByteArray s = QLocal8Bit::convertFromUnicode(in.data(), in.length(), state);
- memcpy(out, s.constData(), s.length());
- return out + s.length();
+ QByteArray s = QLocal8Bit::convertFromUnicode(in, state);
+ memcpy(out, s.constData(), s.size());
+ return out + s.size();
}
static qsizetype fromUtf8Len(qsizetype l) { return l + 1; }
static qsizetype toUtf8Len(qsizetype l) { return 3*(l + 1); }
+#ifndef QT_BOOTSTRAPPED
static qsizetype fromUtf16Len(qsizetype l) { return l/2 + 2; }
static qsizetype toUtf16Len(qsizetype l) { return 2*(l + 1); }
static qsizetype fromUtf32Len(qsizetype l) { return l/2 + 2; }
static qsizetype toUtf32Len(qsizetype l) { return 4*(l + 1); }
+#endif
static qsizetype fromLatin1Len(qsizetype l) { return l + 1; }
static qsizetype toLatin1Len(qsizetype l) { return l + 1; }
@@ -1424,7 +1790,7 @@ static qsizetype toLatin1Len(qsizetype l) { return l + 1; }
operation, encoding UTF-16 encoded data (usually in the form of a QString) to
the requested encoding.
- The supported encodings are:
+ The following encodings are always supported:
\list
\li UTF-8
@@ -1438,6 +1804,10 @@ static qsizetype toLatin1Len(qsizetype l) { return l + 1; }
\li The system encoding
\endlist
+ QStringConverter may support more encodings depending on how Qt was
+ compiled. If more codecs are supported, they can be listed using
+ availableCodecs().
+
\l {QStringConverter}s can be used as follows to convert some encoded
string to and from UTF-16.
@@ -1496,6 +1866,7 @@ static qsizetype toLatin1Len(qsizetype l) { return l + 1; }
\value Stateless Ignore possible converter states between different function calls
to encode or decode strings. This will also cause the QStringConverter to raise an error if an incomplete
sequence of data is encountered.
+ \omitvalue UsesIcu
*/
/*!
@@ -1504,17 +1875,18 @@ static qsizetype toLatin1Len(qsizetype l) { return l + 1; }
\value Utf16 Create a converter to or from UTF-16. When decoding, the byte order will get automatically
detected by a leading byte order mark. If none exists or when encoding, the system byte order will
be assumed.
- \value Utf16BE Create a converter to or from big endian UTF-16.
- \value Utf16LE Create a converter to or from litte endian UTF-16.
+ \value Utf16BE Create a converter to or from big-endian UTF-16.
+ \value Utf16LE Create a converter to or from little-endian UTF-16.
\value Utf32 Create a converter to or from UTF-32. When decoding, the byte order will get automatically
detected by a leading byte order mark. If none exists or when encoding, the system byte order will
be assumed.
- \value Utf32BE Create a converter to or from big endian UTF-32.
- \value Utf32LE Create a converter to or from litte endian UTF-32.
+ \value Utf32BE Create a converter to or from big-endian UTF-32.
+ \value Utf32LE Create a converter to or from little-endian UTF-32.
\value Latin1 Create a converter to or from ISO-8859-1 (Latin1).
\value System Create a converter to or from the underlying encoding of the
operating systems locale. This is always assumed to be UTF-8 for Unix based
systems. On Windows, this converts to and from the locale code page.
+ \omitvalue LastEncoding
*/
/*!
@@ -1525,34 +1897,31 @@ static qsizetype toLatin1Len(qsizetype l) { return l + 1; }
const QStringConverter::Interface QStringConverter::encodingInterfaces[QStringConverter::LastEncoding + 1] =
{
{ "UTF-8", QUtf8::convertToUnicode, fromUtf8Len, QUtf8::convertFromUnicode, toUtf8Len },
+#ifndef QT_BOOTSTRAPPED
{ "UTF-16", fromUtf16, fromUtf16Len, toUtf16, toUtf16Len },
{ "UTF-16LE", fromUtf16LE, fromUtf16Len, toUtf16LE, toUtf16Len },
{ "UTF-16BE", fromUtf16BE, fromUtf16Len, toUtf16BE, toUtf16Len },
{ "UTF-32", fromUtf32, fromUtf32Len, toUtf32, toUtf32Len },
{ "UTF-32LE", fromUtf32LE, fromUtf32Len, toUtf32LE, toUtf32Len },
{ "UTF-32BE", fromUtf32BE, fromUtf32Len, toUtf32BE, toUtf32Len },
- { "ISO-8859-1", fromLatin1, fromLatin1Len, toLatin1, toLatin1Len },
+#endif
+ { "ISO-8859-1", QLatin1::convertToUnicode, fromLatin1Len, QLatin1::convertFromUnicode, toLatin1Len },
{ "Locale", fromLocal8Bit, fromUtf8Len, toLocal8Bit, toUtf8Len }
};
// match names case insensitive and skipping '-' and '_'
static bool nameMatch(const char *a, const char *b)
{
- while (*a && *b) {
- if (*a == '-' || *a == '_') {
+ do {
+ while (*a == '-' || *a == '_')
++a;
- continue;
- }
- if (*b == '-' || *b == '_') {
+ while (*b == '-' || *b == '_')
++b;
- continue;
- }
- if (toupper(*a) != toupper(*b))
- return false;
- ++a;
- ++b;
- }
- return !*a && !*b;
+ if (!*a && !*b) // end of both strings
+ return true;
+ } while (QtMiscUtils::toAsciiLower(*a++) == QtMiscUtils::toAsciiLower(*b++));
+
+ return false;
}
@@ -1566,6 +1935,234 @@ static bool nameMatch(const char *a, const char *b)
\internal
*/
+
+#if QT_CONFIG(icu)
+// only derives from QStringConverter to get access to protected types
+struct QStringConverterICU : QStringConverter
+{
+ static void clear_function(QStringConverterBase::State *state) noexcept
+ {
+ ucnv_close(static_cast<UConverter *>(state->d[0]));
+ state->d[0] = nullptr;
+ }
+
+ static void ensureConverter(QStringConverter::State *state)
+ {
+ // old code might reset the state via clear instead of reset
+ // in that case, the converter has been closed, and we have to reopen it
+ if (state->d[0] == nullptr)
+ state->d[0] = createConverterForName(static_cast<const char *>(state->d[1]), state);
+ }
+
+ static QChar *toUtf16(QChar *out, QByteArrayView in, QStringConverter::State *state)
+ {
+ ensureConverter(state);
+
+ auto icu_conv = static_cast<UConverter *>(state->d[0]);
+ UErrorCode err = U_ZERO_ERROR;
+ auto source = in.data();
+ auto sourceLimit = in.data() + in.size();
+
+ qsizetype length = toLen(in.size());
+
+ UChar *target = reinterpret_cast<UChar *>(out);
+ auto targetLimit = target + length;
+ // We explicitly clean up anyway, so no need to set flush to true,
+ // which would just reset the converter.
+ UBool flush = false;
+
+ // If the QStringConverter was moved, the state that we used as a context is stale now.
+ UConverterToUCallback action;
+ const void *context;
+ ucnv_getToUCallBack(icu_conv, &action, &context);
+ if (context != state)
+ ucnv_setToUCallBack(icu_conv, action, state, nullptr, nullptr, &err);
+
+ ucnv_toUnicode(icu_conv, &target, targetLimit, &source, sourceLimit, nullptr, flush, &err);
+ // We did reserve enough space:
+ Q_ASSERT(err != U_BUFFER_OVERFLOW_ERROR);
+ if (state->flags.testFlag(QStringConverter::Flag::Stateless)) {
+ if (auto leftOver = ucnv_toUCountPending(icu_conv, &err)) {
+ ucnv_reset(icu_conv);
+ state->invalidChars += leftOver;
+ }
+ }
+ return reinterpret_cast<QChar *>(target);
+ }
+
+ static char *fromUtf16(char *out, QStringView in, QStringConverter::State *state)
+ {
+ ensureConverter(state);
+ auto icu_conv = static_cast<UConverter *>(state->d[0]);
+ UErrorCode err = U_ZERO_ERROR;
+ auto source = reinterpret_cast<const UChar *>(in.data());
+ auto sourceLimit = reinterpret_cast<const UChar *>(in.data() + in.size());
+
+ qsizetype length = UCNV_GET_MAX_BYTES_FOR_STRING(in.size(), ucnv_getMaxCharSize(icu_conv));
+
+ char *target = out;
+ char *targetLimit = out + length;
+ UBool flush = false;
+
+ // If the QStringConverter was moved, the state that we used as a context is stale now.
+ UConverterFromUCallback action;
+ const void *context;
+ ucnv_getFromUCallBack(icu_conv, &action, &context);
+ if (context != state)
+ ucnv_setFromUCallBack(icu_conv, action, state, nullptr, nullptr, &err);
+
+ ucnv_fromUnicode(icu_conv, &target, targetLimit, &source, sourceLimit, nullptr, flush, &err);
+ // We did reserve enough space:
+ Q_ASSERT(err != U_BUFFER_OVERFLOW_ERROR);
+ if (state->flags.testFlag(QStringConverter::Flag::Stateless)) {
+ if (auto leftOver = ucnv_fromUCountPending(icu_conv, &err)) {
+ ucnv_reset(icu_conv);
+ state->invalidChars += leftOver;
+ }
+ }
+ return target;
+ }
+
+ Q_DISABLE_COPY_MOVE(QStringConverterICU)
+
+ template<qsizetype X>
+ static qsizetype fromLen(qsizetype inLength)
+ {
+ return X * inLength * sizeof(UChar);
+ }
+
+ static qsizetype toLen(qsizetype inLength)
+ {
+
+ /* Assumption: each input char might map to a different codepoint
+ Each codepoint can take up to 4 bytes == 2 QChar
+ We can ignore reserving space for a BOM, as only UTF encodings use one
+ and those are not handled by the ICU converter.
+ */
+ return 2 * inLength;
+ }
+
+ static constexpr QStringConverter::Interface forLength[] = {
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<1>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<2>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<3>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<4>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<5>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<6>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<7>},
+ {"icu, recompile if you see this", QStringConverterICU::toUtf16, QStringConverterICU::toLen, QStringConverterICU::fromUtf16, QStringConverterICU::fromLen<8>}
+ };
+
+ static UConverter *createConverterForName(const char *name, const State *state)
+ {
+ Q_ASSERT(name);
+ Q_ASSERT(state);
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = ucnv_open(name, &status);
+ if (status != U_ZERO_ERROR && status != U_AMBIGUOUS_ALIAS_WARNING) {
+ ucnv_close(conv);
+ return nullptr;
+ }
+
+ if (state->flags.testFlag(Flag::ConvertInvalidToNull)) {
+ UErrorCode error = U_ZERO_ERROR;
+
+ auto nullToSubstituter = [](const void *context, UConverterToUnicodeArgs *toUArgs,
+ const char *, int32_t length,
+ UConverterCallbackReason reason, UErrorCode *err) {
+ if (reason <= UCNV_IRREGULAR) {
+ *err = U_ZERO_ERROR;
+ UChar c = '\0';
+ ucnv_cbToUWriteUChars(toUArgs, &c, 1, 0, err);
+ // Recover outer scope's state (which isn't const) from context:
+ auto state = const_cast<State *>(static_cast<const State *>(context));
+ state->invalidChars += length;
+ }
+ };
+ ucnv_setToUCallBack(conv, nullToSubstituter, state, nullptr, nullptr, &error);
+
+ auto nullFromSubstituter = [](const void *context, UConverterFromUnicodeArgs *fromUArgs,
+ const UChar *, int32_t length,
+ UChar32, UConverterCallbackReason reason, UErrorCode *err) {
+ if (reason <= UCNV_IRREGULAR) {
+ *err = U_ZERO_ERROR;
+ const UChar replacement[] = { 0 };
+ const UChar *stringBegin = std::begin(replacement);
+ ucnv_cbFromUWriteUChars(fromUArgs, &stringBegin, std::end(replacement), 0, err);
+ // Recover outer scope's state (which isn't const) from context:
+ auto state = const_cast<State *>(static_cast<const State *>(context));
+ state->invalidChars += length;
+ }
+ };
+ ucnv_setFromUCallBack(conv, nullFromSubstituter, state, nullptr, nullptr, &error);
+ } else {
+ UErrorCode error = U_ZERO_ERROR;
+
+ auto qmarkToSubstituter = [](const void *context, UConverterToUnicodeArgs *toUArgs,
+ const char *codeUnits,int32_t length,
+ UConverterCallbackReason reason, UErrorCode *err) {
+ if (reason <= UCNV_IRREGULAR) {
+ // Recover outer scope's state (which isn't const) from context:
+ auto state = const_cast<State *>(static_cast<const State *>(context));
+ state->invalidChars += length;
+ }
+ // use existing ICU callback for logic
+ UCNV_TO_U_CALLBACK_SUBSTITUTE(nullptr, toUArgs, codeUnits, length, reason, err);
+
+ };
+ ucnv_setToUCallBack(conv, qmarkToSubstituter, state, nullptr, nullptr, &error);
+
+ auto qmarkFromSubstituter = [](const void *context, UConverterFromUnicodeArgs *fromUArgs,
+ const UChar *codeUnits, int32_t length,
+ UChar32 codePoint, UConverterCallbackReason reason, UErrorCode *err) {
+ if (reason <= UCNV_IRREGULAR) {
+ // Recover outer scope's state (which isn't const) from context:
+ auto state = const_cast<State *>(static_cast<const State *>(context));
+ state->invalidChars += length;
+ }
+ // use existing ICU callback for logic
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE(nullptr, fromUArgs, codeUnits, length,
+ codePoint, reason, err);
+ };
+ ucnv_setFromUCallBack(conv, qmarkFromSubstituter, state, nullptr, nullptr, &error);
+ }
+ return conv;
+ }
+
+ static const QStringConverter::Interface *make_icu_converter(
+ QStringConverterBase::State *state,
+ const char *name)
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = createConverterForName(name, state);
+ if (!conv)
+ return nullptr;
+
+ const char *icuName = ucnv_getName(conv, &status);
+ // ucnv_getStandardName returns a name which is owned by the library
+ // we can thus store it in the state without worrying aobut its lifetime
+ const char *persistentName = ucnv_getStandardName(icuName, "MIME", &status);
+ if (U_FAILURE(status) || !persistentName) {
+ status = U_ZERO_ERROR;
+ persistentName = ucnv_getStandardName(icuName, "IANA", &status);
+ }
+ state->d[1] = const_cast<char *>(persistentName);
+ state->d[0] = conv;
+ state->flags |= QStringConverterBase::Flag::UsesIcu;
+ qsizetype maxCharSize = ucnv_getMaxCharSize(conv);
+ state->clearFn = QStringConverterICU::clear_function;
+ if (maxCharSize > 8 || maxCharSize < 1) {
+ qWarning("Encountered unexpected codec \"%s\" which requires >8x space", name);
+ return nullptr;
+ } else {
+ return &forLength[maxCharSize - 1];
+ }
+
+ }
+
+};
+#endif
+
/*!
\internal
*/
@@ -1574,7 +2171,27 @@ QStringConverter::QStringConverter(const char *name, Flags f)
{
auto e = encodingForName(name);
if (e)
- iface = encodingInterfaces + int(e.value());
+ iface = encodingInterfaces + int(*e);
+#if QT_CONFIG(icu)
+ else
+ iface = QStringConverterICU::make_icu_converter(&state, name);
+#endif
+}
+
+
+const char *QStringConverter::name() const noexcept
+{
+ if (!iface)
+ return nullptr;
+ if (state.flags & QStringConverter::Flag::UsesIcu) {
+#if QT_CONFIG(icu)
+ return static_cast<const char*>(state.d[1]);
+#else
+ return nullptr;
+#endif
+ } else {
+ return iface->name;
+ }
}
/*!
@@ -1607,17 +2224,26 @@ QStringConverter::QStringConverter(const char *name, Flags f)
Returns the canonical name of the encoding this QStringConverter can encode or decode.
Returns a nullptr if the converter is not valid.
+ The returned name is UTF-8 encoded.
\sa isValid()
*/
/*!
- Returns an optional encoding for \a name. The optional is empty if the name could
- not get converted to a valid encoding.
+ Convert \a name to the corresponding \l Encoding member, if there is one.
+
+ If the \a name is not the name of a codec listed in the Encoding enumeration,
+ \c{std::nullopt} is returned. Such a name may, none the less, be accepted by
+ the QStringConverter constructor when Qt is built with ICU, if ICU provides a
+ converter with the given name.
+
+ \a name is expected to be UTF-8 encoded.
*/
-std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(const char *name)
+std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(const char *name) noexcept
{
- for (int i = 0; i < LastEncoding + 1; ++i) {
+ if (!name)
+ return std::nullopt;
+ for (qsizetype i = 0; i < LastEncoding + 1; ++i) {
if (nameMatch(encodingInterfaces[i].name, name))
return QStringConverter::Encoding(i);
}
@@ -1626,20 +2252,24 @@ std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(cons
return std::nullopt;
}
+#ifndef QT_BOOTSTRAPPED
/*!
- Returns the encoding for the content of \a buf if it can be determined.
+ Returns the encoding for the content of \a data if it can be determined.
\a expectedFirstCharacter can be passed as an additional hint to help determine
the encoding.
The returned optional is empty, if the encoding is unclear.
*/
-std::optional<QStringConverter::Encoding> QStringConverter::encodingForData(const char *buf, qsizetype arraySize, char16_t expectedFirstCharacter)
+std::optional<QStringConverter::Encoding>
+QStringConverter::encodingForData(QByteArrayView data, char16_t expectedFirstCharacter) noexcept
{
+ // someone set us up the BOM?
+ qsizetype arraySize = data.size();
if (arraySize > 3) {
- uint uc = qFromUnaligned<uint>(buf);
- if (uc == qToBigEndian(uint(QChar::ByteOrderMark)))
+ char32_t uc = qFromUnaligned<char32_t>(data.data());
+ if (uc == qToBigEndian(char32_t(QChar::ByteOrderMark)))
return QStringConverter::Utf32BE;
- if (uc == qToLittleEndian(uint(QChar::ByteOrderMark)))
+ if (uc == qToLittleEndian(char32_t(QChar::ByteOrderMark)))
return QStringConverter::Utf32LE;
if (expectedFirstCharacter) {
// catch also anything starting with the expected character
@@ -1651,16 +2281,15 @@ std::optional<QStringConverter::Encoding> QStringConverter::encodingForData(cons
}
if (arraySize > 2) {
- static const char utf8bom[] = "\xef\xbb\xbf";
- if (memcmp(buf, utf8bom, sizeof(utf8bom) - 1) == 0)
+ if (memcmp(data.data(), utf8bom, sizeof(utf8bom)) == 0)
return QStringConverter::Utf8;
}
if (arraySize > 1) {
- ushort uc = qFromUnaligned<ushort>(buf);
- if (uc == qToBigEndian(ushort(QChar::ByteOrderMark)))
+ char16_t uc = qFromUnaligned<char16_t>(data.data());
+ if (uc == qToBigEndian(char16_t(QChar::ByteOrderMark)))
return QStringConverter::Utf16BE;
- if (uc == qToLittleEndian(ushort(QChar::ByteOrderMark)))
+ if (uc == qToLittleEndian(char16_t(QChar::ByteOrderMark)))
return QStringConverter::Utf16LE;
if (expectedFirstCharacter) {
// catch also anything starting with the expected character
@@ -1673,52 +2302,149 @@ std::optional<QStringConverter::Encoding> QStringConverter::encodingForData(cons
return std::nullopt;
}
-/*!
- Tries to determine the encoding of the HTML in \a buf by looking at leading byte order marks or
- a charset specifier in the HTML meta tag. If the optional is empty, the encoding specified is
- not supported by QStringConverter. If no encoding is detected, the method returns Utf8.
- */
-std::optional<QStringConverter::Encoding> QStringConverter::encodingForHtml(const char *buf, qsizetype arraySize)
+static QByteArray parseHtmlMetaForEncoding(QByteArrayView data)
{
- // determine charset
- auto encoding = encodingForData(buf, arraySize);
- if (encoding)
- // trust the initial BOM
- return encoding;
+ static constexpr auto metaSearcher = qMakeStaticByteArrayMatcher("meta ");
+ static constexpr auto charsetSearcher = qMakeStaticByteArrayMatcher("charset=");
- QByteArray header = QByteArray(buf, qMin(arraySize, qsizetype(1024))).toLower();
- int pos = header.indexOf("meta ");
+ QByteArray header = data.first(qMin(data.size(), qsizetype(1024))).toByteArray().toLower();
+ qsizetype pos = metaSearcher.indexIn(header);
if (pos != -1) {
- pos = header.indexOf("charset=", pos);
+ pos = charsetSearcher.indexIn(header, pos);
if (pos != -1) {
pos += qstrlen("charset=");
if (pos < header.size() && (header.at(pos) == '\"' || header.at(pos) == '\''))
++pos;
- int pos2 = pos;
+ qsizetype pos2 = pos;
// The attribute can be closed with either """, "'", ">" or "/",
// none of which are valid charset characters.
while (++pos2 < header.size()) {
char ch = header.at(pos2);
if (ch == '\"' || ch == '\'' || ch == '>' || ch == '/') {
QByteArray name = header.mid(pos, pos2 - pos);
- int colon = name.indexOf(':');
+ qsizetype colon = name.indexOf(':');
if (colon > 0)
name = name.left(colon);
name = name.simplified();
if (name == "unicode") // QTBUG-41998, ICU will return UTF-16.
name = QByteArrayLiteral("UTF-8");
if (!name.isEmpty())
- return encodingForName(name);
+ return name;
}
}
}
}
+ return QByteArray();
+}
+
+/*!
+ Tries to determine the encoding of the HTML in \a data by looking at leading byte
+ order marks or a charset specifier in the HTML meta tag. If the optional is empty,
+ the encoding specified is not supported by QStringConverter. If no encoding is
+ detected, the method returns Utf8.
+
+ \sa QStringDecoder::decoderForHtml()
+*/
+std::optional<QStringConverter::Encoding> QStringConverter::encodingForHtml(QByteArrayView data)
+{
+ // determine charset
+ std::optional<QStringConverter::Encoding> encoding = encodingForData(data);
+ if (encoding)
+ // trust the initial BOM
+ return encoding;
+
+ QByteArray encodingTag = parseHtmlMetaForEncoding(data);
+ if (!encodingTag.isEmpty())
+ return encodingForName(encodingTag);
+
return Utf8;
}
+static qsizetype availableCodecCount()
+{
+#if !QT_CONFIG(icu)
+ return QStringConverter::Encoding::LastEncoding;
+#else
+ /* icu contains also the names of what Qt provides
+ except for the special Locale one (so add one for it)
+ */
+ return 1 + ucnv_countAvailable();
+#endif
+}
+
/*!
- Returns the canonical name for \a encoding.
+ Returns a list of names of supported codecs. The names returned
+ by this function can be passed to QStringEncoder's and
+ QStringDecoder's constructor to create a en- or decoder for
+ the given codec.
+
+ This function may be used to obtain a listing of additional codecs beyond
+ the standard ones. Support for additional codecs requires Qt be compiled
+ with support for the ICU library.
+
+ \note The order of codecs is an internal implementation detail
+ and not guaranteed to be stable.
+ */
+QStringList QStringConverter::availableCodecs()
+{
+ auto availableCodec = [](qsizetype index) -> QString
+ {
+ #if !QT_CONFIG(icu)
+ return QString::fromLatin1(encodingInterfaces[index].name);
+ #else
+ if (index == 0) // "Locale", not provided by icu
+ return QString::fromLatin1(
+ encodingInterfaces[QStringConverter::Encoding::System].name);
+ // this mirrors the setup we do to set a converters name
+ UErrorCode status = U_ZERO_ERROR;
+ auto icuName = ucnv_getAvailableName(int32_t(index - 1));
+ const char *standardName = ucnv_getStandardName(icuName, "MIME", &status);
+ if (U_FAILURE(status) || !standardName) {
+ status = U_ZERO_ERROR;
+ standardName = ucnv_getStandardName(icuName, "IANA", &status);
+ }
+ if (!standardName)
+ standardName = icuName;
+ return QString::fromLatin1(standardName);
+ #endif
+ };
+
+ qsizetype codecCount = availableCodecCount();
+ QStringList result;
+ result.reserve(codecCount);
+ for (qsizetype i = 0; i < codecCount; ++i)
+ result.push_back(availableCodec(i));
+ return result;
+}
+
+/*!
+ Tries to determine the encoding of the HTML in \a data by looking at leading byte
+ order marks or a charset specifier in the HTML meta tag and returns a QStringDecoder
+ matching the encoding. If the returned decoder is not valid,
+ the encoding specified is not supported by QStringConverter. If no encoding is
+ detected, the method returns a decoder for Utf8.
+
+ \sa isValid()
+*/
+QStringDecoder QStringDecoder::decoderForHtml(QByteArrayView data)
+{
+ // determine charset
+ std::optional<QStringConverter::Encoding> encoding = encodingForData(data);
+ if (encoding)
+ // trust the initial BOM
+ return QStringDecoder(encoding.value());
+
+ QByteArray encodingTag = parseHtmlMetaForEncoding(data);
+ if (!encodingTag.isEmpty())
+ return QStringDecoder(encodingTag);
+
+ return QStringDecoder(Utf8);
+}
+#endif // !QT_BOOTSTRAPPED
+
+/*!
+ Returns the canonical name for encoding \a e.
*/
const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
{
@@ -1784,26 +2510,24 @@ const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
*/
/*!
- \fn QByteArray QStringEncoder::operator()(const QString &in)
- \fn QByteArray QStringEncoder::encode(const QString &in)
-
- Converts \a in and returns the data as a byte array.
-*/
+ \fn constexpr QStringEncoder::QStringEncoder(const QString &name, Flags flags = Flag::Default)
+ \since 6.8
-/*!
- \fn QByteArray QStringEncoder::operator()(QStringView in)
- \fn QByteArray QStringEncoder::encode(QStringView in)
- \overload
+ Creates an encoder object using \a name and \a flags.
+ If \a name is not the name of a known encoding an invalid converter will get created.
- Converts \a in and returns the data as a byte array.
+ \sa isValid()
*/
/*!
- \fn QByteArray QStringEncoder::operator()(const QChar *in, qsizetype length)
- \fn QByteArray QStringEncoder::encode(const QChar *in, qsizetype length)
- \overload
+ \fn QStringEncoder::DecodedData<const QString &> QStringEncoder::encode(const QString &in)
+ \fn QStringEncoder::DecodedData<QStringView> QStringEncoder::encode(QStringView in)
+ \fn QStringEncoder::DecodedData<const QString &> QStringEncoder::operator()(const QString &in)
+ \fn QStringEncoder::DecodedData<QStringView> QStringEncoder::operator()(QStringView in)
+
+ Converts \a in and returns a struct that is implicitly convertible to QByteArray.
- Converts \a length QChars from \a in and returns the data as a byte array.
+ \snippet code/src_corelib_text_qstringconverter.cpp 5
*/
/*!
@@ -1812,20 +2536,20 @@ const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
Returns the maximum amount of characters required to be able to process
\a inputLength decoded data.
- \sa appendToBuffer
+ \sa appendToBuffer()
*/
/*!
- \fn char *QStringEncoder::appendToBuffer(char *out, const QChar *in, qsizetype length)
+ \fn char *QStringEncoder::appendToBuffer(char *out, QStringView in)
- Encodes \a length QChars from \a in and writes the encoded result into the buffer
- starting at \a out. Returns a pointer to the end of data written.
+ Encodes \a in and writes the encoded result into the buffer
+ starting at \a out. Returns a pointer to the end of the data written.
- \a out needs to be large enough to be able to hold all the decoded data. Use
- \l{requiredSpace} to determine the maximum size requirements to be able to encode
- a QChar buffer of \a length.
+ \note \a out must be large enough to be able to hold all the decoded data. Use
+ requiredSpace() to determine the maximum size requirement to be able to encode
+ \a in.
- \sa requiredSpace
+ \sa requiredSpace()
*/
/*!
@@ -1887,28 +2611,25 @@ const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
*/
/*!
- \fn QString QStringDecoder::operator()(const QByteArray &ba)
- \fn QString QStringDecoder::decode(const QByteArray &ba)
+ \fn constexpr QStringDecoder::QStringDecoder(const QString &name, Flags flags = Flag::Default)
+ \since 6.8
+
+ Creates an decoder object using \a name and \a flags.
+ If \a name is not the name of a known encoding an invalid converter will get created.
- Converts \a ba and returns the data as a QString.
+ \sa isValid()
*/
/*!
- \fn QString QStringDecoder::operator()(const char *in, qsizetype size)
- \fn QString QStringDecoder::decode(const char *in, qsizetype size)
- \overload
+ \fn QStringDecoder::EncodedData<const QByteArray &> QStringDecoder::operator()(const QByteArray &ba)
+ \fn QStringDecoder::EncodedData<const QByteArray &> QStringDecoder::decode(const QByteArray &ba)
+ \fn QStringDecoder::EncodedData<QByteArrayView> QStringDecoder::operator()(QByteArrayView ba)
+ \fn QStringDecoder::EncodedData<QByteArrayView> QStringDecoder::decode(QByteArrayView ba)
- Converts a byte array containing the first \a size bytes of the array \a in
- and returns the data as a QString.
-*/
+ Converts \a ba and returns a struct that is implicitly convertible to QString.
-/*!
- \fn QString QStringDecoder::operator()(const char *chars)
- \fn QString QStringDecoder::decode(const char *chars)
- \overload
- Converts \a chars and returns the data as a QString. \a chars is assumed to
- point to a \c{\0}-terminated string and its length is determined dynamically.
+ \snippet code/src_corelib_text_qstringconverter.cpp 4
*/
/*!
@@ -1921,16 +2642,22 @@ const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
*/
/*!
- \fn QChar *QStringDecoder::appendToBuffer(QChar *out, const char *in, qsizetype length)
+ \fn QChar *QStringDecoder::appendToBuffer(QChar *out, QByteArrayView in)
- Decodes \a length bytes from \a in and writes the decoded result into the buffer
- starting at \a out. Returns a pointer to the end of data written.
+ Decodes the sequence of bytes viewed by \a in and writes the decoded result into
+ the buffer starting at \a out. Returns a pointer to the end of data written.
\a out needs to be large enough to be able to hold all the decoded data. Use
\l{requiredSpace} to determine the maximum size requirements to decode an encoded
- data buffer of \a length.
+ data buffer of \c in.size() bytes.
\sa requiredSpace
*/
+/*!
+ \fn char16_t *QStringDecoder::appendToBuffer(char16_t *out, QByteArrayView in)
+ \since 6.6
+ \overload
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringconverter.h b/src/corelib/text/qstringconverter.h
index 8766968e6d..40791f8e26 100644
--- a/src/corelib/text/qstringconverter.h
+++ b/src/corelib/text/qstringconverter.h
@@ -1,247 +1,78 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#if 0
+// keep existing syncqt header working after the move of the class
+// into qstringconverter_base
+#pragma qt_class(QStringConverter)
+#pragma qt_class(QStringConverterBase)
+#endif
#ifndef QSTRINGCONVERTER_H
#define QSTRINGCONVERTER_H
+#include <QtCore/qstringconverter_base.h>
#include <QtCore/qstring.h>
-#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
#include <QtCore/qstringbuilder.h>
-#endif
-
-#include <optional>
QT_BEGIN_NAMESPACE
-// work around a compiler bug in GCC 7
-#if defined(Q_CC_GNU) && __GNUC__ == 7
-#define QSTRINGCONVERTER_CONSTEXPR
-#else
-#define QSTRINGCONVERTER_CONSTEXPR constexpr
-#endif
-
-class QStringConverterBase
-{
-public:
- enum class Flag {
- Default = 0,
- Stateless = 0x1,
- ConvertInvalidToNull = 0x2,
- WriteBom = 0x4,
- ConvertInitialBom = 0x8
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- struct State {
- constexpr State(Flags f = Flag::Default)
- : flags(f), state_data{0, 0, 0, 0} {}
- ~State() { clear(); }
- State(State &&other)
- : flags(other.flags),
- remainingChars(other.remainingChars),
- invalidChars(other.invalidChars),
- d{other.d[0], other.d[1]},
- clearFn(other.clearFn)
- { other.clearFn = nullptr; }
- State &operator=(State &&other)
- {
- clear();
- flags = other.flags;
- remainingChars = other.remainingChars;
- invalidChars = other.invalidChars;
- d[0] = other.d[0];
- d[1] = other.d[1];
- clearFn = other.clearFn;
- other.clearFn = nullptr;
- return *this;
- }
- Q_CORE_EXPORT void clear();
-
- Flags flags;
- int internalState = 0;
- qsizetype remainingChars = 0;
- qsizetype invalidChars = 0;
-
- union {
- uint state_data[4];
- void *d[2];
- };
- using ClearDataFn = void (*)(State *);
- ClearDataFn clearFn = nullptr;
- private:
- Q_DISABLE_COPY(State)
- };
-};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QStringConverterBase::Flags)
-
-class QStringConverter : public QStringConverterBase
-{
-public:
-
- enum Encoding {
- Utf8,
- Utf16,
- Utf16LE,
- Utf16BE,
- Utf32,
- Utf32LE,
- Utf32BE,
- Latin1,
- System,
- LastEncoding = System
- };
-#ifdef Q_QDOC
- // document the flags here
- enum class Flag {
- Default = 0,
- Stateless = 0x1,
- ConvertInvalidToNull = 0x2,
- WriteBom = 0x4,
- ConvertInitialBom = 0x8
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-#endif
-
-protected:
-
- struct Interface
- {
- // ### FIXME: need a QByteArrayView
- using DecoderFn = QChar * (*)(QChar *out, const char *in, qsizetype length, State *state);
- using LengthFn = qsizetype (*)(qsizetype inLength);
- using EncoderFn = char * (*)(char *out, QStringView in, State *state);
- const char *name = nullptr;
- DecoderFn toUtf16 = nullptr;
- LengthFn toUtf16Len = nullptr;
- EncoderFn fromUtf16 = nullptr;
- LengthFn fromUtf16Len = nullptr;
- };
-
- QSTRINGCONVERTER_CONSTEXPR QStringConverter()
- : iface(nullptr)
- {}
- QSTRINGCONVERTER_CONSTEXPR QStringConverter(Encoding encoding, Flags f)
- : iface(&encodingInterfaces[int(encoding)]), state(f)
- {}
- QSTRINGCONVERTER_CONSTEXPR QStringConverter(const Interface *i)
- : iface(i)
- {}
- Q_CORE_EXPORT QStringConverter(const char *name, Flags f);
-
-
-public:
- bool isValid() const { return iface != nullptr; }
-
- void resetState()
- {
- state.clear();
- }
- bool hasError() const { return state.invalidChars != 0; }
-
- const char *name() const
- { return isValid() ? iface->name : nullptr; }
-
- Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name);
- Q_CORE_EXPORT static const char *nameForEncoding(Encoding e);
- Q_CORE_EXPORT static std::optional<Encoding> encodingForData(const char *buf, qsizetype arraySize, char16_t expectedFirstCharacter = 0);
- Q_CORE_EXPORT static std::optional<Encoding> encodingForHtml(const char *buf, qsizetype arraySize);
-
-protected:
- const Interface *iface;
- State state;
-private:
- Q_CORE_EXPORT static const Interface encodingInterfaces[Encoding::LastEncoding + 1];
-};
-
class QStringEncoder : public QStringConverter
{
protected:
- QSTRINGCONVERTER_CONSTEXPR QStringEncoder(const Interface *i)
+ constexpr explicit QStringEncoder(const Interface *i) noexcept
: QStringConverter(i)
{}
public:
- QSTRINGCONVERTER_CONSTEXPR QStringEncoder()
+ constexpr QStringEncoder() noexcept
: QStringConverter()
{}
- QSTRINGCONVERTER_CONSTEXPR QStringEncoder(Encoding encoding, Flags flags = Flag::Default)
+ constexpr explicit QStringEncoder(Encoding encoding, Flags flags = Flag::Default)
: QStringConverter(encoding, flags)
{}
- QStringEncoder(const char *name, Flags flags = Flag::Default)
+ explicit QStringEncoder(const char *name, Flags flags = Flag::Default)
: QStringConverter(name, flags)
{}
+ Q_WEAK_OVERLOAD explicit QStringEncoder(const QString &name, Flags flags = Flag::Default)
+ : QStringEncoder(name.toLatin1().constData(), flags)
+ {}
-#if defined(Q_QDOC)
- QByteArray operator()(const QString &in);
- QByteArray operator()(QStringView in);
- QByteArray operator()(const QChar *in, qsizetype length);
- QByteArray encode(const QString &in);
- QByteArray encode(QStringView in);
- QByteArray encode(const QChar *in, qsizetype length);
-#else
template<typename T>
struct DecodedData
{
QStringEncoder *encoder;
T data;
- operator QByteArray() const { return encoder->encodeAsByteArray(QStringView(data)); }
+ operator QByteArray() const { return encoder->encodeAsByteArray(data); }
};
+ Q_WEAK_OVERLOAD
DecodedData<const QString &> operator()(const QString &str)
{ return DecodedData<const QString &>{this, str}; }
DecodedData<QStringView> operator()(QStringView in)
{ return DecodedData<QStringView>{this, in}; }
- DecodedData<QStringView> operator()(const QChar *in, qsizetype length)
- { return (*this)(QStringView(in, length)); }
+ Q_WEAK_OVERLOAD
DecodedData<const QString &> encode(const QString &str)
{ return DecodedData<const QString &>{this, str}; }
DecodedData<QStringView> encode(QStringView in)
{ return DecodedData<QStringView>{this, in}; }
- DecodedData<QStringView> encode(const QChar *in, qsizetype length)
- { return (*this)(QStringView(in, length)); }
-#endif
qsizetype requiredSpace(qsizetype inputLength) const
- { return iface->fromUtf16Len(inputLength); }
- char *appendToBuffer(char *out, const QChar *in, qsizetype length)
- { return iface->fromUtf16(out, QStringView(in, length), &state); }
+ { return iface ? iface->fromUtf16Len(inputLength) : 0; }
+ char *appendToBuffer(char *out, QStringView in)
+ {
+ if (!iface) {
+ state.invalidChars = 1;
+ return out;
+ }
+ return iface->fromUtf16(out, in, &state);
+ }
private:
QByteArray encodeAsByteArray(QStringView in)
{
+ if (!iface) {
+ // ensure that hasError returns true
+ state.invalidChars = 1;
+ return {};
+ }
QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized);
char *out = result.data();
out = iface->fromUtf16(out, in, &state);
@@ -253,68 +84,67 @@ private:
class QStringDecoder : public QStringConverter
{
- struct View {
- const char *ch;
- qsizetype l;
- const char *data() const { return ch; }
- qsizetype length() const { return l; }
- };
-
protected:
- QSTRINGCONVERTER_CONSTEXPR QStringDecoder(const Interface *i)
+ constexpr explicit QStringDecoder(const Interface *i) noexcept
: QStringConverter(i)
{}
public:
- QSTRINGCONVERTER_CONSTEXPR QStringDecoder(Encoding encoding, Flags flags = Flag::Default)
+ constexpr explicit QStringDecoder(Encoding encoding, Flags flags = Flag::Default)
: QStringConverter(encoding, flags)
{}
- QSTRINGCONVERTER_CONSTEXPR QStringDecoder()
+ constexpr QStringDecoder() noexcept
: QStringConverter()
{}
- QStringDecoder(const char *name, Flags f = Flag::Default)
+ explicit QStringDecoder(const char *name, Flags f = Flag::Default)
: QStringConverter(name, f)
{}
+ Q_WEAK_OVERLOAD explicit QStringDecoder(const QString &name, Flags f = Flag::Default)
+ : QStringDecoder(name.toLatin1().constData(), f)
+ {}
-#if defined(Q_QDOC)
- QString operator()(const QByteArray &ba);
- QString operator()(const char *in, qsizetype size);
- QString operator()(const char *chars);
- QString decode(const QByteArray &ba);
- QString decode(const char *in, qsizetype size);
- QString decode(const char *chars);
-#else
template<typename T>
struct EncodedData
{
QStringDecoder *decoder;
T data;
- operator QString() const { return decoder->decodeAsString(data.data(), data.length()); }
+ operator QString() const { return decoder->decodeAsString(data); }
};
+ Q_WEAK_OVERLOAD
EncodedData<const QByteArray &> operator()(const QByteArray &ba)
{ return EncodedData<const QByteArray &>{this, ba}; }
- EncodedData<View> operator()(const char *in, qsizetype length)
- { return EncodedData<View>{this, {in, length}}; }
- EncodedData<View> operator()(const char *chars)
- { return EncodedData<View>{this, {chars, qsizetype(strlen(chars))}}; }
+ EncodedData<QByteArrayView> operator()(QByteArrayView ba)
+ { return EncodedData<QByteArrayView>{this, ba}; }
+ Q_WEAK_OVERLOAD
EncodedData<const QByteArray &> decode(const QByteArray &ba)
{ return EncodedData<const QByteArray &>{this, ba}; }
- EncodedData<View> decode(const char *in, qsizetype length)
- { return EncodedData<View>{this, {in, length}}; }
- EncodedData<View> decode(const char *chars)
- { return EncodedData<View>{this, {chars, qsizetype(strlen(chars))}}; }
-#endif
+ EncodedData<QByteArrayView> decode(QByteArrayView ba)
+ { return EncodedData<QByteArrayView>{this, ba}; }
qsizetype requiredSpace(qsizetype inputLength) const
- { return iface->toUtf16Len(inputLength); }
- QChar *appendToBuffer(QChar *out, const char *in, qsizetype length)
- { return iface->toUtf16(out, in, length, &state); }
+ { return iface ? iface->toUtf16Len(inputLength) : 0; }
+ QChar *appendToBuffer(QChar *out, QByteArrayView ba)
+ {
+ if (!iface) {
+ state.invalidChars = 1;
+ return out;
+ }
+ return iface->toUtf16(out, ba, &state);
+ }
+ char16_t *appendToBuffer(char16_t *out, QByteArrayView ba)
+ { return reinterpret_cast<char16_t *>(appendToBuffer(reinterpret_cast<QChar *>(out), ba)); }
+
+ Q_CORE_EXPORT static QStringDecoder decoderForHtml(QByteArrayView data);
+
private:
- QString decodeAsString(const char *in, qsizetype length)
+ QString decodeAsString(QByteArrayView in)
{
- QString result(iface->toUtf16Len(length), Qt::Uninitialized);
- QChar *out = result.data();
- // ### Fixme: state handling needs to be moved into the conversion methods
- out = iface->toUtf16(out, in, length, &state);
+ if (!iface) {
+ // ensure that hasError returns true
+ state.invalidChars = 1;
+ return {};
+ }
+ QString result(iface->toUtf16Len(in.size()), Qt::Uninitialized);
+ const QChar *out = iface->toUtf16(result.data(), in, &state);
result.truncate(out - result.constData());
return result;
}
@@ -329,10 +159,10 @@ struct QConcatenable<QStringDecoder::EncodedData<T>>
typedef QChar type;
typedef QString ConvertTo;
enum { ExactSize = false };
- static qsizetype size(const QStringDecoder::EncodedData<T> &s) { return s.decoder->requiredSpace(s.data.length()); }
+ static qsizetype size(const QStringDecoder::EncodedData<T> &s) { return s.decoder->requiredSpace(s.data.size()); }
static inline void appendTo(const QStringDecoder::EncodedData<T> &s, QChar *&out)
{
- out = s.decoder->appendToBuffer(out, s.data.data(), s.data.length());
+ out = s.decoder->appendToBuffer(out, s.data);
}
};
@@ -343,10 +173,10 @@ struct QConcatenable<QStringEncoder::DecodedData<T>>
typedef char type;
typedef QByteArray ConvertTo;
enum { ExactSize = false };
- static qsizetype size(const QStringEncoder::DecodedData<T> &s) { return s.encoder->requiredSpace(s.data.length()); }
+ static qsizetype size(const QStringEncoder::DecodedData<T> &s) { return s.encoder->requiredSpace(s.data.size()); }
static inline void appendTo(const QStringEncoder::DecodedData<T> &s, char *&out)
{
- out = s.encoder->appendToBuffer(out, s.data.data(), s.data.length());
+ out = s.encoder->appendToBuffer(out, s.data);
}
};
@@ -373,8 +203,66 @@ QByteArray &operator+=(QByteArray &a, const QStringEncoder::DecodedData<T> &b)
}
#endif
-QT_END_NAMESPACE
+template <typename InputIterator>
+void QString::assign_helper_char8(InputIterator first, InputIterator last)
+{
+ static_assert(!QString::is_contiguous_iterator_v<InputIterator>,
+ "Internal error: Should have been handed over to the QAnyStringView overload."
+ );
+
+ using ValueType = typename std::iterator_traits<InputIterator>::value_type;
+ constexpr bool IsFwdIt = std::is_convertible_v<
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ std::forward_iterator_tag
+ >;
+
+ resize(0);
+ // In case of not being shared, there is the possibility of having free space at begin
+ // even after the resize to zero.
+ if (const auto offset = d.freeSpaceAtBegin())
+ d.setBegin(d.begin() - offset);
+
+ if constexpr (IsFwdIt)
+ reserve(static_cast<qsizetype>(std::distance(first, last)));
+
+ auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
+ auto availableCapacity = d.constAllocatedCapacity();
+ auto *dst = d.data();
+ auto *dend = d.data() + availableCapacity;
+
+ while (true) {
+ if (first == last) { // ran out of input elements
+ Q_ASSERT(!std::less<>{}(dend, dst));
+ d.size = dst - d.begin();
+ return;
+ }
+ const ValueType next = *first; // decays proxies, if any
+ const auto chunk = QUtf8StringView(&next, 1);
+ // UTF-8 characters can have a maximum size of 4 bytes and may result in a surrogate
+ // pair of UTF-16 code units. In the input-iterator case, we don't know the size
+ // and would need to always reserve space for 2 code units. To keep our promise
+ // of 'not allocating if it fits', we have to pre-check this condition.
+ // We know that it fits in the forward-iterator case.
+ if constexpr (!IsFwdIt) {
+ constexpr qsizetype Pair = 2;
+ char16_t buf[Pair];
+ const qptrdiff n = toUtf16.appendToBuffer(buf, chunk) - buf;
+ if (dend - dst < n) { // ran out of allocated memory
+ const auto offset = dst - d.begin();
+ reallocData(d.constAllocatedCapacity() + Pair, QArrayData::Grow);
+ // update the pointers since we've re-allocated
+ availableCapacity = d.constAllocatedCapacity();
+ dst = d.data() + offset;
+ dend = d.data() + availableCapacity;
+ }
+ dst = std::copy_n(buf, n, dst);
+ } else { // take the fast path
+ dst = toUtf16.appendToBuffer(dst, chunk);
+ }
+ ++first;
+ }
+}
-#undef QSTRINGCONVERTER_CONSTEXPR
+QT_END_NAMESPACE
#endif
diff --git a/src/corelib/text/qstringconverter_base.h b/src/corelib/text/qstringconverter_base.h
new file mode 100644
index 0000000000..d6b6fcb484
--- /dev/null
+++ b/src/corelib/text/qstringconverter_base.h
@@ -0,0 +1,176 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSTRINGCONVERTER_BASE_H
+#define QSTRINGCONVERTER_BASE_H
+
+#if 0
+// QStringConverter(Base) class are handled in qstringconverter
+#pragma qt_sync_stop_processing
+#endif
+
+#include <optional>
+
+#include <QtCore/qglobal.h> // QT_{BEGIN,END}_NAMESPACE
+#include <QtCore/qflags.h> // Q_DECLARE_FLAGS
+#include <QtCore/qcontainerfwd.h>
+
+#include <cstring>
+
+QT_BEGIN_NAMESPACE
+
+class QByteArrayView;
+class QChar;
+class QByteArrayView;
+class QStringView;
+
+class QStringConverterBase
+{
+public:
+ enum class Flag {
+ Default = 0,
+ Stateless = 0x1,
+ ConvertInvalidToNull = 0x2,
+ WriteBom = 0x4,
+ ConvertInitialBom = 0x8,
+ UsesIcu = 0x10,
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ struct State {
+ constexpr State(Flags f = Flag::Default) noexcept
+ : flags(f), state_data{0, 0, 0, 0} {}
+ ~State() { clear(); }
+
+ State(State &&other) noexcept
+ : flags(other.flags),
+ remainingChars(other.remainingChars),
+ invalidChars(other.invalidChars),
+ state_data{other.state_data[0], other.state_data[1],
+ other.state_data[2], other.state_data[3]},
+ clearFn(other.clearFn)
+ { other.clearFn = nullptr; }
+ State &operator=(State &&other) noexcept
+ {
+ clear();
+ flags = other.flags;
+ remainingChars = other.remainingChars;
+ invalidChars = other.invalidChars;
+ std::memmove(state_data, other.state_data, sizeof state_data); // self-assignment-safe
+ clearFn = other.clearFn;
+ other.clearFn = nullptr;
+ return *this;
+ }
+ Q_CORE_EXPORT void clear() noexcept;
+ Q_CORE_EXPORT void reset() noexcept;
+
+ Flags flags;
+ int internalState = 0;
+ qsizetype remainingChars = 0;
+ qsizetype invalidChars = 0;
+
+ union {
+ uint state_data[4];
+ void *d[2];
+ };
+ using ClearDataFn = void (*)(State *) noexcept;
+ ClearDataFn clearFn = nullptr;
+ private:
+ Q_DISABLE_COPY(State)
+ };
+protected:
+ ~QStringConverterBase() = default;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QStringConverterBase::Flags)
+
+class QStringConverter : public QStringConverterBase
+{
+public:
+
+ enum Encoding {
+ Utf8,
+#ifndef QT_BOOTSTRAPPED
+ Utf16,
+ Utf16LE,
+ Utf16BE,
+ Utf32,
+ Utf32LE,
+ Utf32BE,
+#endif
+ Latin1,
+ System,
+ LastEncoding = System
+ };
+#ifdef Q_QDOC
+ // document the flags here
+ enum class Flag {
+ Default = 0,
+ Stateless = 0x1,
+ ConvertInvalidToNull = 0x2,
+ WriteBom = 0x4,
+ ConvertInitialBom = 0x8,
+ UsesIcu = 0x10,
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+#endif
+
+protected:
+
+ struct Interface
+ {
+ using DecoderFn = QChar * (*)(QChar *out, QByteArrayView in, State *state);
+ using LengthFn = qsizetype (*)(qsizetype inLength);
+ using EncoderFn = char * (*)(char *out, QStringView in, State *state);
+ const char *name = nullptr;
+ DecoderFn toUtf16 = nullptr;
+ LengthFn toUtf16Len = nullptr;
+ EncoderFn fromUtf16 = nullptr;
+ LengthFn fromUtf16Len = nullptr;
+ };
+
+ constexpr QStringConverter() noexcept
+ : iface(nullptr)
+ {}
+ constexpr explicit QStringConverter(Encoding encoding, Flags f)
+ : iface(&encodingInterfaces[qsizetype(encoding)]), state(f)
+ {}
+ constexpr explicit QStringConverter(const Interface *i) noexcept
+ : iface(i)
+ {}
+ Q_CORE_EXPORT explicit QStringConverter(const char *name, Flags f);
+
+
+ ~QStringConverter() = default;
+
+public:
+ QStringConverter(QStringConverter &&) = default;
+ QStringConverter &operator=(QStringConverter &&) = default;
+
+ bool isValid() const noexcept { return iface != nullptr; }
+
+ void resetState() noexcept
+ {
+ state.reset();
+ }
+ bool hasError() const noexcept { return state.invalidChars != 0; }
+
+ Q_CORE_EXPORT const char *name() const noexcept;
+
+ Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name) noexcept;
+ Q_CORE_EXPORT static const char *nameForEncoding(Encoding e);
+ Q_CORE_EXPORT static std::optional<Encoding>
+ encodingForData(QByteArrayView data, char16_t expectedFirstCharacter = 0) noexcept;
+ Q_CORE_EXPORT static std::optional<Encoding> encodingForHtml(QByteArrayView data);
+
+ Q_CORE_EXPORT static QStringList availableCodecs();
+
+protected:
+ const Interface *iface;
+ State state;
+private:
+ Q_CORE_EXPORT static const Interface encodingInterfaces[Encoding::LastEncoding + 1];
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/text/qstringconverter_p.h b/src/corelib/text/qstringconverter_p.h
index 83ffb889cb..e68ffb2bb0 100644
--- a/src/corelib/text/qstringconverter_p.h
+++ b/src/corelib/text/qstringconverter_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGCONVERTER_P_H
#define QSTRINGCONVERTER_P_H
@@ -55,9 +19,42 @@
#include <QtCore/qstring.h>
#include <QtCore/qendian.h>
#include <QtCore/qstringconverter.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
+#ifndef __cpp_char8_t
+enum qchar8_t : uchar {};
+#else
+using qchar8_t = char8_t;
+#endif
+
+struct QLatin1
+{
+ // Defined in qstring.cpp
+ static char16_t *convertToUnicode(char16_t *dst, QLatin1StringView in) noexcept;
+
+ static QChar *convertToUnicode(QChar *buffer, QLatin1StringView in) noexcept
+ {
+ char16_t *dst = reinterpret_cast<char16_t *>(buffer);
+ dst = convertToUnicode(dst, in);
+ return reinterpret_cast<QChar *>(dst);
+ }
+
+ static QChar *convertToUnicode(QChar *dst, QByteArrayView in,
+ [[maybe_unused]] QStringConverterBase::State *state) noexcept
+ {
+ Q_ASSERT(state);
+
+ return convertToUnicode(dst, QLatin1StringView(in.data(), in.size()));
+ }
+
+ static char *convertFromUnicode(char *out, QStringView in, QStringConverter::State *state) noexcept;
+
+ // Defined in qstring.cpp
+ static char *convertFromUnicode(char *out, QStringView in) noexcept;
+};
+
struct QUtf8BaseTraits
{
static const bool isTrusted = false;
@@ -66,44 +63,59 @@ struct QUtf8BaseTraits
static const int Error = -1;
static const int EndOfString = -2;
- static bool isValidCharacter(uint u)
- { return int(u) >= 0; }
-
static void appendByte(uchar *&ptr, uchar b)
{ *ptr++ = b; }
+ static void appendByte(qchar8_t *&ptr, qchar8_t b)
+ { *ptr++ = b; }
+
+ static uchar peekByte(const char *ptr, qsizetype n = 0)
+ { return ptr[n]; }
+
static uchar peekByte(const uchar *ptr, qsizetype n = 0)
{ return ptr[n]; }
+ static uchar peekByte(const qchar8_t *ptr, qsizetype n = 0)
+ { return ptr[n]; }
+
+ static qptrdiff availableBytes(const char *ptr, const char *end)
+ { return end - ptr; }
+
static qptrdiff availableBytes(const uchar *ptr, const uchar *end)
{ return end - ptr; }
+ static qptrdiff availableBytes(const qchar8_t *ptr, const qchar8_t *end)
+ { return end - ptr; }
+
+ static void advanceByte(const char *&ptr, qsizetype n = 1)
+ { ptr += n; }
+
static void advanceByte(const uchar *&ptr, qsizetype n = 1)
{ ptr += n; }
- static void appendUtf16(ushort *&ptr, ushort uc)
- { *ptr++ = uc; }
+ static void advanceByte(const qchar8_t *&ptr, qsizetype n = 1)
+ { ptr += n; }
+
+ static void appendUtf16(char16_t *&ptr, char16_t uc)
+ { *ptr++ = char16_t(uc); }
- static void appendUcs4(ushort *&ptr, uint uc)
+ static void appendUcs4(char16_t *&ptr, char32_t uc)
{
appendUtf16(ptr, QChar::highSurrogate(uc));
appendUtf16(ptr, QChar::lowSurrogate(uc));
}
- static ushort peekUtf16(const ushort *ptr, qsizetype n = 0)
- { return ptr[n]; }
+ static char16_t peekUtf16(const char16_t *ptr, qsizetype n = 0) { return ptr[n]; }
- static qptrdiff availableUtf16(const ushort *ptr, const ushort *end)
+ static qptrdiff availableUtf16(const char16_t *ptr, const char16_t *end)
{ return end - ptr; }
- static void advanceUtf16(const ushort *&ptr, qsizetype n = 1)
- { ptr += n; }
+ static void advanceUtf16(const char16_t *&ptr, qsizetype n = 1) { ptr += n; }
- // it's possible to output to UCS-4 too
- static void appendUtf16(uint *&ptr, ushort uc)
- { *ptr++ = uc; }
+ static void appendUtf16(char32_t *&ptr, char16_t uc)
+ { *ptr++ = char32_t(uc); }
- static void appendUcs4(uint *&ptr, uint uc)
+ static void appendUcs4(char32_t *&ptr, char32_t uc)
{ *ptr++ = uc; }
};
@@ -119,7 +131,7 @@ namespace QUtf8Functions
/// if \a u is a high surrogate, Error if the next isn't a low one,
/// EndOfString if we run into the end of the string.
template <typename Traits, typename OutputPtr, typename InputPtr> inline
- int toUtf8(ushort u, OutputPtr &dst, InputPtr &src, InputPtr end)
+ int toUtf8(char16_t u, OutputPtr &dst, InputPtr &src, InputPtr end)
{
if (!Traits::skipAsciiHandling && u < 0x80) {
// U+0000 to U+007F (US-ASCII) - one byte
@@ -143,14 +155,14 @@ namespace QUtf8Functions
if (Traits::availableUtf16(src, end) == 0)
return Traits::EndOfString;
- ushort low = Traits::peekUtf16(src);
+ char16_t low = Traits::peekUtf16(src);
if (!QChar::isHighSurrogate(u))
return Traits::Error;
if (!QChar::isLowSurrogate(low))
return Traits::Error;
Traits::advanceUtf16(src);
- uint ucs4 = QChar::surrogateToUcs4(u, low);
+ char32_t ucs4 = QChar::surrogateToUcs4(u, low);
if (!Traits::allowNonCharacters && QChar::isNonCharacter(ucs4))
return Traits::Error;
@@ -162,7 +174,7 @@ namespace QUtf8Functions
Traits::appendByte(dst, 0x80 | (uchar(ucs4 >> 12) & 0x3f));
// for the rest of the bytes
- u = ushort(ucs4);
+ u = char16_t(ucs4);
}
// second to last byte
@@ -185,8 +197,8 @@ namespace QUtf8Functions
qsizetype fromUtf8(uchar b, OutputPtr &dst, InputPtr &src, InputPtr end)
{
qsizetype charsNeeded;
- uint min_uc;
- uint uc;
+ char32_t min_uc;
+ char32_t uc;
if (!Traits::skipAsciiHandling && b < 0x80) {
// US-ASCII
@@ -266,7 +278,7 @@ namespace QUtf8Functions
if (!QChar::requiresSurrogates(uc)) {
// UTF-8 decoded and no surrogates are required
// detach if necessary
- Traits::appendUtf16(dst, ushort(uc));
+ Traits::appendUtf16(dst, char16_t(uc));
} else {
// UTF-8 decoded to something that requires a surrogate pair
Traits::appendUcs4(dst, uc);
@@ -286,57 +298,98 @@ enum DataEndianness
struct QUtf8
{
- static QChar *convertToUnicode(QChar *, const char *, qsizetype) noexcept;
- static QString convertToUnicode(const char *, qsizetype);
- Q_CORE_EXPORT static QString convertToUnicode(const char *, qsizetype, QStringConverter::State *);
- static QChar *convertToUnicode(QChar *out, const char *in, qsizetype length, QStringConverter::State *state);
- static QByteArray convertFromUnicode(const QChar *, qsizetype);
- Q_CORE_EXPORT static QByteArray convertFromUnicode(const QChar *, qsizetype, QStringConverter::State *);
+ static QChar *convertToUnicode(QChar *buffer, QByteArrayView in) noexcept
+ {
+ char16_t *dst = reinterpret_cast<char16_t *>(buffer);
+ dst = QUtf8::convertToUnicode(dst, in);
+ return reinterpret_cast<QChar *>(dst);
+ }
+
+ Q_CORE_EXPORT static char16_t* convertToUnicode(char16_t *dst, QByteArrayView in) noexcept;
+ static QString convertToUnicode(QByteArrayView in);
+ Q_CORE_EXPORT static QString convertToUnicode(QByteArrayView in, QStringConverter::State *state);
+
+ static QChar *convertToUnicode(QChar *out, QByteArrayView in, QStringConverter::State *state)
+ {
+ char16_t *buffer = reinterpret_cast<char16_t *>(out);
+ buffer = convertToUnicode(buffer, in, state);
+ return reinterpret_cast<QChar *>(buffer);
+ }
+
+ static char16_t *convertToUnicode(char16_t *dst, QByteArrayView in, QStringConverter::State *state);
+
+ Q_CORE_EXPORT static QByteArray convertFromUnicode(QStringView in);
+ Q_CORE_EXPORT static QByteArray convertFromUnicode(QStringView in, QStringConverterBase::State *state);
static char *convertFromUnicode(char *out, QStringView in, QStringConverter::State *state);
+ Q_CORE_EXPORT static char *convertFromLatin1(char *out, QLatin1StringView in);
struct ValidUtf8Result {
bool isValidUtf8;
bool isValidAscii;
};
- static ValidUtf8Result isValidUtf8(const char *, qsizetype);
- static int compareUtf8(const char *, qsizetype, const QChar *, qsizetype);
- static int compareUtf8(const char *, qsizetype, QLatin1String s);
+ static ValidUtf8Result isValidUtf8(QByteArrayView in);
+ static int compareUtf8(QByteArrayView utf8, QStringView utf16,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+ static int compareUtf8(QByteArrayView utf8, QLatin1StringView s,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ static int compareUtf8(QByteArrayView lhs, QByteArrayView rhs,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
};
struct QUtf16
{
- Q_CORE_EXPORT static QString convertToUnicode(const char *, qsizetype, QStringConverter::State *, DataEndianness = DetectEndianness);
- static QChar *convertToUnicode(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian);
- Q_CORE_EXPORT static QByteArray convertFromUnicode(const QChar *, qsizetype, QStringConverter::State *, DataEndianness = DetectEndianness);
+ Q_CORE_EXPORT static QString convertToUnicode(QByteArrayView, QStringConverter::State *, DataEndianness = DetectEndianness);
+ static QChar *convertToUnicode(QChar *out, QByteArrayView, QStringConverter::State *state, DataEndianness endian);
+ Q_CORE_EXPORT static QByteArray convertFromUnicode(QStringView, QStringConverter::State *, DataEndianness = DetectEndianness);
static char *convertFromUnicode(char *out, QStringView in, QStringConverter::State *state, DataEndianness endian);
};
struct QUtf32
{
- static QChar *convertToUnicode(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian);
- Q_CORE_EXPORT static QString convertToUnicode(const char *, qsizetype, QStringConverter::State *, DataEndianness = DetectEndianness);
- Q_CORE_EXPORT static QByteArray convertFromUnicode(const QChar *, qsizetype, QStringConverter::State *, DataEndianness = DetectEndianness);
+ static QChar *convertToUnicode(QChar *out, QByteArrayView, QStringConverter::State *state, DataEndianness endian);
+ Q_CORE_EXPORT static QString convertToUnicode(QByteArrayView, QStringConverter::State *, DataEndianness = DetectEndianness);
+ Q_CORE_EXPORT static QByteArray convertFromUnicode(QStringView, QStringConverter::State *, DataEndianness = DetectEndianness);
static char *convertFromUnicode(char *out, QStringView in, QStringConverter::State *state, DataEndianness endian);
};
struct Q_CORE_EXPORT QLocal8Bit
{
#if !defined(Q_OS_WIN) || defined(QT_BOOTSTRAPPED)
- static QString convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state)
- { return QUtf8::convertToUnicode(chars, len, state); }
- static QByteArray convertFromUnicode(const QChar *chars, qsizetype len, QStringConverter::State *state)
- { return QUtf8::convertFromUnicode(chars, len, state); }
+ static QString convertToUnicode(QByteArrayView in, QStringConverter::State *state)
+ { return QUtf8::convertToUnicode(in, state); }
+ static QByteArray convertFromUnicode(QStringView in, QStringConverter::State *state)
+ { return QUtf8::convertFromUnicode(in, state); }
#else
- static QString convertToUnicode(const char *, qsizetype, QStringConverter::State *);
- static QByteArray convertFromUnicode(const QChar *, qsizetype, QStringConverter::State *);
+ static int checkUtf8();
+ static bool isUtf8()
+ {
+ Q_CONSTINIT
+ static QBasicAtomicInteger<qint8> result = { 0 };
+ int r = result.loadRelaxed();
+ if (r == 0) {
+ r = checkUtf8();
+ result.storeRelaxed(r);
+ }
+ return r > 0;
+ }
+ static QString convertToUnicode_sys(QByteArrayView, quint32, QStringConverter::State *);
+ static QString convertToUnicode_sys(QByteArrayView, QStringConverter::State *);
+ static QString convertToUnicode(QByteArrayView in, QStringConverter::State *state)
+ {
+ if (isUtf8())
+ return QUtf8::convertToUnicode(in, state);
+ return convertToUnicode_sys(in, state);
+ }
+ static QByteArray convertFromUnicode_sys(QStringView, quint32, QStringConverter::State *);
+ static QByteArray convertFromUnicode_sys(QStringView, QStringConverter::State *);
+ static QByteArray convertFromUnicode(QStringView in, QStringConverter::State *state)
+ {
+ if (isUtf8())
+ return QUtf8::convertFromUnicode(in, state);
+ return convertFromUnicode_sys(in, state);
+ }
#endif
};
-/*
- Converts from different utf encodings looking at a possible byte order mark at the
- beginning of the string. If no BOM exists, utf-8 is assumed.
- */
-Q_CORE_EXPORT QString qFromUtfEncoded(const QByteArray &ba);
-
QT_END_NAMESPACE
#endif // QSTRINGCONVERTER_P_H
diff --git a/src/corelib/text/qstringfwd.h b/src/corelib/text/qstringfwd.h
new file mode 100644
index 0000000000..2e3c9e8248
--- /dev/null
+++ b/src/corelib/text/qstringfwd.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qglobal.h>
+
+#ifndef QSTRINGFWD_H
+#define QSTRINGFWD_H
+
+QT_BEGIN_NAMESPACE
+
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
+# define QT_BEGIN_HAS_CHAR8_T_NAMESPACE inline namespace q_has_char8_t {
+# define QT_BEGIN_NO_CHAR8_T_NAMESPACE namespace q_no_char8_t {
+#else
+# define QT_BEGIN_HAS_CHAR8_T_NAMESPACE namespace q_has_char8_t {
+# define QT_BEGIN_NO_CHAR8_T_NAMESPACE inline namespace q_no_char8_t {
+#endif
+#define QT_END_HAS_CHAR8_T_NAMESPACE }
+#define QT_END_NO_CHAR8_T_NAMESPACE }
+
+// declare namespaces:
+QT_BEGIN_HAS_CHAR8_T_NAMESPACE
+QT_END_HAS_CHAR8_T_NAMESPACE
+QT_BEGIN_NO_CHAR8_T_NAMESPACE
+QT_END_NO_CHAR8_T_NAMESPACE
+
+class QByteArray;
+class QByteArrayView;
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || defined(Q_QDOC)
+class QLatin1StringView;
+using QLatin1String = QLatin1StringView;
+#else
+class QLatin1String;
+using QLatin1StringView = QLatin1String;
+#endif
+class QStringView;
+template <bool> class QBasicUtf8StringView;
+class QAnyStringView;
+class QChar;
+class QRegularExpression;
+class QRegularExpressionMatch;
+
+#ifndef Q_QDOC
+// ### Qt 7: remove the non-char8_t version of QUtf8StringView
+QT_BEGIN_NO_CHAR8_T_NAMESPACE
+using QUtf8StringView = QBasicUtf8StringView<false>;
+QT_END_NO_CHAR8_T_NAMESPACE
+
+QT_BEGIN_HAS_CHAR8_T_NAMESPACE
+using QUtf8StringView = QBasicUtf8StringView<true>;
+QT_END_HAS_CHAR8_T_NAMESPACE
+#endif // Q_QDOC
+
+QT_END_NAMESPACE
+
+#endif // QSTRINGFWD_H
diff --git a/src/corelib/text/qstringiterator.qdoc b/src/corelib/text/qstringiterator.qdoc
index 9be610161f..9b1e43163e 100644
--- a/src/corelib/text/qstringiterator.qdoc
+++ b/src/corelib/text/qstringiterator.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QStringIterator
diff --git a/src/corelib/text/qstringiterator_p.h b/src/corelib/text/qstringiterator_p.h
index 0ee5eb0e53..bb1a861637 100644
--- a/src/corelib/text/qstringiterator_p.h
+++ b/src/corelib/text/qstringiterator_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGITERATOR_H
#define QSTRINGITERATOR_H
@@ -61,6 +25,8 @@ class QStringIterator
{
QString::const_iterator i, pos, e;
static_assert((std::is_same<QString::const_iterator, const QChar *>::value));
+ static bool less(const QChar *lhs, const QChar *rhs) noexcept
+ { return std::less{}(lhs, rhs); }
public:
explicit QStringIterator(QStringView string, qsizetype idx = 0)
: i(string.begin()),
@@ -76,7 +42,7 @@ public:
{
}
- inline explicit QStringIterator(const QChar *begin, int idx, const QChar *end)
+ explicit QStringIterator(const QChar *begin, qsizetype idx, const QChar *end)
: i(begin),
pos(begin + idx),
e(end)
@@ -88,14 +54,15 @@ public:
return pos;
}
- inline int index() const
+ qsizetype index() const
{
- return int(pos - i);
+ return pos - i;
}
inline void setPosition(QString::const_iterator position)
{
- Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
+ Q_ASSERT_X(!less(position, i) && !less(e, position),
+ Q_FUNC_INFO, "position out of bounds");
pos = position;
}
@@ -103,7 +70,7 @@ public:
inline bool hasNext() const
{
- return pos < e;
+ return less(pos, e);
}
inline void advance()
@@ -120,16 +87,20 @@ public:
{
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
- if (Q_UNLIKELY((pos++)->isHighSurrogate()))
+ if (Q_UNLIKELY((pos++)->isHighSurrogate())) {
+ Q_ASSERT(hasNext() && pos->isLowSurrogate());
++pos;
+ }
}
inline char32_t peekNextUnchecked() const
{
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
- if (Q_UNLIKELY(pos->isHighSurrogate()))
+ if (Q_UNLIKELY(pos->isHighSurrogate())) {
+ Q_ASSERT(less(pos + 1, e) && pos[1].isLowSurrogate());
return QChar::surrogateToUcs4(pos[0], pos[1]);
+ }
return pos->unicode();
}
@@ -155,8 +126,10 @@ public:
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
const QChar cur = *pos++;
- if (Q_UNLIKELY(cur.isHighSurrogate()))
+ if (Q_UNLIKELY(cur.isHighSurrogate())) {
+ Q_ASSERT(hasNext() && pos->isLowSurrogate());
return QChar::surrogateToUcs4(cur, *pos++);
+ }
return cur.unicode();
}
@@ -166,7 +139,7 @@ public:
const QChar uc = *pos++;
if (Q_UNLIKELY(uc.isSurrogate())) {
- if (Q_LIKELY(uc.isHighSurrogate() && pos < e && pos->isLowSurrogate()))
+ if (Q_LIKELY(uc.isHighSurrogate() && hasNext() && pos->isLowSurrogate()))
return QChar::surrogateToUcs4(uc, *pos++);
return invalidAs;
}
@@ -178,7 +151,7 @@ public:
inline bool hasPrevious() const
{
- return pos > i;
+ return less(i, pos);
}
inline void recede()
@@ -196,16 +169,20 @@ public:
{
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
- if (Q_UNLIKELY((--pos)->isLowSurrogate()))
+ if (Q_UNLIKELY((--pos)->isLowSurrogate())) {
+ Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate());
--pos;
+ }
}
inline char32_t peekPreviousUnchecked() const
{
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
- if (Q_UNLIKELY(pos[-1].isLowSurrogate()))
+ if (Q_UNLIKELY(pos[-1].isLowSurrogate())) {
+ Q_ASSERT(less(i + 1, pos) && pos[-2].isHighSurrogate());
return QChar::surrogateToUcs4(pos[-2], pos[-1]);
+ }
return pos[-1].unicode();
}
@@ -230,8 +207,10 @@ public:
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
const QChar cur = *--pos;
- if (Q_UNLIKELY(cur.isLowSurrogate()))
+ if (Q_UNLIKELY(cur.isLowSurrogate())) {
+ Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate());
return QChar::surrogateToUcs4(*--pos, cur);
+ }
return cur.unicode();
}
@@ -241,7 +220,7 @@ public:
const QChar uc = *--pos;
if (Q_UNLIKELY(uc.isSurrogate())) {
- if (Q_LIKELY(uc.isLowSurrogate() && pos > i && pos[-1].isHighSurrogate()))
+ if (Q_LIKELY(uc.isLowSurrogate() && hasPrevious() && pos[-1].isHighSurrogate()))
return QChar::surrogateToUcs4(*--pos, uc);
return invalidAs;
}
diff --git a/src/corelib/text/qstringlist.cpp b/src/corelib/text/qstringlist.cpp
index 942b1fdf97..61923e0b3f 100644
--- a/src/corelib/text/qstringlist.cpp
+++ b/src/corelib/text/qstringlist.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qstringlist.h>
#include <qset.h>
@@ -108,7 +72,7 @@ QT_BEGIN_NAMESPACE
\section1 Adding Strings
Strings can be added to a list using the \l
- {QList::insert()}{insert()} \l
+ {QList::insert()}{insert()}, \l
{QList::append()}{append()}, \l
{QList::operator+=()}{operator+=()} and \l
{operator<<()} functions.
@@ -120,25 +84,7 @@ QT_BEGIN_NAMESPACE
\section1 Iterating Over the Strings
- To iterate over a list, you can either use index positions or
- QList's Java-style and STL-style iterator types:
-
- Indexing:
-
- \snippet qstringlist/main.cpp 1
-
- Java-style iterator:
-
- \snippet qstringlist/main.cpp 2
-
- STL-style iterator:
-
- \snippet qstringlist/main.cpp 3
-
- The QStringListIterator class is simply a type definition for
- QListIterator<QString>. QStringList also provide the
- QMutableStringListIterator class which is a type definition for
- QMutableListIterator<QString>.
+ See \l {Iterating over Containers}.
\section1 Manipulating the Strings
@@ -185,12 +131,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringList::QStringList()
-
- Constructs an empty string list.
-*/
-
-/*!
\fn QStringList::QStringList(const QString &str)
Constructs a string list that contains the given string, \a
@@ -249,8 +189,11 @@ QT_BEGIN_NAMESPACE
\fn void QStringList::sort(Qt::CaseSensitivity cs)
Sorts the list of strings in ascending order.
+
+//! [comparison-case-sensitivity]
If \a cs is \l Qt::CaseSensitive (the default), the string comparison
is case sensitive; otherwise the comparison is case insensitive.
+//! [comparison-case-sensitivity]
Sorting is performed using the STL's std::sort() algorithm,
which averages \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}).
@@ -263,34 +206,25 @@ QT_BEGIN_NAMESPACE
integer index.
*/
-namespace {
-struct CaseInsensitiveLessThan {
- typedef bool result_type;
- result_type operator()(const QString &s1, const QString &s2) const
- {
- return s1.compare(s2, Qt::CaseInsensitive) < 0;
- }
-};
-}
-
void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
{
- if (cs == Qt::CaseSensitive)
+ if (cs == Qt::CaseSensitive) {
std::sort(that->begin(), that->end());
- else
- std::sort(that->begin(), that->end(), CaseInsensitiveLessThan());
+ } else {
+ auto CISCompare = [](const auto &s1, const auto &s2) {
+ return s1.compare(s2, Qt::CaseInsensitive) < 0;
+ };
+ std::sort(that->begin(), that->end(), CISCompare);
+ }
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const
Returns a list of all the strings containing the substring \a str.
- If \a cs is \l Qt::CaseSensitive (the default), the string
- comparison is case sensitive; otherwise the comparison is case
- insensitive.
+ \include qstringlist.cpp comparison-case-sensitivity
\snippet qstringlist/main.cpp 5
\snippet qstringlist/main.cpp 10
@@ -302,7 +236,17 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
\sa contains()
*/
-#endif
+
+template <typename String>
+static QStringList filter_helper(const QStringList &that, const String &needle, Qt::CaseSensitivity cs)
+{
+ QStringList res;
+ for (const auto &s : that) {
+ if (s.contains(needle, cs))
+ res.append(s);
+ }
+ return res;
+}
/*!
\fn QStringList QStringList::filter(QStringView str, Qt::CaseSensitivity cs) const
@@ -312,27 +256,47 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
QStringList QtPrivate::QStringList_filter(const QStringList *that, QStringView str,
Qt::CaseSensitivity cs)
{
- QStringMatcher matcher(str, cs);
+ return filter_helper(*that, str, cs);
+}
+
+/*!
+ \fn QStringList QStringList::filter(const QStringMatcher &matcher) const
+ \since 6.7
+ \overload
+
+ Returns a list of all the strings matched by \a matcher (i.e. for which
+ \c matcher.indexIn() returns an index >= 0).
+
+ Using a QStringMatcher may be faster when searching in large lists and/or
+ in lists with long strings (the best way to find out is benchmarking).
+
+ For example:
+ \snippet qstringlist/main.cpp 18
+
+ \sa contains()
+*/
+
+QStringList QtPrivate::QStringList_filter(const QStringList &that, const QStringMatcher &matcher)
+{
QStringList res;
- for (int i = 0; i < that->size(); ++i)
- if (matcher.indexIn(that->at(i)) != -1)
- res << that->at(i);
+ for (const auto &s : that) {
+ if (matcher.indexIn(s) != -1)
+ res.append(s);
+ }
return res;
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/// Not really needed anymore, but kept for binary compatibility
-QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString &str,
+/*!
+ \fn QStringList QStringList::filter(QLatin1StringView str, Qt::CaseSensitivity cs) const
+ \since 6.7
+ \overload
+*/
+
+QStringList QtPrivate::QStringList_filter(const QStringList &that, QLatin1StringView needle,
Qt::CaseSensitivity cs)
{
- QStringMatcher matcher(str, cs);
- QStringList res;
- for (int i = 0; i < that->size(); ++i)
- if (matcher.indexIn(that->at(i)) != -1)
- res << that->at(i);
- return res;
+ return filter_helper(that, needle, cs);
}
-#endif
template<typename T>
static bool stringList_contains(const QStringList &stringList, const T &str, Qt::CaseSensitivity cs)
@@ -345,26 +309,16 @@ static bool stringList_contains(const QStringList &stringList, const T &str, Qt:
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
Returns \c true if the list contains the string \a str; otherwise
- returns \c false. The search is case insensitive if \a cs is
- Qt::CaseInsensitive; the search is case sensitive by default.
+ returns \c false.
+
+ \include qstringlist.cpp comparison-case-sensitivity
\sa indexOf(), lastIndexOf(), QString::contains()
*/
-#endif
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/// Not really needed anymore, but kept for binary compatibility
-bool QtPrivate::QStringList_contains(const QStringList *that, const QString &str,
- Qt::CaseSensitivity cs)
-{
- return stringList_contains(*that, str, cs);
-}
-#endif
/*!
\fn bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const
@@ -372,8 +326,9 @@ bool QtPrivate::QStringList_contains(const QStringList *that, const QString &str
\since 5.12
Returns \c true if the list contains the string \a str; otherwise
- returns \c false. The search is case insensitive if \a cs is
- Qt::CaseInsensitive; the search is case sensitive by default.
+ returns \c false.
+
+ \include qstringlist.cpp comparison-case-sensitivity
*/
bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str,
Qt::CaseSensitivity cs)
@@ -382,71 +337,23 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str,
}
/*!
- \fn bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
+ \fn bool QStringList::contains(QLatin1StringView str, Qt::CaseSensitivity cs) const
\overload
\since 5.10
- Returns \c true if the list contains the string \a str; otherwise
- returns \c false. The search is case insensitive if \a cs is
- Qt::CaseInsensitive; the search is case sensitive by default.
+ Returns \c true if the list contains the Latin-1 string viewed by \a str; otherwise
+ returns \c false.
+
+ \include qstringlist.cpp comparison-case-sensitivity
\sa indexOf(), lastIndexOf(), QString::contains()
*/
-bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str,
+bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1StringView str,
Qt::CaseSensitivity cs)
{
return stringList_contains(*that, str, cs);
}
-/*!
- \fn bool QStringList::indexOf(QStringView str, int from) const
- \overload
- \since 5.13
-
- Returns the index position of the first occurrence of \a str in
- the list, searching forward from index position \a from. Returns
- -1 if no item matched.
-
- \sa lastIndexOf(), contains()
- */
-
-/*!
- \fn bool QStringList::indexOf(QLatin1String str, int from) const
- \overload
- \since 5.13
-
- Returns the index position of the first occurrence of \a str in
- the list, searching forward from index position \a from. Returns
- -1 if no item matched.
-
- \sa lastIndexOf(), contains()
- */
-
-/*!
- \fn bool QStringList::lastIndexOf(QStringView str, int from) const
- \overload
- \since 5.13
-
- Returns the index position of the last occurrence of \a str in
- the list, searching backward from index position \a from. If \a
- from is -1 (the default), the search starts at the last item.
- Returns -1 if no item matched.
-
- \sa indexOf(), contains()
- */
-
-/*!
- \fn bool QStringList::lastIndexOf(QLatin1String str, int from) const
- \overload
- \since 5.13
-
- Returns the index position of the last occurrence of \a str in
- the list, searching backward from index position \a from. If \a
- from is -1 (the default), the search starts at the last item.
- Returns -1 if no item matched.
-
- \sa indexOf(), contains()
- */
#if QT_CONFIG(regularexpression)
/*!
@@ -460,22 +367,22 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str,
QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegularExpression &re)
{
QStringList res;
- for (int i = 0; i < that->size(); ++i) {
- if (that->at(i).contains(re))
- res << that->at(i);
+ for (const auto &str : *that) {
+ if (str.contains(re))
+ res.append(str);
}
return res;
}
#endif // QT_CONFIG(regularexpression)
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
Returns a string list where every string has had the \a before
text replaced with the \a after text wherever the \a before text
- is found. The \a before text is matched case-sensitively or not
- depending on the \a cs flag.
+ is found.
+
+ \include qstringlist.cpp comparison-case-sensitivity
For example:
@@ -496,7 +403,6 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegula
\overload
\since 5.14
*/
-#endif
/*!
\fn QStringList &QStringList::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
@@ -506,19 +412,20 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegula
void QtPrivate::QStringList_replaceInStrings(QStringList *that, QStringView before,
QStringView after, Qt::CaseSensitivity cs)
{
- for (int i = 0; i < that->size(); ++i)
- (*that)[i].replace(before.data(), before.length(), after.data(), after.length(), cs);
-}
+ // Before potentially detaching "that" list, check if any string contains "before"
+ qsizetype i = -1;
+ for (qsizetype j = 0; j < that->size(); ++j) {
+ if (that->at(j).contains(before, cs)) {
+ i = j;
+ break;
+ }
+ }
+ if (i == -1)
+ return;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/// Not really needed anymore, but kept for binary compatibility
-void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QString &before,
- const QString &after, Qt::CaseSensitivity cs)
-{
- for (int i = 0; i < that->size(); ++i)
- (*that)[i].replace(before, after, cs);
+ for (; i < that->size(); ++i)
+ (*that)[i].replace(before.data(), before.size(), after.data(), after.size(), cs);
}
-#endif
#if QT_CONFIG(regularexpression)
/*!
@@ -544,16 +451,28 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QString &b
\snippet qstringlist/main.cpp 5
\snippet qstringlist/main.cpp 17
*/
-void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularExpression &re, const QString &after)
+void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularExpression &re,
+ const QString &after)
{
- for (int i = 0; i < that->size(); ++i)
+ // Before potentially detaching "that" list, check if any string contains "before"
+ qsizetype i = -1;
+ for (qsizetype j = 0; j < that->size(); ++j) {
+ if (that->at(j).contains(re)) {
+ i = j;
+ break;
+ }
+ }
+ if (i == -1)
+ return;
+
+ for (; i < that->size(); ++i)
(*that)[i].replace(re, after);
}
#endif // QT_CONFIG(regularexpression)
-static int accumulatedSize(const QStringList &list, int seplen)
+static qsizetype accumulatedSize(const QStringList &list, qsizetype seplen)
{
- int result = 0;
+ qsizetype result = 0;
if (!list.isEmpty()) {
for (const auto &e : list)
result += e.size() + seplen;
@@ -562,7 +481,6 @@ static int accumulatedSize(const QStringList &list, int seplen)
return result;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn QString QStringList::join(const QString &separator) const
@@ -572,23 +490,22 @@ static int accumulatedSize(const QStringList &list, int seplen)
\sa QString::split()
*/
-#endif
/*!
\fn QString QStringList::join(QChar separator) const
\since 5.0
\overload join()
*/
-QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, int seplen)
+QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, qsizetype seplen)
{
- const int totalLength = accumulatedSize(*that, seplen);
- const int size = that->size();
+ const qsizetype totalLength = accumulatedSize(*that, seplen);
+ const qsizetype size = that->size();
QString res;
if (totalLength == 0)
return res;
res.reserve(totalLength);
- for (int i = 0; i < size; ++i) {
+ for (qsizetype i = 0; i < size; ++i) {
if (i)
res.append(sep, seplen);
res += that->at(i);
@@ -597,11 +514,11 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
}
/*!
- \fn QString QStringList::join(QLatin1String separator) const
+ \fn QString QStringList::join(QLatin1StringView separator) const
\since 5.8
\overload join()
*/
-QString QtPrivate::QStringList_join(const QStringList &list, QLatin1String sep)
+QString QtPrivate::QStringList_join(const QStringList &list, QLatin1StringView sep)
{
QString result;
if (!list.isEmpty()) {
@@ -624,7 +541,7 @@ QString QtPrivate::QStringList_join(const QStringList &list, QLatin1String sep)
*/
QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep)
{
- return QStringList_join(that, sep.data(), sep.length());
+ return QStringList_join(that, sep.data(), sep.size());
}
/*!
@@ -664,9 +581,105 @@ QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep)
the latter string list.
*/
+/*!
+ \fn qsizetype QStringList::indexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringList::indexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringList::indexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
+
+ Returns the index position of the first match of \a str in the list,
+ searching forward from index position \a from. Returns -1 if no item
+ matched.
+
+ \include qstringlist.cpp comparison-case-sensitivity
+
+//! [overloading-base-class-methods]
+ \note The \a cs parameter was added in Qt 6.7, i.e. these methods now overload
+ the methods inherited from the base class. Prior to that these methods only
+ had two parameters. This change is source compatible and existing code should
+ continue to work.
+//! [overloading-base-class-methods]
+
+ \sa lastIndexOf()
+*/
+
+template <typename String>
+qsizetype indexOf_helper(const QStringList &that, String needle, qsizetype from,
+ Qt::CaseSensitivity cs)
+{
+ if (from < 0) // Historical behavior
+ from = qMax(from + that.size(), 0);
+
+ if (from >= that.size())
+ return -1;
+
+ for (qsizetype i = from; i < that.size(); ++i) {
+ if (needle.compare(that.at(i), cs) == 0)
+ return i;
+ }
+ return -1;
+}
+
+qsizetype QtPrivate::QStringList_indexOf(const QStringList &that, QStringView needle,
+ qsizetype from, Qt::CaseSensitivity cs)
+{
+ return indexOf_helper(that, needle, from, cs);
+}
+
+qsizetype QtPrivate::QStringList_indexOf(const QStringList &that, QLatin1StringView needle,
+ qsizetype from, Qt::CaseSensitivity cs)
+{
+ return indexOf_helper(that, needle, from, cs);
+}
+
+/*!
+ \fn qsizetype QStringList::lastIndexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringList::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringList::lastIndexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
+
+ Returns the index position of the last match of \a str in the list,
+ searching backward from index position \a from. If \a from is -1 (the
+ default), the search starts at the last item. Returns -1 if no item
+ matched.
+
+ \include qstringlist.cpp comparison-case-sensitivity
+
+ \include qstringlist.cpp overloading-base-class-methods
+
+ \sa indexOf()
+*/
+
+template <typename String>
+qsizetype lastIndexof_helper(const QStringList &that, String needle, qsizetype from,
+ Qt::CaseSensitivity cs)
+{
+ if (from < 0)
+ from += that.size();
+ else if (from >= that.size())
+ from = that.size() - 1;
+
+ for (qsizetype i = from; i >= 0; --i) {
+ if (needle.compare(that.at(i), cs) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList &that, QLatin1StringView needle,
+ qsizetype from, Qt::CaseSensitivity cs)
+{
+ return lastIndexof_helper(that, needle, from, cs);
+}
+
+qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList &that, QStringView needle,
+ qsizetype from, Qt::CaseSensitivity cs)
+{
+ return lastIndexof_helper(that, needle, from, cs);
+}
+
#if QT_CONFIG(regularexpression)
/*!
- \fn int QStringList::indexOf(const QRegularExpression &re, int from) const
+ \fn qsizetype QStringList::indexOf(const QRegularExpression &re, qsizetype from) const
\overload
\since 5.0
@@ -676,15 +689,15 @@ QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep)
\sa lastIndexOf()
*/
-int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpression &re, int from)
+qsizetype QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpression &re, qsizetype from)
{
if (from < 0)
- from = qMax(from + that->size(), 0);
+ from = qMax(from + that->size(), qsizetype(0));
QString exactPattern = QRegularExpression::anchoredPattern(re.pattern());
QRegularExpression exactRe(exactPattern, re.patternOptions());
- for (int i = from; i < that->size(); ++i) {
+ for (qsizetype i = from; i < that->size(); ++i) {
QRegularExpressionMatch m = exactRe.match(that->at(i));
if (m.hasMatch())
return i;
@@ -693,7 +706,7 @@ int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpres
}
/*!
- \fn int QStringList::lastIndexOf(const QRegularExpression &re, int from) const
+ \fn qsizetype QStringList::lastIndexOf(const QRegularExpression &re, qsizetype from) const
\overload
\since 5.0
@@ -704,7 +717,7 @@ int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpres
\sa indexOf()
*/
-int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, int from)
+qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, qsizetype from)
{
if (from < 0)
from += that->size();
@@ -714,7 +727,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx
QString exactPattern = QRegularExpression::anchoredPattern(re.pattern());
QRegularExpression exactRe(exactPattern, re.patternOptions());
- for (int i = from; i >= 0; --i) {
+ for (qsizetype i = from; i >= 0; --i) {
QRegularExpressionMatch m = exactRe.match(that->at(i));
if (m.hasMatch())
return i;
@@ -724,7 +737,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx
#endif // QT_CONFIG(regularexpression)
/*!
- \fn int QStringList::removeDuplicates()
+ \fn qsizetype QStringList::removeDuplicates()
\since 4.5
@@ -734,41 +747,10 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx
Returns the number of removed entries.
*/
-int QtPrivate::QStringList_removeDuplicates(QStringList *that)
+qsizetype QtPrivate::QStringList_removeDuplicates(QStringList *that)
{
- int n = that->size();
- int j = 0;
-
- QDuplicateTracker<QString> seen;
- seen.reserve(n);
- for (int i = 0; i < n; ++i) {
- const QString &s = that->at(i);
- if (seen.hasSeen(s))
- continue;
- if (j != i)
- that->swapItemsAt(i, j);
- ++j;
- }
- if (n != j)
- that->erase(that->begin() + j, that->end());
- return n - j;
+ QDuplicateTracker<QString> seen(that->size());
+ return that->removeIf([&](const QString &s) { return seen.hasSeen(s); });
}
-/*! \fn QStringList::QStringList(std::initializer_list<QString> args)
- \since 4.8
-
- Construct a list from a std::initializer_list given by \a args.
-
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
-*/
-
- /*! \fn template<typename InputIterator> QStringList::QStringList(InputIterator first, InputIterator last)
- \since 5.14
-
- Constructs a QStringList with the contents in the iterator range [\a first, \a last).
-
- The value type of \c InputIterator must be convertible to \c QString.
- */
-
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringlist.h b/src/corelib/text/qstringlist.h
index 9c4daedd4b..fc5c49bfe1 100644
--- a/src/corelib/text/qstringlist.h
+++ b/src/corelib/text/qstringlist.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qlist.h>
@@ -57,276 +21,155 @@ using QStringListIterator = QListIterator<QString>;
using QMutableStringListIterator = QMutableListIterator<QString>;
#endif
-class QStringList;
-
-#ifdef Q_QDOC
-class QStringList : public QList<QString>
-#else
-template <> struct QListSpecialMethods<QString>
-#endif
-{
-#ifndef Q_QDOC
-protected:
- ~QListSpecialMethods() = default;
-#endif
-public:
- inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive);
- inline int removeDuplicates();
-
-#if QT_STRINGVIEW_LEVEL < 2
- inline QString join(const QString &sep) const;
-#endif
- inline QString join(QStringView sep) const;
- inline QString join(QLatin1String sep) const;
- inline QString join(QChar sep) const;
-
- inline QStringList filter(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline QStringList &replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
-#if QT_STRINGVIEW_LEVEL < 2
- inline QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline QStringList &replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- inline QStringList &replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
- inline QStringList &replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
-#endif
-
-#if QT_CONFIG(regularexpression)
- inline QStringList filter(const QRegularExpression &re) const;
- inline QStringList &replaceInStrings(const QRegularExpression &re, const QString &after);
-#endif // QT_CONFIG(regularexpression)
-
-#ifndef Q_QDOC
-private:
- inline QStringList *self();
- inline const QStringList *self() const;
-};
-
-// ### Qt6: check if there's a better way
-class QStringList : public QList<QString>
-{
-#endif
-public:
- inline QStringList() noexcept { }
- inline explicit QStringList(const QString &i) { append(i); }
- inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
- inline QStringList(QList<QString> &&l) noexcept : QList<QString>(std::move(l)) { }
- inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
- template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
- inline QStringList(InputIterator first, InputIterator last)
- : QList<QString>(first, last) { }
-
- QStringList &operator=(const QList<QString> &other)
- { QList<QString>::operator=(other); return *this; }
- QStringList &operator=(QList<QString> &&other) noexcept
- { QList<QString>::operator=(std::move(other)); return *this; }
-
-#if QT_STRINGVIEW_LEVEL < 2
- inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-#endif
- inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
-
- inline QStringList operator+(const QStringList &other) const
- { QStringList n = *this; n += other; return n; }
- inline QStringList &operator<<(const QString &str)
- { append(str); return *this; }
- inline QStringList &operator<<(const QStringList &l)
- { *this += l; return *this; }
- inline QStringList &operator<<(const QList<QString> &l)
- { *this += l; return *this; }
-
- inline int indexOf(QStringView str, int from = 0) const;
- inline int indexOf(QLatin1String str, int from = 0) const;
-
- inline int lastIndexOf(QStringView str, int from = -1) const;
- inline int lastIndexOf(QLatin1String str, int from = -1) const;
-
-#if QT_CONFIG(regularexpression)
- inline int indexOf(const QRegularExpression &re, int from = 0) const;
- inline int lastIndexOf(const QRegularExpression &re, int from = -1) const;
-#endif // QT_CONFIG(regularexpression)
-
- using QList<QString>::indexOf;
- using QList<QString>::lastIndexOf;
-};
-
-Q_DECLARE_TYPEINFO(QStringList, Q_MOVABLE_TYPE);
-
-#ifndef Q_QDOC
-inline QStringList *QListSpecialMethods<QString>::self()
-{ return static_cast<QStringList *>(this); }
-inline const QStringList *QListSpecialMethods<QString>::self() const
-{ return static_cast<const QStringList *>(this); }
namespace QtPrivate {
void Q_CORE_EXPORT QStringList_sort(QStringList *that, Qt::CaseSensitivity cs);
- int Q_CORE_EXPORT QStringList_removeDuplicates(QStringList *that);
+ qsizetype Q_CORE_EXPORT QStringList_removeDuplicates(QStringList *that);
QString Q_CORE_EXPORT QStringList_join(const QStringList *that, QStringView sep);
- QString Q_CORE_EXPORT QStringList_join(const QStringList *that, const QChar *sep, int seplen);
- Q_CORE_EXPORT QString QStringList_join(const QStringList &list, QLatin1String sep);
+ QString Q_CORE_EXPORT QStringList_join(const QStringList *that, const QChar *sep, qsizetype seplen);
+ Q_CORE_EXPORT QString QStringList_join(const QStringList &list, QLatin1StringView sep);
QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, QStringView str,
Qt::CaseSensitivity cs);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QString &str,
- Qt::CaseSensitivity cs);
-#endif
+ Q_CORE_EXPORT QStringList QStringList_filter(const QStringList &that, QLatin1StringView needle,
+ Qt::CaseSensitivity cs);
+ Q_CORE_EXPORT QStringList QStringList_filter(const QStringList &that,
+ const QStringMatcher &matcher);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, const QString &str, Qt::CaseSensitivity cs);
-#endif
bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, QStringView str, Qt::CaseSensitivity cs);
- bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, QLatin1String str, Qt::CaseSensitivity cs);
+ bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, QLatin1StringView str, Qt::CaseSensitivity cs);
void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, QStringView before, QStringView after,
Qt::CaseSensitivity cs);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QString &before, const QString &after,
- Qt::CaseSensitivity cs);
-#endif
+
+ qsizetype Q_CORE_EXPORT QStringList_indexOf(const QStringList &that, QStringView str,
+ qsizetype from, Qt::CaseSensitivity cs);
+ qsizetype Q_CORE_EXPORT QStringList_indexOf(const QStringList &that, QLatin1StringView str,
+ qsizetype from, Qt::CaseSensitivity cs);
+
+ Q_CORE_EXPORT qsizetype QStringList_lastIndexOf(const QStringList &that, QStringView str,
+ qsizetype from, Qt::CaseSensitivity cs);
+ Q_CORE_EXPORT qsizetype QStringList_lastIndexOf(const QStringList &that, QLatin1StringView str,
+ qsizetype from, Qt::CaseSensitivity cs);
#if QT_CONFIG(regularexpression)
void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QRegularExpression &rx, const QString &after);
QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QRegularExpression &re);
- int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, const QRegularExpression &re, int from);
- int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, int from);
+ qsizetype Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, const QRegularExpression &re, qsizetype from);
+ qsizetype Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, qsizetype from);
#endif // QT_CONFIG(regularexpression)
}
-inline void QListSpecialMethods<QString>::sort(Qt::CaseSensitivity cs)
-{
- QtPrivate::QStringList_sort(self(), cs);
-}
-
-inline int QListSpecialMethods<QString>::removeDuplicates()
-{
- return QtPrivate::QStringList_removeDuplicates(self());
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-inline QString QListSpecialMethods<QString>::join(const QString &sep) const
-{
- return QtPrivate::QStringList_join(self(), sep.constData(), sep.length());
-}
-#endif
-
-inline QString QListSpecialMethods<QString>::join(QStringView sep) const
-{
- return QtPrivate::QStringList_join(self(), sep);
-}
-
-QString QListSpecialMethods<QString>::join(QLatin1String sep) const
-{
- return QtPrivate::QStringList_join(*self(), sep);
-}
-
-inline QString QListSpecialMethods<QString>::join(QChar sep) const
-{
- return QtPrivate::QStringList_join(self(), &sep, 1);
-}
-
-inline QStringList QListSpecialMethods<QString>::filter(QStringView str, Qt::CaseSensitivity cs) const
-{
- return QtPrivate::QStringList_filter(self(), str, cs);
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-inline QStringList QListSpecialMethods<QString>::filter(const QString &str, Qt::CaseSensitivity cs) const
-{
- return QtPrivate::QStringList_filter(self(), str, cs);
-}
-#endif
-
-#if QT_STRINGVIEW_LEVEL < 2
-inline bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
-{
- return QtPrivate::QStringList_contains(this, str, cs);
-}
+#ifdef Q_QDOC
+class QStringList : public QList<QString>
+#else
+template <> struct QListSpecialMethods<QString> : QListSpecialMethodsBase<QString>
#endif
-
-inline bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
-{
- return QtPrivate::QStringList_contains(this, str, cs);
-}
-
-inline bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const
-{
- return QtPrivate::QStringList_contains(this, str, cs);
-}
-
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
-{
- QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
- return *self();
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
{
- QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
- return *self();
-}
-
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs)
-{
- QtPrivate::QStringList_replaceInStrings(self(), before, qToStringViewIgnoringNull(after), cs);
- return *self();
-}
-
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs)
-{
- QtPrivate::QStringList_replaceInStrings(self(), QStringView(before), after, cs);
- return *self();
-}
+#ifdef Q_QDOC
+public:
+ using QList<QString>::QList;
+ QStringList(const QString &str);
+ QStringList(const QList<QString> &other);
+ QStringList(QList<QString> &&other);
+
+ QStringList &operator=(const QList<QString> &other);
+ QStringList &operator=(QList<QString> &&other);
+ QStringList operator+(const QStringList &other) const;
+ QStringList &operator<<(const QString &str);
+ QStringList &operator<<(const QStringList &other);
+ QStringList &operator<<(const QList<QString> &other);
+private:
#endif
-inline QStringList operator+(const QList<QString> &one, const QStringList &other)
-{
- QStringList n = one;
- n += other;
- return n;
-}
-
-inline int QStringList::indexOf(QStringView string, int from) const
-{
- return QtPrivate::indexOf<QString, QStringView>(*this, string, from);
-}
-
-inline int QStringList::indexOf(QLatin1String string, int from) const
-{
- return QtPrivate::indexOf<QString, QLatin1String>(*this, string, from);
-}
-
-inline int QStringList::lastIndexOf(QStringView string, int from) const
-{
- return QtPrivate::lastIndexOf<QString, QStringView>(*this, string, from);
-}
-
-inline int QStringList::lastIndexOf(QLatin1String string, int from) const
-{
- return QtPrivate::lastIndexOf<QString, QLatin1String>(*this, string, from);
-}
+public:
+ inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ { QtPrivate::QStringList_sort(self(), cs); }
+ inline qsizetype removeDuplicates()
+ { return QtPrivate::QStringList_removeDuplicates(self()); }
+
+ inline QString join(QStringView sep) const
+ { return QtPrivate::QStringList_join(self(), sep); }
+ inline QString join(QLatin1StringView sep) const
+ { return QtPrivate::QStringList_join(*self(), sep); }
+ inline QString join(QChar sep) const
+ { return QtPrivate::QStringList_join(self(), &sep, 1); }
+
+ QStringList filter(const QStringMatcher &matcher) const
+ { return QtPrivate::QStringList_filter(*self(), matcher); }
+ QStringList filter(QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return QtPrivate::QStringList_filter(*self(), needle, cs); }
+ inline QStringList filter(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return QtPrivate::QStringList_filter(self(), str, cs); }
+ inline QStringList &replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ {
+ QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
+ return *self();
+ }
+
+ inline QString join(const QString &sep) const
+ { return QtPrivate::QStringList_join(self(), sep.constData(), sep.size()); }
+ inline QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ { return QtPrivate::QStringList_filter(self(), str, cs); }
+ inline QStringList &replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ {
+ QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
+ return *self();
+ }
+ inline QStringList &replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ {
+ QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
+ return *self();
+ }
+ inline QStringList &replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ {
+ QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
+ return *self();
+ }
+ using QListSpecialMethodsBase<QString>::contains;
+ using QListSpecialMethodsBase<QString>::indexOf;
+ using QListSpecialMethodsBase<QString>::lastIndexOf;
+
+ inline bool contains(QLatin1StringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_contains(self(), str, cs); }
+ inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_contains(self(), str, cs); }
+
+ inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_contains(self(), str, cs); }
+
+ qsizetype indexOf(const QString &str, qsizetype from = 0,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(QStringView(str), from, cs); }
+ qsizetype indexOf(QStringView needle, qsizetype from = 0,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_indexOf(*self(), needle, from, cs); }
+ qsizetype indexOf(QLatin1StringView needle, qsizetype from = 0,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_indexOf(*self(), needle, from, cs); }
+
+ qsizetype lastIndexOf(const QString &str, qsizetype from = -1,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(QStringView(str), from, cs); }
+ qsizetype lastIndexOf(QStringView str, qsizetype from = -1,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_lastIndexOf(*self(), str, from, cs); }
+ qsizetype lastIndexOf(QLatin1StringView needle, qsizetype from = -1,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::QStringList_lastIndexOf(*self(), needle, from, cs); }
#if QT_CONFIG(regularexpression)
-inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QRegularExpression &rx, const QString &after)
-{
- QtPrivate::QStringList_replaceInStrings(self(), rx, after);
- return *self();
-}
-
-inline QStringList QListSpecialMethods<QString>::filter(const QRegularExpression &rx) const
-{
- return QtPrivate::QStringList_filter(self(), rx);
-}
-
-inline int QStringList::indexOf(const QRegularExpression &rx, int from) const
-{
- return QtPrivate::QStringList_indexOf(this, rx, from);
-}
-
-inline int QStringList::lastIndexOf(const QRegularExpression &rx, int from) const
-{
- return QtPrivate::QStringList_lastIndexOf(this, rx, from);
-}
+ inline QStringList filter(const QRegularExpression &re) const
+ { return QtPrivate::QStringList_filter(self(), re); }
+ inline QStringList &replaceInStrings(const QRegularExpression &re, const QString &after)
+ {
+ QtPrivate::QStringList_replaceInStrings(self(), re, after);
+ return *self();
+ }
+ inline qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0) const
+ { return QtPrivate::QStringList_indexOf(self(), re, from); }
+ inline qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from = -1) const
+ { return QtPrivate::QStringList_lastIndexOf(self(), re, from); }
#endif // QT_CONFIG(regularexpression)
-#endif // Q_QDOC
+};
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringliteral.h b/src/corelib/text/qstringliteral.h
index a44787c7a4..429d9c02ad 100644
--- a/src/corelib/text/qstringliteral.h
+++ b/src/corelib/text/qstringliteral.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGLITERAL_H
#define QSTRINGLITERAL_H
@@ -55,28 +19,24 @@ QT_BEGIN_NAMESPACE
// to lacking stdlib support. But QStringLiteral only needs the
// core language feature, so just use u"" here unconditionally:
-typedef char16_t qunicodechar;
+#define QT_UNICODE_LITERAL(str) u"" str
-static_assert(sizeof(qunicodechar) == 2,
- "qunicodechar must typedef an integral type of size 2");
+using QStringPrivate = QArrayDataPointer<char16_t>;
+
+namespace QtPrivate {
+template <qsizetype N>
+static Q_ALWAYS_INLINE QStringPrivate qMakeStringPrivate(const char16_t (&literal)[N])
+{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto str = const_cast<char16_t *>(literal);
+ return { nullptr, str, N - 1 };
+}
+}
-#define QT_UNICODE_LITERAL(str) u"" str
#define QStringLiteral(str) \
- ([]() noexcept -> QString { \
- enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
- static const QArrayData qstring_literal = { \
- Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 \
- }; \
- QStringPrivate holder = { \
- static_cast<QTypedArrayData<char16_t> *>(const_cast<QArrayData *>(&qstring_literal)), \
- const_cast<qunicodechar *>(QT_UNICODE_LITERAL(str)), \
- Size \
- }; \
- return QString(holder); \
- }()) \
+ (QString(QtPrivate::qMakeStringPrivate(QT_UNICODE_LITERAL(str)))) \
/**/
-using QStringPrivate = QArrayDataPointer<char16_t>;
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringmatcher.cpp b/src/corelib/text/qstringmatcher.cpp
index e48d72f03e..379d555e54 100644
--- a/src/corelib/text/qstringmatcher.cpp
+++ b/src/corelib/text/qstringmatcher.cpp
@@ -1,52 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Mail.ru Group.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Mail.ru Group.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstringmatcher.h"
QT_BEGIN_NAMESPACE
+static constexpr qsizetype FoldBufferCapacity = 256;
+
static void bm_init_skiptable(QStringView needle, uchar *skiptable, Qt::CaseSensitivity cs)
{
const char16_t *uc = needle.utf16();
- const qsizetype len = needle.size();
- int l = int(qMin(len, qsizetype(255)));
+ const qsizetype len =
+ cs == Qt::CaseSensitive ? needle.size() : qMin(needle.size(), FoldBufferCapacity);
+ int l = qMin(int(len), 255);
memset(skiptable, l, 256 * sizeof(uchar));
uc += len - l;
if (cs == Qt::CaseSensitive) {
@@ -73,11 +40,12 @@ static inline qsizetype bm_find(QStringView haystack, qsizetype index, QStringVi
if (pl == 0)
return index > l ? -1 : index;
- const qsizetype pl_minus_one = pl - 1;
- const char16_t *current = uc + index + pl_minus_one;
- const char16_t *end = uc + l;
if (cs == Qt::CaseSensitive) {
+ const qsizetype pl_minus_one = pl - 1;
+ const char16_t *current = uc + index + pl_minus_one;
+ const char16_t *end = uc + l;
+
while (current < end) {
qsizetype skip = skiptable[*current & 0xff];
if (!skip) {
@@ -102,21 +70,38 @@ static inline qsizetype bm_find(QStringView haystack, qsizetype index, QStringVi
current += skip;
}
} else {
+ char16_t foldBuffer[FoldBufferCapacity];
+ const qsizetype foldBufferLength = qMin(FoldBufferCapacity, pl);
+ const char16_t *start = puc;
+ for (qsizetype i = 0; i < foldBufferLength; ++i)
+ foldBuffer[i] = foldCase(&puc[i], start);
+ QStringView restNeedle = needle.sliced(foldBufferLength);
+ const qsizetype foldBufferEnd = foldBufferLength - 1;
+ const char16_t *current = uc + index + foldBufferEnd;
+ const char16_t *end = uc + l;
+
while (current < end) {
qsizetype skip = skiptable[foldCase(current, uc) & 0xff];
if (!skip) {
// possible match
- while (skip < pl) {
- if (foldCase(current - skip, uc) != foldCase(puc + pl_minus_one - skip, puc))
+ while (skip < foldBufferLength) {
+ if (foldCase(current - skip, uc) != foldBuffer[foldBufferEnd - skip])
break;
++skip;
}
- if (skip > pl_minus_one) // we have a match
- return (current - uc) - pl_minus_one;
+ if (skip > foldBufferEnd) { // Matching foldBuffer
+ qsizetype candidatePos = (current - uc) - foldBufferEnd;
+ QStringView restHaystack =
+ haystack.sliced(qMin(haystack.size(), candidatePos + foldBufferLength));
+ if (restNeedle.size() == 0
+ || restHaystack.startsWith(
+ restNeedle, Qt::CaseInsensitive)) // Check the rest of the string
+ return candidatePos;
+ }
// in case we don't have a match we are a bit inefficient as we only skip by one
// when we have the non matching char in the string.
- if (skiptable[foldCase(current - skip, uc) & 0xff] == pl)
- skip = pl - skip;
+ if (skiptable[foldCase(current - skip, uc) & 0xff] == foldBufferLength)
+ skip = foldBufferLength - skip;
else
skip = 1;
}
@@ -130,7 +115,7 @@ static inline qsizetype bm_find(QStringView haystack, qsizetype index, QStringVi
void QStringMatcher::updateSkipTable()
{
- bm_init_skiptable(p.sv, p.q_skiptable, q_cs);
+ bm_init_skiptable(q_sv, q_skiptable, q_cs);
}
/*!
@@ -156,15 +141,11 @@ void QStringMatcher::updateSkipTable()
\sa QString, QByteArrayMatcher, QRegularExpression
*/
-/*!
+/*! \fn QStringMatcher::QStringMatcher()
+
Constructs an empty string matcher that won't match anything.
Call setPattern() to give it a pattern to match.
*/
-QStringMatcher::QStringMatcher()
- : d_ptr(nullptr), q_cs(Qt::CaseSensitive)
-{
- memset(q_data, 0, sizeof(q_data));
-}
/*!
Constructs a string matcher that will search for \a pattern, with
@@ -173,23 +154,19 @@ QStringMatcher::QStringMatcher()
Call indexIn() to perform a search.
*/
QStringMatcher::QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs)
- : d_ptr(nullptr), q_pattern(pattern), q_cs(cs)
+ : d_ptr(nullptr), q_cs(cs), q_pattern(pattern)
{
- p.sv = q_pattern;
+ q_sv = q_pattern;
updateSkipTable();
}
/*!
- \fn QStringMatcher::QStringMatcher(const QChar *uc, int length, Qt::CaseSensitivity cs)
+ \fn QStringMatcher::QStringMatcher(const QChar *uc, qsizetype length, Qt::CaseSensitivity cs)
\since 4.5
Constructs a string matcher that will search for the pattern referred to
by \a uc with the given \a length and case sensitivity specified by \a cs.
*/
-QStringMatcher::QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs)
- : QStringMatcher(QStringView(uc, len), cs)
-{
-}
/*!
\fn QStringMatcher::QStringMatcher(QStringView pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive)
@@ -201,9 +178,8 @@ QStringMatcher::QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs)
Call indexIn() to perform a search.
*/
QStringMatcher::QStringMatcher(QStringView str, Qt::CaseSensitivity cs)
- : d_ptr(nullptr), q_cs(cs)
+ : d_ptr(nullptr), q_cs(cs), q_sv(str)
{
- p.sv = str;
updateSkipTable();
}
/*!
@@ -231,7 +207,8 @@ QStringMatcher &QStringMatcher::operator=(const QStringMatcher &other)
if (this != &other) {
q_pattern = other.q_pattern;
q_cs = other.q_cs;
- memcpy(q_data, other.q_data, sizeof(q_data));
+ q_sv = other.q_sv;
+ memcpy(q_skiptable, other.q_skiptable, sizeof(q_skiptable));
}
return *this;
}
@@ -245,7 +222,7 @@ QStringMatcher &QStringMatcher::operator=(const QStringMatcher &other)
void QStringMatcher::setPattern(const QString &pattern)
{
q_pattern = pattern;
- p.sv = q_pattern;
+ q_sv = q_pattern;
updateSkipTable();
}
@@ -262,10 +239,19 @@ QString QStringMatcher::pattern() const
{
if (!q_pattern.isEmpty())
return q_pattern;
- return p.sv.toString();
+ return q_sv.toString();
}
/*!
+ \fn QStringView QStringMatcher::patternView() const noexcept
+ \since 6.7
+
+ Returns a string view of the pattern that this string matcher will search for.
+
+ \sa setPattern()
+*/
+
+/*!
Sets the case sensitivity setting of this string matcher to \a
cs.
@@ -279,7 +265,8 @@ void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs)
updateSkipTable();
}
-/*!
+/*! \fn qsizetype QStringMatcher::indexIn(const QString &str, qsizetype from) const
+
Searches the string \a str from character position \a from
(default 0, i.e. from the first character), for the string
pattern() that was set in the constructor or in the most recent
@@ -288,12 +275,8 @@ void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs)
\sa setPattern(), setCaseSensitivity()
*/
-int QStringMatcher::indexIn(const QString &str, int from) const
-{
- return int(indexIn(QStringView(str), from));
-}
-/*!
+/*! \fn qsizetype QStringMatcher::indexIn(const QChar *str, qsizetype length, qsizetype from) const
\since 4.5
Searches the string starting at \a str (of length \a length) from
@@ -305,10 +288,6 @@ int QStringMatcher::indexIn(const QString &str, int from) const
\sa setPattern(), setCaseSensitivity()
*/
-int QStringMatcher::indexIn(const QChar *str, int length, int from) const
-{
- return int(indexIn(QStringView(str, length), from));
-}
/*!
\since 5.14
@@ -325,7 +304,7 @@ qsizetype QStringMatcher::indexIn(QStringView str, qsizetype from) const
{
if (from < 0)
from = 0;
- return bm_find(str, from, p.sv, p.q_skiptable, q_cs);
+ return bm_find(str, from, q_sv, q_skiptable, q_cs);
}
/*!
diff --git a/src/corelib/text/qstringmatcher.h b/src/corelib/text/qstringmatcher.h
index c731efcc97..937f17df0a 100644
--- a/src/corelib/text/qstringmatcher.h
+++ b/src/corelib/text/qstringmatcher.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Mail.ru Group.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Mail.ru Group.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGMATCHER_H
#define QSTRINGMATCHER_H
@@ -53,11 +17,13 @@ class Q_CORE_EXPORT QStringMatcher
{
void updateSkipTable();
public:
- QStringMatcher();
+ QStringMatcher() = default;
explicit QStringMatcher(const QString &pattern,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
- QStringMatcher(const QChar *uc, int len,
- Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QStringMatcher(const QChar *uc, qsizetype len,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ : QStringMatcher(QStringView(uc, len), cs)
+ {}
QStringMatcher(QStringView pattern,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
QStringMatcher(const QStringMatcher &other);
@@ -68,24 +34,23 @@ public:
void setPattern(const QString &pattern);
void setCaseSensitivity(Qt::CaseSensitivity cs);
- int indexIn(const QString &str, int from = 0) const;
- int indexIn(const QChar *str, int length, int from = 0) const;
+ qsizetype indexIn(const QString &str, qsizetype from = 0) const
+ { return indexIn(QStringView(str), from); }
+ qsizetype indexIn(const QChar *str, qsizetype length, qsizetype from = 0) const
+ { return indexIn(QStringView(str, length), from); }
qsizetype indexIn(QStringView str, qsizetype from = 0) const;
QString pattern() const;
+ QStringView patternView() const noexcept
+ { return q_sv; }
+
inline Qt::CaseSensitivity caseSensitivity() const { return q_cs; }
private:
- QStringMatcherPrivate *d_ptr;
+ QStringMatcherPrivate *d_ptr = nullptr;
+ Qt::CaseSensitivity q_cs = Qt::CaseSensitive;
QString q_pattern;
- Qt::CaseSensitivity q_cs;
- struct Data {
- uchar q_skiptable[256];
- QStringView sv;
- };
- union {
- uint q_data[256];
- Data p;
- };
+ QStringView q_sv;
+ uchar q_skiptable[256] = {};
};
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringtokenizer.cpp b/src/corelib/text/qstringtokenizer.cpp
index 4e8ffc2c8e..fc6faed27f 100644
--- a/src/corelib/text/qstringtokenizer.cpp
+++ b/src/corelib/text/qstringtokenizer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstringtokenizer.h"
#include "qstringalgorithms.h"
@@ -73,7 +37,7 @@ QT_BEGIN_NAMESPACE
Argument Deduction (CTAD), you may write
\c{QStringTokenizer{string, separator}} (without template
arguments). If you can't use C++17 CTAD, you must use the
- QStringView::split() or QLatin1String::split() member functions
+ QStringView::split() or QLatin1StringView::split() member functions
and store the return value only in \c{auto} variables:
\code
@@ -143,30 +107,30 @@ QT_BEGIN_NAMESPACE
use(e);
\endcode
- \sa QStringView::split(), QLatin1String::split(), QRegularExpression
+ \sa QStringView::split(), QString::split(), QRegularExpression
*/
/*!
- \typedef QStringTokenizer::value_type
+ \typealias QStringTokenizer::value_type
- Alias for \c{const QStringView} or \c{const QLatin1String},
+ Alias for \c{const QStringView} or \c{const QLatin1StringView},
depending on the tokenizer's \c Haystack template argument.
*/
/*!
- \typedef QStringTokenizer::difference_type
+ \typealias QStringTokenizer::difference_type
Alias for qsizetype.
*/
/*!
- \typedef QStringTokenizer::size_type
+ \typealias QStringTokenizer::size_type
Alias for qsizetype.
*/
/*!
- \typedef QStringTokenizer::reference
+ \typealias QStringTokenizer::reference
Alias for \c{value_type &}.
@@ -175,13 +139,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \typedef QStringTokenizer::const_reference
+ \typealias QStringTokenizer::const_reference
Alias for \c{value_type &}.
*/
/*!
- \typedef QStringTokenizer::pointer
+ \typealias QStringTokenizer::pointer
Alias for \c{value_type *}.
@@ -190,13 +154,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \typedef QStringTokenizer::const_pointer
+ \typealias QStringTokenizer::const_pointer
Alias for \c{value_type *}.
*/
/*!
- \typedef QStringTokenizer::iterator
+ \typealias QStringTokenizer::iterator
This typedef provides an STL-style const iterator for
QStringTokenizer.
@@ -217,7 +181,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \typedef QStringTokenizer::sentinel
+ \typealias QStringTokenizer::sentinel
This typedef provides an STL-style sentinel for
QStringTokenizer::iterator and QStringTokenizer::const_iterator.
@@ -226,8 +190,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringTokenizer(Haystack haystack, String needle, Qt::CaseSensitivity cs, Qt::SplitBehavior sb)
- \fn QStringTokenizer(Haystack haystack, String needle, Qt::SplitBehavior sb, Qt::CaseSensitivity cs)
+ \fn template <typename Haystack, typename Needle> QStringTokenizer<Haystack, Needle>::QStringTokenizer(Haystack haystack, Needle needle, Qt::CaseSensitivity cs, Qt::SplitBehavior sb)
+ \fn template <typename Haystack, typename Needle> QStringTokenizer<Haystack, Needle>::QStringTokenizer(Haystack haystack, Needle needle, Qt::SplitBehavior sb, Qt::CaseSensitivity cs)
Constructs a string tokenizer that splits the string \a haystack
into substrings wherever \a needle occurs, and allows iteration
@@ -238,31 +202,24 @@ QT_BEGIN_NAMESPACE
\a cs specifies whether \a needle should be matched case
sensitively or case insensitively.
- If \a sb is QString::SkipEmptyParts, empty entries don't
+ If \a sb is Qt::SkipEmptyParts, empty entries don't
appear in the result. By default, empty entries are included.
- \sa QStringView::split(), QLatin1String::split(), Qt::CaseSensitivity, Qt::SplitBehavior
+ \sa QStringView::split(), QString::split(), Qt::CaseSensitivity, Qt::SplitBehavior
*/
/*!
- \fn QStringTokenizer::const_iterator QStringTokenizer::begin() const
+ \fn template <typename Haystack, typename Needle> QStringTokenizer<Haystack, Needle>::iterator QStringTokenizer<Haystack, Needle>::begin() const
+ \fn template <typename Haystack, typename Needle> QStringTokenizer<Haystack, Needle>::iterator QStringTokenizer<Haystack, Needle>::cbegin() const
Returns a const \l{STL-style iterators}{STL-style iterator}
pointing to the first token in the list.
- \sa end(), cbegin()
+ \sa end(), cend()
*/
/*!
- \fn QStringTokenizer::const_iterator QStringTokenizer::cbegin() const
-
- Same as begin().
-
- \sa cend(), begin()
-*/
-
-/*!
- \fn QStringTokenizer::sentinel QStringTokenizer::end() const
+ \fn template <typename Haystack, typename Needle> QStringTokenizer<Haystack, Needle>::sentinel QStringTokenizer<Haystack, Needle>::end() const
Returns a const \l{STL-style iterators}{STL-style sentinel}
pointing to the imaginary token after the last token in the list.
@@ -271,7 +228,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringTokenizer::sentinel QStringTokenizer::cend() const
+ \fn template <typename Haystack, typename Needle> QStringTokenizer<Haystack, Needle>::sentinel QStringTokenizer<Haystack, Needle>::cend() const
Same as end().
@@ -279,19 +236,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringTokenizer::toContainer(Container &&c) const &
+ \fn template <typename Haystack, typename Needle> template<typename LContainer> LContainer QStringTokenizer<Haystack, Needle>::toContainer(LContainer &&c) const &
- Convenience method to convert the lazy sequence into a
- (typically) random-access container.
+ Converts the lazy sequence into a (typically) random-access container of
+ type \c LContainer.
This function is only available if \c Container has a \c value_type
matching this tokenizer's value_type.
- If you pass in a named container (an lvalue), then that container
- is filled, and a reference to it is returned.
-
- If you pass in a temporary container (an rvalue, incl. the default
- argument), then that container is filled, and returned by value.
+ If you pass in a named container (an lvalue) for \a c, then that container
+ is filled, and a reference to it is returned. If you pass in a temporary
+ container (an rvalue, incl. the default argument), then that container is
+ filled, and returned by value.
\code
// assuming tok's value_type is QStringView, then...
@@ -311,9 +267,12 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringTokenizer::toContainer(Container &&c) const &&
+ \fn template <typename Haystack, typename Needle> template<typename RContainer> RContainer QStringTokenizer<Haystack, Needle>::toContainer(RContainer &&c) const &&
\overload
+ Converts the lazy sequence into a (typically) random-access container of
+ type \c RContainer.
+
In addition to the constraints on the lvalue-this overload, this
rvalue-this overload is only available when this QStringTokenizer
does not store the haystack internally, as this could create a
@@ -341,17 +300,30 @@ QT_BEGIN_NAMESPACE
func(QStringTokenizer{QStringView{widget.text()}, u','}.toContainer());
// OK: compiler keeps widget.text() around until after func() has executed
\endcode
+
+ If you pass in a named container (an lvalue)for \a c, then that container
+ is filled, and a reference to it is returned. If you pass in a temporary
+ container (an rvalue, incl. the default argument), then that container is
+ filled, and returned by value.
*/
/*!
- \fn qTokenize(Haystack &&haystack, Needle &&needle, Flags...flags)
+ \fn template <typename Haystack, typename Needle, typename...Flags> auto qTokenize(Haystack &&haystack, Needle &&needle, Flags...flags)
\relates QStringTokenizer
\since 6.0
- Factory function for QStringTokenizer. You can use this function
- if your compiler doesn't, yet, support C++17 Class Template
- Argument Deduction (CTAD), but we recommend direct use of
- QStringTokenizer with CTAD instead.
+ Factory function for a QStringTokenizer that splits the string \a haystack
+ into substrings wherever \a needle occurs, and allows iteration
+ over those strings as they are found. If \a needle does not match
+ anywhere in \a haystack, a single element containing \a haystack
+ is produced.
+
+ Pass values from Qt::CaseSensitivity and Qt::SplitBehavior enumerators
+ as \a flags to modify the behavior of the tokenizer.
+
+ You can use this function if your compiler doesn't, yet, support C++17 Class
+ Template Argument Deduction (CTAD). We recommend direct use of QStringTokenizer
+ with CTAD instead.
*/
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringtokenizer.h b/src/corelib/text/qstringtokenizer.h
index 4db23db57f..7a627b4508 100644
--- a/src/corelib/text/qstringtokenizer.h
+++ b/src/corelib/text/qstringtokenizer.h
@@ -1,54 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGTOKENIZER_H
#define QSTRINGTOKENIZER_H
#include <QtCore/qnamespace.h>
#include <QtCore/qcontainerfwd.h>
+#include <iterator>
QT_BEGIN_NAMESPACE
template <typename, typename> class QStringBuilder;
-#if defined(Q_QDOC) || 1 || (defined(__cpp_range_based_for) && __cpp_range_based_for >= 201603)
-# define Q_STRINGTOKENIZER_USE_SENTINEL
-#endif
+#define Q_STRINGTOKENIZER_USE_SENTINEL
class QStringTokenizerBaseBase
{
@@ -109,8 +72,8 @@ public:
iterator() noexcept = default;
// violates std::forward_iterator (returns a reference into the iterator)
- Q_REQUIRED_RESULT constexpr const Haystack* operator->() const { return Q_ASSERT(current.ok), &current.value; }
- Q_REQUIRED_RESULT constexpr const Haystack& operator*() const { return *operator->(); }
+ [[nodiscard]] constexpr const Haystack* operator->() const { return Q_ASSERT(current.ok), &current.value; }
+ [[nodiscard]] constexpr const Haystack& operator*() const { return *operator->(); }
iterator& operator++() { advance(); return *this; }
iterator operator++(int) { auto tmp = *this; advance(); return tmp; }
@@ -145,12 +108,12 @@ public:
using reference = typename iterator::reference;
using const_reference = reference;
- Q_REQUIRED_RESULT iterator begin() const noexcept { return iterator{*this}; }
- Q_REQUIRED_RESULT iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] iterator begin() const noexcept { return iterator{*this}; }
+ [[nodiscard]] iterator cbegin() const noexcept { return begin(); }
template <bool = std::is_same<iterator, sentinel>::value> // ODR protection
- Q_REQUIRED_RESULT constexpr sentinel end() const noexcept { return {}; }
+ [[nodiscard]] constexpr sentinel end() const noexcept { return {}; }
template <bool = std::is_same<iterator, sentinel>::value> // ODR protection
- Q_REQUIRED_RESULT constexpr sentinel cend() const noexcept { return {}; }
+ [[nodiscard]] constexpr sentinel cend() const noexcept { return {}; }
private:
Haystack m_haystack;
@@ -170,10 +133,9 @@ namespace Tok {
template <typename String> struct ViewForImpl {};
template <> struct ViewForImpl<QStringView> { using type = QStringView; };
- template <> struct ViewForImpl<QLatin1String> { using type = QLatin1String; };
+ template <> struct ViewForImpl<QLatin1StringView> { using type = QLatin1StringView; };
template <> struct ViewForImpl<QChar> { using type = QChar; };
template <> struct ViewForImpl<QString> : ViewForImpl<QStringView> {};
- template <> struct ViewForImpl<QStringRef> : ViewForImpl<QStringView> {};
template <> struct ViewForImpl<QLatin1Char> : ViewForImpl<QChar> {};
template <> struct ViewForImpl<char16_t> : ViewForImpl<QChar> {};
template <> struct ViewForImpl<char16_t*> : ViewForImpl<QStringView> {};
@@ -188,7 +150,7 @@ namespace Tok {
#endif
// This metafunction maps a StringLike to a View (currently, QChar,
- // QStringView, QLatin1String). This is what QStringTokenizerBase
+ // QStringView, QLatin1StringView). This is what QStringTokenizerBase
// operates on. QStringTokenizer adds pinning to keep rvalues alive
// for the duration of the algorithm.
template <typename String>
@@ -295,14 +257,30 @@ class QStringTokenizer
using if_haystack_not_pinned = typename if_haystack_not_pinned_impl<Container, HPin>::type;
template <typename Container, typename Iterator = decltype(std::begin(std::declval<Container>()))>
using if_compatible_container = typename std::enable_if<
- std::is_same<
+ std::is_convertible<
typename Base::value_type,
typename std::iterator_traits<Iterator>::value_type
>::value,
bool
>::type;
public:
- using value_type = typename Base::value_type;
+ using value_type = typename Base::value_type;
+ using difference_type = typename Base::difference_type;
+ using size_type = typename Base::size_type;
+ using reference = typename Base::reference;
+ using const_reference = typename Base::const_reference;
+ using pointer = typename Base::pointer;
+ using const_pointer = typename Base::const_pointer;
+ using iterator = typename Base::iterator;
+ using const_iterator = typename Base::const_iterator;
+ using sentinel = typename Base::sentinel;
+
+#ifdef Q_QDOC
+ [[nodiscard]] iterator begin() const noexcept { return Base::begin(); }
+ [[nodiscard]] iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr sentinel end() const noexcept { return {}; }
+ [[nodiscard]] constexpr sentinel cend() const noexcept { return {}; }
+#endif
constexpr explicit QStringTokenizer(Haystack haystack, Needle needle,
Qt::CaseSensitivity cs,
@@ -329,22 +307,26 @@ public:
this->needleView(needle), sb, cs}
{}
+#ifdef Q_QDOC
+ template<typename LContainer> LContainer toContainer(LContainer &&c = {}) const & {}
+ template<typename RContainer> RContainer toContainer(RContainer &&c = {}) const && {}
+#else
template<typename Container = QList<value_type>, if_compatible_container<Container> = true>
Container toContainer(Container &&c = {}) const &
{
for (auto e : *this)
c.emplace_back(e);
- return c;
+ return std::forward<Container>(c);
}
-
template<typename Container = QList<value_type>, if_compatible_container<Container> = true,
if_haystack_not_pinned<Container> = true>
Container toContainer(Container &&c = {}) const &&
{
for (auto e : *this)
c.emplace_back(e);
- return c;
+ return std::forward<Container>(c);
}
+#endif
};
namespace QtPrivate {
@@ -396,7 +378,7 @@ QStringTokenizer(Haystack&&, Needle&&, Qt::CaseSensitivity, Qt::SplitBehavior)
#undef Q_TOK_RESULT
template <typename Haystack, typename Needle, typename...Flags>
-Q_REQUIRED_RESULT constexpr auto
+[[nodiscard]] constexpr auto
qTokenize(Haystack &&h, Needle &&n, Flags...flags)
noexcept(QtPrivate::Tok::is_nothrow_constructible_from<Haystack, Needle>::value)
-> decltype(QtPrivate::Tok::TokenizerResult<Haystack, Needle>{std::forward<Haystack>(h),
@@ -417,13 +399,13 @@ auto QStringTokenizerBase<Haystack, Needle>::next(tokenizer_state state) const n
Haystack result;
if (state.end >= 0) {
// token separator found => return intermediate element:
- result = m_haystack.mid(state.start, state.end - state.start);
+ result = m_haystack.sliced(state.start, state.end - state.start);
const auto ns = QtPrivate::Tok::size(m_needle);
state.start = state.end + ns;
state.extra = (ns == 0 ? 1 : 0);
} else {
// token separator not found => return final element:
- result = m_haystack.mid(state.start);
+ result = m_haystack.sliced(state.start);
}
if ((m_sb & Qt::SkipEmptyParts) && result.isEmpty())
continue;
diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp
index 985d87ac51..29b83ffe8f 100644
--- a/src/corelib/text/qstringview.cpp
+++ b/src/corelib/text/qstringview.cpp
@@ -1,45 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstringview.h"
-#include "qstring.h"
-#include "qlocale_p.h"
QT_BEGIN_NAMESPACE
@@ -69,8 +31,8 @@ QT_BEGIN_NAMESPACE
When used as an interface type, QStringView allows a single function to accept
a wide variety of UTF-16 string data sources. One function accepting QStringView
- thus replaces three function overloads (taking QString, QStringRef, and
- \c{(const QChar*, int)}), while at the same time enabling even more string data
+ thus replaces three function overloads (taking QString and
+ \c{(const QChar*, qsizetype)}), while at the same time enabling even more string data
sources to be passed to the function, such as \c{u"Hello World"}, a \c char16_t
string literal.
@@ -87,11 +49,11 @@ QT_BEGIN_NAMESPACE
QChar constructor by itself.
\li \e QString: if you store an unmodified copy of the string and thus would
like to take advantage of QString's implicit sharing.
- \li QLatin1String: if you can implement the function without converting the
- QLatin1String to UTF-16 first; users expect a function overloaded on
- QLatin1String to perform strictly less memory allocations than the
+ \li QLatin1StringView: if you can implement the function without converting the
+ QLatin1StringView to UTF-16 first; users expect a function overloaded on
+ QLatin1StringView to perform strictly less memory allocations than the
semantically equivalent call of the QStringView version, involving
- construction of a QString from the QLatin1String.
+ construction of a QString from the QLatin1StringView.
\endlist
QStringView can also be used as the return value of a function. If you call a
@@ -105,11 +67,7 @@ QT_BEGIN_NAMESPACE
allowed in \c constexpr functions). You can use an indexed loop and/or utf16() in
\c constexpr contexts instead.
- \note We strongly discourage the use of QList<QStringView>,
- because QList is a very inefficient container for QStringViews (it would heap-allocate
- every element). Use QList (or std::vector) to hold QStringViews instead.
-
- \sa QString, QStringRef
+ \sa QString
*/
/*!
@@ -134,11 +92,6 @@ QT_BEGIN_NAMESPACE
\typedef QStringView::size_type
Alias for qsizetype. Provided for compatibility with the STL.
-
- Unlike other Qt classes, QStringView uses qsizetype as its \c size_type, to allow
- accepting data from \c{std::basic_string} without truncation. The Qt API functions,
- for example length(), return \c int, while the STL-compatible functions, for example
- size(), return \c size_type.
*/
/*!
@@ -226,7 +179,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename Char> QStringView::QStringView(const Char *str, qsizetype len)
+ \fn template <typename Char, QStringView::if_compatible_char<Char> = true> QStringView::QStringView(const Char *str, qsizetype len)
Constructs a string view on \a str with length \a len.
@@ -242,7 +195,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename Char> QStringView::QStringView(const Char *first, const Char *last)
+ \fn template <typename Char, QStringView::if_compatible_char<Char> = true> QStringView::QStringView(const Char *first, const Char *last)
Constructs a string view on \a first with length (\a last - \a first).
@@ -282,11 +235,9 @@ QT_BEGIN_NAMESPACE
\fn template <typename Char, size_t N> QStringView::QStringView(const Char (&string)[N])
Constructs a string view on the character string literal \a string.
- The length is set to \c{N-1}, excluding the trailing \{Char(0)}.
- If you need the full array, use the constructor from pointer and
- size instead:
-
- \snippet code/src_corelib_text_qstringview.cpp 2
+ The view covers the array until the first \c{Char(0)} is encountered,
+ or \c N, whichever comes first.
+ If you need the full array, use fromArray() instead.
\a string must remain valid for the lifetime of this string view
object.
@@ -296,20 +247,12 @@ QT_BEGIN_NAMESPACE
type. The compatible character types are: \c QChar, \c ushort, \c
char16_t and (on platforms, such as Windows, where it is a 16-bit
type) \c wchar_t.
-*/
-
-/*!
- \fn QStringView::QStringView(const QString &str)
-
- Constructs a string view on \a str.
- \c{str.data()} must remain valid for the lifetime of this string view object.
-
- The string view will be null if and only if \c{str.isNull()}.
+ \sa fromArray
*/
/*!
- \fn QStringView::QStringView(const QStringRef &str)
+ \fn QStringView::QStringView(const QString &str)
Constructs a string view on \a str.
@@ -319,42 +262,59 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename StdBasicString> QStringView::QStringView(const StdBasicString &str)
+ \fn template <typename Container, QStringView::if_compatible_container<Container>> QStringView::QStringView(const Container &str)
- Constructs a string view on \a str. The length is taken from \c{str.size()}.
+ Constructs a string view on \a str. The length is taken from \c{std::size(str)}.
- \c{str.data()} must remain valid for the lifetime of this string view object.
+ \c{std::data(str)} must remain valid for the lifetime of this string view object.
- This constructor only participates in overload resolution if \c StdBasicString is an
- instantiation of \c std::basic_string with a compatible character type. The
+ This constructor only participates in overload resolution if \c Container is a
+ container with a compatible character type as \c{value_type}. The
compatible character types are: \c QChar, \c ushort, \c char16_t and
(on platforms, such as Windows, where it is a 16-bit type) \c wchar_t.
- The string view will be empty if and only if \c{str.empty()}. It is unspecified
- whether this constructor can result in a null string view (\c{str.data()} would
+ The string view will be empty if and only if \c{std::size(str) == 0}. It is unspecified
+ whether this constructor can result in a null string view (\c{std::data(str)} would
have to return \nullptr for this).
\sa isNull(), isEmpty()
*/
/*!
+ \fn template <typename Char, size_t Size, QStringView::if_compatible_char<Char> = true> static QStringView QStringView::fromArray(const Char (&string)[Size]) noexcept
+
+ Constructs a string view on the full character string literal \a string,
+ including any trailing \c{Char(0)}. If you don't want the
+ null-terminator included in the view then you can chop() it off
+ when you are certain it is at the end. Alternatively you can use
+ the constructor overload taking an array literal which will create
+ a view up to, but not including, the first null-terminator in the data.
+
+ \a string must remain valid for the lifetime of this string view
+ object.
+
+ This function will work with any array literal if \c Char is a
+ compatible character type. The compatible character types are: \c QChar, \c ushort, \c
+ char16_t and (on platforms, such as Windows, where it is a 16-bit
+ type) \c wchar_t.
+*/
+
+/*!
\fn QString QStringView::toString() const
Returns a deep copy of this string view's data as a QString.
The return value will be the null QString if and only if this string view is null.
-
- \warning QStringView can store strings with more than 2\sup{30} characters
- while QString cannot. Calling this function on a string view for which size()
- returns a value greater than \c{INT_MAX / 2} constitutes undefined behavior.
*/
/*!
\fn const QChar *QStringView::data() const
- Returns a const pointer to the first character in the string.
+//! [const-pointer-to-first-ch]
+ Returns a const pointer to the first character in the string view.
\note The character array represented by the return value is \e not null-terminated.
+//! [const-pointer-to-first-ch]
\sa begin(), end(), utf16()
*/
@@ -363,9 +323,7 @@ QT_BEGIN_NAMESPACE
\fn const QChar *QStringView::constData() const
\since 6.0
- Returns a const pointer to the first character in the string.
-
- \note The character array represented by the return value is \e not null-terminated.
+ \include qstringview.cpp const-pointer-to-first-ch
\sa data(), begin(), end(), utf16()
*/
@@ -373,12 +331,10 @@ QT_BEGIN_NAMESPACE
/*!
\fn const storage_type *QStringView::utf16() const
- Returns a const pointer to the first character in the string.
+ \include qstringview.cpp const-pointer-to-first-ch
\c{storage_type} is \c{char16_t}.
- \note The character array represented by the return value is \e not null-terminated.
-
\sa begin(), end(), data()
*/
@@ -386,11 +342,11 @@ QT_BEGIN_NAMESPACE
\fn QStringView::const_iterator QStringView::begin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
- the string.
+ the string view.
This function is provided for STL compatibility.
- \sa end(), cbegin(), rbegin(), data()
+ \sa end(), constBegin(), cbegin(), rbegin(), data()
*/
/*!
@@ -400,7 +356,16 @@ QT_BEGIN_NAMESPACE
This function is provided for STL compatibility.
- \sa cend(), begin(), crbegin(), data()
+ \sa cend(), begin(), constBegin(), crbegin(), data()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::constBegin() const
+ \since 6.1
+
+ Same as begin().
+
+ \sa constEnd(), begin(), cbegin(), crbegin(), data()
*/
/*!
@@ -411,7 +376,7 @@ QT_BEGIN_NAMESPACE
This function is provided for STL compatibility.
- \sa begin(), cend(), rend()
+ \sa begin(), constEnd(), cend(), rend()
*/
/*! \fn QStringView::const_iterator QStringView::cend() const
@@ -420,14 +385,22 @@ QT_BEGIN_NAMESPACE
This function is provided for STL compatibility.
- \sa cbegin(), end(), crend()
+ \sa cbegin(), end(), constEnd(), crend()
+*/
+
+/*! \fn QStringView::const_iterator QStringView::constEnd() const
+ \since 6.1
+
+ Same as end().
+
+ \sa constBegin(), end(), cend(), crend()
*/
/*!
\fn QStringView::const_reverse_iterator QStringView::rbegin() const
Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- character in the string, in reverse order.
+ character in the string view, in reverse order.
This function is provided for STL compatibility.
@@ -448,7 +421,7 @@ QT_BEGIN_NAMESPACE
\fn QStringView::const_reverse_iterator QStringView::rend() const
Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last character in the string, in reverse order.
+ the last character in the string view, in reverse order.
This function is provided for STL compatibility.
@@ -498,24 +471,20 @@ QT_BEGIN_NAMESPACE
/*!
\fn qsizetype QStringView::size() const
- Returns the size of this string view, in UTF-16 code points (that is,
+ Returns the size of this string view, in UTF-16 code units (that is,
surrogate pairs count as two for the purposes of this function, the same
- as in QString and QStringRef).
+ as in QString).
\sa empty(), isEmpty(), isNull(), length()
*/
/*!
- \fn int QStringView::length() const
+ \fn QStringView::length() const
- Same as size(), except returns the result as an \c int.
+ Same as size().
This function is provided for compatibility with other Qt containers.
- \warning QStringView can represent strings with more than 2\sup{31} characters.
- Calling this function on a string view for which size() returns a value greater
- than \c{INT_MAX} constitutes undefined behavior.
-
\sa empty(), isEmpty(), isNull(), size()
*/
@@ -541,7 +510,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename...Args> QString QStringView::arg(Args &&...args) const
- \fn template <typename...Args> QString QLatin1String::arg(Args &&...args) const
+ \fn template <typename...Args> QString QLatin1StringView::arg(Args &&...args) const
\fn template <typename...Args> QString QString::arg(Args &&...args) const
\since 5.14
@@ -551,7 +520,7 @@ QT_BEGIN_NAMESPACE
second of the \a args the \c{%N} with the next-lowest \c{N} etc.
\c Args can consist of anything that implicitly converts to QString,
- QStringView or QLatin1String.
+ QStringView or QLatin1StringView.
In addition, the following types are also supported: QChar, QLatin1Char.
@@ -561,12 +530,14 @@ QT_BEGIN_NAMESPACE
/*!
\fn QChar QStringView::front() const
- Returns the first character in the string. Same as first().
+ Returns the first character in the string view. Same as first().
This function is provided for STL compatibility.
+//! [calling-on-empty-is-UB]
\warning Calling this function on an empty string view constitutes
undefined behavior.
+//! [calling-on-empty-is-UB]
\sa back(), first(), last()
*/
@@ -574,12 +545,11 @@ QT_BEGIN_NAMESPACE
/*!
\fn QChar QStringView::back() const
- Returns the last character in the string. Same as last().
+ Returns the last character in the string view. Same as last().
This function is provided for STL compatibility.
- \warning Calling this function on an empty string view constitutes
- undefined behavior.
+ \include qstringview.cpp calling-on-empty-is-UB
\sa front(), first(), last()
*/
@@ -587,12 +557,11 @@ QT_BEGIN_NAMESPACE
/*!
\fn QChar QStringView::first() const
- Returns the first character in the string. Same as front().
+ Returns the first character in the string view. Same as front().
This function is provided for compatibility with other Qt containers.
- \warning Calling this function on an empty string view constitutes
- undefined behavior.
+ \include qstringview.cpp calling-on-empty-is-UB
\sa front(), back(), last()
*/
@@ -600,12 +569,11 @@ QT_BEGIN_NAMESPACE
/*!
\fn QChar QStringView::last() const
- Returns the last character in the string. Same as back().
+ Returns the last character in the string view. Same as back().
This function is provided for compatibility with other Qt containers.
- \warning Calling this function on an empty string view constitutes
- undefined behavior.
+ \include qstringview.cpp calling-on-empty-is-UB
\sa back(), front(), first()
*/
@@ -616,11 +584,11 @@ QT_BEGIN_NAMESPACE
Returns the substring of length \a length starting at position
\a start in this object.
- \obsolete Use sliced() instead in new code.
+ \deprecated Use sliced() instead in new code.
Returns an empty string view if \a start exceeds the
- length of the string. If there are less than \a length characters
- available in the string starting at \a start, or if
+ length of the string view. If there are less than \a length characters
+ available in the string view starting at \a start, or if
\a length is negative (default), the function returns all characters that
are available from \a start.
@@ -630,12 +598,12 @@ QT_BEGIN_NAMESPACE
/*!
\fn QStringView QStringView::left(qsizetype length) const
- \obsolete Use first() instead in new code.
+ \deprecated Use first() instead in new code.
Returns the substring of length \a length starting at position
0 in this object.
- The entire string is returned if \a length is greater than or equal
+ The entire string view is returned if \a length is greater than or equal
to size(), or less than zero.
\sa first(), last(), sliced(), startsWith(), chopped(), chop(), truncate()
@@ -644,12 +612,12 @@ QT_BEGIN_NAMESPACE
/*!
\fn QStringView QStringView::right(qsizetype length) const
- \obsolete Use last() instead in new code.
+ \deprecated Use last() instead in new code.
Returns the substring of length \a length starting at position
size() - \a length in this object.
- The entire string is returned if \a length is greater than or equal
+ The entire string view is returned if \a length is greater than or equal
to size(), or less than zero.
\sa first(), last(), sliced(), endsWith(), chopped(), chop(), truncate()
@@ -660,45 +628,51 @@ QT_BEGIN_NAMESPACE
\since 6.0
Returns a string view that points to the first \a n characters
- of this string.
+ of this string view.
\note The behavior is undefined when \a n < 0 or \a n > size().
- \sa last(), subString(), startsWith(), chopped(), chop(), truncate()
+ \sa last(), sliced(), startsWith(), chopped(), chop(), truncate()
*/
/*!
\fn QStringView QStringView::last(qsizetype n) const
\since 6.0
- Returns a string view that points to the last \a n characters of this string.
+ Returns a string view that points to the last \a n characters of this string
+ view.
\note The behavior is undefined when \a n < 0 or \a n > size().
- \sa first(), subString(), endsWith(), chopped(), chop(), truncate()
+ \sa first(), sliced(), endsWith(), chopped(), chop(), truncate()
*/
/*!
\fn QStringView QStringView::sliced(qsizetype pos, qsizetype n) const
\since 6.0
- Returns a string view that points to \a n characters of this string,
+ Returns a string view that points to \a n characters of this string view,
starting at position \a pos.
+//! [UB-sliced-index-length]
\note The behavior is undefined when \a pos < 0, \a n < 0,
or \a pos + \a n > size().
+//! [UB-sliced-index-length]
\sa first(), last(), chopped(), chop(), truncate()
*/
/*!
- \fn QStringView QStringView::from(qsizetype pos) const
+ \fn QStringView QStringView::sliced(qsizetype pos) const
\since 6.0
+ \overload
Returns a string view starting at position \a pos in this object,
and extending to its end.
+//! [UB-sliced-index-only]
\note The behavior is undefined when \a pos < 0 or \a pos > size().
+//! [UB-sliced-index-only]
\sa first(), last(), chopped(), chop(), truncate()
*/
@@ -754,115 +728,286 @@ QT_BEGIN_NAMESPACE
\fn int QStringView::compare(QStringView str, Qt::CaseSensitivity cs) const
\since 5.12
- Returns an integer that compares to zero as this string-view compares to the
- string-view \a str.
+ Compares this string view with string view \a str and returns a negative integer if
+ this string view is less than \a str, a positive integer if it is greater than
+ \a str, and zero if they are equal.
- If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
- otherwise the comparison is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
\sa operator==(), operator<(), operator>()
*/
/*!
- \fn int QStringView::compare(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn int QStringView::compare(QUtf8StringView str, Qt::CaseSensitivity cs) const
+ \since 6.5
+
+ Compares this string view with QUtf8StringView \a str and returns a negative integer if
+ this string view is less than \a str, a positive integer if it is greater than
+ \a str, and zero if they are equal.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
+
+ \sa operator==(), operator<(), operator>()
+*/
+
+/*!
+ \fn int QStringView::compare(QLatin1StringView l1, Qt::CaseSensitivity cs) const
\fn int QStringView::compare(QChar ch) const
\fn int QStringView::compare(QChar ch, Qt::CaseSensitivity cs) const
- \since 5.14
+ \since 5.15
- Returns an integer that compares to zero as this string-view compares to the
- Latin-1 string \a l1, or character \a ch, respectively.
+ Compares this string view to the Latin-1 string view \a l1, or the character \a ch.
+ Returns a negative integer if this string view is less than \a l1 or \a ch,
+ a positive integer if it is greater than \a l1 or \a ch, and zero if they are equal.
- If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
- otherwise the comparison is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
\sa operator==(), operator<(), operator>()
*/
/*!
+ \fn QStringView::operator==(const QStringView &lhs, const QStringView &rhs)
+ \fn QStringView::operator!=(const QStringView &lhs, const QStringView &rhs)
+ \fn QStringView::operator< (const QStringView &lhs, const QStringView &rhs)
+ \fn QStringView::operator<=(const QStringView &lhs, const QStringView &rhs)
+ \fn QStringView::operator> (const QStringView &lhs, const QStringView &rhs)
+ \fn QStringView::operator>=(const QStringView &lhs, const QStringView &rhs)
+
+ Operators for comparing \a lhs to \a rhs.
+
+ \sa compare()
+*/
+
+/*!
+ \fn int QStringView::localeAwareCompare(QStringView other) const
+ \since 6.4
+
+ Compares this string view with the \a other string view and returns
+ an integer less than, equal to, or greater than zero if this string
+ view is less than, equal to, or greater than the \a other string view.
+
+ The comparison is performed in a locale- and also platform-dependent
+ manner. Use this function to present sorted lists of strings to the
+ user.
+
+ \sa {Comparing Strings}
+*/
+
+/*
+//! [utf16-or-latin1-or-ch]
+the UTF-16 string viewed by \a str, the Latin-1 string viewed by \a l1,
+or the character \a ch
+//! [utf16-or-latin1-or-ch]
+*/
+
+/*!
\fn bool QStringView::startsWith(QStringView str, Qt::CaseSensitivity cs) const
- \fn bool QStringView::startsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::startsWith(QLatin1StringView l1, Qt::CaseSensitivity cs) const
\fn bool QStringView::startsWith(QChar ch) const
\fn bool QStringView::startsWith(QChar ch, Qt::CaseSensitivity cs) const
- Returns \c true if this string-view starts with string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively;
- otherwise returns \c false.
+ Returns \c true if this string view starts with
+ \include qstringview.cpp utf16-or-latin1-or-ch
+ respectively; otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
- otherwise the search is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa endsWith()
*/
/*!
\fn bool QStringView::endsWith(QStringView str, Qt::CaseSensitivity cs) const
- \fn bool QStringView::endsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::endsWith(QLatin1StringView l1, Qt::CaseSensitivity cs) const
\fn bool QStringView::endsWith(QChar ch) const
\fn bool QStringView::endsWith(QChar ch, Qt::CaseSensitivity cs) const
- Returns \c true if this string-view ends with string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively;
- otherwise returns \c false.
+ Returns \c true if this string view ends with
+ \include qstringview.cpp utf16-or-latin1-or-ch
+ respectively; otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
- otherwise the search is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa startsWith()
*/
/*!
\fn qsizetype QStringView::indexOf(QStringView str, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \fn qsizetype QStringView::indexOf(QLatin1String l1, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QStringView::indexOf(QLatin1StringView l1, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\fn qsizetype QStringView::indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.14
- Returns the index position of the first occurrence of the string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively, in this string-view,
- searching forward from index position \a from. Returns -1 if \a str is not found.
+ Returns the index position of the first occurrence of
+ \include qstringview.cpp utf16-or-latin1-or-ch
+ respectively, in this string view, searching forward from index position
+ \a from. Returns -1 if \a str, \a l1 or \a ch is not found, respectively.
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
- If \a from is -1, the search starts at the last character; if it is
- -2, at the next to last character and so on.
+ \include qstring.qdocinc negative-index-start-search-from-end
\sa QString::indexOf()
*/
/*!
\fn bool QStringView::contains(QStringView str, Qt::CaseSensitivity cs) const
- \fn bool QStringView::contains(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::contains(QLatin1StringView l1, Qt::CaseSensitivity cs) const
\fn bool QStringView::contains(QChar c, Qt::CaseSensitivity cs) const
\since 5.14
- Returns \c true if this string-view contains an occurrence of the string-view
- \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false.
+ Returns \c true if this string view contains an occurrence of
+ \include qstringview.cpp utf16-or-latin1-or-ch
+ respectively; otherwise returns \c false.
- If \a cs is Qt::CaseSensitive (the default), the search is
- case-sensitive; otherwise the search is case-insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa indexOf()
*/
/*!
\fn qsizetype QStringView::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
- \fn qsizetype QStringView::lastIndexOf(QLatin1String l1, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringView::lastIndexOf(QLatin1StringView l1, qsizetype from, Qt::CaseSensitivity cs) const
\fn qsizetype QStringView::lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const
\since 5.14
- Returns the index position of the last occurrence of the string-view \a str,
- Latin-1 string \a l1, or character \a ch, respectively, in this string-view,
- searching backward from index position \a from. If \a from is -1 (default),
- the search starts at the last character; if \a from is -2, at the next to last
- character and so on. Returns -1 if \a str is not found.
+ Returns the index position of the last occurrence of
+ \include qstringview.cpp utf16-or-latin1-or-ch
+ respectively, in this string view, searching backward from index
+ position \a from.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
- If \a cs is Qt::CaseSensitive (default), the search is case
- sensitive; otherwise the search is case insensitive.
+ Returns -1 if \a str, \a l1 or \a c is not found, respectively.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \note When searching for a 0-length \a str or \a l1, the match at
+ the end of the data is excluded from the search by a negative \a
+ from, even though \c{-1} is normally thought of as searching from
+ the end of the string view: the match at the end is \e after the
+ last character, so it is excluded. To include such a final empty
+ match, either give a positive value for \a from or omit the \a from
+ parameter entirely.
+
+ \sa QString::lastIndexOf()
+*/
+
+/*!
+ \fn qsizetype QStringView::lastIndexOf(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QStringView::lastIndexOf(QLatin1StringView l1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.2
+ \overload lastIndexOf()
+
+ Returns the index position of the last occurrence of the UTF-16 string viewed
+ by \a str or the Latin-1 string viewed by \a l1 respectively, in this string
+ view searching backward from the last character of this string view. Returns
+ -1 if \a str or \a l1 is not found, respectively.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa QString::lastIndexOf()
*/
/*!
+ \fn QStringView::lastIndexOf(QChar c, Qt::CaseSensitivity cs) const
+ \since 6.3
+ \overload lastIndexOf()
+*/
+
+#if QT_CONFIG(regularexpression)
+/*!
+ \fn qsizetype QStringView::indexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
+ \since 6.1
+
+ Returns the index position of the first match of the regular
+ expression \a re in the string view, searching forward from index
+ position \a from. Returns -1 if \a re didn't match anywhere.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ \note Due to how the regular expression matching algorithm works,
+ this function will actually match repeatedly from the beginning of
+ the string view until the position \a from is reached.
+*/
+
+/*!
+ \fn qsizetype QStringView::lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
+ \since 6.1
+
+ Returns the index position of the last match of the regular
+ expression \a re in the string view, which starts before the index
+ position \a from.
+
+ \include qstring.qdocinc negative-index-start-search-from-end
+
+ Returns -1 if \a re didn't match anywhere.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ \note Due to how the regular expression matching algorithm works,
+ this function will actually match repeatedly from the beginning of
+ the string view until the position \a from is reached.
+
+ \note When searching for a regular expression \a re that may match
+ 0 characters, the match at the end of the data is excluded from the
+ search by a negative \a from, even though \c{-1} is normally
+ thought of as searching from the end of the string view: the match
+ at the end is \e after the last character, so it is excluded. To
+ include such a final empty match, either give a positive value for
+ \a from or omit the \a from parameter entirely.
+*/
+
+/*!
+ \fn qsizetype QStringView::lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
+ \since 6.2
+
+ Returns the index position of the last match of the regular
+ expression \a re in the string view. Returns -1 if \a re didn't match
+ anywhere.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ \note Due to how the regular expression matching algorithm works,
+ this function will actually match repeatedly from the beginning of
+ the string view until the end of the string view is reached.
+*/
+
+/*!
+ \fn bool QStringView::contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const
+ \since 6.1
+
+ Returns \c true if the regular expression \a re matches somewhere in this
+ string view; otherwise returns \c false.
+
+ If the match is successful and \a rmatch is not \nullptr, it also
+ writes the results of the match into the QRegularExpressionMatch object
+ pointed to by \a rmatch.
+
+ \sa QRegularExpression::match()
+*/
+
+/*!
+ \fn qsizetype QStringView::count(const QRegularExpression &re) const
+ \since 6.1
+
+ Returns the number of times the regular expression \a re matches
+ in the string view.
+
+ For historical reasons, this function counts overlapping matches.
+ This behavior is different from simply iterating over the matches
+ in the string view using QRegularExpressionMatchIterator.
+
+ \sa QRegularExpression::globalMatch()
+
+*/
+#endif // QT_CONFIG(regularexpression)
+
+/*!
\fn QByteArray QStringView::toLatin1() const
Returns a Latin-1 representation of the string as a QByteArray.
@@ -889,7 +1034,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QByteArray QStringView::toUtf8() const
- Returns a UTF-8 representation of the string as a QByteArray.
+ Returns a UTF-8 representation of the string view as a QByteArray.
UTF-8 is a Unicode codec and can represent all characters in a Unicode
string like QString.
@@ -900,11 +1045,11 @@ QT_BEGIN_NAMESPACE
/*!
\fn QList<uint> QStringView::toUcs4() const
- Returns a UCS-4/UTF-32 representation of the string as a QList<uint>.
+ Returns a UCS-4/UTF-32 representation of the string view as a QList<uint>.
UCS-4 is a Unicode codec and therefore it is lossless. All characters from
- this string will be encoded in UCS-4. Any invalid sequence of code units in
- this string is replaced by the Unicode replacement character
+ this string view will be encoded in UCS-4. Any invalid sequence of code units in
+ this string view is replaced by the Unicode replacement character
(QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
The returned list is not 0-terminated.
@@ -919,19 +1064,19 @@ QT_BEGIN_NAMESPACE
Convert \a s to a QStringView ignoring \c{s.isNull()}.
- Returns a string-view that references \a{s}' data, but is never null.
+ Returns a string view that references \a{s}' data, but is never null.
- This is a faster way to convert a QString or QStringRef to a QStringView,
+ This is a faster way to convert a QString to a QStringView,
if null QStrings can legitimately be treated as empty ones.
- \sa QString::isNull(), QStringRef::isNull(), QStringView
+ \sa QString::isNull(), QStringView
*/
/*!
\fn bool QStringView::isRightToLeft() const
\since 5.11
- Returns \c true if the string is read right to left.
+ Returns \c true if the string view is read right to left.
\sa QString::isRightToLeft()
*/
@@ -940,7 +1085,7 @@ QT_BEGIN_NAMESPACE
\fn bool QStringView::isValidUtf16() const
\since 5.15
- Returns \c true if the string contains valid UTF-16 encoded data,
+ Returns \c true if the string view contains valid UTF-16 encoded data,
or \c false otherwise.
Note that this function does not perform any special validation of the
@@ -952,14 +1097,40 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn bool QStringView::isLower() const
+ \since 6.7
+ Returns \c true if this view is identical to its lowercase folding.
+
+ Note that this does \e not mean that the string view does not contain
+ uppercase letters (some uppercase letters do not have a lowercase
+ folding; they are left unchanged by toString().toLower()).
+ For more information, refer to the Unicode standard, section 3.13.
+
+ \sa QChar::toLower(), isUpper()
+*/
+
+/*!
+ \fn bool QStringView::isUpper() const
+ \since 6.7
+ Returns \c true if this view is identical to its uppercase folding.
+
+ Note that this does \e not mean that the the string view does not contain
+ lowercase letters (some lowercase letters do not have a uppercase
+ folding; they are left unchanged by toString().toUpper()).
+ For more information, refer to the Unicode standard, section 3.13.
+
+ \sa QChar::toUpper(), isLower()
+*/
+
+/*!
\fn QStringView::toWCharArray(wchar_t *array) const
\since 5.14
- Transcribes this string into the given \a array.
+ Transcribes this string view into the given \a array.
The caller is responsible for ensuring \a array is large enough to hold the
- \c wchar_t encoding of this string (allocating the array with the same length
- as the string is always sufficient). The array is encoded in UTF-16 on
+ \c wchar_t encoding of this string view (allocating the array with the same length
+ as the string view is always sufficient). The array is encoded in UTF-16 on
platforms where \c wchar_t is 2 bytes wide (e.g. Windows); otherwise (Unix
systems), \c wchar_t is assumed to be 4 bytes wide and the data is written
in UCS-4.
@@ -978,10 +1149,9 @@ QT_BEGIN_NAMESPACE
\overload count()
Returns the number of occurrences of the character \a ch in the
- string reference.
+ string view.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa QString::count(), contains(), indexOf()
*/
@@ -993,10 +1163,23 @@ QT_BEGIN_NAMESPACE
\overload count()
Returns the number of (potentially overlapping) occurrences of the
- string reference \a str in this string reference.
+ string view \a str in this string view.
- If \a cs is Qt::CaseSensitive (default), the search is
- case sensitive; otherwise the search is case insensitive.
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
+
+ \sa QString::count(), contains(), indexOf()
+*/
+
+/*!
+ \fn qsizetype QStringView::count(QLatin1StringView l1, Qt::CaseSensitivity cs) const noexcept
+
+ \since 6.4
+ \overload count()
+
+ Returns the number of (potentially overlapping) occurrences of the
+ Latin-1 string viewed by \a l1 in this string view.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {search}
\sa QString::count(), contains(), indexOf()
*/
@@ -1004,15 +1187,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn qint64 QStringView::toLongLong(bool *ok, int base) const
- Returns the string converted to a \c{long long} using base \a
+ Returns the string view converted to a \c{long long} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1026,15 +1209,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn quint64 QStringView::toULongLong(bool *ok, int base) const
- Returns the string converted to an \c{unsigned long long} using base \a
+ Returns the string view converted to an \c{unsigned long long} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1048,15 +1231,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn long QStringView::toLong(bool *ok, int base) const
- Returns the string converted to a \c long using base \a
+ Returns the string view converted to a \c long using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1070,15 +1253,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn ulong QStringView::toULong(bool *ok, int base) const
- Returns the string converted to an \c{unsigned long} using base \a
+ Returns the string view converted to an \c{unsigned long} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1092,15 +1275,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn int QStringView::toInt(bool *ok, int base) const
- Returns the string converted to an \c int using base \a
+ Returns the string view converted to an \c int using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1114,15 +1297,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn uint QStringView::toUInt(bool *ok, int base) const
- Returns the string converted to an \c{unsigned int} using base \a
+ Returns the string view converted to an \c{unsigned int} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1136,15 +1319,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn short QStringView::toShort(bool *ok, int base) const
- Returns the string converted to a \c short using base \a
+ Returns the string view converted to a \c short using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1158,15 +1341,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn ushort QStringView::toUShort(bool *ok, int base) const
- Returns the string converted to an \c{unsigned short} using base \a
+ Returns the string view converted to an \c{unsigned short} using base \a
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
- If \a base is 0, the C language convention is used: If the string
- begins with "0x", base 16 is used; if the string begins with "0",
+ If \a base is 0, the C language convention is used: if the string view
+ begins with "0x", base 16 is used; otherwise, if the string view begins with "0",
base 8 is used; otherwise, base 10 is used.
The string conversion will always happen in the 'C' locale. For locale
@@ -1180,7 +1363,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn double QStringView::toDouble(bool *ok) const
- Returns the string converted to a \c double value.
+ Returns the string view converted to a \c double value.
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
@@ -1203,7 +1386,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn float QStringView::toFloat(bool *ok) const
- Returns the string converted to a \c float value.
+ Returns the string view converted to a \c float value.
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
@@ -1221,11 +1404,11 @@ QT_BEGIN_NAMESPACE
/*!
- \fn QStringView::tokenize(Needle &&sep, Flags...flags) const
- \fn QLatin1String::tokenize(Needle &&sep, Flags...flags) const
- \fn QString::tokenize(Needle &&sep, Flags...flags) const &
- \fn QString::tokenize(Needle &&sep, Flags...flags) const &&
- \fn QString::tokenize(Needle &&sep, Flags...flags) &&
+ \fn template <typename Needle, typename...Flags> auto QStringView::tokenize(Needle &&sep, Flags...flags) const
+ \fn template <typename Needle, typename...Flags> auto QLatin1StringView::tokenize(Needle &&sep, Flags...flags) const
+ \fn template <typename Needle, typename...Flags> auto QString::tokenize(Needle &&sep, Flags...flags) const &
+ \fn template <typename Needle, typename...Flags> auto QString::tokenize(Needle &&sep, Flags...flags) const &&
+ \fn template <typename Needle, typename...Flags> auto QString::tokenize(Needle &&sep, Flags...flags) &&
Splits the string into substring views wherever \a sep occurs, and
returns a lazy sequence of those strings.
@@ -1261,4 +1444,13 @@ QT_BEGIN_NAMESPACE
\sa QStringTokenizer, qTokenize()
*/
+/*!
+ \fn QStringView::operator std::u16string_view() const
+ \since 6.7
+
+ Converts this QStringView object to a \c{std::u16string_view} object.
+ The returned view will have the same data pointer and length of
+ this view.
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h
index 17b60fdc42..ab97d834d3 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -1,67 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Copyright (C) 2019 Mail.ru Group.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// Copyright (C) 2019 Mail.ru Group.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTRINGVIEW_H
#define QSTRINGVIEW_H
-/*
- This macro enables three "levels" of QStringView support:
-
- 1. offer QStringView, overload some functions taking QString with
- QStringView
-
- 2. like 1, but remove all overloads of functions taking QStringRef,
- leaving only the function taking QStringView. Do this only where
- QStringRef overloads tradionally existed.
-
- 3. like 2, but replace functions taking QString, too.
-*/
-#ifndef QT_STRINGVIEW_LEVEL
-# define QT_STRINGVIEW_LEVEL 1
-#endif
-
#include <QtCore/qchar.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstringliteral.h>
#include <QtCore/qstringalgorithms.h>
#include <string>
+#include <string_view>
+#include <QtCore/q20type_traits.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
Q_FORWARD_DECLARE_CF_TYPE(CFString);
@@ -71,9 +22,12 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
QT_BEGIN_NAMESPACE
class QString;
-class QStringRef;
class QStringView;
class QRegularExpression;
+class QRegularExpressionMatch;
+#ifdef Q_QDOC
+class QUtf8StringView;
+#endif
namespace QtPrivate {
template <typename Char>
@@ -85,7 +39,7 @@ struct IsCompatibleCharTypeHelper
(std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {};
template <typename Char>
struct IsCompatibleCharType
- : IsCompatibleCharTypeHelper<typename std::remove_cv<typename std::remove_reference<Char>::type>::type> {};
+ : IsCompatibleCharTypeHelper<q20::remove_cvref_t<Char>> {};
template <typename Pointer>
struct IsCompatiblePointerHelper : std::false_type {};
@@ -94,7 +48,7 @@ struct IsCompatiblePointerHelper<Char*>
: IsCompatibleCharType<Char> {};
template <typename Pointer>
struct IsCompatiblePointer
- : IsCompatiblePointerHelper<typename std::remove_cv<typename std::remove_reference<Pointer>::type>::type> {};
+ : IsCompatiblePointerHelper<q20::remove_cvref_t<Pointer>> {};
template <typename T, typename Enable = void>
struct IsContainerCompatibleWithQStringView : std::false_type {};
@@ -113,7 +67,6 @@ struct IsContainerCompatibleWithQStringView<T, std::enable_if_t<std::conjunction
// These need to be treated specially due to the empty vs null distinction
std::negation<std::is_same<std::decay_t<T>, QString>>,
- std::negation<std::is_same<std::decay_t<T>, QStringRef>>,
// Don't make an accidental copy constructor
std::negation<std::is_same<std::decay_t<T>, QStringView>>
@@ -146,22 +99,16 @@ private:
using if_compatible_pointer = typename std::enable_if<QtPrivate::IsCompatiblePointer<Pointer>::value, bool>::type;
template <typename T>
- using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value || std::is_same<T, QStringRef>::value, bool>::type;
+ using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value, bool>::type;
template <typename T>
using if_compatible_container = typename std::enable_if<QtPrivate::IsContainerCompatibleWithQStringView<T>::value, bool>::type;
template <typename Char>
- static qsizetype lengthHelperPointer(const Char *str) noexcept
+ static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
{
-#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
- if (__builtin_constant_p(*str)) {
- qsizetype result = 0;
- while (*str++)
- ++result;
- return result;
- }
-#endif
+ if (q20::is_constant_evaluated())
+ return std::char_traits<Char>::length(str);
return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
}
static qsizetype lengthHelperPointer(const QChar *str) noexcept
@@ -169,55 +116,47 @@ private:
return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
}
- template <typename Container>
- static Q_DECL_CONSTEXPR qsizetype lengthHelperContainer(const Container &c) noexcept
- {
- return qsizetype(std::size(c));
- }
-
- template <typename Char, size_t N>
- static Q_DECL_CONSTEXPR qsizetype lengthHelperContainer(const Char (&)[N]) noexcept
- {
- return qsizetype(N - 1);
- }
-
template <typename Char>
static const storage_type *castHelper(const Char *str) noexcept
{ return reinterpret_cast<const storage_type*>(str); }
- static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *str) noexcept
+ static constexpr const storage_type *castHelper(const storage_type *str) noexcept
{ return str; }
public:
- Q_DECL_CONSTEXPR QStringView() noexcept
- : m_size(0), m_data(nullptr) {}
- Q_DECL_CONSTEXPR QStringView(std::nullptr_t) noexcept
+ constexpr QStringView() noexcept {}
+ constexpr QStringView(std::nullptr_t) noexcept
: QStringView() {}
template <typename Char, if_compatible_char<Char> = true>
- Q_DECL_CONSTEXPR QStringView(const Char *str, qsizetype len)
+ constexpr QStringView(const Char *str, qsizetype len)
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+ : m_data(castHelper(str)),
+ m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len))
+#else
: m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)),
- m_data(castHelper(str)) {}
+ m_data(castHelper(str))
+#endif
+ {}
template <typename Char, if_compatible_char<Char> = true>
- Q_DECL_CONSTEXPR QStringView(const Char *f, const Char *l)
+ constexpr QStringView(const Char *f, const Char *l)
: QStringView(f, l - f) {}
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
template <typename Char, size_t N>
- Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) noexcept;
+ constexpr QStringView(const Char (&array)[N]) noexcept;
template <typename Char>
- Q_DECL_CONSTEXPR QStringView(const Char *str) noexcept;
+ constexpr QStringView(const Char *str) noexcept;
#else
template <typename Pointer, if_compatible_pointer<Pointer> = true>
- Q_DECL_CONSTEXPR QStringView(const Pointer &str) noexcept
+ constexpr QStringView(const Pointer &str) noexcept
: QStringView(str, str ? lengthHelperPointer(str) : 0) {}
#endif
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QStringView(const QString &str) noexcept;
- QStringView(const QStringRef &str) noexcept;
#else
template <typename String, if_compatible_qstring_like<String> = true>
QStringView(const String &str) noexcept
@@ -225,214 +164,339 @@ public:
#endif
template <typename Container, if_compatible_container<Container> = true>
- Q_DECL_CONSTEXPR QStringView(const Container &c) noexcept
- : QStringView(std::data(c), lengthHelperContainer(c)) {}
+ constexpr Q_ALWAYS_INLINE QStringView(const Container &c) noexcept
+ : QStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {}
- Q_REQUIRED_RESULT inline QString toString() const; // defined in qstring.h
+ template <typename Char, size_t Size, if_compatible_char<Char> = true>
+ [[nodiscard]] constexpr static QStringView fromArray(const Char (&string)[Size]) noexcept
+ { return QStringView(string, Size); }
+
+ [[nodiscard]] inline QString toString() const; // defined in qstring.h
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
// defined in qcore_foundation.mm
- Q_REQUIRED_RESULT Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
- Q_REQUIRED_RESULT Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
+ [[nodiscard]] Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
+ [[nodiscard]] Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR qsizetype size() const noexcept { return m_size; }
- Q_REQUIRED_RESULT const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); }
- Q_REQUIRED_RESULT const_pointer constData() const noexcept { return data(); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR const storage_type *utf16() const noexcept { return m_data; }
+ [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
+ [[nodiscard]] const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); }
+ [[nodiscard]] const_pointer constData() const noexcept { return data(); }
+ [[nodiscard]] constexpr const storage_type *utf16() const noexcept { return m_data; }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar operator[](qsizetype n) const
- { return Q_ASSERT(n >= 0), Q_ASSERT(n < size()), QChar(m_data[n]); }
+ [[nodiscard]] constexpr QChar operator[](qsizetype n) const
+ { verify(n, 1); return QChar(m_data[n]); }
//
// QString API
//
template <typename...Args>
- Q_REQUIRED_RESULT inline QString arg(Args &&...args) const; // defined in qstring.h
+ [[nodiscard]] inline QString arg(Args &&...args) const; // defined in qstring.h
- Q_REQUIRED_RESULT QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); }
- Q_REQUIRED_RESULT QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); }
- Q_REQUIRED_RESULT QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); }
- Q_REQUIRED_RESULT inline QList<uint> toUcs4() const; // defined in qlist.h
+ [[nodiscard]] QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); }
+ [[nodiscard]] QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); }
+ [[nodiscard]] QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); }
+ [[nodiscard]] inline QList<uint> toUcs4() const; // defined in qlist.h ### Qt 7 char32_t
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar at(qsizetype n) const { return (*this)[n]; }
+ [[nodiscard]] constexpr QChar at(qsizetype n) const noexcept { return (*this)[n]; }
- Q_REQUIRED_RESULT constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const
+ [[nodiscard]] constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const noexcept
{
using namespace QtPrivate;
auto result = QContainerImplHelper::mid(size(), &pos, &n);
return result == QContainerImplHelper::Null ? QStringView() : QStringView(m_data + pos, n);
}
- Q_REQUIRED_RESULT constexpr QStringView left(qsizetype n) const
+ [[nodiscard]] constexpr QStringView left(qsizetype n) const noexcept
{
if (size_t(n) >= size_t(size()))
n = size();
return QStringView(m_data, n);
}
- Q_REQUIRED_RESULT constexpr QStringView right(qsizetype n) const
+ [[nodiscard]] constexpr QStringView right(qsizetype n) const noexcept
{
if (size_t(n) >= size_t(size()))
n = size();
return QStringView(m_data + m_size - n, n);
}
- Q_REQUIRED_RESULT constexpr QStringView first(qsizetype n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data, n); }
- Q_REQUIRED_RESULT constexpr QStringView last(qsizetype n) const
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data + size() - n, n); }
- Q_REQUIRED_RESULT constexpr QStringView from(qsizetype pos) const
- { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QStringView(m_data + pos, size() - pos); }
- Q_REQUIRED_RESULT constexpr QStringView sliced(qsizetype pos, qsizetype n) const
- { Q_ASSERT(pos >= 0); Q_ASSERT(n >= 0); Q_ASSERT(size_t(pos) + size_t(n) <= size_t(size())); return QStringView(m_data + pos, n); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView chopped(qsizetype n) const
- { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, m_size - n); }
+ [[nodiscard]] constexpr QStringView first(qsizetype n) const noexcept
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] constexpr QStringView last(qsizetype n) const noexcept
+ { verify(0, n); return sliced(size() - n, n); }
+ [[nodiscard]] constexpr QStringView sliced(qsizetype pos) const noexcept
+ { verify(pos, 0); return QStringView(m_data + pos, size() - pos); }
+ [[nodiscard]] constexpr QStringView sliced(qsizetype pos, qsizetype n) const noexcept
+ { verify(pos, n); return QStringView(m_data + pos, n); }
+ [[nodiscard]] constexpr QStringView chopped(qsizetype n) const noexcept
+ { verify(0, n); return sliced(0, m_size - n); }
- Q_DECL_RELAXED_CONSTEXPR void truncate(qsizetype n)
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
- Q_DECL_RELAXED_CONSTEXPR void chop(qsizetype n)
- { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
+ constexpr void truncate(qsizetype n) noexcept
+ { verify(0, n); ; m_size = n; }
+ constexpr void chop(qsizetype n) noexcept
+ { verify(0, n); m_size -= n; }
- Q_REQUIRED_RESULT QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
+ [[nodiscard]] QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
template <typename Needle, typename...Flags>
- Q_REQUIRED_RESULT constexpr inline auto tokenize(Needle &&needle, Flags...flags) const
+ [[nodiscard]] constexpr inline auto tokenize(Needle &&needle, Flags...flags) const
noexcept(noexcept(qTokenize(std::declval<const QStringView&>(), std::forward<Needle>(needle), flags...)))
-> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
{ return qTokenize(*this, std::forward<Needle>(needle), flags...); }
- Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, other, cs); }
- Q_REQUIRED_RESULT inline int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int compare(QChar c) const noexcept
- { return empty() || front() == c ? size() - 1 : *utf16() - c.unicode() ; }
- Q_REQUIRED_RESULT int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
+ [[nodiscard]] inline int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] constexpr int compare(QChar c) const noexcept
+ { return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
+ [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] inline int localeAwareCompare(QStringView other) const;
+
+ [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
- Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- Q_REQUIRED_RESULT bool startsWith(QChar c) const noexcept
+ [[nodiscard]] inline bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] bool startsWith(QChar c) const noexcept
{ return !empty() && front() == c; }
- Q_REQUIRED_RESULT bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
+ [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
- Q_REQUIRED_RESULT inline bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- Q_REQUIRED_RESULT bool endsWith(QChar c) const noexcept
+ [[nodiscard]] inline bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] bool endsWith(QChar c) const noexcept
{ return !empty() && back() == c; }
- Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
+ [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, c.unicode(), cs); }
+ [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::findString(*this, from, s, cs); }
- Q_REQUIRED_RESULT inline qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] inline qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- Q_REQUIRED_RESULT bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); }
- Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return indexOf(s, 0, cs) != qsizetype(-1); }
- Q_REQUIRED_RESULT inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- Q_REQUIRED_RESULT qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::count(*this, c, cs); }
- Q_REQUIRED_RESULT qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::count(*this, s, cs); }
-
- Q_REQUIRED_RESULT qsizetype lastIndexOf(QChar c, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
- { return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT qsizetype lastIndexOf(QStringView s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ [[nodiscard]] inline qsizetype count(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+ [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(c, -1, cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, c.unicode(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return lastIndexOf(s, size(), cs); }
+ [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
- Q_REQUIRED_RESULT inline qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] inline qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- Q_REQUIRED_RESULT bool isRightToLeft() const noexcept
+#if QT_CONFIG(regularexpression)
+ [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const
+ {
+ return QtPrivate::indexOf(*this, re, from, rmatch);
+ }
+#ifdef Q_QDOC
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
+#else
+ // prevent an ambiguity when called like this: lastIndexOf(re, 0)
+ template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
+ {
+ return QtPrivate::lastIndexOf(*this, re, size(), rmatch);
+ }
+#endif
+ [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch = nullptr) const
+ {
+ return QtPrivate::lastIndexOf(*this, re, from, rmatch);
+ }
+ [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
+ {
+ return QtPrivate::contains(*this, re, rmatch);
+ }
+ [[nodiscard]] qsizetype count(const QRegularExpression &re) const
+ {
+ return QtPrivate::count(*this, re);
+ }
+#endif
+
+ [[nodiscard]] bool isRightToLeft() const noexcept
{ return QtPrivate::isRightToLeft(*this); }
- Q_REQUIRED_RESULT bool isValidUtf16() const noexcept
+ [[nodiscard]] bool isValidUtf16() const noexcept
{ return QtPrivate::isValidUtf16(*this); }
- Q_REQUIRED_RESULT inline short toShort(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline ushort toUShort(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline int toInt(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline uint toUInt(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline long toLong(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline ulong toULong(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
- Q_REQUIRED_RESULT Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const;
- Q_REQUIRED_RESULT Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const;
+ [[nodiscard]] bool isUpper() const noexcept
+ { return QtPrivate::isUpper(*this); }
+ [[nodiscard]] bool isLower() const noexcept
+ { return QtPrivate::isLower(*this); }
- Q_REQUIRED_RESULT inline int toWCharArray(wchar_t *array) const; // defined in qstring.h
+ [[nodiscard]] inline short toShort(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline ushort toUShort(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline int toInt(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline uint toUInt(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline long toLong(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline ulong toULong(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline qlonglong toLongLong(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] inline qulonglong toULongLong(bool *ok = nullptr, int base = 10) const;
+ [[nodiscard]] Q_CORE_EXPORT float toFloat(bool *ok = nullptr) const;
+ [[nodiscard]] Q_CORE_EXPORT double toDouble(bool *ok = nullptr) const;
+ [[nodiscard]] inline qsizetype toWCharArray(wchar_t *array) const; // defined in qstring.h
- Q_REQUIRED_RESULT Q_CORE_EXPORT
+
+ [[nodiscard]] Q_CORE_EXPORT
QList<QStringView> split(QStringView sep,
Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- Q_REQUIRED_RESULT Q_CORE_EXPORT
+ [[nodiscard]] Q_CORE_EXPORT
QList<QStringView> split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#if QT_CONFIG(regularexpression)
- Q_REQUIRED_RESULT Q_CORE_EXPORT
+ [[nodiscard]] Q_CORE_EXPORT
QList<QStringView> split(const QRegularExpression &sep,
Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
#endif
+ // QStringView <> QStringView
+ friend bool comparesEqual(const QStringView &lhs, const QStringView &rhs) noexcept
+ { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QStringView &lhs, const QStringView &rhs) noexcept
+ {
+ const int res = QtPrivate::compareStrings(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QStringView)
+
+ // QStringView <> QChar
+ friend bool comparesEqual(const QStringView &lhs, QChar rhs) noexcept
+ { return lhs.size() == 1 && lhs[0] == rhs; }
+ friend Qt::strong_ordering compareThreeWay(const QStringView &lhs, QChar rhs) noexcept
+ { return compareThreeWay(lhs, QStringView(&rhs, 1)); }
+ Q_DECLARE_STRONGLY_ORDERED(QStringView, QChar)
+
//
// STL compatibility API:
//
- Q_REQUIRED_RESULT const_iterator begin() const noexcept { return data(); }
- Q_REQUIRED_RESULT const_iterator end() const noexcept { return data() + size(); }
- Q_REQUIRED_RESULT const_iterator cbegin() const noexcept { return begin(); }
- Q_REQUIRED_RESULT const_iterator cend() const noexcept { return end(); }
- Q_REQUIRED_RESULT const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
- Q_REQUIRED_RESULT const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
- Q_REQUIRED_RESULT const_reverse_iterator crbegin() const noexcept { return rbegin(); }
- Q_REQUIRED_RESULT const_reverse_iterator crend() const noexcept { return rend(); }
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool empty() const noexcept { return size() == 0; }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
+ [[nodiscard]] const_iterator begin() const noexcept { return data(); }
+ [[nodiscard]] const_iterator end() const noexcept { return data() + size(); }
+ [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
+
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+ [[nodiscard]] constexpr QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
+ [[nodiscard]] constexpr QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
+
+ [[nodiscard]] Q_IMPLICIT operator std::u16string_view() const noexcept
+ { return std::u16string_view(m_data, size_t(m_size)); }
//
// Qt compatibility API:
//
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isNull() const noexcept { return !m_data; }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isEmpty() const noexcept { return empty(); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int length() const /* not nothrow! */
- { return Q_ASSERT(int(size()) == size()), int(size()); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar first() const { return front(); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar last() const { return back(); }
+ [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); }
+ [[nodiscard]] const_iterator constEnd() const noexcept { return end(); }
+ [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
+ [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
+ [[nodiscard]] constexpr qsizetype length() const noexcept
+ { return size(); }
+ [[nodiscard]] constexpr QChar first() const { return front(); }
+ [[nodiscard]] constexpr QChar last() const { return back(); }
private:
- qsizetype m_size;
- const storage_type *m_data;
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+ const storage_type *m_data = nullptr;
+ qsizetype m_size = 0;
+#else
+ qsizetype m_size = 0;
+ const storage_type *m_data = nullptr;
+#endif
+
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+
+ constexpr int compare_single_char_helper(int diff) const noexcept
+ { return diff ? diff : size() > 1 ? 1 : 0; }
+
+ Q_CORE_EXPORT static bool equal_helper(QStringView sv, const char *data, qsizetype len);
+ Q_CORE_EXPORT static int compare_helper(QStringView sv, const char *data, qsizetype len);
+
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ friend bool comparesEqual(const QStringView &lhs, const QByteArrayView &rhs) noexcept
+ { return equal_helper(lhs, rhs.data(), rhs.size()); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QStringView &lhs, const QByteArrayView &rhs) noexcept
+ {
+ const int res = compare_helper(lhs, rhs.data(), rhs.size());
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArrayView, QT_ASCII_CAST_WARN)
+ Q_DECLARE_STRONGLY_ORDERED(QStringView, QByteArray, QT_ASCII_CAST_WARN)
+ Q_DECLARE_STRONGLY_ORDERED(QStringView, const char *, QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
};
Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE);
template <typename QStringLike, typename std::enable_if<
- std::is_same<QStringLike, QString>::value || std::is_same<QStringLike, QStringRef>::value,
+ std::is_same<QStringLike, QString>::value,
bool>::type = true>
inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
-{ return QStringView(s.data(), s.size()); }
+{ return QStringView(s.begin(), s.size()); }
// QChar inline functions:
-Q_REQUIRED_RESULT constexpr auto QChar::fromUcs4(char32_t c) noexcept
+[[nodiscard]] constexpr auto QChar::fromUcs4(char32_t c) noexcept
{
struct R {
char16_t chars[2];
- Q_REQUIRED_RESULT constexpr operator QStringView() const noexcept { return {begin(), end()}; }
- Q_REQUIRED_RESULT constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
- Q_REQUIRED_RESULT constexpr const char16_t *begin() const noexcept { return chars; }
- Q_REQUIRED_RESULT constexpr const char16_t *end() const noexcept { return begin() + size(); }
+ [[nodiscard]] constexpr operator QStringView() const noexcept { return {begin(), end()}; }
+ [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
+ [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; }
+ [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); }
};
return requiresSurrogates(c) ? R{{QChar::highSurrogate(c),
QChar::lowSurrogate(c)}} :
R{{char16_t(c), u'\0'}} ;
}
+qsizetype QtPrivate::findString(QStringView str, qsizetype from, QChar ch, Qt::CaseSensitivity cs) noexcept
+{
+ if (from < -str.size()) // from < 0 && abs(from) > str.size(), avoiding overflow
+ return -1;
+ if (from < 0)
+ from = qMax(from + str.size(), qsizetype(0));
+ if (from < str.size()) {
+ const char16_t *s = str.utf16();
+ char16_t c = ch.unicode();
+ const char16_t *n = s + from;
+ const char16_t *e = s + str.size();
+ if (cs == Qt::CaseSensitive)
+ n = qustrchr(QStringView(n, e), c);
+ else
+ n = qustrcasechr(QStringView(n, e), c);
+ if (n != e)
+ return n - s;
+ }
+ return -1;
+}
+
QT_END_NAMESPACE
#endif /* QSTRINGVIEW_H */
diff --git a/src/corelib/text/qt_attribution.json b/src/corelib/text/qt_attribution.json
index c555209f19..6235ec5c16 100644
--- a/src/corelib/text/qt_attribution.json
+++ b/src/corelib/text/qt_attribution.json
@@ -4,37 +4,41 @@
"Name": "Unicode Character Database (UCD)",
"QDocModule": "qtcore",
"QtUsage": "Qt Core uses data obtained from UCD files for working with characters and strings.",
- "Files": "For update, see qtbase/util/unicode/README",
- "Files": "qunicodetables_p.h qunicodetables.cpp",
+ "Comment": { "Files": "For update, see qtbase/util/unicode/README" },
+ "Files": [ "qunicodetables_p.h", "qunicodetables.cpp" ],
"Description": "The Unicode Character Database (UCD) is a set of files that
define the Unicode character properties and internal mappings.",
"Homepage": "https://www.unicode.org/ucd/",
- "Version": "Don't use the Unicode standard version;
- UCD has its own 'Revision' numbers, see the 'UAX #44, UCD' page",
- "Version": "26",
+ "Comment": {
+ "Version": [ "Don't use the Unicode standard version;",
+ "UCD has its own 'Revision' numbers",
+ "see the 'UAX #44, UCD' page (https://www.unicode.org/reports/tr44/)" ],
+ "License": [ "Will change to Unicode-3.0 on next update",
+ "util/unicode/main.cpp is updated to do that already",
+ "Please update the following and delete this note when that happens" ] },
+ "Version": "30",
"License": "Unicode License Agreement - Data Files and Software (2016)",
"LicenseId": "Unicode-DFS-2016",
- "LicenseFile": "UNICODE_LICENSE.txt",
- "Copyright": "Copyright (C) 1991-2018 Unicode, Inc."
+ "Copyright": "Copyright (C) 1991-2022 Unicode, Inc."
},
{
"Id": "unicode-cldr",
"Name": "Unicode Common Locale Data Repository (CLDR)",
"QDocModule": "qtcore",
"QtUsage": "Used in Qt Core (QTimeZone, QLocale).",
- "Files": "For update, see qtbase/util/locale_database/cldr2qlocalexml.py",
- "Files": "qlocale_data_p.h qtimezoneprivate_data_p.h",
+ "Comment": { "Files": "For update, see qtbase/util/locale_database/cldr2qlocalexml.py" },
+ "Files": [ "qlocale_data_p.h",
+ "../time/qtimezoneprivate_data_p.h", "../time/qhijricalendar_data_p.h",
+ "../time/qjalalicalendar_data_p.h", "../time/qromancalendar_data_p.h" ],
"Description": "The Unicode CLDR provides key building blocks for software to support the
world's languages, with the largest and most extensive standard repository of locale data
available.",
- "Homepage": "http://cldr.unicode.org/",
- "Version": "v36",
- "License": "// as specified in https://spdx.org/licenses/Unicode-DFS-2016.html",
- "License": "Unicode License Agreement - Data Files and Software (2016)",
- "LicenseId": "Unicode-DFS-2016",
- "LicenseFile": "UNICODE_LICENSE.txt",
- "Copyright": "Copyright (C) 1991-2019 Unicode, Inc."
+ "Homepage": "https://cldr.unicode.org/",
+ "Version": "v44.1",
+ "License": "Unicode License v3",
+ "LicenseId": "Unicode-3.0",
+ "Copyright": "Copyright (C) 2004-2023 Unicode, Inc."
}
]
diff --git a/src/corelib/text/qtextboundaryfinder.cpp b/src/corelib/text/qtextboundaryfinder.cpp
index fdbb7f0176..21d4c5153e 100644
--- a/src/corelib/text/qtextboundaryfinder.cpp
+++ b/src/corelib/text/qtextboundaryfinder.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qtextboundaryfinder.h>
#include <QtCore/qvarlengtharray.h>
@@ -43,18 +7,10 @@
QT_BEGIN_NAMESPACE
-class QTextBoundaryFinderPrivate
+static void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
{
-public:
- QCharAttributes attributes[1];
-};
-
-static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int length, QCharAttributes *attributes)
-{
- const ushort *string = reinterpret_cast<const ushort *>(chars);
-
QUnicodeTools::ScriptItemArray scriptItems;
- QUnicodeTools::initScripts(string, length, &scriptItems);
+ QUnicodeTools::initScripts(str, &scriptItems);
QUnicodeTools::CharAttributeOptions options;
switch (type) {
@@ -64,7 +20,7 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
case QTextBoundaryFinder::Line: options |= QUnicodeTools::LineBreaks; break;
default: break;
}
- QUnicodeTools::initCharAttributes(string, length, scriptItems.data(), scriptItems.count(), attributes, options);
+ QUnicodeTools::initCharAttributes(str, scriptItems.data(), scriptItems.size(), attributes, options);
}
/*!
@@ -81,8 +37,8 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
QTextBoundaryFinder allows to find Unicode text boundaries in a
string, accordingly to the Unicode text boundary specification (see
- \l{http://www.unicode.org/reports/tr14/}{Unicode Standard Annex #14} and
- \l{http://www.unicode.org/reports/tr29/}{Unicode Standard Annex #29}).
+ \l{https://www.unicode.org/reports/tr14/}{Unicode Standard Annex #14} and
+ \l{https://www.unicode.org/reports/tr29/}{Unicode Standard Annex #29}).
QTextBoundaryFinder can operate on a QString in four possible
modes depending on the value of \a BoundaryType.
@@ -93,17 +49,17 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
for example form one grapheme cluster as the user thinks of them
as one character, yet it is in this case represented by two
unicode code points
- (see \l{http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries}).
+ (see \l{https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries}).
Word boundaries are there to locate the start and end of what a
language considers to be a word
- (see \l{http://www.unicode.org/reports/tr29/#Word_Boundaries}).
+ (see \l{https://www.unicode.org/reports/tr29/#Word_Boundaries}).
Line break boundaries give possible places where a line break
might happen and sentence boundaries will show the beginning and
end of whole sentences
- (see \l{http://www.unicode.org/reports/tr29/#Sentence_Boundaries} and
- \l{http://www.unicode.org/reports/tr14/}).
+ (see \l{https://www.unicode.org/reports/tr29/#Sentence_Boundaries} and
+ \l{https://www.unicode.org/reports/tr14/}).
The first position in a string is always a valid boundary and
refers to the position before the first character. The last
@@ -131,11 +87,11 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
Such a break opportunity might also be an item boundary
(either StartOfItem, EndOfItem, or combination of both),
a mandatory line break, or a soft hyphen.
- \value StartOfItem Since 5.0. The boundary finder is at the start of
+ \value [since 5.0] StartOfItem The boundary finder is at the start of
a grapheme, a word, a sentence, or a line.
- \value EndOfItem Since 5.0. The boundary finder is at the end of
+ \value [since 5.0] EndOfItem The boundary finder is at the end of
a grapheme, a word, a sentence, or a line.
- \value MandatoryBreak Since 5.0. The boundary finder is at the end of line
+ \value [since 5.0] MandatoryBreak The boundary finder is at the end of line
(can occur for a Line boundary type only).
\value SoftHyphen The boundary finder is at the soft hyphen
(can occur for a Line boundary type only).
@@ -145,11 +101,7 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
Constructs an invalid QTextBoundaryFinder object.
*/
QTextBoundaryFinder::QTextBoundaryFinder()
- : t(Grapheme)
- , chars(nullptr)
- , length(0)
- , freePrivate(true)
- , d(nullptr)
+ : freeBuffer(true)
{
}
@@ -159,17 +111,15 @@ QTextBoundaryFinder::QTextBoundaryFinder()
QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other)
: t(other.t)
, s(other.s)
- , chars(other.chars)
- , length(other.length)
+ , sv(other.sv)
, pos(other.pos)
- , freePrivate(true)
- , d(nullptr)
+ , freeBuffer(true)
{
- if (other.d) {
- Q_ASSERT(length > 0);
- d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes));
- Q_CHECK_PTR(d);
- memcpy(d, other.d, (length + 1) * sizeof(QCharAttributes));
+ if (other.attributes) {
+ Q_ASSERT(sv.size() > 0);
+ attributes = (QCharAttributes *) malloc((sv.size() + 1) * sizeof(QCharAttributes));
+ Q_CHECK_PTR(attributes);
+ memcpy(attributes, other.attributes, (sv.size() + 1) * sizeof(QCharAttributes));
}
}
@@ -181,27 +131,26 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
if (&other == this)
return *this;
- if (other.d) {
- Q_ASSERT(other.length > 0);
- uint newCapacity = (other.length + 1) * sizeof(QCharAttributes);
- QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *) realloc(freePrivate ? d : nullptr, newCapacity);
+ if (other.attributes) {
+ Q_ASSERT(other.sv.size() > 0);
+ size_t newCapacity = (size_t(other.sv.size()) + 1) * sizeof(QCharAttributes);
+ QCharAttributes *newD = (QCharAttributes *) realloc(freeBuffer ? attributes : nullptr, newCapacity);
Q_CHECK_PTR(newD);
- freePrivate = true;
- d = newD;
+ freeBuffer = true;
+ attributes = newD;
}
t = other.t;
s = other.s;
- chars = other.chars;
- length = other.length;
+ sv = other.sv;
pos = other.pos;
- if (other.d) {
- memcpy(d, other.d, (length + 1) * sizeof(QCharAttributes));
+ if (other.attributes) {
+ memcpy(attributes, other.attributes, (sv.size() + 1) * sizeof(QCharAttributes));
} else {
- if (freePrivate)
- free(d);
- d = nullptr;
+ if (freeBuffer)
+ free(attributes);
+ attributes = nullptr;
}
return *this;
@@ -213,8 +162,8 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
QTextBoundaryFinder::~QTextBoundaryFinder()
{
Q_UNUSED(unused);
- if (freePrivate)
- free(d);
+ if (freeBuffer)
+ free(attributes);
}
/*!
@@ -223,52 +172,51 @@ QTextBoundaryFinder::~QTextBoundaryFinder()
QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &string)
: t(type)
, s(string)
- , chars(string.unicode())
- , length(string.length())
- , pos(0)
- , freePrivate(true)
- , d(nullptr)
+ , sv(s)
+ , freeBuffer(true)
{
- if (length > 0) {
- d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes));
- Q_CHECK_PTR(d);
- init(t, chars, length, d->attributes);
+ if (sv.size() > 0) {
+ attributes = (QCharAttributes *) malloc((sv.size() + 1) * sizeof(QCharAttributes));
+ Q_CHECK_PTR(attributes);
+ init(t, sv, attributes);
}
}
/*!
- Creates a QTextBoundaryFinder object of \a type operating on \a chars
- with \a length.
+ \fn QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars, qsizetype length, unsigned char *buffer, qsizetype bufferSize)
+ \overload
+
+ The same as QTextBoundaryFinder(type, QStringView(chars, length), buffer, bufferSize).
+*/
+
+/*!
+ Creates a QTextBoundaryFinder object of \a type operating on \a string.
+ \since 6.0
\a buffer is an optional working buffer of size \a bufferSize you can pass to
the QTextBoundaryFinder. If the buffer is large enough to hold the working
data required (bufferSize >= length + 1), it will use this
instead of allocating its own buffer.
- \warning QTextBoundaryFinder does not create a copy of \a chars. It is the
+ \warning QTextBoundaryFinder does not create a copy of \a string. It is the
application programmer's responsibility to ensure the array is allocated for
as long as the QTextBoundaryFinder object stays alive. The same applies to
\a buffer.
*/
-QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer, int bufferSize)
+QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, QStringView string, unsigned char *buffer, qsizetype bufferSize)
: t(type)
- , chars(chars)
- , length(length)
- , pos(0)
- , freePrivate(true)
- , d(nullptr)
+ , sv(string)
+ , freeBuffer(true)
{
- if (!chars) {
- length = 0;
- } else if (length > 0) {
- if (buffer && (uint)bufferSize >= (length + 1) * sizeof(QCharAttributes)) {
- d = (QTextBoundaryFinderPrivate *)buffer;
- freePrivate = false;
+ if (!sv.isEmpty()) {
+ if (buffer && bufferSize / int(sizeof(QCharAttributes)) >= sv.size() + 1) {
+ attributes = reinterpret_cast<QCharAttributes *>(buffer);
+ freeBuffer = false;
} else {
- d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes));
- Q_CHECK_PTR(d);
+ attributes = (QCharAttributes *) malloc((sv.size() + 1) * sizeof(QCharAttributes));
+ Q_CHECK_PTR(attributes);
}
- init(t, chars, length, d->attributes);
+ init(t, sv, attributes);
}
}
@@ -289,7 +237,7 @@ void QTextBoundaryFinder::toStart()
*/
void QTextBoundaryFinder::toEnd()
{
- pos = length;
+ pos = sv.size();
}
/*!
@@ -300,7 +248,7 @@ void QTextBoundaryFinder::toEnd()
\sa setPosition()
*/
-int QTextBoundaryFinder::position() const
+qsizetype QTextBoundaryFinder::position() const
{
return pos;
}
@@ -314,9 +262,9 @@ int QTextBoundaryFinder::position() const
\sa position()
*/
-void QTextBoundaryFinder::setPosition(int position)
+void QTextBoundaryFinder::setPosition(qsizetype position)
{
- pos = qBound(0, position, length);
+ pos = qBound(0, position, sv.size());
}
/*! \fn QTextBoundaryFinder::BoundaryType QTextBoundaryFinder::type() const
@@ -335,9 +283,9 @@ void QTextBoundaryFinder::setPosition(int position)
*/
QString QTextBoundaryFinder::string() const
{
- if (chars == s.unicode() && length == s.length())
+ if (sv.data() == s.unicode() && sv.size() == s.size())
return s;
- return QString(chars, length);
+ return sv.toString();
}
@@ -346,9 +294,9 @@ QString QTextBoundaryFinder::string() const
Returns -1 if there is no next boundary.
*/
-int QTextBoundaryFinder::toNextBoundary()
+qsizetype QTextBoundaryFinder::toNextBoundary()
{
- if (!d || pos < 0 || pos >= length) {
+ if (!attributes || pos < 0 || pos >= sv.size()) {
pos = -1;
return pos;
}
@@ -356,19 +304,19 @@ int QTextBoundaryFinder::toNextBoundary()
++pos;
switch(t) {
case Grapheme:
- while (pos < length && !d->attributes[pos].graphemeBoundary)
+ while (pos < sv.size() && !attributes[pos].graphemeBoundary)
++pos;
break;
case Word:
- while (pos < length && !d->attributes[pos].wordBreak)
+ while (pos < sv.size() && !attributes[pos].wordBreak)
++pos;
break;
case Sentence:
- while (pos < length && !d->attributes[pos].sentenceBoundary)
+ while (pos < sv.size() && !attributes[pos].sentenceBoundary)
++pos;
break;
case Line:
- while (pos < length && !d->attributes[pos].lineBreak)
+ while (pos < sv.size() && !attributes[pos].lineBreak)
++pos;
break;
}
@@ -381,9 +329,9 @@ int QTextBoundaryFinder::toNextBoundary()
Returns -1 if there is no previous boundary.
*/
-int QTextBoundaryFinder::toPreviousBoundary()
+qsizetype QTextBoundaryFinder::toPreviousBoundary()
{
- if (!d || pos <= 0 || pos > length) {
+ if (!attributes || pos <= 0 || pos > sv.size()) {
pos = -1;
return pos;
}
@@ -391,19 +339,19 @@ int QTextBoundaryFinder::toPreviousBoundary()
--pos;
switch(t) {
case Grapheme:
- while (pos > 0 && !d->attributes[pos].graphemeBoundary)
+ while (pos > 0 && !attributes[pos].graphemeBoundary)
--pos;
break;
case Word:
- while (pos > 0 && !d->attributes[pos].wordBreak)
+ while (pos > 0 && !attributes[pos].wordBreak)
--pos;
break;
case Sentence:
- while (pos > 0 && !d->attributes[pos].sentenceBoundary)
+ while (pos > 0 && !attributes[pos].sentenceBoundary)
--pos;
break;
case Line:
- while (pos > 0 && !d->attributes[pos].lineBreak)
+ while (pos > 0 && !attributes[pos].lineBreak)
--pos;
break;
}
@@ -416,19 +364,19 @@ int QTextBoundaryFinder::toPreviousBoundary()
*/
bool QTextBoundaryFinder::isAtBoundary() const
{
- if (!d || pos < 0 || pos > length)
+ if (!attributes || pos < 0 || pos > sv.size())
return false;
switch(t) {
case Grapheme:
- return d->attributes[pos].graphemeBoundary;
+ return attributes[pos].graphemeBoundary;
case Word:
- return d->attributes[pos].wordBreak;
+ return attributes[pos].wordBreak;
case Sentence:
- return d->attributes[pos].sentenceBoundary;
+ return attributes[pos].sentenceBoundary;
case Line:
// ### TR#14 LB2 prohibits break at sot
- return d->attributes[pos].lineBreak || pos == 0;
+ return attributes[pos].lineBreak || pos == 0;
}
return false;
}
@@ -439,17 +387,17 @@ bool QTextBoundaryFinder::isAtBoundary() const
QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() const
{
BoundaryReasons reasons = NotAtBoundary;
- if (!d || pos < 0 || pos > length)
+ if (!attributes || pos < 0 || pos > sv.size())
return reasons;
- const QCharAttributes attr = d->attributes[pos];
+ const QCharAttributes attr = attributes[pos];
switch (t) {
case Grapheme:
if (attr.graphemeBoundary) {
reasons |= BreakOpportunity | StartOfItem | EndOfItem;
if (pos == 0)
reasons &= (~EndOfItem);
- else if (pos == length)
+ else if (pos == sv.size())
reasons &= (~StartOfItem);
}
break;
@@ -467,7 +415,7 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons
reasons |= BreakOpportunity | StartOfItem | EndOfItem;
if (pos == 0)
reasons &= (~EndOfItem);
- else if (pos == length)
+ else if (pos == sv.size())
reasons &= (~StartOfItem);
}
break;
@@ -479,9 +427,9 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons
reasons |= MandatoryBreak | StartOfItem | EndOfItem;
if (pos == 0)
reasons &= (~EndOfItem);
- else if (pos == length)
+ else if (pos == sv.size())
reasons &= (~StartOfItem);
- } else if (pos > 0 && chars[pos - 1].unicode() == QChar::SoftHyphen) {
+ } else if (pos > 0 && sv[pos - 1].unicode() == QChar::SoftHyphen) {
reasons |= SoftHyphen;
}
}
diff --git a/src/corelib/text/qtextboundaryfinder.h b/src/corelib/text/qtextboundaryfinder.h
index b1e5008f54..04e64fd69b 100644
--- a/src/corelib/text/qtextboundaryfinder.h
+++ b/src/corelib/text/qtextboundaryfinder.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTBOUNDARYFINDER_H
#define QTEXTBOUNDARYFINDER_H
@@ -46,7 +10,7 @@
QT_BEGIN_NAMESPACE
-class QTextBoundaryFinderPrivate;
+struct QCharAttributes;
class Q_CORE_EXPORT QTextBoundaryFinder
{
@@ -74,33 +38,35 @@ public:
Q_DECLARE_FLAGS( BoundaryReasons, BoundaryReason )
QTextBoundaryFinder(BoundaryType type, const QString &string);
- QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer = nullptr, int bufferSize = 0);
+ QTextBoundaryFinder(BoundaryType type, const QChar *chars, qsizetype length, unsigned char *buffer = nullptr, qsizetype bufferSize = 0)
+ : QTextBoundaryFinder(type, QStringView(chars, length), buffer, bufferSize)
+ {}
+ QTextBoundaryFinder(BoundaryType type, QStringView str, unsigned char *buffer = nullptr, qsizetype bufferSize = 0);
- inline bool isValid() const { return d; }
+ inline bool isValid() const { return attributes; }
inline BoundaryType type() const { return t; }
QString string() const;
void toStart();
void toEnd();
- int position() const;
- void setPosition(int position);
+ qsizetype position() const;
+ void setPosition(qsizetype position);
- int toNextBoundary();
- int toPreviousBoundary();
+ qsizetype toNextBoundary();
+ qsizetype toPreviousBoundary();
bool isAtBoundary() const;
BoundaryReasons boundaryReasons() const;
private:
- BoundaryType t;
+ BoundaryType t = Grapheme;
QString s;
- const QChar *chars;
- int length;
- int pos;
- uint freePrivate : 1;
+ QStringView sv;
+ qsizetype pos = 0;
+ uint freeBuffer : 1;
uint unused : 31;
- QTextBoundaryFinderPrivate *d;
+ QCharAttributes *attributes = nullptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextBoundaryFinder::BoundaryReasons)
diff --git a/src/corelib/text/qtliterals.qdoc b/src/corelib/text/qtliterals.qdoc
new file mode 100644
index 0000000000..d108aeb615
--- /dev/null
+++ b/src/corelib/text/qtliterals.qdoc
@@ -0,0 +1,44 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \namespace QtLiterals
+ \inmodule QtCore
+
+ \brief The QtLiterals namespace declares literal operators for Qt types.
+*/
+
+/*!
+ \namespace Qt::Literals
+ \inmodule QtCore
+ \inheaderfile QString
+
+ \brief The Literals inline namespace declares literal operators for Qt types.
+*/
+
+/*!
+ \namespace Qt::Literals::StringLiterals
+ \inmodule QtCore
+ \inheaderfile QString
+
+ \brief The StringLiterals namespace declares string literal operators
+ for Qt types.
+
+ The inline Qt::Literals::StringLiterals namespace declares string literal
+ operators for Qt types. Because both \c Literals and \c StringLiterals
+ namespaces are declared as inline, the symbols from this namespace can be
+ accessed by adding one of the following to your code:
+
+ \code
+ // Makes visible only the literal operators declared in StringLiterals
+ using namespace Qt::Literals::StringLiterals;
+
+ // Makes visible literal operators declared in all inline namespaces
+ // inside Literals
+ using namespace Qt::Literals;
+
+ // Makes visible all symbols (including all literal operators) declared
+ // in the Qt namespace
+ using namespace Qt;
+ \endcode
+*/
diff --git a/src/corelib/text/qunicodetables.cpp b/src/corelib/text/qunicodetables.cpp
index 865f93ba52..dc93b99668 100644
--- a/src/corelib/text/qunicodetables.cpp
+++ b/src/corelib/text/qunicodetables.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/* This file is autogenerated from the Unicode 13.0 database. Do not edit */
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-DFS-2016
+
+/* This file is autogenerated from the Unicode 15.1 database. Do not edit */
#include "qunicodetables_p.h"
@@ -45,7 +9,7 @@ QT_BEGIN_NAMESPACE
namespace QUnicodeTables {
-static const unsigned short uc_property_trie[] = {
+static constexpr unsigned short uc_property_trie[] = {
// [0x0..0x11000)
6256, 6288, 6320, 6352, 6384, 6416, 6448, 6480,
@@ -87,784 +51,784 @@ static const unsigned short uc_property_trie[] = {
14032, 14064, 14096, 14128, 14160, 14192, 14224, 14256,
14288, 14320, 14352, 14384, 14416, 14448, 14480, 14512,
14544, 14576, 14608, 14640, 14672, 14704, 14736, 14768,
- 14544, 14544, 14544, 14544, 14800, 14832, 14864, 14896,
- 14928, 14960, 14544, 14992, 15024, 15056, 15088, 15120,
- 15152, 15184, 15216, 15248, 15280, 15312, 15344, 15376,
- 15408, 15408, 15408, 15408, 15408, 15408, 15408, 15408,
- 15440, 15440, 15440, 15440, 15472, 15504, 15536, 15568,
- 15600, 15632, 15440, 15664, 15696, 15728, 15760, 15792,
- 15824, 15856, 15888, 15920, 15952, 15984, 16016, 16048,
- 16080, 16112, 16144, 16176, 16208, 16208, 16208, 16240,
- 16272, 16304, 16336, 16368, 16400, 16432, 16432, 16464,
- 16496, 16528, 16560, 9936, 16592, 16624, 16624, 16656,
- 16688, 16688, 16688, 16688, 16688, 16688, 16720, 16752,
-
- 16784, 16816, 16848, 16880, 16912, 16944, 16976, 17008,
- 17040, 17072, 17104, 17104, 17136, 17168, 17200, 17232,
- 17264, 17296, 17328, 17360, 17296, 17392, 17424, 17456,
- 17488, 17488, 17520, 17552, 17584, 17584, 17616, 17648,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
-
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17680, 17680, 17680,
- 17680, 17680, 17680, 17680, 17680, 17712, 17744, 17744,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
-
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
-
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
-
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
-
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
-
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17776, 17776, 17776,
- 17776, 17776, 17776, 17776, 17776, 17808, 17840, 17872,
-
- 17904, 17936, 17936, 17936, 17936, 17936, 17936, 17936,
- 17936, 17936, 17936, 17936, 17936, 17936, 17936, 17936,
- 17936, 17936, 17936, 17936, 17936, 17936, 17936, 17936,
- 17936, 17936, 17936, 17936, 17936, 17936, 17936, 17936,
- 17936, 17936, 17936, 17936, 17968, 18000, 18032, 18064,
- 18096, 18096, 18096, 18096, 18096, 18096, 18096, 18096,
- 18128, 18160, 18192, 18224, 18256, 18288, 18288, 18320,
- 18352, 18384, 18416, 18448, 18480, 18512, 18544, 18576,
- 18608, 18640, 18672, 18704, 18736, 18768, 18800, 18832,
- 18864, 18896, 18928, 18960, 18992, 19024, 19056, 19088,
- 19120, 19152, 19184, 19216, 19248, 19280, 19312, 19344,
- 19376, 19408, 19440, 19472, 19504, 19536, 19568, 19600,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
- 19664, 19696, 19728, 19760, 19792, 19824, 19632, 19664,
- 19696, 19728, 19760, 19792, 19824, 19632, 19664, 19696,
- 19728, 19760, 19792, 19824, 19632, 19664, 19696, 19728,
-
- 19760, 19792, 19824, 19632, 19664, 19696, 19728, 19760,
- 19792, 19824, 19632, 19664, 19696, 19728, 19760, 19792,
- 19824, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
- 19664, 19696, 19728, 19760, 19792, 19824, 19632, 19664,
- 19696, 19728, 19760, 19792, 19824, 19632, 19664, 19696,
- 19728, 19760, 19792, 19824, 19632, 19664, 19696, 19728,
- 19760, 19792, 19824, 19632, 19664, 19696, 19728, 19760,
- 19792, 19824, 19632, 19664, 19696, 19728, 19760, 19792,
- 19824, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
- 19664, 19696, 19728, 19760, 19792, 19824, 19632, 19664,
- 19696, 19728, 19760, 19792, 19824, 19632, 19664, 19696,
- 19728, 19760, 19792, 19824, 19632, 19664, 19696, 19728,
- 19760, 19792, 19824, 19632, 19664, 19696, 19728, 19760,
- 19792, 19824, 19632, 19664, 19696, 19728, 19760, 19792,
-
- 19824, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
- 19664, 19696, 19728, 19760, 19792, 19824, 19632, 19664,
- 19696, 19728, 19760, 19792, 19824, 19632, 19664, 19696,
- 19728, 19760, 19792, 19824, 19632, 19664, 19696, 19728,
- 19760, 19792, 19824, 19632, 19664, 19696, 19728, 19760,
- 19792, 19824, 19632, 19664, 19696, 19728, 19760, 19792,
- 19824, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
- 19664, 19696, 19728, 19760, 19792, 19824, 19632, 19664,
- 19696, 19728, 19760, 19792, 19824, 19632, 19664, 19696,
- 19728, 19760, 19792, 19824, 19632, 19664, 19696, 19728,
- 19760, 19792, 19824, 19632, 19664, 19696, 19728, 19760,
- 19792, 19824, 19632, 19664, 19696, 19728, 19760, 19792,
- 19824, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
-
- 19664, 19696, 19728, 19760, 19792, 19824, 19632, 19664,
- 19696, 19728, 19760, 19792, 19824, 19632, 19664, 19696,
- 19728, 19760, 19792, 19824, 19632, 19664, 19696, 19728,
- 19760, 19792, 19824, 19632, 19664, 19696, 19728, 19760,
- 19792, 19824, 19632, 19664, 19696, 19728, 19760, 19792,
- 19824, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
- 19632, 19664, 19696, 19728, 19760, 19792, 19824, 19632,
- 19664, 19696, 19728, 19760, 19792, 19856, 19888, 19920,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
- 19952, 19952, 19952, 19952, 19952, 19952, 19952, 19952,
-
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
-
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 19984, 19984, 19984, 19984, 19984, 19984, 19984, 19984,
- 20016, 20016, 20016, 20016, 20016, 20016, 20016, 20016,
- 20048, 20080, 20112, 20144, 20176, 20176, 20208, 20240,
- 20272, 20304, 20336, 20368, 20368, 20400, 20432, 20368,
- 20368, 20368, 20368, 20368, 20368, 20368, 20368, 20368,
- 20368, 20464, 20496, 20368, 20528, 20368, 20560, 20592,
- 20624, 20656, 20688, 20720, 20368, 20368, 20368, 20752,
- 20784, 20816, 20848, 20880, 20912, 20944, 20976, 21008,
-
- 21040, 21072, 21104, 9936, 21136, 21136, 21136, 21168,
- 21200, 21232, 21264, 21296, 21328, 21360, 21392, 21424,
- 9936, 9936, 9936, 9936, 21456, 21488, 21520, 21552,
- 21584, 21616, 21648, 21680, 21712, 21744, 21776, 9936,
- 21808, 21840, 21872, 21904, 21936, 21968, 22000, 22032,
- 22064, 22096, 22128, 22160, 9936, 9936, 9936, 9936,
- 22192, 22192, 22192, 22192, 22192, 22192, 22192, 22192,
- 22192, 22224, 22256, 22288, 9936, 9936, 9936, 9936,
- 22320, 22352, 22384, 22416, 22448, 22480, 8432, 22512,
- 22544, 22576, 8432, 8432, 22608, 22640, 22672, 22704,
- 22736, 22768, 22800, 22832, 22864, 8432, 22896, 22928,
- 22960, 22992, 23024, 23056, 23088, 23120, 8432, 8432,
- 23152, 23152, 23184, 8432, 23216, 23248, 23280, 23312,
- 23344, 23376, 8432, 8432, 8432, 8432, 8432, 8432,
- 8432, 8432, 8432, 23408, 23440, 23472, 8432, 8432,
- 23504, 23536, 23568, 8432, 8432, 23600, 23632, 23664,
+ 14800, 14800, 14832, 14864, 14896, 14928, 14960, 14992,
+ 15024, 15056, 15088, 15120, 15152, 15184, 15216, 15248,
+ 15280, 15312, 15344, 15376, 15408, 15440, 15472, 15504,
+ 15536, 15536, 15536, 15536, 15536, 15536, 15536, 15536,
+ 15568, 15600, 15568, 15568, 15632, 15664, 15696, 15728,
+ 15760, 15792, 15568, 15824, 15856, 15888, 15920, 15952,
+ 15984, 16016, 16048, 16080, 16112, 16144, 16176, 16208,
+ 16240, 16272, 16304, 16336, 16368, 16368, 16368, 16400,
+ 16432, 16464, 16496, 16528, 16560, 16592, 16592, 16624,
+ 16656, 16688, 16720, 9936, 16752, 16784, 16784, 16816,
+ 16848, 16848, 16848, 16848, 16848, 16848, 16880, 16912,
+
+ 16944, 16976, 17008, 17040, 17072, 17104, 17136, 17168,
+ 17200, 17232, 17264, 17296, 17328, 17360, 17392, 17424,
+ 17456, 17488, 17520, 17552, 17584, 17616, 17648, 17680,
+ 17712, 17712, 17744, 17776, 17808, 17808, 17840, 17872,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17904, 17904, 17904,
+ 17904, 17904, 17904, 17904, 17904, 17936, 17968, 17968,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000,
+ 18000, 18000, 18000, 18000, 18000, 18032, 18064, 18096,
+
+ 18128, 18160, 18160, 18160, 18160, 18160, 18160, 18160,
+ 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160,
+ 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160,
+ 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160,
+ 18160, 18160, 18160, 18160, 18192, 18224, 18256, 18288,
+ 18320, 18320, 18320, 18320, 18320, 18320, 18320, 18320,
+ 18352, 18384, 18416, 18448, 18480, 18512, 18512, 18544,
+ 18576, 18608, 18640, 18672, 18704, 18736, 18768, 18800,
+ 18832, 18864, 18896, 18928, 18960, 18992, 19024, 19056,
+ 19088, 19120, 19152, 19184, 19216, 19248, 19280, 19312,
+ 19344, 19376, 19408, 19440, 19472, 19504, 19536, 19568,
+ 19600, 19632, 19664, 19696, 19728, 19760, 19792, 19824,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+ 19888, 19920, 19952, 19984, 20016, 20048, 19856, 19888,
+ 19920, 19952, 19984, 20016, 20048, 19856, 19888, 19920,
+ 19952, 19984, 20016, 20048, 19856, 19888, 19920, 19952,
+
+ 19984, 20016, 20048, 19856, 19888, 19920, 19952, 19984,
+ 20016, 20048, 19856, 19888, 19920, 19952, 19984, 20016,
+ 20048, 19856, 19888, 19920, 19952, 19984, 20016, 20048,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+ 19888, 19920, 19952, 19984, 20016, 20048, 19856, 19888,
+ 19920, 19952, 19984, 20016, 20048, 19856, 19888, 19920,
+ 19952, 19984, 20016, 20048, 19856, 19888, 19920, 19952,
+ 19984, 20016, 20048, 19856, 19888, 19920, 19952, 19984,
+ 20016, 20048, 19856, 19888, 19920, 19952, 19984, 20016,
+ 20048, 19856, 19888, 19920, 19952, 19984, 20016, 20048,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+ 19888, 19920, 19952, 19984, 20016, 20048, 19856, 19888,
+ 19920, 19952, 19984, 20016, 20048, 19856, 19888, 19920,
+ 19952, 19984, 20016, 20048, 19856, 19888, 19920, 19952,
+ 19984, 20016, 20048, 19856, 19888, 19920, 19952, 19984,
+ 20016, 20048, 19856, 19888, 19920, 19952, 19984, 20016,
+
+ 20048, 19856, 19888, 19920, 19952, 19984, 20016, 20048,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+ 19888, 19920, 19952, 19984, 20016, 20048, 19856, 19888,
+ 19920, 19952, 19984, 20016, 20048, 19856, 19888, 19920,
+ 19952, 19984, 20016, 20048, 19856, 19888, 19920, 19952,
+ 19984, 20016, 20048, 19856, 19888, 19920, 19952, 19984,
+ 20016, 20048, 19856, 19888, 19920, 19952, 19984, 20016,
+ 20048, 19856, 19888, 19920, 19952, 19984, 20016, 20048,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+ 19888, 19920, 19952, 19984, 20016, 20048, 19856, 19888,
+ 19920, 19952, 19984, 20016, 20048, 19856, 19888, 19920,
+ 19952, 19984, 20016, 20048, 19856, 19888, 19920, 19952,
+ 19984, 20016, 20048, 19856, 19888, 19920, 19952, 19984,
+ 20016, 20048, 19856, 19888, 19920, 19952, 19984, 20016,
+ 20048, 19856, 19888, 19920, 19952, 19984, 20016, 20048,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+
+ 19888, 19920, 19952, 19984, 20016, 20048, 19856, 19888,
+ 19920, 19952, 19984, 20016, 20048, 19856, 19888, 19920,
+ 19952, 19984, 20016, 20048, 19856, 19888, 19920, 19952,
+ 19984, 20016, 20048, 19856, 19888, 19920, 19952, 19984,
+ 20016, 20048, 19856, 19888, 19920, 19952, 19984, 20016,
+ 20048, 19856, 19888, 19920, 19952, 19984, 20016, 20048,
+ 19856, 19888, 19920, 19952, 19984, 20016, 20048, 19856,
+ 19888, 19920, 19952, 19984, 20016, 20080, 20112, 20144,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+ 20176, 20176, 20176, 20176, 20176, 20176, 20176, 20176,
+
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20208, 20208, 20208, 20208, 20208, 20208, 20208, 20208,
+ 20240, 20240, 20240, 20240, 20240, 20240, 20240, 20240,
+ 20272, 20304, 20336, 20368, 20400, 20400, 20432, 20464,
+ 20496, 20528, 20560, 20592, 20592, 20624, 20656, 20592,
+ 20592, 20592, 20688, 20720, 20592, 20592, 20592, 20592,
+ 20592, 20752, 20784, 20592, 20816, 20592, 20848, 20880,
+ 20912, 20944, 20976, 21008, 20592, 20592, 20592, 21040,
+ 21072, 21104, 21136, 21168, 21200, 21232, 21264, 21296,
+
+ 21328, 21360, 21392, 9936, 21424, 21424, 21424, 21456,
+ 21488, 21520, 21552, 21584, 21616, 21648, 21680, 21712,
+ 9936, 9936, 9936, 9936, 21744, 21776, 21808, 21840,
+ 21872, 21904, 21936, 21968, 22000, 22032, 22064, 9936,
+ 22096, 22128, 22160, 22192, 22224, 22256, 22288, 22320,
+ 22352, 22384, 22416, 22448, 22480, 22512, 9936, 9936,
+ 22544, 22544, 22544, 22544, 22544, 22544, 22544, 22544,
+ 22544, 22576, 22608, 22640, 22672, 22704, 9936, 9936,
+ 22736, 22768, 22800, 22832, 22864, 22896, 22928, 22960,
+ 22992, 23024, 22928, 22928, 23056, 23088, 23120, 23152,
+ 23184, 23216, 23248, 23280, 23312, 22928, 23344, 23376,
+ 23408, 23440, 23472, 23504, 23536, 23568, 22928, 22928,
+ 23600, 23600, 23632, 22928, 23664, 23696, 23728, 23760,
+ 23792, 23824, 22928, 22928, 22928, 22928, 22928, 22928,
+ 22928, 22928, 22928, 23856, 23888, 23920, 22928, 23952,
+ 23984, 24016, 24048, 24080, 24112, 24144, 24176, 24208,
// [0x11000..0x110000)
- 23696, 23952, 24208, 24464, 24720, 24976, 25232, 25488,
- 25744, 26000, 26256, 26512, 26768, 27024, 27280, 27536,
- 27792, 27792, 27792, 28048, 28304, 28560, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 28816, 28816, 29072, 29328, 29584, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 29840, 30096, 30352, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 30608, 30608, 30864, 31120, 26512, 26512, 31376, 31632,
- 31888, 31888, 31888, 31888, 31888, 31888, 31888, 31888,
- 31888, 31888, 31888, 31888, 31888, 31888, 31888, 31888,
- 31888, 31888, 31888, 31888, 31888, 31888, 31888, 32144,
- 31888, 31888, 32400, 32656, 32912, 33168, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 33424, 33680, 33936, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 34192, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 34448, 34704, 34960, 35216, 35472, 35728, 35984, 36240,
- 36496, 36496, 36752, 26512, 26512, 26512, 26512, 26512,
- 37008, 37264, 37520, 26512, 26512, 26512, 26512, 26512,
- 37776, 38032, 38288, 38288, 38544, 38800, 39056, 38288,
- 39312, 39568, 39824, 40080, 40336, 40592, 40848, 41104,
- 41360, 41616, 41872, 42128, 42384, 42384, 42384, 42640,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
-
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 42896, 42896,
- 42896, 42896, 42896, 42896, 42896, 42896, 43152, 43408,
- 43408, 43408, 43408, 43408, 43408, 43408, 43408, 43408,
- 43408, 43408, 43408, 43408, 43408, 43408, 43408, 43664,
- 43920, 44176, 44176, 44176, 44176, 44176, 44176, 44176,
- 44176, 44176, 44176, 44176, 44176, 44176, 44176, 44176,
- 44176, 44176, 44176, 44176, 44176, 44176, 44432, 44688,
- 44688, 44688, 44688, 44688, 44688, 44688, 44688, 44688,
- 44688, 44688, 44688, 44688, 44688, 44688, 44688, 44688,
- 44688, 44688, 44688, 44688, 44688, 44688, 44688, 44688,
- 44688, 44688, 44688, 44944, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 45200, 45200, 45456, 42384, 42384, 42384, 42384, 42640,
- 45712, 45712, 45712, 45712, 45712, 45712, 45712, 45712,
- 45712, 45712, 45712, 45712, 45712, 45712, 45712, 45712,
- 45712, 45712, 45712, 45968, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
-
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42384,
- 42384, 42384, 42384, 42384, 42384, 42384, 42384, 42640,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 46480, 46736, 46992, 46992, 46992, 46992, 46992, 46992,
- 46992, 46992, 46992, 46992, 46992, 46992, 46992, 46992,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
-
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 26512,
- 26512, 26512, 26512, 26512, 26512, 26512, 26512, 46224,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
-
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47504,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
-
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47248,
- 47248, 47248, 47248, 47248, 47248, 47248, 47248, 47504,
+ 24240, 24496, 24752, 25008, 25264, 25520, 25776, 26032,
+ 26288, 26544, 26800, 27056, 27312, 27568, 27824, 28080,
+ 28336, 28336, 28336, 28592, 28848, 29104, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29616,
+ 29872, 29872, 30128, 30384, 30640, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 30896, 31152, 31408, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 31664, 31664, 31920, 32176, 29360, 29360, 32432, 32688,
+ 32944, 32944, 32944, 32944, 32944, 32944, 32944, 32944,
+ 32944, 32944, 32944, 32944, 32944, 32944, 32944, 32944,
+ 32944, 32944, 32944, 32944, 32944, 32944, 32944, 33200,
+ 32944, 32944, 33456, 33712, 33968, 34224, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 34480,
+ 34736, 34992, 35248, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 35504, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 35760,
+ 36016, 36272, 36528, 36784, 37040, 37296, 37552, 37808,
+ 38064, 38064, 38320, 29360, 29360, 29360, 29360, 38576,
+ 38832, 39088, 39344, 29360, 39600, 29360, 29360, 39856,
+ 40112, 40368, 40624, 40624, 40880, 41136, 41392, 40624,
+ 41648, 41904, 42160, 42416, 42672, 42928, 43184, 43440,
+ 43696, 43952, 44208, 44464, 44720, 44720, 44720, 44976,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45232, 45232,
+ 45232, 45232, 45232, 45232, 45232, 45232, 45488, 45744,
+ 45744, 45744, 45744, 45744, 45744, 45744, 45744, 45744,
+ 45744, 45744, 45744, 45744, 45744, 45744, 45744, 46000,
+ 46256, 46512, 46512, 46512, 46512, 46512, 46512, 46512,
+ 46512, 46512, 46512, 46512, 46512, 46512, 46512, 46512,
+ 46512, 46512, 46512, 46512, 46512, 46512, 46768, 47024,
+ 47024, 47024, 47024, 47024, 47024, 47024, 47024, 47024,
+ 47024, 47024, 47024, 47024, 47024, 47024, 47024, 47024,
+ 47024, 47024, 47024, 47024, 47024, 47024, 47024, 47024,
+ 47024, 47024, 47024, 47280, 47536, 47536, 47792, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48304, 48560, 48816, 48048, 48048, 48048, 48048, 49072,
+ 49328, 49328, 49328, 49328, 49328, 49328, 49328, 49328,
+ 49328, 49328, 49328, 49328, 49328, 49328, 49328, 49328,
+ 49328, 49328, 49328, 49584, 49840, 49840, 49840, 49840,
+ 49840, 49840, 49840, 49840, 49840, 49840, 49840, 49840,
+ 49840, 49840, 49840, 50096, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 48048,
+ 48048, 48048, 48048, 48048, 48048, 48048, 48048, 49072,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 50608, 50864, 51120, 51120, 51120, 51120, 51120, 51120,
+ 51120, 51120, 51120, 51120, 51120, 51120, 51120, 51120,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 29360,
+ 29360, 29360, 29360, 29360, 29360, 29360, 29360, 50352,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51632,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51376,
+ 51376, 51376, 51376, 51376, 51376, 51376, 51376, 51632,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -892,2590 +856,2190 @@ static const unsigned short uc_property_trie[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 48, 49, 50, 12, 12, 12, 51, 14,
- 52, 51, 53, 54, 36, 55, 51, 52,
- 56, 57, 58, 59, 60, 61, 14, 62,
- 52, 63, 53, 64, 65, 65, 65, 49,
-
- 66, 66, 66, 66, 66, 66, 38, 66,
- 66, 66, 66, 66, 66, 66, 66, 66,
- 38, 66, 66, 66, 66, 66, 66, 36,
- 38, 66, 66, 66, 66, 66, 38, 67,
-
- 68, 68, 68, 68, 68, 68, 44, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 44, 68, 68, 68, 68, 68, 68, 36,
- 44, 68, 68, 68, 68, 68, 44, 69,
-
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 72, 73, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
-
- 70, 71, 70, 71, 70, 71, 72, 73,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 74, 75, 76, 77, 70, 71, 70, 71,
- 78, 70, 71, 70, 71, 70, 71, 76,
-
- 77, 72, 73, 70, 71, 70, 71, 70,
- 71, 79, 72, 73, 70, 71, 70, 71,
- 70, 71, 72, 73, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
-
- 70, 71, 70, 71, 70, 71, 72, 73,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 80, 70, 71, 70, 71, 70, 71, 81,
-
- 82, 83, 72, 73, 72, 73, 84, 72,
- 73, 85, 85, 72, 73, 78, 86, 87,
- 88, 72, 73, 85, 89, 90, 91, 92,
- 72, 73, 93, 78, 91, 94, 95, 96,
-
- 70, 71, 72, 73, 72, 73, 97, 72,
- 73, 97, 78, 78, 72, 73, 97, 70,
- 71, 98, 98, 72, 73, 72, 73, 99,
- 72, 73, 78, 100, 72, 73, 78, 101,
-
- 100, 100, 100, 100, 102, 103, 104, 102,
- 103, 104, 102, 103, 104, 70, 71, 70,
- 71, 70, 71, 70, 71, 70, 71, 70,
- 71, 70, 71, 70, 71, 105, 70, 71,
-
- 70, 71, 70, 71, 72, 73, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 106, 102, 103, 104, 70, 71, 107, 108,
- 109, 110, 70, 71, 70, 71, 70, 71,
-
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 109, 110, 109, 110, 111, 112, 109, 110,
-
- 113, 114, 111, 112, 111, 112, 109, 110,
- 109, 110, 109, 110, 109, 110, 109, 110,
- 109, 110, 109, 110, 114, 114, 114, 115,
- 115, 115, 116, 117, 118, 119, 120, 121,
-
- 122, 117, 123, 124, 125, 126, 127, 123,
- 127, 123, 127, 123, 127, 123, 127, 123,
- 128, 129, 130, 131, 132, 78, 133, 133,
- 78, 134, 78, 135, 136, 78, 78, 78,
-
- 133, 137, 78, 138, 78, 139, 140, 78,
- 141, 142, 143, 144, 145, 78, 78, 142,
- 78, 146, 147, 78, 78, 148, 78, 78,
- 78, 78, 78, 78, 78, 149, 78, 78,
-
- 150, 78, 151, 150, 78, 78, 78, 152,
- 150, 153, 154, 154, 155, 78, 78, 78,
- 78, 78, 156, 78, 100, 78, 78, 78,
- 78, 78, 78, 78, 78, 157, 158, 78,
-
- 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 159, 159, 159, 159, 159, 114, 114,
- 160, 160, 160, 160, 160, 160, 160, 160,
- 160, 161, 161, 162, 162, 162, 162, 162,
-
- 163, 163, 164, 164, 164, 164, 161, 161,
- 165, 161, 161, 161, 165, 161, 161, 161,
- 162, 162, 164, 164, 164, 164, 164, 164,
- 52, 52, 52, 52, 52, 52, 164, 166,
-
- 160, 160, 160, 160, 160, 164, 164, 164,
- 164, 164, 167, 167, 168, 169, 170, 171,
- 171, 171, 171, 171, 171, 171, 171, 171,
- 171, 171, 171, 171, 171, 171, 171, 171,
-
- 172, 172, 172, 172, 172, 173, 172, 172,
- 172, 172, 172, 172, 172, 173, 173, 172,
- 173, 172, 173, 172, 172, 174, 175, 175,
- 175, 175, 174, 176, 175, 175, 175, 175,
-
- 175, 177, 177, 178, 178, 178, 178, 179,
- 179, 175, 175, 175, 175, 178, 178, 175,
- 178, 178, 175, 175, 180, 180, 180, 180,
- 181, 175, 175, 175, 175, 173, 173, 173,
-
- 182, 182, 172, 182, 182, 183, 184, 185,
- 185, 185, 184, 184, 184, 185, 185, 186,
- 187, 187, 187, 188, 188, 188, 188, 187,
- 189, 190, 190, 191, 192, 193, 193, 194,
-
- 195, 195, 196, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 197, 197,
- 198, 199, 198, 199, 200, 201, 198, 199,
- 202, 202, 203, 204, 204, 204, 205, 206,
-
- 202, 202, 202, 202, 207, 208, 209, 210,
- 211, 211, 211, 202, 212, 202, 213, 213,
- 214, 215, 215, 215, 215, 215, 215, 215,
- 215, 215, 215, 215, 215, 215, 215, 215,
-
- 215, 215, 202, 215, 215, 215, 215, 215,
- 215, 215, 216, 216, 217, 218, 218, 218,
- 219, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220,
-
- 220, 220, 221, 220, 220, 220, 220, 220,
- 220, 220, 222, 222, 223, 224, 224, 225,
- 226, 227, 228, 229, 229, 230, 231, 232,
- 233, 234, 235, 236, 235, 236, 235, 236,
-
- 235, 236, 237, 238, 237, 238, 237, 238,
- 237, 238, 237, 238, 237, 238, 237, 238,
- 239, 240, 241, 242, 243, 244, 245, 246,
- 247, 248, 246, 247, 249, 250, 250, 250,
-
- 251, 252, 253, 252, 253, 253, 253, 252,
- 253, 253, 253, 253, 252, 251, 252, 253,
- 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 255, 254, 254, 254, 254, 254, 254,
-
- 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254,
- 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 257, 256, 256, 256, 256, 256, 256,
-
- 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256,
- 258, 259, 260, 259, 260, 260, 260, 259,
- 260, 260, 260, 260, 259, 258, 259, 260,
-
- 261, 262, 261, 262, 261, 262, 261, 262,
- 261, 262, 261, 262, 261, 262, 261, 262,
- 261, 262, 261, 262, 261, 262, 263, 264,
- 261, 262, 261, 262, 261, 262, 261, 262,
-
- 261, 262, 265, 266, 266, 173, 173, 267,
- 268, 268, 269, 270, 271, 272, 271, 272,
- 261, 262, 261, 262, 261, 262, 261, 262,
- 261, 262, 261, 262, 261, 262, 261, 262,
-
- 261, 262, 261, 262, 261, 262, 261, 262,
- 261, 262, 261, 262, 261, 262, 261, 262,
- 261, 262, 261, 262, 261, 262, 261, 262,
- 261, 262, 261, 262, 261, 262, 261, 262,
-
- 273, 263, 264, 261, 262, 269, 270, 261,
- 262, 269, 270, 261, 262, 269, 270, 274,
- 263, 264, 263, 264, 261, 262, 263, 264,
- 261, 262, 263, 264, 263, 264, 263, 264,
-
- 261, 262, 263, 264, 263, 264, 263, 264,
- 261, 262, 263, 264, 275, 276, 263, 264,
- 263, 264, 263, 264, 263, 264, 277, 278,
- 263, 264, 279, 280, 279, 280, 279, 280,
-
- 269, 270, 269, 270, 269, 270, 269, 270,
- 269, 270, 269, 270, 269, 270, 269, 270,
- 279, 280, 279, 280, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 281, 282,
-
- 281, 282, 281, 282, 283, 284, 285, 286,
- 287, 288, 287, 288, 287, 288, 287, 288,
- 202, 289, 289, 289, 289, 289, 289, 289,
- 289, 289, 289, 289, 289, 289, 289, 289,
-
- 289, 289, 289, 289, 289, 289, 289, 289,
- 289, 289, 289, 289, 289, 289, 289, 289,
- 289, 289, 289, 289, 289, 289, 289, 202,
- 202, 290, 291, 291, 291, 292, 291, 293,
-
- 294, 295, 295, 295, 295, 295, 295, 295,
- 295, 295, 295, 295, 295, 295, 295, 295,
- 295, 295, 295, 295, 295, 295, 295, 295,
- 295, 295, 295, 295, 295, 295, 295, 295,
-
- 295, 295, 295, 295, 295, 295, 295, 296,
- 294, 297, 298, 202, 202, 299, 299, 300,
- 301, 302, 303, 303, 303, 303, 302, 303,
- 303, 303, 304, 302, 303, 303, 303, 303,
-
- 303, 303, 305, 302, 302, 302, 302, 302,
- 303, 303, 302, 303, 303, 304, 306, 303,
- 307, 308, 309, 310, 311, 312, 313, 314,
- 315, 316, 317, 318, 319, 320, 321, 322,
-
- 323, 324, 325, 323, 303, 305, 326, 327,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 328, 328, 328, 328, 328, 328, 328, 328,
- 328, 328, 328, 328, 328, 328, 328, 328,
-
- 328, 328, 328, 328, 328, 328, 328, 328,
- 328, 328, 328, 301, 301, 301, 301, 329,
- 328, 328, 328, 330, 331, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 332, 332, 332, 332, 333, 334, 335, 335,
- 336, 337, 337, 338, 19, 339, 340, 340,
- 341, 341, 341, 341, 341, 341, 342, 342,
- 343, 344, 345, 346, 347, 348, 349, 350,
-
- 351, 352, 353, 353, 353, 353, 354, 355,
- 356, 355, 356, 356, 356, 356, 356, 355,
- 355, 355, 355, 356, 356, 356, 356, 356,
- 356, 356, 356, 357, 357, 357, 357, 357,
-
- 358, 356, 356, 356, 356, 356, 356, 356,
- 355, 356, 356, 359, 360, 361, 362, 363,
- 364, 365, 366, 367, 367, 368, 369, 341,
- 341, 370, 370, 370, 371, 370, 370, 372,
-
- 373, 374, 375, 376, 377, 378, 379, 380,
- 381, 382, 383, 384, 385, 386, 387, 387,
- 388, 355, 355, 355, 352, 389, 389, 389,
- 390, 356, 356, 356, 356, 356, 356, 356,
-
- 356, 356, 356, 356, 356, 356, 356, 356,
- 355, 355, 355, 355, 355, 355, 355, 355,
- 355, 355, 355, 355, 355, 355, 355, 355,
- 355, 355, 356, 356, 356, 356, 356, 356,
-
- 356, 356, 356, 356, 356, 356, 356, 356,
- 356, 356, 356, 356, 356, 356, 356, 356,
- 356, 356, 356, 356, 356, 356, 356, 356,
- 391, 391, 356, 356, 356, 356, 356, 391,
-
- 353, 356, 354, 355, 355, 355, 355, 355,
- 355, 355, 355, 355, 356, 355, 356, 392,
- 356, 356, 355, 353, 393, 355, 394, 394,
- 394, 394, 394, 394, 394, 395, 396, 394,
-
- 394, 394, 394, 397, 394, 398, 398, 394,
- 394, 396, 397, 394, 394, 397, 399, 399,
- 400, 401, 402, 403, 404, 405, 406, 407,
- 408, 409, 391, 391, 391, 410, 410, 411,
-
- 412, 412, 412, 413, 413, 413, 413, 413,
- 413, 413, 413, 413, 413, 413, 348, 414,
- 415, 416, 417, 417, 417, 415, 415, 415,
- 415, 415, 417, 417, 417, 417, 415, 417,
-
- 417, 417, 417, 417, 417, 417, 417, 417,
- 415, 417, 415, 417, 415, 418, 418, 419,
- 420, 421, 420, 420, 421, 420, 420, 421,
- 421, 421, 420, 421, 421, 420, 421, 420,
-
- 420, 420, 421, 420, 421, 420, 421, 420,
- 421, 420, 420, 348, 348, 419, 418, 418,
- 422, 422, 422, 422, 422, 422, 422, 422,
- 422, 423, 423, 423, 422, 422, 422, 422,
-
- 422, 422, 422, 422, 422, 422, 422, 422,
- 422, 422, 422, 423, 423, 422, 357, 357,
- 357, 424, 357, 424, 424, 357, 357, 357,
- 424, 424, 357, 357, 357, 357, 357, 357,
-
- 425, 425, 425, 425, 425, 425, 425, 425,
- 425, 425, 425, 425, 425, 425, 425, 425,
- 425, 425, 425, 425, 425, 425, 425, 425,
- 425, 425, 425, 425, 425, 425, 425, 425,
-
- 425, 425, 425, 425, 425, 425, 426, 426,
- 426, 426, 426, 426, 426, 426, 426, 426,
- 426, 427, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
-
- 428, 429, 430, 431, 432, 433, 434, 435,
- 436, 437, 438, 438, 438, 438, 438, 438,
- 438, 438, 438, 438, 438, 438, 438, 438,
- 438, 438, 438, 438, 438, 438, 438, 438,
-
- 438, 438, 438, 438, 438, 438, 438, 438,
- 438, 438, 438, 439, 439, 439, 439, 439,
- 439, 439, 440, 439, 441, 441, 442, 443,
- 444, 445, 446, 301, 301, 447, 448, 448,
+ 48, 49, 50, 51, 52, 51, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 54, 69,
+ 55, 70, 57, 71, 72, 72, 72, 49,
+
+ 73, 73, 73, 73, 73, 73, 74, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73,
+ 74, 73, 73, 73, 73, 73, 73, 75,
+ 74, 73, 73, 73, 73, 73, 74, 76,
+
+ 77, 77, 78, 78, 78, 78, 79, 78,
+ 77, 77, 77, 78, 77, 77, 78, 78,
+ 79, 78, 77, 77, 78, 78, 78, 75,
+ 79, 77, 77, 78, 77, 78, 79, 80,
+
+ 81, 82, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 84, 85, 81, 82, 81, 83, 81, 83,
+ 81, 83, 81, 82, 81, 83, 81, 83,
+
+ 81, 83, 81, 83, 81, 83, 86, 85,
+ 81, 83, 81, 82, 81, 83, 81, 83,
+ 87, 88, 89, 90, 81, 83, 81, 83,
+ 91, 81, 83, 81, 83, 81, 83, 89,
+
+ 90, 86, 85, 81, 82, 81, 83, 81,
+ 82, 92, 86, 85, 81, 82, 81, 83,
+ 81, 83, 86, 85, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+
+ 81, 83, 81, 83, 81, 83, 86, 85,
+ 81, 83, 81, 82, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 93, 81, 83, 81, 83, 81, 83, 94,
+
+ 95, 96, 84, 97, 84, 97, 98, 84,
+ 97, 99, 99, 84, 97, 100, 101, 102,
+ 103, 84, 97, 99, 104, 105, 106, 107,
+ 84, 97, 108, 100, 106, 109, 110, 111,
+
+ 81, 83, 84, 97, 84, 97, 112, 84,
+ 97, 112, 100, 100, 84, 97, 112, 81,
+ 83, 113, 113, 84, 97, 84, 97, 114,
+ 84, 97, 100, 115, 84, 97, 100, 116,
+
+ 115, 115, 115, 115, 117, 118, 119, 117,
+ 118, 119, 117, 118, 119, 81, 82, 81,
+ 82, 81, 82, 81, 82, 81, 82, 81,
+ 82, 81, 82, 81, 82, 120, 81, 83,
+
+ 81, 83, 81, 83, 84, 97, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 121, 117, 118, 119, 81, 83, 122, 123,
+ 124, 125, 81, 83, 81, 83, 81, 83,
+
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 124, 125, 124, 125, 126, 127, 124, 125,
+
+ 128, 129, 126, 127, 126, 127, 124, 125,
+ 124, 125, 124, 125, 124, 125, 124, 125,
+ 124, 125, 124, 125, 129, 129, 129, 130,
+ 130, 130, 131, 132, 133, 134, 135, 136,
+
+ 137, 132, 138, 139, 140, 141, 142, 138,
+ 142, 138, 142, 138, 142, 138, 142, 138,
+ 143, 144, 145, 146, 147, 100, 148, 148,
+ 100, 149, 100, 150, 151, 100, 100, 100,
+
+ 148, 152, 100, 153, 100, 154, 155, 100,
+ 156, 157, 158, 159, 160, 100, 100, 157,
+ 100, 161, 162, 100, 100, 163, 100, 100,
+ 100, 100, 100, 100, 100, 164, 100, 100,
+
+ 165, 100, 166, 165, 100, 100, 100, 167,
+ 165, 168, 169, 169, 170, 100, 100, 100,
+ 100, 100, 171, 100, 115, 100, 100, 100,
+ 100, 100, 100, 100, 100, 172, 173, 100,
+
+ 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 174, 174, 174, 174, 174, 129, 129,
+ 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 176, 176, 177, 177, 177, 177, 177,
+
+ 178, 178, 179, 179, 180, 179, 176, 181,
+ 182, 181, 181, 181, 182, 181, 176, 176,
+ 183, 177, 179, 179, 179, 179, 179, 179,
+ 55, 55, 55, 55, 184, 55, 179, 185,
+
+ 175, 175, 175, 175, 175, 179, 179, 179,
+ 179, 179, 186, 186, 187, 188, 189, 190,
+ 190, 190, 190, 190, 190, 190, 190, 190,
+ 190, 190, 190, 190, 190, 190, 190, 190,
+
+ 191, 191, 191, 191, 191, 192, 191, 191,
+ 191, 191, 191, 191, 191, 192, 192, 191,
+ 192, 191, 192, 191, 191, 193, 194, 194,
+ 194, 194, 193, 195, 194, 194, 194, 194,
+
+ 194, 196, 196, 197, 197, 197, 197, 198,
+ 198, 194, 194, 194, 194, 197, 197, 194,
+ 197, 197, 194, 194, 199, 199, 199, 199,
+ 200, 194, 194, 194, 194, 192, 192, 192,
+
+ 201, 201, 191, 201, 201, 202, 203, 204,
+ 204, 204, 203, 203, 203, 204, 204, 205,
+ 206, 206, 206, 207, 207, 207, 207, 206,
+ 208, 209, 209, 210, 211, 212, 212, 213,
+
+ 214, 214, 215, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216,
+ 217, 218, 217, 218, 219, 220, 217, 218,
+ 221, 221, 222, 223, 223, 223, 224, 225,
+
+ 221, 221, 221, 221, 226, 227, 228, 229,
+ 230, 230, 230, 221, 231, 221, 232, 232,
+ 233, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234,
+
+ 234, 234, 221, 234, 234, 234, 234, 234,
+ 234, 234, 235, 235, 236, 237, 237, 237,
+ 238, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239,
+
+ 239, 239, 240, 239, 239, 239, 239, 239,
+ 239, 239, 241, 241, 242, 243, 243, 244,
+ 245, 246, 247, 248, 248, 249, 250, 251,
+ 252, 253, 254, 255, 254, 255, 254, 255,
+
+ 254, 255, 256, 257, 256, 257, 256, 257,
+ 256, 257, 256, 257, 256, 257, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 265, 266, 268, 269, 269, 269,
+
+ 270, 271, 272, 273, 272, 272, 272, 273,
+ 272, 272, 272, 272, 273, 270, 273, 272,
+ 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 275, 274, 274, 274, 274, 274, 274,
+
+ 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 274, 274, 274,
+ 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 277, 276, 276, 276, 276, 276, 276,
+
+ 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276,
+ 278, 279, 280, 281, 280, 280, 280, 281,
+ 280, 280, 280, 280, 281, 278, 281, 280,
+
+ 282, 283, 282, 283, 282, 283, 282, 283,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+ 282, 283, 282, 283, 282, 283, 284, 285,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+
+ 282, 283, 286, 287, 287, 288, 288, 289,
+ 290, 290, 291, 292, 293, 294, 293, 294,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+
+ 282, 283, 282, 283, 282, 283, 282, 283,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+ 282, 283, 282, 283, 282, 283, 282, 283,
+
+ 295, 284, 285, 282, 283, 291, 292, 282,
+ 283, 291, 292, 282, 283, 291, 292, 296,
+ 284, 285, 284, 285, 282, 283, 284, 285,
+ 282, 283, 284, 285, 284, 285, 284, 285,
+
+ 282, 283, 284, 285, 284, 285, 284, 285,
+ 282, 283, 284, 285, 297, 298, 284, 285,
+ 284, 285, 284, 285, 284, 285, 299, 300,
+ 284, 285, 301, 302, 301, 302, 301, 302,
+
+ 291, 292, 291, 292, 291, 292, 291, 292,
+ 291, 292, 291, 292, 291, 292, 291, 292,
+ 301, 302, 301, 302, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 303, 304,
+
+ 303, 304, 303, 304, 305, 306, 307, 308,
+ 309, 310, 309, 310, 309, 310, 309, 310,
+ 221, 311, 311, 311, 311, 311, 311, 311,
+ 311, 311, 311, 311, 311, 311, 311, 311,
+
+ 311, 311, 311, 311, 311, 311, 311, 311,
+ 311, 311, 311, 311, 311, 311, 311, 311,
+ 311, 311, 311, 311, 311, 311, 311, 221,
+ 221, 312, 313, 313, 313, 314, 313, 315,
+
+ 316, 317, 317, 317, 317, 317, 317, 317,
+ 317, 317, 317, 317, 317, 317, 317, 317,
+ 317, 317, 317, 317, 317, 317, 317, 317,
+ 317, 317, 317, 317, 317, 317, 317, 317,
+
+ 317, 317, 317, 317, 317, 317, 317, 318,
+ 316, 319, 320, 221, 221, 321, 321, 322,
+ 323, 324, 325, 325, 325, 325, 324, 325,
+ 325, 325, 326, 324, 325, 325, 325, 325,
+
+ 325, 325, 327, 324, 324, 324, 324, 324,
+ 325, 325, 324, 325, 325, 326, 328, 325,
+ 329, 330, 331, 332, 333, 334, 335, 336,
+ 337, 338, 339, 340, 341, 342, 343, 344,
+
+ 345, 346, 347, 345, 325, 327, 348, 349,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 350, 350, 350, 350, 350, 350, 350, 350,
+ 350, 350, 350, 350, 350, 350, 350, 350,
+
+ 350, 350, 350, 350, 350, 350, 350, 350,
+ 350, 350, 350, 323, 323, 323, 323, 351,
+ 350, 350, 350, 352, 353, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 354, 354, 354, 354, 355, 356, 357, 357,
+ 358, 359, 359, 360, 361, 362, 363, 363,
+ 364, 364, 364, 364, 364, 364, 365, 365,
+ 366, 367, 368, 369, 370, 371, 372, 373,
+
+ 374, 375, 376, 376, 376, 376, 377, 378,
+ 379, 378, 379, 379, 379, 379, 379, 378,
+ 378, 378, 378, 379, 379, 379, 379, 379,
+ 379, 379, 379, 380, 380, 380, 380, 380,
+
+ 381, 379, 379, 379, 379, 379, 379, 379,
+ 378, 379, 379, 382, 383, 384, 385, 386,
+ 387, 388, 389, 390, 390, 391, 392, 364,
+ 364, 393, 393, 393, 394, 393, 393, 395,
+
+ 396, 397, 398, 399, 400, 401, 402, 403,
+ 404, 405, 406, 407, 408, 409, 410, 410,
+ 411, 378, 378, 378, 375, 412, 412, 412,
+ 413, 379, 379, 379, 379, 379, 379, 379,
+
+ 379, 379, 379, 379, 379, 379, 379, 379,
+ 378, 378, 378, 378, 378, 378, 378, 378,
+ 378, 378, 378, 378, 378, 378, 378, 378,
+ 378, 378, 379, 379, 379, 379, 379, 379,
+
+ 379, 379, 379, 379, 379, 379, 379, 379,
+ 379, 379, 379, 379, 379, 379, 379, 379,
+ 379, 379, 379, 379, 379, 379, 379, 379,
+ 414, 414, 379, 379, 379, 379, 379, 414,
+
+ 376, 379, 377, 378, 378, 378, 378, 378,
+ 378, 378, 378, 378, 379, 378, 379, 415,
+ 379, 379, 378, 376, 416, 378, 417, 417,
+ 417, 417, 417, 417, 417, 418, 419, 417,
+
+ 417, 417, 417, 420, 417, 421, 421, 417,
+ 417, 419, 420, 417, 417, 420, 422, 422,
+ 423, 424, 425, 426, 427, 428, 429, 430,
+ 431, 432, 414, 414, 414, 433, 433, 434,
+
+ 435, 435, 435, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 437, 438,
+ 439, 440, 441, 441, 441, 439, 439, 439,
+ 439, 439, 441, 441, 441, 441, 439, 441,
+
+ 441, 441, 441, 441, 441, 441, 441, 441,
+ 439, 441, 439, 441, 439, 442, 442, 443,
+ 444, 445, 444, 444, 445, 444, 444, 445,
+ 445, 445, 444, 445, 445, 444, 445, 444,
+
+ 444, 444, 445, 444, 445, 444, 445, 444,
+ 445, 444, 444, 437, 437, 443, 442, 442,
+ 446, 446, 446, 446, 446, 446, 446, 446,
+ 446, 447, 447, 447, 446, 446, 446, 446,
+
+ 446, 446, 446, 446, 446, 446, 446, 446,
+ 446, 446, 446, 447, 447, 446, 380, 380,
+ 380, 448, 380, 448, 448, 380, 380, 380,
+ 448, 448, 380, 380, 380, 380, 380, 380,
449, 449, 449, 449, 449, 449, 449, 449,
449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449,
+
449, 449, 449, 449, 449, 449, 450, 450,
- 450, 450, 451, 450, 450, 450, 450, 450,
-
- 450, 450, 450, 450, 451, 450, 450, 450,
- 451, 450, 450, 450, 450, 450, 301, 301,
- 452, 452, 452, 452, 452, 452, 452, 453,
- 452, 453, 452, 452, 452, 453, 453, 301,
-
- 454, 455, 455, 455, 455, 455, 454, 454,
- 455, 454, 455, 455, 455, 455, 455, 455,
- 455, 455, 455, 455, 454, 455, 454, 454,
- 454, 456, 456, 456, 301, 301, 457, 301,
-
- 458, 459, 458, 458, 458, 458, 459, 460,
- 458, 460, 460, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 461, 462, 461, 461, 461, 461, 461, 461,
- 461, 461, 463, 463, 463, 464, 465, 462,
- 462, 465, 465, 466, 466, 348, 467, 467,
- 467, 468, 467, 467, 467, 467, 469, 469,
-
- 469, 469, 469, 469, 469, 469, 469, 469,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 470, 471, 471, 471, 471,
- 471, 471, 471, 471, 471, 471, 471, 471,
-
- 471, 471, 472, 473, 474, 474, 475, 474,
- 474, 475, 474, 474, 474, 475, 475, 475,
- 476, 477, 478, 474, 474, 474, 475, 474,
- 474, 475, 475, 474, 474, 474, 474, 479,
-
- 480, 481, 481, 482, 483, 484, 484, 484,
- 484, 484, 484, 484, 484, 484, 484, 484,
- 484, 484, 484, 484, 484, 484, 484, 484,
- 484, 484, 484, 484, 484, 484, 484, 484,
-
- 484, 484, 484, 484, 484, 484, 484, 484,
- 484, 485, 484, 484, 484, 484, 484, 484,
- 484, 485, 484, 484, 485, 484, 484, 484,
- 484, 484, 486, 487, 488, 484, 482, 482,
-
- 482, 481, 481, 481, 481, 481, 481, 481,
- 481, 482, 482, 482, 482, 489, 490, 487,
- 484, 173, 175, 173, 173, 480, 486, 486,
- 491, 491, 491, 491, 491, 491, 491, 491,
-
- 484, 484, 481, 481, 492, 492, 493, 494,
- 495, 496, 497, 498, 499, 500, 501, 502,
- 503, 504, 505, 506, 506, 506, 506, 506,
- 507, 508, 508, 509, 509, 510, 509, 509,
-
- 511, 512, 513, 513, 202, 514, 514, 514,
- 514, 514, 514, 514, 514, 202, 202, 514,
- 514, 202, 202, 514, 514, 514, 514, 514,
- 514, 514, 514, 514, 514, 514, 514, 514,
-
- 514, 514, 514, 514, 514, 514, 514, 514,
- 514, 202, 514, 514, 514, 514, 514, 514,
- 514, 202, 514, 202, 202, 202, 514, 514,
- 514, 514, 202, 202, 515, 516, 517, 513,
-
- 513, 512, 512, 512, 512, 202, 202, 513,
- 513, 202, 202, 518, 518, 519, 520, 202,
- 202, 202, 202, 202, 202, 202, 202, 517,
- 202, 202, 202, 202, 521, 521, 202, 521,
-
- 514, 514, 512, 512, 202, 202, 522, 523,
- 524, 525, 526, 527, 528, 529, 530, 531,
- 514, 514, 532, 532, 533, 533, 533, 533,
- 533, 534, 535, 536, 537, 538, 539, 202,
-
- 202, 540, 541, 542, 202, 543, 543, 543,
- 543, 543, 543, 202, 202, 202, 202, 543,
- 543, 202, 202, 543, 543, 543, 543, 543,
- 543, 543, 543, 543, 543, 543, 543, 543,
-
- 543, 543, 543, 543, 543, 543, 543, 543,
- 543, 202, 543, 543, 543, 543, 543, 543,
- 543, 202, 543, 544, 202, 543, 544, 202,
- 543, 543, 202, 202, 545, 202, 546, 546,
-
- 546, 541, 541, 202, 202, 202, 202, 541,
- 541, 202, 202, 541, 541, 547, 202, 202,
- 202, 548, 202, 202, 202, 202, 202, 202,
- 202, 544, 544, 544, 543, 202, 544, 202,
-
- 202, 202, 202, 202, 202, 202, 549, 550,
- 551, 552, 553, 554, 555, 556, 557, 558,
- 541, 541, 543, 543, 543, 548, 559, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 560, 560, 561, 202, 562, 562, 562,
- 562, 562, 562, 562, 563, 562, 202, 562,
- 562, 562, 202, 562, 562, 562, 562, 562,
- 562, 562, 562, 562, 562, 562, 562, 562,
-
- 562, 562, 562, 562, 562, 562, 562, 562,
- 562, 202, 562, 562, 562, 562, 562, 562,
- 562, 202, 562, 562, 202, 562, 562, 562,
- 562, 562, 202, 202, 564, 562, 561, 561,
-
- 561, 560, 560, 560, 560, 560, 202, 560,
- 560, 561, 202, 561, 561, 565, 202, 202,
- 562, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 562, 563, 566, 566, 202, 202, 567, 568,
- 569, 570, 571, 572, 573, 574, 575, 576,
- 577, 578, 202, 202, 202, 202, 202, 202,
- 202, 579, 580, 580, 580, 580, 580, 580,
-
- 202, 581, 582, 582, 202, 583, 583, 583,
- 583, 583, 583, 583, 583, 202, 202, 583,
- 583, 202, 202, 583, 583, 583, 583, 583,
- 583, 583, 583, 583, 583, 583, 583, 583,
-
- 583, 583, 583, 583, 583, 583, 583, 583,
- 583, 202, 583, 583, 583, 583, 583, 583,
- 583, 202, 583, 583, 202, 584, 583, 583,
- 583, 583, 202, 202, 585, 583, 586, 581,
-
- 582, 581, 581, 581, 587, 202, 202, 582,
- 588, 202, 202, 588, 588, 589, 202, 202,
- 202, 202, 202, 202, 202, 590, 591, 586,
- 202, 202, 202, 202, 592, 592, 202, 583,
-
- 583, 583, 587, 587, 202, 202, 593, 594,
- 595, 596, 597, 598, 599, 600, 601, 602,
- 603, 584, 604, 604, 604, 604, 604, 604,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 605, 606, 202, 606, 606, 606,
- 606, 606, 606, 202, 202, 202, 606, 606,
- 606, 202, 606, 606, 607, 606, 202, 202,
- 202, 606, 606, 202, 606, 202, 606, 606,
-
- 202, 202, 202, 606, 606, 202, 202, 202,
- 606, 606, 606, 202, 202, 202, 606, 606,
- 606, 606, 606, 606, 606, 606, 608, 606,
- 606, 606, 202, 202, 202, 202, 609, 610,
-
- 605, 610, 610, 202, 202, 202, 610, 610,
- 610, 202, 611, 611, 611, 612, 202, 202,
- 613, 202, 202, 202, 202, 202, 202, 609,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 614, 615,
- 616, 617, 618, 619, 620, 621, 622, 623,
- 624, 624, 624, 625, 625, 625, 625, 625,
- 625, 626, 625, 202, 202, 202, 202, 202,
-
- 627, 628, 628, 628, 629, 630, 630, 630,
- 630, 630, 630, 630, 630, 202, 630, 630,
- 630, 202, 630, 630, 630, 630, 630, 630,
- 630, 630, 630, 630, 630, 630, 630, 630,
-
- 630, 630, 630, 630, 630, 630, 630, 630,
- 630, 202, 630, 630, 630, 630, 630, 630,
- 630, 630, 630, 630, 631, 630, 630, 630,
- 630, 630, 202, 202, 202, 632, 633, 633,
-
- 633, 628, 628, 628, 628, 202, 633, 633,
- 634, 202, 633, 633, 633, 635, 202, 202,
- 202, 202, 202, 202, 202, 636, 637, 202,
- 632, 632, 638, 202, 202, 202, 202, 202,
-
- 630, 630, 639, 639, 202, 202, 640, 641,
- 642, 643, 644, 645, 646, 647, 648, 649,
- 202, 202, 202, 202, 202, 202, 202, 650,
- 651, 651, 651, 651, 651, 651, 651, 652,
-
- 653, 654, 655, 655, 656, 657, 657, 657,
- 657, 657, 657, 657, 657, 202, 657, 657,
- 657, 202, 657, 657, 657, 657, 657, 657,
- 657, 657, 657, 657, 657, 657, 657, 657,
-
- 657, 657, 657, 657, 657, 657, 657, 657,
- 657, 202, 657, 657, 657, 657, 657, 657,
- 657, 657, 657, 657, 202, 657, 657, 657,
- 657, 657, 202, 202, 658, 659, 655, 660,
-
- 661, 655, 662, 655, 655, 202, 660, 661,
- 661, 202, 661, 661, 663, 664, 202, 202,
- 202, 202, 202, 202, 202, 662, 662, 202,
- 202, 202, 202, 202, 202, 202, 657, 202,
-
- 657, 657, 665, 665, 202, 202, 666, 667,
- 668, 669, 670, 671, 672, 673, 674, 675,
- 202, 676, 676, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 677, 678, 679, 679, 680, 681, 681, 681,
- 681, 681, 681, 681, 681, 202, 681, 681,
- 681, 202, 681, 681, 681, 681, 681, 681,
- 681, 681, 681, 681, 681, 681, 681, 681,
-
- 681, 681, 681, 681, 681, 681, 681, 681,
- 681, 682, 681, 681, 681, 681, 681, 681,
- 681, 681, 681, 681, 681, 681, 681, 681,
- 681, 681, 682, 683, 683, 684, 685, 679,
-
- 679, 686, 686, 686, 687, 202, 679, 679,
- 679, 202, 688, 688, 688, 689, 690, 691,
- 202, 202, 202, 202, 692, 692, 692, 685,
- 693, 693, 693, 693, 693, 693, 693, 694,
-
- 681, 681, 687, 687, 202, 202, 695, 696,
- 697, 698, 699, 700, 701, 702, 703, 704,
- 705, 705, 705, 705, 705, 705, 693, 693,
- 693, 706, 684, 684, 684, 684, 684, 684,
-
- 202, 707, 708, 708, 202, 709, 709, 709,
- 709, 709, 709, 709, 709, 709, 709, 709,
- 709, 709, 709, 709, 709, 709, 709, 202,
- 202, 202, 709, 709, 709, 709, 709, 709,
-
- 709, 709, 709, 709, 709, 709, 709, 709,
- 709, 709, 709, 709, 709, 709, 709, 709,
- 709, 709, 202, 709, 709, 709, 709, 709,
- 709, 709, 709, 709, 202, 709, 202, 202,
-
- 709, 709, 709, 709, 709, 709, 709, 202,
- 202, 202, 710, 202, 202, 202, 202, 711,
- 708, 708, 712, 712, 712, 202, 712, 202,
- 708, 708, 713, 708, 713, 713, 713, 711,
-
- 202, 202, 202, 202, 202, 202, 714, 715,
- 716, 717, 718, 719, 720, 721, 722, 723,
- 202, 202, 708, 708, 724, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 725, 725, 725, 725, 725, 725, 725,
- 725, 725, 725, 725, 725, 725, 725, 725,
- 725, 725, 725, 725, 725, 725, 725, 725,
- 725, 725, 725, 725, 725, 725, 725, 725,
-
- 725, 725, 725, 725, 725, 725, 725, 725,
- 725, 725, 725, 725, 725, 725, 725, 725,
- 725, 726, 725, 727, 726, 726, 726, 726,
- 728, 728, 729, 202, 202, 202, 202, 12,
-
- 725, 725, 725, 725, 725, 725, 730, 726,
- 731, 731, 731, 731, 726, 726, 726, 732,
- 733, 734, 735, 736, 737, 738, 739, 740,
- 741, 742, 743, 743, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 744, 744, 202, 744, 202, 745, 744,
- 744, 745, 744, 202, 745, 744, 745, 745,
- 745, 745, 745, 745, 744, 744, 744, 744,
- 745, 744, 744, 744, 744, 744, 744, 744,
-
- 745, 744, 744, 744, 202, 744, 202, 744,
- 745, 745, 744, 744, 745, 744, 744, 744,
- 744, 746, 744, 747, 746, 746, 746, 746,
- 748, 748, 749, 746, 746, 744, 202, 202,
-
- 744, 744, 744, 744, 744, 202, 750, 202,
- 751, 751, 751, 751, 746, 746, 202, 202,
- 752, 753, 754, 755, 756, 757, 758, 759,
- 760, 761, 202, 202, 762, 762, 763, 763,
-
- 764, 765, 765, 765, 766, 767, 766, 766,
- 768, 766, 766, 769, 770, 771, 771, 771,
- 771, 771, 768, 772, 771, 772, 772, 772,
- 773, 773, 772, 772, 772, 772, 772, 772,
-
- 774, 775, 776, 777, 778, 779, 780, 781,
- 782, 783, 784, 784, 784, 784, 784, 784,
- 784, 784, 784, 784, 785, 773, 772, 773,
- 772, 786, 787, 788, 787, 788, 789, 789,
-
- 764, 764, 764, 790, 764, 764, 764, 764,
- 202, 764, 764, 764, 764, 790, 764, 764,
- 764, 764, 790, 764, 764, 764, 764, 790,
- 764, 764, 764, 764, 790, 764, 764, 764,
-
- 764, 764, 764, 764, 764, 764, 764, 764,
- 764, 790, 791, 792, 792, 202, 202, 202,
- 202, 793, 794, 795, 796, 795, 795, 797,
- 795, 797, 794, 794, 794, 794, 798, 799,
-
- 794, 795, 800, 800, 801, 769, 800, 800,
- 764, 764, 764, 764, 802, 803, 803, 803,
- 798, 798, 798, 795, 798, 798, 804, 798,
- 202, 798, 798, 798, 798, 795, 798, 798,
-
- 798, 798, 795, 798, 798, 798, 798, 795,
- 798, 798, 798, 798, 795, 798, 804, 804,
- 804, 798, 798, 798, 798, 798, 798, 798,
- 804, 795, 804, 804, 804, 202, 805, 805,
-
- 806, 806, 806, 806, 806, 806, 807, 806,
- 806, 806, 806, 806, 806, 202, 808, 806,
- 809, 809, 810, 811, 812, 813, 813, 813,
- 813, 814, 814, 202, 202, 202, 202, 202,
-
- 815, 815, 815, 815, 815, 815, 815, 815,
- 815, 815, 815, 815, 815, 815, 815, 815,
- 815, 815, 815, 815, 815, 815, 815, 815,
- 815, 815, 815, 815, 815, 815, 815, 815,
-
- 815, 815, 816, 815, 815, 815, 817, 815,
- 816, 815, 815, 818, 819, 820, 821, 820,
- 820, 822, 820, 823, 823, 823, 820, 824,
- 819, 825, 826, 827, 827, 823, 823, 816,
-
- 828, 829, 830, 831, 832, 833, 834, 835,
- 836, 837, 838, 838, 839, 839, 839, 839,
- 815, 815, 815, 815, 815, 815, 822, 822,
- 820, 820, 816, 816, 816, 816, 823, 823,
-
- 823, 816, 818, 818, 818, 816, 816, 818,
- 818, 818, 818, 818, 818, 818, 816, 816,
- 816, 823, 823, 823, 823, 816, 816, 816,
- 816, 816, 816, 816, 816, 816, 816, 816,
-
- 816, 816, 823, 818, 827, 823, 823, 818,
- 818, 818, 818, 818, 818, 840, 816, 818,
- 841, 842, 843, 844, 845, 846, 847, 848,
- 849, 850, 851, 851, 851, 852, 853, 853,
-
- 854, 854, 854, 854, 854, 854, 854, 854,
- 854, 854, 854, 854, 854, 854, 854, 854,
- 854, 854, 854, 854, 854, 854, 854, 854,
- 854, 854, 854, 854, 854, 854, 854, 854,
-
- 854, 854, 854, 854, 854, 854, 202, 855,
- 202, 202, 202, 202, 202, 855, 202, 202,
- 856, 856, 856, 856, 856, 856, 856, 856,
+ 450, 450, 450, 450, 450, 450, 450, 450,
+ 450, 451, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+
+ 452, 453, 454, 455, 456, 457, 458, 459,
+ 460, 461, 462, 462, 462, 462, 462, 462,
+ 462, 462, 462, 462, 462, 462, 462, 462,
+ 462, 462, 462, 462, 462, 462, 462, 462,
+
+ 462, 462, 462, 462, 462, 462, 462, 462,
+ 462, 462, 462, 463, 463, 463, 463, 463,
+ 463, 463, 464, 463, 465, 465, 466, 467,
+ 468, 469, 470, 323, 323, 471, 472, 472,
+
+ 473, 473, 473, 473, 473, 473, 473, 473,
+ 473, 473, 473, 473, 473, 473, 473, 473,
+ 473, 473, 473, 473, 473, 473, 474, 474,
+ 474, 474, 475, 474, 474, 474, 474, 474,
+
+ 474, 474, 474, 474, 475, 474, 474, 474,
+ 475, 474, 474, 474, 474, 474, 323, 323,
+ 476, 476, 476, 476, 476, 476, 476, 477,
+ 476, 477, 476, 476, 476, 477, 477, 323,
+
+ 478, 479, 479, 479, 479, 479, 478, 478,
+ 479, 478, 479, 479, 479, 479, 479, 479,
+ 479, 479, 479, 479, 478, 479, 478, 478,
+ 478, 480, 480, 480, 323, 323, 481, 323,
+
+ 482, 483, 482, 482, 482, 482, 483, 484,
+ 482, 484, 484, 323, 323, 323, 323, 323,
+ 485, 485, 485, 485, 485, 485, 485, 485,
+ 485, 485, 485, 485, 485, 485, 485, 485,
+
+ 485, 485, 485, 486, 486, 486, 487, 488,
+ 489, 487, 487, 487, 487, 487, 485, 323,
+ 490, 490, 323, 323, 323, 323, 323, 323,
+ 491, 492, 492, 492, 491, 491, 491, 491,
+
+ 493, 494, 493, 493, 493, 493, 493, 493,
+ 493, 493, 495, 495, 495, 496, 497, 494,
+ 494, 497, 497, 498, 498, 487, 499, 499,
+ 499, 500, 499, 499, 499, 499, 501, 501,
+
+ 501, 501, 501, 501, 501, 501, 501, 501,
+ 487, 502, 491, 491, 491, 491, 491, 492,
+ 492, 492, 492, 503, 504, 504, 504, 504,
+ 504, 504, 504, 504, 504, 504, 504, 504,
+
+ 504, 504, 505, 506, 507, 507, 508, 507,
+ 507, 508, 507, 507, 507, 508, 508, 508,
+ 509, 510, 511, 507, 507, 507, 508, 507,
+ 507, 508, 508, 507, 507, 507, 507, 512,
+
+ 513, 514, 514, 515, 516, 517, 517, 517,
+ 517, 517, 517, 517, 517, 517, 517, 517,
+ 517, 517, 517, 517, 517, 517, 517, 517,
+ 517, 517, 517, 517, 517, 517, 517, 517,
+
+ 517, 517, 517, 517, 517, 517, 517, 517,
+ 517, 518, 517, 517, 517, 517, 517, 517,
+ 517, 518, 517, 517, 518, 517, 517, 517,
+ 517, 517, 519, 520, 521, 517, 515, 515,
+
+ 515, 514, 514, 514, 514, 514, 514, 514,
+ 514, 515, 515, 515, 515, 522, 523, 520,
+ 517, 288, 524, 288, 288, 513, 519, 519,
+ 525, 525, 525, 525, 525, 525, 525, 525,
+
+ 517, 517, 514, 514, 526, 526, 527, 528,
+ 529, 530, 531, 532, 533, 534, 535, 536,
+ 537, 538, 539, 540, 540, 540, 540, 540,
+ 541, 542, 542, 543, 543, 544, 543, 543,
+
+ 545, 546, 547, 547, 221, 548, 548, 548,
+ 548, 548, 548, 548, 548, 221, 221, 548,
+ 548, 221, 221, 548, 548, 548, 548, 548,
+ 548, 548, 548, 548, 548, 548, 548, 548,
+
+ 548, 548, 548, 548, 548, 548, 548, 548,
+ 548, 221, 548, 548, 548, 548, 548, 548,
+ 548, 221, 548, 221, 221, 221, 548, 548,
+ 548, 548, 221, 221, 549, 550, 551, 547,
+
+ 547, 546, 546, 546, 546, 221, 221, 547,
+ 547, 221, 221, 552, 552, 553, 554, 221,
+ 221, 221, 221, 221, 221, 221, 221, 551,
+ 221, 221, 221, 221, 555, 555, 221, 555,
+
+ 548, 548, 546, 546, 221, 221, 556, 557,
+ 558, 559, 560, 561, 562, 563, 564, 565,
+ 548, 548, 566, 566, 567, 567, 567, 567,
+ 567, 568, 569, 570, 571, 572, 573, 221,
+
+ 221, 574, 575, 576, 221, 577, 577, 577,
+ 577, 577, 577, 221, 221, 221, 221, 577,
+ 577, 221, 221, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577,
+
+ 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 221, 577, 577, 577, 577, 577, 577,
+ 577, 221, 577, 578, 221, 577, 578, 221,
+ 577, 577, 221, 221, 579, 221, 580, 580,
+
+ 580, 575, 575, 221, 221, 221, 221, 575,
+ 575, 221, 221, 575, 575, 581, 221, 221,
+ 221, 582, 221, 221, 221, 221, 221, 221,
+ 221, 578, 578, 578, 577, 221, 578, 221,
+
+ 221, 221, 221, 221, 221, 221, 583, 584,
+ 585, 586, 587, 588, 589, 590, 591, 592,
+ 575, 575, 577, 577, 577, 582, 593, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 594, 594, 595, 221, 596, 596, 596,
+ 596, 596, 596, 596, 597, 596, 221, 596,
+ 596, 596, 221, 596, 596, 596, 596, 596,
+ 596, 596, 596, 596, 596, 596, 596, 596,
+
+ 596, 596, 596, 596, 596, 596, 596, 596,
+ 596, 221, 596, 596, 596, 596, 596, 596,
+ 596, 221, 596, 596, 221, 596, 596, 596,
+ 596, 596, 221, 221, 598, 596, 595, 595,
+
+ 595, 594, 594, 594, 594, 594, 221, 594,
+ 594, 595, 221, 595, 595, 599, 221, 221,
+ 596, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 596, 597, 600, 600, 221, 221, 601, 602,
+ 603, 604, 605, 606, 607, 608, 609, 610,
+ 611, 612, 221, 221, 221, 221, 221, 221,
+ 221, 613, 614, 614, 614, 614, 614, 614,
+
+ 221, 615, 616, 616, 221, 617, 617, 617,
+ 617, 617, 617, 617, 617, 221, 221, 617,
+ 617, 221, 221, 617, 617, 617, 617, 617,
+ 617, 617, 617, 617, 617, 617, 617, 617,
+
+ 617, 617, 617, 617, 617, 617, 617, 617,
+ 617, 221, 617, 617, 617, 617, 617, 617,
+ 617, 221, 617, 617, 221, 618, 617, 617,
+ 617, 617, 221, 221, 619, 617, 620, 615,
+
+ 616, 615, 615, 615, 621, 221, 221, 616,
+ 622, 221, 221, 622, 622, 623, 221, 221,
+ 221, 221, 221, 221, 221, 624, 625, 620,
+ 221, 221, 221, 221, 626, 626, 221, 617,
+
+ 617, 617, 621, 621, 221, 221, 627, 628,
+ 629, 630, 631, 632, 633, 634, 635, 636,
+ 637, 618, 638, 638, 638, 638, 638, 638,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 639, 640, 221, 640, 640, 640,
+ 640, 640, 640, 221, 221, 221, 640, 640,
+ 640, 221, 640, 640, 641, 640, 221, 221,
+ 221, 640, 640, 221, 640, 221, 640, 640,
+
+ 221, 221, 221, 640, 640, 221, 221, 221,
+ 640, 640, 640, 221, 221, 221, 640, 640,
+ 640, 640, 640, 640, 640, 640, 642, 640,
+ 640, 640, 221, 221, 221, 221, 643, 644,
+
+ 639, 644, 644, 221, 221, 221, 644, 644,
+ 644, 221, 645, 645, 645, 646, 221, 221,
+ 647, 221, 221, 221, 221, 221, 221, 643,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 648, 649,
+ 650, 651, 652, 653, 654, 655, 656, 657,
+ 658, 658, 658, 659, 659, 659, 659, 659,
+ 659, 660, 659, 221, 221, 221, 221, 221,
+
+ 661, 662, 662, 662, 663, 664, 664, 664,
+ 664, 664, 664, 664, 664, 221, 664, 664,
+ 664, 221, 664, 664, 664, 664, 664, 664,
+ 664, 664, 664, 664, 664, 664, 664, 664,
+
+ 664, 664, 664, 664, 664, 664, 664, 664,
+ 664, 221, 664, 664, 664, 664, 664, 664,
+ 664, 664, 664, 664, 665, 664, 664, 664,
+ 664, 664, 221, 221, 666, 667, 668, 668,
+
+ 668, 662, 662, 662, 662, 221, 668, 668,
+ 669, 221, 668, 668, 668, 670, 221, 221,
+ 221, 221, 221, 221, 221, 671, 672, 221,
+ 667, 667, 673, 221, 221, 674, 221, 221,
+
+ 664, 664, 675, 675, 221, 221, 676, 677,
+ 678, 679, 680, 681, 682, 683, 684, 685,
+ 221, 221, 221, 221, 221, 221, 221, 686,
+ 687, 687, 687, 687, 687, 687, 687, 688,
+
+ 689, 690, 691, 691, 692, 693, 693, 693,
+ 693, 693, 693, 693, 693, 221, 693, 693,
+ 693, 221, 693, 693, 693, 693, 693, 693,
+ 693, 693, 693, 693, 693, 693, 693, 693,
+
+ 693, 693, 693, 693, 693, 693, 693, 693,
+ 693, 221, 693, 693, 693, 693, 693, 693,
+ 693, 693, 693, 693, 221, 693, 693, 693,
+ 693, 693, 221, 221, 694, 695, 691, 696,
+
+ 697, 691, 698, 691, 691, 221, 696, 697,
+ 697, 221, 697, 697, 699, 700, 221, 221,
+ 221, 221, 221, 221, 221, 698, 698, 221,
+ 221, 221, 221, 221, 221, 701, 693, 221,
+
+ 693, 693, 702, 702, 221, 221, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 712,
+ 221, 713, 713, 714, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 715, 716, 717, 717, 718, 719, 719, 719,
+ 719, 719, 719, 719, 719, 221, 719, 719,
+ 719, 221, 719, 719, 719, 719, 719, 719,
+ 719, 719, 719, 719, 719, 719, 719, 719,
+
+ 719, 719, 719, 719, 719, 719, 719, 719,
+ 719, 720, 719, 719, 719, 719, 719, 719,
+ 719, 719, 719, 719, 719, 719, 719, 719,
+ 719, 719, 720, 721, 721, 722, 723, 717,
+
+ 717, 724, 724, 724, 725, 221, 717, 717,
+ 717, 221, 726, 726, 726, 727, 728, 729,
+ 221, 221, 221, 221, 730, 730, 730, 723,
+ 731, 731, 731, 731, 731, 731, 731, 732,
+
+ 719, 719, 725, 725, 221, 221, 733, 734,
+ 735, 736, 737, 738, 739, 740, 741, 742,
+ 743, 743, 743, 743, 743, 743, 731, 731,
+ 731, 744, 722, 722, 722, 722, 722, 722,
+
+ 221, 745, 746, 746, 221, 747, 747, 747,
+ 747, 747, 747, 747, 747, 747, 747, 747,
+ 747, 747, 747, 747, 747, 747, 747, 221,
+ 221, 221, 747, 747, 747, 747, 747, 747,
+
+ 747, 747, 747, 747, 747, 747, 747, 747,
+ 747, 747, 747, 747, 747, 747, 747, 747,
+ 747, 747, 221, 747, 747, 747, 747, 747,
+ 747, 747, 747, 747, 221, 747, 221, 221,
+
+ 747, 747, 747, 747, 747, 747, 747, 221,
+ 221, 221, 748, 221, 221, 221, 221, 749,
+ 746, 746, 750, 750, 750, 221, 750, 221,
+ 746, 746, 751, 746, 751, 751, 751, 749,
+
+ 221, 221, 221, 221, 221, 221, 752, 753,
+ 754, 755, 756, 757, 758, 759, 760, 761,
+ 221, 221, 746, 746, 762, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 763,
+
+ 763, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 763,
+ 763, 764, 763, 765, 764, 764, 764, 764,
+ 766, 766, 767, 221, 221, 221, 221, 768,
+
+ 763, 763, 763, 763, 763, 763, 769, 764,
+ 770, 770, 770, 770, 764, 764, 764, 771,
+ 772, 773, 774, 775, 776, 777, 778, 779,
+ 780, 781, 782, 782, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 783, 783, 221, 783, 221, 784, 783,
+ 783, 784, 783, 221, 784, 783, 784, 784,
+ 784, 784, 784, 784, 783, 783, 783, 783,
+ 784, 783, 783, 783, 783, 783, 783, 783,
+
+ 784, 783, 783, 783, 221, 783, 221, 783,
+ 784, 784, 783, 783, 784, 783, 783, 783,
+ 783, 785, 783, 786, 785, 785, 785, 785,
+ 787, 787, 788, 785, 785, 783, 221, 221,
+
+ 783, 783, 783, 783, 783, 221, 789, 221,
+ 790, 790, 790, 790, 785, 785, 791, 221,
+ 792, 793, 794, 795, 796, 797, 798, 799,
+ 800, 801, 221, 221, 802, 802, 803, 803,
+
+ 804, 805, 805, 805, 806, 807, 806, 806,
+ 808, 806, 806, 809, 810, 811, 811, 811,
+ 811, 811, 808, 812, 811, 812, 812, 812,
+ 813, 813, 812, 812, 812, 812, 812, 812,
+
+ 814, 815, 816, 817, 818, 819, 820, 821,
+ 822, 823, 824, 824, 824, 824, 824, 824,
+ 824, 824, 824, 824, 825, 813, 812, 813,
+ 812, 826, 827, 828, 827, 828, 829, 829,
+
+ 804, 804, 804, 830, 804, 804, 804, 804,
+ 221, 804, 804, 804, 804, 830, 804, 804,
+ 804, 804, 830, 804, 804, 804, 804, 830,
+ 804, 804, 804, 804, 830, 804, 804, 804,
+
+ 804, 804, 804, 804, 804, 804, 804, 804,
+ 804, 830, 831, 832, 832, 221, 221, 221,
+ 221, 833, 834, 835, 836, 835, 835, 837,
+ 835, 837, 834, 834, 834, 834, 838, 839,
+
+ 834, 835, 840, 840, 841, 809, 840, 840,
+ 804, 804, 804, 804, 842, 843, 843, 843,
+ 838, 838, 838, 835, 838, 838, 844, 838,
+ 221, 838, 838, 838, 838, 835, 838, 838,
+
+ 838, 838, 835, 838, 838, 838, 838, 835,
+ 838, 838, 838, 838, 835, 838, 844, 844,
+ 844, 838, 838, 838, 838, 838, 838, 838,
+ 844, 835, 844, 844, 844, 221, 845, 845,
+
+ 846, 846, 846, 846, 846, 846, 847, 846,
+ 846, 846, 846, 846, 846, 221, 848, 846,
+ 849, 849, 850, 851, 852, 853, 853, 853,
+ 853, 854, 854, 221, 221, 221, 221, 221,
+
+ 855, 855, 855, 855, 855, 855, 855, 855,
+ 855, 855, 855, 855, 855, 855, 855, 855,
+ 855, 855, 855, 855, 855, 855, 855, 855,
+ 855, 855, 855, 855, 855, 855, 855, 855,
+
+ 855, 855, 856, 855, 855, 855, 857, 855,
+ 856, 855, 855, 858, 859, 860, 861, 860,
+ 860, 862, 860, 863, 863, 863, 860, 864,
+ 859, 865, 866, 867, 867, 863, 863, 856,
+
+ 868, 869, 870, 871, 872, 873, 874, 875,
+ 876, 877, 878, 878, 879, 879, 879, 879,
+ 855, 855, 855, 855, 855, 855, 862, 862,
+ 860, 860, 856, 856, 856, 856, 863, 863,
+
+ 863, 856, 858, 858, 858, 856, 856, 858,
+ 858, 858, 858, 858, 858, 858, 856, 856,
+ 856, 863, 863, 863, 863, 856, 856, 856,
856, 856, 856, 856, 856, 856, 856, 856,
- 856, 856, 856, 856, 856, 856, 856, 856,
- 856, 856, 856, 856, 856, 856, 856, 856,
- 856, 856, 856, 856, 856, 856, 856, 857,
- 857, 858, 858, 859, 860, 861, 861, 861,
-
- 862, 862, 862, 862, 862, 862, 862, 862,
- 862, 862, 862, 862, 862, 862, 862, 862,
- 862, 862, 862, 862, 862, 862, 862, 862,
- 862, 862, 862, 862, 862, 862, 862, 862,
-
- 862, 862, 862, 862, 862, 862, 862, 862,
- 862, 862, 862, 862, 862, 862, 862, 862,
- 862, 862, 862, 862, 862, 862, 862, 862,
- 862, 862, 863, 863, 863, 863, 863, 862,
-
- 864, 865, 865, 865, 865, 865, 865, 865,
- 865, 865, 865, 865, 865, 865, 865, 865,
- 865, 865, 865, 865, 865, 865, 864, 864,
- 864, 864, 864, 864, 864, 864, 864, 864,
-
- 864, 864, 864, 864, 864, 864, 864, 864,
- 864, 864, 864, 864, 864, 864, 864, 864,
- 864, 864, 864, 864, 864, 864, 864, 864,
- 864, 864, 864, 864, 864, 864, 864, 864,
-
- 864, 864, 864, 866, 866, 866, 866, 866,
- 867, 867, 867, 867, 867, 867, 867, 867,
- 867, 867, 867, 867, 867, 867, 867, 867,
- 867, 867, 867, 867, 867, 867, 867, 867,
-
- 867, 867, 867, 868, 868, 868, 868, 868,
- 868, 868, 868, 868, 868, 868, 868, 868,
- 868, 868, 868, 868, 868, 868, 868, 868,
- 868, 868, 868, 868, 868, 868, 868, 868,
-
- 868, 868, 868, 868, 868, 868, 868, 868,
- 868, 868, 868, 868, 868, 868, 868, 868,
- 868, 868, 868, 868, 868, 868, 868, 868,
- 868, 868, 869, 869, 869, 869, 869, 869,
-
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
-
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
-
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 202, 870, 870, 870, 870, 202, 202,
- 870, 870, 870, 870, 870, 870, 870, 202,
- 870, 202, 870, 870, 870, 870, 202, 202,
-
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 202, 870, 870, 870, 870, 202, 202,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
-
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 202, 870, 870, 870, 870, 202, 202,
- 870, 870, 870, 870, 870, 870, 870, 202,
-
- 870, 202, 870, 870, 870, 870, 202, 202,
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 870, 870, 870, 870, 870, 870, 202,
- 870, 870, 870, 870, 870, 870, 870, 870,
-
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
-
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 202, 870, 870, 870, 870, 202, 202,
- 870, 870, 870, 870, 870, 870, 870, 871,
-
- 870, 870, 870, 870, 870, 870, 870, 871,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 870, 870, 870, 870, 870,
- 870, 870, 870, 202, 202, 872, 872, 873,
-
- 874, 875, 876, 877, 877, 877, 877, 876,
- 876, 878, 879, 880, 881, 882, 883, 884,
- 885, 886, 887, 887, 887, 887, 887, 887,
- 887, 887, 887, 887, 887, 202, 202, 202,
-
- 871, 871, 871, 871, 871, 871, 871, 871,
- 871, 871, 871, 871, 871, 871, 871, 871,
- 888, 888, 888, 888, 888, 888, 888, 888,
- 888, 888, 202, 202, 202, 202, 202, 202,
-
- 889, 890, 891, 892, 893, 894, 895, 896,
- 897, 898, 899, 900, 901, 902, 903, 904,
- 905, 906, 907, 908, 909, 910, 911, 912,
- 913, 914, 915, 916, 917, 918, 919, 920,
-
- 921, 922, 923, 924, 925, 926, 927, 928,
- 929, 930, 931, 932, 933, 934, 935, 936,
- 937, 938, 939, 940, 941, 942, 943, 944,
- 945, 946, 947, 948, 949, 950, 951, 952,
-
- 953, 954, 955, 956, 957, 958, 959, 960,
- 961, 962, 963, 964, 965, 966, 967, 968,
- 969, 969, 969, 969, 969, 970, 202, 202,
- 971, 971, 971, 971, 971, 971, 202, 202,
-
- 972, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 973, 973, 973,
-
- 973, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 973, 973, 973,
-
- 973, 973, 973, 973, 973, 973, 973, 973,
- 973, 973, 973, 973, 973, 974, 975, 973,
- 973, 973, 973, 973, 973, 973, 973, 976,
- 976, 976, 976, 976, 976, 976, 976, 976,
-
- 977, 978, 978, 978, 978, 978, 978, 978,
- 978, 978, 978, 978, 978, 978, 978, 978,
- 978, 978, 978, 978, 978, 978, 978, 978,
- 978, 978, 978, 979, 980, 202, 202, 202,
-
- 981, 981, 981, 981, 981, 981, 981, 981,
- 981, 981, 981, 981, 981, 981, 981, 981,
- 981, 981, 981, 981, 981, 981, 981, 981,
- 981, 981, 981, 981, 981, 981, 981, 981,
-
- 981, 981, 981, 981, 981, 981, 981, 981,
- 981, 981, 981, 982, 982, 982, 983, 983,
- 983, 984, 984, 984, 984, 984, 984, 984,
- 984, 202, 202, 202, 202, 202, 202, 202,
-
- 985, 985, 985, 985, 985, 985, 985, 985,
- 985, 985, 985, 985, 985, 202, 985, 985,
- 985, 985, 986, 986, 987, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 988, 988, 988, 988, 988, 988, 988, 988,
- 988, 988, 988, 988, 988, 988, 988, 988,
- 988, 988, 989, 989, 990, 991, 991, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 992, 992, 992, 992, 992, 992, 992, 992,
- 992, 992, 992, 992, 992, 992, 992, 992,
- 992, 992, 993, 993, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 994, 994, 994, 994, 994, 994, 994, 994,
- 994, 994, 994, 994, 994, 202, 994, 994,
- 994, 202, 995, 995, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 996, 996, 996, 996, 996, 996, 996, 996,
- 996, 996, 996, 996, 996, 996, 996, 996,
- 996, 996, 996, 996, 996, 996, 996, 996,
- 996, 996, 996, 996, 996, 996, 996, 996,
-
- 996, 996, 996, 996, 996, 996, 996, 996,
- 996, 996, 996, 996, 996, 996, 996, 996,
- 996, 996, 996, 996, 997, 997, 998, 997,
- 997, 997, 997, 997, 997, 997, 998, 998,
-
- 998, 998, 998, 998, 998, 998, 997, 998,
- 998, 997, 997, 997, 997, 997, 997, 997,
- 997, 997, 999, 997, 1000, 1000, 1001, 1002,
- 1000, 1003, 1000, 1004, 996, 1005, 202, 202,
-
- 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013,
- 1014, 1015, 202, 202, 202, 202, 202, 202,
- 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016,
- 1016, 1016, 202, 202, 202, 202, 202, 202,
-
- 1017, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
- 1024, 1025, 1026, 1027, 1027, 1027, 1028, 202,
- 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036,
- 1037, 1038, 202, 202, 202, 202, 202, 202,
-
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
-
- 1039, 1039, 1039, 1040, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
-
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1041, 202, 202, 202, 202, 202, 202, 202,
-
- 1042, 1042, 1042, 1042, 1042, 1027, 1027, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
-
- 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039,
- 1039, 1043, 1044, 202, 202, 202, 202, 202,
- 976, 976, 976, 976, 976, 976, 976, 976,
- 976, 976, 976, 976, 976, 976, 976, 976,
-
- 976, 976, 976, 976, 976, 976, 976, 976,
- 976, 976, 976, 976, 976, 976, 976, 976,
- 976, 976, 976, 976, 976, 976, 976, 976,
- 976, 976, 976, 976, 976, 976, 976, 976,
-
- 976, 976, 976, 976, 976, 976, 976, 976,
- 976, 976, 976, 976, 976, 976, 976, 976,
- 976, 976, 976, 976, 976, 976, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045,
- 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045,
- 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045,
- 1045, 1045, 1045, 1045, 1045, 1046, 1046, 202,
-
- 1047, 1047, 1047, 1048, 1048, 1048, 1048, 1047,
- 1047, 1048, 1048, 1048, 202, 202, 202, 202,
- 1048, 1048, 1047, 1048, 1048, 1048, 1048, 1048,
- 1048, 1049, 1050, 1051, 202, 202, 202, 202,
-
- 1052, 202, 202, 202, 1053, 1053, 1054, 1055,
- 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
- 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064,
- 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064,
-
- 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064,
- 1064, 1064, 1064, 1064, 1064, 1064, 202, 202,
- 1064, 1064, 1064, 1064, 1064, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
-
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
- 1065, 1065, 1066, 1066, 202, 202, 202, 202,
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
-
- 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065,
- 1065, 1065, 202, 202, 202, 202, 202, 202,
- 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074,
- 1075, 1076, 1077, 202, 202, 202, 1078, 1078,
-
- 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
- 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
- 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
- 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-
- 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080,
- 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080,
- 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1081,
- 1082, 1083, 1083, 1084, 202, 202, 1085, 1085,
+ 856, 856, 863, 858, 867, 863, 863, 858,
+ 858, 858, 858, 858, 858, 880, 856, 858,
+ 881, 882, 883, 884, 885, 886, 887, 888,
+ 889, 890, 891, 891, 891, 892, 893, 893,
+
+ 894, 894, 894, 894, 894, 894, 894, 894,
+ 894, 894, 894, 894, 894, 894, 894, 894,
+ 894, 894, 894, 894, 894, 894, 894, 894,
+ 894, 894, 894, 894, 894, 894, 894, 894,
+
+ 894, 894, 894, 894, 894, 894, 221, 895,
+ 221, 221, 221, 221, 221, 895, 221, 221,
+ 896, 896, 896, 896, 896, 896, 896, 896,
+ 896, 896, 896, 896, 896, 896, 896, 896,
+
+ 896, 896, 896, 896, 896, 896, 896, 896,
+ 896, 896, 896, 896, 896, 896, 896, 896,
+ 896, 896, 896, 896, 896, 896, 896, 897,
+ 897, 898, 898, 899, 900, 901, 901, 901,
+
+ 902, 902, 902, 902, 902, 902, 902, 902,
+ 902, 902, 902, 902, 902, 902, 902, 902,
+ 902, 902, 902, 902, 902, 902, 902, 902,
+ 902, 902, 902, 902, 902, 902, 902, 902,
+
+ 902, 902, 902, 902, 902, 902, 902, 902,
+ 902, 902, 902, 902, 902, 902, 902, 902,
+ 902, 902, 902, 902, 902, 902, 902, 902,
+ 902, 902, 903, 903, 903, 903, 903, 904,
+
+ 905, 906, 906, 906, 906, 906, 906, 906,
+ 906, 906, 906, 906, 906, 906, 906, 906,
+ 906, 906, 906, 906, 906, 906, 907, 907,
+ 907, 907, 907, 907, 907, 907, 907, 907,
+
+ 907, 907, 907, 907, 907, 907, 907, 907,
+ 907, 907, 907, 907, 907, 907, 907, 907,
+ 907, 907, 907, 907, 907, 907, 907, 907,
+ 907, 907, 907, 907, 907, 907, 907, 907,
+
+ 907, 907, 907, 908, 908, 908, 908, 908,
+ 909, 909, 909, 909, 909, 909, 909, 909,
+ 909, 909, 909, 909, 909, 909, 909, 909,
+ 909, 909, 909, 909, 909, 909, 909, 909,
+
+ 909, 909, 909, 910, 910, 910, 910, 910,
+ 910, 910, 910, 910, 910, 910, 910, 910,
+ 910, 910, 910, 910, 910, 910, 910, 910,
+ 910, 910, 910, 910, 910, 910, 910, 910,
+
+ 910, 910, 910, 910, 910, 910, 910, 910,
+ 910, 910, 910, 910, 910, 910, 910, 910,
+ 910, 910, 910, 910, 910, 910, 910, 910,
+ 910, 910, 911, 911, 911, 911, 911, 911,
+
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 221, 912, 912, 912, 912, 221, 221,
+ 912, 912, 912, 912, 912, 912, 912, 221,
+ 912, 221, 912, 912, 912, 912, 221, 221,
+
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 221, 912, 912, 912, 912, 221, 221,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 221, 912, 912, 912, 912, 221, 221,
+ 912, 912, 912, 912, 912, 912, 912, 221,
+
+ 912, 221, 912, 912, 912, 912, 221, 221,
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 912, 912, 912, 912, 912, 912, 221,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 221, 912, 912, 912, 912, 221, 221,
+ 912, 912, 912, 912, 912, 912, 912, 913,
+
+ 912, 912, 912, 912, 912, 912, 912, 913,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 221, 221, 914, 914, 915,
+
+ 916, 917, 918, 919, 919, 919, 919, 918,
+ 918, 920, 921, 922, 923, 924, 925, 926,
+ 927, 928, 929, 929, 929, 929, 929, 929,
+ 929, 929, 929, 929, 929, 221, 221, 221,
+
+ 913, 913, 913, 913, 913, 913, 913, 913,
+ 913, 913, 913, 913, 913, 913, 913, 913,
+ 930, 930, 930, 930, 930, 930, 930, 930,
+ 930, 930, 221, 221, 221, 221, 221, 221,
+
+ 931, 932, 933, 934, 935, 936, 937, 938,
+ 939, 940, 941, 942, 943, 944, 945, 946,
+ 947, 948, 949, 950, 951, 952, 953, 954,
+ 955, 956, 957, 958, 959, 960, 961, 962,
+
+ 963, 964, 965, 966, 967, 968, 969, 970,
+ 971, 972, 973, 974, 975, 976, 977, 978,
+ 979, 980, 981, 982, 983, 984, 985, 986,
+ 987, 988, 989, 990, 991, 992, 993, 994,
+
+ 995, 996, 997, 998, 999, 1000, 1001, 1002,
+ 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010,
+ 1011, 1011, 1011, 1011, 1011, 1012, 221, 221,
+ 1013, 1013, 1013, 1013, 1013, 1013, 221, 221,
+
+ 1014, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1016, 1017, 1015,
+ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+
+ 1019, 1020, 1020, 1020, 1020, 1020, 1020, 1020,
+ 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020,
+ 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020,
+ 1020, 1020, 1020, 1021, 1022, 221, 221, 221,
+
+ 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
+ 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
+ 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
+ 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
+
+ 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
+ 1023, 1023, 1023, 1024, 1024, 1024, 1025, 1025,
+ 1025, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
+ 1026, 221, 221, 221, 221, 221, 221, 221,
+
+ 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
+ 1027, 1027, 1027, 1027, 1027, 1028, 1027, 1027,
+ 1027, 1027, 1029, 1029, 1030, 1031, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 1028,
+
+ 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032,
+ 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032,
+ 1032, 1032, 1033, 1033, 1034, 1035, 1035, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ 1036, 1036, 1037, 1037, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038,
+ 1038, 1038, 1038, 1038, 1038, 221, 1038, 1038,
+ 1038, 221, 1039, 1039, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+
+ 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1040, 1041, 1041, 1042, 1043,
+ 1043, 1043, 1043, 1043, 1043, 1043, 1042, 1042,
+
+ 1042, 1042, 1042, 1042, 1042, 1042, 1043, 1042,
+ 1042, 1043, 1043, 1043, 1043, 1043, 1043, 1043,
+ 1043, 1043, 1044, 1043, 1045, 1045, 1046, 1047,
+ 1048, 1049, 1048, 1050, 1040, 1051, 221, 221,
+
+ 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059,
+ 1060, 1061, 221, 221, 221, 221, 221, 221,
+ 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062,
+ 1062, 1062, 221, 221, 221, 221, 221, 221,
+
+ 1063, 1063, 1064, 1065, 1066, 1067, 1068, 1069,
+ 1070, 1071, 1072, 1073, 1073, 1073, 1074, 1075,
+ 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083,
+ 1084, 1085, 221, 221, 221, 221, 221, 221,
1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1086, 1086, 1086, 1087, 1086, 1086, 1086, 1086,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
- 1086, 1086, 1086, 1086, 1086, 1087, 1088, 1087,
- 1088, 1088, 1088, 1088, 1088, 1088, 1088, 202,
-
- 1089, 1090, 1088, 1090, 1090, 1088, 1088, 1088,
- 1088, 1088, 1088, 1088, 1088, 1087, 1087, 1087,
- 1087, 1087, 1087, 1088, 1088, 1091, 1091, 1091,
- 1091, 1091, 1091, 1091, 1091, 202, 202, 1092,
-
- 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100,
- 1101, 1102, 202, 202, 202, 202, 202, 202,
- 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100,
- 1101, 1102, 202, 202, 202, 202, 202, 202,
-
- 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1104,
- 1105, 1105, 1105, 1105, 1103, 1103, 202, 202,
- 1106, 1106, 1106, 1106, 1106, 1107, 1107, 1107,
- 1107, 1107, 1107, 1106, 1106, 1107, 1108, 1109,
-
- 1109, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1110, 1110, 1110, 1110, 1111, 1112, 1113, 1112,
- 1113, 1112, 1113, 1112, 1113, 1112, 1113, 1112,
- 1112, 1112, 1113, 1112, 1112, 1112, 1112, 1112,
- 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1088, 221, 221, 221, 221, 221, 221, 221,
+
+ 1089, 1089, 1089, 1089, 1089, 1090, 1090, 1086,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+
+ 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+ 1086, 1091, 1092, 221, 221, 221, 221, 221,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1018, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+ 1093, 1093, 1093, 1093, 1093, 1094, 1094, 221,
+
+ 1095, 1095, 1095, 1096, 1096, 1096, 1096, 1095,
+ 1095, 1096, 1096, 1096, 221, 221, 221, 221,
+ 1096, 1096, 1095, 1096, 1096, 1096, 1096, 1096,
+ 1096, 1097, 1098, 1099, 221, 221, 221, 221,
+
+ 1100, 221, 221, 221, 1101, 1101, 1102, 1103,
+ 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112,
1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112,
- 1112, 1112, 1112, 1112, 1114, 1115, 1110, 1110,
- 1110, 1110, 1110, 1116, 1110, 1116, 1111, 1111,
-
- 1116, 1116, 1110, 1116, 1117, 1112, 1112, 1112,
- 1112, 1112, 1112, 1112, 202, 202, 202, 202,
- 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125,
- 1126, 1127, 1128, 1128, 1129, 1130, 1128, 1128,
-
- 1130, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
- 1131, 1131, 1131, 1132, 1133, 1132, 1132, 1132,
- 1132, 1132, 1132, 1132, 1131, 1131, 1131, 1131,
- 1131, 1131, 1131, 1131, 1131, 202, 202, 202,
-
- 1134, 1134, 1135, 1136, 1136, 1136, 1136, 1136,
- 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136,
- 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136,
- 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136,
-
- 1136, 1135, 1134, 1134, 1134, 1134, 1135, 1135,
- 1134, 1134, 1137, 1138, 1139, 1139, 1136, 1136,
- 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147,
- 1148, 1149, 1150, 1150, 1150, 1150, 1150, 1150,
-
- 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151,
- 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151,
- 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151,
- 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151,
-
- 1151, 1151, 1151, 1151, 1151, 1151, 1152, 1153,
- 1154, 1154, 1153, 1153, 1153, 1154, 1153, 1154,
- 1154, 1154, 1155, 1155, 202, 202, 202, 202,
- 202, 202, 202, 202, 1156, 1156, 1156, 1156,
-
- 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157,
- 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157,
- 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157,
- 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157,
-
- 1157, 1157, 1157, 1157, 1158, 1158, 1158, 1158,
- 1158, 1158, 1158, 1158, 1159, 1159, 1159, 1159,
- 1159, 1159, 1159, 1159, 1158, 1158, 1159, 1160,
- 202, 202, 202, 1161, 1161, 1162, 1162, 1162,
-
- 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170,
- 1171, 1172, 202, 202, 202, 1157, 1157, 1157,
- 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180,
- 1181, 1182, 1183, 1183, 1183, 1183, 1183, 1183,
-
- 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183,
- 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183,
- 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183,
- 1184, 1184, 1184, 1184, 1184, 1184, 1185, 1185,
-
- 1186, 1187, 1188, 1189, 1189, 1190, 1191, 1192,
- 1193, 202, 202, 202, 202, 202, 202, 202,
- 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194,
- 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194,
-
- 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194,
- 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194,
- 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194,
- 1194, 1194, 1194, 202, 202, 1194, 1194, 1194,
-
- 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 1196, 1196, 1196, 1197, 1198, 1199, 1199, 1199,
- 1199, 1199, 1196, 1196, 1199, 1199, 1199, 1199,
-
- 1196, 1200, 1198, 1198, 1198, 1198, 1198, 1198,
- 1198, 1201, 1201, 1201, 1201, 1199, 1201, 1201,
- 1201, 1201, 1201, 1202, 1203, 1202, 1202, 1204,
- 1106, 1106, 1205, 202, 202, 202, 202, 202,
-
- 114, 114, 114, 114, 114, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114,
-
- 114, 114, 114, 114, 114, 114, 1206, 1206,
- 1206, 1206, 1206, 1207, 1208, 1208, 1208, 1209,
- 1208, 1208, 1208, 1208, 1208, 1208, 1208, 1208,
- 1208, 1208, 1208, 1209, 1208, 1208, 1208, 1208,
-
- 1208, 1208, 1208, 1208, 1208, 1208, 1208, 1208,
- 1208, 1208, 1208, 1208, 1208, 1208, 1209, 1208,
- 1208, 1208, 1208, 1208, 1208, 1208, 1208, 1208,
- 1208, 1208, 1208, 1208, 1208, 1210, 1210, 1210,
-
- 1210, 1210, 1208, 1208, 1208, 1208, 1210, 1210,
- 1210, 1210, 1210, 114, 115, 115, 115, 115,
- 115, 115, 115, 115, 115, 115, 115, 115,
- 1211, 1212, 115, 115, 115, 1213, 115, 115,
-
- 115, 115, 115, 115, 115, 115, 115, 115,
- 115, 115, 115, 115, 115, 115, 1214, 115,
- 115, 115, 115, 115, 115, 115, 115, 115,
- 115, 115, 115, 1215, 1215, 1215, 1215, 1215,
-
- 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215,
- 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215,
- 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215,
- 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1216,
-
- 191, 191, 190, 191, 1217, 1217, 1217, 1217,
- 1217, 1217, 1218, 1219, 1219, 1220, 1221, 1222,
- 1223, 1219, 1219, 1219, 1219, 1219, 1219, 1219,
- 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219,
-
- 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1106,
- 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106,
- 1106, 1106, 1106, 1106, 1106, 1106, 1224, 1225,
- 1225, 1226, 202, 1227, 1228, 1199, 1217, 1218,
-
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
-
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 1229, 1230,
- 1231, 1232, 1233, 1234, 1235, 1235, 1236, 1235,
-
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 70, 71, 70, 71, 70, 71,
- 70, 71, 1237, 1238, 1237, 1238, 1237, 1238,
-
- 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,
- 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
- 1239, 1239, 1239, 1239, 1239, 1239, 202, 202,
- 1240, 1240, 1240, 1240, 1240, 1240, 202, 202,
-
- 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,
- 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
- 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,
- 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
-
- 1239, 1239, 1239, 1239, 1239, 1239, 202, 202,
- 1240, 1240, 1240, 1240, 1240, 1240, 202, 202,
- 1241, 1239, 1242, 1239, 1243, 1239, 1244, 1239,
- 202, 1240, 202, 1240, 202, 1240, 202, 1240,
-
- 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,
- 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240,
- 1245, 1246, 1247, 1248, 1247, 1248, 1249, 1250,
- 1251, 1252, 1253, 1254, 1255, 1256, 202, 202,
-
- 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264,
- 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272,
- 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280,
- 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288,
-
- 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296,
- 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304,
- 1239, 1239, 1305, 1306, 1307, 202, 1308, 1309,
- 1240, 1240, 1310, 1311, 1312, 207, 1313, 207,
-
- 207, 1314, 1315, 1316, 1317, 202, 1318, 1319,
- 1320, 1321, 1320, 1321, 1322, 1314, 1314, 1314,
- 1239, 1239, 1323, 1324, 202, 202, 1325, 1326,
- 1240, 1240, 1327, 1328, 202, 1314, 1314, 1314,
-
- 1239, 1239, 1329, 1330, 1331, 1332, 1333, 1334,
- 1240, 1240, 1335, 1336, 1337, 1314, 1338, 1338,
- 202, 202, 1339, 1340, 1341, 202, 1342, 1343,
- 1344, 1345, 1346, 1347, 1348, 1349, 207, 202,
-
- 1350, 1350, 1351, 1351, 1351, 1351, 1351, 1352,
- 1351, 1351, 1351, 1353, 1354, 1355, 1356, 1357,
- 1358, 1359, 1358, 1360, 1361, 1362, 14, 1363,
- 1364, 1365, 1366, 1367, 1367, 1368, 1366, 1367,
-
- 14, 14, 14, 14, 1369, 1370, 1370, 1371,
- 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379,
- 13, 13, 13, 1380, 1380, 1381, 1382, 1382,
- 14, 1383, 1384, 14, 1385, 1386, 1363, 43,
-
- 43, 14, 14, 14, 1387, 16, 1388, 1389,
- 1390, 1390, 1391, 1391, 1391, 1391, 1392, 1392,
- 1392, 1392, 1393, 1394, 1395, 1396, 1397, 1398,
- 1397, 1397, 1397, 1397, 1396, 1397, 1397, 1399,
-
- 1400, 1401, 1401, 1401, 1402, 1403, 1404, 1405,
- 1406, 1407, 1408, 1408, 1408, 1408, 1408, 1408,
- 1409, 1410, 202, 202, 1411, 1412, 1413, 1414,
- 1415, 1416, 1417, 1417, 1418, 1419, 1420, 160,
-
- 1409, 63, 58, 59, 1411, 1412, 1413, 1414,
- 1415, 1416, 1417, 1417, 1418, 1419, 1420, 202,
- 1215, 1215, 1215, 1215, 1215, 1421, 1421, 1421,
- 1421, 1421, 1421, 1421, 1421, 202, 202, 202,
-
- 12, 12, 12, 12, 12, 12, 12, 50,
- 1422, 12, 12, 1423, 1424, 1425, 1425, 1425,
- 1426, 1426, 1427, 1427, 1427, 1427, 1428, 1429,
- 1429, 1430, 1431, 1432, 1433, 1433, 1434, 1435,
-
- 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436,
- 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436,
- 173, 173, 180, 180, 173, 173, 173, 173,
- 180, 180, 180, 173, 173, 1437, 1437, 1437,
-
- 1437, 173, 1438, 1438, 1439, 1440, 1440, 197,
- 1441, 197, 1440, 1442, 1218, 1218, 1218, 1218,
- 1219, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1443, 1443, 1444, 1445, 51, 1443, 1443, 1444,
- 51, 1445, 1446, 1444, 1444, 1444, 1446, 1446,
- 1444, 1444, 1444, 1446, 51, 1444, 1447, 51,
- 36, 1444, 1444, 1444, 1444, 1444, 51, 51,
-
- 1443, 1443, 1443, 51, 1444, 51, 1448, 51,
- 1444, 51, 1449, 1450, 1444, 1444, 1451, 1446,
- 1444, 1444, 1452, 1444, 1446, 1453, 1453, 1453,
- 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1459,
-
- 1460, 1393, 1393, 1393, 1393, 1459, 1458, 1458,
- 1458, 1458, 1461, 1393, 1462, 1463, 1464, 1465,
- 1466, 1466, 1466, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
-
- 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
- 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
- 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
- 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
- 1469, 1469, 1469, 111, 123, 1470, 1470, 1470,
- 1470, 1466, 1471, 1471, 202, 202, 202, 202,
- 36, 36, 36, 36, 36, 51, 51, 51,
- 51, 51, 1472, 1472, 51, 51, 51, 51,
-
- 36, 51, 51, 36, 51, 51, 36, 51,
- 51, 51, 51, 51, 51, 51, 1472, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 1473, 1472, 1472,
- 51, 51, 36, 51, 36, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 1455, 1455, 1455, 1455, 1455,
- 1455, 1455, 1455, 1455, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
-
- 36, 36, 36, 36, 1472, 36, 36, 36,
- 1474, 1475, 1474, 1476, 1477, 1476, 36, 36,
- 36, 36, 18, 57, 36, 1478, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 1479,
-
- 1480, 1481, 1482, 36, 1483, 36, 1472, 36,
- 36, 36, 36, 36, 1418, 1418, 36, 1418,
- 1418, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 1484, 1485, 36, 36,
-
- 36, 1472, 36, 1486, 1472, 1487, 36, 1472,
- 36, 1472, 36, 36, 1488, 36, 36, 36,
- 36, 36, 1484, 1485, 1484, 1485, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
-
- 1472, 36, 1472, 36, 1484, 1485, 1484, 1485,
- 1484, 1485, 1484, 1485, 36, 1472, 1489, 1490,
- 1489, 1490, 1484, 1485, 1489, 1490, 1484, 1485,
- 1489, 1490, 1484, 1485, 1484, 1485, 1484, 1485,
-
- 1489, 1490, 1484, 1485, 1489, 1490, 1484, 1485,
- 1489, 1490, 1484, 1485, 36, 36, 36, 1484,
- 1485, 1484, 1485, 36, 36, 36, 36, 36,
- 1491, 36, 36, 36, 36, 36, 36, 36,
-
- 36, 36, 1484, 1485, 36, 36, 1492, 36,
- 1493, 1494, 36, 1494, 1472, 1472, 1472, 1472,
- 1484, 1485, 1484, 1485, 1484, 1485, 1484, 1485,
- 1495, 36, 36, 36, 36, 36, 36, 36,
-
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 1484, 1485, 1484, 1485, 1496, 36, 36,
- 1484, 1485, 36, 36, 36, 36, 1484, 1485,
- 1484, 1485, 1484, 1485, 1484, 1485, 1484, 1485,
-
- 1489, 1490, 1489, 1490, 1484, 1485, 1484, 1485,
- 1484, 1485, 1489, 1490, 1489, 1490, 36, 1497,
- 1484, 1485, 1498, 1498, 1498, 1393, 1499, 1499,
- 1393, 1393, 1500, 1500, 1500, 1501, 1501, 1393,
-
- 51, 1455, 51, 51, 51, 51, 51, 51,
- 16, 1388, 16, 1388, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 1502, 1502, 51, 51, 51, 51,
-
- 36, 36, 51, 51, 51, 51, 51, 51,
- 51, 1503, 1504, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 1505, 1505,
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
-
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
-
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
- 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505,
- 1505, 1505, 1505, 1455, 1393, 1455, 1455, 1455,
-
- 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455,
- 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455,
- 1455, 1455, 1455, 1455, 1455, 1506, 1455, 1455,
- 1455, 1455, 1455, 1393, 1393, 1393, 1393, 1393,
-
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1461, 1461, 1461, 1461,
- 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461,
-
- 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461,
- 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1507,
- 1507, 1462, 1462, 1462, 1462, 1462, 1462, 1462,
- 1462, 1462, 1462, 1462, 1508, 1508, 1508, 1508,
-
- 1508, 1508, 1463, 1463, 1463, 1463, 1463, 1463,
- 1509, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1511, 1511, 1511, 1511, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1513, 1513, 1513, 1513, 1514,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 1455, 1455, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522,
- 1523, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 1515, 1516, 1517, 1518,
- 1519, 1520, 1521, 1522, 1523, 65, 65, 65,
-
- 65, 65, 65, 65, 65, 65, 65, 65,
- 63, 58, 59, 1411, 1412, 1413, 1414, 1415,
- 1416, 1524, 1524, 1524, 1524, 1524, 1524, 1524,
- 1524, 1524, 1524, 1524, 1525, 1525, 1525, 1525,
-
- 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525,
- 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525,
- 1525, 1525, 1525, 1525, 1525, 1525, 1526, 1526,
- 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526,
-
- 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526,
- 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526,
- 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527,
- 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527,
-
- 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527,
- 1527, 1527, 1528, 1529, 1529, 1529, 1529, 1529,
- 1529, 1529, 1529, 1529, 1529, 1530, 1531, 1532,
- 1533, 1534, 1535, 1536, 1537, 1538, 1529, 1539,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 1461, 1461,
- 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 36,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 36, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
-
- 1502, 1502, 1502, 1502, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1540, 1540, 1461, 1461,
- 1541, 1455, 1502, 1502, 1502, 1542, 1502, 1502,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 1502, 1502, 1502, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 1502, 51, 51, 51, 51, 51, 51, 36,
- 1455, 1455, 1461, 1461, 1461, 1461, 1461, 1461,
- 1461, 1461, 1461, 1461, 1461, 1461, 1462, 1541,
-
- 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461,
- 1461, 1461, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1462, 1462, 1462, 1462, 1462, 1462,
- 1462, 1462, 1462, 1462, 1462, 1543, 1509, 1509,
-
- 1507, 1507, 1462, 1462, 1462, 1462, 1462, 1462,
- 1462, 1462, 1462, 1462, 1544, 1462, 1462, 1462,
- 1462, 1462, 1463, 1543, 1543, 1543, 1543, 1543,
- 1543, 1543, 1543, 1543, 1543, 1545, 1545, 1545,
-
- 1546, 1546, 1546, 1546, 1545, 1545, 1545, 1545,
- 1545, 1509, 1509, 1509, 1509, 1545, 1510, 1545,
- 1545, 1545, 1509, 1545, 1545, 1509, 1509, 1509,
- 1545, 1545, 1509, 1509, 1545, 1509, 1509, 1545,
-
- 1545, 1545, 1510, 1509, 1510, 1510, 1510, 1510,
- 1509, 1509, 1545, 1509, 1509, 1509, 1509, 1509,
- 1509, 1545, 1545, 1545, 1545, 1545, 1509, 1545,
- 1545, 1547, 1545, 1509, 1509, 1545, 1545, 1545,
-
- 1548, 1502, 1502, 1502, 1502, 1510, 51, 51,
- 1502, 1502, 1549, 1549, 1542, 1542, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 1510, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1510, 51, 1510, 51,
- 51, 51, 51, 1510, 1510, 1510, 51, 1509,
- 51, 51, 51, 1550, 1550, 1550, 1550, 1551,
-
- 1551, 51, 1552, 1552, 1502, 51, 51, 51,
- 1553, 1554, 1553, 1554, 1553, 1554, 1553, 1554,
- 1553, 1554, 1553, 1554, 1553, 1554, 1555, 1556,
- 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564,
-
- 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562,
- 1563, 1564, 1555, 1556, 1557, 1558, 1559, 1560,
- 1561, 1562, 1563, 1564, 51, 1510, 1510, 1510,
- 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51,
- 1510, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 1510,
-
- 1565, 1565, 1565, 1566, 1567, 1568, 1569, 1508,
- 1570, 1571, 1508, 1572, 1573, 1574, 1575, 1575,
- 1393, 1393, 1393, 1393, 1393, 1576, 1577, 1393,
- 1393, 1393, 1393, 1393, 1578, 1576, 1577, 1393,
-
- 1393, 1393, 1576, 1577, 1576, 1577, 1553, 1554,
- 1553, 1554, 1553, 1554, 1579, 1580, 1579, 1580,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
-
- 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581,
- 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581,
- 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581,
- 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581,
-
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
-
- 1393, 1393, 1393, 1553, 1554, 1553, 1554, 1553,
- 1554, 1553, 1554, 1553, 1554, 1582, 1583, 1584,
- 1585, 1553, 1554, 1553, 1554, 1553, 1554, 1553,
- 1554, 1393, 1393, 1586, 1393, 1393, 1393, 1393,
-
- 1587, 1393, 1393, 1588, 1576, 1577, 1393, 1393,
- 1576, 1577, 1576, 1577, 1576, 1577, 1576, 1577,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1589, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
-
- 1576, 1577, 1393, 1393, 1576, 1577, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1576,
- 1577, 1576, 1577, 1393, 1576, 1577, 1393, 1393,
- 1553, 1554, 1553, 1554, 1393, 1393, 1393, 1393,
-
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1576, 1577, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1590, 1393, 1393,
- 1576, 1577, 1393, 1393, 1553, 1554, 1393, 1393,
-
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1460, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
-
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1576, 1577, 1576, 1577, 1393,
- 1393, 1393, 1393, 1393, 1576, 1577, 1393, 1393,
- 1393, 1393, 1393, 1393, 1576, 1577, 1393, 1393,
-
- 1393, 1393, 1393, 1393, 1576, 1577, 1393, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
- 1393, 1393, 1393, 1393, 1460, 1460, 1460, 1393,
- 1393, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
-
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
-
- 1577, 1576, 1577, 1393, 1393, 1393, 1576, 1577,
- 1576, 1577, 1576, 1577, 1576, 1577, 1393, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
-
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1576,
- 1577, 1576, 1577, 1576, 1577, 1576, 1577, 1393,
- 1393, 1393, 1393, 1393, 1591, 1393, 1592, 1393,
-
- 1393, 1393, 1393, 1593, 1594, 1593, 1393, 1393,
- 1393, 1393, 1393, 1393, 1576, 1577, 1595, 1393,
- 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1576,
- 1577, 1576, 1577, 1393, 1393, 1393, 1393, 1393,
-
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1462, 1462,
- 1462, 1462, 1462, 1462, 1463, 1463, 1463, 1463,
- 1463, 1463, 1463, 1543, 1543, 1543, 1543, 1543,
-
- 1463, 1463, 1463, 1463, 1543, 1543, 1543, 1543,
- 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543,
- 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573,
- 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573,
-
- 1573, 1573, 1573, 1573, 1573, 1543, 1543, 1573,
- 1573, 1573, 1573, 1573, 1573, 1512, 1512, 1512,
- 1543, 1543, 1543, 1543, 1543, 1509, 1509, 1509,
- 1509, 1509, 1512, 1512, 1512, 1512, 1512, 1512,
-
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 202, 202, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
-
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 202, 1596,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
-
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1597, 1597, 1597, 1512, 1512, 1512,
-
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1598, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1514, 1597, 1597, 1597, 1597, 1597,
- 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597,
-
- 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597,
- 1597, 1597, 1597, 1597, 1471, 1471, 1471, 1471,
- 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597,
- 1597, 1597, 1597, 1597, 1597, 1597, 1599, 1598,
-
- 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600,
- 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600,
- 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600,
- 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600,
-
- 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600,
- 1600, 1600, 1600, 1600, 1600, 1600, 1600, 202,
- 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601,
- 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601,
-
- 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601,
- 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601,
- 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601,
- 1601, 1601, 1601, 1601, 1601, 1601, 1601, 202,
-
- 127, 123, 1602, 1603, 1604, 1605, 1606, 127,
- 123, 127, 123, 127, 123, 1607, 1608, 1609,
- 1610, 1235, 1237, 1238, 1611, 127, 123, 1611,
- 1235, 1235, 1235, 1235, 1612, 1612, 1613, 1614,
-
- 1615, 1616, 1615, 1616, 1615, 1616, 1615, 1616,
- 1615, 1616, 1615, 1616, 1615, 1616, 1615, 1616,
- 1615, 1616, 1615, 1616, 1615, 1616, 1615, 1616,
- 1615, 1616, 1615, 1616, 1615, 1616, 1615, 1616,
-
- 1615, 1616, 1615, 1616, 1617, 1618, 1618, 1618,
- 1618, 1618, 1618, 1619, 1620, 1619, 1620, 1621,
- 1621, 1621, 1622, 1623, 202, 202, 202, 202,
- 202, 1624, 1625, 1625, 1625, 1626, 1624, 1625,
-
- 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627,
- 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627,
- 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627,
- 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627,
-
- 1627, 1627, 1627, 1627, 1627, 1627, 202, 1628,
- 202, 202, 202, 202, 202, 1628, 202, 202,
- 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629,
- 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629,
-
- 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629,
- 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629,
- 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629,
- 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629,
-
- 1629, 1629, 1629, 1629, 1629, 1629, 1630, 1630,
- 202, 202, 202, 202, 202, 202, 202, 1631,
- 1632, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 1633,
-
- 871, 871, 871, 871, 871, 871, 871, 871,
- 871, 871, 871, 871, 871, 871, 871, 871,
- 871, 871, 871, 871, 871, 871, 871, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 871, 871, 871, 871, 871, 871, 871, 202,
- 871, 871, 871, 871, 871, 871, 871, 202,
- 871, 871, 871, 871, 871, 871, 871, 202,
- 871, 871, 871, 871, 871, 871, 871, 202,
-
- 267, 267, 267, 267, 267, 267, 267, 267,
- 267, 267, 267, 267, 267, 267, 267, 267,
- 267, 267, 267, 267, 267, 267, 267, 267,
- 267, 267, 267, 267, 267, 267, 267, 267,
-
- 1634, 1634, 1635, 1636, 1635, 1636, 1634, 1634,
- 1634, 1635, 1636, 1634, 1635, 1636, 1397, 1397,
- 1397, 1397, 1397, 1397, 1397, 1397, 1396, 1637,
- 1638, 1639, 1640, 1641, 1635, 1636, 1641, 1641,
-
- 1642, 1643, 1579, 1580, 1579, 1580, 1579, 1580,
- 1579, 1580, 1639, 1639, 1639, 1639, 1644, 1645,
- 1639, 1646, 1647, 1648, 1648, 1647, 1647, 1647,
- 1647, 1647, 1649, 1649, 1650, 1651, 1651, 1652,
-
- 1653, 1651, 1654, 1655, 1655, 1656, 1656, 1656,
- 1656, 1656, 1657, 1658, 1657, 1658, 1657, 1659,
- 1596, 1596, 1660, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 202, 1661, 1661, 1661, 1661, 1662,
-
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
-
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661,
- 1661, 1661, 1661, 1662, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662,
- 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662,
- 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662,
- 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662,
-
- 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662,
- 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662,
- 1662, 1662, 1662, 1662, 1662, 1662, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663,
- 1663, 1663, 1663, 1663, 202, 202, 202, 202,
-
- 1351, 1664, 1665, 1666, 1502, 1667, 1668, 1669,
- 16, 1388, 16, 1388, 16, 1388, 16, 1388,
- 16, 1388, 1502, 1502, 16, 1388, 16, 1388,
- 16, 1388, 16, 1388, 1670, 1366, 1671, 1671,
-
- 1502, 1669, 1669, 1669, 1669, 1669, 1669, 1669,
- 1669, 1669, 1672, 1673, 174, 1674, 1675, 1675,
- 1676, 1677, 1677, 1677, 1677, 1678, 1679, 1502,
- 1680, 1680, 1680, 1681, 1682, 1683, 1663, 1502,
-
- 202, 1684, 1685, 1684, 1685, 1684, 1685, 1684,
- 1685, 1684, 1685, 1685, 1686, 1685, 1686, 1685,
- 1686, 1685, 1686, 1685, 1686, 1685, 1686, 1685,
- 1686, 1685, 1686, 1685, 1686, 1685, 1686, 1685,
-
- 1686, 1685, 1686, 1684, 1685, 1686, 1685, 1686,
- 1685, 1686, 1685, 1685, 1685, 1685, 1685, 1685,
- 1686, 1686, 1685, 1686, 1686, 1685, 1686, 1686,
- 1685, 1686, 1686, 1685, 1686, 1686, 1685, 1685,
-
- 1685, 1685, 1685, 1684, 1685, 1684, 1685, 1684,
- 1685, 1685, 1685, 1685, 1685, 1685, 1684, 1685,
- 1685, 1685, 1685, 1685, 1686, 1687, 1687, 202,
- 202, 1688, 1688, 1689, 1689, 1690, 1691, 1692,
-
- 1693, 1694, 1695, 1694, 1695, 1694, 1695, 1694,
- 1695, 1694, 1695, 1695, 1696, 1695, 1696, 1695,
- 1696, 1695, 1696, 1695, 1696, 1695, 1696, 1695,
- 1696, 1695, 1696, 1695, 1696, 1695, 1696, 1695,
-
- 1696, 1695, 1696, 1694, 1695, 1696, 1695, 1696,
- 1695, 1696, 1695, 1695, 1695, 1695, 1695, 1695,
- 1696, 1696, 1695, 1696, 1696, 1695, 1696, 1696,
- 1695, 1696, 1696, 1695, 1696, 1696, 1695, 1695,
-
- 1695, 1695, 1695, 1694, 1695, 1694, 1695, 1694,
- 1695, 1695, 1695, 1695, 1695, 1695, 1694, 1695,
- 1695, 1695, 1695, 1695, 1696, 1694, 1694, 1696,
- 1696, 1696, 1696, 1697, 1698, 1699, 1700, 1701,
-
- 202, 202, 202, 202, 202, 1702, 1702, 1702,
- 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702,
- 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702,
- 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702,
-
- 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702,
- 1702, 1702, 1702, 1702, 1702, 1703, 1704, 1705,
- 202, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
-
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
-
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 202,
- 1707, 1707, 1708, 1708, 1708, 1708, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
-
- 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710,
- 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710,
- 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710,
- 1711, 1711, 1711, 1712, 1712, 1712, 1712, 1712,
-
- 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541,
- 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
-
- 1546, 1546, 1546, 1546, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713,
- 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713,
-
- 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714,
- 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714,
- 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714,
- 1714, 1714, 1714, 1714, 1714, 1715, 1715, 202,
-
- 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708,
- 1708, 1708, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
-
- 1709, 1709, 1709, 1709, 1716, 1716, 1716, 1716,
- 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717,
- 1718, 1719, 1719, 1719, 1719, 1719, 1719, 1719,
- 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719,
-
- 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714,
- 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714,
- 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714,
- 1714, 1714, 1714, 1714, 1715, 1715, 1720, 1707,
-
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1719, 1719, 1719, 1719, 1719, 1719, 1719,
- 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719,
-
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1718, 1718, 1718, 1718,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
-
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1722,
-
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
-
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
-
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1718,
- 1718, 1718, 1718, 1709, 1709, 1709, 1709, 1709,
-
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
-
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1718, 1718,
-
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709,
- 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1718,
-
- 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
- 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
- 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
- 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
-
- 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
- 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
- 1723, 1723, 1723, 1723, 1723, 1723, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
-
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
-
- 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
- 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
- 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
- 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
-
- 1725, 1725, 1725, 1725, 1725, 1725, 1726, 1726,
- 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726,
- 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726,
- 1726, 1726, 1726, 1726, 1727, 1727, 1727, 1727,
-
- 1727, 1727, 1727, 1727, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1729, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
-
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1732, 1732, 1732, 1732, 1732,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1733, 1733, 1733,
-
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 1735, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
-
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
-
- 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734,
- 1734, 1734, 1734, 1734, 1734, 202, 202, 202,
- 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736,
- 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736,
-
- 1736, 1736, 1737, 1737, 1736, 1736, 1736, 1736,
- 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736,
- 1736, 1736, 1736, 1736, 1737, 1736, 1736, 1736,
- 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736,
-
- 1736, 1737, 1736, 1736, 1736, 1737, 1736, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738,
- 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738,
-
- 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738,
- 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738,
- 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738,
- 1739, 1739, 1739, 1739, 1739, 1739, 1740, 1741,
-
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
-
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
- 1742, 1742, 1742, 1742, 1743, 1744, 1745, 1746,
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742,
-
- 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754,
- 1755, 1756, 1742, 1742, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 281, 282, 281, 282, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 281, 282,
-
- 285, 286, 281, 282, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 1757, 267,
- 1758, 1758, 1758, 1759, 1760, 1760, 1760, 1760,
- 1760, 1760, 1760, 1760, 267, 267, 1759, 1761,
-
- 281, 282, 281, 282, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 281, 282,
- 281, 282, 281, 282, 281, 282, 281, 282,
- 287, 288, 287, 288, 1762, 1762, 1763, 1760,
-
- 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764,
- 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764,
- 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764,
- 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764,
-
- 1764, 1764, 1764, 1764, 1764, 1764, 1765, 1765,
- 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765,
- 1766, 1766, 1767, 1768, 1769, 1769, 1769, 1768,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770,
- 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771,
- 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1772,
- 1772, 1772, 1772, 1645, 1645, 1645, 1645, 1645,
-
- 1773, 1773, 1237, 1238, 1237, 1238, 1237, 1238,
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1235, 1235, 1237, 1238, 1237, 1238, 1237, 1238,
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
-
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
-
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1612, 1235, 1235, 1235, 1235, 1235, 1235, 1235,
- 1235, 1237, 1238, 1237, 1238, 1774, 1237, 1238,
-
- 1237, 1238, 1237, 1238, 1237, 1238, 1237, 1238,
- 1645, 1775, 1775, 1237, 1238, 1776, 1777, 1778,
- 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786,
- 1785, 1786, 1785, 1786, 1785, 1786, 1785, 1786,
-
- 1779, 1780, 1779, 1780, 1779, 1780, 1779, 1780,
- 1779, 1780, 1787, 1788, 1789, 1790, 1791, 1792,
- 1793, 1794, 1795, 1796, 1797, 1798, 1797, 1798,
- 1799, 1800, 1801, 1802, 1801, 1802, 1801, 1802,
-
- 202, 202, 1801, 1802, 1803, 1804, 1805, 1806,
- 1807, 1806, 1807, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 1806, 1807, 1808,
- 1809, 1809, 1777, 1810, 1810, 1810, 1810, 1810,
-
- 1811, 1811, 1812, 1811, 1811, 1811, 1813, 1811,
- 1811, 1811, 1811, 1812, 1811, 1811, 1811, 1811,
- 1811, 1811, 1811, 1811, 1811, 1811, 1811, 1811,
- 1811, 1811, 1811, 1811, 1811, 1811, 1811, 1811,
-
- 1811, 1811, 1811, 1814, 1814, 1812, 1812, 1814,
- 1815, 1815, 1815, 1815, 1816, 202, 202, 202,
- 1717, 1717, 1717, 1717, 1717, 1717, 813, 813,
- 1428, 1817, 202, 202, 202, 202, 202, 202,
-
- 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818,
- 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818,
- 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818,
- 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818,
-
- 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818,
- 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818,
- 1818, 1818, 1819, 1820, 1821, 1821, 1822, 1822,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1823, 1823, 1824, 1824, 1824, 1824, 1824, 1824,
- 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
- 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
- 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
+ 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112,
+ 1112, 1112, 1112, 1112, 1112, 1112, 221, 221,
+ 1112, 1112, 1112, 1112, 1112, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1114, 1114, 221, 221, 221, 221,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 221, 221, 221, 221, 221, 221,
+ 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122,
+ 1123, 1124, 1125, 221, 221, 221, 1126, 1126,
+
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127,
+
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128,
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128,
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1129,
+ 1130, 1131, 1131, 1132, 221, 221, 1133, 1133,
+
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1134, 1135, 1136, 1135,
+ 1136, 1136, 1136, 1136, 1136, 1136, 1136, 221,
+
+ 1137, 1138, 1136, 1138, 1138, 1136, 1136, 1136,
+ 1136, 1136, 1136, 1136, 1136, 1135, 1135, 1135,
+ 1135, 1135, 1135, 1136, 1136, 1139, 1139, 1139,
+ 1139, 1139, 1139, 1139, 1139, 221, 221, 1140,
+
+ 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148,
+ 1149, 1150, 221, 221, 221, 221, 221, 221,
+ 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148,
+ 1149, 1150, 221, 221, 221, 221, 221, 221,
+
+ 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1152,
+ 1153, 1153, 1153, 1153, 1151, 1151, 221, 221,
+ 1154, 1154, 1154, 1154, 1154, 1155, 1155, 1155,
+ 1155, 1155, 1155, 1154, 1154, 1155, 1156, 1157,
+
+ 1157, 1158, 1158, 1159, 1159, 1158, 1158, 1158,
+ 1158, 1158, 1159, 1158, 1158, 1158, 1158, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1160, 1160, 1160, 1160, 1161, 1162, 1163, 1162,
+ 1163, 1162, 1163, 1162, 1163, 1162, 1163, 1162,
+ 1162, 1162, 1163, 1162, 1162, 1162, 1162, 1162,
+ 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162,
+
+ 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162,
+ 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162,
+ 1162, 1162, 1162, 1162, 1164, 1165, 1160, 1160,
+ 1160, 1160, 1160, 1166, 1160, 1166, 1161, 1161,
+
+ 1166, 1166, 1160, 1166, 1167, 1162, 1162, 1162,
+ 1162, 1162, 1162, 1162, 1168, 221, 221, 221,
+ 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
+ 1177, 1178, 1179, 1179, 1180, 1181, 1179, 1179,
+
+ 1181, 1182, 1182, 1182, 1182, 1182, 1182, 1182,
+ 1182, 1182, 1182, 1183, 1184, 1183, 1183, 1183,
+ 1183, 1183, 1183, 1183, 1182, 1182, 1182, 1182,
+ 1182, 1182, 1182, 1182, 1182, 1185, 1185, 221,
+
+ 1186, 1186, 1187, 1188, 1188, 1188, 1188, 1188,
+ 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188,
+ 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188,
+ 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188,
+
+ 1188, 1187, 1186, 1186, 1186, 1186, 1187, 1187,
+ 1186, 1186, 1189, 1190, 1191, 1191, 1188, 1188,
+ 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199,
+ 1200, 1201, 1202, 1202, 1202, 1202, 1202, 1202,
+
+ 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203,
+ 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203,
+ 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203,
+ 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203,
+
+ 1203, 1203, 1203, 1203, 1203, 1203, 1204, 1205,
+ 1206, 1206, 1205, 1205, 1205, 1206, 1205, 1206,
+ 1206, 1206, 1207, 1207, 221, 221, 221, 221,
+ 221, 221, 221, 221, 1208, 1208, 1208, 1208,
+
+ 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209,
+ 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209,
+ 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209,
+ 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209,
+
+ 1209, 1209, 1209, 1209, 1210, 1210, 1210, 1210,
+ 1210, 1210, 1210, 1210, 1211, 1211, 1211, 1211,
+ 1211, 1211, 1211, 1211, 1210, 1210, 1211, 1212,
+ 221, 221, 221, 1213, 1213, 1214, 1214, 1214,
+
+ 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222,
+ 1223, 1224, 221, 221, 221, 1209, 1209, 1209,
+ 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232,
+ 1233, 1234, 1235, 1235, 1235, 1235, 1235, 1235,
+
+ 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235,
+ 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235,
+ 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235,
+ 1236, 1236, 1236, 1236, 1236, 1236, 1237, 1237,
+
+ 1238, 1239, 1240, 1241, 1241, 1242, 1243, 1244,
+ 1245, 221, 221, 221, 221, 221, 221, 221,
+ 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+ 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+
+ 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+ 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+ 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+ 1246, 1246, 1246, 221, 221, 1246, 1246, 1246,
+
+ 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 1248, 1248, 1248, 1249, 1250, 1251, 1251, 1251,
+ 1251, 1251, 1248, 1248, 1251, 1251, 1251, 1251,
+
+ 1248, 1252, 1250, 1250, 1250, 1250, 1250, 1250,
+ 1250, 1253, 1253, 1253, 1253, 1251, 1253, 1253,
+ 1253, 1253, 1253, 1254, 1255, 1254, 1254, 1256,
+ 1154, 1154, 1257, 221, 221, 221, 221, 221,
+
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+
+ 129, 129, 129, 129, 129, 129, 1258, 1258,
+ 1258, 1258, 1258, 1259, 1260, 1260, 1260, 1261,
+ 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260,
+ 1260, 1260, 1260, 1261, 1260, 1260, 1260, 1260,
+
+ 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260,
+ 1260, 1260, 1260, 1260, 1260, 1260, 1261, 1260,
+ 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260,
+ 1260, 1260, 1260, 1260, 1260, 1262, 1262, 1262,
+
+ 1262, 1262, 1260, 1260, 1260, 1260, 1262, 1262,
+ 1262, 1262, 1262, 129, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130,
+ 1263, 1264, 130, 130, 130, 1265, 130, 130,
+
+ 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 1266, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 1267, 1267, 1267, 1267, 1267,
+
+ 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
+ 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
+ 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
+ 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1268,
+
+ 1269, 1269, 1270, 1269, 1271, 1271, 1271, 1271,
+ 1271, 1271, 1272, 1273, 1273, 1274, 1275, 1276,
+ 1277, 1273, 1273, 1273, 1273, 1273, 1273, 1273,
+ 1273, 1273, 1273, 1273, 1273, 1273, 1273, 1273,
+
+ 1273, 1273, 1273, 1273, 1273, 1273, 1273, 1154,
+ 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154,
+ 1154, 1154, 1154, 1154, 1154, 1154, 1278, 1279,
+ 1279, 1280, 1281, 1282, 1283, 1251, 1271, 1272,
+
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 1284, 1285,
+ 1286, 1287, 1288, 1289, 1290, 1290, 1291, 1290,
+
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 81, 83, 81, 83, 81, 83,
+ 81, 83, 1292, 1293, 1292, 1293, 1292, 1293,
+
+ 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
+ 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295,
+ 1294, 1294, 1294, 1294, 1294, 1294, 221, 221,
+ 1295, 1295, 1295, 1295, 1295, 1295, 221, 221,
+
+ 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
+ 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295,
+ 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
+ 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295,
+
+ 1294, 1294, 1294, 1294, 1294, 1294, 221, 221,
+ 1295, 1295, 1295, 1295, 1295, 1295, 221, 221,
+ 1296, 1294, 1297, 1294, 1298, 1294, 1299, 1294,
+ 221, 1295, 221, 1295, 221, 1295, 221, 1295,
+
+ 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
+ 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295,
+ 1300, 1301, 1302, 1303, 1302, 1303, 1304, 1305,
+ 1306, 1307, 1308, 1309, 1310, 1311, 221, 221,
+
+ 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319,
+ 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327,
+ 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335,
+ 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343,
+
+ 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351,
+ 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359,
+ 1294, 1294, 1360, 1361, 1362, 221, 1363, 1364,
+ 1295, 1295, 1365, 1366, 1367, 226, 1368, 226,
+
+ 226, 1369, 1370, 1371, 1372, 221, 1373, 1374,
+ 1375, 1376, 1375, 1376, 1377, 1369, 1369, 1369,
+ 1294, 1294, 1378, 1379, 221, 221, 1380, 1381,
+ 1295, 1295, 1382, 1383, 221, 1369, 1369, 1369,
+
+ 1294, 1294, 1384, 1385, 1386, 1387, 1388, 1389,
+ 1295, 1295, 1390, 1391, 1392, 1369, 1393, 1393,
+ 221, 221, 1394, 1395, 1396, 221, 1397, 1398,
+ 1399, 1400, 1401, 1402, 1403, 1404, 226, 221,
+
+ 1405, 1405, 1406, 1406, 1406, 1406, 1406, 1407,
+ 1406, 1406, 1406, 1408, 1409, 1410, 1411, 1412,
+ 1413, 1414, 1415, 1416, 1417, 1418, 54, 1419,
+ 1420, 1421, 1422, 1423, 1424, 1425, 1422, 1423,
+
+ 54, 54, 54, 1426, 1427, 1428, 1428, 1429,
+ 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437,
+ 1438, 1439, 1438, 1440, 1441, 1442, 1443, 1443,
+ 1426, 1444, 1445, 54, 1446, 1447, 1448, 1449,
+
+ 1449, 1426, 1426, 1426, 1450, 1451, 1452, 1453,
+ 1454, 1455, 1456, 1456, 1456, 1456, 1457, 1457,
+ 1457, 1457, 1458, 1459, 1460, 1461, 1462, 1463,
+ 1462, 1462, 1462, 1462, 1461, 1462, 1462, 1464,
+
+ 1465, 1466, 1466, 1466, 1467, 1468, 1469, 1470,
+ 1471, 1472, 1473, 1473, 1473, 1473, 1473, 1473,
+ 1474, 1475, 221, 221, 1476, 1477, 1478, 1479,
+ 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487,
+
+ 1474, 70, 65, 66, 1476, 1477, 1478, 1479,
+ 1480, 1481, 1482, 1483, 1484, 1485, 1486, 221,
+ 1267, 1267, 1267, 1267, 1267, 1488, 1488, 1488,
+ 1488, 1488, 1488, 1488, 1488, 221, 221, 221,
+
+ 768, 768, 768, 768, 768, 768, 768, 1489,
+ 1490, 1491, 768, 1492, 1493, 1494, 1494, 1494,
+ 1495, 1495, 1496, 1496, 1496, 1496, 1497, 1498,
+ 1498, 1499, 1500, 1501, 1502, 1502, 1503, 1504,
+
+ 1505, 1506, 1506, 1506, 1506, 1506, 1506, 1506,
+ 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506,
+ 288, 288, 1507, 1507, 288, 288, 288, 288,
+ 1507, 1507, 1507, 288, 288, 1508, 1508, 1508,
+
+ 1508, 288, 1509, 1509, 1510, 1511, 1511, 1512,
+ 1513, 1512, 1511, 1514, 1272, 1272, 1272, 1272,
+ 1273, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1515, 1515, 1516, 1517, 1518, 1519, 1515, 1516,
+ 1518, 1517, 1520, 1516, 1516, 1516, 1520, 1520,
+ 1516, 1516, 1516, 1521, 1518, 1516, 1522, 1518,
+ 1523, 1516, 1516, 1516, 1516, 1516, 1518, 1518,
+
+ 1524, 1525, 1526, 1518, 1516, 1518, 1527, 1518,
+ 1516, 1518, 1528, 1529, 1516, 1516, 1530, 1520,
+ 1516, 1516, 1531, 1516, 1520, 1532, 1532, 1532,
+ 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1538,
+
+ 1539, 1458, 1458, 1458, 1458, 1538, 1537, 1537,
+ 1537, 1537, 1540, 1458, 1541, 1542, 1543, 1544,
+ 1545, 1545, 1545, 72, 72, 1546, 1546, 1546,
+ 1546, 1546, 1546, 72, 72, 72, 72, 1546,
+
+ 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547,
+ 1547, 1547, 1547, 1547, 1548, 1548, 1548, 1548,
+ 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549,
+ 1549, 1549, 1550, 1550, 1550, 1550, 1550, 1550,
+
+ 1551, 1551, 1551, 1552, 138, 1553, 1553, 1553,
+ 1553, 1554, 1555, 1555, 221, 221, 221, 221,
+ 75, 75, 75, 75, 1556, 61, 61, 61,
+ 61, 61, 1557, 1557, 1518, 1518, 1518, 1518,
+
+ 1523, 1518, 1518, 1523, 1518, 1518, 1523, 1518,
+ 1518, 56, 56, 1518, 1518, 1518, 1557, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1558, 1558, 1518, 1518, 1518, 1518, 1518, 1518,
+
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1559, 1557, 1557,
+ 1518, 1518, 75, 1518, 75, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1558,
+ 1518, 1518, 1518, 1534, 1534, 1534, 1534, 1534,
+ 1534, 1534, 1534, 1534, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+
+ 75, 1523, 75, 75, 1557, 1523, 1523, 75,
+ 1560, 1561, 1562, 1563, 1564, 1565, 1523, 75,
+ 1523, 75, 1566, 1567, 1523, 1568, 1523, 1523,
+ 1523, 1523, 75, 1523, 1523, 75, 75, 1569,
+
+ 1570, 1571, 1572, 75, 1573, 75, 1557, 75,
+ 75, 75, 75, 75, 1574, 1575, 75, 1575,
+ 1575, 1523, 1523, 1523, 75, 75, 75, 75,
+ 1523, 1523, 1523, 1523, 1576, 1577, 1523, 1523,
+
+ 1523, 1557, 1523, 1578, 1557, 1579, 1523, 1557,
+ 75, 1557, 1523, 1523, 1580, 1523, 1523, 1523,
+ 1523, 1523, 1576, 1581, 1582, 1581, 1523, 1523,
+ 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523,
+
+ 1583, 75, 1557, 1523, 1576, 1577, 1576, 1577,
+ 1582, 1581, 1576, 1577, 1523, 1557, 1584, 1585,
+ 1586, 1587, 1582, 1581, 1586, 1587, 1582, 1581,
+ 1586, 1587, 1582, 1581, 1582, 1581, 1582, 1581,
+
+ 1586, 1587, 1576, 1577, 1586, 1587, 1576, 1577,
+ 1586, 1587, 1582, 1581, 1523, 1523, 1523, 1582,
+ 1581, 1582, 1581, 1523, 1523, 75, 1523, 1523,
+ 1588, 75, 1523, 1523, 1523, 1523, 1523, 1523,
+
+ 1523, 1523, 1582, 1581, 1523, 75, 1589, 1523,
+ 1590, 1591, 1523, 1591, 1557, 1557, 1557, 1557,
+ 1582, 1581, 1582, 1581, 1582, 1581, 1582, 1581,
+ 1592, 1523, 1523, 1523, 1523, 1523, 1523, 75,
+
+ 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523,
+ 1523, 1582, 1581, 1582, 1581, 1593, 1523, 1523,
+ 1582, 1581, 1523, 1523, 1523, 1523, 1582, 1581,
+ 1582, 1581, 1582, 1581, 1582, 1581, 1582, 1581,
+
+ 1586, 1587, 1586, 1587, 1582, 1581, 1582, 1581,
+ 1582, 1581, 1586, 1587, 1586, 1587, 1523, 1594,
+ 1582, 1581, 1595, 1595, 1595, 1458, 1596, 1596,
+ 1458, 1458, 1597, 1597, 1597, 1598, 1598, 1458,
+
+ 1518, 1534, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1451, 1452, 1451, 1452, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1558, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1599, 1599, 1518, 1518, 1518, 1518,
+
+ 1523, 1523, 1518, 1518, 1518, 1518, 1518, 1518,
+ 56, 1600, 1601, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1602, 1602,
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+ 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602,
+ 1602, 1602, 1602, 1534, 1458, 1534, 1534, 1534,
+
+ 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534,
+ 1603, 1534, 1534, 1534, 1534, 1534, 1534, 1534,
+ 1534, 1534, 1534, 1534, 1534, 1604, 1534, 1534,
+ 1534, 1534, 1534, 1458, 1458, 1458, 1458, 1458,
+
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1540, 1540, 1540, 1540,
+ 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540,
+
+ 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540,
+ 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1605,
+ 1606, 1541, 1541, 1541, 1541, 1541, 1541, 1541,
+ 1541, 1541, 1541, 1541, 1607, 1607, 1607, 1607,
+
+ 1607, 1607, 1542, 1542, 1542, 1542, 1542, 1542,
+ 1608, 1609, 1609, 1609, 1609, 1610, 1610, 1610,
+ 1611, 1612, 1612, 1611, 1613, 1613, 1613, 1613,
+ 1614, 1614, 1614, 1615, 1615, 1615, 1615, 1616,
+
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+ 1518, 1518, 1518, 1518, 1518, 1534, 1534, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624,
+ 1625, 72, 72, 72, 72, 72, 72, 72,
+ 72, 72, 72, 72, 1626, 1627, 1628, 1629,
+ 1630, 1631, 1632, 1633, 1634, 1635, 1635, 1635,
+
+ 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635,
+ 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643,
+ 1644, 1645, 1645, 1645, 1645, 1645, 1645, 1645,
+ 1645, 1645, 1645, 1645, 1646, 1646, 1646, 1646,
+
+ 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646,
+ 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646,
+ 1646, 1646, 1646, 1646, 1646, 1646, 1647, 1647,
+ 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647,
+
+ 1647, 1647, 1648, 1647, 1647, 1647, 1647, 1647,
+ 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647,
+ 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649,
+ 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649,
+
+ 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649,
+ 1649, 1649, 1650, 1651, 1651, 1651, 1651, 1651,
+ 1651, 1651, 1651, 1651, 1651, 1652, 1653, 1654,
+ 1655, 1656, 1657, 1658, 1659, 1660, 1651, 1661,
+
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1518, 1518, 1518, 1518,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1518, 1518, 1558, 1558, 1558, 1558, 1540, 1540,
+ 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540,
+
+ 1558, 1558, 1518, 1558, 1558, 1558, 1558, 1558,
+ 1558, 1558, 56, 56, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1558, 1558, 1518, 1518, 61, 75,
+ 1518, 1518, 1518, 1518, 1558, 1558, 1518, 1518,
+
+ 61, 75, 1518, 1518, 1518, 1518, 1558, 1558,
+ 1558, 1518, 1518, 1558, 1518, 1518, 1558, 1558,
+ 1558, 1558, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+ 1518, 1518, 1558, 1558, 1558, 1558, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1558,
+ 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534,
+ 1458, 1458, 1458, 1662, 1662, 1663, 1663, 1458,
+
+ 1664, 1664, 1664, 1664, 56, 61, 1558, 56,
+ 56, 61, 56, 56, 56, 56, 61, 61,
+ 56, 56, 56, 1518, 1665, 1665, 1666, 1666,
+ 1667, 1603, 1664, 1664, 1668, 1669, 1668, 1664,
+
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 1664, 1664, 1664, 56, 56, 56, 56,
+
+ 61, 56, 61, 56, 56, 56, 56, 56,
+ 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670,
+ 1670, 1670, 1670, 1670, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+
+ 61, 61, 56, 61, 61, 61, 56, 61,
+ 1668, 61, 61, 56, 61, 61, 56, 1556,
+ 1603, 1603, 1666, 1666, 1666, 1666, 1666, 1666,
+ 1666, 1666, 1666, 1666, 1666, 1666, 1671, 1672,
+
+ 1666, 1666, 1666, 1666, 1666, 1666, 1540, 1540,
+ 1540, 1540, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1605, 1605, 1671, 1673, 1671, 1671, 1671, 1671,
+ 1671, 1671, 1671, 1671, 1671, 1674, 1675, 1675,
+
+ 1605, 1676, 1671, 1671, 1671, 1671, 1671, 1671,
+ 1671, 1671, 1673, 1673, 1677, 1671, 1671, 1671,
+ 1671, 1671, 1678, 1674, 1674, 1674, 1674, 1674,
+ 1674, 1674, 1674, 1674, 1674, 1679, 1679, 1680,
+
+ 1681, 1681, 1681, 1681, 1679, 1679, 1680, 1680,
+ 1680, 1675, 1675, 1675, 1675, 1680, 1609, 1680,
+ 1680, 1680, 1675, 1680, 1679, 1675, 1675, 1675,
+ 1680, 1680, 1675, 1675, 1680, 1675, 1675, 1680,
+
+ 1680, 1680, 1610, 1675, 1610, 1610, 1610, 1610,
+ 1675, 1675, 1679, 1675, 1675, 1675, 1675, 1675,
+ 1675, 1680, 1679, 1679, 1680, 1679, 1675, 1680,
+ 1680, 1682, 1679, 1675, 1675, 1679, 1680, 1680,
+
+ 1683, 1664, 1664, 1664, 1664, 1609, 1518, 1518,
+ 1664, 1664, 1684, 1684, 1669, 1669, 56, 56,
+ 56, 56, 56, 1518, 56, 1518, 56, 1518,
+ 1518, 1518, 1518, 1518, 1518, 56, 1518, 1518,
+
+ 1518, 56, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1609, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 56, 56, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1558, 1518, 1518,
+
+ 1518, 1518, 1518, 1518, 56, 1518, 1518, 56,
+ 1518, 1518, 1518, 1518, 1609, 1518, 1609, 1518,
+ 1518, 1518, 1518, 1609, 1609, 1609, 1518, 1685,
+ 1518, 1518, 1518, 1686, 1686, 1686, 1686, 1687,
+
+ 1687, 1518, 1688, 1689, 1664, 56, 56, 56,
+ 1690, 1691, 1690, 1691, 1690, 1691, 1690, 1691,
+ 1690, 1691, 1690, 1691, 1690, 1691, 1692, 1693,
+ 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701,
+
+ 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709,
+ 1710, 1711, 1702, 1703, 1704, 1705, 1706, 1707,
+ 1708, 1709, 1710, 1711, 1518, 1609, 1609, 1609,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+ 1518, 56, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1609, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+ 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1609,
+
+ 1712, 1712, 1712, 1713, 1714, 1715, 1716, 1607,
+ 1717, 1718, 1607, 1719, 1720, 1721, 1722, 1722,
+ 1458, 1458, 1458, 1458, 1458, 1723, 1724, 1458,
+ 1458, 1458, 1458, 1458, 1725, 1723, 1724, 1458,
+
+ 1458, 1458, 1723, 1724, 1723, 1724, 1726, 1727,
+ 1726, 1727, 1726, 1727, 1728, 1729, 1730, 1731,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+
+ 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732,
+ 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732,
+ 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732,
+ 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732,
+
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1662, 1662, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+
+ 1458, 1458, 1458, 1690, 1691, 1726, 1727, 1690,
+ 1691, 1690, 1691, 1690, 1691, 1733, 1734, 1735,
+ 1736, 1690, 1691, 1690, 1691, 1690, 1691, 1690,
+ 1691, 1458, 1458, 1737, 1458, 1458, 1458, 1458,
+
+ 1738, 1458, 1458, 1739, 1723, 1724, 1458, 1458,
+ 1723, 1724, 1723, 1724, 1723, 1724, 1723, 1724,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1740, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+
+ 1723, 1724, 1458, 1458, 1723, 1724, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1723,
+ 1724, 1723, 1724, 1458, 1723, 1724, 1458, 1458,
+ 1690, 1691, 1690, 1691, 1458, 1458, 1458, 1458,
+
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1723, 1724, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1741, 1458, 1458,
+ 1723, 1724, 1458, 1458, 1690, 1691, 1458, 1458,
+
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1539, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1723, 1724, 1723, 1724, 1458,
+ 1458, 1458, 1458, 1458, 1723, 1724, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1723, 1724, 1458, 1458,
+
+ 1458, 1458, 1458, 1458, 1723, 1724, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1742, 1742, 1742, 1458,
+ 1458, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+
+ 1724, 1723, 1724, 1458, 1458, 1458, 1723, 1724,
+ 1723, 1724, 1723, 1724, 1723, 1724, 1458, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1723,
+ 1724, 1723, 1724, 1723, 1724, 1723, 1724, 1458,
+ 1458, 1458, 1458, 1458, 1743, 1458, 1744, 1458,
+
+ 1458, 1458, 1458, 1745, 1746, 1745, 1458, 1458,
+ 1458, 1458, 1458, 1458, 1723, 1724, 1747, 1458,
+ 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1723,
+ 1724, 1723, 1724, 1458, 1458, 1458, 1458, 1458,
+
+ 1606, 1606, 1606, 1606, 1606, 1605, 1605, 1605,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1541, 1541,
+ 1541, 1541, 1541, 1541, 1542, 1542, 1542, 1542,
+ 1542, 1542, 1542, 1748, 1748, 1749, 1749, 1749,
+
+ 1542, 1542, 1542, 1542, 1749, 1749, 1749, 1749,
+ 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749,
+ 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720,
+ 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720,
+
+ 1720, 1720, 1720, 1720, 1720, 1749, 1749, 1720,
+ 1720, 1720, 1720, 1720, 1720, 1613, 1613, 1613,
+ 1748, 1749, 1749, 1749, 1749, 1685, 1750, 1750,
+ 1750, 1750, 1613, 1613, 1613, 1613, 1613, 1613,
+
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 221, 221, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 221, 1751,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1752, 1752, 1752, 1613, 1613, 1613,
+
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1753, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1616, 1752, 1752, 1752, 1752, 1752,
+ 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752,
+
+ 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752,
+ 1752, 1752, 1752, 1752, 1555, 1555, 1555, 1555,
+ 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752,
+ 1752, 1752, 1752, 1752, 1752, 1752, 1754, 1753,
+
+ 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755,
+ 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755,
+ 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755,
+ 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755,
+
+ 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755,
+ 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1756,
+ 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757,
+ 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757,
+
+ 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757,
+ 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757,
+ 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757,
+ 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1758,
+
+ 142, 138, 1759, 1760, 1761, 1762, 1763, 142,
+ 138, 142, 138, 142, 138, 1764, 1765, 1766,
+ 1767, 1290, 1292, 1293, 1768, 142, 138, 1768,
+ 1290, 1290, 1290, 1290, 1769, 1769, 1770, 1771,
+
+ 1772, 1773, 1772, 1773, 1772, 1773, 1772, 1773,
+ 1772, 1773, 1772, 1773, 1772, 1773, 1772, 1773,
+ 1772, 1773, 1772, 1773, 1772, 1773, 1772, 1773,
+ 1772, 1773, 1772, 1773, 1772, 1773, 1772, 1773,
+
+ 1772, 1773, 1772, 1773, 1774, 1775, 1775, 1775,
+ 1775, 1775, 1775, 1776, 1777, 1776, 1777, 1778,
+ 1778, 1778, 1779, 1780, 221, 221, 221, 221,
+ 221, 1781, 1782, 1782, 1782, 1783, 1781, 1782,
- 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
- 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
- 1824, 1824, 1824, 1824, 1823, 1823, 1823, 1823,
- 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+ 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
+ 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
+ 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
+ 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
- 1823, 1823, 1823, 1823, 1825, 1826, 202, 202,
- 202, 202, 202, 202, 202, 202, 1827, 1827,
- 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835,
- 1836, 1837, 202, 202, 202, 202, 202, 202,
-
- 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838,
- 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838,
- 1838, 1838, 508, 508, 508, 508, 508, 508,
- 1839, 1839, 1839, 508, 1840, 1841, 1842, 1843,
-
- 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851,
- 1852, 1853, 1854, 1854, 1854, 1854, 1854, 1854,
- 1854, 1854, 1854, 1854, 1854, 1854, 1854, 1854,
- 1854, 1854, 1854, 1854, 1854, 1854, 1854, 1854,
-
- 1854, 1854, 1854, 1854, 1854, 1854, 1855, 1855,
- 1855, 1855, 1855, 1856, 1856, 1856, 1857, 1858,
- 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859,
- 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859,
-
- 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1860,
- 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860,
- 1860, 1860, 1861, 1862, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 1863,
-
- 863, 863, 863, 863, 863, 863, 863, 863,
- 863, 863, 863, 863, 863, 863, 863, 863,
- 863, 863, 863, 863, 863, 863, 863, 863,
- 863, 863, 863, 863, 863, 202, 202, 202,
-
- 1864, 1864, 1864, 1865, 1866, 1866, 1866, 1866,
- 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866,
- 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866,
- 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866,
-
- 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866,
- 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866,
- 1866, 1866, 1866, 1867, 1865, 1865, 1864, 1864,
- 1864, 1864, 1865, 1865, 1864, 1864, 1865, 1865,
-
- 1868, 1869, 1869, 1869, 1869, 1869, 1869, 1870,
- 1871, 1871, 1869, 1869, 1869, 1869, 202, 1872,
- 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880,
- 1881, 1882, 202, 202, 202, 202, 1869, 1869,
-
- 1883, 1883, 1883, 1883, 1883, 1884, 1885, 1883,
- 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
- 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893,
- 1894, 1895, 1883, 1883, 1883, 1883, 1883, 202,
-
- 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896,
- 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896,
- 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896,
- 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896,
-
- 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896,
- 1896, 1897, 1897, 1897, 1897, 1897, 1897, 1898,
- 1898, 1897, 1897, 1898, 1898, 1897, 1897, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1896, 1896, 1896, 1897, 1896, 1896, 1896, 1896,
- 1896, 1896, 1896, 1896, 1897, 1898, 202, 202,
- 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906,
- 1907, 1908, 202, 202, 1909, 1910, 1910, 1910,
-
- 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911,
- 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911,
- 1912, 1911, 1911, 1911, 1911, 1911, 1911, 1913,
- 1913, 1913, 1911, 851, 1884, 1914, 1883, 1883,
-
- 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915,
- 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915,
- 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915,
- 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915,
-
- 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915,
- 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915,
- 1916, 1915, 1916, 1916, 1917, 1915, 1915, 1916,
- 1916, 1915, 1915, 1915, 1915, 1915, 1916, 1916,
-
- 1915, 1916, 1915, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 1915, 1915, 1918, 1919, 1919,
+ 1784, 1784, 1784, 1784, 1784, 1784, 221, 1785,
+ 221, 221, 221, 221, 221, 1785, 221, 221,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786,
- 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
- 1920, 1920, 1920, 1921, 1922, 1922, 1921, 1921,
- 1923, 1923, 1920, 1924, 1924, 1921, 1925, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786,
- 202, 1926, 1926, 1926, 1926, 1926, 1926, 202,
- 202, 1926, 1926, 1926, 1926, 1926, 1926, 202,
- 202, 1926, 1926, 1926, 1926, 1926, 1926, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
+ 1786, 1786, 1786, 1786, 1786, 1786, 1787, 1787,
+ 221, 221, 221, 221, 221, 221, 221, 1788,
+ 1789, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 1790,
- 1926, 1926, 1926, 1926, 1926, 1926, 1926, 202,
- 1926, 1926, 1926, 1926, 1926, 1926, 1926, 202,
- 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
- 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
+ 913, 913, 913, 913, 913, 913, 913, 913,
+ 913, 913, 913, 913, 913, 913, 913, 913,
+ 913, 913, 913, 913, 913, 913, 913, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
- 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
- 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
- 1784, 1784, 1784, 1927, 1784, 1784, 1784, 1784,
- 1784, 1784, 1784, 1928, 1929, 1929, 1929, 1929,
-
- 1930, 1930, 1930, 1930, 1784, 1931, 1932, 1932,
- 1933, 1934, 1935, 1935, 202, 202, 202, 202,
- 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943,
- 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951,
-
- 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959,
- 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967,
- 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975,
- 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983,
-
- 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991,
- 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
-
- 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016,
- 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016,
- 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016,
- 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016,
-
- 2016, 2016, 2016, 2017, 2017, 2018, 2017, 2017,
- 2018, 2017, 2017, 2019, 2017, 2020, 202, 202,
- 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028,
- 2029, 2030, 202, 202, 202, 202, 202, 202,
-
- 2031, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2031, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2031, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2031, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2031, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2031, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2031, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 2031, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
- 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032,
-
- 2032, 2032, 2032, 2032, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 866, 866, 866, 866, 866, 866, 866, 866,
- 866, 866, 866, 866, 866, 866, 866, 866,
-
- 866, 866, 866, 866, 866, 866, 866, 202,
- 202, 202, 202, 869, 869, 869, 869, 869,
- 869, 869, 869, 869, 869, 869, 869, 869,
- 869, 869, 869, 869, 869, 869, 869, 869,
-
- 869, 869, 869, 869, 869, 869, 869, 869,
- 869, 869, 869, 869, 869, 869, 869, 869,
- 869, 869, 869, 869, 869, 869, 869, 869,
- 869, 869, 869, 869, 202, 202, 202, 202,
-
- 2033, 2033, 2033, 2033, 2033, 2033, 2033, 2033,
- 2033, 2033, 2033, 2033, 2033, 2033, 2033, 2033,
- 2033, 2033, 2033, 2033, 2033, 2033, 2033, 2033,
- 2033, 2033, 2033, 2033, 2033, 2033, 2033, 2033,
-
- 2034, 2034, 2034, 2034, 2034, 2034, 2034, 2034,
- 2034, 2034, 2034, 2034, 2034, 2034, 2034, 2034,
- 2034, 2034, 2034, 2034, 2034, 2034, 2034, 2034,
- 2034, 2034, 2034, 2034, 2034, 2034, 2034, 2034,
-
- 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035,
- 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035,
- 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035,
- 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035,
-
- 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035,
- 2035, 2035, 2035, 2035, 2035, 2035, 1725, 1725,
- 2035, 1725, 2035, 1725, 1725, 2035, 2035, 2035,
- 2035, 2035, 2035, 2035, 2035, 2035, 2035, 1725,
-
- 2035, 1725, 2035, 1725, 1725, 2035, 2035, 1725,
- 1725, 1725, 2035, 2035, 2035, 2035, 2036, 2036,
- 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
- 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
+ 913, 913, 913, 913, 913, 913, 913, 221,
+ 913, 913, 913, 913, 913, 913, 913, 221,
+ 913, 913, 913, 913, 913, 913, 913, 221,
+ 913, 913, 913, 913, 913, 913, 913, 221,
- 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
- 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
+ 289, 289, 289, 289, 289, 289, 289, 289,
+ 289, 289, 289, 289, 289, 289, 289, 289,
+ 289, 289, 289, 289, 289, 289, 289, 289,
+ 289, 289, 289, 289, 289, 289, 289, 289,
+
+ 1791, 1791, 1792, 1793, 1792, 1793, 1791, 1791,
+ 1791, 1792, 1793, 1791, 1792, 1793, 1462, 1462,
+ 1462, 1462, 1462, 1462, 1462, 1462, 1461, 1794,
+ 1795, 1796, 1797, 1798, 1792, 1793, 1798, 1798,
+
+ 1799, 1800, 1730, 1731, 1730, 1731, 1730, 1731,
+ 1730, 1731, 1796, 1796, 1796, 1796, 1801, 1802,
+ 1796, 1803, 1804, 1805, 1805, 1804, 1804, 1804,
+ 1804, 1804, 1806, 1806, 1807, 1808, 1808, 1809,
+
+ 1810, 1808, 1811, 1812, 1812, 1813, 1813, 1813,
+ 1813, 1813, 1814, 1815, 1814, 1815, 1814, 1816,
+ 1751, 1751, 1817, 1818, 1818, 1819, 1820, 1819,
+ 1820, 1819, 1820, 1819, 1820, 1821, 221, 221,
+
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 221, 1822, 1822, 1822, 1822, 1823,
+
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822,
+ 1822, 1822, 1822, 1823, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+ 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+ 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+ 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+
+ 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+ 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+ 1823, 1823, 1823, 1823, 1823, 1823, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
+ 1824, 1824, 1824, 1824, 1825, 1825, 1825, 1825,
+
+ 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833,
+ 1834, 1835, 1834, 1835, 1834, 1835, 1834, 1835,
+ 1834, 1835, 1830, 1830, 1834, 1835, 1834, 1835,
+ 1834, 1835, 1834, 1835, 1836, 1837, 1838, 1838,
+
+ 1830, 1833, 1833, 1833, 1833, 1833, 1833, 1833,
+ 1833, 1833, 1839, 1840, 1841, 1842, 1843, 1843,
+ 1844, 1845, 1845, 1845, 1845, 1846, 1847, 1830,
+ 1848, 1848, 1848, 1849, 1850, 1851, 1852, 1853,
+
+ 221, 1854, 1855, 1854, 1855, 1854, 1855, 1854,
+ 1855, 1854, 1855, 1855, 1856, 1855, 1856, 1855,
+ 1856, 1855, 1856, 1855, 1856, 1855, 1856, 1855,
+ 1856, 1855, 1856, 1855, 1856, 1855, 1856, 1855,
+
+ 1856, 1855, 1856, 1854, 1855, 1856, 1855, 1856,
+ 1855, 1856, 1855, 1855, 1855, 1855, 1855, 1855,
+ 1856, 1856, 1855, 1856, 1856, 1855, 1856, 1856,
+ 1855, 1856, 1856, 1855, 1856, 1856, 1855, 1855,
+
+ 1855, 1855, 1855, 1854, 1855, 1854, 1855, 1854,
+ 1855, 1855, 1855, 1855, 1855, 1855, 1854, 1855,
+ 1855, 1855, 1855, 1855, 1856, 1857, 1857, 221,
+ 221, 1858, 1858, 1859, 1859, 1860, 1861, 1862,
+
+ 1863, 1864, 1865, 1864, 1865, 1864, 1865, 1864,
+ 1865, 1864, 1865, 1865, 1866, 1865, 1866, 1865,
+ 1866, 1865, 1866, 1865, 1866, 1865, 1866, 1865,
+ 1866, 1865, 1866, 1865, 1866, 1865, 1866, 1865,
+
+ 1866, 1865, 1866, 1864, 1865, 1866, 1865, 1866,
+ 1865, 1866, 1865, 1865, 1865, 1865, 1865, 1865,
+ 1866, 1866, 1865, 1866, 1866, 1865, 1866, 1866,
+ 1865, 1866, 1866, 1865, 1866, 1866, 1865, 1865,
+
+ 1865, 1865, 1865, 1864, 1865, 1864, 1865, 1864,
+ 1865, 1865, 1865, 1865, 1865, 1865, 1864, 1865,
+ 1865, 1865, 1865, 1865, 1866, 1864, 1864, 1866,
+ 1866, 1866, 1866, 1867, 1868, 1869, 1870, 1871,
+
+ 221, 221, 221, 221, 221, 1872, 1872, 1872,
+ 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872,
+ 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872,
+ 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872,
+
+ 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872,
+ 1872, 1872, 1872, 1872, 1872, 1873, 1874, 1875,
+ 221, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+
+ 1876, 1876, 1876, 1876, 1877, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876,
+ 1876, 1876, 1876, 1876, 1876, 1876, 1876, 221,
+ 1878, 1878, 1879, 1879, 1879, 1879, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+
+ 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
+ 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
+ 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
+ 1882, 1882, 1882, 1883, 1883, 1883, 1883, 1883,
+
+ 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884,
+ 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884,
+ 1885, 1885, 1885, 1885, 1885, 1885, 1885, 1885,
+ 1885, 1885, 1885, 1885, 1885, 1885, 1885, 1885,
+
+ 1885, 1885, 1885, 1885, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 1825,
+ 1886, 1886, 1886, 1886, 1886, 1886, 1886, 1886,
+ 1886, 1886, 1886, 1886, 1886, 1886, 1886, 1886,
+
+ 1887, 1887, 1887, 1887, 1887, 1887, 1887, 1887,
+ 1887, 1887, 1887, 1887, 1887, 1887, 1887, 1887,
+ 1887, 1887, 1887, 1887, 1887, 1887, 1887, 1887,
+ 1887, 1887, 1887, 1887, 1887, 1888, 1888, 221,
+
+ 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889,
+ 1889, 1889, 1890, 1890, 1890, 1890, 1890, 1890,
+ 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890,
+ 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890,
+
+ 1890, 1890, 1890, 1890, 1891, 1891, 1891, 1891,
+ 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892,
+ 1893, 1894, 1894, 1894, 1894, 1894, 1894, 1894,
+ 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894,
+
+ 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895,
+ 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895,
+ 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895,
+ 1895, 1895, 1895, 1895, 1896, 1896, 1897, 1878,
+
+ 1879, 1879, 1879, 1879, 1879, 1879, 1879, 1879,
+ 1879, 1879, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1898,
+ 1880, 1898, 1880, 1880, 1880, 1880, 1880, 1880,
+
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1894, 1894, 1894, 1894, 1894, 1894, 1894,
+ 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894,
+
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1893, 1893, 1893, 1893,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1900,
+
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1893,
+ 1893, 1893, 1893, 1880, 1880, 1880, 1880, 1880,
+
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+
+ 1880, 1880, 1890, 1880, 1880, 1880, 1880, 1890,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1890, 1880, 1880, 1880, 1880, 1880, 1893, 1893,
+
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880,
+ 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1893,
+
+ 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901,
+ 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901,
+ 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901,
+ 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901,
+
+ 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901,
+ 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901,
+ 1901, 1901, 1901, 1901, 1901, 1901, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+
+ 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903,
+ 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903,
+ 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903,
+ 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903,
+
+ 1903, 1903, 1903, 1903, 1903, 1903, 1904, 1904,
+ 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904,
+ 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904,
+ 1904, 1904, 1904, 1904, 1905, 1905, 1905, 1905,
+
+ 1905, 1905, 1905, 1905, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1907, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1910, 1910, 1910, 1910, 1910,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1911, 1911, 1911,
+
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 1913, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+
+ 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912,
+ 1912, 1912, 1912, 1912, 1912, 221, 221, 221,
+ 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914,
+ 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914,
+
+ 1914, 1914, 1915, 1915, 1914, 1914, 1914, 1914,
+ 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914,
+ 1914, 1914, 1914, 1914, 1915, 1914, 1914, 1914,
+ 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914,
+
+ 1914, 1915, 1914, 1914, 1914, 1915, 1914, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916,
+ 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916,
+
+ 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916,
+ 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916,
+ 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916,
+ 1917, 1917, 1917, 1917, 1917, 1917, 1918, 1919,
+
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+ 1920, 1920, 1920, 1920, 1921, 1922, 1923, 1924,
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+ 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920,
+
+ 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932,
+ 1933, 1934, 1920, 1920, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 303, 304, 303, 304, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 303, 304,
+
+ 307, 308, 303, 304, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 1935, 289,
+ 1936, 1936, 1936, 1937, 1938, 1938, 1938, 1938,
+ 1938, 1938, 1938, 1938, 289, 289, 1937, 1939,
+
+ 303, 304, 303, 304, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 303, 304,
+ 303, 304, 303, 304, 303, 304, 303, 304,
+ 309, 310, 309, 310, 1940, 1940, 1941, 1938,
+
+ 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
+ 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
+ 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
+ 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
+
+ 1942, 1942, 1942, 1942, 1942, 1942, 1943, 1943,
+ 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943,
+ 1944, 1944, 1945, 1946, 1947, 1947, 1947, 1946,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948,
+ 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949,
+ 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1950,
+ 1950, 1950, 1950, 1802, 1802, 1802, 1802, 1802,
+
+ 1951, 1951, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1290, 1290, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1769, 1290, 1290, 1290, 1290, 1290, 1290, 1290,
+ 1290, 1292, 1293, 1292, 1293, 1952, 1292, 1293,
+
+ 1292, 1293, 1292, 1293, 1292, 1293, 1292, 1293,
+ 1802, 1953, 1953, 1292, 1293, 1954, 1955, 1956,
+ 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964,
+ 1963, 1964, 1963, 1964, 1963, 1964, 1963, 1964,
+
+ 1957, 1958, 1957, 1958, 1957, 1958, 1957, 1958,
+ 1957, 1958, 1965, 1966, 1967, 1968, 1969, 1970,
+ 1971, 1972, 1973, 1974, 1975, 1976, 1975, 1976,
+ 1977, 1978, 1979, 1980, 1979, 1980, 1979, 1980,
+
+ 1981, 1982, 1979, 1980, 1983, 1984, 1985, 1986,
+ 1987, 1986, 1987, 221, 221, 221, 221, 221,
+ 1981, 1982, 221, 1988, 221, 1988, 1981, 1982,
+ 1981, 1982, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 1989, 1989, 1989, 1986, 1987, 1990,
+ 1991, 1991, 1955, 1992, 1992, 1992, 1992, 1992,
+
+ 1993, 1993, 1994, 1993, 1993, 1993, 1995, 1993,
+ 1993, 1993, 1993, 1994, 1993, 1993, 1993, 1993,
+ 1993, 1993, 1993, 1993, 1993, 1993, 1993, 1993,
+ 1993, 1993, 1993, 1993, 1993, 1993, 1993, 1993,
+
+ 1993, 1993, 1993, 1996, 1996, 1994, 1994, 1996,
+ 1997, 1997, 1997, 1997, 1998, 221, 221, 221,
+ 1999, 1999, 1999, 1999, 1999, 1999, 853, 853,
+ 1497, 2000, 221, 221, 221, 221, 221, 221,
+
+ 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001,
+ 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001,
+ 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001,
+ 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001,
+
+ 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001,
+ 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001,
+ 2001, 2001, 2002, 2003, 2004, 2004, 2005, 2005,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2006, 2006, 2007, 2007, 2007, 2007, 2007, 2007,
+ 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007,
+ 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007,
+ 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007,
+
+ 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007,
+ 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007,
+ 2007, 2007, 2007, 2007, 2006, 2006, 2006, 2006,
+ 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006,
+
+ 2006, 2006, 2006, 2006, 2008, 2009, 221, 221,
+ 221, 221, 221, 221, 221, 221, 2010, 2010,
+ 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
+ 2019, 2020, 221, 221, 221, 221, 221, 221,
+
+ 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021,
+ 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021,
+ 2021, 2021, 542, 542, 542, 542, 542, 542,
+ 2022, 2022, 2022, 542, 2023, 2024, 2025, 2026,
+
+ 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034,
+ 2035, 2036, 2037, 2037, 2037, 2037, 2037, 2037,
2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
- 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037,
- 2037, 2037, 2037, 2038, 2038, 2038, 1733, 1733,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
-
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
-
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 2039, 2039, 2039, 2039, 2039, 2039,
- 2039, 2039, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 2040, 2041, 2042, 2043, 2044, 2045, 2045, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 2046, 2047, 2048, 2049, 2050,
- 202, 202, 202, 202, 202, 2051, 2052, 2053,
-
- 2054, 2054, 2054, 2054, 2054, 2054, 2054, 2054,
- 2054, 2055, 2053, 2053, 2053, 2053, 2053, 2053,
- 2053, 2053, 2053, 2053, 2053, 2053, 2053, 301,
- 2053, 2053, 2053, 2053, 2053, 301, 2053, 301,
-
- 2053, 2053, 301, 2053, 2053, 301, 2053, 2053,
- 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2054,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
-
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
-
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2057, 2057, 2057, 2057, 2057, 2057,
- 2057, 2057, 2057, 2057, 2057, 2057, 2057, 2057,
-
- 2057, 2057, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
-
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 1671, 1366,
-
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
-
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 348, 348, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
-
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058,
- 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058,
-
- 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058,
- 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2059, 340, 348, 348,
-
- 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060,
- 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060,
- 2061, 2062, 2063, 2064, 2065, 2066, 2066, 2067,
- 2068, 2069, 202, 202, 202, 202, 202, 202,
-
- 173, 173, 173, 173, 1219, 1219, 1219, 1107,
- 1107, 1107, 1107, 1107, 1107, 1107, 1763, 1763,
- 2070, 2071, 2071, 2072, 2072, 2073, 2074, 2073,
- 2074, 2073, 2074, 2073, 2074, 2073, 2074, 2073,
-
- 2074, 2073, 2074, 2073, 2074, 1683, 1683, 2075,
- 2076, 2070, 2070, 2070, 2070, 2072, 2072, 2072,
- 2077, 2078, 2079, 202, 2080, 2081, 2082, 2082,
- 2071, 1419, 1420, 1419, 1420, 1419, 1420, 2083,
-
- 2070, 2070, 2084, 2085, 2086, 2087, 2088, 202,
- 2070, 1422, 1380, 2070, 202, 202, 202, 202,
- 2056, 2056, 2056, 2089, 2056, 348, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
-
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056,
- 2056, 2056, 2056, 2056, 2056, 348, 348, 2090,
-
- 202, 2082, 2070, 2083, 1422, 1380, 2070, 2091,
- 1419, 1420, 2070, 2084, 2077, 2085, 2079, 2092,
- 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100,
- 2101, 2102, 2081, 2080, 2103, 2088, 2104, 2082,
-
- 2070, 2105, 2105, 2105, 2105, 2105, 2105, 2105,
- 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105,
- 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105,
- 2105, 2105, 2105, 2106, 2070, 2107, 2108, 2072,
-
- 2108, 2109, 2109, 2109, 2109, 2109, 2109, 2109,
- 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109,
- 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109,
- 2109, 2109, 2109, 2106, 2088, 2107, 2088, 2110,
-
- 2111, 2112, 1419, 1420, 2113, 2114, 2115, 2116,
- 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116,
- 2117, 2115, 2115, 2115, 2115, 2115, 2115, 2115,
- 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115,
-
- 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115,
- 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115,
- 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115,
- 2115, 2115, 2115, 2115, 2115, 2115, 2118, 2118,
-
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706,
- 1706, 1706, 1706, 1706, 1706, 1706, 1706, 202,
-
- 202, 202, 1706, 1706, 1706, 1706, 1706, 1706,
- 202, 202, 1706, 1706, 1706, 1706, 1706, 1706,
- 202, 202, 1706, 1706, 1706, 1706, 1706, 1706,
- 202, 202, 1706, 1706, 1706, 202, 202, 202,
-
- 2119, 1422, 2088, 2108, 1679, 1422, 1422, 202,
- 1443, 1418, 1418, 1418, 1418, 1443, 1443, 202,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 2120, 2120, 2120, 2121, 51, 2122, 2122,
-
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 202, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
-
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 202,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 202, 2123, 2123, 202, 2123,
-
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 202, 202,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 202, 202,
-
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
-
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123,
- 2123, 2123, 2123, 202, 202, 202, 202, 202,
-
- 2124, 2125, 2124, 202, 202, 202, 202, 2126,
- 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126,
- 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126,
- 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126,
-
- 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126,
- 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126,
- 2126, 2126, 2126, 2126, 202, 202, 202, 2127,
- 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127,
-
- 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128,
- 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128,
- 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128,
- 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128,
-
- 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128,
- 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128,
- 2128, 2128, 2128, 2128, 2128, 2129, 2129, 2129,
- 2129, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
-
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2129, 2131, 2132, 2133, 2133, 202,
- 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543,
- 1543, 1543, 1543, 1543, 1596, 202, 202, 202,
-
- 2132, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
- 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
-
- 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
- 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
- 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465,
- 1465, 1465, 1465, 1465, 1465, 1222, 202, 202,
-
- 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134,
- 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134,
- 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134,
- 2134, 2134, 2134, 2134, 2134, 202, 202, 202,
-
- 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135,
- 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135,
- 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135,
- 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135,
-
- 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135,
- 2135, 2135, 2135, 2135, 2135, 2135, 2135, 2135,
- 2135, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1107, 2136, 2136, 2136, 2136, 2136, 2136, 2136,
- 2136, 2136, 2136, 2136, 2136, 2136, 2136, 2136,
- 2136, 2136, 2136, 2136, 2136, 2136, 2136, 2136,
- 2136, 2136, 2136, 2136, 202, 202, 202, 202,
-
- 2137, 2137, 2137, 2137, 2137, 2137, 2137, 2137,
- 2137, 2137, 2137, 2137, 2137, 2137, 2137, 2137,
- 2137, 2137, 2137, 2137, 2137, 2137, 2137, 2137,
- 2137, 2137, 2137, 2137, 2137, 2137, 2137, 2138,
-
- 2139, 2139, 2139, 2139, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 2140, 2140, 2140,
- 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141,
- 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141,
-
- 2141, 2142, 2141, 2141, 2141, 2141, 2141, 2141,
- 2141, 2141, 2142, 202, 202, 202, 202, 202,
- 2143, 2143, 2143, 2143, 2143, 2143, 2143, 2143,
- 2143, 2143, 2143, 2143, 2143, 2143, 2143, 2143,
-
- 2143, 2143, 2143, 2143, 2143, 2143, 2143, 2143,
- 2143, 2143, 2143, 2143, 2143, 2143, 2143, 2143,
- 2143, 2143, 2143, 2143, 2143, 2143, 2144, 2144,
- 2144, 2144, 2144, 202, 202, 202, 202, 202,
-
- 2145, 2145, 2145, 2145, 2145, 2145, 2145, 2145,
- 2145, 2145, 2145, 2145, 2145, 2145, 2145, 2145,
- 2145, 2145, 2145, 2145, 2145, 2145, 2145, 2145,
- 2145, 2145, 2145, 2145, 2145, 2145, 202, 2146,
-
- 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
- 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
- 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
- 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-
- 2147, 2147, 2147, 2147, 202, 202, 202, 202,
- 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
- 2148, 2149, 2149, 2149, 2149, 2149, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2150, 2150, 2150, 2150, 2150, 2150, 2150, 2150,
- 2150, 2150, 2150, 2150, 2150, 2150, 2150, 2150,
- 2150, 2150, 2150, 2150, 2150, 2150, 2150, 2150,
- 2150, 2150, 2150, 2150, 2150, 2150, 2150, 2150,
-
- 2150, 2150, 2150, 2150, 2150, 2150, 2151, 2151,
- 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152,
- 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152,
- 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152,
-
- 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152,
- 2152, 2152, 2152, 2152, 2152, 2152, 2153, 2153,
- 2154, 2154, 2154, 2154, 2154, 2154, 2154, 2154,
- 2154, 2154, 2154, 2154, 2154, 2154, 2154, 2154,
-
- 2154, 2154, 2154, 2154, 2154, 2154, 2154, 2154,
- 2154, 2154, 2154, 2154, 2154, 2154, 2154, 2154,
- 2154, 2154, 2154, 2154, 2154, 2154, 2154, 2154,
- 2154, 2154, 2154, 2154, 2154, 2154, 2154, 2154,
-
- 2155, 2155, 2155, 2155, 2155, 2155, 2155, 2155,
- 2155, 2155, 2155, 2155, 2155, 2155, 2155, 2155,
- 2155, 2155, 2155, 2155, 2155, 2155, 2155, 2155,
- 2155, 2155, 2155, 2155, 2155, 2155, 202, 202,
-
- 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163,
- 2164, 2165, 202, 202, 202, 202, 202, 202,
- 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166,
- 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166,
-
- 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166,
- 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166,
- 2166, 2166, 2166, 2166, 202, 202, 202, 202,
- 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167,
-
- 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167,
- 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167,
- 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167,
- 2167, 2167, 2167, 2167, 202, 202, 202, 202,
-
- 2168, 2168, 2168, 2168, 2168, 2168, 2168, 2168,
- 2168, 2168, 2168, 2168, 2168, 2168, 2168, 2168,
- 2168, 2168, 2168, 2168, 2168, 2168, 2168, 2168,
- 2168, 2168, 2168, 2168, 2168, 2168, 2168, 2168,
-
- 2168, 2168, 2168, 2168, 2168, 2168, 2168, 2168,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169,
- 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169,
-
- 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169,
- 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169,
- 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169,
- 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169,
-
- 2169, 2169, 2169, 2169, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 2170,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
-
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 2171, 2171, 2171, 2171, 2171, 2171, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2172, 2172, 2172, 2172, 2172, 2172, 301, 301,
- 2172, 301, 2172, 2172, 2172, 2172, 2172, 2172,
- 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172,
- 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172,
-
- 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172,
- 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172,
- 2172, 2172, 2172, 2172, 2172, 2172, 301, 2172,
- 2172, 301, 301, 301, 2172, 301, 301, 2172,
-
- 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173,
- 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173,
- 2173, 2173, 2173, 2173, 2173, 2173, 301, 2174,
- 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175,
-
- 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176,
- 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176,
- 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2177,
- 2177, 2178, 2178, 2178, 2178, 2178, 2178, 2178,
-
- 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179,
- 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179,
- 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179,
- 2179, 2179, 2179, 2179, 2179, 2179, 2179, 301,
-
- 301, 301, 301, 301, 301, 301, 301, 2180,
- 2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181,
- 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181,
- 2181, 2181, 2181, 301, 2181, 2181, 301, 301,
- 301, 301, 301, 2182, 2182, 2182, 2182, 2182,
-
- 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183,
- 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183,
- 2183, 2183, 2183, 2183, 2183, 2183, 2184, 2184,
- 2184, 2184, 2185, 2185, 301, 301, 301, 2186,
-
- 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187,
- 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187,
- 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187,
- 2187, 2187, 301, 301, 301, 301, 301, 2188,
-
- 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189,
- 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189,
- 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189,
- 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189,
-
- 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190,
- 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190,
- 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190,
- 301, 301, 301, 301, 2191, 2191, 2190, 2190,
-
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
- 301, 301, 2191, 2191, 2191, 2191, 2191, 2191,
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
-
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
- 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191,
-
- 2192, 2193, 2193, 2193, 301, 2193, 2193, 301,
- 301, 301, 301, 301, 2193, 2194, 2193, 2195,
- 2192, 2192, 2192, 2192, 301, 2192, 2192, 2192,
- 301, 2192, 2192, 2192, 2192, 2192, 2192, 2192,
-
- 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192,
- 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192,
- 2192, 2192, 2192, 2192, 2196, 2196, 301, 301,
- 2195, 2197, 2194, 301, 301, 301, 301, 2198,
-
- 2199, 2200, 2201, 2202, 2203, 2203, 2203, 2203,
- 2204, 301, 301, 301, 301, 301, 301, 301,
- 2205, 2205, 2205, 2205, 2205, 2205, 2206, 2206,
- 2207, 301, 301, 301, 301, 301, 301, 301,
-
- 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208,
- 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208,
- 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208,
- 2208, 2208, 2208, 2208, 2208, 2209, 2209, 2210,
-
- 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211,
- 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211,
- 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211,
- 2211, 2211, 2211, 2211, 2211, 2212, 2212, 2212,
-
- 2213, 2213, 2213, 2213, 2213, 2214, 2215, 2214,
- 2216, 2214, 2214, 2215, 2215, 2217, 2214, 2214,
- 2214, 2214, 2214, 2213, 2213, 2213, 2213, 2217,
- 2213, 2213, 2213, 2213, 2213, 2214, 2213, 2213,
-
- 2213, 2214, 2215, 2215, 2214, 2218, 2219, 301,
- 301, 301, 301, 2220, 2220, 2220, 2220, 2221,
- 2222, 2222, 2222, 2222, 2222, 2222, 2223, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
+ 2037, 2037, 2037, 2037, 2037, 2037, 2038, 2038,
+ 2038, 2038, 2038, 2039, 2039, 2039, 2040, 2041,
+ 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042,
+ 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042,
+
+ 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2043,
+ 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043,
+ 2043, 2043, 2044, 2045, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 2046,
+
+ 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 221, 221, 221,
+
+ 2047, 2047, 2047, 2048, 2049, 2049, 2049, 2049,
+ 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049,
+ 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049,
+ 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049,
+
+ 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049,
+ 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049,
+ 2049, 2049, 2049, 2050, 2048, 2048, 2047, 2047,
+ 2047, 2047, 2048, 2048, 2047, 2047, 2048, 2048,
+
+ 2051, 2052, 2052, 2052, 2052, 2052, 2052, 2053,
+ 2054, 2054, 2052, 2052, 2052, 2052, 221, 2055,
+ 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063,
+ 2064, 2065, 221, 221, 221, 221, 2052, 2052,
+
+ 2066, 2066, 2066, 2066, 2066, 2067, 2068, 2066,
+ 2066, 2066, 2066, 2066, 2066, 2066, 2066, 2066,
+ 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076,
+ 2077, 2078, 2066, 2066, 2066, 2066, 2066, 221,
+
+ 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079,
+ 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079,
+ 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079,
+ 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079,
+
+ 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079,
+ 2079, 2080, 2080, 2080, 2080, 2080, 2080, 2081,
+ 2081, 2080, 2080, 2081, 2081, 2080, 2080, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2082, 2082, 2082, 2080, 2082, 2082, 2082, 2082,
+ 2082, 2082, 2082, 2082, 2080, 2081, 221, 221,
+ 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090,
+ 2091, 2092, 221, 221, 2093, 2094, 2094, 2094,
+
+ 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095,
+ 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095,
+ 2096, 2095, 2095, 2095, 2095, 2095, 2095, 2097,
+ 2097, 2097, 2095, 891, 2067, 2098, 2066, 2066,
+
+ 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099,
+ 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099,
+ 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099,
+ 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099,
+
+ 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099,
+ 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099,
+ 2100, 2099, 2100, 2100, 2101, 2099, 2099, 2100,
+ 2100, 2099, 2099, 2099, 2099, 2099, 2100, 2100,
+
+ 2099, 2100, 2099, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 2099, 2099, 2102, 2103, 2103,
+
+ 2104, 2104, 2104, 2104, 2104, 2104, 2104, 2104,
+ 2104, 2104, 2104, 2105, 2106, 2106, 2105, 2105,
+ 2107, 2107, 2104, 2108, 2108, 2105, 2109, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 2110, 2110, 2110, 2110, 2110, 2110, 221,
+ 221, 2110, 2110, 2110, 2110, 2110, 2110, 221,
+ 221, 2110, 2110, 2110, 2110, 2110, 2110, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2110, 2110, 2110, 2110, 2110, 2110, 2110, 221,
+ 2110, 2110, 2110, 2110, 2110, 2110, 2110, 221,
+ 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962,
+ 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962,
+
+ 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962,
+ 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962,
+ 1962, 1962, 1962, 2111, 1962, 1962, 1962, 1962,
+ 1962, 1962, 1962, 2112, 2113, 2113, 2113, 2113,
+
+ 2114, 2114, 2114, 2114, 1962, 2115, 2116, 2116,
+ 2117, 2118, 2119, 2119, 221, 221, 221, 221,
+ 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127,
+ 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135,
+
+ 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143,
+ 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151,
+ 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159,
+ 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167,
+
+ 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175,
+ 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183,
+ 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191,
+ 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199,
+
+ 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200,
+ 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200,
+ 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200,
+ 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200,
+
+ 2200, 2200, 2200, 2201, 2201, 2202, 2201, 2201,
+ 2202, 2201, 2201, 2203, 2201, 2204, 221, 221,
+ 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212,
+ 2213, 2214, 221, 221, 221, 221, 221, 221,
+
+ 2215, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2215, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2215, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2215, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2215, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2215, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2215, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 2215, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+ 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216,
+
+ 2216, 2216, 2216, 2216, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 908, 908, 908, 908, 908, 908, 908, 908,
+ 908, 908, 908, 908, 908, 908, 908, 908,
+
+ 908, 908, 908, 908, 908, 908, 908, 221,
+ 221, 221, 221, 911, 911, 911, 911, 911,
+ 911, 911, 911, 911, 911, 911, 911, 911,
+ 911, 911, 911, 911, 911, 911, 911, 911,
+
+ 911, 911, 911, 911, 911, 911, 911, 911,
+ 911, 911, 911, 911, 911, 911, 911, 911,
+ 911, 911, 911, 911, 911, 911, 911, 911,
+ 911, 911, 911, 911, 221, 221, 221, 221,
+
+ 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217,
+ 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217,
+ 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217,
+ 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217,
+
+ 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218,
+ 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218,
+ 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218,
+ 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218,
+
+ 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219,
+ 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219,
+ 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219,
+ 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219,
+
+ 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219,
+ 2219, 2219, 2219, 2219, 2219, 2219, 1903, 1903,
+ 2219, 1903, 2219, 1903, 1903, 2219, 2219, 2219,
+ 2219, 2219, 2219, 2219, 2219, 2219, 2219, 1903,
+
+ 2219, 1903, 2219, 1903, 1903, 2219, 2219, 1903,
+ 1903, 1903, 2219, 2219, 2219, 2219, 2220, 2220,
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+
+ 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221,
+ 2221, 2221, 2221, 2222, 2222, 2222, 2223, 2223,
+ 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
+ 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
@@ -3484,806 +3048,730 @@ static const unsigned short uc_property_trie[] = {
2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
- 2224, 2224, 2224, 2224, 2224, 2224, 301, 301,
- 301, 2225, 2225, 2225, 2225, 2225, 2225, 2225,
-
- 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226,
- 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226,
- 2226, 2226, 2226, 2226, 2226, 2226, 301, 301,
- 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227,
-
- 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228,
- 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228,
- 2228, 2228, 2228, 301, 301, 301, 301, 301,
- 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229,
-
- 2230, 2231, 2230, 2231, 2231, 2231, 2230, 2230,
- 2230, 2231, 2230, 2230, 2231, 2230, 2231, 2231,
- 2230, 2231, 301, 301, 301, 301, 301, 301,
- 301, 2232, 2232, 2232, 2232, 301, 301, 301,
-
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 2233, 2233, 2233, 2233, 2234, 2234, 2235,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236,
- 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236,
- 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236,
- 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236,
-
- 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236,
- 2236, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237,
- 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237,
- 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237,
- 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237,
-
- 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237,
- 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237,
- 2237, 2237, 2237, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238,
- 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238,
- 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238,
- 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238,
-
- 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238,
- 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238,
- 2238, 2238, 2238, 301, 301, 301, 301, 301,
- 301, 301, 2239, 2239, 2239, 2239, 2239, 2239,
-
- 2240, 2241, 2241, 2241, 2241, 2241, 2241, 2241,
- 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241,
- 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241,
- 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241,
-
- 2241, 2241, 2242, 2241, 2243, 2243, 2243, 2243,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251,
- 2252, 2253, 301, 301, 301, 301, 301, 301,
-
- 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261,
- 2262, 2263, 2263, 2263, 2263, 2263, 2263, 2263,
- 2263, 2263, 2263, 2263, 2263, 2263, 2263, 2263,
- 2263, 2263, 2263, 2263, 2263, 2263, 2263, 301,
-
- 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264,
- 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264,
- 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264,
- 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264,
-
- 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264,
- 2264, 2264, 301, 2265, 2265, 2266, 301, 301,
- 2264, 2264, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267,
- 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267,
- 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267,
- 2267, 2267, 2267, 2267, 2267, 2268, 2268, 2268,
-
- 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2267,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 2269, 2269, 2269, 2270, 2269, 2269, 2269, 2269,
- 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269,
-
- 2269, 2269, 2269, 2269, 2269, 2271, 2272, 2272,
- 2273, 2273, 2273, 2272, 2273, 2272, 2272, 2272,
- 2272, 2274, 2274, 2274, 2275, 2276, 2276, 2276,
- 2276, 2276, 301, 301, 301, 301, 301, 301,
-
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 2277, 2278, 2277, 2277, 2279, 2279, 2279, 2278,
- 2277, 2279, 2279, 2277, 2277, 2279, 2277, 2277,
-
- 2278, 2277, 2279, 2279, 2277, 2280, 2280, 2280,
- 2280, 2281, 2282, 2283, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284,
- 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284,
- 2284, 2284, 2284, 2284, 2284, 2284, 2284, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2285, 2286, 2285, 2287, 2287, 2287, 2287, 2287,
- 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287,
- 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287,
- 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287,
- 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287,
- 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287,
- 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287,
- 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286,
- 2286, 2286, 2286, 2286, 2286, 2286, 2288, 2289,
- 2289, 2290, 2290, 2290, 2290, 2290, 202, 202,
- 202, 202, 2291, 2292, 2293, 2294, 2295, 2296,
- 2297, 2298, 2299, 2300, 2300, 2300, 2300, 2300,
- 2300, 2300, 2300, 2300, 2300, 2300, 2301, 2302,
- 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 2311,
- 2312, 2312, 2313, 2314, 2314, 2314, 2314, 2314,
- 2314, 2314, 2314, 2314, 2314, 2314, 2314, 2314,
- 2314, 2314, 2314, 2314, 2314, 2314, 2314, 2314,
- 2314, 2314, 2315, 2314, 2315, 2314, 2314, 2314,
- 2314, 2314, 2314, 2314, 2314, 2314, 2314, 2314,
- 2314, 2314, 2314, 2315, 2314, 2314, 2314, 2314,
- 2313, 2313, 2313, 2312, 2312, 2312, 2312, 2313,
- 2313, 2316, 2317, 2318, 2318, 2319, 2320, 2320,
- 2320, 2320, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 2321, 202, 202,
- 2322, 2322, 2322, 2322, 2322, 2322, 2322, 2322,
+ 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224,
+ 2224, 2224, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 2225, 2226, 2227, 2228, 2229, 2230, 2231, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 2232, 2233, 2234, 2235, 2236,
+ 221, 221, 221, 221, 221, 2237, 2238, 2239,
+
+ 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240,
+ 2240, 2241, 2239, 2239, 2239, 2239, 2239, 2239,
+ 2239, 2239, 2239, 2239, 2239, 2239, 2239, 323,
+ 2239, 2239, 2239, 2239, 2239, 323, 2239, 323,
+
+ 2239, 2239, 323, 2239, 2239, 323, 2239, 2239,
+ 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2240,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2243, 2243, 2243, 2243, 2243, 2243,
+ 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243,
+
+ 2243, 2243, 489, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2244, 2244,
+
+ 2244, 2244, 2244, 2244, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2245, 1422,
+
+ 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246,
+ 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 437, 437, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 437, 437, 437, 437, 437, 437, 437, 2246,
+ 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247,
+ 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247,
+
+ 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247,
+ 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2244, 2244, 2248, 363, 2246, 2246,
+
+ 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249,
+ 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249,
+ 2250, 2251, 2252, 2253, 2254, 2255, 2255, 2256,
+ 2257, 2258, 221, 221, 221, 221, 221, 221,
+
+ 288, 288, 288, 288, 1273, 1273, 1273, 1155,
+ 1155, 1155, 1155, 1155, 1155, 1155, 1941, 1941,
+ 2259, 2260, 2260, 2261, 2261, 2262, 2263, 2262,
+ 2263, 2264, 2265, 2264, 2265, 2264, 2265, 2264,
+
+ 2265, 2264, 2265, 2264, 2265, 2266, 2266, 2267,
+ 2268, 2259, 2259, 2259, 2259, 2261, 2261, 2261,
+ 2269, 2270, 2271, 221, 2272, 2273, 2274, 2274,
+ 2260, 2275, 2276, 2275, 2276, 2277, 2278, 2279,
+
+ 2259, 2259, 2280, 2281, 2282, 2283, 2284, 221,
+ 2259, 2285, 2286, 2259, 221, 221, 221, 221,
+ 2244, 2242, 2244, 2287, 2244, 437, 2244, 2242,
+ 2244, 2242, 2244, 2242, 2244, 2242, 2244, 2242,
+
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242,
+ 2242, 2242, 2242, 2242, 2242, 437, 437, 2288,
+
+ 221, 2289, 2290, 2291, 2292, 2293, 2290, 2294,
+ 2295, 2296, 2290, 2297, 2298, 2299, 2300, 2301,
+ 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309,
+ 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2289,
+
+ 2290, 2317, 2317, 2317, 2317, 2317, 2317, 2317,
+ 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2317,
+ 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2317,
+ 2317, 2317, 2317, 2318, 2290, 2319, 2320, 2321,
+
+ 2320, 2322, 2322, 2322, 2322, 2322, 2322, 2322,
2322, 2322, 2322, 2322, 2322, 2322, 2322, 2322,
2322, 2322, 2322, 2322, 2322, 2322, 2322, 2322,
- 2322, 202, 202, 202, 202, 202, 202, 202,
- 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330,
- 2331, 2332, 202, 202, 202, 202, 202, 202,
-
- 2333, 2333, 2333, 2334, 2334, 2334, 2334, 2334,
- 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334,
- 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334,
- 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334,
- 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2335,
- 2336, 2336, 2336, 2336, 2337, 2336, 2338, 2338,
- 2336, 2336, 2336, 2339, 2339, 202, 2340, 2341,
- 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349,
- 2350, 2351, 2351, 2351, 2352, 2353, 2353, 2354,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355,
- 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355,
- 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355,
- 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355,
- 2355, 2355, 2355, 2356, 2357, 2358, 2355, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2359, 2359, 2360, 2361, 2361, 2361, 2361, 2361,
- 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361,
- 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361,
- 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361,
- 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361,
- 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361,
- 2361, 2361, 2361, 2360, 2360, 2360, 2359, 2359,
- 2359, 2359, 2359, 2359, 2359, 2359, 2359, 2360,
- 2362, 2361, 2363, 2363, 2361, 2364, 2364, 2365,
- 2366, 2367, 2368, 2367, 2367, 2369, 2370, 2371,
- 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379,
- 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2386,
- 202, 2387, 2387, 2387, 2387, 2387, 2387, 2387,
- 2387, 2387, 2387, 2387, 2387, 2387, 2387, 2387,
- 2387, 2387, 2387, 2387, 2387, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2388, 2388, 2388, 2388, 2388, 2388, 2388, 2388,
- 2388, 2388, 2388, 2388, 2388, 2388, 2388, 2388,
- 2388, 2388, 202, 2388, 2388, 2388, 2388, 2388,
- 2388, 2388, 2388, 2388, 2388, 2388, 2388, 2388,
- 2388, 2388, 2388, 2388, 2388, 2388, 2388, 2388,
- 2388, 2388, 2388, 2388, 2389, 2389, 2389, 2390,
- 2390, 2390, 2389, 2389, 2390, 2391, 2392, 2390,
- 2393, 2393, 2394, 2393, 2393, 2394, 2395, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2396, 2396, 2396, 2396, 2396, 2396, 2396, 202,
- 2396, 202, 2396, 2396, 2396, 2396, 202, 2396,
+ 2322, 2322, 2322, 2318, 2315, 2319, 2315, 2323,
+
+ 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331,
+ 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331,
+ 2332, 2330, 2330, 2330, 2330, 2330, 2330, 2330,
+ 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330,
+
+ 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330,
+ 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330,
+ 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330,
+ 2330, 2330, 2330, 2330, 2330, 2330, 2333, 2333,
+
+ 2334, 2335, 2335, 2335, 2335, 2335, 2335, 2335,
+ 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335,
+ 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335,
+ 2335, 2335, 2335, 2335, 2335, 2335, 2335, 221,
+
+ 221, 221, 2335, 2335, 2335, 2335, 2335, 2335,
+ 221, 221, 2335, 2335, 2335, 2335, 2335, 2335,
+ 221, 221, 2335, 2335, 2335, 2335, 2335, 2335,
+ 221, 221, 2335, 2335, 2335, 221, 221, 221,
+
+ 2336, 2337, 2338, 2320, 2339, 2337, 2337, 221,
+ 2340, 2341, 2341, 2341, 2341, 2340, 2340, 221,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 2342, 2342, 2342, 2343, 2344, 2345, 2345,
+
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 221, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 221,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 221, 2346, 2346, 221, 2346,
+
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 221, 221,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 221, 221,
+
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346,
+ 2346, 2346, 2346, 221, 221, 221, 221, 221,
+
+ 2347, 2348, 2347, 221, 221, 221, 221, 2349,
+ 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349,
+ 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349,
+ 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349,
+
+ 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349,
+ 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349,
+ 2349, 2349, 2349, 2349, 221, 221, 221, 2350,
+ 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350,
+
+ 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351,
+ 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351,
+ 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351,
+ 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351,
+
+ 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351,
+ 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351,
+ 2351, 2351, 2351, 2351, 2351, 2352, 2352, 2352,
+ 2352, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2352, 2354, 2355, 2356, 2356, 221,
+ 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749,
+ 1749, 1749, 1749, 1749, 1751, 221, 221, 221,
+
+ 2355, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544,
+ 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544,
+
+ 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544,
+ 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544,
+ 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544,
+ 1544, 1544, 1544, 1544, 1544, 1276, 221, 221,
+
+ 2357, 2357, 2357, 2357, 2357, 2357, 2357, 2357,
+ 2357, 2357, 2357, 2357, 2357, 2357, 2357, 2357,
+ 2357, 2357, 2357, 2357, 2357, 2357, 2357, 2357,
+ 2357, 2357, 2357, 2357, 2357, 221, 221, 221,
+
+ 2358, 2358, 2358, 2358, 2358, 2358, 2358, 2358,
+ 2358, 2358, 2358, 2358, 2358, 2358, 2358, 2358,
+ 2358, 2358, 2358, 2358, 2358, 2358, 2358, 2358,
+ 2358, 2358, 2358, 2358, 2358, 2358, 2358, 2358,
+
+ 2358, 2358, 2358, 2358, 2358, 2358, 2358, 2358,
+ 2358, 2358, 2358, 2358, 2358, 2358, 2358, 2358,
+ 2358, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1155, 2359, 2359, 2359, 2359, 2359, 2359, 2359,
+ 2359, 2359, 2359, 2359, 2359, 2359, 2359, 2359,
+ 2359, 2359, 2359, 2359, 2359, 2359, 2359, 2359,
+ 2359, 2359, 2359, 2359, 221, 221, 221, 221,
+
+ 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360,
+ 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360,
+ 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360,
+ 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2361,
+
+ 2362, 2362, 2362, 2362, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 2363, 2363, 2363,
+ 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364,
+ 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364,
+
+ 2364, 2365, 2364, 2364, 2364, 2364, 2364, 2364,
+ 2364, 2364, 2365, 221, 221, 221, 221, 221,
+ 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366,
+ 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366,
+
+ 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366,
+ 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366,
+ 2366, 2366, 2366, 2366, 2366, 2366, 2367, 2367,
+ 2367, 2367, 2367, 221, 221, 221, 221, 221,
+
+ 2368, 2368, 2368, 2368, 2368, 2368, 2368, 2368,
+ 2368, 2368, 2368, 2368, 2368, 2368, 2368, 2368,
+ 2368, 2368, 2368, 2368, 2368, 2368, 2368, 2368,
+ 2368, 2368, 2368, 2368, 2368, 2368, 221, 2369,
+
+ 2370, 2370, 2370, 2370, 2370, 2370, 2370, 2370,
+ 2370, 2370, 2370, 2370, 2370, 2370, 2370, 2370,
+ 2370, 2370, 2370, 2370, 2370, 2370, 2370, 2370,
+ 2370, 2370, 2370, 2370, 2370, 2370, 2370, 2370,
+
+ 2370, 2370, 2370, 2370, 221, 221, 221, 221,
+ 2370, 2370, 2370, 2370, 2370, 2370, 2370, 2370,
+ 2371, 2372, 2372, 2372, 2372, 2372, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2373, 2373, 2373, 2373, 2373, 2373, 2373, 2373,
+ 2373, 2373, 2373, 2373, 2373, 2373, 2373, 2373,
+ 2373, 2373, 2373, 2373, 2373, 2373, 2373, 2373,
+ 2373, 2373, 2373, 2373, 2373, 2373, 2373, 2373,
+
+ 2373, 2373, 2373, 2373, 2373, 2373, 2374, 2374,
+ 2375, 2375, 2375, 2375, 2375, 2375, 2375, 2375,
+ 2375, 2375, 2375, 2375, 2375, 2375, 2375, 2375,
+ 2375, 2375, 2375, 2375, 2375, 2375, 2375, 2375,
+
+ 2375, 2375, 2375, 2375, 2375, 2375, 2375, 2375,
+ 2375, 2375, 2375, 2375, 2375, 2375, 2376, 2376,
+ 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377,
+ 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377,
+
+ 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377,
+ 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377,
+ 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377,
+ 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377,
+
+ 2378, 2378, 2378, 2378, 2378, 2378, 2378, 2378,
+ 2378, 2378, 2378, 2378, 2378, 2378, 2378, 2378,
+ 2378, 2378, 2378, 2378, 2378, 2378, 2378, 2378,
+ 2378, 2378, 2378, 2378, 2378, 2378, 221, 221,
+
+ 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386,
+ 2387, 2388, 221, 221, 221, 221, 221, 221,
+ 2389, 2389, 2389, 2389, 2389, 2389, 2389, 2389,
+ 2389, 2389, 2389, 2389, 2389, 2389, 2389, 2389,
+
+ 2389, 2389, 2389, 2389, 2389, 2389, 2389, 2389,
+ 2389, 2389, 2389, 2389, 2389, 2389, 2389, 2389,
+ 2389, 2389, 2389, 2389, 221, 221, 221, 221,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 221, 221, 221, 221,
+
+ 2391, 2391, 2391, 2391, 2391, 2391, 2391, 2391,
+ 2391, 2391, 2391, 2391, 2391, 2391, 2391, 2391,
+ 2391, 2391, 2391, 2391, 2391, 2391, 2391, 2391,
+ 2391, 2391, 2391, 2391, 2391, 2391, 2391, 2391,
+
+ 2391, 2391, 2391, 2391, 2391, 2391, 2391, 2391,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
+ 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
+
+ 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
+ 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
+ 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
+ 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
+
+ 2392, 2392, 2392, 2392, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 2393,
+ 2394, 2394, 2394, 2394, 2394, 2394, 2394, 2394,
+ 2394, 2394, 2394, 221, 2394, 2394, 2394, 2394,
+
+ 2394, 2394, 2394, 2394, 2394, 2394, 2394, 2394,
+ 2394, 2394, 2394, 221, 2394, 2394, 2394, 2394,
+ 2394, 2394, 2394, 221, 2394, 2394, 221, 2395,
+ 2395, 2395, 2395, 2395, 2395, 2395, 2395, 2395,
+
+ 2395, 2395, 221, 2395, 2395, 2395, 2395, 2395,
+ 2395, 2395, 2395, 2395, 2395, 2395, 2395, 2395,
+ 2395, 2395, 221, 2395, 2395, 2395, 2395, 2395,
+ 2395, 2395, 221, 2395, 2395, 221, 221, 221,
+
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
- 2396, 2396, 2396, 2396, 2396, 2396, 202, 2396,
+
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
+ 2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
+ 2396, 2396, 2396, 2396, 2396, 2396, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
2396, 2396, 2396, 2396, 2396, 2396, 2396, 2396,
- 2396, 2397, 202, 202, 202, 202, 202, 202,
- 2398, 2398, 2398, 2398, 2398, 2398, 2398, 2398,
- 2398, 2398, 2398, 2398, 2398, 2398, 2398, 2398,
- 2398, 2398, 2398, 2398, 2398, 2398, 2398, 2398,
- 2398, 2398, 2398, 2398, 2398, 2398, 2398, 2398,
- 2398, 2398, 2398, 2398, 2398, 2398, 2398, 2398,
- 2398, 2398, 2398, 2398, 2398, 2398, 2398, 2399,
- 2400, 2400, 2400, 2399, 2399, 2399, 2399, 2399,
- 2399, 2401, 2402, 202, 202, 202, 202, 202,
- 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410,
- 2411, 2412, 202, 202, 202, 202, 202, 202,
-
- 2413, 2414, 2415, 2415, 202, 2416, 2416, 2416,
- 2416, 2416, 2416, 2416, 2416, 202, 202, 2416,
- 2416, 202, 202, 2416, 2416, 2416, 2416, 2416,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2397, 2398, 2398, 1989, 1989, 1989, 221, 1989,
+ 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+ 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+ 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+
+ 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+ 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+ 1989, 221, 1989, 1989, 1989, 1989, 1989, 1989,
+ 1989, 1989, 1989, 221, 221, 221, 221, 221,
+
+ 2399, 2399, 2399, 2399, 2399, 2399, 323, 323,
+ 2399, 323, 2399, 2399, 2399, 2399, 2399, 2399,
+ 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399,
+ 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399,
+
+ 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399,
+ 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399,
+ 2399, 2399, 2399, 2399, 2399, 2399, 323, 2399,
+ 2399, 323, 323, 323, 2399, 323, 323, 2399,
+
+ 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400,
+ 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400,
+ 2400, 2400, 2400, 2400, 2400, 2400, 323, 2401,
+ 2402, 2402, 2402, 2402, 2402, 2402, 2402, 2402,
+
+ 2403, 2403, 2403, 2403, 2403, 2403, 2403, 2403,
+ 2403, 2403, 2403, 2403, 2403, 2403, 2403, 2403,
+ 2403, 2403, 2403, 2403, 2403, 2403, 2403, 2404,
+ 2404, 2405, 2405, 2405, 2405, 2405, 2405, 2405,
+
+ 2406, 2406, 2406, 2406, 2406, 2406, 2406, 2406,
+ 2406, 2406, 2406, 2406, 2406, 2406, 2406, 2406,
+ 2406, 2406, 2406, 2406, 2406, 2406, 2406, 2406,
+ 2406, 2406, 2406, 2406, 2406, 2406, 2406, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 2407,
+ 2407, 2407, 2407, 2407, 2407, 2407, 2407, 2407,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408,
+ 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408,
+ 2408, 2408, 2408, 323, 2408, 2408, 323, 323,
+ 323, 323, 323, 2409, 2409, 2409, 2409, 2409,
+
+ 2410, 2410, 2410, 2410, 2410, 2410, 2410, 2410,
+ 2410, 2410, 2410, 2410, 2410, 2410, 2410, 2410,
+ 2410, 2410, 2410, 2410, 2410, 2410, 2411, 2411,
+ 2411, 2411, 2412, 2412, 323, 323, 323, 2413,
+
+ 2414, 2414, 2414, 2414, 2414, 2414, 2414, 2414,
+ 2414, 2414, 2414, 2414, 2414, 2414, 2414, 2414,
+ 2414, 2414, 2414, 2414, 2414, 2414, 2414, 2414,
+ 2414, 2414, 323, 323, 323, 323, 323, 2415,
+
+ 2416, 2416, 2416, 2416, 2416, 2416, 2416, 2416,
2416, 2416, 2416, 2416, 2416, 2416, 2416, 2416,
2416, 2416, 2416, 2416, 2416, 2416, 2416, 2416,
- 2416, 202, 2416, 2416, 2416, 2416, 2416, 2416,
- 2416, 202, 2416, 2416, 202, 2416, 2416, 2416,
- 2416, 2416, 202, 2417, 2418, 2416, 2419, 2415,
- 2414, 2415, 2415, 2415, 2415, 202, 202, 2415,
- 2415, 202, 202, 2420, 2420, 2421, 202, 202,
- 2422, 202, 202, 202, 202, 202, 202, 2419,
- 202, 202, 202, 202, 202, 2416, 2416, 2416,
- 2416, 2416, 2415, 2415, 202, 202, 2423, 2423,
- 2423, 2423, 2423, 2423, 2423, 202, 202, 202,
- 2423, 2423, 2423, 2423, 2423, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2424, 2424, 2424, 2424, 2424, 2424, 2424, 2424,
- 2424, 2424, 2424, 2424, 2424, 2424, 2424, 2424,
- 2424, 2424, 2424, 2424, 2424, 2424, 2424, 2424,
- 2424, 2424, 2424, 2424, 2424, 2424, 2424, 2424,
- 2424, 2424, 2424, 2424, 2424, 2424, 2424, 2424,
- 2424, 2424, 2424, 2424, 2424, 2424, 2424, 2424,
- 2424, 2424, 2424, 2424, 2424, 2425, 2425, 2425,
- 2426, 2426, 2426, 2426, 2426, 2426, 2426, 2426,
- 2425, 2425, 2427, 2426, 2426, 2425, 2428, 2424,
- 2424, 2424, 2424, 2429, 2429, 2430, 2430, 2431,
- 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439,
- 2440, 2441, 2442, 2430, 202, 2431, 2443, 2444,
- 2445, 2445, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446,
- 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446,
- 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446,
- 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446,
- 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446,
- 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446,
- 2447, 2448, 2448, 2449, 2449, 2449, 2449, 2449,
- 2449, 2448, 2450, 2451, 2451, 2447, 2451, 2449,
- 2449, 2448, 2452, 2453, 2446, 2446, 2454, 2446,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462,
- 2463, 2464, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
+ 2416, 2416, 2416, 2416, 2416, 2416, 2416, 2416,
+
+ 2417, 2417, 2417, 2417, 2417, 2417, 2417, 2417,
+ 2417, 2417, 2417, 2417, 2417, 2417, 2417, 2417,
+ 2417, 2417, 2417, 2417, 2417, 2417, 2417, 2417,
+ 323, 323, 323, 323, 2418, 2418, 2417, 2417,
+
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+ 323, 323, 2418, 2418, 2418, 2418, 2418, 2418,
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+ 2418, 2418, 2418, 2418, 2418, 2418, 2418, 2418,
+
+ 2419, 2420, 2420, 2420, 323, 2420, 2420, 323,
+ 323, 323, 323, 323, 2420, 2421, 2420, 2422,
+ 2419, 2419, 2419, 2419, 323, 2419, 2419, 2419,
+ 323, 2419, 2419, 2419, 2419, 2419, 2419, 2419,
+
+ 2419, 2419, 2419, 2419, 2419, 2419, 2419, 2419,
+ 2419, 2419, 2419, 2419, 2419, 2419, 2419, 2419,
+ 2419, 2419, 2419, 2419, 2423, 2423, 323, 323,
+ 2422, 2424, 2421, 323, 323, 323, 323, 2425,
+
+ 2426, 2427, 2428, 2429, 2430, 2430, 2430, 2430,
+ 2431, 323, 323, 323, 323, 323, 323, 323,
+ 2432, 2432, 2432, 2432, 2432, 2432, 2433, 2433,
+ 2434, 323, 323, 323, 323, 323, 323, 323,
+
+ 2435, 2435, 2435, 2435, 2435, 2435, 2435, 2435,
+ 2435, 2435, 2435, 2435, 2435, 2435, 2435, 2435,
+ 2435, 2435, 2435, 2435, 2435, 2435, 2435, 2435,
+ 2435, 2435, 2435, 2435, 2435, 2436, 2436, 2437,
+
+ 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438,
+ 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438,
+ 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438,
+ 2438, 2438, 2438, 2438, 2438, 2439, 2439, 2439,
+
+ 2440, 2440, 2440, 2440, 2440, 2441, 2442, 2441,
+ 2443, 2441, 2441, 2442, 2442, 2444, 2441, 2441,
+ 2441, 2441, 2441, 2440, 2440, 2440, 2440, 2444,
+ 2440, 2440, 2440, 2440, 2440, 2441, 2440, 2440,
+
+ 2440, 2441, 2442, 2442, 2441, 2445, 2446, 323,
+ 323, 323, 323, 2447, 2447, 2447, 2447, 2448,
+ 2449, 2449, 2449, 2449, 2449, 2449, 2450, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451,
+ 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451,
+ 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451,
+ 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451,
+
+ 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451,
+ 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451,
+ 2451, 2451, 2451, 2451, 2451, 2451, 323, 323,
+ 323, 2452, 2452, 2452, 2452, 2452, 2452, 2452,
+
+ 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453,
+ 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453,
+ 2453, 2453, 2453, 2453, 2453, 2453, 323, 323,
+ 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454,
+
+ 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455,
+ 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455,
+ 2455, 2455, 2455, 323, 323, 323, 323, 323,
+ 2456, 2456, 2456, 2456, 2456, 2456, 2456, 2456,
+
+ 2457, 2458, 2457, 2458, 2458, 2458, 2457, 2457,
+ 2457, 2458, 2457, 2457, 2458, 2457, 2458, 2458,
+ 2457, 2458, 323, 323, 323, 323, 323, 323,
+ 323, 2459, 2459, 2459, 2459, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 2460, 2460, 2460, 2460, 2461, 2461, 2462,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463,
+ 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463,
+ 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463,
+ 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463,
+
+ 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463,
+ 2463, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464,
+ 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464,
+ 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464,
+ 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464,
+
+ 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464,
+ 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464,
+ 2464, 2464, 2464, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465,
2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465,
2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465,
2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465,
+
2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465,
2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465,
- 2465, 2465, 2465, 2465, 2465, 2465, 2465, 2466,
- 2467, 2467, 2468, 2468, 2468, 2468, 202, 202,
- 2467, 2467, 2469, 2469, 2468, 2468, 2467, 2470,
- 2471, 2472, 2473, 2473, 2474, 2474, 2475, 2475,
- 2475, 2473, 2476, 2476, 2476, 2476, 2476, 2476,
- 2476, 2476, 2476, 2476, 2476, 2476, 2476, 2476,
- 2477, 2477, 2477, 2477, 2478, 2478, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2479, 2479, 2479, 2479, 2479, 2479, 2479, 2479,
- 2479, 2479, 2479, 2479, 2479, 2479, 2479, 2479,
- 2479, 2479, 2479, 2479, 2479, 2479, 2479, 2479,
- 2479, 2479, 2479, 2479, 2479, 2479, 2479, 2479,
- 2479, 2479, 2479, 2479, 2479, 2479, 2479, 2479,
- 2479, 2479, 2479, 2479, 2479, 2479, 2479, 2479,
- 2480, 2480, 2480, 2481, 2481, 2481, 2481, 2481,
- 2481, 2481, 2481, 2480, 2480, 2481, 2480, 2482,
- 2481, 2483, 2483, 2484, 2479, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492,
- 2493, 2494, 202, 202, 202, 202, 202, 202,
+ 2465, 2465, 2465, 323, 323, 323, 323, 323,
+ 323, 323, 2466, 2466, 2466, 2466, 2466, 2466,
+
+ 2467, 2468, 2468, 2468, 2468, 2468, 2468, 2468,
+ 2468, 2468, 2468, 2468, 2468, 2468, 2468, 2468,
+ 2468, 2468, 2468, 2468, 2468, 2468, 2468, 2468,
+ 2468, 2468, 2468, 2468, 2468, 2468, 2468, 2468,
+
+ 2468, 2468, 2469, 2468, 2470, 2470, 2470, 2470,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478,
+ 2479, 2480, 323, 323, 323, 323, 323, 323,
+
+ 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488,
+ 2489, 2490, 2490, 2490, 2490, 2490, 2490, 2490,
+ 2490, 2490, 2490, 2490, 2490, 2490, 2490, 2490,
+ 2490, 2490, 2490, 2490, 2490, 2490, 2490, 323,
+
+ 2491, 2491, 2491, 2491, 2491, 2491, 2491, 2491,
+ 2491, 2491, 2491, 2491, 2491, 2491, 2491, 2491,
+ 2491, 2491, 2491, 2491, 2491, 2491, 2491, 2491,
+ 2491, 2491, 2491, 2491, 2491, 2491, 2491, 2491,
+
+ 2491, 2491, 2491, 2491, 2491, 2491, 2491, 2491,
+ 2491, 2491, 323, 2492, 2492, 2493, 323, 323,
+ 2491, 2491, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 2494, 2494, 2494,
+
2495, 2495, 2495, 2495, 2495, 2495, 2495, 2495,
- 2495, 2495, 2495, 2495, 2495, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2496, 2496, 2496, 2496, 2496, 2496, 2496, 2496,
- 2496, 2496, 2496, 2496, 2496, 2496, 2496, 2496,
- 2496, 2496, 2496, 2496, 2496, 2496, 2496, 2496,
- 2496, 2496, 2496, 2496, 2496, 2496, 2496, 2496,
- 2496, 2496, 2496, 2496, 2496, 2496, 2496, 2496,
- 2496, 2496, 2496, 2497, 2498, 2497, 2498, 2498,
- 2497, 2497, 2497, 2497, 2497, 2497, 2499, 2500,
- 2501, 202, 202, 202, 202, 202, 202, 202,
- 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509,
- 2510, 2511, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2512, 2512, 2512, 2512, 2512, 2512, 2512, 2512,
- 2512, 2512, 2512, 2512, 2512, 2512, 2512, 2512,
- 2512, 2512, 2512, 2512, 2512, 2512, 2512, 2512,
- 2512, 2512, 2513, 202, 202, 2514, 2514, 2514,
- 2515, 2515, 2514, 2514, 2514, 2514, 2515, 2514,
- 2514, 2514, 2514, 2516, 202, 202, 202, 202,
- 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524,
- 2525, 2526, 2527, 2527, 2528, 2528, 2528, 2529,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530,
- 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530,
- 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530,
- 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530,
- 2530, 2530, 2530, 2530, 2530, 2530, 2530, 2530,
- 2530, 2530, 2530, 2530, 2531, 2531, 2531, 2532,
- 2532, 2532, 2532, 2532, 2532, 2532, 2532, 2532,
- 2531, 2533, 2534, 2535, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2536, 2536, 2536, 2536, 2536, 2536, 2536, 2536,
- 2536, 2536, 2536, 2536, 2536, 2536, 2536, 2536,
- 2536, 2536, 2536, 2536, 2536, 2536, 2536, 2536,
- 2536, 2536, 2536, 2536, 2536, 2536, 2536, 2536,
- 2537, 2537, 2537, 2537, 2537, 2537, 2537, 2537,
- 2537, 2537, 2537, 2537, 2537, 2537, 2537, 2537,
- 2537, 2537, 2537, 2537, 2537, 2537, 2537, 2537,
- 2537, 2537, 2537, 2537, 2537, 2537, 2537, 2537,
- 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545,
- 2546, 2547, 2548, 2548, 2548, 2548, 2548, 2548,
- 2548, 2548, 2548, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 2549,
-
- 2550, 2550, 2550, 2550, 2550, 2550, 2550, 202,
- 202, 2550, 202, 202, 2550, 2550, 2550, 2550,
- 2550, 2550, 2550, 2550, 202, 2550, 2550, 202,
+ 2495, 2495, 2495, 2495, 2495, 2495, 2495, 2495,
+ 2495, 2495, 2495, 2495, 2495, 2495, 2495, 2495,
+ 2495, 2495, 2495, 2495, 2495, 2496, 2496, 2496,
+
+ 2496, 2496, 2496, 2496, 2496, 2496, 2496, 2495,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 2497, 2497, 2497, 2498, 2497, 2497, 2497, 2497,
+ 2497, 2497, 2497, 2497, 2497, 2497, 2497, 2497,
+
+ 2497, 2497, 2497, 2497, 2497, 2499, 2500, 2500,
+ 2501, 2501, 2501, 2500, 2501, 2500, 2500, 2500,
+ 2500, 2502, 2502, 2502, 2503, 2504, 2504, 2504,
+ 2504, 2504, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 2505, 2505, 2505, 2505, 2506, 2506, 2505, 2505,
+ 2505, 2505, 2505, 2505, 2505, 2505, 2505, 2505,
+
+ 2505, 2505, 2507, 2508, 2507, 2508, 2509, 2509,
+ 2509, 2509, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 2510, 2511, 2510, 2510, 2512, 2512, 2512, 2511,
+ 2510, 2512, 2512, 2510, 2510, 2512, 2510, 2510,
+
+ 2511, 2510, 2512, 2512, 2510, 2513, 2513, 2513,
+ 2513, 2514, 2515, 2516, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2517, 2517, 2517, 2517, 2517, 2517, 2517, 2517,
+ 2517, 2517, 2517, 2517, 2517, 2517, 2517, 2517,
+ 2517, 2517, 2517, 2517, 2517, 2517, 2517, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 2518, 2519, 2518, 2520, 2520, 2520, 2520, 2520,
+ 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520,
+ 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520,
+ 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520,
+ 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520,
+ 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520,
+ 2520, 2520, 2520, 2520, 2520, 2520, 2520, 2520,
+ 2519, 2519, 2519, 2519, 2519, 2519, 2519, 2519,
+ 2519, 2519, 2519, 2519, 2519, 2519, 2521, 2522,
+ 2522, 2523, 2523, 2523, 2523, 2523, 221, 221,
+ 221, 221, 2524, 2525, 2526, 2527, 2528, 2529,
+ 2530, 2531, 2532, 2533, 2533, 2533, 2533, 2533,
+ 2533, 2533, 2533, 2533, 2533, 2533, 2534, 2535,
+ 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543,
+ 2544, 2545, 2545, 2546, 2546, 2545, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 2547,
+ 2548, 2548, 2549, 2550, 2550, 2550, 2550, 2550,
2550, 2550, 2550, 2550, 2550, 2550, 2550, 2550,
2550, 2550, 2550, 2550, 2550, 2550, 2550, 2550,
+ 2550, 2550, 2551, 2550, 2551, 2550, 2550, 2550,
2550, 2550, 2550, 2550, 2550, 2550, 2550, 2550,
- 2551, 2552, 2552, 2552, 2552, 2552, 202, 2552,
- 2553, 202, 202, 2554, 2554, 2555, 2556, 2557,
- 2552, 2557, 2552, 2558, 2559, 2560, 2559, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568,
- 2569, 2570, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2571, 2571, 2571, 2571, 2571, 2571, 2571, 2571,
- 202, 202, 2571, 2571, 2571, 2571, 2571, 2571,
- 2571, 2571, 2571, 2571, 2571, 2571, 2571, 2571,
+ 2550, 2550, 2550, 2551, 2550, 2550, 2550, 2550,
+ 2549, 2549, 2549, 2548, 2548, 2548, 2548, 2549,
+ 2549, 2552, 2553, 2554, 2554, 2555, 2556, 2556,
+ 2556, 2556, 2557, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 2558, 221, 221,
+ 2559, 2559, 2559, 2559, 2559, 2559, 2559, 2559,
+ 2559, 2559, 2559, 2559, 2559, 2559, 2559, 2559,
+ 2559, 2559, 2559, 2559, 2559, 2559, 2559, 2559,
+ 2559, 221, 221, 221, 221, 221, 221, 221,
+ 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567,
+ 2568, 2569, 221, 221, 221, 221, 221, 221,
+
+ 2570, 2570, 2570, 2571, 2571, 2571, 2571, 2571,
2571, 2571, 2571, 2571, 2571, 2571, 2571, 2571,
2571, 2571, 2571, 2571, 2571, 2571, 2571, 2571,
2571, 2571, 2571, 2571, 2571, 2571, 2571, 2571,
- 2571, 2572, 2572, 2572, 2573, 2573, 2573, 2573,
- 202, 202, 2573, 2573, 2572, 2572, 2572, 2572,
- 2574, 2571, 2575, 2571, 2572, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2576, 2577, 2577, 2577, 2577, 2577, 2577, 2578,
- 2578, 2577, 2577, 2576, 2576, 2576, 2576, 2576,
- 2576, 2576, 2576, 2576, 2576, 2576, 2576, 2576,
- 2576, 2576, 2576, 2576, 2576, 2576, 2576, 2576,
- 2576, 2576, 2576, 2576, 2576, 2576, 2576, 2576,
- 2576, 2576, 2576, 2576, 2576, 2576, 2576, 2576,
- 2576, 2576, 2576, 2577, 2579, 2577, 2577, 2577,
- 2577, 2580, 2581, 2577, 2577, 2577, 2577, 2582,
- 2583, 2584, 2585, 2585, 2584, 2582, 2583, 2579,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2586, 2587, 2587, 2587, 2587, 2587, 2587, 2588,
- 2588, 2587, 2587, 2587, 2586, 2586, 2586, 2586,
- 2586, 2586, 2586, 2586, 2586, 2586, 2586, 2586,
- 2586, 2586, 2586, 2586, 2586, 2586, 2586, 2586,
- 2586, 2586, 2586, 2586, 2586, 2586, 2586, 2586,
- 2586, 2586, 2586, 2586, 2586, 2586, 2586, 2586,
- 2586, 2586, 2586, 2586, 2589, 2589, 2590, 2590,
- 2590, 2590, 2587, 2587, 2587, 2587, 2587, 2587,
- 2587, 2587, 2587, 2587, 2587, 2587, 2587, 2588,
- 2587, 2591, 2592, 2593, 2593, 2594, 2595, 2595,
- 2595, 2592, 2592, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2596,
- 2596, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597,
- 2597, 202, 2597, 2597, 2597, 2597, 2597, 2597,
- 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597,
- 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597,
- 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2597,
- 2597, 2597, 2597, 2597, 2597, 2597, 2597, 2598,
- 2599, 2599, 2599, 2599, 2599, 2599, 2599, 202,
- 2599, 2599, 2599, 2599, 2599, 2599, 2598, 2600,
- 2597, 2601, 2601, 2602, 2602, 2602, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610,
- 2611, 2612, 2613, 2613, 2613, 2613, 2613, 2613,
- 2613, 2613, 2613, 2613, 2613, 2613, 2613, 2613,
- 2613, 2613, 2613, 2613, 2613, 202, 202, 202,
- 2614, 2615, 2616, 2616, 2616, 2616, 2616, 2616,
- 2616, 2616, 2616, 2616, 2616, 2616, 2616, 2616,
- 2616, 2616, 2616, 2616, 2616, 2616, 2616, 2616,
- 2616, 2616, 2616, 2616, 2616, 2616, 2616, 2616,
- 202, 202, 2617, 2617, 2617, 2617, 2617, 2617,
- 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617,
- 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617,
- 202, 2618, 2617, 2617, 2617, 2617, 2617, 2617,
- 2617, 2618, 2617, 2617, 2618, 2617, 2617, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2619, 2619, 2619, 2619, 2619, 2619, 2619, 202,
- 2619, 2619, 202, 2619, 2619, 2619, 2619, 2619,
- 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619,
- 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619,
- 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619,
- 2619, 2619, 2619, 2619, 2619, 2619, 2619, 2619,
- 2619, 2620, 2620, 2620, 2620, 2620, 2620, 202,
- 202, 202, 2620, 202, 2620, 2620, 202, 2620,
- 2620, 2620, 2621, 2620, 2622, 2622, 2623, 2620,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631,
- 2632, 2633, 202, 202, 202, 202, 202, 202,
- 2634, 2634, 2634, 2634, 2634, 2634, 202, 2634,
- 2634, 202, 2634, 2634, 2634, 2634, 2634, 2634,
- 2634, 2634, 2634, 2634, 2634, 2634, 2634, 2634,
- 2634, 2634, 2634, 2634, 2634, 2634, 2634, 2634,
- 2634, 2634, 2634, 2634, 2634, 2634, 2634, 2634,
- 2634, 2634, 2635, 2635, 2635, 2635, 2635, 202,
- 2636, 2636, 202, 2635, 2635, 2636, 2635, 2637,
- 2634, 202, 202, 202, 202, 202, 202, 202,
- 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645,
- 2646, 2647, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2648, 2648, 2648, 2648, 2648, 2648, 2648, 2648,
- 2648, 2648, 2648, 2648, 2648, 2648, 2648, 2648,
- 2648, 2648, 2648, 2649, 2649, 2650, 2650, 2651,
- 2651, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2652, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2653, 2653, 2653, 2653, 2653, 2653, 2653, 2653,
- 2653, 2653, 2653, 2653, 2653, 2653, 2653, 2653,
- 2653, 2653, 2653, 2653, 2653, 2654, 2654, 2654,
- 2654, 2654, 2654, 2654, 2654, 2655, 2655, 2655,
- 2655, 2654, 2654, 2654, 2654, 2654, 2654, 2654,
- 2654, 2654, 2654, 2654, 2654, 2654, 2654, 2654,
- 2654, 2654, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 2656,
-
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
-
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657,
- 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2658,
- 2658, 2658, 2658, 2658, 2658, 2658, 2658, 2658,
- 2658, 2658, 2658, 2658, 2658, 2658, 2658, 2658,
- 2658, 2658, 2658, 2658, 2658, 2658, 2658, 2658,
- 2658, 2658, 2658, 2658, 2658, 2658, 2658, 2658,
- 2658, 2658, 2658, 2658, 2658, 2658, 2658, 2658,
- 2658, 2659, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2660, 2660, 2660, 2660, 2660,
- 2660, 2660, 2660, 2661, 2661, 2661, 2661, 2661,
- 2661, 2661, 2661, 2661, 2661, 2661, 2661, 202,
- 2662, 2662, 2662, 2662, 2663, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
-
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 2659, 2659, 2659, 2659,
- 2659, 2659, 2659, 2659, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
+ 2571, 2571, 2571, 2571, 2571, 2571, 2571, 2572,
+ 2573, 2573, 2573, 2573, 2574, 2573, 2575, 2575,
+ 2573, 2573, 2573, 2576, 2576, 221, 2577, 2578,
+ 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586,
+ 2587, 2588, 2588, 2588, 2589, 2590, 2590, 2591,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2592, 2592, 2592, 2592, 2592, 2592, 2592, 2592,
+ 2592, 2592, 2592, 2592, 2592, 2592, 2592, 2592,
+ 2592, 2592, 2592, 2592, 2592, 2592, 2592, 2592,
+ 2592, 2592, 2592, 2592, 2592, 2592, 2592, 2592,
+ 2592, 2592, 2592, 2593, 2594, 2595, 2592, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2596, 2596, 2597, 2598, 2598, 2598, 2598, 2598,
+ 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2598,
+ 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2598,
+ 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2598,
+ 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2598,
+ 2598, 2598, 2598, 2598, 2598, 2598, 2598, 2598,
+ 2598, 2598, 2598, 2597, 2597, 2597, 2596, 2596,
+ 2596, 2596, 2596, 2596, 2596, 2596, 2596, 2597,
+ 2599, 2598, 2600, 2600, 2598, 2601, 2601, 2602,
+ 2603, 2604, 2605, 2604, 2604, 2606, 2607, 2608,
+ 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616,
+ 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2623,
+ 221, 2624, 2624, 2624, 2624, 2624, 2624, 2624,
+ 2624, 2624, 2624, 2624, 2624, 2624, 2624, 2624,
+ 2624, 2624, 2624, 2624, 2624, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625,
+ 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625,
+ 2625, 2625, 221, 2625, 2625, 2625, 2625, 2625,
+ 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625,
+ 2625, 2625, 2625, 2625, 2625, 2625, 2625, 2625,
+ 2625, 2625, 2625, 2625, 2626, 2626, 2626, 2627,
+ 2627, 2627, 2626, 2626, 2627, 2628, 2629, 2627,
+ 2630, 2630, 2631, 2630, 2630, 2631, 2632, 2633,
+ 2633, 2634, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2635, 2635, 2635, 2635, 2635, 2635, 2635, 221,
+ 2635, 221, 2635, 2635, 2635, 2635, 221, 2635,
+ 2635, 2635, 2635, 2635, 2635, 2635, 2635, 2635,
+ 2635, 2635, 2635, 2635, 2635, 2635, 221, 2635,
+ 2635, 2635, 2635, 2635, 2635, 2635, 2635, 2635,
+ 2635, 2636, 221, 221, 221, 221, 221, 221,
+ 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637,
+ 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637,
+ 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637,
+ 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637,
+ 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2637,
+ 2637, 2637, 2637, 2637, 2637, 2637, 2637, 2638,
+ 2639, 2639, 2639, 2638, 2638, 2638, 2638, 2638,
+ 2638, 2640, 2641, 221, 221, 221, 221, 221,
+ 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649,
+ 2650, 2651, 221, 221, 221, 221, 221, 221,
+
+ 2652, 2653, 2654, 2654, 221, 2655, 2655, 2655,
+ 2655, 2655, 2655, 2655, 2655, 221, 221, 2655,
+ 2655, 221, 221, 2655, 2655, 2655, 2655, 2655,
+ 2655, 2655, 2655, 2655, 2655, 2655, 2655, 2655,
+ 2655, 2655, 2655, 2655, 2655, 2655, 2655, 2655,
+ 2655, 221, 2655, 2655, 2655, 2655, 2655, 2655,
+ 2655, 221, 2655, 2655, 221, 2655, 2655, 2655,
+ 2655, 2655, 221, 2656, 2657, 2658, 2659, 2654,
+ 2653, 2654, 2654, 2654, 2654, 221, 221, 2654,
+ 2654, 221, 221, 2660, 2660, 2661, 221, 221,
+ 2662, 221, 221, 221, 221, 221, 221, 2659,
+ 221, 221, 221, 221, 221, 2658, 2655, 2655,
+ 2655, 2655, 2654, 2654, 221, 221, 2663, 2663,
+ 2663, 2663, 2663, 2663, 2663, 221, 221, 221,
+ 2663, 2663, 2663, 2663, 2663, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
@@ -4291,5321 +3779,6682 @@ static const unsigned short uc_property_trie[] = {
2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2665, 2665, 2665, 2666, 2666, 2666, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2666, 2664, 2664, 2664, 2665, 2666,
- 2665, 2666, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
-
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2665, 2666, 2666, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
-
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 2664,
- 2664, 2664, 2664, 2664, 2664, 2664, 2664, 202,
- 2667, 2667, 2667, 2667, 2667, 2667, 2667, 2668,
- 2669, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
-
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2671, 2672,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
-
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 2670,
- 2670, 2670, 2670, 2670, 2670, 2670, 2670, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
-
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 2673, 2673, 2673, 2673, 2673, 2673, 2673,
- 2673, 202, 202, 202, 202, 202, 202, 202,
- 2674, 2674, 2674, 2674, 2674, 2674, 2674, 2674,
- 2674, 2674, 2674, 2674, 2674, 2674, 2674, 2674,
- 2674, 2674, 2674, 2674, 2674, 2674, 2674, 2674,
- 2674, 2674, 2674, 2674, 2674, 2674, 2674, 202,
- 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682,
- 2683, 2684, 202, 202, 202, 202, 2685, 2685,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
+ 2664, 2664, 2664, 2664, 2664, 2665, 2665, 2665,
+ 2666, 2666, 2666, 2666, 2666, 2666, 2666, 2666,
+ 2665, 2665, 2667, 2666, 2666, 2665, 2668, 2664,
+ 2664, 2664, 2664, 2669, 2669, 2670, 2670, 2671,
+ 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679,
+ 2680, 2681, 2682, 2670, 221, 2671, 2683, 2684,
+ 2685, 2685, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686,
2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686,
2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686,
- 2686, 2686, 2686, 2686, 2686, 2686, 202, 202,
- 2687, 2687, 2687, 2687, 2687, 2688, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2690, 2690, 2690, 2690, 2690, 2690, 2690, 2691,
- 2691, 2692, 2693, 2693, 2694, 2694, 2694, 2694,
- 2695, 2695, 2695, 2695, 2691, 2694, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703,
- 2704, 2705, 202, 2706, 2706, 2706, 2706, 2706,
- 2706, 2706, 202, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 202, 202, 202, 202, 202, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 2689, 2689, 2689, 2689, 2689, 2689, 2689, 2689,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2707, 2707, 2707, 2707, 2707, 2707, 2707, 2707,
- 2707, 2707, 2707, 2707, 2707, 2707, 2707, 2707,
- 2707, 2707, 2707, 2707, 2707, 2707, 2707, 2707,
- 2707, 2707, 2707, 2707, 2707, 2707, 2707, 2707,
- 2708, 2708, 2708, 2708, 2708, 2708, 2708, 2708,
- 2708, 2708, 2708, 2708, 2708, 2708, 2708, 2708,
- 2708, 2708, 2708, 2708, 2708, 2708, 2708, 2708,
- 2708, 2708, 2708, 2708, 2708, 2708, 2708, 2708,
- 2709, 2709, 2709, 2709, 2709, 2709, 2709, 2709,
- 2709, 2709, 2709, 2709, 2709, 2709, 2709, 2709,
- 2709, 2709, 2709, 2709, 2709, 2709, 2709, 2710,
- 2711, 2712, 2712, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2713, 2713, 2713,
- 2713, 2713, 2713, 2713, 2713, 2714, 2714, 2714,
- 2714, 2714, 2714, 202, 202, 202, 202, 2715,
- 2713, 2716, 2716, 2716, 2716, 2716, 2716, 2716,
- 2716, 2716, 2716, 2716, 2716, 2716, 2716, 2716,
- 2716, 2716, 2716, 2716, 2716, 2716, 2716, 2716,
- 2716, 2716, 2716, 2716, 2716, 2716, 2716, 2716,
+ 2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686,
+ 2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686,
+ 2686, 2686, 2686, 2686, 2686, 2686, 2686, 2686,
+ 2687, 2688, 2688, 2689, 2689, 2689, 2689, 2689,
+ 2689, 2688, 2690, 2691, 2691, 2687, 2691, 2689,
+ 2689, 2688, 2692, 2693, 2686, 2686, 2694, 2686,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702,
+ 2703, 2704, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2705,
+ 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2705,
+ 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2705,
+ 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2705,
+ 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2705,
+ 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2706,
+ 2707, 2707, 2708, 2708, 2708, 2708, 221, 221,
+ 2707, 2707, 2709, 2709, 2708, 2708, 2707, 2710,
+ 2711, 2712, 2713, 2713, 2714, 2714, 2715, 2715,
+ 2715, 2713, 2716, 2716, 2716, 2716, 2716, 2716,
2716, 2716, 2716, 2716, 2716, 2716, 2716, 2716,
- 2716, 2716, 2716, 2716, 2716, 2716, 2716, 2717,
- 2717, 2717, 2717, 2717, 2717, 2717, 2717, 2717,
- 202, 202, 202, 202, 202, 202, 202, 2718,
- 2718, 2718, 2718, 2719, 2719, 2719, 2719, 2719,
- 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2720, 2721, 2722, 2723, 2724, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2725, 2725, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
-
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2727, 2727, 2727,
- 2727, 2727, 2728, 2728, 2728, 2728, 2728, 2728,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2726, 2726, 2726, 2726, 2726,
- 2726, 2726, 2726, 2729, 2729, 2729, 2729, 2729,
- 2729, 2729, 2729, 2729, 2729, 2729, 2729, 2729,
-
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
-
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 2730, 2730,
- 2730, 2730, 2730, 2730, 2730, 2730, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2729, 2729, 2729, 2729, 2729, 2729, 2729, 2729,
- 2729, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2731, 2732, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
-
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 2733,
- 2733, 2733, 2733, 2733, 2733, 2733, 2733, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2734, 2734, 2734, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 2735, 2735, 2735, 2735,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
+ 2717, 2717, 2717, 2717, 2718, 2718, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
+ 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
+ 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
+ 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
+ 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
+ 2719, 2719, 2719, 2719, 2719, 2719, 2719, 2719,
+ 2720, 2720, 2720, 2721, 2721, 2721, 2721, 2721,
+ 2721, 2721, 2721, 2720, 2720, 2721, 2720, 2722,
+ 2721, 2723, 2723, 2724, 2719, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732,
+ 2733, 2734, 221, 221, 221, 221, 221, 221,
+ 2735, 2735, 2735, 2735, 2735, 2735, 2735, 2735,
+ 2735, 2735, 2735, 2735, 2735, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 2736, 2736, 2736, 2736,
- 2736, 2736, 2736, 2736, 202, 202, 202, 202,
-
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 202, 202, 202, 202, 202,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 2737, 2737, 2737, 202, 202, 202,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 202, 202, 202, 202, 202, 202, 202,
- 2737, 2737, 2737, 2737, 2737, 2737, 2737, 2737,
- 2737, 2737, 202, 202, 2738, 2739, 2740, 2741,
- 2742, 2742, 2742, 2742, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 202,
- 202, 1465, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2744, 2744,
- 2744, 2744, 2744, 2744, 2744, 2745, 2746, 2747,
- 2747, 2747, 2743, 2743, 2743, 2748, 2745, 2745,
- 2745, 2745, 2745, 2749, 2749, 2749, 2749, 2749,
- 2749, 2749, 2749, 2750, 2750, 2750, 2750, 2750,
- 2750, 2750, 2750, 2743, 2743, 2751, 2751, 2751,
- 2751, 2751, 2750, 2750, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2751, 2751, 2751, 2751, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2744, 2744, 2744, 2744, 2744,
- 2744, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2743, 2743,
- 2743, 2743, 2743, 2743, 2743, 2743, 2752, 2752,
- 2752, 2752, 2752, 2752, 2752, 2752, 2752, 2752,
- 2752, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130,
- 2130, 2130, 2753, 2753, 2753, 2130, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2754, 2754, 2754, 2754, 2754, 2754, 2754, 2754,
- 2754, 2754, 2754, 2754, 2754, 2754, 2754, 2754,
- 2754, 2754, 2754, 2754, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507,
- 1507, 1507, 1507, 1507, 1507, 1507, 1507, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2755, 2755, 2755, 2755, 2755, 2755, 2755, 2755,
- 2755, 2755, 2755, 2755, 2755, 2755, 2755, 2755,
- 2755, 2755, 2754, 2754, 2754, 2754, 2754, 2754,
- 2754, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 202, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2756, 202, 2756, 2756,
- 202, 202, 2756, 202, 202, 2756, 2756, 202,
- 202, 2756, 2756, 2756, 2756, 202, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2757, 2757,
- 2757, 2757, 202, 2757, 202, 2757, 2757, 2757,
- 2757, 2758, 2757, 2757, 202, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
-
- 2757, 2757, 2757, 2757, 2756, 2756, 202, 2756,
- 2756, 2756, 2756, 202, 202, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 202, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 202, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 202, 2756, 2756, 2756, 2756, 202,
- 2756, 2756, 2756, 2756, 2756, 202, 2756, 202,
- 202, 202, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 202, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
-
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 1457, 1457, 202, 202,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2759, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2760, 2757, 2757, 2757, 2757,
- 2757, 2757, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2759, 2757, 2757, 2757, 2757,
-
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2760, 2757, 2757,
- 2757, 2757, 2757, 2757, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2759, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2760,
- 2757, 2757, 2757, 2757, 2757, 2757, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2759,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2760, 2757, 2757, 2757, 2757, 2757, 2757,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2756, 2756, 2756, 2756, 2756, 2756, 2756,
- 2756, 2759, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2757, 2757, 2757, 2757, 2757,
- 2757, 2757, 2757, 2760, 2757, 2757, 2757, 2757,
- 2757, 2757, 2761, 2762, 202, 202, 2763, 2764,
- 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772,
- 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770,
- 2771, 2772, 2763, 2764, 2765, 2766, 2767, 2768,
- 2769, 2770, 2771, 2772, 2763, 2764, 2765, 2766,
- 2767, 2768, 2769, 2770, 2771, 2772, 2763, 2764,
- 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772,
+ 2736, 2736, 2736, 2737, 2738, 2737, 2738, 2738,
+ 2737, 2737, 2737, 2737, 2737, 2737, 2739, 2740,
+ 2741, 2742, 221, 221, 221, 221, 221, 221,
+ 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750,
+ 2751, 2752, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2753, 2753, 2753, 2753, 2753, 2753, 2753, 2753,
+ 2753, 2753, 2753, 2753, 2753, 2753, 2753, 2753,
+ 2753, 2753, 2753, 2753, 2753, 2753, 2753, 2753,
+ 2753, 2753, 2754, 221, 221, 2755, 2755, 2755,
+ 2756, 2756, 2755, 2755, 2755, 2755, 2757, 2755,
+ 2755, 2755, 2755, 2758, 221, 221, 221, 221,
+ 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766,
+ 2767, 2768, 2769, 2769, 2770, 2770, 2770, 2771,
+ 2772, 2772, 2772, 2772, 2772, 2772, 2772, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
-
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2773,
- 2773, 2773, 2773, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2774, 2773, 2773,
- 2773, 2773, 2773, 2773, 2773, 2773, 2773, 2773,
- 2773, 2773, 2773, 2773, 2774, 2773, 2773, 2775,
- 2776, 2775, 2775, 2777, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 2774, 2774, 2774, 2774, 2774,
- 202, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 2778, 2778, 2778, 2778, 2778, 2778, 2778, 202,
- 2778, 2778, 2778, 2778, 2778, 2778, 2778, 2778,
- 2778, 2778, 2778, 2778, 2778, 2778, 2778, 2778,
- 2778, 202, 202, 2778, 2778, 2778, 2778, 2778,
- 2778, 2778, 202, 2778, 2778, 202, 2778, 2778,
- 2778, 2778, 2778, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
+ 2773, 2773, 2773, 2773, 2774, 2774, 2774, 2775,
+ 2775, 2775, 2775, 2775, 2775, 2775, 2775, 2775,
+ 2774, 2776, 2777, 2778, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
2779, 2779, 2779, 2779, 2779, 2779, 2779, 2779,
2779, 2779, 2779, 2779, 2779, 2779, 2779, 2779,
2779, 2779, 2779, 2779, 2779, 2779, 2779, 2779,
2779, 2779, 2779, 2779, 2779, 2779, 2779, 2779,
- 2779, 2779, 2779, 2779, 2779, 2779, 2779, 2779,
- 2779, 2779, 2779, 2779, 2779, 202, 202, 202,
- 2780, 2780, 2780, 2780, 2780, 2780, 2780, 2781,
- 2781, 2781, 2781, 2781, 2781, 2781, 202, 202,
- 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789,
- 2790, 2791, 202, 202, 202, 202, 2779, 2792,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793,
+ 2780, 2780, 2780, 2780, 2780, 2780, 2780, 2780,
+ 2780, 2780, 2780, 2780, 2780, 2780, 2780, 2780,
+ 2780, 2780, 2780, 2780, 2780, 2780, 2780, 2780,
+ 2780, 2780, 2780, 2780, 2780, 2780, 2780, 2780,
+ 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788,
+ 2789, 2790, 2791, 2791, 2791, 2791, 2791, 2791,
+ 2791, 2791, 2791, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 2792,
+
+ 2793, 2793, 2793, 2793, 2793, 2793, 2793, 221,
+ 221, 2793, 221, 221, 2793, 2793, 2793, 2793,
+ 2793, 2793, 2793, 2793, 221, 2793, 2793, 221,
2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793,
2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793,
2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793,
- 2793, 2793, 2793, 2793, 2793, 2793, 2793, 2793,
- 2793, 2793, 2793, 2793, 2794, 2794, 2794, 2794,
- 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802,
- 2803, 2804, 202, 202, 202, 202, 202, 2805,
-
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806,
- 2806, 2806, 2806, 2806, 2806, 301, 301, 2807,
- 2807, 2807, 2807, 2807, 2807, 2807, 2807, 2807,
- 2808, 2808, 2808, 2808, 2808, 2808, 2808, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2809, 2809, 2809, 2809, 2809, 2809, 2809, 2809,
- 2809, 2809, 2809, 2809, 2809, 2809, 2809, 2809,
- 2809, 2809, 2809, 2809, 2809, 2809, 2809, 2809,
- 2809, 2809, 2809, 2809, 2809, 2809, 2809, 2809,
- 2809, 2809, 2810, 2810, 2810, 2810, 2810, 2810,
- 2810, 2810, 2810, 2810, 2810, 2810, 2810, 2810,
- 2810, 2810, 2810, 2810, 2810, 2810, 2810, 2810,
- 2810, 2810, 2810, 2810, 2810, 2810, 2810, 2810,
- 2810, 2810, 2810, 2810, 2811, 2811, 2811, 2811,
- 2811, 2811, 2812, 2813, 301, 301, 301, 301,
- 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821,
- 2822, 2823, 301, 301, 301, 301, 2824, 2824,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
- 2825, 2825, 2825, 2825, 2826, 2825, 2825, 2825,
- 2827, 2825, 2825, 2825, 2825, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 301, 2828, 2828, 2828, 2828, 2828, 2828, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 2828, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 2828, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 2828, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 2828, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 2829, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 2828, 2828,
- 2828, 2828, 2828, 2828, 2828, 2828, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
- 301, 301, 301, 301, 301, 301, 301, 301,
-
- 2830, 2830, 2830, 2830, 348, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 348, 2830, 2830, 348, 2830, 348, 348, 2830,
- 348, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 348, 2830, 2830, 2830, 2830,
- 348, 2830, 348, 2830, 348, 348, 348, 348,
- 348, 348, 2830, 348, 348, 348, 348, 2830,
- 348, 2830, 348, 2830, 348, 2830, 2830, 2830,
- 348, 2830, 2830, 348, 2830, 348, 348, 2830,
- 348, 2830, 348, 2830, 348, 2830, 348, 2830,
- 348, 2830, 2830, 348, 2830, 348, 348, 2830,
- 2830, 2830, 2830, 348, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 348, 2830, 2830, 2830, 2830,
- 348, 2830, 2830, 2830, 2830, 348, 2830, 348,
- 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 348, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 348, 348, 348, 348,
- 348, 2830, 2830, 2830, 348, 2830, 2830, 2830,
- 2830, 2830, 348, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2830,
- 2830, 2830, 2830, 2830, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
- 2831, 2831, 348, 348, 348, 348, 348, 348,
- 348, 348, 348, 348, 348, 348, 348, 348,
-
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1733, 1733, 1733, 1733,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546,
- 1546, 1546, 1546, 1546, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1733,
- 1733, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1548,
- 1733, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1733, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 2832, 2832, 2833, 2834, 2835, 2836, 2837, 2838,
- 2839, 2840, 2841, 2842, 2842, 2843, 2843, 2843,
- 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844,
- 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844,
- 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844,
- 2844, 2844, 2844, 2844, 2844, 2844, 2844, 1597,
- 2845, 2846, 2845, 2845, 2845, 2845, 2845, 2845,
- 2845, 2845, 2845, 2845, 2845, 2846, 2845, 2846,
- 2845, 2845, 2846, 2845, 2845, 2845, 2846, 2845,
- 2845, 2845, 2844, 2844, 2844, 2844, 2844, 2847,
- 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2849,
- 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2849,
- 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2848,
- 2848, 2848, 2850, 2850, 2851, 2843, 2843, 2843,
- 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2848,
- 2848, 2849, 2848, 2849, 2849, 2848, 2848, 2849,
- 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2848,
- 2848, 2848, 813, 813, 813, 813, 2852, 2852,
- 2844, 2852, 2852, 2852, 2852, 2852, 2852, 2852,
- 2852, 2852, 2852, 2853, 2853, 2853, 2853, 2853,
- 2853, 2853, 2853, 2853, 2853, 2853, 2853, 2853,
- 2853, 2853, 2853, 2853, 2853, 2843, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 2854, 2854,
- 2854, 2854, 2854, 2854, 2854, 2854, 2854, 2854,
- 2854, 2854, 2854, 2854, 2854, 2854, 2854, 2854,
- 2854, 2854, 2854, 2854, 2854, 2854, 2854, 2854,
-
- 2855, 2856, 2856, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
- 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
- 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
- 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
- 1716, 1716, 2856, 2856, 2856, 2856, 2856, 2856,
- 2856, 2856, 2856, 2857, 1733, 1733, 1733, 1733,
- 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
- 1716, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2856, 2856, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2858, 2858, 2858, 2858, 2858, 2858, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 2859, 2859, 2859,
- 1511, 1511, 1511, 1511, 1511, 1511, 1548, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1548, 2859, 2859,
- 1511, 1511, 1511, 1511, 1511, 1549, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1512, 1512, 1548, 1548,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1510, 1510, 1511,
- 1511, 1511, 1511, 1511, 1510, 1511, 1511, 1511,
- 1511, 1511, 1549, 1549, 1549, 1548, 1511, 1549,
- 1511, 1511, 1549, 2860, 2860, 1548, 1548, 2859,
- 2859, 2859, 2859, 2859, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 2859, 2859, 2859, 2861, 2861, 2861, 2861, 2861,
-
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1548,
- 1511, 1548, 1549, 1549, 1511, 1511, 1549, 1549,
- 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549,
- 1549, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1549, 1549,
- 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549,
- 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549,
- 1549, 1511, 1511, 1511, 1549, 1511, 1511, 1511,
- 1511, 1549, 1549, 1549, 1511, 1549, 1549, 1549,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1549,
- 1511, 1549, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1510, 1511, 1510, 1511, 1510, 1511, 1511, 1511,
- 1511, 1511, 1549, 1511, 1511, 1511, 1511, 1510,
- 1511, 1510, 1510, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1548, 1511, 1511, 1511, 1511, 1548, 1548, 2859,
-
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1512, 1512,
- 2862, 2862, 2862, 2862, 1512, 1512, 1512, 1512,
- 1512, 1512, 1548, 2859, 2859, 2859, 2859, 2859,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 2860, 2860, 1548, 1548,
- 1548, 1548, 2863, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 2860, 1548, 1548, 1548, 1548, 2860, 2860, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 2864, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1512, 1512, 1512, 1512,
- 1512, 1512, 1548, 1511, 1511, 1511, 1511, 1511,
-
- 2865, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 2865, 1511, 1511, 1511, 2865, 1511, 2865,
- 1511, 2865, 1511, 2865, 1511, 1511, 1511, 2865,
- 1511, 1511, 1511, 1511, 1511, 1511, 2865, 2865,
- 1511, 1511, 1511, 1511, 2865, 1511, 2865, 2865,
- 1511, 1511, 1511, 1511, 2865, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1548, 1548, 2859, 2859, 1549, 1549, 1549,
- 1511, 1511, 1511, 1549, 1549, 1549, 1549, 1549,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 2866, 2866,
- 2866, 2867, 2867, 2867, 1512, 1512, 1512, 1512,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1549, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1511, 1511, 1511, 1511, 1549, 1549, 1549, 1511,
- 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,
- 1549, 1511, 1511, 1511, 1511, 1511, 1548, 1548,
- 1548, 1548, 1548, 1548, 2860, 1548, 1548, 1548,
- 2859, 2864, 2864, 2858, 2858, 2868, 2843, 2843,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
- 1548, 1548, 1548, 1548, 1548, 1733, 1733, 1733,
- 1548, 1548, 1548, 1548, 2864, 2864, 2864, 2858,
- 2858, 2869, 2868, 2843, 2843, 1733, 1733, 1733,
-
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510,
- 1510, 1510, 1510, 1510, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 2869, 2869, 2869,
- 2869, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2868, 2868, 2868, 2868, 2868, 2868, 2868, 2868,
- 2868, 2868, 2868, 2868, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1733, 1733, 1733, 1733,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1733, 1733, 1733, 1733, 1733, 1733,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512,
- 1512, 1512, 1512, 1512, 1512, 1512, 1733, 1733,
- 2843, 2843, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514,
- 1514, 1514, 1514, 1514, 2870, 2868, 2868, 2871,
- 2859, 2859, 2859, 2859, 2859, 2859, 2859, 2859,
- 2872, 2863, 2863, 2863, 2863, 2863, 2863, 2873,
- 2864, 2864, 2864, 2864, 2864, 2864, 2863, 2864,
+ 2794, 2795, 2795, 2795, 2795, 2795, 221, 2795,
+ 2796, 221, 221, 2797, 2797, 2798, 2799, 2800,
+ 2795, 2800, 2795, 2801, 2802, 2803, 2802, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811,
+ 2812, 2813, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2814, 2814, 2814, 2814, 2814, 2814, 2814, 2814,
+ 221, 221, 2814, 2814, 2814, 2814, 2814, 2814,
+ 2814, 2814, 2814, 2814, 2814, 2814, 2814, 2814,
+ 2814, 2814, 2814, 2814, 2814, 2814, 2814, 2814,
+ 2814, 2814, 2814, 2814, 2814, 2814, 2814, 2814,
+ 2814, 2814, 2814, 2814, 2814, 2814, 2814, 2814,
+ 2814, 2815, 2815, 2815, 2816, 2816, 2816, 2816,
+ 221, 221, 2816, 2816, 2815, 2815, 2815, 2815,
+ 2817, 2814, 2818, 2814, 2815, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2819, 2820, 2820, 2820, 2820, 2820, 2820, 2821,
+ 2821, 2820, 2820, 2819, 2819, 2819, 2819, 2819,
+ 2819, 2819, 2819, 2819, 2819, 2819, 2819, 2819,
+ 2819, 2819, 2819, 2819, 2819, 2819, 2819, 2819,
+ 2819, 2819, 2819, 2819, 2819, 2819, 2819, 2819,
+ 2819, 2819, 2819, 2819, 2819, 2819, 2819, 2819,
+ 2819, 2819, 2819, 2820, 2822, 2820, 2820, 2820,
+ 2820, 2823, 2824, 2820, 2820, 2820, 2820, 2825,
+ 2826, 2827, 2828, 2828, 2827, 2825, 2826, 2822,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2829, 2830, 2830, 2830, 2830, 2830, 2830, 2831,
+ 2831, 2830, 2830, 2830, 2829, 2829, 2829, 2829,
+ 2829, 2829, 2829, 2829, 2829, 2829, 2829, 2829,
+ 2829, 2829, 2829, 2829, 2829, 2829, 2829, 2829,
+ 2829, 2829, 2829, 2829, 2829, 2829, 2829, 2829,
+ 2829, 2829, 2829, 2829, 2829, 2829, 2829, 2829,
+ 2829, 2829, 2829, 2829, 2832, 2832, 2833, 2833,
+ 2833, 2833, 2830, 2830, 2830, 2830, 2830, 2830,
+ 2830, 2830, 2830, 2830, 2830, 2830, 2830, 2831,
+ 2830, 2834, 2835, 2836, 2836, 2837, 2838, 2838,
+ 2838, 2835, 2835, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2839, 2839, 2839, 2839, 2839, 2839, 2839, 2839,
+ 2839, 2839, 2839, 2839, 2839, 2839, 2839, 2839,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 2840, 2840, 2840, 2840, 2840, 2840, 2840,
+ 2840, 221, 221, 221, 221, 221, 221, 221,
+
+ 2841, 2841, 2841, 2841, 2841, 2841, 2841, 2841,
+ 2841, 2841, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2842, 2842, 2842, 2842, 2842, 2842, 2842, 2842,
+ 2842, 221, 2842, 2842, 2842, 2842, 2842, 2842,
+ 2842, 2842, 2842, 2842, 2842, 2842, 2842, 2842,
+ 2842, 2842, 2842, 2842, 2842, 2842, 2842, 2842,
+ 2842, 2842, 2842, 2842, 2842, 2842, 2842, 2842,
+ 2842, 2842, 2842, 2842, 2842, 2842, 2842, 2843,
+ 2844, 2844, 2844, 2844, 2844, 2844, 2844, 221,
+ 2844, 2844, 2844, 2844, 2844, 2844, 2843, 2845,
+ 2842, 2846, 2846, 2847, 2847, 2847, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855,
+ 2856, 2857, 2858, 2858, 2858, 2858, 2858, 2858,
2858, 2858, 2858, 2858, 2858, 2858, 2858, 2858,
- 2863, 2873, 2873, 2863, 2863, 2863, 2863, 2863,
- 2863, 2863, 2864, 2864, 2863, 2863, 2863, 2868,
+ 2858, 2858, 2858, 2858, 2858, 221, 221, 221,
+ 2859, 2860, 2861, 2861, 2861, 2861, 2861, 2861,
+ 2861, 2861, 2861, 2861, 2861, 2861, 2861, 2861,
+ 2861, 2861, 2861, 2861, 2861, 2861, 2861, 2861,
+ 2861, 2861, 2861, 2861, 2861, 2861, 2861, 2861,
+ 221, 221, 2862, 2862, 2862, 2862, 2862, 2862,
+ 2862, 2862, 2862, 2862, 2862, 2862, 2862, 2862,
+ 2862, 2862, 2862, 2862, 2862, 2862, 2862, 2862,
+ 221, 2863, 2862, 2862, 2862, 2862, 2862, 2862,
+ 2862, 2863, 2862, 2862, 2863, 2862, 2862, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2864, 2864, 2864, 2864, 2864, 2864, 2864, 221,
+ 2864, 2864, 221, 2864, 2864, 2864, 2864, 2864,
2864, 2864, 2864, 2864, 2864, 2864, 2864, 2864,
- 2864, 2864, 2864, 2864, 2858, 2869, 2869, 2869,
2864, 2864, 2864, 2864, 2864, 2864, 2864, 2864,
- 2864, 2864, 2864, 2864, 2864, 2864, 2864, 2858,
- 2858, 2858, 2858, 2858, 2858, 2858, 2858, 2858,
- 2858, 2858, 2858, 2858, 2869, 2869, 2869, 2869,
- 2869, 2868, 2843, 2869, 2869, 2869, 2869, 2870,
- 2843, 1733, 2869, 2868, 2869, 2869, 2869, 2869,
- 2859, 2859, 2859, 2859, 2859, 2864, 2864, 2864,
2864, 2864, 2864, 2864, 2864, 2864, 2864, 2864,
- 2864, 2864, 2858, 2858, 2858, 2858, 2858, 2858,
- 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869,
- 2869, 2869, 2869, 2843, 2843, 2868, 2868, 2868,
- 2868, 2868, 2868, 2843, 2843, 2843, 2868, 2868,
- 2869, 2869, 2869, 2869, 2869, 2874, 2874, 2869,
- 2874, 2874, 2868, 2871, 2868, 2868, 2868, 2868,
- 2859, 2869, 2869, 2868, 2868, 2868, 2868, 2868,
- 2868, 2868, 2868, 2843, 1733, 2871, 2871, 2871,
- 2858, 2873, 2873, 2873, 2873, 2873, 2873, 2873,
- 2873, 2873, 2873, 2873, 2873, 2873, 2858, 2858,
- 2858, 2858, 2858, 2858, 2858, 2858, 2858, 2869,
- 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869,
- 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869,
- 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869,
-
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
- 1598, 1598, 1598, 1598, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869,
- 2869, 2869, 2869, 2869, 2869, 2869, 1733, 1733,
- 2868, 2868, 2868, 2868, 2843, 1733, 1733, 1733,
- 2868, 2868, 2868, 1733, 1733, 1733, 1733, 1733,
- 2868, 2868, 2868, 2843, 2843, 2843, 2843, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2868, 2868, 2868, 2868, 2868, 2868, 2843, 2843,
- 2843, 2843, 2843, 2843, 2843, 2843, 2843, 2843,
- 2843, 2843, 2843, 2843, 2843, 2843, 2843, 2843,
- 2843, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2843, 2843, 2843, 2843, 2843, 2843, 2843, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2843, 2843, 2843, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2843, 2843, 2843, 2843, 2843, 2843, 2843, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 202, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596,
- 1596, 1596, 1596, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882,
- 2883, 2884, 202, 202, 202, 202, 202, 202,
-
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 2885, 2885,
-
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
-
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 2886,
- 2886, 2886, 2886, 2886, 2886, 2886, 2886, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
- 1728, 1728, 1728, 1728, 1728, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
-
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 2887, 2887,
- 2887, 2887, 2887, 2887, 2887, 2887, 1733, 1733,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
-
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
-
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730,
- 1730, 1730, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
-
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
-
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731,
- 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
-
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
- 2888, 2888, 2888, 2888, 2888, 2888, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
-
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
- 1724, 1724, 1724, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
- 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733,
-
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 2885, 2885,
-
- 1403, 2749, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
-
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 2890, 2890, 2890, 2890, 2890, 2890, 2890, 2890,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
-
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
- 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403,
-
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
-
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2891, 2891,
- 2891, 2891, 2891, 2891, 2891, 2891, 2885, 2885
+ 2864, 2864, 2864, 2864, 2864, 2864, 2864, 2864,
+ 2864, 2865, 2865, 2865, 2865, 2865, 2865, 221,
+ 221, 221, 2865, 221, 2865, 2865, 221, 2865,
+ 2865, 2865, 2866, 2865, 2867, 2867, 2868, 2865,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876,
+ 2877, 2878, 221, 221, 221, 221, 221, 221,
+ 2879, 2879, 2879, 2879, 2879, 2879, 221, 2879,
+ 2879, 221, 2879, 2879, 2879, 2879, 2879, 2879,
+ 2879, 2879, 2879, 2879, 2879, 2879, 2879, 2879,
+ 2879, 2879, 2879, 2879, 2879, 2879, 2879, 2879,
+ 2879, 2879, 2879, 2879, 2879, 2879, 2879, 2879,
+ 2879, 2879, 2880, 2880, 2880, 2880, 2880, 221,
+ 2881, 2881, 221, 2880, 2880, 2881, 2880, 2882,
+ 2879, 221, 221, 221, 221, 221, 221, 221,
+ 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890,
+ 2891, 2892, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2893, 2893, 2893, 2893, 2893, 2893, 2893, 2893,
+ 2893, 2893, 2893, 2893, 2893, 2893, 2893, 2893,
+ 2893, 2893, 2894, 2895, 2895, 2896, 2896, 2897,
+ 2897, 221, 221, 221, 221, 221, 221, 221,
+
+ 2898, 2898, 2899, 2900, 2901, 2901, 2901, 2901,
+ 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901,
+ 2901, 221, 2901, 2901, 2901, 2901, 2901, 2901,
+ 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901,
+ 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901,
+ 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901,
+ 2901, 2901, 2901, 2901, 2900, 2900, 2898, 2898,
+ 2898, 2898, 2898, 221, 221, 221, 2900, 2900,
+ 2898, 2902, 2903, 2904, 2904, 2905, 2905, 2905,
+ 2905, 2905, 2905, 2905, 2905, 2905, 2905, 2905,
+ 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913,
+ 2914, 2915, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2916, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2917, 2917, 2917, 2917, 2917, 2917, 2917, 2917,
+ 2917, 2917, 2917, 2917, 2917, 2917, 2917, 2917,
+ 2917, 2917, 2917, 2917, 2917, 2918, 2918, 2918,
+ 2918, 2918, 2918, 2918, 2918, 2919, 2919, 2919,
+ 2919, 2918, 2918, 2918, 2918, 2918, 2918, 2918,
+ 2918, 2918, 2918, 2918, 2918, 2918, 2918, 2918,
+ 2918, 2918, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 2920,
+
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2921,
+ 2921, 2921, 2921, 2921, 2921, 2921, 2921, 2922,
+ 2922, 2922, 2922, 2922, 2922, 2922, 2922, 2922,
+ 2922, 2922, 2922, 2922, 2922, 2922, 2922, 2922,
+ 2922, 2922, 2922, 2922, 2922, 2922, 2922, 2922,
+ 2922, 2922, 2922, 2922, 2922, 2922, 2922, 2922,
+ 2922, 2922, 2922, 2922, 2922, 2922, 2922, 2922,
+ 2922, 2923, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2924, 2924, 2924, 2924, 2924,
+ 2924, 2924, 2924, 2925, 2925, 2925, 2925, 2925,
+ 2925, 2925, 2925, 2925, 2925, 2925, 2925, 221,
+ 2926, 2926, 2926, 2926, 2927, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 2923, 2923, 2923, 2923,
+ 2923, 2923, 2923, 2923, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2928, 2928, 2928, 2928, 2928, 2928, 2928,
+ 2928, 2929, 2929, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2931, 2931, 2931, 2932, 2932, 2932, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2932, 2930, 2930, 2930, 2931, 2932,
+ 2931, 2932, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2931, 2932, 2932, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2930,
+ 2930, 2930, 2930, 2930, 2930, 2930, 2930, 2933,
+ 2934, 2934, 2934, 2934, 2934, 2934, 2934, 2935,
+ 2936, 2937, 2937, 2937, 2938, 2939, 2938, 2939,
+ 2940, 2941, 2941, 2941, 2941, 2941, 2941, 2940,
+ 2940, 2940, 2940, 2940, 2940, 2940, 2940, 2940,
+ 2940, 2940, 2940, 2940, 2940, 2940, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2943, 2944,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 2942,
+ 2942, 2942, 2942, 2942, 2942, 2942, 2942, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945,
+ 2945, 221, 221, 221, 221, 221, 221, 221,
+ 2946, 2946, 2946, 2946, 2946, 2946, 2946, 2946,
+ 2946, 2946, 2946, 2946, 2946, 2946, 2946, 2946,
+ 2946, 2946, 2946, 2946, 2946, 2946, 2946, 2946,
+ 2946, 2946, 2946, 2946, 2946, 2946, 2946, 221,
+ 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954,
+ 2955, 2956, 221, 221, 221, 221, 2957, 2957,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 2958,
+ 2958, 2958, 2958, 2958, 2958, 2958, 2958, 221,
+ 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966,
+ 2967, 2968, 221, 221, 221, 221, 221, 221,
+ 2969, 2969, 2969, 2969, 2969, 2969, 2969, 2969,
+ 2969, 2969, 2969, 2969, 2969, 2969, 2969, 2969,
+ 2969, 2969, 2969, 2969, 2969, 2969, 2969, 2969,
+ 2969, 2969, 2969, 2969, 2969, 2969, 221, 221,
+ 2970, 2970, 2970, 2970, 2970, 2971, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2973, 2973, 2973, 2973, 2973, 2973, 2973, 2974,
+ 2974, 2975, 2976, 2976, 2977, 2977, 2977, 2977,
+ 2978, 2978, 2978, 2978, 2974, 2977, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986,
+ 2987, 2988, 221, 2989, 2989, 2989, 2989, 2989,
+ 2989, 2989, 221, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 221, 221, 221, 221, 221, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 2972, 2972, 2972, 2972, 2972, 2972, 2972, 2972,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 2990, 2990, 2990, 2990, 2990, 2990, 2990, 2990,
+ 2990, 2990, 2990, 2990, 2990, 2990, 2990, 2990,
+ 2990, 2990, 2990, 2990, 2990, 2990, 2990, 2990,
+ 2990, 2990, 2990, 2990, 2990, 2990, 2990, 2990,
+ 2991, 2991, 2991, 2991, 2991, 2991, 2991, 2991,
+ 2991, 2991, 2991, 2991, 2991, 2991, 2991, 2991,
+ 2991, 2991, 2991, 2991, 2991, 2991, 2991, 2991,
+ 2991, 2991, 2991, 2991, 2991, 2991, 2991, 2991,
+ 2992, 2992, 2992, 2992, 2992, 2992, 2992, 2992,
+ 2992, 2992, 2992, 2992, 2992, 2992, 2992, 2992,
+ 2992, 2992, 2992, 2992, 2992, 2992, 2992, 2993,
+ 2994, 2995, 2995, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2996, 2996, 2996,
+ 2996, 2996, 2996, 2996, 2996, 2997, 2997, 2997,
+ 2997, 2997, 2997, 221, 221, 221, 221, 2998,
+ 2996, 2999, 2999, 2999, 2999, 2999, 2999, 2999,
+ 2999, 2999, 2999, 2999, 2999, 2999, 2999, 2999,
+ 2999, 2999, 2999, 2999, 2999, 2999, 2999, 2999,
+ 2999, 2999, 2999, 2999, 2999, 2999, 2999, 2999,
+ 2999, 2999, 2999, 2999, 2999, 2999, 2999, 2999,
+ 2999, 2999, 2999, 2999, 2999, 2999, 2999, 3000,
+ 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000,
+ 221, 221, 221, 221, 221, 221, 221, 3001,
+ 3001, 3001, 3001, 3002, 3002, 3002, 3002, 3002,
+ 3002, 3002, 3002, 3002, 3002, 3002, 3002, 3002,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3003, 3004, 3005, 3006, 3007, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3008, 3008, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3010, 3010, 3010,
+ 3010, 3010, 3011, 3011, 3011, 3011, 3011, 3011,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3009, 3009, 3009, 3009, 3009,
+ 3009, 3009, 3009, 3012, 3012, 3012, 3012, 3012,
+ 3012, 3012, 3012, 3012, 3012, 3012, 3012, 3012,
+
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 3013, 3013,
+ 3013, 3013, 3013, 3013, 3013, 3013, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3012, 3012, 3012, 3012, 3012, 3012, 3012, 3012,
+ 3012, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3014, 3014, 3014, 3014, 221, 3014, 3014, 3014,
+ 3014, 3014, 3014, 3014, 221, 3014, 3014, 221,
+
+ 3015, 3016, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3017,
+ 3017, 3017, 3017, 3017, 3017, 3017, 3017, 3018,
+ 3019, 3019, 3019, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 3020, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3021, 3021, 3021, 221, 221, 3022, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 3023, 3023, 3023, 3023,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 3024, 3024, 3024, 3024,
+ 3024, 3024, 3024, 3024, 221, 221, 221, 221,
+
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 221, 221, 221, 221, 221,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 3025, 3025, 3025, 221, 221, 221,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 221, 221, 221, 221, 221, 221, 221,
+ 3025, 3025, 3025, 3025, 3025, 3025, 3025, 3025,
+ 3025, 3025, 221, 221, 3026, 3027, 3028, 3029,
+ 3030, 3030, 3030, 3030, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 221, 221,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 3031,
+ 3031, 3031, 3031, 3031, 3031, 3031, 3031, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 3032, 3032, 3032, 3032,
+ 3032, 3032, 3032, 3032, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 221,
+ 221, 1544, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3034, 3034,
+ 3034, 3034, 3034, 3034, 3034, 3035, 3036, 3037,
+ 3037, 3037, 3033, 3033, 3033, 3038, 3035, 3035,
+ 3035, 3035, 3035, 3039, 3039, 3039, 3039, 3039,
+ 3039, 3039, 3039, 3040, 3040, 3040, 3040, 3040,
+ 3040, 3040, 3040, 3033, 3033, 3041, 3041, 3041,
+ 3041, 3041, 3040, 3040, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3041, 3041, 3041, 3041, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3034, 3034, 3034, 3034, 3034,
+ 3034, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3033, 3033,
+ 3033, 3033, 3033, 3033, 3033, 3033, 3042, 3042,
+ 3042, 3042, 3042, 3042, 3042, 3042, 3042, 3042,
+ 3042, 3043, 3043, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 2353, 2353, 2353, 2353, 2353, 2353,
+ 2353, 2353, 3044, 3044, 3044, 2353, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3045, 3045, 3045, 3045, 3045, 3045, 3045, 3045,
+ 3045, 3045, 3045, 3045, 3045, 3045, 3045, 3045,
+ 3045, 3045, 3045, 3045, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+ 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+ 3046, 3046, 3046, 3046, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606,
+ 1606, 1606, 1606, 1606, 1606, 1606, 1606, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3047, 3047, 3047, 3047, 3047, 3047, 3047, 3047,
+ 3047, 3047, 3047, 3047, 3047, 3047, 3047, 3047,
+ 3047, 3047, 3046, 3046, 3046, 3046, 3046, 3046,
+ 3046, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 221, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3048, 221, 3048, 3048,
+ 221, 221, 3048, 221, 221, 3048, 3048, 221,
+ 221, 3048, 3048, 3048, 3048, 221, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3049, 3049,
+ 3049, 3049, 221, 3049, 221, 3049, 3049, 3049,
+ 3049, 3050, 3049, 3049, 221, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+
+ 3049, 3049, 3049, 3049, 3048, 3048, 221, 3048,
+ 3048, 3048, 3048, 221, 221, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 221, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 221, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 221, 3048, 3048, 3048, 3048, 221,
+ 3048, 3048, 3048, 3048, 3048, 221, 3048, 221,
+ 221, 221, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 221, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 1536, 1536, 221, 221,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3051, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3052, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3051, 3049, 3049, 3049, 3049,
+
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3052, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3051, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3052,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3051,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3052, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3048, 3048, 3048, 3048, 3048, 3048, 3048,
+ 3048, 3051, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3049, 3052, 3049, 3049, 3049, 3049,
+ 3049, 3049, 3053, 3054, 221, 221, 3055, 3056,
+ 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064,
+ 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062,
+ 3063, 3064, 3055, 3056, 3057, 3058, 3059, 3060,
+ 3061, 3062, 3063, 3064, 3055, 3056, 3057, 3058,
+ 3059, 3060, 3061, 3062, 3063, 3064, 3055, 3056,
+ 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064,
+
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3065,
+ 3065, 3065, 3065, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3066, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3065, 3065, 3065, 3065,
+ 3065, 3065, 3065, 3065, 3066, 3065, 3065, 3067,
+ 3068, 3067, 3067, 3069, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 3066, 3066, 3066, 3066, 3066,
+ 221, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 3066, 3066, 3066, 3066, 3066, 3066, 3066, 3066,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 1988, 1988, 1988, 1988, 1988, 1988, 1988, 1988,
+ 1988, 1988, 3070, 1988, 1988, 1988, 1988, 1988,
+ 1988, 1988, 1988, 1988, 1988, 1988, 1988, 1988,
+ 1988, 1988, 1988, 1988, 1988, 1988, 1988, 221,
+ 221, 221, 221, 221, 221, 3071, 3071, 3071,
+ 3071, 3071, 3071, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3072, 3072, 3072, 3072, 3072, 3072, 3072, 221,
+ 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072,
+ 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072,
+ 3072, 221, 221, 3072, 3072, 3072, 3072, 3072,
+ 3072, 3072, 221, 3072, 3072, 221, 3072, 3072,
+ 3072, 3072, 3072, 221, 221, 221, 221, 221,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 3073, 3073,
+ 3073, 3073, 3073, 3073, 3073, 3073, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 3074,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 3075, 3075, 3075, 3075, 3075, 3075, 3075, 3075,
+ 3075, 3075, 3075, 3075, 3075, 3075, 3075, 3075,
+ 3075, 3075, 3075, 3075, 3075, 3075, 3075, 3075,
+ 3075, 3075, 3075, 3075, 3075, 3075, 3075, 3075,
+ 3075, 3075, 3075, 3075, 3075, 3075, 3075, 3075,
+ 3075, 3075, 3075, 3075, 3075, 221, 221, 221,
+ 3076, 3076, 3076, 3076, 3076, 3076, 3076, 3077,
+ 3077, 3077, 3077, 3077, 3077, 3077, 221, 221,
+ 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085,
+ 3086, 3087, 221, 221, 221, 221, 3075, 3088,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3089, 3089, 3089, 3089, 3089, 3089, 3089, 3089,
+ 3089, 3089, 3089, 3089, 3089, 3089, 3089, 3089,
+ 3089, 3089, 3089, 3089, 3089, 3089, 3089, 3089,
+ 3089, 3089, 3089, 3089, 3089, 3089, 3090, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3091, 3091, 3091, 3091, 3091, 3091, 3091, 3091,
+ 3091, 3091, 3091, 3091, 3091, 3091, 3091, 3091,
+ 3091, 3091, 3091, 3091, 3091, 3091, 3091, 3091,
+ 3091, 3091, 3091, 3091, 3091, 3091, 3091, 3091,
+ 3091, 3091, 3091, 3091, 3091, 3091, 3091, 3091,
+ 3091, 3091, 3091, 3091, 3092, 3092, 3092, 3092,
+ 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100,
+ 3101, 3102, 221, 221, 221, 221, 221, 3103,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3104, 3104, 3104, 3104, 3104, 3104, 3104, 3104,
+ 3104, 3104, 3104, 3104, 3104, 3104, 3104, 3104,
+ 3104, 3104, 3104, 3104, 3104, 3104, 3104, 3104,
+ 3104, 3104, 3104, 3105, 3106, 3106, 3107, 3108,
+ 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116,
+ 3117, 3118, 221, 221, 221, 221, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3119, 3119, 3119, 3119, 3119, 3119, 3119, 221,
+ 3119, 3119, 3119, 3119, 221, 3119, 3119, 221,
+ 3119, 3119, 3119, 3119, 3119, 3119, 3119, 3119,
+ 3119, 3119, 3119, 3119, 3119, 3119, 3119, 221,
+
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 3120, 3120, 3120,
+ 3120, 3120, 3120, 3120, 3120, 323, 323, 3121,
+ 3121, 3121, 3121, 3121, 3121, 3121, 3121, 3121,
+ 3122, 3122, 3122, 3122, 3122, 3122, 3122, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 3123, 3123, 3123, 3123, 3123, 3123, 3123, 3123,
+ 3123, 3123, 3123, 3123, 3123, 3123, 3123, 3123,
+ 3123, 3123, 3123, 3123, 3123, 3123, 3123, 3123,
+ 3123, 3123, 3123, 3123, 3123, 3123, 3123, 3123,
+ 3123, 3123, 3124, 3124, 3124, 3124, 3124, 3124,
+ 3124, 3124, 3124, 3124, 3124, 3124, 3124, 3124,
+ 3124, 3124, 3124, 3124, 3124, 3124, 3124, 3124,
+ 3124, 3124, 3124, 3124, 3124, 3124, 3124, 3124,
+ 3124, 3124, 3124, 3124, 3125, 3125, 3125, 3125,
+ 3125, 3125, 3126, 3127, 323, 323, 323, 323,
+ 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135,
+ 3136, 3137, 323, 323, 323, 323, 3138, 3138,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3139, 3139, 3139, 3139,
+ 3139, 3139, 3139, 3139, 3140, 3139, 3139, 3139,
+ 3141, 3139, 3139, 3139, 3139, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 323, 3142, 3142, 3142, 3142, 3142, 3142, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 3142, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 3142, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 3142, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 3142, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 3143, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 3142, 3142,
+ 3142, 3142, 3142, 3142, 3142, 3142, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323,
+
+ 3144, 3144, 3144, 3144, 437, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 437, 3144, 3144, 437, 3144, 437, 437, 3144,
+ 437, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 437, 3144, 3144, 3144, 3144,
+ 437, 3144, 437, 3144, 437, 437, 437, 437,
+ 437, 437, 3144, 437, 437, 437, 437, 3144,
+ 437, 3144, 437, 3144, 437, 3144, 3144, 3144,
+ 437, 3144, 3144, 437, 3144, 437, 437, 3144,
+ 437, 3144, 437, 3144, 437, 3144, 437, 3144,
+ 437, 3144, 3144, 437, 3144, 437, 437, 3144,
+ 3144, 3144, 3144, 437, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 437, 3144, 3144, 3144, 3144,
+ 437, 3144, 3144, 3144, 3144, 437, 3144, 437,
+ 3144, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 437, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 437, 437, 437, 437,
+ 437, 3144, 3144, 3144, 437, 3144, 3144, 3144,
+ 3144, 3144, 437, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 3144, 3144, 3144, 3144,
+ 3144, 3144, 3144, 3144, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+ 3145, 3145, 437, 437, 437, 437, 437, 437,
+ 437, 437, 437, 437, 437, 437, 437, 437,
+
+ 1681, 1681, 1681, 1681, 3146, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 3147, 3147, 3147, 3147,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
+ 1681, 1681, 1681, 1681, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612,
+ 1612, 1612, 1612, 1612, 1612, 1612, 1612, 3147,
+ 3147, 1612, 1612, 1612, 1612, 1612, 1612, 1612,
+ 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1683,
+ 3147, 1612, 1612, 1612, 1612, 1612, 1612, 1612,
+ 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1611,
+ 3147, 1612, 1612, 1612, 1612, 1612, 1612, 1612,
+ 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+
+ 3148, 3148, 3149, 3150, 3151, 3152, 3153, 3154,
+ 3155, 3156, 3157, 3158, 3158, 3159, 3159, 3159,
+ 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
+ 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
+ 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
+ 3160, 3160, 3161, 3161, 3161, 3161, 3162, 3163,
+ 3164, 3165, 3164, 3164, 3164, 3164, 3164, 3164,
+ 3164, 3164, 3164, 3164, 3164, 3165, 3164, 3165,
+ 3164, 3164, 3165, 3164, 3164, 3164, 3165, 3164,
+ 3164, 3164, 3161, 3161, 3161, 3161, 3161, 3166,
+ 3167, 3167, 3167, 3167, 3167, 3167, 3167, 3168,
+ 3167, 3167, 3167, 3167, 3167, 3167, 3167, 3168,
+ 3167, 3167, 3167, 3167, 3167, 3167, 3167, 3167,
+ 3167, 3167, 3169, 3169, 3170, 3159, 3159, 3159,
+ 3171, 3171, 3167, 3167, 3167, 3167, 3167, 3167,
+ 3167, 3168, 3167, 3168, 3168, 3167, 3171, 3172,
+ 3167, 3167, 3167, 3167, 3167, 3167, 3167, 3167,
+ 3167, 3167, 3173, 3173, 3173, 3173, 3174, 3175,
+ 3161, 3174, 3174, 3174, 3174, 3174, 3174, 3174,
+ 3174, 3174, 3174, 3176, 3176, 3176, 3176, 3176,
+ 3176, 3176, 3176, 3176, 3176, 3176, 3176, 3176,
+ 3176, 3176, 3176, 3176, 3176, 3159, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3177, 3177,
+ 3177, 3177, 3177, 3177, 3177, 3177, 3177, 3177,
+ 3177, 3177, 3177, 3177, 3177, 3177, 3177, 3177,
+ 3177, 3177, 3177, 3177, 3177, 3177, 3177, 3177,
+
+ 3178, 3179, 3179, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891,
+ 1891, 1891, 3180, 1891, 1891, 1891, 1891, 1891,
+ 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891,
+ 1891, 1891, 1891, 1891, 1891, 1891, 1891, 3180,
+ 1891, 1891, 3179, 3179, 3179, 3179, 3179, 3179,
+ 3179, 3179, 3179, 3181, 3147, 3147, 3147, 3147,
+ 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891,
+ 1891, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3179, 3179, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3182, 3182, 3182, 3182, 3182, 3182, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 3183, 3183, 3183,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1683, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1683, 3183, 3183,
+ 1611, 1611, 1611, 1611, 1611, 1684, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1614, 1614, 1683, 1683,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1609, 1609, 1611,
+ 1611, 1611, 1611, 1611, 1609, 1611, 1611, 1611,
+ 1611, 1611, 1684, 1684, 1684, 3184, 1611, 1684,
+ 1611, 1611, 1684, 3185, 3185, 1683, 1683, 3183,
+ 3183, 3183, 3183, 3183, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1683, 1683, 1683, 3184, 1683, 1683, 1683,
+ 3183, 3183, 3183, 3186, 3186, 3186, 3186, 3186,
+
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1683,
+ 1611, 1683, 1684, 1684, 1611, 1611, 1684, 1684,
+ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
+ 1684, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1684, 1684,
+ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
+ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
+ 1684, 1611, 1611, 1611, 1684, 1611, 1611, 1611,
+ 1611, 1684, 1684, 1684, 1611, 1684, 1684, 1684,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1684,
+ 1611, 1684, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1609, 1611, 1609, 1611, 1609, 1611, 1611, 1611,
+ 1611, 1611, 1684, 1611, 1611, 1611, 1611, 1609,
+ 1611, 1609, 1609, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 3184, 1611, 1611, 1611, 1611, 1683, 1683, 3183,
+
+ 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1609,
+ 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609,
+ 1609, 1609, 1609, 1609, 1609, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1609, 1609, 1609, 1609, 1609, 1609,
+ 1609, 1609, 1609, 1609, 1609, 1609, 1613, 1613,
+ 3187, 3187, 3187, 3187, 1613, 1613, 1614, 1614,
+ 1614, 1614, 1683, 3183, 3183, 3183, 3183, 3188,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 3185, 3185, 1683, 1683,
+ 1683, 1683, 3189, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 3185, 1683, 1683, 1683, 1683, 3190, 3190, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 3191, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1614, 1614, 1614, 1614,
+ 1614, 1614, 1614, 1614, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 1683, 1614, 1614, 1614, 1614,
+ 1614, 1614, 1683, 1611, 1611, 1611, 1611, 1611,
+
+ 3192, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 3192, 1611, 1611, 1611, 3192, 1611, 3192,
+ 1611, 3192, 1611, 3192, 1611, 1611, 1611, 3192,
+ 1611, 1611, 1611, 1611, 1611, 1611, 3192, 3192,
+ 1611, 1611, 1611, 1611, 3192, 1611, 3192, 3192,
+ 1611, 1611, 1611, 1611, 3192, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 3184, 3184, 3183, 3183, 1684, 1684, 1684,
+ 1611, 1611, 1611, 1684, 1684, 1684, 1684, 1684,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 3193, 3193,
+ 3193, 3194, 3194, 3194, 1613, 1613, 1613, 1613,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1684, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1611, 1611, 1611, 1611, 1684, 1684, 1684, 1611,
+ 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611,
+ 1684, 1611, 1611, 1611, 1611, 1611, 1683, 1683,
+ 1683, 1683, 1683, 1683, 3190, 1683, 1683, 1683,
+ 3183, 3191, 3191, 3195, 3195, 3196, 3197, 3197,
+ 3147, 3147, 3147, 3147, 3198, 3199, 3199, 3199,
+ 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683,
+ 1683, 1683, 1683, 3184, 3184, 3147, 3147, 3147,
+ 1683, 1683, 1683, 1683, 3191, 3191, 3191, 3182,
+ 3182, 3200, 3196, 3197, 3197, 3147, 3147, 3147,
+
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3201, 3201, 3201, 3201,
+ 3201, 3201, 3201, 3201, 3202, 3202, 3202, 3147,
+ 3147, 3147, 3147, 3202, 3202, 3202, 3202, 3202,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 3203, 3203, 3203,
+ 3203, 3202, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3196, 3196, 3196, 3196, 3196, 3196, 3196, 3196,
+ 3196, 3196, 3196, 3196, 3147, 3147, 3147, 3147,
+ 3199, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 3147, 3147, 3147, 3147,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 3147, 3147, 3147, 3147, 3147, 3147,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613,
+ 1613, 1613, 1613, 1613, 1613, 1613, 3147, 3147,
+ 3159, 3159, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+
+ 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616,
+ 1616, 1616, 1616, 1616, 3204, 3196, 3196, 3205,
+ 3183, 3183, 3183, 3183, 3183, 3183, 3183, 3183,
+ 3206, 3189, 3189, 3189, 3189, 3189, 3189, 3207,
+ 3191, 3191, 3191, 3191, 3191, 3191, 3189, 3191,
+ 3182, 3182, 3182, 3182, 3182, 3182, 3182, 3182,
+ 3189, 3207, 3207, 3189, 3189, 3189, 3189, 3189,
+ 3189, 3189, 3191, 3208, 3189, 3189, 3189, 3196,
+ 3191, 3191, 3191, 3191, 3191, 3191, 3208, 3191,
+ 3191, 3191, 3191, 3191, 3182, 3200, 3200, 3200,
+ 3191, 3191, 3191, 3191, 3191, 3191, 3191, 3191,
+ 3191, 3191, 3191, 3191, 3191, 3191, 3191, 3182,
+ 3182, 3182, 3182, 3182, 3182, 3182, 3182, 3182,
+ 3182, 3182, 3182, 3182, 3200, 3200, 3200, 3200,
+ 3200, 3196, 3197, 3200, 3200, 3200, 3200, 3204,
+ 3197, 3199, 3200, 3196, 3200, 3200, 3200, 3200,
+ 3183, 3183, 3183, 3183, 3183, 3191, 3191, 3191,
+ 3191, 3191, 3191, 3191, 3191, 3191, 3191, 3191,
+ 3191, 3191, 3182, 3182, 3182, 3182, 3182, 3182,
+ 3200, 3200, 3200, 3200, 3200, 3200, 3200, 3200,
+ 3200, 3200, 3200, 3197, 3197, 3196, 3196, 3196,
+ 3196, 3196, 3196, 3197, 3197, 3197, 3196, 3196,
+ 3200, 3200, 3200, 3200, 3200, 3209, 3209, 3200,
+ 3209, 3209, 3196, 3205, 3196, 3196, 3196, 3196,
+ 3183, 3200, 3200, 3196, 3196, 3196, 3196, 3196,
+ 3196, 3196, 3196, 3197, 3199, 3205, 3205, 3205,
+ 3182, 3207, 3207, 3207, 3207, 3207, 3207, 3207,
+ 3207, 3207, 3207, 3207, 3207, 3207, 3182, 3182,
+ 3182, 3182, 3182, 3182, 3182, 3182, 3182, 3200,
+ 3200, 3200, 3200, 3200, 3200, 3200, 3200, 3200,
+ 3200, 3200, 3200, 3200, 3200, 3200, 3200, 3200,
+ 3200, 3200, 3200, 3200, 3200, 3200, 3200, 3200,
+
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3210, 3210, 3210, 3210,
+ 3210, 3210, 3210, 3210, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3203, 3203, 3203, 3203, 3203, 3203, 3203, 3203,
+ 3203, 3203, 3203, 3203, 3203, 3203, 3147, 3147,
+ 3196, 3196, 3196, 3196, 3197, 3198, 3198, 3198,
+ 3196, 3196, 3196, 3199, 3199, 3147, 3147, 3147,
+ 3196, 3196, 3196, 3197, 3197, 3197, 3197, 3198,
+ 3198, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3196, 3196, 3196, 3196, 3196, 3196, 3197, 3197,
+ 3197, 3197, 3197, 3197, 3197, 3197, 3197, 3197,
+ 3197, 3197, 3197, 3197, 3197, 3197, 3197, 3197,
+ 3197, 3199, 3199, 3199, 3199, 3198, 3198, 3198,
+ 3197, 3197, 3197, 3197, 3197, 3197, 3197, 3199,
+ 3199, 3199, 3199, 3198, 3198, 3198, 3147, 3198,
+ 3197, 3197, 3197, 3211, 3211, 3211, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3198, 3198,
+ 3197, 3197, 3197, 3197, 3197, 3197, 3197, 3199,
+ 3199, 3199, 3198, 3198, 3147, 3147, 3147, 3147,
+ 3199, 3199, 3199, 3199, 3199, 3199, 3199, 3199,
+ 3198, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3211, 3211, 3211, 3211, 3211, 3211, 3211, 3212,
+ 3212, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 221, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751,
+ 1751, 1751, 1751, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220,
+ 3221, 3222, 221, 221, 221, 221, 221, 221,
+
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3147, 3147,
+ 3147, 3147, 3147, 3147, 3147, 3147, 3223, 3223,
+
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 3224,
+ 3224, 3224, 3224, 3224, 3224, 3224, 3224, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1911, 1911,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906,
+ 1906, 1906, 1906, 1906, 1906, 1911, 1911, 1911,
+ 1911, 3225, 2223, 2223, 2223, 2223, 2223, 2223,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 3226, 3226,
+ 3226, 3226, 3226, 3226, 3226, 3226, 2223, 2223,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908,
+ 1908, 1908, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909,
+ 1909, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227,
+ 3227, 3227, 3227, 3227, 3227, 3227, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3229, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3229, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3229,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3229,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3229,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228,
+ 3228, 3228, 3228, 3228, 3228, 3228, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 3223, 3223,
+
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902,
+ 1902, 1902, 1902, 2223, 2223, 2223, 2223, 2223,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+ 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223,
+
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 3223, 3223,
+
+ 1468, 3039, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 3230, 3230, 3230, 3230, 3230, 3230, 3230, 3230,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 3231, 3231, 3231, 3231, 3231, 3231, 3231, 3231,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+ 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468,
+
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3232, 3232,
+ 3232, 3232, 3232, 3232, 3232, 3232, 3223, 3223
};
-#define GET_PROP_INDEX(ucs4) \
- (ucs4 < 0x11000 \
- ? (uc_property_trie[uc_property_trie[ucs4>>5] + (ucs4 & 0x1f)]) \
- : (uc_property_trie[uc_property_trie[((ucs4 - 0x11000)>>8) + 0x880] + (ucs4 & 0xff)]))
-
-#define GET_PROP_INDEX_UCS2(ucs2) \
- (uc_property_trie[uc_property_trie[ucs2>>5] + (ucs2 & 0x1f)])
-
-static const Properties uc_properties[] = {
- { 9, 18, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 21, 0, 2 },
- { 9, 8, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 17, 5, 2 },
- { 9, 7, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 2, 2, 37, 2, 2 },
- { 9, 8, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 38, 5, 2 },
- { 9, 9, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 38, 5, 2 },
- { 9, 7, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 1, 1, 36, 1, 2 },
- { 9, 7, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 21, 0, 2 },
- { 9, 8, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 21, 0, 2 },
- { 6, 9, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 22, 35, 5, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 12, 3, 13, 2 },
- { 25, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 25, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 11, 3, 13, 2 },
- { 21, 10, 0, 0, -1, 1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 2, 13, 2 },
- { 26, 3, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 11, 2 },
- { 20, 3, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 11, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 10, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 2 },
- { 3, 2, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 0, 2 },
- { 26, 10, 0, 0, -1, 2, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 3 },
- { 21, 10, 0, 0, -1, 2, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 22, 10, 0, 0, -1, -2, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 2, 13, 2 },
- { 28, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 19, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 12, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 26, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 22, 10, 0, 0, -1, -2, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 9, 7, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 38, 3, 2 },
- { 6, 6, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 4, 5, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 28, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 23, 10, 0, 0, -1, 16, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 10, 18, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 17, 4, 2 },
- { 29, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 26, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 5, 2, 0, 0, 2, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 3, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 28, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 743}, {0, 743}, {0, 775} }, 0, 10, 12, 6, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 12, 0, 2 },
- { 5, 2, 0, 0, 1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 24, 10, 0, 0, -1, -16, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 5, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 418}, {1, 415}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 121}, {0, 121}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {1, 421}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -232}, {0, -232}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 80, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 500}, {1, 500}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -121}, {0, 0}, {0, 0}, {0, -121} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -300}, {0, -300}, {0, -268} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 195}, {0, 195}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 210}, {0, 0}, {0, 0}, {0, 210} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 206}, {0, 0}, {0, 0}, {0, 206} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 205}, {0, 0}, {0, 0}, {0, 205} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 79}, {0, 0}, {0, 0}, {0, 79} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 202}, {0, 0}, {0, 0}, {0, 202} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 203}, {0, 0}, {0, 0}, {0, 203} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 207}, {0, 0}, {0, 0}, {0, 207} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 97}, {0, 97}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 211}, {0, 0}, {0, 0}, {0, 211} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 209}, {0, 0}, {0, 0}, {0, 209} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 163}, {0, 163}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 213}, {0, 0}, {0, 0}, {0, 213} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 130}, {0, 130}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 214}, {0, 0}, {0, 0}, {0, 214} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 218}, {0, 0}, {0, 0}, {0, 218} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 217}, {0, 0}, {0, 0}, {0, 217} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 219}, {0, 0}, {0, 0}, {0, 219} }, 0, 10, 12, 7, 3 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 56}, {0, 56}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 80, { {0, 2}, {0, 0}, {0, 1}, {0, 2} }, 0, 10, 12, 7, 3 },
- { 16, 0, 0, 0, -1, 0, 1, 80, { {0, 1}, {0, -1}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -2}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -79}, {0, -79}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 511}, {1, 511}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {0, -97}, {0, 0}, {0, 0}, {0, -97} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {0, -56}, {0, 0}, {0, 0}, {0, -56} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 4, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 4, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 6, 0, { {0, -130}, {0, 0}, {0, 0}, {0, -130} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {1, 1}, {0, 0}, {0, 0}, {1, 1} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {0, -163}, {0, 0}, {0, 0}, {0, -163} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {1, 3}, {0, 0}, {0, 0}, {1, 3} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {1, 5}, {1, 5}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {1, 7}, {1, 7}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {0, -195}, {0, 0}, {0, 0}, {0, -195} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {0, 69}, {0, 0}, {0, 0}, {0, 69} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {0, 71}, {0, 0}, {0, 0}, {0, 71} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 9}, {1, 9}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 11}, {1, 11}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 13}, {1, 13}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -210}, {0, -210}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -206}, {0, -206}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -205}, {0, -205}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -202}, {0, -202}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -203}, {0, -203}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 15}, {1, 15}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 17}, {1, 17}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -207}, {0, -207}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 19}, {1, 19}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 21}, {1, 21}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -209}, {0, -209}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -211}, {0, -211}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 23}, {1, 23}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 25}, {1, 25}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 27}, {1, 27}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 29}, {1, 29}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -213}, {0, -213}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -214}, {0, -214}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 31}, {1, 31}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -218}, {0, -218}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 33}, {1, 33}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 35}, {1, 35}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -69}, {0, -69}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -217}, {0, -217}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -71}, {0, -71}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -219}, {0, -219}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 37}, {1, 37}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {1, 39}, {1, 39}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 28, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 17, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 18, 8, 2 },
- { 28, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 18, 0, 2 },
- { 28, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 36 },
- { 17, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 28, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 28, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 0, 17, 230, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 232, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 216, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 202, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 202, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 1, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 1, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 240, 5, -1, 0, 1, 204, { {0, 0}, {0, 84}, {0, 84}, {0, 116} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 232, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 233, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 1 },
- { 0, 17, 234, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 1 },
- { 0, 17, 233, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 1 },
- { 0, 17, 234, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 1 },
- { 0, 17, 233, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 17, 10, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 28, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 13, 0, 0, 0, -1, 0, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 17, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 130}, {0, 130}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 25, 10, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {0, 116}, {0, 0}, {0, 0}, {0, 116} }, 0, 10, 12, 7, 4 },
- { 28, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 28, 10, 0, 0, -1, 0, 1, 81, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 38}, {0, 0}, {0, 0}, {0, 38} }, 0, 10, 12, 7, 4 },
- { 25, 10, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 37}, {0, 0}, {0, 0}, {0, 37} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 64}, {0, 0}, {0, 0}, {0, 64} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 63}, {0, 0}, {0, 0}, {0, 63} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 503}, {1, 503}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -38}, {0, -38}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -37}, {0, -37}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 507}, {1, 507}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -31}, {0, -31}, {0, 1} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -64}, {0, -64}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -63}, {0, -63}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {0, 8}, {0, 0}, {0, 0}, {0, 8} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -62}, {0, -62}, {0, -30} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -57}, {0, -57}, {0, -25} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 81, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -47}, {0, -47}, {0, -15} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -54}, {0, -54}, {0, -22} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, -8}, {0, -8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 6, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 46 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 46 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -86}, {0, -86}, {0, -54} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -80}, {0, -80}, {0, -48} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 7}, {0, 7}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -116}, {0, -116}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 5, 80, { {0, -60}, {0, 0}, {0, 0}, {0, -60} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 5, 80, { {0, 0}, {0, -96}, {0, -96}, {0, -64} }, 0, 10, 12, 6, 4 },
- { 26, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 14, 0, 0, 0, -1, 0, 7, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 7, 80, { {0, -7}, {0, 0}, {0, 0}, {0, -7} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {0, -130}, {0, 0}, {0, 0}, {0, -130} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 4, 17, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 12, 7, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 12, 7, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 12, 7, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 4, 17, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 29, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 5 },
- { 0, 17, 230, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 5 },
- { 0, 17, 230, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 5 },
- { 2, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 5 },
- { 14, 0, 0, 0, -1, 0, 6, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 15}, {0, 0}, {0, 0}, {0, 15} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, -15}, {0, -15}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 4, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 4, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 11, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 12, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 5 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 48}, {0, 0}, {0, 0}, {0, 48} }, 0, 10, 12, 7, 6 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 6 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 6 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 11, 6 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 12, 0, 6 },
- { 15, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, -48}, {0, -48}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 467}, {1, 464}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 12, 6 },
- { 20, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 17, 0, 6 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 6 },
- { 27, 4, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 6 },
- { 13, 1, 0, 0, -1, 0, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 0, 17, 220, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 230, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 222, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 220, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 228, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 10, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 11, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 12, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 13, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 14, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 15, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 16, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 17, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 18, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 19, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 19, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 20, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 21, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 22, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 20, 1, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 7 },
- { 0, 17, 23, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 25, 1, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 7 },
- { 0, 17, 24, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 0, 17, 25, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 25, 1, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 7 },
- { 0, 17, 18, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 18, 1, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 13, 8, 7 },
- { 18, 1, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 13, 8, 7 },
- { 25, 1, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 7 },
- { 25, 1, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 12, 0, 7 },
- { 10, 5, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 8 },
- { 10, 5, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 8 },
- { 10, 5, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 2 },
- { 26, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 26, 13, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 25, 4, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 8 },
- { 27, 13, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 8 },
- { 25, 13, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 11, 8 },
- { 29, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 0, 17, 230, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 230, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 30, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 31, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 32, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 25, 13, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 2 },
- { 10, 13, 0, 5, -1, 0, 15, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 8 },
- { 13, 13, 0, 0, -1, 0, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 25, 13, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 8 },
- { 25, 13, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 2 },
- { 18, 13, 0, 2, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 17, 13, 0, 1, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 0, 17, 27, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 28, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 29, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 30, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 31, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 32, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 33, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 34, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 4, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 4, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 230, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 220, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 220, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 3, 5, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 5, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 25, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 8 },
- { 25, 5, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 25, 5, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 11, 9, 8 },
- { 25, 13, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 18, 13, 0, 2, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 0, 17, 35, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 18, 13, 0, 3, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 25, 13, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 8 },
- { 0, 17, 230, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 10, 5, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 0, 17, 220, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 17, 13, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 3, 2, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 3, 2, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 8 },
- { 29, 13, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 18, 13, 0, 2, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 25, 13, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 9 },
- { 25, 13, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 9 },
- { 10, 13, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 9 },
- { 18, 13, 0, 3, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 0, 17, 36, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 9 },
- { 18, 13, 0, 2, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 18, 13, 0, 2, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 18, 13, 0, 3, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 0, 17, 230, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 9 },
- { 0, 17, 220, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 9 },
- { 18, 13, 0, 2, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 10 },
- { 0, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 10 },
- { 18, 13, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 10 },
- { 3, 1, 0, 0, 0, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 2, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 3, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 4, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 5, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 6, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 7, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 8, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 3, 1, 0, 0, 9, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 66 },
- { 18, 1, 0, 2, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 66 },
- { 0, 17, 230, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 66 },
- { 0, 17, 220, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 66 },
- { 17, 1, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 66 },
- { 29, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 66 },
- { 25, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 66 },
- { 25, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 11, 66 },
- { 25, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 66 },
- { 17, 1, 0, 1, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 66 },
- { 0, 17, 220, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 66 },
- { 27, 1, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 66 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 82 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 82 },
- { 17, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 82 },
- { 25, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 82 },
- { 25, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 82 },
- { 18, 1, 0, 3, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 95 },
- { 18, 1, 0, 2, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 95 },
- { 0, 17, 220, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 95 },
- { 25, 1, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 95 },
- { 18, 13, 0, 2, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 18, 13, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 18, 13, 0, 3, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 9 },
- { 18, 13, 0, 2, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 3, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 18, 13, 0, 2, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 0, 17, 220, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 230, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 10, 5, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 2 },
- { 0, 17, 220, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 230, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 220, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 27, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 28, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 29, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 230, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 8 },
- { 0, 17, 0, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 11 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 0, 17, 0, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 1, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 11 },
- { 0, 17, 7, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 11 },
- { 18, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 2 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 11 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 11 },
- { 17, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 12 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 12 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 12 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 12 },
- { 0, 17, 7, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 12 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 12 },
- { 1, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 12 },
- { 1, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 12 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 12 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 12 },
- { 18, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 12 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 12 },
- { 27, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 12 },
- { 5, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 12 },
- { 5, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 12 },
- { 29, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 12 },
- { 27, 4, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 12 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 12 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 12 },
- { 0, 17, 230, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 12 },
- { 0, 17, 0, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 13 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 13 },
- { 1, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 13 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 13 },
- { 18, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 13 },
- { 0, 17, 7, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 13 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 13 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 13 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 13 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 13 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 13 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 14 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 14 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 14 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 14 },
- { 0, 17, 7, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 14 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 14 },
- { 0, 17, 0, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 14 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 14 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 14 },
- { 27, 4, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 14 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 14 },
- { 0, 17, 0, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 14 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 15 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 15 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 15 },
- { 0, 17, 7, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 1, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 1, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 15 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 0, 17, 0, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 0, 17, 0, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 15 },
- { 18, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 15 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 15 },
- { 29, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 15 },
- { 5, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 15 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 16 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 16 },
- { 18, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 16 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 16 },
- { 1, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 16 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 16 },
- { 1, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 16 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 16 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 16 },
- { 3, 0, 0, 0, 0, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 16 },
- { 5, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 16 },
- { 29, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 16 },
- { 27, 4, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 16 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 17 },
- { 0, 17, 0, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 17 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 17 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 17 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 0, 17, 0, 5, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 0, 17, 84, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 0, 17, 91, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 17 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 17 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 17 },
- { 25, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 17 },
- { 5, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 17 },
- { 29, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 17 },
- { 18, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 18 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 18 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 18 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 18 },
- { 0, 17, 7, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 18 },
- { 0, 0, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 1, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 18 },
- { 1, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 0, 17, 0, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 18 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 18 },
- { 18, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 18 },
- { 0, 17, 0, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 1, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 19 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 19 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 19 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 19 },
- { 0, 17, 9, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 19 },
- { 1, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 1, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 19 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 19 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 19 },
- { 29, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 19 },
- { 18, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 19 },
- { 5, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 19 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 19 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 19 },
- { 5, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 19 },
- { 29, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 19 },
- { 0, 17, 0, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 20 },
- { 1, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 20 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 20 },
- { 0, 17, 9, 5, -1, 0, 4, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 20 },
- { 1, 0, 0, 0, -1, 0, 4, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 20 },
- { 0, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 20 },
- { 1, 0, 0, 0, -1, 0, 4, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 20 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 20 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 20 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 21 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 21 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 0, 33, 8, 21 },
- { 0, 17, 103, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 21 },
- { 0, 17, 9, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 21 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 21 },
- { 0, 17, 107, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 21 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 21 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 21 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 21 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 22 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 22 },
- { 0, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 22 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 0, 33, 8, 22 },
- { 0, 17, 118, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 22 },
- { 0, 17, 9, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 22 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 22 },
- { 0, 17, 122, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 22 },
- { 3, 0, 0, 0, 0, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 3, 0, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 22 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 22 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 22 },
- { 18, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 23 },
- { 29, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 4, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 4, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 23 },
- { 29, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 23 },
- { 0, 17, 220, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 3, 0, 0, 0, 0, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 2, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 3, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 4, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 5, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 6, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 7, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 8, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 3, 0, 0, 0, 9, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 23 },
- { 5, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 23 },
- { 29, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 23 },
- { 0, 17, 216, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 21, 10, 0, 0, -1, 1, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 23 },
- { 22, 10, 0, 0, -1, -1, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 23 },
- { 1, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 23 },
- { 18, 0, 0, 0, -1, 0, 2, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 23 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 23 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 23 },
- { 0, 17, 129, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 130, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 0, 5, -1, 0, 2, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 132, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 0, 5, -1, 0, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 0, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 1, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 17, 4, 23 },
- { 0, 17, 230, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 9, 5, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 23 },
- { 0, 17, 0, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 0, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 29, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 23 },
- { 29, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 23 },
- { 0, 17, 220, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 23 },
- { 29, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 23 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 23 },
- { 29, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 4, 0, 23 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 18, 0, 0, 0, -1, 0, 4, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 33, 4, 24 },
- { 1, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 33, 4, 24 },
- { 0, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 0, 17, 0, 5, -1, 0, 4, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 1, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 33, 4, 24 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 0, 17, 7, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 0, 17, 9, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 0, 17, 9, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 33, 4, 24 },
- { 3, 0, 0, 0, 0, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 2, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 3, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 4, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 5, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 6, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 7, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 8, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 9, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 24 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 24 },
- { 0, 17, 220, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 33, 4, 24 },
- { 0, 17, 0, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 29, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 24 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 7264}, {0, 0}, {0, 0}, {0, 7264} }, 0, 10, 12, 7, 25 },
- { 14, 0, 0, 0, -1, 0, 13, 0, { {0, 7264}, {0, 0}, {0, 0}, {0, 7264} }, 0, 10, 12, 7, 25 },
- { 15, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 25 },
- { 15, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 25 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 25 },
- { 25, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 25 },
- { 15, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 25 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 9, 10, 25, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 9, 10, 25, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 26, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 26, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 26, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 11, 10, 27, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 11, 10, 27, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 11, 10, 27, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 27 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 27 },
- { 0, 17, 230, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 27 },
- { 0, 17, 230, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 27 },
- { 25, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 27 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 27 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 2, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 3, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 4, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 5, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 6, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 7, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 8, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, 9, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 5, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 27 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 41}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 43}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 45}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 47}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 49}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 51}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 53}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 55}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 57}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 59}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 61}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 63}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 65}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 67}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 69}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 71}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 73}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 75}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 77}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 79}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 81}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 83}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 85}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 87}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 89}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 91}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 93}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 95}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 97}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 99}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 101}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 103}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 105}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 107}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 109}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 111}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 113}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 115}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 117}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 119}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 121}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 123}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 125}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 127}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 129}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 131}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 133}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 135}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 137}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 139}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 141}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 143}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 145}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 147}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 149}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 151}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 153}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 155}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 157}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 159}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 161}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 163}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 165}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 167}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 169}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 171}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 173}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 175}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 177}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 179}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 181}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 183}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 185}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 187}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 189}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 191}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 193}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 195}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 197}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {1, 199}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 4, 0, { {0, 8}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 14, 0, 0, 0, -1, 0, 17, 0, { {0, 8}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, -8}, {0, -8}, {0, -8} }, 0, 10, 12, 6, 28 },
- { 20, 10, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 29 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 29 },
- { 29, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 29 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 29 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 29 },
- { 6, 9, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 22, 17, 5, 30 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 30 },
- { 21, 10, 0, 0, -1, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 30 },
- { 22, 10, 0, 0, -1, -1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 30 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 31 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 4, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 31 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 31 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 42 },
- { 0, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 42 },
- { 0, 17, 9, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 42 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 43 },
- { 0, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 43 },
- { 0, 17, 9, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 43 },
- { 25, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 2 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 44 },
- { 0, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 44 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 45 },
- { 0, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 45 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 32 },
- { 0, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 32 },
- { 1, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 33, 4, 32 },
- { 0, 17, 9, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 32 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 32 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 0, 32 },
- { 17, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 32 },
- { 25, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 32 },
- { 27, 4, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 32 },
- { 0, 17, 230, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 32 },
- { 3, 0, 0, 0, 0, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 2, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 3, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 4, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 5, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 6, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 7, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 8, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 3, 0, 0, 0, 9, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 32 },
- { 5, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 32 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 33 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 33 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 33 },
- { 25, 10, 0, 2, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 33 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 11, 33 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 33 },
- { 25, 10, 0, 1, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 33 },
- { 0, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 33 },
- { 10, 18, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 4, 4, 33 },
- { 3, 0, 0, 0, 0, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 2, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 3, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 4, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 5, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 6, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 7, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 8, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 3, 0, 0, 0, 9, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 33 },
- { 18, 0, 0, 2, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 33 },
- { 17, 0, 0, 2, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 33 },
- { 18, 0, 0, 2, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 33 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 33 },
- { 0, 17, 228, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 33 },
- { 18, 0, 0, 2, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 33 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 47 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 47 },
- { 0, 17, 0, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 47 },
- { 1, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 47 },
- { 0, 17, 222, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 47 },
- { 0, 17, 230, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 47 },
- { 0, 17, 220, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 47 },
- { 29, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 47 },
- { 25, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 47 },
- { 3, 0, 0, 0, 0, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 2, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 3, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 4, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 5, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 6, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 7, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 8, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 3, 0, 0, 0, 9, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 47 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 48 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 56 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 56 },
- { 3, 0, 0, 0, 0, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 2, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 3, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 4, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 5, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 6, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 7, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 8, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 3, 0, 0, 0, 9, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 56 },
- { 5, 0, 0, 0, 1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 56 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 56 },
- { 29, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 32 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 55 },
- { 0, 17, 230, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 55 },
- { 0, 17, 220, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 55 },
- { 1, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 55 },
- { 0, 17, 0, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 55 },
- { 25, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 55 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 78 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 33, 4, 78 },
- { 0, 17, 0, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 78 },
- { 0, 17, 9, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 78 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 33, 4, 78 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 78 },
- { 0, 17, 220, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 78 },
- { 3, 0, 0, 0, 0, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 2, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 3, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 4, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 5, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 6, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 7, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 8, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 3, 0, 0, 0, 9, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 78 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 78 },
- { 17, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 78 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 12, 78 },
- { 0, 17, 230, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 2, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 0, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 62 },
- { 1, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 62 },
- { 18, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 62 },
- { 18, 0, 0, 0, -1, 0, 9, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 62 },
- { 0, 17, 7, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 62 },
- { 1, 0, 0, 0, -1, 0, 9, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 62 },
- { 1, 0, 0, 0, -1, 0, 9, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 62 },
- { 1, 0, 9, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 62 },
- { 3, 0, 0, 0, 0, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 2, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 3, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 4, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 5, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 6, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 7, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 8, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 3, 0, 0, 0, 9, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 62 },
- { 25, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 62 },
- { 25, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 62 },
- { 25, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 62 },
- { 29, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 62 },
- { 0, 17, 230, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 62 },
- { 0, 17, 220, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 62 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 67 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 67 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 67 },
- { 1, 0, 9, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 67 },
- { 0, 17, 9, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 67 },
- { 0, 17, 0, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 67 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 67 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 67 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 93 },
- { 0, 17, 7, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 93 },
- { 1, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 93 },
- { 0, 17, 0, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 93 },
- { 1, 0, 9, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 93 },
- { 25, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 93 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 68 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 68 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 68 },
- { 0, 17, 7, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 68 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 68 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 68 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 68 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 69 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 69 },
- { 17, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 69 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 69 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6254}, {0, -6254}, {0, -6222} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6253}, {0, -6253}, {0, -6221} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6244}, {0, -6244}, {0, -6212} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6242}, {0, -6242}, {0, -6210} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6243}, {0, -6243}, {0, -6211} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6236}, {0, -6236}, {0, -6204} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -6181}, {0, -6181}, {0, -6180} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {1, 201}, {1, 201}, {1, 719} }, 0, 10, 12, 6, 5 },
- { 14, 0, 0, 0, -1, 0, 20, 0, { {0, -3008}, {0, 0}, {0, 0}, {0, -3008} }, 0, 10, 12, 8, 25 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 67 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 0, 17, 1, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 2 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 0, 17, 230, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 1, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 2 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 15, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 17, 0, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 17, 0, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {1, 203}, {1, 203}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 3814}, {0, 3814}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {1, 205}, {1, 205}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 0, 17, 230, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 234, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 214, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 202, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 232, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 228, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 233, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 514}, {1, 514}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 517}, {1, 517}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 520}, {1, 520}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 523}, {1, 523}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 526}, {1, 526}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 2, 81, { {0, 0}, {0, -59}, {0, -59}, {0, -58} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {0, -7615}, {0, 0}, {0, 0}, {0, -7615} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 8}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {0, 0}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 529}, {1, 529}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 532}, {1, 532}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 536}, {1, 536}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 540}, {1, 540}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 74}, {0, 74}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 74}, {0, 74}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 86}, {0, 86}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 86}, {0, 86}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 100}, {0, 100}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 100}, {0, 100}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 128}, {0, 128}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 128}, {0, 128}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 112}, {0, 112}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 112}, {0, 112}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 126}, {0, 126}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 126}, {0, 126}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 578}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 581}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 584}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 587}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 590}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 593}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 596}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 599}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 578}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 581}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 584}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 587}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 590}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 593}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 596}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 599}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 602}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 605}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 608}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 611}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 614}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 617}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 620}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 623}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 602}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 605}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 608}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 611}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 614}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 617}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 620}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 623}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 626}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 629}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 632}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 635}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 638}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 641}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 644}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 647}, {0, 8}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 626}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 629}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 632}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 635}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 638}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 641}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 644}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -8}, {1, 647}, {0, 0}, {0, -8} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 662}, {1, 659}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 650}, {0, 9}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 668}, {1, 665}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 544}, {1, 544}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 699}, {1, 695}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -74}, {0, 0}, {0, 0}, {0, -74} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -74}, {0, 0}, {0, 0}, {0, -74} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -9}, {1, 650}, {0, 0}, {0, -9} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, -7205}, {0, -7205}, {0, -7173} }, 0, 10, 12, 6, 4 },
- { 28, 10, 0, 0, -1, 0, 1, 81, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 674}, {1, 671}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 653}, {0, 9}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 680}, {1, 677}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 547}, {1, 547}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 707}, {1, 703}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -86}, {0, 0}, {0, 0}, {0, -86} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -86}, {0, 0}, {0, 0}, {0, -86} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -9}, {1, 653}, {0, 0}, {0, -9} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 550}, {1, 550}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {1, 503}, {1, 503}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 554}, {1, 554}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 557}, {1, 557}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -100}, {0, 0}, {0, 0}, {0, -100} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -100}, {0, 0}, {0, 0}, {0, -100} }, 0, 10, 12, 7, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 561}, {1, 561}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {1, 507}, {1, 507}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 565}, {1, 565}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 7}, {0, 7}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 568}, {1, 568}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 571}, {1, 571}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -112}, {0, 0}, {0, 0}, {0, -112} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -112}, {0, 0}, {0, 0}, {0, -112} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -7}, {0, 0}, {0, 0}, {0, -7} }, 0, 10, 12, 7, 4 },
- { 28, 10, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 686}, {1, 683}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 656}, {0, 9}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 692}, {1, 689}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 575}, {1, 575}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {1, 715}, {1, 711}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -128}, {0, 0}, {0, 0}, {0, -128} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -128}, {0, 0}, {0, 0}, {0, -128} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 17, { {0, -126}, {0, 0}, {0, 0}, {0, -126} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -126}, {0, 0}, {0, 0}, {0, -126} }, 0, 10, 12, 7, 4 },
- { 16, 0, 0, 0, -1, 0, 1, 17, { {0, -9}, {1, 656}, {0, 0}, {0, -9} }, 0, 10, 12, 7, 4 },
- { 28, 10, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 4 },
- { 6, 9, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 22, 17, 5, 2 },
- { 6, 9, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 22, 17, 5, 2 },
- { 6, 9, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 4, 5, 2 },
- { 10, 18, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 20, 4, 2 },
- { 10, 18, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 10, 18, 0, 1, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 5, 5, 32, 4, 1 },
- { 10, 0, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 1, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 20, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 4, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 11, 2 },
- { 20, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 11, 2 },
- { 20, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 23, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 3, 13, 2 },
- { 24, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 3, 13, 2 },
- { 21, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 23, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 24, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 15, 10, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 15, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 17, 0, 2 },
- { 7, 9, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 38, 3, 2 },
- { 8, 7, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 38, 3, 2 },
- { 10, 11, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 14, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 16, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 12, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 15, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 6, 6, 0, 0, -1, 0, 4, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 4, 5, 2 },
- { 25, 4, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 23, 10, 0, 0, -1, 1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 24, 10, 0, 0, -1, -1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 12, 2 },
- { 26, 6, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 0, 2 },
- { 22, 10, 0, 0, -1, -1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 4, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 19, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 6, 9, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 22, 17, 5, 2 },
- { 10, 18, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 22, 4, 2 },
- { 10, 18, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 12, 4, 2 },
- { 10, 18, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 12, 4, 2 },
- { 13, 18, 0, 0, -1, 0, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 12, 0, 0 },
- { 10, 19, 0, 0, -1, 0, 15, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 20, 0, 0, -1, 0, 15, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 21, 0, 0, -1, 0, 15, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 22, 0, 0, -1, 0, 15, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 10, 18, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 5, 2, 0, 0, 0, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 5, 2, 0, 0, 4, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 5, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 6, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 7, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 8, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 9, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 3, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 21, 10, 0, 0, -1, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 17, 0, 0, 0, -1, 0, 12, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 27, 4, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 14, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 27, 4, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 13, 4, 0, 0, -1, 0, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 0 },
- { 2, 17, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 2, 17, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 2, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 1, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 220, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 1, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 29, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {0, -7517}, {0, 0}, {0, 0}, {0, -7517} }, 0, 10, 12, 7, 4 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {1, 207}, {0, 0}, {0, 0}, {1, 207} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 1, 85, { {1, 209}, {0, 0}, {0, 0}, {1, 209} }, 0, 10, 12, 7, 3 },
- { 29, 4, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 0, { {0, 28}, {0, 0}, {0, 0}, {0, 28} }, 0, 10, 12, 7, 3 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 15, 0, 0, 0, -1, 0, 4, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 29, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 15, 0, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 14, 0, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 26, 10, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, -28}, {0, -28}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 29, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, -1, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 4, 0, 0, 0, -1, 0, 1, 80, { {0, 16}, {0, 0}, {0, 0}, {0, 16} }, 0, 10, 12, 7, 3 },
- { 4, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -16}, {0, -16}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 4, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 4, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 29, 10, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 3, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 3, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -3, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -3, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2016, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2527, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1923, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1914, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1918, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2250, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 138, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 7, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -7, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1824, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2104, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2108, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2106, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1316, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -138, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 15, 0, 2 },
- { 26, 10, 0, 0, -1, 8, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 7, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -8, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -7, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 21, 10, 0, 0, -1, 1, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 29, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 2, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 3, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 4, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 5, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 6, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 7, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 8, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 9, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 1, 80, { {0, 26}, {0, 0}, {0, 0}, {0, 26} }, 0, 10, 12, 7, 2 },
- { 29, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -26}, {0, -26}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 5, 10, 0, 0, 0, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 2, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 3, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 4, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 5, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 6, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 7, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 8, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 9, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 0, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 29, 10, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 2 },
- { 21, 10, 0, 0, -1, 1, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 5, 10, 0, 0, 1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 2, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 3, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 4, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 5, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 6, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 7, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 8, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, 9, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 21, 10, 0, 0, -1, 1, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 26, 10, 0, 0, -1, 1, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 2, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 1, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1316, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 21, 10, 0, 0, -1, 1, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 29, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 54 },
- { 21, 10, 0, 0, -1, 3, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, 1, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 21, 10, 0, 0, -1, -1, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -3, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 26, 10, 0, 0, -1, -1914, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1918, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1923, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -1824, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2016, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 6, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2104, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2106, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2108, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, -2250, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, -2527, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {0, 48}, {0, 0}, {0, 0}, {0, 48} }, 0, 10, 12, 7, 57 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, -48}, {0, -48}, {0, 0} }, 0, 10, 12, 6, 57 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {1, 211}, {0, 0}, {0, 0}, {1, 211} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {0, -3814}, {0, 0}, {0, 0}, {0, -3814} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 9, 0, { {1, 213}, {0, 0}, {0, 0}, {1, 213} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {1, 215}, {1, 215}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {1, 217}, {1, 217}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {1, 219}, {0, 0}, {0, 0}, {1, 219} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {1, 221}, {0, 0}, {0, 0}, {1, 221} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {1, 223}, {0, 0}, {0, 0}, {1, 223} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 11, 0, { {1, 225}, {0, 0}, {0, 0}, {1, 225} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 10, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 11, 0, { {1, 227}, {0, 0}, {0, 0}, {1, 227} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 11, 0, { {1, 229}, {0, 0}, {0, 0}, {1, 229} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 8, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 46 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 46 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 46 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 46 },
- { 14, 0, 0, 0, -1, 0, 11, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 46 },
- { 15, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 46 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 46 },
- { 14, 0, 0, 0, -1, 0, 13, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 46 },
- { 15, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 46 },
- { 25, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 46 },
- { 25, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 46 },
- { 5, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 46 },
- { 15, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, -7264}, {0, -7264}, {0, 0} }, 0, 10, 12, 6, 25 },
- { 15, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, -7264}, {0, -7264}, {0, 0} }, 0, 10, 12, 6, 25 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 58 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 58 },
- { 17, 0, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 58 },
- { 25, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 58 },
- { 0, 17, 9, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 58 },
- { 25, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 23, 10, 0, 0, -1, 1, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 24, 10, 0, 0, -1, -1, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 20, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 23, 10, 0, 0, -1, 1, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 24, 10, 0, 0, -1, -1, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 2 },
- { 17, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 25, 10, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 21, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 37 },
- { 29, 10, 0, 0, -1, 0, 4, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 37 },
- { 29, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 2 },
- { 4, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 20, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 0, 2 },
- { 22, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 0, 17, 218, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 228, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 222, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 1, 0, 224, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 26 },
- { 20, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 21, 8, 2 },
- { 29, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 4, 0, 0, 0, -1, 0, 4, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 17, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 2 },
- { 25, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 8, 34 },
- { 0, 17, 8, 5, -1, 0, 1, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 28, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 8, 34 },
- { 17, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 34 },
- { 20, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 35 },
- { 25, 10, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 35 },
- { 17, 0, 0, 0, -1, 0, 1, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 26 },
- { 29, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 5, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 36 },
- { 18, 0, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 35 },
- { 29, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 26 },
- { 29, 10, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 26 },
- { 29, 0, 0, 0, -1, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 5, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 5, 10, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 26 },
- { 29, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 0, 35 },
- { 29, 0, 0, 0, -1, 0, 22, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 13, 0, 0, 0, -1, 0, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0 },
- { 18, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 38 },
- { 17, 0, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 38 },
- { 29, 10, 0, 0, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 38 },
- { 29, 10, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 38 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 83 },
- { 17, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 83 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 83 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 83 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 70 },
- { 17, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 70 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 70 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 70 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 70 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 70 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 5 },
- { 2, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 5 },
- { 25, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 5 },
- { 0, 17, 230, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 5 },
- { 17, 10, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 5 },
- { 17, 0, 0, 0, -1, 0, 16, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 5 },
- { 0, 17, 230, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 5 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 84 },
- { 4, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 84 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 84 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 84 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 84 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 84 },
- { 28, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 28, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 17, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 28, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 10, 0, { {1, 231}, {0, 0}, {0, 0}, {1, 231} }, 0, 10, 12, 7, 3 },
- { 28, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 12, 0, { {1, 233}, {0, 0}, {0, 0}, {1, 233} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 14, 0, 0, 0, -1, 0, 12, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 13, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 48}, {0, 48}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 13, 0, { {1, 235}, {0, 0}, {0, 0}, {1, 235} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {1, 237}, {0, 0}, {0, 0}, {1, 237} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {1, 239}, {0, 0}, {0, 0}, {1, 239} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {1, 241}, {0, 0}, {0, 0}, {1, 241} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 18, 0, { {1, 243}, {0, 0}, {0, 0}, {1, 243} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {1, 245}, {0, 0}, {0, 0}, {1, 245} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {1, 247}, {0, 0}, {0, 0}, {1, 247} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 17, 0, { {1, 249}, {0, 0}, {0, 0}, {1, 249} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 17, 0, { {0, 928}, {0, 0}, {0, 0}, {0, 928} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 17, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 20, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 21, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 14, 0, 0, 0, -1, 0, 21, 0, { {0, -48}, {0, 0}, {0, 0}, {0, -48} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 21, 0, { {1, 251}, {0, 0}, {0, 0}, {1, 251} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 21, 0, { {1, 253}, {0, 0}, {0, 0}, {1, 253} }, 0, 10, 12, 7, 3 },
- { 14, 0, 0, 0, -1, 0, 23, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 12, 7, 3 },
- { 15, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 17, 0, 0, 0, -1, 0, 13, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 59 },
- { 0, 17, 0, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 59 },
- { 0, 17, 9, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 59 },
- { 1, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 59 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 59 },
- { 0, 17, 9, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 59 },
- { 29, 4, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 18, 0, 0, 2, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 65 },
- { 18, 0, 0, 4, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 65 },
- { 18, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 65 },
- { 25, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 65 },
- { 25, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 65 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 71 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 71 },
- { 0, 17, 9, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 71 },
- { 0, 17, 0, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 71 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 71 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 71 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 11 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 11 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 11 },
- { 0, 17, 0, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 11 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 72 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 72 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 72 },
- { 0, 17, 220, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 72 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 72 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 73 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 73 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 73 },
- { 1, 0, 9, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 73 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 73 },
- { 0, 17, 0, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 85 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 85 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 85 },
- { 0, 17, 7, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 85 },
- { 1, 0, 9, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 85 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 85 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 85 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 85 },
- { 17, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 2 },
- { 3, 0, 0, 0, 0, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 2, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 3, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 4, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 5, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 6, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 7, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 8, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 3, 0, 0, 0, 9, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 85 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 24 },
- { 17, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 24 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 77 },
- { 0, 17, 0, 5, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 77 },
- { 1, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 77 },
- { 3, 0, 0, 0, 0, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 2, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 3, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 4, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 5, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 6, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 7, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 8, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 3, 0, 0, 0, 9, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 77 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 77 },
- { 25, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 77 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 17, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 24 },
- { 29, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 24 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 33, 4, 24 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 79 },
- { 0, 17, 230, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 79 },
- { 0, 17, 220, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 79 },
- { 17, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 79 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 79 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 86 },
- { 1, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 86 },
- { 0, 17, 0, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 86 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 86 },
- { 17, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 86 },
- { 0, 17, 9, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 86 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 27 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, -928}, {0, -928}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 28, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 16, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 4 },
- { 15, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 17, 0, 0, 0, -1, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 3 },
- { 28, 10, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 255}, {1, 255}, {1, 255} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 257}, {1, 257}, {1, 257} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 259}, {1, 259}, {1, 259} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 261}, {1, 261}, {1, 261} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 263}, {1, 263}, {1, 263} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 265}, {1, 265}, {1, 265} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 267}, {1, 267}, {1, 267} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 269}, {1, 269}, {1, 269} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 271}, {1, 271}, {1, 271} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 273}, {1, 273}, {1, 273} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 275}, {1, 275}, {1, 275} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 277}, {1, 277}, {1, 277} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 279}, {1, 279}, {1, 279} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 281}, {1, 281}, {1, 281} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 283}, {1, 283}, {1, 283} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 285}, {1, 285}, {1, 285} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 287}, {1, 287}, {1, 287} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 289}, {1, 289}, {1, 289} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 291}, {1, 291}, {1, 291} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 293}, {1, 293}, {1, 293} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 295}, {1, 295}, {1, 295} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 297}, {1, 297}, {1, 297} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 299}, {1, 299}, {1, 299} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 301}, {1, 301}, {1, 301} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 303}, {1, 303}, {1, 303} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 305}, {1, 305}, {1, 305} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 307}, {1, 307}, {1, 307} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 309}, {1, 309}, {1, 309} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 311}, {1, 311}, {1, 311} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 313}, {1, 313}, {1, 313} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 315}, {1, 315}, {1, 315} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 317}, {1, 317}, {1, 317} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 319}, {1, 319}, {1, 319} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 321}, {1, 321}, {1, 321} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 323}, {1, 323}, {1, 323} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 325}, {1, 325}, {1, 325} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 327}, {1, 327}, {1, 327} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 329}, {1, 329}, {1, 329} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 331}, {1, 331}, {1, 331} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 333}, {1, 333}, {1, 333} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 335}, {1, 335}, {1, 335} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 337}, {1, 337}, {1, 337} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 339}, {1, 339}, {1, 339} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 341}, {1, 341}, {1, 341} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 343}, {1, 343}, {1, 343} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 345}, {1, 345}, {1, 345} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 347}, {1, 347}, {1, 347} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 349}, {1, 349}, {1, 349} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 351}, {1, 351}, {1, 351} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 353}, {1, 353}, {1, 353} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 355}, {1, 355}, {1, 355} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 357}, {1, 357}, {1, 357} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 359}, {1, 359}, {1, 359} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 361}, {1, 361}, {1, 361} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 363}, {1, 363}, {1, 363} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 365}, {1, 365}, {1, 365} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 367}, {1, 367}, {1, 367} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 369}, {1, 369}, {1, 369} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 371}, {1, 371}, {1, 371} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 373}, {1, 373}, {1, 373} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 375}, {1, 375}, {1, 375} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 377}, {1, 377}, {1, 377} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 379}, {1, 379}, {1, 379} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 381}, {1, 381}, {1, 381} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 383}, {1, 383}, {1, 383} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 385}, {1, 385}, {1, 385} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 387}, {1, 387}, {1, 387} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 389}, {1, 389}, {1, 389} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 391}, {1, 391}, {1, 391} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 393}, {1, 393}, {1, 393} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 395}, {1, 395}, {1, 395} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 397}, {1, 397}, {1, 397} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 399}, {1, 399}, {1, 399} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 401}, {1, 401}, {1, 401} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 403}, {1, 403}, {1, 403} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 405}, {1, 405}, {1, 405} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 407}, {1, 407}, {1, 407} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 409}, {1, 409}, {1, 409} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 411}, {1, 411}, {1, 411} }, 0, 10, 12, 6, 28 },
- { 15, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {1, 413}, {1, 413}, {1, 413} }, 0, 10, 12, 6, 28 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 86 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 86 },
- { 0, 17, 0, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 86 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 86 },
- { 0, 17, 9, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 86 },
- { 3, 0, 0, 0, 0, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 2, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 3, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 4, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 5, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 6, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 7, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 8, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 3, 0, 0, 0, 9, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 86 },
- { 18, 0, 0, 0, -1, 0, 2, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 12, 10, 23, 8, 26 },
- { 18, 0, 0, 0, -1, 0, 2, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 13, 10, 24, 8, 26 },
- { 11, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 34, 0, 0 },
- { 12, 0, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 18, 0, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 13, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 6, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 11, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 8, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 427}, {1, 424}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 433}, {1, 430}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 439}, {1, 436}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 446}, {1, 442}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 454}, {1, 450}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 461}, {1, 458}, {0, 0} }, 0, 10, 12, 6, 3 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 473}, {1, 470}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 479}, {1, 476}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 485}, {1, 482}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 491}, {1, 488}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {1, 497}, {1, 494}, {0, 0} }, 0, 10, 12, 6, 6 },
- { 18, 1, 0, 0, -1, 0, 4, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 13, 8, 7 },
- { 0, 17, 26, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 7 },
- { 18, 1, 0, 0, -1, 0, 1, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 13, 8, 7 },
- { 18, 1, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 13, 8, 7 },
- { 26, 3, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 7 },
- { 18, 13, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 28, 13, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 13, 18, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 27, 13, 0, 0, -1, 0, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 8 },
- { 0, 17, 0, 5, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 8, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 8, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 2 },
- { 21, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 8, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 15, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 20, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 11, 2 },
- { 19, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 14, 0, 2 },
- { 21, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 21, 10, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 1, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 11, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 1, 10, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 5, 0, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 5, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 12, 2 },
- { 25, 4, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 26, 3, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 20, 3, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 11, 2 },
- { 26, 10, 0, 0, -1, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 26, 10, 0, 0, -1, -1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 18, 13, 0, 0, -1, 0, 6, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 10, 18, 0, 5, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 22, 4, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 14, 0, 2 },
- { 25, 6, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 3, 2, 0, 0, 0, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 2, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 3, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 4, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 5, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 6, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 7, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 8, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 3, 2, 0, 0, 9, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 2 },
- { 26, 10, 0, 0, -1, 2, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 26, 10, 0, 0, -1, -2, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 1, 80, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3 },
- { 21, 10, 0, 0, -1, 2, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -2, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 28, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 15, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 3 },
- { 21, 10, 0, 0, -1, 1, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 2 },
- { 22, 10, 0, 0, -1, -1, 6, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 12, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 11, 2 },
- { 25, 10, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 35 },
- { 17, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 2 },
- { 17, 0, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 5, 4, 2 },
- { 27, 4, 0, 0, -1, 0, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 10, 10, 0, 5, -1, 0, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 29, 10, 0, 0, -1, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 29, 0, 2 },
- { 13, 18, 0, 0, -1, 0, 1, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 49 },
- { 25, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 25, 10, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 2 },
- { 5, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 4, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 4 },
- { 5, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 29, 10, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 5, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 29, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 4 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 74 },
- { 18, 0, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 75 },
- { 5, 2, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 18, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 39 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 39 },
- { 5, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 39 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 39 },
- { 18, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 40 },
- { 4, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 40 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 120 },
- { 0, 17, 230, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 120 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 50 },
- { 25, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 50 },
- { 18, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 60 },
- { 25, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 60 },
- { 4, 0, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 60 },
- { 14, 0, 0, 0, -1, 0, 5, 0, { {0, 40}, {0, 0}, {0, 0}, {0, 40} }, 0, 10, 12, 7, 41 },
- { 14, 0, 0, 0, -1, 0, 7, 0, { {0, 40}, {0, 0}, {0, 0}, {0, 40} }, 0, 10, 12, 7, 41 },
- { 15, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, -40}, {0, -40}, {0, 0} }, 0, 10, 12, 6, 41 },
- { 15, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, -40}, {0, -40}, {0, 0} }, 0, 10, 12, 6, 41 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 51 },
- { 18, 0, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 52 },
- { 3, 0, 0, 0, 0, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 2, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 3, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 4, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 5, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 6, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 7, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 8, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 3, 0, 0, 0, 9, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 52 },
- { 14, 0, 0, 0, -1, 0, 18, 0, { {0, 40}, {0, 0}, {0, 0}, {0, 40} }, 0, 10, 12, 7, 136 },
- { 15, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, -40}, {0, -40}, {0, 0} }, 0, 10, 12, 6, 136 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 106 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 103 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 103 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 110 },
- { 18, 1, 0, 0, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 53 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 87 },
- { 25, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 87 },
- { 5, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 87 },
- { 18, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 118 },
- { 29, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 118 },
- { 5, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 118 },
- { 18, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 117 },
- { 5, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 117 },
- { 18, 1, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 128 },
- { 5, 1, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 128 },
- { 18, 1, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 64 },
- { 5, 1, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 64 },
- { 5, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 64 },
- { 25, 10, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 64 },
- { 18, 1, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 76 },
- { 25, 1, 0, 0, -1, 0, 10, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 76 },
- { 18, 1, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 98 },
- { 18, 1, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 97 },
- { 5, 1, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 97 },
- { 18, 1, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 61 },
- { 0, 17, 0, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 61 },
- { 0, 17, 220, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 61 },
- { 0, 17, 230, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 61 },
- { 18, 1, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 61 },
- { 0, 17, 1, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 61 },
- { 0, 17, 9, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 61 },
- { 5, 1, 0, 0, 1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 5, 1, 0, 0, 2, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 5, 1, 0, 0, 3, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 5, 1, 0, 0, 4, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 5, 1, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 5, 1, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 25, 1, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 61 },
- { 25, 1, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 61 },
- { 25, 1, 0, 0, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 61 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 88 },
- { 5, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 88 },
- { 25, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 88 },
- { 18, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 116 },
- { 5, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 116 },
- { 18, 1, 0, 2, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 112 },
- { 18, 1, 0, 3, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 112 },
- { 18, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 112 },
- { 29, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 112 },
- { 18, 1, 0, 4, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 112 },
- { 0, 17, 230, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 112 },
- { 0, 17, 220, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 112 },
- { 5, 1, 0, 2, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 112 },
- { 5, 1, 0, 3, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 112 },
- { 25, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 112 },
- { 25, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 15, 0, 112 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 80 },
- { 25, 10, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 80 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 89 },
- { 5, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 89 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 90 },
- { 5, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 90 },
- { 18, 1, 0, 2, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 121 },
- { 18, 1, 0, 3, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 121 },
- { 25, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 121 },
- { 5, 1, 0, 3, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 121 },
- { 5, 1, 0, 2, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 121 },
- { 5, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 121 },
- { 18, 1, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 91 },
- { 14, 1, 0, 0, -1, 0, 17, 0, { {0, 64}, {0, 0}, {0, 0}, {0, 64} }, 0, 10, 12, 7, 130 },
- { 15, 1, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, -64}, {0, -64}, {0, 0} }, 0, 10, 12, 6, 130 },
- { 5, 1, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 130 },
- { 18, 13, 0, 4, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 144 },
- { 18, 13, 0, 2, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 144 },
- { 18, 13, 0, 3, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 144 },
- { 0, 17, 230, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 144 },
- { 3, 5, 0, 0, 0, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 2, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 3, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 4, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 5, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 6, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 7, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 8, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 3, 5, 0, 0, 9, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 144 },
- { 5, 5, 0, 0, 1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 2, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 3, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 4, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 5, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 6, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 7, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 8, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, 9, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 5, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 18, 1, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 156 },
- { 0, 17, 230, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 156 },
- { 20, 1, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 156 },
- { 18, 1, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 147 },
- { 5, 1, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 147 },
- { 18, 13, 0, 2, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 148 },
- { 18, 13, 0, 3, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 148 },
- { 18, 13, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 148 },
- { 0, 17, 220, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 148 },
- { 0, 17, 230, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 148 },
- { 5, 13, 0, 2, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 148 },
- { 5, 13, 0, 3, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 148 },
- { 25, 13, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 148 },
- { 18, 1, 0, 2, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 153 },
- { 18, 1, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 153 },
- { 18, 1, 0, 3, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 153 },
- { 5, 1, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 153 },
- { 5, 1, 0, 3, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 153 },
- { 5, 1, 0, 2, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 153 },
- { 5, 1, 0, 4, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 153 },
- { 18, 1, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 149 },
- { 1, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 94 },
- { 0, 17, 0, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 94 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 94 },
- { 0, 17, 9, 5, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 94 },
- { 25, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 94 },
- { 25, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 2, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 3, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 4, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 5, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 6, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 7, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 8, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, 9, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 5, 10, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 94 },
- { 3, 0, 0, 0, 0, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 2, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 3, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 4, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 5, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 6, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 7, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 8, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 3, 0, 0, 0, 9, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 94 },
- { 0, 17, 9, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 94 },
- { 0, 17, 0, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 92 },
- { 1, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 92 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 92 },
- { 18, 0, 0, 0, -1, 0, 11, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 92 },
- { 0, 17, 9, 5, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 92 },
- { 0, 17, 7, 5, -1, 0, 11, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 92 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 92 },
- { 10, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 92 },
- { 25, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 92 },
- { 10, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 6, 12, 4, 92 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 101 },
- { 3, 0, 0, 0, 0, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 2, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 3, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 4, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 5, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 6, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 7, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 8, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 3, 0, 0, 0, 9, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 101 },
- { 0, 17, 230, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 96 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 96 },
- { 0, 17, 0, 5, -1, 0, 13, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 96 },
- { 0, 17, 0, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 96 },
- { 1, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 96 },
- { 0, 17, 0, 5, -1, 0, 13, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 96 },
- { 0, 17, 9, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 96 },
- { 3, 0, 0, 0, 0, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 2, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 3, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 4, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 5, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 6, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 7, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 8, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 3, 0, 0, 0, 9, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 96 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 96 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 96 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 96 },
- { 1, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 96 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 96 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 111 },
- { 0, 17, 7, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 111 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 111 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 111 },
- { 0, 17, 0, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 100 },
- { 1, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 100 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 100 },
- { 1, 0, 9, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 100 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 100 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 100 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 100 },
- { 25, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 100 },
- { 0, 17, 0, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 100 },
- { 0, 17, 7, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 100 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 100 },
- { 1, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 100 },
- { 0, 17, 0, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 100 },
- { 3, 0, 0, 0, 0, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 2, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 3, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 4, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 5, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 6, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 7, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 8, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 3, 0, 0, 0, 9, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 100 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 100 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 100 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 100 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 100 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 100 },
- { 5, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 20 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 109 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 109 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 109 },
- { 1, 0, 9, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 109 },
- { 0, 17, 7, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 109 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 109 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 109 },
- { 0, 17, 0, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 109 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 129 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 129 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 123 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 123 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 123 },
- { 0, 17, 7, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 123 },
- { 0, 17, 9, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 123 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 123 },
- { 0, 17, 0, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 107 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 107 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 107 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 107 },
- { 0, 17, 7, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 7, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 107 },
- { 1, 0, 0, 0, -1, 0, 16, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 107 },
- { 1, 0, 0, 0, -1, 0, 16, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 107 },
- { 1, 0, 9, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 107 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 107 },
- { 0, 17, 230, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 107 },
- { 18, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 135 },
- { 1, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 135 },
- { 0, 17, 0, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 135 },
- { 0, 17, 9, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 135 },
- { 0, 17, 7, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 135 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 135 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 135 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 135 },
- { 3, 0, 0, 0, 0, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 2, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 3, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 4, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 5, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 6, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 7, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 8, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 3, 0, 0, 0, 9, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 135 },
- { 25, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 135 },
- { 0, 17, 230, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 135 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 135 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 135 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 124 },
- { 1, 0, 0, 0, -1, 0, 16, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 124 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 124 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 124 },
- { 0, 17, 0, 5, -1, 0, 16, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 124 },
- { 1, 0, 0, 0, -1, 0, 16, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 124 },
- { 0, 17, 9, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 124 },
- { 0, 17, 7, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 124 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 124 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 124 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 122 },
- { 1, 0, 0, 0, -1, 0, 16, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 122 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 122 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 122 },
- { 1, 0, 0, 0, -1, 0, 16, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 122 },
- { 0, 17, 9, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 122 },
- { 0, 17, 7, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 122 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 122 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 122 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 122 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 122 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 122 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 122 },
- { 0, 17, 0, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 122 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 114 },
- { 1, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 114 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 114 },
- { 0, 17, 9, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 114 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 114 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 114 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 114 },
- { 25, 10, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 33 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 102 },
- { 0, 17, 0, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 102 },
- { 1, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 102 },
- { 1, 0, 9, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 102 },
- { 0, 17, 7, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 102 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 102 },
- { 3, 0, 0, 0, 0, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 2, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 3, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 4, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 5, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 6, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 7, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 8, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 3, 0, 0, 0, 9, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 102 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 126 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 8, 126 },
- { 0, 17, 0, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 126 },
- { 1, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 33, 4, 126 },
- { 0, 17, 9, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 4, 126 },
- { 3, 0, 0, 0, 0, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 2, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 3, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 4, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 5, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 6, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 7, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 8, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 3, 0, 0, 0, 9, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 126 },
- { 5, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 126 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 126 },
- { 29, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 33, 0, 126 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 142 },
- { 1, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 142 },
- { 0, 17, 0, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 142 },
- { 0, 17, 9, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 142 },
- { 0, 17, 7, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 142 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 142 },
- { 14, 0, 0, 0, -1, 0, 16, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 125 },
- { 15, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 125 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 125 },
- { 5, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 125 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 125 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 154 },
- { 1, 0, 0, 0, -1, 0, 23, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 154 },
- { 1, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 154 },
- { 1, 0, 0, 0, -1, 0, 23, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 154 },
- { 0, 17, 0, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 154 },
- { 1, 0, 9, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 154 },
- { 0, 17, 9, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 154 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 154 },
- { 0, 17, 7, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 154 },
- { 25, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 154 },
- { 25, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 154 },
- { 3, 0, 0, 0, 0, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 2, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 3, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 4, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 5, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 6, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 7, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 8, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 3, 0, 0, 0, 9, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 154 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 150 },
- { 1, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 150 },
- { 0, 17, 0, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 150 },
- { 0, 17, 9, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 150 },
- { 25, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 150 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 141 },
- { 0, 17, 0, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 141 },
- { 0, 0, 0, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 141 },
- { 0, 17, 9, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 141 },
- { 1, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 141 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 141 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 141 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 141 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 141 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 141 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 140 },
- { 0, 17, 0, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 140 },
- { 1, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 140 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 140 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 140 },
- { 0, 17, 9, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 140 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 140 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 140 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 140 },
- { 25, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 140 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 119 },
- { 18, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 133 },
- { 1, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 133 },
- { 0, 17, 0, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 133 },
- { 0, 0, 9, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 133 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 133 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 133 },
- { 3, 0, 0, 0, 0, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 2, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 3, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 4, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 5, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 6, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 7, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 8, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 3, 0, 0, 0, 9, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 133 },
- { 5, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 133 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 0, 134 },
- { 25, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 134 },
- { 18, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 134 },
- { 0, 17, 0, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 134 },
- { 1, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 134 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 138 },
- { 0, 17, 0, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 138 },
- { 0, 17, 7, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 138 },
- { 0, 17, 9, 5, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 138 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 12, 8, 138 },
- { 3, 0, 0, 0, 0, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 2, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 3, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 4, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 5, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 6, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 7, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 8, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 3, 0, 0, 0, 9, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 138 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 143 },
- { 1, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 143 },
- { 0, 17, 0, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 143 },
- { 0, 17, 9, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 143 },
- { 3, 0, 0, 0, 0, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 2, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 3, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 4, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 5, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 6, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 7, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 8, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 3, 0, 0, 0, 9, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 143 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 145 },
- { 0, 17, 0, 5, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 145 },
- { 1, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 145 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 12, 145 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 83 },
- { 5, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 16 },
- { 29, 10, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 16 },
- { 27, 4, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 16 },
- { 25, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 16 },
- { 18, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 63 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 63 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 63 },
- { 4, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 63 },
- { 4, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 63 },
- { 25, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 63 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 63 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 81 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 0, 8, 81 },
- { 18, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 1, 8, 81 },
- { 10, 0, 0, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 4, 4, 81 },
- { 10, 0, 0, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 0, 4, 81 },
- { 10, 0, 0, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 1, 4, 81 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 127 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 0, 8, 127 },
- { 18, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 1, 8, 127 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 84 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 115 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 115 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 115 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 104 },
- { 0, 17, 1, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 104 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 104 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 108 },
- { 0, 17, 230, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 108 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 108 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 108 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 108 },
- { 29, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 108 },
- { 17, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 108 },
- { 3, 0, 0, 0, 0, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 2, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 3, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 4, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 5, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 6, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 7, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 8, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 3, 0, 0, 0, 9, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 108 },
- { 5, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 108 },
- { 14, 0, 0, 0, -1, 0, 20, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 12, 7, 146 },
- { 15, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 12, 6, 146 },
- { 5, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 146 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 146 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 146 },
- { 25, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 146 },
- { 18, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 99 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 99 },
- { 0, 17, 0, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 99 },
- { 1, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 99 },
- { 1, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 99 },
- { 0, 17, 0, 5, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 99 },
- { 17, 0, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 99 },
- { 17, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 137 },
- { 17, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 139 },
- { 25, 10, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 0, 2 },
- { 17, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 5, 8, 2 },
- { 0, 17, 0, 5, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 4, 4, 155 },
- { 1, 0, 6, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 37 },
- { 18, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 137 },
- { 18, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 137 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 137 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 137 },
- { 18, 0, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 8, 155 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 8, 34 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 5, 8, 35 },
- { 18, 0, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 139 },
- { 18, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 105 },
- { 29, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 105 },
- { 0, 17, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 105 },
- { 0, 17, 1, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 105 },
- { 25, 0, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 105 },
- { 10, 18, 0, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 29, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 1, 0, 216, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 2 },
- { 1, 0, 216, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 2 },
- { 0, 17, 1, 5, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 1, 0, 226, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 21, 4, 2 },
- { 10, 18, 0, 5, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 21, 4, 2 },
- { 0, 17, 220, 5, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 0, 17, 230, 5, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 29, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 0, 17, 230, 5, -1, 0, 8, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 4 },
- { 5, 0, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 0, 0, 0, -1, 0, 9, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 15, 0, 0, 0, -1, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 15, 0, 0, 0, -1, 0, 7, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 26, 0, 0, 0, -1, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 26, 10, 0, 0, -1, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 14, 0, 0, 0, -1, 0, 9, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 15, 0, 0, 0, -1, 0, 9, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 6, 2 },
- { 3, 2, 0, 0, 0, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 1, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 2, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 3, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 4, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 5, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 6, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 7, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 8, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 9, 0, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 29, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 131 },
- { 0, 17, 0, 5, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 131 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 131 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 12, 131 },
- { 25, 0, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 131 },
- { 0, 17, 230, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 57 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 151 },
- { 0, 17, 230, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 151 },
- { 17, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 151 },
- { 3, 0, 0, 0, 0, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 2, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 3, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 4, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 5, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 6, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 7, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 8, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 3, 0, 0, 0, 9, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 151 },
- { 29, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 151 },
- { 18, 0, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 152 },
- { 0, 17, 230, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 152 },
- { 3, 0, 0, 0, 0, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 2, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 3, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 4, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 5, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 6, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 7, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 8, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 3, 0, 0, 0, 9, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 152 },
- { 27, 4, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 152 },
- { 18, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 113 },
- { 5, 1, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 113 },
- { 0, 17, 220, 5, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 113 },
- { 14, 1, 0, 2, -1, 0, 18, 0, { {0, 34}, {0, 0}, {0, 0}, {0, 34} }, 0, 10, 12, 7, 132 },
- { 15, 1, 0, 2, -1, 0, 18, 0, { {0, 0}, {0, -34}, {0, -34}, {0, 0} }, 0, 10, 12, 6, 132 },
- { 0, 17, 230, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 132 },
- { 0, 17, 7, 5, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 132 },
- { 17, 1, 0, 5, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 132 },
- { 3, 1, 0, 0, 0, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 2, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 3, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 4, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 5, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 6, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 7, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 8, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 3, 1, 0, 0, 9, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 132 },
- { 25, 1, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 0, 132 },
- { 5, 13, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 13, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 27, 13, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 0, 2 },
- { 5, 13, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 13, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 18, 13, 0, 0, -1, 0, 13, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 8, 8 },
- { 26, 10, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 8 },
- { 5, 2, 0, 0, 0, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 1, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 2, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 3, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 4, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 5, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 6, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 7, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 8, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 2, 0, 0, 9, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 5, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 12, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 29, 0, 0, 0, -1, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 29, 0, 0, 0, -1, 0, 12, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 29, 0, 0, 0, -1, 0, 11, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 12, 7, 2 },
- { 29, 10, 0, 0, -1, 0, 13, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 21, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 6, 7, 28, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 11, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 34 },
- { 29, 0, 0, 0, -1, 0, 12, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 0, 0, 0, -1, 0, 18, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 28, 10, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 31, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 18, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 13, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 2 },
- { 29, 10, 0, 0, -1, 0, 16, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 5, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 23, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 21, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 17, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 19, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 29, 10, 0, 0, -1, 0, 20, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 30, 0, 2 },
- { 3, 2, 0, 0, 0, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 1, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 2, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 3, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 4, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 5, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 6, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 7, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 8, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 3, 2, 0, 0, 9, 0, 23, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 11, 9, 2 },
- { 13, 18, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 },
- { 18, 0, 0, 0, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 12, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 18, 0, 0, 0, -1, 0, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 37 },
- { 10, 18, 0, 5, -1, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 2 },
- { 0, 17, 0, 5, -1, 0, 7, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 21, 4, 1 },
- { 12, 0, 0, 0, -1, 0, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0 }
+static constexpr Properties uc_properties[] = {
+ { 9, 18, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 23, 0, 0, 2 },
+ { 9, 8, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 19, 5, 0, 2 },
+ { 9, 7, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 2, 2, 39, 2, 0, 2 },
+ { 9, 8, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 40, 5, 0, 2 },
+ { 9, 9, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 40, 5, 0, 2 },
+ { 9, 7, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 1, 1, 38, 1, 0, 2 },
+ { 9, 7, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 23, 0, 0, 2 },
+ { 9, 8, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 23, 0, 0, 2 },
+ { 6, 9, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 18, 37, 5, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 12, 3, 13, 0, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 0, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 11, 3, 13, 0, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 2, 13, 0, 2 },
+ { 26, 3, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 0, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 11, 0, 2 },
+ { 20, 3, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 18, 11, 1, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 10, 1, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 9, 0, 0, 2 },
+ { 3, 2, 0, 0, 0, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 2, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 3, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 4, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 5, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 6, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 7, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 8, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 3, 2, 0, 0, 9, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 10, 11, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, 2, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, -2, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 4, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 3 },
+ { 21, 10, 0, 0, -1, 2, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 0, 2 },
+ { 22, 10, 0, 0, -1, -2, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 2, 13, 0, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 19, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 14, 0, 1, 2 },
+ { 15, 0, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 26, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 0, 2 },
+ { 22, 10, 0, 0, -1, -2, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 9, 7, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 40, 3, 0, 2 },
+ { 6, 6, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 5, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 23, 10, 0, 0, -1, 16, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 10, 18, 0, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 19, 4, 2, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 4, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 29, 4, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 26, 4, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 5, 2, 0, 0, 2, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 2, 0, 0, 3, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 0, 2 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 743}, {0, 743}, {0, 775} }, 0, 10, 14, 6, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 14, 0, 1, 2 },
+ { 5, 2, 0, 0, 1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 24, 10, 0, 0, -1, -16, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 5, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 3 },
+ { 26, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {1, 418}, {1, 415}, {0, 0} }, 0, 10, 14, 6, 4, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 121}, {0, 121}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {1, 421}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, -232}, {0, -232}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {1, 500}, {1, 500}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -121}, {0, 0}, {0, 0}, {0, -121} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -300}, {0, -300}, {0, -268} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 195}, {0, 195}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 210}, {0, 0}, {0, 0}, {0, 210} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 206}, {0, 0}, {0, 0}, {0, 206} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 205}, {0, 0}, {0, 0}, {0, 205} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 79}, {0, 0}, {0, 0}, {0, 79} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 202}, {0, 0}, {0, 0}, {0, 202} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 203}, {0, 0}, {0, 0}, {0, 203} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 207}, {0, 0}, {0, 0}, {0, 207} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 97}, {0, 97}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 211}, {0, 0}, {0, 0}, {0, 211} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 209}, {0, 0}, {0, 0}, {0, 209} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 163}, {0, 163}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 213}, {0, 0}, {0, 0}, {0, 213} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 130}, {0, 130}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 214}, {0, 0}, {0, 0}, {0, 214} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 218}, {0, 0}, {0, 0}, {0, 218} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 217}, {0, 0}, {0, 0}, {0, 217} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 219}, {0, 0}, {0, 0}, {0, 219} }, 0, 10, 14, 7, 3, 3 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 56}, {0, 56}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 2}, {0, 0}, {0, 1}, {0, 2} }, 0, 10, 14, 7, 3, 3 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 1}, {0, -1}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -2}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -79}, {0, -79}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 511}, {1, 511}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {0, -97}, {0, 0}, {0, 0}, {0, -97} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {0, -56}, {0, 0}, {0, 0}, {0, -56} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 6, 3, 0, { {0, -130}, {0, 0}, {0, 0}, {0, -130} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {1, 1}, {0, 0}, {0, 0}, {1, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {0, -163}, {0, 0}, {0, 0}, {0, -163} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {1, 3}, {0, 0}, {0, 0}, {1, 3} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {1, 5}, {1, 5}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {1, 7}, {1, 7}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {0, -195}, {0, 0}, {0, 0}, {0, -195} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 69}, {0, 0}, {0, 0}, {0, 69} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 71}, {0, 0}, {0, 0}, {0, 71} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 9}, {1, 9}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {1, 11}, {1, 11}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 13}, {1, 13}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -210}, {0, -210}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -206}, {0, -206}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -205}, {0, -205}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -202}, {0, -202}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -203}, {0, -203}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 15}, {1, 15}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {1, 17}, {1, 17}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -207}, {0, -207}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 19}, {1, 19}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 21}, {1, 21}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -209}, {0, -209}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -211}, {0, -211}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 23}, {1, 23}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 25}, {1, 25}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 27}, {1, 27}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 29}, {1, 29}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -213}, {0, -213}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -214}, {0, -214}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 31}, {1, 31}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -218}, {0, -218}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 33}, {1, 33}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 35}, {1, 35}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -69}, {0, -69}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -217}, {0, -217}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -71}, {0, -71}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -219}, {0, -219}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 37}, {1, 37}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {1, 39}, {1, 39}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 17, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 17, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 17, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 20, 8, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 28, 10, 0, 0, -1, 0, 4, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 20, 0, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 36 },
+ { 17, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 0, 17, 230, 5, -1, 0, 1, 0, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 232, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 216, 5, -1, 0, 1, 0, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 202, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 1, 0, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 202, 5, -1, 0, 1, 0, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 1, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 1, 5, -1, 0, 1, 0, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 1, 0, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 3, 1 },
+ { 0, 17, 240, 5, -1, 0, 1, 0, 204, { {0, 0}, {0, 84}, {0, 84}, {0, 116} }, 4, 4, 23, 4, 3, 1 },
+ { 0, 17, 230, 5, -1, 0, 4, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 4, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 0, 5, -1, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 2, 1 },
+ { 0, 17, 230, 5, -1, 0, 7, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 7, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 232, 5, -1, 0, 8, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 8, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 8, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 233, 5, -1, 0, 8, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 0, 17, 234, 5, -1, 0, 7, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 0, 17, 233, 5, -1, 0, 7, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 0, 17, 234, 5, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 0, 17, 233, 5, -1, 0, 4, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 17, 10, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 13, 0, 0, 0, -1, 0, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 0, 4 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 130}, {0, 130}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 0, 0, 2 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 116}, {0, 0}, {0, 0}, {0, 116} }, 0, 10, 14, 7, 3, 4 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 4 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 81, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 38}, {0, 0}, {0, 0}, {0, 38} }, 0, 10, 14, 7, 3, 4 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 14, 0, 3, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 37}, {0, 0}, {0, 0}, {0, 37} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 64}, {0, 0}, {0, 0}, {0, 64} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 63}, {0, 0}, {0, 0}, {0, 63} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 503}, {1, 503}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -38}, {0, -38}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -37}, {0, -37}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 507}, {1, 507}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -31}, {0, -31}, {0, 1} }, 0, 10, 14, 6, 4, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -64}, {0, -64}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -63}, {0, -63}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 8}, {0, 0}, {0, 0}, {0, 8} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -62}, {0, -62}, {0, -30} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -57}, {0, -57}, {0, -25} }, 0, 10, 14, 6, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 81, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -47}, {0, -47}, {0, -15} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -54}, {0, -54}, {0, -22} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, -8}, {0, -8}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 46 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 46 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -86}, {0, -86}, {0, -54} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -80}, {0, -80}, {0, -48} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 7}, {0, 7}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -116}, {0, -116}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 5, 3, 80, { {0, -60}, {0, 0}, {0, 0}, {0, -60} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 5, 3, 80, { {0, 0}, {0, -96}, {0, -96}, {0, -64} }, 0, 10, 14, 6, 3, 4 },
+ { 26, 10, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 7, 3, 80, { {0, -7}, {0, 0}, {0, 0}, {0, -7} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {0, -130}, {0, 0}, {0, 0}, {0, -130} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 14, 7, 3, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 17, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 14, 7, 3, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 14, 7, 3, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 80}, {0, 0}, {0, 0}, {0, 80} }, 0, 10, 14, 7, 3, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 17, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 17, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 17, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -80}, {0, -80}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 29, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 5 },
+ { 0, 17, 230, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 0, 17, 230, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 2, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 15}, {0, 0}, {0, 0}, {0, 15} }, 0, 10, 14, 7, 0, 5 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, -15}, {0, -15}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 48}, {0, 0}, {0, 0}, {0, 48} }, 0, 10, 14, 7, 3, 6 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 6 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 6 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 11, 1, 6 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 14, 0, 1, 6 },
+ { 15, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 6 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, -48}, {0, -48}, {0, 0} }, 0, 10, 14, 6, 1, 6 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 467}, {1, 464}, {0, 0} }, 0, 10, 14, 6, 3, 6 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 12, 1, 6 },
+ { 20, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 19, 0, 1, 6 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 6 },
+ { 27, 4, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 6 },
+ { 13, 1, 0, 0, -1, 0, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 0, 17, 220, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 230, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 222, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 220, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 228, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 10, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 11, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 12, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 13, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 14, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 15, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 16, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 17, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 18, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 19, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 19, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 20, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 21, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 22, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 20, 1, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 7 },
+ { 0, 17, 23, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 25, 1, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 7 },
+ { 0, 17, 24, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 0, 17, 25, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 25, 1, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 7 },
+ { 0, 17, 18, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 18, 1, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 15, 8, 1, 7 },
+ { 18, 1, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 15, 8, 1, 7 },
+ { 25, 1, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 7 },
+ { 25, 1, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 14, 0, 1, 7 },
+ { 10, 5, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 8 },
+ { 10, 5, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 8 },
+ { 10, 5, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 2 },
+ { 26, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 26, 13, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 25, 4, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 8 },
+ { 27, 13, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 8 },
+ { 25, 6, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 11, 1, 2 },
+ { 25, 13, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 11, 1, 8 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 30, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 31, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 32, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 25, 13, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 2 },
+ { 10, 13, 0, 5, -1, 0, 15, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 8 },
+ { 25, 13, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 8 },
+ { 25, 13, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 8 },
+ { 25, 13, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 2 },
+ { 18, 13, 0, 2, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 17, 13, 0, 1, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 0, 17, 27, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 28, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 29, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 30, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 31, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 32, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 33, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 34, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 4, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 4, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 220, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 220, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 3, 5, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 5, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 25, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 8 },
+ { 25, 5, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 25, 5, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 13, 9, 1, 8 },
+ { 25, 13, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 0, 17, 35, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 18, 13, 0, 3, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 8 },
+ { 18, 13, 0, 2, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 8 },
+ { 18, 13, 0, 2, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 25, 13, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 10, 5, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 0, 17, 220, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 17, 13, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 3, 2, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 3, 2, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 8 },
+ { 29, 13, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 25, 13, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 9 },
+ { 25, 13, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 9 },
+ { 13, 13, 0, 0, -1, 0, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 10, 13, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 4, 0, 9 },
+ { 18, 13, 0, 3, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 0, 17, 36, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 9 },
+ { 18, 13, 0, 2, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 18, 13, 0, 2, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 18, 13, 0, 3, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 0, 17, 230, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 9 },
+ { 0, 17, 220, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 9 },
+ { 18, 13, 0, 2, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 10 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 10 },
+ { 18, 13, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 10 },
+ { 3, 1, 0, 0, 0, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 2, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 3, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 4, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 5, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 6, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 7, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 8, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 3, 1, 0, 0, 9, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 66 },
+ { 18, 1, 0, 2, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 66 },
+ { 0, 17, 230, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 66 },
+ { 0, 17, 220, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 66 },
+ { 17, 1, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 66 },
+ { 29, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 66 },
+ { 25, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 66 },
+ { 25, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 11, 1, 66 },
+ { 25, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 66 },
+ { 17, 1, 0, 1, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 66 },
+ { 0, 17, 220, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 66 },
+ { 27, 1, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 66 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 82 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 82 },
+ { 17, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 82 },
+ { 25, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 82 },
+ { 25, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 82 },
+ { 18, 1, 0, 3, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 95 },
+ { 18, 1, 0, 2, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 95 },
+ { 0, 17, 220, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 95 },
+ { 25, 1, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 95 },
+ { 18, 13, 0, 2, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 18, 13, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 18, 13, 0, 3, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 9 },
+ { 18, 13, 0, 3, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 1, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 28, 13, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 10, 5, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 8 },
+ { 0, 17, 230, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 220, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 3, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 18, 13, 0, 2, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 17, 13, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 0, 17, 220, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 10, 5, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 2 },
+ { 0, 17, 220, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 220, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 27, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 28, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 29, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 230, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 0, 17, 0, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 0, 17, 0, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 1, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 11 },
+ { 0, 17, 7, 5, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 11 },
+ { 0, 17, 220, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 11 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 2 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 11 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 11 },
+ { 17, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 12 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 12 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 12 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 12 },
+ { 0, 17, 7, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 12 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 12 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 12 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 12 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 12 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 12 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 12 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 12 },
+ { 27, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 12 },
+ { 5, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 12 },
+ { 5, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 12 },
+ { 29, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 12 },
+ { 27, 4, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 12 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 12 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 12 },
+ { 0, 17, 230, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 12 },
+ { 0, 17, 0, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 13 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 13 },
+ { 1, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 13 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 13 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 13 },
+ { 0, 17, 7, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 13 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 13 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 13 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 13 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 13 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 13 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 14 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 14 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 14 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 14 },
+ { 0, 17, 7, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 14 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 14 },
+ { 0, 17, 0, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 14 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 14 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 14 },
+ { 27, 4, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 14 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 14 },
+ { 0, 17, 0, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 14 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 15 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 15 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 15 },
+ { 0, 17, 7, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 15 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 0, 17, 0, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 15 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 15 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 15 },
+ { 29, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 15 },
+ { 5, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 15 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 16 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 16 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 16 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 16 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 16 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 16 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 16 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 16 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 16 },
+ { 3, 0, 0, 0, 0, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 16 },
+ { 5, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 16 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 16 },
+ { 27, 4, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 16 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 17 },
+ { 0, 17, 0, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 17 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 17 },
+ { 0, 17, 7, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 17 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 0, 17, 84, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 0, 17, 91, 5, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 17 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 17 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 17 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 17 },
+ { 25, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 17 },
+ { 5, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 17 },
+ { 29, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 17 },
+ { 18, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 18 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 18 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 18 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 18 },
+ { 0, 17, 7, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 18 },
+ { 0, 0, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 18 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 18 },
+ { 0, 17, 0, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 18 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 18 },
+ { 18, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 18 },
+ { 1, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 18 },
+ { 0, 17, 0, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 19 },
+ { 0, 17, 9, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 19 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 1, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 19 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 19 },
+ { 29, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 19 },
+ { 5, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 19 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 19 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 19 },
+ { 5, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 19 },
+ { 29, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 19 },
+ { 0, 17, 0, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 20 },
+ { 1, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 20 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 20 },
+ { 0, 17, 9, 5, -1, 0, 4, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 20 },
+ { 1, 0, 0, 0, -1, 0, 4, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 20 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 20 },
+ { 1, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 20 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 20 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 20 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 21 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 21 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 0, 35, 8, 3, 21 },
+ { 0, 17, 103, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 21 },
+ { 0, 17, 9, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 21 },
+ { 27, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 21 },
+ { 0, 17, 107, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 21 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 21 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 21 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 21 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 22 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 22 },
+ { 0, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 22 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 0, 35, 8, 3, 22 },
+ { 0, 17, 118, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 22 },
+ { 0, 17, 9, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 22 },
+ { 17, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 22 },
+ { 0, 17, 122, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 22 },
+ { 0, 17, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 22 },
+ { 3, 0, 0, 0, 0, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 3, 0, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 22 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 3, 22 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 22 },
+ { 18, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 2, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 3, 23 },
+ { 25, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 23 },
+ { 0, 17, 220, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 3, 0, 0, 0, 0, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 2, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 3, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 4, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 5, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 6, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 7, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 8, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 3, 0, 0, 0, 9, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 23 },
+ { 5, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 23 },
+ { 0, 17, 216, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 21, 10, 0, 0, -1, 1, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 23 },
+ { 22, 10, 0, 0, -1, -1, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 23 },
+ { 1, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 23 },
+ { 18, 0, 0, 0, -1, 0, 2, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 23 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 23 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 23 },
+ { 0, 17, 129, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 0, 17, 130, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 0, 17, 0, 5, -1, 0, 2, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 3, 23 },
+ { 0, 17, 132, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 0, 17, 0, 5, -1, 0, 2, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 3, 23 },
+ { 0, 17, 0, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 1, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 19, 4, 1, 23 },
+ { 0, 17, 230, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 0, 17, 9, 5, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 23 },
+ { 0, 17, 0, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 23 },
+ { 0, 17, 220, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 23 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 23 },
+ { 29, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 1, 23 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 35, 4, 1, 24 },
+ { 1, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 35, 4, 1, 24 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 1, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 35, 4, 1, 24 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 0, 17, 7, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 0, 17, 9, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 0, 17, 9, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 35, 4, 1, 24 },
+ { 3, 0, 0, 0, 0, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 2, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 3, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 4, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 5, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 6, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 7, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 8, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 9, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 24 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 24 },
+ { 0, 17, 220, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 35, 4, 1, 24 },
+ { 0, 17, 0, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 29, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 24 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 7264}, {0, 0}, {0, 0}, {0, 7264} }, 0, 10, 14, 7, 0, 25 },
+ { 14, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 7264}, {0, 0}, {0, 0}, {0, 7264} }, 0, 10, 14, 7, 3, 25 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 25 },
+ { 15, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 25 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 25 },
+ { 25, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 8, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 25 },
+ { 15, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 3008}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 25 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 9, 10, 27, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 11, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 9, 10, 27, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 9, 10, 27, 8, 0, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 28, 8, 0, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 28, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 28, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 10, 10, 28, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 11, 10, 29, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 11, 10, 29, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 11, 10, 29, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 27 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 27 },
+ { 0, 17, 230, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 27 },
+ { 0, 17, 230, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 27 },
+ { 25, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 27 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 27 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 2, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 3, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 4, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 5, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 6, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 7, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 8, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, 9, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 5, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 27 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 41}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 43}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 45}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 47}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 49}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 51}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 53}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 55}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 57}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 59}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 61}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 63}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 65}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 67}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 69}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 71}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 73}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 75}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 77}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 79}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 81}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 83}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 85}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 87}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 89}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 91}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 93}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 95}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 97}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 99}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 101}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 103}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 105}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 107}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 109}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 111}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 113}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 115}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 117}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 119}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 121}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 123}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 125}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 127}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 129}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 131}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 133}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 135}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 137}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 139}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 141}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 143}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 145}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 147}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 149}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 151}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 153}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 155}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 157}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 159}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 161}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 163}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 165}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 167}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 169}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 171}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 173}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 175}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 177}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 179}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 181}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 183}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 185}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 187}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 189}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 191}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 193}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 195}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 197}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {1, 199}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 8}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 14, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 8}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, -8}, {0, -8}, {0, -8} }, 0, 10, 14, 6, 3, 28 },
+ { 20, 10, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 29 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 29 },
+ { 29, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 29 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 29 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 29 },
+ { 6, 9, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 18, 19, 5, 0, 30 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 30 },
+ { 21, 10, 0, 0, -1, 1, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 30 },
+ { 22, 10, 0, 0, -1, -1, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 30 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 31 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 4, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 31 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 31 },
+ { 18, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 42 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 42 },
+ { 0, 17, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 42 },
+ { 0, 17, 9, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 42 },
+ { 1, 0, 9, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 42 },
+ { 18, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 43 },
+ { 0, 17, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 43 },
+ { 1, 0, 9, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 43 },
+ { 25, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 44 },
+ { 0, 17, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 44 },
+ { 18, 0, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 45 },
+ { 0, 17, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 45 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 32 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 0, 32 },
+ { 1, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 35, 4, 1, 32 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 32 },
+ { 0, 17, 9, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 32 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 32 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 1, 32 },
+ { 17, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 32 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 32 },
+ { 25, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 32 },
+ { 27, 4, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 32 },
+ { 0, 17, 230, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 32 },
+ { 3, 0, 0, 0, 0, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 2, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 3, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 4, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 5, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 6, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 7, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 8, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 3, 0, 0, 0, 9, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 32 },
+ { 5, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 32 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 33 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 11, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 33 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 0, 33 },
+ { 25, 10, 0, 2, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 33 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 11, 1, 33 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 33 },
+ { 25, 10, 0, 1, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 33 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 2, 33 },
+ { 10, 18, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 6, 4, 0, 33 },
+ { 0, 17, 0, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 2, 33 },
+ { 3, 0, 0, 0, 0, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 2, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 3, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 4, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 5, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 6, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 7, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 8, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 3, 0, 0, 0, 9, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 33 },
+ { 18, 0, 0, 2, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 33 },
+ { 17, 0, 0, 2, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 33 },
+ { 18, 0, 0, 2, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 33 },
+ { 18, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 33 },
+ { 0, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 33 },
+ { 0, 17, 228, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 33 },
+ { 18, 0, 0, 2, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 33 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 47 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 47 },
+ { 0, 17, 0, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 47 },
+ { 1, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 47 },
+ { 0, 17, 222, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 47 },
+ { 0, 17, 230, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 47 },
+ { 0, 17, 220, 5, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 47 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 47 },
+ { 25, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 47 },
+ { 3, 0, 0, 0, 0, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 2, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 3, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 4, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 5, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 6, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 7, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 8, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 3, 0, 0, 0, 9, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 47 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 48 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 56 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 56 },
+ { 3, 0, 0, 0, 0, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 2, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 3, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 4, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 5, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 6, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 7, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 8, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 3, 0, 0, 0, 9, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 56 },
+ { 5, 0, 0, 0, 1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 56 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 56 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 32 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 55 },
+ { 0, 17, 230, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 55 },
+ { 0, 17, 220, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 55 },
+ { 1, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 55 },
+ { 0, 17, 0, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 55 },
+ { 25, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 55 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 78 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 35, 4, 1, 78 },
+ { 0, 17, 0, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 78 },
+ { 0, 17, 9, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 78 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 35, 4, 1, 78 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 78 },
+ { 0, 17, 220, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 78 },
+ { 3, 0, 0, 0, 0, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 2, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 3, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 4, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 5, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 6, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 7, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 8, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 3, 0, 0, 0, 9, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 78 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 78 },
+ { 17, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 78 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 12, 1, 78 },
+ { 0, 17, 230, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 2, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 0, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 62 },
+ { 1, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 62 },
+ { 18, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 62 },
+ { 18, 0, 0, 0, -1, 0, 9, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 62 },
+ { 0, 17, 7, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 62 },
+ { 1, 0, 0, 0, -1, 0, 9, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 62 },
+ { 1, 0, 0, 0, -1, 0, 9, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 62 },
+ { 1, 0, 9, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 62 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 62 },
+ { 3, 0, 0, 0, 0, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 2, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 3, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 4, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 5, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 6, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 7, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 8, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 3, 0, 0, 0, 9, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 62 },
+ { 25, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 62 },
+ { 25, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 62 },
+ { 25, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 62 },
+ { 29, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 62 },
+ { 0, 17, 230, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 62 },
+ { 0, 17, 220, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 62 },
+ { 25, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 62 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 67 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 67 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 67 },
+ { 1, 0, 9, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 67 },
+ { 0, 17, 9, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 67 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 67 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 67 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 67 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 93 },
+ { 0, 17, 7, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 93 },
+ { 1, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 93 },
+ { 0, 17, 0, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 93 },
+ { 1, 0, 9, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 93 },
+ { 25, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 93 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 68 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 68 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 68 },
+ { 0, 17, 7, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 68 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 68 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 68 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 68 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 69 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 69 },
+ { 17, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 69 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 69 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6254}, {0, -6254}, {0, -6222} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6253}, {0, -6253}, {0, -6221} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6244}, {0, -6244}, {0, -6212} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6242}, {0, -6242}, {0, -6210} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6243}, {0, -6243}, {0, -6211} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6236}, {0, -6236}, {0, -6204} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -6181}, {0, -6181}, {0, -6180} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {1, 201}, {1, 201}, {1, 719} }, 0, 10, 14, 6, 3, 5 },
+ { 14, 0, 0, 0, -1, 0, 20, 3, 0, { {0, -3008}, {0, 0}, {0, 0}, {0, -3008} }, 0, 10, 14, 8, 3, 25 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 67 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 0, 17, 1, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 0, 17, 230, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 1, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 15, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 5 },
+ { 17, 0, 0, 0, -1, 0, 7, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 17, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 7, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 17, 0, 0, 0, -1, 0, 8, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 5 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {1, 203}, {1, 203}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 3814}, {0, 3814}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {1, 205}, {1, 205}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 8, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 17, 0, 0, 0, -1, 0, 8, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 0, 17, 230, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 234, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 0, 17, 214, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 202, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 232, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 228, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 218, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 233, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 1 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 514}, {1, 514}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 517}, {1, 517}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 520}, {1, 520}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 523}, {1, 523}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 526}, {1, 526}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 2, 3, 81, { {0, 0}, {0, -59}, {0, -59}, {0, -58} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {0, -7615}, {0, 0}, {0, 0}, {0, -7615} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 8}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {0, 0}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 529}, {1, 529}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 532}, {1, 532}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 536}, {1, 536}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 540}, {1, 540}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 74}, {0, 74}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 74}, {0, 74}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 86}, {0, 86}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 86}, {0, 86}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 100}, {0, 100}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 100}, {0, 100}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 128}, {0, 128}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 128}, {0, 128}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 112}, {0, 112}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 112}, {0, 112}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 126}, {0, 126}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 126}, {0, 126}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 578}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 581}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 584}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 587}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 590}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 593}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 596}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 599}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 578}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 581}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 584}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 587}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 590}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 593}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 596}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 599}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 602}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 605}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 608}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 611}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 614}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 617}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 620}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 623}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 602}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 605}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 608}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 611}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 614}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 617}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 620}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 623}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 626}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 629}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 632}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 635}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 638}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 641}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 644}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 647}, {0, 8}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 626}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 629}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 632}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 635}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 638}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 641}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 644}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -8}, {1, 647}, {0, 0}, {0, -8} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 662}, {1, 659}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 650}, {0, 9}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 668}, {1, 665}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 544}, {1, 544}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 699}, {1, 695}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -74}, {0, 0}, {0, 0}, {0, -74} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {0, -74}, {0, 0}, {0, 0}, {0, -74} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -9}, {1, 650}, {0, 0}, {0, -9} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, -7205}, {0, -7205}, {0, -7173} }, 0, 10, 14, 6, 3, 4 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 81, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 674}, {1, 671}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 653}, {0, 9}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 680}, {1, 677}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 547}, {1, 547}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 707}, {1, 703}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -86}, {0, 0}, {0, 0}, {0, -86} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {0, -86}, {0, 0}, {0, 0}, {0, -86} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -9}, {1, 653}, {0, 0}, {0, -9} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 550}, {1, 550}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {1, 503}, {1, 503}, {0, -7235} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 554}, {1, 554}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 557}, {1, 557}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -100}, {0, 0}, {0, 0}, {0, -100} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {0, -100}, {0, 0}, {0, 0}, {0, -100} }, 0, 10, 14, 7, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 561}, {1, 561}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {1, 507}, {1, 507}, {0, -7219} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 565}, {1, 565}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 7}, {0, 7}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 568}, {1, 568}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 571}, {1, 571}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -112}, {0, 0}, {0, 0}, {0, -112} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {0, -112}, {0, 0}, {0, 0}, {0, -112} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -7}, {0, 0}, {0, 0}, {0, -7} }, 0, 10, 14, 7, 3, 4 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 686}, {1, 683}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 656}, {0, 9}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 692}, {1, 689}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 575}, {1, 575}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {1, 715}, {1, 711}, {0, 0} }, 0, 10, 14, 6, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -128}, {0, 0}, {0, 0}, {0, -128} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {0, -128}, {0, 0}, {0, 0}, {0, -128} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -126}, {0, 0}, {0, 0}, {0, -126} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {0, -126}, {0, 0}, {0, 0}, {0, -126} }, 0, 10, 14, 7, 3, 4 },
+ { 16, 0, 0, 0, -1, 0, 1, 3, 17, { {0, -9}, {1, 656}, {0, 0}, {0, -9} }, 0, 10, 14, 7, 3, 4 },
+ { 28, 10, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 0, 4 },
+ { 6, 9, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 18, 19, 5, 0, 2 },
+ { 6, 9, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 18, 19, 5, 0, 2 },
+ { 6, 9, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 5, 0, 2 },
+ { 10, 18, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 22, 4, 2, 2 },
+ { 10, 18, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 4, 1 },
+ { 10, 18, 0, 1, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 5, 5, 34, 4, 4, 1 },
+ { 10, 0, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 1, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 6, 0, 3, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 11, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 21, 11, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 23, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 3, 13, 1, 2 },
+ { 24, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 3, 13, 1, 2 },
+ { 21, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 23, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 23, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 24, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 17, 10, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 19, 0, 1, 2 },
+ { 7, 9, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 40, 3, 0, 2 },
+ { 8, 7, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 3, 40, 3, 0, 2 },
+ { 10, 11, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 14, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 16, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 12, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 15, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 6, 6, 0, 0, -1, 0, 4, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 6, 5, 0, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 2 },
+ { 23, 10, 0, 0, -1, 1, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 24, 10, 0, 0, -1, -1, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 7, 12, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 12, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 19, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 14, 0, 1, 2 },
+ { 26, 6, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 12, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 12, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 7, 12, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 19, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 2 },
+ { 6, 9, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 18, 19, 5, 0, 2 },
+ { 10, 18, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 24, 4, 2, 2 },
+ { 10, 18, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 14, 4, 0, 2 },
+ { 10, 18, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 14, 4, 2, 2 },
+ { 13, 18, 0, 0, -1, 0, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 0, 14, 0, 0, 0 },
+ { 10, 19, 0, 0, -1, 0, 15, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 20, 0, 0, -1, 0, 15, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 21, 0, 0, -1, 0, 15, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 22, 0, 0, -1, 0, 15, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 10, 18, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 5, 2, 0, 0, 0, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 17, 0, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 5, 2, 0, 0, 4, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 2, 0, 0, 5, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 2, 0, 0, 6, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 2, 0, 0, 7, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 2, 0, 0, 8, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 2, 0, 0, 9, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 3, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 26, 3, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 17, 0, 0, 0, -1, 0, 12, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 27, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 3, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 2, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 3, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 14, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 27, 4, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 13, 4, 0, 0, -1, 0, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 0, 0 },
+ { 0, 17, 1, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 2, 17, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 2, 17, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 2, 17, 0, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 1, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 220, 5, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 1, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 3, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 85, { {0, -7517}, {0, 0}, {0, 0}, {0, -7517} }, 0, 10, 14, 7, 3, 4 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 85, { {1, 207}, {0, 0}, {0, 0}, {1, 207} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 1, 0, 85, { {1, 209}, {0, 0}, {0, 0}, {1, 209} }, 0, 10, 14, 7, 3, 3 },
+ { 29, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 28}, {0, 0}, {0, 0}, {0, 28} }, 0, 10, 14, 7, 0, 3 },
+ { 18, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 4, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 10, 14, 6, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 14, 0, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, -28}, {0, -28}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 29, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, -1, 0, 11, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 4, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 16}, {0, 0}, {0, 0}, {0, 16} }, 0, 10, 14, 7, 3, 3 },
+ { 4, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 16}, {0, 0}, {0, 0}, {0, 16} }, 0, 10, 14, 7, 3, 3 },
+ { 4, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, -16}, {0, -16}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 4, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, -16}, {0, -16}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 4, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 0, 3 },
+ { 4, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 5, 10, 0, 0, -1, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 3, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 3, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 3, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -3, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -3, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -3, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 3, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 26, 4, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2016, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2527, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1923, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1914, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1918, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2250, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 1, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 138, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 7, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -7, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 0, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1, 1, 0, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 1, 0, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 1, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1824, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2104, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2108, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2106, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1316, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -138, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 8, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 7, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -8, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -7, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 3, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 2, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 3, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 4, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 5, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 6, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 7, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 8, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 9, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, 1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 2, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 3, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 4, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 5, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 6, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 7, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 8, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, 9, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 2, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 3, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 4, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 5, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 6, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 7, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 8, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 9, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 26}, {0, 0}, {0, 0}, {0, 26} }, 0, 10, 14, 7, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 26}, {0, 0}, {0, 0}, {0, 26} }, 14, 10, 14, 7, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 0, 80, { {0, 0}, {0, -26}, {0, -26}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 5, 10, 0, 0, 0, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 5, 10, 0, 0, -1, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 1, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 2, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 3, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 4, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 5, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 6, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 7, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 8, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 9, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 0, 0, 7, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 7, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 8, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 8, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 7, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 8, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 5, 10, 0, 0, 1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 2, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 3, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 4, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 5, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 6, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 7, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 8, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 9, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 2, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 3, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 4, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 5, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 6, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 7, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 8, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, 9, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 26, 10, 0, 0, -1, 1, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 2, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -2, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 1, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1316, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 6, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 6, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 10, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 10, 4, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 54 },
+ { 21, 10, 0, 0, -1, 3, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, 1, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 21, 10, 0, 0, -1, -1, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -3, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 26, 10, 0, 0, -1, -1914, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1918, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1923, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -1824, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -2016, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, 0, 6, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, -2104, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -2106, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -2108, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 26, 10, 0, 0, -1, -2250, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 10, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, -2527, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 48}, {0, 0}, {0, 0}, {0, 48} }, 0, 10, 14, 7, 3, 57 },
+ { 14, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 48}, {0, 0}, {0, 0}, {0, 48} }, 0, 10, 14, 7, 3, 57 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, -48}, {0, -48}, {0, 0} }, 0, 10, 14, 6, 1, 57 },
+ { 15, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, -48}, {0, -48}, {0, 0} }, 0, 10, 14, 6, 1, 57 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {1, 211}, {0, 0}, {0, 0}, {1, 211} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {0, -3814}, {0, 0}, {0, 0}, {0, -3814} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 0, { {1, 213}, {0, 0}, {0, 0}, {1, 213} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {1, 215}, {1, 215}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {1, 217}, {1, 217}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {1, 219}, {0, 0}, {0, 0}, {1, 219} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {1, 221}, {0, 0}, {0, 0}, {1, 221} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {1, 223}, {0, 0}, {0, 0}, {1, 223} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 11, 3, 0, { {1, 225}, {0, 0}, {0, 0}, {1, 225} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 10, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 11, 3, 0, { {1, 227}, {0, 0}, {0, 0}, {1, 227} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 11, 3, 0, { {1, 229}, {0, 0}, {0, 0}, {1, 229} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 46 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 46 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 46 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 46 },
+ { 14, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 46 },
+ { 15, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 46 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 46 },
+ { 14, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 46 },
+ { 15, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 46 },
+ { 25, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 46 },
+ { 25, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 46 },
+ { 5, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 46 },
+ { 15, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, -7264}, {0, -7264}, {0, 0} }, 0, 10, 14, 6, 1, 25 },
+ { 15, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, -7264}, {0, -7264}, {0, 0} }, 0, 10, 14, 6, 1, 25 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 58 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 58 },
+ { 17, 0, 0, 0, -1, 0, 8, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 58 },
+ { 25, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 58 },
+ { 0, 17, 9, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 58 },
+ { 25, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 23, 10, 0, 0, -1, 1, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 24, 10, 0, 0, -1, -1, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 23, 10, 0, 0, -1, 1, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 24, 10, 0, 0, -1, -1, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 2 },
+ { 17, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 21, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 2 },
+ { 21, 10, 0, 0, -1, 1, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 37 },
+ { 29, 10, 0, 0, -1, 0, 4, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 37 },
+ { 29, 10, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 29, 10, 0, 0, -1, 0, 26, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 6, 9, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 18, 19, 5, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 11, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 12, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 2 },
+ { 4, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 21, 10, 0, 0, -1, 1, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 1, 2 },
+ { 22, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 0, 17, 218, 5, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 228, 5, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 232, 5, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 222, 5, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 1, 0, 224, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 26 },
+ { 20, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 23, 8, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 4, 0, 0, 0, -1, 0, 4, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 17, 0, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 8, 1, 34 },
+ { 0, 17, 8, 5, -1, 0, 1, 5, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 28, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 0, 0, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 8, 1, 34 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 6, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 34 },
+ { 20, 10, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 0, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 1, 35 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 35 },
+ { 17, 0, 0, 0, -1, 0, 1, 5, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 6, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 3, 35 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 18, 0, 0, 0, -1, 0, 10, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 18, 0, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 18, 0, 0, 0, -1, 0, 20, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 3, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 0, 26 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 5, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 18, 0, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 18, 0, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 18, 0, 0, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 36 },
+ { 29, 10, 0, 0, -1, 0, 8, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 10, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 35 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 26 },
+ { 29, 10, 0, 0, -1, 0, 7, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 26 },
+ { 5, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 5, 0, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 7, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 5, 10, 0, 0, -1, 0, 6, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 26 },
+ { 29, 10, 0, 0, -1, 0, 7, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 26 },
+ { 29, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 26 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 0, 3, 35 },
+ { 29, 0, 0, 0, -1, 0, 22, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 18, 0, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 8, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 10, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 11, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 13, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 17, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 20, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 24, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 1, 38 },
+ { 17, 0, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 38 },
+ { 29, 10, 0, 0, -1, 0, 4, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 38 },
+ { 29, 10, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 38 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 83 },
+ { 17, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 83 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 83 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 83 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 70 },
+ { 17, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 70 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 70 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 70 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 70 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 70 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 5 },
+ { 2, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 25, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 5 },
+ { 0, 17, 230, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 17, 10, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 5 },
+ { 17, 0, 0, 0, -1, 0, 16, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 5 },
+ { 0, 17, 230, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 84 },
+ { 4, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 84 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 84 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 84 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 84 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 84 },
+ { 28, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 17, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 14, 0, 0, 0, -1, 0, 10, 3, 0, { {1, 231}, {0, 0}, {0, 0}, {1, 231} }, 0, 10, 14, 7, 3, 3 },
+ { 28, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 14, 0, 0, 0, -1, 0, 12, 3, 0, { {1, 233}, {0, 0}, {0, 0}, {1, 233} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 48}, {0, 48}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 13, 3, 0, { {1, 235}, {0, 0}, {0, 0}, {1, 235} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {1, 237}, {0, 0}, {0, 0}, {1, 237} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {1, 239}, {0, 0}, {0, 0}, {1, 239} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {1, 241}, {0, 0}, {0, 0}, {1, 241} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 18, 3, 0, { {1, 243}, {0, 0}, {0, 0}, {1, 243} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {1, 245}, {0, 0}, {0, 0}, {1, 245} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {1, 247}, {0, 0}, {0, 0}, {1, 247} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 17, 3, 0, { {1, 249}, {0, 0}, {0, 0}, {1, 249} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 928}, {0, 0}, {0, 0}, {0, 928} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 14, 0, 0, 0, -1, 0, 21, 3, 0, { {0, -48}, {0, 0}, {0, 0}, {0, -48} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 21, 3, 0, { {1, 251}, {0, 0}, {0, 0}, {1, 251} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 21, 3, 0, { {1, 253}, {0, 0}, {0, 0}, {1, 253} }, 0, 10, 14, 7, 3, 3 },
+ { 14, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 1}, {0, 0}, {0, 0}, {0, 1} }, 0, 10, 14, 7, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, -1}, {0, -1}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 24, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 13, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 59 },
+ { 0, 17, 0, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 59 },
+ { 0, 17, 9, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 59 },
+ { 1, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 59 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 59 },
+ { 0, 17, 9, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 59 },
+ { 5, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 4, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 18, 0, 0, 2, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 65 },
+ { 18, 0, 0, 4, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 65 },
+ { 18, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 65 },
+ { 25, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 65 },
+ { 25, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 1, 65 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 71 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 71 },
+ { 0, 17, 9, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 71 },
+ { 0, 17, 0, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 71 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 71 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 71 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 11 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 11 },
+ { 0, 17, 0, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 11 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 72 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 72 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 72 },
+ { 0, 17, 220, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 72 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 72 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 73 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 73 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 73 },
+ { 1, 0, 9, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 73 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 73 },
+ { 0, 17, 0, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 85 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 85 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 85 },
+ { 0, 17, 7, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 85 },
+ { 1, 0, 9, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 85 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 85 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 85 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 85 },
+ { 17, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 19, 8, 1, 2 },
+ { 3, 0, 0, 0, 0, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 2, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 3, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 4, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 5, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 6, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 7, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 8, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 3, 0, 0, 0, 9, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 85 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 24 },
+ { 17, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 24 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 77 },
+ { 0, 17, 0, 5, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 77 },
+ { 1, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 77 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 19, 8, 1, 77 },
+ { 3, 0, 0, 0, 0, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 2, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 3, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 4, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 5, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 6, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 7, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 8, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 3, 0, 0, 0, 9, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 77 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 77 },
+ { 25, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 77 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 17, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 24 },
+ { 29, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 24 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 35, 4, 1, 24 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 79 },
+ { 0, 17, 230, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 79 },
+ { 0, 17, 220, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 79 },
+ { 17, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 79 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 79 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 86 },
+ { 1, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 86 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 86 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 86 },
+ { 17, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 86 },
+ { 0, 17, 9, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 86 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 27 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, -928}, {0, -928}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 28, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 0, 1, 2 },
+ { 17, 0, 0, 0, -1, 0, 16, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 4 },
+ { 15, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 28, 10, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 255}, {1, 255}, {1, 255} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 257}, {1, 257}, {1, 257} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 259}, {1, 259}, {1, 259} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 261}, {1, 261}, {1, 261} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 263}, {1, 263}, {1, 263} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 265}, {1, 265}, {1, 265} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 267}, {1, 267}, {1, 267} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 269}, {1, 269}, {1, 269} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 271}, {1, 271}, {1, 271} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 273}, {1, 273}, {1, 273} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 275}, {1, 275}, {1, 275} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 277}, {1, 277}, {1, 277} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 279}, {1, 279}, {1, 279} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 281}, {1, 281}, {1, 281} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 283}, {1, 283}, {1, 283} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 285}, {1, 285}, {1, 285} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 287}, {1, 287}, {1, 287} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 289}, {1, 289}, {1, 289} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 291}, {1, 291}, {1, 291} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 293}, {1, 293}, {1, 293} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 295}, {1, 295}, {1, 295} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 297}, {1, 297}, {1, 297} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 299}, {1, 299}, {1, 299} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 301}, {1, 301}, {1, 301} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 303}, {1, 303}, {1, 303} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 305}, {1, 305}, {1, 305} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 307}, {1, 307}, {1, 307} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 309}, {1, 309}, {1, 309} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 311}, {1, 311}, {1, 311} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 313}, {1, 313}, {1, 313} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 315}, {1, 315}, {1, 315} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 317}, {1, 317}, {1, 317} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 319}, {1, 319}, {1, 319} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 321}, {1, 321}, {1, 321} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 323}, {1, 323}, {1, 323} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 325}, {1, 325}, {1, 325} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 327}, {1, 327}, {1, 327} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 329}, {1, 329}, {1, 329} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 331}, {1, 331}, {1, 331} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 333}, {1, 333}, {1, 333} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 335}, {1, 335}, {1, 335} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 337}, {1, 337}, {1, 337} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 339}, {1, 339}, {1, 339} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 341}, {1, 341}, {1, 341} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 343}, {1, 343}, {1, 343} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 345}, {1, 345}, {1, 345} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 347}, {1, 347}, {1, 347} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 349}, {1, 349}, {1, 349} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 351}, {1, 351}, {1, 351} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 353}, {1, 353}, {1, 353} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 355}, {1, 355}, {1, 355} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 357}, {1, 357}, {1, 357} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 359}, {1, 359}, {1, 359} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 361}, {1, 361}, {1, 361} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 363}, {1, 363}, {1, 363} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 365}, {1, 365}, {1, 365} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 367}, {1, 367}, {1, 367} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 369}, {1, 369}, {1, 369} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 371}, {1, 371}, {1, 371} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 373}, {1, 373}, {1, 373} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 375}, {1, 375}, {1, 375} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 377}, {1, 377}, {1, 377} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 379}, {1, 379}, {1, 379} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 381}, {1, 381}, {1, 381} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 383}, {1, 383}, {1, 383} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 385}, {1, 385}, {1, 385} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 387}, {1, 387}, {1, 387} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 389}, {1, 389}, {1, 389} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 391}, {1, 391}, {1, 391} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 393}, {1, 393}, {1, 393} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 395}, {1, 395}, {1, 395} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 397}, {1, 397}, {1, 397} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 399}, {1, 399}, {1, 399} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 401}, {1, 401}, {1, 401} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 403}, {1, 403}, {1, 403} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 405}, {1, 405}, {1, 405} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 407}, {1, 407}, {1, 407} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 409}, {1, 409}, {1, 409} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 411}, {1, 411}, {1, 411} }, 0, 10, 14, 6, 3, 28 },
+ { 15, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {1, 413}, {1, 413}, {1, 413} }, 0, 10, 14, 6, 3, 28 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 86 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 86 },
+ { 0, 17, 0, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 86 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 86 },
+ { 0, 17, 9, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 86 },
+ { 3, 0, 0, 0, 0, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 2, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 3, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 4, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 5, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 6, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 7, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 8, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 3, 0, 0, 0, 9, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 86 },
+ { 18, 0, 0, 0, -1, 0, 2, 5, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 12, 10, 25, 8, 1, 26 },
+ { 18, 0, 0, 0, -1, 0, 2, 5, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 13, 10, 26, 8, 1, 26 },
+ { 11, 0, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 36, 0, 0, 0 },
+ { 12, 0, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 18, 0, 0, 0, -1, 0, 1, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 18, 0, 0, 0, -1, 0, 13, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 18, 0, 0, 0, -1, 0, 6, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 18, 0, 0, 0, -1, 0, 11, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 13, 0, 0, 0, -1, 0, 0, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 0 },
+ { 18, 0, 0, 0, -1, 0, 8, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 427}, {1, 424}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 433}, {1, 430}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 439}, {1, 436}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 446}, {1, 442}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 454}, {1, 450}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 461}, {1, 458}, {0, 1} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 461}, {1, 458}, {0, 0} }, 0, 10, 14, 6, 3, 3 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 473}, {1, 470}, {0, 0} }, 0, 10, 14, 6, 3, 6 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 479}, {1, 476}, {0, 0} }, 0, 10, 14, 6, 3, 6 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 485}, {1, 482}, {0, 0} }, 0, 10, 14, 6, 3, 6 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 491}, {1, 488}, {0, 0} }, 0, 10, 14, 6, 3, 6 },
+ { 15, 0, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {1, 497}, {1, 494}, {0, 0} }, 0, 10, 14, 6, 3, 6 },
+ { 18, 1, 0, 0, -1, 0, 4, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 15, 8, 3, 7 },
+ { 0, 17, 26, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 7 },
+ { 18, 1, 0, 0, -1, 0, 1, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 15, 8, 3, 7 },
+ { 18, 1, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 9, 15, 8, 3, 7 },
+ { 26, 3, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 7 },
+ { 18, 13, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 8 },
+ { 28, 13, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 18, 13, 0, 0, -1, 0, 1, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 0, 8 },
+ { 22, 10, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 13, 18, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 27, 13, 0, 0, -1, 0, 6, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 8 },
+ { 0, 17, 0, 5, -1, 0, 6, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 2, 1 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 11, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 11, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 10, 11, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 10, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 0, 2 },
+ { 21, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 3, 2 },
+ { 22, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 8, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 20, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 11, 3, 2 },
+ { 19, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 16, 0, 3, 2 },
+ { 21, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 21, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 3, 2 },
+ { 22, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 6, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 21, 10, 0, 0, -1, 0, 7, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, 0, 7, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 1, 11, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 11, 3, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 1, 10, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 7, 0, 0, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 7, 11, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 0, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 3, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 3, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 26, 3, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 20, 3, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 11, 3, 2 },
+ { 26, 10, 0, 0, -1, 1, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, -1, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 0, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0, 2 },
+ { 18, 13, 0, 0, -1, 0, 6, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 8 },
+ { 10, 18, 0, 5, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 24, 4, 2, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 12, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 0, 2 },
+ { 25, 4, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 16, 0, 0, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 26, 3, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 1, 11, 0, 2 },
+ { 20, 3, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 11, 3, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 13, 1, 10, 3, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 3, 2, 0, 0, 0, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 2, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 3, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 4, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 5, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 6, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 7, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 8, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 3, 2, 0, 0, 9, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 3, 2 },
+ { 25, 6, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 14, 7, 11, 0, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 15, 7, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, 2, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 26, 10, 0, 0, -1, -2, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 14, 0, 0, 0, -1, 0, 1, 1, 80, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 16, 7, 3, 3 },
+ { 21, 10, 0, 0, -1, 2, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 0, 2 },
+ { 22, 10, 0, 0, -1, -2, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 0, 2 },
+ { 28, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 0, 2 },
+ { 19, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 17, 16, 0, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 16, 6, 3, 3 },
+ { 21, 10, 0, 0, -1, 1, 6, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 3, 2 },
+ { 22, 10, 0, 0, -1, -1, 6, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 12, 3, 2 },
+ { 21, 10, 0, 0, -1, 1, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 13, 3, 2 },
+ { 22, 10, 0, 0, -1, -1, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 13, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 1, 11, 3, 2 },
+ { 25, 10, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 3, 2 },
+ { 18, 0, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 3, 35 },
+ { 18, 0, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 3, 35 },
+ { 17, 0, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 3, 2 },
+ { 17, 0, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 7, 4, 3, 2 },
+ { 18, 0, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 0, 26 },
+ { 18, 0, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 16, 8, 3, 26 },
+ { 27, 4, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 3, 2 },
+ { 27, 4, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 1, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 1, 2, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 10, 10, 0, 5, -1, 0, 4, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 29, 10, 0, 0, -1, 0, 3, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 31, 0, 0, 2 },
+ { 29, 10, 0, 0, -1, 0, 1, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 13, 18, 0, 0, -1, 0, 1, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 49 },
+ { 25, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 25, 10, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 2 },
+ { 5, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 4, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 4 },
+ { 5, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 29, 10, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 5, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 29, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 4 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 74 },
+ { 18, 0, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 75 },
+ { 5, 2, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 18, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 39 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 39 },
+ { 5, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 39 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 39 },
+ { 18, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 40 },
+ { 4, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 40 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 120 },
+ { 0, 17, 230, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 120 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 50 },
+ { 25, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 50 },
+ { 18, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 60 },
+ { 25, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 60 },
+ { 4, 0, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 60 },
+ { 14, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 40}, {0, 0}, {0, 0}, {0, 40} }, 0, 10, 14, 7, 3, 41 },
+ { 14, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 40}, {0, 0}, {0, 0}, {0, 40} }, 0, 10, 14, 7, 3, 41 },
+ { 15, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, -40}, {0, -40}, {0, 0} }, 0, 10, 14, 6, 1, 41 },
+ { 15, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, -40}, {0, -40}, {0, 0} }, 0, 10, 14, 6, 1, 41 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 51 },
+ { 18, 0, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 52 },
+ { 3, 0, 0, 0, 0, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 2, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 3, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 4, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 5, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 6, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 7, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 8, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 3, 0, 0, 0, 9, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 52 },
+ { 14, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 40}, {0, 0}, {0, 0}, {0, 40} }, 0, 10, 14, 7, 3, 136 },
+ { 15, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, -40}, {0, -40}, {0, 0} }, 0, 10, 14, 6, 1, 136 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 106 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 103 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 103 },
+ { 14, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 39}, {0, 0}, {0, 0}, {0, 39} }, 0, 10, 14, 7, 3, 161 },
+ { 15, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, -39}, {0, -39}, {0, 0} }, 0, 10, 14, 6, 1, 161 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 110 },
+ { 17, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 17, 0, 0, 0, -1, 0, 24, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 3 },
+ { 18, 1, 0, 0, -1, 0, 7, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 53 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 87 },
+ { 25, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 87 },
+ { 5, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 87 },
+ { 18, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 118 },
+ { 29, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 118 },
+ { 5, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 118 },
+ { 18, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 117 },
+ { 5, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 117 },
+ { 18, 1, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 128 },
+ { 5, 1, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 128 },
+ { 18, 1, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 64 },
+ { 5, 1, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 64 },
+ { 5, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 64 },
+ { 25, 10, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 64 },
+ { 18, 1, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 76 },
+ { 25, 1, 0, 0, -1, 0, 10, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 76 },
+ { 18, 1, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 98 },
+ { 18, 1, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 97 },
+ { 5, 1, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 97 },
+ { 18, 1, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 61 },
+ { 0, 17, 0, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 61 },
+ { 0, 17, 220, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 61 },
+ { 0, 17, 230, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 61 },
+ { 18, 1, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 61 },
+ { 0, 17, 1, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 61 },
+ { 0, 17, 9, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 61 },
+ { 5, 1, 0, 0, 1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 5, 1, 0, 0, 2, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 5, 1, 0, 0, 3, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 5, 1, 0, 0, 4, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 5, 1, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 5, 1, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 25, 1, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 61 },
+ { 25, 1, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 61 },
+ { 25, 1, 0, 0, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 61 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 88 },
+ { 5, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 88 },
+ { 25, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 88 },
+ { 18, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 116 },
+ { 5, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 116 },
+ { 18, 1, 0, 2, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 112 },
+ { 18, 1, 0, 3, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 112 },
+ { 18, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 112 },
+ { 29, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 112 },
+ { 18, 1, 0, 4, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 112 },
+ { 0, 17, 230, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 112 },
+ { 0, 17, 220, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 112 },
+ { 5, 1, 0, 2, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 112 },
+ { 5, 1, 0, 3, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 112 },
+ { 25, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 112 },
+ { 25, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 17, 0, 1, 112 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 80 },
+ { 25, 10, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 80 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 89 },
+ { 5, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 89 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 90 },
+ { 5, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 90 },
+ { 18, 1, 0, 2, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 121 },
+ { 18, 1, 0, 3, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 121 },
+ { 25, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 121 },
+ { 5, 1, 0, 3, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 121 },
+ { 5, 1, 0, 2, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 121 },
+ { 5, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 121 },
+ { 18, 1, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 91 },
+ { 14, 1, 0, 0, -1, 0, 17, 3, 0, { {0, 64}, {0, 0}, {0, 0}, {0, 64} }, 0, 10, 14, 7, 3, 130 },
+ { 15, 1, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, -64}, {0, -64}, {0, 0} }, 0, 10, 14, 6, 1, 130 },
+ { 5, 1, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 130 },
+ { 18, 13, 0, 4, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 144 },
+ { 18, 13, 0, 2, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 144 },
+ { 18, 13, 0, 3, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 144 },
+ { 0, 17, 230, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 144 },
+ { 3, 5, 0, 0, 0, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 2, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 3, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 4, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 5, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 6, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 7, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 8, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 3, 5, 0, 0, 9, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 144 },
+ { 5, 5, 0, 0, 1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 2, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 3, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 4, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 5, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 6, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 7, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 8, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, 9, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 5, 5, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 18, 1, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 156 },
+ { 0, 17, 230, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 156 },
+ { 20, 1, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 156 },
+ { 0, 17, 220, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 8 },
+ { 18, 1, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 147 },
+ { 5, 1, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 147 },
+ { 18, 13, 0, 2, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 148 },
+ { 18, 13, 0, 3, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 148 },
+ { 18, 13, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 148 },
+ { 0, 17, 220, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 148 },
+ { 0, 17, 230, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 148 },
+ { 5, 13, 0, 2, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 148 },
+ { 5, 13, 0, 3, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 148 },
+ { 25, 13, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 148 },
+ { 18, 1, 0, 2, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 158 },
+ { 18, 1, 0, 3, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 158 },
+ { 0, 17, 230, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 158 },
+ { 0, 17, 220, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 158 },
+ { 25, 1, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 158 },
+ { 18, 1, 0, 2, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 153 },
+ { 18, 1, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 153 },
+ { 18, 1, 0, 3, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 153 },
+ { 5, 1, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 153 },
+ { 5, 1, 0, 3, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 153 },
+ { 5, 1, 0, 2, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 153 },
+ { 5, 1, 0, 4, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 153 },
+ { 18, 1, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 149 },
+ { 1, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 94 },
+ { 0, 17, 0, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 94 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 94 },
+ { 0, 17, 9, 5, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 94 },
+ { 25, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 94 },
+ { 25, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 2, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 3, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 4, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 5, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 6, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 7, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 8, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, 9, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 5, 10, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 94 },
+ { 3, 0, 0, 0, 0, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 2, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 3, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 4, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 5, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 6, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 7, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 8, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 3, 0, 0, 0, 9, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 94 },
+ { 0, 17, 9, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 94 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 94 },
+ { 0, 17, 0, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 94 },
+ { 0, 17, 9, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 94 },
+ { 0, 17, 0, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 92 },
+ { 1, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 92 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 92 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 92 },
+ { 0, 17, 9, 5, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 92 },
+ { 0, 17, 7, 5, -1, 0, 11, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 92 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 92 },
+ { 10, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 92 },
+ { 25, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 92 },
+ { 0, 17, 0, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 92 },
+ { 10, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 16, 13, 9, 0, 92 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 101 },
+ { 3, 0, 0, 0, 0, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 2, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 3, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 4, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 5, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 6, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 7, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 8, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 3, 0, 0, 0, 9, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 101 },
+ { 0, 17, 230, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 96 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 96 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 96 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 96 },
+ { 1, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 96 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 96 },
+ { 0, 17, 9, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 96 },
+ { 3, 0, 0, 0, 0, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 2, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 3, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 4, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 5, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 6, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 7, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 8, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 3, 0, 0, 0, 9, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 96 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 96 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 96 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 96 },
+ { 1, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 96 },
+ { 18, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 96 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 111 },
+ { 0, 17, 7, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 111 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 111 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 111 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 100 },
+ { 1, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 100 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 100 },
+ { 1, 0, 9, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 100 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 100 },
+ { 0, 17, 0, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 100 },
+ { 0, 17, 7, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 12, 1, 100 },
+ { 1, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 100 },
+ { 0, 17, 0, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 100 },
+ { 3, 0, 0, 0, 0, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 2, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 3, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 4, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 5, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 6, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 7, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 8, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 3, 0, 0, 0, 9, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 100 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 100 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 100 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 100 },
+ { 5, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 20 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 109 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 109 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 109 },
+ { 1, 0, 9, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 109 },
+ { 0, 17, 7, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 109 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 109 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 109 },
+ { 0, 17, 0, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 109 },
+ { 18, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 109 },
+ { 0, 17, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 109 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 129 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 129 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 123 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 123 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 123 },
+ { 0, 17, 7, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 123 },
+ { 0, 17, 9, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 123 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 123 },
+ { 0, 17, 0, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 107 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 107 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 107 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 107 },
+ { 0, 17, 7, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 7, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 107 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 19, 8, 1, 107 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 107 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 107 },
+ { 1, 0, 9, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 107 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 107 },
+ { 0, 17, 230, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 107 },
+ { 18, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 135 },
+ { 1, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 135 },
+ { 0, 17, 0, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 135 },
+ { 0, 17, 9, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 135 },
+ { 0, 17, 7, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 135 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 135 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 135 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 135 },
+ { 3, 0, 0, 0, 0, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 2, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 3, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 4, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 5, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 6, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 7, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 8, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 3, 0, 0, 0, 9, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 135 },
+ { 25, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 135 },
+ { 0, 17, 230, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 135 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 135 },
+ { 18, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 135 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 124 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 124 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 124 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 124 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 124 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 124 },
+ { 0, 17, 9, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 124 },
+ { 0, 17, 7, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 124 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 124 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 124 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 122 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 122 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 122 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 122 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 122 },
+ { 0, 17, 9, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 122 },
+ { 0, 17, 7, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 122 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 122 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 122 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 122 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 122 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 122 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 122 },
+ { 0, 17, 0, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 122 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 114 },
+ { 1, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 114 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 114 },
+ { 0, 17, 9, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 114 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 114 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 114 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 114 },
+ { 25, 10, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 33 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 102 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 102 },
+ { 1, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 102 },
+ { 1, 0, 9, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 102 },
+ { 0, 17, 7, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 102 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 102 },
+ { 25, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 102 },
+ { 3, 0, 0, 0, 0, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 2, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 3, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 4, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 5, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 6, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 7, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 8, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 3, 0, 0, 0, 9, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 102 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 126 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 126 },
+ { 0, 17, 0, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 126 },
+ { 1, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 4, 35, 4, 1, 126 },
+ { 1, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 35, 4, 1, 126 },
+ { 0, 17, 9, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 35, 4, 1, 126 },
+ { 3, 0, 0, 0, 0, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 2, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 3, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 4, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 5, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 6, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 7, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 8, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 3, 0, 0, 0, 9, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 126 },
+ { 5, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 126 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 126 },
+ { 29, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 0, 1, 126 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 35, 8, 1, 126 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 142 },
+ { 1, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 142 },
+ { 0, 17, 0, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 142 },
+ { 0, 17, 9, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 142 },
+ { 0, 17, 7, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 142 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 142 },
+ { 14, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 125 },
+ { 15, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 125 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 125 },
+ { 5, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 125 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 125 },
+ { 18, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 154 },
+ { 1, 0, 0, 0, -1, 0, 23, 3, 204, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 154 },
+ { 1, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 154 },
+ { 1, 0, 0, 0, -1, 0, 23, 3, 17, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 154 },
+ { 0, 17, 0, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 154 },
+ { 1, 0, 9, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 154 },
+ { 0, 17, 9, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 154 },
+ { 18, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 154 },
+ { 0, 17, 7, 5, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 154 },
+ { 25, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 154 },
+ { 25, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 154 },
+ { 3, 0, 0, 0, 0, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 2, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 3, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 4, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 5, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 6, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 7, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 8, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 3, 0, 0, 0, 9, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 16, 9, 1, 154 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 150 },
+ { 1, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 150 },
+ { 0, 17, 0, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 150 },
+ { 0, 17, 9, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 150 },
+ { 25, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 150 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 141 },
+ { 0, 17, 0, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 141 },
+ { 0, 0, 0, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 141 },
+ { 0, 17, 9, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 141 },
+ { 1, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 141 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 141 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 141 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 141 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 141 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 141 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 140 },
+ { 0, 17, 0, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 140 },
+ { 1, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 140 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 140 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 140 },
+ { 0, 17, 9, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 140 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 140 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 140 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 140 },
+ { 25, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 140 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 29 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 119 },
+ { 25, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 11 },
+ { 18, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 133 },
+ { 1, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 133 },
+ { 0, 17, 0, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 133 },
+ { 0, 0, 9, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 133 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 133 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 133 },
+ { 3, 0, 0, 0, 0, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 2, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 3, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 4, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 5, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 6, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 7, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 8, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 3, 0, 0, 0, 9, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 133 },
+ { 5, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 133 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 20, 0, 1, 134 },
+ { 25, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 8, 0, 1, 134 },
+ { 18, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 134 },
+ { 0, 17, 0, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 134 },
+ { 1, 0, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 134 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 138 },
+ { 0, 17, 0, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 138 },
+ { 0, 17, 7, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 138 },
+ { 0, 17, 9, 5, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 138 },
+ { 18, 0, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 138 },
+ { 3, 0, 0, 0, 0, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 2, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 3, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 4, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 5, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 6, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 7, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 8, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 3, 0, 0, 0, 9, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 138 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 143 },
+ { 1, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 143 },
+ { 0, 17, 0, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 143 },
+ { 0, 17, 9, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 143 },
+ { 3, 0, 0, 0, 0, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 2, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 3, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 4, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 5, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 6, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 7, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 8, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 3, 0, 0, 0, 9, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 143 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 145 },
+ { 18, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 19, 8, 1, 145 },
+ { 0, 17, 0, 5, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 145 },
+ { 1, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 145 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 145 },
+ { 0, 17, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 162 },
+ { 18, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 7, 10, 14, 8, 1, 162 },
+ { 1, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 162 },
+ { 18, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 162 },
+ { 1, 0, 9, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 162 },
+ { 0, 17, 9, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 162 },
+ { 25, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 162 },
+ { 25, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 162 },
+ { 3, 0, 0, 0, 0, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 2, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 3, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 4, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 5, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 6, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 7, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 8, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 3, 0, 0, 0, 9, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 14, 9, 1, 162 },
+ { 18, 0, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 83 },
+ { 5, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 16 },
+ { 29, 10, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 16 },
+ { 27, 4, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 16 },
+ { 25, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 16 },
+ { 18, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 63 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 63 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 63 },
+ { 4, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 63 },
+ { 4, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 63 },
+ { 25, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 63 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 63 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 157 },
+ { 25, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 157 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 81 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 0, 8, 1, 81 },
+ { 18, 0, 0, 0, -1, 0, 11, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 1, 8, 1, 81 },
+ { 18, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 0, 8, 1, 81 },
+ { 10, 0, 0, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 6, 4, 0, 81 },
+ { 10, 0, 0, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 0, 4, 0, 81 },
+ { 10, 0, 0, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 1, 4, 0, 81 },
+ { 10, 0, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 6, 4, 0, 81 },
+ { 10, 0, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 0, 4, 0, 81 },
+ { 10, 0, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 1, 4, 0, 81 },
+ { 0, 17, 0, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 81 },
+ { 18, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 81 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 127 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 0, 8, 1, 127 },
+ { 18, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 1, 8, 1, 127 },
+ { 18, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 84 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 115 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 115 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 115 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 159 },
+ { 3, 0, 0, 0, 0, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 2, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 3, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 4, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 5, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 6, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 7, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 8, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 3, 0, 0, 0, 9, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 159 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 104 },
+ { 0, 17, 1, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 104 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 104 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 108 },
+ { 0, 17, 230, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 108 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 108 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 108 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 108 },
+ { 29, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 108 },
+ { 17, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 108 },
+ { 3, 0, 0, 0, 0, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 2, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 3, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 4, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 5, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 6, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 7, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 8, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 3, 0, 0, 0, 9, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 108 },
+ { 5, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 108 },
+ { 14, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 32}, {0, 0}, {0, 0}, {0, 32} }, 0, 10, 14, 7, 3, 146 },
+ { 15, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, -32}, {0, -32}, {0, 0} }, 0, 10, 14, 6, 1, 146 },
+ { 5, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 146 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 146 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 146 },
+ { 25, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 146 },
+ { 18, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 99 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 99 },
+ { 0, 17, 0, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 99 },
+ { 1, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 99 },
+ { 1, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 99 },
+ { 0, 17, 0, 5, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 99 },
+ { 17, 0, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 99 },
+ { 17, 0, 0, 0, -1, 0, 18, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 137 },
+ { 17, 0, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 139 },
+ { 25, 10, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 1, 37 },
+ { 17, 0, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 7, 8, 1, 37 },
+ { 0, 17, 0, 5, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 6, 4, 1, 155 },
+ { 1, 0, 6, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 18, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 137 },
+ { 18, 0, 0, 0, -1, 0, 20, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 137 },
+ { 18, 0, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 137 },
+ { 18, 0, 0, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 137 },
+ { 18, 0, 0, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 8, 1, 155 },
+ { 17, 0, 0, 0, -1, 0, 24, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 14, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 24, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 24, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 16, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 25, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 8, 1, 34 },
+ { 18, 0, 0, 0, -1, 0, 25, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 8, 7, 8, 1, 35 },
+ { 18, 0, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 139 },
+ { 18, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 105 },
+ { 29, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 105 },
+ { 0, 17, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 105 },
+ { 0, 17, 1, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 105 },
+ { 25, 0, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 105 },
+ { 10, 18, 0, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 2, 2 },
+ { 0, 17, 0, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 29, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 5, 3, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 1, 0, 216, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 2 },
+ { 1, 0, 216, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 2 },
+ { 0, 17, 1, 5, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 1, 0, 226, 0, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 8, 4, 23, 4, 1, 2 },
+ { 10, 18, 0, 5, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 3, 6, 23, 4, 0, 2 },
+ { 0, 17, 220, 5, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 0, 17, 230, 5, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 1 },
+ { 29, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 0, 17, 230, 5, -1, 0, 8, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 4 },
+ { 5, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 0, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 5, 0, 0, 0, -1, 0, 9, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 14, 0, 0, 0, -1, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 7, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 26, 0, 0, 0, -1, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 26, 10, 0, 0, -1, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 14, 0, 0, 0, -1, 0, 9, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 2 },
+ { 15, 0, 0, 0, -1, 0, 9, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 2 },
+ { 3, 2, 0, 0, 0, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 1, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 2, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 3, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 4, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 5, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 6, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 7, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 8, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 9, 0, 5, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 131 },
+ { 0, 17, 0, 5, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 131 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 0, 1, 131 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 19, 12, 1, 131 },
+ { 25, 0, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 131 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 3 },
+ { 15, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 1, 3 },
+ { 0, 17, 230, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 57 },
+ { 17, 0, 0, 0, -1, 0, 25, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 6, 3, 5 },
+ { 0, 17, 230, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 5 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 151 },
+ { 0, 17, 230, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 151 },
+ { 17, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 151 },
+ { 3, 0, 0, 0, 0, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 2, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 3, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 4, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 5, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 6, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 7, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 8, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 3, 0, 0, 0, 9, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 151 },
+ { 29, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 151 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 160 },
+ { 0, 17, 230, 5, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 160 },
+ { 18, 0, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 152 },
+ { 0, 17, 230, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 152 },
+ { 3, 0, 0, 0, 0, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 2, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 3, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 4, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 5, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 6, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 7, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 8, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 3, 0, 0, 0, 9, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 152 },
+ { 27, 4, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 11, 0, 1, 152 },
+ { 18, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 163 },
+ { 17, 0, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 163 },
+ { 0, 17, 232, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 163 },
+ { 0, 17, 220, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 163 },
+ { 0, 17, 230, 5, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 163 },
+ { 3, 0, 0, 0, 0, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 2, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 3, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 4, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 5, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 6, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 7, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 8, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 3, 0, 0, 0, 9, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 163 },
+ { 18, 0, 0, 0, -1, 0, 24, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 27 },
+ { 18, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 113 },
+ { 5, 1, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 113 },
+ { 0, 17, 220, 5, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 113 },
+ { 14, 1, 0, 2, -1, 0, 18, 3, 0, { {0, 34}, {0, 0}, {0, 0}, {0, 34} }, 0, 10, 14, 7, 3, 132 },
+ { 15, 1, 0, 2, -1, 0, 18, 3, 0, { {0, 0}, {0, -34}, {0, -34}, {0, 0} }, 0, 10, 14, 6, 1, 132 },
+ { 0, 17, 230, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 132 },
+ { 0, 17, 7, 5, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 1, 132 },
+ { 17, 1, 0, 5, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 1, 132 },
+ { 3, 1, 0, 0, 0, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 2, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 3, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 4, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 5, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 6, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 7, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 8, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 3, 1, 0, 0, 9, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 1, 132 },
+ { 25, 1, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 0, 0, 1, 132 },
+ { 5, 13, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 13, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 27, 13, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 12, 0, 1, 2 },
+ { 5, 13, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 13, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 18, 13, 0, 0, -1, 0, 13, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 8, 3, 8 },
+ { 26, 10, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 8 },
+ { 29, 10, 0, 0, -1, 0, 10, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 13, 0, 0, 0, -1, 0, 0, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 0, 0 },
+ { 5, 2, 0, 0, 0, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 1, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 2, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 3, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 4, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 5, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 6, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 7, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 8, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 2, 0, 0, 9, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 5, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 23, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 0, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 10, 14, 7, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 13, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 21, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 10, 14, 7, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 10, 14, 7, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 18, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 6, 7, 30, 0, 1, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 34 },
+ { 29, 0, 0, 0, -1, 0, 12, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 11, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 3, 2 },
+ { 29, 0, 0, 0, -1, 0, 18, 5, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 3, 2 },
+ { 29, 10, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 17, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 28, 10, 0, 0, -1, 0, 17, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 33, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 13, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 17, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 18, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 18, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 13, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 3, 13, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 16, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 7, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 19, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 25, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 24, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 20, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 12, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 25, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 20, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 23, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 21, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 17, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 19, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 18, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 20, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 21, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 14, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 24, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 29, 10, 0, 0, -1, 0, 25, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 14, 0, 32, 0, 1, 2 },
+ { 3, 2, 0, 0, 0, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 1, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 2, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 3, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 4, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 5, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 6, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 7, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 8, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 3, 2, 0, 0, 9, 0, 23, 3, 80, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 16, 13, 9, 3, 2 },
+ { 13, 18, 0, 0, -1, 0, 2, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 },
+ { 18, 0, 0, 0, -1, 0, 5, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 25, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 12, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 26, 5, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 1, 37 },
+ { 18, 0, 0, 0, -1, 0, 5, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 3, 37 },
+ { 18, 0, 0, 0, -1, 0, 5, 5, 85, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 16, 8, 0, 37 },
+ { 10, 18, 0, 5, -1, 0, 5, 3, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 0, 2 },
+ { 0, 17, 0, 5, -1, 0, 7, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 4, 4, 23, 4, 2, 1 },
+ { 12, 0, 0, 0, -1, 0, 2, 0, 0, { {0, 0}, {0, 0}, {0, 0}, {0, 0} }, 0, 0, 14, 0, 0, 0 }
};
Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char32_t ucs4) noexcept
{
- return uc_properties + GET_PROP_INDEX(ucs4);
+ Q_ASSERT(ucs4 <= QChar::LastValidCodePoint);
+ if (ucs4 < 0x11000)
+ return uc_properties + uc_property_trie[uc_property_trie[ucs4 >> 5] + (ucs4 & 0x1f)];
+
+ return uc_properties
+ + uc_property_trie[uc_property_trie[((ucs4 - 0x11000) >> 8) + 0x880] + (ucs4 & 0xff)];
}
Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(char16_t ucs2) noexcept
{
- return uc_properties + GET_PROP_INDEX_UCS2(ucs2);
+ return uc_properties + uc_property_trie[uc_property_trie[ucs2 >> 5] + (ucs2 & 0x1f)];
}
Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(char32_t ucs4) noexcept
@@ -9638,8 +10487,17 @@ Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(char32_t ucs4) noexcept
return static_cast<LineBreakClass>(qGetProp(ucs4)->lineBreakClass);
}
+Q_CORE_EXPORT IdnaStatus QT_FASTCALL idnaStatus(char32_t ucs4) noexcept
+{
+ return static_cast<IdnaStatus>(qGetProp(ucs4)->idnaStatus);
+}
+
+Q_CORE_EXPORT EastAsianWidth QT_FASTCALL eastAsianWidth(char32_t ucs4) noexcept
+{
+ return static_cast<EastAsianWidth>(qGetProp(ucs4)->eastAsianWidth);
+}
-static const unsigned short specialCaseMap[] = {
+static constexpr unsigned short specialCaseMap[] = {
0x0, // placeholder
0x1, 0x2c65,
0x1, 0x2c66,
@@ -9946,10 +10804,9 @@ static const unsigned short specialCaseMap[] = {
0x1, 0xa64b
};
-const unsigned int MaxSpecialCaseLength = 3;
+constexpr unsigned int MaxSpecialCaseLength = 3;
-
-static const unsigned short uc_decomposition_trie[] = {
+static constexpr unsigned short uc_decomposition_trie[] = {
// 0 - 0x3400
1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548,
@@ -10089,9 +10946,9 @@ static const unsigned short uc_decomposition_trie[] = {
5356, 5356, 5356, 5356, 5356, 6380, 6636, 6892,
7148, 7404, 7660, 7916, 5356, 5356, 5356, 5356,
- 5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
- 5356, 5356, 5356, 5356, 8172, 8428, 5356, 8684,
- 8940, 9196, 5356, 5356, 5356, 9452, 5356, 5356,
+ 5356, 5356, 5356, 8172, 5356, 5356, 5356, 5356,
+ 5356, 5356, 5356, 5356, 8428, 8684, 5356, 8940,
+ 9196, 9452, 5356, 5356, 5356, 9708, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
@@ -10114,13 +10971,13 @@ static const unsigned short uc_decomposition_trie[] = {
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
- 5356, 5356, 5356, 5356, 5356, 9708, 5356, 5356,
- 9964, 10220, 10476, 10732, 5356, 5356, 5356, 5356,
+ 5356, 5356, 5356, 5356, 5356, 9964, 5356, 5356,
+ 10220, 10476, 10732, 10988, 5356, 5356, 5356, 5356,
+ 5356, 5356, 5356, 5356, 11244, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
- 5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
- 5356, 5356, 10988, 5356, 5356, 11244, 11500, 5356,
+ 5356, 5356, 11500, 5356, 5356, 11756, 12012, 5356,
- 5356, 5356, 5356, 5356, 5356, 5356, 5356, 11756,
+ 5356, 5356, 5356, 5356, 5356, 5356, 5356, 12268,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
@@ -10153,7 +11010,7 @@ static const unsigned short uc_decomposition_trie[] = {
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
5356, 5356, 5356, 5356, 5356, 5356, 5356, 5356,
- 5356, 5356, 5356, 5356, 12012, 12268, 12524, 5356,
+ 5356, 5356, 5356, 5356, 12524, 12780, 13036, 5356,
5356, 5356, 5356, 5356,
@@ -10967,8 +11824,8 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x19fe, 0x1a00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x19fe, 0x1a00, 0x1a02, 0xffff, 0xffff, 0xffff,
+ 0x1a04, 0x1a06, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -10981,9 +11838,9 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0x1a02, 0x1a04, 0x1a06, 0x1a08,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0x1a08, 0x1a0a, 0x1a0c, 0x1a0e,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0x1a0a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x1a10, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11003,234 +11860,267 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x1a0c, 0x1a0e, 0x1a10, 0x1a12, 0x1a14, 0x1a16, 0x1a18, 0x1a1a,
- 0x1a1c, 0x1a1e, 0x1a20, 0x1a22, 0x1a24, 0x1a26, 0x1a28, 0x1a2a,
- 0x1a2c, 0x1a2e, 0x1a30, 0x1a32, 0x1a34, 0x1a36, 0x1a38, 0x1a3a,
- 0x1a3c, 0x1a3e, 0x1a40, 0x1a42, 0x1a44, 0x1a46, 0x1a48, 0x1a4a,
- 0x1a4c, 0x1a4e, 0x1a50, 0x1a52, 0x1a54, 0x1a56, 0x1a58, 0x1a5a,
- 0x1a5c, 0x1a5e, 0x1a60, 0x1a62, 0x1a64, 0x1a66, 0x1a68, 0x1a6a,
- 0x1a6c, 0x1a6e, 0x1a70, 0x1a72, 0x1a74, 0x1a76, 0x1a78, 0x1a7a,
- 0x1a7c, 0x1a7e, 0x1a80, 0x1a82, 0x1a84, 0x1a86, 0x1a88, 0x1a8a,
- 0x1a8c, 0x1a8e, 0x1a90, 0x1a92, 0x1a94, 0x1a96, 0x1a98, 0x1a9a,
- 0x1a9c, 0x1a9e, 0x1aa0, 0x1aa2, 0x1aa4, 0x1aa6, 0x1aa8, 0x1aaa,
- 0x1aac, 0x1aae, 0x1ab0, 0x1ab2, 0x1ab4, 0x1ab6, 0x1ab8, 0x1aba,
- 0x1abc, 0x1abe, 0x1ac0, 0x1ac2, 0x1ac4, 0x1ac6, 0x1ac8, 0x1aca,
- 0x1acc, 0x1ace, 0x1ad0, 0x1ad2, 0x1ad4, 0x1ad6, 0x1ad8, 0x1ada,
- 0x1adc, 0x1ade, 0x1ae0, 0x1ae2, 0x1ae4, 0x1ae6, 0x1ae8, 0x1aea,
- 0x1aec, 0x1aee, 0x1af0, 0x1af2, 0x1af4, 0x1af6, 0x1af8, 0x1afa,
- 0x1afc, 0x1afe, 0x1b00, 0x1b02, 0x1b04, 0x1b06, 0x1b08, 0x1b0a,
- 0x1b0c, 0x1b0e, 0x1b10, 0x1b12, 0x1b14, 0x1b16, 0x1b18, 0x1b1a,
- 0x1b1c, 0x1b1e, 0x1b20, 0x1b22, 0x1b24, 0x1b26, 0x1b28, 0x1b2a,
- 0x1b2c, 0x1b2e, 0x1b30, 0x1b32, 0x1b34, 0x1b36, 0x1b38, 0x1b3a,
- 0x1b3c, 0x1b3e, 0x1b40, 0x1b42, 0x1b44, 0x1b46, 0x1b48, 0x1b4a,
- 0x1b4c, 0x1b4e, 0x1b50, 0x1b52, 0x1b54, 0x1b56, 0x1b58, 0x1b5a,
- 0x1b5c, 0x1b5e, 0x1b60, 0x1b62, 0x1b64, 0x1b66, 0x1b68, 0x1b6a,
- 0x1b6c, 0x1b6e, 0x1b70, 0x1b72, 0x1b74, 0x1b76, 0x1b78, 0x1b7a,
- 0x1b7c, 0x1b7e, 0x1b80, 0x1b82, 0x1b84, 0x1b86, 0x1b88, 0x1b8a,
- 0x1b8c, 0x1b8e, 0x1b90, 0x1b92, 0x1b94, 0x1b96, 0x1b98, 0x1b9a,
- 0x1b9c, 0x1b9e, 0x1ba0, 0x1ba2, 0x1ba4, 0x1ba6, 0x1ba8, 0x1baa,
- 0x1bac, 0x1bae, 0x1bb0, 0x1bb2, 0x1bb4, 0x1bb6, 0x1bb8, 0x1bba,
- 0x1bbc, 0x1bbe, 0x1bc0, 0x1bc2, 0x1bc4, 0x1bc6, 0x1bc8, 0x1bca,
- 0x1bcc, 0x1bce, 0x1bd0, 0x1bd2, 0x1bd4, 0x1bd6, 0x1bd8, 0x1bda,
- 0x1bdc, 0x1bde, 0x1be0, 0x1be2, 0x1be4, 0x1be6, 0x1be8, 0x1bea,
- 0x1bec, 0x1bee, 0x1bf0, 0x1bf2, 0x1bf4, 0x1bf6, 0x1bf8, 0x1bfa,
- 0x1bfc, 0x1bfe, 0x1c00, 0x1c02, 0x1c04, 0x1c06, 0x1c08, 0x1c0a,
+ 0x1a12, 0x1a14, 0x1a16, 0x1a18, 0x1a1a, 0x1a1c, 0x1a1e, 0x1a20,
+ 0x1a22, 0x1a24, 0x1a26, 0x1a28, 0x1a2a, 0x1a2c, 0x1a2e, 0x1a30,
+ 0x1a32, 0x1a34, 0x1a36, 0x1a38, 0x1a3a, 0x1a3c, 0x1a3e, 0x1a40,
+ 0x1a42, 0x1a44, 0x1a46, 0x1a48, 0x1a4a, 0x1a4c, 0x1a4e, 0x1a50,
+ 0x1a52, 0x1a54, 0x1a56, 0x1a58, 0x1a5a, 0x1a5c, 0x1a5e, 0x1a60,
+ 0x1a62, 0x1a64, 0x1a66, 0x1a68, 0x1a6a, 0x1a6c, 0x1a6e, 0x1a70,
+ 0x1a72, 0x1a74, 0x1a76, 0x1a78, 0x1a7a, 0x1a7c, 0x1a7e, 0x1a80,
+ 0x1a82, 0x1a84, 0x1a86, 0x1a88, 0x1a8a, 0x1a8c, 0x1a8e, 0x1a90,
+ 0x1a92, 0x1a94, 0x1a96, 0x1a98, 0x1a9a, 0x1a9c, 0x1a9e, 0x1aa0,
+ 0x1aa2, 0x1aa4, 0x1aa6, 0x1aa8, 0x1aaa, 0x1aac, 0x1aae, 0x1ab0,
+ 0x1ab2, 0x1ab4, 0x1ab6, 0x1ab8, 0x1aba, 0x1abc, 0x1abe, 0x1ac0,
+ 0x1ac2, 0x1ac4, 0x1ac6, 0x1ac8, 0x1aca, 0x1acc, 0x1ace, 0x1ad0,
+ 0x1ad2, 0x1ad4, 0x1ad6, 0x1ad8, 0x1ada, 0x1adc, 0x1ade, 0x1ae0,
+ 0x1ae2, 0x1ae4, 0x1ae6, 0x1ae8, 0x1aea, 0x1aec, 0x1aee, 0x1af0,
+ 0x1af2, 0x1af4, 0x1af6, 0x1af8, 0x1afa, 0x1afc, 0x1afe, 0x1b00,
+ 0x1b02, 0x1b04, 0x1b06, 0x1b08, 0x1b0a, 0x1b0c, 0x1b0e, 0x1b10,
+ 0x1b12, 0x1b14, 0x1b16, 0x1b18, 0x1b1a, 0x1b1c, 0x1b1e, 0x1b20,
+ 0x1b22, 0x1b24, 0x1b26, 0x1b28, 0x1b2a, 0x1b2c, 0x1b2e, 0x1b30,
+ 0x1b32, 0x1b34, 0x1b36, 0x1b38, 0x1b3a, 0x1b3c, 0x1b3e, 0x1b40,
+ 0x1b42, 0x1b44, 0x1b46, 0x1b48, 0x1b4a, 0x1b4c, 0x1b4e, 0x1b50,
+ 0x1b52, 0x1b54, 0x1b56, 0x1b58, 0x1b5a, 0x1b5c, 0x1b5e, 0x1b60,
+ 0x1b62, 0x1b64, 0x1b66, 0x1b68, 0x1b6a, 0x1b6c, 0x1b6e, 0x1b70,
+ 0x1b72, 0x1b74, 0x1b76, 0x1b78, 0x1b7a, 0x1b7c, 0x1b7e, 0x1b80,
+ 0x1b82, 0x1b84, 0x1b86, 0x1b88, 0x1b8a, 0x1b8c, 0x1b8e, 0x1b90,
+ 0x1b92, 0x1b94, 0x1b96, 0x1b98, 0x1b9a, 0x1b9c, 0x1b9e, 0x1ba0,
+ 0x1ba2, 0x1ba4, 0x1ba6, 0x1ba8, 0x1baa, 0x1bac, 0x1bae, 0x1bb0,
+ 0x1bb2, 0x1bb4, 0x1bb6, 0x1bb8, 0x1bba, 0x1bbc, 0x1bbe, 0x1bc0,
+ 0x1bc2, 0x1bc4, 0x1bc6, 0x1bc8, 0x1bca, 0x1bcc, 0x1bce, 0x1bd0,
+ 0x1bd2, 0x1bd4, 0x1bd6, 0x1bd8, 0x1bda, 0x1bdc, 0x1bde, 0x1be0,
+ 0x1be2, 0x1be4, 0x1be6, 0x1be8, 0x1bea, 0x1bec, 0x1bee, 0x1bf0,
+ 0x1bf2, 0x1bf4, 0x1bf6, 0x1bf8, 0x1bfa, 0x1bfc, 0x1bfe, 0x1c00,
+ 0x1c02, 0x1c04, 0x1c06, 0x1c08, 0x1c0a, 0x1c0c, 0x1c0e, 0x1c10,
- 0x1c0c, 0x1c0e, 0x1c10, 0x1c12, 0x1c14, 0x1c16, 0x1c18, 0x1c1a,
- 0x1c1c, 0x1c1e, 0x1c20, 0x1c22, 0x1c24, 0x1c26, 0xffff, 0xffff,
- 0x1c28, 0xffff, 0x1c2a, 0xffff, 0xffff, 0x1c2c, 0x1c2e, 0x1c30,
- 0x1c32, 0x1c34, 0x1c36, 0x1c38, 0x1c3a, 0x1c3c, 0x1c3e, 0xffff,
- 0x1c40, 0xffff, 0x1c42, 0xffff, 0xffff, 0x1c44, 0x1c46, 0xffff,
- 0xffff, 0xffff, 0x1c48, 0x1c4a, 0x1c4c, 0x1c4e, 0x1c50, 0x1c52,
- 0x1c54, 0x1c56, 0x1c58, 0x1c5a, 0x1c5c, 0x1c5e, 0x1c60, 0x1c62,
- 0x1c64, 0x1c66, 0x1c68, 0x1c6a, 0x1c6c, 0x1c6e, 0x1c70, 0x1c72,
- 0x1c74, 0x1c76, 0x1c78, 0x1c7a, 0x1c7c, 0x1c7e, 0x1c80, 0x1c82,
- 0x1c84, 0x1c86, 0x1c88, 0x1c8a, 0x1c8c, 0x1c8e, 0x1c90, 0x1c92,
- 0x1c94, 0x1c96, 0x1c98, 0x1c9a, 0x1c9c, 0x1c9e, 0x1ca0, 0x1ca2,
- 0x1ca4, 0x1ca6, 0x1ca8, 0x1caa, 0x1cac, 0x1cae, 0x1cb0, 0x1cb2,
- 0x1cb4, 0x1cb6, 0x1cb8, 0x1cba, 0x1cbc, 0x1cbe, 0x1cc0, 0x1cc2,
- 0x1cc4, 0x1cc6, 0x1cc8, 0x1cca, 0x1ccc, 0x1ccf, 0xffff, 0xffff,
- 0x1cd1, 0x1cd3, 0x1cd5, 0x1cd7, 0x1cd9, 0x1cdb, 0x1cdd, 0x1cdf,
- 0x1ce1, 0x1ce3, 0x1ce5, 0x1ce7, 0x1ce9, 0x1ceb, 0x1ced, 0x1cef,
- 0x1cf1, 0x1cf3, 0x1cf5, 0x1cf7, 0x1cf9, 0x1cfb, 0x1cfd, 0x1cff,
- 0x1d01, 0x1d03, 0x1d05, 0x1d07, 0x1d09, 0x1d0b, 0x1d0d, 0x1d0f,
- 0x1d11, 0x1d13, 0x1d15, 0x1d17, 0x1d19, 0x1d1b, 0x1d1d, 0x1d1f,
- 0x1d21, 0x1d23, 0x1d25, 0x1d27, 0x1d29, 0x1d2b, 0x1d2d, 0x1d2f,
- 0x1d31, 0x1d33, 0x1d35, 0x1d37, 0x1d39, 0x1d3b, 0x1d3d, 0x1d3f,
- 0x1d41, 0x1d43, 0x1d45, 0x1d47, 0x1d49, 0x1d4b, 0x1d4d, 0x1d4f,
- 0x1d51, 0x1d53, 0x1d55, 0x1d57, 0x1d59, 0x1d5b, 0x1d5d, 0x1d5f,
- 0x1d61, 0x1d63, 0x1d65, 0x1d67, 0x1d69, 0x1d6b, 0x1d6d, 0x1d6f,
- 0x1d71, 0x1d73, 0x1d75, 0x1d77, 0x1d79, 0x1d7b, 0x1d7d, 0x1d7f,
- 0x1d81, 0x1d83, 0x1d85, 0x1d87, 0x1d89, 0x1d8b, 0x1d8d, 0x1d8f,
- 0x1d92, 0x1d95, 0x1d98, 0x1d9a, 0x1d9c, 0x1d9e, 0x1da1, 0x1da4,
- 0x1da7, 0x1da9, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x1c12, 0x1c14, 0x1c16, 0x1c18, 0x1c1a, 0x1c1c, 0x1c1e, 0x1c20,
+ 0x1c22, 0x1c24, 0x1c26, 0x1c28, 0x1c2a, 0x1c2c, 0xffff, 0xffff,
+ 0x1c2e, 0xffff, 0x1c30, 0xffff, 0xffff, 0x1c32, 0x1c34, 0x1c36,
+ 0x1c38, 0x1c3a, 0x1c3c, 0x1c3e, 0x1c40, 0x1c42, 0x1c44, 0xffff,
+ 0x1c46, 0xffff, 0x1c48, 0xffff, 0xffff, 0x1c4a, 0x1c4c, 0xffff,
+ 0xffff, 0xffff, 0x1c4e, 0x1c50, 0x1c52, 0x1c54, 0x1c56, 0x1c58,
+ 0x1c5a, 0x1c5c, 0x1c5e, 0x1c60, 0x1c62, 0x1c64, 0x1c66, 0x1c68,
+ 0x1c6a, 0x1c6c, 0x1c6e, 0x1c70, 0x1c72, 0x1c74, 0x1c76, 0x1c78,
+ 0x1c7a, 0x1c7c, 0x1c7e, 0x1c80, 0x1c82, 0x1c84, 0x1c86, 0x1c88,
+ 0x1c8a, 0x1c8c, 0x1c8e, 0x1c90, 0x1c92, 0x1c94, 0x1c96, 0x1c98,
+ 0x1c9a, 0x1c9c, 0x1c9e, 0x1ca0, 0x1ca2, 0x1ca4, 0x1ca6, 0x1ca8,
+ 0x1caa, 0x1cac, 0x1cae, 0x1cb0, 0x1cb2, 0x1cb4, 0x1cb6, 0x1cb8,
+ 0x1cba, 0x1cbc, 0x1cbe, 0x1cc0, 0x1cc2, 0x1cc4, 0x1cc6, 0x1cc8,
+ 0x1cca, 0x1ccc, 0x1cce, 0x1cd0, 0x1cd2, 0x1cd5, 0xffff, 0xffff,
+ 0x1cd7, 0x1cd9, 0x1cdb, 0x1cdd, 0x1cdf, 0x1ce1, 0x1ce3, 0x1ce5,
+ 0x1ce7, 0x1ce9, 0x1ceb, 0x1ced, 0x1cef, 0x1cf1, 0x1cf3, 0x1cf5,
+ 0x1cf7, 0x1cf9, 0x1cfb, 0x1cfd, 0x1cff, 0x1d01, 0x1d03, 0x1d05,
+ 0x1d07, 0x1d09, 0x1d0b, 0x1d0d, 0x1d0f, 0x1d11, 0x1d13, 0x1d15,
+ 0x1d17, 0x1d19, 0x1d1b, 0x1d1d, 0x1d1f, 0x1d21, 0x1d23, 0x1d25,
+ 0x1d27, 0x1d29, 0x1d2b, 0x1d2d, 0x1d2f, 0x1d31, 0x1d33, 0x1d35,
+ 0x1d37, 0x1d39, 0x1d3b, 0x1d3d, 0x1d3f, 0x1d41, 0x1d43, 0x1d45,
+ 0x1d47, 0x1d49, 0x1d4b, 0x1d4d, 0x1d4f, 0x1d51, 0x1d53, 0x1d55,
+ 0x1d57, 0x1d59, 0x1d5b, 0x1d5d, 0x1d5f, 0x1d61, 0x1d63, 0x1d65,
+ 0x1d67, 0x1d69, 0x1d6b, 0x1d6d, 0x1d6f, 0x1d71, 0x1d73, 0x1d75,
+ 0x1d77, 0x1d79, 0x1d7b, 0x1d7d, 0x1d7f, 0x1d81, 0x1d83, 0x1d85,
+ 0x1d87, 0x1d89, 0x1d8b, 0x1d8d, 0x1d8f, 0x1d91, 0x1d93, 0x1d95,
+ 0x1d98, 0x1d9b, 0x1d9e, 0x1da0, 0x1da2, 0x1da4, 0x1da7, 0x1daa,
+ 0x1dad, 0x1daf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x1dab, 0x1dae, 0x1db1, 0x1db4, 0x1db8, 0x1dbc, 0x1dbf, 0xffff,
+ 0x1db1, 0x1db4, 0x1db7, 0x1dba, 0x1dbe, 0x1dc2, 0x1dc5, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x1dc8, 0x1dcb, 0x1dce, 0x1dd1, 0x1dd4,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x1dd7, 0xffff, 0x1dda,
+ 0x1ddd, 0x1ddf, 0x1de1, 0x1de3, 0x1de5, 0x1de7, 0x1de9, 0x1deb,
+ 0x1ded, 0x1def, 0x1df1, 0x1df4, 0x1df7, 0x1dfa, 0x1dfd, 0x1e00,
+ 0x1e03, 0x1e06, 0x1e09, 0x1e0c, 0x1e0f, 0x1e12, 0x1e15, 0xffff,
+ 0x1e18, 0x1e1b, 0x1e1e, 0x1e21, 0x1e24, 0xffff, 0x1e27, 0xffff,
+ 0x1e2a, 0x1e2d, 0xffff, 0x1e30, 0x1e33, 0xffff, 0x1e36, 0x1e39,
+ 0x1e3c, 0x1e3f, 0x1e42, 0x1e45, 0x1e48, 0x1e4b, 0x1e4e, 0x1e51,
+ 0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c, 0x1e5e, 0x1e60, 0x1e62,
+ 0x1e64, 0x1e66, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, 0x1e72,
+ 0x1e74, 0x1e76, 0x1e78, 0x1e7a, 0x1e7c, 0x1e7e, 0x1e80, 0x1e82,
+ 0x1e84, 0x1e86, 0x1e88, 0x1e8a, 0x1e8c, 0x1e8e, 0x1e90, 0x1e92,
+ 0x1e94, 0x1e96, 0x1e98, 0x1e9a, 0x1e9c, 0x1e9e, 0x1ea0, 0x1ea2,
+ 0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac, 0x1eae, 0x1eb0, 0x1eb2,
+ 0x1eb4, 0x1eb6, 0x1eb8, 0x1eba, 0x1ebc, 0x1ebe, 0x1ec0, 0x1ec2,
+ 0x1ec4, 0x1ec6, 0x1ec8, 0x1eca, 0x1ecc, 0x1ece, 0x1ed0, 0x1ed2,
+ 0x1ed4, 0x1ed6, 0x1ed8, 0x1eda, 0x1edc, 0x1ede, 0x1ee0, 0x1ee2,
+ 0x1ee4, 0x1ee6, 0x1ee8, 0x1eea, 0x1eec, 0x1eee, 0x1ef0, 0x1ef2,
+ 0x1ef4, 0x1ef6, 0x1ef8, 0x1efa, 0x1efc, 0x1efe, 0x1f00, 0x1f02,
+ 0x1f04, 0x1f06, 0x1f08, 0x1f0a, 0x1f0c, 0x1f0e, 0x1f10, 0x1f12,
+ 0x1f14, 0x1f16, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x1f18, 0x1f1a, 0x1f1c, 0x1f1e, 0x1f20,
+ 0x1f22, 0x1f24, 0x1f26, 0x1f28, 0x1f2a, 0x1f2c, 0x1f2e, 0x1f30,
+ 0x1f32, 0x1f34, 0x1f36, 0x1f38, 0x1f3a, 0x1f3c, 0x1f3e, 0x1f40,
+ 0x1f42, 0x1f44, 0x1f46, 0x1f49, 0x1f4c, 0x1f4f, 0x1f52, 0x1f55,
+ 0x1f58, 0x1f5b, 0x1f5e, 0x1f61, 0x1f64, 0x1f67, 0x1f6a, 0x1f6d,
+ 0x1f70, 0x1f73, 0x1f76, 0x1f79, 0x1f7c, 0x1f7e, 0x1f80, 0x1f82,
+
+ 0x1f84, 0x1f87, 0x1f8a, 0x1f8d, 0x1f90, 0x1f93, 0x1f96, 0x1f99,
+ 0x1f9c, 0x1f9f, 0x1fa2, 0x1fa5, 0x1fa8, 0x1fab, 0x1fae, 0x1fb1,
+ 0x1fb4, 0x1fb7, 0x1fba, 0x1fbd, 0x1fc0, 0x1fc3, 0x1fc6, 0x1fc9,
+ 0x1fcc, 0x1fcf, 0x1fd2, 0x1fd5, 0x1fd8, 0x1fdb, 0x1fde, 0x1fe1,
+ 0x1fe4, 0x1fe7, 0x1fea, 0x1fed, 0x1ff0, 0x1ff3, 0x1ff6, 0x1ff9,
+ 0x1ffc, 0x1fff, 0x2002, 0x2005, 0x2008, 0x200b, 0x200e, 0x2011,
+ 0x2014, 0x2017, 0x201a, 0x201d, 0x2020, 0x2023, 0x2026, 0x2029,
+ 0x202c, 0x202f, 0x2032, 0x2035, 0x2038, 0x203b, 0x203e, 0x2041,
+ 0x2044, 0x2047, 0x204a, 0x204d, 0x2050, 0x2053, 0x2056, 0x2059,
+ 0x205c, 0x205f, 0x2062, 0x2065, 0x2068, 0x206b, 0x206e, 0x2071,
+ 0x2074, 0x2077, 0x207a, 0x207d, 0x2080, 0x2083, 0x2086, 0x2089,
+ 0x208c, 0x208f, 0x2092, 0x2095, 0x2098, 0x209b, 0x209e, 0x20a2,
+ 0x20a6, 0x20aa, 0x20ae, 0x20b2, 0x20b6, 0x20b9, 0x20bc, 0x20bf,
+ 0x20c2, 0x20c5, 0x20c8, 0x20cb, 0x20ce, 0x20d1, 0x20d4, 0x20d7,
+ 0x20da, 0x20dd, 0x20e0, 0x20e3, 0x20e6, 0x20e9, 0x20ec, 0x20ef,
+ 0x20f2, 0x20f5, 0x20f8, 0x20fb, 0x20fe, 0x2101, 0x2104, 0x2107,
+ 0x210a, 0x210d, 0x2110, 0x2113, 0x2116, 0x2119, 0x211c, 0x211f,
+ 0x2122, 0x2125, 0x2128, 0x212b, 0x212e, 0x2131, 0x2134, 0x2137,
+ 0x213a, 0x213d, 0x2140, 0x2143, 0x2146, 0x2149, 0x214c, 0x214f,
+ 0x2152, 0x2155, 0x2158, 0x215b, 0x215e, 0x2161, 0x2164, 0x2167,
+ 0x216a, 0x216d, 0x2170, 0x2173, 0x2176, 0x2179, 0x217c, 0x217f,
+ 0x2182, 0x2185, 0x2188, 0x218b, 0x218e, 0x2191, 0x2194, 0x2197,
+ 0x219a, 0x219d, 0x21a0, 0x21a3, 0x21a6, 0x21a9, 0x21ac, 0x21af,
+ 0x21b2, 0x21b5, 0x21b8, 0x21bb, 0x21be, 0x21c1, 0x21c4, 0x21c7,
+ 0x21ca, 0x21cd, 0x21d0, 0x21d3, 0x21d6, 0x21d9, 0x21dc, 0x21df,
+ 0x21e2, 0x21e5, 0x21e8, 0x21eb, 0x21ee, 0x21f1, 0x21f4, 0x21f7,
+ 0x21fa, 0x21fd, 0x2200, 0x2203, 0x2206, 0x2209, 0x220c, 0x220f,
+ 0x2212, 0x2215, 0x2218, 0x221b, 0x221e, 0x2221, 0x2224, 0x2227,
+ 0x222a, 0x222d, 0x2230, 0x2233, 0x2236, 0x2239, 0x223c, 0x223f,
+ 0x2242, 0x2245, 0x2248, 0x224b, 0x224e, 0x2251, 0x2254, 0x2257,
+ 0x225a, 0x225d, 0x2260, 0x2264, 0x2268, 0x226c, 0x226f, 0x2272,
+ 0x2275, 0x2278, 0x227b, 0x227e, 0x2281, 0x2284, 0x2287, 0x228a,
+
+ 0x228d, 0x2290, 0x2293, 0x2296, 0x2299, 0x229c, 0x229f, 0x22a2,
+ 0x22a5, 0x22a8, 0x22ab, 0x22ae, 0x22b1, 0x22b4, 0x22b7, 0x22ba,
+ 0x22bd, 0x22c0, 0x22c3, 0x22c6, 0x22c9, 0x22cc, 0x22cf, 0x22d2,
+ 0x22d5, 0x22d8, 0x22db, 0x22de, 0x22e1, 0x22e4, 0x22e7, 0x22ea,
+ 0x22ed, 0x22f0, 0x22f3, 0x22f6, 0x22f9, 0x22fc, 0x22ff, 0x2302,
+ 0x2305, 0x2308, 0x230b, 0x230e, 0x2311, 0x2314, 0x2317, 0x231a,
+ 0x231d, 0x2320, 0x2323, 0x2326, 0x2329, 0x232c, 0x232f, 0x2332,
+ 0x2335, 0x2338, 0x233b, 0x233e, 0x2341, 0x2344, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x2347, 0x234b, 0x234f, 0x2353, 0x2357, 0x235b, 0x235f, 0x2363,
+ 0x2367, 0x236b, 0x236f, 0x2373, 0x2377, 0x237b, 0x237f, 0x2383,
+ 0x2387, 0x238b, 0x238f, 0x2393, 0x2397, 0x239b, 0x239f, 0x23a3,
+ 0x23a7, 0x23ab, 0x23af, 0x23b3, 0x23b7, 0x23bb, 0x23bf, 0x23c3,
+ 0x23c7, 0x23cb, 0x23cf, 0x23d3, 0x23d7, 0x23db, 0x23df, 0x23e3,
+ 0x23e7, 0x23eb, 0x23ef, 0x23f3, 0x23f7, 0x23fb, 0x23ff, 0x2403,
+ 0x2407, 0x240b, 0x240f, 0x2413, 0x2417, 0x241b, 0x241f, 0x2423,
+ 0x2427, 0x242b, 0x242f, 0x2433, 0x2437, 0x243b, 0x243f, 0x2443,
+ 0xffff, 0xffff, 0x2447, 0x244b, 0x244f, 0x2453, 0x2457, 0x245b,
+ 0x245f, 0x2463, 0x2467, 0x246b, 0x246f, 0x2473, 0x2477, 0x247b,
+ 0x247f, 0x2483, 0x2487, 0x248b, 0x248f, 0x2493, 0x2497, 0x249b,
+ 0x249f, 0x24a3, 0x24a7, 0x24ab, 0x24af, 0x24b3, 0x24b7, 0x24bb,
+ 0x24bf, 0x24c3, 0x24c7, 0x24cb, 0x24cf, 0x24d3, 0x24d7, 0x24db,
+ 0x24df, 0x24e3, 0x24e7, 0x24eb, 0x24ef, 0x24f3, 0x24f7, 0x24fb,
+ 0x24ff, 0x2503, 0x2507, 0x250b, 0x250f, 0x2513, 0x2517, 0x251b,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x1dc2, 0x1dc5, 0x1dc8, 0x1dcb, 0x1dce,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x1dd1, 0xffff, 0x1dd4,
- 0x1dd7, 0x1dd9, 0x1ddb, 0x1ddd, 0x1ddf, 0x1de1, 0x1de3, 0x1de5,
- 0x1de7, 0x1de9, 0x1deb, 0x1dee, 0x1df1, 0x1df4, 0x1df7, 0x1dfa,
- 0x1dfd, 0x1e00, 0x1e03, 0x1e06, 0x1e09, 0x1e0c, 0x1e0f, 0xffff,
- 0x1e12, 0x1e15, 0x1e18, 0x1e1b, 0x1e1e, 0xffff, 0x1e21, 0xffff,
- 0x1e24, 0x1e27, 0xffff, 0x1e2a, 0x1e2d, 0xffff, 0x1e30, 0x1e33,
- 0x1e36, 0x1e39, 0x1e3c, 0x1e3f, 0x1e42, 0x1e45, 0x1e48, 0x1e4b,
- 0x1e4e, 0x1e50, 0x1e52, 0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c,
- 0x1e5e, 0x1e60, 0x1e62, 0x1e64, 0x1e66, 0x1e68, 0x1e6a, 0x1e6c,
- 0x1e6e, 0x1e70, 0x1e72, 0x1e74, 0x1e76, 0x1e78, 0x1e7a, 0x1e7c,
- 0x1e7e, 0x1e80, 0x1e82, 0x1e84, 0x1e86, 0x1e88, 0x1e8a, 0x1e8c,
- 0x1e8e, 0x1e90, 0x1e92, 0x1e94, 0x1e96, 0x1e98, 0x1e9a, 0x1e9c,
- 0x1e9e, 0x1ea0, 0x1ea2, 0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac,
- 0x1eae, 0x1eb0, 0x1eb2, 0x1eb4, 0x1eb6, 0x1eb8, 0x1eba, 0x1ebc,
- 0x1ebe, 0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6, 0x1ec8, 0x1eca, 0x1ecc,
- 0x1ece, 0x1ed0, 0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8, 0x1eda, 0x1edc,
- 0x1ede, 0x1ee0, 0x1ee2, 0x1ee4, 0x1ee6, 0x1ee8, 0x1eea, 0x1eec,
- 0x1eee, 0x1ef0, 0x1ef2, 0x1ef4, 0x1ef6, 0x1ef8, 0x1efa, 0x1efc,
- 0x1efe, 0x1f00, 0x1f02, 0x1f04, 0x1f06, 0x1f08, 0x1f0a, 0x1f0c,
- 0x1f0e, 0x1f10, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x1f12, 0x1f14, 0x1f16, 0x1f18, 0x1f1a,
- 0x1f1c, 0x1f1e, 0x1f20, 0x1f22, 0x1f24, 0x1f26, 0x1f28, 0x1f2a,
- 0x1f2c, 0x1f2e, 0x1f30, 0x1f32, 0x1f34, 0x1f36, 0x1f38, 0x1f3a,
- 0x1f3c, 0x1f3e, 0x1f40, 0x1f43, 0x1f46, 0x1f49, 0x1f4c, 0x1f4f,
- 0x1f52, 0x1f55, 0x1f58, 0x1f5b, 0x1f5e, 0x1f61, 0x1f64, 0x1f67,
- 0x1f6a, 0x1f6d, 0x1f70, 0x1f73, 0x1f76, 0x1f78, 0x1f7a, 0x1f7c,
-
- 0x1f7e, 0x1f81, 0x1f84, 0x1f87, 0x1f8a, 0x1f8d, 0x1f90, 0x1f93,
- 0x1f96, 0x1f99, 0x1f9c, 0x1f9f, 0x1fa2, 0x1fa5, 0x1fa8, 0x1fab,
- 0x1fae, 0x1fb1, 0x1fb4, 0x1fb7, 0x1fba, 0x1fbd, 0x1fc0, 0x1fc3,
- 0x1fc6, 0x1fc9, 0x1fcc, 0x1fcf, 0x1fd2, 0x1fd5, 0x1fd8, 0x1fdb,
- 0x1fde, 0x1fe1, 0x1fe4, 0x1fe7, 0x1fea, 0x1fed, 0x1ff0, 0x1ff3,
- 0x1ff6, 0x1ff9, 0x1ffc, 0x1fff, 0x2002, 0x2005, 0x2008, 0x200b,
- 0x200e, 0x2011, 0x2014, 0x2017, 0x201a, 0x201d, 0x2020, 0x2023,
- 0x2026, 0x2029, 0x202c, 0x202f, 0x2032, 0x2035, 0x2038, 0x203b,
- 0x203e, 0x2041, 0x2044, 0x2047, 0x204a, 0x204d, 0x2050, 0x2053,
- 0x2056, 0x2059, 0x205c, 0x205f, 0x2062, 0x2065, 0x2068, 0x206b,
- 0x206e, 0x2071, 0x2074, 0x2077, 0x207a, 0x207d, 0x2080, 0x2083,
- 0x2086, 0x2089, 0x208c, 0x208f, 0x2092, 0x2095, 0x2098, 0x209c,
- 0x20a0, 0x20a4, 0x20a8, 0x20ac, 0x20b0, 0x20b3, 0x20b6, 0x20b9,
- 0x20bc, 0x20bf, 0x20c2, 0x20c5, 0x20c8, 0x20cb, 0x20ce, 0x20d1,
- 0x20d4, 0x20d7, 0x20da, 0x20dd, 0x20e0, 0x20e3, 0x20e6, 0x20e9,
- 0x20ec, 0x20ef, 0x20f2, 0x20f5, 0x20f8, 0x20fb, 0x20fe, 0x2101,
- 0x2104, 0x2107, 0x210a, 0x210d, 0x2110, 0x2113, 0x2116, 0x2119,
- 0x211c, 0x211f, 0x2122, 0x2125, 0x2128, 0x212b, 0x212e, 0x2131,
- 0x2134, 0x2137, 0x213a, 0x213d, 0x2140, 0x2143, 0x2146, 0x2149,
- 0x214c, 0x214f, 0x2152, 0x2155, 0x2158, 0x215b, 0x215e, 0x2161,
- 0x2164, 0x2167, 0x216a, 0x216d, 0x2170, 0x2173, 0x2176, 0x2179,
- 0x217c, 0x217f, 0x2182, 0x2185, 0x2188, 0x218b, 0x218e, 0x2191,
- 0x2194, 0x2197, 0x219a, 0x219d, 0x21a0, 0x21a3, 0x21a6, 0x21a9,
- 0x21ac, 0x21af, 0x21b2, 0x21b5, 0x21b8, 0x21bb, 0x21be, 0x21c1,
- 0x21c4, 0x21c7, 0x21ca, 0x21cd, 0x21d0, 0x21d3, 0x21d6, 0x21d9,
- 0x21dc, 0x21df, 0x21e2, 0x21e5, 0x21e8, 0x21eb, 0x21ee, 0x21f1,
- 0x21f4, 0x21f7, 0x21fa, 0x21fd, 0x2200, 0x2203, 0x2206, 0x2209,
- 0x220c, 0x220f, 0x2212, 0x2215, 0x2218, 0x221b, 0x221e, 0x2221,
- 0x2224, 0x2227, 0x222a, 0x222d, 0x2230, 0x2233, 0x2236, 0x2239,
- 0x223c, 0x223f, 0x2242, 0x2245, 0x2248, 0x224b, 0x224e, 0x2251,
- 0x2254, 0x2257, 0x225a, 0x225e, 0x2262, 0x2266, 0x2269, 0x226c,
- 0x226f, 0x2272, 0x2275, 0x2278, 0x227b, 0x227e, 0x2281, 0x2284,
-
- 0x2287, 0x228a, 0x228d, 0x2290, 0x2293, 0x2296, 0x2299, 0x229c,
- 0x229f, 0x22a2, 0x22a5, 0x22a8, 0x22ab, 0x22ae, 0x22b1, 0x22b4,
- 0x22b7, 0x22ba, 0x22bd, 0x22c0, 0x22c3, 0x22c6, 0x22c9, 0x22cc,
- 0x22cf, 0x22d2, 0x22d5, 0x22d8, 0x22db, 0x22de, 0x22e1, 0x22e4,
- 0x22e7, 0x22ea, 0x22ed, 0x22f0, 0x22f3, 0x22f6, 0x22f9, 0x22fc,
- 0x22ff, 0x2302, 0x2305, 0x2308, 0x230b, 0x230e, 0x2311, 0x2314,
- 0x2317, 0x231a, 0x231d, 0x2320, 0x2323, 0x2326, 0x2329, 0x232c,
- 0x232f, 0x2332, 0x2335, 0x2338, 0x233b, 0x233e, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x2341, 0x2345, 0x2349, 0x234d, 0x2351, 0x2355, 0x2359, 0x235d,
- 0x2361, 0x2365, 0x2369, 0x236d, 0x2371, 0x2375, 0x2379, 0x237d,
- 0x2381, 0x2385, 0x2389, 0x238d, 0x2391, 0x2395, 0x2399, 0x239d,
- 0x23a1, 0x23a5, 0x23a9, 0x23ad, 0x23b1, 0x23b5, 0x23b9, 0x23bd,
- 0x23c1, 0x23c5, 0x23c9, 0x23cd, 0x23d1, 0x23d5, 0x23d9, 0x23dd,
- 0x23e1, 0x23e5, 0x23e9, 0x23ed, 0x23f1, 0x23f5, 0x23f9, 0x23fd,
- 0x2401, 0x2405, 0x2409, 0x240d, 0x2411, 0x2415, 0x2419, 0x241d,
- 0x2421, 0x2425, 0x2429, 0x242d, 0x2431, 0x2435, 0x2439, 0x243d,
- 0xffff, 0xffff, 0x2441, 0x2445, 0x2449, 0x244d, 0x2451, 0x2455,
- 0x2459, 0x245d, 0x2461, 0x2465, 0x2469, 0x246d, 0x2471, 0x2475,
- 0x2479, 0x247d, 0x2481, 0x2485, 0x2489, 0x248d, 0x2491, 0x2495,
- 0x2499, 0x249d, 0x24a1, 0x24a5, 0x24a9, 0x24ad, 0x24b1, 0x24b5,
- 0x24b9, 0x24bd, 0x24c1, 0x24c5, 0x24c9, 0x24cd, 0x24d1, 0x24d5,
- 0x24d9, 0x24dd, 0x24e1, 0x24e5, 0x24e9, 0x24ed, 0x24f1, 0x24f5,
- 0x24f9, 0x24fd, 0x2501, 0x2505, 0x2509, 0x250d, 0x2511, 0x2515,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x251f, 0x2523, 0x2527, 0x252c, 0x2531, 0x2536, 0x253b, 0x2540,
+ 0x2545, 0x254a, 0x254e, 0x2561, 0x256a, 0xffff, 0xffff, 0xffff,
+
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x256f, 0x2571, 0x2573, 0x2575, 0x2577, 0x2579, 0x257b, 0x257d,
+ 0x257f, 0x2581, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x2519, 0x251d, 0x2521, 0x2526, 0x252b, 0x2530, 0x2535, 0x253a,
- 0x253f, 0x2544, 0x2548, 0x255b, 0x2564, 0xffff, 0xffff, 0xffff,
+ 0x2583, 0x2585, 0x2587, 0x2589, 0x258b, 0x258d, 0x258f, 0x2591,
+ 0x2593, 0x2595, 0x2597, 0x2599, 0x259b, 0x259d, 0x259f, 0x25a1,
+ 0x25a3, 0x25a5, 0x25a7, 0x25a9, 0x25ab, 0xffff, 0xffff, 0x25ad,
+ 0x25af, 0x25b1, 0x25b3, 0x25b5, 0x25b7, 0x25b9, 0x25bb, 0x25bd,
+ 0x25bf, 0x25c1, 0x25c3, 0xffff, 0x25c5, 0x25c7, 0x25c9, 0x25cb,
+ 0x25cd, 0x25cf, 0x25d1, 0x25d3, 0x25d5, 0x25d7, 0x25d9, 0x25db,
+ 0x25dd, 0x25df, 0x25e1, 0x25e3, 0x25e5, 0x25e7, 0x25e9, 0xffff,
+ 0x25eb, 0x25ed, 0x25ef, 0x25f1, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x25f3, 0x25f6, 0x25f9, 0xffff, 0x25fc, 0xffff, 0x25ff, 0x2602,
+ 0x2605, 0x2608, 0x260b, 0x260e, 0x2611, 0x2614, 0x2617, 0x261a,
+ 0x261d, 0x261f, 0x2621, 0x2623, 0x2625, 0x2627, 0x2629, 0x262b,
+ 0x262d, 0x262f, 0x2631, 0x2633, 0x2635, 0x2637, 0x2639, 0x263b,
+ 0x263d, 0x263f, 0x2641, 0x2643, 0x2645, 0x2647, 0x2649, 0x264b,
+ 0x264d, 0x264f, 0x2651, 0x2653, 0x2655, 0x2657, 0x2659, 0x265b,
+ 0x265d, 0x265f, 0x2661, 0x2663, 0x2665, 0x2667, 0x2669, 0x266b,
+ 0x266d, 0x266f, 0x2671, 0x2673, 0x2675, 0x2677, 0x2679, 0x267b,
+ 0x267d, 0x267f, 0x2681, 0x2683, 0x2685, 0x2687, 0x2689, 0x268b,
+ 0x268d, 0x268f, 0x2691, 0x2693, 0x2695, 0x2697, 0x2699, 0x269b,
+ 0x269d, 0x269f, 0x26a1, 0x26a3, 0x26a5, 0x26a7, 0x26a9, 0x26ab,
+ 0x26ad, 0x26af, 0x26b1, 0x26b3, 0x26b5, 0x26b7, 0x26b9, 0x26bb,
+ 0x26bd, 0x26bf, 0x26c1, 0x26c3, 0x26c5, 0x26c7, 0x26c9, 0x26cb,
+ 0x26cd, 0x26cf, 0x26d1, 0x26d3, 0x26d5, 0x26d7, 0x26d9, 0x26db,
+ 0x26dd, 0x26df, 0x26e1, 0x26e3, 0x26e5, 0x26e7, 0x26e9, 0x26eb,
+ 0x26ed, 0x26ef, 0x26f1, 0x26f3, 0x26f5, 0x26f7, 0x26f9, 0x26fb,
+ 0x26fd, 0x26ff, 0x2701, 0x2703, 0x2705, 0x2707, 0x270a, 0x270d,
+ 0x2710, 0x2713, 0x2716, 0x2719, 0x271c, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x271f, 0x2721, 0x2723, 0x2725, 0x2727, 0x2729, 0x272b,
+ 0x272d, 0x272f, 0x2731, 0x2733, 0x2735, 0x2737, 0x2739, 0x273b,
+ 0x273d, 0x273f, 0x2741, 0x2743, 0x2745, 0x2747, 0x2749, 0x274b,
+ 0x274d, 0x274f, 0x2751, 0x2753, 0x2755, 0x2757, 0x2759, 0x275b,
+ 0x275d, 0x275f, 0x2761, 0x2763, 0x2765, 0x2767, 0x2769, 0x276b,
+ 0x276d, 0x276f, 0x2771, 0x2773, 0x2775, 0x2777, 0x2779, 0x277b,
+ 0x277d, 0x277f, 0x2781, 0x2783, 0x2785, 0x2787, 0x2789, 0x278b,
+ 0x278d, 0x278f, 0x2791, 0x2793, 0x2795, 0x2797, 0x2799, 0x279b,
+ 0x279d, 0x279f, 0x27a1, 0x27a3, 0x27a5, 0x27a7, 0x27a9, 0x27ab,
+ 0x27ad, 0x27af, 0x27b1, 0x27b3, 0x27b5, 0x27b7, 0x27b9, 0x27bb,
+ 0x27bd, 0x27bf, 0x27c1, 0x27c3, 0x27c5, 0x27c7, 0x27c9, 0x27cb,
+ 0x27cd, 0x27cf, 0x27d1, 0x27d3, 0x27d5, 0x27d7, 0x27d9, 0x27db,
+ 0x27dd, 0x27df, 0x27e1, 0x27e3, 0x27e5, 0x27e7, 0x27e9, 0x27eb,
+ 0x27ed, 0x27ef, 0x27f1, 0x27f3, 0x27f5, 0x27f7, 0x27f9, 0x27fb,
+ 0x27fd, 0x27ff, 0x2801, 0x2803, 0x2805, 0x2807, 0x2809, 0x280b,
+ 0x280d, 0x280f, 0x2811, 0x2813, 0x2815, 0x2817, 0x2819, 0x281b,
+ 0x281d, 0x281f, 0x2821, 0x2823, 0x2825, 0x2827, 0x2829, 0x282b,
+ 0x282d, 0x282f, 0x2831, 0x2833, 0x2835, 0x2837, 0x2839, 0x283b,
+ 0x283d, 0x283f, 0x2841, 0x2843, 0x2845, 0x2847, 0x2849, 0x284b,
+ 0x284d, 0x284f, 0x2851, 0x2853, 0x2855, 0x2857, 0x2859, 0x285b,
+ 0x285d, 0x285f, 0x2861, 0x2863, 0x2865, 0x2867, 0x2869, 0x286b,
+ 0x286d, 0x286f, 0x2871, 0x2873, 0x2875, 0x2877, 0x2879, 0x287b,
+ 0x287d, 0x287f, 0x2881, 0x2883, 0x2885, 0x2887, 0x2889, 0x288b,
+ 0x288d, 0x288f, 0x2891, 0x2893, 0x2895, 0x2897, 0x2899, 0xffff,
+ 0xffff, 0xffff, 0x289b, 0x289d, 0x289f, 0x28a1, 0x28a3, 0x28a5,
+ 0xffff, 0xffff, 0x28a7, 0x28a9, 0x28ab, 0x28ad, 0x28af, 0x28b1,
+ 0xffff, 0xffff, 0x28b3, 0x28b5, 0x28b7, 0x28b9, 0x28bb, 0x28bd,
+ 0xffff, 0xffff, 0x28bf, 0x28c1, 0x28c3, 0xffff, 0xffff, 0xffff,
+ 0x28c5, 0x28c7, 0x28c9, 0x28cb, 0x28cd, 0x28cf, 0x28d1, 0xffff,
+ 0x28d3, 0x28d5, 0x28d7, 0x28d9, 0x28db, 0x28dd, 0x28df, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x28e1, 0x28e3, 0x28e5, 0x28e7, 0x28e9, 0xffff, 0x28eb,
+ 0x28ed, 0x28ef, 0x28f1, 0x28f3, 0x28f5, 0x28f7, 0x28f9, 0x28fb,
+ 0x28fd, 0x28ff, 0x2901, 0x2903, 0x2905, 0x2907, 0x2909, 0x290b,
+ 0x290d, 0x290f, 0x2911, 0x2913, 0x2915, 0x2918, 0x291a, 0x291c,
+ 0x291f, 0x2921, 0x2924, 0x2926, 0x2928, 0x292a, 0x292c, 0x292e,
+ 0x2931, 0x2933, 0x2935, 0x2937, 0x2939, 0x293b, 0x293d, 0x293f,
+ 0x2941, 0xffff, 0x2943, 0x2945, 0x2947, 0x2949, 0x294b, 0x294d,
+ 0x294f, 0x2951, 0x2954, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x2569, 0x256b, 0x256d, 0x256f, 0x2571, 0x2573, 0x2575, 0x2577,
- 0x2579, 0x257b, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x257d, 0x257f, 0x2581, 0x2583, 0x2585, 0x2587, 0x2589, 0x258b,
- 0x258d, 0x258f, 0x2591, 0x2593, 0x2595, 0x2597, 0x2599, 0x259b,
- 0x259d, 0x259f, 0x25a1, 0x25a3, 0x25a5, 0xffff, 0xffff, 0x25a7,
- 0x25a9, 0x25ab, 0x25ad, 0x25af, 0x25b1, 0x25b3, 0x25b5, 0x25b7,
- 0x25b9, 0x25bb, 0x25bd, 0xffff, 0x25bf, 0x25c1, 0x25c3, 0x25c5,
- 0x25c7, 0x25c9, 0x25cb, 0x25cd, 0x25cf, 0x25d1, 0x25d3, 0x25d5,
- 0x25d7, 0x25d9, 0x25db, 0x25dd, 0x25df, 0x25e1, 0x25e3, 0xffff,
- 0x25e5, 0x25e7, 0x25e9, 0x25eb, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x25ed, 0x25f0, 0x25f3, 0xffff, 0x25f6, 0xffff, 0x25f9, 0x25fc,
- 0x25ff, 0x2602, 0x2605, 0x2608, 0x260b, 0x260e, 0x2611, 0x2614,
- 0x2617, 0x2619, 0x261b, 0x261d, 0x261f, 0x2621, 0x2623, 0x2625,
- 0x2627, 0x2629, 0x262b, 0x262d, 0x262f, 0x2631, 0x2633, 0x2635,
- 0x2637, 0x2639, 0x263b, 0x263d, 0x263f, 0x2641, 0x2643, 0x2645,
- 0x2647, 0x2649, 0x264b, 0x264d, 0x264f, 0x2651, 0x2653, 0x2655,
- 0x2657, 0x2659, 0x265b, 0x265d, 0x265f, 0x2661, 0x2663, 0x2665,
- 0x2667, 0x2669, 0x266b, 0x266d, 0x266f, 0x2671, 0x2673, 0x2675,
- 0x2677, 0x2679, 0x267b, 0x267d, 0x267f, 0x2681, 0x2683, 0x2685,
- 0x2687, 0x2689, 0x268b, 0x268d, 0x268f, 0x2691, 0x2693, 0x2695,
- 0x2697, 0x2699, 0x269b, 0x269d, 0x269f, 0x26a1, 0x26a3, 0x26a5,
- 0x26a7, 0x26a9, 0x26ab, 0x26ad, 0x26af, 0x26b1, 0x26b3, 0x26b5,
- 0x26b7, 0x26b9, 0x26bb, 0x26bd, 0x26bf, 0x26c1, 0x26c3, 0x26c5,
- 0x26c7, 0x26c9, 0x26cb, 0x26cd, 0x26cf, 0x26d1, 0x26d3, 0x26d5,
- 0x26d7, 0x26d9, 0x26db, 0x26dd, 0x26df, 0x26e1, 0x26e3, 0x26e5,
- 0x26e7, 0x26e9, 0x26eb, 0x26ed, 0x26ef, 0x26f1, 0x26f3, 0x26f5,
- 0x26f7, 0x26f9, 0x26fb, 0x26fd, 0x26ff, 0x2701, 0x2704, 0x2707,
- 0x270a, 0x270d, 0x2710, 0x2713, 0x2716, 0xffff, 0xffff, 0xffff,
-
- 0xffff, 0x2719, 0x271b, 0x271d, 0x271f, 0x2721, 0x2723, 0x2725,
- 0x2727, 0x2729, 0x272b, 0x272d, 0x272f, 0x2731, 0x2733, 0x2735,
- 0x2737, 0x2739, 0x273b, 0x273d, 0x273f, 0x2741, 0x2743, 0x2745,
- 0x2747, 0x2749, 0x274b, 0x274d, 0x274f, 0x2751, 0x2753, 0x2755,
- 0x2757, 0x2759, 0x275b, 0x275d, 0x275f, 0x2761, 0x2763, 0x2765,
- 0x2767, 0x2769, 0x276b, 0x276d, 0x276f, 0x2771, 0x2773, 0x2775,
- 0x2777, 0x2779, 0x277b, 0x277d, 0x277f, 0x2781, 0x2783, 0x2785,
- 0x2787, 0x2789, 0x278b, 0x278d, 0x278f, 0x2791, 0x2793, 0x2795,
- 0x2797, 0x2799, 0x279b, 0x279d, 0x279f, 0x27a1, 0x27a3, 0x27a5,
- 0x27a7, 0x27a9, 0x27ab, 0x27ad, 0x27af, 0x27b1, 0x27b3, 0x27b5,
- 0x27b7, 0x27b9, 0x27bb, 0x27bd, 0x27bf, 0x27c1, 0x27c3, 0x27c5,
- 0x27c7, 0x27c9, 0x27cb, 0x27cd, 0x27cf, 0x27d1, 0x27d3, 0x27d5,
- 0x27d7, 0x27d9, 0x27db, 0x27dd, 0x27df, 0x27e1, 0x27e3, 0x27e5,
- 0x27e7, 0x27e9, 0x27eb, 0x27ed, 0x27ef, 0x27f1, 0x27f3, 0x27f5,
- 0x27f7, 0x27f9, 0x27fb, 0x27fd, 0x27ff, 0x2801, 0x2803, 0x2805,
- 0x2807, 0x2809, 0x280b, 0x280d, 0x280f, 0x2811, 0x2813, 0x2815,
- 0x2817, 0x2819, 0x281b, 0x281d, 0x281f, 0x2821, 0x2823, 0x2825,
- 0x2827, 0x2829, 0x282b, 0x282d, 0x282f, 0x2831, 0x2833, 0x2835,
- 0x2837, 0x2839, 0x283b, 0x283d, 0x283f, 0x2841, 0x2843, 0x2845,
- 0x2847, 0x2849, 0x284b, 0x284d, 0x284f, 0x2851, 0x2853, 0x2855,
- 0x2857, 0x2859, 0x285b, 0x285d, 0x285f, 0x2861, 0x2863, 0x2865,
- 0x2867, 0x2869, 0x286b, 0x286d, 0x286f, 0x2871, 0x2873, 0x2875,
- 0x2877, 0x2879, 0x287b, 0x287d, 0x287f, 0x2881, 0x2883, 0x2885,
- 0x2887, 0x2889, 0x288b, 0x288d, 0x288f, 0x2891, 0x2893, 0xffff,
- 0xffff, 0xffff, 0x2895, 0x2897, 0x2899, 0x289b, 0x289d, 0x289f,
- 0xffff, 0xffff, 0x28a1, 0x28a3, 0x28a5, 0x28a7, 0x28a9, 0x28ab,
- 0xffff, 0xffff, 0x28ad, 0x28af, 0x28b1, 0x28b3, 0x28b5, 0x28b7,
- 0xffff, 0xffff, 0x28b9, 0x28bb, 0x28bd, 0xffff, 0xffff, 0xffff,
- 0x28bf, 0x28c1, 0x28c3, 0x28c5, 0x28c7, 0x28c9, 0x28cb, 0xffff,
- 0x28cd, 0x28cf, 0x28d1, 0x28d3, 0x28d5, 0x28d7, 0x28d9, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11253,9 +12143,9 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0x28db, 0xffff, 0x28e0, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x2957, 0xffff, 0x295c, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x28e5, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x2961, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11272,7 +12162,7 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x28ea, 0x28ef,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x2966, 0x296b,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11309,7 +12199,7 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x28f4, 0x28f9, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x2970, 0x2975, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11356,7 +12246,7 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x28fe, 0x2903, 0xffff, 0x2908, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x297a, 0x297f, 0xffff, 0x2984, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11389,7 +12279,7 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0x290d, 0x2912, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x2989, 0x298e, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11406,7 +12296,7 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x2917, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x2993, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11443,8 +12333,8 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x291c, 0x2921,
- 0x2926, 0x292b, 0x2930, 0x2935, 0x293a, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x2998, 0x299d,
+ 0x29a2, 0x29a7, 0x29ac, 0x29b1, 0x29b6, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11455,8 +12345,8 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x293f, 0x2944, 0x2949, 0x294e, 0x2953,
- 0x2958, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x29bb, 0x29c0, 0x29c5, 0x29ca, 0x29cf,
+ 0x29d4, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11465,93 +12355,85 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x295d, 0x295f, 0x2961, 0x2963, 0x2965, 0x2967, 0x2969, 0x296b,
- 0x296d, 0x296f, 0x2971, 0x2973, 0x2975, 0x2977, 0x2979, 0x297b,
- 0x297d, 0x297f, 0x2981, 0x2983, 0x2985, 0x2987, 0x2989, 0x298b,
- 0x298d, 0x298f, 0x2991, 0x2993, 0x2995, 0x2997, 0x2999, 0x299b,
- 0x299d, 0x299f, 0x29a1, 0x29a3, 0x29a5, 0x29a7, 0x29a9, 0x29ab,
- 0x29ad, 0x29af, 0x29b1, 0x29b3, 0x29b5, 0x29b7, 0x29b9, 0x29bb,
- 0x29bd, 0x29bf, 0x29c1, 0x29c3, 0x29c5, 0x29c7, 0x29c9, 0x29cb,
- 0x29cd, 0x29cf, 0x29d1, 0x29d3, 0x29d5, 0x29d7, 0x29d9, 0x29db,
- 0x29dd, 0x29df, 0x29e1, 0x29e3, 0x29e5, 0x29e7, 0x29e9, 0x29eb,
- 0x29ed, 0x29ef, 0x29f1, 0x29f3, 0x29f5, 0x29f7, 0x29f9, 0x29fb,
- 0x29fd, 0x29ff, 0x2a01, 0x2a03, 0x2a05, 0xffff, 0x2a07, 0x2a09,
- 0x2a0b, 0x2a0d, 0x2a0f, 0x2a11, 0x2a13, 0x2a15, 0x2a17, 0x2a19,
- 0x2a1b, 0x2a1d, 0x2a1f, 0x2a21, 0x2a23, 0x2a25, 0x2a27, 0x2a29,
- 0x2a2b, 0x2a2d, 0x2a2f, 0x2a31, 0x2a33, 0x2a35, 0x2a37, 0x2a39,
- 0x2a3b, 0x2a3d, 0x2a3f, 0x2a41, 0x2a43, 0x2a45, 0x2a47, 0x2a49,
- 0x2a4b, 0x2a4d, 0x2a4f, 0x2a51, 0x2a53, 0x2a55, 0x2a57, 0x2a59,
- 0x2a5b, 0x2a5d, 0x2a5f, 0x2a61, 0x2a63, 0x2a65, 0x2a67, 0x2a69,
- 0x2a6b, 0x2a6d, 0x2a6f, 0x2a71, 0x2a73, 0x2a75, 0x2a77, 0x2a79,
- 0x2a7b, 0x2a7d, 0x2a7f, 0x2a81, 0x2a83, 0x2a85, 0x2a87, 0x2a89,
- 0x2a8b, 0x2a8d, 0x2a8f, 0x2a91, 0x2a93, 0xffff, 0x2a95, 0x2a97,
- 0xffff, 0xffff, 0x2a99, 0xffff, 0xffff, 0x2a9b, 0x2a9d, 0xffff,
- 0xffff, 0x2a9f, 0x2aa1, 0x2aa3, 0x2aa5, 0xffff, 0x2aa7, 0x2aa9,
- 0x2aab, 0x2aad, 0x2aaf, 0x2ab1, 0x2ab3, 0x2ab5, 0x2ab7, 0x2ab9,
- 0x2abb, 0x2abd, 0xffff, 0x2abf, 0xffff, 0x2ac1, 0x2ac3, 0x2ac5,
- 0x2ac7, 0x2ac9, 0x2acb, 0x2acd, 0xffff, 0x2acf, 0x2ad1, 0x2ad3,
- 0x2ad5, 0x2ad7, 0x2ad9, 0x2adb, 0x2add, 0x2adf, 0x2ae1, 0x2ae3,
- 0x2ae5, 0x2ae7, 0x2ae9, 0x2aeb, 0x2aed, 0x2aef, 0x2af1, 0x2af3,
- 0x2af5, 0x2af7, 0x2af9, 0x2afb, 0x2afd, 0x2aff, 0x2b01, 0x2b03,
- 0x2b05, 0x2b07, 0x2b09, 0x2b0b, 0x2b0d, 0x2b0f, 0x2b11, 0x2b13,
- 0x2b15, 0x2b17, 0x2b19, 0x2b1b, 0x2b1d, 0x2b1f, 0x2b21, 0x2b23,
- 0x2b25, 0x2b27, 0x2b29, 0x2b2b, 0x2b2d, 0x2b2f, 0x2b31, 0x2b33,
- 0x2b35, 0x2b37, 0x2b39, 0x2b3b, 0x2b3d, 0x2b3f, 0x2b41, 0x2b43,
+ 0x29d9, 0x29db, 0x29dd, 0x29df, 0x29e1, 0x29e3, 0x29e5, 0x29e7,
+ 0x29e9, 0x29eb, 0x29ed, 0x29ef, 0x29f1, 0x29f3, 0x29f5, 0x29f7,
+ 0x29f9, 0x29fb, 0x29fd, 0x29ff, 0x2a01, 0x2a03, 0x2a05, 0x2a07,
+ 0x2a09, 0x2a0b, 0x2a0d, 0x2a0f, 0x2a11, 0x2a13, 0x2a15, 0x2a17,
+ 0x2a19, 0x2a1b, 0x2a1d, 0x2a1f, 0x2a21, 0x2a23, 0x2a25, 0x2a27,
+ 0x2a29, 0x2a2b, 0x2a2d, 0x2a2f, 0x2a31, 0x2a33, 0x2a35, 0x2a37,
+ 0x2a39, 0x2a3b, 0x2a3d, 0x2a3f, 0x2a41, 0x2a43, 0x2a45, 0x2a47,
+ 0x2a49, 0x2a4b, 0x2a4d, 0x2a4f, 0x2a51, 0x2a53, 0x2a55, 0x2a57,
+ 0x2a59, 0x2a5b, 0x2a5d, 0x2a5f, 0x2a61, 0x2a63, 0x2a65, 0x2a67,
+ 0x2a69, 0x2a6b, 0x2a6d, 0x2a6f, 0x2a71, 0x2a73, 0x2a75, 0x2a77,
+ 0x2a79, 0x2a7b, 0x2a7d, 0x2a7f, 0x2a81, 0xffff, 0x2a83, 0x2a85,
+ 0x2a87, 0x2a89, 0x2a8b, 0x2a8d, 0x2a8f, 0x2a91, 0x2a93, 0x2a95,
+ 0x2a97, 0x2a99, 0x2a9b, 0x2a9d, 0x2a9f, 0x2aa1, 0x2aa3, 0x2aa5,
+ 0x2aa7, 0x2aa9, 0x2aab, 0x2aad, 0x2aaf, 0x2ab1, 0x2ab3, 0x2ab5,
+ 0x2ab7, 0x2ab9, 0x2abb, 0x2abd, 0x2abf, 0x2ac1, 0x2ac3, 0x2ac5,
+ 0x2ac7, 0x2ac9, 0x2acb, 0x2acd, 0x2acf, 0x2ad1, 0x2ad3, 0x2ad5,
+ 0x2ad7, 0x2ad9, 0x2adb, 0x2add, 0x2adf, 0x2ae1, 0x2ae3, 0x2ae5,
+ 0x2ae7, 0x2ae9, 0x2aeb, 0x2aed, 0x2aef, 0x2af1, 0x2af3, 0x2af5,
+ 0x2af7, 0x2af9, 0x2afb, 0x2afd, 0x2aff, 0x2b01, 0x2b03, 0x2b05,
+ 0x2b07, 0x2b09, 0x2b0b, 0x2b0d, 0x2b0f, 0xffff, 0x2b11, 0x2b13,
+ 0xffff, 0xffff, 0x2b15, 0xffff, 0xffff, 0x2b17, 0x2b19, 0xffff,
+ 0xffff, 0x2b1b, 0x2b1d, 0x2b1f, 0x2b21, 0xffff, 0x2b23, 0x2b25,
+ 0x2b27, 0x2b29, 0x2b2b, 0x2b2d, 0x2b2f, 0x2b31, 0x2b33, 0x2b35,
+ 0x2b37, 0x2b39, 0xffff, 0x2b3b, 0xffff, 0x2b3d, 0x2b3f, 0x2b41,
+ 0x2b43, 0x2b45, 0x2b47, 0x2b49, 0xffff, 0x2b4b, 0x2b4d, 0x2b4f,
+ 0x2b51, 0x2b53, 0x2b55, 0x2b57, 0x2b59, 0x2b5b, 0x2b5d, 0x2b5f,
+ 0x2b61, 0x2b63, 0x2b65, 0x2b67, 0x2b69, 0x2b6b, 0x2b6d, 0x2b6f,
+ 0x2b71, 0x2b73, 0x2b75, 0x2b77, 0x2b79, 0x2b7b, 0x2b7d, 0x2b7f,
+ 0x2b81, 0x2b83, 0x2b85, 0x2b87, 0x2b89, 0x2b8b, 0x2b8d, 0x2b8f,
+ 0x2b91, 0x2b93, 0x2b95, 0x2b97, 0x2b99, 0x2b9b, 0x2b9d, 0x2b9f,
+ 0x2ba1, 0x2ba3, 0x2ba5, 0x2ba7, 0x2ba9, 0x2bab, 0x2bad, 0x2baf,
+ 0x2bb1, 0x2bb3, 0x2bb5, 0x2bb7, 0x2bb9, 0x2bbb, 0x2bbd, 0x2bbf,
- 0x2b45, 0x2b47, 0x2b49, 0x2b4b, 0x2b4d, 0x2b4f, 0xffff, 0x2b51,
- 0x2b53, 0x2b55, 0x2b57, 0xffff, 0xffff, 0x2b59, 0x2b5b, 0x2b5d,
- 0x2b5f, 0x2b61, 0x2b63, 0x2b65, 0x2b67, 0xffff, 0x2b69, 0x2b6b,
- 0x2b6d, 0x2b6f, 0x2b71, 0x2b73, 0x2b75, 0xffff, 0x2b77, 0x2b79,
- 0x2b7b, 0x2b7d, 0x2b7f, 0x2b81, 0x2b83, 0x2b85, 0x2b87, 0x2b89,
- 0x2b8b, 0x2b8d, 0x2b8f, 0x2b91, 0x2b93, 0x2b95, 0x2b97, 0x2b99,
- 0x2b9b, 0x2b9d, 0x2b9f, 0x2ba1, 0x2ba3, 0x2ba5, 0x2ba7, 0x2ba9,
- 0x2bab, 0x2bad, 0xffff, 0x2baf, 0x2bb1, 0x2bb3, 0x2bb5, 0xffff,
- 0x2bb7, 0x2bb9, 0x2bbb, 0x2bbd, 0x2bbf, 0xffff, 0x2bc1, 0xffff,
- 0xffff, 0xffff, 0x2bc3, 0x2bc5, 0x2bc7, 0x2bc9, 0x2bcb, 0x2bcd,
- 0x2bcf, 0xffff, 0x2bd1, 0x2bd3, 0x2bd5, 0x2bd7, 0x2bd9, 0x2bdb,
- 0x2bdd, 0x2bdf, 0x2be1, 0x2be3, 0x2be5, 0x2be7, 0x2be9, 0x2beb,
- 0x2bed, 0x2bef, 0x2bf1, 0x2bf3, 0x2bf5, 0x2bf7, 0x2bf9, 0x2bfb,
- 0x2bfd, 0x2bff, 0x2c01, 0x2c03, 0x2c05, 0x2c07, 0x2c09, 0x2c0b,
- 0x2c0d, 0x2c0f, 0x2c11, 0x2c13, 0x2c15, 0x2c17, 0x2c19, 0x2c1b,
- 0x2c1d, 0x2c1f, 0x2c21, 0x2c23, 0x2c25, 0x2c27, 0x2c29, 0x2c2b,
- 0x2c2d, 0x2c2f, 0x2c31, 0x2c33, 0x2c35, 0x2c37, 0x2c39, 0x2c3b,
- 0x2c3d, 0x2c3f, 0x2c41, 0x2c43, 0x2c45, 0x2c47, 0x2c49, 0x2c4b,
- 0x2c4d, 0x2c4f, 0x2c51, 0x2c53, 0x2c55, 0x2c57, 0x2c59, 0x2c5b,
- 0x2c5d, 0x2c5f, 0x2c61, 0x2c63, 0x2c65, 0x2c67, 0x2c69, 0x2c6b,
- 0x2c6d, 0x2c6f, 0x2c71, 0x2c73, 0x2c75, 0x2c77, 0x2c79, 0x2c7b,
- 0x2c7d, 0x2c7f, 0x2c81, 0x2c83, 0x2c85, 0x2c87, 0x2c89, 0x2c8b,
- 0x2c8d, 0x2c8f, 0x2c91, 0x2c93, 0x2c95, 0x2c97, 0x2c99, 0x2c9b,
- 0x2c9d, 0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5, 0x2ca7, 0x2ca9, 0x2cab,
- 0x2cad, 0x2caf, 0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7, 0x2cb9, 0x2cbb,
- 0x2cbd, 0x2cbf, 0x2cc1, 0x2cc3, 0x2cc5, 0x2cc7, 0x2cc9, 0x2ccb,
- 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3, 0x2cd5, 0x2cd7, 0x2cd9, 0x2cdb,
- 0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce5, 0x2ce7, 0x2ce9, 0x2ceb,
- 0x2ced, 0x2cef, 0x2cf1, 0x2cf3, 0x2cf5, 0x2cf7, 0x2cf9, 0x2cfb,
- 0x2cfd, 0x2cff, 0x2d01, 0x2d03, 0x2d05, 0x2d07, 0x2d09, 0x2d0b,
- 0x2d0d, 0x2d0f, 0x2d11, 0x2d13, 0x2d15, 0x2d17, 0x2d19, 0x2d1b,
- 0x2d1d, 0x2d1f, 0x2d21, 0x2d23, 0x2d25, 0x2d27, 0x2d29, 0x2d2b,
+ 0x2bc1, 0x2bc3, 0x2bc5, 0x2bc7, 0x2bc9, 0x2bcb, 0xffff, 0x2bcd,
+ 0x2bcf, 0x2bd1, 0x2bd3, 0xffff, 0xffff, 0x2bd5, 0x2bd7, 0x2bd9,
+ 0x2bdb, 0x2bdd, 0x2bdf, 0x2be1, 0x2be3, 0xffff, 0x2be5, 0x2be7,
+ 0x2be9, 0x2beb, 0x2bed, 0x2bef, 0x2bf1, 0xffff, 0x2bf3, 0x2bf5,
+ 0x2bf7, 0x2bf9, 0x2bfb, 0x2bfd, 0x2bff, 0x2c01, 0x2c03, 0x2c05,
+ 0x2c07, 0x2c09, 0x2c0b, 0x2c0d, 0x2c0f, 0x2c11, 0x2c13, 0x2c15,
+ 0x2c17, 0x2c19, 0x2c1b, 0x2c1d, 0x2c1f, 0x2c21, 0x2c23, 0x2c25,
+ 0x2c27, 0x2c29, 0xffff, 0x2c2b, 0x2c2d, 0x2c2f, 0x2c31, 0xffff,
+ 0x2c33, 0x2c35, 0x2c37, 0x2c39, 0x2c3b, 0xffff, 0x2c3d, 0xffff,
+ 0xffff, 0xffff, 0x2c3f, 0x2c41, 0x2c43, 0x2c45, 0x2c47, 0x2c49,
+ 0x2c4b, 0xffff, 0x2c4d, 0x2c4f, 0x2c51, 0x2c53, 0x2c55, 0x2c57,
+ 0x2c59, 0x2c5b, 0x2c5d, 0x2c5f, 0x2c61, 0x2c63, 0x2c65, 0x2c67,
+ 0x2c69, 0x2c6b, 0x2c6d, 0x2c6f, 0x2c71, 0x2c73, 0x2c75, 0x2c77,
+ 0x2c79, 0x2c7b, 0x2c7d, 0x2c7f, 0x2c81, 0x2c83, 0x2c85, 0x2c87,
+ 0x2c89, 0x2c8b, 0x2c8d, 0x2c8f, 0x2c91, 0x2c93, 0x2c95, 0x2c97,
+ 0x2c99, 0x2c9b, 0x2c9d, 0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5, 0x2ca7,
+ 0x2ca9, 0x2cab, 0x2cad, 0x2caf, 0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7,
+ 0x2cb9, 0x2cbb, 0x2cbd, 0x2cbf, 0x2cc1, 0x2cc3, 0x2cc5, 0x2cc7,
+ 0x2cc9, 0x2ccb, 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3, 0x2cd5, 0x2cd7,
+ 0x2cd9, 0x2cdb, 0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce5, 0x2ce7,
+ 0x2ce9, 0x2ceb, 0x2ced, 0x2cef, 0x2cf1, 0x2cf3, 0x2cf5, 0x2cf7,
+ 0x2cf9, 0x2cfb, 0x2cfd, 0x2cff, 0x2d01, 0x2d03, 0x2d05, 0x2d07,
+ 0x2d09, 0x2d0b, 0x2d0d, 0x2d0f, 0x2d11, 0x2d13, 0x2d15, 0x2d17,
+ 0x2d19, 0x2d1b, 0x2d1d, 0x2d1f, 0x2d21, 0x2d23, 0x2d25, 0x2d27,
+ 0x2d29, 0x2d2b, 0x2d2d, 0x2d2f, 0x2d31, 0x2d33, 0x2d35, 0x2d37,
+ 0x2d39, 0x2d3b, 0x2d3d, 0x2d3f, 0x2d41, 0x2d43, 0x2d45, 0x2d47,
+ 0x2d49, 0x2d4b, 0x2d4d, 0x2d4f, 0x2d51, 0x2d53, 0x2d55, 0x2d57,
+ 0x2d59, 0x2d5b, 0x2d5d, 0x2d5f, 0x2d61, 0x2d63, 0x2d65, 0x2d67,
+ 0x2d69, 0x2d6b, 0x2d6d, 0x2d6f, 0x2d71, 0x2d73, 0x2d75, 0x2d77,
+ 0x2d79, 0x2d7b, 0x2d7d, 0x2d7f, 0x2d81, 0x2d83, 0x2d85, 0x2d87,
+ 0x2d89, 0x2d8b, 0x2d8d, 0x2d8f, 0x2d91, 0x2d93, 0x2d95, 0x2d97,
+ 0x2d99, 0x2d9b, 0x2d9d, 0x2d9f, 0x2da1, 0x2da3, 0x2da5, 0x2da7,
- 0x2d2d, 0x2d2f, 0x2d31, 0x2d33, 0x2d35, 0x2d37, 0x2d39, 0x2d3b,
- 0x2d3d, 0x2d3f, 0x2d41, 0x2d43, 0x2d45, 0x2d47, 0x2d49, 0x2d4b,
- 0x2d4d, 0x2d4f, 0x2d51, 0x2d53, 0x2d55, 0x2d57, 0x2d59, 0x2d5b,
- 0x2d5d, 0x2d5f, 0x2d61, 0x2d63, 0x2d65, 0x2d67, 0x2d69, 0x2d6b,
- 0x2d6d, 0x2d6f, 0x2d71, 0x2d73, 0x2d75, 0x2d77, 0x2d79, 0x2d7b,
- 0x2d7d, 0x2d7f, 0x2d81, 0x2d83, 0x2d85, 0x2d87, 0x2d89, 0x2d8b,
- 0x2d8d, 0x2d8f, 0x2d91, 0x2d93, 0x2d95, 0x2d97, 0x2d99, 0x2d9b,
- 0x2d9d, 0x2d9f, 0x2da1, 0x2da3, 0x2da5, 0x2da7, 0x2da9, 0x2dab,
- 0x2dad, 0x2daf, 0x2db1, 0x2db3, 0x2db5, 0x2db7, 0x2db9, 0x2dbb,
- 0x2dbd, 0x2dbf, 0x2dc1, 0x2dc3, 0x2dc5, 0x2dc7, 0x2dc9, 0x2dcb,
- 0x2dcd, 0x2dcf, 0x2dd1, 0x2dd3, 0x2dd5, 0x2dd7, 0x2dd9, 0x2ddb,
- 0x2ddd, 0x2ddf, 0x2de1, 0x2de3, 0x2de5, 0x2de7, 0x2de9, 0x2deb,
- 0x2ded, 0x2def, 0x2df1, 0x2df3, 0x2df5, 0x2df7, 0x2df9, 0x2dfb,
- 0x2dfd, 0x2dff, 0x2e01, 0x2e03, 0x2e05, 0x2e07, 0x2e09, 0x2e0b,
- 0x2e0d, 0x2e0f, 0x2e11, 0x2e13, 0x2e15, 0x2e17, 0x2e19, 0x2e1b,
- 0x2e1d, 0x2e1f, 0x2e21, 0x2e23, 0x2e25, 0x2e27, 0x2e29, 0x2e2b,
- 0x2e2d, 0x2e2f, 0x2e31, 0x2e33, 0x2e35, 0x2e37, 0x2e39, 0x2e3b,
- 0x2e3d, 0x2e3f, 0x2e41, 0x2e43, 0x2e45, 0x2e47, 0x2e49, 0x2e4b,
- 0x2e4d, 0x2e4f, 0x2e51, 0x2e53, 0x2e55, 0x2e57, 0x2e59, 0x2e5b,
- 0x2e5d, 0x2e5f, 0x2e61, 0x2e63, 0x2e65, 0x2e67, 0x2e69, 0x2e6b,
- 0x2e6d, 0x2e6f, 0x2e71, 0x2e73, 0x2e75, 0x2e77, 0xffff, 0xffff,
+ 0x2da9, 0x2dab, 0x2dad, 0x2daf, 0x2db1, 0x2db3, 0x2db5, 0x2db7,
+ 0x2db9, 0x2dbb, 0x2dbd, 0x2dbf, 0x2dc1, 0x2dc3, 0x2dc5, 0x2dc7,
+ 0x2dc9, 0x2dcb, 0x2dcd, 0x2dcf, 0x2dd1, 0x2dd3, 0x2dd5, 0x2dd7,
+ 0x2dd9, 0x2ddb, 0x2ddd, 0x2ddf, 0x2de1, 0x2de3, 0x2de5, 0x2de7,
+ 0x2de9, 0x2deb, 0x2ded, 0x2def, 0x2df1, 0x2df3, 0x2df5, 0x2df7,
+ 0x2df9, 0x2dfb, 0x2dfd, 0x2dff, 0x2e01, 0x2e03, 0x2e05, 0x2e07,
+ 0x2e09, 0x2e0b, 0x2e0d, 0x2e0f, 0x2e11, 0x2e13, 0x2e15, 0x2e17,
+ 0x2e19, 0x2e1b, 0x2e1d, 0x2e1f, 0x2e21, 0x2e23, 0x2e25, 0x2e27,
+ 0x2e29, 0x2e2b, 0x2e2d, 0x2e2f, 0x2e31, 0x2e33, 0x2e35, 0x2e37,
+ 0x2e39, 0x2e3b, 0x2e3d, 0x2e3f, 0x2e41, 0x2e43, 0x2e45, 0x2e47,
+ 0x2e49, 0x2e4b, 0x2e4d, 0x2e4f, 0x2e51, 0x2e53, 0x2e55, 0x2e57,
+ 0x2e59, 0x2e5b, 0x2e5d, 0x2e5f, 0x2e61, 0x2e63, 0x2e65, 0x2e67,
+ 0x2e69, 0x2e6b, 0x2e6d, 0x2e6f, 0x2e71, 0x2e73, 0x2e75, 0x2e77,
0x2e79, 0x2e7b, 0x2e7d, 0x2e7f, 0x2e81, 0x2e83, 0x2e85, 0x2e87,
0x2e89, 0x2e8b, 0x2e8d, 0x2e8f, 0x2e91, 0x2e93, 0x2e95, 0x2e97,
0x2e99, 0x2e9b, 0x2e9d, 0x2e9f, 0x2ea1, 0x2ea3, 0x2ea5, 0x2ea7,
@@ -11559,68 +12441,76 @@ static const unsigned short uc_decomposition_trie[] = {
0x2eb9, 0x2ebb, 0x2ebd, 0x2ebf, 0x2ec1, 0x2ec3, 0x2ec5, 0x2ec7,
0x2ec9, 0x2ecb, 0x2ecd, 0x2ecf, 0x2ed1, 0x2ed3, 0x2ed5, 0x2ed7,
0x2ed9, 0x2edb, 0x2edd, 0x2edf, 0x2ee1, 0x2ee3, 0x2ee5, 0x2ee7,
- 0x2ee9, 0x2eeb, 0x2eed, 0x2eef, 0x2ef1, 0x2ef3, 0x2ef5, 0x2ef7,
- 0x2ef9, 0x2efb, 0x2efd, 0x2eff, 0x2f01, 0x2f03, 0x2f05, 0x2f07,
- 0x2f09, 0x2f0b, 0x2f0d, 0x2f0f, 0x2f11, 0x2f13, 0x2f15, 0x2f17,
- 0x2f19, 0x2f1b, 0x2f1d, 0x2f1f, 0x2f21, 0x2f23, 0x2f25, 0x2f27,
-
- 0x2f29, 0x2f2b, 0x2f2d, 0x2f2f, 0x2f31, 0x2f33, 0x2f35, 0x2f37,
- 0x2f39, 0x2f3b, 0x2f3d, 0x2f3f, 0x2f41, 0x2f43, 0x2f45, 0x2f47,
- 0x2f49, 0x2f4b, 0x2f4d, 0x2f4f, 0x2f51, 0x2f53, 0x2f55, 0x2f57,
- 0x2f59, 0x2f5b, 0x2f5d, 0x2f5f, 0x2f61, 0x2f63, 0x2f65, 0x2f67,
- 0x2f69, 0x2f6b, 0x2f6d, 0x2f6f, 0x2f71, 0x2f73, 0x2f75, 0x2f77,
- 0x2f79, 0x2f7b, 0x2f7d, 0x2f7f, 0x2f81, 0x2f83, 0x2f85, 0x2f87,
- 0x2f89, 0x2f8b, 0x2f8d, 0x2f8f, 0x2f91, 0x2f93, 0x2f95, 0x2f97,
- 0x2f99, 0x2f9b, 0x2f9d, 0x2f9f, 0x2fa1, 0x2fa3, 0x2fa5, 0x2fa7,
- 0x2fa9, 0x2fab, 0x2fad, 0x2faf, 0x2fb1, 0x2fb3, 0x2fb5, 0x2fb7,
- 0x2fb9, 0x2fbb, 0x2fbd, 0x2fbf, 0x2fc1, 0x2fc3, 0x2fc5, 0x2fc7,
- 0x2fc9, 0x2fcb, 0x2fcd, 0x2fcf, 0x2fd1, 0x2fd3, 0x2fd5, 0x2fd7,
- 0x2fd9, 0x2fdb, 0x2fdd, 0x2fdf, 0x2fe1, 0x2fe3, 0x2fe5, 0x2fe7,
- 0x2fe9, 0x2feb, 0x2fed, 0x2fef, 0x2ff1, 0x2ff3, 0x2ff5, 0x2ff7,
- 0x2ff9, 0x2ffb, 0x2ffd, 0x2fff, 0x3001, 0x3003, 0x3005, 0x3007,
- 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3013, 0x3015, 0x3017,
- 0x3019, 0x301b, 0x301d, 0x301f, 0x3021, 0x3023, 0x3025, 0x3027,
- 0x3029, 0x302b, 0x302d, 0x302f, 0x3031, 0x3033, 0x3035, 0x3037,
- 0x3039, 0x303b, 0x303d, 0x303f, 0x3041, 0x3043, 0x3045, 0x3047,
- 0x3049, 0x304b, 0x304d, 0x304f, 0x3051, 0x3053, 0x3055, 0x3057,
- 0x3059, 0x305b, 0x305d, 0x305f, 0x3061, 0x3063, 0x3065, 0x3067,
- 0x3069, 0x306b, 0x306d, 0x306f, 0x3071, 0x3073, 0x3075, 0x3077,
- 0x3079, 0x307b, 0x307d, 0x307f, 0x3081, 0x3083, 0x3085, 0x3087,
- 0x3089, 0x308b, 0x308d, 0x308f, 0x3091, 0x3093, 0x3095, 0x3097,
- 0x3099, 0x309b, 0x309d, 0x309f, 0x30a1, 0x30a3, 0x30a5, 0x30a7,
- 0x30a9, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
- 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0xffff, 0xffff, 0x30c1, 0x30c3,
+ 0x2ee9, 0x2eeb, 0x2eed, 0x2eef, 0x2ef1, 0x2ef3, 0xffff, 0xffff,
+ 0x2ef5, 0x2ef7, 0x2ef9, 0x2efb, 0x2efd, 0x2eff, 0x2f01, 0x2f03,
+ 0x2f05, 0x2f07, 0x2f09, 0x2f0b, 0x2f0d, 0x2f0f, 0x2f11, 0x2f13,
+ 0x2f15, 0x2f17, 0x2f19, 0x2f1b, 0x2f1d, 0x2f1f, 0x2f21, 0x2f23,
+ 0x2f25, 0x2f27, 0x2f29, 0x2f2b, 0x2f2d, 0x2f2f, 0x2f31, 0x2f33,
+ 0x2f35, 0x2f37, 0x2f39, 0x2f3b, 0x2f3d, 0x2f3f, 0x2f41, 0x2f43,
+ 0x2f45, 0x2f47, 0x2f49, 0x2f4b, 0x2f4d, 0x2f4f, 0x2f51, 0x2f53,
+ 0x2f55, 0x2f57, 0x2f59, 0x2f5b, 0x2f5d, 0x2f5f, 0x2f61, 0x2f63,
+ 0x2f65, 0x2f67, 0x2f69, 0x2f6b, 0x2f6d, 0x2f6f, 0x2f71, 0x2f73,
+ 0x2f75, 0x2f77, 0x2f79, 0x2f7b, 0x2f7d, 0x2f7f, 0x2f81, 0x2f83,
+ 0x2f85, 0x2f87, 0x2f89, 0x2f8b, 0x2f8d, 0x2f8f, 0x2f91, 0x2f93,
+ 0x2f95, 0x2f97, 0x2f99, 0x2f9b, 0x2f9d, 0x2f9f, 0x2fa1, 0x2fa3,
+
+ 0x2fa5, 0x2fa7, 0x2fa9, 0x2fab, 0x2fad, 0x2faf, 0x2fb1, 0x2fb3,
+ 0x2fb5, 0x2fb7, 0x2fb9, 0x2fbb, 0x2fbd, 0x2fbf, 0x2fc1, 0x2fc3,
+ 0x2fc5, 0x2fc7, 0x2fc9, 0x2fcb, 0x2fcd, 0x2fcf, 0x2fd1, 0x2fd3,
+ 0x2fd5, 0x2fd7, 0x2fd9, 0x2fdb, 0x2fdd, 0x2fdf, 0x2fe1, 0x2fe3,
+ 0x2fe5, 0x2fe7, 0x2fe9, 0x2feb, 0x2fed, 0x2fef, 0x2ff1, 0x2ff3,
+ 0x2ff5, 0x2ff7, 0x2ff9, 0x2ffb, 0x2ffd, 0x2fff, 0x3001, 0x3003,
+ 0x3005, 0x3007, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3013,
+ 0x3015, 0x3017, 0x3019, 0x301b, 0x301d, 0x301f, 0x3021, 0x3023,
+ 0x3025, 0x3027, 0x3029, 0x302b, 0x302d, 0x302f, 0x3031, 0x3033,
+ 0x3035, 0x3037, 0x3039, 0x303b, 0x303d, 0x303f, 0x3041, 0x3043,
+ 0x3045, 0x3047, 0x3049, 0x304b, 0x304d, 0x304f, 0x3051, 0x3053,
+ 0x3055, 0x3057, 0x3059, 0x305b, 0x305d, 0x305f, 0x3061, 0x3063,
+ 0x3065, 0x3067, 0x3069, 0x306b, 0x306d, 0x306f, 0x3071, 0x3073,
+ 0x3075, 0x3077, 0x3079, 0x307b, 0x307d, 0x307f, 0x3081, 0x3083,
+ 0x3085, 0x3087, 0x3089, 0x308b, 0x308d, 0x308f, 0x3091, 0x3093,
+ 0x3095, 0x3097, 0x3099, 0x309b, 0x309d, 0x309f, 0x30a1, 0x30a3,
+ 0x30a5, 0x30a7, 0x30a9, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3,
+ 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3,
0x30c5, 0x30c7, 0x30c9, 0x30cb, 0x30cd, 0x30cf, 0x30d1, 0x30d3,
0x30d5, 0x30d7, 0x30d9, 0x30db, 0x30dd, 0x30df, 0x30e1, 0x30e3,
0x30e5, 0x30e7, 0x30e9, 0x30eb, 0x30ed, 0x30ef, 0x30f1, 0x30f3,
0x30f5, 0x30f7, 0x30f9, 0x30fb, 0x30fd, 0x30ff, 0x3101, 0x3103,
0x3105, 0x3107, 0x3109, 0x310b, 0x310d, 0x310f, 0x3111, 0x3113,
0x3115, 0x3117, 0x3119, 0x311b, 0x311d, 0x311f, 0x3121, 0x3123,
+ 0x3125, 0x3127, 0x3129, 0x312b, 0x312d, 0x312f, 0x3131, 0x3133,
+ 0x3135, 0x3137, 0x3139, 0x313b, 0xffff, 0xffff, 0x313d, 0x313f,
+ 0x3141, 0x3143, 0x3145, 0x3147, 0x3149, 0x314b, 0x314d, 0x314f,
+ 0x3151, 0x3153, 0x3155, 0x3157, 0x3159, 0x315b, 0x315d, 0x315f,
+ 0x3161, 0x3163, 0x3165, 0x3167, 0x3169, 0x316b, 0x316d, 0x316f,
+ 0x3171, 0x3173, 0x3175, 0x3177, 0x3179, 0x317b, 0x317d, 0x317f,
+ 0x3181, 0x3183, 0x3185, 0x3187, 0x3189, 0x318b, 0x318d, 0x318f,
+ 0x3191, 0x3193, 0x3195, 0x3197, 0x3199, 0x319b, 0x319d, 0x319f,
- 0x3125, 0x3127, 0x3129, 0x312b, 0xffff, 0x312d, 0x312f, 0x3131,
- 0x3133, 0x3135, 0x3137, 0x3139, 0x313b, 0x313d, 0x313f, 0x3141,
- 0x3143, 0x3145, 0x3147, 0x3149, 0x314b, 0x314d, 0x314f, 0x3151,
- 0x3153, 0x3155, 0x3157, 0x3159, 0x315b, 0x315d, 0x315f, 0x3161,
- 0xffff, 0x3163, 0x3165, 0xffff, 0x3167, 0xffff, 0xffff, 0x3169,
- 0xffff, 0x316b, 0x316d, 0x316f, 0x3171, 0x3173, 0x3175, 0x3177,
- 0x3179, 0x317b, 0x317d, 0xffff, 0x317f, 0x3181, 0x3183, 0x3185,
- 0xffff, 0x3187, 0xffff, 0x3189, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0x318b, 0xffff, 0xffff, 0xffff, 0xffff, 0x318d,
- 0xffff, 0x318f, 0xffff, 0x3191, 0xffff, 0x3193, 0x3195, 0x3197,
- 0xffff, 0x3199, 0x319b, 0xffff, 0x319d, 0xffff, 0xffff, 0x319f,
- 0xffff, 0x31a1, 0xffff, 0x31a3, 0xffff, 0x31a5, 0xffff, 0x31a7,
- 0xffff, 0x31a9, 0x31ab, 0xffff, 0x31ad, 0xffff, 0xffff, 0x31af,
- 0x31b1, 0x31b3, 0x31b5, 0xffff, 0x31b7, 0x31b9, 0x31bb, 0x31bd,
- 0x31bf, 0x31c1, 0x31c3, 0xffff, 0x31c5, 0x31c7, 0x31c9, 0x31cb,
- 0xffff, 0x31cd, 0x31cf, 0x31d1, 0x31d3, 0xffff, 0x31d5, 0xffff,
- 0x31d7, 0x31d9, 0x31db, 0x31dd, 0x31df, 0x31e1, 0x31e3, 0x31e5,
- 0x31e7, 0x31e9, 0xffff, 0x31eb, 0x31ed, 0x31ef, 0x31f1, 0x31f3,
- 0x31f5, 0x31f7, 0x31f9, 0x31fb, 0x31fd, 0x31ff, 0x3201, 0x3203,
- 0x3205, 0x3207, 0x3209, 0x320b, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0x320d, 0x320f, 0x3211, 0xffff, 0x3213, 0x3215, 0x3217,
- 0x3219, 0x321b, 0xffff, 0x321d, 0x321f, 0x3221, 0x3223, 0x3225,
- 0x3227, 0x3229, 0x322b, 0x322d, 0x322f, 0x3231, 0x3233, 0x3235,
- 0x3237, 0x3239, 0x323b, 0x323d, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x31a1, 0x31a3, 0x31a5, 0x31a7, 0x31a9, 0x31ab, 0x31ad, 0x31af,
+ 0x31b1, 0x31b3, 0x31b5, 0x31b7, 0x31b9, 0x31bb, 0x31bd, 0x31bf,
+ 0x31c1, 0x31c3, 0x31c5, 0x31c7, 0x31c9, 0x31cb, 0x31cd, 0x31cf,
+ 0x31d1, 0x31d3, 0x31d5, 0x31d7, 0x31d9, 0x31db, 0x31dd, 0x31df,
+ 0x31e1, 0x31e3, 0x31e5, 0x31e7, 0x31e9, 0x31eb, 0x31ed, 0x31ef,
+ 0x31f1, 0x31f3, 0x31f5, 0x31f7, 0x31f9, 0x31fb, 0x31fd, 0x31ff,
+ 0x3201, 0x3203, 0x3205, 0x3207, 0x3209, 0x320b, 0x320d, 0x320f,
+ 0x3211, 0x3213, 0x3215, 0x3217, 0x3219, 0x321b, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11630,25 +12520,58 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x323f, 0x3242, 0x3245, 0x3248, 0x324b, 0x324e, 0x3251, 0x3254,
- 0x3257, 0x325a, 0x325d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x3260, 0x3264, 0x3268, 0x326c, 0x3270, 0x3274, 0x3278, 0x327c,
- 0x3280, 0x3284, 0x3288, 0x328c, 0x3290, 0x3294, 0x3298, 0x329c,
- 0x32a0, 0x32a4, 0x32a8, 0x32ac, 0x32b0, 0x32b4, 0x32b8, 0x32bc,
- 0x32c0, 0x32c4, 0x32c8, 0x32cc, 0x32ce, 0x32d0, 0x32d3, 0xffff,
- 0x32d6, 0x32d8, 0x32da, 0x32dc, 0x32de, 0x32e0, 0x32e2, 0x32e4,
- 0x32e6, 0x32e8, 0x32ea, 0x32ec, 0x32ee, 0x32f0, 0x32f2, 0x32f4,
- 0x32f6, 0x32f8, 0x32fa, 0x32fc, 0x32fe, 0x3300, 0x3302, 0x3304,
- 0x3306, 0x3308, 0x330a, 0x330d, 0x3310, 0x3313, 0x3316, 0x331a,
+ 0x321d, 0x321f, 0x3221, 0x3223, 0xffff, 0x3225, 0x3227, 0x3229,
+ 0x322b, 0x322d, 0x322f, 0x3231, 0x3233, 0x3235, 0x3237, 0x3239,
+ 0x323b, 0x323d, 0x323f, 0x3241, 0x3243, 0x3245, 0x3247, 0x3249,
+ 0x324b, 0x324d, 0x324f, 0x3251, 0x3253, 0x3255, 0x3257, 0x3259,
+ 0xffff, 0x325b, 0x325d, 0xffff, 0x325f, 0xffff, 0xffff, 0x3261,
+ 0xffff, 0x3263, 0x3265, 0x3267, 0x3269, 0x326b, 0x326d, 0x326f,
+ 0x3271, 0x3273, 0x3275, 0xffff, 0x3277, 0x3279, 0x327b, 0x327d,
+ 0xffff, 0x327f, 0xffff, 0x3281, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x3283, 0xffff, 0xffff, 0xffff, 0xffff, 0x3285,
+ 0xffff, 0x3287, 0xffff, 0x3289, 0xffff, 0x328b, 0x328d, 0x328f,
+ 0xffff, 0x3291, 0x3293, 0xffff, 0x3295, 0xffff, 0xffff, 0x3297,
+ 0xffff, 0x3299, 0xffff, 0x329b, 0xffff, 0x329d, 0xffff, 0x329f,
+ 0xffff, 0x32a1, 0x32a3, 0xffff, 0x32a5, 0xffff, 0xffff, 0x32a7,
+ 0x32a9, 0x32ab, 0x32ad, 0xffff, 0x32af, 0x32b1, 0x32b3, 0x32b5,
+ 0x32b7, 0x32b9, 0x32bb, 0xffff, 0x32bd, 0x32bf, 0x32c1, 0x32c3,
+ 0xffff, 0x32c5, 0x32c7, 0x32c9, 0x32cb, 0xffff, 0x32cd, 0xffff,
+ 0x32cf, 0x32d1, 0x32d3, 0x32d5, 0x32d7, 0x32d9, 0x32db, 0x32dd,
+ 0x32df, 0x32e1, 0xffff, 0x32e3, 0x32e5, 0x32e7, 0x32e9, 0x32eb,
+ 0x32ed, 0x32ef, 0x32f1, 0x32f3, 0x32f5, 0x32f7, 0x32f9, 0x32fb,
+ 0x32fd, 0x32ff, 0x3301, 0x3303, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x3305, 0x3307, 0x3309, 0xffff, 0x330b, 0x330d, 0x330f,
+ 0x3311, 0x3313, 0xffff, 0x3315, 0x3317, 0x3319, 0x331b, 0x331d,
+ 0x331f, 0x3321, 0x3323, 0x3325, 0x3327, 0x3329, 0x332b, 0x332d,
+ 0x332f, 0x3331, 0x3333, 0x3335, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0x331d, 0x3320, 0x3323, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+
+ 0x3337, 0x333a, 0x333d, 0x3340, 0x3343, 0x3346, 0x3349, 0x334c,
+ 0x334f, 0x3352, 0x3355, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x3358, 0x335c, 0x3360, 0x3364, 0x3368, 0x336c, 0x3370, 0x3374,
+ 0x3378, 0x337c, 0x3380, 0x3384, 0x3388, 0x338c, 0x3390, 0x3394,
+ 0x3398, 0x339c, 0x33a0, 0x33a4, 0x33a8, 0x33ac, 0x33b0, 0x33b4,
+ 0x33b8, 0x33bc, 0x33c0, 0x33c4, 0x33c6, 0x33c8, 0x33cb, 0xffff,
+ 0x33ce, 0x33d0, 0x33d2, 0x33d4, 0x33d6, 0x33d8, 0x33da, 0x33dc,
+ 0x33de, 0x33e0, 0x33e2, 0x33e4, 0x33e6, 0x33e8, 0x33ea, 0x33ec,
+ 0x33ee, 0x33f0, 0x33f2, 0x33f4, 0x33f6, 0x33f8, 0x33fa, 0x33fc,
+ 0x33fe, 0x3400, 0x3402, 0x3405, 0x3408, 0x340b, 0x340e, 0x3412,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0x3415, 0x3418, 0x341b, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x3326, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x341e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11663,17 +12586,17 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x3329, 0x332c, 0x332f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x3421, 0x3424, 0x3427, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x3331, 0x3333, 0x3335, 0x3337, 0x3339, 0x333b, 0x333d, 0x333f,
- 0x3341, 0x3343, 0x3345, 0x3347, 0x3349, 0x334b, 0x334d, 0x334f,
- 0x3351, 0x3353, 0x3355, 0x3357, 0x3359, 0x335b, 0x335d, 0x335f,
- 0x3361, 0x3363, 0x3365, 0x3367, 0x3369, 0x336b, 0x336d, 0x336f,
- 0x3371, 0x3373, 0x3375, 0x3377, 0x3379, 0x337b, 0x337d, 0x337f,
- 0x3381, 0x3383, 0x3385, 0x3387, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x3389, 0x338d, 0x3391, 0x3395, 0x3399, 0x339d, 0x33a1, 0x33a5,
- 0x33a9, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x33ad, 0x33af, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x3429, 0x342b, 0x342d, 0x342f, 0x3431, 0x3433, 0x3435, 0x3437,
+ 0x3439, 0x343b, 0x343d, 0x343f, 0x3441, 0x3443, 0x3445, 0x3447,
+ 0x3449, 0x344b, 0x344d, 0x344f, 0x3451, 0x3453, 0x3455, 0x3457,
+ 0x3459, 0x345b, 0x345d, 0x345f, 0x3461, 0x3463, 0x3465, 0x3467,
+ 0x3469, 0x346b, 0x346d, 0x346f, 0x3471, 0x3473, 0x3475, 0x3477,
+ 0x3479, 0x347b, 0x347d, 0x347f, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x3481, 0x3485, 0x3489, 0x348d, 0x3491, 0x3495, 0x3499, 0x349d,
+ 0x34a1, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x34a5, 0x34a7, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11726,79 +12649,79 @@ static const unsigned short uc_decomposition_trie[] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x33b1, 0x33b3, 0x33b5, 0x33b7, 0x33b9, 0x33bb, 0x33bd, 0x33bf,
- 0x33c1, 0x33c3, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x34a9, 0x34ab, 0x34ad, 0x34af, 0x34b1, 0x34b3, 0x34b5, 0x34b7,
+ 0x34b9, 0x34bb, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x33c5, 0x33c7, 0x33c9, 0x33cb, 0x33ce, 0x33d0, 0x33d2, 0x33d4,
- 0x33d6, 0x33d8, 0x33da, 0x33dc, 0x33de, 0x33e0, 0x33e3, 0x33e5,
- 0x33e7, 0x33e9, 0x33eb, 0x33ee, 0x33f0, 0x33f2, 0x33f4, 0x33f7,
- 0x33f9, 0x33fb, 0x33fd, 0x33ff, 0x3401, 0x3404, 0x3406, 0x3408,
- 0x340a, 0x340c, 0x340e, 0x3410, 0x3412, 0x3414, 0x3416, 0x3418,
- 0x341a, 0x341c, 0x341e, 0x3420, 0x3422, 0x3424, 0x3426, 0x3428,
- 0x342a, 0x342c, 0x342e, 0x3430, 0x3432, 0x3435, 0x3437, 0x3439,
- 0x343b, 0x343e, 0x3440, 0x3442, 0x3444, 0x3446, 0x3448, 0x344a,
- 0x344c, 0x344e, 0x3450, 0x3452, 0x3454, 0x3456, 0x3458, 0x345a,
- 0x345c, 0x345e, 0x3460, 0x3462, 0x3464, 0x3466, 0x3468, 0x346a,
- 0x346c, 0x346e, 0x3470, 0x3472, 0x3474, 0x3476, 0x3478, 0x347a,
- 0x347c, 0x347e, 0x3481, 0x3483, 0x3485, 0x3487, 0x3489, 0x348b,
- 0x348d, 0x3490, 0x3493, 0x3495, 0x3497, 0x3499, 0x349b, 0x349d,
- 0x349f, 0x34a1, 0x34a3, 0x34a5, 0x34a7, 0x34aa, 0x34ac, 0x34ae,
- 0x34b0, 0x34b2, 0x34b5, 0x34b7, 0x34b9, 0x34bb, 0x34bd, 0x34bf,
- 0x34c1, 0x34c3, 0x34c5, 0x34c7, 0x34ca, 0x34cc, 0x34cf, 0x34d1,
- 0x34d3, 0x34d5, 0x34d7, 0x34d9, 0x34db, 0x34dd, 0x34df, 0x34e1,
- 0x34e3, 0x34e5, 0x34e8, 0x34ea, 0x34ec, 0x34ee, 0x34f0, 0x34f2,
- 0x34f5, 0x34f7, 0x34fa, 0x34fd, 0x34ff, 0x3501, 0x3503, 0x3505,
- 0x3508, 0x350b, 0x350d, 0x350f, 0x3511, 0x3513, 0x3515, 0x3517,
- 0x3519, 0x351b, 0x351d, 0x351f, 0x3521, 0x3524, 0x3526, 0x3528,
- 0x352a, 0x352c, 0x352e, 0x3530, 0x3532, 0x3534, 0x3536, 0x3538,
- 0x353a, 0x353c, 0x353e, 0x3540, 0x3542, 0x3544, 0x3546, 0x3548,
- 0x354a, 0x354d, 0x354f, 0x3551, 0x3553, 0x3555, 0x3557, 0x355a,
- 0x355c, 0x355e, 0x3560, 0x3562, 0x3564, 0x3566, 0x3568, 0x356a,
- 0x356c, 0x356e, 0x3570, 0x3573, 0x3575, 0x3577, 0x3579, 0x357b,
- 0x357d, 0x357f, 0x3581, 0x3583, 0x3585, 0x3587, 0x3589, 0x358b,
- 0x358d, 0x358f, 0x3591, 0x3593, 0x3595, 0x3597, 0x359a, 0x359c,
- 0x359e, 0x35a0, 0x35a2, 0x35a4, 0x35a7, 0x35a9, 0x35ab, 0x35ad,
- 0x35af, 0x35b1, 0x35b3, 0x35b5, 0x35b7, 0x35ba, 0x35bc, 0x35be,
- 0x35c0, 0x35c3, 0x35c5, 0x35c7, 0x35c9, 0x35cb, 0x35cd, 0x35cf,
- 0x35d2, 0x35d5, 0x35d8, 0x35da, 0x35dd, 0x35df, 0x35e1, 0x35e3,
+ 0x34bd, 0x34bf, 0x34c1, 0x34c3, 0x34c6, 0x34c8, 0x34ca, 0x34cc,
+ 0x34ce, 0x34d0, 0x34d2, 0x34d4, 0x34d6, 0x34d8, 0x34db, 0x34dd,
+ 0x34df, 0x34e1, 0x34e3, 0x34e6, 0x34e8, 0x34ea, 0x34ec, 0x34ef,
+ 0x34f1, 0x34f3, 0x34f5, 0x34f7, 0x34f9, 0x34fc, 0x34fe, 0x3500,
+ 0x3502, 0x3504, 0x3506, 0x3508, 0x350a, 0x350c, 0x350e, 0x3510,
+ 0x3512, 0x3514, 0x3516, 0x3518, 0x351a, 0x351c, 0x351e, 0x3520,
+ 0x3522, 0x3524, 0x3526, 0x3528, 0x352a, 0x352d, 0x352f, 0x3531,
+ 0x3533, 0x3536, 0x3538, 0x353a, 0x353c, 0x353e, 0x3540, 0x3542,
+ 0x3544, 0x3546, 0x3548, 0x354a, 0x354c, 0x354e, 0x3550, 0x3552,
+ 0x3554, 0x3556, 0x3558, 0x355a, 0x355c, 0x355e, 0x3560, 0x3562,
+ 0x3564, 0x3566, 0x3568, 0x356a, 0x356c, 0x356e, 0x3570, 0x3572,
+ 0x3574, 0x3576, 0x3579, 0x357b, 0x357d, 0x357f, 0x3581, 0x3583,
+ 0x3585, 0x3588, 0x358b, 0x358d, 0x358f, 0x3591, 0x3593, 0x3595,
+ 0x3597, 0x3599, 0x359b, 0x359d, 0x359f, 0x35a2, 0x35a4, 0x35a6,
+ 0x35a8, 0x35aa, 0x35ad, 0x35af, 0x35b1, 0x35b3, 0x35b5, 0x35b7,
+ 0x35b9, 0x35bb, 0x35bd, 0x35bf, 0x35c2, 0x35c4, 0x35c7, 0x35c9,
+ 0x35cb, 0x35cd, 0x35cf, 0x35d1, 0x35d3, 0x35d5, 0x35d7, 0x35d9,
+ 0x35db, 0x35dd, 0x35e0, 0x35e2, 0x35e4, 0x35e6, 0x35e8, 0x35ea,
+ 0x35ed, 0x35ef, 0x35f2, 0x35f5, 0x35f7, 0x35f9, 0x35fb, 0x35fd,
+ 0x3600, 0x3603, 0x3605, 0x3607, 0x3609, 0x360b, 0x360d, 0x360f,
+ 0x3611, 0x3613, 0x3615, 0x3617, 0x3619, 0x361c, 0x361e, 0x3620,
+ 0x3622, 0x3624, 0x3626, 0x3628, 0x362a, 0x362c, 0x362e, 0x3630,
+ 0x3632, 0x3634, 0x3636, 0x3638, 0x363a, 0x363c, 0x363e, 0x3640,
+ 0x3642, 0x3645, 0x3647, 0x3649, 0x364b, 0x364d, 0x364f, 0x3652,
+ 0x3654, 0x3656, 0x3658, 0x365a, 0x365c, 0x365e, 0x3660, 0x3662,
+ 0x3664, 0x3666, 0x3668, 0x366b, 0x366d, 0x366f, 0x3671, 0x3673,
+ 0x3675, 0x3677, 0x3679, 0x367b, 0x367d, 0x367f, 0x3681, 0x3683,
+ 0x3685, 0x3687, 0x3689, 0x368b, 0x368d, 0x368f, 0x3692, 0x3694,
+ 0x3696, 0x3698, 0x369a, 0x369c, 0x369f, 0x36a1, 0x36a3, 0x36a5,
+ 0x36a7, 0x36a9, 0x36ab, 0x36ad, 0x36af, 0x36b2, 0x36b4, 0x36b6,
+ 0x36b8, 0x36bb, 0x36bd, 0x36bf, 0x36c1, 0x36c3, 0x36c5, 0x36c7,
+ 0x36ca, 0x36cd, 0x36d0, 0x36d2, 0x36d5, 0x36d7, 0x36d9, 0x36db,
- 0x35e5, 0x35e7, 0x35e9, 0x35eb, 0x35ed, 0x35ef, 0x35f1, 0x35f4,
- 0x35f6, 0x35f8, 0x35fa, 0x35fc, 0x35fe, 0x3600, 0x3603, 0x3605,
- 0x3607, 0x360a, 0x360d, 0x360f, 0x3611, 0x3613, 0x3615, 0x3617,
- 0x3619, 0x361b, 0x361d, 0x361f, 0x3622, 0x3624, 0x3627, 0x3629,
- 0x362c, 0x362e, 0x3630, 0x3632, 0x3635, 0x3637, 0x3639, 0x363c,
- 0x363f, 0x3641, 0x3643, 0x3645, 0x3647, 0x3649, 0x364b, 0x364d,
- 0x364f, 0x3651, 0x3653, 0x3655, 0x3657, 0x3659, 0x365c, 0x365e,
- 0x3661, 0x3663, 0x3666, 0x3668, 0x366b, 0x366e, 0x3671, 0x3673,
- 0x3675, 0x3677, 0x367a, 0x367d, 0x3680, 0x3683, 0x3685, 0x3687,
- 0x3689, 0x368b, 0x368d, 0x368f, 0x3691, 0x3693, 0x3696, 0x3698,
- 0x369a, 0x369c, 0x369e, 0x36a1, 0x36a3, 0x36a6, 0x36a9, 0x36ab,
- 0x36ad, 0x36af, 0x36b1, 0x36b3, 0x36b5, 0x36b8, 0x36bb, 0x36be,
- 0x36c0, 0x36c2, 0x36c5, 0x36c7, 0x36c9, 0x36cb, 0x36ce, 0x36d0,
- 0x36d2, 0x36d4, 0x36d6, 0x36d8, 0x36db, 0x36dd, 0x36df, 0x36e1,
- 0x36e3, 0x36e5, 0x36e7, 0x36ea, 0x36ed, 0x36ef, 0x36f2, 0x36f4,
- 0x36f7, 0x36f9, 0x36fb, 0x36fd, 0x3700, 0x3703, 0x3705, 0x3708,
- 0x370a, 0x370d, 0x370f, 0x3711, 0x3713, 0x3715, 0x3717, 0x3719,
- 0x371c, 0x371f, 0x3722, 0x3725, 0x3727, 0x3729, 0x372b, 0x372d,
- 0x372f, 0x3731, 0x3733, 0x3735, 0x3737, 0x3739, 0x373b, 0x373d,
- 0x3740, 0x3742, 0x3744, 0x3746, 0x3748, 0x374a, 0x374c, 0x374e,
- 0x3750, 0x3752, 0x3754, 0x3756, 0x3758, 0x375b, 0x375e, 0x3761,
- 0x3763, 0x3765, 0x3767, 0x3769, 0x376c, 0x376e, 0x3771, 0x3773,
- 0x3775, 0x3778, 0x377b, 0x377d, 0x377f, 0x3781, 0x3783, 0x3785,
- 0x3787, 0x3789, 0x378b, 0x378d, 0x378f, 0x3791, 0x3793, 0x3795,
- 0x3797, 0x3799, 0x379b, 0x379d, 0x379f, 0x37a1, 0x37a4, 0x37a6,
- 0x37a8, 0x37aa, 0x37ac, 0x37ae, 0x37b1, 0x37b4, 0x37b6, 0x37b8,
- 0x37ba, 0x37bc, 0x37be, 0x37c0, 0x37c3, 0x37c5, 0x37c7, 0x37c9,
- 0x37cb, 0x37ce, 0x37d1, 0x37d3, 0x37d5, 0x37d7, 0x37da, 0x37dc,
- 0x37de, 0x37e1, 0x37e4, 0x37e6, 0x37e8, 0x37ea, 0x37ed, 0x37ef,
- 0x37f1, 0x37f3, 0x37f5, 0x37f7, 0x37f9, 0x37fb, 0x37fe, 0x3800,
- 0x3802, 0x3804, 0x3807, 0x3809, 0x380b, 0x380d, 0x380f, 0x3812,
- 0x3815, 0x3817, 0x3819, 0x381b, 0x381e, 0x3820, 0x3823, 0x3825,
+ 0x36dd, 0x36df, 0x36e1, 0x36e3, 0x36e5, 0x36e7, 0x36e9, 0x36ec,
+ 0x36ee, 0x36f0, 0x36f2, 0x36f4, 0x36f6, 0x36f8, 0x36fb, 0x36fd,
+ 0x36ff, 0x3702, 0x3705, 0x3707, 0x3709, 0x370b, 0x370d, 0x370f,
+ 0x3711, 0x3713, 0x3715, 0x3717, 0x371a, 0x371c, 0x371f, 0x3721,
+ 0x3724, 0x3726, 0x3728, 0x372a, 0x372d, 0x372f, 0x3731, 0x3734,
+ 0x3737, 0x3739, 0x373b, 0x373d, 0x373f, 0x3741, 0x3743, 0x3745,
+ 0x3747, 0x3749, 0x374b, 0x374d, 0x374f, 0x3751, 0x3754, 0x3756,
+ 0x3759, 0x375b, 0x375e, 0x3760, 0x3763, 0x3766, 0x3769, 0x376b,
+ 0x376d, 0x376f, 0x3772, 0x3775, 0x3778, 0x377b, 0x377d, 0x377f,
+ 0x3781, 0x3783, 0x3785, 0x3787, 0x3789, 0x378b, 0x378e, 0x3790,
+ 0x3792, 0x3794, 0x3796, 0x3799, 0x379b, 0x379e, 0x37a1, 0x37a3,
+ 0x37a5, 0x37a7, 0x37a9, 0x37ab, 0x37ad, 0x37b0, 0x37b3, 0x37b6,
+ 0x37b8, 0x37ba, 0x37bd, 0x37bf, 0x37c1, 0x37c3, 0x37c6, 0x37c8,
+ 0x37ca, 0x37cc, 0x37ce, 0x37d0, 0x37d3, 0x37d5, 0x37d7, 0x37d9,
+ 0x37db, 0x37dd, 0x37df, 0x37e2, 0x37e5, 0x37e7, 0x37ea, 0x37ec,
+ 0x37ef, 0x37f1, 0x37f3, 0x37f5, 0x37f8, 0x37fb, 0x37fd, 0x3800,
+ 0x3802, 0x3805, 0x3807, 0x3809, 0x380b, 0x380d, 0x380f, 0x3811,
+ 0x3814, 0x3817, 0x381a, 0x381d, 0x381f, 0x3821, 0x3823, 0x3825,
+ 0x3827, 0x3829, 0x382b, 0x382d, 0x382f, 0x3831, 0x3833, 0x3835,
+ 0x3838, 0x383a, 0x383c, 0x383e, 0x3840, 0x3842, 0x3844, 0x3846,
+ 0x3848, 0x384a, 0x384c, 0x384e, 0x3850, 0x3853, 0x3856, 0x3859,
+ 0x385b, 0x385d, 0x385f, 0x3861, 0x3864, 0x3866, 0x3869, 0x386b,
+ 0x386d, 0x3870, 0x3873, 0x3875, 0x3877, 0x3879, 0x387b, 0x387d,
+ 0x387f, 0x3881, 0x3883, 0x3885, 0x3887, 0x3889, 0x388b, 0x388d,
+ 0x388f, 0x3891, 0x3893, 0x3895, 0x3897, 0x3899, 0x389c, 0x389e,
+ 0x38a0, 0x38a2, 0x38a4, 0x38a6, 0x38a9, 0x38ac, 0x38ae, 0x38b0,
+ 0x38b2, 0x38b4, 0x38b6, 0x38b8, 0x38bb, 0x38bd, 0x38bf, 0x38c1,
+ 0x38c3, 0x38c6, 0x38c9, 0x38cb, 0x38cd, 0x38cf, 0x38d2, 0x38d4,
+ 0x38d6, 0x38d9, 0x38dc, 0x38de, 0x38e0, 0x38e2, 0x38e5, 0x38e7,
+ 0x38e9, 0x38eb, 0x38ed, 0x38ef, 0x38f1, 0x38f3, 0x38f6, 0x38f8,
+ 0x38fa, 0x38fc, 0x38ff, 0x3901, 0x3903, 0x3905, 0x3907, 0x390a,
+ 0x390d, 0x390f, 0x3911, 0x3913, 0x3916, 0x3918, 0x391b, 0x391d,
- 0x3827, 0x3829, 0x382c, 0x382e, 0x3830, 0x3832, 0x3834, 0x3836,
- 0x3838, 0x383a, 0x383d, 0x383f, 0x3841, 0x3843, 0x3845, 0x3847,
- 0x3849, 0x384c, 0x384e, 0x3851, 0x3854, 0x3857, 0x3859, 0x385b,
- 0x385d, 0x385f, 0x3861, 0x3863, 0x3865, 0x3867, 0xffff, 0xffff,
+ 0x391f, 0x3921, 0x3924, 0x3926, 0x3928, 0x392a, 0x392c, 0x392e,
+ 0x3930, 0x3932, 0x3935, 0x3937, 0x3939, 0x393b, 0x393d, 0x393f,
+ 0x3941, 0x3944, 0x3946, 0x3949, 0x394c, 0x394f, 0x3951, 0x3953,
+ 0x3955, 0x3957, 0x3959, 0x395b, 0x395d, 0x395f, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
@@ -11831,12 +12754,12 @@ static const unsigned short uc_decomposition_trie[] = {
#define GET_DECOMPOSITION_INDEX(ucs4) \
(ucs4 < 0x3400 \
- ? (uc_decomposition_trie[uc_decomposition_trie[ucs4>>4] + (ucs4 & 0xf)]) \
- : (ucs4 < 0x30000 \
- ? uc_decomposition_trie[uc_decomposition_trie[((ucs4 - 0x3400)>>8) + 0x340] + (ucs4 & 0xff)] \
- : 0xffff))
+ ? (uc_decomposition_trie[uc_decomposition_trie[ucs4 >> 4] + (ucs4 & 0xf)]) \
+ : ucs4 < 0x30000 \
+ ? uc_decomposition_trie[uc_decomposition_trie[((ucs4 - 0x3400) >> 8) + 0x340] + (ucs4 & 0xff)] \
+ : 0xffff)
-static const unsigned short uc_decomposition_map[] = {
+static constexpr unsigned short uc_decomposition_map[] = {
0x103, 0x20, 0x210, 0x20, 0x308, 0x109, 0x61, 0x210,
0x20, 0x304, 0x109, 0x32, 0x109, 0x33, 0x210, 0x20,
0x301, 0x110, 0x3bc, 0x210, 0x20, 0x327, 0x109, 0x31,
@@ -12668,677 +13591,678 @@ static const unsigned short uc_decomposition_map[] = {
0x310, 0x32, 0x37, 0x65e5, 0x310, 0x32, 0x38, 0x65e5,
0x310, 0x32, 0x39, 0x65e5, 0x310, 0x33, 0x30, 0x65e5,
0x310, 0x33, 0x31, 0x65e5, 0x30f, 0x67, 0x61, 0x6c,
- 0x109, 0x44a, 0x109, 0x44c, 0x109, 0xa76f, 0x109, 0x126,
- 0x109, 0x153, 0x109, 0xa727, 0x109, 0xab37, 0x109, 0x26b,
- 0x109, 0xab52, 0x109, 0x28d, 0x101, 0x8c48, 0x101, 0x66f4,
- 0x101, 0x8eca, 0x101, 0x8cc8, 0x101, 0x6ed1, 0x101, 0x4e32,
- 0x101, 0x53e5, 0x101, 0x9f9c, 0x101, 0x9f9c, 0x101, 0x5951,
- 0x101, 0x91d1, 0x101, 0x5587, 0x101, 0x5948, 0x101, 0x61f6,
- 0x101, 0x7669, 0x101, 0x7f85, 0x101, 0x863f, 0x101, 0x87ba,
- 0x101, 0x88f8, 0x101, 0x908f, 0x101, 0x6a02, 0x101, 0x6d1b,
- 0x101, 0x70d9, 0x101, 0x73de, 0x101, 0x843d, 0x101, 0x916a,
- 0x101, 0x99f1, 0x101, 0x4e82, 0x101, 0x5375, 0x101, 0x6b04,
- 0x101, 0x721b, 0x101, 0x862d, 0x101, 0x9e1e, 0x101, 0x5d50,
- 0x101, 0x6feb, 0x101, 0x85cd, 0x101, 0x8964, 0x101, 0x62c9,
- 0x101, 0x81d8, 0x101, 0x881f, 0x101, 0x5eca, 0x101, 0x6717,
- 0x101, 0x6d6a, 0x101, 0x72fc, 0x101, 0x90ce, 0x101, 0x4f86,
- 0x101, 0x51b7, 0x101, 0x52de, 0x101, 0x64c4, 0x101, 0x6ad3,
- 0x101, 0x7210, 0x101, 0x76e7, 0x101, 0x8001, 0x101, 0x8606,
- 0x101, 0x865c, 0x101, 0x8def, 0x101, 0x9732, 0x101, 0x9b6f,
- 0x101, 0x9dfa, 0x101, 0x788c, 0x101, 0x797f, 0x101, 0x7da0,
- 0x101, 0x83c9, 0x101, 0x9304, 0x101, 0x9e7f, 0x101, 0x8ad6,
- 0x101, 0x58df, 0x101, 0x5f04, 0x101, 0x7c60, 0x101, 0x807e,
- 0x101, 0x7262, 0x101, 0x78ca, 0x101, 0x8cc2, 0x101, 0x96f7,
- 0x101, 0x58d8, 0x101, 0x5c62, 0x101, 0x6a13, 0x101, 0x6dda,
- 0x101, 0x6f0f, 0x101, 0x7d2f, 0x101, 0x7e37, 0x101, 0x964b,
- 0x101, 0x52d2, 0x101, 0x808b, 0x101, 0x51dc, 0x101, 0x51cc,
- 0x101, 0x7a1c, 0x101, 0x7dbe, 0x101, 0x83f1, 0x101, 0x9675,
- 0x101, 0x8b80, 0x101, 0x62cf, 0x101, 0x6a02, 0x101, 0x8afe,
- 0x101, 0x4e39, 0x101, 0x5be7, 0x101, 0x6012, 0x101, 0x7387,
- 0x101, 0x7570, 0x101, 0x5317, 0x101, 0x78fb, 0x101, 0x4fbf,
- 0x101, 0x5fa9, 0x101, 0x4e0d, 0x101, 0x6ccc, 0x101, 0x6578,
- 0x101, 0x7d22, 0x101, 0x53c3, 0x101, 0x585e, 0x101, 0x7701,
- 0x101, 0x8449, 0x101, 0x8aaa, 0x101, 0x6bba, 0x101, 0x8fb0,
- 0x101, 0x6c88, 0x101, 0x62fe, 0x101, 0x82e5, 0x101, 0x63a0,
- 0x101, 0x7565, 0x101, 0x4eae, 0x101, 0x5169, 0x101, 0x51c9,
- 0x101, 0x6881, 0x101, 0x7ce7, 0x101, 0x826f, 0x101, 0x8ad2,
- 0x101, 0x91cf, 0x101, 0x52f5, 0x101, 0x5442, 0x101, 0x5973,
- 0x101, 0x5eec, 0x101, 0x65c5, 0x101, 0x6ffe, 0x101, 0x792a,
- 0x101, 0x95ad, 0x101, 0x9a6a, 0x101, 0x9e97, 0x101, 0x9ece,
- 0x101, 0x529b, 0x101, 0x66c6, 0x101, 0x6b77, 0x101, 0x8f62,
- 0x101, 0x5e74, 0x101, 0x6190, 0x101, 0x6200, 0x101, 0x649a,
- 0x101, 0x6f23, 0x101, 0x7149, 0x101, 0x7489, 0x101, 0x79ca,
- 0x101, 0x7df4, 0x101, 0x806f, 0x101, 0x8f26, 0x101, 0x84ee,
- 0x101, 0x9023, 0x101, 0x934a, 0x101, 0x5217, 0x101, 0x52a3,
- 0x101, 0x54bd, 0x101, 0x70c8, 0x101, 0x88c2, 0x101, 0x8aaa,
- 0x101, 0x5ec9, 0x101, 0x5ff5, 0x101, 0x637b, 0x101, 0x6bae,
- 0x101, 0x7c3e, 0x101, 0x7375, 0x101, 0x4ee4, 0x101, 0x56f9,
- 0x101, 0x5be7, 0x101, 0x5dba, 0x101, 0x601c, 0x101, 0x73b2,
- 0x101, 0x7469, 0x101, 0x7f9a, 0x101, 0x8046, 0x101, 0x9234,
- 0x101, 0x96f6, 0x101, 0x9748, 0x101, 0x9818, 0x101, 0x4f8b,
- 0x101, 0x79ae, 0x101, 0x91b4, 0x101, 0x96b8, 0x101, 0x60e1,
- 0x101, 0x4e86, 0x101, 0x50da, 0x101, 0x5bee, 0x101, 0x5c3f,
- 0x101, 0x6599, 0x101, 0x6a02, 0x101, 0x71ce, 0x101, 0x7642,
- 0x101, 0x84fc, 0x101, 0x907c, 0x101, 0x9f8d, 0x101, 0x6688,
- 0x101, 0x962e, 0x101, 0x5289, 0x101, 0x677b, 0x101, 0x67f3,
- 0x101, 0x6d41, 0x101, 0x6e9c, 0x101, 0x7409, 0x101, 0x7559,
- 0x101, 0x786b, 0x101, 0x7d10, 0x101, 0x985e, 0x101, 0x516d,
- 0x101, 0x622e, 0x101, 0x9678, 0x101, 0x502b, 0x101, 0x5d19,
- 0x101, 0x6dea, 0x101, 0x8f2a, 0x101, 0x5f8b, 0x101, 0x6144,
- 0x101, 0x6817, 0x101, 0x7387, 0x101, 0x9686, 0x101, 0x5229,
- 0x101, 0x540f, 0x101, 0x5c65, 0x101, 0x6613, 0x101, 0x674e,
- 0x101, 0x68a8, 0x101, 0x6ce5, 0x101, 0x7406, 0x101, 0x75e2,
- 0x101, 0x7f79, 0x101, 0x88cf, 0x101, 0x88e1, 0x101, 0x91cc,
- 0x101, 0x96e2, 0x101, 0x533f, 0x101, 0x6eba, 0x101, 0x541d,
- 0x101, 0x71d0, 0x101, 0x7498, 0x101, 0x85fa, 0x101, 0x96a3,
- 0x101, 0x9c57, 0x101, 0x9e9f, 0x101, 0x6797, 0x101, 0x6dcb,
- 0x101, 0x81e8, 0x101, 0x7acb, 0x101, 0x7b20, 0x101, 0x7c92,
- 0x101, 0x72c0, 0x101, 0x7099, 0x101, 0x8b58, 0x101, 0x4ec0,
- 0x101, 0x8336, 0x101, 0x523a, 0x101, 0x5207, 0x101, 0x5ea6,
- 0x101, 0x62d3, 0x101, 0x7cd6, 0x101, 0x5b85, 0x101, 0x6d1e,
- 0x101, 0x66b4, 0x101, 0x8f3b, 0x101, 0x884c, 0x101, 0x964d,
- 0x101, 0x898b, 0x101, 0x5ed3, 0x101, 0x5140, 0x101, 0x55c0,
- 0x101, 0x585a, 0x101, 0x6674, 0x101, 0x51de, 0x101, 0x732a,
- 0x101, 0x76ca, 0x101, 0x793c, 0x101, 0x795e, 0x101, 0x7965,
- 0x101, 0x798f, 0x101, 0x9756, 0x101, 0x7cbe, 0x101, 0x7fbd,
- 0x101, 0x8612, 0x101, 0x8af8, 0x101, 0x9038, 0x101, 0x90fd,
- 0x101, 0x98ef, 0x101, 0x98fc, 0x101, 0x9928, 0x101, 0x9db4,
- 0x101, 0x90de, 0x101, 0x96b7, 0x101, 0x4fae, 0x101, 0x50e7,
- 0x101, 0x514d, 0x101, 0x52c9, 0x101, 0x52e4, 0x101, 0x5351,
- 0x101, 0x559d, 0x101, 0x5606, 0x101, 0x5668, 0x101, 0x5840,
- 0x101, 0x58a8, 0x101, 0x5c64, 0x101, 0x5c6e, 0x101, 0x6094,
- 0x101, 0x6168, 0x101, 0x618e, 0x101, 0x61f2, 0x101, 0x654f,
- 0x101, 0x65e2, 0x101, 0x6691, 0x101, 0x6885, 0x101, 0x6d77,
- 0x101, 0x6e1a, 0x101, 0x6f22, 0x101, 0x716e, 0x101, 0x722b,
- 0x101, 0x7422, 0x101, 0x7891, 0x101, 0x793e, 0x101, 0x7949,
- 0x101, 0x7948, 0x101, 0x7950, 0x101, 0x7956, 0x101, 0x795d,
- 0x101, 0x798d, 0x101, 0x798e, 0x101, 0x7a40, 0x101, 0x7a81,
- 0x101, 0x7bc0, 0x101, 0x7df4, 0x101, 0x7e09, 0x101, 0x7e41,
- 0x101, 0x7f72, 0x101, 0x8005, 0x101, 0x81ed, 0x101, 0x8279,
- 0x101, 0x8279, 0x101, 0x8457, 0x101, 0x8910, 0x101, 0x8996,
- 0x101, 0x8b01, 0x101, 0x8b39, 0x101, 0x8cd3, 0x101, 0x8d08,
- 0x101, 0x8fb6, 0x101, 0x9038, 0x101, 0x96e3, 0x101, 0x97ff,
- 0x101, 0x983b, 0x101, 0x6075, 0x201, 0xd850, 0xdeee, 0x101,
- 0x8218, 0x101, 0x4e26, 0x101, 0x51b5, 0x101, 0x5168, 0x101,
- 0x4f80, 0x101, 0x5145, 0x101, 0x5180, 0x101, 0x52c7, 0x101,
- 0x52fa, 0x101, 0x559d, 0x101, 0x5555, 0x101, 0x5599, 0x101,
- 0x55e2, 0x101, 0x585a, 0x101, 0x58b3, 0x101, 0x5944, 0x101,
- 0x5954, 0x101, 0x5a62, 0x101, 0x5b28, 0x101, 0x5ed2, 0x101,
- 0x5ed9, 0x101, 0x5f69, 0x101, 0x5fad, 0x101, 0x60d8, 0x101,
- 0x614e, 0x101, 0x6108, 0x101, 0x618e, 0x101, 0x6160, 0x101,
- 0x61f2, 0x101, 0x6234, 0x101, 0x63c4, 0x101, 0x641c, 0x101,
- 0x6452, 0x101, 0x6556, 0x101, 0x6674, 0x101, 0x6717, 0x101,
- 0x671b, 0x101, 0x6756, 0x101, 0x6b79, 0x101, 0x6bba, 0x101,
- 0x6d41, 0x101, 0x6edb, 0x101, 0x6ecb, 0x101, 0x6f22, 0x101,
- 0x701e, 0x101, 0x716e, 0x101, 0x77a7, 0x101, 0x7235, 0x101,
- 0x72af, 0x101, 0x732a, 0x101, 0x7471, 0x101, 0x7506, 0x101,
- 0x753b, 0x101, 0x761d, 0x101, 0x761f, 0x101, 0x76ca, 0x101,
- 0x76db, 0x101, 0x76f4, 0x101, 0x774a, 0x101, 0x7740, 0x101,
- 0x78cc, 0x101, 0x7ab1, 0x101, 0x7bc0, 0x101, 0x7c7b, 0x101,
- 0x7d5b, 0x101, 0x7df4, 0x101, 0x7f3e, 0x101, 0x8005, 0x101,
- 0x8352, 0x101, 0x83ef, 0x101, 0x8779, 0x101, 0x8941, 0x101,
- 0x8986, 0x101, 0x8996, 0x101, 0x8abf, 0x101, 0x8af8, 0x101,
- 0x8acb, 0x101, 0x8b01, 0x101, 0x8afe, 0x101, 0x8aed, 0x101,
- 0x8b39, 0x101, 0x8b8a, 0x101, 0x8d08, 0x101, 0x8f38, 0x101,
- 0x9072, 0x101, 0x9199, 0x101, 0x9276, 0x101, 0x967c, 0x101,
- 0x96e3, 0x101, 0x9756, 0x101, 0x97db, 0x101, 0x97ff, 0x101,
- 0x980b, 0x101, 0x983b, 0x101, 0x9b12, 0x101, 0x9f9c, 0x201,
- 0xd84a, 0xdc4a, 0x201, 0xd84a, 0xdc44, 0x201, 0xd84c, 0xdfd5,
- 0x101, 0x3b9d, 0x101, 0x4018, 0x101, 0x4039, 0x201, 0xd854,
- 0xde49, 0x201, 0xd857, 0xdcd0, 0x201, 0xd85f, 0xded3, 0x101,
- 0x9f43, 0x101, 0x9f8e, 0x210, 0x66, 0x66, 0x210, 0x66,
- 0x69, 0x210, 0x66, 0x6c, 0x310, 0x66, 0x66, 0x69,
- 0x310, 0x66, 0x66, 0x6c, 0x210, 0x17f, 0x74, 0x210,
- 0x73, 0x74, 0x210, 0x574, 0x576, 0x210, 0x574, 0x565,
- 0x210, 0x574, 0x56b, 0x210, 0x57e, 0x576, 0x210, 0x574,
- 0x56d, 0x201, 0x5d9, 0x5b4, 0x201, 0x5f2, 0x5b7, 0x102,
- 0x5e2, 0x102, 0x5d0, 0x102, 0x5d3, 0x102, 0x5d4, 0x102,
- 0x5db, 0x102, 0x5dc, 0x102, 0x5dd, 0x102, 0x5e8, 0x102,
- 0x5ea, 0x102, 0x2b, 0x201, 0x5e9, 0x5c1, 0x201, 0x5e9,
- 0x5c2, 0x201, 0xfb49, 0x5c1, 0x201, 0xfb49, 0x5c2, 0x201,
- 0x5d0, 0x5b7, 0x201, 0x5d0, 0x5b8, 0x201, 0x5d0, 0x5bc,
- 0x201, 0x5d1, 0x5bc, 0x201, 0x5d2, 0x5bc, 0x201, 0x5d3,
- 0x5bc, 0x201, 0x5d4, 0x5bc, 0x201, 0x5d5, 0x5bc, 0x201,
- 0x5d6, 0x5bc, 0x201, 0x5d8, 0x5bc, 0x201, 0x5d9, 0x5bc,
- 0x201, 0x5da, 0x5bc, 0x201, 0x5db, 0x5bc, 0x201, 0x5dc,
- 0x5bc, 0x201, 0x5de, 0x5bc, 0x201, 0x5e0, 0x5bc, 0x201,
- 0x5e1, 0x5bc, 0x201, 0x5e3, 0x5bc, 0x201, 0x5e4, 0x5bc,
- 0x201, 0x5e6, 0x5bc, 0x201, 0x5e7, 0x5bc, 0x201, 0x5e8,
- 0x5bc, 0x201, 0x5e9, 0x5bc, 0x201, 0x5ea, 0x5bc, 0x201,
- 0x5d5, 0x5b9, 0x201, 0x5d1, 0x5bf, 0x201, 0x5db, 0x5bf,
- 0x201, 0x5e4, 0x5bf, 0x210, 0x5d0, 0x5dc, 0x107, 0x671,
- 0x106, 0x671, 0x107, 0x67b, 0x106, 0x67b, 0x104, 0x67b,
- 0x105, 0x67b, 0x107, 0x67e, 0x106, 0x67e, 0x104, 0x67e,
- 0x105, 0x67e, 0x107, 0x680, 0x106, 0x680, 0x104, 0x680,
- 0x105, 0x680, 0x107, 0x67a, 0x106, 0x67a, 0x104, 0x67a,
- 0x105, 0x67a, 0x107, 0x67f, 0x106, 0x67f, 0x104, 0x67f,
- 0x105, 0x67f, 0x107, 0x679, 0x106, 0x679, 0x104, 0x679,
- 0x105, 0x679, 0x107, 0x6a4, 0x106, 0x6a4, 0x104, 0x6a4,
- 0x105, 0x6a4, 0x107, 0x6a6, 0x106, 0x6a6, 0x104, 0x6a6,
- 0x105, 0x6a6, 0x107, 0x684, 0x106, 0x684, 0x104, 0x684,
- 0x105, 0x684, 0x107, 0x683, 0x106, 0x683, 0x104, 0x683,
- 0x105, 0x683, 0x107, 0x686, 0x106, 0x686, 0x104, 0x686,
- 0x105, 0x686, 0x107, 0x687, 0x106, 0x687, 0x104, 0x687,
- 0x105, 0x687, 0x107, 0x68d, 0x106, 0x68d, 0x107, 0x68c,
- 0x106, 0x68c, 0x107, 0x68e, 0x106, 0x68e, 0x107, 0x688,
- 0x106, 0x688, 0x107, 0x698, 0x106, 0x698, 0x107, 0x691,
- 0x106, 0x691, 0x107, 0x6a9, 0x106, 0x6a9, 0x104, 0x6a9,
- 0x105, 0x6a9, 0x107, 0x6af, 0x106, 0x6af, 0x104, 0x6af,
- 0x105, 0x6af, 0x107, 0x6b3, 0x106, 0x6b3, 0x104, 0x6b3,
- 0x105, 0x6b3, 0x107, 0x6b1, 0x106, 0x6b1, 0x104, 0x6b1,
- 0x105, 0x6b1, 0x107, 0x6ba, 0x106, 0x6ba, 0x107, 0x6bb,
- 0x106, 0x6bb, 0x104, 0x6bb, 0x105, 0x6bb, 0x107, 0x6c0,
- 0x106, 0x6c0, 0x107, 0x6c1, 0x106, 0x6c1, 0x104, 0x6c1,
- 0x105, 0x6c1, 0x107, 0x6be, 0x106, 0x6be, 0x104, 0x6be,
- 0x105, 0x6be, 0x107, 0x6d2, 0x106, 0x6d2, 0x107, 0x6d3,
- 0x106, 0x6d3, 0x107, 0x6ad, 0x106, 0x6ad, 0x104, 0x6ad,
- 0x105, 0x6ad, 0x107, 0x6c7, 0x106, 0x6c7, 0x107, 0x6c6,
- 0x106, 0x6c6, 0x107, 0x6c8, 0x106, 0x6c8, 0x107, 0x677,
- 0x107, 0x6cb, 0x106, 0x6cb, 0x107, 0x6c5, 0x106, 0x6c5,
- 0x107, 0x6c9, 0x106, 0x6c9, 0x107, 0x6d0, 0x106, 0x6d0,
- 0x104, 0x6d0, 0x105, 0x6d0, 0x104, 0x649, 0x105, 0x649,
- 0x207, 0x626, 0x627, 0x206, 0x626, 0x627, 0x207, 0x626,
- 0x6d5, 0x206, 0x626, 0x6d5, 0x207, 0x626, 0x648, 0x206,
- 0x626, 0x648, 0x207, 0x626, 0x6c7, 0x206, 0x626, 0x6c7,
- 0x207, 0x626, 0x6c6, 0x206, 0x626, 0x6c6, 0x207, 0x626,
- 0x6c8, 0x206, 0x626, 0x6c8, 0x207, 0x626, 0x6d0, 0x206,
- 0x626, 0x6d0, 0x204, 0x626, 0x6d0, 0x207, 0x626, 0x649,
- 0x206, 0x626, 0x649, 0x204, 0x626, 0x649, 0x107, 0x6cc,
- 0x106, 0x6cc, 0x104, 0x6cc, 0x105, 0x6cc, 0x207, 0x626,
- 0x62c, 0x207, 0x626, 0x62d, 0x207, 0x626, 0x645, 0x207,
- 0x626, 0x649, 0x207, 0x626, 0x64a, 0x207, 0x628, 0x62c,
- 0x207, 0x628, 0x62d, 0x207, 0x628, 0x62e, 0x207, 0x628,
- 0x645, 0x207, 0x628, 0x649, 0x207, 0x628, 0x64a, 0x207,
- 0x62a, 0x62c, 0x207, 0x62a, 0x62d, 0x207, 0x62a, 0x62e,
- 0x207, 0x62a, 0x645, 0x207, 0x62a, 0x649, 0x207, 0x62a,
- 0x64a, 0x207, 0x62b, 0x62c, 0x207, 0x62b, 0x645, 0x207,
- 0x62b, 0x649, 0x207, 0x62b, 0x64a, 0x207, 0x62c, 0x62d,
- 0x207, 0x62c, 0x645, 0x207, 0x62d, 0x62c, 0x207, 0x62d,
- 0x645, 0x207, 0x62e, 0x62c, 0x207, 0x62e, 0x62d, 0x207,
- 0x62e, 0x645, 0x207, 0x633, 0x62c, 0x207, 0x633, 0x62d,
- 0x207, 0x633, 0x62e, 0x207, 0x633, 0x645, 0x207, 0x635,
- 0x62d, 0x207, 0x635, 0x645, 0x207, 0x636, 0x62c, 0x207,
- 0x636, 0x62d, 0x207, 0x636, 0x62e, 0x207, 0x636, 0x645,
- 0x207, 0x637, 0x62d, 0x207, 0x637, 0x645, 0x207, 0x638,
- 0x645, 0x207, 0x639, 0x62c, 0x207, 0x639, 0x645, 0x207,
- 0x63a, 0x62c, 0x207, 0x63a, 0x645, 0x207, 0x641, 0x62c,
- 0x207, 0x641, 0x62d, 0x207, 0x641, 0x62e, 0x207, 0x641,
- 0x645, 0x207, 0x641, 0x649, 0x207, 0x641, 0x64a, 0x207,
- 0x642, 0x62d, 0x207, 0x642, 0x645, 0x207, 0x642, 0x649,
- 0x207, 0x642, 0x64a, 0x207, 0x643, 0x627, 0x207, 0x643,
- 0x62c, 0x207, 0x643, 0x62d, 0x207, 0x643, 0x62e, 0x207,
- 0x643, 0x644, 0x207, 0x643, 0x645, 0x207, 0x643, 0x649,
- 0x207, 0x643, 0x64a, 0x207, 0x644, 0x62c, 0x207, 0x644,
- 0x62d, 0x207, 0x644, 0x62e, 0x207, 0x644, 0x645, 0x207,
- 0x644, 0x649, 0x207, 0x644, 0x64a, 0x207, 0x645, 0x62c,
- 0x207, 0x645, 0x62d, 0x207, 0x645, 0x62e, 0x207, 0x645,
- 0x645, 0x207, 0x645, 0x649, 0x207, 0x645, 0x64a, 0x207,
- 0x646, 0x62c, 0x207, 0x646, 0x62d, 0x207, 0x646, 0x62e,
- 0x207, 0x646, 0x645, 0x207, 0x646, 0x649, 0x207, 0x646,
- 0x64a, 0x207, 0x647, 0x62c, 0x207, 0x647, 0x645, 0x207,
- 0x647, 0x649, 0x207, 0x647, 0x64a, 0x207, 0x64a, 0x62c,
- 0x207, 0x64a, 0x62d, 0x207, 0x64a, 0x62e, 0x207, 0x64a,
- 0x645, 0x207, 0x64a, 0x649, 0x207, 0x64a, 0x64a, 0x207,
- 0x630, 0x670, 0x207, 0x631, 0x670, 0x207, 0x649, 0x670,
- 0x307, 0x20, 0x64c, 0x651, 0x307, 0x20, 0x64d, 0x651,
- 0x307, 0x20, 0x64e, 0x651, 0x307, 0x20, 0x64f, 0x651,
- 0x307, 0x20, 0x650, 0x651, 0x307, 0x20, 0x651, 0x670,
- 0x206, 0x626, 0x631, 0x206, 0x626, 0x632, 0x206, 0x626,
- 0x645, 0x206, 0x626, 0x646, 0x206, 0x626, 0x649, 0x206,
- 0x626, 0x64a, 0x206, 0x628, 0x631, 0x206, 0x628, 0x632,
- 0x206, 0x628, 0x645, 0x206, 0x628, 0x646, 0x206, 0x628,
- 0x649, 0x206, 0x628, 0x64a, 0x206, 0x62a, 0x631, 0x206,
- 0x62a, 0x632, 0x206, 0x62a, 0x645, 0x206, 0x62a, 0x646,
- 0x206, 0x62a, 0x649, 0x206, 0x62a, 0x64a, 0x206, 0x62b,
- 0x631, 0x206, 0x62b, 0x632, 0x206, 0x62b, 0x645, 0x206,
- 0x62b, 0x646, 0x206, 0x62b, 0x649, 0x206, 0x62b, 0x64a,
- 0x206, 0x641, 0x649, 0x206, 0x641, 0x64a, 0x206, 0x642,
- 0x649, 0x206, 0x642, 0x64a, 0x206, 0x643, 0x627, 0x206,
- 0x643, 0x644, 0x206, 0x643, 0x645, 0x206, 0x643, 0x649,
- 0x206, 0x643, 0x64a, 0x206, 0x644, 0x645, 0x206, 0x644,
- 0x649, 0x206, 0x644, 0x64a, 0x206, 0x645, 0x627, 0x206,
- 0x645, 0x645, 0x206, 0x646, 0x631, 0x206, 0x646, 0x632,
- 0x206, 0x646, 0x645, 0x206, 0x646, 0x646, 0x206, 0x646,
- 0x649, 0x206, 0x646, 0x64a, 0x206, 0x649, 0x670, 0x206,
- 0x64a, 0x631, 0x206, 0x64a, 0x632, 0x206, 0x64a, 0x645,
- 0x206, 0x64a, 0x646, 0x206, 0x64a, 0x649, 0x206, 0x64a,
- 0x64a, 0x204, 0x626, 0x62c, 0x204, 0x626, 0x62d, 0x204,
- 0x626, 0x62e, 0x204, 0x626, 0x645, 0x204, 0x626, 0x647,
- 0x204, 0x628, 0x62c, 0x204, 0x628, 0x62d, 0x204, 0x628,
- 0x62e, 0x204, 0x628, 0x645, 0x204, 0x628, 0x647, 0x204,
- 0x62a, 0x62c, 0x204, 0x62a, 0x62d, 0x204, 0x62a, 0x62e,
- 0x204, 0x62a, 0x645, 0x204, 0x62a, 0x647, 0x204, 0x62b,
- 0x645, 0x204, 0x62c, 0x62d, 0x204, 0x62c, 0x645, 0x204,
- 0x62d, 0x62c, 0x204, 0x62d, 0x645, 0x204, 0x62e, 0x62c,
- 0x204, 0x62e, 0x645, 0x204, 0x633, 0x62c, 0x204, 0x633,
- 0x62d, 0x204, 0x633, 0x62e, 0x204, 0x633, 0x645, 0x204,
- 0x635, 0x62d, 0x204, 0x635, 0x62e, 0x204, 0x635, 0x645,
- 0x204, 0x636, 0x62c, 0x204, 0x636, 0x62d, 0x204, 0x636,
- 0x62e, 0x204, 0x636, 0x645, 0x204, 0x637, 0x62d, 0x204,
- 0x638, 0x645, 0x204, 0x639, 0x62c, 0x204, 0x639, 0x645,
- 0x204, 0x63a, 0x62c, 0x204, 0x63a, 0x645, 0x204, 0x641,
- 0x62c, 0x204, 0x641, 0x62d, 0x204, 0x641, 0x62e, 0x204,
- 0x641, 0x645, 0x204, 0x642, 0x62d, 0x204, 0x642, 0x645,
- 0x204, 0x643, 0x62c, 0x204, 0x643, 0x62d, 0x204, 0x643,
- 0x62e, 0x204, 0x643, 0x644, 0x204, 0x643, 0x645, 0x204,
- 0x644, 0x62c, 0x204, 0x644, 0x62d, 0x204, 0x644, 0x62e,
- 0x204, 0x644, 0x645, 0x204, 0x644, 0x647, 0x204, 0x645,
- 0x62c, 0x204, 0x645, 0x62d, 0x204, 0x645, 0x62e, 0x204,
- 0x645, 0x645, 0x204, 0x646, 0x62c, 0x204, 0x646, 0x62d,
- 0x204, 0x646, 0x62e, 0x204, 0x646, 0x645, 0x204, 0x646,
- 0x647, 0x204, 0x647, 0x62c, 0x204, 0x647, 0x645, 0x204,
- 0x647, 0x670, 0x204, 0x64a, 0x62c, 0x204, 0x64a, 0x62d,
- 0x204, 0x64a, 0x62e, 0x204, 0x64a, 0x645, 0x204, 0x64a,
- 0x647, 0x205, 0x626, 0x645, 0x205, 0x626, 0x647, 0x205,
- 0x628, 0x645, 0x205, 0x628, 0x647, 0x205, 0x62a, 0x645,
- 0x205, 0x62a, 0x647, 0x205, 0x62b, 0x645, 0x205, 0x62b,
- 0x647, 0x205, 0x633, 0x645, 0x205, 0x633, 0x647, 0x205,
- 0x634, 0x645, 0x205, 0x634, 0x647, 0x205, 0x643, 0x644,
- 0x205, 0x643, 0x645, 0x205, 0x644, 0x645, 0x205, 0x646,
- 0x645, 0x205, 0x646, 0x647, 0x205, 0x64a, 0x645, 0x205,
- 0x64a, 0x647, 0x305, 0x640, 0x64e, 0x651, 0x305, 0x640,
- 0x64f, 0x651, 0x305, 0x640, 0x650, 0x651, 0x207, 0x637,
- 0x649, 0x207, 0x637, 0x64a, 0x207, 0x639, 0x649, 0x207,
- 0x639, 0x64a, 0x207, 0x63a, 0x649, 0x207, 0x63a, 0x64a,
- 0x207, 0x633, 0x649, 0x207, 0x633, 0x64a, 0x207, 0x634,
- 0x649, 0x207, 0x634, 0x64a, 0x207, 0x62d, 0x649, 0x207,
- 0x62d, 0x64a, 0x207, 0x62c, 0x649, 0x207, 0x62c, 0x64a,
- 0x207, 0x62e, 0x649, 0x207, 0x62e, 0x64a, 0x207, 0x635,
- 0x649, 0x207, 0x635, 0x64a, 0x207, 0x636, 0x649, 0x207,
- 0x636, 0x64a, 0x207, 0x634, 0x62c, 0x207, 0x634, 0x62d,
- 0x207, 0x634, 0x62e, 0x207, 0x634, 0x645, 0x207, 0x634,
- 0x631, 0x207, 0x633, 0x631, 0x207, 0x635, 0x631, 0x207,
- 0x636, 0x631, 0x206, 0x637, 0x649, 0x206, 0x637, 0x64a,
- 0x206, 0x639, 0x649, 0x206, 0x639, 0x64a, 0x206, 0x63a,
- 0x649, 0x206, 0x63a, 0x64a, 0x206, 0x633, 0x649, 0x206,
- 0x633, 0x64a, 0x206, 0x634, 0x649, 0x206, 0x634, 0x64a,
- 0x206, 0x62d, 0x649, 0x206, 0x62d, 0x64a, 0x206, 0x62c,
- 0x649, 0x206, 0x62c, 0x64a, 0x206, 0x62e, 0x649, 0x206,
- 0x62e, 0x64a, 0x206, 0x635, 0x649, 0x206, 0x635, 0x64a,
- 0x206, 0x636, 0x649, 0x206, 0x636, 0x64a, 0x206, 0x634,
- 0x62c, 0x206, 0x634, 0x62d, 0x206, 0x634, 0x62e, 0x206,
- 0x634, 0x645, 0x206, 0x634, 0x631, 0x206, 0x633, 0x631,
- 0x206, 0x635, 0x631, 0x206, 0x636, 0x631, 0x204, 0x634,
- 0x62c, 0x204, 0x634, 0x62d, 0x204, 0x634, 0x62e, 0x204,
- 0x634, 0x645, 0x204, 0x633, 0x647, 0x204, 0x634, 0x647,
- 0x204, 0x637, 0x645, 0x205, 0x633, 0x62c, 0x205, 0x633,
- 0x62d, 0x205, 0x633, 0x62e, 0x205, 0x634, 0x62c, 0x205,
- 0x634, 0x62d, 0x205, 0x634, 0x62e, 0x205, 0x637, 0x645,
- 0x205, 0x638, 0x645, 0x206, 0x627, 0x64b, 0x207, 0x627,
- 0x64b, 0x304, 0x62a, 0x62c, 0x645, 0x306, 0x62a, 0x62d,
- 0x62c, 0x304, 0x62a, 0x62d, 0x62c, 0x304, 0x62a, 0x62d,
- 0x645, 0x304, 0x62a, 0x62e, 0x645, 0x304, 0x62a, 0x645,
- 0x62c, 0x304, 0x62a, 0x645, 0x62d, 0x304, 0x62a, 0x645,
- 0x62e, 0x306, 0x62c, 0x645, 0x62d, 0x304, 0x62c, 0x645,
- 0x62d, 0x306, 0x62d, 0x645, 0x64a, 0x306, 0x62d, 0x645,
- 0x649, 0x304, 0x633, 0x62d, 0x62c, 0x304, 0x633, 0x62c,
- 0x62d, 0x306, 0x633, 0x62c, 0x649, 0x306, 0x633, 0x645,
- 0x62d, 0x304, 0x633, 0x645, 0x62d, 0x304, 0x633, 0x645,
- 0x62c, 0x306, 0x633, 0x645, 0x645, 0x304, 0x633, 0x645,
- 0x645, 0x306, 0x635, 0x62d, 0x62d, 0x304, 0x635, 0x62d,
- 0x62d, 0x306, 0x635, 0x645, 0x645, 0x306, 0x634, 0x62d,
- 0x645, 0x304, 0x634, 0x62d, 0x645, 0x306, 0x634, 0x62c,
- 0x64a, 0x306, 0x634, 0x645, 0x62e, 0x304, 0x634, 0x645,
- 0x62e, 0x306, 0x634, 0x645, 0x645, 0x304, 0x634, 0x645,
- 0x645, 0x306, 0x636, 0x62d, 0x649, 0x306, 0x636, 0x62e,
- 0x645, 0x304, 0x636, 0x62e, 0x645, 0x306, 0x637, 0x645,
- 0x62d, 0x304, 0x637, 0x645, 0x62d, 0x304, 0x637, 0x645,
- 0x645, 0x306, 0x637, 0x645, 0x64a, 0x306, 0x639, 0x62c,
- 0x645, 0x306, 0x639, 0x645, 0x645, 0x304, 0x639, 0x645,
- 0x645, 0x306, 0x639, 0x645, 0x649, 0x306, 0x63a, 0x645,
- 0x645, 0x306, 0x63a, 0x645, 0x64a, 0x306, 0x63a, 0x645,
- 0x649, 0x306, 0x641, 0x62e, 0x645, 0x304, 0x641, 0x62e,
- 0x645, 0x306, 0x642, 0x645, 0x62d, 0x306, 0x642, 0x645,
- 0x645, 0x306, 0x644, 0x62d, 0x645, 0x306, 0x644, 0x62d,
- 0x64a, 0x306, 0x644, 0x62d, 0x649, 0x304, 0x644, 0x62c,
- 0x62c, 0x306, 0x644, 0x62c, 0x62c, 0x306, 0x644, 0x62e,
- 0x645, 0x304, 0x644, 0x62e, 0x645, 0x306, 0x644, 0x645,
- 0x62d, 0x304, 0x644, 0x645, 0x62d, 0x304, 0x645, 0x62d,
- 0x62c, 0x304, 0x645, 0x62d, 0x645, 0x306, 0x645, 0x62d,
- 0x64a, 0x304, 0x645, 0x62c, 0x62d, 0x304, 0x645, 0x62c,
- 0x645, 0x304, 0x645, 0x62e, 0x62c, 0x304, 0x645, 0x62e,
- 0x645, 0x304, 0x645, 0x62c, 0x62e, 0x304, 0x647, 0x645,
- 0x62c, 0x304, 0x647, 0x645, 0x645, 0x304, 0x646, 0x62d,
- 0x645, 0x306, 0x646, 0x62d, 0x649, 0x306, 0x646, 0x62c,
- 0x645, 0x304, 0x646, 0x62c, 0x645, 0x306, 0x646, 0x62c,
- 0x649, 0x306, 0x646, 0x645, 0x64a, 0x306, 0x646, 0x645,
- 0x649, 0x306, 0x64a, 0x645, 0x645, 0x304, 0x64a, 0x645,
- 0x645, 0x306, 0x628, 0x62e, 0x64a, 0x306, 0x62a, 0x62c,
- 0x64a, 0x306, 0x62a, 0x62c, 0x649, 0x306, 0x62a, 0x62e,
- 0x64a, 0x306, 0x62a, 0x62e, 0x649, 0x306, 0x62a, 0x645,
- 0x64a, 0x306, 0x62a, 0x645, 0x649, 0x306, 0x62c, 0x645,
- 0x64a, 0x306, 0x62c, 0x62d, 0x649, 0x306, 0x62c, 0x645,
- 0x649, 0x306, 0x633, 0x62e, 0x649, 0x306, 0x635, 0x62d,
- 0x64a, 0x306, 0x634, 0x62d, 0x64a, 0x306, 0x636, 0x62d,
- 0x64a, 0x306, 0x644, 0x62c, 0x64a, 0x306, 0x644, 0x645,
- 0x64a, 0x306, 0x64a, 0x62d, 0x64a, 0x306, 0x64a, 0x62c,
- 0x64a, 0x306, 0x64a, 0x645, 0x64a, 0x306, 0x645, 0x645,
- 0x64a, 0x306, 0x642, 0x645, 0x64a, 0x306, 0x646, 0x62d,
- 0x64a, 0x304, 0x642, 0x645, 0x62d, 0x304, 0x644, 0x62d,
- 0x645, 0x306, 0x639, 0x645, 0x64a, 0x306, 0x643, 0x645,
- 0x64a, 0x304, 0x646, 0x62c, 0x62d, 0x306, 0x645, 0x62e,
- 0x64a, 0x304, 0x644, 0x62c, 0x645, 0x306, 0x643, 0x645,
- 0x645, 0x306, 0x644, 0x62c, 0x645, 0x306, 0x646, 0x62c,
- 0x62d, 0x306, 0x62c, 0x62d, 0x64a, 0x306, 0x62d, 0x62c,
- 0x64a, 0x306, 0x645, 0x62c, 0x64a, 0x306, 0x641, 0x645,
- 0x64a, 0x306, 0x628, 0x62d, 0x64a, 0x304, 0x643, 0x645,
- 0x645, 0x304, 0x639, 0x62c, 0x645, 0x304, 0x635, 0x645,
- 0x645, 0x306, 0x633, 0x62e, 0x64a, 0x306, 0x646, 0x62c,
- 0x64a, 0x307, 0x635, 0x644, 0x6d2, 0x307, 0x642, 0x644,
- 0x6d2, 0x407, 0x627, 0x644, 0x644, 0x647, 0x407, 0x627,
- 0x643, 0x628, 0x631, 0x407, 0x645, 0x62d, 0x645, 0x62f,
- 0x407, 0x635, 0x644, 0x639, 0x645, 0x407, 0x631, 0x633,
- 0x648, 0x644, 0x407, 0x639, 0x644, 0x64a, 0x647, 0x407,
- 0x648, 0x633, 0x644, 0x645, 0x307, 0x635, 0x644, 0x649,
- 0x1207, 0x635, 0x644, 0x649, 0x20, 0x627, 0x644, 0x644,
- 0x647, 0x20, 0x639, 0x644, 0x64a, 0x647, 0x20, 0x648,
- 0x633, 0x644, 0x645, 0x807, 0x62c, 0x644, 0x20, 0x62c,
- 0x644, 0x627, 0x644, 0x647, 0x407, 0x631, 0x6cc, 0x627,
- 0x644, 0x10b, 0x2c, 0x10b, 0x3001, 0x10b, 0x3002, 0x10b,
- 0x3a, 0x10b, 0x3b, 0x10b, 0x21, 0x10b, 0x3f, 0x10b,
- 0x3016, 0x10b, 0x3017, 0x10b, 0x2026, 0x10b, 0x2025, 0x10b,
- 0x2014, 0x10b, 0x2013, 0x10b, 0x5f, 0x10b, 0x5f, 0x10b,
- 0x28, 0x10b, 0x29, 0x10b, 0x7b, 0x10b, 0x7d, 0x10b,
- 0x3014, 0x10b, 0x3015, 0x10b, 0x3010, 0x10b, 0x3011, 0x10b,
- 0x300a, 0x10b, 0x300b, 0x10b, 0x3008, 0x10b, 0x3009, 0x10b,
- 0x300c, 0x10b, 0x300d, 0x10b, 0x300e, 0x10b, 0x300f, 0x10b,
- 0x5b, 0x10b, 0x5d, 0x110, 0x203e, 0x110, 0x203e, 0x110,
- 0x203e, 0x110, 0x203e, 0x110, 0x5f, 0x110, 0x5f, 0x110,
- 0x5f, 0x10e, 0x2c, 0x10e, 0x3001, 0x10e, 0x2e, 0x10e,
- 0x3b, 0x10e, 0x3a, 0x10e, 0x3f, 0x10e, 0x21, 0x10e,
- 0x2014, 0x10e, 0x28, 0x10e, 0x29, 0x10e, 0x7b, 0x10e,
- 0x7d, 0x10e, 0x3014, 0x10e, 0x3015, 0x10e, 0x23, 0x10e,
- 0x26, 0x10e, 0x2a, 0x10e, 0x2b, 0x10e, 0x2d, 0x10e,
- 0x3c, 0x10e, 0x3e, 0x10e, 0x3d, 0x10e, 0x5c, 0x10e,
- 0x24, 0x10e, 0x25, 0x10e, 0x40, 0x207, 0x20, 0x64b,
- 0x205, 0x640, 0x64b, 0x207, 0x20, 0x64c, 0x207, 0x20,
- 0x64d, 0x207, 0x20, 0x64e, 0x205, 0x640, 0x64e, 0x207,
- 0x20, 0x64f, 0x205, 0x640, 0x64f, 0x207, 0x20, 0x650,
- 0x205, 0x640, 0x650, 0x207, 0x20, 0x651, 0x205, 0x640,
- 0x651, 0x207, 0x20, 0x652, 0x205, 0x640, 0x652, 0x107,
- 0x621, 0x107, 0x622, 0x106, 0x622, 0x107, 0x623, 0x106,
- 0x623, 0x107, 0x624, 0x106, 0x624, 0x107, 0x625, 0x106,
- 0x625, 0x107, 0x626, 0x106, 0x626, 0x104, 0x626, 0x105,
- 0x626, 0x107, 0x627, 0x106, 0x627, 0x107, 0x628, 0x106,
- 0x628, 0x104, 0x628, 0x105, 0x628, 0x107, 0x629, 0x106,
- 0x629, 0x107, 0x62a, 0x106, 0x62a, 0x104, 0x62a, 0x105,
- 0x62a, 0x107, 0x62b, 0x106, 0x62b, 0x104, 0x62b, 0x105,
- 0x62b, 0x107, 0x62c, 0x106, 0x62c, 0x104, 0x62c, 0x105,
- 0x62c, 0x107, 0x62d, 0x106, 0x62d, 0x104, 0x62d, 0x105,
- 0x62d, 0x107, 0x62e, 0x106, 0x62e, 0x104, 0x62e, 0x105,
- 0x62e, 0x107, 0x62f, 0x106, 0x62f, 0x107, 0x630, 0x106,
- 0x630, 0x107, 0x631, 0x106, 0x631, 0x107, 0x632, 0x106,
- 0x632, 0x107, 0x633, 0x106, 0x633, 0x104, 0x633, 0x105,
- 0x633, 0x107, 0x634, 0x106, 0x634, 0x104, 0x634, 0x105,
- 0x634, 0x107, 0x635, 0x106, 0x635, 0x104, 0x635, 0x105,
- 0x635, 0x107, 0x636, 0x106, 0x636, 0x104, 0x636, 0x105,
- 0x636, 0x107, 0x637, 0x106, 0x637, 0x104, 0x637, 0x105,
- 0x637, 0x107, 0x638, 0x106, 0x638, 0x104, 0x638, 0x105,
- 0x638, 0x107, 0x639, 0x106, 0x639, 0x104, 0x639, 0x105,
- 0x639, 0x107, 0x63a, 0x106, 0x63a, 0x104, 0x63a, 0x105,
- 0x63a, 0x107, 0x641, 0x106, 0x641, 0x104, 0x641, 0x105,
- 0x641, 0x107, 0x642, 0x106, 0x642, 0x104, 0x642, 0x105,
- 0x642, 0x107, 0x643, 0x106, 0x643, 0x104, 0x643, 0x105,
- 0x643, 0x107, 0x644, 0x106, 0x644, 0x104, 0x644, 0x105,
- 0x644, 0x107, 0x645, 0x106, 0x645, 0x104, 0x645, 0x105,
- 0x645, 0x107, 0x646, 0x106, 0x646, 0x104, 0x646, 0x105,
- 0x646, 0x107, 0x647, 0x106, 0x647, 0x104, 0x647, 0x105,
- 0x647, 0x107, 0x648, 0x106, 0x648, 0x107, 0x649, 0x106,
- 0x649, 0x107, 0x64a, 0x106, 0x64a, 0x104, 0x64a, 0x105,
- 0x64a, 0x207, 0x644, 0x622, 0x206, 0x644, 0x622, 0x207,
- 0x644, 0x623, 0x206, 0x644, 0x623, 0x207, 0x644, 0x625,
- 0x206, 0x644, 0x625, 0x207, 0x644, 0x627, 0x206, 0x644,
- 0x627, 0x10c, 0x21, 0x10c, 0x22, 0x10c, 0x23, 0x10c,
- 0x24, 0x10c, 0x25, 0x10c, 0x26, 0x10c, 0x27, 0x10c,
- 0x28, 0x10c, 0x29, 0x10c, 0x2a, 0x10c, 0x2b, 0x10c,
- 0x2c, 0x10c, 0x2d, 0x10c, 0x2e, 0x10c, 0x2f, 0x10c,
- 0x30, 0x10c, 0x31, 0x10c, 0x32, 0x10c, 0x33, 0x10c,
- 0x34, 0x10c, 0x35, 0x10c, 0x36, 0x10c, 0x37, 0x10c,
- 0x38, 0x10c, 0x39, 0x10c, 0x3a, 0x10c, 0x3b, 0x10c,
- 0x3c, 0x10c, 0x3d, 0x10c, 0x3e, 0x10c, 0x3f, 0x10c,
- 0x40, 0x10c, 0x41, 0x10c, 0x42, 0x10c, 0x43, 0x10c,
- 0x44, 0x10c, 0x45, 0x10c, 0x46, 0x10c, 0x47, 0x10c,
- 0x48, 0x10c, 0x49, 0x10c, 0x4a, 0x10c, 0x4b, 0x10c,
- 0x4c, 0x10c, 0x4d, 0x10c, 0x4e, 0x10c, 0x4f, 0x10c,
- 0x50, 0x10c, 0x51, 0x10c, 0x52, 0x10c, 0x53, 0x10c,
- 0x54, 0x10c, 0x55, 0x10c, 0x56, 0x10c, 0x57, 0x10c,
- 0x58, 0x10c, 0x59, 0x10c, 0x5a, 0x10c, 0x5b, 0x10c,
- 0x5c, 0x10c, 0x5d, 0x10c, 0x5e, 0x10c, 0x5f, 0x10c,
- 0x60, 0x10c, 0x61, 0x10c, 0x62, 0x10c, 0x63, 0x10c,
- 0x64, 0x10c, 0x65, 0x10c, 0x66, 0x10c, 0x67, 0x10c,
- 0x68, 0x10c, 0x69, 0x10c, 0x6a, 0x10c, 0x6b, 0x10c,
- 0x6c, 0x10c, 0x6d, 0x10c, 0x6e, 0x10c, 0x6f, 0x10c,
- 0x70, 0x10c, 0x71, 0x10c, 0x72, 0x10c, 0x73, 0x10c,
- 0x74, 0x10c, 0x75, 0x10c, 0x76, 0x10c, 0x77, 0x10c,
- 0x78, 0x10c, 0x79, 0x10c, 0x7a, 0x10c, 0x7b, 0x10c,
- 0x7c, 0x10c, 0x7d, 0x10c, 0x7e, 0x10c, 0x2985, 0x10c,
- 0x2986, 0x10d, 0x3002, 0x10d, 0x300c, 0x10d, 0x300d, 0x10d,
- 0x3001, 0x10d, 0x30fb, 0x10d, 0x30f2, 0x10d, 0x30a1, 0x10d,
- 0x30a3, 0x10d, 0x30a5, 0x10d, 0x30a7, 0x10d, 0x30a9, 0x10d,
- 0x30e3, 0x10d, 0x30e5, 0x10d, 0x30e7, 0x10d, 0x30c3, 0x10d,
- 0x30fc, 0x10d, 0x30a2, 0x10d, 0x30a4, 0x10d, 0x30a6, 0x10d,
- 0x30a8, 0x10d, 0x30aa, 0x10d, 0x30ab, 0x10d, 0x30ad, 0x10d,
- 0x30af, 0x10d, 0x30b1, 0x10d, 0x30b3, 0x10d, 0x30b5, 0x10d,
- 0x30b7, 0x10d, 0x30b9, 0x10d, 0x30bb, 0x10d, 0x30bd, 0x10d,
- 0x30bf, 0x10d, 0x30c1, 0x10d, 0x30c4, 0x10d, 0x30c6, 0x10d,
- 0x30c8, 0x10d, 0x30ca, 0x10d, 0x30cb, 0x10d, 0x30cc, 0x10d,
- 0x30cd, 0x10d, 0x30ce, 0x10d, 0x30cf, 0x10d, 0x30d2, 0x10d,
- 0x30d5, 0x10d, 0x30d8, 0x10d, 0x30db, 0x10d, 0x30de, 0x10d,
- 0x30df, 0x10d, 0x30e0, 0x10d, 0x30e1, 0x10d, 0x30e2, 0x10d,
- 0x30e4, 0x10d, 0x30e6, 0x10d, 0x30e8, 0x10d, 0x30e9, 0x10d,
- 0x30ea, 0x10d, 0x30eb, 0x10d, 0x30ec, 0x10d, 0x30ed, 0x10d,
- 0x30ef, 0x10d, 0x30f3, 0x10d, 0x3099, 0x10d, 0x309a, 0x10d,
- 0x3164, 0x10d, 0x3131, 0x10d, 0x3132, 0x10d, 0x3133, 0x10d,
- 0x3134, 0x10d, 0x3135, 0x10d, 0x3136, 0x10d, 0x3137, 0x10d,
- 0x3138, 0x10d, 0x3139, 0x10d, 0x313a, 0x10d, 0x313b, 0x10d,
- 0x313c, 0x10d, 0x313d, 0x10d, 0x313e, 0x10d, 0x313f, 0x10d,
- 0x3140, 0x10d, 0x3141, 0x10d, 0x3142, 0x10d, 0x3143, 0x10d,
- 0x3144, 0x10d, 0x3145, 0x10d, 0x3146, 0x10d, 0x3147, 0x10d,
- 0x3148, 0x10d, 0x3149, 0x10d, 0x314a, 0x10d, 0x314b, 0x10d,
- 0x314c, 0x10d, 0x314d, 0x10d, 0x314e, 0x10d, 0x314f, 0x10d,
- 0x3150, 0x10d, 0x3151, 0x10d, 0x3152, 0x10d, 0x3153, 0x10d,
- 0x3154, 0x10d, 0x3155, 0x10d, 0x3156, 0x10d, 0x3157, 0x10d,
- 0x3158, 0x10d, 0x3159, 0x10d, 0x315a, 0x10d, 0x315b, 0x10d,
- 0x315c, 0x10d, 0x315d, 0x10d, 0x315e, 0x10d, 0x315f, 0x10d,
- 0x3160, 0x10d, 0x3161, 0x10d, 0x3162, 0x10d, 0x3163, 0x10c,
- 0xa2, 0x10c, 0xa3, 0x10c, 0xac, 0x10c, 0xaf, 0x10c,
- 0xa6, 0x10c, 0xa5, 0x10c, 0x20a9, 0x10d, 0x2502, 0x10d,
- 0x2190, 0x10d, 0x2191, 0x10d, 0x2192, 0x10d, 0x2193, 0x10d,
- 0x25a0, 0x10d, 0x25cb, 0x401, 0xd804, 0xdc99, 0xd804, 0xdcba,
- 0x401, 0xd804, 0xdc9b, 0xd804, 0xdcba, 0x401, 0xd804, 0xdca5,
- 0xd804, 0xdcba, 0x401, 0xd804, 0xdd31, 0xd804, 0xdd27, 0x401,
- 0xd804, 0xdd32, 0xd804, 0xdd27, 0x401, 0xd804, 0xdf47, 0xd804,
- 0xdf3e, 0x401, 0xd804, 0xdf47, 0xd804, 0xdf57, 0x401, 0xd805,
- 0xdcb9, 0xd805, 0xdcba, 0x401, 0xd805, 0xdcb9, 0xd805, 0xdcb0,
- 0x401, 0xd805, 0xdcb9, 0xd805, 0xdcbd, 0x401, 0xd805, 0xddb8,
- 0xd805, 0xddaf, 0x401, 0xd805, 0xddb9, 0xd805, 0xddaf, 0x401,
- 0xd806, 0xdd35, 0xd806, 0xdd30, 0x401, 0xd834, 0xdd57, 0xd834,
- 0xdd65, 0x401, 0xd834, 0xdd58, 0xd834, 0xdd65, 0x401, 0xd834,
- 0xdd5f, 0xd834, 0xdd6e, 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd6f,
- 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd70, 0x401, 0xd834, 0xdd5f,
- 0xd834, 0xdd71, 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd72, 0x401,
- 0xd834, 0xddb9, 0xd834, 0xdd65, 0x401, 0xd834, 0xddba, 0xd834,
- 0xdd65, 0x401, 0xd834, 0xddbb, 0xd834, 0xdd6e, 0x401, 0xd834,
- 0xddbc, 0xd834, 0xdd6e, 0x401, 0xd834, 0xddbb, 0xd834, 0xdd6f,
- 0x401, 0xd834, 0xddbc, 0xd834, 0xdd6f, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102,
- 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102,
- 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, 0x74, 0x102,
- 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, 0x78, 0x102,
- 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102,
- 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, 0x46, 0x102,
- 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102,
- 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102,
- 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, 0x52, 0x102,
- 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, 0x56, 0x102,
- 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102,
- 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, 0x64, 0x102,
- 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, 0x68, 0x102,
- 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102,
- 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102,
- 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, 0x74, 0x102,
- 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, 0x78, 0x102,
- 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, 0x43, 0x102,
- 0x44, 0x102, 0x47, 0x102, 0x4a, 0x102, 0x4b, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, 0x56, 0x102,
- 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102,
- 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, 0x64, 0x102,
- 0x66, 0x102, 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102,
+ 0x109, 0x44a, 0x109, 0x44c, 0x109, 0xa76f, 0x109, 0x43,
+ 0x109, 0x46, 0x109, 0x51, 0x109, 0x126, 0x109, 0x153,
+ 0x109, 0xa727, 0x109, 0xab37, 0x109, 0x26b, 0x109, 0xab52,
+ 0x109, 0x28d, 0x101, 0x8c48, 0x101, 0x66f4, 0x101, 0x8eca,
+ 0x101, 0x8cc8, 0x101, 0x6ed1, 0x101, 0x4e32, 0x101, 0x53e5,
+ 0x101, 0x9f9c, 0x101, 0x9f9c, 0x101, 0x5951, 0x101, 0x91d1,
+ 0x101, 0x5587, 0x101, 0x5948, 0x101, 0x61f6, 0x101, 0x7669,
+ 0x101, 0x7f85, 0x101, 0x863f, 0x101, 0x87ba, 0x101, 0x88f8,
+ 0x101, 0x908f, 0x101, 0x6a02, 0x101, 0x6d1b, 0x101, 0x70d9,
+ 0x101, 0x73de, 0x101, 0x843d, 0x101, 0x916a, 0x101, 0x99f1,
+ 0x101, 0x4e82, 0x101, 0x5375, 0x101, 0x6b04, 0x101, 0x721b,
+ 0x101, 0x862d, 0x101, 0x9e1e, 0x101, 0x5d50, 0x101, 0x6feb,
+ 0x101, 0x85cd, 0x101, 0x8964, 0x101, 0x62c9, 0x101, 0x81d8,
+ 0x101, 0x881f, 0x101, 0x5eca, 0x101, 0x6717, 0x101, 0x6d6a,
+ 0x101, 0x72fc, 0x101, 0x90ce, 0x101, 0x4f86, 0x101, 0x51b7,
+ 0x101, 0x52de, 0x101, 0x64c4, 0x101, 0x6ad3, 0x101, 0x7210,
+ 0x101, 0x76e7, 0x101, 0x8001, 0x101, 0x8606, 0x101, 0x865c,
+ 0x101, 0x8def, 0x101, 0x9732, 0x101, 0x9b6f, 0x101, 0x9dfa,
+ 0x101, 0x788c, 0x101, 0x797f, 0x101, 0x7da0, 0x101, 0x83c9,
+ 0x101, 0x9304, 0x101, 0x9e7f, 0x101, 0x8ad6, 0x101, 0x58df,
+ 0x101, 0x5f04, 0x101, 0x7c60, 0x101, 0x807e, 0x101, 0x7262,
+ 0x101, 0x78ca, 0x101, 0x8cc2, 0x101, 0x96f7, 0x101, 0x58d8,
+ 0x101, 0x5c62, 0x101, 0x6a13, 0x101, 0x6dda, 0x101, 0x6f0f,
+ 0x101, 0x7d2f, 0x101, 0x7e37, 0x101, 0x964b, 0x101, 0x52d2,
+ 0x101, 0x808b, 0x101, 0x51dc, 0x101, 0x51cc, 0x101, 0x7a1c,
+ 0x101, 0x7dbe, 0x101, 0x83f1, 0x101, 0x9675, 0x101, 0x8b80,
+ 0x101, 0x62cf, 0x101, 0x6a02, 0x101, 0x8afe, 0x101, 0x4e39,
+ 0x101, 0x5be7, 0x101, 0x6012, 0x101, 0x7387, 0x101, 0x7570,
+ 0x101, 0x5317, 0x101, 0x78fb, 0x101, 0x4fbf, 0x101, 0x5fa9,
+ 0x101, 0x4e0d, 0x101, 0x6ccc, 0x101, 0x6578, 0x101, 0x7d22,
+ 0x101, 0x53c3, 0x101, 0x585e, 0x101, 0x7701, 0x101, 0x8449,
+ 0x101, 0x8aaa, 0x101, 0x6bba, 0x101, 0x8fb0, 0x101, 0x6c88,
+ 0x101, 0x62fe, 0x101, 0x82e5, 0x101, 0x63a0, 0x101, 0x7565,
+ 0x101, 0x4eae, 0x101, 0x5169, 0x101, 0x51c9, 0x101, 0x6881,
+ 0x101, 0x7ce7, 0x101, 0x826f, 0x101, 0x8ad2, 0x101, 0x91cf,
+ 0x101, 0x52f5, 0x101, 0x5442, 0x101, 0x5973, 0x101, 0x5eec,
+ 0x101, 0x65c5, 0x101, 0x6ffe, 0x101, 0x792a, 0x101, 0x95ad,
+ 0x101, 0x9a6a, 0x101, 0x9e97, 0x101, 0x9ece, 0x101, 0x529b,
+ 0x101, 0x66c6, 0x101, 0x6b77, 0x101, 0x8f62, 0x101, 0x5e74,
+ 0x101, 0x6190, 0x101, 0x6200, 0x101, 0x649a, 0x101, 0x6f23,
+ 0x101, 0x7149, 0x101, 0x7489, 0x101, 0x79ca, 0x101, 0x7df4,
+ 0x101, 0x806f, 0x101, 0x8f26, 0x101, 0x84ee, 0x101, 0x9023,
+ 0x101, 0x934a, 0x101, 0x5217, 0x101, 0x52a3, 0x101, 0x54bd,
+ 0x101, 0x70c8, 0x101, 0x88c2, 0x101, 0x8aaa, 0x101, 0x5ec9,
+ 0x101, 0x5ff5, 0x101, 0x637b, 0x101, 0x6bae, 0x101, 0x7c3e,
+ 0x101, 0x7375, 0x101, 0x4ee4, 0x101, 0x56f9, 0x101, 0x5be7,
+ 0x101, 0x5dba, 0x101, 0x601c, 0x101, 0x73b2, 0x101, 0x7469,
+ 0x101, 0x7f9a, 0x101, 0x8046, 0x101, 0x9234, 0x101, 0x96f6,
+ 0x101, 0x9748, 0x101, 0x9818, 0x101, 0x4f8b, 0x101, 0x79ae,
+ 0x101, 0x91b4, 0x101, 0x96b8, 0x101, 0x60e1, 0x101, 0x4e86,
+ 0x101, 0x50da, 0x101, 0x5bee, 0x101, 0x5c3f, 0x101, 0x6599,
+ 0x101, 0x6a02, 0x101, 0x71ce, 0x101, 0x7642, 0x101, 0x84fc,
+ 0x101, 0x907c, 0x101, 0x9f8d, 0x101, 0x6688, 0x101, 0x962e,
+ 0x101, 0x5289, 0x101, 0x677b, 0x101, 0x67f3, 0x101, 0x6d41,
+ 0x101, 0x6e9c, 0x101, 0x7409, 0x101, 0x7559, 0x101, 0x786b,
+ 0x101, 0x7d10, 0x101, 0x985e, 0x101, 0x516d, 0x101, 0x622e,
+ 0x101, 0x9678, 0x101, 0x502b, 0x101, 0x5d19, 0x101, 0x6dea,
+ 0x101, 0x8f2a, 0x101, 0x5f8b, 0x101, 0x6144, 0x101, 0x6817,
+ 0x101, 0x7387, 0x101, 0x9686, 0x101, 0x5229, 0x101, 0x540f,
+ 0x101, 0x5c65, 0x101, 0x6613, 0x101, 0x674e, 0x101, 0x68a8,
+ 0x101, 0x6ce5, 0x101, 0x7406, 0x101, 0x75e2, 0x101, 0x7f79,
+ 0x101, 0x88cf, 0x101, 0x88e1, 0x101, 0x91cc, 0x101, 0x96e2,
+ 0x101, 0x533f, 0x101, 0x6eba, 0x101, 0x541d, 0x101, 0x71d0,
+ 0x101, 0x7498, 0x101, 0x85fa, 0x101, 0x96a3, 0x101, 0x9c57,
+ 0x101, 0x9e9f, 0x101, 0x6797, 0x101, 0x6dcb, 0x101, 0x81e8,
+ 0x101, 0x7acb, 0x101, 0x7b20, 0x101, 0x7c92, 0x101, 0x72c0,
+ 0x101, 0x7099, 0x101, 0x8b58, 0x101, 0x4ec0, 0x101, 0x8336,
+ 0x101, 0x523a, 0x101, 0x5207, 0x101, 0x5ea6, 0x101, 0x62d3,
+ 0x101, 0x7cd6, 0x101, 0x5b85, 0x101, 0x6d1e, 0x101, 0x66b4,
+ 0x101, 0x8f3b, 0x101, 0x884c, 0x101, 0x964d, 0x101, 0x898b,
+ 0x101, 0x5ed3, 0x101, 0x5140, 0x101, 0x55c0, 0x101, 0x585a,
+ 0x101, 0x6674, 0x101, 0x51de, 0x101, 0x732a, 0x101, 0x76ca,
+ 0x101, 0x793c, 0x101, 0x795e, 0x101, 0x7965, 0x101, 0x798f,
+ 0x101, 0x9756, 0x101, 0x7cbe, 0x101, 0x7fbd, 0x101, 0x8612,
+ 0x101, 0x8af8, 0x101, 0x9038, 0x101, 0x90fd, 0x101, 0x98ef,
+ 0x101, 0x98fc, 0x101, 0x9928, 0x101, 0x9db4, 0x101, 0x90de,
+ 0x101, 0x96b7, 0x101, 0x4fae, 0x101, 0x50e7, 0x101, 0x514d,
+ 0x101, 0x52c9, 0x101, 0x52e4, 0x101, 0x5351, 0x101, 0x559d,
+ 0x101, 0x5606, 0x101, 0x5668, 0x101, 0x5840, 0x101, 0x58a8,
+ 0x101, 0x5c64, 0x101, 0x5c6e, 0x101, 0x6094, 0x101, 0x6168,
+ 0x101, 0x618e, 0x101, 0x61f2, 0x101, 0x654f, 0x101, 0x65e2,
+ 0x101, 0x6691, 0x101, 0x6885, 0x101, 0x6d77, 0x101, 0x6e1a,
+ 0x101, 0x6f22, 0x101, 0x716e, 0x101, 0x722b, 0x101, 0x7422,
+ 0x101, 0x7891, 0x101, 0x793e, 0x101, 0x7949, 0x101, 0x7948,
+ 0x101, 0x7950, 0x101, 0x7956, 0x101, 0x795d, 0x101, 0x798d,
+ 0x101, 0x798e, 0x101, 0x7a40, 0x101, 0x7a81, 0x101, 0x7bc0,
+ 0x101, 0x7df4, 0x101, 0x7e09, 0x101, 0x7e41, 0x101, 0x7f72,
+ 0x101, 0x8005, 0x101, 0x81ed, 0x101, 0x8279, 0x101, 0x8279,
+ 0x101, 0x8457, 0x101, 0x8910, 0x101, 0x8996, 0x101, 0x8b01,
+ 0x101, 0x8b39, 0x101, 0x8cd3, 0x101, 0x8d08, 0x101, 0x8fb6,
+ 0x101, 0x9038, 0x101, 0x96e3, 0x101, 0x97ff, 0x101, 0x983b,
+ 0x101, 0x6075, 0x201, 0xd850, 0xdeee, 0x101, 0x8218, 0x101,
+ 0x4e26, 0x101, 0x51b5, 0x101, 0x5168, 0x101, 0x4f80, 0x101,
+ 0x5145, 0x101, 0x5180, 0x101, 0x52c7, 0x101, 0x52fa, 0x101,
+ 0x559d, 0x101, 0x5555, 0x101, 0x5599, 0x101, 0x55e2, 0x101,
+ 0x585a, 0x101, 0x58b3, 0x101, 0x5944, 0x101, 0x5954, 0x101,
+ 0x5a62, 0x101, 0x5b28, 0x101, 0x5ed2, 0x101, 0x5ed9, 0x101,
+ 0x5f69, 0x101, 0x5fad, 0x101, 0x60d8, 0x101, 0x614e, 0x101,
+ 0x6108, 0x101, 0x618e, 0x101, 0x6160, 0x101, 0x61f2, 0x101,
+ 0x6234, 0x101, 0x63c4, 0x101, 0x641c, 0x101, 0x6452, 0x101,
+ 0x6556, 0x101, 0x6674, 0x101, 0x6717, 0x101, 0x671b, 0x101,
+ 0x6756, 0x101, 0x6b79, 0x101, 0x6bba, 0x101, 0x6d41, 0x101,
+ 0x6edb, 0x101, 0x6ecb, 0x101, 0x6f22, 0x101, 0x701e, 0x101,
+ 0x716e, 0x101, 0x77a7, 0x101, 0x7235, 0x101, 0x72af, 0x101,
+ 0x732a, 0x101, 0x7471, 0x101, 0x7506, 0x101, 0x753b, 0x101,
+ 0x761d, 0x101, 0x761f, 0x101, 0x76ca, 0x101, 0x76db, 0x101,
+ 0x76f4, 0x101, 0x774a, 0x101, 0x7740, 0x101, 0x78cc, 0x101,
+ 0x7ab1, 0x101, 0x7bc0, 0x101, 0x7c7b, 0x101, 0x7d5b, 0x101,
+ 0x7df4, 0x101, 0x7f3e, 0x101, 0x8005, 0x101, 0x8352, 0x101,
+ 0x83ef, 0x101, 0x8779, 0x101, 0x8941, 0x101, 0x8986, 0x101,
+ 0x8996, 0x101, 0x8abf, 0x101, 0x8af8, 0x101, 0x8acb, 0x101,
+ 0x8b01, 0x101, 0x8afe, 0x101, 0x8aed, 0x101, 0x8b39, 0x101,
+ 0x8b8a, 0x101, 0x8d08, 0x101, 0x8f38, 0x101, 0x9072, 0x101,
+ 0x9199, 0x101, 0x9276, 0x101, 0x967c, 0x101, 0x96e3, 0x101,
+ 0x9756, 0x101, 0x97db, 0x101, 0x97ff, 0x101, 0x980b, 0x101,
+ 0x983b, 0x101, 0x9b12, 0x101, 0x9f9c, 0x201, 0xd84a, 0xdc4a,
+ 0x201, 0xd84a, 0xdc44, 0x201, 0xd84c, 0xdfd5, 0x101, 0x3b9d,
+ 0x101, 0x4018, 0x101, 0x4039, 0x201, 0xd854, 0xde49, 0x201,
+ 0xd857, 0xdcd0, 0x201, 0xd85f, 0xded3, 0x101, 0x9f43, 0x101,
+ 0x9f8e, 0x210, 0x66, 0x66, 0x210, 0x66, 0x69, 0x210,
+ 0x66, 0x6c, 0x310, 0x66, 0x66, 0x69, 0x310, 0x66,
+ 0x66, 0x6c, 0x210, 0x17f, 0x74, 0x210, 0x73, 0x74,
+ 0x210, 0x574, 0x576, 0x210, 0x574, 0x565, 0x210, 0x574,
+ 0x56b, 0x210, 0x57e, 0x576, 0x210, 0x574, 0x56d, 0x201,
+ 0x5d9, 0x5b4, 0x201, 0x5f2, 0x5b7, 0x102, 0x5e2, 0x102,
+ 0x5d0, 0x102, 0x5d3, 0x102, 0x5d4, 0x102, 0x5db, 0x102,
+ 0x5dc, 0x102, 0x5dd, 0x102, 0x5e8, 0x102, 0x5ea, 0x102,
+ 0x2b, 0x201, 0x5e9, 0x5c1, 0x201, 0x5e9, 0x5c2, 0x201,
+ 0xfb49, 0x5c1, 0x201, 0xfb49, 0x5c2, 0x201, 0x5d0, 0x5b7,
+ 0x201, 0x5d0, 0x5b8, 0x201, 0x5d0, 0x5bc, 0x201, 0x5d1,
+ 0x5bc, 0x201, 0x5d2, 0x5bc, 0x201, 0x5d3, 0x5bc, 0x201,
+ 0x5d4, 0x5bc, 0x201, 0x5d5, 0x5bc, 0x201, 0x5d6, 0x5bc,
+ 0x201, 0x5d8, 0x5bc, 0x201, 0x5d9, 0x5bc, 0x201, 0x5da,
+ 0x5bc, 0x201, 0x5db, 0x5bc, 0x201, 0x5dc, 0x5bc, 0x201,
+ 0x5de, 0x5bc, 0x201, 0x5e0, 0x5bc, 0x201, 0x5e1, 0x5bc,
+ 0x201, 0x5e3, 0x5bc, 0x201, 0x5e4, 0x5bc, 0x201, 0x5e6,
+ 0x5bc, 0x201, 0x5e7, 0x5bc, 0x201, 0x5e8, 0x5bc, 0x201,
+ 0x5e9, 0x5bc, 0x201, 0x5ea, 0x5bc, 0x201, 0x5d5, 0x5b9,
+ 0x201, 0x5d1, 0x5bf, 0x201, 0x5db, 0x5bf, 0x201, 0x5e4,
+ 0x5bf, 0x210, 0x5d0, 0x5dc, 0x107, 0x671, 0x106, 0x671,
+ 0x107, 0x67b, 0x106, 0x67b, 0x104, 0x67b, 0x105, 0x67b,
+ 0x107, 0x67e, 0x106, 0x67e, 0x104, 0x67e, 0x105, 0x67e,
+ 0x107, 0x680, 0x106, 0x680, 0x104, 0x680, 0x105, 0x680,
+ 0x107, 0x67a, 0x106, 0x67a, 0x104, 0x67a, 0x105, 0x67a,
+ 0x107, 0x67f, 0x106, 0x67f, 0x104, 0x67f, 0x105, 0x67f,
+ 0x107, 0x679, 0x106, 0x679, 0x104, 0x679, 0x105, 0x679,
+ 0x107, 0x6a4, 0x106, 0x6a4, 0x104, 0x6a4, 0x105, 0x6a4,
+ 0x107, 0x6a6, 0x106, 0x6a6, 0x104, 0x6a6, 0x105, 0x6a6,
+ 0x107, 0x684, 0x106, 0x684, 0x104, 0x684, 0x105, 0x684,
+ 0x107, 0x683, 0x106, 0x683, 0x104, 0x683, 0x105, 0x683,
+ 0x107, 0x686, 0x106, 0x686, 0x104, 0x686, 0x105, 0x686,
+ 0x107, 0x687, 0x106, 0x687, 0x104, 0x687, 0x105, 0x687,
+ 0x107, 0x68d, 0x106, 0x68d, 0x107, 0x68c, 0x106, 0x68c,
+ 0x107, 0x68e, 0x106, 0x68e, 0x107, 0x688, 0x106, 0x688,
+ 0x107, 0x698, 0x106, 0x698, 0x107, 0x691, 0x106, 0x691,
+ 0x107, 0x6a9, 0x106, 0x6a9, 0x104, 0x6a9, 0x105, 0x6a9,
+ 0x107, 0x6af, 0x106, 0x6af, 0x104, 0x6af, 0x105, 0x6af,
+ 0x107, 0x6b3, 0x106, 0x6b3, 0x104, 0x6b3, 0x105, 0x6b3,
+ 0x107, 0x6b1, 0x106, 0x6b1, 0x104, 0x6b1, 0x105, 0x6b1,
+ 0x107, 0x6ba, 0x106, 0x6ba, 0x107, 0x6bb, 0x106, 0x6bb,
+ 0x104, 0x6bb, 0x105, 0x6bb, 0x107, 0x6c0, 0x106, 0x6c0,
+ 0x107, 0x6c1, 0x106, 0x6c1, 0x104, 0x6c1, 0x105, 0x6c1,
+ 0x107, 0x6be, 0x106, 0x6be, 0x104, 0x6be, 0x105, 0x6be,
+ 0x107, 0x6d2, 0x106, 0x6d2, 0x107, 0x6d3, 0x106, 0x6d3,
+ 0x107, 0x6ad, 0x106, 0x6ad, 0x104, 0x6ad, 0x105, 0x6ad,
+ 0x107, 0x6c7, 0x106, 0x6c7, 0x107, 0x6c6, 0x106, 0x6c6,
+ 0x107, 0x6c8, 0x106, 0x6c8, 0x107, 0x677, 0x107, 0x6cb,
+ 0x106, 0x6cb, 0x107, 0x6c5, 0x106, 0x6c5, 0x107, 0x6c9,
+ 0x106, 0x6c9, 0x107, 0x6d0, 0x106, 0x6d0, 0x104, 0x6d0,
+ 0x105, 0x6d0, 0x104, 0x649, 0x105, 0x649, 0x207, 0x626,
+ 0x627, 0x206, 0x626, 0x627, 0x207, 0x626, 0x6d5, 0x206,
+ 0x626, 0x6d5, 0x207, 0x626, 0x648, 0x206, 0x626, 0x648,
+ 0x207, 0x626, 0x6c7, 0x206, 0x626, 0x6c7, 0x207, 0x626,
+ 0x6c6, 0x206, 0x626, 0x6c6, 0x207, 0x626, 0x6c8, 0x206,
+ 0x626, 0x6c8, 0x207, 0x626, 0x6d0, 0x206, 0x626, 0x6d0,
+ 0x204, 0x626, 0x6d0, 0x207, 0x626, 0x649, 0x206, 0x626,
+ 0x649, 0x204, 0x626, 0x649, 0x107, 0x6cc, 0x106, 0x6cc,
+ 0x104, 0x6cc, 0x105, 0x6cc, 0x207, 0x626, 0x62c, 0x207,
+ 0x626, 0x62d, 0x207, 0x626, 0x645, 0x207, 0x626, 0x649,
+ 0x207, 0x626, 0x64a, 0x207, 0x628, 0x62c, 0x207, 0x628,
+ 0x62d, 0x207, 0x628, 0x62e, 0x207, 0x628, 0x645, 0x207,
+ 0x628, 0x649, 0x207, 0x628, 0x64a, 0x207, 0x62a, 0x62c,
+ 0x207, 0x62a, 0x62d, 0x207, 0x62a, 0x62e, 0x207, 0x62a,
+ 0x645, 0x207, 0x62a, 0x649, 0x207, 0x62a, 0x64a, 0x207,
+ 0x62b, 0x62c, 0x207, 0x62b, 0x645, 0x207, 0x62b, 0x649,
+ 0x207, 0x62b, 0x64a, 0x207, 0x62c, 0x62d, 0x207, 0x62c,
+ 0x645, 0x207, 0x62d, 0x62c, 0x207, 0x62d, 0x645, 0x207,
+ 0x62e, 0x62c, 0x207, 0x62e, 0x62d, 0x207, 0x62e, 0x645,
+ 0x207, 0x633, 0x62c, 0x207, 0x633, 0x62d, 0x207, 0x633,
+ 0x62e, 0x207, 0x633, 0x645, 0x207, 0x635, 0x62d, 0x207,
+ 0x635, 0x645, 0x207, 0x636, 0x62c, 0x207, 0x636, 0x62d,
+ 0x207, 0x636, 0x62e, 0x207, 0x636, 0x645, 0x207, 0x637,
+ 0x62d, 0x207, 0x637, 0x645, 0x207, 0x638, 0x645, 0x207,
+ 0x639, 0x62c, 0x207, 0x639, 0x645, 0x207, 0x63a, 0x62c,
+ 0x207, 0x63a, 0x645, 0x207, 0x641, 0x62c, 0x207, 0x641,
+ 0x62d, 0x207, 0x641, 0x62e, 0x207, 0x641, 0x645, 0x207,
+ 0x641, 0x649, 0x207, 0x641, 0x64a, 0x207, 0x642, 0x62d,
+ 0x207, 0x642, 0x645, 0x207, 0x642, 0x649, 0x207, 0x642,
+ 0x64a, 0x207, 0x643, 0x627, 0x207, 0x643, 0x62c, 0x207,
+ 0x643, 0x62d, 0x207, 0x643, 0x62e, 0x207, 0x643, 0x644,
+ 0x207, 0x643, 0x645, 0x207, 0x643, 0x649, 0x207, 0x643,
+ 0x64a, 0x207, 0x644, 0x62c, 0x207, 0x644, 0x62d, 0x207,
+ 0x644, 0x62e, 0x207, 0x644, 0x645, 0x207, 0x644, 0x649,
+ 0x207, 0x644, 0x64a, 0x207, 0x645, 0x62c, 0x207, 0x645,
+ 0x62d, 0x207, 0x645, 0x62e, 0x207, 0x645, 0x645, 0x207,
+ 0x645, 0x649, 0x207, 0x645, 0x64a, 0x207, 0x646, 0x62c,
+ 0x207, 0x646, 0x62d, 0x207, 0x646, 0x62e, 0x207, 0x646,
+ 0x645, 0x207, 0x646, 0x649, 0x207, 0x646, 0x64a, 0x207,
+ 0x647, 0x62c, 0x207, 0x647, 0x645, 0x207, 0x647, 0x649,
+ 0x207, 0x647, 0x64a, 0x207, 0x64a, 0x62c, 0x207, 0x64a,
+ 0x62d, 0x207, 0x64a, 0x62e, 0x207, 0x64a, 0x645, 0x207,
+ 0x64a, 0x649, 0x207, 0x64a, 0x64a, 0x207, 0x630, 0x670,
+ 0x207, 0x631, 0x670, 0x207, 0x649, 0x670, 0x307, 0x20,
+ 0x64c, 0x651, 0x307, 0x20, 0x64d, 0x651, 0x307, 0x20,
+ 0x64e, 0x651, 0x307, 0x20, 0x64f, 0x651, 0x307, 0x20,
+ 0x650, 0x651, 0x307, 0x20, 0x651, 0x670, 0x206, 0x626,
+ 0x631, 0x206, 0x626, 0x632, 0x206, 0x626, 0x645, 0x206,
+ 0x626, 0x646, 0x206, 0x626, 0x649, 0x206, 0x626, 0x64a,
+ 0x206, 0x628, 0x631, 0x206, 0x628, 0x632, 0x206, 0x628,
+ 0x645, 0x206, 0x628, 0x646, 0x206, 0x628, 0x649, 0x206,
+ 0x628, 0x64a, 0x206, 0x62a, 0x631, 0x206, 0x62a, 0x632,
+ 0x206, 0x62a, 0x645, 0x206, 0x62a, 0x646, 0x206, 0x62a,
+ 0x649, 0x206, 0x62a, 0x64a, 0x206, 0x62b, 0x631, 0x206,
+ 0x62b, 0x632, 0x206, 0x62b, 0x645, 0x206, 0x62b, 0x646,
+ 0x206, 0x62b, 0x649, 0x206, 0x62b, 0x64a, 0x206, 0x641,
+ 0x649, 0x206, 0x641, 0x64a, 0x206, 0x642, 0x649, 0x206,
+ 0x642, 0x64a, 0x206, 0x643, 0x627, 0x206, 0x643, 0x644,
+ 0x206, 0x643, 0x645, 0x206, 0x643, 0x649, 0x206, 0x643,
+ 0x64a, 0x206, 0x644, 0x645, 0x206, 0x644, 0x649, 0x206,
+ 0x644, 0x64a, 0x206, 0x645, 0x627, 0x206, 0x645, 0x645,
+ 0x206, 0x646, 0x631, 0x206, 0x646, 0x632, 0x206, 0x646,
+ 0x645, 0x206, 0x646, 0x646, 0x206, 0x646, 0x649, 0x206,
+ 0x646, 0x64a, 0x206, 0x649, 0x670, 0x206, 0x64a, 0x631,
+ 0x206, 0x64a, 0x632, 0x206, 0x64a, 0x645, 0x206, 0x64a,
+ 0x646, 0x206, 0x64a, 0x649, 0x206, 0x64a, 0x64a, 0x204,
+ 0x626, 0x62c, 0x204, 0x626, 0x62d, 0x204, 0x626, 0x62e,
+ 0x204, 0x626, 0x645, 0x204, 0x626, 0x647, 0x204, 0x628,
+ 0x62c, 0x204, 0x628, 0x62d, 0x204, 0x628, 0x62e, 0x204,
+ 0x628, 0x645, 0x204, 0x628, 0x647, 0x204, 0x62a, 0x62c,
+ 0x204, 0x62a, 0x62d, 0x204, 0x62a, 0x62e, 0x204, 0x62a,
+ 0x645, 0x204, 0x62a, 0x647, 0x204, 0x62b, 0x645, 0x204,
+ 0x62c, 0x62d, 0x204, 0x62c, 0x645, 0x204, 0x62d, 0x62c,
+ 0x204, 0x62d, 0x645, 0x204, 0x62e, 0x62c, 0x204, 0x62e,
+ 0x645, 0x204, 0x633, 0x62c, 0x204, 0x633, 0x62d, 0x204,
+ 0x633, 0x62e, 0x204, 0x633, 0x645, 0x204, 0x635, 0x62d,
+ 0x204, 0x635, 0x62e, 0x204, 0x635, 0x645, 0x204, 0x636,
+ 0x62c, 0x204, 0x636, 0x62d, 0x204, 0x636, 0x62e, 0x204,
+ 0x636, 0x645, 0x204, 0x637, 0x62d, 0x204, 0x638, 0x645,
+ 0x204, 0x639, 0x62c, 0x204, 0x639, 0x645, 0x204, 0x63a,
+ 0x62c, 0x204, 0x63a, 0x645, 0x204, 0x641, 0x62c, 0x204,
+ 0x641, 0x62d, 0x204, 0x641, 0x62e, 0x204, 0x641, 0x645,
+ 0x204, 0x642, 0x62d, 0x204, 0x642, 0x645, 0x204, 0x643,
+ 0x62c, 0x204, 0x643, 0x62d, 0x204, 0x643, 0x62e, 0x204,
+ 0x643, 0x644, 0x204, 0x643, 0x645, 0x204, 0x644, 0x62c,
+ 0x204, 0x644, 0x62d, 0x204, 0x644, 0x62e, 0x204, 0x644,
+ 0x645, 0x204, 0x644, 0x647, 0x204, 0x645, 0x62c, 0x204,
+ 0x645, 0x62d, 0x204, 0x645, 0x62e, 0x204, 0x645, 0x645,
+ 0x204, 0x646, 0x62c, 0x204, 0x646, 0x62d, 0x204, 0x646,
+ 0x62e, 0x204, 0x646, 0x645, 0x204, 0x646, 0x647, 0x204,
+ 0x647, 0x62c, 0x204, 0x647, 0x645, 0x204, 0x647, 0x670,
+ 0x204, 0x64a, 0x62c, 0x204, 0x64a, 0x62d, 0x204, 0x64a,
+ 0x62e, 0x204, 0x64a, 0x645, 0x204, 0x64a, 0x647, 0x205,
+ 0x626, 0x645, 0x205, 0x626, 0x647, 0x205, 0x628, 0x645,
+ 0x205, 0x628, 0x647, 0x205, 0x62a, 0x645, 0x205, 0x62a,
+ 0x647, 0x205, 0x62b, 0x645, 0x205, 0x62b, 0x647, 0x205,
+ 0x633, 0x645, 0x205, 0x633, 0x647, 0x205, 0x634, 0x645,
+ 0x205, 0x634, 0x647, 0x205, 0x643, 0x644, 0x205, 0x643,
+ 0x645, 0x205, 0x644, 0x645, 0x205, 0x646, 0x645, 0x205,
+ 0x646, 0x647, 0x205, 0x64a, 0x645, 0x205, 0x64a, 0x647,
+ 0x305, 0x640, 0x64e, 0x651, 0x305, 0x640, 0x64f, 0x651,
+ 0x305, 0x640, 0x650, 0x651, 0x207, 0x637, 0x649, 0x207,
+ 0x637, 0x64a, 0x207, 0x639, 0x649, 0x207, 0x639, 0x64a,
+ 0x207, 0x63a, 0x649, 0x207, 0x63a, 0x64a, 0x207, 0x633,
+ 0x649, 0x207, 0x633, 0x64a, 0x207, 0x634, 0x649, 0x207,
+ 0x634, 0x64a, 0x207, 0x62d, 0x649, 0x207, 0x62d, 0x64a,
+ 0x207, 0x62c, 0x649, 0x207, 0x62c, 0x64a, 0x207, 0x62e,
+ 0x649, 0x207, 0x62e, 0x64a, 0x207, 0x635, 0x649, 0x207,
+ 0x635, 0x64a, 0x207, 0x636, 0x649, 0x207, 0x636, 0x64a,
+ 0x207, 0x634, 0x62c, 0x207, 0x634, 0x62d, 0x207, 0x634,
+ 0x62e, 0x207, 0x634, 0x645, 0x207, 0x634, 0x631, 0x207,
+ 0x633, 0x631, 0x207, 0x635, 0x631, 0x207, 0x636, 0x631,
+ 0x206, 0x637, 0x649, 0x206, 0x637, 0x64a, 0x206, 0x639,
+ 0x649, 0x206, 0x639, 0x64a, 0x206, 0x63a, 0x649, 0x206,
+ 0x63a, 0x64a, 0x206, 0x633, 0x649, 0x206, 0x633, 0x64a,
+ 0x206, 0x634, 0x649, 0x206, 0x634, 0x64a, 0x206, 0x62d,
+ 0x649, 0x206, 0x62d, 0x64a, 0x206, 0x62c, 0x649, 0x206,
+ 0x62c, 0x64a, 0x206, 0x62e, 0x649, 0x206, 0x62e, 0x64a,
+ 0x206, 0x635, 0x649, 0x206, 0x635, 0x64a, 0x206, 0x636,
+ 0x649, 0x206, 0x636, 0x64a, 0x206, 0x634, 0x62c, 0x206,
+ 0x634, 0x62d, 0x206, 0x634, 0x62e, 0x206, 0x634, 0x645,
+ 0x206, 0x634, 0x631, 0x206, 0x633, 0x631, 0x206, 0x635,
+ 0x631, 0x206, 0x636, 0x631, 0x204, 0x634, 0x62c, 0x204,
+ 0x634, 0x62d, 0x204, 0x634, 0x62e, 0x204, 0x634, 0x645,
+ 0x204, 0x633, 0x647, 0x204, 0x634, 0x647, 0x204, 0x637,
+ 0x645, 0x205, 0x633, 0x62c, 0x205, 0x633, 0x62d, 0x205,
+ 0x633, 0x62e, 0x205, 0x634, 0x62c, 0x205, 0x634, 0x62d,
+ 0x205, 0x634, 0x62e, 0x205, 0x637, 0x645, 0x205, 0x638,
+ 0x645, 0x206, 0x627, 0x64b, 0x207, 0x627, 0x64b, 0x304,
+ 0x62a, 0x62c, 0x645, 0x306, 0x62a, 0x62d, 0x62c, 0x304,
+ 0x62a, 0x62d, 0x62c, 0x304, 0x62a, 0x62d, 0x645, 0x304,
+ 0x62a, 0x62e, 0x645, 0x304, 0x62a, 0x645, 0x62c, 0x304,
+ 0x62a, 0x645, 0x62d, 0x304, 0x62a, 0x645, 0x62e, 0x306,
+ 0x62c, 0x645, 0x62d, 0x304, 0x62c, 0x645, 0x62d, 0x306,
+ 0x62d, 0x645, 0x64a, 0x306, 0x62d, 0x645, 0x649, 0x304,
+ 0x633, 0x62d, 0x62c, 0x304, 0x633, 0x62c, 0x62d, 0x306,
+ 0x633, 0x62c, 0x649, 0x306, 0x633, 0x645, 0x62d, 0x304,
+ 0x633, 0x645, 0x62d, 0x304, 0x633, 0x645, 0x62c, 0x306,
+ 0x633, 0x645, 0x645, 0x304, 0x633, 0x645, 0x645, 0x306,
+ 0x635, 0x62d, 0x62d, 0x304, 0x635, 0x62d, 0x62d, 0x306,
+ 0x635, 0x645, 0x645, 0x306, 0x634, 0x62d, 0x645, 0x304,
+ 0x634, 0x62d, 0x645, 0x306, 0x634, 0x62c, 0x64a, 0x306,
+ 0x634, 0x645, 0x62e, 0x304, 0x634, 0x645, 0x62e, 0x306,
+ 0x634, 0x645, 0x645, 0x304, 0x634, 0x645, 0x645, 0x306,
+ 0x636, 0x62d, 0x649, 0x306, 0x636, 0x62e, 0x645, 0x304,
+ 0x636, 0x62e, 0x645, 0x306, 0x637, 0x645, 0x62d, 0x304,
+ 0x637, 0x645, 0x62d, 0x304, 0x637, 0x645, 0x645, 0x306,
+ 0x637, 0x645, 0x64a, 0x306, 0x639, 0x62c, 0x645, 0x306,
+ 0x639, 0x645, 0x645, 0x304, 0x639, 0x645, 0x645, 0x306,
+ 0x639, 0x645, 0x649, 0x306, 0x63a, 0x645, 0x645, 0x306,
+ 0x63a, 0x645, 0x64a, 0x306, 0x63a, 0x645, 0x649, 0x306,
+ 0x641, 0x62e, 0x645, 0x304, 0x641, 0x62e, 0x645, 0x306,
+ 0x642, 0x645, 0x62d, 0x306, 0x642, 0x645, 0x645, 0x306,
+ 0x644, 0x62d, 0x645, 0x306, 0x644, 0x62d, 0x64a, 0x306,
+ 0x644, 0x62d, 0x649, 0x304, 0x644, 0x62c, 0x62c, 0x306,
+ 0x644, 0x62c, 0x62c, 0x306, 0x644, 0x62e, 0x645, 0x304,
+ 0x644, 0x62e, 0x645, 0x306, 0x644, 0x645, 0x62d, 0x304,
+ 0x644, 0x645, 0x62d, 0x304, 0x645, 0x62d, 0x62c, 0x304,
+ 0x645, 0x62d, 0x645, 0x306, 0x645, 0x62d, 0x64a, 0x304,
+ 0x645, 0x62c, 0x62d, 0x304, 0x645, 0x62c, 0x645, 0x304,
+ 0x645, 0x62e, 0x62c, 0x304, 0x645, 0x62e, 0x645, 0x304,
+ 0x645, 0x62c, 0x62e, 0x304, 0x647, 0x645, 0x62c, 0x304,
+ 0x647, 0x645, 0x645, 0x304, 0x646, 0x62d, 0x645, 0x306,
+ 0x646, 0x62d, 0x649, 0x306, 0x646, 0x62c, 0x645, 0x304,
+ 0x646, 0x62c, 0x645, 0x306, 0x646, 0x62c, 0x649, 0x306,
+ 0x646, 0x645, 0x64a, 0x306, 0x646, 0x645, 0x649, 0x306,
+ 0x64a, 0x645, 0x645, 0x304, 0x64a, 0x645, 0x645, 0x306,
+ 0x628, 0x62e, 0x64a, 0x306, 0x62a, 0x62c, 0x64a, 0x306,
+ 0x62a, 0x62c, 0x649, 0x306, 0x62a, 0x62e, 0x64a, 0x306,
+ 0x62a, 0x62e, 0x649, 0x306, 0x62a, 0x645, 0x64a, 0x306,
+ 0x62a, 0x645, 0x649, 0x306, 0x62c, 0x645, 0x64a, 0x306,
+ 0x62c, 0x62d, 0x649, 0x306, 0x62c, 0x645, 0x649, 0x306,
+ 0x633, 0x62e, 0x649, 0x306, 0x635, 0x62d, 0x64a, 0x306,
+ 0x634, 0x62d, 0x64a, 0x306, 0x636, 0x62d, 0x64a, 0x306,
+ 0x644, 0x62c, 0x64a, 0x306, 0x644, 0x645, 0x64a, 0x306,
+ 0x64a, 0x62d, 0x64a, 0x306, 0x64a, 0x62c, 0x64a, 0x306,
+ 0x64a, 0x645, 0x64a, 0x306, 0x645, 0x645, 0x64a, 0x306,
+ 0x642, 0x645, 0x64a, 0x306, 0x646, 0x62d, 0x64a, 0x304,
+ 0x642, 0x645, 0x62d, 0x304, 0x644, 0x62d, 0x645, 0x306,
+ 0x639, 0x645, 0x64a, 0x306, 0x643, 0x645, 0x64a, 0x304,
+ 0x646, 0x62c, 0x62d, 0x306, 0x645, 0x62e, 0x64a, 0x304,
+ 0x644, 0x62c, 0x645, 0x306, 0x643, 0x645, 0x645, 0x306,
+ 0x644, 0x62c, 0x645, 0x306, 0x646, 0x62c, 0x62d, 0x306,
+ 0x62c, 0x62d, 0x64a, 0x306, 0x62d, 0x62c, 0x64a, 0x306,
+ 0x645, 0x62c, 0x64a, 0x306, 0x641, 0x645, 0x64a, 0x306,
+ 0x628, 0x62d, 0x64a, 0x304, 0x643, 0x645, 0x645, 0x304,
+ 0x639, 0x62c, 0x645, 0x304, 0x635, 0x645, 0x645, 0x306,
+ 0x633, 0x62e, 0x64a, 0x306, 0x646, 0x62c, 0x64a, 0x307,
+ 0x635, 0x644, 0x6d2, 0x307, 0x642, 0x644, 0x6d2, 0x407,
+ 0x627, 0x644, 0x644, 0x647, 0x407, 0x627, 0x643, 0x628,
+ 0x631, 0x407, 0x645, 0x62d, 0x645, 0x62f, 0x407, 0x635,
+ 0x644, 0x639, 0x645, 0x407, 0x631, 0x633, 0x648, 0x644,
+ 0x407, 0x639, 0x644, 0x64a, 0x647, 0x407, 0x648, 0x633,
+ 0x644, 0x645, 0x307, 0x635, 0x644, 0x649, 0x1207, 0x635,
+ 0x644, 0x649, 0x20, 0x627, 0x644, 0x644, 0x647, 0x20,
+ 0x639, 0x644, 0x64a, 0x647, 0x20, 0x648, 0x633, 0x644,
+ 0x645, 0x807, 0x62c, 0x644, 0x20, 0x62c, 0x644, 0x627,
+ 0x644, 0x647, 0x407, 0x631, 0x6cc, 0x627, 0x644, 0x10b,
+ 0x2c, 0x10b, 0x3001, 0x10b, 0x3002, 0x10b, 0x3a, 0x10b,
+ 0x3b, 0x10b, 0x21, 0x10b, 0x3f, 0x10b, 0x3016, 0x10b,
+ 0x3017, 0x10b, 0x2026, 0x10b, 0x2025, 0x10b, 0x2014, 0x10b,
+ 0x2013, 0x10b, 0x5f, 0x10b, 0x5f, 0x10b, 0x28, 0x10b,
+ 0x29, 0x10b, 0x7b, 0x10b, 0x7d, 0x10b, 0x3014, 0x10b,
+ 0x3015, 0x10b, 0x3010, 0x10b, 0x3011, 0x10b, 0x300a, 0x10b,
+ 0x300b, 0x10b, 0x3008, 0x10b, 0x3009, 0x10b, 0x300c, 0x10b,
+ 0x300d, 0x10b, 0x300e, 0x10b, 0x300f, 0x10b, 0x5b, 0x10b,
+ 0x5d, 0x110, 0x203e, 0x110, 0x203e, 0x110, 0x203e, 0x110,
+ 0x203e, 0x110, 0x5f, 0x110, 0x5f, 0x110, 0x5f, 0x10e,
+ 0x2c, 0x10e, 0x3001, 0x10e, 0x2e, 0x10e, 0x3b, 0x10e,
+ 0x3a, 0x10e, 0x3f, 0x10e, 0x21, 0x10e, 0x2014, 0x10e,
+ 0x28, 0x10e, 0x29, 0x10e, 0x7b, 0x10e, 0x7d, 0x10e,
+ 0x3014, 0x10e, 0x3015, 0x10e, 0x23, 0x10e, 0x26, 0x10e,
+ 0x2a, 0x10e, 0x2b, 0x10e, 0x2d, 0x10e, 0x3c, 0x10e,
+ 0x3e, 0x10e, 0x3d, 0x10e, 0x5c, 0x10e, 0x24, 0x10e,
+ 0x25, 0x10e, 0x40, 0x207, 0x20, 0x64b, 0x205, 0x640,
+ 0x64b, 0x207, 0x20, 0x64c, 0x207, 0x20, 0x64d, 0x207,
+ 0x20, 0x64e, 0x205, 0x640, 0x64e, 0x207, 0x20, 0x64f,
+ 0x205, 0x640, 0x64f, 0x207, 0x20, 0x650, 0x205, 0x640,
+ 0x650, 0x207, 0x20, 0x651, 0x205, 0x640, 0x651, 0x207,
+ 0x20, 0x652, 0x205, 0x640, 0x652, 0x107, 0x621, 0x107,
+ 0x622, 0x106, 0x622, 0x107, 0x623, 0x106, 0x623, 0x107,
+ 0x624, 0x106, 0x624, 0x107, 0x625, 0x106, 0x625, 0x107,
+ 0x626, 0x106, 0x626, 0x104, 0x626, 0x105, 0x626, 0x107,
+ 0x627, 0x106, 0x627, 0x107, 0x628, 0x106, 0x628, 0x104,
+ 0x628, 0x105, 0x628, 0x107, 0x629, 0x106, 0x629, 0x107,
+ 0x62a, 0x106, 0x62a, 0x104, 0x62a, 0x105, 0x62a, 0x107,
+ 0x62b, 0x106, 0x62b, 0x104, 0x62b, 0x105, 0x62b, 0x107,
+ 0x62c, 0x106, 0x62c, 0x104, 0x62c, 0x105, 0x62c, 0x107,
+ 0x62d, 0x106, 0x62d, 0x104, 0x62d, 0x105, 0x62d, 0x107,
+ 0x62e, 0x106, 0x62e, 0x104, 0x62e, 0x105, 0x62e, 0x107,
+ 0x62f, 0x106, 0x62f, 0x107, 0x630, 0x106, 0x630, 0x107,
+ 0x631, 0x106, 0x631, 0x107, 0x632, 0x106, 0x632, 0x107,
+ 0x633, 0x106, 0x633, 0x104, 0x633, 0x105, 0x633, 0x107,
+ 0x634, 0x106, 0x634, 0x104, 0x634, 0x105, 0x634, 0x107,
+ 0x635, 0x106, 0x635, 0x104, 0x635, 0x105, 0x635, 0x107,
+ 0x636, 0x106, 0x636, 0x104, 0x636, 0x105, 0x636, 0x107,
+ 0x637, 0x106, 0x637, 0x104, 0x637, 0x105, 0x637, 0x107,
+ 0x638, 0x106, 0x638, 0x104, 0x638, 0x105, 0x638, 0x107,
+ 0x639, 0x106, 0x639, 0x104, 0x639, 0x105, 0x639, 0x107,
+ 0x63a, 0x106, 0x63a, 0x104, 0x63a, 0x105, 0x63a, 0x107,
+ 0x641, 0x106, 0x641, 0x104, 0x641, 0x105, 0x641, 0x107,
+ 0x642, 0x106, 0x642, 0x104, 0x642, 0x105, 0x642, 0x107,
+ 0x643, 0x106, 0x643, 0x104, 0x643, 0x105, 0x643, 0x107,
+ 0x644, 0x106, 0x644, 0x104, 0x644, 0x105, 0x644, 0x107,
+ 0x645, 0x106, 0x645, 0x104, 0x645, 0x105, 0x645, 0x107,
+ 0x646, 0x106, 0x646, 0x104, 0x646, 0x105, 0x646, 0x107,
+ 0x647, 0x106, 0x647, 0x104, 0x647, 0x105, 0x647, 0x107,
+ 0x648, 0x106, 0x648, 0x107, 0x649, 0x106, 0x649, 0x107,
+ 0x64a, 0x106, 0x64a, 0x104, 0x64a, 0x105, 0x64a, 0x207,
+ 0x644, 0x622, 0x206, 0x644, 0x622, 0x207, 0x644, 0x623,
+ 0x206, 0x644, 0x623, 0x207, 0x644, 0x625, 0x206, 0x644,
+ 0x625, 0x207, 0x644, 0x627, 0x206, 0x644, 0x627, 0x10c,
+ 0x21, 0x10c, 0x22, 0x10c, 0x23, 0x10c, 0x24, 0x10c,
+ 0x25, 0x10c, 0x26, 0x10c, 0x27, 0x10c, 0x28, 0x10c,
+ 0x29, 0x10c, 0x2a, 0x10c, 0x2b, 0x10c, 0x2c, 0x10c,
+ 0x2d, 0x10c, 0x2e, 0x10c, 0x2f, 0x10c, 0x30, 0x10c,
+ 0x31, 0x10c, 0x32, 0x10c, 0x33, 0x10c, 0x34, 0x10c,
+ 0x35, 0x10c, 0x36, 0x10c, 0x37, 0x10c, 0x38, 0x10c,
+ 0x39, 0x10c, 0x3a, 0x10c, 0x3b, 0x10c, 0x3c, 0x10c,
+ 0x3d, 0x10c, 0x3e, 0x10c, 0x3f, 0x10c, 0x40, 0x10c,
+ 0x41, 0x10c, 0x42, 0x10c, 0x43, 0x10c, 0x44, 0x10c,
+ 0x45, 0x10c, 0x46, 0x10c, 0x47, 0x10c, 0x48, 0x10c,
+ 0x49, 0x10c, 0x4a, 0x10c, 0x4b, 0x10c, 0x4c, 0x10c,
+ 0x4d, 0x10c, 0x4e, 0x10c, 0x4f, 0x10c, 0x50, 0x10c,
+ 0x51, 0x10c, 0x52, 0x10c, 0x53, 0x10c, 0x54, 0x10c,
+ 0x55, 0x10c, 0x56, 0x10c, 0x57, 0x10c, 0x58, 0x10c,
+ 0x59, 0x10c, 0x5a, 0x10c, 0x5b, 0x10c, 0x5c, 0x10c,
+ 0x5d, 0x10c, 0x5e, 0x10c, 0x5f, 0x10c, 0x60, 0x10c,
+ 0x61, 0x10c, 0x62, 0x10c, 0x63, 0x10c, 0x64, 0x10c,
+ 0x65, 0x10c, 0x66, 0x10c, 0x67, 0x10c, 0x68, 0x10c,
+ 0x69, 0x10c, 0x6a, 0x10c, 0x6b, 0x10c, 0x6c, 0x10c,
+ 0x6d, 0x10c, 0x6e, 0x10c, 0x6f, 0x10c, 0x70, 0x10c,
+ 0x71, 0x10c, 0x72, 0x10c, 0x73, 0x10c, 0x74, 0x10c,
+ 0x75, 0x10c, 0x76, 0x10c, 0x77, 0x10c, 0x78, 0x10c,
+ 0x79, 0x10c, 0x7a, 0x10c, 0x7b, 0x10c, 0x7c, 0x10c,
+ 0x7d, 0x10c, 0x7e, 0x10c, 0x2985, 0x10c, 0x2986, 0x10d,
+ 0x3002, 0x10d, 0x300c, 0x10d, 0x300d, 0x10d, 0x3001, 0x10d,
+ 0x30fb, 0x10d, 0x30f2, 0x10d, 0x30a1, 0x10d, 0x30a3, 0x10d,
+ 0x30a5, 0x10d, 0x30a7, 0x10d, 0x30a9, 0x10d, 0x30e3, 0x10d,
+ 0x30e5, 0x10d, 0x30e7, 0x10d, 0x30c3, 0x10d, 0x30fc, 0x10d,
+ 0x30a2, 0x10d, 0x30a4, 0x10d, 0x30a6, 0x10d, 0x30a8, 0x10d,
+ 0x30aa, 0x10d, 0x30ab, 0x10d, 0x30ad, 0x10d, 0x30af, 0x10d,
+ 0x30b1, 0x10d, 0x30b3, 0x10d, 0x30b5, 0x10d, 0x30b7, 0x10d,
+ 0x30b9, 0x10d, 0x30bb, 0x10d, 0x30bd, 0x10d, 0x30bf, 0x10d,
+ 0x30c1, 0x10d, 0x30c4, 0x10d, 0x30c6, 0x10d, 0x30c8, 0x10d,
+ 0x30ca, 0x10d, 0x30cb, 0x10d, 0x30cc, 0x10d, 0x30cd, 0x10d,
+ 0x30ce, 0x10d, 0x30cf, 0x10d, 0x30d2, 0x10d, 0x30d5, 0x10d,
+ 0x30d8, 0x10d, 0x30db, 0x10d, 0x30de, 0x10d, 0x30df, 0x10d,
+ 0x30e0, 0x10d, 0x30e1, 0x10d, 0x30e2, 0x10d, 0x30e4, 0x10d,
+ 0x30e6, 0x10d, 0x30e8, 0x10d, 0x30e9, 0x10d, 0x30ea, 0x10d,
+ 0x30eb, 0x10d, 0x30ec, 0x10d, 0x30ed, 0x10d, 0x30ef, 0x10d,
+ 0x30f3, 0x10d, 0x3099, 0x10d, 0x309a, 0x10d, 0x3164, 0x10d,
+ 0x3131, 0x10d, 0x3132, 0x10d, 0x3133, 0x10d, 0x3134, 0x10d,
+ 0x3135, 0x10d, 0x3136, 0x10d, 0x3137, 0x10d, 0x3138, 0x10d,
+ 0x3139, 0x10d, 0x313a, 0x10d, 0x313b, 0x10d, 0x313c, 0x10d,
+ 0x313d, 0x10d, 0x313e, 0x10d, 0x313f, 0x10d, 0x3140, 0x10d,
+ 0x3141, 0x10d, 0x3142, 0x10d, 0x3143, 0x10d, 0x3144, 0x10d,
+ 0x3145, 0x10d, 0x3146, 0x10d, 0x3147, 0x10d, 0x3148, 0x10d,
+ 0x3149, 0x10d, 0x314a, 0x10d, 0x314b, 0x10d, 0x314c, 0x10d,
+ 0x314d, 0x10d, 0x314e, 0x10d, 0x314f, 0x10d, 0x3150, 0x10d,
+ 0x3151, 0x10d, 0x3152, 0x10d, 0x3153, 0x10d, 0x3154, 0x10d,
+ 0x3155, 0x10d, 0x3156, 0x10d, 0x3157, 0x10d, 0x3158, 0x10d,
+ 0x3159, 0x10d, 0x315a, 0x10d, 0x315b, 0x10d, 0x315c, 0x10d,
+ 0x315d, 0x10d, 0x315e, 0x10d, 0x315f, 0x10d, 0x3160, 0x10d,
+ 0x3161, 0x10d, 0x3162, 0x10d, 0x3163, 0x10c, 0xa2, 0x10c,
+ 0xa3, 0x10c, 0xac, 0x10c, 0xaf, 0x10c, 0xa6, 0x10c,
+ 0xa5, 0x10c, 0x20a9, 0x10d, 0x2502, 0x10d, 0x2190, 0x10d,
+ 0x2191, 0x10d, 0x2192, 0x10d, 0x2193, 0x10d, 0x25a0, 0x10d,
+ 0x25cb, 0x109, 0x2d0, 0x109, 0x2d1, 0x109, 0xe6, 0x109,
+ 0x299, 0x109, 0x253, 0x109, 0x2a3, 0x109, 0xab66, 0x109,
+ 0x2a5, 0x109, 0x2a4, 0x109, 0x256, 0x109, 0x257, 0x109,
+ 0x1d91, 0x109, 0x258, 0x109, 0x25e, 0x109, 0x2a9, 0x109,
+ 0x264, 0x109, 0x262, 0x109, 0x260, 0x109, 0x29b, 0x109,
+ 0x127, 0x109, 0x29c, 0x109, 0x267, 0x109, 0x284, 0x109,
+ 0x2aa, 0x109, 0x2ab, 0x109, 0x26c, 0x209, 0xd837, 0xdf04,
+ 0x109, 0xa78e, 0x109, 0x26e, 0x209, 0xd837, 0xdf05, 0x109,
+ 0x28e, 0x209, 0xd837, 0xdf06, 0x109, 0xf8, 0x109, 0x276,
+ 0x109, 0x277, 0x109, 0x71, 0x109, 0x27a, 0x209, 0xd837,
+ 0xdf08, 0x109, 0x27d, 0x109, 0x27e, 0x109, 0x280, 0x109,
+ 0x2a8, 0x109, 0x2a6, 0x109, 0xab67, 0x109, 0x2a7, 0x109,
+ 0x288, 0x109, 0x2c71, 0x109, 0x28f, 0x109, 0x2a1, 0x109,
+ 0x2a2, 0x109, 0x298, 0x109, 0x1c0, 0x109, 0x1c1, 0x109,
+ 0x1c2, 0x209, 0xd837, 0xdf0a, 0x209, 0xd837, 0xdf1e, 0x401,
+ 0xd804, 0xdc99, 0xd804, 0xdcba, 0x401, 0xd804, 0xdc9b, 0xd804,
+ 0xdcba, 0x401, 0xd804, 0xdca5, 0xd804, 0xdcba, 0x401, 0xd804,
+ 0xdd31, 0xd804, 0xdd27, 0x401, 0xd804, 0xdd32, 0xd804, 0xdd27,
+ 0x401, 0xd804, 0xdf47, 0xd804, 0xdf3e, 0x401, 0xd804, 0xdf47,
+ 0xd804, 0xdf57, 0x401, 0xd805, 0xdcb9, 0xd805, 0xdcba, 0x401,
+ 0xd805, 0xdcb9, 0xd805, 0xdcb0, 0x401, 0xd805, 0xdcb9, 0xd805,
+ 0xdcbd, 0x401, 0xd805, 0xddb8, 0xd805, 0xddaf, 0x401, 0xd805,
+ 0xddb9, 0xd805, 0xddaf, 0x401, 0xd806, 0xdd35, 0xd806, 0xdd30,
+ 0x401, 0xd834, 0xdd57, 0xd834, 0xdd65, 0x401, 0xd834, 0xdd58,
+ 0xd834, 0xdd65, 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd6e, 0x401,
+ 0xd834, 0xdd5f, 0xd834, 0xdd6f, 0x401, 0xd834, 0xdd5f, 0xd834,
+ 0xdd70, 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd71, 0x401, 0xd834,
+ 0xdd5f, 0xd834, 0xdd72, 0x401, 0xd834, 0xddb9, 0xd834, 0xdd65,
+ 0x401, 0xd834, 0xddba, 0xd834, 0xdd65, 0x401, 0xd834, 0xddbb,
+ 0xd834, 0xdd6e, 0x401, 0xd834, 0xddbc, 0xd834, 0xdd6e, 0x401,
+ 0xd834, 0xddbb, 0xd834, 0xdd6f, 0x401, 0xd834, 0xddbc, 0xd834,
+ 0xdd6f, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x69, 0x102, 0x6a, 0x102,
0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x44, 0x102, 0x45, 0x102, 0x46, 0x102,
- 0x47, 0x102, 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102,
+ 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102, 0x72, 0x102,
+ 0x73, 0x102, 0x74, 0x102, 0x75, 0x102, 0x76, 0x102,
+ 0x77, 0x102, 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102,
+ 0x41, 0x102, 0x42, 0x102, 0x43, 0x102, 0x44, 0x102,
+ 0x45, 0x102, 0x46, 0x102, 0x47, 0x102, 0x48, 0x102,
+ 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102,
0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102,
- 0x51, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, 0x64, 0x102,
- 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, 0x68, 0x102,
+ 0x51, 0x102, 0x52, 0x102, 0x53, 0x102, 0x54, 0x102,
+ 0x55, 0x102, 0x56, 0x102, 0x57, 0x102, 0x58, 0x102,
+ 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102,
+ 0x63, 0x102, 0x64, 0x102, 0x65, 0x102, 0x66, 0x102,
+ 0x67, 0x102, 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102,
+ 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102,
+ 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102, 0x72, 0x102,
+ 0x73, 0x102, 0x74, 0x102, 0x75, 0x102, 0x76, 0x102,
+ 0x77, 0x102, 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102,
+ 0x41, 0x102, 0x43, 0x102, 0x44, 0x102, 0x47, 0x102,
+ 0x4a, 0x102, 0x4b, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x53, 0x102, 0x54, 0x102,
+ 0x55, 0x102, 0x56, 0x102, 0x57, 0x102, 0x58, 0x102,
+ 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102,
+ 0x63, 0x102, 0x64, 0x102, 0x66, 0x102, 0x68, 0x102,
0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102,
- 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102,
- 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, 0x74, 0x102,
- 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, 0x78, 0x102,
- 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102,
+ 0x6d, 0x102, 0x6e, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
- 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102,
- 0x4d, 0x102, 0x4f, 0x102, 0x53, 0x102, 0x54, 0x102,
- 0x55, 0x102, 0x56, 0x102, 0x57, 0x102, 0x58, 0x102,
- 0x59, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102,
- 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102,
- 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102,
- 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102,
- 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102,
- 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102,
- 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102,
- 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102,
- 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102,
- 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102,
- 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102,
- 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102,
- 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102,
- 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x131, 0x102,
- 0x237, 0x102, 0x391, 0x102, 0x392, 0x102, 0x393, 0x102,
- 0x394, 0x102, 0x395, 0x102, 0x396, 0x102, 0x397, 0x102,
- 0x398, 0x102, 0x399, 0x102, 0x39a, 0x102, 0x39b, 0x102,
- 0x39c, 0x102, 0x39d, 0x102, 0x39e, 0x102, 0x39f, 0x102,
- 0x3a0, 0x102, 0x3a1, 0x102, 0x3f4, 0x102, 0x3a3, 0x102,
- 0x3a4, 0x102, 0x3a5, 0x102, 0x3a6, 0x102, 0x3a7, 0x102,
- 0x3a8, 0x102, 0x3a9, 0x102, 0x2207, 0x102, 0x3b1, 0x102,
- 0x3b2, 0x102, 0x3b3, 0x102, 0x3b4, 0x102, 0x3b5, 0x102,
- 0x3b6, 0x102, 0x3b7, 0x102, 0x3b8, 0x102, 0x3b9, 0x102,
- 0x3ba, 0x102, 0x3bb, 0x102, 0x3bc, 0x102, 0x3bd, 0x102,
- 0x3be, 0x102, 0x3bf, 0x102, 0x3c0, 0x102, 0x3c1, 0x102,
- 0x3c2, 0x102, 0x3c3, 0x102, 0x3c4, 0x102, 0x3c5, 0x102,
- 0x3c6, 0x102, 0x3c7, 0x102, 0x3c8, 0x102, 0x3c9, 0x102,
- 0x2202, 0x102, 0x3f5, 0x102, 0x3d1, 0x102, 0x3f0, 0x102,
- 0x3d5, 0x102, 0x3f1, 0x102, 0x3d6, 0x102, 0x391, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x44, 0x102,
+ 0x45, 0x102, 0x46, 0x102, 0x47, 0x102, 0x4a, 0x102,
+ 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102,
+ 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x61, 0x102, 0x62, 0x102,
+ 0x63, 0x102, 0x64, 0x102, 0x65, 0x102, 0x66, 0x102,
+ 0x67, 0x102, 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102,
+ 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102,
+ 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102, 0x72, 0x102,
+ 0x73, 0x102, 0x74, 0x102, 0x75, 0x102, 0x76, 0x102,
+ 0x77, 0x102, 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102,
+ 0x41, 0x102, 0x42, 0x102, 0x44, 0x102, 0x45, 0x102,
+ 0x46, 0x102, 0x47, 0x102, 0x49, 0x102, 0x4a, 0x102,
+ 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, 0x4f, 0x102,
+ 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, 0x56, 0x102,
+ 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, 0x43, 0x102,
+ 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102,
+ 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102,
+ 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102,
+ 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, 0x53, 0x102,
+ 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, 0x57, 0x102,
+ 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, 0x61, 0x102,
+ 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, 0x65, 0x102,
+ 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, 0x69, 0x102,
+ 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102,
+ 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, 0x71, 0x102,
+ 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, 0x75, 0x102,
+ 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, 0x79, 0x102,
+ 0x7a, 0x102, 0x131, 0x102, 0x237, 0x102, 0x391, 0x102,
0x392, 0x102, 0x393, 0x102, 0x394, 0x102, 0x395, 0x102,
0x396, 0x102, 0x397, 0x102, 0x398, 0x102, 0x399, 0x102,
0x39a, 0x102, 0x39b, 0x102, 0x39c, 0x102, 0x39d, 0x102,
@@ -13396,10 +14320,22 @@ static const unsigned short uc_decomposition_map[] = {
0x3c2, 0x102, 0x3c3, 0x102, 0x3c4, 0x102, 0x3c5, 0x102,
0x3c6, 0x102, 0x3c7, 0x102, 0x3c8, 0x102, 0x3c9, 0x102,
0x2202, 0x102, 0x3f5, 0x102, 0x3d1, 0x102, 0x3f0, 0x102,
- 0x3d5, 0x102, 0x3f1, 0x102, 0x3d6, 0x102, 0x3dc, 0x102,
- 0x3dd, 0x102, 0x30, 0x102, 0x31, 0x102, 0x32, 0x102,
- 0x33, 0x102, 0x34, 0x102, 0x35, 0x102, 0x36, 0x102,
- 0x37, 0x102, 0x38, 0x102, 0x39, 0x102, 0x30, 0x102,
+ 0x3d5, 0x102, 0x3f1, 0x102, 0x3d6, 0x102, 0x391, 0x102,
+ 0x392, 0x102, 0x393, 0x102, 0x394, 0x102, 0x395, 0x102,
+ 0x396, 0x102, 0x397, 0x102, 0x398, 0x102, 0x399, 0x102,
+ 0x39a, 0x102, 0x39b, 0x102, 0x39c, 0x102, 0x39d, 0x102,
+ 0x39e, 0x102, 0x39f, 0x102, 0x3a0, 0x102, 0x3a1, 0x102,
+ 0x3f4, 0x102, 0x3a3, 0x102, 0x3a4, 0x102, 0x3a5, 0x102,
+ 0x3a6, 0x102, 0x3a7, 0x102, 0x3a8, 0x102, 0x3a9, 0x102,
+ 0x2207, 0x102, 0x3b1, 0x102, 0x3b2, 0x102, 0x3b3, 0x102,
+ 0x3b4, 0x102, 0x3b5, 0x102, 0x3b6, 0x102, 0x3b7, 0x102,
+ 0x3b8, 0x102, 0x3b9, 0x102, 0x3ba, 0x102, 0x3bb, 0x102,
+ 0x3bc, 0x102, 0x3bd, 0x102, 0x3be, 0x102, 0x3bf, 0x102,
+ 0x3c0, 0x102, 0x3c1, 0x102, 0x3c2, 0x102, 0x3c3, 0x102,
+ 0x3c4, 0x102, 0x3c5, 0x102, 0x3c6, 0x102, 0x3c7, 0x102,
+ 0x3c8, 0x102, 0x3c9, 0x102, 0x2202, 0x102, 0x3f5, 0x102,
+ 0x3d1, 0x102, 0x3f0, 0x102, 0x3d5, 0x102, 0x3f1, 0x102,
+ 0x3d6, 0x102, 0x3dc, 0x102, 0x3dd, 0x102, 0x30, 0x102,
0x31, 0x102, 0x32, 0x102, 0x33, 0x102, 0x34, 0x102,
0x35, 0x102, 0x36, 0x102, 0x37, 0x102, 0x38, 0x102,
0x39, 0x102, 0x30, 0x102, 0x31, 0x102, 0x32, 0x102,
@@ -13409,7 +14345,25 @@ static const unsigned short uc_decomposition_map[] = {
0x35, 0x102, 0x36, 0x102, 0x37, 0x102, 0x38, 0x102,
0x39, 0x102, 0x30, 0x102, 0x31, 0x102, 0x32, 0x102,
0x33, 0x102, 0x34, 0x102, 0x35, 0x102, 0x36, 0x102,
- 0x37, 0x102, 0x38, 0x102, 0x39, 0x102, 0x627, 0x102,
+ 0x37, 0x102, 0x38, 0x102, 0x39, 0x102, 0x30, 0x102,
+ 0x31, 0x102, 0x32, 0x102, 0x33, 0x102, 0x34, 0x102,
+ 0x35, 0x102, 0x36, 0x102, 0x37, 0x102, 0x38, 0x102,
+ 0x39, 0x109, 0x430, 0x109, 0x431, 0x109, 0x432, 0x109,
+ 0x433, 0x109, 0x434, 0x109, 0x435, 0x109, 0x436, 0x109,
+ 0x437, 0x109, 0x438, 0x109, 0x43a, 0x109, 0x43b, 0x109,
+ 0x43c, 0x109, 0x43e, 0x109, 0x43f, 0x109, 0x440, 0x109,
+ 0x441, 0x109, 0x442, 0x109, 0x443, 0x109, 0x444, 0x109,
+ 0x445, 0x109, 0x446, 0x109, 0x447, 0x109, 0x448, 0x109,
+ 0x44b, 0x109, 0x44d, 0x109, 0x44e, 0x109, 0xa689, 0x109,
+ 0x4d9, 0x109, 0x456, 0x109, 0x458, 0x109, 0x4e9, 0x109,
+ 0x4af, 0x109, 0x4cf, 0x10a, 0x430, 0x10a, 0x431, 0x10a,
+ 0x432, 0x10a, 0x433, 0x10a, 0x434, 0x10a, 0x435, 0x10a,
+ 0x436, 0x10a, 0x437, 0x10a, 0x438, 0x10a, 0x43a, 0x10a,
+ 0x43b, 0x10a, 0x43e, 0x10a, 0x43f, 0x10a, 0x441, 0x10a,
+ 0x443, 0x10a, 0x444, 0x10a, 0x445, 0x10a, 0x446, 0x10a,
+ 0x447, 0x10a, 0x448, 0x10a, 0x44a, 0x10a, 0x44b, 0x10a,
+ 0x491, 0x10a, 0x456, 0x10a, 0x455, 0x10a, 0x45f, 0x109,
+ 0x4ab, 0x109, 0xa651, 0x109, 0x4b1, 0x102, 0x627, 0x102,
0x628, 0x102, 0x62c, 0x102, 0x62f, 0x102, 0x648, 0x102,
0x632, 0x102, 0x62d, 0x102, 0x637, 0x102, 0x64a, 0x102,
0x643, 0x102, 0x644, 0x102, 0x645, 0x102, 0x646, 0x102,
@@ -13645,7 +14599,7 @@ static const unsigned short uc_decomposition_map[] = {
0xd869, 0xde00
};
-static const unsigned short uc_ligature_trie[] = {
+static constexpr unsigned short uc_ligature_trie[] = {
// 0 - 0x3100
631, 631, 631, 631, 631, 631, 631, 631,
@@ -14070,12 +15024,12 @@ static const unsigned short uc_ligature_trie[] = {
#define GET_LIGATURE_INDEX(ucs4) \
(ucs4 < 0x3100 \
- ? (uc_ligature_trie[uc_ligature_trie[ucs4>>5] + (ucs4 & 0x1f)]) \
- : (ucs4 < 0x12000 \
- ? uc_ligature_trie[uc_ligature_trie[((ucs4 - 0x3100)>>8) + 0x188] + (ucs4 & 0xff)] \
- : 0xffff))
+ ? (uc_ligature_trie[uc_ligature_trie[ucs4 >> 5] + (ucs4 & 0x1f)]) \
+ : ucs4 < 0x12000 \
+ ? uc_ligature_trie[uc_ligature_trie[((ucs4 - 0x3100) >> 8) + 0x188] + (ucs4 & 0xff)] \
+ : 0xffff)
-static const unsigned short uc_ligature_map[] = {
+static constexpr unsigned short uc_ligature_map[] = {
0x54, 0x41, 0xc0, 0x45, 0xc8, 0x49, 0xcc, 0x4e,
0x1f8, 0x4f, 0xd2, 0x55, 0xd9, 0x57, 0x1e80, 0x59,
0x1ef2, 0x61, 0xe0, 0x65, 0xe8, 0x69, 0xec, 0x6e,
@@ -14325,14 +15279,13 @@ static const unsigned short uc_ligature_map[] = {
0xdd35, 0xd806, 0xdd38
};
-
struct NormalizationCorrection {
uint ucs4;
uint old_mapping;
int version;
};
-static const NormalizationCorrection uc_normalization_corrections[] = {
+static constexpr NormalizationCorrection uc_normalization_corrections[] = {
{ 0xf951, 0x96fb, 6 },
{ 0x2f868, 0x2136a, 7 },
{ 0x2f874, 0x5f33, 7 },
@@ -14344,6 +15297,6023 @@ static const NormalizationCorrection uc_normalization_corrections[] = {
enum { NumNormalizationCorrections = 6 };
enum { NormalizationCorrectionsVersionMax = 7 };
+static constexpr char16_t idnaMappingData[] = {
+ 0x31, 0x31, 0x65e5, 0x31, 0x31, 0x6708, 0x31, 0x31, 0x70b9, 0x31, 0x32, 0x65e5,
+ 0x31, 0x32, 0x6708, 0x31, 0x32, 0x70b9, 0x31, 0x33, 0x65e5, 0x31, 0x33, 0x70b9,
+ 0x31, 0x34, 0x65e5, 0x31, 0x34, 0x70b9, 0x31, 0x35, 0x65e5, 0x31, 0x35, 0x70b9,
+ 0x31, 0x36, 0x65e5, 0x31, 0x36, 0x70b9, 0x31, 0x37, 0x65e5, 0x31, 0x37, 0x70b9,
+ 0x31, 0x38, 0x65e5, 0x31, 0x38, 0x70b9, 0x31, 0x39, 0x65e5, 0x31, 0x39, 0x70b9,
+ 0x31, 0x2044, 0x36, 0x31, 0x2044, 0x35, 0x31, 0x2044, 0x34, 0x31, 0x2044, 0x33,
+ 0x31, 0x2044, 0x32, 0x35, 0x65e5, 0x62, 0x61, 0x72, 0x61, 0x64, 0x2215, 0x73,
+ 0x32, 0x2044, 0x35, 0x65, 0x72, 0x67, 0x61, 0x6c, 0x6d, 0x68, 0x7a, 0x70,
+ 0x74, 0x65, 0x6c, 0x6f, 0x67, 0x68, 0x7a, 0x6d, 0x69, 0x6c, 0x74, 0x68,
+ 0x7a, 0x5e9, 0x5bc, 0x5c1, 0x628, 0x62d, 0x64a, 0x62a, 0x62c, 0x645, 0x62a, 0x62c,
+ 0x64a, 0x62a, 0x62d, 0x645, 0x62a, 0x62e, 0x649, 0x62a, 0x645, 0x62c, 0x62e, 0x646,
+ 0x62d, 0x649, 0x222e, 0x222e, 0x222e, 0x3014, 0x6253, 0x3015, 0x30a4, 0x30f3, 0x30c1, 0x30ac,
+ 0x30f3, 0x30de, 0x30f3, 0x30b7, 0x30e7, 0x30f3, 0x30ec, 0x30f3, 0x30c8, 0x30b2, 0x30f3, 0xd834,
+ 0xddba, 0xd834, 0xdd65, 0xd834, 0xdd6f, 0xd834, 0xddba, 0xd834, 0xdd65, 0xd834, 0xdd6e, 0xd834,
+ 0xddb9, 0xd834, 0xdd65, 0xd834, 0xdd6f, 0xd834, 0xddb9, 0xd834, 0xdd65, 0xd834, 0xdd6e, 0xd834,
+ 0xdd58, 0xd834, 0xdd65, 0xd834, 0xdd72, 0xd834, 0xdd58, 0xd834, 0xdd65, 0xd834, 0xdd71, 0xd834,
+ 0xdd58, 0xd834, 0xdd65, 0xd834, 0xdd70, 0xd834, 0xdd58, 0xd834, 0xdd65, 0xd834, 0xdd6f, 0xd834,
+ 0xdd58, 0xd834, 0xdd65, 0xd834, 0xdd6e, 0x30ad, 0x30ed, 0x30e1, 0x30fc, 0x30c8, 0x30eb, 0x30fc,
+ 0x30d6, 0x30eb, 0x30df, 0x30af, 0x30ed, 0x30f3, 0x30d0, 0x30fc, 0x30ec, 0x30eb, 0x30b5, 0x30a4,
+ 0x30af, 0x30eb, 0x30bc, 0x30a4, 0x30ed, 0x30ad, 0x30ed, 0x30b0, 0x30e9, 0x30e0, 0x30c8, 0x30f3,
+ 0x30d4, 0x30a2, 0x30b9, 0x30c8, 0x30eb, 0x30d1, 0x30fc, 0x30bb, 0x30f3, 0x30c8, 0x30b5, 0x30f3,
+ 0x30c1, 0x30fc, 0x30e0, 0x30ad, 0x30ed, 0x30ef, 0x30c3, 0x30c8, 0x30a8, 0x30b9, 0x30af, 0x30fc,
+ 0x30c9, 0xd834, 0xdd57, 0xd834, 0xdd65, 0x682a, 0x5f0f, 0x4f1a, 0x793e, 0x30e1, 0x30ac, 0x30c8,
+ 0x30f3, 0x30d5, 0x30a3, 0x30fc, 0x30c8, 0x30ae, 0x30eb, 0x30c0, 0x30fc, 0x30b9, 0x30d5, 0x30e9,
+ 0x30f3, 0x30da, 0x30fc, 0x30b8, 0x30de, 0x30a4, 0x30eb, 0x30e6, 0x30a2, 0x30f3, 0x30da, 0x30a2,
+ 0x30eb, 0x30d5, 0x30a1, 0x30e9, 0x30c3, 0x30c9, 0x30d6, 0x30c3, 0x30b7, 0x30a7, 0x30eb, 0x30d8,
+ 0x30af, 0x30bf, 0x30fc, 0x30eb, 0x30df, 0x30ea, 0x30d0, 0x30fc, 0x30eb, 0x30d4, 0x30fc, 0x627,
+ 0x643, 0x628, 0x631, 0x6cc, 0x627, 0x644, 0x644, 0x647, 0x645, 0x62c, 0x64a, 0x646,
+ 0x62d, 0x645, 0x64a, 0x633, 0x645, 0x645, 0x635, 0x62d, 0x64a, 0x636, 0x62e, 0x645,
+ 0x639, 0x645, 0x649, 0x640, 0x64f, 0x651, 0x642, 0x645, 0x645, 0x644, 0x62c, 0x645,
+ 0x62d, 0x633, 0x62d, 0x62c, 0x634, 0x62d, 0x64a, 0x635, 0x645, 0x645, 0x637, 0x645,
+ 0x64a, 0x63a, 0x645, 0x649, 0x641, 0x645, 0x64a, 0x643, 0x645, 0x64a, 0x644, 0x62d,
+ 0x649, 0x646, 0x62c, 0x62d, 0x64a, 0x633, 0x62c, 0x649, 0x634, 0x62d, 0x645, 0x635,
+ 0x644, 0x6d2, 0x637, 0x645, 0x645, 0x63a, 0x645, 0x645, 0x641, 0x62e, 0x645, 0x643,
+ 0x645, 0x645, 0x644, 0x62d, 0x645, 0x649, 0x633, 0x645, 0x62d, 0x635, 0x62d, 0x62d,
+ 0x636, 0x62d, 0x64a, 0x639, 0x645, 0x645, 0x640, 0x64e, 0x651, 0x642, 0x645, 0x62d,
+ 0x64a, 0x646, 0x62d, 0x64a, 0x3014, 0x73, 0x3015, 0x3014, 0x6557, 0x3015, 0x30a6, 0x30a9,
+ 0x30f3, 0x30ae, 0x30cb, 0x30fc, 0x30bb, 0x30f3, 0x30c1, 0x30d4, 0x30af, 0x30eb, 0x30da, 0x30f3,
+ 0x30b9, 0x30dd, 0x30f3, 0x30c9, 0x30e4, 0x30fc, 0x30eb, 0x6b, 0x63, 0x61, 0x6c, 0x74,
+ 0x64, 0x6d, 0x33, 0x2044, 0x34, 0x2044, 0x35, 0x2044, 0x38, 0x6b, 0x68, 0x7a,
+ 0x70, 0x70, 0x6d, 0x70, 0x61, 0x2215, 0x6d, 0x6f, 0x6c, 0x76, 0x2215, 0x6d,
+ 0x2215, 0x73, 0x32, 0x2044, 0x33, 0x30, 0x65e5, 0x66, 0x61, 0x78, 0x69, 0x69,
+ 0x5e9, 0x5bc, 0x5c2, 0x628, 0x62e, 0x64a, 0x62a, 0x62c, 0x649, 0x62a, 0x62d, 0x62c,
+ 0x62a, 0x62e, 0x645, 0x62a, 0x62e, 0x64a, 0x62a, 0x645, 0x62d, 0x62a, 0x645, 0x64a,
+ 0x62a, 0x645, 0x649, 0x62a, 0x645, 0x62e, 0x645, 0x62c, 0x62d, 0x649, 0x633, 0x62c,
+ 0x62d, 0x634, 0x62c, 0x64a, 0x635, 0x644, 0x649, 0x637, 0x645, 0x62d, 0x62c, 0x64a,
+ 0x633, 0x645, 0x62c, 0x645, 0x649, 0x633, 0x62e, 0x64a, 0x634, 0x645, 0x645, 0x636,
+ 0x62d, 0x649, 0x639, 0x62c, 0x645, 0x63a, 0x645, 0x64a, 0x642, 0x644, 0x6d2, 0x644,
+ 0x62c, 0x62c, 0x644, 0x62d, 0x64a, 0x646, 0x62c, 0x645, 0x64a, 0x633, 0x62e, 0x649,
+ 0x634, 0x645, 0x62e, 0x64a, 0x646, 0x645, 0x64a, 0x62c, 0x64a, 0x62d, 0x64a, 0x645,
+ 0x64a, 0x645, 0x645, 0x64a, 0xfb2, 0xf71, 0xf80, 0x3014, 0x4e8c, 0x3015, 0x3014, 0x70b9,
+ 0x3015, 0x30aa, 0x30fc, 0x30e0, 0x30b3, 0x30eb, 0x30ca, 0x30d1, 0x30fc, 0x30c4, 0x30da, 0x30cb,
+ 0x30d2, 0x30dc, 0x30eb, 0x30c8, 0x30e4, 0x30fc, 0x30c9, 0x63, 0x2215, 0x6b, 0x67, 0x70,
+ 0x61, 0x6d, 0x6d, 0x32, 0x39, 0x65e5, 0x64, 0x6d, 0x32, 0x37, 0x65e5, 0x63,
+ 0x6d, 0x32, 0x36, 0x65e5, 0x32, 0x34, 0x70b9, 0x32, 0x34, 0x65e5, 0x32, 0x33,
+ 0x70b9, 0x32, 0x33, 0x65e5, 0x32, 0x32, 0x70b9, 0x32, 0x32, 0x65e5, 0x32, 0x31,
+ 0x70b9, 0x32, 0x31, 0x65e5, 0x32, 0x30, 0x70b9, 0x32, 0x30, 0x65e5, 0x31, 0x2044,
+ 0x39, 0x31, 0x2044, 0x38, 0x31, 0x2044, 0x37, 0x2044, 0x38, 0x6b, 0x6d, 0x32,
+ 0x38, 0x65e5, 0x63, 0x6d, 0x33, 0x31, 0x65e5, 0x66, 0x66, 0x69, 0x6b, 0x6d,
+ 0x33, 0x2044, 0x35, 0x2044, 0x36, 0x68, 0x70, 0x61, 0x6d, 0x6d, 0x33, 0x2044,
+ 0x38, 0x66, 0x66, 0x6c, 0x6b, 0x70, 0x61, 0x70, 0x70, 0x76, 0x69, 0x69,
+ 0x69, 0x631, 0x633, 0x648, 0x644, 0x645, 0x62d, 0x645, 0x62f, 0x635, 0x644, 0x639,
+ 0x645, 0x64a, 0x640, 0x650, 0x651, 0x642, 0x645, 0x64a, 0x644, 0x62c, 0x64a, 0x644,
+ 0x62e, 0x645, 0x646, 0x62c, 0x64a, 0x2035, 0x2035, 0x2035, 0x3014, 0x5b89, 0x3015, 0x30a2,
+ 0x30fc, 0x30eb, 0x30ac, 0x30ed, 0x30f3, 0x30b3, 0x30fc, 0x30dd, 0x30a4, 0x30f3, 0x30c8, 0x30b7,
+ 0x30ea, 0x30f3, 0x30b0, 0x30ad, 0x30e5, 0x30ea, 0x30fc, 0x30ab, 0x30e9, 0x30c3, 0x30c8, 0x30a4,
+ 0x30cb, 0x30f3, 0x30b0, 0x222b, 0x222b, 0x222b, 0x222b, 0x648, 0x633, 0x644, 0x645, 0x64a,
+ 0x646, 0x62c, 0x649, 0xfb3, 0xf71, 0xf80, 0x3014, 0x52dd, 0x3015, 0x3014, 0x76d7, 0x3015,
+ 0x30ab, 0x30a4, 0x30ea, 0x30c3, 0x30c8, 0x30eb, 0x30de, 0x30a4, 0x30af, 0x30ed, 0x30fc, 0x30cd,
+ 0x30ab, 0x30ed, 0x30ea, 0x30fc, 0x30a8, 0x30fc, 0x30ab, 0x30fc, 0x30a2, 0x30d1, 0x30fc, 0x30c8,
+ 0x2032, 0x2032, 0x2032, 0x2032, 0x639, 0x644, 0x64a, 0x647, 0x645, 0x645, 0x62e, 0x62c,
+ 0x646, 0x645, 0x649, 0x3014, 0x4e09, 0x3015, 0x3014, 0x672c, 0x3015, 0x30aa, 0x30f3, 0x30b9,
+ 0x30b1, 0x30fc, 0x30b9, 0x30ce, 0x30c3, 0x30c8, 0x30d8, 0x30eb, 0x30c4, 0x30db, 0x30fc, 0x30eb,
+ 0x30de, 0x30c3, 0x30cf, 0x30a4, 0x30c4, 0x30d9, 0x30fc, 0x30bf, 0x30db, 0x30fc, 0x30f3, 0x30de,
+ 0x30eb, 0x30af, 0x31, 0x2044, 0x31, 0x30, 0x70b9, 0x31, 0x30, 0x6708, 0x31, 0x30,
+ 0x65e5, 0x30, 0x2044, 0x33,
+};
+
+struct IdnaMapEntry {
+ // 21 bits suffice for any valid code-point (LastValidCodePoint = 0x10ffff)
+ unsigned codePoint : 24;
+ unsigned size : 8;
+ char16_t ucs[2]; // ucs[0] is offset if size > 2
+};
+static_assert(sizeof(IdnaMapEntry) == 8);
+
+static constexpr IdnaMapEntry idnaMap[] = {
+ { 0xaa, 1, { 0x61, 0 } },
+ { 0xb2, 1, { 0x32, 0 } },
+ { 0xb3, 1, { 0x33, 0 } },
+ { 0xb5, 1, { 0x3bc, 0 } },
+ { 0xb9, 1, { 0x31, 0 } },
+ { 0xba, 1, { 0x6f, 0 } },
+ { 0xbc, 3, { 66, 0 } },
+ { 0xbd, 3, { 72, 0 } },
+ { 0xbe, 3, { 470, 0 } },
+ { 0xc0, 1, { 0xe0, 0 } },
+ { 0xc1, 1, { 0xe1, 0 } },
+ { 0xc2, 1, { 0xe2, 0 } },
+ { 0xc3, 1, { 0xe3, 0 } },
+ { 0xc4, 1, { 0xe4, 0 } },
+ { 0xc5, 1, { 0xe5, 0 } },
+ { 0xc6, 1, { 0xe6, 0 } },
+ { 0xc7, 1, { 0xe7, 0 } },
+ { 0xc8, 1, { 0xe8, 0 } },
+ { 0xc9, 1, { 0xe9, 0 } },
+ { 0xca, 1, { 0xea, 0 } },
+ { 0xcb, 1, { 0xeb, 0 } },
+ { 0xcc, 1, { 0xec, 0 } },
+ { 0xcd, 1, { 0xed, 0 } },
+ { 0xce, 1, { 0xee, 0 } },
+ { 0xcf, 1, { 0xef, 0 } },
+ { 0xd0, 1, { 0xf0, 0 } },
+ { 0xd1, 1, { 0xf1, 0 } },
+ { 0xd2, 1, { 0xf2, 0 } },
+ { 0xd3, 1, { 0xf3, 0 } },
+ { 0xd4, 1, { 0xf4, 0 } },
+ { 0xd5, 1, { 0xf5, 0 } },
+ { 0xd6, 1, { 0xf6, 0 } },
+ { 0xd8, 1, { 0xf8, 0 } },
+ { 0xd9, 1, { 0xf9, 0 } },
+ { 0xda, 1, { 0xfa, 0 } },
+ { 0xdb, 1, { 0xfb, 0 } },
+ { 0xdc, 1, { 0xfc, 0 } },
+ { 0xdd, 1, { 0xfd, 0 } },
+ { 0xde, 1, { 0xfe, 0 } },
+ { 0xdf, 2, { 0x73, 0x73 } },
+ { 0x100, 1, { 0x101, 0 } },
+ { 0x102, 1, { 0x103, 0 } },
+ { 0x104, 1, { 0x105, 0 } },
+ { 0x106, 1, { 0x107, 0 } },
+ { 0x108, 1, { 0x109, 0 } },
+ { 0x10a, 1, { 0x10b, 0 } },
+ { 0x10c, 1, { 0x10d, 0 } },
+ { 0x10e, 1, { 0x10f, 0 } },
+ { 0x110, 1, { 0x111, 0 } },
+ { 0x112, 1, { 0x113, 0 } },
+ { 0x114, 1, { 0x115, 0 } },
+ { 0x116, 1, { 0x117, 0 } },
+ { 0x118, 1, { 0x119, 0 } },
+ { 0x11a, 1, { 0x11b, 0 } },
+ { 0x11c, 1, { 0x11d, 0 } },
+ { 0x11e, 1, { 0x11f, 0 } },
+ { 0x120, 1, { 0x121, 0 } },
+ { 0x122, 1, { 0x123, 0 } },
+ { 0x124, 1, { 0x125, 0 } },
+ { 0x126, 1, { 0x127, 0 } },
+ { 0x128, 1, { 0x129, 0 } },
+ { 0x12a, 1, { 0x12b, 0 } },
+ { 0x12c, 1, { 0x12d, 0 } },
+ { 0x12e, 1, { 0x12f, 0 } },
+ { 0x130, 2, { 0x69, 0x307 } },
+ { 0x132, 2, { 0x69, 0x6a } },
+ { 0x133, 2, { 0x69, 0x6a } },
+ { 0x134, 1, { 0x135, 0 } },
+ { 0x136, 1, { 0x137, 0 } },
+ { 0x139, 1, { 0x13a, 0 } },
+ { 0x13b, 1, { 0x13c, 0 } },
+ { 0x13d, 1, { 0x13e, 0 } },
+ { 0x13f, 2, { 0x6c, 0xb7 } },
+ { 0x140, 2, { 0x6c, 0xb7 } },
+ { 0x141, 1, { 0x142, 0 } },
+ { 0x143, 1, { 0x144, 0 } },
+ { 0x145, 1, { 0x146, 0 } },
+ { 0x147, 1, { 0x148, 0 } },
+ { 0x149, 2, { 0x2bc, 0x6e } },
+ { 0x14a, 1, { 0x14b, 0 } },
+ { 0x14c, 1, { 0x14d, 0 } },
+ { 0x14e, 1, { 0x14f, 0 } },
+ { 0x150, 1, { 0x151, 0 } },
+ { 0x152, 1, { 0x153, 0 } },
+ { 0x154, 1, { 0x155, 0 } },
+ { 0x156, 1, { 0x157, 0 } },
+ { 0x158, 1, { 0x159, 0 } },
+ { 0x15a, 1, { 0x15b, 0 } },
+ { 0x15c, 1, { 0x15d, 0 } },
+ { 0x15e, 1, { 0x15f, 0 } },
+ { 0x160, 1, { 0x161, 0 } },
+ { 0x162, 1, { 0x163, 0 } },
+ { 0x164, 1, { 0x165, 0 } },
+ { 0x166, 1, { 0x167, 0 } },
+ { 0x168, 1, { 0x169, 0 } },
+ { 0x16a, 1, { 0x16b, 0 } },
+ { 0x16c, 1, { 0x16d, 0 } },
+ { 0x16e, 1, { 0x16f, 0 } },
+ { 0x170, 1, { 0x171, 0 } },
+ { 0x172, 1, { 0x173, 0 } },
+ { 0x174, 1, { 0x175, 0 } },
+ { 0x176, 1, { 0x177, 0 } },
+ { 0x178, 1, { 0xff, 0 } },
+ { 0x179, 1, { 0x17a, 0 } },
+ { 0x17b, 1, { 0x17c, 0 } },
+ { 0x17d, 1, { 0x17e, 0 } },
+ { 0x17f, 1, { 0x73, 0 } },
+ { 0x181, 1, { 0x253, 0 } },
+ { 0x182, 1, { 0x183, 0 } },
+ { 0x184, 1, { 0x185, 0 } },
+ { 0x186, 1, { 0x254, 0 } },
+ { 0x187, 1, { 0x188, 0 } },
+ { 0x189, 1, { 0x256, 0 } },
+ { 0x18a, 1, { 0x257, 0 } },
+ { 0x18b, 1, { 0x18c, 0 } },
+ { 0x18e, 1, { 0x1dd, 0 } },
+ { 0x18f, 1, { 0x259, 0 } },
+ { 0x190, 1, { 0x25b, 0 } },
+ { 0x191, 1, { 0x192, 0 } },
+ { 0x193, 1, { 0x260, 0 } },
+ { 0x194, 1, { 0x263, 0 } },
+ { 0x196, 1, { 0x269, 0 } },
+ { 0x197, 1, { 0x268, 0 } },
+ { 0x198, 1, { 0x199, 0 } },
+ { 0x19c, 1, { 0x26f, 0 } },
+ { 0x19d, 1, { 0x272, 0 } },
+ { 0x19f, 1, { 0x275, 0 } },
+ { 0x1a0, 1, { 0x1a1, 0 } },
+ { 0x1a2, 1, { 0x1a3, 0 } },
+ { 0x1a4, 1, { 0x1a5, 0 } },
+ { 0x1a6, 1, { 0x280, 0 } },
+ { 0x1a7, 1, { 0x1a8, 0 } },
+ { 0x1a9, 1, { 0x283, 0 } },
+ { 0x1ac, 1, { 0x1ad, 0 } },
+ { 0x1ae, 1, { 0x288, 0 } },
+ { 0x1af, 1, { 0x1b0, 0 } },
+ { 0x1b1, 1, { 0x28a, 0 } },
+ { 0x1b2, 1, { 0x28b, 0 } },
+ { 0x1b3, 1, { 0x1b4, 0 } },
+ { 0x1b5, 1, { 0x1b6, 0 } },
+ { 0x1b7, 1, { 0x292, 0 } },
+ { 0x1b8, 1, { 0x1b9, 0 } },
+ { 0x1bc, 1, { 0x1bd, 0 } },
+ { 0x1c4, 2, { 0x64, 0x17e } },
+ { 0x1c5, 2, { 0x64, 0x17e } },
+ { 0x1c6, 2, { 0x64, 0x17e } },
+ { 0x1c7, 2, { 0x6c, 0x6a } },
+ { 0x1c8, 2, { 0x6c, 0x6a } },
+ { 0x1c9, 2, { 0x6c, 0x6a } },
+ { 0x1ca, 2, { 0x6e, 0x6a } },
+ { 0x1cb, 2, { 0x6e, 0x6a } },
+ { 0x1cc, 2, { 0x6e, 0x6a } },
+ { 0x1cd, 1, { 0x1ce, 0 } },
+ { 0x1cf, 1, { 0x1d0, 0 } },
+ { 0x1d1, 1, { 0x1d2, 0 } },
+ { 0x1d3, 1, { 0x1d4, 0 } },
+ { 0x1d5, 1, { 0x1d6, 0 } },
+ { 0x1d7, 1, { 0x1d8, 0 } },
+ { 0x1d9, 1, { 0x1da, 0 } },
+ { 0x1db, 1, { 0x1dc, 0 } },
+ { 0x1de, 1, { 0x1df, 0 } },
+ { 0x1e0, 1, { 0x1e1, 0 } },
+ { 0x1e2, 1, { 0x1e3, 0 } },
+ { 0x1e4, 1, { 0x1e5, 0 } },
+ { 0x1e6, 1, { 0x1e7, 0 } },
+ { 0x1e8, 1, { 0x1e9, 0 } },
+ { 0x1ea, 1, { 0x1eb, 0 } },
+ { 0x1ec, 1, { 0x1ed, 0 } },
+ { 0x1ee, 1, { 0x1ef, 0 } },
+ { 0x1f1, 2, { 0x64, 0x7a } },
+ { 0x1f2, 2, { 0x64, 0x7a } },
+ { 0x1f3, 2, { 0x64, 0x7a } },
+ { 0x1f4, 1, { 0x1f5, 0 } },
+ { 0x1f6, 1, { 0x195, 0 } },
+ { 0x1f7, 1, { 0x1bf, 0 } },
+ { 0x1f8, 1, { 0x1f9, 0 } },
+ { 0x1fa, 1, { 0x1fb, 0 } },
+ { 0x1fc, 1, { 0x1fd, 0 } },
+ { 0x1fe, 1, { 0x1ff, 0 } },
+ { 0x200, 1, { 0x201, 0 } },
+ { 0x202, 1, { 0x203, 0 } },
+ { 0x204, 1, { 0x205, 0 } },
+ { 0x206, 1, { 0x207, 0 } },
+ { 0x208, 1, { 0x209, 0 } },
+ { 0x20a, 1, { 0x20b, 0 } },
+ { 0x20c, 1, { 0x20d, 0 } },
+ { 0x20e, 1, { 0x20f, 0 } },
+ { 0x210, 1, { 0x211, 0 } },
+ { 0x212, 1, { 0x213, 0 } },
+ { 0x214, 1, { 0x215, 0 } },
+ { 0x216, 1, { 0x217, 0 } },
+ { 0x218, 1, { 0x219, 0 } },
+ { 0x21a, 1, { 0x21b, 0 } },
+ { 0x21c, 1, { 0x21d, 0 } },
+ { 0x21e, 1, { 0x21f, 0 } },
+ { 0x220, 1, { 0x19e, 0 } },
+ { 0x222, 1, { 0x223, 0 } },
+ { 0x224, 1, { 0x225, 0 } },
+ { 0x226, 1, { 0x227, 0 } },
+ { 0x228, 1, { 0x229, 0 } },
+ { 0x22a, 1, { 0x22b, 0 } },
+ { 0x22c, 1, { 0x22d, 0 } },
+ { 0x22e, 1, { 0x22f, 0 } },
+ { 0x230, 1, { 0x231, 0 } },
+ { 0x232, 1, { 0x233, 0 } },
+ { 0x23a, 1, { 0x2c65, 0 } },
+ { 0x23b, 1, { 0x23c, 0 } },
+ { 0x23d, 1, { 0x19a, 0 } },
+ { 0x23e, 1, { 0x2c66, 0 } },
+ { 0x241, 1, { 0x242, 0 } },
+ { 0x243, 1, { 0x180, 0 } },
+ { 0x244, 1, { 0x289, 0 } },
+ { 0x245, 1, { 0x28c, 0 } },
+ { 0x246, 1, { 0x247, 0 } },
+ { 0x248, 1, { 0x249, 0 } },
+ { 0x24a, 1, { 0x24b, 0 } },
+ { 0x24c, 1, { 0x24d, 0 } },
+ { 0x24e, 1, { 0x24f, 0 } },
+ { 0x2b0, 1, { 0x68, 0 } },
+ { 0x2b1, 1, { 0x266, 0 } },
+ { 0x2b2, 1, { 0x6a, 0 } },
+ { 0x2b3, 1, { 0x72, 0 } },
+ { 0x2b4, 1, { 0x279, 0 } },
+ { 0x2b5, 1, { 0x27b, 0 } },
+ { 0x2b6, 1, { 0x281, 0 } },
+ { 0x2b7, 1, { 0x77, 0 } },
+ { 0x2b8, 1, { 0x79, 0 } },
+ { 0x2e0, 1, { 0x263, 0 } },
+ { 0x2e1, 1, { 0x6c, 0 } },
+ { 0x2e2, 1, { 0x73, 0 } },
+ { 0x2e3, 1, { 0x78, 0 } },
+ { 0x2e4, 1, { 0x295, 0 } },
+ { 0x340, 1, { 0x300, 0 } },
+ { 0x341, 1, { 0x301, 0 } },
+ { 0x343, 1, { 0x313, 0 } },
+ { 0x344, 2, { 0x308, 0x301 } },
+ { 0x345, 1, { 0x3b9, 0 } },
+ { 0x370, 1, { 0x371, 0 } },
+ { 0x372, 1, { 0x373, 0 } },
+ { 0x374, 1, { 0x2b9, 0 } },
+ { 0x376, 1, { 0x377, 0 } },
+ { 0x37f, 1, { 0x3f3, 0 } },
+ { 0x386, 1, { 0x3ac, 0 } },
+ { 0x387, 1, { 0xb7, 0 } },
+ { 0x388, 1, { 0x3ad, 0 } },
+ { 0x389, 1, { 0x3ae, 0 } },
+ { 0x38a, 1, { 0x3af, 0 } },
+ { 0x38c, 1, { 0x3cc, 0 } },
+ { 0x38e, 1, { 0x3cd, 0 } },
+ { 0x38f, 1, { 0x3ce, 0 } },
+ { 0x391, 1, { 0x3b1, 0 } },
+ { 0x392, 1, { 0x3b2, 0 } },
+ { 0x393, 1, { 0x3b3, 0 } },
+ { 0x394, 1, { 0x3b4, 0 } },
+ { 0x395, 1, { 0x3b5, 0 } },
+ { 0x396, 1, { 0x3b6, 0 } },
+ { 0x397, 1, { 0x3b7, 0 } },
+ { 0x398, 1, { 0x3b8, 0 } },
+ { 0x399, 1, { 0x3b9, 0 } },
+ { 0x39a, 1, { 0x3ba, 0 } },
+ { 0x39b, 1, { 0x3bb, 0 } },
+ { 0x39c, 1, { 0x3bc, 0 } },
+ { 0x39d, 1, { 0x3bd, 0 } },
+ { 0x39e, 1, { 0x3be, 0 } },
+ { 0x39f, 1, { 0x3bf, 0 } },
+ { 0x3a0, 1, { 0x3c0, 0 } },
+ { 0x3a1, 1, { 0x3c1, 0 } },
+ { 0x3a3, 1, { 0x3c3, 0 } },
+ { 0x3a4, 1, { 0x3c4, 0 } },
+ { 0x3a5, 1, { 0x3c5, 0 } },
+ { 0x3a6, 1, { 0x3c6, 0 } },
+ { 0x3a7, 1, { 0x3c7, 0 } },
+ { 0x3a8, 1, { 0x3c8, 0 } },
+ { 0x3a9, 1, { 0x3c9, 0 } },
+ { 0x3aa, 1, { 0x3ca, 0 } },
+ { 0x3ab, 1, { 0x3cb, 0 } },
+ { 0x3c2, 1, { 0x3c3, 0 } },
+ { 0x3cf, 1, { 0x3d7, 0 } },
+ { 0x3d0, 1, { 0x3b2, 0 } },
+ { 0x3d1, 1, { 0x3b8, 0 } },
+ { 0x3d2, 1, { 0x3c5, 0 } },
+ { 0x3d3, 1, { 0x3cd, 0 } },
+ { 0x3d4, 1, { 0x3cb, 0 } },
+ { 0x3d5, 1, { 0x3c6, 0 } },
+ { 0x3d6, 1, { 0x3c0, 0 } },
+ { 0x3d8, 1, { 0x3d9, 0 } },
+ { 0x3da, 1, { 0x3db, 0 } },
+ { 0x3dc, 1, { 0x3dd, 0 } },
+ { 0x3de, 1, { 0x3df, 0 } },
+ { 0x3e0, 1, { 0x3e1, 0 } },
+ { 0x3e2, 1, { 0x3e3, 0 } },
+ { 0x3e4, 1, { 0x3e5, 0 } },
+ { 0x3e6, 1, { 0x3e7, 0 } },
+ { 0x3e8, 1, { 0x3e9, 0 } },
+ { 0x3ea, 1, { 0x3eb, 0 } },
+ { 0x3ec, 1, { 0x3ed, 0 } },
+ { 0x3ee, 1, { 0x3ef, 0 } },
+ { 0x3f0, 1, { 0x3ba, 0 } },
+ { 0x3f1, 1, { 0x3c1, 0 } },
+ { 0x3f2, 1, { 0x3c3, 0 } },
+ { 0x3f4, 1, { 0x3b8, 0 } },
+ { 0x3f5, 1, { 0x3b5, 0 } },
+ { 0x3f7, 1, { 0x3f8, 0 } },
+ { 0x3f9, 1, { 0x3c3, 0 } },
+ { 0x3fa, 1, { 0x3fb, 0 } },
+ { 0x3fd, 1, { 0x37b, 0 } },
+ { 0x3fe, 1, { 0x37c, 0 } },
+ { 0x3ff, 1, { 0x37d, 0 } },
+ { 0x400, 1, { 0x450, 0 } },
+ { 0x401, 1, { 0x451, 0 } },
+ { 0x402, 1, { 0x452, 0 } },
+ { 0x403, 1, { 0x453, 0 } },
+ { 0x404, 1, { 0x454, 0 } },
+ { 0x405, 1, { 0x455, 0 } },
+ { 0x406, 1, { 0x456, 0 } },
+ { 0x407, 1, { 0x457, 0 } },
+ { 0x408, 1, { 0x458, 0 } },
+ { 0x409, 1, { 0x459, 0 } },
+ { 0x40a, 1, { 0x45a, 0 } },
+ { 0x40b, 1, { 0x45b, 0 } },
+ { 0x40c, 1, { 0x45c, 0 } },
+ { 0x40d, 1, { 0x45d, 0 } },
+ { 0x40e, 1, { 0x45e, 0 } },
+ { 0x40f, 1, { 0x45f, 0 } },
+ { 0x410, 1, { 0x430, 0 } },
+ { 0x411, 1, { 0x431, 0 } },
+ { 0x412, 1, { 0x432, 0 } },
+ { 0x413, 1, { 0x433, 0 } },
+ { 0x414, 1, { 0x434, 0 } },
+ { 0x415, 1, { 0x435, 0 } },
+ { 0x416, 1, { 0x436, 0 } },
+ { 0x417, 1, { 0x437, 0 } },
+ { 0x418, 1, { 0x438, 0 } },
+ { 0x419, 1, { 0x439, 0 } },
+ { 0x41a, 1, { 0x43a, 0 } },
+ { 0x41b, 1, { 0x43b, 0 } },
+ { 0x41c, 1, { 0x43c, 0 } },
+ { 0x41d, 1, { 0x43d, 0 } },
+ { 0x41e, 1, { 0x43e, 0 } },
+ { 0x41f, 1, { 0x43f, 0 } },
+ { 0x420, 1, { 0x440, 0 } },
+ { 0x421, 1, { 0x441, 0 } },
+ { 0x422, 1, { 0x442, 0 } },
+ { 0x423, 1, { 0x443, 0 } },
+ { 0x424, 1, { 0x444, 0 } },
+ { 0x425, 1, { 0x445, 0 } },
+ { 0x426, 1, { 0x446, 0 } },
+ { 0x427, 1, { 0x447, 0 } },
+ { 0x428, 1, { 0x448, 0 } },
+ { 0x429, 1, { 0x449, 0 } },
+ { 0x42a, 1, { 0x44a, 0 } },
+ { 0x42b, 1, { 0x44b, 0 } },
+ { 0x42c, 1, { 0x44c, 0 } },
+ { 0x42d, 1, { 0x44d, 0 } },
+ { 0x42e, 1, { 0x44e, 0 } },
+ { 0x42f, 1, { 0x44f, 0 } },
+ { 0x460, 1, { 0x461, 0 } },
+ { 0x462, 1, { 0x463, 0 } },
+ { 0x464, 1, { 0x465, 0 } },
+ { 0x466, 1, { 0x467, 0 } },
+ { 0x468, 1, { 0x469, 0 } },
+ { 0x46a, 1, { 0x46b, 0 } },
+ { 0x46c, 1, { 0x46d, 0 } },
+ { 0x46e, 1, { 0x46f, 0 } },
+ { 0x470, 1, { 0x471, 0 } },
+ { 0x472, 1, { 0x473, 0 } },
+ { 0x474, 1, { 0x475, 0 } },
+ { 0x476, 1, { 0x477, 0 } },
+ { 0x478, 1, { 0x479, 0 } },
+ { 0x47a, 1, { 0x47b, 0 } },
+ { 0x47c, 1, { 0x47d, 0 } },
+ { 0x47e, 1, { 0x47f, 0 } },
+ { 0x480, 1, { 0x481, 0 } },
+ { 0x48a, 1, { 0x48b, 0 } },
+ { 0x48c, 1, { 0x48d, 0 } },
+ { 0x48e, 1, { 0x48f, 0 } },
+ { 0x490, 1, { 0x491, 0 } },
+ { 0x492, 1, { 0x493, 0 } },
+ { 0x494, 1, { 0x495, 0 } },
+ { 0x496, 1, { 0x497, 0 } },
+ { 0x498, 1, { 0x499, 0 } },
+ { 0x49a, 1, { 0x49b, 0 } },
+ { 0x49c, 1, { 0x49d, 0 } },
+ { 0x49e, 1, { 0x49f, 0 } },
+ { 0x4a0, 1, { 0x4a1, 0 } },
+ { 0x4a2, 1, { 0x4a3, 0 } },
+ { 0x4a4, 1, { 0x4a5, 0 } },
+ { 0x4a6, 1, { 0x4a7, 0 } },
+ { 0x4a8, 1, { 0x4a9, 0 } },
+ { 0x4aa, 1, { 0x4ab, 0 } },
+ { 0x4ac, 1, { 0x4ad, 0 } },
+ { 0x4ae, 1, { 0x4af, 0 } },
+ { 0x4b0, 1, { 0x4b1, 0 } },
+ { 0x4b2, 1, { 0x4b3, 0 } },
+ { 0x4b4, 1, { 0x4b5, 0 } },
+ { 0x4b6, 1, { 0x4b7, 0 } },
+ { 0x4b8, 1, { 0x4b9, 0 } },
+ { 0x4ba, 1, { 0x4bb, 0 } },
+ { 0x4bc, 1, { 0x4bd, 0 } },
+ { 0x4be, 1, { 0x4bf, 0 } },
+ { 0x4c1, 1, { 0x4c2, 0 } },
+ { 0x4c3, 1, { 0x4c4, 0 } },
+ { 0x4c5, 1, { 0x4c6, 0 } },
+ { 0x4c7, 1, { 0x4c8, 0 } },
+ { 0x4c9, 1, { 0x4ca, 0 } },
+ { 0x4cb, 1, { 0x4cc, 0 } },
+ { 0x4cd, 1, { 0x4ce, 0 } },
+ { 0x4d0, 1, { 0x4d1, 0 } },
+ { 0x4d2, 1, { 0x4d3, 0 } },
+ { 0x4d4, 1, { 0x4d5, 0 } },
+ { 0x4d6, 1, { 0x4d7, 0 } },
+ { 0x4d8, 1, { 0x4d9, 0 } },
+ { 0x4da, 1, { 0x4db, 0 } },
+ { 0x4dc, 1, { 0x4dd, 0 } },
+ { 0x4de, 1, { 0x4df, 0 } },
+ { 0x4e0, 1, { 0x4e1, 0 } },
+ { 0x4e2, 1, { 0x4e3, 0 } },
+ { 0x4e4, 1, { 0x4e5, 0 } },
+ { 0x4e6, 1, { 0x4e7, 0 } },
+ { 0x4e8, 1, { 0x4e9, 0 } },
+ { 0x4ea, 1, { 0x4eb, 0 } },
+ { 0x4ec, 1, { 0x4ed, 0 } },
+ { 0x4ee, 1, { 0x4ef, 0 } },
+ { 0x4f0, 1, { 0x4f1, 0 } },
+ { 0x4f2, 1, { 0x4f3, 0 } },
+ { 0x4f4, 1, { 0x4f5, 0 } },
+ { 0x4f6, 1, { 0x4f7, 0 } },
+ { 0x4f8, 1, { 0x4f9, 0 } },
+ { 0x4fa, 1, { 0x4fb, 0 } },
+ { 0x4fc, 1, { 0x4fd, 0 } },
+ { 0x4fe, 1, { 0x4ff, 0 } },
+ { 0x500, 1, { 0x501, 0 } },
+ { 0x502, 1, { 0x503, 0 } },
+ { 0x504, 1, { 0x505, 0 } },
+ { 0x506, 1, { 0x507, 0 } },
+ { 0x508, 1, { 0x509, 0 } },
+ { 0x50a, 1, { 0x50b, 0 } },
+ { 0x50c, 1, { 0x50d, 0 } },
+ { 0x50e, 1, { 0x50f, 0 } },
+ { 0x510, 1, { 0x511, 0 } },
+ { 0x512, 1, { 0x513, 0 } },
+ { 0x514, 1, { 0x515, 0 } },
+ { 0x516, 1, { 0x517, 0 } },
+ { 0x518, 1, { 0x519, 0 } },
+ { 0x51a, 1, { 0x51b, 0 } },
+ { 0x51c, 1, { 0x51d, 0 } },
+ { 0x51e, 1, { 0x51f, 0 } },
+ { 0x520, 1, { 0x521, 0 } },
+ { 0x522, 1, { 0x523, 0 } },
+ { 0x524, 1, { 0x525, 0 } },
+ { 0x526, 1, { 0x527, 0 } },
+ { 0x528, 1, { 0x529, 0 } },
+ { 0x52a, 1, { 0x52b, 0 } },
+ { 0x52c, 1, { 0x52d, 0 } },
+ { 0x52e, 1, { 0x52f, 0 } },
+ { 0x531, 1, { 0x561, 0 } },
+ { 0x532, 1, { 0x562, 0 } },
+ { 0x533, 1, { 0x563, 0 } },
+ { 0x534, 1, { 0x564, 0 } },
+ { 0x535, 1, { 0x565, 0 } },
+ { 0x536, 1, { 0x566, 0 } },
+ { 0x537, 1, { 0x567, 0 } },
+ { 0x538, 1, { 0x568, 0 } },
+ { 0x539, 1, { 0x569, 0 } },
+ { 0x53a, 1, { 0x56a, 0 } },
+ { 0x53b, 1, { 0x56b, 0 } },
+ { 0x53c, 1, { 0x56c, 0 } },
+ { 0x53d, 1, { 0x56d, 0 } },
+ { 0x53e, 1, { 0x56e, 0 } },
+ { 0x53f, 1, { 0x56f, 0 } },
+ { 0x540, 1, { 0x570, 0 } },
+ { 0x541, 1, { 0x571, 0 } },
+ { 0x542, 1, { 0x572, 0 } },
+ { 0x543, 1, { 0x573, 0 } },
+ { 0x544, 1, { 0x574, 0 } },
+ { 0x545, 1, { 0x575, 0 } },
+ { 0x546, 1, { 0x576, 0 } },
+ { 0x547, 1, { 0x577, 0 } },
+ { 0x548, 1, { 0x578, 0 } },
+ { 0x549, 1, { 0x579, 0 } },
+ { 0x54a, 1, { 0x57a, 0 } },
+ { 0x54b, 1, { 0x57b, 0 } },
+ { 0x54c, 1, { 0x57c, 0 } },
+ { 0x54d, 1, { 0x57d, 0 } },
+ { 0x54e, 1, { 0x57e, 0 } },
+ { 0x54f, 1, { 0x57f, 0 } },
+ { 0x550, 1, { 0x580, 0 } },
+ { 0x551, 1, { 0x581, 0 } },
+ { 0x552, 1, { 0x582, 0 } },
+ { 0x553, 1, { 0x583, 0 } },
+ { 0x554, 1, { 0x584, 0 } },
+ { 0x555, 1, { 0x585, 0 } },
+ { 0x556, 1, { 0x586, 0 } },
+ { 0x587, 2, { 0x565, 0x582 } },
+ { 0x675, 2, { 0x627, 0x674 } },
+ { 0x676, 2, { 0x648, 0x674 } },
+ { 0x677, 2, { 0x6c7, 0x674 } },
+ { 0x678, 2, { 0x64a, 0x674 } },
+ { 0x958, 2, { 0x915, 0x93c } },
+ { 0x959, 2, { 0x916, 0x93c } },
+ { 0x95a, 2, { 0x917, 0x93c } },
+ { 0x95b, 2, { 0x91c, 0x93c } },
+ { 0x95c, 2, { 0x921, 0x93c } },
+ { 0x95d, 2, { 0x922, 0x93c } },
+ { 0x95e, 2, { 0x92b, 0x93c } },
+ { 0x95f, 2, { 0x92f, 0x93c } },
+ { 0x9dc, 2, { 0x9a1, 0x9bc } },
+ { 0x9dd, 2, { 0x9a2, 0x9bc } },
+ { 0x9df, 2, { 0x9af, 0x9bc } },
+ { 0xa33, 2, { 0xa32, 0xa3c } },
+ { 0xa36, 2, { 0xa38, 0xa3c } },
+ { 0xa59, 2, { 0xa16, 0xa3c } },
+ { 0xa5a, 2, { 0xa17, 0xa3c } },
+ { 0xa5b, 2, { 0xa1c, 0xa3c } },
+ { 0xa5e, 2, { 0xa2b, 0xa3c } },
+ { 0xb5c, 2, { 0xb21, 0xb3c } },
+ { 0xb5d, 2, { 0xb22, 0xb3c } },
+ { 0xe33, 2, { 0xe4d, 0xe32 } },
+ { 0xeb3, 2, { 0xecd, 0xeb2 } },
+ { 0xedc, 2, { 0xeab, 0xe99 } },
+ { 0xedd, 2, { 0xeab, 0xea1 } },
+ { 0xf0c, 1, { 0xf0b, 0 } },
+ { 0xf43, 2, { 0xf42, 0xfb7 } },
+ { 0xf4d, 2, { 0xf4c, 0xfb7 } },
+ { 0xf52, 2, { 0xf51, 0xfb7 } },
+ { 0xf57, 2, { 0xf56, 0xfb7 } },
+ { 0xf5c, 2, { 0xf5b, 0xfb7 } },
+ { 0xf69, 2, { 0xf40, 0xfb5 } },
+ { 0xf73, 2, { 0xf71, 0xf72 } },
+ { 0xf75, 2, { 0xf71, 0xf74 } },
+ { 0xf76, 2, { 0xfb2, 0xf80 } },
+ { 0xf77, 3, { 604, 0 } },
+ { 0xf78, 2, { 0xfb3, 0xf80 } },
+ { 0xf79, 3, { 807, 0 } },
+ { 0xf81, 2, { 0xf71, 0xf80 } },
+ { 0xf93, 2, { 0xf92, 0xfb7 } },
+ { 0xf9d, 2, { 0xf9c, 0xfb7 } },
+ { 0xfa2, 2, { 0xfa1, 0xfb7 } },
+ { 0xfa7, 2, { 0xfa6, 0xfb7 } },
+ { 0xfac, 2, { 0xfab, 0xfb7 } },
+ { 0xfb9, 2, { 0xf90, 0xfb5 } },
+ { 0x10c7, 1, { 0x2d27, 0 } },
+ { 0x10cd, 1, { 0x2d2d, 0 } },
+ { 0x10fc, 1, { 0x10dc, 0 } },
+ { 0x13f8, 1, { 0x13f0, 0 } },
+ { 0x13f9, 1, { 0x13f1, 0 } },
+ { 0x13fa, 1, { 0x13f2, 0 } },
+ { 0x13fb, 1, { 0x13f3, 0 } },
+ { 0x13fc, 1, { 0x13f4, 0 } },
+ { 0x13fd, 1, { 0x13f5, 0 } },
+ { 0x1c80, 1, { 0x432, 0 } },
+ { 0x1c81, 1, { 0x434, 0 } },
+ { 0x1c82, 1, { 0x43e, 0 } },
+ { 0x1c83, 1, { 0x441, 0 } },
+ { 0x1c84, 1, { 0x442, 0 } },
+ { 0x1c85, 1, { 0x442, 0 } },
+ { 0x1c86, 1, { 0x44a, 0 } },
+ { 0x1c87, 1, { 0x463, 0 } },
+ { 0x1c88, 1, { 0xa64b, 0 } },
+ { 0x1c90, 1, { 0x10d0, 0 } },
+ { 0x1c91, 1, { 0x10d1, 0 } },
+ { 0x1c92, 1, { 0x10d2, 0 } },
+ { 0x1c93, 1, { 0x10d3, 0 } },
+ { 0x1c94, 1, { 0x10d4, 0 } },
+ { 0x1c95, 1, { 0x10d5, 0 } },
+ { 0x1c96, 1, { 0x10d6, 0 } },
+ { 0x1c97, 1, { 0x10d7, 0 } },
+ { 0x1c98, 1, { 0x10d8, 0 } },
+ { 0x1c99, 1, { 0x10d9, 0 } },
+ { 0x1c9a, 1, { 0x10da, 0 } },
+ { 0x1c9b, 1, { 0x10db, 0 } },
+ { 0x1c9c, 1, { 0x10dc, 0 } },
+ { 0x1c9d, 1, { 0x10dd, 0 } },
+ { 0x1c9e, 1, { 0x10de, 0 } },
+ { 0x1c9f, 1, { 0x10df, 0 } },
+ { 0x1ca0, 1, { 0x10e0, 0 } },
+ { 0x1ca1, 1, { 0x10e1, 0 } },
+ { 0x1ca2, 1, { 0x10e2, 0 } },
+ { 0x1ca3, 1, { 0x10e3, 0 } },
+ { 0x1ca4, 1, { 0x10e4, 0 } },
+ { 0x1ca5, 1, { 0x10e5, 0 } },
+ { 0x1ca6, 1, { 0x10e6, 0 } },
+ { 0x1ca7, 1, { 0x10e7, 0 } },
+ { 0x1ca8, 1, { 0x10e8, 0 } },
+ { 0x1ca9, 1, { 0x10e9, 0 } },
+ { 0x1caa, 1, { 0x10ea, 0 } },
+ { 0x1cab, 1, { 0x10eb, 0 } },
+ { 0x1cac, 1, { 0x10ec, 0 } },
+ { 0x1cad, 1, { 0x10ed, 0 } },
+ { 0x1cae, 1, { 0x10ee, 0 } },
+ { 0x1caf, 1, { 0x10ef, 0 } },
+ { 0x1cb0, 1, { 0x10f0, 0 } },
+ { 0x1cb1, 1, { 0x10f1, 0 } },
+ { 0x1cb2, 1, { 0x10f2, 0 } },
+ { 0x1cb3, 1, { 0x10f3, 0 } },
+ { 0x1cb4, 1, { 0x10f4, 0 } },
+ { 0x1cb5, 1, { 0x10f5, 0 } },
+ { 0x1cb6, 1, { 0x10f6, 0 } },
+ { 0x1cb7, 1, { 0x10f7, 0 } },
+ { 0x1cb8, 1, { 0x10f8, 0 } },
+ { 0x1cb9, 1, { 0x10f9, 0 } },
+ { 0x1cba, 1, { 0x10fa, 0 } },
+ { 0x1cbd, 1, { 0x10fd, 0 } },
+ { 0x1cbe, 1, { 0x10fe, 0 } },
+ { 0x1cbf, 1, { 0x10ff, 0 } },
+ { 0x1d2c, 1, { 0x61, 0 } },
+ { 0x1d2d, 1, { 0xe6, 0 } },
+ { 0x1d2e, 1, { 0x62, 0 } },
+ { 0x1d30, 1, { 0x64, 0 } },
+ { 0x1d31, 1, { 0x65, 0 } },
+ { 0x1d32, 1, { 0x1dd, 0 } },
+ { 0x1d33, 1, { 0x67, 0 } },
+ { 0x1d34, 1, { 0x68, 0 } },
+ { 0x1d35, 1, { 0x69, 0 } },
+ { 0x1d36, 1, { 0x6a, 0 } },
+ { 0x1d37, 1, { 0x6b, 0 } },
+ { 0x1d38, 1, { 0x6c, 0 } },
+ { 0x1d39, 1, { 0x6d, 0 } },
+ { 0x1d3a, 1, { 0x6e, 0 } },
+ { 0x1d3c, 1, { 0x6f, 0 } },
+ { 0x1d3d, 1, { 0x223, 0 } },
+ { 0x1d3e, 1, { 0x70, 0 } },
+ { 0x1d3f, 1, { 0x72, 0 } },
+ { 0x1d40, 1, { 0x74, 0 } },
+ { 0x1d41, 1, { 0x75, 0 } },
+ { 0x1d42, 1, { 0x77, 0 } },
+ { 0x1d43, 1, { 0x61, 0 } },
+ { 0x1d44, 1, { 0x250, 0 } },
+ { 0x1d45, 1, { 0x251, 0 } },
+ { 0x1d46, 1, { 0x1d02, 0 } },
+ { 0x1d47, 1, { 0x62, 0 } },
+ { 0x1d48, 1, { 0x64, 0 } },
+ { 0x1d49, 1, { 0x65, 0 } },
+ { 0x1d4a, 1, { 0x259, 0 } },
+ { 0x1d4b, 1, { 0x25b, 0 } },
+ { 0x1d4c, 1, { 0x25c, 0 } },
+ { 0x1d4d, 1, { 0x67, 0 } },
+ { 0x1d4f, 1, { 0x6b, 0 } },
+ { 0x1d50, 1, { 0x6d, 0 } },
+ { 0x1d51, 1, { 0x14b, 0 } },
+ { 0x1d52, 1, { 0x6f, 0 } },
+ { 0x1d53, 1, { 0x254, 0 } },
+ { 0x1d54, 1, { 0x1d16, 0 } },
+ { 0x1d55, 1, { 0x1d17, 0 } },
+ { 0x1d56, 1, { 0x70, 0 } },
+ { 0x1d57, 1, { 0x74, 0 } },
+ { 0x1d58, 1, { 0x75, 0 } },
+ { 0x1d59, 1, { 0x1d1d, 0 } },
+ { 0x1d5a, 1, { 0x26f, 0 } },
+ { 0x1d5b, 1, { 0x76, 0 } },
+ { 0x1d5c, 1, { 0x1d25, 0 } },
+ { 0x1d5d, 1, { 0x3b2, 0 } },
+ { 0x1d5e, 1, { 0x3b3, 0 } },
+ { 0x1d5f, 1, { 0x3b4, 0 } },
+ { 0x1d60, 1, { 0x3c6, 0 } },
+ { 0x1d61, 1, { 0x3c7, 0 } },
+ { 0x1d62, 1, { 0x69, 0 } },
+ { 0x1d63, 1, { 0x72, 0 } },
+ { 0x1d64, 1, { 0x75, 0 } },
+ { 0x1d65, 1, { 0x76, 0 } },
+ { 0x1d66, 1, { 0x3b2, 0 } },
+ { 0x1d67, 1, { 0x3b3, 0 } },
+ { 0x1d68, 1, { 0x3c1, 0 } },
+ { 0x1d69, 1, { 0x3c6, 0 } },
+ { 0x1d6a, 1, { 0x3c7, 0 } },
+ { 0x1d78, 1, { 0x43d, 0 } },
+ { 0x1d9b, 1, { 0x252, 0 } },
+ { 0x1d9c, 1, { 0x63, 0 } },
+ { 0x1d9d, 1, { 0x255, 0 } },
+ { 0x1d9e, 1, { 0xf0, 0 } },
+ { 0x1d9f, 1, { 0x25c, 0 } },
+ { 0x1da0, 1, { 0x66, 0 } },
+ { 0x1da1, 1, { 0x25f, 0 } },
+ { 0x1da2, 1, { 0x261, 0 } },
+ { 0x1da3, 1, { 0x265, 0 } },
+ { 0x1da4, 1, { 0x268, 0 } },
+ { 0x1da5, 1, { 0x269, 0 } },
+ { 0x1da6, 1, { 0x26a, 0 } },
+ { 0x1da7, 1, { 0x1d7b, 0 } },
+ { 0x1da8, 1, { 0x29d, 0 } },
+ { 0x1da9, 1, { 0x26d, 0 } },
+ { 0x1daa, 1, { 0x1d85, 0 } },
+ { 0x1dab, 1, { 0x29f, 0 } },
+ { 0x1dac, 1, { 0x271, 0 } },
+ { 0x1dad, 1, { 0x270, 0 } },
+ { 0x1dae, 1, { 0x272, 0 } },
+ { 0x1daf, 1, { 0x273, 0 } },
+ { 0x1db0, 1, { 0x274, 0 } },
+ { 0x1db1, 1, { 0x275, 0 } },
+ { 0x1db2, 1, { 0x278, 0 } },
+ { 0x1db3, 1, { 0x282, 0 } },
+ { 0x1db4, 1, { 0x283, 0 } },
+ { 0x1db5, 1, { 0x1ab, 0 } },
+ { 0x1db6, 1, { 0x289, 0 } },
+ { 0x1db7, 1, { 0x28a, 0 } },
+ { 0x1db8, 1, { 0x1d1c, 0 } },
+ { 0x1db9, 1, { 0x28b, 0 } },
+ { 0x1dba, 1, { 0x28c, 0 } },
+ { 0x1dbb, 1, { 0x7a, 0 } },
+ { 0x1dbc, 1, { 0x290, 0 } },
+ { 0x1dbd, 1, { 0x291, 0 } },
+ { 0x1dbe, 1, { 0x292, 0 } },
+ { 0x1dbf, 1, { 0x3b8, 0 } },
+ { 0x1e00, 1, { 0x1e01, 0 } },
+ { 0x1e02, 1, { 0x1e03, 0 } },
+ { 0x1e04, 1, { 0x1e05, 0 } },
+ { 0x1e06, 1, { 0x1e07, 0 } },
+ { 0x1e08, 1, { 0x1e09, 0 } },
+ { 0x1e0a, 1, { 0x1e0b, 0 } },
+ { 0x1e0c, 1, { 0x1e0d, 0 } },
+ { 0x1e0e, 1, { 0x1e0f, 0 } },
+ { 0x1e10, 1, { 0x1e11, 0 } },
+ { 0x1e12, 1, { 0x1e13, 0 } },
+ { 0x1e14, 1, { 0x1e15, 0 } },
+ { 0x1e16, 1, { 0x1e17, 0 } },
+ { 0x1e18, 1, { 0x1e19, 0 } },
+ { 0x1e1a, 1, { 0x1e1b, 0 } },
+ { 0x1e1c, 1, { 0x1e1d, 0 } },
+ { 0x1e1e, 1, { 0x1e1f, 0 } },
+ { 0x1e20, 1, { 0x1e21, 0 } },
+ { 0x1e22, 1, { 0x1e23, 0 } },
+ { 0x1e24, 1, { 0x1e25, 0 } },
+ { 0x1e26, 1, { 0x1e27, 0 } },
+ { 0x1e28, 1, { 0x1e29, 0 } },
+ { 0x1e2a, 1, { 0x1e2b, 0 } },
+ { 0x1e2c, 1, { 0x1e2d, 0 } },
+ { 0x1e2e, 1, { 0x1e2f, 0 } },
+ { 0x1e30, 1, { 0x1e31, 0 } },
+ { 0x1e32, 1, { 0x1e33, 0 } },
+ { 0x1e34, 1, { 0x1e35, 0 } },
+ { 0x1e36, 1, { 0x1e37, 0 } },
+ { 0x1e38, 1, { 0x1e39, 0 } },
+ { 0x1e3a, 1, { 0x1e3b, 0 } },
+ { 0x1e3c, 1, { 0x1e3d, 0 } },
+ { 0x1e3e, 1, { 0x1e3f, 0 } },
+ { 0x1e40, 1, { 0x1e41, 0 } },
+ { 0x1e42, 1, { 0x1e43, 0 } },
+ { 0x1e44, 1, { 0x1e45, 0 } },
+ { 0x1e46, 1, { 0x1e47, 0 } },
+ { 0x1e48, 1, { 0x1e49, 0 } },
+ { 0x1e4a, 1, { 0x1e4b, 0 } },
+ { 0x1e4c, 1, { 0x1e4d, 0 } },
+ { 0x1e4e, 1, { 0x1e4f, 0 } },
+ { 0x1e50, 1, { 0x1e51, 0 } },
+ { 0x1e52, 1, { 0x1e53, 0 } },
+ { 0x1e54, 1, { 0x1e55, 0 } },
+ { 0x1e56, 1, { 0x1e57, 0 } },
+ { 0x1e58, 1, { 0x1e59, 0 } },
+ { 0x1e5a, 1, { 0x1e5b, 0 } },
+ { 0x1e5c, 1, { 0x1e5d, 0 } },
+ { 0x1e5e, 1, { 0x1e5f, 0 } },
+ { 0x1e60, 1, { 0x1e61, 0 } },
+ { 0x1e62, 1, { 0x1e63, 0 } },
+ { 0x1e64, 1, { 0x1e65, 0 } },
+ { 0x1e66, 1, { 0x1e67, 0 } },
+ { 0x1e68, 1, { 0x1e69, 0 } },
+ { 0x1e6a, 1, { 0x1e6b, 0 } },
+ { 0x1e6c, 1, { 0x1e6d, 0 } },
+ { 0x1e6e, 1, { 0x1e6f, 0 } },
+ { 0x1e70, 1, { 0x1e71, 0 } },
+ { 0x1e72, 1, { 0x1e73, 0 } },
+ { 0x1e74, 1, { 0x1e75, 0 } },
+ { 0x1e76, 1, { 0x1e77, 0 } },
+ { 0x1e78, 1, { 0x1e79, 0 } },
+ { 0x1e7a, 1, { 0x1e7b, 0 } },
+ { 0x1e7c, 1, { 0x1e7d, 0 } },
+ { 0x1e7e, 1, { 0x1e7f, 0 } },
+ { 0x1e80, 1, { 0x1e81, 0 } },
+ { 0x1e82, 1, { 0x1e83, 0 } },
+ { 0x1e84, 1, { 0x1e85, 0 } },
+ { 0x1e86, 1, { 0x1e87, 0 } },
+ { 0x1e88, 1, { 0x1e89, 0 } },
+ { 0x1e8a, 1, { 0x1e8b, 0 } },
+ { 0x1e8c, 1, { 0x1e8d, 0 } },
+ { 0x1e8e, 1, { 0x1e8f, 0 } },
+ { 0x1e90, 1, { 0x1e91, 0 } },
+ { 0x1e92, 1, { 0x1e93, 0 } },
+ { 0x1e94, 1, { 0x1e95, 0 } },
+ { 0x1e9a, 2, { 0x61, 0x2be } },
+ { 0x1e9b, 1, { 0x1e61, 0 } },
+ { 0x1e9e, 1, { 0xdf, 0 } },
+ { 0x1ea0, 1, { 0x1ea1, 0 } },
+ { 0x1ea2, 1, { 0x1ea3, 0 } },
+ { 0x1ea4, 1, { 0x1ea5, 0 } },
+ { 0x1ea6, 1, { 0x1ea7, 0 } },
+ { 0x1ea8, 1, { 0x1ea9, 0 } },
+ { 0x1eaa, 1, { 0x1eab, 0 } },
+ { 0x1eac, 1, { 0x1ead, 0 } },
+ { 0x1eae, 1, { 0x1eaf, 0 } },
+ { 0x1eb0, 1, { 0x1eb1, 0 } },
+ { 0x1eb2, 1, { 0x1eb3, 0 } },
+ { 0x1eb4, 1, { 0x1eb5, 0 } },
+ { 0x1eb6, 1, { 0x1eb7, 0 } },
+ { 0x1eb8, 1, { 0x1eb9, 0 } },
+ { 0x1eba, 1, { 0x1ebb, 0 } },
+ { 0x1ebc, 1, { 0x1ebd, 0 } },
+ { 0x1ebe, 1, { 0x1ebf, 0 } },
+ { 0x1ec0, 1, { 0x1ec1, 0 } },
+ { 0x1ec2, 1, { 0x1ec3, 0 } },
+ { 0x1ec4, 1, { 0x1ec5, 0 } },
+ { 0x1ec6, 1, { 0x1ec7, 0 } },
+ { 0x1ec8, 1, { 0x1ec9, 0 } },
+ { 0x1eca, 1, { 0x1ecb, 0 } },
+ { 0x1ecc, 1, { 0x1ecd, 0 } },
+ { 0x1ece, 1, { 0x1ecf, 0 } },
+ { 0x1ed0, 1, { 0x1ed1, 0 } },
+ { 0x1ed2, 1, { 0x1ed3, 0 } },
+ { 0x1ed4, 1, { 0x1ed5, 0 } },
+ { 0x1ed6, 1, { 0x1ed7, 0 } },
+ { 0x1ed8, 1, { 0x1ed9, 0 } },
+ { 0x1eda, 1, { 0x1edb, 0 } },
+ { 0x1edc, 1, { 0x1edd, 0 } },
+ { 0x1ede, 1, { 0x1edf, 0 } },
+ { 0x1ee0, 1, { 0x1ee1, 0 } },
+ { 0x1ee2, 1, { 0x1ee3, 0 } },
+ { 0x1ee4, 1, { 0x1ee5, 0 } },
+ { 0x1ee6, 1, { 0x1ee7, 0 } },
+ { 0x1ee8, 1, { 0x1ee9, 0 } },
+ { 0x1eea, 1, { 0x1eeb, 0 } },
+ { 0x1eec, 1, { 0x1eed, 0 } },
+ { 0x1eee, 1, { 0x1eef, 0 } },
+ { 0x1ef0, 1, { 0x1ef1, 0 } },
+ { 0x1ef2, 1, { 0x1ef3, 0 } },
+ { 0x1ef4, 1, { 0x1ef5, 0 } },
+ { 0x1ef6, 1, { 0x1ef7, 0 } },
+ { 0x1ef8, 1, { 0x1ef9, 0 } },
+ { 0x1efa, 1, { 0x1efb, 0 } },
+ { 0x1efc, 1, { 0x1efd, 0 } },
+ { 0x1efe, 1, { 0x1eff, 0 } },
+ { 0x1f08, 1, { 0x1f00, 0 } },
+ { 0x1f09, 1, { 0x1f01, 0 } },
+ { 0x1f0a, 1, { 0x1f02, 0 } },
+ { 0x1f0b, 1, { 0x1f03, 0 } },
+ { 0x1f0c, 1, { 0x1f04, 0 } },
+ { 0x1f0d, 1, { 0x1f05, 0 } },
+ { 0x1f0e, 1, { 0x1f06, 0 } },
+ { 0x1f0f, 1, { 0x1f07, 0 } },
+ { 0x1f18, 1, { 0x1f10, 0 } },
+ { 0x1f19, 1, { 0x1f11, 0 } },
+ { 0x1f1a, 1, { 0x1f12, 0 } },
+ { 0x1f1b, 1, { 0x1f13, 0 } },
+ { 0x1f1c, 1, { 0x1f14, 0 } },
+ { 0x1f1d, 1, { 0x1f15, 0 } },
+ { 0x1f28, 1, { 0x1f20, 0 } },
+ { 0x1f29, 1, { 0x1f21, 0 } },
+ { 0x1f2a, 1, { 0x1f22, 0 } },
+ { 0x1f2b, 1, { 0x1f23, 0 } },
+ { 0x1f2c, 1, { 0x1f24, 0 } },
+ { 0x1f2d, 1, { 0x1f25, 0 } },
+ { 0x1f2e, 1, { 0x1f26, 0 } },
+ { 0x1f2f, 1, { 0x1f27, 0 } },
+ { 0x1f38, 1, { 0x1f30, 0 } },
+ { 0x1f39, 1, { 0x1f31, 0 } },
+ { 0x1f3a, 1, { 0x1f32, 0 } },
+ { 0x1f3b, 1, { 0x1f33, 0 } },
+ { 0x1f3c, 1, { 0x1f34, 0 } },
+ { 0x1f3d, 1, { 0x1f35, 0 } },
+ { 0x1f3e, 1, { 0x1f36, 0 } },
+ { 0x1f3f, 1, { 0x1f37, 0 } },
+ { 0x1f48, 1, { 0x1f40, 0 } },
+ { 0x1f49, 1, { 0x1f41, 0 } },
+ { 0x1f4a, 1, { 0x1f42, 0 } },
+ { 0x1f4b, 1, { 0x1f43, 0 } },
+ { 0x1f4c, 1, { 0x1f44, 0 } },
+ { 0x1f4d, 1, { 0x1f45, 0 } },
+ { 0x1f59, 1, { 0x1f51, 0 } },
+ { 0x1f5b, 1, { 0x1f53, 0 } },
+ { 0x1f5d, 1, { 0x1f55, 0 } },
+ { 0x1f5f, 1, { 0x1f57, 0 } },
+ { 0x1f68, 1, { 0x1f60, 0 } },
+ { 0x1f69, 1, { 0x1f61, 0 } },
+ { 0x1f6a, 1, { 0x1f62, 0 } },
+ { 0x1f6b, 1, { 0x1f63, 0 } },
+ { 0x1f6c, 1, { 0x1f64, 0 } },
+ { 0x1f6d, 1, { 0x1f65, 0 } },
+ { 0x1f6e, 1, { 0x1f66, 0 } },
+ { 0x1f6f, 1, { 0x1f67, 0 } },
+ { 0x1f71, 1, { 0x3ac, 0 } },
+ { 0x1f73, 1, { 0x3ad, 0 } },
+ { 0x1f75, 1, { 0x3ae, 0 } },
+ { 0x1f77, 1, { 0x3af, 0 } },
+ { 0x1f79, 1, { 0x3cc, 0 } },
+ { 0x1f7b, 1, { 0x3cd, 0 } },
+ { 0x1f7d, 1, { 0x3ce, 0 } },
+ { 0x1f80, 2, { 0x1f00, 0x3b9 } },
+ { 0x1f81, 2, { 0x1f01, 0x3b9 } },
+ { 0x1f82, 2, { 0x1f02, 0x3b9 } },
+ { 0x1f83, 2, { 0x1f03, 0x3b9 } },
+ { 0x1f84, 2, { 0x1f04, 0x3b9 } },
+ { 0x1f85, 2, { 0x1f05, 0x3b9 } },
+ { 0x1f86, 2, { 0x1f06, 0x3b9 } },
+ { 0x1f87, 2, { 0x1f07, 0x3b9 } },
+ { 0x1f88, 2, { 0x1f00, 0x3b9 } },
+ { 0x1f89, 2, { 0x1f01, 0x3b9 } },
+ { 0x1f8a, 2, { 0x1f02, 0x3b9 } },
+ { 0x1f8b, 2, { 0x1f03, 0x3b9 } },
+ { 0x1f8c, 2, { 0x1f04, 0x3b9 } },
+ { 0x1f8d, 2, { 0x1f05, 0x3b9 } },
+ { 0x1f8e, 2, { 0x1f06, 0x3b9 } },
+ { 0x1f8f, 2, { 0x1f07, 0x3b9 } },
+ { 0x1f90, 2, { 0x1f20, 0x3b9 } },
+ { 0x1f91, 2, { 0x1f21, 0x3b9 } },
+ { 0x1f92, 2, { 0x1f22, 0x3b9 } },
+ { 0x1f93, 2, { 0x1f23, 0x3b9 } },
+ { 0x1f94, 2, { 0x1f24, 0x3b9 } },
+ { 0x1f95, 2, { 0x1f25, 0x3b9 } },
+ { 0x1f96, 2, { 0x1f26, 0x3b9 } },
+ { 0x1f97, 2, { 0x1f27, 0x3b9 } },
+ { 0x1f98, 2, { 0x1f20, 0x3b9 } },
+ { 0x1f99, 2, { 0x1f21, 0x3b9 } },
+ { 0x1f9a, 2, { 0x1f22, 0x3b9 } },
+ { 0x1f9b, 2, { 0x1f23, 0x3b9 } },
+ { 0x1f9c, 2, { 0x1f24, 0x3b9 } },
+ { 0x1f9d, 2, { 0x1f25, 0x3b9 } },
+ { 0x1f9e, 2, { 0x1f26, 0x3b9 } },
+ { 0x1f9f, 2, { 0x1f27, 0x3b9 } },
+ { 0x1fa0, 2, { 0x1f60, 0x3b9 } },
+ { 0x1fa1, 2, { 0x1f61, 0x3b9 } },
+ { 0x1fa2, 2, { 0x1f62, 0x3b9 } },
+ { 0x1fa3, 2, { 0x1f63, 0x3b9 } },
+ { 0x1fa4, 2, { 0x1f64, 0x3b9 } },
+ { 0x1fa5, 2, { 0x1f65, 0x3b9 } },
+ { 0x1fa6, 2, { 0x1f66, 0x3b9 } },
+ { 0x1fa7, 2, { 0x1f67, 0x3b9 } },
+ { 0x1fa8, 2, { 0x1f60, 0x3b9 } },
+ { 0x1fa9, 2, { 0x1f61, 0x3b9 } },
+ { 0x1faa, 2, { 0x1f62, 0x3b9 } },
+ { 0x1fab, 2, { 0x1f63, 0x3b9 } },
+ { 0x1fac, 2, { 0x1f64, 0x3b9 } },
+ { 0x1fad, 2, { 0x1f65, 0x3b9 } },
+ { 0x1fae, 2, { 0x1f66, 0x3b9 } },
+ { 0x1faf, 2, { 0x1f67, 0x3b9 } },
+ { 0x1fb2, 2, { 0x1f70, 0x3b9 } },
+ { 0x1fb3, 2, { 0x3b1, 0x3b9 } },
+ { 0x1fb4, 2, { 0x3ac, 0x3b9 } },
+ { 0x1fb7, 2, { 0x1fb6, 0x3b9 } },
+ { 0x1fb8, 1, { 0x1fb0, 0 } },
+ { 0x1fb9, 1, { 0x1fb1, 0 } },
+ { 0x1fba, 1, { 0x1f70, 0 } },
+ { 0x1fbb, 1, { 0x3ac, 0 } },
+ { 0x1fbc, 2, { 0x3b1, 0x3b9 } },
+ { 0x1fbe, 1, { 0x3b9, 0 } },
+ { 0x1fc2, 2, { 0x1f74, 0x3b9 } },
+ { 0x1fc3, 2, { 0x3b7, 0x3b9 } },
+ { 0x1fc4, 2, { 0x3ae, 0x3b9 } },
+ { 0x1fc7, 2, { 0x1fc6, 0x3b9 } },
+ { 0x1fc8, 1, { 0x1f72, 0 } },
+ { 0x1fc9, 1, { 0x3ad, 0 } },
+ { 0x1fca, 1, { 0x1f74, 0 } },
+ { 0x1fcb, 1, { 0x3ae, 0 } },
+ { 0x1fcc, 2, { 0x3b7, 0x3b9 } },
+ { 0x1fd3, 1, { 0x390, 0 } },
+ { 0x1fd8, 1, { 0x1fd0, 0 } },
+ { 0x1fd9, 1, { 0x1fd1, 0 } },
+ { 0x1fda, 1, { 0x1f76, 0 } },
+ { 0x1fdb, 1, { 0x3af, 0 } },
+ { 0x1fe3, 1, { 0x3b0, 0 } },
+ { 0x1fe8, 1, { 0x1fe0, 0 } },
+ { 0x1fe9, 1, { 0x1fe1, 0 } },
+ { 0x1fea, 1, { 0x1f7a, 0 } },
+ { 0x1feb, 1, { 0x3cd, 0 } },
+ { 0x1fec, 1, { 0x1fe5, 0 } },
+ { 0x1ff2, 2, { 0x1f7c, 0x3b9 } },
+ { 0x1ff3, 2, { 0x3c9, 0x3b9 } },
+ { 0x1ff4, 2, { 0x3ce, 0x3b9 } },
+ { 0x1ff7, 2, { 0x1ff6, 0x3b9 } },
+ { 0x1ff8, 1, { 0x1f78, 0 } },
+ { 0x1ff9, 1, { 0x3cc, 0 } },
+ { 0x1ffa, 1, { 0x1f7c, 0 } },
+ { 0x1ffb, 1, { 0x3ce, 0 } },
+ { 0x1ffc, 2, { 0x3c9, 0x3b9 } },
+ { 0x2011, 1, { 0x2010, 0 } },
+ { 0x2033, 2, { 0x2032, 0x2032 } },
+ { 0x2034, 3, { 840, 0 } },
+ { 0x2036, 2, { 0x2035, 0x2035 } },
+ { 0x2037, 3, { 761, 0 } },
+ { 0x2057, 4, { 840, 0 } },
+ { 0x2070, 1, { 0x30, 0 } },
+ { 0x2071, 1, { 0x69, 0 } },
+ { 0x2074, 1, { 0x34, 0 } },
+ { 0x2075, 1, { 0x35, 0 } },
+ { 0x2076, 1, { 0x36, 0 } },
+ { 0x2077, 1, { 0x37, 0 } },
+ { 0x2078, 1, { 0x38, 0 } },
+ { 0x2079, 1, { 0x39, 0 } },
+ { 0x207b, 1, { 0x2212, 0 } },
+ { 0x207f, 1, { 0x6e, 0 } },
+ { 0x2080, 1, { 0x30, 0 } },
+ { 0x2081, 1, { 0x31, 0 } },
+ { 0x2082, 1, { 0x32, 0 } },
+ { 0x2083, 1, { 0x33, 0 } },
+ { 0x2084, 1, { 0x34, 0 } },
+ { 0x2085, 1, { 0x35, 0 } },
+ { 0x2086, 1, { 0x36, 0 } },
+ { 0x2087, 1, { 0x37, 0 } },
+ { 0x2088, 1, { 0x38, 0 } },
+ { 0x2089, 1, { 0x39, 0 } },
+ { 0x208b, 1, { 0x2212, 0 } },
+ { 0x2090, 1, { 0x61, 0 } },
+ { 0x2091, 1, { 0x65, 0 } },
+ { 0x2092, 1, { 0x6f, 0 } },
+ { 0x2093, 1, { 0x78, 0 } },
+ { 0x2094, 1, { 0x259, 0 } },
+ { 0x2095, 1, { 0x68, 0 } },
+ { 0x2096, 1, { 0x6b, 0 } },
+ { 0x2097, 1, { 0x6c, 0 } },
+ { 0x2098, 1, { 0x6d, 0 } },
+ { 0x2099, 1, { 0x6e, 0 } },
+ { 0x209a, 1, { 0x70, 0 } },
+ { 0x209b, 1, { 0x73, 0 } },
+ { 0x209c, 1, { 0x74, 0 } },
+ { 0x20a8, 2, { 0x72, 0x73 } },
+ { 0x2102, 1, { 0x63, 0 } },
+ { 0x2103, 2, { 0xb0, 0x63 } },
+ { 0x2107, 1, { 0x25b, 0 } },
+ { 0x2109, 2, { 0xb0, 0x66 } },
+ { 0x210a, 1, { 0x67, 0 } },
+ { 0x210b, 1, { 0x68, 0 } },
+ { 0x210c, 1, { 0x68, 0 } },
+ { 0x210d, 1, { 0x68, 0 } },
+ { 0x210e, 1, { 0x68, 0 } },
+ { 0x210f, 1, { 0x127, 0 } },
+ { 0x2110, 1, { 0x69, 0 } },
+ { 0x2111, 1, { 0x69, 0 } },
+ { 0x2112, 1, { 0x6c, 0 } },
+ { 0x2113, 1, { 0x6c, 0 } },
+ { 0x2115, 1, { 0x6e, 0 } },
+ { 0x2116, 2, { 0x6e, 0x6f } },
+ { 0x2119, 1, { 0x70, 0 } },
+ { 0x211a, 1, { 0x71, 0 } },
+ { 0x211b, 1, { 0x72, 0 } },
+ { 0x211c, 1, { 0x72, 0 } },
+ { 0x211d, 1, { 0x72, 0 } },
+ { 0x2120, 2, { 0x73, 0x6d } },
+ { 0x2121, 3, { 96, 0 } },
+ { 0x2122, 2, { 0x74, 0x6d } },
+ { 0x2124, 1, { 0x7a, 0 } },
+ { 0x2126, 1, { 0x3c9, 0 } },
+ { 0x2128, 1, { 0x7a, 0 } },
+ { 0x212a, 1, { 0x6b, 0 } },
+ { 0x212b, 1, { 0xe5, 0 } },
+ { 0x212c, 1, { 0x62, 0 } },
+ { 0x212d, 1, { 0x63, 0 } },
+ { 0x212f, 1, { 0x65, 0 } },
+ { 0x2130, 1, { 0x65, 0 } },
+ { 0x2131, 1, { 0x66, 0 } },
+ { 0x2133, 1, { 0x6d, 0 } },
+ { 0x2134, 1, { 0x6f, 0 } },
+ { 0x2135, 1, { 0x5d0, 0 } },
+ { 0x2136, 1, { 0x5d1, 0 } },
+ { 0x2137, 1, { 0x5d2, 0 } },
+ { 0x2138, 1, { 0x5d3, 0 } },
+ { 0x2139, 1, { 0x69, 0 } },
+ { 0x213b, 3, { 499, 0 } },
+ { 0x213c, 1, { 0x3c0, 0 } },
+ { 0x213d, 1, { 0x3b3, 0 } },
+ { 0x213e, 1, { 0x3b3, 0 } },
+ { 0x213f, 1, { 0x3c0, 0 } },
+ { 0x2140, 1, { 0x2211, 0 } },
+ { 0x2145, 1, { 0x64, 0 } },
+ { 0x2146, 1, { 0x64, 0 } },
+ { 0x2147, 1, { 0x65, 0 } },
+ { 0x2148, 1, { 0x69, 0 } },
+ { 0x2149, 1, { 0x6a, 0 } },
+ { 0x2150, 3, { 688, 0 } },
+ { 0x2151, 3, { 682, 0 } },
+ { 0x2152, 4, { 890, 0 } },
+ { 0x2153, 3, { 69, 0 } },
+ { 0x2154, 3, { 494, 0 } },
+ { 0x2155, 3, { 63, 0 } },
+ { 0x2156, 3, { 84, 0 } },
+ { 0x2157, 3, { 708, 0 } },
+ { 0x2158, 3, { 472, 0 } },
+ { 0x2159, 3, { 60, 0 } },
+ { 0x215a, 3, { 710, 0 } },
+ { 0x215b, 3, { 685, 0 } },
+ { 0x215c, 3, { 718, 0 } },
+ { 0x215d, 3, { 474, 0 } },
+ { 0x215e, 3, { 690, 0 } },
+ { 0x215f, 2, { 0x31, 0x2044 } },
+ { 0x2160, 1, { 0x69, 0 } },
+ { 0x2161, 2, { 0x69, 0x69 } },
+ { 0x2162, 3, { 730, 0 } },
+ { 0x2163, 2, { 0x69, 0x76 } },
+ { 0x2164, 1, { 0x76, 0 } },
+ { 0x2165, 2, { 0x76, 0x69 } },
+ { 0x2166, 3, { 729, 0 } },
+ { 0x2167, 4, { 729, 0 } },
+ { 0x2168, 2, { 0x69, 0x78 } },
+ { 0x2169, 1, { 0x78, 0 } },
+ { 0x216a, 2, { 0x78, 0x69 } },
+ { 0x216b, 3, { 501, 0 } },
+ { 0x216c, 1, { 0x6c, 0 } },
+ { 0x216d, 1, { 0x63, 0 } },
+ { 0x216e, 1, { 0x64, 0 } },
+ { 0x216f, 1, { 0x6d, 0 } },
+ { 0x2170, 1, { 0x69, 0 } },
+ { 0x2171, 2, { 0x69, 0x69 } },
+ { 0x2172, 3, { 730, 0 } },
+ { 0x2173, 2, { 0x69, 0x76 } },
+ { 0x2174, 1, { 0x76, 0 } },
+ { 0x2175, 2, { 0x76, 0x69 } },
+ { 0x2176, 3, { 729, 0 } },
+ { 0x2177, 4, { 729, 0 } },
+ { 0x2178, 2, { 0x69, 0x78 } },
+ { 0x2179, 1, { 0x78, 0 } },
+ { 0x217a, 2, { 0x78, 0x69 } },
+ { 0x217b, 3, { 501, 0 } },
+ { 0x217c, 1, { 0x6c, 0 } },
+ { 0x217d, 1, { 0x63, 0 } },
+ { 0x217e, 1, { 0x64, 0 } },
+ { 0x217f, 1, { 0x6d, 0 } },
+ { 0x2189, 3, { 901, 0 } },
+ { 0x222c, 2, { 0x222b, 0x222b } },
+ { 0x222d, 3, { 795, 0 } },
+ { 0x222f, 2, { 0x222e, 0x222e } },
+ { 0x2230, 3, { 134, 0 } },
+ { 0x2329, 1, { 0x3008, 0 } },
+ { 0x232a, 1, { 0x3009, 0 } },
+ { 0x2460, 1, { 0x31, 0 } },
+ { 0x2461, 1, { 0x32, 0 } },
+ { 0x2462, 1, { 0x33, 0 } },
+ { 0x2463, 1, { 0x34, 0 } },
+ { 0x2464, 1, { 0x35, 0 } },
+ { 0x2465, 1, { 0x36, 0 } },
+ { 0x2466, 1, { 0x37, 0 } },
+ { 0x2467, 1, { 0x38, 0 } },
+ { 0x2468, 1, { 0x39, 0 } },
+ { 0x2469, 2, { 0x31, 0x30 } },
+ { 0x246a, 2, { 0x31, 0x31 } },
+ { 0x246b, 2, { 0x31, 0x32 } },
+ { 0x246c, 2, { 0x31, 0x33 } },
+ { 0x246d, 2, { 0x31, 0x34 } },
+ { 0x246e, 2, { 0x31, 0x35 } },
+ { 0x246f, 2, { 0x31, 0x36 } },
+ { 0x2470, 2, { 0x31, 0x37 } },
+ { 0x2471, 2, { 0x31, 0x38 } },
+ { 0x2472, 2, { 0x31, 0x39 } },
+ { 0x2473, 2, { 0x32, 0x30 } },
+ { 0x24b6, 1, { 0x61, 0 } },
+ { 0x24b7, 1, { 0x62, 0 } },
+ { 0x24b8, 1, { 0x63, 0 } },
+ { 0x24b9, 1, { 0x64, 0 } },
+ { 0x24ba, 1, { 0x65, 0 } },
+ { 0x24bb, 1, { 0x66, 0 } },
+ { 0x24bc, 1, { 0x67, 0 } },
+ { 0x24bd, 1, { 0x68, 0 } },
+ { 0x24be, 1, { 0x69, 0 } },
+ { 0x24bf, 1, { 0x6a, 0 } },
+ { 0x24c0, 1, { 0x6b, 0 } },
+ { 0x24c1, 1, { 0x6c, 0 } },
+ { 0x24c2, 1, { 0x6d, 0 } },
+ { 0x24c3, 1, { 0x6e, 0 } },
+ { 0x24c4, 1, { 0x6f, 0 } },
+ { 0x24c5, 1, { 0x70, 0 } },
+ { 0x24c6, 1, { 0x71, 0 } },
+ { 0x24c7, 1, { 0x72, 0 } },
+ { 0x24c8, 1, { 0x73, 0 } },
+ { 0x24c9, 1, { 0x74, 0 } },
+ { 0x24ca, 1, { 0x75, 0 } },
+ { 0x24cb, 1, { 0x76, 0 } },
+ { 0x24cc, 1, { 0x77, 0 } },
+ { 0x24cd, 1, { 0x78, 0 } },
+ { 0x24ce, 1, { 0x79, 0 } },
+ { 0x24cf, 1, { 0x7a, 0 } },
+ { 0x24d0, 1, { 0x61, 0 } },
+ { 0x24d1, 1, { 0x62, 0 } },
+ { 0x24d2, 1, { 0x63, 0 } },
+ { 0x24d3, 1, { 0x64, 0 } },
+ { 0x24d4, 1, { 0x65, 0 } },
+ { 0x24d5, 1, { 0x66, 0 } },
+ { 0x24d6, 1, { 0x67, 0 } },
+ { 0x24d7, 1, { 0x68, 0 } },
+ { 0x24d8, 1, { 0x69, 0 } },
+ { 0x24d9, 1, { 0x6a, 0 } },
+ { 0x24da, 1, { 0x6b, 0 } },
+ { 0x24db, 1, { 0x6c, 0 } },
+ { 0x24dc, 1, { 0x6d, 0 } },
+ { 0x24dd, 1, { 0x6e, 0 } },
+ { 0x24de, 1, { 0x6f, 0 } },
+ { 0x24df, 1, { 0x70, 0 } },
+ { 0x24e0, 1, { 0x71, 0 } },
+ { 0x24e1, 1, { 0x72, 0 } },
+ { 0x24e2, 1, { 0x73, 0 } },
+ { 0x24e3, 1, { 0x74, 0 } },
+ { 0x24e4, 1, { 0x75, 0 } },
+ { 0x24e5, 1, { 0x76, 0 } },
+ { 0x24e6, 1, { 0x77, 0 } },
+ { 0x24e7, 1, { 0x78, 0 } },
+ { 0x24e8, 1, { 0x79, 0 } },
+ { 0x24e9, 1, { 0x7a, 0 } },
+ { 0x24ea, 1, { 0x30, 0 } },
+ { 0x2a0c, 4, { 795, 0 } },
+ { 0x2adc, 2, { 0x2add, 0x338 } },
+ { 0x2c00, 1, { 0x2c30, 0 } },
+ { 0x2c01, 1, { 0x2c31, 0 } },
+ { 0x2c02, 1, { 0x2c32, 0 } },
+ { 0x2c03, 1, { 0x2c33, 0 } },
+ { 0x2c04, 1, { 0x2c34, 0 } },
+ { 0x2c05, 1, { 0x2c35, 0 } },
+ { 0x2c06, 1, { 0x2c36, 0 } },
+ { 0x2c07, 1, { 0x2c37, 0 } },
+ { 0x2c08, 1, { 0x2c38, 0 } },
+ { 0x2c09, 1, { 0x2c39, 0 } },
+ { 0x2c0a, 1, { 0x2c3a, 0 } },
+ { 0x2c0b, 1, { 0x2c3b, 0 } },
+ { 0x2c0c, 1, { 0x2c3c, 0 } },
+ { 0x2c0d, 1, { 0x2c3d, 0 } },
+ { 0x2c0e, 1, { 0x2c3e, 0 } },
+ { 0x2c0f, 1, { 0x2c3f, 0 } },
+ { 0x2c10, 1, { 0x2c40, 0 } },
+ { 0x2c11, 1, { 0x2c41, 0 } },
+ { 0x2c12, 1, { 0x2c42, 0 } },
+ { 0x2c13, 1, { 0x2c43, 0 } },
+ { 0x2c14, 1, { 0x2c44, 0 } },
+ { 0x2c15, 1, { 0x2c45, 0 } },
+ { 0x2c16, 1, { 0x2c46, 0 } },
+ { 0x2c17, 1, { 0x2c47, 0 } },
+ { 0x2c18, 1, { 0x2c48, 0 } },
+ { 0x2c19, 1, { 0x2c49, 0 } },
+ { 0x2c1a, 1, { 0x2c4a, 0 } },
+ { 0x2c1b, 1, { 0x2c4b, 0 } },
+ { 0x2c1c, 1, { 0x2c4c, 0 } },
+ { 0x2c1d, 1, { 0x2c4d, 0 } },
+ { 0x2c1e, 1, { 0x2c4e, 0 } },
+ { 0x2c1f, 1, { 0x2c4f, 0 } },
+ { 0x2c20, 1, { 0x2c50, 0 } },
+ { 0x2c21, 1, { 0x2c51, 0 } },
+ { 0x2c22, 1, { 0x2c52, 0 } },
+ { 0x2c23, 1, { 0x2c53, 0 } },
+ { 0x2c24, 1, { 0x2c54, 0 } },
+ { 0x2c25, 1, { 0x2c55, 0 } },
+ { 0x2c26, 1, { 0x2c56, 0 } },
+ { 0x2c27, 1, { 0x2c57, 0 } },
+ { 0x2c28, 1, { 0x2c58, 0 } },
+ { 0x2c29, 1, { 0x2c59, 0 } },
+ { 0x2c2a, 1, { 0x2c5a, 0 } },
+ { 0x2c2b, 1, { 0x2c5b, 0 } },
+ { 0x2c2c, 1, { 0x2c5c, 0 } },
+ { 0x2c2d, 1, { 0x2c5d, 0 } },
+ { 0x2c2e, 1, { 0x2c5e, 0 } },
+ { 0x2c2f, 1, { 0x2c5f, 0 } },
+ { 0x2c60, 1, { 0x2c61, 0 } },
+ { 0x2c62, 1, { 0x26b, 0 } },
+ { 0x2c63, 1, { 0x1d7d, 0 } },
+ { 0x2c64, 1, { 0x27d, 0 } },
+ { 0x2c67, 1, { 0x2c68, 0 } },
+ { 0x2c69, 1, { 0x2c6a, 0 } },
+ { 0x2c6b, 1, { 0x2c6c, 0 } },
+ { 0x2c6d, 1, { 0x251, 0 } },
+ { 0x2c6e, 1, { 0x271, 0 } },
+ { 0x2c6f, 1, { 0x250, 0 } },
+ { 0x2c70, 1, { 0x252, 0 } },
+ { 0x2c72, 1, { 0x2c73, 0 } },
+ { 0x2c75, 1, { 0x2c76, 0 } },
+ { 0x2c7c, 1, { 0x6a, 0 } },
+ { 0x2c7d, 1, { 0x76, 0 } },
+ { 0x2c7e, 1, { 0x23f, 0 } },
+ { 0x2c7f, 1, { 0x240, 0 } },
+ { 0x2c80, 1, { 0x2c81, 0 } },
+ { 0x2c82, 1, { 0x2c83, 0 } },
+ { 0x2c84, 1, { 0x2c85, 0 } },
+ { 0x2c86, 1, { 0x2c87, 0 } },
+ { 0x2c88, 1, { 0x2c89, 0 } },
+ { 0x2c8a, 1, { 0x2c8b, 0 } },
+ { 0x2c8c, 1, { 0x2c8d, 0 } },
+ { 0x2c8e, 1, { 0x2c8f, 0 } },
+ { 0x2c90, 1, { 0x2c91, 0 } },
+ { 0x2c92, 1, { 0x2c93, 0 } },
+ { 0x2c94, 1, { 0x2c95, 0 } },
+ { 0x2c96, 1, { 0x2c97, 0 } },
+ { 0x2c98, 1, { 0x2c99, 0 } },
+ { 0x2c9a, 1, { 0x2c9b, 0 } },
+ { 0x2c9c, 1, { 0x2c9d, 0 } },
+ { 0x2c9e, 1, { 0x2c9f, 0 } },
+ { 0x2ca0, 1, { 0x2ca1, 0 } },
+ { 0x2ca2, 1, { 0x2ca3, 0 } },
+ { 0x2ca4, 1, { 0x2ca5, 0 } },
+ { 0x2ca6, 1, { 0x2ca7, 0 } },
+ { 0x2ca8, 1, { 0x2ca9, 0 } },
+ { 0x2caa, 1, { 0x2cab, 0 } },
+ { 0x2cac, 1, { 0x2cad, 0 } },
+ { 0x2cae, 1, { 0x2caf, 0 } },
+ { 0x2cb0, 1, { 0x2cb1, 0 } },
+ { 0x2cb2, 1, { 0x2cb3, 0 } },
+ { 0x2cb4, 1, { 0x2cb5, 0 } },
+ { 0x2cb6, 1, { 0x2cb7, 0 } },
+ { 0x2cb8, 1, { 0x2cb9, 0 } },
+ { 0x2cba, 1, { 0x2cbb, 0 } },
+ { 0x2cbc, 1, { 0x2cbd, 0 } },
+ { 0x2cbe, 1, { 0x2cbf, 0 } },
+ { 0x2cc0, 1, { 0x2cc1, 0 } },
+ { 0x2cc2, 1, { 0x2cc3, 0 } },
+ { 0x2cc4, 1, { 0x2cc5, 0 } },
+ { 0x2cc6, 1, { 0x2cc7, 0 } },
+ { 0x2cc8, 1, { 0x2cc9, 0 } },
+ { 0x2cca, 1, { 0x2ccb, 0 } },
+ { 0x2ccc, 1, { 0x2ccd, 0 } },
+ { 0x2cce, 1, { 0x2ccf, 0 } },
+ { 0x2cd0, 1, { 0x2cd1, 0 } },
+ { 0x2cd2, 1, { 0x2cd3, 0 } },
+ { 0x2cd4, 1, { 0x2cd5, 0 } },
+ { 0x2cd6, 1, { 0x2cd7, 0 } },
+ { 0x2cd8, 1, { 0x2cd9, 0 } },
+ { 0x2cda, 1, { 0x2cdb, 0 } },
+ { 0x2cdc, 1, { 0x2cdd, 0 } },
+ { 0x2cde, 1, { 0x2cdf, 0 } },
+ { 0x2ce0, 1, { 0x2ce1, 0 } },
+ { 0x2ce2, 1, { 0x2ce3, 0 } },
+ { 0x2ceb, 1, { 0x2cec, 0 } },
+ { 0x2ced, 1, { 0x2cee, 0 } },
+ { 0x2cf2, 1, { 0x2cf3, 0 } },
+ { 0x2d6f, 1, { 0x2d61, 0 } },
+ { 0x2e9f, 1, { 0x6bcd, 0 } },
+ { 0x2ef3, 1, { 0x9f9f, 0 } },
+ { 0x2f00, 1, { 0x4e00, 0 } },
+ { 0x2f01, 1, { 0x4e28, 0 } },
+ { 0x2f02, 1, { 0x4e36, 0 } },
+ { 0x2f03, 1, { 0x4e3f, 0 } },
+ { 0x2f04, 1, { 0x4e59, 0 } },
+ { 0x2f05, 1, { 0x4e85, 0 } },
+ { 0x2f06, 1, { 0x4e8c, 0 } },
+ { 0x2f07, 1, { 0x4ea0, 0 } },
+ { 0x2f08, 1, { 0x4eba, 0 } },
+ { 0x2f09, 1, { 0x513f, 0 } },
+ { 0x2f0a, 1, { 0x5165, 0 } },
+ { 0x2f0b, 1, { 0x516b, 0 } },
+ { 0x2f0c, 1, { 0x5182, 0 } },
+ { 0x2f0d, 1, { 0x5196, 0 } },
+ { 0x2f0e, 1, { 0x51ab, 0 } },
+ { 0x2f0f, 1, { 0x51e0, 0 } },
+ { 0x2f10, 1, { 0x51f5, 0 } },
+ { 0x2f11, 1, { 0x5200, 0 } },
+ { 0x2f12, 1, { 0x529b, 0 } },
+ { 0x2f13, 1, { 0x52f9, 0 } },
+ { 0x2f14, 1, { 0x5315, 0 } },
+ { 0x2f15, 1, { 0x531a, 0 } },
+ { 0x2f16, 1, { 0x5338, 0 } },
+ { 0x2f17, 1, { 0x5341, 0 } },
+ { 0x2f18, 1, { 0x535c, 0 } },
+ { 0x2f19, 1, { 0x5369, 0 } },
+ { 0x2f1a, 1, { 0x5382, 0 } },
+ { 0x2f1b, 1, { 0x53b6, 0 } },
+ { 0x2f1c, 1, { 0x53c8, 0 } },
+ { 0x2f1d, 1, { 0x53e3, 0 } },
+ { 0x2f1e, 1, { 0x56d7, 0 } },
+ { 0x2f1f, 1, { 0x571f, 0 } },
+ { 0x2f20, 1, { 0x58eb, 0 } },
+ { 0x2f21, 1, { 0x5902, 0 } },
+ { 0x2f22, 1, { 0x590a, 0 } },
+ { 0x2f23, 1, { 0x5915, 0 } },
+ { 0x2f24, 1, { 0x5927, 0 } },
+ { 0x2f25, 1, { 0x5973, 0 } },
+ { 0x2f26, 1, { 0x5b50, 0 } },
+ { 0x2f27, 1, { 0x5b80, 0 } },
+ { 0x2f28, 1, { 0x5bf8, 0 } },
+ { 0x2f29, 1, { 0x5c0f, 0 } },
+ { 0x2f2a, 1, { 0x5c22, 0 } },
+ { 0x2f2b, 1, { 0x5c38, 0 } },
+ { 0x2f2c, 1, { 0x5c6e, 0 } },
+ { 0x2f2d, 1, { 0x5c71, 0 } },
+ { 0x2f2e, 1, { 0x5ddb, 0 } },
+ { 0x2f2f, 1, { 0x5de5, 0 } },
+ { 0x2f30, 1, { 0x5df1, 0 } },
+ { 0x2f31, 1, { 0x5dfe, 0 } },
+ { 0x2f32, 1, { 0x5e72, 0 } },
+ { 0x2f33, 1, { 0x5e7a, 0 } },
+ { 0x2f34, 1, { 0x5e7f, 0 } },
+ { 0x2f35, 1, { 0x5ef4, 0 } },
+ { 0x2f36, 1, { 0x5efe, 0 } },
+ { 0x2f37, 1, { 0x5f0b, 0 } },
+ { 0x2f38, 1, { 0x5f13, 0 } },
+ { 0x2f39, 1, { 0x5f50, 0 } },
+ { 0x2f3a, 1, { 0x5f61, 0 } },
+ { 0x2f3b, 1, { 0x5f73, 0 } },
+ { 0x2f3c, 1, { 0x5fc3, 0 } },
+ { 0x2f3d, 1, { 0x6208, 0 } },
+ { 0x2f3e, 1, { 0x6236, 0 } },
+ { 0x2f3f, 1, { 0x624b, 0 } },
+ { 0x2f40, 1, { 0x652f, 0 } },
+ { 0x2f41, 1, { 0x6534, 0 } },
+ { 0x2f42, 1, { 0x6587, 0 } },
+ { 0x2f43, 1, { 0x6597, 0 } },
+ { 0x2f44, 1, { 0x65a4, 0 } },
+ { 0x2f45, 1, { 0x65b9, 0 } },
+ { 0x2f46, 1, { 0x65e0, 0 } },
+ { 0x2f47, 1, { 0x65e5, 0 } },
+ { 0x2f48, 1, { 0x66f0, 0 } },
+ { 0x2f49, 1, { 0x6708, 0 } },
+ { 0x2f4a, 1, { 0x6728, 0 } },
+ { 0x2f4b, 1, { 0x6b20, 0 } },
+ { 0x2f4c, 1, { 0x6b62, 0 } },
+ { 0x2f4d, 1, { 0x6b79, 0 } },
+ { 0x2f4e, 1, { 0x6bb3, 0 } },
+ { 0x2f4f, 1, { 0x6bcb, 0 } },
+ { 0x2f50, 1, { 0x6bd4, 0 } },
+ { 0x2f51, 1, { 0x6bdb, 0 } },
+ { 0x2f52, 1, { 0x6c0f, 0 } },
+ { 0x2f53, 1, { 0x6c14, 0 } },
+ { 0x2f54, 1, { 0x6c34, 0 } },
+ { 0x2f55, 1, { 0x706b, 0 } },
+ { 0x2f56, 1, { 0x722a, 0 } },
+ { 0x2f57, 1, { 0x7236, 0 } },
+ { 0x2f58, 1, { 0x723b, 0 } },
+ { 0x2f59, 1, { 0x723f, 0 } },
+ { 0x2f5a, 1, { 0x7247, 0 } },
+ { 0x2f5b, 1, { 0x7259, 0 } },
+ { 0x2f5c, 1, { 0x725b, 0 } },
+ { 0x2f5d, 1, { 0x72ac, 0 } },
+ { 0x2f5e, 1, { 0x7384, 0 } },
+ { 0x2f5f, 1, { 0x7389, 0 } },
+ { 0x2f60, 1, { 0x74dc, 0 } },
+ { 0x2f61, 1, { 0x74e6, 0 } },
+ { 0x2f62, 1, { 0x7518, 0 } },
+ { 0x2f63, 1, { 0x751f, 0 } },
+ { 0x2f64, 1, { 0x7528, 0 } },
+ { 0x2f65, 1, { 0x7530, 0 } },
+ { 0x2f66, 1, { 0x758b, 0 } },
+ { 0x2f67, 1, { 0x7592, 0 } },
+ { 0x2f68, 1, { 0x7676, 0 } },
+ { 0x2f69, 1, { 0x767d, 0 } },
+ { 0x2f6a, 1, { 0x76ae, 0 } },
+ { 0x2f6b, 1, { 0x76bf, 0 } },
+ { 0x2f6c, 1, { 0x76ee, 0 } },
+ { 0x2f6d, 1, { 0x77db, 0 } },
+ { 0x2f6e, 1, { 0x77e2, 0 } },
+ { 0x2f6f, 1, { 0x77f3, 0 } },
+ { 0x2f70, 1, { 0x793a, 0 } },
+ { 0x2f71, 1, { 0x79b8, 0 } },
+ { 0x2f72, 1, { 0x79be, 0 } },
+ { 0x2f73, 1, { 0x7a74, 0 } },
+ { 0x2f74, 1, { 0x7acb, 0 } },
+ { 0x2f75, 1, { 0x7af9, 0 } },
+ { 0x2f76, 1, { 0x7c73, 0 } },
+ { 0x2f77, 1, { 0x7cf8, 0 } },
+ { 0x2f78, 1, { 0x7f36, 0 } },
+ { 0x2f79, 1, { 0x7f51, 0 } },
+ { 0x2f7a, 1, { 0x7f8a, 0 } },
+ { 0x2f7b, 1, { 0x7fbd, 0 } },
+ { 0x2f7c, 1, { 0x8001, 0 } },
+ { 0x2f7d, 1, { 0x800c, 0 } },
+ { 0x2f7e, 1, { 0x8012, 0 } },
+ { 0x2f7f, 1, { 0x8033, 0 } },
+ { 0x2f80, 1, { 0x807f, 0 } },
+ { 0x2f81, 1, { 0x8089, 0 } },
+ { 0x2f82, 1, { 0x81e3, 0 } },
+ { 0x2f83, 1, { 0x81ea, 0 } },
+ { 0x2f84, 1, { 0x81f3, 0 } },
+ { 0x2f85, 1, { 0x81fc, 0 } },
+ { 0x2f86, 1, { 0x820c, 0 } },
+ { 0x2f87, 1, { 0x821b, 0 } },
+ { 0x2f88, 1, { 0x821f, 0 } },
+ { 0x2f89, 1, { 0x826e, 0 } },
+ { 0x2f8a, 1, { 0x8272, 0 } },
+ { 0x2f8b, 1, { 0x8278, 0 } },
+ { 0x2f8c, 1, { 0x864d, 0 } },
+ { 0x2f8d, 1, { 0x866b, 0 } },
+ { 0x2f8e, 1, { 0x8840, 0 } },
+ { 0x2f8f, 1, { 0x884c, 0 } },
+ { 0x2f90, 1, { 0x8863, 0 } },
+ { 0x2f91, 1, { 0x897e, 0 } },
+ { 0x2f92, 1, { 0x898b, 0 } },
+ { 0x2f93, 1, { 0x89d2, 0 } },
+ { 0x2f94, 1, { 0x8a00, 0 } },
+ { 0x2f95, 1, { 0x8c37, 0 } },
+ { 0x2f96, 1, { 0x8c46, 0 } },
+ { 0x2f97, 1, { 0x8c55, 0 } },
+ { 0x2f98, 1, { 0x8c78, 0 } },
+ { 0x2f99, 1, { 0x8c9d, 0 } },
+ { 0x2f9a, 1, { 0x8d64, 0 } },
+ { 0x2f9b, 1, { 0x8d70, 0 } },
+ { 0x2f9c, 1, { 0x8db3, 0 } },
+ { 0x2f9d, 1, { 0x8eab, 0 } },
+ { 0x2f9e, 1, { 0x8eca, 0 } },
+ { 0x2f9f, 1, { 0x8f9b, 0 } },
+ { 0x2fa0, 1, { 0x8fb0, 0 } },
+ { 0x2fa1, 1, { 0x8fb5, 0 } },
+ { 0x2fa2, 1, { 0x9091, 0 } },
+ { 0x2fa3, 1, { 0x9149, 0 } },
+ { 0x2fa4, 1, { 0x91c6, 0 } },
+ { 0x2fa5, 1, { 0x91cc, 0 } },
+ { 0x2fa6, 1, { 0x91d1, 0 } },
+ { 0x2fa7, 1, { 0x9577, 0 } },
+ { 0x2fa8, 1, { 0x9580, 0 } },
+ { 0x2fa9, 1, { 0x961c, 0 } },
+ { 0x2faa, 1, { 0x96b6, 0 } },
+ { 0x2fab, 1, { 0x96b9, 0 } },
+ { 0x2fac, 1, { 0x96e8, 0 } },
+ { 0x2fad, 1, { 0x9751, 0 } },
+ { 0x2fae, 1, { 0x975e, 0 } },
+ { 0x2faf, 1, { 0x9762, 0 } },
+ { 0x2fb0, 1, { 0x9769, 0 } },
+ { 0x2fb1, 1, { 0x97cb, 0 } },
+ { 0x2fb2, 1, { 0x97ed, 0 } },
+ { 0x2fb3, 1, { 0x97f3, 0 } },
+ { 0x2fb4, 1, { 0x9801, 0 } },
+ { 0x2fb5, 1, { 0x98a8, 0 } },
+ { 0x2fb6, 1, { 0x98db, 0 } },
+ { 0x2fb7, 1, { 0x98df, 0 } },
+ { 0x2fb8, 1, { 0x9996, 0 } },
+ { 0x2fb9, 1, { 0x9999, 0 } },
+ { 0x2fba, 1, { 0x99ac, 0 } },
+ { 0x2fbb, 1, { 0x9aa8, 0 } },
+ { 0x2fbc, 1, { 0x9ad8, 0 } },
+ { 0x2fbd, 1, { 0x9adf, 0 } },
+ { 0x2fbe, 1, { 0x9b25, 0 } },
+ { 0x2fbf, 1, { 0x9b2f, 0 } },
+ { 0x2fc0, 1, { 0x9b32, 0 } },
+ { 0x2fc1, 1, { 0x9b3c, 0 } },
+ { 0x2fc2, 1, { 0x9b5a, 0 } },
+ { 0x2fc3, 1, { 0x9ce5, 0 } },
+ { 0x2fc4, 1, { 0x9e75, 0 } },
+ { 0x2fc5, 1, { 0x9e7f, 0 } },
+ { 0x2fc6, 1, { 0x9ea5, 0 } },
+ { 0x2fc7, 1, { 0x9ebb, 0 } },
+ { 0x2fc8, 1, { 0x9ec3, 0 } },
+ { 0x2fc9, 1, { 0x9ecd, 0 } },
+ { 0x2fca, 1, { 0x9ed1, 0 } },
+ { 0x2fcb, 1, { 0x9ef9, 0 } },
+ { 0x2fcc, 1, { 0x9efd, 0 } },
+ { 0x2fcd, 1, { 0x9f0e, 0 } },
+ { 0x2fce, 1, { 0x9f13, 0 } },
+ { 0x2fcf, 1, { 0x9f20, 0 } },
+ { 0x2fd0, 1, { 0x9f3b, 0 } },
+ { 0x2fd1, 1, { 0x9f4a, 0 } },
+ { 0x2fd2, 1, { 0x9f52, 0 } },
+ { 0x2fd3, 1, { 0x9f8d, 0 } },
+ { 0x2fd4, 1, { 0x9f9c, 0 } },
+ { 0x2fd5, 1, { 0x9fa0, 0 } },
+ { 0x3002, 1, { 0x2e, 0 } },
+ { 0x3036, 1, { 0x3012, 0 } },
+ { 0x3038, 1, { 0x5341, 0 } },
+ { 0x3039, 1, { 0x5344, 0 } },
+ { 0x303a, 1, { 0x5345, 0 } },
+ { 0x309f, 2, { 0x3088, 0x308a } },
+ { 0x30ff, 2, { 0x30b3, 0x30c8 } },
+ { 0x3131, 1, { 0x1100, 0 } },
+ { 0x3132, 1, { 0x1101, 0 } },
+ { 0x3133, 1, { 0x11aa, 0 } },
+ { 0x3134, 1, { 0x1102, 0 } },
+ { 0x3135, 1, { 0x11ac, 0 } },
+ { 0x3136, 1, { 0x11ad, 0 } },
+ { 0x3137, 1, { 0x1103, 0 } },
+ { 0x3138, 1, { 0x1104, 0 } },
+ { 0x3139, 1, { 0x1105, 0 } },
+ { 0x313a, 1, { 0x11b0, 0 } },
+ { 0x313b, 1, { 0x11b1, 0 } },
+ { 0x313c, 1, { 0x11b2, 0 } },
+ { 0x313d, 1, { 0x11b3, 0 } },
+ { 0x313e, 1, { 0x11b4, 0 } },
+ { 0x313f, 1, { 0x11b5, 0 } },
+ { 0x3140, 1, { 0x111a, 0 } },
+ { 0x3141, 1, { 0x1106, 0 } },
+ { 0x3142, 1, { 0x1107, 0 } },
+ { 0x3143, 1, { 0x1108, 0 } },
+ { 0x3144, 1, { 0x1121, 0 } },
+ { 0x3145, 1, { 0x1109, 0 } },
+ { 0x3146, 1, { 0x110a, 0 } },
+ { 0x3147, 1, { 0x110b, 0 } },
+ { 0x3148, 1, { 0x110c, 0 } },
+ { 0x3149, 1, { 0x110d, 0 } },
+ { 0x314a, 1, { 0x110e, 0 } },
+ { 0x314b, 1, { 0x110f, 0 } },
+ { 0x314c, 1, { 0x1110, 0 } },
+ { 0x314d, 1, { 0x1111, 0 } },
+ { 0x314e, 1, { 0x1112, 0 } },
+ { 0x314f, 1, { 0x1161, 0 } },
+ { 0x3150, 1, { 0x1162, 0 } },
+ { 0x3151, 1, { 0x1163, 0 } },
+ { 0x3152, 1, { 0x1164, 0 } },
+ { 0x3153, 1, { 0x1165, 0 } },
+ { 0x3154, 1, { 0x1166, 0 } },
+ { 0x3155, 1, { 0x1167, 0 } },
+ { 0x3156, 1, { 0x1168, 0 } },
+ { 0x3157, 1, { 0x1169, 0 } },
+ { 0x3158, 1, { 0x116a, 0 } },
+ { 0x3159, 1, { 0x116b, 0 } },
+ { 0x315a, 1, { 0x116c, 0 } },
+ { 0x315b, 1, { 0x116d, 0 } },
+ { 0x315c, 1, { 0x116e, 0 } },
+ { 0x315d, 1, { 0x116f, 0 } },
+ { 0x315e, 1, { 0x1170, 0 } },
+ { 0x315f, 1, { 0x1171, 0 } },
+ { 0x3160, 1, { 0x1172, 0 } },
+ { 0x3161, 1, { 0x1173, 0 } },
+ { 0x3162, 1, { 0x1174, 0 } },
+ { 0x3163, 1, { 0x1175, 0 } },
+ { 0x3165, 1, { 0x1114, 0 } },
+ { 0x3166, 1, { 0x1115, 0 } },
+ { 0x3167, 1, { 0x11c7, 0 } },
+ { 0x3168, 1, { 0x11c8, 0 } },
+ { 0x3169, 1, { 0x11cc, 0 } },
+ { 0x316a, 1, { 0x11ce, 0 } },
+ { 0x316b, 1, { 0x11d3, 0 } },
+ { 0x316c, 1, { 0x11d7, 0 } },
+ { 0x316d, 1, { 0x11d9, 0 } },
+ { 0x316e, 1, { 0x111c, 0 } },
+ { 0x316f, 1, { 0x11dd, 0 } },
+ { 0x3170, 1, { 0x11df, 0 } },
+ { 0x3171, 1, { 0x111d, 0 } },
+ { 0x3172, 1, { 0x111e, 0 } },
+ { 0x3173, 1, { 0x1120, 0 } },
+ { 0x3174, 1, { 0x1122, 0 } },
+ { 0x3175, 1, { 0x1123, 0 } },
+ { 0x3176, 1, { 0x1127, 0 } },
+ { 0x3177, 1, { 0x1129, 0 } },
+ { 0x3178, 1, { 0x112b, 0 } },
+ { 0x3179, 1, { 0x112c, 0 } },
+ { 0x317a, 1, { 0x112d, 0 } },
+ { 0x317b, 1, { 0x112e, 0 } },
+ { 0x317c, 1, { 0x112f, 0 } },
+ { 0x317d, 1, { 0x1132, 0 } },
+ { 0x317e, 1, { 0x1136, 0 } },
+ { 0x317f, 1, { 0x1140, 0 } },
+ { 0x3180, 1, { 0x1147, 0 } },
+ { 0x3181, 1, { 0x114c, 0 } },
+ { 0x3182, 1, { 0x11f1, 0 } },
+ { 0x3183, 1, { 0x11f2, 0 } },
+ { 0x3184, 1, { 0x1157, 0 } },
+ { 0x3185, 1, { 0x1158, 0 } },
+ { 0x3186, 1, { 0x1159, 0 } },
+ { 0x3187, 1, { 0x1184, 0 } },
+ { 0x3188, 1, { 0x1185, 0 } },
+ { 0x3189, 1, { 0x1188, 0 } },
+ { 0x318a, 1, { 0x1191, 0 } },
+ { 0x318b, 1, { 0x1192, 0 } },
+ { 0x318c, 1, { 0x1194, 0 } },
+ { 0x318d, 1, { 0x119e, 0 } },
+ { 0x318e, 1, { 0x11a1, 0 } },
+ { 0x3192, 1, { 0x4e00, 0 } },
+ { 0x3193, 1, { 0x4e8c, 0 } },
+ { 0x3194, 1, { 0x4e09, 0 } },
+ { 0x3195, 1, { 0x56db, 0 } },
+ { 0x3196, 1, { 0x4e0a, 0 } },
+ { 0x3197, 1, { 0x4e2d, 0 } },
+ { 0x3198, 1, { 0x4e0b, 0 } },
+ { 0x3199, 1, { 0x7532, 0 } },
+ { 0x319a, 1, { 0x4e59, 0 } },
+ { 0x319b, 1, { 0x4e19, 0 } },
+ { 0x319c, 1, { 0x4e01, 0 } },
+ { 0x319d, 1, { 0x5929, 0 } },
+ { 0x319e, 1, { 0x5730, 0 } },
+ { 0x319f, 1, { 0x4eba, 0 } },
+ { 0x3244, 1, { 0x554f, 0 } },
+ { 0x3245, 1, { 0x5e7c, 0 } },
+ { 0x3246, 1, { 0x6587, 0 } },
+ { 0x3247, 1, { 0x7b8f, 0 } },
+ { 0x3250, 3, { 95, 0 } },
+ { 0x3251, 2, { 0x32, 0x31 } },
+ { 0x3252, 2, { 0x32, 0x32 } },
+ { 0x3253, 2, { 0x32, 0x33 } },
+ { 0x3254, 2, { 0x32, 0x34 } },
+ { 0x3255, 2, { 0x32, 0x35 } },
+ { 0x3256, 2, { 0x32, 0x36 } },
+ { 0x3257, 2, { 0x32, 0x37 } },
+ { 0x3258, 2, { 0x32, 0x38 } },
+ { 0x3259, 2, { 0x32, 0x39 } },
+ { 0x325a, 2, { 0x33, 0x30 } },
+ { 0x325b, 2, { 0x33, 0x31 } },
+ { 0x325c, 2, { 0x33, 0x32 } },
+ { 0x325d, 2, { 0x33, 0x33 } },
+ { 0x325e, 2, { 0x33, 0x34 } },
+ { 0x325f, 2, { 0x33, 0x35 } },
+ { 0x3260, 1, { 0x1100, 0 } },
+ { 0x3261, 1, { 0x1102, 0 } },
+ { 0x3262, 1, { 0x1103, 0 } },
+ { 0x3263, 1, { 0x1105, 0 } },
+ { 0x3264, 1, { 0x1106, 0 } },
+ { 0x3265, 1, { 0x1107, 0 } },
+ { 0x3266, 1, { 0x1109, 0 } },
+ { 0x3267, 1, { 0x110b, 0 } },
+ { 0x3268, 1, { 0x110c, 0 } },
+ { 0x3269, 1, { 0x110e, 0 } },
+ { 0x326a, 1, { 0x110f, 0 } },
+ { 0x326b, 1, { 0x1110, 0 } },
+ { 0x326c, 1, { 0x1111, 0 } },
+ { 0x326d, 1, { 0x1112, 0 } },
+ { 0x326e, 1, { 0xac00, 0 } },
+ { 0x326f, 1, { 0xb098, 0 } },
+ { 0x3270, 1, { 0xb2e4, 0 } },
+ { 0x3271, 1, { 0xb77c, 0 } },
+ { 0x3272, 1, { 0xb9c8, 0 } },
+ { 0x3273, 1, { 0xbc14, 0 } },
+ { 0x3274, 1, { 0xc0ac, 0 } },
+ { 0x3275, 1, { 0xc544, 0 } },
+ { 0x3276, 1, { 0xc790, 0 } },
+ { 0x3277, 1, { 0xcc28, 0 } },
+ { 0x3278, 1, { 0xce74, 0 } },
+ { 0x3279, 1, { 0xd0c0, 0 } },
+ { 0x327a, 1, { 0xd30c, 0 } },
+ { 0x327b, 1, { 0xd558, 0 } },
+ { 0x327c, 2, { 0xcc38, 0xace0 } },
+ { 0x327d, 2, { 0xc8fc, 0xc758 } },
+ { 0x327e, 1, { 0xc6b0, 0 } },
+ { 0x3280, 1, { 0x4e00, 0 } },
+ { 0x3281, 1, { 0x4e8c, 0 } },
+ { 0x3282, 1, { 0x4e09, 0 } },
+ { 0x3283, 1, { 0x56db, 0 } },
+ { 0x3284, 1, { 0x4e94, 0 } },
+ { 0x3285, 1, { 0x516d, 0 } },
+ { 0x3286, 1, { 0x4e03, 0 } },
+ { 0x3287, 1, { 0x516b, 0 } },
+ { 0x3288, 1, { 0x4e5d, 0 } },
+ { 0x3289, 1, { 0x5341, 0 } },
+ { 0x328a, 1, { 0x6708, 0 } },
+ { 0x328b, 1, { 0x706b, 0 } },
+ { 0x328c, 1, { 0x6c34, 0 } },
+ { 0x328d, 1, { 0x6728, 0 } },
+ { 0x328e, 1, { 0x91d1, 0 } },
+ { 0x328f, 1, { 0x571f, 0 } },
+ { 0x3290, 1, { 0x65e5, 0 } },
+ { 0x3291, 1, { 0x682a, 0 } },
+ { 0x3292, 1, { 0x6709, 0 } },
+ { 0x3293, 1, { 0x793e, 0 } },
+ { 0x3294, 1, { 0x540d, 0 } },
+ { 0x3295, 1, { 0x7279, 0 } },
+ { 0x3296, 1, { 0x8ca1, 0 } },
+ { 0x3297, 1, { 0x795d, 0 } },
+ { 0x3298, 1, { 0x52b4, 0 } },
+ { 0x3299, 1, { 0x79d8, 0 } },
+ { 0x329a, 1, { 0x7537, 0 } },
+ { 0x329b, 1, { 0x5973, 0 } },
+ { 0x329c, 1, { 0x9069, 0 } },
+ { 0x329d, 1, { 0x512a, 0 } },
+ { 0x329e, 1, { 0x5370, 0 } },
+ { 0x329f, 1, { 0x6ce8, 0 } },
+ { 0x32a0, 1, { 0x9805, 0 } },
+ { 0x32a1, 1, { 0x4f11, 0 } },
+ { 0x32a2, 1, { 0x5199, 0 } },
+ { 0x32a3, 1, { 0x6b63, 0 } },
+ { 0x32a4, 1, { 0x4e0a, 0 } },
+ { 0x32a5, 1, { 0x4e2d, 0 } },
+ { 0x32a6, 1, { 0x4e0b, 0 } },
+ { 0x32a7, 1, { 0x5de6, 0 } },
+ { 0x32a8, 1, { 0x53f3, 0 } },
+ { 0x32a9, 1, { 0x533b, 0 } },
+ { 0x32aa, 1, { 0x5b97, 0 } },
+ { 0x32ab, 1, { 0x5b66, 0 } },
+ { 0x32ac, 1, { 0x76e3, 0 } },
+ { 0x32ad, 1, { 0x4f01, 0 } },
+ { 0x32ae, 1, { 0x8cc7, 0 } },
+ { 0x32af, 1, { 0x5354, 0 } },
+ { 0x32b0, 1, { 0x591c, 0 } },
+ { 0x32b1, 2, { 0x33, 0x36 } },
+ { 0x32b2, 2, { 0x33, 0x37 } },
+ { 0x32b3, 2, { 0x33, 0x38 } },
+ { 0x32b4, 2, { 0x33, 0x39 } },
+ { 0x32b5, 2, { 0x34, 0x30 } },
+ { 0x32b6, 2, { 0x34, 0x31 } },
+ { 0x32b7, 2, { 0x34, 0x32 } },
+ { 0x32b8, 2, { 0x34, 0x33 } },
+ { 0x32b9, 2, { 0x34, 0x34 } },
+ { 0x32ba, 2, { 0x34, 0x35 } },
+ { 0x32bb, 2, { 0x34, 0x36 } },
+ { 0x32bc, 2, { 0x34, 0x37 } },
+ { 0x32bd, 2, { 0x34, 0x38 } },
+ { 0x32be, 2, { 0x34, 0x39 } },
+ { 0x32bf, 2, { 0x35, 0x30 } },
+ { 0x32c0, 2, { 0x31, 0x6708 } },
+ { 0x32c1, 2, { 0x32, 0x6708 } },
+ { 0x32c2, 2, { 0x33, 0x6708 } },
+ { 0x32c3, 2, { 0x34, 0x6708 } },
+ { 0x32c4, 2, { 0x35, 0x6708 } },
+ { 0x32c5, 2, { 0x36, 0x6708 } },
+ { 0x32c6, 2, { 0x37, 0x6708 } },
+ { 0x32c7, 2, { 0x38, 0x6708 } },
+ { 0x32c8, 2, { 0x39, 0x6708 } },
+ { 0x32c9, 3, { 895, 0 } },
+ { 0x32ca, 3, { 3, 0 } },
+ { 0x32cb, 3, { 12, 0 } },
+ { 0x32cc, 2, { 0x68, 0x67 } },
+ { 0x32cd, 3, { 87, 0 } },
+ { 0x32ce, 2, { 0x65, 0x76 } },
+ { 0x32cf, 3, { 466, 0 } },
+ { 0x32d0, 1, { 0x30a2, 0 } },
+ { 0x32d1, 1, { 0x30a4, 0 } },
+ { 0x32d2, 1, { 0x30a6, 0 } },
+ { 0x32d3, 1, { 0x30a8, 0 } },
+ { 0x32d4, 1, { 0x30aa, 0 } },
+ { 0x32d5, 1, { 0x30ab, 0 } },
+ { 0x32d6, 1, { 0x30ad, 0 } },
+ { 0x32d7, 1, { 0x30af, 0 } },
+ { 0x32d8, 1, { 0x30b1, 0 } },
+ { 0x32d9, 1, { 0x30b3, 0 } },
+ { 0x32da, 1, { 0x30b5, 0 } },
+ { 0x32db, 1, { 0x30b7, 0 } },
+ { 0x32dc, 1, { 0x30b9, 0 } },
+ { 0x32dd, 1, { 0x30bb, 0 } },
+ { 0x32de, 1, { 0x30bd, 0 } },
+ { 0x32df, 1, { 0x30bf, 0 } },
+ { 0x32e0, 1, { 0x30c1, 0 } },
+ { 0x32e1, 1, { 0x30c4, 0 } },
+ { 0x32e2, 1, { 0x30c6, 0 } },
+ { 0x32e3, 1, { 0x30c8, 0 } },
+ { 0x32e4, 1, { 0x30ca, 0 } },
+ { 0x32e5, 1, { 0x30cb, 0 } },
+ { 0x32e6, 1, { 0x30cc, 0 } },
+ { 0x32e7, 1, { 0x30cd, 0 } },
+ { 0x32e8, 1, { 0x30ce, 0 } },
+ { 0x32e9, 1, { 0x30cf, 0 } },
+ { 0x32ea, 1, { 0x30d2, 0 } },
+ { 0x32eb, 1, { 0x30d5, 0 } },
+ { 0x32ec, 1, { 0x30d8, 0 } },
+ { 0x32ed, 1, { 0x30db, 0 } },
+ { 0x32ee, 1, { 0x30de, 0 } },
+ { 0x32ef, 1, { 0x30df, 0 } },
+ { 0x32f0, 1, { 0x30e0, 0 } },
+ { 0x32f1, 1, { 0x30e1, 0 } },
+ { 0x32f2, 1, { 0x30e2, 0 } },
+ { 0x32f3, 1, { 0x30e4, 0 } },
+ { 0x32f4, 1, { 0x30e6, 0 } },
+ { 0x32f5, 1, { 0x30e8, 0 } },
+ { 0x32f6, 1, { 0x30e9, 0 } },
+ { 0x32f7, 1, { 0x30ea, 0 } },
+ { 0x32f8, 1, { 0x30eb, 0 } },
+ { 0x32f9, 1, { 0x30ec, 0 } },
+ { 0x32fa, 1, { 0x30ed, 0 } },
+ { 0x32fb, 1, { 0x30ef, 0 } },
+ { 0x32fc, 1, { 0x30f0, 0 } },
+ { 0x32fd, 1, { 0x30f1, 0 } },
+ { 0x32fe, 1, { 0x30f2, 0 } },
+ { 0x32ff, 2, { 0x4ee4, 0x548c } },
+ { 0x3300, 4, { 836, 0 } },
+ { 0x3301, 4, { 299, 0 } },
+ { 0x3302, 4, { 296, 0 } },
+ { 0x3303, 3, { 767, 0 } },
+ { 0x3304, 4, { 791, 0 } },
+ { 0x3305, 3, { 140, 0 } },
+ { 0x3306, 3, { 442, 0 } },
+ { 0x3307, 5, { 260, 0 } },
+ { 0x3308, 4, { 832, 0 } },
+ { 0x3309, 3, { 861, 0 } },
+ { 0x330a, 3, { 613, 0 } },
+ { 0x330b, 3, { 816, 0 } },
+ { 0x330c, 4, { 787, 0 } },
+ { 0x330d, 4, { 828, 0 } },
+ { 0x330e, 3, { 770, 0 } },
+ { 0x330f, 3, { 143, 0 } },
+ { 0x3310, 2, { 0x30ae, 0x30ac } },
+ { 0x3311, 3, { 445, 0 } },
+ { 0x3312, 4, { 783, 0 } },
+ { 0x3313, 4, { 281, 0 } },
+ { 0x3314, 2, { 0x30ad, 0x30ed } },
+ { 0x3315, 5, { 233, 0 } },
+ { 0x3316, 6, { 209, 0 } },
+ { 0x3317, 5, { 255, 0 } },
+ { 0x3318, 3, { 235, 0 } },
+ { 0x3319, 5, { 235, 0 } },
+ { 0x331a, 5, { 228, 0 } },
+ { 0x331b, 4, { 824, 0 } },
+ { 0x331c, 3, { 864, 0 } },
+ { 0x331d, 3, { 616, 0 } },
+ { 0x331e, 3, { 773, 0 } },
+ { 0x331f, 4, { 226, 0 } },
+ { 0x3320, 5, { 250, 0 } },
+ { 0x3321, 4, { 779, 0 } },
+ { 0x3322, 3, { 448, 0 } },
+ { 0x3323, 3, { 247, 0 } },
+ { 0x3324, 3, { 283, 0 } },
+ { 0x3325, 2, { 0x30c7, 0x30b7 } },
+ { 0x3326, 2, { 0x30c9, 0x30eb } },
+ { 0x3327, 2, { 0x30c8, 0x30f3 } },
+ { 0x3328, 2, { 0x30ca, 0x30ce } },
+ { 0x3329, 3, { 867, 0 } },
+ { 0x332a, 3, { 878, 0 } },
+ { 0x332b, 5, { 245, 0 } },
+ { 0x332c, 3, { 619, 0 } },
+ { 0x332d, 4, { 222, 0 } },
+ { 0x332e, 5, { 240, 0 } },
+ { 0x332f, 3, { 451, 0 } },
+ { 0x3330, 2, { 0x30d4, 0x30b3 } },
+ { 0x3331, 2, { 0x30d3, 0x30eb } },
+ { 0x3332, 5, { 301, 0 } },
+ { 0x3333, 4, { 277, 0 } },
+ { 0x3334, 5, { 306, 0 } },
+ { 0x3335, 3, { 286, 0 } },
+ { 0x3336, 5, { 311, 0 } },
+ { 0x3337, 2, { 0x30da, 0x30bd } },
+ { 0x3338, 3, { 622, 0 } },
+ { 0x3339, 3, { 870, 0 } },
+ { 0x333a, 3, { 454, 0 } },
+ { 0x333b, 3, { 289, 0 } },
+ { 0x333c, 3, { 881, 0 } },
+ { 0x333d, 4, { 775, 0 } },
+ { 0x333e, 3, { 625, 0 } },
+ { 0x333f, 2, { 0x30db, 0x30f3 } },
+ { 0x3340, 3, { 457, 0 } },
+ { 0x3341, 3, { 873, 0 } },
+ { 0x3342, 3, { 884, 0 } },
+ { 0x3343, 4, { 822, 0 } },
+ { 0x3344, 3, { 292, 0 } },
+ { 0x3345, 3, { 876, 0 } },
+ { 0x3346, 3, { 887, 0 } },
+ { 0x3347, 5, { 145, 0 } },
+ { 0x3348, 4, { 218, 0 } },
+ { 0x3349, 2, { 0x30df, 0x30ea } },
+ { 0x334a, 5, { 316, 0 } },
+ { 0x334b, 2, { 0x30e1, 0x30ac } },
+ { 0x334c, 4, { 273, 0 } },
+ { 0x334d, 4, { 211, 0 } },
+ { 0x334e, 3, { 628, 0 } },
+ { 0x334f, 3, { 460, 0 } },
+ { 0x3350, 3, { 295, 0 } },
+ { 0x3351, 4, { 818, 0 } },
+ { 0x3352, 2, { 0x30ea, 0x30e9 } },
+ { 0x3353, 3, { 320, 0 } },
+ { 0x3354, 4, { 214, 0 } },
+ { 0x3355, 2, { 0x30ec, 0x30e0 } },
+ { 0x3356, 5, { 150, 0 } },
+ { 0x3357, 3, { 257, 0 } },
+ { 0x3358, 2, { 0x30, 0x70b9 } },
+ { 0x3359, 2, { 0x31, 0x70b9 } },
+ { 0x335a, 2, { 0x32, 0x70b9 } },
+ { 0x335b, 2, { 0x33, 0x70b9 } },
+ { 0x335c, 2, { 0x34, 0x70b9 } },
+ { 0x335d, 2, { 0x35, 0x70b9 } },
+ { 0x335e, 2, { 0x36, 0x70b9 } },
+ { 0x335f, 2, { 0x37, 0x70b9 } },
+ { 0x3360, 2, { 0x38, 0x70b9 } },
+ { 0x3361, 2, { 0x39, 0x70b9 } },
+ { 0x3362, 3, { 892, 0 } },
+ { 0x3363, 3, { 6, 0 } },
+ { 0x3364, 3, { 15, 0 } },
+ { 0x3365, 3, { 21, 0 } },
+ { 0x3366, 3, { 27, 0 } },
+ { 0x3367, 3, { 33, 0 } },
+ { 0x3368, 3, { 39, 0 } },
+ { 0x3369, 3, { 45, 0 } },
+ { 0x336a, 3, { 51, 0 } },
+ { 0x336b, 3, { 57, 0 } },
+ { 0x336c, 3, { 676, 0 } },
+ { 0x336d, 3, { 670, 0 } },
+ { 0x336e, 3, { 664, 0 } },
+ { 0x336f, 3, { 658, 0 } },
+ { 0x3370, 3, { 652, 0 } },
+ { 0x3371, 3, { 713, 0 } },
+ { 0x3372, 2, { 0x64, 0x61 } },
+ { 0x3373, 2, { 0x61, 0x75 } },
+ { 0x3374, 3, { 77, 0 } },
+ { 0x3375, 2, { 0x6f, 0x76 } },
+ { 0x3376, 2, { 0x70, 0x63 } },
+ { 0x3377, 2, { 0x64, 0x6d } },
+ { 0x3378, 3, { 642, 0 } },
+ { 0x3379, 3, { 468, 0 } },
+ { 0x337a, 2, { 0x69, 0x75 } },
+ { 0x337b, 2, { 0x5e73, 0x6210 } },
+ { 0x337c, 2, { 0x662d, 0x548c } },
+ { 0x337d, 2, { 0x5927, 0x6b63 } },
+ { 0x337e, 2, { 0x660e, 0x6cbb } },
+ { 0x337f, 4, { 269, 0 } },
+ { 0x3380, 2, { 0x70, 0x61 } },
+ { 0x3381, 2, { 0x6e, 0x61 } },
+ { 0x3382, 2, { 0x3bc, 0x61 } },
+ { 0x3383, 2, { 0x6d, 0x61 } },
+ { 0x3384, 2, { 0x6b, 0x61 } },
+ { 0x3385, 2, { 0x6b, 0x62 } },
+ { 0x3386, 2, { 0x6d, 0x62 } },
+ { 0x3387, 2, { 0x67, 0x62 } },
+ { 0x3388, 3, { 464, 0 } },
+ { 0x3389, 4, { 463, 0 } },
+ { 0x338a, 2, { 0x70, 0x66 } },
+ { 0x338b, 2, { 0x6e, 0x66 } },
+ { 0x338c, 2, { 0x3bc, 0x66 } },
+ { 0x338d, 2, { 0x3bc, 0x67 } },
+ { 0x338e, 2, { 0x6d, 0x67 } },
+ { 0x338f, 2, { 0x6b, 0x67 } },
+ { 0x3390, 2, { 0x68, 0x7a } },
+ { 0x3391, 3, { 477, 0 } },
+ { 0x3392, 3, { 92, 0 } },
+ { 0x3393, 3, { 100, 0 } },
+ { 0x3394, 3, { 106, 0 } },
+ { 0x3395, 2, { 0x3bc, 0x6c } },
+ { 0x3396, 2, { 0x6d, 0x6c } },
+ { 0x3397, 2, { 0x64, 0x6c } },
+ { 0x3398, 2, { 0x6b, 0x6c } },
+ { 0x3399, 2, { 0x66, 0x6d } },
+ { 0x339a, 2, { 0x6e, 0x6d } },
+ { 0x339b, 2, { 0x3bc, 0x6d } },
+ { 0x339c, 2, { 0x6d, 0x6d } },
+ { 0x339d, 2, { 0x63, 0x6d } },
+ { 0x339e, 2, { 0x6b, 0x6d } },
+ { 0x339f, 3, { 637, 0 } },
+ { 0x33a0, 3, { 647, 0 } },
+ { 0x33a1, 2, { 0x6d, 0x32 } },
+ { 0x33a2, 3, { 693, 0 } },
+ { 0x33a3, 3, { 716, 0 } },
+ { 0x33a4, 3, { 698, 0 } },
+ { 0x33a5, 2, { 0x6d, 0x33 } },
+ { 0x33a6, 3, { 706, 0 } },
+ { 0x33a7, 3, { 491, 0 } },
+ { 0x33a8, 4, { 491, 0 } },
+ { 0x33a9, 2, { 0x70, 0x61 } },
+ { 0x33aa, 3, { 724, 0 } },
+ { 0x33ab, 3, { 482, 0 } },
+ { 0x33ac, 3, { 634, 0 } },
+ { 0x33ad, 3, { 79, 0 } },
+ { 0x33ae, 5, { 79, 0 } },
+ { 0x33af, 6, { 79, 0 } },
+ { 0x33b0, 2, { 0x70, 0x73 } },
+ { 0x33b1, 2, { 0x6e, 0x73 } },
+ { 0x33b2, 2, { 0x3bc, 0x73 } },
+ { 0x33b3, 2, { 0x6d, 0x73 } },
+ { 0x33b4, 2, { 0x70, 0x76 } },
+ { 0x33b5, 2, { 0x6e, 0x76 } },
+ { 0x33b6, 2, { 0x3bc, 0x76 } },
+ { 0x33b7, 2, { 0x6d, 0x76 } },
+ { 0x33b8, 2, { 0x6b, 0x76 } },
+ { 0x33b9, 2, { 0x6d, 0x76 } },
+ { 0x33ba, 2, { 0x70, 0x77 } },
+ { 0x33bb, 2, { 0x6e, 0x77 } },
+ { 0x33bc, 2, { 0x3bc, 0x77 } },
+ { 0x33bd, 2, { 0x6d, 0x77 } },
+ { 0x33be, 2, { 0x6b, 0x77 } },
+ { 0x33bf, 2, { 0x6d, 0x77 } },
+ { 0x33c0, 2, { 0x6b, 0x3c9 } },
+ { 0x33c1, 2, { 0x6d, 0x3c9 } },
+ { 0x33c3, 2, { 0x62, 0x71 } },
+ { 0x33c4, 2, { 0x63, 0x63 } },
+ { 0x33c5, 2, { 0x63, 0x64 } },
+ { 0x33c6, 4, { 631, 0 } },
+ { 0x33c8, 2, { 0x64, 0x62 } },
+ { 0x33c9, 2, { 0x67, 0x79 } },
+ { 0x33ca, 2, { 0x68, 0x61 } },
+ { 0x33cb, 2, { 0x68, 0x70 } },
+ { 0x33cc, 2, { 0x69, 0x6e } },
+ { 0x33cd, 2, { 0x6b, 0x6b } },
+ { 0x33ce, 2, { 0x6b, 0x6d } },
+ { 0x33cf, 2, { 0x6b, 0x74 } },
+ { 0x33d0, 2, { 0x6c, 0x6d } },
+ { 0x33d1, 2, { 0x6c, 0x6e } },
+ { 0x33d2, 3, { 98, 0 } },
+ { 0x33d3, 2, { 0x6c, 0x78 } },
+ { 0x33d4, 2, { 0x6d, 0x62 } },
+ { 0x33d5, 3, { 103, 0 } },
+ { 0x33d6, 3, { 486, 0 } },
+ { 0x33d7, 2, { 0x70, 0x68 } },
+ { 0x33d9, 3, { 480, 0 } },
+ { 0x33da, 2, { 0x70, 0x72 } },
+ { 0x33db, 2, { 0x73, 0x72 } },
+ { 0x33dc, 2, { 0x73, 0x76 } },
+ { 0x33dd, 2, { 0x77, 0x62 } },
+ { 0x33de, 3, { 489, 0 } },
+ { 0x33df, 3, { 484, 0 } },
+ { 0x33e0, 2, { 0x31, 0x65e5 } },
+ { 0x33e1, 2, { 0x32, 0x65e5 } },
+ { 0x33e2, 2, { 0x33, 0x65e5 } },
+ { 0x33e3, 2, { 0x34, 0x65e5 } },
+ { 0x33e4, 2, { 0x35, 0x65e5 } },
+ { 0x33e5, 2, { 0x36, 0x65e5 } },
+ { 0x33e6, 2, { 0x37, 0x65e5 } },
+ { 0x33e7, 2, { 0x38, 0x65e5 } },
+ { 0x33e8, 2, { 0x39, 0x65e5 } },
+ { 0x33e9, 3, { 898, 0 } },
+ { 0x33ea, 3, { 0, 0 } },
+ { 0x33eb, 3, { 9, 0 } },
+ { 0x33ec, 3, { 18, 0 } },
+ { 0x33ed, 3, { 24, 0 } },
+ { 0x33ee, 3, { 30, 0 } },
+ { 0x33ef, 3, { 36, 0 } },
+ { 0x33f0, 3, { 42, 0 } },
+ { 0x33f1, 3, { 48, 0 } },
+ { 0x33f2, 3, { 54, 0 } },
+ { 0x33f3, 3, { 679, 0 } },
+ { 0x33f4, 3, { 673, 0 } },
+ { 0x33f5, 3, { 667, 0 } },
+ { 0x33f6, 3, { 661, 0 } },
+ { 0x33f7, 3, { 655, 0 } },
+ { 0x33f8, 3, { 74, 0 } },
+ { 0x33f9, 3, { 649, 0 } },
+ { 0x33fa, 3, { 644, 0 } },
+ { 0x33fb, 3, { 695, 0 } },
+ { 0x33fc, 3, { 639, 0 } },
+ { 0x33fd, 3, { 496, 0 } },
+ { 0x33fe, 3, { 700, 0 } },
+ { 0x33ff, 3, { 89, 0 } },
+ { 0xa640, 1, { 0xa641, 0 } },
+ { 0xa642, 1, { 0xa643, 0 } },
+ { 0xa644, 1, { 0xa645, 0 } },
+ { 0xa646, 1, { 0xa647, 0 } },
+ { 0xa648, 1, { 0xa649, 0 } },
+ { 0xa64a, 1, { 0xa64b, 0 } },
+ { 0xa64c, 1, { 0xa64d, 0 } },
+ { 0xa64e, 1, { 0xa64f, 0 } },
+ { 0xa650, 1, { 0xa651, 0 } },
+ { 0xa652, 1, { 0xa653, 0 } },
+ { 0xa654, 1, { 0xa655, 0 } },
+ { 0xa656, 1, { 0xa657, 0 } },
+ { 0xa658, 1, { 0xa659, 0 } },
+ { 0xa65a, 1, { 0xa65b, 0 } },
+ { 0xa65c, 1, { 0xa65d, 0 } },
+ { 0xa65e, 1, { 0xa65f, 0 } },
+ { 0xa660, 1, { 0xa661, 0 } },
+ { 0xa662, 1, { 0xa663, 0 } },
+ { 0xa664, 1, { 0xa665, 0 } },
+ { 0xa666, 1, { 0xa667, 0 } },
+ { 0xa668, 1, { 0xa669, 0 } },
+ { 0xa66a, 1, { 0xa66b, 0 } },
+ { 0xa66c, 1, { 0xa66d, 0 } },
+ { 0xa680, 1, { 0xa681, 0 } },
+ { 0xa682, 1, { 0xa683, 0 } },
+ { 0xa684, 1, { 0xa685, 0 } },
+ { 0xa686, 1, { 0xa687, 0 } },
+ { 0xa688, 1, { 0xa689, 0 } },
+ { 0xa68a, 1, { 0xa68b, 0 } },
+ { 0xa68c, 1, { 0xa68d, 0 } },
+ { 0xa68e, 1, { 0xa68f, 0 } },
+ { 0xa690, 1, { 0xa691, 0 } },
+ { 0xa692, 1, { 0xa693, 0 } },
+ { 0xa694, 1, { 0xa695, 0 } },
+ { 0xa696, 1, { 0xa697, 0 } },
+ { 0xa698, 1, { 0xa699, 0 } },
+ { 0xa69a, 1, { 0xa69b, 0 } },
+ { 0xa69c, 1, { 0x44a, 0 } },
+ { 0xa69d, 1, { 0x44c, 0 } },
+ { 0xa722, 1, { 0xa723, 0 } },
+ { 0xa724, 1, { 0xa725, 0 } },
+ { 0xa726, 1, { 0xa727, 0 } },
+ { 0xa728, 1, { 0xa729, 0 } },
+ { 0xa72a, 1, { 0xa72b, 0 } },
+ { 0xa72c, 1, { 0xa72d, 0 } },
+ { 0xa72e, 1, { 0xa72f, 0 } },
+ { 0xa732, 1, { 0xa733, 0 } },
+ { 0xa734, 1, { 0xa735, 0 } },
+ { 0xa736, 1, { 0xa737, 0 } },
+ { 0xa738, 1, { 0xa739, 0 } },
+ { 0xa73a, 1, { 0xa73b, 0 } },
+ { 0xa73c, 1, { 0xa73d, 0 } },
+ { 0xa73e, 1, { 0xa73f, 0 } },
+ { 0xa740, 1, { 0xa741, 0 } },
+ { 0xa742, 1, { 0xa743, 0 } },
+ { 0xa744, 1, { 0xa745, 0 } },
+ { 0xa746, 1, { 0xa747, 0 } },
+ { 0xa748, 1, { 0xa749, 0 } },
+ { 0xa74a, 1, { 0xa74b, 0 } },
+ { 0xa74c, 1, { 0xa74d, 0 } },
+ { 0xa74e, 1, { 0xa74f, 0 } },
+ { 0xa750, 1, { 0xa751, 0 } },
+ { 0xa752, 1, { 0xa753, 0 } },
+ { 0xa754, 1, { 0xa755, 0 } },
+ { 0xa756, 1, { 0xa757, 0 } },
+ { 0xa758, 1, { 0xa759, 0 } },
+ { 0xa75a, 1, { 0xa75b, 0 } },
+ { 0xa75c, 1, { 0xa75d, 0 } },
+ { 0xa75e, 1, { 0xa75f, 0 } },
+ { 0xa760, 1, { 0xa761, 0 } },
+ { 0xa762, 1, { 0xa763, 0 } },
+ { 0xa764, 1, { 0xa765, 0 } },
+ { 0xa766, 1, { 0xa767, 0 } },
+ { 0xa768, 1, { 0xa769, 0 } },
+ { 0xa76a, 1, { 0xa76b, 0 } },
+ { 0xa76c, 1, { 0xa76d, 0 } },
+ { 0xa76e, 1, { 0xa76f, 0 } },
+ { 0xa770, 1, { 0xa76f, 0 } },
+ { 0xa779, 1, { 0xa77a, 0 } },
+ { 0xa77b, 1, { 0xa77c, 0 } },
+ { 0xa77d, 1, { 0x1d79, 0 } },
+ { 0xa77e, 1, { 0xa77f, 0 } },
+ { 0xa780, 1, { 0xa781, 0 } },
+ { 0xa782, 1, { 0xa783, 0 } },
+ { 0xa784, 1, { 0xa785, 0 } },
+ { 0xa786, 1, { 0xa787, 0 } },
+ { 0xa78b, 1, { 0xa78c, 0 } },
+ { 0xa78d, 1, { 0x265, 0 } },
+ { 0xa790, 1, { 0xa791, 0 } },
+ { 0xa792, 1, { 0xa793, 0 } },
+ { 0xa796, 1, { 0xa797, 0 } },
+ { 0xa798, 1, { 0xa799, 0 } },
+ { 0xa79a, 1, { 0xa79b, 0 } },
+ { 0xa79c, 1, { 0xa79d, 0 } },
+ { 0xa79e, 1, { 0xa79f, 0 } },
+ { 0xa7a0, 1, { 0xa7a1, 0 } },
+ { 0xa7a2, 1, { 0xa7a3, 0 } },
+ { 0xa7a4, 1, { 0xa7a5, 0 } },
+ { 0xa7a6, 1, { 0xa7a7, 0 } },
+ { 0xa7a8, 1, { 0xa7a9, 0 } },
+ { 0xa7aa, 1, { 0x266, 0 } },
+ { 0xa7ab, 1, { 0x25c, 0 } },
+ { 0xa7ac, 1, { 0x261, 0 } },
+ { 0xa7ad, 1, { 0x26c, 0 } },
+ { 0xa7ae, 1, { 0x26a, 0 } },
+ { 0xa7b0, 1, { 0x29e, 0 } },
+ { 0xa7b1, 1, { 0x287, 0 } },
+ { 0xa7b2, 1, { 0x29d, 0 } },
+ { 0xa7b3, 1, { 0xab53, 0 } },
+ { 0xa7b4, 1, { 0xa7b5, 0 } },
+ { 0xa7b6, 1, { 0xa7b7, 0 } },
+ { 0xa7b8, 1, { 0xa7b9, 0 } },
+ { 0xa7ba, 1, { 0xa7bb, 0 } },
+ { 0xa7bc, 1, { 0xa7bd, 0 } },
+ { 0xa7be, 1, { 0xa7bf, 0 } },
+ { 0xa7c0, 1, { 0xa7c1, 0 } },
+ { 0xa7c2, 1, { 0xa7c3, 0 } },
+ { 0xa7c4, 1, { 0xa794, 0 } },
+ { 0xa7c5, 1, { 0x282, 0 } },
+ { 0xa7c6, 1, { 0x1d8e, 0 } },
+ { 0xa7c7, 1, { 0xa7c8, 0 } },
+ { 0xa7c9, 1, { 0xa7ca, 0 } },
+ { 0xa7d0, 1, { 0xa7d1, 0 } },
+ { 0xa7d6, 1, { 0xa7d7, 0 } },
+ { 0xa7d8, 1, { 0xa7d9, 0 } },
+ { 0xa7f2, 1, { 0x63, 0 } },
+ { 0xa7f3, 1, { 0x66, 0 } },
+ { 0xa7f4, 1, { 0x71, 0 } },
+ { 0xa7f5, 1, { 0xa7f6, 0 } },
+ { 0xa7f8, 1, { 0x127, 0 } },
+ { 0xa7f9, 1, { 0x153, 0 } },
+ { 0xab5c, 1, { 0xa727, 0 } },
+ { 0xab5d, 1, { 0xab37, 0 } },
+ { 0xab5e, 1, { 0x26b, 0 } },
+ { 0xab5f, 1, { 0xab52, 0 } },
+ { 0xab69, 1, { 0x28d, 0 } },
+ { 0xab70, 1, { 0x13a0, 0 } },
+ { 0xab71, 1, { 0x13a1, 0 } },
+ { 0xab72, 1, { 0x13a2, 0 } },
+ { 0xab73, 1, { 0x13a3, 0 } },
+ { 0xab74, 1, { 0x13a4, 0 } },
+ { 0xab75, 1, { 0x13a5, 0 } },
+ { 0xab76, 1, { 0x13a6, 0 } },
+ { 0xab77, 1, { 0x13a7, 0 } },
+ { 0xab78, 1, { 0x13a8, 0 } },
+ { 0xab79, 1, { 0x13a9, 0 } },
+ { 0xab7a, 1, { 0x13aa, 0 } },
+ { 0xab7b, 1, { 0x13ab, 0 } },
+ { 0xab7c, 1, { 0x13ac, 0 } },
+ { 0xab7d, 1, { 0x13ad, 0 } },
+ { 0xab7e, 1, { 0x13ae, 0 } },
+ { 0xab7f, 1, { 0x13af, 0 } },
+ { 0xab80, 1, { 0x13b0, 0 } },
+ { 0xab81, 1, { 0x13b1, 0 } },
+ { 0xab82, 1, { 0x13b2, 0 } },
+ { 0xab83, 1, { 0x13b3, 0 } },
+ { 0xab84, 1, { 0x13b4, 0 } },
+ { 0xab85, 1, { 0x13b5, 0 } },
+ { 0xab86, 1, { 0x13b6, 0 } },
+ { 0xab87, 1, { 0x13b7, 0 } },
+ { 0xab88, 1, { 0x13b8, 0 } },
+ { 0xab89, 1, { 0x13b9, 0 } },
+ { 0xab8a, 1, { 0x13ba, 0 } },
+ { 0xab8b, 1, { 0x13bb, 0 } },
+ { 0xab8c, 1, { 0x13bc, 0 } },
+ { 0xab8d, 1, { 0x13bd, 0 } },
+ { 0xab8e, 1, { 0x13be, 0 } },
+ { 0xab8f, 1, { 0x13bf, 0 } },
+ { 0xab90, 1, { 0x13c0, 0 } },
+ { 0xab91, 1, { 0x13c1, 0 } },
+ { 0xab92, 1, { 0x13c2, 0 } },
+ { 0xab93, 1, { 0x13c3, 0 } },
+ { 0xab94, 1, { 0x13c4, 0 } },
+ { 0xab95, 1, { 0x13c5, 0 } },
+ { 0xab96, 1, { 0x13c6, 0 } },
+ { 0xab97, 1, { 0x13c7, 0 } },
+ { 0xab98, 1, { 0x13c8, 0 } },
+ { 0xab99, 1, { 0x13c9, 0 } },
+ { 0xab9a, 1, { 0x13ca, 0 } },
+ { 0xab9b, 1, { 0x13cb, 0 } },
+ { 0xab9c, 1, { 0x13cc, 0 } },
+ { 0xab9d, 1, { 0x13cd, 0 } },
+ { 0xab9e, 1, { 0x13ce, 0 } },
+ { 0xab9f, 1, { 0x13cf, 0 } },
+ { 0xaba0, 1, { 0x13d0, 0 } },
+ { 0xaba1, 1, { 0x13d1, 0 } },
+ { 0xaba2, 1, { 0x13d2, 0 } },
+ { 0xaba3, 1, { 0x13d3, 0 } },
+ { 0xaba4, 1, { 0x13d4, 0 } },
+ { 0xaba5, 1, { 0x13d5, 0 } },
+ { 0xaba6, 1, { 0x13d6, 0 } },
+ { 0xaba7, 1, { 0x13d7, 0 } },
+ { 0xaba8, 1, { 0x13d8, 0 } },
+ { 0xaba9, 1, { 0x13d9, 0 } },
+ { 0xabaa, 1, { 0x13da, 0 } },
+ { 0xabab, 1, { 0x13db, 0 } },
+ { 0xabac, 1, { 0x13dc, 0 } },
+ { 0xabad, 1, { 0x13dd, 0 } },
+ { 0xabae, 1, { 0x13de, 0 } },
+ { 0xabaf, 1, { 0x13df, 0 } },
+ { 0xabb0, 1, { 0x13e0, 0 } },
+ { 0xabb1, 1, { 0x13e1, 0 } },
+ { 0xabb2, 1, { 0x13e2, 0 } },
+ { 0xabb3, 1, { 0x13e3, 0 } },
+ { 0xabb4, 1, { 0x13e4, 0 } },
+ { 0xabb5, 1, { 0x13e5, 0 } },
+ { 0xabb6, 1, { 0x13e6, 0 } },
+ { 0xabb7, 1, { 0x13e7, 0 } },
+ { 0xabb8, 1, { 0x13e8, 0 } },
+ { 0xabb9, 1, { 0x13e9, 0 } },
+ { 0xabba, 1, { 0x13ea, 0 } },
+ { 0xabbb, 1, { 0x13eb, 0 } },
+ { 0xabbc, 1, { 0x13ec, 0 } },
+ { 0xabbd, 1, { 0x13ed, 0 } },
+ { 0xabbe, 1, { 0x13ee, 0 } },
+ { 0xabbf, 1, { 0x13ef, 0 } },
+ { 0xf900, 1, { 0x8c48, 0 } },
+ { 0xf901, 1, { 0x66f4, 0 } },
+ { 0xf902, 1, { 0x8eca, 0 } },
+ { 0xf903, 1, { 0x8cc8, 0 } },
+ { 0xf904, 1, { 0x6ed1, 0 } },
+ { 0xf905, 1, { 0x4e32, 0 } },
+ { 0xf906, 1, { 0x53e5, 0 } },
+ { 0xf907, 1, { 0x9f9c, 0 } },
+ { 0xf908, 1, { 0x9f9c, 0 } },
+ { 0xf909, 1, { 0x5951, 0 } },
+ { 0xf90a, 1, { 0x91d1, 0 } },
+ { 0xf90b, 1, { 0x5587, 0 } },
+ { 0xf90c, 1, { 0x5948, 0 } },
+ { 0xf90d, 1, { 0x61f6, 0 } },
+ { 0xf90e, 1, { 0x7669, 0 } },
+ { 0xf90f, 1, { 0x7f85, 0 } },
+ { 0xf910, 1, { 0x863f, 0 } },
+ { 0xf911, 1, { 0x87ba, 0 } },
+ { 0xf912, 1, { 0x88f8, 0 } },
+ { 0xf913, 1, { 0x908f, 0 } },
+ { 0xf914, 1, { 0x6a02, 0 } },
+ { 0xf915, 1, { 0x6d1b, 0 } },
+ { 0xf916, 1, { 0x70d9, 0 } },
+ { 0xf917, 1, { 0x73de, 0 } },
+ { 0xf918, 1, { 0x843d, 0 } },
+ { 0xf919, 1, { 0x916a, 0 } },
+ { 0xf91a, 1, { 0x99f1, 0 } },
+ { 0xf91b, 1, { 0x4e82, 0 } },
+ { 0xf91c, 1, { 0x5375, 0 } },
+ { 0xf91d, 1, { 0x6b04, 0 } },
+ { 0xf91e, 1, { 0x721b, 0 } },
+ { 0xf91f, 1, { 0x862d, 0 } },
+ { 0xf920, 1, { 0x9e1e, 0 } },
+ { 0xf921, 1, { 0x5d50, 0 } },
+ { 0xf922, 1, { 0x6feb, 0 } },
+ { 0xf923, 1, { 0x85cd, 0 } },
+ { 0xf924, 1, { 0x8964, 0 } },
+ { 0xf925, 1, { 0x62c9, 0 } },
+ { 0xf926, 1, { 0x81d8, 0 } },
+ { 0xf927, 1, { 0x881f, 0 } },
+ { 0xf928, 1, { 0x5eca, 0 } },
+ { 0xf929, 1, { 0x6717, 0 } },
+ { 0xf92a, 1, { 0x6d6a, 0 } },
+ { 0xf92b, 1, { 0x72fc, 0 } },
+ { 0xf92c, 1, { 0x90ce, 0 } },
+ { 0xf92d, 1, { 0x4f86, 0 } },
+ { 0xf92e, 1, { 0x51b7, 0 } },
+ { 0xf92f, 1, { 0x52de, 0 } },
+ { 0xf930, 1, { 0x64c4, 0 } },
+ { 0xf931, 1, { 0x6ad3, 0 } },
+ { 0xf932, 1, { 0x7210, 0 } },
+ { 0xf933, 1, { 0x76e7, 0 } },
+ { 0xf934, 1, { 0x8001, 0 } },
+ { 0xf935, 1, { 0x8606, 0 } },
+ { 0xf936, 1, { 0x865c, 0 } },
+ { 0xf937, 1, { 0x8def, 0 } },
+ { 0xf938, 1, { 0x9732, 0 } },
+ { 0xf939, 1, { 0x9b6f, 0 } },
+ { 0xf93a, 1, { 0x9dfa, 0 } },
+ { 0xf93b, 1, { 0x788c, 0 } },
+ { 0xf93c, 1, { 0x797f, 0 } },
+ { 0xf93d, 1, { 0x7da0, 0 } },
+ { 0xf93e, 1, { 0x83c9, 0 } },
+ { 0xf93f, 1, { 0x9304, 0 } },
+ { 0xf940, 1, { 0x9e7f, 0 } },
+ { 0xf941, 1, { 0x8ad6, 0 } },
+ { 0xf942, 1, { 0x58df, 0 } },
+ { 0xf943, 1, { 0x5f04, 0 } },
+ { 0xf944, 1, { 0x7c60, 0 } },
+ { 0xf945, 1, { 0x807e, 0 } },
+ { 0xf946, 1, { 0x7262, 0 } },
+ { 0xf947, 1, { 0x78ca, 0 } },
+ { 0xf948, 1, { 0x8cc2, 0 } },
+ { 0xf949, 1, { 0x96f7, 0 } },
+ { 0xf94a, 1, { 0x58d8, 0 } },
+ { 0xf94b, 1, { 0x5c62, 0 } },
+ { 0xf94c, 1, { 0x6a13, 0 } },
+ { 0xf94d, 1, { 0x6dda, 0 } },
+ { 0xf94e, 1, { 0x6f0f, 0 } },
+ { 0xf94f, 1, { 0x7d2f, 0 } },
+ { 0xf950, 1, { 0x7e37, 0 } },
+ { 0xf951, 1, { 0x964b, 0 } },
+ { 0xf952, 1, { 0x52d2, 0 } },
+ { 0xf953, 1, { 0x808b, 0 } },
+ { 0xf954, 1, { 0x51dc, 0 } },
+ { 0xf955, 1, { 0x51cc, 0 } },
+ { 0xf956, 1, { 0x7a1c, 0 } },
+ { 0xf957, 1, { 0x7dbe, 0 } },
+ { 0xf958, 1, { 0x83f1, 0 } },
+ { 0xf959, 1, { 0x9675, 0 } },
+ { 0xf95a, 1, { 0x8b80, 0 } },
+ { 0xf95b, 1, { 0x62cf, 0 } },
+ { 0xf95c, 1, { 0x6a02, 0 } },
+ { 0xf95d, 1, { 0x8afe, 0 } },
+ { 0xf95e, 1, { 0x4e39, 0 } },
+ { 0xf95f, 1, { 0x5be7, 0 } },
+ { 0xf960, 1, { 0x6012, 0 } },
+ { 0xf961, 1, { 0x7387, 0 } },
+ { 0xf962, 1, { 0x7570, 0 } },
+ { 0xf963, 1, { 0x5317, 0 } },
+ { 0xf964, 1, { 0x78fb, 0 } },
+ { 0xf965, 1, { 0x4fbf, 0 } },
+ { 0xf966, 1, { 0x5fa9, 0 } },
+ { 0xf967, 1, { 0x4e0d, 0 } },
+ { 0xf968, 1, { 0x6ccc, 0 } },
+ { 0xf969, 1, { 0x6578, 0 } },
+ { 0xf96a, 1, { 0x7d22, 0 } },
+ { 0xf96b, 1, { 0x53c3, 0 } },
+ { 0xf96c, 1, { 0x585e, 0 } },
+ { 0xf96d, 1, { 0x7701, 0 } },
+ { 0xf96e, 1, { 0x8449, 0 } },
+ { 0xf96f, 1, { 0x8aaa, 0 } },
+ { 0xf970, 1, { 0x6bba, 0 } },
+ { 0xf971, 1, { 0x8fb0, 0 } },
+ { 0xf972, 1, { 0x6c88, 0 } },
+ { 0xf973, 1, { 0x62fe, 0 } },
+ { 0xf974, 1, { 0x82e5, 0 } },
+ { 0xf975, 1, { 0x63a0, 0 } },
+ { 0xf976, 1, { 0x7565, 0 } },
+ { 0xf977, 1, { 0x4eae, 0 } },
+ { 0xf978, 1, { 0x5169, 0 } },
+ { 0xf979, 1, { 0x51c9, 0 } },
+ { 0xf97a, 1, { 0x6881, 0 } },
+ { 0xf97b, 1, { 0x7ce7, 0 } },
+ { 0xf97c, 1, { 0x826f, 0 } },
+ { 0xf97d, 1, { 0x8ad2, 0 } },
+ { 0xf97e, 1, { 0x91cf, 0 } },
+ { 0xf97f, 1, { 0x52f5, 0 } },
+ { 0xf980, 1, { 0x5442, 0 } },
+ { 0xf981, 1, { 0x5973, 0 } },
+ { 0xf982, 1, { 0x5eec, 0 } },
+ { 0xf983, 1, { 0x65c5, 0 } },
+ { 0xf984, 1, { 0x6ffe, 0 } },
+ { 0xf985, 1, { 0x792a, 0 } },
+ { 0xf986, 1, { 0x95ad, 0 } },
+ { 0xf987, 1, { 0x9a6a, 0 } },
+ { 0xf988, 1, { 0x9e97, 0 } },
+ { 0xf989, 1, { 0x9ece, 0 } },
+ { 0xf98a, 1, { 0x529b, 0 } },
+ { 0xf98b, 1, { 0x66c6, 0 } },
+ { 0xf98c, 1, { 0x6b77, 0 } },
+ { 0xf98d, 1, { 0x8f62, 0 } },
+ { 0xf98e, 1, { 0x5e74, 0 } },
+ { 0xf98f, 1, { 0x6190, 0 } },
+ { 0xf990, 1, { 0x6200, 0 } },
+ { 0xf991, 1, { 0x649a, 0 } },
+ { 0xf992, 1, { 0x6f23, 0 } },
+ { 0xf993, 1, { 0x7149, 0 } },
+ { 0xf994, 1, { 0x7489, 0 } },
+ { 0xf995, 1, { 0x79ca, 0 } },
+ { 0xf996, 1, { 0x7df4, 0 } },
+ { 0xf997, 1, { 0x806f, 0 } },
+ { 0xf998, 1, { 0x8f26, 0 } },
+ { 0xf999, 1, { 0x84ee, 0 } },
+ { 0xf99a, 1, { 0x9023, 0 } },
+ { 0xf99b, 1, { 0x934a, 0 } },
+ { 0xf99c, 1, { 0x5217, 0 } },
+ { 0xf99d, 1, { 0x52a3, 0 } },
+ { 0xf99e, 1, { 0x54bd, 0 } },
+ { 0xf99f, 1, { 0x70c8, 0 } },
+ { 0xf9a0, 1, { 0x88c2, 0 } },
+ { 0xf9a1, 1, { 0x8aaa, 0 } },
+ { 0xf9a2, 1, { 0x5ec9, 0 } },
+ { 0xf9a3, 1, { 0x5ff5, 0 } },
+ { 0xf9a4, 1, { 0x637b, 0 } },
+ { 0xf9a5, 1, { 0x6bae, 0 } },
+ { 0xf9a6, 1, { 0x7c3e, 0 } },
+ { 0xf9a7, 1, { 0x7375, 0 } },
+ { 0xf9a8, 1, { 0x4ee4, 0 } },
+ { 0xf9a9, 1, { 0x56f9, 0 } },
+ { 0xf9aa, 1, { 0x5be7, 0 } },
+ { 0xf9ab, 1, { 0x5dba, 0 } },
+ { 0xf9ac, 1, { 0x601c, 0 } },
+ { 0xf9ad, 1, { 0x73b2, 0 } },
+ { 0xf9ae, 1, { 0x7469, 0 } },
+ { 0xf9af, 1, { 0x7f9a, 0 } },
+ { 0xf9b0, 1, { 0x8046, 0 } },
+ { 0xf9b1, 1, { 0x9234, 0 } },
+ { 0xf9b2, 1, { 0x96f6, 0 } },
+ { 0xf9b3, 1, { 0x9748, 0 } },
+ { 0xf9b4, 1, { 0x9818, 0 } },
+ { 0xf9b5, 1, { 0x4f8b, 0 } },
+ { 0xf9b6, 1, { 0x79ae, 0 } },
+ { 0xf9b7, 1, { 0x91b4, 0 } },
+ { 0xf9b8, 1, { 0x96b8, 0 } },
+ { 0xf9b9, 1, { 0x60e1, 0 } },
+ { 0xf9ba, 1, { 0x4e86, 0 } },
+ { 0xf9bb, 1, { 0x50da, 0 } },
+ { 0xf9bc, 1, { 0x5bee, 0 } },
+ { 0xf9bd, 1, { 0x5c3f, 0 } },
+ { 0xf9be, 1, { 0x6599, 0 } },
+ { 0xf9bf, 1, { 0x6a02, 0 } },
+ { 0xf9c0, 1, { 0x71ce, 0 } },
+ { 0xf9c1, 1, { 0x7642, 0 } },
+ { 0xf9c2, 1, { 0x84fc, 0 } },
+ { 0xf9c3, 1, { 0x907c, 0 } },
+ { 0xf9c4, 1, { 0x9f8d, 0 } },
+ { 0xf9c5, 1, { 0x6688, 0 } },
+ { 0xf9c6, 1, { 0x962e, 0 } },
+ { 0xf9c7, 1, { 0x5289, 0 } },
+ { 0xf9c8, 1, { 0x677b, 0 } },
+ { 0xf9c9, 1, { 0x67f3, 0 } },
+ { 0xf9ca, 1, { 0x6d41, 0 } },
+ { 0xf9cb, 1, { 0x6e9c, 0 } },
+ { 0xf9cc, 1, { 0x7409, 0 } },
+ { 0xf9cd, 1, { 0x7559, 0 } },
+ { 0xf9ce, 1, { 0x786b, 0 } },
+ { 0xf9cf, 1, { 0x7d10, 0 } },
+ { 0xf9d0, 1, { 0x985e, 0 } },
+ { 0xf9d1, 1, { 0x516d, 0 } },
+ { 0xf9d2, 1, { 0x622e, 0 } },
+ { 0xf9d3, 1, { 0x9678, 0 } },
+ { 0xf9d4, 1, { 0x502b, 0 } },
+ { 0xf9d5, 1, { 0x5d19, 0 } },
+ { 0xf9d6, 1, { 0x6dea, 0 } },
+ { 0xf9d7, 1, { 0x8f2a, 0 } },
+ { 0xf9d8, 1, { 0x5f8b, 0 } },
+ { 0xf9d9, 1, { 0x6144, 0 } },
+ { 0xf9da, 1, { 0x6817, 0 } },
+ { 0xf9db, 1, { 0x7387, 0 } },
+ { 0xf9dc, 1, { 0x9686, 0 } },
+ { 0xf9dd, 1, { 0x5229, 0 } },
+ { 0xf9de, 1, { 0x540f, 0 } },
+ { 0xf9df, 1, { 0x5c65, 0 } },
+ { 0xf9e0, 1, { 0x6613, 0 } },
+ { 0xf9e1, 1, { 0x674e, 0 } },
+ { 0xf9e2, 1, { 0x68a8, 0 } },
+ { 0xf9e3, 1, { 0x6ce5, 0 } },
+ { 0xf9e4, 1, { 0x7406, 0 } },
+ { 0xf9e5, 1, { 0x75e2, 0 } },
+ { 0xf9e6, 1, { 0x7f79, 0 } },
+ { 0xf9e7, 1, { 0x88cf, 0 } },
+ { 0xf9e8, 1, { 0x88e1, 0 } },
+ { 0xf9e9, 1, { 0x91cc, 0 } },
+ { 0xf9ea, 1, { 0x96e2, 0 } },
+ { 0xf9eb, 1, { 0x533f, 0 } },
+ { 0xf9ec, 1, { 0x6eba, 0 } },
+ { 0xf9ed, 1, { 0x541d, 0 } },
+ { 0xf9ee, 1, { 0x71d0, 0 } },
+ { 0xf9ef, 1, { 0x7498, 0 } },
+ { 0xf9f0, 1, { 0x85fa, 0 } },
+ { 0xf9f1, 1, { 0x96a3, 0 } },
+ { 0xf9f2, 1, { 0x9c57, 0 } },
+ { 0xf9f3, 1, { 0x9e9f, 0 } },
+ { 0xf9f4, 1, { 0x6797, 0 } },
+ { 0xf9f5, 1, { 0x6dcb, 0 } },
+ { 0xf9f6, 1, { 0x81e8, 0 } },
+ { 0xf9f7, 1, { 0x7acb, 0 } },
+ { 0xf9f8, 1, { 0x7b20, 0 } },
+ { 0xf9f9, 1, { 0x7c92, 0 } },
+ { 0xf9fa, 1, { 0x72c0, 0 } },
+ { 0xf9fb, 1, { 0x7099, 0 } },
+ { 0xf9fc, 1, { 0x8b58, 0 } },
+ { 0xf9fd, 1, { 0x4ec0, 0 } },
+ { 0xf9fe, 1, { 0x8336, 0 } },
+ { 0xf9ff, 1, { 0x523a, 0 } },
+ { 0xfa00, 1, { 0x5207, 0 } },
+ { 0xfa01, 1, { 0x5ea6, 0 } },
+ { 0xfa02, 1, { 0x62d3, 0 } },
+ { 0xfa03, 1, { 0x7cd6, 0 } },
+ { 0xfa04, 1, { 0x5b85, 0 } },
+ { 0xfa05, 1, { 0x6d1e, 0 } },
+ { 0xfa06, 1, { 0x66b4, 0 } },
+ { 0xfa07, 1, { 0x8f3b, 0 } },
+ { 0xfa08, 1, { 0x884c, 0 } },
+ { 0xfa09, 1, { 0x964d, 0 } },
+ { 0xfa0a, 1, { 0x898b, 0 } },
+ { 0xfa0b, 1, { 0x5ed3, 0 } },
+ { 0xfa0c, 1, { 0x5140, 0 } },
+ { 0xfa0d, 1, { 0x55c0, 0 } },
+ { 0xfa10, 1, { 0x585a, 0 } },
+ { 0xfa12, 1, { 0x6674, 0 } },
+ { 0xfa15, 1, { 0x51de, 0 } },
+ { 0xfa16, 1, { 0x732a, 0 } },
+ { 0xfa17, 1, { 0x76ca, 0 } },
+ { 0xfa18, 1, { 0x793c, 0 } },
+ { 0xfa19, 1, { 0x795e, 0 } },
+ { 0xfa1a, 1, { 0x7965, 0 } },
+ { 0xfa1b, 1, { 0x798f, 0 } },
+ { 0xfa1c, 1, { 0x9756, 0 } },
+ { 0xfa1d, 1, { 0x7cbe, 0 } },
+ { 0xfa1e, 1, { 0x7fbd, 0 } },
+ { 0xfa20, 1, { 0x8612, 0 } },
+ { 0xfa22, 1, { 0x8af8, 0 } },
+ { 0xfa25, 1, { 0x9038, 0 } },
+ { 0xfa26, 1, { 0x90fd, 0 } },
+ { 0xfa2a, 1, { 0x98ef, 0 } },
+ { 0xfa2b, 1, { 0x98fc, 0 } },
+ { 0xfa2c, 1, { 0x9928, 0 } },
+ { 0xfa2d, 1, { 0x9db4, 0 } },
+ { 0xfa2e, 1, { 0x90de, 0 } },
+ { 0xfa2f, 1, { 0x96b7, 0 } },
+ { 0xfa30, 1, { 0x4fae, 0 } },
+ { 0xfa31, 1, { 0x50e7, 0 } },
+ { 0xfa32, 1, { 0x514d, 0 } },
+ { 0xfa33, 1, { 0x52c9, 0 } },
+ { 0xfa34, 1, { 0x52e4, 0 } },
+ { 0xfa35, 1, { 0x5351, 0 } },
+ { 0xfa36, 1, { 0x559d, 0 } },
+ { 0xfa37, 1, { 0x5606, 0 } },
+ { 0xfa38, 1, { 0x5668, 0 } },
+ { 0xfa39, 1, { 0x5840, 0 } },
+ { 0xfa3a, 1, { 0x58a8, 0 } },
+ { 0xfa3b, 1, { 0x5c64, 0 } },
+ { 0xfa3c, 1, { 0x5c6e, 0 } },
+ { 0xfa3d, 1, { 0x6094, 0 } },
+ { 0xfa3e, 1, { 0x6168, 0 } },
+ { 0xfa3f, 1, { 0x618e, 0 } },
+ { 0xfa40, 1, { 0x61f2, 0 } },
+ { 0xfa41, 1, { 0x654f, 0 } },
+ { 0xfa42, 1, { 0x65e2, 0 } },
+ { 0xfa43, 1, { 0x6691, 0 } },
+ { 0xfa44, 1, { 0x6885, 0 } },
+ { 0xfa45, 1, { 0x6d77, 0 } },
+ { 0xfa46, 1, { 0x6e1a, 0 } },
+ { 0xfa47, 1, { 0x6f22, 0 } },
+ { 0xfa48, 1, { 0x716e, 0 } },
+ { 0xfa49, 1, { 0x722b, 0 } },
+ { 0xfa4a, 1, { 0x7422, 0 } },
+ { 0xfa4b, 1, { 0x7891, 0 } },
+ { 0xfa4c, 1, { 0x793e, 0 } },
+ { 0xfa4d, 1, { 0x7949, 0 } },
+ { 0xfa4e, 1, { 0x7948, 0 } },
+ { 0xfa4f, 1, { 0x7950, 0 } },
+ { 0xfa50, 1, { 0x7956, 0 } },
+ { 0xfa51, 1, { 0x795d, 0 } },
+ { 0xfa52, 1, { 0x798d, 0 } },
+ { 0xfa53, 1, { 0x798e, 0 } },
+ { 0xfa54, 1, { 0x7a40, 0 } },
+ { 0xfa55, 1, { 0x7a81, 0 } },
+ { 0xfa56, 1, { 0x7bc0, 0 } },
+ { 0xfa57, 1, { 0x7df4, 0 } },
+ { 0xfa58, 1, { 0x7e09, 0 } },
+ { 0xfa59, 1, { 0x7e41, 0 } },
+ { 0xfa5a, 1, { 0x7f72, 0 } },
+ { 0xfa5b, 1, { 0x8005, 0 } },
+ { 0xfa5c, 1, { 0x81ed, 0 } },
+ { 0xfa5d, 1, { 0x8279, 0 } },
+ { 0xfa5e, 1, { 0x8279, 0 } },
+ { 0xfa5f, 1, { 0x8457, 0 } },
+ { 0xfa60, 1, { 0x8910, 0 } },
+ { 0xfa61, 1, { 0x8996, 0 } },
+ { 0xfa62, 1, { 0x8b01, 0 } },
+ { 0xfa63, 1, { 0x8b39, 0 } },
+ { 0xfa64, 1, { 0x8cd3, 0 } },
+ { 0xfa65, 1, { 0x8d08, 0 } },
+ { 0xfa66, 1, { 0x8fb6, 0 } },
+ { 0xfa67, 1, { 0x9038, 0 } },
+ { 0xfa68, 1, { 0x96e3, 0 } },
+ { 0xfa69, 1, { 0x97ff, 0 } },
+ { 0xfa6a, 1, { 0x983b, 0 } },
+ { 0xfa6b, 1, { 0x6075, 0 } },
+ { 0xfa6c, 2, { 0xd850, 0xdeee } },
+ { 0xfa6d, 1, { 0x8218, 0 } },
+ { 0xfa70, 1, { 0x4e26, 0 } },
+ { 0xfa71, 1, { 0x51b5, 0 } },
+ { 0xfa72, 1, { 0x5168, 0 } },
+ { 0xfa73, 1, { 0x4f80, 0 } },
+ { 0xfa74, 1, { 0x5145, 0 } },
+ { 0xfa75, 1, { 0x5180, 0 } },
+ { 0xfa76, 1, { 0x52c7, 0 } },
+ { 0xfa77, 1, { 0x52fa, 0 } },
+ { 0xfa78, 1, { 0x559d, 0 } },
+ { 0xfa79, 1, { 0x5555, 0 } },
+ { 0xfa7a, 1, { 0x5599, 0 } },
+ { 0xfa7b, 1, { 0x55e2, 0 } },
+ { 0xfa7c, 1, { 0x585a, 0 } },
+ { 0xfa7d, 1, { 0x58b3, 0 } },
+ { 0xfa7e, 1, { 0x5944, 0 } },
+ { 0xfa7f, 1, { 0x5954, 0 } },
+ { 0xfa80, 1, { 0x5a62, 0 } },
+ { 0xfa81, 1, { 0x5b28, 0 } },
+ { 0xfa82, 1, { 0x5ed2, 0 } },
+ { 0xfa83, 1, { 0x5ed9, 0 } },
+ { 0xfa84, 1, { 0x5f69, 0 } },
+ { 0xfa85, 1, { 0x5fad, 0 } },
+ { 0xfa86, 1, { 0x60d8, 0 } },
+ { 0xfa87, 1, { 0x614e, 0 } },
+ { 0xfa88, 1, { 0x6108, 0 } },
+ { 0xfa89, 1, { 0x618e, 0 } },
+ { 0xfa8a, 1, { 0x6160, 0 } },
+ { 0xfa8b, 1, { 0x61f2, 0 } },
+ { 0xfa8c, 1, { 0x6234, 0 } },
+ { 0xfa8d, 1, { 0x63c4, 0 } },
+ { 0xfa8e, 1, { 0x641c, 0 } },
+ { 0xfa8f, 1, { 0x6452, 0 } },
+ { 0xfa90, 1, { 0x6556, 0 } },
+ { 0xfa91, 1, { 0x6674, 0 } },
+ { 0xfa92, 1, { 0x6717, 0 } },
+ { 0xfa93, 1, { 0x671b, 0 } },
+ { 0xfa94, 1, { 0x6756, 0 } },
+ { 0xfa95, 1, { 0x6b79, 0 } },
+ { 0xfa96, 1, { 0x6bba, 0 } },
+ { 0xfa97, 1, { 0x6d41, 0 } },
+ { 0xfa98, 1, { 0x6edb, 0 } },
+ { 0xfa99, 1, { 0x6ecb, 0 } },
+ { 0xfa9a, 1, { 0x6f22, 0 } },
+ { 0xfa9b, 1, { 0x701e, 0 } },
+ { 0xfa9c, 1, { 0x716e, 0 } },
+ { 0xfa9d, 1, { 0x77a7, 0 } },
+ { 0xfa9e, 1, { 0x7235, 0 } },
+ { 0xfa9f, 1, { 0x72af, 0 } },
+ { 0xfaa0, 1, { 0x732a, 0 } },
+ { 0xfaa1, 1, { 0x7471, 0 } },
+ { 0xfaa2, 1, { 0x7506, 0 } },
+ { 0xfaa3, 1, { 0x753b, 0 } },
+ { 0xfaa4, 1, { 0x761d, 0 } },
+ { 0xfaa5, 1, { 0x761f, 0 } },
+ { 0xfaa6, 1, { 0x76ca, 0 } },
+ { 0xfaa7, 1, { 0x76db, 0 } },
+ { 0xfaa8, 1, { 0x76f4, 0 } },
+ { 0xfaa9, 1, { 0x774a, 0 } },
+ { 0xfaaa, 1, { 0x7740, 0 } },
+ { 0xfaab, 1, { 0x78cc, 0 } },
+ { 0xfaac, 1, { 0x7ab1, 0 } },
+ { 0xfaad, 1, { 0x7bc0, 0 } },
+ { 0xfaae, 1, { 0x7c7b, 0 } },
+ { 0xfaaf, 1, { 0x7d5b, 0 } },
+ { 0xfab0, 1, { 0x7df4, 0 } },
+ { 0xfab1, 1, { 0x7f3e, 0 } },
+ { 0xfab2, 1, { 0x8005, 0 } },
+ { 0xfab3, 1, { 0x8352, 0 } },
+ { 0xfab4, 1, { 0x83ef, 0 } },
+ { 0xfab5, 1, { 0x8779, 0 } },
+ { 0xfab6, 1, { 0x8941, 0 } },
+ { 0xfab7, 1, { 0x8986, 0 } },
+ { 0xfab8, 1, { 0x8996, 0 } },
+ { 0xfab9, 1, { 0x8abf, 0 } },
+ { 0xfaba, 1, { 0x8af8, 0 } },
+ { 0xfabb, 1, { 0x8acb, 0 } },
+ { 0xfabc, 1, { 0x8b01, 0 } },
+ { 0xfabd, 1, { 0x8afe, 0 } },
+ { 0xfabe, 1, { 0x8aed, 0 } },
+ { 0xfabf, 1, { 0x8b39, 0 } },
+ { 0xfac0, 1, { 0x8b8a, 0 } },
+ { 0xfac1, 1, { 0x8d08, 0 } },
+ { 0xfac2, 1, { 0x8f38, 0 } },
+ { 0xfac3, 1, { 0x9072, 0 } },
+ { 0xfac4, 1, { 0x9199, 0 } },
+ { 0xfac5, 1, { 0x9276, 0 } },
+ { 0xfac6, 1, { 0x967c, 0 } },
+ { 0xfac7, 1, { 0x96e3, 0 } },
+ { 0xfac8, 1, { 0x9756, 0 } },
+ { 0xfac9, 1, { 0x97db, 0 } },
+ { 0xfaca, 1, { 0x97ff, 0 } },
+ { 0xfacb, 1, { 0x980b, 0 } },
+ { 0xfacc, 1, { 0x983b, 0 } },
+ { 0xfacd, 1, { 0x9b12, 0 } },
+ { 0xface, 1, { 0x9f9c, 0 } },
+ { 0xfacf, 2, { 0xd84a, 0xdc4a } },
+ { 0xfad0, 2, { 0xd84a, 0xdc44 } },
+ { 0xfad1, 2, { 0xd84c, 0xdfd5 } },
+ { 0xfad2, 1, { 0x3b9d, 0 } },
+ { 0xfad3, 1, { 0x4018, 0 } },
+ { 0xfad4, 1, { 0x4039, 0 } },
+ { 0xfad5, 2, { 0xd854, 0xde49 } },
+ { 0xfad6, 2, { 0xd857, 0xdcd0 } },
+ { 0xfad7, 2, { 0xd85f, 0xded3 } },
+ { 0xfad8, 1, { 0x9f43, 0 } },
+ { 0xfad9, 1, { 0x9f8e, 0 } },
+ { 0xfb00, 2, { 0x66, 0x66 } },
+ { 0xfb01, 2, { 0x66, 0x69 } },
+ { 0xfb02, 2, { 0x66, 0x6c } },
+ { 0xfb03, 3, { 703, 0 } },
+ { 0xfb04, 3, { 721, 0 } },
+ { 0xfb05, 2, { 0x73, 0x74 } },
+ { 0xfb06, 2, { 0x73, 0x74 } },
+ { 0xfb13, 2, { 0x574, 0x576 } },
+ { 0xfb14, 2, { 0x574, 0x565 } },
+ { 0xfb15, 2, { 0x574, 0x56b } },
+ { 0xfb16, 2, { 0x57e, 0x576 } },
+ { 0xfb17, 2, { 0x574, 0x56d } },
+ { 0xfb1d, 2, { 0x5d9, 0x5b4 } },
+ { 0xfb1f, 2, { 0x5f2, 0x5b7 } },
+ { 0xfb20, 1, { 0x5e2, 0 } },
+ { 0xfb21, 1, { 0x5d0, 0 } },
+ { 0xfb22, 1, { 0x5d3, 0 } },
+ { 0xfb23, 1, { 0x5d4, 0 } },
+ { 0xfb24, 1, { 0x5db, 0 } },
+ { 0xfb25, 1, { 0x5dc, 0 } },
+ { 0xfb26, 1, { 0x5dd, 0 } },
+ { 0xfb27, 1, { 0x5e8, 0 } },
+ { 0xfb28, 1, { 0x5ea, 0 } },
+ { 0xfb2a, 2, { 0x5e9, 0x5c1 } },
+ { 0xfb2b, 2, { 0x5e9, 0x5c2 } },
+ { 0xfb2c, 3, { 109, 0 } },
+ { 0xfb2d, 3, { 504, 0 } },
+ { 0xfb2e, 2, { 0x5d0, 0x5b7 } },
+ { 0xfb2f, 2, { 0x5d0, 0x5b8 } },
+ { 0xfb30, 2, { 0x5d0, 0x5bc } },
+ { 0xfb31, 2, { 0x5d1, 0x5bc } },
+ { 0xfb32, 2, { 0x5d2, 0x5bc } },
+ { 0xfb33, 2, { 0x5d3, 0x5bc } },
+ { 0xfb34, 2, { 0x5d4, 0x5bc } },
+ { 0xfb35, 2, { 0x5d5, 0x5bc } },
+ { 0xfb36, 2, { 0x5d6, 0x5bc } },
+ { 0xfb38, 2, { 0x5d8, 0x5bc } },
+ { 0xfb39, 2, { 0x5d9, 0x5bc } },
+ { 0xfb3a, 2, { 0x5da, 0x5bc } },
+ { 0xfb3b, 2, { 0x5db, 0x5bc } },
+ { 0xfb3c, 2, { 0x5dc, 0x5bc } },
+ { 0xfb3e, 2, { 0x5de, 0x5bc } },
+ { 0xfb40, 2, { 0x5e0, 0x5bc } },
+ { 0xfb41, 2, { 0x5e1, 0x5bc } },
+ { 0xfb43, 2, { 0x5e3, 0x5bc } },
+ { 0xfb44, 2, { 0x5e4, 0x5bc } },
+ { 0xfb46, 2, { 0x5e6, 0x5bc } },
+ { 0xfb47, 2, { 0x5e7, 0x5bc } },
+ { 0xfb48, 2, { 0x5e8, 0x5bc } },
+ { 0xfb49, 2, { 0x5e9, 0x5bc } },
+ { 0xfb4a, 2, { 0x5ea, 0x5bc } },
+ { 0xfb4b, 2, { 0x5d5, 0x5b9 } },
+ { 0xfb4c, 2, { 0x5d1, 0x5bf } },
+ { 0xfb4d, 2, { 0x5db, 0x5bf } },
+ { 0xfb4e, 2, { 0x5e4, 0x5bf } },
+ { 0xfb4f, 2, { 0x5d0, 0x5dc } },
+ { 0xfb50, 1, { 0x671, 0 } },
+ { 0xfb51, 1, { 0x671, 0 } },
+ { 0xfb52, 1, { 0x67b, 0 } },
+ { 0xfb53, 1, { 0x67b, 0 } },
+ { 0xfb54, 1, { 0x67b, 0 } },
+ { 0xfb55, 1, { 0x67b, 0 } },
+ { 0xfb56, 1, { 0x67e, 0 } },
+ { 0xfb57, 1, { 0x67e, 0 } },
+ { 0xfb58, 1, { 0x67e, 0 } },
+ { 0xfb59, 1, { 0x67e, 0 } },
+ { 0xfb5a, 1, { 0x680, 0 } },
+ { 0xfb5b, 1, { 0x680, 0 } },
+ { 0xfb5c, 1, { 0x680, 0 } },
+ { 0xfb5d, 1, { 0x680, 0 } },
+ { 0xfb5e, 1, { 0x67a, 0 } },
+ { 0xfb5f, 1, { 0x67a, 0 } },
+ { 0xfb60, 1, { 0x67a, 0 } },
+ { 0xfb61, 1, { 0x67a, 0 } },
+ { 0xfb62, 1, { 0x67f, 0 } },
+ { 0xfb63, 1, { 0x67f, 0 } },
+ { 0xfb64, 1, { 0x67f, 0 } },
+ { 0xfb65, 1, { 0x67f, 0 } },
+ { 0xfb66, 1, { 0x679, 0 } },
+ { 0xfb67, 1, { 0x679, 0 } },
+ { 0xfb68, 1, { 0x679, 0 } },
+ { 0xfb69, 1, { 0x679, 0 } },
+ { 0xfb6a, 1, { 0x6a4, 0 } },
+ { 0xfb6b, 1, { 0x6a4, 0 } },
+ { 0xfb6c, 1, { 0x6a4, 0 } },
+ { 0xfb6d, 1, { 0x6a4, 0 } },
+ { 0xfb6e, 1, { 0x6a6, 0 } },
+ { 0xfb6f, 1, { 0x6a6, 0 } },
+ { 0xfb70, 1, { 0x6a6, 0 } },
+ { 0xfb71, 1, { 0x6a6, 0 } },
+ { 0xfb72, 1, { 0x684, 0 } },
+ { 0xfb73, 1, { 0x684, 0 } },
+ { 0xfb74, 1, { 0x684, 0 } },
+ { 0xfb75, 1, { 0x684, 0 } },
+ { 0xfb76, 1, { 0x683, 0 } },
+ { 0xfb77, 1, { 0x683, 0 } },
+ { 0xfb78, 1, { 0x683, 0 } },
+ { 0xfb79, 1, { 0x683, 0 } },
+ { 0xfb7a, 1, { 0x686, 0 } },
+ { 0xfb7b, 1, { 0x686, 0 } },
+ { 0xfb7c, 1, { 0x686, 0 } },
+ { 0xfb7d, 1, { 0x686, 0 } },
+ { 0xfb7e, 1, { 0x687, 0 } },
+ { 0xfb7f, 1, { 0x687, 0 } },
+ { 0xfb80, 1, { 0x687, 0 } },
+ { 0xfb81, 1, { 0x687, 0 } },
+ { 0xfb82, 1, { 0x68d, 0 } },
+ { 0xfb83, 1, { 0x68d, 0 } },
+ { 0xfb84, 1, { 0x68c, 0 } },
+ { 0xfb85, 1, { 0x68c, 0 } },
+ { 0xfb86, 1, { 0x68e, 0 } },
+ { 0xfb87, 1, { 0x68e, 0 } },
+ { 0xfb88, 1, { 0x688, 0 } },
+ { 0xfb89, 1, { 0x688, 0 } },
+ { 0xfb8a, 1, { 0x698, 0 } },
+ { 0xfb8b, 1, { 0x698, 0 } },
+ { 0xfb8c, 1, { 0x691, 0 } },
+ { 0xfb8d, 1, { 0x691, 0 } },
+ { 0xfb8e, 1, { 0x6a9, 0 } },
+ { 0xfb8f, 1, { 0x6a9, 0 } },
+ { 0xfb90, 1, { 0x6a9, 0 } },
+ { 0xfb91, 1, { 0x6a9, 0 } },
+ { 0xfb92, 1, { 0x6af, 0 } },
+ { 0xfb93, 1, { 0x6af, 0 } },
+ { 0xfb94, 1, { 0x6af, 0 } },
+ { 0xfb95, 1, { 0x6af, 0 } },
+ { 0xfb96, 1, { 0x6b3, 0 } },
+ { 0xfb97, 1, { 0x6b3, 0 } },
+ { 0xfb98, 1, { 0x6b3, 0 } },
+ { 0xfb99, 1, { 0x6b3, 0 } },
+ { 0xfb9a, 1, { 0x6b1, 0 } },
+ { 0xfb9b, 1, { 0x6b1, 0 } },
+ { 0xfb9c, 1, { 0x6b1, 0 } },
+ { 0xfb9d, 1, { 0x6b1, 0 } },
+ { 0xfb9e, 1, { 0x6ba, 0 } },
+ { 0xfb9f, 1, { 0x6ba, 0 } },
+ { 0xfba0, 1, { 0x6bb, 0 } },
+ { 0xfba1, 1, { 0x6bb, 0 } },
+ { 0xfba2, 1, { 0x6bb, 0 } },
+ { 0xfba3, 1, { 0x6bb, 0 } },
+ { 0xfba4, 1, { 0x6c0, 0 } },
+ { 0xfba5, 1, { 0x6c0, 0 } },
+ { 0xfba6, 1, { 0x6c1, 0 } },
+ { 0xfba7, 1, { 0x6c1, 0 } },
+ { 0xfba8, 1, { 0x6c1, 0 } },
+ { 0xfba9, 1, { 0x6c1, 0 } },
+ { 0xfbaa, 1, { 0x6be, 0 } },
+ { 0xfbab, 1, { 0x6be, 0 } },
+ { 0xfbac, 1, { 0x6be, 0 } },
+ { 0xfbad, 1, { 0x6be, 0 } },
+ { 0xfbae, 1, { 0x6d2, 0 } },
+ { 0xfbaf, 1, { 0x6d2, 0 } },
+ { 0xfbb0, 1, { 0x6d3, 0 } },
+ { 0xfbb1, 1, { 0x6d3, 0 } },
+ { 0xfbd3, 1, { 0x6ad, 0 } },
+ { 0xfbd4, 1, { 0x6ad, 0 } },
+ { 0xfbd5, 1, { 0x6ad, 0 } },
+ { 0xfbd6, 1, { 0x6ad, 0 } },
+ { 0xfbd7, 1, { 0x6c7, 0 } },
+ { 0xfbd8, 1, { 0x6c7, 0 } },
+ { 0xfbd9, 1, { 0x6c6, 0 } },
+ { 0xfbda, 1, { 0x6c6, 0 } },
+ { 0xfbdb, 1, { 0x6c8, 0 } },
+ { 0xfbdc, 1, { 0x6c8, 0 } },
+ { 0xfbdd, 2, { 0x6c7, 0x674 } },
+ { 0xfbde, 1, { 0x6cb, 0 } },
+ { 0xfbdf, 1, { 0x6cb, 0 } },
+ { 0xfbe0, 1, { 0x6c5, 0 } },
+ { 0xfbe1, 1, { 0x6c5, 0 } },
+ { 0xfbe2, 1, { 0x6c9, 0 } },
+ { 0xfbe3, 1, { 0x6c9, 0 } },
+ { 0xfbe4, 1, { 0x6d0, 0 } },
+ { 0xfbe5, 1, { 0x6d0, 0 } },
+ { 0xfbe6, 1, { 0x6d0, 0 } },
+ { 0xfbe7, 1, { 0x6d0, 0 } },
+ { 0xfbe8, 1, { 0x649, 0 } },
+ { 0xfbe9, 1, { 0x649, 0 } },
+ { 0xfbea, 2, { 0x626, 0x627 } },
+ { 0xfbeb, 2, { 0x626, 0x627 } },
+ { 0xfbec, 2, { 0x626, 0x6d5 } },
+ { 0xfbed, 2, { 0x626, 0x6d5 } },
+ { 0xfbee, 2, { 0x626, 0x648 } },
+ { 0xfbef, 2, { 0x626, 0x648 } },
+ { 0xfbf0, 2, { 0x626, 0x6c7 } },
+ { 0xfbf1, 2, { 0x626, 0x6c7 } },
+ { 0xfbf2, 2, { 0x626, 0x6c6 } },
+ { 0xfbf3, 2, { 0x626, 0x6c6 } },
+ { 0xfbf4, 2, { 0x626, 0x6c8 } },
+ { 0xfbf5, 2, { 0x626, 0x6c8 } },
+ { 0xfbf6, 2, { 0x626, 0x6d0 } },
+ { 0xfbf7, 2, { 0x626, 0x6d0 } },
+ { 0xfbf8, 2, { 0x626, 0x6d0 } },
+ { 0xfbf9, 2, { 0x626, 0x649 } },
+ { 0xfbfa, 2, { 0x626, 0x649 } },
+ { 0xfbfb, 2, { 0x626, 0x649 } },
+ { 0xfbfc, 1, { 0x6cc, 0 } },
+ { 0xfbfd, 1, { 0x6cc, 0 } },
+ { 0xfbfe, 1, { 0x6cc, 0 } },
+ { 0xfbff, 1, { 0x6cc, 0 } },
+ { 0xfc00, 2, { 0x626, 0x62c } },
+ { 0xfc01, 2, { 0x626, 0x62d } },
+ { 0xfc02, 2, { 0x626, 0x645 } },
+ { 0xfc03, 2, { 0x626, 0x649 } },
+ { 0xfc04, 2, { 0x626, 0x64a } },
+ { 0xfc05, 2, { 0x628, 0x62c } },
+ { 0xfc06, 2, { 0x628, 0x62d } },
+ { 0xfc07, 2, { 0x628, 0x62e } },
+ { 0xfc08, 2, { 0x628, 0x645 } },
+ { 0xfc09, 2, { 0x628, 0x649 } },
+ { 0xfc0a, 2, { 0x628, 0x64a } },
+ { 0xfc0b, 2, { 0x62a, 0x62c } },
+ { 0xfc0c, 2, { 0x62a, 0x62d } },
+ { 0xfc0d, 2, { 0x62a, 0x62e } },
+ { 0xfc0e, 2, { 0x62a, 0x645 } },
+ { 0xfc0f, 2, { 0x62a, 0x649 } },
+ { 0xfc10, 2, { 0x62a, 0x64a } },
+ { 0xfc11, 2, { 0x62b, 0x62c } },
+ { 0xfc12, 2, { 0x62b, 0x645 } },
+ { 0xfc13, 2, { 0x62b, 0x649 } },
+ { 0xfc14, 2, { 0x62b, 0x64a } },
+ { 0xfc15, 2, { 0x62c, 0x62d } },
+ { 0xfc16, 2, { 0x62c, 0x645 } },
+ { 0xfc17, 2, { 0x62d, 0x62c } },
+ { 0xfc18, 2, { 0x62d, 0x645 } },
+ { 0xfc19, 2, { 0x62e, 0x62c } },
+ { 0xfc1a, 2, { 0x62e, 0x62d } },
+ { 0xfc1b, 2, { 0x62e, 0x645 } },
+ { 0xfc1c, 2, { 0x633, 0x62c } },
+ { 0xfc1d, 2, { 0x633, 0x62d } },
+ { 0xfc1e, 2, { 0x633, 0x62e } },
+ { 0xfc1f, 2, { 0x633, 0x645 } },
+ { 0xfc20, 2, { 0x635, 0x62d } },
+ { 0xfc21, 2, { 0x635, 0x645 } },
+ { 0xfc22, 2, { 0x636, 0x62c } },
+ { 0xfc23, 2, { 0x636, 0x62d } },
+ { 0xfc24, 2, { 0x636, 0x62e } },
+ { 0xfc25, 2, { 0x636, 0x645 } },
+ { 0xfc26, 2, { 0x637, 0x62d } },
+ { 0xfc27, 2, { 0x637, 0x645 } },
+ { 0xfc28, 2, { 0x638, 0x645 } },
+ { 0xfc29, 2, { 0x639, 0x62c } },
+ { 0xfc2a, 2, { 0x639, 0x645 } },
+ { 0xfc2b, 2, { 0x63a, 0x62c } },
+ { 0xfc2c, 2, { 0x63a, 0x645 } },
+ { 0xfc2d, 2, { 0x641, 0x62c } },
+ { 0xfc2e, 2, { 0x641, 0x62d } },
+ { 0xfc2f, 2, { 0x641, 0x62e } },
+ { 0xfc30, 2, { 0x641, 0x645 } },
+ { 0xfc31, 2, { 0x641, 0x649 } },
+ { 0xfc32, 2, { 0x641, 0x64a } },
+ { 0xfc33, 2, { 0x642, 0x62d } },
+ { 0xfc34, 2, { 0x642, 0x645 } },
+ { 0xfc35, 2, { 0x642, 0x649 } },
+ { 0xfc36, 2, { 0x642, 0x64a } },
+ { 0xfc37, 2, { 0x643, 0x627 } },
+ { 0xfc38, 2, { 0x643, 0x62c } },
+ { 0xfc39, 2, { 0x643, 0x62d } },
+ { 0xfc3a, 2, { 0x643, 0x62e } },
+ { 0xfc3b, 2, { 0x643, 0x644 } },
+ { 0xfc3c, 2, { 0x643, 0x645 } },
+ { 0xfc3d, 2, { 0x643, 0x649 } },
+ { 0xfc3e, 2, { 0x643, 0x64a } },
+ { 0xfc3f, 2, { 0x644, 0x62c } },
+ { 0xfc40, 2, { 0x644, 0x62d } },
+ { 0xfc41, 2, { 0x644, 0x62e } },
+ { 0xfc42, 2, { 0x644, 0x645 } },
+ { 0xfc43, 2, { 0x644, 0x649 } },
+ { 0xfc44, 2, { 0x644, 0x64a } },
+ { 0xfc45, 2, { 0x645, 0x62c } },
+ { 0xfc46, 2, { 0x645, 0x62d } },
+ { 0xfc47, 2, { 0x645, 0x62e } },
+ { 0xfc48, 2, { 0x645, 0x645 } },
+ { 0xfc49, 2, { 0x645, 0x649 } },
+ { 0xfc4a, 2, { 0x645, 0x64a } },
+ { 0xfc4b, 2, { 0x646, 0x62c } },
+ { 0xfc4c, 2, { 0x646, 0x62d } },
+ { 0xfc4d, 2, { 0x646, 0x62e } },
+ { 0xfc4e, 2, { 0x646, 0x645 } },
+ { 0xfc4f, 2, { 0x646, 0x649 } },
+ { 0xfc50, 2, { 0x646, 0x64a } },
+ { 0xfc51, 2, { 0x647, 0x62c } },
+ { 0xfc52, 2, { 0x647, 0x645 } },
+ { 0xfc53, 2, { 0x647, 0x649 } },
+ { 0xfc54, 2, { 0x647, 0x64a } },
+ { 0xfc55, 2, { 0x64a, 0x62c } },
+ { 0xfc56, 2, { 0x64a, 0x62d } },
+ { 0xfc57, 2, { 0x64a, 0x62e } },
+ { 0xfc58, 2, { 0x64a, 0x645 } },
+ { 0xfc59, 2, { 0x64a, 0x649 } },
+ { 0xfc5a, 2, { 0x64a, 0x64a } },
+ { 0xfc5b, 2, { 0x630, 0x670 } },
+ { 0xfc5c, 2, { 0x631, 0x670 } },
+ { 0xfc5d, 2, { 0x649, 0x670 } },
+ { 0xfc64, 2, { 0x626, 0x631 } },
+ { 0xfc65, 2, { 0x626, 0x632 } },
+ { 0xfc66, 2, { 0x626, 0x645 } },
+ { 0xfc67, 2, { 0x626, 0x646 } },
+ { 0xfc68, 2, { 0x626, 0x649 } },
+ { 0xfc69, 2, { 0x626, 0x64a } },
+ { 0xfc6a, 2, { 0x628, 0x631 } },
+ { 0xfc6b, 2, { 0x628, 0x632 } },
+ { 0xfc6c, 2, { 0x628, 0x645 } },
+ { 0xfc6d, 2, { 0x628, 0x646 } },
+ { 0xfc6e, 2, { 0x628, 0x649 } },
+ { 0xfc6f, 2, { 0x628, 0x64a } },
+ { 0xfc70, 2, { 0x62a, 0x631 } },
+ { 0xfc71, 2, { 0x62a, 0x632 } },
+ { 0xfc72, 2, { 0x62a, 0x645 } },
+ { 0xfc73, 2, { 0x62a, 0x646 } },
+ { 0xfc74, 2, { 0x62a, 0x649 } },
+ { 0xfc75, 2, { 0x62a, 0x64a } },
+ { 0xfc76, 2, { 0x62b, 0x631 } },
+ { 0xfc77, 2, { 0x62b, 0x632 } },
+ { 0xfc78, 2, { 0x62b, 0x645 } },
+ { 0xfc79, 2, { 0x62b, 0x646 } },
+ { 0xfc7a, 2, { 0x62b, 0x649 } },
+ { 0xfc7b, 2, { 0x62b, 0x64a } },
+ { 0xfc7c, 2, { 0x641, 0x649 } },
+ { 0xfc7d, 2, { 0x641, 0x64a } },
+ { 0xfc7e, 2, { 0x642, 0x649 } },
+ { 0xfc7f, 2, { 0x642, 0x64a } },
+ { 0xfc80, 2, { 0x643, 0x627 } },
+ { 0xfc81, 2, { 0x643, 0x644 } },
+ { 0xfc82, 2, { 0x643, 0x645 } },
+ { 0xfc83, 2, { 0x643, 0x649 } },
+ { 0xfc84, 2, { 0x643, 0x64a } },
+ { 0xfc85, 2, { 0x644, 0x645 } },
+ { 0xfc86, 2, { 0x644, 0x649 } },
+ { 0xfc87, 2, { 0x644, 0x64a } },
+ { 0xfc88, 2, { 0x645, 0x627 } },
+ { 0xfc89, 2, { 0x645, 0x645 } },
+ { 0xfc8a, 2, { 0x646, 0x631 } },
+ { 0xfc8b, 2, { 0x646, 0x632 } },
+ { 0xfc8c, 2, { 0x646, 0x645 } },
+ { 0xfc8d, 2, { 0x646, 0x646 } },
+ { 0xfc8e, 2, { 0x646, 0x649 } },
+ { 0xfc8f, 2, { 0x646, 0x64a } },
+ { 0xfc90, 2, { 0x649, 0x670 } },
+ { 0xfc91, 2, { 0x64a, 0x631 } },
+ { 0xfc92, 2, { 0x64a, 0x632 } },
+ { 0xfc93, 2, { 0x64a, 0x645 } },
+ { 0xfc94, 2, { 0x64a, 0x646 } },
+ { 0xfc95, 2, { 0x64a, 0x649 } },
+ { 0xfc96, 2, { 0x64a, 0x64a } },
+ { 0xfc97, 2, { 0x626, 0x62c } },
+ { 0xfc98, 2, { 0x626, 0x62d } },
+ { 0xfc99, 2, { 0x626, 0x62e } },
+ { 0xfc9a, 2, { 0x626, 0x645 } },
+ { 0xfc9b, 2, { 0x626, 0x647 } },
+ { 0xfc9c, 2, { 0x628, 0x62c } },
+ { 0xfc9d, 2, { 0x628, 0x62d } },
+ { 0xfc9e, 2, { 0x628, 0x62e } },
+ { 0xfc9f, 2, { 0x628, 0x645 } },
+ { 0xfca0, 2, { 0x628, 0x647 } },
+ { 0xfca1, 2, { 0x62a, 0x62c } },
+ { 0xfca2, 2, { 0x62a, 0x62d } },
+ { 0xfca3, 2, { 0x62a, 0x62e } },
+ { 0xfca4, 2, { 0x62a, 0x645 } },
+ { 0xfca5, 2, { 0x62a, 0x647 } },
+ { 0xfca6, 2, { 0x62b, 0x645 } },
+ { 0xfca7, 2, { 0x62c, 0x62d } },
+ { 0xfca8, 2, { 0x62c, 0x645 } },
+ { 0xfca9, 2, { 0x62d, 0x62c } },
+ { 0xfcaa, 2, { 0x62d, 0x645 } },
+ { 0xfcab, 2, { 0x62e, 0x62c } },
+ { 0xfcac, 2, { 0x62e, 0x645 } },
+ { 0xfcad, 2, { 0x633, 0x62c } },
+ { 0xfcae, 2, { 0x633, 0x62d } },
+ { 0xfcaf, 2, { 0x633, 0x62e } },
+ { 0xfcb0, 2, { 0x633, 0x645 } },
+ { 0xfcb1, 2, { 0x635, 0x62d } },
+ { 0xfcb2, 2, { 0x635, 0x62e } },
+ { 0xfcb3, 2, { 0x635, 0x645 } },
+ { 0xfcb4, 2, { 0x636, 0x62c } },
+ { 0xfcb5, 2, { 0x636, 0x62d } },
+ { 0xfcb6, 2, { 0x636, 0x62e } },
+ { 0xfcb7, 2, { 0x636, 0x645 } },
+ { 0xfcb8, 2, { 0x637, 0x62d } },
+ { 0xfcb9, 2, { 0x638, 0x645 } },
+ { 0xfcba, 2, { 0x639, 0x62c } },
+ { 0xfcbb, 2, { 0x639, 0x645 } },
+ { 0xfcbc, 2, { 0x63a, 0x62c } },
+ { 0xfcbd, 2, { 0x63a, 0x645 } },
+ { 0xfcbe, 2, { 0x641, 0x62c } },
+ { 0xfcbf, 2, { 0x641, 0x62d } },
+ { 0xfcc0, 2, { 0x641, 0x62e } },
+ { 0xfcc1, 2, { 0x641, 0x645 } },
+ { 0xfcc2, 2, { 0x642, 0x62d } },
+ { 0xfcc3, 2, { 0x642, 0x645 } },
+ { 0xfcc4, 2, { 0x643, 0x62c } },
+ { 0xfcc5, 2, { 0x643, 0x62d } },
+ { 0xfcc6, 2, { 0x643, 0x62e } },
+ { 0xfcc7, 2, { 0x643, 0x644 } },
+ { 0xfcc8, 2, { 0x643, 0x645 } },
+ { 0xfcc9, 2, { 0x644, 0x62c } },
+ { 0xfcca, 2, { 0x644, 0x62d } },
+ { 0xfccb, 2, { 0x644, 0x62e } },
+ { 0xfccc, 2, { 0x644, 0x645 } },
+ { 0xfccd, 2, { 0x644, 0x647 } },
+ { 0xfcce, 2, { 0x645, 0x62c } },
+ { 0xfccf, 2, { 0x645, 0x62d } },
+ { 0xfcd0, 2, { 0x645, 0x62e } },
+ { 0xfcd1, 2, { 0x645, 0x645 } },
+ { 0xfcd2, 2, { 0x646, 0x62c } },
+ { 0xfcd3, 2, { 0x646, 0x62d } },
+ { 0xfcd4, 2, { 0x646, 0x62e } },
+ { 0xfcd5, 2, { 0x646, 0x645 } },
+ { 0xfcd6, 2, { 0x646, 0x647 } },
+ { 0xfcd7, 2, { 0x647, 0x62c } },
+ { 0xfcd8, 2, { 0x647, 0x645 } },
+ { 0xfcd9, 2, { 0x647, 0x670 } },
+ { 0xfcda, 2, { 0x64a, 0x62c } },
+ { 0xfcdb, 2, { 0x64a, 0x62d } },
+ { 0xfcdc, 2, { 0x64a, 0x62e } },
+ { 0xfcdd, 2, { 0x64a, 0x645 } },
+ { 0xfcde, 2, { 0x64a, 0x647 } },
+ { 0xfcdf, 2, { 0x626, 0x645 } },
+ { 0xfce0, 2, { 0x626, 0x647 } },
+ { 0xfce1, 2, { 0x628, 0x645 } },
+ { 0xfce2, 2, { 0x628, 0x647 } },
+ { 0xfce3, 2, { 0x62a, 0x645 } },
+ { 0xfce4, 2, { 0x62a, 0x647 } },
+ { 0xfce5, 2, { 0x62b, 0x645 } },
+ { 0xfce6, 2, { 0x62b, 0x647 } },
+ { 0xfce7, 2, { 0x633, 0x645 } },
+ { 0xfce8, 2, { 0x633, 0x647 } },
+ { 0xfce9, 2, { 0x634, 0x645 } },
+ { 0xfcea, 2, { 0x634, 0x647 } },
+ { 0xfceb, 2, { 0x643, 0x644 } },
+ { 0xfcec, 2, { 0x643, 0x645 } },
+ { 0xfced, 2, { 0x644, 0x645 } },
+ { 0xfcee, 2, { 0x646, 0x645 } },
+ { 0xfcef, 2, { 0x646, 0x647 } },
+ { 0xfcf0, 2, { 0x64a, 0x645 } },
+ { 0xfcf1, 2, { 0x64a, 0x647 } },
+ { 0xfcf2, 3, { 426, 0 } },
+ { 0xfcf3, 3, { 351, 0 } },
+ { 0xfcf4, 3, { 746, 0 } },
+ { 0xfcf5, 2, { 0x637, 0x649 } },
+ { 0xfcf6, 2, { 0x637, 0x64a } },
+ { 0xfcf7, 2, { 0x639, 0x649 } },
+ { 0xfcf8, 2, { 0x639, 0x64a } },
+ { 0xfcf9, 2, { 0x63a, 0x649 } },
+ { 0xfcfa, 2, { 0x63a, 0x64a } },
+ { 0xfcfb, 2, { 0x633, 0x649 } },
+ { 0xfcfc, 2, { 0x633, 0x64a } },
+ { 0xfcfd, 2, { 0x634, 0x649 } },
+ { 0xfcfe, 2, { 0x634, 0x64a } },
+ { 0xfcff, 2, { 0x62d, 0x649 } },
+ { 0xfd00, 2, { 0x62d, 0x64a } },
+ { 0xfd01, 2, { 0x62c, 0x649 } },
+ { 0xfd02, 2, { 0x62c, 0x64a } },
+ { 0xfd03, 2, { 0x62e, 0x649 } },
+ { 0xfd04, 2, { 0x62e, 0x64a } },
+ { 0xfd05, 2, { 0x635, 0x649 } },
+ { 0xfd06, 2, { 0x635, 0x64a } },
+ { 0xfd07, 2, { 0x636, 0x649 } },
+ { 0xfd08, 2, { 0x636, 0x64a } },
+ { 0xfd09, 2, { 0x634, 0x62c } },
+ { 0xfd0a, 2, { 0x634, 0x62d } },
+ { 0xfd0b, 2, { 0x634, 0x62e } },
+ { 0xfd0c, 2, { 0x634, 0x645 } },
+ { 0xfd0d, 2, { 0x634, 0x631 } },
+ { 0xfd0e, 2, { 0x633, 0x631 } },
+ { 0xfd0f, 2, { 0x635, 0x631 } },
+ { 0xfd10, 2, { 0x636, 0x631 } },
+ { 0xfd11, 2, { 0x637, 0x649 } },
+ { 0xfd12, 2, { 0x637, 0x64a } },
+ { 0xfd13, 2, { 0x639, 0x649 } },
+ { 0xfd14, 2, { 0x639, 0x64a } },
+ { 0xfd15, 2, { 0x63a, 0x649 } },
+ { 0xfd16, 2, { 0x63a, 0x64a } },
+ { 0xfd17, 2, { 0x633, 0x649 } },
+ { 0xfd18, 2, { 0x633, 0x64a } },
+ { 0xfd19, 2, { 0x634, 0x649 } },
+ { 0xfd1a, 2, { 0x634, 0x64a } },
+ { 0xfd1b, 2, { 0x62d, 0x649 } },
+ { 0xfd1c, 2, { 0x62d, 0x64a } },
+ { 0xfd1d, 2, { 0x62c, 0x649 } },
+ { 0xfd1e, 2, { 0x62c, 0x64a } },
+ { 0xfd1f, 2, { 0x62e, 0x649 } },
+ { 0xfd20, 2, { 0x62e, 0x64a } },
+ { 0xfd21, 2, { 0x635, 0x649 } },
+ { 0xfd22, 2, { 0x635, 0x64a } },
+ { 0xfd23, 2, { 0x636, 0x649 } },
+ { 0xfd24, 2, { 0x636, 0x64a } },
+ { 0xfd25, 2, { 0x634, 0x62c } },
+ { 0xfd26, 2, { 0x634, 0x62d } },
+ { 0xfd27, 2, { 0x634, 0x62e } },
+ { 0xfd28, 2, { 0x634, 0x645 } },
+ { 0xfd29, 2, { 0x634, 0x631 } },
+ { 0xfd2a, 2, { 0x633, 0x631 } },
+ { 0xfd2b, 2, { 0x635, 0x631 } },
+ { 0xfd2c, 2, { 0x636, 0x631 } },
+ { 0xfd2d, 2, { 0x634, 0x62c } },
+ { 0xfd2e, 2, { 0x634, 0x62d } },
+ { 0xfd2f, 2, { 0x634, 0x62e } },
+ { 0xfd30, 2, { 0x634, 0x645 } },
+ { 0xfd31, 2, { 0x633, 0x647 } },
+ { 0xfd32, 2, { 0x634, 0x647 } },
+ { 0xfd33, 2, { 0x637, 0x645 } },
+ { 0xfd34, 2, { 0x633, 0x62c } },
+ { 0xfd35, 2, { 0x633, 0x62d } },
+ { 0xfd36, 2, { 0x633, 0x62e } },
+ { 0xfd37, 2, { 0x634, 0x62c } },
+ { 0xfd38, 2, { 0x634, 0x62d } },
+ { 0xfd39, 2, { 0x634, 0x62e } },
+ { 0xfd3a, 2, { 0x637, 0x645 } },
+ { 0xfd3b, 2, { 0x638, 0x645 } },
+ { 0xfd3c, 2, { 0x627, 0x64b } },
+ { 0xfd3d, 2, { 0x627, 0x64b } },
+ { 0xfd50, 3, { 115, 0 } },
+ { 0xfd51, 3, { 513, 0 } },
+ { 0xfd52, 3, { 513, 0 } },
+ { 0xfd53, 3, { 121, 0 } },
+ { 0xfd54, 3, { 516, 0 } },
+ { 0xfd55, 3, { 127, 0 } },
+ { 0xfd56, 3, { 522, 0 } },
+ { 0xfd57, 3, { 531, 0 } },
+ { 0xfd58, 3, { 358, 0 } },
+ { 0xfd59, 3, { 358, 0 } },
+ { 0xfd5a, 3, { 336, 0 } },
+ { 0xfd5b, 3, { 411, 0 } },
+ { 0xfd5c, 3, { 361, 0 } },
+ { 0xfd5d, 3, { 538, 0 } },
+ { 0xfd5e, 3, { 389, 0 } },
+ { 0xfd5f, 3, { 414, 0 } },
+ { 0xfd60, 3, { 414, 0 } },
+ { 0xfd61, 3, { 552, 0 } },
+ { 0xfd62, 3, { 339, 0 } },
+ { 0xfd63, 3, { 339, 0 } },
+ { 0xfd64, 3, { 417, 0 } },
+ { 0xfd65, 3, { 417, 0 } },
+ { 0xfd66, 3, { 367, 0 } },
+ { 0xfd67, 3, { 392, 0 } },
+ { 0xfd68, 3, { 392, 0 } },
+ { 0xfd69, 3, { 541, 0 } },
+ { 0xfd6a, 3, { 588, 0 } },
+ { 0xfd6b, 3, { 588, 0 } },
+ { 0xfd6c, 3, { 560, 0 } },
+ { 0xfd6d, 3, { 560, 0 } },
+ { 0xfd6e, 3, { 563, 0 } },
+ { 0xfd6f, 3, { 345, 0 } },
+ { 0xfd70, 3, { 345, 0 } },
+ { 0xfd71, 3, { 547, 0 } },
+ { 0xfd72, 3, { 547, 0 } },
+ { 0xfd73, 3, { 398, 0 } },
+ { 0xfd74, 3, { 370, 0 } },
+ { 0xfd75, 3, { 566, 0 } },
+ { 0xfd76, 3, { 423, 0 } },
+ { 0xfd77, 3, { 423, 0 } },
+ { 0xfd78, 3, { 348, 0 } },
+ { 0xfd79, 3, { 401, 0 } },
+ { 0xfd7a, 3, { 569, 0 } },
+ { 0xfd7b, 3, { 373, 0 } },
+ { 0xfd7c, 3, { 404, 0 } },
+ { 0xfd7d, 3, { 404, 0 } },
+ { 0xfd7e, 3, { 429, 0 } },
+ { 0xfd7f, 3, { 354, 0 } },
+ { 0xfd80, 3, { 410, 0 } },
+ { 0xfd81, 3, { 578, 0 } },
+ { 0xfd82, 3, { 382, 0 } },
+ { 0xfd83, 3, { 575, 0 } },
+ { 0xfd84, 3, { 575, 0 } },
+ { 0xfd85, 3, { 755, 0 } },
+ { 0xfd86, 3, { 755, 0 } },
+ { 0xfd87, 3, { 736, 0 } },
+ { 0xfd88, 3, { 736, 0 } },
+ { 0xfd89, 3, { 548, 0 } },
+ { 0xfd8a, 3, { 737, 0 } },
+ { 0xfd8b, 3, { 430, 0 } },
+ { 0xfd8c, 3, { 534, 0 } },
+ { 0xfd8d, 3, { 553, 0 } },
+ { 0xfd8e, 3, { 849, 0 } },
+ { 0xfd8f, 3, { 532, 0 } },
+ { 0xfd92, 3, { 128, 0 } },
+ { 0xfd93, 3, { 331, 0 } },
+ { 0xfd94, 3, { 847, 0 } },
+ { 0xfd95, 3, { 335, 0 } },
+ { 0xfd96, 3, { 131, 0 } },
+ { 0xfd97, 3, { 581, 0 } },
+ { 0xfd98, 3, { 581, 0 } },
+ { 0xfd99, 3, { 804, 0 } },
+ { 0xfd9a, 3, { 592, 0 } },
+ { 0xfd9b, 3, { 852, 0 } },
+ { 0xfd9c, 3, { 600, 0 } },
+ { 0xfd9d, 3, { 600, 0 } },
+ { 0xfd9e, 3, { 507, 0 } },
+ { 0xfd9f, 3, { 118, 0 } },
+ { 0xfda0, 3, { 510, 0 } },
+ { 0xfda1, 3, { 519, 0 } },
+ { 0xfda2, 3, { 124, 0 } },
+ { 0xfda3, 3, { 525, 0 } },
+ { 0xfda4, 3, { 528, 0 } },
+ { 0xfda5, 3, { 582, 0 } },
+ { 0xfda6, 3, { 535, 0 } },
+ { 0xfda7, 3, { 554, 0 } },
+ { 0xfda8, 3, { 585, 0 } },
+ { 0xfda9, 3, { 342, 0 } },
+ { 0xfdaa, 3, { 364, 0 } },
+ { 0xfdab, 3, { 420, 0 } },
+ { 0xfdac, 3, { 752, 0 } },
+ { 0xfdad, 3, { 801, 0 } },
+ { 0xfdae, 3, { 596, 0 } },
+ { 0xfdaf, 3, { 594, 0 } },
+ { 0xfdb0, 3, { 598, 0 } },
+ { 0xfdb1, 3, { 601, 0 } },
+ { 0xfdb2, 3, { 749, 0 } },
+ { 0xfdb3, 3, { 433, 0 } },
+ { 0xfdb4, 3, { 429, 0 } },
+ { 0xfdb5, 3, { 410, 0 } },
+ { 0xfdb6, 3, { 743, 0 } },
+ { 0xfdb7, 3, { 379, 0 } },
+ { 0xfdb8, 3, { 385, 0 } },
+ { 0xfdb9, 3, { 589, 0 } },
+ { 0xfdba, 3, { 357, 0 } },
+ { 0xfdbb, 3, { 407, 0 } },
+ { 0xfdbc, 3, { 357, 0 } },
+ { 0xfdbd, 3, { 385, 0 } },
+ { 0xfdbe, 3, { 386, 0 } },
+ { 0xfdbf, 3, { 549, 0 } },
+ { 0xfdc0, 3, { 332, 0 } },
+ { 0xfdc1, 3, { 376, 0 } },
+ { 0xfdc2, 3, { 112, 0 } },
+ { 0xfdc3, 3, { 407, 0 } },
+ { 0xfdc4, 3, { 566, 0 } },
+ { 0xfdc5, 3, { 367, 0 } },
+ { 0xfdc6, 3, { 557, 0 } },
+ { 0xfdc7, 3, { 758, 0 } },
+ { 0xfdf0, 3, { 395, 0 } },
+ { 0xfdf1, 3, { 572, 0 } },
+ { 0xfdf2, 4, { 328, 0 } },
+ { 0xfdf3, 4, { 323, 0 } },
+ { 0xfdf4, 4, { 737, 0 } },
+ { 0xfdf5, 4, { 741, 0 } },
+ { 0xfdf6, 4, { 733, 0 } },
+ { 0xfdf7, 4, { 844, 0 } },
+ { 0xfdf8, 4, { 799, 0 } },
+ { 0xfdf9, 3, { 544, 0 } },
+ { 0xfdfc, 4, { 326, 0 } },
+ { 0xfe11, 1, { 0x3001, 0 } },
+ { 0xfe17, 1, { 0x3016, 0 } },
+ { 0xfe18, 1, { 0x3017, 0 } },
+ { 0xfe31, 1, { 0x2014, 0 } },
+ { 0xfe32, 1, { 0x2013, 0 } },
+ { 0xfe33, 1, { 0x5f, 0 } },
+ { 0xfe34, 1, { 0x5f, 0 } },
+ { 0xfe39, 1, { 0x3014, 0 } },
+ { 0xfe3a, 1, { 0x3015, 0 } },
+ { 0xfe3b, 1, { 0x3010, 0 } },
+ { 0xfe3c, 1, { 0x3011, 0 } },
+ { 0xfe3d, 1, { 0x300a, 0 } },
+ { 0xfe3e, 1, { 0x300b, 0 } },
+ { 0xfe3f, 1, { 0x3008, 0 } },
+ { 0xfe40, 1, { 0x3009, 0 } },
+ { 0xfe41, 1, { 0x300c, 0 } },
+ { 0xfe42, 1, { 0x300d, 0 } },
+ { 0xfe43, 1, { 0x300e, 0 } },
+ { 0xfe44, 1, { 0x300f, 0 } },
+ { 0xfe4d, 1, { 0x5f, 0 } },
+ { 0xfe4e, 1, { 0x5f, 0 } },
+ { 0xfe4f, 1, { 0x5f, 0 } },
+ { 0xfe51, 1, { 0x3001, 0 } },
+ { 0xfe58, 1, { 0x2014, 0 } },
+ { 0xfe5d, 1, { 0x3014, 0 } },
+ { 0xfe5e, 1, { 0x3015, 0 } },
+ { 0xfe63, 1, { 0x2d, 0 } },
+ { 0xfe71, 2, { 0x640, 0x64b } },
+ { 0xfe77, 2, { 0x640, 0x64e } },
+ { 0xfe79, 2, { 0x640, 0x64f } },
+ { 0xfe7b, 2, { 0x640, 0x650 } },
+ { 0xfe7d, 2, { 0x640, 0x651 } },
+ { 0xfe7f, 2, { 0x640, 0x652 } },
+ { 0xfe80, 1, { 0x621, 0 } },
+ { 0xfe81, 1, { 0x622, 0 } },
+ { 0xfe82, 1, { 0x622, 0 } },
+ { 0xfe83, 1, { 0x623, 0 } },
+ { 0xfe84, 1, { 0x623, 0 } },
+ { 0xfe85, 1, { 0x624, 0 } },
+ { 0xfe86, 1, { 0x624, 0 } },
+ { 0xfe87, 1, { 0x625, 0 } },
+ { 0xfe88, 1, { 0x625, 0 } },
+ { 0xfe89, 1, { 0x626, 0 } },
+ { 0xfe8a, 1, { 0x626, 0 } },
+ { 0xfe8b, 1, { 0x626, 0 } },
+ { 0xfe8c, 1, { 0x626, 0 } },
+ { 0xfe8d, 1, { 0x627, 0 } },
+ { 0xfe8e, 1, { 0x627, 0 } },
+ { 0xfe8f, 1, { 0x628, 0 } },
+ { 0xfe90, 1, { 0x628, 0 } },
+ { 0xfe91, 1, { 0x628, 0 } },
+ { 0xfe92, 1, { 0x628, 0 } },
+ { 0xfe93, 1, { 0x629, 0 } },
+ { 0xfe94, 1, { 0x629, 0 } },
+ { 0xfe95, 1, { 0x62a, 0 } },
+ { 0xfe96, 1, { 0x62a, 0 } },
+ { 0xfe97, 1, { 0x62a, 0 } },
+ { 0xfe98, 1, { 0x62a, 0 } },
+ { 0xfe99, 1, { 0x62b, 0 } },
+ { 0xfe9a, 1, { 0x62b, 0 } },
+ { 0xfe9b, 1, { 0x62b, 0 } },
+ { 0xfe9c, 1, { 0x62b, 0 } },
+ { 0xfe9d, 1, { 0x62c, 0 } },
+ { 0xfe9e, 1, { 0x62c, 0 } },
+ { 0xfe9f, 1, { 0x62c, 0 } },
+ { 0xfea0, 1, { 0x62c, 0 } },
+ { 0xfea1, 1, { 0x62d, 0 } },
+ { 0xfea2, 1, { 0x62d, 0 } },
+ { 0xfea3, 1, { 0x62d, 0 } },
+ { 0xfea4, 1, { 0x62d, 0 } },
+ { 0xfea5, 1, { 0x62e, 0 } },
+ { 0xfea6, 1, { 0x62e, 0 } },
+ { 0xfea7, 1, { 0x62e, 0 } },
+ { 0xfea8, 1, { 0x62e, 0 } },
+ { 0xfea9, 1, { 0x62f, 0 } },
+ { 0xfeaa, 1, { 0x62f, 0 } },
+ { 0xfeab, 1, { 0x630, 0 } },
+ { 0xfeac, 1, { 0x630, 0 } },
+ { 0xfead, 1, { 0x631, 0 } },
+ { 0xfeae, 1, { 0x631, 0 } },
+ { 0xfeaf, 1, { 0x632, 0 } },
+ { 0xfeb0, 1, { 0x632, 0 } },
+ { 0xfeb1, 1, { 0x633, 0 } },
+ { 0xfeb2, 1, { 0x633, 0 } },
+ { 0xfeb3, 1, { 0x633, 0 } },
+ { 0xfeb4, 1, { 0x633, 0 } },
+ { 0xfeb5, 1, { 0x634, 0 } },
+ { 0xfeb6, 1, { 0x634, 0 } },
+ { 0xfeb7, 1, { 0x634, 0 } },
+ { 0xfeb8, 1, { 0x634, 0 } },
+ { 0xfeb9, 1, { 0x635, 0 } },
+ { 0xfeba, 1, { 0x635, 0 } },
+ { 0xfebb, 1, { 0x635, 0 } },
+ { 0xfebc, 1, { 0x635, 0 } },
+ { 0xfebd, 1, { 0x636, 0 } },
+ { 0xfebe, 1, { 0x636, 0 } },
+ { 0xfebf, 1, { 0x636, 0 } },
+ { 0xfec0, 1, { 0x636, 0 } },
+ { 0xfec1, 1, { 0x637, 0 } },
+ { 0xfec2, 1, { 0x637, 0 } },
+ { 0xfec3, 1, { 0x637, 0 } },
+ { 0xfec4, 1, { 0x637, 0 } },
+ { 0xfec5, 1, { 0x638, 0 } },
+ { 0xfec6, 1, { 0x638, 0 } },
+ { 0xfec7, 1, { 0x638, 0 } },
+ { 0xfec8, 1, { 0x638, 0 } },
+ { 0xfec9, 1, { 0x639, 0 } },
+ { 0xfeca, 1, { 0x639, 0 } },
+ { 0xfecb, 1, { 0x639, 0 } },
+ { 0xfecc, 1, { 0x639, 0 } },
+ { 0xfecd, 1, { 0x63a, 0 } },
+ { 0xfece, 1, { 0x63a, 0 } },
+ { 0xfecf, 1, { 0x63a, 0 } },
+ { 0xfed0, 1, { 0x63a, 0 } },
+ { 0xfed1, 1, { 0x641, 0 } },
+ { 0xfed2, 1, { 0x641, 0 } },
+ { 0xfed3, 1, { 0x641, 0 } },
+ { 0xfed4, 1, { 0x641, 0 } },
+ { 0xfed5, 1, { 0x642, 0 } },
+ { 0xfed6, 1, { 0x642, 0 } },
+ { 0xfed7, 1, { 0x642, 0 } },
+ { 0xfed8, 1, { 0x642, 0 } },
+ { 0xfed9, 1, { 0x643, 0 } },
+ { 0xfeda, 1, { 0x643, 0 } },
+ { 0xfedb, 1, { 0x643, 0 } },
+ { 0xfedc, 1, { 0x643, 0 } },
+ { 0xfedd, 1, { 0x644, 0 } },
+ { 0xfede, 1, { 0x644, 0 } },
+ { 0xfedf, 1, { 0x644, 0 } },
+ { 0xfee0, 1, { 0x644, 0 } },
+ { 0xfee1, 1, { 0x645, 0 } },
+ { 0xfee2, 1, { 0x645, 0 } },
+ { 0xfee3, 1, { 0x645, 0 } },
+ { 0xfee4, 1, { 0x645, 0 } },
+ { 0xfee5, 1, { 0x646, 0 } },
+ { 0xfee6, 1, { 0x646, 0 } },
+ { 0xfee7, 1, { 0x646, 0 } },
+ { 0xfee8, 1, { 0x646, 0 } },
+ { 0xfee9, 1, { 0x647, 0 } },
+ { 0xfeea, 1, { 0x647, 0 } },
+ { 0xfeeb, 1, { 0x647, 0 } },
+ { 0xfeec, 1, { 0x647, 0 } },
+ { 0xfeed, 1, { 0x648, 0 } },
+ { 0xfeee, 1, { 0x648, 0 } },
+ { 0xfeef, 1, { 0x649, 0 } },
+ { 0xfef0, 1, { 0x649, 0 } },
+ { 0xfef1, 1, { 0x64a, 0 } },
+ { 0xfef2, 1, { 0x64a, 0 } },
+ { 0xfef3, 1, { 0x64a, 0 } },
+ { 0xfef4, 1, { 0x64a, 0 } },
+ { 0xfef5, 2, { 0x644, 0x622 } },
+ { 0xfef6, 2, { 0x644, 0x622 } },
+ { 0xfef7, 2, { 0x644, 0x623 } },
+ { 0xfef8, 2, { 0x644, 0x623 } },
+ { 0xfef9, 2, { 0x644, 0x625 } },
+ { 0xfefa, 2, { 0x644, 0x625 } },
+ { 0xfefb, 2, { 0x644, 0x627 } },
+ { 0xfefc, 2, { 0x644, 0x627 } },
+ { 0xff0d, 1, { 0x2d, 0 } },
+ { 0xff0e, 1, { 0x2e, 0 } },
+ { 0xff10, 1, { 0x30, 0 } },
+ { 0xff11, 1, { 0x31, 0 } },
+ { 0xff12, 1, { 0x32, 0 } },
+ { 0xff13, 1, { 0x33, 0 } },
+ { 0xff14, 1, { 0x34, 0 } },
+ { 0xff15, 1, { 0x35, 0 } },
+ { 0xff16, 1, { 0x36, 0 } },
+ { 0xff17, 1, { 0x37, 0 } },
+ { 0xff18, 1, { 0x38, 0 } },
+ { 0xff19, 1, { 0x39, 0 } },
+ { 0xff21, 1, { 0x61, 0 } },
+ { 0xff22, 1, { 0x62, 0 } },
+ { 0xff23, 1, { 0x63, 0 } },
+ { 0xff24, 1, { 0x64, 0 } },
+ { 0xff25, 1, { 0x65, 0 } },
+ { 0xff26, 1, { 0x66, 0 } },
+ { 0xff27, 1, { 0x67, 0 } },
+ { 0xff28, 1, { 0x68, 0 } },
+ { 0xff29, 1, { 0x69, 0 } },
+ { 0xff2a, 1, { 0x6a, 0 } },
+ { 0xff2b, 1, { 0x6b, 0 } },
+ { 0xff2c, 1, { 0x6c, 0 } },
+ { 0xff2d, 1, { 0x6d, 0 } },
+ { 0xff2e, 1, { 0x6e, 0 } },
+ { 0xff2f, 1, { 0x6f, 0 } },
+ { 0xff30, 1, { 0x70, 0 } },
+ { 0xff31, 1, { 0x71, 0 } },
+ { 0xff32, 1, { 0x72, 0 } },
+ { 0xff33, 1, { 0x73, 0 } },
+ { 0xff34, 1, { 0x74, 0 } },
+ { 0xff35, 1, { 0x75, 0 } },
+ { 0xff36, 1, { 0x76, 0 } },
+ { 0xff37, 1, { 0x77, 0 } },
+ { 0xff38, 1, { 0x78, 0 } },
+ { 0xff39, 1, { 0x79, 0 } },
+ { 0xff3a, 1, { 0x7a, 0 } },
+ { 0xff3f, 1, { 0x5f, 0 } },
+ { 0xff41, 1, { 0x61, 0 } },
+ { 0xff42, 1, { 0x62, 0 } },
+ { 0xff43, 1, { 0x63, 0 } },
+ { 0xff44, 1, { 0x64, 0 } },
+ { 0xff45, 1, { 0x65, 0 } },
+ { 0xff46, 1, { 0x66, 0 } },
+ { 0xff47, 1, { 0x67, 0 } },
+ { 0xff48, 1, { 0x68, 0 } },
+ { 0xff49, 1, { 0x69, 0 } },
+ { 0xff4a, 1, { 0x6a, 0 } },
+ { 0xff4b, 1, { 0x6b, 0 } },
+ { 0xff4c, 1, { 0x6c, 0 } },
+ { 0xff4d, 1, { 0x6d, 0 } },
+ { 0xff4e, 1, { 0x6e, 0 } },
+ { 0xff4f, 1, { 0x6f, 0 } },
+ { 0xff50, 1, { 0x70, 0 } },
+ { 0xff51, 1, { 0x71, 0 } },
+ { 0xff52, 1, { 0x72, 0 } },
+ { 0xff53, 1, { 0x73, 0 } },
+ { 0xff54, 1, { 0x74, 0 } },
+ { 0xff55, 1, { 0x75, 0 } },
+ { 0xff56, 1, { 0x76, 0 } },
+ { 0xff57, 1, { 0x77, 0 } },
+ { 0xff58, 1, { 0x78, 0 } },
+ { 0xff59, 1, { 0x79, 0 } },
+ { 0xff5a, 1, { 0x7a, 0 } },
+ { 0xff5f, 1, { 0x2985, 0 } },
+ { 0xff60, 1, { 0x2986, 0 } },
+ { 0xff61, 1, { 0x2e, 0 } },
+ { 0xff62, 1, { 0x300c, 0 } },
+ { 0xff63, 1, { 0x300d, 0 } },
+ { 0xff64, 1, { 0x3001, 0 } },
+ { 0xff65, 1, { 0x30fb, 0 } },
+ { 0xff66, 1, { 0x30f2, 0 } },
+ { 0xff67, 1, { 0x30a1, 0 } },
+ { 0xff68, 1, { 0x30a3, 0 } },
+ { 0xff69, 1, { 0x30a5, 0 } },
+ { 0xff6a, 1, { 0x30a7, 0 } },
+ { 0xff6b, 1, { 0x30a9, 0 } },
+ { 0xff6c, 1, { 0x30e3, 0 } },
+ { 0xff6d, 1, { 0x30e5, 0 } },
+ { 0xff6e, 1, { 0x30e7, 0 } },
+ { 0xff6f, 1, { 0x30c3, 0 } },
+ { 0xff70, 1, { 0x30fc, 0 } },
+ { 0xff71, 1, { 0x30a2, 0 } },
+ { 0xff72, 1, { 0x30a4, 0 } },
+ { 0xff73, 1, { 0x30a6, 0 } },
+ { 0xff74, 1, { 0x30a8, 0 } },
+ { 0xff75, 1, { 0x30aa, 0 } },
+ { 0xff76, 1, { 0x30ab, 0 } },
+ { 0xff77, 1, { 0x30ad, 0 } },
+ { 0xff78, 1, { 0x30af, 0 } },
+ { 0xff79, 1, { 0x30b1, 0 } },
+ { 0xff7a, 1, { 0x30b3, 0 } },
+ { 0xff7b, 1, { 0x30b5, 0 } },
+ { 0xff7c, 1, { 0x30b7, 0 } },
+ { 0xff7d, 1, { 0x30b9, 0 } },
+ { 0xff7e, 1, { 0x30bb, 0 } },
+ { 0xff7f, 1, { 0x30bd, 0 } },
+ { 0xff80, 1, { 0x30bf, 0 } },
+ { 0xff81, 1, { 0x30c1, 0 } },
+ { 0xff82, 1, { 0x30c4, 0 } },
+ { 0xff83, 1, { 0x30c6, 0 } },
+ { 0xff84, 1, { 0x30c8, 0 } },
+ { 0xff85, 1, { 0x30ca, 0 } },
+ { 0xff86, 1, { 0x30cb, 0 } },
+ { 0xff87, 1, { 0x30cc, 0 } },
+ { 0xff88, 1, { 0x30cd, 0 } },
+ { 0xff89, 1, { 0x30ce, 0 } },
+ { 0xff8a, 1, { 0x30cf, 0 } },
+ { 0xff8b, 1, { 0x30d2, 0 } },
+ { 0xff8c, 1, { 0x30d5, 0 } },
+ { 0xff8d, 1, { 0x30d8, 0 } },
+ { 0xff8e, 1, { 0x30db, 0 } },
+ { 0xff8f, 1, { 0x30de, 0 } },
+ { 0xff90, 1, { 0x30df, 0 } },
+ { 0xff91, 1, { 0x30e0, 0 } },
+ { 0xff92, 1, { 0x30e1, 0 } },
+ { 0xff93, 1, { 0x30e2, 0 } },
+ { 0xff94, 1, { 0x30e4, 0 } },
+ { 0xff95, 1, { 0x30e6, 0 } },
+ { 0xff96, 1, { 0x30e8, 0 } },
+ { 0xff97, 1, { 0x30e9, 0 } },
+ { 0xff98, 1, { 0x30ea, 0 } },
+ { 0xff99, 1, { 0x30eb, 0 } },
+ { 0xff9a, 1, { 0x30ec, 0 } },
+ { 0xff9b, 1, { 0x30ed, 0 } },
+ { 0xff9c, 1, { 0x30ef, 0 } },
+ { 0xff9d, 1, { 0x30f3, 0 } },
+ { 0xff9e, 1, { 0x3099, 0 } },
+ { 0xff9f, 1, { 0x309a, 0 } },
+ { 0xffa1, 1, { 0x1100, 0 } },
+ { 0xffa2, 1, { 0x1101, 0 } },
+ { 0xffa3, 1, { 0x11aa, 0 } },
+ { 0xffa4, 1, { 0x1102, 0 } },
+ { 0xffa5, 1, { 0x11ac, 0 } },
+ { 0xffa6, 1, { 0x11ad, 0 } },
+ { 0xffa7, 1, { 0x1103, 0 } },
+ { 0xffa8, 1, { 0x1104, 0 } },
+ { 0xffa9, 1, { 0x1105, 0 } },
+ { 0xffaa, 1, { 0x11b0, 0 } },
+ { 0xffab, 1, { 0x11b1, 0 } },
+ { 0xffac, 1, { 0x11b2, 0 } },
+ { 0xffad, 1, { 0x11b3, 0 } },
+ { 0xffae, 1, { 0x11b4, 0 } },
+ { 0xffaf, 1, { 0x11b5, 0 } },
+ { 0xffb0, 1, { 0x111a, 0 } },
+ { 0xffb1, 1, { 0x1106, 0 } },
+ { 0xffb2, 1, { 0x1107, 0 } },
+ { 0xffb3, 1, { 0x1108, 0 } },
+ { 0xffb4, 1, { 0x1121, 0 } },
+ { 0xffb5, 1, { 0x1109, 0 } },
+ { 0xffb6, 1, { 0x110a, 0 } },
+ { 0xffb7, 1, { 0x110b, 0 } },
+ { 0xffb8, 1, { 0x110c, 0 } },
+ { 0xffb9, 1, { 0x110d, 0 } },
+ { 0xffba, 1, { 0x110e, 0 } },
+ { 0xffbb, 1, { 0x110f, 0 } },
+ { 0xffbc, 1, { 0x1110, 0 } },
+ { 0xffbd, 1, { 0x1111, 0 } },
+ { 0xffbe, 1, { 0x1112, 0 } },
+ { 0xffc2, 1, { 0x1161, 0 } },
+ { 0xffc3, 1, { 0x1162, 0 } },
+ { 0xffc4, 1, { 0x1163, 0 } },
+ { 0xffc5, 1, { 0x1164, 0 } },
+ { 0xffc6, 1, { 0x1165, 0 } },
+ { 0xffc7, 1, { 0x1166, 0 } },
+ { 0xffca, 1, { 0x1167, 0 } },
+ { 0xffcb, 1, { 0x1168, 0 } },
+ { 0xffcc, 1, { 0x1169, 0 } },
+ { 0xffcd, 1, { 0x116a, 0 } },
+ { 0xffce, 1, { 0x116b, 0 } },
+ { 0xffcf, 1, { 0x116c, 0 } },
+ { 0xffd2, 1, { 0x116d, 0 } },
+ { 0xffd3, 1, { 0x116e, 0 } },
+ { 0xffd4, 1, { 0x116f, 0 } },
+ { 0xffd5, 1, { 0x1170, 0 } },
+ { 0xffd6, 1, { 0x1171, 0 } },
+ { 0xffd7, 1, { 0x1172, 0 } },
+ { 0xffda, 1, { 0x1173, 0 } },
+ { 0xffdb, 1, { 0x1174, 0 } },
+ { 0xffdc, 1, { 0x1175, 0 } },
+ { 0xffe0, 1, { 0xa2, 0 } },
+ { 0xffe1, 1, { 0xa3, 0 } },
+ { 0xffe2, 1, { 0xac, 0 } },
+ { 0xffe4, 1, { 0xa6, 0 } },
+ { 0xffe5, 1, { 0xa5, 0 } },
+ { 0xffe6, 1, { 0x20a9, 0 } },
+ { 0xffe8, 1, { 0x2502, 0 } },
+ { 0xffe9, 1, { 0x2190, 0 } },
+ { 0xffea, 1, { 0x2191, 0 } },
+ { 0xffeb, 1, { 0x2192, 0 } },
+ { 0xffec, 1, { 0x2193, 0 } },
+ { 0xffed, 1, { 0x25a0, 0 } },
+ { 0xffee, 1, { 0x25cb, 0 } },
+ { 0x10400, 2, { 0xd801, 0xdc28 } },
+ { 0x10401, 2, { 0xd801, 0xdc29 } },
+ { 0x10402, 2, { 0xd801, 0xdc2a } },
+ { 0x10403, 2, { 0xd801, 0xdc2b } },
+ { 0x10404, 2, { 0xd801, 0xdc2c } },
+ { 0x10405, 2, { 0xd801, 0xdc2d } },
+ { 0x10406, 2, { 0xd801, 0xdc2e } },
+ { 0x10407, 2, { 0xd801, 0xdc2f } },
+ { 0x10408, 2, { 0xd801, 0xdc30 } },
+ { 0x10409, 2, { 0xd801, 0xdc31 } },
+ { 0x1040a, 2, { 0xd801, 0xdc32 } },
+ { 0x1040b, 2, { 0xd801, 0xdc33 } },
+ { 0x1040c, 2, { 0xd801, 0xdc34 } },
+ { 0x1040d, 2, { 0xd801, 0xdc35 } },
+ { 0x1040e, 2, { 0xd801, 0xdc36 } },
+ { 0x1040f, 2, { 0xd801, 0xdc37 } },
+ { 0x10410, 2, { 0xd801, 0xdc38 } },
+ { 0x10411, 2, { 0xd801, 0xdc39 } },
+ { 0x10412, 2, { 0xd801, 0xdc3a } },
+ { 0x10413, 2, { 0xd801, 0xdc3b } },
+ { 0x10414, 2, { 0xd801, 0xdc3c } },
+ { 0x10415, 2, { 0xd801, 0xdc3d } },
+ { 0x10416, 2, { 0xd801, 0xdc3e } },
+ { 0x10417, 2, { 0xd801, 0xdc3f } },
+ { 0x10418, 2, { 0xd801, 0xdc40 } },
+ { 0x10419, 2, { 0xd801, 0xdc41 } },
+ { 0x1041a, 2, { 0xd801, 0xdc42 } },
+ { 0x1041b, 2, { 0xd801, 0xdc43 } },
+ { 0x1041c, 2, { 0xd801, 0xdc44 } },
+ { 0x1041d, 2, { 0xd801, 0xdc45 } },
+ { 0x1041e, 2, { 0xd801, 0xdc46 } },
+ { 0x1041f, 2, { 0xd801, 0xdc47 } },
+ { 0x10420, 2, { 0xd801, 0xdc48 } },
+ { 0x10421, 2, { 0xd801, 0xdc49 } },
+ { 0x10422, 2, { 0xd801, 0xdc4a } },
+ { 0x10423, 2, { 0xd801, 0xdc4b } },
+ { 0x10424, 2, { 0xd801, 0xdc4c } },
+ { 0x10425, 2, { 0xd801, 0xdc4d } },
+ { 0x10426, 2, { 0xd801, 0xdc4e } },
+ { 0x10427, 2, { 0xd801, 0xdc4f } },
+ { 0x104b0, 2, { 0xd801, 0xdcd8 } },
+ { 0x104b1, 2, { 0xd801, 0xdcd9 } },
+ { 0x104b2, 2, { 0xd801, 0xdcda } },
+ { 0x104b3, 2, { 0xd801, 0xdcdb } },
+ { 0x104b4, 2, { 0xd801, 0xdcdc } },
+ { 0x104b5, 2, { 0xd801, 0xdcdd } },
+ { 0x104b6, 2, { 0xd801, 0xdcde } },
+ { 0x104b7, 2, { 0xd801, 0xdcdf } },
+ { 0x104b8, 2, { 0xd801, 0xdce0 } },
+ { 0x104b9, 2, { 0xd801, 0xdce1 } },
+ { 0x104ba, 2, { 0xd801, 0xdce2 } },
+ { 0x104bb, 2, { 0xd801, 0xdce3 } },
+ { 0x104bc, 2, { 0xd801, 0xdce4 } },
+ { 0x104bd, 2, { 0xd801, 0xdce5 } },
+ { 0x104be, 2, { 0xd801, 0xdce6 } },
+ { 0x104bf, 2, { 0xd801, 0xdce7 } },
+ { 0x104c0, 2, { 0xd801, 0xdce8 } },
+ { 0x104c1, 2, { 0xd801, 0xdce9 } },
+ { 0x104c2, 2, { 0xd801, 0xdcea } },
+ { 0x104c3, 2, { 0xd801, 0xdceb } },
+ { 0x104c4, 2, { 0xd801, 0xdcec } },
+ { 0x104c5, 2, { 0xd801, 0xdced } },
+ { 0x104c6, 2, { 0xd801, 0xdcee } },
+ { 0x104c7, 2, { 0xd801, 0xdcef } },
+ { 0x104c8, 2, { 0xd801, 0xdcf0 } },
+ { 0x104c9, 2, { 0xd801, 0xdcf1 } },
+ { 0x104ca, 2, { 0xd801, 0xdcf2 } },
+ { 0x104cb, 2, { 0xd801, 0xdcf3 } },
+ { 0x104cc, 2, { 0xd801, 0xdcf4 } },
+ { 0x104cd, 2, { 0xd801, 0xdcf5 } },
+ { 0x104ce, 2, { 0xd801, 0xdcf6 } },
+ { 0x104cf, 2, { 0xd801, 0xdcf7 } },
+ { 0x104d0, 2, { 0xd801, 0xdcf8 } },
+ { 0x104d1, 2, { 0xd801, 0xdcf9 } },
+ { 0x104d2, 2, { 0xd801, 0xdcfa } },
+ { 0x104d3, 2, { 0xd801, 0xdcfb } },
+ { 0x10570, 2, { 0xd801, 0xdd97 } },
+ { 0x10571, 2, { 0xd801, 0xdd98 } },
+ { 0x10572, 2, { 0xd801, 0xdd99 } },
+ { 0x10573, 2, { 0xd801, 0xdd9a } },
+ { 0x10574, 2, { 0xd801, 0xdd9b } },
+ { 0x10575, 2, { 0xd801, 0xdd9c } },
+ { 0x10576, 2, { 0xd801, 0xdd9d } },
+ { 0x10577, 2, { 0xd801, 0xdd9e } },
+ { 0x10578, 2, { 0xd801, 0xdd9f } },
+ { 0x10579, 2, { 0xd801, 0xdda0 } },
+ { 0x1057a, 2, { 0xd801, 0xdda1 } },
+ { 0x1057c, 2, { 0xd801, 0xdda3 } },
+ { 0x1057d, 2, { 0xd801, 0xdda4 } },
+ { 0x1057e, 2, { 0xd801, 0xdda5 } },
+ { 0x1057f, 2, { 0xd801, 0xdda6 } },
+ { 0x10580, 2, { 0xd801, 0xdda7 } },
+ { 0x10581, 2, { 0xd801, 0xdda8 } },
+ { 0x10582, 2, { 0xd801, 0xdda9 } },
+ { 0x10583, 2, { 0xd801, 0xddaa } },
+ { 0x10584, 2, { 0xd801, 0xddab } },
+ { 0x10585, 2, { 0xd801, 0xddac } },
+ { 0x10586, 2, { 0xd801, 0xddad } },
+ { 0x10587, 2, { 0xd801, 0xddae } },
+ { 0x10588, 2, { 0xd801, 0xddaf } },
+ { 0x10589, 2, { 0xd801, 0xddb0 } },
+ { 0x1058a, 2, { 0xd801, 0xddb1 } },
+ { 0x1058c, 2, { 0xd801, 0xddb3 } },
+ { 0x1058d, 2, { 0xd801, 0xddb4 } },
+ { 0x1058e, 2, { 0xd801, 0xddb5 } },
+ { 0x1058f, 2, { 0xd801, 0xddb6 } },
+ { 0x10590, 2, { 0xd801, 0xddb7 } },
+ { 0x10591, 2, { 0xd801, 0xddb8 } },
+ { 0x10592, 2, { 0xd801, 0xddb9 } },
+ { 0x10594, 2, { 0xd801, 0xddbb } },
+ { 0x10595, 2, { 0xd801, 0xddbc } },
+ { 0x10781, 1, { 0x2d0, 0 } },
+ { 0x10782, 1, { 0x2d1, 0 } },
+ { 0x10783, 1, { 0xe6, 0 } },
+ { 0x10784, 1, { 0x299, 0 } },
+ { 0x10785, 1, { 0x253, 0 } },
+ { 0x10787, 1, { 0x2a3, 0 } },
+ { 0x10788, 1, { 0xab66, 0 } },
+ { 0x10789, 1, { 0x2a5, 0 } },
+ { 0x1078a, 1, { 0x2a4, 0 } },
+ { 0x1078b, 1, { 0x256, 0 } },
+ { 0x1078c, 1, { 0x257, 0 } },
+ { 0x1078d, 1, { 0x1d91, 0 } },
+ { 0x1078e, 1, { 0x258, 0 } },
+ { 0x1078f, 1, { 0x25e, 0 } },
+ { 0x10790, 1, { 0x2a9, 0 } },
+ { 0x10791, 1, { 0x264, 0 } },
+ { 0x10792, 1, { 0x262, 0 } },
+ { 0x10793, 1, { 0x260, 0 } },
+ { 0x10794, 1, { 0x29b, 0 } },
+ { 0x10795, 1, { 0x127, 0 } },
+ { 0x10796, 1, { 0x29c, 0 } },
+ { 0x10797, 1, { 0x267, 0 } },
+ { 0x10798, 1, { 0x284, 0 } },
+ { 0x10799, 1, { 0x2aa, 0 } },
+ { 0x1079a, 1, { 0x2ab, 0 } },
+ { 0x1079b, 1, { 0x26c, 0 } },
+ { 0x1079c, 2, { 0xd837, 0xdf04 } },
+ { 0x1079d, 1, { 0xa78e, 0 } },
+ { 0x1079e, 1, { 0x26e, 0 } },
+ { 0x1079f, 2, { 0xd837, 0xdf05 } },
+ { 0x107a0, 1, { 0x28e, 0 } },
+ { 0x107a1, 2, { 0xd837, 0xdf06 } },
+ { 0x107a2, 1, { 0xf8, 0 } },
+ { 0x107a3, 1, { 0x276, 0 } },
+ { 0x107a4, 1, { 0x277, 0 } },
+ { 0x107a5, 1, { 0x71, 0 } },
+ { 0x107a6, 1, { 0x27a, 0 } },
+ { 0x107a7, 2, { 0xd837, 0xdf08 } },
+ { 0x107a8, 1, { 0x27d, 0 } },
+ { 0x107a9, 1, { 0x27e, 0 } },
+ { 0x107aa, 1, { 0x280, 0 } },
+ { 0x107ab, 1, { 0x2a8, 0 } },
+ { 0x107ac, 1, { 0x2a6, 0 } },
+ { 0x107ad, 1, { 0xab67, 0 } },
+ { 0x107ae, 1, { 0x2a7, 0 } },
+ { 0x107af, 1, { 0x288, 0 } },
+ { 0x107b0, 1, { 0x2c71, 0 } },
+ { 0x107b2, 1, { 0x28f, 0 } },
+ { 0x107b3, 1, { 0x2a1, 0 } },
+ { 0x107b4, 1, { 0x2a2, 0 } },
+ { 0x107b5, 1, { 0x298, 0 } },
+ { 0x107b6, 1, { 0x1c0, 0 } },
+ { 0x107b7, 1, { 0x1c1, 0 } },
+ { 0x107b8, 1, { 0x1c2, 0 } },
+ { 0x107b9, 2, { 0xd837, 0xdf0a } },
+ { 0x107ba, 2, { 0xd837, 0xdf1e } },
+ { 0x10c80, 2, { 0xd803, 0xdcc0 } },
+ { 0x10c81, 2, { 0xd803, 0xdcc1 } },
+ { 0x10c82, 2, { 0xd803, 0xdcc2 } },
+ { 0x10c83, 2, { 0xd803, 0xdcc3 } },
+ { 0x10c84, 2, { 0xd803, 0xdcc4 } },
+ { 0x10c85, 2, { 0xd803, 0xdcc5 } },
+ { 0x10c86, 2, { 0xd803, 0xdcc6 } },
+ { 0x10c87, 2, { 0xd803, 0xdcc7 } },
+ { 0x10c88, 2, { 0xd803, 0xdcc8 } },
+ { 0x10c89, 2, { 0xd803, 0xdcc9 } },
+ { 0x10c8a, 2, { 0xd803, 0xdcca } },
+ { 0x10c8b, 2, { 0xd803, 0xdccb } },
+ { 0x10c8c, 2, { 0xd803, 0xdccc } },
+ { 0x10c8d, 2, { 0xd803, 0xdccd } },
+ { 0x10c8e, 2, { 0xd803, 0xdcce } },
+ { 0x10c8f, 2, { 0xd803, 0xdccf } },
+ { 0x10c90, 2, { 0xd803, 0xdcd0 } },
+ { 0x10c91, 2, { 0xd803, 0xdcd1 } },
+ { 0x10c92, 2, { 0xd803, 0xdcd2 } },
+ { 0x10c93, 2, { 0xd803, 0xdcd3 } },
+ { 0x10c94, 2, { 0xd803, 0xdcd4 } },
+ { 0x10c95, 2, { 0xd803, 0xdcd5 } },
+ { 0x10c96, 2, { 0xd803, 0xdcd6 } },
+ { 0x10c97, 2, { 0xd803, 0xdcd7 } },
+ { 0x10c98, 2, { 0xd803, 0xdcd8 } },
+ { 0x10c99, 2, { 0xd803, 0xdcd9 } },
+ { 0x10c9a, 2, { 0xd803, 0xdcda } },
+ { 0x10c9b, 2, { 0xd803, 0xdcdb } },
+ { 0x10c9c, 2, { 0xd803, 0xdcdc } },
+ { 0x10c9d, 2, { 0xd803, 0xdcdd } },
+ { 0x10c9e, 2, { 0xd803, 0xdcde } },
+ { 0x10c9f, 2, { 0xd803, 0xdcdf } },
+ { 0x10ca0, 2, { 0xd803, 0xdce0 } },
+ { 0x10ca1, 2, { 0xd803, 0xdce1 } },
+ { 0x10ca2, 2, { 0xd803, 0xdce2 } },
+ { 0x10ca3, 2, { 0xd803, 0xdce3 } },
+ { 0x10ca4, 2, { 0xd803, 0xdce4 } },
+ { 0x10ca5, 2, { 0xd803, 0xdce5 } },
+ { 0x10ca6, 2, { 0xd803, 0xdce6 } },
+ { 0x10ca7, 2, { 0xd803, 0xdce7 } },
+ { 0x10ca8, 2, { 0xd803, 0xdce8 } },
+ { 0x10ca9, 2, { 0xd803, 0xdce9 } },
+ { 0x10caa, 2, { 0xd803, 0xdcea } },
+ { 0x10cab, 2, { 0xd803, 0xdceb } },
+ { 0x10cac, 2, { 0xd803, 0xdcec } },
+ { 0x10cad, 2, { 0xd803, 0xdced } },
+ { 0x10cae, 2, { 0xd803, 0xdcee } },
+ { 0x10caf, 2, { 0xd803, 0xdcef } },
+ { 0x10cb0, 2, { 0xd803, 0xdcf0 } },
+ { 0x10cb1, 2, { 0xd803, 0xdcf1 } },
+ { 0x10cb2, 2, { 0xd803, 0xdcf2 } },
+ { 0x118a0, 2, { 0xd806, 0xdcc0 } },
+ { 0x118a1, 2, { 0xd806, 0xdcc1 } },
+ { 0x118a2, 2, { 0xd806, 0xdcc2 } },
+ { 0x118a3, 2, { 0xd806, 0xdcc3 } },
+ { 0x118a4, 2, { 0xd806, 0xdcc4 } },
+ { 0x118a5, 2, { 0xd806, 0xdcc5 } },
+ { 0x118a6, 2, { 0xd806, 0xdcc6 } },
+ { 0x118a7, 2, { 0xd806, 0xdcc7 } },
+ { 0x118a8, 2, { 0xd806, 0xdcc8 } },
+ { 0x118a9, 2, { 0xd806, 0xdcc9 } },
+ { 0x118aa, 2, { 0xd806, 0xdcca } },
+ { 0x118ab, 2, { 0xd806, 0xdccb } },
+ { 0x118ac, 2, { 0xd806, 0xdccc } },
+ { 0x118ad, 2, { 0xd806, 0xdccd } },
+ { 0x118ae, 2, { 0xd806, 0xdcce } },
+ { 0x118af, 2, { 0xd806, 0xdccf } },
+ { 0x118b0, 2, { 0xd806, 0xdcd0 } },
+ { 0x118b1, 2, { 0xd806, 0xdcd1 } },
+ { 0x118b2, 2, { 0xd806, 0xdcd2 } },
+ { 0x118b3, 2, { 0xd806, 0xdcd3 } },
+ { 0x118b4, 2, { 0xd806, 0xdcd4 } },
+ { 0x118b5, 2, { 0xd806, 0xdcd5 } },
+ { 0x118b6, 2, { 0xd806, 0xdcd6 } },
+ { 0x118b7, 2, { 0xd806, 0xdcd7 } },
+ { 0x118b8, 2, { 0xd806, 0xdcd8 } },
+ { 0x118b9, 2, { 0xd806, 0xdcd9 } },
+ { 0x118ba, 2, { 0xd806, 0xdcda } },
+ { 0x118bb, 2, { 0xd806, 0xdcdb } },
+ { 0x118bc, 2, { 0xd806, 0xdcdc } },
+ { 0x118bd, 2, { 0xd806, 0xdcdd } },
+ { 0x118be, 2, { 0xd806, 0xdcde } },
+ { 0x118bf, 2, { 0xd806, 0xdcdf } },
+ { 0x16e40, 2, { 0xd81b, 0xde60 } },
+ { 0x16e41, 2, { 0xd81b, 0xde61 } },
+ { 0x16e42, 2, { 0xd81b, 0xde62 } },
+ { 0x16e43, 2, { 0xd81b, 0xde63 } },
+ { 0x16e44, 2, { 0xd81b, 0xde64 } },
+ { 0x16e45, 2, { 0xd81b, 0xde65 } },
+ { 0x16e46, 2, { 0xd81b, 0xde66 } },
+ { 0x16e47, 2, { 0xd81b, 0xde67 } },
+ { 0x16e48, 2, { 0xd81b, 0xde68 } },
+ { 0x16e49, 2, { 0xd81b, 0xde69 } },
+ { 0x16e4a, 2, { 0xd81b, 0xde6a } },
+ { 0x16e4b, 2, { 0xd81b, 0xde6b } },
+ { 0x16e4c, 2, { 0xd81b, 0xde6c } },
+ { 0x16e4d, 2, { 0xd81b, 0xde6d } },
+ { 0x16e4e, 2, { 0xd81b, 0xde6e } },
+ { 0x16e4f, 2, { 0xd81b, 0xde6f } },
+ { 0x16e50, 2, { 0xd81b, 0xde70 } },
+ { 0x16e51, 2, { 0xd81b, 0xde71 } },
+ { 0x16e52, 2, { 0xd81b, 0xde72 } },
+ { 0x16e53, 2, { 0xd81b, 0xde73 } },
+ { 0x16e54, 2, { 0xd81b, 0xde74 } },
+ { 0x16e55, 2, { 0xd81b, 0xde75 } },
+ { 0x16e56, 2, { 0xd81b, 0xde76 } },
+ { 0x16e57, 2, { 0xd81b, 0xde77 } },
+ { 0x16e58, 2, { 0xd81b, 0xde78 } },
+ { 0x16e59, 2, { 0xd81b, 0xde79 } },
+ { 0x16e5a, 2, { 0xd81b, 0xde7a } },
+ { 0x16e5b, 2, { 0xd81b, 0xde7b } },
+ { 0x16e5c, 2, { 0xd81b, 0xde7c } },
+ { 0x16e5d, 2, { 0xd81b, 0xde7d } },
+ { 0x16e5e, 2, { 0xd81b, 0xde7e } },
+ { 0x16e5f, 2, { 0xd81b, 0xde7f } },
+ { 0x1d15e, 4, { 265, 0 } },
+ { 0x1d15f, 4, { 179, 0 } },
+ { 0x1d160, 6, { 203, 0 } },
+ { 0x1d161, 6, { 197, 0 } },
+ { 0x1d162, 6, { 191, 0 } },
+ { 0x1d163, 6, { 185, 0 } },
+ { 0x1d164, 6, { 179, 0 } },
+ { 0x1d1bb, 4, { 167, 0 } },
+ { 0x1d1bc, 4, { 155, 0 } },
+ { 0x1d1bd, 6, { 173, 0 } },
+ { 0x1d1be, 6, { 161, 0 } },
+ { 0x1d1bf, 6, { 167, 0 } },
+ { 0x1d1c0, 6, { 155, 0 } },
+ { 0x1d400, 1, { 0x61, 0 } },
+ { 0x1d401, 1, { 0x62, 0 } },
+ { 0x1d402, 1, { 0x63, 0 } },
+ { 0x1d403, 1, { 0x64, 0 } },
+ { 0x1d404, 1, { 0x65, 0 } },
+ { 0x1d405, 1, { 0x66, 0 } },
+ { 0x1d406, 1, { 0x67, 0 } },
+ { 0x1d407, 1, { 0x68, 0 } },
+ { 0x1d408, 1, { 0x69, 0 } },
+ { 0x1d409, 1, { 0x6a, 0 } },
+ { 0x1d40a, 1, { 0x6b, 0 } },
+ { 0x1d40b, 1, { 0x6c, 0 } },
+ { 0x1d40c, 1, { 0x6d, 0 } },
+ { 0x1d40d, 1, { 0x6e, 0 } },
+ { 0x1d40e, 1, { 0x6f, 0 } },
+ { 0x1d40f, 1, { 0x70, 0 } },
+ { 0x1d410, 1, { 0x71, 0 } },
+ { 0x1d411, 1, { 0x72, 0 } },
+ { 0x1d412, 1, { 0x73, 0 } },
+ { 0x1d413, 1, { 0x74, 0 } },
+ { 0x1d414, 1, { 0x75, 0 } },
+ { 0x1d415, 1, { 0x76, 0 } },
+ { 0x1d416, 1, { 0x77, 0 } },
+ { 0x1d417, 1, { 0x78, 0 } },
+ { 0x1d418, 1, { 0x79, 0 } },
+ { 0x1d419, 1, { 0x7a, 0 } },
+ { 0x1d41a, 1, { 0x61, 0 } },
+ { 0x1d41b, 1, { 0x62, 0 } },
+ { 0x1d41c, 1, { 0x63, 0 } },
+ { 0x1d41d, 1, { 0x64, 0 } },
+ { 0x1d41e, 1, { 0x65, 0 } },
+ { 0x1d41f, 1, { 0x66, 0 } },
+ { 0x1d420, 1, { 0x67, 0 } },
+ { 0x1d421, 1, { 0x68, 0 } },
+ { 0x1d422, 1, { 0x69, 0 } },
+ { 0x1d423, 1, { 0x6a, 0 } },
+ { 0x1d424, 1, { 0x6b, 0 } },
+ { 0x1d425, 1, { 0x6c, 0 } },
+ { 0x1d426, 1, { 0x6d, 0 } },
+ { 0x1d427, 1, { 0x6e, 0 } },
+ { 0x1d428, 1, { 0x6f, 0 } },
+ { 0x1d429, 1, { 0x70, 0 } },
+ { 0x1d42a, 1, { 0x71, 0 } },
+ { 0x1d42b, 1, { 0x72, 0 } },
+ { 0x1d42c, 1, { 0x73, 0 } },
+ { 0x1d42d, 1, { 0x74, 0 } },
+ { 0x1d42e, 1, { 0x75, 0 } },
+ { 0x1d42f, 1, { 0x76, 0 } },
+ { 0x1d430, 1, { 0x77, 0 } },
+ { 0x1d431, 1, { 0x78, 0 } },
+ { 0x1d432, 1, { 0x79, 0 } },
+ { 0x1d433, 1, { 0x7a, 0 } },
+ { 0x1d434, 1, { 0x61, 0 } },
+ { 0x1d435, 1, { 0x62, 0 } },
+ { 0x1d436, 1, { 0x63, 0 } },
+ { 0x1d437, 1, { 0x64, 0 } },
+ { 0x1d438, 1, { 0x65, 0 } },
+ { 0x1d439, 1, { 0x66, 0 } },
+ { 0x1d43a, 1, { 0x67, 0 } },
+ { 0x1d43b, 1, { 0x68, 0 } },
+ { 0x1d43c, 1, { 0x69, 0 } },
+ { 0x1d43d, 1, { 0x6a, 0 } },
+ { 0x1d43e, 1, { 0x6b, 0 } },
+ { 0x1d43f, 1, { 0x6c, 0 } },
+ { 0x1d440, 1, { 0x6d, 0 } },
+ { 0x1d441, 1, { 0x6e, 0 } },
+ { 0x1d442, 1, { 0x6f, 0 } },
+ { 0x1d443, 1, { 0x70, 0 } },
+ { 0x1d444, 1, { 0x71, 0 } },
+ { 0x1d445, 1, { 0x72, 0 } },
+ { 0x1d446, 1, { 0x73, 0 } },
+ { 0x1d447, 1, { 0x74, 0 } },
+ { 0x1d448, 1, { 0x75, 0 } },
+ { 0x1d449, 1, { 0x76, 0 } },
+ { 0x1d44a, 1, { 0x77, 0 } },
+ { 0x1d44b, 1, { 0x78, 0 } },
+ { 0x1d44c, 1, { 0x79, 0 } },
+ { 0x1d44d, 1, { 0x7a, 0 } },
+ { 0x1d44e, 1, { 0x61, 0 } },
+ { 0x1d44f, 1, { 0x62, 0 } },
+ { 0x1d450, 1, { 0x63, 0 } },
+ { 0x1d451, 1, { 0x64, 0 } },
+ { 0x1d452, 1, { 0x65, 0 } },
+ { 0x1d453, 1, { 0x66, 0 } },
+ { 0x1d454, 1, { 0x67, 0 } },
+ { 0x1d456, 1, { 0x69, 0 } },
+ { 0x1d457, 1, { 0x6a, 0 } },
+ { 0x1d458, 1, { 0x6b, 0 } },
+ { 0x1d459, 1, { 0x6c, 0 } },
+ { 0x1d45a, 1, { 0x6d, 0 } },
+ { 0x1d45b, 1, { 0x6e, 0 } },
+ { 0x1d45c, 1, { 0x6f, 0 } },
+ { 0x1d45d, 1, { 0x70, 0 } },
+ { 0x1d45e, 1, { 0x71, 0 } },
+ { 0x1d45f, 1, { 0x72, 0 } },
+ { 0x1d460, 1, { 0x73, 0 } },
+ { 0x1d461, 1, { 0x74, 0 } },
+ { 0x1d462, 1, { 0x75, 0 } },
+ { 0x1d463, 1, { 0x76, 0 } },
+ { 0x1d464, 1, { 0x77, 0 } },
+ { 0x1d465, 1, { 0x78, 0 } },
+ { 0x1d466, 1, { 0x79, 0 } },
+ { 0x1d467, 1, { 0x7a, 0 } },
+ { 0x1d468, 1, { 0x61, 0 } },
+ { 0x1d469, 1, { 0x62, 0 } },
+ { 0x1d46a, 1, { 0x63, 0 } },
+ { 0x1d46b, 1, { 0x64, 0 } },
+ { 0x1d46c, 1, { 0x65, 0 } },
+ { 0x1d46d, 1, { 0x66, 0 } },
+ { 0x1d46e, 1, { 0x67, 0 } },
+ { 0x1d46f, 1, { 0x68, 0 } },
+ { 0x1d470, 1, { 0x69, 0 } },
+ { 0x1d471, 1, { 0x6a, 0 } },
+ { 0x1d472, 1, { 0x6b, 0 } },
+ { 0x1d473, 1, { 0x6c, 0 } },
+ { 0x1d474, 1, { 0x6d, 0 } },
+ { 0x1d475, 1, { 0x6e, 0 } },
+ { 0x1d476, 1, { 0x6f, 0 } },
+ { 0x1d477, 1, { 0x70, 0 } },
+ { 0x1d478, 1, { 0x71, 0 } },
+ { 0x1d479, 1, { 0x72, 0 } },
+ { 0x1d47a, 1, { 0x73, 0 } },
+ { 0x1d47b, 1, { 0x74, 0 } },
+ { 0x1d47c, 1, { 0x75, 0 } },
+ { 0x1d47d, 1, { 0x76, 0 } },
+ { 0x1d47e, 1, { 0x77, 0 } },
+ { 0x1d47f, 1, { 0x78, 0 } },
+ { 0x1d480, 1, { 0x79, 0 } },
+ { 0x1d481, 1, { 0x7a, 0 } },
+ { 0x1d482, 1, { 0x61, 0 } },
+ { 0x1d483, 1, { 0x62, 0 } },
+ { 0x1d484, 1, { 0x63, 0 } },
+ { 0x1d485, 1, { 0x64, 0 } },
+ { 0x1d486, 1, { 0x65, 0 } },
+ { 0x1d487, 1, { 0x66, 0 } },
+ { 0x1d488, 1, { 0x67, 0 } },
+ { 0x1d489, 1, { 0x68, 0 } },
+ { 0x1d48a, 1, { 0x69, 0 } },
+ { 0x1d48b, 1, { 0x6a, 0 } },
+ { 0x1d48c, 1, { 0x6b, 0 } },
+ { 0x1d48d, 1, { 0x6c, 0 } },
+ { 0x1d48e, 1, { 0x6d, 0 } },
+ { 0x1d48f, 1, { 0x6e, 0 } },
+ { 0x1d490, 1, { 0x6f, 0 } },
+ { 0x1d491, 1, { 0x70, 0 } },
+ { 0x1d492, 1, { 0x71, 0 } },
+ { 0x1d493, 1, { 0x72, 0 } },
+ { 0x1d494, 1, { 0x73, 0 } },
+ { 0x1d495, 1, { 0x74, 0 } },
+ { 0x1d496, 1, { 0x75, 0 } },
+ { 0x1d497, 1, { 0x76, 0 } },
+ { 0x1d498, 1, { 0x77, 0 } },
+ { 0x1d499, 1, { 0x78, 0 } },
+ { 0x1d49a, 1, { 0x79, 0 } },
+ { 0x1d49b, 1, { 0x7a, 0 } },
+ { 0x1d49c, 1, { 0x61, 0 } },
+ { 0x1d49e, 1, { 0x63, 0 } },
+ { 0x1d49f, 1, { 0x64, 0 } },
+ { 0x1d4a2, 1, { 0x67, 0 } },
+ { 0x1d4a5, 1, { 0x6a, 0 } },
+ { 0x1d4a6, 1, { 0x6b, 0 } },
+ { 0x1d4a9, 1, { 0x6e, 0 } },
+ { 0x1d4aa, 1, { 0x6f, 0 } },
+ { 0x1d4ab, 1, { 0x70, 0 } },
+ { 0x1d4ac, 1, { 0x71, 0 } },
+ { 0x1d4ae, 1, { 0x73, 0 } },
+ { 0x1d4af, 1, { 0x74, 0 } },
+ { 0x1d4b0, 1, { 0x75, 0 } },
+ { 0x1d4b1, 1, { 0x76, 0 } },
+ { 0x1d4b2, 1, { 0x77, 0 } },
+ { 0x1d4b3, 1, { 0x78, 0 } },
+ { 0x1d4b4, 1, { 0x79, 0 } },
+ { 0x1d4b5, 1, { 0x7a, 0 } },
+ { 0x1d4b6, 1, { 0x61, 0 } },
+ { 0x1d4b7, 1, { 0x62, 0 } },
+ { 0x1d4b8, 1, { 0x63, 0 } },
+ { 0x1d4b9, 1, { 0x64, 0 } },
+ { 0x1d4bb, 1, { 0x66, 0 } },
+ { 0x1d4bd, 1, { 0x68, 0 } },
+ { 0x1d4be, 1, { 0x69, 0 } },
+ { 0x1d4bf, 1, { 0x6a, 0 } },
+ { 0x1d4c0, 1, { 0x6b, 0 } },
+ { 0x1d4c1, 1, { 0x6c, 0 } },
+ { 0x1d4c2, 1, { 0x6d, 0 } },
+ { 0x1d4c3, 1, { 0x6e, 0 } },
+ { 0x1d4c5, 1, { 0x70, 0 } },
+ { 0x1d4c6, 1, { 0x71, 0 } },
+ { 0x1d4c7, 1, { 0x72, 0 } },
+ { 0x1d4c8, 1, { 0x73, 0 } },
+ { 0x1d4c9, 1, { 0x74, 0 } },
+ { 0x1d4ca, 1, { 0x75, 0 } },
+ { 0x1d4cb, 1, { 0x76, 0 } },
+ { 0x1d4cc, 1, { 0x77, 0 } },
+ { 0x1d4cd, 1, { 0x78, 0 } },
+ { 0x1d4ce, 1, { 0x79, 0 } },
+ { 0x1d4cf, 1, { 0x7a, 0 } },
+ { 0x1d4d0, 1, { 0x61, 0 } },
+ { 0x1d4d1, 1, { 0x62, 0 } },
+ { 0x1d4d2, 1, { 0x63, 0 } },
+ { 0x1d4d3, 1, { 0x64, 0 } },
+ { 0x1d4d4, 1, { 0x65, 0 } },
+ { 0x1d4d5, 1, { 0x66, 0 } },
+ { 0x1d4d6, 1, { 0x67, 0 } },
+ { 0x1d4d7, 1, { 0x68, 0 } },
+ { 0x1d4d8, 1, { 0x69, 0 } },
+ { 0x1d4d9, 1, { 0x6a, 0 } },
+ { 0x1d4da, 1, { 0x6b, 0 } },
+ { 0x1d4db, 1, { 0x6c, 0 } },
+ { 0x1d4dc, 1, { 0x6d, 0 } },
+ { 0x1d4dd, 1, { 0x6e, 0 } },
+ { 0x1d4de, 1, { 0x6f, 0 } },
+ { 0x1d4df, 1, { 0x70, 0 } },
+ { 0x1d4e0, 1, { 0x71, 0 } },
+ { 0x1d4e1, 1, { 0x72, 0 } },
+ { 0x1d4e2, 1, { 0x73, 0 } },
+ { 0x1d4e3, 1, { 0x74, 0 } },
+ { 0x1d4e4, 1, { 0x75, 0 } },
+ { 0x1d4e5, 1, { 0x76, 0 } },
+ { 0x1d4e6, 1, { 0x77, 0 } },
+ { 0x1d4e7, 1, { 0x78, 0 } },
+ { 0x1d4e8, 1, { 0x79, 0 } },
+ { 0x1d4e9, 1, { 0x7a, 0 } },
+ { 0x1d4ea, 1, { 0x61, 0 } },
+ { 0x1d4eb, 1, { 0x62, 0 } },
+ { 0x1d4ec, 1, { 0x63, 0 } },
+ { 0x1d4ed, 1, { 0x64, 0 } },
+ { 0x1d4ee, 1, { 0x65, 0 } },
+ { 0x1d4ef, 1, { 0x66, 0 } },
+ { 0x1d4f0, 1, { 0x67, 0 } },
+ { 0x1d4f1, 1, { 0x68, 0 } },
+ { 0x1d4f2, 1, { 0x69, 0 } },
+ { 0x1d4f3, 1, { 0x6a, 0 } },
+ { 0x1d4f4, 1, { 0x6b, 0 } },
+ { 0x1d4f5, 1, { 0x6c, 0 } },
+ { 0x1d4f6, 1, { 0x6d, 0 } },
+ { 0x1d4f7, 1, { 0x6e, 0 } },
+ { 0x1d4f8, 1, { 0x6f, 0 } },
+ { 0x1d4f9, 1, { 0x70, 0 } },
+ { 0x1d4fa, 1, { 0x71, 0 } },
+ { 0x1d4fb, 1, { 0x72, 0 } },
+ { 0x1d4fc, 1, { 0x73, 0 } },
+ { 0x1d4fd, 1, { 0x74, 0 } },
+ { 0x1d4fe, 1, { 0x75, 0 } },
+ { 0x1d4ff, 1, { 0x76, 0 } },
+ { 0x1d500, 1, { 0x77, 0 } },
+ { 0x1d501, 1, { 0x78, 0 } },
+ { 0x1d502, 1, { 0x79, 0 } },
+ { 0x1d503, 1, { 0x7a, 0 } },
+ { 0x1d504, 1, { 0x61, 0 } },
+ { 0x1d505, 1, { 0x62, 0 } },
+ { 0x1d507, 1, { 0x64, 0 } },
+ { 0x1d508, 1, { 0x65, 0 } },
+ { 0x1d509, 1, { 0x66, 0 } },
+ { 0x1d50a, 1, { 0x67, 0 } },
+ { 0x1d50d, 1, { 0x6a, 0 } },
+ { 0x1d50e, 1, { 0x6b, 0 } },
+ { 0x1d50f, 1, { 0x6c, 0 } },
+ { 0x1d510, 1, { 0x6d, 0 } },
+ { 0x1d511, 1, { 0x6e, 0 } },
+ { 0x1d512, 1, { 0x6f, 0 } },
+ { 0x1d513, 1, { 0x70, 0 } },
+ { 0x1d514, 1, { 0x71, 0 } },
+ { 0x1d516, 1, { 0x73, 0 } },
+ { 0x1d517, 1, { 0x74, 0 } },
+ { 0x1d518, 1, { 0x75, 0 } },
+ { 0x1d519, 1, { 0x76, 0 } },
+ { 0x1d51a, 1, { 0x77, 0 } },
+ { 0x1d51b, 1, { 0x78, 0 } },
+ { 0x1d51c, 1, { 0x79, 0 } },
+ { 0x1d51e, 1, { 0x61, 0 } },
+ { 0x1d51f, 1, { 0x62, 0 } },
+ { 0x1d520, 1, { 0x63, 0 } },
+ { 0x1d521, 1, { 0x64, 0 } },
+ { 0x1d522, 1, { 0x65, 0 } },
+ { 0x1d523, 1, { 0x66, 0 } },
+ { 0x1d524, 1, { 0x67, 0 } },
+ { 0x1d525, 1, { 0x68, 0 } },
+ { 0x1d526, 1, { 0x69, 0 } },
+ { 0x1d527, 1, { 0x6a, 0 } },
+ { 0x1d528, 1, { 0x6b, 0 } },
+ { 0x1d529, 1, { 0x6c, 0 } },
+ { 0x1d52a, 1, { 0x6d, 0 } },
+ { 0x1d52b, 1, { 0x6e, 0 } },
+ { 0x1d52c, 1, { 0x6f, 0 } },
+ { 0x1d52d, 1, { 0x70, 0 } },
+ { 0x1d52e, 1, { 0x71, 0 } },
+ { 0x1d52f, 1, { 0x72, 0 } },
+ { 0x1d530, 1, { 0x73, 0 } },
+ { 0x1d531, 1, { 0x74, 0 } },
+ { 0x1d532, 1, { 0x75, 0 } },
+ { 0x1d533, 1, { 0x76, 0 } },
+ { 0x1d534, 1, { 0x77, 0 } },
+ { 0x1d535, 1, { 0x78, 0 } },
+ { 0x1d536, 1, { 0x79, 0 } },
+ { 0x1d537, 1, { 0x7a, 0 } },
+ { 0x1d538, 1, { 0x61, 0 } },
+ { 0x1d539, 1, { 0x62, 0 } },
+ { 0x1d53b, 1, { 0x64, 0 } },
+ { 0x1d53c, 1, { 0x65, 0 } },
+ { 0x1d53d, 1, { 0x66, 0 } },
+ { 0x1d53e, 1, { 0x67, 0 } },
+ { 0x1d540, 1, { 0x69, 0 } },
+ { 0x1d541, 1, { 0x6a, 0 } },
+ { 0x1d542, 1, { 0x6b, 0 } },
+ { 0x1d543, 1, { 0x6c, 0 } },
+ { 0x1d544, 1, { 0x6d, 0 } },
+ { 0x1d546, 1, { 0x6f, 0 } },
+ { 0x1d54a, 1, { 0x73, 0 } },
+ { 0x1d54b, 1, { 0x74, 0 } },
+ { 0x1d54c, 1, { 0x75, 0 } },
+ { 0x1d54d, 1, { 0x76, 0 } },
+ { 0x1d54e, 1, { 0x77, 0 } },
+ { 0x1d54f, 1, { 0x78, 0 } },
+ { 0x1d550, 1, { 0x79, 0 } },
+ { 0x1d552, 1, { 0x61, 0 } },
+ { 0x1d553, 1, { 0x62, 0 } },
+ { 0x1d554, 1, { 0x63, 0 } },
+ { 0x1d555, 1, { 0x64, 0 } },
+ { 0x1d556, 1, { 0x65, 0 } },
+ { 0x1d557, 1, { 0x66, 0 } },
+ { 0x1d558, 1, { 0x67, 0 } },
+ { 0x1d559, 1, { 0x68, 0 } },
+ { 0x1d55a, 1, { 0x69, 0 } },
+ { 0x1d55b, 1, { 0x6a, 0 } },
+ { 0x1d55c, 1, { 0x6b, 0 } },
+ { 0x1d55d, 1, { 0x6c, 0 } },
+ { 0x1d55e, 1, { 0x6d, 0 } },
+ { 0x1d55f, 1, { 0x6e, 0 } },
+ { 0x1d560, 1, { 0x6f, 0 } },
+ { 0x1d561, 1, { 0x70, 0 } },
+ { 0x1d562, 1, { 0x71, 0 } },
+ { 0x1d563, 1, { 0x72, 0 } },
+ { 0x1d564, 1, { 0x73, 0 } },
+ { 0x1d565, 1, { 0x74, 0 } },
+ { 0x1d566, 1, { 0x75, 0 } },
+ { 0x1d567, 1, { 0x76, 0 } },
+ { 0x1d568, 1, { 0x77, 0 } },
+ { 0x1d569, 1, { 0x78, 0 } },
+ { 0x1d56a, 1, { 0x79, 0 } },
+ { 0x1d56b, 1, { 0x7a, 0 } },
+ { 0x1d56c, 1, { 0x61, 0 } },
+ { 0x1d56d, 1, { 0x62, 0 } },
+ { 0x1d56e, 1, { 0x63, 0 } },
+ { 0x1d56f, 1, { 0x64, 0 } },
+ { 0x1d570, 1, { 0x65, 0 } },
+ { 0x1d571, 1, { 0x66, 0 } },
+ { 0x1d572, 1, { 0x67, 0 } },
+ { 0x1d573, 1, { 0x68, 0 } },
+ { 0x1d574, 1, { 0x69, 0 } },
+ { 0x1d575, 1, { 0x6a, 0 } },
+ { 0x1d576, 1, { 0x6b, 0 } },
+ { 0x1d577, 1, { 0x6c, 0 } },
+ { 0x1d578, 1, { 0x6d, 0 } },
+ { 0x1d579, 1, { 0x6e, 0 } },
+ { 0x1d57a, 1, { 0x6f, 0 } },
+ { 0x1d57b, 1, { 0x70, 0 } },
+ { 0x1d57c, 1, { 0x71, 0 } },
+ { 0x1d57d, 1, { 0x72, 0 } },
+ { 0x1d57e, 1, { 0x73, 0 } },
+ { 0x1d57f, 1, { 0x74, 0 } },
+ { 0x1d580, 1, { 0x75, 0 } },
+ { 0x1d581, 1, { 0x76, 0 } },
+ { 0x1d582, 1, { 0x77, 0 } },
+ { 0x1d583, 1, { 0x78, 0 } },
+ { 0x1d584, 1, { 0x79, 0 } },
+ { 0x1d585, 1, { 0x7a, 0 } },
+ { 0x1d586, 1, { 0x61, 0 } },
+ { 0x1d587, 1, { 0x62, 0 } },
+ { 0x1d588, 1, { 0x63, 0 } },
+ { 0x1d589, 1, { 0x64, 0 } },
+ { 0x1d58a, 1, { 0x65, 0 } },
+ { 0x1d58b, 1, { 0x66, 0 } },
+ { 0x1d58c, 1, { 0x67, 0 } },
+ { 0x1d58d, 1, { 0x68, 0 } },
+ { 0x1d58e, 1, { 0x69, 0 } },
+ { 0x1d58f, 1, { 0x6a, 0 } },
+ { 0x1d590, 1, { 0x6b, 0 } },
+ { 0x1d591, 1, { 0x6c, 0 } },
+ { 0x1d592, 1, { 0x6d, 0 } },
+ { 0x1d593, 1, { 0x6e, 0 } },
+ { 0x1d594, 1, { 0x6f, 0 } },
+ { 0x1d595, 1, { 0x70, 0 } },
+ { 0x1d596, 1, { 0x71, 0 } },
+ { 0x1d597, 1, { 0x72, 0 } },
+ { 0x1d598, 1, { 0x73, 0 } },
+ { 0x1d599, 1, { 0x74, 0 } },
+ { 0x1d59a, 1, { 0x75, 0 } },
+ { 0x1d59b, 1, { 0x76, 0 } },
+ { 0x1d59c, 1, { 0x77, 0 } },
+ { 0x1d59d, 1, { 0x78, 0 } },
+ { 0x1d59e, 1, { 0x79, 0 } },
+ { 0x1d59f, 1, { 0x7a, 0 } },
+ { 0x1d5a0, 1, { 0x61, 0 } },
+ { 0x1d5a1, 1, { 0x62, 0 } },
+ { 0x1d5a2, 1, { 0x63, 0 } },
+ { 0x1d5a3, 1, { 0x64, 0 } },
+ { 0x1d5a4, 1, { 0x65, 0 } },
+ { 0x1d5a5, 1, { 0x66, 0 } },
+ { 0x1d5a6, 1, { 0x67, 0 } },
+ { 0x1d5a7, 1, { 0x68, 0 } },
+ { 0x1d5a8, 1, { 0x69, 0 } },
+ { 0x1d5a9, 1, { 0x6a, 0 } },
+ { 0x1d5aa, 1, { 0x6b, 0 } },
+ { 0x1d5ab, 1, { 0x6c, 0 } },
+ { 0x1d5ac, 1, { 0x6d, 0 } },
+ { 0x1d5ad, 1, { 0x6e, 0 } },
+ { 0x1d5ae, 1, { 0x6f, 0 } },
+ { 0x1d5af, 1, { 0x70, 0 } },
+ { 0x1d5b0, 1, { 0x71, 0 } },
+ { 0x1d5b1, 1, { 0x72, 0 } },
+ { 0x1d5b2, 1, { 0x73, 0 } },
+ { 0x1d5b3, 1, { 0x74, 0 } },
+ { 0x1d5b4, 1, { 0x75, 0 } },
+ { 0x1d5b5, 1, { 0x76, 0 } },
+ { 0x1d5b6, 1, { 0x77, 0 } },
+ { 0x1d5b7, 1, { 0x78, 0 } },
+ { 0x1d5b8, 1, { 0x79, 0 } },
+ { 0x1d5b9, 1, { 0x7a, 0 } },
+ { 0x1d5ba, 1, { 0x61, 0 } },
+ { 0x1d5bb, 1, { 0x62, 0 } },
+ { 0x1d5bc, 1, { 0x63, 0 } },
+ { 0x1d5bd, 1, { 0x64, 0 } },
+ { 0x1d5be, 1, { 0x65, 0 } },
+ { 0x1d5bf, 1, { 0x66, 0 } },
+ { 0x1d5c0, 1, { 0x67, 0 } },
+ { 0x1d5c1, 1, { 0x68, 0 } },
+ { 0x1d5c2, 1, { 0x69, 0 } },
+ { 0x1d5c3, 1, { 0x6a, 0 } },
+ { 0x1d5c4, 1, { 0x6b, 0 } },
+ { 0x1d5c5, 1, { 0x6c, 0 } },
+ { 0x1d5c6, 1, { 0x6d, 0 } },
+ { 0x1d5c7, 1, { 0x6e, 0 } },
+ { 0x1d5c8, 1, { 0x6f, 0 } },
+ { 0x1d5c9, 1, { 0x70, 0 } },
+ { 0x1d5ca, 1, { 0x71, 0 } },
+ { 0x1d5cb, 1, { 0x72, 0 } },
+ { 0x1d5cc, 1, { 0x73, 0 } },
+ { 0x1d5cd, 1, { 0x74, 0 } },
+ { 0x1d5ce, 1, { 0x75, 0 } },
+ { 0x1d5cf, 1, { 0x76, 0 } },
+ { 0x1d5d0, 1, { 0x77, 0 } },
+ { 0x1d5d1, 1, { 0x78, 0 } },
+ { 0x1d5d2, 1, { 0x79, 0 } },
+ { 0x1d5d3, 1, { 0x7a, 0 } },
+ { 0x1d5d4, 1, { 0x61, 0 } },
+ { 0x1d5d5, 1, { 0x62, 0 } },
+ { 0x1d5d6, 1, { 0x63, 0 } },
+ { 0x1d5d7, 1, { 0x64, 0 } },
+ { 0x1d5d8, 1, { 0x65, 0 } },
+ { 0x1d5d9, 1, { 0x66, 0 } },
+ { 0x1d5da, 1, { 0x67, 0 } },
+ { 0x1d5db, 1, { 0x68, 0 } },
+ { 0x1d5dc, 1, { 0x69, 0 } },
+ { 0x1d5dd, 1, { 0x6a, 0 } },
+ { 0x1d5de, 1, { 0x6b, 0 } },
+ { 0x1d5df, 1, { 0x6c, 0 } },
+ { 0x1d5e0, 1, { 0x6d, 0 } },
+ { 0x1d5e1, 1, { 0x6e, 0 } },
+ { 0x1d5e2, 1, { 0x6f, 0 } },
+ { 0x1d5e3, 1, { 0x70, 0 } },
+ { 0x1d5e4, 1, { 0x71, 0 } },
+ { 0x1d5e5, 1, { 0x72, 0 } },
+ { 0x1d5e6, 1, { 0x73, 0 } },
+ { 0x1d5e7, 1, { 0x74, 0 } },
+ { 0x1d5e8, 1, { 0x75, 0 } },
+ { 0x1d5e9, 1, { 0x76, 0 } },
+ { 0x1d5ea, 1, { 0x77, 0 } },
+ { 0x1d5eb, 1, { 0x78, 0 } },
+ { 0x1d5ec, 1, { 0x79, 0 } },
+ { 0x1d5ed, 1, { 0x7a, 0 } },
+ { 0x1d5ee, 1, { 0x61, 0 } },
+ { 0x1d5ef, 1, { 0x62, 0 } },
+ { 0x1d5f0, 1, { 0x63, 0 } },
+ { 0x1d5f1, 1, { 0x64, 0 } },
+ { 0x1d5f2, 1, { 0x65, 0 } },
+ { 0x1d5f3, 1, { 0x66, 0 } },
+ { 0x1d5f4, 1, { 0x67, 0 } },
+ { 0x1d5f5, 1, { 0x68, 0 } },
+ { 0x1d5f6, 1, { 0x69, 0 } },
+ { 0x1d5f7, 1, { 0x6a, 0 } },
+ { 0x1d5f8, 1, { 0x6b, 0 } },
+ { 0x1d5f9, 1, { 0x6c, 0 } },
+ { 0x1d5fa, 1, { 0x6d, 0 } },
+ { 0x1d5fb, 1, { 0x6e, 0 } },
+ { 0x1d5fc, 1, { 0x6f, 0 } },
+ { 0x1d5fd, 1, { 0x70, 0 } },
+ { 0x1d5fe, 1, { 0x71, 0 } },
+ { 0x1d5ff, 1, { 0x72, 0 } },
+ { 0x1d600, 1, { 0x73, 0 } },
+ { 0x1d601, 1, { 0x74, 0 } },
+ { 0x1d602, 1, { 0x75, 0 } },
+ { 0x1d603, 1, { 0x76, 0 } },
+ { 0x1d604, 1, { 0x77, 0 } },
+ { 0x1d605, 1, { 0x78, 0 } },
+ { 0x1d606, 1, { 0x79, 0 } },
+ { 0x1d607, 1, { 0x7a, 0 } },
+ { 0x1d608, 1, { 0x61, 0 } },
+ { 0x1d609, 1, { 0x62, 0 } },
+ { 0x1d60a, 1, { 0x63, 0 } },
+ { 0x1d60b, 1, { 0x64, 0 } },
+ { 0x1d60c, 1, { 0x65, 0 } },
+ { 0x1d60d, 1, { 0x66, 0 } },
+ { 0x1d60e, 1, { 0x67, 0 } },
+ { 0x1d60f, 1, { 0x68, 0 } },
+ { 0x1d610, 1, { 0x69, 0 } },
+ { 0x1d611, 1, { 0x6a, 0 } },
+ { 0x1d612, 1, { 0x6b, 0 } },
+ { 0x1d613, 1, { 0x6c, 0 } },
+ { 0x1d614, 1, { 0x6d, 0 } },
+ { 0x1d615, 1, { 0x6e, 0 } },
+ { 0x1d616, 1, { 0x6f, 0 } },
+ { 0x1d617, 1, { 0x70, 0 } },
+ { 0x1d618, 1, { 0x71, 0 } },
+ { 0x1d619, 1, { 0x72, 0 } },
+ { 0x1d61a, 1, { 0x73, 0 } },
+ { 0x1d61b, 1, { 0x74, 0 } },
+ { 0x1d61c, 1, { 0x75, 0 } },
+ { 0x1d61d, 1, { 0x76, 0 } },
+ { 0x1d61e, 1, { 0x77, 0 } },
+ { 0x1d61f, 1, { 0x78, 0 } },
+ { 0x1d620, 1, { 0x79, 0 } },
+ { 0x1d621, 1, { 0x7a, 0 } },
+ { 0x1d622, 1, { 0x61, 0 } },
+ { 0x1d623, 1, { 0x62, 0 } },
+ { 0x1d624, 1, { 0x63, 0 } },
+ { 0x1d625, 1, { 0x64, 0 } },
+ { 0x1d626, 1, { 0x65, 0 } },
+ { 0x1d627, 1, { 0x66, 0 } },
+ { 0x1d628, 1, { 0x67, 0 } },
+ { 0x1d629, 1, { 0x68, 0 } },
+ { 0x1d62a, 1, { 0x69, 0 } },
+ { 0x1d62b, 1, { 0x6a, 0 } },
+ { 0x1d62c, 1, { 0x6b, 0 } },
+ { 0x1d62d, 1, { 0x6c, 0 } },
+ { 0x1d62e, 1, { 0x6d, 0 } },
+ { 0x1d62f, 1, { 0x6e, 0 } },
+ { 0x1d630, 1, { 0x6f, 0 } },
+ { 0x1d631, 1, { 0x70, 0 } },
+ { 0x1d632, 1, { 0x71, 0 } },
+ { 0x1d633, 1, { 0x72, 0 } },
+ { 0x1d634, 1, { 0x73, 0 } },
+ { 0x1d635, 1, { 0x74, 0 } },
+ { 0x1d636, 1, { 0x75, 0 } },
+ { 0x1d637, 1, { 0x76, 0 } },
+ { 0x1d638, 1, { 0x77, 0 } },
+ { 0x1d639, 1, { 0x78, 0 } },
+ { 0x1d63a, 1, { 0x79, 0 } },
+ { 0x1d63b, 1, { 0x7a, 0 } },
+ { 0x1d63c, 1, { 0x61, 0 } },
+ { 0x1d63d, 1, { 0x62, 0 } },
+ { 0x1d63e, 1, { 0x63, 0 } },
+ { 0x1d63f, 1, { 0x64, 0 } },
+ { 0x1d640, 1, { 0x65, 0 } },
+ { 0x1d641, 1, { 0x66, 0 } },
+ { 0x1d642, 1, { 0x67, 0 } },
+ { 0x1d643, 1, { 0x68, 0 } },
+ { 0x1d644, 1, { 0x69, 0 } },
+ { 0x1d645, 1, { 0x6a, 0 } },
+ { 0x1d646, 1, { 0x6b, 0 } },
+ { 0x1d647, 1, { 0x6c, 0 } },
+ { 0x1d648, 1, { 0x6d, 0 } },
+ { 0x1d649, 1, { 0x6e, 0 } },
+ { 0x1d64a, 1, { 0x6f, 0 } },
+ { 0x1d64b, 1, { 0x70, 0 } },
+ { 0x1d64c, 1, { 0x71, 0 } },
+ { 0x1d64d, 1, { 0x72, 0 } },
+ { 0x1d64e, 1, { 0x73, 0 } },
+ { 0x1d64f, 1, { 0x74, 0 } },
+ { 0x1d650, 1, { 0x75, 0 } },
+ { 0x1d651, 1, { 0x76, 0 } },
+ { 0x1d652, 1, { 0x77, 0 } },
+ { 0x1d653, 1, { 0x78, 0 } },
+ { 0x1d654, 1, { 0x79, 0 } },
+ { 0x1d655, 1, { 0x7a, 0 } },
+ { 0x1d656, 1, { 0x61, 0 } },
+ { 0x1d657, 1, { 0x62, 0 } },
+ { 0x1d658, 1, { 0x63, 0 } },
+ { 0x1d659, 1, { 0x64, 0 } },
+ { 0x1d65a, 1, { 0x65, 0 } },
+ { 0x1d65b, 1, { 0x66, 0 } },
+ { 0x1d65c, 1, { 0x67, 0 } },
+ { 0x1d65d, 1, { 0x68, 0 } },
+ { 0x1d65e, 1, { 0x69, 0 } },
+ { 0x1d65f, 1, { 0x6a, 0 } },
+ { 0x1d660, 1, { 0x6b, 0 } },
+ { 0x1d661, 1, { 0x6c, 0 } },
+ { 0x1d662, 1, { 0x6d, 0 } },
+ { 0x1d663, 1, { 0x6e, 0 } },
+ { 0x1d664, 1, { 0x6f, 0 } },
+ { 0x1d665, 1, { 0x70, 0 } },
+ { 0x1d666, 1, { 0x71, 0 } },
+ { 0x1d667, 1, { 0x72, 0 } },
+ { 0x1d668, 1, { 0x73, 0 } },
+ { 0x1d669, 1, { 0x74, 0 } },
+ { 0x1d66a, 1, { 0x75, 0 } },
+ { 0x1d66b, 1, { 0x76, 0 } },
+ { 0x1d66c, 1, { 0x77, 0 } },
+ { 0x1d66d, 1, { 0x78, 0 } },
+ { 0x1d66e, 1, { 0x79, 0 } },
+ { 0x1d66f, 1, { 0x7a, 0 } },
+ { 0x1d670, 1, { 0x61, 0 } },
+ { 0x1d671, 1, { 0x62, 0 } },
+ { 0x1d672, 1, { 0x63, 0 } },
+ { 0x1d673, 1, { 0x64, 0 } },
+ { 0x1d674, 1, { 0x65, 0 } },
+ { 0x1d675, 1, { 0x66, 0 } },
+ { 0x1d676, 1, { 0x67, 0 } },
+ { 0x1d677, 1, { 0x68, 0 } },
+ { 0x1d678, 1, { 0x69, 0 } },
+ { 0x1d679, 1, { 0x6a, 0 } },
+ { 0x1d67a, 1, { 0x6b, 0 } },
+ { 0x1d67b, 1, { 0x6c, 0 } },
+ { 0x1d67c, 1, { 0x6d, 0 } },
+ { 0x1d67d, 1, { 0x6e, 0 } },
+ { 0x1d67e, 1, { 0x6f, 0 } },
+ { 0x1d67f, 1, { 0x70, 0 } },
+ { 0x1d680, 1, { 0x71, 0 } },
+ { 0x1d681, 1, { 0x72, 0 } },
+ { 0x1d682, 1, { 0x73, 0 } },
+ { 0x1d683, 1, { 0x74, 0 } },
+ { 0x1d684, 1, { 0x75, 0 } },
+ { 0x1d685, 1, { 0x76, 0 } },
+ { 0x1d686, 1, { 0x77, 0 } },
+ { 0x1d687, 1, { 0x78, 0 } },
+ { 0x1d688, 1, { 0x79, 0 } },
+ { 0x1d689, 1, { 0x7a, 0 } },
+ { 0x1d68a, 1, { 0x61, 0 } },
+ { 0x1d68b, 1, { 0x62, 0 } },
+ { 0x1d68c, 1, { 0x63, 0 } },
+ { 0x1d68d, 1, { 0x64, 0 } },
+ { 0x1d68e, 1, { 0x65, 0 } },
+ { 0x1d68f, 1, { 0x66, 0 } },
+ { 0x1d690, 1, { 0x67, 0 } },
+ { 0x1d691, 1, { 0x68, 0 } },
+ { 0x1d692, 1, { 0x69, 0 } },
+ { 0x1d693, 1, { 0x6a, 0 } },
+ { 0x1d694, 1, { 0x6b, 0 } },
+ { 0x1d695, 1, { 0x6c, 0 } },
+ { 0x1d696, 1, { 0x6d, 0 } },
+ { 0x1d697, 1, { 0x6e, 0 } },
+ { 0x1d698, 1, { 0x6f, 0 } },
+ { 0x1d699, 1, { 0x70, 0 } },
+ { 0x1d69a, 1, { 0x71, 0 } },
+ { 0x1d69b, 1, { 0x72, 0 } },
+ { 0x1d69c, 1, { 0x73, 0 } },
+ { 0x1d69d, 1, { 0x74, 0 } },
+ { 0x1d69e, 1, { 0x75, 0 } },
+ { 0x1d69f, 1, { 0x76, 0 } },
+ { 0x1d6a0, 1, { 0x77, 0 } },
+ { 0x1d6a1, 1, { 0x78, 0 } },
+ { 0x1d6a2, 1, { 0x79, 0 } },
+ { 0x1d6a3, 1, { 0x7a, 0 } },
+ { 0x1d6a4, 1, { 0x131, 0 } },
+ { 0x1d6a5, 1, { 0x237, 0 } },
+ { 0x1d6a8, 1, { 0x3b1, 0 } },
+ { 0x1d6a9, 1, { 0x3b2, 0 } },
+ { 0x1d6aa, 1, { 0x3b3, 0 } },
+ { 0x1d6ab, 1, { 0x3b4, 0 } },
+ { 0x1d6ac, 1, { 0x3b5, 0 } },
+ { 0x1d6ad, 1, { 0x3b6, 0 } },
+ { 0x1d6ae, 1, { 0x3b7, 0 } },
+ { 0x1d6af, 1, { 0x3b8, 0 } },
+ { 0x1d6b0, 1, { 0x3b9, 0 } },
+ { 0x1d6b1, 1, { 0x3ba, 0 } },
+ { 0x1d6b2, 1, { 0x3bb, 0 } },
+ { 0x1d6b3, 1, { 0x3bc, 0 } },
+ { 0x1d6b4, 1, { 0x3bd, 0 } },
+ { 0x1d6b5, 1, { 0x3be, 0 } },
+ { 0x1d6b6, 1, { 0x3bf, 0 } },
+ { 0x1d6b7, 1, { 0x3c0, 0 } },
+ { 0x1d6b8, 1, { 0x3c1, 0 } },
+ { 0x1d6b9, 1, { 0x3b8, 0 } },
+ { 0x1d6ba, 1, { 0x3c3, 0 } },
+ { 0x1d6bb, 1, { 0x3c4, 0 } },
+ { 0x1d6bc, 1, { 0x3c5, 0 } },
+ { 0x1d6bd, 1, { 0x3c6, 0 } },
+ { 0x1d6be, 1, { 0x3c7, 0 } },
+ { 0x1d6bf, 1, { 0x3c8, 0 } },
+ { 0x1d6c0, 1, { 0x3c9, 0 } },
+ { 0x1d6c1, 1, { 0x2207, 0 } },
+ { 0x1d6c2, 1, { 0x3b1, 0 } },
+ { 0x1d6c3, 1, { 0x3b2, 0 } },
+ { 0x1d6c4, 1, { 0x3b3, 0 } },
+ { 0x1d6c5, 1, { 0x3b4, 0 } },
+ { 0x1d6c6, 1, { 0x3b5, 0 } },
+ { 0x1d6c7, 1, { 0x3b6, 0 } },
+ { 0x1d6c8, 1, { 0x3b7, 0 } },
+ { 0x1d6c9, 1, { 0x3b8, 0 } },
+ { 0x1d6ca, 1, { 0x3b9, 0 } },
+ { 0x1d6cb, 1, { 0x3ba, 0 } },
+ { 0x1d6cc, 1, { 0x3bb, 0 } },
+ { 0x1d6cd, 1, { 0x3bc, 0 } },
+ { 0x1d6ce, 1, { 0x3bd, 0 } },
+ { 0x1d6cf, 1, { 0x3be, 0 } },
+ { 0x1d6d0, 1, { 0x3bf, 0 } },
+ { 0x1d6d1, 1, { 0x3c0, 0 } },
+ { 0x1d6d2, 1, { 0x3c1, 0 } },
+ { 0x1d6d3, 1, { 0x3c3, 0 } },
+ { 0x1d6d4, 1, { 0x3c3, 0 } },
+ { 0x1d6d5, 1, { 0x3c4, 0 } },
+ { 0x1d6d6, 1, { 0x3c5, 0 } },
+ { 0x1d6d7, 1, { 0x3c6, 0 } },
+ { 0x1d6d8, 1, { 0x3c7, 0 } },
+ { 0x1d6d9, 1, { 0x3c8, 0 } },
+ { 0x1d6da, 1, { 0x3c9, 0 } },
+ { 0x1d6db, 1, { 0x2202, 0 } },
+ { 0x1d6dc, 1, { 0x3b5, 0 } },
+ { 0x1d6dd, 1, { 0x3b8, 0 } },
+ { 0x1d6de, 1, { 0x3ba, 0 } },
+ { 0x1d6df, 1, { 0x3c6, 0 } },
+ { 0x1d6e0, 1, { 0x3c1, 0 } },
+ { 0x1d6e1, 1, { 0x3c0, 0 } },
+ { 0x1d6e2, 1, { 0x3b1, 0 } },
+ { 0x1d6e3, 1, { 0x3b2, 0 } },
+ { 0x1d6e4, 1, { 0x3b3, 0 } },
+ { 0x1d6e5, 1, { 0x3b4, 0 } },
+ { 0x1d6e6, 1, { 0x3b5, 0 } },
+ { 0x1d6e7, 1, { 0x3b6, 0 } },
+ { 0x1d6e8, 1, { 0x3b7, 0 } },
+ { 0x1d6e9, 1, { 0x3b8, 0 } },
+ { 0x1d6ea, 1, { 0x3b9, 0 } },
+ { 0x1d6eb, 1, { 0x3ba, 0 } },
+ { 0x1d6ec, 1, { 0x3bb, 0 } },
+ { 0x1d6ed, 1, { 0x3bc, 0 } },
+ { 0x1d6ee, 1, { 0x3bd, 0 } },
+ { 0x1d6ef, 1, { 0x3be, 0 } },
+ { 0x1d6f0, 1, { 0x3bf, 0 } },
+ { 0x1d6f1, 1, { 0x3c0, 0 } },
+ { 0x1d6f2, 1, { 0x3c1, 0 } },
+ { 0x1d6f3, 1, { 0x3b8, 0 } },
+ { 0x1d6f4, 1, { 0x3c3, 0 } },
+ { 0x1d6f5, 1, { 0x3c4, 0 } },
+ { 0x1d6f6, 1, { 0x3c5, 0 } },
+ { 0x1d6f7, 1, { 0x3c6, 0 } },
+ { 0x1d6f8, 1, { 0x3c7, 0 } },
+ { 0x1d6f9, 1, { 0x3c8, 0 } },
+ { 0x1d6fa, 1, { 0x3c9, 0 } },
+ { 0x1d6fb, 1, { 0x2207, 0 } },
+ { 0x1d6fc, 1, { 0x3b1, 0 } },
+ { 0x1d6fd, 1, { 0x3b2, 0 } },
+ { 0x1d6fe, 1, { 0x3b3, 0 } },
+ { 0x1d6ff, 1, { 0x3b4, 0 } },
+ { 0x1d700, 1, { 0x3b5, 0 } },
+ { 0x1d701, 1, { 0x3b6, 0 } },
+ { 0x1d702, 1, { 0x3b7, 0 } },
+ { 0x1d703, 1, { 0x3b8, 0 } },
+ { 0x1d704, 1, { 0x3b9, 0 } },
+ { 0x1d705, 1, { 0x3ba, 0 } },
+ { 0x1d706, 1, { 0x3bb, 0 } },
+ { 0x1d707, 1, { 0x3bc, 0 } },
+ { 0x1d708, 1, { 0x3bd, 0 } },
+ { 0x1d709, 1, { 0x3be, 0 } },
+ { 0x1d70a, 1, { 0x3bf, 0 } },
+ { 0x1d70b, 1, { 0x3c0, 0 } },
+ { 0x1d70c, 1, { 0x3c1, 0 } },
+ { 0x1d70d, 1, { 0x3c3, 0 } },
+ { 0x1d70e, 1, { 0x3c3, 0 } },
+ { 0x1d70f, 1, { 0x3c4, 0 } },
+ { 0x1d710, 1, { 0x3c5, 0 } },
+ { 0x1d711, 1, { 0x3c6, 0 } },
+ { 0x1d712, 1, { 0x3c7, 0 } },
+ { 0x1d713, 1, { 0x3c8, 0 } },
+ { 0x1d714, 1, { 0x3c9, 0 } },
+ { 0x1d715, 1, { 0x2202, 0 } },
+ { 0x1d716, 1, { 0x3b5, 0 } },
+ { 0x1d717, 1, { 0x3b8, 0 } },
+ { 0x1d718, 1, { 0x3ba, 0 } },
+ { 0x1d719, 1, { 0x3c6, 0 } },
+ { 0x1d71a, 1, { 0x3c1, 0 } },
+ { 0x1d71b, 1, { 0x3c0, 0 } },
+ { 0x1d71c, 1, { 0x3b1, 0 } },
+ { 0x1d71d, 1, { 0x3b2, 0 } },
+ { 0x1d71e, 1, { 0x3b3, 0 } },
+ { 0x1d71f, 1, { 0x3b4, 0 } },
+ { 0x1d720, 1, { 0x3b5, 0 } },
+ { 0x1d721, 1, { 0x3b6, 0 } },
+ { 0x1d722, 1, { 0x3b7, 0 } },
+ { 0x1d723, 1, { 0x3b8, 0 } },
+ { 0x1d724, 1, { 0x3b9, 0 } },
+ { 0x1d725, 1, { 0x3ba, 0 } },
+ { 0x1d726, 1, { 0x3bb, 0 } },
+ { 0x1d727, 1, { 0x3bc, 0 } },
+ { 0x1d728, 1, { 0x3bd, 0 } },
+ { 0x1d729, 1, { 0x3be, 0 } },
+ { 0x1d72a, 1, { 0x3bf, 0 } },
+ { 0x1d72b, 1, { 0x3c0, 0 } },
+ { 0x1d72c, 1, { 0x3c1, 0 } },
+ { 0x1d72d, 1, { 0x3b8, 0 } },
+ { 0x1d72e, 1, { 0x3c3, 0 } },
+ { 0x1d72f, 1, { 0x3c4, 0 } },
+ { 0x1d730, 1, { 0x3c5, 0 } },
+ { 0x1d731, 1, { 0x3c6, 0 } },
+ { 0x1d732, 1, { 0x3c7, 0 } },
+ { 0x1d733, 1, { 0x3c8, 0 } },
+ { 0x1d734, 1, { 0x3c9, 0 } },
+ { 0x1d735, 1, { 0x2207, 0 } },
+ { 0x1d736, 1, { 0x3b1, 0 } },
+ { 0x1d737, 1, { 0x3b2, 0 } },
+ { 0x1d738, 1, { 0x3b3, 0 } },
+ { 0x1d739, 1, { 0x3b4, 0 } },
+ { 0x1d73a, 1, { 0x3b5, 0 } },
+ { 0x1d73b, 1, { 0x3b6, 0 } },
+ { 0x1d73c, 1, { 0x3b7, 0 } },
+ { 0x1d73d, 1, { 0x3b8, 0 } },
+ { 0x1d73e, 1, { 0x3b9, 0 } },
+ { 0x1d73f, 1, { 0x3ba, 0 } },
+ { 0x1d740, 1, { 0x3bb, 0 } },
+ { 0x1d741, 1, { 0x3bc, 0 } },
+ { 0x1d742, 1, { 0x3bd, 0 } },
+ { 0x1d743, 1, { 0x3be, 0 } },
+ { 0x1d744, 1, { 0x3bf, 0 } },
+ { 0x1d745, 1, { 0x3c0, 0 } },
+ { 0x1d746, 1, { 0x3c1, 0 } },
+ { 0x1d747, 1, { 0x3c3, 0 } },
+ { 0x1d748, 1, { 0x3c3, 0 } },
+ { 0x1d749, 1, { 0x3c4, 0 } },
+ { 0x1d74a, 1, { 0x3c5, 0 } },
+ { 0x1d74b, 1, { 0x3c6, 0 } },
+ { 0x1d74c, 1, { 0x3c7, 0 } },
+ { 0x1d74d, 1, { 0x3c8, 0 } },
+ { 0x1d74e, 1, { 0x3c9, 0 } },
+ { 0x1d74f, 1, { 0x2202, 0 } },
+ { 0x1d750, 1, { 0x3b5, 0 } },
+ { 0x1d751, 1, { 0x3b8, 0 } },
+ { 0x1d752, 1, { 0x3ba, 0 } },
+ { 0x1d753, 1, { 0x3c6, 0 } },
+ { 0x1d754, 1, { 0x3c1, 0 } },
+ { 0x1d755, 1, { 0x3c0, 0 } },
+ { 0x1d756, 1, { 0x3b1, 0 } },
+ { 0x1d757, 1, { 0x3b2, 0 } },
+ { 0x1d758, 1, { 0x3b3, 0 } },
+ { 0x1d759, 1, { 0x3b4, 0 } },
+ { 0x1d75a, 1, { 0x3b5, 0 } },
+ { 0x1d75b, 1, { 0x3b6, 0 } },
+ { 0x1d75c, 1, { 0x3b7, 0 } },
+ { 0x1d75d, 1, { 0x3b8, 0 } },
+ { 0x1d75e, 1, { 0x3b9, 0 } },
+ { 0x1d75f, 1, { 0x3ba, 0 } },
+ { 0x1d760, 1, { 0x3bb, 0 } },
+ { 0x1d761, 1, { 0x3bc, 0 } },
+ { 0x1d762, 1, { 0x3bd, 0 } },
+ { 0x1d763, 1, { 0x3be, 0 } },
+ { 0x1d764, 1, { 0x3bf, 0 } },
+ { 0x1d765, 1, { 0x3c0, 0 } },
+ { 0x1d766, 1, { 0x3c1, 0 } },
+ { 0x1d767, 1, { 0x3b8, 0 } },
+ { 0x1d768, 1, { 0x3c3, 0 } },
+ { 0x1d769, 1, { 0x3c4, 0 } },
+ { 0x1d76a, 1, { 0x3c5, 0 } },
+ { 0x1d76b, 1, { 0x3c6, 0 } },
+ { 0x1d76c, 1, { 0x3c7, 0 } },
+ { 0x1d76d, 1, { 0x3c8, 0 } },
+ { 0x1d76e, 1, { 0x3c9, 0 } },
+ { 0x1d76f, 1, { 0x2207, 0 } },
+ { 0x1d770, 1, { 0x3b1, 0 } },
+ { 0x1d771, 1, { 0x3b2, 0 } },
+ { 0x1d772, 1, { 0x3b3, 0 } },
+ { 0x1d773, 1, { 0x3b4, 0 } },
+ { 0x1d774, 1, { 0x3b5, 0 } },
+ { 0x1d775, 1, { 0x3b6, 0 } },
+ { 0x1d776, 1, { 0x3b7, 0 } },
+ { 0x1d777, 1, { 0x3b8, 0 } },
+ { 0x1d778, 1, { 0x3b9, 0 } },
+ { 0x1d779, 1, { 0x3ba, 0 } },
+ { 0x1d77a, 1, { 0x3bb, 0 } },
+ { 0x1d77b, 1, { 0x3bc, 0 } },
+ { 0x1d77c, 1, { 0x3bd, 0 } },
+ { 0x1d77d, 1, { 0x3be, 0 } },
+ { 0x1d77e, 1, { 0x3bf, 0 } },
+ { 0x1d77f, 1, { 0x3c0, 0 } },
+ { 0x1d780, 1, { 0x3c1, 0 } },
+ { 0x1d781, 1, { 0x3c3, 0 } },
+ { 0x1d782, 1, { 0x3c3, 0 } },
+ { 0x1d783, 1, { 0x3c4, 0 } },
+ { 0x1d784, 1, { 0x3c5, 0 } },
+ { 0x1d785, 1, { 0x3c6, 0 } },
+ { 0x1d786, 1, { 0x3c7, 0 } },
+ { 0x1d787, 1, { 0x3c8, 0 } },
+ { 0x1d788, 1, { 0x3c9, 0 } },
+ { 0x1d789, 1, { 0x2202, 0 } },
+ { 0x1d78a, 1, { 0x3b5, 0 } },
+ { 0x1d78b, 1, { 0x3b8, 0 } },
+ { 0x1d78c, 1, { 0x3ba, 0 } },
+ { 0x1d78d, 1, { 0x3c6, 0 } },
+ { 0x1d78e, 1, { 0x3c1, 0 } },
+ { 0x1d78f, 1, { 0x3c0, 0 } },
+ { 0x1d790, 1, { 0x3b1, 0 } },
+ { 0x1d791, 1, { 0x3b2, 0 } },
+ { 0x1d792, 1, { 0x3b3, 0 } },
+ { 0x1d793, 1, { 0x3b4, 0 } },
+ { 0x1d794, 1, { 0x3b5, 0 } },
+ { 0x1d795, 1, { 0x3b6, 0 } },
+ { 0x1d796, 1, { 0x3b7, 0 } },
+ { 0x1d797, 1, { 0x3b8, 0 } },
+ { 0x1d798, 1, { 0x3b9, 0 } },
+ { 0x1d799, 1, { 0x3ba, 0 } },
+ { 0x1d79a, 1, { 0x3bb, 0 } },
+ { 0x1d79b, 1, { 0x3bc, 0 } },
+ { 0x1d79c, 1, { 0x3bd, 0 } },
+ { 0x1d79d, 1, { 0x3be, 0 } },
+ { 0x1d79e, 1, { 0x3bf, 0 } },
+ { 0x1d79f, 1, { 0x3c0, 0 } },
+ { 0x1d7a0, 1, { 0x3c1, 0 } },
+ { 0x1d7a1, 1, { 0x3b8, 0 } },
+ { 0x1d7a2, 1, { 0x3c3, 0 } },
+ { 0x1d7a3, 1, { 0x3c4, 0 } },
+ { 0x1d7a4, 1, { 0x3c5, 0 } },
+ { 0x1d7a5, 1, { 0x3c6, 0 } },
+ { 0x1d7a6, 1, { 0x3c7, 0 } },
+ { 0x1d7a7, 1, { 0x3c8, 0 } },
+ { 0x1d7a8, 1, { 0x3c9, 0 } },
+ { 0x1d7a9, 1, { 0x2207, 0 } },
+ { 0x1d7aa, 1, { 0x3b1, 0 } },
+ { 0x1d7ab, 1, { 0x3b2, 0 } },
+ { 0x1d7ac, 1, { 0x3b3, 0 } },
+ { 0x1d7ad, 1, { 0x3b4, 0 } },
+ { 0x1d7ae, 1, { 0x3b5, 0 } },
+ { 0x1d7af, 1, { 0x3b6, 0 } },
+ { 0x1d7b0, 1, { 0x3b7, 0 } },
+ { 0x1d7b1, 1, { 0x3b8, 0 } },
+ { 0x1d7b2, 1, { 0x3b9, 0 } },
+ { 0x1d7b3, 1, { 0x3ba, 0 } },
+ { 0x1d7b4, 1, { 0x3bb, 0 } },
+ { 0x1d7b5, 1, { 0x3bc, 0 } },
+ { 0x1d7b6, 1, { 0x3bd, 0 } },
+ { 0x1d7b7, 1, { 0x3be, 0 } },
+ { 0x1d7b8, 1, { 0x3bf, 0 } },
+ { 0x1d7b9, 1, { 0x3c0, 0 } },
+ { 0x1d7ba, 1, { 0x3c1, 0 } },
+ { 0x1d7bb, 1, { 0x3c3, 0 } },
+ { 0x1d7bc, 1, { 0x3c3, 0 } },
+ { 0x1d7bd, 1, { 0x3c4, 0 } },
+ { 0x1d7be, 1, { 0x3c5, 0 } },
+ { 0x1d7bf, 1, { 0x3c6, 0 } },
+ { 0x1d7c0, 1, { 0x3c7, 0 } },
+ { 0x1d7c1, 1, { 0x3c8, 0 } },
+ { 0x1d7c2, 1, { 0x3c9, 0 } },
+ { 0x1d7c3, 1, { 0x2202, 0 } },
+ { 0x1d7c4, 1, { 0x3b5, 0 } },
+ { 0x1d7c5, 1, { 0x3b8, 0 } },
+ { 0x1d7c6, 1, { 0x3ba, 0 } },
+ { 0x1d7c7, 1, { 0x3c6, 0 } },
+ { 0x1d7c8, 1, { 0x3c1, 0 } },
+ { 0x1d7c9, 1, { 0x3c0, 0 } },
+ { 0x1d7ca, 1, { 0x3dd, 0 } },
+ { 0x1d7cb, 1, { 0x3dd, 0 } },
+ { 0x1d7ce, 1, { 0x30, 0 } },
+ { 0x1d7cf, 1, { 0x31, 0 } },
+ { 0x1d7d0, 1, { 0x32, 0 } },
+ { 0x1d7d1, 1, { 0x33, 0 } },
+ { 0x1d7d2, 1, { 0x34, 0 } },
+ { 0x1d7d3, 1, { 0x35, 0 } },
+ { 0x1d7d4, 1, { 0x36, 0 } },
+ { 0x1d7d5, 1, { 0x37, 0 } },
+ { 0x1d7d6, 1, { 0x38, 0 } },
+ { 0x1d7d7, 1, { 0x39, 0 } },
+ { 0x1d7d8, 1, { 0x30, 0 } },
+ { 0x1d7d9, 1, { 0x31, 0 } },
+ { 0x1d7da, 1, { 0x32, 0 } },
+ { 0x1d7db, 1, { 0x33, 0 } },
+ { 0x1d7dc, 1, { 0x34, 0 } },
+ { 0x1d7dd, 1, { 0x35, 0 } },
+ { 0x1d7de, 1, { 0x36, 0 } },
+ { 0x1d7df, 1, { 0x37, 0 } },
+ { 0x1d7e0, 1, { 0x38, 0 } },
+ { 0x1d7e1, 1, { 0x39, 0 } },
+ { 0x1d7e2, 1, { 0x30, 0 } },
+ { 0x1d7e3, 1, { 0x31, 0 } },
+ { 0x1d7e4, 1, { 0x32, 0 } },
+ { 0x1d7e5, 1, { 0x33, 0 } },
+ { 0x1d7e6, 1, { 0x34, 0 } },
+ { 0x1d7e7, 1, { 0x35, 0 } },
+ { 0x1d7e8, 1, { 0x36, 0 } },
+ { 0x1d7e9, 1, { 0x37, 0 } },
+ { 0x1d7ea, 1, { 0x38, 0 } },
+ { 0x1d7eb, 1, { 0x39, 0 } },
+ { 0x1d7ec, 1, { 0x30, 0 } },
+ { 0x1d7ed, 1, { 0x31, 0 } },
+ { 0x1d7ee, 1, { 0x32, 0 } },
+ { 0x1d7ef, 1, { 0x33, 0 } },
+ { 0x1d7f0, 1, { 0x34, 0 } },
+ { 0x1d7f1, 1, { 0x35, 0 } },
+ { 0x1d7f2, 1, { 0x36, 0 } },
+ { 0x1d7f3, 1, { 0x37, 0 } },
+ { 0x1d7f4, 1, { 0x38, 0 } },
+ { 0x1d7f5, 1, { 0x39, 0 } },
+ { 0x1d7f6, 1, { 0x30, 0 } },
+ { 0x1d7f7, 1, { 0x31, 0 } },
+ { 0x1d7f8, 1, { 0x32, 0 } },
+ { 0x1d7f9, 1, { 0x33, 0 } },
+ { 0x1d7fa, 1, { 0x34, 0 } },
+ { 0x1d7fb, 1, { 0x35, 0 } },
+ { 0x1d7fc, 1, { 0x36, 0 } },
+ { 0x1d7fd, 1, { 0x37, 0 } },
+ { 0x1d7fe, 1, { 0x38, 0 } },
+ { 0x1d7ff, 1, { 0x39, 0 } },
+ { 0x1e030, 1, { 0x430, 0 } },
+ { 0x1e031, 1, { 0x431, 0 } },
+ { 0x1e032, 1, { 0x432, 0 } },
+ { 0x1e033, 1, { 0x433, 0 } },
+ { 0x1e034, 1, { 0x434, 0 } },
+ { 0x1e035, 1, { 0x435, 0 } },
+ { 0x1e036, 1, { 0x436, 0 } },
+ { 0x1e037, 1, { 0x437, 0 } },
+ { 0x1e038, 1, { 0x438, 0 } },
+ { 0x1e039, 1, { 0x43a, 0 } },
+ { 0x1e03a, 1, { 0x43b, 0 } },
+ { 0x1e03b, 1, { 0x43c, 0 } },
+ { 0x1e03c, 1, { 0x43e, 0 } },
+ { 0x1e03d, 1, { 0x43f, 0 } },
+ { 0x1e03e, 1, { 0x440, 0 } },
+ { 0x1e03f, 1, { 0x441, 0 } },
+ { 0x1e040, 1, { 0x442, 0 } },
+ { 0x1e041, 1, { 0x443, 0 } },
+ { 0x1e042, 1, { 0x444, 0 } },
+ { 0x1e043, 1, { 0x445, 0 } },
+ { 0x1e044, 1, { 0x446, 0 } },
+ { 0x1e045, 1, { 0x447, 0 } },
+ { 0x1e046, 1, { 0x448, 0 } },
+ { 0x1e047, 1, { 0x44b, 0 } },
+ { 0x1e048, 1, { 0x44d, 0 } },
+ { 0x1e049, 1, { 0x44e, 0 } },
+ { 0x1e04a, 1, { 0xa689, 0 } },
+ { 0x1e04b, 1, { 0x4d9, 0 } },
+ { 0x1e04c, 1, { 0x456, 0 } },
+ { 0x1e04d, 1, { 0x458, 0 } },
+ { 0x1e04e, 1, { 0x4e9, 0 } },
+ { 0x1e04f, 1, { 0x4af, 0 } },
+ { 0x1e050, 1, { 0x4cf, 0 } },
+ { 0x1e051, 1, { 0x430, 0 } },
+ { 0x1e052, 1, { 0x431, 0 } },
+ { 0x1e053, 1, { 0x432, 0 } },
+ { 0x1e054, 1, { 0x433, 0 } },
+ { 0x1e055, 1, { 0x434, 0 } },
+ { 0x1e056, 1, { 0x435, 0 } },
+ { 0x1e057, 1, { 0x436, 0 } },
+ { 0x1e058, 1, { 0x437, 0 } },
+ { 0x1e059, 1, { 0x438, 0 } },
+ { 0x1e05a, 1, { 0x43a, 0 } },
+ { 0x1e05b, 1, { 0x43b, 0 } },
+ { 0x1e05c, 1, { 0x43e, 0 } },
+ { 0x1e05d, 1, { 0x43f, 0 } },
+ { 0x1e05e, 1, { 0x441, 0 } },
+ { 0x1e05f, 1, { 0x443, 0 } },
+ { 0x1e060, 1, { 0x444, 0 } },
+ { 0x1e061, 1, { 0x445, 0 } },
+ { 0x1e062, 1, { 0x446, 0 } },
+ { 0x1e063, 1, { 0x447, 0 } },
+ { 0x1e064, 1, { 0x448, 0 } },
+ { 0x1e065, 1, { 0x44a, 0 } },
+ { 0x1e066, 1, { 0x44b, 0 } },
+ { 0x1e067, 1, { 0x491, 0 } },
+ { 0x1e068, 1, { 0x456, 0 } },
+ { 0x1e069, 1, { 0x455, 0 } },
+ { 0x1e06a, 1, { 0x45f, 0 } },
+ { 0x1e06b, 1, { 0x4ab, 0 } },
+ { 0x1e06c, 1, { 0xa651, 0 } },
+ { 0x1e06d, 1, { 0x4b1, 0 } },
+ { 0x1e900, 2, { 0xd83a, 0xdd22 } },
+ { 0x1e901, 2, { 0xd83a, 0xdd23 } },
+ { 0x1e902, 2, { 0xd83a, 0xdd24 } },
+ { 0x1e903, 2, { 0xd83a, 0xdd25 } },
+ { 0x1e904, 2, { 0xd83a, 0xdd26 } },
+ { 0x1e905, 2, { 0xd83a, 0xdd27 } },
+ { 0x1e906, 2, { 0xd83a, 0xdd28 } },
+ { 0x1e907, 2, { 0xd83a, 0xdd29 } },
+ { 0x1e908, 2, { 0xd83a, 0xdd2a } },
+ { 0x1e909, 2, { 0xd83a, 0xdd2b } },
+ { 0x1e90a, 2, { 0xd83a, 0xdd2c } },
+ { 0x1e90b, 2, { 0xd83a, 0xdd2d } },
+ { 0x1e90c, 2, { 0xd83a, 0xdd2e } },
+ { 0x1e90d, 2, { 0xd83a, 0xdd2f } },
+ { 0x1e90e, 2, { 0xd83a, 0xdd30 } },
+ { 0x1e90f, 2, { 0xd83a, 0xdd31 } },
+ { 0x1e910, 2, { 0xd83a, 0xdd32 } },
+ { 0x1e911, 2, { 0xd83a, 0xdd33 } },
+ { 0x1e912, 2, { 0xd83a, 0xdd34 } },
+ { 0x1e913, 2, { 0xd83a, 0xdd35 } },
+ { 0x1e914, 2, { 0xd83a, 0xdd36 } },
+ { 0x1e915, 2, { 0xd83a, 0xdd37 } },
+ { 0x1e916, 2, { 0xd83a, 0xdd38 } },
+ { 0x1e917, 2, { 0xd83a, 0xdd39 } },
+ { 0x1e918, 2, { 0xd83a, 0xdd3a } },
+ { 0x1e919, 2, { 0xd83a, 0xdd3b } },
+ { 0x1e91a, 2, { 0xd83a, 0xdd3c } },
+ { 0x1e91b, 2, { 0xd83a, 0xdd3d } },
+ { 0x1e91c, 2, { 0xd83a, 0xdd3e } },
+ { 0x1e91d, 2, { 0xd83a, 0xdd3f } },
+ { 0x1e91e, 2, { 0xd83a, 0xdd40 } },
+ { 0x1e91f, 2, { 0xd83a, 0xdd41 } },
+ { 0x1e920, 2, { 0xd83a, 0xdd42 } },
+ { 0x1e921, 2, { 0xd83a, 0xdd43 } },
+ { 0x1ee00, 1, { 0x627, 0 } },
+ { 0x1ee01, 1, { 0x628, 0 } },
+ { 0x1ee02, 1, { 0x62c, 0 } },
+ { 0x1ee03, 1, { 0x62f, 0 } },
+ { 0x1ee05, 1, { 0x648, 0 } },
+ { 0x1ee06, 1, { 0x632, 0 } },
+ { 0x1ee07, 1, { 0x62d, 0 } },
+ { 0x1ee08, 1, { 0x637, 0 } },
+ { 0x1ee09, 1, { 0x64a, 0 } },
+ { 0x1ee0a, 1, { 0x643, 0 } },
+ { 0x1ee0b, 1, { 0x644, 0 } },
+ { 0x1ee0c, 1, { 0x645, 0 } },
+ { 0x1ee0d, 1, { 0x646, 0 } },
+ { 0x1ee0e, 1, { 0x633, 0 } },
+ { 0x1ee0f, 1, { 0x639, 0 } },
+ { 0x1ee10, 1, { 0x641, 0 } },
+ { 0x1ee11, 1, { 0x635, 0 } },
+ { 0x1ee12, 1, { 0x642, 0 } },
+ { 0x1ee13, 1, { 0x631, 0 } },
+ { 0x1ee14, 1, { 0x634, 0 } },
+ { 0x1ee15, 1, { 0x62a, 0 } },
+ { 0x1ee16, 1, { 0x62b, 0 } },
+ { 0x1ee17, 1, { 0x62e, 0 } },
+ { 0x1ee18, 1, { 0x630, 0 } },
+ { 0x1ee19, 1, { 0x636, 0 } },
+ { 0x1ee1a, 1, { 0x638, 0 } },
+ { 0x1ee1b, 1, { 0x63a, 0 } },
+ { 0x1ee1c, 1, { 0x66e, 0 } },
+ { 0x1ee1d, 1, { 0x6ba, 0 } },
+ { 0x1ee1e, 1, { 0x6a1, 0 } },
+ { 0x1ee1f, 1, { 0x66f, 0 } },
+ { 0x1ee21, 1, { 0x628, 0 } },
+ { 0x1ee22, 1, { 0x62c, 0 } },
+ { 0x1ee24, 1, { 0x647, 0 } },
+ { 0x1ee27, 1, { 0x62d, 0 } },
+ { 0x1ee29, 1, { 0x64a, 0 } },
+ { 0x1ee2a, 1, { 0x643, 0 } },
+ { 0x1ee2b, 1, { 0x644, 0 } },
+ { 0x1ee2c, 1, { 0x645, 0 } },
+ { 0x1ee2d, 1, { 0x646, 0 } },
+ { 0x1ee2e, 1, { 0x633, 0 } },
+ { 0x1ee2f, 1, { 0x639, 0 } },
+ { 0x1ee30, 1, { 0x641, 0 } },
+ { 0x1ee31, 1, { 0x635, 0 } },
+ { 0x1ee32, 1, { 0x642, 0 } },
+ { 0x1ee34, 1, { 0x634, 0 } },
+ { 0x1ee35, 1, { 0x62a, 0 } },
+ { 0x1ee36, 1, { 0x62b, 0 } },
+ { 0x1ee37, 1, { 0x62e, 0 } },
+ { 0x1ee39, 1, { 0x636, 0 } },
+ { 0x1ee3b, 1, { 0x63a, 0 } },
+ { 0x1ee42, 1, { 0x62c, 0 } },
+ { 0x1ee47, 1, { 0x62d, 0 } },
+ { 0x1ee49, 1, { 0x64a, 0 } },
+ { 0x1ee4b, 1, { 0x644, 0 } },
+ { 0x1ee4d, 1, { 0x646, 0 } },
+ { 0x1ee4e, 1, { 0x633, 0 } },
+ { 0x1ee4f, 1, { 0x639, 0 } },
+ { 0x1ee51, 1, { 0x635, 0 } },
+ { 0x1ee52, 1, { 0x642, 0 } },
+ { 0x1ee54, 1, { 0x634, 0 } },
+ { 0x1ee57, 1, { 0x62e, 0 } },
+ { 0x1ee59, 1, { 0x636, 0 } },
+ { 0x1ee5b, 1, { 0x63a, 0 } },
+ { 0x1ee5d, 1, { 0x6ba, 0 } },
+ { 0x1ee5f, 1, { 0x66f, 0 } },
+ { 0x1ee61, 1, { 0x628, 0 } },
+ { 0x1ee62, 1, { 0x62c, 0 } },
+ { 0x1ee64, 1, { 0x647, 0 } },
+ { 0x1ee67, 1, { 0x62d, 0 } },
+ { 0x1ee68, 1, { 0x637, 0 } },
+ { 0x1ee69, 1, { 0x64a, 0 } },
+ { 0x1ee6a, 1, { 0x643, 0 } },
+ { 0x1ee6c, 1, { 0x645, 0 } },
+ { 0x1ee6d, 1, { 0x646, 0 } },
+ { 0x1ee6e, 1, { 0x633, 0 } },
+ { 0x1ee6f, 1, { 0x639, 0 } },
+ { 0x1ee70, 1, { 0x641, 0 } },
+ { 0x1ee71, 1, { 0x635, 0 } },
+ { 0x1ee72, 1, { 0x642, 0 } },
+ { 0x1ee74, 1, { 0x634, 0 } },
+ { 0x1ee75, 1, { 0x62a, 0 } },
+ { 0x1ee76, 1, { 0x62b, 0 } },
+ { 0x1ee77, 1, { 0x62e, 0 } },
+ { 0x1ee79, 1, { 0x636, 0 } },
+ { 0x1ee7a, 1, { 0x638, 0 } },
+ { 0x1ee7b, 1, { 0x63a, 0 } },
+ { 0x1ee7c, 1, { 0x66e, 0 } },
+ { 0x1ee7e, 1, { 0x6a1, 0 } },
+ { 0x1ee80, 1, { 0x627, 0 } },
+ { 0x1ee81, 1, { 0x628, 0 } },
+ { 0x1ee82, 1, { 0x62c, 0 } },
+ { 0x1ee83, 1, { 0x62f, 0 } },
+ { 0x1ee84, 1, { 0x647, 0 } },
+ { 0x1ee85, 1, { 0x648, 0 } },
+ { 0x1ee86, 1, { 0x632, 0 } },
+ { 0x1ee87, 1, { 0x62d, 0 } },
+ { 0x1ee88, 1, { 0x637, 0 } },
+ { 0x1ee89, 1, { 0x64a, 0 } },
+ { 0x1ee8b, 1, { 0x644, 0 } },
+ { 0x1ee8c, 1, { 0x645, 0 } },
+ { 0x1ee8d, 1, { 0x646, 0 } },
+ { 0x1ee8e, 1, { 0x633, 0 } },
+ { 0x1ee8f, 1, { 0x639, 0 } },
+ { 0x1ee90, 1, { 0x641, 0 } },
+ { 0x1ee91, 1, { 0x635, 0 } },
+ { 0x1ee92, 1, { 0x642, 0 } },
+ { 0x1ee93, 1, { 0x631, 0 } },
+ { 0x1ee94, 1, { 0x634, 0 } },
+ { 0x1ee95, 1, { 0x62a, 0 } },
+ { 0x1ee96, 1, { 0x62b, 0 } },
+ { 0x1ee97, 1, { 0x62e, 0 } },
+ { 0x1ee98, 1, { 0x630, 0 } },
+ { 0x1ee99, 1, { 0x636, 0 } },
+ { 0x1ee9a, 1, { 0x638, 0 } },
+ { 0x1ee9b, 1, { 0x63a, 0 } },
+ { 0x1eea1, 1, { 0x628, 0 } },
+ { 0x1eea2, 1, { 0x62c, 0 } },
+ { 0x1eea3, 1, { 0x62f, 0 } },
+ { 0x1eea5, 1, { 0x648, 0 } },
+ { 0x1eea6, 1, { 0x632, 0 } },
+ { 0x1eea7, 1, { 0x62d, 0 } },
+ { 0x1eea8, 1, { 0x637, 0 } },
+ { 0x1eea9, 1, { 0x64a, 0 } },
+ { 0x1eeab, 1, { 0x644, 0 } },
+ { 0x1eeac, 1, { 0x645, 0 } },
+ { 0x1eead, 1, { 0x646, 0 } },
+ { 0x1eeae, 1, { 0x633, 0 } },
+ { 0x1eeaf, 1, { 0x639, 0 } },
+ { 0x1eeb0, 1, { 0x641, 0 } },
+ { 0x1eeb1, 1, { 0x635, 0 } },
+ { 0x1eeb2, 1, { 0x642, 0 } },
+ { 0x1eeb3, 1, { 0x631, 0 } },
+ { 0x1eeb4, 1, { 0x634, 0 } },
+ { 0x1eeb5, 1, { 0x62a, 0 } },
+ { 0x1eeb6, 1, { 0x62b, 0 } },
+ { 0x1eeb7, 1, { 0x62e, 0 } },
+ { 0x1eeb8, 1, { 0x630, 0 } },
+ { 0x1eeb9, 1, { 0x636, 0 } },
+ { 0x1eeba, 1, { 0x638, 0 } },
+ { 0x1eebb, 1, { 0x63a, 0 } },
+ { 0x1f12a, 3, { 436, 0 } },
+ { 0x1f12b, 1, { 0x63, 0 } },
+ { 0x1f12c, 1, { 0x72, 0 } },
+ { 0x1f12d, 2, { 0x63, 0x64 } },
+ { 0x1f12e, 2, { 0x77, 0x7a } },
+ { 0x1f130, 1, { 0x61, 0 } },
+ { 0x1f131, 1, { 0x62, 0 } },
+ { 0x1f132, 1, { 0x63, 0 } },
+ { 0x1f133, 1, { 0x64, 0 } },
+ { 0x1f134, 1, { 0x65, 0 } },
+ { 0x1f135, 1, { 0x66, 0 } },
+ { 0x1f136, 1, { 0x67, 0 } },
+ { 0x1f137, 1, { 0x68, 0 } },
+ { 0x1f138, 1, { 0x69, 0 } },
+ { 0x1f139, 1, { 0x6a, 0 } },
+ { 0x1f13a, 1, { 0x6b, 0 } },
+ { 0x1f13b, 1, { 0x6c, 0 } },
+ { 0x1f13c, 1, { 0x6d, 0 } },
+ { 0x1f13d, 1, { 0x6e, 0 } },
+ { 0x1f13e, 1, { 0x6f, 0 } },
+ { 0x1f13f, 1, { 0x70, 0 } },
+ { 0x1f140, 1, { 0x71, 0 } },
+ { 0x1f141, 1, { 0x72, 0 } },
+ { 0x1f142, 1, { 0x73, 0 } },
+ { 0x1f143, 1, { 0x74, 0 } },
+ { 0x1f144, 1, { 0x75, 0 } },
+ { 0x1f145, 1, { 0x76, 0 } },
+ { 0x1f146, 1, { 0x77, 0 } },
+ { 0x1f147, 1, { 0x78, 0 } },
+ { 0x1f148, 1, { 0x79, 0 } },
+ { 0x1f149, 1, { 0x7a, 0 } },
+ { 0x1f14a, 2, { 0x68, 0x76 } },
+ { 0x1f14b, 2, { 0x6d, 0x76 } },
+ { 0x1f14c, 2, { 0x73, 0x64 } },
+ { 0x1f14d, 2, { 0x73, 0x73 } },
+ { 0x1f14e, 3, { 727, 0 } },
+ { 0x1f14f, 2, { 0x77, 0x63 } },
+ { 0x1f16a, 2, { 0x6d, 0x63 } },
+ { 0x1f16b, 2, { 0x6d, 0x64 } },
+ { 0x1f16c, 2, { 0x6d, 0x72 } },
+ { 0x1f190, 2, { 0x64, 0x6a } },
+ { 0x1f200, 2, { 0x307b, 0x304b } },
+ { 0x1f201, 2, { 0x30b3, 0x30b3 } },
+ { 0x1f202, 1, { 0x30b5, 0 } },
+ { 0x1f210, 1, { 0x624b, 0 } },
+ { 0x1f211, 1, { 0x5b57, 0 } },
+ { 0x1f212, 1, { 0x53cc, 0 } },
+ { 0x1f213, 1, { 0x30c7, 0 } },
+ { 0x1f214, 1, { 0x4e8c, 0 } },
+ { 0x1f215, 1, { 0x591a, 0 } },
+ { 0x1f216, 1, { 0x89e3, 0 } },
+ { 0x1f217, 1, { 0x5929, 0 } },
+ { 0x1f218, 1, { 0x4ea4, 0 } },
+ { 0x1f219, 1, { 0x6620, 0 } },
+ { 0x1f21a, 1, { 0x7121, 0 } },
+ { 0x1f21b, 1, { 0x6599, 0 } },
+ { 0x1f21c, 1, { 0x524d, 0 } },
+ { 0x1f21d, 1, { 0x5f8c, 0 } },
+ { 0x1f21e, 1, { 0x518d, 0 } },
+ { 0x1f21f, 1, { 0x65b0, 0 } },
+ { 0x1f220, 1, { 0x521d, 0 } },
+ { 0x1f221, 1, { 0x7d42, 0 } },
+ { 0x1f222, 1, { 0x751f, 0 } },
+ { 0x1f223, 1, { 0x8ca9, 0 } },
+ { 0x1f224, 1, { 0x58f0, 0 } },
+ { 0x1f225, 1, { 0x5439, 0 } },
+ { 0x1f226, 1, { 0x6f14, 0 } },
+ { 0x1f227, 1, { 0x6295, 0 } },
+ { 0x1f228, 1, { 0x6355, 0 } },
+ { 0x1f229, 1, { 0x4e00, 0 } },
+ { 0x1f22a, 1, { 0x4e09, 0 } },
+ { 0x1f22b, 1, { 0x904a, 0 } },
+ { 0x1f22c, 1, { 0x5de6, 0 } },
+ { 0x1f22d, 1, { 0x4e2d, 0 } },
+ { 0x1f22e, 1, { 0x53f3, 0 } },
+ { 0x1f22f, 1, { 0x6307, 0 } },
+ { 0x1f230, 1, { 0x8d70, 0 } },
+ { 0x1f231, 1, { 0x6253, 0 } },
+ { 0x1f232, 1, { 0x7981, 0 } },
+ { 0x1f233, 1, { 0x7a7a, 0 } },
+ { 0x1f234, 1, { 0x5408, 0 } },
+ { 0x1f235, 1, { 0x6e80, 0 } },
+ { 0x1f236, 1, { 0x6709, 0 } },
+ { 0x1f237, 1, { 0x6708, 0 } },
+ { 0x1f238, 1, { 0x7533, 0 } },
+ { 0x1f239, 1, { 0x5272, 0 } },
+ { 0x1f23a, 1, { 0x55b6, 0 } },
+ { 0x1f23b, 1, { 0x914d, 0 } },
+ { 0x1f240, 3, { 858, 0 } },
+ { 0x1f241, 3, { 855, 0 } },
+ { 0x1f242, 3, { 607, 0 } },
+ { 0x1f243, 3, { 764, 0 } },
+ { 0x1f244, 3, { 610, 0 } },
+ { 0x1f245, 3, { 137, 0 } },
+ { 0x1f246, 3, { 813, 0 } },
+ { 0x1f247, 3, { 810, 0 } },
+ { 0x1f248, 3, { 439, 0 } },
+ { 0x1f250, 1, { 0x5f97, 0 } },
+ { 0x1f251, 1, { 0x53ef, 0 } },
+ { 0x1fbf0, 1, { 0x30, 0 } },
+ { 0x1fbf1, 1, { 0x31, 0 } },
+ { 0x1fbf2, 1, { 0x32, 0 } },
+ { 0x1fbf3, 1, { 0x33, 0 } },
+ { 0x1fbf4, 1, { 0x34, 0 } },
+ { 0x1fbf5, 1, { 0x35, 0 } },
+ { 0x1fbf6, 1, { 0x36, 0 } },
+ { 0x1fbf7, 1, { 0x37, 0 } },
+ { 0x1fbf8, 1, { 0x38, 0 } },
+ { 0x1fbf9, 1, { 0x39, 0 } },
+ { 0x2f800, 1, { 0x4e3d, 0 } },
+ { 0x2f801, 1, { 0x4e38, 0 } },
+ { 0x2f802, 1, { 0x4e41, 0 } },
+ { 0x2f803, 2, { 0xd840, 0xdd22 } },
+ { 0x2f804, 1, { 0x4f60, 0 } },
+ { 0x2f805, 1, { 0x4fae, 0 } },
+ { 0x2f806, 1, { 0x4fbb, 0 } },
+ { 0x2f807, 1, { 0x5002, 0 } },
+ { 0x2f808, 1, { 0x507a, 0 } },
+ { 0x2f809, 1, { 0x5099, 0 } },
+ { 0x2f80a, 1, { 0x50e7, 0 } },
+ { 0x2f80b, 1, { 0x50cf, 0 } },
+ { 0x2f80c, 1, { 0x349e, 0 } },
+ { 0x2f80d, 2, { 0xd841, 0xde3a } },
+ { 0x2f80e, 1, { 0x514d, 0 } },
+ { 0x2f80f, 1, { 0x5154, 0 } },
+ { 0x2f810, 1, { 0x5164, 0 } },
+ { 0x2f811, 1, { 0x5177, 0 } },
+ { 0x2f812, 2, { 0xd841, 0xdd1c } },
+ { 0x2f813, 1, { 0x34b9, 0 } },
+ { 0x2f814, 1, { 0x5167, 0 } },
+ { 0x2f815, 1, { 0x518d, 0 } },
+ { 0x2f816, 2, { 0xd841, 0xdd4b } },
+ { 0x2f817, 1, { 0x5197, 0 } },
+ { 0x2f818, 1, { 0x51a4, 0 } },
+ { 0x2f819, 1, { 0x4ecc, 0 } },
+ { 0x2f81a, 1, { 0x51ac, 0 } },
+ { 0x2f81b, 1, { 0x51b5, 0 } },
+ { 0x2f81c, 2, { 0xd864, 0xdddf } },
+ { 0x2f81d, 1, { 0x51f5, 0 } },
+ { 0x2f81e, 1, { 0x5203, 0 } },
+ { 0x2f81f, 1, { 0x34df, 0 } },
+ { 0x2f820, 1, { 0x523b, 0 } },
+ { 0x2f821, 1, { 0x5246, 0 } },
+ { 0x2f822, 1, { 0x5272, 0 } },
+ { 0x2f823, 1, { 0x5277, 0 } },
+ { 0x2f824, 1, { 0x3515, 0 } },
+ { 0x2f825, 1, { 0x52c7, 0 } },
+ { 0x2f826, 1, { 0x52c9, 0 } },
+ { 0x2f827, 1, { 0x52e4, 0 } },
+ { 0x2f828, 1, { 0x52fa, 0 } },
+ { 0x2f829, 1, { 0x5305, 0 } },
+ { 0x2f82a, 1, { 0x5306, 0 } },
+ { 0x2f82b, 1, { 0x5317, 0 } },
+ { 0x2f82c, 1, { 0x5349, 0 } },
+ { 0x2f82d, 1, { 0x5351, 0 } },
+ { 0x2f82e, 1, { 0x535a, 0 } },
+ { 0x2f82f, 1, { 0x5373, 0 } },
+ { 0x2f830, 1, { 0x537d, 0 } },
+ { 0x2f831, 1, { 0x537f, 0 } },
+ { 0x2f832, 1, { 0x537f, 0 } },
+ { 0x2f833, 1, { 0x537f, 0 } },
+ { 0x2f834, 2, { 0xd842, 0xde2c } },
+ { 0x2f835, 1, { 0x7070, 0 } },
+ { 0x2f836, 1, { 0x53ca, 0 } },
+ { 0x2f837, 1, { 0x53df, 0 } },
+ { 0x2f838, 2, { 0xd842, 0xdf63 } },
+ { 0x2f839, 1, { 0x53eb, 0 } },
+ { 0x2f83a, 1, { 0x53f1, 0 } },
+ { 0x2f83b, 1, { 0x5406, 0 } },
+ { 0x2f83c, 1, { 0x549e, 0 } },
+ { 0x2f83d, 1, { 0x5438, 0 } },
+ { 0x2f83e, 1, { 0x5448, 0 } },
+ { 0x2f83f, 1, { 0x5468, 0 } },
+ { 0x2f840, 1, { 0x54a2, 0 } },
+ { 0x2f841, 1, { 0x54f6, 0 } },
+ { 0x2f842, 1, { 0x5510, 0 } },
+ { 0x2f843, 1, { 0x5553, 0 } },
+ { 0x2f844, 1, { 0x5563, 0 } },
+ { 0x2f845, 1, { 0x5584, 0 } },
+ { 0x2f846, 1, { 0x5584, 0 } },
+ { 0x2f847, 1, { 0x5599, 0 } },
+ { 0x2f848, 1, { 0x55ab, 0 } },
+ { 0x2f849, 1, { 0x55b3, 0 } },
+ { 0x2f84a, 1, { 0x55c2, 0 } },
+ { 0x2f84b, 1, { 0x5716, 0 } },
+ { 0x2f84c, 1, { 0x5606, 0 } },
+ { 0x2f84d, 1, { 0x5717, 0 } },
+ { 0x2f84e, 1, { 0x5651, 0 } },
+ { 0x2f84f, 1, { 0x5674, 0 } },
+ { 0x2f850, 1, { 0x5207, 0 } },
+ { 0x2f851, 1, { 0x58ee, 0 } },
+ { 0x2f852, 1, { 0x57ce, 0 } },
+ { 0x2f853, 1, { 0x57f4, 0 } },
+ { 0x2f854, 1, { 0x580d, 0 } },
+ { 0x2f855, 1, { 0x578b, 0 } },
+ { 0x2f856, 1, { 0x5832, 0 } },
+ { 0x2f857, 1, { 0x5831, 0 } },
+ { 0x2f858, 1, { 0x58ac, 0 } },
+ { 0x2f859, 2, { 0xd845, 0xdce4 } },
+ { 0x2f85a, 1, { 0x58f2, 0 } },
+ { 0x2f85b, 1, { 0x58f7, 0 } },
+ { 0x2f85c, 1, { 0x5906, 0 } },
+ { 0x2f85d, 1, { 0x591a, 0 } },
+ { 0x2f85e, 1, { 0x5922, 0 } },
+ { 0x2f85f, 1, { 0x5962, 0 } },
+ { 0x2f860, 2, { 0xd845, 0xdea8 } },
+ { 0x2f861, 2, { 0xd845, 0xdeea } },
+ { 0x2f862, 1, { 0x59ec, 0 } },
+ { 0x2f863, 1, { 0x5a1b, 0 } },
+ { 0x2f864, 1, { 0x5a27, 0 } },
+ { 0x2f865, 1, { 0x59d8, 0 } },
+ { 0x2f866, 1, { 0x5a66, 0 } },
+ { 0x2f867, 1, { 0x36ee, 0 } },
+ { 0x2f869, 1, { 0x5b08, 0 } },
+ { 0x2f86a, 1, { 0x5b3e, 0 } },
+ { 0x2f86b, 1, { 0x5b3e, 0 } },
+ { 0x2f86c, 2, { 0xd846, 0xddc8 } },
+ { 0x2f86d, 1, { 0x5bc3, 0 } },
+ { 0x2f86e, 1, { 0x5bd8, 0 } },
+ { 0x2f86f, 1, { 0x5be7, 0 } },
+ { 0x2f870, 1, { 0x5bf3, 0 } },
+ { 0x2f871, 2, { 0xd846, 0xdf18 } },
+ { 0x2f872, 1, { 0x5bff, 0 } },
+ { 0x2f873, 1, { 0x5c06, 0 } },
+ { 0x2f875, 1, { 0x5c22, 0 } },
+ { 0x2f876, 1, { 0x3781, 0 } },
+ { 0x2f877, 1, { 0x5c60, 0 } },
+ { 0x2f878, 1, { 0x5c6e, 0 } },
+ { 0x2f879, 1, { 0x5cc0, 0 } },
+ { 0x2f87a, 1, { 0x5c8d, 0 } },
+ { 0x2f87b, 2, { 0xd847, 0xdde4 } },
+ { 0x2f87c, 1, { 0x5d43, 0 } },
+ { 0x2f87d, 2, { 0xd847, 0xdde6 } },
+ { 0x2f87e, 1, { 0x5d6e, 0 } },
+ { 0x2f87f, 1, { 0x5d6b, 0 } },
+ { 0x2f880, 1, { 0x5d7c, 0 } },
+ { 0x2f881, 1, { 0x5de1, 0 } },
+ { 0x2f882, 1, { 0x5de2, 0 } },
+ { 0x2f883, 1, { 0x382f, 0 } },
+ { 0x2f884, 1, { 0x5dfd, 0 } },
+ { 0x2f885, 1, { 0x5e28, 0 } },
+ { 0x2f886, 1, { 0x5e3d, 0 } },
+ { 0x2f887, 1, { 0x5e69, 0 } },
+ { 0x2f888, 1, { 0x3862, 0 } },
+ { 0x2f889, 2, { 0xd848, 0xdd83 } },
+ { 0x2f88a, 1, { 0x387c, 0 } },
+ { 0x2f88b, 1, { 0x5eb0, 0 } },
+ { 0x2f88c, 1, { 0x5eb3, 0 } },
+ { 0x2f88d, 1, { 0x5eb6, 0 } },
+ { 0x2f88e, 1, { 0x5eca, 0 } },
+ { 0x2f88f, 2, { 0xd868, 0xdf92 } },
+ { 0x2f890, 1, { 0x5efe, 0 } },
+ { 0x2f891, 2, { 0xd848, 0xdf31 } },
+ { 0x2f892, 2, { 0xd848, 0xdf31 } },
+ { 0x2f893, 1, { 0x8201, 0 } },
+ { 0x2f894, 1, { 0x5f22, 0 } },
+ { 0x2f895, 1, { 0x5f22, 0 } },
+ { 0x2f896, 1, { 0x38c7, 0 } },
+ { 0x2f897, 2, { 0xd84c, 0xdeb8 } },
+ { 0x2f898, 2, { 0xd858, 0xddda } },
+ { 0x2f899, 1, { 0x5f62, 0 } },
+ { 0x2f89a, 1, { 0x5f6b, 0 } },
+ { 0x2f89b, 1, { 0x38e3, 0 } },
+ { 0x2f89c, 1, { 0x5f9a, 0 } },
+ { 0x2f89d, 1, { 0x5fcd, 0 } },
+ { 0x2f89e, 1, { 0x5fd7, 0 } },
+ { 0x2f89f, 1, { 0x5ff9, 0 } },
+ { 0x2f8a0, 1, { 0x6081, 0 } },
+ { 0x2f8a1, 1, { 0x393a, 0 } },
+ { 0x2f8a2, 1, { 0x391c, 0 } },
+ { 0x2f8a3, 1, { 0x6094, 0 } },
+ { 0x2f8a4, 2, { 0xd849, 0xded4 } },
+ { 0x2f8a5, 1, { 0x60c7, 0 } },
+ { 0x2f8a6, 1, { 0x6148, 0 } },
+ { 0x2f8a7, 1, { 0x614c, 0 } },
+ { 0x2f8a8, 1, { 0x614e, 0 } },
+ { 0x2f8a9, 1, { 0x614c, 0 } },
+ { 0x2f8aa, 1, { 0x617a, 0 } },
+ { 0x2f8ab, 1, { 0x618e, 0 } },
+ { 0x2f8ac, 1, { 0x61b2, 0 } },
+ { 0x2f8ad, 1, { 0x61a4, 0 } },
+ { 0x2f8ae, 1, { 0x61af, 0 } },
+ { 0x2f8af, 1, { 0x61de, 0 } },
+ { 0x2f8b0, 1, { 0x61f2, 0 } },
+ { 0x2f8b1, 1, { 0x61f6, 0 } },
+ { 0x2f8b2, 1, { 0x6210, 0 } },
+ { 0x2f8b3, 1, { 0x621b, 0 } },
+ { 0x2f8b4, 1, { 0x625d, 0 } },
+ { 0x2f8b5, 1, { 0x62b1, 0 } },
+ { 0x2f8b6, 1, { 0x62d4, 0 } },
+ { 0x2f8b7, 1, { 0x6350, 0 } },
+ { 0x2f8b8, 2, { 0xd84a, 0xdf0c } },
+ { 0x2f8b9, 1, { 0x633d, 0 } },
+ { 0x2f8ba, 1, { 0x62fc, 0 } },
+ { 0x2f8bb, 1, { 0x6368, 0 } },
+ { 0x2f8bc, 1, { 0x6383, 0 } },
+ { 0x2f8bd, 1, { 0x63e4, 0 } },
+ { 0x2f8be, 2, { 0xd84a, 0xdff1 } },
+ { 0x2f8bf, 1, { 0x6422, 0 } },
+ { 0x2f8c0, 1, { 0x63c5, 0 } },
+ { 0x2f8c1, 1, { 0x63a9, 0 } },
+ { 0x2f8c2, 1, { 0x3a2e, 0 } },
+ { 0x2f8c3, 1, { 0x6469, 0 } },
+ { 0x2f8c4, 1, { 0x647e, 0 } },
+ { 0x2f8c5, 1, { 0x649d, 0 } },
+ { 0x2f8c6, 1, { 0x6477, 0 } },
+ { 0x2f8c7, 1, { 0x3a6c, 0 } },
+ { 0x2f8c8, 1, { 0x654f, 0 } },
+ { 0x2f8c9, 1, { 0x656c, 0 } },
+ { 0x2f8ca, 2, { 0xd84c, 0xdc0a } },
+ { 0x2f8cb, 1, { 0x65e3, 0 } },
+ { 0x2f8cc, 1, { 0x66f8, 0 } },
+ { 0x2f8cd, 1, { 0x6649, 0 } },
+ { 0x2f8ce, 1, { 0x3b19, 0 } },
+ { 0x2f8cf, 1, { 0x6691, 0 } },
+ { 0x2f8d0, 1, { 0x3b08, 0 } },
+ { 0x2f8d1, 1, { 0x3ae4, 0 } },
+ { 0x2f8d2, 1, { 0x5192, 0 } },
+ { 0x2f8d3, 1, { 0x5195, 0 } },
+ { 0x2f8d4, 1, { 0x6700, 0 } },
+ { 0x2f8d5, 1, { 0x669c, 0 } },
+ { 0x2f8d6, 1, { 0x80ad, 0 } },
+ { 0x2f8d7, 1, { 0x43d9, 0 } },
+ { 0x2f8d8, 1, { 0x6717, 0 } },
+ { 0x2f8d9, 1, { 0x671b, 0 } },
+ { 0x2f8da, 1, { 0x6721, 0 } },
+ { 0x2f8db, 1, { 0x675e, 0 } },
+ { 0x2f8dc, 1, { 0x6753, 0 } },
+ { 0x2f8dd, 2, { 0xd84c, 0xdfc3 } },
+ { 0x2f8de, 1, { 0x3b49, 0 } },
+ { 0x2f8df, 1, { 0x67fa, 0 } },
+ { 0x2f8e0, 1, { 0x6785, 0 } },
+ { 0x2f8e1, 1, { 0x6852, 0 } },
+ { 0x2f8e2, 1, { 0x6885, 0 } },
+ { 0x2f8e3, 2, { 0xd84d, 0xdc6d } },
+ { 0x2f8e4, 1, { 0x688e, 0 } },
+ { 0x2f8e5, 1, { 0x681f, 0 } },
+ { 0x2f8e6, 1, { 0x6914, 0 } },
+ { 0x2f8e7, 1, { 0x3b9d, 0 } },
+ { 0x2f8e8, 1, { 0x6942, 0 } },
+ { 0x2f8e9, 1, { 0x69a3, 0 } },
+ { 0x2f8ea, 1, { 0x69ea, 0 } },
+ { 0x2f8eb, 1, { 0x6aa8, 0 } },
+ { 0x2f8ec, 2, { 0xd84d, 0xdea3 } },
+ { 0x2f8ed, 1, { 0x6adb, 0 } },
+ { 0x2f8ee, 1, { 0x3c18, 0 } },
+ { 0x2f8ef, 1, { 0x6b21, 0 } },
+ { 0x2f8f0, 2, { 0xd84e, 0xdca7 } },
+ { 0x2f8f1, 1, { 0x6b54, 0 } },
+ { 0x2f8f2, 1, { 0x3c4e, 0 } },
+ { 0x2f8f3, 1, { 0x6b72, 0 } },
+ { 0x2f8f4, 1, { 0x6b9f, 0 } },
+ { 0x2f8f5, 1, { 0x6bba, 0 } },
+ { 0x2f8f6, 1, { 0x6bbb, 0 } },
+ { 0x2f8f7, 2, { 0xd84e, 0xde8d } },
+ { 0x2f8f8, 2, { 0xd847, 0xdd0b } },
+ { 0x2f8f9, 2, { 0xd84e, 0xdefa } },
+ { 0x2f8fa, 1, { 0x6c4e, 0 } },
+ { 0x2f8fb, 2, { 0xd84f, 0xdcbc } },
+ { 0x2f8fc, 1, { 0x6cbf, 0 } },
+ { 0x2f8fd, 1, { 0x6ccd, 0 } },
+ { 0x2f8fe, 1, { 0x6c67, 0 } },
+ { 0x2f8ff, 1, { 0x6d16, 0 } },
+ { 0x2f900, 1, { 0x6d3e, 0 } },
+ { 0x2f901, 1, { 0x6d77, 0 } },
+ { 0x2f902, 1, { 0x6d41, 0 } },
+ { 0x2f903, 1, { 0x6d69, 0 } },
+ { 0x2f904, 1, { 0x6d78, 0 } },
+ { 0x2f905, 1, { 0x6d85, 0 } },
+ { 0x2f906, 2, { 0xd84f, 0xdd1e } },
+ { 0x2f907, 1, { 0x6d34, 0 } },
+ { 0x2f908, 1, { 0x6e2f, 0 } },
+ { 0x2f909, 1, { 0x6e6e, 0 } },
+ { 0x2f90a, 1, { 0x3d33, 0 } },
+ { 0x2f90b, 1, { 0x6ecb, 0 } },
+ { 0x2f90c, 1, { 0x6ec7, 0 } },
+ { 0x2f90d, 2, { 0xd84f, 0xded1 } },
+ { 0x2f90e, 1, { 0x6df9, 0 } },
+ { 0x2f90f, 1, { 0x6f6e, 0 } },
+ { 0x2f910, 2, { 0xd84f, 0xdf5e } },
+ { 0x2f911, 2, { 0xd84f, 0xdf8e } },
+ { 0x2f912, 1, { 0x6fc6, 0 } },
+ { 0x2f913, 1, { 0x7039, 0 } },
+ { 0x2f914, 1, { 0x701e, 0 } },
+ { 0x2f915, 1, { 0x701b, 0 } },
+ { 0x2f916, 1, { 0x3d96, 0 } },
+ { 0x2f917, 1, { 0x704a, 0 } },
+ { 0x2f918, 1, { 0x707d, 0 } },
+ { 0x2f919, 1, { 0x7077, 0 } },
+ { 0x2f91a, 1, { 0x70ad, 0 } },
+ { 0x2f91b, 2, { 0xd841, 0xdd25 } },
+ { 0x2f91c, 1, { 0x7145, 0 } },
+ { 0x2f91d, 2, { 0xd850, 0xde63 } },
+ { 0x2f91e, 1, { 0x719c, 0 } },
+ { 0x2f920, 1, { 0x7228, 0 } },
+ { 0x2f921, 1, { 0x7235, 0 } },
+ { 0x2f922, 1, { 0x7250, 0 } },
+ { 0x2f923, 2, { 0xd851, 0xde08 } },
+ { 0x2f924, 1, { 0x7280, 0 } },
+ { 0x2f925, 1, { 0x7295, 0 } },
+ { 0x2f926, 2, { 0xd851, 0xdf35 } },
+ { 0x2f927, 2, { 0xd852, 0xdc14 } },
+ { 0x2f928, 1, { 0x737a, 0 } },
+ { 0x2f929, 1, { 0x738b, 0 } },
+ { 0x2f92a, 1, { 0x3eac, 0 } },
+ { 0x2f92b, 1, { 0x73a5, 0 } },
+ { 0x2f92c, 1, { 0x3eb8, 0 } },
+ { 0x2f92d, 1, { 0x3eb8, 0 } },
+ { 0x2f92e, 1, { 0x7447, 0 } },
+ { 0x2f92f, 1, { 0x745c, 0 } },
+ { 0x2f930, 1, { 0x7471, 0 } },
+ { 0x2f931, 1, { 0x7485, 0 } },
+ { 0x2f932, 1, { 0x74ca, 0 } },
+ { 0x2f933, 1, { 0x3f1b, 0 } },
+ { 0x2f934, 1, { 0x7524, 0 } },
+ { 0x2f935, 2, { 0xd853, 0xdc36 } },
+ { 0x2f936, 1, { 0x753e, 0 } },
+ { 0x2f937, 2, { 0xd853, 0xdc92 } },
+ { 0x2f938, 1, { 0x7570, 0 } },
+ { 0x2f939, 2, { 0xd848, 0xdd9f } },
+ { 0x2f93a, 1, { 0x7610, 0 } },
+ { 0x2f93b, 2, { 0xd853, 0xdfa1 } },
+ { 0x2f93c, 2, { 0xd853, 0xdfb8 } },
+ { 0x2f93d, 2, { 0xd854, 0xdc44 } },
+ { 0x2f93e, 1, { 0x3ffc, 0 } },
+ { 0x2f93f, 1, { 0x4008, 0 } },
+ { 0x2f940, 1, { 0x76f4, 0 } },
+ { 0x2f941, 2, { 0xd854, 0xdcf3 } },
+ { 0x2f942, 2, { 0xd854, 0xdcf2 } },
+ { 0x2f943, 2, { 0xd854, 0xdd19 } },
+ { 0x2f944, 2, { 0xd854, 0xdd33 } },
+ { 0x2f945, 1, { 0x771e, 0 } },
+ { 0x2f946, 1, { 0x771f, 0 } },
+ { 0x2f947, 1, { 0x771f, 0 } },
+ { 0x2f948, 1, { 0x774a, 0 } },
+ { 0x2f949, 1, { 0x4039, 0 } },
+ { 0x2f94a, 1, { 0x778b, 0 } },
+ { 0x2f94b, 1, { 0x4046, 0 } },
+ { 0x2f94c, 1, { 0x4096, 0 } },
+ { 0x2f94d, 2, { 0xd855, 0xdc1d } },
+ { 0x2f94e, 1, { 0x784e, 0 } },
+ { 0x2f94f, 1, { 0x788c, 0 } },
+ { 0x2f950, 1, { 0x78cc, 0 } },
+ { 0x2f951, 1, { 0x40e3, 0 } },
+ { 0x2f952, 2, { 0xd855, 0xde26 } },
+ { 0x2f953, 1, { 0x7956, 0 } },
+ { 0x2f954, 2, { 0xd855, 0xde9a } },
+ { 0x2f955, 2, { 0xd855, 0xdec5 } },
+ { 0x2f956, 1, { 0x798f, 0 } },
+ { 0x2f957, 1, { 0x79eb, 0 } },
+ { 0x2f958, 1, { 0x412f, 0 } },
+ { 0x2f959, 1, { 0x7a40, 0 } },
+ { 0x2f95a, 1, { 0x7a4a, 0 } },
+ { 0x2f95b, 1, { 0x7a4f, 0 } },
+ { 0x2f95c, 2, { 0xd856, 0xdd7c } },
+ { 0x2f95d, 2, { 0xd856, 0xdea7 } },
+ { 0x2f95e, 2, { 0xd856, 0xdea7 } },
+ { 0x2f960, 1, { 0x4202, 0 } },
+ { 0x2f961, 2, { 0xd856, 0xdfab } },
+ { 0x2f962, 1, { 0x7bc6, 0 } },
+ { 0x2f963, 1, { 0x7bc9, 0 } },
+ { 0x2f964, 1, { 0x4227, 0 } },
+ { 0x2f965, 2, { 0xd857, 0xdc80 } },
+ { 0x2f966, 1, { 0x7cd2, 0 } },
+ { 0x2f967, 1, { 0x42a0, 0 } },
+ { 0x2f968, 1, { 0x7ce8, 0 } },
+ { 0x2f969, 1, { 0x7ce3, 0 } },
+ { 0x2f96a, 1, { 0x7d00, 0 } },
+ { 0x2f96b, 2, { 0xd857, 0xdf86 } },
+ { 0x2f96c, 1, { 0x7d63, 0 } },
+ { 0x2f96d, 1, { 0x4301, 0 } },
+ { 0x2f96e, 1, { 0x7dc7, 0 } },
+ { 0x2f96f, 1, { 0x7e02, 0 } },
+ { 0x2f970, 1, { 0x7e45, 0 } },
+ { 0x2f971, 1, { 0x4334, 0 } },
+ { 0x2f972, 2, { 0xd858, 0xde28 } },
+ { 0x2f973, 2, { 0xd858, 0xde47 } },
+ { 0x2f974, 1, { 0x4359, 0 } },
+ { 0x2f975, 2, { 0xd858, 0xded9 } },
+ { 0x2f976, 1, { 0x7f7a, 0 } },
+ { 0x2f977, 2, { 0xd858, 0xdf3e } },
+ { 0x2f978, 1, { 0x7f95, 0 } },
+ { 0x2f979, 1, { 0x7ffa, 0 } },
+ { 0x2f97a, 1, { 0x8005, 0 } },
+ { 0x2f97b, 2, { 0xd859, 0xdcda } },
+ { 0x2f97c, 2, { 0xd859, 0xdd23 } },
+ { 0x2f97d, 1, { 0x8060, 0 } },
+ { 0x2f97e, 2, { 0xd859, 0xdda8 } },
+ { 0x2f97f, 1, { 0x8070, 0 } },
+ { 0x2f980, 2, { 0xd84c, 0xdf5f } },
+ { 0x2f981, 1, { 0x43d5, 0 } },
+ { 0x2f982, 1, { 0x80b2, 0 } },
+ { 0x2f983, 1, { 0x8103, 0 } },
+ { 0x2f984, 1, { 0x440b, 0 } },
+ { 0x2f985, 1, { 0x813e, 0 } },
+ { 0x2f986, 1, { 0x5ab5, 0 } },
+ { 0x2f987, 2, { 0xd859, 0xdfa7 } },
+ { 0x2f988, 2, { 0xd859, 0xdfb5 } },
+ { 0x2f989, 2, { 0xd84c, 0xdf93 } },
+ { 0x2f98a, 2, { 0xd84c, 0xdf9c } },
+ { 0x2f98b, 1, { 0x8201, 0 } },
+ { 0x2f98c, 1, { 0x8204, 0 } },
+ { 0x2f98d, 1, { 0x8f9e, 0 } },
+ { 0x2f98e, 1, { 0x446b, 0 } },
+ { 0x2f98f, 1, { 0x8291, 0 } },
+ { 0x2f990, 1, { 0x828b, 0 } },
+ { 0x2f991, 1, { 0x829d, 0 } },
+ { 0x2f992, 1, { 0x52b3, 0 } },
+ { 0x2f993, 1, { 0x82b1, 0 } },
+ { 0x2f994, 1, { 0x82b3, 0 } },
+ { 0x2f995, 1, { 0x82bd, 0 } },
+ { 0x2f996, 1, { 0x82e6, 0 } },
+ { 0x2f997, 2, { 0xd85a, 0xdf3c } },
+ { 0x2f998, 1, { 0x82e5, 0 } },
+ { 0x2f999, 1, { 0x831d, 0 } },
+ { 0x2f99a, 1, { 0x8363, 0 } },
+ { 0x2f99b, 1, { 0x83ad, 0 } },
+ { 0x2f99c, 1, { 0x8323, 0 } },
+ { 0x2f99d, 1, { 0x83bd, 0 } },
+ { 0x2f99e, 1, { 0x83e7, 0 } },
+ { 0x2f99f, 1, { 0x8457, 0 } },
+ { 0x2f9a0, 1, { 0x8353, 0 } },
+ { 0x2f9a1, 1, { 0x83ca, 0 } },
+ { 0x2f9a2, 1, { 0x83cc, 0 } },
+ { 0x2f9a3, 1, { 0x83dc, 0 } },
+ { 0x2f9a4, 2, { 0xd85b, 0xdc36 } },
+ { 0x2f9a5, 2, { 0xd85b, 0xdd6b } },
+ { 0x2f9a6, 2, { 0xd85b, 0xdcd5 } },
+ { 0x2f9a7, 1, { 0x452b, 0 } },
+ { 0x2f9a8, 1, { 0x84f1, 0 } },
+ { 0x2f9a9, 1, { 0x84f3, 0 } },
+ { 0x2f9aa, 1, { 0x8516, 0 } },
+ { 0x2f9ab, 2, { 0xd85c, 0xdfca } },
+ { 0x2f9ac, 1, { 0x8564, 0 } },
+ { 0x2f9ad, 2, { 0xd85b, 0xdf2c } },
+ { 0x2f9ae, 1, { 0x455d, 0 } },
+ { 0x2f9af, 1, { 0x4561, 0 } },
+ { 0x2f9b0, 2, { 0xd85b, 0xdfb1 } },
+ { 0x2f9b1, 2, { 0xd85c, 0xdcd2 } },
+ { 0x2f9b2, 1, { 0x456b, 0 } },
+ { 0x2f9b3, 1, { 0x8650, 0 } },
+ { 0x2f9b4, 1, { 0x865c, 0 } },
+ { 0x2f9b5, 1, { 0x8667, 0 } },
+ { 0x2f9b6, 1, { 0x8669, 0 } },
+ { 0x2f9b7, 1, { 0x86a9, 0 } },
+ { 0x2f9b8, 1, { 0x8688, 0 } },
+ { 0x2f9b9, 1, { 0x870e, 0 } },
+ { 0x2f9ba, 1, { 0x86e2, 0 } },
+ { 0x2f9bb, 1, { 0x8779, 0 } },
+ { 0x2f9bc, 1, { 0x8728, 0 } },
+ { 0x2f9bd, 1, { 0x876b, 0 } },
+ { 0x2f9be, 1, { 0x8786, 0 } },
+ { 0x2f9c0, 1, { 0x87e1, 0 } },
+ { 0x2f9c1, 1, { 0x8801, 0 } },
+ { 0x2f9c2, 1, { 0x45f9, 0 } },
+ { 0x2f9c3, 1, { 0x8860, 0 } },
+ { 0x2f9c4, 1, { 0x8863, 0 } },
+ { 0x2f9c5, 2, { 0xd85d, 0xde67 } },
+ { 0x2f9c6, 1, { 0x88d7, 0 } },
+ { 0x2f9c7, 1, { 0x88de, 0 } },
+ { 0x2f9c8, 1, { 0x4635, 0 } },
+ { 0x2f9c9, 1, { 0x88fa, 0 } },
+ { 0x2f9ca, 1, { 0x34bb, 0 } },
+ { 0x2f9cb, 2, { 0xd85e, 0xdcae } },
+ { 0x2f9cc, 2, { 0xd85e, 0xdd66 } },
+ { 0x2f9cd, 1, { 0x46be, 0 } },
+ { 0x2f9ce, 1, { 0x46c7, 0 } },
+ { 0x2f9cf, 1, { 0x8aa0, 0 } },
+ { 0x2f9d0, 1, { 0x8aed, 0 } },
+ { 0x2f9d1, 1, { 0x8b8a, 0 } },
+ { 0x2f9d2, 1, { 0x8c55, 0 } },
+ { 0x2f9d3, 2, { 0xd85f, 0xdca8 } },
+ { 0x2f9d4, 1, { 0x8cab, 0 } },
+ { 0x2f9d5, 1, { 0x8cc1, 0 } },
+ { 0x2f9d6, 1, { 0x8d1b, 0 } },
+ { 0x2f9d7, 1, { 0x8d77, 0 } },
+ { 0x2f9d8, 2, { 0xd85f, 0xdf2f } },
+ { 0x2f9d9, 2, { 0xd842, 0xdc04 } },
+ { 0x2f9da, 1, { 0x8dcb, 0 } },
+ { 0x2f9db, 1, { 0x8dbc, 0 } },
+ { 0x2f9dc, 1, { 0x8df0, 0 } },
+ { 0x2f9dd, 2, { 0xd842, 0xdcde } },
+ { 0x2f9de, 1, { 0x8ed4, 0 } },
+ { 0x2f9df, 1, { 0x8f38, 0 } },
+ { 0x2f9e0, 2, { 0xd861, 0xddd2 } },
+ { 0x2f9e1, 2, { 0xd861, 0xdded } },
+ { 0x2f9e2, 1, { 0x9094, 0 } },
+ { 0x2f9e3, 1, { 0x90f1, 0 } },
+ { 0x2f9e4, 1, { 0x9111, 0 } },
+ { 0x2f9e5, 2, { 0xd861, 0xdf2e } },
+ { 0x2f9e6, 1, { 0x911b, 0 } },
+ { 0x2f9e7, 1, { 0x9238, 0 } },
+ { 0x2f9e8, 1, { 0x92d7, 0 } },
+ { 0x2f9e9, 1, { 0x92d8, 0 } },
+ { 0x2f9ea, 1, { 0x927c, 0 } },
+ { 0x2f9eb, 1, { 0x93f9, 0 } },
+ { 0x2f9ec, 1, { 0x9415, 0 } },
+ { 0x2f9ed, 2, { 0xd862, 0xdffa } },
+ { 0x2f9ee, 1, { 0x958b, 0 } },
+ { 0x2f9ef, 1, { 0x4995, 0 } },
+ { 0x2f9f0, 1, { 0x95b7, 0 } },
+ { 0x2f9f1, 2, { 0xd863, 0xdd77 } },
+ { 0x2f9f2, 1, { 0x49e6, 0 } },
+ { 0x2f9f3, 1, { 0x96c3, 0 } },
+ { 0x2f9f4, 1, { 0x5db2, 0 } },
+ { 0x2f9f5, 1, { 0x9723, 0 } },
+ { 0x2f9f6, 2, { 0xd864, 0xdd45 } },
+ { 0x2f9f7, 2, { 0xd864, 0xde1a } },
+ { 0x2f9f8, 1, { 0x4a6e, 0 } },
+ { 0x2f9f9, 1, { 0x4a76, 0 } },
+ { 0x2f9fa, 1, { 0x97e0, 0 } },
+ { 0x2f9fb, 2, { 0xd865, 0xdc0a } },
+ { 0x2f9fc, 1, { 0x4ab2, 0 } },
+ { 0x2f9fd, 2, { 0xd865, 0xdc96 } },
+ { 0x2f9fe, 1, { 0x980b, 0 } },
+ { 0x2f9ff, 1, { 0x980b, 0 } },
+ { 0x2fa00, 1, { 0x9829, 0 } },
+ { 0x2fa01, 2, { 0xd865, 0xddb6 } },
+ { 0x2fa02, 1, { 0x98e2, 0 } },
+ { 0x2fa03, 1, { 0x4b33, 0 } },
+ { 0x2fa04, 1, { 0x9929, 0 } },
+ { 0x2fa05, 1, { 0x99a7, 0 } },
+ { 0x2fa06, 1, { 0x99c2, 0 } },
+ { 0x2fa07, 1, { 0x99fe, 0 } },
+ { 0x2fa08, 1, { 0x4bce, 0 } },
+ { 0x2fa09, 2, { 0xd866, 0xdf30 } },
+ { 0x2fa0a, 1, { 0x9b12, 0 } },
+ { 0x2fa0b, 1, { 0x9c40, 0 } },
+ { 0x2fa0c, 1, { 0x9cfd, 0 } },
+ { 0x2fa0d, 1, { 0x4cce, 0 } },
+ { 0x2fa0e, 1, { 0x4ced, 0 } },
+ { 0x2fa0f, 1, { 0x9d67, 0 } },
+ { 0x2fa10, 2, { 0xd868, 0xdcce } },
+ { 0x2fa11, 1, { 0x4cf8, 0 } },
+ { 0x2fa12, 2, { 0xd868, 0xdd05 } },
+ { 0x2fa13, 2, { 0xd868, 0xde0e } },
+ { 0x2fa14, 2, { 0xd868, 0xde91 } },
+ { 0x2fa15, 1, { 0x9ebb, 0 } },
+ { 0x2fa16, 1, { 0x4d56, 0 } },
+ { 0x2fa17, 1, { 0x9ef9, 0 } },
+ { 0x2fa18, 1, { 0x9efe, 0 } },
+ { 0x2fa19, 1, { 0x9f05, 0 } },
+ { 0x2fa1a, 1, { 0x9f0f, 0 } },
+ { 0x2fa1b, 1, { 0x9f16, 0 } },
+ { 0x2fa1c, 1, { 0x9f3b, 0 } },
+ { 0x2fa1d, 2, { 0xd869, 0xde00 } },
+};
+
+Q_CORE_EXPORT QStringView QT_FASTCALL idnaMapping(char32_t ucs4) noexcept
+{
+ auto i = std::lower_bound(std::begin(idnaMap), std::end(idnaMap), ucs4,
+ [](const auto &p, char32_t c) { return p.codePoint < c; });
+ if (i == std::end(idnaMap) || i->codePoint != ucs4)
+ return {};
+
+ return QStringView(i->size > 2 ? idnaMappingData + i->ucs[0] : i->ucs, i->size);
+}
+
} // namespace QUnicodeTables
using namespace QUnicodeTables;
diff --git a/src/corelib/text/qunicodetables_p.h b/src/corelib/text/qunicodetables_p.h
index e59aea25bd..eabdc919cb 100644
--- a/src/corelib/text/qunicodetables_p.h
+++ b/src/corelib/text/qunicodetables_p.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/* This file is autogenerated from the Unicode 13.0 database. Do not edit */
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-DFS-2016
+
+/* This file is autogenerated from the Unicode 15.1 database. Do not edit */
//
// W A R N I N G
@@ -59,7 +23,7 @@
QT_BEGIN_NAMESPACE
-#define UNICODE_DATA_VERSION QChar::Unicode_13_0
+#define UNICODE_DATA_VERSION QChar::Unicode_15_1
namespace QUnicodeTables {
@@ -79,7 +43,8 @@ struct Properties {
ushort joining : 3;
signed short digitValue : 5;
signed short mirrorDiff : 16;
- ushort unicodeVersion : 8; /* 5 used */
+ ushort unicodeVersion : 5; /* 5 used */
+ ushort eastAsianWidth : 3; /* 3 used */
ushort nfQuickCheck : 8;
#ifdef Q_OS_WASM
unsigned char : 0; //wasm 64 packing trick
@@ -94,7 +59,8 @@ struct Properties {
ushort graphemeBreakClass : 5; /* 5 used */
ushort wordBreakClass : 5; /* 5 used */
ushort lineBreakClass : 6; /* 6 used */
- ushort sentenceBreakClass : 8; /* 4 used */
+ ushort sentenceBreakClass : 4; /* 4 used */
+ ushort idnaStatus : 4; /* 3 used */
ushort script : 8;
};
@@ -103,6 +69,15 @@ Q_CORE_EXPORT const Properties * QT_FASTCALL properties(char16_t ucs2) noexcept;
static_assert(sizeof(Properties) == 20);
+enum class EastAsianWidth : unsigned int {
+ A,
+ F,
+ H,
+ N,
+ Na,
+ W,
+};
+
enum GraphemeBreakClass {
GraphemeBreak_Any,
GraphemeBreak_CR,
@@ -118,10 +93,7 @@ enum GraphemeBreakClass {
GraphemeBreak_T,
GraphemeBreak_LV,
GraphemeBreak_LVT,
- Graphemebreak_E_Base,
- Graphemebreak_E_Modifier,
- Graphemebreak_Glue_After_Zwj,
- Graphemebreak_E_Base_GAZ,
+ GraphemeBreak_Extended_Pictographic,
NumGraphemeBreakClasses
};
@@ -145,10 +117,6 @@ enum WordBreakClass {
WordBreak_MidNum,
WordBreak_Numeric,
WordBreak_ExtendNumLet,
- WordBreak_E_Base,
- WordBreak_E_Modifier,
- WordBreak_Glue_After_Zwj,
- WordBreak_E_Base_GAZ,
WordBreak_WSegSpace,
NumWordBreakClasses
@@ -174,9 +142,11 @@ enum SentenceBreakClass {
};
// see http://www.unicode.org/reports/tr14/tr14-30.html
-// we don't use the XX and AI classes and map them to AL instead.
+// we don't use the XX, AK, AP, AS and AI classes and map them to AL instead.
+// VI and VF classes are mapped to CM.
enum LineBreakClass {
- LineBreak_OP, LineBreak_CL, LineBreak_CP, LineBreak_QU, LineBreak_GL,
+ LineBreak_OP, LineBreak_CL, LineBreak_CP,
+ LineBreak_QU, LineBreak_QU_Pi, LineBreak_QU_Pf, LineBreak_GL,
LineBreak_NS, LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR,
LineBreak_PO, LineBreak_NU, LineBreak_AL, LineBreak_HL, LineBreak_ID,
LineBreak_IN, LineBreak_HY, LineBreak_BA, LineBreak_BB, LineBreak_B2,
@@ -189,6 +159,14 @@ enum LineBreakClass {
NumLineBreakClasses
};
+enum class IdnaStatus : unsigned int {
+ Disallowed,
+ Valid,
+ Ignored,
+ Mapped,
+ Deviation
+};
+
Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(char32_t ucs4) noexcept;
inline GraphemeBreakClass graphemeBreakClass(QChar ch) noexcept
{ return graphemeBreakClass(ch.unicode()); }
@@ -205,6 +183,18 @@ Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(char32_t ucs4) noexcept;
inline LineBreakClass lineBreakClass(QChar ch) noexcept
{ return lineBreakClass(ch.unicode()); }
+Q_CORE_EXPORT IdnaStatus QT_FASTCALL idnaStatus(char32_t ucs4) noexcept;
+inline IdnaStatus idnaStatus(QChar ch) noexcept
+{ return idnaStatus(ch.unicode()); }
+
+Q_CORE_EXPORT QStringView QT_FASTCALL idnaMapping(char32_t usc4) noexcept;
+inline QStringView idnaMapping(QChar ch) noexcept
+{ return idnaMapping(ch.unicode()); }
+
+Q_CORE_EXPORT EastAsianWidth QT_FASTCALL eastAsianWidth(char32_t ucs4) noexcept;
+inline EastAsianWidth eastAsianWidth(QChar ch) noexcept
+{ return eastAsianWidth(ch.unicode()); }
+
} // namespace QUnicodeTables
QT_END_NAMESPACE
diff --git a/src/corelib/text/qunicodetools.cpp b/src/corelib/text/qunicodetools.cpp
index 61976ab9ca..2917804830 100644
--- a/src/corelib/text/qunicodetools.cpp
+++ b/src/corelib/text/qunicodetools.cpp
@@ -1,108 +1,128 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qunicodetools_p.h"
#include "qunicodetables_p.h"
#include "qvarlengtharray.h"
+#if QT_CONFIG(library)
#include "qlibrary.h"
+#endif
+
+#include <limits.h>
#define FLAG(x) (1 << (x))
QT_BEGIN_NAMESPACE
-Q_AUTOTEST_EXPORT int qt_initcharattributes_default_algorithm_only = 0;
+using namespace Qt::StringLiterals;
+
+#ifdef QT_BUILD_INTERNAL
+Q_CONSTINIT Q_AUTOTEST_EXPORT
+#else
+constexpr
+#endif
+int qt_initcharattributes_default_algorithm_only = 0;
namespace QUnicodeTools {
// -----------------------------------------------------------------------------------------------------
//
// The text boundaries determination algorithm.
-// See http://www.unicode.org/reports/tr29/tr29-31.html
+// See https://www.unicode.org/reports/tr29/tr29-37.html
//
// -----------------------------------------------------------------------------------------------------
namespace GB {
-/*
- * Most grapheme break rules can be implemented table driven, but rules GB10, GB12 and GB13 need a bit
- * of special treatment.
- */
-enum State : uchar {
- Break,
- Inside,
- GB10,
- GB10_2,
- GB10_3,
- GB13, // also covers GB12
+// This table is indexed by the grapheme break classes of two
+// (adjacent) code points.
+// The class of the first code point selects an entry.
+// If the entry's bit at position second_cp_class is set
+// (in other words: if entry & (1u << second_cp_class) is non-zero)
+// then there is NO grapheme break between the two code points.
+
+using GBTableEntryType = quint16;
+
+// Check that we have enough bits in the table (in case
+// NumGraphemeBreakClasses grows too much).
+static_assert(sizeof(GBTableEntryType) * CHAR_BIT >= QUnicodeTables::NumGraphemeBreakClasses,
+ "Internal error: increase the size in bits of GBTableEntryType");
+
+// GB9, GB9a
+static const GBTableEntryType Extend_SpacingMark_ZWJ =
+ FLAG(QUnicodeTables::GraphemeBreak_Extend)
+ | FLAG(QUnicodeTables::GraphemeBreak_SpacingMark)
+ | FLAG(QUnicodeTables::GraphemeBreak_ZWJ);
+
+static const GBTableEntryType HardBreak = 0u;
+
+static const GBTableEntryType breakTable[QUnicodeTables::NumGraphemeBreakClasses] = {
+ Extend_SpacingMark_ZWJ, // Any
+ FLAG(QUnicodeTables::GraphemeBreak_LF), // CR
+ HardBreak, // LF
+ HardBreak, // Control
+ Extend_SpacingMark_ZWJ, // Extend
+ Extend_SpacingMark_ZWJ, // ZWJ
+ Extend_SpacingMark_ZWJ, // RegionalIndicator
+ (Extend_SpacingMark_ZWJ
+ | FLAG(QUnicodeTables::GraphemeBreak_Any)
+ | FLAG(QUnicodeTables::GraphemeBreak_Prepend)
+ | FLAG(QUnicodeTables::GraphemeBreak_L)
+ | FLAG(QUnicodeTables::GraphemeBreak_V)
+ | FLAG(QUnicodeTables::GraphemeBreak_T)
+ | FLAG(QUnicodeTables::GraphemeBreak_LV)
+ | FLAG(QUnicodeTables::GraphemeBreak_LVT)
+ | FLAG(QUnicodeTables::GraphemeBreak_RegionalIndicator)
+ | FLAG(QUnicodeTables::GraphemeBreak_Extended_Pictographic)
+ ), // Prepend
+ Extend_SpacingMark_ZWJ, // SpacingMark
+ (Extend_SpacingMark_ZWJ
+ | FLAG(QUnicodeTables::GraphemeBreak_L)
+ | FLAG(QUnicodeTables::GraphemeBreak_V)
+ | FLAG(QUnicodeTables::GraphemeBreak_LV)
+ | FLAG(QUnicodeTables::GraphemeBreak_LVT)
+ ), // L
+ (Extend_SpacingMark_ZWJ
+ | FLAG(QUnicodeTables::GraphemeBreak_V)
+ | FLAG(QUnicodeTables::GraphemeBreak_T)
+ ), // V
+ (Extend_SpacingMark_ZWJ
+ | FLAG(QUnicodeTables::GraphemeBreak_T)
+ ), // T
+ (Extend_SpacingMark_ZWJ
+ | FLAG(QUnicodeTables::GraphemeBreak_V)
+ | FLAG(QUnicodeTables::GraphemeBreak_T)
+ ), // LV
+ (Extend_SpacingMark_ZWJ
+ | FLAG(QUnicodeTables::GraphemeBreak_T)
+ ), // LVT
+ Extend_SpacingMark_ZWJ // Extended_Pictographic
};
-static const State breakTable[QUnicodeTables::NumGraphemeBreakClasses][QUnicodeTables::NumGraphemeBreakClasses] = {
-// Any CR LF Control Extend ZWJ RI Prepend S-Mark L V T LV LVT E_B E_M GAZ EBG
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Any
- { Break , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // CR
- { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // LF
- { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Control
- { Break , Break , Break , Break , GB10_2, Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , GB10_3, Break , Break }, // Extend
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Inside, Inside }, // ZWJ
- { Break , Break , Break , Break , Inside, Inside, GB13 , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Break , Break }, // RegionalIndicator
- { Inside, Break , Break , Break , Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside, Inside }, // Prepend
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Break , Break }, // SpacingMark
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Inside, Inside, Break , Inside, Inside, Break , Break , Break , Break }, // L
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Inside, Inside, Break , Break , Break , Break , Break , Break }, // V
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break }, // T
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Inside, Inside, Break , Break , Break , Break , Break , Break }, // LV
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break }, // LVT
- { Break , Break , Break , Break , GB10 , Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Inside, Break , Break }, // E_B
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Break , Break }, // E_M
- { Break , Break , Break , Break , Inside, Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Break , Break , Break }, // GAZ
- { Break , Break , Break , Break , GB10 , Inside, Break , Break , Inside, Break , Break , Break , Break , Break , Break , Inside, Break , Break }, // EBG
+static bool shouldBreakBetweenClasses(QUnicodeTables::GraphemeBreakClass first,
+ QUnicodeTables::GraphemeBreakClass second)
+{
+ return (breakTable[first] & FLAG(second)) == 0;
+}
+
+// Some rules (GB11, GB12, GB13) cannot be represented by the table alone,
+// so we need to store some local state.
+enum class State : uchar {
+ Normal,
+ GB11_ExtPicExt, // saw a Extend after a Extended_Pictographic
+ GB11_ExtPicExtZWJ, // saw a ZWG after a Extended_Pictographic and zero or more Extend
+ GB12_13_RI, // saw a RegionalIndicator following a non-RegionalIndicator
};
} // namespace GB
-static void getGraphemeBreaks(const ushort *string, quint32 len, QCharAttributes *attributes)
+static void getGraphemeBreaks(const char16_t *string, qsizetype len, QCharAttributes *attributes)
{
QUnicodeTables::GraphemeBreakClass lcls = QUnicodeTables::GraphemeBreak_LF; // to meet GB1
- GB::State state = GB::Break; // only required to track some of the rules
- for (quint32 i = 0; i != len; ++i) {
- quint32 pos = i;
+ GB::State state = GB::State::Normal;
+ for (qsizetype i = 0; i != len; ++i) {
+ qsizetype pos = i;
char32_t ucs4 = string[i];
if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
ushort low = string[i + 1];
@@ -115,37 +135,67 @@ static void getGraphemeBreaks(const ushort *string, quint32 len, QCharAttributes
const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4);
QUnicodeTables::GraphemeBreakClass cls = (QUnicodeTables::GraphemeBreakClass) prop->graphemeBreakClass;
- switch (GB::breakTable[lcls][cls]) {
- case GB::Break:
- attributes[pos].graphemeBoundary = true;
- state = GB::Break;
- break;
- case GB::Inside:
- state = GB::Break;
- break;
- case GB::GB10:
- state = GB::GB10;
+ bool shouldBreak = GB::shouldBreakBetweenClasses(lcls, cls);
+ bool handled = false;
+
+ switch (state) {
+ case GB::State::Normal:
+ break; // will deal with it below
+
+ case GB::State::GB11_ExtPicExt:
+ Q_ASSERT(lcls == QUnicodeTables::GraphemeBreak_Extend);
+ if (cls == QUnicodeTables::GraphemeBreak_Extend) {
+ // keep going in the current state
+ Q_ASSERT(!shouldBreak); // GB9, do not break before Extend
+ handled = true;
+ } else if (cls == QUnicodeTables::GraphemeBreak_ZWJ) {
+ state = GB::State::GB11_ExtPicExtZWJ;
+ Q_ASSERT(!shouldBreak); // GB9, do not break before ZWJ
+ handled = true;
+ } else {
+ state = GB::State::Normal;
+ }
break;
- case GB::GB10_2:
- if (state == GB::GB10 || state == GB::GB10_2)
- state = GB::GB10_2;
- else
- state = GB::Break;
+
+ case GB::State::GB11_ExtPicExtZWJ:
+ Q_ASSERT(lcls == QUnicodeTables::GraphemeBreak_ZWJ);
+ if (cls == QUnicodeTables::GraphemeBreak_Extended_Pictographic) {
+ shouldBreak = false;
+ handled = true;
+ }
+
+ state = GB::State::Normal;
break;
- case GB::GB10_3:
- if (state != GB::GB10 && state != GB::GB10_2)
- attributes[pos].graphemeBoundary = true;
- state = GB::Break;
+
+ case GB::State::GB12_13_RI:
+ Q_ASSERT(lcls == QUnicodeTables::GraphemeBreak_RegionalIndicator);
+ if (cls == QUnicodeTables::GraphemeBreak_RegionalIndicator) {
+ shouldBreak = false;
+ handled = true;
+ }
+
+ state = GB::State::Normal;
break;
- case GB::GB13:
- if (state != GB::GB13) {
- state = GB::GB13;
- } else {
- attributes[pos].graphemeBoundary = true;
- state = GB::Break;
+ }
+
+ if (!handled) {
+ Q_ASSERT(state == GB::State::Normal);
+ if (lcls == QUnicodeTables::GraphemeBreak_Extended_Pictographic) { // GB11
+ if (cls == QUnicodeTables::GraphemeBreak_Extend) {
+ state = GB::State::GB11_ExtPicExt;
+ Q_ASSERT(!shouldBreak); // GB9, do not break before Extend
+ } else if (cls == QUnicodeTables::GraphemeBreak_ZWJ) {
+ state = GB::State::GB11_ExtPicExtZWJ;
+ Q_ASSERT(!shouldBreak); // GB9, do not break before ZWJ
+ }
+ } else if (cls == QUnicodeTables::GraphemeBreak_RegionalIndicator) { // GB12, GB13
+ state = GB::State::GB12_13_RI;
}
}
+ if (shouldBreak)
+ attributes[pos].graphemeBoundary = true;
+
lcls = cls;
}
@@ -163,43 +213,41 @@ enum Action {
};
static const uchar breakTable[QUnicodeTables::NumWordBreakClasses][QUnicodeTables::NumWordBreakClasses] = {
-// Any CR LF Newline Extend ZWJ Format RI Katakana HLetter ALetter SQuote DQuote MidNumLet MidLetter MidNum Numeric ExtNumLet E_Base E_Mod GAZ EBG WSeg
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Any
- { Break , Break , NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // CR
- { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // LF
- { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Newline
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Extend
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , NoBreak, NoBreak, Break }, // ZWJ
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Format
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // RegionalIndicator
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , NoBreak, Break , Break , Break , Break , Break }, // Katakana
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , NoBreak, NoBreak, LookupW, Lookup , LookupW, LookupW, Break , NoBreak, NoBreak, Break , Break , Break , Break , Break }, // HebrewLetter
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , NoBreak, NoBreak, LookupW, Break , LookupW, LookupW, Break , NoBreak, NoBreak, Break , Break , Break , Break , Break }, // ALetter
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // SingleQuote
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // DoubleQuote
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // MidNumLet
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // MidLetter
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // MidNum
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , NoBreak, NoBreak, Lookup , Break , Lookup , Break , Lookup , NoBreak, NoBreak, Break , Break , Break , Break , Break }, // Numeric
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , NoBreak, NoBreak, Break , Break , Break , Break , Break }, // ExtendNumLet
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , NoBreak, Break , Break , Break }, // E_Base
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // E_Mod
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // GAZ
- { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , NoBreak, Break , Break , Break }, // EBG
- { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // WSeg
+// Any CR LF Newline Extend ZWJ Format RI Katakana HLetter ALetter SQuote DQuote MidNumLet MidLetter MidNum Numeric ExtNumLet WSeg
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Any
+ { Break , Break , NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // CR
+ { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // LF
+ { Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Newline
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Extend
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // ZWJ
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // Format
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // RegionalIndicator
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , NoBreak, Break }, // Katakana
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , NoBreak, NoBreak, LookupW, Lookup , LookupW, LookupW, Break , NoBreak, NoBreak, Break }, // HebrewLetter
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , NoBreak, NoBreak, LookupW, Break , LookupW, LookupW, Break , NoBreak, NoBreak, Break }, // ALetter
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // SingleQuote
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // DoubleQuote
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // MidNumLet
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // MidLetter
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break }, // MidNum
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , NoBreak, NoBreak, Lookup , Break , Lookup , Break , Lookup , NoBreak, NoBreak, Break }, // Numeric
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , NoBreak, NoBreak, Break }, // ExtendNumLet
+ { Break , Break , Break , Break , NoBreak, NoBreak, NoBreak, Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , Break , NoBreak }, // WSegSpace
};
} // namespace WB
-static void getWordBreaks(const ushort *string, quint32 len, QCharAttributes *attributes)
+static void getWordBreaks(const char16_t *string, qsizetype len, QCharAttributes *attributes)
{
enum WordType {
WordTypeNone, WordTypeAlphaNumeric, WordTypeHiraganaKatakana
} currentWordType = WordTypeNone;
QUnicodeTables::WordBreakClass cls = QUnicodeTables::WordBreak_LF; // to meet WB1
- for (quint32 i = 0; i != len; ++i) {
- quint32 pos = i;
+ auto real_cls = cls; // Unaffected by WB4
+
+ for (qsizetype i = 0; i != len; ++i) {
+ qsizetype pos = i;
char32_t ucs4 = string[i];
if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
ushort low = string[i + 1];
@@ -211,7 +259,6 @@ static void getWordBreaks(const ushort *string, quint32 len, QCharAttributes *at
const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4);
QUnicodeTables::WordBreakClass ncls = (QUnicodeTables::WordBreakClass) prop->wordBreakClass;
-#ifdef QT_BUILD_INTERNAL
if (qt_initcharattributes_default_algorithm_only) {
// as of Unicode 5.1, some punctuation marks were mapped to MidLetter and MidNumLet
// which caused "hi.there" to be treated like if it were just a single word;
@@ -222,26 +269,36 @@ static void getWordBreaks(const ushort *string, quint32 len, QCharAttributes *at
else if (ucs4 == 0x003A) // COLON
ncls = QUnicodeTables::WordBreak_MidLetter;
}
-#endif
uchar action = WB::breakTable[cls][ncls];
switch (action) {
case WB::Break:
+ if (Q_UNLIKELY(real_cls == QUnicodeTables::WordBreak_ZWJ
+ && prop->graphemeBreakClass
+ == QUnicodeTables::GraphemeBreak_Extended_Pictographic)) {
+ // WB3c: ZWJ × \p{Extended_Pictographic}
+ action = WB::NoBreak;
+ }
break;
case WB::NoBreak:
if (Q_UNLIKELY(ncls == QUnicodeTables::WordBreak_Extend || ncls == QUnicodeTables::WordBreak_ZWJ || ncls == QUnicodeTables::WordBreak_Format)) {
// WB4: X(Extend|Format)* -> X
- if (cls != QUnicodeTables::WordBreak_ZWJ) // WB3c
- continue;
+ real_cls = ncls;
+ continue;
}
if (Q_UNLIKELY(cls == QUnicodeTables::WordBreak_RegionalIndicator)) {
// WB15/WB16: break between pairs of Regional indicator
ncls = QUnicodeTables::WordBreak_Any;
}
+ if (Q_UNLIKELY(ncls == QUnicodeTables::WordBreak_WSegSpace
+ && real_cls != QUnicodeTables::WordBreak_WSegSpace)) {
+ // WB3d should not be affected by WB4
+ action = WB::Break;
+ }
break;
case WB::Lookup:
case WB::LookupW:
- for (quint32 lookahead = i + 1; lookahead < len; ++lookahead) {
+ for (qsizetype lookahead = i + 1; lookahead < len; ++lookahead) {
ucs4 = string[lookahead];
if (QChar::isHighSurrogate(ucs4) && lookahead + 1 != len) {
ushort low = string[lookahead + 1];
@@ -276,6 +333,8 @@ static void getWordBreaks(const ushort *string, quint32 len, QCharAttributes *at
}
cls = ncls;
+ real_cls = ncls;
+
if (action == WB::Break) {
attributes[pos].wordBreak = true;
if (currentWordType != WordTypeNone)
@@ -343,11 +402,11 @@ static const uchar breakTable[BAfter + 1][QUnicodeTables::NumSentenceBreakClasse
} // namespace SB
-static void getSentenceBreaks(const ushort *string, quint32 len, QCharAttributes *attributes)
+static void getSentenceBreaks(const char16_t *string, qsizetype len, QCharAttributes *attributes)
{
uchar state = SB::BAfter; // to meet SB1
- for (quint32 i = 0; i != len; ++i) {
- quint32 pos = i;
+ for (qsizetype i = 0; i != len; ++i) {
+ qsizetype pos = i;
char32_t ucs4 = string[i];
if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
ushort low = string[i + 1];
@@ -364,7 +423,7 @@ static void getSentenceBreaks(const ushort *string, quint32 len, QCharAttributes
state = SB::breakTable[state][ncls];
if (Q_UNLIKELY(state == SB::Lookup)) { // SB8
state = SB::Break;
- for (quint32 lookahead = i + 1; lookahead < len; ++lookahead) {
+ for (qsizetype lookahead = i + 1; lookahead < len; ++lookahead) {
ucs4 = string[lookahead];
if (QChar::isHighSurrogate(ucs4) && lookahead + 1 != len) {
ushort low = string[lookahead + 1];
@@ -496,61 +555,67 @@ enum Action {
IndirectBreak, IB = IndirectBreak,
CombiningIndirectBreak, CI = CombiningIndirectBreak,
CombiningProhibitedBreak, CP = CombiningProhibitedBreak,
- ProhibitedBreakAfterHebrewPlusHyphen, HH = ProhibitedBreakAfterHebrewPlusHyphen
+ ProhibitedBreakAfterHebrewPlusHyphen, HH = ProhibitedBreakAfterHebrewPlusHyphen,
+ IndirectBreakIfNarrow, IN = IndirectBreakIfNarrow, // For LB30
};
-static const uchar breakTable[QUnicodeTables::LineBreak_SA][QUnicodeTables::LineBreak_SA] = {
-/* OP CL CP QU GL NS EX SY IS PR PO NU AL HL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT RI CB EB EM ZWJ*/
-/* OP */ { PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, CP, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB },
-/* CL */ { DB, PB, PB, IB, IB, PB, PB, PB, PB, DB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* CP */ { DB, PB, PB, IB, IB, PB, PB, PB, PB, DB, DB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* QU */ { PB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
-/* GL */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
-/* NS */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* EX */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* SY */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* IS */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* PR */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, IB, IB, DB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, IB, DB, DB, IB, IB, IB },
-/* PO */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* NU */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* AL */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* HL */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, CI, CI, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* ID */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* IN */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* HY */ { HH, PB, PB, IB, HH, IB, PB, PB, PB, HH, HH, IB, HH, HH, HH, HH, IB, IB, HH, HH, PB, CI, PB, HH, HH, HH, HH, HH, HH, DB, DB, DB, IB },
-/* BA */ { HH, PB, PB, IB, HH, IB, PB, PB, PB, HH, HH, HH, HH, HH, HH, HH, IB, IB, HH, HH, PB, CI, PB, HH, HH, HH, HH, HH, HH, DB, DB, DB, IB },
-/* BB */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, DB, IB, IB, IB },
-/* B2 */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, DB, IB, IB, DB, PB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* ZW */ { DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
-/* CM */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* WJ */ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
-/* H2 */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB, DB, DB, DB, DB, IB },
-/* H3 */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB, DB, DB, DB, DB, IB },
-/* JL */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, DB, DB, DB, DB, DB, IB },
-/* JV */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB, DB, DB, DB, DB, IB },
-/* JT */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB, DB, DB, DB, DB, IB },
-/* RI */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, IB, DB, DB, DB, IB },
-/* CB */ { DB, PB, PB, IB, IB, DB, PB, PB, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* EB */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, IB, IB },
-/* EM */ { DB, PB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
-/* ZWJ*/ { IB, PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, IB, IB, IB }
+// See https://www.unicode.org/reports/tr14/tr14-37.html for the information
+// about the table. It was removed in the later versions of the standard.
+static const uchar breakTable[QUnicodeTables::LineBreak_ZWJ][QUnicodeTables::LineBreak_ZWJ] = {
+/* 1↓ 2→ OP CL CP QU +Pi +Pf GL NS EX SY IS PR PO NU AL HL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT RI CB EB EM*/
+/* OP */ { PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, CP, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB },
+/* CL */ { DB, PB, PB, IB, IB, PB, IB, PB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* CP */ { DB, PB, PB, IB, IB, PB, IB, PB, PB, PB, PB, DB, DB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* QU */ { IB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
+/* +Pi*/ { PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, CP, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB },
+/* +Pf*/ { IB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
+/* GL */ { IB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
+/* NS */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* EX */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* SY */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, DB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* IS */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* PR */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, IB, IB, IB, IB, IB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, IB, DB, DB, IB, IB },
+/* PO */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* NU */ { IN, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* AL */ { IN, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* HL */ { IN, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, CI, CI, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* ID */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* IN */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* HY */ { HH, PB, PB, IB, IB, PB, HH, IB, PB, PB, PB, HH, HH, IB, HH, HH, HH, IB, IB, IB, HH, HH, PB, CI, PB, HH, HH, HH, HH, HH, HH, DB, DB, DB },
+/* BA */ { HH, PB, PB, IB, IB, PB, HH, IB, PB, PB, PB, HH, HH, HH, HH, HH, HH, IB, IB, IB, HH, HH, PB, CI, PB, HH, HH, HH, HH, HH, HH, DB, DB, DB },
+/* BB */ { IB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, DB, IB, IB },
+/* B2 */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, PB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* ZW */ { DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* CM */ { IB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* WJ */ { IB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB },
+/* H2 */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB, DB, DB, DB, DB },
+/* H3 */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB, DB, DB, DB, DB },
+/* JL */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, DB, DB, DB, DB, DB },
+/* JV */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB, DB, DB, DB, DB },
+/* JT */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB, DB, DB, DB, DB },
+/* RI */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, IB, DB, DB, DB },
+/* CB */ { DB, PB, PB, IB, IB, PB, IB, DB, PB, PB, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
+/* EB */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, IB },
+/* EM */ { DB, PB, PB, IB, IB, PB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB, DB, DB, DB, DB },
};
// The following line break classes are not treated by the pair table
// and must be resolved outside:
-// AI, BK, CB, CJ, CR, LF, NL, SA, SG, SP, XX
+// AI, AK, AP, AS, BK, CB, CJ, CR, LF, NL, SA, SG, SP, VF, VI, XX, ZWJ
} // namespace LB
-static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *attributes, QUnicodeTools::CharAttributeOptions options)
+static void getLineBreaks(const char16_t *string, qsizetype len, QCharAttributes *attributes, QUnicodeTools::CharAttributeOptions options)
{
- quint32 nestart = 0;
+ qsizetype nestart = 0;
LB::NS::Class nelast = LB::NS::XX;
QUnicodeTables::LineBreakClass lcls = QUnicodeTables::LineBreak_LF; // to meet LB10
QUnicodeTables::LineBreakClass cls = lcls;
- for (quint32 i = 0; i != len; ++i) {
- quint32 pos = i;
+ const QUnicodeTables::Properties *lastProp = QUnicodeTables::properties(U'\n');
+
+ for (qsizetype i = 0; i != len; ++i) {
+ qsizetype pos = i;
char32_t ucs4 = string[i];
if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
ushort low = string[i + 1];
@@ -596,6 +661,61 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
ncls = QUnicodeTables::LineBreak_CM;
}
+ if (Q_UNLIKELY(ncls == QUnicodeTables::LineBreak_QU)) {
+ if (prop->category == QChar::Punctuation_InitialQuote) {
+ // LB15a: Do not break after an unresolved initial punctuation
+ // that lies at the start of the line, after a space, after
+ // opening punctuation, or after an unresolved quotation mark,
+ // even after spaces.
+ // (sot | BK | CR | LF | NL | OP | QU | GL | SP | ZW)
+ // [\p{Pi}&QU] SP* ×
+ // Note: sot is treated as LF here due to initial loop setup.
+ constexpr QUnicodeTables::LineBreakClass lb15a[] = {
+ QUnicodeTables::LineBreak_BK, QUnicodeTables::LineBreak_CR,
+ QUnicodeTables::LineBreak_LF, QUnicodeTables::LineBreak_OP,
+ QUnicodeTables::LineBreak_QU, QUnicodeTables::LineBreak_QU_Pi,
+ QUnicodeTables::LineBreak_QU_Pf, QUnicodeTables::LineBreak_GL,
+ QUnicodeTables::LineBreak_SP, QUnicodeTables::LineBreak_ZW};
+ if (std::any_of(std::begin(lb15a), std::end(lb15a),
+ [lcls](auto x) { return x == lcls; })) {
+ ncls = QUnicodeTables::LineBreak_QU_Pi;
+ }
+ } else if (prop->category == QChar::Punctuation_FinalQuote) {
+ // LB15b: Do not break before an unresolved final punctuation
+ // that lies at the end of the line, before a space, before
+ // a prohibited break, or before an unresolved quotation mark,
+ // even after spaces.
+ // × [\p{Pf}&QU] ( SP | GL | WJ | CL | QU | CP | EX | IS
+ // | SY | BK | CR | LF | NL | ZW | eot)
+ auto nncls = QUnicodeTables::LineBreak_LF;
+
+ if (i + 1 < len) {
+ char32_t c = string[i + 1];
+ if (QChar::isHighSurrogate(c) && i + 2 != len) {
+ ushort low = string[i + 2];
+ if (QChar::isLowSurrogate(low))
+ c = QChar::surrogateToUcs4(c, low);
+ }
+ nncls = QUnicodeTables::LineBreakClass(
+ QUnicodeTables::properties(c)->lineBreakClass);
+ }
+
+ constexpr QUnicodeTables::LineBreakClass lb15b[] = {
+ QUnicodeTables::LineBreak_SP, QUnicodeTables::LineBreak_GL,
+ QUnicodeTables::LineBreak_WJ, QUnicodeTables::LineBreak_CL,
+ QUnicodeTables::LineBreak_QU, QUnicodeTables::LineBreak_QU_Pi,
+ QUnicodeTables::LineBreak_QU_Pf, QUnicodeTables::LineBreak_CP,
+ QUnicodeTables::LineBreak_EX, QUnicodeTables::LineBreak_IS,
+ QUnicodeTables::LineBreak_SY, QUnicodeTables::LineBreak_BK,
+ QUnicodeTables::LineBreak_CR, QUnicodeTables::LineBreak_LF,
+ QUnicodeTables::LineBreak_ZW};
+ if (std::any_of(std::begin(lb15b), std::end(lb15b),
+ [nncls](auto x) { return x == nncls; })) {
+ ncls = QUnicodeTables::LineBreak_QU_Pf;
+ }
+ }
+ }
+
if (Q_UNLIKELY(lcls >= QUnicodeTables::LineBreak_CR)) {
// LB4: BK!, LB5: (CRxLF|CR|LF|NL)!
if (lcls > QUnicodeTables::LineBreak_CR || ncls != QUnicodeTables::LineBreak_LF)
@@ -621,9 +741,8 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
}
if (Q_UNLIKELY(lcls == QUnicodeTables::LineBreak_ZWJ)) {
- // LB8a: ZWJ x (ID | EB | EM)
- if (ncls == QUnicodeTables::LineBreak_ID || ncls == QUnicodeTables::LineBreak_EB || ncls == QUnicodeTables::LineBreak_EM)
- goto next;
+ // LB8a: ZWJ x
+ goto next;
}
// LB25: do not break lines inside numbers
@@ -632,7 +751,7 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
switch (LB::NS::actionTable[nelast][necur]) {
case LB::NS::Break:
// do not change breaks before and after the expression
- for (quint32 j = nestart + 1; j < pos; ++j)
+ for (qsizetype j = nestart + 1; j < pos; ++j)
attributes[j].lineBreak = false;
Q_FALLTHROUGH();
case LB::NS::None:
@@ -653,16 +772,24 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
goto next;
}
+ if (Q_UNLIKELY(ncls == QUnicodeTables::LineBreak_EM
+ && lastProp->category == QChar::Other_NotAssigned
+ && lastProp->graphemeBreakClass
+ == QUnicodeTables::GraphemeBreak_Extended_Pictographic)) {
+ // LB30b: [\p{Extended_Pictographic}&\p{Cn}] × EM
+ goto next;
+ }
+
// for South East Asian chars that require a complex analysis, the Unicode
// standard recommends to treat them as AL. tailoring that do dictionary analysis can override
if (Q_UNLIKELY(cls >= QUnicodeTables::LineBreak_SA))
cls = QUnicodeTables::LineBreak_AL;
tcls = cls;
- if (tcls == QUnicodeTables::LineBreak_CM)
+ if (tcls == QUnicodeTables::LineBreak_CM || tcls == QUnicodeTables::LineBreak_ZWJ)
// LB10
tcls = QUnicodeTables::LineBreak_AL;
- switch (LB::breakTable[tcls][ncls < QUnicodeTables::LineBreak_SA ? ncls : QUnicodeTables::LineBreak_AL]) {
+ switch (LB::breakTable[tcls][ncls < QUnicodeTables::LineBreak_ZWJ ? ncls : QUnicodeTables::LineBreak_AL]) {
case LB::DirectBreak:
attributes[pos].lineBreak = true;
break;
@@ -683,6 +810,19 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
if (lcls != QUnicodeTables::LineBreak_HL)
attributes[pos].lineBreak = true;
break;
+ case LB::IndirectBreakIfNarrow:
+ switch (static_cast<QUnicodeTables::EastAsianWidth>(prop->eastAsianWidth)) {
+ default:
+ if (lcls != QUnicodeTables::LineBreak_SP)
+ break;
+ Q_FALLTHROUGH();
+ case QUnicodeTables::EastAsianWidth::F:
+ case QUnicodeTables::EastAsianWidth::W:
+ case QUnicodeTables::EastAsianWidth::H:
+ attributes[pos].lineBreak = true;
+ break;
+ }
+ break;
case LB::ProhibitedBreak:
// nothing to do
default:
@@ -691,13 +831,14 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
next:
cls = ncls;
+ lastProp = prop;
next_no_cls_update:
lcls = ncls;
}
if (Q_UNLIKELY(LB::NS::actionTable[nelast][LB::NS::XX] == LB::NS::Break)) {
// LB25: do not break lines inside numbers
- for (quint32 j = nestart + 1; j < len; ++j)
+ for (qsizetype j = nestart + 1; j < len; ++j)
attributes[j].lineBreak = false;
}
@@ -706,9 +847,9 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
}
-static void getWhiteSpaces(const ushort *string, quint32 len, QCharAttributes *attributes)
+static void getWhiteSpaces(const char16_t *string, qsizetype len, QCharAttributes *attributes)
{
- for (quint32 i = 0; i != len; ++i) {
+ for (qsizetype i = 0; i != len; ++i) {
uint ucs4 = string[i];
if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
ushort low = string[i + 1];
@@ -725,7 +866,7 @@ static void getWhiteSpaces(const ushort *string, quint32 len, QCharAttributes *a
namespace Tailored {
-using CharAttributeFunction = void (*)(QChar::Script script, const ushort *text, uint from, uint len, QCharAttributes *attributes);
+using CharAttributeFunction = void (*)(QChar::Script script, const char16_t *text, qsizetype from, qsizetype len, QCharAttributes *attributes);
enum Form {
@@ -1179,17 +1320,17 @@ static inline Form form(unsigned short uc) {
(Consonant Nukta? Halant)* Consonant Halant
IndependentVowel VowelMark? StressMark?
- We return syllable boundaries on invalid combinations aswell
+ We return syllable boundaries on invalid combinations as well
*/
-static int indic_nextSyllableBoundary(QChar::Script script, const ushort *s, int start, int end, bool *invalid)
+static qsizetype indic_nextSyllableBoundary(QChar::Script script, const char16_t *s, qsizetype start, qsizetype end, bool *invalid)
{
*invalid = false;
- IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end);
- const ushort *uc = s+start;
+ IDEBUG("indic_nextSyllableBoundary: start=%lld, end=%lld", qlonglong(start), qlonglong(end));
+ const char16_t *uc = s+start;
- int pos = 0;
+ qsizetype pos = 0;
Form state = form(uc[pos]);
- IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);
+ IDEBUG("state[%lld]=%d (uc=%4x)", qlonglong(pos), state, uc[pos]);
pos++;
if (state != Consonant && state != IndependentVowel) {
@@ -1200,7 +1341,7 @@ static int indic_nextSyllableBoundary(QChar::Script script, const ushort *s, int
while (pos < end - start) {
Form newState = form(uc[pos]);
- IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos]);
+ IDEBUG("state[%lld]=%d (uc=%4x)", qlonglong(pos), newState, uc[pos]);
switch (newState) {
case Control:
newState = state;
@@ -1242,11 +1383,11 @@ static int indic_nextSyllableBoundary(QChar::Script script, const ushort *s, int
case StressMark:
if (state == VowelMark)
break;
- // fall through
+ Q_FALLTHROUGH();
case VowelMark:
if (state == Matra || state == LengthMark || state == IndependentVowel)
break;
- // fall through
+ Q_FALLTHROUGH();
case Matra:
if (state == Consonant || state == Nukta)
break;
@@ -1273,6 +1414,7 @@ static int indic_nextSyllableBoundary(QChar::Script script, const ushort *s, int
// ### needs proper testing for correct two/three part matras
break;
}
+ Q_FALLTHROUGH();
case IndependentVowel:
case Invalid:
case Other:
@@ -1285,22 +1427,20 @@ static int indic_nextSyllableBoundary(QChar::Script script, const ushort *s, int
return pos+start;
}
-static void indicAttributes(QChar::Script script, const ushort *text, uint from, uint len, QCharAttributes *attributes)
+static void indicAttributes(QChar::Script script, const char16_t *text, qsizetype from, qsizetype len, QCharAttributes *attributes)
{
- int end = from + len;
- const ushort *uc = text + from;
+ qsizetype end = from + len;
attributes += from;
- uint i = 0;
+ qsizetype i = 0;
while (i < len) {
bool invalid;
- uint boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from;
+ qsizetype boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from;
attributes[i].graphemeBoundary = true;
if (boundary > len-1) boundary = len;
i++;
while (i < boundary) {
attributes[i].graphemeBoundary = false;
- ++uc;
++i;
}
assert(i == boundary);
@@ -1309,6 +1449,8 @@ static void indicAttributes(QChar::Script script, const ushort *text, uint from,
}
+#if QT_CONFIG(library)
+
#define LIBTHAI_MAJOR 0
/*
@@ -1319,38 +1461,87 @@ struct thcell_t {
unsigned char hilo; /**< upper/lower vowel/diacritic */
unsigned char top; /**< top-level mark */
};
-typedef int (*th_brk_def) (const unsigned char*, int*, size_t);
-typedef size_t (*th_next_cell_def) (const unsigned char *, size_t, struct thcell_t *, int);
-
-/* libthai related function handles */
-static th_brk_def th_brk = 0;
-static th_next_cell_def th_next_cell = 0;
-
-static int init_libthai() {
- static bool initialized = false;
- if (!initialized && (!th_brk || !th_next_cell)) {
- th_brk = (th_brk_def) QLibrary::resolve(QLatin1String("thai"), (int)LIBTHAI_MAJOR, "th_brk");
- th_next_cell = (th_next_cell_def)QLibrary::resolve(QLatin1String("thai"), LIBTHAI_MAJOR, "th_next_cell");
- initialized = true;
+
+using ThBrk = struct _ThBrk;
+
+namespace {
+
+class LibThai final
+{
+ Q_DISABLE_COPY_MOVE(LibThai)
+
+ using th_brk_new_def = ThBrk *(*)(const char *);
+ using th_brk_delete_def = void (*)(ThBrk *);
+ using th_brk_find_breaks_def = int (*)(ThBrk *, const unsigned char *, int *, size_t);
+ using th_next_cell_def = size_t (*)(const unsigned char *, size_t, struct thcell_t *, int);
+
+public:
+ LibThai() : m_library("thai"_L1, LIBTHAI_MAJOR)
+ {
+ m_th_brk_find_breaks =
+ reinterpret_cast<th_brk_find_breaks_def>(m_library.resolve("th_brk_find_breaks"));
+ m_th_next_cell = reinterpret_cast<th_next_cell_def>(m_library.resolve("th_next_cell"));
+
+ auto th_brk_new = reinterpret_cast<th_brk_new_def>(m_library.resolve("th_brk_new"));
+ if (th_brk_new) {
+ m_state = th_brk_new(nullptr);
+ m_th_brk_delete =
+ reinterpret_cast<th_brk_delete_def>(m_library.resolve("th_brk_delete"));
+ }
+ }
+
+ ~LibThai()
+ {
+ if (m_state && m_th_brk_delete)
+ m_th_brk_delete(m_state);
+ m_library.unload();
+ }
+
+ bool isInitialized() const { return m_th_brk_find_breaks && m_th_next_cell && m_state; }
+
+ int brk_find_breaks(const unsigned char *s, int *pos, size_t pos_sz) const
+ {
+ Q_ASSERT(m_state);
+ Q_ASSERT(m_th_brk_find_breaks);
+ return m_th_brk_find_breaks(m_state, s, pos, pos_sz);
+ }
+
+ size_t next_cell(const unsigned char *s, size_t len, struct thcell_t *cell, int is_decomp_am)
+ {
+ Q_ASSERT(m_th_next_cell);
+ return m_th_next_cell(s, len, cell, is_decomp_am);
}
- if (th_brk && th_next_cell)
- return 1;
- else
- return 0;
-}
-static void to_tis620(const ushort *string, uint len, char *cstr)
+private:
+ QLibrary m_library;
+
+ // Global state for th_brk_find_breaks().
+ // Note: even if signature for th_brk_find_breaks() suggests otherwise, the
+ // state is read-only, and so it is safe to use it from multiple threads after
+ // initialization. This is also stated in the libthai documentation.
+ ThBrk *m_state = nullptr;
+
+ th_brk_find_breaks_def m_th_brk_find_breaks = nullptr;
+ th_next_cell_def m_th_next_cell = nullptr;
+ th_brk_delete_def m_th_brk_delete = nullptr;
+};
+
+} // unnamed namespace
+
+Q_GLOBAL_STATIC(LibThai, g_libThai)
+
+static void to_tis620(const char16_t *string, qsizetype len, char *cstr)
{
- uint i;
- unsigned char *result = (unsigned char *)cstr;
+ qsizetype i;
+ unsigned char *result = reinterpret_cast<unsigned char *>(cstr);
for (i = 0; i < len; ++i) {
if (string[i] <= 0xa0)
- result[i] = (unsigned char)string[i];
+ result[i] = static_cast<unsigned char>(string[i]);
else if (string[i] >= 0xe01 && string[i] <= 0xe5b)
- result[i] = (unsigned char)(string[i] - 0xe00 + 0xa0);
+ result[i] = static_cast<unsigned char>(string[i] - 0xe00 + 0xa0);
else
- result[i] = (unsigned char)~0; // Same encoding as libthai uses for invalid chars
+ result[i] = static_cast<unsigned char>(~0); // Same encoding as libthai uses for invalid chars
}
result[len] = 0;
@@ -1359,23 +1550,19 @@ static void to_tis620(const ushort *string, uint len, char *cstr)
/*
* Thai Attributes: computes Word Break, Word Boundary and Char stop for THAI.
*/
-static void thaiAssignAttributes(const ushort *string, uint len, QCharAttributes *attributes)
+static void thaiAssignAttributes(const char16_t *string, qsizetype len, QCharAttributes *attributes)
{
- char s[128];
- char *cstr = s;
- int *break_positions = 0;
- int brp[128];
- int brp_size = 0;
- uint numbreaks, i, j, cell_length;
+ constexpr qsizetype Prealloc = 128;
+ QVarLengthArray<char, Prealloc + 1> s(len + 1);
+ QVarLengthArray<int, Prealloc> break_positions(len);
+ qsizetype numbreaks, i;
struct thcell_t tis_cell;
- if (!init_libthai())
- return ;
-
- if (len >= 128)
- cstr = (char *)malloc(len*sizeof(char) + 1);
+ LibThai *libThai = g_libThai;
+ if (!libThai || !libThai->isInitialized())
+ return;
- to_tis620(string, len, cstr);
+ to_tis620(string, len, s.data());
for (i = 0; i < len; ++i) {
attributes[i].wordBreak = false;
@@ -1384,61 +1571,53 @@ static void thaiAssignAttributes(const ushort *string, uint len, QCharAttributes
attributes[i].lineBreak = false;
}
- if (len > 128) {
- break_positions = (int*) malloc (sizeof(int) * len);
- memset (break_positions, 0, sizeof(int) * len);
- brp_size = len;
- }
- else {
- break_positions = brp;
- brp_size = 128;
- }
-
- if (break_positions) {
- attributes[0].wordBreak = true;
- attributes[0].wordStart = true;
- attributes[0].wordEnd = false;
- numbreaks = th_brk((const unsigned char *)cstr, break_positions, brp_size);
- for (i = 0; i < numbreaks; ++i) {
- attributes[break_positions[i]].wordBreak = true;
- attributes[break_positions[i]].wordStart = true;
- attributes[break_positions[i]].wordEnd = true;
- attributes[break_positions[i]].lineBreak = true;
- }
- if (numbreaks > 0)
- attributes[break_positions[numbreaks - 1]].wordStart = false;
-
- if (break_positions != brp)
- free(break_positions);
+ attributes[0].wordBreak = true;
+ attributes[0].wordStart = true;
+ attributes[0].wordEnd = false;
+ numbreaks = libThai->brk_find_breaks(reinterpret_cast<const unsigned char *>(s.data()),
+ break_positions.data(),
+ static_cast<size_t>(break_positions.size()));
+ for (i = 0; i < numbreaks; ++i) {
+ attributes[break_positions[i]].wordBreak = true;
+ attributes[break_positions[i]].wordStart = true;
+ attributes[break_positions[i]].wordEnd = true;
+ attributes[break_positions[i]].lineBreak = true;
}
+ if (numbreaks > 0)
+ attributes[break_positions[numbreaks - 1]].wordStart = false;
/* manage grapheme boundaries */
i = 0;
while (i < len) {
- cell_length = (uint)(th_next_cell((const unsigned char *)cstr + i, len - i, &tis_cell, true));
+ size_t cell_length =
+ libThai->next_cell(reinterpret_cast<const unsigned char *>(s.data()) + i,
+ size_t(len - i), &tis_cell, true);
attributes[i].graphemeBoundary = true;
- for (j = 1; j < cell_length; j++)
+ for (size_t j = 1; j < cell_length; ++j)
attributes[i + j].graphemeBoundary = false;
- /* Set graphemeBoundary for SARA AM */
- if (cstr[i + cell_length - 1] == (char)0xd3)
- attributes[i + cell_length - 1].graphemeBoundary = true;
-
i += cell_length;
}
-
- if (len >= 128)
- free(cstr);
}
-static void thaiAttributes(QChar::Script script, const ushort *text, uint from, uint len, QCharAttributes *attributes)
+#endif // QT_CONFIG(library)
+
+static void thaiAttributes(QChar::Script script, const char16_t *text, qsizetype from, qsizetype len, QCharAttributes *attributes)
{
assert(script == QChar::Script_Thai);
- const ushort *uc = text + from;
+#if QT_CONFIG(library)
+ const char16_t *uc = text + from;
attributes += from;
Q_UNUSED(script);
thaiAssignAttributes(uc, len, attributes);
+#else
+ Q_UNUSED(script);
+ Q_UNUSED(text);
+ Q_UNUSED(from);
+ Q_UNUSED(len);
+ Q_UNUSED(attributes);
+#endif
}
/*
@@ -1505,11 +1684,11 @@ static const unsigned char tibetanForm[0x80] = {
#define tibetan_form(c) \
((c) >= 0x0f40 && (c) < 0x0fc0 ? (TibetanForm)tibetanForm[(c) - 0x0f40] : TibetanOther)
-static int tibetan_nextSyllableBoundary(const ushort *s, int start, int end, bool *invalid)
+static qsizetype tibetan_nextSyllableBoundary(const char16_t *s, qsizetype start, qsizetype end, bool *invalid)
{
- const ushort *uc = s + start;
+ const char16_t *uc = s + start;
- int pos = 0;
+ qsizetype pos = 0;
TibetanForm state = tibetan_form(*uc);
/* qDebug("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);*/
@@ -1549,16 +1728,15 @@ finish:
return start+pos;
}
-static void tibetanAttributes(QChar::Script script, const ushort *text, uint from, uint len, QCharAttributes *attributes)
+static void tibetanAttributes(QChar::Script script, const char16_t *text, qsizetype from, qsizetype len, QCharAttributes *attributes)
{
- int end = from + len;
- const ushort *uc = text + from;
- uint i = 0;
+ qsizetype end = from + len;
+ qsizetype i = 0;
Q_UNUSED(script);
attributes += from;
while (i < len) {
bool invalid;
- uint boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from;
+ qsizetype boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from;
attributes[i].graphemeBoundary = true;
@@ -1566,7 +1744,6 @@ static void tibetanAttributes(QChar::Script script, const ushort *text, uint fro
i++;
while (i < boundary) {
attributes[i].graphemeBoundary = false;
- ++uc;
++i;
}
assert(i == boundary);
@@ -1617,6 +1794,8 @@ enum MymrCharClassFlags {
Mymr_CF_AFTER_KINZI = 0x00100000
};
+Q_DECLARE_MIXED_ENUM_OPERATORS(int, MymrCharClassValues, MymrCharClassFlags)
+
/* Characters that get refrered to by name */
enum MymrChar
{
@@ -1736,11 +1915,11 @@ static const signed char mymrStateTable[][Mymr_CC_COUNT] =
// calculate, using the state table, which one is the last character of the syllable
// that starts in the starting position.
*/
-static int myanmar_nextSyllableBoundary(const ushort *s, int start, int end, bool *invalid)
+static qsizetype myanmar_nextSyllableBoundary(const char16_t *s, qsizetype start, qsizetype end, bool *invalid)
{
- const ushort *uc = s + start;
+ const char16_t *uc = s + start;
int state = 0;
- int pos = start;
+ qsizetype pos = start;
*invalid = false;
while (pos < end) {
@@ -1749,7 +1928,7 @@ static int myanmar_nextSyllableBoundary(const ushort *s, int start, int end, boo
if (pos == start)
*invalid = (bool)(charClass & Mymr_CF_DOTTED_CIRCLE);
- MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, *uc);
+ MMDEBUG("state[%lld]=%d class=%8x (uc=%4x)", qlonglong(pos - start), state, charClass, *uc);
if (state < 0) {
if (state < -1)
@@ -1762,16 +1941,15 @@ static int myanmar_nextSyllableBoundary(const ushort *s, int start, int end, boo
return pos;
}
-static void myanmarAttributes(QChar::Script script, const ushort *text, uint from, uint len, QCharAttributes *attributes)
+static void myanmarAttributes(QChar::Script script, const char16_t *text, qsizetype from, qsizetype len, QCharAttributes *attributes)
{
- int end = from + len;
- const ushort *uc = text + from;
- uint i = 0;
+ qsizetype end = from + len;
+ qsizetype i = 0;
Q_UNUSED(script);
attributes += from;
while (i < len) {
bool invalid;
- uint boundary = myanmar_nextSyllableBoundary(text, from+i, end, &invalid) - from;
+ qsizetype boundary = myanmar_nextSyllableBoundary(text, from+i, end, &invalid) - from;
attributes[i].graphemeBoundary = true;
attributes[i].lineBreak = true;
@@ -1781,7 +1959,6 @@ static void myanmarAttributes(QChar::Script script, const ushort *text, uint fro
i++;
while (i < boundary) {
attributes[i].graphemeBoundary = false;
- ++uc;
++i;
}
assert(i == boundary);
@@ -1864,6 +2041,7 @@ enum KhmerCharClassFlags {
CF_POS_MASK = 0x000f0000
};
+Q_DECLARE_MIXED_ENUM_OPERATORS(int, KhmerCharClassValues, KhmerCharClassFlags)
/* Characters that get referred to by name */
enum KhmerChar {
@@ -2071,11 +2249,11 @@ static const signed char khmerStateTable[][CC_COUNT] =
// calculate, using the state table, which one is the last character of the syllable
// that starts in the starting position.
*/
-static int khmer_nextSyllableBoundary(const ushort *s, int start, int end, bool *invalid)
+static qsizetype khmer_nextSyllableBoundary(const char16_t *s, qsizetype start, qsizetype end, bool *invalid)
{
- const ushort *uc = s + start;
+ const char16_t *uc = s + start;
int state = 0;
- int pos = start;
+ qsizetype pos = start;
*invalid = false;
while (pos < end) {
@@ -2085,7 +2263,7 @@ static int khmer_nextSyllableBoundary(const ushort *s, int start, int end, bool
}
state = khmerStateTable[state][charClass & CF_CLASS_MASK];
- KHDEBUG("state[%d]=%d class=%8lx (uc=%4x)", pos - start, state,
+ KHDEBUG("state[%lld]=%d class=%8lx (uc=%4x)", qlonglong(pos - start), state,
charClass, *uc );
if (state < 0) {
@@ -2097,16 +2275,15 @@ static int khmer_nextSyllableBoundary(const ushort *s, int start, int end, bool
return pos;
}
-static void khmerAttributes(QChar::Script script, const ushort *text, uint from, uint len, QCharAttributes *attributes)
+static void khmerAttributes(QChar::Script script, const char16_t *text, qsizetype from, qsizetype len, QCharAttributes *attributes)
{
- int end = from + len;
- const ushort *uc = text + from;
- uint i = 0;
+ qsizetype end = from + len;
+ qsizetype i = 0;
Q_UNUSED(script);
attributes += from;
while ( i < len ) {
bool invalid;
- uint boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from;
+ qsizetype boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from;
attributes[i].graphemeBoundary = true;
@@ -2114,7 +2291,6 @@ static void khmerAttributes(QChar::Script script, const ushort *text, uint from,
i++;
while ( i < boundary ) {
attributes[i].graphemeBoundary = false;
- ++uc;
++i;
}
assert( i == boundary );
@@ -2191,52 +2367,52 @@ const CharAttributeFunction charAttributeFunction[] = {
khmerAttributes
};
-static void getCharAttributes(const ushort *string, uint stringLength,
- const QUnicodeTools::ScriptItem *items, uint numItems,
+static void getCharAttributes(const char16_t *string, qsizetype stringLength,
+ const QUnicodeTools::ScriptItem *items, qsizetype numItems,
QCharAttributes *attributes)
{
if (stringLength == 0)
return;
- for (uint i = 0; i < numItems; ++i) {
+ for (qsizetype i = 0; i < numItems; ++i) {
QChar::Script script = items[i].script;
if (script > QChar::Script_Khmer)
script = QChar::Script_Common;
CharAttributeFunction attributeFunction = charAttributeFunction[script];
if (!attributeFunction)
continue;
- int end = i < numItems - 1 ? items[i + 1].position : stringLength;
+ qsizetype end = i < numItems - 1 ? items[i + 1].position : stringLength;
attributeFunction(script, string, items[i].position, end - items[i].position, attributes);
}
}
}
-Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
- const ScriptItem *items, int numItems,
+Q_CORE_EXPORT void initCharAttributes(QStringView string,
+ const ScriptItem *items, qsizetype numItems,
QCharAttributes *attributes, CharAttributeOptions options)
{
- if (length <= 0)
+ if (string.size() <= 0)
return;
if (!(options & DontClearAttributes))
- ::memset(attributes, 0, (length + 1) * sizeof(QCharAttributes));
+ ::memset(attributes, 0, (string.size() + 1) * sizeof(QCharAttributes));
if (options & GraphemeBreaks)
- getGraphemeBreaks(string, length, attributes);
+ getGraphemeBreaks(string.utf16(), string.size(), attributes);
if (options & WordBreaks)
- getWordBreaks(string, length, attributes);
+ getWordBreaks(string.utf16(), string.size(), attributes);
if (options & SentenceBreaks)
- getSentenceBreaks(string, length, attributes);
+ getSentenceBreaks(string.utf16(), string.size(), attributes);
if (options & LineBreaks)
- getLineBreaks(string, length, attributes, options);
+ getLineBreaks(string.utf16(), string.size(), attributes, options);
if (options & WhiteSpaces)
- getWhiteSpaces(string, length, attributes);
+ getWhiteSpaces(string.utf16(), string.size(), attributes);
if (!qt_initcharattributes_default_algorithm_only) {
if (!items || numItems <= 0)
return;
- Tailored::getCharAttributes(string, length, items, numItems, attributes);
+ Tailored::getCharAttributes(string.utf16(), string.size(), items, numItems, attributes);
}
}
@@ -2247,16 +2423,16 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
//
// ----------------------------------------------------------------------------
-Q_CORE_EXPORT void initScripts(const ushort *string, int length, ScriptItemArray *scripts)
+Q_CORE_EXPORT void initScripts(QStringView string, ScriptItemArray *scripts)
{
- int sor = 0;
- int eor = 0;
+ qsizetype sor = 0;
+ qsizetype eor = 0;
QChar::Script script = QChar::Script_Common;
- for (int i = 0; i < length; ++i, eor = i) {
- char32_t ucs4 = string[i];
- if (QChar::isHighSurrogate(ucs4) && i + 1 < length) {
- ushort low = string[i + 1];
+ for (qsizetype i = 0; i < string.size(); ++i, eor = i) {
+ char32_t ucs4 = string[i].unicode();
+ if (QChar::isHighSurrogate(ucs4) && i + 1 < string.size()) {
+ ushort low = string[i + 1].unicode();
if (QChar::isLowSurrogate(low)) {
ucs4 = QChar::surrogateToUcs4(ucs4, low);
++i;
@@ -2294,7 +2470,7 @@ Q_CORE_EXPORT void initScripts(const ushort *string, int length, ScriptItemArray
}
Q_ASSERT(script >= QChar::Script_Common);
- Q_ASSERT(eor == length);
+ Q_ASSERT(eor == string.size());
scripts->append(ScriptItem{sor, script});
}
diff --git a/src/corelib/text/qunicodetools_p.h b/src/corelib/text/qunicodetools_p.h
index 5715444025..06f31a5511 100644
--- a/src/corelib/text/qunicodetools_p.h
+++ b/src/corelib/text/qunicodetools_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QUNICODETOOLS_P_H
#define QUNICODETOOLS_P_H
@@ -74,7 +38,7 @@ namespace QUnicodeTools {
struct ScriptItem
{
- int position;
+ qsizetype position;
QChar::Script script;
};
@@ -91,19 +55,18 @@ enum CharAttributeOption {
LineBreaks = 0x08,
WhiteSpaces = 0x10,
HangulLineBreakTailoring = 0x20,
- DefaultOptionsCompat = GraphemeBreaks | LineBreaks | WhiteSpaces, // ### remove
DontClearAttributes = 0x1000
};
Q_DECLARE_FLAGS(CharAttributeOptions, CharAttributeOption)
// attributes buffer has to have a length of string length + 1
-Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
- const ScriptItem *items, int numItems,
- QCharAttributes *attributes, CharAttributeOptions options = DefaultOptionsCompat);
+Q_CORE_EXPORT void initCharAttributes(QStringView str,
+ const ScriptItem *items, qsizetype numItems,
+ QCharAttributes *attributes, CharAttributeOptions options);
-Q_CORE_EXPORT void initScripts(const ushort *string, int length, ScriptItemArray *scripts);
+Q_CORE_EXPORT void initScripts(QStringView str, ScriptItemArray *scripts);
} // namespace QUnicodeTools
diff --git a/src/corelib/text/qutf8stringview.h b/src/corelib/text/qutf8stringview.h
new file mode 100644
index 0000000000..fe105e283e
--- /dev/null
+++ b/src/corelib/text/qutf8stringview.h
@@ -0,0 +1,434 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QUTF8STRINGVIEW_H
+#define QUTF8STRINGVIEW_H
+
+#if 0
+#pragma qt_class(QUtf8StringView)
+#endif
+
+#include <QtCore/qstringalgorithms.h>
+#include <QtCore/qstringfwd.h>
+#include <QtCore/qarraydata.h> // for QContainerImplHelper
+#include <QtCore/qbytearrayview.h>
+#include <QtCore/qcompare.h>
+
+#include <string>
+#include <string_view>
+#include <QtCore/q20type_traits.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+template <typename Char>
+using IsCompatibleChar8TypeHelper = std::disjunction<
+#ifdef __cpp_char8_t
+ std::is_same<Char, char8_t>,
+#endif
+ std::is_same<Char, char>,
+ std::is_same<Char, uchar>,
+ std::is_same<Char, signed char>
+ >;
+template <typename Char>
+using IsCompatibleChar8Type
+ = IsCompatibleChar8TypeHelper<q20::remove_cvref_t<Char>>;
+
+template <typename Pointer>
+struct IsCompatiblePointer8Helper : std::false_type {};
+template <typename Char>
+struct IsCompatiblePointer8Helper<Char*>
+ : IsCompatibleChar8Type<Char> {};
+template <typename Pointer>
+using IsCompatiblePointer8
+ = IsCompatiblePointer8Helper<q20::remove_cvref_t<Pointer>>;
+
+template <typename T, typename Enable = void>
+struct IsContainerCompatibleWithQUtf8StringView : std::false_type {};
+
+template <typename T>
+struct IsContainerCompatibleWithQUtf8StringView<T, std::enable_if_t<std::conjunction_v<
+ // lacking concepts and ranges, we accept any T whose std::data yields a suitable pointer ...
+ IsCompatiblePointer8<decltype(std::data(std::declval<const T &>()))>,
+ // ... and that has a suitable size ...
+ std::is_convertible<
+ decltype(std::size(std::declval<const T &>())),
+ qsizetype
+ >,
+ // ... and it's a range as it defines an iterator-like API
+ IsCompatibleChar8Type<typename std::iterator_traits<
+ decltype(std::begin(std::declval<const T &>()))>::value_type
+ >,
+ std::is_convertible<
+ decltype( std::begin(std::declval<const T &>()) != std::end(std::declval<const T &>()) ),
+ bool
+ >,
+
+ // This needs to be treated specially due to the empty vs null distinction
+ std::negation<std::is_same<std::decay_t<T>, QByteArray>>,
+
+ // This has a compatible value_type, but explicitly a different encoding
+ std::negation<std::is_same<std::decay_t<T>, QLatin1StringView>>,
+
+ // Don't make an accidental copy constructor
+ std::negation<std::disjunction<
+ std::is_same<std::decay_t<T>, QBasicUtf8StringView<true>>,
+ std::is_same<std::decay_t<T>, QBasicUtf8StringView<false>>
+ >>
+ >>> : std::true_type {};
+
+struct hide_char8_t {
+#ifdef __cpp_char8_t
+ using type = char8_t;
+#endif
+};
+
+struct wrap_char { using type = char; };
+
+} // namespace QtPrivate
+
+#ifdef Q_QDOC
+#define QBasicUtf8StringView QUtf8StringView
+#else
+template <bool UseChar8T>
+#endif
+class QBasicUtf8StringView
+{
+public:
+#ifndef Q_QDOC
+ using storage_type = typename std::conditional<UseChar8T,
+ QtPrivate::hide_char8_t,
+ QtPrivate::wrap_char
+ >::type::type;
+#else
+ using storage_type = typename QtPrivate::hide_char8_t;
+#endif
+ typedef const storage_type value_type;
+ typedef qptrdiff difference_type;
+ typedef qsizetype size_type;
+ typedef value_type &reference;
+ typedef value_type &const_reference;
+ typedef value_type *pointer;
+ typedef value_type *const_pointer;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+private:
+ template <typename Char>
+ using if_compatible_char = std::enable_if_t<QtPrivate::IsCompatibleChar8Type<Char>::value, bool>;
+
+ template <typename Pointer>
+ using if_compatible_pointer = std::enable_if_t<QtPrivate::IsCompatiblePointer8<Pointer>::value, bool>;
+
+ template <typename T>
+ using if_compatible_qstring_like = std::enable_if_t<std::is_same_v<T, QByteArray>, bool>;
+
+ template <typename T>
+ using if_compatible_container = std::enable_if_t<QtPrivate::IsContainerCompatibleWithQUtf8StringView<T>::value, bool>;
+
+ template <typename Container>
+ static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
+ {
+ return qsizetype(std::size(c));
+ }
+
+ // Note: Do not replace with std::size(const Char (&)[N]), cause the result
+ // will be of by one.
+ template <typename Char, size_t N>
+ static constexpr qsizetype lengthHelperContainer(const Char (&str)[N]) noexcept
+ {
+ const auto it = std::char_traits<Char>::find(str, N, Char(0));
+ const auto end = it ? it : std::next(str, N);
+ return qsizetype(std::distance(str, end));
+ }
+
+ template <typename Char>
+ static const storage_type *castHelper(const Char *str) noexcept
+ { return reinterpret_cast<const storage_type*>(str); }
+ static constexpr const storage_type *castHelper(const storage_type *str) noexcept
+ { return str; }
+
+public:
+ constexpr QBasicUtf8StringView() noexcept
+ : m_data(nullptr), m_size(0) {}
+ constexpr QBasicUtf8StringView(std::nullptr_t) noexcept
+ : QBasicUtf8StringView() {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ constexpr QBasicUtf8StringView(const Char *str, qsizetype len)
+ : m_data(castHelper(str)),
+ m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)) {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ constexpr QBasicUtf8StringView(const Char *f, const Char *l)
+ : QBasicUtf8StringView(f, l - f) {}
+
+#ifdef Q_QDOC
+ template <typename Char, size_t N>
+ constexpr QBasicUtf8StringView(const Char (&array)[N]) noexcept;
+
+ template <typename Char>
+ constexpr QBasicUtf8StringView(const Char *str) noexcept;
+#else
+ template <typename Pointer, if_compatible_pointer<Pointer> = true>
+ constexpr QBasicUtf8StringView(const Pointer &str) noexcept
+ : QBasicUtf8StringView(str,
+ str ? std::char_traits<std::remove_cv_t<std::remove_pointer_t<Pointer>>>::length(str) : 0) {}
+#endif
+
+#ifdef Q_QDOC
+ QBasicUtf8StringView(const QByteArray &str) noexcept;
+ constexpr QBasicUtf8StringView(const storage_type *d, qsizetype n) noexcept {};
+#else
+ template <typename String, if_compatible_qstring_like<String> = true>
+ QBasicUtf8StringView(const String &str) noexcept
+ : QBasicUtf8StringView(str.isNull() ? nullptr : str.data(), qsizetype(str.size())) {}
+#endif
+
+ template <typename Container, if_compatible_container<Container> = true>
+ constexpr QBasicUtf8StringView(const Container &c) noexcept
+ : QBasicUtf8StringView(std::data(c), lengthHelperContainer(c)) {}
+
+#if defined(__cpp_char8_t) && !defined(Q_QDOC)
+ constexpr QBasicUtf8StringView(QBasicUtf8StringView<!UseChar8T> other)
+ : QBasicUtf8StringView(other.data(), other.size()) {}
+#endif
+
+ template <typename Char, size_t Size, if_compatible_char<Char> = true>
+ [[nodiscard]] constexpr static QBasicUtf8StringView fromArray(const Char (&string)[Size]) noexcept
+ { return QBasicUtf8StringView(string, Size); }
+
+ [[nodiscard]] inline QString toString() const; // defined in qstring.h
+
+ [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
+ [[nodiscard]] constexpr const_pointer data() const noexcept { return m_data; }
+#ifdef __cpp_char8_t
+ [[nodiscard]] const char8_t *utf8() const noexcept { return reinterpret_cast<const char8_t*>(m_data); }
+#endif
+
+ [[nodiscard]] constexpr storage_type operator[](qsizetype n) const
+ { verify(n, 1); return m_data[n]; }
+
+ //
+ // QString API
+ //
+
+ [[nodiscard]] constexpr storage_type at(qsizetype n) const { return (*this)[n]; }
+
+ [[nodiscard]]
+ constexpr QBasicUtf8StringView mid(qsizetype pos, qsizetype n = -1) const
+ {
+ using namespace QtPrivate;
+ auto result = QContainerImplHelper::mid(size(), &pos, &n);
+ return result == QContainerImplHelper::Null ? QBasicUtf8StringView() : QBasicUtf8StringView(m_data + pos, n);
+ }
+ [[nodiscard]]
+ constexpr QBasicUtf8StringView left(qsizetype n) const
+ {
+ if (size_t(n) >= size_t(size()))
+ n = size();
+ return QBasicUtf8StringView(m_data, n);
+ }
+ [[nodiscard]]
+ constexpr QBasicUtf8StringView right(qsizetype n) const
+ {
+ if (size_t(n) >= size_t(size()))
+ n = size();
+ return QBasicUtf8StringView(m_data + m_size - n, n);
+ }
+
+ [[nodiscard]] constexpr QBasicUtf8StringView sliced(qsizetype pos) const
+ { verify(pos, 0); return QBasicUtf8StringView{m_data + pos, m_size - pos}; }
+ [[nodiscard]] constexpr QBasicUtf8StringView sliced(qsizetype pos, qsizetype n) const
+ { verify(pos, n); return QBasicUtf8StringView(m_data + pos, n); }
+ [[nodiscard]] constexpr QBasicUtf8StringView first(qsizetype n) const
+ { verify(0, n); return sliced(0, n); }
+ [[nodiscard]] constexpr QBasicUtf8StringView last(qsizetype n) const
+ { verify(0, n); return sliced(m_size - n, n); }
+ [[nodiscard]] constexpr QBasicUtf8StringView chopped(qsizetype n) const
+ { verify(0, n); return sliced(0, m_size - n); }
+
+ constexpr void truncate(qsizetype n)
+ { verify(0, n); m_size = n; }
+ constexpr void chop(qsizetype n)
+ { verify(0, n); m_size -= n; }
+
+ [[nodiscard]] inline bool isValidUtf8() const noexcept
+ {
+ return QByteArrayView(reinterpret_cast<const char *>(data()), size()).isValidUtf8();
+ }
+
+ //
+ // STL compatibility API:
+ //
+ [[nodiscard]] const_iterator begin() const noexcept { return data(); }
+ [[nodiscard]] const_iterator end() const noexcept { return data() + size(); }
+ [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
+
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+ [[nodiscard]] constexpr storage_type front() const { return Q_ASSERT(!empty()), m_data[0]; }
+ [[nodiscard]] constexpr storage_type back() const { return Q_ASSERT(!empty()), m_data[m_size - 1]; }
+
+ [[nodiscard]] Q_IMPLICIT operator std::basic_string_view<storage_type>() const noexcept
+ { return std::basic_string_view<storage_type>(data(), size_t(size())); }
+
+ //
+ // Qt compatibility API:
+ //
+ [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
+ [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
+ [[nodiscard]] constexpr qsizetype length() const noexcept
+ { return size(); }
+
+ [[nodiscard]] int compare(QBasicUtf8StringView other,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ {
+ return QtPrivate::compareStrings(*this, other, cs);
+ }
+
+ [[nodiscard]] int compare(QChar other,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] int compare(QStringView other,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] int compare(QLatin1StringView other,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ [[nodiscard]] int compare(const QByteArray &other,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+
+ [[nodiscard]] bool equal(QChar other) const noexcept;
+ [[nodiscard]] bool equal(QStringView other) const noexcept;
+ [[nodiscard]] bool equal(QLatin1StringView other) const noexcept;
+ [[nodiscard]] bool equal(const QByteArray &other) const noexcept;
+
+private:
+ [[nodiscard]] static inline int compare(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
+ {
+ return QtPrivate::compareStrings(QBasicUtf8StringView<false>(lhs.data(), lhs.size()),
+ QBasicUtf8StringView<false>(rhs.data(), rhs.size()));
+ }
+
+ friend bool
+ comparesEqual(const QBasicUtf8StringView &lhs, const QBasicUtf8StringView &rhs) noexcept
+ {
+ return lhs.size() == rhs.size()
+ && QtPrivate::equalStrings(QBasicUtf8StringView<false>(lhs.data(), lhs.size()),
+ QBasicUtf8StringView<false>(rhs.data(), rhs.size()));
+ }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const QBasicUtf8StringView &rhs) noexcept
+ {
+ const int res = QBasicUtf8StringView::compare(lhs, rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView)
+
+ friend bool
+ comparesEqual(const QBasicUtf8StringView &lhs, const QLatin1StringView &rhs) noexcept
+ {
+ return lhs.equal(rhs);
+ }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const QLatin1StringView &rhs) noexcept
+ {
+ const int res = lhs.compare(rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, QLatin1StringView)
+
+ friend bool
+ comparesEqual(const QBasicUtf8StringView &lhs, const QStringView &rhs) noexcept
+ { return lhs.equal(rhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const QStringView &rhs) noexcept
+ {
+ const int res = lhs.compare(rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, QStringView)
+
+ friend bool comparesEqual(const QBasicUtf8StringView &lhs, const QChar &rhs) noexcept
+ { return lhs.equal(rhs); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const QChar &rhs) noexcept
+ {
+ const int res = lhs.compare(rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, QChar)
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, char16_t)
+
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ friend bool
+ comparesEqual(const QBasicUtf8StringView &lhs, const QByteArrayView &rhs) noexcept
+ {
+ return lhs.size() == rhs.size()
+ && QtPrivate::equalStrings(QBasicUtf8StringView<false>(lhs.data(), lhs.size()),
+ QBasicUtf8StringView<false>(rhs.data(), rhs.size()));
+ }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const QByteArrayView &rhs) noexcept
+ {
+ const int res = QtPrivate::compareStrings(QBasicUtf8StringView<false>(lhs.data(), lhs.size()),
+ QBasicUtf8StringView<false>(rhs.data(), rhs.size()));
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, QByteArrayView, QT_ASCII_CAST_WARN)
+
+ friend bool
+ comparesEqual(const QBasicUtf8StringView &lhs, const QByteArray &rhs) noexcept
+ {
+ return lhs.equal(rhs);
+ }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const QByteArray &rhs) noexcept
+ {
+ const int res = lhs.compare(rhs);
+ return Qt::compareThreeWay(res, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, QByteArray, QT_ASCII_CAST_WARN)
+
+ friend bool comparesEqual(const QBasicUtf8StringView &lhs, const char *rhs) noexcept
+ { return comparesEqual(lhs, QByteArrayView(rhs)); }
+ friend Qt::strong_ordering
+ compareThreeWay(const QBasicUtf8StringView &lhs, const char *rhs) noexcept
+ { return compareThreeWay(lhs, QByteArrayView(rhs)); }
+ Q_DECLARE_STRONGLY_ORDERED(QBasicUtf8StringView, const char *, QT_ASCII_CAST_WARN)
+#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+ const storage_type *m_data;
+ qsizetype m_size;
+};
+
+constexpr QByteArrayView::QByteArrayView(QUtf8StringView v) noexcept
+ : QByteArrayView(v.data(), v.size())
+{}
+
+#ifdef Q_QDOC
+#undef QBasicUtf8StringView
+#else
+template <bool UseChar8T>
+Q_DECLARE_TYPEINFO_BODY(QBasicUtf8StringView<UseChar8T>, Q_PRIMITIVE_TYPE);
+
+template <typename QStringLike, std::enable_if_t<std::is_same_v<QStringLike, QByteArray>, bool> = true>
+[[nodiscard]] inline q_no_char8_t::QUtf8StringView qToUtf8StringViewIgnoringNull(const QStringLike &s) noexcept
+{ return q_no_char8_t::QUtf8StringView(s.begin(), s.size()); }
+#endif // Q_QDOC
+
+QT_END_NAMESPACE
+
+#endif /* QUTF8STRINGVIEW_H */
diff --git a/src/corelib/text/qutf8stringview.qdoc b/src/corelib/text/qutf8stringview.qdoc
new file mode 100644
index 0000000000..b433e5b995
--- /dev/null
+++ b/src/corelib/text/qutf8stringview.qdoc
@@ -0,0 +1,720 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \class QUtf8StringView
+ \inmodule QtCore
+ \since 6.0
+ \brief The QUtf8StringView class provides a unified view on UTF-8 strings
+ with a read-only subset of the QString API.
+ \reentrant
+ \ingroup tools
+ \ingroup string-processing
+
+ \compares strong
+ \compareswith strong char16_t QChar {const char16_t *} QString QStringView \
+ QLatin1StringView
+ \endcompareswith
+ \compareswith strong {const char *} QByteArray QByteArrayView
+ The contents of byte arrays is interpreted as utf-8.
+ \endcompareswith
+
+ A QUtf8StringView references a contiguous portion of a UTF-8
+ string it does not own. It acts as an interface type to all kinds
+ of UTF-8 string, without the need to construct a QString or
+ QByteArray first.
+
+ The UTF-8 string may be represented as an array (or an
+ array-compatible data-structure such as std::basic_string, etc.)
+ of \c char8_t, \c char, \c{signed char} or \c{unsigned char}.
+
+ QUtf8StringView is designed as an interface type; its main
+ use-case is as a function parameter type. When QUtf8StringViews
+ are used as automatic variables or data members, care must be
+ taken to ensure that the referenced string data (for example,
+ owned by a std::u8string) outlives the QUtf8StringView on all code
+ paths, lest the string view ends up referencing deleted data.
+
+ When used as an interface type, QUtf8StringView allows a single
+ function to accept a wide variety of UTF-8 string data
+ sources. One function accepting QUtf8StringView thus replaces
+ several function overloads (taking e.g. QByteArray), while at the
+ same time enabling even more string data sources to be passed to
+ the function, such as \c{u8"Hello World"}, a \c char8_t (C++20) or
+ \c char (C++17) string literal. The \c char8_t incompatibility
+ between C++17 and C++20 goes away when using QUtf8StringView.
+
+ Like all views, QUtf8StringViews should be passed by value, not by
+ reference-to-const:
+ \snippet code/src_corelib_text_qutf8stringview.cpp 0
+
+ If you want to give your users maximum freedom in what strings
+ they can pass to your function, consider using QAnyStringView
+ instead.
+
+ QUtf8StringView can also be used as the return value of a
+ function. If you call a function returning QUtf8StringView, take
+ extra care to not keep the QUtf8StringView around longer than the
+ function promises to keep the referenced string data alive. If in
+ doubt, obtain a strong reference to the data by calling toString()
+ to convert the QUtf8StringView into a QString.
+
+ QUtf8StringView is a \e{Literal Type}.
+
+ \section2 Compatible Character Types
+
+ QUtf8StringView accepts strings over a variety of character types:
+
+ \list
+ \li \c char (both signed and unsigned)
+ \li \c char8_t (C++20 only)
+ \endlist
+
+ \section2 Sizes and Sub-Strings
+
+ All sizes and positions in QUtf8StringView functions are in
+ UTF-8 code points (that is, UTF-8 multibyte sequences count as
+ two, three or four, depending on their length). QUtf8StringView
+ does not an attempt to detect or prevent slicing right through
+ UTF-8 multibyte sequences. This is similar to the situation with
+ QStringView and surrogate pairs.
+
+ \section2 C++20, char8_t, and QUtf8StringView
+
+ In C++20, \c{u8""} string literals changed their type from
+ \c{const char[]} to \c{const char8_t[]}. If Qt 6 could have depended
+ on C++20, QUtf8StringView would store \c char8_t natively, and the
+ following functions and aliases would use (pointers to) \c char8_t:
+
+ \list
+ \li storage_type, value_type, etc
+ \li begin(), end(), data(), etc
+ \li front(), back(), at(), operator[]()
+ \endlist
+
+ This is what QUtf8StringView is expected to look like in Qt 7, but for
+ Qt 6, this was not possible. Instead of locking users into a C++17-era
+ interface for the next decade, Qt provides two QUtf8StringView classes,
+ in different (inline) namespaces. The first, in namespace \c{q_no_char8_t},
+ has a value_type of \c{const char} and is universally available.
+ The second, in namespace \c{q_has_char8_t}, has a value_type of
+ \c{const char8_t} and is only available when compiling in C++20 mode.
+
+ \c{q_no_char8_t} is an inline namespace regardless of C++ edition, to avoid
+ accidental binary incompatibilities. To use the \c{char8_t} version, you
+ need to name it explicitly with \c{q_has_char8_t::QUtf8StringView}.
+
+ Internally, both are instantiations of the same template class,
+ QBasicUtf8StringView. Please do not use the template class's name in your
+ source code.
+
+ \sa QAnyStringView, QUtf8StringView, QString
+*/
+
+/*!
+ \typedef QUtf8StringView::storage_type
+
+ Alias for \c{char}.
+*/
+
+/*!
+ \typedef QUtf8StringView::value_type
+
+ Alias for \c{const char}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QUtf8StringView::difference_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QUtf8StringView::size_type
+
+ Alias for qsizetype. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QUtf8StringView::reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+
+ QUtf8StringView does not support mutable references, so this is the same
+ as const_reference.
+*/
+
+/*!
+ \typedef QUtf8StringView::const_reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QUtf8StringView::pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+
+ QUtf8StringView does not support mutable pointers, so this is the same
+ as const_pointer.
+*/
+
+/*!
+ \typedef QUtf8StringView::const_pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QUtf8StringView::iterator
+
+ This typedef provides an STL-style const iterator for QUtf8StringView.
+
+ QUtf8StringView does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QUtf8StringView::const_iterator
+
+ This typedef provides an STL-style const iterator for QUtf8StringView.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QUtf8StringView::reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QUtf8StringView.
+
+ QUtf8StringView does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QUtf8StringView::const_reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QUtf8StringView.
+
+ \sa reverse_iterator, const_iterator
+*/
+
+/*!
+ \fn QUtf8StringView::QUtf8StringView()
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QUtf8StringView::QUtf8StringView(const storage_type *d, qsizetype n)
+ \internal
+*/
+
+/*!
+ \fn QUtf8StringView::QUtf8StringView(std::nullptr_t)
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn template <typename Char, QUtf8StringView::if_compatible_char<Char> = true> QUtf8StringView::QUtf8StringView(const Char *str, qsizetype len)
+
+ Constructs a string view on \a str with length \a len.
+
+ The range \c{[str,len)} must remain valid for the lifetime of this string view object.
+
+ Passing \nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
+
+ The behavior is undefined if \a len is negative or, when positive, if \a str is \nullptr.
+
+ This constructor only participates in overload resolution if \c Char is a compatible
+ character type. The compatible character types are: \c char8_t, \c char, \c{signed char} and
+ \c{unsigned char}.
+*/
+
+/*!
+ \fn template <typename Char, QUtf8StringView::if_compatible_char<Char> = true> QUtf8StringView::QUtf8StringView(const Char *first, const Char *last)
+
+ Constructs a string view on \a first with length (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this string view object.
+
+ Passing \c \nullptr as \a first is safe if \a last is \nullptr, too,
+ and results in a null string view.
+
+ The behavior is undefined if \a last precedes \a first, or \a first
+ is \nullptr and \a last is not.
+
+ This constructor only participates in overload resolution if \c Char is a compatible
+ character type. The compatible character types are: \c char8_t, \c char, \c{signed char} and
+ \c{unsigned char}.
+*/
+
+/*!
+ \fn template <typename Char> QUtf8StringView::QUtf8StringView(const Char *str)
+
+ Constructs a string view on \a str. The length is determined
+ by scanning for the first \c{Char(0)}.
+
+ \a str must remain valid for the lifetime of this string view object.
+
+ Passing \nullptr as \a str is safe and results in a null string view.
+
+ This constructor only participates in overload resolution if \a str
+ is not an array and if \c Char is a compatible character type. The
+ compatible character types are: \c char8_t, \c char, \c{signed char} and
+ \c{unsigned char}.
+*/
+
+/*!
+ \fn template <typename Char, size_t N> QUtf8StringView::QUtf8StringView(const Char (&string)[N])
+
+ Constructs a string view on the character string literal \a string.
+ The view covers the array until the first \c{Char(0)} is encountered,
+ or \c N, whichever comes first.
+ If you need the full array, use fromArray() instead.
+
+ \a string must remain valid for the lifetime of this string view
+ object.
+
+ This constructor only participates in overload resolution if \a string
+ is an actual array and if \c Char is a compatible character type. The
+ compatible character types are: \c char8_t, \c char, \c{signed char} and
+ \c{unsigned char}.
+
+ \sa fromArray()
+*/
+
+/*!
+ \fn template <typename Container, QUtf8StringView::if_compatible_container<Container>> QUtf8StringView::QUtf8StringView(const Container &str)
+
+ Constructs a string view on \a str. The length is taken from \c{std::size(str)}.
+
+ \c{std::data(str)} must remain valid for the lifetime of this string view object.
+
+ This constructor only participates in overload resolution if \c Container is a
+ container with a compatible character type as \c{value_type}. The
+ compatible character types are: \c char8_t, \c char, \c{signed char} and
+ \c{unsigned char}.
+
+ The string view will be empty if and only if \c{std::size(str) == 0}. It is unspecified
+ whether this constructor can result in a null string view (\c{std::data(str)} would
+ have to return \nullptr for this).
+
+ \sa isNull(), isEmpty()
+*/
+
+/*!
+ \fn template <typename Char, size_t Size, QUtf8StringView::if_compatible_char<Char>> QUtf8StringView::fromArray(const Char (&string)[Size])
+
+ Constructs a string view on the full character string literal \a string,
+ including any trailing \c{Char(0)}. If you don't want the
+ null-terminator included in the view then you can chop() it off
+ when you are certain it is at the end. Alternatively you can use
+ the constructor overload taking an array literal which will create
+ a view up to, but not including, the first null-terminator in the data.
+
+ \a string must remain valid for the lifetime of this string view
+ object.
+
+ This function will work with any array literal if \c Char is a
+ compatible character type. The compatible character types
+ are: \c char8_t, \c char, \c{signed char} and \c{unsigned char}.
+*/
+
+/*!
+ \fn QString QUtf8StringView::toString() const
+
+ Returns a deep copy of this string view's data as a QString.
+
+ The return value will be a null QString if and only if this string view is null.
+*/
+
+/*!
+ \fn QUtf8StringView::data() const
+
+ Returns a const pointer to the first code point in the string view.
+
+ \note The character array represented by the return value is \e not null-terminated.
+
+ \sa begin(), end(), utf8()
+*/
+
+/*!
+ \fn QUtf8StringView::utf8() const
+
+ Returns a const pointer to the first code point in the string view.
+
+ The result is returned as a \c{const char8_t*}, so this function is only available when
+ compiling in C++20 mode.
+
+ \note The character array represented by the return value is \e not null-terminated.
+
+ \sa begin(), end(), data()
+*/
+
+/*!
+ \fn QUtf8StringView::const_iterator QUtf8StringView::begin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first code point in
+ the string view.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QUtf8StringView::const_iterator QUtf8StringView::cbegin() const
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QUtf8StringView::const_iterator QUtf8StringView::end() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ code point after the last code point in the list.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QUtf8StringView::const_iterator QUtf8StringView::cend() const
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QUtf8StringView::const_reverse_iterator QUtf8StringView::rbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ code point in the string view, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QUtf8StringView::const_reverse_iterator QUtf8StringView::crbegin() const
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QUtf8StringView::const_reverse_iterator QUtf8StringView::rend() const
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last code point in the string view, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QUtf8StringView::const_reverse_iterator QUtf8StringView::crend() const
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
+/*!
+ \fn bool QUtf8StringView::empty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size(), length()
+*/
+
+/*!
+ \fn bool QUtf8StringView::isEmpty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa empty(), isNull(), size(), length()
+*/
+
+/*!
+ \fn bool QUtf8StringView::isNull() const
+
+ Returns whether this string view is null - that is, whether \c{data() == nullptr}.
+
+ This functions is provided for compatibility with other Qt containers.
+
+ \sa empty(), isEmpty(), size(), length()
+*/
+
+/*!
+ \fn qsizetype QUtf8StringView::size() const
+
+ Returns the size of this string view, in UTF-8 code points (that is,
+ multi-byte sequences count as more than one for the purposes of this function, the same
+ as surrogate pairs in QString and QStringView).
+
+ \sa empty(), isEmpty(), isNull(), length()
+*/
+
+/*!
+ \fn QUtf8StringView::length() const
+
+ Same as size().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa empty(), isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn QUtf8StringView::operator[](qsizetype n) const
+
+ Returns the code point at position \a n in this string view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa at(), front(), back()
+*/
+
+/*!
+ \fn QUtf8StringView::at(qsizetype n) const
+
+ Returns the code point at position \a n in this string view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa operator[](), front(), back()
+*/
+
+/*!
+ \fn QUtf8StringView::front() const
+
+ Returns the first code point in the string view. Same as first().
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa back()
+*/
+
+/*!
+ \fn QUtf8StringView::back() const
+
+ Returns the last code point in the string view. Same as last().
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa front()
+*/
+
+/*!
+ \fn QUtf8StringView::mid(qsizetype pos, qsizetype n) const
+
+ Returns the substring of length \a n starting at position
+ \a pos in this object.
+
+ \deprecated Use sliced() instead in new code.
+
+ Returns an empty string view if \a n exceeds the
+ length of the string view. If there are less than \a n code points
+ available in the string view starting at \a pos, or if
+ \a n is negative (default), the function returns all code points that
+ are available from \a pos.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::left(qsizetype n) const
+
+ \deprecated Use first() instead in new code.
+
+ Returns the substring of length \a n starting at position
+ 0 in this object.
+
+ The entire string view is returned if \a n is greater than or equal
+ to size(), or less than zero.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::right(qsizetype n) const
+
+ \deprecated Use last() instead in new code.
+
+ Returns the substring of length \a n starting at position
+ size() - \a n in this object.
+
+ The entire string view is returned if \a n is greater than or equal
+ to size(), or less than zero.
+
+ \sa first(), last(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::first(qsizetype n) const
+
+ Returns a string view that contains the first \a n code points
+ of this string view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa last(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::last(qsizetype n) const
+
+ Returns a string view that contains the last \a n code points of this string view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa first(), sliced(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::sliced(qsizetype pos, qsizetype n) const
+
+ Returns a string view containing \a n code points of this string view,
+ starting at position \a pos.
+
+//! [UB-sliced-index-length]
+ \note The behavior is undefined when \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+//! [UB-sliced-index-length]
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::sliced(qsizetype pos) const
+
+ Returns a string view starting at position \a pos in this object,
+ and extending to its end.
+
+//! [UB-sliced-index-only]
+ \note The behavior is undefined when \a pos < 0 or \a pos > size().
+//! [UB-sliced-index-only]
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::chopped(qsizetype n) const
+
+ Returns the substring of length size() - \a n starting at the
+ beginning of this object.
+
+ Same as \c{first(size() - n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa sliced(), first(), last(), chop(), truncate()
+*/
+
+/*!
+ \fn QUtf8StringView::truncate(qsizetype n)
+
+ Truncates this string view to \a n code points.
+
+ Same as \c{*this = first(n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa sliced(), first(), last(), chopped(), chop()
+*/
+
+/*!
+ \fn QUtf8StringView::chop(qsizetype n)
+
+ Truncates this string view by \a n code points.
+
+ Same as \c{*this = first(size() - n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa sliced(), first(), last(), chopped(), truncate()
+*/
+
+/*!
+ \fn int QUtf8StringView::compare(QLatin1StringView str, Qt::CaseSensitivity cs) const
+ \fn int QUtf8StringView::compare(QUtf8StringView str, Qt::CaseSensitivity cs) const
+ \fn int QUtf8StringView::compare(QStringView str, Qt::CaseSensitivity cs) const
+ \since 6.5
+
+ Compares this string view with \a str and returns a negative integer if
+ this string view is less than \a str, a positive integer if it is greater than
+ \a str, and zero if they are equal.
+
+ \include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
+*/
+
+
+/*!
+ \fn QUtf8StringView::isValidUtf8() const
+
+ Returns \c true if this string contains valid UTF-8 encoded data,
+ or \c false otherwise.
+
+ \since 6.3
+*/
+
+/*!
+ \fn template <typename QStringLike> qToUtf8StringViewIgnoringNull(const QStringLike &s);
+ \relates QUtf8StringView
+ \internal
+
+ Convert \a s to a QUtf8StringView ignoring \c{s.isNull()}.
+
+ Returns a string view that references \a{s}'s data, but is never null.
+
+ This is a faster way to convert a QByteArray to a QUtf8StringView,
+ if null QByteArrays can legitimately be treated as empty ones.
+
+ \sa QByteArray::isNull(), QUtf8StringView
+*/
+
+
+/*! \fn QUtf8StringView::operator std::basic_string_view<storage_type>() const
+ \since 6.7
+
+ Converts this QUtf8StringView object to a
+ \c{std::basic_string_view} object. The returned view will have the
+ same data pointer and length of this view. The character type of
+ the returned view will be \c{storage_type}.
+*/
diff --git a/src/corelib/text/qvsnprintf.cpp b/src/corelib/text/qvsnprintf.cpp
index 43a21771a1..839fc24217 100644
--- a/src/corelib/text/qvsnprintf.cpp
+++ b/src/corelib/text/qvsnprintf.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
@@ -46,7 +10,7 @@
QT_BEGIN_NAMESPACE
-#if !defined(QT_VSNPRINTF) || defined(Q_CLANG_QDOC)
+#if !defined(QT_VSNPRINTF) || defined(Q_QDOC)
/*!
\relates QByteArray
diff --git a/src/corelib/text/text.pri b/src/corelib/text/text.pri
deleted file mode 100644
index 1d83bc151b..0000000000
--- a/src/corelib/text/text.pri
+++ /dev/null
@@ -1,92 +0,0 @@
-# Qt text / string / character / unicode / byte array module
-
-HEADERS += \
- text/qbytearray.h \
- text/qbytearray_p.h \
- text/qbytearraylist.h \
- text/qbytearraymatcher.h \
- text/qbytedata_p.h \
- text/qchar.h \
- text/qcollator.h \
- text/qcollator_p.h \
- text/qdoublescanprint_p.h \
- text/qlocale.h \
- text/qlocale_p.h \
- text/qlocale_tools_p.h \
- text/qlocale_data_p.h \
- text/qregexp.h \
- text/qstring.h \
- text/qstringalgorithms.h \
- text/qstringalgorithms_p.h \
- text/qstringbuilder.h \
- text/qstringconverter.h \
- text/qstringconverter_p.h \
- text/qstringiterator_p.h \
- text/qstringlist.h \
- text/qstringliteral.h \
- text/qstringmatcher.h \
- text/qstringview.h \
- text/qstringtokenizer.h \
- text/qtextboundaryfinder.h \
- text/qunicodetables_p.h \
- text/qunicodetools_p.h
-
-
-SOURCES += \
- text/qbytearray.cpp \
- text/qbytearraylist.cpp \
- text/qbytearraymatcher.cpp \
- text/qcollator.cpp \
- text/qlocale.cpp \
- text/qlocale_tools.cpp \
- text/qregexp.cpp \
- text/qstring.cpp \
- text/qstringbuilder.cpp \
- text/qstringconverter.cpp \
- text/qstringlist.cpp \
- text/qstringview.cpp \
- text/qstringtokenizer.cpp \
- text/qtextboundaryfinder.cpp \
- text/qunicodetools.cpp \
- text/qvsnprintf.cpp
-
-NO_PCH_SOURCES += text/qstring_compat.cpp
-false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator
-
-!nacl:darwin: {
- SOURCES += text/qlocale_mac.mm
-}
-else:unix {
- SOURCES += text/qlocale_unix.cpp
-}
-else:win32 {
- SOURCES += text/qlocale_win.cpp
-} else:integrity {
- SOURCES += text/qlocale_unix.cpp
-}
-
-qtConfig(icu) {
- QMAKE_USE_PRIVATE += icu
-
- SOURCES += text/qlocale_icu.cpp \
- text/qcollator_icu.cpp
-} else: win32 {
- SOURCES += text/qcollator_win.cpp
-} else: macos {
- SOURCES += text/qcollator_macx.cpp
-} else {
- SOURCES += text/qcollator_posix.cpp
-}
-
-qtConfig(regularexpression) {
- QMAKE_USE_PRIVATE += pcre2
-
- HEADERS += \
- text/qregularexpression.h
- SOURCES += text/qregularexpression.cpp
-}
-
-TR_EXCLUDE += ../3rdparty/*
-
-# MIPS DSP
-MIPS_DSP_ASM += text/qstring_mips_dsp_asm.S
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index d302da72eb..a437eb3319 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qatomic.h"
@@ -67,19 +31,19 @@
The template parameter \c T must be a C++ integer type:
\list
- \li 8-bit: char, signed char, unsigned char, qint8, quint8
- \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
- \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
+ \li 8-bit: bool, char, signed char, unsigned char, qint8, quint8, char8_t (C++20)
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t
\li 64-bit: long long, unsigned long long, qint64, quint64
\li platform-specific size: long, unsigned long
\li pointer size: qintptr, quintptr, qptrdiff
\endlist
- Of the list above, only the 32-bit- and pointer-sized instantiations are guaranteed to
- work on all platforms. Support for other sizes depends on the compiler and
- processor architecture the code is being compiled for. To test whether the
- other types are supported, check the macro \c Q_ATOMIC_INT\e{nn}_IS_SUPPORTED,
- where \c{\e{nn}} is the number of bits desired.
+ Of the list above, only the 8-bit, 16-bit, 32-bit- and pointer-sized
+ instantiations are guaranteed to work on all platforms. Support for other
+ sizes depends on the compiler and processor architecture the code is being
+ compiled for. To test whether the 64-bit types are supported on 32-bit
+ platforms, check the macro \c Q_ATOMIC_INT64_IS_SUPPORTED.
\section1 The Atomic API
@@ -261,19 +225,6 @@
/*!
- \fn template <typename T> T QAtomicInteger<T>::load() const
- \obsolete
-
- Use loadRelaxed() instead.
-
- Atomically loads the value of this QAtomicInteger using relaxed memory
- ordering. The value is not modified in any way, but note that there's no
- guarantee that it remains so.
-
- \sa storeRelaxed(), loadAcquire()
-*/
-
-/*!
\fn template <typename T> T QAtomicInteger<T>::loadRelaxed() const
\since 5.14
@@ -295,18 +246,6 @@
*/
/*!
- \fn template <typename T> void QAtomicInteger<T>::store(T newValue)
- \obsolete
-
- Use storeRelaxed() instead.
-
- Atomically stores the \a newValue value into this atomic type, using
- relaxed memory ordering.
-
- \sa storeRelease(), loadRelaxed()
-*/
-
-/*!
\fn template <typename T> void QAtomicInteger<T>::storeRelaxed(T newValue)
\since 5.14
@@ -322,7 +261,7 @@
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
- \sa store(), loadAcquire()
+ \sa storeRelaxed(), loadAcquire()
*/
/*!
@@ -458,14 +397,21 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-relaxed]
This function uses \e relaxed \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses.
+//![memory-order-relaxed]
+
*/
/*!
@@ -473,15 +419,21 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-acquire]
This function uses \e acquire \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not
be re-ordered before the atomic operation.
+//![memory-order-acquire]
*/
/*!
@@ -489,15 +441,21 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-release]
This function uses \e release \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be
re-ordered after the atomic operation.
+//![memory-order-release]
*/
/*!
@@ -505,15 +463,78 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-ordered]
This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
+//![memory-order-ordered]
+
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelaxed(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, the functions load the
+ current value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-relaxed
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetAcquire(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, the functions load the
+ current value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-acquire
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelease(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, the functions loads the
+ current value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-release
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetOrdered(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, it loads the current
+ value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-ordered
*/
/*!
@@ -1011,9 +1032,16 @@
This macro is defined if atomic integers of size \e{nn} (in bits) are
supported in this compiler / architecture combination.
- Q_ATOMIC_INT32_IS_SUPPORTED is always defined.
\e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
+
+ The following macros always defined:
+
+ \list
+ \li Q_ATOMIC_INT8_IS_SUPPORTED
+ \li Q_ATOMIC_INT16_IS_SUPPORTED
+ \li Q_ATOMIC_INT32_IS_SUPPORTED
+ \endlist
*/
/*!
@@ -1331,7 +1359,7 @@
\endlist
- \sa QAtomicInteger
+ \sa QAtomicInteger, qYieldCpu()
*/
/*!
@@ -1354,19 +1382,6 @@
*/
/*!
- \fn template <typename T> T *QAtomicPointer<T>::load() const
- \obsolete
-
- Use loadRelaxed() instead.
-
- Atomically loads the value of this QAtomicPointer using relaxed memory
- ordering. The value is not modified in any way, but note that there's no
- guarantee that it remains so.
-
- \sa storeRelaxed(), loadAcquire()
-*/
-
-/*!
\fn template <typename T> T *QAtomicPointer<T>::loadRelaxed() const
\since 5.14
@@ -1389,18 +1404,6 @@
*/
/*!
- \fn template <typename T> void QAtomicPointer<T>::store(T *newValue)
- \obsolete
-
- Use storeRelaxed() instead.
-
- Atomically stores the \a newValue value into this atomic type, using
- relaxed memory ordering.
-
- \sa storeRelease(), loadRelaxed()
-*/
-
-/*!
\fn template <typename T> void QAtomicPointer<T>::storeRelaxed(T *newValue)
\since 5.14
@@ -1739,6 +1742,12 @@
*/
// static checks
+#ifndef Q_ATOMIC_INT8_IS_SUPPORTED
+# error "Q_ATOMIC_INT8_IS_SUPPORTED must be defined"
+#endif
+#ifndef Q_ATOMIC_INT16_IS_SUPPORTED
+# error "Q_ATOMIC_INT16_IS_SUPPORTED must be defined"
+#endif
#ifndef Q_ATOMIC_INT32_IS_SUPPORTED
# error "Q_ATOMIC_INT32_IS_SUPPORTED must be defined"
#endif
@@ -1755,28 +1764,21 @@ static_assert(sizeof(QAtomicInteger<long>));
static_assert(sizeof(QAtomicInteger<unsigned long>));
static_assert(sizeof(QAtomicInteger<quintptr>));
static_assert(sizeof(QAtomicInteger<qptrdiff>));
-#ifdef Q_COMPILER_UNICODE_STRINGS
static_assert(sizeof(QAtomicInteger<char32_t>));
-#endif
-#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
static_assert(sizeof(QAtomicInteger<short>));
static_assert(sizeof(QAtomicInteger<unsigned short>));
-# if WCHAR_MAX < 0x10000
static_assert(sizeof(QAtomicInteger<wchar_t>));
-# endif
-# ifdef Q_COMPILER_UNICODE_STRINGS
static_assert(sizeof(QAtomicInteger<char16_t>));
-# endif
-#endif
+
+static_assert(sizeof(QAtomicInteger<char>));
+static_assert(sizeof(QAtomicInteger<unsigned char>));
+static_assert(sizeof(QAtomicInteger<signed char>));
+static_assert(sizeof(QAtomicInteger<bool>));
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
static_assert(sizeof(QAtomicInteger<qint64>));
static_assert(sizeof(QAtomicInteger<quint64>));
#endif
-#if WCHAR_MAX == INT_MAX
-static_assert(sizeof(QAtomicInteger<wchar_t>));
-#endif
-
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index aa57ddc610..7fe5ac69b9 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -1,44 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QATOMIC_H
#define QATOMIC_H
@@ -50,29 +12,16 @@ QT_BEGIN_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wextra")
-#ifdef Q_CLANG_QDOC
-# undef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
-#endif
-
// High-level atomic integer operations
template <typename T>
class QAtomicInteger : public QBasicAtomicInteger<T>
{
public:
// Non-atomic API
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
constexpr QAtomicInteger(T value = 0) noexcept : QBasicAtomicInteger<T>(value) {}
-#else
- inline QAtomicInteger(T value = 0) noexcept
- {
- this->_q_value = value;
- }
-#endif
inline QAtomicInteger(const QAtomicInteger &other) noexcept
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
: QBasicAtomicInteger<T>()
-#endif
{
this->storeRelease(other.loadAcquire());
}
@@ -83,41 +32,44 @@ public:
return *this;
}
-#ifdef Q_CLANG_QDOC
- T load() const;
+#ifdef Q_QDOC
T loadRelaxed() const;
T loadAcquire() const;
- void store(T newValue);
void storeRelaxed(T newValue);
void storeRelease(T newValue);
operator T() const;
QAtomicInteger &operator=(T);
- static Q_DECL_CONSTEXPR bool isReferenceCountingNative();
- static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree();
+ static constexpr bool isReferenceCountingNative();
+ static constexpr bool isReferenceCountingWaitFree();
bool ref();
bool deref();
- static Q_DECL_CONSTEXPR bool isTestAndSetNative();
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree();
+ static constexpr bool isTestAndSetNative();
+ static constexpr bool isTestAndSetWaitFree();
bool testAndSetRelaxed(T expectedValue, T newValue);
bool testAndSetAcquire(T expectedValue, T newValue);
bool testAndSetRelease(T expectedValue, T newValue);
bool testAndSetOrdered(T expectedValue, T newValue);
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative();
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree();
+ bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue);
+ bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue);
+ bool testAndSetRelease(T expectedValue, T newValue, T &currentValue);
+ bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue);
+
+ static constexpr bool isFetchAndStoreNative();
+ static constexpr bool isFetchAndStoreWaitFree();
T fetchAndStoreRelaxed(T newValue);
T fetchAndStoreAcquire(T newValue);
T fetchAndStoreRelease(T newValue);
T fetchAndStoreOrdered(T newValue);
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative();
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree();
+ static constexpr bool isFetchAndAddNative();
+ static constexpr bool isFetchAndAddWaitFree();
T fetchAndAddRelaxed(T valueToAdd);
T fetchAndAddAcquire(T valueToAdd);
@@ -162,10 +114,7 @@ public:
// Non-atomic API
// We could use QT_COMPILER_INHERITING_CONSTRUCTORS, but we need only one;
// the implicit definition for all the others is fine.
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr
-#endif
- QAtomicInt(int value = 0) noexcept : QAtomicInteger<int>(value) {}
+ constexpr QAtomicInt(int value = 0) noexcept : QAtomicInteger<int>(value) {}
};
// High-level atomic pointer operations
@@ -173,18 +122,10 @@ template <typename T>
class QAtomicPointer : public QBasicAtomicPointer<T>
{
public:
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
constexpr QAtomicPointer(T *value = nullptr) noexcept : QBasicAtomicPointer<T>(value) {}
-#else
- inline QAtomicPointer(T *value = nullptr) noexcept
- {
- this->storeRelaxed(value);
- }
-#endif
+
inline QAtomicPointer(const QAtomicPointer<T> &other) noexcept
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
: QBasicAtomicPointer<T>()
-#endif
{
this->storeRelease(other.loadAcquire());
}
@@ -196,31 +137,29 @@ public:
}
#ifdef Q_QDOC
- T *load() const;
T *loadAcquire() const;
T *loadRelaxed() const;
- void store(T *newValue);
void storeRelaxed(T *newValue);
void storeRelease(T *newValue);
- static Q_DECL_CONSTEXPR bool isTestAndSetNative();
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree();
+ static constexpr bool isTestAndSetNative();
+ static constexpr bool isTestAndSetWaitFree();
bool testAndSetRelaxed(T *expectedValue, T *newValue);
bool testAndSetAcquire(T *expectedValue, T *newValue);
bool testAndSetRelease(T *expectedValue, T *newValue);
bool testAndSetOrdered(T *expectedValue, T *newValue);
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative();
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree();
+ static constexpr bool isFetchAndStoreNative();
+ static constexpr bool isFetchAndStoreWaitFree();
T *fetchAndStoreRelaxed(T *newValue);
T *fetchAndStoreAcquire(T *newValue);
T *fetchAndStoreRelease(T *newValue);
T *fetchAndStoreOrdered(T *newValue);
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative();
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree();
+ static constexpr bool isFetchAndAddNative();
+ static constexpr bool isFetchAndAddWaitFree();
T *fetchAndAddRelaxed(qptrdiff valueToAdd);
T *fetchAndAddAcquire(qptrdiff valueToAdd);
@@ -231,10 +170,6 @@ public:
QT_WARNING_POP
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
-# undef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
-#endif
-
/*!
This is a helper for the assignment operators of implicitly
shared classes. Your assignment operator should look like this:
diff --git a/src/corelib/thread/qatomic_bootstrap.h b/src/corelib/thread/qatomic_bootstrap.h
deleted file mode 100644
index c4279ee7b1..0000000000
--- a/src/corelib/thread/qatomic_bootstrap.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QATOMIC_BOOTSTRAP_H
-#define QATOMIC_BOOTSTRAP_H
-
-#include <QtCore/qgenericatomic.h>
-
-QT_BEGIN_NAMESPACE
-
-#if 0
-// silence syncqt warnings
-QT_END_NAMESPACE
-#pragma qt_sync_skip_header_check
-#pragma qt_sync_stop_processing
-#endif
-
-template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
-{
- typedef T Type;
-
- static bool ref(T &_q_value) noexcept
- {
- return ++_q_value != 0;
- }
- static bool deref(T &_q_value) noexcept
- {
- return --_q_value != 0;
- }
-
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
- {
- if (currentValue)
- *currentValue = _q_value;
- if (_q_value == expectedValue) {
- _q_value = newValue;
- return true;
- }
- return false;
- }
-
- static T fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
- {
- T tmp = _q_value;
- _q_value = newValue;
- return tmp;
- }
-
- template <typename AdditiveType> static
- T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) noexcept
- {
- T returnValue = _q_value;
- _q_value += valueToAdd;
- return returnValue;
- }
-};
-
-QT_END_NAMESPACE
-
-#endif // QATOMIC_BOOTSTRAP_H
diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h
index 9669554515..47a7bc9a10 100644
--- a/src/corelib/thread/qatomic_cxx11.h
+++ b/src/corelib/thread/qatomic_cxx11.h
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QATOMIC_CXX11_H
#define QATOMIC_CXX11_H
#include <QtCore/qgenericatomic.h>
+#include <QtCore/qyieldcpu.h>
#include <atomic>
QT_BEGIN_NAMESPACE
@@ -70,10 +35,8 @@ QT_END_NAMESPACE
* QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So
* we'll err in the side of caution and say it isn't.
*/
-
-// ### Qt 6: make non-constexpr (see above)
template <int N> struct QAtomicTraits
-{ static Q_DECL_CONSTEXPR inline bool isLockFree(); };
+{ static inline bool isLockFree(); };
#define Q_ATOMIC_INT32_IS_SUPPORTED
#if ATOMIC_INT_LOCK_FREE == 2
@@ -86,7 +49,7 @@ template <int N> struct QAtomicTraits
# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
+template <> inline bool QAtomicTraits<4>::isLockFree()
{ return true; }
#elif ATOMIC_INT_LOCK_FREE == 1
# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
@@ -98,7 +61,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
+template <> inline bool QAtomicTraits<4>::isLockFree()
{ return false; }
#else
# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE
@@ -110,7 +73,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE
# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
+template <> inline bool QAtomicTraits<4>::isLockFree()
{ return false; }
#endif
@@ -139,7 +102,7 @@ template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; };
# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE
# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree()
+template <> inline bool QAtomicTraits<1>::isLockFree()
{ return true; }
#elif ATOMIC_CHAR_LOCK_FREE == 1
# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
@@ -147,7 +110,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree()
# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree()
+template <> inline bool QAtomicTraits<1>::isLockFree()
{ return false; }
#else
# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE
@@ -155,7 +118,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree()
# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE
# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE
-template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree()
+template <> bool QAtomicTraits<1>::isLockFree()
{ return false; }
#endif
@@ -167,7 +130,7 @@ template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
+template <> inline bool QAtomicTraits<2>::isLockFree()
{ return false; }
#elif ATOMIC_SHORT_LOCK_FREE == 1
# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
@@ -175,7 +138,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
+template <> inline bool QAtomicTraits<2>::isLockFree()
{ return false; }
#else
# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE
@@ -183,11 +146,11 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE
# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
+template <> inline bool QAtomicTraits<2>::isLockFree()
{ return false; }
#endif
-#if QT_CONFIG(std_atomic64)
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(std_atomic64)
template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
# define Q_ATOMIC_INT64_IS_SUPPORTED
# if ATOMIC_LLONG_LOCK_FREE == 2
@@ -196,7 +159,7 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
+template <> inline bool QAtomicTraits<8>::isLockFree()
{ return true; }
# elif ATOMIC_LLONG_LOCK_FREE == 1
# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
@@ -204,7 +167,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
+template <> inline bool QAtomicTraits<8>::isLockFree()
{ return false; }
# else
# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NEVER_NATIVE
@@ -212,7 +175,7 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NEVER_NATIVE
# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NEVER_NATIVE
-template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
+template <> inline bool QAtomicTraits<8>::isLockFree()
{ return false; }
# endif
#endif
@@ -275,23 +238,37 @@ template <typename X> struct QAtomicOps
_q_value.store(newValue, std::memory_order_release);
}
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return false; }
+ static inline bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); }
+ static inline constexpr bool isReferenceCountingWaitFree() noexcept { return false; }
template <typename T>
static inline bool ref(std::atomic<T> &_q_value)
{
- return ++_q_value != 0;
+ /* Conceptually, we want to
+ * return ++_q_value != 0;
+ * However, that would be sequentially consistent, and thus stronger
+ * than what we need. Based on
+ * http://eel.is/c++draft/atomics.types.memop#6, we know that
+ * pre-increment is equivalent to fetch_add(1) + 1. Unlike
+ * pre-increment, fetch_add takes a memory order argument, so we can get
+ * the desired acquire-release semantics.
+ * One last gotcha is that fetch_add(1) + 1 would need to be converted
+ * back to T, because it's susceptible to integer promotion. To sidestep
+ * this issue and to avoid UB on signed overflow, we rewrite the
+ * expression to:
+ */
+ return _q_value.fetch_add(1, std::memory_order_acq_rel) != T(-1);
}
template <typename T>
static inline bool deref(std::atomic<T> &_q_value) noexcept
{
- return --_q_value != 0;
+ // compare with ref
+ return _q_value.fetch_sub(1, std::memory_order_acq_rel) != T(1);
}
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept
+ static inline bool isTestAndSetNative() noexcept
{ return QAtomicTraits<sizeof(X)>::isLockFree(); }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return false; }
+ static inline constexpr bool isTestAndSetWaitFree() noexcept { return false; }
template <typename T>
static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
@@ -329,8 +306,8 @@ template <typename X> struct QAtomicOps
return tmp;
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; }
+ static inline bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); }
+ static inline constexpr bool isFetchAndStoreWaitFree() noexcept { return false; }
template <typename T>
static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
@@ -356,8 +333,8 @@ template <typename X> struct QAtomicOps
return _q_value.exchange(newValue, std::memory_order_acq_rel);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; }
+ static inline bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); }
+ static inline constexpr bool isFetchAndAddWaitFree() noexcept { return false; }
template <typename T> static inline
T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
@@ -480,11 +457,7 @@ template <typename X> struct QAtomicOps
}
};
-#if defined(Q_COMPILER_CONSTEXPR)
# define Q_BASIC_ATOMIC_INITIALIZER(a) { a }
-#else
-# define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) }
-#endif
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qatomic_msvc.h b/src/corelib/thread/qatomic_msvc.h
deleted file mode 100644
index 54b12f5bb2..0000000000
--- a/src/corelib/thread/qatomic_msvc.h
+++ /dev/null
@@ -1,485 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QATOMIC_MSVC_H
-#define QATOMIC_MSVC_H
-
-#include <QtCore/qgenericatomic.h>
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// use compiler intrinsics for all atomic functions
-# define QT_INTERLOCKED_PREFIX _
-# define QT_INTERLOCKED_PROTOTYPE
-# define QT_INTERLOCKED_DECLARE_PROTOTYPES
-# define QT_INTERLOCKED_INTRINSIC
-# define Q_ATOMIC_INT16_IS_SUPPORTED
-
-# ifdef _WIN64
-# define Q_ATOMIC_INT64_IS_SUPPORTED
-# endif
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Prototype declaration
-
-#define QT_INTERLOCKED_CONCAT_I(prefix, suffix) \
- prefix ## suffix
-#define QT_INTERLOCKED_CONCAT(prefix, suffix) \
- QT_INTERLOCKED_CONCAT_I(prefix, suffix)
-
-// MSVC intrinsics prefix function names with an underscore. Also, if platform
-// SDK headers have been included, the Interlocked names may be defined as
-// macros.
-// To avoid double underscores, we paste the prefix with Interlocked first and
-// then the remainder of the function name.
-#define QT_INTERLOCKED_FUNCTION(name) \
- QT_INTERLOCKED_CONCAT( \
- QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, Interlocked), name)
-
-#ifndef QT_INTERLOCKED_VOLATILE
-# define QT_INTERLOCKED_VOLATILE volatile
-#endif
-
-#ifndef QT_INTERLOCKED_PREFIX
-#define QT_INTERLOCKED_PREFIX
-#endif
-
-#ifndef QT_INTERLOCKED_PROTOTYPE
-#define QT_INTERLOCKED_PROTOTYPE
-#endif
-
-#ifdef QT_INTERLOCKED_DECLARE_PROTOTYPES
-#undef QT_INTERLOCKED_DECLARE_PROTOTYPES
-
-extern "C" {
-
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment )(long QT_INTERLOCKED_VOLATILE *);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement )(long QT_INTERLOCKED_VOLATILE *);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange )(long QT_INTERLOCKED_VOLATILE *, long, long);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange )(long QT_INTERLOCKED_VOLATILE *, long);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd )(long QT_INTERLOCKED_VOLATILE *, long);
-
-# if !defined(__i386__) && !defined(_M_IX86)
- void * QT_INTERLOCKED_FUNCTION( CompareExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *, void *);
- void * QT_INTERLOCKED_FUNCTION( ExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *);
- __int64 QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64);
-# endif
-
-# ifdef Q_ATOMIC_INT16_IS_SUPPORTED
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment16 )(short QT_INTERLOCKED_VOLATILE *);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement16 )(short QT_INTERLOCKED_VOLATILE *);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange16 )(short QT_INTERLOCKED_VOLATILE *, short, short);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange16 )(short QT_INTERLOCKED_VOLATILE *, short);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd16 )(short QT_INTERLOCKED_VOLATILE *, short);
-# endif
-# ifdef Q_ATOMIC_INT64_IS_SUPPORTED
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment64 )(__int64 QT_INTERLOCKED_VOLATILE *);
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement64 )(__int64 QT_INTERLOCKED_VOLATILE *);
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64, __int64);
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64);
- //above already: qint64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(qint64 QT_INTERLOCKED_VOLATILE *, qint64);
-# endif
-}
-
-#endif // QT_INTERLOCKED_DECLARE_PROTOTYPES
-
-#undef QT_INTERLOCKED_PROTOTYPE
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef QT_INTERLOCKED_INTRINSIC
-#undef QT_INTERLOCKED_INTRINSIC
-
-# pragma intrinsic (_InterlockedIncrement)
-# pragma intrinsic (_InterlockedDecrement)
-# pragma intrinsic (_InterlockedExchange)
-# pragma intrinsic (_InterlockedCompareExchange)
-# pragma intrinsic (_InterlockedExchangeAdd)
-
-# if !defined(_M_IX86)
-# pragma intrinsic (_InterlockedCompareExchangePointer)
-# pragma intrinsic (_InterlockedExchangePointer)
-# pragma intrinsic (_InterlockedExchangeAdd64)
-# endif
-
-#endif // QT_INTERLOCKED_INTRINSIC
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interlocked* replacement macros
-
-#if defined(__i386__) || defined(_M_IX86)
-
-# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
- reinterpret_cast<void *>( \
- QT_INTERLOCKED_FUNCTION(CompareExchange)( \
- reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
- long(newValue), \
- long(expectedValue)))
-
-# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
- QT_INTERLOCKED_FUNCTION(Exchange)( \
- reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
- long(newValue))
-
-# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
- QT_INTERLOCKED_FUNCTION(ExchangeAdd)( \
- reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
- (valueToAdd))
-
-#else // !defined(__i386__) && !defined(_M_IX86)
-
-# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
- QT_INTERLOCKED_FUNCTION(CompareExchangePointer)( \
- (void * QT_INTERLOCKED_VOLATILE *)(value), \
- (void *) (newValue), \
- (void *) (expectedValue))
-
-# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
- QT_INTERLOCKED_FUNCTION(ExchangePointer)( \
- (void * QT_INTERLOCKED_VOLATILE *)(value), \
- (void *) (newValue))
-
-# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
- QT_INTERLOCKED_FUNCTION(ExchangeAdd64)( \
- reinterpret_cast<qint64 QT_INTERLOCKED_VOLATILE *>(value), \
- (valueToAdd))
-
-#endif // !defined(__i386__) && !defined(_M_IX86)
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-QT_BEGIN_NAMESPACE
-
-#if 0
-// silence syncqt warnings
-QT_END_NAMESPACE
-#pragma qt_sync_skip_header_check
-#pragma qt_sync_stop_processing
-#endif
-
-#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_IS_SUPPORTED
-
-#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_WAIT_FREE
-
-#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
-
-#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
-
-#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
-
-#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
-# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_TEST_AND_SET_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE
-
-template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
-#endif
-
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
-# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_TEST_AND_SET_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE
-
-template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
-#endif
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-template <int N> struct QAtomicWindowsType { typedef typename QIntegerForSize<N>::Signed Type; };
-template <> struct QAtomicWindowsType<4> { typedef long Type; };
-
-
-template <int N> struct QAtomicOpsBySize : QGenericAtomicOps<QAtomicOpsBySize<N> >
-{
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return true; }
- template <typename T> static bool ref(T &_q_value) noexcept;
- template <typename T> static bool deref(T &_q_value) noexcept;
-
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return true; }
- template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept;
- template <typename T>
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return true; }
- template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return true; }
- template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept;
-
-private:
- typedef typename QAtomicWindowsType<N>::Type Type;
- template <typename T> static inline Type *atomic(T *t)
- { static_assert(sizeof(T) == sizeof(Type)); return reinterpret_cast<Type *>(t); }
- template <typename T> static inline Type value(T t)
- { static_assert(sizeof(T) == sizeof(Type)); return Type(t); }
-};
-
-template <typename T>
-struct QAtomicOps : QAtomicOpsBySize<sizeof(T)>
-{
- typedef T Type;
-};
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::ref(T &_q_value) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Increment)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::deref(T &_q_value) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Decrement)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
-}
-
-template<> template <typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
-{
- *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Exchange)(atomic(&_q_value), value(newValue));
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(ExchangeAdd)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
-}
-
-#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
-template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::ref(T &_q_value) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Increment16)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::deref(T &_q_value) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Decrement16)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
-}
-
-template<> template <typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
-{
- *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Exchange16)(atomic(&_q_value), value(newValue));
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(ExchangeAdd16)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
-}
-#endif
-
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
-template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::ref(T &_q_value) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Increment64)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::deref(T &_q_value) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Decrement64)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
-}
-
-template<> template <typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
-{
- *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(Exchange64)(atomic(&_q_value), value(newValue));
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
-{
- return QT_INTERLOCKED_FUNCTION(ExchangeAdd64)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
-}
-#endif
-
-// Specialization for pointer types, since we have Interlocked*Pointer() variants in some configurations
-template <typename T>
-struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
-{
- typedef T *Type;
-
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return true; }
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) noexcept;
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) noexcept;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return true; }
- static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) noexcept;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return true; }
- static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) noexcept;
-};
-
-template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) noexcept
-{
- return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue;
-}
-
-template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) noexcept
-{
- *currentValue = reinterpret_cast<T *>(QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template <typename T>
-inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) noexcept
-{
- return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
-}
-
-template <typename T>
-inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) noexcept
-{
- return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Cleanup
-
-#undef QT_INTERLOCKED_CONCAT_I
-#undef QT_INTERLOCKED_CONCAT
-#undef QT_INTERLOCKED_FUNCTION
-#undef QT_INTERLOCKED_PREFIX
-
-#undef QT_INTERLOCKED_VOLATILE
-
-#undef QT_INTERLOCKED_INCREMENT
-#undef QT_INTERLOCKED_DECREMENT
-#undef QT_INTERLOCKED_COMPARE_EXCHANGE
-#undef QT_INTERLOCKED_EXCHANGE
-#undef QT_INTERLOCKED_EXCHANGE_ADD
-#undef QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER
-#undef QT_INTERLOCKED_EXCHANGE_POINTER
-#undef QT_INTERLOCKED_EXCHANGE_ADD_POINTER
-
-QT_END_NAMESPACE
-#endif // QATOMIC_MSVC_H
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index 18da268270..6d061ea49a 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -1,65 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
+// Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBASICATOMIC_H
#define QBASICATOMIC_H
-#if defined(QT_BOOTSTRAPPED)
-# include <QtCore/qatomic_bootstrap.h>
-
-// If C++11 atomics are supported, use them!
-// Note that constexpr support is sometimes disabled in QNX or INTEGRITY builds,
-// but their libraries have <atomic>.
-#elif defined(Q_COMPILER_ATOMICS) && (defined(Q_COMPILER_CONSTEXPR) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY))
-# include <QtCore/qatomic_cxx11.h>
-
-// We only support one fallback: MSVC, because even on version 2015, it lacks full constexpr support
-#elif defined(Q_CC_MSVC)
-# include <QtCore/qatomic_msvc.h>
-
-// No fallback
-#else
-# error "Qt requires C++11 support"
-#endif
+#include <QtCore/qatomic_cxx11.h>
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4522)
@@ -73,19 +19,6 @@ QT_END_NAMESPACE
#pragma qt_sync_stop_processing
#endif
-// New atomics
-
-#if defined(Q_COMPILER_CONSTEXPR)
-# if defined(Q_CC_CLANG) && Q_CC_CLANG < 303
- /*
- Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for Clang before version 3.3.
- For details about the bug: see http://llvm.org/bugs/show_bug.cgi?id=12670
- */
-# else
-# define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
-# endif
-#endif
-
template <typename T>
class QBasicAtomicInteger
{
@@ -93,17 +26,13 @@ public:
typedef T Type;
typedef QAtomicOps<T> Ops;
// static check that this is a valid integer
- static_assert(QTypeInfo<T>::isIntegral, "template parameter is not an integral type");
+ static_assert(std::is_integral_v<T>, "template parameter is not an integral type");
static_assert(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform");
typename Ops::Type _q_value;
- // Everything below is either implemented in ../arch/qatomic_XXX.h or (as fallback) in qgenericatomic.h
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") T load() const noexcept { return loadRelaxed(); }
- QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(T newValue) noexcept { storeRelaxed(newValue); }
-#endif
-
+ // Everything below is either implemented in ../arch/qatomic_XXX.h or (as
+ // fallback) in qgenericatomic.h
T loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
void storeRelaxed(T newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
@@ -112,14 +41,14 @@ public:
operator T() const noexcept { return loadAcquire(); }
T operator=(T newValue) noexcept { storeRelease(newValue); return newValue; }
- static Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return Ops::isReferenceCountingNative(); }
- static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return Ops::isReferenceCountingWaitFree(); }
+ static constexpr bool isReferenceCountingNative() noexcept { return Ops::isReferenceCountingNative(); }
+ static constexpr bool isReferenceCountingWaitFree() noexcept { return Ops::isReferenceCountingWaitFree(); }
bool ref() noexcept { return Ops::ref(_q_value); }
bool deref() noexcept { return Ops::deref(_q_value); }
- static Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
+ static constexpr bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
+ static constexpr bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
bool testAndSetRelaxed(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
@@ -139,8 +68,8 @@ public:
bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
+ static constexpr bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
+ static constexpr bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
T fetchAndStoreRelaxed(T newValue) noexcept
{ return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
@@ -151,8 +80,8 @@ public:
T fetchAndStoreOrdered(T newValue) noexcept
{ return Ops::fetchAndStoreOrdered(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
+ static constexpr bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
+ static constexpr bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
T fetchAndAddRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
@@ -220,13 +149,11 @@ public:
{ return fetchAndXorOrdered(v) ^ v; }
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicInteger() = default;
constexpr QBasicAtomicInteger(T value) noexcept : _q_value(value) {}
QBasicAtomicInteger(const QBasicAtomicInteger &) = delete;
QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete;
QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete;
-#endif
};
typedef QBasicAtomicInteger<int> QBasicAtomicInt;
@@ -240,11 +167,6 @@ public:
AtomicType _q_value;
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") Type load() const noexcept { return loadRelaxed(); }
- QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(Type newValue) noexcept { storeRelaxed(newValue); }
-#endif
-
Type loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
void storeRelaxed(Type newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
@@ -255,8 +177,8 @@ public:
Type loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
void storeRelease(Type newValue) noexcept { Ops::storeRelease(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
+ static constexpr bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
+ static constexpr bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
bool testAndSetRelaxed(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
@@ -276,8 +198,8 @@ public:
bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
+ static constexpr bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
+ static constexpr bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
Type fetchAndStoreRelaxed(Type newValue) noexcept
{ return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
@@ -288,8 +210,8 @@ public:
Type fetchAndStoreOrdered(Type newValue) noexcept
{ return Ops::fetchAndStoreOrdered(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
+ static constexpr bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
+ static constexpr bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
Type fetchAndAddRelaxed(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
@@ -322,13 +244,11 @@ public:
Type operator-=(qptrdiff valueToSub) noexcept
{ return fetchAndSubOrdered(valueToSub) - valueToSub; }
-#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicPointer() = default;
constexpr QBasicAtomicPointer(Type value) noexcept : _q_value(value) {}
QBasicAtomicPointer(const QBasicAtomicPointer &) = delete;
QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete;
QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete;
-#endif
};
#ifndef Q_BASIC_ATOMIC_INITIALIZER
diff --git a/src/corelib/thread/qexception.cpp b/src/corelib/thread/qexception.cpp
index 2dc277523a..a623dc1c6e 100644
--- a/src/corelib/thread/qexception.cpp
+++ b/src/corelib/thread/qexception.cpp
@@ -1,46 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qexception.h"
#include "QtCore/qshareddata.h"
-#if !defined(QT_NO_EXCEPTIONS) || defined(Q_CLANG_QDOC)
+#if !defined(QT_NO_EXCEPTIONS) || defined(Q_QDOC)
QT_BEGIN_NAMESPACE
@@ -62,7 +26,7 @@ QT_BEGIN_NAMESPACE
\snippet code/src_corelib_thread_qexception.cpp 1
If you throw an exception that is not a subclass of QException,
- the Qt functions will throw a QUnhandledException
+ the \l{Qt Concurrent} functions will throw a QUnhandledException
in the receiver thread.
When using QFuture, transferred exceptions will be thrown when calling the following functions:
@@ -92,12 +56,18 @@ QT_BEGIN_NAMESPACE
\class QUnhandledException
\inmodule QtCore
- \brief The UnhandledException class represents an unhandled exception in a worker thread.
+ \brief The QUnhandledException class represents an unhandled exception in a
+ Qt Concurrent worker thread.
\since 5.0
If a worker thread throws an exception that is not a subclass of QException,
- the Qt functions will throw a QUnhandledException
- on the receiver thread side.
+ the \l{Qt Concurrent} functions will throw a QUnhandledException on the receiver
+ thread side. The information about the actual exception that has been thrown
+ will be saved in the QUnhandledException class and can be obtained using the
+ exception() method. For example, you can process the exception held by
+ QUnhandledException in the following way:
+
+ \snippet code/src_corelib_thread_qexception.cpp 4
Inheriting from this class is not supported.
*/
@@ -112,14 +82,8 @@ QT_BEGIN_NAMESPACE
\internal
*/
-QException::~QException()
-#ifdef Q_COMPILER_NOEXCEPT
- noexcept
-#else
- throw()
-#endif
+QException::~QException() noexcept
{
- // must stay empty until ### Qt 6
}
void QException::raise() const
@@ -133,14 +97,76 @@ QException *QException::clone() const
return new QException(*this);
}
-QUnhandledException::~QUnhandledException()
-#ifdef Q_COMPILER_NOEXCEPT
- noexcept
-#else
- throw()
-#endif
+class QUnhandledExceptionPrivate : public QSharedData
+{
+public:
+ QUnhandledExceptionPrivate(std::exception_ptr exception) noexcept : exceptionPtr(exception) { }
+ std::exception_ptr exceptionPtr;
+};
+
+/*!
+ \fn QUnhandledException::QUnhandledException(std::exception_ptr exception = nullptr) noexcept
+ \since 6.0
+
+ Constructs a new QUnhandledException object. Saves the pointer to the actual
+ exception object if \a exception is passed.
+
+ \sa exception()
+*/
+QUnhandledException::QUnhandledException(std::exception_ptr exception) noexcept
+ : d(new QUnhandledExceptionPrivate(exception))
+{
+}
+
+/*!
+ Move-constructs a QUnhandledException, making it point to the same
+ object as \a other was pointing to.
+*/
+QUnhandledException::QUnhandledException(QUnhandledException &&other) noexcept
+ : d(std::exchange(other.d, {}))
+{
+}
+
+/*!
+ Constructs a QUnhandledException object as a copy of \a other.
+*/
+QUnhandledException::QUnhandledException(const QUnhandledException &other) noexcept
+ : d(other.d)
+{
+}
+
+/*!
+ Assigns \a other to this QUnhandledException object and returns a reference
+ to this QUnhandledException object.
+*/
+QUnhandledException &QUnhandledException::operator=(const QUnhandledException &other) noexcept
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn void QUnhandledException::swap(QUnhandledException &other)
+ \since 6.0
+
+ Swaps this QUnhandledException with \a other. This function is very fast and
+ never fails.
+*/
+
+/*!
+ \since 6.0
+
+ Returns a \l{https://en.cppreference.com/w/cpp/error/exception_ptr}{pointer} to
+ the actual exception that has been saved in this QUnhandledException. Returns a
+ \c null pointer, if it does not point to an exception object.
+*/
+std::exception_ptr QUnhandledException::exception() const
+{
+ return d->exceptionPtr;
+}
+
+QUnhandledException::~QUnhandledException() noexcept
{
- // must stay empty until ### Qt 6
}
void QUnhandledException::raise() const
@@ -154,7 +180,7 @@ QUnhandledException *QUnhandledException::clone() const
return new QUnhandledException(*this);
}
-#if !defined(Q_CLANG_QDOC)
+#if !defined(Q_QDOC)
namespace QtPrivate {
@@ -190,9 +216,15 @@ void ExceptionStore::throwPossibleException()
std::rethrow_exception(exceptionHolder);
}
+void ExceptionStore::rethrowException() const
+{
+ Q_ASSERT(hasException());
+ std::rethrow_exception(exceptionHolder);
+}
+
} // namespace QtPrivate
-#endif //Q_CLANG_QDOC
+#endif //Q_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qexception.h b/src/corelib/thread/qexception.h
index b117d90caf..62b9e70bea 100644
--- a/src/corelib/thread/qexception.h
+++ b/src/corelib/thread/qexception.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTCORE_QEXCEPTION_H
#define QTCORE_QEXCEPTION_H
@@ -52,34 +16,38 @@ QT_REQUIRE_CONFIG(future);
QT_BEGIN_NAMESPACE
-#if !defined(QT_NO_EXCEPTIONS) || defined(Q_CLANG_QDOC)
+#if !defined(QT_NO_EXCEPTIONS) || defined(Q_QDOC)
class Q_CORE_EXPORT QException : public std::exception
{
public:
- ~QException()
-#ifdef Q_COMPILER_NOEXCEPT
- noexcept
-#else
- throw()
-#endif
- ;
+ ~QException() noexcept;
virtual void raise() const;
virtual QException *clone() const;
};
-class Q_CORE_EXPORT QUnhandledException : public QException
+class QUnhandledExceptionPrivate;
+class Q_CORE_EXPORT QUnhandledException final : public QException
{
public:
- ~QUnhandledException()
-#ifdef Q_COMPILER_NOEXCEPT
- noexcept
-#else
- throw()
-#endif
- ;
+ QUnhandledException(std::exception_ptr exception = nullptr) noexcept;
+ ~QUnhandledException() noexcept override;
+
+ QUnhandledException(QUnhandledException &&other) noexcept;
+ QUnhandledException(const QUnhandledException &other) noexcept;
+
+ void swap(QUnhandledException &other) noexcept { d.swap(other.d); }
+
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QUnhandledException)
+ QUnhandledException &operator=(const QUnhandledException &other) noexcept;
+
void raise() const override;
QUnhandledException *clone() const override;
+
+ std::exception_ptr exception() const;
+
+private:
+ QSharedDataPointer<QUnhandledExceptionPrivate> d;
};
namespace QtPrivate {
@@ -92,6 +60,7 @@ public:
bool hasException() const;
std::exception_ptr exception() const;
void throwPossibleException();
+ Q_NORETURN void rethrowException() const;
std::exception_ptr exceptionHolder;
};
@@ -106,6 +75,7 @@ class Q_CORE_EXPORT ExceptionStore
public:
ExceptionStore() { }
inline void throwPossibleException() {}
+ inline void rethrowException() const { }
};
} // namespace QtPrivate
diff --git a/src/corelib/thread/qfutex_freebsd_p.h b/src/corelib/thread/qfutex_freebsd_p.h
new file mode 100644
index 0000000000..b31774d28d
--- /dev/null
+++ b/src/corelib/thread/qfutex_freebsd_p.h
@@ -0,0 +1,82 @@
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFUTEX_FREEBSD_P_H
+#define QFUTEX_FREEBSD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qcore_unix_p.h>
+#include <qdeadlinetimer.h>
+
+// https://man.freebsd.org/cgi/man.cgi?query=_umtx_op
+#include <sys/umtx.h>
+
+#define QT_ALWAYS_USE_FUTEX
+
+QT_BEGIN_NAMESPACE
+
+namespace QtFreeBSDFutex {
+constexpr inline bool futexAvailable() { return true; }
+
+template <typename Atomic>
+inline int do_wait(Atomic &futex, typename Atomic::Type expectedValue, _umtx_time *tmp = nullptr)
+{
+ // FreeBSD UMTX_OP_WAIT does not apply acquire or release memory barriers,
+ // so there are no QtTsan calls here.
+
+ int op = UMTX_OP_WAIT_UINT_PRIVATE;
+ if (sizeof(futex) > sizeof(quint32))
+ op = UMTX_OP_WAIT; // no _PRIVATE version
+
+ // The timeout is passed in uaddr2, with its size in uaddr
+ void *uaddr = reinterpret_cast<void *>(tmp ? sizeof(*tmp) : 0);
+ void *uaddr2 = tmp;
+ int ret = _umtx_op(&futex, op, u_long(expectedValue), uaddr, uaddr2);
+
+ return ret;
+}
+
+template <typename Atomic>
+inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
+{
+ do_wait(futex, expectedValue);
+}
+
+template <typename Atomic>
+inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
+{
+ struct _umtx_time tm = {};
+ auto deadline = timer.deadline<std::chrono::steady_clock>();
+ tm._timeout = durationToTimespec(deadline.time_since_epoch());
+ tm._flags = UMTX_ABSTIME;
+ tm._clockid = CLOCK_MONOTONIC;
+ int r = do_wait(futex, expectedValue, &tm);
+ return r == 0 || errno != ETIMEDOUT;
+}
+
+template <typename Atomic> inline void futexWakeOne(Atomic &futex)
+{
+ _umtx_op(&futex, UMTX_OP_WAKE_PRIVATE, 1, nullptr, nullptr);
+}
+
+template <typename Atomic> inline void futexWakeAll(Atomic &futex)
+{
+ _umtx_op(&futex, UMTX_OP_WAKE_PRIVATE, INT_MAX, nullptr, nullptr);
+}
+} //namespace QtFreeBSDFutex
+
+namespace QtFutex = QtFreeBSDFutex;
+
+QT_END_NAMESPACE
+
+#endif // QFUTEX_FREEBSD_P_H
diff --git a/src/corelib/thread/qfutex_linux_p.h b/src/corelib/thread/qfutex_linux_p.h
new file mode 100644
index 0000000000..e114dfca72
--- /dev/null
+++ b/src/corelib/thread/qfutex_linux_p.h
@@ -0,0 +1,95 @@
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFUTEX_LINUX_P_H
+#define QFUTEX_LINUX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qcore_unix_p.h>
+#include <qdeadlinetimer.h>
+#include <qtsan_impl.h>
+
+#include <asm/unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+// RISC-V does not supply __NR_futex
+#ifndef __NR_futex
+# define __NR_futex __NR_futex_time64
+#endif
+
+#define QT_ALWAYS_USE_FUTEX
+
+QT_BEGIN_NAMESPACE
+
+namespace QtLinuxFutex {
+constexpr inline bool futexAvailable() { return true; }
+
+inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
+ int *addr2 = nullptr, int val3 = 0) noexcept
+{
+ QtTsan::futexRelease(addr, addr2);
+
+ // we use __NR_futex because some libcs (like Android's bionic) don't
+ // provide SYS_futex etc.
+ int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
+
+ QtTsan::futexAcquire(addr, addr2);
+
+ return result;
+}
+template <typename T> int *addr(T *ptr)
+{
+ int *int_addr = reinterpret_cast<int *>(ptr);
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ if (sizeof(T) > sizeof(int))
+ int_addr++; //We want a pointer to the least significant half
+#endif
+ return int_addr;
+}
+
+template <typename Atomic>
+inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
+{
+ _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue));
+}
+template <typename Atomic>
+inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer deadline)
+{
+ auto timeout = deadline.deadline<std::chrono::steady_clock>().time_since_epoch();
+ struct timespec ts = durationToTimespec(timeout);
+ int r = _q_futex(addr(&futex), FUTEX_WAIT_BITSET, qintptr(expectedValue), quintptr(&ts),
+ nullptr, FUTEX_BITSET_MATCH_ANY);
+ return r == 0 || errno != ETIMEDOUT;
+}
+template <typename Atomic> inline void futexWakeOne(Atomic &futex)
+{
+ _q_futex(addr(&futex), FUTEX_WAKE, 1);
+}
+template <typename Atomic> inline void futexWakeAll(Atomic &futex)
+{
+ _q_futex(addr(&futex), FUTEX_WAKE, INT_MAX);
+}
+template <typename Atomic> inline
+void futexWakeOp(Atomic &futex1, int wake1, int wake2, Atomic &futex2, quint32 op)
+{
+ _q_futex(addr(&futex1), FUTEX_WAKE_OP, wake1, wake2, addr(&futex2), op);
+}} // namespace QtLinuxFutex
+namespace QtFutex = QtLinuxFutex;
+
+QT_END_NAMESPACE
+
+#endif // QFUTEX_LINUX_P_H
diff --git a/src/corelib/thread/qfutex_mac_p.h b/src/corelib/thread/qfutex_mac_p.h
new file mode 100644
index 0000000000..0de08954ab
--- /dev/null
+++ b/src/corelib/thread/qfutex_mac_p.h
@@ -0,0 +1,140 @@
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFUTEX_MAC_P_H
+#define QFUTEX_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qdeadlinetimer.h>
+#include <qtsan_impl.h>
+#include <private/qglobal_p.h>
+
+// The Darwin kernel exposes a set of __ulock_{wait,wait2,wake} APIs in
+// https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.81.2/bsd/sys/ulock.h,
+// but these APIs are marked as private, so we cannot rely on them being
+// stable, nor we can use these APIs in builds of Qt intended for
+// the Apple App Store. By wholesale disabling the use of the APIs
+// in App Store compliant builds, and runtime checking availability
+// of the APIs when we do build them in, we should be safe, unless
+// the semantics of the APIs change in ways we haven't accounted for,
+// but that's a risk we're willing to take.
+
+#if QT_CONFIG(appstore_compliant)
+QT_BEGIN_NAMESPACE
+namespace QtFutex = QtDummyFutex;
+QT_END_NAMESPACE
+#else
+
+extern "C" {
+// -------- BEGIN OS Declarations --------
+// Source: https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.81.2/bsd/sys/ulock.h
+// Modification: added __attribute((__weak__))
+// Copyright (c) 2015 Apple Inc. All rights reserved.
+
+__attribute((__weak__))
+extern int __ulock_wait2(uint32_t operation, void *addr, uint64_t value,
+ uint64_t timeout, uint64_t value2);
+__attribute((__weak__))
+extern int __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value);
+
+/*
+ * operation bits [7, 0] contain the operation code.
+ */
+#define UL_COMPARE_AND_WAIT 1
+#define UL_COMPARE_AND_WAIT_SHARED 3
+#define UL_COMPARE_AND_WAIT64 5
+#define UL_COMPARE_AND_WAIT64_SHARED 6
+
+/*
+ * operation bits [15, 8] contain the flags for __ulock_wake
+ */
+#define ULF_WAKE_ALL 0x00000100
+#define ULF_WAKE_THREAD 0x00000200
+#define ULF_WAKE_ALLOW_NON_OWNER 0x00000400
+
+/*
+ * operation bits [15, 8] contain the flags for __ulock_wake
+ */
+#define ULF_WAKE_ALL 0x00000100
+#define ULF_WAKE_THREAD 0x00000200
+#define ULF_WAKE_ALLOW_NON_OWNER 0x00000400
+
+/*
+ * operation bits [31, 24] contain the generic flags
+ */
+#define ULF_NO_ERRNO 0x01000000
+
+// -------- END OS Declarations --------
+} // extern "C"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtDarwinFutex {
+
+/*not constexpr*/ inline bool futexAvailable() { return __ulock_wake && __ulock_wait2; }
+
+template <typename Atomic>
+inline uint32_t baseOperation(Atomic &)
+{
+ static_assert(sizeof(Atomic) >= sizeof(quint32), "Can only operate on 32- or 64-bit atomics");
+
+ uint32_t operation = ULF_NO_ERRNO;
+ if (sizeof(Atomic) == sizeof(quint32))
+ operation |= UL_COMPARE_AND_WAIT;
+ else
+ operation |= UL_COMPARE_AND_WAIT64;
+ return operation;
+}
+
+template <typename Atomic> inline int
+do_wait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
+{
+ // source code inspection shows __ulock_wait2 uses nanoseconds for timeout
+ QtTsan::futexRelease(&futex);
+ int ret = __ulock_wait2(baseOperation(futex), &futex, uint64_t(expectedValue),
+ timer.remainingTimeNSecs(), 0);
+ QtTsan::futexAcquire(&futex);
+ return ret;
+}
+
+template <typename Atomic>
+inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
+{
+ do_wait(futex, expectedValue, {});
+}
+
+template <typename Atomic>
+inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
+{
+ int r = do_wait(futex, expectedValue, timer);
+ return r == 0 || r != -ETIMEDOUT;
+}
+
+template <typename Atomic> inline void futexWakeAll(Atomic &futex)
+{
+ __ulock_wake(baseOperation(futex) | ULF_WAKE_ALL, &futex, 0);
+}
+
+template <typename Atomic> inline void futexWakeOne(Atomic &futex)
+{
+ __ulock_wake(baseOperation(futex), &futex, 0);
+}
+} //namespace QtDarwinMutex
+
+namespace QtFutex = QtDarwinFutex;
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(appstore_compliant)
+
+#endif // QFUTEX_MAC_P_H
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
index f287b752d7..8ba798f920 100644
--- a/src/corelib/thread/qfutex_p.h
+++ b/src/corelib/thread/qfutex_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTEX_P_H
#define QFUTEX_P_H
@@ -51,15 +15,16 @@
// We mean it.
//
-#include <qglobal.h>
+#include <qdeadlinetimer.h>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
namespace QtDummyFutex {
- Q_DECL_CONSTEXPR inline bool futexAvailable() { return false; }
+ constexpr inline bool futexAvailable() { return false; }
template <typename Atomic>
- inline bool futexWait(Atomic &, typename Atomic::Type, int = 0)
- { Q_UNREACHABLE(); return false; }
+ inline bool futexWait(Atomic &, typename Atomic::Type, QDeadlineTimer = {})
+ { Q_UNREACHABLE_RETURN(false); }
template <typename Atomic> inline void futexWakeOne(Atomic &)
{ Q_UNREACHABLE(); }
template <typename Atomic> inline void futexWakeAll(Atomic &)
@@ -68,100 +33,16 @@ namespace QtDummyFutex {
QT_END_NAMESPACE
-#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
+#if defined(Q_OS_DARWIN)
+# include "qfutex_mac_p.h"
+#elif defined(Q_OS_FREEBSD)
+# include "qfutex_freebsd_p.h"
+#elif defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
// use Linux mutexes everywhere except for LSB builds
-# include <sys/syscall.h>
-# include <errno.h>
-# include <limits.h>
-# include <unistd.h>
-# include <asm/unistd.h>
-# include <linux/futex.h>
-# define QT_ALWAYS_USE_FUTEX
-
-// if not defined in linux/futex.h
-# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
-
-# if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
-# include <sanitizer/tsan_interface.h>
-inline void _q_tsan_acquire(void *addr, void *addr2)
-{
- __tsan_acquire(addr);
- if (addr2)
- __tsan_acquire(addr2);
-}
-inline void _q_tsan_release(void *addr, void *addr2)
-{
- if (addr2)
- __tsan_release(addr2);
- __tsan_release(addr);
-}
-# else
-inline void _q_tsan_acquire(void *, void *) {}
-inline void _q_tsan_release(void *, void *) {}
-# endif // __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
-
-QT_BEGIN_NAMESPACE
-namespace QtLinuxFutex {
- constexpr inline bool futexAvailable() { return true; }
- inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
- int *addr2 = nullptr, int val3 = 0) noexcept
- {
- // A futex call ensures total ordering on the futex words
- // (in either success or failure of the call). Instruct TSAN accordingly,
- // as TSAN does not understand the futex(2) syscall.
- _q_tsan_release(addr, addr2);
-
- // we use __NR_futex because some libcs (like Android's bionic) don't
- // provide SYS_futex etc.
- int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
-
- _q_tsan_acquire(addr, addr2);
-
- return result;
- }
- template <typename T> int *addr(T *ptr)
- {
- int *int_addr = reinterpret_cast<int *>(ptr);
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- if (sizeof(T) > sizeof(int))
- int_addr++; //We want a pointer to the least significant half
-#endif
- return int_addr;
- }
-
- template <typename Atomic>
- inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
- {
- _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue));
- }
- template <typename Atomic>
- inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, qint64 nstimeout)
- {
- struct timespec ts;
- ts.tv_sec = nstimeout / 1000 / 1000 / 1000;
- ts.tv_nsec = nstimeout % (1000 * 1000 * 1000);
- int r = _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue), quintptr(&ts));
- return r == 0 || errno != ETIMEDOUT;
- }
- template <typename Atomic> inline void futexWakeOne(Atomic &futex)
- {
- _q_futex(addr(&futex), FUTEX_WAKE, 1);
- }
- template <typename Atomic> inline void futexWakeAll(Atomic &futex)
- {
- _q_futex(addr(&futex), FUTEX_WAKE, INT_MAX);
- }
- template <typename Atomic> inline
- void futexWakeOp(Atomic &futex1, int wake1, int wake2, Atomic &futex2, quint32 op)
- {
- _q_futex(addr(&futex1), FUTEX_WAKE_OP, wake1, wake2, addr(&futex2), op);
- }
-}
-namespace QtFutex = QtLinuxFutex;
-QT_END_NAMESPACE
-
+# include "qfutex_linux_p.h"
+#elif defined(Q_OS_WIN)
+# include "qfutex_win_p.h"
#else
-
QT_BEGIN_NAMESPACE
namespace QtFutex = QtDummyFutex;
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfutex_win_p.h b/src/corelib/thread/qfutex_win_p.h
new file mode 100644
index 0000000000..75a12bd82c
--- /dev/null
+++ b/src/corelib/thread/qfutex_win_p.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QFUTEX_WIN_P_H
+#define QFUTEX_WIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qglobal_p.h>
+#include <qdeadlinetimer.h>
+#include <qtsan_impl.h>
+
+#include <qt_windows.h>
+
+#define QT_ALWAYS_USE_FUTEX
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWindowsFutex {
+constexpr inline bool futexAvailable() { return true; }
+
+template <typename Atomic>
+inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
+{
+ QtTsan::futexRelease(&futex);
+ WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), INFINITE);
+ QtTsan::futexAcquire(&futex);
+}
+template <typename Atomic>
+inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer deadline)
+{
+ using namespace std::chrono;
+ BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(deadline.remainingTime()));
+ return r || GetLastError() != ERROR_TIMEOUT;
+}
+template <typename Atomic> inline void futexWakeAll(Atomic &futex)
+{
+ WakeByAddressAll(&futex);
+}
+template <typename Atomic> inline void futexWakeOne(Atomic &futex)
+{
+ WakeByAddressSingle(&futex);
+}
+} // namespace QtWindowsFutex
+namespace QtFutex = QtWindowsFutex;
+
+QT_END_NAMESPACE
+
+#endif // QFUTEX_WIN_P_H
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h
index dc8e0d1d2d..3945df066a 100644
--- a/src/corelib/thread/qfuture.h
+++ b/src/corelib/thread/qfuture.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTURE_H
#define QFUTURE_H
@@ -43,12 +7,12 @@
#include <QtCore/qglobal.h>
#include <QtCore/qfutureinterface.h>
+#include <QtCore/qmetatype.h>
#include <QtCore/qstring.h>
#include <QtCore/qfuture_impl.h>
#include <type_traits>
-#include <vector>
QT_REQUIRE_CONFIG(future);
@@ -60,10 +24,9 @@ class QFutureWatcher;
template <typename T>
class QFuture
{
- static_assert (std::is_copy_constructible_v<T>
- || std::is_move_constructible_v<T>
+ static_assert (std::is_move_constructible_v<T>
|| std::is_same_v<T, void>,
- "Type with copy or move constructors or type void is required");
+ "A move-constructible type or type void is required");
public:
QFuture()
: d(QFutureInterface<T>::canceledResult())
@@ -80,9 +43,8 @@ public:
{
}
-#if !defined(Q_CC_XLC)
template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
- QFuture(const QFuture<U> &other) : d(other.d)
+ explicit QFuture(const QFuture<U> &other) : d(other.d)
{
}
@@ -92,20 +54,13 @@ public:
d = other.d;
return *this;
}
-#endif
-#if defined(Q_CLANG_QDOC)
+#if defined(Q_QDOC)
~QFuture() { }
QFuture(const QFuture<T> &) { }
QFuture<T> & operator=(const QFuture<T> &) { }
-
- // This is required to allow QDoc to find the declaration of operator T().
- operator T() const;
#endif
- bool operator==(const QFuture &other) const { return (d == other.d); }
- bool operator!=(const QFuture &other) const { return (d != other.d); }
-
void cancel() { d.cancel(); }
bool isCanceled() const { return d.isCanceled(); }
@@ -155,18 +110,17 @@ QT_WARNING_POP
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
- // operator T()
- template<typename U = T>
- operator typename std::enable_if_t<!std::is_same_v<U, void>, U>() const { return result(); }
-
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
QList<T> results() const { return d.results(); }
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
T takeResult() { return d.takeResult(); }
+#if 0
+ // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
std::vector<T> takeResults() { return d.takeResults(); }
+#endif
bool isValid() const { return d.isValid(); }
@@ -182,15 +136,33 @@ QT_WARNING_POP
template<class Function>
QFuture<ResultType<Function>> then(QThreadPool *pool, Function &&function);
+ template<class Function>
+ QFuture<ResultType<Function>> then(QObject *context, Function &&function);
+
#ifndef QT_NO_EXCEPTIONS
template<class Function,
typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
QFuture<T> onFailed(Function &&handler);
+
+ template<class Function,
+ typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
+ QFuture<T> onFailed(QObject *context, Function &&handler);
#endif
template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
QFuture<T> onCanceled(Function &&handler);
+ template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
+ QFuture<T> onCanceled(QObject *context, Function &&handler);
+
+#if !defined(Q_QDOC)
+ template<class U = T, typename = std::enable_if_t<QtPrivate::isQFutureV<U>>>
+ auto unwrap();
+#else
+ template<class U>
+ QFuture<U> unwrap();
+#endif
+
class const_iterator
{
public:
@@ -211,8 +183,6 @@ QT_WARNING_POP
{ future = o.future; index = o.index; return *this; }
inline const T &operator*() const { return future->d.resultReference(index); }
inline const T *operator->() const { return future->d.resultPointer(index); }
- inline bool operator!=(const const_iterator &other) const { return index != other.index; }
- inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
inline const_iterator &operator++()
{ index = advanceIndex(index, 1); return *this; }
inline const_iterator &operator--()
@@ -241,6 +211,12 @@ QT_WARNING_POP
{ return const_iterator(k.future, k.advanceIndex(k.index, j)); }
private:
+ friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return lhs.index == rhs.index;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(const_iterator)
+
/*! \internal
Advances the iterator index \a idx \a n steps, waits for the
@@ -301,6 +277,8 @@ private:
template<class U>
friend class QFuture;
+ friend class QFutureInterfaceBase;
+
template<class Function, class ResultType, class ParentResultType>
friend class QtPrivate::Continuation;
@@ -312,6 +290,11 @@ private:
friend class QtPrivate::FailureHandler;
#endif
+ template<typename ResultType>
+ friend struct QtPrivate::WhenAnyContext;
+
+ friend struct QtPrivate::UnwrapHandler;
+
using QFuturePrivate =
std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>;
@@ -356,7 +339,7 @@ QFuture<typename QFuture<T>::template ResultType<Function>>
QFuture<T>::then(QtFuture::Launch policy, Function &&function)
{
QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
- QtPrivate::Continuation<Function, ResultType<Function>, T>::create(
+ QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
std::forward<Function>(function), this, promise, policy);
return promise.future();
}
@@ -367,19 +350,40 @@ QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QTh
Function &&function)
{
QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
- QtPrivate::Continuation<Function, ResultType<Function>, T>::create(
+ QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
std::forward<Function>(function), this, promise, pool);
return promise.future();
}
-#ifndef QT_NO_EXCEPTIONS
+template<class T>
+template<class Function>
+QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QObject *context,
+ Function &&function)
+{
+ QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
+ QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
+ std::forward<Function>(function), this, promise, context);
+ return promise.future();
+}
+#ifndef QT_NO_EXCEPTIONS
template<class T>
template<class Function, typename>
QFuture<T> QFuture<T>::onFailed(Function &&handler)
{
QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
- QtPrivate::FailureHandler<Function, T>::create(std::forward<Function>(handler), this, promise);
+ QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
+ this, promise);
+ return promise.future();
+}
+
+template<class T>
+template<class Function, typename>
+QFuture<T> QFuture<T>::onFailed(QObject *context, Function &&handler)
+{
+ QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
+ QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
+ this, promise, context);
return promise.future();
}
@@ -390,23 +394,157 @@ template<class Function, typename>
QFuture<T> QFuture<T>::onCanceled(Function &&handler)
{
QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
- QtPrivate::CanceledHandler<Function, T>::create(std::forward<Function>(handler), this, promise);
+ QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
+ this, promise);
return promise.future();
}
+template<class T>
+template<class Function, typename>
+QFuture<T> QFuture<T>::onCanceled(QObject *context, Function &&handler)
+{
+ QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
+ QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
+ this, promise, context);
+ return promise.future();
+}
+
+template<class T>
+template<class U, typename>
+auto QFuture<T>::unwrap()
+{
+ if constexpr (QtPrivate::isQFutureV<typename QtPrivate::Future<T>::type>)
+ return QtPrivate::UnwrapHandler::unwrapImpl(this).unwrap();
+ else
+ return QtPrivate::UnwrapHandler::unwrapImpl(this);
+}
+
inline QFuture<void> QFutureInterface<void>::future()
{
return QFuture<void>(this);
}
-template <typename T>
-QFuture<void> qToVoidFuture(const QFuture<T> &future)
+template<typename T>
+QFutureInterfaceBase QFutureInterfaceBase::get(const QFuture<T> &future)
{
- return QFuture<void>(future.d);
+ return future.d;
}
+namespace QtPrivate
+{
+
+template<typename T>
+struct MetaTypeQFutureHelper<QFuture<T>>
+{
+ static bool registerConverter() {
+ if constexpr (std::is_same_v<T, void>)
+ return false;
+
+ return QMetaType::registerConverter<QFuture<T>, QFuture<void>>(
+ [](const QFuture<T> &future) { return QFuture<void>(future); });
+ }
+};
+
+} // namespace QtPrivate
+
+namespace QtFuture {
+
+#ifndef Q_QDOC
+
+template<typename OutputSequence, typename InputIt,
+ typename ValueType = typename std::iterator_traits<InputIt>::value_type,
+ std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
+ QtPrivate::IsRandomAccessible<OutputSequence>,
+ QtPrivate::isQFuture<ValueType>>,
+ int> = 0>
+QFuture<OutputSequence> whenAll(InputIt first, InputIt last)
+{
+ return QtPrivate::whenAllImpl<OutputSequence, InputIt, ValueType>(first, last);
+}
+
+template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
+ std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
+ QtPrivate::isQFuture<ValueType>>,
+ int> = 0>
+QFuture<QList<ValueType>> whenAll(InputIt first, InputIt last)
+{
+ return QtPrivate::whenAllImpl<QList<ValueType>, InputIt, ValueType>(first, last);
+}
+
+template<typename OutputSequence, typename... Futures,
+ std::enable_if_t<std::conjunction_v<QtPrivate::IsRandomAccessible<OutputSequence>,
+ QtPrivate::NotEmpty<Futures...>,
+ QtPrivate::isQFuture<std::decay_t<Futures>>...>,
+ int> = 0>
+QFuture<OutputSequence> whenAll(Futures &&... futures)
+{
+ return QtPrivate::whenAllImpl<OutputSequence, Futures...>(std::forward<Futures>(futures)...);
+}
+
+template<typename... Futures,
+ std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
+ QtPrivate::isQFuture<std::decay_t<Futures>>...>,
+ int> = 0>
+QFuture<QList<std::variant<std::decay_t<Futures>...>>> whenAll(Futures &&... futures)
+{
+ return QtPrivate::whenAllImpl<QList<std::variant<std::decay_t<Futures>...>>, Futures...>(
+ std::forward<Futures>(futures)...);
+}
+
+template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
+ std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
+ QtPrivate::isQFuture<ValueType>>,
+ int> = 0>
+QFuture<WhenAnyResult<typename QtPrivate::Future<ValueType>::type>> whenAny(InputIt first,
+ InputIt last)
+{
+ return QtPrivate::whenAnyImpl<InputIt, ValueType>(first, last);
+}
+
+template<typename... Futures,
+ std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
+ QtPrivate::isQFuture<std::decay_t<Futures>>...>,
+ int> = 0>
+QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures)
+{
+ return QtPrivate::whenAnyImpl(std::forward<Futures>(futures)...);
+}
+
+#else
+
+template<typename OutputSequence, typename InputIt>
+QFuture<OutputSequence> whenAll(InputIt first, InputIt last);
+
+template<typename OutputSequence, typename... Futures>
+QFuture<OutputSequence> whenAll(Futures &&... futures);
+
+template<typename T, typename InputIt>
+QFuture<QtFuture::WhenAnyResult<T>> whenAny(InputIt first, InputIt last);
+
+template<typename... Futures>
+QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures);
+
+#endif // Q_QDOC
+
+#if QT_DEPRECATED_SINCE(6, 10)
+#if defined(Q_QDOC)
+static QFuture<void> makeReadyFuture()
+#else
+template<typename T = void>
+QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyVoidFuture() instead.")
+static QFuture<T> makeReadyFuture()
+#endif
+{
+ return makeReadyVoidFuture();
+}
+#endif // QT_DEPRECATED_SINCE(6, 10)
+
+} // namespace QtFuture
+
Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
QT_END_NAMESPACE
+Q_DECLARE_METATYPE_TEMPLATE_1ARG(QFuture)
+
#endif // QFUTURE_H
diff --git a/src/corelib/thread/qfuture.qdoc b/src/corelib/thread/qfuture.qdoc
index b20875c423..b278d39882 100644
--- a/src/corelib/thread/qfuture.qdoc
+++ b/src/corelib/thread/qfuture.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \class QFuture
\inmodule QtCore
@@ -33,21 +9,18 @@
\ingroup thread
- To start a computation, use one of the APIs in the \l {Qt Concurrent} framework.
-
QFuture allows threads to be synchronized against one or more results
which will be ready at a later point in time. The result can be of any type
that has default, copy and possibly move constructors. If
a result is not available at the time of calling the result(), resultAt(),
- results(), takeResult(), or takeResults() functions, QFuture
- will wait until the result becomes available. You can use the isResultReadyAt()
- function to determine if a result is ready or not. For QFuture objects that
- report more than one result, the resultCount() function returns the number
- of continuous results. This means that it is always safe to iterate through
- the results from 0 to resultCount(). takeResult() and takeResults()
- invalidate a future and any subsequent attempt to access result or results
- from the future leads to undefined behavior. isValid() tells you if
- results can be accessed.
+ results() and takeResult() functions, QFuture will wait until the result
+ becomes available. You can use the isResultReadyAt() function to determine
+ if a result is ready or not. For QFuture objects that report more than one
+ result, the resultCount() function returns the number of continuous results.
+ This means that it is always safe to iterate through the results from 0 to
+ resultCount(). takeResult() invalidates a future, and any subsequent attempt
+ to access result or results from the future leads to undefined behavior.
+ isValid() tells you if results can be accessed.
QFuture provides a \l{Java-style iterators}{Java-style iterator}
(QFutureIterator) and an \l{STL-style iterators}{STL-style iterator}
@@ -68,7 +41,7 @@
using exceptions. Let's say we want to send a network request to obtain a large
file from a network location. Then we want to write it to the file system and
return its location in case of a success. Both of these operations may fail
- with different errors. So, we use std::variant to keep the result
+ with different errors. So, we use \c std::variant to keep the result
or error:
\snippet code/src_corelib_thread_qfuture.cpp 3
@@ -78,13 +51,13 @@
\snippet code/src_corelib_thread_qfuture.cpp 4
It's possible to chain multiple continuations and handlers in any order.
- The first handler that can handle the state of its parent is invoked first.
- If there's no proper handler, the state is propagated to the next continuation
- or handler. For example:
+ For example:
\snippet code/src_corelib_thread_qfuture.cpp 15
- If \c testFuture is successfully fulfilled \c {Block 1} will be called. If
+ Depending on the state of \c testFuture (canceled, has exception or has a
+ result), the next onCanceled(), onFailed() or then() will be called. So
+ if \c testFuture is successfully fulfilled, \c {Block 1} will be called. If
it succeeds as well, the next then() (\c {Block 4}) is called. If \c testFuture
gets canceled or fails with an exception, either \c {Block 2} or \c {Block 3}
will be called respectively. The next then() will be called afterwards, and the
@@ -102,7 +75,16 @@
If \c testFuture gets canceled, its state is propagated to the next then(),
which will be also canceled. So in this case \c {Block 6} will be called.
- QFuture also offers ways to interact with a runnning computation. For
+ The future can have only one continuation. Consider the following example:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 31
+
+ In this case \c f1 and \c f2 are effectively the same QFuture object, as
+ they share the same internal state. As a result, calling
+ \l {QFuture::}{then} on \c f2 will overwrite the continuation specified for
+ \c {f1}. So, only \c {"second"} will be printed when this code is executed.
+
+ QFuture also offers ways to interact with a running computation. For
instance, the computation can be canceled with the cancel() function. To
suspend or resume the computation, use the setSuspended() function or one of
the suspend(), resume(), or toggleSuspended() convenience functions. Be aware
@@ -119,9 +101,6 @@
the isCanceled(), isStarted(), isFinished(), isRunning(), isSuspending()
or isSuspended() functions.
- QFuture is a lightweight reference counted class that can be passed by
- value.
-
QFuture<void> is specialized to not contain any of the result fetching
functions. Any QFuture<T> can be assigned or copied into a QFuture<void>
as well. This is useful if only status or progress information is needed
@@ -129,13 +108,32 @@
To interact with running tasks using signals and slots, use QFutureWatcher.
- You can also use QtFuture::connect to connect signals to a QFuture object
+ You can also use QtFuture::connect() to connect signals to a QFuture object
which will be resolved when a signal is emitted. This allows working with
signals like with QFuture objects. For example, if you combine it with then(),
you can attach multiple continuations to a signal, which are invoked in the
same thread or a new thread.
- \sa QtFuture::connect(), QFutureWatcher, {Qt Concurrent}
+ The QtFuture::whenAll() and QtFuture::whenAny() functions can be used to
+ combine several futures and track when the last or first of them completes.
+
+ A ready QFuture object with a value or a QFuture object holding exception can
+ be created using convenience functions QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(), and
+ QtFuture::makeExceptionalFuture().
+
+ \note Some APIs (see \l {QFuture::then()} or various QtConcurrent method
+ overloads) allow scheduling the computation to a specific thread pool.
+ However, QFuture implements a work-stealing algorithm to prevent deadlocks
+ and optimize thread usage. As a result, computations can be executed
+ directly in the thread which requests the QFuture's result.
+
+ \note To start a computation and store results in a QFuture, use QPromise or
+ one of the APIs in the \l {Qt Concurrent} framework.
+
+ \sa QPromise, QtFuture::connect(), QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(),
+ QtFuture::makeExceptionalFuture(), QFutureWatcher, {Qt Concurrent}
*/
/*! \fn template <typename T> QFuture<T>::QFuture()
@@ -168,22 +166,11 @@
Assigns \a other to this future and returns a reference to this future.
*/
-/*! \fn template <typename T> bool QFuture<T>::operator==(const QFuture &other) const
-
- Returns \c true if \a other is a copy of this future; otherwise returns \c false.
-*/
-
-/*! \fn template <typename T> bool QFuture<T>::operator!=(const QFuture &other) const
-
- Returns \c true if \a other is \e not a copy of this future; otherwise returns
- false.
-*/
-
/*! \fn template <typename T> void QFuture<T>::cancel()
Cancels the asynchronous computation represented by this future. Note that
- the cancelation is asynchronous. Use waitForFinished() after calling
- cancel() when you need synchronous cancelation.
+ the cancellation is asynchronous. Use waitForFinished() after calling
+ cancel() when you need synchronous cancellation.
Results currently available may still be accessed on a canceled future,
but new results will \e not become available after calling this function.
@@ -208,8 +195,7 @@
#if QT_DEPRECATED_SINCE(6, 0)
/*! \fn template <typename T> void QFuture<T>::setPaused(bool paused)
- \obsolete
- Use setSuspended() instead.
+ \deprecated [6.0] Use setSuspended() instead.
If \a paused is true, this function pauses the asynchronous computation
represented by the future. If the computation is already paused, this
@@ -225,13 +211,12 @@
returned by QtConcurrent::run() cannot be paused; but the future returned
by QtConcurrent::mappedReduced() can.
- \sa pause(), resume(), togglePaused()
+ \sa suspend(), resume(), toggleSuspended()
*/
/*! \fn template <typename T> bool QFuture<T>::isPaused() const
- \obsolete
- Use isSuspending() or isSuspended() instead.
+ \deprecated [6.0] Use isSuspending() or isSuspended() instead.
Returns \c true if the asynchronous computation has been paused with the
pause() function; otherwise returns \c false.
@@ -240,13 +225,12 @@
function returns \c true. See setPaused() for more details. To check
if pause actually took effect, use isSuspended() instead.
- \sa setPaused(), togglePaused(), isSuspended()
+ \sa toggleSuspended(), isSuspended()
*/
/*! \fn template <typename T> void QFuture<T>::pause()
- \obsolete
- Use suspend() instead.
+ \deprecated [6.0] Use suspend() instead.
Pauses the asynchronous computation represented by this future. This is a
convenience method that simply calls setPaused(true).
@@ -256,15 +240,14 @@
/*! \fn template <typename T> void QFuture<T>::togglePaused()
- \obsolete
- Use toggleSuspended() instead.
+ \deprecated [6.0] Use toggleSuspended() instead.
Toggles the paused state of the asynchronous computation. In other words,
if the computation is currently paused, calling this function resumes it;
if the computation is running, it is paused. This is a convenience method
for calling setPaused(!isPaused()).
- \sa setPaused(), pause(), resume()
+ \sa setSuspended(), suspend(), resume()
*/
#endif // QT_DEPRECATED_SINCE(6, 0)
@@ -367,7 +350,7 @@
number of results stored might be different from this value, due to gaps
in the result set. It is always safe to iterate through the results from 0
to resultCount().
- \sa result(), resultAt(), results(), takeResult(), takeResults()
+ \sa result(), resultAt(), results(), takeResult()
*/
/*! \fn template <typename T> int QFuture<T>::progressValue() const
@@ -404,22 +387,25 @@
/*! \fn template <typename T> void QFuture<T>::waitForFinished()
Waits for the asynchronous computation to finish (including cancel()ed
- computations).
+ computations), i.e. until isFinished() returns \c true.
*/
-/*! \fn template <typename T> T QFuture<T>::result() const
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture<T>::result() const
Returns the first result in the future. If the result is not immediately
available, this function will block and wait for the result to become
- available. This is a convenience method for calling resultAt(0).
+ available. This is a convenience method for calling resultAt(0). Note
+ that \c result() returns a copy of the internally stored result. If \c T is
+ a move-only type, or you don't want to copy the result, use takeResult()
+ instead.
- \note Calling result() leads to undefined behavior if isValid()
+ \note Calling \c result() leads to undefined behavior if isValid()
returns \c false for this QFuture.
- \sa resultAt(), results(), takeResult(), takeResults()
+ \sa resultAt(), results(), takeResult()
*/
-/*! \fn template <typename T> T QFuture<T>::resultAt(int index) const
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture<T>::resultAt(int index) const
Returns the result at \a index in the future. If the result is not
immediately available, this function will block and wait for the result to
@@ -428,10 +414,10 @@
\note Calling resultAt() leads to undefined behavior if isValid()
returns \c false for this QFuture.
- \sa result(), results(), takeResult(), takeResults(), resultCount()
+ \sa result(), results(), takeResult(), resultCount()
*/
-/*! \fn template <typename T> bool QFuture<T>::isResultReadyAt(int index) const
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool QFuture<T>::isResultReadyAt(int index) const
Returns \c true if the result at \a index is immediately available; otherwise
returns \c false.
@@ -439,34 +425,26 @@
\note Calling isResultReadyAt() leads to undefined behavior if isValid()
returns \c false for this QFuture.
- \sa resultAt(), resultCount(), takeResult(), takeResults()
-*/
-
-/*! \fn template <typename T> QFuture<T>::operator T() const
-
- Returns the first result in the future. If the result is not immediately
- available, this function will block and wait for the result to become
- available. This is a convenience method for calling result() or
- resultAt(0).
-
- \note Calling this function leads to undefined behavior if isValid()
- returns \c false for this QFuture.
-
- \sa result(), resultAt(), results(), takeResult(), takeResults(), isValid()
+ \sa resultAt(), resultCount(), takeResult()
*/
-/*! \fn template <typename T> QList<T> QFuture<T>::results() const
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QList<T> QFuture<T>::results() const
Returns all results from the future. If the results are not immediately available,
- this function will block and wait for them to become available.
+ this function will block and wait for them to become available. Note that
+ \c results() returns a copy of the internally stored results. Getting all
+ results of a move-only type \c T is not supported at the moment. However you can
+ still iterate through the list of move-only results by using \l{STL-style iterators}
+ or read-only \l{Java-style iterators}.
- \note Calling results() leads to undefined behavior if isValid()
+ \note Calling \c results() leads to undefined behavior if isValid()
returns \c false for this QFuture.
- \sa result(), resultAt(), takeResult(), takeResults(), resultCount(), isValid()
+ \sa result(), resultAt(), takeResult(), resultCount(), isValid()
*/
-/*! \fn template <typename T> std::vector<T> QFuture<T>::takeResults()
+#if 0
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> std::vector<T> QFuture<T>::takeResults()
If isValid() returns \c false, calling this function leads to undefined behavior.
takeResults() takes all results from the QFuture object and invalidates it
@@ -483,14 +461,16 @@
\sa takeResult(), result(), resultAt(), results(), resultCount(), isValid()
*/
+#endif
-/*! \fn template <typename T> std::vector<T> QFuture<T>::takeResult()
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> std::vector<T> QFuture<T>::takeResult()
+
+ \since 6.0
Call this function only if isValid() returns \c true, otherwise
- the behavior is undefined. This function takes the first result from
- the QFuture object, for convenience when only one result is expected.
- If there are any other results, they are discarded after taking the
- first one (if such behavior is undesired, use takeResults() instead).
+ the behavior is undefined. This function takes (moves) the first result from
+ the QFuture object, when only one result is expected. If there are any other
+ results, they are discarded after taking the first one.
If the result is not immediately available, this function will block and
wait for the result to become available. The QFuture will try to use move
semantics if possible, and will fall back to copy construction if the type
@@ -501,20 +481,24 @@
objects (and potentially between different threads). takeResult() was introduced
to make QFuture also work with move-only types (like std::unique_ptr), so it
assumes that only one thread can move the results out of the future, and
- do it only once.
+ do it only once. Also note that taking the list of all results is not supported
+ at the moment. However you can still iterate through the list of move-only
+ results by using \l{STL-style iterators} or read-only \l{Java-style iterators}.
- \sa takeResults(), result(), results(), resultAt(), isValid()
+ \sa result(), results(), resultAt(), isValid()
*/
/*! \fn template <typename T> bool QFuture<T>::isValid() const
+ \since 6.0
+
Returns \c true if a result or results can be accessed or taken from this
QFuture object. Returns false after the result was taken from the future.
- \sa takeResults(), takeResult(), result(), results(), resultAt()
+ \sa takeResult(), result(), results(), resultAt()
*/
-/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::begin() const
+/*! \fn template<typename T> template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture<T>::begin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first result in the
future.
@@ -522,7 +506,7 @@
\sa constBegin(), end()
*/
-/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::end() const
+/*! \fn template<typename T> template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture<T>::end() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary result
after the last result in the future.
@@ -530,7 +514,7 @@
\sa begin(), constEnd()
*/
-/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::constBegin() const
+/*! \fn template<typename T> template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture<T>::constBegin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first result in the
future.
@@ -538,7 +522,7 @@
\sa begin(), constEnd()
*/
-/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::constEnd() const
+/*! \fn template<typename T> template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture<T>::constEnd() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary result
after the last result in the future.
@@ -629,17 +613,17 @@
Returns a pointer to the current result.
*/
-/*! \fn template <typename T> bool QFuture<T>::const_iterator::operator!=(const const_iterator &other) const
+/*! \fn template <typename T> bool QFuture<T>::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different result than this iterator;
+ Returns \c true if \a lhs points to a different result than \a rhs iterator;
otherwise returns \c false.
\sa operator==()
*/
-/*! \fn template <typename T> bool QFuture<T>::const_iterator::operator==(const const_iterator &other) const
+/*! \fn template <typename T> bool QFuture<T>::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same result as this iterator;
+ Returns \c true if \a lhs points to the same result as \a rhs iterator;
otherwise returns \c false.
\sa operator!=()
@@ -647,7 +631,7 @@
/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator++()
- The prefix ++ operator (\c{++it}) advances the iterator to the next result
+ The prefix \c{++} operator (\c{++it}) advances the iterator to the next result
in the future and returns an iterator to the new current result.
Calling this function on QFuture<T>::constEnd() leads to undefined results.
@@ -659,14 +643,14 @@
\overload
- The postfix ++ operator (\c{it++}) advances the iterator to the next
+ The postfix \c{++} operator (\c{it++}) advances the iterator to the next
result in the future and returns an iterator to the previously current
result.
*/
/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator--()
- The prefix -- operator (\c{--it}) makes the preceding result current and
+ The prefix \c{--} operator (\c{--it}) makes the preceding result current and
returns an iterator to the new current result.
Calling this function on QFuture<T>::constBegin() leads to undefined results.
@@ -678,7 +662,7 @@
\overload
- The postfix -- operator (\c{it--}) makes the preceding result current and
+ The postfix \c{--} operator (\c{it--}) makes the preceding result current and
returns an iterator to the previously current result.
*/
@@ -888,6 +872,7 @@
/*!
\namespace QtFuture
+ \inheaderfile QFuture
\inmodule QtCore
\brief Contains miscellaneous identifiers used by the QFuture class.
@@ -901,20 +886,57 @@
Represents execution policies for running a QFuture continuation.
- \value Sync The continuation will be launched in the same thread in
- which the parent has been executing.
+ \value Sync The continuation will be launched in the same thread that
+ fulfills the promise associated with the future to which the
+ continuation was attached, or if it has already finished, the
+ continuation will be invoked immediately, in the thread that
+ executes \c then().
- \value Async The continuation will be launched in in a separate thread taken from
+ \value Async The continuation will be launched in a separate thread taken from
the global QThreadPool.
- \value Inherit The continuation will inherit the launch policy of the parent or its
- thread pool, if it was using a custom one.
+ \value Inherit The continuation will inherit the launch policy or thread pool of
+ the future to which it is attached.
+
+ \c Sync is used as a default launch policy.
\sa QFuture::then(), QThreadPool::globalInstance()
*/
-/*! \fn template<class Sender, class Signal> static QFuture<ArgsType<Signal>> QtFuture::connect(Sender *sender, Signal signal)
+/*!
+ \class QtFuture::WhenAnyResult
+ \inmodule QtCore
+ \ingroup thread
+ \brief QtFuture::WhenAnyResult is used to represent the result of QtFuture::whenAny().
+ \since 6.3
+
+ The \c {QtFuture::WhenAnyResult<T>} struct is used for packaging the copy and
+ the index of the first completed \c QFuture<T> in the sequence of futures
+ packaging type \c T that are passed to QtFuture::whenAny().
+
+ \sa QFuture, QtFuture::whenAny()
+*/
+
+/*!
+ \variable QtFuture::WhenAnyResult::index
+
+ The field contains the index of the first completed QFuture in the sequence
+ of futures passed to whenAny(). It has type \c qsizetype.
+
+ \sa QtFuture::whenAny()
+*/
+
+/*!
+ \variable QtFuture::WhenAnyResult::future
+
+ The field contains the copy of the first completed QFuture that packages type
+ \c T, where \c T is the type packaged by the futures passed to whenAny().
+
+ \sa QtFuture::whenAny()
+*/
+
+/*! \fn template<class Sender, class Signal, typename = QtPrivate::EnableIfInvocable<Sender, Signal>> static QFuture<ArgsType<Signal>> QtFuture::connect(Sender *sender, Signal signal)
Creates and returns a QFuture which will become available when the \a sender emits
the \a signal. If the \a signal takes no arguments, a QFuture<void> is returned. If
@@ -953,23 +975,212 @@
\sa QFuture, QFuture::then()
*/
+/*! \fn template<typename T, typename = QtPrivate::EnableForNonVoid<T>> static QFuture<std::decay_t<T>> QtFuture::makeReadyFuture(T &&value)
+
+ \since 6.1
+ \overload
+ \deprecated [6.6] Use makeReadyValueFuture() instead.
+
+ Creates and returns a QFuture which already has a result \a value.
+ The returned QFuture has a type of std::decay_t<T>, where T is not void.
+
+ \code
+ auto f = QtFuture::makeReadyFuture(std::make_unique<int>(42));
+ ...
+ const int result = *f.takeResult(); // result == 42
+ \endcode
+
+ The method should be avoided because
+ it has an inconsistent set of overloads. From Qt 6.10 onwards, using it
+ in code will result in compiler warnings.
+
+ \sa QFuture, QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(),
+ QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn QFuture<void> QtFuture::makeReadyFuture()
+
+ \since 6.1
+ \overload
+ \deprecated [6.6] Use makeReadyVoidFuture() instead.
+
+ Creates and returns a void QFuture. Such QFuture can't store any result.
+ One can use it to query the state of the computation.
+ The returned QFuture will always be in the finished state.
+
+ \code
+ auto f = QtFuture::makeReadyFuture();
+ ...
+ const bool started = f.isStarted(); // started == true
+ const bool running = f.isRunning(); // running == false
+ const bool finished = f.isFinished(); // finished == true
+ \endcode
+
+ The method should be avoided because
+ it has an inconsistent set of overloads. From Qt 6.10 onwards, using it
+ in code will result in compiler warnings.
+
+ \sa QFuture, QFuture::isStarted(), QFuture::isRunning(),
+ QFuture::isFinished(), QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(),
+ QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<T> QtFuture::makeReadyFuture(const QList<T> &values)
+
+ \since 6.1
+ \overload
+ \deprecated [6.6] Use makeReadyRangeFuture() instead.
+
+ Creates and returns a QFuture which already has multiple results set from \a values.
+
+ \code
+ const QList<int> values { 1, 2, 3 };
+ auto f = QtFuture::makeReadyFuture(values);
+ ...
+ const int count = f.resultCount(); // count == 3
+ const auto results = f.results(); // results == { 1, 2, 3 }
+ \endcode
+
+ The method should be avoided because
+ it has an inconsistent set of overloads. From Qt 6.10 onwards, using it
+ in code will result in compiler warnings.
+
+ \sa QFuture, QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(),
+ QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<std::decay_t<T>> QtFuture::makeReadyValueFuture(T &&value)
+
+ \since 6.6
+
+ Creates and returns a QFuture which already has a result \a value.
+ The returned QFuture has a type of std::decay_t<T>, where T is not void.
+ The returned QFuture will already be in the finished state.
+
+ \snippet code/src_corelib_thread_qfuture.cpp 35
+
+ \sa QFuture, QtFuture::makeReadyRangeFuture(),
+ QtFuture::makeReadyVoidFuture(), QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn QFuture<void> QtFuture::makeReadyVoidFuture()
+
+ \since 6.6
+
+ Creates and returns a void QFuture. Such QFuture can't store any result.
+ One can use it to query the state of the computation.
+ The returned QFuture will already be in the finished state.
+
+ \snippet code/src_corelib_thread_qfuture.cpp 36
+
+ \sa QFuture, QFuture::isStarted(), QFuture::isRunning(),
+ QFuture::isFinished(), QtFuture::makeReadyValueFuture(),
+ QtFuture::makeReadyRangeFuture(), QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<T> QtFuture::makeExceptionalFuture(const QException &exception)
+
+ \since 6.1
+
+ Creates and returns a QFuture which already has an exception \a exception.
+
+ \code
+ QException e;
+ auto f = QtFuture::makeExceptionalFuture<int>(e);
+ ...
+ try {
+ f.result(); // throws QException
+ } catch (QException &) {
+ // handle exception here
+ }
+ \endcode
+
+ \sa QFuture, QException, QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<T> QtFuture::makeExceptionalFuture(std::exception_ptr exception)
+
+ \since 6.1
+ \overload
+
+ Creates and returns a QFuture which already has an exception \a exception.
+
+ \code
+ struct TestException
+ {
+ };
+ ...
+ auto exception = std::make_exception_ptr(TestException());
+ auto f = QtFuture::makeExceptionalFuture<int>(exception);
+ ...
+ try {
+ f.result(); // throws TestException
+ } catch (TestException &) {
+ // handle exception here
+ }
+ \endcode
+
+ \sa QFuture, QException, QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture()
+*/
+
+/*! \fn template<typename Container, QtFuture::if_container_with_input_iterators<Container>> static QFuture<QtFuture::ContainedType<Container>> QtFuture::makeReadyRangeFuture(Container &&container)
+
+ \since 6.6
+ \overload
+
+ Takes an input container \a container and returns a QFuture with multiple
+ results of type \c ContainedType initialized from the values of the
+ \a container.
+
+ \note This overload only participates in overload resolution if the
+ \c Container has input iterators.
+
+ \snippet code/src_corelib_thread_qfuture.cpp 32
+ \dots
+ \snippet code/src_corelib_thread_qfuture.cpp 34
+
+ \sa QFuture, QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn template<typename ValueType> static QFuture<ValueType> QtFuture::makeReadyRangeFuture(std::initializer_list<ValueType> values)
+
+ \since 6.6
+ \overload
+
+ Returns a QFuture with multiple results of type \c ValueType initialized
+ from the input initializer list \a values.
+
+ \snippet code/src_corelib_thread_qfuture.cpp 33
+ \dots
+ \snippet code/src_corelib_thread_qfuture.cpp 34
+
+ \sa QFuture, QtFuture::makeReadyVoidFuture(),
+ QtFuture::makeReadyValueFuture(), QtFuture::makeExceptionalFuture()
+*/
+
/*! \fn template<class T> template<class Function> QFuture<typename QFuture<T>::ResultType<Function>> QFuture<T>::then(Function &&function)
\since 6.0
\overload
Attaches a continuation to this future, allowing to chain multiple asynchronous
- computations if desired. When the asynchronous computation represented by this
- future finishes, \a function will be invoked in the same thread in which this
- future has been running. A new QFuture representing the result of the continuation
- is returned.
+ computations if desired, using the \l {QtFuture::Launch}{Sync} policy.
+ \a function is a callable that takes an argument of the type packaged by this
+ future if this has a result (is not a QFuture<void>). Otherwise it takes no
+ arguments. This method returns a new QFuture that packages a value of the type
+ returned by \a function. The returned future will be in an uninitialized state
+ until the attached continuation is invoked, or until this future fails or is
+ canceled.
\note Use other overloads of this method if you need to launch the continuation in
a separate thread.
- If this future has a result (is not a QFuture<void>), \a function takes the result
- of this future as its argument.
-
You can chain multiple operations like this:
\code
@@ -999,7 +1210,7 @@
In this case the whole chain of continuations will be interrupted.
- \note If the parent future gets canceled, its continuations will
+ \note If this future gets canceled, the continuations attached to it will
also be canceled.
\sa onFailed(), onCanceled()
@@ -1015,10 +1226,12 @@
finishes, \a function will be invoked according to the given launch \a policy.
A new QFuture representing the result of the continuation is returned.
- Depending on the \a policy, continuation will run in the same thread as the parent,
- run in a new thread, or inherit the launch policy and thread pool of the parent.
+ Depending on the \a policy, continuation will be invoked in the same thread as
+ this future, in a new thread, or will inherit the launch policy and thread pool of
+ this future. If no launch policy is specified (see the overload taking only a callable),
+ the \c Sync policy will be used.
- In the following example both continuations will run in a new thread (but in
+ In the following example both continuations will be invoked in a new thread (but in
the same one).
\code
@@ -1026,8 +1239,8 @@
future.then(QtFuture::Launch::Async, [](int res){ ... }).then([](int res2){ ... });
\endcode
- In the following example both continuations will run in new threads using the same
- thread pool.
+ In the following example both continuations will be invoked in new threads using the
+ same thread pool.
\code
QFuture<int> future = ...;
@@ -1035,6 +1248,8 @@
.then(QtFuture::Launch::Inherit, [](int res2){ ... });
\endcode
+ See the documentation of the other overload for more details about \a function.
+
\sa onFailed(), onCanceled()
*/
@@ -1045,24 +1260,86 @@
Attaches a continuation to this future, allowing to chain multiple asynchronous
computations if desired. When the asynchronous computation represented by this
- future finishes, \a function will be invoked in a separate thread taken from the
- QThreadPool \a pool.
+ future finishes, \a function will be scheduled on \a pool.
\sa onFailed(), onCanceled()
*/
-/*! \fn template<class T> template<class Function> QFuture<T> QFuture<T>::onFailed(Function &&handler)
+/*! \fn template<class T> template<class Function> QFuture<typename QFuture<T>::ResultType<Function>> QFuture<T>::then(QObject *context, Function &&function)
+
+ \since 6.1
+ \overload
+
+ Attaches a continuation to this future, allowing to chain multiple asynchronous
+ computations if desired. When the asynchronous computation represented by this
+ future finishes, \a function will be invoked in the thread of the \a context object.
+ This can be useful if the continuation needs to be invoked in a specific thread.
+ For example:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 17
+
+ The continuation attached into QtConcurrent::run updates the UI elements and cannot
+ be invoked from a non-gui thread. So \c this is provided as a context to \c .then(),
+ to make sure that it will be invoked in the main thread.
+
+ The following continuations will be also invoked from the same context,
+ unless a different context or launch policy is specified:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 18
+
+ This is because by default \c .then() is invoked from the same thread as the
+ previous one.
+
+ But note that if the continuation is attached after this future has already finished,
+ it will be invoked immediately, in the thread that executes \c then():
+
+ \snippet code/src_corelib_thread_qfuture.cpp 20
+
+ In the above example if \c cachedResultsReady is \c true, and a ready future is
+ returned, it is possible that the first \c .then() finishes before the second one
+ is attached. In this case it will be resolved in the current thread. Therefore, when
+ in doubt, pass the context explicitly.
+
+ \target context_lifetime
+ If the \a context is destroyed before the chain has finished, the future is canceled.
+ This implies that a cancellation handler might be invoked when the \a context is not valid
+ anymore. To guard against this, capture the \a context as a QPointer:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 37
+
+ When the context object is destroyed, cancellation happens immediately. Previous futures in the
+ chain are \e {not} cancelled and keep running until they are finished.
+
+ \note When calling this method, it should be guaranteed that the \a context stays alive
+ during setup of the chain.
+
+ \sa onFailed(), onCanceled()
+*/
+
+/*! \fn template<class T> template<class Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture<T>::onFailed(Function &&handler)
\since 6.0
- Attaches a failure handler to this future, to handle any exceptions that may
- have been generated. Returns a QFuture of the parent type. The handler will
- be invoked only in case of an exception, in the same thread as the parent
- future has been running. \a handler is a callable which takes either no argument
- or one argument, to filter by specific error types similar to
+ Attaches a failure handler to this future, to handle any exceptions. The
+ returned future behaves exactly as this future (has the same state and result)
+ unless this future fails with an exception.
+
+ The \a handler is a callable which takes either no argument or one argument, to
+ filter by specific error types, similar to the
\l {https://en.cppreference.com/w/cpp/language/try_catch} {catch} statement.
+ It returns a value of the type packaged by this future. After the failure, the
+ returned future packages the value returned by \a handler.
- For example:
+ The handler will only be invoked if an exception is raised. If the exception
+ is raised after this handler is attached, the handler is executed in the thread
+ that reports the future as finished as a result of the exception. If the handler
+ is attached after this future has already failed, it will be invoked immediately,
+ in the thread that executes \c onFailed(). Therefore, the handler cannot always
+ make assumptions about which thread it will be run on. Use the overload that
+ takes a context object if you want to control which thread the handler is
+ invoked on.
+
+ The example below demonstrates how to attach a failure handler:
\snippet code/src_corelib_thread_qfuture.cpp 7
@@ -1082,13 +1359,247 @@
\sa then(), onCanceled()
*/
-/*! \fn template<class T> template<class Function> QFuture<T> QFuture<T>::onCanceled(Function &&handler)
+/*! \fn template<class T> template<class Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture<T>::onFailed(QObject *context, Function &&handler)
+
+ \since 6.1
+ \overload
+
+ Attaches a failure handler to this future, to handle any exceptions that the future
+ raises, or that it has already raised. Returns a QFuture of the same type as this
+ future. The handler will be invoked only in case of an exception, in the thread of
+ the \a context object. This can be useful if the failure needs to be handled in a
+ specific thread. For example:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 19
+
+ The failure handler attached into QtConcurrent::run updates the UI elements and cannot
+ be invoked from a non-gui thread. So \c this is provided as a context to \c .onFailed(),
+ to make sure that it will be invoked in the main thread.
+
+ If the \a context is destroyed before the chain has finished, the future is canceled.
+ See \l {context_lifetime}{then()} for details.
+
+ \note When calling this method, it should be guaranteed that the \a context stays alive
+ during setup of the chain.
+
+ See the documentation of the other overload for more details about \a handler.
+
+ \sa then(), onCanceled()
+*/
+
+/*! \fn template<class T> template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture<T>::onCanceled(Function &&handler)
\since 6.0
+ Attaches a cancellation \a handler to this future. The returned future
+ behaves exactly as this future (has the same state and result) unless
+ this future is cancelled. The \a handler is a callable which takes no
+ arguments and returns a value of the type packaged by this future. After
+ cancellation, the returned future packages the value returned by \a handler.
+
+ If attached before the cancellation, \a handler will be invoked in the same
+ thread that reports the future as finished after the cancellation. If the
+ handler is attached after this future has already been canceled, it will be
+ invoked immediately in the thread that executes \c onCanceled(). Therefore,
+ the handler cannot always make assumptions about which thread it will be run
+ on. Use the overload that takes a context object if you want to control
+ which thread the handler is invoked on.
+
+ The example below demonstrates how to attach a cancellation handler:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 21
+
+ If \c testFuture is canceled, \c {Block 3} will be called and the
+ \c resultFuture will have \c -1 as its result. Unlike \c testFuture, it won't
+ be in a \c Canceled state. This means that you can get its result, attach
+ countinuations to it, and so on.
+
+ Also note that you can cancel the chain of continuations while they are
+ executing via the future that started the chain. Let's say \c testFuture.cancel()
+ was called while \c {Block 1} is already executing. The next continuation will
+ detect that cancellation was requested, so \c {Block 2} will be skipped, and
+ the cancellation handler (\c {Block 3}) will be called.
+
+ \note This method returns a new \c QFuture representing the result of the
+ continuation chain. Canceling the resulting \c QFuture itself won't invoke the
+ cancellation handler in the chain that lead to it. This means that if you call
+ \c resultFuture.cancel(), \c {Block 3} won't be called: because \c resultFuture is
+ the future that results from attaching the cancellation handler to \c testFuture,
+ no cancellation handlers have been attached to \c resultFuture itself. Only
+ cancellation of \c testFuture or the futures returned by continuations attached
+ before the \c onCancelled() call can trigger \c{Block 3}.
+
+ \sa then(), onFailed()
+*/
+
+/*! \fn template<class T> template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture<T>::onCanceled(QObject *context, Function &&handler)
+
+ \since 6.1
+ \overload
+
Attaches a cancellation \a handler to this future, to be called when the future is
canceled. The \a handler is a callable which doesn't take any arguments. It will be
- invoked in the same thread in which this future has been running.
+ invoked in the thread of the \a context object. This can be useful if the cancellation
+ needs to be handled in a specific thread.
+
+ If the \a context is destroyed before the chain has finished, the future is canceled.
+ See \l {context_lifetime}{then()} for details.
+
+ \note When calling this method, it should be guaranteed that the \a context stays alive
+ during setup of the chain.
+
+ See the documentation of the other overload for more details about \a handler.
\sa then(), onFailed()
*/
+
+/*! \fn template<class T> template<class U> QFuture<U> QFuture<T>::unwrap()
+
+ \since 6.4
+
+ Unwraps the inner future from this \c QFuture<T>, where \c T is a future
+ of type \c QFuture<U>, i.e. this future has type of \c QFuture<QFuture<U>>.
+ For example:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 28
+
+ \c unwrappedFuture will be fulfilled as soon as the inner future nested
+ inside the \c outerFuture is fulfilled, with the same result or exception
+ and in the same thread that reports the inner future as finished. If the
+ inner future is canceled, \c unwrappedFuture will also be canceled.
+
+ This is especially useful when chaining multiple computations, and one of
+ them returns a \c QFuture as its result type. For example, let's say we
+ want to download multiple images from an URL, scale the images, and reduce
+ them to a single image using QtConcurrent::mappedReduced(). We could write
+ something like:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 29
+
+ Here \c QtConcurrent::mappedReduced() returns a \c QFuture<QImage>, so
+ \c .then(processImages) returns a \c QFuture<QFuture<QImage>>. Since
+ \c show() takes a \c QImage as argument, the result of \c .then(processImages)
+ can't be passed to it directly. We need to call \c .unwrap(), that will
+ get the result of the inner future when it's ready and pass it to the next
+ continuation.
+
+ In case of multiple nesting, \c .unwrap() goes down to the innermost level:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 30
+*/
+
+/*! \fn template<typename OutputSequence, typename InputIt> QFuture<OutputSequence> QtFuture::whenAll(InputIt first, InputIt last)
+
+ \since 6.3
+
+ Returns a new QFuture that succeeds when all futures from \a first to \a last
+ complete. \a first and \a last are iterators to a sequence of futures packaging
+ type \c T. \c OutputSequence is a sequence containing all completed futures
+ from \a first to \a last, appearing in the same order as in the input. If the
+ type of \c OutputSequence is not specified, the resulting futures will be
+ returned in a \c QList of \c QFuture<T>. For example:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 22
+
+ \note The output sequence must support random access and the \c resize()
+ operation.
+
+ If \c first equals \c last, this function returns a ready QFuture that
+ contains an empty \c OutputSequence.
+
+//! [whenAll]
+ The returned future always completes successfully after all the specified
+ futures complete. It doesn't matter if any of these futures completes with
+ error or is canceled. You can use \c .then() to process the completed futures
+ after the future returned by \c whenAll() succeeds:
+//! [whenAll]
+
+ \snippet code/src_corelib_thread_qfuture.cpp 23
+
+//! [whenAll-note]
+ \note If the input futures complete on different threads, the future returned
+ by this method will complete in the thread that the last future completes in.
+ Therefore, the continuations attached to the future returned by \c whenAll()
+ cannot always make assumptions about which thread they will be run on. Use the
+ overload of \c .then() that takes a context object if you want to control which
+ thread the continuations are invoked on.
+//! [whenAll-note]
+*/
+
+/*! \fn template<typename OutputSequence, typename... Futures> QFuture<OutputSequence> QtFuture::whenAll(Futures &&... futures)
+
+ \since 6.3
+
+ Returns a new QFuture that succeeds when all \a futures packaging arbitrary
+ types complete. \c OutputSequence is a sequence of completed futures. The type
+ of its entries is \c std::variant<Futures...>. For each \c QFuture<T> passed to
+ \c whenAll(), the entry at the corresponding position in \c OutputSequence
+ will be a \c std::variant holding that \c QFuture<T>, in its completed state.
+ If the type of \c OutputSequence is not specified, the resulting futures will
+ be returned in a QList of \c std::variant<Futures...>. For example:
+
+ \snippet code/src_corelib_thread_qfuture.cpp 24
+
+ \note The output sequence should support random access and the \c resize()
+ operation.
+
+ \include qfuture.qdoc whenAll
+
+ \snippet code/src_corelib_thread_qfuture.cpp 25
+
+ \include qfuture.qdoc whenAll-note
+*/
+
+/*! \fn template<typename T, typename InputIt> QFuture<QtFuture::WhenAnyResult<T>> QtFuture::whenAny(InputIt first, InputIt last)
+
+ \since 6.3
+
+ Returns a new QFuture that succeeds when any of the futures from \a first to
+ \a last completes. \a first and \a last are iterators to a sequence of futures
+ packaging type \c T. The returned future packages a value of type
+ \c {QtFuture::WhenAnyResult<T>} which in turn packages the index of the
+ first completed \c QFuture and the \c QFuture itself. If \a first equals \a last,
+ this function returns a ready \c QFuture that has \c -1 for the \c index field in
+ the QtFuture::WhenAnyResult struct and a default-constructed \c QFuture<T> for
+ the \c future field. Note that a default-constructed QFuture is a completed
+ future in a cancelled state.
+
+//! [whenAny]
+ The returned future always completes successfully after the first future
+ from the specified futures completes. It doesn't matter if the first future
+ completes with error or is canceled. You can use \c .then() to process the
+ result after the future returned by \c whenAny() succeeds:
+//! [whenAny]
+
+ \snippet code/src_corelib_thread_qfuture.cpp 26
+
+//! [whenAny-note]
+ \note If the input futures complete on different threads, the future returned
+ by this method will complete in the thread that the first future completes in.
+ Therefore, the continuations attached to the future returned by \c whenAny()
+ cannot always make assumptions about which thread they will be run on. Use the
+ overload of \c .then() that takes a context object if you want to control which
+ thread the continuations are invoked on.
+//! [whenAny-note]
+
+ \sa QtFuture::WhenAnyResult
+*/
+
+/*! \fn template<typename... Futures> QFuture<std::variant<std::decay_t<Futures>...>> QtFuture::whenAny(Futures &&... futures)
+
+ \since 6.3
+
+ Returns a new QFuture that succeeds when any of the \a futures completes.
+ \a futures can package arbitrary types. The returned future packages the
+ value of type \c std::variant<Futures...> which in turn packages the first
+ completed QFuture from \a futures. You can use
+ \l {https://en.cppreference.com/w/cpp/utility/variant/index} {std::variant::index()}
+ to find out the index of the future in the sequence of \a futures that
+ finished first.
+
+ \include qfuture.qdoc whenAny
+
+ \snippet code/src_corelib_thread_qfuture.cpp 27
+
+ \include qfuture.qdoc whenAny-note
+*/
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index 883f8d4f09..351093adc7 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTURE_H
#error Do not include qfuture_impl.h directly
@@ -49,6 +13,10 @@
#include <QtCore/qglobal.h>
#include <QtCore/qfutureinterface.h>
#include <QtCore/qthreadpool.h>
+#include <QtCore/qexception.h>
+#include <QtCore/qpromise.h>
+
+#include <memory>
QT_BEGIN_NAMESPACE
@@ -59,17 +27,27 @@ template<class T>
class QFuture;
template<class T>
class QFutureInterface;
+template<class T>
+class QPromise;
namespace QtFuture {
+
enum class Launch { Sync, Async, Inherit };
+
+template<class T>
+struct WhenAnyResult
+{
+ qsizetype index = -1;
+ QFuture<T> future;
+};
+
+// Deduction guide
+template<class T>
+WhenAnyResult(qsizetype, const QFuture<T> &) -> WhenAnyResult<T>;
}
namespace QtPrivate {
-template<class T, class U>
-using EnableIfSameOrConvertible = std::enable_if_t<std::is_same_v<T, U>
- || std::is_convertible_v<T, U>>;
-
template<class T>
using EnableForVoid = std::enable_if_t<std::is_same_v<T, void>>;
@@ -113,7 +91,48 @@ struct ResultTypeHelper<
using ResultType = std::invoke_result_t<std::decay_t<F>>;
};
+// Helpers to remove QPrivateSignal argument from the list of arguments
+
+template<class T, class Enable = void>
+inline constexpr bool IsPrivateSignalArg = false;
+
+template<class T>
+inline constexpr bool IsPrivateSignalArg<T, typename std::enable_if_t<
+ // finds injected-class-name, the 'class' avoids falling into the rules of [class.qual]/2:
+ std::is_class_v<class T::QPrivateSignal>
+ >> = true;
+
+template<class Tuple, std::size_t... I>
+auto cutTuple(Tuple &&t, std::index_sequence<I...>)
+{
+ return std::make_tuple(std::get<I>(t)...);
+}
+
+template<class Arg, class... Args>
+auto createTuple(Arg &&arg, Args &&... args)
+{
+ using TupleType = std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>;
+ constexpr auto Size = sizeof...(Args); // One less than the size of all arguments
+ if constexpr (QtPrivate::IsPrivateSignalArg<std::tuple_element_t<Size, TupleType>>) {
+ if constexpr (Size == 1) {
+ return std::forward<Arg>(arg);
+ } else {
+ return cutTuple(std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...),
+ std::make_index_sequence<Size>());
+ }
+ } else {
+ return std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...);
+ }
+}
+
// Helpers to resolve argument types of callables.
+
+template<class Arg, class... Args>
+using FilterLastPrivateSignalArg =
+ std::conditional_t<(sizeof...(Args) > 0),
+ std::invoke_result_t<decltype(createTuple<Arg, Args...>), Arg, Args...>,
+ std::conditional_t<IsPrivateSignalArg<Arg>, void, Arg>>;
+
template<typename...>
struct ArgsType;
@@ -121,19 +140,34 @@ template<typename Arg, typename... Args>
struct ArgsType<Arg, Args...>
{
using First = Arg;
+ using PromiseType = void;
+ using IsPromise = std::false_type;
static const bool HasExtraArgs = (sizeof...(Args) > 0);
- using AllArgs =
- std::conditional_t<HasExtraArgs, std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>,
- std::decay_t<Arg>>;
+ using AllArgs = FilterLastPrivateSignalArg<std::decay_t<Arg>, std::decay_t<Args>...>;
template<class Class, class Callable>
static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, Arg, Args...>;
};
+template<typename Arg, typename... Args>
+struct ArgsType<QPromise<Arg> &, Args...>
+{
+ using First = QPromise<Arg> &;
+ using PromiseType = Arg;
+ using IsPromise = std::true_type;
+ static const bool HasExtraArgs = (sizeof...(Args) > 0);
+ using AllArgs = FilterLastPrivateSignalArg<QPromise<Arg>, std::decay_t<Args>...>;
+
+ template<class Class, class Callable>
+ static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, QPromise<Arg> &, Args...>;
+};
+
template<>
struct ArgsType<>
{
using First = void;
+ using PromiseType = void;
+ using IsPromise = std::false_type;
static const bool HasExtraArgs = false;
using AllArgs = void;
@@ -146,6 +180,11 @@ struct ArgResolver : ArgResolver<decltype(&std::decay_t<F>::operator())>
{
};
+template<typename F>
+struct ArgResolver<std::reference_wrapper<F>> : ArgResolver<decltype(&std::decay_t<F>::operator())>
+{
+};
+
template<typename R, typename... Args>
struct ArgResolver<R(Args...)> : public ArgsType<Args...>
{
@@ -157,6 +196,16 @@ struct ArgResolver<R (*)(Args...)> : public ArgsType<Args...>
};
template<typename R, typename... Args>
+struct ArgResolver<R (*&)(Args...)> : public ArgsType<Args...>
+{
+};
+
+template<typename R, typename... Args>
+struct ArgResolver<R (* const)(Args...)> : public ArgsType<Args...>
+{
+};
+
+template<typename R, typename... Args>
struct ArgResolver<R (&)(Args...)> : public ArgsType<Args...>
{
};
@@ -181,39 +230,85 @@ struct ArgResolver<R (Class::*)(Args...) const noexcept> : public ArgsType<Args.
{
};
+template<typename Class, typename R, typename... Args>
+struct ArgResolver<R (Class::* const)(Args...) const> : public ArgsType<Args...>
+{
+};
+
+template<typename Class, typename R, typename... Args>
+struct ArgResolver<R (Class::* const)(Args...) const noexcept> : public ArgsType<Args...>
+{
+};
+
template<class Class, class Callable>
using EnableIfInvocable = std::enable_if_t<
QtPrivate::ArgResolver<Callable>::template CanInvokeWithArgs<Class, Callable>>;
-template<class>
-struct isTuple : std::false_type
+template<class T>
+inline constexpr bool isQFutureV = false;
+
+template<class T>
+inline constexpr bool isQFutureV<QFuture<T>> = true;
+
+template<class T>
+using isQFuture = std::bool_constant<isQFutureV<T>>;
+
+template<class T>
+struct Future
{
};
-template<class... T>
-struct isTuple<std::tuple<T...>> : std::true_type
+
+template<class T>
+struct Future<QFuture<T>>
{
+ using type = T;
};
-template<class T>
-inline constexpr bool isTupleV = isTuple<T>::value;
+
+template<class... Args>
+using NotEmpty = std::bool_constant<(sizeof...(Args) > 0)>;
+
+template<class Sequence>
+using IsRandomAccessible =
+ std::is_convertible<typename std::iterator_traits<std::decay_t<decltype(
+ std::begin(std::declval<Sequence>()))>>::iterator_category,
+ std::random_access_iterator_tag>;
+
+template<class Sequence>
+using HasInputIterator =
+ std::is_convertible<typename std::iterator_traits<std::decay_t<decltype(
+ std::begin(std::declval<Sequence>()))>>::iterator_category,
+ std::input_iterator_tag>;
+
+template<class Iterator>
+using IsForwardIterable =
+ std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category,
+ std::forward_iterator_tag>;
template<typename Function, typename ResultType, typename ParentResultType>
class Continuation
{
+ Q_DISABLE_COPY_MOVE(Continuation)
public:
- Continuation(Function &&func, const QFuture<ParentResultType> &f,
- const QFutureInterface<ResultType> &p)
- : promise(p), parentFuture(f), function(std::forward<Function>(func))
+ template<typename F = Function>
+ Continuation(F &&func, const QFuture<ParentResultType> &f, QPromise<ResultType> &&p)
+ : promise(std::move(p)), parentFuture(f), function(std::forward<F>(func))
{
}
virtual ~Continuation() = default;
bool execute();
- static void create(Function &&func, QFuture<ParentResultType> *f,
- QFutureInterface<ResultType> &p, QtFuture::Launch policy);
+ template<typename F = Function>
+ static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &fi,
+ QtFuture::Launch policy);
+
+ template<typename F = Function>
+ static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &fi,
+ QThreadPool *pool);
- static void create(Function &&func, QFuture<ParentResultType> *f,
- QFutureInterface<ResultType> &p, QThreadPool *pool);
+ template<typename F = Function>
+ static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &fi,
+ QObject *context);
private:
void fulfillPromiseWithResult();
@@ -229,7 +324,7 @@ protected:
void runFunction();
protected:
- QFutureInterface<ResultType> promise;
+ QPromise<ResultType> promise;
QFuture<ParentResultType> parentFuture;
Function function;
};
@@ -238,9 +333,10 @@ template<typename Function, typename ResultType, typename ParentResultType>
class SyncContinuation final : public Continuation<Function, ResultType, ParentResultType>
{
public:
- SyncContinuation(Function &&func, const QFuture<ParentResultType> &f,
- const QFutureInterface<ResultType> &p)
- : Continuation<Function, ResultType, ParentResultType>(std::forward<Function>(func), f, p)
+ template<typename F = Function>
+ SyncContinuation(F &&func, const QFuture<ParentResultType> &f, QPromise<ResultType> &&p)
+ : Continuation<Function, ResultType, ParentResultType>(std::forward<F>(func), f,
+ std::move(p))
{
}
@@ -255,12 +351,13 @@ class AsyncContinuation final : public QRunnable,
public Continuation<Function, ResultType, ParentResultType>
{
public:
- AsyncContinuation(Function &&func, const QFuture<ParentResultType> &f,
- const QFutureInterface<ResultType> &p, QThreadPool *pool = nullptr)
- : Continuation<Function, ResultType, ParentResultType>(std::forward<Function>(func), f, p),
+ template<typename F = Function>
+ AsyncContinuation(F &&func, const QFuture<ParentResultType> &f, QPromise<ResultType> &&p,
+ QThreadPool *pool = nullptr)
+ : Continuation<Function, ResultType, ParentResultType>(std::forward<F>(func), f,
+ std::move(p)),
threadPool(pool)
{
- this->promise.setRunnable(this);
}
~AsyncContinuation() override = default;
@@ -287,12 +384,17 @@ template<class Function, class ResultType>
class FailureHandler
{
public:
- static void create(Function &&function, QFuture<ResultType> *future,
- const QFutureInterface<ResultType> &promise);
+ template<typename F = Function>
+ static void create(F &&function, QFuture<ResultType> *future,
+ const QFutureInterface<ResultType> &fi);
- FailureHandler(Function &&func, const QFuture<ResultType> &f,
- const QFutureInterface<ResultType> &p)
- : promise(p), parentFuture(f), handler(std::forward<Function>(func))
+ template<typename F = Function>
+ static void create(F &&function, QFuture<ResultType> *future, QFutureInterface<ResultType> &fi,
+ QObject *context);
+
+ template<typename F = Function>
+ FailureHandler(F &&func, const QFuture<ResultType> &f, QPromise<ResultType> &&p)
+ : promise(std::move(p)), parentFuture(f), handler(std::forward<F>(func))
{
}
@@ -305,7 +407,7 @@ private:
void handleAllExceptions();
private:
- QFutureInterface<ResultType> promise;
+ QPromise<ResultType> promise;
QFuture<ResultType> parentFuture;
Function handler;
};
@@ -315,7 +417,7 @@ private:
template<typename Function, typename ResultType, typename ParentResultType>
void Continuation<Function, ResultType, ParentResultType>::runFunction()
{
- promise.reportStarted();
+ promise.start();
Q_ASSERT(parentFuture.isFinished());
@@ -329,7 +431,7 @@ void Continuation<Function, ResultType, ParentResultType>::runFunction()
fulfillPromiseWithResult();
} else {
// This assert normally should never fail, this is to make sure
- // that nothing unexpected happend.
+ // that nothing unexpected happened.
static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
"The continuation is not invocable with the provided arguments");
fulfillPromise(parentFuture);
@@ -344,7 +446,7 @@ void Continuation<Function, ResultType, ParentResultType>::runFunction()
fulfillVoidPromise();
} else {
// This assert normally should never fail, this is to make sure
- // that nothing unexpected happend.
+ // that nothing unexpected happened.
static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
"The continuation is not invocable with the provided arguments");
function(parentFuture);
@@ -352,10 +454,10 @@ void Continuation<Function, ResultType, ParentResultType>::runFunction()
}
#ifndef QT_NO_EXCEPTIONS
} catch (...) {
- promise.reportException(std::current_exception());
+ promise.setException(std::current_exception());
}
#endif
- promise.reportFinished();
+ promise.finish();
}
template<typename Function, typename ResultType, typename ParentResultType>
@@ -363,25 +465,25 @@ bool Continuation<Function, ResultType, ParentResultType>::execute()
{
Q_ASSERT(parentFuture.isFinished());
- if (parentFuture.isCanceled()) {
+ if (parentFuture.d.isChainCanceled()) {
#ifndef QT_NO_EXCEPTIONS
- if (parentFuture.d.exceptionStore().hasException()) {
+ if (parentFuture.d.hasException()) {
// If the continuation doesn't take a QFuture argument, propagate the exception
// to the caller, by reporting it. If the continuation takes a QFuture argument,
// the user may want to catch the exception inside the continuation, to not
// interrupt the continuation chain, so don't report anything yet.
if constexpr (!std::is_invocable_v<std::decay_t<Function>, QFuture<ParentResultType>>) {
- promise.reportStarted();
- promise.reportException(parentFuture.d.exceptionStore().exception());
- promise.reportFinished();
+ promise.start();
+ promise.setException(parentFuture.d.exceptionStore().exception());
+ promise.finish();
return false;
}
} else
#endif
{
- promise.reportStarted();
- promise.reportCanceled();
- promise.reportFinished();
+ promise.start();
+ promise.future().cancel();
+ promise.finish();
return false;
}
}
@@ -390,10 +492,30 @@ bool Continuation<Function, ResultType, ParentResultType>::execute()
return true;
}
+// Workaround for keeping move-only lambdas inside std::function
+template<class Function>
+struct ContinuationWrapper
+{
+ ContinuationWrapper(Function &&f) : function(std::move(f)) { }
+ ContinuationWrapper(const ContinuationWrapper &other)
+ : function(std::move(const_cast<ContinuationWrapper &>(other).function))
+ {
+ Q_ASSERT_X(false, "QFuture", "Continuation shouldn't be copied");
+ }
+ ContinuationWrapper(ContinuationWrapper &&other) = default;
+ ContinuationWrapper &operator=(ContinuationWrapper &&) = default;
+
+ void operator()(const QFutureInterfaceBase &parentData) { function(parentData); }
+
+private:
+ Function function;
+};
+
template<typename Function, typename ResultType, typename ParentResultType>
-void Continuation<Function, ResultType, ParentResultType>::create(Function &&func,
+template<typename F>
+void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
QFuture<ParentResultType> *f,
- QFutureInterface<ResultType> &p,
+ QFutureInterface<ResultType> &fi,
QtFuture::Launch policy)
{
Q_ASSERT(f);
@@ -407,22 +529,26 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
// If the parent future was using a custom thread pool, inherit it as well.
if (launchAsync && f->d.threadPool()) {
pool = f->d.threadPool();
- p.setThreadPool(pool);
+ fi.setThreadPool(pool);
}
}
- Continuation<Function, ResultType, ParentResultType> *continuationJob = nullptr;
- if (launchAsync) {
- continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
- std::forward<Function>(func), *f, p, pool);
- } else {
- continuationJob = new SyncContinuation<Function, ResultType, ParentResultType>(
- std::forward<Function>(func), *f, p);
- }
-
- p.setLaunchAsync(launchAsync);
+ fi.setLaunchAsync(launchAsync);
+
+ auto continuation = [func = std::forward<F>(func), fi, promise_ = QPromise(fi), pool,
+ launchAsync](const QFutureInterfaceBase &parentData) mutable {
+ const auto parent = QFutureInterface<ParentResultType>(parentData).future();
+ Continuation<Function, ResultType, ParentResultType> *continuationJob = nullptr;
+ if (launchAsync) {
+ auto asyncJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
+ std::forward<Function>(func), parent, std::move(promise_), pool);
+ fi.setRunnable(asyncJob);
+ continuationJob = asyncJob;
+ } else {
+ continuationJob = new SyncContinuation<Function, ResultType, ParentResultType>(
+ std::forward<Function>(func), parent, std::move(promise_));
+ }
- auto continuation = [continuationJob, launchAsync]() mutable {
bool isLaunched = continuationJob->execute();
// If continuation is successfully launched, AsyncContinuation will be deleted
// by the QThreadPool which has started it. Synchronous continuation will be
@@ -432,24 +558,26 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
continuationJob = nullptr;
}
};
-
- f->d.setContinuation(std::move(continuation));
+ f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d);
}
template<typename Function, typename ResultType, typename ParentResultType>
-void Continuation<Function, ResultType, ParentResultType>::create(Function &&func,
+template<typename F>
+void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
QFuture<ParentResultType> *f,
- QFutureInterface<ResultType> &p,
+ QFutureInterface<ResultType> &fi,
QThreadPool *pool)
{
Q_ASSERT(f);
- auto continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
- std::forward<Function>(func), *f, p, pool);
- p.setLaunchAsync(true);
- p.setThreadPool(pool);
+ fi.setLaunchAsync(true);
+ fi.setThreadPool(pool);
- auto continuation = [continuationJob]() mutable {
+ auto continuation = [func = std::forward<F>(func), promise_ = QPromise(fi),
+ pool](const QFutureInterfaceBase &parentData) mutable {
+ const auto parent = QFutureInterface<ParentResultType>(parentData).future();
+ auto continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
+ std::forward<Function>(func), parent, std::move(promise_), pool);
bool isLaunched = continuationJob->execute();
// If continuation is successfully launched, AsyncContinuation will be deleted
// by the QThreadPool which has started it.
@@ -458,8 +586,39 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
continuationJob = nullptr;
}
};
+ f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d);
+}
+
+template <typename Continuation>
+void watchContinuation(const QObject *context, Continuation &&c, QFutureInterfaceBase &fi)
+{
+ using Prototype = typename QtPrivate::Callable<Continuation>::Function;
+ watchContinuationImpl(context,
+ QtPrivate::makeCallableObject<Prototype>(std::forward<Continuation>(c)),
+ fi);
+}
+
+template<typename Function, typename ResultType, typename ParentResultType>
+template<typename F>
+void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
+ QFuture<ParentResultType> *f,
+ QFutureInterface<ResultType> &fi,
+ QObject *context)
+{
+ Q_ASSERT(f);
+ Q_ASSERT(context);
+
+ // When the context object is destroyed, the signal-slot connection is broken and the
+ // continuation callback is destroyed. The promise that is created in the capture list is
+ // destroyed and, if it is not yet finished, cancelled.
+ auto continuation = [func = std::forward<F>(func), parent = *f,
+ promise_ = QPromise(fi)]() mutable {
+ SyncContinuation<Function, ResultType, ParentResultType> continuationJob(
+ std::forward<Function>(func), parent, std::move(promise_));
+ continuationJob.execute();
+ };
- f->d.setContinuation(continuation);
+ QtPrivate::watchContinuation(context, std::move(continuation), f->d);
}
template<typename Function, typename ResultType, typename ParentResultType>
@@ -493,51 +652,65 @@ template<typename Function, typename ResultType, typename ParentResultType>
template<class... Args>
void Continuation<Function, ResultType, ParentResultType>::fulfillPromise(Args &&... args)
{
- if constexpr (std::is_copy_constructible_v<ResultType>)
- promise.reportResult(std::invoke(function, std::forward<Args>(args)...));
- else
- promise.reportAndMoveResult(std::invoke(function, std::forward<Args>(args)...));
+ promise.addResult(std::invoke(function, std::forward<Args>(args)...));
}
template<class T>
-void fulfillPromise(QFutureInterface<T> &promise, QFuture<T> &future)
+void fulfillPromise(QPromise<T> &promise, QFuture<T> &future)
{
if constexpr (!std::is_void_v<T>) {
if constexpr (std::is_copy_constructible_v<T>)
- promise.reportResult(future.result());
+ promise.addResult(future.result());
else
- promise.reportAndMoveResult(future.takeResult());
+ promise.addResult(future.takeResult());
}
}
template<class T, class Function>
-void fulfillPromise(QFutureInterface<T> &promise, Function &&handler)
+void fulfillPromise(QPromise<T> &promise, Function &&handler)
{
if constexpr (std::is_void_v<T>)
handler();
- else if constexpr (std::is_copy_constructible_v<T>)
- promise.reportResult(handler());
else
- promise.reportAndMoveResult(handler());
+ promise.addResult(handler());
}
#ifndef QT_NO_EXCEPTIONS
template<class Function, class ResultType>
-void FailureHandler<Function, ResultType>::create(Function &&function, QFuture<ResultType> *future,
- const QFutureInterface<ResultType> &promise)
+template<class F>
+void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
+ const QFutureInterface<ResultType> &fi)
{
Q_ASSERT(future);
- FailureHandler<Function, ResultType> *failureHandler = new FailureHandler<Function, ResultType>(
- std::forward<Function>(function), *future, promise);
+ auto failureContinuation = [function = std::forward<F>(function), promise_ = QPromise(fi)](
+ const QFutureInterfaceBase &parentData) mutable {
+ const auto parent = QFutureInterface<ResultType>(parentData).future();
+ FailureHandler<Function, ResultType> failureHandler(std::forward<Function>(function),
+ parent, std::move(promise_));
+ failureHandler.run();
+ };
- auto failureContinuation = [failureHandler]() mutable {
- failureHandler->run();
- delete failureHandler;
+ future->d.setContinuation(ContinuationWrapper(std::move(failureContinuation)));
+}
+
+template<class Function, class ResultType>
+template<class F>
+void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
+ QFutureInterface<ResultType> &fi,
+ QObject *context)
+{
+ Q_ASSERT(future);
+ Q_ASSERT(context);
+ auto failureContinuation = [function = std::forward<F>(function),
+ parent = *future, promise_ = QPromise(fi)]() mutable {
+ FailureHandler<Function, ResultType> failureHandler(
+ std::forward<Function>(function), parent, std::move(promise_));
+ failureHandler.run();
};
- future->d.setContinuation(std::move(failureContinuation));
+ QtPrivate::watchContinuation(context, std::move(failureContinuation), future->d);
}
template<class Function, class ResultType>
@@ -545,19 +718,21 @@ void FailureHandler<Function, ResultType>::run()
{
Q_ASSERT(parentFuture.isFinished());
- promise.reportStarted();
+ promise.start();
- if (parentFuture.d.exceptionStore().hasException()) {
+ if (parentFuture.d.hasException()) {
using ArgType = typename QtPrivate::ArgResolver<Function>::First;
if constexpr (std::is_void_v<ArgType>) {
handleAllExceptions();
} else {
handleException<ArgType>();
}
+ } else if (parentFuture.d.isChainCanceled()) {
+ promise.future().cancel();
} else {
QtPrivate::fulfillPromise(promise, parentFuture);
}
- promise.reportFinished();
+ promise.finish();
}
template<class Function, class ResultType>
@@ -565,25 +740,22 @@ template<class ArgType>
void FailureHandler<Function, ResultType>::handleException()
{
try {
- parentFuture.d.exceptionStore().throwPossibleException();
+ Q_ASSERT(parentFuture.d.hasException());
+ parentFuture.d.exceptionStore().rethrowException();
} catch (const ArgType &e) {
try {
// Handle exceptions matching with the handler's argument type
- if constexpr (std::is_void_v<ResultType>) {
+ if constexpr (std::is_void_v<ResultType>)
handler(e);
- } else {
- if constexpr (std::is_copy_constructible_v<ResultType>)
- promise.reportResult(handler(e));
- else
- promise.reportAndMoveResult(handler(e));
- }
+ else
+ promise.addResult(handler(e));
} catch (...) {
- promise.reportException(std::current_exception());
+ promise.setException(std::current_exception());
}
} catch (...) {
// Exception doesn't match with handler's argument type, propagate
// the exception to be handled later.
- promise.reportException(std::current_exception());
+ promise.setException(std::current_exception());
}
}
@@ -591,12 +763,13 @@ template<class Function, class ResultType>
void FailureHandler<Function, ResultType>::handleAllExceptions()
{
try {
- parentFuture.d.exceptionStore().throwPossibleException();
+ Q_ASSERT(parentFuture.d.hasException());
+ parentFuture.d.exceptionStore().rethrowException();
} catch (...) {
try {
QtPrivate::fulfillPromise(promise, std::forward<Function>(handler));
} catch (...) {
- promise.reportException(std::current_exception());
+ promise.setException(std::current_exception());
}
}
}
@@ -607,41 +780,124 @@ template<class Function, class ResultType>
class CanceledHandler
{
public:
- static QFuture<ResultType> create(Function &&handler, QFuture<ResultType> *future,
- QFutureInterface<ResultType> promise)
+ template<class F = Function>
+ static void create(F &&handler, QFuture<ResultType> *future, QFutureInterface<ResultType> &fi)
{
Q_ASSERT(future);
- auto canceledContinuation = [parentFuture = *future, promise,
- handler = std::move(handler)]() mutable {
- promise.reportStarted();
+ auto canceledContinuation = [promise = QPromise(fi), handler = std::forward<F>(handler)](
+ const QFutureInterfaceBase &parentData) mutable {
+ auto parentFuture = QFutureInterface<ResultType>(parentData).future();
+ run(std::forward<F>(handler), parentFuture, std::move(promise));
+ };
+ future->d.setContinuation(ContinuationWrapper(std::move(canceledContinuation)));
+ }
- if (parentFuture.isCanceled()) {
+ template<class F = Function>
+ static void create(F &&handler, QFuture<ResultType> *future, QFutureInterface<ResultType> &fi,
+ QObject *context)
+ {
+ Q_ASSERT(future);
+ Q_ASSERT(context);
+ auto canceledContinuation = [handler = std::forward<F>(handler),
+ parentFuture = *future, promise = QPromise(fi)]() mutable {
+ run(std::forward<F>(handler), parentFuture, std::move(promise));
+ };
+
+ QtPrivate::watchContinuation(context, std::move(canceledContinuation), future->d);
+ }
+
+ template<class F = Function>
+ static void run(F &&handler, QFuture<ResultType> &parentFuture, QPromise<ResultType> &&promise)
+ {
+ promise.start();
+
+ if (parentFuture.isCanceled()) {
#ifndef QT_NO_EXCEPTIONS
- if (parentFuture.d.exceptionStore().hasException()) {
- // Propagate the exception to the result future
- promise.reportException(parentFuture.d.exceptionStore().exception());
- } else {
- try {
+ if (parentFuture.d.hasException()) {
+ // Propagate the exception to the result future
+ promise.setException(parentFuture.d.exceptionStore().exception());
+ } else {
+ try {
#endif
- QtPrivate::fulfillPromise(promise, std::forward<Function>(handler));
+ QtPrivate::fulfillPromise(promise, std::forward<F>(handler));
#ifndef QT_NO_EXCEPTIONS
- } catch (...) {
- promise.reportException(std::current_exception());
- }
+ } catch (...) {
+ promise.setException(std::current_exception());
}
+ }
#endif
- } else {
- QtPrivate::fulfillPromise(promise, parentFuture);
+ } else {
+ QtPrivate::fulfillPromise(promise, parentFuture);
+ }
+
+ promise.finish();
+ }
+};
+
+struct UnwrapHandler
+{
+ template<class T>
+ static auto unwrapImpl(T *outer)
+ {
+ Q_ASSERT(outer);
+
+ using ResultType = typename QtPrivate::Future<std::decay_t<T>>::type;
+ using NestedType = typename QtPrivate::Future<ResultType>::type;
+ QFutureInterface<NestedType> promise(QFutureInterfaceBase::State::Pending);
+
+ outer->then([promise](const QFuture<ResultType> &outerFuture) mutable {
+ // We use the .then([](QFuture<ResultType> outerFuture) {...}) version
+ // (where outerFuture == *outer), to propagate the exception if the
+ // outer future has failed.
+ Q_ASSERT(outerFuture.isFinished());
+#ifndef QT_NO_EXCEPTIONS
+ if (outerFuture.d.hasException()) {
+ promise.reportStarted();
+ promise.reportException(outerFuture.d.exceptionStore().exception());
+ promise.reportFinished();
+ return;
}
+#endif
+
+ promise.reportStarted();
+ ResultType nestedFuture = outerFuture.result();
+ nestedFuture.then([promise] (const QFuture<NestedType> &nested) mutable {
+#ifndef QT_NO_EXCEPTIONS
+ if (nested.d.hasException()) {
+ promise.reportException(nested.d.exceptionStore().exception());
+ } else
+#endif
+ {
+ if constexpr (!std::is_void_v<NestedType>)
+ promise.reportResults(nested.results());
+ }
+ promise.reportFinished();
+ }).onCanceled([promise] () mutable {
+ promise.reportCanceled();
+ promise.reportFinished();
+ });
+ }).onCanceled([promise]() mutable {
+ // propagate the cancellation of the outer future
+ promise.reportStarted();
+ promise.reportCanceled();
promise.reportFinished();
- };
- future->d.setContinuation(std::move(canceledContinuation));
+ });
return promise.future();
}
};
+template<typename ValueType>
+QFuture<ValueType> makeReadyRangeFutureImpl(const QList<ValueType> &values)
+{
+ QFutureInterface<ValueType> promise;
+ promise.reportStarted();
+ promise.reportResults(values);
+ promise.reportFinished();
+ return promise.future();
+}
+
} // namespace QtPrivate
namespace QtFuture {
@@ -655,6 +911,11 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
using ArgsType = ArgsType<Signal>;
QFutureInterface<ArgsType> promise;
promise.reportStarted();
+ if (!sender) {
+ promise.reportCanceled();
+ promise.reportFinished();
+ return promise.future();
+ }
using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
auto connections = std::make_shared<Connections>();
@@ -662,39 +923,280 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
if constexpr (std::is_void_v<ArgsType>) {
connections->first =
QObject::connect(sender, signal, sender, [promise, connections]() mutable {
- promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
+ promise.reportFinished();
});
- } else if constexpr (QtPrivate::isTupleV<ArgsType>) {
+ } else if constexpr (QtPrivate::ArgResolver<Signal>::HasExtraArgs) {
connections->first = QObject::connect(sender, signal, sender,
[promise, connections](auto... values) mutable {
- promise.reportResult(std::make_tuple(values...));
- promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
+ promise.reportResult(QtPrivate::createTuple(
+ std::move(values)...));
+ promise.reportFinished();
});
} else {
connections->first = QObject::connect(sender, signal, sender,
[promise, connections](ArgsType value) mutable {
- promise.reportResult(value);
- promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
+ promise.reportResult(value);
+ promise.reportFinished();
});
}
+ if (!connections->first) {
+ promise.reportCanceled();
+ promise.reportFinished();
+ return promise.future();
+ }
+
connections->second =
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
- promise.reportCanceled();
- promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
+ promise.reportCanceled();
+ promise.reportFinished();
});
return promise.future();
}
+template<typename Container>
+using if_container_with_input_iterators =
+ std::enable_if_t<QtPrivate::HasInputIterator<Container>::value, bool>;
+
+template<typename Container>
+using ContainedType =
+ typename std::iterator_traits<decltype(
+ std::cbegin(std::declval<Container&>()))>::value_type;
+
+template<typename Container, if_container_with_input_iterators<Container> = true>
+static QFuture<ContainedType<Container>> makeReadyRangeFuture(Container &&container)
+{
+ // handle QList<T> separately, because reportResults() takes a QList
+ // as an input
+ using ValueType = ContainedType<Container>;
+ if constexpr (std::is_convertible_v<q20::remove_cvref_t<Container>, QList<ValueType>>) {
+ return QtPrivate::makeReadyRangeFutureImpl(container);
+ } else {
+ return QtPrivate::makeReadyRangeFutureImpl(QList<ValueType>{std::cbegin(container),
+ std::cend(container)});
+ }
+}
+
+template<typename ValueType>
+static QFuture<ValueType> makeReadyRangeFuture(std::initializer_list<ValueType> values)
+{
+ return QtPrivate::makeReadyRangeFutureImpl(QList<ValueType>{values});
+}
+
+template<typename T>
+static QFuture<std::decay_t<T>> makeReadyValueFuture(T &&value)
+{
+ QFutureInterface<std::decay_t<T>> promise;
+ promise.reportStarted();
+ promise.reportResult(std::forward<T>(value));
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+Q_CORE_EXPORT QFuture<void> makeReadyVoidFuture(); // implemented in qfutureinterface.cpp
+
+#if QT_DEPRECATED_SINCE(6, 10)
+template<typename T, typename = QtPrivate::EnableForNonVoid<T>>
+QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyValueFuture() instead.")
+static QFuture<std::decay_t<T>> makeReadyFuture(T &&value)
+{
+ return makeReadyValueFuture(std::forward<T>(value));
+}
+
+// the void specialization is moved to the end of qfuture.h, because it now
+// uses makeReadyVoidFuture() and required QFuture<void> to be defined.
+
+template<typename T>
+QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyRangeFuture() instead.")
+static QFuture<T> makeReadyFuture(const QList<T> &values)
+{
+ return makeReadyRangeFuture(values);
+}
+#endif // QT_DEPRECATED_SINCE(6, 10)
+
+#ifndef QT_NO_EXCEPTIONS
+
+template<typename T = void>
+static QFuture<T> makeExceptionalFuture(std::exception_ptr exception)
+{
+ QFutureInterface<T> promise;
+ promise.reportStarted();
+ promise.reportException(exception);
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+template<typename T = void>
+static QFuture<T> makeExceptionalFuture(const QException &exception)
+{
+ try {
+ exception.raise();
+ } catch (...) {
+ return makeExceptionalFuture<T>(std::current_exception());
+ }
+ Q_UNREACHABLE();
+}
+
+#endif // QT_NO_EXCEPTIONS
+
} // namespace QtFuture
+namespace QtPrivate {
+
+template<typename ResultFutures>
+struct WhenAllContext
+{
+ using ValueType = typename ResultFutures::value_type;
+
+ explicit WhenAllContext(qsizetype size) : remaining(size) {}
+
+ template<typename T = ValueType>
+ void checkForCompletion(qsizetype index, T &&future)
+ {
+ futures[index] = std::forward<T>(future);
+ const auto oldRemaining = remaining.fetchAndSubRelaxed(1);
+ Q_ASSERT(oldRemaining > 0);
+ if (oldRemaining <= 1) { // that was the last one
+ promise.addResult(futures);
+ promise.finish();
+ }
+ }
+
+ QAtomicInteger<qsizetype> remaining;
+ QPromise<ResultFutures> promise;
+ ResultFutures futures;
+};
+
+template<typename ResultType>
+struct WhenAnyContext
+{
+ using ValueType = ResultType;
+
+ template<typename T = ResultType, typename = EnableForNonVoid<T>>
+ void checkForCompletion(qsizetype, T &&result)
+ {
+ if (!ready.fetchAndStoreRelaxed(true)) {
+ promise.addResult(std::forward<T>(result));
+ promise.finish();
+ }
+ }
+
+ QAtomicInt ready = false;
+ QPromise<ResultType> promise;
+};
+
+template<qsizetype Index, typename ContextType, typename... Ts>
+void addCompletionHandlersImpl(const std::shared_ptr<ContextType> &context,
+ const std::tuple<Ts...> &t)
+{
+ auto future = std::get<Index>(t);
+ using ResultType = typename ContextType::ValueType;
+ // Need context=context so that the compiler does not infer the captured variable's type as 'const'
+ future.then([context=context](const std::tuple_element_t<Index, std::tuple<Ts...>> &f) {
+ context->checkForCompletion(Index, ResultType { std::in_place_index<Index>, f });
+ }).onCanceled([context=context, future]() {
+ context->checkForCompletion(Index, ResultType { std::in_place_index<Index>, future });
+ });
+
+ if constexpr (Index != 0)
+ addCompletionHandlersImpl<Index - 1, ContextType, Ts...>(context, t);
+}
+
+template<typename ContextType, typename... Ts>
+void addCompletionHandlers(const std::shared_ptr<ContextType> &context, const std::tuple<Ts...> &t)
+{
+ constexpr qsizetype size = std::tuple_size<std::tuple<Ts...>>::value;
+ addCompletionHandlersImpl<size - 1, ContextType, Ts...>(context, t);
+}
+
+template<typename OutputSequence, typename InputIt, typename ValueType>
+QFuture<OutputSequence> whenAllImpl(InputIt first, InputIt last)
+{
+ const qsizetype size = std::distance(first, last);
+ if (size == 0)
+ return QtFuture::makeReadyValueFuture(OutputSequence());
+
+ const auto context = std::make_shared<QtPrivate::WhenAllContext<OutputSequence>>(size);
+ context->futures.resize(size);
+ context->promise.start();
+
+ qsizetype idx = 0;
+ for (auto it = first; it != last; ++it, ++idx) {
+ // Need context=context so that the compiler does not infer the captured variable's type as 'const'
+ it->then([context=context, idx](const ValueType &f) {
+ context->checkForCompletion(idx, f);
+ }).onCanceled([context=context, idx, f = *it] {
+ context->checkForCompletion(idx, f);
+ });
+ }
+ return context->promise.future();
+}
+
+template<typename OutputSequence, typename... Futures>
+QFuture<OutputSequence> whenAllImpl(Futures &&... futures)
+{
+ constexpr qsizetype size = sizeof...(Futures);
+ const auto context = std::make_shared<QtPrivate::WhenAllContext<OutputSequence>>(size);
+ context->futures.resize(size);
+ context->promise.start();
+
+ QtPrivate::addCompletionHandlers(context, std::make_tuple(std::forward<Futures>(futures)...));
+
+ return context->promise.future();
+}
+
+template<typename InputIt, typename ValueType>
+QFuture<QtFuture::WhenAnyResult<typename Future<ValueType>::type>> whenAnyImpl(InputIt first,
+ InputIt last)
+{
+ using PackagedType = typename Future<ValueType>::type;
+ using ResultType = QtFuture::WhenAnyResult<PackagedType>;
+
+ const qsizetype size = std::distance(first, last);
+ if (size == 0) {
+ return QtFuture::makeReadyValueFuture(
+ QtFuture::WhenAnyResult { qsizetype(-1), QFuture<PackagedType>() });
+ }
+
+ const auto context = std::make_shared<QtPrivate::WhenAnyContext<ResultType>>();
+ context->promise.start();
+
+ qsizetype idx = 0;
+ for (auto it = first; it != last; ++it, ++idx) {
+ // Need context=context so that the compiler does not infer the captured variable's type as 'const'
+ it->then([context=context, idx](const ValueType &f) {
+ context->checkForCompletion(idx, QtFuture::WhenAnyResult { idx, f });
+ }).onCanceled([context=context, idx, f = *it] {
+ context->checkForCompletion(idx, QtFuture::WhenAnyResult { idx, f });
+ });
+ }
+ return context->promise.future();
+}
+
+template<typename... Futures>
+QFuture<std::variant<std::decay_t<Futures>...>> whenAnyImpl(Futures &&... futures)
+{
+ using ResultType = std::variant<std::decay_t<Futures>...>;
+
+ const auto context = std::make_shared<QtPrivate::WhenAnyContext<ResultType>>();
+ context->promise.start();
+
+ QtPrivate::addCompletionHandlers(context, std::make_tuple(std::forward<Futures>(futures)...));
+
+ return context->promise.future();
+}
+
+} // namespace QtPrivate
+
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index 1785815cf3..f83306af00 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -1,53 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// qfutureinterface.h included from qfuture.h
#include "qfuture.h"
#include "qfutureinterface_p.h"
#include <QtCore/qatomic.h>
+#include <QtCore/qcoreapplication.h>
#include <QtCore/qthread.h>
+#include <QtCore/qvarlengtharray.h>
#include <private/qthreadpool_p.h>
+#include <private/qobject_p.h>
-#ifdef interface
-# undef interface
-#endif
+// GCC 12 gets confused about QFutureInterfaceBase::state, for some non-obvious
+// reason
+// warning: ‘unsigned int __atomic_or_fetch_4(volatile void*, unsigned int, int)’ writing 4 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
+QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
QT_BEGIN_NAMESPACE
@@ -59,6 +27,7 @@ namespace {
class ThreadPoolThreadReleaser {
QThreadPool *m_pool;
public:
+ Q_NODISCARD_CTOR
explicit ThreadPoolThreadReleaser(QThreadPool *pool)
: m_pool(pool)
{ if (pool) pool->releaseThread(); }
@@ -71,6 +40,67 @@ const auto suspendingOrSuspended =
} // unnamed namespace
+class QObjectContinuationWrapper : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QObjectContinuationWrapper(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ }
+
+signals:
+ void run();
+};
+
+void QtPrivate::watchContinuationImpl(const QObject *context, QSlotObjectBase *slotObj,
+ QFutureInterfaceBase &fi)
+{
+ Q_ASSERT(context);
+ Q_ASSERT(slotObj);
+
+ auto slot = SlotObjUniquePtr(slotObj);
+
+ auto *watcher = new QObjectContinuationWrapper;
+ watcher->moveToThread(context->thread());
+
+ // We need to protect acccess to the watcher. The context object (and in turn, the watcher)
+ // could be destroyed while the continuation that emits the signal is running. We have to
+ // prevent that.
+ // The mutex has to be recursive, because the continuation itself could delete the context
+ // object (and thus the watcher), which will try to lock the mutex from the same thread twice.
+ auto watcherMutex = std::make_shared<QRecursiveMutex>();
+ const auto destroyWatcher = [watcherMutex, watcher]() mutable {
+ QMutexLocker lock(watcherMutex.get());
+ delete watcher;
+ };
+
+ // ### we're missing a convenient way to `QObject::connect()` to a `QSlotObjectBase`...
+ QObject::connect(watcher, &QObjectContinuationWrapper::run,
+ // for the following, cf. QMetaObject::invokeMethodImpl():
+ // we know `slot` is a lambda returning `void`, so we can just
+ // `call()` with `obj` and `args[0]` set to `nullptr`:
+ context, [slot = std::move(slot)] {
+ void *args[] = { nullptr }; // for `void` return value
+ slot->call(nullptr, args);
+ });
+ QObject::connect(watcher, &QObjectContinuationWrapper::run, watcher, &QObject::deleteLater);
+ QObject::connect(context, &QObject::destroyed, watcher, destroyWatcher);
+
+ fi.setContinuation([watcherMutex, watcher = QPointer(watcher)]
+ (const QFutureInterfaceBase &parentData)
+ {
+ Q_UNUSED(parentData);
+ QMutexLocker lock(watcherMutex.get());
+ if (watcher)
+ emit watcher->run();
+ });
+}
+
+QFutureCallOutInterface::~QFutureCallOutInterface()
+ = default;
+
+Q_IMPL_EVENT_COMMON(QFutureCallOutEvent)
QFutureInterfaceBase::QFutureInterfaceBase(State initialState)
: d(new QFutureInterfaceBasePrivate(initialState))
@@ -84,7 +114,7 @@ QFutureInterfaceBase::QFutureInterfaceBase(const QFutureInterfaceBase &other)
QFutureInterfaceBase::~QFutureInterfaceBase()
{
- if (!d->refCount.deref())
+ if (d && !d->refCount.deref())
delete d;
}
@@ -100,24 +130,52 @@ static inline int switch_off(QAtomicInt &a, int which)
static inline int switch_from_to(QAtomicInt &a, int from, int to)
{
- int newValue;
- int expected = a.loadRelaxed();
- do {
- newValue = (expected & ~from) | to;
- } while (!a.testAndSetRelaxed(expected, newValue, expected));
- return newValue;
+ const auto adjusted = [&](int old) { return (old & ~from) | to; };
+ int value = a.loadRelaxed();
+ while (!a.testAndSetRelaxed(value, adjusted(value), value))
+ qYieldCpu();
+ return value;
}
void QFutureInterfaceBase::cancel()
{
+ cancel(CancelMode::CancelOnly);
+}
+
+void QFutureInterfaceBase::cancel(QFutureInterfaceBase::CancelMode mode)
+{
QMutexLocker locker(&d->m_mutex);
- if (d->state.loadRelaxed() & Canceled)
- return;
- switch_from_to(d->state, suspendingOrSuspended, Canceled);
+ const auto oldState = d->state.loadRelaxed();
+
+ switch (mode) {
+ case CancelMode::CancelAndFinish:
+ if ((oldState & Finished) && (oldState & Canceled))
+ return;
+ switch_from_to(d->state, suspendingOrSuspended | Running, Canceled | Finished);
+ break;
+ case CancelMode::CancelOnly:
+ if (oldState & Canceled)
+ return;
+ switch_from_to(d->state, suspendingOrSuspended, Canceled);
+ break;
+ }
+
+ // Cancel the continuations chain
+ QFutureInterfaceBasePrivate *next = d->continuationData;
+ while (next) {
+ next->continuationState = QFutureInterfaceBasePrivate::Canceled;
+ next = next->continuationData;
+ }
+
d->waitCondition.wakeAll();
d->pausedWaitCondition.wakeAll();
- d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+
+ if (!(oldState & Canceled))
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+ if (mode == CancelMode::CancelAndFinish && !(oldState & Finished))
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
+
d->isValid = false;
}
@@ -153,7 +211,7 @@ void QFutureInterfaceBase::reportSuspended() const
// i.e. no more events will be reported.
QMutexLocker locker(&d->m_mutex);
- const int state = d->state;
+ const int state = d->state.loadRelaxed();
if (!(state & Suspending) || (state & Suspended))
return;
@@ -299,13 +357,13 @@ int QFutureInterfaceBase::progressValue() const
int QFutureInterfaceBase::progressMinimum() const
{
const QMutexLocker lock(&d->m_mutex);
- return d->m_progressMinimum;
+ return d->m_progress ? d->m_progress->minimum : 0;
}
int QFutureInterfaceBase::progressMaximum() const
{
const QMutexLocker lock(&d->m_mutex);
- return d->m_progressMaximum;
+ return d->m_progress ? d->m_progress->maximum : 0;
}
int QFutureInterfaceBase::resultCount() const
@@ -317,7 +375,7 @@ int QFutureInterfaceBase::resultCount() const
QString QFutureInterfaceBase::progressText() const
{
QMutexLocker locker(&d->m_mutex);
- return d->m_progressText;
+ return d->m_progress ? d->m_progress->text : QString();
}
bool QFutureInterfaceBase::isProgressUpdateNeeded() const
@@ -351,13 +409,18 @@ void QFutureInterfaceBase::reportException(const QException &exception)
}
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
void QFutureInterfaceBase::reportException(std::exception_ptr exception)
+#else
+void QFutureInterfaceBase::reportException(const std::exception_ptr &exception)
+#endif
{
QMutexLocker locker(&d->m_mutex);
if (d->state.loadRelaxed() & (Canceled|Finished))
return;
- d->m_exceptionStore.setException(exception);
+ d->hasException = true;
+ d->data.setException(exception);
switch_on(d->state, Canceled);
d->waitCondition.wakeAll();
d->pausedWaitCondition.wakeAll();
@@ -377,7 +440,7 @@ void QFutureInterfaceBase::reportFinished()
void QFutureInterfaceBase::setExpectedResultCount(int resultCount)
{
- if (d->manualProgress == false)
+ if (d->m_progress)
setProgressRange(0, resultCount);
d->m_expectedResultCount = resultCount;
}
@@ -394,12 +457,16 @@ bool QFutureInterfaceBase::queryState(State state) const
int QFutureInterfaceBase::loadState() const
{
+ // Used from ~QPromise, so this check is needed
+ if (!d)
+ return QFutureInterfaceBase::State::NoState;
return d->state.loadRelaxed();
}
void QFutureInterfaceBase::waitForResult(int resultIndex)
{
- d->m_exceptionStore.throwPossibleException();
+ if (d->hasException)
+ d->data.m_exceptionStore.rethrowException();
QMutexLocker lock(&d->m_mutex);
if (!isRunningOrPending())
@@ -416,13 +483,14 @@ void QFutureInterfaceBase::waitForResult(int resultIndex)
while (isRunningOrPending() && !d->internal_isResultReadyAt(waitIndex))
d->waitCondition.wait(&d->m_mutex);
- d->m_exceptionStore.throwPossibleException();
+ if (d->hasException)
+ d->data.m_exceptionStore.rethrowException();
}
void QFutureInterfaceBase::waitForFinished()
{
QMutexLocker lock(&d->m_mutex);
- const bool alreadyFinished = !isRunningOrPending();
+ const bool alreadyFinished = isFinished();
lock.unlock();
if (!alreadyFinished) {
@@ -430,11 +498,12 @@ void QFutureInterfaceBase::waitForFinished()
lock.relock();
- while (isRunningOrPending())
+ while (!isFinished())
d->waitCondition.wait(&d->m_mutex);
}
- d->m_exceptionStore.throwPossibleException();
+ if (d->hasException)
+ d->data.m_exceptionStore.rethrowException();
}
void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
@@ -444,8 +513,8 @@ void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
d->waitCondition.wakeAll();
- if (d->manualProgress == false) {
- if (d->internal_updateProgress(d->m_progressValue + endIndex - beginIndex) == false) {
+ if (!d->m_progress) {
+ if (d->internal_updateProgressValue(d->m_progressValue + endIndex - beginIndex) == false) {
d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
beginIndex,
endIndex));
@@ -454,7 +523,7 @@ void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
d->sendCallOuts(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
d->m_progressValue,
- d->m_progressText),
+ QString()),
QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
beginIndex,
endIndex));
@@ -481,15 +550,35 @@ QThreadPool *QFutureInterfaceBase::threadPool() const
void QFutureInterfaceBase::setFilterMode(bool enable)
{
QMutexLocker locker(&d->m_mutex);
- resultStoreBase().setFilterMode(enable);
+ if (!hasException())
+ resultStoreBase().setFilterMode(enable);
}
+/*!
+ \internal
+ Sets the progress range's minimum and maximum values to \a minimum and
+ \a maximum respectively.
+
+ If \a maximum is smaller than \a minimum, \a minimum becomes the only
+ legal value.
+
+ The progress value is reset to be \a minimum.
+
+ The progress range usage can be disabled by using setProgressRange(0, 0).
+ In this case progress value is also reset to 0.
+
+ The behavior of this method is mostly inspired by
+ \l QProgressBar::setRange.
+*/
void QFutureInterfaceBase::setProgressRange(int minimum, int maximum)
{
QMutexLocker locker(&d->m_mutex);
- d->m_progressMinimum = minimum;
- d->m_progressMaximum = maximum;
+ if (!d->m_progress)
+ d->m_progress.reset(new QFutureInterfaceBasePrivate::ProgressData());
+ d->m_progress->minimum = minimum;
+ d->m_progress->maximum = qMax(minimum, maximum);
d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange, minimum, maximum));
+ d->m_progressValue = minimum;
}
void QFutureInterfaceBase::setProgressValue(int progressValue)
@@ -497,12 +586,25 @@ void QFutureInterfaceBase::setProgressValue(int progressValue)
setProgressValueAndText(progressValue, QString());
}
+/*!
+ \internal
+ In case of the \a progressValue falling out of the progress range,
+ this method has no effect.
+ Such behavior is inspired by \l QProgressBar::setValue.
+*/
void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
const QString &progressText)
{
QMutexLocker locker(&d->m_mutex);
- if (d->manualProgress == false)
- d->manualProgress = true;
+ if (!d->m_progress)
+ d->m_progress.reset(new QFutureInterfaceBasePrivate::ProgressData());
+
+ const bool useProgressRange = (d->m_progress->maximum != 0) || (d->m_progress->minimum != 0);
+ if (useProgressRange
+ && ((progressValue < d->m_progress->minimum) || (progressValue > d->m_progress->maximum))) {
+ return;
+ }
+
if (d->m_progressValue >= progressValue)
return;
@@ -512,7 +614,7 @@ void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
if (d->internal_updateProgress(progressValue, progressText)) {
d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
d->m_progressValue,
- d->m_progressText));
+ d->m_progress->text));
}
}
@@ -521,77 +623,121 @@ QMutex &QFutureInterfaceBase::mutex() const
return d->m_mutex;
}
+bool QFutureInterfaceBase::hasException() const
+{
+ return d->hasException;
+}
+
QtPrivate::ExceptionStore &QFutureInterfaceBase::exceptionStore()
{
- return d->m_exceptionStore;
+ Q_ASSERT(d->hasException);
+ return d->data.m_exceptionStore;
}
QtPrivate::ResultStoreBase &QFutureInterfaceBase::resultStoreBase()
{
- return d->m_results;
+ Q_ASSERT(!d->hasException);
+ return d->data.m_results;
}
const QtPrivate::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const
{
- return d->m_results;
+ Q_ASSERT(!d->hasException);
+ return d->data.m_results;
}
QFutureInterfaceBase &QFutureInterfaceBase::operator=(const QFutureInterfaceBase &other)
{
- other.d->refCount.ref();
- if (!d->refCount.deref())
- delete d;
- d = other.d;
+ QFutureInterfaceBase copy(other);
+ swap(copy);
return *this;
}
-bool QFutureInterfaceBase::refT() const
+// ### Qt 7: inline
+void QFutureInterfaceBase::swap(QFutureInterfaceBase &other) noexcept
+{
+ qSwap(d, other.d);
+}
+
+bool QFutureInterfaceBase::refT() const noexcept
{
return d->refCount.refT();
}
-bool QFutureInterfaceBase::derefT() const
+bool QFutureInterfaceBase::derefT() const noexcept
{
- return d->refCount.derefT();
+ // Called from ~QFutureInterface
+ return !d || d->refCount.derefT();
}
void QFutureInterfaceBase::reset()
{
d->m_progressValue = 0;
- d->m_progressMinimum = 0;
- d->m_progressMaximum = 0;
- d->setState(QFutureInterfaceBase::NoState);
+ d->m_progress.reset();
d->progressTime.invalidate();
d->isValid = false;
}
+void QFutureInterfaceBase::rethrowPossibleException()
+{
+ if (hasException())
+ exceptionStore().rethrowException();
+}
+
QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState)
- : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0),
- state(initialState),
- manualProgress(false), m_expectedResultCount(0), runnable(nullptr), m_pool(nullptr)
+ : state(initialState)
{
progressTime.invalidate();
}
+QFutureInterfaceBasePrivate::~QFutureInterfaceBasePrivate()
+{
+ if (hasException)
+ data.m_exceptionStore.~ExceptionStore();
+ else
+ data.m_results.~ResultStoreBase();
+}
+
int QFutureInterfaceBasePrivate::internal_resultCount() const
{
- return m_results.count(); // ### subtract canceled results.
+ return hasException ? 0 : data.m_results.count(); // ### subtract canceled results.
}
bool QFutureInterfaceBasePrivate::internal_isResultReadyAt(int index) const
{
- return (m_results.contains(index));
+ return hasException ? false : (data.m_results.contains(index));
}
bool QFutureInterfaceBasePrivate::internal_waitForNextResult()
{
- if (m_results.hasNextResult())
+ if (hasException)
+ return false;
+
+ if (data.m_results.hasNextResult())
return true;
- while ((state.loadRelaxed() & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
+ while ((state.loadRelaxed() & QFutureInterfaceBase::Running)
+ && data.m_results.hasNextResult() == false)
waitCondition.wait(&m_mutex);
- return !(state.loadRelaxed() & QFutureInterfaceBase::Canceled) && m_results.hasNextResult();
+ return !(state.loadRelaxed() & QFutureInterfaceBase::Canceled)
+ && data.m_results.hasNextResult();
+}
+
+bool QFutureInterfaceBasePrivate::internal_updateProgressValue(int progress)
+{
+ if (m_progressValue >= progress)
+ return false;
+
+ m_progressValue = progress;
+
+ if (progressTime.isValid() && m_progressValue != 0) // make sure the first and last steps are emitted.
+ if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond))
+ return false;
+
+ progressTime.start();
+ return true;
+
}
bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
@@ -600,10 +746,12 @@ bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
if (m_progressValue >= progress)
return false;
+ Q_ASSERT(m_progress);
+
m_progressValue = progress;
- m_progressText = progressText;
+ m_progress->text = progressText;
- if (progressTime.isValid() && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted.
+ if (progressTime.isValid() && m_progressValue != m_progress->maximum) // make sure the first and last steps are emitted.
if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond))
return false;
@@ -633,7 +781,7 @@ void QFutureInterfaceBasePrivate::sendCallOut(const QFutureCallOutEvent &callOut
if (outputConnections.isEmpty())
return;
- for (int i = 0; i < outputConnections.count(); ++i)
+ for (int i = 0; i < outputConnections.size(); ++i)
outputConnections.at(i)->postCallOutEvent(callOutEvent);
}
@@ -643,65 +791,75 @@ void QFutureInterfaceBasePrivate::sendCallOuts(const QFutureCallOutEvent &callOu
if (outputConnections.isEmpty())
return;
- for (int i = 0; i < outputConnections.count(); ++i) {
- QFutureCallOutInterface *interface = outputConnections.at(i);
- interface->postCallOutEvent(callOutEvent1);
- interface->postCallOutEvent(callOutEvent2);
+ for (int i = 0; i < outputConnections.size(); ++i) {
+ QFutureCallOutInterface *iface = outputConnections.at(i);
+ iface->postCallOutEvent(callOutEvent1);
+ iface->postCallOutEvent(callOutEvent2);
}
}
// This function connects an output interface (for example a QFutureWatcher)
// to this future. While holding the lock we check the state and ready results
-// and add the appropriate callouts to the queue. In order to avoid deadlocks,
-// the actual callouts are made at the end while not holding the lock.
-void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface *interface)
+// and add the appropriate callouts to the queue.
+void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface *iface)
{
QMutexLocker locker(&m_mutex);
const auto currentState = state.loadRelaxed();
if (currentState & QFutureInterfaceBase::Started) {
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Started));
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
- m_progressMinimum,
- m_progressMaximum));
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Started));
+ if (m_progress) {
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
+ m_progress->minimum,
+ m_progress->maximum));
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ m_progressValue,
+ m_progress->text));
+ } else {
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
+ 0,
+ 0));
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
m_progressValue,
- m_progressText));
+ QString()));
+ }
}
- QtPrivate::ResultIteratorBase it = m_results.begin();
- while (it != m_results.end()) {
- const int begin = it.resultIndex();
- const int end = begin + it.batchSize();
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ if (!hasException) {
+ QtPrivate::ResultIteratorBase it = data.m_results.begin();
+ while (it != data.m_results.end()) {
+ const int begin = it.resultIndex();
+ const int end = begin + it.batchSize();
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
begin,
end));
- it.batchedAdvance();
+ it.batchedAdvance();
+ }
}
if (currentState & QFutureInterfaceBase::Suspended)
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Suspended));
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Suspended));
else if (currentState & QFutureInterfaceBase::Suspending)
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Suspending));
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Suspending));
if (currentState & QFutureInterfaceBase::Canceled)
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
if (currentState & QFutureInterfaceBase::Finished)
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
+ iface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
- outputConnections.append(interface);
+ outputConnections.append(iface);
}
-void QFutureInterfaceBasePrivate::disconnectOutputInterface(QFutureCallOutInterface *interface)
+void QFutureInterfaceBasePrivate::disconnectOutputInterface(QFutureCallOutInterface *iface)
{
QMutexLocker lock(&m_mutex);
- const int index = outputConnections.indexOf(interface);
+ const qsizetype index = outputConnections.indexOf(iface);
if (index == -1)
return;
outputConnections.removeAt(index);
- interface->callOutInterfaceDisconnected();
+ iface->callOutInterfaceDisconnected();
}
void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
@@ -709,28 +867,72 @@ void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
state.storeRelaxed(newState);
}
-void QFutureInterfaceBase::setContinuation(std::function<void()> func)
+void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInterfaceBase &)> func)
+{
+ setContinuation(std::move(func), nullptr);
+}
+
+void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInterfaceBase &)> func,
+ QFutureInterfaceBasePrivate *continuationFutureData)
{
QMutexLocker lock(&d->continuationMutex);
+
// If the state is ready, run continuation immediately,
// otherwise save it for later.
if (isFinished()) {
lock.unlock();
- func();
- } else {
+ func(*this);
+ lock.relock();
+ }
+ // Unless the continuation has been cleaned earlier, we have to
+ // store the move-only continuation, to guarantee that the associated
+ // future's data stays alive.
+ if (d->continuationState != QFutureInterfaceBasePrivate::Cleaned) {
+ if (d->continuation) {
+ qWarning() << "Adding a continuation to a future which already has a continuation. "
+ "The existing continuation is overwritten.";
+ }
d->continuation = std::move(func);
+ d->continuationData = continuationFutureData;
}
}
+void QFutureInterfaceBase::cleanContinuation()
+{
+ if (!d)
+ return;
+
+ QMutexLocker lock(&d->continuationMutex);
+ d->continuation = nullptr;
+ d->continuationState = QFutureInterfaceBasePrivate::Cleaned;
+ d->continuationData = nullptr;
+}
+
void QFutureInterfaceBase::runContinuation() const
{
QMutexLocker lock(&d->continuationMutex);
if (d->continuation) {
+ // Save the continuation in a local function, to avoid calling
+ // a null std::function below, in case cleanContinuation() is
+ // called from some other thread right after unlock() below.
+ auto fn = std::move(d->continuation);
lock.unlock();
- d->continuation();
+ fn(*this);
+
+ lock.relock();
+ // Unless the continuation has been cleaned earlier, we have to
+ // store the move-only continuation, to guarantee that the associated
+ // future's data stays alive.
+ if (d->continuationState != QFutureInterfaceBasePrivate::Cleaned)
+ d->continuation = std::move(fn);
}
}
+bool QFutureInterfaceBase::isChainCanceled() const
+{
+ return isCanceled() || d->continuationState == QFutureInterfaceBasePrivate::Canceled;
+}
+
void QFutureInterfaceBase::setLaunchAsync(bool value)
{
d->launchAsync = value;
@@ -741,4 +943,19 @@ bool QFutureInterfaceBase::launchAsync() const
return d->launchAsync;
}
+namespace QtFuture {
+
+QFuture<void> makeReadyVoidFuture()
+{
+ QFutureInterface<void> promise;
+ promise.reportStarted();
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+} // namespace QtFuture
+
QT_END_NAMESPACE
+
+#include "qfutureinterface.moc"
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index 2e15cbb013..180a59a94e 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -1,61 +1,27 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTUREINTERFACE_H
#define QFUTUREINTERFACE_H
-#include <QtCore/qrunnable.h>
#include <QtCore/qmutex.h>
-#include <QtCore/qexception.h>
#include <QtCore/qresultstore.h>
+#ifndef QT_NO_EXCEPTIONS
+#include <exception>
+#endif
#include <utility>
-#include <vector>
-#include <mutex>
QT_REQUIRE_CONFIG(future);
+QT_FORWARD_DECLARE_CLASS(QRunnable)
+QT_FORWARD_DECLARE_CLASS(QException)
QT_BEGIN_NAMESPACE
template <typename T> class QFuture;
class QThreadPool;
+class QFutureInterfaceBase;
class QFutureInterfaceBasePrivate;
class QFutureWatcherBase;
class QFutureWatcherBasePrivate;
@@ -64,6 +30,8 @@ namespace QtPrivate {
template<typename Function, typename ResultType, typename ParentResultType>
class Continuation;
+class ExceptionStore;
+
template<class Function, class ResultType>
class CanceledHandler;
@@ -71,6 +39,10 @@ class CanceledHandler;
template<class Function, class ResultType>
class FailureHandler;
#endif
+
+void Q_CORE_EXPORT watchContinuationImpl(const QObject *context,
+ QtPrivate::QSlotObjectBase *slotObj,
+ QFutureInterfaceBase &fi);
}
class Q_CORE_EXPORT QFutureInterfaceBase
@@ -91,6 +63,10 @@ public:
QFutureInterfaceBase(State initialState = NoState);
QFutureInterfaceBase(const QFutureInterfaceBase &other);
+ QFutureInterfaceBase(QFutureInterfaceBase &&other) noexcept
+ : d(std::exchange(other.d, nullptr)) {}
+ QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterfaceBase)
virtual ~QFutureInterfaceBase();
// reporting functions available to the engine author:
@@ -99,7 +75,11 @@ public:
void reportCanceled();
#ifndef QT_NO_EXCEPTIONS
void reportException(const QException &e);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
void reportException(std::exception_ptr e);
+#else
+ void reportException(const std::exception_ptr &e);
+#endif
#endif
void reportResultsReady(int beginIndex, int endIndex);
@@ -143,6 +123,8 @@ public:
int loadState() const;
void cancel();
+ void cancelAndFinish() { cancel(CancelMode::CancelAndFinish); }
+
void setSuspended(bool suspend);
void toggleSuspended();
void reportSuspended() const;
@@ -155,18 +137,28 @@ public:
void suspendIfRequested();
QMutex &mutex() const;
+ bool hasException() const;
QtPrivate::ExceptionStore &exceptionStore();
QtPrivate::ResultStoreBase &resultStoreBase();
const QtPrivate::ResultStoreBase &resultStoreBase() const;
inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
- QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
+
+ // ### Qt 7: inline
+ void swap(QFutureInterfaceBase &other) noexcept;
+
+ template<typename T>
+ static QFutureInterfaceBase get(const QFuture<T> &future); // implemented in qfuture.h
+
+ bool isChainCanceled() const;
protected:
- bool refT() const;
- bool derefT() const;
+ // ### Qt 7: remove const from refT/derefT
+ bool refT() const noexcept;
+ bool derefT() const noexcept;
void reset();
+ void rethrowPossibleException();
public:
#ifndef QFUTURE_TEST
@@ -189,16 +181,33 @@ private:
friend class QtPrivate::FailureHandler;
#endif
+ friend Q_CORE_EXPORT void QtPrivate::watchContinuationImpl(
+ const QObject *context, QtPrivate::QSlotObjectBase *slotObj, QFutureInterfaceBase &fi);
+
+ template<class T>
+ friend class QPromise;
+
protected:
- void setContinuation(std::function<void()> func);
+ void setContinuation(std::function<void(const QFutureInterfaceBase &)> func);
+ void setContinuation(std::function<void(const QFutureInterfaceBase &)> func,
+ QFutureInterfaceBasePrivate *continuationFutureData);
+ void cleanContinuation();
void runContinuation() const;
void setLaunchAsync(bool value);
bool launchAsync() const;
bool isRunningOrPending() const;
+
+ enum class CancelMode { CancelOnly, CancelAndFinish };
+ void cancel(CancelMode mode);
};
+inline void swap(QFutureInterfaceBase &lhs, QFutureInterfaceBase &rhs) noexcept
+{
+ lhs.swap(rhs);
+}
+
template <typename T>
class QFutureInterface : public QFutureInterfaceBase
{
@@ -213,32 +222,36 @@ public:
{
refT();
}
+ QFutureInterface(const QFutureInterfaceBase &dd) : QFutureInterfaceBase(dd) { refT(); }
+ QFutureInterface(QFutureInterfaceBase &&dd) noexcept : QFutureInterfaceBase(std::move(dd)) { refT(); }
+ QFutureInterface &operator=(const QFutureInterface &other)
+ {
+ QFutureInterface copy(other);
+ swap(copy);
+ return *this;
+ }
+ QFutureInterface(QFutureInterface &&other) = default;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterface)
+
~QFutureInterface()
{
- if (!derefT())
+ if (!derefT() && !hasException())
resultStoreBase().template clear<T>();
}
static QFutureInterface canceledResult()
{ return QFutureInterface(State(Started | Finished | Canceled)); }
- QFutureInterface &operator=(const QFutureInterface &other)
- {
- other.refT();
- if (!derefT())
- resultStoreBase().template clear<T>();
- QFutureInterfaceBase::operator=(other);
- return *this;
- }
-
inline QFuture<T> future(); // implemented in qfuture.h
- inline void reportResult(const T *result, int index = -1);
- inline void reportAndMoveResult(T &&result, int index = -1);
- inline void reportResult(T &&result, int index = -1);
- inline void reportResult(const T &result, int index = -1);
- inline void reportResults(const QList<T> &results, int beginIndex = -1, int count = -1);
- inline void reportFinished(const T *result);
+ template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
+ inline bool reportAndEmplaceResult(int index, Args&&...args);
+ inline bool reportResult(const T *result, int index = -1);
+ inline bool reportAndMoveResult(T &&result, int index = -1);
+ inline bool reportResult(T &&result, int index = -1);
+ inline bool reportResult(const T &result, int index = -1);
+ inline bool reportResults(const QList<T> &results, int beginIndex = -1, int count = -1);
+ inline bool reportFinished(const T *result);
void reportFinished()
{
QFutureInterfaceBase::reportFinished();
@@ -250,95 +263,137 @@ public:
inline QList<T> results();
T takeResult();
+#if 0
+ // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
std::vector<T> takeResults();
+#endif
+
+#ifndef QT_NO_EXCEPTIONS
+ void reportException(const std::exception_ptr &e)
+ {
+ if (hasException())
+ return;
+
+ resultStoreBase().template clear<T>();
+ QFutureInterfaceBase::reportException(e);
+ }
+ void reportException(const QException &e)
+ {
+ if (hasException())
+ return;
+
+ resultStoreBase().template clear<T>();
+ QFutureInterfaceBase::reportException(e);
+ }
+#endif
};
template <typename T>
-inline void QFutureInterface<T>::reportResult(const T *result, int index)
+inline bool QFutureInterface<T>::reportResult(const T *result, int index)
{
- std::lock_guard<QMutex> locker{mutex()};
- if (this->queryState(Canceled) || this->queryState(Finished)) {
- return;
- }
+ QMutexLocker<QMutex> locker{&mutex()};
+ if (this->queryState(Canceled) || this->queryState(Finished))
+ return false;
+ Q_ASSERT(!hasException());
QtPrivate::ResultStoreBase &store = resultStoreBase();
+ const int resultCountBefore = store.count();
+ const int insertIndex = store.addResult<T>(index, result);
+ if (insertIndex == -1)
+ return false;
if (store.filterMode()) {
- const int resultCountBefore = store.count();
- store.addResult<T>(index, result);
this->reportResultsReady(resultCountBefore, store.count());
} else {
- const int insertIndex = store.addResult<T>(index, result);
this->reportResultsReady(insertIndex, insertIndex + 1);
}
+ return true;
}
template<typename T>
-void QFutureInterface<T>::reportAndMoveResult(T &&result, int index)
+template<typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool>>
+bool QFutureInterface<T>::reportAndEmplaceResult(int index, Args&&...args)
{
- std::lock_guard<QMutex> locker{mutex()};
+ QMutexLocker<QMutex> locker{&mutex()};
if (queryState(Canceled) || queryState(Finished))
- return;
+ return false;
+ Q_ASSERT(!hasException());
QtPrivate::ResultStoreBase &store = resultStoreBase();
const int oldResultCount = store.count();
- const int insertIndex = store.moveResult(index, std::forward<T>(result));
- if (!store.filterMode() || oldResultCount < store.count()) // Let's make sure it's not in pending results.
+ const int insertIndex = store.emplaceResult<T>(index, std::forward<Args>(args)...);
+ // Let's make sure it's not in pending results.
+ if (insertIndex != -1 && (!store.filterMode() || oldResultCount < store.count()))
reportResultsReady(insertIndex, store.count());
+ return insertIndex != -1;
}
template<typename T>
-void QFutureInterface<T>::reportResult(T &&result, int index)
+bool QFutureInterface<T>::reportAndMoveResult(T &&result, int index)
{
- reportAndMoveResult(std::move(result), index);
+ return reportAndEmplaceResult(index, std::move(result));
+}
+
+template<typename T>
+bool QFutureInterface<T>::reportResult(T &&result, int index)
+{
+ return reportAndMoveResult(std::move(result), index);
}
template <typename T>
-inline void QFutureInterface<T>::reportResult(const T &result, int index)
+inline bool QFutureInterface<T>::reportResult(const T &result, int index)
{
- reportResult(&result, index);
+ return reportResult(&result, index);
}
template<typename T>
-inline void QFutureInterface<T>::reportResults(const QList<T> &_results, int beginIndex, int count)
+inline bool QFutureInterface<T>::reportResults(const QList<T> &_results, int beginIndex, int count)
{
- std::lock_guard<QMutex> locker{mutex()};
- if (this->queryState(Canceled) || this->queryState(Finished)) {
- return;
- }
+ QMutexLocker<QMutex> locker{&mutex()};
+ if (this->queryState(Canceled) || this->queryState(Finished))
+ return false;
+ Q_ASSERT(!hasException());
auto &store = resultStoreBase();
+ const int resultCountBefore = store.count();
+ const int insertIndex = store.addResults(beginIndex, &_results, count);
+ if (insertIndex == -1)
+ return false;
if (store.filterMode()) {
- const int resultCountBefore = store.count();
- store.addResults(beginIndex, &_results, count);
this->reportResultsReady(resultCountBefore, store.count());
} else {
- const int insertIndex = store.addResults(beginIndex, &_results, count);
- this->reportResultsReady(insertIndex, insertIndex + _results.count());
+ this->reportResultsReady(insertIndex, insertIndex + _results.size());
}
+ return true;
}
template <typename T>
-inline void QFutureInterface<T>::reportFinished(const T *result)
+inline bool QFutureInterface<T>::reportFinished(const T *result)
{
+ bool resultReported = false;
if (result)
- reportResult(result);
+ resultReported = reportResult(result);
reportFinished();
+ return resultReported;
}
template <typename T>
inline const T &QFutureInterface<T>::resultReference(int index) const
{
- std::lock_guard<QMutex> locker{mutex()};
+ Q_ASSERT(!hasException());
+
+ QMutexLocker<QMutex> locker{&mutex()};
return resultStoreBase().resultAt(index).template value<T>();
}
template <typename T>
inline const T *QFutureInterface<T>::resultPointer(int index) const
{
- std::lock_guard<QMutex> locker{mutex()};
+ Q_ASSERT(!hasException());
+
+ QMutexLocker<QMutex> locker{&mutex()};
return resultStoreBase().resultAt(index).template pointer<T>();
}
@@ -346,14 +401,14 @@ template <typename T>
inline QList<T> QFutureInterface<T>::results()
{
if (this->isCanceled()) {
- exceptionStore().throwPossibleException();
+ rethrowPossibleException();
return QList<T>();
}
QFutureInterfaceBase::waitForResult(-1);
QList<T> res;
- std::lock_guard<QMutex> locker{mutex()};
+ QMutexLocker<QMutex> locker{&mutex()};
QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
while (it != resultStoreBase().end()) {
@@ -373,7 +428,9 @@ T QFutureInterface<T>::takeResult()
// not to mess with other unready results.
waitForResult(-1);
- const std::lock_guard<QMutex> locker{mutex()};
+ Q_ASSERT(!hasException());
+
+ const QMutexLocker<QMutex> locker{&mutex()};
QtPrivate::ResultIteratorBase position = resultStoreBase().resultAt(0);
T ret(std::move_if_noexcept(position.value<T>()));
reset();
@@ -382,16 +439,20 @@ T QFutureInterface<T>::takeResult()
return ret;
}
+#if 0
template<typename T>
std::vector<T> QFutureInterface<T>::takeResults()
{
Q_ASSERT(isValid());
waitForResult(-1);
+
+ Q_ASSERT(!hasException());
+
std::vector<T> res;
res.reserve(resultCount());
- const std::lock_guard<QMutex> locker{mutex()};
+ const QMutexLocker<QMutex> locker{&mutex()};
QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
for (auto endIt = resultStoreBase().end(); it != endIt; ++it)
@@ -402,30 +463,44 @@ std::vector<T> QFutureInterface<T>::takeResults()
return res;
}
+#endif
template <>
class QFutureInterface<void> : public QFutureInterfaceBase
{
public:
- explicit QFutureInterface<void>(State initialState = NoState)
+ explicit QFutureInterface(State initialState = NoState)
: QFutureInterfaceBase(initialState)
{ }
+ QFutureInterface(const QFutureInterfaceBase &dd) : QFutureInterfaceBase(dd) { }
+
static QFutureInterface<void> canceledResult()
{ return QFutureInterface(State(Started | Finished | Canceled)); }
inline QFuture<void> future(); // implemented in qfuture.h
- void reportResult(const void *, int) { }
- void reportResults(const QList<void> &, int) { }
- void reportFinished(const void * = nullptr)
+ bool reportResult(const void *, int) { return false; }
+ bool reportResults(const QList<void> &, int) { return false; }
+ bool reportFinished(const void *)
+ {
+ reportFinished();
+ return false;
+ }
+ void reportFinished()
{
QFutureInterfaceBase::reportFinished();
QFutureInterfaceBase::runContinuation();
}
};
+template<typename T>
+inline void swap(QFutureInterface<T> &a, QFutureInterface<T> &b) noexcept
+{
+ a.swap(b);
+}
+
QT_END_NAMESPACE
#endif // QFUTUREINTERFACE_H
diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h
index 8ef27044bf..92a1072591 100644
--- a/src/corelib/thread/qfutureinterface_p.h
+++ b/src/corelib/thread/qfutureinterface_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTUREINTERFACE_P_H
#define QFUTUREINTERFACE_P_H
@@ -58,13 +22,20 @@
#include <QtCore/qwaitcondition.h>
#include <QtCore/qrunnable.h>
#include <QtCore/qthreadpool.h>
+#include <QtCore/qfutureinterface.h>
+#include <QtCore/qexception.h>
QT_REQUIRE_CONFIG(future);
QT_BEGIN_NAMESPACE
-class QFutureCallOutEvent : public QEvent
+// Although QFutureCallOutEvent and QFutureCallOutInterface are private,
+// for historical reasons they were used externally (in QtJambi, see
+// https://github.com/OmixVisualization/qtjambi), so we export them to
+// not break the pre-existing code.
+class Q_CORE_EXPORT QFutureCallOutEvent : public QEvent
{
+ Q_DECL_EVENT_COMMON(QFutureCallOutEvent)
public:
enum CallOutType {
Started,
@@ -100,29 +71,12 @@ public:
int index1;
int index2;
QString text;
-
- QFutureCallOutEvent *clone() const
- {
- return new QFutureCallOutEvent(callOutType, index1, index2, text);
- }
-
-private:
- QFutureCallOutEvent(CallOutType callOutType,
- int index1,
- int index2,
- const QString &text)
- : QEvent(QEvent::FutureCallOut),
- callOutType(callOutType),
- index1(index1),
- index2(index2),
- text(text)
- { }
};
-class QFutureCallOutInterface
+class Q_CORE_EXPORT QFutureCallOutInterface
{
public:
- virtual ~QFutureCallOutInterface() {}
+ virtual ~QFutureCallOutInterface();
virtual void postCallOutEvent(const QFutureCallOutEvent &) = 0;
virtual void callOutInterfaceDisconnected() = 0;
};
@@ -131,6 +85,7 @@ class QFutureInterfaceBasePrivate
{
public:
QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState);
+ ~QFutureInterfaceBasePrivate();
// When the last QFuture<T> reference is removed, we need to make
// sure that data stored in the ResultStore is cleaned out.
@@ -158,23 +113,55 @@ public:
// T: accessed from executing thread
// Q: accessed from the waiting/querying thread
- RefCount refCount;
mutable QMutex m_mutex;
- QWaitCondition waitCondition;
+ QBasicMutex continuationMutex;
QList<QFutureCallOutInterface *> outputConnections;
- int m_progressValue; // TQ
- int m_progressMinimum; // TQ
- int m_progressMaximum; // TQ
- QAtomicInt state; // reads and writes can happen unprotected, both must be atomic
QElapsedTimer progressTime;
+ QWaitCondition waitCondition;
QWaitCondition pausedWaitCondition;
- QtPrivate::ResultStoreBase m_results;
- bool manualProgress; // only accessed from executing thread
- int m_expectedResultCount;
- QtPrivate::ExceptionStore m_exceptionStore;
- QString m_progressText;
- QRunnable *runnable;
- QThreadPool *m_pool;
+
+ union Data {
+ QtPrivate::ResultStoreBase m_results;
+ QtPrivate::ExceptionStore m_exceptionStore;
+
+#ifndef QT_NO_EXCEPTIONS
+ void setException(const std::exception_ptr &e)
+ {
+ m_results.~ResultStoreBase();
+ new (&m_exceptionStore) QtPrivate::ExceptionStore();
+ m_exceptionStore.setException(e);
+ }
+#endif
+
+ ~Data() { }
+ };
+ Data data = { QtPrivate::ResultStoreBase() };
+
+ QRunnable *runnable = nullptr;
+ QThreadPool *m_pool = nullptr;
+ // Wrapper for continuation
+ std::function<void(const QFutureInterfaceBase &)> continuation;
+ QFutureInterfaceBasePrivate *continuationData = nullptr;
+
+ RefCount refCount = 1;
+ QAtomicInt state; // reads and writes can happen unprotected, both must be atomic
+
+ int m_progressValue = 0; // TQ
+ struct ProgressData
+ {
+ int minimum = 0; // TQ
+ int maximum = 0; // TQ
+ QString text;
+ };
+ QScopedPointer<ProgressData> m_progress;
+
+ int m_expectedResultCount = 0;
+ bool launchAsync = false;
+ bool isValid = false;
+ bool hasException = false;
+
+ enum ContinuationState : quint8 { Default, Canceled, Cleaned };
+ std::atomic<ContinuationState> continuationState { Default };
inline QThreadPool *pool() const
{ return m_pool ? m_pool : QThreadPool::globalInstance(); }
@@ -184,6 +171,7 @@ public:
int internal_resultCount() const;
bool internal_isResultReadyAt(int index) const;
bool internal_waitForNextResult();
+ bool internal_updateProgressValue(int progress);
bool internal_updateProgress(int progress, const QString &progressText = QString());
void internal_setThrottled(bool enable);
void sendCallOut(const QFutureCallOutEvent &callOut);
@@ -192,13 +180,6 @@ public:
void disconnectOutputInterface(QFutureCallOutInterface *iface);
void setState(QFutureInterfaceBase::State state);
-
- // Wrapper for continuation
- std::function<void()> continuation;
- QBasicMutex continuationMutex;
-
- bool launchAsync = false;
- bool isValid = false;
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfuturesynchronizer.h b/src/corelib/thread/qfuturesynchronizer.h
index 5006ebb9cf..a996362bfd 100644
--- a/src/corelib/thread/qfuturesynchronizer.h
+++ b/src/corelib/thread/qfuturesynchronizer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTURESYNCHRONIZER_H
#define QFUTURESYNCHRONIZER_H
@@ -53,33 +17,34 @@ class QFutureSynchronizer
Q_DISABLE_COPY(QFutureSynchronizer)
public:
- QFutureSynchronizer() : m_cancelOnWait(false) { }
- explicit QFutureSynchronizer(const QFuture<T> &future)
+ Q_NODISCARD_CTOR QFutureSynchronizer() : m_cancelOnWait(false) { }
+ Q_NODISCARD_CTOR_X("Use future.waitForFinished() instead.")
+ explicit QFutureSynchronizer(QFuture<T> future)
: m_cancelOnWait(false)
- { addFuture(future); }
+ { addFuture(std::move(future)); }
~QFutureSynchronizer() { waitForFinished(); }
- void setFuture(const QFuture<T> &future)
+ void setFuture(QFuture<T> future)
{
waitForFinished();
m_futures.clear();
- addFuture(future);
+ addFuture(std::move(future));
}
- void addFuture(const QFuture<T> &future)
+ void addFuture(QFuture<T> future)
{
- m_futures.append(future);
+ m_futures.append(std::move(future));
}
void waitForFinished()
{
if (m_cancelOnWait) {
- for (int i = 0; i < m_futures.count(); ++i) {
+ for (int i = 0; i < m_futures.size(); ++i) {
m_futures[i].cancel();
}
}
- for (int i = 0; i < m_futures.count(); ++i) {
+ for (int i = 0; i < m_futures.size(); ++i) {
m_futures[i].waitForFinished();
}
}
@@ -105,7 +70,7 @@ public:
}
protected:
- QList<QFuture<T> > m_futures;
+ QList<QFuture<T>> m_futures;
bool m_cancelOnWait;
};
diff --git a/src/corelib/thread/qfuturesynchronizer.qdoc b/src/corelib/thread/qfuturesynchronizer.qdoc
index 67dafb039e..7d2d16d6e9 100644
--- a/src/corelib/thread/qfuturesynchronizer.qdoc
+++ b/src/corelib/thread/qfuturesynchronizer.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \class QFutureSynchronizer
\since 4.4
@@ -62,7 +38,7 @@
*/
/*!
- \fn template <typename T> QFutureSynchronizer<T>::QFutureSynchronizer(const QFuture<T> &future)
+ \fn template <typename T> QFutureSynchronizer<T>::QFutureSynchronizer(QFuture<T> future)
Constructs a QFutureSynchronizer and begins watching \a future by calling
addFuture().
@@ -80,7 +56,7 @@
*/
/*!
- \fn template <typename T> void QFutureSynchronizer<T>::setFuture(const QFuture<T> &future)
+ \fn template <typename T> void QFutureSynchronizer<T>::setFuture(QFuture<T> future)
Sets \a future to be the only future managed by this QFutureSynchronizer.
This is a convenience function that calls waitForFinished(),
@@ -90,7 +66,7 @@
*/
/*!
- \fn template <typename T> void QFutureSynchronizer<T>::addFuture(const QFuture<T> &future)
+ \fn template <typename T> void QFutureSynchronizer<T>::addFuture(QFuture<T> future)
Adds \a future to the list of managed futures.
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index 75f5e297e2..2cffadfa5b 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfuturewatcher.h"
#include "qfuturewatcher_p.h"
@@ -114,8 +78,8 @@ QFutureWatcherBase::QFutureWatcherBase(QObject *parent)
/*! \fn template <typename T> void QFutureWatcher<T>::cancel()
Cancels the asynchronous computation represented by the future(). Note that
- the cancelation is asynchronous. Use waitForFinished() after calling
- cancel() when you need synchronous cancelation.
+ the cancellation is asynchronous. Use waitForFinished() after calling
+ cancel() when you need synchronous cancellation.
Currently available results may still be accessed on a canceled QFuture,
but new results will \e not become available after calling this function.
@@ -136,8 +100,7 @@ void QFutureWatcherBase::cancel()
#if QT_DEPRECATED_SINCE(6, 0)
/*! \fn template <typename T> void QFutureWatcher<T>::setPaused(bool paused)
- \obsolete
- Use setSuspended() instead.
+ \deprecated [6.6] Use setSuspended() instead.
If \a paused is true, this function pauses the asynchronous computation
represented by the future(). If the computation is already paused, this
@@ -154,7 +117,7 @@ void QFutureWatcherBase::cancel()
QFuture returned by QtConcurrent::run() cannot be paused; but the QFuture
returned by QtConcurrent::mappedReduced() can.
- \sa pause(), resume(), togglePaused()
+ \sa suspend(), resume(), toggleSuspended()
*/
void QFutureWatcherBase::setPaused(bool paused)
{
@@ -163,7 +126,7 @@ void QFutureWatcherBase::setPaused(bool paused)
/*! \fn template <typename T> void QFutureWatcher<T>::pause()
- \obsolete
+ \deprecated
Use suspend() instead.
Pauses the asynchronous computation represented by the future(). This is a
@@ -233,15 +196,14 @@ void QFutureWatcherBase::resume()
#if QT_DEPRECATED_SINCE(6, 0)
/*! \fn template <typename T> void QFutureWatcher<T>::togglePaused()
- \obsolete
- Use toggleSuspended() instead.
+ \deprecated [6.0] Use toggleSuspended() instead.
Toggles the paused state of the asynchronous computation. In other words,
if the computation is currently paused, calling this function resumes it;
if the computation is running, it is paused. This is a convenience method
for calling setPaused(!isPaused()).
- \sa setPaused(), pause(), resume()
+ \sa setSuspended(), suspend(), resume()
*/
void QFutureWatcherBase::togglePaused()
{
@@ -329,8 +291,7 @@ bool QFutureWatcherBase::isStarted() const
*/
bool QFutureWatcherBase::isFinished() const
{
- Q_D(const QFutureWatcherBase);
- return d->finished;
+ return futureInterface().isFinished();
}
/*! \fn template <typename T> bool QFutureWatcher<T>::isRunning() const
@@ -360,8 +321,7 @@ bool QFutureWatcherBase::isCanceled() const
/*! \fn template <typename T> bool QFutureWatcher<T>::isPaused() const
- \obsolete
- Use isSuspending() or isSuspended() instead.
+ \deprecated [6.0] Use isSuspending() or isSuspended() instead.
Returns \c true if the asynchronous computation has been paused with the
pause() function; otherwise returns \c false.
@@ -370,7 +330,7 @@ bool QFutureWatcherBase::isCanceled() const
function returns \c true. See setPaused() for more details. To check
if pause actually took effect, use isSuspended() instead.
- \sa setPaused(), togglePaused(), isSuspended()
+ \sa setSuspended(), toggleSuspended(), isSuspended()
*/
bool QFutureWatcherBase::isPaused() const
@@ -417,7 +377,7 @@ bool QFutureWatcherBase::isSuspended() const
/*! \fn template <typename T> void QFutureWatcher<T>::waitForFinished()
Waits for the asynchronous computation to finish (including cancel()ed
- computations).
+ computations), i.e. until isFinished() returns \c true.
*/
void QFutureWatcherBase::waitForFinished()
{
@@ -480,8 +440,7 @@ void QFutureWatcherBase::disconnectNotify(const QMetaMethod &signal)
*/
QFutureWatcherBasePrivate::QFutureWatcherBasePrivate()
: maximumPendingResultsReady(QThread::idealThreadCount() * 2),
- resultAtConnected(0),
- finished(true) /* the initial m_future is a canceledResult(), with Finished set */
+ resultAtConnected(0)
{ }
/*!
@@ -500,7 +459,6 @@ void QFutureWatcherBase::disconnectOutputInterface(bool pendingAssignment)
if (pendingAssignment) {
Q_D(QFutureWatcherBase);
d->pendingResultsReady.storeRelaxed(0);
- d->finished = false; /* May soon be amended, during connectOutputInterface() */
}
futureInterface().d->disconnectOutputInterface(d_func());
@@ -532,7 +490,6 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
emit q->started();
break;
case QFutureCallOutEvent::Finished:
- finished = true;
emit q->finished();
break;
case QFutureCallOutEvent::Canceled:
@@ -595,7 +552,7 @@ QT_WARNING_POP
}
-/*! \fn template <typename T> const T &QFutureWatcher<T>::result() const
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> const T &QFutureWatcher<T>::result() const
Returns the first result in the future(). If the result is not immediately
available, this function will block and wait for the result to become
@@ -604,7 +561,7 @@ QT_WARNING_POP
\sa resultAt()
*/
-/*! \fn template <typename T> const T &QFutureWatcher<T>::resultAt(int index) const
+/*! \fn template <typename T> template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> const T &QFutureWatcher<T>::resultAt(int index) const
Returns the result at \a index in the future(). If the result is not
immediately available, this function will block and wait for the result to
@@ -617,9 +574,15 @@ QT_WARNING_POP
Starts watching the given \a future.
- One of the signals might be emitted for the current state of the
- \a future. For example, if the future is already stopped, the
- finished signal will be emitted.
+ If \a future has already started, the watcher will initially emit signals
+ that bring their listeners up to date about the future's state. The
+ following signals will, if applicable, be emitted in the given order:
+ started(), progressRangeChanged(), progressValueChanged(),
+ progressTextChanged(), resultsReadyAt(), resultReadyAt(), suspending(),
+ suspended(), canceled(), and finished(). Of these, resultsReadyAt() and
+ resultReadyAt() may be emitted several times to cover all available
+ results. progressValueChanged() and progressTextChanged() will only be
+ emitted once for the latest available progress value and text.
To avoid a race condition, it is important to call this function
\e after doing the connections.
@@ -665,8 +628,7 @@ QT_WARNING_POP
#if QT_DEPRECATED_SINCE(6, 0)
/*! \fn template <typename T> void QFutureWatcher<T>::paused()
- \obsolete
- Use suspending() instead.
+ \deprecated [6.0] Use suspending() instead.
This signal is emitted when the state of the watched future is
set to paused.
@@ -677,7 +639,7 @@ QT_WARNING_POP
still be delivered. To to be informed when pause() actually
took effect, use the suspended() signal.
- \sa setPaused(), pause(), suspended()
+ \sa setSuspended(), suspend(), suspended()
*/
#endif // QT_DEPRECATED_SINCE(6, 0)
diff --git a/src/corelib/thread/qfuturewatcher.h b/src/corelib/thread/qfuturewatcher.h
index d2b8eeace1..89c5b408fa 100644
--- a/src/corelib/thread/qfuturewatcher.h
+++ b/src/corelib/thread/qfuturewatcher.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTUREWATCHER_H
#define QFUTUREWATCHER_H
@@ -131,12 +95,6 @@ private:
virtual QFutureInterfaceBase &futureInterface() = 0;
};
-namespace QtPrivate {
-
-template<class T>
-using EnableForNonVoid = std::enable_if_t<!std::is_same_v<T, void>>;
-}
-
template <typename T>
class QFutureWatcher : public QFutureWatcherBase
{
@@ -216,7 +174,7 @@ private:
template <typename T>
Q_INLINE_TEMPLATE void QFutureWatcher<T>::setFuture(const QFuture<T> &_future)
{
- if (_future == m_future)
+ if (_future.d == m_future.d)
return;
disconnectOutputInterface(true);
diff --git a/src/corelib/thread/qfuturewatcher_p.h b/src/corelib/thread/qfuturewatcher_p.h
index b086b88773..6d6bf29774 100644
--- a/src/corelib/thread/qfuturewatcher_p.h
+++ b/src/corelib/thread/qfuturewatcher_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFUTUREWATCHER_P_H
#define QFUTUREWATCHER_P_H
@@ -78,7 +42,6 @@ public:
int maximumPendingResultsReady;
QAtomicInt resultAtConnected;
- bool finished;
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index e9e5f3c74b..91ccbbd1cd 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICATOMIC_H
#define QGENERICATOMIC_H
-#include <QtCore/qglobal.h>
-#include <QtCore/qtypeinfo.h>
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtypes.h>
QT_BEGIN_NAMESPACE
@@ -53,8 +18,10 @@ QT_END_NAMESPACE
#pragma qt_sync_stop_processing
#endif
-template<int> struct QAtomicOpsSupport { enum { IsSupported = 0 }; };
-template<> struct QAtomicOpsSupport<4> { enum { IsSupported = 1 }; };
+template<int Size> struct QAtomicOpsSupport
+{
+ enum { IsSupported = (Size == sizeof(int) || Size == sizeof(qptrdiff)) };
+};
template <typename T> struct QAtomicAdditiveType
{
@@ -67,335 +34,5 @@ template <typename T> struct QAtomicAdditiveType<T *>
static const int AddScale = sizeof(T);
};
-// not really atomic...
-template <typename BaseClass> struct QGenericAtomicOps
-{
- template <typename T> struct AtomicType { typedef T Type; typedef T *PointerType; };
-
- template <typename T> static void acquireMemoryFence(const T &_q_value) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- }
- template <typename T> static void releaseMemoryFence(const T &_q_value) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- }
- template <typename T> static void orderedMemoryFence(const T &) noexcept
- {
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T load(const T &_q_value) noexcept
- {
- return _q_value;
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- void store(T &_q_value, X newValue) noexcept
- {
- _q_value = newValue;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T loadRelaxed(const T &_q_value) noexcept
- {
- return _q_value;
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- void storeRelaxed(T &_q_value, X newValue) noexcept
- {
- _q_value = newValue;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T loadAcquire(const T &_q_value) noexcept
- {
- T tmp = *static_cast<const volatile T *>(&_q_value);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- void storeRelease(T &_q_value, X newValue) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- *static_cast<volatile T *>(&_q_value) = newValue;
- }
-
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept
- { return BaseClass::isFetchAndAddNative(); }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept
- { return BaseClass::isFetchAndAddWaitFree(); }
- template <typename T> static Q_ALWAYS_INLINE
- bool ref(T &_q_value) noexcept
- {
- return BaseClass::fetchAndAddRelaxed(_q_value, 1) != T(-1);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- bool deref(T &_q_value) noexcept
- {
- return BaseClass::fetchAndAddRelaxed(_q_value, -1) != 1;
- }
-
-#if 0
- // These functions have no default implementation
- // Archictectures must implement them
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept;
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept;
- template <typename T, typename X> static inline
- bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) noexcept;
- template <typename T, typename X> static inline
- bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept;
-#endif
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) noexcept
- {
- bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
- {
- bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
- }
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return false; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreRelaxed(T &_q_value, X newValue) noexcept
- {
- // implement fetchAndStore on top of testAndSet
- Q_FOREVER {
- T tmp = loadRelaxed(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, newValue))
- return tmp;
- }
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreAcquire(T &_q_value, X newValue) noexcept
- {
- T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreRelease(T &_q_value, X newValue) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
- }
-
- template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreOrdered(T &_q_value, X newValue) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
- }
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return false; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; }
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
- {
- // implement fetchAndAdd on top of testAndSet
- Q_FOREVER {
- T tmp = BaseClass::loadRelaxed(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp + valueToAdd)))
- return tmp;
- }
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
- {
- T tmp = BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
- }
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
- {
- // implement fetchAndSub on top of fetchAndAdd
- return fetchAndAddRelaxed(_q_value, -operand);
- }
-QT_WARNING_POP
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
- {
- T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::fetchAndSubRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::fetchAndSubRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- // implement fetchAndAnd on top of testAndSet
- T tmp = BaseClass::loadRelaxed(_q_value);
- Q_FOREVER {
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand), &tmp))
- return tmp;
- }
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::fetchAndAndRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::fetchAndAndRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- // implement fetchAndOr on top of testAndSet
- T tmp = BaseClass::loadRelaxed(_q_value);
- Q_FOREVER {
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand), &tmp))
- return tmp;
- }
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::fetchAndOrRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::fetchAndOrRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- // implement fetchAndXor on top of testAndSet
- T tmp = BaseClass::loadRelaxed(_q_value);
- Q_FOREVER {
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand), &tmp))
- return tmp;
- }
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand);
- BaseClass::acquireMemoryFence(_q_value);
- return tmp;
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- BaseClass::releaseMemoryFence(_q_value);
- return BaseClass::fetchAndXorRelaxed(_q_value, operand);
- }
-
- template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
- {
- BaseClass::orderedMemoryFence(_q_value);
- return BaseClass::fetchAndXorRelaxed(_q_value, operand);
- }
-};
-
QT_END_NAMESPACE
#endif // QGENERICATOMIC_H
diff --git a/src/corelib/thread/qlocking_p.h b/src/corelib/thread/qlocking_p.h
index 9a796cf7f7..9fa7e70da9 100644
--- a/src/corelib/thread/qlocking_p.h
+++ b/src/corelib/thread/qlocking_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLOCKING_P_H
#define QLOCKING_P_H
@@ -44,15 +8,15 @@
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header
-// file may change from version to version without notice, or even be
-// removed.
+// This file is not part of the Qt API. It exists for the convenience of
+// qmutex.cpp and qmutex_unix.cpp. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qmutex.h>
+#include <QtCore/private/qglobal_p.h>
#include <mutex>
@@ -84,15 +48,11 @@ QT_BEGIN_NAMESPACE
namespace {
template <typename Mutex, typename Lock =
-#if defined(__cpp_guaranteed_copy_elision) && __cpp_guaranteed_copy_elision >= 201606L
# if defined(__cpp_lib_scoped_lock) && __cpp_lib_scoped_lock >= 201703L
std::scoped_lock
# else
std::lock_guard
# endif
-#else
- std::unique_lock
-#endif
<typename std::decay<Mutex>::type>
>
Lock qt_scoped_lock(Mutex &mutex)
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 9bfd50f2d9..ec6c711a4f 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -1,90 +1,29 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "global/qglobal.h"
#include "qplatformdefs.h"
#include "qmutex.h"
#include <qdebug.h>
#include "qatomic.h"
-#include "qelapsedtimer.h"
+#include "qfutex_p.h"
#include "qthread.h"
#include "qmutex_p.h"
-#ifndef QT_LINUX_FUTEX
+#ifndef QT_ALWAYS_USE_FUTEX
#include "private/qfreelist_p.h"
#endif
QT_BEGIN_NAMESPACE
-static inline bool isRecursive(QMutexData *d)
+using namespace QtFutex;
+static inline QMutexPrivate *dummyFutexValue()
{
- quintptr u = quintptr(d);
- if (Q_LIKELY(u <= 0x3))
- return false;
-#ifdef QT_LINUX_FUTEX
- Q_ASSERT(d->recursive);
- return true;
-#else
- return d->recursive;
-#endif
+ return reinterpret_cast<QMutexPrivate *>(quintptr(3));
}
-class QRecursiveMutexPrivate : public QMutexData
-{
-public:
- QRecursiveMutexPrivate()
- : QMutexData(QMutex::Recursive), owner(nullptr), count(0) {}
-
- // written to by the thread that first owns 'mutex';
- // read during attempts to acquire ownership of 'mutex' from any other thread:
- QAtomicPointer<std::remove_pointer<Qt::HANDLE>::type> owner;
-
- // only ever accessed from the thread that owns 'mutex':
- uint count;
-
- QMutex mutex;
-
- bool lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
- void unlock() noexcept;
-};
-
/*
\class QBasicMutex
\inmodule QtCore
@@ -142,8 +81,8 @@ public:
lock calls unlock(). A non-blocking alternative to lock() is
tryLock().
- QMutex is optimized to be fast in the non-contended case. A non-recursive
- QMutex will not allocate memory if there is no contention on that mutex.
+ QMutex is optimized to be fast in the non-contended case. It
+ will not allocate memory if there is no contention on that mutex.
It is constructed and destroyed with almost no overhead,
which means it is fine to have many mutexes as part of other classes.
@@ -151,64 +90,28 @@ public:
*/
/*!
- \enum QMutex::RecursionMode
-
- \value Recursive In this mode, a thread can lock the same mutex
- multiple times and the mutex won't be unlocked
- until a corresponding number of unlock() calls
- have been made. You should use QRecursiveMutex
- for this use-case.
-
- \value NonRecursive In this mode, a thread may only lock a mutex
- once.
-
- \sa QMutex(), QRecursiveMutex
-*/
-
-/*!
\fn QMutex::QMutex()
Constructs a new mutex. The mutex is created in an unlocked state.
*/
-/*!
- Constructs a new mutex. The mutex is created in an unlocked state.
+/*! \fn QMutex::~QMutex()
- If \a mode is QMutex::Recursive, a thread can lock the same mutex
- multiple times and the mutex won't be unlocked until a
- corresponding number of unlock() calls have been made. Otherwise
- a thread may only lock a mutex once. The default is
- QMutex::NonRecursive.
-
- Recursive mutexes are slower and take more memory than non-recursive ones.
-
- \sa lock(), unlock()
-*/
-QMutex::QMutex(RecursionMode mode)
-{
- d_ptr.storeRelaxed(mode == Recursive ? new QRecursiveMutexPrivate : nullptr);
-}
-
-/*!
Destroys the mutex.
\warning Destroying a locked mutex may result in undefined behavior.
*/
-QMutex::~QMutex()
+void QBasicMutex::destroyInternal(QMutexPrivate *d)
{
- QMutexData *d = d_ptr.loadRelaxed();
- if (isRecursive()) {
- delete static_cast<QRecursiveMutexPrivate *>(d);
- } else if (d) {
-#ifndef QT_LINUX_FUTEX
- if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.loadRelaxed()
- && tryLock()) {
+ if (!d)
+ return;
+ if (!futexAvailable()) {
+ if (d != dummyLocked() && d->possiblyUnlocked.loadRelaxed() && tryLock()) {
unlock();
return;
}
-#endif
- qWarning("QMutex: destroying locked mutex");
}
+ qWarning("QMutex: destroying locked mutex");
}
/*! \fn void QMutex::lock()
@@ -217,23 +120,10 @@ QMutex::~QMutex()
call will block until that thread has unlocked it.
Calling this function multiple times on the same mutex from the
- same thread is allowed if this mutex is a
- \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
- \l{QMutex}{non-recursive mutex}, this function will
- \e dead-lock when the mutex is locked recursively.
+ same thread will cause a \e dead-lock.
\sa unlock()
*/
-void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
-{
- QMutexData *current;
- if (fastTryLock(current))
- return;
- if (QT_PREPEND_NAMESPACE(isRecursive)(current))
- static_cast<QRecursiveMutexPrivate *>(current)->lock(-1);
- else
- lockInternal();
-}
/*! \fn bool QMutex::tryLock(int timeout)
@@ -250,24 +140,42 @@ void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
before another thread can successfully lock it.
Calling this function multiple times on the same mutex from the
- same thread is allowed if this mutex is a
- \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
- \l{QMutex}{non-recursive mutex}, this function will
- \e always return false when attempting to lock the mutex
- recursively.
+ same thread will cause a \e dead-lock.
+
+ \sa lock(), unlock()
+*/
+
+/*! \fn bool QMutex::tryLock(QDeadlineTimer timer)
+ \since 6.6
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false. If another thread has
+ locked the mutex, this function will wait until \a timer expires
+ for the mutex to become available.
+
+ If the lock was obtained, the mutex must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread will cause a \e dead-lock.
+
+ \sa lock(), unlock()
+*/
+
+/*! \fn bool QMutex::tryLock()
+ \overload
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false.
+
+ If the lock was obtained, the mutex must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread will cause a \e dead-lock.
\sa lock(), unlock()
*/
-bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
-{
- QMutexData *current;
- if (fastTryLock(current))
- return true;
- if (QT_PREPEND_NAMESPACE(isRecursive)(current))
- return static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout);
- else
- return lockInternal(timeout);
-}
/*! \fn bool QMutex::try_lock()
\since 5.8
@@ -277,9 +185,6 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
This function is provided for compatibility with the Standard Library
concept \c Lockable. It is equivalent to tryLock().
-
- The function returns \c true if the lock was obtained; otherwise it
- returns \c false
*/
/*! \fn template <class Rep, class Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
@@ -297,11 +202,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
before another thread can successfully lock it.
Calling this function multiple times on the same mutex from the
- same thread is allowed if this mutex is a
- \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
- \l{QMutex}{non-recursive mutex}, this function will
- \e always return false when attempting to lock the mutex
- recursively.
+ same thread will cause a \e dead-lock.
\sa lock(), unlock()
*/
@@ -321,11 +222,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
before another thread can successfully lock it.
Calling this function multiple times on the same mutex from the
- same thread is allowed if this mutex is a
- \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
- \l{QMutex}{non-recursive mutex}, this function will
- \e always return false when attempting to lock the mutex
- recursively.
+ same thread will cause a \e dead-lock.
\sa lock(), unlock()
*/
@@ -338,39 +235,6 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
\sa lock()
*/
-void QMutex::unlock() noexcept
-{
- QMutexData *current;
- if (fastTryUnlock(current))
- return;
- if (QT_PREPEND_NAMESPACE(isRecursive)(current))
- static_cast<QRecursiveMutexPrivate *>(current)->unlock();
- else
- unlockInternal();
-}
-
-
-/*!
- \fn bool QMutex::isRecursive() const
- \since 5.7
-
- Returns \c true if the mutex is recursive.
-*/
-
-bool QBasicMutex::isRecursive() noexcept
-{
- return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
-}
-
-/*!
- \since 5.7
-
- Returns \c true if the mutex is recursive.
-*/
-bool QBasicMutex::isRecursive() const noexcept
-{
- return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
-}
/*!
\class QRecursiveMutex
@@ -403,16 +267,12 @@ bool QBasicMutex::isRecursive() const noexcept
\sa QMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
*/
-/*!
+/*! \fn QRecursiveMutex::QRecursiveMutex()
+
Constructs a new recursive mutex. The mutex is created in an unlocked state.
\sa lock(), unlock()
*/
-QRecursiveMutex::QRecursiveMutex()
- : QMutex()
-{
- d_ptr.storeRelaxed(new QRecursiveMutexPrivate);
-}
/*!
Destroys the mutex.
@@ -421,9 +281,158 @@ QRecursiveMutex::QRecursiveMutex()
*/
QRecursiveMutex::~QRecursiveMutex()
{
- delete static_cast<QRecursiveMutexPrivate*>(d_ptr.fetchAndStoreAcquire(nullptr));
}
+/*! \fn void QRecursiveMutex::lock()
+
+ Locks the mutex. If another thread has locked the mutex then this
+ call will block until that thread has unlocked it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread is allowed.
+
+ \sa unlock()
+*/
+
+/*!
+ \fn QRecursiveMutex::tryLock(int timeout)
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false. If another thread has
+ locked the mutex, this function will wait for at most \a timeout
+ milliseconds for the mutex to become available.
+
+ Note: Passing a negative number as the \a timeout is equivalent to
+ calling lock(), i.e. this function will wait forever until mutex
+ can be locked if \a timeout is negative.
+
+ If the lock was obtained, the mutex must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread is allowed.
+
+ \sa lock(), unlock()
+*/
+
+/*!
+ \since 6.6
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false. If another thread has
+ locked the mutex, this function will wait until \a timeout expires
+ for the mutex to become available.
+
+ If the lock was obtained, the mutex must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread is allowed.
+
+ \sa lock(), unlock()
+*/
+bool QRecursiveMutex::tryLock(QDeadlineTimer timeout) QT_MUTEX_LOCK_NOEXCEPT
+{
+ unsigned tsanFlags = QtTsan::MutexWriteReentrant | QtTsan::TryLock;
+ QtTsan::mutexPreLock(this, tsanFlags);
+
+ Qt::HANDLE self = QThread::currentThreadId();
+ if (owner.loadRelaxed() == self) {
+ ++count;
+ Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
+ QtTsan::mutexPostLock(this, tsanFlags, 0);
+ return true;
+ }
+ bool success = true;
+ if (timeout.isForever()) {
+ mutex.lock();
+ } else {
+ success = mutex.tryLock(timeout);
+ }
+
+ if (success)
+ owner.storeRelaxed(self);
+ else
+ tsanFlags |= QtTsan::TryLockFailed;
+
+ QtTsan::mutexPostLock(this, tsanFlags, 0);
+
+ return success;
+}
+
+/*! \fn bool QRecursiveMutex::try_lock()
+ \since 5.8
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false.
+
+ This function is provided for compatibility with the Standard Library
+ concept \c Lockable. It is equivalent to tryLock().
+*/
+
+/*! \fn template <class Rep, class Period> bool QRecursiveMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
+ \since 5.8
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false. If another thread has
+ locked the mutex, this function will wait for at least \a duration
+ for the mutex to become available.
+
+ Note: Passing a negative duration as the \a duration is equivalent to
+ calling try_lock(). This behavior differs from tryLock().
+
+ If the lock was obtained, the mutex must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread is allowed.
+
+ \sa lock(), unlock()
+*/
+
+/*! \fn template<class Clock, class Duration> bool QRecursiveMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
+ \since 5.8
+
+ Attempts to lock the mutex. This function returns \c true if the lock
+ was obtained; otherwise it returns \c false. If another thread has
+ locked the mutex, this function will wait at least until \a timePoint
+ for the mutex to become available.
+
+ Note: Passing a \a timePoint which has already passed is equivalent
+ to calling try_lock(). This behavior differs from tryLock().
+
+ If the lock was obtained, the mutex must be unlocked with unlock()
+ before another thread can successfully lock it.
+
+ Calling this function multiple times on the same mutex from the
+ same thread is allowed.
+
+ \sa lock(), unlock()
+*/
+
+/*!
+ Unlocks the mutex. Attempting to unlock a mutex in a different
+ thread to the one that locked it results in an error. Unlocking a
+ mutex that is not locked results in undefined behavior.
+
+ \sa lock()
+*/
+void QRecursiveMutex::unlock() noexcept
+{
+ Q_ASSERT(owner.loadRelaxed() == QThread::currentThreadId());
+ QtTsan::mutexPreUnlock(this, 0u);
+
+ if (count > 0) {
+ count--;
+ } else {
+ owner.storeRelaxed(nullptr);
+ mutex.unlock();
+ }
+
+ QtTsan::mutexPostUnlock(this, 0u);
+}
+
+
/*!
\class QMutexLocker
\inmodule QtCore
@@ -434,7 +443,7 @@ QRecursiveMutex::~QRecursiveMutex()
\ingroup thread
- Locking and unlocking a QMutex in complex functions and
+ Locking and unlocking a QMutex or QRecursiveMutex in complex functions and
statements or in exception handling code is error-prone and
difficult to debug. QMutexLocker can be used in such situations
to ensure that the state of the mutex is always well-defined.
@@ -478,7 +487,7 @@ QRecursiveMutex::~QRecursiveMutex()
*/
/*!
- \fn QMutexLocker::QMutexLocker(QMutex *mutex)
+ \fn template <typename Mutex> QMutexLocker<Mutex>::QMutexLocker(Mutex *mutex) noexcept
Constructs a QMutexLocker and locks \a mutex. The mutex will be
unlocked when the QMutexLocker is destroyed. If \a mutex is \nullptr,
@@ -488,18 +497,41 @@ QRecursiveMutex::~QRecursiveMutex()
*/
/*!
- \fn QMutexLocker::QMutexLocker(QRecursiveMutex *mutex)
- \since 5.14
+ \fn template <typename Mutex> QMutexLocker<Mutex>::QMutexLocker(QMutexLocker &&other) noexcept
+ \since 6.4
- Constructs a QMutexLocker and locks \a mutex. The mutex will be
- unlocked (unlock() called) when the QMutexLocker is destroyed.
- If \a mutex is \nullptr, QMutexLocker does nothing.
+ Move-constructs a QMutexLocker from \a other. The mutex and the
+ state of \a other is transferred to the newly constructed instance.
+ After the move, \a other will no longer be managing any mutex.
\sa QMutex::lock()
*/
/*!
- \fn QMutexLocker::~QMutexLocker()
+ \fn template <typename Mutex> QMutexLocker<Mutex> &QMutexLocker<Mutex>::operator=(QMutexLocker &&other) noexcept
+ \since 6.4
+
+ Move-assigns \a other onto this QMutexLocker. If this QMutexLocker
+ was holding a locked mutex before the assignment, the mutex will be
+ unlocked. The mutex and the state of \a other is then transferred
+ to this QMutexLocker. After the move, \a other will no longer be
+ managing any mutex.
+
+ \sa QMutex::lock()
+*/
+
+/*!
+ \fn template <typename Mutex> void QMutexLocker<Mutex>::swap(QMutexLocker &other) noexcept
+ \since 6.4
+
+ Swaps the mutex and the state of this QMutexLocker with \a other.
+ This operation is very fast and never fails.
+
+ \sa QMutex::lock()
+*/
+
+/*!
+ \fn template <typename Mutex> QMutexLocker<Mutex>::~QMutexLocker() noexcept
Destroys the QMutexLocker and unlocks the mutex that was locked
in the constructor.
@@ -508,7 +540,15 @@ QRecursiveMutex::~QRecursiveMutex()
*/
/*!
- \fn void QMutexLocker::unlock()
+ \fn template <typename Mutex> bool QMutexLocker<Mutex>::isLocked() const noexcept
+ \since 6.4
+
+ Returns true if this QMutexLocker is currently locking its associated
+ mutex, or false otherwise.
+*/
+
+/*!
+ \fn template <typename Mutex> void QMutexLocker<Mutex>::unlock() noexcept
Unlocks this mutex locker. You can use \c relock() to lock
it again. It does not need to be locked when destroyed.
@@ -517,7 +557,7 @@ QRecursiveMutex::~QRecursiveMutex()
*/
/*!
- \fn void QMutexLocker::relock()
+ \fn template <typename Mutex> void QMutexLocker<Mutex>::relock() noexcept
Relocks an unlocked mutex locker.
@@ -525,14 +565,12 @@ QRecursiveMutex::~QRecursiveMutex()
*/
/*!
- \fn QMutex *QMutexLocker::mutex() const
+ \fn template <typename Mutex> QMutex *QMutexLocker<Mutex>::mutex() const
Returns the mutex on which the QMutexLocker is operating.
*/
-#ifndef QT_LINUX_FUTEX //linux implementation is in qmutex_linux.cpp
-
/*
For a rough introduction on how this works, refer to
http://woboq.com/blog/internals-of-qmutex-in-qt5.html
@@ -553,28 +591,125 @@ QRecursiveMutex::~QRecursiveMutex()
possiblyUnlocked flag.
*/
+/*
+ * QBasicMutex implementation with futexes (Linux, Windows 10)
+ *
+ * QBasicMutex contains one pointer value, which can contain one of four
+ * different values:
+ * 0x0 unlocked
+ * 0x1 locked, no waiters
+ * 0x3 locked, at least one waiter
+ *
+ * LOCKING:
+ *
+ * A starts in the 0x0 state, indicating that it's unlocked. When the first
+ * thread attempts to lock it, it will perform a testAndSetAcquire
+ * from 0x0 to 0x1. If that succeeds, the caller concludes that it
+ * successfully locked the mutex. That happens in fastTryLock().
+ *
+ * If that testAndSetAcquire fails, QBasicMutex::lockInternal is called.
+ *
+ * lockInternal will examine the value of the pointer. Otherwise, it will use
+ * futexes to sleep and wait for another thread to unlock. To do that, it needs
+ * to set a pointer value of 0x3, which indicates that thread is waiting. It
+ * does that by a simple fetchAndStoreAcquire operation.
+ *
+ * If the pointer value was 0x0, it means we succeeded in acquiring the mutex.
+ * For other values, it will then call FUTEX_WAIT and with an expected value of
+ * 0x3.
+ *
+ * If the pointer value changed before futex(2) managed to sleep, it will
+ * return -1 / EWOULDBLOCK, in which case we have to start over. And even if we
+ * are woken up directly by a FUTEX_WAKE, we need to acquire the mutex, so we
+ * start over again.
+ *
+ * UNLOCKING:
+ *
+ * To unlock, we need to set a value of 0x0 to indicate it's unlocked. The
+ * first attempt is a testAndSetRelease operation from 0x1 to 0x0. If that
+ * succeeds, we're done.
+ *
+ * If it fails, unlockInternal() is called. The only possibility is that the
+ * mutex value was 0x3, which indicates some other thread is waiting or was
+ * waiting in the past. We then set the mutex to 0x0 and perform a FUTEX_WAKE.
+ */
+
/*!
\internal helper for lock()
*/
void QBasicMutex::lockInternal() QT_MUTEX_LOCK_NOEXCEPT
{
- lockInternal(-1);
+ if (futexAvailable()) {
+ // note we must set to dummyFutexValue because there could be other threads
+ // also waiting
+ while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != nullptr) {
+ // successfully set the waiting bit, now sleep
+ futexWait(d_ptr, dummyFutexValue());
+
+ // we got woken up, so try to acquire the mutex
+ }
+ Q_ASSERT(d_ptr.loadRelaxed());
+ } else {
+ lockInternal(-1);
+ }
}
/*!
\internal helper for lock(int)
*/
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
{
- Q_ASSERT(!isRecursive());
+ if (timeout == 0)
+ return false;
+
+ return lockInternal(QDeadlineTimer(timeout));
+}
+#endif
+
+/*!
+ \internal helper for tryLock(QDeadlineTimer)
+ */
+bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXCEPT
+{
+ if (deadlineTimer.hasExpired())
+ return false;
+
+ if (futexAvailable()) {
+ if (Q_UNLIKELY(deadlineTimer.isForever())) {
+ lockInternal();
+ return true;
+ }
+
+ // The mutex is already locked, set a bit indicating we're waiting.
+ // Note we must set to dummyFutexValue because there could be other threads
+ // also waiting.
+ if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
+ return true;
+
+ for (;;) {
+ if (!futexWait(d_ptr, dummyFutexValue(), deadlineTimer))
+ return false;
+
+ // We got woken up, so must try to acquire the mutex. We must set
+ // to dummyFutexValue() again because there could be other threads
+ // waiting.
+ if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
+ return true;
+
+ if (deadlineTimer.hasExpired())
+ return false;
+ }
+ }
+#if !defined(QT_ALWAYS_USE_FUTEX)
while (!fastTryLock()) {
- QMutexData *copy = d_ptr.loadAcquire();
+ QMutexPrivate *copy = d_ptr.loadAcquire();
if (!copy) // if d is 0, the mutex is unlocked
continue;
if (copy == dummyLocked()) {
- if (timeout == 0)
+ if (deadlineTimer.hasExpired())
return false;
// The mutex is locked but does not have a QMutexPrivate yet.
// we need to allocate a QMutexPrivate
@@ -589,7 +724,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
- if (timeout == 0 && !d->possiblyUnlocked.loadRelaxed())
+ if (deadlineTimer.hasExpired() && !d->possiblyUnlocked.loadRelaxed())
return false;
// At this point we have a pointer to a QMutexPrivate. But the other thread
@@ -597,7 +732,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
// We will try to reference it to avoid unlock to release it to the pool to make
// sure it won't be released. But if the refcount is already 0 it has been released.
if (!d->ref())
- continue; //that QMutexData was already released
+ continue; //that QMutexPrivate was already released
// We now hold a reference to the QMutexPrivate. It won't be released and re-used.
// But it is still possible that it was already re-used by another QMutex right before
@@ -613,7 +748,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
// is set to the BigNumber magic value set in unlockInternal()
int old_waiters;
do {
- old_waiters = d->waiters.loadRelaxed();
+ old_waiters = d->waiters.loadAcquire();
if (old_waiters == -QMutexPrivate::BigNumber) {
// we are unlocking, and the thread that unlocks is about to change d to 0
// we try to acquire the mutex by changing to dummyLocked()
@@ -642,7 +777,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
continue;
}
- if (d->wait(timeout)) {
+ if (d->wait(deadlineTimer)) {
// reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
d->deref();
@@ -651,8 +786,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
Q_ASSERT(d == d_ptr.loadRelaxed());
return true;
} else {
- Q_ASSERT(timeout >= 0);
- //timeout
+ // timed out
d->derefWaiters(1);
//There may be a race in which the mutex is unlocked right after we timed out,
// and before we deref the waiters, so maybe the mutex is actually unlocked.
@@ -667,6 +801,9 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
Q_ASSERT(d_ptr.loadRelaxed() != 0);
return true;
+#else
+ Q_UNREACHABLE();
+#endif
}
/*!
@@ -674,11 +811,16 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
*/
void QBasicMutex::unlockInternal() noexcept
{
- QMutexData *copy = d_ptr.loadAcquire();
+ QMutexPrivate *copy = d_ptr.loadAcquire();
Q_ASSERT(copy); //we must be locked
Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
- Q_ASSERT(!isRecursive());
+ if (futexAvailable()) {
+ d_ptr.storeRelease(nullptr);
+ return futexWakeOne(d_ptr);
+ }
+
+#if !defined(QT_ALWAYS_USE_FUTEX)
QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy);
// If no one is waiting for the lock anymore, we should reset d to 0x0.
@@ -700,15 +842,19 @@ void QBasicMutex::unlockInternal() noexcept
d->wakeUp();
}
d->deref();
+#else
+ Q_UNUSED(copy);
+#endif
}
+#if !defined(QT_ALWAYS_USE_FUTEX)
//The freelist management
namespace {
struct FreeListConstants : QFreeListDefaultConstants {
enum { BlockCount = 4, MaxIndex=0xffff };
static const int Sizes[BlockCount];
};
-const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
+Q_CONSTINIT const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
16,
128,
1024,
@@ -717,7 +863,7 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
// We cannot use Q_GLOBAL_STATIC because it uses QMutex
-static FreeList freeList_;
+Q_CONSTINIT static FreeList freeList_;
FreeList *freelist()
{
return &freeList_;
@@ -730,7 +876,6 @@ QMutexPrivate *QMutexPrivate::allocate()
QMutexPrivate *d = &(*freelist())[i];
d->id = i;
Q_ASSERT(d->refCount.loadRelaxed() == 0);
- Q_ASSERT(!d->recursive);
Q_ASSERT(!d->possiblyUnlocked.loadRelaxed());
Q_ASSERT(d->waiters.loadRelaxed() == 0);
d->refCount.storeRelaxed(1);
@@ -739,7 +884,6 @@ QMutexPrivate *QMutexPrivate::allocate()
void QMutexPrivate::release()
{
- Q_ASSERT(!recursive);
Q_ASSERT(refCount.loadRelaxed() == 0);
Q_ASSERT(!possiblyUnlocked.loadRelaxed());
Q_ASSERT(waiters.loadRelaxed() == 0);
@@ -762,50 +906,12 @@ void QMutexPrivate::derefWaiters(int value) noexcept
}
#endif
-/*!
- \internal
- */
-inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
-{
- Qt::HANDLE self = QThread::currentThreadId();
- if (owner.loadRelaxed() == self) {
- ++count;
- Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
- return true;
- }
- bool success = true;
- if (timeout == -1) {
- mutex.QBasicMutex::lock();
- } else {
- success = mutex.tryLock(timeout);
- }
-
- if (success)
- owner.storeRelaxed(self);
- return success;
-}
-
-/*!
- \internal
- */
-inline void QRecursiveMutexPrivate::unlock() noexcept
-{
- if (count > 0) {
- count--;
- } else {
- owner.storeRelaxed(nullptr);
- mutex.QBasicMutex::unlock();
- }
-}
-
QT_END_NAMESPACE
-#ifdef QT_LINUX_FUTEX
-# include "qmutex_linux.cpp"
-#elif defined(Q_OS_MAC)
+#if defined(QT_ALWAYS_USE_FUTEX)
+// nothing
+#elif defined(Q_OS_DARWIN)
# include "qmutex_mac.cpp"
-#elif defined(Q_OS_WIN)
-# include "qmutex_win.cpp"
#else
# include "qmutex_unix.cpp"
#endif
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 93c4bf23e8..743b86939e 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -1,62 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMUTEX_H
#define QMUTEX_H
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
-#include <new>
+#include <QtCore/qdeadlinetimer.h>
+#include <QtCore/qtsan_impl.h>
-#if __has_include(<chrono>)
-# include <chrono>
-# include <limits>
-#endif
-
-class tst_QMutex;
+#include <chrono>
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(thread) || defined(Q_QDOC)
-#if QT_CONFIG(thread) || defined(Q_CLANG_QDOC)
-
-#ifdef Q_OS_LINUX
+#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) // these platforms use futex
# define QT_MUTEX_LOCK_NOEXCEPT noexcept
#else
# define QT_MUTEX_LOCK_NOEXCEPT
@@ -64,238 +23,271 @@ QT_BEGIN_NAMESPACE
class QMutex;
class QRecursiveMutex;
-class QMutexData;
+class QMutexPrivate;
class Q_CORE_EXPORT QBasicMutex
{
+ Q_DISABLE_COPY_MOVE(QBasicMutex)
public:
-#ifdef Q_COMPILER_CONSTEXPR
constexpr QBasicMutex()
: d_ptr(nullptr)
{}
-#endif
// BasicLockable concept
inline void lock() QT_MUTEX_LOCK_NOEXCEPT {
+ QtTsan::mutexPreLock(this, 0u);
+
if (!fastTryLock())
lockInternal();
+
+ QtTsan::mutexPostLock(this, 0u, 0);
}
// BasicLockable concept
inline void unlock() noexcept {
Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
+
+ QtTsan::mutexPreUnlock(this, 0u);
+
if (!fastTryUnlock())
unlockInternal();
+
+ QtTsan::mutexPostUnlock(this, 0u);
}
bool tryLock() noexcept {
- return fastTryLock();
+ unsigned tsanFlags = QtTsan::TryLock;
+ QtTsan::mutexPreLock(this, tsanFlags);
+
+ const bool success = fastTryLock();
+
+ if (!success)
+ tsanFlags |= QtTsan::TryLockFailed;
+ QtTsan::mutexPostLock(this, tsanFlags, 0);
+
+ return success;
}
// Lockable concept
bool try_lock() noexcept { return tryLock(); }
- bool isRecursive() noexcept; //### Qt6: remove me
- bool isRecursive() const noexcept;
-
private:
- inline bool fastTryLock() noexcept {
+ inline bool fastTryLock() noexcept
+ {
+ if (d_ptr.loadRelaxed() != nullptr)
+ return false;
return d_ptr.testAndSetAcquire(nullptr, dummyLocked());
}
inline bool fastTryUnlock() noexcept {
return d_ptr.testAndSetRelease(dummyLocked(), nullptr);
}
- inline bool fastTryLock(QMutexData *&current) noexcept {
- return d_ptr.testAndSetAcquire(nullptr, dummyLocked(), current);
- }
- inline bool fastTryUnlock(QMutexData *&current) noexcept {
- return d_ptr.testAndSetRelease(dummyLocked(), nullptr, current);
- }
void lockInternal() QT_MUTEX_LOCK_NOEXCEPT;
+ bool lockInternal(QDeadlineTimer timeout) QT_MUTEX_LOCK_NOEXCEPT;
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
bool lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
+#endif
void unlockInternal() noexcept;
+ void destroyInternal(QMutexPrivate *d);
- QBasicAtomicPointer<QMutexData> d_ptr;
- static inline QMutexData *dummyLocked() {
- return reinterpret_cast<QMutexData *>(quintptr(1));
+ QBasicAtomicPointer<QMutexPrivate> d_ptr;
+ static inline QMutexPrivate *dummyLocked() {
+ return reinterpret_cast<QMutexPrivate *>(quintptr(1));
}
friend class QMutex;
- friend class QRecursiveMutex;
- friend class QMutexData;
+ friend class QMutexPrivate;
};
class Q_CORE_EXPORT QMutex : public QBasicMutex
{
public:
-#if defined(Q_COMPILER_CONSTEXPR)
constexpr QMutex() = default;
-#else
- QMutex() { d_ptr.storeRelaxed(nullptr); }
-#endif
- enum RecursionMode { NonRecursive, Recursive };
- explicit QMutex(RecursionMode mode);
- ~QMutex();
+ ~QMutex()
+ {
+ QMutexPrivate *d = d_ptr.loadRelaxed();
+ if (d)
+ destroyInternal(d);
+ }
- // BasicLockable concept
- void lock() QT_MUTEX_LOCK_NOEXCEPT;
- bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT;
- // BasicLockable concept
- void unlock() noexcept;
+#ifdef Q_QDOC
+ inline void lock() QT_MUTEX_LOCK_NOEXCEPT;
+ inline void unlock() noexcept;
+ bool tryLock() noexcept;
+#endif
// Lockable concept
- bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
+ bool try_lock() noexcept { return tryLock(); }
+
+
+ using QBasicMutex::tryLock;
+ bool tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
+ {
+ return tryLock(QDeadlineTimer(timeout));
+ }
+
+ bool tryLock(QDeadlineTimer timeout) QT_MUTEX_LOCK_NOEXCEPT
+ {
+ unsigned tsanFlags = QtTsan::TryLock;
+ QtTsan::mutexPreLock(this, tsanFlags);
+
+ bool success = fastTryLock();
+
+ if (success) {
+ QtTsan::mutexPostLock(this, tsanFlags, 0);
+ return success;
+ }
+
+ success = lockInternal(timeout);
+
+ if (!success)
+ tsanFlags |= QtTsan::TryLockFailed;
+ QtTsan::mutexPostLock(this, tsanFlags, 0);
+
+ return success;
+ }
-#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
// TimedLockable concept
template <class Rep, class Period>
bool try_lock_for(std::chrono::duration<Rep, Period> duration)
{
- return tryLock(convertToMilliseconds(duration));
+ return tryLock(QDeadlineTimer(duration));
}
// TimedLockable concept
template<class Clock, class Duration>
bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
{
- // Implemented in terms of try_lock_for to honor the similar
- // requirement in N4606 § 30.4.1.3 [thread.timedmutex.requirements]/12.
-
- return try_lock_for(timePoint - Clock::now());
+ return tryLock(QDeadlineTimer(timePoint));
}
-#endif
+};
- bool isRecursive() const noexcept
- { return QBasicMutex::isRecursive(); }
+class Q_CORE_EXPORT QRecursiveMutex
+{
+ Q_DISABLE_COPY_MOVE(QRecursiveMutex)
+ // written to by the thread that first owns 'mutex';
+ // read during attempts to acquire ownership of 'mutex' from any other thread:
+ QAtomicPointer<void> owner = nullptr;
+ // only ever accessed from the thread that owns 'mutex':
+ uint count = 0;
+ QMutex mutex;
-private:
- Q_DISABLE_COPY(QMutex)
- friend class QMutexLocker;
- friend class QRecursiveMutex;
- friend class ::tst_QMutex;
+public:
+ constexpr QRecursiveMutex() = default;
+ ~QRecursiveMutex();
+
+
+ // BasicLockable concept
+ void lock() QT_MUTEX_LOCK_NOEXCEPT
+ { tryLock(QDeadlineTimer(QDeadlineTimer::Forever)); }
+ QT_CORE_INLINE_SINCE(6, 6)
+ bool tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
+ bool tryLock(QDeadlineTimer timer = {}) QT_MUTEX_LOCK_NOEXCEPT;
+ // BasicLockable concept
+ void unlock() noexcept;
+
+ // Lockable concept
+ bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
-#if __has_include(<chrono>)
- template<class Rep, class Period>
- static int convertToMilliseconds(std::chrono::duration<Rep, Period> duration)
+ // TimedLockable concept
+ template <class Rep, class Period>
+ bool try_lock_for(std::chrono::duration<Rep, Period> duration)
{
- // N4606 § 30.4.1.3.5 [thread.timedmutex.requirements] specifies that a
- // duration less than or equal to duration.zero() shall result in a
- // try_lock, unlike QMutex's tryLock with a negative duration which
- // results in a lock.
-
- if (duration <= duration.zero())
- return 0;
-
- // when converting from 'duration' to milliseconds, make sure that
- // the result is not shorter than 'duration':
- std::chrono::milliseconds wait = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
- if (wait < duration)
- wait += std::chrono::milliseconds(1);
- Q_ASSERT(wait >= duration);
- const auto ms = wait.count();
- const auto maxInt = (std::numeric_limits<int>::max)();
-
- return ms < maxInt ? int(ms) : maxInt;
+ return tryLock(QDeadlineTimer(duration));
+ }
+
+ // TimedLockable concept
+ template<class Clock, class Duration>
+ bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
+ {
+ return tryLock(QDeadlineTimer(timePoint));
}
-#endif
};
-class QRecursiveMutex : private QMutex
+#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
+bool QRecursiveMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
{
- // ### Qt 6: make it independent of QMutex
- friend class QMutexLocker;
-public:
- Q_CORE_EXPORT QRecursiveMutex();
- Q_CORE_EXPORT ~QRecursiveMutex();
-
- using QMutex::lock;
- using QMutex::tryLock;
- using QMutex::unlock;
- using QMutex::try_lock;
-#if __has_include(<chrono>)
- using QMutex::try_lock_for;
- using QMutex::try_lock_until;
+ return tryLock(QDeadlineTimer(timeout));
+}
#endif
-};
-class Q_CORE_EXPORT QMutexLocker
+template <typename Mutex>
+class QMutexLocker
{
public:
-#ifndef Q_CLANG_QDOC
- inline explicit QMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT
+ Q_NODISCARD_CTOR
+ inline explicit QMutexLocker(Mutex *mutex) QT_MUTEX_LOCK_NOEXCEPT
{
- Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
- "QMutexLocker", "QMutex pointer is misaligned");
- val = quintptr(m);
- if (Q_LIKELY(m)) {
- // call QMutex::lock() instead of QBasicMutex::lock()
- static_cast<QMutex *>(m)->lock();
- val |= 1;
+ m_mutex = mutex;
+ if (Q_LIKELY(mutex)) {
+ mutex->lock();
+ m_isLocked = true;
}
}
- explicit QMutexLocker(QRecursiveMutex *m) QT_MUTEX_LOCK_NOEXCEPT
- : QMutexLocker{static_cast<QBasicMutex*>(m)} {}
-#else
- QMutexLocker(QMutex *) { }
- QMutexLocker(QRecursiveMutex *) {}
-#endif
- inline ~QMutexLocker() { unlock(); }
- inline void unlock() noexcept
+ Q_NODISCARD_CTOR
+ inline QMutexLocker(QMutexLocker &&other) noexcept
+ : m_mutex(std::exchange(other.m_mutex, nullptr)),
+ m_isLocked(std::exchange(other.m_isLocked, false))
+ {}
+
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMutexLocker)
+
+ inline ~QMutexLocker()
{
- if ((val & quintptr(1u)) == quintptr(1u)) {
- val &= ~quintptr(1u);
- mutex()->unlock();
- }
+ if (m_isLocked)
+ unlock();
}
- inline void relock() QT_MUTEX_LOCK_NOEXCEPT
+ inline bool isLocked() const noexcept
{
- if (val) {
- if ((val & quintptr(1u)) == quintptr(0u)) {
- mutex()->lock();
- val |= quintptr(1u);
- }
- }
+ return m_isLocked;
}
-#if defined(Q_CC_MSVC)
-#pragma warning( push )
-#pragma warning( disable : 4312 ) // ignoring the warning from /Wp64
-#endif
+ inline void unlock() noexcept
+ {
+ Q_ASSERT(m_isLocked);
+ m_mutex->unlock();
+ m_isLocked = false;
+ }
- inline QMutex *mutex() const
+ inline void relock() QT_MUTEX_LOCK_NOEXCEPT
{
- return reinterpret_cast<QMutex *>(val & ~quintptr(1u));
+ Q_ASSERT(!m_isLocked);
+ m_mutex->lock();
+ m_isLocked = true;
}
-#if defined(Q_CC_MSVC)
-#pragma warning( pop )
-#endif
+ inline void swap(QMutexLocker &other) noexcept
+ {
+ qt_ptr_swap(m_mutex, other.m_mutex);
+ std::swap(m_isLocked, other.m_isLocked);
+ }
+ Mutex *mutex() const
+ {
+ return m_mutex;
+ }
private:
Q_DISABLE_COPY(QMutexLocker)
- quintptr val;
+ Mutex *m_mutex;
+ bool m_isLocked = false;
};
-#else // !QT_CONFIG(thread) && !Q_CLANG_QDOC
+#else // !QT_CONFIG(thread) && !Q_QDOC
-class Q_CORE_EXPORT QMutex
+class QMutex
{
public:
- enum RecursionMode { NonRecursive, Recursive };
- inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) noexcept { }
+ constexpr QMutex() noexcept { }
inline void lock() noexcept {}
inline bool tryLock(int timeout = 0) noexcept { Q_UNUSED(timeout); return true; }
inline bool try_lock() noexcept { return true; }
inline void unlock() noexcept {}
- inline bool isRecursive() const noexcept { return true; }
-#if __has_include(<chrono>)
template <class Rep, class Period>
inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
{
@@ -309,7 +301,6 @@ public:
Q_UNUSED(timePoint);
return true;
}
-#endif
private:
Q_DISABLE_COPY(QMutex)
@@ -317,15 +308,17 @@ private:
class QRecursiveMutex : public QMutex {};
-class Q_CORE_EXPORT QMutexLocker
+template <typename Mutex>
+class QMutexLocker
{
public:
- inline explicit QMutexLocker(QMutex *) noexcept {}
+ Q_NODISCARD_CTOR
+ inline explicit QMutexLocker(Mutex *) noexcept {}
inline ~QMutexLocker() noexcept {}
inline void unlock() noexcept {}
void relock() noexcept {}
- inline QMutex *mutex() const noexcept { return nullptr; }
+ inline Mutex *mutex() const noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QMutexLocker)
@@ -333,7 +326,7 @@ private:
typedef QMutex QBasicMutex;
-#endif // !QT_CONFIG(thread) && !Q_CLANG_QDOC
+#endif // !QT_CONFIG(thread) && !Q_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
deleted file mode 100644
index 72002838cf..0000000000
--- a/src/corelib/thread/qmutex_linux.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-#include "qmutex.h"
-#include "qatomic.h"
-#include "qmutex_p.h"
-#include "qfutex_p.h"
-
-#ifndef QT_ALWAYS_USE_FUTEX
-# error "Qt build is broken: qmutex_linux.cpp is being built but futex support is not wanted"
-#endif
-
-#ifndef FUTEX_PRIVATE_FLAG
-# define FUTEX_PRIVATE_FLAG 0
-#endif
-
-QT_BEGIN_NAMESPACE
-
-using namespace QtFutex;
-
-/*
- * QBasicMutex implementation on Linux with futexes
- *
- * QBasicMutex contains one pointer value, which can contain one of four
- * different values:
- * 0x0 unlocked, non-recursive mutex
- * 0x1 locked non-recursive mutex, no waiters
- * 0x3 locked non-recursive mutex, at least one waiter
- * > 0x3 recursive mutex, points to a QMutexPrivate object
- *
- * LOCKING (non-recursive):
- *
- * A non-recursive mutex starts in the 0x0 state, indicating that it's
- * unlocked. When the first thread attempts to lock it, it will perform a
- * testAndSetAcquire from 0x0 to 0x1. If that succeeds, the caller concludes
- * that it successfully locked the mutex. That happens in fastTryLock().
- *
- * If that testAndSetAcquire fails, QBasicMutex::lockInternal is called.
- *
- * lockInternal will examine the value of the pointer. Otherwise, it will use
- * futexes to sleep and wait for another thread to unlock. To do that, it needs
- * to set a pointer value of 0x3, which indicates that thread is waiting. It
- * does that by a simple fetchAndStoreAcquire operation.
- *
- * If the pointer value was 0x0, it means we succeeded in acquiring the mutex.
- * For other values, it will then call FUTEX_WAIT and with an expected value of
- * 0x3.
- *
- * If the pointer value changed before futex(2) managed to sleep, it will
- * return -1 / EWOULDBLOCK, in which case we have to start over. And even if we
- * are woken up directly by a FUTEX_WAKE, we need to acquire the mutex, so we
- * start over again.
- *
- * UNLOCKING (non-recursive):
- *
- * To unlock, we need to set a value of 0x0 to indicate it's unlocked. The
- * first attempt is a testAndSetRelease operation from 0x1 to 0x0. If that
- * succeeds, we're done.
- *
- * If it fails, unlockInternal() is called. The only possibility is that the
- * mutex value was 0x3, which indicates some other thread is waiting or was
- * waiting in the past. We then set the mutex to 0x0 and perform a FUTEX_WAKE.
- */
-
-static inline QMutexData *dummyFutexValue()
-{
- return reinterpret_cast<QMutexData *>(quintptr(3));
-}
-
-template <bool IsTimed> static inline
-bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = nullptr) noexcept
-{
- if (!IsTimed)
- timeout = -1;
-
- // we're here because fastTryLock() has just failed
- if (timeout == 0)
- return false;
-
- // the mutex is locked already, set a bit indicating we're waiting
- if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
- return true;
-
- qint64 nstimeout = timeout * Q_INT64_C(1000) * 1000;
- qint64 remainingTime = nstimeout;
- forever {
- // successfully set the waiting bit, now sleep
- if (IsTimed && nstimeout >= 0) {
- bool r = futexWait(d_ptr, dummyFutexValue(), remainingTime);
- if (!r)
- return false;
-
- // we got woken up, so try to acquire the mutex
- // note we must set to dummyFutexValue because there could be other threads
- // also waiting
- if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
- return true;
-
- // recalculate the timeout
- remainingTime = nstimeout - elapsedTimer->nsecsElapsed();
- if (remainingTime <= 0)
- return false;
- } else {
- futexWait(d_ptr, dummyFutexValue());
-
- // we got woken up, so try to acquire the mutex
- // note we must set to dummyFutexValue because there could be other threads
- // also waiting
- if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
- return true;
- }
- }
-
- Q_ASSERT(d_ptr.loadRelaxed());
- return true;
-}
-
-void QBasicMutex::lockInternal() noexcept
-{
- Q_ASSERT(!isRecursive());
- lockInternal_helper<false>(d_ptr);
-}
-
-bool QBasicMutex::lockInternal(int timeout) noexcept
-{
- Q_ASSERT(!isRecursive());
- QElapsedTimer elapsedTimer;
- elapsedTimer.start();
- return lockInternal_helper<true>(d_ptr, timeout, &elapsedTimer);
-}
-
-void QBasicMutex::unlockInternal() noexcept
-{
- QMutexData *d = d_ptr.loadRelaxed();
- Q_ASSERT(d); //we must be locked
- Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
- Q_UNUSED(d);
- Q_ASSERT(!isRecursive());
-
- d_ptr.storeRelease(nullptr);
- futexWakeOne(d_ptr);
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp
index 923f89f697..7849133e58 100644
--- a/src/corelib/thread/qmutex_mac.cpp
+++ b/src/corelib/thread/qmutex_mac.cpp
@@ -1,46 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qmutex.h"
#include "qmutex_p.h"
+#include "private/qcore_unix_p.h"
+
#include <mach/mach.h>
#include <mach/task.h>
@@ -62,18 +28,19 @@ QMutexPrivate::~QMutexPrivate()
qWarning("QMutex: failed to destroy semaphore, error %d", r);
}
-bool QMutexPrivate::wait(int timeout)
+bool QMutexPrivate::wait(QDeadlineTimer timeout)
{
kern_return_t r;
- if (timeout < 0) {
+ if (timeout.isForever()) {
do {
r = semaphore_wait(mach_semaphore);
} while (r == KERN_ABORTED);
Q_ASSERT(r == KERN_SUCCESS);
} else {
+ timespec tv = durationToTimespec(timeout.remainingTimeAsDuration());
mach_timespec_t ts;
- ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
- ts.tv_sec = (timeout / 1000);
+ ts.tv_nsec = tv.tv_nsec;
+ ts.tv_sec = tv.tv_sec;
r = semaphore_timedwait(mach_semaphore, ts);
}
return (r == KERN_SUCCESS);
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index 048d8707c4..aabb66fa55 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMUTEX_P_H
#define QMUTEX_P_H
@@ -46,10 +10,9 @@
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header
-// file may change from version to version without notice, or even be
-// removed.
+// This file is not part of the Qt API. It exists for the convenience of
+// qmutex.cpp and qmutex_unix.cpp. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -60,45 +23,35 @@
#include <QtCore/qatomic.h>
#include <QtCore/qdeadlinetimer.h>
-#if defined(Q_OS_MAC)
+#include "qplatformdefs.h" // _POSIX_VERSION
+
+#if defined(Q_OS_DARWIN)
# include <mach/semaphore.h>
-#elif defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
-// use Linux mutexes everywhere except for LSB builds
-# define QT_LINUX_FUTEX
#elif defined(Q_OS_UNIX)
-# if _POSIX_VERSION-0 >= 200112L || _XOPEN_VERSION-0 >= 600
# include <semaphore.h>
-# define QT_UNIX_SEMAPHORE
-# endif
#endif
struct timespec;
QT_BEGIN_NAMESPACE
-class QMutexData
-{
-public:
- bool recursive;
- QMutexData(QMutex::RecursionMode mode = QMutex::NonRecursive)
- : recursive(mode == QMutex::Recursive) {}
-};
-
-#if !defined(QT_LINUX_FUTEX)
-class QMutexPrivate : public QMutexData
+// We manipulate the pointer to this class in inline, atomic code,
+// so syncqt mustn't mark them as private, so ELFVERSION:ignore-next
+class QMutexPrivate
{
public:
~QMutexPrivate();
QMutexPrivate();
- bool wait(int timeout = -1);
+ bool wait(QDeadlineTimer timeout = QDeadlineTimer::Forever);
void wakeUp() noexcept;
// Control the lifetime of the privates
QAtomicInt refCount;
int id;
- bool ref() {
+ bool ref()
+ {
Q_ASSERT(refCount.loadRelaxed() >= 0);
int c;
do {
@@ -109,7 +62,8 @@ public:
Q_ASSERT(refCount.loadRelaxed() >= 0);
return true;
}
- void deref() {
+ void deref()
+ {
Q_ASSERT(refCount.loadRelaxed() >= 0);
if (!refCount.deref())
release();
@@ -128,27 +82,12 @@ public:
void derefWaiters(int value) noexcept;
//platform specific stuff
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
semaphore_t mach_semaphore;
-#elif defined(QT_UNIX_SEMAPHORE)
- sem_t semaphore;
#elif defined(Q_OS_UNIX)
- bool wakeup;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-#elif defined(Q_OS_WIN)
- Qt::HANDLE event;
+ sem_t semaphore;
#endif
};
-#endif //QT_LINUX_FUTEX
-
-
-#ifdef Q_OS_UNIX
-// helper functions for qmutex_unix.cpp and qwaitcondition_unix.cpp
-// they are in qwaitcondition_unix.cpp actually
-void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where);
-void qt_abstime_for_timeout(struct timespec *ts, QDeadlineTimer deadline);
-#endif
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index df2f606a23..4d01deb7d4 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -1,47 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qmutex.h"
#include "qstring.h"
-#include "qelapsedtimer.h"
#include "qatomic.h"
#include "qmutex_p.h"
#include <errno.h>
@@ -55,105 +18,48 @@
QT_BEGIN_NAMESPACE
-static void report_error(int code, const char *where, const char *what)
+static void qt_report_error(int code, const char *where, const char *what)
{
if (code != 0)
qErrnoWarning(code, "%s: %s failure", where, what);
}
-#ifdef QT_UNIX_SEMAPHORE
-
QMutexPrivate::QMutexPrivate()
{
- report_error(sem_init(&semaphore, 0, 0), "QMutex", "sem_init");
+ qt_report_error(sem_init(&semaphore, 0, 0), "QMutex", "sem_init");
}
QMutexPrivate::~QMutexPrivate()
{
- report_error(sem_destroy(&semaphore), "QMutex", "sem_destroy");
+ qt_report_error(sem_destroy(&semaphore), "QMutex", "sem_destroy");
}
-bool QMutexPrivate::wait(int timeout)
+bool QMutexPrivate::wait(QDeadlineTimer timeout)
{
int errorCode;
- if (timeout < 0) {
+ if (timeout.isForever()) {
do {
errorCode = sem_wait(&semaphore);
} while (errorCode && errno == EINTR);
- report_error(errorCode, "QMutex::lock()", "sem_wait");
+ qt_report_error(errorCode, "QMutex::lock()", "sem_wait");
} else {
- timespec ts;
- report_error(clock_gettime(CLOCK_REALTIME, &ts), "QMutex::lock()", "clock_gettime");
- ts.tv_sec += timeout / 1000;
- ts.tv_nsec += timeout % 1000 * Q_UINT64_C(1000) * 1000;
- normalizedTimespec(ts);
do {
+ auto tp = timeout.deadline<std::chrono::system_clock>();
+ timespec ts = durationToTimespec(tp.time_since_epoch());
errorCode = sem_timedwait(&semaphore, &ts);
} while (errorCode && errno == EINTR);
if (errorCode && errno == ETIMEDOUT)
return false;
- report_error(errorCode, "QMutex::lock()", "sem_timedwait");
+ qt_report_error(errorCode, "QMutex::lock()", "sem_timedwait");
}
return true;
}
void QMutexPrivate::wakeUp() noexcept
{
- report_error(sem_post(&semaphore), "QMutex::unlock", "sem_post");
-}
-
-#else // QT_UNIX_SEMAPHORE
-
-QMutexPrivate::QMutexPrivate()
- : wakeup(false)
-{
- report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
- qt_initialize_pthread_cond(&cond, "QMutex");
-}
-
-QMutexPrivate::~QMutexPrivate()
-{
- report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
- report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
-}
-
-bool QMutexPrivate::wait(int timeout)
-{
- report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock");
- int errorCode = 0;
- while (!wakeup) {
- if (timeout < 0) {
- errorCode = pthread_cond_wait(&cond, &mutex);
- } else {
- timespec ti;
- qt_abstime_for_timeout(&ti, QDeadlineTimer(timeout));
- errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
- }
- if (errorCode) {
- if (errorCode == ETIMEDOUT) {
- if (wakeup)
- errorCode = 0;
- break;
- }
- report_error(errorCode, "QMutex::lock()", "cv wait");
- }
- }
- bool ret = wakeup;
- wakeup = false;
- report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
- return ret;
-}
-
-void QMutexPrivate::wakeUp() noexcept
-{
- report_error(pthread_mutex_lock(&mutex), "QMutex::unlock", "mutex lock");
- wakeup = true;
- report_error(pthread_cond_signal(&cond), "QMutex::unlock", "cv signal");
- report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
+ qt_report_error(sem_post(&semaphore), "QMutex::unlock", "sem_post");
}
-#endif
-
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
deleted file mode 100644
index 73673cd5fb..0000000000
--- a/src/corelib/thread/qmutex_win.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmutex.h"
-#include <qatomic.h>
-#include "qmutex_p.h"
-#include <qt_windows.h>
-
-QT_BEGIN_NAMESPACE
-
-QMutexPrivate::QMutexPrivate()
-{
- event = CreateEvent(0, FALSE, FALSE, 0);
-
- if (!event)
- qWarning("QMutexData::QMutexData: Cannot create event");
-}
-
-QMutexPrivate::~QMutexPrivate()
-{ CloseHandle(event); }
-
-bool QMutexPrivate::wait(int timeout)
-{
- return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);
-}
-
-void QMutexPrivate::wakeUp() noexcept
-{ SetEvent(event); }
-
-QT_END_NAMESPACE
diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h
index 83edfd5879..fb2e223e01 100644
--- a/src/corelib/thread/qorderedmutexlocker_p.h
+++ b/src/corelib/thread/qorderedmutexlocker_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QORDEREDMUTEXLOCKER_P_H
#define QORDEREDMUTEXLOCKER_P_H
@@ -67,6 +31,7 @@ QT_BEGIN_NAMESPACE
class QOrderedMutexLocker
{
public:
+ Q_NODISCARD_CTOR
QOrderedMutexLocker(QBasicMutex *m1, QBasicMutex *m2)
: mtx1((m1 == m2) ? m1 : (std::less<QBasicMutex *>()(m1, m2) ? m1 : m2)),
mtx2((m1 == m2) ? nullptr : (std::less<QBasicMutex *>()(m1, m2) ? m2 : m1)),
@@ -74,6 +39,25 @@ public:
{
relock();
}
+
+ Q_DISABLE_COPY(QOrderedMutexLocker)
+
+ void swap(QOrderedMutexLocker &other) noexcept
+ {
+ qSwap(this->mtx1, other.mtx1);
+ qSwap(this->mtx2, other.mtx2);
+ qSwap(this->locked, other.locked);
+ }
+
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QOrderedMutexLocker)
+
+ Q_NODISCARD_CTOR
+ QOrderedMutexLocker(QOrderedMutexLocker &&other) noexcept
+ : mtx1(std::exchange(other.mtx1, nullptr))
+ , mtx2(std::exchange(other.mtx2, nullptr))
+ , locked(std::exchange(other.locked, false))
+ {}
+
~QOrderedMutexLocker()
{
unlock();
@@ -88,6 +72,21 @@ public:
}
}
+ /*!
+ \internal
+ Can be called if the mutexes have been unlocked manually, and sets the
+ state of the QOrderedMutexLocker to unlocked.
+ The caller is expected to have unlocked both of them if they
+ are not the same. Calling this method when the QOrderedMutexLocker is
+ unlocked or when the provided mutexes have not actually been unlocked is
+ UB.
+ */
+ void dismiss()
+ {
+ Q_ASSERT(locked);
+ locked = false;
+ }
+
void unlock()
{
if (locked) {
@@ -119,51 +118,26 @@ private:
bool locked;
};
-class QBasicMutexLocker
-{
-public:
- inline explicit QBasicMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT
- : m(m), isLocked(true)
- {
- m->lock();
- }
- inline ~QBasicMutexLocker() { if (isLocked) unlock(); }
-
- inline void unlock() noexcept
- {
- isLocked = false;
- m->unlock();
- }
-
- inline void relock() QT_MUTEX_LOCK_NOEXCEPT
- {
- isLocked = true;
- m->lock();
- }
-
-private:
- Q_DISABLE_COPY(QBasicMutexLocker)
-
- QBasicMutex *m;
- bool isLocked;
-};
-
#else
class QOrderedMutexLocker
{
public:
+ Q_DISABLE_COPY(QOrderedMutexLocker)
+ Q_NODISCARD_CTOR
QOrderedMutexLocker(QBasicMutex *, QBasicMutex *) {}
+ Q_NODISCARD_CTOR
+ QOrderedMutexLocker(QOrderedMutexLocker &&) = default;
+ QOrderedMutexLocker& operator=(QOrderedMutexLocker &&other) = default;
~QOrderedMutexLocker() {}
void relock() {}
void unlock() {}
+ void dismiss() {}
static bool relock(QBasicMutex *, QBasicMutex *) { return false; }
};
-using QBasicMutexLocker = QMutexLocker;
-
#endif
diff --git a/src/corelib/thread/qpromise.h b/src/corelib/thread/qpromise.h
index 9cd9238381..c2b6c119ae 100644
--- a/src/corelib/thread/qpromise.h
+++ b/src/corelib/thread/qpromise.h
@@ -1,102 +1,78 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROMISE_H
#define QPROMISE_H
#include <QtCore/qglobal.h>
-#include <QtCore/qfuture.h>
+#include <QtCore/qfutureinterface.h>
+
+#include <utility>
QT_REQUIRE_CONFIG(future);
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+
+template<class T, class U>
+using EnableIfSameOrConvertible = std::enable_if_t<std::is_convertible_v<T, U>>;
+
+} // namespace QtPrivate
+
template<typename T>
class QPromise
{
- static_assert (std::is_copy_constructible_v<T>
- || std::is_move_constructible_v<T>
+ static_assert (std::is_move_constructible_v<T>
|| std::is_same_v<T, void>,
- "Type with copy or move constructors or type void is required");
+ "A move-constructible type or type void is required");
public:
QPromise() = default;
Q_DISABLE_COPY(QPromise)
- QPromise(QPromise<T> &&other) : d(other.d)
- {
- // In constructor, there's no need to perform swap(). Assign new
- // QFutureInterface to other.d instead which is slightly cheaper.
- other.d = QFutureInterface<T>();
- }
- QPromise& operator=(QPromise<T> &&other)
- {
- swap(other);
- return *this;
- }
+ QPromise(QPromise<T> &&other) = default;
+ QPromise(const QFutureInterface<T> &other) : d(other) {}
+ QPromise(QFutureInterface<T> &&other) noexcept : d(std::move(other)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPromise)
~QPromise()
{
- const int state = d.loadState();
- // If QFutureInterface has no state, there is nothing to be done
- if (state == static_cast<int>(QFutureInterfaceBase::State::NoState))
- return;
- // Otherwise, if computation is not finished at this point, cancel
+ // If computation is not finished at this point, cancel
// potential waits
- if (!(state & QFutureInterfaceBase::State::Finished)) {
- d.cancel();
- reportFinished(); // required to finalize the state
+ if (d.d && !(d.loadState() & QFutureInterfaceBase::State::Finished)) {
+ d.cancelAndFinish(); // cancel and finalize the state
+ d.runContinuation();
}
+ d.cleanContinuation();
}
// Core QPromise APIs
QFuture<T> future() const { return d.future(); }
- template<typename U = T,
- typename = QtPrivate::EnableForNonVoid<std::decay_t<U>>,
- typename = QtPrivate::EnableIfSameOrConvertible<std::decay_t<U>, std::decay_t<T>>>
- void addResult(U &&result, int index = -1)
+ template<typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
+ bool emplaceResultAt(int index, Args&&...args)
+ {
+ return d.reportAndEmplaceResult(index, std::forward<Args>(args)...);
+ }
+ template<typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
+ bool emplaceResult(Args&&...args)
+ {
+ return d.reportAndEmplaceResult(-1, std::forward<Args>(args)...);
+ }
+ template<typename U = T, typename = QtPrivate::EnableIfSameOrConvertible<U, T>>
+ bool addResult(U &&result, int index = -1)
{
- d.reportResult(std::forward<U>(result), index);
+ return d.reportAndEmplaceResult(index, std::forward<U>(result));
}
+ bool addResults(const QList<T> &result)
+ { return d.reportResults(result); }
#ifndef QT_NO_EXCEPTIONS
void setException(const QException &e) { d.reportException(e); }
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
void setException(std::exception_ptr e) { d.reportException(e); }
+#else
+ void setException(const std::exception_ptr &e) { d.reportException(e); }
#endif
- void reportStarted() { d.reportStarted(); }
- void reportFinished() { d.reportFinished(); }
+#endif
+ void start() { d.reportStarted(); }
+ void finish() { d.reportFinished(); }
void suspendIfRequested() { d.suspendIfRequested(); }
@@ -110,24 +86,25 @@ public:
d.setProgressValueAndText(progressValue, progressText);
}
-#if defined(Q_CLANG_QDOC) // documentation-only simplified signatures
- void addResult(const T &result, int index = -1) { }
- void addResult(T &&result, int index = -1) { }
-#endif
-
-private:
- mutable QFutureInterface<T> d = QFutureInterface<T>();
-
- void swap(QPromise<T> &other)
+ void swap(QPromise<T> &other) noexcept
{
- // Note: copy operations are expensive! They trigger several atomic
- // reference counts
- auto tmp = this->d;
- this->d = other.d;
- other.d = tmp;
+ d.swap(other.d);
}
+
+#if defined(Q_QDOC) // documentation-only simplified signatures
+ bool addResult(const T &result, int index = -1) { }
+ bool addResult(T &&result, int index = -1) { }
+#endif
+private:
+ mutable QFutureInterface<T> d;
};
+template<typename T>
+inline void swap(QPromise<T> &a, QPromise<T> &b) noexcept
+{
+ a.swap(b);
+}
+
QT_END_NAMESPACE
#endif // QPROMISE_H
diff --git a/src/corelib/thread/qpromise.qdoc b/src/corelib/thread/qpromise.qdoc
index e78e16bdd6..e9c3eb4b7e 100644
--- a/src/corelib/thread/qpromise.qdoc
+++ b/src/corelib/thread/qpromise.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \class QPromise
\inmodule QtCore
@@ -62,6 +38,8 @@
\snippet snippet_qpromise.cpp multithread_init
\codeline
\snippet snippet_qpromise.cpp multithread_main
+ \codeline
+ \snippet snippet_qpromise.cpp multithread_cleanup
\sa QFuture
*/
@@ -78,6 +56,19 @@
\sa operator=()
*/
+/*! \fn template <typename T> QPromise<T>::QPromise(const QFutureInterface<T> &other)
+ \fn template <typename T> QPromise<T>::QPromise(QFutureInterface<T> &&other) noexcept
+
+ \internal
+ Constructs a QPromise with a passed QFutureInterface \a other.
+ Used internally for QtConcurrent::run(), when its callable takes
+ a reference to the associated promise as its first argument
+ (run with promise mode).
+
+ \sa operator=()
+*/
+
+
/*! \fn template <typename T> QPromise<T> &QPromise<T>::operator=(QPromise<T> &&other)
Move assigns \a other to this promise and returns a reference to this
@@ -88,8 +79,8 @@
Destroys the promise.
- \note The promise implicitly transitions to a cancelled state on destruction
- unless reportFinished() is called beforehand by the user.
+ \note The promise implicitly transitions to a canceled state on destruction
+ unless finish() is called beforehand by the user.
*/
/*! \fn template <typename T> QFuture<T> QPromise<T>::future() const
@@ -97,10 +88,40 @@
Returns a future associated with this promise.
*/
-/*! \fn template <typename T> void QPromise<T>::addResult(const T &result, int index = -1)
+/*! \fn template <typename T> bool QPromise<T>::addResult(const T &result, int index = -1)
+ \fn template <typename T> bool QPromise<T>::addResult(T &&result, int index = -1)
+
+ Same as
+ \code
+ emplaceResultAt(index, result); // first overload
+ emplaceResultAt(index, std::move(result)); // second overload
+ \endcode
+ or, if \c{index == -1} (the default)
+ \code
+ emplaceResult(result); // first overload
+ emplaceResult(std::move(result)); // second overload
+ \endcode
+
+ \sa emplaceResultAt(), emplaceResult(), addResults()
+*/
+
+/*!
+ \fn template <typename T> template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true> bool QPromise<T>::emplaceResultAt(int index, Args&&...args)
+ \fn template <typename T> template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true> bool QPromise<T>::emplaceResult(Args&&...args)
+ \since 6.6
+
+ Adds a result constructed from \a args... to the internal result collection
+ at \a index position (emplaceResultAt()) or the end of of the collection
+ (emplaceResult()).
+
+ Returns \c true when the result was added to the collection.
- Adds \a result to the internal result collection at \a index position. If
- index is unspecified, \a result is added to the end of the collection.
+ Returns \c false when this promise is in canceled or finished state or when
+ the result was rejected. addResult() rejects to add a result if there's already
+ another result in the collection stored at the same index.
+
+ These functions only participate in overload resolutions if \c T is
+ constructible from \a args....
You can get a result at a specific index by calling QFuture::resultAt().
@@ -109,11 +130,29 @@
For instance, iterative approaches that use QFuture::resultCount() or
QFuture::const_iterator. In order to get all available results without
thinking if there are index gaps or not, use QFuture::results().
+
+ \sa addResult(), addResults()
*/
-/*! \fn template <typename T> void QPromise<T>::addResult(T &&result, int index = -1)
+/*!
+ \fn template <typename T> bool QPromise<T>::addResults(const QList<T> &results)
+ \since 6.6
- \overload
+ Adds \a results at the end of the internal result collection.
+
+ Returns \c true when \a results are added to the collection.
+
+ Returns \c false when this promise is in canceled or finished state.
+
+ This is more efficient than looping over addResult(), because associated
+ futures will be notified only once per addResults() call, instead of once
+ per element contained in \a results, as would be the case with individual
+ addResult() calls. But if the calculation of each element takes time, then
+ the code on the receiving end (future) cannot make progress until all
+ results are reported, so use this function only if the calculation of
+ consecutive elements is relatively fast.
+
+ \sa addResult()
*/
/*! \fn template<typename T> void QPromise<T>::setException(const QException &e)
@@ -124,41 +163,48 @@
execution.
\note This method must not be used after QFuture::cancel() or
- reportFinished().
+ finish().
\sa isCanceled()
*/
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*! \fn template<typename T> void QPromise<T>::setException(std::exception_ptr e)
\overload
*/
+#else
+/*! \fn template<typename T> void QPromise<T>::setException(const std::exception_ptr &e)
+
+ \overload
+*/
+#endif
-/*! \fn template<typename T> void QPromise<T>::reportStarted()
+/*! \fn template<typename T> void QPromise<T>::start()
Reports that the computation is started. Calling this method is important to
state the beginning of the computation as QFuture methods rely on this
information.
- \note Extra attention is required when reportStarted() is called from a
+ \note Extra attention is required when start() is called from a
newly created thread. In such case, the call might naturally be delayed due
to the implementation details of the thread scheduling.
- \sa QFuture::isStarted(), QFuture::waitForFinished(), reportFinished()
+ \sa QFuture::isStarted(), QFuture::waitForFinished(), finish()
*/
-/*! \fn template<typename T> void QPromise<T>::reportFinished()
+/*! \fn template<typename T> void QPromise<T>::finish()
Reports that the computation is finished. Once finished, no new results will
- be added when calling addResult(). This method accompanies reportStarted().
+ be added when calling addResult(). This method accompanies start().
- \sa QFuture::isFinished(), QFuture::waitForFinished(), reportStarted()
+ \sa QFuture::isFinished(), QFuture::waitForFinished(), start()
*/
/*! \fn template<typename T> void QPromise<T>::suspendIfRequested()
Conditionally suspends current thread of execution and waits until resumed
- or cancelled by the corresponding methods of QFuture. This method does not
+ or canceled by the corresponding methods of QFuture. This method does not
block unless the computation is requested to be suspended by
QFuture::suspend() or another related method. If you want to check that the
execution has been suspended, use QFuture::isSuspended().
@@ -192,9 +238,9 @@
/*! \fn template<typename T> bool QPromise<T>::isCanceled() const
- Returns whether the computation has been cancelled with the
+ Returns whether the computation has been canceled with the
QFuture::cancel() function. The returned value \c true indicates that the
- computation should be finished and reportFinished() called.
+ computation should be finished and finish() called.
\note After cancellation, results currently available may still be accessed
by a future, but new results will not be added when calling addResult().
@@ -205,7 +251,16 @@
Sets the progress range of the computation to be between \a minimum and \a
maximum.
- \sa QFuture::progressMinimum(), QFuture::progressMaximum()
+ If \a maximum is smaller than \a minimum, \a minimum becomes the only
+ legal value.
+
+ The progress value is reset to be \a minimum.
+
+ The progress range usage can be disabled by using setProgressRange(0, 0).
+ In this case progress value is also reset to 0.
+
+ \sa QFuture::progressMinimum(), QFuture::progressMaximum(),
+ QFuture::progressValue()
*/
/*! \fn template<typename T> void QPromise<T>::setProgressValue(int progressValue)
@@ -214,7 +269,10 @@
possible to only increment the progress value. This is a convenience method
for calling setProgressValueAndText(progressValue, QString()).
- \sa QFuture::progressValue()
+ In case of the \a progressValue falling out of the progress range,
+ this method has no effect.
+
+ \sa QFuture::progressValue(), setProgressRange()
*/
/*! \fn template<typename T> void QPromise<T>::setProgressValueAndText(int progressValue, const QString &progressText)
@@ -223,9 +281,14 @@
progressValue and \a progressText respectively. It is possible to only
increment the progress value.
- \note This function has no effect if the promise is in cancelled or finished
+ \note This function has no effect if the promise is in canceled or finished
state.
\sa QFuture::progressValue(), QFuture::progressText(), QFuture::cancel(),
- reportFinished()
+ finish()
+*/
+
+/*! \fn template<typename T> void QPromise<T>::swap(QPromise<T> &other) noexcept
+
+ Swaps promise \a other with this promise. This operation is very fast and never fails.
*/
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index 8c28507d5a..e79bed2231 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -1,55 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qreadwritelock.h"
-#include "qmutex.h"
#include "qthread.h"
-#include "qwaitcondition.h"
#include "qreadwritelock_p.h"
-#include "qelapsedtimer.h"
#include "private/qfreelist_p.h"
#include "private/qlocking_p.h"
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
/*
@@ -64,18 +27,22 @@ QT_BEGIN_NAMESPACE
* - In any other case, d_ptr points to an actual QReadWriteLockPrivate.
*/
+using namespace QReadWriteLockStates;
namespace {
-enum {
- StateMask = 0x3,
- StateLockedForRead = 0x1,
- StateLockedForWrite = 0x2,
-};
+
+using steady_clock = std::chrono::steady_clock;
+
const auto dummyLockedForRead = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForRead));
const auto dummyLockedForWrite = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForWrite));
inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
{ return quintptr(d) & StateMask; }
}
+static bool contendedTryLockForRead(QAtomicPointer<QReadWriteLockPrivate> &d_ptr,
+ QDeadlineTimer timeout, QReadWriteLockPrivate *d);
+static bool contendedTryLockForWrite(QAtomicPointer<QReadWriteLockPrivate> &d_ptr,
+ QDeadlineTimer timeout, QReadWriteLockPrivate *d);
+
/*! \class QReadWriteLock
\inmodule QtCore
\brief The QReadWriteLock class provides read-write locking.
@@ -133,6 +100,7 @@ inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
*/
/*!
+ \fn QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
\since 4.4
Constructs a QReadWriteLock object in the given \a recursionMode.
@@ -141,21 +109,22 @@ inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
\sa lockForRead(), lockForWrite(), RecursionMode
*/
-QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
- : d_ptr(recursionMode == Recursive ? new QReadWriteLockPrivate(true) : nullptr)
+QReadWriteLockPrivate *QReadWriteLock::initRecursive()
{
- Q_ASSERT_X(!(quintptr(d_ptr.loadRelaxed()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
+ auto d = new QReadWriteLockPrivate(true);
+ Q_ASSERT_X(!(quintptr(d) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
+ return d;
}
/*!
+ \fn QReadWriteLock::~QReadWriteLock()
Destroys the QReadWriteLock object.
\warning Destroying a read-write lock that is in use may result
in undefined behavior.
*/
-QReadWriteLock::~QReadWriteLock()
+void QReadWriteLock::destroyRecursive(QReadWriteLockPrivate *d)
{
- auto d = d_ptr.loadRelaxed();
if (isUncontendedLocked(d)) {
qWarning("QReadWriteLock: destroying locked QReadWriteLock");
return;
@@ -164,6 +133,7 @@ QReadWriteLock::~QReadWriteLock()
}
/*!
+ \fn QReadWriteLock::lockForRead()
Locks the lock for reading. This function will block the current
thread if another thread has locked for writing.
@@ -172,20 +142,18 @@ QReadWriteLock::~QReadWriteLock()
\sa unlock(), lockForWrite(), tryLockForRead()
*/
-void QReadWriteLock::lockForRead()
-{
- if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead))
- return;
- tryLockForRead(-1);
-}
/*!
- Attempts to lock for reading. If the lock was obtained, this
- function returns \c true, otherwise it returns \c false instead of
- waiting for the lock to become available, i.e. it does not block.
+ \fn bool QReadWriteLock::tryLockForRead(int timeout)
- The lock attempt will fail if another thread has locked for
- writing.
+ Attempts to lock for reading. This function returns \c true if the
+ lock was obtained; otherwise it returns \c false. If another thread
+ has locked for writing, this function will wait for at most \a
+ timeout milliseconds for the lock to become available.
+
+ Note: Passing a negative number as the \a timeout is equivalent to
+ calling lockForRead(), i.e. this function will wait forever until
+ lock can be locked for reading when \a timeout is negative.
If the lock was obtained, the lock must be unlocked with unlock()
before another thread can successfully lock it for writing.
@@ -195,21 +163,15 @@ void QReadWriteLock::lockForRead()
\sa unlock(), lockForRead()
*/
-bool QReadWriteLock::tryLockForRead()
-{
- return tryLockForRead(0);
-}
-/*! \overload
-
- Attempts to lock for reading. This function returns \c true if the
- lock was obtained; otherwise it returns \c false. If another thread
- has locked for writing, this function will wait for at most \a
- timeout milliseconds for the lock to become available.
+/*!
+ \overload
+ \since 6.6
- Note: Passing a negative number as the \a timeout is equivalent to
- calling lockForRead(), i.e. this function will wait forever until
- lock can be locked for reading when \a timeout is negative.
+ Attempts to lock for reading. This function returns \c true if the lock was
+ obtained; otherwise it returns \c false. If another thread has locked for
+ writing, this function will wait until \a timeout expires for the lock to
+ become available.
If the lock was obtained, the lock must be unlocked with unlock()
before another thread can successfully lock it for writing.
@@ -219,13 +181,18 @@ bool QReadWriteLock::tryLockForRead()
\sa unlock(), lockForRead()
*/
-bool QReadWriteLock::tryLockForRead(int timeout)
+bool QReadWriteLock::tryLockForRead(QDeadlineTimer timeout)
{
// Fast case: non contended:
- QReadWriteLockPrivate *d;
- if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d))
+ QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
+ if (d == nullptr && d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d))
return true;
+ return contendedTryLockForRead(d_ptr, timeout, d);
+}
+Q_NEVER_INLINE static bool contendedTryLockForRead(QAtomicPointer<QReadWriteLockPrivate> &d_ptr,
+ QDeadlineTimer timeout, QReadWriteLockPrivate *d)
+{
while (true) {
if (d == nullptr) {
if (!d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d))
@@ -244,7 +211,7 @@ bool QReadWriteLock::tryLockForRead(int timeout)
}
if (d == dummyLockedForWrite) {
- if (!timeout)
+ if (timeout.hasExpired())
return false;
// locked for write, assign a d_ptr and wait.
@@ -274,11 +241,12 @@ bool QReadWriteLock::tryLockForRead(int timeout)
d = d_ptr.loadAcquire();
continue;
}
- return d->lockForRead(timeout);
+ return d->lockForRead(lock, timeout);
}
}
/*!
+ \fn QReadWriteLock::lockForWrite()
Locks the lock for writing. This function will block the current
thread if another thread (including the current) has locked for
reading or writing (unless the lock has been created using the
@@ -289,17 +257,18 @@ bool QReadWriteLock::tryLockForRead(int timeout)
\sa unlock(), lockForRead(), tryLockForWrite()
*/
-void QReadWriteLock::lockForWrite()
-{
- tryLockForWrite(-1);
-}
/*!
- Attempts to lock for writing. If the lock was obtained, this
- function returns \c true; otherwise, it returns \c false immediately.
+ \fn QReadWriteLock::tryLockForWrite(int timeout)
+
+ Attempts to lock for writing. This function returns \c true if the
+ lock was obtained; otherwise it returns \c false. If another thread
+ has locked for reading or writing, this function will wait for at
+ most \a timeout milliseconds for the lock to become available.
- The lock attempt will fail if another thread has locked for
- reading or writing.
+ Note: Passing a negative number as the \a timeout is equivalent to
+ calling lockForWrite(), i.e. this function will wait forever until
+ lock can be locked for writing when \a timeout is negative.
If the lock was obtained, the lock must be unlocked with unlock()
before another thread can successfully lock it.
@@ -309,21 +278,15 @@ void QReadWriteLock::lockForWrite()
\sa unlock(), lockForWrite()
*/
-bool QReadWriteLock::tryLockForWrite()
-{
- return tryLockForWrite(0);
-}
-
-/*! \overload
- Attempts to lock for writing. This function returns \c true if the
- lock was obtained; otherwise it returns \c false. If another thread
- has locked for reading or writing, this function will wait for at
- most \a timeout milliseconds for the lock to become available.
+/*!
+ \overload
+ \since 6.6
- Note: Passing a negative number as the \a timeout is equivalent to
- calling lockForWrite(), i.e. this function will wait forever until
- lock can be locked for writing when \a timeout is negative.
+ Attempts to lock for writing. This function returns \c true if the lock was
+ obtained; otherwise it returns \c false. If another thread has locked for
+ reading or writing, this function will wait until \a timeout expires for
+ the lock to become available.
If the lock was obtained, the lock must be unlocked with unlock()
before another thread can successfully lock it.
@@ -333,13 +296,18 @@ bool QReadWriteLock::tryLockForWrite()
\sa unlock(), lockForWrite()
*/
-bool QReadWriteLock::tryLockForWrite(int timeout)
+bool QReadWriteLock::tryLockForWrite(QDeadlineTimer timeout)
{
// Fast case: non contended:
- QReadWriteLockPrivate *d;
- if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForWrite, d))
+ QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
+ if (d == nullptr && d_ptr.testAndSetAcquire(nullptr, dummyLockedForWrite, d))
return true;
+ return contendedTryLockForWrite(d_ptr, timeout, d);
+}
+Q_NEVER_INLINE static bool contendedTryLockForWrite(QAtomicPointer<QReadWriteLockPrivate> &d_ptr,
+ QDeadlineTimer timeout, QReadWriteLockPrivate *d)
+{
while (true) {
if (d == nullptr) {
if (!d_ptr.testAndSetAcquire(d, dummyLockedForWrite, d))
@@ -348,7 +316,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
}
if (isUncontendedLocked(d)) {
- if (!timeout)
+ if (timeout.hasExpired())
return false;
// locked for either read or write, assign a d_ptr and wait.
@@ -378,7 +346,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
d = d_ptr.loadAcquire();
continue;
}
- return d->lockForWrite(timeout);
+ return d->lockForWrite(lock, timeout);
}
}
@@ -442,45 +410,19 @@ void QReadWriteLock::unlock()
}
}
-/*! \internal Helper for QWaitCondition::wait */
-QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const
+bool QReadWriteLockPrivate::lockForRead(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout)
{
- QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
- switch (quintptr(d) & StateMask) {
- case StateLockedForRead: return LockedForRead;
- case StateLockedForWrite: return LockedForWrite;
- }
-
- if (!d)
- return Unlocked;
- if (d->writerCount > 1)
- return RecursivelyLocked;
- else if (d->writerCount == 1)
- return LockedForWrite;
- return LockedForRead;
-
-}
-
-bool QReadWriteLockPrivate::lockForRead(int timeout)
-{
- Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function
-
- QElapsedTimer t;
- if (timeout > 0)
- t.start();
+ Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function
while (waitingWriters || writerCount) {
- if (timeout == 0)
+ if (timeout.hasExpired())
return false;
- if (timeout > 0) {
- auto elapsed = t.elapsed();
- if (elapsed > timeout)
- return false;
+ if (!timeout.isForever()) {
waitingReaders++;
- readerCond.wait(&mutex, QDeadlineTimer(timeout - elapsed));
+ readerCond.wait_until(lock, timeout.deadline<steady_clock>());
} else {
waitingReaders++;
- readerCond.wait(&mutex);
+ readerCond.wait(lock);
}
waitingReaders--;
}
@@ -489,32 +431,25 @@ bool QReadWriteLockPrivate::lockForRead(int timeout)
return true;
}
-bool QReadWriteLockPrivate::lockForWrite(int timeout)
+bool QReadWriteLockPrivate::lockForWrite(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout)
{
- Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function
-
- QElapsedTimer t;
- if (timeout > 0)
- t.start();
+ Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function
while (readerCount || writerCount) {
- if (timeout == 0)
- return false;
- if (timeout > 0) {
- auto elapsed = t.elapsed();
- if (elapsed > timeout) {
- if (waitingReaders && !waitingWriters && !writerCount) {
- // We timed out and now there is no more writers or waiting writers, but some
- // readers were queueud (probably because of us). Wake the waiting readers.
- readerCond.wakeAll();
- }
- return false;
+ if (timeout.hasExpired()) {
+ if (waitingReaders && !waitingWriters && !writerCount) {
+ // We timed out and now there is no more writers or waiting writers, but some
+ // readers were queued (probably because of us). Wake the waiting readers.
+ readerCond.notify_all();
}
+ return false;
+ }
+ if (!timeout.isForever()) {
waitingWriters++;
- writerCond.wait(&mutex, QDeadlineTimer(timeout - elapsed));
+ writerCond.wait_until(lock, timeout.deadline<steady_clock>());
} else {
waitingWriters++;
- writerCond.wait(&mutex);
+ writerCond.wait(lock);
}
waitingWriters--;
}
@@ -527,34 +462,41 @@ bool QReadWriteLockPrivate::lockForWrite(int timeout)
void QReadWriteLockPrivate::unlock()
{
- Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function
+ Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function
if (waitingWriters)
- writerCond.wakeOne();
+ writerCond.notify_one();
else if (waitingReaders)
- readerCond.wakeAll();
+ readerCond.notify_all();
}
-bool QReadWriteLockPrivate::recursiveLockForRead(int timeout)
+static auto handleEquals(Qt::HANDLE handle)
+{
+ return [handle](QReadWriteLockPrivate::Reader reader) { return reader.handle == handle; };
+}
+
+bool QReadWriteLockPrivate::recursiveLockForRead(QDeadlineTimer timeout)
{
Q_ASSERT(recursive);
auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
- auto it = currentReaders.find(self);
+ auto it = std::find_if(currentReaders.begin(), currentReaders.end(),
+ handleEquals(self));
if (it != currentReaders.end()) {
- ++it.value();
+ ++it->recursionLevel;
return true;
}
- if (!lockForRead(timeout))
+ if (!lockForRead(lock, timeout))
return false;
- currentReaders.insert(self, 1);
+ Reader r = {self, 1};
+ currentReaders.append(std::move(r));
return true;
}
-bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
+bool QReadWriteLockPrivate::recursiveLockForWrite(QDeadlineTimer timeout)
{
Q_ASSERT(recursive);
auto lock = qt_unique_lock(mutex);
@@ -565,7 +507,7 @@ bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
return true;
}
- if (!lockForWrite(timeout))
+ if (!lockForWrite(lock, timeout))
return false;
currentWriter = self;
@@ -583,12 +525,13 @@ void QReadWriteLockPrivate::recursiveUnlock()
return;
currentWriter = nullptr;
} else {
- auto it = currentReaders.find(self);
+ auto it = std::find_if(currentReaders.begin(), currentReaders.end(),
+ handleEquals(self));
if (it == currentReaders.end()) {
qWarning("QReadWriteLock::unlock: unlocking from a thread that did not lock");
return;
} else {
- if (--it.value() <= 0) {
+ if (--it->recursionLevel <= 0) {
currentReaders.erase(it);
readerCount--;
}
@@ -602,25 +545,24 @@ void QReadWriteLockPrivate::recursiveUnlock()
// The freelist management
namespace {
-struct FreeListConstants : QFreeListDefaultConstants {
+struct QReadWriteLockFreeListConstants : QFreeListDefaultConstants
+{
enum { BlockCount = 4, MaxIndex=0xffff };
static const int Sizes[BlockCount];
};
-const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
- 16,
- 128,
- 1024,
- FreeListConstants::MaxIndex - (16 + 128 + 1024)
-};
+Q_CONSTINIT const int
+ QReadWriteLockFreeListConstants::Sizes[QReadWriteLockFreeListConstants::BlockCount] = {
+ 16, 128, 1024, QReadWriteLockFreeListConstants::MaxIndex - (16 + 128 + 1024)
+ };
-typedef QFreeList<QReadWriteLockPrivate, FreeListConstants> FreeList;
-Q_GLOBAL_STATIC(FreeList, freelist);
+typedef QFreeList<QReadWriteLockPrivate, QReadWriteLockFreeListConstants> QReadWriteLockFreeList;
+Q_GLOBAL_STATIC(QReadWriteLockFreeList, qrwl_freelist);
}
QReadWriteLockPrivate *QReadWriteLockPrivate::allocate()
{
- int i = freelist->next();
- QReadWriteLockPrivate *d = &(*freelist)[i];
+ int i = qrwl_freelist->next();
+ QReadWriteLockPrivate *d = &(*qrwl_freelist)[i];
d->id = i;
Q_ASSERT(!d->recursive);
Q_ASSERT(!d->waitingReaders && !d->waitingWriters && !d->readerCount && !d->writerCount);
@@ -631,7 +573,7 @@ void QReadWriteLockPrivate::release()
{
Q_ASSERT(!recursive);
Q_ASSERT(!waitingReaders && !waitingWriters && !readerCount && !writerCount);
- freelist->release(id);
+ qrwl_freelist->release(id);
}
/*!
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
index 3c1ed91b94..6ca9be440a 100644
--- a/src/corelib/thread/qreadwritelock.h
+++ b/src/corelib/thread/qreadwritelock.h
@@ -1,50 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QREADWRITELOCK_H
#define QREADWRITELOCK_H
#include <QtCore/qglobal.h>
+#include <QtCore/qdeadlinetimer.h>
QT_BEGIN_NAMESPACE
-
#if QT_CONFIG(thread)
class QReadWriteLockPrivate;
@@ -54,36 +18,81 @@ class Q_CORE_EXPORT QReadWriteLock
public:
enum RecursionMode { NonRecursive, Recursive };
+ QT_CORE_INLINE_SINCE(6, 6)
explicit QReadWriteLock(RecursionMode recursionMode = NonRecursive);
+ QT_CORE_INLINE_SINCE(6, 6)
~QReadWriteLock();
+ QT_CORE_INLINE_SINCE(6, 6)
void lockForRead();
+#if QT_CORE_REMOVED_SINCE(6, 6)
bool tryLockForRead();
+#endif
+ QT_CORE_INLINE_SINCE(6, 6)
bool tryLockForRead(int timeout);
+ bool tryLockForRead(QDeadlineTimer timeout = {});
+ QT_CORE_INLINE_SINCE(6, 6)
void lockForWrite();
+#if QT_CORE_REMOVED_SINCE(6, 6)
bool tryLockForWrite();
+#endif
+ QT_CORE_INLINE_SINCE(6, 6)
bool tryLockForWrite(int timeout);
+ bool tryLockForWrite(QDeadlineTimer timeout = {});
void unlock();
private:
Q_DISABLE_COPY(QReadWriteLock)
QAtomicPointer<QReadWriteLockPrivate> d_ptr;
-
- enum StateForWaitCondition { LockedForRead, LockedForWrite, Unlocked, RecursivelyLocked };
- StateForWaitCondition stateForWaitCondition() const;
- friend class QWaitCondition;
+ friend class QReadWriteLockPrivate;
+ static QReadWriteLockPrivate *initRecursive();
+ static void destroyRecursive(QReadWriteLockPrivate *);
};
+#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
+QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
+ : d_ptr(recursionMode == Recursive ? initRecursive() : nullptr)
+{
+}
+
+QReadWriteLock::~QReadWriteLock()
+{
+ if (auto d = d_ptr.loadAcquire())
+ destroyRecursive(d);
+}
+
+void QReadWriteLock::lockForRead()
+{
+ tryLockForRead(QDeadlineTimer(QDeadlineTimer::Forever));
+}
+
+bool QReadWriteLock::tryLockForRead(int timeout)
+{
+ return tryLockForRead(QDeadlineTimer(timeout));
+}
+
+void QReadWriteLock::lockForWrite()
+{
+ tryLockForWrite(QDeadlineTimer(QDeadlineTimer::Forever));
+}
+
+bool QReadWriteLock::tryLockForWrite(int timeout)
+{
+ return tryLockForWrite(QDeadlineTimer(timeout));
+}
+#endif // inline since 6.6
+
#if defined(Q_CC_MSVC)
#pragma warning( push )
#pragma warning( disable : 4312 ) // ignoring the warning from /Wp64
#endif
-class Q_CORE_EXPORT QReadLocker
+class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
{
public:
+ Q_NODISCARD_CTOR
inline QReadLocker(QReadWriteLock *readWriteLock);
inline ~QReadLocker()
@@ -125,9 +134,10 @@ inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock)
relock();
}
-class Q_CORE_EXPORT QWriteLocker
+class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
{
public:
+ Q_NODISCARD_CTOR
inline QWriteLocker(QReadWriteLock *readWriteLock);
inline ~QWriteLocker()
@@ -176,7 +186,7 @@ inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
#else // QT_CONFIG(thread)
-class Q_CORE_EXPORT QReadWriteLock
+class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock
{
public:
enum RecursionMode { NonRecursive, Recursive };
@@ -185,10 +195,12 @@ public:
void lockForRead() noexcept { }
bool tryLockForRead() noexcept { return true; }
+ bool tryLockForRead(QDeadlineTimer) noexcept { return true; }
bool tryLockForRead(int timeout) noexcept { Q_UNUSED(timeout); return true; }
void lockForWrite() noexcept { }
bool tryLockForWrite() noexcept { return true; }
+ bool tryLockForWrite(QDeadlineTimer) noexcept { return true; }
bool tryLockForWrite(int timeout) noexcept { Q_UNUSED(timeout); return true; }
void unlock() noexcept { }
@@ -197,9 +209,10 @@ private:
Q_DISABLE_COPY(QReadWriteLock)
};
-class Q_CORE_EXPORT QReadLocker
+class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
{
public:
+ Q_NODISCARD_CTOR
inline explicit QReadLocker(QReadWriteLock *) noexcept { }
inline ~QReadLocker() noexcept { }
@@ -211,9 +224,10 @@ private:
Q_DISABLE_COPY(QReadLocker)
};
-class Q_CORE_EXPORT QWriteLocker
+class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
{
public:
+ Q_NODISCARD_CTOR
inline explicit QWriteLocker(QReadWriteLock *) noexcept { }
inline ~QWriteLocker() noexcept { }
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
index a4d002b7f2..68fa642a73 100644
--- a/src/corelib/thread/qreadwritelock_p.h
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QREADWRITELOCK_P_H
#define QREADWRITELOCK_P_H
@@ -52,23 +16,39 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qwaitcondition.h>
+#include <QtCore/private/qlocking_p.h>
+#include <QtCore/private/qwaitcondition_p.h>
+#include <QtCore/qreadwritelock.h>
+#include <QtCore/qvarlengtharray.h>
QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
+namespace QReadWriteLockStates {
+enum {
+ StateMask = 0x3,
+ StateLockedForRead = 0x1,
+ StateLockedForWrite = 0x2,
+};
+enum StateForWaitCondition {
+ LockedForRead,
+ LockedForWrite,
+ Unlocked,
+ RecursivelyLocked
+};
+}
+
class QReadWriteLockPrivate
{
public:
explicit QReadWriteLockPrivate(bool isRecursive = false)
: recursive(isRecursive) {}
- QMutex mutex;
- QWaitCondition writerCond;
- QWaitCondition readerCond;
+ alignas(QtPrivate::IdealMutexAlignment) std::condition_variable writerCond;
+ std::condition_variable readerCond;
+
+ alignas(QtPrivate::IdealMutexAlignment) std::mutex mutex;
int readerCount = 0;
int writerCount = 0;
int waitingReaders = 0;
@@ -76,8 +56,8 @@ public:
const bool recursive;
//Called with the mutex locked
- bool lockForWrite(int timeout);
- bool lockForRead(int timeout);
+ bool lockForWrite(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout);
+ bool lockForRead(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout);
void unlock();
//memory management
@@ -85,15 +65,47 @@ public:
void release();
static QReadWriteLockPrivate *allocate();
- // Recusive mutex handling
+ // Recursive mutex handling
Qt::HANDLE currentWriter = {};
- QHash<Qt::HANDLE, int> currentReaders;
+
+ struct Reader {
+ Qt::HANDLE handle;
+ int recursionLevel;
+ };
+
+ QVarLengthArray<Reader, 16> currentReaders;
// called with the mutex unlocked
- bool recursiveLockForWrite(int timeout);
- bool recursiveLockForRead(int timeout);
+ bool recursiveLockForWrite(QDeadlineTimer timeout);
+ bool recursiveLockForRead(QDeadlineTimer timeout);
void recursiveUnlock();
+
+ static QReadWriteLockStates::StateForWaitCondition
+ stateForWaitCondition(const QReadWriteLock *lock);
};
+Q_DECLARE_TYPEINFO(QReadWriteLockPrivate::Reader, Q_PRIMITIVE_TYPE);\
+
+/*! \internal Helper for QWaitCondition::wait */
+inline QReadWriteLockStates::StateForWaitCondition
+QReadWriteLockPrivate::stateForWaitCondition(const QReadWriteLock *q)
+{
+ using namespace QReadWriteLockStates;
+ QReadWriteLockPrivate *d = q->d_ptr.loadAcquire();
+ switch (quintptr(d) & StateMask) {
+ case StateLockedForRead: return LockedForRead;
+ case StateLockedForWrite: return LockedForWrite;
+ }
+
+ if (!d)
+ return Unlocked;
+ const auto lock = qt_scoped_lock(d->mutex);
+ if (d->writerCount > 1)
+ return RecursivelyLocked;
+ else if (d->writerCount == 1)
+ return LockedForWrite;
+ return LockedForRead;
+
+}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp
index 0b82b938e1..14ed7c6b87 100644
--- a/src/corelib/thread/qresultstore.cpp
+++ b/src/corelib/thread/qresultstore.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qresultstore.h"
@@ -44,6 +8,42 @@ QT_BEGIN_NAMESPACE
namespace QtPrivate {
/*!
+ \internal
+
+ Finds result in \a store by \a index
+ */
+static ResultIteratorBase findResult(const QMap<int, ResultItem> &store, int index)
+{
+ if (store.isEmpty())
+ return ResultIteratorBase(store.end());
+ QMap<int, ResultItem>::const_iterator it = store.lowerBound(index);
+
+ // lowerBound returns either an iterator to the result or an iterator
+ // to the nearest greater index. If the latter happens it might be
+ // that the result is stored in a vector at the previous index.
+ if (it == store.end()) {
+ --it;
+ if (it.value().isVector() == false) {
+ return ResultIteratorBase(store.end());
+ }
+ } else {
+ if (it.key() > index) {
+ if (it == store.begin())
+ return ResultIteratorBase(store.end());
+ --it;
+ }
+ }
+
+ const int vectorIndex = index - it.key();
+
+ if (vectorIndex >= it.value().count())
+ return ResultIteratorBase(store.end());
+ else if (it.value().isVector() == false && vectorIndex != 0)
+ return ResultIteratorBase(store.end());
+ return ResultIteratorBase(it, vectorIndex);
+}
+
+/*!
\class QtPrivate::ResultItem
\internal
*/
@@ -108,6 +108,11 @@ bool ResultIteratorBase::canIncrementVectorIndex() const
return (m_vectorIndex + 1 < mapIterator.value().m_count);
}
+bool ResultIteratorBase::isValid() const
+{
+ return mapIterator.value().isValid();
+}
+
ResultStoreBase::ResultStoreBase()
: insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { }
@@ -160,6 +165,15 @@ int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem)
return storeIndex;
}
+bool ResultStoreBase::containsValidResultItem(int index) const
+{
+ // index might refer to either visible or pending result
+ const bool inPending = m_filterMode && index != -1 && index > insertIndex;
+ const auto &store = inPending ? pendingResults : m_results;
+ auto it = findResult(store, index);
+ return it != ResultIteratorBase(store.end()) && it.isValid();
+}
+
void ResultStoreBase::syncPendingResults()
{
// check if we can insert any of the pending results:
@@ -185,6 +199,7 @@ int ResultStoreBase::addResult(int index, const void *result)
int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount)
{
if (m_filterMode == false || vectorSize == totalCount) {
+ Q_ASSERT(vectorSize != 0);
ResultItem resultItem(results, vectorSize);
return insertResultItem(index, resultItem);
} else {
@@ -214,33 +229,7 @@ bool ResultStoreBase::hasNextResult() const
ResultIteratorBase ResultStoreBase::resultAt(int index) const
{
- if (m_results.isEmpty())
- return ResultIteratorBase(m_results.end());
- QMap<int, ResultItem>::const_iterator it = m_results.lowerBound(index);
-
- // lowerBound returns either an iterator to the result or an iterator
- // to the nearest greater index. If the latter happens it might be
- // that the result is stored in a vector at the previous index.
- if (it == m_results.end()) {
- --it;
- if (it.value().isVector() == false) {
- return ResultIteratorBase(m_results.end());
- }
- } else {
- if (it.key() > index) {
- if (it == m_results.begin())
- return ResultIteratorBase(m_results.end());
- --it;
- }
- }
-
- const int vectorIndex = index - it.key();
-
- if (vectorIndex >= it.value().count())
- return ResultIteratorBase(m_results.end());
- else if (it.value().isVector() == false && vectorIndex != 0)
- return ResultIteratorBase(m_results.end());
- return ResultIteratorBase(it, vectorIndex);
+ return findResult(m_results, index);
}
bool ResultStoreBase::contains(int index) const
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index 523c745a8e..30ce1fe904 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -1,47 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTCORE_RESULTSTORE_H
#define QTCORE_RESULTSTORE_H
#include <QtCore/qmap.h>
-#include <QtCore/qdebug.h>
#include <utility>
@@ -53,7 +16,7 @@ QT_BEGIN_NAMESPACE
ResultStore stores indexed results. Results can be added and retrieved
either individually batched in a QList. Retriveing results and checking
which indexes are in the store can be done either by iterating or by random
- accees. In addition results kan be removed from the front of the store,
+ access. In addition results can be removed from the front of the store,
either individually or in batches.
*/
@@ -62,7 +25,7 @@ namespace QtPrivate {
class ResultItem
{
public:
- ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
+ ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // construct with vector of results
ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
ResultItem() : m_count(0), result(nullptr) { }
bool isValid() const { return result != nullptr; }
@@ -87,6 +50,8 @@ public:
bool operator!=(const ResultIteratorBase &other) const;
bool isVector() const;
bool canIncrementVectorIndex() const;
+ bool isValid() const;
+
protected:
QMap<int, ResultItem>::const_iterator mapIterator;
int m_vectorIndex;
@@ -106,7 +71,7 @@ public:
template <typename T>
T *pointer()
{
- const T *p = qAsConst(*this).pointer<T>();
+ const T *p = std::as_const(*this).pointer<T>();
return const_cast<T *>(p);
}
@@ -120,7 +85,7 @@ public:
}
};
-class Q_CORE_EXPORT ResultStoreBase
+class Q_CORE_EXPORT ResultStoreBase final
{
public:
ResultStoreBase();
@@ -134,11 +99,14 @@ public:
ResultIteratorBase resultAt(int index) const;
bool contains(int index) const;
int count() const;
+ // ### Qt 7: 'virtual' isn't required, can be removed, along with renaming
+ // the class to ResultStore and changing the members below to be private.
virtual ~ResultStoreBase();
protected:
int insertResultItem(int index, ResultItem &resultItem);
void insertResultItemIfValid(int index, ResultItem &resultItem);
+ bool containsValidResultItem(int index) const;
void syncPendingResults();
void syncResultCount();
int updateInsertIndex(int index, int _count);
@@ -151,10 +119,35 @@ protected:
QMap<int, ResultItem> pendingResults;
int filteredResults;
+ template <typename T>
+ static void clear(QMap<int, ResultItem> &store)
+ {
+ QMap<int, ResultItem>::const_iterator mapIterator = store.constBegin();
+ while (mapIterator != store.constEnd()) {
+ if (mapIterator.value().isVector())
+ delete reinterpret_cast<const QList<T> *>(mapIterator.value().result);
+ else
+ delete reinterpret_cast<const T *>(mapIterator.value().result);
+ ++mapIterator;
+ }
+ store.clear();
+ }
+
public:
+ template <typename T, typename...Args>
+ int emplaceResult(int index, Args&&...args)
+ {
+ if (containsValidResultItem(index)) // reject if already present
+ return -1;
+ return addResult(index, static_cast<void *>(new T(std::forward<Args>(args)...)));
+ }
+
template <typename T>
int addResult(int index, const T *result)
{
+ if (containsValidResultItem(index)) // reject if already present
+ return -1;
+
if (result == nullptr)
return addResult(index, static_cast<void *>(nullptr));
@@ -164,32 +157,53 @@ public:
template <typename T>
int moveResult(int index, T &&result)
{
- return addResult(index, static_cast<void *>(new T(std::move_if_noexcept(result))));
+ static_assert(!std::is_reference_v<T>, "trying to move from an lvalue!");
+
+ return emplaceResult<std::remove_cv_t<T>>(index, std::forward<T>(result));
}
template<typename T>
int addResults(int index, const QList<T> *results)
{
- return addResults(index, new QList<T>(*results), results->count(), results->count());
+ if (results->empty()) // reject if results are empty
+ return -1;
+
+ if (containsValidResultItem(index)) // reject if already present
+ return -1;
+
+ return addResults(index, new QList<T>(*results), results->size(), results->size());
}
template<typename T>
int addResults(int index, const QList<T> *results, int totalCount)
{
- if (m_filterMode == true && results->count() != totalCount && 0 == results->count())
+ // reject if results are empty, and nothing is filtered away
+ if ((m_filterMode == false || results->size() == totalCount) && results->empty())
+ return -1;
+
+ if (containsValidResultItem(index)) // reject if already present
+ return -1;
+
+ if (m_filterMode == true && results->size() != totalCount && 0 == results->size())
return addResults(index, nullptr, 0, totalCount);
- return addResults(index, new QList<T>(*results), results->count(), totalCount);
+ return addResults(index, new QList<T>(*results), results->size(), totalCount);
}
int addCanceledResult(int index)
{
+ if (containsValidResultItem(index)) // reject if already present
+ return -1;
+
return addResult(index, static_cast<void *>(nullptr));
}
template <typename T>
int addCanceledResults(int index, int _count)
{
+ if (containsValidResultItem(index)) // reject if already present
+ return -1;
+
QList<T> empty;
return addResults(index, &empty, _count);
}
@@ -197,16 +211,11 @@ public:
template <typename T>
void clear()
{
- QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
- while (mapIterator != m_results.constEnd()) {
- if (mapIterator.value().isVector())
- delete reinterpret_cast<const QList<T> *>(mapIterator.value().result);
- else
- delete reinterpret_cast<const T *>(mapIterator.value().result);
- ++mapIterator;
- }
+ ResultStoreBase::clear<T>(m_results);
resultCount = 0;
- m_results.clear();
+ insertIndex = 0;
+ ResultStoreBase::clear<T>(pendingResults);
+ filteredResults = 0;
}
};
diff --git a/src/corelib/thread/qrunnable.cpp b/src/corelib/thread/qrunnable.cpp
index 32f3cd657e..f9d69ed5cb 100644
--- a/src/corelib/thread/qrunnable.cpp
+++ b/src/corelib/thread/qrunnable.cpp
@@ -1,44 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qrunnable.h"
+#include <QtCore/qlogging.h>
+
QT_BEGIN_NAMESPACE
QRunnable::~QRunnable()
@@ -46,6 +12,27 @@ QRunnable::~QRunnable()
}
/*!
+ \internal
+ Prints a warning and returns nullptr.
+*/
+QRunnable *QRunnable::warnNullCallable()
+{
+ qWarning("Trying to create null QRunnable. This may stop working.");
+ return nullptr;
+}
+
+
+QRunnable::QGenericRunnable::~QGenericRunnable()
+{
+ runHelper->destroy();
+}
+
+void QRunnable::QGenericRunnable::run()
+{
+ runHelper->run();
+}
+
+/*!
\class QRunnable
\inmodule QtCore
\since 4.4
@@ -113,31 +100,20 @@ QRunnable::~QRunnable()
\sa autoDelete(), QThreadPool
*/
-class FunctionRunnable : public QRunnable
-{
- std::function<void()> m_functionToRun;
-public:
- FunctionRunnable(std::function<void()> functionToRun) : m_functionToRun(std::move(functionToRun))
- {
- }
- void run() override
- {
- m_functionToRun();
- }
-};
-
/*!
+ \fn template<typename Callable, QRunnable::if_callable<Callable>> QRunnable *QRunnable::create(Callable &&callableToRun);
\since 5.15
- Creates a QRunnable that calls \a functionToRun in run().
+ Creates a QRunnable that calls \a callableToRun in run().
Auto-deletion is enabled by default.
+ \note This function participates in overload resolution only if \c Callable
+ is a function or function object which can be called with zero arguments.
+
+ \note In Qt versions prior to 6.6, this method took copyable functions only.
+
\sa run(), autoDelete()
*/
-QRunnable *QRunnable::create(std::function<void()> functionToRun)
-{
- return new FunctionRunnable(std::move(functionToRun));
-}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qrunnable.h b/src/corelib/thread/qrunnable.h
index 9f8ab2a3d0..f0dd0a582e 100644
--- a/src/corelib/thread/qrunnable.h
+++ b/src/corelib/thread/qrunnable.h
@@ -1,69 +1,137 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRUNNABLE_H
#define QRUNNABLE_H
-#include <QtCore/qglobal.h>
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qfunctionaltools_impl.h>
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/qtcoreexports.h>
+
#include <functional>
+#include <type_traits>
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QRunnable
{
- int ref; // Qt6: Make this a bool, or make autoDelete() virtual.
+ bool m_autoDelete = true;
- friend class QThreadPool;
- friend class QThreadPoolPrivate;
- friend class QThreadPoolThread;
Q_DISABLE_COPY(QRunnable)
public:
virtual void run() = 0;
- QRunnable() : ref(0) { }
+ constexpr QRunnable() noexcept = default;
virtual ~QRunnable();
+#if QT_CORE_REMOVED_SINCE(6, 6)
static QRunnable *create(std::function<void()> functionToRun);
+#endif
+ template <typename Callable>
+ using if_callable = std::enable_if_t<std::is_invocable_r_v<void, Callable>, bool>;
+
+ template <typename Callable, if_callable<Callable> = true>
+ static QRunnable *create(Callable &&functionToRun);
+ static QRunnable *create(std::nullptr_t) = delete;
- bool autoDelete() const { return ref != -1; }
- void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }
+ bool autoDelete() const { return m_autoDelete; }
+ void setAutoDelete(bool autoDelete) { m_autoDelete = autoDelete; }
+
+private:
+ static Q_DECL_COLD_FUNCTION QRunnable *warnNullCallable();
+ class QGenericRunnable;
};
+class Q_CORE_EXPORT QRunnable::QGenericRunnable : public QRunnable
+{
+ // Type erasure, to only instantiate a non-virtual class per Callable:
+ class HelperBase
+ {
+ protected:
+ enum class Op {
+ Run,
+ Destroy,
+ };
+ using OpFn = void* (*)(Op, HelperBase *, void*);
+ OpFn fn;
+ protected:
+ constexpr explicit HelperBase(OpFn f) noexcept : fn(f) {}
+ ~HelperBase() = default;
+ public:
+ void run() { fn(Op::Run, this, nullptr); }
+ void destroy() { fn(Op::Destroy, this, nullptr); }
+ };
+
+ template <typename Callable>
+ class Helper : public HelperBase, private QtPrivate::CompactStorage<Callable>
+ {
+ using Storage = QtPrivate::CompactStorage<Callable>;
+ static void *impl(Op op, HelperBase *that, [[maybe_unused]] void *arg)
+ {
+ const auto _this = static_cast<Helper*>(that);
+ switch (op) {
+ case Op::Run: _this->object()(); break;
+ case Op::Destroy: delete _this; break;
+ }
+ return nullptr;
+ }
+ public:
+ template <typename UniCallable>
+ explicit Helper(UniCallable &&functionToRun) noexcept
+ : HelperBase(&impl),
+ Storage{std::forward<UniCallable>(functionToRun)}
+ {
+ }
+ };
+
+ HelperBase *runHelper;
+public:
+ template <typename Callable, if_callable<Callable> = true>
+ explicit QGenericRunnable(Callable &&c)
+ : runHelper(new Helper<std::decay_t<Callable>>(std::forward<Callable>(c)))
+ {
+ }
+ ~QGenericRunnable() override;
+
+ void run() override;
+};
+
+namespace QtPrivate {
+
+template <typename T>
+constexpr inline bool is_function_pointer_v = std::conjunction_v<
+ std::is_pointer<T>,
+ std::is_function<std::remove_pointer_t<T>>
+ >;
+template <typename T>
+constexpr inline bool is_std_function_v = false;
+template <typename T>
+constexpr inline bool is_std_function_v<std::function<T>> = true;
+
+} // namespace QtPrivate
+
+template <typename Callable, QRunnable::if_callable<Callable>>
+QRunnable *QRunnable::create(Callable &&functionToRun)
+{
+ using F = std::decay_t<Callable>;
+ constexpr bool is_std_function = QtPrivate::is_std_function_v<F>;
+ constexpr bool is_function_pointer = QtPrivate::is_function_pointer_v<F>;
+ if constexpr (is_std_function || is_function_pointer) {
+ bool is_null;
+ if constexpr (is_std_function) {
+ is_null = !functionToRun;
+ } else if constexpr (is_function_pointer) {
+ // shut up warnings about functions always having a non-null address:
+ const void *functionPtr = reinterpret_cast<void *>(functionToRun);
+ is_null = !functionPtr;
+ }
+ if (is_null)
+ return warnNullCallable();
+ }
+
+ return new QGenericRunnable(std::forward<Callable>(functionToRun));
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index d4fb756b94..72781942ac 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -1,49 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsemaphore.h"
-#include "qmutex.h"
#include "qfutex_p.h"
-#include "qwaitcondition.h"
#include "qdeadlinetimer.h"
#include "qdatetime.h"
+#include "qdebug.h"
+#include "qlocking_p.h"
+#include "qwaitcondition_p.h"
+
+#include <chrono>
QT_BEGIN_NAMESPACE
@@ -83,7 +50,7 @@ using namespace QtFutex;
A typical application of semaphores is for controlling access to
a circular buffer shared by a producer thread and a consumer
- thread. The \l{Semaphores Example} shows how
+ thread. The \l{Producer and Consumer using Semaphores} example shows how
to use QSemaphore to solve that problem.
A non-computing example of a semaphore would be dining at a
@@ -96,7 +63,8 @@ using namespace QtFutex;
seated (taking the available seats to 5, making the party of 10
people wait longer).
- \sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread, {Semaphores Example}
+ \sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread,
+ {Producer and Consumer using Semaphores}
*/
/*
@@ -127,13 +95,13 @@ using namespace QtFutex;
*/
#if defined(FUTEX_OP) && QT_POINTER_SIZE > 4
-static Q_CONSTEXPR bool futexHasWaiterCount = true;
+static constexpr bool futexHasWaiterCount = true;
#else
-static Q_CONSTEXPR bool futexHasWaiterCount = false;
+static constexpr bool futexHasWaiterCount = false;
#endif
-static const quintptr futexNeedsWakeAllBit =
- Q_UINT64_C(1) << (sizeof(quintptr) * CHAR_BIT - 1);
+static constexpr quintptr futexNeedsWakeAllBit = futexHasWaiterCount ?
+ (Q_UINT64_C(1) << (sizeof(quintptr) * CHAR_BIT - 1)) : 0x80000000U;
static int futexAvailCounter(quintptr v)
{
@@ -150,10 +118,11 @@ static int futexAvailCounter(quintptr v)
static bool futexNeedsWake(quintptr v)
{
- // If we're counting waiters, the number of waiters is stored in the low 31
- // bits of the high word (that is, bits 32-62). If we're not, then we use
- // bit 31 to indicate anyone is waiting. Either way, if any bit 31 or above
- // is set, there are waiters.
+ // If we're counting waiters, the number of waiters plus value is stored in the
+ // low 31 bits of the high word (that is, bits 32-62). If we're not, then we only
+ // use futexNeedsWakeAllBit to indicate anyone is waiting.
+ if constexpr (futexHasWaiterCount)
+ return unsigned(quint64(v) >> 32) > unsigned(v);
return v >> 31;
}
@@ -168,6 +137,7 @@ static QBasicAtomicInteger<quint32> *futexLow32(QBasicAtomicInteger<quintptr> *p
static QBasicAtomicInteger<quint32> *futexHigh32(QBasicAtomicInteger<quintptr> *ptr)
{
+ Q_ASSERT(futexHasWaiterCount);
auto result = reinterpret_cast<QBasicAtomicInteger<quint32> *>(ptr);
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && QT_POINTER_SIZE > 4
++result;
@@ -176,43 +146,28 @@ static QBasicAtomicInteger<quint32> *futexHigh32(QBasicAtomicInteger<quintptr> *
}
template <bool IsTimed> bool
-futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValue, quintptr nn, int timeout)
+futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValue, quintptr nn,
+ QDeadlineTimer timer)
{
- QDeadlineTimer timer(IsTimed ? QDeadlineTimer(timeout) : QDeadlineTimer());
- qint64 remainingTime = timeout * Q_INT64_C(1000) * 1000;
+ using namespace std::chrono;
int n = int(unsigned(nn));
// we're called after one testAndSet, so start by waiting first
- goto start_wait;
-
- forever {
- if (futexAvailCounter(curValue) >= n) {
- // try to acquire
- quintptr newValue = curValue - nn;
- if (u.testAndSetOrdered(curValue, newValue, curValue))
- return true; // succeeded!
- continue;
- }
-
- // not enough tokens available, put us to wait
- if (remainingTime == 0)
- return false;
-
+ for (;;) {
// indicate we're waiting
-start_wait:
auto ptr = futexLow32(&u);
if (n > 1 || !futexHasWaiterCount) {
u.fetchAndOrRelaxed(futexNeedsWakeAllBit);
curValue |= futexNeedsWakeAllBit;
- if (n > 1 && futexHasWaiterCount) {
+ if constexpr (futexHasWaiterCount) {
+ Q_ASSERT(n > 1);
ptr = futexHigh32(&u);
- //curValue >>= 32; // but this is UB in 32-bit, so roundabout:
curValue = quint64(curValue) >> 32;
}
}
- if (IsTimed && remainingTime > 0) {
- bool timedout = !futexWait(*ptr, curValue, remainingTime);
+ if (IsTimed) {
+ bool timedout = !futexWait(*ptr, curValue, timer);
if (timedout)
return false;
} else {
@@ -220,13 +175,27 @@ start_wait:
}
curValue = u.loadAcquire();
- if (IsTimed)
- remainingTime = timer.remainingTimeNSecs();
+
+ // try to acquire
+ while (futexAvailCounter(curValue) >= n) {
+ quintptr newValue = curValue - nn;
+ if (u.testAndSetOrdered(curValue, newValue, curValue))
+ return true; // succeeded!
+ }
+
+ // not enough tokens available, put us to wait
+ if (IsTimed && timer.hasExpired())
+ return false;
}
}
-template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintptr> &u, int n, int timeout)
+static constexpr QDeadlineTimer::ForeverConstant Expired =
+ QDeadlineTimer::ForeverConstant(1);
+
+template <typename T> bool
+futexSemaphoreTryAcquire(QBasicAtomicInteger<quintptr> &u, int n, T timeout)
{
+ constexpr bool IsTimed = std::is_same_v<QDeadlineTimer, T>;
// Try to acquire without waiting (we still loop because the testAndSet
// call can fail).
quintptr nn = unsigned(n);
@@ -240,19 +209,27 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
if (u.testAndSetOrdered(curValue, newValue, curValue))
return true; // succeeded!
}
- if (timeout == 0)
- return false;
+ if constexpr (IsTimed) {
+ if (timeout.hasExpired())
+ return false;
+ } else {
+ if (timeout == Expired)
+ return false;
+ }
// we need to wait
- quintptr oneWaiter = quintptr(Q_UINT64_C(1) << 32); // zero on 32-bit
- if (futexHasWaiterCount) {
- // increase the waiter count
- u.fetchAndAddRelaxed(oneWaiter);
-
+ constexpr quintptr oneWaiter = quintptr(Q_UINT64_C(1) << 32); // zero on 32-bit
+ if constexpr (futexHasWaiterCount) {
// We don't use the fetched value from above so futexWait() fails if
// it changed after the testAndSetOrdered above.
- if ((quint64(curValue) >> 32) == 0x7fffffff)
- return false; // overflow!
+ quint32 waiterCount = (quint64(curValue) >> 32) & 0x7fffffffU;
+ if (waiterCount == 0x7fffffffU) {
+ qCritical() << "Waiter count overflow in QSemaphore";
+ return false;
+ }
+
+ // increase the waiter count
+ u.fetchAndAddRelaxed(oneWaiter);
curValue += oneWaiter;
// Also adjust nn to subtract oneWaiter when we succeed in acquiring.
@@ -262,6 +239,8 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
if (futexSemaphoreTryAcquire_loop<IsTimed>(u, curValue, nn, timeout))
return true;
+ Q_ASSERT(IsTimed);
+
if (futexHasWaiterCount) {
// decrement the number of threads waiting
Q_ASSERT(futexHigh32(&u)->loadRelaxed() & 0x7fffffffU);
@@ -270,14 +249,31 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
return false;
}
-class QSemaphorePrivate {
-public:
- inline QSemaphorePrivate(int n) : avail(n) { }
+namespace QtSemaphorePrivate {
+using namespace QtPrivate;
+struct Layout1
+{
+ alignas(IdealMutexAlignment) std::mutex mutex;
+ qsizetype avail = 0;
+ alignas(IdealMutexAlignment) std::condition_variable cond;
+};
+
+struct Layout2
+{
+ alignas(IdealMutexAlignment) std::mutex mutex;
+ alignas(IdealMutexAlignment) std::condition_variable cond;
+ qsizetype avail = 0;
+};
- QMutex mutex;
- QWaitCondition cond;
+// Choose Layout1 if it is smaller than Layout2. That happens for platforms
+// where sizeof(mutex) is 64.
+using Members = std::conditional_t<sizeof(Layout1) <= sizeof(Layout2), Layout1, Layout2>;
+} // namespace QtSemaphorePrivate
- int avail;
+class QSemaphorePrivate : public QtSemaphorePrivate::Members
+{
+public:
+ explicit QSemaphorePrivate(qsizetype n) { avail = n; }
};
/*!
@@ -320,16 +316,22 @@ QSemaphore::~QSemaphore()
*/
void QSemaphore::acquire(int n)
{
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
+# warning "Move the Q_ASSERT to inline code, make QSemaphore have wide contract, " \
+ "and mark noexcept where futexes are in use."
+#else
Q_ASSERT_X(n >= 0, "QSemaphore::acquire", "parameter 'n' must be non-negative");
+#endif
if (futexAvailable()) {
- futexSemaphoreTryAcquire<false>(u, n, -1);
+ futexSemaphoreTryAcquire(u, n, QDeadlineTimer::Forever);
return;
}
- QMutexLocker locker(&d->mutex);
- while (n > d->avail)
- d->cond.wait(locker.mutex());
+ const auto sufficientResourcesAvailable = [this, n] { return d->avail >= n; };
+
+ auto locker = qt_unique_lock(d->mutex);
+ d->cond.wait(locker, sufficientResourcesAvailable);
d->avail -= n;
}
@@ -354,66 +356,56 @@ void QSemaphore::release(int n)
quintptr nn = unsigned(n);
if (futexHasWaiterCount)
nn |= quint64(nn) << 32; // token count replicated in high word
- quintptr prevValue = u.fetchAndAddRelease(nn);
+ quintptr prevValue = u.loadRelaxed();
+ quintptr newValue;
+ do { // loop just to ensure the operations are done atomically
+ newValue = prevValue + nn;
+ newValue &= (futexNeedsWakeAllBit - 1);
+ } while (!u.testAndSetRelease(prevValue, newValue, prevValue));
if (futexNeedsWake(prevValue)) {
#ifdef FUTEX_OP
- if (!futexHasWaiterCount) {
- /*
- On 32-bit systems, all waiters are waiting on the same address,
- so we'll wake them all and ask the kernel to clear the high bit.
-
- atomic {
- int oldval = u;
- u = oldval & ~(1 << 31);
- futexWake(u, INT_MAX);
- if (oldval == 0) // impossible condition
- futexWake(u, INT_MAX);
- }
- */
- quint32 op = FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT;
- quint32 oparg = 31;
- quint32 cmp = FUTEX_OP_CMP_EQ;
- quint32 cmparg = 0;
- futexWakeOp(u, INT_MAX, INT_MAX, u, FUTEX_OP(op, oparg, cmp, cmparg));
- } else {
+ if (futexHasWaiterCount) {
/*
On 64-bit systems, the single-token waiters wait on the low half
and the multi-token waiters wait on the upper half. So we ask
the kernel to wake up n single-token waiters and all multi-token
- waiters (if any), then clear the multi-token wait bit.
+ waiters (if any), and clear the multi-token wait bit.
atomic {
int oldval = *upper;
- *upper = oldval & ~(1 << 31);
+ *upper = oldval | 0;
futexWake(lower, n);
- if (oldval < 0) // sign bit set
+ if (oldval != 0) // always true
futexWake(upper, INT_MAX);
}
*/
- quint32 op = FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT;
- quint32 oparg = 31;
- quint32 cmp = FUTEX_OP_CMP_LT;
+ quint32 op = FUTEX_OP_OR;
+ quint32 oparg = 0;
+ quint32 cmp = FUTEX_OP_CMP_NE;
quint32 cmparg = 0;
futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg));
+ return;
}
-#else
- // Unset the bit and wake everyone. There are two possibibilies
+#endif
+ // Unset the bit and wake everyone. There are two possibilities
// under which a thread can set the bit between the AND and the
// futexWake:
// 1) it did see the new counter value, but it wasn't enough for
// its acquisition anyway, so it has to wait;
// 2) it did not see the new counter value, in which case its
// futexWait will fail.
- u.fetchAndAndRelease(futexNeedsWakeAllBit - 1);
- futexWakeAll(u);
-#endif
+ futexWakeAll(*futexLow32(&u));
+ if (futexHasWaiterCount)
+ futexWakeAll(*futexHigh32(&u));
}
return;
}
- QMutexLocker locker(&d->mutex);
+ // Keep mutex locked until after notify_all() lest another thread acquire()s
+ // the semaphore once d->avail == 0 and then destroys it, leaving `d` dangling.
+ const auto locker = qt_scoped_lock(d->mutex);
d->avail += n;
- d->cond.wakeAll();
+ d->cond.notify_all();
}
/*!
@@ -427,7 +419,7 @@ int QSemaphore::available() const
if (futexAvailable())
return futexAvailCounter(u.loadRelaxed());
- QMutexLocker locker(&d->mutex);
+ const auto locker = qt_scoped_lock(d->mutex);
return d->avail;
}
@@ -447,9 +439,9 @@ bool QSemaphore::tryAcquire(int n)
Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
if (futexAvailable())
- return futexSemaphoreTryAcquire<false>(u, n, 0);
+ return futexSemaphoreTryAcquire(u, n, Expired);
- QMutexLocker locker(&d->mutex);
+ const auto locker = qt_scoped_lock(d->mutex);
if (n > d->avail)
return false;
d->avail -= n;
@@ -457,6 +449,8 @@ bool QSemaphore::tryAcquire(int n)
}
/*!
+ \fn QSemaphore::tryAcquire(int n, int timeout)
+
Tries to acquire \c n resources guarded by the semaphore and
returns \c true on success. If available() < \a n, this call will
wait for at most \a timeout milliseconds for resources to become
@@ -472,30 +466,89 @@ bool QSemaphore::tryAcquire(int n)
\sa acquire()
*/
-bool QSemaphore::tryAcquire(int n, int timeout)
+
+/*!
+ \since 6.6
+
+ Tries to acquire \c n resources guarded by the semaphore and returns \c
+ true on success. If available() < \a n, this call will wait until \a timer
+ expires for resources to become available.
+
+ Example:
+
+ \snippet code/src_corelib_thread_qsemaphore.cpp tryAcquire-QDeadlineTimer
+
+ \sa acquire()
+*/
+bool QSemaphore::tryAcquire(int n, QDeadlineTimer timer)
{
- Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
+ if (timer.isForever()) {
+ acquire(n);
+ return true;
+ }
+
+ if (timer.hasExpired())
+ return tryAcquire(n);
- // We're documented to accept any negative value as "forever"
- // but QDeadlineTimer only accepts -1.
- timeout = qMax(timeout, -1);
+ Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
if (futexAvailable())
- return futexSemaphoreTryAcquire<true>(u, n, timeout);
+ return futexSemaphoreTryAcquire(u, n, timer);
- QDeadlineTimer timer(timeout);
- QMutexLocker locker(&d->mutex);
- while (n > d->avail && !timer.hasExpired()) {
- if (!d->cond.wait(locker.mutex(), timer))
- return false;
- }
- if (n > d->avail)
+ using namespace std::chrono;
+ const auto sufficientResourcesAvailable = [this, n] { return d->avail >= n; };
+
+ auto locker = qt_unique_lock(d->mutex);
+ if (!d->cond.wait_until(locker, timer.deadline<steady_clock>(), sufficientResourcesAvailable))
return false;
d->avail -= n;
return true;
+}
+/*!
+ \fn template <typename Rep, typename Period> QSemaphore::tryAcquire(int n, std::chrono::duration<Rep, Period> timeout)
+ \overload
+ \since 6.3
+*/
-}
+/*!
+ \fn bool QSemaphore::try_acquire()
+ \since 6.3
+
+ This function is provided for \c{std::counting_semaphore} compatibility.
+
+ It is equivalent to calling \c{tryAcquire(1)}, where the function returns
+ \c true on acquiring the resource successfully.
+
+ \sa tryAcquire(), try_acquire_for(), try_acquire_until()
+*/
+
+/*!
+ \fn template <typename Rep, typename Period> bool QSemaphore::try_acquire_for(const std::chrono::duration<Rep, Period> &timeout)
+ \since 6.3
+
+ This function is provided for \c{std::counting_semaphore} compatibility.
+
+ It is equivalent to calling \c{tryAcquire(1, timeout)}, where the call
+ times out on the given \a timeout value. The function returns \c true
+ on acquiring the resource successfully.
+
+ \sa tryAcquire(), try_acquire(), try_acquire_until()
+*/
+
+/*!
+ \fn template <typename Clock, typename Duration> bool QSemaphore::try_acquire_until(const std::chrono::time_point<Clock, Duration> &tp)
+ \since 6.3
+
+ This function is provided for \c{std::counting_semaphore} compatibility.
+
+ It is equivalent to calling \c{tryAcquire(1, tp - Clock::now())},
+ which means that the \a tp (time point) is recorded, ignoring the
+ adjustments to \c{Clock} while waiting. The function returns \c true
+ on acquiring the resource successfully.
+
+ \sa tryAcquire(), try_acquire(), try_acquire_for()
+*/
/*!
\class QSemaphoreReleaser
@@ -594,7 +647,7 @@ bool QSemaphore::tryAcquire(int n, int timeout)
/*!
\fn QSemaphoreReleaser::swap(QSemaphoreReleaser &other)
- Exchanges the responsibilites of \c{*this} and \a other.
+ Exchanges the responsibilities of \c{*this} and \a other.
Unlike move assignment, neither of the two objects ever releases its
semaphore, if any, as a consequence of swapping.
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index b3b9b52052..dda722a582 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -1,53 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSEMAPHORE_H
#define QSEMAPHORE_H
#include <QtCore/qglobal.h>
+#include <QtCore/qdeadlinetimer.h>
+
+#include <chrono>
QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
class QSemaphorePrivate;
-
class Q_CORE_EXPORT QSemaphore
{
public:
@@ -56,33 +22,62 @@ public:
void acquire(int n = 1);
bool tryAcquire(int n = 1);
+ QT_CORE_INLINE_SINCE(6, 6)
bool tryAcquire(int n, int timeout);
+ bool tryAcquire(int n, QDeadlineTimer timeout);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ template <typename Rep, typename Period>
+ bool tryAcquire(int n, std::chrono::duration<Rep, Period> timeout)
+ { return tryAcquire(n, QDeadlineTimer(timeout)); }
+#endif
void release(int n = 1);
int available() const;
+ // std::counting_semaphore compatibility:
+ bool try_acquire() noexcept { return tryAcquire(); }
+ template <typename Rep, typename Period>
+ bool try_acquire_for(const std::chrono::duration<Rep, Period> &timeout)
+ { return tryAcquire(1, timeout); }
+ template <typename Clock, typename Duration>
+ bool try_acquire_until(const std::chrono::time_point<Clock, Duration> &tp)
+ {
+ return try_acquire_for(tp - Clock::now());
+ }
private:
Q_DISABLE_COPY(QSemaphore)
union {
QSemaphorePrivate *d;
- QBasicAtomicInteger<quintptr> u; // ### Qt6: make 64-bit
+ QBasicAtomicInteger<quintptr> u;
+ QBasicAtomicInteger<quint32> u32[2];
+ QBasicAtomicInteger<quint64> u64;
};
};
+#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
+bool QSemaphore::tryAcquire(int n, int timeout)
+{
+ return tryAcquire(n, QDeadlineTimer(timeout));
+}
+#endif
+
class QSemaphoreReleaser
{
public:
+ Q_NODISCARD_CTOR
QSemaphoreReleaser() = default;
+ Q_NODISCARD_CTOR
explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) noexcept
: m_sem(&sem), m_n(n) {}
+ Q_NODISCARD_CTOR
explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept
: m_sem(sem), m_n(n) {}
+ Q_NODISCARD_CTOR
QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept
: m_sem(other.cancel()), m_n(other.m_n) {}
- QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) noexcept
- { QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSemaphoreReleaser)
~QSemaphoreReleaser()
{
@@ -92,8 +87,8 @@ public:
void swap(QSemaphoreReleaser &other) noexcept
{
- qSwap(m_sem, other.m_sem);
- qSwap(m_n, other.m_n);
+ qt_ptr_swap(m_sem, other.m_sem);
+ std::swap(m_n, other.m_n);
}
QSemaphore *semaphore() const noexcept
@@ -101,7 +96,7 @@ public:
QSemaphore *cancel() noexcept
{
- return qExchange(m_sem, nullptr);
+ return std::exchange(m_sem, nullptr);
}
private:
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 6e31ca4fbb..ea76a2ccad 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qthread.h"
#include "qthreadstorage.h"
#include "qmutex.h"
#include "qreadwritelock.h"
#include "qabstracteventdispatcher.h"
+#include "qbindingstorage.h"
#include <qeventloop.h>
@@ -54,6 +19,29 @@
QT_BEGIN_NAMESPACE
/*
+ QPostEventList
+*/
+
+void QPostEventList::addEvent(const QPostEvent &ev)
+{
+ int priority = ev.priority;
+ if (isEmpty() ||
+ constLast().priority >= priority ||
+ insertionOffset >= size()) {
+ // optimization: we can simply append if the last event in
+ // the queue has higher or equal priority
+ append(ev);
+ } else {
+ // insert event in descending priority order, using upper
+ // bound for a given priority (to ensure proper ordering
+ // of events with the same priority)
+ QPostEventList::iterator at = std::upper_bound(begin() + insertionOffset, end(), ev);
+ insert(at, ev);
+ }
+}
+
+
+/*
QThreadData
*/
@@ -77,9 +65,10 @@ QThreadData::~QThreadData()
// crashing during QCoreApplicationData's global static cleanup we need to
// safeguard the main thread here.. This fix is a bit crude, but it solves
// the problem...
- if (this->thread.loadAcquire() == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
- QCoreApplicationPrivate::theMainThread.storeRelease(nullptr);
- QThreadData::clearCurrentThreadData();
+ if (threadId.loadAcquire() == QCoreApplicationPrivate::theMainThreadId.loadAcquire()) {
+ QCoreApplicationPrivate::theMainThread.storeRelease(nullptr);
+ QCoreApplicationPrivate::theMainThreadId.storeRelaxed(nullptr);
+ QThreadData::clearCurrentThreadData();
}
// ~QThread() sets thread to nullptr, so if it isn't null here, it's
@@ -97,7 +86,7 @@ QThreadData::~QThreadData()
const QPostEvent &pe = postEventList.at(i);
if (pe.event) {
--pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
+ pe.event->m_posted = false;
delete pe.event;
}
}
@@ -125,7 +114,6 @@ QAbstractEventDispatcher *QThreadData::createEventDispatcher()
{
QAbstractEventDispatcher *ed = QThreadPrivate::createEventDispatcher(this);
eventDispatcher.storeRelease(ed);
- ed->startingUp();
return ed;
}
@@ -142,8 +130,9 @@ QAdoptedThread::QAdoptedThread(QThreadData *data)
d_func()->running = true;
d_func()->finished = false;
init();
+ d_func()->m_statusOrPendingObjects.setStatusAndClearList(
+ QtPrivate::getBindingStatus({}));
#endif
-
// fprintf(stderr, "new QAdoptedThread = %p\n", this);
}
@@ -158,7 +147,24 @@ void QAdoptedThread::run()
// this function should never be called
qFatal("QAdoptedThread::run(): Internal error, this implementation should never be called.");
}
+#endif
+
+QScopedScopeLevelCounter::QScopedScopeLevelCounter(QThreadData *threadData)
+ : threadData(threadData)
+{
+ ++threadData->scopeLevel;
+ qCDebug(lcDeleteLater) << "Increased" << threadData->thread
+ << "scope level to" << threadData->scopeLevel;
+}
+
+QScopedScopeLevelCounter::~QScopedScopeLevelCounter()
+{
+ --threadData->scopeLevel;
+ qCDebug(lcDeleteLater) << "Decreased" << threadData->thread
+ << "scope level to" << threadData->scopeLevel;
+}
+#if QT_CONFIG(thread)
/*
QThreadPrivate
*/
@@ -176,7 +182,7 @@ QThreadPrivate::QThreadPrivate(QThreadData *d)
#ifdef Q_OS_INTEGRITY
stackSize = 128 * 1024;
#elif defined(Q_OS_RTEMS)
- static bool envStackSizeOk = false;
+ Q_CONSTINIT static bool envStackSizeOk = false;
static const int envStackSize = qEnvironmentVariableIntValue("QT_DEFAULT_THREAD_STACK_SIZE", &envStackSizeOk);
if (envStackSizeOk)
stackSize = envStackSize;
@@ -196,6 +202,10 @@ QThreadPrivate::QThreadPrivate(QThreadData *d)
QThreadPrivate::~QThreadPrivate()
{
+ // access to m_statusOrPendingObjects cannot race with anything
+ // unless there is already a potential use-after-free bug, as the
+ // thread is in the process of being destroyed
+ delete m_statusOrPendingObjects.list();
data->deref();
}
@@ -248,11 +258,13 @@ QThreadPrivate::~QThreadPrivate()
different threads. Check that it is safe to do so.
\note Care must be taken when interacting with objects across different
- threads. See \l{Synchronizing Threads} for details.
+ threads. As a general rule, functions can only be called from the thread
+ that created the QThread object itself (e.g. setPriority()), unless the
+ documentation says otherwise. See \l{Synchronizing Threads} for details.
\section1 Managing Threads
- QThread will notifiy you via a signal when the thread is
+ QThread will notify you via a signal when the thread is
started() and finished(), or you can use isFinished() and
isRunning() to query the state of the thread.
@@ -262,22 +274,21 @@ QThreadPrivate::~QThreadPrivate()
documentation for terminate() and setTerminationEnabled() for
detailed information.
- From Qt 4.8 onwards, it is possible to deallocate objects that
- live in a thread that has just ended, by connecting the
- finished() signal to QObject::deleteLater().
+ You often want to deallocate objects that live in a thread when
+ a thread ends. To do this, connect the finished() signal to
+ QObject::deleteLater().
Use wait() to block the calling thread, until the other thread
has finished execution (or until a specified time has passed).
QThread also provides static, platform independent sleep
functions: sleep(), msleep(), and usleep() allow full second,
- millisecond, and microsecond resolution respectively. These
- functions were made public in Qt 5.0.
+ millisecond, and microsecond resolution respectively.
\note wait() and the sleep() functions should be unnecessary in
general, since Qt is an event-driven framework. Instead of
wait(), consider listening for the finished() signal. Instead of
- the sleep() functions, consider using QTimer.
+ the sleep() functions, consider using QChronoTimer.
The static functions currentThreadId() and currentThread() return
identifiers for the currently executing thread. The former
@@ -290,11 +301,12 @@ QThreadPrivate::~QThreadPrivate()
If you don't call \l{QObject::setObjectName()}{setObjectName()},
the name given to your thread will be the class name of the runtime
type of your thread object (for example, \c "RenderThread" in the case of the
- \l{Mandelbrot Example}, as that is the name of the QThread subclass).
+ \l{Mandelbrot} example, as that is the name of the QThread subclass).
Note that this is currently not available with release builds on Windows.
\sa {Thread Support in Qt}, QThreadStorage, {Synchronizing Threads},
- {Mandelbrot Example}, {Semaphores Example}, {Wait Conditions Example}
+ Mandelbrot, {Producer and Consumer using Semaphores},
+ {Producer and Consumer using Wait Conditions}
*/
/*!
@@ -313,9 +325,20 @@ QThreadPrivate::~QThreadPrivate()
/*!
\fn int QThread::idealThreadCount()
- Returns the ideal number of threads that can be run on the system. This is done querying
- the number of processor cores, both real and logical, in the system. This function returns 1
- if the number of processor cores could not be detected.
+ Returns the ideal number of threads that this process can run in parallel.
+ This is done by querying the number of logical processors available to this
+ process (if supported by this OS) or the total number of logical processors
+ in the system. This function returns 1 if neither value could be
+ determined.
+
+ \note On operating systems that support setting a thread's affinity to a
+ subset of all logical processors, the value returned by this function may
+ change between threads and over time.
+
+ \note On operating systems that support CPU hotplugging and hot-unplugging,
+ the value returned by this function may also change over time (and note
+ that CPUs can be turned on and off by software, without a physical,
+ hardware change).
*/
/*!
@@ -404,6 +427,23 @@ QThread *QThread::currentThread()
}
/*!
+ \since 6.8
+
+ Returns whether the currently executing thread is the main thread.
+
+ The main thread is the thread in which QCoreApplication was created.
+ This is usually the thread that called the \c{main()} function, but not necessarily so.
+ It is the thread that is processing the GUI events and in which graphical objects
+ (QWindow, QWidget) can be created.
+
+ \sa currentThread(), QCoreApplication::instance()
+*/
+bool QThread::isMainThread()
+{
+ return currentThreadId() == QCoreApplicationPrivate::theMainThreadId.loadRelaxed();
+}
+
+/*!
Constructs a new QThread to manage a new thread. The \a parent
takes ownership of the QThread. The thread does not begin
executing until start() is called.
@@ -437,6 +477,15 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent)
isFinished() returns \c false) will result in a program
crash. Wait for the finished() signal before deleting the
QThread.
+
+ Since Qt 6.3, it is allowed to delete a QThread instance created by
+ a call to QThread::create() even if the corresponding thread is
+ still running. In such a case, Qt will post an interruption request
+ to that thread (via requestInterruption()); will ask the thread's
+ event loop (if any) to quit (via quit()); and will block until the
+ thread has finished.
+
+ \sa create(), isInterruptionRequested(), exec(), quit()
*/
QThread::~QThread()
{
@@ -456,6 +505,7 @@ QThread::~QThread()
}
/*!
+ \threadsafe
Returns \c true if the thread is finished; otherwise returns \c false.
\sa isRunning()
@@ -468,6 +518,7 @@ bool QThread::isFinished() const
}
/*!
+ \threadsafe
Returns \c true if the thread is running; otherwise returns \c false.
\sa isFinished()
@@ -480,10 +531,18 @@ bool QThread::isRunning() const
}
/*!
- Sets the maximum stack size for the thread to \a stackSize. If \a
- stackSize is greater than zero, the maximum stack size is set to
- \a stackSize bytes, otherwise the maximum stack size is
- automatically determined by the operating system.
+ Sets the stack size for the thread to \a stackSize. If \a stackSize is
+ zero, the operating system or runtime will choose a default value.
+ Otherwise, the thread's stack size will be the value provided (which may be
+ rounded up or down).
+
+ On most operating systems, the amount of memory allocated to serve the
+ stack will initially be smaller than \a stackSize and will grow as the
+ thread uses the stack. This parameter sets the maximum size it will be
+ allowed to grow to (that is, it sets the size of the virtual memory space
+ the stack is allowed to occupy).
+
+ This function can only be called before the thread is started.
\warning Most operating systems place minimum and maximum limits
on thread stack sizes. The thread will fail to start if the stack
@@ -514,6 +573,24 @@ uint QThread::stackSize() const
}
/*!
+ \internal
+ Transitions BindingStatusOrList to the binding status state. If we had a list of
+ pending objects, all objects get their reinitBindingStorageAfterThreadMove method
+ called, and afterwards, the list gets discarded.
+ */
+void QtPrivate::BindingStatusOrList::setStatusAndClearList(QBindingStatus *status) noexcept
+{
+
+ if (auto pendingObjects = list()) {
+ for (auto obj: *pendingObjects)
+ QObjectPrivate::get(obj)->reinitBindingStorageAfterThreadMove();
+ delete pendingObjects;
+ }
+ // synchronizes-with the load-acquire in bindingStatus():
+ data.store(encodeBindingStatus(status), std::memory_order_release);
+}
+
+/*!
Enters the event loop and waits until exit() is called, returning the value
that was passed to exit(). The value returned is 0 if exit() is called via
quit().
@@ -521,12 +598,18 @@ uint QThread::stackSize() const
This function is meant to be called from within run(). It is necessary to
call this function to start event handling.
+ \note This can only be called within the thread itself, i.e. when
+ it is the current thread.
+
\sa quit(), exit()
*/
int QThread::exec()
{
Q_D(QThread);
+ const auto status = QtPrivate::getBindingStatus(QtPrivate::QBindingStatusAccessToken{});
+
QMutexLocker locker(&d->mutex);
+ d->m_statusOrPendingObjects.setStatusAndClearList(status);
d->data->quitNow = false;
if (d->exited) {
d->exited = false;
@@ -543,7 +626,60 @@ int QThread::exec()
return returnCode;
}
+
+/*!
+ \internal
+ If BindingStatusOrList is already in the binding status state, this will
+ return that BindingStatus pointer.
+ Otherwise, \a object is added to the list, and we return nullptr.
+ The list is allocated if it does not already exist.
+ */
+QBindingStatus *QtPrivate::BindingStatusOrList::addObjectUnlessAlreadyStatus(QObject *object)
+{
+ if (auto status = bindingStatus())
+ return status;
+ List *objectList = list();
+ if (!objectList) {
+ objectList = new List();
+ objectList->reserve(8);
+ data.store(encodeList(objectList), std::memory_order_relaxed);
+ }
+ objectList->push_back(object);
+ return nullptr;
+}
+
/*!
+ \internal
+ If BindingStatusOrList is a list, remove \a object from it
+ */
+void QtPrivate::BindingStatusOrList::removeObject(QObject *object)
+{
+ List *objectList = list();
+ if (!objectList)
+ return;
+ auto it = std::remove(objectList->begin(), objectList->end(), object);
+ objectList->erase(it, objectList->end());
+}
+
+QBindingStatus *QThreadPrivate::addObjectWithPendingBindingStatusChange(QObject *obj)
+{
+ if (auto status = m_statusOrPendingObjects.bindingStatus())
+ return status;
+ QMutexLocker lock(&mutex);
+ return m_statusOrPendingObjects.addObjectUnlessAlreadyStatus(obj);
+}
+
+void QThreadPrivate::removeObjectWithPendingBindingStatusChange(QObject *obj)
+{
+ if (m_statusOrPendingObjects.bindingStatus())
+ return;
+ QMutexLocker lock(&mutex);
+ m_statusOrPendingObjects.removeObject(obj);
+}
+
+
+/*!
+ \threadsafe
Tells the thread's event loop to exit with a return code.
After calling this function, the thread leaves the event loop and
@@ -578,6 +714,7 @@ void QThread::exit(int returnCode)
}
/*!
+ \threadsafe
Tells the thread's event loop to exit with return code 0 (success).
Equivalent to calling QThread::exit(0).
@@ -657,16 +794,28 @@ QThread::Priority QThread::priority() const
}
/*!
- \fn void QThread::sleep(unsigned long secs)
+ \fn void QThread::sleep(std::chrono::nanoseconds nsecs)
+ \since 6.6
- Forces the current thread to sleep for \a secs seconds.
+ Forces the current thread to sleep for \a nsecs.
Avoid using this function if you need to wait for a given condition to
change. Instead, connect a slot to the signal that indicates the change or
use an event handler (see \l QObject::event()).
\note This function does not guarantee accuracy. The application may sleep
- longer than \a secs under heavy load conditions.
+ longer than \a nsecs under heavy load conditions.
+*/
+
+/*!
+ \fn void QThread::sleep(unsigned long secs)
+
+ Forces the current thread to sleep for \a secs seconds.
+
+ This is an overloaded function, equivalent to calling:
+ \code
+ QThread::sleep(std::chrono::seconds{secs});
+ \endcode
\sa msleep(), usleep()
*/
@@ -674,11 +823,10 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::msleep(unsigned long msecs)
- Forces the current thread to sleep for \a msecs milliseconds.
-
- Avoid using this function if you need to wait for a given condition to
- change. Instead, connect a slot to the signal that indicates the change or
- use an event handler (see \l QObject::event()).
+ This is an overloaded function, equivalent to calling:
+ \code
+ QThread::sleep(std::chrono::milliseconds{msecs});
+ \endcode
\note This function does not guarantee accuracy. The application may sleep
longer than \a msecs under heavy load conditions. Some OSes might round \a
@@ -690,11 +838,10 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::usleep(unsigned long usecs)
- Forces the current thread to sleep for \a usecs microseconds.
-
- Avoid using this function if you need to wait for a given condition to
- change. Instead, connect a slot to the signal that indicates the change or
- use an event handler (see \l QObject::event()).
+ This is an overloaded function, equivalent to calling:
+ \code
+ QThread::sleep(std::chrono::microseconds{secs});
+ \endcode
\note This function does not guarantee accuracy. The application may sleep
longer than \a usecs under heavy load conditions. Some OSes might round \a
@@ -706,6 +853,7 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::terminate()
+ \threadsafe
Terminates the execution of the thread. The thread may or may not
be terminated immediately, depending on the operating system's
@@ -791,6 +939,36 @@ int QThread::loopLevel() const
return d->data->eventLoops.size();
}
+/*!
+ \internal
+ Returns the thread handle of this thread.
+ It can be compared with the return value of currentThreadId().
+
+ This is used to implement isCurrentThread, and might be useful
+ for debugging (e.g. by comparing the value in gdb with info threads).
+
+ \note Thread handles of destroyed threads might be reused by the
+ operating system. Storing the return value of this function can
+ therefore give surprising results if it outlives the QThread object
+ (threads claimed to be the same even if they aren't).
+*/
+Qt::HANDLE QThreadPrivate::threadId() const
+{
+ return data->threadId.loadRelaxed();
+}
+
+/*!
+ \since 6.8
+ Returns true if this thread is QThread::currentThread.
+
+ \sa currentThreadId()
+*/
+bool QThread::isCurrentThread() const
+{
+ Q_D(const QThread);
+ return QThread::currentThreadId() == d->threadId();
+}
+
#else // QT_CONFIG(thread)
QThread::QThread(QObject *parent)
@@ -848,7 +1026,7 @@ bool QThread::wait(QDeadlineTimer deadline)
return false;
}
-bool QThread::event(QEvent* event)
+bool QThread::event(QEvent *event)
{
return QObject::event(event);
}
@@ -863,6 +1041,11 @@ QThread *QThread::currentThread()
return QThreadData::current()->thread.loadAcquire();
}
+bool QThread::isCurrentThread() const
+{
+ return true;
+}
+
int QThread::idealThreadCount() noexcept
{
return 1;
@@ -884,8 +1067,22 @@ bool QThread::isRunning() const
return d->running;
}
+void QThread::requestInterruption()
+{
+
+}
+
+bool QThread::isInterruptionRequested() const
+{
+ return false;
+}
+
+void QThread::setTerminationEnabled(bool)
+{
+}
+
// No threads: so we can just use static variables
-static QThreadData *data = 0;
+Q_CONSTINIT static QThreadData *data = nullptr;
QThreadData *QThreadData::current(bool createIfNecessary)
{
@@ -895,8 +1092,10 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->threadId.storeRelaxed(Qt::HANDLE(data->thread.loadAcquire()));
data->deref();
data->isAdopted = true;
- if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
+ if (!QCoreApplicationPrivate::theMainThreadId.loadAcquire()) {
QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
+ QCoreApplicationPrivate::theMainThreadId.storeRelaxed(data->threadId.loadRelaxed());
+ }
}
return data;
}
@@ -957,8 +1156,11 @@ QAbstractEventDispatcher *QThread::eventDispatcher() const
Sets the event dispatcher for the thread to \a eventDispatcher. This is
only possible as long as there is no event dispatcher installed for the
- thread yet. That is, before the thread has been started with start() or, in
- case of the main thread, before QCoreApplication has been instantiated.
+ thread yet.
+
+ An event dispatcher is automatically created for the main thread when \l
+ QCoreApplication is instantiated and on start() for auxiliary threads.
+
This method takes ownership of the object.
*/
void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
@@ -977,14 +1179,11 @@ void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
/*!
\fn bool QThread::wait(unsigned long time)
+
\overload
+ \a time is the time to wait in milliseconds.
+ If \a time is ULONG_MAX, then the wait will never timeout.
*/
-bool QThread::wait(unsigned long time)
-{
- if (time == std::numeric_limits<unsigned long>::max())
- return wait(QDeadlineTimer(QDeadlineTimer::Forever));
- return wait(QDeadlineTimer(time));
-}
#if QT_CONFIG(thread)
@@ -1003,6 +1202,7 @@ bool QThread::event(QEvent *event)
/*!
\since 5.2
+ \threadsafe
Request the interruption of the thread.
That request is advisory and it is up to code running on the thread to decide
@@ -1015,13 +1215,11 @@ bool QThread::event(QEvent *event)
void QThread::requestInterruption()
{
- if (this == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
+ Q_D(QThread);
+ if (d->threadId() == QCoreApplicationPrivate::theMainThreadId.loadAcquire()) {
qWarning("QThread::requestInterruption has no effect on the main thread");
return;
}
- Q_D(QThread);
- // ### Qt 6: use std::atomic_flag, and document that
- // requestInterruption/isInterruptionRequested do not synchronize with each other
QMutexLocker locker(&d->mutex);
if (!d->running || d->finished || d->isInFinish)
return;
@@ -1049,6 +1247,9 @@ void QThread::requestInterruption()
}
\endcode
+ \note This can only be called within the thread itself, i.e. when
+ it is the current thread.
+
\sa currentThread() requestInterruption()
*/
bool QThread::isInterruptionRequested() const
@@ -1078,36 +1279,12 @@ bool QThread::isInterruptionRequested() const
\note the caller acquires ownership of the returned QThread instance.
- \note this function is only available when using C++17.
-
\warning do not call start() on the returned QThread instance more than once;
doing so will result in undefined behavior.
\sa start()
*/
-/*!
- \fn template <typename Function> QThread *QThread::create(Function &&f)
- \since 5.10
-
- Creates a new QThread object that will execute the function \a f.
-
- The new thread is not started -- it must be started by an explicit call
- to start(). This allows you to connect to its signals, move QObjects
- to the thread, choose the new thread's priority and so on. The function
- \a f will be called in the new thread.
-
- Returns the newly created QThread instance.
-
- \note the caller acquires ownership of the returned QThread instance.
-
- \warning do not call start() on the returned QThread instance more than once;
- doing so will result in undefined behavior.
-
- \sa start()
-*/
-
-#if QT_CONFIG(cxx11_future)
class QThreadCreateThread : public QThread
{
public:
@@ -1116,6 +1293,13 @@ public:
{
}
+ ~QThreadCreateThread()
+ {
+ requestInterruption();
+ quit();
+ wait();
+ }
+
private:
void run() override
{
@@ -1129,7 +1313,6 @@ QThread *QThread::createThreadImpl(std::future<void> &&future)
{
return new QThreadCreateThread(std::move(future));
}
-#endif // QT_CONFIG(cxx11_future)
/*!
\class QDaemonThread
@@ -1144,7 +1327,9 @@ QDaemonThread::QDaemonThread(QObject *parent)
{
// QThread::started() is emitted from the thread we start
connect(this, &QThread::started,
- [](){ QThreadData::current()->requiresCoreApplication = false; });
+ this,
+ [](){ QThreadData::current()->requiresCoreApplication = false; },
+ Qt::DirectConnection);
}
QDaemonThread::~QDaemonThread()
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 5a1e63ee0a..641c8ef68a 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTHREAD_H
#define QTHREAD_H
@@ -44,18 +8,12 @@
#include <QtCore/qobject.h>
#include <QtCore/qdeadlinetimer.h>
-// For QThread::create. The configure-time test just checks for the availability
-// of std::future and std::async; for the C++17 codepath we perform some extra
-// checks here (for std::invoke and C++14 lambdas).
-#if QT_CONFIG(cxx11_future)
-# include <future> // for std::async
-# include <functional> // for std::invoke; no guard needed as it's a C++98 header
-
-# if defined(__cpp_lib_invoke) && __cpp_lib_invoke >= 201411 \
- && defined(__cpp_init_captures) && __cpp_init_captures >= 201304 \
- && defined(__cpp_generic_lambdas) && __cpp_generic_lambdas >= 201304
-# define QTHREAD_HAS_VARIADIC_CREATE
-# endif
+// For QThread::create
+#include <future> // for std::async
+#include <functional> // for std::invoke; no guard needed as it's a C++98 header
+// internal compiler error with mingw 8.1
+#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
+#include <intrin.h>
#endif
QT_BEGIN_NAMESPACE
@@ -64,6 +22,7 @@ QT_BEGIN_NAMESPACE
class QThreadData;
class QThreadPrivate;
class QAbstractEventDispatcher;
+class QEventLoopLocker;
class Q_CORE_EXPORT QThread : public QObject
{
@@ -71,6 +30,7 @@ class Q_CORE_EXPORT QThread : public QObject
public:
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
static QThread *currentThread();
+ static bool isMainThread();
static int idealThreadCount() noexcept;
static void yieldCurrentThread();
@@ -103,44 +63,36 @@ public:
void setStackSize(uint stackSize);
uint stackSize() const;
- void exit(int retcode = 0);
-
QAbstractEventDispatcher *eventDispatcher() const;
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
bool event(QEvent *event) override;
int loopLevel() const;
-#ifdef Q_CLANG_QDOC
- template <typename Function, typename... Args>
- static QThread *create(Function &&f, Args &&... args);
- template <typename Function>
- static QThread *create(Function &&f);
-#else
-# if QT_CONFIG(cxx11_future)
-# ifdef QTHREAD_HAS_VARIADIC_CREATE
+ bool isCurrentThread() const;
+
template <typename Function, typename... Args>
- static QThread *create(Function &&f, Args &&... args);
-# else
- template <typename Function>
- static QThread *create(Function &&f);
-# endif // QTHREAD_HAS_VARIADIC_CREATE
-# endif // QT_CONFIG(cxx11_future)
-#endif // Q_CLANG_QDOC
+ [[nodiscard]] static QThread *create(Function &&f, Args &&... args);
public Q_SLOTS:
void start(Priority = InheritPriority);
void terminate();
+ void exit(int retcode = 0);
void quit();
public:
bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
- // ### Qt6 inline this function
- bool wait(unsigned long time);
+ bool wait(unsigned long time)
+ {
+ if (time == (std::numeric_limits<unsigned long>::max)())
+ return wait(QDeadlineTimer(QDeadlineTimer::Forever));
+ return wait(QDeadlineTimer(time));
+ }
static void sleep(unsigned long);
static void msleep(unsigned long);
static void usleep(unsigned long);
+ static void sleep(std::chrono::nanoseconds nsec);
Q_SIGNALS:
void started(QPrivateSignal);
@@ -157,20 +109,15 @@ protected:
private:
Q_DECLARE_PRIVATE(QThread)
+ friend class QEventLoopLocker;
-#if QT_CONFIG(cxx11_future)
- static QThread *createThreadImpl(std::future<void> &&future);
-#endif
+ [[nodiscard]] static QThread *createThreadImpl(std::future<void> &&future);
static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
friend class QCoreApplication;
friend class QThreadData;
};
-#if QT_CONFIG(cxx11_future)
-
-#if defined(QTHREAD_HAS_VARIADIC_CREATE) || defined(Q_CLANG_QDOC)
-// C++17: std::thread's constructor complying call
template <typename Function, typename... Args>
QThread *QThread::create(Function &&f, Args &&... args)
{
@@ -185,57 +132,6 @@ QThread *QThread::create(Function &&f, Args &&... args)
std::move(threadFunction),
std::forward<Args>(args)...));
}
-#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
-// C++14: implementation for just one callable
-template <typename Function>
-QThread *QThread::create(Function &&f)
-{
- using DecayedFunction = typename std::decay<Function>::type;
- auto threadFunction =
- [f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void
- {
- (void)f();
- };
-
- return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction)));
-}
-#else
-// C++11: same as C++14, but with a workaround for not having generalized lambda captures
-namespace QtPrivate {
-template <typename Function>
-struct Callable
-{
- explicit Callable(Function &&f)
- : m_function(std::forward<Function>(f))
- {
- }
-
- // Apply the same semantics of a lambda closure type w.r.t. the special
- // member functions, if possible: delete the copy assignment operator,
- // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
- ~Callable() = default;
- Callable(const Callable &) = default;
- Callable(Callable &&) = default;
- Callable &operator=(const Callable &) = delete;
- Callable &operator=(Callable &&) = default;
-
- void operator()()
- {
- (void)m_function();
- }
-
- typename std::decay<Function>::type m_function;
-};
-} // namespace QtPrivate
-
-template <typename Function>
-QThread *QThread::create(Function &&f)
-{
- return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
-}
-#endif // QTHREAD_HAS_VARIADIC_CREATE
-
-#endif // QT_CONFIG(cxx11_future)
/*
On architectures and platforms we know, interpret the thread control
@@ -247,23 +143,47 @@ QThread *QThread::create(Function &&f)
value for anything. In Qt we use the handle to check if threads are identical,
for which the TCB is sufficient.
- So we use the fastest possible way, rathern than spend time on returning
+ So we use the fastest possible way, rather than spend time on returning
some pseudo-interoperable value.
*/
inline Qt::HANDLE QThread::currentThreadId() noexcept
{
+ // define is undefed if we have to fall back to currentThreadIdImpl
+#define QT_HAS_FAST_CURRENT_THREAD_ID
Qt::HANDLE tid; // typedef to void*
static_assert(sizeof(tid) == sizeof(void*));
// See https://akkadia.org/drepper/tls.pdf for x86 ABI
-#if defined(Q_PROCESSOR_X86_32) && defined(Q_OS_LINUX) // x86 32-bit always uses GS
- __asm__("movl %%gs:0, %0" : "=r" (tid) : : );
-#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN64)
+#if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) // x86 32-bit always uses GS
+ __asm__("mov %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
+#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
// 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
- __asm__("movq %%gs:0, %0" : "=r" (tid) : : );
-#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD))
+ __asm__("mov %%gs:0, %0" : "=r" (tid) : : );
+#elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
// x86_64 Linux, BSD uses FS
- __asm__("movq %%fs:0, %0" : "=r" (tid) : : );
+ __asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
+#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
+ // See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
+ // First get the pointer to the TIB
+ quint8 *tib;
+# if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
+ __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
+# else
+ tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
+# endif
+ // Then read the thread ID
+ tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
+#elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
+ // First get the pointer to the TIB
+ quint8 *tib;
+# if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
+ __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
+# else
+ tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
+# endif
+ // Then read the thread ID
+ tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x24);
#else
+#undef QT_HAS_FAST_CURRENT_THREAD_ID
tid = currentThreadIdImpl();
#endif
return tid;
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index c853bd1de4..c39e21ec9a 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTHREAD_P_H
#define QTHREAD_P_H
@@ -85,7 +49,7 @@ public:
: receiver(r), event(e), priority(p)
{ }
};
-Q_DECLARE_TYPEINFO(QPostEvent, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QPostEvent, Q_RELOCATABLE_TYPE);
inline bool operator<(const QPostEvent &first, const QPostEvent &second)
{
@@ -94,6 +58,7 @@ inline bool operator<(const QPostEvent &first, const QPostEvent &second)
// This class holds the list of posted events.
// The list has to be kept sorted by priority
+// It's used in a virtual in QCoreApplication, so ELFVERSION:ignore-next
class QPostEventList : public QList<QPostEvent>
{
public:
@@ -101,36 +66,101 @@ public:
int recursion;
// sendOffset == the current event to start sending
- int startOffset;
+ qsizetype startOffset;
// insertionOffset == set by sendPostedEvents to tell postEvent() where to start insertions
- int insertionOffset;
+ qsizetype insertionOffset;
QMutex mutex;
inline QPostEventList() : QList<QPostEvent>(), recursion(0), startOffset(0), insertionOffset(0) { }
- void addEvent(const QPostEvent &ev) {
- int priority = ev.priority;
- if (isEmpty() ||
- constLast().priority >= priority ||
- insertionOffset >= size()) {
- // optimization: we can simply append if the last event in
- // the queue has higher or equal priority
- append(ev);
- } else {
- // insert event in descending priority order, using upper
- // bound for a given priority (to ensure proper ordering
- // of events with the same priority)
- QPostEventList::iterator at = std::upper_bound(begin() + insertionOffset, end(), ev);
- insert(at, ev);
- }
- }
+ void addEvent(const QPostEvent &ev);
+
private:
//hides because they do not keep that list sorted. addEvent must be used
using QList<QPostEvent>::append;
using QList<QPostEvent>::insert;
};
+namespace QtPrivate {
+
+/* BindingStatusOrList is basically a QBiPointer (as found in declarative)
+ with some helper methods to manipulate the list. BindingStatusOrList starts
+ its life in a null state and supports the following transitions
+
+ 0 state (initial)
+ / \
+ / \
+ v v
+ pending object list----------->binding status
+ Note that binding status is the final state, and we never transition away
+ from it
+*/
+class BindingStatusOrList
+{
+ Q_DISABLE_COPY_MOVE(BindingStatusOrList)
+public:
+ using List = std::vector<QObject *>;
+
+ constexpr BindingStatusOrList() noexcept : data(0) {}
+ explicit BindingStatusOrList(QBindingStatus *status) noexcept :
+ data(encodeBindingStatus(status)) {}
+ explicit BindingStatusOrList(List *list) noexcept : data(encodeList(list)) {}
+
+ // requires external synchronization:
+ QBindingStatus *addObjectUnlessAlreadyStatus(QObject *object);
+ void removeObject(QObject *object);
+ void setStatusAndClearList(QBindingStatus *status) noexcept;
+
+
+ static bool isBindingStatus(quintptr data) noexcept
+ {
+ return !isNull(data) && !isList(data);
+ }
+ static bool isList(quintptr data) noexcept { return data & 1; }
+ static bool isNull(quintptr data) noexcept { return data == 0; }
+
+ // thread-safe:
+ QBindingStatus *bindingStatus() const noexcept
+ {
+ // synchronizes-with the store-release in setStatusAndClearList():
+ const auto d = data.load(std::memory_order_acquire);
+ if (isBindingStatus(d))
+ return reinterpret_cast<QBindingStatus *>(d);
+ else
+ return nullptr;
+ }
+
+ // requires external synchronization:
+ List *list() const noexcept
+ {
+ return decodeList(data.load(std::memory_order_relaxed));
+ }
+
+private:
+ static List *decodeList(quintptr ptr) noexcept
+ {
+ if (isList(ptr))
+ return reinterpret_cast<List *>(ptr & ~1);
+ else
+ return nullptr;
+ }
+
+ static quintptr encodeBindingStatus(QBindingStatus *status) noexcept
+ {
+ return quintptr(status);
+ }
+
+ static quintptr encodeList(List *list) noexcept
+ {
+ return quintptr(list) | 1;
+ }
+
+ std::atomic<quintptr> data;
+};
+
+} // namespace QtPrivate
+
#if QT_CONFIG(thread)
class Q_CORE_EXPORT QDaemonThread : public QThread
@@ -140,7 +170,7 @@ public:
~QDaemonThread();
};
-class QThreadPrivate : public QObjectPrivate
+class Q_AUTOTEST_EXPORT QThreadPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QThread)
@@ -149,6 +179,7 @@ public:
~QThreadPrivate();
void setPriority(QThread::Priority prio);
+ Qt::HANDLE threadId() const;
mutable QMutex mutex;
QAtomicInt quitLockRef;
@@ -162,9 +193,7 @@ public:
int returnCode;
uint stackSize;
- QThread::Priority priority;
-
- static QThread *threadForId(int id);
+ std::underlying_type_t<QThread::Priority> priority;
#ifdef Q_OS_UNIX
QWaitCondition thread_done;
@@ -176,7 +205,7 @@ public:
#ifdef Q_OS_WIN
static unsigned int __stdcall start(void *) noexcept;
- static void finish(void *, bool lockAnyway=true) noexcept;
+ static void finish(void *, bool lockAnyway = true) noexcept;
Qt::HANDLE handle;
unsigned int id;
@@ -201,6 +230,26 @@ public:
QCoreApplication::instance()->postEvent(q_ptr, new QEvent(QEvent::Quit));
}
}
+
+ QBindingStatus *bindingStatus()
+ {
+ return m_statusOrPendingObjects.bindingStatus();
+ }
+
+ /* Returns nullptr if the object has been added, or the binding status
+ if that one has been set in the meantime
+ */
+ QBindingStatus *addObjectWithPendingBindingStatusChange(QObject *obj);
+ void removeObjectWithPendingBindingStatusChange(QObject *obj);
+
+ // manipulating m_statusOrPendingObjects requires mutex to be locked
+ QtPrivate::BindingStatusOrList m_statusOrPendingObjects = {};
+#ifndef Q_OS_INTEGRITY
+private:
+ // Used in QThread(Private)::start to avoid racy access to QObject::objectName,
+ // unset afterwards. On INTEGRITY we set the thread name before starting it.
+ QString objectName;
+#endif
};
#else // QT_CONFIG(thread)
@@ -208,15 +257,19 @@ public:
class QThreadPrivate : public QObjectPrivate
{
public:
- QThreadPrivate(QThreadData *d = 0);
+ QThreadPrivate(QThreadData *d = nullptr);
~QThreadPrivate();
mutable QMutex mutex;
QThreadData *data;
+ QBindingStatus* m_bindingStatus;
bool running = false;
- static void setCurrentThread(QThread*) {}
- static QThread *threadForId(int) { return QThread::currentThread(); }
+ QBindingStatus* bindingStatus() { return m_bindingStatus; }
+ QBindingStatus *addObjectWithPendingBindingStatusChange(QObject *) { return nullptr; }
+ void removeObjectWithPendingBindingStatusChange(QObject *) {}
+
+ static void setCurrentThread(QThread *) { }
static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data);
void ref() {}
@@ -258,26 +311,6 @@ public:
return canWait;
}
- // This class provides per-thread (by way of being a QThreadData
- // member) storage for qFlagLocation()
- class FlaggedDebugSignatures
- {
- static const uint Count = 2;
-
- uint idx;
- const char* locations[Count];
-
- public:
- FlaggedDebugSignatures() : idx(0)
- { std::fill_n(locations, Count, static_cast<char*>(nullptr)); }
-
- void store(const char* method)
- { locations[idx++ % Count] = method; }
-
- bool contains(const char *method) const
- { return std::find(locations, locations + Count, method) != locations + Count; }
- };
-
private:
QAtomicInt _ref;
@@ -291,7 +324,6 @@ public:
QAtomicPointer<void> threadId;
QAtomicPointer<QAbstractEventDispatcher> eventDispatcher;
QList<void *> tls;
- FlaggedDebugSignatures flaggedSignatures;
bool quitNow;
bool canWait;
@@ -303,11 +335,8 @@ class QScopedScopeLevelCounter
{
QThreadData *threadData;
public:
- inline QScopedScopeLevelCounter(QThreadData *threadData)
- : threadData(threadData)
- { ++threadData->scopeLevel; }
- inline ~QScopedScopeLevelCounter()
- { --threadData->scopeLevel; }
+ QScopedScopeLevelCounter(QThreadData *threadData);
+ ~QScopedScopeLevelCounter();
};
// thread wrapper for the main() thread
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 18b6caf5fc..556f05018f 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qthread.h"
@@ -44,16 +8,21 @@
#include <private/qcoreapplication_p.h>
#include <private/qcore_unix_p.h>
+#include <private/qtools_p.h>
#if defined(Q_OS_DARWIN)
# include <private/qeventdispatcher_cf_p.h>
+#elif defined(Q_OS_WASM)
+# include <private/qeventdispatcher_wasm_p.h>
#else
# if !defined(QT_NO_GLIB)
# include "../kernel/qeventdispatcher_glib_p.h"
# endif
#endif
-#include <private/qeventdispatcher_unix_p.h>
+#if !defined(Q_OS_WASM)
+# include <private/qeventdispatcher_unix_p.h>
+#endif
#include "qthreadstorage.h"
@@ -68,8 +37,10 @@
#include <sched.h>
#include <errno.h>
-#ifdef Q_OS_BSD4
-#include <sys/sysctl.h>
+#if defined(Q_OS_FREEBSD)
+# include <sys/cpuset.h>
+#elif defined(Q_OS_BSD4)
+# include <sys/sysctl.h>
#endif
#ifdef Q_OS_VXWORKS
# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6))
@@ -102,6 +73,8 @@
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
#if QT_CONFIG(thread)
static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
@@ -109,65 +82,89 @@ static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
enum { ThreadPriorityResetFlag = 0x80000000 };
-class QThreadDataHolder
-{
-public:
- QThreadData* data;
+Q_CONSTINIT static thread_local QThreadData *currentThreadData = nullptr;
- ~QThreadDataHolder()
- {
- if (!data)
- return;
+Q_CONSTINIT static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
+Q_CONSTINIT static pthread_key_t current_thread_data_key;
- if (data->isAdopted) {
- QThread *thread = data->thread.loadAcquire();
- Q_ASSERT(thread);
- QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
- Q_ASSERT(!thread_p->finished);
- thread_p->finish(thread);
- }
- data->deref();
+static void destroy_current_thread_data(void *p)
+{
+ QThreadData *data = static_cast<QThreadData *>(p);
+ // thread_local variables are set to zero before calling this destructor function,
+ // if they are internally using pthread-specific data management,
+ // so we need to set it back to the right value...
+ currentThreadData = data;
+ if (data->isAdopted) {
+ QThread *thread = data->thread.loadAcquire();
+ Q_ASSERT(thread);
+ QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
+ Q_ASSERT(!thread_p->finished);
+ thread_p->finish(thread);
}
-};
+ data->deref();
+
+ // ... but we must reset it to zero before returning so we aren't
+ // leaving a dangling pointer.
+ currentThreadData = nullptr;
+}
+
+static void create_current_thread_data_key()
+{
+ pthread_key_create(&current_thread_data_key, destroy_current_thread_data);
+}
+
+static void destroy_current_thread_data_key()
+{
+ pthread_once(&current_thread_data_once, create_current_thread_data_key);
+ pthread_key_delete(current_thread_data_key);
+
+ // Reset current_thread_data_once in case we end up recreating
+ // the thread-data in the rare case of QObject construction
+ // after destroying the QThreadData.
+ pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
+ current_thread_data_once = pthread_once_init;
+}
+Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
-static thread_local QThreadDataHolder currentThreadData;
// Utility functions for getting, setting and clearing thread specific data.
static QThreadData *get_thread_data()
{
- return currentThreadData.data;
+ return currentThreadData;
}
static void set_thread_data(QThreadData *data)
{
- currentThreadData.data = data;
+ currentThreadData = data;
+ pthread_once(&current_thread_data_once, create_current_thread_data_key);
+ pthread_setspecific(current_thread_data_key, data);
}
static void clear_thread_data()
{
- currentThreadData.data = nullptr;
+ set_thread_data(nullptr);
}
template <typename T>
-static typename std::enable_if<QTypeInfo<T>::isIntegral, Qt::HANDLE>::type to_HANDLE(T id)
+static typename std::enable_if<std::is_integral_v<T>, Qt::HANDLE>::type to_HANDLE(T id)
{
return reinterpret_cast<Qt::HANDLE>(static_cast<intptr_t>(id));
}
template <typename T>
-static typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type from_HANDLE(Qt::HANDLE id)
+static typename std::enable_if<std::is_integral_v<T>, T>::type from_HANDLE(Qt::HANDLE id)
{
return static_cast<T>(reinterpret_cast<intptr_t>(id));
}
template <typename T>
-static typename std::enable_if<QTypeInfo<T>::isPointer, Qt::HANDLE>::type to_HANDLE(T id)
+static typename std::enable_if<std::is_pointer_v<T>, Qt::HANDLE>::type to_HANDLE(T id)
{
return id;
}
template <typename T>
-static typename std::enable_if<QTypeInfo<T>::isPointer, T>::type from_HANDLE(Qt::HANDLE id)
+static typename std::enable_if<std::is_pointer_v<T>, T>::type from_HANDLE(Qt::HANDLE id)
{
return static_cast<T>(id);
}
@@ -194,8 +191,10 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->deref();
data->isAdopted = true;
data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
- if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
+ if (!QCoreApplicationPrivate::theMainThreadId.loadAcquire()) {
QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
+ QCoreApplicationPrivate::theMainThreadId.storeRelaxed(data->threadId.loadRelaxed());
+ }
}
return data;
}
@@ -210,7 +209,7 @@ void QAdoptedThread::init()
*/
extern "C" {
-typedef void*(*QtThreadCallback)(void*);
+typedef void *(*QtThreadCallback)(void *);
}
#endif // QT_CONFIG(thread)
@@ -225,6 +224,8 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
return new QEventDispatcherCoreFoundation;
else
return new QEventDispatcherUNIX;
+#elif defined(Q_OS_WASM)
+ return new QEventDispatcherWasm();
#elif !defined(QT_NO_GLIB)
const bool isQtMainThread = data->thread.loadAcquire() == QCoreApplicationPrivate::mainThread();
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
@@ -240,12 +241,12 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
#if QT_CONFIG(thread)
-#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
+#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
static void setCurrentThreadName(const char *name)
{
# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
-# elif defined(Q_OS_MAC)
+# elif defined(Q_OS_DARWIN)
pthread_setname_np(name);
# elif defined(Q_OS_QNX)
pthread_setname_np(pthread_self(), name);
@@ -253,17 +254,41 @@ static void setCurrentThreadName(const char *name)
}
#endif
+namespace {
+template <typename T>
+void terminate_on_exception(T &&t)
+{
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ std::forward<T>(t)();
+#ifndef QT_NO_EXCEPTIONS
+#ifdef __GLIBCXX__
+ // POSIX thread cancellation under glibc is implemented by throwing an exception
+ // of this type. Do what libstdc++ is doing and handle it specially in order not to
+ // abort the application if user's code calls a cancellation function.
+ } catch (abi::__forced_unwind &) {
+ throw;
+#endif // __GLIBCXX__
+ } catch (...) {
+ qTerminate();
+ }
+#endif // QT_NO_EXCEPTIONS
+}
+} // unnamed namespace
+
void *QThreadPrivate::start(void *arg)
{
-#if !defined(Q_OS_ANDROID)
+#ifdef PTHREAD_CANCEL_DISABLE
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
#endif
- pthread_cleanup_push(QThreadPrivate::finish, arg);
-
-#ifndef QT_NO_EXCEPTIONS
- try
+#if !defined(Q_OS_QNX)
+ // On QNX, calling finish() from a thread_local destructor causes the C
+ // library to hang.
+ static thread_local
#endif
- {
+ auto cleanup = qScopeGuard([=] { finish(arg); });
+ terminate_on_exception([&] {
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
@@ -271,11 +296,13 @@ void *QThreadPrivate::start(void *arg)
QMutexLocker locker(&thr->d_func()->mutex);
// do we need to reset the thread priority?
- if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
+ if (thr->d_func()->priority & ThreadPriorityResetFlag) {
thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
}
- data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
+ // threadId is set in QThread::start()
+ Q_ASSERT(pthread_equal(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()),
+ pthread_self()));
set_thread_data(data);
data->ref();
@@ -283,54 +310,35 @@ void *QThreadPrivate::start(void *arg)
}
data->ensureEventDispatcher();
+ data->eventDispatcher.loadRelaxed()->startingUp();
-#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
+#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
{
// Sets the name of the current thread. We can only do this
// when the thread is starting, as we don't have a cross
// platform way of setting the name of an arbitrary thread.
- if (Q_LIKELY(thr->objectName().isEmpty()))
+ if (Q_LIKELY(thr->d_func()->objectName.isEmpty()))
setCurrentThreadName(thr->metaObject()->className());
else
- setCurrentThreadName(thr->objectName().toLocal8Bit());
+ setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit());
}
#endif
emit thr->started(QThread::QPrivateSignal());
-#if !defined(Q_OS_ANDROID)
+#ifdef PTHREAD_CANCEL_DISABLE
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr);
pthread_testcancel();
#endif
thr->run();
- }
-#ifndef QT_NO_EXCEPTIONS
-#ifdef __GLIBCXX__
- // POSIX thread cancellation under glibc is implemented by throwing an exception
- // of this type. Do what libstdc++ is doing and handle it specially in order not to
- // abort the application if user's code calls a cancellation function.
- catch (const abi::__forced_unwind &) {
- throw;
- }
-#endif // __GLIBCXX__
- catch (...) {
- qTerminate();
- }
-#endif // QT_NO_EXCEPTIONS
-
- // This pop runs finish() below. It's outside the try/catch (and has its
- // own try/catch) to prevent finish() to be run in case an exception is
- // thrown.
- pthread_cleanup_pop(1);
+ });
+ // The qScopeGuard above call runs finish() below.
return nullptr;
}
void QThreadPrivate::finish(void *arg)
{
-#ifndef QT_NO_EXCEPTIONS
- try
-#endif
- {
+ terminate_on_exception([&] {
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
@@ -341,6 +349,7 @@ void QThreadPrivate::finish(void *arg)
void *data = &d->data->tls;
locker.unlock();
emit thr->finished(QThread::QPrivateSignal());
+ qCDebug(lcDeleteLater) << "Sending deferred delete events as part of finishing thread" << thr;
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QThreadStorageData::finish((void **)data);
locker.relock();
@@ -356,24 +365,13 @@ void QThreadPrivate::finish(void *arg)
d->running = false;
d->finished = true;
- d->interruptionRequested = false;
+ d->interruptionRequested.store(false, std::memory_order_relaxed);
d->isInFinish = false;
+ d->data->threadId.storeRelaxed(nullptr);
+
d->thread_done.wakeAll();
- }
-#ifndef QT_NO_EXCEPTIONS
-#ifdef __GLIBCXX__
- // POSIX thread cancellation under glibc is implemented by throwing an exception
- // of this type. Do what libstdc++ is doing and handle it specially in order not to
- // abort the application if user's code calls a cancellation function.
- catch (const abi::__forced_unwind &) {
- throw;
- }
-#endif // __GLIBCXX__
- catch (...) {
- qTerminate();
- }
-#endif // QT_NO_EXCEPTIONS
+ });
}
@@ -421,8 +419,31 @@ int QThread::idealThreadCount() noexcept
} else {
cores = (int)psd.psd_proc_cnt;
}
+#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
+# if defined(Q_OS_FREEBSD) && !defined(CPU_COUNT_S)
+# define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp))
+ // match the Linux API for simplicity
+ using cpu_set_t = cpuset_t;
+ auto sched_getaffinity = [](pid_t, size_t cpusetsize, cpu_set_t *mask) {
+ return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, cpusetsize, mask);
+ };
+# endif
+
+ // get the number of threads we're assigned, not the total in the system
+ QVarLengthArray<cpu_set_t, 1> cpuset(1);
+ int size = 1;
+ if (Q_UNLIKELY(sched_getaffinity(0, sizeof(cpu_set_t), cpuset.data()) < 0)) {
+ for (size = 2; size <= 4; size *= 2) {
+ cpuset.resize(size);
+ if (sched_getaffinity(0, sizeof(cpu_set_t) * size, cpuset.data()) == 0)
+ break;
+ }
+ if (size > 4)
+ return 1;
+ }
+ cores = CPU_COUNT_S(sizeof(cpu_set_t) * size, cpuset.data());
#elif defined(Q_OS_BSD4)
- // FreeBSD, OpenBSD, NetBSD, BSD/OS, OS X, iOS
+ // OpenBSD, NetBSD, BSD/OS, Darwin (macOS, iOS, etc.)
size_t len = sizeof(cores);
int mib[2];
mib[0] = CTL_HW;
@@ -460,7 +481,7 @@ int QThread::idealThreadCount() noexcept
#elif defined(Q_OS_WASM)
cores = QThreadPrivate::idealThreadCount;
#else
- // the rest: Linux, Solaris, AIX, Tru64
+ // the rest: Solaris, AIX, Tru64
cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (cores == -1)
return 1;
@@ -475,27 +496,38 @@ void QThread::yieldCurrentThread()
#endif // QT_CONFIG(thread)
-static timespec makeTimespec(time_t secs, long nsecs)
+static void qt_nanosleep(timespec amount)
{
- struct timespec ts;
- ts.tv_sec = secs;
- ts.tv_nsec = nsecs;
- return ts;
+ // We'd like to use clock_nanosleep.
+ //
+ // But clock_nanosleep is from POSIX.1-2001 and both are *not*
+ // affected by clock changes when using relative sleeps, even for
+ // CLOCK_REALTIME.
+ //
+ // nanosleep is POSIX.1-1993
+
+ int r;
+ QT_EINTR_LOOP(r, nanosleep(&amount, &amount));
}
void QThread::sleep(unsigned long secs)
{
- qt_nanosleep(makeTimespec(secs, 0));
+ sleep(std::chrono::seconds{secs});
}
void QThread::msleep(unsigned long msecs)
{
- qt_nanosleep(makeTimespec(msecs / 1000, msecs % 1000 * 1000 * 1000));
+ sleep(std::chrono::milliseconds{msecs});
}
void QThread::usleep(unsigned long usecs)
{
- qt_nanosleep(makeTimespec(usecs / 1000 / 1000, usecs % (1000*1000) * 1000));
+ sleep(std::chrono::microseconds{usecs});
+}
+
+void QThread::sleep(std::chrono::nanoseconds nsec)
+{
+ qt_nanosleep(durationToTimespec(nsec));
}
#if QT_CONFIG(thread)
@@ -610,7 +642,7 @@ void QThread::start(Priority priority)
d->finished = false;
d->returnCode = 0;
d->exited = false;
- d->interruptionRequested = false;
+ d->interruptionRequested.store(false, std::memory_order_relaxed);
pthread_attr_t attr;
pthread_attr_init(&attr);
@@ -653,7 +685,7 @@ void QThread::start(Priority priority)
// could not set scheduling hints, fallback to inheriting them
// we'll try again from inside the thread
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
- d->priority = Priority(priority | ThreadPriorityResetFlag);
+ d->priority = qToUnderlying(priority) | ThreadPriorityResetFlag;
}
break;
}
@@ -684,7 +716,12 @@ void QThread::start(Priority priority)
pthread_attr_setthreadname(&attr, metaObject()->className());
else
pthread_attr_setthreadname(&attr, objectName().toLocal8Bit());
+#else
+ // avoid interacting with the binding system
+ d->objectName = d->extraData ? d->extraData->objectName.valueBypassingBindings()
+ : QString();
#endif
+
pthread_t threadId;
int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
if (code == EPERM) {
@@ -741,6 +778,8 @@ bool QThread::wait(QDeadlineTimer deadline)
if (!d->thread_done.wait(locker.mutex(), deadline))
return false;
}
+ Q_ASSERT(d->data->threadId.loadRelaxed() == nullptr);
+
return true;
}
@@ -750,7 +789,7 @@ void QThread::setTerminationEnabled(bool enabled)
Q_ASSERT_X(thr != nullptr, "QThread::setTerminationEnabled()",
"Current thread was not started with QThread.");
- Q_UNUSED(thr)
+ Q_UNUSED(thr);
#if defined(Q_OS_ANDROID)
Q_UNUSED(enabled);
#else
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index ffd476d6d3..74bc1d2650 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qthread.h"
#include "qthread_p.h"
@@ -55,6 +19,17 @@
#endif // _MT
#include <process.h>
+extern "C" {
+// MinGW is missing the declaration of SetThreadDescription:
+WINBASEAPI
+HRESULT
+WINAPI
+SetThreadDescription(
+ _In_ HANDLE hThread,
+ _In_ PCWSTR lpThreadDescription
+ );
+}
+
QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread)
@@ -67,7 +42,7 @@ void qt_create_tls()
{
if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
return;
- static QBasicMutex mutex;
+ Q_CONSTINIT static QBasicMutex mutex;
QMutexLocker locker(&mutex);
if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
return;
@@ -112,8 +87,9 @@ QThreadData *QThreadData::current(bool createIfNecessary)
threadData->isAdopted = true;
threadData->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
- if (!QCoreApplicationPrivate::theMainThread) {
- QCoreApplicationPrivate::theMainThread = threadData->thread.loadRelaxed();
+ if (!QCoreApplicationPrivate::theMainThreadId) {
+ QCoreApplicationPrivate::theMainThread.storeRelease(threadData->thread.loadRelaxed());
+ QCoreApplicationPrivate::theMainThreadId.storeRelaxed(threadData->threadId.loadRelaxed());
} else {
HANDLE realHandle = INVALID_HANDLE_VALUE;
DuplicateHandle(GetCurrentProcess(),
@@ -137,7 +113,7 @@ void QAdoptedThread::init()
static QList<HANDLE> qt_adopted_thread_handles;
static QList<QThread *> qt_adopted_qthreads;
-static QBasicMutex qt_adopted_thread_watcher_mutex;
+Q_CONSTINIT static QBasicMutex qt_adopted_thread_watcher_mutex;
static DWORD qt_adopted_thread_watcher_id = 0;
static HANDLE qt_adopted_thread_wakeup = 0;
@@ -229,7 +205,7 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
QThread *thread = data->thread;
Q_ASSERT(thread);
auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
- Q_UNUSED(thread_p)
+ Q_UNUSED(thread_p);
Q_ASSERT(!thread_p->finished);
QThreadPrivate::finish(thread);
}
@@ -248,39 +224,6 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
return 0;
}
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
-
-#ifndef Q_OS_WIN64
-# define ULONG_PTR DWORD
-#endif
-
-typedef struct tagTHREADNAME_INFO
-{
- DWORD dwType; // must be 0x1000
- LPCSTR szName; // pointer to name (in user addr space)
- HANDLE dwThreadID; // thread ID (-1=caller thread)
- DWORD dwFlags; // reserved for future use, must be zero
-} THREADNAME_INFO;
-
-void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
-{
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = threadName;
- info.dwThreadID = threadId;
- info.dwFlags = 0;
-
- __try
- {
- RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD),
- reinterpret_cast<const ULONG_PTR*>(&info));
- }
- __except (EXCEPTION_CONTINUE_EXECUTION)
- {
- }
-}
-#endif // !QT_NO_DEBUG && Q_CC_MSVC
-
/**************************************************************************
** QThreadPrivate
*************************************************************************/
@@ -312,14 +255,13 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
}
data->ensureEventDispatcher();
+ data->eventDispatcher.loadRelaxed()->startingUp();
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
// sets the name of the current thread.
- QByteArray objectName = thr->objectName().toLocal8Bit();
- qt_set_thread_name(HANDLE(-1),
- objectName.isEmpty() ?
- thr->metaObject()->className() : objectName.constData());
-#endif
+ QString threadName = std::exchange(thr->d_func()->objectName, {});
+ if (Q_LIKELY(threadName.isEmpty()))
+ threadName = QString::fromUtf8(thr->metaObject()->className());
+ SetThreadDescription(GetCurrentThread(), reinterpret_cast<const wchar_t *>(threadName.utf16()));
emit thr->started(QThread::QPrivateSignal());
QThread::setTerminationEnabled(true);
@@ -329,34 +271,50 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
return 0;
}
+/*
+ For regularly terminating threads, this will be called and executed by the thread as the
+ last code before the thread exits. In that case, \a arg is the current QThread.
+
+ However, this function will also be called by QThread::terminate (as well as wait() and
+ setTerminationEnabled) to give Qt a chance to update the terminated thread's state and
+ process pending DeleteLater events for objects that live in the terminated thread. And for
+ adopted thread, this method is called by the thread watcher.
+
+ In those cases, \a arg will not be the current thread.
+*/
void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
- QMutexLocker locker(lockAnyway ? &d->mutex : 0);
+ QMutexLocker locker(lockAnyway ? &d->mutex : nullptr);
d->isInFinish = true;
d->priority = QThread::InheritPriority;
void **tls_data = reinterpret_cast<void **>(&d->data->tls);
- locker.unlock();
+ if (lockAnyway)
+ locker.unlock();
emit thr->finished(QThread::QPrivateSignal());
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ qCDebug(lcDeleteLater) << "Sending deferred delete events as part of finishing thread" << thr;
+ QCoreApplicationPrivate::sendPostedEvents(nullptr, QEvent::DeferredDelete, d->data);
QThreadStorageData::finish(tls_data);
- locker.relock();
+ if (lockAnyway)
+ locker.relock();
QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
d->data->eventDispatcher = 0;
- locker.unlock();
+ if (lockAnyway)
+ locker.unlock();
eventDispatcher->closingDown();
delete eventDispatcher;
- locker.relock();
+ if (lockAnyway)
+ locker.relock();
}
d->running = false;
d->finished = true;
d->isInFinish = false;
- d->interruptionRequested = false;
+ d->interruptionRequested.store(false, std::memory_order_relaxed);
if (!d->waiters) {
CloseHandle(d->handle);
@@ -389,6 +347,12 @@ void QThread::yieldCurrentThread()
#endif // QT_CONFIG(thread)
+void QThread::sleep(std::chrono::nanoseconds nsecs)
+{
+ using namespace std::chrono;
+ ::Sleep(DWORD(duration_cast<milliseconds>(nsecs).count()));
+}
+
void QThread::sleep(unsigned long secs)
{
::Sleep(secs * 1000);
@@ -420,11 +384,14 @@ void QThread::start(Priority priority)
if (d->running)
return;
+ // avoid interacting with the binding system
+ d->objectName = d->extraData ? d->extraData->objectName.valueBypassingBindings()
+ : QString();
d->running = true;
d->finished = false;
d->exited = false;
d->returnCode = 0;
- d->interruptionRequested = false;
+ d->interruptionRequested.store(false, std::memory_order_relaxed);
/*
NOTE: we create the thread in the suspended state, set the
@@ -456,7 +423,7 @@ void QThread::start(Priority priority)
int prio;
d->priority = priority;
- switch (d->priority) {
+ switch (priority) {
case IdlePriority:
prio = THREAD_PRIORITY_IDLE;
break;
@@ -583,7 +550,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
int prio;
priority = threadPriority;
- switch (priority) {
+ switch (threadPriority) {
case QThread::IdlePriority:
prio = THREAD_PRIORITY_IDLE;
break;
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index 1478cfcb19..c7531111da 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -1,51 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qthreadpool.h"
#include "qthreadpool_p.h"
#include "qdeadlinetimer.h"
#include "qcoreapplication.h"
+#include <QtCore/qpointer.h>
+
#include <algorithm>
+#include <memory>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*
QThread wrapper, provides synchronization against a ThreadPool
*/
@@ -88,9 +57,8 @@ void QThreadPoolThread::run()
do {
if (r) {
+ // If autoDelete() is false, r might already be deleted after run(), so check status now.
const bool del = r->autoDelete();
- Q_ASSERT(!del || r->ref == 1);
-
// run the task
locker.unlock();
@@ -113,16 +81,15 @@ void QThreadPoolThread::run()
locker.relock();
}
- // if too many threads are active, expire this thread
+ // if too many threads are active, stop working in this one
if (manager->tooManyThreadsActive())
break;
- if (manager->queue.isEmpty()) {
- r = nullptr;
+ // all work is done, time to wait for more
+ if (manager->queue.isEmpty())
break;
- }
- QueuePage *page = manager->queue.first();
+ QueuePage *page = manager->queue.constFirst();
r = page->pop();
if (page->isFinished()) {
@@ -131,26 +98,32 @@ void QThreadPoolThread::run()
}
} while (true);
- // if too many threads are active, expire this thread
- bool expired = manager->tooManyThreadsActive();
- if (!expired) {
- manager->waitingThreads.enqueue(this);
+ // this thread is about to be deleted, do not wait or expire
+ if (!manager->allThreads.contains(this)) {
registerThreadInactive();
- // wait for work, exiting after the expiry timeout is reached
- runnableReady.wait(locker.mutex(), QDeadlineTimer(manager->expiryTimeout));
- ++manager->activeThreads;
- if (manager->waitingThreads.removeOne(this))
- expired = true;
- if (!manager->allThreads.contains(this)) {
- registerThreadInactive();
- break;
- }
+ return;
}
- if (expired) {
+
+ // if too many threads are active, expire this thread
+ if (manager->tooManyThreadsActive()) {
manager->expiredThreads.enqueue(this);
registerThreadInactive();
- break;
+ return;
+ }
+ manager->waitingThreads.enqueue(this);
+ registerThreadInactive();
+ // wait for work, exiting after the expiry timeout is reached
+ runnableReady.wait(locker.mutex(), QDeadlineTimer(manager->expiryTimeout));
+ // this thread is about to be deleted, do not work or expire
+ if (!manager->allThreads.contains(this)) {
+ Q_ASSERT(manager->queue.isEmpty());
+ return;
}
+ if (manager->waitingThreads.removeOne(this)) {
+ manager->expiredThreads.enqueue(this);
+ return;
+ }
+ ++manager->activeThreads;
}
}
@@ -177,10 +150,10 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
}
// can't do anything if we're over the limit
- if (activeThreadCount() >= maxThreadCount)
+ if (areAllThreadsActive())
return false;
- if (waitingThreads.count() > 0) {
+ if (!waitingThreads.isEmpty()) {
// recycle an available thread
enqueueTask(task);
waitingThreads.takeFirst()->runnableReady.wakeOne();
@@ -195,7 +168,12 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
++activeThreads;
thread->runnable = task;
- thread->start();
+
+ // Ensure that the thread has actually finished, otherwise the following
+ // start() has no effect.
+ thread->wait();
+ Q_ASSERT(thread->isFinished());
+ thread->start(threadPriority);
return true;
}
@@ -212,7 +190,7 @@ inline bool comparePriority(int priority, const QueuePage *p)
void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
{
Q_ASSERT(runnable != nullptr);
- for (QueuePage *page : qAsConst(queue)) {
+ for (QueuePage *page : std::as_const(queue)) {
if (page->priority() == priority && !page->isFull()) {
page->push(runnable);
return;
@@ -224,9 +202,9 @@ void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
int QThreadPoolPrivate::activeThreadCount() const
{
- return (allThreads.count()
- - expiredThreads.count()
- - waitingThreads.count()
+ return (allThreads.size()
+ - expiredThreads.size()
+ - waitingThreads.size()
+ reservedThreads);
}
@@ -234,7 +212,7 @@ void QThreadPoolPrivate::tryToStartMoreThreads()
{
// try to push tasks on the queue to any available threads
while (!queue.isEmpty()) {
- QueuePage *page = queue.first();
+ QueuePage *page = queue.constFirst();
if (!tryStart(page->first()))
break;
@@ -247,10 +225,16 @@ void QThreadPoolPrivate::tryToStartMoreThreads()
}
}
+bool QThreadPoolPrivate::areAllThreadsActive() const
+{
+ const int activeThreadCount = this->activeThreadCount();
+ return activeThreadCount >= maxThreadCount() && (activeThreadCount - reservedThreads) >= 1;
+}
+
bool QThreadPoolPrivate::tooManyThreadsActive() const
{
const int activeThreadCount = this->activeThreadCount();
- return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;
+ return activeThreadCount > maxThreadCount() && (activeThreadCount - reservedThreads) > 1;
}
/*!
@@ -259,32 +243,36 @@ bool QThreadPoolPrivate::tooManyThreadsActive() const
void QThreadPoolPrivate::startThread(QRunnable *runnable)
{
Q_ASSERT(runnable != nullptr);
- QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
- thread->setObjectName(QLatin1String("Thread (pooled)"));
- Q_ASSERT(!allThreads.contains(thread.data())); // if this assert hits, we have an ABA problem (deleted threads don't get removed here)
- allThreads.insert(thread.data());
+ auto thread = std::make_unique<QThreadPoolThread>(this);
+ if (objectName.isEmpty())
+ objectName = u"Thread (pooled)"_s;
+ thread->setObjectName(objectName);
+ Q_ASSERT(!allThreads.contains(thread.get())); // if this assert hits, we have an ABA problem (deleted threads don't get removed here)
+ allThreads.insert(thread.get());
++activeThreads;
thread->runnable = runnable;
- thread.take()->start();
+ thread.release()->start(threadPriority);
}
/*!
\internal
- Helper function only to be called from waitForDone(int)
+ Helper function only to be called from waitForDone()
+
+ Deletes all current threads.
*/
void QThreadPoolPrivate::reset()
{
// move the contents of the set out so that we can iterate without the lock
- QSet<QThreadPoolThread *> allThreadsCopy;
- allThreadsCopy.swap(allThreads);
+ auto allThreadsCopy = std::exchange(allThreads, {});
expiredThreads.clear();
waitingThreads.clear();
+
mutex.unlock();
- for (QThreadPoolThread *thread: qAsConst(allThreadsCopy)) {
- if (!thread->isFinished()) {
+ for (QThreadPoolThread *thread : std::as_const(allThreadsCopy)) {
+ if (thread->isRunning()) {
thread->runnableReady.wakeAll();
thread->wait();
}
@@ -297,47 +285,39 @@ void QThreadPoolPrivate::reset()
/*!
\internal
- Helper function only to be called from waitForDone(int)
+ Helper function only to be called from the public waitForDone()
*/
bool QThreadPoolPrivate::waitForDone(const QDeadlineTimer &timer)
{
+ QMutexLocker locker(&mutex);
while (!(queue.isEmpty() && activeThreads == 0) && !timer.hasExpired())
noActiveThreads.wait(&mutex, timer);
- return queue.isEmpty() && activeThreads == 0;
-}
-
-bool QThreadPoolPrivate::waitForDone(int msecs)
-{
- QMutexLocker locker(&mutex);
- QDeadlineTimer timer(msecs);
- do {
- if (!waitForDone(timer))
- return false;
- reset();
- // More threads can be started during reset(), in that case continue
- // waiting if we still have time left.
- } while ((!queue.isEmpty() || activeThreads) && !timer.hasExpired());
+ if (!queue.isEmpty() || activeThreads)
+ return false;
- return queue.isEmpty() && activeThreads == 0;
+ reset();
+ // New jobs might have started during reset, but return anyway
+ // as the active thread and task count did reach 0 once, and
+ // race conditions are outside our scope.
+ return true;
}
void QThreadPoolPrivate::clear()
{
QMutexLocker locker(&mutex);
- for (QueuePage *page : qAsConst(queue)) {
+ while (!queue.isEmpty()) {
+ auto *page = queue.takeLast();
while (!page->isFinished()) {
QRunnable *r = page->pop();
if (r && r->autoDelete()) {
- Q_ASSERT(r->ref == 1);
locker.unlock();
delete r;
locker.relock();
}
}
+ delete page;
}
- qDeleteAll(queue);
- queue.clear();
}
/*!
@@ -365,16 +345,12 @@ bool QThreadPool::tryTake(QRunnable *runnable)
return false;
QMutexLocker locker(&d->mutex);
- for (QueuePage *page : qAsConst(d->queue)) {
+ for (QueuePage *page : std::as_const(d->queue)) {
if (page->tryTake(runnable)) {
if (page->isFinished()) {
d->queue.removeOne(page);
delete page;
}
- if (runnable->autoDelete()) {
- Q_ASSERT(runnable->ref == 1);
- --runnable->ref; // undo ++ref in start()
- }
return true;
}
}
@@ -393,14 +369,13 @@ void QThreadPoolPrivate::stealAndRunRunnable(QRunnable *runnable)
Q_Q(QThreadPool);
if (!q->tryTake(runnable))
return;
+ // If autoDelete() is false, runnable might already be deleted after run(), so check status now.
const bool del = runnable->autoDelete();
runnable->run();
- if (del) {
- Q_ASSERT(runnable->ref == 0); // tryTake already deref'ed
+ if (del)
delete runnable;
- }
}
/*!
@@ -412,7 +387,7 @@ void QThreadPoolPrivate::stealAndRunRunnable(QRunnable *runnable)
\ingroup thread
- QThreadPool manages and recyles individual QThread objects to help reduce
+ QThreadPool manages and recycles individual QThread objects to help reduce
thread creation costs in programs that use threads. Each Qt application
has one global QThreadPool object, which can be accessed by calling
globalInstance().
@@ -461,7 +436,14 @@ void QThreadPoolPrivate::stealAndRunRunnable(QRunnable *runnable)
*/
QThreadPool::QThreadPool(QObject *parent)
: QObject(*new QThreadPoolPrivate, parent)
-{ }
+{
+ Q_D(QThreadPool);
+ connect(this, &QObject::objectNameChanged, this, [d](const QString &newName) {
+ // We keep a copy of the name under our own lock, so we can access it thread-safely.
+ QMutexLocker locker(&d->mutex);
+ d->objectName = newName;
+ });
+}
/*!
Destroys the QThreadPool.
@@ -469,7 +451,10 @@ QThreadPool::QThreadPool(QObject *parent)
*/
QThreadPool::~QThreadPool()
{
+ Q_D(QThreadPool);
waitForDone();
+ Q_ASSERT(d->queue.isEmpty());
+ Q_ASSERT(d->allThreads.isEmpty());
}
/*!
@@ -477,8 +462,8 @@ QThreadPool::~QThreadPool()
*/
QThreadPool *QThreadPool::globalInstance()
{
- static QPointer<QThreadPool> theInstance;
- static QBasicMutex theMutex;
+ Q_CONSTINIT static QPointer<QThreadPool> theInstance;
+ Q_CONSTINIT static QBasicMutex theMutex;
const QMutexLocker locker(&theMutex);
if (theInstance.isNull() && !QCoreApplication::closingDown())
@@ -487,6 +472,21 @@ QThreadPool *QThreadPool::globalInstance()
}
/*!
+ Returns the QThreadPool instance for Qt Gui.
+ \internal
+*/
+QThreadPool *QThreadPoolPrivate::qtGuiInstance()
+{
+ Q_CONSTINIT static QPointer<QThreadPool> guiInstance;
+ Q_CONSTINIT static QBasicMutex theMutex;
+
+ const QMutexLocker locker(&theMutex);
+ if (guiInstance.isNull() && !QCoreApplication::closingDown())
+ guiInstance = new QThreadPool();
+ return guiInstance;
+}
+
+/*!
Reserves a thread and uses it to run \a runnable, unless this thread will
make the current thread count exceed maxThreadCount(). In that case,
\a runnable is added to a run queue instead. The \a priority argument can
@@ -508,34 +508,27 @@ void QThreadPool::start(QRunnable *runnable, int priority)
Q_D(QThreadPool);
QMutexLocker locker(&d->mutex);
- if (runnable->autoDelete()) {
- Q_ASSERT(runnable->ref == 0);
- ++runnable->ref;
- }
- if (!d->tryStart(runnable)) {
+ if (!d->tryStart(runnable))
d->enqueueTask(runnable, priority);
-
- if (!d->waitingThreads.isEmpty())
- d->waitingThreads.takeFirst()->runnableReady.wakeOne();
- }
}
/*!
+ \fn template<typename Callable, QRunnable::if_callable<Callable>> void QThreadPool::start(Callable &&callableToRun, int priority)
\overload
\since 5.15
- Reserves a thread and uses it to run \a functionToRun, unless this thread will
+ Reserves a thread and uses it to run \a callableToRun, unless this thread will
make the current thread count exceed maxThreadCount(). In that case,
- \a functionToRun is added to a run queue instead. The \a priority argument can
+ \a callableToRun is added to a run queue instead. The \a priority argument can
be used to control the run queue's order of execution.
+
+ \note This function participates in overload resolution only if \c Callable
+ is a function or function object which can be called with zero arguments.
+
+ \note In Qt version prior to 6.6, this function took std::function<void()>,
+ and therefore couldn't handle move-only callables.
*/
-void QThreadPool::start(std::function<void()> functionToRun, int priority)
-{
- if (!functionToRun)
- return;
- start(QRunnable::create(std::move(functionToRun)), priority);
-}
/*!
Attempts to reserve a thread to run \a runnable.
@@ -558,54 +551,35 @@ bool QThreadPool::tryStart(QRunnable *runnable)
if (!runnable)
return false;
- if (runnable->autoDelete()) {
- Q_ASSERT(runnable->ref == 0);
- ++runnable->ref;
- }
-
Q_D(QThreadPool);
QMutexLocker locker(&d->mutex);
if (d->tryStart(runnable))
return true;
- // Undo the reference above as we did not start the runnable and
- // take over ownership.
- if (runnable->autoDelete()) {
- --runnable->ref;
- Q_ASSERT(runnable->ref == 0);
- }
return false;
}
/*!
+ \fn template<typename Callable, QRunnable::if_callable<Callable>> bool QThreadPool::tryStart(Callable &&callableToRun)
\overload
\since 5.15
- Attempts to reserve a thread to run \a functionToRun.
+ Attempts to reserve a thread to run \a callableToRun.
If no threads are available at the time of calling, then this function
- does nothing and returns \c false. Otherwise, \a functionToRun is run immediately
+ does nothing and returns \c false. Otherwise, \a callableToRun is run immediately
using one available thread and this function returns \c true.
-*/
-bool QThreadPool::tryStart(std::function<void()> functionToRun)
-{
- if (!functionToRun)
- return false;
- Q_D(QThreadPool);
- QMutexLocker locker(&d->mutex);
- if (!d->allThreads.isEmpty() && d->activeThreadCount() >= d->maxThreadCount)
- return false;
+ \note This function participates in overload resolution only if \c Callable
+ is a function or function object which can be called with zero arguments.
- QRunnable *runnable = QRunnable::create(std::move(functionToRun));
- if (d->tryStart(runnable))
- return true;
- delete runnable;
- return false;
-}
+ \note In Qt version prior to 6.6, this function took std::function<void()>,
+ and therefore couldn't handle move-only callables.
+*/
/*! \property QThreadPool::expiryTimeout
+ \brief the thread expiry timeout value in milliseconds.
- Threads that are unused for \a expiryTimeout milliseconds are considered
+ Threads that are unused for \e expiryTimeout milliseconds are considered
to have expired and will exit. Such threads will be restarted as needed.
The default \a expiryTimeout is 30000 milliseconds (30 seconds). If
\a expiryTimeout is negative, newly created threads will not expire, e.g.,
@@ -619,22 +593,24 @@ bool QThreadPool::tryStart(std::function<void()> functionToRun)
int QThreadPool::expiryTimeout() const
{
+ using namespace std::chrono;
Q_D(const QThreadPool);
- return d->expiryTimeout;
+ QMutexLocker locker(&d->mutex);
+ return duration_cast<milliseconds>(d->expiryTimeout).count();
}
void QThreadPool::setExpiryTimeout(int expiryTimeout)
{
Q_D(QThreadPool);
- if (d->expiryTimeout == expiryTimeout)
- return;
- d->expiryTimeout = expiryTimeout;
+ QMutexLocker locker(&d->mutex);
+ d->expiryTimeout = std::chrono::milliseconds(expiryTimeout);
}
/*! \property QThreadPool::maxThreadCount
- This property represents the maximum number of threads used by the thread
- pool.
+ \brief the maximum number of threads used by the thread pool. This property
+ will default to the value of QThread::idealThreadCount() at the moment the
+ QThreadPool object is created.
\note The thread pool will always use at least 1 thread, even if
\a maxThreadCount limit is zero or negative.
@@ -645,7 +621,8 @@ void QThreadPool::setExpiryTimeout(int expiryTimeout)
int QThreadPool::maxThreadCount() const
{
Q_D(const QThreadPool);
- return d->maxThreadCount;
+ QMutexLocker locker(&d->mutex);
+ return d->requestedMaxThreadCount;
}
void QThreadPool::setMaxThreadCount(int maxThreadCount)
@@ -653,16 +630,16 @@ void QThreadPool::setMaxThreadCount(int maxThreadCount)
Q_D(QThreadPool);
QMutexLocker locker(&d->mutex);
- if (maxThreadCount == d->maxThreadCount)
+ if (maxThreadCount == d->requestedMaxThreadCount)
return;
- d->maxThreadCount = maxThreadCount;
+ d->requestedMaxThreadCount = maxThreadCount;
d->tryToStartMoreThreads();
}
/*! \property QThreadPool::activeThreadCount
- This property represents the number of active threads in the thread pool.
+ \brief the number of active threads in the thread pool.
\note It is possible for this function to return a value that is greater
than maxThreadCount(). See reserveThread() for more details.
@@ -683,7 +660,10 @@ int QThreadPool::activeThreadCount() const
Once you are done with the thread, call releaseThread() to allow it to be
reused.
- \note This function will always increase the number of active threads.
+ \note Even if reserving maxThreadCount() threads or more, the thread pool
+ will still allow a minimum of one thread.
+
+ \note This function will increase the reported number of active threads.
This means that by using this function, it is possible for
activeThreadCount() to return a value greater than maxThreadCount() .
@@ -697,9 +677,7 @@ void QThreadPool::reserveThread()
}
/*! \property QThreadPool::stackSize
-
- This property contains the stack size for the thread pool worker
- threads.
+ \brief the stack size for the thread pool worker threads.
The value of the property is only used when the thread pool creates
new threads. Changing it has no effect for already created
@@ -713,15 +691,45 @@ void QThreadPool::reserveThread()
void QThreadPool::setStackSize(uint stackSize)
{
Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
d->stackSize = stackSize;
}
uint QThreadPool::stackSize() const
{
Q_D(const QThreadPool);
+ QMutexLocker locker(&d->mutex);
return d->stackSize;
}
+/*! \property QThreadPool::threadPriority
+ \brief the thread priority for new worker threads.
+
+ The value of the property is only used when the thread pool starts
+ new threads. Changing it has no effect for already running threads.
+
+ The default value is QThread::InheritPriority, which makes QThread
+ use the same priority as the one the QThreadPool object lives in.
+
+ \sa QThread::Priority
+
+ \since 6.2
+*/
+
+void QThreadPool::setThreadPriority(QThread::Priority priority)
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ d->threadPriority = priority;
+}
+
+QThread::Priority QThreadPool::threadPriority() const
+{
+ Q_D(const QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ return d->threadPriority;
+}
+
/*!
Releases a thread previously reserved by a call to reserveThread().
@@ -743,15 +751,75 @@ void QThreadPool::releaseThread()
}
/*!
+ Releases a thread previously reserved with reserveThread() and uses it
+ to run \a runnable.
+
+ Note that the thread pool takes ownership of the \a runnable if
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c true,
+ and the \a runnable will be deleted automatically by the thread
+ pool after the \l{QRunnable::run()}{runnable->run()} returns. If
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c false,
+ ownership of \a runnable remains with the caller. Note that
+ changing the auto-deletion on \a runnable after calling this
+ functions results in undefined behavior.
+
+ \note Calling this when no threads are reserved results in
+ undefined behavior.
+
+ \since 6.3
+ \sa reserveThread(), start()
+*/
+void QThreadPool::startOnReservedThread(QRunnable *runnable)
+{
+ if (!runnable)
+ return releaseThread();
+
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ Q_ASSERT(d->reservedThreads > 0);
+ --d->reservedThreads;
+
+ if (!d->tryStart(runnable)) {
+ // This can only happen if we reserved max threads,
+ // and something took the one minimum thread.
+ d->enqueueTask(runnable, INT_MAX);
+ }
+}
+
+/*!
+ \fn template<typename Callable, QRunnable::if_callable<Callable>> void QThreadPool::startOnReservedThread(Callable &&callableToRun)
+ \overload
+ \since 6.3
+
+ Releases a thread previously reserved with reserveThread() and uses it
+ to run \a callableToRun.
+
+ \note This function participates in overload resolution only if \c Callable
+ is a function or function object which can be called with zero arguments.
+
+ \note In Qt version prior to 6.6, this function took std::function<void()>,
+ and therefore couldn't handle move-only callables.
+*/
+
+/*!
+ \fn bool QThreadPool::waitForDone(int msecs)
Waits up to \a msecs milliseconds for all threads to exit and removes all
threads from the thread pool. Returns \c true if all threads were removed;
- otherwise it returns \c false. If \a msecs is -1 (the default), the timeout
- is ignored (waits for the last thread to exit).
+ otherwise it returns \c false. If \a msecs is -1, this function waits for
+ the last thread to exit.
*/
-bool QThreadPool::waitForDone(int msecs)
+
+/*!
+ \since 6.8
+
+ Waits until \a deadline expires for all threads to exit and removes all
+ threads from the thread pool. Returns \c true if all threads were removed;
+ otherwise it returns \c false.
+*/
+bool QThreadPool::waitForDone(QDeadlineTimer deadline)
{
Q_D(QThreadPool);
- return d->waitForDone(msecs);
+ return d->waitForDone(deadline);
}
/*!
@@ -769,25 +837,18 @@ void QThreadPool::clear()
d->clear();
}
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-/*!
- \internal
-
- Returns \c true if \a thread is a thread managed by this thread pool.
-*/
-#else
/*!
\since 6.0
Returns \c true if \a thread is a thread managed by this thread pool.
*/
-#endif
bool QThreadPool::contains(const QThread *thread) const
{
Q_D(const QThreadPool);
const QThreadPoolThread *poolThread = qobject_cast<const QThreadPoolThread *>(thread);
if (!poolThread)
return false;
+ QMutexLocker locker(&d->mutex);
return d->allThreads.contains(const_cast<QThreadPoolThread *>(poolThread));
}
diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
index 0d143574cf..0640f41587 100644
--- a/src/corelib/thread/qthreadpool.h
+++ b/src/corelib/thread/qthreadpool.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTHREADPOOL_H
#define QTHREADPOOL_H
@@ -45,13 +9,14 @@
#include <QtCore/qthread.h>
#include <QtCore/qrunnable.h>
+#if QT_CORE_REMOVED_SINCE(6, 6)
#include <functional>
+#endif
QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
-
class QThreadPoolPrivate;
class Q_CORE_EXPORT QThreadPool : public QObject
{
@@ -61,6 +26,7 @@ class Q_CORE_EXPORT QThreadPool : public QObject
Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount)
Q_PROPERTY(int activeThreadCount READ activeThreadCount)
Q_PROPERTY(uint stackSize READ stackSize WRITE setStackSize)
+ Q_PROPERTY(QThread::Priority threadPriority READ threadPriority WRITE setThreadPriority)
friend class QFutureInterfaceBase;
public:
@@ -72,8 +38,22 @@ public:
void start(QRunnable *runnable, int priority = 0);
bool tryStart(QRunnable *runnable);
+#if QT_CORE_REMOVED_SINCE(6, 6)
void start(std::function<void()> functionToRun, int priority = 0);
bool tryStart(std::function<void()> functionToRun);
+#endif
+
+ void startOnReservedThread(QRunnable *runnable);
+#if QT_CORE_REMOVED_SINCE(6, 6)
+ void startOnReservedThread(std::function<void()> functionToRun);
+#endif
+
+ template <typename Callable, QRunnable::if_callable<Callable> = true>
+ void start(Callable &&functionToRun, int priority = 0);
+ template <typename Callable, QRunnable::if_callable<Callable> = true>
+ bool tryStart(Callable &&functionToRun);
+ template <typename Callable, QRunnable::if_callable<Callable> = true>
+ void startOnReservedThread(Callable &&functionToRun);
int expiryTimeout() const;
void setExpiryTimeout(int expiryTimeout);
@@ -86,18 +66,52 @@ public:
void setStackSize(uint stackSize);
uint stackSize() const;
+ void setThreadPriority(QThread::Priority priority);
+ QThread::Priority threadPriority() const;
+
void reserveThread();
void releaseThread();
- bool waitForDone(int msecs = -1);
+ QT_CORE_INLINE_SINCE(6, 8)
+ bool waitForDone(int msecs);
+ bool waitForDone(QDeadlineTimer deadline = QDeadlineTimer::Forever);
void clear();
bool contains(const QThread *thread) const;
- Q_REQUIRED_RESULT bool tryTake(QRunnable *runnable);
+ [[nodiscard]] bool tryTake(QRunnable *runnable);
};
+template <typename Callable, QRunnable::if_callable<Callable>>
+void QThreadPool::start(Callable &&functionToRun, int priority)
+{
+ start(QRunnable::create(std::forward<Callable>(functionToRun)), priority);
+}
+
+template <typename Callable, QRunnable::if_callable<Callable>>
+bool QThreadPool::tryStart(Callable &&functionToRun)
+{
+ QRunnable *runnable = QRunnable::create(std::forward<Callable>(functionToRun));
+ if (tryStart(runnable))
+ return true;
+ delete runnable;
+ return false;
+}
+
+template <typename Callable, QRunnable::if_callable<Callable>>
+void QThreadPool::startOnReservedThread(Callable &&functionToRun)
+{
+ startOnReservedThread(QRunnable::create(std::forward<Callable>(functionToRun)));
+}
+
+#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
+bool QThreadPool::waitForDone(int msecs)
+{
+ return waitForDone(QDeadlineTimer(msecs));
+}
+#endif
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index f019b480f5..7910592f70 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTHREADPOOL_P_H
#define QTHREADPOOL_P_H
@@ -55,6 +19,7 @@
#include "QtCore/qmutex.h"
#include "QtCore/qthread.h"
#include "QtCore/qwaitcondition.h"
+#include "QtCore/qthreadpool.h"
#include "QtCore/qset.h"
#include "QtCore/qqueue.h"
#include "private/qobject_p.h"
@@ -65,47 +30,44 @@ QT_BEGIN_NAMESPACE
class QDeadlineTimer;
-class QueuePage {
+class QueuePage
+{
public:
enum {
MaxPageSize = 256
};
- QueuePage(QRunnable *runnable, int pri)
- : m_priority(pri)
- {
- push(runnable);
- }
+ QueuePage(QRunnable *runnable, int pri) : m_priority(pri) { push(runnable); }
- bool isFull() {
- return m_lastIndex >= MaxPageSize - 1;
- }
+ bool isFull() { return m_lastIndex >= MaxPageSize - 1; }
- bool isFinished() {
- return m_firstIndex > m_lastIndex;
- }
+ bool isFinished() { return m_firstIndex > m_lastIndex; }
- void push(QRunnable *runnable) {
+ void push(QRunnable *runnable)
+ {
Q_ASSERT(runnable != nullptr);
Q_ASSERT(!isFull());
m_lastIndex += 1;
m_entries[m_lastIndex] = runnable;
}
- void skipToNextOrEnd() {
+ void skipToNextOrEnd()
+ {
while (!isFinished() && m_entries[m_firstIndex] == nullptr) {
m_firstIndex += 1;
}
}
- QRunnable *first() {
+ QRunnable *first()
+ {
Q_ASSERT(!isFinished());
QRunnable *runnable = m_entries[m_firstIndex];
Q_ASSERT(runnable);
return runnable;
}
- QRunnable *pop() {
+ QRunnable *pop()
+ {
Q_ASSERT(!isFinished());
QRunnable *runnable = first();
Q_ASSERT(runnable);
@@ -120,7 +82,8 @@ public:
return runnable;
}
- bool tryTake(QRunnable *runnable) {
+ bool tryTake(QRunnable *runnable)
+ {
Q_ASSERT(!isFinished());
for (int i = m_firstIndex; i <= m_lastIndex; i++) {
if (m_entries[i] == runnable) {
@@ -135,9 +98,7 @@ public:
return false;
}
- int priority() const {
- return m_priority;
- }
+ int priority() const { return m_priority; }
private:
int m_priority = 0;
@@ -160,28 +121,34 @@ public:
int activeThreadCount() const;
void tryToStartMoreThreads();
+ bool areAllThreadsActive() const;
bool tooManyThreadsActive() const;
+ int maxThreadCount() const
+ { return qMax(requestedMaxThreadCount, 1); } // documentation says we start at least one
void startThread(QRunnable *runnable = nullptr);
void reset();
- bool waitForDone(int msecs);
bool waitForDone(const QDeadlineTimer &timer);
void clear();
void stealAndRunRunnable(QRunnable *runnable);
void deletePageIfFinished(QueuePage *page);
+ static QThreadPool *qtGuiInstance();
+
mutable QMutex mutex;
QSet<QThreadPoolThread *> allThreads;
QQueue<QThreadPoolThread *> waitingThreads;
QQueue<QThreadPoolThread *> expiredThreads;
QList<QueuePage *> queue;
QWaitCondition noActiveThreads;
+ QString objectName;
- int expiryTimeout = 30000;
- int maxThreadCount = QThread::idealThreadCount();
+ std::chrono::duration<int, std::milli> expiryTimeout = std::chrono::seconds(30);
+ int requestedMaxThreadCount = QThread::idealThreadCount(); // don't use this directly
int reservedThreads = 0;
int activeThreads = 0;
uint stackSize = 0;
+ QThread::Priority threadPriority = QThread::InheritPriority;
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 9c9a63d29b..c2029fe1b3 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qthreadstorage.h"
@@ -65,10 +29,10 @@ void qtsDebug(const char *fmt, ...)
va_end(va);
}
#else
-# define DEBUG_MSG if(false)qDebug
+# define DEBUG_MSG if (false)qDebug
#endif
-static QBasicMutex destructorsMutex;
+Q_CONSTINIT static QBasicMutex destructorsMutex;
typedef QList<void (*)(void *)> DestructorMap;
Q_GLOBAL_STATIC(DestructorMap, destructors)
@@ -87,15 +51,15 @@ QThreadStorageData::QThreadStorageData(void (*func)(void *))
no where to store it, and no way to actually call it.
*/
QThreadData *data = QThreadData::current();
- id = data->tls.count();
+ id = data->tls.size();
DEBUG_MSG("QThreadStorageData: Allocated id %d, destructor %p cannot be stored", id, func);
return;
}
- for (id = 0; id < destr->count(); id++) {
- if (destr->at(id) == 0)
+ for (id = 0; id < destr->size(); id++) {
+ if (destr->at(id) == nullptr)
break;
}
- if (id == destr->count()) {
+ if (id == destr->size()) {
destr->append(func);
} else {
(*destr)[id] = func;
@@ -108,7 +72,7 @@ QThreadStorageData::~QThreadStorageData()
DEBUG_MSG("QThreadStorageData: Released id %d", id);
QMutexLocker locker(&destructorsMutex);
if (destructors())
- (*destructors())[id] = 0;
+ (*destructors())[id] = nullptr;
}
void **QThreadStorageData::get() const
@@ -152,7 +116,7 @@ void **QThreadStorageData::set(void *p)
QMutexLocker locker(&destructorsMutex);
DestructorMap *destr = destructors();
- void (*destructor)(void *) = destr ? destr->value(id) : 0;
+ void (*destructor)(void *) = destr ? destr->value(id) : nullptr;
locker.unlock();
void *q = value;
@@ -201,7 +165,7 @@ void QThreadStorageData::finish(void **p)
if (tls->size() > i) {
//re reset the tls in case it has been recreated by its own destructor.
- (*tls)[i] = 0;
+ (*tls)[i] = nullptr;
}
}
tls->clear();
@@ -225,7 +189,7 @@ void QThreadStorageData::finish(void **p)
The hasLocalData() function allows the programmer to determine if
data has previously been set using the setLocalData() function.
- This is also useful for lazy initializiation.
+ This is also useful for lazy initialization.
If T is a pointer type, QThreadStorage takes ownership of the data
(which must be created on the heap with \c new) and deletes it when
diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h
index 9eb8672e92..1a8dacae0f 100644
--- a/src/corelib/thread/qthreadstorage.h
+++ b/src/corelib/thread/qthreadstorage.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTHREADSTORAGE_H
#define QTHREADSTORAGE_H
@@ -158,6 +122,8 @@ QT_END_NAMESPACE
#include <type_traits>
+QT_BEGIN_NAMESPACE
+
template <typename T, typename U>
inline bool qThreadStorage_hasLocalData(const QScopedPointer<T, U> &data)
{
@@ -209,7 +175,7 @@ public:
return qThreadStorage_hasLocalData(data);
}
- inline T& localData()
+ inline T &localData()
{
if (!data)
data.reset(new T());
@@ -227,6 +193,8 @@ public:
}
};
+QT_END_NAMESPACE
+
#endif // QT_CONFIG(thread)
#endif // QTHREADSTORAGE_H
diff --git a/src/corelib/thread/qtsan_impl.h b/src/corelib/thread/qtsan_impl.h
new file mode 100644
index 0000000000..b28d65e65f
--- /dev/null
+++ b/src/corelib/thread/qtsan_impl.h
@@ -0,0 +1,79 @@
+// Copyright (C) 2017 Intel Corporation.
+// Copyright (C) 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTSAN_IMPL_H
+#define QTSAN_IMPL_H
+
+#include <QtCore/qglobal.h>
+
+#if (__has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)) && __has_include(<sanitizer/tsan_interface.h>)
+# define QT_BUILDING_UNDER_TSAN
+# include <sanitizer/tsan_interface.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtTsan {
+#ifdef QT_BUILDING_UNDER_TSAN
+inline void futexAcquire(void *addr, void *addr2 = nullptr)
+{
+ // A futex call ensures total ordering on the futex words
+ // (in either success or failure of the call). Instruct TSAN accordingly,
+ // as TSAN does not understand the futex(2) syscall (or equivalent).
+ ::__tsan_acquire(addr);
+ if (addr2)
+ ::__tsan_acquire(addr2);
+}
+
+inline void futexRelease(void *addr, void *addr2 = nullptr)
+{
+ if (addr2)
+ ::__tsan_release(addr2);
+ ::__tsan_release(addr);
+}
+
+inline void mutexPreLock(void *addr, unsigned flags)
+{
+ ::__tsan_mutex_pre_lock(addr, flags);
+}
+
+inline void mutexPostLock(void *addr, unsigned flags, int recursion)
+{
+ ::__tsan_mutex_post_lock(addr, flags, recursion);
+}
+
+inline void mutexPreUnlock(void *addr, unsigned flags)
+{
+ ::__tsan_mutex_pre_unlock(addr, flags);
+}
+
+inline void mutexPostUnlock(void *addr, unsigned flags)
+{
+ ::__tsan_mutex_post_unlock(addr, flags);
+}
+
+enum : unsigned {
+ MutexWriteReentrant = ::__tsan_mutex_write_reentrant,
+ TryLock = ::__tsan_mutex_try_lock,
+ TryLockFailed = ::__tsan_mutex_try_lock_failed,
+};
+#else
+inline void futexAcquire(void *, void * = nullptr) {}
+inline void futexRelease(void *, void * = nullptr) {}
+
+enum : unsigned {
+ MutexWriteReentrant,
+ TryLock,
+ TryLockFailed,
+};
+inline void mutexPreLock(void *, unsigned) {}
+inline void mutexPostLock(void *, unsigned, int) {}
+inline void mutexPreUnlock(void *, unsigned) {}
+inline void mutexPostUnlock(void *, unsigned) {}
+#endif // QT_BUILDING_UNDER_TSAN
+} // namespace QtTsan
+
+QT_END_NAMESPACE
+
+#endif // QTSAN_IMPL_H
diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h
index 0a47ac3717..8f8270c918 100644
--- a/src/corelib/thread/qwaitcondition.h
+++ b/src/corelib/thread/qwaitcondition.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAITCONDITION_H
#define QWAITCONDITION_H
@@ -73,7 +37,7 @@ public:
private:
Q_DISABLE_COPY(QWaitCondition)
- QWaitConditionPrivate * d;
+ QWaitConditionPrivate *d;
};
#else
diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc
index 014d549477..8466eb13d2 100644
--- a/src/corelib/thread/qwaitcondition.qdoc
+++ b/src/corelib/thread/qwaitcondition.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QWaitCondition
@@ -75,12 +51,12 @@
simultaneously are unpredictable.
Wait conditions are a powerful thread synchronization primitive.
- The \l{Wait Conditions Example} example shows how
- to use QWaitCondition as an alternative to QSemaphore for
- controlling access to a circular buffer shared by a producer
+ The \l{Producer and Consumer using Wait Conditions} example
+ shows how to use QWaitCondition as an alternative to QSemaphore
+ for controlling access to a circular buffer shared by a producer
thread and a consumer thread.
- \sa QMutex, QSemaphore, QThread, {Wait Conditions Example}
+ \sa QMutex, QSemaphore, QThread, {Producer and Consumer using Wait Conditions}
*/
/*!
@@ -122,10 +98,16 @@
/*!
\fn bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time)
\overload
+
+ Releases the \a lockedMutex and waits on the wait condition for \a time
+ milliseconds.
*/
/*!
\fn bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time)
\overload
+
+ Releases the \a lockedReadWriteLock and waits on the wait condition for \a
+ time milliseconds.
*/
/*!
diff --git a/src/corelib/thread/qwaitcondition_p.h b/src/corelib/thread/qwaitcondition_p.h
index 5133e52e92..14833d56ef 100644
--- a/src/corelib/thread/qwaitcondition_p.h
+++ b/src/corelib/thread/qwaitcondition_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWAITCONDITION_P_H
#define QWAITCONDITION_P_H
@@ -43,10 +7,9 @@
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header
-// file may change from version to version without notice, or even be
-// removed.
+// This file is not part of the Qt API. It exists for the convenience of
+// qmutex.cpp and qmutex_unix.cpp. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -54,97 +17,21 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QMutex>
#include <QtCore/QDeadlineTimer>
+#include <QtCore/private/qglobal_p.h>
#include <condition_variable>
#include <mutex>
QT_BEGIN_NAMESPACE
-namespace QtPrivate
-{
-
-#if defined(Q_OS_INTEGRITY)
-
-class condition_variable;
-
-class mutex : private QMutex
-{
- friend class QtPrivate::condition_variable;
-public:
- // all special member functions are ok!
- // do not expose the (QMutex::Recursive) ctor
- // don't use 'using QMutex::lock;' etc as those have the wrong noexcept
-
- void lock() { return QMutex::lock(); }
- void unlock() { return QMutex::unlock(); }
- bool try_lock() { return QMutex::tryLock(); }
-};
-
-class condition_variable : private QWaitCondition
-{
-public:
- // all special member functions are ok!
-
- void notify_one() { QWaitCondition::wakeOne(); }
- void notify_all() { QWaitCondition::wakeAll(); }
-
- void wait(std::unique_lock<QtPrivate::mutex> &lock) { QWaitCondition::wait(lock.mutex()); }
- template <class Predicate>
- void wait(std::unique_lock<QtPrivate::mutex> &lock, Predicate p)
- {
- while (!p())
- wait(lock);
- }
-
- template <typename Rep, typename Period>
- std::cv_status wait_for(std::unique_lock<QtPrivate::mutex> &lock,
- const std::chrono::duration<Rep, Period> &d)
- {
- return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{d})
- ? std::cv_status::no_timeout
- : std::cv_status::timeout;
- }
- template <typename Rep, typename Period, typename Predicate>
- bool wait_for(std::unique_lock<QtPrivate::mutex> &lock,
- const std::chrono::duration<Rep, Period> &d, Predicate p)
- {
- const auto timer = QDeadlineTimer{d};
- while (!p()) {
- if (!QWaitCondition::wait(lock.mutex(), timer))
- return p();
- }
- return true;
- }
-
- template <typename Clock, typename Duration>
- std::cv_status wait_until(std::unique_lock<QtPrivate::mutex> &lock,
- const std::chrono::time_point<Clock, Duration> &t)
- {
- return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{t})
- ? std::cv_status::no_timeout
- : std::cv_status::timeout;
- }
-
- template <typename Clock, typename Duration, typename Predicate>
- bool wait_until(std::unique_lock<QtPrivate::mutex> &lock,
- const std::chrono::time_point<Clock, Duration> &t, Predicate p)
- {
- const auto timer = QDeadlineTimer{t};
- while (!p()) {
- if (!QWaitCondition::wait(lock.mutex(), timer))
- return p();
- }
- return true;
- }
-
-};
-
-#else // Integrity
-
-using mutex = std::mutex;
-using condition_variable = std::condition_variable;
-
-#endif // Integrity
+namespace QtPrivate {
+// Ideal alignment for mutex and condition_variable: it's the hardware
+// interference size (size of a cache line) if the types are likely to contain
+// the actual data structures, otherwise just that of a pointer.
+static constexpr quintptr IdealMutexAlignment =
+ sizeof(std::mutex) > sizeof(void *) &&
+ sizeof(std::condition_variable) > sizeof(void *) ?
+ 64 : alignof(void*);
} // namespace QtPrivate
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index a1c973562b..d841183f09 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -1,55 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qplatformdefs.h"
#include "qwaitcondition.h"
+
+#include "qatomic.h"
+#include "qdeadlinetimer.h"
#include "qmutex.h"
+#include "qplatformdefs.h"
#include "qreadwritelock.h"
-#include "qatomic.h"
#include "qstring.h"
-#include "qdeadlinetimer.h"
-#include "private/qdeadlinetimer_p.h"
-#include "qelapsedtimer.h"
-#include "private/qcore_unix_p.h"
-#include "qmutex_p.h"
+#include "private/qcore_unix_p.h"
#include "qreadwritelock_p.h"
#include <errno.h>
@@ -58,63 +20,65 @@
QT_BEGIN_NAMESPACE
-#ifdef Q_OS_ANDROID
-// pthread_condattr_setclock is available only since Android 5.0. On older versions, there's
-// a private function for relative waits (hidden in 5.0).
-// Use weakref so we can determine at runtime whether each of them is present.
-static int local_condattr_setclock(pthread_condattr_t*, clockid_t)
-__attribute__((weakref("pthread_condattr_setclock")));
-
-static int local_cond_timedwait_relative(pthread_cond_t*, pthread_mutex_t *, const timespec *)
-__attribute__((weakref("__pthread_cond_timedwait_relative")));
+static constexpr clockid_t SteadyClockClockId =
+#if !defined(CLOCK_MONOTONIC)
+ // we don't know how to set the monotonic clock
+ CLOCK_REALTIME
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
+ // libc++ falling back to system_clock
+ CLOCK_REALTIME
+#elif defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_CLOCK_MONOTONIC)
+ // libstdc++ falling back to system_clock
+ CLOCK_REALTIME
+#elif defined(Q_OS_DARWIN)
+ // Darwin lacks pthread_condattr_setclock()
+ CLOCK_REALTIME
+#elif defined(Q_OS_QNX)
+ // unknown why
+ CLOCK_REALTIME
+#elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
+ // both libstdc++ and libc++ do use CLOCK_MONOTONIC
+ CLOCK_MONOTONIC
+#else
+# warning "Unknown C++ Standard Library implementation - code may be sub-optimal"
+ CLOCK_REALTIME
#endif
+ ;
-static void report_error(int code, const char *where, const char *what)
+static void qt_report_pthread_error(int code, const char *where, const char *what)
{
if (code != 0)
qErrnoWarning(code, "%s: %s failure", where, what);
}
-void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
+static void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
{
+ pthread_condattr_t *attrp = nullptr;
+
+#if defined(CLOCK_MONOTONIC) && !defined(Q_OS_DARWIN)
pthread_condattr_t condattr;
+ attrp = &condattr;
pthread_condattr_init(&condattr);
-#if (_POSIX_MONOTONIC_CLOCK-0 >= 0)
-#if defined(Q_OS_ANDROID)
- if (local_condattr_setclock && QElapsedTimer::clockType() == QElapsedTimer::MonotonicClock)
- local_condattr_setclock(&condattr, CLOCK_MONOTONIC);
-#elif !defined(Q_OS_MAC)
- if (QElapsedTimer::clockType() == QElapsedTimer::MonotonicClock)
- pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
+ auto destroy = qScopeGuard([&] { pthread_condattr_destroy(&condattr); });
+ if (SteadyClockClockId != CLOCK_REALTIME)
+ pthread_condattr_setclock(&condattr, SteadyClockClockId);
#endif
-#endif
- report_error(pthread_cond_init(cond, &condattr), where, "cv init");
- pthread_condattr_destroy(&condattr);
+
+ qt_report_pthread_error(pthread_cond_init(cond, attrp), where, "cv init");
}
-void qt_abstime_for_timeout(timespec *ts, QDeadlineTimer deadline)
+static void qt_abstime_for_timeout(timespec *ts, QDeadlineTimer deadline)
{
-#ifdef Q_OS_MAC
- // on Mac, qt_gettime() (on qelapsedtimer_mac.cpp) returns ticks related to the Mach absolute time
- // that doesn't work with pthread
- // Mac also doesn't have clock_gettime
- struct timeval tv;
- qint64 nsec = deadline.remainingTimeNSecs();
- gettimeofday(&tv, 0);
- ts->tv_sec = tv.tv_sec + nsec / (1000 * 1000 * 1000);
- ts->tv_nsec = tv.tv_usec * 1000 + nsec % (1000 * 1000 * 1000);
-
- normalizedTimespec(*ts);
-#else
- // depends on QDeadlineTimer's internals!!
- static_assert(QDeadlineTimerNanosecondsInT2);
- ts->tv_sec = deadline._q_data().first;
- ts->tv_nsec = deadline._q_data().second;
-#endif
+ using namespace std::chrono;
+ using Clock =
+ std::conditional_t<SteadyClockClockId == CLOCK_REALTIME, system_clock, steady_clock>;
+ auto timePoint = deadline.deadline<Clock>();
+ *ts = durationToTimespec(timePoint.time_since_epoch());
}
-class QWaitConditionPrivate {
+class QWaitConditionPrivate
+{
public:
pthread_mutex_t mutex;
pthread_cond_t cond;
@@ -124,14 +88,6 @@ public:
int wait_relative(QDeadlineTimer deadline)
{
timespec ti;
-#ifdef Q_OS_ANDROID
- if (!local_condattr_setclock && local_cond_timedwait_relative) {
- qint64 nsec = deadline.remainingTimeNSecs();
- ti.tv_sec = nsec / (1000 * 1000 * 1000);
- ti.tv_nsec = nsec - ti.tv_sec * 1000 * 1000 * 1000;
- return local_cond_timedwait_relative(&cond, &mutex, &ti);
- }
-#endif
qt_abstime_for_timeout(&ti, deadline);
return pthread_cond_timedwait(&cond, &mutex, &ti);
}
@@ -146,9 +102,7 @@ public:
code = pthread_cond_wait(&cond, &mutex);
}
if (code == 0 && wakeups == 0) {
- // many vendors warn of spurious wakeups from
- // pthread_cond_wait(), especially after signal delivery,
- // even though POSIX doesn't allow for it... sigh
+ // spurious wakeup
continue;
}
break;
@@ -160,46 +114,51 @@ public:
Q_ASSERT_X(wakeups > 0, "QWaitCondition::wait", "internal error (wakeups)");
--wakeups;
}
- report_error(pthread_mutex_unlock(&mutex), "QWaitCondition::wait()", "mutex unlock");
+ qt_report_pthread_error(pthread_mutex_unlock(&mutex), "QWaitCondition::wait()",
+ "mutex unlock");
if (code && code != ETIMEDOUT)
- report_error(code, "QWaitCondition::wait()", "cv wait");
+ qt_report_pthread_error(code, "QWaitCondition::wait()", "cv wait");
return (code == 0);
}
};
-
QWaitCondition::QWaitCondition()
{
d = new QWaitConditionPrivate;
- report_error(pthread_mutex_init(&d->mutex, nullptr), "QWaitCondition", "mutex init");
+ qt_report_pthread_error(pthread_mutex_init(&d->mutex, nullptr), "QWaitCondition", "mutex init");
qt_initialize_pthread_cond(&d->cond, "QWaitCondition");
d->waiters = d->wakeups = 0;
}
-
QWaitCondition::~QWaitCondition()
{
- report_error(pthread_cond_destroy(&d->cond), "QWaitCondition", "cv destroy");
- report_error(pthread_mutex_destroy(&d->mutex), "QWaitCondition", "mutex destroy");
+ qt_report_pthread_error(pthread_cond_destroy(&d->cond), "QWaitCondition", "cv destroy");
+ qt_report_pthread_error(pthread_mutex_destroy(&d->mutex), "QWaitCondition", "mutex destroy");
delete d;
}
void QWaitCondition::wakeOne()
{
- report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeOne()", "mutex lock");
+ qt_report_pthread_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeOne()",
+ "mutex lock");
d->wakeups = qMin(d->wakeups + 1, d->waiters);
- report_error(pthread_cond_signal(&d->cond), "QWaitCondition::wakeOne()", "cv signal");
- report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeOne()", "mutex unlock");
+ qt_report_pthread_error(pthread_cond_signal(&d->cond), "QWaitCondition::wakeOne()",
+ "cv signal");
+ qt_report_pthread_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeOne()",
+ "mutex unlock");
}
void QWaitCondition::wakeAll()
{
- report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeAll()", "mutex lock");
+ qt_report_pthread_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeAll()",
+ "mutex lock");
d->wakeups = d->waiters;
- report_error(pthread_cond_broadcast(&d->cond), "QWaitCondition::wakeAll()", "cv broadcast");
- report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeAll()", "mutex unlock");
+ qt_report_pthread_error(pthread_cond_broadcast(&d->cond), "QWaitCondition::wakeAll()",
+ "cv broadcast");
+ qt_report_pthread_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeAll()",
+ "mutex unlock");
}
bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
@@ -211,14 +170,10 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
{
- if (! mutex)
+ if (!mutex)
return false;
- if (mutex->isRecursive()) {
- qWarning("QWaitCondition: cannot wait on recursive mutexes");
- return false;
- }
- report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
+ qt_report_pthread_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
++d->waiters;
mutex->unlock();
@@ -238,24 +193,26 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
{
+ using namespace QReadWriteLockStates;
+
if (!readWriteLock)
return false;
- auto previousState = readWriteLock->stateForWaitCondition();
- if (previousState == QReadWriteLock::Unlocked)
+ auto previousState = QReadWriteLockPrivate::stateForWaitCondition(readWriteLock);
+ if (previousState == Unlocked)
return false;
- if (previousState == QReadWriteLock::RecursivelyLocked) {
+ if (previousState == RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false;
}
- report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
+ qt_report_pthread_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
++d->waiters;
readWriteLock->unlock();
bool returnValue = d->wait(deadline);
- if (previousState == QReadWriteLock::LockedForWrite)
+ if (previousState == LockedForWrite)
readWriteLock->lockForWrite();
else
readWriteLock->lockForRead();
diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp
index ba34129b7f..ba53309e1b 100644
--- a/src/corelib/thread/qwaitcondition_win.cpp
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwaitcondition.h"
#include "qdeadlinetimer.h"
@@ -45,7 +9,7 @@
#include "qlist.h"
#include "qalgorithms.h"
-#define Q_MUTEX_T void*
+#define Q_MUTEX_T void *
#include <private/qmutex_p.h>
#include <private/qreadwritelock_p.h>
#include <qt_windows.h>
@@ -79,7 +43,7 @@ public:
EventQueue freeQueue;
QWaitConditionEvent *pre();
- bool wait(QWaitConditionEvent *wce, unsigned long time);
+ bool wait(QWaitConditionEvent *wce, QDeadlineTimer deadline);
void post(QWaitConditionEvent *wce, bool ret);
};
@@ -87,7 +51,7 @@ QWaitConditionEvent *QWaitConditionPrivate::pre()
{
mtx.lock();
QWaitConditionEvent *wce =
- freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst();
+ freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst();
wce->priority = GetThreadPriority(GetCurrentThread());
wce->wokenUp = false;
@@ -104,18 +68,25 @@ QWaitConditionEvent *QWaitConditionPrivate::pre()
return wce;
}
-bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time)
+bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, QDeadlineTimer deadline)
{
// wait for the event
- bool ret = false;
- switch (WaitForSingleObjectEx(wce->event, time, FALSE)) {
- default: break;
-
- case WAIT_OBJECT_0:
- ret = true;
- break;
+ while (true) {
+ const DWORD timeout = deadline.isForever()
+ ? INFINITE
+ : DWORD(std::min(deadline.remainingTime(), qint64(INFINITE - 1)));
+
+ switch (WaitForSingleObjectEx(wce->event, timeout, FALSE)) {
+ case WAIT_OBJECT_0:
+ return true;
+ case WAIT_TIMEOUT:
+ if (deadline.hasExpired())
+ return false;
+ break;
+ default:
+ return false;
+ }
}
- return ret;
}
void QWaitConditionPrivate::post(QWaitConditionEvent *wce, bool ret)
@@ -159,17 +130,20 @@ QWaitCondition::~QWaitCondition()
bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
{
+ if (time == std::numeric_limits<unsigned long>::max())
+ return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever));
+ return wait(mutex, QDeadlineTimer(time));
+}
+
+bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
+{
if (!mutex)
return false;
- if (mutex->isRecursive()) {
- qWarning("QWaitCondition::wait: Cannot wait on recursive mutexes");
- return false;
- }
QWaitConditionEvent *wce = d->pre();
mutex->unlock();
- bool returnValue = d->wait(wce, time);
+ bool returnValue = d->wait(wce, deadline);
mutex->lock();
d->post(wce, returnValue);
@@ -177,19 +151,23 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
return returnValue;
}
-bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
- return wait(mutex, deadline.remainingTime());
+ if (time == std::numeric_limits<unsigned long>::max())
+ return wait(readWriteLock, QDeadlineTimer(QDeadlineTimer::Forever));
+ return wait(readWriteLock, QDeadlineTimer(time));
}
-bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
{
+ using namespace QReadWriteLockStates;
+
if (!readWriteLock)
return false;
- auto previousState = readWriteLock->stateForWaitCondition();
- if (previousState == QReadWriteLock::Unlocked)
+ auto previousState = QReadWriteLockPrivate::stateForWaitCondition(readWriteLock);
+ if (previousState == Unlocked)
return false;
- if (previousState == QReadWriteLock::RecursivelyLocked) {
+ if (previousState == RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false;
}
@@ -197,9 +175,9 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
QWaitConditionEvent *wce = d->pre();
readWriteLock->unlock();
- bool returnValue = d->wait(wce, time);
+ bool returnValue = d->wait(wce, deadline);
- if (previousState == QReadWriteLock::LockedForWrite)
+ if (previousState == LockedForWrite)
readWriteLock->lockForWrite();
else
readWriteLock->lockForRead();
@@ -208,16 +186,11 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
return returnValue;
}
-bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
-{
- return wait(readWriteLock, deadline.remainingTime());
-}
-
void QWaitCondition::wakeOne()
{
// wake up the first waiting thread in the queue
QMutexLocker locker(&d->mtx);
- for (QWaitConditionEvent *current : qAsConst(d->queue)) {
+ for (QWaitConditionEvent *current : std::as_const(d->queue)) {
if (current->wokenUp)
continue;
SetEvent(current->event);
@@ -230,7 +203,7 @@ void QWaitCondition::wakeAll()
{
// wake up the all threads in the queue
QMutexLocker locker(&d->mtx);
- for (QWaitConditionEvent *current : qAsConst(d->queue)) {
+ for (QWaitConditionEvent *current : std::as_const(d->queue)) {
SetEvent(current->event);
current->wokenUp = true;
}
diff --git a/src/corelib/thread/qyieldcpu.h b/src/corelib/thread/qyieldcpu.h
new file mode 100644
index 0000000000..d5da58deeb
--- /dev/null
+++ b/src/corelib/thread/qyieldcpu.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QYIELDCPU_H
+#define QYIELDCPU_H
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qprocessordetection.h>
+#include <QtCore/qtconfigmacros.h>
+
+#ifdef Q_CC_MSVC_ONLY
+// MSVC defines _YIELD_PROCESSOR() in <xatomic.h>, but as that is a private
+// header, we include the public ones
+# ifdef __cplusplus
+# include <atomic>
+extern "C"
+# endif
+void _mm_pause(void); // the compiler recognizes as intrinsic
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_CC_GNU
+__attribute__((artificial))
+#endif
+Q_ALWAYS_INLINE void qYieldCpu(void) Q_DECL_NOEXCEPT;
+
+void qYieldCpu(void)
+#ifdef __cplusplus
+ noexcept
+#endif
+{
+#if __has_builtin(__yield)
+ __yield(); // Generic
+#elif defined(_YIELD_PROCESSOR) && defined(Q_CC_MSVC)
+ _YIELD_PROCESSOR(); // Generic; MSVC's <atomic>
+
+#elif __has_builtin(__builtin_ia32_pause)
+ __builtin_ia32_pause();
+#elif defined(Q_PROCESSOR_X86) && defined(Q_CC_GNU)
+ // GCC < 10 didn't have __has_builtin()
+ __builtin_ia32_pause();
+#elif defined(Q_PROCESSOR_X86) && defined(Q_CC_MSVC)
+ _mm_pause();
+#elif defined(Q_PROCESSOR_X86)
+ asm("pause"); // hopefully asm() works in this compiler
+
+#elif __has_builtin(__builtin_arm_yield)
+ __builtin_arm_yield();
+#elif defined(Q_PROCESSOR_ARM) && Q_PROCESSOR_ARM >= 7 && defined(Q_CC_GNU)
+ asm("yield"); // this works everywhere
+
+#elif defined(Q_PROCESSOR_RISCV)
+ asm(".word 0x0100000f"); // a.k.a. "pause"
+
+#elif defined(_YIELD_PROCESSOR) && defined(Q_CC_GHS)
+ _YIELD_PROCESSOR; // Green Hills (INTEGRITY), but only on ARM
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QYIELDCPU_H
diff --git a/src/corelib/thread/qyieldcpu.qdoc b/src/corelib/thread/qyieldcpu.qdoc
new file mode 100644
index 0000000000..c55b2c8a73
--- /dev/null
+++ b/src/corelib/thread/qyieldcpu.qdoc
@@ -0,0 +1,59 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2023 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \fn qYieldCpu()
+ \inmodule QtCore
+ \ingroup thread
+ \relates QAtomicInteger
+ //! \relatesalso QAtomicPointer
+ \since 6.7
+
+ Pauses the execution of the current thread for an unspecified time, using
+ hardware instructions, without de-scheduling this thread. This function is
+ meant to be used in high-throughput loops where the code expects another
+ thread to modify an atomic variable. This is completely different from
+ QThread::yieldCurrentThread(), which is an OS-level operation that may take
+ the whole thread off the CPU and allow other threads (possibly belonging to
+ other processes) to run.
+
+ So, instead of
+ \code
+ while (!condition)
+ ;
+ \endcode
+
+ one should write
+ \code
+ while (!condition)
+ qYieldCpu();
+ \endcode
+
+ This is useful both with and without hardware multithreading on the same
+ core. In the case of hardware threads, it serves to prevent further
+ speculative execution filling up the pipeline, which could starve the
+ sibling thread of resources. Across cores and higher levels of separation,
+ it allows the cache coherency protocol to allocate the cache line being
+ modified and inspected to the logical processor whose result this code is
+ expecting.
+
+ It is also recommended to loop around code that does not modify the global
+ variable, to avoid contention in exclusively obtaining the memory location.
+ Therefore, an atomic modification loop such as a spinlock acquisition
+ should be:
+
+ \code
+ while (true) {
+ while (!readOnlyCondition(atomic))
+ qYieldCpu();
+ if (modify(atomic))
+ break;
+ }
+ \endcode
+
+ On x86 processors and on RISC-V processors with the \c{Zihintpause}
+ extension, this will emit the \c PAUSE instruction, which is ignored on
+ processors that don't support it; on ARMv7 or later ARM processors, it will
+ emit the \c{YIELD} instruction.
+*/
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
deleted file mode 100644
index d36c8011ef..0000000000
--- a/src/corelib/thread/thread.pri
+++ /dev/null
@@ -1,85 +0,0 @@
-# Qt core thread module
-
-HEADERS += \
- thread/qmutex.h \
- thread/qreadwritelock.h \
- thread/qrunnable.h \
- thread/qthread.h \
- thread/qthreadstorage.h \
- thread/qwaitcondition_p.h \
- thread/qwaitcondition.h
-
-SOURCES += \
- thread/qrunnable.cpp \
- thread/qthread.cpp
-
-win32 {
- HEADERS += thread/qatomic_msvc.h
-
- SOURCES += thread/qthread_win.cpp
-} else {
- SOURCES += thread/qthread_unix.cpp
-}
-
-qtConfig(thread) {
- HEADERS += \
- thread/qatomic.h \
- thread/qatomic_bootstrap.h \
- thread/qatomic_cxx11.h \
- thread/qbasicatomic.h \
- thread/qfutex_p.h \
- thread/qgenericatomic.h \
- thread/qlocking_p.h \
- thread/qmutex_p.h \
- thread/qorderedmutexlocker_p.h \
- thread/qreadwritelock_p.h \
- thread/qsemaphore.h \
- thread/qthreadpool.h \
- thread/qthreadpool_p.h \
- thread/qthread_p.h
-
- SOURCES += \
- thread/qatomic.cpp \
- thread/qmutex.cpp \
- thread/qreadwritelock.cpp \
- thread/qsemaphore.cpp \
- thread/qthreadpool.cpp \
- thread/qthreadstorage.cpp
-
- win32 {
- SOURCES += \
- thread/qmutex_win.cpp \
- thread/qwaitcondition_win.cpp
- } else {
- darwin {
- SOURCES += thread/qmutex_mac.cpp
- } else: linux {
- SOURCES += thread/qmutex_linux.cpp
- } else {
- SOURCES += thread/qmutex_unix.cpp
- }
- SOURCES += thread/qwaitcondition_unix.cpp
- }
-}
-
-qtConfig(future) {
- HEADERS += \
- thread/qexception.h \
- thread/qfuture.h \
- thread/qfuture_impl.h \
- thread/qfutureinterface.h \
- thread/qfutureinterface_p.h \
- thread/qfuturesynchronizer.h \
- thread/qfuturewatcher.h \
- thread/qfuturewatcher_p.h \
- thread/qresultstore.h \
- thread/qpromise.h
-
- SOURCES += \
- thread/qexception.cpp \
- thread/qfutureinterface.cpp \
- thread/qfuturewatcher.cpp \
- thread/qresultstore.cpp
-}
-
-qtConfig(std-atomic64): QMAKE_USE += libatomic
diff --git a/src/corelib/time/qcalendar.cpp b/src/corelib/time/qcalendar.cpp
index 7b50eb008c..c87d4b7cf3 100644
--- a/src/corelib/time/qcalendar.cpp
+++ b/src/corelib/time/qcalendar.cpp
@@ -1,31 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcalendar.h"
#include "qcalendarbackend_p.h"
#include "qgregoriancalendar_p.h"
@@ -40,96 +14,423 @@
#include "qislamiccivilcalendar_p.h"
#endif
+#include <private/qflatmap_p.h>
+#include "qatomic.h"
#include "qdatetime.h"
#include "qcalendarmath_p.h"
#include <qhash.h>
-#include <qdebug.h>
+#include <qreadwritelock.h>
-#include <unordered_map>
+#include <vector>
QT_BEGIN_NAMESPACE
-namespace {
-
-struct CalendarName : public QString
+struct QCalendarRegistryCaseInsensitiveAnyStringViewLessThan
{
- CalendarName(const QString &name) : QString(name) {}
+ struct is_transparent {};
+ bool operator()(QAnyStringView lhs, QAnyStringView rhs) const
+ {
+ return QAnyStringView::compare(lhs, rhs, Qt::CaseInsensitive) < 0;
+ }
};
-inline bool operator==(const CalendarName &u, const CalendarName &v)
-{
- return u.compare(v, Qt::CaseInsensitive) == 0;
-}
+namespace QtPrivate {
-inline size_t qHash(const CalendarName &key, size_t seed = 0) noexcept
+/*
+ \internal
+ Handles calendar backend registration.
+*/
+class QCalendarRegistry
{
- return qHash(key.toLower(), seed);
-}
+ Q_DISABLE_COPY_MOVE(QCalendarRegistry); // This is a singleton.
-struct Registry {
+ static constexpr qsizetype ExpectedNumberOfBackends = qsizetype(QCalendar::System::Last) + 1;
+
+ /*
+ Lock protecting the registry from concurrent modification.
+ */
+ QReadWriteLock lock;
+
+ /*
+ Vector containing all registered backends.
+
+ The indices 0 to \c QCalendar::System::Last inclusive are allocated
+ for system backends and always present (but may be null).
+ */
std::vector<QCalendarBackend *> byId;
- QHash<CalendarName, QCalendarBackend *> byName;
- QCalendarBackend *gregorianCalendar = nullptr;
- bool populated = false;
- Registry()
+ /*
+ Backends registered by name.
+
+ Each backend may be registered with several names associated with it.
+ The names are case-insensitive.
+ */
+ QFlatMap<
+ QString, QCalendarBackend *,
+ QCalendarRegistryCaseInsensitiveAnyStringViewLessThan,
+ QStringList,
+ std::vector<QCalendarBackend *>
+ > byName;
+
+ /*
+ Pointer to the Gregorian backend for faster lockless access to it.
+
+ This pointer may be null if the Gregorian backend is not yet registered.
+ This pointer may only be set once and only when write lock is held on
+ the registry.
+ */
+ QAtomicPointer<const QCalendarBackend> gregorianCalendar = nullptr;
+
+ enum : int {
+ Unpopulated, // The standard backends may not yet be created
+ Populated, // All standard backends were created
+ IsBeingDestroyed, // The registry and the backends are being destroyed
+ };
+
+ /*
+ Fast way to check whether the standard calendars were populated.
+
+ The status should only be changed while the write lock is held.
+ */
+ QAtomicInt status = Unpopulated;
+
+ void ensurePopulated();
+ QCalendarBackend *registerSystemBackendLockHeld(QCalendar::System system);
+ void registerBackendLockHeld(QCalendarBackend *backend, const QStringList &names,
+ QCalendar::System system);
+
+public:
+ QCalendarRegistry()
{
- byId.resize(int(QCalendar::System::Last) + 1);
+ byId.resize(ExpectedNumberOfBackends);
+ byName.reserve(ExpectedNumberOfBackends * 2); // assume one alias on average
}
- ~Registry()
+ ~QCalendarRegistry();
+
+ bool isBeingDestroyed() const { return status.loadRelaxed() == IsBeingDestroyed; }
+
+ void registerCustomBackend(QCalendarBackend *backend, const QStringList &names);
+
+ QStringList availableCalendars();
+
+ /*
+ Returns backend for Gregorian calendar.
+
+ The backend is returned without locking the registry if possible.
+ */
+ const QCalendarBackend *gregorian()
{
- qDeleteAll(byId);
+ const QCalendarBackend *backend = gregorianCalendar.loadAcquire();
+ if (Q_LIKELY(backend != nullptr))
+ return backend;
+ return fromEnum(QCalendar::System::Gregorian);
}
- bool registerName(QCalendarBackend *calendar, const QString &name)
+ /*
+ Returns \a true if the argument matches the registered Gregorian backend.
+
+ \a backend should not be \nullptr.
+ */
+ bool isGregorian(const QCalendarBackend *backend) const
{
- if (byName.find(name) != byName.end()) {
- qWarning() << "Calendar name" << name
- << "is already taken, new calendar will not be registered.";
- return false;
- }
- byName.insert(name, calendar);
- return true;
+ return backend == gregorianCalendar.loadRelaxed();
}
- void addCalendar(QCalendarBackend *calendar, const QString &name, QCalendar::System id)
- {
- if (!registerName(calendar, name))
- return;
- Q_ASSERT(byId.size() >= size_t(id));
- if (id == QCalendar::System::User) {
- byId.push_back(calendar);
- } else {
- Q_ASSERT(byId[size_t(id)] == nullptr);
- byId[size_t(id)] = calendar;
+
+ const QCalendarBackend *fromName(QAnyStringView name);
+ const QCalendarBackend *fromIndex(size_t index);
+ const QCalendarBackend *fromEnum(QCalendar::System system);
+
+ QStringList backendNames(const QCalendarBackend *backend);
+};
+
+/*
+ Destroy the registry.
+
+ This destroys all registered backends. This destructor should only be called
+ in a single-threaded context at program exit.
+*/
+QCalendarRegistry::~QCalendarRegistry()
+{
+ QWriteLocker locker(&lock);
+
+ status.storeRelaxed(IsBeingDestroyed);
+
+ qDeleteAll(byId);
+}
+
+/*
+ Registers a custom backend.
+
+ A new unique ID is allocated for the \a backend. The registry takes
+ ownership of the \a backend.
+
+ The \a names of the backend are also registered. Already registered
+ names are not updated.
+
+ The \a backend should not be already registered.
+
+ The \a backend should be fully initialized. It becomes available
+ to other threads before this function returns.
+*/
+void QCalendarRegistry::registerCustomBackend(QCalendarBackend *backend, const QStringList &names)
+{
+ Q_ASSERT(!backend->calendarId().isValid());
+
+ ensurePopulated();
+
+ QWriteLocker locker(&lock);
+ registerBackendLockHeld(backend, names, QCalendar::System::User);
+}
+
+/*
+ Ensures all system calendars have been instantiated.
+
+ This arranges for each system backend to be registered. The method only
+ does anything on its first call, which ensures that name-based lookups can
+ always find all the calendars available via the \c QCalendar::System other
+ than \c QCalendar::System::User.
+*/
+void QCalendarRegistry::ensurePopulated()
+{
+ if (Q_LIKELY(status.loadAcquire() != Unpopulated))
+ return;
+
+ QWriteLocker locker(&lock);
+ if (status.loadAcquire() != Unpopulated)
+ return;
+
+ for (int i = 0; i <= int(QCalendar::System::Last); ++i) {
+ if (byId[i] == nullptr)
+ registerSystemBackendLockHeld(QCalendar::System(i));
+ }
+
+#if defined(QT_FORCE_ASSERTS) || !defined(QT_NO_DEBUG)
+ auto oldValue = status.fetchAndStoreRelease(Populated);
+ Q_ASSERT(oldValue == Unpopulated);
+#else
+ status.storeRelease(Populated);
+#endif
+}
+
+/*
+ Helper functions for system backend registration.
+
+ This function must be called with write lock held on the registry.
+
+ \sa registerSystemBackend
+*/
+QCalendarBackend *QCalendarRegistry::registerSystemBackendLockHeld(QCalendar::System system)
+{
+ Q_ASSERT(system != QCalendar::System::User);
+
+ QCalendarBackend *backend = nullptr;
+ QStringList names;
+
+ switch (system) {
+ case QCalendar::System::Gregorian:
+ backend = new QGregorianCalendar;
+ names = QGregorianCalendar::nameList();
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QCalendar::System::Julian:
+ backend = new QJulianCalendar;
+ names = QJulianCalendar::nameList();
+ break;
+ case QCalendar::System::Milankovic:
+ backend = new QMilankovicCalendar;
+ names = QMilankovicCalendar::nameList();
+ break;
+#endif
+#if QT_CONFIG(jalalicalendar)
+ case QCalendar::System::Jalali:
+ backend = new QJalaliCalendar;
+ names = QJalaliCalendar::nameList();
+ break;
+#endif
+#if QT_CONFIG(islamiccivilcalendar)
+ case QCalendar::System::IslamicCivil:
+ backend = new QIslamicCivilCalendar;
+ names = QIslamicCivilCalendar::nameList();
+ break;
+#else // When highest-numbered system isn't enabled, ensure we have a case for Last:
+ case QCalendar::System::Last:
+#endif
+ case QCalendar::System::User:
+ Q_UNREACHABLE();
+ }
+ if (!backend)
+ return nullptr;
+
+ registerBackendLockHeld(backend, names, system);
+ Q_ASSERT(backend == byId[size_t(system)]);
+
+ return backend;
+}
+
+/*
+ Helper function for backend registration.
+
+ This function must be called with write lock held on the registry.
+
+ \sa registerBackend
+*/
+void QCalendarRegistry::registerBackendLockHeld(QCalendarBackend *backend, const QStringList &names,
+ QCalendar::System system)
+{
+ Q_ASSERT(!backend->calendarId().isValid());
+
+ auto index = size_t(system);
+
+ // Note: it is important to update the calendar ID before making
+ // the calendar available for queries.
+ if (system == QCalendar::System::User) {
+ backend->setIndex(byId.size());
+ byId.push_back(backend);
+ } else if (byId[index] == nullptr) {
+ backend->setIndex(index);
+ if (system == QCalendar::System::Gregorian) {
+#if defined(QT_FORCE_ASSERTS) || !defined(QT_NO_DEBUG)
+ auto oldValue = gregorianCalendar.fetchAndStoreRelease(backend);
+ Q_ASSERT(oldValue == nullptr);
+#else
+ gregorianCalendar.storeRelease(backend);
+#endif
}
- if (id == QCalendar::System::Gregorian) {
- Q_ASSERT(!gregorianCalendar);
- gregorianCalendar = calendar;
+
+ Q_ASSERT(byId.size() > index);
+ Q_ASSERT(byId[index] == nullptr);
+ byId[index] = backend;
+ }
+
+ // Register any names.
+ for (const auto &name : names) {
+ auto [it, inserted] = byName.try_emplace(name, backend);
+ if (!inserted) {
+ Q_ASSERT(system == QCalendar::System::User);
+ qWarning("Cannot register name %ls (already in use) for %ls",
+ qUtf16Printable(name), qUtf16Printable(backend->name()));
}
}
- /*
- \internal
- Ensures each enum-available calendar has been instantiated.
+}
- This arranges for each to register itself by name; it only does anything on
- its first call, which ensures that name-based lookups can always find all
- the calendars available via the enum.
- */
- void populate()
+/*
+ Returns a list of names of the available calendar systems.
+
+ Any QCalendarBackend sub-class must be registered before being exposed to Date
+ and Time APIs.
+
+ \sa fromName()
+*/
+QStringList QCalendarRegistry::availableCalendars()
+{
+ ensurePopulated();
+
+ QReadLocker locker(&lock);
+ return byName.keys();
+}
+
+/*
+ Returns a pointer to a named calendar backend.
+
+ If the given \a name is present in availableCalendars(), the backend
+ matching it is returned. Otherwise, \nullptr is returned. Matching of
+ names ignores case.
+
+ \sa availableCalendars(), fromEnum(), fromIndex()
+*/
+const QCalendarBackend *QCalendarRegistry::fromName(QAnyStringView name)
+{
+ ensurePopulated();
+
+ QReadLocker locker(&lock);
+ return byName.value(name, nullptr);
+}
+
+/*
+ Returns a pointer to a calendar backend, specified by index.
+
+ If a calendar with ID \a index is known to the calendar registry, the backend
+ with this ID is returned. Otherwise, \nullptr is returned.
+
+ \sa fromEnum(), calendarId()
+*/
+const QCalendarBackend *QCalendarRegistry::fromIndex(size_t index)
+{
{
- if (populated)
- return;
+ QReadLocker locker(&lock);
+
+ if (index >= byId.size())
+ return nullptr;
- for (int i = 0; i <= int(QCalendar::System::Last); ++i)
- (void)QCalendar(QCalendar::System(i));
+ if (auto backend = byId[index])
+ return backend;
}
-};
+ if (index <= size_t(QCalendar::System::Last))
+ return fromEnum(QCalendar::System(index));
+
+ return nullptr;
}
-Q_GLOBAL_STATIC(Registry, calendarRegistry);
+/*
+ Returns a pointer to a calendar backend, specified by \a system.
+
+ This will instantiate the indicated calendar (which will enable fromName()
+ to return it subsequently), but only for the Qt-supported calendars for
+ which (where relevant) the appropriate feature has been enabled.
+ \a system should be a member of \a QCalendar::System other than
+ \a QCalendar::System::User.
+
+ \sa fromName(), fromId()
+*/
+const QCalendarBackend *QCalendarRegistry::fromEnum(QCalendar::System system)
+{
+ Q_ASSERT(system <= QCalendar::System::Last);
+ auto index = size_t(system);
+
+ {
+ QReadLocker locker(&lock);
+ Q_ASSERT(byId.size() > index);
+ if (auto backend = byId[index])
+ return backend;
+ }
+
+ QWriteLocker locker(&lock);
+
+ // Check if the backend was registered after releasing the read lock above.
+ if (auto backend = byId[index])
+ return backend;
+
+ return registerSystemBackendLockHeld(system);
+}
+
+/*
+ Returns a list of names \a backend was registered with.
+*/
+QStringList QCalendarRegistry::backendNames(const QCalendarBackend *backend)
+{
+ QStringList l;
+ l.reserve(byName.size()); // too large, but never really large, so ok
+
+ QT_WARNING_PUSH
+ // Clang complains about the reference still causing a copy. The reference is idiomatic, but
+ // runs afoul of QFlatMap's iterators which return a pair of references instead of a reference
+ // to pair. Suppress the warning, because `const auto [key, value]` would look wrong.
+ QT_WARNING_DISABLE_CLANG("-Wrange-loop-analysis")
+ for (const auto &[key, value] : byName) {
+ if (value == backend)
+ l.push_back(key);
+ }
+ QT_WARNING_POP
+
+ return l;
+}
+
+} // namespace QtPrivate
+
+Q_GLOBAL_STATIC(QtPrivate::QCalendarRegistry, calendarRegistry);
/*!
\since 5.14
@@ -141,70 +442,198 @@ Q_GLOBAL_STATIC(Registry, calendarRegistry);
\brief The QCalendarBackend class provides basic calendaring functions.
QCalendarBackend provides the base class on which all calendar types are
- implemented. On construction, the backend is registered with its primary
- name.
+ implemented. The backend must be registered before it is available via
+ QCalendar API. The registration for system backends is arranged by
+ the calendar registry. Custom backends may be registered using the
+ \c registerCustomBackend() method.
+
+ A backend may also be registered by one or more names. Registering with the
+ name used by CLDR (the Unicode consortium's Common Locale Data Repository)
+ is recommended, particularly when interacting with third-party software.
+ Once a backend is registered for a name, QCalendar can be constructed using
+ that name to select the backend.
- A backend may also be registered with aliases, where the calendar is known
- by several names. Registering with the name used by CLDR (the Unicode
- consortium's Common Locale Data Repository) is recommended, particularly
- when interacting with third-party software. Once a backend is registered for
- a name, QCalendar can be constructed using that name to select the backend.
+ Each built-in backend has a distinct primary name and all built-in backends
+ are instantiated before any custom backend is registered, to prevent custom
+ backends with conflicting names from replacing built-in backends.
Each calendar backend must inherit from QCalendarBackend and implement its
pure virtual methods. It may also override some other virtual methods, as
needed.
- Most backends are pure code, with no data elements. Such backends should
- normally be implemented as singletons. For a backend to be added to the
- QCalendar::System enum, it should be such a singleton, with a case in
- QCalendar::fromEnum()'s switch statement to instantiate it.
+ Most backends are pure code, with only one data element (this base-classe's
+ \c m_id). Such backends should normally be implemented as singletons.
+
+ The backends may be used by multiple threads simultaneously. The virtual
+ methods must be implemented in a \l {thread-safe} way.
+
+ \section1 Instantiating backends
+
+ Backends may be defined by third-party, plugin or user code. When such
+ custom backends are registered they shall be allocated a unique ID, by
+ which client code may access it. A custom backend instance can have no names
+ if access by name is not needed, or impractical (e.g. because the backend
+ is not a singleton and constructing names for each instance would not make
+ sense). If a custom backend has names that are already registered for
+ another backend, those names are ignored.
+
+ A backend class that has instance variables as well as code may be
+ instantiated many times, each with a distinct set of names, to implement
+ distinct backends - presumably variants on some parameterized calendar.
+ Each instance is then a distinct backend. A pure code backend class shall
+ typically only be instantiated once, as it is only capable of representing
+ one backend.
+
+ Each backend should be instantiated exactly once, on the heap (using the C++
+ \c new operator), so that the registry can take ownership of it after
+ registration.
+
+ Built-in backends, identified by \c QCalendar::System values other than
+ \c{User}, should only be registered by \c{QCalendarRegistry::fromEnum()};
+ no other code should ever register one, this guarantees that such a backend
+ will be a singleton.
+
+ The shareable base-classes for backends, QRomanCalendar and QHijriCalendar,
+ are not themselves identified by QCalendar::System and may be used as
+ base-classes for custom calendar backends, but cannot be instantiated
+ themselves.
+
+ \sa calendarId(), QDate, QDateTime, QDateEdit, QDateTimeEdit,
+ QCalendarWidget, {The Low-Level API: Extending Qt Applications}
+*/
- Non-singleton calendar backends should ensure that each instance is created
- with a distinct primary name. Later instances attempting to register with a
- name already in use shall fail to register and be unavailable to QCalendar,
- hence unusable.
+/*!
+ Destroys the calendar backend.
- \sa registerAlias(), QDate, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
+ Each calendar backend, once instantiated and successfully registered by ID,
+ shall exist until it is destroyed by the registry. Destroying a
+ successfully-registered backend otherwise may leave existing QCalendar
+ instances referencing the destroyed calendar, with undefined results.
+
+ If a backend has not been registered it may safely be deleted.
+
+ \sa calendarId()
*/
+QCalendarBackend::~QCalendarBackend()
+{
+ Q_ASSERT(!m_id.isValid() || calendarRegistry.isDestroyed()
+ || calendarRegistry->isBeingDestroyed());
+}
/*!
- Constructs the calendar and registers it under \a name using \a id.
+ \fn QString QCalendarBackend::name() const
+ Returns the primary name of the calendar.
+ */
+
+/*!
+ Returns list of names this backend was registered with.
+
+ The list is a subset of the names passed to \c registerCustomBackend().
+ Some names passed during the registration may not be associated
+ with a backend if they were claimed by another backend first.
+
+ \sa registerCustomBackend()
*/
-QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System id)
+QStringList QCalendarBackend::names() const
{
- calendarRegistry->addCalendar(this, name, id);
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
+ return {};
+
+ return calendarRegistry->backendNames(this);
}
/*!
- Destroys the calendar.
+ Set the internal index of the backed to the specified value.
+
+ This method exists to allow QCalendarRegistry to update the backend ID
+ after registration without exposing it in public API for QCalendar.
+ */
+void QCalendarBackend::setIndex(size_t index)
+{
+ Q_ASSERT(!m_id.isValid());
+ m_id.id = index;
+}
- Never call this from user code. Each calendar backend, once instantiated,
- shall exist for the lifetime of the program. Its destruction is taken care
- of by destruction of the registry of calendar backends and their names.
+/*!
+ Register this backend as a custom backend.
+
+ The backend should not already be registered. This method should only be
+ called on objects that are completely initialized because they become
+ available to other threads immediately. In particular, this function should
+ not be called from backend constructors.
+
+ The backend is also registered by names passed in \a names. Only the names
+ that are not already registered are associated with the backend. The name
+ matching is case-insensitive. The list of names associated with the backend
+ can be queried using \c names() method after successful registration.
+
+ Returns the new ID assigned to this backend. If its isValid() is \c true,
+ the calendar registry has taken ownership of the object; this ID can then
+ be used to create \c QCalendar instances. Otherwise, registration failed
+ and the caller is responsible for destruction of the backend, which shall
+ not be available for use by \c QCalendar. Failure should normally only
+ happen if registration is attempted during program termination.
+
+ \sa names()
*/
-QCalendarBackend::~QCalendarBackend()
+QCalendar::SystemId QCalendarBackend::registerCustomBackend(const QStringList &names)
+{
+ Q_ASSERT(!m_id.isValid());
+
+ if (Q_LIKELY(!calendarRegistry.isDestroyed()))
+ calendarRegistry->registerCustomBackend(this, names);
+
+ return m_id;
+}
+
+bool QCalendarBackend::isGregorian() const
{
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
+ return false;
+
+ return calendarRegistry->isGregorian(this);
}
/*!
- The calendar system of this calendar.
+ \since 6.2
+ \fn QCalendar::SystemId QCalendarBackend::calendarId() const
+
+ Each backend is allocated an ID when successfully registered. A backend whose
+ calendarId() has isValid() \c{false} has not been registered; it also cannot
+ be used, as it is not known to any of the available ways to create a QCalendar.
- Each calendar backend constructible from the QCalendar::System enum should
- return the member of that enum that produces it. Other calendars should
- return User.
+ \sa calendarSystem(), fromId()
+*/
- \sa QCalendarBackend::fromEnum()
+/*!
+ The calendar system of this calendar.
+
+ \sa fromEnum(), calendarId()
*/
QCalendar::System QCalendarBackend::calendarSystem() const
{
- return QCalendar::System::User;
+ return m_id.isInEnum() ? QCalendar::System(m_id.index()) : QCalendar::System::User;
}
+/*
+ Create local variable d containing the backend associated with a QCalendar
+ instance unless the calendar registry is destroyed together with all backends,
+ then return nullptr.
+
+ This assumes that the registry is only destroyed in single threaded context.
+*/
+#define SAFE_D() const auto d = Q_UNLIKELY(calendarRegistry.isDestroyed()) ? nullptr : d_ptr
+
/*!
The primary name of this calendar.
- */
+
+ The calendar may also be known by some aliases. A calendar instantiated by
+ name may use such an alias, in which case its name() need not match the
+ alias by which it was instantiated.
+*/
QString QCalendar::name() const
{
+ SAFE_D();
return d ? d->name() : QString();
}
@@ -424,18 +853,73 @@ int QCalendarBackend::maximumMonthsInYear() const
already used in QDate::dayOfWeek() to mean an invalid date). The calendar
should treat the numbers used as an \c enum, whose values need not be
contiguous, nor need they follow closely from the 1 through 7 of the usual
- returns. It suffices that weekDayName() can recognize each such number as
- identifying a distinct name, that it returns to identify the particular
- intercallary day.
+ returns. It suffices that;
+ \list
+ \li weekDayName() can recognize each such number as identifying a distinct
+ name, that it returns to identify the particular intercallary day; and
+ \li matchCenturyToWeekday() can determine what century adjustment aligns a
+ given date within a century to a given day of the week, where this is
+ relevant and possible.
+ \endlist
This base implementation uses the day-numbering that various calendars have
borrowed off the Hebrew calendar.
- \sa weekDayName(), standaloneWeekDayName(), QDate::dayOfWeek()
- */
+ \sa weekDayName(), standaloneWeekDayName(), QDate::dayOfWeek(), Qt::DayOfWeek
+*/
int QCalendarBackend::dayOfWeek(qint64 jd) const
{
- return QRoundingDown::qMod(jd, 7) + 1;
+ return QRoundingDown::qMod<7>(jd) + 1;
+}
+
+/*!
+ \since 6.7
+ Adjusts century of \a parts to match \a dow.
+
+ Preserves parts.month and parts.day while adjusting parts.year by a multiple
+ of 100 (taking the absence of year zero into account, when relevant) to
+ obtain a date for which dayOfWeek() is \a dow. Prefers smaller changes over
+ larger and increases to the century over decreases of the same
+ magnitude. Returns the Julian Day number for the selected date or
+ std::numeric_limits<qint64>::min(), a.k.a. QDate::nullJd(), if there is no
+ date matching these requirements.
+
+ The base-class provides a brute-force implementation that steps outwards
+ from the given date by centures, above and below by up to 14 centuries, in
+ search of a matching date. This is neither computationally efficient nor
+ elegant but should work as advertised for calendars in which every month-day
+ combination does appear on all days of the week, across sufficiently many
+ centuries.
+*/
+qint64 QCalendarBackend::matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const
+{
+ Q_ASSERT(parts.isValid());
+ // Brute-force solution as fall-back.
+ const auto checkOffset = [parts, dow, this](int centuries) -> std::optional<qint64> {
+ // Offset parts.year by the given number of centuries:
+ int year = parts.year + centuries * 100;
+ // but take into account the effect of crossing zero, if we did:
+ if (!hasYearZero() && (parts.year > 0) != (year > 0))
+ year += parts.year > 0 ? -1 : +1;
+ qint64 jd;
+ if (isDateValid(year, parts.month, parts.day)
+ && dateToJulianDay(year, parts.month, parts.day, &jd)
+ && dayOfWeek(jd) == dow) {
+ return jd;
+ }
+ return std::nullopt;
+ };
+ // Empirically, aside from Gregorian, each calendar finds every dow within
+ // any 29-century run, so 14 centuries is the biggest offset we ever need.
+ for (int offset = 0; offset < 15; ++offset) {
+ if (auto jd = checkOffset(offset))
+ return *jd;
+ if (offset) {
+ if (auto jd = checkOffset(-offset))
+ return *jd;
+ }
+ }
+ return (std::numeric_limits<qint64>::min)();
}
// Month and week-day name look-ups (implemented in qlocale.cpp):
@@ -546,103 +1030,81 @@ int QCalendarBackend::dayOfWeek(qint64 jd) const
QCalendarBackend sub-class must be registered before being exposed to Date
and Time APIs.
- \sa registerAlias(), fromName()
+ \sa fromName()
*/
QStringList QCalendarBackend::availableCalendars()
{
- if (calendarRegistry.isDestroyed())
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
return {};
- calendarRegistry->populate();
- return QStringList(calendarRegistry->byName.keyBegin(), calendarRegistry->byName.keyEnd());
-}
-
-/*!
- Registers an alias for this calendar backend. Once a backend is registered,
- its name will be included in the list of available calendars and the
- calendar can be instantiated by name.
- Returns \c false if the given \a name is already in use, otherwise it
- registers this calendar backend and returns \c true.
-
- \sa availableCalendars(), fromName()
-*/
-bool QCalendarBackend::registerAlias(const QString &name)
-{
- if (calendarRegistry.isDestroyed())
- return false;
- return calendarRegistry->registerName(this, name);
+ return calendarRegistry->availableCalendars();
}
/*!
+ \internal
Returns a pointer to a named calendar backend.
If the given \a name is present in availableCalendars(), the backend
- matching it is returned; otherwise, \c nullptr is returned. Matching of
- names ignores case. Note that this won't provoke construction of a calendar
- backend, it will only return ones that have been instantiated (and not yet
- destroyed) by some other means. However, calendars available via the
- QCalendar::System enum are always registered when this is called.
+ matching it is returned; otherwise, \nullptr is returned. Matching of
+ names ignores case.
- \sa availableCalendars(), registerAlias(), fromEnum()
+ \sa availableCalendars(), fromEnum(), fromId()
*/
-const QCalendarBackend *QCalendarBackend::fromName(QStringView name)
+const QCalendarBackend *QCalendarBackend::fromName(QAnyStringView name)
{
- if (calendarRegistry.isDestroyed())
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
return nullptr;
- calendarRegistry->populate();
- auto it = calendarRegistry->byName.find(name.toString());
- return it == calendarRegistry->byName.end() ? nullptr : *it;
+
+ return calendarRegistry->fromName(name);
}
/*!
- \overload
- */
-const QCalendarBackend *QCalendarBackend::fromName(QLatin1String name)
+ \internal
+ Returns a pointer to a calendar backend, specified by ID.
+
+ If a calendar with ID \a id is known to the calendar registry, the backend
+ with this ID is returned; otherwise, \nullptr is returned.
+
+ \sa fromEnum(), calendarId()
+*/
+const QCalendarBackend *QCalendarBackend::fromId(QCalendar::SystemId id)
{
- if (calendarRegistry.isDestroyed())
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed() || !id.isValid()))
return nullptr;
- calendarRegistry->populate();
- auto it = calendarRegistry->byName.find(QString(name));
- return it == calendarRegistry->byName.end() ? nullptr : *it;
+
+ return calendarRegistry->fromIndex(id.index());
}
/*!
- Returns a pointer to a calendar backend, specified by enum.
+ \internal
+ Returns a pointer to a calendar backend, specified by \c enum.
This will instantiate the indicated calendar (which will enable fromName()
to return it subsequently), but only for the Qt-supported calendars for
which (where relevant) the appropriate feature has been enabled.
+
+ \sa fromName(), fromId()
*/
const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
{
- if (calendarRegistry.isDestroyed() || system == QCalendar::System::User)
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed() || system == QCalendar::System::User))
return nullptr;
- Q_ASSERT(calendarRegistry->byId.size() >= size_t(system));
- if (auto *c = calendarRegistry->byId[size_t(system)])
- return c;
- switch (system) {
- case QCalendar::System::Gregorian:
- return new QGregorianCalendar;
-#ifndef QT_BOOTSTRAPPED
- case QCalendar::System::Julian:
- return new QJulianCalendar;
- case QCalendar::System::Milankovic:
- return new QMilankovicCalendar;
-#endif
-#if QT_CONFIG(jalalicalendar)
- case QCalendar::System::Jalali:
- return new QJalaliCalendar;
-#endif
-#if QT_CONFIG(islamiccivilcalendar)
- case QCalendar::System::IslamicCivil:
- return new QIslamicCivilCalendar;
-#else // When highest-numbered system isn't enabled, ensure we have a case for Last:
- case QCalendar::System::Last:
-#endif
- case QCalendar::System::User:
- Q_UNREACHABLE();
- }
- return nullptr;
+
+ return calendarRegistry->fromEnum(system);
+}
+
+/*!
+ \internal
+ Returns backend for Gregorian calendar.
+
+ The backend is returned without locking the registry if possible.
+*/
+const QCalendarBackend *QCalendarBackend::gregorian()
+{
+ if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
+ return nullptr;
+
+ return calendarRegistry->gregorian();
}
/*!
@@ -664,7 +1126,8 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
calendars may be constructed by name, once they have been constructed. (Thus
plugins instantiate their calendar backend to register it.) Built-in
backends, accessible via QCalendar::System, are also always available by
- name.
+ name. Calendars using custom backends may also be constructed using a unique
+ ID allocated to the backend on construction.
A QCalendar value is immutable.
@@ -677,51 +1140,108 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
This enumerated type is used to specify a choice of calendar system.
\value Gregorian The default calendar, used internationally.
- \value Julian An ancient Roman calendar with too few leap years.
+ \value Julian An ancient Roman calendar.
\value Milankovic A revised Julian calendar used by some Orthodox churches.
\value Jalali The Solar Hijri calendar (also called Persian).
\value IslamicCivil The (tabular) Islamic Civil calendar.
\omitvalue Last
\omitvalue User
+ \sa QCalendar, QCalendar::SystemId
+*/
+
+/*!
+ \class QCalendar::SystemId
+ \inmodule QtCore
+ \since 6.2
+
+ This is an opaque type used to identify custom calendar implementations. The
+ only supported source for values of this type is the backend's \c
+ calendarId() method. A value of this type whose isValid() is false does not
+ identify a successfully-registered backend. The only valid consumer of
+ values of this type is a QCalendar constructor, which will only produce a
+ valid QCalendar instance if the ID passed to it is valid.
+
+ \sa QCalendar, QCalendar::System
+*/
+
+/*!
+ \fn QCalendar::SystemId::isValid() const
+
+ Returns \c true if this is a valid calendar implementation identifier,
+ \c false otherwise.
+
\sa QCalendar
*/
/*!
+ \internal
+ \fn QCalendar::SystemId::SystemId()
+
+ Constructs an invalid calendar system identifier.
+*/
+
+/*!
+ \internal
+ \fn QCalendar::SystemId::index()
+
+ Returns the internal representation of the identifier.
+*/
+
+/*!
\fn QCalendar::QCalendar()
\fn QCalendar::QCalendar(QCalendar::System system)
- \fn QCalendar::QCalendar(QLatin1String name)
- \fn QCalendar::QCalendar(QStringView name)
+ \fn QCalendar::QCalendar(QAnyStringView name)
Constructs a calendar object.
- The choice of calendar to use may be indicated as \a system, using the
+ The choice of calendar to use may be indicated by \a system, using the
enumeration QCalendar::System, or by \a name, using a string (either Unicode
or Latin 1). Construction by name may depend on an instance of the given
calendar being constructed by other means first. With no argument, the
default constructor returns the Gregorian calendar.
+ \note In Qt versions before 6.4, the constructor by \a name accepted only
+ QStringView and QLatin1String, not QAnyStringView.
+
\sa QCalendar, System, isValid()
*/
QCalendar::QCalendar()
- : d(nullptr)
+ : d_ptr(QCalendarBackend::gregorian())
{
- if (calendarRegistry.isDestroyed())
- return;
- d = calendarRegistry->gregorianCalendar;
- if (!d)
- d = new QGregorianCalendar;
+ Q_ASSERT(!d_ptr || d_ptr->calendarId().isValid());
}
-QCalendar::QCalendar(QCalendar::System system)
- : d(QCalendarBackend::fromEnum(system)) {}
+QCalendar::QCalendar(QCalendar::System system) : d_ptr(QCalendarBackend::fromEnum(system))
+{
+ // If system is valid, we should get a valid d for that system.
+ Q_ASSERT(!d_ptr || (uint(system) > uint(QCalendar::System::Last))
+ || (d_ptr->calendarId().index() == size_t(system)));
+}
-QCalendar::QCalendar(QLatin1String name)
- : d(QCalendarBackend::fromName(name)) {}
+/*!
+ \overload
+ \since 6.2
-QCalendar::QCalendar(QStringView name)
- : d(QCalendarBackend::fromName(name)) {}
+ Constructs a calendar object.
+
+ When using a custom calendar implementation, its backend is allocated a unique
+ ID when created; passing that as \a id to this constructor will get a
+ QCalendar using that backend. This can be useful when the backend is not
+ registered by name.
+*/
+QCalendar::QCalendar(QCalendar::SystemId id)
+ : d_ptr(QCalendarBackend::fromId(id))
+{
+ Q_ASSERT(!d_ptr || d_ptr->calendarId().index() == id.index());
+}
+
+QCalendar::QCalendar(QAnyStringView name)
+ : d_ptr(QCalendarBackend::fromName(name))
+{
+ Q_ASSERT(!d_ptr || d_ptr->calendarId().isValid());
+}
/*!
\fn bool QCalendar::isValid() const
@@ -745,6 +1265,7 @@ QCalendar::QCalendar(QStringView name)
*/
int QCalendar::daysInMonth(int month, int year) const
{
+ SAFE_D();
return d ? d->daysInMonth(month, year) : 0;
}
@@ -755,6 +1276,7 @@ int QCalendar::daysInMonth(int month, int year) const
*/
int QCalendar::daysInYear(int year) const
{
+ SAFE_D();
return d ? d->daysInYear(year) : 0;
}
@@ -768,6 +1290,7 @@ int QCalendar::daysInYear(int year) const
*/
int QCalendar::monthsInYear(int year) const
{
+ SAFE_D();
return d ? year == Unspecified ? d->maximumMonthsInYear() : d->monthsInYear(year) : 0;
}
@@ -781,6 +1304,7 @@ int QCalendar::monthsInYear(int year) const
*/
bool QCalendar::isDateValid(int year, int month, int day) const
{
+ SAFE_D();
return d && d->isDateValid(year, month, day);
}
@@ -792,8 +1316,8 @@ bool QCalendar::isDateValid(int year, int month, int day) const
*/
bool QCalendar::isGregorian() const
{
- Q_ASSERT(!calendarRegistry.isDestroyed());
- return d == calendarRegistry->gregorianCalendar;
+ SAFE_D();
+ return d && d->isGregorian();
}
/*!
@@ -807,6 +1331,7 @@ bool QCalendar::isGregorian() const
*/
bool QCalendar::isLeapYear(int year) const
{
+ SAFE_D();
return d && d->isLeapYear(year);
}
@@ -817,6 +1342,7 @@ bool QCalendar::isLeapYear(int year) const
*/
bool QCalendar::isLunar() const
{
+ SAFE_D();
return d && d->isLunar();
}
@@ -829,6 +1355,7 @@ bool QCalendar::isLunar() const
*/
bool QCalendar::isLuniSolar() const
{
+ SAFE_D();
return d && d->isLuniSolar();
}
@@ -840,6 +1367,7 @@ bool QCalendar::isLuniSolar() const
*/
bool QCalendar::isSolar() const
{
+ SAFE_D();
return d && d->isSolar();
}
@@ -854,6 +1382,7 @@ bool QCalendar::isSolar() const
*/
bool QCalendar::isProleptic() const
{
+ SAFE_D();
return d && d->isProleptic();
}
@@ -884,6 +1413,7 @@ bool QCalendar::isProleptic() const
*/
bool QCalendar::hasYearZero() const
{
+ SAFE_D();
return d && d->hasYearZero();
}
@@ -894,6 +1424,7 @@ bool QCalendar::hasYearZero() const
*/
int QCalendar::maximumDaysInMonth() const
{
+ SAFE_D();
return d ? d->maximumDaysInMonth() : 0;
}
@@ -904,6 +1435,7 @@ int QCalendar::maximumDaysInMonth() const
*/
int QCalendar::minimumDaysInMonth() const
{
+ SAFE_D();
return d ? d->minimumDaysInMonth() : 0;
}
@@ -914,6 +1446,7 @@ int QCalendar::minimumDaysInMonth() const
*/
int QCalendar::maximumMonthsInYear() const
{
+ SAFE_D();
return d ? d->maximumMonthsInYear() : 0;
}
@@ -935,6 +1468,7 @@ int QCalendar::maximumMonthsInYear() const
*/
QDate QCalendar::dateFromParts(int year, int month, int day) const
{
+ SAFE_D();
qint64 jd;
return d && d->dateToJulianDay(year, month, day, &jd)
? QDate::fromJulianDay(jd) : QDate();
@@ -946,6 +1480,32 @@ QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
}
/*!
+ \since 6.7
+ Adjusts the century of a date to match a given day of the week.
+
+ For use when given a date's day of week, day of month, month and last two
+ digits of the year. Returns a QDate instance with the given \a dow as its \l
+ {QDate::}{dayOfWeek()}, matching the given \a parts in month and day of the
+ month. The returned QDate's \l {QDate::}{year()} shall differ from
+ \c{parts.year} by a multiple of 100, preferring small multiples over larger
+ and positive multiples over their negations.
+
+ If no date matches these conditions, an invalid QDate is returned: the day
+ of week is incompatible with the other data given. This arises, for example,
+ with the Gregorian calendar, whose 400-year cycle is a whole number of weeks
+ long, so any given month and day of that month only ever falls, in years
+ with a given last two digits, on four days of the week. (In the special case
+ of February 29th at the turn of a century, when that is a leap year, only
+ one day of the week is possible: Tuesday.)
+*/
+QDate QCalendar::matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const
+{
+ SAFE_D();
+ return d && parts.isValid()
+ ? QDate::fromJulianDay(d->matchCenturyToWeekday(parts, dow)) : QDate();
+}
+
+/*!
Converts a QDate to a year, month, and day of the month.
The returned structure's isValid() shall be false if the calendar is unable
@@ -956,7 +1516,8 @@ QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
*/
QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
{
- return d ? d->julianDayToDate(date.toJulianDay()) : YearMonthDay();
+ SAFE_D();
+ return d && date.isValid() ? d->julianDayToDate(date.toJulianDay()) : YearMonthDay();
}
/*!
@@ -970,7 +1531,8 @@ QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
*/
int QCalendar::dayOfWeek(QDate date) const
{
- return d ? d->dayOfWeek(date.toJulianDay()) : 0;
+ SAFE_D();
+ return d && date.isValid() ? d->dayOfWeek(date.toJulianDay()) : 0;
}
// Locale data access
@@ -997,6 +1559,7 @@ int QCalendar::dayOfWeek(QDate date) const
QString QCalendar::monthName(const QLocale &locale, int month, int year,
QLocale::FormatType format) const
{
+ SAFE_D();
const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
if (!d || month < 1 || month > maxMonth)
return QString();
@@ -1026,6 +1589,7 @@ QString QCalendar::monthName(const QLocale &locale, int month, int year,
QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
QLocale::FormatType format) const
{
+ SAFE_D();
const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
if (!d || month < 1 || month > maxMonth)
return QString();
@@ -1050,6 +1614,7 @@ QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int yea
QString QCalendar::weekDayName(const QLocale &locale, int day,
QLocale::FormatType format) const
{
+ SAFE_D();
return d ? d->weekDayName(locale, day, format) : QString();
}
@@ -1072,6 +1637,7 @@ QString QCalendar::weekDayName(const QLocale &locale, int day,
QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
QLocale::FormatType format) const
{
+ SAFE_D();
return d ? d->standaloneWeekDayName(locale, day, format) : QString();
}
@@ -1098,6 +1664,7 @@ QString QCalendar::dateTimeToString(QStringView format, const QDateTime &datetim
QDate dateOnly, QTime timeOnly,
const QLocale &locale) const
{
+ SAFE_D();
return d ? d->dateTimeToString(format, datetime, dateOnly, timeOnly, locale) : QString();
}
@@ -1114,3 +1681,7 @@ QStringList QCalendar::availableCalendars()
}
QT_END_NAMESPACE
+
+#ifndef QT_BOOTSTRAPPED
+#include "moc_qcalendar.cpp"
+#endif
diff --git a/src/corelib/time/qcalendar.h b/src/corelib/time/qcalendar.h
index 5eb2e541c8..434f06d67f 100644
--- a/src/corelib/time/qcalendar.h
+++ b/src/corelib/time/qcalendar.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCALENDAR_H
#define QCALENDAR_H
@@ -130,14 +94,31 @@ public:
// New entries must be added to the \enum doc in qcalendar.cpp and
// handled in QCalendarBackend::fromEnum()
Q_ENUM(System)
+ class SystemId
+ {
+ size_t id;
+ friend class QCalendarBackend;
+ constexpr bool isInEnum() const { return id <= size_t(QCalendar::System::Last); }
+ constexpr explicit SystemId(QCalendar::System e) : id(size_t(e)) { }
+ constexpr explicit SystemId(size_t i) : id(i) { }
+
+ public:
+ constexpr SystemId() : id(~size_t(0)) {}
+ constexpr size_t index() const noexcept { return id; }
+ constexpr bool isValid() const noexcept { return ~id; }
+ };
explicit QCalendar(); // Gregorian, optimised
explicit QCalendar(System system);
- explicit QCalendar(QLatin1String name);
+#if QT_CORE_REMOVED_SINCE(6, 4)
+ explicit QCalendar(QLatin1StringView name);
explicit QCalendar(QStringView name);
+#endif
+ explicit QCalendar(QAnyStringView name);
+ explicit QCalendar(SystemId id);
// QCalendar is a trivially copyable value type.
- bool isValid() const { return d != nullptr; }
+ bool isValid() const { return d_ptr != nullptr; }
// Date queries:
int daysInMonth(int month, int year = Unspecified) const;
@@ -163,6 +144,7 @@ public:
// QDate conversions:
QDate dateFromParts(int year, int month, int day) const;
QDate dateFromParts(const YearMonthDay &parts) const;
+ QDate matchCenturyToWeekday(const YearMonthDay &parts, int dow) const;
YearMonthDay partsFromDate(QDate date) const;
int dayOfWeek(QDate date) const;
@@ -185,7 +167,10 @@ public:
static QStringList availableCalendars();
private:
// Always supplied by QCalendarBackend and expected to be a singleton
- const QCalendarBackend *d;
+ // Note that the calendar registry destroys all backends when it is itself
+ // destroyed. The code should check if the registry is destroyed before
+ // dereferencing this pointer.
+ const QCalendarBackend *d_ptr;
};
QT_END_NAMESPACE
diff --git a/src/corelib/time/qcalendarbackend_p.h b/src/corelib/time/qcalendarbackend_p.h
index 129e86494b..15e0795755 100644
--- a/src/corelib/time/qcalendarbackend_p.h
+++ b/src/corelib/time/qcalendarbackend_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCALENDAR_BACKEND_P_H
#define QCALENDAR_BACKEND_P_H
@@ -56,14 +20,19 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qstring.h>
#include <QtCore/qmap.h>
+#include <QtCore/qanystringview.h>
#include <QtCore/private/qlocale_p.h>
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+class QCalendarRegistry;
+}
+
// Locale-related parts, mostly handled in ../text/qlocale.cpp
struct QCalendarLocale {
- quint16 m_language_id, m_script_id, m_country_id;
+ quint16 m_language_id, m_script_id, m_territory_id;
#define rangeGetter(name) \
QLocaleData::DataRange name() const { return { m_ ## name ## _idx, m_ ## name ## _size }; }
@@ -89,10 +58,18 @@ struct QCalendarLocale {
class Q_CORE_EXPORT QCalendarBackend
{
friend class QCalendar;
+ friend class QtPrivate::QCalendarRegistry;
+ Q_DISABLE_COPY_MOVE(QCalendarBackend)
+
public:
+ QCalendarBackend() = default;
virtual ~QCalendarBackend();
virtual QString name() const = 0;
- virtual QCalendar::System calendarSystem() const;
+
+ QStringList names() const;
+
+ QCalendar::System calendarSystem() const;
+ QCalendar::SystemId calendarId() const { return m_id; }
// Date queries:
virtual int daysInMonth(int month, int year = QCalendar::Unspecified) const = 0;
virtual int daysInYear(int year) const;
@@ -111,8 +88,9 @@ public:
// Julian Day conversions:
virtual bool dateToJulianDay(int year, int month, int day, qint64 *jd) const = 0;
virtual QCalendar::YearMonthDay julianDayToDate(qint64 jd) const = 0;
- // Day of week and week numbering:
+ // Day of week:
virtual int dayOfWeek(qint64 jd) const;
+ virtual qint64 matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const;
// Names of months and week-days (implemented in qlocale.cpp):
virtual QString monthName(const QLocale &locale, int month, int year,
@@ -129,24 +107,29 @@ public:
QDate dateOnly, QTime timeOnly,
const QLocale &locale) const;
+ bool isGregorian() const;
+
+ QCalendar::SystemId registerCustomBackend(const QStringList &names);
+
// Calendar enumeration by name:
static QStringList availableCalendars();
protected:
- QCalendarBackend(const QString &name, QCalendar::System id = QCalendar::System::User);
-
// Locale support:
virtual const QCalendarLocale *localeMonthIndexData() const = 0;
virtual const char16_t *localeMonthData() const = 0;
- bool registerAlias(const QString &name);
-
private:
+ QCalendar::SystemId m_id;
+
+ void setIndex(size_t index);
+
// QCalendar's access to its registry:
- static const QCalendarBackend *fromName(QStringView name);
- static const QCalendarBackend *fromName(QLatin1String name);
+ static const QCalendarBackend *fromName(QAnyStringView name);
+ static const QCalendarBackend *fromId(QCalendar::SystemId id);
// QCalendar's access to singletons:
static const QCalendarBackend *fromEnum(QCalendar::System system);
+ static const QCalendarBackend *gregorian();
};
QT_END_NAMESPACE
diff --git a/src/corelib/time/qcalendarmath_p.h b/src/corelib/time/qcalendarmath_p.h
index 61c2c5d2b5..c785803ce3 100644
--- a/src/corelib/time/qcalendarmath_p.h
+++ b/src/corelib/time/qcalendarmath_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCALENDARMATH_P_H
#define QCALENDARMATH_P_H
@@ -52,26 +16,130 @@
//
#include <QtCore/private/qglobal_p.h>
+#include <QtCore/QtAlgorithms>
QT_BEGIN_NAMESPACE
namespace QRoundingDown {
+// Note: qgregoriancalendar.cpp contains some static asserts to verify this all works.
+namespace QRoundingDownPrivate {
+#ifdef Q_CC_MSVC
+// MSVC 2019 doesn't believe in the constexpr-ness of the #else clause's version :-(
+#define QCALMATH_ISPOW2(b) ((b > 0) && !(b & (b - 1))) // See #else's comment.
+#else
+// Subtracting one toggles the least significant set bit and any unset bits less
+// significant than it, leaving other bits unchanged. Thus the & of this with
+// the original number preserves all more significant bits, clearing the least
+// significant. If there are no such bits, either our number was 0 or it only
+// had one bit set, hence is a power of two.
+template <typename Int>
+inline constexpr bool isPowerOfTwo(Int b) { return b > 0 && (b & (b - 1)) == 0; }
+#define QCALMATH_ISPOW2(b) QRoundingDownPrivate::isPowerOfTwo(b)
+#endif
+}
/*
Division, rounding down (rather than towards zero).
From C++11 onwards, integer division is defined to round towards zero, so we
can rely on that when implementing this. This is only used with denominator b
> 0, so we only have to treat negative numerator, a, specially.
+
+ If a is a multiple of b, adding 1 before and subtracting it after dividing by
+ b gets us to where we should be (albeit by an eccentric path), since the
+ adding caused rounding up, undone by the subtracting. Otherwise, adding 1
+ doesn't change the result of dividing by b; and we want one less than that
+ result. This is equivalent to subtracting b - 1 and simply dividing, except
+ when that subtraction would underflow.
+
+ For the remainder, with negative a, aside from having to add one and subtract
+ it later to deal with the exact multiples, we can simply use the truncating
+ remainder and then add b. When b is a power of two we can, of course, get the
+ remainder correctly by the same masking that works for positive a.
*/
-template<typename Int> constexpr Int qDiv(Int a, unsigned b)
-{ return (a - (a < 0 ? int(b - 1) : 0)) / int(b); }
+// Fall-back, to ensure intelligible error messages on mis-use:
+template <unsigned b, typename Int, std::enable_if_t<(int(b) < 2), bool> = true>
+constexpr auto qDivMod(Int)
+{
+ static_assert(b, "Division by 0 is undefined");
+ // Use complement of earlier cases || new check, to ensure only one error:
+ static_assert(!b || int(b) > 0, "Denominator is too big");
+ static_assert(int(b) < 1 || b > 1, "Division by 1 is fautous");
+ struct R { Int quotient; Int remainder; };
+ return R { 0, 0 };
+}
+
+template <unsigned b, typename Int,
+ std::enable_if_t<(b > 1) && !QCALMATH_ISPOW2(b) && (int(b) > 0),
+ bool> = true>
+constexpr auto qDivMod(Int a)
+{
+ struct R { Int quotient; Int remainder; };
+ if constexpr (std::is_signed_v<Int>) {
+ if (a < 0) {
+ ++a; // can't overflow, it's negative
+ return R { Int(a / int(b) - 1), Int(a % int(b) - 1 + int(b)) };
+ }
+ }
+ return R { Int(a / int(b)), Int(a % int(b)) };
+}
+
+template <unsigned b, typename Int,
+ std::enable_if_t<(b > 1) && QCALMATH_ISPOW2(b) && (int(b) > 0),
+ bool> = true>
+constexpr auto qDivMod(Int a)
+{
+ constexpr unsigned w = QtPrivate::qConstexprCountTrailingZeroBits(b);
+ struct R { Int quotient; Int remainder; };
+ if constexpr (std::is_signed_v<Int>) {
+ if (a < 0)
+ return R { Int((a + 1) / int(b) - 1), Int(a & int(b - 1)) };
+ }
+ return R { Int(a >> w), Int(a & int(b - 1)) };
+}
-template<typename Int> constexpr Int qMod(Int a, unsigned b)
-{ return a - qDiv(a, b) * b; }
+#undef QCALMATH_ISPOW2
+// </kludge>
+
+template <unsigned b, typename Int> constexpr Int qDiv(Int a) { return qDivMod<b>(a).quotient; }
+template <unsigned b, typename Int> constexpr Int qMod(Int a) { return qDivMod<b>(a).remainder; }
} // QRoundingDown
+namespace QRomanCalendrical {
+// Julian Day number of Gregorian 1 BCE, February 29th:
+constexpr qint64 LeapDayGregorian1Bce = 1721119;
+// Aside from (maybe) some turns of centuries, one year in four is leap:
+constexpr unsigned FourYears = 4 * 365 + 1;
+constexpr unsigned FiveMonths = 31 + 30 + 31 + 30 + 31; // Mar-Jul or Aug-Dec.
+
+constexpr auto yearMonthToYearDays(int year, int month)
+{
+ // Pre-digests year and month to (possibly denormal) year count and day-within-year.
+ struct R { qint64 year; qint64 days; };
+ if (year < 0) // Represent -N BCE as 1-N so year numbering is contiguous.
+ ++year;
+ month -= 3; // Adjust month numbering so March = 0, ...
+ if (month < 0) { // and Jan = 10, Feb = 11, in the previous year.
+ --year;
+ month += 12;
+ }
+ return R { year, QRoundingDown::qDiv<5>(FiveMonths * month + 2) };
+}
+
+constexpr auto dayInYearToYmd(int dayInYear)
+{
+ // The year is an adjustment to the year for which dayInYear may be denormal.
+ struct R { int year; int month; int day; };
+ // Shared code for Julian and Milankovic (at least).
+ using namespace QRoundingDown;
+ const auto month5Day = qDivMod<FiveMonths>(5 * dayInYear + 2);
+ // Its remainder changes by 5 per day, except at roughly monthly quotient steps.
+ const auto yearMonth = qDivMod<12>(month5Day.quotient + 2);
+ return R { yearMonth.quotient, yearMonth.remainder + 1, qDiv<5>(month5Day.remainder) + 1 };
+}
+}
+
QT_END_NAMESPACE
#endif // QCALENDARMATH_P_H
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index 7a3e49e076..687f174c07 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1,99 +1,56 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qdatetime.h"
+
+#include "qcalendar.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+#include "qlocale.h"
+#include "qset.h"
+
+#include "private/qcalendarmath_p.h"
#include "private/qdatetime_p.h"
#if QT_CONFIG(datetimeparser)
#include "private/qdatetimeparser_p.h"
#endif
-
-#include "qdatastream.h"
-#include "qset.h"
-#include "qlocale.h"
-#include "qdatetime.h"
-#if QT_CONFIG(timezone)
-#include "qtimezoneprivate_p.h"
+#ifdef Q_OS_DARWIN
+#include "private/qcore_mac_p.h"
#endif
-#include "qdebug.h"
-#ifndef Q_OS_WIN
-#include <locale.h>
+#include "private/qgregoriancalendar_p.h"
+#include "private/qlocale_tools_p.h"
+#include "private/qlocaltime_p.h"
+#include "private/qnumeric_p.h"
+#include "private/qstringconverter_p.h"
+#include "private/qstringiterator_p.h"
+#if QT_CONFIG(timezone)
+#include "private/qtimezoneprivate_p.h"
#endif
#include <cmath>
-#ifdef Q_CC_MINGW
-# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
-#endif
-#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
#endif
-#if defined(Q_OS_MAC)
-#include <private/qcore_mac_p.h>
-#endif
-
-#include "qcalendar.h"
-#include "qgregoriancalendar_p.h"
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QtPrivate::DateTimeConstants;
+using namespace QtMiscUtils;
+
/*****************************************************************************
Date/Time Constants
*****************************************************************************/
-enum {
- SECS_PER_DAY = 86400,
- MSECS_PER_DAY = 86400000,
- SECS_PER_HOUR = 3600,
- MSECS_PER_HOUR = 3600000,
- SECS_PER_MIN = 60,
- MSECS_PER_MIN = 60000,
- TIME_T_MAX = 2145916799, // int maximum 2037-12-31T23:59:59 UTC
- JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
-};
-
/*****************************************************************************
QDate static helper functions
*****************************************************************************/
+static_assert(std::is_trivially_copyable_v<QCalendar::YearMonthDay>);
-static inline QDate fixedDate(QCalendar::YearMonthDay &&parts, QCalendar cal)
+static inline QDate fixedDate(QCalendar::YearMonthDay parts, QCalendar cal)
{
if ((parts.year < 0 && !cal.isProleptic()) || (parts.year == 0 && !cal.hasYearZero()))
return QDate();
@@ -102,13 +59,13 @@ static inline QDate fixedDate(QCalendar::YearMonthDay &&parts, QCalendar cal)
return cal.dateFromParts(parts);
}
-static inline QDate fixedDate(QCalendar::YearMonthDay &&parts)
+static inline QDate fixedDate(QCalendar::YearMonthDay parts)
{
if (parts.year) {
parts.day = qMin(parts.day, QGregorianCalendar::monthLength(parts.month, parts.year));
- qint64 jd;
- if (QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day, &jd))
- return QDate::fromJulianDay(jd);
+ const auto jd = QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day);
+ if (jd)
+ return QDate::fromJulianDay(*jd);
}
return QDate();
}
@@ -126,7 +83,7 @@ static const char qt_shortMonthNames[][4] = {
static int fromShortMonthName(QStringView monthName)
{
for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
- if (monthName == QLatin1String(qt_shortMonthNames[i], 3))
+ if (monthName == QLatin1StringView(qt_shortMonthNames[i], 3))
return i + 1;
}
return -1;
@@ -134,10 +91,46 @@ static int fromShortMonthName(QStringView monthName)
#endif // textdate
#if QT_CONFIG(datestring) // depends on, so implies, textdate
+namespace {
+using ParsedInt = QSimpleParsedNumber<qulonglong>;
+
+/*
+ Reads a whole number that must be the whole text.
+*/
+ParsedInt readInt(QLatin1StringView text)
+{
+ // Various date formats' fields (e.g. all in ISO) should not accept spaces
+ // or signs, so check that the string starts with a digit and that qstrntoull()
+ // converted the whole string.
+
+ if (text.isEmpty() || !isAsciiDigit(text.front().toLatin1()))
+ return {};
+
+ QSimpleParsedNumber res = qstrntoull(text.data(), text.size(), 10);
+ return res.used == text.size() ? res : ParsedInt{};
+}
+
+ParsedInt readInt(QStringView text)
+{
+ if (text.isEmpty())
+ return {};
+
+ // Converting to Latin-1 because QStringView::toULongLong() works with
+ // US-ASCII only by design anyway.
+ // Also QStringView::toULongLong() can't be used here as it will happily ignore
+ // spaces and accept signs; but various date formats' fields (e.g. all in ISO)
+ // should not.
+ QVarLengthArray<char> latin1(text.size());
+ QLatin1::convertFromUnicode(latin1.data(), text);
+ return readInt(QLatin1StringView{latin1.data(), latin1.size()});
+}
+
+} // namespace
+
struct ParsedRfcDateTime {
QDate date;
QTime time;
- int utcOffset;
+ int utcOffset = 0;
};
static int shortDayFromName(QStringView name)
@@ -150,23 +143,28 @@ static int shortDayFromName(QStringView name)
return 0;
}
-static ParsedRfcDateTime rfcDateImpl(const QString &s)
+static ParsedRfcDateTime rfcDateImpl(QStringView s)
{
// Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format -
// or "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only)
ParsedRfcDateTime result;
- auto words = QStringView{s}.split(QLatin1Char(' '), Qt::SkipEmptyParts);
- if (words.size() < 3 || words.size() > 6)
+ QVarLengthArray<QStringView, 6> words;
+
+ auto tokens = s.tokenize(u' ', Qt::SkipEmptyParts);
+ auto it = tokens.begin();
+ for (int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
+ words.emplace_back(*it);
+
+ if (words.size() < 3 || it != tokens.end())
return result;
- const QChar colon(QLatin1Char(':'));
- const QLocale C = QLocale::c();
+ const QChar colon(u':');
bool ok = true;
QDate date;
const auto isShortName = [](QStringView name) {
- return (name.length() == 3 && name.at(0).isUpper()
- && name.at(1).isLower() && name.at(2).isLower());
+ return (name.size() == 3 && name[0].isUpper()
+ && name[1].isLower() && name[2].isLower());
};
/* Reject entirely (return) if the string is malformed; however, if the date
@@ -176,10 +174,13 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
do { // "loop" so that we can use break on merely invalid, but "right shape" date.
QStringView dayName;
bool rfcX22 = true;
- if (words.at(0).endsWith(QLatin1Char(','))) {
- dayName = words.takeFirst().chopped(1);
- } else if (!words.at(0).at(0).isDigit()) {
- dayName = words.takeFirst();
+ const QStringView maybeDayName = words.front();
+ if (maybeDayName.endsWith(u',')) {
+ dayName = maybeDayName.chopped(1);
+ words.erase(words.begin());
+ } else if (!maybeDayName.front().isDigit()) {
+ dayName = maybeDayName;
+ words.erase(words.begin());
rfcX22 = false;
} // else: dayName is not specified (so we can only be RFC *22)
if (words.size() < 3 || words.size() > 5)
@@ -231,36 +232,40 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
// Time: [hh:mm[:ss]]
QTime time;
if (words.size() && words.at(0).contains(colon)) {
- const QStringView when = words.takeFirst();
- if (when.at(2) != colon || (when.size() == 8 ? when.at(5) != colon : when.size() > 5))
+ const QStringView when = words.front();
+ words.erase(words.begin());
+ if (when.size() < 5 || when[2] != colon
+ || (when.size() == 8 ? when[5] != colon : when.size() > 5)) {
return result;
- const int hour = C.toInt(when.left(2), &ok);
+ }
+ const int hour = when.first(2).toInt(&ok);
if (!ok)
return result;
- const int minute = C.toInt(when.mid(3, 2), &ok);
+ const int minute = when.sliced(3, 2).toInt(&ok);
if (!ok)
return result;
- const auto secs = when.size() == 8 ? C.toInt(when.right(2), &ok) : 0;
+ const auto secs = when.size() == 8 ? when.last(2).toInt(&ok) : 0;
if (!ok)
return result;
time = QTime(hour, minute, secs);
}
- // Offset: [±hhmm]
+ // Offset: [±hh[mm]]
int offset = 0;
if (words.size()) {
- const QStringView zone = words.takeFirst();
+ const QStringView zone = words.front();
+ words.erase(words.begin());
if (words.size() || !(zone.size() == 3 || zone.size() == 5))
return result;
bool negate = false;
- if (zone.at(0) == QLatin1Char('-'))
+ if (zone[0] == u'-')
negate = true;
- else if (zone.at(0) != QLatin1Char('+'))
+ else if (zone[0] != u'+')
return result;
- const int hour = C.toInt(zone.mid(1, 2), &ok);
+ const int hour = zone.sliced(1, 2).toInt(&ok);
if (!ok)
return result;
- const auto minute = zone.size() > 3 ? C.toInt(zone.mid(3, 2), &ok) : 0;
+ const auto minute = zone.size() == 5 ? zone.last(2).toInt(&ok) : 0;
if (!ok)
return result;
offset = (hour * 60 + minute) * 60;
@@ -275,24 +280,24 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
}
#endif // datestring
-// Return offset in [+-]HH:mm format
+// Return offset in ±HH:mm format
static QString toOffsetString(Qt::DateFormat format, int offset)
{
return QString::asprintf("%c%02d%s%02d",
offset >= 0 ? '+' : '-',
- qAbs(offset) / SECS_PER_HOUR,
+ qAbs(offset) / int(SECS_PER_HOUR),
// Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not:
format == Qt::TextDate ? "" : ":",
(qAbs(offset) / 60) % 60);
}
#if QT_CONFIG(datestring)
-// Parse offset in [+-]HH[[:]mm] format
+// Parse offset in ±HH[[:]mm] format
static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
{
*valid = false;
- const int size = offsetString.size();
+ const qsizetype size = offsetString.size();
if (size < 2 || size > 6)
return 0;
@@ -300,32 +305,31 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
int sign;
// First char must be + or -
- const QChar signChar = offsetString.at(0);
- if (signChar == QLatin1Char('+'))
+ const QChar signChar = offsetString[0];
+ if (signChar == u'+')
sign = 1;
- else if (signChar == QLatin1Char('-'))
+ else if (signChar == u'-')
sign = -1;
else
return 0;
// Split the hour and minute parts
- const QStringView time = offsetString.mid(1);
- qsizetype hhLen = time.indexOf(QLatin1Char(':'));
+ const QStringView time = offsetString.sliced(1);
+ qsizetype hhLen = time.indexOf(u':');
qsizetype mmIndex;
if (hhLen == -1)
- mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
+ mmIndex = hhLen = 2; // ±HHmm or ±HH format
else
mmIndex = hhLen + 1;
- const QLocale C = QLocale::c();
- const QStringView hhRef = time.left(qMin(hhLen, time.size()));
+ const QStringView hhRef = time.first(qMin(hhLen, time.size()));
bool ok = false;
- const int hour = C.toInt(hhRef, &ok);
- if (!ok)
+ const int hour = hhRef.toInt(&ok);
+ if (!ok || hour > 23) // More generous than QTimeZone::MaxUtcOffsetSecs
return 0;
- const QStringView mmRef = time.mid(qMin(mmIndex, time.size()));
- const int minute = mmRef.isEmpty() ? 0 : C.toInt(mmRef, &ok);
+ const QStringView mmRef = time.sliced(qMin(mmIndex, time.size()));
+ const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
if (!ok || minute < 0 || minute > 59)
return 0;
@@ -344,11 +348,18 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
\reentrant
\brief The QDate class provides date functions.
- A QDate object represents a particular day, regardless of calendar,
- locale or other settings used when creating it or supplied by the system.
- It can report the year, month and day of the month that represent the
- day with respect to the proleptic Gregorian calendar or any calendar supplied
- as a QCalendar object.
+ \compares strong
+ \compareswith strong std::chrono::year_month_day std::chrono::year_month_day_last \
+ std::chrono::year_month_weekday std::chrono::year_month_weekday_last
+ These comparison operators are only available when using C++20.
+ \endcompareswith
+
+ A QDate object represents a particular day, regardless of calendar, locale
+ or other settings used when creating it or supplied by the system. It can
+ report the year, month and day of the month that represent the day with
+ respect to the proleptic Gregorian calendar or any calendar supplied as a
+ QCalendar object. QDate objects should be passed by value rather than by
+ reference to const; they simply package \c qint64.
A QDate object is typically created by giving the year, month, and day
numbers explicitly. Note that QDate interprets year numbers less than 100 as
@@ -430,8 +441,9 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
QDate::QDate(int y, int m, int d)
{
- if (!QGregorianCalendar::julianFromParts(y, m, d, &jd))
- jd = nullJd();
+ static_assert(maxJd() == JulianDayMax);
+ static_assert(minJd() == JulianDayMin);
+ jd = QGregorianCalendar::julianFromParts(y, m, d).value_or(nullJd());
}
QDate::QDate(int y, int m, int d, QCalendar cal)
@@ -440,6 +452,54 @@ QDate::QDate(int y, int m, int d, QCalendar cal)
}
/*!
+ \fn QDate::QDate(std::chrono::year_month_day date)
+ \fn QDate::QDate(std::chrono::year_month_day_last date)
+ \fn QDate::QDate(std::chrono::year_month_weekday date)
+ \fn QDate::QDate(std::chrono::year_month_weekday_last date)
+
+ \since 6.4
+
+ Constructs a QDate representing the same date as \a date. This allows for
+ easy interoperability between the Standard Library calendaring classes and
+ Qt datetime classes.
+
+ For example:
+
+ \snippet code/src_corelib_time_qdatetime.cpp 22
+
+ \note Unlike QDate, std::chrono::year and the related classes feature the
+ year zero. This means that if \a date is in the year zero or before, the
+ resulting QDate object will have an year one less than the one specified by
+ \a date.
+
+ \note This function requires C++20.
+*/
+
+/*!
+ \fn QDate QDate::fromStdSysDays(const std::chrono::sys_days &days)
+ \since 6.4
+
+ Returns a QDate \a days days after January 1st, 1970 (the UNIX epoch). If
+ \a days is negative, the returned date will be before the epoch.
+
+ \note This function requires C++20.
+
+ \sa toStdSysDays()
+*/
+
+/*!
+ \fn std::chrono::sys_days QDate::toStdSysDays() const
+
+ Returns the number of days between January 1st, 1970 (the UNIX epoch) and
+ this date, represented as a \c{std::chrono::sys_days} object. If this date
+ is before the epoch, the number of days will be negative.
+
+ \note This function requires C++20.
+
+ \sa fromStdSysDays(), daysTo()
+*/
+
+/*!
\fn bool QDate::isNull() const
Returns \c true if the date is null; otherwise returns \c false. A null
@@ -642,9 +702,8 @@ int QDate::dayOfYear(QCalendar cal) const
int QDate::dayOfYear() const
{
if (isValid()) {
- qint64 first;
- if (QGregorianCalendar::julianFromParts(year(), 1, 1, &first))
- return jd - first + 1;
+ if (const auto first = QGregorianCalendar::julianFromParts(year(), 1, 1))
+ return jd - *first + 1;
}
return 0;
}
@@ -735,17 +794,49 @@ int QDate::weekNumber(int *yearNumber) const
// This could be replaced by use of QIso8601Calendar, once we implement it.
// The Thursday of the same week determines our answer:
- QDate thursday(addDays(4 - dayOfWeek()));
- int year = thursday.year();
+ const QDate thursday(addDays(4 - dayOfWeek()));
+ if (yearNumber)
+ *yearNumber = thursday.year();
+
// Week n's Thurs's DOY has 1 <= DOY - 7*(n-1) < 8, so 0 <= DOY + 6 - 7*n < 7:
- int week = (thursday.dayOfYear() + 6) / 7;
+ return (thursday.dayOfYear() + 6) / 7;
+}
- if (yearNumber)
- *yearNumber = year;
- return week;
+#if QT_DEPRECATED_SINCE(6, 9)
+// Only called by deprecated methods (so bootstrap builds warn unused without this #if).
+static QTimeZone asTimeZone(Qt::TimeSpec spec, int offset, const char *warner)
+{
+ if (warner) {
+ switch (spec) {
+ case Qt::TimeZone:
+ qWarning("%s: Pass a QTimeZone instead of Qt::TimeZone.", warner);
+ break;
+ case Qt::LocalTime:
+ if (offset) {
+ qWarning("%s: Ignoring offset (%d seconds) passed with Qt::LocalTime",
+ warner, offset);
+ }
+ break;
+ case Qt::UTC:
+ if (offset) {
+ qWarning("%s: Ignoring offset (%d seconds) passed with Qt::UTC",
+ warner, offset);
+ offset = 0;
+ }
+ break;
+ case Qt::OffsetFromUTC:
+ break;
+ }
+ }
+ return QTimeZone::isUtcOrFixedOffset(spec)
+ ? QTimeZone::fromSecondsAheadOfUtc(offset)
+ : QTimeZone(QTimeZone::LocalTime);
}
+#endif // Helper for 6.9 deprecation
+
+enum class DaySide { Start, End };
-static bool inDateTimeRange(qint64 jd, bool start)
+static bool inDateTimeRange(qint64 jd, DaySide side)
{
using Bounds = std::numeric_limits<qint64>;
if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
@@ -753,30 +844,24 @@ static bool inDateTimeRange(qint64 jd, bool start)
jd -= JULIAN_DAY_FOR_EPOCH;
const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
- // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.)
+ // (Divisions rounded towards zero, as MSECS_PER_DAY is even - so doesn't
+ // divide max() - and has factors other than two, so doesn't divide min().)
// Range includes start of last day and end of first:
- if (start)
+ switch (side) {
+ case DaySide::Start:
return jd > minDay && jd <= maxDay;
- return jd >= minDay && jd < maxDay;
+ case DaySide::End:
+ return jd >= minDay && jd < maxDay;
+ }
+ Q_UNREACHABLE_RETURN(false);
}
-static QDateTime toEarliest(QDate day, const QDateTime &form)
+static QDateTime toEarliest(QDate day, const QTimeZone &zone)
{
- const Qt::TimeSpec spec = form.timeSpec();
- const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
-#if QT_CONFIG(timezone)
- QTimeZone zone;
- if (spec == Qt::TimeZone)
- zone = form.timeZone();
-#endif
- auto moment = [=](QTime time) {
- switch (spec) {
- case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
-#if QT_CONFIG(timezone)
- case Qt::TimeZone: return QDateTime(day, time, zone);
-#endif
- default: return QDateTime(day, time, spec);
- }
+ Q_ASSERT(!zone.isUtcOrFixedOffset());
+ // And the day starts in a gap. First find a moment not in that gap.
+ const auto moment = [=](QTime time) {
+ return QDateTime(day, time, zone, QDateTime::TransitionResolution::Reject);
};
// Longest routine time-zone transition is 2 hours:
QDateTime when = moment(QTime(2, 0));
@@ -794,8 +879,9 @@ static QDateTime toEarliest(QDate day, const QDateTime &form)
int low = 0;
// Binary chop to the right minute
while (high > low + 1) {
- int mid = (high + low) / 2;
- QDateTime probe = moment(QTime(mid / 60, mid % 60));
+ const int mid = (high + low) / 2;
+ const QDateTime probe = QDateTime(day, QTime(mid / 60, mid % 60), zone,
+ QDateTime::TransitionResolution::PreferBefore);
if (probe.isValid() && probe.date() == day) {
high = mid;
when = probe;
@@ -803,104 +889,134 @@ static QDateTime toEarliest(QDate day, const QDateTime &form)
low = mid;
}
}
- return when;
+ // Transitions out of local solar mean time, and the few international
+ // date-line crossings before that (Alaska, Philippines), may have happened
+ // between minute boundaries. Don't try to fix milliseconds.
+ if (QDateTime p = moment(when.time().addSecs(-1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
+ high *= 60;
+ low *= 60;
+ while (high > low + 1) {
+ const int mid = (high + low) / 2;
+ const int min = mid / 60;
+ const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60));
+ if (probe.isValid() && probe.date() == day) {
+ high = mid;
+ when = probe;
+ } else {
+ low = mid;
+ }
+ }
+ }
+ return when.isValid() ? when : QDateTime();
}
/*!
\since 5.14
- \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
- \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const
- Returns the start-moment of the day. Usually, this shall be midnight at the
- start of the day: however, if a time-zone transition causes the given date
- to skip over that midnight (e.g. a DST spring-forward skipping from the end
- of the previous day to 01:00 of the new day), the actual earliest time in
- the day is returned. This can only arise when the start-moment is specified
- in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of
- local time (by passing Qt::LocalTime as \a spec; this is its default).
+ Returns the start-moment of the day.
+
+ When a day starts depends on a how time is described: each day starts and
+ ends earlier for those in time-zones further west and later for those in
+ time-zones further east. The time representation to use can be specified by
+ an optional time \a zone. The default time representation is the system's
+ local time.
- The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
- gives the implied zone's offset from UTC. As UTC and such zones have no
- transitions, the start of the day is QTime(0, 0) in these cases.
+ Usually, the start of the day is midnight, 00:00: however, if a time-zone
+ transition causes the given date to skip over that midnight (e.g. a DST
+ spring-forward skipping over the first hour of the day day), the actual
+ earliest time in the day is returned. This can only arise when the time
+ representation is a time-zone or local time.
+
+ When \a zone has a timeSpec() of is Qt::OffsetFromUTC or Qt::UTC, the time
+ representation has no transitions so the start of the day is QTime(0, 0).
In the rare case of a date that was entirely skipped (this happens when a
zone east of the international date-line switches to being west of it), the
- return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
- passing a QTimeZone) or passing an invalid time-zone as \a zone will also
+ return shall be invalid. Passing an invalid time-zone as \a zone will also
produce an invalid result, as shall dates that start outside the range
representable by QDateTime.
\sa endOfDay()
*/
-QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+QDateTime QDate::startOfDay(const QTimeZone &zone) const
{
- if (!inDateTimeRange(jd, true))
+ if (!inDateTimeRange(jd, DaySide::Start) || !zone.isValid())
return QDateTime();
- switch (spec) {
- case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
- qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this;
- return QDateTime();
- case Qt::OffsetFromUTC:
- case Qt::UTC:
- return QDateTime(*this, QTime(0, 0), spec, offsetSeconds);
+ QDateTime when(*this, QTime(0, 0), zone,
+ QDateTime::TransitionResolution::RelativeToBefore);
+ if (Q_UNLIKELY(!when.isValid() || when.date() != *this)) {
+#if QT_CONFIG(timezone)
+ // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
+ if (zone.timeSpec() == Qt::TimeZone && zone.hasTransitions()) {
+ QTimeZone::OffsetData tran
+ // There's unlikely to be another transition before noon tomorrow.
+ // However, the whole of today may have been skipped !
+ = zone.previousTransition(QDateTime(addDays(1), QTime(12, 0), zone));
+ const QDateTime &at = tran.atUtc.toTimeZone(zone);
+ if (at.isValid() && at.date() == *this)
+ return at;
+ }
+#endif
- case Qt::LocalTime:
- if (offsetSeconds)
- qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
- break;
+ when = toEarliest(*this, zone);
}
- QDateTime when(*this, QTime(0, 0), spec);
- if (!when.isValid())
- when = toEarliest(*this, when);
- return when.isValid() ? when : QDateTime();
+ return when;
}
-#if QT_CONFIG(timezone)
/*!
- \overload
- \since 5.14
+ \overload
+ \since 6.5
*/
-QDateTime QDate::startOfDay(const QTimeZone &zone) const
+QDateTime QDate::startOfDay() const
{
- if (!inDateTimeRange(jd, true) || !zone.isValid())
- return QDateTime();
+ return startOfDay(QTimeZone::LocalTime);
+}
+
+#if QT_DEPRECATED_SINCE(6, 9)
+/*!
+ \overload
+ \since 5.14
+ \deprecated [6.9] Use \c{startOfDay(const QTimeZone &)} instead.
- QDateTime when(*this, QTime(0, 0), zone);
- if (when.isValid())
- return when;
+ Returns the start-moment of the day.
- // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
- if (zone.hasTransitions()) {
- QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
- const QDateTime &at = tran.atUtc.toTimeZone(zone);
- if (at.isValid() && at.date() == *this)
- return at;
- }
+ When a day starts depends on a how time is described: each day starts and
+ ends earlier for those with higher offsets from UTC and later for those with
+ lower offsets from UTC. The time representation to use can be specified
+ either by a \a spec and \a offsetSeconds (ignored unless \a spec is
+ Qt::OffsetSeconds) or by a time zone.
- when = toEarliest(*this, when);
- return when.isValid() ? when : QDateTime();
+ Usually, the start of the day is midnight, 00:00: however, if a local time
+ transition causes the given date to skip over that midnight (e.g. a DST
+ spring-forward skipping over the first hour of the day day), the actual
+ earliest time in the day is returned.
+
+ When \a spec is Qt::OffsetFromUTC, \a offsetSeconds gives an implied zone's
+ offset from UTC. As UTC and such zones have no transitions, the start of the
+ day is QTime(0, 0) in these cases.
+
+ In the rare case of a date that was entirely skipped (this happens when a
+ zone east of the international date-line switches to being west of it), the
+ return shall be invalid. Passing Qt::TimeZone as \a spec (instead of passing
+ a QTimeZone) will also produce an invalid result, as shall dates that start
+ outside the range representable by QDateTime.
+*/
+QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+{
+ QTimeZone zone = asTimeZone(spec, offsetSeconds, "QDate::startOfDay");
+ // If spec was Qt::TimeZone, zone's is Qt::LocalTime.
+ return zone.timeSpec() == spec ? startOfDay(zone) : QDateTime();
}
-#endif // timezone
+#endif // 6.9 deprecation
-static QDateTime toLatest(QDate day, const QDateTime &form)
+static QDateTime toLatest(QDate day, const QTimeZone &zone)
{
- const Qt::TimeSpec spec = form.timeSpec();
- const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
-#if QT_CONFIG(timezone)
- QTimeZone zone;
- if (spec == Qt::TimeZone)
- zone = form.timeZone();
-#endif
- auto moment = [=](QTime time) {
- switch (spec) {
- case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
-#if QT_CONFIG(timezone)
- case Qt::TimeZone: return QDateTime(day, time, zone);
-#endif
- default: return QDateTime(day, time, spec);
- }
+ Q_ASSERT(!zone.isUtcOrFixedOffset());
+ // And the day ends in a gap. First find a moment not in that gap:
+ const auto moment = [=](QTime time) {
+ return QDateTime(day, time, zone, QDateTime::TransitionResolution::Reject);
};
// Longest routine time-zone transition is 2 hours:
QDateTime when = moment(QTime(21, 59, 59, 999));
@@ -918,8 +1034,9 @@ static QDateTime toLatest(QDate day, const QDateTime &form)
int low = when.time().msecsSinceStartOfDay() / 60000;
// Binary chop to the right minute
while (high > low + 1) {
- int mid = (high + low) / 2;
- QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
+ const int mid = (high + low) / 2;
+ const QDateTime probe = QDateTime(day, QTime(mid / 60, mid % 60, 59, 999), zone,
+ QDateTime::TransitionResolution::PreferAfter);
if (probe.isValid() && probe.date() == day) {
low = mid;
when = probe;
@@ -927,85 +1044,127 @@ static QDateTime toLatest(QDate day, const QDateTime &form)
high = mid;
}
}
- return when;
+ // Transitions out of local solar mean time, and the few international
+ // date-line crossings before that (Alaska, Philippines), may have happened
+ // between minute boundaries. Don't try to fix milliseconds.
+ if (QDateTime p = moment(when.time().addSecs(1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
+ high *= 60;
+ low *= 60;
+ while (high > low + 1) {
+ const int mid = (high + low) / 2;
+ const int min = mid / 60;
+ const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60, 999));
+ if (probe.isValid() && probe.date() == day) {
+ low = mid;
+ when = probe;
+ } else {
+ high = mid;
+ }
+ }
+ }
+ return when.isValid() ? when : QDateTime();
}
/*!
\since 5.14
- \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
- \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const
-
- Returns the end-moment of the day. Usually, this is one millisecond before
- the midnight at the end of the day: however, if a time-zone transition
- causes the given date to skip over that midnight (e.g. a DST spring-forward
- skipping from just before 23:00 to the start of the next day), the actual
- latest time in the day is returned. This can only arise when the
- start-moment is specified in terms of a time-zone (by passing its QTimeZone
- as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec;
- this is its default).
-
- The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
- gives the implied zone's offset from UTC. As UTC and such zones have no
- transitions, the end of the day is QTime(23, 59, 59, 999) in these cases.
+
+ Returns the end-moment of the day.
+
+ When a day ends depends on a how time is described: each day starts and ends
+ earlier for those in time-zones further west and later for those in
+ time-zones further east. The time representation to use can be specified by
+ an optional time \a zone. The default time representation is the system's
+ local time.
+
+ Usually, the end of the day is one millisecond before the midnight, 24:00:
+ however, if a time-zone transition causes the given date to skip over that
+ moment (e.g. a DST spring-forward skipping over 23:00 and the following
+ hour), the actual latest time in the day is returned. This can only arise
+ when the time representation is a time-zone or local time.
+
+ When \a zone has a timeSpec() of Qt::OffsetFromUTC or Qt::UTC, the time
+ representation has no transitions so the end of the day is QTime(23, 59, 59,
+ 999).
In the rare case of a date that was entirely skipped (this happens when a
zone east of the international date-line switches to being west of it), the
- return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
- passing a QTimeZone) will also produce an invalid result, as shall dates
- that end outside the range representable by QDateTime.
+ return shall be invalid. Passing an invalid time-zone as \a zone will also
+ produce an invalid result, as shall dates that end outside the range
+ representable by QDateTime.
\sa startOfDay()
*/
-QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+QDateTime QDate::endOfDay(const QTimeZone &zone) const
{
- if (!inDateTimeRange(jd, false))
+ if (!inDateTimeRange(jd, DaySide::End) || !zone.isValid())
return QDateTime();
- switch (spec) {
- case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
- qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this;
- return QDateTime();
- case Qt::UTC:
- case Qt::OffsetFromUTC:
- return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds);
+ QDateTime when(*this, QTime(23, 59, 59, 999), zone,
+ QDateTime::TransitionResolution::RelativeToAfter);
+ if (Q_UNLIKELY(!when.isValid() || when.date() != *this)) {
+#if QT_CONFIG(timezone)
+ // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
+ if (zone.timeSpec() == Qt::TimeZone && zone.hasTransitions()) {
+ QTimeZone::OffsetData tran
+ // It's unlikely there's been another transition since yesterday noon.
+ // However, the whole of today may have been skipped !
+ = zone.nextTransition(QDateTime(addDays(-1), QTime(12, 0), zone));
+ const QDateTime &at = tran.atUtc.toTimeZone(zone);
+ if (at.isValid() && at.date() == *this)
+ return at;
+ }
+#endif
- case Qt::LocalTime:
- if (offsetSeconds)
- qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
- break;
+ when = toLatest(*this, zone);
}
- QDateTime when(*this, QTime(23, 59, 59, 999), spec);
- if (!when.isValid())
- when = toLatest(*this, when);
- return when.isValid() ? when : QDateTime();
+ return when;
}
-#if QT_CONFIG(timezone)
/*!
- \overload
- \since 5.14
+ \overload
+ \since 6.5
*/
-QDateTime QDate::endOfDay(const QTimeZone &zone) const
+QDateTime QDate::endOfDay() const
{
- if (!inDateTimeRange(jd, false) || !zone.isValid())
- return QDateTime();
+ return endOfDay(QTimeZone::LocalTime);
+}
- QDateTime when(*this, QTime(23, 59, 59, 999), zone);
- if (when.isValid())
- return when;
+#if QT_DEPRECATED_SINCE(6, 9)
+/*!
+ \overload
+ \since 5.14
+ \deprecated [6.9] Use \c{endOfDay(const QTimeZone &) instead.
- // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
- if (zone.hasTransitions()) {
- QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
- const QDateTime &at = tran.atUtc.toTimeZone(zone);
- if (at.isValid() && at.date() == *this)
- return at;
- }
+ Returns the end-moment of the day.
- when = toLatest(*this, when);
- return when.isValid() ? when : QDateTime();
+ When a day ends depends on a how time is described: each day starts and ends
+ earlier for those with higher offsets from UTC and later for those with
+ lower offsets from UTC. The time representation to use can be specified
+ either by a \a spec and \a offsetSeconds (ignored unless \a spec is
+ Qt::OffsetSeconds) or by a time zone.
+
+ Usually, the end of the day is one millisecond before the midnight, 24:00:
+ however, if a local time transition causes the given date to skip over that
+ moment (e.g. a DST spring-forward skipping over 23:00 and the following
+ hour), the actual latest time in the day is returned.
+
+ When \a spec is Qt::OffsetFromUTC, \a offsetSeconds gives the implied zone's
+ offset from UTC. As UTC and such zones have no transitions, the end of the
+ day is QTime(23, 59, 59, 999) in these cases.
+
+ In the rare case of a date that was entirely skipped (this happens when a
+ zone east of the international date-line switches to being west of it), the
+ return shall be invalid. Passing Qt::TimeZone as \a spec (instead of passing
+ a QTimeZone) will also produce an invalid result, as shall dates that end
+ outside the range representable by QDateTime.
+*/
+QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+{
+ QTimeZone zone = asTimeZone(spec, offsetSeconds, "QDate::endOfDay");
+ // If spec was Qt::TimeZone, zone's is Qt::LocalTime.
+ return endOfDay(zone);
}
-#endif // timezone
+#endif // 6.9 deprecation
#if QT_CONFIG(datestring) // depends on, so implies, textdate
@@ -1018,7 +1177,8 @@ static QString toStringTextDate(QDate date)
const QLatin1Char sp(' ');
return QLocale::c().dayName(cal.dayOfWeek(date), QLocale::ShortFormat) + sp
+ cal.monthName(QLocale::c(), parts.month, parts.year, QLocale::ShortFormat)
- + sp + QString::number(parts.day) + sp + QString::number(parts.year);
+ // Documented to use 4-digit year
+ + sp + QString::asprintf("%d %04d", parts.day, parts.year);
}
}
return QString();
@@ -1081,12 +1241,14 @@ QString QDate::toString(Qt::DateFormat format) const
/*!
\fn QString QDate::toString(const QString &format, QCalendar cal) const
\fn QString QDate::toString(QStringView format, QCalendar cal) const
+ \since 5.14
Returns the date as a string. The \a format parameter determines the format
of the result string. If \a cal is supplied, it determines the calendar used
- to represent the date; it defaults to Gregorian.
+ to represent the date; it defaults to Gregorian. Prior to Qt 5.14, there was
+ no \a cal parameter and the Gregorian calendar was always used.
- These expressions may be used:
+ These expressions may be used in the \a format parameter:
\table
\header \li Expression \li Output
@@ -1126,25 +1288,41 @@ QString QDate::toString(Qt::DateFormat format) const
If the datetime is invalid, an empty string will be returned.
- \note If localized month and day names are desired, please switch to using
- QLocale::system().toString() as QDate methods shall change to use English (C
- locale) names at Qt 6.
+ \note Day and month names are given in English (C locale). To get localized
+ month and day names, use QLocale::system().toString().
- \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
+ \note If a format character is repeated more times than the longest
+ expression in the table above using it, this part of the format will be read
+ as several expressions with no separator between them; the longest above,
+ possibly repeated as many times as there are copies of it, ending with a
+ residue that may be a shorter expression. Thus \c{'MMMMMMMMMM'} for a date
+ in May will contribute \c{"MayMay05"} to the output.
+ \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
QString QDate::toString(QStringView format, QCalendar cal) const
{
return QLocale::c().toString(*this, format, cal);
}
-#if QT_STRINGVIEW_LEVEL < 2
-QString QDate::toString(const QString &format, QCalendar cal) const
+// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
+/*!
+ \overload
+ \since 5.10
+*/
+QString QDate::toString(QStringView format) const
{
- return toString(qToStringViewIgnoringNull(format), cal);
+ return QLocale::c().toString(*this, format, QCalendar());
}
-#endif
+/*!
+ \overload
+ \since 4.6
+*/
+QString QDate::toString(const QString &format) const
+{
+ return QLocale::c().toString(*this, qToStringViewIgnoringNull(format), QCalendar());
+}
#endif // datestring
/*!
@@ -1159,11 +1337,9 @@ QString QDate::toString(const QString &format, QCalendar cal) const
*/
bool QDate::setDate(int year, int month, int day)
{
- if (QGregorianCalendar::julianFromParts(year, month, day, &jd))
- return true;
-
- jd = nullJd();
- return false;
+ const auto maybe = QGregorianCalendar::julianFromParts(year, month, day);
+ jd = maybe.value_or(nullJd());
+ return bool(maybe);
}
/*!
@@ -1225,12 +1401,35 @@ QDate QDate::addDays(qint64 ndays) const
if (isNull())
return QDate();
- // Due to limits on minJd() and maxJd() we know that any overflow
- // will be invalid and caught by fromJulianDay().
- return fromJulianDay(jd + ndays);
+ if (qint64 r; Q_UNLIKELY(qAddOverflow(jd, ndays, &r)))
+ return QDate();
+ else
+ return fromJulianDay(r);
}
/*!
+ \fn QDate QDate::addDuration(std::chrono::days ndays) const
+
+ \since 6.4
+
+ Returns a QDate object containing a date \a ndays later than the
+ date of this object (or earlier if \a ndays is negative).
+
+ Returns a null date if the current date is invalid or the new date is
+ out of range.
+
+ \note Adding durations expressed in \c{std::chrono::months} or
+ \c{std::chrono::years} does not yield the same result obtained by using
+ addMonths() or addYears(). The former are fixed durations, calculated in
+ relation to the solar year; the latter use the Gregorian calendar definitions
+ of months/years.
+
+ \note This function requires C++20.
+
+ \sa addMonths(), addYears(), daysTo()
+*/
+
+/*!
Returns a QDate object containing a date \a nmonths later than the
date of this object (or earlier if \a nmonths is negative).
@@ -1268,7 +1467,7 @@ QDate QDate::addMonths(int nmonths, QCalendar cal) const
count = (++parts.year || cal.hasYearZero()) ? cal.monthsInYear(parts.year) : 0;
}
- return fixedDate(std::move(parts), cal);
+ return fixedDate(parts, cal);
}
/*!
@@ -1300,7 +1499,7 @@ QDate QDate::addMonths(int nmonths) const
++parts.year;
}
- return fixedDate(std::move(parts));
+ return fixedDate(parts);
}
/*!
@@ -1329,11 +1528,11 @@ QDate QDate::addYears(int nyears, QCalendar cal) const
int old_y = parts.year;
parts.year += nyears;
- // If we just crossed (or hit) a missing year zero, adjust year by +/- 1:
+ // If we just crossed (or hit) a missing year zero, adjust year by ±1:
if (!cal.hasYearZero() && ((old_y > 0) != (parts.year > 0) || !parts.year))
parts.year += nyears > 0 ? +1 : -1;
- return fixedDate(std::move(parts), cal);
+ return fixedDate(parts, cal);
}
/*!
@@ -1352,11 +1551,11 @@ QDate QDate::addYears(int nyears) const
int old_y = parts.year;
parts.year += nyears;
- // If we just crossed (or hit) a missing year zero, adjust year by +/- 1:
+ // If we just crossed (or hit) a missing year zero, adjust year by ±1:
if ((old_y > 0) != (parts.year > 0) || !parts.year)
parts.year += nyears > 0 ? +1 : -1;
- return fixedDate(std::move(parts));
+ return fixedDate(parts);
}
/*!
@@ -1382,81 +1581,59 @@ qint64 QDate::daysTo(QDate d) const
/*!
- \fn bool QDate::operator==(QDate d) const
+ \fn bool QDate::operator==(const QDate &lhs, const QDate &rhs)
- Returns \c true if this date and \a d represent the same day, otherwise
+ Returns \c true if \a lhs and \a rhs represent the same day, otherwise
\c false.
*/
/*!
- \fn bool QDate::operator!=(QDate d) const
+ \fn bool QDate::operator!=(const QDate &lhs, const QDate &rhs)
- Returns \c true if this date is different from \a d; otherwise
+ Returns \c true if \a lhs and \a rhs represent distinct days; otherwise
returns \c false.
\sa operator==()
*/
/*!
- \fn bool QDate::operator<(QDate d) const
+ \fn bool QDate::operator<(const QDate &lhs, const QDate &rhs)
- Returns \c true if this date is earlier than \a d; otherwise returns
- false.
+ Returns \c true if \a lhs is earlier than \a rhs; otherwise returns \c false.
*/
/*!
- \fn bool QDate::operator<=(QDate d) const
+ \fn bool QDate::operator<=(const QDate &lhs, const QDate &rhs)
- Returns \c true if this date is earlier than or equal to \a d;
+ Returns \c true if \a lhs is earlier than or equal to \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QDate::operator>(QDate d) const
+ \fn bool QDate::operator>(const QDate &lhs, const QDate &rhs)
- Returns \c true if this date is later than \a d; otherwise returns
- false.
+ Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
*/
/*!
- \fn bool QDate::operator>=(QDate d) const
+ \fn bool QDate::operator>=(const QDate &lhs, const QDate &rhs)
- Returns \c true if this date is later than or equal to \a d;
+ Returns \c true if \a lhs is later than or equal to \a rhs;
otherwise returns \c false.
*/
/*!
\fn QDate::currentDate()
- Returns the current date, as reported by the system clock.
+ Returns the system clock's current date.
\sa QTime::currentTime(), QDateTime::currentDateTime()
*/
#if QT_CONFIG(datestring) // depends on, so implies, textdate
-namespace {
-
-struct ParsedInt { int value = 0; bool ok = false; };
-
-/*
- /internal
-
- Read an int that must be the whole text. QStringView ::toInt() will ignore
- spaces happily; but ISO date format should not.
-*/
-ParsedInt readInt(QStringView text)
-{
- ParsedInt result;
- for (const auto &ch : text) {
- if (ch.isSpace())
- return result;
- }
- result.value = QLocale::c().toInt(text, &result.ok);
- return result;
-}
-
-}
/*!
+ \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
+
Returns the QDate represented by the \a string, using the
\a format given, or an invalid date if the string cannot be
parsed.
@@ -1467,7 +1644,11 @@ ParsedInt readInt(QStringView text)
\sa toString(), QLocale::toDate()
*/
-QDate QDate::fromString(const QString &string, Qt::DateFormat format)
+/*!
+ \overload
+ \since 6.0
+*/
+QDate QDate::fromString(QStringView string, Qt::DateFormat format)
{
if (string.isEmpty())
return QDate();
@@ -1477,9 +1658,14 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
return rfcDateImpl(string).date;
default:
case Qt::TextDate: {
- auto parts = QStringView{string}.split(QLatin1Char(' '), Qt::SkipEmptyParts);
-
- if (parts.count() != 4)
+ // Documented as "ddd MMM d yyyy"
+ QVarLengthArray<QStringView, 4> parts;
+ auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
+ auto it = tokens.begin();
+ for (int i = 0; i < 4 && it != tokens.end(); ++i, ++it)
+ parts.emplace_back(*it);
+
+ if (parts.size() != 4 || it != tokens.end())
return QDate();
bool ok = false;
@@ -1496,14 +1682,13 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
}
case Qt::ISODate:
// Semi-strict parsing, must be long enough and have punctuators as separators
- if (string.size() >= 10 && string.at(4).isPunct() && string.at(7).isPunct()
- && (string.size() == 10 || !string.at(10).isDigit())) {
- QStringView view(string);
- const ParsedInt year = readInt(view.mid(0, 4));
- const ParsedInt month = readInt(view.mid(5, 2));
- const ParsedInt day = readInt(view.mid(8, 2));
- if (year.ok && year.value > 0 && year.value <= 9999 && month.ok && day.ok)
- return QDate(year.value, month.value, day.value);
+ if (string.size() >= 10 && string[4].isPunct() && string[7].isPunct()
+ && (string.size() == 10 || !string[10].isDigit())) {
+ const ParsedInt year = readInt(string.first(4));
+ const ParsedInt month = readInt(string.sliced(5, 2));
+ const ParsedInt day = readInt(string.sliced(8, 2));
+ if (year.ok() && year.result > 0 && year.result <= 9999 && month.ok() && day.ok())
+ return QDate(year.result, month.result, day.result);
}
break;
}
@@ -1511,7 +1696,7 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
}
/*!
- \fn QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
+ \fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
Returns the QDate represented by the \a string, using the \a
format given, or an invalid date if the string cannot be parsed.
@@ -1537,9 +1722,8 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
minus sign for negative years.
\endtable
- \note Unlike the other version of this function, day and month names must
- be given in the user's local language. It is only possible to use the English
- names if the user's language is English.
+ \note Day and month names must be given in English (C locale). If localized
+ month and day names are to be recognized, use QLocale::system().toDate().
All other input characters will be treated as text. Any non-empty sequence
of characters enclosed in single quotes will also be treated (stripped of
@@ -1562,38 +1746,157 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
\table
\header \li Field \li Default value
- \row \li Year \li 1900
- \row \li Month \li 1
+ \row \li Year \li \a baseYear (or 1900)
+ \row \li Month \li 1 (January)
\row \li Day \li 1
\endtable
+ When \a format only specifies the last two digits of a year, the 100 years
+ starting at \a baseYear are the candidates first considered. Prior to 6.7
+ there was no \a baseYear parameter and 1900 was always used. This is the
+ default for \a baseYear, selecting a year from then to 1999. Passing 1976 as
+ \a baseYear will select a year from 1976 through 2075, for example. When the
+ format also includes month, day (of month) and day-of-week, these suffice to
+ imply the century. In such a case, a matching date is selected in the
+ nearest century to the one indicated by \a baseYear, prefering later over
+ earlier. See \l QCalendar::matchCenturyToWeekday() and \l {Date ambiguities}
+ for further details,
+
The following examples demonstrate the default values:
\snippet code/src_corelib_time_qdatetime.cpp 3
- \note If localized month and day names are used, please switch to using
- QLocale::system().toDate() as QDate methods shall change to only recognize
- English (C locale) names at Qt 6.
+ \note If a format character is repeated more times than the longest
+ expression in the table above using it, this part of the format will be read
+ as several expressions with no separator between them; the longest above,
+ possibly repeated as many times as there are copies of it, ending with a
+ residue that may be a shorter expression. Thus \c{'MMMMMMMMMM'} would match
+ \c{"MayMay05"} and set the month to May. Likewise, \c{'MMMMMM'} would match
+ \c{"May08"} and find it inconsistent, leading to an invalid date.
+
+ \section2 Date ambiguities
+
+ Different cultures use different formats for dates and, as a result, users
+ may mix up the order in which date fields should be given. For example,
+ \c{"Wed 28-Nov-01"} might mean either 2028 November 1st or the 28th of
+ November, 2001 (each of which happens to be a Wednesday). Using format
+ \c{"ddd yy-MMM-dd"} it shall be interpreted the first way, using \c{"ddd
+ dd-MMM-yy"} the second. However, which the user meant may depend on the way
+ the user normally writes dates, rather than the format the code was
+ expecting.
+
+ The example considered above mixed up day of the month and a two-digit year.
+ Similar confusion can arise over interchanging the month and day of the
+ month, when both are given as numbers. In these cases, including a day of
+ the week field in the date format can provide some redundancy, that may help
+ to catch errors of this kind. However, as in the example above, this is not
+ always effective: the interchange of two fields (or their meanings) may
+ produce dates with the same day of the week.
+
+ Including a day of the week in the format can also resolve the century of a
+ date specified using only the last two digits of its year. Unfortunately,
+ when combined with a date in which the user (or other source of data) has
+ mixed up two of the fields, this resolution can lead to finding a date which
+ does match the format's reading but isn't the one intended by its author.
+ Likewise, if the user simply gets the day of the week wrong, in an otherwise
+ correct date, this can lead a date in a different century. In each case,
+ finding a date in a different century can turn a wrongly-input date into a
+ wildly different one.
+
+ The best way to avoid date ambiguities is to use four-digit years and months
+ specified by name (whether full or abbreviated), ideally collected via user
+ interface idioms that make abundantly clear to the user which part of the
+ date they are selecting. Including a day of the week can also help by
+ providing the means to check consistency of the data. Where data comes from
+ the user, using a format supplied by a locale selected by the user, it is
+ best to use a long format as short formats are more likely to use two-digit
+ years. Of course, it is not always possible to control the format - data may
+ come from a source you do not control, for example.
+
+ As a result of these possible sources of confusion, particularly when you
+ cannot be sure an unambiguous format is in use, it is important to check
+ that the result of reading a string as a date is not just valid but
+ reasonable for the purpose for which it was supplied. If the result is
+ outside some range of reasonable values, it may be worth getting the user to
+ confirm their date selection, showing the date read from the string in a
+ long format that does include month name and four-digit year, to make it
+ easier for them to recognize any errors.
\sa toString(), QDateTime::fromString(), QTime::fromString(),
QLocale::toDate()
*/
-QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
+/*!
+ \fn QDate QDate::fromString(QStringView string, QStringView format, QCalendar cal)
+ \overload
+ \since 6.0
+*/
+
+/*!
+ \overload
+ \since 6.0
+*/
+QDate QDate::fromString(const QString &string, QStringView format, int baseYear, QCalendar cal)
{
QDate date;
#if QT_CONFIG(datetimeparser)
QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
dt.setDefaultLocale(QLocale::c());
if (dt.parseFormat(format))
- dt.fromString(string, &date, nullptr);
+ dt.fromString(string, &date, nullptr, baseYear);
#else
Q_UNUSED(string);
Q_UNUSED(format);
+ Q_UNUSED(baseYear);
Q_UNUSED(cal);
#endif
return date;
}
+
+/*!
+ \fn QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
+ \overload
+ \since 5.14
+*/
+
+/*!
+ \fn QDate QDate::fromString(const QString &string, QStringView format, QCalendar cal)
+ \overload
+ \since 6.0
+*/
+
+/*!
+ \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
+ \overload
+ \since 6.7
+*/
+
+/*!
+ \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear)
+ \overload
+ \since 6.7
+
+ Uses a default-constructed QCalendar.
+*/
+
+/*!
+ \overload
+ \since 6.7
+
+ Uses a default-constructed QCalendar.
+*/
+QDate QDate::fromString(const QString &string, QStringView format, int baseYear)
+{
+ return fromString(string, format, baseYear, QCalendar());
+}
+
+/*!
+ \fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear)
+ \overload
+ \since 6.7
+
+ Uses a default-constructed QCalendar.
+*/
#endif // datestring
/*!
@@ -1652,10 +1955,13 @@ bool QDate::isLeapYear(int y)
\brief The QTime class provides clock time functions.
+ \compares strong
+
A QTime object contains a clock time, which it can express as the numbers of
hours, minutes, seconds, and milliseconds since midnight. It provides
functions for comparing times and for manipulating a time by adding a number
- of milliseconds.
+ of milliseconds. QTime objects should be passed by value rather than by
+ reference to const; they simply package \c int.
QTime uses the 24-hour clock format; it has no concept of AM/PM.
Unlike QDateTime, QTime knows nothing about time zones or
@@ -1782,7 +2088,7 @@ int QTime::second() const
if (!isValid())
return -1;
- return (ds() / 1000)%SECS_PER_MIN;
+ return (ds() / MSECS_PER_SEC) % SECS_PER_MIN;
}
/*!
@@ -1798,7 +2104,7 @@ int QTime::msec() const
if (!isValid())
return -1;
- return ds() % 1000;
+ return ds() % MSECS_PER_SEC;
}
#if QT_CONFIG(datestring) // depends on, so implies, textdate
@@ -1865,19 +2171,49 @@ QString QTime::toString(Qt::DateFormat format) const
\row \li mm \li The minute with a leading zero (00 to 59)
\row \li s \li The whole second, without any leading zero (0 to 59)
\row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
- \row \li z \li The fractional part of the second, to go after a decimal
- point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
- reports the seconds to full available (millisecond) precision
- without trailing zeroes.
- \row \li zzz \li The fractional part of the second, to millisecond
- precision, including trailing zeroes where applicable (000 to 999).
+ \row \li z or zz
+ \li The fractional part of the second, to go after a decimal point,
+ without trailing zeroes. Thus \c{"s.z"} reports the seconds to full
+ available (millisecond) precision without trailing zeroes (0 to
+ 999). For example, \c{"s.z"} would produce \c{"0.25"} for a time a
+ quarter second into a minute.
+ \row \li zzz
+ \li The fractional part of the second, to millisecond precision,
+ including trailing zeroes where applicable (000 to 999). For
+ example, \c{"ss.zzz"} would produce \c{"00.250"} for a time a
+ quarter second into a minute.
\row \li AP or A
- \li Use AM/PM display. \e A/AP will be replaced by an upper-case
- version of either QLocale::amText() or QLocale::pmText().
+ \li Use AM/PM display. \c A/AP will be replaced by 'AM' or 'PM'. In
+ localized forms (only relevant to \l{QLocale::toString()}), the
+ locale-appropriate text is converted to upper-case.
\row \li ap or a
- \li Use am/pm display. \e a/ap will be replaced by a lower-case version
- of either QLocale::amText() or QLocale::pmText().
- \row \li t \li The timezone (for example "CEST")
+ \li Use am/pm display. \c a/ap will be replaced by 'am' or 'pm'. In
+ localized forms (only relevant to \l{QLocale::toString()}), the
+ locale-appropriate text is converted to lower-case.
+ \row \li aP or Ap
+ \li Use AM/PM display (since 6.3). \c aP/Ap will be replaced by 'AM' or
+ 'PM'. In localized forms (only relevant to
+ \l{QLocale::toString()}), the locale-appropriate text (returned by
+ \l{QLocale::amText()} or \l{QLocale::pmText()}) is used without
+ change of case.
+ \row \li t
+ \li The timezone abbreviation (for example "CEST"). Note that time zone
+ abbreviations are not unique. In particular, \l toString() cannot
+ parse this.
+ \row \li tt
+ \li The timezone's offset from UTC with no colon between the hours and
+ minutes (for example "+0200").
+ \row \li ttt
+ \li The timezone's offset from UTC with a colon between the hours and
+ minutes (for example "+02:00").
+ \row \li tttt
+ \li The timezone name (for example "Europe/Berlin"). Note that this
+ gives no indication of whether the datetime was in daylight-saving
+ time or standard time, which may lead to ambiguity if the datetime
+ falls in an hour repeated by a transition between the two. The name
+ used is the one provided by \l QTimeZone::displayName() with the \l
+ QTimeZone::LongName type. This may depend on the operating system
+ in use.
\endtable
Any non-empty sequence of characters enclosed in single quotes will be
@@ -1891,8 +2227,7 @@ QString QTime::toString(Qt::DateFormat format) const
produces "212" it could mean either the 2nd of December or the 21st of
February).
- Example format strings (assuming that the QTime is 14:13:09.042 and the system
- locale is \c{en_US})
+ Example format strings (assuming that the QTime is 14:13:09.042)
\table
\header \li Format \li Result
@@ -1902,26 +2237,24 @@ QString QTime::toString(Qt::DateFormat format) const
\endtable
If the time is invalid, an empty string will be returned.
- If \a format is empty, the default format "hh:mm:ss" is used.
- \note If localized forms of am or pm (the AP, ap, A or a formats) are
- desired, please switch to using QLocale::system().toString() as QTime
- methods shall change to use English (C locale) at Qt 6.
+ \note To get localized forms of AM or PM (the AP, ap, A, a, aP or Ap
+ formats), use QLocale::system().toString().
+
+ \note If a format character is repeated more times than the longest
+ expression in the table above using it, this part of the format will be read
+ as several expressions with no separator between them; the longest above,
+ possibly repeated as many times as there are copies of it, ending with a
+ residue that may be a shorter expression. Thus \c{'HHHHH'} for the time
+ 08:00 will contribute \c{"08088"} to the output.
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
+// ### Qt 7 The 't' format specifiers should be specific to QDateTime (compare fromString).
QString QTime::toString(QStringView format) const
{
return QLocale::c().toString(*this, format);
}
-
-#if QT_STRINGVIEW_VERSION < 2
-QString QTime::toString(const QString &format) const
-{
- return toString(qToStringViewIgnoringNull(format));
-}
-#endif
-
#endif // datestring
/*!
@@ -1941,7 +2274,8 @@ bool QTime::setHMS(int h, int m, int s, int ms)
mds = NullTime; // make this invalid
return false;
}
- mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
+ mds = ((h * MINS_PER_HOUR + m) * SECS_PER_MIN + s) * MSECS_PER_SEC + ms;
+ Q_ASSERT(mds >= 0 && mds < MSECS_PER_DAY);
return true;
}
@@ -1963,7 +2297,7 @@ bool QTime::setHMS(int h, int m, int s, int ms)
QTime QTime::addSecs(int s) const
{
s %= SECS_PER_DAY;
- return addMSecs(s * 1000);
+ return addMSecs(s * MSECS_PER_SEC);
}
/*!
@@ -1987,8 +2321,8 @@ int QTime::secsTo(QTime t) const
return 0;
// Truncate milliseconds as we do not want to consider them.
- int ourSeconds = ds() / 1000;
- int theirSeconds = t.ds() / 1000;
+ int ourSeconds = ds() / MSECS_PER_SEC;
+ int theirSeconds = t.ds() / MSECS_PER_SEC;
return theirSeconds - ourSeconds;
}
@@ -2007,15 +2341,8 @@ int QTime::secsTo(QTime t) const
QTime QTime::addMSecs(int ms) const
{
QTime t;
- if (isValid()) {
- if (ms < 0) {
- // %,/ not well-defined for -ve, so always work with +ve.
- int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
- t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
- } else {
- t.mds = (ds() + ms) % MSECS_PER_DAY;
- }
- }
+ if (isValid())
+ t.mds = QRoundingDown::qMod<MSECS_PER_DAY>(ds() + ms);
return t;
}
@@ -2042,40 +2369,40 @@ int QTime::msecsTo(QTime t) const
/*!
- \fn bool QTime::operator==(QTime t) const
+ \fn bool QTime::operator==(const QTime &lhs, const QTime &rhs)
- Returns \c true if this time is equal to \a t; otherwise returns \c false.
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
*/
/*!
- \fn bool QTime::operator!=(QTime t) const
+ \fn bool QTime::operator!=(const QTime &lhs, const QTime &rhs)
- Returns \c true if this time is different from \a t; otherwise returns \c false.
+ Returns \c true if \a lhs is different from \a rhs; otherwise returns \c false.
*/
/*!
- \fn bool QTime::operator<(QTime t) const
+ \fn bool QTime::operator<(const QTime &lhs, const QTime &rhs)
- Returns \c true if this time is earlier than \a t; otherwise returns \c false.
+ Returns \c true if \a lhs is earlier than \a rhs; otherwise returns \c false.
*/
/*!
- \fn bool QTime::operator<=(QTime t) const
+ \fn bool QTime::operator<=(const QTime &lhs, const QTime &rhs)
- Returns \c true if this time is earlier than or equal to \a t;
+ Returns \c true if \a lhs is earlier than or equal to \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QTime::operator>(QTime t) const
+ \fn bool QTime::operator>(const QTime &lhs, const QTime &rhs)
- Returns \c true if this time is later than \a t; otherwise returns \c false.
+ Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
*/
/*!
- \fn bool QTime::operator>=(QTime t) const
+ \fn bool QTime::operator>=(const QTime &lhs, const QTime &rhs)
- Returns \c true if this time is later than or equal to \a t;
+ Returns \c true if \a lhs is later than or equal to \a rhs;
otherwise returns \c false.
*/
@@ -2117,97 +2444,121 @@ int QTime::msecsTo(QTime t) const
static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
{
+ Q_ASSERT(format == Qt::TextDate || format == Qt::ISODate || format == Qt::ISODateWithMs);
if (isMidnight24)
*isMidnight24 = false;
+ // Match /\d\d(:\d\d(:\d\d)?)?([,.]\d+)?/ as "HH[:mm[:ss]][.zzz]"
+ // The fractional part, if present, is in the same units as the field it follows.
+ // TextDate restricts fractional parts to the seconds field.
+
+ QStringView tail;
+ const qsizetype dot = string.indexOf(u'.'), comma = string.indexOf(u',');
+ if (dot != -1) {
+ tail = string.sliced(dot + 1);
+ if (tail.indexOf(u'.') != -1) // Forbid second dot:
+ return QTime();
+ string = string.first(dot);
+ } else if (comma != -1) {
+ tail = string.sliced(comma + 1);
+ string = string.first(comma);
+ }
+ if (tail.indexOf(u',') != -1) // Forbid comma after first dot-or-comma:
+ return QTime();
- const int size = string.size();
- if (size < 5 || string.at(2) != QLatin1Char(':'))
+ const ParsedInt frac = readInt(tail);
+ // There must be *some* digits in a fractional part; and it must be all digits:
+ if (tail.isEmpty() ? dot != -1 || comma != -1 : !frac.ok())
return QTime();
+ Q_ASSERT(frac.ok() ^ tail.isEmpty());
+ double fraction = frac.ok() ? frac.result * std::pow(0.1, tail.size()) : 0.0;
- ParsedInt hour = readInt(string.mid(0, 2));
- ParsedInt minute = readInt(string.mid(3, 2));
- if (!hour.ok || !minute.ok)
+ const qsizetype size = string.size();
+ if (size < 2 || size > 8)
return QTime();
- // FIXME: ISO 8601 allows [,.]\d+ after hour, just as it does after minute
- int second = 0;
- int msec = 0;
+ ParsedInt hour = readInt(string.first(2));
+ if (!hour.ok() || hour.result > (format == Qt::TextDate ? 23 : 24))
+ return QTime();
- if (size == 5) {
- // HH:mm format
- second = 0;
- msec = 0;
- } else if (string.at(5) == QLatin1Char(',') || string.at(5) == QLatin1Char('.')) {
- if (format == Qt::TextDate)
+ ParsedInt minute{};
+ if (string.size() > 2) {
+ if (string[2] == u':' && string.size() > 4)
+ minute = readInt(string.sliced(3, 2));
+ if (!minute.ok() || minute.result >= MINS_PER_HOUR)
return QTime();
- // ISODate HH:mm.ssssss format
- // We only want 5 digits worth of fraction of minute. This follows the existing
- // behavior that determines how milliseconds are read; 4 millisecond digits are
- // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
- // the maximum amount of millisecond digits it will expand to once converted to
- // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
- // will then be rounded up AND clamped to 999.
-
- const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
- const ParsedInt parsed = readInt(minuteFractionStr);
- if (!parsed.ok)
+ } else if (format == Qt::TextDate) { // Requires minutes
+ return QTime();
+ } else if (frac.ok()) {
+ Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
+ fraction *= MINS_PER_HOUR;
+ minute.result = qulonglong(fraction);
+ fraction -= minute.result;
+ }
+
+ ParsedInt second{};
+ if (string.size() > 5) {
+ if (string[5] == u':' && string.size() == 8)
+ second = readInt(string.sliced(6, 2));
+ if (!second.ok() || second.result >= SECS_PER_MIN)
return QTime();
- const float secondWithMs
- = double(parsed.value) * 60 / (std::pow(double(10), minuteFractionStr.size()));
-
- second = std::floor(secondWithMs);
- const float secondFraction = secondWithMs - second;
- msec = qMin(qRound(secondFraction * 1000.0), 999);
- } else if (string.at(5) == QLatin1Char(':')) {
- // HH:mm:ss or HH:mm:ss.zzz
- const ParsedInt parsed = readInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)));
- if (!parsed.ok)
+ } else if (frac.ok()) {
+ if (format == Qt::TextDate) // Doesn't allow fraction of minutes
return QTime();
- second = parsed.value;
- if (size <= 8) {
- // No fractional part to read
- } else if (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.')) {
- QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
- bool ok = true;
- // Can't use readInt() here, as we *do* allow trailing space - but not leading:
- if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
- return QTime();
- msecStr = msecStr.trimmed();
- int msecInt = msecStr.isEmpty() ? 0 : QLocale::c().toInt(msecStr, &ok);
- if (!ok)
- return QTime();
- const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
- msec = qMin(qRound(secondFraction * 1000.0), 999);
- } else {
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) // behavior change
- // Stray cruft after date-time: tolerate trailing space, but nothing else.
- for (const auto &ch : string.mid(8)) {
- if (!ch.isSpace())
- return QTime();
+ Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
+ fraction *= SECS_PER_MIN;
+ second.result = qulonglong(fraction);
+ fraction -= second.result;
+ }
+
+ Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
+ // Round millis to nearest (unlike minutes and seconds, rounded down):
+ int msec = frac.ok() ? qRound(MSECS_PER_SEC * fraction) : 0;
+ // But handle overflow gracefully:
+ if (msec == MSECS_PER_SEC) {
+ // If we can (when data were otherwise valid) validly propagate overflow
+ // into other fields, do so:
+ if (isMidnight24 || hour.result < 23 || minute.result < 59 || second.result < 59) {
+ msec = 0;
+ if (++second.result == SECS_PER_MIN) {
+ second.result = 0;
+ if (++minute.result == MINS_PER_HOUR) {
+ minute.result = 0;
+ ++hour.result;
+ // May need to propagate further via isMidnight24, see below
+ }
}
-#endif
+ } else {
+ // QTime::fromString() or Qt::TextDate: rounding up would cause
+ // 23:59:59.999... to become invalid; clip to 999 ms instead:
+ msec = MSECS_PER_SEC - 1;
}
- } else {
- return QTime();
}
- const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
- if (isISODate && hour.value == 24 && minute.value == 0 && second == 0 && msec == 0) {
+ // For ISO date format, 24:0:0 means 0:0:0 on the next day:
+ if (hour.result == 24 && minute.result == 0 && second.result == 0 && msec == 0) {
+ Q_ASSERT(format != Qt::TextDate); // It clipped hour at 23, above.
if (isMidnight24)
*isMidnight24 = true;
- hour.value = 0;
+ hour.result = 0;
}
- return QTime(hour.value, minute.value, second, msec);
+ return QTime(hour.result, minute.result, second.result, msec);
}
/*!
+ \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
+
Returns the time represented in the \a string as a QTime using the
\a format given, or an invalid time if this is not possible.
\sa toString(), QLocale::toTime()
*/
-QTime QTime::fromString(const QString &string, Qt::DateFormat format)
+
+/*!
+ \overload
+ \since 6.0
+*/
+QTime QTime::fromString(QStringView string, Qt::DateFormat format)
{
if (string.isEmpty())
return QTime();
@@ -2219,11 +2570,13 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
case Qt::ISODateWithMs:
case Qt::TextDate:
default:
- return fromIsoTimeString(QStringView(string), format, nullptr);
+ return fromIsoTimeString(string, format, nullptr);
}
}
/*!
+ \fn QTime QTime::fromString(const QString &string, const QString &format)
+
Returns the QTime represented by the \a string, using the \a
format given, or an invalid time if the string cannot be parsed.
@@ -2243,18 +2596,23 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
\row \li mm \li The minute with a leading zero (00 to 59)
\row \li s \li The whole second, without any leading zero (0 to 59)
\row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
- \row \li z \li The fractional part of the second, to go after a decimal
- point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
- reports the seconds to full available (millisecond) precision
- without trailing zeroes.
- \row \li zzz \li The fractional part of the second, to millisecond
- precision, including trailing zeroes where applicable (000 to 999).
- \row \li AP or A
- \li Interpret as an AM/PM time. \e A/AP will match an upper-case
- version of either QLocale::amText() or QLocale::pmText().
- \row \li ap or a
- \li Interpret as an am/pm time. \e a/ap will match a lower-case version
- of either QLocale::amText() or QLocale::pmText().
+ \row \li z or zz
+ \li The fractional part of the second, as would usually follow a
+ decimal point, without requiring trailing zeroes (0 to 999). Thus
+ \c{"s.z"} matches the seconds with up to three digits of fractional
+ part supplying millisecond precision, without needing trailing
+ zeroes. For example, \c{"s.z"} would recognize either \c{"00.250"}
+ or \c{"0.25"} as representing a time a quarter second into its
+ minute.
+ \row \li zzz
+ \li Three digit fractional part of the second, to millisecond
+ precision, including trailing zeroes where applicable (000 to 999).
+ For example, \c{"ss.zzz"} would reject \c{"0.25"} but recognize
+ \c{"00.250"} as representing a time a quarter second into its
+ minute.
+ \row \li AP, A, ap, a, aP or Ap
+ \li Either 'AM' indicating a time before 12:00 or 'PM' for later times,
+ matched case-insensitively.
\endtable
All other input characters will be treated as text. Any non-empty sequence
@@ -2265,7 +2623,7 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
If the format is not satisfied, an invalid QTime is returned.
Expressions that do not expect leading zeroes to be given (h, m, s
- and z) are greedy. This means that they will use two digits even if
+ and z) are greedy. This means that they will use two digits (or three, for z) even if
this puts them outside the range of accepted values and leaves too
few digits for other sections. For example, the following string
could have meant 00:07:10, but the m will grab two digits, resulting
@@ -2278,15 +2636,33 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
\snippet code/src_corelib_time_qdatetime.cpp 8
- \note If localized forms of am or pm (the AP, ap, A or a formats) are used,
- please switch to using QLocale::system().toTime() as QTime methods shall
- change to only recognize English (C locale) at Qt 6.
+ \note If localized forms of am or pm (the AP, ap, Ap, aP, A or a formats)
+ are to be recognized, use QLocale::system().toTime().
+
+ \note If a format character is repeated more times than the longest
+ expression in the table above using it, this part of the format will be read
+ as several expressions with no separator between them; the longest above,
+ possibly repeated as many times as there are copies of it, ending with a
+ residue that may be a shorter expression. Thus \c{'HHHHH'} would match
+ \c{"08088"} or \c{"080808"} and set the hour to 8; if the time string
+ contained "070809" it would "match" but produce an inconsistent result,
+ leading to an invalid time.
\sa toString(), QDateTime::fromString(), QDate::fromString(),
- QLocale::toTime()
+ QLocale::toTime(), QLocale::toDateTime()
+*/
+
+/*!
+ \fn QTime QTime::fromString(QStringView string, QStringView format)
+ \overload
+ \since 6.0
*/
-QTime QTime::fromString(const QString &string, const QString &format)
+/*!
+ \overload
+ \since 6.0
+*/
+QTime QTime::fromString(const QString &string, QStringView format)
{
QTime time;
#if QT_CONFIG(datetimeparser)
@@ -2300,7 +2676,6 @@ QTime QTime::fromString(const QString &string, const QString &format)
#endif
return time;
}
-
#endif // datestring
@@ -2320,7 +2695,8 @@ QTime QTime::fromString(const QString &string, const QString &format)
bool QTime::isValid(int h, int m, int s, int ms)
{
- return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
+ return (uint(h) < 24 && uint(m) < MINS_PER_HOUR && uint(s) < SECS_PER_MIN
+ && uint(ms) < MSECS_PER_SEC);
}
/*****************************************************************************
@@ -2331,371 +2707,353 @@ bool QTime::isValid(int h, int m, int s, int ms)
typedef QDateTimePrivate::QDateTimeShortData ShortData;
typedef QDateTimePrivate::QDateTimeData QDateTimeData;
-// Returns the platform variant of timezone, i.e. the standard time offset
-// The timezone external variable is documented as always holding the
-// Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600
-// Note this may not be historicaly accurate.
-// Relies on tzset, mktime, or localtime having been called to populate timezone
-static int qt_timezone()
-{
-#if defined(_MSC_VER)
- long offset;
- _get_timezone(&offset);
- return offset;
-#elif defined(Q_OS_BSD4) && !defined(Q_OS_DARWIN)
- time_t clock = time(NULL);
- struct tm t;
- localtime_r(&clock, &t);
- // QTBUG-36080 Workaround for systems without the POSIX timezone
- // variable. This solution is not very efficient but fixing it is up to
- // the libc implementations.
- //
- // tm_gmtoff has some important differences compared to the timezone
- // variable:
- // - It returns the number of seconds east of UTC, and we want the
- // number of seconds west of UTC.
- // - It also takes DST into account, so we need to adjust it to always
- // get the Standard Time offset.
- return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
-#elif defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
- return 0;
-#else
- return timezone;
-#endif // Q_OS_WIN
+// Converts milliseconds since the start of 1970 into a date and/or time:
+static qint64 msecsToJulianDay(qint64 msecs)
+{
+ return JULIAN_DAY_FOR_EPOCH + QRoundingDown::qDiv<MSECS_PER_DAY>(msecs);
}
-// Returns the tzname, assume tzset has been called already
-static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
+static QDate msecsToDate(qint64 msecs)
{
- int isDst = (daylightStatus == QDateTimePrivate::DaylightTime) ? 1 : 0;
-#if defined(Q_CC_MSVC)
- size_t s = 0;
- char name[512];
- if (_get_tzname(&s, name, 512, isDst))
- return QString();
- return QString::fromLocal8Bit(name);
-#else
- return QString::fromLocal8Bit(tzname[isDst]);
-#endif // Q_OS_WIN
+ return QDate::fromJulianDay(msecsToJulianDay(msecs));
}
-#if QT_CONFIG(datetimeparser)
-/*
- \internal
- Implemented here to share qt_tzname()
-*/
-int QDateTimeParser::startsWithLocalTimeZone(QStringView name)
+static QTime msecsToTime(qint64 msecs)
{
- QDateTimePrivate::DaylightStatus zones[2] = {
- QDateTimePrivate::StandardTime,
- QDateTimePrivate::DaylightTime
- };
- for (const auto z : zones) {
- QString zone(qt_tzname(z));
- if (name.startsWith(zone))
- return zone.size();
- }
- return 0;
+ return QTime::fromMSecsSinceStartOfDay(QRoundingDown::qMod<MSECS_PER_DAY>(msecs));
}
-#endif // datetimeparser
-
-// Calls the platform variant of mktime for the given date, time and daylightStatus,
-// and updates the date, time, daylightStatus and abbreviation with the returned values
-// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
-// then null date/time will be returned, you should adjust the date first if
-// you need a guaranteed result.
-static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
- QString *abbreviation, bool *ok = nullptr)
-{
- const qint64 msec = time->msec();
- int yy, mm, dd;
- date->getDate(&yy, &mm, &dd);
-
- // All other platforms provide standard C library time functions
- tm local;
- memset(&local, 0, sizeof(local)); // tm_[wy]day plus any non-standard fields
- local.tm_sec = time->second();
- local.tm_min = time->minute();
- local.tm_hour = time->hour();
- local.tm_mday = dd;
- local.tm_mon = mm - 1;
- local.tm_year = yy - 1900;
- local.tm_isdst = daylightStatus ? int(*daylightStatus) : -1;
-#if defined(Q_OS_WIN)
- int hh = local.tm_hour;
-#endif // Q_OS_WIN
- time_t secsSinceEpoch = qMkTime(&local);
- if (secsSinceEpoch != time_t(-1)) {
- *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
- *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
-#if defined(Q_OS_WIN)
- // Windows mktime for the missing hour subtracts 1 hour from the time
- // instead of adding 1 hour. If time differs and is standard time then
- // this has happened, so add 2 hours to the time and 1 hour to the msecs
- if (local.tm_isdst == 0 && local.tm_hour != hh) {
- if (time->hour() >= 22)
- *date = date->addDays(1);
- *time = time->addSecs(2 * SECS_PER_HOUR);
- secsSinceEpoch += SECS_PER_HOUR;
- local.tm_isdst = 1;
- }
-#endif // Q_OS_WIN
- if (local.tm_isdst >= 1) {
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::DaylightTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::DaylightTime);
- } else if (local.tm_isdst == 0) {
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::StandardTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
- } else {
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
- }
- if (ok)
- *ok = true;
- } else {
- *date = QDate();
- *time = QTime();
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- if (abbreviation)
- *abbreviation = QString();
- if (ok)
- *ok = false;
- }
+// True if combining days with millis overflows; otherwise, stores result in *sumMillis
+// The inputs should not have opposite signs.
+static inline bool daysAndMillisOverflow(qint64 days, qint64 millisInDay, qint64 *sumMillis)
+{
+ return qMulOverflow(days, std::integral_constant<qint64, MSECS_PER_DAY>(), sumMillis)
+ || qAddOverflow(*sumMillis, millisInDay, sumMillis);
+}
- return ((qint64)secsSinceEpoch * 1000) + msec;
-}
-
-// Calls the platform variant of localtime for the given msecs, and updates
-// the date, time, and DST status with the returned values.
-static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localTime,
- QDateTimePrivate::DaylightStatus *daylightStatus)
-{
- const time_t secsSinceEpoch = msecsSinceEpoch / 1000;
- const int msec = msecsSinceEpoch % 1000;
-
- tm local;
- bool valid = false;
-
- // localtime() is specified to work as if it called tzset().
- // localtime_r() does not have this constraint, so make an explicit call.
- // The explicit call should also request the timezone info be re-parsed.
- qTzSet();
-#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
- // Use the reentrant version of localtime() where available
- // as is thread-safe and doesn't use a shared static data area
- tm *res = nullptr;
- res = localtime_r(&secsSinceEpoch, &local);
- if (res)
- valid = true;
-#elif defined(Q_CC_MSVC)
- if (!_localtime64_s(&local, &secsSinceEpoch))
- valid = true;
-#else
- // Returns shared static data which may be overwritten at any time
- // So copy the result asap
- tm *res = nullptr;
- res = localtime(&secsSinceEpoch);
- if (res) {
- local = *res;
- valid = true;
+// Converts a date/time value into msecs
+static qint64 timeToMSecs(QDate date, QTime time)
+{
+ qint64 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
+ qint64 msecs, dayms = time.msecsSinceStartOfDay();
+ if (days < 0 && dayms > 0) {
+ ++days;
+ dayms -= MSECS_PER_DAY;
}
-#endif
- if (valid) {
- *localDate = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
- *localTime = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
- if (daylightStatus) {
- if (local.tm_isdst > 0)
- *daylightStatus = QDateTimePrivate::DaylightTime;
- else if (local.tm_isdst < 0)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- else
- *daylightStatus = QDateTimePrivate::StandardTime;
- }
- return true;
- } else {
- *localDate = QDate();
- *localTime = QTime();
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- return false;
+ if (daysAndMillisOverflow(days, dayms, &msecs)) {
+ using Bound = std::numeric_limits<qint64>;
+ return days < 0 ? Bound::min() : Bound::max();
}
+ return msecs;
}
-// Converts an msecs value into a date and time
-static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
+/*!
+ \internal
+ Tests whether system functions can handle a given time.
+
+ The range of milliseconds for which the time_t-based functions work depends
+ somewhat on platform (see computeSystemMillisRange() for details). This
+ function tests whether the UTC time \a millis milliseconds from the epoch is
+ in the supported range.
+
+ To test a local time, pass an upper bound on the magnitude of time-zone
+ correction potentially needed as \a slack: in this case the range is
+ extended by this many milliseconds at each end (where applicable). The
+ function then returns true precisely if \a millis is within this (possibly)
+ widened range. This doesn't guarantee that the time_t functions can handle
+ the time, so check their returns to be sure. Values for which the function
+ returns false should be assumed unrepresentable.
+*/
+static inline bool millisInSystemRange(qint64 millis, qint64 slack = 0)
{
- qint64 jd = JULIAN_DAY_FOR_EPOCH;
- qint64 ds = 0;
+ static const auto bounds = QLocalTime::computeSystemMillisRange();
+ return (bounds.minClip || millis >= bounds.min - slack)
+ && (bounds.maxClip || millis <= bounds.max + slack);
+}
+
+/*!
+ \internal
+ Returns a year, in the system range, with the same day-of-week pattern
+
+ Returns the number of a year, in the range supported by system time_t
+ functions, that starts and ends on the same days of the week as \a year.
+ This implies it is a leap year precisely if \a year is. If year is before
+ the epoch, a year early in the supported range is used; otherwise, one late
+ in that range. For a leap year, this may be as much as 26 years years from
+ the range's relevant end; for normal years at most a decade from the end.
- if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
- jd += msecs / MSECS_PER_DAY;
- msecs %= MSECS_PER_DAY;
+ This ensures that any DST rules based on, e.g., the last Sunday in a
+ particular month will select the same date in the returned year as they
+ would if applied to \a year. Of course, the zone's rules may be different in
+ \a year than in the selected year, but it's hard to do better.
+*/
+static int systemTimeYearMatching(int year)
+{
+#if defined(Q_OS_WIN) || defined(Q_OS_WASM)// They don't support times before the epoch
+ static constexpr int forLeapEarly[] = { 1984, 1996, 1980, 1992, 1976, 1988, 1972 };
+ static constexpr int regularEarly[] = { 1978, 1973, 1974, 1975, 1970, 1971, 1977 };
+#else // First year fully in 32-bit time_t range is 1902
+ static constexpr int forLeapEarly[] = { 1928, 1912, 1924, 1908, 1920, 1904, 1916 };
+ static constexpr int regularEarly[] = { 1905, 1906, 1907, 1902, 1903, 1909, 1910 };
+#endif
+ static constexpr int forLeapLate[] = { 2012, 2024, 2036, 2020, 2032, 2016, 2028 };
+ static constexpr int regularLate[] = { 2034, 2035, 2030, 2031, 2037, 2027, 2033 };
+ const int dow = QGregorianCalendar::yearStartWeekDay(year);
+ Q_ASSERT(dow == QDate(year, 1, 1).dayOfWeek());
+ const int res = (QGregorianCalendar::leapTest(year)
+ ? (year < 1970 ? forLeapEarly : forLeapLate)
+ : (year < 1970 ? regularEarly : regularLate))[dow == 7 ? 0 : dow];
+ Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == dow);
+ Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
+ return res;
+}
+
+// Sets up d and status to represent local time at the given UTC msecs since epoch:
+QDateTimePrivate::ZoneState QDateTimePrivate::expressUtcAsLocal(qint64 utcMSecs)
+{
+ ZoneState result{utcMSecs};
+ // Within the time_t supported range, localtime() can handle it:
+ if (millisInSystemRange(utcMSecs)) {
+ result = QLocalTime::utcToLocal(utcMSecs);
+ if (result.valid)
+ return result;
}
- if (msecs < 0) {
- ds = MSECS_PER_DAY - msecs - 1;
- jd -= ds / MSECS_PER_DAY;
- ds = ds % MSECS_PER_DAY;
- ds = MSECS_PER_DAY - ds - 1;
- } else {
- ds = msecs;
+ // Docs state any LocalTime after 2038-01-18 *will* have any DST applied.
+ // When this falls outside the supported range, we need to fake it.
+#if QT_CONFIG(timezone) // Use the system time-zone.
+ if (const auto sys = QTimeZone::systemTimeZone(); sys.isValid()) {
+ result.offset = sys.d->offsetFromUtc(utcMSecs);
+ if (qAddOverflow(utcMSecs, result.offset * MSECS_PER_SEC, &result.when))
+ return result;
+ result.dst = sys.d->isDaylightTime(utcMSecs) ? DaylightTime : StandardTime;
+ result.valid = true;
+ return result;
}
+#endif // timezone
- if (date)
- *date = QDate::fromJulianDay(jd);
- if (time)
- *time = QTime::fromMSecsSinceStartOfDay(ds);
+ // Kludge
+ // Do the conversion in a year with the same days of the week, so DST
+ // dates might be right, and adjust by the number of days that was off:
+ const qint64 jd = msecsToJulianDay(utcMSecs);
+ const auto ymd = QGregorianCalendar::partsFromJulian(jd);
+ qint64 diffMillis, fakeUtc;
+ const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
+ ymd.month, ymd.day);
+ if (Q_UNLIKELY(!fakeJd
+ || qMulOverflow(jd - *fakeJd, std::integral_constant<qint64, MSECS_PER_DAY>(),
+ &diffMillis)
+ || qSubOverflow(utcMSecs, diffMillis, &fakeUtc))) {
+ return result;
+ }
+
+ result = QLocalTime::utcToLocal(fakeUtc);
+ // Now correct result.when for the use of the fake date:
+ if (!result.valid || qAddOverflow(result.when, diffMillis, &result.when)) {
+ // If utcToLocal() failed, its return has the fake when; restore utcMSecs.
+ // Fail on overflow, but preserve offset and DST-ness.
+ result.when = utcMSecs;
+ result.valid = false;
+ }
+ return result;
}
-// Converts a date/time value into msecs
-static qint64 timeToMSecs(QDate date, QTime time)
+static auto millisToWithinRange(qint64 millis)
{
- return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
- + time.msecsSinceStartOfDay();
+ struct R {
+ qint64 shifted = 0;
+ bool good = false;
+ } result;
+ qint64 jd = msecsToJulianDay(millis);
+ auto ymd = QGregorianCalendar::partsFromJulian(jd);
+ const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
+ ymd.month, ymd.day);
+ result.good = fakeJd && !daysAndMillisOverflow(*fakeJd - jd, millis, &result.shifted);
+ return result;
}
-// Convert an MSecs Since Epoch into Local Time
-static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTime,
- QDateTimePrivate::DaylightStatus *daylightStatus = nullptr)
+/*!
+ \internal
+ \enum QDateTimePrivate::TransitionOption
+
+ This enumeration is used to resolve datetime combinations which fall in \l
+ {Timezone transitions}. The transition is described as a "gap" if there are
+ time representations skipped over by the zone, as is common in the "spring
+ forward" transitions in many zones on entering daylight-saving time. The
+ transition is described as a "fold" if there are time representations
+ repeated in the zone, as in a "fall back" transition out of daylight-saving
+ time.
+
+ When the options specified do not determine a resolution for a datetime, it
+ is marked invalid.
+
+ The prepared option sets above are in fact composed from low-level atomic
+ options. For each of gap and fold you can chose between two candidate times,
+ one before or after the transition, based on the time requested; or you can
+ pick the moment of transition, or the start or end of the transition
+ interval. For a gap, the start and end of the interval are the moment of the
+ transition, but for a repeated interval the start of the first pass is the
+ start of the transition interval, the end of the second pass is the end of
+ the transition interval and the moment of the transition itself is both the
+ end of the first pass and the start of the second.
+
+ \value GapUseBefore For a time in a gap, use a time before the transition,
+ as if stepping back from a later time.
+ \value GapUseAfter For a time in a gap, use a time after the transition, as
+ if stepping forward from an earlier time.
+ \value FoldUseBefore For a repeated time, use the first candidate, which is
+ before the transition.
+ \value FoldUseAfter For a repeated time, use the second candidate, which is
+ after the transition.
+ \value FlipForReverseDst For "reversed" DST, this reverses the preceding
+ four options (see below).
+
+ The last has no effect unless the "daylight-saving" time side of the
+ transition is known to have a lower offset from UTC than the standard time
+ side. (This is the "reversed" DST case of \l {Timezone transitions}.) In
+ that case, if other options would select a time after the transition, a time
+ before is used instead, and vice versa. This effectively turns a preference
+ for the side with lower offset into a preference for the side that is
+ officially standard time, even if it has higher offset; and conversely a
+ preference for higher offset into a preference for daylight-saving time,
+ even if it has a lower offset. This option has no effect on a resolution
+ that selects the moment of transition or the start or end of the transition
+ interval.
+
+ The result of combining more than one of the \c GapUse* options is
+ undefined; likewise for the \c FoldUse*. Each of QDateTime's
+ TransitionResolution values, aside from Reject, maps to a combination that
+ incorporates one from each of these sets.
+*/
+
+constexpr static QDateTimePrivate::TransitionOptions
+toTransitionOptions(QDateTime::TransitionResolution res)
+{
+ switch (res) {
+ case QDateTime::TransitionResolution::RelativeToBefore:
+ return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseBefore;
+ case QDateTime::TransitionResolution::RelativeToAfter:
+ return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseAfter;
+ case QDateTime::TransitionResolution::PreferBefore:
+ return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseBefore;
+ case QDateTime::TransitionResolution::PreferAfter:
+ return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseAfter;
+ case QDateTime::TransitionResolution::PreferStandard:
+ return QDateTimePrivate::GapUseBefore
+ | QDateTimePrivate::FoldUseAfter
+ | QDateTimePrivate::FlipForReverseDst;
+ case QDateTime::TransitionResolution::PreferDaylightSaving:
+ return QDateTimePrivate::GapUseAfter
+ | QDateTimePrivate::FoldUseBefore
+ | QDateTimePrivate::FlipForReverseDst;
+ case QDateTime::TransitionResolution::Reject: break;
+ }
+ return {};
+}
+
+constexpr static QDateTimePrivate::TransitionOptions
+toTransitionOptions(QDateTimePrivate::DaylightStatus dst)
{
- if (msecs < 0) {
- // Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied
- // Instead just use the standard offset from UTC to convert to UTC time
- qTzSet();
- msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime);
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::StandardTime;
- return true;
- } else if (msecs > (qint64(TIME_T_MAX) * 1000)) {
- // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
- // but this may fall outside the supported time_t range, so need to fake it.
- // Use existing method to fake the conversion, but this is deeply flawed as it may
- // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
- // TODO Use QTimeZone when available to apply the future rule correctly
- QDate utcDate;
- QTime utcTime;
- msecsToTime(msecs, &utcDate, &utcTime);
- int year, month, day;
- utcDate.getDate(&year, &month, &day);
- // 2037 is not a leap year, so make sure date isn't Feb 29
- if (month == 2 && day == 29)
- --day;
- QDate fakeDate(2037, month, day);
- qint64 fakeMsecs = QDateTime(fakeDate, utcTime, Qt::UTC).toMSecsSinceEpoch();
- bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus);
- *localDate = localDate->addDays(fakeDate.daysTo(utcDate));
- return res;
- } else {
- // Falls inside time_t suported range so can use localtime
- return qt_localtime(msecs, localDate, localTime, daylightStatus);
+ return toTransitionOptions(dst == QDateTimePrivate::DaylightTime
+ ? QDateTime::TransitionResolution::PreferDaylightSaving
+ : QDateTime::TransitionResolution::PreferStandard);
+}
+
+QString QDateTimePrivate::localNameAtMillis(qint64 millis, DaylightStatus dst)
+{
+ const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(dst);
+ QString abbreviation;
+ if (millisInSystemRange(millis, MSECS_PER_DAY)) {
+ abbreviation = QLocalTime::localTimeAbbbreviationAt(millis, resolve);
+ if (!abbreviation.isEmpty())
+ return abbreviation;
}
+
+ // Otherwise, outside the system range.
+#if QT_CONFIG(timezone)
+ // Use the system zone:
+ const auto sys = QTimeZone::systemTimeZone();
+ if (sys.isValid()) {
+ ZoneState state = zoneStateAtMillis(sys, millis, resolve);
+ if (state.valid)
+ return sys.d->abbreviation(state.when - state.offset * MSECS_PER_SEC);
+ }
+#endif // timezone
+
+ // Kludge
+ // Use a time in the system range with the same day-of-week pattern to its year:
+ auto fake = millisToWithinRange(millis);
+ if (Q_LIKELY(fake.good))
+ return QLocalTime::localTimeAbbbreviationAt(fake.shifted, resolve);
+
+ // Overflow, apparently.
+ return {};
}
-// Convert a LocalTime expressed in local msecs encoding and the corresponding
-// DST status into a UTC epoch msecs. Optionally populate the returned
-// values from mktime for the adjusted local date and time.
-static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
- QDateTimePrivate::DaylightStatus *daylightStatus,
- QDate *localDate = nullptr, QTime *localTime = nullptr,
- QString *abbreviation = nullptr)
+// Determine the offset from UTC at the given local time as millis.
+QDateTimePrivate::ZoneState QDateTimePrivate::localStateAtMillis(
+ qint64 millis, QDateTimePrivate::TransitionOptions resolve)
{
- QDate dt;
- QTime tm;
- msecsToTime(localMsecs, &dt, &tm);
-
- const qint64 msecsMax = qint64(TIME_T_MAX) * 1000;
-
- if (localMsecs <= qint64(MSECS_PER_DAY)) {
-
- // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
-
- // First, if localMsecs is within +/- 1 day of minimum time_t try mktime in case it does
- // fall after minimum and needs proper DST conversion
- if (localMsecs >= -qint64(MSECS_PER_DAY)) {
- bool valid;
- qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
- if (valid && utcMsecs >= 0) {
- // mktime worked and falls in valid range, so use it
- if (localDate)
- *localDate = dt;
- if (localTime)
- *localTime = tm;
- return utcMsecs;
+ // First, if millis is within a day of the viable range, try mktime() in
+ // case it does fall in the range and gets useful information:
+ if (millisInSystemRange(millis, MSECS_PER_DAY)) {
+ auto result = QLocalTime::mapLocalTime(millis, resolve);
+ if (result.valid)
+ return result;
+ }
+
+ // Otherwise, outside the system range.
+#if QT_CONFIG(timezone)
+ // Use the system zone:
+ const auto sys = QTimeZone::systemTimeZone();
+ if (sys.isValid())
+ return zoneStateAtMillis(sys, millis, resolve);
+#endif // timezone
+
+ // Kludge
+ // Use a time in the system range with the same day-of-week pattern to its year:
+ auto fake = millisToWithinRange(millis);
+ if (Q_LIKELY(fake.good)) {
+ auto result = QLocalTime::mapLocalTime(fake.shifted, resolve);
+ if (result.valid) {
+ qint64 adjusted;
+ if (Q_UNLIKELY(qAddOverflow(result.when, millis - fake.shifted, &adjusted))) {
+ using Bound = std::numeric_limits<qint64>;
+ adjusted = millis < fake.shifted ? Bound::min() : Bound::max();
}
+ result.when = adjusted;
} else {
- // If we don't call mktime then need to call tzset to get offset
- qTzSet();
- }
- // Time is clearly before 1970-01-01 so just use standard offset to convert
- qint64 utcMsecs = localMsecs + qt_timezone() * 1000;
- if (localDate || localTime)
- msecsToTime(localMsecs, localDate, localTime);
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::StandardTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
- return utcMsecs;
-
- } else if (localMsecs >= msecsMax - MSECS_PER_DAY) {
-
- // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
- // but this may fall outside the supported time_t range, so need to fake it.
-
- // First, if localMsecs is within +/- 1 day of maximum time_t try mktime in case it does
- // fall before maximum and can use proper DST conversion
- if (localMsecs <= msecsMax + MSECS_PER_DAY) {
- bool valid;
- qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
- if (valid && utcMsecs <= msecsMax) {
- // mktime worked and falls in valid range, so use it
- if (localDate)
- *localDate = dt;
- if (localTime)
- *localTime = tm;
- return utcMsecs;
- }
+ result.when = millis;
}
- // Use existing method to fake the conversion, but this is deeply flawed as it may
- // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
- // TODO Use QTimeZone when available to apply the future rule correctly
- int year, month, day;
- dt.getDate(&year, &month, &day);
- // 2037 is not a leap year, so make sure date isn't Feb 29
- if (month == 2 && day == 29)
- --day;
- QDate fakeDate(2037, month, day);
- qint64 fakeDiff = fakeDate.daysTo(dt);
- qint64 utcMsecs = qt_mktime(&fakeDate, &tm, daylightStatus, abbreviation);
- if (localDate)
- *localDate = fakeDate.addDays(fakeDiff);
- if (localTime)
- *localTime = tm;
- QDate utcDate;
- QTime utcTime;
- msecsToTime(utcMsecs, &utcDate, &utcTime);
- utcDate = utcDate.addDays(fakeDiff);
- utcMsecs = timeToMSecs(utcDate, utcTime);
- return utcMsecs;
-
- } else {
+ return result;
+ }
+ // Overflow, apparently.
+ return {millis};
+}
- // Clearly falls inside 1970-2037 suported range so can use mktime
- qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation);
- if (localDate)
- *localDate = dt;
- if (localTime)
- *localTime = tm;
- return utcMsecs;
+#if QT_CONFIG(timezone)
+// For a TimeZone and a time expressed in zone msecs encoding, compute the
+// actual DST-ness and offset, adjusting the time if needed to escape a
+// spring-forward.
+QDateTimePrivate::ZoneState QDateTimePrivate::zoneStateAtMillis(
+ const QTimeZone &zone, qint64 millis, QDateTimePrivate::TransitionOptions resolve)
+{
+ Q_ASSERT(zone.isValid());
+ Q_ASSERT(zone.timeSpec() == Qt::TimeZone);
+ return zone.d->stateAtZoneTime(millis, resolve);
+}
+#endif // timezone
- }
+static inline QDateTimePrivate::ZoneState stateAtMillis(const QTimeZone &zone, qint64 millis,
+ QDateTimePrivate::TransitionOptions resolve)
+{
+ if (zone.timeSpec() == Qt::LocalTime)
+ return QDateTimePrivate::localStateAtMillis(millis, resolve);
+#if QT_CONFIG(timezone)
+ if (zone.timeSpec() == Qt::TimeZone && zone.isValid())
+ return QDateTimePrivate::zoneStateAtMillis(zone, millis, resolve);
+#endif
+ return {millis};
}
static inline bool specCanBeSmall(Qt::TimeSpec spec)
@@ -2705,7 +3063,7 @@ static inline bool specCanBeSmall(Qt::TimeSpec spec)
static inline bool msecsCanBeSmall(qint64 msecs)
{
- if (!QDateTimeData::CanBeSmall)
+ if constexpr (!QDateTimeData::CanBeSmall)
return false;
ShortData sd;
@@ -2713,20 +3071,21 @@ static inline bool msecsCanBeSmall(qint64 msecs)
return sd.msecs == msecs;
}
-static Q_DECL_CONSTEXPR inline
+static constexpr inline
QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
{
- return QDateTimePrivate::StatusFlags((status & ~QDateTimePrivate::TimeSpecMask) |
- (int(spec) << QDateTimePrivate::TimeSpecShift));
+ status &= ~QDateTimePrivate::TimeSpecMask;
+ status |= QDateTimePrivate::StatusFlags::fromInt(int(spec) << QDateTimePrivate::TimeSpecShift);
+ return status;
}
-static Q_DECL_CONSTEXPR inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
+static constexpr inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
{
- return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask) >> QDateTimePrivate::TimeSpecShift);
+ return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask).toInt() >> QDateTimePrivate::TimeSpecShift);
}
// Set the Daylight Status if LocalTime set via msecs
-static Q_DECL_RELAXED_CONSTEXPR inline QDateTimePrivate::StatusFlags
+static constexpr inline QDateTimePrivate::StatusFlags
mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
{
sf &= ~QDateTimePrivate::DaylightMask;
@@ -2739,12 +3098,12 @@ mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::Daylight
}
// Get the DST Status if LocalTime set via msecs
-static Q_DECL_RELAXED_CONSTEXPR inline
+static constexpr inline
QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
{
- if (status & QDateTimePrivate::SetToDaylightTime)
+ if (status.testFlag(QDateTimePrivate::SetToDaylightTime))
return QDateTimePrivate::DaylightTime;
- if (status & QDateTimePrivate::SetToStandardTime)
+ if (status.testFlag(QDateTimePrivate::SetToStandardTime))
return QDateTimePrivate::StandardTime;
return QDateTimePrivate::UnknownDaylightTime;
}
@@ -2774,67 +3133,90 @@ static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
return extractSpec(getStatus(d));
}
-#if QT_CONFIG(timezone)
-void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
+/* True if we *can cheaply determine* that a and b use the same offset.
+ If they use different offsets or it would be expensive to find out, false.
+ Calls to toMSecsSinceEpoch() are expensive, for these purposes.
+ See QDateTime's comparison operators.
+*/
+static inline bool usesSameOffset(const QDateTimeData &a, const QDateTimeData &b)
{
- m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
+ const auto status = getStatus(a);
+ if (status != getStatus(b))
+ return false;
+ // Status includes DST-ness, so we now know they match in it.
+
+ switch (extractSpec(status)) {
+ case Qt::LocalTime:
+ case Qt::UTC:
+ return true;
+
+ case Qt::TimeZone:
+ /* TimeZone always determines its offset during construction of the
+ private data. Even if we're in different zones, what matters is the
+ offset actually in effect at the specific time. (DST can cause things
+ with the same time-zone to use different offsets, but we already
+ checked their DSTs match.) */
+ case Qt::OffsetFromUTC: // always knows its offset, which is all that matters.
+ Q_ASSERT(!a.isShort() && !b.isShort());
+ return a->m_offsetFromUtc == b->m_offsetFromUtc;
+ }
+ Q_UNREACHABLE_RETURN(false);
}
-#endif
-// Refresh the LocalTime validity and offset
-static void refreshDateTime(QDateTimeData &d)
+// Refresh the LocalTime or TimeZone validity and offset
+static void refreshZonedDateTime(QDateTimeData &d, const QTimeZone &zone,
+ QDateTimePrivate::TransitionOptions resolve)
{
+ Q_ASSERT(zone.timeSpec() == Qt::TimeZone || zone.timeSpec() == Qt::LocalTime);
auto status = getStatus(d);
- const auto spec = extractSpec(status);
- const qint64 msecs = getMSecs(d);
- qint64 epochMSecs = 0;
- QDate testDate;
- QTime testTime;
- Q_ASSERT(spec == Qt::TimeZone || spec == Qt::LocalTime);
-
-#if QT_CONFIG(timezone)
- // If not valid time zone then is invalid
- if (spec == Qt::TimeZone) {
- if (!d->m_timeZone.isValid()) {
- status &= ~QDateTimePrivate::ValidDateTime;
- } else {
- epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
- d->setUtcOffsetByTZ(epochMSecs);
- }
- }
-#endif // timezone
+ Q_ASSERT(extractSpec(status) == zone.timeSpec());
+ int offsetFromUtc = 0;
+ /* Callers are:
+ * QDTP::create(), where d is too new to be shared yet
+ * reviseTimeZone(), which detach()es if not short before calling this
+ * checkValidDateTime(), always follows a setDateTime() that detach()ed if not short
+
+ So we can assume d is not shared. We only need to detach() if we convert
+ from short to pimpled to accommodate an oversize msecs, which can only be
+ needed in the unlikely event we revise it.
+ */
// If not valid date and time then is invalid
- if (!(status & QDateTimePrivate::ValidDate) || !(status & QDateTimePrivate::ValidTime)) {
- status &= ~QDateTimePrivate::ValidDateTime;
- if (status & QDateTimePrivate::ShortData) {
- d.data.status = status;
+ if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime)) {
+ status.setFlag(QDateTimePrivate::ValidDateTime, false);
+ } else {
+ // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone
+ // that might fall into a "missing" DST transition hour.
+ qint64 msecs = getMSecs(d);
+ QDateTimePrivate::ZoneState state = stateAtMillis(zone, msecs, resolve);
+ Q_ASSERT(!state.valid || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
+ if (state.dst == QDateTimePrivate::UnknownDaylightTime) { // Overflow
+ status.setFlag(QDateTimePrivate::ValidDateTime, false);
+ } else if (state.valid) {
+ status = mergeDaylightStatus(status, state.dst);
+ offsetFromUtc = state.offset;
+ status.setFlag(QDateTimePrivate::ValidDateTime, true);
+ if (Q_UNLIKELY(msecs != state.when)) {
+ // Update msecs to the resolution:
+ if (status.testFlag(QDateTimePrivate::ShortData)) {
+ if (msecsCanBeSmall(state.when)) {
+ d.data.msecs = qintptr(state.when);
+ } else {
+ // Convert to long-form so we can hold the revised msecs:
+ status.setFlag(QDateTimePrivate::ShortData, false);
+ d.detach();
+ }
+ }
+ if (!status.testFlag(QDateTimePrivate::ShortData))
+ d->m_msecs = state.when;
+ }
} else {
- d->m_status = status;
- d->m_offsetFromUtc = 0;
+ status.setFlag(QDateTimePrivate::ValidDateTime, false);
}
- return;
}
- // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
- // LocalTime and TimeZone might fall into a "missing" DST transition hour
- // Calling toEpochMSecs will adjust the returned date/time if it does
- if (spec == Qt::LocalTime) {
- auto dstStatus = extractDaylightStatus(status);
- epochMSecs = localMSecsToEpochMSecs(msecs, &dstStatus, &testDate, &testTime);
- status = mergeDaylightStatus(status, dstStatus);
- }
- int offsetFromUtc = 0;
- if (timeToMSecs(testDate, testTime) == msecs) {
- status |= QDateTimePrivate::ValidDateTime;
- // Cache the offset to use in offsetFromUtc()
- offsetFromUtc = (msecs - epochMSecs) / 1000;
- } else {
- status &= ~QDateTimePrivate::ValidDateTime;
- }
-
- if (status & QDateTimePrivate::ShortData) {
- d.data.status = status;
+ if (status.testFlag(QDateTimePrivate::ShortData)) {
+ d.data.status = status.toInt();
} else {
d->m_status = status;
d->m_offsetFromUtc = offsetFromUtc;
@@ -2842,72 +3224,86 @@ static void refreshDateTime(QDateTimeData &d)
}
// Check the UTC / offsetFromUTC validity
-static void checkValidDateTime(QDateTimeData &d)
+static void refreshSimpleDateTime(QDateTimeData &d)
{
auto status = getStatus(d);
- auto spec = extractSpec(status);
+ Q_ASSERT(QTimeZone::isUtcOrFixedOffset(extractSpec(status)));
+ status.setFlag(QDateTimePrivate::ValidDateTime,
+ status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime));
+
+ if (status.testFlag(QDateTimePrivate::ShortData))
+ d.data.status = status.toInt();
+ else
+ d->m_status = status;
+}
+
+// Clean up and set status after assorted set-up or reworking:
+static void checkValidDateTime(QDateTimeData &d, QDateTime::TransitionResolution resolve)
+{
+ auto spec = extractSpec(getStatus(d));
switch (spec) {
case Qt::OffsetFromUTC:
case Qt::UTC:
// for these, a valid date and a valid time imply a valid QDateTime
- if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime))
- status |= QDateTimePrivate::ValidDateTime;
- else
- status &= ~QDateTimePrivate::ValidDateTime;
- if (status & QDateTimePrivate::ShortData)
- d.data.status = status;
- else
- d->m_status = status;
+ refreshSimpleDateTime(d);
break;
case Qt::TimeZone:
case Qt::LocalTime:
- // for these, we need to check whether the timezone is valid and whether
- // the time is valid in that timezone. Expensive, but no other option.
- refreshDateTime(d);
+ // For these, we need to check whether (the zone is valid and) the time
+ // is valid for the zone. Expensive, but we have no other option.
+ refreshZonedDateTime(d, d.timeZone(), toTransitionOptions(resolve));
break;
}
}
-static void setTimeSpec(QDateTimeData &d, Qt::TimeSpec spec, int offsetSeconds)
+static void reviseTimeZone(QDateTimeData &d, const QTimeZone &zone,
+ QDateTime::TransitionResolution resolve)
{
- auto status = getStatus(d);
- status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask |
- QDateTimePrivate::TimeSpecMask);
+ Qt::TimeSpec spec = zone.timeSpec();
+ auto status = mergeSpec(getStatus(d), spec);
+ bool reuse = d.isShort();
+ int offset = 0;
switch (spec) {
+ case Qt::UTC:
+ Q_ASSERT(zone.fixedSecondsAheadOfUtc() == 0);
+ break;
case Qt::OffsetFromUTC:
- if (offsetSeconds == 0)
- spec = Qt::UTC;
+ reuse = false;
+ offset = zone.fixedSecondsAheadOfUtc();
+ Q_ASSERT(offset);
break;
case Qt::TimeZone:
- qWarning("Using TimeZone in setTimeSpec() is unsupported"); // Use system time zone instead
- spec = Qt::LocalTime;
- Q_FALLTHROUGH();
- case Qt::UTC:
+ reuse = false;
+ break;
case Qt::LocalTime:
- offsetSeconds = 0;
break;
}
- status = mergeSpec(status, spec);
- if (d.isShort() && offsetSeconds == 0) {
- d.data.status = status;
+ status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask);
+ if (reuse) {
+ d.data.status = status.toInt();
} else {
d.detach();
d->m_status = status & ~QDateTimePrivate::ShortData;
- d->m_offsetFromUtc = offsetSeconds;
+ d->m_offsetFromUtc = offset;
#if QT_CONFIG(timezone)
- d->m_timeZone = QTimeZone();
+ if (spec == Qt::TimeZone)
+ d->m_timeZone = zone;
#endif // timezone
}
+
+ if (QTimeZone::isUtcOrFixedOffset(spec))
+ refreshSimpleDateTime(d);
+ else
+ refreshZonedDateTime(d, zone, toTransitionOptions(resolve));
}
static void setDateTime(QDateTimeData &d, QDate date, QTime time)
{
// If the date is valid and the time is not we set time to 00:00:00
- QTime useTime = time;
- if (!useTime.isValid() && date.isValid())
- useTime = QTime::fromMSecsSinceStartOfDay(0);
+ if (!time.isValid() && date.isValid())
+ time = QTime::fromMSecsSinceStartOfDay(0);
QDateTimePrivate::StatusFlags newStatus = { };
@@ -2920,20 +3316,31 @@ static void setDateTime(QDateTimeData &d, QDate date, QTime time)
// Set time value and status
int ds = 0;
- if (useTime.isValid()) {
- ds = useTime.msecsSinceStartOfDay();
+ if (time.isValid()) {
+ ds = time.msecsSinceStartOfDay();
newStatus |= QDateTimePrivate::ValidTime;
}
+ Q_ASSERT(ds < MSECS_PER_DAY);
+ // Only the later parts of the very first day are representable - its start
+ // would overflow - so get ds the same side of 0 as days:
+ if (days < 0 && ds > 0) {
+ days++;
+ ds -= MSECS_PER_DAY;
+ }
- // Set msecs serial value
- qint64 msecs = (days * MSECS_PER_DAY) + ds;
+ // Check in representable range:
+ qint64 msecs = 0;
+ if (daysAndMillisOverflow(days, qint64(ds), &msecs)) {
+ newStatus = QDateTimePrivate::StatusFlags{};
+ msecs = 0;
+ }
if (d.isShort()) {
// let's see if we can keep this short
if (msecsCanBeSmall(msecs)) {
// yes, we can
d.data.msecs = qintptr(msecs);
- d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
- d.data.status |= newStatus;
+ d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask).toInt();
+ d.data.status |= newStatus.toInt();
} else {
// nope...
d.detach();
@@ -2945,61 +3352,63 @@ static void setDateTime(QDateTimeData &d, QDate date, QTime time)
d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
d->m_status |= newStatus;
}
-
- // Set if date and time are valid
- checkValidDateTime(d);
}
-static QPair<QDate, QTime> getDateTime(const QDateTimeData &d)
+static std::pair<QDate, QTime> getDateTime(const QDateTimeData &d)
{
- QPair<QDate, QTime> result;
- qint64 msecs = getMSecs(d);
auto status = getStatus(d);
- msecsToTime(msecs, &result.first, &result.second);
-
- if (!status.testFlag(QDateTimePrivate::ValidDate))
- result.first = QDate();
-
- if (!status.testFlag(QDateTimePrivate::ValidTime))
- result.second = QTime();
-
- return result;
+ const qint64 msecs = getMSecs(d);
+ const auto dayMilli = QRoundingDown::qDivMod<MSECS_PER_DAY>(msecs);
+ return { status.testFlag(QDateTimePrivate::ValidDate)
+ ? QDate::fromJulianDay(JULIAN_DAY_FOR_EPOCH + dayMilli.quotient)
+ : QDate(),
+ status.testFlag(QDateTimePrivate::ValidTime)
+ ? QTime::fromMSecsSinceStartOfDay(dayMilli.remainder)
+ : QTime() };
}
/*****************************************************************************
QDateTime::Data member functions
*****************************************************************************/
-inline QDateTime::Data::Data()
+inline QDateTime::Data::Data() noexcept
{
// default-constructed data has a special exception:
// it can be small even if CanBeSmall == false
// (optimization so we don't allocate memory in the default constructor)
- quintptr value = quintptr(mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime));
+ quintptr value = mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime).toInt();
d = reinterpret_cast<QDateTimePrivate *>(value);
}
-inline QDateTime::Data::Data(Qt::TimeSpec spec)
+inline QDateTime::Data::Data(const QTimeZone &zone)
{
+ Qt::TimeSpec spec = zone.timeSpec();
if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
- d = reinterpret_cast<QDateTimePrivate *>(quintptr(mergeSpec(QDateTimePrivate::ShortData, spec)));
+ quintptr value = mergeSpec(QDateTimePrivate::ShortData, spec).toInt();
+ d = reinterpret_cast<QDateTimePrivate *>(value);
+ Q_ASSERT(isShort());
} else {
// the structure is too small, we need to detach
d = new QDateTimePrivate;
d->ref.ref();
d->m_status = mergeSpec({}, spec);
+ if (spec == Qt::OffsetFromUTC)
+ d->m_offsetFromUtc = zone.fixedSecondsAheadOfUtc();
+ else if (spec == Qt::TimeZone)
+ d->m_timeZone = zone;
+ Q_ASSERT(!isShort());
}
}
-inline QDateTime::Data::Data(const Data &other)
- : d(other.d)
+inline QDateTime::Data::Data(const Data &other) noexcept
+ : data(other.data)
{
if (!isShort()) {
// check if we could shrink
if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
ShortData sd;
sd.msecs = qintptr(d->m_msecs);
- sd.status = d->m_status | QDateTimePrivate::ShortData;
+ sd.status = (d->m_status | QDateTimePrivate::ShortData).toInt();
data = sd;
} else {
// no, have to keep it big
@@ -3008,18 +3417,18 @@ inline QDateTime::Data::Data(const Data &other)
}
}
-inline QDateTime::Data::Data(Data &&other)
- : d(other.d)
+inline QDateTime::Data::Data(Data &&other) noexcept
+ : data(other.data)
{
// reset the other to a short state
Data dummy;
Q_ASSERT(dummy.isShort());
- other.d = dummy.d;
+ other.data = dummy.data;
}
-inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
+inline QDateTime::Data &QDateTime::Data::operator=(const Data &other) noexcept
{
- if (d == other.d)
+ if (isShort() ? data == other.data : d == other.d)
return *this;
auto x = d;
@@ -3029,7 +3438,7 @@ inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
ShortData sd;
sd.msecs = qintptr(other.d->m_msecs);
- sd.status = other.d->m_status | QDateTimePrivate::ShortData;
+ sd.status = (other.d->m_status | QDateTimePrivate::ShortData).toInt();
data = sd;
} else {
// no, have to keep it big
@@ -3053,11 +3462,11 @@ inline bool QDateTime::Data::isShort() const
bool b = quintptr(d) & QDateTimePrivate::ShortData;
// sanity check:
- Q_ASSERT(b || (d->m_status & QDateTimePrivate::ShortData) == 0);
+ Q_ASSERT(b || !d->m_status.testFlag(QDateTimePrivate::ShortData));
// even if CanBeSmall = false, we have short data for a default-constructed
// QDateTime object. But it's unlikely.
- if (CanBeSmall)
+ if constexpr (CanBeSmall)
return Q_LIKELY(b);
return Q_UNLIKELY(b);
}
@@ -3069,7 +3478,7 @@ inline void QDateTime::Data::detach()
if (wasShort) {
// force enlarging
x = new QDateTimePrivate;
- x->m_status = QDateTimePrivate::StatusFlag(data.status & ~QDateTimePrivate::ShortData);
+ x->m_status = QDateTimePrivate::StatusFlags::fromInt(data.status) & ~QDateTimePrivate::ShortData;
x->m_msecs = data.msecs;
} else {
if (d->ref.loadRelaxed() == 1)
@@ -3084,6 +3493,35 @@ inline void QDateTime::Data::detach()
d = x;
}
+void QDateTime::Data::invalidate()
+{
+ if (isShort()) {
+ data.status &= ~int(QDateTimePrivate::ValidityMask);
+ } else {
+ detach();
+ d->m_status &= ~QDateTimePrivate::ValidityMask;
+ }
+}
+
+QTimeZone QDateTime::Data::timeZone() const
+{
+ switch (getSpec(*this)) {
+ case Qt::UTC:
+ return QTimeZone::UTC;
+ case Qt::OffsetFromUTC:
+ return QTimeZone::fromSecondsAheadOfUtc(d->m_offsetFromUtc);
+ case Qt::TimeZone:
+#if QT_CONFIG(timezone)
+ if (d->m_timeZone.isValid())
+ return d->m_timeZone;
+#endif
+ break;
+ case Qt::LocalTime:
+ return QTimeZone::LocalTime;
+ }
+ return QTimeZone();
+}
+
inline const QDateTimePrivate *QDateTime::Data::operator->() const
{
Q_ASSERT(!isShort());
@@ -3103,49 +3541,18 @@ inline QDateTimePrivate *QDateTime::Data::operator->()
*****************************************************************************/
Q_NEVER_INLINE
-QDateTime::Data QDateTimePrivate::create(QDate toDate, QTime toTime, Qt::TimeSpec toSpec,
- int offsetSeconds)
+QDateTime::Data QDateTimePrivate::create(QDate toDate, QTime toTime, const QTimeZone &zone,
+ QDateTime::TransitionResolution resolve)
{
- QDateTime::Data result(toSpec);
- setTimeSpec(result, toSpec, offsetSeconds);
- setDateTime(result, toDate, toTime);
- return result;
-}
-
-#if QT_CONFIG(timezone)
-inline QDateTime::Data QDateTimePrivate::create(QDate toDate, QTime toTime,
- const QTimeZone &toTimeZone)
-{
- QDateTime::Data result(Qt::TimeZone);
- Q_ASSERT(!result.isShort());
-
- result.d->m_status = mergeSpec(result.d->m_status, Qt::TimeZone);
- result.d->m_timeZone = toTimeZone;
+ QDateTime::Data result(zone);
setDateTime(result, toDate, toTime);
+ if (zone.isUtcOrFixedOffset())
+ refreshSimpleDateTime(result);
+ else
+ refreshZonedDateTime(result, zone, toTransitionOptions(resolve));
return result;
}
-// Convert a TimeZone time expressed in zone msecs encoding into a UTC epoch msecs
-// DST transitions are disambiguated by hint.
-inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
- DaylightStatus hint,
- QDate *zoneDate, QTime *zoneTime)
-{
- Q_ASSERT(zone.isValid());
- // Get the effective data from QTimeZone
- QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
- // Docs state any time before 1970-01-01 will *not* have any DST applied
- // but all affected times afterwards will have DST applied.
- if (data.atMSecsSinceEpoch < 0) {
- msecsToTime(zoneMSecs, zoneDate, zoneTime);
- return zoneMSecs - data.standardTimeOffset * 1000;
- } else {
- msecsToTime(data.atMSecsSinceEpoch + data.offsetFromUtc * 1000, zoneDate, zoneTime);
- return data.atMSecsSinceEpoch;
- }
-}
-#endif // timezone
-
/*****************************************************************************
QDateTime member functions
*****************************************************************************/
@@ -3157,37 +3564,42 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
\reentrant
\brief The QDateTime class provides date and time functions.
+ \compares weak
- A QDateTime object encodes a calendar date and a clock time (a
- "datetime"). It combines features of the QDate and QTime classes.
- It can read the current datetime from the system clock. It
- provides functions for comparing datetimes and for manipulating a
+ A QDateTime object encodes a calendar date and a clock time (a "datetime")
+ in accordance with a time representation. It combines features of the QDate
+ and QTime classes. It can read the current datetime from the system
+ clock. It provides functions for comparing datetimes and for manipulating a
datetime by adding a number of seconds, days, months, or years.
QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local
time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset from
- UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction with the
- QTimeZone class. For example, a time zone of "Europe/Berlin" will apply the
- daylight-saving rules as used in Germany since 1970. In contrast, an offset
- from UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO
- standard notation as "UTC+01:00"), with no daylight-saving offset or
- changes. When using either local time or a specified time zone, time-zone
- transitions such as the starts and ends of daylight-saving time (DST; but
- see below) are taken into account. The choice of system used to represent a
- datetime is described as its "timespec".
+ UTC} or to a specified \l{Qt::TimeZone}{time zone}. Each of these time
+ representations can be encapsulated in a suitable instance of the QTimeZone
+ class. For example, a time zone of "Europe/Berlin" will apply the
+ daylight-saving rules as used in Germany. In contrast, a fixed offset from
+ UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO
+ standard notation as "UTC+01:00"), with no daylight-saving
+ complications. When using either local time or a specified time zone,
+ time-zone transitions (see \l {Timezone transitions}{below}) are taken into
+ account. A QDateTime's timeSpec() will tell you which of the four types of
+ time representation is in use; its timeRepresentation() provides a full
+ description of that time representation, as a QTimeZone.
A QDateTime object is typically created either by giving a date and time
explicitly in the constructor, or by using a static function such as
currentDateTime() or fromMSecsSinceEpoch(). The date and time can be changed
with setDate() and setTime(). A datetime can also be set using the
setMSecsSinceEpoch() function that takes the time, in milliseconds, since
- 00:00:00 on January 1, 1970. The fromString() function returns a QDateTime,
- given a string and a date format used to interpret the date within the
- string.
+ the start, in UTC, of the year 1970. The fromString() function returns a
+ QDateTime, given a string and a date format used to interpret the date
+ within the string.
QDateTime::currentDateTime() returns a QDateTime that expresses the current
- time with respect to local time. QDateTime::currentDateTimeUtc() returns a
- QDateTime that expresses the current time with respect to UTC.
+ date and time with respect to a specific time representation, such as local
+ time (its default). QDateTime::currentDateTimeUtc() returns a QDateTime that
+ expresses the current date and time with respect to UTC; it is equivalent to
+ \c {QDateTime::currentDateTime(QTimeZone::UTC)}.
The date() and time() functions provide access to the date and
time parts of the datetime. The same information is provided in
@@ -3206,17 +3618,17 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
daylight-saving time (DST) and other time-zone transitions, where
applicable.
- Use toTimeSpec() to express a datetime in local time or UTC,
- toOffsetFromUtc() to express in terms of an offset from UTC, or toTimeZone()
- to express it with respect to a general time zone. You can use timeSpec() to
- find out what time-spec a QDateTime object stores its time relative to. When
- that is Qt::TimeZone, you can use timeZone() to find out which zone it is
- using.
-
- \note QDateTime does not account for leap seconds.
+ Use toTimeZone() to re-express a datetime in terms of a different time
+ representation. By passing a lightweight QTimeZone that represents local
+ time, UTC or a fixed offset from UTC, you can convert the datetime to use
+ the corresponding time representation; or you can pass a full time zone
+ (whose \l {QTimeZone::timeSpec()}{timeSpec()} is \c {Qt::TimeZone}) to use
+ that instead.
\section1 Remarks
+ \note QDateTime does not account for leap seconds.
+
\note All conversion to and from string formats is done using the C locale.
For localized conversions, see QLocale.
@@ -3224,15 +3636,21 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
considered invalid. The year -1 is the year "1 before Christ" or "1 before
common era." The day before 1 January 1 CE is 31 December 1 BCE.
+ \note Using local time (the default) or a specified time zone implies a need
+ to resolve any issues around \l {Timezone transitions}{transitions}. As a
+ result, operations on such QDateTime instances (notably including
+ constructing them) may be more expensive than the equivalent when using UTC
+ or a fixed offset from it.
+
\section2 Range of Valid Dates
The range of values that QDateTime can represent is dependent on the
internal storage implementation. QDateTime is currently stored in a qint64
as a serial msecs value encoding the date and time. This restricts the date
- range to about +/- 292 million years, compared to the QDate range of +/- 2
- billion years. Care must be taken when creating a QDateTime with extreme
- values that you do not overflow the storage. The exact range of supported
- values varies depending on the Qt::TimeSpec and time zone.
+ range to about ±292 million years, compared to the QDate range of ±2 billion
+ years. Care must be taken when creating a QDateTime with extreme values that
+ you do not overflow the storage. The exact range of supported values varies
+ depending on the time representation used.
\section2 Use of Timezones
@@ -3249,34 +3667,106 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
information about historical transitions (including DST, see below) whenever
possible. On Windows, where the system doesn't support historical timezone
data, historical accuracy is not maintained with respect to timezone
- transitions, notably including DST.
-
- \section2 Daylight-Saving Time (DST)
-
- QDateTime takes into account transitions between Standard Time and
- Daylight-Saving Time. For example, if the transition is at 2am and the clock
- goes forward to 3am, then there is a "missing" hour from 02:00:00 to
- 02:59:59.999 which QDateTime considers to be invalid. Any date arithmetic
- performed will take this missing hour into account and return a valid
- result. For example, adding one minute to 01:59:59 will get 03:00:00.
-
- The range of valid dates taking DST into account is 1970-01-01 to the
- present, and rules are in place for handling DST correctly until 2037-12-31,
- but these could change. For dates after 2037, QDateTime makes a \e{best
- guess} using the rules for year 2037, but we can't guarantee accuracy;
- indeed, for \e{any} future date, the time-zone may change its rules before
- that date comes around. For dates before 1970, QDateTime doesn't take DST
- changes into account, even if the system's time zone database provides that
- information, although it does take into account changes to the time-zone's
- standard offset, where this information is available.
+ transitions, notably including DST. However, building Qt with the ICU
+ library will equip QTimeZone with the same timezone database as is used on
+ Unix.
+
+ \section2 Timezone transitions
+
+ QDateTime takes into account timezone transitions, both the transitions
+ between Standard Time and Daylight-Saving Time (DST) and the transitions
+ that arise when a zone changes its standard offset. For example, if the
+ transition is at 2am and the clock goes forward to 3am, then there is a
+ "missing" hour from 02:00:00 to 02:59:59.999. Such a transition is known as
+ a "spring forward" and the times skipped over have no meaning. When a
+ transition goes the other way, known as a "fall back", a time interval is
+ repeated, first in the old zone (usually DST), then in the new zone (usually
+ Standard Time), so times in this interval are ambiguous.
+
+ Some zones use "reversed" DST, using standard time in summer and
+ daylight-saving time (with a lowered offset) in winter. For such zones, the
+ spring forward still happens in spring and skips an hour, but is a
+ transition \e{out of} daylight-saving time, while the fall back still
+ repeats an autumn hour but is a transition \e to daylight-saving time.
+
+ When converting from a UTC time (or a time at fixed offset from UTC), there
+ is always an unambiguous valid result in any timezone. However, when
+ combining a date and time to make a datetime, expressed with respect to
+ local time or a specific time-zone, the nominal result may fall in a
+ transition, making it either invalid or ambiguous. Methods where this
+ situation may arise take a \c resolve parameter: this is always ignored if
+ the requested datetime is valid and unambiguous. See \l TransitionResolution
+ for the options it lets you control. Prior to Qt 6.7, the equivalent of its
+ \l LegacyBehavior was selected.
+
+ For a spring forward's skipped interval, interpreting the requested time
+ with either offset yields an actual time at which the other offset was in
+ use; so passing \c TransitionResolution::RelativeToBefore for \c resolve
+ will actually result in a time after the transition, that would have had the
+ requested representation had the transition not happened. Likewise, \c
+ TransitionResolution::RelativeToAfter for \c resolve results in a time
+ before the transition, that would have had the requested representation, had
+ the transition happened earlier.
+
+ When QDateTime performs arithmetic, as with addDay() or addSecs(), it takes
+ care to produce a valid result. For example, on a day when there is a spring
+ forward from 02:00 to 03:00, adding one second to 01:59:59 will get
+ 03:00:00. Adding one day to 02:30 on the preceding day will get 03:30 on the
+ day of the transition, while subtracting one day, by calling \c{addDay(-1)},
+ to 02:30 on the following day will get 01:30 on the day of the transition.
+ While addSecs() will deliver a time offset by the given number of seconds,
+ addDays() adjusts the date and only adjusts time if it would otherwise get
+ an invalid result. Applying \c{addDays(1)} to 03:00 on the day before the
+ spring-forward will simply get 03:00 on the day of the transition, even
+ though the latter is only 23 hours after the former; but \c{addSecs(24 * 60
+ * 60)} will get 04:00 on the day of the transition, since that's 24 hours
+ later. Typical transitions make some days 23 or 25 hours long.
+
+ For datetimes that the system \c time_t can represent (from 1901-12-14 to
+ 2038-01-18 on systems with 32-bit \c time_t; for the full range QDateTime
+ can represent if the type is 64-bit), the standard system APIs are used to
+ determine local time's offset from UTC. For datetimes not handled by these
+ system APIs (potentially including some within the \c time_t range),
+ QTimeZone::systemTimeZone() is used, if available, or a best effort is made
+ to estimate. In any case, the offset information used depends on the system
+ and may be incomplete or, for past times, historically
+ inaccurate. Furthermore, for future dates, the local time zone's offsets and
+ DST rules may change before that date comes around.
+
+ \section3 Whole day transitions
+
+ A small number of zones have skipped or repeated entire days as part of
+ moving The International Date Line across themselves. For these, daysTo()
+ will be unaware of the duplication or gap, simply using the difference in
+ calendar date; in contrast, msecsTo() and secsTo() know the true time
+ interval. Likewise, addMSecs() and addSecs() correspond directly to elapsed
+ time, where addDays(), addMonths() and addYears() follow the nominal
+ calendar, aside from where landing in a gap or duplication requires
+ resolving an ambiguity or invalidity due to a duplication or omission.
+
+ \note Days "lost" during a change of calendar, such as from Julian to
+ Gregorian, do not affect QDateTime. Although the two calendars describe
+ dates differently, the successive days across the change are described by
+ consecutive QDate instances, each one day later than the previous, as
+ described by either calendar or by their toJulianDay() values. In contrast,
+ a zone skipping or duplicating a day is changing its description of \e time,
+ not date, for all that it does so by a whole 24 hours.
\section2 Offsets From UTC
+ Offsets from UTC are measured in seconds east of Greenwich. The moment
+ described by a particular date and time, such as noon on a particular day,
+ depends on the time representation used. Those with a higher offset from UTC
+ describe an earlier moment, and those with a lower offset a later moment, by
+ any given combination of date and time.
+
There is no explicit size restriction on an offset from UTC, but there is an
implicit limit imposed when using the toString() and fromString() methods
- which use a [+|-]hh:mm format, effectively limiting the range to +/- 99
- hours and 59 minutes and whole minutes only. Note that currently no time
- zone lies outside the range of +/- 14 hours.
+ which use a ±hh:mm format, effectively limiting the range to ± 99 hours and
+ 59 minutes and whole minutes only. Note that currently no time zone has an
+ offset outside the range of ±14 hours and all known offsets are multiples of
+ five minutes. Historical time zones have a wider range and may have offsets
+ including seconds; these last cannot be faithfully represented in strings.
\sa QDate, QTime, QDateTimeEdit, QTimeZone
*/
@@ -3302,53 +3792,230 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
*/
/*!
- Constructs a null datetime (i.e. null date and null time). A null
- datetime is invalid, since the date is invalid.
+ \since 6.7
+ \enum QDateTime::TransitionResolution
+
+ This enumeration is used to resolve datetime combinations which fall in \l
+ {Timezone transitions}.
+
+ When constructing a datetime, specified in terms of local time or a
+ time-zone that has daylight-saving time, or revising one with setDate(),
+ setTime() or setTimeZone(), the given parameters may imply a time
+ representation that either has no meaning or has two meanings in the
+ zone. Such time representations are described as being in the transition. In
+ either case, we can simply return an invalid datetime, to indicate that the
+ operation is ill-defined. In the ambiguous case, we can alternatively select
+ one of the two times that could be meant. When there is no meaning, we can
+ select a time either side of it that might plausibly have been meant. For
+ example, when advancing from an earlier time, we can select the time after
+ the transition that is actually the specified amount of time after the
+ earlier time in question. The options specified here configure how such
+ selection is performed.
+
+ \value Reject
+ Treat any time in a transition as invalid. Either it really is, or it
+ is ambiguous.
+ \value RelativeToBefore
+ Selects a time as if stepping forward from a time before the
+ transition. This interprets the requested time using the offset in
+ effect before the transition and, if necessary, converts the result
+ to the offset in effect at the resulting time.
+ \value RelativeToAfter
+ Select a time as if stepping backward from a time after the
+ transition. This interprets the requested time using the offset in
+ effect after the transition and, if necessary, converts the result to
+ the offset in effect at the resulting time.
+ \value PreferBefore
+ Selects a time before the transition,
+ \value PreferAfter
+ Selects a time after the transition.
+ \value PreferStandard
+ Selects a time on the standard time side of the transition.
+ \value PreferDaylightSaving
+ Selects a time on the daylight-saving-time side of the transition.
+ \value LegacyBehavior
+ An alias for RelativeToBefore, which is used as default for
+ TransitionResolution parameters, as this most closely matches the
+ behavior prior to Qt 6.7.
+
+ For \l addDays(), \l addMonths() or \l addYears(), the behavior is and
+ (mostly) was to use \c RelativeToBefore if adding a positive adjustment and \c
+ RelativeToAfter if adding a negative adjustment.
+
+ \note In time zones where daylight-saving increases the offset from UTC in
+ summer (known as "positive DST"), PreferStandard is an alias for
+ RelativeToAfter and PreferDaylightSaving for RelativeToBefore. In time zones
+ where the daylight-saving mechanism is a decrease in offset from UTC in
+ winter (known as "negative DST"), the reverse applies, provided the
+ operating system reports - as it does on most platforms - whether a datetime
+ is in DST or standard time. For some platforms, where transition times are
+ unavailable even for Qt::TimeZone datetimes, QTimeZone is obliged to presume
+ that the side with lower offset from UTC is standard time, effectively
+ assuming positive DST.
+
+ The following tables illustrate how a QDateTime constructor resolves a
+ request for 02:30 on a day when local time has a transition between 02:00
+ and 03:00, with a nominal standard time LST and daylight-saving time LDT on
+ the two sides, in the various possible cases. The transition type may be to
+ skip an hour or repeat it. The type of transition and value of a parameter
+ \c resolve determine which actual time on the given date is selected. First,
+ the common case of positive daylight-saving, where:
- \sa isValid()
+ \table
+ \header \li Before \li 02:00--03:00 \li After \li \c resolve \li selected
+ \row \li LST \li skip \li LDT \li RelativeToBefore \li 03:30 LDT
+ \row \li LST \li skip \li LDT \li RelativeToAfter \li 01:30 LST
+ \row \li LST \li skip \li LDT \li PreferBefore \li 01:30 LST
+ \row \li LST \li skip \li LDT \li PreferAfter \li 03:30 LDT
+ \row \li LST \li skip \li LDT \li PreferStandard \li 01:30 LST
+ \row \li LST \li skip \li LDT \li PreferDaylightSaving \li 03:30 LDT
+ \row \li LDT \li repeat \li LST \li RelativeToBefore \li 02:30 LDT
+ \row \li LDT \li repeat \li LST \li RelativeToAfter \li 02:30 LST
+ \row \li LDT \li repeat \li LST \li PreferBefore \li 02:30 LDT
+ \row \li LDT \li repeat \li LST \li PreferAfter \li 02:30 LST
+ \row \li LDT \li repeat \li LST \li PreferStandard \li 02:30 LST
+ \row \li LDT \li repeat \li LST \li PreferDaylightSaving \li 02:30 LDT
+ \endtable
+
+ Second, the case for negative daylight-saving, using LDT in winter and
+ skipping an hour to transition to LST in summer, then repeating an hour at
+ the transition back to winter:
+
+ \table
+ \row \li LDT \li skip \li LST \li RelativeToBefore \li 03:30 LST
+ \row \li LDT \li skip \li LST \li RelativeToAfter \li 01:30 LDT
+ \row \li LDT \li skip \li LST \li PreferBefore \li 01:30 LDT
+ \row \li LDT \li skip \li LST \li PreferAfter \li 03:30 LST
+ \row \li LDT \li skip \li LST \li PreferStandard \li 03:30 LST
+ \row \li LDT \li skip \li LST \li PreferDaylightSaving \li 01:30 LDT
+ \row \li LST \li repeat \li LDT \li RelativeToBefore \li 02:30 LST
+ \row \li LST \li repeat \li LDT \li RelativeToAfter \li 02:30 LDT
+ \row \li LST \li repeat \li LDT \li PreferBefore \li 02:30 LST
+ \row \li LST \li repeat \li LDT \li PreferAfter \li 02:30 LDT
+ \row \li LST \li repeat \li LDT \li PreferStandard \li 02:30 LST
+ \row \li LST \li repeat \li LDT \li PreferDaylightSaving \li 02:30 LDT
+ \endtable
+
+ Reject can be used to prompt relevant QDateTime APIs to return an invalid
+ datetime object so that your code can deal with transitions for itself, for
+ example by alerting a user to the fact that the datetime they have selected
+ is in a transition interval, to offer them the opportunity to resolve a
+ conflict or ambiguity. Code using this may well find the other options above
+ useful to determine relevant information to use in its own (or the user's)
+ resolution. If the start or end of the transition, or the moment of the
+ transition itself, is the right resolution, QTimeZone's transition APIs can
+ be used to obtain that information. You can determine whether the transition
+ is a repeated or skipped interval by using \l secsTo() to measure the actual
+ time between noon on the previous and following days. The result will be
+ less than 48 hours for a skipped interval (such as a spring-forward) and
+ more than 48 hours for a repeated interval (such as a fall-back).
+
+ \note When a resolution other than Reject is specified, a valid QDateTime
+ object is returned, if possible. If the requested date-time falls in a gap,
+ the returned date-time will not have the time() requested - or, in some
+ cases, the date(), if a whole day was skipped. You can thus detect when a
+ gap is hit by comparing date() and time() to what was requested.
+
+ \section2 Relation to other datetime software
+
+ The Python programming language's datetime APIs have a \c fold parameter
+ that corresponds to \c RelativeToBefore (\c{fold = True}) and \c
+ RelativeToAfter (\c{fold = False}).
+
+ The \c Temporal proposal to replace JavaScript's \c Date offers four options
+ for how to resolve a transition, as value for a \c disambiguation
+ parameter. Its \c{'reject'} raises an exception, which roughly corresponds
+ to \c Reject producing an invalid result. Its \c{'earlier'} and \c{'later'}
+ options correspond to \c PreferBefore and \c PreferAfter. Its
+ \c{'compatible'} option corresponds to \c RelativeToBefore (and Python's
+ \c{fold = True}).
+
+ \sa {Timezone transitions}, QDateTime::TransitionResolution
*/
-QDateTime::QDateTime() noexcept(Data::CanBeSmall)
+
+/*!
+ Constructs a null datetime, nominally using local time.
+
+ A null datetime is invalid, since its date and time are invalid.
+
+ \sa isValid(), setMSecsSinceEpoch(), setDate(), setTime(), setTimeZone()
+*/
+QDateTime::QDateTime() noexcept
{
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || QT_POINTER_SIZE == 8
+ static_assert(sizeof(ShortData) == sizeof(qint64));
+ static_assert(sizeof(Data) == sizeof(qint64));
+#endif
+ static_assert(sizeof(ShortData) >= sizeof(void*), "oops, Data::swap() is broken!");
}
+#if QT_DEPRECATED_SINCE(6, 9)
/*!
- Constructs a datetime with the given \a date and \a time, using
- the time specification defined by \a spec and \a offsetSeconds seconds.
+ \deprecated [6.9] Use \c{QDateTime(date, time)} or \c{QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds))}.
- If \a date is valid and \a time is not, the time will be set to midnight.
+ Constructs a datetime with the given \a date and \a time, using the time
+ representation implied by \a spec and \a offsetSeconds seconds.
- If the \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be ignored.
+ If \a date is valid and \a time is not, the time will be set to midnight.
- If the \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
+ If \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be
+ ignored. If \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
i.e. the current system time zone. To create a Qt::TimeZone datetime
use the correct constructor.
-*/
+ If \a date lies outside the range of dates representable by QDateTime, the
+ result is invalid. If \a spec is Qt::LocalTime and the system's time-zone
+ skipped over the given date and time, the result is invalid.
+*/
QDateTime::QDateTime(QDate date, QTime time, Qt::TimeSpec spec, int offsetSeconds)
- : d(QDateTimePrivate::create(date, time, spec, offsetSeconds))
+ : d(QDateTimePrivate::create(date, time, asTimeZone(spec, offsetSeconds, "QDateTime"),
+ TransitionResolution::LegacyBehavior))
{
}
+#endif // 6.9 deprecation
-#if QT_CONFIG(timezone)
/*!
\since 5.2
- Constructs a datetime with the given \a date and \a time, using
- the Time Zone specified by \a timeZone.
+ Constructs a datetime with the given \a date and \a time, using the time
+ representation described by \a timeZone.
- If \a date is valid and \a time is not, the time will be set to 00:00:00.
+ If \a date is valid and \a time is not, the time will be set to midnight.
+ If \a timeZone is invalid then the datetime will be invalid. If \a date and
+ \a time describe a moment close to a transition for \a timeZone, \a resolve
+ controls how that situation is resolved.
- If \a timeZone is invalid then the datetime will be invalid.
+//! [pre-resolve-note]
+ \note Prior to Qt 6.7, the version of this function lacked the \a resolve
+ parameter so had no way to resolve the ambiguities related to transitions.
+//! [pre-resolve-note]
*/
-QDateTime::QDateTime(QDate date, QTime time, const QTimeZone &timeZone)
- : d(QDateTimePrivate::create(date, time, timeZone))
+QDateTime::QDateTime(QDate date, QTime time, const QTimeZone &timeZone, TransitionResolution resolve)
+ : d(QDateTimePrivate::create(date, time, timeZone, resolve))
+{
+}
+
+/*!
+ \since 6.5
+ \overload
+
+ Constructs a datetime with the given \a date and \a time, using local time.
+
+ If \a date is valid and \a time is not, midnight will be used as the
+ time. If \a date and \a time describe a moment close to a transition for
+ local time, \a resolve controls how that situation is resolved.
+
+ \include qdatetime.cpp pre-resolve-note
+*/
+
+QDateTime::QDateTime(QDate date, QTime time, TransitionResolution resolve)
+ : d(QDateTimePrivate::create(date, time, QTimeZone::LocalTime, resolve))
{
}
-#endif // timezone
/*!
Constructs a copy of the \a other datetime.
@@ -3376,8 +4043,7 @@ QDateTime::~QDateTime()
}
/*!
- Makes a copy of the \a other datetime and returns a reference to the
- copy.
+ Copies the \a other datetime into this and returns this copy.
*/
QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
@@ -3402,65 +4068,60 @@ QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
bool QDateTime::isNull() const
{
- auto status = getStatus(d);
- return !status.testFlag(QDateTimePrivate::ValidDate) &&
- !status.testFlag(QDateTimePrivate::ValidTime);
+ // If date or time is invalid, we don't set datetime valid.
+ return !getStatus(d).testAnyFlag(QDateTimePrivate::ValidityMask);
}
/*!
- Returns \c true if both the date and the time are valid and they are valid in
- the current Qt::TimeSpec, otherwise returns \c false.
+ Returns \c true if this datetime represents a definite moment, otherwise \c false.
- If the timeSpec() is Qt::LocalTime or Qt::TimeZone then the date and time are
- checked to see if they fall in the Standard Time to Daylight-Saving Time transition
- hour, i.e. if the transition is at 2am and the clock goes forward to 3am
- then the time from 02:00:00 to 02:59:59.999 is considered to be invalid.
+ A datetime is valid if both its date and its time are valid and the time
+ representation used gives a valid meaning to their combination. When the
+ time representation is a specific time-zone or local time, there may be
+ times on some dates that the zone skips in its representation, as when a
+ daylight-saving transition skips an hour (typically during a night in
+ spring). For example, if DST ends at 2am with the clock advancing to 3am,
+ then datetimes from 02:00:00 to 02:59:59.999 on that day are invalid.
\sa QDateTime::YearRange, QDate::isValid(), QTime::isValid()
*/
bool QDateTime::isValid() const
{
- auto status = getStatus(d);
- return status & QDateTimePrivate::ValidDateTime;
+ return getStatus(d).testFlag(QDateTimePrivate::ValidDateTime);
}
/*!
Returns the date part of the datetime.
- \sa setDate(), time(), timeSpec()
+ \sa setDate(), time(), timeRepresentation()
*/
QDate QDateTime::date() const
{
- auto status = getStatus(d);
- if (!status.testFlag(QDateTimePrivate::ValidDate))
- return QDate();
- QDate dt;
- msecsToTime(getMSecs(d), &dt, nullptr);
- return dt;
+ return getStatus(d).testFlag(QDateTimePrivate::ValidDate) ? msecsToDate(getMSecs(d)) : QDate();
}
/*!
Returns the time part of the datetime.
- \sa setTime(), date(), timeSpec()
+ \sa setTime(), date(), timeRepresentation()
*/
QTime QDateTime::time() const
{
- auto status = getStatus(d);
- if (!status.testFlag(QDateTimePrivate::ValidTime))
- return QTime();
- QTime tm;
- msecsToTime(getMSecs(d), nullptr, &tm);
- return tm;
+ return getStatus(d).testFlag(QDateTimePrivate::ValidTime) ? msecsToTime(getMSecs(d)) : QTime();
}
/*!
Returns the time specification of the datetime.
- \sa setTimeSpec(), date(), time(), Qt::TimeSpec
+ This classifies its time representation as local time, UTC, a fixed offset
+ from UTC (without indicating the offset) or a time zone (without giving the
+ details of that time zone). Equivalent to
+ \c{timeRepresentation().timeSpec()}.
+
+ \sa setTimeSpec(), timeRepresentation(), date(), time()
*/
Qt::TimeSpec QDateTime::timeSpec() const
@@ -3468,41 +4129,51 @@ Qt::TimeSpec QDateTime::timeSpec() const
return getSpec(d);
}
+/*!
+ \since 6.5
+ Returns a QTimeZone identifying how this datetime represents time.
+
+ The timeSpec() of the returned QTimeZone will coincide with that of this
+ datetime; if it is not Qt::TimeZone then the returned QTimeZone is a time
+ representation. When their timeSpec() is Qt::OffsetFromUTC, the returned
+ QTimeZone's fixedSecondsAheadOfUtc() supplies the offset. When timeSpec()
+ is Qt::TimeZone, the QTimeZone object itself is the full representation of
+ that time zone.
+
+ \sa timeZone(), setTimeZone(), QTimeZone::asBackendZone()
+*/
+
+QTimeZone QDateTime::timeRepresentation() const
+{
+ return d.timeZone();
+}
+
#if QT_CONFIG(timezone)
/*!
\since 5.2
Returns the time zone of the datetime.
- If the timeSpec() is Qt::LocalTime then an instance of the current system
- time zone will be returned. Note however that if you copy this time zone
- the instance will not remain in sync if the system time zone changes.
+ The result is the same as \c{timeRepresentation().asBackendZone()}. In all
+ cases, the result's \l {QTimeZone::timeSpec()}{timeSpec()} is Qt::TimeZone.
+
+ When timeSpec() is Qt::LocalTime, the result will describe local time at the
+ time this method was called. It will not reflect subsequent changes to the
+ system time zone, even when the QDateTime from which it was obtained does.
- \sa setTimeZone(), Qt::TimeSpec
+ \sa timeRepresentation(), setTimeZone(), Qt::TimeSpec, QTimeZone::asBackendZone()
*/
QTimeZone QDateTime::timeZone() const
{
- switch (getSpec(d)) {
- case Qt::UTC:
- return QTimeZone::utc();
- case Qt::OffsetFromUTC:
- return QTimeZone(d->m_offsetFromUtc);
- case Qt::TimeZone:
- if (d->m_timeZone.isValid())
- return d->m_timeZone;
- break;
- case Qt::LocalTime:
- return QTimeZone::systemTimeZone();
- }
- return QTimeZone();
+ return d.timeZone().asBackendZone();
}
#endif // timezone
/*!
\since 5.2
- Returns this date-time's Offset From UTC in seconds.
+ Returns this datetime's Offset From UTC in seconds.
The result depends on timeSpec():
\list
@@ -3513,27 +4184,28 @@ QTimeZone QDateTime::timeZone() const
\endlist
For the last two, the offset at this date and time will be returned, taking
- account of Daylight-Saving Offset unless the date precedes the start of
- 1970. The offset is the difference between the local time or time in the
- given time-zone and UTC time; it is positive in time-zones ahead of UTC
- (East of The Prime Meridian), negative for those behind UTC (West of The
- Prime Meridian).
+ account of Daylight-Saving Offset. The offset is the difference between the
+ local time or time in the given time-zone and UTC time; it is positive in
+ time-zones ahead of UTC (East of The Prime Meridian), negative for those
+ behind UTC (West of The Prime Meridian).
\sa setOffsetFromUtc()
*/
int QDateTime::offsetFromUtc() const
{
+ const auto status = getStatus(d);
+ if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
+ return 0;
+ // But allow invalid date-time (e.g. gap's resolution) to report its offset.
if (!d.isShort())
return d->m_offsetFromUtc;
- if (!isValid())
- return 0;
- auto spec = getSpec(d);
+ auto spec = extractSpec(status);
if (spec == Qt::LocalTime) {
- // we didn't cache the value, so we need to calculate it now...
- qint64 msecs = getMSecs(d);
- return (msecs - toMSecsSinceEpoch()) / 1000;
+ // We didn't cache the value, so we need to calculate it:
+ const auto resolve = toTransitionOptions(extractDaylightStatus(status));
+ return QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve).offset;
}
Q_ASSERT(spec == Qt::UTC);
@@ -3543,22 +4215,22 @@ int QDateTime::offsetFromUtc() const
/*!
\since 5.2
- Returns the Time Zone Abbreviation for the datetime.
-
- If the timeSpec() is Qt::UTC this will be "UTC".
+ Returns the Time Zone Abbreviation for this datetime.
- If the timeSpec() is Qt::OffsetFromUTC this will be in the format
- "UTC[+-]00:00".
+ The returned string depends on timeSpec():
- If the timeSpec() is Qt::LocalTime then the host system is queried for the
- correct abbreviation.
-
- Note that abbreviations may or may not be localized.
+ \list
+ \li For Qt::UTC it is "UTC".
+ \li For Qt::OffsetFromUTC it will be in the format "UTC±00:00".
+ \li For Qt::LocalTime, the host system is queried.
+ \li For Qt::TimeZone, the associated QTimeZone object is queried.
+ \endlist
- Note too that the abbreviation is not guaranteed to be a unique value,
- i.e. different time zones may have the same abbreviation.
+ \note The abbreviation is not guaranteed to be unique, i.e. different time
+ zones may have the same abbreviation. For Qt::LocalTime and Qt::TimeZone,
+ when returned by the host system, the abbreviation may be localized.
- \sa timeSpec()
+ \sa timeSpec(), QTimeZone::abbreviation()
*/
QString QDateTime::timeZoneAbbreviation() const
@@ -3568,22 +4240,19 @@ QString QDateTime::timeZoneAbbreviation() const
switch (getSpec(d)) {
case Qt::UTC:
- return QLatin1String("UTC");
+ return "UTC"_L1;
case Qt::OffsetFromUTC:
- return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
+ return "UTC"_L1 + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
case Qt::TimeZone:
#if !QT_CONFIG(timezone)
break;
#else
Q_ASSERT(d->m_timeZone.isValid());
- return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
+ return d->m_timeZone.abbreviation(*this);
#endif // timezone
- case Qt::LocalTime: {
- QString abbrev;
- auto status = extractDaylightStatus(getStatus(d));
- localMSecsToEpochMSecs(getMSecs(d), &status, nullptr, nullptr, &abbrev);
- return abbrev;
- }
+ case Qt::LocalTime:
+ return QDateTimePrivate::localNameAtMillis(getMSecs(d),
+ extractDaylightStatus(getStatus(d)));
}
return QString();
}
@@ -3613,28 +4282,43 @@ bool QDateTime::isDaylightTime() const
break;
#else
Q_ASSERT(d->m_timeZone.isValid());
+ if (auto dst = extractDaylightStatus(getStatus(d));
+ dst != QDateTimePrivate::UnknownDaylightTime) {
+ return dst == QDateTimePrivate::DaylightTime;
+ }
return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
#endif // timezone
case Qt::LocalTime: {
- auto status = extractDaylightStatus(getStatus(d));
- if (status == QDateTimePrivate::UnknownDaylightTime)
- localMSecsToEpochMSecs(getMSecs(d), &status);
- return (status == QDateTimePrivate::DaylightTime);
+ auto dst = extractDaylightStatus(getStatus(d));
+ if (dst == QDateTimePrivate::UnknownDaylightTime) {
+ dst = QDateTimePrivate::localStateAtMillis(
+ getMSecs(d), toTransitionOptions(TransitionResolution::LegacyBehavior)).dst;
+ }
+ return dst == QDateTimePrivate::DaylightTime;
}
}
return false;
}
/*!
- Sets the date part of this datetime to \a date. If no time is set yet, it
- is set to midnight. If \a date is invalid, this QDateTime becomes invalid.
+ Sets the date part of this datetime to \a date.
+
+ If no time is set yet, it is set to midnight. If \a date is invalid, this
+ QDateTime becomes invalid.
+
+ If \a date and time() describe a moment close to a transition for this
+ datetime's time representation, \a resolve controls how that situation is
+ resolved.
- \sa date(), setTime(), setTimeSpec()
+ \include qdatetime.cpp pre-resolve-note
+
+ \sa date(), setTime(), setTimeZone()
*/
-void QDateTime::setDate(QDate date)
+void QDateTime::setDate(QDate date, TransitionResolution resolve)
{
setDateTime(d, date, time());
+ checkValidDateTime(d, resolve);
}
/*!
@@ -3647,17 +4331,27 @@ void QDateTime::setDate(QDate date)
dt.setTime(QTime());
\endcode
- \sa time(), setDate(), setTimeSpec()
+ If date() and \a time describe a moment close to a transition for this
+ datetime's time representation, \a resolve controls how that situation is
+ resolved.
+
+ \include qdatetime.cpp pre-resolve-note
+
+ \sa time(), setDate(), setTimeZone()
*/
-void QDateTime::setTime(QTime time)
+void QDateTime::setTime(QTime time, TransitionResolution resolve)
{
setDateTime(d, date(), time);
+ checkValidDateTime(d, resolve);
}
+#if QT_DEPRECATED_SINCE(6, 9)
/*!
+ \deprecated [6.9] Use setTimeZone() instead
+
Sets the time specification used in this datetime to \a spec.
- The datetime will refer to a different point in time.
+ The datetime may refer to a different point in time.
If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
to Qt::UTC, i.e. an effective offset of 0.
@@ -3668,20 +4362,21 @@ void QDateTime::setTime(QTime time)
Example:
\snippet code/src_corelib_time_qdatetime.cpp 19
- \sa timeSpec(), setDate(), setTime(), setTimeZone(), Qt::TimeSpec
+ \sa setTimeZone(), timeSpec(), toTimeSpec(), setDate(), setTime()
*/
void QDateTime::setTimeSpec(Qt::TimeSpec spec)
{
- QT_PREPEND_NAMESPACE(setTimeSpec(d, spec, 0));
- checkValidDateTime(d);
+ reviseTimeZone(d, asTimeZone(spec, 0, "QDateTime::setTimeSpec"),
+ TransitionResolution::LegacyBehavior);
}
/*!
\since 5.2
+ \deprecated [6.9] Use setTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds)) instead
Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
- The datetime will refer to a different point in time.
+ The datetime may refer to a different point in time.
The maximum and minimum offset is 14 positive or negative hours. If
\a offsetSeconds is larger or smaller than that, then the result is
@@ -3689,42 +4384,46 @@ void QDateTime::setTimeSpec(Qt::TimeSpec spec)
If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
- \sa isValid(), offsetFromUtc()
+ \sa setTimeZone(), isValid(), offsetFromUtc(), toOffsetFromUtc()
*/
void QDateTime::setOffsetFromUtc(int offsetSeconds)
{
- QT_PREPEND_NAMESPACE(setTimeSpec(d, Qt::OffsetFromUTC, offsetSeconds));
- checkValidDateTime(d);
+ reviseTimeZone(d, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds),
+ TransitionResolution::Reject);
}
+#endif // 6.9 deprecations
-#if QT_CONFIG(timezone)
/*!
\since 5.2
Sets the time zone used in this datetime to \a toZone.
- The datetime will refer to a different point in time.
- If \a toZone is invalid then the datetime will be invalid.
+ The datetime may refer to a different point in time. It uses the time
+ representation of \a toZone, which may change the meaning of its unchanged
+ date() and time().
+
+ If \a toZone is invalid then the datetime will be invalid. Otherwise, this
+ datetime's timeSpec() after the call will match \c{toZone.timeSpec()}.
+
+ If date() and time() describe a moment close to a transition for \a toZone,
+ \a resolve controls how that situation is resolved.
+
+ \include qdatetime.cpp pre-resolve-note
- \sa timeZone(), Qt::TimeSpec
+ \sa timeRepresentation(), timeZone(), Qt::TimeSpec
*/
-void QDateTime::setTimeZone(const QTimeZone &toZone)
+void QDateTime::setTimeZone(const QTimeZone &toZone, TransitionResolution resolve)
{
- d.detach(); // always detach
- d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
- d->m_offsetFromUtc = 0;
- d->m_timeZone = toZone;
- refreshDateTime(d);
+ reviseTimeZone(d, toZone, resolve);
}
-#endif // timezone
/*!
\since 4.7
- Returns the datetime as the number of milliseconds that have passed
- since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
+ Returns the datetime as a number of milliseconds after the start, in UTC, of
+ the year 1970.
On systems that do not support time zones, this function will
behave as if local time were Qt::UTC.
@@ -3733,45 +4432,54 @@ void QDateTime::setTimeZone(const QTimeZone &toZone)
this object is not valid. However, for all valid dates, this function
returns a unique value.
- \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
+ \sa toSecsSinceEpoch(), setMSecsSinceEpoch(), fromMSecsSinceEpoch()
*/
qint64 QDateTime::toMSecsSinceEpoch() const
{
// Note: QDateTimeParser relies on this producing a useful result, even when
// !isValid(), at least when the invalidity is a time in a fall-back (that
// we'll have adjusted to lie outside it, but marked invalid because it's
- // not what was asked for). Other things may be doing similar.
- switch (getSpec(d)) {
+ // not what was asked for). Other things may be doing similar. But that's
+ // only relevant when we got enough data for resolution to find it invalid.
+ const auto status = getStatus(d);
+ if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
+ return 0;
+
+ switch (extractSpec(status)) {
case Qt::UTC:
return getMSecs(d);
case Qt::OffsetFromUTC:
- return d->m_msecs - (d->m_offsetFromUtc * 1000);
+ Q_ASSERT(!d.isShort());
+ return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
- case Qt::LocalTime: {
- // recalculate the local timezone
- auto status = extractDaylightStatus(getStatus(d));
- return localMSecsToEpochMSecs(getMSecs(d), &status);
- }
+ case Qt::LocalTime:
+ if (status.testFlag(QDateTimePrivate::ShortData)) {
+ // Short form has nowhere to cache the offset, so recompute.
+ const auto resolve = toTransitionOptions(extractDaylightStatus(getStatus(d)));
+ const auto state = QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve);
+ return state.when - state.offset * MSECS_PER_SEC;
+ }
+ // Use the offset saved by refreshZonedDateTime() on creation.
+ return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
case Qt::TimeZone:
+ Q_ASSERT(!d.isShort());
#if QT_CONFIG(timezone)
- if (d->m_timeZone.isValid()) {
- return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
- extractDaylightStatus(getStatus(d)));
- }
+ // Use offset refreshZonedDateTime() saved on creation:
+ if (d->m_timeZone.isValid())
+ return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
#endif
return 0;
}
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
/*!
\since 5.8
- Returns the datetime as the number of seconds that have passed since
- 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
+ Returns the datetime as a number of seconds after the start, in UTC, of the
+ year 1970.
On systems that do not support time zones, this function will
behave as if local time were Qt::UTC.
@@ -3780,111 +4488,97 @@ qint64 QDateTime::toMSecsSinceEpoch() const
this object is not valid. However, for all valid dates, this function
returns a unique value.
- \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
+ \sa toMSecsSinceEpoch(), fromSecsSinceEpoch(), setSecsSinceEpoch()
*/
qint64 QDateTime::toSecsSinceEpoch() const
{
- return toMSecsSinceEpoch() / 1000;
+ return toMSecsSinceEpoch() / MSECS_PER_SEC;
}
/*!
\since 4.7
- Sets the date and time given the number of milliseconds \a msecs that have
- passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
- (Qt::UTC). On systems that do not support time zones this function
- will behave as if local time were Qt::UTC.
+ Sets the datetime to represent a moment a given number, \a msecs, of
+ milliseconds after the start, in UTC, of the year 1970.
+
+ On systems that do not support time zones, this function will
+ behave as if local time were Qt::UTC.
Note that passing the minimum of \c qint64
(\c{std::numeric_limits<qint64>::min()}) to \a msecs will result in
undefined behavior.
- \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
+ \sa setSecsSinceEpoch(), toMSecsSinceEpoch(), fromMSecsSinceEpoch()
*/
void QDateTime::setMSecsSinceEpoch(qint64 msecs)
{
- const auto spec = getSpec(d);
auto status = getStatus(d);
+ const auto spec = extractSpec(status);
+ Q_ASSERT(specCanBeSmall(spec) || !d.isShort());
+ QDateTimePrivate::ZoneState state(msecs);
status &= ~QDateTimePrivate::ValidityMask;
- switch (spec) {
- case Qt::UTC:
- status = status
- | QDateTimePrivate::ValidDate
- | QDateTimePrivate::ValidTime
- | QDateTimePrivate::ValidDateTime;
- break;
- case Qt::OffsetFromUTC:
- msecs = msecs + (d->m_offsetFromUtc * 1000);
- status = status
- | QDateTimePrivate::ValidDate
- | QDateTimePrivate::ValidTime
- | QDateTimePrivate::ValidDateTime;
- break;
- case Qt::TimeZone:
- Q_ASSERT(!d.isShort());
+ if (QTimeZone::isUtcOrFixedOffset(spec)) {
+ if (spec == Qt::OffsetFromUTC)
+ state.offset = d->m_offsetFromUtc;
+ if (!state.offset || !qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))
+ status |= QDateTimePrivate::ValidityMask;
+ } else if (spec == Qt::LocalTime) {
+ state = QDateTimePrivate::expressUtcAsLocal(msecs);
+ if (state.valid)
+ status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask, state.dst);
#if QT_CONFIG(timezone)
- d.detach();
- if (!d->m_timeZone.isValid())
- break;
- // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
- // but all affected times afterwards will have DST applied.
- if (msecs >= 0) {
- status = mergeDaylightStatus(status,
- d->m_timeZone.d->isDaylightTime(msecs)
- ? QDateTimePrivate::DaylightTime
- : QDateTimePrivate::StandardTime);
- d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
- } else {
- status = mergeDaylightStatus(status, QDateTimePrivate::StandardTime);
- d->m_offsetFromUtc = d->m_timeZone.d->standardTimeOffset(msecs);
- }
- msecs = msecs + (d->m_offsetFromUtc * 1000);
- status = status
- | QDateTimePrivate::ValidDate
- | QDateTimePrivate::ValidTime
- | QDateTimePrivate::ValidDateTime;
+ } else if (spec == Qt::TimeZone && (d.detach(), d->m_timeZone.isValid())) {
+ const auto data = d->m_timeZone.d->data(msecs);
+ if (Q_LIKELY(data.offsetFromUtc != QTimeZonePrivate::invalidSeconds())) {
+ state.offset = data.offsetFromUtc;
+ Q_ASSERT(state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY);
+ if (!state.offset
+ || !Q_UNLIKELY(qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))) {
+ d->m_status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask,
+ data.daylightTimeOffset
+ ? QDateTimePrivate::DaylightTime
+ : QDateTimePrivate::StandardTime);
+ d->m_msecs = state.when;
+ d->m_offsetFromUtc = state.offset;
+ return;
+ } // else: zone can't represent this UTC time
+ } // else: zone unable to represent given UTC time (should only happen on overflow).
#endif // timezone
- break;
- case Qt::LocalTime: {
- QDate dt;
- QTime tm;
- QDateTimePrivate::DaylightStatus dstStatus;
- epochMSecsToLocalTime(msecs, &dt, &tm, &dstStatus);
- setDateTime(d, dt, tm);
- msecs = getMSecs(d);
- status = mergeDaylightStatus(getStatus(d), dstStatus);
- break;
- }
}
+ Q_ASSERT(!status.testFlag(QDateTimePrivate::ValidDateTime)
+ || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
- if (msecsCanBeSmall(msecs) && d.isShort()) {
+ if (msecsCanBeSmall(state.when) && d.isShort()) {
// we can keep short
- d.data.msecs = qintptr(msecs);
- d.data.status = status;
+ d.data.msecs = qintptr(state.when);
+ d.data.status = status.toInt();
} else {
d.detach();
d->m_status = status & ~QDateTimePrivate::ShortData;
- d->m_msecs = msecs;
+ d->m_msecs = state.when;
+ d->m_offsetFromUtc = state.offset;
}
-
- if (spec == Qt::LocalTime || spec == Qt::TimeZone)
- refreshDateTime(d);
}
/*!
\since 5.8
- Sets the date and time given the number of seconds \a secs that have
- passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
- (Qt::UTC). On systems that do not support time zones this function
- will behave as if local time were Qt::UTC.
+ Sets the datetime to represent a moment a given number, \a secs, of seconds
+ after the start, in UTC, of the year 1970.
+
+ On systems that do not support time zones, this function will
+ behave as if local time were Qt::UTC.
- \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
+ \sa setMSecsSinceEpoch(), toSecsSinceEpoch(), fromSecsSinceEpoch()
*/
void QDateTime::setSecsSinceEpoch(qint64 secs)
{
- setMSecsSinceEpoch(secs * 1000);
+ qint64 msecs;
+ if (!qMulOverflow(secs, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
+ setMSecsSinceEpoch(msecs);
+ else
+ d.invalidate();
}
#if QT_CONFIG(datestring) // depends on, so implies, textdate
@@ -3898,15 +4592,14 @@ void QDateTime::setSecsSinceEpoch(qint64 secs)
formatting is "Wed May 20 03:40:13 1998". For localized formatting, see
\l{QLocale::toString()}.
- If the \a format is Qt::ISODate, the string format corresponds
- to the ISO 8601 extended specification for representations of
- dates and times, taking the form yyyy-MM-ddTHH:mm:ss[Z|[+|-]HH:mm],
- depending on the timeSpec() of the QDateTime. If the timeSpec()
- is Qt::UTC, Z will be appended to the string; if the timeSpec() is
- Qt::OffsetFromUTC, the offset in hours and minutes from UTC will
- be appended to the string. To include milliseconds in the ISO 8601
+ If the \a format is Qt::ISODate, the string format corresponds to the ISO
+ 8601 extended specification for representations of dates and times, taking
+ the form yyyy-MM-ddTHH:mm:ss[Z|±HH:mm], depending on the timeSpec() of the
+ QDateTime. If the timeSpec() is Qt::UTC, Z will be appended to the string;
+ if the timeSpec() is Qt::OffsetFromUTC, the offset in hours and minutes from
+ UTC will be appended to the string. To include milliseconds in the ISO 8601
date, use the \a format Qt::ISODateWithMs, which corresponds to
- yyyy-MM-ddTHH:mm:ss.zzz[Z|[+|-]HH:mm].
+ yyyy-MM-ddTHH:mm:ss.zzz[Z|±HH:mm].
If the \a format is Qt::RFC2822Date, the string is formatted
following \l{RFC 2822}.
@@ -3932,22 +4625,27 @@ QString QDateTime::toString(Qt::DateFormat format) const
return buf;
default:
case Qt::TextDate: {
- const QPair<QDate, QTime> p = getDateTime(d);
+ const std::pair<QDate, QTime> p = getDateTime(d);
buf = toStringTextDate(p.first);
// Insert time between date's day and year:
- buf.insert(buf.lastIndexOf(QLatin1Char(' ')),
- QLatin1Char(' ') + p.second.toString(Qt::TextDate));
+ buf.insert(buf.lastIndexOf(u' '),
+ u' ' + p.second.toString(Qt::TextDate));
// Append zone/offset indicator, as appropriate:
switch (timeSpec()) {
case Qt::LocalTime:
break;
#if QT_CONFIG(timezone)
case Qt::TimeZone:
- buf += QLatin1Char(' ') + d->m_timeZone.abbreviation(*this);
+ buf += u' ' + d->m_timeZone.displayName(
+ *this, QTimeZone::OffsetName, QLocale::c());
break;
#endif
default:
- buf += QLatin1String(" GMT");
+#if 0 // ### Qt 7 GMT: use UTC instead, see qnamespace.qdoc documentation
+ buf += " UTC"_L1;
+#else
+ buf += " GMT"_L1;
+#endif
if (getSpec(d) == Qt::OffsetFromUTC)
buf += toOffsetString(Qt::TextDate, offsetFromUtc());
}
@@ -3955,19 +4653,17 @@ QString QDateTime::toString(Qt::DateFormat format) const
}
case Qt::ISODate:
case Qt::ISODateWithMs: {
- const QPair<QDate, QTime> p = getDateTime(d);
+ const std::pair<QDate, QTime> p = getDateTime(d);
buf = toStringIsoDate(p.first);
if (buf.isEmpty())
return QString(); // failed to convert
- buf += QLatin1Char('T') + p.second.toString(format);
+ buf += u'T' + p.second.toString(format);
switch (getSpec(d)) {
case Qt::UTC:
- buf += QLatin1Char('Z');
+ buf += u'Z';
break;
case Qt::OffsetFromUTC:
-#if QT_CONFIG(timezone)
case Qt::TimeZone:
-#endif
buf += toOffsetString(Qt::ISODate, offsetFromUtc());
break;
default:
@@ -3981,12 +4677,14 @@ QString QDateTime::toString(Qt::DateFormat format) const
/*!
\fn QString QDateTime::toString(const QString &format, QCalendar cal) const
\fn QString QDateTime::toString(QStringView format, QCalendar cal) const
+ \since 5.14
Returns the datetime as a string. The \a format parameter determines the
- format of the result string. If \a cal is supplied, it determines the calendar
- used to represent the date; it defaults to Gregorian. See QTime::toString()
- and QDate::toString() for the supported specifiers for time and date,
- respectively.
+ format of the result string. If \a cal is supplied, it determines the
+ calendar used to represent the date; it defaults to Gregorian. Prior to Qt
+ 5.14, there was no \a cal parameter and the Gregorian calendar was always
+ used. See QTime::toString() and QDate::toString() for the supported
+ specifiers for time and date, respectively, in the \a format parameter.
Any sequence of characters enclosed in single quotes will be included
verbatim in the output string (stripped of the quotes), even if it contains
@@ -4013,9 +4711,9 @@ QString QDateTime::toString(Qt::DateFormat format) const
If the datetime is invalid, an empty string will be returned.
- \note If localized month and day names are desired, please switch to using
- QLocale::system().toString() as QDateTime methods shall change to use
- English (C locale) names at Qt 6.
+ \note Day and month names as well as AM/PM indicators are given in English
+ (C locale). To get localized month and day names and localized forms of
+ AM/PM, use QLocale::system().toDateTime().
\sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
*/
@@ -4024,39 +4722,58 @@ QString QDateTime::toString(QStringView format, QCalendar cal) const
return QLocale::c().toString(*this, format, cal);
}
-# if QT_STRINGVIEW_LEVEL < 2
-QString QDateTime::toString(const QString &format, QCalendar cal) const
+// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
+/*!
+ \overload
+ \since 5.10
+*/
+QString QDateTime::toString(QStringView format) const
+{
+ return QLocale::c().toString(*this, format, QCalendar());
+}
+
+/*!
+ \overload
+ \since 4.6
+*/
+QString QDateTime::toString(const QString &format) const
{
- return toString(qToStringViewIgnoringNull(format), cal);
+ return QLocale::c().toString(*this, qToStringViewIgnoringNull(format), QCalendar());
}
-# endif
#endif // datestring
-static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QTime *time)
-{
- /*
- If we have just adjusted to a day with a DST transition, our given time
- may lie in the transition hour (either missing or duplicated). For any
- other time, telling mktime (deep in the bowels of localMSecsToEpochMSecs)
- we don't know its DST-ness will produce no adjustment (just a decision as
- to its DST-ness); but for a time in spring's missing hour it'll adjust the
- time while picking a DST-ness. (Handling of autumn is trickier, as either
- DST-ness is valid, without adjusting the time. We might want to propagate
- the daylight status in that case, but it's hard to do so without breaking
- (far more common) other cases; and it makes little difference, as the two
- answers do then differ only in DST-ness.)
- */
- auto spec = getSpec(d);
- if (spec == Qt::LocalTime) {
- QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
- localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
-#if QT_CONFIG(timezone)
- } else if (spec == Qt::TimeZone && d->m_timeZone.isValid()) {
- QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
- d->m_timeZone,
- QDateTimePrivate::UnknownDaylightTime,
- date, time);
-#endif // timezone
+static inline void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime time, bool forward)
+{
+ const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(
+ forward ? QDateTime::TransitionResolution::RelativeToBefore
+ : QDateTime::TransitionResolution::RelativeToAfter);
+ auto status = getStatus(d);
+ Q_ASSERT(status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime
+ | QDateTimePrivate::ValidDateTime));
+ auto spec = extractSpec(status);
+ if (QTimeZone::isUtcOrFixedOffset(spec)) {
+ setDateTime(d, date, time);
+ refreshSimpleDateTime(d);
+ return;
+ }
+ qint64 local = timeToMSecs(date, time);
+ const QDateTimePrivate::ZoneState state = stateAtMillis(d.timeZone(), local, resolve);
+ Q_ASSERT(state.valid || state.dst == QDateTimePrivate::UnknownDaylightTime);
+ if (state.dst == QDateTimePrivate::UnknownDaylightTime)
+ status.setFlag(QDateTimePrivate::ValidDateTime, false);
+ else
+ status = mergeDaylightStatus(status | QDateTimePrivate::ValidDateTime, state.dst);
+
+ if (status & QDateTimePrivate::ShortData) {
+ d.data.msecs = state.when;
+ d.data.status = status.toInt();
+ } else {
+ d.detach();
+ d->m_status = status;
+ if (state.valid) {
+ d->m_msecs = state.when;
+ d->m_offsetFromUtc = state.offset;
+ }
}
}
@@ -4065,24 +4782,24 @@ static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date,
later than the datetime of this object (or earlier if \a ndays is
negative).
- If the timeSpec() is Qt::LocalTime and the resulting
- date and time fall in the Standard Time to Daylight-Saving Time transition
- hour then the result will be adjusted accordingly, i.e. if the transition
- is at 2am and the clock goes forward to 3am and the result falls between
- 2am and 3am then the result will be adjusted to fall after 3am.
+ If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
+ and time fall in the Standard Time to Daylight-Saving Time transition hour
+ then the result will be just beyond this gap, in the direction of change.
+ If the transition is at 2am and the clock goes forward to 3am, the result of
+ aiming between 2am and 3am will be adjusted to fall before 2am (if \c{ndays
+ < 0}) or after 3am (otherwise).
- \sa daysTo(), addMonths(), addYears(), addSecs()
+ \sa daysTo(), addMonths(), addYears(), addSecs(), {Timezone transitions}
*/
QDateTime QDateTime::addDays(qint64 ndays) const
{
+ if (isNull())
+ return QDateTime();
+
QDateTime dt(*this);
- QPair<QDate, QTime> p = getDateTime(d);
- QDate &date = p.first;
- QTime &time = p.second;
- date = date.addDays(ndays);
- massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
+ std::pair<QDate, QTime> p = getDateTime(d);
+ massageAdjustedDateTime(dt.d, p.first.addDays(ndays), p.second, ndays >= 0);
return dt;
}
@@ -4091,24 +4808,24 @@ QDateTime QDateTime::addDays(qint64 ndays) const
later than the datetime of this object (or earlier if \a nmonths
is negative).
- If the timeSpec() is Qt::LocalTime and the resulting
- date and time fall in the Standard Time to Daylight-Saving Time transition
- hour then the result will be adjusted accordingly, i.e. if the transition
- is at 2am and the clock goes forward to 3am and the result falls between
- 2am and 3am then the result will be adjusted to fall after 3am.
+ If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
+ and time fall in the Standard Time to Daylight-Saving Time transition hour
+ then the result will be just beyond this gap, in the direction of change.
+ If the transition is at 2am and the clock goes forward to 3am, the result of
+ aiming between 2am and 3am will be adjusted to fall before 2am (if
+ \c{nmonths < 0}) or after 3am (otherwise).
- \sa daysTo(), addDays(), addYears(), addSecs()
+ \sa daysTo(), addDays(), addYears(), addSecs(), {Timezone transitions}
*/
QDateTime QDateTime::addMonths(int nmonths) const
{
+ if (isNull())
+ return QDateTime();
+
QDateTime dt(*this);
- QPair<QDate, QTime> p = getDateTime(d);
- QDate &date = p.first;
- QTime &time = p.second;
- date = date.addMonths(nmonths);
- massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
+ std::pair<QDate, QTime> p = getDateTime(d);
+ massageAdjustedDateTime(dt.d, p.first.addMonths(nmonths), p.second, nmonths >= 0);
return dt;
}
@@ -4117,24 +4834,24 @@ QDateTime QDateTime::addMonths(int nmonths) const
later than the datetime of this object (or earlier if \a nyears is
negative).
- If the timeSpec() is Qt::LocalTime and the resulting
- date and time fall in the Standard Time to Daylight-Saving Time transition
- hour then the result will be adjusted accordingly, i.e. if the transition
- is at 2am and the clock goes forward to 3am and the result falls between
- 2am and 3am then the result will be adjusted to fall after 3am.
+ If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
+ and time fall in the Standard Time to Daylight-Saving Time transition hour
+ then the result will be just beyond this gap, in the direction of change.
+ If the transition is at 2am and the clock goes forward to 3am, the result of
+ aiming between 2am and 3am will be adjusted to fall before 2am (if \c{nyears
+ < 0}) or after 3am (otherwise).
- \sa daysTo(), addDays(), addMonths(), addSecs()
+ \sa daysTo(), addDays(), addMonths(), addSecs(), {Timezone transitions}
*/
QDateTime QDateTime::addYears(int nyears) const
{
+ if (isNull())
+ return QDateTime();
+
QDateTime dt(*this);
- QPair<QDate, QTime> p = getDateTime(d);
- QDate &date = p.first;
- QTime &time = p.second;
- date = date.addYears(nyears);
- massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
+ std::pair<QDate, QTime> p = getDateTime(d);
+ massageAdjustedDateTime(dt.d, p.first.addYears(nyears), p.second, nyears >= 0);
return dt;
}
@@ -4150,11 +4867,14 @@ QDateTime QDateTime::addYears(int nyears) const
QDateTime QDateTime::addSecs(qint64 s) const
{
- return addMSecs(s * 1000);
+ qint64 msecs;
+ if (qMulOverflow(s, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
+ return QDateTime();
+ return addMSecs(msecs);
}
/*!
- Returns a QDateTime object containing a datetime \a msecs miliseconds
+ Returns a QDateTime object containing a datetime \a msecs milliseconds
later than the datetime of this object (or earlier if \a msecs is
negative).
@@ -4168,30 +4888,52 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const
return QDateTime();
QDateTime dt(*this);
- auto spec = getSpec(d);
- if (spec == Qt::LocalTime || spec == Qt::TimeZone) {
- // Convert to real UTC first in case crosses DST transition
- dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs);
- } else {
+ switch (getSpec(d)) {
+ case Qt::LocalTime:
+ case Qt::TimeZone:
+ // Convert to real UTC first in case this crosses a DST transition:
+ if (!qAddOverflow(toMSecsSinceEpoch(), msecs, &msecs))
+ dt.setMSecsSinceEpoch(msecs);
+ else
+ dt.d.invalidate();
+ break;
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
// No need to convert, just add on
- if (d.isShort()) {
- // need to check if we need to enlarge first
- msecs += dt.d.data.msecs;
- if (msecsCanBeSmall(msecs)) {
- dt.d.data.msecs = qintptr(msecs);
- } else {
- dt.d.detach();
- dt.d->m_msecs = msecs;
- }
+ if (qAddOverflow(getMSecs(d), msecs, &msecs)) {
+ dt.d.invalidate();
+ } else if (d.isShort() && msecsCanBeSmall(msecs)) {
+ dt.d.data.msecs = qintptr(msecs);
} else {
dt.d.detach();
- dt.d->m_msecs += msecs;
+ dt.d->m_msecs = msecs;
}
+ break;
}
return dt;
}
/*!
+ \fn QDateTime QDateTime::addDuration(std::chrono::milliseconds msecs) const
+
+ \since 6.4
+
+ Returns a QDateTime object containing a datetime \a msecs milliseconds
+ later than the datetime of this object (or earlier if \a msecs is
+ negative).
+
+ If this datetime is invalid, an invalid datetime will be returned.
+
+ \note Adding durations expressed in \c{std::chrono::months} or
+ \c{std::chrono::years} does not yield the same result obtained by using
+ addMonths() or addYears(). The former are fixed durations, calculated in
+ relation to the solar year; the latter use the Gregorian calendar definitions
+ of months/years.
+
+ \sa addMSecs(), msecsTo(), addDays(), addMonths(), addYears()
+*/
+
+/*!
Returns the number of days from this datetime to the \a other
datetime. The number of days is counted as the number of times
midnight is reached between this datetime to the \a other
@@ -4231,7 +4973,7 @@ qint64 QDateTime::daysTo(const QDateTime &other) const
qint64 QDateTime::secsTo(const QDateTime &other) const
{
- return (msecsTo(other) / 1000);
+ return msecsTo(other) / MSECS_PER_SEC;
}
/*!
@@ -4257,75 +4999,172 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const
}
/*!
- Returns a copy of this datetime converted to the given time
- \a spec.
+ \fn std::chrono::milliseconds QDateTime::operator-(const QDateTime &lhs, const QDateTime &rhs)
+ \since 6.4
+
+ Returns the number of milliseconds between \a lhs and \a rhs.
+ If \a lhs is earlier than \a rhs, the result will be negative.
+
+ Returns 0 if either datetime is invalid.
+
+ \sa msecsTo()
+*/
+
+/*!
+ \fn QDateTime QDateTime::operator+(const QDateTime &dateTime, std::chrono::milliseconds duration)
+ \fn QDateTime QDateTime::operator+(std::chrono::milliseconds duration, const QDateTime &dateTime)
+
+ \since 6.4
+
+ Returns a QDateTime object containing a datetime \a duration milliseconds
+ later than \a dateTime (or earlier if \a duration is negative).
+
+ If \a dateTime is invalid, an invalid datetime will be returned.
+
+ \sa addMSecs()
+*/
+
+/*!
+ \fn QDateTime &QDateTime::operator+=(std::chrono::milliseconds duration)
+ \since 6.4
+
+ Modifies this datetime object by adding the given \a duration.
+ The updated object will be later if \a duration is positive,
+ or earlier if it is negative.
+
+ If this datetime is invalid, this function has no effect.
+
+ Returns a reference to this datetime object.
+
+ \sa addMSecs()
+*/
+
+/*!
+ \fn QDateTime QDateTime::operator-(const QDateTime &dateTime, std::chrono::milliseconds duration)
+
+ \since 6.4
+
+ Returns a QDateTime object containing a datetime \a duration milliseconds
+ earlier than \a dateTime (or later if \a duration is negative).
+
+ If \a dateTime is invalid, an invalid datetime will be returned.
+
+ \sa addMSecs()
+*/
+
+/*!
+ \fn QDateTime &QDateTime::operator-=(std::chrono::milliseconds duration)
+ \since 6.4
+
+ Modifies this datetime object by subtracting the given \a duration.
+ The updated object will be earlier if \a duration is positive,
+ or later if it is negative.
- If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC. To set to a
- spec of Qt::OffsetFromUTC use toOffsetFromUtc().
+ If this datetime is invalid, this function has no effect.
- If \a spec is Qt::TimeZone then it is set to Qt::LocalTime,
- i.e. the local Time Zone.
+ Returns a reference to this datetime object.
+
+ \sa addMSecs
+*/
+
+#if QT_DEPRECATED_SINCE(6, 9)
+/*!
+ \deprecated [6.9] Use \l toTimeZone() instead.
+
+ Returns a copy of this datetime converted to the given time \a spec.
+
+ The result represents the same moment in time as, and is equal to, this datetime.
+
+ If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC. To set to a fixed
+ offset from UTC, use toTimeZone() or toOffsetFromUtc().
+
+ If \a spec is Qt::TimeZone then it is set to Qt::LocalTime, i.e. the local
+ Time Zone. To set a specified time-zone, use toTimeZone().
Example:
\snippet code/src_corelib_time_qdatetime.cpp 16
- \sa timeSpec(), toTimeZone(), toOffsetFromUtc()
+ \sa setTimeSpec(), timeSpec(), toTimeZone()
*/
QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
{
- if (getSpec(d) == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
- return *this;
-
- if (!isValid()) {
- QDateTime ret = *this;
- ret.setTimeSpec(spec);
- return ret;
- }
-
- return fromMSecsSinceEpoch(toMSecsSinceEpoch(), spec, 0);
+ return toTimeZone(asTimeZone(spec, 0, "toTimeSpec"));
}
+#endif // 6.9 deprecation
/*!
\since 5.2
- \fn QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
-
Returns a copy of this datetime converted to a spec of Qt::OffsetFromUTC
- with the given \a offsetSeconds.
+ with the given \a offsetSeconds. Equivalent to
+ \c{toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds))}.
- If the \a offsetSeconds equals 0 then a UTC datetime will be returned
+ If the \a offsetSeconds equals 0 then a UTC datetime will be returned.
- \sa setOffsetFromUtc(), offsetFromUtc(), toTimeSpec()
+ The result represents the same moment in time as, and is equal to, this datetime.
+
+ \sa setOffsetFromUtc(), offsetFromUtc(), toTimeZone()
*/
QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
{
- if (getSpec(d) == Qt::OffsetFromUTC
- && d->m_offsetFromUtc == offsetSeconds)
- return *this;
+ return toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds));
+}
- if (!isValid()) {
- QDateTime ret = *this;
- ret.setOffsetFromUtc(offsetSeconds);
- return ret;
- }
+/*!
+ Returns a copy of this datetime converted to local time.
+
+ The result represents the same moment in time as, and is equal to, this datetime.
+
+ Example:
+
+ \snippet code/src_corelib_time_qdatetime.cpp 17
+
+ \sa toTimeZone(), toUTC(), toOffsetFromUtc()
+*/
+QDateTime QDateTime::toLocalTime() const
+{
+ return toTimeZone(QTimeZone::LocalTime);
+}
+
+/*!
+ Returns a copy of this datetime converted to UTC.
+
+ The result represents the same moment in time as, and is equal to, this datetime.
+
+ Example:
+
+ \snippet code/src_corelib_time_qdatetime.cpp 18
- return fromMSecsSinceEpoch(toMSecsSinceEpoch(), Qt::OffsetFromUTC, offsetSeconds);
+ \sa toTimeZone(), toLocalTime(), toOffsetFromUtc()
+*/
+QDateTime QDateTime::toUTC() const
+{
+ return toTimeZone(QTimeZone::UTC);
}
-#if QT_CONFIG(timezone)
/*!
\since 5.2
- Returns a copy of this datetime converted to the given \a timeZone
+ Returns a copy of this datetime converted to the given \a timeZone.
+
+ The result represents the same moment in time as, and is equal to, this datetime.
+
+ The result describes the moment in time in terms of \a timeZone's time
+ representation. For example:
+
+ \snippet code/src_corelib_time_qdatetime.cpp 23
+
+ If \a timeZone is invalid then the datetime will be invalid. Otherwise the
+ returned datetime's timeSpec() will match \c{timeZone.timeSpec()}.
- \sa timeZone(), toTimeSpec()
+ \sa timeRepresentation(), toLocalTime(), toUTC(), toOffsetFromUtc()
*/
QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
{
- if (getSpec(d) == Qt::TimeZone && d->m_timeZone == timeZone)
+ if (timeRepresentation() == timeZone)
return *this;
if (!isValid()) {
@@ -4336,26 +5175,23 @@ QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
}
-#endif // timezone
/*!
+ \internal
Returns \c true if this datetime is equal to the \a other datetime;
otherwise returns \c false.
- Since 5.14, all invalid datetimes are equal to one another and differ from
- all other datetimes.
-
- \sa operator!=()
+ \sa precedes(), operator==()
*/
-bool QDateTime::operator==(const QDateTime &other) const
+bool QDateTime::equals(const QDateTime &other) const
{
if (!isValid())
return !other.isValid();
if (!other.isValid())
return false;
- if (getSpec(d) == Qt::LocalTime && getStatus(d) == getStatus(other.d))
+ if (usesSameOffset(d, other.d))
return getMSecs(d) == getMSecs(other.d);
// Convert to UTC and compare
@@ -4363,82 +5199,137 @@ bool QDateTime::operator==(const QDateTime &other) const
}
/*!
- \fn bool QDateTime::operator!=(const QDateTime &other) const
+ \fn bool QDateTime::operator==(const QDateTime &lhs, const QDateTime &rhs)
- Returns \c true if this datetime is different from the \a other
- datetime; otherwise returns \c false.
+ Returns \c true if \a lhs represents the same moment in time as \a rhs;
+ otherwise returns \c false.
- Two datetimes are different if either the date, the time, or the time zone
- components are different. Since 5.14, any invalid datetime is less than all
- valid datetimes.
+//! [datetime-order-details]
+ Two datetimes using different time representations can have different
+ offsets from UTC. In this case, they may compare equivalent even if their \l
+ date() and \l time() differ, if that difference matches the difference in
+ UTC offset. If their \c date() and \c time() coincide, the one with higher
+ offset from UTC is less (earlier) than the one with lower offset. As a
+ result, datetimes are only weakly ordered.
- \sa operator==()
+ Since 5.14, all invalid datetimes are equivalent and less than all valid
+ datetimes.
+//! [datetime-order-details]
+
+ \sa operator!=(), operator<(), operator<=(), operator>(), operator>=()
*/
/*!
- Returns \c true if this datetime is earlier than the \a other
- datetime; otherwise returns \c false.
+ \fn bool QDateTime::operator!=(const QDateTime &lhs, const QDateTime &rhs)
+
+ Returns \c true if \a lhs is different from \a rhs; otherwise returns \c
+ false.
+
+ \include qdatetime.cpp datetime-order-details
+
+ \sa operator==()
*/
-bool QDateTime::operator<(const QDateTime &other) const
+Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
{
- if (!isValid())
- return other.isValid();
- if (!other.isValid())
- return false;
+ if (!lhs.isValid())
+ return rhs.isValid() ? Qt::weak_ordering::less : Qt::weak_ordering::equivalent;
+
+ if (!rhs.isValid())
+ return Qt::weak_ordering::greater; // we know that lhs is valid here
- if (getSpec(d) == Qt::LocalTime && getStatus(d) == getStatus(other.d))
- return getMSecs(d) < getMSecs(other.d);
+ if (usesSameOffset(lhs.d, rhs.d))
+ return Qt::compareThreeWay(getMSecs(lhs.d), getMSecs(rhs.d));
// Convert to UTC and compare
- return toMSecsSinceEpoch() < other.toMSecsSinceEpoch();
+ return Qt::compareThreeWay(lhs.toMSecsSinceEpoch(), rhs.toMSecsSinceEpoch());
}
/*!
- \fn bool QDateTime::operator<=(const QDateTime &other) const
+ \fn bool QDateTime::operator<(const QDateTime &lhs, const QDateTime &rhs)
+
+ Returns \c true if \a lhs is earlier than \a rhs;
+ otherwise returns \c false.
+
+ \include qdatetime.cpp datetime-order-details
+
+ \sa operator==()
+*/
+
+/*!
+ \fn bool QDateTime::operator<=(const QDateTime &lhs, const QDateTime &rhs)
+
+ Returns \c true if \a lhs is earlier than or equal to \a rhs; otherwise
+ returns \c false.
- Returns \c true if this datetime is earlier than or equal to the
- \a other datetime; otherwise returns \c false.
+ \include qdatetime.cpp datetime-order-details
+
+ \sa operator==()
*/
/*!
- \fn bool QDateTime::operator>(const QDateTime &other) const
+ \fn bool QDateTime::operator>(const QDateTime &lhs, const QDateTime &rhs)
- Returns \c true if this datetime is later than the \a other datetime;
- otherwise returns \c false.
+ Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
+
+ \include qdatetime.cpp datetime-order-details
+
+ \sa operator==()
*/
/*!
- \fn bool QDateTime::operator>=(const QDateTime &other) const
+ \fn bool QDateTime::operator>=(const QDateTime &lhs, const QDateTime &rhs)
+
+ Returns \c true if \a lhs is later than or equal to \a rhs;
+ otherwise returns \c false.
- Returns \c true if this datetime is later than or equal to the
- \a other datetime; otherwise returns \c false.
+ \include qdatetime.cpp datetime-order-details
+
+ \sa operator==()
*/
/*!
- \fn QDateTime QDateTime::currentDateTime()
- Returns the current datetime, as reported by the system clock, in
- the local time zone.
+ \since 6.5
+ \fn QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
+
+ Returns the system clock's current datetime, using the time representation
+ described by \a zone. If \a zone is omitted, local time is used.
\sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
*/
/*!
+ \overload
+ \since 0.90
+*/
+QDateTime QDateTime::currentDateTime()
+{
+ return currentDateTime(QTimeZone::LocalTime);
+}
+
+/*!
\fn QDateTime QDateTime::currentDateTimeUtc()
\since 4.7
- Returns the current datetime, as reported by the system clock, in
- UTC.
+ Returns the system clock's current datetime, expressed in terms of UTC.
+
+ Equivalent to \c{currentDateTime(QTimeZone::UTC)}.
\sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
*/
+QDateTime QDateTime::currentDateTimeUtc()
+{
+ return currentDateTime(QTimeZone::UTC);
+}
+
/*!
\fn qint64 QDateTime::currentMSecsSinceEpoch()
\since 4.7
- Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
- Coordinated Time. This number is like the POSIX time_t variable, but
- expressed in milliseconds instead.
+ Returns the current number of milliseconds since the start, in UTC, of the year 1970.
+
+ This number is like the POSIX time_t variable, but expressed in milliseconds
+ instead of seconds.
\sa currentDateTime(), currentDateTimeUtc(), toTimeSpec()
*/
@@ -4447,22 +5338,101 @@ bool QDateTime::operator<(const QDateTime &other) const
\fn qint64 QDateTime::currentSecsSinceEpoch()
\since 5.8
- Returns the number of seconds since 1970-01-01T00:00:00 Universal
- Coordinated Time.
+ Returns the number of seconds since the start, in UTC, of the year 1970.
+
+ This number is like the POSIX time_t variable.
\sa currentMSecsSinceEpoch()
*/
+/*!
+ \fn template <typename Clock, typename Duration> QDateTime QDateTime::fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
+ \since 6.4
+
+ Constructs a datetime representing the same point in time as \a time,
+ using Qt::UTC as its specification.
+
+ The clock of \a time must be compatible with \c{std::chrono::system_clock},
+ and the duration type must be convertible to \c{std::chrono::milliseconds}.
+
+ \note This function requires C++20.
+
+ \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
+*/
+
+/*!
+ \fn QDateTime QDateTime::fromStdTimePoint(const std::chrono::local_time<std::chrono::milliseconds> &time)
+ \since 6.4
+
+ Constructs a datetime whose date and time are the number of milliseconds
+ represented by \a time, counted since 1970-01-01T00:00:00.000 in local
+ time (Qt::LocalTime).
+
+ \note This function requires C++20.
+
+ \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
+*/
+
+/*!
+ \fn QDateTime QDateTime::fromStdLocalTime(const std::chrono::local_time<std::chrono::milliseconds> &time)
+ \since 6.4
+
+ Constructs a datetime whose date and time are the number of milliseconds
+ represented by \a time, counted since 1970-01-01T00:00:00.000 in local
+ time (Qt::LocalTime).
+
+ \note This function requires C++20.
+
+ \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
+*/
+
+/*!
+ \fn QDateTime QDateTime::fromStdZonedTime(const std::chrono::zoned_time<std::chrono::milliseconds, const std::chrono::time_zone *> &time);
+ \since 6.4
+
+ Constructs a datetime representing the same point in time as \a time.
+ The result will be expressed in \a{time}'s time zone.
+
+ \note This function requires C++20.
+
+ \sa QTimeZone
+
+ \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
+*/
+
+/*!
+ \fn std::chrono::sys_time<std::chrono::milliseconds> QDateTime::toStdSysMilliseconds() const
+ \since 6.4
+
+ Converts this datetime object to the equivalent time point expressed in
+ milliseconds, using \c{std::chrono::system_clock} as a clock.
+
+ \note This function requires C++20.
+
+ \sa fromStdTimePoint(), toMSecsSinceEpoch()
+*/
+
+/*!
+ \fn std::chrono::sys_seconds QDateTime::toStdSysSeconds() const
+ \since 6.4
+
+ Converts this datetime object to the equivalent time point expressed in
+ seconds, using \c{std::chrono::system_clock} as a clock.
+
+ \note This function requires C++20.
+
+ \sa fromStdTimePoint(), toSecsSinceEpoch()
+*/
+
#if defined(Q_OS_WIN)
static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
{
- return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
+ return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + MSECS_PER_SEC * sec + msec;
}
QDate QDate::currentDate()
{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
+ SYSTEMTIME st = {};
GetLocalTime(&st);
return QDate(st.wYear, st.wMonth, st.wDay);
}
@@ -4470,58 +5440,50 @@ QDate QDate::currentDate()
QTime QTime::currentTime()
{
QTime ct;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
+ SYSTEMTIME st = {};
GetLocalTime(&st);
ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
return ct;
}
-QDateTime QDateTime::currentDateTime()
+QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
{
- QTime t;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetLocalTime(&st);
+ // We can get local time or "system" time (which is UTC); otherwise, we must
+ // convert, which is most efficiently done from UTC.
+ const Qt::TimeSpec spec = zone.timeSpec();
+ SYSTEMTIME st = {};
+ // GetSystemTime()'s page links to its partner page for GetLocalTime().
+ // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtime
+ (spec == Qt::LocalTime ? GetLocalTime : GetSystemTime)(&st);
QDate d(st.wYear, st.wMonth, st.wDay);
- t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
- return QDateTime(d, t);
-}
-
-QDateTime QDateTime::currentDateTimeUtc()
-{
- QTime t;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetSystemTime(&st);
- QDate d(st.wYear, st.wMonth, st.wDay);
- t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
- return QDateTime(d, t, Qt::UTC);
+ QTime t(msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds));
+ if (spec == Qt::LocalTime)
+ return QDateTime(d, t);
+ QDateTime utc(d, t, QTimeZone::UTC);
+ return spec == Qt::UTC ? utc : utc.toTimeZone(zone);
}
qint64 QDateTime::currentMSecsSinceEpoch() noexcept
{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
+ SYSTEMTIME st = {};
GetSystemTime(&st);
const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
- daysAfterEpoch * Q_INT64_C(86400000);
+ daysAfterEpoch * MSECS_PER_DAY;
}
qint64 QDateTime::currentSecsSinceEpoch() noexcept
{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
+ SYSTEMTIME st = {};
GetSystemTime(&st);
const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
- daysAfterEpoch * Q_INT64_C(86400);
+ daysAfterEpoch * SECS_PER_DAY;
}
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) // Assume POSIX-compliant
QDate QDate::currentDate()
{
return QDateTime::currentDateTime().date();
@@ -4532,131 +5494,157 @@ QTime QTime::currentTime()
return QDateTime::currentDateTime().time();
}
-QDateTime QDateTime::currentDateTime()
-{
- return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::LocalTime);
-}
-
-QDateTime QDateTime::currentDateTimeUtc()
+QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
{
- return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::UTC);
+ return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), zone);
}
qint64 QDateTime::currentMSecsSinceEpoch() noexcept
{
- // posix compliant system
- // we have milliseconds
- struct timeval tv;
- gettimeofday(&tv, nullptr);
- return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
+ struct timespec when;
+ if (clock_gettime(CLOCK_REALTIME, &when) == 0) // should always succeed
+ return when.tv_sec * MSECS_PER_SEC + (when.tv_nsec + 500'000) / 1'000'000;
+ Q_UNREACHABLE_RETURN(0);
}
qint64 QDateTime::currentSecsSinceEpoch() noexcept
{
- struct timeval tv;
- gettimeofday(&tv, nullptr);
- return qint64(tv.tv_sec);
+ struct timespec when;
+ if (clock_gettime(CLOCK_REALTIME, &when) == 0) // should always succeed
+ return when.tv_sec;
+ Q_UNREACHABLE_RETURN(0);
}
#else
#error "What system is this?"
#endif
+#if QT_DEPRECATED_SINCE(6, 9)
/*!
- Returns a datetime whose date and time are the number of milliseconds \a msecs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and converted to the given \a spec.
+ \since 5.2
+ \overload
+ \deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
- Note that there are possible values for \a msecs that lie outside the valid
- range of QDateTime, both negative and positive. The behavior of this
- function is undefined for those values.
+ Returns a datetime representing a moment the given number \a msecs of
+ milliseconds after the start, in UTC, of the year 1970, described as
+ specified by \a spec and \a offsetSeconds.
- If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
- ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
- then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
+ Note that there are possible values for \a msecs that lie outside the valid
+ range of QDateTime, both negative and positive. The behavior of this
+ function is undefined for those values.
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone.
+ If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
+ ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
+ then Qt::UTC will be used as the \a spec, since UTC has zero offset.
- \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
+ If \a spec is Qt::TimeZone then Qt::LocalTime will be used in its place,
+ equivalent to using the current system time zone (but differently
+ represented).
+
+ \sa fromSecsSinceEpoch(), toMSecsSinceEpoch(), setMSecsSinceEpoch()
*/
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
{
- QDateTime dt;
- QT_PREPEND_NAMESPACE(setTimeSpec(dt.d, spec, offsetSeconds));
- dt.setMSecsSinceEpoch(msecs);
- return dt;
+ return fromMSecsSinceEpoch(msecs,
+ asTimeZone(spec, offsetSeconds, "QDateTime::fromMSecsSinceEpoch"));
}
/*!
- \since 5.8
+ \since 5.8
+ \overload
+ \deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
- Returns a datetime whose date and time are the number of seconds \a secs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and converted to the given \a spec.
+ Returns a datetime representing a moment the given number \a secs of seconds
+ after the start, in UTC, of the year 1970, described as specified by \a spec
+ and \a offsetSeconds.
- Note that there are possible values for \a secs that lie outside the valid
- range of QDateTime, both negative and positive. The behavior of this
- function is undefined for those values.
+ Note that there are possible values for \a secs that lie outside the valid
+ range of QDateTime, both negative and positive. The behavior of this
+ function is undefined for those values.
- If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
- ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
- then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
+ If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
+ ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
+ then Qt::UTC will be used as the \a spec, since UTC has zero offset.
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone.
+ If \a spec is Qt::TimeZone then Qt::LocalTime will be used in its place,
+ equivalent to using the current system time zone (but differently
+ represented).
- \sa toSecsSinceEpoch(), setSecsSinceEpoch()
+ \sa fromMSecsSinceEpoch(), toSecsSinceEpoch(), setSecsSinceEpoch()
*/
QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds)
{
- constexpr qint64 maxSeconds = std::numeric_limits<qint64>::max() / 1000;
- constexpr qint64 minSeconds = std::numeric_limits<qint64>::min() / 1000;
- if (secs > maxSeconds || secs < minSeconds)
- return QDateTime(); // Would {und,ov}erflow
- return fromMSecsSinceEpoch(secs * 1000, spec, offsetSeconds);
+ return fromSecsSinceEpoch(secs,
+ asTimeZone(spec, offsetSeconds, "QDateTime::fromSecsSinceEpoch"));
}
+#endif // 6.9 deprecations
-#if QT_CONFIG(timezone)
/*!
\since 5.2
- Returns a datetime whose date and time are the number of milliseconds \a msecs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and with the given \a timeZone.
+ Returns a datetime representing a moment the given number \a msecs of
+ milliseconds after the start, in UTC, of the year 1970, described as
+ specified by \a timeZone. The default time representation is local time.
+
+ Note that there are possible values for \a msecs that lie outside the valid
+ range of QDateTime, both negative and positive. The behavior of this
+ function is undefined for those values.
- \sa fromSecsSinceEpoch()
+ \sa fromSecsSinceEpoch(), toMSecsSinceEpoch(), setMSecsSinceEpoch()
*/
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
{
QDateTime dt;
- dt.setTimeZone(timeZone);
+ reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
if (timeZone.isValid())
dt.setMSecsSinceEpoch(msecs);
return dt;
}
/*!
+ \since 6.5
+ \overload
+*/
+QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
+{
+ return fromMSecsSinceEpoch(msecs, QTimeZone::LocalTime);
+}
+
+/*!
\since 5.8
- Returns a datetime whose date and time are the number of seconds \a secs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and with the given \a timeZone.
+ Returns a datetime representing a moment the given number \a secs of seconds
+ after the start, in UTC, of the year 1970, described as specified by \a
+ timeZone. The default time representation is local time.
- \sa fromMSecsSinceEpoch()
+ Note that there are possible values for \a secs that lie outside the valid
+ range of QDateTime, both negative and positive. The behavior of this
+ function is undefined for those values.
+
+ \sa fromMSecsSinceEpoch(), toSecsSinceEpoch(), setSecsSinceEpoch()
*/
QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
{
- constexpr qint64 maxSeconds = std::numeric_limits<qint64>::max() / 1000;
- constexpr qint64 minSeconds = std::numeric_limits<qint64>::min() / 1000;
- if (secs > maxSeconds || secs < minSeconds)
- return QDateTime(); // Would {und,ov}erflow
- return fromMSecsSinceEpoch(secs * 1000, timeZone);
+ QDateTime dt;
+ reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
+ if (timeZone.isValid())
+ dt.setSecsSinceEpoch(secs);
+ return dt;
+}
+
+/*!
+ \since 6.5
+ \overload
+*/
+QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
+{
+ return fromSecsSinceEpoch(secs, QTimeZone::LocalTime);
}
-#endif
#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
+ \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
+
Returns the QDateTime represented by the \a string, using the
\a format given, or an invalid datetime if this is not possible.
@@ -4665,7 +5653,12 @@ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
\sa toString(), QLocale::toDateTime()
*/
-QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
+
+/*!
+ \overload
+ \since 6.0
+*/
+QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
{
if (string.isEmpty())
return QDateTime();
@@ -4677,8 +5670,8 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
if (!rfc.date.isValid() || !rfc.time.isValid())
return QDateTime();
- QDateTime dateTime(rfc.date, rfc.time, Qt::UTC);
- dateTime.setOffsetFromUtc(rfc.utcOffset);
+ QDateTime dateTime(rfc.date, rfc.time, QTimeZone::UTC);
+ dateTime.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(rfc.utcOffset));
return dateTime;
}
case Qt::ISODate:
@@ -4687,30 +5680,29 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
if (size < 10)
return QDateTime();
- QDate date = QDate::fromString(string.left(10), Qt::ISODate);
+ QDate date = QDate::fromString(string.first(10), Qt::ISODate);
if (!date.isValid())
return QDateTime();
if (size == 10)
return date.startOfDay();
- Qt::TimeSpec spec = Qt::LocalTime;
- QStringView isoString = QStringView(string).mid(10); // trim "yyyy-MM-dd"
+ QTimeZone zone = QTimeZone::LocalTime;
+ QStringView isoString = string.sliced(10); // trim "yyyy-MM-dd"
// Must be left with T (or space) and at least one digit for the hour:
if (isoString.size() < 2
- || !(isoString.startsWith(QLatin1Char('T'), Qt::CaseInsensitive)
+ || !(isoString.startsWith(u'T', Qt::CaseInsensitive)
// RFC 3339 (section 5.6) allows a space here. (It actually
// allows any separator one considers more readable, merely
// giving space as an example - but let's not go wild !)
- || isoString.startsWith(QLatin1Char(' ')))) {
+ || isoString.startsWith(u' '))) {
return QDateTime();
}
- isoString = isoString.mid(1); // trim 'T' (or space)
+ isoString = isoString.sliced(1); // trim 'T' (or space)
- int offset = 0;
- // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
- if (isoString.endsWith(QLatin1Char('Z'), Qt::CaseInsensitive)) {
- spec = Qt::UTC;
+ // Check end of string for Time Zone definition, either Z for UTC or ±HH:mm for Offset
+ if (isoString.endsWith(u'Z', Qt::CaseInsensitive)) {
+ zone = QTimeZone::UTC;
isoString.chop(1); // trim 'Z'
} else {
// the loop below is faster but functionally equal to:
@@ -4718,22 +5710,18 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
int signIndex = isoString.size() - 1;
Q_ASSERT(signIndex >= 0);
bool found = false;
- {
- const QChar plus = QLatin1Char('+');
- const QChar minus = QLatin1Char('-');
- do {
- QChar character(isoString.at(signIndex));
- found = character == plus || character == minus;
- } while (!found && --signIndex >= 0);
- }
+ do {
+ QChar character(isoString[signIndex]);
+ found = character == u'+' || character == u'-';
+ } while (!found && --signIndex >= 0);
if (found) {
bool ok;
- offset = fromOffsetString(isoString.mid(signIndex), &ok);
+ int offset = fromOffsetString(isoString.sliced(signIndex), &ok);
if (!ok)
return QDateTime();
- isoString = isoString.left(signIndex);
- spec = Qt::OffsetFromUTC;
+ isoString = isoString.first(signIndex);
+ zone = QTimeZone::fromSecondsAheadOfUtc(offset);
}
}
@@ -4743,116 +5731,65 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
if (!time.isValid())
return QDateTime();
- if (isMidnight24)
- date = date.addDays(1);
- return QDateTime(date, time, spec, offset);
+ if (isMidnight24) // time is 0:0, but we want the start of next day:
+ return date.addDays(1).startOfDay(zone);
+ return QDateTime(date, time, zone);
}
case Qt::TextDate: {
- QList<QStringView> parts = QStringView { string }.split(QLatin1Char(' '), Qt::SkipEmptyParts);
+ QVarLengthArray<QStringView, 6> parts;
- if ((parts.count() < 5) || (parts.count() > 6))
- return QDateTime();
+ auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
+ auto it = tokens.begin();
+ for (int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
+ parts.emplace_back(*it);
- // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
+ // Documented as "ddd MMM d HH:mm:ss yyyy" with optional offset-suffix;
+ // and allow time either before or after year.
+ if (parts.size() < 5 || it != tokens.end())
+ return QDateTime();
// Year and time can be in either order.
// Guess which by looking for ':' in the time
int yearPart = 3;
int timePart = 3;
- if (parts.at(3).contains(QLatin1Char(':')))
+ if (parts.at(3).contains(u':'))
yearPart = 4;
- else if (parts.at(4).contains(QLatin1Char(':')))
+ else if (parts.at(4).contains(u':'))
timePart = 4;
else
return QDateTime();
- int month = 0;
- int day = 0;
bool ok = false;
-
- int year = parts.at(yearPart).toInt(&ok);
- if (!ok || year == 0)
- return QDateTime();
-
- // Next try month then day
- month = fromShortMonthName(parts.at(1));
- if (month)
- day = parts.at(2).toInt(&ok);
-
- // If failed, try day then month
- if (!ok || !month || !day) {
- month = fromShortMonthName(parts.at(2));
- if (month) {
- QStringView dayStr = parts.at(1);
- if (dayStr.endsWith(QLatin1Char('.'))) {
- dayStr = dayStr.left(dayStr.size() - 1);
- day = dayStr.toInt(&ok);
- }
- }
- }
-
- // If both failed, give up
- if (!ok || !month || !day)
+ int day = parts.at(2).toInt(&ok);
+ int year = ok ? parts.at(yearPart).toInt(&ok) : 0;
+ int month = fromShortMonthName(parts.at(1));
+ if (!ok || year == 0 || day == 0 || month < 1)
return QDateTime();
- QDate date(year, month, day);
+ const QDate date(year, month, day);
if (!date.isValid())
return QDateTime();
- // ### fixme, use QStringView::tokenize() when available
- QList<QStringView> timeParts = parts.at(timePart).split(QLatin1Char(':'));
- if (timeParts.count() < 2 || timeParts.count() > 3)
- return QDateTime();
-
- int hour = timeParts.at(0).toInt(&ok);
- if (!ok)
- return QDateTime();
-
- int minute = timeParts.at(1).toInt(&ok);
- if (!ok)
- return QDateTime();
-
- int second = 0;
- int millisecond = 0;
- if (timeParts.count() > 2) {
- // ### fixme, use QStringView::tokenize() when available
- const QList<QStringView> secondParts = timeParts.at(2).split(QLatin1Char('.'));
- if (secondParts.size() > 2) {
- return QDateTime();
- }
-
- second = secondParts.first().toInt(&ok);
- if (!ok) {
- return QDateTime();
- }
-
- if (secondParts.size() > 1) {
- millisecond = secondParts.last().toInt(&ok);
- if (!ok) {
- return QDateTime();
- }
- }
- }
-
- QTime time(hour, minute, second, millisecond);
+ const QTime time = fromIsoTimeString(parts.at(timePart), format, nullptr);
if (!time.isValid())
return QDateTime();
- if (parts.count() == 5)
- return QDateTime(date, time, Qt::LocalTime);
+ if (parts.size() == 5)
+ return QDateTime(date, time);
QStringView tz = parts.at(5);
- if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
- return QDateTime();
- tz = tz.mid(3);
- if (!tz.isEmpty()) {
+ if (tz.startsWith("UTC"_L1)
+ // GMT has long been deprecated as an alias for UTC.
+ || tz.startsWith("GMT"_L1, Qt::CaseInsensitive)) {
+ tz = tz.sliced(3);
+ if (tz.isEmpty())
+ return QDateTime(date, time, QTimeZone::UTC);
+
int offset = fromOffsetString(tz, &ok);
- if (!ok)
- return QDateTime();
- return QDateTime(date, time, Qt::OffsetFromUTC, offset);
- } else {
- return QDateTime(date, time, Qt::UTC);
+ return ok ? QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offset))
+ : QDateTime();
}
+ return QDateTime();
}
}
@@ -4860,29 +5797,55 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
}
/*!
+ \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
+
Returns the QDateTime represented by the \a string, using the \a
format given, or an invalid datetime if the string cannot be parsed.
Uses the calendar \a cal if supplied, else Gregorian.
+ \include qlocale.cpp base-year-for-two-digit
+
In addition to the expressions, recognized in the format string to represent
parts of the date and time, by QDate::fromString() and QTime::fromString(),
this method supports:
\table
\header \li Expression \li Output
- \row \li t \li the timezone (for example "CEST")
+ \row \li t
+ \li the timezone (offset, name, "Z" or offset with "UTC" prefix)
+ \row \li tt
+ \li the timezone in offset format with no colon between hours and
+ minutes (for example "+0200")
+ \row \li ttt
+ \li the timezone in offset format with a colon between hours and
+ minutes (for example "+02:00")
+ \row \li tttt
+ \li the timezone name (for example "Europe/Berlin"). The name
+ recognized are those known to \l QTimeZone, which may depend on the
+ operating system in use.
\endtable
+ If no 't' format specifier is present, the system's local time-zone is used.
+ For the defaults of all other fields, see QDate::fromString() and QTime::fromString().
+
+ For example:
+
+ \snippet code/src_corelib_time_qdatetime.cpp 14
+
All other input characters will be treated as text. Any non-empty sequence
of characters enclosed in single quotes will also be treated (stripped of
the quotes) as text and not be interpreted as expressions.
\snippet code/src_corelib_time_qdatetime.cpp 12
- If the format is not satisfied, an invalid QDateTime is returned.
+ If the format is not satisfied, an invalid QDateTime is returned. If the
+ format is satisfied but \a string represents an invalid datetime (e.g. in a
+ gap skipped by a time-zone transition), an valid QDateTime is returned, that
+ represents a near-by datetime that is valid.
+
The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
- greedy. This means that they will use two digits even if this will
+ greedy. This means that they will use two digits (or three, for z) even if this will
put them outside the range and/or leave too few digits for other
sections.
@@ -4903,74 +5866,99 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
\snippet code/src_corelib_time_qdatetime.cpp 21
- For any field that is not represented in the format, the following
- defaults are used:
-
- \table
- \header \li Field \li Default value
- \row \li Year \li 1900
- \row \li Month \li 1 (January)
- \row \li Day \li 1
- \row \li Hour \li 0
- \row \li Minute \li 0
- \row \li Second \li 0
- \endtable
-
- For example:
-
- \snippet code/src_corelib_time_qdatetime.cpp 14
+ \note Day and month names as well as AM/PM indicators must be given in
+ English (C locale). If localized month and day names or localized forms of
+ AM/PM are to be recognized, use QLocale::system().toDateTime().
- \note If localized month and day names are used, please switch to using
- QLocale::system().toDateTime() as QDateTime methods shall change to only
- recognize English (C locale) names at Qt 6.
+ \note If a format character is repeated more times than the longest
+ expression in the table above using it, this part of the format will be read
+ as several expressions with no separator between them; the longest above,
+ possibly repeated as many times as there are copies of it, ending with a
+ residue that may be a shorter expression. Thus \c{'tttttt'} would match
+ \c{"Europe/BerlinEurope/Berlin"} and set the zone to Berlin time; if the
+ datetime string contained "Europe/BerlinZ" it would "match" but produce an
+ inconsistent result, leading to an invalid datetime.
\sa toString(), QDate::fromString(), QTime::fromString(),
QLocale::toDateTime()
*/
-QDateTime QDateTime::fromString(const QString &string, const QString &format, QCalendar cal)
+/*!
+ \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, QCalendar cal)
+ \overload
+ \since 6.0
+*/
+
+/*!
+ \overload
+ \since 6.0
+*/
+QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear,
+ QCalendar cal)
{
#if QT_CONFIG(datetimeparser)
QDateTime datetime;
QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
dt.setDefaultLocale(QLocale::c());
- if (dt.parseFormat(format) && dt.fromString(string, &datetime))
+ if (dt.parseFormat(format) && (dt.fromString(string, &datetime, baseYear)
+ || !datetime.isValid())) {
return datetime;
+ }
#else
Q_UNUSED(string);
Q_UNUSED(format);
+ Q_UNUSED(baseYear);
Q_UNUSED(cal);
#endif
return QDateTime();
}
-#endif // datestring
/*!
- \fn QDateTime QDateTime::toLocalTime() const
+ \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, QCalendar cal)
+ \overload
+ \since 5.14
+*/
- Returns a datetime containing the date and time information in
- this datetime, but specified using the Qt::LocalTime definition.
+/*!
+ \fn QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal)
+ \overload
+ \since 6.0
+*/
- Example:
+/*!
+ \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
+ \overload
+ \since 6.7
+*/
- \snippet code/src_corelib_time_qdatetime.cpp 17
+/*!
+ \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear)
+ \overload
+ \since 6.7
- \sa toTimeSpec()
+ Uses a default-constructed QCalendar.
*/
/*!
- \fn QDateTime QDateTime::toUTC() const
-
- Returns a datetime containing the date and time information in
- this datetime, but specified using the Qt::UTC definition.
+ \overload
+ \since 6.7
- Example:
+ Uses a default-constructed QCalendar.
+*/
+QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear)
+{
+ return fromString(string, format, baseYear, QCalendar());
+}
- \snippet code/src_corelib_time_qdatetime.cpp 18
+/*!
+ \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear)
+ \overload
+ \since 6.7
- \sa toTimeSpec()
+ Uses a default-constructed QCalendar.
*/
+#endif // datestring
/*****************************************************************************
Date/time stream functions
@@ -4990,7 +5978,7 @@ QDataStream &operator<<(QDataStream &out, QDate date)
if (out.version() < QDataStream::Qt_5_0)
return out << quint32(date.jd);
else
- return out << qint64(date.jd);
+ return out << date.jd;
}
/*!
@@ -5009,9 +5997,7 @@ QDataStream &operator>>(QDataStream &in, QDate &date)
// Older versions consider 0 an invalid jd.
date.jd = (jd != 0 ? jd : QDate::nullJd());
} else {
- qint64 jd;
- in >> jd;
- date.jd = jd;
+ in >> date.jd;
}
return in;
@@ -5065,11 +6051,12 @@ QDataStream &operator>>(QDataStream &in, QTime &time)
*/
QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
{
- QPair<QDate, QTime> dateAndTime;
+ std::pair<QDate, QTime> dateAndTime;
+ // TODO: new version, route spec and details via QTimeZone
if (out.version() >= QDataStream::Qt_5_2) {
- // In 5.2 we switched to using Qt::TimeSpec and added offset support
+ // In 5.2 we switched to using Qt::TimeSpec and added offset and zone support
dateAndTime = getDateTime(dateTime.d);
out << dateAndTime << qint8(dateTime.timeSpec());
if (dateTime.timeSpec() == Qt::OffsetFromUTC)
@@ -5132,67 +6119,61 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
QDate dt;
QTime tm;
qint8 ts = 0;
- Qt::TimeSpec spec = Qt::LocalTime;
- qint32 offset = 0;
-#if QT_CONFIG(timezone)
- QTimeZone tz;
-#endif // timezone
+ QTimeZone zone(QTimeZone::LocalTime);
if (in.version() >= QDataStream::Qt_5_2) {
- // In 5.2 we switched to using Qt::TimeSpec and added offset support
+ // In 5.2 we switched to using Qt::TimeSpec and added offset and zone support
in >> dt >> tm >> ts;
- spec = static_cast<Qt::TimeSpec>(ts);
- if (spec == Qt::OffsetFromUTC) {
+ switch (static_cast<Qt::TimeSpec>(ts)) {
+ case Qt::UTC:
+ zone = QTimeZone::UTC;
+ break;
+ case Qt::OffsetFromUTC: {
+ qint32 offset = 0;
in >> offset;
- dateTime = QDateTime(dt, tm, spec, offset);
-#if QT_CONFIG(timezone)
- } else if (spec == Qt::TimeZone) {
- in >> tz;
- dateTime = QDateTime(dt, tm, tz);
-#endif // timezone
- } else {
- dateTime = QDateTime(dt, tm, spec);
+ zone = QTimeZone::fromSecondsAheadOfUtc(offset);
+ break;
}
+ case Qt::LocalTime:
+ break;
+ case Qt::TimeZone:
+ in >> zone;
+ break;
+ }
+ // Note: no way to resolve transition ambiguity, when relevant; use default.
+ dateTime = QDateTime(dt, tm, zone);
} else if (in.version() == QDataStream::Qt_5_0) {
// In Qt 5.0 we incorrectly serialised all datetimes as UTC
in >> dt >> tm >> ts;
- spec = static_cast<Qt::TimeSpec>(ts);
- dateTime = QDateTime(dt, tm, Qt::UTC);
- dateTime = dateTime.toTimeSpec(spec);
+ dateTime = QDateTime(dt, tm, QTimeZone::UTC);
+ if (static_cast<Qt::TimeSpec>(ts) == Qt::LocalTime)
+ dateTime = dateTime.toTimeZone(zone);
} else if (in.version() >= QDataStream::Qt_4_0) {
// From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
in >> dt >> tm >> ts;
- switch ((QDateTimePrivate::Spec)ts) {
+ switch (static_cast<QDateTimePrivate::Spec>(ts)) {
+ case QDateTimePrivate::OffsetFromUTC: // No offset was stored, so treat as UTC.
case QDateTimePrivate::UTC:
- spec = Qt::UTC;
- break;
- case QDateTimePrivate::OffsetFromUTC:
- spec = Qt::OffsetFromUTC;
- break;
- case QDateTimePrivate::TimeZone:
- spec = Qt::TimeZone;
-#if QT_CONFIG(timezone)
- // FIXME: need to use a different constructor !
-#endif
+ zone = QTimeZone::UTC;
break;
+ case QDateTimePrivate::TimeZone: // No zone was stored, so treat as LocalTime:
case QDateTimePrivate::LocalUnknown:
case QDateTimePrivate::LocalStandard:
case QDateTimePrivate::LocalDST:
- spec = Qt::LocalTime;
break;
}
- dateTime = QDateTime(dt, tm, spec, offset);
+ dateTime = QDateTime(dt, tm, zone);
} else { // version < QDataStream::Qt_4_0
// Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
in >> dt >> tm;
- dateTime = QDateTime(dt, tm, spec, offset);
+ dateTime = QDateTime(dt, tm);
}
@@ -5210,7 +6191,11 @@ QDebug operator<<(QDebug dbg, QDate date)
QDebugStateSaver saver(dbg);
dbg.nospace() << "QDate(";
if (date.isValid())
- dbg.nospace() << date.toString(Qt::ISODate);
+ // QTBUG-91070, ISODate only supports years in the range 0-9999
+ if (int y = date.year(); y > 0 && y <= 9999)
+ dbg.nospace() << date.toString(Qt::ISODate);
+ else
+ dbg.nospace() << date.toString(Qt::TextDate);
else
dbg.nospace() << "Invalid";
dbg.nospace() << ')';
diff --git a/src/corelib/time/qdatetime.h b/src/corelib/time/qdatetime.h
index 62642a5fd2..a9fefc4c22 100644
--- a/src/corelib/time/qdatetime.h
+++ b/src/corelib/time/qdatetime.h
@@ -1,52 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATETIME_H
#define QDATETIME_H
-#include <QtCore/qstring.h>
+#include <QtCore/qcalendar.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qlocale.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qshareddata.h>
-#include <QtCore/qcalendar.h>
+#include <QtCore/qstring.h>
#include <limits>
+#include <chrono>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
Q_FORWARD_DECLARE_CF_TYPE(CFDate);
@@ -55,21 +22,53 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSDate);
QT_BEGIN_NAMESPACE
-#if QT_CONFIG(timezone)
class QTimeZone;
-#endif
class QDateTime;
-class Q_CORE_EXPORT QDate // ### Qt 6: change to be used by value, not const &
+class Q_CORE_EXPORT QDate
{
- explicit Q_DECL_CONSTEXPR QDate(qint64 julianDay) : jd(julianDay) {}
+ explicit constexpr QDate(qint64 julianDay) : jd(julianDay) {}
public:
- Q_DECL_CONSTEXPR QDate() : jd(nullJd()) {}
+ constexpr QDate() : jd(nullJd()) {}
QDate(int y, int m, int d);
QDate(int y, int m, int d, QCalendar cal);
+#if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT constexpr QDate(std::chrono::year_month_day date) noexcept
+ : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd())
+ {}
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT constexpr QDate(std::chrono::year_month_day_last date) noexcept
+ : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd())
+ {}
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT constexpr QDate(std::chrono::year_month_weekday date) noexcept
+ : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd())
+ {}
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT constexpr QDate(std::chrono::year_month_weekday_last date) noexcept
+ : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd())
+ {}
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static constexpr QDate fromStdSysDays(const std::chrono::sys_days &days) noexcept
+ {
+ return QDate(stdSysDaysToJulianDay(days));
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ constexpr std::chrono::sys_days toStdSysDays() const noexcept
+ {
+ const qint64 days = isValid() ? jd - unixEpochJd() : 0;
+ return std::chrono::sys_days(std::chrono::days(days));
+ }
+#endif
- Q_DECL_CONSTEXPR bool isNull() const { return !isValid(); }
- Q_DECL_CONSTEXPR bool isValid() const { return jd >= minJd() && jd <= maxJd(); }
+ constexpr bool isNull() const { return !isValid(); }
+ constexpr bool isValid() const { return jd >= minJd() && jd <= maxJd(); }
// Gregorian-optimized:
int year() const;
@@ -89,83 +88,139 @@ public:
int daysInMonth(QCalendar cal) const;
int daysInYear(QCalendar cal) const;
- QDateTime startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
- QDateTime endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
-#if QT_CONFIG(timezone)
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead")
+ QDateTime startOfDay(Qt::TimeSpec spec, int offsetSeconds = 0) const;
+ QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead")
+ QDateTime endOfDay(Qt::TimeSpec spec, int offsetSeconds = 0) const;
+#endif
+
QDateTime startOfDay(const QTimeZone &zone) const;
QDateTime endOfDay(const QTimeZone &zone) const;
-#endif
+ QDateTime startOfDay() const;
+ QDateTime endOfDay() const;
#if QT_CONFIG(datestring)
QString toString(Qt::DateFormat format = Qt::TextDate) const;
-# if QT_STRINGVIEW_LEVEL < 2
- QString toString(const QString &format, QCalendar cal = QCalendar()) const;
-# endif
- QString toString(QStringView format, QCalendar cal = QCalendar()) const;
+ QString toString(const QString &format) const;
+ QString toString(const QString &format, QCalendar cal) const
+ { return toString(qToStringViewIgnoringNull(format), cal); }
+ QString toString(QStringView format) const;
+ QString toString(QStringView format, QCalendar cal) const;
#endif
bool setDate(int year, int month, int day); // Gregorian-optimized
bool setDate(int year, int month, int day, QCalendar cal);
void getDate(int *year, int *month, int *day) const;
- Q_REQUIRED_RESULT QDate addDays(qint64 days) const;
+ [[nodiscard]] QDate addDays(qint64 days) const;
+#if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ [[nodiscard]] QDate addDuration(std::chrono::days days) const
+ {
+ return addDays(days.count());
+ }
+#endif
// Gregorian-optimized:
- Q_REQUIRED_RESULT QDate addMonths(int months) const;
- Q_REQUIRED_RESULT QDate addYears(int years) const;
- Q_REQUIRED_RESULT QDate addMonths(int months, QCalendar cal) const;
- Q_REQUIRED_RESULT QDate addYears(int years, QCalendar cal) const;
+ [[nodiscard]] QDate addMonths(int months) const;
+ [[nodiscard]] QDate addYears(int years) const;
+ [[nodiscard]] QDate addMonths(int months, QCalendar cal) const;
+ [[nodiscard]] QDate addYears(int years, QCalendar cal) const;
qint64 daysTo(QDate d) const;
- Q_DECL_CONSTEXPR bool operator==(QDate other) const { return jd == other.jd; }
- Q_DECL_CONSTEXPR bool operator!=(QDate other) const { return jd != other.jd; }
- Q_DECL_CONSTEXPR bool operator< (QDate other) const { return jd < other.jd; }
- Q_DECL_CONSTEXPR bool operator<=(QDate other) const { return jd <= other.jd; }
- Q_DECL_CONSTEXPR bool operator> (QDate other) const { return jd > other.jd; }
- Q_DECL_CONSTEXPR bool operator>=(QDate other) const { return jd >= other.jd; }
-
static QDate currentDate();
#if QT_CONFIG(datestring)
- static QDate fromString(QStringView s, Qt::DateFormat f = Qt::TextDate);
- static QDate fromString(QStringView s, QStringView format, QCalendar cal = QCalendar());
-# if QT_STRINGVIEW_LEVEL < 2
- static QDate fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
- static QDate fromString(const QString &s, const QString &format, QCalendar cal = QCalendar());
-# endif
+ // No DateFormat accepts a two-digit year, so no need for baseYear:
+ static QDate fromString(QStringView string, Qt::DateFormat format = Qt::TextDate);
+ static QDate fromString(const QString &string, Qt::DateFormat format = Qt::TextDate)
+ { return fromString(qToStringViewIgnoringNull(string), format); }
+
+ // Accept calendar without over-ride of base year:
+ static QDate fromString(QStringView string, QStringView format, QCalendar cal)
+ { return fromString(string.toString(), format, QLocale::DefaultTwoDigitBaseYear, cal); }
+ QT_CORE_INLINE_SINCE(6, 7)
+ static QDate fromString(const QString &string, QStringView format, QCalendar cal);
+ static QDate fromString(const QString &string, const QString &format, QCalendar cal)
+ { return fromString(string, qToStringViewIgnoringNull(format), QLocale::DefaultTwoDigitBaseYear, cal); }
+
+ // Overriding base year is likely more common than overriding calendar (and
+ // likely to get more so, as the legacy base drops ever further behind us).
+ static QDate fromString(QStringView string, QStringView format,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear)
+ { return fromString(string.toString(), format, baseYear); }
+ static QDate fromString(QStringView string, QStringView format,
+ int baseYear, QCalendar cal)
+ { return fromString(string.toString(), format, baseYear, cal); }
+ static QDate fromString(const QString &string, QStringView format,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear);
+ static QDate fromString(const QString &string, QStringView format,
+ int baseYear, QCalendar cal);
+ static QDate fromString(const QString &string, const QString &format,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear)
+ { return fromString(string, qToStringViewIgnoringNull(format), baseYear); }
+ static QDate fromString(const QString &string, const QString &format,
+ int baseYear, QCalendar cal)
+ { return fromString(string, qToStringViewIgnoringNull(format), baseYear, cal); }
#endif
static bool isValid(int y, int m, int d);
static bool isLeapYear(int year);
- static Q_DECL_CONSTEXPR inline QDate fromJulianDay(qint64 jd_)
+ static constexpr inline QDate fromJulianDay(qint64 jd_)
{ return jd_ >= minJd() && jd_ <= maxJd() ? QDate(jd_) : QDate() ; }
- Q_DECL_CONSTEXPR inline qint64 toJulianDay() const { return jd; }
+ constexpr inline qint64 toJulianDay() const { return jd; }
private:
// using extra parentheses around min to avoid expanding it if it is a macro
- static Q_DECL_CONSTEXPR inline qint64 nullJd() { return (std::numeric_limits<qint64>::min)(); }
- static Q_DECL_CONSTEXPR inline qint64 minJd() { return Q_INT64_C(-784350574879); }
- static Q_DECL_CONSTEXPR inline qint64 maxJd() { return Q_INT64_C( 784354017364); }
+ static constexpr inline qint64 nullJd() { return (std::numeric_limits<qint64>::min)(); }
+ static constexpr inline qint64 minJd() { return Q_INT64_C(-784350574879); }
+ static constexpr inline qint64 maxJd() { return Q_INT64_C( 784354017364); }
+ static constexpr inline qint64 unixEpochJd() { return Q_INT64_C(2440588); }
+
+#if __cpp_lib_chrono >= 201907L
+ static constexpr qint64 stdSysDaysToJulianDay(const std::chrono::sys_days &days) noexcept
+ {
+ const auto epochDays = days.time_since_epoch().count();
+ // minJd() and maxJd() fit into 40 bits.
+ if constexpr (sizeof(epochDays) * CHAR_BIT >= 41) {
+ constexpr auto top = maxJd() - unixEpochJd();
+ constexpr auto bottom = minJd() - unixEpochJd();
+ if (epochDays > top || epochDays < bottom)
+ return nullJd();
+ }
+ return unixEpochJd() + epochDays;
+ }
+#endif // __cpp_lib_chrono >= 201907L
qint64 jd;
friend class QDateTime;
+ friend class QDateTimeParser;
friend class QDateTimePrivate;
+
+ friend constexpr bool comparesEqual(const QDate &lhs, const QDate &rhs) noexcept
+ { return lhs.jd == rhs.jd; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QDate &lhs, const QDate &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.jd, rhs.jd); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QDate)
+
#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QDate);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);
#endif
};
-Q_DECLARE_TYPEINFO(QDate, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QDate, Q_RELOCATABLE_TYPE);
-class Q_CORE_EXPORT QTime // ### Qt 6: change to be used by value, not const &
+class Q_CORE_EXPORT QTime
{
- explicit Q_DECL_CONSTEXPR QTime(int ms) : mds(ms)
+ explicit constexpr QTime(int ms) : mds(ms)
{}
public:
- Q_DECL_CONSTEXPR QTime(): mds(NullTime)
+ constexpr QTime(): mds(NullTime)
{}
QTime(int h, int m, int s = 0, int ms = 0);
- Q_DECL_CONSTEXPR bool isNull() const { return mds == NullTime; }
+ constexpr bool isNull() const { return mds == NullTime; }
bool isValid() const;
int hour() const;
@@ -174,40 +229,45 @@ public:
int msec() const;
#if QT_CONFIG(datestring)
QString toString(Qt::DateFormat f = Qt::TextDate) const;
-#if QT_STRINGVIEW_LEVEL < 2
- QString toString(const QString &format) const;
-#endif
+ QString toString(const QString &format) const
+ { return toString(qToStringViewIgnoringNull(format)); }
QString toString(QStringView format) const;
#endif
bool setHMS(int h, int m, int s, int ms = 0);
- Q_REQUIRED_RESULT QTime addSecs(int secs) const;
+ [[nodiscard]] QTime addSecs(int secs) const;
int secsTo(QTime t) const;
- Q_REQUIRED_RESULT QTime addMSecs(int ms) const;
+ [[nodiscard]] QTime addMSecs(int ms) const;
int msecsTo(QTime t) const;
- Q_DECL_CONSTEXPR bool operator==(QTime other) const { return mds == other.mds; }
- Q_DECL_CONSTEXPR bool operator!=(QTime other) const { return mds != other.mds; }
- Q_DECL_CONSTEXPR bool operator< (QTime other) const { return mds < other.mds; }
- Q_DECL_CONSTEXPR bool operator<=(QTime other) const { return mds <= other.mds; }
- Q_DECL_CONSTEXPR bool operator> (QTime other) const { return mds > other.mds; }
- Q_DECL_CONSTEXPR bool operator>=(QTime other) const { return mds >= other.mds; }
-
- static Q_DECL_CONSTEXPR inline QTime fromMSecsSinceStartOfDay(int msecs) { return QTime(msecs); }
- Q_DECL_CONSTEXPR inline int msecsSinceStartOfDay() const { return mds == NullTime ? 0 : mds; }
+ static constexpr inline QTime fromMSecsSinceStartOfDay(int msecs) { return QTime(msecs); }
+ constexpr inline int msecsSinceStartOfDay() const { return mds == NullTime ? 0 : mds; }
static QTime currentTime();
#if QT_CONFIG(datestring)
- static QTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
- static QTime fromString(const QString &s, const QString &format);
+ static QTime fromString(QStringView string, Qt::DateFormat format = Qt::TextDate);
+ static QTime fromString(QStringView string, QStringView format)
+ { return fromString(string.toString(), format); }
+ static QTime fromString(const QString &string, QStringView format);
+ static QTime fromString(const QString &string, Qt::DateFormat format = Qt::TextDate)
+ { return fromString(qToStringViewIgnoringNull(string), format); }
+ static QTime fromString(const QString &string, const QString &format)
+ { return fromString(string, qToStringViewIgnoringNull(format)); }
#endif
static bool isValid(int h, int m, int s, int ms = 0);
private:
enum TimeFlag { NullTime = -1 };
- Q_DECL_CONSTEXPR inline int ds() const { return mds == -1 ? 0 : mds; }
+ constexpr inline int ds() const { return mds == -1 ? 0 : mds; }
int mds;
+ friend constexpr bool comparesEqual(const QTime &lhs, const QTime &rhs) noexcept
+ { return lhs.mds == rhs.mds; }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QTime &lhs, const QTime &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.mds, rhs.mds); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QTime)
+
friend class QDateTime;
friend class QDateTimePrivate;
#ifndef QT_NO_DATASTREAM
@@ -215,42 +275,58 @@ private:
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &);
#endif
};
-Q_DECLARE_TYPEINFO(QTime, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QTime, Q_RELOCATABLE_TYPE);
class QDateTimePrivate;
class Q_CORE_EXPORT QDateTime
{
- // ### Qt 6: revisit the optimization
struct ShortData {
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#if QT_VERSION >= QT_VERSION_CHECK(7,0,0) || defined(QT_BOOTSTRAPPED)
+# if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ qint64 status : 8;
+# endif
+ qint64 msecs : 56;
+
+# if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ qint64 status : 8;
+# endif
+#else
+# if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
quintptr status : 8;
-#endif
+# endif
// note: this is only 24 bits on 32-bit systems...
qintptr msecs : sizeof(void *) * 8 - 8;
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+# if Q_BYTE_ORDER == Q_BIG_ENDIAN
quintptr status : 8;
+# endif
#endif
+ friend constexpr bool operator==(ShortData lhs, ShortData rhs)
+ { return lhs.status == rhs.status && lhs.msecs == rhs.msecs; }
};
union Data {
- enum {
- // To be of any use, we need at least 60 years around 1970, which
- // is 1,893,456,000,000 ms. That requires 41 bits to store, plus
- // the sign bit. With the status byte, the minimum size is 50 bits.
- CanBeSmall = sizeof(ShortData) * 8 > 50
- };
-
- Data();
- Data(Qt::TimeSpec);
- Data(const Data &other);
- Data(Data &&other);
- Data &operator=(const Data &other);
+ // To be of any use, we need at least 60 years around 1970, which
+ // is 1,893,456,000,000 ms. That requires 41 bits to store, plus
+ // the sign bit. With the status byte, the minimum size is 50 bits.
+ static constexpr bool CanBeSmall = sizeof(ShortData) * 8 > 50;
+
+ Data() noexcept;
+ Data(const QTimeZone &);
+ Data(const Data &other) noexcept;
+ Data(Data &&other) noexcept;
+ Data &operator=(const Data &other) noexcept;
+ Data &operator=(Data &&other) noexcept { swap(other); return *this; }
~Data();
+ void swap(Data &other) noexcept
+ { std::swap(data, other.data); }
+
bool isShort() const;
+ inline void invalidate();
void detach();
+ QTimeZone timeZone() const;
const QDateTimePrivate *operator->() const;
QDateTimePrivate *operator->();
@@ -260,19 +336,40 @@ class Q_CORE_EXPORT QDateTime
};
public:
- QDateTime() noexcept(Data::CanBeSmall);
- QDateTime(QDate date, QTime time, Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0);
-#if QT_CONFIG(timezone)
+ QDateTime() noexcept;
+
+ enum class TransitionResolution {
+ Reject = 0,
+ RelativeToBefore,
+ RelativeToAfter,
+ PreferBefore,
+ PreferAfter,
+ PreferStandard,
+ PreferDaylightSaving,
+ // Closest match to behavior prior to introducing TransitionResolution:
+ LegacyBehavior = RelativeToBefore
+ };
+
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead")
+ QDateTime(QDate date, QTime time, Qt::TimeSpec spec, int offsetSeconds = 0);
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 7)
QDateTime(QDate date, QTime time, const QTimeZone &timeZone);
-#endif // timezone
+ QDateTime(QDate date, QTime time);
+#endif
+ QDateTime(QDate date, QTime time, const QTimeZone &timeZone,
+ TransitionResolution resolve = TransitionResolution::LegacyBehavior);
+ QDateTime(QDate date, QTime time,
+ TransitionResolution resolve = TransitionResolution::LegacyBehavior);
QDateTime(const QDateTime &other) noexcept;
QDateTime(QDateTime &&other) noexcept;
~QDateTime();
- QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QDateTime)
QDateTime &operator=(const QDateTime &other) noexcept;
- void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); }
+ void swap(QDateTime &other) noexcept { d.swap(other.d); }
bool isNull() const;
bool isValid() const;
@@ -281,6 +378,7 @@ public:
QTime time() const;
Qt::TimeSpec timeSpec() const;
int offsetFromUtc() const;
+ QTimeZone timeRepresentation() const;
#if QT_CONFIG(timezone)
QTimeZone timeZone() const;
#endif // timezone
@@ -290,65 +388,106 @@ public:
qint64 toMSecsSinceEpoch() const;
qint64 toSecsSinceEpoch() const;
+#if QT_CORE_REMOVED_SINCE(6, 7)
void setDate(QDate date);
void setTime(QTime time);
+#endif
+ void setDate(QDate date, TransitionResolution resolve = TransitionResolution::LegacyBehavior);
+ void setTime(QTime time, TransitionResolution resolve = TransitionResolution::LegacyBehavior);
+
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_DEPRECATED_VERSION_X_6_9("Use setTimeZone() instead")
void setTimeSpec(Qt::TimeSpec spec);
+ QT_DEPRECATED_VERSION_X_6_9("Use setTimeZone() instead")
void setOffsetFromUtc(int offsetSeconds);
-#if QT_CONFIG(timezone)
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 7)
void setTimeZone(const QTimeZone &toZone);
-#endif // timezone
+#endif
+ void setTimeZone(const QTimeZone &toZone,
+ TransitionResolution resolve = TransitionResolution::LegacyBehavior);
void setMSecsSinceEpoch(qint64 msecs);
void setSecsSinceEpoch(qint64 secs);
#if QT_CONFIG(datestring)
QString toString(Qt::DateFormat format = Qt::TextDate) const;
-# if QT_STRINGVIEW_LEVEL < 2
- QString toString(const QString &format, QCalendar cal = QCalendar()) const;
-# endif
- QString toString(QStringView format, QCalendar cal = QCalendar()) const;
+ QString toString(const QString &format) const;
+ QString toString(const QString &format, QCalendar cal) const
+ { return toString(qToStringViewIgnoringNull(format), cal); }
+ QString toString(QStringView format) const;
+ QString toString(QStringView format, QCalendar cal) const;
#endif
- Q_REQUIRED_RESULT QDateTime addDays(qint64 days) const;
- Q_REQUIRED_RESULT QDateTime addMonths(int months) const;
- Q_REQUIRED_RESULT QDateTime addYears(int years) const;
- Q_REQUIRED_RESULT QDateTime addSecs(qint64 secs) const;
- Q_REQUIRED_RESULT QDateTime addMSecs(qint64 msecs) const;
-
+ [[nodiscard]] QDateTime addDays(qint64 days) const;
+ [[nodiscard]] QDateTime addMonths(int months) const;
+ [[nodiscard]] QDateTime addYears(int years) const;
+ [[nodiscard]] QDateTime addSecs(qint64 secs) const;
+ [[nodiscard]] QDateTime addMSecs(qint64 msecs) const;
+ [[nodiscard]] QDateTime addDuration(std::chrono::milliseconds msecs) const
+ {
+ return addMSecs(msecs.count());
+ }
+
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_DEPRECATED_VERSION_X_6_9("Use toTimeZone instead")
QDateTime toTimeSpec(Qt::TimeSpec spec) const;
- inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); }
- inline QDateTime toUTC() const { return toTimeSpec(Qt::UTC); }
+#endif
+ QDateTime toLocalTime() const;
+ QDateTime toUTC() const;
QDateTime toOffsetFromUtc(int offsetSeconds) const;
-#if QT_CONFIG(timezone)
QDateTime toTimeZone(const QTimeZone &toZone) const;
-#endif // timezone
qint64 daysTo(const QDateTime &) const;
qint64 secsTo(const QDateTime &) const;
qint64 msecsTo(const QDateTime &) const;
- bool operator==(const QDateTime &other) const;
- inline bool operator!=(const QDateTime &other) const { return !(*this == other); }
- bool operator<(const QDateTime &other) const;
- inline bool operator<=(const QDateTime &other) const { return !(other < *this); }
- inline bool operator>(const QDateTime &other) const { return other < *this; }
- inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
-
+ static QDateTime currentDateTime(const QTimeZone &zone);
static QDateTime currentDateTime();
static QDateTime currentDateTimeUtc();
#if QT_CONFIG(datestring)
- static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate);
- static QDateTime fromString(const QString &s, const QString &format,
- QCalendar cal = QCalendar());
+ // No DateFormat accepts a two-digit year, so no need for baseYear:
+ static QDateTime fromString(QStringView string, Qt::DateFormat format = Qt::TextDate);
+ static QDateTime fromString(const QString &string, Qt::DateFormat format = Qt::TextDate)
+ { return fromString(qToStringViewIgnoringNull(string), format); }
+
+ // Accept calendar without over-ride of base year:
+ static QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
+ { return fromString(string.toString(), format, QLocale::DefaultTwoDigitBaseYear, cal); }
+ QT_CORE_INLINE_SINCE(6, 7)
+ static QDateTime fromString(const QString &string, QStringView format, QCalendar cal);
+ static QDateTime fromString(const QString &string, const QString &format, QCalendar cal)
+ { return fromString(string, qToStringViewIgnoringNull(format), QLocale::DefaultTwoDigitBaseYear, cal); }
+
+ // Overriding base year is likely more common than overriding calendar (and
+ // likely to get more so, as the legacy base drops ever further behind us).
+ static QDateTime fromString(QStringView string, QStringView format,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear)
+ { return fromString(string.toString(), format, baseYear); }
+ static QDateTime fromString(QStringView string, QStringView format,
+ int baseYear, QCalendar cal)
+ { return fromString(string.toString(), format, baseYear, cal); }
+ static QDateTime fromString(const QString &string, QStringView format,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear);
+ static QDateTime fromString(const QString &string, QStringView format,
+ int baseYear, QCalendar cal);
+ static QDateTime fromString(const QString &string, const QString &format,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear)
+ { return fromString(string, qToStringViewIgnoringNull(format), baseYear); }
+ static QDateTime fromString(const QString &string, const QString &format,
+ int baseYear, QCalendar cal)
+ { return fromString(string, qToStringViewIgnoringNull(format), baseYear, cal); }
#endif
- static QDateTime fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec = Qt::LocalTime,
- int offsetFromUtc = 0);
- static QDateTime fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spe = Qt::LocalTime,
- int offsetFromUtc = 0);
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead of time-spec, offset")
+ static QDateTime fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetFromUtc = 0);
+ QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead of time-spec, offset")
+ static QDateTime fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetFromUtc = 0);
+#endif
-#if QT_CONFIG(timezone)
static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone);
static QDateTime fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone);
-#endif
+ static QDateTime fromMSecsSinceEpoch(qint64 msecs);
+ static QDateTime fromSecsSinceEpoch(qint64 secs);
static qint64 currentMSecsSinceEpoch() noexcept;
static qint64 currentSecsSinceEpoch() noexcept;
@@ -360,15 +499,115 @@ public:
NSDate *toNSDate() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
+#if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
+#if __cpp_concepts >= 201907L || defined(Q_QDOC)
+ // Generic clock, as long as it's compatible with us (= system_clock)
+ template <typename Clock, typename Duration>
+ static QDateTime fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
+ requires
+ requires(const std::chrono::time_point<Clock, Duration> &t) {
+ // the clock can be converted to system_clock
+ std::chrono::clock_cast<std::chrono::system_clock>(t);
+ // the duration can be converted to milliseconds
+ requires std::is_convertible_v<Duration, std::chrono::milliseconds>;
+ }
+ {
+ const auto sysTime = std::chrono::clock_cast<std::chrono::system_clock>(time);
+ // clock_cast can change the duration, so convert it again to milliseconds
+ const auto timeInMSec = std::chrono::time_point_cast<std::chrono::milliseconds>(sysTime);
+ return fromMSecsSinceEpoch(timeInMSec.time_since_epoch().count(), Qt::UTC);
+ }
+#endif // __cpp_concepts
+
+ // local_time
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static QDateTime fromStdTimePoint(const std::chrono::local_time<std::chrono::milliseconds> &time)
+ {
+ return fromStdLocalTime(time);
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static QDateTime fromStdLocalTime(const std::chrono::local_time<std::chrono::milliseconds> &time)
+ {
+ QDateTime result(QDate(1970, 1, 1), QTime(0, 0, 0), TransitionResolution::LegacyBehavior);
+ return result.addMSecs(time.time_since_epoch().count());
+ }
+
+#if QT_CONFIG(timezone) && (__cpp_lib_chrono >= 201907L || defined(Q_QDOC))
+ // zoned_time. defined in qtimezone.h
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static QDateTime fromStdZonedTime(const std::chrono::zoned_time<
+ std::chrono::milliseconds,
+ const std::chrono::time_zone *
+ > &time);
+#endif // QT_CONFIG(timezone)
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ std::chrono::sys_time<std::chrono::milliseconds> toStdSysMilliseconds() const
+ {
+ const std::chrono::milliseconds duration(toMSecsSinceEpoch());
+ return std::chrono::sys_time<std::chrono::milliseconds>(duration);
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ std::chrono::sys_seconds toStdSysSeconds() const
+ {
+ const std::chrono::seconds duration(toSecsSinceEpoch());
+ return std::chrono::sys_seconds(duration);
+ }
+#endif // __cpp_lib_chrono >= 201907L
+
+ friend std::chrono::milliseconds operator-(const QDateTime &lhs, const QDateTime &rhs)
+ {
+ return std::chrono::milliseconds(rhs.msecsTo(lhs));
+ }
+
+ friend QDateTime operator+(const QDateTime &dateTime, std::chrono::milliseconds duration)
+ {
+ return dateTime.addMSecs(duration.count());
+ }
+
+ friend QDateTime operator+(std::chrono::milliseconds duration, const QDateTime &dateTime)
+ {
+ return dateTime + duration;
+ }
+
+ QDateTime &operator+=(std::chrono::milliseconds duration)
+ {
+ *this = addMSecs(duration.count());
+ return *this;
+ }
+
+ friend QDateTime operator-(const QDateTime &dateTime, std::chrono::milliseconds duration)
+ {
+ return dateTime.addMSecs(-duration.count());
+ }
+
+ QDateTime &operator-=(std::chrono::milliseconds duration)
+ {
+ *this = addMSecs(-duration.count());
+ return *this;
+ }
+
// (1<<63) ms is 292277024.6 (average Gregorian) years, counted from the start of 1970, so
// Last is floor(1970 + 292277024.6); no year 0, so First is floor(1970 - 1 - 292277024.6)
enum class YearRange : qint32 { First = -292275056, Last = +292278994 };
private:
+ bool equals(const QDateTime &other) const;
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ bool precedes(const QDateTime &other) const;
+#endif
friend class QDateTimePrivate;
Data d;
+ friend bool comparesEqual(const QDateTime &lhs, const QDateTime &rhs)
+ { return lhs.equals(rhs); }
+ friend Q_CORE_EXPORT Qt::weak_ordering
+ compareThreeWay(const QDateTime &lhs, const QDateTime &rhs);
+ Q_DECLARE_WEAKLY_ORDERED(QDateTime)
+
#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &);
@@ -401,6 +640,18 @@ Q_CORE_EXPORT size_t qHash(const QDateTime &key, size_t seed = 0);
Q_CORE_EXPORT size_t qHash(QDate key, size_t seed = 0) noexcept;
Q_CORE_EXPORT size_t qHash(QTime key, size_t seed = 0) noexcept;
+#if QT_CONFIG(datestring) && QT_CORE_INLINE_IMPL_SINCE(6, 7)
+QDate QDate::fromString(const QString &string, QStringView format, QCalendar cal)
+{
+ return fromString(string, format, QLocale::DefaultTwoDigitBaseYear, cal);
+}
+
+QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal)
+{
+ return fromString(string, format, QLocale::DefaultTwoDigitBaseYear, cal);
+}
+#endif
+
QT_END_NAMESPACE
#endif // QDATETIME_H
diff --git a/src/corelib/time/qdatetime_p.h b/src/corelib/time/qdatetime_p.h
index c500b023c4..02b047dd73 100644
--- a/src/corelib/time/qdatetime_p.h
+++ b/src/corelib/time/qdatetime_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATETIME_P_H
#define QDATETIME_P_H
@@ -57,11 +21,14 @@
#include "QtCore/qatomic.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qshareddata.h"
+#include "QtCore/qtimezone.h"
#if QT_CONFIG(timezone)
#include "qtimezone.h"
#endif
+#include <chrono>
+
QT_BEGIN_NAMESPACE
class QDateTimePrivate : public QSharedData
@@ -100,39 +67,85 @@ public:
TimeSpecMask = 0x30,
SetToStandardTime = 0x40,
- SetToDaylightTime = 0x80
+ SetToDaylightTime = 0x80,
+ ValidityMask = ValidDate | ValidTime | ValidDateTime,
+ DaylightMask = SetToStandardTime | SetToDaylightTime,
};
Q_DECLARE_FLAGS(StatusFlags, StatusFlag)
+
+ enum TransitionOption {
+ // Handling of a spring-forward (or other gap):
+ GapUseBefore = 2,
+ GapUseAfter = 4,
+ // Handling of a fall-back (or other repeated period):
+ FoldUseBefore = 0x20,
+ FoldUseAfter = 0x40,
+ // Quirk for negative DST:
+ FlipForReverseDst = 0x400,
+
+ GapMask = GapUseBefore | GapUseAfter,
+ FoldMask = FoldUseBefore | FoldUseAfter,
+ };
+ Q_DECLARE_FLAGS(TransitionOptions, TransitionOption)
+
enum {
TimeSpecShift = 4,
- ValidityMask = ValidDate | ValidTime | ValidDateTime,
- DaylightMask = SetToStandardTime | SetToDaylightTime
};
- static QDateTime::Data create(QDate toDate, QTime toTime, Qt::TimeSpec toSpec,
- int offsetSeconds);
+ struct ZoneState {
+ qint64 when; // ms after zone/local 1970 start; may be revised from the input time.
+ int offset = 0; // seconds
+ DaylightStatus dst = UnknownDaylightTime;
+ // Other fields are set, if possible, even when valid is false due to spring-forward.
+ bool valid = false;
+
+ ZoneState(qint64 local) : when(local) {}
+ ZoneState(qint64 w, int o, DaylightStatus d, bool v = true)
+ : when(w), offset(o), dst(d), valid(v) {}
+ };
+ static QDateTime::Data create(QDate toDate, QTime toTime, const QTimeZone &timeZone,
+ QDateTime::TransitionResolution resolve);
#if QT_CONFIG(timezone)
- static QDateTime::Data create(QDate toDate, QTime toTime, const QTimeZone & timeZone);
+ static ZoneState zoneStateAtMillis(const QTimeZone &zone, qint64 millis,
+ TransitionOptions resolve);
#endif // timezone
+ static ZoneState expressUtcAsLocal(qint64 utcMSecs);
+
+ static ZoneState localStateAtMillis(qint64 millis, TransitionOptions resolve);
+ static QString localNameAtMillis(qint64 millis, DaylightStatus dst); // empty if unknown
+
StatusFlags m_status = StatusFlag(Qt::LocalTime << TimeSpecShift);
qint64 m_msecs = 0;
int m_offsetFromUtc = 0;
-#if QT_CONFIG(timezone)
QTimeZone m_timeZone;
-#endif // timezone
+};
-#if QT_CONFIG(timezone)
- static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
- DaylightStatus hint = UnknownDaylightTime,
- QDate *localDate = nullptr, QTime *localTime = nullptr);
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::StatusFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::TransitionOptions)
- // Inlined for its one caller in qdatetime.cpp
- inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
-#endif // timezone
-};
+namespace QtPrivate {
+namespace DateTimeConstants {
+using namespace std::chrono;
+constexpr qint64 SECS_PER_MIN = minutes::period::num;
+constexpr qint64 SECS_PER_HOUR = hours::period::num;
+constexpr qint64 SECS_PER_DAY = SECS_PER_HOUR * 24; // std::chrono::days is C++20
+
+constexpr qint64 MINS_PER_HOUR = std::ratio_divide<hours::period, minutes::period>::num;
+
+constexpr qint64 MSECS_PER_SEC = milliseconds::period::den;
+constexpr qint64 MSECS_PER_MIN = SECS_PER_MIN * MSECS_PER_SEC;
+constexpr qint64 MSECS_PER_HOUR = SECS_PER_HOUR * MSECS_PER_SEC;
+constexpr qint64 MSECS_PER_DAY = SECS_PER_DAY * MSECS_PER_SEC;
+
+constexpr qint64 JULIAN_DAY_FOR_EPOCH = 2440588; // result of QDate(1970, 1, 1).toJulianDay()
+
+constexpr qint64 JulianDayMax = Q_INT64_C( 784354017364);
+constexpr qint64 JulianDayMin = Q_INT64_C(-784350574879);
+}
+}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index dd9e1507e4..cce32e7ad2 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -1,53 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "private/qdatetimeparser_p.h"
#include "qdatastream.h"
-#include "qset.h"
-#include "qlocale.h"
#include "qdatetime.h"
-#if QT_CONFIG(timezone)
-#include "qtimezone.h"
-#endif
#include "qdebug.h"
+#include "qlocale.h"
+#include "qset.h"
+#include "qtimezone.h"
+#include "qvarlengtharray.h"
+#include "private/qlocale_p.h"
+
+#include "private/qstringiterator_p.h"
+#include "private/qtenvironmentvariables_p.h"
//#define QDATETIMEPARSER_DEBUG
#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
@@ -60,6 +27,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
template <typename T>
using ShortVector = QVarLengthArray<T, 13>; // enough for month (incl. leap) and day-of-week names
@@ -79,12 +48,8 @@ QDateTimeParser::~QDateTimeParser()
int QDateTimeParser::getDigit(const QDateTime &t, int index) const
{
if (index < 0 || index >= sectionNodes.size()) {
-#if QT_CONFIG(datestring)
qWarning("QDateTimeParser::getDigit() Internal error (%ls %d)",
qUtf16Printable(t.toString()), index);
-#else
- qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
-#endif
return -1;
}
const SectionNode &node = sectionNodes.at(index);
@@ -99,22 +64,46 @@ int QDateTimeParser::getDigit(const QDateTime &t, int index) const
case MonthSection: return t.date().month(calendar);
case DaySection: return t.date().day(calendar);
case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: return t.date().day(calendar);
+ case DayOfWeekSectionLong: return calendar.dayOfWeek(t.date());
case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
default: break;
}
-#if QT_CONFIG(datestring)
qWarning("QDateTimeParser::getDigit() Internal error 2 (%ls %d)",
qUtf16Printable(t.toString()), index);
-#else
- qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
-#endif
return -1;
}
/*!
+ \internal
+ Difference between two days of the week.
+
+ Returns a difference in the range from -3 through +3, so that steps by small
+ numbers of days move us through the month in the same direction as through
+ the week.
+*/
+
+static int dayOfWeekDiff(int sought, int held)
+{
+ const int diff = sought - held;
+ return diff < -3 ? diff + 7 : diff > 3 ? diff - 7 : diff;
+}
+
+static bool preferDayOfWeek(const QList<QDateTimeParser::SectionNode> &nodes)
+{
+ // True precisely if there is a day-of-week field but no day-of-month field.
+ bool result = false;
+ for (const auto &node : nodes) {
+ if (node.type & QDateTimeParser::DaySection)
+ return false;
+ if (node.type & QDateTimeParser::DayOfWeekSectionMask)
+ result = true;
+ }
+ return result;
+}
+
+/*!
\internal
Sets a digit in a datetime. E.g.
@@ -129,27 +118,24 @@ int QDateTimeParser::getDigit(const QDateTime &t, int index) const
bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
{
if (index < 0 || index >= sectionNodes.size()) {
-#if QT_CONFIG(datestring)
qWarning("QDateTimeParser::setDigit() Internal error (%ls %d %d)",
qUtf16Printable(v.toString()), index, newVal);
-#else
- qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
-#endif
return false;
}
- QCalendar::YearMonthDay date = calendar.partsFromDate(v.date());
+ const QDate oldDate = v.date();
+ QCalendar::YearMonthDay date = calendar.partsFromDate(oldDate);
if (!date.isValid())
return false;
+ int weekDay = calendar.dayOfWeek(oldDate);
+ enum { NoFix, MonthDay, WeekDay } fixDay = NoFix;
const QTime time = v.time();
int hour = time.hour();
int minute = time.minute();
int second = time.second();
int msec = time.msec();
- Qt::TimeSpec tspec = v.timeSpec();
- // Only offset from UTC is amenable to setting an int value:
- int offset = tspec == Qt::OffsetFromUTC ? v.offsetFromUtc() : 0;
+ QTimeZone timeZone = v.timeRepresentation();
const SectionNode &node = sectionNodes.at(index);
switch (node.type) {
@@ -161,8 +147,6 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
case YearSection: date.year = newVal; break;
case MonthSection: date.month = newVal; break;
case DaySection:
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong:
if (newVal > 31) {
// have to keep legacy behavior. setting the
// date to 32 should return false. Setting it
@@ -170,12 +154,21 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
return false;
}
date.day = newVal;
+ fixDay = MonthDay;
+ break;
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong:
+ if (newVal > 7 || newVal <= 0)
+ return false;
+ date.day += dayOfWeekDiff(newVal, weekDay);
+ weekDay = newVal;
+ fixDay = WeekDay;
break;
case TimeZoneSection:
if (newVal < absoluteMin(index) || newVal > absoluteMax(index))
return false;
- tspec = Qt::OffsetFromUTC;
- offset = newVal;
+ // Only offset from UTC is amenable to setting an int value:
+ timeZone = QTimeZone::fromSecondsAheadOfUtc(newVal);
break;
case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
default:
@@ -187,9 +180,27 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
if (!(node.type & DaySectionMask)) {
if (date.day < cachedDay)
date.day = cachedDay;
+ fixDay = MonthDay;
+ if (weekDay > 0 && weekDay <= 7 && preferDayOfWeek(sectionNodes)) {
+ const int max = calendar.daysInMonth(date.month, date.year);
+ if (max > 0 && date.day > max)
+ date.day = max;
+ const int newDoW = calendar.dayOfWeek(calendar.dateFromParts(date));
+ if (newDoW > 0 && newDoW <= 7)
+ date.day += dayOfWeekDiff(weekDay, newDoW);
+ fixDay = WeekDay;
+ }
+ }
+
+ if (fixDay != NoFix) {
const int max = calendar.daysInMonth(date.month, date.year);
- if (date.day > max)
- date.day = max;
+ // max > 0 precisely if the year does have such a month
+ if (max > 0 && date.day > max)
+ date.day = fixDay == WeekDay ? date.day - 7 : max;
+ else if (date.day < 1)
+ date.day = fixDay == WeekDay ? date.day + 7 : 1;
+ Q_ASSERT(fixDay != WeekDay
+ || calendar.dayOfWeek(calendar.dateFromParts(date)) == weekDay);
}
const QDate newDate = calendar.dateFromParts(date);
@@ -197,12 +208,7 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
if (!newDate.isValid() || !newTime.isValid())
return false;
- // Preserve zone:
- v =
-#if QT_CONFIG(timezone)
- tspec == Qt::TimeZone ? QDateTime(newDate, newTime, v.timeZone()) :
-#endif
- QDateTime(newDate, newTime, tspec, offset);
+ v = QDateTime(newDate, newTime, timeZone);
return true;
}
@@ -219,11 +225,7 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
const SectionNode &sn = sectionNode(s);
switch (sn.type) {
case TimeZoneSection:
-#if QT_CONFIG(timezone)
return QTimeZone::MaxUtcOffsetSecs;
-#else
- return +14 * 3600; // NB: copied from QTimeZone
-#endif
case Hour24Section:
case Hour12Section:
// This is special-cased in parseSection.
@@ -235,18 +237,19 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
case MSecSection:
return 999;
case YearSection2Digits:
- case YearSection:
// sectionMaxSize will prevent people from typing in a larger number in
// count == 2 sections; stepBy() will work on real years anyway.
+ case YearSection:
return 9999;
case MonthSection:
return calendar.maximumMonthsInYear();
case DaySection:
+ return cur.isValid() ? cur.date().daysInMonth(calendar) : calendar.maximumDaysInMonth();
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
- return cur.isValid() ? cur.date().daysInMonth(calendar) : calendar.maximumDaysInMonth();
+ return 7;
case AmPmSection:
- return 1;
+ return int(UpperCase);
default:
break;
}
@@ -266,23 +269,21 @@ int QDateTimeParser::absoluteMin(int s) const
const SectionNode &sn = sectionNode(s);
switch (sn.type) {
case TimeZoneSection:
-#if QT_CONFIG(timezone)
return QTimeZone::MinUtcOffsetSecs;
-#else
- return -14 * 3600; // NB: copied from QTimeZone
-#endif
case Hour24Section:
case Hour12Section:
case MinuteSection:
case SecondSection:
case MSecSection:
case YearSection2Digits:
- case YearSection: return 0;
+ return 0;
+ case YearSection:
+ return -9999;
case MonthSection:
case DaySection:
case DayOfWeekSectionShort:
case DayOfWeekSectionLong: return 1;
- case AmPmSection: return 0;
+ case AmPmSection: return int(NativeCase);
default: break;
}
qWarning("QDateTimeParser::absoluteMin() Internal error (%ls, %0x)",
@@ -333,7 +334,7 @@ int QDateTimeParser::sectionPos(int sectionIndex) const
return sectionPos(sectionNode(sectionIndex));
}
-int QDateTimeParser::sectionPos(const SectionNode &sn) const
+int QDateTimeParser::sectionPos(SectionNode sn) const
{
switch (sn.type) {
case FirstSection: return 0;
@@ -347,6 +348,22 @@ int QDateTimeParser::sectionPos(const SectionNode &sn) const
return sn.pos;
}
+/*!
+ \internal
+
+ Helper function for parseSection.
+*/
+
+static qsizetype digitCount(QStringView str)
+{
+ qsizetype digits = 0;
+ for (QStringIterator it(str); it.hasNext();) {
+ if (!QChar::isDigit(it.next()))
+ break;
+ digits++;
+ }
+ return digits;
+}
/*!
\internal
@@ -355,24 +372,23 @@ int QDateTimeParser::sectionPos(const SectionNode &sn) const
not escaped and removes the escaping on those that are escaped
*/
-
static QString unquote(QStringView str)
{
- const QChar quote(QLatin1Char('\''));
- const QChar slash(QLatin1Char('\\'));
- const QChar zero(QLatin1Char('0'));
+ // ### Align unquoting format strings for both from/toString(), QTBUG-110669
+ const QLatin1Char quote('\'');
+ const QLatin1Char slash('\\');
+ const QLatin1Char zero('0');
QString ret;
QChar status(zero);
const int max = str.size();
for (int i=0; i<max; ++i) {
if (str.at(i) == quote) {
- if (status != quote) {
+ if (status != quote)
status = quote;
- } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
+ else if (!ret.isEmpty() && str.at(i - 1) == slash)
ret[ret.size() - 1] = quote;
- } else {
+ else
status = zero;
- }
} else {
ret += str.at(i);
}
@@ -380,20 +396,20 @@ static QString unquote(QStringView str)
return ret;
}
-static inline int countRepeat(const QString &str, int index, int maxCount)
+static inline int countRepeat(QStringView str, int index, int maxCount)
{
- int count = 1;
- const QChar ch(str.at(index));
- const int max = qMin(index + maxCount, str.size());
- while (index + count < max && str.at(index + count) == ch) {
- ++count;
- }
- return count;
+ str = str.sliced(index);
+ if (maxCount < str.size())
+ str = str.first(maxCount);
+
+ return qt_repeatCount(str);
}
-static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
+static inline void appendSeparator(QStringList *list, QStringView string,
+ int from, int size, int lastQuote)
{
- const QStringView separator = QStringView(string).mid(from, size);
+ Q_ASSERT(size >= 0 && from + size <= string.size());
+ const QStringView separator = string.sliced(from, size);
list->append(lastQuote >= from ? unquote(separator) : separator.toString());
}
@@ -403,14 +419,13 @@ static inline void appendSeparator(QStringList *list, const QString &string, int
Parses the format \a newFormat. If successful, returns \c true and sets up
the format. Else keeps the old format and returns \c false.
*/
-bool QDateTimeParser::parseFormat(const QString &newFormat)
+bool QDateTimeParser::parseFormat(QStringView newFormat)
{
const QLatin1Char quote('\'');
const QLatin1Char slash('\\');
const QLatin1Char zero('0');
- if (newFormat == displayFormat && !newFormat.isEmpty()) {
+ if (newFormat == displayFormat && !newFormat.isEmpty())
return true;
- }
QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
@@ -419,18 +434,17 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
QStringList newSeparators;
int i, index = 0;
int add = 0;
- QChar status(zero);
+ QLatin1Char status(zero);
const int max = newFormat.size();
int lastQuote = -1;
for (i = 0; i<max; ++i) {
if (newFormat.at(i) == quote) {
lastQuote = i;
++add;
- if (status != quote) {
+ if (status != quote)
status = quote;
- } else if (i > 0 && newFormat.at(i - 1) != slash) {
+ else if (i > 0 && newFormat.at(i - 1) != slash)
status = zero;
- }
} else if (status != quote) {
const char sect = newFormat.at(i).toLatin1();
switch (sect) {
@@ -469,10 +483,11 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
case 'z':
if (parserType != QMetaType::QDate) {
- const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 };
+ const int repeat = countRepeat(newFormat, i, 3);
+ const SectionNode sn = { MSecSection, i - add, repeat < 3 ? 1 : 3, 0 };
newSectionNodes.append(sn);
appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
- i += sn.count - 1;
+ i += repeat - 1;
index = i + 1;
newDisplay |= MSecSection;
}
@@ -480,15 +495,18 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
case 'A':
case 'a':
if (parserType != QMetaType::QDate) {
- const bool cap = (sect == 'A');
- const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 };
- newSectionNodes.append(sn);
+ const int pos = i - add;
+ Case caseOpt = sect == 'A' ? UpperCase : LowerCase;
appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
newDisplay |= AmPmSection;
if (i + 1 < newFormat.size()
- && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
+ && newFormat.sliced(i + 1).startsWith(u'p', Qt::CaseInsensitive)) {
++i;
+ if (newFormat.at(i) != QLatin1Char(caseOpt == UpperCase ? 'P' : 'p'))
+ caseOpt = NativeCase;
}
+ const SectionNode sn = { AmPmSection, pos, int(caseOpt), 0 };
+ newSectionNodes.append(sn);
index = i + 1;
}
break;
@@ -510,7 +528,7 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
if (parserType != QMetaType::QTime) {
const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 };
newSectionNodes.append(sn);
- newSeparators.append(unquote(QStringView{newFormat}.mid(index, i - index)));
+ newSeparators.append(unquote(newFormat.first(i).sliced(index)));
i += sn.count - 1;
index = i + 1;
newDisplay |= MonthSection;
@@ -531,7 +549,8 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
break;
case 't':
if (parserType == QMetaType::QDateTime) {
- const SectionNode sn = { TimeZoneSection, i - add, countRepeat(newFormat, i, 4), 0 };
+ const SectionNode sn
+ = { TimeZoneSection, i - add, countRepeat(newFormat, i, 4), 0 };
newSectionNodes.append(sn);
appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
i += sn.count - 1;
@@ -544,9 +563,8 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
}
}
}
- if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
+ if (newSectionNodes.isEmpty() && context == DateTimeEdit)
return false;
- }
if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
const int count = newSectionNodes.size();
@@ -557,13 +575,12 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
}
}
- if (index < max) {
- appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
- } else {
+ if (index < max)
+ appendSeparator(&newSeparators, newFormat, index, max - index, lastQuote);
+ else
newSeparators.append(QString());
- }
- displayFormat = newFormat;
+ displayFormat = newFormat.toString();
separators = newSeparators;
sectionNodes = newSectionNodes;
display = newDisplay;
@@ -574,7 +591,7 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
// }
QDTPDEBUG << newFormat << displayFormat;
- QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
+ QDTPDEBUGN("separators:\n'%s'", separators.join("\n"_L1).toLatin1().constData());
return true;
}
@@ -602,7 +619,7 @@ int QDateTimeParser::sectionSize(int sectionIndex) const
// The size difference is always due to leading zeroes.
int sizeAdjustment = 0;
const int displayTextSize = displayText().size();
- if (displayTextSize != text.size()) {
+ if (displayTextSize != m_text.size()) {
// Any zeroes added before this section will affect our size.
int preceedingZeroesAdded = 0;
if (sectionNodes.size() > 1 && context == DateTimeEdit) {
@@ -634,13 +651,10 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
case LastSection:
return 0;
- case AmPmSection: {
- const int lowerMax = qMax(getAmPmText(AmText, LowerCase).size(),
- getAmPmText(PmText, LowerCase).size());
- const int upperMax = qMax(getAmPmText(AmText, UpperCase).size(),
- getAmPmText(PmText, UpperCase).size());
- return qMax(lowerMax, upperMax);
- }
+ case AmPmSection:
+ // Special: "count" here is a case flag, not field width !
+ return qMax(getAmPmText(AmText, Case(count)).size(),
+ getAmPmText(PmText, Case(count)).size());
case Hour24Section:
case Hour12Section:
@@ -651,16 +665,12 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
-#if !QT_CONFIG(textdate)
- return 2;
-#else
+#if QT_CONFIG(textdate)
mcount = 7;
Q_FALLTHROUGH();
#endif
case MonthSection:
-#if !QT_CONFIG(textdate)
- return 2;
-#else
+#if QT_CONFIG(textdate)
if (count <= 2)
return 2;
@@ -676,7 +686,9 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
}
return ret;
}
-#endif
+#else
+ return 2;
+#endif // textdate
case MSecSection:
return 3;
case YearSection:
@@ -697,6 +709,7 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
case DaySectionMask:
qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
SectionNode::name(s).toLatin1().constData());
+ break;
case NoSectionIndex:
case FirstSectionIndex:
@@ -715,6 +728,36 @@ int QDateTimeParser::sectionMaxSize(int index) const
return sectionMaxSize(sn.type, sn.count);
}
+// Separator matching
+//
+// QTBUG-114909: user may be oblivious to difference between visibly
+// indistinguishable spacing characters. For now we only treat horizontal
+// spacing characters, excluding tab, as equivalent.
+
+static int matchesSeparator(QStringView text, QStringView separator)
+{
+ const auto isSimpleSpace = [](char32_t ch) {
+ // Distinguish tab, CR and the vertical spaces from the rest:
+ return ch == u' ' || (ch > 127 && QChar::isSpace(ch));
+ };
+ // -1 if not a match, else length of prefix of text that does match.
+ // First check for exact match
+ if (!text.startsWith(separator)) {
+ // Failing that, check for space-identifying match:
+ QStringIterator given(text), sep(separator);
+ while (sep.hasNext()) {
+ if (!given.hasNext())
+ return -1;
+ char32_t s = sep.next(), g = given.next();
+ if (s != g && !(isSimpleSpace(s) && isSimpleSpace(g)))
+ return -1;
+ }
+ // One side may have used a surrogate pair space where the other didn't:
+ return given.index();
+ }
+ return separator.size();
+}
+
/*!
\internal
@@ -743,26 +786,24 @@ QString QDateTimeParser::sectionText(int sectionIndex) const
return sectionText(displayText(), sectionIndex, sn.pos);
}
-
-#if QT_CONFIG(datestring)
-
QDateTimeParser::ParsedSection
-QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
- int offset, QString *text) const
+QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex, int offset) const
{
ParsedSection result; // initially Invalid
const SectionNode &sn = sectionNode(sectionIndex);
- if (sn.type & Internal) {
- qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
- qUtf16Printable(sn.name()), sectionIndex);
- return result;
- }
+ Q_ASSERT_X(!(sn.type & Internal),
+ "QDateTimeParser::parseSection", "Internal error");
const int sectionmaxsize = sectionMaxSize(sectionIndex);
- QStringView sectionTextRef = QStringView{*text}.mid(offset, sectionmaxsize);
+ const bool negate = (sn.type == YearSection && m_text.size() > offset
+ && m_text.at(offset) == u'-');
+ const int negativeYearOffset = negate ? 1 : 0;
+
+ QStringView sectionTextRef =
+ QStringView { m_text }.mid(offset + negativeYearOffset, sectionmaxsize);
QDTPDEBUG << "sectionValue for" << sn.name()
- << "with text" << *text << "and (at" << offset
+ << "with text" << m_text << "and (at" << offset
<< ") st:" << sectionTextRef;
switch (sn.type) {
@@ -790,12 +831,12 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
break;
}
if (result.state != Invalid)
- text->replace(offset, used, sectiontext.constData(), used);
+ m_text.replace(offset, used, sectiontext.constData(), used);
break; }
case TimeZoneSection:
result = findTimeZone(sectionTextRef, currentValue,
absoluteMax(sectionIndex),
- absoluteMin(sectionIndex));
+ absoluteMin(sectionIndex), sn.count);
break;
case MonthSection:
case DayOfWeekSectionShort:
@@ -814,7 +855,7 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
result = ParsedSection(Intermediate, num, used);
if (num != -1) {
- text->replace(offset, used, sectiontext.constData(), used);
+ m_text.replace(offset, used, sectiontext.constData(), used);
if (used == sectiontext.size())
result = ParsedSection(Acceptable, num, used);
}
@@ -830,73 +871,96 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
case MinuteSection:
case SecondSection:
case MSecSection: {
- int sectiontextSize = sectionTextRef.size();
- if (sectiontextSize == 0) {
- result = ParsedSection(Intermediate);
- } else {
- for (int i = 0; i < sectiontextSize; ++i) {
- if (sectionTextRef.at(i).isSpace())
- sectiontextSize = i; // which exits the loop
- }
+ const auto checkSeparator = [&result, field=QStringView{m_text}.sliced(offset),
+ negativeYearOffset, sectionIndex, this]() {
+ // No-digit field if next separator is here, otherwise invalid.
+ const auto &sep = separators.at(sectionIndex + 1);
+ if (matchesSeparator(field.sliced(negativeYearOffset), sep) != -1)
+ result = ParsedSection(Intermediate, 0, negativeYearOffset);
+ else if (negativeYearOffset && matchesSeparator(field, sep) != -1)
+ result = ParsedSection(Intermediate, 0, 0);
+ else
+ return false;
+ return true;
+ };
+ int used = negativeYearOffset;
+ // We already sliced off the - sign if it was acceptable.
+ // QLocale::toUInt() would accept a sign, so we must reject it overtly:
+ if (sectionTextRef.startsWith(u'-')
+ || sectionTextRef.startsWith(u'+')) {
+ // However, a sign here may indicate a field with no digits, if it
+ // starts the next separator:
+ checkSeparator();
+ break;
+ }
+ QStringView digitsStr = sectionTextRef.left(digitCount(sectionTextRef));
+ if (digitsStr.isEmpty()) {
+ result = ParsedSection(Intermediate, 0, used);
+ } else {
+ const QLocale loc = locale();
const int absMax = absoluteMax(sectionIndex);
- QLocale loc;
- bool ok = true;
- int last = -1, used = -1;
-
- Q_ASSERT(sectiontextSize <= sectionmaxsize);
- QStringView digitsStr = sectionTextRef.left(sectiontextSize);
- for (int digits = sectiontextSize; digits >= 1; --digits) {
- digitsStr.truncate(digits);
- int tmp = (int)loc.toUInt(digitsStr, &ok);
- if (ok && sn.type == Hour12Section) {
- if (tmp > 12) {
- tmp = -1;
- ok = false;
- } else if (tmp == 12) {
- tmp = 0;
- }
- }
- if (ok && tmp <= absMax) {
- QDTPDEBUG << sectionTextRef.left(digits) << tmp << digits;
- last = tmp;
- used = digits;
- break;
+ const int absMin = absoluteMin(sectionIndex);
+
+ int lastVal = -1;
+
+ for (; digitsStr.size(); digitsStr.chop(1)) {
+ bool ok = false;
+ int value = int(loc.toUInt(digitsStr, &ok));
+ if (!ok || (negate ? -value < absMin : value > absMax))
+ continue;
+
+ if (sn.type == Hour12Section) {
+ if (value > 12)
+ continue;
+ if (value == 12)
+ value = 0;
}
+
+ QDTPDEBUG << digitsStr << value << digitsStr.size();
+ lastVal = value;
+ used += digitsStr.size();
+ break;
}
- if (last == -1) {
- QChar first(sectionTextRef.at(0));
- if (separators.at(sectionIndex + 1).startsWith(first))
- result = ParsedSection(Intermediate, 0, used);
- else
- QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok;
+ if (lastVal == -1) {
+ if (!checkSeparator()) {
+ QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint"
+ << lastVal;
+ }
} else {
+ if (negate)
+ lastVal = -lastVal;
const FieldInfo fi = fieldInfo(sectionIndex);
- const bool unfilled = used < sectionmaxsize;
+ const bool unfilled = used - negativeYearOffset < sectionmaxsize;
if (unfilled && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
for (int i = used; i < sectionmaxsize; ++i)
- last *= 10;
+ lastVal *= 10;
}
// Even those *= 10s can't take last above absMax:
- Q_ASSERT(last <= absMax);
- const int absMin = absoluteMin(sectionIndex);
- if (last < absMin) {
- if (unfilled)
- result = ParsedSection(Intermediate, last, used);
- else
- QDTPDEBUG << "invalid because" << last << "is less than absoluteMin" << absMin;
- } else if (unfilled && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
+ Q_ASSERT(negate ? lastVal >= absMin : lastVal <= absMax);
+ if (negate ? lastVal > absMax : lastVal < absMin) {
+ if (unfilled) {
+ result = ParsedSection(Intermediate, lastVal, used);
+ } else if (negate) {
+ QDTPDEBUG << "invalid because" << lastVal << "is greater than absoluteMax"
+ << absMax;
+ } else {
+ QDTPDEBUG << "invalid because" << lastVal << "is less than absoluteMin"
+ << absMin;
+ }
+
+ } else if (unfilled && (fi & (FixedWidth | Numeric)) == (FixedWidth | Numeric)) {
if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
const int missingZeroes = sectionmaxsize - digitsStr.size();
- result = ParsedSection(Acceptable, last, sectionmaxsize, missingZeroes);
- text->insert(offset, QString(missingZeroes, QLatin1Char('0')));
+ result = ParsedSection(Acceptable, lastVal, sectionmaxsize, missingZeroes);
+ m_text.insert(offset, QString(missingZeroes, u'0'));
++(const_cast<QDateTimeParser*>(this)->sectionNodes[sectionIndex].zeroesAdded);
} else {
- result = ParsedSection(Intermediate, last, used);;
+ result = ParsedSection(Intermediate, lastVal, used);
}
} else {
- result = ParsedSection(Acceptable, last, used);
+ result = ParsedSection(Acceptable, lastVal, used);
}
}
}
@@ -914,21 +978,30 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
/*!
\internal
- Returns a day-number, in the same month as \a rough and as close to \a rough's
- day number as is valid, that \a calendar puts on the day of the week indicated
- by \a weekDay.
+ Returns the day-number of a day, as close as possible to the given \a day, in
+ the specified \a month of \a year for the given \a calendar, that falls on the
+ day of the week indicated by \a weekDay.
*/
-static int weekDayWithinMonth(QCalendar calendar, QDate rough, int weekDay)
+static int weekDayWithinMonth(QCalendar calendar, int year, int month, int day, int weekDay)
{
// TODO: can we adapt this to cope gracefully with intercallary days (day of
// week > 7) without making it slower for more widely-used calendars ?
- int day = rough.day(calendar) + weekDay - calendar.dayOfWeek(rough);
- if (day <= 0)
- return day + 7;
- if (day > rough.daysInMonth(calendar))
- return day - 7;
- return day;
+ const int maxDay = calendar.daysInMonth(month, year); // 0 if no such month
+ day = maxDay > 1 ? qBound(1, day, maxDay) : qMax(1, day);
+ day += dayOfWeekDiff(weekDay, calendar.dayOfWeek(QDate(year, month, day, calendar)));
+ return day <= 0 ? day + 7 : maxDay > 0 && day > maxDay ? day - 7 : day;
+}
+
+/*!
+ \internal
+ Returns whichever of baseYear through baseYear + 99 has its % 100 == y2d.
+*/
+static int yearInCenturyFrom(int y2d, int baseYear)
+{
+ Q_ASSERT(0 <= y2d && y2d < 100);
+ const int year = baseYear - baseYear % 100 + y2d;
+ return year < baseYear ? year + 100 : year;
}
/*!
@@ -939,21 +1012,21 @@ static int weekDayWithinMonth(QCalendar calendar, QDate rough, int weekDay)
when on valid date is consistent with the data.
*/
-static QDate actualDate(QDateTimeParser::Sections known, const QCalendar &calendar,
+static QDate actualDate(QDateTimeParser::Sections known, QCalendar calendar, int baseYear,
int year, int year2digits, int month, int day, int dayofweek)
{
QDate actual(year, month, day, calendar);
if (actual.isValid() && year % 100 == year2digits && calendar.dayOfWeek(actual) == dayofweek)
return actual; // The obvious candidate is fine :-)
- if (dayofweek < 1 || dayofweek > 7) // Invalid: ignore
+ if (dayofweek < 1 || dayofweek > 7) // Intercallary (or invalid): ignore
known &= ~QDateTimeParser::DayOfWeekSectionMask;
// Assuming year > 0 ...
if (year % 100 != year2digits) {
if (known & QDateTimeParser::YearSection2Digits) {
// Over-ride year, even if specified:
- year += year2digits - year % 100;
+ year = yearInCenturyFrom(year2digits, baseYear);
known &= ~QDateTimeParser::YearSection;
} else {
year2digits = year % 100;
@@ -970,16 +1043,21 @@ static QDate actualDate(QDateTimeParser::Sections known, const QCalendar &calend
}
QDate first(year, month, 1, calendar);
- int last = known & QDateTimeParser::YearSection && known & QDateTimeParser::MonthSection
- ? first.daysInMonth(calendar) : 0;
+ int last = known & QDateTimeParser::MonthSection
+ ? (known.testAnyFlag(QDateTimeParser::YearSectionMask)
+ ? calendar.daysInMonth(month, year) : calendar.daysInMonth(month))
+ : 0;
+ // We can only fix DOW if we know year as well as month (hence last):
+ const bool fixDayOfWeek = last && known & QDateTimeParser::YearSection
+ && known & QDateTimeParser::DayOfWeekSectionMask;
// If we also know day-of-week, tweak last to the last in the month that matches it:
- if (last && known & QDateTimeParser::DayOfWeekSectionMask) {
- int diff = (dayofweek - calendar.dayOfWeek(first) - last) % 7;
+ if (fixDayOfWeek) {
+ const int diff = (dayofweek - calendar.dayOfWeek(first) - last) % 7;
Q_ASSERT(diff <= 0); // C++11 specifies (-ve) % (+ve) to be <= 0.
last += diff;
}
if (day < 1) {
- if (known & QDateTimeParser::DayOfWeekSectionMask && last) {
+ if (fixDayOfWeek) {
day = 1 + dayofweek - calendar.dayOfWeek(first);
if (day < 1)
day += 7;
@@ -987,7 +1065,7 @@ static QDate actualDate(QDateTimeParser::Sections known, const QCalendar &calend
day = 1;
}
known &= ~QDateTimeParser::DaySection;
- } else if (day > 31) {
+ } else if (day > calendar.maximumDaysInMonth()) {
day = last;
known &= ~QDateTimeParser::DaySection;
} else if (last && day > last && (known & QDateTimeParser::DaySection) == 0) {
@@ -1014,7 +1092,7 @@ static QDate actualDate(QDateTimeParser::Sections known, const QCalendar &calend
if ((known & QDateTimeParser::DaySection) == 0) {
// Relatively easy to fix.
- day = weekDayWithinMonth(calendar, actual, dayofweek);
+ day = weekDayWithinMonth(calendar, year, month, day, dayofweek);
actual = QDate(year, month, day, calendar);
return actual;
}
@@ -1043,20 +1121,11 @@ static QDate actualDate(QDateTimeParser::Sections known, const QCalendar &calend
if ((known & QDateTimeParser::YearSection) == 0) {
if (known & QDateTimeParser::YearSection2Digits) {
- /*
- Two-digit year and month are specified; choice of century can only
- fix this if diff is in one of {1, 2, 5} or {2, 4, 6}; but not if
- diff is in the other. It's also only reasonable to consider
- adjacent century, e.g. if year thinks it's 2012 and two-digit year
- is '97, it makes sense to consider 1997. If either adjacent
- century does work, the other won't.
- */
- actual = QDate(year + 100, month, day, calendar);
- if (calendar.dayOfWeek(actual) == dayofweek)
- return actual;
- actual = QDate(year - 100, month, day, calendar);
- if (calendar.dayOfWeek(actual) == dayofweek)
+ actual = calendar.matchCenturyToWeekday({year, month, day}, dayofweek);
+ if (actual.isValid()) {
+ Q_ASSERT(calendar.dayOfWeek(actual) == dayofweek);
return actual;
+ }
} else {
// Offset by 7 is usually enough, but rare cases may need more:
for (int y = 1; y < 12; y++) {
@@ -1109,12 +1178,53 @@ static QTime actualTime(QDateTimeParser::Sections known,
return actual;
}
+/*
+ \internal
+*/
+static int startsWithLocalTimeZone(QStringView name, const QDateTime &when, const QLocale &locale)
+{
+ // Pick longest match that we might get.
+ qsizetype longest = 0;
+ // On MS-Win, at least when system zone is UTC, the tzname[]s may be empty.
+ for (int i = 0; i < 2; ++i) {
+ const QString zone(qTzName(i));
+ if (zone.size() > longest && name.startsWith(zone))
+ longest = zone.size();
+ }
+ // Mimic each candidate QLocale::toString() could have used, to ensure round-trips work:
+ const auto consider = [name, &longest](QStringView zone) {
+ if (name.startsWith(zone)) {
+ // UTC-based zone's displayName() only includes seconds if non-zero:
+ if (9 > longest && zone.size() == 6 && zone.startsWith("UTC"_L1)
+ && name.sliced(6, 3) == ":00"_L1) {
+ longest = 9;
+ } else if (zone.size() > longest) {
+ longest = zone.size();
+ }
+ }
+ };
+#if QT_CONFIG(timezone)
+ /* QLocale::toString would skip this if locale == QLocale::system(), but we
+ might not be using the same system locale as whoever generated the text
+ we're parsing. So consider it anyway. */
+ {
+ const auto localWhen = QDateTime(when.date(), when.time());
+ consider(localWhen.timeRepresentation().displayName(
+ localWhen, QTimeZone::ShortName, locale));
+ }
+#else
+ Q_UNUSED(locale);
+#endif
+ consider(QDateTime(when.date(), when.time()).timeZoneAbbreviation());
+ Q_ASSERT(longest <= INT_MAX); // Timezone names are not that long.
+ return int(longest);
+}
+
/*!
\internal
*/
QDateTimeParser::StateNode
-QDateTimeParser::scanString(const QDateTime &defaultValue,
- bool fixup, QString *input) const
+QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const
{
State state = Acceptable;
bool conflicts = false;
@@ -1132,26 +1242,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
int second = defaultTime.second();
int msec = defaultTime.msec();
int dayofweek = calendar.dayOfWeek(defaultDate);
- Qt::TimeSpec tspec = defaultValue.timeSpec();
- int zoneOffset = 0; // In seconds; local - UTC
-#if QT_CONFIG(timezone)
- QTimeZone timeZone;
-#endif
- switch (tspec) {
- case Qt::OffsetFromUTC: // timeZone is ignored
- zoneOffset = defaultValue.offsetFromUtc();
- break;
-#if QT_CONFIG(timezone)
- case Qt::TimeZone:
- timeZone = defaultValue.timeZone();
- if (timeZone.isValid())
- zoneOffset = timeZone.offsetFromUtc(defaultValue);
- // else: is there anything we can do about this ?
- break;
-#endif
- default: // zoneOffset and timeZone are ignored
- break;
- }
+ QTimeZone timeZone = defaultValue.timeRepresentation();
int ampm = -1;
Sections isSet = NoSection;
@@ -1159,39 +1250,35 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
for (int index = 0; index < sectionNodesCount; ++index) {
Q_ASSERT(state != Invalid);
const QString &separator = separators.at(index);
- if (QStringView{*input}.mid(pos, separator.size()) != separator) {
- QDTPDEBUG << "invalid because" << QStringView{*input}.mid(pos, separator.size())
- << "!=" << separator
+ int step = matchesSeparator(QStringView{m_text}.sliced(pos), separator);
+ if (step == -1) {
+ QDTPDEBUG << "invalid because" << QStringView{m_text}.sliced(pos)
+ << "does not start with" << separator
<< index << pos << currentSectionIndex;
return StateNode();
}
- pos += separator.size();
+ pos += step;
sectionNodes[index].pos = pos;
int *current = nullptr;
+ int zoneOffset; // Needed to serve as *current when setting zone
const SectionNode sn = sectionNodes.at(index);
- ParsedSection sect;
-
- {
- const QDate date = actualDate(isSet, calendar, year, year2digits,
- month, day, dayofweek);
+ const QDateTime usedDateTime = [&] {
+ const QDate date = actualDate(isSet, calendar, defaultCenturyStart,
+ year, year2digits, month, day, dayofweek);
const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec);
- sect = parseSection(
-#if QT_CONFIG(timezone)
- tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) :
-#endif
- QDateTime(date, time, tspec, zoneOffset),
- index, pos, input);
- }
+ return QDateTime(date, time, timeZone);
+ }();
+ ParsedSection sect = parseSection(usedDateTime, index, pos);
- QDTPDEBUG << "sectionValue" << sn.name() << *input
+ QDTPDEBUG << "sectionValue" << sn.name() << m_text
<< "pos" << pos << "used" << sect.used << stateName(sect.state);
padding += sect.zeroes;
if (fixup && sect.state == Intermediate && sect.used < sn.count) {
const FieldInfo fi = fieldInfo(index);
if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
- const QString newText = QString::fromLatin1("%1").arg(sect.value, sn.count, 10, QLatin1Char('0'));
- input->replace(pos, sect.used, newText);
+ const QString newText = QString::asprintf("%0*d", sn.count, sect.value);
+ m_text.replace(pos, sect.used, newText);
sect.used = sn.count;
}
}
@@ -1206,27 +1293,24 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
current = &zoneOffset;
if (sect.used > 0) {
// Synchronize with what findTimeZone() found:
- QStringView zoneName = QStringView{*input}.mid(pos, sect.used);
+ QStringView zoneName = QStringView{m_text}.sliced(pos, sect.used);
Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0
- const QStringView offsetStr = zoneName.startsWith(QLatin1String("UTC"))
- ? zoneName.mid(3) : zoneName;
- const bool isUtcOffset = offsetStr.startsWith(QLatin1Char('+'))
- || offsetStr.startsWith(QLatin1Char('-'));
- const bool isUtc = zoneName == QLatin1String("Z")
- || zoneName == QLatin1String("UTC");
+ const QStringView offsetStr
+ = zoneName.startsWith("UTC"_L1) ? zoneName.sliced(3) : zoneName;
+ const bool isUtcOffset = offsetStr.startsWith(u'+') || offsetStr.startsWith(u'-');
+ const bool isUtc = zoneName == "Z"_L1 || zoneName == "UTC"_L1;
if (isUtc || isUtcOffset) {
- tspec = sect.value ? Qt::OffsetFromUTC : Qt::UTC;
- } else {
+ timeZone = QTimeZone::fromSecondsAheadOfUtc(sect.value);
#if QT_CONFIG(timezone)
- timeZone = QTimeZone(zoneName.toLatin1());
- tspec = timeZone.isValid()
- ? Qt::TimeZone
- : (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime);
-#else
- tspec = Qt::LocalTime;
+ } else if (startsWithLocalTimeZone(zoneName, usedDateTime, locale()) != sect.used) {
+ QTimeZone namedZone = QTimeZone(zoneName.toLatin1());
+ Q_ASSERT(namedZone.isValid());
+ timeZone = namedZone;
#endif
+ } else {
+ timeZone = QTimeZone::LocalTime;
}
}
break;
@@ -1245,71 +1329,69 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
default:
qWarning("QDateTimeParser::parse Internal error (%ls)",
qUtf16Printable(sn.name()));
- break;
+ return StateNode();
}
+ Q_ASSERT(current);
+ Q_ASSERT(sect.state != Invalid);
if (sect.used > 0)
pos += sect.used;
QDTPDEBUG << index << sn.name() << "is set to"
<< pos << "state is" << stateName(state);
- if (!current) {
- qWarning("QDateTimeParser::parse Internal error 2");
- return StateNode();
- }
if (isSet & sn.type && *current != sect.value) {
QDTPDEBUG << "CONFLICT " << sn.name() << *current << sect.value;
conflicts = true;
- if (index != currentSectionIndex || sect.state == Invalid) {
+ if (index != currentSectionIndex)
continue;
- }
}
- if (sect.state != Invalid)
- *current = sect.value;
+ *current = sect.value;
// Record the present section:
isSet |= sn.type;
}
- if (QStringView{*input}.mid(pos) != separators.last()) {
- QDTPDEBUG << "invalid because" << QStringView{*input}.mid(pos)
- << "!=" << separators.last() << pos;
+ int step = matchesSeparator(QStringView{m_text}.sliced(pos), separators.last());
+ if (step == -1 || step + pos < m_text.size()) {
+ QDTPDEBUG << "invalid because" << QStringView{m_text}.sliced(pos)
+ << "does not match" << separators.last() << pos;
return StateNode();
}
if (parserType != QMetaType::QTime) {
if (year % 100 != year2digits && (isSet & YearSection2Digits)) {
+ const QDate date = actualDate(isSet, calendar, defaultCenturyStart,
+ year, year2digits, month, day, dayofweek);
if (!(isSet & YearSection)) {
- year = (year / 100) * 100;
- year += year2digits;
+ year = date.year();
} else {
conflicts = true;
const SectionNode &sn = sectionNode(currentSectionIndex);
- if (sn.type == YearSection2Digits) {
- year = (year / 100) * 100;
- year += year2digits;
- }
+ if (sn.type == YearSection2Digits)
+ year = date.year();
}
}
+ const auto fieldType = sectionType(currentSectionIndex);
const QDate date(year, month, day, calendar);
- if (dayofweek != calendar.dayOfWeek(date)
+ if ((!date.isValid() || dayofweek != calendar.dayOfWeek(date))
&& state == Acceptable && isSet & DayOfWeekSectionMask) {
if (isSet & DaySection)
conflicts = true;
- const SectionNode &sn = sectionNode(currentSectionIndex);
- if (sn.type & DayOfWeekSectionMask || currentSectionIndex == -1) {
- // dayofweek should be preferred
- day = weekDayWithinMonth(calendar, date, dayofweek);
+ // Change to day of week should adjust day of month;
+ // when day of month isn't set, so should change to year or month.
+ if (currentSectionIndex == -1 || fieldType & DayOfWeekSectionMask
+ || (!conflicts && (fieldType & (YearSectionMask | MonthSection)))) {
+ day = weekDayWithinMonth(calendar, year, month, day, dayofweek);
QDTPDEBUG << year << month << day << dayofweek
<< calendar.dayOfWeek(QDate(year, month, day, calendar));
}
}
bool needfixday = false;
- if (sectionType(currentSectionIndex) & DaySectionMask) {
+ if (fieldType & DaySectionMask) {
cachedDay = day;
- } else if (cachedDay > day) {
+ } else if (cachedDay > day && !(isSet & DayOfWeekSectionMask && state == Acceptable)) {
day = cachedDay;
needfixday = true;
}
@@ -1321,9 +1403,8 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
needfixday = true;
}
if (needfixday) {
- if (context == FromString) {
+ if (context == FromString)
return StateNode();
- }
if (state == Acceptable && fixday) {
day = qMin<int>(day, calendar.daysInMonth(month, year));
@@ -1331,14 +1412,14 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
for (int i=0; i<sectionNodesCount; ++i) {
const SectionNode sn = sectionNode(i);
if (sn.type & DaySection) {
- input->replace(sectionPos(sn), sectionSize(i), loc.toString(day));
+ m_text.replace(sectionPos(sn), sectionSize(i), loc.toString(day));
} else if (sn.type & DayOfWeekSectionMask) {
const int dayOfWeek = calendar.dayOfWeek(QDate(year, month, day, calendar));
const QLocale::FormatType dayFormat =
(sn.type == DayOfWeekSectionShort
? QLocale::ShortFormat : QLocale::LongFormat);
const QString dayName(loc.dayName(dayOfWeek, dayFormat));
- input->replace(sectionPos(sn), sectionSize(i), dayName);
+ m_text.replace(sectionPos(sn), sectionSize(i), dayName);
}
}
} else if (state > Intermediate) {
@@ -1349,26 +1430,19 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
if (parserType != QMetaType::QDate) {
if (isSet & Hour12Section) {
- const bool hasHour = isSet & Hour24Section;
- if (ampm == -1) {
- if (hasHour) {
- ampm = (hour < 12 ? 0 : 1);
- } else {
- ampm = 0; // no way to tell if this is am or pm so I assume am
- }
- }
- hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
- if (!hasHour) {
+ const bool hasHour = isSet.testAnyFlag(Hour24Section);
+ if (ampm == -1) // If we don't know from hour, assume am:
+ ampm = !hasHour || hour < 12 ? 0 : 1;
+ hour12 = hour12 % 12 + ampm * 12;
+ if (!hasHour)
hour = hour12;
- } else if (hour != hour12) {
+ else if (hour != hour12)
conflicts = true;
- }
} else if (ampm != -1) {
- if (!(isSet & (Hour24Section))) {
- hour = (12 * ampm); // special case. Only ap section
- } else if ((ampm == 0) != (hour < 12)) {
+ if (!(isSet & (Hour24Section)))
+ hour = 12 * ampm; // Special case: only ap section
+ else if ((ampm == 0) != (hour < 12))
conflicts = true;
- }
}
}
@@ -1377,29 +1451,42 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
const QDate date(year, month, day, calendar);
const QTime time(hour, minute, second, msec);
- const QDateTime when =
-#if QT_CONFIG(timezone)
- tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) :
-#endif
- QDateTime(date, time, tspec, zoneOffset);
-
- // If hour wasn't specified, check the default we're using exists on the
- // given date (which might be a spring-forward, skipping an hour).
- if (parserType == QMetaType::QDateTime && !(isSet & HourSectionMask) && !when.isValid()) {
- qint64 msecs = when.toMSecsSinceEpoch();
- // Fortunately, that gets a useful answer, even though when is invalid ...
- const QDateTime replace =
-#if QT_CONFIG(timezone)
- tspec == Qt::TimeZone
- ? QDateTime::fromMSecsSinceEpoch(msecs, timeZone) :
-#endif
- QDateTime::fromMSecsSinceEpoch(msecs, tspec, zoneOffset);
- const QTime tick = replace.time();
- if (replace.date() == date
- && (!(isSet & MinuteSection) || tick.minute() == minute)
- && (!(isSet & SecondSection) || tick.second() == second)
- && (!(isSet & MSecSection) || tick.msec() == msec)) {
- return StateNode(replace, state, padding, conflicts);
+ const QDateTime when = QDateTime(date, time, timeZone);
+
+ if (when.time() != time || when.date() != date) {
+ // In a spring-forward, if we hit the skipped hour, we may have been
+ // shunted out of it.
+
+ // If hour wasn't specified, so we're using our default, changing it may
+ // fix that.
+ if (!(isSet & HourSectionMask)) {
+ switch (parserType) {
+ case QMetaType::QDateTime: {
+ qint64 msecs = when.toMSecsSinceEpoch();
+ // Fortunately, that gets a useful answer, even though when is invalid ...
+ const QDateTime replace = QDateTime::fromMSecsSinceEpoch(msecs, timeZone);
+ const QTime tick = replace.time();
+ if (replace.date() == date
+ && (!(isSet & MinuteSection) || tick.minute() == minute)
+ && (!(isSet & SecondSection) || tick.second() == second)
+ && (!(isSet & MSecSection) || tick.msec() == msec)) {
+ return StateNode(replace, state, padding, conflicts);
+ }
+ } break;
+ case QMetaType::QDate:
+ // Don't care about time, so just use start of day (and ignore spec):
+ return StateNode(date.startOfDay(QTimeZone::UTC),
+ state, padding, conflicts);
+ break;
+ case QMetaType::QTime:
+ // Don't care about date or representation, so pick a safe representation:
+ return StateNode(QDateTime(date, time, QTimeZone::UTC),
+ state, padding, conflicts);
+ default:
+ Q_UNREACHABLE_RETURN(StateNode());
+ }
+ } else if (state > Intermediate) {
+ state = Intermediate;
}
}
@@ -1411,15 +1498,17 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
*/
QDateTimeParser::StateNode
-QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const
+QDateTimeParser::parse(const QString &input, int position,
+ const QDateTime &defaultValue, bool fixup) const
{
const QDateTime minimum = getMinimum();
const QDateTime maximum = getMaximum();
+ m_text = input;
QDTPDEBUG << "parse" << input;
- StateNode scan = scanString(defaultValue, fixup, &input);
- QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
- scan.value.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
+ StateNode scan = scanString(defaultValue, fixup);
+ QDTPDEBUGN("'%s' => '%s'(%s)", m_text.toLatin1().constData(),
+ scan.value.toString("yyyy/MM/dd hh:mm:ss.zzz"_L1).toLatin1().constData(),
stateName(scan.state).toLatin1().constData());
if (scan.value.isValid() && scan.state != Invalid) {
@@ -1434,9 +1523,9 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
const int sectionNodesCount = sectionNodes.size();
for (int i=0; i<sectionNodesCount && !done; ++i) {
const SectionNode &sn = sectionNodes.at(i);
- QString t = sectionText(input, i, sn.pos).toLower();
+ QString t = sectionText(m_text, i, sn.pos).toLower();
if ((t.size() < sectionMaxSize(i)
- && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
+ && ((fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
|| t.contains(space)) {
switch (sn.type) {
case AmPmSection:
@@ -1484,9 +1573,9 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
int toMax;
if (sn.type & TimeSectionMask) {
- if (scan.value.daysTo(minimum) != 0) {
+ if (scan.value.daysTo(minimum) != 0)
break;
- }
+
const QTime time = scan.value.time();
toMin = time.msecsTo(minimum.time());
if (scan.value.daysTo(maximum) > 0)
@@ -1540,22 +1629,16 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
Q_ASSERT(maximum.date().toJulianDay() == 5373484);
if (scan.value.date().toJulianDay() > 5373484)
scan.state = Invalid;
- } else {
- if (scan.value > maximum)
- scan.state = Invalid;
+ } else if (scan.value > maximum) {
+ scan.state = Invalid;
}
QDTPDEBUG << "not checking intermediate because scanned value is" << scan.value << minimum << maximum;
}
}
- text = scan.input = input;
- /*
- We might have ended up with an invalid datetime: the non-existent hour
- during dst changes, for instance.
- */
- if (!scan.value.isValid() && scan.state == Acceptable)
- scan.state = Intermediate;
+ // An invalid time should only arise if we set the state to less than acceptable:
+ Q_ASSERT(scan.value.isValid() || scan.state != Acceptable);
return scan;
}
@@ -1571,7 +1654,7 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
length of overlap in *used (if \a used is non-NULL) and the first entry that
overlapped this much in *usedText (if \a usedText is non-NULL).
*/
-static int findTextEntry(const QString &text, const ShortVector<QString> &entries, QString *usedText, int *used)
+static int findTextEntry(QStringView text, const ShortVector<QString> &entries, QString *usedText, int *used)
{
if (text.isEmpty())
return -1;
@@ -1608,7 +1691,7 @@ static int findTextEntry(const QString &text, const ShortVector<QString> &entrie
match. Starting from \a index; str should already by lowered
*/
-int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
+int QDateTimeParser::findMonth(QStringView str, int startMonth, int sectionIndex,
int year, QString *usedMonth, int *used) const
{
const SectionNode &sn = sectionNode(sectionIndex);
@@ -1624,11 +1707,11 @@ int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionI
for (int month = startMonth; month <= 12; ++month)
monthNames.append(calendar.monthName(l, month, year, type));
- const int index = findTextEntry(str1, monthNames, usedMonth, used);
+ const int index = findTextEntry(str, monthNames, usedMonth, used);
return index < 0 ? index : index + startMonth;
}
-int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
+int QDateTimeParser::findDay(QStringView str, int startDay, int sectionIndex, QString *usedDay, int *used) const
{
const SectionNode &sn = sectionNode(sectionIndex);
if (!(sn.type & DaySectionMask)) {
@@ -1643,7 +1726,7 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex
for (int day = startDay; day <= 7; ++day)
daysOfWeek.append(l.dayName(day, type));
- const int index = findTextEntry(str1, daysOfWeek, usedDay, used);
+ const int index = findTextEntry(str, daysOfWeek, usedDay, used);
return index < 0 ? index : index + startDay;
}
@@ -1652,21 +1735,29 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex
Return's .value is UTC offset in seconds.
The caller must verify that the offset is within a valid range.
+ The mode is 1 for permissive parsing, 2 and 3 for strict offset-only format
+ (no UTC prefix) with no colon for 2 and a colon for 3.
*/
-QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringView str) const
+QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringView str, int mode) const
{
- const bool startsWithUtc = str.startsWith(QLatin1String("UTC"));
- // Get rid of UTC prefix if it exists
- if (startsWithUtc)
- str = str.mid(3);
+ Q_ASSERT(mode > 0 && mode < 4);
+ const bool startsWithUtc = str.startsWith("UTC"_L1);
+ // Deal with UTC prefix if present:
+ if (startsWithUtc) {
+ if (mode != 1)
+ return ParsedSection();
+ str = str.sliced(3);
+ if (str.isEmpty())
+ return ParsedSection(Acceptable, 0, 3);
+ }
- const bool negativeSign = str.startsWith(QLatin1Char('-'));
+ const bool negativeSign = str.startsWith(u'-');
// Must start with a sign:
- if (!negativeSign && !str.startsWith(QLatin1Char('+')))
+ if (!negativeSign && !str.startsWith(u'+'))
return ParsedSection();
- str = str.mid(1); // drop sign
+ str = str.sliced(1); // drop sign
- const int colonPosition = str.indexOf(QLatin1Char(':'));
+ const int colonPosition = str.indexOf(u':');
// Colon that belongs to offset is at most at position 2 (hh:mm)
bool hasColon = (colonPosition >= 0 && colonPosition < 3);
@@ -1688,10 +1779,12 @@ QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringView str) c
i = hoursLength;
hasColon = false;
}
+ if (mode == (hasColon ? 2 : 3))
+ return ParsedSection();
str.truncate(i); // The rest of the string is not part of the UTC offset
bool isInt = false;
- const int hours = str.mid(0, hoursLength).toInt(&isInt);
+ const int hours = str.first(hoursLength).toInt(&isInt);
if (!isInt)
return ParsedSection();
const QStringView minutesStr = str.mid(hasColon ? colonPosition + 1 : 2, 2);
@@ -1726,17 +1819,35 @@ QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringView str) c
QDateTimeParser::ParsedSection
QDateTimeParser::findTimeZoneName(QStringView str, const QDateTime &when) const
{
- const int systemLength = startsWithLocalTimeZone(str);
+ const int systemLength = startsWithLocalTimeZone(str, when, locale());
#if QT_CONFIG(timezone)
// Collect up plausibly-valid characters; let QTimeZone work out what's
// truly valid.
const auto invalidZoneNameCharacter = [] (const QChar &c) {
- return c.unicode() >= 127u
- || (!c.isLetterOrNumber() && !QLatin1String("+-./:_").contains(c));
+ const auto cu = c.unicode();
+ return cu >= 127u || !(memchr("+-./:_", char(cu), 6) || c.isLetterOrNumber());
};
int index = std::distance(str.cbegin(),
std::find_if(str.cbegin(), str.cend(), invalidZoneNameCharacter));
+ // Limit name fragments (between slashes) to 20 characters.
+ // (Valid time-zone IDs are allowed up to 14 and Android has quirks up to 17.)
+ // Limit number of fragments to six; no known zone name has more than four.
+ int lastSlash = -1;
+ int count = 0;
+ Q_ASSERT(index <= str.size());
+ while (lastSlash < index) {
+ int slash = str.indexOf(u'/', lastSlash + 1);
+ if (slash < 0 || slash > index)
+ slash = index; // i.e. the end of the candidate text
+ else if (++count > 5)
+ index = slash; // Truncate
+ if (slash - lastSlash > 20)
+ index = lastSlash + 20; // Truncate
+ // If any of those conditions was met, index <= slash, so this exits the loop:
+ lastSlash = slash;
+ }
+
for (; index > systemLength; --index) { // Find longest match
str.truncate(index);
QTimeZone zone(str.toLatin1());
@@ -1754,13 +1865,26 @@ QDateTimeParser::findTimeZoneName(QStringView str, const QDateTime &when) const
Return's .value is zone's offset, zone time - UTC time, in seconds.
See QTimeZonePrivate::isValidId() for the format of zone names.
- */
+
+ The mode is the number of 't' characters in the field specifier:
+ * 1: any recognized format
+ * 2: only the simple offset format, without colon
+ * 3: only the simple offset format, with colon
+ * 4: only a zone name
+*/
QDateTimeParser::ParsedSection
QDateTimeParser::findTimeZone(QStringView str, const QDateTime &when,
- int maxVal, int minVal) const
+ int maxVal, int minVal, int mode) const
{
- ParsedSection section = findUtcOffset(str);
- if (section.used <= 0) // if nothing used, try time zone parsing
+ Q_ASSERT(mode > 0 && mode <= 4);
+ // Short-cut Zulu suffix when it's all there is (rather than a prefix match):
+ if (mode == 1 && str == u'Z')
+ return ParsedSection(Acceptable, 0, 1);
+
+ ParsedSection section;
+ if (mode != 4)
+ section = findUtcOffset(str, mode);
+ if (mode != 2 && mode != 3 && section.used <= 0) // if nothing used, try time zone parsing
section = findTimeZoneName(str, when);
// It can be a well formed time zone specifier, but with value out of range
if (section.state == Acceptable && (section.value < minVal || section.value > maxVal))
@@ -1768,11 +1892,13 @@ QDateTimeParser::findTimeZone(QStringView str, const QDateTime &when,
if (section.used > 0)
return section;
- // Check if string is UTC or alias to UTC, after all other options
- if (str.startsWith(QLatin1String("UTC")))
- return ParsedSection(Acceptable, 0, 3);
- if (str.startsWith(QLatin1Char('Z')))
- return ParsedSection(Acceptable, 0, 1);
+ if (mode == 1) {
+ // Check if string is UTC or alias to UTC, after all other options
+ if (str.startsWith("UTC"_L1))
+ return ParsedSection(Acceptable, 0, 3);
+ if (str.startsWith(u'Z'))
+ return ParsedSection(Acceptable, 0, 1);
+ }
return ParsedSection();
}
@@ -1800,9 +1926,9 @@ QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionI
}
if (used)
*used = str.size();
- if (QStringView(str).trimmed().isEmpty()) {
+ if (QStringView(str).trimmed().isEmpty())
return PossibleBoth;
- }
+
const QLatin1Char space(' ');
int size = sectionMaxSize(sectionIndex);
@@ -1811,9 +1937,9 @@ QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionI
pmindex = 1
};
QString ampm[2];
- ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
- ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
- for (int i=0; i<2; ++i)
+ ampm[amindex] = getAmPmText(AmText, Case(s.count));
+ ampm[pmindex] = getAmPmText(PmText, Case(s.count));
+ for (int i = 0; i < 2; ++i)
ampm[i].truncate(size);
QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
@@ -1831,20 +1957,21 @@ QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionI
bool broken[2] = {false, false};
for (int i=0; i<size; ++i) {
- if (str.at(i) != space) {
+ const QChar ch = str.at(i);
+ if (ch != space) {
for (int j=0; j<2; ++j) {
if (!broken[j]) {
- int index = ampm[j].indexOf(str.at(i));
- QDTPDEBUG << "looking for" << str.at(i)
+ int index = ampm[j].indexOf(ch);
+ QDTPDEBUG << "looking for" << ch
<< "in" << ampm[j] << "and got" << index;
if (index == -1) {
- if (str.at(i).category() == QChar::Letter_Uppercase) {
- index = ampm[j].indexOf(str.at(i).toLower());
- QDTPDEBUG << "trying with" << str.at(i).toLower()
+ if (ch.category() == QChar::Letter_Uppercase) {
+ index = ampm[j].indexOf(ch.toLower());
+ QDTPDEBUG << "trying with" << ch.toLower()
<< "in" << ampm[j] << "and got" << index;
- } else if (str.at(i).category() == QChar::Letter_Lowercase) {
- index = ampm[j].indexOf(str.at(i).toUpper());
- QDTPDEBUG << "trying with" << str.at(i).toUpper()
+ } else if (ch.category() == QChar::Letter_Lowercase) {
+ index = ampm[j].indexOf(ch.toUpper());
+ QDTPDEBUG << "trying with" << ch.toUpper()
<< "in" << ampm[j] << "and got" << index;
}
if (index == -1) {
@@ -1867,7 +1994,6 @@ QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionI
return PossibleBoth;
return (!broken[amindex] ? PossibleAM : PossiblePM);
}
-#endif // datestring
/*!
\internal
@@ -1935,7 +2061,12 @@ QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
ret |= FixedWidth;
break;
case AmPmSection:
- ret |= FixedWidth;
+ // Some locales have different length AM and PM texts.
+ if (getAmPmText(AmText, Case(sn.count)).size()
+ == getAmPmText(PmText, Case(sn.count)).size()) {
+ // Only relevant to DateTimeEdit's fixups in parse().
+ ret |= FixedWidth;
+ }
break;
case TimeZoneSection:
break;
@@ -1951,18 +2082,18 @@ QString QDateTimeParser::SectionNode::format() const
{
QChar fillChar;
switch (type) {
- case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
- case MSecSection: fillChar = QLatin1Char('z'); break;
- case SecondSection: fillChar = QLatin1Char('s'); break;
- case MinuteSection: fillChar = QLatin1Char('m'); break;
- case Hour24Section: fillChar = QLatin1Char('H'); break;
- case Hour12Section: fillChar = QLatin1Char('h'); break;
+ case AmPmSection: return count == 1 ? "ap"_L1 : count == 2 ? "AP"_L1 : "Ap"_L1;
+ case MSecSection: fillChar = u'z'; break;
+ case SecondSection: fillChar = u's'; break;
+ case MinuteSection: fillChar = u'm'; break;
+ case Hour24Section: fillChar = u'H'; break;
+ case Hour12Section: fillChar = u'h'; break;
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
- case DaySection: fillChar = QLatin1Char('d'); break;
- case MonthSection: fillChar = QLatin1Char('M'); break;
+ case DaySection: fillChar = u'd'; break;
+ case MonthSection: fillChar = u'M'; break;
case YearSection2Digits:
- case YearSection: fillChar = QLatin1Char('y'); break;
+ case YearSection: fillChar = u'y'; break;
default:
qWarning("QDateTimeParser::sectionFormat Internal error (%ls)",
qUtf16Printable(name(type)));
@@ -1986,9 +2117,9 @@ QString QDateTimeParser::SectionNode::format() const
bool QDateTimeParser::potentialValue(QStringView str, int min, int max, int index,
const QDateTime &currentValue, int insert) const
{
- if (str.isEmpty()) {
+ if (str.isEmpty())
return true;
- }
+
const int size = sectionMaxSize(index);
int val = (int)locale().toUInt(str);
const SectionNode &sn = sectionNode(index);
@@ -1996,13 +2127,10 @@ bool QDateTimeParser::potentialValue(QStringView str, int min, int max, int inde
const int year = currentValue.date().year(calendar);
val += year - (year % 100);
}
- if (val >= min && val <= max && str.size() == size) {
+ if (val >= min && val <= max && str.size() == size)
return true;
- } else if (val > max) {
+ if (val > max || (str.size() == size && val < min))
return false;
- } else if (str.size() == size && val < min) {
- return false;
- }
const int len = size - str.size();
for (int i=0; i<len; ++i) {
@@ -2063,23 +2191,23 @@ bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, QSt
QString QDateTimeParser::SectionNode::name(QDateTimeParser::Section s)
{
switch (s) {
- case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
- case QDateTimeParser::DaySection: return QLatin1String("DaySection");
- case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort");
- case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong");
- case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
- case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
- case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
- case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
- case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
- case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
- case QDateTimeParser::TimeZoneSection: return QLatin1String("TimeZoneSection");
- case QDateTimeParser::YearSection: return QLatin1String("YearSection");
- case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
- case QDateTimeParser::NoSection: return QLatin1String("NoSection");
- case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
- case QDateTimeParser::LastSection: return QLatin1String("LastSection");
- default: return QLatin1String("Unknown section ") + QString::number(int(s));
+ case AmPmSection: return "AmPmSection"_L1;
+ case DaySection: return "DaySection"_L1;
+ case DayOfWeekSectionShort: return "DayOfWeekSectionShort"_L1;
+ case DayOfWeekSectionLong: return "DayOfWeekSectionLong"_L1;
+ case Hour24Section: return "Hour24Section"_L1;
+ case Hour12Section: return "Hour12Section"_L1;
+ case MSecSection: return "MSecSection"_L1;
+ case MinuteSection: return "MinuteSection"_L1;
+ case MonthSection: return "MonthSection"_L1;
+ case SecondSection: return "SecondSection"_L1;
+ case TimeZoneSection: return "TimeZoneSection"_L1;
+ case YearSection: return "YearSection"_L1;
+ case YearSection2Digits: return "YearSection2Digits"_L1;
+ case NoSection: return "NoSection"_L1;
+ case FirstSection: return "FirstSection"_L1;
+ case LastSection: return "LastSection"_L1;
+ default: return "Unknown section "_L1 + QString::number(int(s));
}
}
@@ -2091,53 +2219,63 @@ QString QDateTimeParser::SectionNode::name(QDateTimeParser::Section s)
QString QDateTimeParser::stateName(State s) const
{
switch (s) {
- case Invalid: return QLatin1String("Invalid");
- case Intermediate: return QLatin1String("Intermediate");
- case Acceptable: return QLatin1String("Acceptable");
- default: return QLatin1String("Unknown state ") + QString::number(s);
+ case Invalid: return "Invalid"_L1;
+ case Intermediate: return "Intermediate"_L1;
+ case Acceptable: return "Acceptable"_L1;
+ default: return "Unknown state "_L1 + QString::number(s);
}
}
-#if QT_CONFIG(datestring)
-bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
+
+/*!
+ \internal
+ Compute a defaultValue to pass to parse().
+*/
+QDateTime QDateTimeParser::baseDate(const QTimeZone &zone) const
+{
+ QDateTime when = QDate(defaultCenturyStart, 1, 1).startOfDay(zone);
+ if (const QDateTime start = getMinimum(); when < start)
+ return start;
+ if (const QDateTime end = getMaximum(); when > end)
+ return end;
+ return when;
+}
+
+// Only called when we want only one of date or time; use UTC to avoid bogus DST issues.
+bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time, int baseYear) const
{
- QDateTime datetime;
- if (!fromString(t, &datetime))
+ defaultCenturyStart = baseYear;
+ const StateNode tmp = parse(t, -1, baseDate(QTimeZone::UTC), false);
+ if (tmp.state != Acceptable || tmp.conflicts)
return false;
if (time) {
- const QTime t = datetime.time();
- if (!t.isValid()) {
+ Q_ASSERT(!date);
+ const QTime t = tmp.value.time();
+ if (!t.isValid())
return false;
- }
*time = t;
}
if (date) {
- const QDate d = datetime.date();
- if (!d.isValid()) {
+ Q_ASSERT(!time);
+ const QDate d = tmp.value.date();
+ if (!d.isValid())
return false;
- }
*date = d;
}
return true;
}
-bool QDateTimeParser::fromString(const QString &t, QDateTime* datetime) const
+// Only called when we want both date and time; default to local time.
+bool QDateTimeParser::fromString(const QString &t, QDateTime *datetime, int baseYear) const
{
- QDateTime val(QDate(1900, 1, 1).startOfDay());
- const StateNode tmp = parse(t, -1, val, false);
- if (tmp.state != Acceptable || tmp.conflicts)
- return false;
- if (datetime) {
- if (!tmp.value.isValid())
- return false;
+ defaultCenturyStart = baseYear;
+ const StateNode tmp = parse(t, -1, baseDate(QTimeZone::LocalTime), false);
+ if (datetime)
*datetime = tmp.value;
- }
-
- return true;
+ return tmp.state >= Intermediate && !tmp.conflicts && tmp.value.isValid();
}
-#endif // datestring
QDateTime QDateTimeParser::getMinimum() const
{
@@ -2146,7 +2284,7 @@ QDateTime QDateTimeParser::getMinimum() const
// method. At the time of writing, this is done by QDateTimeEditPrivate.
// Cache the only case
- static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay(Qt::LocalTime));
+ static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay());
return localTimeMin;
}
@@ -2157,7 +2295,7 @@ QDateTime QDateTimeParser::getMaximum() const
// method. At the time of writing, this is done by QDateTimeEditPrivate.
// Cache the only case
- static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay(Qt::LocalTime));
+ static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay());
return localTimeMax;
}
@@ -2165,16 +2303,20 @@ QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
{
const QLocale loc = locale();
QString raw = ap == AmText ? loc.amText() : loc.pmText();
- return cs == UpperCase ? raw.toUpper() : raw.toLower();
+ switch (cs)
+ {
+ case UpperCase: return std::move(raw).toUpper();
+ case LowerCase: return std::move(raw).toLower();
+ case NativeCase: return raw;
+ }
+ Q_UNREACHABLE_RETURN(raw);
}
/*
\internal
-
- I give arg2 preference because arg1 is always a QDateTime.
*/
-bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
+bool operator==(QDateTimeParser::SectionNode s1, QDateTimeParser::SectionNode s2)
{
return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
}
@@ -2183,7 +2325,7 @@ bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::S
Sets \a cal as the calendar to use. The default is Gregorian.
*/
-void QDateTimeParser::setCalendar(const QCalendar &cal)
+void QDateTimeParser::setCalendar(QCalendar cal)
{
calendar = cal;
}
diff --git a/src/corelib/time/qdatetimeparser_p.h b/src/corelib/time/qdatetimeparser_p.h
index 43fe4f261e..30e9e4d524 100644
--- a/src/corelib/time/qdatetimeparser_p.h
+++ b/src/corelib/time/qdatetimeparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATETIMEPARSER_P_H
#define QDATETIMEPARSER_P_H
@@ -82,9 +46,8 @@ public:
FromString,
DateTimeEdit
};
- QDateTimeParser(QMetaType::Type t, Context ctx, const QCalendar &cal = QCalendar())
- : currentSectionIndex(-1), cachedDay(-1), parserType(t),
- fixday(false), context(ctx), calendar(cal)
+ QDateTimeParser(QMetaType::Type t, Context ctx, QCalendar cal = QCalendar())
+ : parserType(t), context(ctx), calendar(cal)
{
defaultLocale = QLocale::system();
first.type = FirstSection;
@@ -141,7 +104,7 @@ public:
struct Q_CORE_EXPORT SectionNode {
Section type;
mutable int pos;
- int count;
+ int count; // (used as Case(count) indicator for AmPmSection)
int zeroesAdded;
static QString name(Section s);
@@ -160,7 +123,6 @@ public:
StateNode() : state(Invalid), padded(0), conflicts(false) {}
StateNode(const QDateTime &val, State ok=Acceptable, int pad=0, bool bad=false)
: value(val), state(ok), padded(pad), conflicts(bad) {}
- QString input;
QDateTime value;
State state;
int padded;
@@ -172,17 +134,12 @@ public:
PmText
};
- enum Case {
- UpperCase,
- LowerCase
- };
-
-#if QT_CONFIG(datestring)
- StateNode parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const;
- bool fromString(const QString &text, QDate *date, QTime *time) const;
- bool fromString(const QString &text, QDateTime* datetime) const;
-#endif
- bool parseFormat(const QString &format);
+ StateNode parse(const QString &input, int position,
+ const QDateTime &defaultValue, bool fixup) const;
+ bool fromString(const QString &text, QDate *date, QTime *time,
+ int baseYear = QLocale::DefaultTwoDigitBaseYear) const;
+ bool fromString(const QString &text, QDateTime *datetime, int baseYear) const;
+ bool parseFormat(QStringView format);
enum FieldInfoFlag {
Numeric = 0x01,
@@ -195,37 +152,32 @@ public:
FieldInfo fieldInfo(int index) const;
void setDefaultLocale(const QLocale &loc) { defaultLocale = loc; }
- virtual QString displayText() const { return text; }
- void setCalendar(const QCalendar &calendar);
+ virtual QString displayText() const { return m_text; }
+ void setCalendar(QCalendar calendar);
private:
int sectionMaxSize(Section s, int count) const;
QString sectionText(const QString &text, int sectionIndex, int index) const;
-#if QT_CONFIG(datestring)
- StateNode scanString(const QDateTime &defaultValue,
- bool fixup, QString *input) const;
+ StateNode scanString(const QDateTime &defaultValue, bool fixup) const;
struct ParsedSection {
int value;
int used;
int zeroes;
State state;
- Q_DECL_CONSTEXPR ParsedSection(State ok = Invalid,
+ constexpr ParsedSection(State ok = Invalid,
int val = 0, int read = 0, int zs = 0)
: value(ok == Invalid ? -1 : val), used(read), zeroes(zs), state(ok)
{}
};
- ParsedSection parseSection(const QDateTime &currentValue, int sectionIndex,
- int offset, QString *text) const;
- int findMonth(const QString &str1, int monthstart, int sectionIndex,
+ ParsedSection parseSection(const QDateTime &currentValue, int sectionIndex, int offset) const;
+ int findMonth(QStringView str, int monthstart, int sectionIndex,
int year, QString *monthName = nullptr, int *used = nullptr) const;
- int findDay(const QString &str1, int intDaystart, int sectionIndex,
+ int findDay(QStringView str, int intDaystart, int sectionIndex,
QString *dayName = nullptr, int *used = nullptr) const;
- ParsedSection findUtcOffset(QStringView str) const;
+ ParsedSection findUtcOffset(QStringView str, int mode) const;
ParsedSection findTimeZoneName(QStringView str, const QDateTime &when) const;
ParsedSection findTimeZone(QStringView str, const QDateTime &when,
- int maxVal, int minVal) const;
- // Implemented in qdatetime.cpp:
- static int startsWithLocalTimeZone(const QStringView name);
+ int maxVal, int minVal, int mode) const;
enum AmPmFinder {
Neither = -1,
@@ -236,7 +188,6 @@ private:
PossibleBoth = 4
};
AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const;
-#endif // datestring
bool potentialValue(QStringView str, int min, int max, int index,
const QDateTime &currentValue, int insert) const;
@@ -246,11 +197,22 @@ private:
return potentialValue(QStringView(str), min, max, index, currentValue, insert);
}
+ enum Case {
+ NativeCase,
+ LowerCase,
+ UpperCase
+ };
+
+ QString getAmPmText(AmPm ap, Case cs) const;
+ QDateTime baseDate(const QTimeZone &zone) const;
+
+ friend class QDTPUnitTestParser;
+
protected: // for the benefit of QDateTimeEditPrivate
int sectionSize(int index) const;
int sectionMaxSize(int index) const;
int sectionPos(int index) const;
- int sectionPos(const SectionNode &sn) const;
+ int sectionPos(SectionNode sn) const;
const SectionNode &sectionNode(int index) const;
Section sectionType(int index) const;
@@ -267,14 +229,14 @@ protected: // for the benefit of QDateTimeEditPrivate
return skipToNextSection(section, current, QStringView(sectionText));
}
QString stateName(State s) const;
- QString getAmPmText(AmPm ap, Case cs) const;
virtual QDateTime getMinimum() const;
virtual QDateTime getMaximum() const;
virtual int cursorPosition() const { return -1; }
virtual QLocale locale() const { return defaultLocale; }
- mutable int currentSectionIndex;
+ mutable int currentSectionIndex = int(NoSectionIndex);
+ mutable int defaultCenturyStart = QLocale::DefaultTwoDigitBaseYear;
Sections display;
/*
This stores the most recently selected day.
@@ -289,21 +251,21 @@ protected: // for the benefit of QDateTimeEditPrivate
This is good for when users have selected their desired day and are scrolling up or down in the month or year section
and do not want smaller months (or non-leap years) to alter the day that they chose.
*/
- mutable int cachedDay;
- mutable QString text;
+ mutable int cachedDay = -1;
+ mutable QString m_text;
QList<SectionNode> sectionNodes;
SectionNode first, last, none, popup;
QStringList separators;
QString displayFormat;
QLocale defaultLocale;
QMetaType::Type parserType;
- bool fixday;
+ bool fixday = false;
Context context;
QCalendar calendar;
};
Q_DECLARE_TYPEINFO(QDateTimeParser::SectionNode, Q_PRIMITIVE_TYPE);
-Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
+Q_CORE_EXPORT bool operator==(QDateTimeParser::SectionNode s1, QDateTimeParser::SectionNode s2);
Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
diff --git a/src/corelib/time/qgregoriancalendar.cpp b/src/corelib/time/qgregoriancalendar.cpp
index 633b1ea94e..d46d24ac30 100644
--- a/src/corelib/time/qgregoriancalendar.cpp
+++ b/src/corelib/time/qgregoriancalendar.cpp
@@ -1,50 +1,34 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgregoriancalendar_p.h"
#include "qcalendarmath_p.h"
+
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
using namespace QRoundingDown;
+// Verification that QRoundingDown::qDivMod() works correctly:
+static_assert(qDivMod<2>(-86400).quotient == -43200);
+static_assert(qDivMod<2>(-86400).remainder == 0);
+static_assert(qDivMod<86400>(-86400).quotient == -1);
+static_assert(qDivMod<86400>(-86400).remainder == 0);
+static_assert(qDivMod<86400>(-86401).quotient == -2);
+static_assert(qDivMod<86400>(-86401).remainder == 86399);
+static_assert(qDivMod<86400>(-100000).quotient == -2);
+static_assert(qDivMod<86400>(-100000).remainder == 72800);
+static_assert(qDivMod<86400>(-172799).quotient == -2);
+static_assert(qDivMod<86400>(-172799).remainder == 1);
+static_assert(qDivMod<86400>(-172800).quotient == -2);
+static_assert(qDivMod<86400>(-172800).remainder == 0);
+
+// Uncomment to verify error on bad denominator is clear and intelligible:
+// static_assert(qDivMod<1>(17).remainder == 0);
+// static_assert(qDivMod<0>(17).remainder == 0);
+// static_assert(qDivMod<std::numeric_limits<unsigned>::max()>(17).remainder == 0);
+
/*!
\since 5.14
@@ -60,20 +44,17 @@ using namespace QRoundingDown;
\sa QRomanCalendar, QJulianCalendar, QCalendar
*/
-QGregorianCalendar::QGregorianCalendar()
- : QRomanCalendar(QStringLiteral("Gregorian"), QCalendar::System::Gregorian)
-{
- registerAlias(QStringLiteral("gregory"));
-}
-
QString QGregorianCalendar::name() const
{
return QStringLiteral("Gregorian");
}
-QCalendar::System QGregorianCalendar::calendarSystem() const
+QStringList QGregorianCalendar::nameList()
{
- return QCalendar::System::Gregorian;
+ return {
+ QStringLiteral("Gregorian"),
+ QStringLiteral("gregory"),
+ };
}
bool QGregorianCalendar::isLeapYear(int year) const
@@ -112,64 +93,174 @@ bool QGregorianCalendar::validParts(int year, int month, int day)
int QGregorianCalendar::weekDayOfJulian(qint64 jd)
{
- return qMod(jd, 7) + 1;
+ return int(qMod<7>(jd) + 1);
}
bool QGregorianCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const
{
- return julianFromParts(year, month, day, jd);
+ const auto maybe = julianFromParts(year, month, day);
+ if (maybe)
+ *jd = *maybe;
+ return bool(maybe);
}
-bool QGregorianCalendar::julianFromParts(int year, int month, int day, qint64 *jd)
+QCalendar::YearMonthDay QGregorianCalendar::julianDayToDate(qint64 jd) const
{
- Q_ASSERT(jd);
- if (!validParts(year, month, day))
- return false;
+ return partsFromJulian(jd);
+}
- if (year < 0)
- ++year;
+qint64
+QGregorianCalendar::matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const
+{
+ /* The Gregorian four-century cycle is a whole number of weeks long, so we
+ only need to consider four centuries, from previous through next-but-one.
+ There are thus three days of the week that can't happen, for any given
+ day-of-month, month and year-mod-100. (Exception: '00 Feb 29 has only one
+ option.)
+ */
+ auto maybe = julianFromParts(parts.year, parts.month, parts.day);
+ if (maybe) {
+ int diff = weekDayOfJulian(*maybe) - dow;
+ if (!diff)
+ return *maybe;
+ int year = parts.year < 0 ? parts.year + 1 : parts.year;
+ // What matters is the placement of leap days, so dates before March
+ // effectively belong with the dates since the preceding March:
+ const auto yearSplit = qDivMod<100>(year - (parts.month < 3 ? 1 : 0));
+ const int centuryMod4 = qMod<4>(yearSplit.quotient);
+ // Week-day shift for a century is 5, unless crossing a multiple of 400's Feb 29th.
+ static_assert(qMod<7>(36524) == 5); // and (3 * 5) % 7 = 1
+ // Formulae arrived at by case-by-case analysis of the values of
+ // centuryMod4 and diff (and the above clue to multiply by -3 = 4):
+ if (qMod<7>(diff * 4 + centuryMod4) < 4) {
+ // Century offset maps qMod<7>(diff) in {5, 6} to -1, {3, 4} to +2, and {1, 2} to +1:
+ year += (((qMod<7>(diff) + 3) / 2) % 4 - 1) * 100;
+ maybe = julianFromParts(year > 0 ? year : year - 1, parts.month, parts.day);
+ if (maybe && weekDayOfJulian(*maybe) == dow)
+ return *maybe;
+ Q_ASSERT(parts.month == 2 && parts.day == 29
+ && dow != int(Qt::Tuesday) && !(year % 100));
+ }
- /*
- * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
- * This formula is correct for all julian days, when using mathematical integer
- * division (round to negative infinity), not c++11 integer division (round to zero)
- */
- int a = month < 3 ? 1 : 0;
- qint64 y = qint64(year) + 4800 - a;
- int m = month + 12 * a - 3;
- *jd = day + qDiv(153 * m + 2, 5) - 32045
- + 365 * y + qDiv(y, 4) - qDiv(y, 100) + qDiv(y, 400);
- return true;
+ } else if (parts.month == 2 && parts.day == 29) {
+ int year = parts.year < 0 ? parts.year + 1 : parts.year;
+ // Feb 29th on a century needs to resolve to a multiple of 400 years.
+ const auto yearSplit = qDivMod<100>(year);
+ if (!yearSplit.remainder) {
+ const auto centuryMod4 = qMod<4>(yearSplit.quotient);
+ Q_ASSERT(centuryMod4); // or we'd have got a valid date to begin with.
+ if (centuryMod4 == 1) // round down
+ year -= 100;
+ else // 2 or 3; round up
+ year += (4 - centuryMod4) * 100;
+ maybe = julianFromParts(year > 0 ? year : year - 1, parts.month, parts.day);
+ if (maybe && weekDayOfJulian(*maybe) == dow) // (Can only happen for Tuesday.)
+ return *maybe;
+ Q_ASSERT(dow != int(Qt::Tuesday));
+ }
+ }
+ return (std::numeric_limits<qint64>::min)();
}
-QCalendar::YearMonthDay QGregorianCalendar::julianDayToDate(qint64 jd) const
+int QGregorianCalendar::yearStartWeekDay(int year)
{
- return partsFromJulian(jd);
+ // Equivalent to weekDayOfJulian(julianForParts({year, 1, 1})
+ const int y = year - (year < 0 ? 800 : 801);
+ return qMod<7>(y + qDiv<4>(y) - qDiv<100>(y) + qDiv<400>(y)) + 1;
+}
+
+int QGregorianCalendar::yearSharingWeekDays(QDate date)
+{
+ // Returns a post-epoch year, no later than 2400, that has the same pattern
+ // of week-days (in the proleptic Gregorian calendar) as the year in which
+ // the given date falls. This will be the year in question if it's in the
+ // given range. Otherwise, the returned year's last two (decimal) digits
+ // won't coincide with the month number or day-of-month of the given date.
+ // For positive years, except when necessary to avoid such a clash, the
+ // returned year's last two digits shall coincide with those of the original
+ // year.
+
+ // Needed when formatting dates using system APIs with limited year ranges
+ // and possibly only a two-digit year. (The need to be able to safely
+ // replace the two-digit form of the returned year with a suitable form of
+ // the true year, when they don't coincide, is why the last two digits are
+ // treated specially.)
+
+ static_assert((400 * 365 + 97) % 7 == 0);
+ // A full 400-year cycle of the Gregorian calendar has 97 + 400 * 365 days;
+ // as 365 is one more than a multiple of seven and 497 is a multiple of
+ // seven, that full cycle is a whole number of weeks. So adding a multiple
+ // of four hundred years should get us a result that meets our needs.
+
+ const int year = date.year();
+ int res = (year < 1970
+ ? 2400 - (2000 - (year < 0 ? year + 1 : year)) % 400
+ : year > 2399 ? 2000 + (year - 2000) % 400 : year);
+ Q_ASSERT(res > 0);
+ if (res != year) {
+ const int lastTwo = res % 100;
+ if (lastTwo == date.month() || lastTwo == date.day()) {
+ Q_ASSERT(lastTwo && !(lastTwo & ~31));
+ // Last two digits of these years are all > 31:
+ static constexpr int usual[] = { 2198, 2199, 2098, 2099, 2399, 2298, 2299 };
+ static constexpr int leaps[] = { 2396, 2284, 2296, 2184, 2196, 2084, 2096 };
+ // Indexing is: first day of year's day-of-week, Monday = 0, one less
+ // than Qt's, as it's simpler to subtract one than to s/7/0/.
+ res = (leapTest(year) ? leaps : usual)[yearStartWeekDay(year) - 1];
+ }
+ Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == QDate(year, 1, 1).dayOfWeek());
+ Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
+ }
+ Q_ASSERT(res >= 1970 && res <= 2400);
+ return res;
+}
+
+/*
+ * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
+ * This formula is correct for all julian days, when using mathematical integer
+ * division (round to negative infinity), not c++11 integer division (round to zero).
+ *
+ * The source given uses 4801 BCE as base date; the following adjusts that by
+ * 4800 years to simplify part of the arithmetic (and match more closely what we
+ * do for Milankovic).
+ */
+
+using namespace QRomanCalendrical;
+// End a Gregorian four-century cycle on 1 BC's leap day:
+constexpr qint64 BaseJd = LeapDayGregorian1Bce;
+// Every four centures there are 97 leap years:
+constexpr unsigned FourCenturies = 400 * 365 + 97;
+
+std::optional<qint64> QGregorianCalendar::julianFromParts(int year, int month, int day)
+{
+ if (!validParts(year, month, day))
+ return std::nullopt;
+
+ const auto yearDays = yearMonthToYearDays(year, month);
+ const qint64 y = yearDays.year;
+ const qint64 fromYear = 365 * y + qDiv<4>(y) - qDiv<100>(y) + qDiv<400>(y);
+ return fromYear + yearDays.days + day + BaseJd;
}
QCalendar::YearMonthDay QGregorianCalendar::partsFromJulian(qint64 jd)
{
- /*
- * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
- * This formula is correct for all julian days, when using mathematical integer
- * division (round to negative infinity), not c++11 integer division (round to zero)
- */
- qint64 a = jd + 32044;
- qint64 b = qDiv(4 * a + 3, 146097);
- int c = a - qDiv(146097 * b, 4);
+ const qint64 dayNumber = jd - BaseJd;
+ const qint64 century = qDiv<FourCenturies>(4 * dayNumber - 1);
+ const int dayInCentury = dayNumber - qDiv<4>(FourCenturies * century);
- int d = qDiv(4 * c + 3, 1461);
- int e = c - qDiv(1461 * d, 4);
- int m = qDiv(5 * e + 2, 153);
+ const int yearInCentury = qDiv<FourYears>(4 * dayInCentury - 1);
+ const int dayInYear = dayInCentury - qDiv<4>(FourYears * yearInCentury);
+ const int m = qDiv<FiveMonths>(5 * dayInYear - 3);
+ Q_ASSERT(m < 12 && m >= 0);
+ // That m is a month adjusted to March = 0, with Jan = 10, Feb = 11 in the previous year.
+ const int yearOffset = m < 10 ? 0 : 1;
- int y = 100 * b + d - 4800 + qDiv(m, 10);
+ const int y = 100 * century + yearInCentury + yearOffset;
+ const int month = m + 3 - 12 * yearOffset;
+ const int day = dayInYear - qDiv<5>(FiveMonths * m + 2);
// Adjust for no year 0
- int year = y > 0 ? y : y - 1;
- int month = m + 3 - 12 * qDiv(m, 10);
- int day = e - qDiv(153 * m + 2, 5) + 1;
-
- return QCalendar::YearMonthDay(year, month, day);
+ return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);
}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qgregoriancalendar_p.h b/src/corelib/time/qgregoriancalendar_p.h
index 191f9c127b..1093a7b9de 100644
--- a/src/corelib/time/qgregoriancalendar_p.h
+++ b/src/corelib/time/qgregoriancalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGREGORIAN_CALENDAR_P_H
#define QGREGORIAN_CALENDAR_P_H
@@ -53,6 +17,8 @@
#include "qromancalendar_p.h"
+#include <optional>
+
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QGregorianCalendar : public QRomanCalendar
@@ -60,21 +26,15 @@ class Q_CORE_EXPORT QGregorianCalendar : public QRomanCalendar
// TODO: provide static methods, called by the overrides, that can be called
// directly by QDate to optimize various parts.
public:
- QGregorianCalendar();
- // CAlendar properties:
+ // Calendar property:
QString name() const override;
- QCalendar::System calendarSystem() const override;
+ static QStringList nameList();
// Date queries:
bool isLeapYear(int year) const override;
// Julian Day conversions:
bool dateToJulianDay(int year, int month, int day, qint64 *jd) const override;
QCalendar::YearMonthDay julianDayToDate(qint64 jd) const override;
-
- // Names of months (implemented in qlocale.cpp):
- QString monthName(const QLocale &locale, int month, int year,
- QLocale::FormatType format) const override;
- QString standaloneMonthName(const QLocale &locale, int month, int year,
- QLocale::FormatType format) const override;
+ qint64 matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const override;
// Static optimized versions for the benefit of QDate:
static int weekDayOfJulian(qint64 jd);
@@ -82,7 +42,10 @@ public:
static int monthLength(int month, int year);
static bool validParts(int year, int month, int day);
static QCalendar::YearMonthDay partsFromJulian(qint64 jd);
- static bool julianFromParts(int year, int month, int day, qint64 *jd);
+ static std::optional<qint64> julianFromParts(int year, int month, int day);
+ // Used internally:
+ static int yearStartWeekDay(int year);
+ static int yearSharingWeekDays(QDate date);
};
QT_END_NAMESPACE
diff --git a/src/corelib/time/qhijricalendar.cpp b/src/corelib/time/qhijricalendar.cpp
index c0f7662c0d..3d5a97c310 100644
--- a/src/corelib/time/qhijricalendar.cpp
+++ b/src/corelib/time/qhijricalendar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qhijricalendar_p.h"
@@ -115,12 +79,12 @@ int QHijriCalendar::daysInYear(int year) const
const QCalendarLocale *QHijriCalendar::localeMonthIndexData() const
{
- return locale_data;
+ return QtPrivate::Hijri::locale_data;
}
const char16_t *QHijriCalendar::localeMonthData() const
{
- return months_data;
+ return QtPrivate::Hijri::months_data;
}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qhijricalendar_data_p.h b/src/corelib/time/qhijricalendar_data_p.h
index 5445375c3c..a52bf1dc4e 100644
--- a/src/corelib/time/qhijricalendar_data_p.h
+++ b/src/corelib/time/qhijricalendar_data_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-3.0
#ifndef QHIJRI_CALENDAR_DATA_P_H
#define QHIJRI_CALENDAR_DATA_P_H
@@ -56,11 +20,13 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate::Hijri {
+
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-04-07 from the
- Common Locale Data Repository v36
+ This part of the file was generated on 2024-01-09 from the
+ Common Locale Data Repository v44.1
http://www.unicode.org/cldr/
@@ -69,1145 +35,1759 @@ QT_BEGIN_NAMESPACE
edited) CLDR data; see qtbase/util/locale_database/.
*/
-static const QCalendarLocale locale_data[] = {
+static constexpr QCalendarLocale locale_data[] = {
// lang script terr sLong long sShrt short sNarw narow Sizes...
- { 1, 0, 0, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// C/AnyScript/AnyCountry
- { 3, 7, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Ethiopia
- { 3, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Kenya
- { 4, 7, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afar/Latin/Ethiopia
- { 5, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afrikaans/Latin/South Africa
- { 5, 7, 148, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afrikaans/Latin/Namibia
- { 6, 7, 2, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Albanian/Latin/Albania
- { 6, 7, 127, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Albanian/Latin/Macedonia
- { 6, 7, 257, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Albanian/Latin/Kosovo
- { 7, 14, 69, 210, 210, 106, 106, 184, 184, 74, 74, 78, 78, 26, 26 },// Amharic/Ethiopic/Ethiopia
- { 8, 1, 64, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Egypt
- { 8, 1, 3, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Algeria
- { 8, 1, 17, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Bahrain
- { 8, 1, 42, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Chad
- { 8, 1, 48, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Comoros
- { 8, 1, 59, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Djibouti
- { 8, 1, 67, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Eritrea
- { 8, 1, 103, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Iraq
- { 8, 1, 105, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Israel
- { 8, 1, 109, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Jordan
- { 8, 1, 115, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Kuwait
- { 8, 1, 119, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Lebanon
- { 8, 1, 122, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Libya
- { 8, 1, 136, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Mauritania
- { 8, 1, 145, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Morocco
- { 8, 1, 162, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Oman
- { 8, 1, 165, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Palestinian Territories
- { 8, 1, 175, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Qatar
- { 8, 1, 186, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Saudi Arabia
- { 8, 1, 194, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Somalia
- { 8, 1, 201, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Sudan
- { 8, 1, 207, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Syria
- { 8, 1, 216, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Tunisia
- { 8, 1, 223, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/United Arab Emirates
- { 8, 1, 236, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Western Sahara
- { 8, 1, 237, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Yemen
- { 8, 1, 254, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/South Sudan
- { 8, 1, 260, 284, 284, 284, 284, 380, 380, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/World
- { 9, 10, 11, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Armenian/Armenian/Armenia
- { 10, 11, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Assamese/Bengali/India
- { 12, 7, 15, 406, 406, 516, 516, 184, 184,110,110, 71, 71, 26, 26 },// Azerbaijani/Latin/Azerbaijan
- { 12, 1, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Azerbaijani/Arabic/Iran
- { 12, 2, 15, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Azerbaijani/Cyrillic/Azerbaijan
- { 13, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bashkir/Cyrillic/Russia
- { 14, 7, 197, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Basque/Latin/Spain
- { 15, 11, 18, 587, 587, 587, 587, 691, 691,104,104,104,104, 26, 26 },// Bengali/Bengali/Bangladesh
- { 15, 11, 100, 587, 587, 587, 587, 691, 691,104,104,104,104, 26, 26 },// Bengali/Bengali/India
- { 16, 31, 25, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Dzongkha/Tibetan/Bhutan
- { 19, 7, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Breton/Latin/France
- { 20, 2, 33, 717, 717, 106, 106, 184, 184, 96, 96, 78, 78, 26, 26 },// Bulgarian/Cyrillic/Bulgaria
- { 21, 25, 147, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Burmese/Myanmar/Myanmar
- { 22, 2, 20, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Belarusian/Cyrillic/Belarus
- { 23, 20, 36, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Khmer/Khmer/Cambodia
- { 24, 7, 197, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/Spain
- { 24, 7, 5, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/Andorra
- { 24, 7, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/France
- { 24, 7, 106, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/Italy
- { 25, 5, 44, 813, 813, 850, 850, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/China
- { 25, 5, 97, 813, 813, 850, 850, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Hong Kong
- { 25, 5, 126, 813, 813, 850, 850, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Macau
- { 25, 5, 190, 813, 813, 850, 850, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Singapore
- { 25, 6, 97, 888, 888, 888, 888, 184, 184, 71, 71, 71, 71, 26, 26 },// Chinese/Traditional Han/Hong Kong
- { 25, 6, 126, 888, 888, 888, 888, 184, 184, 71, 71, 71, 71, 26, 26 },// Chinese/Traditional Han/Macau
- { 25, 6, 208, 888, 888, 888, 888, 184, 184, 71, 71, 71, 71, 26, 26 },// Chinese/Traditional Han/Taiwan
- { 26, 7, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Corsican/Latin/France
- { 27, 7, 54, 0, 0, 106, 106, 959, 959,106,106, 78, 78, 38, 38 },// Croatian/Latin/Croatia
- { 27, 7, 27, 0, 0, 106, 106, 959, 959,106,106, 78, 78, 38, 38 },// Croatian/Latin/Bosnia And Herzegowina
- { 28, 7, 57, 997, 997, 1126, 1126, 184, 184,129,129, 76, 76, 26, 26 },// Czech/Latin/Czech Republic
- { 29, 7, 58, 1202, 1202, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Danish/Latin/Denmark
- { 29, 7, 86, 1202, 1202, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Danish/Latin/Greenland
- { 30, 7, 151, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Netherlands
- { 30, 7, 12, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Aruba
- { 30, 7, 21, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Belgium
- { 30, 7, 152, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Cura Sao
- { 30, 7, 202, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Suriname
- { 30, 7, 255, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Bonaire
- { 30, 7, 256, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Sint Maarten
- { 31, 7, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United States
- { 31, 3, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Deseret/United States
- { 31, 7, 4, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/American Samoa
- { 31, 7, 7, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Anguilla
- { 31, 7, 9, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Antigua And Barbuda
- { 31, 7, 13, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Australia
- { 31, 7, 14, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Austria
- { 31, 7, 16, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Bahamas
- { 31, 7, 19, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Barbados
- { 31, 7, 21, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Belgium
- { 31, 7, 22, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Belize
- { 31, 7, 24, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Bermuda
- { 31, 7, 28, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Botswana
- { 31, 7, 31, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/British Indian Ocean Territory
- { 31, 7, 35, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Burundi
- { 31, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cameroon
- { 31, 7, 38, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Canada
- { 31, 7, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cayman Islands
- { 31, 7, 45, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Christmas Island
- { 31, 7, 46, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cocos Islands
- { 31, 7, 51, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cook Islands
- { 31, 7, 56, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cyprus
- { 31, 7, 58, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Denmark
- { 31, 7, 60, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Dominica
- { 31, 7, 67, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Eritrea
- { 31, 7, 70, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Falkland Islands
- { 31, 7, 72, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Fiji
- { 31, 7, 73, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Finland
- { 31, 7, 75, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Guernsey
- { 31, 7, 80, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Gambia
- { 31, 7, 82, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Germany
- { 31, 7, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Ghana
- { 31, 7, 84, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Gibraltar
- { 31, 7, 87, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Grenada
- { 31, 7, 89, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Guam
- { 31, 7, 93, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Guyana
- { 31, 7, 97, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Hong Kong
- { 31, 7, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/India
- { 31, 7, 104, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Ireland
- { 31, 7, 105, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Israel
- { 31, 7, 107, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Jamaica
- { 31, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Kenya
- { 31, 7, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Kiribati
- { 31, 7, 120, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Lesotho
- { 31, 7, 121, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Liberia
- { 31, 7, 126, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Macau
- { 31, 7, 128, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Madagascar
- { 31, 7, 129, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Malawi
- { 31, 7, 130, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Malaysia
- { 31, 7, 133, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Malta
- { 31, 7, 134, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Marshall Islands
- { 31, 7, 137, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Mauritius
- { 31, 7, 140, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Micronesia
- { 31, 7, 144, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Montserrat
- { 31, 7, 148, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Namibia
- { 31, 7, 149, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Nauru
- { 31, 7, 151, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Netherlands
- { 31, 7, 154, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/New Zealand
- { 31, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Nigeria
- { 31, 7, 158, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Niue
- { 31, 7, 159, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Norfolk Island
- { 31, 7, 160, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Northern Mariana Islands
- { 31, 7, 163, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Pakistan
- { 31, 7, 164, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Palau
- { 31, 7, 167, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Papua New Guinea
- { 31, 7, 170, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Philippines
- { 31, 7, 171, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Pitcairn
- { 31, 7, 174, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Puerto Rico
- { 31, 7, 179, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Rwanda
- { 31, 7, 180, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Kitts And Nevis
- { 31, 7, 181, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Lucia
- { 31, 7, 182, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Vincent And The Grenadines
- { 31, 7, 183, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Samoa
- { 31, 7, 188, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Seychelles
- { 31, 7, 189, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sierra Leone
- { 31, 7, 190, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Singapore
- { 31, 7, 192, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Slovenia
- { 31, 7, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Solomon Islands
- { 31, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/South Africa
- { 31, 7, 199, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Helena
- { 31, 7, 201, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sudan
- { 31, 7, 204, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Swaziland
- { 31, 7, 205, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sweden
- { 31, 7, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Switzerland
- { 31, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tanzania
- { 31, 7, 213, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tokelau
- { 31, 7, 214, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tonga
- { 31, 7, 215, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Trinidad And Tobago
- { 31, 7, 219, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Turks And Caicos Islands
- { 31, 7, 220, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tuvalu
- { 31, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Uganda
- { 31, 7, 223, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United Arab Emirates
- { 31, 7, 224, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United Kingdom
- { 31, 7, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United States Minor Outlying Islands
- { 31, 7, 229, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Vanuatu
- { 31, 7, 233, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/British Virgin Islands
- { 31, 7, 234, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United States Virgin Islands
- { 31, 7, 239, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Zambia
- { 31, 7, 240, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Zimbabwe
- { 31, 7, 249, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Diego Garcia
- { 31, 7, 251, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Isle Of Man
- { 31, 7, 252, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Jersey
- { 31, 7, 254, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/South Sudan
- { 31, 7, 256, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sint Maarten
- { 31, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/World
- { 31, 7, 261, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Europe
- { 32, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Esperanto/Latin/World
- { 33, 7, 68, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Estonian/Latin/Estonia
- { 34, 7, 71, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Faroese/Latin/Faroe Islands
- { 34, 7, 58, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Faroese/Latin/Denmark
- { 36, 7, 73, 1525, 1525, 106, 106, 184, 184,129,129, 78, 78, 26, 26 },// Finnish/Latin/Finland
- { 37, 7, 74, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/France
- { 37, 7, 3, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Algeria
- { 37, 7, 21, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Belgium
- { 37, 7, 23, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Benin
- { 37, 7, 34, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Burkina Faso
- { 37, 7, 35, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Burundi
- { 37, 7, 37, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Cameroon
- { 37, 7, 38, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Canada
- { 37, 7, 41, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Central African Republic
- { 37, 7, 42, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Chad
- { 37, 7, 48, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Comoros
- { 37, 7, 49, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Congo Kinshasa
- { 37, 7, 50, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Congo Brazzaville
- { 37, 7, 53, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Ivory Coast
- { 37, 7, 59, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Djibouti
- { 37, 7, 66, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Equatorial Guinea
- { 37, 7, 76, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/French Guiana
- { 37, 7, 77, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/French Polynesia
- { 37, 7, 79, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Gabon
- { 37, 7, 88, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Guadeloupe
- { 37, 7, 91, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Guinea
- { 37, 7, 94, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Haiti
- { 37, 7, 125, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Luxembourg
- { 37, 7, 128, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Madagascar
- { 37, 7, 132, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mali
- { 37, 7, 135, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Martinique
- { 37, 7, 136, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mauritania
- { 37, 7, 137, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mauritius
- { 37, 7, 138, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mayotte
- { 37, 7, 142, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Monaco
- { 37, 7, 145, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Morocco
- { 37, 7, 153, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/New Caledonia
- { 37, 7, 156, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Niger
- { 37, 7, 176, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Reunion
- { 37, 7, 179, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Rwanda
- { 37, 7, 187, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Senegal
- { 37, 7, 188, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Seychelles
- { 37, 7, 200, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Saint Pierre And Miquelon
- { 37, 7, 206, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Switzerland
- { 37, 7, 207, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Syria
- { 37, 7, 212, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Togo
- { 37, 7, 216, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Tunisia
- { 37, 7, 229, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Vanuatu
- { 37, 7, 235, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Wallis And Futuna Islands
- { 37, 7, 244, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Saint Barthelemy
- { 37, 7, 245, 1654, 1654, 1793, 1883, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Saint Martin
- { 38, 7, 151, 1308, 1308, 1442, 1442, 184, 184,134,134, 83, 83, 26, 26 },// Western Frisian/Latin/Netherlands
- { 39, 7, 224, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Gaelic/Latin/United Kingdom
- { 40, 7, 197, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Galician/Latin/Spain
- { 41, 15, 81, 1973, 1973, 2097, 2097, 184, 184,124,124, 73, 73, 26, 26 },// Georgian/Georgian/Georgia
- { 42, 7, 82, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Germany
- { 42, 7, 14, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Austria
- { 42, 7, 21, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Belgium
- { 42, 7, 106, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Italy
- { 42, 7, 123, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Liechtenstein
- { 42, 7, 125, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Luxembourg
- { 42, 7, 206, 2170, 2170, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Switzerland
- { 43, 16, 85, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Greek/Greek/Greece
- { 43, 16, 56, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Greek/Greek/Cyprus
- { 44, 7, 86, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Greenlandic/Latin/Greenland
- { 45, 7, 168, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Guarani/Latin/Paraguay
- { 46, 17, 100, 2286, 2286, 2384, 2384, 184, 184, 98, 98, 74, 74, 26, 26 },// Gujarati/Gujarati/India
- { 47, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hausa/Latin/Nigeria
- { 47, 1, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hausa/Arabic/Nigeria
- { 47, 7, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hausa/Latin/Ghana
- { 47, 7, 156, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hausa/Latin/Niger
- { 48, 18, 105, 2458, 2574, 2690, 2690, 184, 184,116,116, 95, 95, 26, 26 },// Hebrew/Hebrew/Israel
- { 49, 13, 100, 2785, 2785, 106, 106, 184, 184,108,108, 78, 78, 26, 26 },// Hindi/Devanagari/India
- { 50, 7, 98, 2893, 2992, 3119, 3119, 184, 184, 99,127, 76, 76, 26, 26 },// Hungarian/Latin/Hungary
- { 51, 7, 99, 1202, 1202, 3195, 3195, 184, 184,106,106, 78, 78, 26, 26 },// Icelandic/Latin/Iceland
- { 52, 7, 101, 3273, 3273, 3382, 3382, 184, 184,109,109, 86, 86, 26, 26 },// Indonesian/Latin/Indonesia
- { 53, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Interlingua/Latin/World
- { 55, 44, 38, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Inuktitut/Canadian Aboriginal/Canada
- { 55, 7, 38, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Inuktitut/Latin/Canada
- { 57, 7, 104, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Irish/Latin/Ireland
- { 57, 7, 224, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Irish/Latin/United Kingdom
- { 58, 7, 106, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/Italy
- { 58, 7, 184, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/San Marino
- { 58, 7, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/Switzerland
- { 58, 7, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/Vatican City State
- { 59, 19, 108, 3468, 3468, 3468, 3468, 184, 184, 97, 97, 97, 97, 26, 26 },// Japanese/Japanese/Japan
- { 60, 7, 101, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Javanese/Latin/Indonesia
- { 61, 21, 100, 3565, 3565, 3665, 3665, 184, 184,100,100, 79, 79, 26, 26 },// Kannada/Kannada/India
- { 62, 1, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kashmiri/Arabic/India
- { 63, 2, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kazakh/Cyrillic/Kazakhstan
- { 64, 7, 179, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kinyarwanda/Latin/Rwanda
- { 65, 2, 116, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kirghiz/Cyrillic/Kyrgyzstan
- { 66, 22, 114, 3744, 3744, 106, 106, 184, 184, 69, 69, 78, 78, 26, 26 },// Korean/Korean/South Korea
- { 66, 22, 113, 3744, 3744, 106, 106, 184, 184, 69, 69, 78, 78, 26, 26 },// Korean/Korean/North Korea
- { 67, 7, 217, 3813, 3813, 106, 106, 184, 184,109,109, 78, 78, 26, 26 },// Kurdish/Latin/Turkey
- { 68, 7, 35, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rundi/Latin/Burundi
- { 69, 23, 117, 3922, 3922, 4017, 4092, 184, 184, 95, 95, 75, 77, 26, 26 },// Lao/Lao/Laos
- { 71, 7, 118, 4169, 4169, 106, 106, 184, 184,108,108, 78, 78, 26, 26 },// Latvian/Latin/Latvia
- { 72, 7, 49, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Congo Kinshasa
- { 72, 7, 6, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Angola
- { 72, 7, 41, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Central African Republic
- { 72, 7, 50, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Congo Brazzaville
- { 73, 7, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lithuanian/Latin/Lithuania
- { 74, 2, 127, 4277, 4277, 4366, 4366, 184, 184, 89, 89, 71, 71, 26, 26 },// Macedonian/Cyrillic/Macedonia
- { 75, 7, 128, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malagasy/Latin/Madagascar
- { 76, 7, 130, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malay/Latin/Malaysia
- { 76, 1, 130, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malay/Arabic/Malaysia
- { 76, 7, 32, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malay/Latin/Brunei
- { 76, 7, 190, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malay/Latin/Singapore
- { 77, 24, 100, 4437, 4539, 4641, 4641, 4738, 4738,102,102, 97, 97, 26, 26 },// Malayalam/Malayalam/India
- { 78, 7, 133, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Maltese/Latin/Malta
- { 79, 7, 154, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Maori/Latin/New Zealand
- { 80, 13, 100, 4764, 4764, 4851, 4851, 4929, 4929, 87, 87, 78, 78, 26, 26 },// Marathi/Devanagari/India
- { 82, 2, 143, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mongolian/Cyrillic/Mongolia
- { 82, 8, 44, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mongolian/Mongolian/China
- { 84, 13, 150, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nepali/Devanagari/Nepal
- { 84, 13, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nepali/Devanagari/India
- { 85, 7, 161, 4955, 4955, 5061, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Norwegian Bokmal/Latin/Norway
- { 85, 7, 203, 4955, 4955, 5061, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands
- { 86, 7, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Occitan/Latin/France
- { 87, 26, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oriya/Oriya/India
- { 88, 1, 1, 5217, 5291, 5366, 5439, 184, 184, 74, 75, 73, 73, 26, 26 },// Pashto/Arabic/Afghanistan
- { 88, 1, 163, 5512, 5591, 5366, 5439, 184, 184, 79, 80, 73, 73, 26, 26 },// Pashto/Arabic/Pakistan
- { 89, 1, 102, 5671, 5761, 5671, 5761, 5853, 5853, 90, 92, 90, 92, 23, 23 },// Persian/Arabic/Iran
- { 89, 1, 1, 5671, 5761, 5671, 5761, 5853, 5853, 90, 92, 90, 92, 23, 23 },// Persian/Arabic/Afghanistan
- { 90, 7, 172, 5876, 5876, 5983, 5983, 184, 184,107,107, 77, 77, 26, 26 },// Polish/Latin/Poland
- { 91, 7, 30, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Brazil
- { 91, 7, 6, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Angola
- { 91, 7, 39, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Cape Verde
- { 91, 7, 62, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/East Timor
- { 91, 7, 66, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Equatorial Guinea
- { 91, 7, 92, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Guinea Bissau
- { 91, 7, 125, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Luxembourg
- { 91, 7, 126, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Macau
- { 91, 7, 146, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Mozambique
- { 91, 7, 173, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Portugal
- { 91, 7, 185, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Sao Tome And Principe
- { 91, 7, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Switzerland
- { 92, 4, 100, 6060, 6152, 6246, 6246, 184, 184, 92, 94, 77, 77, 26, 26 },// Punjabi/Gurmukhi/India
- { 92, 1, 163, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Punjabi/Arabic/Pakistan
- { 93, 7, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Quechua/Latin/Peru
- { 93, 7, 26, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Quechua/Latin/Bolivia
- { 93, 7, 63, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Quechua/Latin/Ecuador
- { 94, 7, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Romansh/Latin/Switzerland
- { 95, 7, 177, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Romanian/Latin/Romania
- { 95, 7, 141, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Romanian/Latin/Moldova
- { 96, 2, 178, 6323, 6323, 6454, 6454, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Russia
- { 96, 2, 20, 6323, 6323, 6454, 6454, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Belarus
- { 96, 2, 110, 6323, 6323, 6454, 6454, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Kazakhstan
- { 96, 2, 116, 6323, 6323, 6454, 6454, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Kyrgyzstan
- { 96, 2, 141, 6323, 6323, 6454, 6454, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Moldova
- { 96, 2, 222, 6323, 6323, 6454, 6454, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Ukraine
- { 98, 7, 41, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sango/Latin/Central African Republic
- { 99, 13, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sanskrit/Devanagari/India
- { 100, 2, 243, 6533, 6623, 6720, 6720, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Serbia
- { 100, 7, 27, 6789, 6883, 6980, 6980, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Bosnia And Herzegowina
- { 100, 7, 242, 6789, 6883, 6980, 6980, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Montenegro
- { 100, 7, 243, 6789, 6883, 6980, 6980, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Serbia
- { 100, 2, 27, 6533, 6623, 6720, 6720, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Bosnia And Herzegowina
- { 100, 2, 242, 6533, 6623, 6720, 6720, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Montenegro
- { 100, 2, 257, 6533, 6623, 6720, 6720, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Kosovo
- { 100, 7, 257, 6789, 6883, 6980, 6980, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Kosovo
- { 101, 2, 81, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ossetic/Cyrillic/Georgia
- { 101, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ossetic/Cyrillic/Russia
- { 102, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Sotho/Latin/South Africa
- { 103, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tswana/Latin/South Africa
- { 104, 7, 240, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Shona/Latin/Zimbabwe
- { 105, 1, 163, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sindhi/Arabic/Pakistan
- { 106, 32, 198, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sinhala/Sinhala/Sri Lanka
- { 107, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swati/Latin/South Africa
- { 108, 7, 191, 7052, 7052, 7187, 7187, 184, 184,135,135, 78, 78, 26, 26 },// Slovak/Latin/Slovakia
- { 109, 7, 192, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Slovenian/Latin/Slovenia
- { 110, 7, 194, 7265, 7396, 7526, 7600, 184, 184,131,130, 74, 78, 26, 26 },// Somali/Latin/Somalia
- { 110, 7, 59, 7265, 7396, 7526, 7600, 184, 184,131,130, 74, 78, 26, 26 },// Somali/Latin/Djibouti
- { 110, 7, 69, 7265, 7396, 7526, 7600, 184, 184,131,130, 74, 78, 26, 26 },// Somali/Latin/Ethiopia
- { 110, 7, 111, 7265, 7396, 7526, 7600, 184, 184,131,130, 74, 78, 26, 26 },// Somali/Latin/Kenya
- { 111, 7, 197, 7678, 7678, 5139, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Spain
- { 111, 7, 10, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Argentina
- { 111, 7, 22, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Belize
- { 111, 7, 26, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Bolivia
- { 111, 7, 30, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Brazil
- { 111, 7, 43, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Chile
- { 111, 7, 47, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Colombia
- { 111, 7, 52, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Costa Rica
- { 111, 7, 55, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Cuba
- { 111, 7, 61, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Dominican Republic
- { 111, 7, 63, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Ecuador
- { 111, 7, 65, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/El Salvador
- { 111, 7, 66, 7678, 7678, 5139, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Equatorial Guinea
- { 111, 7, 90, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Guatemala
- { 111, 7, 96, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Honduras
- { 111, 7, 139, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Mexico
- { 111, 7, 155, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Nicaragua
- { 111, 7, 166, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Panama
- { 111, 7, 168, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Paraguay
- { 111, 7, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Peru
- { 111, 7, 170, 7678, 7678, 5139, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Philippines
- { 111, 7, 174, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Puerto Rico
- { 111, 7, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/United States
- { 111, 7, 227, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Uruguay
- { 111, 7, 231, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Venezuela
- { 111, 7, 238, 7678, 7678, 5139, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Canary Islands
- { 111, 7, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Latin America
- { 111, 7, 250, 7678, 7678, 5139, 5139, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Ceuta And Melilla
- { 112, 7, 101, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sundanese/Latin/Indonesia
- { 113, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Tanzania
- { 113, 7, 49, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Congo Kinshasa
- { 113, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Kenya
- { 113, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Uganda
- { 114, 7, 205, 7784, 7911, 106, 106, 184, 184,127,127, 78, 78, 26, 26 },// Swedish/Latin/Sweden
- { 114, 7, 73, 7784, 7911, 106, 106, 184, 184,127,127, 78, 78, 26, 26 },// Swedish/Latin/Finland
- { 114, 7, 248, 7784, 7911, 106, 106, 184, 184,127,127, 78, 78, 26, 26 },// Swedish/Latin/Aland Islands
- { 115, 7, 106, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sardinian/Latin/Italy
- { 116, 2, 209, 8038, 8148, 8258, 8258, 184, 184,110,110, 74, 74, 26, 26 },// Tajik/Cyrillic/Tajikistan
- { 117, 27, 100, 8332, 8332, 8423, 8423, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/India
- { 117, 27, 130, 8332, 8332, 8423, 8423, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/Malaysia
- { 117, 27, 190, 8332, 8332, 8423, 8423, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/Singapore
- { 117, 27, 198, 8332, 8332, 8423, 8423, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/Sri Lanka
- { 118, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tatar/Cyrillic/Russia
- { 119, 28, 100, 8495, 0, 8590, 8590, 184, 184, 95,106, 74, 74, 26, 26 },// Telugu/Telugu/India
- { 120, 30, 211, 8664, 8664, 8766, 8766, 184, 184,102,102, 89, 89, 26, 26 },// Thai/Thai/Thailand
- { 121, 31, 44, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tibetan/Tibetan/China
- { 121, 31, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tibetan/Tibetan/India
- { 122, 14, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tigrinya/Ethiopic/Ethiopia
- { 122, 14, 67, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tigrinya/Ethiopic/Eritrea
- { 123, 7, 214, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tongan/Latin/Tonga
- { 124, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tsonga/Latin/South Africa
- { 125, 7, 217, 8855, 8855, 8965, 8965, 184, 184,110,110, 83, 83, 26, 26 },// Turkish/Latin/Turkey
- { 125, 7, 56, 8855, 8855, 8965, 8965, 184, 184,110,110, 83, 83, 26, 26 },// Turkish/Latin/Cyprus
- { 126, 7, 218, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Turkmen/Latin/Turkmenistan
- { 128, 1, 44, 9048, 9048, 9048, 9048, 184, 184,118,118,118,118, 26, 26 },// Uighur/Arabic/China
- { 129, 2, 222, 9166, 9166, 9269, 9340, 184, 184,103,103, 71, 81, 26, 26 },// Ukrainian/Cyrillic/Ukraine
- { 130, 1, 163, 9421, 9421, 9517, 9517, 184, 184, 96, 96, 98, 98, 26, 26 },// Urdu/Arabic/Pakistan
- { 130, 1, 100, 9421, 9421, 9517, 9517, 184, 184, 96, 96, 98, 98, 26, 26 },// Urdu/Arabic/India
- { 131, 7, 228, 9615, 9615, 9737, 9737, 184, 184,122,122, 82, 82, 26, 26 },// Uzbek/Latin/Uzbekistan
- { 131, 1, 1, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Uzbek/Arabic/Afghanistan
- { 131, 2, 228, 9819, 9819, 106, 106, 184, 184,114,114, 78, 78, 26, 26 },// Uzbek/Cyrillic/Uzbekistan
- { 132, 7, 232, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vietnamese/Latin/Vietnam
- { 133, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Volapuk/Latin/World
- { 134, 7, 224, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Welsh/Latin/United Kingdom
- { 135, 7, 187, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Wolof/Latin/Senegal
- { 136, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Xhosa/Latin/South Africa
- { 137, 18, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yiddish/Hebrew/World
- { 138, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yoruba/Latin/Nigeria
- { 138, 7, 23, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yoruba/Latin/Benin
- { 140, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Zulu/Latin/South Africa
- { 141, 7, 161, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Norwegian Nynorsk/Latin/Norway
- { 142, 7, 27, 9933, 9933,10031,10031, 184, 184, 98, 98, 74, 74, 26, 26 },// Bosnian/Latin/Bosnia And Herzegowina
- { 142, 2, 27, 6533, 6623, 6720, 6720, 184, 184, 90, 97, 69, 69, 26, 26 },// Bosnian/Cyrillic/Bosnia And Herzegowina
- { 143, 29, 131, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Divehi/Thaana/Maldives
- { 144, 7, 251, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Manx/Latin/Isle Of Man
- { 145, 7, 224, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Cornish/Latin/United Kingdom
- { 146, 7, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Akan/Latin/Ghana
- { 147, 13, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Konkani/Devanagari/India
- { 148, 7, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ga/Latin/Ghana
- { 149, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Igbo/Latin/Nigeria
- { 150, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kamba/Latin/Kenya
- { 151, 33, 103, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Syriac/Syriac/Iraq
- { 152, 14, 67, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Blin/Ethiopic/Eritrea
- { 153, 14, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Geez/Ethiopic/Ethiopia
- { 155, 7, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sidamo/Latin/Ethiopia
- { 156, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Atsam/Latin/Nigeria
- { 157, 14, 67, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tigre/Ethiopic/Eritrea
- { 158, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Jju/Latin/Nigeria
- { 159, 7, 106, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Friulian/Latin/Italy
- { 160, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Venda/Latin/South Africa
- { 161, 7, 83,10105,10105,10191,10191, 184, 184, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Ghana
- { 161, 7, 212,10105,10105,10191,10191, 184, 184, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Togo
- { 162, 14, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Walamo/Ethiopic/Ethiopia
- { 163, 7, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hawaiian/Latin/United States
- { 164, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tyap/Latin/Nigeria
- { 165, 7, 129, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nyanja/Latin/Malawi
- { 166, 7, 170, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Filipino/Latin/Philippines
- { 167, 7, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swiss German/Latin/Switzerland
- { 167, 7, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swiss German/Latin/France
- { 167, 7, 123, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swiss German/Latin/Liechtenstein
- { 168, 34, 44, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sichuan Yi/Yi/China
- { 169, 7, 121, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kpelle/Latin/Liberia
- { 170, 7, 82, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Low German/Latin/Germany
- { 170, 7, 151, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Low German/Latin/Netherlands
- { 171, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// South Ndebele/Latin/South Africa
- { 172, 7, 195, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sotho/Latin/South Africa
- { 173, 7, 161, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sami/Latin/Norway
- { 173, 7, 73, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sami/Latin/Finland
- { 173, 7, 205, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sami/Latin/Sweden
- { 174, 7, 208, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Taroko/Latin/Taiwan
- { 175, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Gusii/Latin/Kenya
- { 176, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Taita/Latin/Kenya
- { 177, 7, 187, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Senegal
- { 177, 7, 34, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Burkina Faso
- { 177, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Cameroon
- { 177, 7, 80, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Gambia
- { 177, 7, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Ghana
- { 177, 7, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Guinea
- { 177, 7, 92, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Guinea Bissau
- { 177, 7, 121, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Liberia
- { 177, 7, 136, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Mauritania
- { 177, 7, 156, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Niger
- { 177, 7, 157, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Nigeria
- { 177, 7, 189, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Sierra Leone
- { 177, 134, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Adlam/Guinea
- { 178, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kikuyu/Latin/Kenya
- { 179, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Samburu/Latin/Kenya
- { 180, 7, 146, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sena/Latin/Mozambique
- { 181, 7, 240, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// North Ndebele/Latin/Zimbabwe
- { 182, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rombo/Latin/Tanzania
- { 183, 9, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tachelhit/Tifinagh/Morocco
- { 183, 7, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tachelhit/Latin/Morocco
- { 184, 7, 3, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kabyle/Latin/Algeria
- { 185, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nyankole/Latin/Uganda
- { 186, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bena/Latin/Tanzania
- { 187, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vunjo/Latin/Tanzania
- { 188, 7, 132, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bambara/Latin/Mali
- { 188, 75, 132, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bambara/Nko/Mali
- { 189, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Embu/Latin/Kenya
- { 190, 12, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Cherokee/Cherokee/United States
- { 191, 7, 137, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Morisyen/Latin/Mauritius
- { 192, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Makonde/Latin/Tanzania
- { 193, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Langi/Latin/Tanzania
- { 194, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ganda/Latin/Uganda
- { 195, 7, 239, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bemba/Latin/Zambia
- { 196, 7, 39, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kabuverdianu/Latin/Cape Verde
- { 197, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Meru/Latin/Kenya
- { 198, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kalenjin/Latin/Kenya
- { 199, 7, 148, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nama/Latin/Namibia
- { 200, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Machame/Latin/Tanzania
- { 201, 7, 82, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Colognian/Latin/Germany
- { 202, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Masai/Latin/Kenya
- { 202, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Masai/Latin/Tanzania
- { 203, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Soga/Latin/Uganda
- { 204, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luyia/Latin/Kenya
- { 205, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Asu/Latin/Tanzania
- { 206, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Teso/Latin/Uganda
- { 206, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Teso/Latin/Kenya
- { 207, 7, 67, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Saho/Latin/Eritrea
- { 208, 7, 132, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Koyra Chiini/Latin/Mali
- { 209, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rwa/Latin/Tanzania
- { 210, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luo/Latin/Kenya
- { 211, 7, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chiga/Latin/Uganda
- { 212, 7, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Central Morocco Tamazight/Latin/Morocco
- { 213, 7, 132, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Koyraboro Senni/Latin/Mali
- { 214, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Shambala/Latin/Tanzania
- { 215, 13, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bodo/Devanagari/India
- { 218, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chechen/Cyrillic/Russia
- { 219, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Church/Cyrillic/Russia
- { 220, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chuvash/Cyrillic/Russia
- { 230, 7, 49, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luba Katanga/Latin/Congo Kinshasa
- { 231, 7, 125, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luxembourgish/Latin/Luxembourg
- { 236, 7, 21, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Walloon/Latin/Belgium
- { 237, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Aghem/Latin/Cameroon
- { 238, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Basaa/Latin/Cameroon
- { 239, 7, 156, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Zarma/Latin/Niger
- { 240, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Duala/Latin/Cameroon
- { 241, 7, 187, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Jola Fonyi/Latin/Senegal
- { 242, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ewondo/Latin/Cameroon
- { 243, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bafia/Latin/Cameroon
- { 244, 7, 146, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Makhuwa Meetto/Latin/Mozambique
- { 245, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mundang/Latin/Cameroon
- { 246, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kwasio/Latin/Cameroon
- { 247, 7, 254, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nuer/Latin/South Sudan
- { 248, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sakha/Cyrillic/Russia
- { 249, 7, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sangu/Latin/Tanzania
- { 251, 7, 156, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tasawaq/Latin/Niger
- { 252, 35, 121, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vai/Vai/Liberia
- { 252, 7, 121, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vai/Latin/Liberia
- { 253, 7, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Walser/Latin/Switzerland
- { 254, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yangben/Latin/Cameroon
- { 256, 7, 197, 0,10238, 106, 106, 184, 184,106,142, 78, 78, 26, 26 },// Asturian/Latin/Spain
- { 257, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ngomba/Latin/Cameroon
- { 258, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kako/Latin/Cameroon
- { 259, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Meta/Latin/Cameroon
- { 260, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ngiemboon/Latin/Cameroon
- { 261, 7, 197, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Aragonese/Latin/Spain
- { 272, 46, 18,10380,10380, 106, 106,10601,10601,221,221, 78, 78, 41, 41 },// Chakma/Chakma/Bangladesh
- { 272, 46, 100,10380,10380, 106, 106,10601,10601,221,221, 78, 78, 41, 41 },// Chakma/Chakma/India
- { 290, 11, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Manipuri/Bengali/India
- { 309, 100, 232, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tai Dam/Tai Viet/Vietnam
- { 312, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Akoose/Latin/Cameroon
- { 313, 7, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lakota/Latin/United States
- { 314, 9, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Standard Moroccan Tamazight/Tifinagh/Morocco
- { 315, 7, 43, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mapuche/Latin/Chile
- { 316, 1, 103, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Central Kurdish/Arabic/Iraq
- { 316, 1, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Central Kurdish/Arabic/Iran
- { 317, 7, 82, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lower Sorbian/Latin/Germany
- { 318, 7, 82, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Upper Sorbian/Latin/Germany
- { 319, 7, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kenyang/Latin/Cameroon
- { 320, 7, 38, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mohawk/Latin/Canada
- { 321, 75, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nko/Nko/Guinea
- { 322, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Prussian/Latin/World
- { 323, 7, 90, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kiche/Latin/Guatemala
- { 324, 7, 205, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Sami/Latin/Sweden
- { 325, 7, 205, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lule Sami/Latin/Sweden
- { 326, 7, 73, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Inari Sami/Latin/Finland
- { 327, 7, 73, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Skolt Sami/Latin/Finland
- { 328, 7, 13, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Warlpiri/Latin/Australia
- { 346, 1, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mazanderani/Arabic/Iran
- { 349, 1, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Luri/Arabic/Iran
- { 349, 1, 103, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Luri/Arabic/Iraq
- { 357, 6, 97, 888, 888, 888, 888, 184, 184, 71, 71, 71, 71, 26, 26 },// Cantonese/Traditional Han/Hong Kong
- { 357, 5, 44,10642,10642,10642,10642, 184, 184, 71, 71, 71, 71, 26, 26 },// Cantonese/Simplified Han/China
- { 358, 138, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Osage/Osage/United States
- { 360, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ido/Latin/World
- { 361, 7, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lojban/Latin/World
- { 362, 7, 106, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sicilian/Latin/Italy
- { 363, 1, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Kurdish/Arabic/Iran
- { 364, 1, 163, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Western Balochi/Arabic/Pakistan
- { 365, 7, 170, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Cebuano/Latin/Philippines
- { 366, 2, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Erzya/Cyrillic/Russia
- { 367, 7, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chickasaw/Latin/United States
- { 368, 7, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Muscogee/Latin/United States
- { 369, 7, 172, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Silesian/Latin/Poland
+ { 1, 0, 0, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// C/AnyScript/AnyTerritory
+ { 2, 27, 90, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Abkhazian/Cyrillic/Georgia
+ { 3, 66, 77, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afar/Latin/Ethiopia
+ { 3, 66, 67, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afar/Latin/Djibouti
+ { 3, 66, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afar/Latin/Eritrea
+ { 4, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afrikaans/Latin/South Africa
+ { 4, 66, 162, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Afrikaans/Latin/Namibia
+ { 5, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Aghem/Latin/Cameroon
+ { 6, 66, 92, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Akan/Latin/Ghana
+ { 8, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Akoose/Latin/Cameroon
+ { 9, 66, 3, 210, 325, 440, 519, 184, 184,115,115, 79, 79, 26, 26 },// Albanian/Latin/Albania
+ { 9, 66, 126, 210, 325, 440, 519, 184, 184,115,115, 79, 79, 26, 26 },// Albanian/Latin/Kosovo
+ { 9, 66, 140, 210, 325, 440, 519, 184, 184,115,115, 79, 79, 26, 26 },// Albanian/Latin/Macedonia
+ { 11, 33, 77, 598, 598, 106, 106, 184, 184, 74, 74, 78, 78, 26, 26 },// Amharic/Ethiopic/Ethiopia
+ { 14, 4, 71, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Egypt
+ { 14, 4, 4, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Algeria
+ { 14, 4, 19, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Bahrain
+ { 14, 4, 48, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Chad
+ { 14, 4, 55, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Comoros
+ { 14, 4, 67, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Djibouti
+ { 14, 4, 74, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Eritrea
+ { 14, 4, 113, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Iraq
+ { 14, 4, 116, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Israel
+ { 14, 4, 122, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Jordan
+ { 14, 4, 127, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Kuwait
+ { 14, 4, 132, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Lebanon
+ { 14, 4, 135, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Libya
+ { 14, 4, 149, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Mauritania
+ { 14, 4, 159, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Morocco
+ { 14, 4, 176, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Oman
+ { 14, 4, 180, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Palestinian Territories
+ { 14, 4, 190, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Qatar
+ { 14, 4, 205, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Saudi Arabia
+ { 14, 4, 215, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Somalia
+ { 14, 4, 219, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/South Sudan
+ { 14, 4, 222, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Sudan
+ { 14, 4, 227, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Syria
+ { 14, 4, 238, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Tunisia
+ { 14, 4, 245, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/United Arab Emirates
+ { 14, 4, 257, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Western Sahara
+ { 14, 4, 258, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/world
+ { 14, 4, 259, 672, 672, 672, 672, 768, 768, 96, 96, 96, 96, 26, 26 },// Arabic/Arabic/Yemen
+ { 15, 66, 220, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Aragonese/Latin/Spain
+ { 17, 5, 12, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Armenian/Armenian/Armenia
+ { 18, 9, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Assamese/Bangla/India
+ { 19, 66, 220, 0, 794, 106, 106, 184, 184,106,142, 78, 78, 26, 26 },// Asturian/Latin/Spain
+ { 20, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Asu/Latin/Tanzania
+ { 21, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Atsam/Latin/Nigeria
+ { 25, 66, 17, 936, 936, 1046, 1046, 184, 184,110,110, 71, 71, 26, 26 },// Azerbaijani/Latin/Azerbaijan
+ { 25, 4, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Azerbaijani/Arabic/Iran
+ { 25, 4, 113, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Azerbaijani/Arabic/Iraq
+ { 25, 4, 239, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Azerbaijani/Arabic/Turkey
+ { 25, 27, 17, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Azerbaijani/Cyrillic/Azerbaijan
+ { 26, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bafia/Latin/Cameroon
+ { 28, 66, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bambara/Latin/Mali
+ { 28, 90, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bambara/Nko/Mali
+ { 30, 9, 20, 1117, 1117, 1117, 1117, 1221, 1221,104,104,104,104, 26, 26 },// Bangla/Bangla/Bangladesh
+ { 30, 9, 110, 1117, 1117, 1117, 1117, 1221, 1221,104,104,104,104, 26, 26 },// Bangla/Bangla/India
+ { 31, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Basaa/Latin/Cameroon
+ { 32, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bashkir/Cyrillic/Russia
+ { 33, 66, 220, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Basque/Latin/Spain
+ { 35, 27, 22, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Belarusian/Cyrillic/Belarus
+ { 36, 66, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bemba/Latin/Zambia
+ { 37, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bena/Latin/Tanzania
+ { 38, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bhojpuri/Devanagari/India
+ { 40, 33, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Blin/Ethiopic/Eritrea
+ { 41, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Bodo/Devanagari/India
+ { 42, 66, 29, 1247, 1247, 1346, 1346, 184, 184, 99, 99, 74, 74, 26, 26 },// Bosnian/Latin/Bosnia and Herzegovina
+ { 42, 27, 29, 1420, 1510, 1607, 1607, 184, 184, 90, 97, 69, 69, 26, 26 },// Bosnian/Cyrillic/Bosnia and Herzegovina
+ { 43, 66, 84, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Breton/Latin/France
+ { 45, 27, 36, 1676, 1676, 106, 106, 184, 184, 96, 96, 78, 78, 26, 26 },// Bulgarian/Cyrillic/Bulgaria
+ { 46, 86, 161, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Burmese/Myanmar/Myanmar
+ { 47, 137, 107, 1772, 1772, 1772, 1772, 184, 184, 71, 71, 71, 71, 26, 26 },// Cantonese/Traditional Han/Hong Kong
+ { 47, 118, 50, 1843, 1843, 1843, 1843, 184, 184, 71, 71, 71, 71, 26, 26 },// Cantonese/Simplified Han/China
+ { 48, 66, 220, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/Spain
+ { 48, 66, 6, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/Andorra
+ { 48, 66, 84, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/France
+ { 48, 66, 117, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Catalan/Latin/Italy
+ { 49, 66, 185, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Cebuano/Latin/Philippines
+ { 50, 66, 159, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Central Atlas Tamazight/Latin/Morocco
+ { 51, 4, 113, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Central Kurdish/Arabic/Iraq
+ { 51, 4, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Central Kurdish/Arabic/Iran
+ { 52, 21, 20, 1914, 1914, 106, 106, 2135, 2135,221,221, 78, 78, 41, 41 },// Chakma/Chakma/Bangladesh
+ { 52, 21, 110, 1914, 1914, 106, 106, 2135, 2135,221,221, 78, 78, 41, 41 },// Chakma/Chakma/India
+ { 54, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chechen/Cyrillic/Russia
+ { 55, 23, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Cherokee/Cherokee/United States
+ { 56, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chickasaw/Latin/United States
+ { 57, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chiga/Latin/Uganda
+ { 58, 118, 50, 2176, 2176, 2213, 2213, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/China
+ { 58, 118, 107, 2176, 2176, 2213, 2213, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Hong Kong
+ { 58, 118, 139, 2176, 2176, 2213, 2213, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Macao
+ { 58, 118, 210, 2176, 2176, 2213, 2213, 184, 184, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Singapore
+ { 58, 137, 107, 1772, 1772, 1772, 1772, 184, 184, 71, 71, 71, 71, 26, 26 },// Chinese/Traditional Han/Hong Kong
+ { 58, 137, 139, 1772, 1772, 1772, 1772, 184, 184, 71, 71, 71, 71, 26, 26 },// Chinese/Traditional Han/Macao
+ { 58, 137, 228, 1772, 1772, 1772, 1772, 184, 184, 71, 71, 71, 71, 26, 26 },// Chinese/Traditional Han/Taiwan
+ { 59, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Church/Cyrillic/Russia
+ { 60, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Chuvash/Cyrillic/Russia
+ { 61, 66, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Colognian/Latin/Germany
+ { 63, 66, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Cornish/Latin/United Kingdom
+ { 64, 66, 84, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Corsican/Latin/France
+ { 66, 66, 60, 0, 0, 106, 106, 2251, 2251,106,106, 78, 78, 38, 38 },// Croatian/Latin/Croatia
+ { 66, 66, 29, 0, 0, 106, 106, 2251, 2251,106,106, 78, 78, 38, 38 },// Croatian/Latin/Bosnia and Herzegovina
+ { 67, 66, 64, 2289, 2289, 2418, 2418, 184, 184,129,129, 76, 76, 26, 26 },// Czech/Latin/Czechia
+ { 68, 66, 65, 2494, 2494, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Danish/Latin/Denmark
+ { 68, 66, 95, 2494, 2494, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Danish/Latin/Greenland
+ { 69, 132, 144, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Divehi/Thaana/Maldives
+ { 70, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Dogri/Devanagari/India
+ { 71, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Duala/Latin/Cameroon
+ { 72, 66, 165, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Netherlands
+ { 72, 66, 13, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Aruba
+ { 72, 66, 23, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Belgium
+ { 72, 66, 44, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Caribbean Netherlands
+ { 72, 66, 62, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Curacao
+ { 72, 66, 211, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Sint Maarten
+ { 72, 66, 223, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Dutch/Latin/Suriname
+ { 73, 134, 27, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Dzongkha/Tibetan/Bhutan
+ { 74, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Embu/Latin/Kenya
+ { 75, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United States
+ { 75, 28, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Deseret/United States
+ { 75, 66, 5, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/American Samoa
+ { 75, 66, 8, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Anguilla
+ { 75, 66, 10, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Antigua and Barbuda
+ { 75, 66, 15, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Australia
+ { 75, 66, 16, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Austria
+ { 75, 66, 18, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Bahamas
+ { 75, 66, 21, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Barbados
+ { 75, 66, 23, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Belgium
+ { 75, 66, 24, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Belize
+ { 75, 66, 26, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Bermuda
+ { 75, 66, 30, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Botswana
+ { 75, 66, 33, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/British Indian Ocean Territory
+ { 75, 66, 34, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/British Virgin Islands
+ { 75, 66, 38, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Burundi
+ { 75, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cameroon
+ { 75, 66, 41, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Canada
+ { 75, 66, 45, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cayman Islands
+ { 75, 66, 51, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Christmas Island
+ { 75, 66, 53, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cocos Islands
+ { 75, 66, 58, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cook Islands
+ { 75, 66, 63, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Cyprus
+ { 75, 66, 65, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Denmark
+ { 75, 66, 66, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Diego Garcia
+ { 75, 66, 68, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Dominica
+ { 75, 66, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Eritrea
+ { 75, 66, 76, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Eswatini
+ { 75, 66, 78, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Europe
+ { 75, 66, 80, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Falkland Islands
+ { 75, 66, 82, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Fiji
+ { 75, 66, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Finland
+ { 75, 66, 89, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Gambia
+ { 75, 66, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Germany
+ { 75, 66, 92, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Ghana
+ { 75, 66, 93, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Gibraltar
+ { 75, 66, 96, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Grenada
+ { 75, 66, 98, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Guam
+ { 75, 66, 100, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Guernsey
+ { 75, 66, 103, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Guyana
+ { 75, 66, 107, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Hong Kong
+ { 75, 66, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/India
+ { 75, 66, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Indonesia
+ { 75, 66, 114, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Ireland
+ { 75, 66, 115, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Isle of Man
+ { 75, 66, 116, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Israel
+ { 75, 66, 119, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Jamaica
+ { 75, 66, 121, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Jersey
+ { 75, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Kenya
+ { 75, 66, 125, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Kiribati
+ { 75, 66, 133, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Lesotho
+ { 75, 66, 134, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Liberia
+ { 75, 66, 139, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Macao
+ { 75, 66, 141, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Madagascar
+ { 75, 66, 142, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Malawi
+ { 75, 66, 143, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Malaysia
+ { 75, 66, 144, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Maldives
+ { 75, 66, 146, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Malta
+ { 75, 66, 147, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Marshall Islands
+ { 75, 66, 150, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Mauritius
+ { 75, 66, 153, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Micronesia
+ { 75, 66, 158, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Montserrat
+ { 75, 66, 162, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Namibia
+ { 75, 66, 163, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Nauru
+ { 75, 66, 165, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Netherlands
+ { 75, 66, 167, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/New Zealand
+ { 75, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Nigeria
+ { 75, 66, 171, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Niue
+ { 75, 66, 172, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Norfolk Island
+ { 75, 66, 173, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Northern Mariana Islands
+ { 75, 66, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Pakistan
+ { 75, 66, 179, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Palau
+ { 75, 66, 182, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Papua New Guinea
+ { 75, 66, 185, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Philippines
+ { 75, 66, 186, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Pitcairn
+ { 75, 66, 189, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Puerto Rico
+ { 75, 66, 194, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Rwanda
+ { 75, 66, 196, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Helena
+ { 75, 66, 197, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Kitts and Nevis
+ { 75, 66, 198, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Lucia
+ { 75, 66, 201, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Saint Vincent and Grenadines
+ { 75, 66, 202, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Samoa
+ { 75, 66, 208, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Seychelles
+ { 75, 66, 209, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sierra Leone
+ { 75, 66, 210, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Singapore
+ { 75, 66, 211, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sint Maarten
+ { 75, 66, 213, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Slovenia
+ { 75, 66, 214, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Solomon Islands
+ { 75, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/South Africa
+ { 75, 66, 219, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/South Sudan
+ { 75, 66, 222, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sudan
+ { 75, 66, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Sweden
+ { 75, 66, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Switzerland
+ { 75, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tanzania
+ { 75, 66, 234, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tokelau
+ { 75, 66, 235, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tonga
+ { 75, 66, 236, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Trinidad and Tobago
+ { 75, 66, 241, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Turks and Caicos Islands
+ { 75, 66, 242, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Tuvalu
+ { 75, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Uganda
+ { 75, 66, 245, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United Arab Emirates
+ { 75, 66, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United Kingdom
+ { 75, 66, 247, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United States Outlying Islands
+ { 75, 66, 249, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/United States Virgin Islands
+ { 75, 66, 252, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Vanuatu
+ { 75, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/world
+ { 75, 66, 260, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Zambia
+ { 75, 66, 261, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Latin/Zimbabwe
+ { 75, 115, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// English/Shavian/United Kingdom
+ { 76, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Erzya/Cyrillic/Russia
+ { 77, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Esperanto/Latin/world
+ { 78, 66, 75, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Estonian/Latin/Estonia
+ { 79, 66, 92, 2817, 2817, 2903, 2903, 184, 184, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Ghana
+ { 79, 66, 233, 2817, 2817, 2903, 2903, 184, 184, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Togo
+ { 80, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ewondo/Latin/Cameroon
+ { 81, 66, 81, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Faroese/Latin/Faroe Islands
+ { 81, 66, 65, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Faroese/Latin/Denmark
+ { 83, 66, 185, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Filipino/Latin/Philippines
+ { 84, 66, 83, 2950, 2950, 106, 106, 184, 184,129,129, 78, 78, 26, 26 },// Finnish/Latin/Finland
+ { 85, 66, 84, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/France
+ { 85, 66, 4, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Algeria
+ { 85, 66, 23, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Belgium
+ { 85, 66, 25, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Benin
+ { 85, 66, 37, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Burkina Faso
+ { 85, 66, 38, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Burundi
+ { 85, 66, 40, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Cameroon
+ { 85, 66, 41, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Canada
+ { 85, 66, 46, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Central African Republic
+ { 85, 66, 48, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Chad
+ { 85, 66, 55, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Comoros
+ { 85, 66, 56, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Congo - Brazzaville
+ { 85, 66, 57, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Congo - Kinshasa
+ { 85, 66, 67, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Djibouti
+ { 85, 66, 73, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Equatorial Guinea
+ { 85, 66, 85, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/French Guiana
+ { 85, 66, 86, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/French Polynesia
+ { 85, 66, 88, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Gabon
+ { 85, 66, 97, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Guadeloupe
+ { 85, 66, 102, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Guinea
+ { 85, 66, 104, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Haiti
+ { 85, 66, 118, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Ivory Coast
+ { 85, 66, 138, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Luxembourg
+ { 85, 66, 141, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Madagascar
+ { 85, 66, 145, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mali
+ { 85, 66, 148, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Martinique
+ { 85, 66, 149, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mauritania
+ { 85, 66, 150, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mauritius
+ { 85, 66, 151, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Mayotte
+ { 85, 66, 155, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Monaco
+ { 85, 66, 159, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Morocco
+ { 85, 66, 166, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/New Caledonia
+ { 85, 66, 170, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Niger
+ { 85, 66, 191, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Reunion
+ { 85, 66, 194, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Rwanda
+ { 85, 66, 195, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Saint Barthelemy
+ { 85, 66, 199, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Saint Martin
+ { 85, 66, 200, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Saint Pierre and Miquelon
+ { 85, 66, 206, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Senegal
+ { 85, 66, 208, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Seychelles
+ { 85, 66, 226, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Switzerland
+ { 85, 66, 227, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Syria
+ { 85, 66, 233, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Togo
+ { 85, 66, 238, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Tunisia
+ { 85, 66, 252, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Vanuatu
+ { 85, 66, 256, 3079, 3079, 3218, 3308, 184, 184,139,139, 90, 90, 26, 26 },// French/Latin/Wallis and Futuna
+ { 86, 66, 117, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Friulian/Latin/Italy
+ { 87, 66, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Senegal
+ { 87, 1, 37, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Burkina Faso
+ { 87, 1, 40, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Cameroon
+ { 87, 1, 89, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Gambia
+ { 87, 1, 92, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Ghana
+ { 87, 1, 101, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Guinea-Bissau
+ { 87, 1, 102, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Guinea
+ { 87, 1, 134, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Liberia
+ { 87, 1, 149, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Mauritania
+ { 87, 1, 169, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Nigeria
+ { 87, 1, 170, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Niger
+ { 87, 1, 206, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Senegal
+ { 87, 1, 209, 3398, 3398, 3651, 3651, 3746, 3746,253,253, 95, 95, 41, 41 },// Fulah/Adlam/Sierra Leone
+ { 87, 66, 37, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Burkina Faso
+ { 87, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Cameroon
+ { 87, 66, 89, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Gambia
+ { 87, 66, 92, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Ghana
+ { 87, 66, 101, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Guinea-Bissau
+ { 87, 66, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Guinea
+ { 87, 66, 134, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Liberia
+ { 87, 66, 149, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Mauritania
+ { 87, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Nigeria
+ { 87, 66, 170, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Niger
+ { 87, 66, 209, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Fulah/Latin/Sierra Leone
+ { 88, 66, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Gaelic/Latin/United Kingdom
+ { 89, 66, 92, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ga/Latin/Ghana
+ { 90, 66, 220, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Galician/Latin/Spain
+ { 91, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ganda/Latin/Uganda
+ { 92, 33, 77, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Geez/Ethiopic/Ethiopia
+ { 92, 33, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Geez/Ethiopic/Eritrea
+ { 93, 35, 90, 3787, 3787, 3911, 3911, 184, 184,124,124, 73, 73, 26, 26 },// Georgian/Georgian/Georgia
+ { 94, 66, 91, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Germany
+ { 94, 66, 16, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Austria
+ { 94, 66, 23, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Belgium
+ { 94, 66, 117, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Italy
+ { 94, 66, 136, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Liechtenstein
+ { 94, 66, 138, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Luxembourg
+ { 94, 66, 226, 3984, 3984, 106, 106, 184, 184,116,116, 78, 78, 26, 26 },// German/Latin/Switzerland
+ { 96, 39, 94, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Greek/Greek/Greece
+ { 96, 39, 63, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Greek/Greek/Cyprus
+ { 97, 66, 183, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Guarani/Latin/Paraguay
+ { 98, 40, 110, 4100, 4100, 4198, 4198, 184, 184, 98, 98, 74, 74, 26, 26 },// Gujarati/Gujarati/India
+ { 99, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Gusii/Latin/Kenya
+ { 101, 66, 169, 4272, 4272, 106, 106, 184, 184,107,107, 78, 78, 26, 26 },// Hausa/Latin/Nigeria
+ { 101, 4, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hausa/Arabic/Nigeria
+ { 101, 4, 222, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hausa/Arabic/Sudan
+ { 101, 66, 92, 4272, 4272, 106, 106, 184, 184,107,107, 78, 78, 26, 26 },// Hausa/Latin/Ghana
+ { 101, 66, 170, 4272, 4272, 106, 106, 184, 184,107,107, 78, 78, 26, 26 },// Hausa/Latin/Niger
+ { 102, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Hawaiian/Latin/United States
+ { 103, 47, 116, 4379, 4495, 4611, 4611, 184, 184,116,116, 95, 95, 26, 26 },// Hebrew/Hebrew/Israel
+ { 105, 29, 110, 4706, 4706, 106, 106, 184, 184,108,108, 78, 78, 26, 26 },// Hindi/Devanagari/India
+ { 105, 66, 110, 0, 4814, 106, 4944, 184, 184,106,130, 78, 63, 26, 26 },// Hindi/Latin/India
+ { 107, 66, 108, 5007, 5106, 5233, 5233, 184, 184, 99,127, 76, 76, 26, 26 },// Hungarian/Latin/Hungary
+ { 108, 66, 109, 2494, 2494, 5309, 5309, 184, 184,106,106, 78, 78, 26, 26 },// Icelandic/Latin/Iceland
+ { 109, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ido/Latin/world
+ { 110, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Igbo/Latin/Nigeria
+ { 111, 66, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Inari Sami/Latin/Finland
+ { 112, 66, 111, 5387, 5387, 5496, 5496, 184, 184,109,109, 86, 86, 26, 26 },// Indonesian/Latin/Indonesia
+ { 114, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Interlingua/Latin/world
+ { 115, 66, 75, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Interlingue/Latin/Estonia
+ { 116, 18, 41, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Inuktitut/Canadian Aboriginal/Canada
+ { 116, 66, 41, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Inuktitut/Latin/Canada
+ { 118, 66, 114, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Irish/Latin/Ireland
+ { 118, 66, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Irish/Latin/United Kingdom
+ { 119, 66, 117, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/Italy
+ { 119, 66, 203, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/San Marino
+ { 119, 66, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/Switzerland
+ { 119, 66, 253, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Italian/Latin/Vatican City
+ { 120, 53, 120, 5582, 5582, 5582, 5582, 184, 184, 97, 97, 97, 97, 26, 26 },// Japanese/Japanese/Japan
+ { 121, 66, 111, 5679, 5679, 5765, 5765, 184, 184, 86, 86, 72, 72, 26, 26 },// Javanese/Latin/Indonesia
+ { 122, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Jju/Latin/Nigeria
+ { 123, 66, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Jola-Fonyi/Latin/Senegal
+ { 124, 66, 43, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kabuverdianu/Latin/Cape Verde
+ { 125, 66, 4, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kabyle/Latin/Algeria
+ { 126, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kako/Latin/Cameroon
+ { 127, 66, 95, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kalaallisut/Latin/Greenland
+ { 128, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kalenjin/Latin/Kenya
+ { 129, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kamba/Latin/Kenya
+ { 130, 56, 110, 5837, 5837, 5937, 5937, 184, 184,100,100, 79, 79, 26, 26 },// Kannada/Kannada/India
+ { 132, 4, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kashmiri/Arabic/India
+ { 132, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kashmiri/Devanagari/India
+ { 133, 27, 123, 6016, 6016, 6139, 6213, 184, 184,123,123, 74, 62, 26, 26 },// Kazakh/Cyrillic/Kazakhstan
+ { 134, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kenyang/Latin/Cameroon
+ { 135, 60, 39, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Khmer/Khmer/Cambodia
+ { 136, 66, 99, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kiche/Latin/Guatemala
+ { 137, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kikuyu/Latin/Kenya
+ { 138, 66, 194, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kinyarwanda/Latin/Rwanda
+ { 141, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Konkani/Devanagari/India
+ { 142, 63, 218, 6275, 6275, 106, 106, 184, 184, 69, 69, 78, 78, 26, 26 },// Korean/Korean/South Korea
+ { 142, 63, 50, 6275, 6275, 106, 106, 184, 184, 69, 69, 78, 78, 26, 26 },// Korean/Korean/China
+ { 142, 63, 174, 6275, 6275, 106, 106, 184, 184, 69, 69, 78, 78, 26, 26 },// Korean/Korean/North Korea
+ { 144, 66, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Koyraboro Senni/Latin/Mali
+ { 145, 66, 145, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Koyra Chiini/Latin/Mali
+ { 146, 66, 134, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kpelle/Latin/Liberia
+ { 146, 66, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kpelle/Latin/Guinea
+ { 148, 66, 239, 6344, 6344, 6453, 6453, 184, 184,109,109, 79, 79, 26, 26 },// Kurdish/Latin/Turkey
+ { 149, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kwasio/Latin/Cameroon
+ { 150, 27, 128, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kyrgyz/Cyrillic/Kyrgyzstan
+ { 151, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lakota/Latin/United States
+ { 152, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Langi/Latin/Tanzania
+ { 153, 65, 129, 6532, 6532, 6627, 6702, 184, 184, 95, 95, 75, 77, 26, 26 },// Lao/Lao/Laos
+ { 154, 66, 253, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Latin/Latin/Vatican City
+ { 155, 66, 131, 6779, 6779, 106, 106, 184, 184,108,108, 78, 78, 26, 26 },// Latvian/Latin/Latvia
+ { 158, 66, 57, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Congo - Kinshasa
+ { 158, 66, 7, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Angola
+ { 158, 66, 46, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Central African Republic
+ { 158, 66, 56, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lingala/Latin/Congo - Brazzaville
+ { 160, 66, 137, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lithuanian/Latin/Lithuania
+ { 161, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lojban/Latin/world
+ { 162, 66, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lower Sorbian/Latin/Germany
+ { 163, 66, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Low German/Latin/Germany
+ { 163, 66, 165, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Low German/Latin/Netherlands
+ { 164, 66, 57, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luba-Katanga/Latin/Congo - Kinshasa
+ { 165, 66, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lule Sami/Latin/Sweden
+ { 165, 66, 175, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Lule Sami/Latin/Norway
+ { 166, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luo/Latin/Kenya
+ { 167, 66, 138, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luxembourgish/Latin/Luxembourg
+ { 168, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Luyia/Latin/Kenya
+ { 169, 27, 140, 6887, 6887, 6976, 6976, 184, 184, 89, 89, 71, 71, 26, 26 },// Macedonian/Cyrillic/Macedonia
+ { 170, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Machame/Latin/Tanzania
+ { 171, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Maithili/Devanagari/India
+ { 172, 66, 160, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Makhuwa-Meetto/Latin/Mozambique
+ { 173, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Makonde/Latin/Tanzania
+ { 174, 66, 141, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malagasy/Latin/Madagascar
+ { 175, 74, 110, 7047, 7149, 7251, 7251, 7348, 7348,102,102, 97, 97, 26, 26 },// Malayalam/Malayalam/India
+ { 176, 66, 143, 7374, 7374, 7483, 7483, 184, 184,109,109, 73, 73, 26, 26 },// Malay/Latin/Malaysia
+ { 176, 4, 35, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malay/Arabic/Brunei
+ { 176, 4, 143, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Malay/Arabic/Malaysia
+ { 176, 66, 35, 7374, 7374, 7483, 7483, 184, 184,109,109, 73, 73, 26, 26 },// Malay/Latin/Brunei
+ { 176, 66, 111, 7374, 7374, 7483, 7483, 184, 184,109,109, 73, 73, 26, 26 },// Malay/Latin/Indonesia
+ { 176, 66, 210, 7374, 7374, 7483, 7483, 184, 184,109,109, 73, 73, 26, 26 },// Malay/Latin/Singapore
+ { 177, 66, 146, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Maltese/Latin/Malta
+ { 179, 9, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Manipuri/Bangla/India
+ { 179, 78, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Manipuri/Meitei Mayek/India
+ { 180, 66, 115, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Manx/Latin/Isle of Man
+ { 181, 66, 167, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Maori/Latin/New Zealand
+ { 182, 66, 49, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mapuche/Latin/Chile
+ { 183, 29, 110, 7556, 7556, 7643, 7643, 7721, 7721, 87, 87, 78, 78, 26, 26 },// Marathi/Devanagari/India
+ { 185, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Masai/Latin/Kenya
+ { 185, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Masai/Latin/Tanzania
+ { 186, 4, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mazanderani/Arabic/Iran
+ { 188, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Meru/Latin/Kenya
+ { 189, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Meta/Latin/Cameroon
+ { 190, 66, 41, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mohawk/Latin/Canada
+ { 191, 27, 156, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mongolian/Cyrillic/Mongolia
+ { 191, 83, 50, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mongolian/Mongolian/China
+ { 191, 83, 156, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mongolian/Mongolian/Mongolia
+ { 192, 66, 150, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Morisyen/Latin/Mauritius
+ { 193, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Mundang/Latin/Cameroon
+ { 194, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Muscogee/Latin/United States
+ { 195, 66, 162, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nama/Latin/Namibia
+ { 197, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Navajo/Latin/United States
+ { 199, 29, 164, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nepali/Devanagari/Nepal
+ { 199, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nepali/Devanagari/India
+ { 201, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ngiemboon/Latin/Cameroon
+ { 202, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ngomba/Latin/Cameroon
+ { 203, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nigerian Pidgin/Latin/Nigeria
+ { 204, 90, 102, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nko/Nko/Guinea
+ { 205, 4, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Luri/Arabic/Iran
+ { 205, 4, 113, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Luri/Arabic/Iraq
+ { 206, 66, 175, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sami/Latin/Norway
+ { 206, 66, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sami/Latin/Finland
+ { 206, 66, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sami/Latin/Sweden
+ { 207, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Sotho/Latin/South Africa
+ { 208, 66, 261, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// North Ndebele/Latin/Zimbabwe
+ { 209, 66, 175, 7747, 7747, 7853, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Norwegian Bokmal/Latin/Norway
+ { 209, 66, 224, 7747, 7747, 7853, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Norwegian Bokmal/Latin/Svalbard and Jan Mayen
+ { 210, 66, 175, 7747, 7747, 7853, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Norwegian Nynorsk/Latin/Norway
+ { 211, 66, 219, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nuer/Latin/South Sudan
+ { 212, 66, 142, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nyanja/Latin/Malawi
+ { 213, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nyankole/Latin/Uganda
+ { 214, 66, 84, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Occitan/Latin/France
+ { 214, 66, 220, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Occitan/Latin/Spain
+ { 215, 91, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Odia/Odia/India
+ { 220, 66, 77, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Ethiopia
+ { 220, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Kenya
+ { 221, 101, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Osage/Osage/United States
+ { 222, 27, 90, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ossetic/Cyrillic/Georgia
+ { 222, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ossetic/Cyrillic/Russia
+ { 226, 66, 62, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Papiamento/Latin/Curacao
+ { 226, 66, 13, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Papiamento/Latin/Aruba
+ { 227, 4, 1, 8009, 8009, 8084, 8084, 184, 184, 75, 75, 73, 73, 26, 26 },// Pashto/Arabic/Afghanistan
+ { 227, 4, 178, 8157, 8157, 8084, 8084, 184, 184, 80, 80, 73, 73, 26, 26 },// Pashto/Arabic/Pakistan
+ { 228, 4, 112, 8237, 8237, 8237, 8237, 8327, 8327, 90, 90, 90, 90, 23, 23 },// Persian/Arabic/Iran
+ { 228, 4, 1, 8237, 8237, 8237, 8237, 8327, 8327, 90, 90, 90, 90, 23, 23 },// Persian/Arabic/Afghanistan
+ { 230, 66, 187, 8350, 8350, 8457, 8457, 184, 184,107,107, 77, 77, 26, 26 },// Polish/Latin/Poland
+ { 231, 66, 32, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Brazil
+ { 231, 66, 7, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Angola
+ { 231, 66, 43, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Cape Verde
+ { 231, 66, 73, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Equatorial Guinea
+ { 231, 66, 101, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Guinea-Bissau
+ { 231, 66, 138, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Luxembourg
+ { 231, 66, 139, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Macao
+ { 231, 66, 160, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Mozambique
+ { 231, 66, 188, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Portugal
+ { 231, 66, 204, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Sao Tome and Principe
+ { 231, 66, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Switzerland
+ { 231, 66, 232, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Portuguese/Latin/Timor-Leste
+ { 232, 66, 187, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Prussian/Latin/Poland
+ { 233, 41, 110, 8534, 8626, 8720, 8720, 184, 184, 92, 94, 77, 77, 26, 26 },// Punjabi/Gurmukhi/India
+ { 233, 4, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Punjabi/Arabic/Pakistan
+ { 234, 66, 184, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Quechua/Latin/Peru
+ { 234, 66, 28, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Quechua/Latin/Bolivia
+ { 234, 66, 70, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Quechua/Latin/Ecuador
+ { 235, 66, 192, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Romanian/Latin/Romania
+ { 235, 66, 154, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Romanian/Latin/Moldova
+ { 236, 66, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Romansh/Latin/Switzerland
+ { 237, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rombo/Latin/Tanzania
+ { 238, 66, 38, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rundi/Latin/Burundi
+ { 239, 27, 193, 8797, 8797, 8928, 8928, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Russia
+ { 239, 27, 22, 8797, 8797, 8928, 8928, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Belarus
+ { 239, 27, 123, 8797, 8797, 8928, 8928, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Kazakhstan
+ { 239, 27, 128, 8797, 8797, 8928, 8928, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Kyrgyzstan
+ { 239, 27, 154, 8797, 8797, 8928, 8928, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Moldova
+ { 239, 27, 244, 8797, 8797, 8928, 8928, 184, 184,131,131, 79, 79, 26, 26 },// Russian/Cyrillic/Ukraine
+ { 240, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rwa/Latin/Tanzania
+ { 241, 66, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Saho/Latin/Eritrea
+ { 242, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sakha/Cyrillic/Russia
+ { 243, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Samburu/Latin/Kenya
+ { 245, 66, 46, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sango/Latin/Central African Republic
+ { 246, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sangu/Latin/Tanzania
+ { 247, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sanskrit/Devanagari/India
+ { 248, 93, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Santali/Ol Chiki/India
+ { 248, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Santali/Devanagari/India
+ { 249, 66, 117, 9007, 9007, 7931, 7931, 184, 184,105,105, 78, 78, 26, 26 },// Sardinian/Latin/Italy
+ { 251, 66, 160, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sena/Latin/Mozambique
+ { 252, 27, 207, 1420, 9112, 1607, 1607, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Serbia
+ { 252, 27, 29, 1420, 9112, 1607, 1607, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Bosnia and Herzegovina
+ { 252, 27, 126, 1420, 9112, 1607, 1607, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Kosovo
+ { 252, 27, 157, 1420, 9112, 1607, 1607, 184, 184, 90, 97, 69, 69, 26, 26 },// Serbian/Cyrillic/Montenegro
+ { 252, 66, 29, 9209, 9303, 9400, 9400, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Bosnia and Herzegovina
+ { 252, 66, 126, 9209, 9303, 9400, 9400, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Kosovo
+ { 252, 66, 157, 9209, 9303, 9400, 9400, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Montenegro
+ { 252, 66, 207, 9209, 9303, 9400, 9400, 184, 184, 94, 97, 72, 72, 26, 26 },// Serbian/Latin/Serbia
+ { 253, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Shambala/Latin/Tanzania
+ { 254, 66, 261, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Shona/Latin/Zimbabwe
+ { 255, 141, 50, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sichuan Yi/Yi/China
+ { 256, 66, 117, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sicilian/Latin/Italy
+ { 257, 66, 77, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sidamo/Latin/Ethiopia
+ { 258, 66, 187, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Silesian/Latin/Poland
+ { 259, 4, 178, 9472, 9472, 9472, 9472, 184, 184, 91, 91, 91, 91, 26, 26 },// Sindhi/Arabic/Pakistan
+ { 259, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sindhi/Devanagari/India
+ { 260, 119, 221, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sinhala/Sinhala/Sri Lanka
+ { 261, 66, 83, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Skolt Sami/Latin/Finland
+ { 262, 66, 212, 9563, 9563, 9698, 9698, 184, 184,135,135, 78, 78, 26, 26 },// Slovak/Latin/Slovakia
+ { 263, 66, 213, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Slovenian/Latin/Slovenia
+ { 264, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Soga/Latin/Uganda
+ { 265, 66, 215, 9776, 9907,10037,10111, 184, 184,131,130, 74, 81, 26, 26 },// Somali/Latin/Somalia
+ { 265, 66, 67, 9776, 9907,10037,10111, 184, 184,131,130, 74, 81, 26, 26 },// Somali/Latin/Djibouti
+ { 265, 66, 77, 9776, 9907,10037,10111, 184, 184,131,130, 74, 81, 26, 26 },// Somali/Latin/Ethiopia
+ { 265, 66, 124, 9776, 9907,10037,10111, 184, 184,131,130, 74, 81, 26, 26 },// Somali/Latin/Kenya
+ { 266, 4, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Kurdish/Arabic/Iran
+ { 266, 4, 113, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Kurdish/Arabic/Iraq
+ { 267, 66, 225, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Sami/Latin/Sweden
+ { 267, 66, 175, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Sami/Latin/Norway
+ { 268, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Sotho/Latin/South Africa
+ { 268, 66, 133, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Southern Sotho/Latin/Lesotho
+ { 269, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// South Ndebele/Latin/South Africa
+ { 270, 66, 220,10192,10192, 7931, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Spain
+ { 270, 66, 11, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Argentina
+ { 270, 66, 24, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Belize
+ { 270, 66, 28, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Bolivia
+ { 270, 66, 32, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Brazil
+ { 270, 66, 42,10192,10192, 7931, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Canary Islands
+ { 270, 66, 47,10192,10192, 7931, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Ceuta and Melilla
+ { 270, 66, 49, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Chile
+ { 270, 66, 54, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Colombia
+ { 270, 66, 59, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Costa Rica
+ { 270, 66, 61, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Cuba
+ { 270, 66, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Dominican Republic
+ { 270, 66, 70, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Ecuador
+ { 270, 66, 72, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/El Salvador
+ { 270, 66, 73,10192,10192, 7931, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Equatorial Guinea
+ { 270, 66, 99, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Guatemala
+ { 270, 66, 106, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Honduras
+ { 270, 66, 130, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Latin America
+ { 270, 66, 152, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Mexico
+ { 270, 66, 168, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Nicaragua
+ { 270, 66, 181, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Panama
+ { 270, 66, 183, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Paraguay
+ { 270, 66, 184, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Peru
+ { 270, 66, 185,10192,10192, 7931, 7931, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Philippines
+ { 270, 66, 189, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Puerto Rico
+ { 270, 66, 248, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/United States
+ { 270, 66, 250, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Uruguay
+ { 270, 66, 254, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Spanish/Latin/Venezuela
+ { 271, 135, 159, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Standard Moroccan Tamazight/Tifinagh/Morocco
+ { 272, 66, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Sundanese/Latin/Indonesia
+ { 273, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Tanzania
+ { 273, 66, 57, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Congo - Kinshasa
+ { 273, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Kenya
+ { 273, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swahili/Latin/Uganda
+ { 274, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swati/Latin/South Africa
+ { 274, 66, 76, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swati/Latin/Eswatini
+ { 275, 66, 225,10298,10425, 106, 106, 184, 184,127,127, 78, 78, 26, 26 },// Swedish/Latin/Sweden
+ { 275, 66, 2,10298,10425, 106, 106, 184, 184,127,127, 78, 78, 26, 26 },// Swedish/Latin/Aland Islands
+ { 275, 66, 83,10298,10425, 106, 106, 184, 184,127,127, 78, 78, 26, 26 },// Swedish/Latin/Finland
+ { 276, 66, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swiss German/Latin/Switzerland
+ { 276, 66, 84, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swiss German/Latin/France
+ { 276, 66, 136, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Swiss German/Latin/Liechtenstein
+ { 277, 123, 113, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Syriac/Syriac/Iraq
+ { 277, 123, 227, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Syriac/Syriac/Syria
+ { 278, 135, 159, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tachelhit/Tifinagh/Morocco
+ { 278, 66, 159, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tachelhit/Latin/Morocco
+ { 280, 127, 255, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tai Dam/Tai Viet/Vietnam
+ { 281, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Taita/Latin/Kenya
+ { 282, 27, 229,10552,10662,10772,10772, 184, 184,110,110, 74, 74, 26, 26 },// Tajik/Cyrillic/Tajikistan
+ { 283, 129, 110,10846,10846,10937,10937, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/India
+ { 283, 129, 143,10846,10846,10937,10937, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/Malaysia
+ { 283, 129, 210,10846,10846,10937,10937, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/Singapore
+ { 283, 129, 221,10846,10846,10937,10937, 184, 184, 91, 91, 72, 72, 26, 26 },// Tamil/Tamil/Sri Lanka
+ { 284, 66, 228, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Taroko/Latin/Taiwan
+ { 285, 66, 170, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tasawaq/Latin/Niger
+ { 286, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tatar/Cyrillic/Russia
+ { 287, 131, 110,11009, 0,11104,11104, 184, 184, 95,106, 74, 74, 26, 26 },// Telugu/Telugu/India
+ { 288, 66, 243, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Teso/Latin/Uganda
+ { 288, 66, 124, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Teso/Latin/Kenya
+ { 289, 133, 231,11178,11178,11280,11280, 184, 184,102,102, 89, 89, 26, 26 },// Thai/Thai/Thailand
+ { 290, 134, 50, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tibetan/Tibetan/China
+ { 290, 134, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tibetan/Tibetan/India
+ { 291, 33, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tigre/Ethiopic/Eritrea
+ { 292, 33, 77, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tigrinya/Ethiopic/Ethiopia
+ { 292, 33, 74, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tigrinya/Ethiopic/Eritrea
+ { 294, 66, 182, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tok Pisin/Latin/Papua New Guinea
+ { 295, 66, 235,11369,11369,11468,11468, 184, 184, 99, 99, 60, 60, 26, 26 },// Tongan/Latin/Tonga
+ { 296, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tsonga/Latin/South Africa
+ { 297, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tswana/Latin/South Africa
+ { 297, 66, 30, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tswana/Latin/Botswana
+ { 298, 66, 239,11528,11528,11638,11638, 184, 184,110,110, 83, 83, 26, 26 },// Turkish/Latin/Turkey
+ { 298, 66, 63,11528,11528,11638,11638, 184, 184,110,110, 83, 83, 26, 26 },// Turkish/Latin/Cyprus
+ { 299, 66, 240,11721,11721,11834,11834, 184, 184,113,113, 59, 59, 26, 26 },// Turkmen/Latin/Turkmenistan
+ { 301, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Tyap/Latin/Nigeria
+ { 303, 27, 244,11893,11893,11996,12067, 184, 184,103,103, 71, 81, 26, 26 },// Ukrainian/Cyrillic/Ukraine
+ { 304, 66, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Upper Sorbian/Latin/Germany
+ { 305, 4, 178,12148,12148,12244,12342, 184, 184, 96, 96, 98, 96, 26, 26 },// Urdu/Arabic/Pakistan
+ { 305, 4, 110,12148,12148,12244,12342, 184, 184, 96, 96, 98, 96, 26, 26 },// Urdu/Arabic/India
+ { 306, 4, 50,12438,12438,12438,12438, 184, 184,118,118,118,118, 26, 26 },// Uyghur/Arabic/China
+ { 307, 66, 251,12556,12556,12678,12678, 184, 184,122,122, 82, 82, 26, 26 },// Uzbek/Latin/Uzbekistan
+ { 307, 4, 1, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Uzbek/Arabic/Afghanistan
+ { 307, 27, 251,12760,12760, 106, 106, 184, 184,114,114, 78, 78, 26, 26 },// Uzbek/Cyrillic/Uzbekistan
+ { 308, 139, 134, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vai/Vai/Liberia
+ { 308, 66, 134, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vai/Latin/Liberia
+ { 309, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Venda/Latin/South Africa
+ { 310, 66, 255, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vietnamese/Latin/Vietnam
+ { 311, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Volapuk/Latin/world
+ { 312, 66, 230, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Vunjo/Latin/Tanzania
+ { 313, 66, 23, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Walloon/Latin/Belgium
+ { 314, 66, 226, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Walser/Latin/Switzerland
+ { 315, 66, 15, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Warlpiri/Latin/Australia
+ { 316, 66, 246, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Welsh/Latin/United Kingdom
+ { 317, 4, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Western Balochi/Arabic/Pakistan
+ { 317, 4, 1, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Western Balochi/Arabic/Afghanistan
+ { 317, 4, 112, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Western Balochi/Arabic/Iran
+ { 317, 4, 176, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Western Balochi/Arabic/Oman
+ { 317, 4, 245, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Western Balochi/Arabic/United Arab Emirates
+ { 318, 66, 165, 2600, 2600, 2734, 2734, 184, 184,134,134, 83, 83, 26, 26 },// Western Frisian/Latin/Netherlands
+ { 319, 33, 77, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Wolaytta/Ethiopic/Ethiopia
+ { 320, 66, 206, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Wolof/Latin/Senegal
+ { 321, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Xhosa/Latin/South Africa
+ { 322, 66, 40, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yangben/Latin/Cameroon
+ { 323, 47, 244, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yiddish/Hebrew/Ukraine
+ { 324, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yoruba/Latin/Nigeria
+ { 324, 66, 25, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Yoruba/Latin/Benin
+ { 325, 66, 170, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Zarma/Latin/Niger
+ { 326, 66, 50, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Zhuang/Latin/China
+ { 327, 66, 216, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Zulu/Latin/South Africa
+ { 328, 66, 32, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kaingang/Latin/Brazil
+ { 329, 66, 32, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nheengatu/Latin/Brazil
+ { 329, 66, 54, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nheengatu/Latin/Colombia
+ { 329, 66, 254, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Nheengatu/Latin/Venezuela
+ { 330, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Haryanvi/Devanagari/India
+ { 331, 66, 91, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Northern Frisian/Latin/Germany
+ { 332, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rajasthani/Devanagari/India
+ { 333, 27, 193, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Moksha/Cyrillic/Russia
+ { 334, 66, 258, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Toki Pona/Latin/world
+ { 335, 66, 214, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Pijin/Latin/Solomon Islands
+ { 336, 66, 169, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Obolo/Latin/Nigeria
+ { 337, 4, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Baluchi/Arabic/Pakistan
+ { 337, 66, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Baluchi/Latin/Pakistan
+ { 338, 66, 117, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Ligurian/Latin/Italy
+ { 339, 142, 161, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rohingya/Hanifi/Myanmar
+ { 339, 142, 20, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Rohingya/Hanifi/Bangladesh
+ { 340, 4, 178, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Torwali/Arabic/Pakistan
+ { 341, 66, 25, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Anii/Latin/Benin
+ { 342, 29, 110, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Kangri/Devanagari/India
+ { 343, 66, 117, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Venetian/Latin/Italy
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },// trailing zeros
};
-static const char16_t months_data[] = {
-0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb,
-0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61,
-0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c,
-0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d,
-0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e,
-0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x4a, 0x75,
-0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e,
-0x3b, 0x53, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb,
-0x6c, 0x2d, 0x48, 0x2e, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38, 0x3b,
-0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x1219, 0x1200, 0x1228, 0x121d, 0x3b, 0x1233, 0x1348, 0x122d, 0x3b, 0x1228,
-0x1262, 0x12d1, 0x120d, 0x20, 0x12a0, 0x12c8, 0x120d, 0x3b, 0x1228, 0x1262, 0x12d1, 0x120d, 0x20, 0x12a0, 0x12ba, 0x122d, 0x3b, 0x1300, 0x121b, 0x12f0,
-0x120d, 0x20, 0x12a0, 0x12c8, 0x120d, 0x3b, 0x1300, 0x121b, 0x12f0, 0x120d, 0x20, 0x12a0, 0x12ba, 0x122d, 0x3b, 0x1228, 0x1300, 0x1265, 0x3b, 0x123b,
-0x12a5, 0x1263, 0x1295, 0x3b, 0x1228, 0x1218, 0x12f3, 0x1295, 0x3b, 0x1238, 0x12cb, 0x120d, 0x3b, 0x12d9, 0x120d, 0x1242, 0x12f3, 0x1205, 0x3b, 0x12d9,
-0x120d, 0x1202, 0x1303, 0x1205, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x627, 0x644,
-0x623, 0x648, 0x644, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x627, 0x644, 0x622, 0x62e, 0x631, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x649,
-0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x649, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x649, 0x20, 0x627, 0x644, 0x622, 0x62e, 0x631, 0x629,
-0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627,
-0x644, 0x3b, 0x630, 0x648, 0x20, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x629, 0x3b, 0x630, 0x648, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x629,
-0x661, 0x3b, 0x662, 0x3b, 0x663, 0x3b, 0x664, 0x3b, 0x665, 0x3b, 0x666, 0x3b, 0x667, 0x3b, 0x668, 0x3b, 0x669, 0x3b, 0x661, 0x660,
-0x3b, 0x661, 0x661, 0x3b, 0x661, 0x662, 0x4d, 0x259, 0x68, 0x259, 0x72, 0x72, 0x259, 0x6d, 0x3b, 0x53, 0x259, 0x66, 0x259, 0x72,
-0x3b, 0x52, 0x259, 0x62, 0x69, 0xfc, 0x6c, 0x259, 0x76, 0x76, 0x259, 0x6c, 0x3b, 0x52, 0x259, 0x62, 0x69, 0xfc, 0x6c, 0x61,
-0x78, 0x131, 0x72, 0x3b, 0x43, 0x259, 0x6d, 0x61, 0x64, 0x69, 0x79, 0x259, 0x6c, 0x259, 0x76, 0x76, 0x259, 0x6c, 0x3b, 0x43,
-0x259, 0x6d, 0x61, 0x64, 0x69, 0x79, 0x259, 0x6c, 0x61, 0x78, 0x131, 0x72, 0x3b, 0x52, 0x259, 0x63, 0x259, 0x62, 0x3b, 0x15e,
-0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a, 0x61, 0x6e, 0x3b, 0x15e, 0x259, 0x76, 0x76, 0x61, 0x6c, 0x3b,
-0x5a, 0x69, 0x6c, 0x71, 0x259, 0x64, 0x259, 0x3b, 0x5a, 0x69, 0x6c, 0x68, 0x69, 0x63, 0x63, 0x259, 0x4d, 0x259, 0x68, 0x2e,
-0x3b, 0x53, 0x259, 0x66, 0x2e, 0x3b, 0x52, 0x259, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x52, 0x259, 0x62, 0x2e, 0x20, 0x49, 0x49,
-0x3b, 0x43, 0x259, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x43, 0x259, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x259, 0x63, 0x2e,
-0x3b, 0x15e, 0x61, 0x62, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x15e, 0x259, 0x76, 0x2e, 0x3b, 0x5a, 0x69, 0x6c, 0x71,
-0x2e, 0x3b, 0x5a, 0x69, 0x6c, 0x68, 0x2e, 0x9ae, 0x9b9, 0x9b0, 0x9b0, 0x9ae, 0x3b, 0x9b8, 0x9ab, 0x9b0, 0x3b, 0x9b0, 0x9ac, 0x9bf,
-0x989, 0x9b2, 0x20, 0x986, 0x989, 0x9af, 0x9bc, 0x9be, 0x9b2, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x989, 0x9b8, 0x20, 0x9b8, 0x9be, 0x9a8, 0x9bf,
-0x3b, 0x99c, 0x9ae, 0x9be, 0x9a6, 0x9bf, 0x989, 0x9b2, 0x20, 0x986, 0x989, 0x9af, 0x9bc, 0x9be, 0x9b2, 0x3b, 0x99c, 0x9ae, 0x9be, 0x9a6,
-0x9bf, 0x989, 0x9b8, 0x20, 0x9b8, 0x9be, 0x9a8, 0x9bf, 0x3b, 0x9b0, 0x99c, 0x9ac, 0x3b, 0x9b6, 0x9be, 0x2018, 0x9ac, 0x9be, 0x9a8, 0x3b,
-0x9b0, 0x9ae, 0x99c, 0x9be, 0x9a8, 0x3b, 0x9b6, 0x9be, 0x993, 0x9af, 0x9bc, 0x9be, 0x9b2, 0x3b, 0x99c, 0x9cd, 0x9ac, 0x9bf, 0x9b2, 0x995,
-0x9a6, 0x3b, 0x99c, 0x9cd, 0x9ac, 0x9bf, 0x9b2, 0x9b9, 0x99c, 0x9cd, 0x99c, 0x9e7, 0x3b, 0x9e8, 0x3b, 0x9e9, 0x3b, 0x9ea, 0x3b, 0x9eb,
-0x3b, 0x9ec, 0x3b, 0x9ed, 0x3b, 0x9ee, 0x3b, 0x9ef, 0x3b, 0x9e7, 0x9e6, 0x3b, 0x9e7, 0x9e7, 0x3b, 0x9e7, 0x9e8, 0x43c, 0x443, 0x445,
-0x430, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x440, 0x430, 0x431, 0x438, 0x2d, 0x31, 0x3b, 0x440, 0x430,
-0x431, 0x438, 0x2d, 0x32, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x2d, 0x31, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430,
-0x434, 0x430, 0x2d, 0x32, 0x3b, 0x440, 0x430, 0x434, 0x436, 0x430, 0x431, 0x3b, 0x448, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430,
-0x43c, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x430, 0x43b, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d, 0x41a, 0x430, 0x430,
-0x434, 0x430, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d, 0x445, 0x438, 0x434, 0x436, 0x430, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b, 0x4e09,
-0x6708, 0x3b, 0x56db, 0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b, 0x4e5d, 0x6708, 0x3b,
-0x5341, 0x6708, 0x3b, 0x5341, 0x4e00, 0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34,
-0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708,
-0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x7a46, 0x54c8, 0x862d, 0x59c6, 0x6708, 0x3b, 0x8272, 0x6cd5, 0x723e, 0x6708, 0x3b, 0x8cf4,
-0x6bd4, 0x6708, 0x20, 0x49, 0x3b, 0x8cf4, 0x6bd4, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x4e3b, 0x99ac, 0x9054, 0x6708, 0x20, 0x49, 0x3b, 0x4e3b,
-0x99ac, 0x9054, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x8cf4, 0x54f2, 0x535c, 0x6708, 0x3b, 0x820d, 0x723e, 0x90a6, 0x6708, 0x3b, 0x8cf4, 0x8cb7, 0x4e39,
-0x6708, 0x3b, 0x9583, 0x74e6, 0x9b6f, 0x6708, 0x3b, 0x90fd, 0x723e, 0x5580, 0x723e, 0x5fb7, 0x6708, 0x3b, 0x90fd, 0x723e, 0x9ed1, 0x54f2, 0x6708, 0x31,
-0x2e, 0x3b, 0x32, 0x2e, 0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e, 0x3b, 0x37, 0x2e, 0x3b,
-0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30, 0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e, 0x6d, 0x75, 0x68,
-0x61, 0x72, 0x72, 0x65, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x65, 0x62, 0xed, 0x2019, 0x75, 0x20, 0x6c,
-0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x72, 0x65, 0x62, 0xed, 0x2019, 0x75, 0x20, 0x73, 0x2d, 0x73, 0xe1, 0x6e, 0xed,
-0x3b, 0x64, 0x17e, 0x75, 0x6d, 0xe1, 0x64, 0xe1, 0x20, 0x61, 0x6c, 0x2d, 0xfa, 0x6c, 0xe1, 0x3b, 0x64, 0x17e, 0x75, 0x6d,
-0xe1, 0x64, 0xe1, 0x20, 0x61, 0x6c, 0x2d, 0xe1, 0x63, 0x68, 0x69, 0x72, 0x61, 0x3b, 0x72, 0x65, 0x64, 0x17e, 0x65, 0x62,
-0x3b, 0x161, 0x61, 0x2019, 0x62, 0xe1, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x161, 0x61, 0x77, 0x77,
-0x61, 0x6c, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d, 0x6b, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d, 0x68,
-0x69, 0x64, 0x17e, 0x64, 0x17e, 0x61, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x65, 0x62, 0x2e,
-0x20, 0x49, 0x3b, 0x72, 0x65, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x64,
-0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x65, 0x64, 0x2e, 0x3b, 0x161, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d,
-0x2e, 0x3b, 0x161, 0x61, 0x77, 0x2e, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d,
-0x68, 0x2e, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62,
-0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61,
-0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x73,
-0x68, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x77,
-0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb,
-0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x6f, 0x65, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61,
-0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x61, 0x20, 0x61, 0x6c, 0x20, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x52,
-0x61, 0x62, 0x69, 0x2bb, 0x61, 0x20, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b, 0x4a, 0x6f, 0x65, 0x6d, 0x61,
-0x64, 0x2bb, 0x61, 0x6c, 0x20, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x4a, 0x6f, 0x65, 0x6d, 0x61, 0x64, 0x2bb, 0x61, 0x6c, 0x20,
-0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x6a, 0x61, 0x2bb, 0x61, 0x62, 0x61, 0x6e,
-0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x6a, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x6f, 0x65, 0x20,
-0x61, 0x6c, 0x20, 0x6b, 0x61, 0x2bb, 0x61, 0x62, 0x61, 0x3b, 0x44, 0x6f, 0x65, 0x20, 0x61, 0x6c, 0x20, 0x68, 0x69, 0x7a,
-0x6a, 0x61, 0x4d, 0x6f, 0x65, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b,
-0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x6f, 0x65, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x4a, 0x6f, 0x65, 0x6d,
-0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x6a, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b,
-0x53, 0x6a, 0x61, 0x77, 0x2e, 0x3b, 0x44, 0x6f, 0x65, 0x20, 0x61, 0x6c, 0x20, 0x6b, 0x2e, 0x3b, 0x44, 0x6f, 0x65, 0x20,
-0x61, 0x6c, 0x20, 0x68, 0x2e, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b,
-0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2019,
-0x20, 0x61, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d,
-0x75, 0x6c, 0x61, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x61,
-0x3b, 0x72, 0x61, 0x64, 0x17e, 0x61, 0x62, 0x3b, 0x161, 0x61, 0x2019, 0x62, 0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64,
-0x61, 0x6e, 0x3b, 0x161, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x71, 0x61, 0x2019, 0x64,
-0x61, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x68, 0x69, 0x64, 0x64, 0x17e, 0x61, 0x6d, 0x6f, 0x75, 0x68, 0x61, 0x72,
-0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x61, 0x20, 0x61, 0x6c, 0x20, 0x61,
-0x77, 0x61, 0x6c, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x61, 0x20, 0x61, 0x74, 0x68, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b,
-0x6a, 0x6f, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x6c, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6d,
-0x61, 0x64, 0x61, 0x20, 0x61, 0x74, 0x68, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62,
-0x3b, 0x63, 0x68, 0x61, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x63, 0x68,
-0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x20, 0x71, 0x69, 0x60, 0x64, 0x61, 0x3b,
-0x64, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61, 0x6d, 0x6f, 0x75, 0x68, 0x2e, 0x3b, 0x73,
-0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x61, 0x77, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x74, 0x68,
-0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x6f, 0x75, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x74, 0x68,
-0x2e, 0x3b, 0x72, 0x61, 0x6a, 0x2e, 0x3b, 0x63, 0x68, 0x61, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x63, 0x68,
-0x61, 0x77, 0x2e, 0x3b, 0x64, 0x68, 0x6f, 0x75, 0x2e, 0x20, 0x71, 0x69, 0x2e, 0x3b, 0x64, 0x68, 0x6f, 0x75, 0x2e, 0x20,
-0x68, 0x69, 0x2e, 0x6d, 0x6f, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x61,
-0x77, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x74, 0x68, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x6f, 0x75,
-0x6c, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x74, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6a, 0x2e, 0x3b, 0x63,
-0x68, 0x61, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x63, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x64, 0x68, 0x6f, 0x75,
-0x2e, 0x20, 0x71, 0x2e, 0x3b, 0x64, 0x68, 0x6f, 0x75, 0x2e, 0x20, 0x68, 0x2e, 0x10db, 0x10e3, 0x10f0, 0x10d0, 0x10e0, 0x10d0, 0x10db,
-0x10d8, 0x3b, 0x10e1, 0x10d0, 0x10e4, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10e0, 0x10d0, 0x10d1, 0x10d8, 0x20, 0x10e3, 0x10da, 0x2d, 0x10d0, 0x10d5, 0x10d0,
-0x10da, 0x10d8, 0x3b, 0x10e0, 0x10d0, 0x10d1, 0x10d8, 0x20, 0x10e3, 0x10da, 0x2d, 0x10d0, 0x10ee, 0x10d8, 0x10e0, 0x10d8, 0x3b, 0x10ef, 0x10e3, 0x10db,
-0x10d0, 0x10d3, 0x10d0, 0x20, 0x10e3, 0x10da, 0x2d, 0x10d0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10ef, 0x10e3, 0x10db, 0x10d0, 0x10d3, 0x10d0, 0x20,
-0x10e3, 0x10da, 0x2d, 0x10d0, 0x10ee, 0x10d8, 0x10e0, 0x10d8, 0x3b, 0x10e0, 0x10d0, 0x10ef, 0x10d0, 0x10d1, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d0,
-0x10dc, 0x10d8, 0x3b, 0x10e0, 0x10d0, 0x10db, 0x10d0, 0x10d3, 0x10d0, 0x10dc, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10d6,
-0x10e3, 0x10da, 0x2d, 0x10d9, 0x10d0, 0x10d0, 0x10d3, 0x10d0, 0x3b, 0x10d6, 0x10e3, 0x10da, 0x2d, 0x10f0, 0x10d8, 0x10ef, 0x10d0, 0x10db, 0x10e3, 0x10f0,
-0x2e, 0x3b, 0x10e1, 0x10d0, 0x10e4, 0x2e, 0x3b, 0x10e0, 0x10d0, 0x10d1, 0x2e, 0x20, 0x49, 0x3b, 0x10e0, 0x10d0, 0x10d1, 0x2e, 0x20, 0x49,
-0x49, 0x3b, 0x10ef, 0x10e3, 0x10db, 0x2e, 0x20, 0x49, 0x3b, 0x10ef, 0x10e3, 0x10db, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x10e0, 0x10d0, 0x10ef,
-0x2e, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x2e, 0x3b, 0x10e0, 0x10d0, 0x10db, 0x2e, 0x3b, 0x10e8, 0x10d0, 0x10d5, 0x2e, 0x3b, 0x10d6, 0x10e3, 0x10da,
-0x2d, 0x10d9, 0x2e, 0x3b, 0x10d6, 0x10e3, 0x10da, 0x2d, 0x10f0, 0x2e, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53,
-0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49,
-0x49, 0x3b, 0x44, 0x73, 0x63, 0x68, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x44, 0x73, 0x63, 0x68, 0x75, 0x6d,
-0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x64, 0x73, 0x63, 0x68, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x2bb,
-0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b,
-0x44, 0x68, 0x75, 0x20, 0x6c, 0x2d, 0x71, 0x61, 0x2bf, 0x64, 0x61, 0x3b, 0x44, 0x68, 0x75, 0x20, 0x6c, 0x2d, 0x48, 0x69,
-0x64, 0x64, 0x73, 0x63, 0x68, 0x61, 0xaae, 0xac1, 0xab9, 0xab0, 0xacd, 0xab0, 0xaae, 0x3b, 0xab8, 0xaab, 0xab0, 0x3b, 0xab0, 0xabe,
-0xaac, 0xac0, 0x2bb, 0x20, 0x49, 0x3b, 0xab0, 0xabe, 0xaac, 0xac0, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0xa9c, 0xac1, 0xaae, 0xabe, 0xaa6,
-0xabe, 0x20, 0x49, 0x3b, 0xa9c, 0xac1, 0xaae, 0xabe, 0xaa6, 0xabe, 0x20, 0x49, 0x49, 0x3b, 0xab0, 0xa9c, 0xaac, 0x3b, 0xab6, 0xabe,
-0x2bb, 0xaac, 0xabe, 0xaa8, 0x3b, 0xab0, 0xaae, 0xaa6, 0xabe, 0xaa8, 0x3b, 0xab6, 0xabe, 0xab5, 0xacd, 0xab5, 0xab2, 0x3b, 0xaa7, 0xac1,
-0x2bb, 0xab2, 0x2d, 0xa95, 0xacd, 0xab5, 0xac0, 0x2bb, 0xaa1, 0xabe, 0xab9, 0x3b, 0xaa7, 0xac1, 0x2bb, 0xab2, 0x2d, 0xab9, 0xabf, 0xa9c,
-0xacd, 0xa9c, 0xabe, 0xab9, 0xaae, 0xac1, 0xab9, 0x2e, 0x3b, 0xab8, 0xaab, 0x2e, 0x3b, 0xab0, 0xaac, 0x2e, 0x49, 0x3b, 0xab0, 0xaac,
-0x2e, 0x20, 0x49, 0x49, 0x3b, 0xa9c, 0xac1, 0xaae, 0x2e, 0x20, 0x49, 0x3b, 0xa9c, 0xac1, 0xaae, 0x2e, 0x20, 0x49, 0x49, 0x3b,
-0xab0, 0xabe, 0xa9c, 0x2e, 0x3b, 0xab6, 0xabe, 0x2e, 0x3b, 0xab0, 0xabe, 0xaae, 0x2e, 0x3b, 0xab6, 0xabe, 0xab5, 0x2e, 0x3b, 0xaa7,
-0xac1, 0x2bb, 0xab2, 0x2d, 0xa95, 0xacd, 0xaaf, 0xac1, 0x2e, 0x3b, 0xaa7, 0xac1, 0x2bb, 0xab2, 0x2d, 0xa8f, 0xa9a, 0x2e, 0x5de, 0x5d5,
-0x5d7, 0x5e8, 0x5dd, 0x3b, 0x5e6, 0x5e4, 0x5e8, 0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d0, 0x5d5, 0x5d5, 0x5dc,
-0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0, 0x5be, 0x5ea, 0x5f3, 0x5d0, 0x5e0, 0x5d9, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3,
-0x5d0, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d0, 0x5d5, 0x5dc, 0x5d0, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0, 0x5be,
-0x5ea, 0x5f3, 0x5d0, 0x5e0, 0x5d9, 0x5d4, 0x3b, 0x5e8, 0x5d2, 0x5f3, 0x5d1, 0x3b, 0x5e9, 0x5e2, 0x5d1, 0x5d0, 0x5df, 0x3b, 0x5e8, 0x5de,
-0x5d3, 0x5d0, 0x5df, 0x3b, 0x5e9, 0x5d5, 0x5d5, 0x5d0, 0x5dc, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5e7, 0x5e2, 0x5d3,
-0x5d4, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d7, 0x5d9, 0x5d2, 0x5f3, 0x5d4, 0x5de, 0x5d5, 0x5d7, 0x5e8, 0x5dd, 0x3b,
-0x5e6, 0x5e4, 0x5e8, 0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0, 0x5dc, 0x2d, 0x5d0, 0x5d5, 0x5d5, 0x5dc, 0x3b, 0x5e8, 0x5d1, 0x5d9,
-0x5e2, 0x20, 0x5d0, 0x2d, 0x5ea, 0x5f3, 0x5d0, 0x5e0, 0x5d9, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0, 0x5dc,
-0x2d, 0x5d0, 0x5d5, 0x5dc, 0x5d0, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0, 0x2d, 0x5ea, 0x5f3, 0x5d0, 0x5e0,
-0x5d9, 0x5d4, 0x3b, 0x5e8, 0x5d2, 0x5f3, 0x5d1, 0x3b, 0x5e9, 0x5e2, 0x5d1, 0x5d0, 0x5df, 0x3b, 0x5e8, 0x5de, 0x5d3, 0x5d0, 0x5df, 0x3b,
-0x5e9, 0x5d5, 0x5d5, 0x5d0, 0x5dc, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5e7, 0x5e2, 0x5d3, 0x5d4, 0x3b, 0x5d3, 0x5f3,
-0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d7, 0x5d9, 0x5d2, 0x5f3, 0x5d4, 0x5de, 0x5d5, 0x5d7, 0x5e8, 0x5dd, 0x3b, 0x5e6, 0x5e4, 0x5e8, 0x3b,
-0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de,
-0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5e8, 0x5d2,
-0x5f3, 0x5d1, 0x3b, 0x5e9, 0x5e2, 0x5d1, 0x5d0, 0x5df, 0x3b, 0x5e8, 0x5de, 0x5d3, 0x5d0, 0x5df, 0x3b, 0x5e9, 0x5d5, 0x5d5, 0x5d0, 0x5dc,
-0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5e7, 0x5e2, 0x5d3, 0x5d4, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be,
-0x5d7, 0x5d9, 0x5d2, 0x5f3, 0x5d4, 0x92e, 0x941, 0x939, 0x930, 0x94d, 0x930, 0x92e, 0x3b, 0x938, 0x92b, 0x930, 0x3b, 0x930, 0x93e, 0x92c,
-0x940, 0x20, 0x92a, 0x94d, 0x930, 0x925, 0x92e, 0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x926, 0x94d, 0x935, 0x93f, 0x924, 0x940, 0x92f,
-0x3b, 0x91c, 0x941, 0x92e, 0x94d, 0x921, 0x93e, 0x20, 0x92a, 0x94d, 0x930, 0x925, 0x92e, 0x3b, 0x91c, 0x941, 0x92e, 0x94d, 0x921, 0x93e,
-0x20, 0x926, 0x94d, 0x935, 0x93f, 0x924, 0x940, 0x92f, 0x3b, 0x930, 0x91c, 0x92c, 0x3b, 0x936, 0x93e, 0x935, 0x928, 0x3b, 0x930, 0x92e,
-0x91c, 0x93e, 0x928, 0x3b, 0x936, 0x935, 0x94d, 0x935, 0x94d, 0x932, 0x3b, 0x91c, 0x93f, 0x932, 0x2d, 0x915, 0x94d, 0x926, 0x93e, 0x939,
-0x3b, 0x91c, 0x93f, 0x932, 0x94d, 0x2d, 0x939, 0x93f, 0x91c, 0x94d, 0x91c, 0x93e, 0x939, 0x4d, 0x6f, 0x68, 0x61, 0x72, 0x72, 0x65,
-0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0xe9, 0x62, 0x69, 0x20, 0x49, 0x3b, 0x52, 0xe9, 0x62, 0x69, 0x20,
-0x49, 0x49, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0xe1, 0x64, 0x69, 0x20, 0x49, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0xe1, 0x64, 0x69,
-0x20, 0x49, 0x49, 0x3b, 0x52, 0x65, 0x64, 0x73, 0x65, 0x62, 0x3b, 0x53, 0x61, 0x62, 0xe1, 0x6e, 0x3b, 0x52, 0x61, 0x6d,
-0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x53, 0x65, 0x76, 0x76, 0xe1, 0x6c, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x6b, 0x61, 0x64,
-0x65, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x68, 0x65, 0x64, 0x73, 0x65, 0x4d, 0x6f, 0x68, 0x61, 0x72, 0x72, 0x65, 0x6d,
-0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0xe9, 0x62, 0x69, 0x20, 0x65, 0x6c, 0x20, 0x61, 0x76, 0x76, 0x65, 0x6c,
-0x3b, 0x52, 0xe9, 0x62, 0x69, 0x20, 0x65, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x73, 0x65, 0x6d,
-0xe1, 0x64, 0x69, 0x20, 0x65, 0x6c, 0x20, 0x61, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0xe1, 0x64, 0x69,
-0x20, 0x65, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x68, 0x65, 0x72, 0x3b, 0x52, 0x65, 0x64, 0x73, 0x65, 0x62, 0x3b, 0x53, 0x61,
-0x62, 0xe1, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x53, 0x65, 0x76, 0x76, 0xe1, 0x6c, 0x3b, 0x44,
-0x73, 0xfc, 0x6c, 0x20, 0x6b, 0x61, 0x64, 0x65, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x68, 0x65, 0x64, 0x73, 0x65, 0x4d,
-0x6f, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0xe9, 0x62, 0x2e, 0x20, 0x31, 0x3b, 0x52, 0xe9, 0x62, 0x2e,
-0x20, 0x32, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b,
-0x52, 0x65, 0x64, 0x2e, 0x3b, 0x53, 0x61, 0x62, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x65, 0x76, 0x2e, 0x3b,
-0x44, 0x73, 0xfc, 0x6c, 0x20, 0x6b, 0x2e, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x68, 0x2e, 0x6d, 0x75, 0x68, 0x2e, 0x3b,
-0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b,
-0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a, 0x2e, 0x3b,
-0x73, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb,
-0x6c, 0x2d, 0x51, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x2e, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x61, 0x6d,
-0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x75, 0x6c, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61,
-0x62, 0x69, 0x75, 0x6c, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x69, 0x6c, 0x61, 0x77, 0x61,
-0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x69, 0x6c, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62,
-0x3b, 0x53, 0x79, 0x61, 0x6b, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x79, 0x61,
-0x77, 0x61, 0x6c, 0x3b, 0x5a, 0x75, 0x6c, 0x6b, 0x61, 0x69, 0x64, 0x61, 0x68, 0x3b, 0x5a, 0x75, 0x6c, 0x68, 0x69, 0x6a,
-0x61, 0x68, 0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x41, 0x77, 0x61,
-0x6c, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x41, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x41, 0x77,
-0x61, 0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x41, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53,
-0x79, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x79, 0x61, 0x77, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x6b, 0x61,
-0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x68, 0x69, 0x2e, 0x30e0, 0x30cf, 0x30c3, 0x30e9, 0x30e0, 0x3b, 0x30b5, 0x30d5, 0x30a2, 0x30eb, 0x3b, 0x30e9,
-0x30d3, 0x30fc, 0x30fb, 0x30a6, 0x30eb, 0x30fb, 0x30a2, 0x30a6, 0x30ef, 0x30eb, 0x3b, 0x30e9, 0x30d3, 0x30fc, 0x30fb, 0x30a6, 0x30c3, 0x30fb, 0x30b5, 0x30fc,
-0x30cb, 0x30fc, 0x3b, 0x30b8, 0x30e5, 0x30de, 0x30fc, 0x30c0, 0x30eb, 0x30fb, 0x30a2, 0x30a6, 0x30ef, 0x30eb, 0x3b, 0x30b8, 0x30e5, 0x30de, 0x30fc, 0x30c0,
-0x30c3, 0x30b5, 0x30fc, 0x30cb, 0x30fc, 0x3b, 0x30e9, 0x30b8, 0x30e3, 0x30d6, 0x3b, 0x30b7, 0x30e3, 0x30a2, 0x30d0, 0x30fc, 0x30f3, 0x3b, 0x30e9, 0x30de,
-0x30c0, 0x30fc, 0x30f3, 0x3b, 0x30b7, 0x30e3, 0x30a6, 0x30ef, 0x30fc, 0x30eb, 0x3b, 0x30ba, 0x30eb, 0x30fb, 0x30ab, 0x30a4, 0x30c0, 0x3b, 0x30ba, 0x30eb,
-0x30fb, 0x30d2, 0x30c3, 0x30b8, 0x30e3, 0xcae, 0xcc1, 0xcb9, 0xcb0, 0xcae, 0xccd, 0x3b, 0xcb8, 0xcab, 0xcbe, 0xcb0, 0xccd, 0x3b, 0xcb0, 0xcac,
-0xcbf, 0x2018, 0x20, 0x49, 0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018, 0x20, 0x49, 0x49, 0x3b, 0xc9c, 0xcc1, 0xcae, 0xcbe, 0xca6, 0xcbe, 0x20,
-0x49, 0x3b, 0xc9c, 0xcc1, 0xcae, 0xcbe, 0xca6, 0xcbe, 0x20, 0x49, 0x49, 0x3b, 0xcb0, 0xc9c, 0xcac, 0xccd, 0x3b, 0xcb6, 0x2019, 0xcac,
-0xcbe, 0xca8, 0xccd, 0x3b, 0xcb0, 0xcae, 0xca6, 0xcbe, 0xca8, 0xccd, 0x3b, 0xcb6, 0xcb5, 0xccd, 0xcb5, 0xcbe, 0xcb2, 0xccd, 0x3b, 0xca7,
-0xcc1, 0x2018, 0xcb2, 0xccd, 0x2d, 0xc95, 0xcbf, 0x2018, 0xca1, 0xcbe, 0xcb9, 0xccd, 0x3b, 0xca7, 0xcc1, 0x2018, 0xcb2, 0xccd, 0x2d, 0xcb9,
-0xcbf, 0xc9c, 0xcbe, 0xcb9, 0xccd, 0xcae, 0xcc1, 0xcb9, 0xccd, 0x2e, 0x3b, 0xcb8, 0xcab, 0xcbe, 0x2e, 0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018,
-0x20, 0x49, 0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018, 0x20, 0x49, 0x49, 0x3b, 0xc9c, 0xcc1, 0xcae, 0xccd, 0x2e, 0x20, 0x49, 0x3b, 0xc9c,
-0xcc1, 0xcae, 0xccd, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xcb0, 0xc9c, 0xccd, 0x2e, 0x3b, 0xcb6, 0x2e, 0x3b, 0xcb0, 0xcae, 0xccd, 0x2e,
-0x3b, 0xcb6, 0xcb5, 0xccd, 0x2e, 0x3b, 0xca7, 0xcc1, 0x2018, 0xcb2, 0xccd, 0x2d, 0xc95, 0xcbf, 0x2e, 0x3b, 0xca7, 0xcc1, 0x2018, 0xcb2,
-0xccd, 0x2d, 0xcb9, 0x2e, 0xbb34, 0xd558, 0xb78c, 0x3b, 0xc0ac, 0xd30c, 0xb974, 0x3b, 0xb77c, 0xbe44, 0x20, 0xc54c, 0x20, 0xc544, 0xc648, 0x3b,
-0xb77c, 0xbe44, 0x20, 0xc54c, 0x20, 0xc384, 0xb2c8, 0x3b, 0xc8fc, 0xb9c8, 0xb2e4, 0x20, 0xc54c, 0x20, 0xc544, 0xc648, 0x3b, 0xc8fc, 0xb9c8, 0xb2e4,
-0x20, 0xc54c, 0x20, 0xc384, 0xb2c8, 0x3b, 0xb77c, 0xc7a1, 0x3b, 0xc250, 0xc544, 0xbc18, 0x3b, 0xb77c, 0xb9c8, 0xb2e8, 0x3b, 0xc250, 0xc648, 0x3b,
-0xb4c0, 0x20, 0xc54c, 0x20, 0xae4c, 0xb2e4, 0x3b, 0xb4c0, 0x20, 0xc54c, 0x20, 0xd788, 0xc790, 0x6d, 0x75, 0x1e96, 0x65, 0x72, 0x65, 0x6d,
-0x3b, 0x73, 0x65, 0x66, 0x65, 0x72, 0x3b, 0x72, 0x65, 0x62, 0xee, 0x2bf, 0x75, 0x6c, 0x65, 0x77, 0x65, 0x6c, 0x3b, 0x72,
-0x65, 0x62, 0xee, 0x2bf, 0x75, 0x6c, 0x61, 0x78, 0x65, 0x72, 0x3b, 0x63, 0x65, 0x6d, 0x61, 0x7a, 0xee, 0x79, 0x65, 0x6c,
-0x65, 0x77, 0x65, 0x6c, 0x3b, 0x63, 0x65, 0x6d, 0x61, 0x7a, 0xee, 0x79, 0x65, 0x6c, 0x61, 0x78, 0x65, 0x72, 0x3b, 0x72,
-0x65, 0x63, 0x65, 0x62, 0x3b, 0x15f, 0x65, 0x2bf, 0x62, 0x61, 0x6e, 0x3b, 0x72, 0x65, 0x6d, 0x65, 0x7a, 0x61, 0x6e, 0x3b,
-0x15f, 0x65, 0x77, 0x61, 0x6c, 0x3b, 0x7a, 0xee, 0x6c, 0x71, 0x65, 0x2bf, 0x64, 0x65, 0x3b, 0x7a, 0xee, 0x6c, 0x1e96, 0x65,
-0x63, 0x65, 0xea1, 0xeb8, 0xea3, 0xeb0, 0xeae, 0xead, 0xea1, 0x3b, 0xe8a, 0xeb2, 0xe9f, 0xeb2, 0xea3, 0x3b, 0xeae, 0xead, 0xe94, 0xe9a,
-0xeb5, 0x20, 0x31, 0x3b, 0xeae, 0xead, 0xe94, 0xe9a, 0xeb5, 0x20, 0x32, 0x3b, 0xe88, 0xeb8, 0xea1, 0xeb2, 0xe94, 0xeb2, 0x20, 0x31,
-0x3b, 0xe88, 0xeb8, 0xea1, 0xeb2, 0xe94, 0xeb2, 0x20, 0x32, 0x3b, 0xeae, 0xeb2, 0xe88, 0xeb1, 0xe9a, 0x3b, 0xe8a, 0xeb0, 0xe9a, 0xeb2,
-0xe99, 0x3b, 0xeae, 0xeb2, 0xea1, 0xeb2, 0xe94, 0xead, 0xe99, 0x3b, 0xec0, 0xe8a, 0xebb, 0xeb2, 0xea7, 0xeb1, 0xe94, 0x3b, 0xe94, 0xeb8,
-0xead, 0xeb1, 0xe94, 0xe81, 0xeb4, 0xe94, 0xeb0, 0x3b, 0xe94, 0xeb8, 0xead, 0xeb1, 0xe94, 0xe81, 0xeb4, 0xe88, 0xeb0, 0xea1, 0xeb8, 0xeae,
-0xeb1, 0xe94, 0x3b, 0xec0, 0xe84, 0xeb2, 0xeb0, 0x3b, 0xeae, 0xead, 0xe81, 0xe9a, 0xeb5, 0x20, 0x31, 0x3b, 0xeae, 0xead, 0xe81, 0xe9a,
-0xeb5, 0x20, 0x32, 0x3b, 0xe99, 0xeb8, 0xea1, 0xeb2, 0x20, 0x31, 0x3b, 0xe99, 0xeb8, 0xea1, 0xeb2, 0x20, 0x32, 0x3b, 0xec0, 0xeae,
-0xeb2, 0xeb0, 0x3b, 0xe8a, 0xeb2, 0x3b, 0xec0, 0xeae, 0xeb2, 0xeb0, 0xea1, 0xeb0, 0x3b, 0xec0, 0xe8a, 0xebb, 0xeb2, 0x3b, 0xe8a, 0xeb8,
-0xea5, 0xe81, 0xeb4, 0xead, 0xeb8, 0x3b, 0xe8a, 0xeb8, 0xea5, 0xeab, 0xeb4, 0xe88, 0xea1, 0xeb8, 0xeae, 0xeb1, 0xe94, 0x3b, 0xec0, 0xe84,
-0xeb2, 0xeb0, 0x3b, 0xeae, 0xead, 0xe94, 0xe9a, 0xeb5, 0x20, 0x31, 0x3b, 0xeae, 0xead, 0xe81, 0xe9a, 0xeb5, 0x20, 0x32, 0x3b, 0xe99,
-0xeb8, 0xea1, 0xeb2, 0x20, 0x31, 0x3b, 0xe99, 0xeb8, 0xea1, 0xeb2, 0x20, 0x32, 0x3b, 0xec0, 0xeae, 0xeb2, 0xeb0, 0x3b, 0xe8a, 0xeb0,
-0xead, 0xecc, 0x3b, 0xec0, 0xeae, 0xeb2, 0xeb0, 0xea1, 0xeb0, 0x3b, 0xec0, 0xe8a, 0xebb, 0xeb2, 0x3b, 0xe8a, 0xeb8, 0xea5, 0xe81, 0xeb4,
-0xead, 0xeb8, 0x3b, 0xe8a, 0xeb8, 0xea5, 0xeab, 0xeb4, 0xe88, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3b, 0x73, 0x61,
-0x66, 0x61, 0x72, 0x73, 0x3b, 0x31, 0x2e, 0x20, 0x72, 0x61, 0x62, 0x12b, 0x3b, 0x32, 0x2e, 0x20, 0x72, 0x61, 0x62, 0x12b,
-0x3b, 0x31, 0x2e, 0x20, 0x64, 0x17e, 0x75, 0x6d, 0x101, 0x64, 0x101, 0x3b, 0x32, 0x2e, 0x20, 0x64, 0x17e, 0x75, 0x6d, 0x101,
-0x64, 0x101, 0x3b, 0x72, 0x61, 0x64, 0x17e, 0x61, 0x62, 0x73, 0x3b, 0x161, 0x61, 0x62, 0x61, 0x6e, 0x73, 0x3b, 0x72, 0x61,
-0x6d, 0x61, 0x64, 0x101, 0x6e, 0x73, 0x3b, 0x161, 0x61, 0x75, 0x76, 0x61, 0x6c, 0x73, 0x3b, 0x64, 0x75, 0x20, 0x61, 0x6c,
-0x2d, 0x6b, 0x69, 0x64, 0x101, 0x3b, 0x64, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x68, 0x69, 0x64, 0x17e, 0x101, 0x43c, 0x443, 0x445,
-0x430, 0x440, 0x435, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x440, 0x430, 0x431, 0x438, 0x20, 0x49, 0x3b, 0x440, 0x430,
-0x431, 0x438, 0x20, 0x49, 0x49, 0x3b, 0x45f, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49, 0x3b, 0x45f, 0x443, 0x43c, 0x430, 0x434,
-0x430, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x45f, 0x430, 0x431, 0x3b, 0x448, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430, 0x43c,
-0x430, 0x434, 0x430, 0x43d, 0x3b, 0x448, 0x430, 0x432, 0x430, 0x43b, 0x3b, 0x434, 0x443, 0x43b, 0x43a, 0x438, 0x434, 0x430, 0x3b, 0x434,
-0x443, 0x43b, 0x445, 0x438, 0x45f, 0x430, 0x43c, 0x443, 0x445, 0x2e, 0x3b, 0x441, 0x430, 0x444, 0x2e, 0x3b, 0x440, 0x430, 0x431, 0x2e,
-0x20, 0x49, 0x3b, 0x440, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x45f, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x3b, 0x45f, 0x443,
-0x43c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x45f, 0x2e, 0x3b, 0x448, 0x430, 0x431, 0x2e, 0x3b, 0x440, 0x430, 0x43c, 0x2e,
-0x3b, 0x448, 0x430, 0x432, 0x2e, 0x3b, 0x434, 0x443, 0x43b, 0x43a, 0x2e, 0x3b, 0x434, 0x443, 0x43b, 0x445, 0x2e, 0xd2e, 0xd41, 0xd39,
-0xd31, 0xd02, 0x3b, 0xd38, 0xd2b, 0xd7c, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35, 0xd7d, 0x3b,
-0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0xd7c, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd05,
-0xd35, 0xd4d, 0xd35, 0xd7d, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0xd7c, 0x3b, 0xd31, 0xd1c, 0xd2c,
-0xd4d, 0x3b, 0xd36, 0xd39, 0xd2c, 0xd3e, 0xd7b, 0x3b, 0xd31, 0xd2e, 0xd26, 0xd3e, 0xd7b, 0x3b, 0xd36, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd7d,
-0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd16, 0xd39, 0xd26, 0xd4d, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd39, 0xd3f, 0xd1c, 0xd4d, 0xd1c, 0xd2e,
-0xd41, 0xd39, 0xd31, 0xd02, 0x3b, 0xd38, 0xd2b, 0xd7c, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35,
-0xd7d, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0xd7c, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d,
-0x20, 0xd05, 0xd35, 0xd4d, 0xd35, 0xd7d, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0xd7c, 0x3b, 0xd31,
-0xd1c, 0xd2c, 0xd4d, 0x3b, 0xd36, 0xd39, 0xd2c, 0xd3e, 0xd7b, 0x3b, 0xd31, 0xd2e, 0xd33, 0xd3e, 0xd7b, 0x3b, 0xd36, 0xd35, 0xd4d, 0xd35,
-0xd3e, 0xd7d, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd16, 0xd39, 0xd26, 0xd4d, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd39, 0xd3f, 0xd1c, 0xd4d,
-0xd1c, 0xd2e, 0xd41, 0xd39, 0x2e, 0x3b, 0xd38, 0xd2b, 0x2e, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d,
-0xd35, 0x2e, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0x2e, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41,
-0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35, 0x2e, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0x2e, 0x3b,
-0xd31, 0xd1c, 0x2e, 0x3b, 0xd36, 0xd39, 0xd2c, 0xd3e, 0x2e, 0x3b, 0xd31, 0xd2e, 0xd26, 0xd3e, 0x2e, 0x3b, 0xd36, 0xd35, 0xd4d, 0xd35,
-0xd3e, 0x2e, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd16, 0xd39, 0x2e, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd39, 0xd3f, 0x2e, 0xd2e, 0xd41,
-0x3b, 0xd38, 0x3b, 0xd31, 0x3b, 0xd31, 0x3b, 0xd1c, 0x3b, 0xd1c, 0x3b, 0xd31, 0x3b, 0xd36, 0x3b, 0xd31, 0x3b, 0xd36, 0x3b, 0xd26,
-0xd41, 0x3b, 0xd26, 0xd41, 0x92e, 0x94b, 0x939, 0x930, 0x92e, 0x3b, 0x938, 0x92b, 0x930, 0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49,
-0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49, 0x49, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x926, 0x93e, 0x20, 0x49, 0x3b, 0x91c, 0x941,
-0x92e, 0x93e, 0x926, 0x93e, 0x20, 0x49, 0x49, 0x3b, 0x930, 0x91d, 0x93e, 0x92c, 0x3b, 0x936, 0x93e, 0x92c, 0x93e, 0x928, 0x3b, 0x930,
-0x92e, 0x91c, 0x93e, 0x928, 0x3b, 0x936, 0x935, 0x94d, 0x935, 0x93e, 0x932, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x915, 0x940, 0x926, 0x93e,
-0x939, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x939, 0x93f, 0x91c, 0x93e, 0x939, 0x92e, 0x94b, 0x939, 0x2e, 0x3b, 0x938, 0x92b, 0x2e, 0x3b,
-0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49, 0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49, 0x49, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x2e,
-0x20, 0x49, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x930, 0x91d, 0x93e, 0x2e, 0x3b, 0x936, 0x93e, 0x92c,
-0x93e, 0x2e, 0x3b, 0x930, 0x92e, 0x2e, 0x3b, 0x936, 0x935, 0x94d, 0x935, 0x93e, 0x2e, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x915, 0x940,
-0x2e, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x939, 0x93f, 0x2e, 0x967, 0x3b, 0x968, 0x3b, 0x969, 0x3b, 0x96a, 0x3b, 0x96b, 0x3b, 0x96c,
-0x3b, 0x96d, 0x3b, 0x96e, 0x3b, 0x96f, 0x3b, 0x967, 0x966, 0x3b, 0x967, 0x967, 0x3b, 0x967, 0x968, 0x6d, 0x75, 0x68, 0x61, 0x72,
-0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x72, 0x61,
-0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61,
-0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b,
-0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2bb,
-0x6c, 0x2d, 0x71, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61,
-0x68, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61,
-0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49,
-0x3b, 0x72, 0x61, 0x6a, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x77,
-0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x2e, 0x6d,
-0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x2e,
-0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72,
-0x61, 0x6a, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x2e, 0x3b,
-0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x68, 0x2e, 0x645, 0x62d, 0x631,
-0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b, 0x62c,
-0x645, 0x627, 0x639, 0x647, 0x3b, 0x62c, 0x645, 0x648, 0x645, 0x627, 0x20, 0x49, 0x49, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639,
-0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x62f, 0x627, 0x644, 0x642, 0x627,
-0x639, 0x62f, 0x647, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b,
-0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b, 0x62c, 0x645, 0x627, 0x639, 0x647, 0x3b, 0x62c,
-0x645, 0x648, 0x645, 0x627, 0x20, 0x49, 0x49, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645,
-0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x647, 0x3b, 0x630,
-0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b,
-0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b, 0x62c, 0x645, 0x627, 0x639, 0x647, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x64a, 0x20,
-0x6f2, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648,
-0x627, 0x644, 0x3b, 0x62f, 0x627, 0x644, 0x642, 0x627, 0x639, 0x62f, 0x647, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645,
-0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49,
-0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x20, 0x6f1, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x20, 0x6f2, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634,
-0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x62f, 0x627, 0x644, 0x642,
-0x627, 0x639, 0x62f, 0x647, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x62f, 0x20, 0x635,
-0x641, 0x631, 0x6d2, 0x20, 0x62f, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b, 0x62c,
-0x645, 0x627, 0x639, 0x647, 0x3b, 0x62c, 0x645, 0x648, 0x645, 0x627, 0x20, 0x49, 0x49, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639,
-0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x62f, 0x627, 0x644, 0x642, 0x627,
-0x639, 0x62f, 0x647, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x62f, 0x20, 0x635, 0x641,
-0x631, 0x6d2, 0x20, 0x62f, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b, 0x62c, 0x645,
-0x627, 0x639, 0x647, 0x3b, 0x62c, 0x645, 0x648, 0x645, 0x627, 0x20, 0x49, 0x49, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628,
-0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x642,
-0x639, 0x62f, 0x647, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b,
-0x631, 0x628, 0x6cc, 0x639, 0x200c, 0x627, 0x644, 0x627, 0x648, 0x644, 0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x200c, 0x627, 0x644, 0x62b, 0x627,
-0x646, 0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x200c, 0x627, 0x644, 0x627, 0x648, 0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc,
-0x200c, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x6cc, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645,
-0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630, 0x6cc, 0x642, 0x639, 0x62f, 0x647, 0x3b, 0x630, 0x6cc, 0x62d, 0x62c,
-0x647, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x200c, 0x627, 0x644, 0x627, 0x648, 0x644,
-0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x200c, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x200c, 0x627,
-0x644, 0x627, 0x648, 0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x200c, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x6cc, 0x3b, 0x631, 0x62c,
-0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630,
-0x6cc, 0x642, 0x639, 0x62f, 0x647, 0x654, 0x3b, 0x630, 0x6cc, 0x62d, 0x62c, 0x647, 0x654, 0x645, 0x3b, 0x635, 0x3b, 0x631, 0x3b, 0x631,
-0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x631, 0x3b, 0x634, 0x3b, 0x631, 0x3b, 0x634, 0x3b, 0x630, 0x3b, 0x630, 0x4d, 0x75, 0x68, 0x61,
-0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52,
-0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x44, 0x17c, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x44, 0x17c,
-0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x64, 0x17c, 0x61, 0x62, 0x3b, 0x53, 0x7a, 0x61, 0x62,
-0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x7a, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x5a,
-0x75, 0x20, 0x61, 0x6c, 0x2d, 0x6b, 0x61, 0x64, 0x61, 0x3b, 0x5a, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x68, 0x69, 0x64, 0x17c,
-0x64, 0x17c, 0x61, 0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b,
-0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x44, 0x17c, 0x75, 0x2e, 0x20, 0x49, 0x3b, 0x44, 0x17c, 0x75, 0x2e, 0x20,
-0x49, 0x49, 0x3b, 0x52, 0x61, 0x2e, 0x3b, 0x53, 0x7a, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x7a, 0x61,
-0x77, 0x2e, 0x3b, 0x5a, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x5a, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x68, 0x2e,
-0xa2e, 0xa41, 0xa39, 0xa71, 0xa30, 0xa2e, 0x3b, 0xa38, 0xa2b, 0xa30, 0x3b, 0xa30, 0xa2c, 0xa40, 0x2bb, 0x20, 0x49, 0x3b, 0xa30, 0xa2c,
-0xa40, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26,
-0xa3e, 0x20, 0x49, 0x49, 0x3b, 0xa30, 0xa1c, 0xa2c, 0x3b, 0xa38, 0xa3c, 0xa2c, 0xa3e, 0xa28, 0x3b, 0xa30, 0xa2e, 0xa1c, 0xa3c, 0xa3e,
-0xa28, 0x3b, 0xa38, 0xa3c, 0xa35, 0xa3e, 0xa32, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d, 0xa15, 0xa40, 0xa26, 0xa3e, 0xa39, 0x3b,
-0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d, 0xa39, 0xa3f, 0xa1c, 0xa4d, 0xa39, 0xa3e, 0xa2e, 0xa41, 0xa39, 0xa71, 0xa30, 0xa2e, 0x3b, 0xa38,
-0xa2b, 0xa30, 0x3b, 0xa30, 0xa2c, 0xa40, 0x20, 0x2bb, 0x20, 0x49, 0x3b, 0xa30, 0xa2c, 0xa40, 0x20, 0x2bb, 0x20, 0x49, 0x49, 0x3b,
-0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49, 0x49, 0x3b, 0xa30,
-0xa1c, 0xa2c, 0x3b, 0xa38, 0xa3c, 0xa2c, 0xa3e, 0xa28, 0x3b, 0xa30, 0xa2e, 0xa1c, 0xa3c, 0xa3e, 0xa28, 0x3b, 0xa38, 0xa3c, 0xa35, 0xa3e,
-0xa32, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d, 0xa15, 0xa40, 0xa26, 0xa3e, 0xa39, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d,
-0xa39, 0xa3f, 0xa1c, 0xa4d, 0xa39, 0xa3e, 0xa2e, 0xa41, 0xa39, 0xa71, 0x2e, 0x3b, 0xa38, 0xa2b, 0x2e, 0x3b, 0xa30, 0xa2c, 0x2e, 0x20,
-0x49, 0x3b, 0xa30, 0xa2c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0x2e, 0x20, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0x2e,
-0x20, 0x49, 0x49, 0x3b, 0xa30, 0xa3e, 0xa1c, 0x2e, 0x3b, 0xa38, 0xa3c, 0xa3e, 0x2e, 0x3b, 0xa30, 0xa3e, 0xa2e, 0x2e, 0x3b, 0xa38,
-0xa3c, 0xa05, 0x2e, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d, 0xa15, 0xa40, 0x2e, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d,
-0xa39, 0xa3f, 0x2e, 0x43c, 0x443, 0x445, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x440, 0x430,
-0x431, 0x438, 0x2d, 0x443, 0x43b, 0x44c, 0x2d, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x44c, 0x3b, 0x440, 0x430, 0x431, 0x438, 0x2d, 0x443,
-0x43b, 0x44c, 0x2d, 0x430, 0x445, 0x438, 0x440, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x2d, 0x443, 0x43b, 0x44c, 0x2d, 0x430,
-0x432, 0x432, 0x430, 0x43b, 0x44c, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x2d, 0x443, 0x43b, 0x44c, 0x2d, 0x430, 0x445, 0x438,
-0x440, 0x3b, 0x440, 0x430, 0x434, 0x436, 0x430, 0x431, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430, 0x43c, 0x430,
-0x434, 0x430, 0x43d, 0x3b, 0x448, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x44c, 0x3b, 0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x43a, 0x430, 0x430,
-0x434, 0x430, 0x3b, 0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x445, 0x438, 0x434, 0x436, 0x436, 0x430, 0x43c, 0x443, 0x445, 0x2e, 0x3b, 0x441,
-0x430, 0x444, 0x2e, 0x3b, 0x440, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x434,
-0x436, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x434, 0x436,
-0x2e, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x2e, 0x3b, 0x440, 0x430, 0x43c, 0x2e, 0x3b, 0x448, 0x430, 0x432, 0x2e, 0x3b, 0x437, 0x443,
-0x43b, 0x44c, 0x2d, 0x43a, 0x2e, 0x3b, 0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x445, 0x2e, 0x41c, 0x443, 0x445, 0x430, 0x440, 0x435, 0x43c,
-0x3b, 0x421, 0x430, 0x444, 0x435, 0x440, 0x3b, 0x420, 0x435, 0x431, 0x438, 0x20, 0x31, 0x3b, 0x420, 0x435, 0x431, 0x438, 0x20, 0x32,
-0x3b, 0x40f, 0x443, 0x43c, 0x430, 0x434, 0x435, 0x20, 0x31, 0x3b, 0x40f, 0x443, 0x43c, 0x430, 0x434, 0x435, 0x20, 0x32, 0x3b, 0x420,
-0x435, 0x45f, 0x435, 0x431, 0x3b, 0x428, 0x430, 0x2bb, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x437, 0x430, 0x43d, 0x3b,
-0x428, 0x435, 0x432, 0x430, 0x43b, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x43a, 0x430, 0x434, 0x435, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x445,
-0x438, 0x45f, 0x435, 0x41c, 0x443, 0x440, 0x430, 0x445, 0x430, 0x43c, 0x3b, 0x421, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431,
-0x438, 0x2bb, 0x20, 0x49, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x408, 0x443, 0x43c, 0x430, 0x434, 0x430,
-0x20, 0x49, 0x3b, 0x408, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49, 0x49, 0x3b, 0x420, 0x430, 0x452, 0x430, 0x431, 0x3b, 0x428,
-0x430, 0x2bb, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x430, 0x43b, 0x3b,
-0x414, 0x443, 0x2bb, 0x43b, 0x2d, 0x41a, 0x438, 0x2bb, 0x434, 0x430, 0x3b, 0x414, 0x443, 0x2bb, 0x43b, 0x2d, 0x445, 0x438, 0x452, 0x430,
-0x41c, 0x443, 0x445, 0x2e, 0x3b, 0x421, 0x430, 0x444, 0x2e, 0x3b, 0x420, 0x435, 0x431, 0x2e, 0x20, 0x31, 0x3b, 0x420, 0x435, 0x431,
-0x2e, 0x20, 0x32, 0x3b, 0x40f, 0x443, 0x43c, 0x2e, 0x20, 0x31, 0x3b, 0x40f, 0x443, 0x43c, 0x2e, 0x20, 0x32, 0x3b, 0x420, 0x435,
-0x45f, 0x2e, 0x3b, 0x428, 0x430, 0x2e, 0x3b, 0x420, 0x430, 0x43c, 0x2e, 0x3b, 0x428, 0x435, 0x2e, 0x3b, 0x417, 0x443, 0x43b, 0x2d,
-0x43a, 0x2e, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x445, 0x2e, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x65, 0x6d, 0x3b, 0x53, 0x61, 0x66,
-0x65, 0x72, 0x3b, 0x52, 0x65, 0x62, 0x69, 0x20, 0x31, 0x3b, 0x52, 0x65, 0x62, 0x69, 0x20, 0x32, 0x3b, 0x44, 0x17e, 0x75,
-0x6d, 0x61, 0x64, 0x65, 0x20, 0x31, 0x3b, 0x44, 0x17e, 0x75, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x32, 0x3b, 0x52, 0x65, 0x64,
-0x17e, 0x65, 0x62, 0x3b, 0x160, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a, 0x61, 0x6e, 0x3b, 0x160,
-0x65, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x6b, 0x61, 0x64, 0x65, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x68, 0x69,
-0x64, 0x17e, 0x65, 0x4d, 0x75, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62,
-0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61,
-0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x111, 0x61, 0x62, 0x3b, 0x160,
-0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x160, 0x61, 0x76, 0x61, 0x6c, 0x3b,
-0x44, 0x75, 0x2bb, 0x6c, 0x2d, 0x4b, 0x69, 0x2bb, 0x64, 0x61, 0x3b, 0x44, 0x75, 0x2bb, 0x6c, 0x2d, 0x68, 0x69, 0x111, 0x61,
-0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x65, 0x62, 0x2e, 0x20, 0x31, 0x3b, 0x52, 0x65, 0x62,
-0x2e, 0x20, 0x32, 0x3b, 0x44, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x31, 0x3b, 0x44, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x32, 0x3b,
-0x52, 0x65, 0x64, 0x17e, 0x2e, 0x3b, 0x160, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x160, 0x65, 0x2e, 0x3b, 0x5a,
-0x75, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x68, 0x2e, 0x61, 0x6c, 0x2d, 0x6d, 0x75, 0x68, 0x61, 0x72,
-0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0xed, 0xb4, 0x20, 0x61, 0x6c, 0x2d, 0x61,
-0x76, 0x76, 0x61, 0x6c, 0x3b, 0x72, 0x61, 0x62, 0xed, 0xb4, 0x61, 0x74, 0x68, 0x2d, 0x74, 0x68, 0xe1, 0x6e, 0xed, 0x3b,
-0x64, 0x17e, 0x75, 0x6d, 0xe1, 0x64, 0xe1, 0x20, 0x6c, 0x2d, 0xfa, 0x6c, 0xe1, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0xe1, 0x64,
-0xe1, 0x20, 0x6c, 0x2d, 0xe1, 0x63, 0x68, 0x69, 0x72, 0x61, 0x3b, 0x72, 0x61, 0x64, 0x17e, 0x61, 0x62, 0x3b, 0x161, 0x61,
-0xb4, 0x20, 0x62, 0xe1, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x161, 0x61, 0x75, 0x76, 0xe1, 0x6c,
-0x3b, 0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d, 0x6b, 0x61, 0xb4, 0x20, 0x64, 0x61, 0x3b, 0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d,
-0x68, 0x69, 0x64, 0x17e, 0x64, 0x17e, 0x61, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62,
-0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b,
-0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x64, 0x2e, 0x3b, 0x161, 0x61, 0x2e, 0x3b, 0x72, 0x61,
-0x6d, 0x2e, 0x3b, 0x161, 0x61, 0x75, 0x2e, 0x3b, 0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x64, 0x68, 0xfa,
-0x20, 0x6c, 0x2d, 0x68, 0x2e, 0x4d, 0x75, 0x78, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b,
-0x52, 0x61, 0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x63,
-0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d,
-0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68, 0x61, 0x6e,
-0x69, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x63, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61,
-0x64, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x75, 0x6c, 0x20, 0x61, 0x6c, 0x2d, 0x71,
-0x61, 0x63, 0x64, 0x61, 0x68, 0x3b, 0x44, 0x75, 0x6c, 0x20, 0x78, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x78, 0x61,
-0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d,
-0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x6a, 0x75, 0x6d,
-0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53,
-0x68, 0x61, 0x63, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77,
-0x61, 0x6c, 0x3b, 0x44, 0x75, 0x6c, 0x20, 0x61, 0x6c, 0x2d, 0x71, 0x61, 0x63, 0x64, 0x61, 0x3b, 0x44, 0x75, 0x6c, 0x20,
-0x78, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x78, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e,
-0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x4a, 0x75,
-0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e,
-0x3b, 0x53, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x44, 0x75, 0x6c, 0x2d, 0x51, 0x2e, 0x3b, 0x44, 0x75, 0x6c, 0x2d, 0x58, 0x2e,
-0x4d, 0x75, 0x78, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x52, 0x61, 0x62,
-0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b,
-0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x2e,
-0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x2e, 0x6d, 0x75,
-0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49,
-0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x6a,
-0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x2bb, 0x62,
-0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64,
-0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x68, 0x69,
-0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52,
-0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2019, 0x20,
-0x61, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x75, 0x6c,
-0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x61, 0x3b, 0x52, 0x61,
-0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x2019, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b,
-0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x67, 0x61, 0x2019, 0x64, 0x61, 0x3b,
-0x44, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b,
-0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c,
-0x3b, 0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x6a, 0x75, 0x6d, 0x61,
-0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x75, 0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x61, 0x6b,
-0x68, 0x69, 0x72, 0x61, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x2019, 0x62, 0x61, 0x6e, 0x3b, 0x72,
-0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c,
-0x2d, 0x67, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61, 0x43c, 0x443,
-0x4b3, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a, 0x20, 0x49,
-0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a, 0x20, 0x49, 0x49, 0x3b, 0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443, 0x43b, 0x2d,
-0x443, 0x43b, 0x43e, 0x3b, 0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443, 0x43b, 0x2d, 0x441, 0x43e, 0x43d, 0x438, 0x3b, 0x440,
-0x430, 0x4b7, 0x430, 0x431, 0x3b, 0x428, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x428,
-0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d, 0x49a, 0x438, 0x434, 0x430, 0x4b3, 0x3b, 0x414, 0x445, 0x443,
-0x43b, 0x2d, 0x4b2, 0x438, 0x4b7, 0x4b7, 0x430, 0x4b3, 0x43c, 0x443, 0x4b3, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444,
-0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a, 0x20, 0x49, 0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a, 0x20, 0x49, 0x49, 0x3b,
-0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443, 0x43b, 0x2d, 0x443, 0x43b, 0x43e, 0x3b, 0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438,
-0x2d, 0x443, 0x43b, 0x2d, 0x441, 0x43e, 0x43d, 0x438, 0x3b, 0x440, 0x430, 0x4b7, 0x430, 0x431, 0x3b, 0x428, 0x430, 0x431, 0x430, 0x43d,
-0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x414, 0x445, 0x443, 0x442,
-0x2d, 0x49a, 0x438, 0x434, 0x430, 0x4b3, 0x3b, 0x414, 0x445, 0x443, 0x442, 0x2d, 0x4b2, 0x438, 0x4b7, 0x4b7, 0x430, 0x4b3, 0x41c, 0x443,
-0x4b3, 0x2e, 0x3b, 0x421, 0x430, 0x444, 0x2e, 0x3b, 0x420, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x3b, 0x420, 0x430, 0x431, 0x2e, 0x20,
-0x49, 0x49, 0x3b, 0x4b6, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x3b, 0x4b6, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x420, 0x430,
-0x4b7, 0x2e, 0x3b, 0x428, 0x430, 0x2e, 0x3b, 0x420, 0x430, 0x43c, 0x2e, 0x3b, 0x428, 0x430, 0x432, 0x2e, 0x3b, 0x414, 0x445, 0x443,
-0x43b, 0x2d, 0x49a, 0x2e, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d, 0x4b2, 0x2e, 0xbae, 0xbc1, 0xbb9, 0xbb0, 0xbcd, 0xbb0, 0xbae, 0xbcd,
-0x3b, 0xb9a, 0xb83, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xbb0, 0xbaa, 0xbbf, 0x20, 0x31, 0x3b, 0xbb0, 0xbaa, 0xbbf, 0x20, 0x32, 0x3b, 0xb9c,
-0xbc1, 0xbae, 0xba4, 0xbbe, 0x20, 0x31, 0x3b, 0xb9c, 0xbc1, 0xbae, 0xba4, 0xbbe, 0x20, 0x32, 0x3b, 0xbb0, 0xb9c, 0xbaa, 0xbcd, 0x3b,
-0xbb7, 0xb83, 0xbaa, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xbb0, 0xbae, 0xbb2, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xbb7, 0xbb5, 0xbcd, 0xbb5, 0xbbe, 0xbb2,
-0xbcd, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd, 0x20, 0xb95, 0xb83, 0xba4, 0xbbe, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd, 0x20, 0xbb9, 0xbbf, 0xb9c,
-0xbcd, 0xb9c, 0xbbe, 0xbae, 0xbc1, 0xbb9, 0x2e, 0x3b, 0xb9a, 0xb83, 0xbaa, 0x2e, 0x3b, 0xbb0, 0xbaa, 0xbbf, 0x20, 0x31, 0x3b, 0xbb0,
-0xbaa, 0xbbf, 0x20, 0x32, 0x3b, 0xb9c, 0xbc1, 0xbae, 0x2e, 0x20, 0x31, 0x3b, 0xb9c, 0xbc1, 0xbae, 0x2e, 0x20, 0x32, 0x3b, 0xbb0,
-0xb9c, 0x2e, 0x3b, 0xbb7, 0xb83, 0x2e, 0x3b, 0xbb0, 0xbae, 0x2e, 0x3b, 0xbb7, 0xbb5, 0xbcd, 0x2e, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd,
-0x20, 0xb95, 0xb83, 0x2e, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd, 0x20, 0xbb9, 0xbbf, 0xb9c, 0xbcd, 0x2e, 0xc2e, 0xc41, 0xc39, 0xc30, 0xc4d,
-0xc30, 0xc02, 0x3b, 0xc38, 0xc2b, 0xc30, 0xc4d, 0x3b, 0xc30, 0xc2c, 0xc40, 0x20, 0x49, 0x3b, 0xc30, 0xc2c, 0xc40, 0x20, 0x49, 0x49,
-0x3b, 0xc1c, 0xc41, 0xc2e, 0xc26, 0xc3e, 0x20, 0x49, 0x3b, 0xc1c, 0xc41, 0xc2e, 0xc26, 0xc3e, 0x20, 0x49, 0x49, 0x3b, 0xc30, 0xc1c,
-0xc2c, 0xc4d, 0x3b, 0xc37, 0xc2c, 0xc3e, 0xc28, 0xc4d, 0x3b, 0xc30, 0xc02, 0xc1c, 0xc3e, 0xc28, 0xc4d, 0x3b, 0xc37, 0xc35, 0xc4d, 0xc35,
-0xc3e, 0xc32, 0xc4d, 0x3b, 0xc27, 0xc41, 0xc32, 0xc4d, 0x2d, 0xc15, 0xc3f, 0x20, 0xc26, 0xc3e, 0xc39, 0xc4d, 0x3b, 0xc27, 0xc41, 0xc32,
-0xc4d, 0x2d, 0xc39, 0xc3f, 0xc1c, 0xc4d, 0xc1c, 0xc3e, 0xc39, 0xc4d, 0xc2e, 0xc41, 0xc39, 0x2e, 0x3b, 0xc38, 0xc2b, 0x2e, 0x3b, 0xc30,
-0x2e, 0x20, 0x49, 0x3b, 0xc30, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xc1c, 0xc41, 0xc2e, 0x2e, 0x20, 0x49, 0x3b, 0xc1c, 0xc41, 0xc2e,
-0x2e, 0x20, 0x49, 0x49, 0x3b, 0xc30, 0xc1c, 0x2e, 0x3b, 0xc37, 0xc2c, 0xc3e, 0x2e, 0x3b, 0xc30, 0xc02, 0xc1c, 0xc3e, 0x2e, 0x3b,
-0xc37, 0xc35, 0xc4d, 0xc35, 0xc3e, 0x2e, 0x3b, 0xc27, 0xc41, 0xc32, 0xc4d, 0x2d, 0xc15, 0xc3f, 0x2e, 0x3b, 0xc27, 0xc41, 0xc32, 0xc4d,
-0x2d, 0xc39, 0xc3f, 0x2e, 0xe21, 0xe38, 0xe2e, 0xe30, 0xe23, 0xe4c, 0xe23, 0xe2d, 0xe21, 0x3b, 0xe0b, 0xe2d, 0xe1f, 0xe32, 0xe23, 0xe4c,
-0x3b, 0xe23, 0xe2d, 0xe1a, 0xe35, 0x20, 0x49, 0x3b, 0xe23, 0xe2d, 0xe1a, 0xe35, 0x20, 0x49, 0x49, 0x3b, 0xe08, 0xe38, 0xe21, 0xe32,
-0xe14, 0xe32, 0x20, 0x49, 0x3b, 0xe08, 0xe38, 0xe21, 0xe32, 0xe14, 0xe32, 0x20, 0x49, 0x49, 0x3b, 0xe23, 0xe2d, 0xe08, 0xe31, 0xe1a,
-0x3b, 0xe0a, 0xe30, 0xe2d, 0xe30, 0xe1a, 0xe32, 0xe19, 0x3b, 0xe23, 0xe2d, 0xe21, 0xe30, 0xe14, 0xe2d, 0xe19, 0x3b, 0xe40, 0xe0a, 0xe32,
-0xe27, 0xe31, 0xe25, 0x3b, 0xe0b, 0xe38, 0xe25, 0xe01, 0xe34, 0xe2d, 0xe3a, 0xe14, 0xe30, 0xe2e, 0xe3a, 0x3b, 0xe0b, 0xe38, 0xe25, 0xe2b,
-0xe34, 0xe08, 0xe0d, 0xe30, 0xe2e, 0xe3a, 0xe21, 0xe38, 0xe2e, 0xe31, 0xe23, 0x2e, 0x3b, 0xe40, 0xe28, 0xe32, 0xe30, 0x2e, 0x3b, 0xe23,
-0xe2d, 0xe1a, 0xe35, 0x20, 0x49, 0x3b, 0xe23, 0xe2d, 0xe1a, 0xe35, 0x20, 0x49, 0x49, 0x3b, 0xe08, 0xe38, 0xe21, 0xe32, 0xe14, 0xe32,
-0x20, 0x49, 0x3b, 0xe08, 0xe38, 0xe21, 0xe32, 0xe14, 0xe32, 0x20, 0x49, 0x49, 0x3b, 0xe40, 0xe23, 0xe32, 0xe30, 0x2e, 0x3b, 0xe0a,
-0xe30, 0xe2d, 0xe4c, 0x2e, 0x3b, 0xe40, 0xe23, 0xe32, 0xe30, 0xe21, 0xe30, 0x2e, 0x3b, 0xe40, 0xe0a, 0xe32, 0xe27, 0x2e, 0x3b, 0xe0b,
-0xe38, 0xe25, 0xe01, 0xe34, 0xe2d, 0xe3a, 0x2e, 0x3b, 0xe0b, 0xe38, 0xe25, 0xe2b, 0xe34, 0xe08, 0x2e, 0x4d, 0x75, 0x68, 0x61, 0x72,
-0x72, 0x65, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x65, 0x72, 0x3b, 0x52, 0x65, 0x62, 0x69, 0xfc, 0x6c, 0x65, 0x76, 0x76, 0x65,
-0x6c, 0x3b, 0x52, 0x65, 0x62, 0x69, 0xfc, 0x6c, 0x61, 0x68, 0x69, 0x72, 0x3b, 0x43, 0x65, 0x6d, 0x61, 0x7a, 0x69, 0x79,
-0x65, 0x6c, 0x65, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x43, 0x65, 0x6d, 0x61, 0x7a, 0x69, 0x79, 0x65, 0x6c, 0x61, 0x68, 0x69,
-0x72, 0x3b, 0x52, 0x65, 0x63, 0x65, 0x70, 0x3b, 0x15e, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a, 0x61,
-0x6e, 0x3b, 0x15e, 0x65, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x6c, 0x6b, 0x61, 0x64, 0x65, 0x3b, 0x5a, 0x69, 0x6c,
-0x68, 0x69, 0x63, 0x63, 0x65, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x65, 0x72, 0x3b, 0x52, 0x2e,
-0x65, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x52, 0x2e, 0x61, 0x68, 0x69, 0x72, 0x3b, 0x43, 0x2e, 0x65, 0x76, 0x76, 0x65, 0x6c,
-0x3b, 0x43, 0x2e, 0x61, 0x68, 0x69, 0x72, 0x3b, 0x52, 0x65, 0x63, 0x65, 0x70, 0x3b, 0x15e, 0x61, 0x62, 0x61, 0x6e, 0x3b,
-0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x15e, 0x65, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x6c, 0x6b, 0x61, 0x64, 0x65, 0x3b,
-0x5a, 0x69, 0x6c, 0x68, 0x69, 0x63, 0x63, 0x65, 0x645, 0x6c7, 0x6be, 0x6d5, 0x631, 0x631, 0x6d5, 0x645, 0x3b, 0x633, 0x6d5, 0x67e,
-0x6d5, 0x631, 0x3b, 0x631, 0x6d5, 0x628, 0x649, 0x626, 0x6c7, 0x644, 0x626, 0x6d5, 0x6cb, 0x6cb, 0x6d5, 0x644, 0x3b, 0x631, 0x6d5, 0x628,
-0x649, 0x626, 0x6c7, 0x644, 0x626, 0x627, 0x62e, 0x649, 0x631, 0x3b, 0x62c, 0x6d5, 0x645, 0x627, 0x62f, 0x649, 0x64a, 0x6d5, 0x644, 0x626,
-0x6d5, 0x6cb, 0x6cb, 0x6d5, 0x644, 0x3b, 0x62c, 0x6d5, 0x645, 0x627, 0x62f, 0x649, 0x64a, 0x6d5, 0x644, 0x626, 0x627, 0x62e, 0x649, 0x631,
-0x3b, 0x631, 0x6d5, 0x62c, 0x6d5, 0x628, 0x3b, 0x634, 0x6d5, 0x626, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x627, 0x645, 0x649, 0x632, 0x627,
-0x646, 0x3b, 0x634, 0x6d5, 0x6cb, 0x6cb, 0x627, 0x644, 0x3b, 0x632, 0x6c7, 0x644, 0x642, 0x6d5, 0x626, 0x62f, 0x6d5, 0x3b, 0x632, 0x6c7,
-0x644, 0x6be, 0x6d5, 0x62c, 0x62c, 0x6d5, 0x43c, 0x443, 0x445, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440,
-0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c,
-0x430, 0x434, 0x430, 0x20, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x434,
-0x436, 0x430, 0x431, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x434,
-0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x43a, 0x430, 0x430, 0x434, 0x430, 0x3b, 0x437, 0x443,
-0x2d, 0x43b, 0x44c, 0x2d, 0x445, 0x456, 0x434, 0x436, 0x430, 0x43c, 0x443, 0x445, 0x3b, 0x441, 0x430, 0x444, 0x3b, 0x440, 0x430, 0x431,
-0x456, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x20, 0x49, 0x3b, 0x434,
-0x436, 0x443, 0x43c, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x434, 0x436, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x3b, 0x440, 0x430, 0x43c,
-0x3b, 0x434, 0x430, 0x432, 0x3b, 0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x43a, 0x3b, 0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x445,
-0x43c, 0x443, 0x445, 0x2e, 0x3b, 0x441, 0x430, 0x444, 0x2e, 0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431,
-0x456, 0x20, 0x49, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x2e, 0x20, 0x49,
-0x49, 0x3b, 0x440, 0x430, 0x434, 0x436, 0x2e, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x2e, 0x3b, 0x440, 0x430, 0x43c, 0x2e, 0x3b, 0x434,
-0x430, 0x432, 0x2e, 0x3b, 0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x43a, 0x2e, 0x3b, 0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x445,
-0x2e, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x20, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x627, 0x648,
-0x644, 0x3b, 0x631, 0x20, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc,
-0x20, 0x627, 0x644, 0x627, 0x648, 0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x6cc, 0x3b,
-0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644,
-0x3b, 0x630, 0x648, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x6c3, 0x3b, 0x630, 0x648, 0x627, 0x644, 0x62d, 0x62c, 0x6c3, 0x645, 0x62d, 0x631,
-0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x627, 0x648, 0x651, 0x644, 0x3b, 0x631, 0x628,
-0x6cc, 0x639, 0x20, 0x627, 0x644, 0x62b, 0x651, 0x627, 0x646, 0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x627,
-0x648, 0x651, 0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x62b, 0x651, 0x627, 0x646, 0x6cc, 0x3b, 0x631, 0x62c,
-0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630,
-0x648, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x6c3, 0x3b, 0x630, 0x648, 0x627, 0x644, 0x62d, 0x62c, 0x6c3, 0x4d, 0x75, 0x68, 0x61, 0x72,
-0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x6f, 0x62, 0x69, 0x2019, 0x20, 0x75, 0x6c, 0x2d, 0x61,
-0x76, 0x76, 0x61, 0x6c, 0x3b, 0x52, 0x6f, 0x62, 0x69, 0x2019, 0x20, 0x75, 0x6c, 0x2d, 0x6f, 0x78, 0x69, 0x72, 0x3b, 0x4a,
-0x75, 0x6d, 0x61, 0x64, 0x20, 0x75, 0x6c, 0x2d, 0x61, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x20,
-0x75, 0x6c, 0x2d, 0x6f, 0x78, 0x69, 0x72, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x2019, 0x62, 0x6f,
-0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x76, 0x76, 0x6f, 0x6c, 0x3b, 0x5a, 0x75,
-0x6c, 0x2d, 0x71, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61, 0x4d, 0x75, 0x68,
-0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x6f, 0x62, 0x2e, 0x20, 0x61, 0x76, 0x76, 0x2e, 0x3b, 0x52, 0x6f, 0x62,
-0x2e, 0x20, 0x6f, 0x78, 0x2e, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x61, 0x76, 0x76, 0x2e, 0x3b, 0x4a, 0x75, 0x6d, 0x2e,
-0x20, 0x6f, 0x78, 0x2e, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b,
-0x53, 0x68, 0x61, 0x76, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x71, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x68, 0x2e, 0x41c,
-0x443, 0x4b3, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x421, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x443, 0x43b,
-0x2d, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x443, 0x43b, 0x2d, 0x43e, 0x445, 0x438, 0x440, 0x3b, 0x416,
-0x443, 0x43c, 0x43e, 0x434, 0x438, 0x443, 0x43b, 0x2d, 0x443, 0x43b, 0x43e, 0x3b, 0x416, 0x443, 0x43c, 0x43e, 0x434, 0x438, 0x443, 0x43b,
-0x2d, 0x443, 0x445, 0x440, 0x43e, 0x3b, 0x420, 0x430, 0x436, 0x430, 0x431, 0x3b, 0x428, 0x430, 0x44a, 0x431, 0x43e, 0x43d, 0x3b, 0x420,
-0x430, 0x43c, 0x430, 0x437, 0x43e, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x432, 0x43e, 0x43b, 0x3b, 0x417, 0x438, 0x43b, 0x2d, 0x49b, 0x430,
-0x44a, 0x434, 0x430, 0x3b, 0x417, 0x438, 0x43b, 0x2d, 0x4b3, 0x438, 0x436, 0x436, 0x430, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x65, 0x6d,
-0x3b, 0x73, 0x61, 0x66, 0x65, 0x72, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x69, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb,
-0x20, 0x69, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61, 0x64,
-0x65, 0x20, 0x69, 0x69, 0x3b, 0x72, 0x65, 0x64, 0x17e, 0x65, 0x62, 0x3b, 0x161, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x72,
-0x61, 0x6d, 0x61, 0x7a, 0x61, 0x6e, 0x3b, 0x161, 0x65, 0x76, 0x61, 0x6c, 0x3b, 0x7a, 0x75, 0x6c, 0x2d, 0x6b, 0x61, 0x64,
-0x65, 0x3b, 0x7a, 0x75, 0x6c, 0x2d, 0x68, 0x69, 0x64, 0x17e, 0x65, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e,
-0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x69, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x69, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d,
-0x2e, 0x20, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x69, 0x69, 0x3b, 0x72, 0x65, 0x64, 0x17e, 0x2e, 0x3b, 0x161,
-0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x161, 0x65, 0x2e, 0x3b, 0x7a, 0x75, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x7a,
-0x75, 0x6c, 0x2d, 0x68, 0x2e, 0x64, 0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65,
-0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254, 0x66, 0x69, 0x1ebd, 0x3b, 0x64, 0x61, 0x6d, 0x25b, 0x3b, 0x6d, 0x61, 0x73,
-0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65,
-0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65,
-0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x64, 0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74,
-0x65, 0x64, 0x3b, 0x61, 0x66, 0x254, 0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64,
-0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x64, 0x65,
-0x20, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x64, 0x65, 0x20, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x64,
-0x65, 0x20, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x64, 0x65, 0x20, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49,
-0x49, 0x3b, 0x64, 0x65, 0x20, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x64, 0x65, 0x20, 0x4a, 0x75, 0x6d,
-0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x64, 0x65, 0x20, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x64, 0x65, 0x20, 0x53,
-0x68, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x64, 0x65, 0x20, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x64, 0x65,
-0x20, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x69,
-0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x65, 0x20, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68,
-0xd804, 0xdd1f, 0xd804, 0xdd27, 0xd804, 0xdd26, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804,
-0xdd27, 0xd804, 0xdd1c, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd28, 0xd804, 0xdd05, 0xd804, 0xdd23,
-0xd804, 0xdd34, 0x20, 0xd804, 0xdd03, 0xd804, 0xdd03, 0xd804, 0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd22, 0xd804, 0xdd27,
-0xd804, 0xdd1d, 0xd804, 0xdd28, 0xd804, 0xdd05, 0xd804, 0xdd25, 0xd804, 0xdd34, 0x20, 0xd804, 0xdd25, 0xd804, 0xdd1a, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd0e,
-0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd05, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x20, 0xd804, 0xdd03, 0xd804, 0xdd03, 0xd804,
-0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd05,
-0xd804, 0xdd0c, 0xd804, 0xdd34, 0x20, 0xd804, 0xdd25, 0xd804, 0xdd1a, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd0e, 0xd804, 0xdd27,
-0xd804, 0xdd1d, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd33, 0xd804, 0xdd03, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b,
-0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd24, 0xd804,
-0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0xd804, 0xdd07, 0xd804, 0xdd27, 0xd804, 0xdd18, 0xd804, 0xdd34,
-0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0xd804, 0xdd26, 0xd804, 0xdd27, 0xd804, 0xdd0e, 0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804,
-0xdd27, 0xd804, 0xdd37, 0x3b, 0xd804, 0xdd38, 0x3b, 0xd804, 0xdd39, 0x3b, 0xd804, 0xdd3a, 0x3b, 0xd804, 0xdd3b, 0x3b, 0xd804, 0xdd3c, 0x3b, 0xd804,
-0xdd3d, 0x3b, 0xd804, 0xdd3e, 0x3b, 0xd804, 0xdd3f, 0x3b, 0xd804, 0xdd37, 0xd804, 0xdd36, 0x3b, 0xd804, 0xdd37, 0xd804, 0xdd37, 0x3b, 0xd804, 0xdd37,
-0xd804, 0xdd38, 0x7a46, 0x54c8, 0x5170, 0x59c6, 0x6708, 0x3b, 0x8272, 0x6cd5, 0x5c14, 0x6708, 0x3b, 0x8d56, 0x6bd4, 0x6708, 0x20, 0x49, 0x3b, 0x8d56,
-0x6bd4, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x4e3b, 0x9a6c, 0x8fbe, 0x6708, 0x20, 0x49, 0x3b, 0x4e3b, 0x9a6c, 0x8fbe, 0x6708, 0x20, 0x49, 0x49,
-0x3b, 0x8d56, 0x54f2, 0x535c, 0x6708, 0x3b, 0x820d, 0x5c14, 0x90a6, 0x6708, 0x3b, 0x8d56, 0x4e70, 0x4e39, 0x6708, 0x3b, 0x95ea, 0x74e6, 0x9c81, 0x6708,
-0x3b, 0x90fd, 0x5c14, 0x5580, 0x5c14, 0x5fb7, 0x6708, 0x3b, 0x90fd, 0x5c14, 0x9ed1, 0x54f2, 0x6708
+static constexpr char16_t months_data[] = {
+0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66,
+0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52,
+0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x64, 0x61, 0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20,
+0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61,
+0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e,
+0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x68, 0x75,
+0x2bb, 0x6c, 0x2d, 0x51, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x44, 0x68,
+0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75,
+0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e,
+0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a,
+0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49,
+0x49, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b,
+0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x44,
+0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb,
+0x6c, 0x2d, 0x48, 0x2e, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b,
+0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30,
+0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72,
+0x65, 0x6d, 0x3b, 0x53, 0x65, 0x66, 0x65, 0x72, 0x3b, 0x52, 0x65, 0x62,
+0x69, 0x75, 0x6c, 0x2d, 0x65, 0x76, 0x65, 0x6c, 0x3b, 0x52, 0x65, 0x62,
+0x69, 0x75, 0x2d, 0x74, 0x68, 0x65, 0x6e, 0x69, 0x3b, 0x58, 0x68, 0x75,
+0x6d, 0x61, 0x64, 0x65, 0x6c, 0x2d, 0x75, 0x6c, 0x61, 0x3b, 0x58, 0x68,
+0x75, 0x6d, 0x61, 0x64, 0x65, 0x2d, 0x74, 0x68, 0x65, 0x6e, 0x69, 0x3b,
+0x52, 0x65, 0x78, 0x68, 0x65, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x62, 0x61,
+0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a, 0x61, 0x6e, 0x3b, 0x53, 0x68,
+0x65, 0x76, 0x61, 0x6c, 0x3b, 0x44, 0x68, 0x75, 0x6c, 0x2d, 0x6b, 0x61,
+0x64, 0x65, 0x3b, 0x44, 0x68, 0x75, 0x6c, 0x2d, 0x68, 0x69, 0x78, 0x68,
+0x65, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x65, 0x6d, 0x3b, 0x73, 0x65,
+0x66, 0x65, 0x72, 0x3b, 0x72, 0x65, 0x62, 0x69, 0x75, 0x6c, 0x2d, 0x65,
+0x76, 0x65, 0x6c, 0x3b, 0x72, 0x65, 0x62, 0x69, 0x75, 0x2d, 0x74, 0x68,
+0x65, 0x6e, 0x69, 0x3b, 0x78, 0x68, 0x75, 0x6d, 0x61, 0x64, 0x65, 0x6c,
+0x2d, 0x75, 0x6c, 0x61, 0x3b, 0x78, 0x68, 0x75, 0x6d, 0x61, 0x64, 0x65,
+0x2d, 0x74, 0x68, 0x65, 0x6e, 0x69, 0x3b, 0x72, 0x65, 0x78, 0x68, 0x65,
+0x62, 0x3b, 0x73, 0x68, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d,
+0x61, 0x7a, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x65, 0x76, 0x61, 0x6c, 0x3b,
+0x64, 0x68, 0x75, 0x6c, 0x2d, 0x6b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x68,
+0x75, 0x6c, 0x2d, 0x68, 0x69, 0x78, 0x68, 0x65, 0x4d, 0x75, 0x68, 0x2e,
+0x3b, 0x53, 0x65, 0x66, 0x2e, 0x3b, 0x52, 0x65, 0x62, 0x2e, 0x20, 0x49,
+0x3b, 0x52, 0x65, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x58, 0x68, 0x75,
+0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x58, 0x68, 0x75, 0x6d, 0x2e, 0x20, 0x49,
+0x49, 0x3b, 0x52, 0x65, 0x78, 0x68, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e,
+0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x68, 0x65, 0x76, 0x2e, 0x3b,
+0x44, 0x68, 0x75, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x6c,
+0x2d, 0x68, 0x2e, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x65, 0x66, 0x2e,
+0x3b, 0x72, 0x65, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x65, 0x62, 0x2e,
+0x20, 0x49, 0x49, 0x3b, 0x78, 0x68, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b,
+0x78, 0x68, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x65, 0x78,
+0x68, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e,
+0x3b, 0x73, 0x68, 0x65, 0x76, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x6c, 0x2d,
+0x6b, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x6c, 0x2d, 0x68, 0x2e, 0x1219, 0x1200,
+0x1228, 0x121d, 0x3b, 0x1233, 0x1348, 0x122d, 0x3b, 0x1228, 0x1262, 0x12d1, 0x120d, 0x20,
+0x12a0, 0x12c8, 0x120d, 0x3b, 0x1228, 0x1262, 0x12d1, 0x120d, 0x20, 0x12a0, 0x12ba, 0x122d,
+0x3b, 0x1300, 0x121b, 0x12f0, 0x120d, 0x20, 0x12a0, 0x12c8, 0x120d, 0x3b, 0x1300, 0x121b,
+0x12f0, 0x120d, 0x20, 0x12a0, 0x12ba, 0x122d, 0x3b, 0x1228, 0x1300, 0x1265, 0x3b, 0x123b,
+0x12a5, 0x1263, 0x1295, 0x3b, 0x1228, 0x1218, 0x12f3, 0x1295, 0x3b, 0x1238, 0x12cb, 0x120d,
+0x3b, 0x12d9, 0x120d, 0x1242, 0x12f3, 0x1205, 0x3b, 0x12d9, 0x120d, 0x1202, 0x1303, 0x1205,
+0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x64a,
+0x639, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x631, 0x628, 0x64a, 0x639,
+0x20, 0x627, 0x644, 0x622, 0x62e, 0x631, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x649,
+0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x649, 0x3b, 0x62c, 0x645, 0x627, 0x62f,
+0x649, 0x20, 0x627, 0x644, 0x622, 0x62e, 0x631, 0x629, 0x3b, 0x631, 0x62c, 0x628,
+0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646,
+0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630, 0x648, 0x20, 0x627, 0x644, 0x642,
+0x639, 0x62f, 0x629, 0x3b, 0x630, 0x648, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x629,
+0x661, 0x3b, 0x662, 0x3b, 0x663, 0x3b, 0x664, 0x3b, 0x665, 0x3b, 0x666, 0x3b,
+0x667, 0x3b, 0x668, 0x3b, 0x669, 0x3b, 0x661, 0x660, 0x3b, 0x661, 0x661, 0x3b,
+0x661, 0x662, 0x64, 0x65, 0x20, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61,
+0x6d, 0x3b, 0x64, 0x65, 0x20, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x64,
+0x65, 0x20, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x64, 0x65,
+0x20, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x64, 0x65,
+0x20, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x64, 0x65,
+0x20, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x64,
+0x65, 0x20, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x64, 0x65, 0x20, 0x53,
+0x68, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x64, 0x65, 0x20, 0x52, 0x61,
+0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x64, 0x65, 0x20, 0x53, 0x68, 0x61,
+0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x44, 0x68, 0x75, 0x2bb,
+0x6c, 0x2d, 0x51, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x65, 0x20,
+0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68,
+0x4d, 0x259, 0x68, 0x259, 0x72, 0x72, 0x259, 0x6d, 0x3b, 0x53, 0x259, 0x66,
+0x259, 0x72, 0x3b, 0x52, 0x259, 0x62, 0x69, 0xfc, 0x6c, 0x259, 0x76, 0x76,
+0x259, 0x6c, 0x3b, 0x52, 0x259, 0x62, 0x69, 0xfc, 0x6c, 0x61, 0x78, 0x131,
+0x72, 0x3b, 0x43, 0x259, 0x6d, 0x61, 0x64, 0x69, 0x79, 0x259, 0x6c, 0x259,
+0x76, 0x76, 0x259, 0x6c, 0x3b, 0x43, 0x259, 0x6d, 0x61, 0x64, 0x69, 0x79,
+0x259, 0x6c, 0x61, 0x78, 0x131, 0x72, 0x3b, 0x52, 0x259, 0x63, 0x259, 0x62,
+0x3b, 0x15e, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a,
+0x61, 0x6e, 0x3b, 0x15e, 0x259, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x69,
+0x6c, 0x71, 0x259, 0x64, 0x259, 0x3b, 0x5a, 0x69, 0x6c, 0x68, 0x69, 0x63,
+0x63, 0x259, 0x4d, 0x259, 0x68, 0x2e, 0x3b, 0x53, 0x259, 0x66, 0x2e, 0x3b,
+0x52, 0x259, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x52, 0x259, 0x62, 0x2e, 0x20,
+0x49, 0x49, 0x3b, 0x43, 0x259, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x43, 0x259,
+0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x259, 0x63, 0x2e, 0x3b, 0x15e,
+0x61, 0x62, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x15e, 0x259, 0x76,
+0x2e, 0x3b, 0x5a, 0x69, 0x6c, 0x71, 0x2e, 0x3b, 0x5a, 0x69, 0x6c, 0x68,
+0x2e, 0x9ae, 0x9b9, 0x9b0, 0x9b0, 0x9ae, 0x3b, 0x9b8, 0x9ab, 0x9b0, 0x3b, 0x9b0,
+0x9ac, 0x9bf, 0x989, 0x9b2, 0x20, 0x986, 0x989, 0x9af, 0x9bc, 0x9be, 0x9b2, 0x3b,
+0x9b0, 0x9ac, 0x9bf, 0x989, 0x9b8, 0x20, 0x9b8, 0x9be, 0x9a8, 0x9bf, 0x3b, 0x99c,
+0x9ae, 0x9be, 0x9a6, 0x9bf, 0x989, 0x9b2, 0x20, 0x986, 0x989, 0x9af, 0x9bc, 0x9be,
+0x9b2, 0x3b, 0x99c, 0x9ae, 0x9be, 0x9a6, 0x9bf, 0x989, 0x9b8, 0x20, 0x9b8, 0x9be,
+0x9a8, 0x9bf, 0x3b, 0x9b0, 0x99c, 0x9ac, 0x3b, 0x9b6, 0x9be, 0x2018, 0x9ac, 0x9be,
+0x9a8, 0x3b, 0x9b0, 0x9ae, 0x99c, 0x9be, 0x9a8, 0x3b, 0x9b6, 0x9be, 0x993, 0x9af,
+0x9bc, 0x9be, 0x9b2, 0x3b, 0x99c, 0x9cd, 0x9ac, 0x9bf, 0x9b2, 0x995, 0x9a6, 0x3b,
+0x99c, 0x9cd, 0x9ac, 0x9bf, 0x9b2, 0x9b9, 0x99c, 0x9cd, 0x99c, 0x9e7, 0x3b, 0x9e8,
+0x3b, 0x9e9, 0x3b, 0x9ea, 0x3b, 0x9eb, 0x3b, 0x9ec, 0x3b, 0x9ed, 0x3b, 0x9ee,
+0x3b, 0x9ef, 0x3b, 0x9e7, 0x9e6, 0x3b, 0x9e7, 0x9e7, 0x3b, 0x9e7, 0x9e8, 0x6d,
+0x75, 0x68, 0x61, 0x72, 0x65, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x65, 0x72,
+0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x69, 0x3b, 0x72, 0x61, 0x62,
+0x69, 0x2bb, 0x20, 0x69, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61, 0x64,
+0x65, 0x20, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61, 0x64, 0x65, 0x20,
+0x69, 0x69, 0x3b, 0x72, 0x65, 0x64, 0x17e, 0x65, 0x62, 0x3b, 0x53, 0x68,
+0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x7a, 0x61,
+0x6e, 0x3b, 0x161, 0x65, 0x76, 0x61, 0x6c, 0x3b, 0x7a, 0x75, 0x6c, 0x2d,
+0x6b, 0x61, 0x64, 0x65, 0x3b, 0x7a, 0x75, 0x6c, 0x2d, 0x68, 0x69, 0x64,
+0x17e, 0x65, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b,
+0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20,
+0x69, 0x69, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x69, 0x3b, 0x64,
+0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x69, 0x69, 0x3b, 0x72, 0x65, 0x64, 0x17e,
+0x2e, 0x3b, 0x161, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x161,
+0x65, 0x2e, 0x3b, 0x7a, 0x75, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x7a, 0x75,
+0x6c, 0x2d, 0x68, 0x2e, 0x41c, 0x443, 0x445, 0x430, 0x440, 0x435, 0x43c, 0x3b,
+0x421, 0x430, 0x444, 0x435, 0x440, 0x3b, 0x420, 0x435, 0x431, 0x438, 0x20, 0x31,
+0x3b, 0x420, 0x435, 0x431, 0x438, 0x20, 0x32, 0x3b, 0x40f, 0x443, 0x43c, 0x430,
+0x434, 0x435, 0x20, 0x31, 0x3b, 0x40f, 0x443, 0x43c, 0x430, 0x434, 0x435, 0x20,
+0x32, 0x3b, 0x420, 0x435, 0x45f, 0x435, 0x431, 0x3b, 0x428, 0x430, 0x2bb, 0x431,
+0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x428,
+0x435, 0x432, 0x430, 0x43b, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x43a, 0x430, 0x434,
+0x435, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x445, 0x438, 0x45f, 0x435, 0x41c, 0x443,
+0x440, 0x430, 0x445, 0x430, 0x43c, 0x3b, 0x421, 0x430, 0x444, 0x430, 0x440, 0x3b,
+0x420, 0x430, 0x431, 0x438, 0x2bb, 0x20, 0x49, 0x3b, 0x420, 0x430, 0x431, 0x438,
+0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x408, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20,
+0x49, 0x3b, 0x408, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49, 0x49, 0x3b,
+0x420, 0x430, 0x452, 0x430, 0x431, 0x3b, 0x428, 0x430, 0x2bb, 0x431, 0x430, 0x43d,
+0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432,
+0x430, 0x43b, 0x3b, 0x414, 0x443, 0x2bb, 0x43b, 0x2d, 0x41a, 0x438, 0x2bb, 0x434,
+0x430, 0x3b, 0x414, 0x443, 0x2bb, 0x43b, 0x2d, 0x445, 0x438, 0x452, 0x430, 0x41c,
+0x443, 0x445, 0x2e, 0x3b, 0x421, 0x430, 0x444, 0x2e, 0x3b, 0x420, 0x435, 0x431,
+0x2e, 0x20, 0x31, 0x3b, 0x420, 0x435, 0x431, 0x2e, 0x20, 0x32, 0x3b, 0x40f,
+0x443, 0x43c, 0x2e, 0x20, 0x31, 0x3b, 0x40f, 0x443, 0x43c, 0x2e, 0x20, 0x32,
+0x3b, 0x420, 0x435, 0x45f, 0x2e, 0x3b, 0x428, 0x430, 0x2e, 0x3b, 0x420, 0x430,
+0x43c, 0x2e, 0x3b, 0x428, 0x435, 0x2e, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x43a,
+0x2e, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x445, 0x2e, 0x43c, 0x443, 0x445, 0x430,
+0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x440, 0x430,
+0x431, 0x438, 0x2d, 0x31, 0x3b, 0x440, 0x430, 0x431, 0x438, 0x2d, 0x32, 0x3b,
+0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x2d, 0x31, 0x3b, 0x434, 0x436,
+0x443, 0x43c, 0x430, 0x434, 0x430, 0x2d, 0x32, 0x3b, 0x440, 0x430, 0x434, 0x436,
+0x430, 0x431, 0x3b, 0x448, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430, 0x43c,
+0x430, 0x437, 0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x430, 0x43b, 0x3b, 0x414,
+0x445, 0x443, 0x43b, 0x2d, 0x41a, 0x430, 0x430, 0x434, 0x430, 0x3b, 0x414, 0x445,
+0x443, 0x43b, 0x2d, 0x445, 0x438, 0x434, 0x436, 0x430, 0x7a46, 0x54c8, 0x862d, 0x59c6,
+0x6708, 0x3b, 0x8272, 0x6cd5, 0x723e, 0x6708, 0x3b, 0x8cf4, 0x6bd4, 0x6708, 0x20, 0x49,
+0x3b, 0x8cf4, 0x6bd4, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x4e3b, 0x99ac, 0x9054, 0x6708,
+0x20, 0x49, 0x3b, 0x4e3b, 0x99ac, 0x9054, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x8cf4,
+0x54f2, 0x535c, 0x6708, 0x3b, 0x820d, 0x723e, 0x90a6, 0x6708, 0x3b, 0x8cf4, 0x8cb7, 0x4e39,
+0x6708, 0x3b, 0x9583, 0x74e6, 0x9b6f, 0x6708, 0x3b, 0x90fd, 0x723e, 0x5580, 0x723e, 0x5fb7,
+0x6708, 0x3b, 0x90fd, 0x723e, 0x9ed1, 0x54f2, 0x6708, 0x7a46, 0x54c8, 0x5170, 0x59c6, 0x6708,
+0x3b, 0x8272, 0x6cd5, 0x5c14, 0x6708, 0x3b, 0x8d56, 0x6bd4, 0x6708, 0x20, 0x49, 0x3b,
+0x8d56, 0x6bd4, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x4e3b, 0x9a6c, 0x8fbe, 0x6708, 0x20,
+0x49, 0x3b, 0x4e3b, 0x9a6c, 0x8fbe, 0x6708, 0x20, 0x49, 0x49, 0x3b, 0x8d56, 0x54f2,
+0x535c, 0x6708, 0x3b, 0x820d, 0x5c14, 0x90a6, 0x6708, 0x3b, 0x8d56, 0x4e70, 0x4e39, 0x6708,
+0x3b, 0x95ea, 0x74e6, 0x9c81, 0x6708, 0x3b, 0x90fd, 0x5c14, 0x5580, 0x5c14, 0x5fb7, 0x6708,
+0x3b, 0x90fd, 0x5c14, 0x9ed1, 0x54f2, 0x6708, 0xd804, 0xdd1f, 0xd804, 0xdd27, 0xd804, 0xdd26,
+0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0x3b, 0xd804,
+0xdd25, 0xd804, 0xdd27, 0xd804, 0xdd1c, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd22,
+0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd28, 0xd804, 0xdd05, 0xd804, 0xdd23, 0xd804, 0xdd34,
+0x20, 0xd804, 0xdd03, 0xd804, 0xdd03, 0xd804, 0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd23, 0xd804,
+0xdd34, 0x3b, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd28, 0xd804, 0xdd05,
+0xd804, 0xdd25, 0xd804, 0xdd34, 0x20, 0xd804, 0xdd25, 0xd804, 0xdd1a, 0xd804, 0xdd28, 0x3b,
+0xd804, 0xdd0e, 0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd05,
+0xd804, 0xdd23, 0xd804, 0xdd34, 0x20, 0xd804, 0xdd03, 0xd804, 0xdd03, 0xd804, 0xdd2a, 0xd804,
+0xdd20, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd27, 0xd804, 0xdd1f,
+0xd804, 0xdd18, 0xd804, 0xdd28, 0xd804, 0xdd05, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0x20, 0xd804,
+0xdd25, 0xd804, 0xdd1a, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd22, 0xd804, 0xdd27, 0xd804, 0xdd0e,
+0xd804, 0xdd27, 0xd804, 0xdd1d, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd33, 0xd804,
+0xdd03, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd22,
+0xd804, 0xdd27, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd34,
+0x3b, 0xd804, 0xdd25, 0xd804, 0xdd24, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e,
+0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0xd804, 0xdd07, 0xd804, 0xdd27, 0xd804, 0xdd18,
+0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0xd804,
+0xdd26, 0xd804, 0xdd27, 0xd804, 0xdd0e, 0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd27, 0xd804,
+0xdd37, 0x3b, 0xd804, 0xdd38, 0x3b, 0xd804, 0xdd39, 0x3b, 0xd804, 0xdd3a, 0x3b, 0xd804,
+0xdd3b, 0x3b, 0xd804, 0xdd3c, 0x3b, 0xd804, 0xdd3d, 0x3b, 0xd804, 0xdd3e, 0x3b, 0xd804,
+0xdd3f, 0x3b, 0xd804, 0xdd37, 0xd804, 0xdd36, 0x3b, 0xd804, 0xdd37, 0xd804, 0xdd37, 0x3b,
+0xd804, 0xdd37, 0xd804, 0xdd38, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b, 0x4e09, 0x6708,
+0x3b, 0x56db, 0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708,
+0x3b, 0x516b, 0x6708, 0x3b, 0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b, 0x5341, 0x4e00,
+0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33,
+0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37,
+0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b,
+0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x31, 0x2e, 0x3b, 0x32, 0x2e,
+0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e,
+0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30,
+0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e, 0x6d, 0x75, 0x68,
+0x61, 0x72, 0x72, 0x65, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b,
+0x72, 0x65, 0x62, 0xed, 0x2019, 0x75, 0x20, 0x6c, 0x2d, 0x61, 0x77, 0x77,
+0x61, 0x6c, 0x3b, 0x72, 0x65, 0x62, 0xed, 0x2019, 0x75, 0x20, 0x73, 0x2d,
+0x73, 0xe1, 0x6e, 0xed, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0xe1, 0x64, 0xe1,
+0x20, 0x61, 0x6c, 0x2d, 0xfa, 0x6c, 0xe1, 0x3b, 0x64, 0x17e, 0x75, 0x6d,
+0xe1, 0x64, 0xe1, 0x20, 0x61, 0x6c, 0x2d, 0xe1, 0x63, 0x68, 0x69, 0x72,
+0x61, 0x3b, 0x72, 0x65, 0x64, 0x17e, 0x65, 0x62, 0x3b, 0x161, 0x61, 0x2019,
+0x62, 0xe1, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0xe1, 0x6e, 0x3b,
+0x161, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d,
+0x6b, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d, 0x68,
+0x69, 0x64, 0x17e, 0x64, 0x17e, 0x61, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73,
+0x61, 0x66, 0x2e, 0x3b, 0x72, 0x65, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72,
+0x65, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e,
+0x20, 0x49, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b,
+0x72, 0x65, 0x64, 0x2e, 0x3b, 0x161, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d,
+0x2e, 0x3b, 0x161, 0x61, 0x77, 0x2e, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d,
+0x6b, 0x2e, 0x3b, 0x7a, 0xfa, 0x20, 0x6c, 0x2d, 0x68, 0x2e, 0x6d, 0x75,
+0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72,
+0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62,
+0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61,
+0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49,
+0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x2bb, 0x62,
+0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73,
+0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c,
+0x2d, 0x51, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb,
+0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x6f, 0x65, 0x68,
+0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b,
+0x52, 0x61, 0x62, 0x69, 0x2bb, 0x61, 0x20, 0x61, 0x6c, 0x20, 0x61, 0x77,
+0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x61, 0x20, 0x61, 0x6c,
+0x20, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b, 0x4a, 0x6f, 0x65, 0x6d, 0x61,
+0x64, 0x2bb, 0x61, 0x6c, 0x20, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x4a, 0x6f,
+0x65, 0x6d, 0x61, 0x64, 0x2bb, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x6e,
+0x69, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x6a, 0x61, 0x2bb,
+0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e,
+0x3b, 0x53, 0x6a, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x6f, 0x65, 0x20,
+0x61, 0x6c, 0x20, 0x6b, 0x61, 0x2bb, 0x61, 0x62, 0x61, 0x3b, 0x44, 0x6f,
+0x65, 0x20, 0x61, 0x6c, 0x20, 0x68, 0x69, 0x7a, 0x6a, 0x61, 0x4d, 0x6f,
+0x65, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62,
+0x2e, 0x20, 0x49, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b,
+0x4a, 0x6f, 0x65, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x4a, 0x6f, 0x65, 0x6d,
+0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x6a,
+0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x6a, 0x61, 0x77,
+0x2e, 0x3b, 0x44, 0x6f, 0x65, 0x20, 0x61, 0x6c, 0x20, 0x6b, 0x2e, 0x3b,
+0x44, 0x6f, 0x65, 0x20, 0x61, 0x6c, 0x20, 0x68, 0x2e, 0x64, 0x7a, 0x6f,
+0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65,
+0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254, 0x66, 0x69, 0x1ebd, 0x3b,
+0x64, 0x61, 0x6d, 0x25b, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69,
+0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61,
+0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254,
+0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65,
+0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x64,
+0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61,
+0x66, 0x254, 0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73,
+0x69, 0x61, 0x3b, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b,
+0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x6d, 0x75,
+0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72,
+0x3b, 0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77,
+0x77, 0x61, 0x6c, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c,
+0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x61,
+0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x75, 0x6c, 0x61, 0x3b, 0x64, 0x17e, 0x75,
+0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72,
+0x61, 0x3b, 0x72, 0x61, 0x64, 0x17e, 0x61, 0x62, 0x3b, 0x161, 0x61, 0x2019,
+0x62, 0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b,
+0x161, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c,
+0x2d, 0x71, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c,
+0x2d, 0x68, 0x69, 0x64, 0x64, 0x17e, 0x61, 0x6d, 0x6f, 0x75, 0x68, 0x61,
+0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72,
+0x61, 0x62, 0x69, 0x61, 0x20, 0x61, 0x6c, 0x20, 0x61, 0x77, 0x61, 0x6c,
+0x3b, 0x72, 0x61, 0x62, 0x69, 0x61, 0x20, 0x61, 0x74, 0x68, 0x2d, 0x74,
+0x68, 0x61, 0x6e, 0x69, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x61, 0x64, 0x61,
+0x20, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x6c, 0x61, 0x3b, 0x6a, 0x6f, 0x75,
+0x6d, 0x61, 0x64, 0x61, 0x20, 0x61, 0x74, 0x68, 0x2d, 0x74, 0x68, 0x61,
+0x6e, 0x69, 0x61, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x63, 0x68,
+0x61, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64,
+0x61, 0x6e, 0x3b, 0x63, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64,
+0x68, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x20, 0x71, 0x69, 0x60, 0x64, 0x61,
+0x3b, 0x64, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x68, 0x69, 0x6a,
+0x6a, 0x61, 0x6d, 0x6f, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e,
+0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x61, 0x77, 0x2e, 0x3b, 0x72, 0x61,
+0x62, 0x2e, 0x20, 0x74, 0x68, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e,
+0x20, 0x6f, 0x75, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x74,
+0x68, 0x2e, 0x3b, 0x72, 0x61, 0x6a, 0x2e, 0x3b, 0x63, 0x68, 0x61, 0x61,
+0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x63, 0x68, 0x61, 0x77, 0x2e,
+0x3b, 0x64, 0x68, 0x6f, 0x75, 0x2e, 0x20, 0x71, 0x69, 0x2e, 0x3b, 0x64,
+0x68, 0x6f, 0x75, 0x2e, 0x20, 0x68, 0x69, 0x2e, 0x6d, 0x6f, 0x75, 0x68,
+0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20,
+0x61, 0x77, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x74, 0x68, 0x2e,
+0x3b, 0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x6f, 0x75, 0x6c, 0x2e, 0x3b,
+0x6a, 0x6f, 0x75, 0x6d, 0x2e, 0x20, 0x74, 0x68, 0x61, 0x2e, 0x3b, 0x72,
+0x61, 0x6a, 0x2e, 0x3b, 0x63, 0x68, 0x61, 0x61, 0x2e, 0x3b, 0x72, 0x61,
+0x6d, 0x2e, 0x3b, 0x63, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x64, 0x68, 0x6f,
+0x75, 0x2e, 0x20, 0x71, 0x2e, 0x3b, 0x64, 0x68, 0x6f, 0x75, 0x2e, 0x20,
+0x68, 0x2e, 0xd83a, 0xdd14, 0xd83a, 0xdd2e, 0xd83a, 0xdd25, 0xd83a, 0xdd26, 0xd83a, 0xdd2b,
+0xd83a, 0xdd32, 0xd83a, 0xdd3c, 0xd83a, 0xdd2b, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd22, 0xd83a,
+0xdd26, 0xd83a, 0xdd46, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a, 0xdd35, 0x2d,
+0xd83a, 0xdd06, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0x3b, 0xd83a,
+0xdd06, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0x3b, 0xd83a, 0xdd03,
+0xd83a, 0xdd2d, 0xd83a, 0xdd25, 0xd83a, 0xdd28, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22,
+0xd83a, 0xdd32, 0x3b, 0xd83a, 0xdd04, 0xd83a, 0xdd22, 0xd83a, 0xdd28, 0xd83a, 0xdd46, 0xd83a,
+0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd22,
+0xd83a, 0xdd26, 0xd83a, 0xdd46, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a, 0xdd35,
+0x2d, 0xd83a, 0xdd08, 0xd83a, 0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd36, 0xd83a, 0xdd2d, 0xd83a,
+0xdd26, 0xd83a, 0xdd2d, 0x3b, 0xd83a, 0xdd08, 0xd83a, 0xdd22, 0xd83a, 0xdd44, 0xd83a, 0xdd36,
+0xd83a, 0xdd2d, 0xd83a, 0xdd26, 0xd83a, 0xdd2d, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd22, 0xd83a,
+0xdd26, 0xd83a, 0xdd46, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a, 0xdd35, 0x2d,
+0xd83a, 0xdd05, 0xd83a, 0xdd35, 0xd83a, 0xdd45, 0xd83a, 0xdd25, 0xd83a, 0xdd22, 0xd83a, 0xdd34,
+0xd83a, 0xdd2b, 0xd83a, 0xdd45, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd35, 0xd83a, 0xdd45, 0xd83a,
+0xdd25, 0xd83a, 0xdd22, 0xd83a, 0xdd34, 0xd83a, 0xdd2b, 0xd83a, 0xdd45, 0x3b, 0xd83a, 0xdd14,
+0xd83a, 0xdd35, 0xd83a, 0xdd45, 0xd83a, 0xdd24, 0xd83a, 0xdd23, 0xd83a, 0xdd22, 0xd83a, 0xdd44,
+0xd83a, 0xdd32, 0xd83a, 0xdd4b, 0xd83a, 0xdd23, 0xd83a, 0xdd35, 0x3b, 0xd83a, 0xdd05, 0xd83a,
+0xdd22, 0xd83a, 0xdd26, 0xd83a, 0xdd46, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a,
+0xdd35, 0x2d, 0xd83a, 0xdd01, 0xd83a, 0xdd2e, 0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a, 0xdd2d,
+0xd83a, 0xdd32, 0x3b, 0xd83a, 0xdd01, 0xd83a, 0xdd35, 0xd83a, 0xdd32, 0xd83a, 0xdd33, 0xd83a,
+0xdd2d, 0xd83a, 0xdd32, 0xd83a, 0xdd14, 0xd83a, 0xdd2e, 0xd83a, 0xdd26, 0x2e, 0x3b, 0xd83a,
+0xdd05, 0xd83a, 0xdd22, 0xd83a, 0xdd28, 0x2e, 0x3b, 0xd83a, 0xdd06, 0xd83a, 0xdd22, 0xd83a,
+0xdd2a, 0x2e, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd2d, 0xd83a, 0xdd28, 0x2e, 0x3b, 0xd83a,
+0xdd04, 0xd83a, 0xdd22, 0xd83a, 0xdd28, 0x2e, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd22, 0xd83a,
+0xdd2a, 0x2e, 0x3b, 0xd83a, 0xdd08, 0xd83a, 0xdd22, 0xd83a, 0xdd36, 0x2e, 0x3b, 0xd83a,
+0xdd05, 0xd83a, 0xdd22, 0xd83a, 0xdd27, 0x2e, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd35, 0xd83a,
+0xdd25, 0x2e, 0x3b, 0xd83a, 0xdd14, 0xd83a, 0xdd35, 0xd83a, 0xdd24, 0x2e, 0x3b, 0xd83a,
+0xdd05, 0xd83a, 0xdd22, 0xd83a, 0xdd23, 0x2e, 0x3b, 0xd83a, 0xdd01, 0xd83a, 0xdd2e, 0xd83a,
+0xdd32, 0x2e, 0xd83a, 0xdd51, 0x3b, 0xd83a, 0xdd52, 0x3b, 0xd83a, 0xdd53, 0x3b, 0xd83a,
+0xdd54, 0x3b, 0xd83a, 0xdd55, 0x3b, 0xd83a, 0xdd56, 0x3b, 0xd83a, 0xdd57, 0x3b, 0xd83a,
+0xdd58, 0x3b, 0xd83a, 0xdd59, 0x3b, 0xd83a, 0xdd51, 0xd83a, 0xdd50, 0x3b, 0xd83a, 0xdd51,
+0xd83a, 0xdd51, 0x3b, 0xd83a, 0xdd51, 0xd83a, 0xdd52, 0x10db, 0x10e3, 0x10f0, 0x10d0, 0x10e0,
+0x10d0, 0x10db, 0x10d8, 0x3b, 0x10e1, 0x10d0, 0x10e4, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10e0,
+0x10d0, 0x10d1, 0x10d8, 0x20, 0x10e3, 0x10da, 0x2d, 0x10d0, 0x10d5, 0x10d0, 0x10da, 0x10d8,
+0x3b, 0x10e0, 0x10d0, 0x10d1, 0x10d8, 0x20, 0x10e3, 0x10da, 0x2d, 0x10d0, 0x10ee, 0x10d8,
+0x10e0, 0x10d8, 0x3b, 0x10ef, 0x10e3, 0x10db, 0x10d0, 0x10d3, 0x10d0, 0x20, 0x10e3, 0x10da,
+0x2d, 0x10d0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10ef, 0x10e3, 0x10db, 0x10d0, 0x10d3,
+0x10d0, 0x20, 0x10e3, 0x10da, 0x2d, 0x10d0, 0x10ee, 0x10d8, 0x10e0, 0x10d8, 0x3b, 0x10e0,
+0x10d0, 0x10ef, 0x10d0, 0x10d1, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10dc, 0x10d8,
+0x3b, 0x10e0, 0x10d0, 0x10db, 0x10d0, 0x10d3, 0x10d0, 0x10dc, 0x10d8, 0x3b, 0x10e8, 0x10d0,
+0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10d6, 0x10e3, 0x10da, 0x2d, 0x10d9, 0x10d0, 0x10d0,
+0x10d3, 0x10d0, 0x3b, 0x10d6, 0x10e3, 0x10da, 0x2d, 0x10f0, 0x10d8, 0x10ef, 0x10d0, 0x10db,
+0x10e3, 0x10f0, 0x2e, 0x3b, 0x10e1, 0x10d0, 0x10e4, 0x2e, 0x3b, 0x10e0, 0x10d0, 0x10d1,
+0x2e, 0x20, 0x49, 0x3b, 0x10e0, 0x10d0, 0x10d1, 0x2e, 0x20, 0x49, 0x49, 0x3b,
+0x10ef, 0x10e3, 0x10db, 0x2e, 0x20, 0x49, 0x3b, 0x10ef, 0x10e3, 0x10db, 0x2e, 0x20,
+0x49, 0x49, 0x3b, 0x10e0, 0x10d0, 0x10ef, 0x2e, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x2e,
+0x3b, 0x10e0, 0x10d0, 0x10db, 0x2e, 0x3b, 0x10e8, 0x10d0, 0x10d5, 0x2e, 0x3b, 0x10d6,
+0x10e3, 0x10da, 0x2d, 0x10d9, 0x2e, 0x3b, 0x10d6, 0x10e3, 0x10da, 0x2d, 0x10f0, 0x2e,
+0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66,
+0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52,
+0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x44, 0x73, 0x63, 0x68,
+0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x44, 0x73, 0x63, 0x68,
+0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x64,
+0x73, 0x63, 0x68, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x2bb, 0x62, 0x61,
+0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x68,
+0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x68, 0x75, 0x20, 0x6c, 0x2d,
+0x71, 0x61, 0x2bf, 0x64, 0x61, 0x3b, 0x44, 0x68, 0x75, 0x20, 0x6c, 0x2d,
+0x48, 0x69, 0x64, 0x64, 0x73, 0x63, 0x68, 0x61, 0xaae, 0xac1, 0xab9, 0xab0,
+0xacd, 0xab0, 0xaae, 0x3b, 0xab8, 0xaab, 0xab0, 0x3b, 0xab0, 0xabe, 0xaac, 0xac0,
+0x2bb, 0x20, 0x49, 0x3b, 0xab0, 0xabe, 0xaac, 0xac0, 0x2bb, 0x20, 0x49, 0x49,
+0x3b, 0xa9c, 0xac1, 0xaae, 0xabe, 0xaa6, 0xabe, 0x20, 0x49, 0x3b, 0xa9c, 0xac1,
+0xaae, 0xabe, 0xaa6, 0xabe, 0x20, 0x49, 0x49, 0x3b, 0xab0, 0xa9c, 0xaac, 0x3b,
+0xab6, 0xabe, 0x2bb, 0xaac, 0xabe, 0xaa8, 0x3b, 0xab0, 0xaae, 0xaa6, 0xabe, 0xaa8,
+0x3b, 0xab6, 0xabe, 0xab5, 0xacd, 0xab5, 0xab2, 0x3b, 0xaa7, 0xac1, 0x2bb, 0xab2,
+0x2d, 0xa95, 0xacd, 0xab5, 0xac0, 0x2bb, 0xaa1, 0xabe, 0xab9, 0x3b, 0xaa7, 0xac1,
+0x2bb, 0xab2, 0x2d, 0xab9, 0xabf, 0xa9c, 0xacd, 0xa9c, 0xabe, 0xab9, 0xaae, 0xac1,
+0xab9, 0x2e, 0x3b, 0xab8, 0xaab, 0x2e, 0x3b, 0xab0, 0xaac, 0x2e, 0x49, 0x3b,
+0xab0, 0xaac, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xa9c, 0xac1, 0xaae, 0x2e, 0x20,
+0x49, 0x3b, 0xa9c, 0xac1, 0xaae, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xab0, 0xabe,
+0xa9c, 0x2e, 0x3b, 0xab6, 0xabe, 0x2e, 0x3b, 0xab0, 0xabe, 0xaae, 0x2e, 0x3b,
+0xab6, 0xabe, 0xab5, 0x2e, 0x3b, 0xaa7, 0xac1, 0x2bb, 0xab2, 0x2d, 0xa95, 0xacd,
+0xaaf, 0xac1, 0x2e, 0x3b, 0xaa7, 0xac1, 0x2bb, 0xab2, 0x2d, 0xa8f, 0xa9a, 0x2e,
+0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66,
+0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52,
+0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x64, 0x61, 0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20,
+0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61,
+0x2bc, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61,
+0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x68,
+0x75, 0x2bb, 0x6c, 0x2d, 0x51, 0x69, 0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x44,
+0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x5de,
+0x5d5, 0x5d7, 0x5e8, 0x5dd, 0x3b, 0x5e6, 0x5e4, 0x5e8, 0x3b, 0x5e8, 0x5d1, 0x5d9,
+0x5e2, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d0, 0x5d5, 0x5d5, 0x5dc, 0x3b, 0x5e8, 0x5d1,
+0x5d9, 0x5e2, 0x20, 0x5d0, 0x5be, 0x5ea, 0x5f3, 0x5d0, 0x5e0, 0x5d9, 0x3b, 0x5d2,
+0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d0, 0x5d5,
+0x5dc, 0x5d0, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0,
+0x5be, 0x5ea, 0x5f3, 0x5d0, 0x5e0, 0x5d9, 0x5d4, 0x3b, 0x5e8, 0x5d2, 0x5f3, 0x5d1,
+0x3b, 0x5e9, 0x5e2, 0x5d1, 0x5d0, 0x5df, 0x3b, 0x5e8, 0x5de, 0x5d3, 0x5d0, 0x5df,
+0x3b, 0x5e9, 0x5d5, 0x5d5, 0x5d0, 0x5dc, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0,
+0x5dc, 0x5be, 0x5e7, 0x5e2, 0x5d3, 0x5d4, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0,
+0x5dc, 0x5be, 0x5d7, 0x5d9, 0x5d2, 0x5f3, 0x5d4, 0x5de, 0x5d5, 0x5d7, 0x5e8, 0x5dd,
+0x3b, 0x5e6, 0x5e4, 0x5e8, 0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0, 0x5dc,
+0x2d, 0x5d0, 0x5d5, 0x5d5, 0x5dc, 0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0,
+0x2d, 0x5ea, 0x5f3, 0x5d0, 0x5e0, 0x5d9, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0,
+0x5d3, 0x5d0, 0x20, 0x5d0, 0x5dc, 0x2d, 0x5d0, 0x5d5, 0x5dc, 0x5d0, 0x3b, 0x5d2,
+0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20, 0x5d0, 0x2d, 0x5ea, 0x5f3, 0x5d0,
+0x5e0, 0x5d9, 0x5d4, 0x3b, 0x5e8, 0x5d2, 0x5f3, 0x5d1, 0x3b, 0x5e9, 0x5e2, 0x5d1,
+0x5d0, 0x5df, 0x3b, 0x5e8, 0x5de, 0x5d3, 0x5d0, 0x5df, 0x3b, 0x5e9, 0x5d5, 0x5d5,
+0x5d0, 0x5dc, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5e7, 0x5e2,
+0x5d3, 0x5d4, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d7, 0x5d9,
+0x5d2, 0x5f3, 0x5d4, 0x5de, 0x5d5, 0x5d7, 0x5e8, 0x5dd, 0x3b, 0x5e6, 0x5e4, 0x5e8,
+0x3b, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5e8, 0x5d1, 0x5d9,
+0x5e2, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0,
+0x20, 0x5d0, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x5d5, 0x5de, 0x5d0, 0x5d3, 0x5d0, 0x20,
+0x5d1, 0x5f3, 0x3b, 0x5e8, 0x5d2, 0x5f3, 0x5d1, 0x3b, 0x5e9, 0x5e2, 0x5d1, 0x5d0,
+0x5df, 0x3b, 0x5e8, 0x5de, 0x5d3, 0x5d0, 0x5df, 0x3b, 0x5e9, 0x5d5, 0x5d5, 0x5d0,
+0x5dc, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5e7, 0x5e2, 0x5d3,
+0x5d4, 0x3b, 0x5d3, 0x5f3, 0x5d5, 0x20, 0x5d0, 0x5dc, 0x5be, 0x5d7, 0x5d9, 0x5d2,
+0x5f3, 0x5d4, 0x92e, 0x941, 0x939, 0x930, 0x94d, 0x930, 0x92e, 0x3b, 0x938, 0x92b,
+0x930, 0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x92a, 0x94d, 0x930, 0x925, 0x92e,
+0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x926, 0x94d, 0x935, 0x93f, 0x924, 0x940,
+0x92f, 0x3b, 0x91c, 0x941, 0x92e, 0x94d, 0x921, 0x93e, 0x20, 0x92a, 0x94d, 0x930,
+0x925, 0x92e, 0x3b, 0x91c, 0x941, 0x92e, 0x94d, 0x921, 0x93e, 0x20, 0x926, 0x94d,
+0x935, 0x93f, 0x924, 0x940, 0x92f, 0x3b, 0x930, 0x91c, 0x92c, 0x3b, 0x936, 0x93e,
+0x935, 0x928, 0x3b, 0x930, 0x92e, 0x91c, 0x93e, 0x928, 0x3b, 0x936, 0x935, 0x94d,
+0x935, 0x94d, 0x932, 0x3b, 0x91c, 0x93f, 0x932, 0x2d, 0x915, 0x94d, 0x926, 0x93e,
+0x939, 0x3b, 0x91c, 0x93f, 0x932, 0x94d, 0x2d, 0x939, 0x93f, 0x91c, 0x94d, 0x91c,
+0x93e, 0x939, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53,
+0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x20, 0x61, 0x6c,
+0x2d, 0x41, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x20,
+0x61, 0x73, 0x2d, 0x53, 0x61, 0x61, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d, 0x41, 0x77, 0x77, 0x61,
+0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x64, 0x61, 0x20, 0x61, 0x73,
+0x2d, 0x53, 0x61, 0x61, 0x6e, 0x69, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62,
+0x3b, 0x53, 0x68, 0x61, 0x61, 0x62, 0x61, 0x61, 0x6e, 0x3b, 0x52, 0x61,
+0x6d, 0x7a, 0x61, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61,
+0x61, 0x6c, 0x3b, 0x5a, 0x75, 0x2019, 0x6c, 0x2d, 0x51, 0x61, 0x61, 0x64,
+0x61, 0x3b, 0x5a, 0x75, 0x2019, 0x6c, 0x2d, 0x48, 0x69, 0x6a, 0x6a, 0x61,
+0x4d, 0x75, 0x68, 0x3b, 0x53, 0x61, 0x66, 0x3b, 0x52, 0x61, 0x62, 0x69,
+0x20, 0x31, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x20, 0x32, 0x3b, 0x4a, 0x75,
+0x6d, 0x20, 0x31, 0x3b, 0x4a, 0x75, 0x6d, 0x20, 0x32, 0x3b, 0x52, 0x61,
+0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x62, 0x3b, 0x52, 0x61, 0x6d,
+0x3b, 0x53, 0x68, 0x61, 0x77, 0x3b, 0x5a, 0x75, 0x20, 0x51, 0x3b, 0x5a,
+0x75, 0x20, 0x48, 0x4d, 0x6f, 0x68, 0x61, 0x72, 0x72, 0x65, 0x6d, 0x3b,
+0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0xe9, 0x62, 0x69, 0x20, 0x49,
+0x3b, 0x52, 0xe9, 0x62, 0x69, 0x20, 0x49, 0x49, 0x3b, 0x44, 0x73, 0x65,
+0x6d, 0xe1, 0x64, 0x69, 0x20, 0x49, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0xe1,
+0x64, 0x69, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x65, 0x64, 0x73, 0x65, 0x62,
+0x3b, 0x53, 0x61, 0x62, 0xe1, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64,
+0xe1, 0x6e, 0x3b, 0x53, 0x65, 0x76, 0x76, 0xe1, 0x6c, 0x3b, 0x44, 0x73,
+0xfc, 0x6c, 0x20, 0x6b, 0x61, 0x64, 0x65, 0x3b, 0x44, 0x73, 0xfc, 0x6c,
+0x20, 0x68, 0x65, 0x64, 0x73, 0x65, 0x4d, 0x6f, 0x68, 0x61, 0x72, 0x72,
+0x65, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0xe9, 0x62,
+0x69, 0x20, 0x65, 0x6c, 0x20, 0x61, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x52,
+0xe9, 0x62, 0x69, 0x20, 0x65, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x68, 0x65,
+0x72, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0xe1, 0x64, 0x69, 0x20, 0x65, 0x6c,
+0x20, 0x61, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x44, 0x73, 0x65, 0x6d, 0xe1,
+0x64, 0x69, 0x20, 0x65, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x68, 0x65, 0x72,
+0x3b, 0x52, 0x65, 0x64, 0x73, 0x65, 0x62, 0x3b, 0x53, 0x61, 0x62, 0xe1,
+0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x53, 0x65,
+0x76, 0x76, 0xe1, 0x6c, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x6b, 0x61,
+0x64, 0x65, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x68, 0x65, 0x64, 0x73,
+0x65, 0x4d, 0x6f, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52,
+0xe9, 0x62, 0x2e, 0x20, 0x31, 0x3b, 0x52, 0xe9, 0x62, 0x2e, 0x20, 0x32,
+0x3b, 0x44, 0x73, 0x65, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x44, 0x73, 0x65,
+0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x65, 0x64, 0x2e, 0x3b, 0x53,
+0x61, 0x62, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x65, 0x76,
+0x2e, 0x3b, 0x44, 0x73, 0xfc, 0x6c, 0x20, 0x6b, 0x2e, 0x3b, 0x44, 0x73,
+0xfc, 0x6c, 0x20, 0x68, 0x2e, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61,
+0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61,
+0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49,
+0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a,
+0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b,
+0x73, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d,
+0x51, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x2e, 0x4d,
+0x75, 0x68, 0x61, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72,
+0x3b, 0x52, 0x61, 0x62, 0x69, 0x75, 0x6c, 0x61, 0x77, 0x61, 0x6c, 0x3b,
+0x52, 0x61, 0x62, 0x69, 0x75, 0x6c, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x64, 0x69, 0x6c, 0x61, 0x77, 0x61, 0x6c, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x64, 0x69, 0x6c, 0x61, 0x6b, 0x68, 0x69, 0x72,
+0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x79, 0x61, 0x6b, 0x62,
+0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53,
+0x79, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x5a, 0x75, 0x6c, 0x6b, 0x61, 0x69,
+0x64, 0x61, 0x68, 0x3b, 0x5a, 0x75, 0x6c, 0x68, 0x69, 0x6a, 0x61, 0x68,
+0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61,
+0x62, 0x2e, 0x20, 0x41, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x2e,
+0x20, 0x41, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20,
+0x41, 0x77, 0x61, 0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x41, 0x6b,
+0x68, 0x69, 0x72, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x79, 0x61,
+0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x79, 0x61, 0x77, 0x2e,
+0x3b, 0x5a, 0x75, 0x6c, 0x6b, 0x61, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x68,
+0x69, 0x2e, 0x30e0, 0x30cf, 0x30c3, 0x30e9, 0x30e0, 0x3b, 0x30b5, 0x30d5, 0x30a2, 0x30eb,
+0x3b, 0x30e9, 0x30d3, 0x30fc, 0x30fb, 0x30a6, 0x30eb, 0x30fb, 0x30a2, 0x30a6, 0x30ef, 0x30eb,
+0x3b, 0x30e9, 0x30d3, 0x30fc, 0x30fb, 0x30a6, 0x30c3, 0x30fb, 0x30b5, 0x30fc, 0x30cb, 0x30fc,
+0x3b, 0x30b8, 0x30e5, 0x30de, 0x30fc, 0x30c0, 0x30eb, 0x30fb, 0x30a2, 0x30a6, 0x30ef, 0x30eb,
+0x3b, 0x30b8, 0x30e5, 0x30de, 0x30fc, 0x30c0, 0x30c3, 0x30b5, 0x30fc, 0x30cb, 0x30fc, 0x3b,
+0x30e9, 0x30b8, 0x30e3, 0x30d6, 0x3b, 0x30b7, 0x30e3, 0x30a2, 0x30d0, 0x30fc, 0x30f3, 0x3b,
+0x30e9, 0x30de, 0x30c0, 0x30fc, 0x30f3, 0x3b, 0x30b7, 0x30e3, 0x30a6, 0x30ef, 0x30fc, 0x30eb,
+0x3b, 0x30ba, 0x30eb, 0x30fb, 0x30ab, 0x30a4, 0x30c0, 0x3b, 0x30ba, 0x30eb, 0x30fb, 0x30d2,
+0x30c3, 0x30b8, 0x30e3, 0x53, 0x75, 0x72, 0x61, 0x3b, 0x53, 0x61, 0x70, 0x61,
+0x72, 0x3b, 0x4d, 0x75, 0x6c, 0x75, 0x64, 0x3b, 0x42, 0x61, 0x6b, 0x64,
+0x61, 0x20, 0x4d, 0x75, 0x6c, 0x75, 0x64, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x64, 0x69, 0x6c, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x64, 0x69, 0x6c, 0x61, 0x6b, 0x69, 0x72, 0x3b, 0x52, 0x65, 0x6a, 0x65,
+0x62, 0x3b, 0x52, 0x75, 0x77, 0x61, 0x68, 0x3b, 0x50, 0x61, 0x73, 0x61,
+0x3b, 0x53, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x53, 0x65, 0x6c, 0x6f, 0x3b,
+0x42, 0x65, 0x73, 0x61, 0x72, 0x53, 0x75, 0x72, 0x2e, 0x3b, 0x53, 0x61,
+0x70, 0x2e, 0x3b, 0x4d, 0x75, 0x6c, 0x2e, 0x3b, 0x42, 0x2e, 0x20, 0x4d,
+0x75, 0x6c, 0x2e, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x41, 0x77, 0x2e,
+0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x41, 0x6b, 0x2e, 0x3b, 0x52, 0x65,
+0x6a, 0x2e, 0x3b, 0x52, 0x75, 0x77, 0x2e, 0x3b, 0x50, 0x73, 0x6f, 0x2e,
+0x3b, 0x53, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x53, 0x6c, 0x6f, 0x2e, 0x3b,
+0x42, 0x73, 0x61, 0x72, 0x2e, 0xcae, 0xcc1, 0xcb9, 0xcb0, 0xcae, 0xccd, 0x3b,
+0xcb8, 0xcab, 0xcbe, 0xcb0, 0xccd, 0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018, 0x20, 0x49,
+0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018, 0x20, 0x49, 0x49, 0x3b, 0xc9c, 0xcc1, 0xcae,
+0xcbe, 0xca6, 0xcbe, 0x20, 0x49, 0x3b, 0xc9c, 0xcc1, 0xcae, 0xcbe, 0xca6, 0xcbe,
+0x20, 0x49, 0x49, 0x3b, 0xcb0, 0xc9c, 0xcac, 0xccd, 0x3b, 0xcb6, 0x2019, 0xcac,
+0xcbe, 0xca8, 0xccd, 0x3b, 0xcb0, 0xcae, 0xca6, 0xcbe, 0xca8, 0xccd, 0x3b, 0xcb6,
+0xcb5, 0xccd, 0xcb5, 0xcbe, 0xcb2, 0xccd, 0x3b, 0xca7, 0xcc1, 0x2018, 0xcb2, 0xccd,
+0x2d, 0xc95, 0xcbf, 0x2018, 0xca1, 0xcbe, 0xcb9, 0xccd, 0x3b, 0xca7, 0xcc1, 0x2018,
+0xcb2, 0xccd, 0x2d, 0xcb9, 0xcbf, 0xc9c, 0xcbe, 0xcb9, 0xccd, 0xcae, 0xcc1, 0xcb9,
+0xccd, 0x2e, 0x3b, 0xcb8, 0xcab, 0xcbe, 0x2e, 0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018,
+0x20, 0x49, 0x3b, 0xcb0, 0xcac, 0xcbf, 0x2018, 0x20, 0x49, 0x49, 0x3b, 0xc9c,
+0xcc1, 0xcae, 0xccd, 0x2e, 0x20, 0x49, 0x3b, 0xc9c, 0xcc1, 0xcae, 0xccd, 0x2e,
+0x20, 0x49, 0x49, 0x3b, 0xcb0, 0xc9c, 0xccd, 0x2e, 0x3b, 0xcb6, 0x2e, 0x3b,
+0xcb0, 0xcae, 0xccd, 0x2e, 0x3b, 0xcb6, 0xcb5, 0xccd, 0x2e, 0x3b, 0xca7, 0xcc1,
+0x2018, 0xcb2, 0xccd, 0x2d, 0xc95, 0xcbf, 0x2e, 0x3b, 0xca7, 0xcc1, 0x2018, 0xcb2,
+0xccd, 0x2d, 0xcb9, 0x2e, 0x41c, 0x4b1, 0x445, 0x430, 0x440, 0x440, 0x430, 0x43c,
+0x3b, 0x421, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x493,
+0x20, 0x4d9, 0x43b, 0x2d, 0x4d9, 0x443, 0x443, 0x4d9, 0x43b, 0x3b, 0x420, 0x430,
+0x431, 0x438, 0x493, 0x20, 0x4d9, 0x441, 0x2d, 0x441, 0x4d9, 0x43d, 0x438, 0x3b,
+0x414, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x4d9, 0x43b, 0x2d, 0x4d9,
+0x443, 0x443, 0x4d9, 0x43b, 0x3b, 0x416, 0x443, 0x43c, 0x430, 0x434, 0x20, 0x430,
+0x441, 0x2d, 0x441, 0x4d9, 0x43d, 0x438, 0x3b, 0x420, 0x430, 0x434, 0x436, 0x430,
+0x431, 0x3b, 0x428, 0x430, 0x493, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c,
+0x430, 0x434, 0x430, 0x43d, 0x3b, 0x428, 0x4d9, 0x443, 0x443, 0x4d9, 0x43b, 0x3b,
+0x417, 0x443, 0x43b, 0x2d, 0x49a, 0x430, 0x493, 0x434, 0x430, 0x3b, 0x417, 0x443,
+0x43b, 0x2d, 0x425, 0x438, 0x434, 0x436, 0x430, 0x41c, 0x4b1, 0x445, 0x2e, 0x3b,
+0x421, 0x430, 0x444, 0x2e, 0x3b, 0x420, 0x430, 0x431, 0x2e, 0x20, 0x406, 0x3b,
+0x420, 0x430, 0x431, 0x2e, 0x20, 0x406, 0x406, 0x3b, 0x416, 0x443, 0x43c, 0x2e,
+0x20, 0x406, 0x3b, 0x416, 0x443, 0x43c, 0x2e, 0x20, 0x406, 0x406, 0x3b, 0x420,
+0x430, 0x434, 0x436, 0x2e, 0x3b, 0x428, 0x430, 0x493, 0x2e, 0x3b, 0x420, 0x430,
+0x43c, 0x2e, 0x3b, 0x428, 0x4d9, 0x443, 0x2e, 0x3b, 0x417, 0x443, 0x43b, 0x2d,
+0x49a, 0x2e, 0x3b, 0x417, 0x443, 0x43b, 0x2d, 0x425, 0x2e, 0x49a, 0x430, 0x4a3,
+0x2e, 0x3b, 0x410, 0x49b, 0x43f, 0x2e, 0x3b, 0x41d, 0x430, 0x443, 0x2e, 0x3b,
+0x421, 0x4d9, 0x443, 0x2e, 0x3b, 0x41c, 0x430, 0x43c, 0x2e, 0x3b, 0x4a, 0x75,
+0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442,
+0x430, 0x43c, 0x2e, 0x3b, 0x49a, 0x44b, 0x440, 0x2e, 0x3b, 0x49a, 0x430, 0x437,
+0x2e, 0x3b, 0x49a, 0x430, 0x440, 0x2e, 0x3b, 0x416, 0x435, 0x43b, 0x2e, 0xbb34,
+0xd558, 0xb78c, 0x3b, 0xc0ac, 0xd30c, 0xb974, 0x3b, 0xb77c, 0xbe44, 0x20, 0xc54c, 0x20,
+0xc544, 0xc648, 0x3b, 0xb77c, 0xbe44, 0x20, 0xc54c, 0x20, 0xc384, 0xb2c8, 0x3b, 0xc8fc,
+0xb9c8, 0xb2e4, 0x20, 0xc54c, 0x20, 0xc544, 0xc648, 0x3b, 0xc8fc, 0xb9c8, 0xb2e4, 0x20,
+0xc54c, 0x20, 0xc384, 0xb2c8, 0x3b, 0xb77c, 0xc7a1, 0x3b, 0xc250, 0xc544, 0xbc18, 0x3b,
+0xb77c, 0xb9c8, 0xb2e8, 0x3b, 0xc250, 0xc648, 0x3b, 0xb4c0, 0x20, 0xc54c, 0x20, 0xae4c,
+0xb2e4, 0x3b, 0xb4c0, 0x20, 0xc54c, 0x20, 0xd788, 0xc790, 0x6d, 0x75, 0x68, 0x65,
+0x72, 0x65, 0x6d, 0x3b, 0x73, 0x65, 0x66, 0x65, 0x72, 0x3b, 0x72, 0x65,
+0x62, 0xee, 0x2bf, 0x75, 0x6c, 0x65, 0x77, 0x65, 0x6c, 0x3b, 0x72, 0x65,
+0x62, 0xee, 0x2bf, 0x75, 0x6c, 0x61, 0x78, 0x65, 0x72, 0x3b, 0x63, 0x65,
+0x6d, 0x61, 0x7a, 0xee, 0x79, 0x65, 0x6c, 0x65, 0x77, 0x65, 0x6c, 0x3b,
+0x63, 0x65, 0x6d, 0x61, 0x7a, 0xee, 0x79, 0x65, 0x6c, 0x61, 0x78, 0x65,
+0x72, 0x3b, 0x72, 0x65, 0x63, 0x65, 0x62, 0x3b, 0x15f, 0x65, 0x2bf, 0x62,
+0x61, 0x6e, 0x3b, 0x72, 0x65, 0x6d, 0x65, 0x7a, 0x61, 0x6e, 0x3b, 0x15f,
+0x65, 0x77, 0x61, 0x6c, 0x3b, 0x7a, 0xee, 0x6c, 0x71, 0x65, 0x2bf, 0x64,
+0x65, 0x3b, 0x7a, 0x69, 0x6c, 0x68, 0x65, 0x63, 0x65, 0x6d, 0x75, 0x68,
+0x2e, 0x3b, 0x73, 0x65, 0x66, 0x2e, 0x3b, 0x72, 0x65, 0x62, 0x2e, 0x20,
+0x49, 0x65, 0x6d, 0x3b, 0x72, 0x65, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x79,
+0x65, 0x6d, 0x3b, 0x63, 0x6d, 0x7a, 0x2e, 0x20, 0x49, 0x65, 0x6d, 0x3b,
+0x63, 0x6d, 0x7a, 0x2e, 0x20, 0x49, 0x49, 0x79, 0x65, 0x6d, 0x3b, 0x72,
+0x63, 0x62, 0x2e, 0x3b, 0x15f, 0x62, 0x6e, 0x2e, 0x3b, 0x72, 0x6d, 0x7a,
+0x2e, 0x3b, 0x15f, 0x77, 0x6c, 0x2e, 0x3b, 0x7a, 0x71, 0x64, 0x2e, 0x3b,
+0x7a, 0x68, 0x63, 0x2e, 0xea1, 0xeb8, 0xea3, 0xeb0, 0xeae, 0xead, 0xea1, 0x3b,
+0xe8a, 0xeb2, 0xe9f, 0xeb2, 0xea3, 0x3b, 0xeae, 0xead, 0xe94, 0xe9a, 0xeb5, 0x20,
+0x31, 0x3b, 0xeae, 0xead, 0xe94, 0xe9a, 0xeb5, 0x20, 0x32, 0x3b, 0xe88, 0xeb8,
+0xea1, 0xeb2, 0xe94, 0xeb2, 0x20, 0x31, 0x3b, 0xe88, 0xeb8, 0xea1, 0xeb2, 0xe94,
+0xeb2, 0x20, 0x32, 0x3b, 0xeae, 0xeb2, 0xe88, 0xeb1, 0xe9a, 0x3b, 0xe8a, 0xeb0,
+0xe9a, 0xeb2, 0xe99, 0x3b, 0xeae, 0xeb2, 0xea1, 0xeb2, 0xe94, 0xead, 0xe99, 0x3b,
+0xec0, 0xe8a, 0xebb, 0xeb2, 0xea7, 0xeb1, 0xe94, 0x3b, 0xe94, 0xeb8, 0xead, 0xeb1,
+0xe94, 0xe81, 0xeb4, 0xe94, 0xeb0, 0x3b, 0xe94, 0xeb8, 0xead, 0xeb1, 0xe94, 0xe81,
+0xeb4, 0xe88, 0xeb0, 0xea1, 0xeb8, 0xeae, 0xeb1, 0xe94, 0x3b, 0xec0, 0xe84, 0xeb2,
+0xeb0, 0x3b, 0xeae, 0xead, 0xe81, 0xe9a, 0xeb5, 0x20, 0x31, 0x3b, 0xeae, 0xead,
+0xe81, 0xe9a, 0xeb5, 0x20, 0x32, 0x3b, 0xe99, 0xeb8, 0xea1, 0xeb2, 0x20, 0x31,
+0x3b, 0xe99, 0xeb8, 0xea1, 0xeb2, 0x20, 0x32, 0x3b, 0xec0, 0xeae, 0xeb2, 0xeb0,
+0x3b, 0xe8a, 0xeb2, 0x3b, 0xec0, 0xeae, 0xeb2, 0xeb0, 0xea1, 0xeb0, 0x3b, 0xec0,
+0xe8a, 0xebb, 0xeb2, 0x3b, 0xe8a, 0xeb8, 0xea5, 0xe81, 0xeb4, 0xead, 0xeb8, 0x3b,
+0xe8a, 0xeb8, 0xea5, 0xeab, 0xeb4, 0xe88, 0xea1, 0xeb8, 0xeae, 0xeb1, 0xe94, 0x3b,
+0xec0, 0xe84, 0xeb2, 0xeb0, 0x3b, 0xeae, 0xead, 0xe94, 0xe9a, 0xeb5, 0x20, 0x31,
+0x3b, 0xeae, 0xead, 0xe81, 0xe9a, 0xeb5, 0x20, 0x32, 0x3b, 0xe99, 0xeb8, 0xea1,
+0xeb2, 0x20, 0x31, 0x3b, 0xe99, 0xeb8, 0xea1, 0xeb2, 0x20, 0x32, 0x3b, 0xec0,
+0xeae, 0xeb2, 0xeb0, 0x3b, 0xe8a, 0xeb0, 0xead, 0xecc, 0x3b, 0xec0, 0xeae, 0xeb2,
+0xeb0, 0xea1, 0xeb0, 0x3b, 0xec0, 0xe8a, 0xebb, 0xeb2, 0x3b, 0xe8a, 0xeb8, 0xea5,
+0xe81, 0xeb4, 0xead, 0xeb8, 0x3b, 0xe8a, 0xeb8, 0xea5, 0xeab, 0xeb4, 0xe88, 0x6d,
+0x75, 0x68, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3b, 0x73, 0x61, 0x66, 0x61,
+0x72, 0x73, 0x3b, 0x31, 0x2e, 0x20, 0x72, 0x61, 0x62, 0x12b, 0x3b, 0x32,
+0x2e, 0x20, 0x72, 0x61, 0x62, 0x12b, 0x3b, 0x31, 0x2e, 0x20, 0x64, 0x17e,
+0x75, 0x6d, 0x101, 0x64, 0x101, 0x3b, 0x32, 0x2e, 0x20, 0x64, 0x17e, 0x75,
+0x6d, 0x101, 0x64, 0x101, 0x3b, 0x72, 0x61, 0x64, 0x17e, 0x61, 0x62, 0x73,
+0x3b, 0x161, 0x61, 0x62, 0x61, 0x6e, 0x73, 0x3b, 0x72, 0x61, 0x6d, 0x61,
+0x64, 0x101, 0x6e, 0x73, 0x3b, 0x161, 0x61, 0x75, 0x76, 0x61, 0x6c, 0x73,
+0x3b, 0x64, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x6b, 0x69, 0x64, 0x101, 0x3b,
+0x64, 0x75, 0x20, 0x61, 0x6c, 0x2d, 0x68, 0x69, 0x64, 0x17e, 0x101, 0x43c,
+0x443, 0x445, 0x430, 0x440, 0x435, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440,
+0x3b, 0x440, 0x430, 0x431, 0x438, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431, 0x438,
+0x20, 0x49, 0x49, 0x3b, 0x45f, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49,
+0x3b, 0x45f, 0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49, 0x49, 0x3b, 0x440,
+0x430, 0x45f, 0x430, 0x431, 0x3b, 0x448, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440,
+0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x448, 0x430, 0x432, 0x430, 0x43b,
+0x3b, 0x434, 0x443, 0x43b, 0x43a, 0x438, 0x434, 0x430, 0x3b, 0x434, 0x443, 0x43b,
+0x445, 0x438, 0x45f, 0x430, 0x43c, 0x443, 0x445, 0x2e, 0x3b, 0x441, 0x430, 0x444,
+0x2e, 0x3b, 0x440, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431,
+0x2e, 0x20, 0x49, 0x49, 0x3b, 0x45f, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x3b,
+0x45f, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x45f, 0x2e,
+0x3b, 0x448, 0x430, 0x431, 0x2e, 0x3b, 0x440, 0x430, 0x43c, 0x2e, 0x3b, 0x448,
+0x430, 0x432, 0x2e, 0x3b, 0x434, 0x443, 0x43b, 0x43a, 0x2e, 0x3b, 0x434, 0x443,
+0x43b, 0x445, 0x2e, 0xd2e, 0xd41, 0xd39, 0xd31, 0xd02, 0x3b, 0xd38, 0xd2b, 0xd7c,
+0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35,
+0xd7d, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f,
+0xd7c, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d,
+0xd35, 0xd7d, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16,
+0xd3f, 0xd7c, 0x3b, 0xd31, 0xd1c, 0xd2c, 0xd4d, 0x3b, 0xd36, 0xd39, 0xd2c, 0xd3e,
+0xd7b, 0x3b, 0xd31, 0xd2e, 0xd26, 0xd3e, 0xd7b, 0x3b, 0xd36, 0xd35, 0xd4d, 0xd35,
+0xd3e, 0xd7d, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd16, 0xd39, 0xd26, 0xd4d, 0x3b,
+0xd26, 0xd41, 0xd7d, 0x20, 0xd39, 0xd3f, 0xd1c, 0xd4d, 0xd1c, 0xd2e, 0xd41, 0xd39,
+0xd31, 0xd02, 0x3b, 0xd38, 0xd2b, 0xd7c, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41,
+0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35, 0xd7d, 0x3b, 0xd31, 0xd2c, 0xd40, 0xd39,
+0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0xd7c, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26,
+0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35, 0xd7d, 0x3b, 0xd1c, 0xd2e, 0xd3e,
+0xd26, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0xd7c, 0x3b, 0xd31, 0xd1c, 0xd2c,
+0xd4d, 0x3b, 0xd36, 0xd39, 0xd2c, 0xd3e, 0xd7b, 0x3b, 0xd31, 0xd2e, 0xd33, 0xd3e,
+0xd7b, 0x3b, 0xd36, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd7d, 0x3b, 0xd26, 0xd41, 0xd7d,
+0x20, 0xd16, 0xd39, 0xd26, 0xd4d, 0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd39, 0xd3f,
+0xd1c, 0xd4d, 0xd1c, 0xd2e, 0xd41, 0xd39, 0x2e, 0x3b, 0xd38, 0xd2b, 0x2e, 0x3b,
+0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35, 0x2e,
+0x3b, 0xd31, 0xd2c, 0xd40, 0xd39, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f, 0x2e,
+0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd05, 0xd35, 0xd4d, 0xd35,
+0x2e, 0x3b, 0xd1c, 0xd2e, 0xd3e, 0xd26, 0xd41, 0xd7d, 0x20, 0xd06, 0xd16, 0xd3f,
+0x2e, 0x3b, 0xd31, 0xd1c, 0x2e, 0x3b, 0xd36, 0xd39, 0xd2c, 0xd3e, 0x2e, 0x3b,
+0xd31, 0xd2e, 0xd26, 0xd3e, 0x2e, 0x3b, 0xd36, 0xd35, 0xd4d, 0xd35, 0xd3e, 0x2e,
+0x3b, 0xd26, 0xd41, 0xd7d, 0x20, 0xd16, 0xd39, 0x2e, 0x3b, 0xd26, 0xd41, 0xd7d,
+0x20, 0xd39, 0xd3f, 0x2e, 0xd2e, 0xd41, 0x3b, 0xd38, 0x3b, 0xd31, 0x3b, 0xd31,
+0x3b, 0xd1c, 0x3b, 0xd1c, 0x3b, 0xd31, 0x3b, 0xd36, 0x3b, 0xd31, 0x3b, 0xd36,
+0x3b, 0xd26, 0xd41, 0x3b, 0xd26, 0xd41, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x61,
+0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69,
+0x75, 0x6c, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x75,
+0x6c, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x64,
+0x69, 0x6c, 0x61, 0x77, 0x61, 0x6c, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x64,
+0x69, 0x6c, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x52, 0x65, 0x6a, 0x61,
+0x62, 0x3b, 0x53, 0x79, 0x61, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61,
+0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x79, 0x61, 0x77, 0x61, 0x6c,
+0x3b, 0x5a, 0x75, 0x6c, 0x6b, 0x61, 0x65, 0x64, 0x61, 0x68, 0x3b, 0x5a,
+0x75, 0x6c, 0x68, 0x69, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x68, 0x2e, 0x3b,
+0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b,
+0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x61, 0x6d, 0x2e,
+0x20, 0x49, 0x3b, 0x4a, 0x61, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52,
+0x65, 0x6a, 0x2e, 0x3b, 0x53, 0x79, 0x61, 0x61, 0x2e, 0x3b, 0x52, 0x61,
+0x6d, 0x2e, 0x3b, 0x53, 0x79, 0x61, 0x77, 0x2e, 0x3b, 0x5a, 0x75, 0x6c,
+0x6b, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x68, 0x2e, 0x92e, 0x94b, 0x939, 0x930,
+0x92e, 0x3b, 0x938, 0x92b, 0x930, 0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49,
+0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49, 0x49, 0x3b, 0x91c, 0x941, 0x92e,
+0x93e, 0x926, 0x93e, 0x20, 0x49, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x926, 0x93e,
+0x20, 0x49, 0x49, 0x3b, 0x930, 0x91d, 0x93e, 0x92c, 0x3b, 0x936, 0x93e, 0x92c,
+0x93e, 0x928, 0x3b, 0x930, 0x92e, 0x91c, 0x93e, 0x928, 0x3b, 0x936, 0x935, 0x94d,
+0x935, 0x93e, 0x932, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x915, 0x940, 0x926, 0x93e,
+0x939, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x939, 0x93f, 0x91c, 0x93e, 0x939, 0x92e,
+0x94b, 0x939, 0x2e, 0x3b, 0x938, 0x92b, 0x2e, 0x3b, 0x930, 0x93e, 0x92c, 0x940,
+0x20, 0x49, 0x3b, 0x930, 0x93e, 0x92c, 0x940, 0x20, 0x49, 0x49, 0x3b, 0x91c,
+0x941, 0x92e, 0x93e, 0x2e, 0x20, 0x49, 0x3b, 0x91c, 0x941, 0x92e, 0x93e, 0x2e,
+0x20, 0x49, 0x49, 0x3b, 0x930, 0x91d, 0x93e, 0x2e, 0x3b, 0x936, 0x93e, 0x92c,
+0x93e, 0x2e, 0x3b, 0x930, 0x92e, 0x2e, 0x3b, 0x936, 0x935, 0x94d, 0x935, 0x93e,
+0x2e, 0x3b, 0x927, 0x941, 0x932, 0x2d, 0x915, 0x940, 0x2e, 0x3b, 0x927, 0x941,
+0x932, 0x2d, 0x939, 0x93f, 0x2e, 0x967, 0x3b, 0x968, 0x3b, 0x969, 0x3b, 0x96a,
+0x3b, 0x96b, 0x3b, 0x96c, 0x3b, 0x96d, 0x3b, 0x96e, 0x3b, 0x96f, 0x3b, 0x967,
+0x966, 0x3b, 0x967, 0x967, 0x3b, 0x967, 0x968, 0x6d, 0x75, 0x68, 0x61, 0x72,
+0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61,
+0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20,
+0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b,
+0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61,
+0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b,
+0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77,
+0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x69,
+0x2bb, 0x64, 0x61, 0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x68,
+0x69, 0x6a, 0x6a, 0x61, 0x68, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61,
+0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61,
+0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49,
+0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a,
+0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b,
+0x73, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d,
+0x71, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x48, 0x2e, 0x6d,
+0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b, 0x72, 0x61, 0x62,
+0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b,
+0x6a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x2e, 0x20,
+0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e,
+0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x2e, 0x3b,
+0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x2e, 0x3b, 0x64, 0x68, 0x75,
+0x2bb, 0x6c, 0x2d, 0x68, 0x2e, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641,
+0x631, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20,
+0x49, 0x49, 0x3b, 0x62c, 0x645, 0x627, 0x639, 0x647, 0x3b, 0x62c, 0x645, 0x627,
+0x639, 0x647, 0x20, 0x49, 0x49, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639,
+0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648,
+0x627, 0x644, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x647,
+0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645,
+0x3b, 0x635, 0x641, 0x631, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628,
+0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x20, 0x6f1,
+0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x20, 0x6f2, 0x3b, 0x631, 0x62c, 0x628, 0x3b,
+0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b,
+0x634, 0x648, 0x627, 0x644, 0x3b, 0x62f, 0x627, 0x644, 0x642, 0x627, 0x639, 0x62f,
+0x647, 0x3b, 0x630, 0x64a, 0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631,
+0x645, 0x3b, 0x62f, 0x20, 0x635, 0x641, 0x631, 0x6d2, 0x20, 0x62f, 0x3b, 0x631,
+0x628, 0x64a, 0x639, 0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x49, 0x49, 0x3b,
+0x62c, 0x645, 0x627, 0x639, 0x647, 0x3b, 0x62c, 0x645, 0x627, 0x639, 0x647, 0x20,
+0x49, 0x49, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646,
+0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b,
+0x630, 0x64a, 0x20, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x647, 0x3b, 0x630, 0x64a,
+0x20, 0x627, 0x644, 0x62d, 0x62c, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641,
+0x631, 0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x200c, 0x627, 0x644, 0x627, 0x648, 0x644,
+0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x200c, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x6cc,
+0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x200c, 0x627, 0x644, 0x627, 0x648, 0x644,
+0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x200c, 0x627, 0x644, 0x62b, 0x627, 0x646,
+0x6cc, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b,
+0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630,
+0x6cc, 0x642, 0x639, 0x62f, 0x647, 0x3b, 0x630, 0x6cc, 0x62d, 0x62c, 0x647, 0x645,
+0x3b, 0x635, 0x3b, 0x631, 0x3b, 0x631, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x631,
+0x3b, 0x634, 0x3b, 0x631, 0x3b, 0x634, 0x3b, 0x630, 0x3b, 0x630, 0x4d, 0x75,
+0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72,
+0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x52, 0x61, 0x62,
+0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x44, 0x17c, 0x75, 0x6d, 0x61, 0x64,
+0x61, 0x20, 0x49, 0x3b, 0x44, 0x17c, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20,
+0x49, 0x49, 0x3b, 0x52, 0x61, 0x64, 0x17c, 0x61, 0x62, 0x3b, 0x53, 0x7a,
+0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e,
+0x3b, 0x53, 0x7a, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x5a, 0x75, 0x20,
+0x61, 0x6c, 0x2d, 0x6b, 0x61, 0x64, 0x61, 0x3b, 0x5a, 0x75, 0x20, 0x61,
+0x6c, 0x2d, 0x68, 0x69, 0x64, 0x17c, 0x64, 0x17c, 0x61, 0x4d, 0x75, 0x68,
+0x2e, 0x3b, 0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20,
+0x49, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x44, 0x17c,
+0x75, 0x2e, 0x20, 0x49, 0x3b, 0x44, 0x17c, 0x75, 0x2e, 0x20, 0x49, 0x49,
+0x3b, 0x52, 0x61, 0x2e, 0x3b, 0x53, 0x7a, 0x61, 0x2e, 0x3b, 0x52, 0x61,
+0x6d, 0x2e, 0x3b, 0x53, 0x7a, 0x61, 0x77, 0x2e, 0x3b, 0x5a, 0x75, 0x20,
+0x61, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x5a, 0x75, 0x20, 0x61, 0x6c, 0x2d,
+0x68, 0x2e, 0xa2e, 0xa41, 0xa39, 0xa71, 0xa30, 0xa2e, 0x3b, 0xa38, 0xa2b, 0xa30,
+0x3b, 0xa30, 0xa2c, 0xa40, 0x2bb, 0x20, 0x49, 0x3b, 0xa30, 0xa2c, 0xa40, 0x2bb,
+0x20, 0x49, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49,
+0x3b, 0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49, 0x49, 0x3b, 0xa30,
+0xa1c, 0xa2c, 0x3b, 0xa38, 0xa3c, 0xa2c, 0xa3e, 0xa28, 0x3b, 0xa30, 0xa2e, 0xa1c,
+0xa3c, 0xa3e, 0xa28, 0x3b, 0xa38, 0xa3c, 0xa35, 0xa3e, 0xa32, 0x3b, 0xa26, 0xa42,
+0x2d, 0xa05, 0xa32, 0x2d, 0xa15, 0xa40, 0xa26, 0xa3e, 0xa39, 0x3b, 0xa26, 0xa42,
+0x2d, 0xa05, 0xa32, 0x2d, 0xa39, 0xa3f, 0xa1c, 0xa4d, 0xa39, 0xa3e, 0xa2e, 0xa41,
+0xa39, 0xa71, 0xa30, 0xa2e, 0x3b, 0xa38, 0xa2b, 0xa30, 0x3b, 0xa30, 0xa2c, 0xa40,
+0x20, 0x2bb, 0x20, 0x49, 0x3b, 0xa30, 0xa2c, 0xa40, 0x20, 0x2bb, 0x20, 0x49,
+0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49, 0x3b, 0xa1c,
+0xa41, 0xa2e, 0xa3e, 0xa26, 0xa3e, 0x20, 0x49, 0x49, 0x3b, 0xa30, 0xa1c, 0xa2c,
+0x3b, 0xa38, 0xa3c, 0xa2c, 0xa3e, 0xa28, 0x3b, 0xa30, 0xa2e, 0xa1c, 0xa3c, 0xa3e,
+0xa28, 0x3b, 0xa38, 0xa3c, 0xa35, 0xa3e, 0xa32, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05,
+0xa32, 0x2d, 0xa15, 0xa40, 0xa26, 0xa3e, 0xa39, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05,
+0xa32, 0x2d, 0xa39, 0xa3f, 0xa1c, 0xa4d, 0xa39, 0xa3e, 0xa2e, 0xa41, 0xa39, 0xa71,
+0x2e, 0x3b, 0xa38, 0xa2b, 0x2e, 0x3b, 0xa30, 0xa2c, 0x2e, 0x20, 0x49, 0x3b,
+0xa30, 0xa2c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0x2e, 0x20,
+0x49, 0x3b, 0xa1c, 0xa41, 0xa2e, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0xa30, 0xa3e,
+0xa1c, 0x2e, 0x3b, 0xa38, 0xa3c, 0xa3e, 0x2e, 0x3b, 0xa30, 0xa3e, 0xa2e, 0x2e,
+0x3b, 0xa38, 0xa3c, 0xa05, 0x2e, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d,
+0xa15, 0xa40, 0x2e, 0x3b, 0xa26, 0xa42, 0x2d, 0xa05, 0xa32, 0x2d, 0xa39, 0xa3f,
+0x2e, 0x43c, 0x443, 0x445, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430,
+0x444, 0x430, 0x440, 0x3b, 0x440, 0x430, 0x431, 0x438, 0x2d, 0x443, 0x43b, 0x44c,
+0x2d, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x44c, 0x3b, 0x440, 0x430, 0x431, 0x438,
+0x2d, 0x443, 0x43b, 0x44c, 0x2d, 0x430, 0x445, 0x438, 0x440, 0x3b, 0x434, 0x436,
+0x443, 0x43c, 0x430, 0x434, 0x2d, 0x443, 0x43b, 0x44c, 0x2d, 0x430, 0x432, 0x432,
+0x430, 0x43b, 0x44c, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x2d, 0x443,
+0x43b, 0x44c, 0x2d, 0x430, 0x445, 0x438, 0x440, 0x3b, 0x440, 0x430, 0x434, 0x436,
+0x430, 0x431, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430,
+0x43c, 0x430, 0x434, 0x430, 0x43d, 0x3b, 0x448, 0x430, 0x432, 0x432, 0x430, 0x43b,
+0x44c, 0x3b, 0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x43a, 0x430, 0x430, 0x434, 0x430,
+0x3b, 0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x445, 0x438, 0x434, 0x436, 0x436, 0x430,
+0x43c, 0x443, 0x445, 0x2e, 0x3b, 0x441, 0x430, 0x444, 0x2e, 0x3b, 0x440, 0x430,
+0x431, 0x2e, 0x20, 0x49, 0x3b, 0x440, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x49,
+0x3b, 0x434, 0x436, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x3b, 0x434, 0x436, 0x443,
+0x43c, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x434, 0x436, 0x2e, 0x3b,
+0x448, 0x430, 0x430, 0x431, 0x2e, 0x3b, 0x440, 0x430, 0x43c, 0x2e, 0x3b, 0x448,
+0x430, 0x432, 0x2e, 0x3b, 0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x43a, 0x2e, 0x3b,
+0x437, 0x443, 0x43b, 0x44c, 0x2d, 0x445, 0x2e, 0x6d, 0x75, 0x68, 0x61, 0x72,
+0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61,
+0x62, 0x69, 0x2bb, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20,
+0x49, 0x49, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b,
+0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61,
+0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x72,
+0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x77,
+0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x69, 0x2bb,
+0x64, 0x61, 0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x68, 0x69,
+0x6a, 0x6a, 0x61, 0x68, 0x41c, 0x443, 0x445, 0x430, 0x440, 0x435, 0x43c, 0x3b,
+0x421, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x2bb, 0x20,
+0x49, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x408,
+0x443, 0x43c, 0x430, 0x434, 0x430, 0x20, 0x49, 0x3b, 0x408, 0x443, 0x43c, 0x430,
+0x434, 0x430, 0x20, 0x49, 0x49, 0x3b, 0x420, 0x430, 0x452, 0x430, 0x431, 0x3b,
+0x428, 0x430, 0x2bb, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434,
+0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x430, 0x43b, 0x3b, 0x414, 0x443, 0x2bb,
+0x43b, 0x2d, 0x41a, 0x438, 0x2bb, 0x434, 0x430, 0x3b, 0x414, 0x443, 0x2bb, 0x43b,
+0x2d, 0x445, 0x438, 0x452, 0x430, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x65, 0x6d,
+0x3b, 0x53, 0x61, 0x66, 0x65, 0x72, 0x3b, 0x52, 0x65, 0x62, 0x69, 0x20,
+0x31, 0x3b, 0x52, 0x65, 0x62, 0x69, 0x20, 0x32, 0x3b, 0x44, 0x17e, 0x75,
+0x6d, 0x61, 0x64, 0x65, 0x20, 0x31, 0x3b, 0x44, 0x17e, 0x75, 0x6d, 0x61,
+0x64, 0x65, 0x20, 0x32, 0x3b, 0x52, 0x65, 0x64, 0x17e, 0x65, 0x62, 0x3b,
+0x160, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a,
+0x61, 0x6e, 0x3b, 0x160, 0x65, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x75, 0x6c,
+0x2d, 0x6b, 0x61, 0x64, 0x65, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x68, 0x69,
+0x64, 0x17e, 0x65, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x65, 0x6d, 0x3b, 0x53,
+0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49,
+0x3b, 0x52, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64,
+0x61, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x111, 0x61, 0x62, 0x3b, 0x160,
+0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61,
+0x6e, 0x3b, 0x160, 0x61, 0x76, 0x61, 0x6c, 0x3b, 0x44, 0x75, 0x2bb, 0x6c,
+0x2d, 0x4b, 0x69, 0x2bb, 0x64, 0x61, 0x3b, 0x44, 0x75, 0x2bb, 0x6c, 0x2d,
+0x68, 0x69, 0x111, 0x61, 0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53, 0x61, 0x66,
+0x2e, 0x3b, 0x52, 0x65, 0x62, 0x2e, 0x20, 0x31, 0x3b, 0x52, 0x65, 0x62,
+0x2e, 0x20, 0x32, 0x3b, 0x44, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x31, 0x3b,
+0x44, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x32, 0x3b, 0x52, 0x65, 0x64, 0x17e,
+0x2e, 0x3b, 0x160, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x160,
+0x65, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b, 0x5a, 0x75,
+0x6c, 0x2d, 0x68, 0x2e, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631,
+0x3b, 0x631, 0x628, 0x64a, 0x639, 0x20, 0x627, 0x644, 0x627, 0x648, 0x644, 0x3b,
+0x631, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x627, 0x62e, 0x631, 0x3b, 0x62c,
+0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x627, 0x648, 0x644, 0x3b, 0x62c,
+0x645, 0x627, 0x62f, 0x64a, 0x20, 0x627, 0x644, 0x627, 0x62e, 0x631, 0x3b, 0x631,
+0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x645, 0x636,
+0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b, 0x630, 0x648, 0x627, 0x644,
+0x642, 0x639, 0x62f, 0x3b, 0x630, 0x648, 0x627, 0x644, 0x62d, 0x62c, 0x6c1, 0x61,
+0x6c, 0x2d, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73,
+0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0xed, 0xb4, 0x20, 0x61,
+0x6c, 0x2d, 0x61, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x72, 0x61, 0x62, 0xed,
+0xb4, 0x61, 0x74, 0x68, 0x2d, 0x74, 0x68, 0xe1, 0x6e, 0xed, 0x3b, 0x64,
+0x17e, 0x75, 0x6d, 0xe1, 0x64, 0xe1, 0x20, 0x6c, 0x2d, 0xfa, 0x6c, 0xe1,
+0x3b, 0x64, 0x17e, 0x75, 0x6d, 0xe1, 0x64, 0xe1, 0x20, 0x6c, 0x2d, 0xe1,
+0x63, 0x68, 0x69, 0x72, 0x61, 0x3b, 0x72, 0x61, 0x64, 0x17e, 0x61, 0x62,
+0x3b, 0x161, 0x61, 0xb4, 0x20, 0x62, 0xe1, 0x6e, 0x3b, 0x72, 0x61, 0x6d,
+0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x161, 0x61, 0x75, 0x76, 0xe1, 0x6c, 0x3b,
+0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d, 0x6b, 0x61, 0xb4, 0x20, 0x64, 0x61,
+0x3b, 0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d, 0x68, 0x69, 0x64, 0x17e, 0x64,
+0x17e, 0x61, 0x6d, 0x75, 0x68, 0x2e, 0x3b, 0x73, 0x61, 0x66, 0x2e, 0x3b,
+0x72, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x2e, 0x20,
+0x49, 0x49, 0x3b, 0x64, 0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x3b, 0x64,
+0x17e, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x64, 0x2e,
+0x3b, 0x161, 0x61, 0x2e, 0x3b, 0x72, 0x61, 0x6d, 0x2e, 0x3b, 0x161, 0x61,
+0x75, 0x2e, 0x3b, 0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d, 0x6b, 0x2e, 0x3b,
+0x64, 0x68, 0xfa, 0x20, 0x6c, 0x2d, 0x68, 0x2e, 0x4d, 0x75, 0x78, 0x61,
+0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52,
+0x61, 0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61,
+0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d, 0x74,
+0x68, 0x61, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20,
+0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x6a, 0x75, 0x6d,
+0x61, 0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69,
+0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x63, 0x62,
+0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53,
+0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x75, 0x6c, 0x20, 0x61,
+0x6c, 0x2d, 0x71, 0x61, 0x63, 0x64, 0x61, 0x68, 0x3b, 0x44, 0x75, 0x6c,
+0x20, 0x78, 0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x78, 0x61, 0x72,
+0x72, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61,
+0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c,
+0x3b, 0x52, 0x61, 0x62, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68,
+0x61, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x61,
+0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x6a, 0x75, 0x6d, 0x61,
+0x64, 0x61, 0x20, 0x61, 0x6c, 0x2d, 0x74, 0x68, 0x61, 0x6e, 0x69, 0x3b,
+0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68, 0x61, 0x63, 0x62, 0x61,
+0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x53, 0x68,
+0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x75, 0x6c, 0x20, 0x61, 0x6c,
+0x2d, 0x71, 0x61, 0x63, 0x64, 0x61, 0x3b, 0x44, 0x75, 0x6c, 0x20, 0x78,
+0x69, 0x6a, 0x6a, 0x61, 0x68, 0x4d, 0x75, 0x78, 0x2e, 0x3b, 0x53, 0x61,
+0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b, 0x52, 0x61,
+0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49,
+0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52, 0x61, 0x6a,
+0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b,
+0x53, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x44, 0x75, 0x6c, 0x2d, 0x51, 0x2e,
+0x3b, 0x44, 0x75, 0x6c, 0x2d, 0x58, 0x2e, 0x4d, 0x75, 0x78, 0x2e, 0x3b,
+0x53, 0x61, 0x66, 0x2e, 0x3b, 0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x3b,
+0x52, 0x61, 0x62, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e,
+0x20, 0x49, 0x3b, 0x4a, 0x75, 0x6d, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x52,
+0x61, 0x6a, 0x2e, 0x3b, 0x53, 0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d,
+0x2e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x2e, 0x3b, 0x44, 0x75, 0x6c, 0x2019,
+0x2d, 0x51, 0x69, 0x63, 0x64, 0x61, 0x2e, 0x3b, 0x44, 0x68, 0x75, 0x2bb,
+0x6c, 0x2d, 0x48, 0x2e, 0x6d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d,
+0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb,
+0x20, 0x49, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2bb, 0x20, 0x49, 0x49, 0x3b,
+0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x20, 0x49, 0x3b, 0x6a, 0x75, 0x6d,
+0x61, 0x64, 0x61, 0x20, 0x49, 0x49, 0x3b, 0x72, 0x61, 0x6a, 0x61, 0x62,
+0x3b, 0x73, 0x68, 0x61, 0x2bb, 0x62, 0x61, 0x6e, 0x3b, 0x72, 0x61, 0x6d,
+0x61, 0x64, 0xe1, 0x6e, 0x3b, 0x73, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c,
+0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x71, 0x69, 0x2bb, 0x64, 0x61,
+0x68, 0x3b, 0x64, 0x68, 0x75, 0x2bb, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a,
+0x61, 0x68, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x53,
+0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61,
+0x6c, 0x2d, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x69,
+0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x4a,
+0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x75, 0x6c, 0x61, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x64, 0x61, 0x2d, 0x6c, 0x2d, 0x61, 0x6b, 0x68,
+0x69, 0x72, 0x61, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53, 0x68,
+0x61, 0x2019, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x64, 0x61,
+0x6e, 0x3b, 0x53, 0x68, 0x61, 0x77, 0x77, 0x61, 0x6c, 0x3b, 0x44, 0x68,
+0x75, 0x2d, 0x6c, 0x2d, 0x67, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x44, 0x68,
+0x75, 0x2d, 0x6c, 0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61, 0x6d, 0x75, 0x68,
+0x61, 0x72, 0x72, 0x61, 0x6d, 0x3b, 0x73, 0x61, 0x66, 0x61, 0x72, 0x3b,
+0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d, 0x61, 0x77, 0x77,
+0x61, 0x6c, 0x3b, 0x72, 0x61, 0x62, 0x69, 0x2019, 0x20, 0x61, 0x6c, 0x2d,
+0x61, 0x6b, 0x68, 0x69, 0x72, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64, 0x61,
+0x2d, 0x6c, 0x2d, 0x75, 0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x64,
+0x61, 0x2d, 0x6c, 0x2d, 0x61, 0x6b, 0x68, 0x69, 0x72, 0x61, 0x3b, 0x72,
+0x61, 0x6a, 0x61, 0x62, 0x3b, 0x73, 0x68, 0x61, 0x2019, 0x62, 0x61, 0x6e,
+0x3b, 0x72, 0x61, 0x6d, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x61,
+0x77, 0x77, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x67,
+0x61, 0x2019, 0x64, 0x61, 0x3b, 0x64, 0x68, 0x75, 0x2d, 0x6c, 0x2d, 0x68,
+0x69, 0x6a, 0x6a, 0x61, 0x43c, 0x443, 0x4b3, 0x430, 0x440, 0x440, 0x430, 0x43c,
+0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a,
+0x20, 0x49, 0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a, 0x20, 0x49, 0x49, 0x3b,
+0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443, 0x43b, 0x2d, 0x443, 0x43b,
+0x43e, 0x3b, 0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443, 0x43b, 0x2d,
+0x441, 0x43e, 0x43d, 0x438, 0x3b, 0x440, 0x430, 0x4b7, 0x430, 0x431, 0x3b, 0x428,
+0x430, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434, 0x430, 0x43d,
+0x3b, 0x428, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x414, 0x445, 0x443, 0x43b,
+0x2d, 0x49a, 0x438, 0x434, 0x430, 0x4b3, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d,
+0x4b2, 0x438, 0x4b7, 0x4b7, 0x430, 0x4b3, 0x43c, 0x443, 0x4b3, 0x430, 0x440, 0x440,
+0x430, 0x43c, 0x3b, 0x441, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431,
+0x435, 0x44a, 0x20, 0x49, 0x3b, 0x420, 0x430, 0x431, 0x435, 0x44a, 0x20, 0x49,
+0x49, 0x3b, 0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443, 0x43b, 0x2d,
+0x443, 0x43b, 0x43e, 0x3b, 0x4b7, 0x438, 0x43c, 0x43e, 0x434, 0x438, 0x2d, 0x443,
+0x43b, 0x2d, 0x441, 0x43e, 0x43d, 0x438, 0x3b, 0x440, 0x430, 0x4b7, 0x430, 0x431,
+0x3b, 0x428, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x420, 0x430, 0x43c, 0x430, 0x434,
+0x430, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x414, 0x445,
+0x443, 0x442, 0x2d, 0x49a, 0x438, 0x434, 0x430, 0x4b3, 0x3b, 0x414, 0x445, 0x443,
+0x442, 0x2d, 0x4b2, 0x438, 0x4b7, 0x4b7, 0x430, 0x4b3, 0x41c, 0x443, 0x4b3, 0x2e,
+0x3b, 0x421, 0x430, 0x444, 0x2e, 0x3b, 0x420, 0x430, 0x431, 0x2e, 0x20, 0x49,
+0x3b, 0x420, 0x430, 0x431, 0x2e, 0x20, 0x49, 0x49, 0x3b, 0x4b6, 0x443, 0x43c,
+0x2e, 0x20, 0x49, 0x3b, 0x4b6, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x49, 0x3b,
+0x420, 0x430, 0x4b7, 0x2e, 0x3b, 0x428, 0x430, 0x2e, 0x3b, 0x420, 0x430, 0x43c,
+0x2e, 0x3b, 0x428, 0x430, 0x432, 0x2e, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d,
+0x49a, 0x2e, 0x3b, 0x414, 0x445, 0x443, 0x43b, 0x2d, 0x4b2, 0x2e, 0xbae, 0xbc1,
+0xbb9, 0xbb0, 0xbcd, 0xbb0, 0xbae, 0xbcd, 0x3b, 0xb9a, 0xb83, 0xbaa, 0xbb0, 0xbcd,
+0x3b, 0xbb0, 0xbaa, 0xbbf, 0x20, 0x31, 0x3b, 0xbb0, 0xbaa, 0xbbf, 0x20, 0x32,
+0x3b, 0xb9c, 0xbc1, 0xbae, 0xba4, 0xbbe, 0x20, 0x31, 0x3b, 0xb9c, 0xbc1, 0xbae,
+0xba4, 0xbbe, 0x20, 0x32, 0x3b, 0xbb0, 0xb9c, 0xbaa, 0xbcd, 0x3b, 0xbb7, 0xb83,
+0xbaa, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xbb0, 0xbae, 0xbb2, 0xbbe, 0xba9, 0xbcd, 0x3b,
+0xbb7, 0xbb5, 0xbcd, 0xbb5, 0xbbe, 0xbb2, 0xbcd, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd,
+0x20, 0xb95, 0xb83, 0xba4, 0xbbe, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd, 0x20, 0xbb9,
+0xbbf, 0xb9c, 0xbcd, 0xb9c, 0xbbe, 0xbae, 0xbc1, 0xbb9, 0x2e, 0x3b, 0xb9a, 0xb83,
+0xbaa, 0x2e, 0x3b, 0xbb0, 0xbaa, 0xbbf, 0x20, 0x31, 0x3b, 0xbb0, 0xbaa, 0xbbf,
+0x20, 0x32, 0x3b, 0xb9c, 0xbc1, 0xbae, 0x2e, 0x20, 0x31, 0x3b, 0xb9c, 0xbc1,
+0xbae, 0x2e, 0x20, 0x32, 0x3b, 0xbb0, 0xb9c, 0x2e, 0x3b, 0xbb7, 0xb83, 0x2e,
+0x3b, 0xbb0, 0xbae, 0x2e, 0x3b, 0xbb7, 0xbb5, 0xbcd, 0x2e, 0x3b, 0xba4, 0xbc1,
+0xbb2, 0xbcd, 0x20, 0xb95, 0xb83, 0x2e, 0x3b, 0xba4, 0xbc1, 0xbb2, 0xbcd, 0x20,
+0xbb9, 0xbbf, 0xb9c, 0xbcd, 0x2e, 0xc2e, 0xc41, 0xc39, 0xc30, 0xc4d, 0xc30, 0xc02,
+0x3b, 0xc38, 0xc2b, 0xc30, 0xc4d, 0x3b, 0xc30, 0xc2c, 0xc40, 0x20, 0x49, 0x3b,
+0xc30, 0xc2c, 0xc40, 0x20, 0x49, 0x49, 0x3b, 0xc1c, 0xc41, 0xc2e, 0xc26, 0xc3e,
+0x20, 0x49, 0x3b, 0xc1c, 0xc41, 0xc2e, 0xc26, 0xc3e, 0x20, 0x49, 0x49, 0x3b,
+0xc30, 0xc1c, 0xc2c, 0xc4d, 0x3b, 0xc37, 0xc2c, 0xc3e, 0xc28, 0xc4d, 0x3b, 0xc30,
+0xc02, 0xc1c, 0xc3e, 0xc28, 0xc4d, 0x3b, 0xc37, 0xc35, 0xc4d, 0xc35, 0xc3e, 0xc32,
+0xc4d, 0x3b, 0xc27, 0xc41, 0xc32, 0xc4d, 0x2d, 0xc15, 0xc3f, 0x20, 0xc26, 0xc3e,
+0xc39, 0xc4d, 0x3b, 0xc27, 0xc41, 0xc32, 0xc4d, 0x2d, 0xc39, 0xc3f, 0xc1c, 0xc4d,
+0xc1c, 0xc3e, 0xc39, 0xc4d, 0xc2e, 0xc41, 0xc39, 0x2e, 0x3b, 0xc38, 0xc2b, 0x2e,
+0x3b, 0xc30, 0x2e, 0x20, 0x49, 0x3b, 0xc30, 0x2e, 0x20, 0x49, 0x49, 0x3b,
+0xc1c, 0xc41, 0xc2e, 0x2e, 0x20, 0x49, 0x3b, 0xc1c, 0xc41, 0xc2e, 0x2e, 0x20,
+0x49, 0x49, 0x3b, 0xc30, 0xc1c, 0x2e, 0x3b, 0xc37, 0xc2c, 0xc3e, 0x2e, 0x3b,
+0xc30, 0xc02, 0xc1c, 0xc3e, 0x2e, 0x3b, 0xc37, 0xc35, 0xc4d, 0xc35, 0xc3e, 0x2e,
+0x3b, 0xc27, 0xc41, 0xc32, 0xc4d, 0x2d, 0xc15, 0xc3f, 0x2e, 0x3b, 0xc27, 0xc41,
+0xc32, 0xc4d, 0x2d, 0xc39, 0xc3f, 0x2e, 0xe21, 0xe38, 0xe2e, 0xe30, 0xe23, 0xe4c,
+0xe23, 0xe2d, 0xe21, 0x3b, 0xe0b, 0xe2d, 0xe1f, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe23,
+0xe2d, 0xe1a, 0xe35, 0x20, 0x49, 0x3b, 0xe23, 0xe2d, 0xe1a, 0xe35, 0x20, 0x49,
+0x49, 0x3b, 0xe08, 0xe38, 0xe21, 0xe32, 0xe14, 0xe32, 0x20, 0x49, 0x3b, 0xe08,
+0xe38, 0xe21, 0xe32, 0xe14, 0xe32, 0x20, 0x49, 0x49, 0x3b, 0xe23, 0xe2d, 0xe08,
+0xe31, 0xe1a, 0x3b, 0xe0a, 0xe30, 0xe2d, 0xe30, 0xe1a, 0xe32, 0xe19, 0x3b, 0xe23,
+0xe2d, 0xe21, 0xe30, 0xe14, 0xe2d, 0xe19, 0x3b, 0xe40, 0xe0a, 0xe32, 0xe27, 0xe31,
+0xe25, 0x3b, 0xe0b, 0xe38, 0xe25, 0xe01, 0xe34, 0xe2d, 0xe3a, 0xe14, 0xe30, 0xe2e,
+0xe3a, 0x3b, 0xe0b, 0xe38, 0xe25, 0xe2b, 0xe34, 0xe08, 0xe0d, 0xe30, 0xe2e, 0xe3a,
+0xe21, 0xe38, 0xe2e, 0xe31, 0xe23, 0x2e, 0x3b, 0xe40, 0xe28, 0xe32, 0xe30, 0x2e,
+0x3b, 0xe23, 0xe2d, 0xe1a, 0xe35, 0x20, 0x49, 0x3b, 0xe23, 0xe2d, 0xe1a, 0xe35,
+0x20, 0x49, 0x49, 0x3b, 0xe08, 0xe38, 0xe21, 0xe32, 0xe14, 0xe32, 0x20, 0x49,
+0x3b, 0xe08, 0xe38, 0xe21, 0xe32, 0xe14, 0xe32, 0x20, 0x49, 0x49, 0x3b, 0xe40,
+0xe23, 0xe32, 0xe30, 0x2e, 0x3b, 0xe0a, 0xe30, 0xe2d, 0xe4c, 0x2e, 0x3b, 0xe40,
+0xe23, 0xe32, 0xe30, 0xe21, 0xe30, 0x2e, 0x3b, 0xe40, 0xe0a, 0xe32, 0xe27, 0x2e,
+0x3b, 0xe0b, 0xe38, 0xe25, 0xe01, 0xe34, 0xe2d, 0xe3a, 0x2e, 0x3b, 0xe0b, 0xe38,
+0xe25, 0xe2b, 0xe34, 0xe08, 0x2e, 0x4d, 0x75, 0x68, 0x61, 0x6c, 0x61, 0x6d,
+0x69, 0x3b, 0x53, 0x61, 0x66, 0x61, 0x6c, 0x69, 0x3b, 0x4c, 0x61, 0x70,
+0x12b, 0x20, 0x49, 0x3b, 0x4c, 0x61, 0x70, 0x12b, 0x20, 0x49, 0x49, 0x3b,
+0x53, 0x75, 0x6d, 0x61, 0x74, 0x101, 0x20, 0x49, 0x3b, 0x53, 0x75, 0x6d,
+0x61, 0x74, 0x101, 0x20, 0x49, 0x49, 0x3b, 0x4c, 0x61, 0x73, 0x61, 0x70,
+0x69, 0x3b, 0x53, 0x61, 0x2bb, 0x61, 0x70, 0x101, 0x6e, 0x69, 0x3b, 0x4c,
+0x61, 0x6d, 0x61, 0x74, 0x101, 0x6e, 0x69, 0x3b, 0x53, 0x61, 0x76, 0x101,
+0x6c, 0x69, 0x3b, 0x53, 0x16b, 0x2d, 0x6b, 0x61, 0x2bb, 0x61, 0x74, 0x61,
+0x3b, 0x53, 0x16b, 0x2d, 0x68, 0x69, 0x73, 0x61, 0x4d, 0x75, 0x68, 0x3b,
+0x53, 0x61, 0x66, 0x3b, 0x4c, 0x61, 0x70, 0x20, 0x49, 0x3b, 0x4c, 0x61,
+0x70, 0x20, 0x49, 0x49, 0x3b, 0x53, 0x75, 0x6d, 0x20, 0x49, 0x3b, 0x53,
+0x75, 0x6d, 0x20, 0x49, 0x49, 0x3b, 0x4c, 0x61, 0x73, 0x3b, 0x53, 0x61,
+0x2bb, 0x61, 0x3b, 0x4c, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x76, 0x3b, 0x53,
+0x16b, 0x2d, 0x6b, 0x3b, 0x53, 0x16b, 0x2d, 0x68, 0x4d, 0x75, 0x68, 0x61,
+0x72, 0x72, 0x65, 0x6d, 0x3b, 0x53, 0x61, 0x66, 0x65, 0x72, 0x3b, 0x52,
+0x65, 0x62, 0x69, 0xfc, 0x6c, 0x65, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x52,
+0x65, 0x62, 0x69, 0xfc, 0x6c, 0x61, 0x68, 0x69, 0x72, 0x3b, 0x43, 0x65,
+0x6d, 0x61, 0x7a, 0x69, 0x79, 0x65, 0x6c, 0x65, 0x76, 0x76, 0x65, 0x6c,
+0x3b, 0x43, 0x65, 0x6d, 0x61, 0x7a, 0x69, 0x79, 0x65, 0x6c, 0x61, 0x68,
+0x69, 0x72, 0x3b, 0x52, 0x65, 0x63, 0x65, 0x70, 0x3b, 0x15e, 0x61, 0x62,
+0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a, 0x61, 0x6e, 0x3b, 0x15e,
+0x65, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x6c, 0x6b, 0x61, 0x64,
+0x65, 0x3b, 0x5a, 0x69, 0x6c, 0x68, 0x69, 0x63, 0x63, 0x65, 0x4d, 0x75,
+0x68, 0x61, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x66, 0x65, 0x72, 0x3b, 0x52,
+0x2e, 0x65, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x52, 0x2e, 0x61, 0x68, 0x69,
+0x72, 0x3b, 0x43, 0x2e, 0x65, 0x76, 0x76, 0x65, 0x6c, 0x3b, 0x43, 0x2e,
+0x61, 0x68, 0x69, 0x72, 0x3b, 0x52, 0x65, 0x63, 0x65, 0x70, 0x3b, 0x15e,
+0x61, 0x62, 0x61, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x15e, 0x65,
+0x76, 0x76, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x6c, 0x6b, 0x61, 0x64, 0x65,
+0x3b, 0x5a, 0x69, 0x6c, 0x68, 0x69, 0x63, 0x63, 0x65, 0x41, 0x15f, 0x79,
+0x72, 0x3b, 0x53, 0x61, 0x70, 0x61, 0x72, 0x3b, 0x44, 0xf6, 0x72, 0x74,
+0x20, 0x74, 0x69, 0x72, 0x6b, 0x65, 0x15f, 0x69, 0x6b, 0x20, 0x31, 0x3b,
+0x44, 0xf6, 0x72, 0x74, 0x20, 0x74, 0x69, 0x72, 0x6b, 0x65, 0x15f, 0x69,
+0x6b, 0x20, 0x32, 0x3b, 0x44, 0xf6, 0x72, 0x74, 0x20, 0x74, 0x69, 0x72,
+0x6b, 0x65, 0x15f, 0x69, 0x6b, 0x20, 0x33, 0x3b, 0x44, 0xf6, 0x72, 0x74,
+0x20, 0x74, 0x69, 0x72, 0x6b, 0x65, 0x15f, 0x69, 0x6b, 0x20, 0x34, 0x3b,
+0x52, 0x65, 0x6a, 0x65, 0x70, 0x3b, 0x4d, 0x65, 0x72, 0x65, 0x74, 0x3b,
+0x4f, 0x72, 0x61, 0x7a, 0x61, 0x3b, 0x42, 0x61, 0xfd, 0x72, 0x61, 0x6d,
+0x3b, 0x42, 0x6f, 0x15f, 0x20, 0x61, 0xfd, 0x3b, 0x47, 0x75, 0x72, 0x62,
+0x61, 0x6e, 0x41, 0x15f, 0x79, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x54, 0x69,
+0x72, 0x20, 0x49, 0x3b, 0x54, 0x69, 0x72, 0x20, 0x49, 0x49, 0x3b, 0x54,
+0x69, 0x72, 0x20, 0x49, 0x49, 0x49, 0x3b, 0x54, 0x69, 0x72, 0x20, 0x49,
+0x56, 0x3b, 0x52, 0x65, 0x6a, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x4f, 0x72,
+0x61, 0x3b, 0x42, 0x61, 0xfd, 0x3b, 0x42, 0x6f, 0x15f, 0x3b, 0x47, 0x75,
+0x72, 0x43c, 0x443, 0x445, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x441, 0x430,
+0x444, 0x430, 0x440, 0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x3b, 0x440,
+0x430, 0x431, 0x456, 0x20, 0x49, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430,
+0x434, 0x430, 0x20, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x430, 0x434, 0x430,
+0x20, 0x49, 0x49, 0x3b, 0x440, 0x430, 0x434, 0x436, 0x430, 0x431, 0x3b, 0x448,
+0x430, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x440, 0x430, 0x43c, 0x430, 0x434, 0x430,
+0x43d, 0x3b, 0x434, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x437, 0x443, 0x2d,
+0x43b, 0x44c, 0x2d, 0x43a, 0x430, 0x430, 0x434, 0x430, 0x3b, 0x437, 0x443, 0x2d,
+0x43b, 0x44c, 0x2d, 0x445, 0x456, 0x434, 0x436, 0x430, 0x43c, 0x443, 0x445, 0x3b,
+0x441, 0x430, 0x444, 0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x3b, 0x440,
+0x430, 0x431, 0x456, 0x20, 0x49, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x20,
+0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x20, 0x49, 0x49, 0x3b, 0x440, 0x430,
+0x434, 0x436, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x3b, 0x440, 0x430, 0x43c, 0x3b,
+0x434, 0x430, 0x432, 0x3b, 0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x43a, 0x3b,
+0x437, 0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x445, 0x43c, 0x443, 0x445, 0x2e, 0x3b,
+0x441, 0x430, 0x444, 0x2e, 0x3b, 0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x3b,
+0x440, 0x430, 0x431, 0x456, 0x20, 0x49, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c,
+0x2e, 0x20, 0x49, 0x3b, 0x434, 0x436, 0x443, 0x43c, 0x2e, 0x20, 0x49, 0x49,
+0x3b, 0x440, 0x430, 0x434, 0x436, 0x2e, 0x3b, 0x448, 0x430, 0x430, 0x431, 0x2e,
+0x3b, 0x440, 0x430, 0x43c, 0x2e, 0x3b, 0x434, 0x430, 0x432, 0x2e, 0x3b, 0x437,
+0x443, 0x2d, 0x43b, 0x44c, 0x2d, 0x43a, 0x2e, 0x3b, 0x437, 0x443, 0x2d, 0x43b,
+0x44c, 0x2d, 0x445, 0x2e, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631,
+0x3b, 0x631, 0x20, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x627, 0x648, 0x644,
+0x3b, 0x631, 0x20, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646,
+0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x627, 0x648,
+0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x62b, 0x627,
+0x646, 0x6cc, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628, 0x627, 0x646,
+0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627, 0x644, 0x3b,
+0x630, 0x648, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x6c3, 0x3b, 0x630, 0x648, 0x627,
+0x644, 0x62d, 0x62c, 0x6c3, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635, 0x641, 0x631,
+0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x627, 0x648, 0x651, 0x644,
+0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x62b, 0x651, 0x627, 0x646,
+0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x627, 0x648,
+0x651, 0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x62b,
+0x651, 0x627, 0x646, 0x6cc, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628,
+0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627,
+0x644, 0x3b, 0x630, 0x648, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x6c3, 0x3b, 0x630,
+0x648, 0x627, 0x644, 0x62d, 0x62c, 0x6c3, 0x645, 0x62d, 0x631, 0x645, 0x3b, 0x635,
+0x641, 0x631, 0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x627, 0x648,
+0x651, 0x644, 0x3b, 0x631, 0x628, 0x6cc, 0x639, 0x20, 0x627, 0x644, 0x62b, 0x627,
+0x646, 0x6cc, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644, 0x627,
+0x648, 0x651, 0x644, 0x3b, 0x62c, 0x645, 0x627, 0x62f, 0x6cc, 0x20, 0x627, 0x644,
+0x62b, 0x627, 0x646, 0x6cc, 0x3b, 0x631, 0x62c, 0x628, 0x3b, 0x634, 0x639, 0x628,
+0x627, 0x646, 0x3b, 0x631, 0x645, 0x636, 0x627, 0x646, 0x3b, 0x634, 0x648, 0x627,
+0x644, 0x3b, 0x630, 0x648, 0x627, 0x644, 0x642, 0x639, 0x62f, 0x6c3, 0x3b, 0x630,
+0x648, 0x627, 0x644, 0x62d, 0x62c, 0x6c3, 0x645, 0x6c7, 0x6be, 0x6d5, 0x631, 0x631,
+0x6d5, 0x645, 0x3b, 0x633, 0x6d5, 0x67e, 0x6d5, 0x631, 0x3b, 0x631, 0x6d5, 0x628,
+0x649, 0x626, 0x6c7, 0x644, 0x626, 0x6d5, 0x6cb, 0x6cb, 0x6d5, 0x644, 0x3b, 0x631,
+0x6d5, 0x628, 0x649, 0x626, 0x6c7, 0x644, 0x626, 0x627, 0x62e, 0x649, 0x631, 0x3b,
+0x62c, 0x6d5, 0x645, 0x627, 0x62f, 0x649, 0x64a, 0x6d5, 0x644, 0x626, 0x6d5, 0x6cb,
+0x6cb, 0x6d5, 0x644, 0x3b, 0x62c, 0x6d5, 0x645, 0x627, 0x62f, 0x649, 0x64a, 0x6d5,
+0x644, 0x626, 0x627, 0x62e, 0x649, 0x631, 0x3b, 0x631, 0x6d5, 0x62c, 0x6d5, 0x628,
+0x3b, 0x634, 0x6d5, 0x626, 0x628, 0x627, 0x646, 0x3b, 0x631, 0x627, 0x645, 0x649,
+0x632, 0x627, 0x646, 0x3b, 0x634, 0x6d5, 0x6cb, 0x6cb, 0x627, 0x644, 0x3b, 0x632,
+0x6c7, 0x644, 0x642, 0x6d5, 0x626, 0x62f, 0x6d5, 0x3b, 0x632, 0x6c7, 0x644, 0x6be,
+0x6d5, 0x62c, 0x62c, 0x6d5, 0x4d, 0x75, 0x68, 0x61, 0x72, 0x72, 0x61, 0x6d,
+0x3b, 0x53, 0x61, 0x66, 0x61, 0x72, 0x3b, 0x52, 0x6f, 0x62, 0x69, 0x2019,
+0x20, 0x75, 0x6c, 0x2d, 0x61, 0x76, 0x76, 0x61, 0x6c, 0x3b, 0x52, 0x6f,
+0x62, 0x69, 0x2019, 0x20, 0x75, 0x6c, 0x2d, 0x6f, 0x78, 0x69, 0x72, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x64, 0x20, 0x75, 0x6c, 0x2d, 0x61, 0x76, 0x76,
+0x61, 0x6c, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x64, 0x20, 0x75, 0x6c, 0x2d,
+0x6f, 0x78, 0x69, 0x72, 0x3b, 0x52, 0x61, 0x6a, 0x61, 0x62, 0x3b, 0x53,
+0x68, 0x61, 0x2019, 0x62, 0x6f, 0x6e, 0x3b, 0x52, 0x61, 0x6d, 0x61, 0x7a,
+0x6f, 0x6e, 0x3b, 0x53, 0x68, 0x61, 0x76, 0x76, 0x6f, 0x6c, 0x3b, 0x5a,
+0x75, 0x6c, 0x2d, 0x71, 0x61, 0x2019, 0x64, 0x61, 0x3b, 0x5a, 0x75, 0x6c,
+0x2d, 0x68, 0x69, 0x6a, 0x6a, 0x61, 0x4d, 0x75, 0x68, 0x2e, 0x3b, 0x53,
+0x61, 0x66, 0x2e, 0x3b, 0x52, 0x6f, 0x62, 0x2e, 0x20, 0x61, 0x76, 0x76,
+0x2e, 0x3b, 0x52, 0x6f, 0x62, 0x2e, 0x20, 0x6f, 0x78, 0x2e, 0x3b, 0x4a,
+0x75, 0x6d, 0x2e, 0x20, 0x61, 0x76, 0x76, 0x2e, 0x3b, 0x4a, 0x75, 0x6d,
+0x2e, 0x20, 0x6f, 0x78, 0x2e, 0x3b, 0x52, 0x61, 0x6a, 0x2e, 0x3b, 0x53,
+0x68, 0x61, 0x2e, 0x3b, 0x52, 0x61, 0x6d, 0x2e, 0x3b, 0x53, 0x68, 0x61,
+0x76, 0x2e, 0x3b, 0x5a, 0x75, 0x6c, 0x2d, 0x71, 0x2e, 0x3b, 0x5a, 0x75,
+0x6c, 0x2d, 0x68, 0x2e, 0x41c, 0x443, 0x4b3, 0x430, 0x440, 0x440, 0x430, 0x43c,
+0x3b, 0x421, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x443,
+0x43b, 0x2d, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x420, 0x430, 0x431, 0x438,
+0x443, 0x43b, 0x2d, 0x43e, 0x445, 0x438, 0x440, 0x3b, 0x416, 0x443, 0x43c, 0x43e,
+0x434, 0x438, 0x443, 0x43b, 0x2d, 0x443, 0x43b, 0x43e, 0x3b, 0x416, 0x443, 0x43c,
+0x43e, 0x434, 0x438, 0x443, 0x43b, 0x2d, 0x443, 0x445, 0x440, 0x43e, 0x3b, 0x420,
+0x430, 0x436, 0x430, 0x431, 0x3b, 0x428, 0x430, 0x44a, 0x431, 0x43e, 0x43d, 0x3b,
+0x420, 0x430, 0x43c, 0x430, 0x437, 0x43e, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x432,
+0x43e, 0x43b, 0x3b, 0x417, 0x438, 0x43b, 0x2d, 0x49b, 0x430, 0x44a, 0x434, 0x430,
+0x3b, 0x417, 0x438, 0x43b, 0x2d, 0x4b3, 0x438, 0x436, 0x436, 0x430
};
// GENERATED PART ENDS HERE
+} // namespace QtPrivate::Hijri
+
QT_END_NAMESPACE
#endif // QHIJRI_CALENDAR_DATA_P_H
diff --git a/src/corelib/time/qhijricalendar_p.h b/src/corelib/time/qhijricalendar_p.h
index abe2ade3e8..6c54b93fac 100644
--- a/src/corelib/time/qhijricalendar_p.h
+++ b/src/corelib/time/qhijricalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QHIJRI_CALENDAR_P_H
#define QHIJRI_CALENDAR_P_H
@@ -73,9 +37,6 @@ public:
protected:
const QCalendarLocale *localeMonthIndexData() const override;
const char16_t *localeMonthData() const override;
- // (The INTEGRITY compiler got upset at: using QCalendarBackend:QCalendarBackend;)
- QHijriCalendar(const QString &name, QCalendar::System id = QCalendar::System::User)
- : QCalendarBackend(name, id) {}
};
QT_END_NAMESPACE
diff --git a/src/corelib/time/qislamiccivilcalendar.cpp b/src/corelib/time/qislamiccivilcalendar.cpp
index a6a2afd207..ac1f97cb6c 100644
--- a/src/corelib/time/qislamiccivilcalendar.cpp
+++ b/src/corelib/time/qislamiccivilcalendar.cpp
@@ -1,46 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qislamiccivilcalendar_p.h"
#include "qcalendarmath_p.h"
-#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE
@@ -72,23 +35,20 @@ using namespace QRoundingDown;
\sa QHijriCalendar, QCalendar
*/
-QIslamicCivilCalendar::QIslamicCivilCalendar()
- : QHijriCalendar(QStringLiteral("Islamic Civil"), QCalendar::System::IslamicCivil)
-{
- registerAlias(QStringLiteral("islamic-civil")); // CLDR name
- registerAlias(QStringLiteral("islamicc")); // old CLDR name, still (2018) used by Mozilla
- // Until we have a oncrete implementation that knows all the needed ephemerides:
- registerAlias(QStringLiteral("Islamic"));
-}
-
QString QIslamicCivilCalendar::name() const
{
return QStringLiteral("Islamic Civil");
}
-QCalendar::System QIslamicCivilCalendar::calendarSystem() const
+QStringList QIslamicCivilCalendar::nameList()
{
- return QCalendar::System::IslamicCivil;
+ return {
+ QStringLiteral("Islamic Civil"),
+ QStringLiteral("islamic-civil"), // CLDR name
+ QStringLiteral("islamicc"), // old CLDR name, still (2018) used by Mozilla
+ // Until we have a concrete implementation that knows all the needed ephemerides:
+ QStringLiteral("Islamic"),
+ };
}
bool QIslamicCivilCalendar::isLeapYear(int year) const
@@ -97,30 +57,37 @@ bool QIslamicCivilCalendar::isLeapYear(int year) const
return false;
if (year < 0)
++year;
- return qMod(year * 11 + 14, 30) < 11;
+ return qMod<30>(year * 11 + 14) < 11;
}
+// First day of first year (Gregorian 622 CE July 19th) is the base date here:
+constexpr qint64 EpochJd = 1948440;
+// Each 30 years has 11 leap years of 355 days and 19 ordinary years of 354:
+constexpr unsigned ThirtyYears = 11 * 355 + 19 * 354;
+// The first eleven months of the year alternate 30, 29, ..., 29, 30 days in length.
+constexpr unsigned ElevenMonths = 6 * 30 + 5 * 29;
+
bool QIslamicCivilCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const
{
Q_ASSERT(jd);
if (!isDateValid(year, month, day))
return false;
- if (year <= 0)
- ++year;
- *jd = qDiv(10631 * year - 10617, 30)
- + qDiv(325 * month - 320, 11)
- + day + 1948439;
+
+ *jd = qDiv<30>(qint64(ThirtyYears) * (year > 0 ? year - 1 : year) + 14)
+ + qDiv<11>(ElevenMonths * (month - 1) + 5)
+ + day + EpochJd - 1;
return true;
}
QCalendar::YearMonthDay QIslamicCivilCalendar::julianDayToDate(qint64 jd) const
{
- const qint64 epoch = 1948440;
- const int32_t k2 = 30 * (jd - epoch) + 15;
- const int32_t k1 = 11 * qDiv(qMod(k2, 10631), 30) + 5;
- int y = qDiv(k2, 10631) + 1;
- const int month = qDiv(k1, 325) + 1;
- const int day = qDiv(qMod(k1, 325), 11) + 1;
+ const auto year30Day = qDivMod<ThirtyYears>(30 * (jd - EpochJd) + 15);
+ // Its remainder changes by 30 per day, except roughly yearly.
+ const auto month11Day = qDivMod<ElevenMonths>(11 * qDiv<30>(year30Day.remainder) + 5);
+ // Its remainder changes by 11 per day except roughly monthly.
+ const int month = month11Day.quotient + 1;
+ const int day = qDiv<11>(month11Day.remainder) + 1;
+ const int y = year30Day.quotient + 1;
return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);
}
diff --git a/src/corelib/time/qislamiccivilcalendar_p.h b/src/corelib/time/qislamiccivilcalendar_p.h
index 01d0525f62..4a4bbcc7ed 100644
--- a/src/corelib/time/qislamiccivilcalendar_p.h
+++ b/src/corelib/time/qislamiccivilcalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QISLAMIC_CIVIL_CALENDAR_P_H
#define QISLAMIC_CIVIL_CALENDAR_P_H
@@ -60,10 +24,9 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QIslamicCivilCalendar : public QHijriCalendar
{
public:
- QIslamicCivilCalendar();
// Calendar properties:
QString name() const override;
- QCalendar::System calendarSystem() const override;
+ static QStringList nameList();
// Date queries:
bool isLeapYear(int year) const override;
// Julian Day conversions:
diff --git a/src/corelib/time/qjalalicalendar.cpp b/src/corelib/time/qjalalicalendar.cpp
index 17588aff6c..fcbdf14395 100644
--- a/src/corelib/time/qjalalicalendar.cpp
+++ b/src/corelib/time/qjalalicalendar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qjalalicalendar_p.h"
@@ -49,16 +13,17 @@ using namespace QRoundingDown;
// Constants
-static const qint64 cycleDays = 1029983;
-static const int cycleYears = 2820;
-static const double yearLength = 365.24219858156028368; // 365 + leapRatio;
-static const qint64 jalaliEpoch = 2121446; // 475/01/01 AP, start of 2820 cycle
+constexpr qint64 cycleDays = 1029983;
+constexpr int cycleYears = 2820;
+constexpr double yearLength = 365.24219858156028368; // 365 + 683 / 2820.
+constexpr qint64 jalaliEpoch = 2121446; // 475/01/01 AP, start of 2820 cycle
+// This appears to be based on Ahmad Birashk's algorithm.
// Calendar implementation
static inline int cycle(qint64 jdn)
{
- return qDiv(jdn - jalaliEpoch, cycleDays);
+ return qDiv<cycleDays>(jdn - jalaliEpoch);
}
qint64 cycleStart(int cycleNo)
@@ -111,22 +76,19 @@ qint64 firstDayOfYear(int year, int cycleNo)
Source: \l {https://en.wikipedia.org/wiki/Solar_Hijri_calendar}{Wikipedia
page on Solar Hijri Calendar}
- */
-
-QJalaliCalendar::QJalaliCalendar()
- : QCalendarBackend(QStringLiteral("Jalali"), QCalendar::System::Jalali)
-{
- registerAlias(QStringLiteral("Persian"));
-}
+*/
QString QJalaliCalendar::name() const
{
return QStringLiteral("Jalali");
}
-QCalendar::System QJalaliCalendar::calendarSystem() const
+QStringList QJalaliCalendar::nameList()
{
- return QCalendar::System::Jalali;
+ return {
+ QStringLiteral("Jalali"),
+ QStringLiteral("Persian"),
+ };
}
bool QJalaliCalendar::isLeapYear(int year) const
@@ -135,7 +97,7 @@ bool QJalaliCalendar::isLeapYear(int year) const
return false;
if (year < 0)
year++;
- return qMod((year + 2346) * 683, 2820) < 683;
+ return qMod<2820>((year + 2346) * 683) < 683;
}
bool QJalaliCalendar::isLunar() const
@@ -160,7 +122,7 @@ bool QJalaliCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd)
return false;
const int y = year - (year < 0 ? 474 : 475);
- const int c = qDiv(y, cycleYears);
+ const int c = qDiv<cycleYears>(y);
const int yearInCycle = y - c * cycleYears;
int dayInYear = day;
for (int i = 1; i < month; ++i)
@@ -201,12 +163,12 @@ int QJalaliCalendar::daysInMonth(int month, int year) const
const QCalendarLocale *QJalaliCalendar::localeMonthIndexData() const
{
- return locale_data;
+ return QtPrivate::Jalali::locale_data;
}
const char16_t *QJalaliCalendar::localeMonthData() const
{
- return months_data;
+ return QtPrivate::Jalali::months_data;
}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qjalalicalendar_data_p.h b/src/corelib/time/qjalalicalendar_data_p.h
index c21c106e60..0e3c3cedb9 100644
--- a/src/corelib/time/qjalalicalendar_data_p.h
+++ b/src/corelib/time/qjalalicalendar_data_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-3.0
#ifndef QPERSIANCALENDAR_DATA_P_H
#define QPERSIANCALENDAR_DATA_P_H
@@ -56,11 +20,13 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate::Jalali {
+
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-04-07 from the
- Common Locale Data Repository v36
+ This part of the file was generated on 2024-01-09 from the
+ Common Locale Data Repository v44.1
http://www.unicode.org/cldr/
@@ -69,835 +35,1134 @@ QT_BEGIN_NAMESPACE
edited) CLDR data; see qtbase/util/locale_database/.
*/
-static const QCalendarLocale locale_data[] = {
+static constexpr QCalendarLocale locale_data[] = {
// lang script terr sLong long sShrt short sNarw narow Sizes...
- { 1, 0, 0, 0, 0, 83, 83, 130, 153, 83, 83, 47, 47, 23, 26 },// C/AnyScript/AnyCountry
- { 3, 7, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Ethiopia
- { 3, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Kenya
- { 4, 7, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afar/Latin/Ethiopia
- { 5, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afrikaans/Latin/South Africa
- { 5, 7, 148, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afrikaans/Latin/Namibia
- { 6, 7, 2, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Albanian/Latin/Albania
- { 6, 7, 127, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Albanian/Latin/Macedonia
- { 6, 7, 257, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Albanian/Latin/Kosovo
- { 7, 14, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Amharic/Ethiopic/Ethiopia
- { 8, 1, 64, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Egypt
- { 8, 1, 3, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Algeria
- { 8, 1, 17, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Bahrain
- { 8, 1, 42, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Chad
- { 8, 1, 48, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Comoros
- { 8, 1, 59, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Djibouti
- { 8, 1, 67, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Eritrea
- { 8, 1, 103, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Iraq
- { 8, 1, 105, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Israel
- { 8, 1, 109, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Jordan
- { 8, 1, 115, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Kuwait
- { 8, 1, 119, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Lebanon
- { 8, 1, 122, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Libya
- { 8, 1, 136, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Mauritania
- { 8, 1, 145, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Morocco
- { 8, 1, 162, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Oman
- { 8, 1, 165, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Palestinian Territories
- { 8, 1, 175, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Qatar
- { 8, 1, 186, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Saudi Arabia
- { 8, 1, 194, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Somalia
- { 8, 1, 201, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Sudan
- { 8, 1, 207, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Syria
- { 8, 1, 216, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Tunisia
- { 8, 1, 223, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/United Arab Emirates
- { 8, 1, 236, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Western Sahara
- { 8, 1, 237, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Yemen
- { 8, 1, 254, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/South Sudan
- { 8, 1, 260, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/World
- { 9, 10, 11, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Armenian/Armenian/Armenia
- { 10, 11, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Assamese/Bengali/India
- { 12, 7, 15, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Latin/Azerbaijan
- { 12, 1, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Arabic/Iran
- { 12, 2, 15, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Cyrillic/Azerbaijan
- { 13, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bashkir/Cyrillic/Russia
- { 14, 7, 197, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Basque/Latin/Spain
- { 15, 11, 18, 246, 246, 334, 334, 421, 421, 88, 88, 87, 87, 26, 26 },// Bengali/Bengali/Bangladesh
- { 15, 11, 100, 246, 246, 334, 334, 421, 421, 88, 88, 87, 87, 26, 26 },// Bengali/Bengali/India
- { 16, 31, 25, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dzongkha/Tibetan/Bhutan
- { 19, 7, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Breton/Latin/France
- { 20, 2, 33, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bulgarian/Cyrillic/Bulgaria
- { 21, 25, 147, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Burmese/Myanmar/Myanmar
- { 22, 2, 20, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Belarusian/Cyrillic/Belarus
- { 23, 20, 36, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Khmer/Khmer/Cambodia
- { 24, 7, 197, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/Spain
- { 24, 7, 5, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/Andorra
- { 24, 7, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/France
- { 24, 7, 106, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/Italy
- { 25, 5, 44, 447, 447, 484, 484, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/China
- { 25, 5, 97, 447, 447, 484, 484, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Hong Kong
- { 25, 5, 126, 447, 447, 484, 484, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Macau
- { 25, 5, 190, 447, 447, 484, 484, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Singapore
- { 25, 6, 97, 484, 484, 484, 484, 153, 153, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Hong Kong
- { 25, 6, 126, 484, 484, 484, 484, 153, 153, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Macau
- { 25, 6, 208, 484, 484, 484, 484, 153, 153, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Taiwan
- { 26, 7, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Corsican/Latin/France
- { 27, 7, 54, 0, 0, 0, 0, 522, 522, 83, 83, 83, 83, 38, 38 },// Croatian/Latin/Croatia
- { 27, 7, 27, 0, 0, 0, 0, 522, 522, 83, 83, 83, 83, 38, 38 },// Croatian/Latin/Bosnia And Herzegowina
- { 28, 7, 57, 560, 560, 560, 560, 153, 153, 81, 81, 81, 81, 26, 26 },// Czech/Latin/Czech Republic
- { 29, 7, 58, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Danish/Latin/Denmark
- { 29, 7, 86, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Danish/Latin/Greenland
- { 30, 7, 151, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Netherlands
- { 30, 7, 12, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Aruba
- { 30, 7, 21, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Belgium
- { 30, 7, 152, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Cura Sao
- { 30, 7, 202, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Suriname
- { 30, 7, 255, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Bonaire
- { 30, 7, 256, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Sint Maarten
- { 31, 7, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United States
- { 31, 3, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Deseret/United States
- { 31, 7, 4, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/American Samoa
- { 31, 7, 7, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Anguilla
- { 31, 7, 9, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Antigua And Barbuda
- { 31, 7, 13, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Australia
- { 31, 7, 14, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Austria
- { 31, 7, 16, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Bahamas
- { 31, 7, 19, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Barbados
- { 31, 7, 21, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Belgium
- { 31, 7, 22, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Belize
- { 31, 7, 24, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Bermuda
- { 31, 7, 28, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Botswana
- { 31, 7, 31, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/British Indian Ocean Territory
- { 31, 7, 35, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Burundi
- { 31, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cameroon
- { 31, 7, 38, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Canada
- { 31, 7, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cayman Islands
- { 31, 7, 45, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Christmas Island
- { 31, 7, 46, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cocos Islands
- { 31, 7, 51, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cook Islands
- { 31, 7, 56, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cyprus
- { 31, 7, 58, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Denmark
- { 31, 7, 60, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Dominica
- { 31, 7, 67, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Eritrea
- { 31, 7, 70, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Falkland Islands
- { 31, 7, 72, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Fiji
- { 31, 7, 73, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Finland
- { 31, 7, 75, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Guernsey
- { 31, 7, 80, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Gambia
- { 31, 7, 82, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Germany
- { 31, 7, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Ghana
- { 31, 7, 84, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Gibraltar
- { 31, 7, 87, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Grenada
- { 31, 7, 89, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Guam
- { 31, 7, 93, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Guyana
- { 31, 7, 97, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Hong Kong
- { 31, 7, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/India
- { 31, 7, 104, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Ireland
- { 31, 7, 105, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Israel
- { 31, 7, 107, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Jamaica
- { 31, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Kenya
- { 31, 7, 112, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Kiribati
- { 31, 7, 120, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Lesotho
- { 31, 7, 121, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Liberia
- { 31, 7, 126, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Macau
- { 31, 7, 128, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Madagascar
- { 31, 7, 129, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Malawi
- { 31, 7, 130, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Malaysia
- { 31, 7, 133, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Malta
- { 31, 7, 134, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Marshall Islands
- { 31, 7, 137, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Mauritius
- { 31, 7, 140, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Micronesia
- { 31, 7, 144, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Montserrat
- { 31, 7, 148, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Namibia
- { 31, 7, 149, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Nauru
- { 31, 7, 151, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Netherlands
- { 31, 7, 154, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/New Zealand
- { 31, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Nigeria
- { 31, 7, 158, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Niue
- { 31, 7, 159, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Norfolk Island
- { 31, 7, 160, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Northern Mariana Islands
- { 31, 7, 163, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Pakistan
- { 31, 7, 164, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Palau
- { 31, 7, 167, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Papua New Guinea
- { 31, 7, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Philippines
- { 31, 7, 171, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Pitcairn
- { 31, 7, 174, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Puerto Rico
- { 31, 7, 179, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Rwanda
- { 31, 7, 180, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Kitts And Nevis
- { 31, 7, 181, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Lucia
- { 31, 7, 182, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Vincent And The Grenadines
- { 31, 7, 183, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Samoa
- { 31, 7, 188, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Seychelles
- { 31, 7, 189, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sierra Leone
- { 31, 7, 190, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Singapore
- { 31, 7, 192, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Slovenia
- { 31, 7, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Solomon Islands
- { 31, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/South Africa
- { 31, 7, 199, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Helena
- { 31, 7, 201, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sudan
- { 31, 7, 204, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Swaziland
- { 31, 7, 205, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sweden
- { 31, 7, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Switzerland
- { 31, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tanzania
- { 31, 7, 213, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tokelau
- { 31, 7, 214, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tonga
- { 31, 7, 215, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Trinidad And Tobago
- { 31, 7, 219, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Turks And Caicos Islands
- { 31, 7, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tuvalu
- { 31, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Uganda
- { 31, 7, 223, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United Arab Emirates
- { 31, 7, 224, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United Kingdom
- { 31, 7, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United States Minor Outlying Islands
- { 31, 7, 229, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Vanuatu
- { 31, 7, 233, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/British Virgin Islands
- { 31, 7, 234, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United States Virgin Islands
- { 31, 7, 239, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Zambia
- { 31, 7, 240, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Zimbabwe
- { 31, 7, 249, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Diego Garcia
- { 31, 7, 251, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Isle Of Man
- { 31, 7, 252, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Jersey
- { 31, 7, 254, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/South Sudan
- { 31, 7, 256, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sint Maarten
- { 31, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/World
- { 31, 7, 261, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Europe
- { 32, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Esperanto/Latin/World
- { 33, 7, 68, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Estonian/Latin/Estonia
- { 34, 7, 71, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Faroese/Latin/Faroe Islands
- { 34, 7, 58, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Faroese/Latin/Denmark
- { 36, 7, 73, 724, 841, 982, 841, 153, 153,117,141, 81,141, 26, 26 },// Finnish/Latin/Finland
- { 37, 7, 74, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/France
- { 37, 7, 3, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Algeria
- { 37, 7, 21, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Belgium
- { 37, 7, 23, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Benin
- { 37, 7, 34, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Burkina Faso
- { 37, 7, 35, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Burundi
- { 37, 7, 37, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Cameroon
- { 37, 7, 38, 1201, 1201, 1282, 1282, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Canada
- { 37, 7, 41, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Central African Republic
- { 37, 7, 42, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Chad
- { 37, 7, 48, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Comoros
- { 37, 7, 49, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Congo Kinshasa
- { 37, 7, 50, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Congo Brazzaville
- { 37, 7, 53, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Ivory Coast
- { 37, 7, 59, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Djibouti
- { 37, 7, 66, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Equatorial Guinea
- { 37, 7, 76, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/French Guiana
- { 37, 7, 77, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/French Polynesia
- { 37, 7, 79, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Gabon
- { 37, 7, 88, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Guadeloupe
- { 37, 7, 91, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Guinea
- { 37, 7, 94, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Haiti
- { 37, 7, 125, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Luxembourg
- { 37, 7, 128, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Madagascar
- { 37, 7, 132, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mali
- { 37, 7, 135, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Martinique
- { 37, 7, 136, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mauritania
- { 37, 7, 137, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mauritius
- { 37, 7, 138, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mayotte
- { 37, 7, 142, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Monaco
- { 37, 7, 145, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Morocco
- { 37, 7, 153, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/New Caledonia
- { 37, 7, 156, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Niger
- { 37, 7, 176, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Reunion
- { 37, 7, 179, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Rwanda
- { 37, 7, 187, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Senegal
- { 37, 7, 188, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Seychelles
- { 37, 7, 200, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Saint Pierre And Miquelon
- { 37, 7, 206, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Switzerland
- { 37, 7, 207, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Syria
- { 37, 7, 212, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Togo
- { 37, 7, 216, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Tunisia
- { 37, 7, 229, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Vanuatu
- { 37, 7, 235, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Wallis And Futuna Islands
- { 37, 7, 244, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Saint Barthelemy
- { 37, 7, 245, 1063, 1063, 1144, 1144, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Saint Martin
- { 38, 7, 151, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Frisian/Latin/Netherlands
- { 39, 7, 224, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Gaelic/Latin/United Kingdom
- { 40, 7, 197, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Galician/Latin/Spain
- { 41, 15, 81, 1339, 1339, 1339, 1339, 153, 153, 91, 91, 91, 91, 26, 26 },// Georgian/Georgian/Georgia
- { 42, 7, 82, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Germany
- { 42, 7, 14, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Austria
- { 42, 7, 21, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Belgium
- { 42, 7, 106, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Italy
- { 42, 7, 123, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Liechtenstein
- { 42, 7, 125, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Luxembourg
- { 42, 7, 206, 1430, 1430, 1430, 1430, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Switzerland
- { 43, 16, 85, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Greek/Greek/Greece
- { 43, 16, 56, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Greek/Greek/Cyprus
- { 44, 7, 86, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Greenlandic/Latin/Greenland
- { 45, 7, 168, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Guarani/Latin/Paraguay
- { 46, 17, 100, 1516, 1516, 1516, 1516, 153, 153, 85, 85, 85, 85, 26, 26 },// Gujarati/Gujarati/India
- { 47, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Latin/Nigeria
- { 47, 1, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Arabic/Nigeria
- { 47, 7, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Latin/Ghana
- { 47, 7, 156, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Latin/Niger
- { 48, 18, 105, 1601, 1601, 1601, 1601, 153, 153, 68, 68, 68, 68, 26, 26 },// Hebrew/Hebrew/Israel
- { 49, 13, 100, 1669, 1669, 1669, 1669, 153, 153, 81, 81, 81, 81, 26, 26 },// Hindi/Devanagari/India
- { 50, 7, 98, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Hungarian/Latin/Hungary
- { 51, 7, 99, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Icelandic/Latin/Iceland
- { 52, 7, 101, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Indonesian/Latin/Indonesia
- { 53, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Interlingua/Latin/World
- { 55, 44, 38, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Inuktitut/Canadian Aboriginal/Canada
- { 55, 7, 38, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Inuktitut/Latin/Canada
- { 57, 7, 104, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Irish/Latin/Ireland
- { 57, 7, 224, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Irish/Latin/United Kingdom
- { 58, 7, 106, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/Italy
- { 58, 7, 184, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/San Marino
- { 58, 7, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/Switzerland
- { 58, 7, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/Vatican City State
- { 59, 19, 108, 1750, 1750, 1750, 1750, 153, 153, 77, 77, 77, 77, 26, 26 },// Japanese/Japanese/Japan
- { 60, 7, 101, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Javanese/Latin/Indonesia
- { 61, 21, 100, 1827, 1827, 1827, 1827, 153, 153, 92, 92, 92, 92, 26, 26 },// Kannada/Kannada/India
- { 62, 1, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kashmiri/Arabic/India
- { 63, 2, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kazakh/Cyrillic/Kazakhstan
- { 64, 7, 179, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kinyarwanda/Latin/Rwanda
- { 65, 2, 116, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kirghiz/Cyrillic/Kyrgyzstan
- { 66, 22, 114, 1919, 1919, 1919, 1919, 153, 153, 54, 54, 54, 54, 26, 26 },// Korean/Korean/South Korea
- { 66, 22, 113, 1919, 1919, 1919, 1919, 153, 153, 54, 54, 54, 54, 26, 26 },// Korean/Korean/North Korea
- { 67, 7, 217, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kurdish/Latin/Turkey
- { 68, 7, 35, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rundi/Latin/Burundi
- { 69, 23, 117, 1973, 1973, 2053, 2132, 153, 153, 80, 80, 79, 79, 26, 26 },// Lao/Lao/Laos
- { 71, 7, 118, 2211, 2211, 2211, 2211, 153, 153, 92, 92, 92, 92, 26, 26 },// Latvian/Latin/Latvia
- { 72, 7, 49, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Congo Kinshasa
- { 72, 7, 6, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Angola
- { 72, 7, 41, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Central African Republic
- { 72, 7, 50, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Congo Brazzaville
- { 73, 7, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lithuanian/Latin/Lithuania
- { 74, 2, 127, 2303, 2303, 2303, 2303, 153, 153, 79, 79, 79, 79, 26, 26 },// Macedonian/Cyrillic/Macedonia
- { 75, 7, 128, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malagasy/Latin/Madagascar
- { 76, 7, 130, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Malaysia
- { 76, 1, 130, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Arabic/Malaysia
- { 76, 7, 32, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Brunei
- { 76, 7, 190, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Singapore
- { 77, 24, 100, 2382, 2382, 2382, 2382, 2473, 2473, 91, 91, 91, 91, 39, 39 },// Malayalam/Malayalam/India
- { 78, 7, 133, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Maltese/Latin/Malta
- { 79, 7, 154, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Maori/Latin/New Zealand
- { 80, 13, 100, 2512, 2512, 2512, 2512, 2592, 2592, 80, 80, 80, 80, 26, 26 },// Marathi/Devanagari/India
- { 82, 2, 143, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mongolian/Cyrillic/Mongolia
- { 82, 8, 44, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mongolian/Mongolian/China
- { 84, 13, 150, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nepali/Devanagari/Nepal
- { 84, 13, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nepali/Devanagari/India
- { 85, 7, 161, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Norwegian Bokmal/Latin/Norway
- { 85, 7, 203, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands
- { 86, 7, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Occitan/Latin/France
- { 87, 26, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oriya/Oriya/India
- { 88, 1, 1, 2618, 2618, 2618, 2618, 2680, 2680, 62, 62, 62, 62, 26, 26 },// Pashto/Arabic/Afghanistan
- { 88, 1, 163, 2618, 2618, 2618, 2618, 2680, 2680, 62, 62, 62, 62, 26, 26 },// Pashto/Arabic/Pakistan
- { 89, 1, 102, 2706, 2706, 2706, 2706, 2772, 2772, 66, 66, 66, 66, 23, 23 },// Persian/Arabic/Iran
- { 89, 1, 1, 2706, 2795, 2706, 2706, 2851, 2772, 66, 56, 66, 66, 23, 23 },// Persian/Arabic/Afghanistan
- { 90, 7, 172, 2874, 2874, 2874, 2874, 153, 153, 83, 83, 83, 83, 26, 26 },// Polish/Latin/Poland
- { 91, 7, 30, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Brazil
- { 91, 7, 6, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Angola
- { 91, 7, 39, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Cape Verde
- { 91, 7, 62, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/East Timor
- { 91, 7, 66, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Equatorial Guinea
- { 91, 7, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Guinea Bissau
- { 91, 7, 125, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Luxembourg
- { 91, 7, 126, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Macau
- { 91, 7, 146, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Mozambique
- { 91, 7, 173, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Portugal
- { 91, 7, 185, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Sao Tome And Principe
- { 91, 7, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Switzerland
- { 92, 4, 100, 2957, 2957, 2957, 2957, 153, 153, 77, 77, 77, 77, 26, 26 },// Punjabi/Gurmukhi/India
- { 92, 1, 163, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Punjabi/Arabic/Pakistan
- { 93, 7, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Quechua/Latin/Peru
- { 93, 7, 26, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Quechua/Latin/Bolivia
- { 93, 7, 63, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Quechua/Latin/Ecuador
- { 94, 7, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Romansh/Latin/Switzerland
- { 95, 7, 177, 3034, 3034, 3034, 3034, 153, 153, 85, 85, 85, 85, 26, 26 },// Romanian/Latin/Romania
- { 95, 7, 141, 3034, 3034, 3034, 3034, 153, 153, 85, 85, 85, 85, 26, 26 },// Romanian/Latin/Moldova
- { 96, 2, 178, 3119, 3119, 3119, 3119, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Russia
- { 96, 2, 20, 3119, 3119, 3119, 3119, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Belarus
- { 96, 2, 110, 3119, 3119, 3119, 3119, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Kazakhstan
- { 96, 2, 116, 3119, 3119, 3119, 3119, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Kyrgyzstan
- { 96, 2, 141, 3119, 3119, 3119, 3119, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Moldova
- { 96, 2, 222, 3119, 3119, 3119, 3119, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Ukraine
- { 98, 7, 41, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sango/Latin/Central African Republic
- { 99, 13, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sanskrit/Devanagari/India
- { 100, 2, 243, 3199, 3199, 3199, 3199, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Serbia
- { 100, 7, 27, 3279, 3279, 3279, 3279, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Bosnia And Herzegowina
- { 100, 7, 242, 3279, 3279, 3279, 3279, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Montenegro
- { 100, 7, 243, 3279, 3279, 3279, 3279, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Serbia
- { 100, 2, 27, 3199, 3199, 3199, 3199, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Bosnia And Herzegowina
- { 100, 2, 242, 3199, 3199, 3199, 3199, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Montenegro
- { 100, 2, 257, 3199, 3199, 3199, 3199, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Kosovo
- { 100, 7, 257, 3279, 3279, 3279, 3279, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Kosovo
- { 101, 2, 81, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ossetic/Cyrillic/Georgia
- { 101, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ossetic/Cyrillic/Russia
- { 102, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Sotho/Latin/South Africa
- { 103, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tswana/Latin/South Africa
- { 104, 7, 240, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Shona/Latin/Zimbabwe
- { 105, 1, 163, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sindhi/Arabic/Pakistan
- { 106, 32, 198, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sinhala/Sinhala/Sri Lanka
- { 107, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swati/Latin/South Africa
- { 108, 7, 191, 560, 560, 560, 560, 153, 153, 81, 81, 81, 81, 26, 26 },// Slovak/Latin/Slovakia
- { 109, 7, 192, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Slovenian/Latin/Slovenia
- { 110, 7, 194, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Somali/Latin/Somalia
- { 110, 7, 59, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Somali/Latin/Djibouti
- { 110, 7, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Somali/Latin/Ethiopia
- { 110, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Somali/Latin/Kenya
- { 111, 7, 197, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Spain
- { 111, 7, 10, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Argentina
- { 111, 7, 22, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Belize
- { 111, 7, 26, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Bolivia
- { 111, 7, 30, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Brazil
- { 111, 7, 43, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Chile
- { 111, 7, 47, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Colombia
- { 111, 7, 52, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Costa Rica
- { 111, 7, 55, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Cuba
- { 111, 7, 61, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Dominican Republic
- { 111, 7, 63, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Ecuador
- { 111, 7, 65, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/El Salvador
- { 111, 7, 66, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Equatorial Guinea
- { 111, 7, 90, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Guatemala
- { 111, 7, 96, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Honduras
- { 111, 7, 139, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Mexico
- { 111, 7, 155, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Nicaragua
- { 111, 7, 166, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Panama
- { 111, 7, 168, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Paraguay
- { 111, 7, 169, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Peru
- { 111, 7, 170, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Philippines
- { 111, 7, 174, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Puerto Rico
- { 111, 7, 225, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/United States
- { 111, 7, 227, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Uruguay
- { 111, 7, 231, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Venezuela
- { 111, 7, 238, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Canary Islands
- { 111, 7, 246, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Latin America
- { 111, 7, 250, 641, 641, 641, 641, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Ceuta And Melilla
- { 112, 7, 101, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sundanese/Latin/Indonesia
- { 113, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Tanzania
- { 113, 7, 49, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Congo Kinshasa
- { 113, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Kenya
- { 113, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Uganda
- { 114, 7, 205, 3359, 3442, 3359, 3442, 153, 153, 83, 83, 83, 83, 26, 26 },// Swedish/Latin/Sweden
- { 114, 7, 73, 3359, 3442, 3359, 3442, 153, 153, 83, 83, 83, 83, 26, 26 },// Swedish/Latin/Finland
- { 114, 7, 248, 3359, 3442, 3359, 3442, 153, 153, 83, 83, 83, 83, 26, 26 },// Swedish/Latin/Aland Islands
- { 115, 7, 106, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sardinian/Latin/Italy
- { 116, 2, 209, 3525, 3525, 3525, 3525, 153, 153, 80, 80, 80, 80, 26, 26 },// Tajik/Cyrillic/Tajikistan
- { 117, 27, 100, 3605, 3605, 3698, 3698, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/India
- { 117, 27, 130, 3605, 3605, 3698, 3698, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/Malaysia
- { 117, 27, 190, 3605, 3605, 3698, 3698, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/Singapore
- { 117, 27, 198, 3605, 3605, 3698, 3698, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/Sri Lanka
- { 118, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tatar/Cyrillic/Russia
- { 119, 28, 100, 3761, 3761, 3761, 3761, 153, 153, 88, 88, 88, 88, 26, 26 },// Telugu/Telugu/India
- { 120, 30, 211, 3849, 3849, 3849, 3849, 153, 153, 98, 98, 98, 98, 26, 26 },// Thai/Thai/Thailand
- { 121, 31, 44, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tibetan/Tibetan/China
- { 121, 31, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tibetan/Tibetan/India
- { 122, 14, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tigrinya/Ethiopic/Ethiopia
- { 122, 14, 67, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tigrinya/Ethiopic/Eritrea
- { 123, 7, 214, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tongan/Latin/Tonga
- { 124, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tsonga/Latin/South Africa
- { 125, 7, 217, 3947, 3947, 3947, 3947, 153, 153, 80, 80, 80, 80, 26, 26 },// Turkish/Latin/Turkey
- { 125, 7, 56, 3947, 3947, 3947, 3947, 153, 153, 80, 80, 80, 80, 26, 26 },// Turkish/Latin/Cyprus
- { 126, 7, 218, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Turkmen/Latin/Turkmenistan
- { 128, 1, 44, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uighur/Arabic/China
- { 129, 2, 222, 4027, 4027, 4107, 4156, 153, 153, 80, 80, 49, 57, 26, 26 },// Ukrainian/Cyrillic/Ukraine
- { 130, 1, 163, 4213, 4213, 4213, 4213, 153, 153, 66, 66, 66, 66, 26, 26 },// Urdu/Arabic/Pakistan
- { 130, 1, 100, 4213, 4213, 4213, 4213, 153, 153, 66, 66, 66, 66, 26, 26 },// Urdu/Arabic/India
- { 131, 7, 228, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uzbek/Latin/Uzbekistan
- { 131, 1, 1, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uzbek/Arabic/Afghanistan
- { 131, 2, 228, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uzbek/Cyrillic/Uzbekistan
- { 132, 7, 232, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vietnamese/Latin/Vietnam
- { 133, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Volapuk/Latin/World
- { 134, 7, 224, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Welsh/Latin/United Kingdom
- { 135, 7, 187, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Wolof/Latin/Senegal
- { 136, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Xhosa/Latin/South Africa
- { 137, 18, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yiddish/Hebrew/World
- { 138, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yoruba/Latin/Nigeria
- { 138, 7, 23, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yoruba/Latin/Benin
- { 140, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Zulu/Latin/South Africa
- { 141, 7, 161, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Norwegian Nynorsk/Latin/Norway
- { 142, 7, 27, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bosnian/Latin/Bosnia And Herzegowina
- { 142, 2, 27, 3199, 3199, 3199, 3199, 153, 153, 80, 80, 80, 80, 26, 26 },// Bosnian/Cyrillic/Bosnia And Herzegowina
- { 143, 29, 131, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Divehi/Thaana/Maldives
- { 144, 7, 251, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Manx/Latin/Isle Of Man
- { 145, 7, 224, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Cornish/Latin/United Kingdom
- { 146, 7, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Akan/Latin/Ghana
- { 147, 13, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Konkani/Devanagari/India
- { 148, 7, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ga/Latin/Ghana
- { 149, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Igbo/Latin/Nigeria
- { 150, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kamba/Latin/Kenya
- { 151, 33, 103, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Syriac/Syriac/Iraq
- { 152, 14, 67, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Blin/Ethiopic/Eritrea
- { 153, 14, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Geez/Ethiopic/Ethiopia
- { 155, 7, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sidamo/Latin/Ethiopia
- { 156, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Atsam/Latin/Nigeria
- { 157, 14, 67, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tigre/Ethiopic/Eritrea
- { 158, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Jju/Latin/Nigeria
- { 159, 7, 106, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Friulian/Latin/Italy
- { 160, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Venda/Latin/South Africa
- { 161, 7, 83, 4279, 4279, 4365, 4365, 153, 153, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Ghana
- { 161, 7, 212, 4279, 4279, 4365, 4365, 153, 153, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Togo
- { 162, 14, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Walamo/Ethiopic/Ethiopia
- { 163, 7, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hawaiian/Latin/United States
- { 164, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tyap/Latin/Nigeria
- { 165, 7, 129, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nyanja/Latin/Malawi
- { 166, 7, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Filipino/Latin/Philippines
- { 167, 7, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swiss German/Latin/Switzerland
- { 167, 7, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swiss German/Latin/France
- { 167, 7, 123, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swiss German/Latin/Liechtenstein
- { 168, 34, 44, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sichuan Yi/Yi/China
- { 169, 7, 121, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kpelle/Latin/Liberia
- { 170, 7, 82, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Low German/Latin/Germany
- { 170, 7, 151, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Low German/Latin/Netherlands
- { 171, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// South Ndebele/Latin/South Africa
- { 172, 7, 195, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sotho/Latin/South Africa
- { 173, 7, 161, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sami/Latin/Norway
- { 173, 7, 73, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sami/Latin/Finland
- { 173, 7, 205, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sami/Latin/Sweden
- { 174, 7, 208, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Taroko/Latin/Taiwan
- { 175, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Gusii/Latin/Kenya
- { 176, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Taita/Latin/Kenya
- { 177, 7, 187, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Senegal
- { 177, 7, 34, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Burkina Faso
- { 177, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Cameroon
- { 177, 7, 80, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Gambia
- { 177, 7, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Ghana
- { 177, 7, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Guinea
- { 177, 7, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Guinea Bissau
- { 177, 7, 121, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Liberia
- { 177, 7, 136, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Mauritania
- { 177, 7, 156, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Niger
- { 177, 7, 157, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Nigeria
- { 177, 7, 189, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Sierra Leone
- { 177, 134, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Adlam/Guinea
- { 178, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kikuyu/Latin/Kenya
- { 179, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Samburu/Latin/Kenya
- { 180, 7, 146, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sena/Latin/Mozambique
- { 181, 7, 240, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// North Ndebele/Latin/Zimbabwe
- { 182, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rombo/Latin/Tanzania
- { 183, 9, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tachelhit/Tifinagh/Morocco
- { 183, 7, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tachelhit/Latin/Morocco
- { 184, 7, 3, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kabyle/Latin/Algeria
- { 185, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nyankole/Latin/Uganda
- { 186, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bena/Latin/Tanzania
- { 187, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vunjo/Latin/Tanzania
- { 188, 7, 132, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bambara/Latin/Mali
- { 188, 75, 132, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bambara/Nko/Mali
- { 189, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Embu/Latin/Kenya
- { 190, 12, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Cherokee/Cherokee/United States
- { 191, 7, 137, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Morisyen/Latin/Mauritius
- { 192, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Makonde/Latin/Tanzania
- { 193, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Langi/Latin/Tanzania
- { 194, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ganda/Latin/Uganda
- { 195, 7, 239, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bemba/Latin/Zambia
- { 196, 7, 39, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kabuverdianu/Latin/Cape Verde
- { 197, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Meru/Latin/Kenya
- { 198, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kalenjin/Latin/Kenya
- { 199, 7, 148, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nama/Latin/Namibia
- { 200, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Machame/Latin/Tanzania
- { 201, 7, 82, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Colognian/Latin/Germany
- { 202, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Masai/Latin/Kenya
- { 202, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Masai/Latin/Tanzania
- { 203, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Soga/Latin/Uganda
- { 204, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luyia/Latin/Kenya
- { 205, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Asu/Latin/Tanzania
- { 206, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Teso/Latin/Uganda
- { 206, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Teso/Latin/Kenya
- { 207, 7, 67, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Saho/Latin/Eritrea
- { 208, 7, 132, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Koyra Chiini/Latin/Mali
- { 209, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rwa/Latin/Tanzania
- { 210, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luo/Latin/Kenya
- { 211, 7, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chiga/Latin/Uganda
- { 212, 7, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Central Morocco Tamazight/Latin/Morocco
- { 213, 7, 132, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Koyraboro Senni/Latin/Mali
- { 214, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Shambala/Latin/Tanzania
- { 215, 13, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bodo/Devanagari/India
- { 218, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chechen/Cyrillic/Russia
- { 219, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Church/Cyrillic/Russia
- { 220, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chuvash/Cyrillic/Russia
- { 230, 7, 49, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luba Katanga/Latin/Congo Kinshasa
- { 231, 7, 125, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luxembourgish/Latin/Luxembourg
- { 236, 7, 21, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Walloon/Latin/Belgium
- { 237, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Aghem/Latin/Cameroon
- { 238, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Basaa/Latin/Cameroon
- { 239, 7, 156, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Zarma/Latin/Niger
- { 240, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Duala/Latin/Cameroon
- { 241, 7, 187, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Jola Fonyi/Latin/Senegal
- { 242, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ewondo/Latin/Cameroon
- { 243, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bafia/Latin/Cameroon
- { 244, 7, 146, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Makhuwa Meetto/Latin/Mozambique
- { 245, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mundang/Latin/Cameroon
- { 246, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kwasio/Latin/Cameroon
- { 247, 7, 254, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nuer/Latin/South Sudan
- { 248, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sakha/Cyrillic/Russia
- { 249, 7, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sangu/Latin/Tanzania
- { 251, 7, 156, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tasawaq/Latin/Niger
- { 252, 35, 121, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vai/Vai/Liberia
- { 252, 7, 121, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vai/Latin/Liberia
- { 253, 7, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Walser/Latin/Switzerland
- { 254, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yangben/Latin/Cameroon
- { 256, 7, 197, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Asturian/Latin/Spain
- { 257, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ngomba/Latin/Cameroon
- { 258, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kako/Latin/Cameroon
- { 259, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Meta/Latin/Cameroon
- { 260, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ngiemboon/Latin/Cameroon
- { 261, 7, 197, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Aragonese/Latin/Spain
- { 272, 46, 18, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chakma/Chakma/Bangladesh
- { 272, 46, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chakma/Chakma/India
- { 290, 11, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Manipuri/Bengali/India
- { 309, 100, 232, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tai Dam/Tai Viet/Vietnam
- { 312, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Akoose/Latin/Cameroon
- { 313, 7, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lakota/Latin/United States
- { 314, 9, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Standard Moroccan Tamazight/Tifinagh/Morocco
- { 315, 7, 43, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mapuche/Latin/Chile
- { 316, 1, 103, 4412, 4412, 4412, 4412, 153, 153,101,101,101,101, 26, 26 },// Central Kurdish/Arabic/Iraq
- { 316, 1, 102, 4412, 4412, 4412, 4412, 153, 153,101,101,101,101, 26, 26 },// Central Kurdish/Arabic/Iran
- { 317, 7, 82, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lower Sorbian/Latin/Germany
- { 318, 7, 82, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Upper Sorbian/Latin/Germany
- { 319, 7, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kenyang/Latin/Cameroon
- { 320, 7, 38, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mohawk/Latin/Canada
- { 321, 75, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nko/Nko/Guinea
- { 322, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Prussian/Latin/World
- { 323, 7, 90, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kiche/Latin/Guatemala
- { 324, 7, 205, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Sami/Latin/Sweden
- { 325, 7, 205, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lule Sami/Latin/Sweden
- { 326, 7, 73, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Inari Sami/Latin/Finland
- { 327, 7, 73, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Skolt Sami/Latin/Finland
- { 328, 7, 13, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Warlpiri/Latin/Australia
- { 346, 1, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mazanderani/Arabic/Iran
- { 349, 1, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Luri/Arabic/Iran
- { 349, 1, 103, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Luri/Arabic/Iraq
- { 357, 6, 97, 484, 484, 484, 484, 153, 153, 38, 38, 38, 38, 26, 26 },// Cantonese/Traditional Han/Hong Kong
- { 357, 5, 44, 484, 484, 484, 484, 153, 153, 38, 38, 38, 38, 26, 26 },// Cantonese/Simplified Han/China
- { 358, 138, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Osage/Osage/United States
- { 360, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ido/Latin/World
- { 361, 7, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lojban/Latin/World
- { 362, 7, 106, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sicilian/Latin/Italy
- { 363, 1, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Kurdish/Arabic/Iran
- { 364, 1, 163, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Balochi/Arabic/Pakistan
- { 365, 7, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Cebuano/Latin/Philippines
- { 366, 2, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Erzya/Cyrillic/Russia
- { 367, 7, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chickasaw/Latin/United States
- { 368, 7, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Muscogee/Latin/United States
- { 369, 7, 172, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Silesian/Latin/Poland
+ { 1, 0, 0, 0, 0, 83, 83, 130, 153, 83, 83, 47, 47, 23, 26 },// C/AnyScript/AnyTerritory
+ { 2, 27, 90, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Abkhazian/Cyrillic/Georgia
+ { 3, 66, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afar/Latin/Ethiopia
+ { 3, 66, 67, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afar/Latin/Djibouti
+ { 3, 66, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afar/Latin/Eritrea
+ { 4, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afrikaans/Latin/South Africa
+ { 4, 66, 162, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Afrikaans/Latin/Namibia
+ { 5, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Aghem/Latin/Cameroon
+ { 6, 66, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Akan/Latin/Ghana
+ { 8, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Akoose/Latin/Cameroon
+ { 9, 66, 3, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Albanian/Latin/Albania
+ { 9, 66, 126, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Albanian/Latin/Kosovo
+ { 9, 66, 140, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Albanian/Latin/Macedonia
+ { 11, 33, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Amharic/Ethiopic/Ethiopia
+ { 14, 4, 71, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Egypt
+ { 14, 4, 4, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Algeria
+ { 14, 4, 19, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Bahrain
+ { 14, 4, 48, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Chad
+ { 14, 4, 55, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Comoros
+ { 14, 4, 67, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Djibouti
+ { 14, 4, 74, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Eritrea
+ { 14, 4, 113, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Iraq
+ { 14, 4, 116, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Israel
+ { 14, 4, 122, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Jordan
+ { 14, 4, 127, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Kuwait
+ { 14, 4, 132, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Lebanon
+ { 14, 4, 135, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Libya
+ { 14, 4, 149, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Mauritania
+ { 14, 4, 159, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Morocco
+ { 14, 4, 176, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Oman
+ { 14, 4, 180, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Palestinian Territories
+ { 14, 4, 190, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Qatar
+ { 14, 4, 205, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Saudi Arabia
+ { 14, 4, 215, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Somalia
+ { 14, 4, 219, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/South Sudan
+ { 14, 4, 222, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Sudan
+ { 14, 4, 227, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Syria
+ { 14, 4, 238, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Tunisia
+ { 14, 4, 245, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/United Arab Emirates
+ { 14, 4, 257, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Western Sahara
+ { 14, 4, 258, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/world
+ { 14, 4, 259, 179, 179, 179, 179, 153, 153, 67, 67, 67, 67, 26, 26 },// Arabic/Arabic/Yemen
+ { 15, 66, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Aragonese/Latin/Spain
+ { 17, 5, 12, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Armenian/Armenian/Armenia
+ { 18, 9, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Assamese/Bangla/India
+ { 19, 66, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Asturian/Latin/Spain
+ { 20, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Asu/Latin/Tanzania
+ { 21, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Atsam/Latin/Nigeria
+ { 25, 66, 17, 246, 246, 246, 246, 153, 153, 80, 80, 80, 80, 26, 26 },// Azerbaijani/Latin/Azerbaijan
+ { 25, 4, 112, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Arabic/Iran
+ { 25, 4, 113, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Arabic/Iraq
+ { 25, 4, 239, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Arabic/Turkey
+ { 25, 27, 17, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Azerbaijani/Cyrillic/Azerbaijan
+ { 26, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bafia/Latin/Cameroon
+ { 28, 66, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bambara/Latin/Mali
+ { 28, 90, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bambara/Nko/Mali
+ { 30, 9, 20, 326, 326, 414, 414, 501, 501, 88, 88, 87, 87, 26, 26 },// Bangla/Bangla/Bangladesh
+ { 30, 9, 110, 326, 326, 414, 414, 501, 501, 88, 88, 87, 87, 26, 26 },// Bangla/Bangla/India
+ { 31, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Basaa/Latin/Cameroon
+ { 32, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bashkir/Cyrillic/Russia
+ { 33, 66, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Basque/Latin/Spain
+ { 35, 27, 22, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Belarusian/Cyrillic/Belarus
+ { 36, 66, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bemba/Latin/Zambia
+ { 37, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bena/Latin/Tanzania
+ { 38, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bhojpuri/Devanagari/India
+ { 40, 33, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Blin/Ethiopic/Eritrea
+ { 41, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bodo/Devanagari/India
+ { 42, 66, 29, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bosnian/Latin/Bosnia and Herzegovina
+ { 42, 27, 29, 527, 527, 527, 527, 153, 153, 80, 80, 80, 80, 26, 26 },// Bosnian/Cyrillic/Bosnia and Herzegovina
+ { 43, 66, 84, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Breton/Latin/France
+ { 45, 27, 36, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Bulgarian/Cyrillic/Bulgaria
+ { 46, 86, 161, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Burmese/Myanmar/Myanmar
+ { 47, 137, 107, 607, 607, 607, 607, 153, 153, 38, 38, 38, 38, 26, 26 },// Cantonese/Traditional Han/Hong Kong
+ { 47, 118, 50, 607, 607, 607, 607, 153, 153, 38, 38, 38, 38, 26, 26 },// Cantonese/Simplified Han/China
+ { 48, 66, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/Spain
+ { 48, 66, 6, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/Andorra
+ { 48, 66, 84, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/France
+ { 48, 66, 117, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Catalan/Latin/Italy
+ { 49, 66, 185, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Cebuano/Latin/Philippines
+ { 50, 66, 159, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Central Atlas Tamazight/Latin/Morocco
+ { 51, 4, 113, 645, 645, 645, 645, 153, 153,101,101,101,101, 26, 26 },// Central Kurdish/Arabic/Iraq
+ { 51, 4, 112, 746, 746, 746, 746, 153, 153,100,100,100,100, 26, 26 },// Central Kurdish/Arabic/Iran
+ { 52, 21, 20, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chakma/Chakma/Bangladesh
+ { 52, 21, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chakma/Chakma/India
+ { 54, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chechen/Cyrillic/Russia
+ { 55, 23, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Cherokee/Cherokee/United States
+ { 56, 66, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chickasaw/Latin/United States
+ { 57, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chiga/Latin/Uganda
+ { 58, 118, 50, 846, 846, 607, 607, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/China
+ { 58, 118, 107, 846, 846, 607, 607, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Hong Kong
+ { 58, 118, 139, 846, 846, 607, 607, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Macao
+ { 58, 118, 210, 846, 846, 607, 607, 153, 153, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Singapore
+ { 58, 137, 107, 607, 607, 607, 607, 153, 153, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Hong Kong
+ { 58, 137, 139, 607, 607, 607, 607, 153, 153, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Macao
+ { 58, 137, 228, 607, 607, 607, 607, 153, 153, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Taiwan
+ { 59, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Church/Cyrillic/Russia
+ { 60, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Chuvash/Cyrillic/Russia
+ { 61, 66, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Colognian/Latin/Germany
+ { 63, 66, 246, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Cornish/Latin/United Kingdom
+ { 64, 66, 84, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Corsican/Latin/France
+ { 66, 66, 60, 0, 0, 0, 0, 883, 883, 83, 83, 83, 83, 38, 38 },// Croatian/Latin/Croatia
+ { 66, 66, 29, 0, 0, 0, 0, 883, 883, 83, 83, 83, 83, 38, 38 },// Croatian/Latin/Bosnia and Herzegovina
+ { 67, 66, 64, 921, 921, 921, 921, 153, 153, 81, 81, 81, 81, 26, 26 },// Czech/Latin/Czechia
+ { 68, 66, 65, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Danish/Latin/Denmark
+ { 68, 66, 95, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Danish/Latin/Greenland
+ { 69, 132, 144, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Divehi/Thaana/Maldives
+ { 70, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dogri/Devanagari/India
+ { 71, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Duala/Latin/Cameroon
+ { 72, 66, 165, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Netherlands
+ { 72, 66, 13, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Aruba
+ { 72, 66, 23, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Belgium
+ { 72, 66, 44, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Caribbean Netherlands
+ { 72, 66, 62, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Curacao
+ { 72, 66, 211, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Sint Maarten
+ { 72, 66, 223, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dutch/Latin/Suriname
+ { 73, 134, 27, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Dzongkha/Tibetan/Bhutan
+ { 74, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Embu/Latin/Kenya
+ { 75, 66, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United States
+ { 75, 28, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Deseret/United States
+ { 75, 66, 5, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/American Samoa
+ { 75, 66, 8, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Anguilla
+ { 75, 66, 10, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Antigua and Barbuda
+ { 75, 66, 15, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Australia
+ { 75, 66, 16, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Austria
+ { 75, 66, 18, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Bahamas
+ { 75, 66, 21, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Barbados
+ { 75, 66, 23, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Belgium
+ { 75, 66, 24, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Belize
+ { 75, 66, 26, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Bermuda
+ { 75, 66, 30, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Botswana
+ { 75, 66, 33, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/British Indian Ocean Territory
+ { 75, 66, 34, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/British Virgin Islands
+ { 75, 66, 38, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Burundi
+ { 75, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cameroon
+ { 75, 66, 41, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Canada
+ { 75, 66, 45, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cayman Islands
+ { 75, 66, 51, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Christmas Island
+ { 75, 66, 53, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cocos Islands
+ { 75, 66, 58, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cook Islands
+ { 75, 66, 63, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Cyprus
+ { 75, 66, 65, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Denmark
+ { 75, 66, 66, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Diego Garcia
+ { 75, 66, 68, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Dominica
+ { 75, 66, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Eritrea
+ { 75, 66, 76, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Eswatini
+ { 75, 66, 78, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Europe
+ { 75, 66, 80, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Falkland Islands
+ { 75, 66, 82, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Fiji
+ { 75, 66, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Finland
+ { 75, 66, 89, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Gambia
+ { 75, 66, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Germany
+ { 75, 66, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Ghana
+ { 75, 66, 93, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Gibraltar
+ { 75, 66, 96, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Grenada
+ { 75, 66, 98, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Guam
+ { 75, 66, 100, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Guernsey
+ { 75, 66, 103, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Guyana
+ { 75, 66, 107, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Hong Kong
+ { 75, 66, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/India
+ { 75, 66, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Indonesia
+ { 75, 66, 114, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Ireland
+ { 75, 66, 115, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Isle of Man
+ { 75, 66, 116, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Israel
+ { 75, 66, 119, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Jamaica
+ { 75, 66, 121, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Jersey
+ { 75, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Kenya
+ { 75, 66, 125, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Kiribati
+ { 75, 66, 133, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Lesotho
+ { 75, 66, 134, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Liberia
+ { 75, 66, 139, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Macao
+ { 75, 66, 141, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Madagascar
+ { 75, 66, 142, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Malawi
+ { 75, 66, 143, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Malaysia
+ { 75, 66, 144, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Maldives
+ { 75, 66, 146, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Malta
+ { 75, 66, 147, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Marshall Islands
+ { 75, 66, 150, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Mauritius
+ { 75, 66, 153, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Micronesia
+ { 75, 66, 158, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Montserrat
+ { 75, 66, 162, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Namibia
+ { 75, 66, 163, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Nauru
+ { 75, 66, 165, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Netherlands
+ { 75, 66, 167, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/New Zealand
+ { 75, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Nigeria
+ { 75, 66, 171, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Niue
+ { 75, 66, 172, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Norfolk Island
+ { 75, 66, 173, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Northern Mariana Islands
+ { 75, 66, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Pakistan
+ { 75, 66, 179, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Palau
+ { 75, 66, 182, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Papua New Guinea
+ { 75, 66, 185, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Philippines
+ { 75, 66, 186, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Pitcairn
+ { 75, 66, 189, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Puerto Rico
+ { 75, 66, 194, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Rwanda
+ { 75, 66, 196, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Helena
+ { 75, 66, 197, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Kitts and Nevis
+ { 75, 66, 198, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Lucia
+ { 75, 66, 201, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Saint Vincent and Grenadines
+ { 75, 66, 202, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Samoa
+ { 75, 66, 208, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Seychelles
+ { 75, 66, 209, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sierra Leone
+ { 75, 66, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Singapore
+ { 75, 66, 211, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sint Maarten
+ { 75, 66, 213, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Slovenia
+ { 75, 66, 214, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Solomon Islands
+ { 75, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/South Africa
+ { 75, 66, 219, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/South Sudan
+ { 75, 66, 222, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sudan
+ { 75, 66, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Sweden
+ { 75, 66, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Switzerland
+ { 75, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tanzania
+ { 75, 66, 234, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tokelau
+ { 75, 66, 235, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tonga
+ { 75, 66, 236, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Trinidad and Tobago
+ { 75, 66, 241, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Turks and Caicos Islands
+ { 75, 66, 242, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Tuvalu
+ { 75, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Uganda
+ { 75, 66, 245, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United Arab Emirates
+ { 75, 66, 246, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United Kingdom
+ { 75, 66, 247, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United States Outlying Islands
+ { 75, 66, 249, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/United States Virgin Islands
+ { 75, 66, 252, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Vanuatu
+ { 75, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/world
+ { 75, 66, 260, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Zambia
+ { 75, 66, 261, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Latin/Zimbabwe
+ { 75, 115, 246, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// English/Shavian/United Kingdom
+ { 76, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Erzya/Cyrillic/Russia
+ { 77, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Esperanto/Latin/world
+ { 78, 66, 75, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Estonian/Latin/Estonia
+ { 79, 66, 92, 1085, 1085, 1171, 1171, 153, 153, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Ghana
+ { 79, 66, 233, 1085, 1085, 1171, 1171, 153, 153, 86, 86, 47, 47, 26, 26 },// Ewe/Latin/Togo
+ { 80, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ewondo/Latin/Cameroon
+ { 81, 66, 81, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Faroese/Latin/Faroe Islands
+ { 81, 66, 65, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Faroese/Latin/Denmark
+ { 83, 66, 185, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Filipino/Latin/Philippines
+ { 84, 66, 83, 1218, 1335, 1476, 1335, 153, 153,117,141, 81,141, 26, 26 },// Finnish/Latin/Finland
+ { 85, 66, 84, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/France
+ { 85, 66, 4, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Algeria
+ { 85, 66, 23, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Belgium
+ { 85, 66, 25, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Benin
+ { 85, 66, 37, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Burkina Faso
+ { 85, 66, 38, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Burundi
+ { 85, 66, 40, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Cameroon
+ { 85, 66, 41, 1695, 1695, 1776, 1776, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Canada
+ { 85, 66, 46, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Central African Republic
+ { 85, 66, 48, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Chad
+ { 85, 66, 55, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Comoros
+ { 85, 66, 56, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Congo - Brazzaville
+ { 85, 66, 57, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Congo - Kinshasa
+ { 85, 66, 67, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Djibouti
+ { 85, 66, 73, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Equatorial Guinea
+ { 85, 66, 85, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/French Guiana
+ { 85, 66, 86, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/French Polynesia
+ { 85, 66, 88, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Gabon
+ { 85, 66, 97, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Guadeloupe
+ { 85, 66, 102, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Guinea
+ { 85, 66, 104, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Haiti
+ { 85, 66, 118, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Ivory Coast
+ { 85, 66, 138, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Luxembourg
+ { 85, 66, 141, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Madagascar
+ { 85, 66, 145, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mali
+ { 85, 66, 148, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Martinique
+ { 85, 66, 149, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mauritania
+ { 85, 66, 150, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mauritius
+ { 85, 66, 151, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Mayotte
+ { 85, 66, 155, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Monaco
+ { 85, 66, 159, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Morocco
+ { 85, 66, 166, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/New Caledonia
+ { 85, 66, 170, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Niger
+ { 85, 66, 191, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Reunion
+ { 85, 66, 194, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Rwanda
+ { 85, 66, 195, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Saint Barthelemy
+ { 85, 66, 199, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Saint Martin
+ { 85, 66, 200, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Saint Pierre and Miquelon
+ { 85, 66, 206, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Senegal
+ { 85, 66, 208, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Seychelles
+ { 85, 66, 226, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Switzerland
+ { 85, 66, 227, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Syria
+ { 85, 66, 233, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Togo
+ { 85, 66, 238, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Tunisia
+ { 85, 66, 252, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Vanuatu
+ { 85, 66, 256, 1557, 1557, 1638, 1638, 153, 153, 81, 81, 57, 57, 26, 26 },// French/Latin/Wallis and Futuna
+ { 86, 66, 117, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Friulian/Latin/Italy
+ { 87, 66, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Senegal
+ { 87, 1, 37, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Burkina Faso
+ { 87, 1, 40, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Cameroon
+ { 87, 1, 89, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Gambia
+ { 87, 1, 92, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Ghana
+ { 87, 1, 101, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Guinea-Bissau
+ { 87, 1, 102, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Guinea
+ { 87, 1, 134, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Liberia
+ { 87, 1, 149, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Mauritania
+ { 87, 1, 169, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Nigeria
+ { 87, 1, 170, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Niger
+ { 87, 1, 206, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Senegal
+ { 87, 1, 209, 1833, 1833, 1833, 1833, 1984, 1984,151,151,151,151, 41, 41 },// Fulah/Adlam/Sierra Leone
+ { 87, 66, 37, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Burkina Faso
+ { 87, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Cameroon
+ { 87, 66, 89, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Gambia
+ { 87, 66, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Ghana
+ { 87, 66, 101, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Guinea-Bissau
+ { 87, 66, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Guinea
+ { 87, 66, 134, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Liberia
+ { 87, 66, 149, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Mauritania
+ { 87, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Nigeria
+ { 87, 66, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Niger
+ { 87, 66, 209, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Fulah/Latin/Sierra Leone
+ { 88, 66, 246, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Gaelic/Latin/United Kingdom
+ { 89, 66, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ga/Latin/Ghana
+ { 90, 66, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Galician/Latin/Spain
+ { 91, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ganda/Latin/Uganda
+ { 92, 33, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Geez/Ethiopic/Ethiopia
+ { 92, 33, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Geez/Ethiopic/Eritrea
+ { 93, 35, 90, 2025, 2025, 2025, 2025, 153, 153, 91, 91, 91, 91, 26, 26 },// Georgian/Georgian/Georgia
+ { 94, 66, 91, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Germany
+ { 94, 66, 16, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Austria
+ { 94, 66, 23, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Belgium
+ { 94, 66, 117, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Italy
+ { 94, 66, 136, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Liechtenstein
+ { 94, 66, 138, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Luxembourg
+ { 94, 66, 226, 2116, 2116, 2116, 2116, 153, 153, 86, 86, 86, 86, 26, 26 },// German/Latin/Switzerland
+ { 96, 39, 94, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Greek/Greek/Greece
+ { 96, 39, 63, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Greek/Greek/Cyprus
+ { 97, 66, 183, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Guarani/Latin/Paraguay
+ { 98, 40, 110, 2202, 2202, 2202, 2202, 153, 153, 85, 85, 85, 85, 26, 26 },// Gujarati/Gujarati/India
+ { 99, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Gusii/Latin/Kenya
+ { 101, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Latin/Nigeria
+ { 101, 4, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Arabic/Nigeria
+ { 101, 4, 222, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Arabic/Sudan
+ { 101, 66, 92, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Latin/Ghana
+ { 101, 66, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hausa/Latin/Niger
+ { 102, 66, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hawaiian/Latin/United States
+ { 103, 47, 116, 2287, 2287, 2287, 2287, 153, 153, 68, 68, 68, 68, 26, 26 },// Hebrew/Hebrew/Israel
+ { 105, 29, 110, 2355, 2355, 2355, 2355, 153, 153, 81, 81, 81, 81, 26, 26 },// Hindi/Devanagari/India
+ { 105, 66, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Hindi/Latin/India
+ { 107, 66, 108, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Hungarian/Latin/Hungary
+ { 108, 66, 109, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Icelandic/Latin/Iceland
+ { 109, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ido/Latin/world
+ { 110, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Igbo/Latin/Nigeria
+ { 111, 66, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Inari Sami/Latin/Finland
+ { 112, 66, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Indonesian/Latin/Indonesia
+ { 114, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Interlingua/Latin/world
+ { 115, 66, 75, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Interlingue/Latin/Estonia
+ { 116, 18, 41, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Inuktitut/Canadian Aboriginal/Canada
+ { 116, 66, 41, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Inuktitut/Latin/Canada
+ { 118, 66, 114, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Irish/Latin/Ireland
+ { 118, 66, 246, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Irish/Latin/United Kingdom
+ { 119, 66, 117, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/Italy
+ { 119, 66, 203, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/San Marino
+ { 119, 66, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/Switzerland
+ { 119, 66, 253, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Italian/Latin/Vatican City
+ { 120, 53, 120, 2436, 2436, 2436, 2436, 153, 153, 77, 77, 77, 77, 26, 26 },// Japanese/Japanese/Japan
+ { 121, 66, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Javanese/Latin/Indonesia
+ { 122, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Jju/Latin/Nigeria
+ { 123, 66, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Jola-Fonyi/Latin/Senegal
+ { 124, 66, 43, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kabuverdianu/Latin/Cape Verde
+ { 125, 66, 4, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kabyle/Latin/Algeria
+ { 126, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kako/Latin/Cameroon
+ { 127, 66, 95, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kalaallisut/Latin/Greenland
+ { 128, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kalenjin/Latin/Kenya
+ { 129, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kamba/Latin/Kenya
+ { 130, 56, 110, 2513, 2513, 2513, 2513, 153, 153, 92, 92, 92, 92, 26, 26 },// Kannada/Kannada/India
+ { 132, 4, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kashmiri/Arabic/India
+ { 132, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kashmiri/Devanagari/India
+ { 133, 27, 123, 2605, 2605, 2605, 2605, 153, 153, 80, 80, 80, 80, 26, 26 },// Kazakh/Cyrillic/Kazakhstan
+ { 134, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kenyang/Latin/Cameroon
+ { 135, 60, 39, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Khmer/Khmer/Cambodia
+ { 136, 66, 99, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kiche/Latin/Guatemala
+ { 137, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kikuyu/Latin/Kenya
+ { 138, 66, 194, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kinyarwanda/Latin/Rwanda
+ { 141, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Konkani/Devanagari/India
+ { 142, 63, 218, 2685, 2685, 2685, 2685, 153, 153, 54, 54, 54, 54, 26, 26 },// Korean/Korean/South Korea
+ { 142, 63, 50, 2685, 2685, 2685, 2685, 153, 153, 54, 54, 54, 54, 26, 26 },// Korean/Korean/China
+ { 142, 63, 174, 2685, 2685, 2685, 2685, 153, 153, 54, 54, 54, 54, 26, 26 },// Korean/Korean/North Korea
+ { 144, 66, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Koyraboro Senni/Latin/Mali
+ { 145, 66, 145, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Koyra Chiini/Latin/Mali
+ { 146, 66, 134, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kpelle/Latin/Liberia
+ { 146, 66, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kpelle/Latin/Guinea
+ { 148, 66, 239, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kurdish/Latin/Turkey
+ { 149, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kwasio/Latin/Cameroon
+ { 150, 27, 128, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kyrgyz/Cyrillic/Kyrgyzstan
+ { 151, 66, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lakota/Latin/United States
+ { 152, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Langi/Latin/Tanzania
+ { 153, 65, 129, 2739, 2739, 2819, 2898, 153, 153, 80, 80, 79, 79, 26, 26 },// Lao/Lao/Laos
+ { 154, 66, 253, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Latin/Latin/Vatican City
+ { 155, 66, 131, 2977, 2977, 2977, 2977, 153, 153, 92, 92, 92, 92, 26, 26 },// Latvian/Latin/Latvia
+ { 158, 66, 57, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Congo - Kinshasa
+ { 158, 66, 7, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Angola
+ { 158, 66, 46, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Central African Republic
+ { 158, 66, 56, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lingala/Latin/Congo - Brazzaville
+ { 160, 66, 137, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lithuanian/Latin/Lithuania
+ { 161, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lojban/Latin/world
+ { 162, 66, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lower Sorbian/Latin/Germany
+ { 163, 66, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Low German/Latin/Germany
+ { 163, 66, 165, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Low German/Latin/Netherlands
+ { 164, 66, 57, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luba-Katanga/Latin/Congo - Kinshasa
+ { 165, 66, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lule Sami/Latin/Sweden
+ { 165, 66, 175, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Lule Sami/Latin/Norway
+ { 166, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luo/Latin/Kenya
+ { 167, 66, 138, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luxembourgish/Latin/Luxembourg
+ { 168, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Luyia/Latin/Kenya
+ { 169, 27, 140, 3069, 3069, 3069, 3069, 153, 153, 79, 79, 79, 79, 26, 26 },// Macedonian/Cyrillic/Macedonia
+ { 170, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Machame/Latin/Tanzania
+ { 171, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Maithili/Devanagari/India
+ { 172, 66, 160, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Makhuwa-Meetto/Latin/Mozambique
+ { 173, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Makonde/Latin/Tanzania
+ { 174, 66, 141, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malagasy/Latin/Madagascar
+ { 175, 74, 110, 3148, 3148, 3148, 3148, 3239, 3239, 91, 91, 91, 91, 39, 39 },// Malayalam/Malayalam/India
+ { 176, 66, 143, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Malaysia
+ { 176, 4, 35, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Arabic/Brunei
+ { 176, 4, 143, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Arabic/Malaysia
+ { 176, 66, 35, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Brunei
+ { 176, 66, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Indonesia
+ { 176, 66, 210, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Malay/Latin/Singapore
+ { 177, 66, 146, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Maltese/Latin/Malta
+ { 179, 9, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Manipuri/Bangla/India
+ { 179, 78, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Manipuri/Meitei Mayek/India
+ { 180, 66, 115, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Manx/Latin/Isle of Man
+ { 181, 66, 167, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Maori/Latin/New Zealand
+ { 182, 66, 49, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mapuche/Latin/Chile
+ { 183, 29, 110, 3278, 3278, 3278, 3278, 3358, 3358, 80, 80, 80, 80, 26, 26 },// Marathi/Devanagari/India
+ { 185, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Masai/Latin/Kenya
+ { 185, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Masai/Latin/Tanzania
+ { 186, 4, 112, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mazanderani/Arabic/Iran
+ { 188, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Meru/Latin/Kenya
+ { 189, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Meta/Latin/Cameroon
+ { 190, 66, 41, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mohawk/Latin/Canada
+ { 191, 27, 156, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mongolian/Cyrillic/Mongolia
+ { 191, 83, 50, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mongolian/Mongolian/China
+ { 191, 83, 156, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mongolian/Mongolian/Mongolia
+ { 192, 66, 150, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Morisyen/Latin/Mauritius
+ { 193, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Mundang/Latin/Cameroon
+ { 194, 66, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Muscogee/Latin/United States
+ { 195, 66, 162, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nama/Latin/Namibia
+ { 197, 66, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Navajo/Latin/United States
+ { 199, 29, 164, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nepali/Devanagari/Nepal
+ { 199, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nepali/Devanagari/India
+ { 201, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ngiemboon/Latin/Cameroon
+ { 202, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ngomba/Latin/Cameroon
+ { 203, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nigerian Pidgin/Latin/Nigeria
+ { 204, 90, 102, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nko/Nko/Guinea
+ { 205, 4, 112, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Luri/Arabic/Iran
+ { 205, 4, 113, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Luri/Arabic/Iraq
+ { 206, 66, 175, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sami/Latin/Norway
+ { 206, 66, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sami/Latin/Finland
+ { 206, 66, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sami/Latin/Sweden
+ { 207, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Sotho/Latin/South Africa
+ { 208, 66, 261, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// North Ndebele/Latin/Zimbabwe
+ { 209, 66, 175, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Norwegian Bokmal/Latin/Norway
+ { 209, 66, 224, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Norwegian Bokmal/Latin/Svalbard and Jan Mayen
+ { 210, 66, 175, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Norwegian Nynorsk/Latin/Norway
+ { 211, 66, 219, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nuer/Latin/South Sudan
+ { 212, 66, 142, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nyanja/Latin/Malawi
+ { 213, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nyankole/Latin/Uganda
+ { 214, 66, 84, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Occitan/Latin/France
+ { 214, 66, 220, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Occitan/Latin/Spain
+ { 215, 91, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Odia/Odia/India
+ { 220, 66, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Ethiopia
+ { 220, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Kenya
+ { 221, 101, 248, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Osage/Osage/United States
+ { 222, 27, 90, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ossetic/Cyrillic/Georgia
+ { 222, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ossetic/Cyrillic/Russia
+ { 226, 66, 62, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Papiamento/Latin/Curacao
+ { 226, 66, 13, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Papiamento/Latin/Aruba
+ { 227, 4, 1, 3384, 3384, 3384, 3384, 3446, 3446, 62, 62, 62, 62, 26, 26 },// Pashto/Arabic/Afghanistan
+ { 227, 4, 178, 3384, 3384, 3384, 3384, 3446, 3446, 62, 62, 62, 62, 26, 26 },// Pashto/Arabic/Pakistan
+ { 228, 4, 112, 3472, 3472, 3472, 3472, 3538, 3538, 66, 66, 66, 66, 23, 23 },// Persian/Arabic/Iran
+ { 228, 4, 1, 3561, 3561, 3561, 3561, 3617, 3617, 56, 56, 56, 56, 23, 23 },// Persian/Arabic/Afghanistan
+ { 230, 66, 187, 3640, 3640, 3640, 3640, 153, 153, 83, 83, 83, 83, 26, 26 },// Polish/Latin/Poland
+ { 231, 66, 32, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Brazil
+ { 231, 66, 7, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Angola
+ { 231, 66, 43, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Cape Verde
+ { 231, 66, 73, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Equatorial Guinea
+ { 231, 66, 101, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Guinea-Bissau
+ { 231, 66, 138, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Luxembourg
+ { 231, 66, 139, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Macao
+ { 231, 66, 160, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Mozambique
+ { 231, 66, 188, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Portugal
+ { 231, 66, 204, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Sao Tome and Principe
+ { 231, 66, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Switzerland
+ { 231, 66, 232, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Portuguese/Latin/Timor-Leste
+ { 232, 66, 187, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Prussian/Latin/Poland
+ { 233, 41, 110, 3723, 3723, 3723, 3723, 153, 153, 77, 77, 77, 77, 26, 26 },// Punjabi/Gurmukhi/India
+ { 233, 4, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Punjabi/Arabic/Pakistan
+ { 234, 66, 184, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Quechua/Latin/Peru
+ { 234, 66, 28, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Quechua/Latin/Bolivia
+ { 234, 66, 70, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Quechua/Latin/Ecuador
+ { 235, 66, 192, 3800, 3800, 3800, 3800, 153, 153, 85, 85, 85, 85, 26, 26 },// Romanian/Latin/Romania
+ { 235, 66, 154, 3800, 3800, 3800, 3800, 153, 153, 85, 85, 85, 85, 26, 26 },// Romanian/Latin/Moldova
+ { 236, 66, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Romansh/Latin/Switzerland
+ { 237, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rombo/Latin/Tanzania
+ { 238, 66, 38, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rundi/Latin/Burundi
+ { 239, 27, 193, 3885, 3885, 3885, 3885, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Russia
+ { 239, 27, 22, 3885, 3885, 3885, 3885, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Belarus
+ { 239, 27, 123, 3885, 3885, 3885, 3885, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Kazakhstan
+ { 239, 27, 128, 3885, 3885, 3885, 3885, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Kyrgyzstan
+ { 239, 27, 154, 3885, 3885, 3885, 3885, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Moldova
+ { 239, 27, 244, 3885, 3885, 3885, 3885, 153, 153, 80, 80, 80, 80, 26, 26 },// Russian/Cyrillic/Ukraine
+ { 240, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rwa/Latin/Tanzania
+ { 241, 66, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Saho/Latin/Eritrea
+ { 242, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sakha/Cyrillic/Russia
+ { 243, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Samburu/Latin/Kenya
+ { 245, 66, 46, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sango/Latin/Central African Republic
+ { 246, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sangu/Latin/Tanzania
+ { 247, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sanskrit/Devanagari/India
+ { 248, 93, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Santali/Ol Chiki/India
+ { 248, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Santali/Devanagari/India
+ { 249, 66, 117, 1002, 1002, 3965, 3965, 153, 153, 83, 83, 57, 57, 26, 26 },// Sardinian/Latin/Italy
+ { 251, 66, 160, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sena/Latin/Mozambique
+ { 252, 27, 207, 527, 527, 527, 527, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Serbia
+ { 252, 27, 29, 527, 527, 527, 527, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Bosnia and Herzegovina
+ { 252, 27, 126, 527, 527, 527, 527, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Kosovo
+ { 252, 27, 157, 527, 527, 527, 527, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Cyrillic/Montenegro
+ { 252, 66, 29, 4022, 4022, 4022, 4022, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Bosnia and Herzegovina
+ { 252, 66, 126, 4022, 4022, 4022, 4022, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Kosovo
+ { 252, 66, 157, 4022, 4022, 4022, 4022, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Montenegro
+ { 252, 66, 207, 4022, 4022, 4022, 4022, 153, 153, 80, 80, 80, 80, 26, 26 },// Serbian/Latin/Serbia
+ { 253, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Shambala/Latin/Tanzania
+ { 254, 66, 261, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Shona/Latin/Zimbabwe
+ { 255, 141, 50, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sichuan Yi/Yi/China
+ { 256, 66, 117, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sicilian/Latin/Italy
+ { 257, 66, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sidamo/Latin/Ethiopia
+ { 258, 66, 187, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Silesian/Latin/Poland
+ { 259, 4, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sindhi/Arabic/Pakistan
+ { 259, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sindhi/Devanagari/India
+ { 260, 119, 221, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sinhala/Sinhala/Sri Lanka
+ { 261, 66, 83, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Skolt Sami/Latin/Finland
+ { 262, 66, 212, 921, 921, 921, 921, 153, 153, 81, 81, 81, 81, 26, 26 },// Slovak/Latin/Slovakia
+ { 263, 66, 213, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Slovenian/Latin/Slovenia
+ { 264, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Soga/Latin/Uganda
+ { 265, 66, 215, 4102, 4102, 4102, 4102, 153, 153, 99, 99, 99, 99, 26, 26 },// Somali/Latin/Somalia
+ { 265, 66, 67, 4102, 4102, 4102, 4102, 153, 153, 99, 99, 99, 99, 26, 26 },// Somali/Latin/Djibouti
+ { 265, 66, 77, 4102, 4102, 4102, 4102, 153, 153, 99, 99, 99, 99, 26, 26 },// Somali/Latin/Ethiopia
+ { 265, 66, 124, 4102, 4102, 4102, 4102, 153, 153, 99, 99, 99, 99, 26, 26 },// Somali/Latin/Kenya
+ { 266, 4, 112, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Kurdish/Arabic/Iran
+ { 266, 4, 113, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Kurdish/Arabic/Iraq
+ { 267, 66, 225, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Sami/Latin/Sweden
+ { 267, 66, 175, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Sami/Latin/Norway
+ { 268, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Sotho/Latin/South Africa
+ { 268, 66, 133, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Southern Sotho/Latin/Lesotho
+ { 269, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// South Ndebele/Latin/South Africa
+ { 270, 66, 220, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Spain
+ { 270, 66, 11, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Argentina
+ { 270, 66, 24, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Belize
+ { 270, 66, 28, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Bolivia
+ { 270, 66, 32, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Brazil
+ { 270, 66, 42, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Canary Islands
+ { 270, 66, 47, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Ceuta and Melilla
+ { 270, 66, 49, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Chile
+ { 270, 66, 54, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Colombia
+ { 270, 66, 59, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Costa Rica
+ { 270, 66, 61, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Cuba
+ { 270, 66, 69, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Dominican Republic
+ { 270, 66, 70, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Ecuador
+ { 270, 66, 72, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/El Salvador
+ { 270, 66, 73, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Equatorial Guinea
+ { 270, 66, 99, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Guatemala
+ { 270, 66, 106, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Honduras
+ { 270, 66, 130, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Latin America
+ { 270, 66, 152, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Mexico
+ { 270, 66, 168, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Nicaragua
+ { 270, 66, 181, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Panama
+ { 270, 66, 183, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Paraguay
+ { 270, 66, 184, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Peru
+ { 270, 66, 185, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Philippines
+ { 270, 66, 189, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Puerto Rico
+ { 270, 66, 248, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/United States
+ { 270, 66, 250, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Uruguay
+ { 270, 66, 254, 1002, 1002, 1002, 1002, 153, 153, 83, 83, 83, 83, 26, 26 },// Spanish/Latin/Venezuela
+ { 271, 135, 159, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Standard Moroccan Tamazight/Tifinagh/Morocco
+ { 272, 66, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Sundanese/Latin/Indonesia
+ { 273, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Tanzania
+ { 273, 66, 57, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Congo - Kinshasa
+ { 273, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Kenya
+ { 273, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swahili/Latin/Uganda
+ { 274, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swati/Latin/South Africa
+ { 274, 66, 76, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swati/Latin/Eswatini
+ { 275, 66, 225, 4201, 4284, 4201, 4284, 153, 153, 83, 83, 83, 83, 26, 26 },// Swedish/Latin/Sweden
+ { 275, 66, 2, 4201, 4284, 4201, 4284, 153, 153, 83, 83, 83, 83, 26, 26 },// Swedish/Latin/Aland Islands
+ { 275, 66, 83, 4201, 4284, 4201, 4284, 153, 153, 83, 83, 83, 83, 26, 26 },// Swedish/Latin/Finland
+ { 276, 66, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swiss German/Latin/Switzerland
+ { 276, 66, 84, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swiss German/Latin/France
+ { 276, 66, 136, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Swiss German/Latin/Liechtenstein
+ { 277, 123, 113, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Syriac/Syriac/Iraq
+ { 277, 123, 227, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Syriac/Syriac/Syria
+ { 278, 135, 159, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tachelhit/Tifinagh/Morocco
+ { 278, 66, 159, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tachelhit/Latin/Morocco
+ { 280, 127, 255, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tai Dam/Tai Viet/Vietnam
+ { 281, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Taita/Latin/Kenya
+ { 282, 27, 229, 4367, 4367, 4367, 4367, 153, 153, 80, 80, 80, 80, 26, 26 },// Tajik/Cyrillic/Tajikistan
+ { 283, 129, 110, 4447, 4447, 4540, 4540, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/India
+ { 283, 129, 143, 4447, 4447, 4540, 4540, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/Malaysia
+ { 283, 129, 210, 4447, 4447, 4540, 4540, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/Singapore
+ { 283, 129, 221, 4447, 4447, 4540, 4540, 153, 153, 93, 93, 63, 63, 26, 26 },// Tamil/Tamil/Sri Lanka
+ { 284, 66, 228, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Taroko/Latin/Taiwan
+ { 285, 66, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tasawaq/Latin/Niger
+ { 286, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tatar/Cyrillic/Russia
+ { 287, 131, 110, 4603, 4603, 4603, 4603, 153, 153, 88, 88, 88, 88, 26, 26 },// Telugu/Telugu/India
+ { 288, 66, 243, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Teso/Latin/Uganda
+ { 288, 66, 124, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Teso/Latin/Kenya
+ { 289, 133, 231, 4691, 4691, 4691, 4691, 153, 153, 98, 98, 98, 98, 26, 26 },// Thai/Thai/Thailand
+ { 290, 134, 50, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tibetan/Tibetan/China
+ { 290, 134, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tibetan/Tibetan/India
+ { 291, 33, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tigre/Ethiopic/Eritrea
+ { 292, 33, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tigrinya/Ethiopic/Ethiopia
+ { 292, 33, 74, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tigrinya/Ethiopic/Eritrea
+ { 294, 66, 182, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tok Pisin/Latin/Papua New Guinea
+ { 295, 66, 235, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tongan/Latin/Tonga
+ { 296, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tsonga/Latin/South Africa
+ { 297, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tswana/Latin/South Africa
+ { 297, 66, 30, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tswana/Latin/Botswana
+ { 298, 66, 239, 4789, 4789, 4789, 4789, 153, 153, 80, 80, 80, 80, 26, 26 },// Turkish/Latin/Turkey
+ { 298, 66, 63, 4789, 4789, 4789, 4789, 153, 153, 80, 80, 80, 80, 26, 26 },// Turkish/Latin/Cyprus
+ { 299, 66, 240, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Turkmen/Latin/Turkmenistan
+ { 301, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Tyap/Latin/Nigeria
+ { 303, 27, 244, 4869, 4869, 4949, 4998, 153, 153, 80, 80, 49, 57, 26, 26 },// Ukrainian/Cyrillic/Ukraine
+ { 304, 66, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Upper Sorbian/Latin/Germany
+ { 305, 4, 178, 5055, 5055, 5055, 5055, 153, 153, 66, 66, 66, 66, 26, 26 },// Urdu/Arabic/Pakistan
+ { 305, 4, 110, 5055, 5055, 5055, 5055, 153, 153, 66, 66, 66, 66, 26, 26 },// Urdu/Arabic/India
+ { 306, 4, 50, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uyghur/Arabic/China
+ { 307, 66, 251, 5121, 5204, 5286, 5204, 153, 153, 83, 82, 83, 82, 26, 26 },// Uzbek/Latin/Uzbekistan
+ { 307, 4, 1, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uzbek/Arabic/Afghanistan
+ { 307, 27, 251, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Uzbek/Cyrillic/Uzbekistan
+ { 308, 139, 134, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vai/Vai/Liberia
+ { 308, 66, 134, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vai/Latin/Liberia
+ { 309, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Venda/Latin/South Africa
+ { 310, 66, 255, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vietnamese/Latin/Vietnam
+ { 311, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Volapuk/Latin/world
+ { 312, 66, 230, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Vunjo/Latin/Tanzania
+ { 313, 66, 23, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Walloon/Latin/Belgium
+ { 314, 66, 226, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Walser/Latin/Switzerland
+ { 315, 66, 15, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Warlpiri/Latin/Australia
+ { 316, 66, 246, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Welsh/Latin/United Kingdom
+ { 317, 4, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Balochi/Arabic/Pakistan
+ { 317, 4, 1, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Balochi/Arabic/Afghanistan
+ { 317, 4, 112, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Balochi/Arabic/Iran
+ { 317, 4, 176, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Balochi/Arabic/Oman
+ { 317, 4, 245, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Balochi/Arabic/United Arab Emirates
+ { 318, 66, 165, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Western Frisian/Latin/Netherlands
+ { 319, 33, 77, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Wolaytta/Ethiopic/Ethiopia
+ { 320, 66, 206, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Wolof/Latin/Senegal
+ { 321, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Xhosa/Latin/South Africa
+ { 322, 66, 40, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yangben/Latin/Cameroon
+ { 323, 47, 244, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yiddish/Hebrew/Ukraine
+ { 324, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yoruba/Latin/Nigeria
+ { 324, 66, 25, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Yoruba/Latin/Benin
+ { 325, 66, 170, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Zarma/Latin/Niger
+ { 326, 66, 50, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Zhuang/Latin/China
+ { 327, 66, 216, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Zulu/Latin/South Africa
+ { 328, 66, 32, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kaingang/Latin/Brazil
+ { 329, 66, 32, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nheengatu/Latin/Brazil
+ { 329, 66, 54, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nheengatu/Latin/Colombia
+ { 329, 66, 254, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Nheengatu/Latin/Venezuela
+ { 330, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Haryanvi/Devanagari/India
+ { 331, 66, 91, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Northern Frisian/Latin/Germany
+ { 332, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rajasthani/Devanagari/India
+ { 333, 27, 193, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Moksha/Cyrillic/Russia
+ { 334, 66, 258, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Toki Pona/Latin/world
+ { 335, 66, 214, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Pijin/Latin/Solomon Islands
+ { 336, 66, 169, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Obolo/Latin/Nigeria
+ { 337, 4, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Baluchi/Arabic/Pakistan
+ { 337, 66, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Baluchi/Latin/Pakistan
+ { 338, 66, 117, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Ligurian/Latin/Italy
+ { 339, 142, 161, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rohingya/Hanifi/Myanmar
+ { 339, 142, 20, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Rohingya/Hanifi/Bangladesh
+ { 340, 4, 178, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Torwali/Arabic/Pakistan
+ { 341, 66, 25, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Anii/Latin/Benin
+ { 342, 29, 110, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Kangri/Devanagari/India
+ { 343, 66, 117, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Venetian/Latin/Italy
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },// trailing zeros
};
-static const char16_t months_data[] = {
-0x46, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x68,
-0x74, 0x3b, 0x4b, 0x68, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x61, 0x64,
-0x3b, 0x53, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e,
-0x3b, 0x41, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66,
-0x61, 0x6e, 0x64, 0x46, 0x61, 0x72, 0x3b, 0x4f, 0x72, 0x64, 0x3b, 0x4b, 0x68, 0x6f, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d,
-0x6f, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4d, 0x65, 0x68, 0x3b, 0x41, 0x62, 0x61, 0x3b, 0x41, 0x7a, 0x61, 0x3b, 0x44,
-0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x3b, 0x45, 0x73, 0x66, 0x46, 0x3b, 0x4f, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b,
-0x53, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x45, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34,
-0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x641,
-0x631, 0x641, 0x631, 0x62f, 0x646, 0x3b, 0x623, 0x630, 0x631, 0x628, 0x64a, 0x647, 0x634, 0x62a, 0x3b, 0x62e, 0x631, 0x62f, 0x627, 0x62f,
-0x3b, 0x62a, 0x627, 0x631, 0x3b, 0x645, 0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x634, 0x647, 0x631, 0x641, 0x627, 0x631, 0x3b, 0x645, 0x647,
-0x631, 0x3b, 0x622, 0x64a, 0x627, 0x646, 0x3b, 0x622, 0x630, 0x631, 0x3b, 0x62f, 0x64a, 0x3b, 0x628, 0x647, 0x645, 0x646, 0x3b, 0x627,
-0x633, 0x641, 0x646, 0x62f, 0x627, 0x631, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9ad, 0x9be, 0x9b0, 0x9cd, 0x9a1, 0x9bf, 0x9a8, 0x3b, 0x985, 0x9b0,
-0x9a1, 0x9bf, 0x9ac, 0x9c7, 0x9b9, 0x9c7, 0x9b6, 0x9cd, 0x9a4, 0x3b, 0x996, 0x9cb, 0x9b0, 0x9cd, 0x9a6, 0x9cd, 0x9a6, 0x3b, 0x9a4, 0x9c0,
-0x9b0, 0x3b, 0x9ae, 0x9b0, 0x9cd, 0x9af, 0x9be, 0x9a6, 0x3b, 0x9b6, 0x9be, 0x9b9, 0x9b0, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x9c7,
-0x9b9, 0x9c7, 0x9b0, 0x3b, 0x986, 0x9ac, 0x9be, 0x9a8, 0x3b, 0x9ac, 0x9be, 0x99c, 0x9be, 0x9b0, 0x3b, 0x9a6, 0x9c7, 0x3b, 0x9ac, 0x9be,
-0x9b9, 0x9ae, 0x9be, 0x9a8, 0x3b, 0x98f, 0x9b8, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9a8, 0x9cd, 0x9a1, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9ad, 0x9be,
-0x9b0, 0x9cd, 0x9a1, 0x9bf, 0x9a8, 0x3b, 0x985, 0x9b0, 0x9a1, 0x9bf, 0x9ac, 0x9c7, 0x9b9, 0x9c7, 0x9b6, 0x9cd, 0x9a4, 0x3b, 0x996, 0x9cb,
-0x9b0, 0x9cd, 0x9a6, 0x9cd, 0x9a6, 0x3b, 0x9a4, 0x9c0, 0x9b0, 0x3b, 0x9ae, 0x9b0, 0x9cd, 0x9af, 0x9be, 0x9a6, 0x3b, 0x9b6, 0x9be, 0x9b9,
-0x9b0, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x9c7, 0x9b9, 0x9c7, 0x9b0, 0x3b, 0x986, 0x9ac, 0x9be, 0x9a8, 0x3b, 0x986, 0x99c, 0x9be,
-0x9b0, 0x3b, 0x9a6, 0x9c7, 0x3b, 0x9ac, 0x9be, 0x9b9, 0x9ae, 0x9be, 0x9a8, 0x3b, 0x98f, 0x9b8, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9a8, 0x9cd,
-0x9a1, 0x9e7, 0x3b, 0x9e8, 0x3b, 0x9e9, 0x3b, 0x9ea, 0x3b, 0x9eb, 0x3b, 0x9ec, 0x3b, 0x9ed, 0x3b, 0x9ee, 0x3b, 0x9ef, 0x3b, 0x9e7,
-0x9e6, 0x3b, 0x9e7, 0x9e7, 0x3b, 0x9e7, 0x9e8, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b, 0x4e09, 0x6708, 0x3b, 0x56db, 0x6708, 0x3b, 0x4e94,
-0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b, 0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b, 0x5341, 0x4e00, 0x6708,
-0x3b, 0x5341, 0x4e8c, 0x6708, 0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36,
-0x6708, 0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31,
-0x32, 0x6708, 0x31, 0x2e, 0x3b, 0x32, 0x2e, 0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e, 0x3b,
-0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30, 0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e,
-0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74,
-0x3b, 0x63, 0x68, 0x6f, 0x72, 0x64, 0xe1, 0x64, 0x3b, 0x74, 0xed, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0xe1, 0x64, 0x3b,
-0x161, 0x61, 0x68, 0x72, 0xed, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0xe1, 0x62, 0xe1, 0x6e, 0x3b, 0xe1,
-0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x69, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e,
-0x64, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73,
-0x68, 0x74, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x61,
-0x64, 0x3b, 0x73, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0x61, 0x62, 0x61,
-0x6e, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65, 0x73,
-0x66, 0x61, 0x6e, 0x64, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x6b, 0x75, 0x75, 0x3b, 0x6f, 0x72, 0x64,
-0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x6b, 0x75, 0x75, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x6b, 0x75,
-0x75, 0x3b, 0x74, 0x69, 0x72, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x6b, 0x75, 0x75, 0x3b, 0x161,
-0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x6b, 0x75, 0x75, 0x3b, 0x61,
-0x62, 0x61, 0x6e, 0x6b, 0x75, 0x75, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x6b, 0x75, 0x75, 0x3b, 0x64, 0x65, 0x79, 0x6b, 0x75,
-0x75, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x6b, 0x75,
-0x75, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6f, 0x72, 0x64, 0x69,
-0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x6b,
-0x75, 0x75, 0x74, 0x61, 0x3b, 0x74, 0x69, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x61, 0x64,
-0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x161, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b,
-0x6d, 0x65, 0x68, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x61, 0x62, 0x61, 0x6e, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b,
-0x61, 0x7a, 0x61, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x64, 0x65, 0x79, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x62,
-0x61, 0x68, 0x6d, 0x61, 0x6e, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x6b, 0x75, 0x75,
-0x74, 0x61, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65,
-0x161, 0x74, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x61,
-0x64, 0x3b, 0x161, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0x61, 0x62, 0x61, 0x6e,
-0x3b, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65, 0x73, 0x66,
-0x61, 0x6e, 0x64, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68,
-0x65, 0x161, 0x74, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0xe2, 0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64,
-0xe2, 0x64, 0x3b, 0x161, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0xe2, 0x62, 0xe2,
-0x6e, 0x3b, 0xe2, 0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65, 0x73,
-0x66, 0x61, 0x6e, 0x64, 0x66, 0x61, 0x72, 0x2e, 0x3b, 0x6f, 0x72, 0x64, 0x2e, 0x3b, 0x6b, 0x68, 0x6f, 0x2e, 0x3b, 0x74,
-0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x2e, 0x3b, 0x161, 0x61, 0x68, 0x2e, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0xe2, 0x62,
-0xe2, 0x6e, 0x3b, 0xe2, 0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x2e, 0x3b, 0x65, 0x73, 0x66,
-0x2e, 0x46, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161,
-0x74, 0x3b, 0x4b, 0x68, 0x6f, 0x72, 0x64, 0xe2, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0xe2, 0x64,
-0x3b, 0x160, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0xc2, 0x62, 0xe2, 0x6e, 0x3b,
-0xc2, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61,
-0x6e, 0x64, 0x46, 0x61, 0x72, 0x2e, 0x3b, 0x4f, 0x72, 0x64, 0x2e, 0x3b, 0x4b, 0x68, 0x6f, 0x2e, 0x3b, 0x54, 0x69, 0x72,
-0x3b, 0x4d, 0x6f, 0x72, 0x2e, 0x3b, 0x160, 0x61, 0x68, 0x2e, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0xc2, 0x62, 0xe2, 0x2e,
-0x3b, 0xc2, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x2e, 0x3b, 0x45, 0x73, 0x66, 0x2e, 0x10e4,
-0x10d0, 0x10e0, 0x10d5, 0x10d0, 0x10e0, 0x10d3, 0x10d8, 0x10dc, 0x10d8, 0x3b, 0x10dd, 0x10e0, 0x10d3, 0x10d8, 0x10d1, 0x10d4, 0x10f0, 0x10d4, 0x10e8, 0x10d7,
-0x10d8, 0x3b, 0x10ee, 0x10dd, 0x10e0, 0x10d3, 0x10d0, 0x10d3, 0x10d8, 0x3b, 0x10d7, 0x10d8, 0x10e0, 0x10d8, 0x3b, 0x10db, 0x10dd, 0x10e0, 0x10d3, 0x10d0,
-0x10d3, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10f0, 0x10e0, 0x10d8, 0x10d5, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10db, 0x10d4, 0x10f0, 0x10e0, 0x10d8, 0x3b, 0x10d0,
-0x10d1, 0x10d0, 0x10dc, 0x10d8, 0x3b, 0x10d0, 0x10d6, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d8, 0x3b, 0x10d1, 0x10d0, 0x10f0, 0x10db, 0x10d0,
-0x10dc, 0x10d8, 0x3b, 0x10d4, 0x10e1, 0x10e4, 0x10d0, 0x10dc, 0x10d3, 0x10d8, 0x46, 0x61, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b,
-0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x63, 0x68, 0x74, 0x3b, 0x43, 0x68, 0x6f, 0x72, 0x64, 0x101, 0x64,
-0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x53, 0x63, 0x68, 0x61, 0x68, 0x72, 0x69, 0x77,
-0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x100, 0x62, 0x101, 0x6e, 0x3b, 0x100, 0x73, 0x61, 0x72, 0x3b, 0x44, 0xe9,
-0x69, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x73, 0x66, 0x61, 0x6e, 0x64, 0xaab, 0xabe, 0xab0, 0xacd,
-0xab5, 0xabe, 0xab0, 0xacd, 0xaa6, 0xabf, 0xaa8, 0x3b, 0xa93, 0xab0, 0xaa1, 0xac0, 0xaac, 0xac7, 0xab9, 0xac7, 0xab6, 0xacd, 0xa9f, 0x3b,
-0xa96, 0xacb, 0xab0, 0xaa6, 0xabe, 0xaa6, 0x3b, 0xaa4, 0xabf, 0xab0, 0x3b, 0xaae, 0xacb, 0xab0, 0xacd, 0xaa6, 0xabe, 0xaa6, 0x3b, 0xab6,
-0xabe, 0xab9, 0xab0, 0xabf, 0xab5, 0xab0, 0x3b, 0xaae, 0xac7, 0xab9, 0xab0, 0x3b, 0xa85, 0xaac, 0xabe, 0xaa8, 0x3b, 0xa85, 0xa9d, 0xabe,
-0xab0, 0x3b, 0xaa1, 0xac7, 0xaaf, 0x3b, 0xaac, 0xabe, 0xab9, 0xaae, 0xac7, 0xaa8, 0x3b, 0xa8f, 0xab8, 0xacd, 0xaab, 0xabe, 0xaa8, 0xacd,
-0xaa1, 0x5e4, 0x5e8, 0x5d5, 0x5e8, 0x5d3, 0x5d9, 0x5df, 0x3b, 0x5d0, 0x5e8, 0x5d3, 0x5d9, 0x5d1, 0x5d4, 0x5e9, 0x5ea, 0x3b, 0x5d7, 0x5f3,
-0x5e8, 0x5d3, 0x5d0, 0x5d3, 0x3b, 0x5ea, 0x5d9, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5d3, 0x5d0, 0x5d3, 0x3b, 0x5e9, 0x5d4, 0x5e8, 0x5d9, 0x5d5,
-0x5e8, 0x3b, 0x5de, 0x5d4, 0x5e8, 0x3b, 0x5d0, 0x5d1, 0x5d0, 0x5df, 0x3b, 0x5d0, 0x5d3, 0x5f3, 0x5e8, 0x3b, 0x5d3, 0x5d9, 0x3b, 0x5d1,
-0x5d4, 0x5de, 0x5df, 0x3b, 0x5d0, 0x5e1, 0x5e4, 0x5e0, 0x5d3, 0x92b, 0x930, 0x94d, 0x935, 0x93e, 0x926, 0x93f, 0x928, 0x3b, 0x913, 0x930,
-0x94d, 0x926, 0x93f, 0x935, 0x947, 0x939, 0x947, 0x938, 0x94d, 0x91f, 0x3b, 0x916, 0x94b, 0x930, 0x930, 0x94d, 0x926, 0x93e, 0x926, 0x3b,
-0x91f, 0x93f, 0x930, 0x3b, 0x92e, 0x94b, 0x930, 0x926, 0x93e, 0x926, 0x3b, 0x936, 0x93e, 0x939, 0x930, 0x940, 0x935, 0x930, 0x94d, 0x3b,
-0x92e, 0x947, 0x939, 0x930, 0x3b, 0x905, 0x935, 0x928, 0x3b, 0x905, 0x91c, 0x93c, 0x930, 0x3b, 0x921, 0x947, 0x3b, 0x92c, 0x939, 0x92e,
-0x928, 0x3b, 0x908, 0x938, 0x94d, 0x92b, 0x928, 0x94d, 0x926, 0x94d, 0x30d5, 0x30a1, 0x30eb, 0x30f4, 0x30a1, 0x30eb, 0x30c7, 0x30a3, 0x30fc, 0x30f3,
-0x3b, 0x30aa, 0x30eb, 0x30c7, 0x30a3, 0x30fc, 0x30d9, 0x30d8, 0x30b7, 0x30e5, 0x30c8, 0x3b, 0x30db, 0x30eb, 0x30c0, 0x30fc, 0x30c9, 0x3b, 0x30c6, 0x30a3,
-0x30fc, 0x30eb, 0x3b, 0x30e2, 0x30eb, 0x30c0, 0x30fc, 0x30c9, 0x3b, 0x30b7, 0x30e3, 0x30cf, 0x30ea, 0x30fc, 0x30f4, 0x30a1, 0x30eb, 0x3b, 0x30e1, 0x30d5,
-0x30eb, 0x3b, 0x30a2, 0x30fc, 0x30d0, 0x30fc, 0x30f3, 0x3b, 0x30a2, 0x30fc, 0x30b6, 0x30eb, 0x3b, 0x30c7, 0x30a4, 0x3b, 0x30d0, 0x30d5, 0x30de, 0x30f3,
-0x3b, 0x30a8, 0x30b9, 0x30d5, 0x30a1, 0x30f3, 0x30c9, 0xcab, 0xcb0, 0xccd, 0xcb5, 0xcb0, 0xccd, 0xca6, 0xcbf, 0xca8, 0xccd, 0x3b, 0xc93, 0xcb0,
-0xccd, 0xca6, 0xcbf, 0xcac, 0xcc6, 0xcb9, 0xcc6, 0xcb6, 0xccd, 0xc9f, 0xccd, 0x3b, 0xc96, 0xccb, 0xcb0, 0xccd, 0xca1, 0xcbe, 0xca6, 0xccd,
-0x3b, 0xc9f, 0xcbf, 0xcb0, 0xccd, 0x3b, 0xcae, 0xcca, 0xcb0, 0xccd, 0xca6, 0xcbe, 0xca6, 0xccd, 0x3b, 0xcb6, 0xcb9, 0xcb0, 0xcbf, 0xcb5,
-0xcbe, 0xcb0, 0xccd, 0x3b, 0xcae, 0xcc6, 0xcb9, 0xccd, 0xcb0, 0xccd, 0x3b, 0xc85, 0xcac, 0xca8, 0xccd, 0x3b, 0xc85, 0xc9d, 0xcb0, 0xccd,
-0x3b, 0xca1, 0xcc7, 0x3b, 0xcac, 0xcb9, 0xccd, 0xcae, 0xca8, 0xccd, 0x3b, 0xc8e, 0xcb8, 0xccd, 0xcab, 0xcbe, 0xc82, 0xca1, 0xccd, 0xd654,
-0xb974, 0xbc14, 0xb518, 0x3b, 0xc624, 0xb974, 0xb514, 0xbca0, 0xd5e4, 0xc26c, 0xd2b8, 0x3b, 0xd638, 0xb974, 0xb2e4, 0xb4dc, 0x3b, 0xd2f0, 0xb974, 0x3b,
-0xbaa8, 0xb974, 0xb2e4, 0xb4dc, 0x3b, 0xc0e4, 0xd750, 0xb9ac, 0xbc14, 0xb974, 0x3b, 0xba54, 0xd750, 0xb974, 0x3b, 0xc544, 0xbc18, 0x3b, 0xc544, 0xc790,
-0xb974, 0x3b, 0xb2e4, 0xc774, 0x3b, 0xbc14, 0xd750, 0xb9cc, 0x3b, 0xc5d0, 0xc2a4, 0xd310, 0xb4dc, 0xe9f, 0xea3, 0xeb2, 0xea7, 0xeb2, 0xe94, 0xeb4,
-0xe99, 0x3b, 0xead, 0xecd, 0xea3, 0xe94, 0xeb5, 0xe9a, 0xeb5, 0xec0, 0xeab, 0xea3, 0xe94, 0x3b, 0xe84, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94,
-0x3b, 0xec1, 0xe95, 0xea3, 0x3b, 0xea1, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xe8a, 0xeb2, 0xea3, 0xeab, 0xeb4, 0xea7, 0xeb2, 0x3b,
-0xec0, 0xea1, 0xeb5, 0x3b, 0xead, 0xeb2, 0xe9a, 0xeb2, 0xe99, 0x3b, 0xead, 0xeb2, 0xe8a, 0xeb2, 0xea3, 0x3b, 0xe94, 0xeb5, 0xea3, 0x3b,
-0xe9a, 0xea3, 0xeb2, 0xec1, 0xea1, 0xe99, 0x3b, 0xec0, 0xead, 0xeaa, 0xe9f, 0xeb2, 0xe99, 0xe9f, 0xea3, 0xeb2, 0xea7, 0xeb2, 0xe94, 0xeb4,
-0xe99, 0x3b, 0xead, 0xecd, 0xea3, 0xe94, 0xeb5, 0xe9a, 0xeb5, 0xec0, 0xeab, 0xeae, 0xe94, 0x3b, 0xe84, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94,
-0x3b, 0xec1, 0xe95, 0xea3, 0x3b, 0xea1, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xe8a, 0xeb2, 0xea3, 0xea5, 0xeb4, 0xea7, 0xeb2, 0x3b,
-0xec0, 0xea1, 0xeb5, 0x3b, 0xead, 0xeb2, 0xe9a, 0xeb2, 0xe99, 0x3b, 0xead, 0xeb2, 0xe8a, 0xeb2, 0x3b, 0xe94, 0xeb5, 0xea3, 0x3b, 0xe9a,
-0xea3, 0xeb2, 0xea1, 0xeb2, 0xe99, 0x3b, 0xec0, 0xead, 0xeaa, 0xe9f, 0xeb2, 0xe99, 0xe9f, 0xeb2, 0xea3, 0xea7, 0xeb2, 0xe94, 0xeb4, 0xe99,
-0x3b, 0xead, 0xecd, 0xea3, 0xe94, 0xeb5, 0xe9a, 0xeb5, 0xec0, 0xeab, 0xea3, 0xe94, 0x3b, 0xe84, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b,
-0xec1, 0xe95, 0xea3, 0x3b, 0xea1, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xe8a, 0xeb2, 0xea3, 0xeab, 0xeb4, 0xea7, 0xeb2, 0x3b, 0xec0,
-0xea1, 0xeb5, 0x3b, 0xead, 0xeb2, 0xe9a, 0xeb2, 0xe99, 0x3b, 0xead, 0xeb2, 0xe8a, 0xeb2, 0x3b, 0xe94, 0xeb5, 0xea3, 0x3b, 0xe9a, 0xea3,
-0xeb2, 0xea1, 0xeb2, 0xe99, 0x3b, 0xec0, 0xead, 0xeaa, 0xe9f, 0xeb2, 0xe99, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x12b, 0x6e,
-0x73, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x73, 0x3b, 0x68, 0x6f, 0x72, 0x64, 0x101, 0x64,
-0x73, 0x3b, 0x74, 0x12b, 0x72, 0x73, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x73, 0x3b, 0x161, 0x61, 0x68, 0x72, 0x69,
-0x76, 0x113, 0x72, 0x73, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x73, 0x3b, 0x61, 0x62, 0x61, 0x6e, 0x73, 0x3b, 0x61, 0x7a, 0x65,
-0x72, 0x73, 0x3b, 0x64, 0x65, 0x6a, 0x73, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x73, 0x3b, 0x65, 0x73, 0x66, 0x61,
-0x6e, 0x64, 0x73, 0x444, 0x430, 0x440, 0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x43e, 0x440, 0x434, 0x438, 0x431, 0x435, 0x445,
-0x435, 0x448, 0x442, 0x3b, 0x43a, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x442, 0x438, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x434, 0x430,
-0x434, 0x3b, 0x448, 0x430, 0x445, 0x440, 0x438, 0x432, 0x430, 0x440, 0x3b, 0x43c, 0x435, 0x440, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b,
-0x430, 0x437, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x458, 0x3b, 0x431, 0x430, 0x445, 0x43c, 0x430, 0x43d, 0x3b, 0x435, 0x441, 0x444, 0x430,
-0x43d, 0x434, 0xd2b, 0xd7c, 0xd35, 0xd3e, 0xd7c, 0xd26, 0xd3f, 0xd7b, 0x3b, 0xd13, 0xd7c, 0xd21, 0xd3f, 0xd2c, 0xd46, 0xd39, 0xd46, 0xd37,
-0xd4d, 0x200c, 0xd31, 0xd4d, 0xd31, 0xd4d, 0x3b, 0xd16, 0xd4b, 0xd7c, 0xd26, 0xd3e, 0xd26, 0xd4d, 0x3b, 0xd1f, 0xd3f, 0xd7c, 0x3b, 0xd2e,
-0xd4b, 0xd7c, 0xd26, 0xd3e, 0xd26, 0xd4d, 0x3b, 0xd37, 0xd39, 0xd4d, 0x200c, 0xd30, 0xd3f, 0xd35, 0xd3e, 0xd7c, 0x3b, 0xd2e, 0xd46, 0xd39,
-0xd7c, 0x3b, 0xd05, 0xd2c, 0xd3e, 0xd7b, 0x3b, 0xd05, 0xd38, 0xd7c, 0x3b, 0xd21, 0xd46, 0xd2f, 0xd4d, 0x3b, 0xd2c, 0xd39, 0xd4d, 0x200c,
-0xd2e, 0xd3e, 0xd7b, 0x3b, 0xd0e, 0xd38, 0xd4d, 0x200c, 0xd2b, 0xd3e, 0xd7b, 0xd21, 0xd4d, 0xd2b, 0x2e, 0x3b, 0xd13, 0x2e, 0x3b, 0xd16,
-0xd4b, 0x3b, 0xd1f, 0xd3f, 0x2e, 0x3b, 0xd2e, 0xd4b, 0x2e, 0x3b, 0xd37, 0x2e, 0x3b, 0xd2e, 0xd46, 0x2e, 0x3b, 0xd05, 0x2e, 0x3b,
-0xd05, 0x2e, 0x3b, 0xd21, 0xd46, 0x2e, 0x3b, 0xd2c, 0x2e, 0x3b, 0xd0e, 0x2e, 0x92b, 0x930, 0x935, 0x930, 0x926, 0x93f, 0x928, 0x3b,
-0x913, 0x930, 0x94d, 0x926, 0x93f, 0x92c, 0x947, 0x939, 0x947, 0x936, 0x94d, 0x924, 0x3b, 0x916, 0x94b, 0x930, 0x926, 0x93e, 0x926, 0x3b,
-0x924, 0x93f, 0x930, 0x3b, 0x92e, 0x94b, 0x930, 0x926, 0x93e, 0x926, 0x3b, 0x936, 0x93e, 0x939, 0x930, 0x940, 0x935, 0x93e, 0x930, 0x3b,
-0x92e, 0x947, 0x939, 0x947, 0x930, 0x3b, 0x905, 0x92c, 0x93e, 0x928, 0x3b, 0x905, 0x91d, 0x93e, 0x930, 0x3b, 0x926, 0x947, 0x3b, 0x92c,
-0x93e, 0x939, 0x92e, 0x93e, 0x928, 0x3b, 0x90f, 0x938, 0x92b, 0x93e, 0x902, 0x926, 0x967, 0x3b, 0x968, 0x3b, 0x969, 0x3b, 0x96a, 0x3b,
-0x96b, 0x3b, 0x96c, 0x3b, 0x96d, 0x3b, 0x96e, 0x3b, 0x96f, 0x3b, 0x967, 0x966, 0x3b, 0x967, 0x967, 0x3b, 0x967, 0x968, 0x648, 0x631,
-0x6cc, 0x3b, 0x63a, 0x648, 0x6cc, 0x6cc, 0x3b, 0x63a, 0x628, 0x631, 0x6af, 0x648, 0x644, 0x6cc, 0x3b, 0x686, 0x646, 0x6af, 0x627, 0x69a,
-0x3b, 0x632, 0x645, 0x631, 0x6cc, 0x3b, 0x648, 0x696, 0x6cc, 0x3b, 0x62a, 0x644, 0x647, 0x3b, 0x644, 0x693, 0x645, 0x3b, 0x644, 0x6cc,
-0x646, 0x62f, 0x6cd, 0x3b, 0x645, 0x631, 0x63a, 0x648, 0x645, 0x6cc, 0x3b, 0x633, 0x644, 0x648, 0x627, 0x63a, 0x647, 0x3b, 0x6a9, 0x628,
-0x6f1, 0x3b, 0x6f2, 0x3b, 0x6f3, 0x3b, 0x6f4, 0x3b, 0x6f5, 0x3b, 0x6f6, 0x3b, 0x6f7, 0x3b, 0x6f8, 0x3b, 0x6f9, 0x3b, 0x6f1, 0x6f0,
-0x3b, 0x6f1, 0x6f1, 0x3b, 0x6f1, 0x6f2, 0x641, 0x631, 0x648, 0x631, 0x62f, 0x6cc, 0x646, 0x3b, 0x627, 0x631, 0x62f, 0x6cc, 0x628, 0x647,
-0x634, 0x62a, 0x3b, 0x62e, 0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x62a, 0x6cc, 0x631, 0x3b, 0x645, 0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x634,
-0x647, 0x631, 0x6cc, 0x648, 0x631, 0x3b, 0x645, 0x647, 0x631, 0x3b, 0x622, 0x628, 0x627, 0x646, 0x3b, 0x622, 0x630, 0x631, 0x3b, 0x62f,
-0x6cc, 0x3b, 0x628, 0x647, 0x645, 0x646, 0x3b, 0x627, 0x633, 0x641, 0x646, 0x62f, 0x641, 0x3b, 0x627, 0x3b, 0x62e, 0x3b, 0x62a, 0x3b,
-0x645, 0x3b, 0x634, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x622, 0x3b, 0x62f, 0x3b, 0x628, 0x3b, 0x627, 0x62d, 0x645, 0x644, 0x3b, 0x62b,
-0x648, 0x631, 0x3b, 0x62c, 0x648, 0x632, 0x627, 0x3b, 0x633, 0x631, 0x637, 0x627, 0x646, 0x3b, 0x627, 0x633, 0x62f, 0x3b, 0x633, 0x646,
-0x628, 0x644, 0x647, 0x654, 0x3b, 0x645, 0x6cc, 0x632, 0x627, 0x646, 0x3b, 0x639, 0x642, 0x631, 0x628, 0x3b, 0x642, 0x648, 0x633, 0x3b,
-0x62c, 0x62f, 0x6cc, 0x3b, 0x62f, 0x644, 0x648, 0x3b, 0x62d, 0x648, 0x62a, 0x62d, 0x3b, 0x62b, 0x3b, 0x62c, 0x3b, 0x633, 0x3b, 0x627,
-0x3b, 0x633, 0x3b, 0x645, 0x3b, 0x639, 0x3b, 0x642, 0x3b, 0x62c, 0x3b, 0x62f, 0x3b, 0x62d, 0x46, 0x61, 0x72, 0x77, 0x61, 0x72,
-0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x7a, 0x74, 0x3b, 0x43, 0x68, 0x6f, 0x72,
-0x64, 0x101, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x53, 0x7a, 0x61, 0x68, 0x72,
-0x69, 0x77, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x100, 0x62, 0x101, 0x6e, 0x3b, 0x100, 0x73, 0x61, 0x72, 0x3b,
-0x44, 0xe9, 0x69, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64, 0xa2b, 0xa3e, 0xa30,
-0xa35, 0xa30, 0xa21, 0xa40, 0xa28, 0x3b, 0xa14, 0xa30, 0xa21, 0xa3e, 0xa08, 0xa2c, 0xa39, 0xa48, 0xa38, 0xa3c, 0xa1f, 0x3b, 0xa16, 0xa4b,
-0xa21, 0xa30, 0xa21, 0x3b, 0xa1f, 0xa3f, 0xa30, 0x3b, 0xa2e, 0xa4b, 0xa30, 0xa21, 0xa3e, 0xa26, 0x3b, 0xa38, 0xa3c, 0xa30, 0xa3e, 0xa07,
-0xa35, 0xa30, 0x3b, 0xa2e, 0xa47, 0xa39, 0xa30, 0x3b, 0xa05, 0xa2c, 0xa3e, 0xa28, 0x3b, 0xa05, 0xa1c, 0xa3c, 0xa3e, 0xa30, 0x3b, 0xa21,
-0xa47, 0xa05, 0x3b, 0xa2c, 0xa3e, 0xa39, 0xa2e, 0xa28, 0x3b, 0xa10, 0xa38, 0xa2b, 0xa70, 0xa21, 0x46, 0x61, 0x72, 0x76, 0x61, 0x72,
-0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x68, 0x74, 0x3b, 0x4b, 0x68, 0x6f, 0x72,
-0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x41, 0x2d, 0x4d, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x53, 0x68, 0x61,
-0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e, 0x3b, 0x41, 0x7a, 0x61,
-0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x444,
-0x430, 0x440, 0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x43e, 0x440, 0x434, 0x438, 0x431, 0x435, 0x445, 0x435, 0x448, 0x442, 0x3b,
-0x445, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x442, 0x438, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x448, 0x430,
-0x445, 0x440, 0x438, 0x432, 0x435, 0x440, 0x3b, 0x43c, 0x435, 0x445, 0x440, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x435,
-0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x43c, 0x430, 0x43d, 0x3b, 0x44d, 0x441, 0x444, 0x430, 0x43d, 0x434, 0x424,
-0x430, 0x440, 0x430, 0x432, 0x430, 0x434, 0x438, 0x43d, 0x3b, 0x41e, 0x440, 0x434, 0x438, 0x431, 0x435, 0x445, 0x435, 0x448, 0x442, 0x3b,
-0x41a, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x422, 0x438, 0x440, 0x3b, 0x41c, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x428, 0x430,
-0x445, 0x440, 0x438, 0x432, 0x430, 0x440, 0x3b, 0x41c, 0x435, 0x445, 0x440, 0x3b, 0x410, 0x431, 0x430, 0x43d, 0x3b, 0x410, 0x437, 0x430,
-0x440, 0x3b, 0x414, 0x435, 0x458, 0x3b, 0x411, 0x430, 0x445, 0x43c, 0x430, 0x43d, 0x3b, 0x415, 0x441, 0x444, 0x430, 0x43d, 0x434, 0x46,
-0x61, 0x72, 0x61, 0x76, 0x61, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x3b,
-0x4b, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x160, 0x61,
-0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e, 0x3b, 0x41, 0x7a, 0x61,
-0x72, 0x3b, 0x44, 0x65, 0x6a, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x46,
-0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x68, 0x74,
-0x3b, 0x4b, 0x68, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b,
-0x53, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x100, 0x62, 0x101, 0x6e, 0x3b,
-0x100, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61,
-0x6e, 0x64, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65,
-0x73, 0x68, 0x74, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64,
-0x101, 0x64, 0x3b, 0x73, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0x101, 0x62,
-0x101, 0x6e, 0x3b, 0x101, 0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65,
-0x73, 0x66, 0x61, 0x6e, 0x64, 0x444, 0x430, 0x440, 0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x443, 0x440, 0x434, 0x438, 0x431,
-0x438, 0x4b3, 0x438, 0x448, 0x442, 0x3b, 0x445, 0x443, 0x440, 0x434, 0x43e, 0x434, 0x3b, 0x442, 0x438, 0x440, 0x3b, 0x43c, 0x443, 0x440,
-0x434, 0x43e, 0x434, 0x3b, 0x448, 0x430, 0x4b3, 0x440, 0x438, 0x432, 0x430, 0x440, 0x3b, 0x43c, 0x435, 0x4b3, 0x440, 0x3b, 0x43e, 0x431,
-0x43e, 0x43d, 0x3b, 0x43e, 0x437, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x4b3, 0x43c, 0x430, 0x43d, 0x3b, 0x438,
-0x441, 0x444, 0x430, 0x43d, 0x434, 0xb83, 0xbaa, 0xbb0, 0xbcd, 0xbb5, 0xbbe, 0xba4, 0xbbf, 0xba9, 0xbcd, 0x3b, 0xb86, 0xbb0, 0xbcd, 0xb9f,
-0xbbf, 0xbaa, 0xbc6, 0xbb9, 0xbc6, 0xbb7, 0xbcd, 0xba4, 0xbcd, 0x3b, 0xb95, 0xbca, 0xbb0, 0xbcd, 0xba4, 0xbbe, 0xba4, 0xbcd, 0x3b, 0xba4,
-0xbbf, 0xbb0, 0xbcd, 0x3b, 0xbae, 0xbca, 0xbb0, 0xbcd, 0xba4, 0xbbe, 0xba4, 0xbcd, 0x3b, 0xbb7, 0xbbe, 0xbb0, 0xbbf, 0xbb5, 0xbbe, 0xbb0,
-0xbcd, 0x3b, 0xbae, 0xbc6, 0xbb9, 0xbcd, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xbaa, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xb85, 0xb9a, 0xbbe, 0xbb0, 0xbcd,
-0x3b, 0xba4, 0xbc7, 0x3b, 0xbaa, 0xbb9, 0xbcd, 0xbae, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xb8e, 0xb83, 0xbaa, 0xbbe, 0xba9, 0xbcd, 0xb83, 0xbaa,
-0xbb0, 0xbcd, 0x2e, 0x3b, 0xb86, 0xbb0, 0xbcd, 0xb9f, 0xbbf, 0x2e, 0x3b, 0xb95, 0xbca, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xba4, 0xbbf, 0xbb0,
-0xbcd, 0x3b, 0xbae, 0xbca, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xbb7, 0xbbe, 0xbb0, 0xbbf, 0x2e, 0x3b, 0xbae, 0xbc6, 0xbb9, 0xbcd, 0x2e, 0x3b,
-0xb85, 0xbaa, 0xbbe, 0x2e, 0x3b, 0xb85, 0xb9a, 0xbbe, 0x2e, 0x3b, 0xba4, 0xbc7, 0x3b, 0xbaa, 0xbb9, 0xbcd, 0x2e, 0x3b, 0xb8e, 0xb83,
-0x2e, 0xc2b, 0xc3e, 0xc35, 0xc30, 0xc4d, 0xc21, 0xc3f, 0xc28, 0xc4d, 0x3b, 0xc0a, 0xc21, 0xc3e, 0xc2c, 0xc39, 0xc37, 0xc4d, 0xc1f, 0xc4d,
-0x3b, 0xc16, 0xc4b, 0xc30, 0xc4d, 0xc21, 0xc3e, 0xc21, 0xc4d, 0x3b, 0xc1f, 0xc3f, 0xc30, 0xc4d, 0x3b, 0xc2e, 0xc46, 0xc30, 0xc4d, 0xc21,
-0xc3e, 0xc21, 0xc4d, 0x3b, 0xc36, 0xc36, 0xc3f, 0xc35, 0xc30, 0xc4d, 0x3b, 0xc2e, 0xc46, 0xc39, 0xc30, 0xc4d, 0x3b, 0xc05, 0xc2c, 0xc28,
-0xc4d, 0x3b, 0xc05, 0xc1c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc47, 0x3b, 0xc2c, 0xc3e, 0xc39, 0xc4d, 0x200c, 0xc2e, 0xc3e, 0xc28, 0xc4d, 0x3b,
-0xc0e, 0xc38, 0xc4d, 0x200c, 0xc2b, 0xc3e, 0xc02, 0xc21, 0xc4d, 0xe1f, 0xe32, 0xe23, 0xe4c, 0xe27, 0xe32, 0xe23, 0xe4c, 0xe14, 0xe34, 0xe19,
-0x3b, 0xe2d, 0xe2d, 0xe23, 0xe4c, 0xe14, 0xe34, 0xe40, 0xe1a, 0xe40, 0xe2e, 0xe0a, 0xe15, 0xe4c, 0x3b, 0xe04, 0xe2d, 0xe23, 0xe4c, 0xe41,
-0xe14, 0xe14, 0x3b, 0xe40, 0xe15, 0xe2d, 0xe23, 0xe4c, 0x3b, 0xe21, 0xe2d, 0xe23, 0xe4c, 0xe41, 0xe14, 0xe14, 0x3b, 0xe0a, 0xe32, 0xe2b,
-0xe23, 0xe34, 0xe27, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe40, 0xe21, 0xe2e, 0xe23, 0xe4c, 0x3b, 0xe2d, 0xe30, 0xe1a, 0xe32, 0xe19, 0x3b, 0xe2d,
-0xe30, 0xe0b, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe40, 0xe14, 0xe22, 0xe4c, 0x3b, 0xe1a, 0xe32, 0xe2e, 0xe4c, 0xe21, 0xe32, 0xe19, 0x3b, 0xe40,
-0xe2d, 0xe2a, 0xe1f, 0xe32, 0xe19, 0xe14, 0xe4c, 0x46, 0x65, 0x72, 0x76, 0x65, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64,
-0x69, 0x62, 0x65, 0x68, 0x65, 0x15f, 0x74, 0x3b, 0x48, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d,
-0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x15e, 0x65, 0x68, 0x72, 0x69, 0x76, 0x65, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b,
-0x41, 0x62, 0x61, 0x6e, 0x3b, 0x41, 0x7a, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x65, 0x68, 0x6d, 0x65, 0x6e,
-0x3b, 0x45, 0x73, 0x66, 0x65, 0x6e, 0x64, 0x444, 0x430, 0x440, 0x432, 0x430, 0x440, 0x434, 0x456, 0x43d, 0x3b, 0x43e, 0x440, 0x434,
-0x456, 0x431, 0x435, 0x445, 0x435, 0x448, 0x442, 0x3b, 0x445, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x442, 0x456, 0x440, 0x3b, 0x43c,
-0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b, 0x448, 0x430, 0x445, 0x440, 0x456, 0x432, 0x435, 0x440, 0x3b, 0x43c, 0x435, 0x445, 0x440, 0x3b,
-0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x435, 0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x43c, 0x430, 0x43d,
-0x3b, 0x435, 0x441, 0x444, 0x430, 0x43d, 0x434, 0x444, 0x430, 0x440, 0x3b, 0x43e, 0x440, 0x434, 0x3b, 0x445, 0x43e, 0x440, 0x3b, 0x442,
-0x456, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x3b, 0x448, 0x430, 0x445, 0x3b, 0x43c, 0x435, 0x445, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b,
-0x430, 0x437, 0x435, 0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x3b, 0x435, 0x441, 0x444, 0x444, 0x430, 0x440, 0x2e,
-0x3b, 0x43e, 0x440, 0x434, 0x2e, 0x3b, 0x445, 0x43e, 0x440, 0x2e, 0x3b, 0x442, 0x456, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x2e, 0x3b,
-0x448, 0x430, 0x445, 0x2e, 0x3b, 0x43c, 0x435, 0x445, 0x2e, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x435, 0x440, 0x3b,
-0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x2e, 0x3b, 0x435, 0x441, 0x444, 0x2e, 0x641, 0x631, 0x648, 0x631, 0x62f, 0x646, 0x3b,
-0x622, 0x631, 0x688, 0x628, 0x627, 0x626, 0x634, 0x3b, 0x62e, 0x62f, 0x627, 0x62f, 0x627, 0x62f, 0x3b, 0x62a, 0x6cc, 0x631, 0x3b, 0x645,
-0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x634, 0x6c1, 0x631, 0x6cc, 0x648, 0x627, 0x631, 0x3b, 0x645, 0x6c1, 0x631, 0x3b, 0x627, 0x628, 0x627,
-0x646, 0x3b, 0x622, 0x632, 0x631, 0x3b, 0x688, 0x6d2, 0x3b, 0x628, 0x6c1, 0x645, 0x646, 0x3b, 0x627, 0x633, 0x641, 0x646, 0x62f, 0x64,
-0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61,
-0x66, 0x254, 0x66, 0x69, 0x1ebd, 0x3b, 0x64, 0x61, 0x6d, 0x25b, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d,
-0x6c, 0x254, 0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e,
-0x79, 0x254, 0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b,
-0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x64, 0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61, 0x66, 0x254,
-0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79,
-0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x62e, 0x627, 0x6a9, 0x6d5, 0x644, 0x6ce, 0x648, 0x6d5,
-0x3b, 0x628, 0x627, 0x646, 0x6d5, 0x645, 0x6d5, 0x695, 0x3b, 0x62c, 0x6c6, 0x632, 0x6d5, 0x631, 0x62f, 0x627, 0x646, 0x3b, 0x67e, 0x648,
-0x648, 0x634, 0x67e, 0x6d5, 0x695, 0x3b, 0x6af, 0x6d5, 0x644, 0x627, 0x648, 0x6ce, 0x698, 0x3b, 0x62e, 0x6d5, 0x631, 0x645, 0x627, 0x646,
-0x627, 0x646, 0x3b, 0x695, 0x6d5, 0x632, 0x628, 0x6d5, 0x631, 0x3b, 0x62e, 0x6d5, 0x632, 0x6d5, 0x6b5, 0x648, 0x6d5, 0x631, 0x3b, 0x633,
-0x6d5, 0x631, 0x645, 0x627, 0x648, 0x6d5, 0x632, 0x3b, 0x628, 0x6d5, 0x641, 0x631, 0x627, 0x646, 0x628, 0x627, 0x631, 0x3b, 0x695, 0x6ce,
-0x628, 0x6d5, 0x646, 0x62f, 0x627, 0x646, 0x3b, 0x631, 0x6d5, 0x634, 0x6d5, 0x645, 0x6ce
+static constexpr char16_t months_data[] = {
+0x46, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72,
+0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x68, 0x74, 0x3b, 0x4b, 0x68,
+0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f,
+0x72, 0x64, 0x61, 0x64, 0x3b, 0x53, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76,
+0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e,
+0x3b, 0x41, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61,
+0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x46,
+0x61, 0x72, 0x3b, 0x4f, 0x72, 0x64, 0x3b, 0x4b, 0x68, 0x6f, 0x3b, 0x54,
+0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4d,
+0x65, 0x68, 0x3b, 0x41, 0x62, 0x61, 0x3b, 0x41, 0x7a, 0x61, 0x3b, 0x44,
+0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x3b, 0x45, 0x73, 0x66, 0x46, 0x3b,
+0x4f, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x41, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x45, 0x31, 0x3b, 0x32,
+0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38,
+0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x641,
+0x631, 0x641, 0x631, 0x62f, 0x646, 0x3b, 0x623, 0x630, 0x631, 0x628, 0x64a, 0x647,
+0x634, 0x62a, 0x3b, 0x62e, 0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x62a, 0x627, 0x631,
+0x3b, 0x645, 0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x634, 0x647, 0x631, 0x641, 0x627,
+0x631, 0x3b, 0x645, 0x647, 0x631, 0x3b, 0x622, 0x64a, 0x627, 0x646, 0x3b, 0x622,
+0x630, 0x631, 0x3b, 0x62f, 0x64a, 0x3b, 0x628, 0x647, 0x645, 0x646, 0x3b, 0x627,
+0x633, 0x641, 0x646, 0x62f, 0x627, 0x631, 0x66, 0x259, 0x72, 0x76, 0x259, 0x72,
+0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65,
+0x15f, 0x74, 0x3b, 0x78, 0x6f, 0x72, 0x64, 0x259, 0x64, 0x3b, 0x74, 0x69,
+0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x259, 0x64, 0x3b, 0x15f, 0x259, 0x68,
+0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0x61,
+0x62, 0x259, 0x6e, 0x3b, 0x61, 0x7a, 0x259, 0x72, 0x3b, 0x64, 0x65, 0x79,
+0x3b, 0x62, 0x259, 0x68, 0x6d, 0x259, 0x6e, 0x3b, 0x69, 0x73, 0x66, 0x259,
+0x6e, 0x64, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9ad, 0x9be, 0x9b0, 0x9cd, 0x9a1, 0x9bf,
+0x9a8, 0x3b, 0x985, 0x9b0, 0x9a1, 0x9bf, 0x9ac, 0x9c7, 0x9b9, 0x9c7, 0x9b6, 0x9cd,
+0x9a4, 0x3b, 0x996, 0x9cb, 0x9b0, 0x9cd, 0x9a6, 0x9cd, 0x9a6, 0x3b, 0x9a4, 0x9c0,
+0x9b0, 0x3b, 0x9ae, 0x9b0, 0x9cd, 0x9af, 0x9be, 0x9a6, 0x3b, 0x9b6, 0x9be, 0x9b9,
+0x9b0, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x9c7, 0x9b9, 0x9c7, 0x9b0, 0x3b,
+0x986, 0x9ac, 0x9be, 0x9a8, 0x3b, 0x9ac, 0x9be, 0x99c, 0x9be, 0x9b0, 0x3b, 0x9a6,
+0x9c7, 0x3b, 0x9ac, 0x9be, 0x9b9, 0x9ae, 0x9be, 0x9a8, 0x3b, 0x98f, 0x9b8, 0x9ab,
+0x9cd, 0x9af, 0x9be, 0x9a8, 0x9cd, 0x9a1, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9ad, 0x9be,
+0x9b0, 0x9cd, 0x9a1, 0x9bf, 0x9a8, 0x3b, 0x985, 0x9b0, 0x9a1, 0x9bf, 0x9ac, 0x9c7,
+0x9b9, 0x9c7, 0x9b6, 0x9cd, 0x9a4, 0x3b, 0x996, 0x9cb, 0x9b0, 0x9cd, 0x9a6, 0x9cd,
+0x9a6, 0x3b, 0x9a4, 0x9c0, 0x9b0, 0x3b, 0x9ae, 0x9b0, 0x9cd, 0x9af, 0x9be, 0x9a6,
+0x3b, 0x9b6, 0x9be, 0x9b9, 0x9b0, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x9c7,
+0x9b9, 0x9c7, 0x9b0, 0x3b, 0x986, 0x9ac, 0x9be, 0x9a8, 0x3b, 0x986, 0x99c, 0x9be,
+0x9b0, 0x3b, 0x9a6, 0x9c7, 0x3b, 0x9ac, 0x9be, 0x9b9, 0x9ae, 0x9be, 0x9a8, 0x3b,
+0x98f, 0x9b8, 0x9ab, 0x9cd, 0x9af, 0x9be, 0x9a8, 0x9cd, 0x9a1, 0x9e7, 0x3b, 0x9e8,
+0x3b, 0x9e9, 0x3b, 0x9ea, 0x3b, 0x9eb, 0x3b, 0x9ec, 0x3b, 0x9ed, 0x3b, 0x9ee,
+0x3b, 0x9ef, 0x3b, 0x9e7, 0x9e6, 0x3b, 0x9e7, 0x9e7, 0x3b, 0x9e7, 0x9e8, 0x424,
+0x430, 0x440, 0x430, 0x432, 0x430, 0x434, 0x438, 0x43d, 0x3b, 0x41e, 0x440, 0x434,
+0x438, 0x431, 0x435, 0x445, 0x435, 0x448, 0x442, 0x3b, 0x41a, 0x43e, 0x440, 0x434,
+0x430, 0x434, 0x3b, 0x422, 0x438, 0x440, 0x3b, 0x41c, 0x43e, 0x440, 0x434, 0x430,
+0x434, 0x3b, 0x428, 0x430, 0x445, 0x440, 0x438, 0x432, 0x430, 0x440, 0x3b, 0x41c,
+0x435, 0x445, 0x440, 0x3b, 0x410, 0x431, 0x430, 0x43d, 0x3b, 0x410, 0x437, 0x430,
+0x440, 0x3b, 0x414, 0x435, 0x458, 0x3b, 0x411, 0x430, 0x445, 0x43c, 0x430, 0x43d,
+0x3b, 0x415, 0x441, 0x444, 0x430, 0x43d, 0x434, 0x31, 0x6708, 0x3b, 0x32, 0x6708,
+0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708,
+0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30,
+0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x62e, 0x627, 0x6a9,
+0x6d5, 0x644, 0x6ce, 0x648, 0x6d5, 0x3b, 0x628, 0x627, 0x646, 0x6d5, 0x645, 0x6d5,
+0x695, 0x3b, 0x62c, 0x6c6, 0x632, 0x6d5, 0x631, 0x62f, 0x627, 0x646, 0x3b, 0x67e,
+0x648, 0x648, 0x634, 0x67e, 0x6d5, 0x695, 0x3b, 0x6af, 0x6d5, 0x644, 0x627, 0x648,
+0x6ce, 0x698, 0x3b, 0x62e, 0x6d5, 0x631, 0x645, 0x627, 0x646, 0x627, 0x646, 0x3b,
+0x695, 0x6d5, 0x632, 0x628, 0x6d5, 0x631, 0x3b, 0x62e, 0x6d5, 0x632, 0x6d5, 0x6b5,
+0x648, 0x6d5, 0x631, 0x3b, 0x633, 0x6d5, 0x631, 0x645, 0x627, 0x648, 0x6d5, 0x632,
+0x3b, 0x628, 0x6d5, 0x641, 0x631, 0x627, 0x646, 0x628, 0x627, 0x631, 0x3b, 0x695,
+0x6ce, 0x628, 0x6d5, 0x646, 0x62f, 0x627, 0x646, 0x3b, 0x631, 0x6d5, 0x634, 0x6d5,
+0x645, 0x6ce, 0x62e, 0x627, 0x6a9, 0x6d5, 0x644, 0x6ce, 0x648, 0x6d5, 0x3b, 0x6af,
+0x648, 0x6b5, 0x627, 0x646, 0x3b, 0x62c, 0x6c6, 0x632, 0x6d5, 0x631, 0x62f, 0x627,
+0x646, 0x3b, 0x67e, 0x648, 0x648, 0x634, 0x67e, 0x6d5, 0x695, 0x3b, 0x6af, 0x6d5,
+0x644, 0x627, 0x648, 0x6ce, 0x698, 0x3b, 0x62e, 0x6d5, 0x631, 0x645, 0x627, 0x646,
+0x627, 0x646, 0x3b, 0x695, 0x6d5, 0x632, 0x628, 0x6d5, 0x631, 0x3b, 0x6af, 0x6d5,
+0x6b5, 0x627, 0x695, 0x6ce, 0x632, 0x627, 0x646, 0x3b, 0x633, 0x6d5, 0x631, 0x645,
+0x627, 0x648, 0x6d5, 0x632, 0x3b, 0x628, 0x6d5, 0x641, 0x631, 0x627, 0x646, 0x628,
+0x627, 0x631, 0x3b, 0x695, 0x6ce, 0x628, 0x6d5, 0x646, 0x62f, 0x627, 0x646, 0x3b,
+0x695, 0x6d5, 0x634, 0x6d5, 0x645, 0x6d5, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b,
+0x4e09, 0x6708, 0x3b, 0x56db, 0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b,
+0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b, 0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b,
+0x5341, 0x4e00, 0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x31, 0x2e, 0x3b, 0x32, 0x2e,
+0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e,
+0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30,
+0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e, 0x66, 0x61, 0x72,
+0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62,
+0x65, 0x68, 0x65, 0x161, 0x74, 0x3b, 0x63, 0x68, 0x6f, 0x72, 0x64, 0xe1,
+0x64, 0x3b, 0x74, 0xed, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0xe1, 0x64,
+0x3b, 0x161, 0x61, 0x68, 0x72, 0xed, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65,
+0x68, 0x72, 0x3b, 0xe1, 0x62, 0xe1, 0x6e, 0x3b, 0xe1, 0x7a, 0x61, 0x72,
+0x3b, 0x64, 0x65, 0x69, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b,
+0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72,
+0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65,
+0x73, 0x68, 0x74, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b,
+0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x73,
+0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68,
+0x72, 0x3b, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x3b,
+0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65,
+0x73, 0x66, 0x61, 0x6e, 0x64, 0x64, 0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x64,
+0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64, 0x6f, 0x78, 0x65,
+0x3b, 0x61, 0x66, 0x254, 0x66, 0x69, 0x1ebd, 0x3b, 0x64, 0x61, 0x6d, 0x25b,
+0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c, 0x254,
+0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65,
+0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x6b, 0x65, 0x6c,
+0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78,
+0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x64, 0x7a, 0x76, 0x3b, 0x64,
+0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61, 0x66, 0x254, 0x3b, 0x64,
+0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64,
+0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61,
+0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72,
+0x64, 0x69, 0x6e, 0x6b, 0x75, 0x75, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62,
+0x65, 0x68, 0x65, 0x161, 0x74, 0x6b, 0x75, 0x75, 0x3b, 0x6b, 0x68, 0x6f,
+0x72, 0x64, 0x61, 0x64, 0x6b, 0x75, 0x75, 0x3b, 0x74, 0x69, 0x72, 0x6b,
+0x75, 0x75, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x61, 0x64, 0x6b, 0x75, 0x75,
+0x3b, 0x161, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x6b, 0x75, 0x75,
+0x3b, 0x6d, 0x65, 0x68, 0x72, 0x6b, 0x75, 0x75, 0x3b, 0x61, 0x62, 0x61,
+0x6e, 0x6b, 0x75, 0x75, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x6b, 0x75, 0x75,
+0x3b, 0x64, 0x65, 0x79, 0x6b, 0x75, 0x75, 0x3b, 0x62, 0x61, 0x68, 0x6d,
+0x61, 0x6e, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64,
+0x6b, 0x75, 0x75, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e,
+0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62, 0x65,
+0x68, 0x65, 0x161, 0x74, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x68,
+0x6f, 0x72, 0x64, 0x61, 0x64, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x74,
+0x69, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x6f, 0x72, 0x64,
+0x61, 0x64, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x161, 0x61, 0x68, 0x72,
+0x69, 0x76, 0x61, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x65,
+0x68, 0x72, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x61, 0x62, 0x61, 0x6e,
+0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x6b, 0x75,
+0x75, 0x74, 0x61, 0x3b, 0x64, 0x65, 0x79, 0x6b, 0x75, 0x75, 0x74, 0x61,
+0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x6b, 0x75, 0x75, 0x74, 0x61,
+0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x6b, 0x75, 0x75, 0x74, 0x61,
+0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72,
+0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x3b, 0x6b, 0x68, 0x6f,
+0x72, 0x64, 0x61, 0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72,
+0x64, 0x61, 0x64, 0x3b, 0x161, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72,
+0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x61,
+0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d,
+0x61, 0x6e, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x66, 0x61, 0x72,
+0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72, 0x64, 0x69, 0x62,
+0x65, 0x68, 0x65, 0x161, 0x74, 0x3b, 0x6b, 0x68, 0x6f, 0x72, 0x64, 0xe2,
+0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x64, 0xe2, 0x64,
+0x3b, 0x161, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65,
+0x68, 0x72, 0x3b, 0xe2, 0x62, 0xe2, 0x6e, 0x3b, 0xe2, 0x7a, 0x61, 0x72,
+0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b,
+0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x66, 0x61, 0x72, 0x2e, 0x3b, 0x6f,
+0x72, 0x64, 0x2e, 0x3b, 0x6b, 0x68, 0x6f, 0x2e, 0x3b, 0x74, 0x69, 0x72,
+0x3b, 0x6d, 0x6f, 0x72, 0x2e, 0x3b, 0x161, 0x61, 0x68, 0x2e, 0x3b, 0x6d,
+0x65, 0x68, 0x72, 0x3b, 0xe2, 0x62, 0xe2, 0x6e, 0x3b, 0xe2, 0x7a, 0x61,
+0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x2e, 0x3b, 0x65,
+0x73, 0x66, 0x2e, 0x46, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e,
+0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x3b,
+0x4b, 0x68, 0x6f, 0x72, 0x64, 0xe2, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b,
+0x4d, 0x6f, 0x72, 0x64, 0xe2, 0x64, 0x3b, 0x160, 0x61, 0x68, 0x72, 0x69,
+0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0xc2, 0x62, 0xe2,
+0x6e, 0x3b, 0xc2, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42,
+0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64,
+0x46, 0x61, 0x72, 0x2e, 0x3b, 0x4f, 0x72, 0x64, 0x2e, 0x3b, 0x4b, 0x68,
+0x6f, 0x2e, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x2e, 0x3b,
+0x160, 0x61, 0x68, 0x2e, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0xc2, 0x62,
+0xe2, 0x2e, 0x3b, 0xc2, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b,
+0x42, 0x61, 0x68, 0x2e, 0x3b, 0x45, 0x73, 0x66, 0x2e, 0xd83a, 0xdd0a, 0xd83a,
+0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd3e, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a,
+0xdd2d, 0xd83a, 0xdd32, 0x3b, 0xd83a, 0xdd0c, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a, 0xdd2d,
+0xd83a, 0xdd26, 0xd83a, 0xdd2b, 0xd83a, 0xdd38, 0xd83a, 0xdd2b, 0xd83a, 0xdd43, 0xd83a, 0xdd3c,
+0x3b, 0xd83a, 0xdd1d, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a, 0xdd22, 0xd83a,
+0xdd23, 0x3b, 0xd83a, 0xdd1a, 0xd83a, 0xdd2d, 0xd83a, 0xdd2a, 0x3b, 0xd83a, 0xdd03, 0xd83a,
+0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd23, 0xd83a, 0xdd22, 0xd83a, 0xdd23, 0x3b, 0xd83a, 0xdd21,
+0xd83a, 0xdd22, 0xd83a, 0xdd38, 0xd83a, 0xdd2a, 0xd83a, 0xdd2d, 0xd83a, 0xdd3e, 0xd83a, 0xdd22,
+0xd83a, 0xdd2a, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd2b, 0xd83a, 0xdd38, 0xd83a, 0xdd2b, 0xd83a,
+0xdd2a, 0x3b, 0xd83a, 0xdd00, 0xd83a, 0xdd26, 0xd83a, 0xdd22, 0xd83a, 0xdd32, 0x3b, 0xd83a,
+0xdd00, 0xd83a, 0xdd41, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0x3b, 0xd83a, 0xdd01, 0xd83a, 0xdd2b,
+0xd83a, 0xdd34, 0x3b, 0xd83a, 0xdd04, 0xd83a, 0xdd22, 0xd83a, 0xdd38, 0xd83a, 0xdd25, 0xd83a,
+0xdd22, 0xd83a, 0xdd32, 0x3b, 0xd83a, 0xdd09, 0xd83a, 0xdd27, 0xd83a, 0xdd2c, 0xd83a, 0xdd22,
+0xd83a, 0xdd32, 0xd83a, 0xdd23, 0xd83a, 0xdd51, 0x3b, 0xd83a, 0xdd52, 0x3b, 0xd83a, 0xdd53,
+0x3b, 0xd83a, 0xdd54, 0x3b, 0xd83a, 0xdd55, 0x3b, 0xd83a, 0xdd56, 0x3b, 0xd83a, 0xdd57,
+0x3b, 0xd83a, 0xdd58, 0x3b, 0xd83a, 0xdd59, 0x3b, 0xd83a, 0xdd51, 0xd83a, 0xdd50, 0x3b,
+0xd83a, 0xdd51, 0xd83a, 0xdd51, 0x3b, 0xd83a, 0xdd51, 0xd83a, 0xdd52, 0x10e4, 0x10d0, 0x10e0,
+0x10d5, 0x10d0, 0x10e0, 0x10d3, 0x10d8, 0x10dc, 0x10d8, 0x3b, 0x10dd, 0x10e0, 0x10d3, 0x10d8,
+0x10d1, 0x10d4, 0x10f0, 0x10d4, 0x10e8, 0x10d7, 0x10d8, 0x3b, 0x10ee, 0x10dd, 0x10e0, 0x10d3,
+0x10d0, 0x10d3, 0x10d8, 0x3b, 0x10d7, 0x10d8, 0x10e0, 0x10d8, 0x3b, 0x10db, 0x10dd, 0x10e0,
+0x10d3, 0x10d0, 0x10d3, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10f0, 0x10e0, 0x10d8, 0x10d5, 0x10d0,
+0x10e0, 0x10d8, 0x3b, 0x10db, 0x10d4, 0x10f0, 0x10e0, 0x10d8, 0x3b, 0x10d0, 0x10d1, 0x10d0,
+0x10dc, 0x10d8, 0x3b, 0x10d0, 0x10d6, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d8,
+0x3b, 0x10d1, 0x10d0, 0x10f0, 0x10db, 0x10d0, 0x10dc, 0x10d8, 0x3b, 0x10d4, 0x10e1, 0x10e4,
+0x10d0, 0x10dc, 0x10d3, 0x10d8, 0x46, 0x61, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69,
+0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x63,
+0x68, 0x74, 0x3b, 0x43, 0x68, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x54,
+0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x53, 0x63,
+0x68, 0x61, 0x68, 0x72, 0x69, 0x77, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68,
+0x72, 0x3b, 0x100, 0x62, 0x101, 0x6e, 0x3b, 0x100, 0x73, 0x61, 0x72, 0x3b,
+0x44, 0xe9, 0x69, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45,
+0x73, 0x73, 0x66, 0x61, 0x6e, 0x64, 0xaab, 0xabe, 0xab0, 0xacd, 0xab5, 0xabe,
+0xab0, 0xacd, 0xaa6, 0xabf, 0xaa8, 0x3b, 0xa93, 0xab0, 0xaa1, 0xac0, 0xaac, 0xac7,
+0xab9, 0xac7, 0xab6, 0xacd, 0xa9f, 0x3b, 0xa96, 0xacb, 0xab0, 0xaa6, 0xabe, 0xaa6,
+0x3b, 0xaa4, 0xabf, 0xab0, 0x3b, 0xaae, 0xacb, 0xab0, 0xacd, 0xaa6, 0xabe, 0xaa6,
+0x3b, 0xab6, 0xabe, 0xab9, 0xab0, 0xabf, 0xab5, 0xab0, 0x3b, 0xaae, 0xac7, 0xab9,
+0xab0, 0x3b, 0xa85, 0xaac, 0xabe, 0xaa8, 0x3b, 0xa85, 0xa9d, 0xabe, 0xab0, 0x3b,
+0xaa1, 0xac7, 0xaaf, 0x3b, 0xaac, 0xabe, 0xab9, 0xaae, 0xac7, 0xaa8, 0x3b, 0xa8f,
+0xab8, 0xacd, 0xaab, 0xabe, 0xaa8, 0xacd, 0xaa1, 0x5e4, 0x5e8, 0x5d5, 0x5e8, 0x5d3,
+0x5d9, 0x5df, 0x3b, 0x5d0, 0x5e8, 0x5d3, 0x5d9, 0x5d1, 0x5d4, 0x5e9, 0x5ea, 0x3b,
+0x5d7, 0x5f3, 0x5e8, 0x5d3, 0x5d0, 0x5d3, 0x3b, 0x5ea, 0x5d9, 0x5e8, 0x3b, 0x5de,
+0x5e8, 0x5d3, 0x5d0, 0x5d3, 0x3b, 0x5e9, 0x5d4, 0x5e8, 0x5d9, 0x5d5, 0x5e8, 0x3b,
+0x5de, 0x5d4, 0x5e8, 0x3b, 0x5d0, 0x5d1, 0x5d0, 0x5df, 0x3b, 0x5d0, 0x5d3, 0x5f3,
+0x5e8, 0x3b, 0x5d3, 0x5d9, 0x3b, 0x5d1, 0x5d4, 0x5de, 0x5df, 0x3b, 0x5d0, 0x5e1,
+0x5e4, 0x5e0, 0x5d3, 0x92b, 0x930, 0x94d, 0x935, 0x93e, 0x926, 0x93f, 0x928, 0x3b,
+0x913, 0x930, 0x94d, 0x926, 0x93f, 0x935, 0x947, 0x939, 0x947, 0x938, 0x94d, 0x91f,
+0x3b, 0x916, 0x94b, 0x930, 0x930, 0x94d, 0x926, 0x93e, 0x926, 0x3b, 0x91f, 0x93f,
+0x930, 0x3b, 0x92e, 0x94b, 0x930, 0x926, 0x93e, 0x926, 0x3b, 0x936, 0x93e, 0x939,
+0x930, 0x940, 0x935, 0x930, 0x94d, 0x3b, 0x92e, 0x947, 0x939, 0x930, 0x3b, 0x905,
+0x935, 0x928, 0x3b, 0x905, 0x91c, 0x93c, 0x930, 0x3b, 0x921, 0x947, 0x3b, 0x92c,
+0x939, 0x92e, 0x928, 0x3b, 0x908, 0x938, 0x94d, 0x92b, 0x928, 0x94d, 0x926, 0x94d,
+0x30d5, 0x30a1, 0x30eb, 0x30f4, 0x30a1, 0x30eb, 0x30c7, 0x30a3, 0x30fc, 0x30f3, 0x3b, 0x30aa,
+0x30eb, 0x30c7, 0x30a3, 0x30fc, 0x30d9, 0x30d8, 0x30b7, 0x30e5, 0x30c8, 0x3b, 0x30db, 0x30eb,
+0x30c0, 0x30fc, 0x30c9, 0x3b, 0x30c6, 0x30a3, 0x30fc, 0x30eb, 0x3b, 0x30e2, 0x30eb, 0x30c0,
+0x30fc, 0x30c9, 0x3b, 0x30b7, 0x30e3, 0x30cf, 0x30ea, 0x30fc, 0x30f4, 0x30a1, 0x30eb, 0x3b,
+0x30e1, 0x30d5, 0x30eb, 0x3b, 0x30a2, 0x30fc, 0x30d0, 0x30fc, 0x30f3, 0x3b, 0x30a2, 0x30fc,
+0x30b6, 0x30eb, 0x3b, 0x30c7, 0x30a4, 0x3b, 0x30d0, 0x30d5, 0x30de, 0x30f3, 0x3b, 0x30a8,
+0x30b9, 0x30d5, 0x30a1, 0x30f3, 0x30c9, 0xcab, 0xcb0, 0xccd, 0xcb5, 0xcb0, 0xccd, 0xca6,
+0xcbf, 0xca8, 0xccd, 0x3b, 0xc93, 0xcb0, 0xccd, 0xca6, 0xcbf, 0xcac, 0xcc6, 0xcb9,
+0xcc6, 0xcb6, 0xccd, 0xc9f, 0xccd, 0x3b, 0xc96, 0xccb, 0xcb0, 0xccd, 0xca1, 0xcbe,
+0xca6, 0xccd, 0x3b, 0xc9f, 0xcbf, 0xcb0, 0xccd, 0x3b, 0xcae, 0xcca, 0xcb0, 0xccd,
+0xca6, 0xcbe, 0xca6, 0xccd, 0x3b, 0xcb6, 0xcb9, 0xcb0, 0xcbf, 0xcb5, 0xcbe, 0xcb0,
+0xccd, 0x3b, 0xcae, 0xcc6, 0xcb9, 0xccd, 0xcb0, 0xccd, 0x3b, 0xc85, 0xcac, 0xca8,
+0xccd, 0x3b, 0xc85, 0xc9d, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcc7, 0x3b, 0xcac, 0xcb9,
+0xccd, 0xcae, 0xca8, 0xccd, 0x3b, 0xc8e, 0xcb8, 0xccd, 0xcab, 0xcbe, 0xc82, 0xca1,
+0xccd, 0x424, 0x430, 0x440, 0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x41e,
+0x440, 0x434, 0x438, 0x431, 0x435, 0x445, 0x435, 0x448, 0x442, 0x3b, 0x425, 0x43e,
+0x440, 0x434, 0x430, 0x434, 0x3b, 0x422, 0x438, 0x440, 0x3b, 0x41c, 0x43e, 0x440,
+0x434, 0x430, 0x434, 0x3b, 0x428, 0x430, 0x445, 0x440, 0x438, 0x432, 0x430, 0x440,
+0x3b, 0x41c, 0x435, 0x445, 0x440, 0x3b, 0x410, 0x431, 0x430, 0x43d, 0x3b, 0x410,
+0x437, 0x430, 0x440, 0x3b, 0x414, 0x435, 0x439, 0x3b, 0x411, 0x430, 0x445, 0x43c,
+0x430, 0x43d, 0x3b, 0x42d, 0x441, 0x444, 0x430, 0x43d, 0x434, 0xd654, 0xb974, 0xbc14,
+0xb518, 0x3b, 0xc624, 0xb974, 0xb514, 0xbca0, 0xd5e4, 0xc26c, 0xd2b8, 0x3b, 0xd638, 0xb974,
+0xb2e4, 0xb4dc, 0x3b, 0xd2f0, 0xb974, 0x3b, 0xbaa8, 0xb974, 0xb2e4, 0xb4dc, 0x3b, 0xc0e4,
+0xd750, 0xb9ac, 0xbc14, 0xb974, 0x3b, 0xba54, 0xd750, 0xb974, 0x3b, 0xc544, 0xbc18, 0x3b,
+0xc544, 0xc790, 0xb974, 0x3b, 0xb2e4, 0xc774, 0x3b, 0xbc14, 0xd750, 0xb9cc, 0x3b, 0xc5d0,
+0xc2a4, 0xd310, 0xb4dc, 0xe9f, 0xea3, 0xeb2, 0xea7, 0xeb2, 0xe94, 0xeb4, 0xe99, 0x3b,
+0xead, 0xecd, 0xea3, 0xe94, 0xeb5, 0xe9a, 0xeb5, 0xec0, 0xeab, 0xea3, 0xe94, 0x3b,
+0xe84, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xec1, 0xe95, 0xea3, 0x3b, 0xea1,
+0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xe8a, 0xeb2, 0xea3, 0xeab, 0xeb4, 0xea7,
+0xeb2, 0x3b, 0xec0, 0xea1, 0xeb5, 0x3b, 0xead, 0xeb2, 0xe9a, 0xeb2, 0xe99, 0x3b,
+0xead, 0xeb2, 0xe8a, 0xeb2, 0xea3, 0x3b, 0xe94, 0xeb5, 0xea3, 0x3b, 0xe9a, 0xea3,
+0xeb2, 0xec1, 0xea1, 0xe99, 0x3b, 0xec0, 0xead, 0xeaa, 0xe9f, 0xeb2, 0xe99, 0xe9f,
+0xea3, 0xeb2, 0xea7, 0xeb2, 0xe94, 0xeb4, 0xe99, 0x3b, 0xead, 0xecd, 0xea3, 0xe94,
+0xeb5, 0xe9a, 0xeb5, 0xec0, 0xeab, 0xeae, 0xe94, 0x3b, 0xe84, 0xecd, 0xea3, 0xec0,
+0xe94, 0xe94, 0x3b, 0xec1, 0xe95, 0xea3, 0x3b, 0xea1, 0xecd, 0xea3, 0xec0, 0xe94,
+0xe94, 0x3b, 0xe8a, 0xeb2, 0xea3, 0xea5, 0xeb4, 0xea7, 0xeb2, 0x3b, 0xec0, 0xea1,
+0xeb5, 0x3b, 0xead, 0xeb2, 0xe9a, 0xeb2, 0xe99, 0x3b, 0xead, 0xeb2, 0xe8a, 0xeb2,
+0x3b, 0xe94, 0xeb5, 0xea3, 0x3b, 0xe9a, 0xea3, 0xeb2, 0xea1, 0xeb2, 0xe99, 0x3b,
+0xec0, 0xead, 0xeaa, 0xe9f, 0xeb2, 0xe99, 0xe9f, 0xeb2, 0xea3, 0xea7, 0xeb2, 0xe94,
+0xeb4, 0xe99, 0x3b, 0xead, 0xecd, 0xea3, 0xe94, 0xeb5, 0xe9a, 0xeb5, 0xec0, 0xeab,
+0xea3, 0xe94, 0x3b, 0xe84, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xec1, 0xe95,
+0xea3, 0x3b, 0xea1, 0xecd, 0xea3, 0xec0, 0xe94, 0xe94, 0x3b, 0xe8a, 0xeb2, 0xea3,
+0xeab, 0xeb4, 0xea7, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeb5, 0x3b, 0xead, 0xeb2, 0xe9a,
+0xeb2, 0xe99, 0x3b, 0xead, 0xeb2, 0xe8a, 0xeb2, 0x3b, 0xe94, 0xeb5, 0xea3, 0x3b,
+0xe9a, 0xea3, 0xeb2, 0xea1, 0xeb2, 0xe99, 0x3b, 0xec0, 0xead, 0xeaa, 0xe9f, 0xeb2,
+0xe99, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x12b, 0x6e, 0x73, 0x3b,
+0x6f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x73, 0x3b,
+0x68, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x73, 0x3b, 0x74, 0x12b, 0x72, 0x73,
+0x3b, 0x6d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x73, 0x3b, 0x161, 0x61, 0x68,
+0x72, 0x69, 0x76, 0x113, 0x72, 0x73, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x73,
+0x3b, 0x61, 0x62, 0x61, 0x6e, 0x73, 0x3b, 0x61, 0x7a, 0x65, 0x72, 0x73,
+0x3b, 0x64, 0x65, 0x6a, 0x73, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e,
+0x73, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x73, 0x444, 0x430, 0x440,
+0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x43e, 0x440, 0x434, 0x438, 0x431,
+0x435, 0x445, 0x435, 0x448, 0x442, 0x3b, 0x43a, 0x43e, 0x440, 0x434, 0x430, 0x434,
+0x3b, 0x442, 0x438, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b,
+0x448, 0x430, 0x445, 0x440, 0x438, 0x432, 0x430, 0x440, 0x3b, 0x43c, 0x435, 0x440,
+0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x430, 0x440, 0x3b, 0x434,
+0x435, 0x458, 0x3b, 0x431, 0x430, 0x445, 0x43c, 0x430, 0x43d, 0x3b, 0x435, 0x441,
+0x444, 0x430, 0x43d, 0x434, 0xd2b, 0xd7c, 0xd35, 0xd3e, 0xd7c, 0xd26, 0xd3f, 0xd7b,
+0x3b, 0xd13, 0xd7c, 0xd21, 0xd3f, 0xd2c, 0xd46, 0xd39, 0xd46, 0xd37, 0xd4d, 0x200c,
+0xd31, 0xd4d, 0xd31, 0xd4d, 0x3b, 0xd16, 0xd4b, 0xd7c, 0xd26, 0xd3e, 0xd26, 0xd4d,
+0x3b, 0xd1f, 0xd3f, 0xd7c, 0x3b, 0xd2e, 0xd4b, 0xd7c, 0xd26, 0xd3e, 0xd26, 0xd4d,
+0x3b, 0xd37, 0xd39, 0xd4d, 0x200c, 0xd30, 0xd3f, 0xd35, 0xd3e, 0xd7c, 0x3b, 0xd2e,
+0xd46, 0xd39, 0xd7c, 0x3b, 0xd05, 0xd2c, 0xd3e, 0xd7b, 0x3b, 0xd05, 0xd38, 0xd7c,
+0x3b, 0xd21, 0xd46, 0xd2f, 0xd4d, 0x3b, 0xd2c, 0xd39, 0xd4d, 0x200c, 0xd2e, 0xd3e,
+0xd7b, 0x3b, 0xd0e, 0xd38, 0xd4d, 0x200c, 0xd2b, 0xd3e, 0xd7b, 0xd21, 0xd4d, 0xd2b,
+0x2e, 0x3b, 0xd13, 0x2e, 0x3b, 0xd16, 0xd4b, 0x3b, 0xd1f, 0xd3f, 0x2e, 0x3b,
+0xd2e, 0xd4b, 0x2e, 0x3b, 0xd37, 0x2e, 0x3b, 0xd2e, 0xd46, 0x2e, 0x3b, 0xd05,
+0x2e, 0x3b, 0xd05, 0x2e, 0x3b, 0xd21, 0xd46, 0x2e, 0x3b, 0xd2c, 0x2e, 0x3b,
+0xd0e, 0x2e, 0x92b, 0x930, 0x935, 0x930, 0x926, 0x93f, 0x928, 0x3b, 0x913, 0x930,
+0x94d, 0x926, 0x93f, 0x92c, 0x947, 0x939, 0x947, 0x936, 0x94d, 0x924, 0x3b, 0x916,
+0x94b, 0x930, 0x926, 0x93e, 0x926, 0x3b, 0x924, 0x93f, 0x930, 0x3b, 0x92e, 0x94b,
+0x930, 0x926, 0x93e, 0x926, 0x3b, 0x936, 0x93e, 0x939, 0x930, 0x940, 0x935, 0x93e,
+0x930, 0x3b, 0x92e, 0x947, 0x939, 0x947, 0x930, 0x3b, 0x905, 0x92c, 0x93e, 0x928,
+0x3b, 0x905, 0x91d, 0x93e, 0x930, 0x3b, 0x926, 0x947, 0x3b, 0x92c, 0x93e, 0x939,
+0x92e, 0x93e, 0x928, 0x3b, 0x90f, 0x938, 0x92b, 0x93e, 0x902, 0x926, 0x967, 0x3b,
+0x968, 0x3b, 0x969, 0x3b, 0x96a, 0x3b, 0x96b, 0x3b, 0x96c, 0x3b, 0x96d, 0x3b,
+0x96e, 0x3b, 0x96f, 0x3b, 0x967, 0x966, 0x3b, 0x967, 0x967, 0x3b, 0x967, 0x968,
+0x648, 0x631, 0x6cc, 0x3b, 0x63a, 0x648, 0x6cc, 0x6cc, 0x3b, 0x63a, 0x628, 0x631,
+0x6af, 0x648, 0x644, 0x6cc, 0x3b, 0x686, 0x646, 0x6af, 0x627, 0x69a, 0x3b, 0x632,
+0x645, 0x631, 0x6cc, 0x3b, 0x648, 0x696, 0x6cc, 0x3b, 0x62a, 0x644, 0x647, 0x3b,
+0x644, 0x693, 0x645, 0x3b, 0x644, 0x6cc, 0x646, 0x62f, 0x6cd, 0x3b, 0x645, 0x631,
+0x63a, 0x648, 0x645, 0x6cc, 0x3b, 0x633, 0x644, 0x648, 0x627, 0x63a, 0x647, 0x3b,
+0x6a9, 0x628, 0x6f1, 0x3b, 0x6f2, 0x3b, 0x6f3, 0x3b, 0x6f4, 0x3b, 0x6f5, 0x3b,
+0x6f6, 0x3b, 0x6f7, 0x3b, 0x6f8, 0x3b, 0x6f9, 0x3b, 0x6f1, 0x6f0, 0x3b, 0x6f1,
+0x6f1, 0x3b, 0x6f1, 0x6f2, 0x641, 0x631, 0x648, 0x631, 0x62f, 0x6cc, 0x646, 0x3b,
+0x627, 0x631, 0x62f, 0x6cc, 0x628, 0x647, 0x634, 0x62a, 0x3b, 0x62e, 0x631, 0x62f,
+0x627, 0x62f, 0x3b, 0x62a, 0x6cc, 0x631, 0x3b, 0x645, 0x631, 0x62f, 0x627, 0x62f,
+0x3b, 0x634, 0x647, 0x631, 0x6cc, 0x648, 0x631, 0x3b, 0x645, 0x647, 0x631, 0x3b,
+0x622, 0x628, 0x627, 0x646, 0x3b, 0x622, 0x630, 0x631, 0x3b, 0x62f, 0x6cc, 0x3b,
+0x628, 0x647, 0x645, 0x646, 0x3b, 0x627, 0x633, 0x641, 0x646, 0x62f, 0x641, 0x3b,
+0x627, 0x3b, 0x62e, 0x3b, 0x62a, 0x3b, 0x645, 0x3b, 0x634, 0x3b, 0x645, 0x3b,
+0x622, 0x3b, 0x622, 0x3b, 0x62f, 0x3b, 0x628, 0x3b, 0x627, 0x62d, 0x645, 0x644,
+0x3b, 0x62b, 0x648, 0x631, 0x3b, 0x62c, 0x648, 0x632, 0x627, 0x3b, 0x633, 0x631,
+0x637, 0x627, 0x646, 0x3b, 0x627, 0x633, 0x62f, 0x3b, 0x633, 0x646, 0x628, 0x644,
+0x647, 0x654, 0x3b, 0x645, 0x6cc, 0x632, 0x627, 0x646, 0x3b, 0x639, 0x642, 0x631,
+0x628, 0x3b, 0x642, 0x648, 0x633, 0x3b, 0x62c, 0x62f, 0x6cc, 0x3b, 0x62f, 0x644,
+0x648, 0x3b, 0x62d, 0x648, 0x62a, 0x62d, 0x3b, 0x62b, 0x3b, 0x62c, 0x3b, 0x633,
+0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x645, 0x3b, 0x639, 0x3b, 0x642, 0x3b, 0x62c,
+0x3b, 0x62f, 0x3b, 0x62d, 0x46, 0x61, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69,
+0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x7a,
+0x74, 0x3b, 0x43, 0x68, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x54, 0x69,
+0x72, 0x3b, 0x4d, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x53, 0x7a, 0x61,
+0x68, 0x72, 0x69, 0x77, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b,
+0x100, 0x62, 0x101, 0x6e, 0x3b, 0x100, 0x73, 0x61, 0x72, 0x3b, 0x44, 0xe9,
+0x69, 0x3b, 0x42, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66,
+0x61, 0x6e, 0x64, 0xa2b, 0xa3e, 0xa30, 0xa35, 0xa30, 0xa21, 0xa40, 0xa28, 0x3b,
+0xa14, 0xa30, 0xa21, 0xa3e, 0xa08, 0xa2c, 0xa39, 0xa48, 0xa38, 0xa3c, 0xa1f, 0x3b,
+0xa16, 0xa4b, 0xa21, 0xa30, 0xa21, 0x3b, 0xa1f, 0xa3f, 0xa30, 0x3b, 0xa2e, 0xa4b,
+0xa30, 0xa21, 0xa3e, 0xa26, 0x3b, 0xa38, 0xa3c, 0xa30, 0xa3e, 0xa07, 0xa35, 0xa30,
+0x3b, 0xa2e, 0xa47, 0xa39, 0xa30, 0x3b, 0xa05, 0xa2c, 0xa3e, 0xa28, 0x3b, 0xa05,
+0xa1c, 0xa3c, 0xa3e, 0xa30, 0x3b, 0xa21, 0xa47, 0xa05, 0x3b, 0xa2c, 0xa3e, 0xa39,
+0xa2e, 0xa28, 0x3b, 0xa10, 0xa38, 0xa2b, 0xa70, 0xa21, 0x46, 0x61, 0x72, 0x76,
+0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f, 0x72, 0x64, 0x69, 0x62, 0x65,
+0x68, 0x65, 0x73, 0x68, 0x74, 0x3b, 0x4b, 0x68, 0x6f, 0x72, 0x64, 0x61,
+0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x41, 0x2d, 0x4d, 0x6f, 0x72, 0x64,
+0x61, 0x64, 0x3b, 0x53, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72,
+0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e, 0x3b, 0x41,
+0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x61, 0x68, 0x6d,
+0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x444, 0x430, 0x440,
+0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x43e, 0x440, 0x434, 0x438, 0x431,
+0x435, 0x445, 0x435, 0x448, 0x442, 0x3b, 0x445, 0x43e, 0x440, 0x434, 0x430, 0x434,
+0x3b, 0x442, 0x438, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b,
+0x448, 0x430, 0x445, 0x440, 0x438, 0x432, 0x435, 0x440, 0x3b, 0x43c, 0x435, 0x445,
+0x440, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x435, 0x440, 0x3b,
+0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x43c, 0x430, 0x43d, 0x3b, 0x44d,
+0x441, 0x444, 0x430, 0x43d, 0x434, 0x66, 0x61, 0x72, 0x2e, 0x3b, 0x6f, 0x72,
+0x64, 0x2e, 0x3b, 0x6b, 0x68, 0x6f, 0x2e, 0x3b, 0x74, 0x69, 0x72, 0x3b,
+0x6d, 0x6f, 0x72, 0x2e, 0x3b, 0x73, 0x68, 0x61, 0x2e, 0x3b, 0x6d, 0x65,
+0x68, 0x72, 0x3b, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x61, 0x7a, 0x61, 0x72,
+0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x2e, 0x3b, 0x65, 0x73,
+0x66, 0x2e, 0x46, 0x61, 0x72, 0x61, 0x76, 0x61, 0x64, 0x69, 0x6e, 0x3b,
+0x4f, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x161, 0x74, 0x3b, 0x4b,
+0x6f, 0x72, 0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f,
+0x72, 0x64, 0x61, 0x64, 0x3b, 0x160, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61,
+0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e, 0x3b,
+0x41, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x6a, 0x3b, 0x42, 0x61, 0x68,
+0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x4a, 0x61,
+0x6e, 0x61, 0x61, 0x79, 0x6f, 0x3b, 0x46, 0x65, 0x65, 0x62, 0x72, 0x61,
+0x61, 0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41,
+0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x61, 0x79, 0x6f, 0x3b, 0x4a,
+0x75, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x75, 0x6c, 0x69, 0x79, 0x6f, 0x3b,
+0x41, 0x67, 0x6f, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74,
+0x65, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f,
+0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x6f, 0x66, 0x65, 0x65, 0x6d, 0x62,
+0x61, 0x72, 0x3b, 0x44, 0x69, 0x69, 0x73, 0x65, 0x65, 0x6d, 0x62, 0x61,
+0x72, 0x46, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f,
+0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x68, 0x74, 0x3b, 0x4b,
+0x68, 0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d,
+0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x53, 0x68, 0x61, 0x68, 0x72, 0x69,
+0x76, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x100, 0x62, 0x101,
+0x6e, 0x3b, 0x100, 0x7a, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42,
+0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x61, 0x6e, 0x64,
+0x66, 0x61, 0x72, 0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x72,
+0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x73, 0x68, 0x74, 0x3b, 0x6b, 0x68,
+0x6f, 0x72, 0x64, 0x101, 0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x6f,
+0x72, 0x64, 0x101, 0x64, 0x3b, 0x73, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76,
+0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68, 0x72, 0x3b, 0x101, 0x62, 0x101, 0x6e,
+0x3b, 0x101, 0x7a, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61,
+0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x65, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x444,
+0x430, 0x440, 0x432, 0x430, 0x440, 0x434, 0x438, 0x43d, 0x3b, 0x443, 0x440, 0x434,
+0x438, 0x431, 0x438, 0x4b3, 0x438, 0x448, 0x442, 0x3b, 0x445, 0x443, 0x440, 0x434,
+0x43e, 0x434, 0x3b, 0x442, 0x438, 0x440, 0x3b, 0x43c, 0x443, 0x440, 0x434, 0x43e,
+0x434, 0x3b, 0x448, 0x430, 0x4b3, 0x440, 0x438, 0x432, 0x430, 0x440, 0x3b, 0x43c,
+0x435, 0x4b3, 0x440, 0x3b, 0x43e, 0x431, 0x43e, 0x43d, 0x3b, 0x43e, 0x437, 0x430,
+0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x4b3, 0x43c, 0x430, 0x43d,
+0x3b, 0x438, 0x441, 0x444, 0x430, 0x43d, 0x434, 0xb83, 0xbaa, 0xbb0, 0xbcd, 0xbb5,
+0xbbe, 0xba4, 0xbbf, 0xba9, 0xbcd, 0x3b, 0xb86, 0xbb0, 0xbcd, 0xb9f, 0xbbf, 0xbaa,
+0xbc6, 0xbb9, 0xbc6, 0xbb7, 0xbcd, 0xba4, 0xbcd, 0x3b, 0xb95, 0xbca, 0xbb0, 0xbcd,
+0xba4, 0xbbe, 0xba4, 0xbcd, 0x3b, 0xba4, 0xbbf, 0xbb0, 0xbcd, 0x3b, 0xbae, 0xbca,
+0xbb0, 0xbcd, 0xba4, 0xbbe, 0xba4, 0xbcd, 0x3b, 0xbb7, 0xbbe, 0xbb0, 0xbbf, 0xbb5,
+0xbbe, 0xbb0, 0xbcd, 0x3b, 0xbae, 0xbc6, 0xbb9, 0xbcd, 0xbb0, 0xbcd, 0x3b, 0xb85,
+0xbaa, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xb85, 0xb9a, 0xbbe, 0xbb0, 0xbcd, 0x3b, 0xba4,
+0xbc7, 0x3b, 0xbaa, 0xbb9, 0xbcd, 0xbae, 0xbbe, 0xba9, 0xbcd, 0x3b, 0xb8e, 0xb83,
+0xbaa, 0xbbe, 0xba9, 0xbcd, 0xb83, 0xbaa, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb86, 0xbb0,
+0xbcd, 0xb9f, 0xbbf, 0x2e, 0x3b, 0xb95, 0xbca, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xba4,
+0xbbf, 0xbb0, 0xbcd, 0x3b, 0xbae, 0xbca, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xbb7, 0xbbe,
+0xbb0, 0xbbf, 0x2e, 0x3b, 0xbae, 0xbc6, 0xbb9, 0xbcd, 0x2e, 0x3b, 0xb85, 0xbaa,
+0xbbe, 0x2e, 0x3b, 0xb85, 0xb9a, 0xbbe, 0x2e, 0x3b, 0xba4, 0xbc7, 0x3b, 0xbaa,
+0xbb9, 0xbcd, 0x2e, 0x3b, 0xb8e, 0xb83, 0x2e, 0xc2b, 0xc3e, 0xc35, 0xc30, 0xc4d,
+0xc21, 0xc3f, 0xc28, 0xc4d, 0x3b, 0xc0a, 0xc21, 0xc3e, 0xc2c, 0xc39, 0xc37, 0xc4d,
+0xc1f, 0xc4d, 0x3b, 0xc16, 0xc4b, 0xc30, 0xc4d, 0xc21, 0xc3e, 0xc21, 0xc4d, 0x3b,
+0xc1f, 0xc3f, 0xc30, 0xc4d, 0x3b, 0xc2e, 0xc46, 0xc30, 0xc4d, 0xc21, 0xc3e, 0xc21,
+0xc4d, 0x3b, 0xc36, 0xc36, 0xc3f, 0xc35, 0xc30, 0xc4d, 0x3b, 0xc2e, 0xc46, 0xc39,
+0xc30, 0xc4d, 0x3b, 0xc05, 0xc2c, 0xc28, 0xc4d, 0x3b, 0xc05, 0xc1c, 0xc30, 0xc4d,
+0x3b, 0xc21, 0xc47, 0x3b, 0xc2c, 0xc3e, 0xc39, 0xc4d, 0x200c, 0xc2e, 0xc3e, 0xc28,
+0xc4d, 0x3b, 0xc0e, 0xc38, 0xc4d, 0x200c, 0xc2b, 0xc3e, 0xc02, 0xc21, 0xc4d, 0xe1f,
+0xe32, 0xe23, 0xe4c, 0xe27, 0xe32, 0xe23, 0xe4c, 0xe14, 0xe34, 0xe19, 0x3b, 0xe2d,
+0xe2d, 0xe23, 0xe4c, 0xe14, 0xe34, 0xe40, 0xe1a, 0xe40, 0xe2e, 0xe0a, 0xe15, 0xe4c,
+0x3b, 0xe04, 0xe2d, 0xe23, 0xe4c, 0xe41, 0xe14, 0xe14, 0x3b, 0xe40, 0xe15, 0xe2d,
+0xe23, 0xe4c, 0x3b, 0xe21, 0xe2d, 0xe23, 0xe4c, 0xe41, 0xe14, 0xe14, 0x3b, 0xe0a,
+0xe32, 0xe2b, 0xe23, 0xe34, 0xe27, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe40, 0xe21, 0xe2e,
+0xe23, 0xe4c, 0x3b, 0xe2d, 0xe30, 0xe1a, 0xe32, 0xe19, 0x3b, 0xe2d, 0xe30, 0xe0b,
+0xe32, 0xe23, 0xe4c, 0x3b, 0xe40, 0xe14, 0xe22, 0xe4c, 0x3b, 0xe1a, 0xe32, 0xe2e,
+0xe4c, 0xe21, 0xe32, 0xe19, 0x3b, 0xe40, 0xe2d, 0xe2a, 0xe1f, 0xe32, 0xe19, 0xe14,
+0xe4c, 0x46, 0x65, 0x72, 0x76, 0x65, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x4f,
+0x72, 0x64, 0x69, 0x62, 0x65, 0x68, 0x65, 0x15f, 0x74, 0x3b, 0x48, 0x6f,
+0x72, 0x64, 0x61, 0x64, 0x3b, 0x54, 0x69, 0x72, 0x3b, 0x4d, 0x6f, 0x72,
+0x64, 0x61, 0x64, 0x3b, 0x15e, 0x65, 0x68, 0x72, 0x69, 0x76, 0x65, 0x72,
+0x3b, 0x4d, 0x65, 0x68, 0x72, 0x3b, 0x41, 0x62, 0x61, 0x6e, 0x3b, 0x41,
+0x7a, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x79, 0x3b, 0x42, 0x65, 0x68, 0x6d,
+0x65, 0x6e, 0x3b, 0x45, 0x73, 0x66, 0x65, 0x6e, 0x64, 0x444, 0x430, 0x440,
+0x432, 0x430, 0x440, 0x434, 0x456, 0x43d, 0x3b, 0x43e, 0x440, 0x434, 0x456, 0x431,
+0x435, 0x445, 0x435, 0x448, 0x442, 0x3b, 0x445, 0x43e, 0x440, 0x434, 0x430, 0x434,
+0x3b, 0x442, 0x456, 0x440, 0x3b, 0x43c, 0x43e, 0x440, 0x434, 0x430, 0x434, 0x3b,
+0x448, 0x430, 0x445, 0x440, 0x456, 0x432, 0x435, 0x440, 0x3b, 0x43c, 0x435, 0x445,
+0x440, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x435, 0x440, 0x3b,
+0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x43c, 0x430, 0x43d, 0x3b, 0x435,
+0x441, 0x444, 0x430, 0x43d, 0x434, 0x444, 0x430, 0x440, 0x3b, 0x43e, 0x440, 0x434,
+0x3b, 0x445, 0x43e, 0x440, 0x3b, 0x442, 0x456, 0x440, 0x3b, 0x43c, 0x43e, 0x440,
+0x3b, 0x448, 0x430, 0x445, 0x3b, 0x43c, 0x435, 0x445, 0x3b, 0x430, 0x431, 0x430,
+0x43d, 0x3b, 0x430, 0x437, 0x435, 0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431,
+0x430, 0x445, 0x3b, 0x435, 0x441, 0x444, 0x444, 0x430, 0x440, 0x2e, 0x3b, 0x43e,
+0x440, 0x434, 0x2e, 0x3b, 0x445, 0x43e, 0x440, 0x2e, 0x3b, 0x442, 0x456, 0x440,
+0x3b, 0x43c, 0x43e, 0x440, 0x2e, 0x3b, 0x448, 0x430, 0x445, 0x2e, 0x3b, 0x43c,
+0x435, 0x445, 0x2e, 0x3b, 0x430, 0x431, 0x430, 0x43d, 0x3b, 0x430, 0x437, 0x435,
+0x440, 0x3b, 0x434, 0x435, 0x439, 0x3b, 0x431, 0x430, 0x445, 0x2e, 0x3b, 0x435,
+0x441, 0x444, 0x2e, 0x641, 0x631, 0x648, 0x631, 0x62f, 0x646, 0x3b, 0x622, 0x631,
+0x688, 0x628, 0x627, 0x626, 0x634, 0x3b, 0x62e, 0x62f, 0x627, 0x62f, 0x627, 0x62f,
+0x3b, 0x62a, 0x6cc, 0x631, 0x3b, 0x645, 0x631, 0x62f, 0x627, 0x62f, 0x3b, 0x634,
+0x6c1, 0x631, 0x6cc, 0x648, 0x627, 0x631, 0x3b, 0x645, 0x6c1, 0x631, 0x3b, 0x627,
+0x628, 0x627, 0x646, 0x3b, 0x622, 0x632, 0x631, 0x3b, 0x688, 0x6d2, 0x3b, 0x628,
+0x6c1, 0x645, 0x646, 0x3b, 0x627, 0x633, 0x641, 0x646, 0x62f, 0x66, 0x61, 0x72,
+0x76, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x2bb, 0x72, 0x64, 0x69,
+0x62, 0x65, 0x68, 0x69, 0x73, 0x68, 0x74, 0x3b, 0x78, 0x75, 0x72, 0x64,
+0x6f, 0x64, 0x3b, 0x74, 0x75, 0x72, 0x3b, 0x6d, 0x75, 0x72, 0x64, 0x6f,
+0x64, 0x3b, 0x73, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b,
+0x6d, 0x65, 0x68, 0x72, 0x3b, 0x6f, 0x62, 0x6f, 0x6e, 0x3b, 0x6f, 0x7a,
+0x61, 0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61,
+0x6e, 0x3b, 0x69, 0x73, 0x66, 0x61, 0x6e, 0x64, 0x66, 0x61, 0x72, 0x76,
+0x61, 0x72, 0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x2bb, 0x72, 0x64, 0x69, 0x62,
+0x65, 0x68, 0x69, 0x73, 0x68, 0x74, 0x3b, 0x78, 0x75, 0x72, 0x64, 0x6f,
+0x64, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6d, 0x75, 0x72, 0x64, 0x6f, 0x64,
+0x3b, 0x73, 0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d,
+0x65, 0x68, 0x72, 0x3b, 0x6f, 0x62, 0x6f, 0x6e, 0x3b, 0x6f, 0x7a, 0x61,
+0x72, 0x3b, 0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e,
+0x3b, 0x69, 0x73, 0x66, 0x61, 0x6e, 0x66, 0x61, 0x72, 0x76, 0x61, 0x72,
+0x64, 0x69, 0x6e, 0x3b, 0x6f, 0x2bb, 0x72, 0x64, 0x69, 0x62, 0x65, 0x68,
+0x69, 0x73, 0x68, 0x74, 0x3b, 0x78, 0x75, 0x72, 0x64, 0x6f, 0x64, 0x3b,
+0x74, 0x69, 0x72, 0x3b, 0x6d, 0x75, 0x72, 0x64, 0x6f, 0x64, 0x3b, 0x73,
+0x68, 0x61, 0x68, 0x72, 0x69, 0x76, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x68,
+0x72, 0x3b, 0x6f, 0x62, 0x6f, 0x6e, 0x3b, 0x6f, 0x7a, 0x61, 0x72, 0x3b,
+0x64, 0x65, 0x79, 0x3b, 0x62, 0x61, 0x68, 0x6d, 0x61, 0x6e, 0x3b, 0x69,
+0x73, 0x66, 0x61, 0x6e, 0x64
};
// GENERATED PART ENDS HERE
+} // namespace QtPrivate::Jalali
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/time/qjalalicalendar_p.h b/src/corelib/time/qjalalicalendar_p.h
index 77b87a36b3..51c89fe297 100644
--- a/src/corelib/time/qjalalicalendar_p.h
+++ b/src/corelib/time/qjalalicalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJALALI_CALENDAR_P_H
#define QJALALI_CALENDAR_P_H
@@ -60,10 +24,9 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QJalaliCalendar : public QCalendarBackend
{
public:
- QJalaliCalendar();
// Calendar properties:
QString name() const override;
- QCalendar::System calendarSystem() const override;
+ static QStringList nameList();
// Date queries:
int daysInMonth(int month, int year = QCalendar::Unspecified) const override;
bool isLeapYear(int year) const override;
diff --git a/src/corelib/time/qjuliancalendar.cpp b/src/corelib/time/qjuliancalendar.cpp
index 8c6818eb31..1439ae3e00 100644
--- a/src/corelib/time/qjuliancalendar.cpp
+++ b/src/corelib/time/qjuliancalendar.cpp
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qjuliancalendar_p.h"
#include "qromancalendar_data_p.h"
#include "qcalendarmath_p.h"
-#include <QtCore/qmath.h>
-#include <QtCore/qlocale.h>
+
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
@@ -75,17 +38,14 @@ using namespace QRoundingDown;
Julian Calendar}
*/
-QJulianCalendar::QJulianCalendar()
- : QRomanCalendar(QStringLiteral("Julian"), QCalendar::System::Julian) {}
-
QString QJulianCalendar::name() const
{
return QStringLiteral("Julian");
}
-QCalendar::System QJulianCalendar::calendarSystem() const
+QStringList QJulianCalendar::nameList()
{
- return QCalendar::System::Julian;
+ return { QStringLiteral("Julian") };
}
bool QJulianCalendar::isLeapYear(int year) const
@@ -93,36 +53,32 @@ bool QJulianCalendar::isLeapYear(int year) const
if (year == QCalendar::Unspecified || !year)
return false;
- return qMod(year < 0 ? year + 1 : year, 4) == 0;
+ return qMod<4>(year < 0 ? year + 1 : year) == 0;
}
-// Julian Day 0 was January the first in the proleptic Julian calendar's 4713 BC
+// Julian Day 0 was January the first in the proleptic Julian calendar's 4713 BC.
+using namespace QRomanCalendrical;
+// End a Julian four-year cycle on 1 BC's leap day (Gregorian Feb 27th):
+constexpr qint64 JulianBaseJd = LeapDayGregorian1Bce - 2;
bool QJulianCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const
{
Q_ASSERT(jd);
if (!isDateValid(year, month, day))
return false;
- if (year < 0)
- ++year;
- const qint64 c0 = month < 3 ? -1 : 0;
- const qint64 j1 = qDiv(1461 * (year + c0), 4);
- const qint64 j2 = qDiv(153 * month - 1836 * c0 - 457, 5);
- *jd = j1 + j2 + day + 1721117;
+
+ const auto yearDays = yearMonthToYearDays(year, month);
+ *jd = qDiv<4>(FourYears * yearDays.year) + yearDays.days + day + JulianBaseJd;
return true;
}
QCalendar::YearMonthDay QJulianCalendar::julianDayToDate(qint64 jd) const
{
- const qint64 y2 = jd - 1721118;
- const qint64 k2 = 4 * y2 + 3;
- const qint64 k1 = 5 * qDiv(qMod(k2, 1461), 4) + 2;
- const qint64 x1 = qDiv(k1, 153);
- const qint64 c0 = qDiv(x1 + 2, 12);
- const int y = qint16(qDiv(k2, 1461) + c0);
- const int month = quint8(x1 - 12 * c0 + 3);
- const int day = qDiv(qMod(k1, 153), 5) + 1;
- return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);
+ const auto year4Day = qDivMod<FourYears>(4 * (jd - JulianBaseJd) - 1);
+ // Its remainder changes by 4 per day, except at roughly yearly quotient steps.
+ const auto ymd = dayInYearToYmd(qDiv<4>(year4Day.remainder));
+ const int y = year4Day.quotient + ymd.year;
+ return QCalendar::YearMonthDay(y > 0 ? y : y - 1, ymd.month, ymd.day);
}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qjuliancalendar_p.h b/src/corelib/time/qjuliancalendar_p.h
index 104cf6aa30..95850fd4f9 100644
--- a/src/corelib/time/qjuliancalendar_p.h
+++ b/src/corelib/time/qjuliancalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJULIAN_CALENDAR_P_H
#define QJULIAN_CALENDAR_P_H
@@ -58,10 +22,9 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QJulianCalendar : public QRomanCalendar
{
public:
- QJulianCalendar();
// Calendar properties:
QString name() const override;
- QCalendar::System calendarSystem() const override;
+ static QStringList nameList();
// Date queries:
bool isLeapYear(int year) const override;
// Julian Day conversions:
diff --git a/src/corelib/time/qlocaltime.cpp b/src/corelib/time/qlocaltime.cpp
new file mode 100644
index 0000000000..609a5a4b37
--- /dev/null
+++ b/src/corelib/time/qlocaltime.cpp
@@ -0,0 +1,720 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qlocaltime_p.h"
+#include "qplatformdefs.h"
+
+#include "private/qcalendarmath_p.h"
+#if QT_CONFIG(datetimeparser)
+#include "private/qdatetimeparser_p.h"
+#endif
+#include "private/qgregoriancalendar_p.h"
+#include "private/qnumeric_p.h"
+#include "private/qtenvironmentvariables_p.h"
+#if QT_CONFIG(timezone)
+#include "private/qtimezoneprivate_p.h"
+#endif
+
+#include <time.h>
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
+#ifdef __GLIBC__ // Extends struct tm with some extra fields:
+#define HAVE_TM_GMTOFF // tm_gmtoff is the UTC offset.
+#define HAVE_TM_ZONE // tm_zone is the zone abbreviation.
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace QtPrivate::DateTimeConstants;
+namespace {
+/*
+ Qt represents n BCE as -n, whereas struct tm's tm_year field represents a
+ year by the number of years after (negative for before) 1900, so that 1+m
+ BCE is -1900 -m; so treating 1 BCE as 0 CE. We thus shift by different
+ offsets depending on whether the year is BCE or CE.
+*/
+constexpr int tmYearFromQYear(int year) { return year - (year < 0 ? 1899 : 1900); }
+constexpr int qYearFromTmYear(int year) { return year + (year < -1899 ? 1899 : 1900); }
+
+constexpr inline qint64 tmSecsWithinDay(const struct tm &when)
+{
+ return (when.tm_hour * MINS_PER_HOUR + when.tm_min) * SECS_PER_MIN + when.tm_sec;
+}
+
+/* Call mktime() and make sense of the result.
+
+ This packages the call to mktime() with the needed determination of whether
+ that succeeded and whether the call has materially perturbed, including
+ normalizing, the struct tm it was passed (as opposed to merely filling in
+ details).
+*/
+class MkTimeResult
+{
+ // mktime()'s return on error; or last second of 1969 UTC:
+ static constexpr time_t maybeError = -1;
+ inline bool meansEnd1969();
+ bool changed(const struct tm &prior) const;
+
+public:
+ struct tm local = {}; // Describes the local time in familiar form.
+ time_t utcSecs = maybeError; // Seconds since UTC epoch.
+ bool good = false; // Ignore the rest unless this is true.
+ bool adjusted = true; // Is local at odds with prior ?
+ MkTimeResult() { local.tm_isdst = -1; }
+
+ // Note: the calls to qMkTime() and meansEnd1969() potentially modify local.
+ explicit MkTimeResult(const struct tm &prior)
+ : local(prior), utcSecs(qMkTime(&local)),
+ good(utcSecs != maybeError || meansEnd1969()),
+ adjusted(changed(prior))
+ {}
+};
+
+/* If mktime() returns -1, is it really an error ?
+
+ It might return -1 because we're looking at the last second of 1969 and
+ mktime does support times before 1970 (POSIX says "If the year is <1970 or
+ the value is negative, the relationship is undefined" and MS rejects the
+ value, consistent with that; so we don't call mktime() on MS in this case and
+ can't get -1 unless it's a real error). However, on UNIX, that's -1 UTC time
+ and all we know, aside from mktime's return, is the local time. (We could
+ check errno, but we call mktime from within a qt_scoped_lock(QBasicMutex),
+ whose unlocking and destruction of the locker might frob errno.)
+
+ We can assume time-zone offsets are less than a day, so this can only arise
+ if the struct tm describes either the last day of 1969 or the first day of
+ 1970. When we do know the offset (a glibc extension supplies it as a member
+ of struct tm), we can determine whether we're on the last second of the day,
+ refining that check. That makes for a cheap pre-test; if it holds, we can ask
+ mktime() about the preceding second; if it gives us -2, then the -1 we
+ originally saw is not (or at least didn't need to be) an error. We can then
+ synthesize a corrected value for local using the -2 result.
+*/
+inline bool MkTimeResult::meansEnd1969()
+{
+#ifdef Q_OS_WIN
+ return false;
+#else
+ if (local.tm_year < 69 || local.tm_year > 70
+# ifdef HAVE_TM_GMTOFF
+ // Africa/Monrovia had offset 00:44:30 at the epoch, so (although all
+ // other zones' offsets were round multiples of five minutes) we need
+ // the offset to determine whether the time might match:
+ || (tmSecsWithinDay(local) - local.tm_gmtoff + 1) % SECS_PER_DAY
+# endif
+ || (local.tm_year == 69 // ... and less than a day:
+ ? local.tm_mon < 11 || local.tm_mday < 31
+ : local.tm_mon > 0 || local.tm_mday > 1)) {
+ return false;
+ }
+ struct tm copy = local;
+ copy.tm_sec--; // Preceding second should get -2, not -1
+ if (qMkTime(&copy) != -2)
+ return false;
+ // The original call to qMkTime() may have returned -1 as failure, not
+ // updating local, even though it could have; so fake it here. Assumes there
+ // was no transition in the last minute of the day !
+ local = copy;
+ local.tm_sec++; // Advance back to the intended second
+ return true;
+#endif
+}
+
+bool MkTimeResult::changed(const struct tm &prior) const
+{
+ // If mktime() has been passed a copy of prior and local is its value on
+ // return, this checks whether mktime() has made a material change
+ // (including normalization) to the value, as opposed to merely filling in
+ // the fields that it's specified to fill in. It returns true if there has
+ // been any material change.
+ return !(prior.tm_year == local.tm_year && prior.tm_mon == local.tm_mon
+ && prior.tm_mday == local.tm_mday && prior.tm_hour == local.tm_hour
+ && prior.tm_min == local.tm_min && prior.tm_sec == local.tm_sec
+ && (prior.tm_isdst == -1
+ ? local.tm_isdst >= 0 : prior.tm_isdst == local.tm_isdst));
+}
+
+struct tm timeToTm(qint64 localDay, int secs)
+{
+ Q_ASSERT(0 <= secs && secs < SECS_PER_DAY);
+ const auto ymd = QGregorianCalendar::partsFromJulian(JULIAN_DAY_FOR_EPOCH + localDay);
+ struct tm local = {};
+ local.tm_year = tmYearFromQYear(ymd.year);
+ local.tm_mon = ymd.month - 1;
+ local.tm_mday = ymd.day;
+ local.tm_hour = secs / 3600;
+ local.tm_min = (secs % 3600) / 60;
+ local.tm_sec = (secs % 60);
+ local.tm_isdst = -1;
+ return local;
+}
+
+// Transitions account for a small fraction of 1% of the time.
+// So mark functions only used in handling them as cold.
+Q_DECL_COLD_FUNCTION
+struct tm matchYearMonth(struct tm when, const struct tm &base)
+{
+ // Adjust *when to be a denormal representation of the same point in time
+ // but with tm_year and tm_mon the same as base. In practice this will
+ // represent an adjacent month, so don't worry too much about optimising for
+ // any other case; we almost certainly run zero or one iteration of one of
+ // the year loops then zero or one iteration of one of the month loops.
+ while (when.tm_year > base.tm_year) {
+ --when.tm_year;
+ when.tm_mon += 12;
+ }
+ while (when.tm_year < base.tm_year) {
+ ++when.tm_year;
+ when.tm_mon -= 12;
+ }
+ Q_ASSERT(when.tm_year == base.tm_year);
+ while (when.tm_mon > base.tm_mon) {
+ const auto yearMon = QRoundingDown::qDivMod<12>(when.tm_mon);
+ int year = yearMon.quotient;
+ // We want the month before's Qt month number, which is the tm_mon mod 12:
+ int month = yearMon.remainder;
+ if (month == 0) {
+ --year;
+ month = 12;
+ }
+ year += when.tm_year;
+ when.tm_mday += QGregorianCalendar::monthLength(month, qYearFromTmYear(year));
+ --when.tm_mon;
+ }
+ while (when.tm_mon < base.tm_mon) {
+ const auto yearMon = QRoundingDown::qDivMod<12>(when.tm_mon);
+ // Qt month number is offset from tm_mon by one:
+ when.tm_mday -= QGregorianCalendar::monthLength(
+ yearMon.remainder + 1, qYearFromTmYear(yearMon.quotient + when.tm_year));
+ ++when.tm_mon;
+ }
+ Q_ASSERT(when.tm_mon == base.tm_mon);
+ return when;
+}
+
+Q_DECL_COLD_FUNCTION
+struct tm adjacentDay(struct tm when, int dayStep)
+{
+ // Before we adjust it, when is a return from timeToTm(), so in normal form.
+ Q_ASSERT(dayStep * dayStep == 1);
+ when.tm_mday += dayStep;
+ // That may have bumped us across a month boundary or even a year one.
+ // So now we normalize it.
+
+ if (dayStep < 0) {
+ if (when.tm_mday <= 0) {
+ // Month before's day-count; but tm_mon's value is one less than Qt's
+ // month numbering so, before we decrement it, it has the value we need,
+ // unless it's 0.
+ int daysInMonth = when.tm_mon
+ ? QGregorianCalendar::monthLength(when.tm_mon, qYearFromTmYear(when.tm_year))
+ : QGregorianCalendar::monthLength(12, qYearFromTmYear(when.tm_year - 1));
+ when.tm_mday += daysInMonth;
+ if (--when.tm_mon < 0) {
+ --when.tm_year;
+ when.tm_mon = 11;
+ }
+ Q_ASSERT(when.tm_mday >= 1);
+ }
+ } else if (when.tm_mday > 28) {
+ // We have to wind through months one at a time, since their lengths vary.
+ int daysInMonth = QGregorianCalendar::monthLength(
+ when.tm_mon + 1, qYearFromTmYear(when.tm_year));
+ if (when.tm_mday > daysInMonth) {
+ when.tm_mday -= daysInMonth;
+ if (++when.tm_mon > 11) {
+ ++when.tm_year;
+ when.tm_mon = 0;
+ }
+ Q_ASSERT(when.tm_mday <= QGregorianCalendar::monthLength(
+ when.tm_mon + 1, qYearFromTmYear(when.tm_year)));
+ }
+ }
+ return when;
+}
+
+Q_DECL_COLD_FUNCTION
+qint64 secondsBetween(const struct tm &start, const struct tm &stop)
+{
+ // Nominal difference between start and stop, in seconds (negative if start
+ // is after stop); may differ from actual UTC difference if there's a
+ // transition between them.
+ struct tm from = matchYearMonth(start, stop);
+ qint64 diff = stop.tm_mday - from.tm_mday; // in days
+ diff = diff * 24 + stop.tm_hour - from.tm_hour; // in hours
+ diff = diff * 60 + stop.tm_min - from.tm_min; // in minutes
+ return diff * 60 + stop.tm_sec - from.tm_sec; // in seconds
+}
+
+Q_DECL_COLD_FUNCTION
+MkTimeResult hopAcrossGap(const MkTimeResult &outside, const struct tm &base)
+{
+ // base fell in a gap; outside is one resolution
+ // This returns the other resolution, if possible.
+ const qint64 shift = secondsBetween(outside.local, base);
+ struct tm across;
+ // Shift is the nominal time adjustment between outside and base; now obtain
+ // the actual time that far from outside:
+ if (qLocalTime(outside.utcSecs + shift, &across)) {
+ const qint64 wider = secondsBetween(outside.local, across);
+ // That should be bigger than shift (typically by a factor of two), in
+ // the same direction:
+ if (shift > 0 ? wider > shift : wider < shift) {
+ MkTimeResult result(across);
+ if (result.good && !result.adjusted)
+ return result;
+ }
+ }
+ // This can surely only arise if the other resolution lies outside the
+ // time_t-range supported by the system functions.
+ return {};
+}
+
+Q_DECL_COLD_FUNCTION
+MkTimeResult resolveRejected(struct tm base, MkTimeResult result,
+ QDateTimePrivate::TransitionOptions resolve)
+{
+ // May result from a time outside the supported range of system time_t
+ // functions, or from a gap (on a platform where mktime() rejects them).
+ // QDateTime filters on times well outside the supported range, but may
+ // pass values only slightly outside the range.
+
+ // The easy case - no need to find a resolution anyway:
+ if (!resolve.testAnyFlags(QDateTimePrivate::GapMask))
+ return {};
+
+ constexpr time_t twoDaysInSeconds = 2 * 24 * 60 * 60;
+ // Bracket base, one day each side (in case the zone skipped a whole day):
+ MkTimeResult early(adjacentDay(base, -1));
+ MkTimeResult later(adjacentDay(base, +1));
+ if (!early.good || !later.good) // Assume out of range, rather than gap.
+ return {};
+
+ // OK, looks like a gap.
+ Q_ASSERT(twoDaysInSeconds + early.utcSecs > later.utcSecs);
+ result.adjusted = true;
+
+ // Extrapolate backwards from later if this option is set:
+ QDateTimePrivate::TransitionOption beforeLater = QDateTimePrivate::GapUseBefore;
+ if (resolve.testFlag(QDateTimePrivate::FlipForReverseDst)) {
+ // Reverse DST has DST before a gap and not after:
+ if (early.local.tm_isdst == 1 && !later.local.tm_isdst)
+ beforeLater = QDateTimePrivate::GapUseAfter;
+ }
+ if (resolve.testFlag(beforeLater)) // Result will be before the gap:
+ result.utcSecs = later.utcSecs - secondsBetween(base, later.local);
+ else // Result will be after the gap:
+ result.utcSecs = early.utcSecs + secondsBetween(early.local, base);
+
+ if (!qLocalTime(result.utcSecs, &result.local)) // Abandon hope.
+ return {};
+
+ return result;
+}
+
+Q_DECL_COLD_FUNCTION
+bool preferAlternative(QDateTimePrivate::TransitionOptions resolve,
+ // is_dst flags of incumbent and an alternative:
+ int gotDst, int altDst,
+ // True precisely if alternative selects a later UTC time:
+ bool altIsLater,
+ // True for a gap, false for a fold:
+ bool inGap)
+{
+ // If resolve has this option set, prefer the later candidate, else the earlier:
+ QDateTimePrivate::TransitionOption preferLater = inGap ? QDateTimePrivate::GapUseAfter
+ : QDateTimePrivate::FoldUseAfter;
+ if (resolve.testFlag(QDateTimePrivate::FlipForReverseDst)) {
+ // gotDst and altDst are {-1: unknown, 0: standard, 1: daylight-saving}
+ // So gotDst ^ altDst is 1 precisely if exactly one candidate thinks it's DST.
+ if ((altDst ^ gotDst) == 1) {
+ // In this case, we can tell whether we have reversed DST: that's a
+ // gap with DST before it or a fold with DST after it.
+#if 1
+ const bool isReversed = (altDst == 1) != (altIsLater == inGap);
+#else // Pedagogic version of the same thing:
+ bool isReversed;
+ if (altIsLater == inGap) // alt is after a gap or before a fold, so summer-time
+ isReversed = altDst != 1; // flip if summer-time isn't DST
+ else // alt is before a gap or after a fold, so winter-time
+ isReversed = altDst == 1; // flip if winter-time is DST
+#endif
+ if (isReversed) {
+ preferLater = inGap ? QDateTimePrivate::GapUseBefore
+ : QDateTimePrivate::FoldUseBefore;
+ }
+ } // Otherwise, we can't tell, so assume not.
+ }
+ return resolve.testFlag(preferLater) == altIsLater;
+}
+
+/*
+ Determine UTC time and offset, if possible, at a given local time.
+
+ The local time is specified as a number of seconds since the epoch (so, in
+ effect, a time_t, albeit delivered as qint64). If the specified local time
+ falls in a transition, resolve determines what to do.
+
+ If the specified local time is outside what the system time_t APIs will
+ handle, this fails.
+*/
+MkTimeResult resolveLocalTime(qint64 local, QDateTimePrivate::TransitionOptions resolve)
+{
+ const auto localDaySecs = QRoundingDown::qDivMod<SECS_PER_DAY>(local);
+ struct tm base = timeToTm(localDaySecs.quotient, localDaySecs.remainder);
+
+ // Get provisional result (correct > 99.9 % of the time):
+ MkTimeResult result(base);
+
+ // Our callers (mostly) deal with questions of being within the range that
+ // system time_t functions can handle, and timeToTm() gave us data in
+ // normalized form, so the only excuse for !good or a change to the HH:mm:ss
+ // fields (aside from being at the boundary of time_t's supported range) is
+ // that we hit a gap, although we have to handle these cases differently:
+ if (!result.good) {
+ // Rejected. The tricky case: maybe mktime() doesn't resolve gaps.
+ return resolveRejected(base, result, resolve);
+ } else if (result.local.tm_isdst < 0) {
+ // Apparently success without knowledge of whether this is DST or not.
+ // Should not happen, but that means our usual understanding of what the
+ // system is up to has gone out the window. So just let it be.
+ } else if (result.adjusted) {
+ // Shunted out of a gap.
+ if (!resolve.testAnyFlags(QDateTimePrivate::GapMask)) {
+ result = {};
+ return result;
+ }
+
+ // Try to obtain a matching point on the other side of the gap:
+ const MkTimeResult flipped = hopAcrossGap(result, base);
+ // Even if that failed, result may be the correct resolution
+
+ if (preferAlternative(resolve, result.local.tm_isdst, flipped.local.tm_isdst,
+ flipped.utcSecs > result.utcSecs, true)) {
+ // If hopAcrossGap() failed and we do need its answer, give up.
+ if (!flipped.good || flipped.adjusted)
+ return {};
+
+ // As resolution of local, flipped involves adjustment (across gap):
+ result = flipped;
+ result.adjusted = true;
+ }
+ } else if (resolve.testFlag(QDateTimePrivate::FlipForReverseDst)
+ // In fold, DST counts as before and standard as after -
+ // we may not need to check whether we're in a transition:
+ && resolve.testFlag(result.local.tm_isdst ? QDateTimePrivate::FoldUseBefore
+ : QDateTimePrivate::FoldUseAfter)) {
+ // We prefer DST or standard and got what we wanted, so we're good.
+ // As below, but we don't need to check, because we're on the side of
+ // the transition that it would select as valid, if we were near one.
+ // NB: this branch is routinely exercised, when QDT::Data::isShort()
+ // obliges us to rediscover an offsetFromUtc that ShortData has no space
+ // to store, as it does remember the DST status we got before.
+ } else {
+ // What we gave was valid. However, it might have been in a fall-back.
+ // If so, the same input but with tm_isdst flipped should also be valid.
+ struct tm copy = base;
+ copy.tm_isdst = !result.local.tm_isdst;
+ const MkTimeResult flipped(copy);
+ if (flipped.good && !flipped.adjusted) {
+ // We're in a fall-back
+ if (!resolve.testAnyFlags(QDateTimePrivate::FoldMask)) {
+ result = {};
+ return result;
+ }
+
+ // Work out which repeat to use:
+ if (preferAlternative(resolve, result.local.tm_isdst, flipped.local.tm_isdst,
+ flipped.utcSecs > result.utcSecs, false)) {
+ result = flipped;
+ }
+ } // else: not in a transition, nothing to worry about.
+ }
+ return result;
+}
+
+inline std::optional<qint64> tmToJd(const struct tm &date)
+{
+ return QGregorianCalendar::julianFromParts(qYearFromTmYear(date.tm_year),
+ date.tm_mon + 1, date.tm_mday);
+}
+
+#define IC(N) std::integral_constant<qint64, N>()
+
+// True if combining day and seconds overflows qint64; otherwise, sets *epochSeconds
+inline bool daysAndSecondsOverflow(qint64 julianDay, qint64 daySeconds, qint64 *epochSeconds)
+{
+ return qMulOverflow(julianDay - JULIAN_DAY_FOR_EPOCH, IC(SECS_PER_DAY), epochSeconds)
+ || qAddOverflow(*epochSeconds, daySeconds, epochSeconds);
+}
+
+// True if combining seconds and millis overflows; otherwise sets *epochMillis
+inline bool secondsAndMillisOverflow(qint64 epochSeconds, qint64 millis, qint64 *epochMillis)
+{
+ return qMulOverflow(epochSeconds, IC(MSECS_PER_SEC), epochMillis)
+ || qAddOverflow(*epochMillis, millis, epochMillis);
+}
+
+#undef IC
+
+} // namespace
+
+namespace QLocalTime {
+
+#ifndef QT_BOOTSTRAPPED
+// Even if local time is currently in DST, this returns the standard time offset
+// (in seconds) nominally in effect at present:
+int getCurrentStandardUtcOffset()
+{
+#ifdef Q_OS_WIN
+ TIME_ZONE_INFORMATION tzInfo;
+ if (GetTimeZoneInformation(&tzInfo) != TIME_ZONE_ID_INVALID) {
+ int bias = tzInfo.Bias; // In minutes.
+ // StandardBias is usually zero, but include it if given:
+ if (tzInfo.StandardDate.wMonth) // Zero month means ignore StandardBias.
+ bias += tzInfo.StandardBias;
+ // MS's bias is +ve in the USA, so minutes *behind* UTC - we want seconds *ahead*:
+ return -bias * SECS_PER_MIN;
+ }
+#else
+ qTzSet();
+ const time_t curr = time(nullptr);
+ if (curr != -1) {
+ /* Set t to the UTC representation of curr; the time whose local
+ standard time representation coincides with that differs from curr by
+ local time's standard offset. Note that gmtime() leaves the tm_isdst
+ flag set to 0, so mktime() will, even if local time is currently
+ using DST, return the time since epoch at which local standard time
+ would have the same representation as UTC's representation of
+ curr. The fact that mktime() also flips tm_isdst and updates the time
+ fields to the DST-equivalent time needn't concern us here; all that
+ matters is that it returns the time after epoch at which standard
+ time's representation would have matched UTC's, had it been in
+ effect.
+ */
+# if defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ struct tm t;
+ if (gmtime_r(&curr, &t)) {
+ time_t mkt = qMkTime(&t);
+ int offset = int(curr - mkt);
+ Q_ASSERT(std::abs(offset) <= SECS_PER_DAY);
+ return offset;
+ }
+# else
+ if (struct tm *tp = gmtime(&curr)) {
+ struct tm t = *tp; // Copy it quick, hopefully before it can get stomped
+ time_t mkt = qMkTime(&t);
+ int offset = int(curr - mkt);
+ Q_ASSERT(std::abs(offset) <= SECS_PER_DAY);
+ return offset;
+ }
+# endif
+ } // else, presumably: errno == EOVERFLOW
+#endif // Platform choice
+ qDebug("Unable to determine current standard time offset from UTC");
+ // We can't tell, presume UTC.
+ return 0;
+}
+
+// This is local time's offset (in seconds), at the specified time, including
+// any DST part.
+int getUtcOffset(qint64 atMSecsSinceEpoch)
+{
+ return QDateTimePrivate::expressUtcAsLocal(atMSecsSinceEpoch).offset;
+}
+#endif // QT_BOOTSTRAPPED
+
+// Calls the platform variant of localtime() for the given utcMillis, and
+// returns the local milliseconds, offset from UTC and DST status.
+QDateTimePrivate::ZoneState utcToLocal(qint64 utcMillis)
+{
+ const auto epoch = QRoundingDown::qDivMod<MSECS_PER_SEC>(utcMillis);
+ const time_t epochSeconds = epoch.quotient;
+ const int msec = epoch.remainder;
+ Q_ASSERT(msec >= 0 && msec < MSECS_PER_SEC);
+ if (qint64(epochSeconds) * MSECS_PER_SEC + msec != utcMillis) // time_t range too narrow
+ return {utcMillis};
+
+ tm local;
+ if (!qLocalTime(epochSeconds, &local))
+ return {utcMillis};
+
+ auto jd = tmToJd(local);
+ if (Q_UNLIKELY(!jd))
+ return {utcMillis};
+
+ const qint64 daySeconds = tmSecsWithinDay(local);
+ Q_ASSERT(0 <= daySeconds && daySeconds < SECS_PER_DAY);
+ qint64 localSeconds, localMillis;
+ if (Q_UNLIKELY(daysAndSecondsOverflow(*jd, daySeconds, &localSeconds)
+ || secondsAndMillisOverflow(localSeconds, qint64(msec), &localMillis))) {
+ return {utcMillis};
+ }
+ const auto dst
+ = local.tm_isdst ? QDateTimePrivate::DaylightTime : QDateTimePrivate::StandardTime;
+ return { localMillis, int(localSeconds - epochSeconds), dst };
+}
+
+QString localTimeAbbbreviationAt(qint64 local, QDateTimePrivate::TransitionOptions resolve)
+{
+ auto use = resolveLocalTime(QRoundingDown::qDiv<MSECS_PER_SEC>(local), resolve);
+ if (!use.good)
+ return {};
+#ifdef HAVE_TM_ZONE
+ if (use.local.tm_zone)
+ return QString::fromLocal8Bit(use.local.tm_zone);
+#endif
+ return qTzName(use.local.tm_isdst > 0 ? 1 : 0);
+}
+
+QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::TransitionOptions resolve)
+{
+ // Revised later to match what use.local tells us:
+ qint64 localSecs = local / MSECS_PER_SEC;
+ auto use = resolveLocalTime(localSecs, resolve);
+ if (!use.good)
+ return {local};
+
+ qint64 millis = local - localSecs * MSECS_PER_SEC;
+ // Division is defined to round towards zero:
+ Q_ASSERT(local < 0 ? (millis <= 0 && millis > -MSECS_PER_SEC)
+ : (millis >= 0 && millis < MSECS_PER_SEC));
+
+ QDateTimePrivate::DaylightStatus dst =
+ use.local.tm_isdst > 0 ? QDateTimePrivate::DaylightTime : QDateTimePrivate::StandardTime;
+
+#ifdef HAVE_TM_GMTOFF
+ const int offset = use.local.tm_gmtoff;
+ localSecs = offset + use.utcSecs;
+#else
+ // Provisional offset, until we have a revised localSecs:
+ int offset = localSecs - use.utcSecs;
+ auto jd = tmToJd(use.local);
+ if (Q_UNLIKELY(!jd))
+ return {local, offset, dst, false};
+
+ qint64 daySecs = tmSecsWithinDay(use.local);
+ Q_ASSERT(0 <= daySecs && daySecs < SECS_PER_DAY);
+ if (daySecs > 0 && *jd < JULIAN_DAY_FOR_EPOCH) {
+ jd = *jd + 1;
+ daySecs -= SECS_PER_DAY;
+ }
+ if (Q_UNLIKELY(daysAndSecondsOverflow(*jd, daySecs, &localSecs)))
+ return {local, offset, dst, false};
+
+ // Use revised localSecs to refine offset:
+ offset = localSecs - use.utcSecs;
+#endif // HAVE_TM_GMTOFF
+
+ // The only way localSecs and millis can now have opposite sign is for
+ // resolution of the local time to have kicked us across the epoch, in which
+ // case there's no danger of overflow. So if overflow is in danger of
+ // happening, we're already doing the best we can to avoid it.
+ qint64 revised;
+ if (secondsAndMillisOverflow(localSecs, millis, &revised))
+ return {local, offset, QDateTimePrivate::UnknownDaylightTime, false};
+ return {revised, offset, dst, true};
+}
+
+/*!
+ \internal
+ Determine the range of the system time_t functions.
+
+ On MS-systems (where time_t is 64-bit by default), the start-point is the
+ epoch, the end-point is the end of the year 3000 (for mktime(); for
+ _localtime64_s it's 18 days later, but we ignore that here). Darwin's range
+ runs from the beginning of 1900 to the end of its 64-bit time_t and Linux
+ uses the full range of time_t (but this might still be 32-bit on some
+ embedded systems).
+
+ (One potential constraint might appear to be the range of struct tm's int
+ tm_year, only allowing time_t to represent times from the start of year
+ 1900+INT_MIN to the end of year INT_MAX. The 26-bit number of seconds in a
+ year means that a 64-bit time_t can indeed represent times outside the range
+ of 32-bit years, by a factor of 32 - but the range of representable
+ milliseconds needs ten more bits than that of seconds, so can't reach the
+ ends of the 32-bit year range.)
+
+ Given the diversity of ranges, we conservatively estimate the actual
+ supported range by experiment on the first call to qdatetime.cpp's
+ millisInSystemRange() by exploration among the known candidates, converting
+ the result to milliseconds and flagging whether each end is the qint64
+ range's bound (so millisInSystemRange will know not to try to pad beyond
+ those bounds). The probed date-times are somewhat inside the range, but
+ close enough to the relevant bound that we can be fairly sure the bound is
+ reached, if the probe succeeds.
+*/
+SystemMillisRange computeSystemMillisRange()
+{
+ // Assert this here, as this is called just once, in a static initialization.
+ Q_ASSERT(QGregorianCalendar::julianFromParts(1970, 1, 1) == JULIAN_DAY_FOR_EPOCH);
+
+ constexpr qint64 TIME_T_MAX = std::numeric_limits<time_t>::max();
+ using Bounds = std::numeric_limits<qint64>;
+ constexpr bool isNarrow = Bounds::max() / MSECS_PER_SEC > TIME_T_MAX;
+ if constexpr (isNarrow) {
+ const qint64 msecsMax = quint64(TIME_T_MAX) * MSECS_PER_SEC - 1 + MSECS_PER_SEC;
+ const qint64 msecsMin = -1 - msecsMax; // TIME_T_MIN is -1 - TIME_T_MAX
+ // If we reach back to msecsMin, use it; otherwise, assume 1970 cut-off (MS).
+ struct tm local = {};
+ local.tm_year = tmYearFromQYear(1901);
+ local.tm_mon = 11;
+ local.tm_mday = 15; // A day and a bit after the start of 32-bit time_t:
+ local.tm_isdst = -1;
+ return {qMkTime(&local) == -1 ? 0 : msecsMin, msecsMax, false, false};
+ } else {
+ const struct { int year; qint64 millis; } starts[] = {
+ { int(QDateTime::YearRange::First) + 1, Bounds::min() },
+ // Beginning of the Common Era:
+ { 1, -Q_INT64_C(62135596800000) },
+ // Invention of the Gregorian calendar:
+ { 1582, -Q_INT64_C(12244089600000) },
+ // Its adoption by the anglophone world:
+ { 1752, -Q_INT64_C(6879427200000) },
+ // Before this, struct tm's tm_year is negative (Darwin):
+ { 1900, -Q_INT64_C(2208988800000) },
+ }, ends[] = {
+ { int(QDateTime::YearRange::Last) - 1, Bounds::max() },
+ // MS's end-of-range, end of year 3000:
+ { 3000, Q_INT64_C(32535215999999) },
+ };
+ // Assume we do at least reach the end of a signed 32-bit time_t (since
+ // our actual time_t is bigger than that):
+ qint64 stop =
+ quint64(std::numeric_limits<qint32>::max()) * MSECS_PER_SEC - 1 + MSECS_PER_SEC;
+ // Cleared if first pass round loop fails:
+ bool stopMax = true;
+ for (const auto c : ends) {
+ struct tm local = {};
+ local.tm_year = tmYearFromQYear(c.year);
+ local.tm_mon = 11;
+ local.tm_mday = 31;
+ local.tm_hour = 23;
+ local.tm_min = local.tm_sec = 59;
+ local.tm_isdst = -1;
+ if (qMkTime(&local) != -1) {
+ stop = c.millis;
+ break;
+ }
+ stopMax = false;
+ }
+ bool startMin = true;
+ for (const auto c : starts) {
+ struct tm local {};
+ local.tm_year = tmYearFromQYear(c.year);
+ local.tm_mon = 1;
+ local.tm_mday = 1;
+ local.tm_isdst = -1;
+ if (qMkTime(&local) != -1)
+ return {c.millis, stop, startMin, stopMax};
+ startMin = false;
+ }
+ return {0, stop, false, stopMax};
+ }
+}
+
+} // QLocalTime
+
+QT_END_NAMESPACE
diff --git a/src/corelib/time/qlocaltime_p.h b/src/corelib/time/qlocaltime_p.h
new file mode 100644
index 0000000000..5e31d5e9cc
--- /dev/null
+++ b/src/corelib/time/qlocaltime_p.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QLOCALTIME_P_H
+#define QLOCALTIME_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an implementation
+// detail. This header file may change from version to version without notice,
+// or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/private/qdatetime_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// Packaging system time_t functions
+namespace QLocalTime {
+#ifndef QT_BOOTSTRAPPED
+// Support for V4's Date implelenentation.
+// Each returns offset from UTC in seconds (or 0 if unknown).
+// V4 shall need to multiply by 1000.
+// Offset is -ve East of Greenwich, +ve west of Greenwich.
+// Add it to UTC seconds since epoch to get local seconds since nominal local epoch.
+Q_CORE_EXPORT int getCurrentStandardUtcOffset();
+Q_CORE_EXPORT int getUtcOffset(qint64 atMSecsSinceEpoch);
+#endif // QT_BOOTSTRAPPED
+
+// Support for QDateTime
+QDateTimePrivate::ZoneState utcToLocal(qint64 utcMillis);
+QString localTimeAbbbreviationAt(qint64 local, QDateTimePrivate::TransitionOptions resolve);
+QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::TransitionOptions resolve);
+
+struct SystemMillisRange { qint64 min, max; bool minClip, maxClip; };
+SystemMillisRange computeSystemMillisRange();
+}
+
+QT_END_NAMESPACE
+
+#endif // QLOCALTIME_P_H
diff --git a/src/corelib/time/qmilankoviccalendar.cpp b/src/corelib/time/qmilankoviccalendar.cpp
index 673713a266..a3ffa2a305 100644
--- a/src/corelib/time/qmilankoviccalendar.cpp
+++ b/src/corelib/time/qmilankoviccalendar.cpp
@@ -1,47 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qmilankoviccalendar_p.h"
#include "qcalendarmath_p.h"
-#include <QtCore/qmath.h>
-#include <QtCore/qlocale.h>
+
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
@@ -73,17 +36,14 @@ using namespace QRoundingDown;
page on Milanković Calendar}
*/
-QMilankovicCalendar::QMilankovicCalendar()
- : QRomanCalendar(QStringLiteral("Milankovic"), QCalendar::System::Milankovic) {}
-
QString QMilankovicCalendar::name() const
{
return QStringLiteral("Milankovic");
}
-QCalendar::System QMilankovicCalendar::calendarSystem() const
+QStringList QMilankovicCalendar::nameList()
{
- return QCalendar::System::Milankovic;
+ return { QStringLiteral("Milankovic") };
}
bool QMilankovicCalendar::isLeapYear(int year) const
@@ -92,48 +52,48 @@ bool QMilankovicCalendar::isLeapYear(int year) const
return false;
if (year <= 0)
++year;
- if (qMod(year, 4))
+ if (qMod<4>(year))
return false;
- if (qMod(year, 100) == 0) {
- const qint16 century = qMod(qDiv(year, 100), 9);
+ const auto yeardm = qDivMod<100>(year);
+ if (yeardm.remainder == 0) {
+ const qint16 century = qMod<9>(yeardm.quotient);
if (century != 2 && century != 6)
return false;
}
return true;
}
+using namespace QRomanCalendrical;
+// End a Milankovic nine-century cycle on 1 BC, Feb 28 (Gregorian Feb 29):
+constexpr qint64 MilankovicBaseJd = LeapDayGregorian1Bce;
+// Leap years every 4 years, except for 7 turn-of-century years per nine centuries:
+constexpr unsigned NineCenturies = 365 * 900 + 900 / 4 - 7;
+// When the turn-of-century is a leap year, the century has 25 leap years in it:
+constexpr unsigned LeapCentury = 365 * 100 + 25;
+
bool QMilankovicCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const
{
Q_ASSERT(jd);
if (!isDateValid(year, month, day))
return false;
- if (year <= 0)
- ++year;
- const qint16 c0 = month < 3 ? -1 : 0;
- const qint16 x1 = month - 12 * c0 - 3;
- const qint16 x4 = year + c0;
- const qint16 x3 = qDiv(x4, 100);
- const qint16 x2 = qMod(x4, 100);
- *jd = qDiv(328718 * x3 + 6, 9)
- + qDiv(36525 * x2 , 100)
- + qDiv(153 * x1 + 2 , 5)
- + day + 1721119;
+
+ const auto yearDays = yearMonthToYearDays(year, month);
+ const auto centuryYear = qDivMod<100>(yearDays.year);
+ const qint64 fromYear = qDiv<9>(NineCenturies * centuryYear.quotient + 6)
+ + qDiv<100>(LeapCentury * centuryYear.remainder);
+ *jd = fromYear + yearDays.days + day + MilankovicBaseJd;
return true;
}
QCalendar::YearMonthDay QMilankovicCalendar::julianDayToDate(qint64 jd) const
{
- const qint64 k3 = 9 * (jd - 1721120) + 2;
- const qint64 x3 = qDiv(k3, 328718);
- const qint64 k2 = 100 * qDiv(qMod(k3, 328718), 9) + 99;
- const qint64 k1 = qDiv(qMod(k2, 36525), 100) * 5 + 2;
- const qint64 x2 = qDiv(k2, 36525);
- const qint64 x1 = qDiv(5 * qDiv(qMod(k2, 36525), 100) + 2, 153);
- const qint64 c0 = qDiv(x1 + 2, 12);
- const int y = 100 * x3 + x2 + c0;
- const int month = x1 - 12 * c0 + 3;
- const int day = qDiv(qMod(k1, 153), 5) + 1;
- return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);
+ const auto century9Day = qDivMod<NineCenturies>(9 * (jd - MilankovicBaseJd) - 7);
+ // Its remainder changes by 9 per day, except roughly once per century.
+ const auto year100Day = qDivMod<LeapCentury>(100 * qDiv<9>(century9Day.remainder) + 99);
+ // Its remainder changes by 100 per day, except roughly once per year.
+ const auto ymd = dayInYearToYmd(qDiv<100>(year100Day.remainder));
+ const int y = 100 * century9Day.quotient + year100Day.quotient + ymd.year;
+ return QCalendar::YearMonthDay(y > 0 ? y : y - 1, ymd.month, ymd.day);
}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qmilankoviccalendar_p.h b/src/corelib/time/qmilankoviccalendar_p.h
index ebff7e7f39..c6797ac221 100644
--- a/src/corelib/time/qmilankoviccalendar_p.h
+++ b/src/corelib/time/qmilankoviccalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMILANKOVICCALENDAR_CALENDAR_P_H
#define QMILANKOVICCALENDAR_CALENDAR_P_H
@@ -58,10 +22,9 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QMilankovicCalendar : public QRomanCalendar
{
public:
- QMilankovicCalendar();
// Calendar properties:
QString name() const override;
- QCalendar::System calendarSystem() const override;
+ static QStringList nameList();
// Date queries:
bool isLeapYear(int year) const override;
// Julian Day conversions:
diff --git a/src/corelib/time/qromancalendar.cpp b/src/corelib/time/qromancalendar.cpp
index 98b53eb9cf..0a7399ea51 100644
--- a/src/corelib/time/qromancalendar.cpp
+++ b/src/corelib/time/qromancalendar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
#include "qromancalendar_p.h"
@@ -51,11 +15,10 @@ QT_BEGIN_NAMESPACE
\brief The QRomanCalendar class is a shared base for calendars based on the
ancient Roman calendar.
- \section1
-
- Calendars based on the ancient Roman calendar share the names of months,
- whose lengths depend in a common way on whether the year is a leap
- year. They differ in how they determine which years are leap years.
+ Calendars based on the ancient Roman calendar have several common properties:
+ they have the same names for months, the month lengths depend in a common
+ way on whether the year is a leap year. They differ in how they determine
+ which years are leap years.
\sa QGregorianCalendar, QJulianCalendar, QMilankovicCalendar
*/
@@ -94,12 +57,12 @@ bool QRomanCalendar::isSolar() const
const QCalendarLocale *QRomanCalendar::localeMonthIndexData() const
{
- return locale_data;
+ return QtPrivate::Roman::locale_data;
}
const char16_t *QRomanCalendar::localeMonthData() const
{
- return months_data;
+ return QtPrivate::Roman::months_data;
}
QT_END_NAMESPACE
diff --git a/src/corelib/time/qromancalendar_data_p.h b/src/corelib/time/qromancalendar_data_p.h
index 8a0ec14d49..320a19ccdc 100644
--- a/src/corelib/time/qromancalendar_data_p.h
+++ b/src/corelib/time/qromancalendar_data_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-3.0
#ifndef QROMANCALENDAR_DATA_P_H
#define QROMANCALENDAR_DATA_P_H
@@ -56,11 +20,13 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate::Roman {
+
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-04-07 from the
- Common Locale Data Repository v36
+ This part of the file was generated on 2024-01-09 from the
+ Common Locale Data Repository v44.1
http://www.unicode.org/cldr/
@@ -69,2594 +35,5052 @@ QT_BEGIN_NAMESPACE
edited) CLDR data; see qtbase/util/locale_database/.
*/
-static const QCalendarLocale locale_data[] = {
+static constexpr QCalendarLocale locale_data[] = {
// lang script terr sLong long sShrt short sNarw narow Sizes...
- { 1, 0, 0, 0, 0, 85, 85, 132, 155, 85, 85, 47, 47, 23, 26 },// C/AnyScript/AnyCountry
- { 3, 7, 69, 181, 181, 291, 291, 132, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Ethiopia
- { 3, 7, 111, 181, 181, 291, 291, 338, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Kenya
- { 4, 7, 69, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Afar/Latin/Ethiopia
- { 5, 7, 195, 408, 408, 499, 499, 132, 132, 91, 91, 58, 58, 23, 23 },// Afrikaans/Latin/South Africa
- { 5, 7, 148, 408, 408, 499, 499, 132, 132, 91, 91, 58, 58, 23, 23 },// Afrikaans/Latin/Namibia
- { 6, 7, 2, 557, 557, 634, 634, 683, 683, 77, 77, 49, 49, 26, 26 },// Albanian/Latin/Albania
- { 6, 7, 127, 557, 557, 634, 634, 683, 683, 77, 77, 49, 49, 26, 26 },// Albanian/Latin/Macedonia
- { 6, 7, 257, 557, 557, 634, 634, 683, 683, 77, 77, 49, 49, 26, 26 },// Albanian/Latin/Kosovo
- { 7, 14, 69, 709, 709, 769, 769, 814, 814, 60, 60, 45, 45, 23, 23 },// Amharic/Ethiopic/Ethiopia
- { 8, 1, 64, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Egypt
- { 8, 1, 3, 934, 934, 934, 934, 1004, 1004, 70, 70, 70, 70, 23, 23 },// Arabic/Arabic/Algeria
- { 8, 1, 17, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Bahrain
- { 8, 1, 42, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Chad
- { 8, 1, 48, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Comoros
- { 8, 1, 59, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Djibouti
- { 8, 1, 67, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Eritrea
- { 8, 1, 103, 1027, 1027, 1027, 1118, 1209, 1209, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Iraq
- { 8, 1, 105, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Israel
- { 8, 1, 109, 1027, 1027, 1027, 1027, 1209, 1209, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Jordan
- { 8, 1, 115, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Kuwait
- { 8, 1, 119, 1027, 1027, 1027, 1027, 1209, 1209, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Lebanon
- { 8, 1, 122, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Libya
- { 8, 1, 136, 1232, 1232, 1232, 1232, 1303, 1303, 71, 71, 71, 71, 23, 23 },// Arabic/Arabic/Mauritania
- { 8, 1, 145, 1326, 1326, 1326, 1326, 1395, 1395, 69, 69, 69, 69, 23, 23 },// Arabic/Arabic/Morocco
- { 8, 1, 162, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Oman
- { 8, 1, 165, 1027, 1027, 1027, 1027, 1209, 1209, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Palestinian Territories
- { 8, 1, 175, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Qatar
- { 8, 1, 186, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Saudi Arabia
- { 8, 1, 194, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Somalia
- { 8, 1, 201, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Sudan
- { 8, 1, 207, 1027, 1027, 1027, 1027, 1209, 1209, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Syria
- { 8, 1, 216, 934, 934, 934, 934, 1004, 1004, 70, 70, 70, 70, 23, 23 },// Arabic/Arabic/Tunisia
- { 8, 1, 223, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/United Arab Emirates
- { 8, 1, 236, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Western Sahara
- { 8, 1, 237, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Yemen
- { 8, 1, 254, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/South Sudan
- { 8, 1, 260, 837, 837, 837, 837, 911, 911, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/World
- { 9, 10, 11, 1418, 1511, 1616, 1616, 1663, 1663, 93,105, 47, 47, 23, 23 },// Armenian/Armenian/Armenia
- { 10, 11, 100, 1686, 1686, 1774, 1774, 1837, 1837, 88, 88, 63, 63, 23, 23 },// Assamese/Bengali/India
- { 12, 7, 15, 1860, 1936, 2012, 2012, 155, 155, 76, 76, 47, 47, 26, 26 },// Azerbaijani/Latin/Azerbaijan
- { 12, 1, 102, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Azerbaijani/Arabic/Iran
- { 12, 2, 15, 2059, 2135, 2211, 2211, 155, 155, 76, 76, 47, 47, 26, 26 },// Azerbaijani/Cyrillic/Azerbaijan
- { 13, 2, 178, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Bashkir/Cyrillic/Russia
- { 14, 7, 197, 2258, 2258, 2350, 2350, 2409, 2409, 92, 92, 59, 59, 23, 23 },// Basque/Latin/Spain
- { 15, 11, 18, 2432, 2432, 2432, 2521, 2597, 2597, 89, 89, 89, 76, 32, 32 },// Bengali/Bengali/Bangladesh
- { 15, 11, 100, 2432, 2432, 2432, 2521, 2597, 2597, 89, 89, 89, 76, 32, 32 },// Bengali/Bengali/India
- { 16, 31, 25, 2629, 2819, 2950, 3012, 3038, 3064,190,131, 62, 26, 26, 26 },// Dzongkha/Tibetan/Bhutan
- { 19, 7, 74, 3090, 3090, 3167, 3167, 3229, 3229, 77, 77, 62, 62, 35, 35 },// Breton/Latin/France
- { 20, 2, 33, 3264, 3264, 3345, 3345, 3393, 3393, 81, 81, 48, 48, 23, 23 },// Bulgarian/Cyrillic/Bulgaria
- { 21, 25, 147, 3416, 3416, 3503, 3503, 3545, 3545, 87, 87, 42, 42, 23, 23 },// Burmese/Myanmar/Myanmar
- { 22, 2, 20, 3568, 3662, 3759, 3806, 3853, 3853, 94, 97, 47, 47, 23, 23 },// Belarusian/Cyrillic/Belarus
- { 23, 20, 36, 3876, 3876, 3876, 3876, 3946, 3946, 70, 70, 70, 70, 23, 23 },// Khmer/Khmer/Cambodia
- { 24, 7, 197, 3969, 4050, 4164, 4223, 4315, 4315, 81,114, 59, 92, 35, 35 },// Catalan/Latin/Spain
- { 24, 7, 5, 3969, 4050, 4164, 4223, 4315, 4315, 81,114, 59, 92, 35, 35 },// Catalan/Latin/Andorra
- { 24, 7, 74, 3969, 4050, 4164, 4223, 4315, 4315, 81,114, 59, 92, 35, 35 },// Catalan/Latin/France
- { 24, 7, 106, 3969, 4050, 4164, 4223, 4315, 4315, 81,114, 59, 92, 35, 35 },// Catalan/Latin/Italy
- { 25, 5, 44, 4350, 4350, 4387, 4387, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/China
- { 25, 5, 97, 4350, 4350, 4387, 4387, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Hong Kong
- { 25, 5, 126, 4350, 4350, 4387, 4387, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Macau
- { 25, 5, 190, 4350, 4350, 4387, 4387, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Singapore
- { 25, 6, 97, 4387, 4387, 4387, 4387, 155, 155, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Hong Kong
- { 25, 6, 126, 4387, 4387, 4387, 4387, 155, 155, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Macau
- { 25, 6, 208, 4387, 4387, 4387, 4387, 155, 155, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Taiwan
- { 26, 7, 74, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Corsican/Latin/France
- { 27, 7, 54, 4425, 4518, 4615, 4615, 4663, 4663, 93, 97, 48, 48, 38, 38 },// Croatian/Latin/Croatia
- { 27, 7, 27, 4425, 4518, 4615, 4615, 4663, 4663, 93, 97, 48, 48, 38, 38 },// Croatian/Latin/Bosnia And Herzegowina
- { 28, 7, 57, 4701, 4782, 4865, 4865, 155, 155, 81, 83, 47, 47, 26, 26 },// Czech/Latin/Czech Republic
- { 29, 7, 58, 4912, 4912, 4995, 4995, 132, 132, 83, 83, 58, 58, 23, 23 },// Danish/Latin/Denmark
- { 29, 7, 86, 4912, 4912, 4995, 4995, 132, 132, 83, 83, 58, 58, 23, 23 },// Danish/Latin/Greenland
- { 30, 7, 151, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Netherlands
- { 30, 7, 12, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Aruba
- { 30, 7, 21, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Belgium
- { 30, 7, 152, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Cura Sao
- { 30, 7, 202, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Suriname
- { 30, 7, 255, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Bonaire
- { 30, 7, 256, 5053, 5053, 5140, 5140, 132, 132, 87, 87, 58, 58, 23, 23 },// Dutch/Latin/Sint Maarten
- { 31, 7, 225, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United States
- { 31, 3, 225, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// English/Deseret/United States
- { 31, 7, 4, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/American Samoa
- { 31, 7, 7, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Anguilla
- { 31, 7, 9, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Antigua And Barbuda
- { 31, 7, 13, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Australia
- { 31, 7, 14, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Austria
- { 31, 7, 16, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Bahamas
- { 31, 7, 19, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Barbados
- { 31, 7, 21, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Belgium
- { 31, 7, 22, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Belize
- { 31, 7, 24, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Bermuda
- { 31, 7, 28, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Botswana
- { 31, 7, 31, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/British Indian Ocean Territory
- { 31, 7, 35, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Burundi
- { 31, 7, 37, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Cameroon
- { 31, 7, 38, 0, 0, 5198, 5198, 132, 132, 85, 85, 58, 58, 23, 23 },// English/Latin/Canada
- { 31, 7, 40, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Cayman Islands
- { 31, 7, 45, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Christmas Island
- { 31, 7, 46, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Cocos Islands
- { 31, 7, 51, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Cook Islands
- { 31, 7, 56, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Cyprus
- { 31, 7, 58, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Denmark
- { 31, 7, 60, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Dominica
- { 31, 7, 67, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Eritrea
- { 31, 7, 70, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Falkland Islands
- { 31, 7, 72, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Fiji
- { 31, 7, 73, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Finland
- { 31, 7, 75, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Guernsey
- { 31, 7, 80, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Gambia
- { 31, 7, 82, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Germany
- { 31, 7, 83, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Ghana
- { 31, 7, 84, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Gibraltar
- { 31, 7, 87, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Grenada
- { 31, 7, 89, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Guam
- { 31, 7, 93, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Guyana
- { 31, 7, 97, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Hong Kong
- { 31, 7, 100, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/India
- { 31, 7, 104, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Ireland
- { 31, 7, 105, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Israel
- { 31, 7, 107, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Jamaica
- { 31, 7, 111, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Kenya
- { 31, 7, 112, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Kiribati
- { 31, 7, 120, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Lesotho
- { 31, 7, 121, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Liberia
- { 31, 7, 126, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Macau
- { 31, 7, 128, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Madagascar
- { 31, 7, 129, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Malawi
- { 31, 7, 130, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Malaysia
- { 31, 7, 133, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Malta
- { 31, 7, 134, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Marshall Islands
- { 31, 7, 137, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Mauritius
- { 31, 7, 140, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Micronesia
- { 31, 7, 144, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Montserrat
- { 31, 7, 148, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Namibia
- { 31, 7, 149, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Nauru
- { 31, 7, 151, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Netherlands
- { 31, 7, 154, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/New Zealand
- { 31, 7, 157, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Nigeria
- { 31, 7, 158, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Niue
- { 31, 7, 159, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Norfolk Island
- { 31, 7, 160, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Northern Mariana Islands
- { 31, 7, 163, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Pakistan
- { 31, 7, 164, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Palau
- { 31, 7, 167, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Papua New Guinea
- { 31, 7, 170, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Philippines
- { 31, 7, 171, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Pitcairn
- { 31, 7, 174, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Puerto Rico
- { 31, 7, 179, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Rwanda
- { 31, 7, 180, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Saint Kitts And Nevis
- { 31, 7, 181, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Saint Lucia
- { 31, 7, 182, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Saint Vincent And The Grenadines
- { 31, 7, 183, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Samoa
- { 31, 7, 188, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Seychelles
- { 31, 7, 189, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Sierra Leone
- { 31, 7, 190, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Singapore
- { 31, 7, 192, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Slovenia
- { 31, 7, 193, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Solomon Islands
- { 31, 7, 195, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/South Africa
- { 31, 7, 199, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Saint Helena
- { 31, 7, 201, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Sudan
- { 31, 7, 204, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Swaziland
- { 31, 7, 205, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Sweden
- { 31, 7, 206, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Switzerland
- { 31, 7, 210, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Tanzania
- { 31, 7, 213, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Tokelau
- { 31, 7, 214, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Tonga
- { 31, 7, 215, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Trinidad And Tobago
- { 31, 7, 219, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Turks And Caicos Islands
- { 31, 7, 220, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Tuvalu
- { 31, 7, 221, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Uganda
- { 31, 7, 223, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United Arab Emirates
- { 31, 7, 224, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United Kingdom
- { 31, 7, 226, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United States Minor Outlying Islands
- { 31, 7, 229, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Vanuatu
- { 31, 7, 233, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/British Virgin Islands
- { 31, 7, 234, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United States Virgin Islands
- { 31, 7, 239, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Zambia
- { 31, 7, 240, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Zimbabwe
- { 31, 7, 249, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Diego Garcia
- { 31, 7, 251, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Isle Of Man
- { 31, 7, 252, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Jersey
- { 31, 7, 254, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/South Sudan
- { 31, 7, 256, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Sint Maarten
- { 31, 7, 260, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/World
- { 31, 7, 261, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Europe
- { 32, 7, 260, 5256, 5256, 5346, 5346, 132, 132, 90, 90, 47, 47, 23, 23 },// Esperanto/Latin/World
- { 33, 7, 68, 5393, 5393, 5483, 5483, 5541, 5541, 90, 90, 58, 58, 23, 23 },// Estonian/Latin/Estonia
- { 34, 7, 71, 5564, 5564, 5646, 5693, 132, 132, 82, 82, 47, 58, 23, 23 },// Faroese/Latin/Faroe Islands
- { 34, 7, 58, 5564, 5564, 5646, 5693, 132, 132, 82, 82, 47, 58, 23, 23 },// Faroese/Latin/Denmark
- { 36, 7, 73, 5751, 5855, 5983, 6051, 6143, 6143,104,128, 68, 92, 23, 23 },// Finnish/Latin/Finland
- { 37, 7, 74, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/France
- { 37, 7, 3, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Algeria
- { 37, 7, 21, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Belgium
- { 37, 7, 23, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Benin
- { 37, 7, 34, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Burkina Faso
- { 37, 7, 35, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Burundi
- { 37, 7, 37, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Cameroon
- { 37, 7, 38, 6166, 6166, 6312, 6312, 132, 132, 84, 84, 63, 63, 23, 23 },// French/Latin/Canada
- { 37, 7, 41, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Central African Republic
- { 37, 7, 42, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Chad
- { 37, 7, 48, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Comoros
- { 37, 7, 49, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Congo Kinshasa
- { 37, 7, 50, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Congo Brazzaville
- { 37, 7, 53, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Ivory Coast
- { 37, 7, 59, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Djibouti
- { 37, 7, 66, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Equatorial Guinea
- { 37, 7, 76, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/French Guiana
- { 37, 7, 77, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/French Polynesia
- { 37, 7, 79, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Gabon
- { 37, 7, 88, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Guadeloupe
- { 37, 7, 91, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Guinea
- { 37, 7, 94, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Haiti
- { 37, 7, 125, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Luxembourg
- { 37, 7, 128, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Madagascar
- { 37, 7, 132, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mali
- { 37, 7, 135, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Martinique
- { 37, 7, 136, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mauritania
- { 37, 7, 137, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mauritius
- { 37, 7, 138, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mayotte
- { 37, 7, 142, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Monaco
- { 37, 7, 145, 6166, 6166, 6375, 6375, 132, 132, 84, 84, 60, 60, 23, 23 },// French/Latin/Morocco
- { 37, 7, 153, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/New Caledonia
- { 37, 7, 156, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Niger
- { 37, 7, 176, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Reunion
- { 37, 7, 179, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Rwanda
- { 37, 7, 187, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Senegal
- { 37, 7, 188, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Seychelles
- { 37, 7, 200, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Saint Pierre And Miquelon
- { 37, 7, 206, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Switzerland
- { 37, 7, 207, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Syria
- { 37, 7, 212, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Togo
- { 37, 7, 216, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Tunisia
- { 37, 7, 229, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Vanuatu
- { 37, 7, 235, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Wallis And Futuna Islands
- { 37, 7, 244, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Saint Barthelemy
- { 37, 7, 245, 6166, 6166, 6250, 6250, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Saint Martin
- { 38, 7, 151, 6435, 6435, 6529, 6529, 132, 132, 94, 94, 47, 47, 23, 23 },// Western Frisian/Latin/Netherlands
- { 39, 7, 224, 6576, 6717, 6883, 6883, 6943, 6943,141,166, 60, 60, 23, 23 },// Gaelic/Latin/United Kingdom
- { 40, 7, 197, 6966, 7052, 7138, 7197, 7256, 7279, 86, 86, 59, 59, 23, 35 },// Galician/Latin/Spain
- { 41, 15, 81, 7314, 7314, 7412, 7412, 7459, 7459, 98, 98, 47, 47, 23, 23 },// Georgian/Georgian/Georgia
- { 42, 7, 82, 7482, 7482, 7564, 7611, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Germany
- { 42, 7, 14, 7670, 7670, 7752, 7799, 132, 132, 82, 82, 47, 58, 23, 23 },// German/Latin/Austria
- { 42, 7, 21, 7482, 7482, 7564, 7611, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Belgium
- { 42, 7, 106, 7670, 7670, 7752, 7799, 132, 132, 82, 82, 47, 58, 23, 23 },// German/Latin/Italy
- { 42, 7, 123, 7482, 7482, 7564, 7611, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Liechtenstein
- { 42, 7, 125, 7482, 7482, 7564, 7611, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Luxembourg
- { 42, 7, 206, 7482, 7482, 7564, 7611, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Switzerland
- { 43, 16, 85, 7857, 7971, 8085, 8134, 8183, 8183,114,114, 49, 49, 23, 23 },// Greek/Greek/Greece
- { 43, 16, 56, 7857, 7971, 8085, 8134, 8183, 8183,114,114, 49, 49, 23, 23 },// Greek/Greek/Cyprus
- { 44, 7, 86, 8206, 8304, 8414, 8414, 132, 132, 98,110, 49, 49, 23, 23 },// Greenlandic/Latin/Greenland
- { 45, 7, 168, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Guarani/Latin/Paraguay
- { 46, 17, 100, 8463, 8463, 8549, 8549, 8615, 8615, 86, 86, 66, 66, 30, 30 },// Gujarati/Gujarati/India
- { 47, 7, 157, 8645, 8645, 8729, 8729, 8776, 8776, 84, 84, 47, 47, 23, 23 },// Hausa/Latin/Nigeria
- { 47, 1, 157, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Hausa/Arabic/Nigeria
- { 47, 7, 83, 8645, 8645, 8729, 8729, 8776, 8776, 84, 84, 47, 47, 23, 23 },// Hausa/Latin/Ghana
- { 47, 7, 156, 8645, 8645, 8729, 8729, 8776, 8776, 84, 84, 47, 47, 23, 23 },// Hausa/Latin/Niger
- { 48, 18, 105, 8799, 8799, 8870, 8870, 155, 155, 71, 71, 57, 57, 26, 26 },// Hebrew/Hebrew/Israel
- { 49, 13, 100, 8927, 8927, 8999, 8999, 9057, 9057, 72, 72, 58, 58, 29, 29 },// Hindi/Devanagari/India
- { 50, 7, 98, 9086, 9086, 9183, 9183, 9246, 9246, 97, 97, 63, 63, 24, 24 },// Hungarian/Latin/Hungary
- { 51, 7, 99, 9270, 9270, 9351, 9351, 9409, 9409, 81, 81, 58, 58, 23, 23 },// Icelandic/Latin/Iceland
- { 52, 7, 101, 9432, 9432, 9518, 9518, 132, 132, 86, 86, 47, 47, 23, 23 },// Indonesian/Latin/Indonesia
- { 53, 7, 260, 9565, 9565, 9657, 9657, 155, 9704, 92, 92, 47, 47, 26, 23 },// Interlingua/Latin/World
- { 55, 44, 38, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Inuktitut/Canadian Aboriginal/Canada
- { 55, 7, 38, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Inuktitut/Latin/Canada
- { 57, 7, 104, 9727, 9727, 9833, 9833, 9894, 9894,106,106, 61, 61, 23, 23 },// Irish/Latin/Ireland
- { 57, 7, 224, 9727, 9727, 9833, 9833, 9894, 9894,106,106, 61, 61, 23, 23 },// Irish/Latin/United Kingdom
- { 58, 7, 106, 9917, 9917,10010,10010,10057,10057, 93, 93, 47, 47, 23, 23 },// Italian/Latin/Italy
- { 58, 7, 184, 9917, 9917,10010,10010,10057,10057, 93, 93, 47, 47, 23, 23 },// Italian/Latin/San Marino
- { 58, 7, 206, 9917, 9917,10010,10010,10057,10057, 93, 93, 47, 47, 23, 23 },// Italian/Latin/Switzerland
- { 58, 7, 230, 9917, 9917,10010,10010,10057,10057, 93, 93, 47, 47, 23, 23 },// Italian/Latin/Vatican City State
- { 59, 19, 108, 4387, 4387, 4387, 4387, 155, 155, 38, 38, 38, 38, 26, 26 },// Japanese/Japanese/Japan
- { 60, 7, 101, 9432, 9432,10080,10080, 132, 132, 86, 86, 47, 47, 23, 23 },// Javanese/Latin/Indonesia
- { 61, 21, 100,10127,10127,10213,10275,10343,10343, 86, 86, 62, 68, 30, 30 },// Kannada/Kannada/India
- { 62, 1, 100,10373,10373,10373,10373,10444,10444, 71, 71, 71, 71, 23, 23 },// Kashmiri/Arabic/India
- { 63, 2, 110,10467,10549,10631,10631,10690,10690, 82, 82, 59, 59, 23, 23 },// Kazakh/Cyrillic/Kazakhstan
- { 64, 7, 179,10713,10713,10813,10813, 155, 155,100,100, 59, 59, 26, 26 },// Kinyarwanda/Latin/Rwanda
- { 65, 2, 116,10872,10951,11030,11077,11135,11135, 79, 79, 47, 58, 23, 23 },// Kirghiz/Cyrillic/Kyrgyzstan
- { 66, 22, 114,11158,11158,11158,11158,11158,11158, 38, 38, 38, 38, 38, 38 },// Korean/Korean/South Korea
- { 66, 22, 113,11158,11158,11158,11158,11158,11158, 38, 38, 38, 38, 38, 38 },// Korean/Korean/North Korea
- { 67, 7, 217,11196,11283,11383,11383,11430,11430, 87,100, 47, 47, 23, 23 },// Kurdish/Latin/Turkey
- { 68, 7, 35,11453,11453,11558,11558, 155, 155,105,105, 59, 59, 26, 26 },// Rundi/Latin/Burundi
- { 69, 23, 117,11617,11617,11691,11691, 155, 155, 74, 74, 60, 60, 26, 26 },// Lao/Lao/Laos
- { 71, 7, 118,11751,11751,11851,11851, 132, 132,100,100, 64, 64, 23, 23 },// Latvian/Latin/Latvia
- { 72, 7, 49,11915,11915,12117,12117,12164,12164,202,202, 47, 47, 23, 23 },// Lingala/Latin/Congo Kinshasa
- { 72, 7, 6,11915,11915,12117,12117,12164,12164,202,202, 47, 47, 23, 23 },// Lingala/Latin/Angola
- { 72, 7, 41,11915,11915,12117,12117,12164,12164,202,202, 47, 47, 23, 23 },// Lingala/Latin/Central African Republic
- { 72, 7, 50,11915,11915,12117,12117,12164,12164,202,202, 47, 47, 23, 23 },// Lingala/Latin/Congo Brazzaville
- { 73, 7, 124,12187,12282,12379,12379,12448,12448, 95, 97, 69, 69, 23, 23 },// Lithuanian/Latin/Lithuania
- { 74, 2, 127,12471,12471,12555,12555,12615,12615, 84, 84, 60, 60, 23, 23 },// Macedonian/Cyrillic/Macedonia
- { 75, 7, 128,12638,12638,12729,12729, 132, 132, 91, 91, 47, 47, 23, 23 },// Malagasy/Latin/Madagascar
- { 76, 7, 130,12776,12776,12857,12857,12904,12904, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Malaysia
- { 76, 1, 130, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Malay/Arabic/Malaysia
- { 76, 7, 32,12776,12776,12857,12857,12904,12904, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Brunei
- { 76, 7, 190,12776,12776,12857,12857,12904,12904, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Singapore
- { 77, 24, 100,12927,12927,13014,13014,13075,13075, 87, 87, 61, 61, 31, 31 },// Malayalam/Malayalam/India
- { 78, 7, 133,13106,13106,13191,13191,13238,13273, 85, 85, 47, 47, 35, 23 },// Maltese/Latin/Malta
- { 79, 7, 154,13296,13296,13428,13428,13486,13486,132,132, 58, 58, 23, 23 },// Maori/Latin/New Zealand
- { 80, 13, 100,13509,13509,13594,13594,13659,13659, 85, 85, 65, 65, 31, 31 },// Marathi/Devanagari/India
- { 82, 2, 143,13690,13881,14072,14072,14170,14170,191,191, 98, 98, 37, 37 },// Mongolian/Cyrillic/Mongolia
- { 82, 8, 44, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Mongolian/Mongolian/China
- { 84, 13, 150,14207,14207,14207,14207,14291,14343, 84, 84, 84, 84, 52, 51 },// Nepali/Devanagari/Nepal
- { 84, 13, 100,14207,14207,14207,14207,14291,14343, 84, 84, 84, 84, 52, 51 },// Nepali/Devanagari/India
- { 85, 7, 161,14394,14394, 5646, 5693, 132, 132, 82, 82, 47, 58, 23, 23 },// Norwegian Bokmal/Latin/Norway
- { 85, 7, 203,14394,14394, 5646, 5693, 132, 132, 82, 82, 47, 58, 23, 23 },// Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands
- { 86, 7, 74, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Occitan/Latin/France
- { 87, 26, 100,14476,14476,14476,14476,14561,14561, 85, 85, 85, 85, 31, 31 },// Oriya/Oriya/India
- { 88, 1, 1,14592,14660,14728,14660, 155,14795, 68, 68, 67, 68, 26, 23 },// Pashto/Arabic/Afghanistan
- { 88, 1, 163,14592,14660,14728,14660, 155,14795, 68, 68, 67, 68, 26, 23 },// Pashto/Arabic/Pakistan
- { 89, 1, 102,14818,14887,14818,14887,14960,14960, 69, 73, 69, 73, 23, 23 },// Persian/Arabic/Iran
- { 89, 1, 1,14983,14983,14983,15050,14795,14795, 67, 67, 67, 61, 23, 23 },// Persian/Arabic/Afghanistan
- { 90, 7, 172,15111,15207,15305,15305,15352,15375, 96, 98, 47, 47, 23, 23 },// Polish/Latin/Poland
- { 91, 7, 30,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Brazil
- { 91, 7, 6,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Angola
- { 91, 7, 39,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Cape Verde
- { 91, 7, 62,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/East Timor
- { 91, 7, 66,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Equatorial Guinea
- { 91, 7, 92,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Guinea Bissau
- { 91, 7, 125,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Luxembourg
- { 91, 7, 126,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Macau
- { 91, 7, 146,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Mozambique
- { 91, 7, 173,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Portugal
- { 91, 7, 185,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Sao Tome And Principe
- { 91, 7, 206,15398,15398,15486,15486, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Switzerland
- { 92, 4, 100,15545,15545,15612,15612,15661,15661, 67, 67, 49, 49, 27, 27 },// Punjabi/Gurmukhi/India
- { 92, 1, 163,15688,15688,15688,15688, 155, 155, 66, 66, 66, 66, 26, 26 },// Punjabi/Arabic/Pakistan
- { 93, 7, 169,15754,15754,15841,15841, 155, 155, 87, 87, 47, 47, 26, 26 },// Quechua/Latin/Peru
- { 93, 7, 26,15754,15754,15841,15841, 155, 155, 87, 87, 47, 47, 26, 26 },// Quechua/Latin/Bolivia
- { 93, 7, 63,15754,15754,15841,15841, 155, 155, 87, 87, 47, 47, 26, 26 },// Quechua/Latin/Ecuador
- { 94, 7, 206,15888,15979,16103,16103,16169,16169, 91,124, 66, 66, 23, 23 },// Romansh/Latin/Switzerland
- { 95, 7, 177,16192,16192,16289,16289,16348,16348, 97, 97, 59, 59, 23, 23 },// Romanian/Latin/Romania
- { 95, 7, 141,16192,16192,16289,16289,16348,16348, 97, 97, 59, 59, 23, 23 },// Romanian/Latin/Moldova
- { 96, 2, 178,10951,16371,16452,16513,11135,11135, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Russia
- { 96, 2, 20,10951,16371,16452,16513,11135,11135, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Belarus
- { 96, 2, 110,10951,16371,16452,16513,11135,11135, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Kazakhstan
- { 96, 2, 116,10951,16371,16452,16513,11135,11135, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Kyrgyzstan
- { 96, 2, 141,10951,16371,16452,16513,11135,11135, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Moldova
- { 96, 2, 222,10951,16371,16452,16513,11135,11135, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Ukraine
- { 98, 7, 41,16574,16574,16664,16664,16711,16711, 90, 90, 47, 47, 23, 23 },// Sango/Latin/Central African Republic
- { 99, 13, 100, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Sanskrit/Devanagari/India
- { 100, 2, 243,16734,16734,16814,16814,12615,12615, 80, 80, 47, 47, 23, 23 },// Serbian/Cyrillic/Serbia
- { 100, 7, 27,16861,16861,16941,16941, 9704, 9704, 80, 80, 47, 47, 23, 23 },// Serbian/Latin/Bosnia And Herzegowina
- { 100, 7, 242,16861,16861,16988,16988, 9704, 9704, 80, 80, 49, 49, 23, 23 },// Serbian/Latin/Montenegro
- { 100, 7, 243,16861,16861,16941,16941, 9704, 9704, 80, 80, 47, 47, 23, 23 },// Serbian/Latin/Serbia
- { 100, 2, 27,16734,16734,16814,16814,12615,12615, 80, 80, 47, 47, 23, 23 },// Serbian/Cyrillic/Bosnia And Herzegowina
- { 100, 2, 242,16734,16734,17037,17037,12615,12615, 80, 80, 49, 49, 23, 23 },// Serbian/Cyrillic/Montenegro
- { 100, 2, 257,16734,16734,17037,17037,12615,12615, 80, 80, 49, 49, 23, 23 },// Serbian/Cyrillic/Kosovo
- { 100, 7, 257,16861,16861,16988,16988, 9704, 9704, 80, 80, 49, 49, 23, 23 },// Serbian/Latin/Kosovo
- { 101, 2, 81,17086,17167,17252,17314,11135,11135, 81, 85, 62, 59, 23, 23 },// Ossetic/Cyrillic/Georgia
- { 101, 2, 178,17086,17167,17252,17314,11135,11135, 81, 85, 62, 59, 23, 23 },// Ossetic/Cyrillic/Russia
- { 102, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Sotho/Latin/South Africa
- { 103, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Tswana/Latin/South Africa
- { 104, 7, 240,17373,17373,17472,17472,17519,17519, 99, 99, 47, 47, 23, 23 },// Shona/Latin/Zimbabwe
- { 105, 1, 163,17542,17542,17542,17542, 132, 132, 71, 71, 71, 71, 23, 23 },// Sindhi/Arabic/Pakistan
- { 106, 32, 198,17613,17613,17708,17766,17826,17826, 95, 95, 58, 60, 31, 31 },// Sinhala/Sinhala/Sri Lanka
- { 107, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Swati/Latin/South Africa
- { 108, 7, 191,17857,17938,18026,18026, 9704, 9704, 81, 88, 47, 47, 23, 23 },// Slovak/Latin/Slovakia
- { 109, 7, 192,18073,18073,18158,18158, 9704, 9704, 85, 85, 58, 58, 23, 23 },// Slovenian/Latin/Slovenia
- { 110, 7, 194,18216,18307,18495,18495,18542,18542, 91,188, 47, 47, 23, 23 },// Somali/Latin/Somalia
- { 110, 7, 59,18216,18307,18495,18495,18542,18542, 91,188, 47, 47, 23, 23 },// Somali/Latin/Djibouti
- { 110, 7, 69,18216,18307,18495,18495,18542,18542, 91,188, 47, 47, 23, 23 },// Somali/Latin/Ethiopia
- { 110, 7, 111,18216,18307,18495,18495,18542,18542, 91,188, 47, 47, 23, 23 },// Somali/Latin/Kenya
- { 111, 7, 197,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Spain
- { 111, 7, 10,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Argentina
- { 111, 7, 22,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Belize
- { 111, 7, 26,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Bolivia
- { 111, 7, 30,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Brazil
- { 111, 7, 43,18565,18565,18653,18736,18713,18713, 88, 88, 60, 59, 23, 23 },// Spanish/Latin/Chile
- { 111, 7, 47,18565,18565,18653,18736,18713,18713, 88, 88, 60, 59, 23, 23 },// Spanish/Latin/Colombia
- { 111, 7, 52,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Costa Rica
- { 111, 7, 55,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Cuba
- { 111, 7, 61,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Dominican Republic
- { 111, 7, 63,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Ecuador
- { 111, 7, 65,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/El Salvador
- { 111, 7, 66,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Equatorial Guinea
- { 111, 7, 90,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Guatemala
- { 111, 7, 96,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Honduras
- { 111, 7, 139,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Mexico
- { 111, 7, 155,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Nicaragua
- { 111, 7, 166,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Panama
- { 111, 7, 168,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Paraguay
- { 111, 7, 169,15754,18795,18882,18941,18713,18713, 87, 87, 59, 59, 23, 23 },// Spanish/Latin/Peru
- { 111, 7, 170,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Philippines
- { 111, 7, 174,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Puerto Rico
- { 111, 7, 225,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/United States
- { 111, 7, 227,15754,18795,18882,18941,18713,18713, 87, 87, 59, 59, 23, 23 },// Spanish/Latin/Uruguay
- { 111, 7, 231,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Venezuela
- { 111, 7, 238,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Canary Islands
- { 111, 7, 246,18565,18565,18736,18736,18713,18713, 88, 88, 59, 59, 23, 23 },// Spanish/Latin/Latin America
- { 111, 7, 250,18565,18565,18653,18653,18713,18713, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Ceuta And Melilla
- { 112, 7, 101, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Sundanese/Latin/Indonesia
- { 113, 7, 210,19000,19000,19083,19083, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Tanzania
- { 113, 7, 49,19000,19000,19083,19083, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Congo Kinshasa
- { 113, 7, 111,19000,19000,19083,19083, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Kenya
- { 113, 7, 221,19000,19000,19083,19083, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Uganda
- { 114, 7, 205,19130,19130,19215,19215, 132, 132, 85, 85, 58, 58, 23, 23 },// Swedish/Latin/Sweden
- { 114, 7, 73,19130,19130,19215,19215, 132, 132, 85, 85, 58, 58, 23, 23 },// Swedish/Latin/Finland
- { 114, 7, 248,19130,19130,19215,19215, 132, 132, 85, 85, 58, 58, 23, 23 },// Swedish/Latin/Aland Islands
- { 115, 7, 106, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Sardinian/Latin/Italy
- { 116, 2, 209,19273,19273,11030,11030,11135,11135, 70, 70, 47, 47, 23, 23 },// Tajik/Cyrillic/Tajikistan
- { 117, 27, 100,19343,19343,19428,19428,19485,19485, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/India
- { 117, 27, 130,19343,19343,19428,19428,19485,19485, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/Malaysia
- { 117, 27, 190,19343,19343,19428,19428,19485,19485, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/Singapore
- { 117, 27, 198,19343,19343,19428,19428,19485,19485, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/Sri Lanka
- { 118, 2, 178,19515,19515,19595,19595, 155, 155, 80, 80, 61, 61, 26, 26 },// Tatar/Cyrillic/Russia
- { 119, 28, 100,19656,19656,19741,19741,19802,19802, 85, 85, 61, 61, 30, 30 },// Telugu/Telugu/India
- { 120, 30, 211,19832,19832,19929,19929,19929,19929, 97, 97, 62, 62, 62, 62 },// Thai/Thai/Thailand
- { 121, 31, 44,19991,20149, 2950, 2950, 155, 155,158,146, 62, 62, 26, 26 },// Tibetan/Tibetan/China
- { 121, 31, 100,19991,20149, 2950, 2950, 155, 155,158,146, 62, 62, 26, 26 },// Tibetan/Tibetan/India
- { 122, 14, 69,20295,20295,20348,20348,20383,20383, 53, 53, 35, 35, 23, 23 },// Tigrinya/Ethiopic/Ethiopia
- { 122, 14, 67,20295,20295,20348,20348,20383,20383, 53, 53, 35, 35, 23, 23 },// Tigrinya/Ethiopic/Eritrea
- { 123, 7, 214,20406,20406,20492,20492,20542,20542, 86, 86, 50, 50, 23, 23 },// Tongan/Latin/Tonga
- { 124, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Tsonga/Latin/South Africa
- { 125, 7, 217,20565,20565,20639,20639,20686,20686, 74, 74, 47, 47, 23, 23 },// Turkish/Latin/Turkey
- { 125, 7, 56,20565,20565,20639,20639,20686,20686, 74, 74, 47, 47, 23, 23 },// Turkish/Latin/Cyprus
- { 126, 7, 218,20709,20785,20861,20910,20960,20960, 76, 76, 49, 50, 23, 23 },// Turkmen/Latin/Turkmenistan
- { 128, 1, 44,20983,20983,20983,20983, 155, 155, 83, 83, 83, 83, 26, 26 },// Uighur/Arabic/China
- { 129, 2, 222,21066,21160,21246,21293,21359,21382, 94, 86, 47, 66, 23, 23 },// Ukrainian/Cyrillic/Ukraine
- { 130, 1, 163,21405,21405,21405,21405, 132, 132, 67, 67, 67, 67, 23, 23 },// Urdu/Arabic/Pakistan
- { 130, 1, 100,21405,21405,21405,21405, 132, 132, 67, 67, 67, 67, 23, 23 },// Urdu/Arabic/India
- { 131, 7, 228,21472,21546,21620,21667,21714,21714, 74, 74, 47, 47, 23, 23 },// Uzbek/Latin/Uzbekistan
- { 131, 1, 1,14983,14983,21737,21737, 155, 155, 67, 67, 46, 46, 26, 26 },// Uzbek/Arabic/Afghanistan
- { 131, 2, 228,21783,21783,21853,21853,11135,11135, 70, 70, 47, 47, 23, 23 },// Uzbek/Cyrillic/Uzbekistan
- { 132, 7, 232,21900,21998,22096,22170, 155, 155, 98, 98, 74, 74, 26, 26 },// Vietnamese/Latin/Vietnam
- { 133, 7, 260,22244,22244,22317,22364,22411,22411, 73, 73, 47, 47, 23, 23 },// Volapuk/Latin/World
- { 134, 7, 224,22434,22434,22520,22571,22626,22626, 86, 86, 51, 55, 25, 25 },// Welsh/Latin/United Kingdom
- { 135, 7, 187,22651,22651,22734,22734, 155, 155, 83, 83, 46, 46, 26, 26 },// Wolof/Latin/Senegal
- { 136, 7, 195,22780,22780,22870,22870, 155, 155, 90, 90, 47, 47, 26, 26 },// Xhosa/Latin/South Africa
- { 137, 18, 260,22917,22917,23008,22917, 155, 155, 91, 91, 57, 91, 26, 26 },// Yiddish/Hebrew/World
- { 138, 7, 157,23065,23137,23257,23296,23350,23350, 72,120, 39, 54, 26, 26 },// Yoruba/Latin/Nigeria
- { 138, 7, 23,23376,23449,23582,23622,23677,23677, 73,133, 40, 55, 26, 26 },// Yoruba/Latin/Benin
- { 140, 7, 195,23703,23703,23793,23793, 132,23840, 90, 90, 47, 47, 23, 23 },// Zulu/Latin/South Africa
- { 141, 7, 161,14394,14394, 5646,23863, 132, 132, 82, 82, 47, 58, 23, 23 },// Norwegian Nynorsk/Latin/Norway
- { 142, 7, 27,23921,23921,24003,24003, 9704, 9704, 82, 82, 47, 47, 23, 23 },// Bosnian/Latin/Bosnia And Herzegowina
- { 142, 2, 27,24050,24050,24132,24132,12615,12615, 82, 82, 47, 47, 23, 23 },// Bosnian/Cyrillic/Bosnia And Herzegowina
- { 143, 29, 131, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Divehi/Thaana/Maldives
- { 144, 7, 251,24179,24179,24318,24318, 155, 155,139,139,101,101, 26, 26 },// Manx/Latin/Isle Of Man
- { 145, 7, 224,24419,24419,24548,24548, 155, 155,129,129, 45, 45, 26, 26 },// Cornish/Latin/United Kingdom
- { 146, 7, 83,24593,24593,24784,24784, 155, 155,191,191, 47, 47, 26, 26 },// Akan/Latin/Ghana
- { 147, 13, 100,24831,24831,24831,24831, 155, 155, 87, 87, 87, 87, 26, 26 },// Konkani/Devanagari/India
- { 148, 7, 83, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Ga/Latin/Ghana
- { 149, 7, 157,24918,24918,25004,25004,25051,25051, 86, 86, 47, 47, 23, 23 },// Igbo/Latin/Nigeria
- { 150, 7, 111,25074,25074,25262,25262,25309,25309,188,188, 47, 47, 23, 23 },// Kamba/Latin/Kenya
- { 151, 33, 103, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Syriac/Syriac/Iraq
- { 152, 14, 67, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Blin/Ethiopic/Eritrea
- { 153, 14, 69, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Geez/Ethiopic/Ethiopia
- { 155, 7, 69, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Sidamo/Latin/Ethiopia
- { 156, 7, 157, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Atsam/Latin/Nigeria
- { 157, 14, 67, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Tigre/Ethiopic/Eritrea
- { 158, 7, 157, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Jju/Latin/Nigeria
- { 159, 7, 106,25332,25332,25408,25408,25455,25455, 76, 76, 47, 47, 23, 23 },// Friulian/Latin/Italy
- { 160, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Venda/Latin/South Africa
- { 161, 7, 83,25478,25478,25564,25564,25611,25611, 86, 86, 47, 47, 23, 23 },// Ewe/Latin/Ghana
- { 161, 7, 212,25478,25478,25564,25564,25611,25611, 86, 86, 47, 47, 23, 23 },// Ewe/Latin/Togo
- { 162, 14, 69, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Walamo/Ethiopic/Ethiopia
- { 163, 7, 225,25634,25634,25728,25728, 155, 155, 94, 94, 58, 58, 26, 26 },// Hawaiian/Latin/United States
- { 164, 7, 157, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Tyap/Latin/Nigeria
- { 165, 7, 129, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Nyanja/Latin/Malawi
- { 166, 7, 170,25786,25786,25873,25873,25920,25873, 87, 87, 47, 47, 37, 47 },// Filipino/Latin/Philippines
- { 167, 7, 206,25957,25957, 7564, 7564, 132, 132, 85, 85, 47, 47, 23, 23 },// Swiss German/Latin/Switzerland
- { 167, 7, 74,25957,25957, 7564, 7564, 132, 132, 85, 85, 47, 47, 23, 23 },// Swiss German/Latin/France
- { 167, 7, 123,25957,25957, 7564, 7564, 132, 132, 85, 85, 47, 47, 23, 23 },// Swiss German/Latin/Liechtenstein
- { 168, 34, 44,26042,26042,26042,26042, 155, 155, 37, 37, 37, 37, 26, 26 },// Sichuan Yi/Yi/China
- { 169, 7, 121, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Kpelle/Latin/Liberia
- { 170, 7, 82,26079,26079,26163,26163, 132, 132, 84, 84, 58, 58, 23, 23 },// Low German/Latin/Germany
- { 170, 7, 151,26079,26079,26163,26163, 132, 132, 84, 84, 58, 58, 23, 23 },// Low German/Latin/Netherlands
- { 171, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// South Ndebele/Latin/South Africa
- { 172, 7, 195, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Northern Sotho/Latin/South Africa
- { 173, 7, 161,26221,26221,26365,26365,26423,26423,144,144, 58, 58, 23, 23 },// Northern Sami/Latin/Norway
- { 173, 7, 73,26221,26221,26446,26446,26423,26423,144,144, 59, 59, 23, 23 },// Northern Sami/Latin/Finland
- { 173, 7, 205,26221,26221,26365,26365,26423,26423,144,144, 58, 58, 23, 23 },// Northern Sami/Latin/Sweden
- { 174, 7, 208, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Taroko/Latin/Taiwan
- { 175, 7, 111,26505,26505,26592,26592,26639,26639, 87, 87, 47, 47, 23, 23 },// Gusii/Latin/Kenya
- { 176, 7, 111,26662,26662,26882,26882,26929,26929,220,220, 47, 47, 23, 23 },// Taita/Latin/Kenya
- { 177, 7, 187,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Senegal
- { 177, 7, 34,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Burkina Faso
- { 177, 7, 37,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Cameroon
- { 177, 7, 80,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Gambia
- { 177, 7, 83,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Ghana
- { 177, 7, 91,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Guinea
- { 177, 7, 92,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Guinea Bissau
- { 177, 7, 121,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Liberia
- { 177, 7, 136,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Mauritania
- { 177, 7, 156,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Niger
- { 177, 7, 157,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Nigeria
- { 177, 7, 189,26952,26952,27028,27028,27075,27075, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Sierra Leone
- { 177, 134, 91, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Fulah/Adlam/Guinea
- { 178, 7, 111,27098,27098,27282,27282,27329,27329,184,184, 47, 47, 23, 23 },// Kikuyu/Latin/Kenya
- { 179, 7, 111,27352,27352,27524,27524,27571,27571,172,172, 47, 47, 23, 23 },// Samburu/Latin/Kenya
- { 180, 7, 146,27594,27594,27681,27681, 132, 132, 87, 87, 47, 47, 23, 23 },// Sena/Latin/Mozambique
- { 181, 7, 240,27728,27728,27839,27839,27890,27890,111,111, 51, 51, 23, 23 },// North Ndebele/Latin/Zimbabwe
- { 182, 7, 210,27913,27913,28106,28106,28144,28144,193,193, 38, 38, 23, 23 },// Rombo/Latin/Tanzania
- { 183, 9, 145,28167,28167,28247,28247,28294,28294, 80, 80, 47, 47, 23, 23 },// Tachelhit/Tifinagh/Morocco
- { 183, 7, 145,28317,28317,28397,28397,28444,28444, 80, 80, 47, 47, 23, 23 },// Tachelhit/Latin/Morocco
- { 184, 7, 3,28467,28548,28631,28678,28725,28748, 81, 83, 47, 47, 23, 23 },// Kabyle/Latin/Algeria
- { 185, 7, 221,28771,28771,28922,28922, 132, 132,151,151, 47, 47, 23, 23 },// Nyankole/Latin/Uganda
- { 186, 7, 210,28969,28969,29222,29222,29269,29269,253,253, 47, 47, 23, 23 },// Bena/Latin/Tanzania
- { 187, 7, 210,29292,29292,19083,19083, 132, 132, 86, 86, 47, 47, 23, 23 },// Vunjo/Latin/Tanzania
- { 188, 7, 132,29378,29378,29469,29469,29515,29515, 91, 91, 46, 46, 23, 23 },// Bambara/Latin/Mali
- { 188, 75, 132, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Bambara/Nko/Mali
- { 189, 7, 111,29538,29538,29744,29744,29791,29791,206,206, 47, 47, 23, 23 },// Embu/Latin/Kenya
- { 190, 12, 225,29814,29814,29871,29871,29906,29906, 57, 57, 35, 35, 23, 23 },// Cherokee/Cherokee/United States
- { 191, 7, 137,29929,29929,29996,29996,30042,30042, 67, 67, 46, 46, 23, 23 },// Morisyen/Latin/Mauritius
- { 192, 7, 210,30065,30065,19083,19083, 132, 132,263,263, 47, 47, 23, 23 },// Makonde/Latin/Tanzania
- { 193, 7, 210,30328,30328,30438,30438,30520,30520,110,110, 82, 82, 23, 23 },// Langi/Latin/Tanzania
- { 194, 7, 221,30543,30543,30639,30639, 132, 132, 96, 96, 47, 47, 23, 23 },// Ganda/Latin/Uganda
- { 195, 7, 239,30686,30686,30768,30768,30815,30815, 82, 82, 47, 47, 23, 23 },// Bemba/Latin/Zambia
- { 196, 7, 39,30838,30838,30922,30922, 132, 132, 84, 84, 47, 47, 23, 23 },// Kabuverdianu/Latin/Cape Verde
- { 197, 7, 111,30969,30969,31054,31054,31101,31101, 85, 85, 47, 47, 23, 23 },// Meru/Latin/Kenya
- { 198, 7, 111,31124,31124,31244,31244,31292,31292,120,120, 48, 48, 23, 23 },// Kalenjin/Latin/Kenya
- { 199, 7, 148,31315,31315, 85, 85, 132, 132,135,135, 47, 47, 23, 23 },// Nama/Latin/Namibia
- { 200, 7, 210,29292,29292,19083,19083, 132, 132, 86, 86, 47, 47, 23, 23 },// Machame/Latin/Tanzania
- { 201, 7, 82,31450,31450,31536,31594,12904,12904, 86, 86, 58, 47, 23, 23 },// Colognian/Latin/Germany
- { 202, 7, 111,31641,31641,31772,31772, 155, 155,131,131, 50, 50, 26, 26 },// Masai/Latin/Kenya
- { 202, 7, 210,31641,31641,31772,31772, 155, 155,131,131, 50, 50, 26, 26 },// Masai/Latin/Tanzania
- { 203, 7, 221,30543,30543,30639,30639, 132, 132, 96, 96, 47, 47, 23, 23 },// Soga/Latin/Uganda
- { 204, 7, 111,19000,19000,31822,31822, 132, 132, 83, 83, 47, 47, 23, 23 },// Luyia/Latin/Kenya
- { 205, 7, 210,19000,19000,31869,31869, 132, 132, 83, 83, 47, 47, 23, 23 },// Asu/Latin/Tanzania
- { 206, 7, 221,31916,31916,32009,32009,32056,32056, 93, 93, 47, 47, 23, 23 },// Teso/Latin/Uganda
- { 206, 7, 111,31916,31916,32009,32009,32056,32056, 93, 93, 47, 47, 23, 23 },// Teso/Latin/Kenya
- { 207, 7, 67, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Saho/Latin/Eritrea
- { 208, 7, 132,32079,32079,32166,32166,32211,32211, 87, 87, 45, 45, 23, 23 },// Koyra Chiini/Latin/Mali
- { 209, 7, 210,29292,29292,19083,19083, 132, 132, 86, 86, 47, 47, 23, 23 },// Rwa/Latin/Tanzania
- { 210, 7, 111,32234,32234,32419,32419,32466,32466,185,185, 47, 47, 23, 23 },// Luo/Latin/Kenya
- { 211, 7, 221,28771,28771,28922,28922, 132, 132,151,151, 47, 47, 23, 23 },// Chiga/Latin/Uganda
- { 212, 7, 145,32489,32489,32574,32574,32621,32621, 85, 85, 47, 47, 23, 23 },// Central Morocco Tamazight/Latin/Morocco
- { 213, 7, 132,32079,32079,32166,32166,32211,32211, 87, 87, 45, 45, 23, 23 },// Koyraboro Senni/Latin/Mali
- { 214, 7, 210,32644,32644,19083,19083, 132, 132, 83, 83, 47, 47, 23, 23 },// Shambala/Latin/Tanzania
- { 215, 13, 100,32727,32727,32727,32727,32814,32814, 87, 87, 87, 87, 30, 30 },// Bodo/Devanagari/India
- { 218, 2, 178,10951,10951,21853,21853,11135,11135, 79, 79, 47, 47, 23, 23 },// Chechen/Cyrillic/Russia
- { 219, 2, 178,32844,32960,33076,33076,33140,33140,116,116, 64, 64, 29, 29 },// Church/Cyrillic/Russia
- { 220, 2, 178, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Chuvash/Cyrillic/Russia
- { 230, 7, 49,33169,33169,33267,33267,33315,33315, 98, 98, 48, 48, 23, 23 },// Luba Katanga/Latin/Congo Kinshasa
- { 231, 7, 125,33338,33338,33422,33469, 132, 132, 84, 84, 47, 58, 23, 23 },// Luxembourgish/Latin/Luxembourg
- { 236, 7, 21, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Walloon/Latin/Belgium
- { 237, 7, 37,33527,33527,33721,33721,33768,33768,194,194, 47, 47, 23, 23 },// Aghem/Latin/Cameroon
- { 238, 7, 37,33791,33791,33880,33880,33927,33927, 89, 89, 47, 47, 23, 23 },// Basaa/Latin/Cameroon
- { 239, 7, 156,32079,32079,32166,32166,32211,32211, 87, 87, 45, 45, 23, 23 },// Zarma/Latin/Niger
- { 240, 7, 37,33950,33950,34048,34048,34096,34096, 98, 98, 48, 48, 23, 23 },// Duala/Latin/Cameroon
- { 241, 7, 187,34119,34119,34200,34200,34235,34235, 81, 81, 35, 35, 23, 23 },// Jola Fonyi/Latin/Senegal
- { 242, 7, 37,34258,34258,34398,34398,34447,34447,140,140, 49, 49, 23, 23 },// Ewondo/Latin/Cameroon
- { 243, 7, 37,34470,34470,34660,34660, 155, 155,190,190, 38, 38, 26, 26 },// Bafia/Latin/Cameroon
- { 244, 7, 146,34698,34698,34910,34910,34957,34957,212,212, 47, 47, 23, 23 },// Makhuwa Meetto/Latin/Mozambique
- { 245, 7, 37,34980,34980,35118,35118,35165,35165,138,138, 47, 47, 23, 23 },// Mundang/Latin/Cameroon
- { 246, 7, 37,35188,35188,35330,35330, 155, 155,142,142, 50, 50, 26, 26 },// Kwasio/Latin/Cameroon
- { 247, 7, 254,35380,35380,35475,35475,35528,35528, 95, 95, 53, 53, 23, 23 },// Nuer/Latin/South Sudan
- { 248, 2, 178,35551,35666,35786,35786,35835,35835,115,120, 49, 49, 23, 23 },// Sakha/Cyrillic/Russia
- { 249, 7, 210,35858,35858,35974,35974, 155, 155,116,116, 47, 47, 26, 26 },// Sangu/Latin/Tanzania
- { 251, 7, 156,32079,32079,32166,32166,32211,32211, 87, 87, 45, 45, 23, 23 },// Tasawaq/Latin/Niger
- { 252, 35, 121,36021,36021,36081,36081, 155, 155, 60, 60, 37, 37, 26, 26 },// Vai/Vai/Liberia
- { 252, 7, 121,36118,36118,36118,36118, 155, 155, 80, 80, 80, 80, 26, 26 },// Vai/Latin/Liberia
- { 253, 7, 206,36198,36198,36296,36296,36343,36343, 98, 98, 47, 47, 23, 23 },// Walser/Latin/Switzerland
- { 254, 7, 37,36366,36366,36556,36556, 155, 155,190,190, 50, 50, 26, 26 },// Yangben/Latin/Cameroon
- { 256, 7, 197,36606,36690,36806,36853,36900,36900, 84,116, 47, 47, 23, 23 },// Asturian/Latin/Spain
- { 257, 7, 37,36923,36923,36923,36923, 155, 155,173,173,173,173, 26, 26 },// Ngomba/Latin/Cameroon
- { 258, 7, 37,37096,37096,37096,37096, 155, 155,101,101,101,101, 26, 26 },// Kako/Latin/Cameroon
- { 259, 7, 37,37197,37197,37338,37338,37474,37474,141,141,136,136, 35, 35 },// Meta/Latin/Cameroon
- { 260, 7, 37,37509,37509,37509,37509, 155, 155,164,164,164,164, 26, 26 },// Ngiemboon/Latin/Cameroon
- { 261, 7, 197, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Aragonese/Latin/Spain
- { 272, 46, 18,37673,37862,37673,38051,38218,38218,189,189,189,167, 57, 57 },// Chakma/Chakma/Bangladesh
- { 272, 46, 100,37673,37862,37673,38051,38218,38218,189,189,189,167, 57, 57 },// Chakma/Chakma/India
- { 290, 11, 100, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Manipuri/Bengali/India
- { 309, 100, 232, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Tai Dam/Tai Viet/Vietnam
- { 312, 7, 37, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Akoose/Latin/Cameroon
- { 313, 7, 225,38275,38275,38275,38275, 155, 155,179,179,179,179, 26, 26 },// Lakota/Latin/United States
- { 314, 9, 145,28167,28167,28247,28247,28294,28294, 80, 80, 47, 47, 23, 23 },// Standard Moroccan Tamazight/Tifinagh/Morocco
- { 315, 7, 43, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Mapuche/Latin/Chile
- { 316, 1, 103,38454,38454,38454,38454,38558,38558,104,104,104,104, 23, 23 },// Central Kurdish/Arabic/Iraq
- { 316, 1, 102,38454,38454,38454,38454,38558,38558,104,104,104,104, 23, 23 },// Central Kurdish/Arabic/Iran
- { 317, 7, 82,38581,38665,38757,38804, 9704, 9704, 84, 92, 47, 59, 23, 23 },// Lower Sorbian/Latin/Germany
- { 318, 7, 82,38863,38948,39040,39087, 9704, 9704, 85, 92, 47, 59, 23, 23 },// Upper Sorbian/Latin/Germany
- { 319, 7, 37, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Kenyang/Latin/Cameroon
- { 320, 7, 38, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Mohawk/Latin/Canada
- { 321, 75, 91, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Nko/Nko/Guinea
- { 322, 7, 260,39146,39146,39236,39236,39283,39283, 90, 90, 47, 47, 23, 23 },// Prussian/Latin/World
- { 323, 7, 90, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Kiche/Latin/Guatemala
- { 324, 7, 205, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Sami/Latin/Sweden
- { 325, 7, 205, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Lule Sami/Latin/Sweden
- { 326, 7, 73,39306,39306,39445,39445,39521,39521,139,139, 76, 76, 24, 24 },// Inari Sami/Latin/Finland
- { 327, 7, 73, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Skolt Sami/Latin/Finland
- { 328, 7, 13, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Warlpiri/Latin/Australia
- { 346, 1, 102,14818,14818,14818,14818, 155, 155, 69, 69, 69, 69, 26, 26 },// Mazanderani/Arabic/Iran
- { 349, 1, 102,39545,39545,39545,39545, 155, 155, 76, 76, 76, 76, 26, 26 },// Northern Luri/Arabic/Iran
- { 349, 1, 103,39545,39545,39545,39545, 155, 155, 76, 76, 76, 76, 26, 26 },// Northern Luri/Arabic/Iraq
- { 357, 6, 97, 4387, 4387, 4387, 4387, 155, 155, 38, 38, 38, 38, 26, 26 },// Cantonese/Traditional Han/Hong Kong
- { 357, 5, 44, 4350, 4350, 4387, 4387, 155, 155, 37, 37, 38, 38, 26, 26 },// Cantonese/Simplified Han/China
- { 358, 138, 225, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Osage/Osage/United States
- { 360, 7, 260, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Ido/Latin/World
- { 361, 7, 260, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Lojban/Latin/World
- { 362, 7, 106, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Sicilian/Latin/Italy
- { 363, 1, 102, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Kurdish/Arabic/Iran
- { 364, 1, 163, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Western Balochi/Arabic/Pakistan
- { 365, 7, 170,25786,25786,39621,39621,39666,39666, 87, 87, 45, 45, 23, 23 },// Cebuano/Latin/Philippines
- { 366, 2, 178, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Erzya/Cyrillic/Russia
- { 367, 7, 225, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Chickasaw/Latin/United States
- { 368, 7, 225, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Muscogee/Latin/United States
- { 369, 7, 172, 361, 361, 361, 361, 155, 155, 47, 47, 47, 47, 26, 26 },// Silesian/Latin/Poland
+ { 1, 0, 0, 0, 0, 85, 85, 132, 155, 85, 85, 47, 47, 23, 26 },// C/AnyScript/AnyTerritory
+ { 2, 27, 90, 181, 181, 278, 278, 336, 364, 97, 97, 58, 58, 28, 28 },// Abkhazian/Cyrillic/Georgia
+ { 3, 66, 77, 392, 392, 509, 509, 556, 556,117,117, 47, 47, 23, 23 },// Afar/Latin/Ethiopia
+ { 3, 66, 67, 579, 579, 509, 509, 556, 556,118,118, 47, 47, 23, 23 },// Afar/Latin/Djibouti
+ { 3, 66, 74, 392, 392, 509, 509, 556, 556,117,117, 47, 47, 23, 23 },// Afar/Latin/Eritrea
+ { 4, 66, 216, 697, 697, 788, 788, 132, 132, 91, 91, 58, 58, 23, 23 },// Afrikaans/Latin/South Africa
+ { 4, 66, 162, 697, 697, 788, 788, 132, 132, 91, 91, 58, 58, 23, 23 },// Afrikaans/Latin/Namibia
+ { 5, 66, 40, 846, 846, 1040, 1040, 1087, 1087,194,194, 47, 47, 23, 23 },// Aghem/Latin/Cameroon
+ { 6, 66, 92, 1110, 1110, 1301, 1301, 155, 155,191,191, 47, 47, 26, 26 },// Akan/Latin/Ghana
+ { 8, 66, 40, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Akoose/Latin/Cameroon
+ { 9, 66, 3, 1395, 1395, 1472, 1472, 1521, 1521, 77, 77, 49, 49, 26, 26 },// Albanian/Latin/Albania
+ { 9, 66, 126, 1395, 1395, 1472, 1472, 1521, 1521, 77, 77, 49, 49, 26, 26 },// Albanian/Latin/Kosovo
+ { 9, 66, 140, 1395, 1395, 1472, 1472, 1521, 1521, 77, 77, 49, 49, 26, 26 },// Albanian/Latin/Macedonia
+ { 11, 33, 77, 1547, 1547, 1606, 1606, 1649, 1649, 59, 59, 43, 43, 23, 23 },// Amharic/Ethiopic/Ethiopia
+ { 14, 4, 71, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Egypt
+ { 14, 4, 4, 1769, 1769, 1769, 1769, 1839, 1839, 70, 70, 70, 70, 23, 23 },// Arabic/Arabic/Algeria
+ { 14, 4, 19, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Bahrain
+ { 14, 4, 48, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Chad
+ { 14, 4, 55, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Comoros
+ { 14, 4, 67, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Djibouti
+ { 14, 4, 74, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Eritrea
+ { 14, 4, 113, 1862, 1862, 1862, 1953, 2044, 2044, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Iraq
+ { 14, 4, 116, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Israel
+ { 14, 4, 122, 1862, 1862, 1862, 1862, 2044, 2044, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Jordan
+ { 14, 4, 127, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Kuwait
+ { 14, 4, 132, 1862, 1862, 1862, 1862, 2044, 2044, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Lebanon
+ { 14, 4, 135, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Libya
+ { 14, 4, 149, 2067, 2067, 2067, 2067, 2138, 2138, 71, 71, 71, 71, 23, 23 },// Arabic/Arabic/Mauritania
+ { 14, 4, 159, 2161, 2161, 2161, 2161, 2230, 2230, 69, 69, 69, 69, 23, 23 },// Arabic/Arabic/Morocco
+ { 14, 4, 176, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Oman
+ { 14, 4, 180, 1862, 1862, 1862, 1862, 2044, 2044, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Palestinian Territories
+ { 14, 4, 190, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Qatar
+ { 14, 4, 205, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Saudi Arabia
+ { 14, 4, 215, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Somalia
+ { 14, 4, 219, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/South Sudan
+ { 14, 4, 222, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Sudan
+ { 14, 4, 227, 1862, 1862, 1862, 1862, 2044, 2044, 91, 91, 91, 91, 23, 23 },// Arabic/Arabic/Syria
+ { 14, 4, 238, 1769, 1769, 1769, 1769, 1839, 1839, 70, 70, 70, 70, 23, 23 },// Arabic/Arabic/Tunisia
+ { 14, 4, 245, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/United Arab Emirates
+ { 14, 4, 257, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Western Sahara
+ { 14, 4, 258, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/world
+ { 14, 4, 259, 1672, 1672, 1672, 1672, 1746, 1746, 74, 74, 74, 74, 23, 23 },// Arabic/Arabic/Yemen
+ { 15, 66, 220, 2253, 2343, 2465, 2465, 155, 155, 90,122, 59, 59, 26, 26 },// Aragonese/Latin/Spain
+ { 17, 5, 12, 2524, 2617, 2722, 2722, 2769, 2769, 93,105, 47, 47, 23, 23 },// Armenian/Armenian/Armenia
+ { 18, 9, 110, 2792, 2792, 2880, 2880, 2943, 2943, 88, 88, 63, 63, 23, 23 },// Assamese/Bangla/India
+ { 19, 66, 220, 2966, 3050, 3166, 3213, 3260, 3260, 84,116, 47, 47, 23, 23 },// Asturian/Latin/Spain
+ { 20, 66, 230, 3283, 3283, 3366, 3366, 132, 132, 83, 83, 47, 47, 23, 23 },// Asu/Latin/Tanzania
+ { 21, 66, 169, 3413, 3413, 3541, 3541, 155, 155,128,128, 58, 58, 26, 26 },// Atsam/Latin/Nigeria
+ { 25, 66, 17, 3599, 3599, 3675, 3675, 155, 155, 76, 76, 47, 47, 26, 26 },// Azerbaijani/Latin/Azerbaijan
+ { 25, 4, 112, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Azerbaijani/Arabic/Iran
+ { 25, 4, 113, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Azerbaijani/Arabic/Iraq
+ { 25, 4, 239, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Azerbaijani/Arabic/Turkey
+ { 25, 27, 17, 3722, 3798, 3874, 3874, 155, 155, 76, 76, 47, 47, 26, 26 },// Azerbaijani/Cyrillic/Azerbaijan
+ { 26, 66, 40, 3921, 3921, 4111, 4111, 155, 155,190,190, 38, 38, 26, 26 },// Bafia/Latin/Cameroon
+ { 28, 66, 145, 4149, 4149, 4240, 4240, 4286, 4286, 91, 91, 46, 46, 23, 23 },// Bambara/Latin/Mali
+ { 28, 90, 145, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Bambara/Nko/Mali
+ { 30, 9, 20, 4309, 4309, 4398, 4474, 4527, 4527, 89, 89, 76, 53, 32, 32 },// Bangla/Bangla/Bangladesh
+ { 30, 9, 110, 4309, 4309, 4559, 4625, 4685, 4685, 89, 89, 66, 60, 33, 33 },// Bangla/Bangla/India
+ { 31, 66, 40, 4718, 4718, 4807, 4807, 4854, 4854, 89, 89, 47, 47, 23, 23 },// Basaa/Latin/Cameroon
+ { 32, 27, 193, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Bashkir/Cyrillic/Russia
+ { 33, 66, 220, 4877, 4877, 4969, 4969, 5028, 5028, 92, 92, 59, 59, 23, 23 },// Basque/Latin/Spain
+ { 35, 27, 22, 5051, 5145, 5242, 5289, 5336, 5336, 94, 97, 47, 47, 23, 23 },// Belarusian/Cyrillic/Belarus
+ { 36, 66, 260, 5359, 5359, 5441, 5441, 5488, 5488, 82, 82, 47, 47, 23, 23 },// Bemba/Latin/Zambia
+ { 37, 66, 230, 5511, 5511, 5764, 5764, 5811, 5811,253,253, 47, 47, 23, 23 },// Bena/Latin/Tanzania
+ { 38, 29, 110, 5834, 5834, 5834, 5834, 155, 155, 72, 72, 72, 72, 26, 26 },// Bhojpuri/Devanagari/India
+ { 40, 33, 74, 5906, 5906, 5982, 5982, 6028, 6028, 76, 76, 46, 46, 23, 23 },// Blin/Ethiopic/Eritrea
+ { 41, 29, 110, 6051, 6051, 6138, 6138, 6190, 6190, 87, 87, 52, 52, 23, 23 },// Bodo/Devanagari/India
+ { 42, 66, 29, 6213, 6213, 6295, 6295, 6342, 6342, 82, 82, 47, 47, 23, 23 },// Bosnian/Latin/Bosnia and Herzegovina
+ { 42, 27, 29, 6365, 6365, 6447, 6447, 6494, 6494, 82, 82, 47, 47, 23, 23 },// Bosnian/Cyrillic/Bosnia and Herzegovina
+ { 43, 66, 84, 6517, 6517, 6594, 6594, 6656, 6656, 77, 77, 62, 62, 35, 35 },// Breton/Latin/France
+ { 45, 27, 36, 6691, 6691, 6772, 6772, 6820, 6820, 81, 81, 48, 48, 23, 23 },// Bulgarian/Cyrillic/Bulgaria
+ { 46, 86, 161, 6843, 6843, 6930, 6930, 6972, 6972, 87, 87, 42, 42, 23, 23 },// Burmese/Myanmar/Myanmar
+ { 47, 137, 107, 6995, 6995, 6995, 6995, 155, 155, 38, 38, 38, 38, 26, 26 },// Cantonese/Traditional Han/Hong Kong
+ { 47, 118, 50, 7033, 7033, 6995, 6995, 155, 155, 37, 37, 38, 38, 26, 26 },// Cantonese/Simplified Han/China
+ { 48, 66, 220, 7070, 7151, 7265, 7324, 7416, 7416, 81,114, 59, 92, 35, 35 },// Catalan/Latin/Spain
+ { 48, 66, 6, 7070, 7151, 7265, 7324, 7416, 7416, 81,114, 59, 92, 35, 35 },// Catalan/Latin/Andorra
+ { 48, 66, 84, 7070, 7151, 7265, 7324, 7416, 7416, 81,114, 59, 92, 35, 35 },// Catalan/Latin/France
+ { 48, 66, 117, 7070, 7151, 7265, 7324, 7416, 7416, 81,114, 59, 92, 35, 35 },// Catalan/Latin/Italy
+ { 49, 66, 185, 7451, 7451, 7540, 7540, 7587, 7587, 89, 89, 47, 47, 23, 23 },// Cebuano/Latin/Philippines
+ { 50, 66, 159, 7610, 7610, 7695, 7695, 7742, 7742, 85, 85, 47, 47, 23, 23 },// Central Atlas Tamazight/Latin/Morocco
+ { 51, 4, 113, 7765, 7765, 7765, 7765, 7869, 7869,104,104,104,104, 23, 23 },// Central Kurdish/Arabic/Iraq
+ { 51, 4, 112, 7765, 7765, 7765, 7765, 7869, 7869,104,104,104,104, 23, 23 },// Central Kurdish/Arabic/Iran
+ { 52, 21, 20, 7892, 8081, 7892, 8270, 8437, 8437,189,189,189,167, 57, 57 },// Chakma/Chakma/Bangladesh
+ { 52, 21, 110, 7892, 8081, 7892, 8270, 8437, 8437,189,189,189,167, 57, 57 },// Chakma/Chakma/India
+ { 54, 27, 193, 8494, 8494, 8573, 8573, 8620, 8620, 79, 79, 47, 47, 23, 23 },// Chechen/Cyrillic/Russia
+ { 55, 23, 248, 8643, 8643, 8700, 8700, 8735, 8735, 57, 57, 35, 35, 23, 23 },// Cherokee/Cherokee/United States
+ { 56, 66, 248, 8758, 8758, 8758, 8758, 155, 155,118,118,118,118, 26, 26 },// Chickasaw/Latin/United States
+ { 57, 66, 243, 8876, 8876, 9027, 9027, 132, 132,151,151, 47, 47, 23, 23 },// Chiga/Latin/Uganda
+ { 58, 118, 50, 7033, 7033, 6995, 6995, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/China
+ { 58, 118, 107, 7033, 7033, 6995, 6995, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Hong Kong
+ { 58, 118, 139, 7033, 7033, 6995, 6995, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Macao
+ { 58, 118, 210, 7033, 7033, 6995, 6995, 155, 155, 37, 37, 38, 38, 26, 26 },// Chinese/Simplified Han/Singapore
+ { 58, 137, 107, 6995, 6995, 6995, 6995, 155, 155, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Hong Kong
+ { 58, 137, 139, 6995, 6995, 6995, 6995, 155, 155, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Macao
+ { 58, 137, 228, 6995, 6995, 6995, 6995, 155, 155, 38, 38, 38, 38, 26, 26 },// Chinese/Traditional Han/Taiwan
+ { 59, 27, 193, 9074, 9190, 9306, 9306, 9370, 9370,116,116, 64, 64, 29, 29 },// Church/Cyrillic/Russia
+ { 60, 27, 193, 9399, 9399, 9459, 9459, 9511, 9511, 60, 60, 52, 52, 23, 23 },// Chuvash/Cyrillic/Russia
+ { 61, 66, 91, 9534, 9534, 9620, 9678, 9725, 9725, 86, 86, 58, 47, 23, 23 },// Colognian/Latin/Germany
+ { 63, 66, 246, 9748, 9748, 9877, 9877, 155, 155,129,129, 45, 45, 26, 26 },// Cornish/Latin/United Kingdom
+ { 64, 66, 84, 9922,10020,10151,10151,10211,10211, 98,131, 60, 60, 23, 23 },// Corsican/Latin/France
+ { 66, 66, 60,10234,10327,10424,10424,10472,10472, 93, 97, 48, 48, 38, 38 },// Croatian/Latin/Croatia
+ { 66, 66, 29,10234,10327,10424,10424,10472,10472, 93, 97, 48, 48, 38, 38 },// Croatian/Latin/Bosnia and Herzegovina
+ { 67, 66, 64,10510,10591,10674,10674, 155, 155, 81, 83, 47, 47, 26, 26 },// Czech/Latin/Czechia
+ { 68, 66, 65,10721,10721,10804,10804, 132, 132, 83, 83, 58, 58, 23, 23 },// Danish/Latin/Denmark
+ { 68, 66, 95,10721,10721,10804,10804, 132, 132, 83, 83, 58, 58, 23, 23 },// Danish/Latin/Greenland
+ { 69, 132, 144, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Divehi/Thaana/Maldives
+ { 70, 29, 110,10862,10862,10934,10934,10993,10993, 72, 72, 59, 59, 29, 29 },// Dogri/Devanagari/India
+ { 71, 66, 40,11022,11022,11120,11120,11168,11168, 98, 98, 48, 48, 23, 23 },// Duala/Latin/Cameroon
+ { 72, 66, 165,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Netherlands
+ { 72, 66, 13,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Aruba
+ { 72, 66, 23,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Belgium
+ { 72, 66, 44,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Caribbean Netherlands
+ { 72, 66, 62,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Curacao
+ { 72, 66, 211,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Sint Maarten
+ { 72, 66, 223,11191,11191,11278,11278, 132, 132, 87, 87, 47, 47, 23, 23 },// Dutch/Latin/Suriname
+ { 73, 134, 27,11325,11515,11646,11708,11734,11760,190,131, 62, 26, 26, 26 },// Dzongkha/Tibetan/Bhutan
+ { 74, 66, 124,11786,11786,11992,11992,12039,12039,206,206, 47, 47, 23, 23 },// Embu/Latin/Kenya
+ { 75, 66, 248, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United States
+ { 75, 28, 248,12062,12062,12215,12215,12294,12294,153,153, 79, 79, 35, 35 },// English/Deseret/United States
+ { 75, 66, 5, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/American Samoa
+ { 75, 66, 8, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Anguilla
+ { 75, 66, 10, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Antigua and Barbuda
+ { 75, 66, 15, 0, 0,12377,12377, 132, 132, 85, 85, 50, 50, 23, 23 },// English/Latin/Australia
+ { 75, 66, 16, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Austria
+ { 75, 66, 18, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Bahamas
+ { 75, 66, 21, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Barbados
+ { 75, 66, 23, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Belgium
+ { 75, 66, 24, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Belize
+ { 75, 66, 26, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Bermuda
+ { 75, 66, 30, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Botswana
+ { 75, 66, 33, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/British Indian Ocean Territory
+ { 75, 66, 34, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/British Virgin Islands
+ { 75, 66, 38, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Burundi
+ { 75, 66, 40, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Cameroon
+ { 75, 66, 41, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Canada
+ { 75, 66, 45, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Cayman Islands
+ { 75, 66, 51, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Christmas Island
+ { 75, 66, 53, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Cocos Islands
+ { 75, 66, 58, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Cook Islands
+ { 75, 66, 63, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Cyprus
+ { 75, 66, 65, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Denmark
+ { 75, 66, 66, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Diego Garcia
+ { 75, 66, 68, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Dominica
+ { 75, 66, 74, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Eritrea
+ { 75, 66, 76, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Eswatini
+ { 75, 66, 78, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Europe
+ { 75, 66, 80, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Falkland Islands
+ { 75, 66, 82, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Fiji
+ { 75, 66, 83, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Finland
+ { 75, 66, 89, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Gambia
+ { 75, 66, 91, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Germany
+ { 75, 66, 92, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Ghana
+ { 75, 66, 93, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Gibraltar
+ { 75, 66, 96, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Grenada
+ { 75, 66, 98, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Guam
+ { 75, 66, 100, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Guernsey
+ { 75, 66, 103, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Guyana
+ { 75, 66, 107, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Hong Kong
+ { 75, 66, 110, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/India
+ { 75, 66, 111, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Indonesia
+ { 75, 66, 114, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Ireland
+ { 75, 66, 115, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Isle of Man
+ { 75, 66, 116, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Israel
+ { 75, 66, 119, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Jamaica
+ { 75, 66, 121, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Jersey
+ { 75, 66, 124, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Kenya
+ { 75, 66, 125, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Kiribati
+ { 75, 66, 133, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Lesotho
+ { 75, 66, 134, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Liberia
+ { 75, 66, 139, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Macao
+ { 75, 66, 141, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Madagascar
+ { 75, 66, 142, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Malawi
+ { 75, 66, 143, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Malaysia
+ { 75, 66, 144, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Maldives
+ { 75, 66, 146, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Malta
+ { 75, 66, 147, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Marshall Islands
+ { 75, 66, 150, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Mauritius
+ { 75, 66, 153, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Micronesia
+ { 75, 66, 158, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Montserrat
+ { 75, 66, 162, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Namibia
+ { 75, 66, 163, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Nauru
+ { 75, 66, 165, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Netherlands
+ { 75, 66, 167, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/New Zealand
+ { 75, 66, 169, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Nigeria
+ { 75, 66, 171, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Niue
+ { 75, 66, 172, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Norfolk Island
+ { 75, 66, 173, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Northern Mariana Islands
+ { 75, 66, 178, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Pakistan
+ { 75, 66, 179, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Palau
+ { 75, 66, 182, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Papua New Guinea
+ { 75, 66, 185, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Philippines
+ { 75, 66, 186, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Pitcairn
+ { 75, 66, 189, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/Puerto Rico
+ { 75, 66, 194, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Rwanda
+ { 75, 66, 196, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Saint Helena
+ { 75, 66, 197, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Saint Kitts and Nevis
+ { 75, 66, 198, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Saint Lucia
+ { 75, 66, 201, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Saint Vincent and Grenadines
+ { 75, 66, 202, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Samoa
+ { 75, 66, 208, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Seychelles
+ { 75, 66, 209, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Sierra Leone
+ { 75, 66, 210, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Singapore
+ { 75, 66, 211, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Sint Maarten
+ { 75, 66, 213, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Slovenia
+ { 75, 66, 214, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Solomon Islands
+ { 75, 66, 216, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/South Africa
+ { 75, 66, 219, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/South Sudan
+ { 75, 66, 222, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Sudan
+ { 75, 66, 225, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Sweden
+ { 75, 66, 226, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Switzerland
+ { 75, 66, 230, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Tanzania
+ { 75, 66, 234, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Tokelau
+ { 75, 66, 235, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Tonga
+ { 75, 66, 236, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Trinidad and Tobago
+ { 75, 66, 241, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Turks and Caicos Islands
+ { 75, 66, 242, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Tuvalu
+ { 75, 66, 243, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Uganda
+ { 75, 66, 245, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United Arab Emirates
+ { 75, 66, 246, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/United Kingdom
+ { 75, 66, 247, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United States Outlying Islands
+ { 75, 66, 249, 0, 0, 85, 85, 132, 132, 85, 85, 47, 47, 23, 23 },// English/Latin/United States Virgin Islands
+ { 75, 66, 252, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Vanuatu
+ { 75, 66, 258, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/world
+ { 75, 66, 260, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Zambia
+ { 75, 66, 261, 0, 0,12329,12329, 132, 132, 85, 85, 48, 48, 23, 23 },// English/Latin/Zimbabwe
+ { 75, 115, 246,12427,12427,12582,12582,12653,12653,155,155, 71, 71, 35, 35 },// English/Shavian/United Kingdom
+ { 76, 27, 193,12688,12688,12793,12688, 155, 155,105,105, 47,105, 26, 26 },// Erzya/Cyrillic/Russia
+ { 77, 66, 258,12840,12840,12930,12930, 132, 132, 90, 90, 47, 47, 23, 23 },// Esperanto/Latin/world
+ { 78, 66, 75,12977,12977,13067,13067,13125,13125, 90, 90, 58, 58, 23, 23 },// Estonian/Latin/Estonia
+ { 79, 66, 92,13148,13148,13234,13234,13281,13281, 86, 86, 47, 47, 23, 23 },// Ewe/Latin/Ghana
+ { 79, 66, 233,13148,13148,13234,13234,13281,13281, 86, 86, 47, 47, 23, 23 },// Ewe/Latin/Togo
+ { 80, 66, 40,13304,13304,13444,13444,13493,13493,140,140, 49, 49, 23, 23 },// Ewondo/Latin/Cameroon
+ { 81, 66, 81,13516,13516,13598,13645, 132, 132, 82, 82, 47, 58, 23, 23 },// Faroese/Latin/Faroe Islands
+ { 81, 66, 65,13516,13516,13598,13645, 132, 132, 82, 82, 47, 58, 23, 23 },// Faroese/Latin/Denmark
+ { 83, 66, 185,13703,13703,13790,13790,13837,13790, 87, 87, 47, 47, 37, 47 },// Filipino/Latin/Philippines
+ { 84, 66, 83,13874,13978,14106,14174,14266,14266,104,128, 68, 92, 23, 23 },// Finnish/Latin/Finland
+ { 85, 66, 84,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/France
+ { 85, 66, 4,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Algeria
+ { 85, 66, 23,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Belgium
+ { 85, 66, 25,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Benin
+ { 85, 66, 37,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Burkina Faso
+ { 85, 66, 38,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Burundi
+ { 85, 66, 40,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Cameroon
+ { 85, 66, 41,14289,14289,14435,14435, 132, 132, 84, 84, 63, 63, 23, 23 },// French/Latin/Canada
+ { 85, 66, 46,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Central African Republic
+ { 85, 66, 48,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Chad
+ { 85, 66, 55,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Comoros
+ { 85, 66, 56,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Congo - Brazzaville
+ { 85, 66, 57,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Congo - Kinshasa
+ { 85, 66, 67,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Djibouti
+ { 85, 66, 73,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Equatorial Guinea
+ { 85, 66, 85,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/French Guiana
+ { 85, 66, 86,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/French Polynesia
+ { 85, 66, 88,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Gabon
+ { 85, 66, 97,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Guadeloupe
+ { 85, 66, 102,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Guinea
+ { 85, 66, 104,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Haiti
+ { 85, 66, 118,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Ivory Coast
+ { 85, 66, 138,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Luxembourg
+ { 85, 66, 141,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Madagascar
+ { 85, 66, 145,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mali
+ { 85, 66, 148,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Martinique
+ { 85, 66, 149,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mauritania
+ { 85, 66, 150,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mauritius
+ { 85, 66, 151,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Mayotte
+ { 85, 66, 155,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Monaco
+ { 85, 66, 159,14289,14289,14498,14498, 132, 132, 84, 84, 60, 60, 23, 23 },// French/Latin/Morocco
+ { 85, 66, 166,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/New Caledonia
+ { 85, 66, 170,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Niger
+ { 85, 66, 191,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Reunion
+ { 85, 66, 194,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Rwanda
+ { 85, 66, 195,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Saint Barthelemy
+ { 85, 66, 199,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Saint Martin
+ { 85, 66, 200,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Saint Pierre and Miquelon
+ { 85, 66, 206,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Senegal
+ { 85, 66, 208,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Seychelles
+ { 85, 66, 226,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Switzerland
+ { 85, 66, 227,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Syria
+ { 85, 66, 233,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Togo
+ { 85, 66, 238,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Tunisia
+ { 85, 66, 252,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Vanuatu
+ { 85, 66, 256,14289,14289,14373,14373, 132, 132, 84, 84, 62, 62, 23, 23 },// French/Latin/Wallis and Futuna
+ { 86, 66, 117,14558,14558,14634,14634,14681,14681, 76, 76, 47, 47, 23, 23 },// Friulian/Latin/Italy
+ { 87, 66, 206,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Senegal
+ { 87, 1, 37,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Burkina Faso
+ { 87, 1, 40,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Cameroon
+ { 87, 1, 89,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Gambia
+ { 87, 1, 92,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Ghana
+ { 87, 1, 101,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Guinea-Bissau
+ { 87, 1, 102,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Guinea
+ { 87, 1, 134,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Liberia
+ { 87, 1, 149,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Mauritania
+ { 87, 1, 169,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Nigeria
+ { 87, 1, 170,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Niger
+ { 87, 1, 206,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Senegal
+ { 87, 1, 209,14850,14850,14979,14850,15072,15072,129,129, 93,129, 35, 35 },// Fulah/Adlam/Sierra Leone
+ { 87, 66, 37,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Burkina Faso
+ { 87, 66, 40,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Cameroon
+ { 87, 66, 89,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Gambia
+ { 87, 66, 92,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Ghana
+ { 87, 66, 101,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Guinea-Bissau
+ { 87, 66, 102,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Guinea
+ { 87, 66, 134,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Liberia
+ { 87, 66, 149,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Mauritania
+ { 87, 66, 169,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Nigeria
+ { 87, 66, 170,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Niger
+ { 87, 66, 209,14704,14704,14780,14780,14827,14827, 76, 76, 47, 47, 23, 23 },// Fulah/Latin/Sierra Leone
+ { 88, 66, 246,15107,15248,15414,15414,15474,15474,141,166, 60, 60, 23, 23 },// Gaelic/Latin/United Kingdom
+ { 89, 66, 92,15497,15588,15679,15679,15726,15726, 91, 91, 47, 47, 23, 23 },// Ga/Latin/Ghana
+ { 90, 66, 220,15749,15749,15835,15835,15894,15917, 86, 86, 59, 59, 23, 35 },// Galician/Latin/Spain
+ { 91, 66, 243,15952,15952,16048,16048, 132, 132, 96, 96, 47, 47, 23, 23 },// Ganda/Latin/Uganda
+ { 92, 33, 77,16095,16095,16095,16095,16143,16143, 48, 48, 48, 48, 23, 23 },// Geez/Ethiopic/Ethiopia
+ { 92, 33, 74,16095,16095,16095,16095,16143,16143, 48, 48, 48, 48, 23, 23 },// Geez/Ethiopic/Eritrea
+ { 93, 35, 90,16166,16166,16264,16264,16311,16311, 98, 98, 47, 47, 23, 23 },// Georgian/Georgian/Georgia
+ { 94, 66, 91,16334,16334,16416,16463, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Germany
+ { 94, 66, 16,16522,16522,16604,16651, 132, 132, 82, 82, 47, 58, 23, 23 },// German/Latin/Austria
+ { 94, 66, 23,16334,16334,16416,16463, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Belgium
+ { 94, 66, 117,16522,16522,16604,16651, 132, 132, 82, 82, 47, 58, 23, 23 },// German/Latin/Italy
+ { 94, 66, 136,16334,16334,16416,16463, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Liechtenstein
+ { 94, 66, 138,16334,16334,16416,16463, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Luxembourg
+ { 94, 66, 226,16334,16334,16416,16463, 132, 132, 82, 82, 47, 59, 23, 23 },// German/Latin/Switzerland
+ { 96, 39, 94,16709,16823,16937,16986,17035,17035,114,114, 49, 49, 23, 23 },// Greek/Greek/Greece
+ { 96, 39, 63,16709,16823,16937,16986,17035,17035,114,114, 49, 49, 23, 23 },// Greek/Greek/Cyprus
+ { 97, 66, 183,17058,17058,17058,17058, 155, 155,109,109,109,109, 26, 26 },// Guarani/Latin/Paraguay
+ { 98, 40, 110,17167,17167,17253,17253,17319,17319, 86, 86, 66, 66, 30, 30 },// Gujarati/Gujarati/India
+ { 99, 66, 124,17349,17349,17436,17436,17483,17483, 87, 87, 47, 47, 23, 23 },// Gusii/Latin/Kenya
+ { 101, 66, 169,17506,17506,17590,17590,17637,17637, 84, 84, 47, 47, 23, 23 },// Hausa/Latin/Nigeria
+ { 101, 4, 169,17660,17660,17758,17758, 155, 155, 98, 98, 54, 54, 26, 26 },// Hausa/Arabic/Nigeria
+ { 101, 4, 222,17660,17660,17758,17758, 155, 155, 98, 98, 54, 54, 26, 26 },// Hausa/Arabic/Sudan
+ { 101, 66, 92,17506,17506,17590,17590,17637,17637, 84, 84, 47, 47, 23, 23 },// Hausa/Latin/Ghana
+ { 101, 66, 170,17506,17506,17590,17590,17637,17637, 84, 84, 47, 47, 23, 23 },// Hausa/Latin/Niger
+ { 102, 66, 248,17812,17812,17906,17906, 155, 155, 94, 94, 58, 58, 26, 26 },// Hawaiian/Latin/United States
+ { 103, 47, 116,17964,17964,18035,18035, 155, 155, 71, 71, 57, 57, 26, 26 },// Hebrew/Hebrew/Israel
+ { 105, 29, 110,18092,18092,18164,18164,18222,18222, 72, 72, 58, 58, 29, 29 },// Hindi/Devanagari/India
+ { 105, 66, 110, 0, 0,12329, 85, 132, 132, 85, 85, 48, 47, 23, 23 },// Hindi/Latin/India
+ { 107, 66, 108,18251,18251,18348,18348,18411,18411, 97, 97, 63, 63, 24, 24 },// Hungarian/Latin/Hungary
+ { 108, 66, 109,18435,18435,18516,18516,18574,18574, 81, 81, 58, 58, 23, 23 },// Icelandic/Latin/Iceland
+ { 109, 66, 258, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Ido/Latin/world
+ { 110, 66, 169,18597,18597,18683,18683,18730,18730, 86, 86, 47, 47, 23, 23 },// Igbo/Latin/Nigeria
+ { 111, 66, 83,18753,18753,18892,18892,18968,18968,139,139, 76, 76, 24, 24 },// Inari Sami/Latin/Finland
+ { 112, 66, 111,18992,18992,19078,19078, 132, 132, 86, 86, 47, 47, 23, 23 },// Indonesian/Latin/Indonesia
+ { 114, 66, 258,19125,19125,19217,19217, 155, 6342, 92, 92, 47, 47, 26, 23 },// Interlingua/Latin/world
+ { 115, 66, 75,19264,19264,19348,19348, 132, 132, 84, 84, 60, 60, 23, 23 },// Interlingue/Latin/Estonia
+ { 116, 18, 41,19408,19408,19408,19408, 155, 155, 58, 58, 58, 58, 26, 26 },// Inuktitut/Canadian Aboriginal/Canada
+ { 116, 66, 41, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Inuktitut/Latin/Canada
+ { 118, 66, 114,19466,19466,19572,19572,19633,19633,106,106, 61, 61, 23, 23 },// Irish/Latin/Ireland
+ { 118, 66, 246,19466,19466,19572,19572,19633,19633,106,106, 61, 61, 23, 23 },// Irish/Latin/United Kingdom
+ { 119, 66, 117,19656,19656,19749,19749,10211,10211, 93, 93, 47, 47, 23, 23 },// Italian/Latin/Italy
+ { 119, 66, 203,19656,19656,19749,19749,10211,10211, 93, 93, 47, 47, 23, 23 },// Italian/Latin/San Marino
+ { 119, 66, 226,19656,19656,19749,19749,10211,10211, 93, 93, 47, 47, 23, 23 },// Italian/Latin/Switzerland
+ { 119, 66, 253,19656,19656,19749,19749,10211,10211, 93, 93, 47, 47, 23, 23 },// Italian/Latin/Vatican City
+ { 120, 53, 120, 6995, 6995, 6995, 6995, 155, 155, 38, 38, 38, 38, 26, 26 },// Japanese/Japanese/Japan
+ { 121, 66, 111,18992,18992,19796,19796, 132, 132, 86, 86, 47, 47, 23, 23 },// Javanese/Latin/Indonesia
+ { 122, 66, 169,19843,19843,20020,20020, 155, 155,177,177, 56, 56, 26, 26 },// Jju/Latin/Nigeria
+ { 123, 66, 206,20076,20076,20157,20157,20192,20192, 81, 81, 35, 35, 23, 23 },// Jola-Fonyi/Latin/Senegal
+ { 124, 66, 43,20215,20215,20299,20299, 132, 132, 84, 84, 47, 47, 23, 23 },// Kabuverdianu/Latin/Cape Verde
+ { 125, 66, 4,20346,20346,20429,20476,20523,20546, 83, 83, 47, 47, 23, 23 },// Kabyle/Latin/Algeria
+ { 126, 66, 40,20569,20569,20569,20569, 155, 155,102,102,102,102, 26, 26 },// Kako/Latin/Cameroon
+ { 127, 66, 95,20671,20769,20879,20879, 132, 132, 98,110, 49, 49, 23, 23 },// Kalaallisut/Latin/Greenland
+ { 128, 66, 124,20928,20928,21048,21048,21096,21096,120,120, 48, 48, 23, 23 },// Kalenjin/Latin/Kenya
+ { 129, 66, 124,21119,21119,21307,21307,21354,21354,188,188, 47, 47, 23, 23 },// Kamba/Latin/Kenya
+ { 130, 56, 110,21377,21377,21463,21525,21597,21597, 86, 86, 62, 72, 30, 30 },// Kannada/Kannada/India
+ { 132, 4, 110,21627,21698,21627,21770,21839,21839, 71, 72, 71, 69, 23, 23 },// Kashmiri/Arabic/India
+ { 132, 29, 110,21862,21936,21862,22006,22079,22079, 74, 70, 74, 73, 24, 24 },// Kashmiri/Devanagari/India
+ { 133, 27, 123,22103,22185,22267,22267,22326,22326, 82, 82, 59, 59, 23, 23 },// Kazakh/Cyrillic/Kazakhstan
+ { 134, 66, 40, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Kenyang/Latin/Cameroon
+ { 135, 60, 39,22349,22349,22349,22349,22419,22419, 70, 70, 70, 70, 23, 23 },// Khmer/Khmer/Cambodia
+ { 136, 66, 99, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Kiche/Latin/Guatemala
+ { 137, 66, 124,22442,22442,22626,22626,22673,22673,184,184, 47, 47, 23, 23 },// Kikuyu/Latin/Kenya
+ { 138, 66, 194,22696,22696,22795,22795, 155, 155, 99, 99, 59, 59, 26, 26 },// Kinyarwanda/Latin/Rwanda
+ { 141, 29, 110,22854,22854,22939,22854, 155, 155, 85, 85, 58, 85, 26, 26 },// Konkani/Devanagari/India
+ { 142, 63, 218,22997,22997,22997,22997,22997,22997, 38, 38, 38, 38, 38, 38 },// Korean/Korean/South Korea
+ { 142, 63, 50,22997,22997,22997,22997,22997,22997, 38, 38, 38, 38, 38, 38 },// Korean/Korean/China
+ { 142, 63, 174,22997,22997,22997,22997,22997,22997, 38, 38, 38, 38, 38, 38 },// Korean/Korean/North Korea
+ { 144, 66, 145,23035,23035,23122,23122,23167,23167, 87, 87, 45, 45, 23, 23 },// Koyraboro Senni/Latin/Mali
+ { 145, 66, 145,23035,23035,23122,23122,23167,23167, 87, 87, 45, 45, 23, 23 },// Koyra Chiini/Latin/Mali
+ { 146, 66, 134, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Kpelle/Latin/Liberia
+ { 146, 66, 102, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Kpelle/Latin/Guinea
+ { 148, 66, 239,23190,23190,23271,23271,23318,23318, 81, 81, 47, 47, 23, 23 },// Kurdish/Latin/Turkey
+ { 149, 66, 40,23341,23341,23483,23483, 155, 155,142,142, 50, 50, 26, 26 },// Kwasio/Latin/Cameroon
+ { 150, 27, 128,23533, 8494,23612,23659, 8620, 8620, 79, 79, 47, 58, 23, 23 },// Kyrgyz/Cyrillic/Kyrgyzstan
+ { 151, 66, 248,23717,23717,23717,23717, 155, 155,179,179,179,179, 26, 26 },// Lakota/Latin/United States
+ { 152, 66, 230,23896,23896,24006,24006,24088,24088,110,110, 82, 82, 23, 23 },// Langi/Latin/Tanzania
+ { 153, 65, 129,24111,24111,24185,24185, 155, 155, 74, 74, 60, 60, 26, 26 },// Lao/Lao/Laos
+ { 154, 66, 253,24245,24346,24444,24444, 155, 155,101, 98, 47, 47, 26, 26 },// Latin/Latin/Vatican City
+ { 155, 66, 131,24491,24491,24591,24591, 132, 132,100,100, 64, 64, 23, 23 },// Latvian/Latin/Latvia
+ { 158, 66, 57,24655,24655,24857,24857,24904,24904,202,202, 47, 47, 23, 23 },// Lingala/Latin/Congo - Kinshasa
+ { 158, 66, 7,24655,24655,24857,24857,24904,24904,202,202, 47, 47, 23, 23 },// Lingala/Latin/Angola
+ { 158, 66, 46,24655,24655,24857,24857,24904,24904,202,202, 47, 47, 23, 23 },// Lingala/Latin/Central African Republic
+ { 158, 66, 56,24655,24655,24857,24857,24904,24904,202,202, 47, 47, 23, 23 },// Lingala/Latin/Congo - Brazzaville
+ { 160, 66, 137,24927,25022,25119,25119,25188,25188, 95, 97, 69, 69, 23, 23 },// Lithuanian/Latin/Lithuania
+ { 161, 66, 258, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Lojban/Latin/world
+ { 162, 66, 91,25211,25295,25387,25434, 6342, 6342, 84, 92, 47, 59, 23, 23 },// Lower Sorbian/Latin/Germany
+ { 163, 66, 91,25493,25493,25577,25577, 132, 132, 84, 84, 58, 58, 23, 23 },// Low German/Latin/Germany
+ { 163, 66, 165,25493,25493,25577,25577, 132, 132, 84, 84, 58, 58, 23, 23 },// Low German/Latin/Netherlands
+ { 164, 66, 57,25635,25635,25733,25733,25781,25781, 98, 98, 48, 48, 23, 23 },// Luba-Katanga/Latin/Congo - Kinshasa
+ { 165, 66, 225, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Lule Sami/Latin/Sweden
+ { 165, 66, 175, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Lule Sami/Latin/Norway
+ { 166, 66, 124,25804,25804,25989,25989,26036,26036,185,185, 47, 47, 23, 23 },// Luo/Latin/Kenya
+ { 167, 66, 138,26059,26059,26143,26190, 132, 132, 84, 84, 47, 58, 23, 23 },// Luxembourgish/Latin/Luxembourg
+ { 168, 66, 124, 3283, 3283,26248,26248, 132, 132, 83, 83, 47, 47, 23, 23 },// Luyia/Latin/Kenya
+ { 169, 27, 140,26295,26295,26379,26379, 6494, 6494, 84, 84, 58, 58, 23, 23 },// Macedonian/Cyrillic/Macedonia
+ { 170, 66, 230,26437,26437,26523,26523, 132, 132, 86, 86, 47, 47, 23, 23 },// Machame/Latin/Tanzania
+ { 171, 29, 110,26570,26641,26712,18164,26769,26769, 71, 71, 57, 58, 28, 28 },// Maithili/Devanagari/India
+ { 172, 66, 160,26797,26797,27009,27009,27056,27056,212,212, 47, 47, 23, 23 },// Makhuwa-Meetto/Latin/Mozambique
+ { 173, 66, 230,27079,27079,26523,26523, 132, 132,263,263, 47, 47, 23, 23 },// Makonde/Latin/Tanzania
+ { 174, 66, 141,27342,27342,27433,27433, 132, 132, 91, 91, 47, 47, 23, 23 },// Malagasy/Latin/Madagascar
+ { 175, 74, 110,27480,27480,27567,27567,27628,27628, 87, 87, 61, 61, 31, 31 },// Malayalam/Malayalam/India
+ { 176, 66, 143,27659,27659,27740,27740, 9725, 9725, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Malaysia
+ { 176, 4, 35,27787,27787,27787,27787, 155, 155, 74, 74, 74, 74, 26, 26 },// Malay/Arabic/Brunei
+ { 176, 4, 143,27787,27787,27787,27787, 155, 155, 74, 74, 74, 74, 26, 26 },// Malay/Arabic/Malaysia
+ { 176, 66, 35,27659,27659,27740,27740, 9725, 9725, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Brunei
+ { 176, 66, 111,27659,27659,27740,27740, 9725, 9725, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Indonesia
+ { 176, 66, 210,27659,27659,27740,27740, 9725, 9725, 81, 81, 47, 47, 23, 23 },// Malay/Latin/Singapore
+ { 177, 66, 146,27861,27861,27946,27946,27993,28028, 85, 85, 47, 47, 35, 23 },// Maltese/Latin/Malta
+ { 179, 9, 110,28051,28138,28225,28282,28360,28396, 87, 87, 57, 78, 36, 37 },// Manipuri/Bangla/India
+ { 179, 78, 110, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Manipuri/Meitei Mayek/India
+ { 180, 66, 115,28433,28433,28572,28572, 155, 155,139,139,101,101, 26, 26 },// Manx/Latin/Isle of Man
+ { 181, 66, 167,28673,28755,28838,28838,28885,28885, 82, 83, 47, 47, 23, 23 },// Maori/Latin/New Zealand
+ { 182, 66, 49, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Mapuche/Latin/Chile
+ { 183, 29, 110,28908,28908,28993,28993,29058,29058, 85, 85, 65, 65, 31, 31 },// Marathi/Devanagari/India
+ { 185, 66, 124,29089,29089,29220,29220, 155, 155,131,131, 50, 50, 26, 26 },// Masai/Latin/Kenya
+ { 185, 66, 230,29089,29089,29220,29220, 155, 155,131,131, 50, 50, 26, 26 },// Masai/Latin/Tanzania
+ { 186, 4, 112,29270,29270,29270,29270, 155, 155, 69, 69, 69, 69, 26, 26 },// Mazanderani/Arabic/Iran
+ { 188, 66, 124,29339,29339,29424,29424,29471,29471, 85, 85, 47, 47, 23, 23 },// Meru/Latin/Kenya
+ { 189, 66, 40,29494,29494,29635,29635,29771,29771,141,141,136,136, 35, 35 },// Meta/Latin/Cameroon
+ { 190, 66, 41, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Mohawk/Latin/Canada
+ { 191, 27, 156,29806,29997,30188,30188,30286,30286,191,191, 98, 98, 37, 37 },// Mongolian/Cyrillic/Mongolia
+ { 191, 83, 50, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Mongolian/Mongolian/China
+ { 191, 83, 156,30323,30323,30534,30665,30286,30286,211,211,131,132, 37, 37 },// Mongolian/Mongolian/Mongolia
+ { 192, 66, 150,30797,30797,30864,30864,30910,30910, 67, 67, 46, 46, 23, 23 },// Morisyen/Latin/Mauritius
+ { 193, 66, 40,30933,30933,31071,31071,31118,31118,138,138, 47, 47, 23, 23 },// Mundang/Latin/Cameroon
+ { 194, 66, 248,31141,31141,31141,31141, 155, 155,124,124,124,124, 26, 26 },// Muscogee/Latin/United States
+ { 195, 66, 162,31265,31265, 85, 85, 132, 132,135,135, 47, 47, 23, 23 },// Nama/Latin/Namibia
+ { 197, 66, 248, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Navajo/Latin/United States
+ { 199, 29, 164,31400,31400,31400,31400,31484,31536, 84, 84, 84, 84, 52, 51 },// Nepali/Devanagari/Nepal
+ { 199, 29, 110,31400,31400,31400,31400,31484,31536, 84, 84, 84, 84, 52, 51 },// Nepali/Devanagari/India
+ { 201, 66, 40,31587,31587,31587,31587, 155, 155,164,164,164,164, 26, 26 },// Ngiemboon/Latin/Cameroon
+ { 202, 66, 40,31751,31751,31751,31751, 155, 155,173,173,173,173, 26, 26 },// Ngomba/Latin/Cameroon
+ { 203, 66, 169,31924,31924,32006,32056, 132, 132, 82, 82, 50, 49, 23, 23 },// Nigerian Pidgin/Latin/Nigeria
+ { 204, 90, 102,32105,32105,32210,32210,32271,32271,105,105, 61, 61, 23, 23 },// Nko/Nko/Guinea
+ { 205, 4, 112,32294,32294,32294,32294, 155, 155, 76, 76, 76, 76, 26, 26 },// Northern Luri/Arabic/Iran
+ { 205, 4, 113,32294,32294,32294,32294, 155, 155, 76, 76, 76, 76, 26, 26 },// Northern Luri/Arabic/Iraq
+ { 206, 66, 175,32370,32370,32514,32514,32572,32572,144,144, 58, 58, 23, 23 },// Northern Sami/Latin/Norway
+ { 206, 66, 83,32370,32370,32595,32595,32572,32572,144,144, 59, 59, 23, 23 },// Northern Sami/Latin/Finland
+ { 206, 66, 225,32370,32370,32514,32514,32572,32572,144,144, 58, 58, 23, 23 },// Northern Sami/Latin/Sweden
+ { 207, 66, 216,32654,32654,32759,32759,32823,32823,105,105, 64, 64, 23, 23 },// Northern Sotho/Latin/South Africa
+ { 208, 66, 261,32846,32846,32957,32957,33008,33008,111,111, 51, 51, 23, 23 },// North Ndebele/Latin/Zimbabwe
+ { 209, 66, 175,33031,33031,13598,33113, 132, 132, 82, 82, 47, 58, 23, 23 },// Norwegian Bokmal/Latin/Norway
+ { 209, 66, 224,33031,33031,13598,33113, 132, 132, 82, 82, 47, 58, 23, 23 },// Norwegian Bokmal/Latin/Svalbard and Jan Mayen
+ { 210, 66, 175,33031,33031,13598,33113, 132, 132, 82, 82, 47, 58, 23, 23 },// Norwegian Nynorsk/Latin/Norway
+ { 211, 66, 219,33171,33171,33266,33266,33319,33319, 95, 95, 53, 53, 23, 23 },// Nuer/Latin/South Sudan
+ { 212, 66, 142,33342,33342,33432,33432, 155, 155, 90, 90, 47, 47, 26, 26 },// Nyanja/Latin/Malawi
+ { 213, 66, 243, 8876, 8876, 9027, 9027, 132, 132,151,151, 47, 47, 23, 23 },// Nyankole/Latin/Uganda
+ { 214, 66, 84,33479,33561,33676,33676,33734,33734, 82,115, 58, 58, 23, 23 },// Occitan/Latin/France
+ { 214, 66, 220,33757,33757,33830,33830,33734,33877, 73, 73, 47, 47, 23, 23 },// Occitan/Latin/Spain
+ { 215, 91, 110,33900,33900,33900,33900,33985,33985, 85, 85, 85, 85, 31, 31 },// Odia/Odia/India
+ { 220, 66, 77,34016,34016,34126,34126, 132, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Ethiopia
+ { 220, 66, 124,34016,34016,34126,34126,34173,34173,110,110, 47, 47, 23, 23 },// Oromo/Latin/Kenya
+ { 221, 101, 248,34196,34196,34527,34527, 155, 155,331,331,155,155, 26, 26 },// Osage/Osage/United States
+ { 222, 27, 90,34682,34763,34848,34910, 8620, 8620, 81, 85, 62, 59, 23, 23 },// Ossetic/Cyrillic/Georgia
+ { 222, 27, 193,34682,34763,34848,34910, 8620, 8620, 81, 85, 62, 59, 23, 23 },// Ossetic/Cyrillic/Russia
+ { 226, 66, 62,34969,34969,35055,35102, 155, 155, 86, 86, 47, 47, 26, 26 },// Papiamento/Latin/Curacao
+ { 226, 66, 13,34969,34969,35055,35102, 155, 155, 86, 86, 47, 47, 26, 26 },// Papiamento/Latin/Aruba
+ { 227, 4, 1,35149,35217,35285,35217, 155,35352, 68, 68, 67, 68, 26, 23 },// Pashto/Arabic/Afghanistan
+ { 227, 4, 178,35149,35217,35285,35217, 155,35352, 68, 68, 67, 68, 26, 23 },// Pashto/Arabic/Pakistan
+ { 228, 4, 112,29270,35375,29270,29270,35448,35448, 69, 73, 69, 69, 23, 23 },// Persian/Arabic/Iran
+ { 228, 4, 1,35471,35471,35471,35538,35352,35352, 67, 67, 67, 61, 23, 23 },// Persian/Arabic/Afghanistan
+ { 230, 66, 187,35599,35695,35793,35793,35840,35863, 96, 98, 47, 47, 23, 23 },// Polish/Latin/Poland
+ { 231, 66, 32,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Brazil
+ { 231, 66, 7,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Angola
+ { 231, 66, 43,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Cape Verde
+ { 231, 66, 73,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Equatorial Guinea
+ { 231, 66, 101,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Guinea-Bissau
+ { 231, 66, 138,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Luxembourg
+ { 231, 66, 139,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Macao
+ { 231, 66, 160,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Mozambique
+ { 231, 66, 188,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Portugal
+ { 231, 66, 204,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Sao Tome and Principe
+ { 231, 66, 226,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Switzerland
+ { 231, 66, 232,35886,35886,35974,35974, 132, 132, 88, 88, 59, 59, 23, 23 },// Portuguese/Latin/Timor-Leste
+ { 232, 66, 187,36033,36033,36123,36123,36170,36170, 90, 90, 47, 47, 23, 23 },// Prussian/Latin/Poland
+ { 233, 41, 110,36193,36193,36260,36260,36309,36309, 67, 67, 49, 49, 27, 27 },// Punjabi/Gurmukhi/India
+ { 233, 4, 178,36336,36336,36336,36336, 155, 155, 66, 66, 66, 66, 26, 26 },// Punjabi/Arabic/Pakistan
+ { 234, 66, 184,36402,36402,36489,36489, 155, 155, 87, 87, 47, 47, 26, 26 },// Quechua/Latin/Peru
+ { 234, 66, 28,36402,36402,36489,36489, 155, 155, 87, 87, 47, 47, 26, 26 },// Quechua/Latin/Bolivia
+ { 234, 66, 70,36402,36402,36489,36489, 155, 155, 87, 87, 47, 47, 26, 26 },// Quechua/Latin/Ecuador
+ { 235, 66, 192,36536,36536,36633,36633,36692,36692, 97, 97, 59, 59, 23, 23 },// Romanian/Latin/Romania
+ { 235, 66, 154,36536,36536,36633,36633,36692,36692, 97, 97, 59, 59, 23, 23 },// Romanian/Latin/Moldova
+ { 236, 66, 226,36715,36806,36930,36930,36996,36996, 91,124, 66, 66, 23, 23 },// Romansh/Latin/Switzerland
+ { 237, 66, 230,37019,37019,37212,37212,37250,37250,193,193, 38, 38, 23, 23 },// Rombo/Latin/Tanzania
+ { 238, 66, 38,37273,37273,37378,37378, 155, 155,105,105, 59, 59, 26, 26 },// Rundi/Latin/Burundi
+ { 239, 27, 193, 8494,37437,37518,37579, 8620, 8620, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Russia
+ { 239, 27, 22, 8494,37437,37518,37579, 8620, 8620, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Belarus
+ { 239, 27, 123, 8494,37437,37518,37579, 8620, 8620, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Kazakhstan
+ { 239, 27, 128, 8494,37437,37518,37579, 8620, 8620, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Kyrgyzstan
+ { 239, 27, 154, 8494,37437,37518,37579, 8620, 8620, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Moldova
+ { 239, 27, 244, 8494,37437,37518,37579, 8620, 8620, 79, 81, 61, 61, 23, 23 },// Russian/Cyrillic/Ukraine
+ { 240, 66, 230,26437,26437,26523,26523, 132, 132, 86, 86, 47, 47, 23, 23 },// Rwa/Latin/Tanzania
+ { 241, 66, 74, 392, 392, 509, 509, 556, 556,117,117, 47, 47, 23, 23 },// Saho/Latin/Eritrea
+ { 242, 27, 193,37640,37755,37875,37875,37924,37924,115,120, 49, 49, 23, 23 },// Sakha/Cyrillic/Russia
+ { 243, 66, 124,37947,37947,38119,38119,38166,38166,172,172, 47, 47, 23, 23 },// Samburu/Latin/Kenya
+ { 245, 66, 46,38189,38189,38279,38279,38326,38326, 90, 90, 47, 47, 23, 23 },// Sango/Latin/Central African Republic
+ { 246, 66, 230,38349,38349,38465,38465, 155, 155,116,116, 47, 47, 26, 26 },// Sangu/Latin/Tanzania
+ { 247, 29, 110,38512,38512,38631,38631, 155,26769,119,119, 82, 82, 26, 28 },// Sanskrit/Devanagari/India
+ { 248, 93, 110,38713,38713,38795,38795,38841,38841, 82, 82, 46, 46, 23, 23 },// Santali/Ol Chiki/India
+ { 248, 29, 110, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Santali/Devanagari/India
+ { 249, 66, 117,38864,38864,38964,38964,39011,39011,100,100, 47, 47, 23, 23 },// Sardinian/Latin/Italy
+ { 251, 66, 160,39034,39034,39121,39121, 132, 132, 87, 87, 47, 47, 23, 23 },// Sena/Latin/Mozambique
+ { 252, 27, 207,39168,39168,39248,39248, 6494, 6494, 80, 80, 47, 47, 23, 23 },// Serbian/Cyrillic/Serbia
+ { 252, 27, 29,39168,39168,39248,39248, 6494, 6494, 80, 80, 47, 47, 23, 23 },// Serbian/Cyrillic/Bosnia and Herzegovina
+ { 252, 27, 126,39168,39168,39295,39295, 6494, 6494, 80, 80, 49, 49, 23, 23 },// Serbian/Cyrillic/Kosovo
+ { 252, 27, 157,39168,39168,39295,39295, 6494, 6494, 80, 80, 49, 49, 23, 23 },// Serbian/Cyrillic/Montenegro
+ { 252, 66, 29,39344,39344,39424,39424, 6342, 6342, 80, 80, 47, 47, 23, 23 },// Serbian/Latin/Bosnia and Herzegovina
+ { 252, 66, 126,39344,39344,39471,39471, 6342, 6342, 80, 80, 49, 49, 23, 23 },// Serbian/Latin/Kosovo
+ { 252, 66, 157,39344,39344,39471,39471, 6342, 6342, 80, 80, 49, 49, 23, 23 },// Serbian/Latin/Montenegro
+ { 252, 66, 207,39344,39344,39424,39424, 6342, 6342, 80, 80, 47, 47, 23, 23 },// Serbian/Latin/Serbia
+ { 253, 66, 230,39520,39520,26523,26523, 132, 132, 83, 83, 47, 47, 23, 23 },// Shambala/Latin/Tanzania
+ { 254, 66, 261,39603,39603,39702,39702,39749,39749, 99, 99, 47, 47, 23, 23 },// Shona/Latin/Zimbabwe
+ { 255, 141, 50,39772,39772,39772,39772, 155, 155, 37, 37, 37, 37, 26, 26 },// Sichuan Yi/Yi/China
+ { 256, 66, 117,39809,39809,39906,39906,39953,39953, 97, 97, 47, 47, 23, 23 },// Sicilian/Latin/Italy
+ { 257, 66, 77, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Sidamo/Latin/Ethiopia
+ { 258, 66, 187,39976,40072,40170,40170,35840,35840, 96, 98, 47, 47, 23, 23 },// Silesian/Latin/Poland
+ { 259, 4, 178,40217,40217,40217,40217, 132, 132, 71, 71, 71, 71, 23, 23 },// Sindhi/Arabic/Pakistan
+ { 259, 29, 110,40288,40362,40436,40489,40540,40569, 74, 74, 53, 51, 29, 30 },// Sindhi/Devanagari/India
+ { 260, 119, 221,40599,40599,40694,40752,40812,40812, 95, 95, 58, 60, 31, 31 },// Sinhala/Sinhala/Sri Lanka
+ { 261, 66, 83, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Skolt Sami/Latin/Finland
+ { 262, 66, 212,40843,40924,41012,41012, 6342, 6342, 81, 88, 47, 47, 23, 23 },// Slovak/Latin/Slovakia
+ { 263, 66, 213,41059,41059,41144,41144, 6342, 6342, 85, 85, 58, 58, 23, 23 },// Slovenian/Latin/Slovenia
+ { 264, 66, 243,15952,15952,16048,16048, 132, 132, 96, 96, 47, 47, 23, 23 },// Soga/Latin/Uganda
+ { 265, 66, 215,41202,41298,41486,41486,41533,41533, 96,188, 47, 47, 23, 23 },// Somali/Latin/Somalia
+ { 265, 66, 67,41202,41298,41486,41486,41533,41533, 96,188, 47, 47, 23, 23 },// Somali/Latin/Djibouti
+ { 265, 66, 77,41202,41298,41486,41486,41533,41533, 96,188, 47, 47, 23, 23 },// Somali/Latin/Ethiopia
+ { 265, 66, 124,41202,41298,41486,41486,41533,41533, 96,188, 47, 47, 23, 23 },// Somali/Latin/Kenya
+ { 266, 4, 112, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Kurdish/Arabic/Iran
+ { 266, 4, 113, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Kurdish/Arabic/Iraq
+ { 267, 66, 225, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Sami/Latin/Sweden
+ { 267, 66, 175, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Southern Sami/Latin/Norway
+ { 268, 66, 216,41556,41556,41660,41660, 155, 155,104,104, 47, 47, 26, 26 },// Southern Sotho/Latin/South Africa
+ { 268, 66, 133,41556,41556,41660,41660, 155, 155,104,104, 47, 47, 26, 26 },// Southern Sotho/Latin/Lesotho
+ { 269, 66, 216,41707,41707,41806,41806, 155, 155, 99, 99, 47, 47, 26, 26 },// South Ndebele/Latin/South Africa
+ { 270, 66, 220,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Spain
+ { 270, 66, 11,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Argentina
+ { 270, 66, 24,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Belize
+ { 270, 66, 28,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Bolivia
+ { 270, 66, 32,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Brazil
+ { 270, 66, 42,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Canary Islands
+ { 270, 66, 47,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Ceuta and Melilla
+ { 270, 66, 49,41853,41853,42012,41941,41989,41989, 88, 88, 60, 48, 23, 23 },// Spanish/Latin/Chile
+ { 270, 66, 54,41853,41853,42012,41941,41989,41989, 88, 88, 60, 48, 23, 23 },// Spanish/Latin/Colombia
+ { 270, 66, 59,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Costa Rica
+ { 270, 66, 61,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Cuba
+ { 270, 66, 69,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Dominican Republic
+ { 270, 66, 70,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Ecuador
+ { 270, 66, 72,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/El Salvador
+ { 270, 66, 73,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Equatorial Guinea
+ { 270, 66, 99,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Guatemala
+ { 270, 66, 106,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Honduras
+ { 270, 66, 130,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Latin America
+ { 270, 66, 152,41853,41853,42072,42072,41989,41989, 88, 88, 47, 47, 23, 23 },// Spanish/Latin/Mexico
+ { 270, 66, 168,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Nicaragua
+ { 270, 66, 181,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Panama
+ { 270, 66, 183,41853,41853,42012,42012,41989,41989, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Paraguay
+ { 270, 66, 184,36402,42119,42206,42265,41989,41989, 87, 87, 59, 59, 23, 23 },// Spanish/Latin/Peru
+ { 270, 66, 185,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Philippines
+ { 270, 66, 189,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/Puerto Rico
+ { 270, 66, 248,41853,41853,41941,41941,41989,41989, 88, 88, 48, 48, 23, 23 },// Spanish/Latin/United States
+ { 270, 66, 250,36402,42119,42206,42265,41989,41989, 87, 87, 59, 59, 23, 23 },// Spanish/Latin/Uruguay
+ { 270, 66, 254,41853,41853,42012,42012,41989,41989, 88, 88, 60, 60, 23, 23 },// Spanish/Latin/Venezuela
+ { 271, 135, 159,42324,42324,42404,42404,42451,42451, 80, 80, 47, 47, 23, 23 },// Standard Moroccan Tamazight/Tifinagh/Morocco
+ { 272, 66, 111,42474,42474,42560,42560,42607,42607, 86, 86, 47, 47, 23, 23 },// Sundanese/Latin/Indonesia
+ { 273, 66, 230, 3283, 3283,26523,26523, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Tanzania
+ { 273, 66, 57, 3283, 3283,26523,26523, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Congo - Kinshasa
+ { 273, 66, 124, 3283, 3283,26523,26523, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Kenya
+ { 273, 66, 243, 3283, 3283,26523,26523, 132, 132, 83, 83, 47, 47, 23, 23 },// Swahili/Latin/Uganda
+ { 274, 66, 216,42630,42630,42743,42743, 155, 155,113,113, 47, 47, 26, 26 },// Swati/Latin/South Africa
+ { 274, 66, 76,42630,42630,42743,42743, 155, 155,113,113, 47, 47, 26, 26 },// Swati/Latin/Eswatini
+ { 275, 66, 225,42790,42790,42875,42875, 132, 132, 85, 85, 58, 58, 23, 23 },// Swedish/Latin/Sweden
+ { 275, 66, 2,42790,42790,42875,42875, 132, 132, 85, 85, 58, 58, 23, 23 },// Swedish/Latin/Aland Islands
+ { 275, 66, 83,42790,42790,42875,42875, 132, 132, 85, 85, 58, 58, 23, 23 },// Swedish/Latin/Finland
+ { 276, 66, 226,42933,42933,16416,16416, 132, 132, 85, 85, 47, 47, 23, 23 },// Swiss German/Latin/Switzerland
+ { 276, 66, 84,42933,42933,16416,16416, 132, 132, 85, 85, 47, 47, 23, 23 },// Swiss German/Latin/France
+ { 276, 66, 136,42933,42933,16416,16416, 132, 132, 85, 85, 47, 47, 23, 23 },// Swiss German/Latin/Liechtenstein
+ { 277, 123, 113,43018,43018,43100,43100,43166,43189, 82, 82, 66, 66, 23, 23 },// Syriac/Syriac/Iraq
+ { 277, 123, 227,43018,43018,43100,43100,43166,43189, 82, 82, 66, 66, 23, 23 },// Syriac/Syriac/Syria
+ { 278, 135, 159,42324,42324,42404,42404,42451,42451, 80, 80, 47, 47, 23, 23 },// Tachelhit/Tifinagh/Morocco
+ { 278, 66, 159,43212,43212,43292,43292,43339,43339, 80, 80, 47, 47, 23, 23 },// Tachelhit/Latin/Morocco
+ { 280, 127, 255, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Tai Dam/Tai Viet/Vietnam
+ { 281, 66, 124,43362,43362,43582,43582,43629,43629,220,220, 47, 47, 23, 23 },// Taita/Latin/Kenya
+ { 282, 27, 229,43652,43652,23612,23612, 8620, 8620, 70, 70, 47, 47, 23, 23 },// Tajik/Cyrillic/Tajikistan
+ { 283, 129, 110,43722,43722,43807,43807,43864,43864, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/India
+ { 283, 129, 143,43722,43722,43807,43807,43864,43864, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/Malaysia
+ { 283, 129, 210,43722,43722,43807,43807,43864,43864, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/Singapore
+ { 283, 129, 221,43722,43722,43807,43807,43864,43864, 85, 85, 57, 57, 30, 30 },// Tamil/Tamil/Sri Lanka
+ { 284, 66, 228,43894,43894,44035,44035,44082,44082,141,141, 47, 47, 23, 23 },// Taroko/Latin/Taiwan
+ { 285, 66, 170,23035,23035,23122,23122,23167,23167, 87, 87, 45, 45, 23, 23 },// Tasawaq/Latin/Niger
+ { 286, 27, 193,44105,44105,44185,44185, 155, 155, 80, 80, 61, 61, 26, 26 },// Tatar/Cyrillic/Russia
+ { 287, 131, 110,44246,44246,44331,44331,44392,44392, 85, 85, 61, 61, 30, 30 },// Telugu/Telugu/India
+ { 288, 66, 243,44422,44422,44515,44515,44562,44562, 93, 93, 47, 47, 23, 23 },// Teso/Latin/Uganda
+ { 288, 66, 124,44422,44422,44515,44515,44562,44562, 93, 93, 47, 47, 23, 23 },// Teso/Latin/Kenya
+ { 289, 133, 231,44585,44585,44682,44682,44682,44682, 97, 97, 62, 62, 62, 62 },// Thai/Thai/Thailand
+ { 290, 134, 50,44744,44902,11646,11646, 155, 155,158,146, 62, 62, 26, 26 },// Tibetan/Tibetan/China
+ { 290, 134, 110,44744,44902,11646,11646, 155, 155,158,146, 62, 62, 26, 26 },// Tibetan/Tibetan/India
+ { 291, 33, 74,45048,45048,45109,45109, 1649, 1649, 61, 61, 45, 45, 23, 23 },// Tigre/Ethiopic/Eritrea
+ { 292, 33, 77,45154,45154,45207,45207,45242,45242, 53, 53, 35, 35, 23, 23 },// Tigrinya/Ethiopic/Ethiopia
+ { 292, 33, 74,45154,45154,45207,45207,45242,45242, 53, 53, 35, 35, 23, 23 },// Tigrinya/Ethiopic/Eritrea
+ { 294, 66, 182,45265,45265,45341,45341, 155, 155, 76, 76, 46, 46, 26, 26 },// Tok Pisin/Latin/Papua New Guinea
+ { 295, 66, 235,45387,45473,45559,45559,45609,45609, 86, 86, 50, 50, 26, 26 },// Tongan/Latin/Tonga
+ { 296, 66, 216,45635,45635,45756,45756, 155, 155,121,121, 47, 47, 26, 26 },// Tsonga/Latin/South Africa
+ { 297, 66, 216,45803,45803,45919,45919, 155, 155,116,116, 47, 47, 26, 26 },// Tswana/Latin/South Africa
+ { 297, 66, 30,45803,45803,45919,45919, 155, 155,116,116, 47, 47, 26, 26 },// Tswana/Latin/Botswana
+ { 298, 66, 239,45966,45966,46040,46040,46087,46087, 74, 74, 47, 47, 23, 23 },// Turkish/Latin/Turkey
+ { 298, 66, 63,45966,45966,46040,46040,46087,46087, 74, 74, 47, 47, 23, 23 },// Turkish/Latin/Cyprus
+ { 299, 66, 240,46110,46186,46262,46311,46361,46361, 76, 76, 49, 50, 23, 23 },// Turkmen/Latin/Turkmenistan
+ { 301, 66, 169,46384,46384,46536,46536, 155, 155,152,152, 47, 47, 26, 26 },// Tyap/Latin/Nigeria
+ { 303, 27, 244,46583,46677,46763,46763,46829,46852, 94, 86, 66, 66, 23, 23 },// Ukrainian/Cyrillic/Ukraine
+ { 304, 66, 91,46875,46960,47052,47099, 6342, 6342, 85, 92, 47, 59, 23, 23 },// Upper Sorbian/Latin/Germany
+ { 305, 4, 178,47158,47158,47158,47158, 132, 132, 67, 67, 67, 67, 23, 23 },// Urdu/Arabic/Pakistan
+ { 305, 4, 110,47158,47158,47158,47158, 132, 132, 67, 67, 67, 67, 23, 23 },// Urdu/Arabic/India
+ { 306, 4, 50,47225,47225,47225,47225, 155, 155, 83, 83, 83, 83, 26, 26 },// Uyghur/Arabic/China
+ { 307, 66, 251,47308,47382,47456,47503,47550,47550, 74, 74, 47, 47, 23, 23 },// Uzbek/Latin/Uzbekistan
+ { 307, 4, 1,35471,35471,47573,47573, 155, 155, 67, 67, 46, 46, 26, 26 },// Uzbek/Arabic/Afghanistan
+ { 307, 27, 251,47619,47619, 8573, 8573, 8620, 8620, 70, 70, 47, 47, 23, 23 },// Uzbek/Cyrillic/Uzbekistan
+ { 308, 139, 134,47689,47689,47749,47749, 155, 155, 60, 60, 37, 37, 26, 26 },// Vai/Vai/Liberia
+ { 308, 66, 134, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Vai/Latin/Liberia
+ { 309, 66, 216,47786,47786,47896,47896, 155, 155,110,110, 47, 47, 26, 26 },// Venda/Latin/South Africa
+ { 310, 66, 255,47943,48041,47943,48139, 155, 155, 98, 98, 98, 74, 26, 26 },// Vietnamese/Latin/Vietnam
+ { 311, 66, 258,48213,48213,48286,48333,48380,48380, 73, 73, 47, 47, 23, 23 },// Volapuk/Latin/world
+ { 312, 66, 230,26437,26437,26523,26523, 132, 132, 86, 86, 47, 47, 23, 23 },// Vunjo/Latin/Tanzania
+ { 313, 66, 23, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Walloon/Latin/Belgium
+ { 314, 66, 226,48403,48403,48501,48501,48548,48548, 98, 98, 47, 47, 23, 23 },// Walser/Latin/Switzerland
+ { 315, 66, 15, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Warlpiri/Latin/Australia
+ { 316, 66, 246,48571,48571,48657,48708,48763,48763, 86, 86, 51, 55, 25, 25 },// Welsh/Latin/United Kingdom
+ { 317, 4, 178, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Western Balochi/Arabic/Pakistan
+ { 317, 4, 1, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Western Balochi/Arabic/Afghanistan
+ { 317, 4, 112, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Western Balochi/Arabic/Iran
+ { 317, 4, 176, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Western Balochi/Arabic/Oman
+ { 317, 4, 245, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Western Balochi/Arabic/United Arab Emirates
+ { 318, 66, 165,48788,48788,48882,48882, 132, 132, 94, 94, 47, 47, 23, 23 },// Western Frisian/Latin/Netherlands
+ { 319, 33, 77,45048,45048,45109,45109, 1649, 1649, 61, 61, 45, 45, 23, 23 },// Wolaytta/Ethiopic/Ethiopia
+ { 320, 66, 206,48929,48929,49012,49012, 155, 155, 83, 83, 46, 46, 26, 26 },// Wolof/Latin/Senegal
+ { 321, 66, 216,49058,49148,49239,49286, 155, 155, 90, 91, 47, 48, 26, 26 },// Xhosa/Latin/South Africa
+ { 322, 66, 40,49334,49334,49524,49524, 155, 155,190,190, 50, 50, 26, 26 },// Yangben/Latin/Cameroon
+ { 323, 47, 244,49574,49574,49665,49574, 155, 155, 91, 91, 57, 91, 26, 26 },// Yiddish/Hebrew/Ukraine
+ { 324, 66, 169,49722,49794,49914,49953,50007,50007, 72,120, 39, 54, 26, 26 },// Yoruba/Latin/Nigeria
+ { 324, 66, 25,50033,50106,50239,50279,50334,50334, 73,133, 40, 55, 26, 26 },// Yoruba/Latin/Benin
+ { 325, 66, 170,23035,23035,23122,23122,23167,23167, 87, 87, 45, 45, 23, 23 },// Zarma/Latin/Niger
+ { 326, 66, 50,50360,50360,50360,50360, 155, 155,121,121,121,121, 26, 26 },// Zhuang/Latin/China
+ { 327, 66, 216,50481,50481,50571,50571, 132,50618, 90, 90, 47, 47, 23, 23 },// Zulu/Latin/South Africa
+ { 328, 66, 32,50641,50641,50727,50727,50789,50789, 86, 86, 62, 62, 38, 38 },// Kaingang/Latin/Brazil
+ { 329, 66, 32,50827,50827,50927,50927,50962,50962,100,100, 35, 35, 23, 23 },// Nheengatu/Latin/Brazil
+ { 329, 66, 54,50827,50827,50927,50927,50962,50962,100,100, 35, 35, 23, 23 },// Nheengatu/Latin/Colombia
+ { 329, 66, 254,50827,50827,50927,50927,50962,50962,100,100, 35, 35, 23, 23 },// Nheengatu/Latin/Venezuela
+ { 330, 29, 110,50985,50985,50985,50985, 155, 155, 73, 73, 73, 73, 26, 26 },// Haryanvi/Devanagari/India
+ { 331, 66, 91,51058,51058,51152,51152, 132, 132, 94, 94, 47, 47, 23, 23 },// Northern Frisian/Latin/Germany
+ { 332, 29, 110, 5834, 5834, 5834, 5834, 155, 155, 72, 72, 72, 72, 26, 26 },// Rajasthani/Devanagari/India
+ { 333, 27, 193, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Moksha/Cyrillic/Russia
+ { 334, 66, 258,51199,51199,51199,51199, 155, 155, 86, 86, 86, 86, 26, 26 },// Toki Pona/Latin/world
+ { 335, 66, 214,51285,51285,51285,51285, 155, 155, 76, 76, 76, 76, 26, 26 },// Pijin/Latin/Solomon Islands
+ { 336, 66, 169, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Obolo/Latin/Nigeria
+ { 337, 4, 178,51361,51361,51430,51430, 155, 155, 69, 69, 48, 48, 26, 26 },// Baluchi/Arabic/Pakistan
+ { 337, 66, 178,51478,51478,51560,51560, 155, 155, 82, 82, 47, 47, 26, 26 },// Baluchi/Latin/Pakistan
+ { 338, 66, 117,51607,51690,51806,51865,51957,51957, 83,116, 59, 92, 35, 35 },// Ligurian/Latin/Italy
+ { 339, 142, 161, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Rohingya/Hanifi/Myanmar
+ { 339, 142, 20, 1348, 1348, 1348, 1348, 155, 155, 47, 47, 47, 47, 26, 26 },// Rohingya/Hanifi/Bangladesh
+ { 340, 4, 178,36336,36336,36336,36336,35352,35352, 66, 66, 66, 66, 23, 23 },// Torwali/Arabic/Pakistan
+ { 341, 66, 25,51992,51992,52190,52190, 155, 155,198,198, 44, 44, 26, 26 },// Anii/Latin/Benin
+ { 342, 29, 110,18092,18092,18164,18164,18222,18222, 72, 72, 58, 58, 29, 29 },// Kangri/Devanagari/India
+ { 343, 66, 117,52234,52234,52318,52318,52365,52365, 84, 84, 47, 47, 23, 23 },// Venetian/Latin/Italy
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },// trailing zeros
};
-static const char16_t months_data[] = {
-0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61, 0x72,
-0x63, 0x68, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x65, 0x3b, 0x4a, 0x75,
-0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x4f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x63,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72,
-0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70,
-0x3b, 0x4f, 0x63, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
-0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x31, 0x3b, 0x32, 0x3b, 0x33,
-0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31,
-0x32, 0x41, 0x6d, 0x61, 0x6a, 0x6a, 0x69, 0x69, 0x3b, 0x47, 0x75, 0x72, 0x61, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6c, 0x61,
-0x3b, 0x42, 0x69, 0x74, 0x6f, 0x6f, 0x74, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x45, 0x6c, 0x62, 0x61, 0x3b, 0x43, 0x61,
-0x61, 0x6d, 0x73, 0x61, 0x3b, 0x57, 0x61, 0x78, 0x61, 0x62, 0x61, 0x6a, 0x6a, 0x69, 0x69, 0x3b, 0x41, 0x64, 0x6f, 0x6f,
-0x6c, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x48, 0x61, 0x67, 0x61, 0x79, 0x79, 0x61, 0x3b, 0x46, 0x75, 0x75, 0x6c, 0x62,
-0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6e, 0x6b, 0x6f, 0x6c, 0x6f, 0x6c, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x53, 0x61, 0x64,
-0x61, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x75, 0x64, 0x64, 0x65, 0x65, 0x41, 0x6d, 0x61, 0x3b, 0x47, 0x75, 0x72, 0x3b, 0x42,
-0x69, 0x74, 0x3b, 0x45, 0x6c, 0x62, 0x3b, 0x43, 0x61, 0x6d, 0x3b, 0x57, 0x61, 0x78, 0x3b, 0x41, 0x64, 0x6f, 0x3b, 0x48,
-0x61, 0x67, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4f, 0x6e, 0x6b, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x4d, 0x75, 0x64, 0x41, 0x3b,
-0x47, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x43, 0x3b, 0x57, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x46, 0x3b, 0x4f, 0x3b, 0x53, 0x3b,
-0x4d, 0x4d, 0x30, 0x31, 0x3b, 0x4d, 0x30, 0x32, 0x3b, 0x4d, 0x30, 0x33, 0x3b, 0x4d, 0x30, 0x34, 0x3b, 0x4d, 0x30, 0x35,
-0x3b, 0x4d, 0x30, 0x36, 0x3b, 0x4d, 0x30, 0x37, 0x3b, 0x4d, 0x30, 0x38, 0x3b, 0x4d, 0x30, 0x39, 0x3b, 0x4d, 0x31, 0x30,
-0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x46, 0x65, 0x62,
-0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d,
-0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x65, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73,
-0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65,
-0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a,
-0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x72, 0x74, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d,
-0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65,
-0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x73, 0x2e, 0x6a, 0x61, 0x6e,
-0x61, 0x72, 0x3b, 0x73, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x6c,
-0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b,
-0x67, 0x75, 0x73, 0x68, 0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b,
-0x6e, 0xeb, 0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x73, 0x68,
-0x6b, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x3b, 0x6b, 0x6f,
-0x72, 0x72, 0x3b, 0x67, 0x75, 0x73, 0x68, 0x3b, 0x73, 0x68, 0x74, 0x3b, 0x74, 0x65, 0x74, 0x3b, 0x6e, 0xeb, 0x6e, 0x3b,
-0x64, 0x68, 0x6a, 0x6a, 0x3b, 0x73, 0x68, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x6d, 0x3b, 0x71, 0x3b, 0x6b, 0x3b, 0x67, 0x3b,
-0x73, 0x68, 0x3b, 0x74, 0x3b, 0x6e, 0x3b, 0x64, 0x68, 0x1303, 0x1295, 0x12e9, 0x12c8, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12c8, 0x122a,
-0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x120d, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b,
-0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x1260, 0x122d, 0x3b, 0x1296, 0x126c,
-0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b, 0x122d, 0x127d,
-0x3b, 0x12a4, 0x1355, 0x122a, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x3b, 0x1234,
-0x1355, 0x1274, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b,
-0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b, 0x12f2, 0x64a, 0x646, 0x627,
-0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644,
-0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a,
-0x633, 0x637, 0x633, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
-0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x648,
-0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x62c, 0x627, 0x646, 0x641, 0x64a, 0x3b,
-0x641, 0x64a, 0x641, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x641, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a,
-0x3b, 0x62c, 0x648, 0x627, 0x646, 0x3b, 0x62c, 0x648, 0x64a, 0x644, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x62a, 0x3b, 0x633, 0x628, 0x62a,
-0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a,
-0x633, 0x645, 0x628, 0x631, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x623, 0x3b,
-0x633, 0x3b, 0x623, 0x3b, 0x646, 0x3b, 0x62f, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b,
-0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631,
-0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648,
-0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20,
-0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x643, 0x627,
-0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631,
-0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a,
-0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0xa0, 0x627,
-0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627,
-0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x643, 0x3b, 0x634, 0x3b, 0x622, 0x3b, 0x646, 0x3b, 0x623, 0x3b, 0x62d,
-0x3b, 0x62a, 0x3b, 0x622, 0x3b, 0x623, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b, 0x643, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628,
-0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x625, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648,
-0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a,
-0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x62c,
-0x645, 0x628, 0x631, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x625, 0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634,
-0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645,
-0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b,
-0x64a, 0x648, 0x644, 0x64a, 0x648, 0x632, 0x3b, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a, 0x646, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a,
-0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x646, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x646, 0x628, 0x631, 0x64a, 0x3b, 0x641, 0x3b, 0x645,
-0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x570, 0x578,
-0x582, 0x576, 0x57e, 0x561, 0x580, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x3b, 0x561,
-0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x570, 0x578,
-0x582, 0x56c, 0x56b, 0x57d, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562,
-0x565, 0x580, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565,
-0x580, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x56b, 0x3b,
-0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x56b, 0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c,
-0x56b, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582,
-0x56c, 0x56b, 0x57d, 0x56b, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x56b, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574,
-0x562, 0x565, 0x580, 0x56b, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x576, 0x578, 0x575, 0x565,
-0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x570, 0x576, 0x57e, 0x3b,
-0x583, 0x57f, 0x57e, 0x3b, 0x574, 0x580, 0x57f, 0x3b, 0x561, 0x57a, 0x580, 0x3b, 0x574, 0x575, 0x57d, 0x3b, 0x570, 0x576, 0x57d, 0x3b,
-0x570, 0x56c, 0x57d, 0x3b, 0x585, 0x563, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x3b, 0x570, 0x578, 0x56f, 0x3b, 0x576, 0x578, 0x575, 0x3b,
-0x564, 0x565, 0x56f, 0x540, 0x3b, 0x553, 0x3b, 0x544, 0x3b, 0x531, 0x3b, 0x544, 0x3b, 0x540, 0x3b, 0x540, 0x3b, 0x555, 0x3b, 0x54d,
-0x3b, 0x540, 0x3b, 0x546, 0x3b, 0x534, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0,
-0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae,
-0x9c7, 0x2019, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b, 0x99b,
-0x9c7, 0x9aa, 0x9cd, 0x9a4, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8, 0x9f1,
-0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab,
-0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae,
-0x9c7, 0x2019, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x3b, 0x99b, 0x9c7, 0x9aa, 0x9cd,
-0x9a4, 0x9c7, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x99c, 0x3b, 0x9ab,
-0x3b, 0x9ae, 0x3b, 0x98f, 0x3b, 0x9ae, 0x3b, 0x99c, 0x3b, 0x99c, 0x3b, 0x986, 0x3b, 0x99b, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1,
-0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x41,
-0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x130, 0x79, 0x75, 0x6e, 0x3b, 0x130, 0x79, 0x75, 0x6c, 0x3b, 0x41,
-0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x79, 0x61,
-0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x79, 0x61, 0x6e, 0x76,
-0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c,
-0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x71, 0x75, 0x73,
-0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6e,
-0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b,
-0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b,
-0x61, 0x76, 0x71, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x408,
-0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f,
-0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x458, 0x443, 0x43d, 0x3b, 0x418, 0x458, 0x443, 0x43b, 0x3b, 0x410, 0x432,
-0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, 0x458, 0x430, 0x431,
-0x440, 0x3b, 0x41d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x458, 0x430, 0x43d, 0x432, 0x430,
-0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x3b,
-0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x443, 0x43d, 0x3b, 0x438, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442,
-0x3b, 0x441, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43d, 0x43e,
-0x458, 0x430, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c,
-0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x43d, 0x3b, 0x438, 0x458, 0x43b, 0x3b, 0x430,
-0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x458, 0x3b, 0x434, 0x435, 0x43a, 0x75, 0x72,
-0x74, 0x61, 0x72, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x74,
-0x78, 0x6f, 0x61, 0x3b, 0x61, 0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b,
-0x65, 0x6b, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x75, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x61, 0x62, 0x75, 0x7a, 0x74,
-0x75, 0x61, 0x3b, 0x69, 0x72, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x61, 0x7a, 0x61, 0x72,
-0x6f, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x6e, 0x64, 0x75, 0x61, 0x75, 0x72, 0x74, 0x2e, 0x3b, 0x6f, 0x74, 0x73, 0x2e, 0x3b,
-0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x69, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e, 0x3b, 0x65, 0x6b, 0x61, 0x2e, 0x3b,
-0x75, 0x7a, 0x74, 0x2e, 0x3b, 0x61, 0x62, 0x75, 0x2e, 0x3b, 0x69, 0x72, 0x61, 0x2e, 0x3b, 0x75, 0x72, 0x72, 0x2e, 0x3b,
-0x61, 0x7a, 0x61, 0x2e, 0x3b, 0x61, 0x62, 0x65, 0x2e, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45,
-0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0,
-0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b,
-0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b,
-0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd,
-0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac,
-0x9b0, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0,
-0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd,
-0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0,
-0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x99c, 0x9be, 0x3b,
-0x9ab, 0x9c7, 0x3b, 0x9ae, 0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b, 0x986, 0x3b,
-0x9b8, 0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54,
-0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
-0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54,
-0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1,
-0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42,
-0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0xf5f,
-0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
-0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf22, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf25, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf26, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf28, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf20,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf22, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b,
-0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0x31, 0x32, 0xf21, 0x3b,
-0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21,
-0xf21, 0x3b, 0xf21, 0xf22, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0x34, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b,
-0x39, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x43, 0x2bc, 0x68,
-0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b,
-0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x72, 0x65, 0x3b,
-0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44,
-0x75, 0x3b, 0x4b, 0x65, 0x72, 0x7a, 0x75, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d,
-0x65, 0x75, 0x72, 0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x2e, 0x3b,
-0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72,
-0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x7a, 0x75, 0x2e, 0x30, 0x31, 0x3b, 0x30, 0x32, 0x3b, 0x30, 0x33, 0x3b, 0x30, 0x34,
-0x3b, 0x30, 0x35, 0x3b, 0x30, 0x36, 0x3b, 0x30, 0x37, 0x3b, 0x30, 0x38, 0x3b, 0x30, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31,
-0x31, 0x3b, 0x31, 0x32, 0x44f, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b,
-0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e,
-0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b,
-0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a,
-0x435, 0x43c, 0x432, 0x440, 0x438, 0x44f, 0x43d, 0x443, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f,
-0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435,
-0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x435, 0x3b, 0x434, 0x435, 0x43a, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430,
-0x3b, 0x43c, 0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x1007, 0x1014, 0x103a, 0x1014,
-0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1016, 0x1031, 0x1016, 0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b,
-0x1027, 0x1015, 0x103c, 0x102e, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004, 0x103a,
-0x3b, 0x1029, 0x1002, 0x102f, 0x1010, 0x103a, 0x3b, 0x1005, 0x1000, 0x103a, 0x1010, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000,
-0x103a, 0x1010, 0x102d, 0x102f, 0x1018, 0x102c, 0x3b, 0x1014, 0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012, 0x102e, 0x1007, 0x1004,
-0x103a, 0x1018, 0x102c, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007,
-0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b, 0x1005, 0x1000, 0x103a, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x3b, 0x1014,
-0x102d, 0x102f, 0x3b, 0x1012, 0x102e, 0x1007, 0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b, 0x1029,
-0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442,
-0x44b, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43c,
-0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x436, 0x43d,
-0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440,
-0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x430,
-0x43d, 0x44c, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x430, 0x433, 0x430, 0x3b, 0x441, 0x430,
-0x43a, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43c, 0x430, 0x44f,
-0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44f, 0x3b, 0x436, 0x43d, 0x456, 0x45e,
-0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x43d, 0x44f, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456,
-0x43a, 0x430, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x43d, 0x44f, 0x441,
-0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447,
-0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b,
-0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440,
-0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435,
-0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a,
-0x3b, 0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x1798, 0x1780, 0x179a, 0x17b6,
-0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b8, 0x1793, 0x17b6, 0x3b, 0x1798, 0x17c1, 0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f,
-0x1797, 0x17b6, 0x3b, 0x1798, 0x17b7, 0x1790, 0x17bb, 0x1793, 0x17b6, 0x3b, 0x1780, 0x1780, 0x17d2, 0x1780, 0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8, 0x17a0,
-0x17b6, 0x3b, 0x1780, 0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, 0x17bb, 0x179b, 0x17b6, 0x3b, 0x179c, 0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780,
-0x17b6, 0x3b, 0x1792, 0x17d2, 0x1793, 0x17bc, 0x1798, 0x3b, 0x1780, 0x3b, 0x1798, 0x3b, 0x1798, 0x3b, 0x17a7, 0x3b, 0x1798, 0x3b, 0x1780, 0x3b,
-0x179f, 0x3b, 0x1780, 0x3b, 0x178f, 0x3b, 0x179c, 0x3b, 0x1792, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65,
-0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75,
-0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64,
-0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61,
-0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79,
-0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x64,
-0x65, 0x20, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65,
-0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b,
-0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b,
-0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64,
-0x65, 0x73, 0x2e, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b,
-0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61,
-0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x64,
-0x2019, 0x61, 0x67, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x2e, 0x3b,
-0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73, 0x2e, 0x47, 0x4e, 0x3b, 0x46, 0x42,
-0x3b, 0x4d, 0xc7, 0x3b, 0x41, 0x42, 0x3b, 0x4d, 0x47, 0x3b, 0x4a, 0x4e, 0x3b, 0x4a, 0x4c, 0x3b, 0x41, 0x47, 0x3b, 0x53,
-0x54, 0x3b, 0x4f, 0x43, 0x3b, 0x4e, 0x56, 0x3b, 0x44, 0x53, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b, 0x4e09, 0x6708, 0x3b, 0x56db,
-0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b, 0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b,
-0x5341, 0x4e00, 0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35,
-0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31,
-0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x73, 0x69, 0x6a, 0x65, 0x10d, 0x61, 0x6e, 0x6a, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d,
-0x61, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x61, 0x6b, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x76, 0x69,
-0x62, 0x61, 0x6e, 0x6a, 0x3b, 0x6c, 0x69, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x72, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x6b,
-0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x3b, 0x72, 0x75, 0x6a, 0x61, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61,
-0x64, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x69, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x61, 0x63, 0x73, 0x69,
-0x6a, 0x65, 0x10d, 0x6e, 0x6a, 0x61, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d, 0x65, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x6b,
-0x61, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x6e, 0x6a, 0x61, 0x3b, 0x6c, 0x69,
-0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x61,
-0x3b, 0x72, 0x75, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x73, 0x74, 0x75,
-0x64, 0x65, 0x6e, 0x6f, 0x67, 0x61, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x61, 0x73, 0x69, 0x6a, 0x3b, 0x76,
-0x65, 0x6c, 0x6a, 0x3b, 0x6f, 0x17e, 0x75, 0x3b, 0x74, 0x72, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x3b, 0x6c, 0x69, 0x70, 0x3b,
-0x73, 0x72, 0x70, 0x3b, 0x6b, 0x6f, 0x6c, 0x3b, 0x72, 0x75, 0x6a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x73, 0x74, 0x75, 0x3b,
-0x70, 0x72, 0x6f, 0x31, 0x2e, 0x3b, 0x32, 0x2e, 0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e,
-0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30, 0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32,
-0x2e, 0x6c, 0x65, 0x64, 0x65, 0x6e, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x3b, 0x62, 0x159, 0x65, 0x7a, 0x65, 0x6e, 0x3b, 0x64,
-0x75, 0x62, 0x65, 0x6e, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x65, 0x6e, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x3b, 0x10d,
-0x65, 0x72, 0x76, 0x65, 0x6e, 0x65, 0x63, 0x3b, 0x73, 0x72, 0x70, 0x65, 0x6e, 0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b, 0x159,
-0xed, 0x6a, 0x65, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e,
-0x65, 0x63, 0x6c, 0x65, 0x64, 0x6e, 0x61, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x61, 0x3b, 0x62, 0x159, 0x65, 0x7a, 0x6e, 0x61,
-0x3b, 0x64, 0x75, 0x62, 0x6e, 0x61, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x6e, 0x61,
-0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x61, 0x3b, 0x7a, 0xe1, 0x159, 0xed,
-0x3b, 0x159, 0xed, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x75, 0x3b, 0x70, 0x72, 0x6f,
-0x73, 0x69, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x3b, 0xfa, 0x6e, 0x6f, 0x3b, 0x62, 0x159, 0x65, 0x3b, 0x64, 0x75, 0x62,
-0x3b, 0x6b, 0x76, 0x11b, 0x3b, 0x10d, 0x76, 0x6e, 0x3b, 0x10d, 0x76, 0x63, 0x3b, 0x73, 0x72, 0x70, 0x3b, 0x7a, 0xe1, 0x159,
-0x3b, 0x159, 0xed, 0x6a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x70, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66,
-0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d,
-0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f,
-0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
-0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a,
-0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
-0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69,
-0x6c, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75,
-0x73, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62,
-0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72,
-0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x72, 0x74, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b,
-0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73,
-0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x4a, 0x61,
-0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61,
-0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70,
-0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x6a, 0x61, 0x6e, 0x75,
-0x61, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x6f, 0x3b, 0x61,
-0x70, 0x72, 0x69, 0x6c, 0x6f, 0x3b, 0x6d, 0x61, 0x6a, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c,
-0x69, 0x6f, 0x3b, 0x61, 0x16d, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f,
-0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65,
-0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70,
-0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x16d, 0x67, 0x3b, 0x73, 0x65,
-0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x61, 0x6e, 0x75, 0x61, 0x72,
-0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69,
-0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61,
-0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
-0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x6a, 0x61, 0x61, 0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b,
-0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b,
-0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x74,
-0x73, 0x4a, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
-0x3b, 0x4e, 0x3b, 0x44, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d,
-0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a,
-0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65,
-0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70,
-0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65,
-0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
-0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e,
-0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74,
-0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b,
-0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x68,
-0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x3b, 0x6b, 0x65, 0x73,
-0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75,
-0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x72,
-0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x6d, 0x6d, 0x69,
-0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x61,
-0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b,
-0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61,
-0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61,
-0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x74, 0x61,
-0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75,
-0x75, 0x74, 0x61, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69,
-0x73, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x3b, 0x68,
-0x65, 0x69, 0x6e, 0xe4, 0x3b, 0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x3b, 0x6d,
-0x61, 0x72, 0x72, 0x61, 0x73, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68,
-0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x2e, 0x3b, 0x68, 0x75, 0x68, 0x74,
-0x69, 0x6b, 0x2e, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x2e, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x2e, 0x3b, 0x68,
-0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x2e, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x2e, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x2e, 0x3b,
-0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6c,
-0x75, 0x6b, 0x2e, 0x54, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53,
-0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x6a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x69, 0x65,
-0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69,
-0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x3b, 0x64, 0xe9, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72,
-0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e,
-0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
-0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9,
-0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75,
-0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e,
-0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
-0x66, 0xe9, 0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a,
-0x75, 0x69, 0x2e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e,
-0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x4a, 0x61, 0x6e, 0x6e, 0x65,
-0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x61,
-0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x61, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x3b,
-0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x69, 0x6d,
-0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x44, 0x65, 0x73, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x72, 0x74,
-0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67,
-0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x41, 0x6d, 0x20, 0x46,
-0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e,
-0x3b, 0x41, 0x6d, 0x20, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b,
-0x41, 0x6e, 0x20, 0x43, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0xd2, 0x67, 0x6d, 0x68,
-0x69, 0x6f, 0x73, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x4c,
-0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e,
-0x3b, 0x41, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d,
-0x68, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x64, 0x68, 0x65,
-0x6e, 0x20, 0x46, 0x68, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47,
-0x68, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x4d, 0x68, 0xe0, 0x72, 0x74, 0x3b, 0x64,
-0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x43, 0x68,
-0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0xd2, 0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b,
-0x64, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0xf9, 0x6e,
-0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e,
-0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74,
-0x2d, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61,
-0x63, 0x68, 0x64, 0x46, 0x61, 0x6f, 0x69, 0x3b, 0x47, 0x65, 0x61, 0x72, 0x72, 0x3b, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x47,
-0x69, 0x62, 0x6c, 0x3b, 0x43, 0xe8, 0x69, 0x74, 0x3b, 0xd2, 0x67, 0x6d, 0x68, 0x3b, 0x49, 0x75, 0x63, 0x68, 0x3b, 0x4c,
-0xf9, 0x6e, 0x61, 0x3b, 0x53, 0x75, 0x6c, 0x74, 0x3b, 0x44, 0xe0, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x44,
-0xf9, 0x62, 0x68, 0x46, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x43, 0x3b, 0xd2, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x53,
-0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x44, 0x58, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x69,
-0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b,
-0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65,
-0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x78, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
-0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x61, 0x67, 0x6f,
-0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x58, 0x61,
-0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61,
-0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65,
-0x74, 0x2e, 0x3b, 0x4f, 0x75, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x78, 0x61, 0x6e,
-0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69,
-0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74,
-0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x58, 0x3b, 0x46, 0x3b,
-0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x78,
-0x2e, 0x3b, 0x66, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x78, 0x2e, 0x3b,
-0x61, 0x2e, 0x3b, 0x73, 0x2e, 0x3b, 0x6f, 0x2e, 0x3b, 0x6e, 0x2e, 0x3b, 0x64, 0x2e, 0x10d8, 0x10d0, 0x10dc, 0x10d5, 0x10d0, 0x10e0,
-0x10d8, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x10d4, 0x10e0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2, 0x10d8, 0x3b, 0x10d0, 0x10de,
-0x10e0, 0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5,
-0x10da, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x10d8, 0x10e1, 0x10e2, 0x10dd, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x10e2, 0x10d4, 0x10db, 0x10d1,
-0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x10dd, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x10db, 0x10d1, 0x10d4,
-0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x10d8, 0x10d0, 0x10dc, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x3b,
-0x10db, 0x10d0, 0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x3b,
-0x10d0, 0x10d2, 0x10d5, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d8,
-0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b, 0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc,
-0x3b, 0x10d3, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72,
-0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
-0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f,
-0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
-0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b,
-0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e,
-0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b,
-0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e,
-0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x4a, 0xe4, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x46, 0x65, 0x62,
-0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0xe4, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
-0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
-0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a,
-0xe4, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d,
-0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65,
-0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x399, 0x3b1, 0x3bd,
-0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b,
-0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3b9,
-0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391,
-0x3cd, 0x3b3, 0x3bf, 0x3c5, 0x3c3, 0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
-0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
-0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf,
-0x3c5, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3c4, 0x3af, 0x3bf,
-0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b9, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5,
-0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3bf, 0x3cd, 0x3c3, 0x3c4,
-0x3bf, 0x3c5, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3c9, 0x3b2,
-0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b5, 0x3bc,
-0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1,
-0x3b, 0x39c, 0x3ac, 0x3b9, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3b, 0x3a3,
-0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3b, 0x394, 0x3b5, 0x3ba, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5,
-0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1, 0x390, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3b, 0x399,
-0x3bf, 0x3c5, 0x3bb, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3b,
-0x394, 0x3b5, 0x3ba, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3,
-0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75,
-0x61, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x69, 0x6c, 0x69, 0x3b, 0x6d,
-0x61, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x67, 0x67,
-0x75, 0x73, 0x74, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
-0x62, 0x61, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
-0x62, 0x61, 0x72, 0x69, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x61, 0x72, 0x69, 0x70, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
-0x61, 0x72, 0x69, 0x70, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x69, 0x70, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x69, 0x6c, 0x69, 0x70,
-0x3b, 0x6d, 0x61, 0x61, 0x6a, 0x69, 0x70, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x70, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69,
-0x70, 0x3b, 0x61, 0x67, 0x67, 0x75, 0x73, 0x74, 0x69, 0x70, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72,
-0x69, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x69, 0x70, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61,
-0x72, 0x69, 0x70, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x70, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65,
-0x62, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a,
-0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b,
-0x64, 0x65, 0x63, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0xa86,
-0xab0, 0xac0, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c,
-0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7,
-0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0,
-0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd,
-0xab0, 0xac1, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c,
-0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7,
-0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5, 0xac7, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0xa9c, 0xabe, 0x3b, 0xaab, 0xac7,
-0x3b, 0xaae, 0xabe, 0x3b, 0xa8f, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0x3b, 0xa9c, 0xac1, 0x3b, 0xa91, 0x3b, 0xab8, 0x3b, 0xa91,
-0x3b, 0xaa8, 0x3b, 0xaa1, 0xabf, 0x4a, 0x61, 0x6e, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x46, 0x61, 0x62, 0x75, 0x72, 0x61, 0x69,
-0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x41, 0x66, 0x69, 0x72, 0x69, 0x6c, 0x75, 0x3b, 0x4d, 0x61, 0x79,
-0x75, 0x3b, 0x59, 0x75, 0x6e, 0x69, 0x3b, 0x59, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x53,
-0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x75, 0x77, 0x61, 0x6d, 0x62,
-0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, 0x61, 0x72,
-0x3b, 0x41, 0x66, 0x69, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75,
-0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b,
-0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x5d9,
-0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5d9,
-0x5dc, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5d5,
-0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0, 0x5d5,
-0x5d1, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5d1, 0x5e8, 0x5d9, 0x5e0, 0x5d5, 0x5f3, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b,
-0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5,
-0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5f3, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5f3, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5f3, 0x3b, 0x5e0, 0x5d5,
-0x5d1, 0x5f3, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5f3, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940, 0x3b,
-0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b,
-0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x902, 0x92c, 0x930, 0x3b, 0x905,
-0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x91c,
-0x928, 0x970, 0x3b, 0x92b, 0x93c, 0x930, 0x970, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932,
-0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x970, 0x3b, 0x905, 0x917, 0x970, 0x3b, 0x938, 0x93f, 0x924,
-0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x970, 0x3b, 0x928, 0x935, 0x970, 0x3b, 0x926, 0x93f, 0x938, 0x970, 0x91c, 0x3b, 0x92b,
-0x93c, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x3b, 0x938, 0x93f, 0x3b,
-0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72,
-0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x69, 0x75, 0x73, 0x3b, 0xe1, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a,
-0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6c, 0x69, 0x75, 0x73, 0x3b, 0x61, 0x75, 0x67,
-0x75, 0x73, 0x7a, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b,
-0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x2e, 0x3b,
-0xe1, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x6a, 0x2e, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b,
-0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76,
-0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b,
-0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x6a, 0x61, 0x6e, 0xfa, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62,
-0x72, 0xfa, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0xed, 0x3b,
-0x6a, 0xfa, 0x6e, 0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b, 0xe1, 0x67, 0xfa, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0xf3, 0x76, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e,
-0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b,
-0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0xe1, 0x67, 0xfa, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b,
-0x6e, 0xf3, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
-0x3b, 0x4a, 0x3b, 0xc1, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b,
-0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c,
-0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74,
-0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
-0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61,
-0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75,
-0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
-0x76, 0x3b, 0x44, 0x65, 0x73, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
-0x72, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x6f, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69,
-0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74,
-0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b,
-0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x6a, 0x61, 0x6e,
-0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e,
-0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76,
-0x3b, 0x64, 0x65, 0x63, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b,
-0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x45, 0x61, 0x6e, 0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x72,
-0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61, 0x6c,
-0x74, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x65, 0x61, 0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c,
-0x3b, 0x4c, 0xfa, 0x6e, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x65, 0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72,
-0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61, 0x64, 0x68, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53, 0x61,
-0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x61, 0x69, 0x67, 0x45, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x61,
-0x62, 0x68, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x3b, 0x4d, 0x65,
-0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x44,
-0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
-0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x67, 0x65, 0x6e,
-0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b,
-0x61, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x6f,
-0x3b, 0x6c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x67, 0x65, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61,
-0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x6c, 0x75, 0x67, 0x3b, 0x61, 0x67,
-0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x47, 0x3b, 0x46,
-0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
-0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
-0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0xc9c, 0xca8, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0,
-0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc7, 0x3b,
-0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa,
-0xccd, 0xc9f, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6,
-0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0xc9c, 0xca8, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd,
-0xcb0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2,
-0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85,
-0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xc9c, 0xca8, 0xcb5, 0xcb0, 0xcbf,
-0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd,
-0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8,
-0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf,
-0xcb8, 0xcc6, 0xc82, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8f, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b, 0xc9c,
-0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8, 0x3b, 0xca1, 0xcbf, 0x62c, 0x646, 0x624, 0x631, 0x6cc, 0x3b, 0x641,
-0x631, 0x624, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x654,
-0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c, 0x648, 0x657, 0x644, 0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633,
-0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f,
-0x633, 0x645, 0x628, 0x631, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b,
-0x633, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x49a, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x410, 0x49b, 0x43f, 0x430, 0x43d, 0x3b,
-0x41d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x421, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x41c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x41c,
-0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x428, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x422, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49a, 0x44b,
-0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49a, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b,
-0x416, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x49b, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430,
-0x43d, 0x3b, 0x43d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x441, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x43c, 0x430, 0x43c, 0x44b, 0x440,
-0x3b, 0x43c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x448, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b,
-0x49b, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49b, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448,
-0x430, 0x3b, 0x436, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x49b, 0x430, 0x4a3, 0x2e, 0x3b, 0x430, 0x49b, 0x43f, 0x2e,
-0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9, 0x443, 0x2e, 0x3b, 0x43c, 0x430, 0x43c, 0x2e, 0x3b, 0x43c, 0x430, 0x443, 0x2e,
-0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, 0x2e, 0x3b, 0x49b, 0x44b, 0x440, 0x2e, 0x3b, 0x49b, 0x430, 0x437, 0x2e,
-0x3b, 0x49b, 0x430, 0x440, 0x2e, 0x3b, 0x436, 0x435, 0x43b, 0x2e, 0x49a, 0x3b, 0x410, 0x3b, 0x41d, 0x3b, 0x421, 0x3b, 0x41c, 0x3b,
-0x41c, 0x3b, 0x428, 0x3b, 0x422, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x416, 0x4d, 0x75, 0x74, 0x61, 0x72, 0x61, 0x6d,
-0x61, 0x3b, 0x47, 0x61, 0x73, 0x68, 0x79, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x3b, 0x57, 0x65, 0x72, 0x75, 0x72, 0x77,
-0x65, 0x3b, 0x4d, 0x61, 0x74, 0x61, 0x3b, 0x47, 0x69, 0x63, 0x75, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x3b, 0x4b, 0x61, 0x6d,
-0x65, 0x6e, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x3b,
-0x4e, 0x7a, 0x65, 0x6c, 0x69, 0x3b, 0x55, 0x6b, 0x77, 0x61, 0x6b, 0x69, 0x72, 0x61, 0x3b, 0x55, 0x67, 0x75, 0x73, 0x68,
-0x79, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x55, 0x6b, 0x75, 0x62, 0x6f, 0x7a, 0x61, 0x6d, 0x75, 0x74, 0x2e, 0x3b, 0x67, 0x61,
-0x73, 0x2e, 0x3b, 0x77, 0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x2e, 0x3b, 0x67, 0x69, 0x63, 0x2e, 0x3b, 0x6b, 0x61,
-0x6d, 0x2e, 0x3b, 0x6e, 0x79, 0x61, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x6e, 0x7a, 0x65, 0x2e, 0x3b, 0x75, 0x6b,
-0x77, 0x2e, 0x3b, 0x75, 0x67, 0x75, 0x2e, 0x3b, 0x75, 0x6b, 0x75, 0x2e, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424,
-0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c,
-0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b,
-0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f,
-0x431, 0x440, 0x44c, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x444, 0x435,
-0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x43c, 0x430,
-0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441,
-0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d, 0x43e, 0x44f, 0x431,
-0x440, 0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x42f, 0x43d, 0x432, 0x3b, 0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430,
-0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432,
-0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a, 0x442, 0x3b, 0x41d, 0x43e, 0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x44f, 0x43d, 0x432,
-0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439,
-0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e,
-0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x42f, 0x3b, 0x424, 0x3b, 0x41c,
-0x3b, 0x410, 0x3b, 0x41c, 0x3b, 0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b, 0x414, 0x31, 0xc6d4,
-0x3b, 0x32, 0xc6d4, 0x3b, 0x33, 0xc6d4, 0x3b, 0x34, 0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37, 0xc6d4, 0x3b, 0x38,
-0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b, 0x31, 0x30, 0xc6d4, 0x3b, 0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x72, 0xea, 0x62, 0x65,
-0x6e, 0x64, 0x61, 0x6e, 0x3b, 0x72, 0x65, 0x15f, 0x65, 0x6d, 0xee, 0x3b, 0x61, 0x64, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72,
-0xea, 0x6c, 0x3b, 0x67, 0x75, 0x6c, 0x61, 0x6e, 0x3b, 0x70, 0xfb, 0x15f, 0x70, 0x65, 0x72, 0x3b, 0x74, 0xee, 0x72, 0x6d,
-0x65, 0x68, 0x3b, 0x67, 0x65, 0x6c, 0x61, 0x77, 0xea, 0x6a, 0x3b, 0x72, 0x65, 0x7a, 0x62, 0x65, 0x72, 0x3b, 0x6b, 0x65,
-0x77, 0xe7, 0xea, 0x72, 0x3b, 0x73, 0x65, 0x72, 0x6d, 0x61, 0x77, 0x65, 0x7a, 0x3b, 0x62, 0x65, 0x72, 0x66, 0x61, 0x6e,
-0x62, 0x61, 0x72, 0x72, 0xea, 0x62, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0xea, 0x3b, 0x72, 0x65, 0x15f, 0x65, 0x6d, 0x69, 0x79,
-0xea, 0x3b, 0x61, 0x64, 0x61, 0x72, 0xea, 0x3b, 0x61, 0x76, 0x72, 0xea, 0x6c, 0xea, 0x3b, 0x67, 0x75, 0x6c, 0x61, 0x6e,
-0xea, 0x3b, 0x70, 0xfb, 0x15f, 0x70, 0x65, 0x72, 0xea, 0x3b, 0x74, 0xee, 0x72, 0x6d, 0x65, 0x68, 0xea, 0x3b, 0x67, 0x65,
-0x6c, 0x61, 0x77, 0xea, 0x6a, 0xea, 0x3b, 0x72, 0x65, 0x7a, 0x62, 0x65, 0x72, 0xea, 0x3b, 0x6b, 0x65, 0x77, 0xe7, 0xea,
-0x72, 0xea, 0x3b, 0x73, 0x65, 0x72, 0x6d, 0x61, 0x77, 0x65, 0x7a, 0xea, 0x3b, 0x62, 0x65, 0x72, 0x66, 0x61, 0x6e, 0x62,
-0x61, 0x72, 0xea, 0x72, 0xea, 0x62, 0x3b, 0x72, 0x65, 0x15f, 0x3b, 0x61, 0x64, 0x61, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x67,
-0x75, 0x6c, 0x3b, 0x70, 0xfb, 0x15f, 0x3b, 0x74, 0xee, 0x72, 0x3b, 0x67, 0x65, 0x6c, 0x3b, 0x72, 0x65, 0x7a, 0x3b, 0x6b,
-0x65, 0x77, 0x3b, 0x73, 0x65, 0x72, 0x3b, 0x62, 0x65, 0x72, 0x52, 0x3b, 0x52, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x47, 0x3b,
-0x50, 0x3b, 0x54, 0x3b, 0x47, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x42, 0x4e, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x52,
-0x75, 0x68, 0x75, 0x68, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x74, 0x77, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x3b, 0x4e, 0x64,
-0x61, 0x6d, 0x75, 0x6b, 0x69, 0x7a, 0x61, 0x3b, 0x52, 0x75, 0x73, 0x61, 0x6d, 0x61, 0x3b, 0x52, 0x75, 0x68, 0x65, 0x73,
-0x68, 0x69, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x6b, 0x61, 0x72, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x61,
-0x72, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x47, 0x69, 0x74, 0x75, 0x67, 0x75, 0x74, 0x75,
-0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x6f, 0x6e, 0x79, 0x6f, 0x3b, 0x4b, 0x69, 0x67, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x4d, 0x75,
-0x74, 0x2e, 0x3b, 0x47, 0x61, 0x73, 0x2e, 0x3b, 0x57, 0x65, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x74, 0x2e, 0x3b, 0x47, 0x69,
-0x63, 0x2e, 0x3b, 0x4b, 0x61, 0x6d, 0x2e, 0x3b, 0x4e, 0x79, 0x61, 0x2e, 0x3b, 0x4b, 0x61, 0x6e, 0x2e, 0x3b, 0x4e, 0x7a,
-0x65, 0x2e, 0x3b, 0x55, 0x6b, 0x77, 0x2e, 0x3b, 0x55, 0x67, 0x75, 0x2e, 0x3b, 0x55, 0x6b, 0x75, 0x2e, 0xea1, 0xeb1, 0xe87,
-0xe81, 0xead, 0xe99, 0x3b, 0xe81, 0xeb8, 0xea1, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa, 0xeb2, 0x3b,
-0xe9e, 0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb4, 0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5, 0xeb0, 0xe81,
-0xebb, 0xe94, 0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, 0x3b, 0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2, 0x3b, 0xe95, 0xeb8, 0xea5, 0xeb2, 0x3b,
-0xe9e, 0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b, 0xe97, 0xeb1, 0xe99, 0xea7, 0xeb2, 0xea1, 0x2e, 0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e,
-0x3b, 0xea1, 0x2e, 0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb4, 0x2e, 0xe96,
-0x2e, 0x3b, 0xe81, 0x2e, 0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81, 0x2e, 0xe8d, 0x2e, 0x3b, 0xe95, 0x2e, 0xea5,
-0x2e, 0x3b, 0xe9e, 0x2e, 0xe88, 0x2e, 0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x6a, 0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x12b,
-0x6c, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6c,
-0x69, 0x6a, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72,
-0x69, 0x73, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x69,
-0x73, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0x65, 0x62,
-0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b,
-0x6a, 0x16b, 0x6e, 0x2e, 0x3b, 0x6a, 0x16b, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e,
-0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x73, 0xe1, 0x6e, 0x7a, 0xe1,
-0x20, 0x79, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d,
-0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74,
-0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73, 0xe1, 0x6e,
-0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79,
-0x61, 0x20, 0x6d, 0x6f, 0x74, 0xf3, 0x62, 0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6e, 0x73,
-0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d, 0x62, 0x65,
-0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1, 0x6e, 0x7a,
-0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a,
-0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20,
-0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x79, 0x61, 0x6e,
-0x3b, 0x66, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x79, 0x75, 0x6e,
-0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x74, 0x3b, 0x73, 0x74, 0x62, 0x3b, 0x254, 0x74, 0x62, 0x3b, 0x6e, 0x76, 0x62,
-0x3b, 0x64, 0x73, 0x62, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x61, 0x3b,
-0x73, 0x3b, 0x254, 0x3b, 0x6e, 0x3b, 0x64, 0x73, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69,
-0x73, 0x3b, 0x6b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x3b, 0x67, 0x65, 0x67,
-0x75, 0x17e, 0x117, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x61, 0x3b, 0x72,
-0x75, 0x67, 0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x69, 0x73, 0x3b, 0x73, 0x70,
-0x61, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64,
-0x69, 0x73, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x6b, 0x6f, 0x76,
-0x6f, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e, 0x117, 0x73, 0x3b,
-0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x70,
-0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x6f, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x69, 0x6f,
-0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x10d, 0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x17e, 0x69, 0x6f, 0x73,
-0x61, 0x75, 0x73, 0x2e, 0x3b, 0x76, 0x61, 0x73, 0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x2e, 0x3b, 0x62, 0x61, 0x6c, 0x2e, 0x3b,
-0x67, 0x65, 0x67, 0x2e, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x2e, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67,
-0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x2e, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x2e, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72,
-0x2e, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x2e, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b,
-0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444,
-0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c,
-0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b,
-0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d,
-0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x458, 0x430, 0x43d, 0x2e, 0x3b,
-0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
-0x443, 0x43d, 0x2e, 0x3b, 0x458, 0x443, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b,
-0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x458, 0x3b, 0x444, 0x3b, 0x43c,
-0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x458, 0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x4a, 0x61,
-0x6e, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x73,
-0x61, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x61, 0x3b, 0x4a, 0x6f,
-0x6c, 0x61, 0x79, 0x3b, 0x41, 0x6f, 0x67, 0x6f, 0x73, 0x69, 0x74, 0x72, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x61, 0x6d,
-0x62, 0x72, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x61, 0x6d, 0x62, 0x72, 0x61,
-0x3b, 0x44, 0x65, 0x73, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72,
-0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x41, 0x6f, 0x67,
-0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x4a, 0x61, 0x6e, 0x75,
-0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72,
-0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x6f,
-0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
-0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e,
-0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
-0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76,
-0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b,
-0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41,
-0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd7d, 0x3b, 0xd2e,
-0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0xd38, 0xd4d, 0xd31, 0xd4d, 0xd31,
-0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd12, 0xd15, 0xd4d, 0x200c, 0xd1f, 0xd4b, 0xd2c,
-0xd7c, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd7c, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46,
-0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b,
-0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02,
-0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0x3b, 0xd28, 0xd35, 0xd02, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b,
-0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0xd46, 0x3b,
-0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x4a, 0x61, 0x6e, 0x6e, 0x61, 0x72, 0x3b, 0x46, 0x72, 0x61, 0x72, 0x3b, 0x4d, 0x61,
-0x72, 0x7a, 0x75, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x6a, 0x6a, 0x75, 0x3b, 0x120, 0x75, 0x6e, 0x6a,
-0x75, 0x3b, 0x4c, 0x75, 0x6c, 0x6a, 0x75, 0x3b, 0x41, 0x77, 0x77, 0x69, 0x73, 0x73, 0x75, 0x3b, 0x53, 0x65, 0x74, 0x74,
-0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
-0x72, 0x75, 0x3b, 0x44, 0x69, 0x10b, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b, 0x4d,
-0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x6a, 0x3b, 0x120, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x6c, 0x3b, 0x41,
-0x77, 0x77, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x10b, 0x4a, 0x6e,
-0x3b, 0x46, 0x72, 0x3b, 0x4d, 0x7a, 0x3b, 0x41, 0x70, 0x3b, 0x4d, 0x6a, 0x3b, 0x120, 0x6e, 0x3b, 0x4c, 0x6a, 0x3b, 0x41,
-0x77, 0x3b, 0x53, 0x74, 0x3b, 0x4f, 0x62, 0x3b, 0x4e, 0x76, 0x3b, 0x44, 0x10b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
-0x3b, 0x4d, 0x3b, 0x120, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4b, 0x6f, 0x68, 0x69,
-0x74, 0x101, 0x74, 0x65, 0x61, 0x3b, 0x48, 0x75, 0x69, 0x74, 0x61, 0x6e, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x50, 0x6f, 0x75,
-0x74, 0x16b, 0x74, 0x65, 0x72, 0x61, 0x6e, 0x67, 0x69, 0x3b, 0x50, 0x61, 0x65, 0x6e, 0x67, 0x61, 0x77, 0x68, 0x101, 0x77,
-0x68, 0x101, 0x3b, 0x48, 0x61, 0x72, 0x61, 0x74, 0x75, 0x61, 0x3b, 0x50, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x48, 0x14d,
-0x6e, 0x67, 0x6f, 0x6e, 0x67, 0x6f, 0x69, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x74, 0x75, 0x72, 0x69, 0x6b, 0x14d, 0x6b, 0x101,
-0x3b, 0x4d, 0x61, 0x68, 0x75, 0x72, 0x75, 0x3b, 0x57, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x2d, 0x101, 0x2d, 0x6e,
-0x75, 0x6b, 0x75, 0x3b, 0x57, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x2d, 0x101, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x69,
-0x3b, 0x48, 0x61, 0x6b, 0x69, 0x68, 0x65, 0x61, 0x4b, 0x6f, 0x68, 0x69, 0x3b, 0x48, 0x75, 0x69, 0x3b, 0x50, 0x6f, 0x75,
-0x3b, 0x50, 0x61, 0x65, 0x3b, 0x48, 0x61, 0x72, 0x61, 0x3b, 0x50, 0x69, 0x70, 0x69, 0x3b, 0x48, 0x14d, 0x6e, 0x67, 0x6f,
-0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x61, 0x68, 0x75, 0x3b, 0x4e, 0x75, 0x6b, 0x75, 0x3b, 0x52, 0x61, 0x6e, 0x67,
-0x69, 0x3b, 0x48, 0x61, 0x6b, 0x69, 0x4b, 0x3b, 0x48, 0x3b, 0x50, 0x3b, 0x50, 0x3b, 0x48, 0x3b, 0x50, 0x3b, 0x48, 0x3b,
-0x48, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x48, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947,
-0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f,
-0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x911, 0x917, 0x938, 0x94d, 0x91f, 0x3b,
-0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935,
-0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x91c, 0x93e, 0x928, 0x947, 0x3b, 0x92b,
-0x947, 0x92c, 0x94d, 0x930, 0x941, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x3b, 0x92e, 0x947,
-0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x911, 0x917, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x3b,
-0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x91c,
-0x93e, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x911,
-0x3b, 0x938, 0x3b, 0x911, 0x3b, 0x928, 0x94b, 0x3b, 0x921, 0x93f, 0x41d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20,
-0x441, 0x430, 0x440, 0x3b, 0x425, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x413,
-0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x414, 0x4e9, 0x440, 0x4e9, 0x432,
-0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x422, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440,
-0x20, 0x441, 0x430, 0x440, 0x3b, 0x417, 0x443, 0x440, 0x433, 0x430, 0x430, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x414, 0x43e, 0x43b, 0x43e, 0x43e, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x41d, 0x430,
-0x439, 0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x415, 0x441, 0x434, 0x4af, 0x433, 0x44d, 0x44d,
-0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x410, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440,
-0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440,
-0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x43d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x445, 0x43e, 0x451, 0x440, 0x434,
-0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x433, 0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430,
-0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x434, 0x4e9, 0x440, 0x4e9, 0x432, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x442, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x437, 0x443, 0x440, 0x433,
-0x430, 0x430, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x434, 0x43e, 0x43b, 0x43e, 0x43e, 0x434, 0x443,
-0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x43d, 0x430, 0x439, 0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20,
-0x441, 0x430, 0x440, 0x3b, 0x435, 0x441, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x430,
-0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d, 0x44d,
-0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e,
-0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x31, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
-0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x33, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x34, 0x2d, 0x440, 0x20,
-0x441, 0x430, 0x440, 0x3b, 0x35, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x36, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
-0x37, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x38, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x39, 0x2d, 0x440, 0x20,
-0x441, 0x430, 0x440, 0x3b, 0x31, 0x30, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x31, 0x31, 0x2d, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x31, 0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x49, 0x3b, 0x49, 0x49, 0x3b, 0x49, 0x49, 0x49, 0x3b, 0x49,
-0x56, 0x3b, 0x56, 0x3b, 0x56, 0x49, 0x3b, 0x56, 0x49, 0x49, 0x3b, 0x56, 0x49, 0x49, 0x49, 0x3b, 0x49, 0x58, 0x3b, 0x58,
-0x3b, 0x58, 0x49, 0x3b, 0x58, 0x49, 0x49, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x905,
-0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c,
-0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f,
-0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x92e, 0x94d,
-0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x91c, 0x928, 0x3b, 0x92b, 0x947, 0x947, 0x92c, 0x3b, 0x92e,
-0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932,
-0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921,
-0x93f, 0x938, 0x947, 0x91c, 0x928, 0x3b, 0x92b, 0x947, 0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930,
-0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b, 0x905,
-0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74,
-0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e,
-0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0xb1c, 0xb3e, 0xb28, 0xb41,
-0xb06, 0xb30, 0xb40, 0x3b, 0xb2b, 0xb47, 0xb2c, 0xb43, 0xb06, 0xb30, 0xb40, 0x3b, 0xb2e, 0xb3e, 0xb30, 0xb4d, 0xb1a, 0xb4d, 0xb1a, 0x3b,
-0xb05, 0xb2a, 0xb4d, 0xb30, 0xb47, 0xb32, 0x3b, 0xb2e, 0xb07, 0x3b, 0xb1c, 0xb41, 0xb28, 0x3b, 0xb1c, 0xb41, 0xb32, 0xb3e, 0xb07, 0x3b,
-0xb05, 0xb17, 0xb37, 0xb4d, 0xb1f, 0x3b, 0xb38, 0xb47, 0xb2a, 0xb4d, 0xb1f, 0xb47, 0xb2e, 0xb4d, 0xb2c, 0xb30, 0x3b, 0xb05, 0xb15, 0xb4d,
-0xb1f, 0xb4b, 0xb2c, 0xb30, 0x3b, 0xb28, 0xb2d, 0xb47, 0xb2e, 0xb4d, 0xb2c, 0xb30, 0x3b, 0xb21, 0xb3f, 0xb38, 0xb47, 0xb2e, 0xb4d, 0xb2c,
-0xb30, 0xb1c, 0xb3e, 0x3b, 0xb2b, 0xb47, 0x3b, 0xb2e, 0xb3e, 0x3b, 0xb05, 0x3b, 0xb2e, 0xb07, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb1c, 0xb41,
-0x3b, 0xb05, 0x3b, 0xb38, 0xb47, 0x3b, 0xb05, 0x3b, 0xb28, 0x3b, 0xb21, 0xb3f, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x6d0,
-0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b,
-0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628,
-0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631,
-0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e,
-0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6ab, 0x633,
-0x62a, 0x3b, 0x633, 0x6d0, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645,
-0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a,
-0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c,
-0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a,
-0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x3b, 0x641, 0x3b, 0x645,
-0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x698, 0x627,
-0x646, 0x648, 0x6cc, 0x647, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc,
-0x644, 0x3b, 0x645, 0x647, 0x3b, 0x698, 0x648, 0x626, 0x646, 0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x3b, 0x627, 0x648, 0x62a, 0x3b,
-0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631,
-0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x654, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647,
-0x654, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x654, 0x3b, 0x698, 0x648, 0x626,
-0x646, 0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x654, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628, 0x631,
-0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631,
-0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x3b, 0x698, 0x3b, 0x698, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b,
-0x646, 0x3b, 0x62f, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686,
-0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b,
-0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646,
-0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc,
-0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c,
-0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628,
-0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x65, 0x144, 0x3b, 0x6c,
-0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x65, 0x63, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x65, 0x144, 0x3b,
-0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77, 0x69, 0x65, 0x63, 0x3b, 0x6c, 0x69, 0x70, 0x69, 0x65, 0x63, 0x3b,
-0x73, 0x69, 0x65, 0x72, 0x70, 0x69, 0x65, 0x144, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x73, 0x69, 0x65, 0x144, 0x3b, 0x70, 0x61,
-0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67,
-0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65,
-0x67, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x3b, 0x6d, 0x61,
-0x6a, 0x61, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77, 0x63, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x65,
-0x72, 0x70, 0x6e, 0x69, 0x61, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x15b, 0x6e, 0x69, 0x61, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a,
-0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x67, 0x72,
-0x75, 0x64, 0x6e, 0x69, 0x61, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69,
-0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x3b, 0x6c, 0x69, 0x70, 0x3b, 0x73, 0x69, 0x65, 0x3b, 0x77, 0x72, 0x7a,
-0x3b, 0x70, 0x61, 0x17a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b,
-0x4d, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x47, 0x73, 0x3b, 0x6c, 0x3b, 0x6d,
-0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b, 0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x6a, 0x61,
-0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0xe7,
-0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x6a,
-0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f,
-0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65,
-0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e,
-0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e,
-0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e,
-0x3b, 0x64, 0x65, 0x7a, 0x2e, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b, 0xa3c, 0xa30, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2e, 0xa3e,
-0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0xa32, 0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32,
-0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa05, 0xa15, 0xa24, 0xa42, 0xa2c, 0xa30,
-0x3b, 0xa28, 0xa35, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30, 0xa1c, 0xa28, 0x3b, 0xa2b, 0xa3c, 0xa30, 0x3b, 0xa2e,
-0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32,
-0xa3e, 0x3b, 0xa05, 0xa17, 0x3b, 0xa38, 0xa24, 0xa70, 0x3b, 0xa05, 0xa15, 0xa24, 0xa42, 0x3b, 0xa28, 0xa35, 0xa70, 0x3b, 0xa26, 0xa38,
-0xa70, 0xa1c, 0x3b, 0xa2b, 0xa3c, 0x3b, 0xa2e, 0xa3e, 0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05,
-0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b,
-0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648,
-0x644, 0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648,
-0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b,
-0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b,
-0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f,
-0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x63, 0x74, 0x75, 0x62, 0x72,
-0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x45, 0x6e, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79,
-0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x74,
-0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x63, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x61, 0x76, 0x72,
-0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x67, 0x6c, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b,
-0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x66, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x61, 0x76,
-0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65,
-0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x64,
-0x61, 0x20, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x61, 0x20, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b,
-0x64, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x72, 0x69, 0x67, 0x6c, 0x3b, 0x64, 0x61, 0x20,
-0x6d, 0x61, 0x74, 0x67, 0x3b, 0x64, 0x61, 0x20, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x64, 0x61,
-0x20, 0x66, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x64, 0x61, 0x20,
-0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
-0x64, 0x61, 0x20, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x61, 0x20, 0x64, 0x65, 0x63, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73,
-0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x2e, 0x3b, 0x66, 0x61,
-0x6e, 0x2e, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b,
-0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a,
-0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x69, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x65,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x65, 0x3b, 0x61, 0x70,
-0x72, 0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x69, 0x75, 0x6c, 0x69,
-0x65, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b,
-0x6f, 0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6e, 0x6f, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b,
-0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x69, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d,
-0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x2e, 0x3b, 0x69, 0x75,
-0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e,
-0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b,
-0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435,
-0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44f, 0x3b, 0x43c,
-0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e, 0x43b, 0x44f, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x430,
-0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e,
-0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44f, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432,
-0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d,
-0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a,
-0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435,
-0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e,
-0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e,
-0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65,
-0x3b, 0x46, 0x75, 0x6c, 0x75, 0x6e, 0x64, 0xef, 0x67, 0x69, 0x3b, 0x4d, 0x62, 0xe4, 0x6e, 0x67, 0xfc, 0x3b, 0x4e, 0x67,
-0x75, 0x62, 0xf9, 0x65, 0x3b, 0x42, 0xea, 0x6c, 0xe4, 0x77, 0xfc, 0x3b, 0x46, 0xf6, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x65,
-0x6e, 0x67, 0x75, 0x61, 0x3b, 0x4b, 0xfc, 0x6b, 0xfc, 0x72, 0xfc, 0x3b, 0x4d, 0x76, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x67,
-0x62, 0x65, 0x72, 0x65, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x62, 0xe4, 0x6e, 0x64, 0xfc, 0x72, 0x75, 0x3b, 0x4b, 0x61, 0x6b,
-0x61, 0x75, 0x6b, 0x61, 0x4e, 0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4d, 0x62, 0xe4, 0x3b, 0x4e, 0x67, 0x75, 0x3b,
-0x42, 0xea, 0x6c, 0x3b, 0x46, 0xf6, 0x6e, 0x3b, 0x4c, 0x65, 0x6e, 0x3b, 0x4b, 0xfc, 0x6b, 0x3b, 0x4d, 0x76, 0x75, 0x3b,
-0x4e, 0x67, 0x62, 0x3b, 0x4e, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6b, 0x4e, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42,
-0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440,
-0x3b, 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b,
-0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441,
-0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432,
-0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435,
-0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443,
-0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435,
-0x446, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61,
-0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
-0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61,
-0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a,
-0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74,
-0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67,
-0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x458, 0x430, 0x43d,
-0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443,
-0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d,
-0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c,
-0x3b, 0x41c, 0x430, 0x440, 0x442, 0x44a, 0x438, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418,
-0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442,
-0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b,
-0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44b, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b,
-0x44b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x44a, 0x438, 0x439, 0x44b, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44b, 0x3b, 0x43c, 0x430,
-0x439, 0x44b, 0x3b, 0x438, 0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x44b,
-0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43d, 0x43e,
-0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44b, 0x42f, 0x43d, 0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432,
-0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x2e, 0x3b, 0x410, 0x43f, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e,
-0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x2e, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x41e,
-0x43a, 0x442, 0x2e, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x414, 0x435, 0x43a, 0x2e, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444,
-0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x44b, 0x3b, 0x438,
-0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e,
-0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x4e, 0x64, 0x69, 0x72, 0x61, 0x3b, 0x4b,
-0x75, 0x6b, 0x61, 0x64, 0x7a, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x75, 0x6d, 0x65, 0x3b, 0x4b, 0x75, 0x62, 0x76, 0x75, 0x6d,
-0x62, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x76, 0x61, 0x62, 0x76, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b,
-0x43, 0x68, 0x69, 0x6b, 0x75, 0x6e, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x4e, 0x79, 0x61, 0x6d, 0x61, 0x76, 0x68, 0x75, 0x76,
-0x68, 0x75, 0x3b, 0x47, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x61, 0x3b, 0x47, 0x75, 0x6d, 0x69, 0x67, 0x75, 0x72, 0x75, 0x3b,
-0x4d, 0x62, 0x75, 0x64, 0x7a, 0x69, 0x3b, 0x5a, 0x76, 0x69, 0x74, 0x61, 0x4e, 0x64, 0x69, 0x3b, 0x4b, 0x75, 0x6b, 0x3b,
-0x4b, 0x75, 0x72, 0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x43, 0x68, 0x76, 0x3b, 0x43, 0x68, 0x6b, 0x3b, 0x43, 0x68, 0x67, 0x3b,
-0x4e, 0x79, 0x61, 0x3b, 0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x75, 0x3b, 0x5a, 0x76, 0x69, 0x4e,
-0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d,
-0x3b, 0x5a, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x64a, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686,
-0x3b, 0x627, 0x67e, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x626, 0x64a, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x621,
-0x650, 0x3b, 0x622, 0x6af, 0x633, 0x67d, 0x3b, 0x633, 0x64a, 0x67e, 0x67d, 0x645, 0x628, 0x631, 0x3b, 0x622, 0x6aa, 0x67d, 0x648, 0x628,
-0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x68a, 0x633, 0x645, 0x628, 0x631, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b,
-0xdb4, 0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d,
-0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b,
-0xd85, 0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b,
-0xd94, 0xd9a, 0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf,
-0xdd9, 0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0x3b,
-0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2,
-0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0,
-0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b,
-0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2,
-0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0,
-0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, 0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0, 0x3b, 0xda2,
-0xdd6, 0x3b, 0xda2, 0xdd6, 0x3b, 0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b, 0xd94, 0x3b, 0xdb1, 0xdd9, 0x3b, 0xdaf, 0xdd9, 0x6a, 0x61, 0x6e,
-0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b, 0x61, 0x70,
-0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x75,
-0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61,
-0x6e, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61,
-0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x61, 0x3b, 0x6d, 0xe1, 0x6a, 0x61, 0x3b, 0x6a, 0xfa, 0x6e, 0x61, 0x3b, 0x6a, 0xfa,
-0x6c, 0x61, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61,
-0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65,
-0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70,
-0x72, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65,
-0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x76, 0x67, 0x75,
-0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61,
-0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
-0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70,
-0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x4a, 0x61, 0x6e, 0x6e,
-0x61, 0x61, 0x79, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x61, 0x61, 0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x73, 0x6f,
-0x3b, 0x41, 0x62, 0x72, 0x69, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x75,
-0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x62, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72,
-0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x66, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44,
-0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64,
-0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20,
-0x53, 0x61, 0x64, 0x64, 0x65, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61,
-0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
-0x68, 0x61, 0x20, 0x4c, 0x69, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x64, 0x6f,
-0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x69, 0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64,
-0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
-0x68, 0x61, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x77,
-0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c,
-0x61, 0x62, 0x61, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x4a, 0x61, 0x6e, 0x3b, 0x46,
-0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4c,
-0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x73, 0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x66, 0x3b, 0x44,
-0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x4f, 0x3b, 0x53, 0x3b,
-0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d,
-0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69,
-0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x69,
-0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65,
-0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75,
-0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f,
-0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
-0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x65, 0x6e, 0x65, 0x2e,
-0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e,
-0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e,
-0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x65, 0x6e, 0x65, 0x72, 0x6f,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
-0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67,
-0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62,
-0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62,
-0x72, 0x65, 0x45, 0x6e, 0x65, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72,
-0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x2e, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x67, 0x6f,
-0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x69, 0x63,
-0x2e, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e,
-0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e,
-0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e,
-0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63,
-0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a,
-0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61,
-0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65,
-0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d,
-0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f,
-0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65,
-0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61,
-0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f,
-0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
-0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a,
-0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
-0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424,
-0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439,
-0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442,
-0x44f, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a,
-0x430, 0x431, 0x440, 0xb9c, 0xba9, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe,
-0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b,
-0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0xbb8, 0xbcd, 0xb9f, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa,
-0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd, 0xb9f, 0xbcb, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b,
-0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0xb9c, 0xba9, 0x2e, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbbe,
-0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2,
-0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xb85, 0xb95, 0xbcd, 0x2e, 0x3b, 0xba8, 0xbb5, 0x2e,
-0x3b, 0xb9f, 0xbbf, 0xb9a, 0x2e, 0xb9c, 0x3b, 0xbaa, 0xbbf, 0x3b, 0xbae, 0xbbe, 0x3b, 0xb8f, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2,
-0x3b, 0xb9c, 0xbc2, 0x3b, 0xb86, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xb85, 0x3b, 0xba8, 0x3b, 0xb9f, 0xbbf, 0x433, 0x44b, 0x439, 0x43d, 0x432,
-0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435,
-0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433,
-0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c,
-0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x433, 0x44b, 0x439, 0x43d, 0x2e,
-0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b,
-0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e,
-0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0xc1c, 0xc28, 0xc35, 0xc30,
-0xc3f, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a,
-0xc4d, 0xc30, 0xc3f, 0xc32, 0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06,
-0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc05, 0xc15, 0xc4d,
-0xc1f, 0xc4b, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc28, 0xc35, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0xc2c, 0xc30,
-0xc4d, 0xc1c, 0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d,
-0xc30, 0xc3f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0x3b, 0xc38,
-0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f, 0xc38,
-0xc46, 0xc02, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0x3b, 0xc0f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0x3b, 0xc1c, 0xc41,
-0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21, 0xc3f, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01,
-0xe38, 0xe21, 0xe20, 0xe32, 0xe1e, 0xe31, 0xe19, 0xe18, 0xe4c, 0x3b, 0xe21, 0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29,
-0xe32, 0xe22, 0xe19, 0x3b, 0xe1e, 0xe24, 0xe29, 0xe20, 0xe32, 0xe04, 0xe21, 0x3b, 0xe21, 0xe34, 0xe16, 0xe38, 0xe19, 0xe32, 0xe22, 0xe19,
-0x3b, 0xe01, 0xe23, 0xe01, 0xe0e, 0xe32, 0xe04, 0xe21, 0x3b, 0xe2a, 0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31, 0xe19,
-0xe22, 0xe32, 0xe22, 0xe19, 0x3b, 0xe15, 0xe38, 0xe25, 0xe32, 0xe04, 0xe21, 0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22,
-0xe19, 0x3b, 0xe18, 0xe31, 0xe19, 0xe27, 0xe32, 0xe04, 0xe21, 0xe21, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21,
-0xe35, 0x2e, 0xe04, 0x2e, 0x3b, 0xe40, 0xe21, 0x2e, 0xe22, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22,
-0x2e, 0x3b, 0xe01, 0x2e, 0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04,
-0x2e, 0x3b, 0xe1e, 0x2e, 0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04, 0x2e, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54,
-0xf7c, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
-0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74,
-0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
-0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45,
-0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74,
-0xf58, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
-0xf63, 0xf94, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b,
-0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b,
-0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45,
-0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab,
-0x1272, 0x1275, 0x3b, 0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x12eb, 0x3b, 0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290,
-0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x1228, 0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b,
-0x1215, 0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x1235, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x3b, 0x1218, 0x130b, 0x3b, 0x121a, 0x12eb, 0x3b,
-0x130d, 0x1295, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x3b, 0x1290, 0x1213, 0x3b, 0x1218, 0x1235, 0x3b, 0x1325, 0x1245, 0x3b, 0x1215, 0x12f3,
-0x3b, 0x1273, 0x1215, 0x1325, 0x3b, 0x1208, 0x3b, 0x1218, 0x3b, 0x121a, 0x3b, 0x130d, 0x3b, 0x1230, 0x3b, 0x1213, 0x3b, 0x1290, 0x3b, 0x1218,
-0x3b, 0x1325, 0x3b, 0x1215, 0x3b, 0x1273, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x113, 0x70, 0x75, 0x65, 0x6c,
-0x69, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x73, 0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x113,
-0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x6f, 0x73, 0x69,
-0x3b, 0x53, 0x65, 0x70, 0x69, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x4e,
-0x14d, 0x76, 0x65, 0x6d, 0x61, 0x3b, 0x54, 0x12b, 0x73, 0x65, 0x6d, 0x61, 0x53, 0x101, 0x6e, 0x3b, 0x46, 0x113, 0x70, 0x3b,
-0x4d, 0x61, 0x2bb, 0x61, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75,
-0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54,
-0x12b, 0x73, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b,
-0x4f, 0x3b, 0x4e, 0x3b, 0x54, 0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e, 0x75, 0x62, 0x61, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x74,
-0x3b, 0x4e, 0x69, 0x73, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61, 0x7a, 0x69, 0x72, 0x61, 0x6e,
-0x3b, 0x54, 0x65, 0x6d, 0x6d, 0x75, 0x7a, 0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73, 0x3b, 0x45, 0x79, 0x6c, 0xfc,
-0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131, 0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6c, 0x131, 0x6b, 0x4f,
-0x63, 0x61, 0x3b, 0x15e, 0x75, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48,
-0x61, 0x7a, 0x3b, 0x54, 0x65, 0x6d, 0x3b, 0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x3b, 0x4b,
-0x61, 0x73, 0x3b, 0x41, 0x72, 0x61, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b,
-0x41, 0x3b, 0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0xdd, 0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x77, 0x72,
-0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0xfd, 0x3b, 0x49, 0xfd,
-0x75, 0x6e, 0x3b, 0x49, 0xfd, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0xfd,
-0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x44,
-0x65, 0x6b, 0x61, 0x62, 0x72, 0xfd, 0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b, 0x6d,
-0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69,
-0xfd, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b,
-0x6f, 0x6b, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62,
-0x72, 0xdd, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x77, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0xfd,
-0x3b, 0x49, 0xfd, 0x75, 0x6e, 0x3b, 0x49, 0xfd, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f,
-0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0xfd, 0x3b, 0x44, 0x65, 0x6b, 0xfd, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x77, 0x3b, 0x6d, 0x61,
-0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c,
-0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0xfd, 0x3b, 0x64, 0x65, 0x6b,
-0xdd, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
-0x4e, 0x3b, 0x44, 0x64a, 0x627, 0x646, 0x6cb, 0x627, 0x631, 0x3b, 0x641, 0x6d0, 0x6cb, 0x631, 0x627, 0x644, 0x3b, 0x645, 0x627, 0x631,
-0x62a, 0x3b, 0x626, 0x627, 0x67e, 0x631, 0x6d0, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x646, 0x3b, 0x626,
-0x649, 0x64a, 0x6c7, 0x644, 0x3b, 0x626, 0x627, 0x6cb, 0x63a, 0x6c7, 0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x646, 0x62a, 0x6d5, 0x628, 0x649,
-0x631, 0x3b, 0x626, 0x6c6, 0x643, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x646, 0x648, 0x64a, 0x627, 0x628, 0x649, 0x631, 0x3b, 0x62f,
-0x6d0, 0x643, 0x627, 0x628, 0x649, 0x631, 0x441, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442, 0x438, 0x439, 0x3b, 0x431,
-0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x442, 0x440, 0x430, 0x432,
-0x435, 0x43d, 0x44c, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x441,
-0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x436, 0x43e, 0x432, 0x442,
-0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c,
-0x441, 0x456, 0x447, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x43d, 0x44f,
-0x3b, 0x43a, 0x432, 0x456, 0x442, 0x43d, 0x44f, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x43d,
-0x44f, 0x3b, 0x43b, 0x438, 0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441,
-0x43d, 0x44f, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x430, 0x3b,
-0x433, 0x440, 0x443, 0x434, 0x43d, 0x44f, 0x441, 0x456, 0x447, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x431, 0x435, 0x440, 0x3b, 0x43a, 0x432,
-0x456, 0x3b, 0x442, 0x440, 0x430, 0x3b, 0x447, 0x435, 0x440, 0x3b, 0x43b, 0x438, 0x43f, 0x3b, 0x441, 0x435, 0x440, 0x3b, 0x432, 0x435,
-0x440, 0x3b, 0x436, 0x43e, 0x432, 0x3b, 0x43b, 0x438, 0x441, 0x3b, 0x433, 0x440, 0x443, 0x441, 0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e,
-0x442, 0x2e, 0x3b, 0x431, 0x435, 0x440, 0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x2e, 0x3b,
-0x447, 0x435, 0x440, 0x432, 0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440,
-0x2e, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x2e, 0x421,
-0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b, 0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b,
-0x3b, 0x413, 0x441, 0x3b, 0x43b, 0x3b, 0x431, 0x3b, 0x43a, 0x3b, 0x442, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x432, 0x3b,
-0x436, 0x3b, 0x43b, 0x3b, 0x433, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631,
-0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627,
-0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631,
-0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46,
-0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79,
-0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b, 0x49, 0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65,
-0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b,
-0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b,
-0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b,
-0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b,
-0x6f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72,
-0x59, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b,
-0x49, 0x79, 0x6e, 0x3b, 0x49, 0x79, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
-0x4e, 0x6f, 0x79, 0x3b, 0x44, 0x65, 0x6b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61,
-0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73,
-0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
-0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x62c, 0x646, 0x648,
-0x3b, 0x641, 0x628, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627, 0x67e, 0x631, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b,
-0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x3b, 0x633, 0x67e, 0x62a, 0x3b, 0x627, 0x6a9, 0x62a, 0x3b, 0x646, 0x648, 0x645, 0x3b,
-0x62f, 0x633, 0x645, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442,
-0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430,
-0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440,
-0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44f, 0x43d, 0x432, 0x3b, 0x444, 0x435, 0x432,
-0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b,
-0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x44f, 0x3b, 0x434, 0x435, 0x43a,
-0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x54, 0x68, 0xe1, 0x6e,
-0x67, 0x20, 0x33, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b,
-0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x36, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37, 0x3b, 0x54, 0x68, 0xe1, 0x6e,
-0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x39, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30,
-0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x32, 0x74, 0x68,
-0xe1, 0x6e, 0x67, 0x20, 0x31, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20,
-0x33, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b, 0x74, 0x68,
-0xe1, 0x6e, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20,
-0x38, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x74,
-0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x32, 0x54, 0x68, 0x67, 0x20,
-0x31, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x34, 0x3b,
-0x54, 0x68, 0x67, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x54, 0x68,
-0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x39, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x54, 0x68, 0x67,
-0x20, 0x31, 0x31, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x32, 0x74, 0x68, 0x67, 0x20, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20,
-0x32, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x33, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x35, 0x3b,
-0x74, 0x68, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x74, 0x68,
-0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x74, 0x68,
-0x67, 0x20, 0x31, 0x32, 0x79, 0x61, 0x6e, 0x75, 0x6c, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x6c, 0x3b, 0x6d, 0xe4, 0x7a, 0x75,
-0x6c, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x75, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x6c, 0x3b, 0x79, 0x75, 0x6e, 0x75, 0x6c,
-0x3b, 0x79, 0x75, 0x6c, 0x75, 0x6c, 0x3b, 0x67, 0x75, 0x73, 0x74, 0x75, 0x6c, 0x3b, 0x73, 0x65, 0x74, 0x75, 0x6c, 0x3b,
-0x74, 0x6f, 0x62, 0x75, 0x6c, 0x3b, 0x6e, 0x6f, 0x76, 0x75, 0x6c, 0x3b, 0x64, 0x65, 0x6b, 0x75, 0x6c, 0x79, 0x61, 0x6e,
-0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0xe4, 0x7a, 0x3b, 0x70, 0x72, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e,
-0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x67, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x74, 0x6f, 0x62, 0x3b, 0x6e, 0x6f, 0x76,
-0x3b, 0x64, 0x65, 0x6b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0xe4, 0x7a, 0x3b, 0x70, 0x72, 0x6c, 0x3b,
-0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x67, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x3b,
-0x74, 0x6f, 0x6e, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x6b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4d,
-0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x49, 0x6f, 0x6e, 0x61, 0x77, 0x72,
-0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x72, 0x6f, 0x72, 0x3b, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x45, 0x62, 0x72,
-0x69, 0x6c, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x65, 0x66, 0x69, 0x6e, 0x3b, 0x47, 0x6f, 0x72, 0x66,
-0x66, 0x65, 0x6e, 0x6e, 0x61, 0x66, 0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79, 0x64,
-0x72, 0x65, 0x66, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x77, 0x65, 0x64, 0x64, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x66, 0x79, 0x72,
-0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
-0x4d, 0x65, 0x68, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79,
-0x64, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66,
-0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x3b, 0x47, 0x6f, 0x72,
-0x66, 0x66, 0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x3b, 0x54, 0x61, 0x63,
-0x68, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x49, 0x3b, 0x43, 0x68, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x52, 0x68, 0x53, 0x61, 0x6d, 0x77, 0x69, 0x79, 0x65, 0x65, 0x3b,
-0x46, 0x65, 0x77, 0x72, 0x69, 0x79, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x77, 0x72, 0x69, 0x6c, 0x3b,
-0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x77, 0x65, 0x3b, 0x53, 0x75, 0x6c, 0x65, 0x74, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0xe0,
-0x74, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x77,
-0xe0, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x73, 0xe0, 0x6d, 0x62, 0x61, 0x72, 0x53, 0x61, 0x6d, 0x3b, 0x46, 0x65,
-0x77, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x77, 0x3b, 0x53, 0x75,
-0x6c, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0xe0, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x77, 0x3b, 0x44, 0x65, 0x73,
-0x4a, 0x61, 0x6e, 0x79, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b,
-0x4d, 0x61, 0x74, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a,
-0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65,
-0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61,
-0x74, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67,
-0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x5d9, 0x5d0, 0x5b7,
-0x5e0, 0x5d5, 0x5d0, 0x5b7, 0x5e8, 0x3b, 0x5e4, 0x5bf, 0x5e2, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5b7, 0x5e8, 0x3b, 0x5de, 0x5e2, 0x5e8, 0x5e5,
-0x3b, 0x5d0, 0x5b7, 0x5e4, 0x5bc, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5,
-0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d9, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e2, 0x5e4, 0x5bc, 0x5d8, 0x5e2, 0x5de, 0x5d1, 0x5e2,
-0x5e8, 0x3b, 0x5d0, 0x5e7, 0x5d8, 0x5d0, 0x5d1, 0x5e2, 0x5e8, 0x3b, 0x5e0, 0x5d0, 0x5d5, 0x5d5, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x3b,
-0x5d3, 0x5e2, 0x5e6, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x5d9, 0x5d0, 0x5b7, 0x5e0, 0x3b, 0x5e4, 0x5bf, 0x5e2, 0x5d1, 0x3b, 0x5de, 0x5e2,
-0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5b7, 0x5e4, 0x5bc, 0x5e8, 0x3b, 0x5de, 0x5d9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5,
-0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d9, 0x5d2, 0x3b, 0x5e1, 0x5e2, 0x5e4, 0x5bc, 0x3b, 0x5d0, 0x5e7, 0x5d8, 0x3b, 0x5e0, 0x5d0, 0x5d5,
-0x5d5, 0x3b, 0x5d3, 0x5e2, 0x5e6, 0x1e62, 0x1eb9, 0x301, 0x72, 0x1eb9, 0x301, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x1eb8, 0x72,
-0x1eb9, 0x300, 0x6e, 0xe0, 0x3b, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0xd2, 0x6b, 0xfa,
-0x64, 0x75, 0x3b, 0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd, 0x3b, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b,
-0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x4f, 0x1e63, 0xf9,
-0x20, 0x1e62, 0x1eb9, 0x301, 0x72, 0x1eb9, 0x301, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x4f, 0x1e63,
-0xf9, 0x20, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e, 0xe0, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x4f, 0x1e63,
-0xf9, 0x20, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x4f,
-0x1e63, 0xf9, 0x20, 0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x1e63,
-0xf9, 0x20, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x4f,
-0x1e63, 0xf9, 0x20, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x1e62, 0x1eb9, 0x301,
-0x3b, 0xc8, 0x72, 0x3b, 0x1eb8, 0x72, 0x3b, 0xcc, 0x67, 0x3b, 0x1eb8, 0x300, 0x62, 0x3b, 0xd2, 0x6b, 0x3b, 0x41, 0x67, 0x3b,
-0xd2, 0x67, 0x3b, 0x4f, 0x77, 0x3b, 0x1ecc, 0x300, 0x77, 0x3b, 0x42, 0xe9, 0x3b, 0x1ecc, 0x300, 0x70, 0x1e62, 0x1eb9, 0x301, 0x72,
-0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0x3b, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e, 0x3b, 0xcc, 0x67, 0x62, 0x3b, 0x1eb8, 0x300, 0x62, 0x69,
-0x3b, 0xd2, 0x6b, 0xfa, 0x3b, 0x41, 0x67, 0x1eb9, 0x3b, 0xd2, 0x67, 0xfa, 0x3b, 0x4f, 0x77, 0x65, 0x3b, 0x1ecc, 0x300, 0x77,
-0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0x3b, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x53, 0x3b, 0xc8, 0x3b, 0x1eb8, 0x3b, 0xcc, 0x3b, 0x1eb8, 0x300,
-0x3b, 0xd2, 0x3b, 0x41, 0x3b, 0xd2, 0x3b, 0x4f, 0x3b, 0x1ecc, 0x300, 0x3b, 0x42, 0x3b, 0x1ecc, 0x300, 0x53, 0x68, 0x25b, 0x301,
-0x72, 0x25b, 0x301, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x190, 0x72, 0x25b, 0x300, 0x6e, 0xe0, 0x3b, 0xcc, 0x67, 0x62,
-0xe9, 0x3b, 0x190, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x41, 0x67, 0x25b, 0x6d, 0x254,
-0x3b, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x186, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x42,
-0xe9, 0x6c, 0xfa, 0x3b, 0x186, 0x300, 0x70, 0x25b, 0x300, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x53, 0x68, 0x25b, 0x301, 0x72, 0x25b,
-0x301, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x190, 0x72,
-0x25b, 0x300, 0x6e, 0xe0, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20,
-0x190, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x4f, 0x73,
-0x68, 0xf9, 0x20, 0x41, 0x67, 0x25b, 0x6d, 0x254, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f,
-0x73, 0x68, 0xf9, 0x20, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x186, 0x300, 0x77, 0xe0, 0x72,
-0xe0, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x186, 0x300, 0x70,
-0x25b, 0x300, 0x53, 0x68, 0x25b, 0x301, 0x3b, 0xc8, 0x72, 0x3b, 0x190, 0x72, 0x3b, 0xcc, 0x67, 0x3b, 0x190, 0x300, 0x62, 0x3b,
-0xd2, 0x6b, 0x3b, 0x41, 0x67, 0x3b, 0xd2, 0x67, 0x3b, 0x4f, 0x77, 0x3b, 0x186, 0x300, 0x77, 0x3b, 0x42, 0xe9, 0x3b, 0x186,
-0x300, 0x70, 0x53, 0x68, 0x25b, 0x301, 0x72, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0x3b, 0x190, 0x72, 0x25b, 0x300, 0x6e, 0x3b, 0xcc,
-0x67, 0x62, 0x3b, 0x190, 0x300, 0x62, 0x69, 0x3b, 0xd2, 0x6b, 0xfa, 0x3b, 0x41, 0x67, 0x25b, 0x3b, 0xd2, 0x67, 0xfa, 0x3b,
-0x4f, 0x77, 0x65, 0x3b, 0x186, 0x300, 0x77, 0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0x3b, 0x186, 0x300, 0x70, 0x25b, 0x53, 0x3b, 0xc8,
-0x3b, 0x190, 0x3b, 0xcc, 0x3b, 0x190, 0x300, 0x3b, 0xd2, 0x3b, 0x41, 0x3b, 0xd2, 0x3b, 0x4f, 0x3b, 0x186, 0x300, 0x3b, 0x42,
-0x3b, 0x186, 0x300, 0x4a, 0x61, 0x6e, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72,
-0x69, 0x3b, 0x4d, 0x61, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x68, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b,
-0x53, 0x65, 0x70, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f,
-0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
-0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x45, 0x70, 0x68, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c,
-0x3b, 0x41, 0x67, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73,
-0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
-0x4e, 0x3b, 0x44, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70,
-0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67,
-0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73,
-0x2e, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
-0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b,
-0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
-0x62, 0x61, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
-0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f,
-0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x431,
-0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b,
-0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x443, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f,
-0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c,
-0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b,
-0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b,
-0x430, 0x443, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x4a,
-0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x67, 0x65, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68, 0x69, 0x61, 0x67,
-0x68, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x65, 0x72,
-0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x73, 0x6f, 0x75, 0x72,
-0x65, 0x65, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61,
-0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a,
-0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x48, 0x6f, 0x75,
-0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x6e, 0x79, 0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x4a, 0x2d,
-0x67, 0x75, 0x65, 0x72, 0x3b, 0x54, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b,
-0x41, 0x76, 0x72, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x73, 0x6f, 0x75,
-0x72, 0x65, 0x65, 0x3b, 0x4a, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74,
-0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72,
-0x3b, 0x4d, 0x2d, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x2d, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x6d,
-0x69, 0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x77, 0x65, 0x76, 0x72, 0x65,
-0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x62, 0x72,
-0x65, 0x6c, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x65, 0x76,
-0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73,
-0x20, 0x45, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x77, 0x79, 0x6e, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x6d,
-0x69, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x44, 0x75, 0x3b, 0x6d, 0x69, 0x73, 0x20,
-0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68, 0x75, 0x47, 0x65, 0x6e, 0x3b, 0x48, 0x77, 0x65, 0x3b, 0x4d, 0x65, 0x75, 0x3b,
-0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x3b, 0x4d, 0x65, 0x74, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x47,
-0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d, 0x186,
-0x70, 0x25b, 0x70, 0x254, 0x6e, 0x3b, 0x4b, 0x77, 0x61, 0x6b, 0x77, 0x61, 0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75,
-0x6f, 0x3b, 0x45, 0x62, 0x254, 0x77, 0x2d, 0x186, 0x62, 0x65, 0x6e, 0x65, 0x6d, 0x3b, 0x45, 0x62, 0x254, 0x62, 0x69, 0x72,
-0x61, 0x2d, 0x4f, 0x66, 0x6f, 0x72, 0x69, 0x73, 0x75, 0x6f, 0x3b, 0x45, 0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41, 0x6b,
-0x65, 0x74, 0x73, 0x65, 0x61, 0x62, 0x61, 0x2d, 0x4b, 0x254, 0x74, 0x254, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62,
-0x69, 0x72, 0x61, 0x64, 0x65, 0x2d, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x6d, 0x75, 0x6d, 0x75, 0x3b, 0x41, 0x79,
-0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x2d, 0x4b, 0x69, 0x74, 0x61, 0x77, 0x6f, 0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66, 0x75,
-0x75, 0x2d, 0x186, 0x73, 0x61, 0x6e, 0x64, 0x61, 0x61, 0x3b, 0x46, 0x61, 0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254,
-0x3b, 0x186, 0x62, 0x25b, 0x73, 0x25b, 0x2d, 0x41, 0x68, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x3b, 0x186, 0x62, 0x65, 0x72, 0x25b,
-0x66, 0x25b, 0x77, 0x2d, 0x4f, 0x62, 0x75, 0x62, 0x75, 0x6f, 0x3b, 0x4d, 0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b, 0x6e,
-0x69, 0x6d, 0x62, 0x61, 0x53, 0x2d, 0x186, 0x3b, 0x4b, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f, 0x3b,
-0x45, 0x2d, 0x4b, 0x3b, 0x4f, 0x2d, 0x41, 0x3b, 0x41, 0x2d, 0x4b, 0x3b, 0x44, 0x2d, 0x186, 0x3b, 0x46, 0x2d, 0x190, 0x3b,
-0x186, 0x2d, 0x41, 0x3b, 0x186, 0x2d, 0x4f, 0x3b, 0x4d, 0x2d, 0x186, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b,
-0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d,
-0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x92f, 0x3b, 0x906, 0x917, 0x94b,
-0x938, 0x94d, 0x924, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930,
-0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x4a, 0x65,
-0x6e, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x4d, 0x61, 0x61,
-0x63, 0x68, 0x1ecb, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b,
-0x4a, 0x75, 0x6c, 0x61, 0x1ecb, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
-0x61, 0x3b, 0x1ecc, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73,
-0x65, 0x6d, 0x62, 0x61, 0x4a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x45, 0x70, 0x72, 0x3b,
-0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x3b, 0x53, 0x65, 0x70, 0x3b,
-0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d,
-0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x1ecc, 0x3b, 0x53, 0x3b, 0x1ecc, 0x3b, 0x4e, 0x3b, 0x44, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b,
-0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61,
-0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169,
-0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x75, 0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x6e, 0x79, 0x61, 0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x3b,
-0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x129, 0x6d, 0x77,
-0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69,
-0x6c, 0x129, 0x4d, 0x62, 0x65, 0x3b, 0x4b, 0x65, 0x6c, 0x3b, 0x4b, 0x74, 0x169, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x74,
-0x6e, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x4b, 0x6e, 0x64, 0x3b, 0x128, 0x6b,
-0x75, 0x3b, 0x128, 0x6b, 0x6d, 0x3b, 0x128, 0x6b, 0x6c, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54,
-0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x128, 0x5a, 0x65, 0x6e, 0xe2, 0x72, 0x3b, 0x46, 0x65,
-0x76, 0x72, 0xe2, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
-0x4a, 0x75, 0x67, 0x6e, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d,
-0x62, 0x61, 0x72, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b,
-0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x5a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b,
-0x41, 0x76, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x3b,
-0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x63, 0x5a, 0x3b, 0x46, 0x3b, 0x4d,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x64, 0x7a,
-0x6f, 0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66,
-0x254, 0x66, 0x129, 0x65, 0x3b, 0x64, 0x61, 0x6d, 0x61, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c,
-0x254, 0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79,
-0x254, 0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x64,
-0x7a, 0x6f, 0x6d, 0x65, 0x64, 0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61, 0x66, 0x254, 0x3b,
-0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79, 0x3b,
-0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x64, 0x3b, 0x64, 0x3b, 0x74, 0x3b, 0x61, 0x3b, 0x64,
-0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x61, 0x3b, 0x6b, 0x3b, 0x61, 0x3b, 0x64, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x6c,
-0x69, 0x3b, 0x50, 0x65, 0x70, 0x65, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x6b, 0x69, 0x3b, 0x2bb,
-0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49, 0x75, 0x6c,
-0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b, 0x61, 0x6b, 0x65, 0x3b, 0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, 0x61, 0x70,
-0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x6b, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x77, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b,
-0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x49, 0x61, 0x6e, 0x2e, 0x3b, 0x50, 0x65, 0x70, 0x2e, 0x3b, 0x4d, 0x61,
-0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c,
-0x2e, 0x3b, 0x2bb, 0x41, 0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, 0x3b, 0x2bb, 0x4f, 0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77,
-0x2e, 0x3b, 0x4b, 0x65, 0x6b, 0x2e, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b,
-0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6e,
-0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x79,
-0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x62, 0x79, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x45, 0x6e, 0x65, 0x3b, 0x50, 0x65, 0x62,
-0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c,
-0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73,
-0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67,
-0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x4a, 0x61, 0x6e,
-0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72,
-0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67,
-0x75, 0x73, 0x63, 0x68, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
-0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62,
-0x65, 0x72, 0xa2cd, 0xa1aa, 0x3b, 0xa44d, 0xa1aa, 0x3b, 0xa315, 0xa1aa, 0x3b, 0xa1d6, 0xa1aa, 0x3b, 0xa26c, 0xa1aa, 0x3b, 0xa0d8, 0xa1aa, 0x3b,
-0xa3c3, 0xa1aa, 0x3b, 0xa246, 0xa1aa, 0x3b, 0xa22c, 0xa1aa, 0x3b, 0xa2b0, 0xa1aa, 0x3b, 0xa2b0, 0xa2aa, 0xa1aa, 0x3b, 0xa2b0, 0xa44b, 0xa1aa, 0x4a,
-0x61, 0x6e, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a,
-0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
-0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b,
-0x74, 0x6f, 0x76, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70,
-0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67,
-0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a,
-0x2e, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x76,
-0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x63,
-0x75, 0x6f, 0x14b, 0x6f, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e,
-0x75, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x64, 0x6e,
-0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x10d, 0x61,
-0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f, 0x74, 0x6d, 0xe1, 0x6e, 0x6e,
-0x75, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0x61,
-0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x3b,
-0x63, 0x75, 0x6f, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x3b, 0x62,
-0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x3b, 0x6a,
-0x75, 0x6f, 0x76, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x10c,
-0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x4a, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75, 0x6b,
-0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f, 0x69,
-0x3b, 0x62, 0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62,
-0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x43, 0x68, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x61,
-0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x65, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x43, 0x68, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b,
-0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x62,
-0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x43, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
-0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x43, 0x75, 0x6c, 0x3b,
-0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x43,
-0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e,
-0x3b, 0x44, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6d, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4d,
-0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67,
-0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61,
-0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61,
-0x6e, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x72, 0x61, 0x6e, 0x64, 0x61,
-0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6d, 0x66, 0x75, 0x6e, 0x67, 0x61, 0x64,
-0x65, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x77, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61,
-0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x6f,
-0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67,
-0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b,
-0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69,
-0x77, 0x69, 0x49, 0x6d, 0x62, 0x3b, 0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61,
-0x73, 0x3b, 0x4b, 0x61, 0x72, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x57, 0x75, 0x6e, 0x3b, 0x49, 0x6b, 0x65, 0x3b, 0x49, 0x6b,
-0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x77, 0x69, 0x49, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b,
-0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x73, 0x69, 0x69, 0x6c, 0x6f, 0x3b, 0x63, 0x6f,
-0x6c, 0x74, 0x65, 0x3b, 0x6d, 0x62, 0x6f, 0x6f, 0x79, 0x3b, 0x73, 0x65, 0x65, 0x257, 0x74, 0x6f, 0x3b, 0x64, 0x75, 0x75,
-0x6a, 0x61, 0x6c, 0x3b, 0x6b, 0x6f, 0x72, 0x73, 0x65, 0x3b, 0x6d, 0x6f, 0x72, 0x73, 0x6f, 0x3b, 0x6a, 0x75, 0x6b, 0x6f,
-0x3b, 0x73, 0x69, 0x69, 0x6c, 0x74, 0x6f, 0x3b, 0x79, 0x61, 0x72, 0x6b, 0x6f, 0x6d, 0x61, 0x61, 0x3b, 0x6a, 0x6f, 0x6c,
-0x61, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x74, 0x65, 0x73, 0x69, 0x69, 0x3b, 0x63, 0x6f, 0x6c, 0x3b, 0x6d, 0x62, 0x6f, 0x3b,
-0x73, 0x65, 0x65, 0x3b, 0x64, 0x75, 0x75, 0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x3b, 0x6a, 0x75, 0x6b, 0x3b,
-0x73, 0x6c, 0x74, 0x3b, 0x79, 0x61, 0x72, 0x3b, 0x6a, 0x6f, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x73, 0x3b, 0x63, 0x3b, 0x6d,
-0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a, 0x3b, 0x62, 0x4e, 0x6a,
-0x65, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x72, 0x129,
-0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65,
-0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20,
-0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61,
-0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65,
-0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69,
-0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4e, 0x64, 0x69, 0x74, 0x68, 0x65, 0x6d,
-0x62, 0x61, 0x4a, 0x45, 0x4e, 0x3b, 0x57, 0x4b, 0x52, 0x3b, 0x57, 0x47, 0x54, 0x3b, 0x57, 0x4b, 0x4e, 0x3b, 0x57, 0x54,
-0x4e, 0x3b, 0x57, 0x54, 0x44, 0x3b, 0x57, 0x4d, 0x4a, 0x3b, 0x57, 0x4e, 0x4e, 0x3b, 0x57, 0x4b, 0x44, 0x3b, 0x57, 0x49,
-0x4b, 0x3b, 0x57, 0x4d, 0x57, 0x3b, 0x44, 0x49, 0x54, 0x4a, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47,
-0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20,
-0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4c, 0x61,
-0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20,
-0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x65, 0x74,
-0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65,
-0x20, 0x73, 0x61, 0x70, 0x61, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x69, 0x65, 0x74, 0x3b,
-0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65,
-0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e,
-0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x77,
-0x61, 0x61, 0x72, 0x65, 0x4f, 0x62, 0x6f, 0x3b, 0x57, 0x61, 0x61, 0x3b, 0x4f, 0x6b, 0x75, 0x3b, 0x4f, 0x6e, 0x67, 0x3b,
-0x49, 0x6d, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x49, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x3b,
-0x54, 0x6f, 0x6d, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x54, 0x6f, 0x77, 0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x49,
-0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72,
-0x6f, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x6f, 0x3b, 0x41, 0x62, 0x72,
-0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b,
-0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x74, 0x75,
-0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72,
-0x6f, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75,
-0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x5a, 0x69, 0x62, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x6c, 0x61, 0x3b, 0x4e,
-0x68, 0x6c, 0x6f, 0x6c, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x62, 0x69, 0x6d, 0x62, 0x69, 0x74, 0x68, 0x6f, 0x3b, 0x4d,
-0x61, 0x62, 0x61, 0x73, 0x61, 0x3b, 0x4e, 0x6b, 0x77, 0x65, 0x6e, 0x6b, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4e, 0x68, 0x6c,
-0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x6c, 0x69, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4e, 0x63, 0x77,
-0x61, 0x62, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x64, 0x75, 0x6c, 0x61, 0x3b, 0x4d, 0x66, 0x75,
-0x6d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x5a,
-0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c, 0x6f, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77, 0x3b,
-0x4e, 0x68, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x3b, 0x4e, 0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x3b, 0x4d, 0x66,
-0x75, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x5a, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b,
-0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61,
-0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x69,
-0x74, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65,
-0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f,
-0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61,
-0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x4d, 0x31, 0x3b, 0x4d, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4d, 0x34, 0x3b, 0x4d, 0x35,
-0x3b, 0x4d, 0x36, 0x3b, 0x4d, 0x37, 0x3b, 0x4d, 0x38, 0x3b, 0x4d, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31,
-0x3b, 0x4d, 0x31, 0x32, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b,
-0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x2d49, 0x2d4f, 0x2d4f, 0x2d30, 0x2d62, 0x2d54, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x2d62, 0x2d55, 0x3b,
-0x2d4e, 0x2d30, 0x2d55, 0x2d5a, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x2d49, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4f,
-0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x2d62, 0x2d53, 0x2d63, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x2d5c, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x2d30, 0x2d4f,
-0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x2d31, 0x2d54, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d37,
-0x2d53, 0x2d4a, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x2d49, 0x2d4f, 0x2d4f, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x3b, 0x2d49,
-0x2d31, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x3b, 0x2d5b,
-0x2d53, 0x2d5c, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b,
-0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62, 0x3b, 0x2d56, 0x3b, 0x2d5b, 0x3b, 0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x69, 0x6e, 0x6e,
-0x61, 0x79, 0x72, 0x3b, 0x62, 0x1e5b, 0x61, 0x79, 0x1e5b, 0x3b, 0x6d, 0x61, 0x1e5b, 0x1e63, 0x3b, 0x69, 0x62, 0x72, 0x69, 0x72,
-0x3b, 0x6d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b,
-0x263, 0x75, 0x63, 0x74, 0x3b, 0x63, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x3b,
-0x6e, 0x75, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x64, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x69, 0x6e, 0x6e,
-0x3b, 0x62, 0x1e5b, 0x61, 0x3b, 0x6d, 0x61, 0x1e5b, 0x3b, 0x69, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e,
-0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x263, 0x75, 0x63, 0x3b, 0x63, 0x75, 0x74, 0x3b, 0x6b, 0x74, 0x75, 0x3b, 0x6e, 0x75, 0x77,
-0x3b, 0x64, 0x75, 0x6a, 0x69, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x263, 0x3b,
-0x63, 0x3b, 0x6b, 0x3b, 0x6e, 0x3b, 0x64, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x46, 0x75, 0x1e5b, 0x61,
-0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72, 0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79,
-0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43,
-0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x57, 0x61, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b,
-0x44, 0x75, 0x1e7, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x46, 0x75, 0x1e5b,
-0x61, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72, 0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79,
-0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b,
-0x43, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x4e, 0x75, 0x6e, 0x65, 0x6d, 0x62,
-0x65, 0x1e5b, 0x3b, 0x44, 0x75, 0x1e7, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b, 0x4d,
-0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194,
-0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x57, 0x61, 0x6d, 0x3b, 0x44, 0x75, 0x6a, 0x59, 0x65,
-0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75,
-0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x4e, 0x75,
-0x6e, 0x3b, 0x44, 0x75, 0x1e7, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194,
-0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x59, 0x3b, 0x46, 0x3b, 0x194, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b,
-0x4c, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x52, 0x3b, 0x57, 0x3b, 0x44, 0x4f, 0x6b, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e,
-0x7a, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61,
-0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b,
-0x61, 0x74, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x4f,
-0x6b, 0x77, 0x61, 0x6d, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x6a, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6e, 0x61,
-0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x77, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69,
-0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6b, 0x75,
-0x6d, 0x77, 0x65, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x62, 0x69,
-0x72, 0x69, 0x4b, 0x42, 0x5a, 0x3b, 0x4b, 0x42, 0x52, 0x3b, 0x4b, 0x53, 0x54, 0x3b, 0x4b, 0x4b, 0x4e, 0x3b, 0x4b, 0x54,
-0x4e, 0x3b, 0x4b, 0x4d, 0x4b, 0x3b, 0x4b, 0x4d, 0x53, 0x3b, 0x4b, 0x4d, 0x4e, 0x3b, 0x4b, 0x4d, 0x57, 0x3b, 0x4b, 0x4b,
-0x4d, 0x3b, 0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
-0x77, 0x61, 0x20, 0x68, 0x75, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
-0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
-0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a,
-0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a,
-0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64,
-0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a,
-0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
-0x20, 0x67, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
-0x67, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
-0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77,
-0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77,
-0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69,
-0x6c, 0x69, 0x48, 0x75, 0x74, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x44, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x48, 0x61,
-0x6e, 0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75,
-0x6d, 0x3b, 0x4b, 0x6d, 0x6a, 0x3b, 0x4b, 0x6d, 0x62, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x53,
-0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b,
-0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c,
-0x79, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x61, 0x69, 0x3b,
-0x41, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
-0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x7a, 0x61,
-0x6e, 0x77, 0x75, 0x79, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x72, 0x75, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x69, 0x73,
-0x69, 0x3b, 0x61, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x25b, 0x6e, 0x3b, 0x7a,
-0x75, 0x6c, 0x75, 0x79, 0x65, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b,
-0x254, 0x6b, 0x75, 0x74, 0x254, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b,
-0x64, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72,
-0x3b, 0x61, 0x77, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x3b, 0x7a, 0x75, 0x6c, 0x3b, 0x75, 0x74, 0x69, 0x3b,
-0x73, 0x25b, 0x74, 0x3b, 0x254, 0x6b, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x73, 0x5a, 0x3b, 0x46, 0x3b, 0x4d,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e, 0x3b, 0x44, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x6b, 0x61, 0x129, 0x72, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74,
-0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d,
-0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e,
-0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65,
-0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x4b,
-0x61, 0x129, 0x72, 0x129, 0x4d, 0x62, 0x65, 0x3b, 0x4b, 0x61, 0x69, 0x3b, 0x4b, 0x61, 0x74, 0x3b, 0x4b, 0x61, 0x6e, 0x3b,
-0x47, 0x61, 0x74, 0x3b, 0x47, 0x61, 0x6e, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x4b, 0x6e, 0x6e, 0x3b, 0x4b, 0x65, 0x6e, 0x3b,
-0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x67, 0x69, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47,
-0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x13a4, 0x13c3, 0x13b8, 0x13d4, 0x13c5, 0x3b,
-0x13a7, 0x13a6, 0x13b5, 0x3b, 0x13a0, 0x13c5, 0x13f1, 0x3b, 0x13a7, 0x13ec, 0x13c2, 0x3b, 0x13a0, 0x13c2, 0x13cd, 0x13ac, 0x13d8, 0x3b, 0x13d5, 0x13ad,
-0x13b7, 0x13f1, 0x3b, 0x13ab, 0x13f0, 0x13c9, 0x13c2, 0x3b, 0x13a6, 0x13b6, 0x13c2, 0x3b, 0x13da, 0x13b5, 0x13cd, 0x13d7, 0x3b, 0x13da, 0x13c2, 0x13c5,
-0x13d7, 0x3b, 0x13c5, 0x13d3, 0x13d5, 0x13c6, 0x3b, 0x13a5, 0x13cd, 0x13a9, 0x13f1, 0x13a4, 0x13c3, 0x3b, 0x13a7, 0x13a6, 0x3b, 0x13a0, 0x13c5, 0x3b,
-0x13a7, 0x13ec, 0x3b, 0x13a0, 0x13c2, 0x3b, 0x13d5, 0x13ad, 0x3b, 0x13ab, 0x13f0, 0x3b, 0x13a6, 0x13b6, 0x3b, 0x13da, 0x13b5, 0x3b, 0x13da, 0x13c2,
-0x3b, 0x13c5, 0x13d3, 0x3b, 0x13a5, 0x13cd, 0x13a4, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5, 0x3b, 0x13ab, 0x3b,
-0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a5, 0x7a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x76, 0x72,
-0x69, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69,
-0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x79, 0x65, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x3b, 0x6f,
-0x6b, 0x74, 0x6f, 0x62, 0x3b, 0x6e, 0x6f, 0x76, 0x61, 0x6d, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6d, 0x7a, 0x61, 0x6e, 0x3b,
-0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a,
-0x69, 0x6c, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64,
-0x65, 0x73, 0x7a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b,
-0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x4e, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x77,
-0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x54, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63,
-0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d,
-0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x6d,
-0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61,
-0x20, 0x4d, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79,
-0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69,
-0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20,
-0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61,
-0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x3b, 0x4d, 0x77,
-0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79,
-0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x4b, 0x289, 0x66, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4b, 0x289,
-0x6e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x289, 0x6b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6b,
-0x75, 0x6d, 0x69, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x4b, 0x77, 0x69,
-0x69, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4b, 0x289, 0x6d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x4b, 0x289,
-0x76, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79,
-0x69, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x73, 0x61, 0x74, 0x289, 0x46, 0xfa,
-0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x49,
-0x6b, 0xfa, 0x6d, 0x69, 0x3b, 0x49, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0x61, 0x6c, 0x61, 0x3b, 0x49, 0x64, 0x77, 0x61, 0x61,
-0x74, 0x61, 0x3b, 0x4d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x56, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x53, 0x61, 0x61,
-0x74, 0x289, 0x3b, 0x49, 0x6e, 0x79, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x53, 0x61, 0x73, 0x61, 0x74, 0x289,
-0x46, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b,
-0x53, 0x3b, 0x53, 0x4a, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x77, 0x61, 0x6c, 0x69,
-0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x70, 0x75, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x61, 0x79,
-0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73,
-0x69, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x62, 0x75, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f,
-0x62, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a,
-0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x75, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4a,
-0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x69, 0x3b, 0x4e,
-0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61,
-0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a,
-0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61,
-0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b,
-0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b,
-0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d,
-0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x61,
-0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x75, 0x3b, 0x41,
-0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x75, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x68,
-0x75, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74,
-0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69, 0x7a, 0x65, 0x6e, 0x62,
-0x72, 0x75, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61,
-0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74,
-0x75, 0x3b, 0x4e, 0x75, 0x76, 0x3b, 0x44, 0x69, 0x7a, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x46, 0x65, 0x62,
-0x75, 0x72, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x128, 0x70, 0x75, 0x72, 0x169, 0x3b, 0x4d,
-0x129, 0x129, 0x3b, 0x4e, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x72, 0x61, 0x129, 0x3b, 0x41, 0x67, 0x61, 0x73,
-0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x169, 0x62, 0x61, 0x3b, 0x4e,
-0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x41, 0x4e, 0x3b, 0x46, 0x45,
-0x42, 0x3b, 0x4d, 0x41, 0x43, 0x3b, 0x128, 0x50, 0x55, 0x3b, 0x4d, 0x128, 0x128, 0x3b, 0x4e, 0x4a, 0x55, 0x3b, 0x4e, 0x4a,
-0x52, 0x3b, 0x41, 0x47, 0x41, 0x3b, 0x53, 0x50, 0x54, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4e, 0x4f, 0x56, 0x3b, 0x44, 0x45,
-0x43, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
-0x3b, 0x4e, 0x3b, 0x44, 0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x2019, 0x61, 0x74, 0x79, 0x61, 0x61, 0x74,
-0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61, 0x61, 0x6d, 0x6f, 0x3b, 0x49, 0x77, 0x6f, 0x6f, 0x74, 0x6b, 0x75, 0x75, 0x74,
-0x3b, 0x4d, 0x61, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x50, 0x61, 0x61, 0x67, 0x69, 0x3b, 0x4e, 0x67, 0x2019, 0x65, 0x69, 0x79,
-0x65, 0x65, 0x74, 0x3b, 0x52, 0x6f, 0x6f, 0x70, 0x74, 0x75, 0x69, 0x3b, 0x42, 0x75, 0x72, 0x65, 0x65, 0x74, 0x3b, 0x45,
-0x70, 0x65, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x20, 0x74,
-0x61, 0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20, 0x61,
-0x65, 0x6e, 0x67, 0x2019, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x61, 0x3b, 0x49, 0x77, 0x6f,
-0x3b, 0x4d, 0x61, 0x6d, 0x3b, 0x50, 0x61, 0x61, 0x3b, 0x4e, 0x67, 0x65, 0x3b, 0x52, 0x6f, 0x6f, 0x3b, 0x42, 0x75, 0x72,
-0x3b, 0x45, 0x70, 0x65, 0x3b, 0x4b, 0x70, 0x74, 0x3b, 0x4b, 0x70, 0x61, 0x4d, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b,
-0x4d, 0x3b, 0x50, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e,
-0x6e, 0x69, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x1c0, 0x67, 0xf4, 0x61, 0x62, 0x3b, 0x1c0, 0x4b, 0x68, 0x75, 0x75, 0x1c1,
-0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c3, 0x48, 0xf4, 0x61, 0x1c2, 0x6b, 0x68, 0x61, 0x69, 0x62, 0x3b, 0x1c3, 0x4b, 0x68, 0x61,
-0x69, 0x74, 0x73, 0xe2, 0x62, 0x3b, 0x47, 0x61, 0x6d, 0x61, 0x1c0, 0x61, 0x65, 0x62, 0x3b, 0x1c2, 0x4b, 0x68, 0x6f, 0x65,
-0x73, 0x61, 0x6f, 0x62, 0x3b, 0x41, 0x6f, 0x1c1, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b,
-0x54, 0x61, 0x72, 0x61, 0x1c0, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c2, 0x4e, 0xfb,
-0x1c1, 0x6e, 0xe2, 0x69, 0x73, 0x65, 0x62, 0x3b, 0x1c0, 0x48, 0x6f, 0x6f, 0x1c2, 0x67, 0x61, 0x65, 0x62, 0x3b, 0x48, 0xf4,
-0x61, 0x73, 0x6f, 0x72, 0x65, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61, 0x3b, 0x46, 0xe4,
-0x62, 0x72, 0x6f, 0x77, 0x61, 0x3b, 0x4d, 0xe4, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x6c, 0x3b, 0x4d, 0x61,
-0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x4f, 0x75, 0x6a, 0x6f, 0xdf, 0x3b,
-0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x68, 0x62, 0x65, 0x72, 0x3b, 0x4e,
-0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x2e,
-0x3b, 0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x7a, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f, 0x75, 0x6a, 0x2e, 0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b,
-0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0xe4,
-0x62, 0x3b, 0x4d, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
-0x6c, 0x3b, 0x4f, 0x75, 0x6a, 0x3b, 0x53, 0xe4, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65,
-0x7a, 0x4f, 0x6c, 0x61, 0x64, 0x61, 0x6c, 0x289, 0x301, 0x3b, 0x41, 0x72, 0xe1, 0x74, 0x3b, 0x186, 0x25b, 0x6e, 0x268, 0x301,
-0x254, 0x268, 0x14b, 0x254, 0x6b, 0x3b, 0x4f, 0x6c, 0x6f, 0x64, 0x6f, 0x79, 0xed, 0xf3, 0x72, 0xed, 0xea, 0x20, 0x69, 0x6e,
-0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4f, 0x6c, 0x6f, 0x69, 0x6c, 0xe9, 0x70, 0x16b, 0x6e, 0x79, 0x12b, 0x113, 0x20, 0x69,
-0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4b, 0xfa, 0x6a, 0xfa, 0x254, 0x72, 0x254, 0x6b, 0x3b, 0x4d, 0xf3, 0x72, 0x75,
-0x73, 0xe1, 0x73, 0x69, 0x6e, 0x3b, 0x186, 0x6c, 0x254, 0x301, 0x268, 0x301, 0x62, 0x254, 0x301, 0x72, 0xe1, 0x72, 0x25b, 0x3b,
-0x4b, 0xfa, 0x73, 0x68, 0xee, 0x6e, 0x3b, 0x4f, 0x6c, 0x67, 0xed, 0x73, 0x61, 0x6e, 0x3b, 0x50, 0x289, 0x73, 0x68, 0x289,
-0x301, 0x6b, 0x61, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x14b, 0x289, 0x301, 0x73, 0x44, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0xe1, 0x3b,
-0x186, 0x25b, 0x6e, 0x3b, 0x44, 0x6f, 0x79, 0x3b, 0x4c, 0xe9, 0x70, 0x3b, 0x52, 0x6f, 0x6b, 0x3b, 0x53, 0xe1, 0x73, 0x3b,
-0x42, 0x254, 0x301, 0x72, 0x3b, 0x4b, 0xfa, 0x73, 0x3b, 0x47, 0xed, 0x73, 0x3b, 0x53, 0x68, 0x289, 0x301, 0x3b, 0x4e, 0x74,
-0x289, 0x301, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65,
-0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
-0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63,
-0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f,
-0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x4f, 0x72, 0x61, 0x72,
-0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x67, 0x2019, 0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67,
-0x2019, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d, 0x6f, 0x64, 0x6f, 0x6b, 0x2019, 0x6b, 0x69,
-0x6e, 0x67, 0x2019, 0x6f, 0x6c, 0x3b, 0x4f, 0x6a, 0x6f, 0x6c, 0x61, 0x3b, 0x4f, 0x70, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x4f,
-0x73, 0x6f, 0x6b, 0x6f, 0x73, 0x6f, 0x6b, 0x6f, 0x6d, 0x61, 0x3b, 0x4f, 0x74, 0x69, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6c,
-0x61, 0x62, 0x6f, 0x72, 0x3b, 0x4f, 0x70, 0x6f, 0x6f, 0x52, 0x61, 0x72, 0x3b, 0x4d, 0x75, 0x6b, 0x3b, 0x4b, 0x77, 0x61,
-0x3b, 0x44, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x6f, 0x64, 0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x50, 0x65, 0x64,
-0x3b, 0x53, 0x6f, 0x6b, 0x3b, 0x54, 0x69, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x50, 0x6f, 0x6f, 0x52, 0x3b, 0x4d, 0x3b,
-0x4b, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x50, 0x17d,
-0x61, 0x6e, 0x77, 0x69, 0x79, 0x65, 0x3b, 0x46, 0x65, 0x65, 0x77, 0x69, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x4d, 0x61, 0x72,
-0x73, 0x69, 0x3b, 0x41, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x65, 0x14b, 0x3b, 0x17d,
-0x75, 0x79, 0x79, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x4f, 0x6b,
-0x74, 0x6f, 0x6f, 0x62, 0x75, 0x72, 0x3b, 0x4e, 0x6f, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x44, 0x65, 0x65,
-0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x17d, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77,
-0x69, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x3b, 0x17d, 0x75, 0x79, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x3b,
-0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x6f, 0x3b, 0x44, 0x65, 0x65, 0x17d, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d,
-0x3b, 0x17d, 0x3b, 0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61,
-0x72, 0x20, 0x41, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x72, 0x69,
-0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x44, 0x77, 0x65, 0x20,
-0x6d, 0x61, 0x72, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20,
-0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x75, 0x63, 0x68, 0x69, 0x65,
-0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77,
-0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x6f, 0x72, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20,
-0x4f, 0x63, 0x68, 0x69, 0x6b, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72, 0x3b,
-0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77,
-0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x72, 0x69, 0x79, 0x6f, 0x44,
-0x41, 0x43, 0x3b, 0x44, 0x41, 0x52, 0x3b, 0x44, 0x41, 0x44, 0x3b, 0x44, 0x41, 0x4e, 0x3b, 0x44, 0x41, 0x48, 0x3b, 0x44,
-0x41, 0x55, 0x3b, 0x44, 0x41, 0x4f, 0x3b, 0x44, 0x41, 0x42, 0x3b, 0x44, 0x4f, 0x43, 0x3b, 0x44, 0x41, 0x50, 0x3b, 0x44,
-0x47, 0x49, 0x3b, 0x44, 0x41, 0x47, 0x43, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b,
-0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x59, 0x65,
-0x62, 0x72, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x49, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61,
-0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x194, 0x75, 0x63,
-0x74, 0x3b, 0x43, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x4b, 0x1e6d, 0x75, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x77,
-0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x44, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x59, 0x65, 0x6e, 0x3b, 0x59, 0x65,
-0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x49, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75,
-0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x75, 0x74, 0x3b, 0x4b, 0x1e6d, 0x75, 0x3b, 0x4e, 0x77, 0x61, 0x3b, 0x44, 0x75,
-0x6a, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x4b,
-0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x6c, 0x75, 0x61, 0x6c, 0x69,
-0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x6c, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75,
-0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74,
-0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b,
-0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x91c, 0x93e, 0x928, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d,
-0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x938, 0x3b, 0x90f, 0x92b, 0x94d, 0x930, 0x93f, 0x932, 0x3b,
-0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x907, 0x3b, 0x906, 0x917, 0x938, 0x94d, 0x925, 0x3b, 0x938,
-0x947, 0x92c, 0x925, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x905, 0x916, 0x925, 0x92c, 0x930, 0x3b, 0x928, 0x92c, 0x947, 0x91c,
-0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x91c, 0x3b, 0x92b, 0x947, 0x3b, 0x92e,
-0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x3b, 0x91c, 0x941, 0x3b, 0x906, 0x3b, 0x938, 0x947, 0x3b, 0x905, 0x3b,
-0x928, 0x3b, 0x926, 0x93f, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x444, 0x435, 0x432, 0x440,
-0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x44a, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301,
-0x43b, 0x43b, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x439, 0x3b, 0x456,
-0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x439, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x44a, 0x3b, 0x441, 0x435, 0x43f,
-0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x439, 0x3b,
-0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439,
-0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440,
-0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b, 0x457, 0x430,
-0x3b, 0x43c, 0x430, 0x301, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b,
-0x457, 0x430, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c,
-0x432, 0x440, 0x457, 0x430, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43d, 0x43e, 0x435, 0x301,
-0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x456, 0x486, 0x430, 0x2de9,
-0x487, 0x3b, 0x444, 0x435, 0x2de1, 0x487, 0x3b, 0x43c, 0x430, 0x2dec, 0x487, 0x3b, 0x430, 0x486, 0x43f, 0x2dec, 0x487, 0x3b, 0x43c, 0x430,
-0xa675, 0x3b, 0x456, 0x486, 0xa64b, 0x2de9, 0x487, 0x3b, 0x456, 0x486, 0xa64b, 0x2de7, 0x487, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x2de2, 0x487,
-0x3b, 0x441, 0x435, 0x2deb, 0x487, 0x3b, 0x47b, 0x486, 0x43a, 0x2dee, 0x3b, 0x43d, 0x43e, 0x435, 0x2de8, 0x3b, 0x434, 0x435, 0x2de6, 0x487,
-0x406, 0x486, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x486, 0x3b, 0x41c, 0x3b, 0x406, 0x486, 0x3b, 0x406, 0x486, 0x3b, 0x410, 0x486,
-0x3b, 0x421, 0x3b, 0x47a, 0x486, 0x3b, 0x41d, 0x3b, 0x414, 0x43, 0x69, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0xf9, 0x69, 0x73,
-0x68, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0xf2, 0x6c, 0x6f, 0x3b, 0x4d, 0xf9, 0x75, 0x79, 0xe0, 0x3b, 0x4c, 0x75, 0x6d, 0xf9,
-0x6e, 0x67, 0xf9, 0x6c, 0xf9, 0x3b, 0x4c, 0x75, 0x66, 0x75, 0x69, 0x6d, 0x69, 0x3b, 0x4b, 0x61, 0x62, 0xe0, 0x6c, 0xe0,
-0x73, 0x68, 0xec, 0x70, 0xf9, 0x3b, 0x4c, 0xf9, 0x73, 0x68, 0xec, 0x6b, 0xe0, 0x3b, 0x4c, 0x75, 0x74, 0x6f, 0x6e, 0x67,
-0x6f, 0x6c, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x67, 0xf9, 0x64, 0x69, 0x3b, 0x4b, 0x61, 0x73, 0x77, 0xe8, 0x6b, 0xe8, 0x73,
-0xe8, 0x3b, 0x43, 0x69, 0x73, 0x77, 0xe0, 0x43, 0x69, 0x6f, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0x3b, 0x4d,
-0x75, 0x75, 0x3b, 0x4c, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x66, 0x3b, 0x4b, 0x61, 0x62, 0x3b, 0x4c, 0x75, 0x73, 0x68, 0x3b,
-0x4c, 0x75, 0x74, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x43, 0x69, 0x73, 0x43, 0x3b, 0x4c, 0x3b, 0x4c,
-0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x43, 0x4a, 0x61,
-0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x65, 0x72, 0x7a, 0x3b, 0x41,
-0x62, 0x72, 0xeb, 0x6c, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b,
-0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
-0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x65,
-0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
-0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d,
-0xe4, 0x65, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75,
-0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f,
-0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0xf9, 0x6d, 0x3b, 0x6e,
-0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x197, 0x300, 0x7a, 0xf9, 0x294, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b,
-0x254, 0x300, 0x74, 0x197, 0x300, 0x64, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300,
-0x74, 0x1ce, 0x61, 0x66, 0x289, 0x304, 0x67, 0x68, 0x101, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0xe8, 0x73, 0xe8, 0x65,
-0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0x7a, 0xf9, 0x67, 0x68, 0xf2, 0x3b, 0x6e, 0x64, 0x7a, 0x254,
-0x300, 0x14b, 0x254, 0x300, 0x64, 0xf9, 0x6d, 0x6c, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x77,
-0xee, 0x66, 0x254, 0x300, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x66, 0x289, 0x300,
-0x67, 0x68, 0xe0, 0x64, 0x7a, 0x75, 0x67, 0x68, 0xf9, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x67, 0x68,
-0x1d4, 0x75, 0x77, 0x65, 0x6c, 0x254, 0x300, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x63, 0x68, 0x77,
-0x61, 0x294, 0xe0, 0x6b, 0x61, 0x61, 0x20, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0xe8, 0x66, 0x77, 0xf2,
-0x6f, 0x6e, 0xf9, 0x6d, 0x3b, 0x6b, 0x268, 0x7a, 0x3b, 0x74, 0x268, 0x64, 0x3b, 0x74, 0x61, 0x61, 0x3b, 0x73, 0x65, 0x65,
-0x3b, 0x6e, 0x7a, 0x75, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x66, 0x254, 0x65, 0x3b, 0x64, 0x7a, 0x75, 0x3b, 0x6c, 0x254, 0x6d,
-0x3b, 0x6b, 0x61, 0x61, 0x3b, 0x66, 0x77, 0x6f, 0x6e, 0x3b, 0x6b, 0x3b, 0x74, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b,
-0x6b, 0x3b, 0x66, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x63, 0x3b, 0x66, 0x4b, 0x254, 0x6e, 0x64, 0x254, 0x14b, 0x3b, 0x4d, 0xe0,
-0x63, 0x25b, 0x302, 0x6c, 0x3b, 0x4d, 0xe0, 0x74, 0xf9, 0x6d, 0x62, 0x3b, 0x4d, 0xe0, 0x74, 0x6f, 0x70, 0x3b, 0x4d, 0x300,
-0x70, 0x75, 0x79, 0x25b, 0x3b, 0x48, 0xec, 0x6c, 0xf2, 0x6e, 0x64, 0x25b, 0x300, 0x3b, 0x4e, 0x6a, 0xe8, 0x62, 0xe0, 0x3b,
-0x48, 0xec, 0x6b, 0x61, 0x14b, 0x3b, 0x44, 0xec, 0x70, 0x254, 0x300, 0x73, 0x3b, 0x42, 0xec, 0xf2, 0xf4, 0x6d, 0x3b, 0x4d,
-0xe0, 0x79, 0x25b, 0x73, 0xe8, 0x70, 0x3b, 0x4c, 0xec, 0x62, 0x75, 0x79, 0x20, 0x6c, 0x69, 0x20, 0x144, 0x79, 0xe8, 0x65,
-0x6b, 0x254, 0x6e, 0x3b, 0x6d, 0x61, 0x63, 0x3b, 0x6d, 0x61, 0x74, 0x3b, 0x6d, 0x74, 0x6f, 0x3b, 0x6d, 0x70, 0x75, 0x3b,
-0x68, 0x69, 0x6c, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x68, 0x69, 0x6b, 0x3b, 0x64, 0x69, 0x70, 0x3b, 0x62, 0x69, 0x6f, 0x3b,
-0x6d, 0x61, 0x79, 0x3b, 0x6c, 0x69, 0x253, 0x6b, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x68, 0x3b, 0x6e,
-0x3b, 0x68, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x6c, 0x64, 0x69, 0x6d, 0x254, 0x301, 0x64, 0x69, 0x3b, 0x14b, 0x67,
-0x254, 0x6e, 0x64, 0x25b, 0x3b, 0x73, 0x254, 0x14b, 0x25b, 0x3b, 0x64, 0x69, 0x253, 0xe1, 0x253, 0xe1, 0x3b, 0x65, 0x6d, 0x69,
-0x61, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x65, 0x73, 0x254, 0x70, 0x25b, 0x73, 0x254, 0x70, 0x25b, 0x3b, 0x6d, 0x61, 0x64, 0x69,
-0x253, 0x25b, 0x301, 0x64, 0xed, 0x253, 0x25b, 0x301, 0x3b, 0x64, 0x69, 0x14b, 0x67, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6e, 0x79,
-0x25b, 0x74, 0x25b, 0x6b, 0x69, 0x3b, 0x6d, 0x61, 0x79, 0xe9, 0x73, 0x25b, 0x301, 0x3b, 0x74, 0x69, 0x6e, 0xed, 0x6e, 0xed,
-0x3b, 0x65, 0x6c, 0xe1, 0x14b, 0x67, 0x25b, 0x301, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x3b, 0x73, 0x254, 0x14b, 0x3b,
-0x64, 0x69, 0x253, 0x3b, 0x65, 0x6d, 0x69, 0x3b, 0x65, 0x73, 0x254, 0x3b, 0x6d, 0x61, 0x64, 0x3b, 0x64, 0x69, 0x14b, 0x3b,
-0x6e, 0x79, 0x25b, 0x74, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x74, 0x69, 0x6e, 0x3b, 0x65, 0x6c, 0xe1, 0x64, 0x3b, 0x14b, 0x3b,
-0x73, 0x3b, 0x64, 0x3b, 0x65, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x64, 0x3b, 0x6e, 0x3b, 0x6d, 0x3b, 0x74, 0x3b, 0x65, 0x53,
-0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x46, 0xe9, 0x62, 0x69, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x41,
-0x62, 0x75, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x65, 0x14b, 0x3b, 0x53, 0xfa, 0x75, 0x79, 0x65,
-0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
-0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x72,
-0x53, 0x61, 0x3b, 0x46, 0x65, 0x3b, 0x4d, 0x61, 0x3b, 0x41, 0x62, 0x3b, 0x4d, 0x65, 0x3b, 0x53, 0x75, 0x3b, 0x53, 0xfa,
-0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x3b, 0x4f, 0x6b, 0x3b, 0x4e, 0x6f, 0x3b, 0x44, 0x65, 0x53, 0x3b, 0x46, 0x3b, 0x4d,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x6e, 0x67,
-0x254, 0x6e, 0x20, 0x6f, 0x73, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6e, 0x67, 0x254, 0x6e,
-0x20, 0x6c, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6e, 0x79, 0x69, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254,
-0x6e, 0x20, 0x74, 0xe1, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x73, 0x61, 0x6d, 0x259, 0x6e, 0x61, 0x3b, 0x6e,
-0x67, 0x254, 0x6e, 0x20, 0x7a, 0x61, 0x6d, 0x67, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6d, 0x77,
-0x6f, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x65, 0x62, 0x75, 0x6c, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61,
-0x77, 0xf3, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x64, 0x7a, 0x69,
-0xe1, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x62, 0x25b, 0x30c, 0x6e, 0x67,
-0x6f, 0x3b, 0x6e, 0x67, 0x62, 0x3b, 0x6e, 0x67, 0x6c, 0x3b, 0x6e, 0x67, 0x6e, 0x3b, 0x6e, 0x67, 0x74, 0x3b, 0x6e, 0x67,
-0x73, 0x3b, 0x6e, 0x67, 0x7a, 0x3b, 0x6e, 0x67, 0x6d, 0x3b, 0x6e, 0x67, 0x65, 0x3b, 0x6e, 0x67, 0x61, 0x3b, 0x6e, 0x67,
-0x61, 0x64, 0x3b, 0x6e, 0x67, 0x61, 0x62, 0x6f, 0x3b, 0x62, 0x3b, 0x6c, 0x3b, 0x6e, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a,
-0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x62, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x20, 0x6e, 0x74, 0x254,
-0x301, 0x6e, 0x74, 0x254, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x14b,
-0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x72, 0xe1, 0xe1, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd,
-0x20, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x3b, 0x14b,
-0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x66, 0x254, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20,
-0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x62, 0x25b, 0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20,
-0x74, 0xe1, 0x61, 0x72, 0x61, 0x61, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e,
-0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x3b, 0x14b, 0x77, 0xed,
-0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x254, 0x301, 0x6b, 0x3b, 0x14b,
-0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x25b, 0x301, 0x25b,
-0x14b, 0x31, 0x3b, 0x14b, 0x32, 0x3b, 0x14b, 0x33, 0x3b, 0x14b, 0x34, 0x3b, 0x14b, 0x35, 0x3b, 0x14b, 0x36, 0x3b, 0x14b, 0x37,
-0x3b, 0x14b, 0x38, 0x3b, 0x14b, 0x39, 0x3b, 0x14b, 0x31, 0x30, 0x3b, 0x14b, 0x31, 0x31, 0x3b, 0x14b, 0x31, 0x32, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x6f, 0x20, 0x75, 0x6e, 0x61, 0x79, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20,
-0x75, 0x6e, 0x65, 0x72, 0x61, 0x72, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65,
-0x63, 0x68, 0x65, 0x73, 0x68, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x74,
-0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x20,
-0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x63, 0x68, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x73, 0x61,
-0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65,
-0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20,
-0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e,
-0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69,
-0x20, 0x6e, 0x61, 0x20, 0x79, 0x65, 0x6c, 0x2019, 0x6c, 0x69, 0x4b, 0x77, 0x61, 0x3b, 0x55, 0x6e, 0x61, 0x3b, 0x52, 0x61,
-0x72, 0x3b, 0x43, 0x68, 0x65, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x63, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61,
-0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4d, 0x6f, 0x6a, 0x3b, 0x59, 0x65, 0x6c, 0x4b, 0x3b, 0x55,
-0x3b, 0x52, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x59,
-0x46, 0x129, 0x69, 0x20, 0x4c, 0x6f, 0x6f, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x61, 0x14b, 0x6e, 0x65,
-0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x61, 0x72, 0x66,
-0x6f, 0x6f, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x1dd, 0x75, 0x75, 0x74, 0x1dd, 0x62, 0x69, 0x6a, 0x61, 0x14b, 0x3b, 0x4d, 0x61,
-0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x66, 0x61, 0x68, 0x62, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b, 0x67,
-0x77, 0xe3, 0x61, 0x6c, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x6d, 0x62, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20,
-0x44, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x75, 0x6e, 0x64, 0x61, 0x14b, 0x3b, 0x46, 0x129,
-0x69, 0x20, 0x47, 0x77, 0x61, 0x68, 0x6c, 0x6c, 0x65, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x59, 0x75, 0x72, 0x75, 0x46, 0x4c,
-0x4f, 0x3b, 0x43, 0x4c, 0x41, 0x3b, 0x43, 0x4b, 0x49, 0x3b, 0x46, 0x4d, 0x46, 0x3b, 0x4d, 0x41, 0x44, 0x3b, 0x4d, 0x42,
-0x49, 0x3b, 0x4d, 0x4c, 0x49, 0x3b, 0x4d, 0x41, 0x4d, 0x3b, 0x46, 0x44, 0x45, 0x3b, 0x46, 0x4d, 0x55, 0x3b, 0x46, 0x47,
-0x57, 0x3b, 0x46, 0x59, 0x55, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4d,
-0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x57, 0x3b, 0x59, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0xe1, 0x68, 0x72,
-0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6d, 0x62, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144,
-0x6c, 0x61, 0x6c, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20,
-0x144, 0x74, 0x61, 0x6e, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x75, 0xf3, 0x3b, 0x6e, 0x67, 0x77, 0x25b,
-0x6e, 0x20, 0x68, 0x25b, 0x6d, 0x62, 0x75, 0x25b, 0x72, 0xed, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6c, 0x254, 0x6d,
-0x62, 0x69, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x72, 0x25b, 0x62, 0x76, 0x75, 0xe2, 0x3b, 0x6e, 0x67, 0x77, 0x25b,
-0x6e, 0x20, 0x77, 0x75, 0x6d, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x20, 0x6e, 0x61, 0x76, 0x1d4,
-0x72, 0x3b, 0x6b, 0x72, 0xed, 0x73, 0x69, 0x6d, 0x69, 0x6e, 0x6e, 0x67, 0x31, 0x3b, 0x6e, 0x67, 0x32, 0x3b, 0x6e, 0x67,
-0x33, 0x3b, 0x6e, 0x67, 0x34, 0x3b, 0x6e, 0x67, 0x35, 0x3b, 0x6e, 0x67, 0x36, 0x3b, 0x6e, 0x67, 0x37, 0x3b, 0x6e, 0x67,
-0x38, 0x3b, 0x6e, 0x67, 0x39, 0x3b, 0x6e, 0x67, 0x31, 0x30, 0x3b, 0x6e, 0x67, 0x31, 0x31, 0x3b, 0x6b, 0x72, 0x69, 0x73,
-0x54, 0x69, 0x6f, 0x70, 0x20, 0x74, 0x68, 0x61, 0x72, 0x20, 0x70, 0x25b, 0x74, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75,
-0x254, 0x331, 0x254, 0x331, 0x14b, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x74, 0x3b, 0x4b, 0x6f, 0x72, 0x6e,
-0x79, 0x6f, 0x6f, 0x74, 0x3b, 0x50, 0x61, 0x79, 0x20, 0x79, 0x69, 0x65, 0x331, 0x74, 0x6e, 0x69, 0x3b, 0x54, 0x68, 0x6f,
-0x331, 0x6f, 0x331, 0x72, 0x3b, 0x54, 0x25b, 0x25b, 0x72, 0x3b, 0x4c, 0x61, 0x61, 0x74, 0x68, 0x3b, 0x4b, 0x75, 0x72, 0x3b,
-0x54, 0x69, 0x6f, 0x331, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x69, 0x331, 0x69, 0x331, 0x74, 0x54, 0x69, 0x6f, 0x70, 0x3b,
-0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x3b,
-0x4b, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x6f, 0x6f, 0x3b, 0x54, 0x25b, 0x25b, 0x3b, 0x4c, 0x61, 0x61,
-0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x64, 0x54, 0x3b, 0x50, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x4b, 0x3b,
-0x50, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x54, 0x442, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443,
-0x3b, 0x43e, 0x43b, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x43a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440,
-0x3b, 0x43c, 0x443, 0x443, 0x441, 0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x44b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x430, 0x3b,
-0x431, 0x44d, 0x441, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x43e, 0x442, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x430, 0x442, 0x44b, 0x440, 0x434,
-0x44c, 0x44b, 0x445, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x431, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x430, 0x3b,
-0x430, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x441, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445,
-0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x422, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41e, 0x43b, 0x443, 0x43d,
-0x43d, 0x44c, 0x443, 0x3b, 0x41a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440, 0x3b, 0x41c, 0x443, 0x443, 0x441,
-0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x42b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x44d, 0x441, 0x20,
-0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x41e, 0x442, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x410, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b,
-0x445, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b,
-0x410, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x421, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445,
-0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x422, 0x43e, 0x445, 0x441, 0x3b, 0x41e, 0x43b, 0x443, 0x43d, 0x3b, 0x41a, 0x43b, 0x43d, 0x3b,
-0x41c, 0x441, 0x443, 0x3b, 0x42b, 0x430, 0x43c, 0x3b, 0x411, 0x44d, 0x441, 0x3b, 0x41e, 0x442, 0x439, 0x3b, 0x410, 0x442, 0x440, 0x3b,
-0x411, 0x43b, 0x495, 0x3b, 0x410, 0x43b, 0x442, 0x3b, 0x421, 0x44d, 0x442, 0x3b, 0x410, 0x445, 0x441, 0x422, 0x3b, 0x41e, 0x3b, 0x41a,
-0x3b, 0x41c, 0x3b, 0x42b, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x410, 0x3b, 0x411, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x410, 0x4d, 0x75,
-0x70, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x77, 0x61, 0x3b, 0x4d, 0x77, 0x69, 0x74, 0x6f, 0x70, 0x65, 0x3b, 0x4d,
-0x75, 0x73, 0x68, 0x65, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e,
-0x64, 0x65, 0x20, 0x4d, 0x61, 0x67, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x75, 0x6a, 0x69, 0x6d, 0x62, 0x69, 0x3b, 0x4d, 0x75,
-0x73, 0x68, 0x69, 0x70, 0x65, 0x70, 0x6f, 0x3b, 0x4d, 0x75, 0x70, 0x75, 0x67, 0x75, 0x74, 0x6f, 0x3b, 0x4d, 0x75, 0x6e,
-0x79, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x68, 0x75, 0x3b, 0x4d, 0x75, 0x73, 0x6f, 0x6e, 0x67, 0x61, 0x6e,
-0x64, 0x65, 0x6d, 0x62, 0x77, 0x65, 0x3b, 0x4d, 0x75, 0x68, 0x61, 0x61, 0x6e, 0x6f, 0x4d, 0x75, 0x70, 0x3b, 0x4d, 0x77,
-0x69, 0x3b, 0x4d, 0x73, 0x68, 0x3b, 0x4d, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x67, 0x3b, 0x4d, 0x75, 0x6a, 0x3b, 0x4d, 0x73,
-0x70, 0x3b, 0x4d, 0x70, 0x67, 0x3b, 0x4d, 0x79, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x4d, 0x75, 0x73, 0x3b, 0x4d, 0x75,
-0x68, 0xa5a8, 0xa595, 0x20, 0xa56a, 0xa574, 0x20, 0xa51e, 0xa500, 0xa56e, 0xa54a, 0x3b, 0xa552, 0xa561, 0xa59d, 0xa595, 0x3b, 0xa57e, 0xa5ba, 0x3b,
-0xa5a2, 0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0xa5b1, 0xa60b, 0x3b, 0xa5b1, 0xa55e, 0xa524, 0x3b, 0xa5db, 0xa515, 0x3b, 0xa562, 0xa54c, 0x3b, 0xa56d,
-0xa583, 0x3b, 0xa51e, 0xa60b, 0xa554, 0xa57f, 0x20, 0xa578, 0xa583, 0xa5cf, 0x3b, 0xa5a8, 0xa595, 0x20, 0xa56a, 0xa574, 0x20, 0xa5cf, 0xa5ba, 0xa56e,
-0xa54a, 0xa5a8, 0xa595, 0xa51e, 0x3b, 0xa552, 0xa561, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0xa5b1, 0xa60b, 0x3b,
-0xa5b1, 0xa55e, 0x3b, 0xa5db, 0xa515, 0x3b, 0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0x3b, 0xa5a8, 0xa595, 0xa5cf, 0x6c, 0x75,
-0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6b, 0x65, 0x6d, 0xe3, 0x3b, 0x253, 0x61, 0x6e, 0x64, 0x61, 0x253, 0x75, 0x3b, 0x76, 0x254,
-0x254, 0x3b, 0x66, 0x75, 0x6c, 0x75, 0x3b, 0x67, 0x6f, 0x6f, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x6b, 0x254, 0x6e, 0x64, 0x65,
-0x3b, 0x73, 0x61, 0x61, 0x68, 0x3b, 0x67, 0x61, 0x6c, 0x6f, 0x3b, 0x6b, 0x65, 0x6e, 0x70, 0x6b, 0x61, 0x74, 0x6f, 0x20,
-0x253, 0x6f, 0x6c, 0x6f, 0x6c, 0x254, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6c, 0x254, 0x6d, 0x61, 0x4a, 0x65,
-0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x48, 0x6f, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x65, 0x3b, 0x41, 0x62,
-0x72, 0x69, 0x6c, 0x6c, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x6a, 0x65, 0x3b, 0x42, 0x72, 0xe1, 0x10d, 0x65, 0x74, 0x3b, 0x48,
-0x65, 0x69, 0x77, 0x65, 0x74, 0x3b, 0xd6, 0x69, 0x67, 0x161, 0x74, 0x65, 0x3b, 0x48, 0x65, 0x72, 0x62, 0x161, 0x74, 0x6d,
-0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0xed, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d,
-0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x43, 0x68, 0x72, 0x69, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x4a, 0x65, 0x6e, 0x3b,
-0x48, 0x6f, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x42, 0x72, 0xe1, 0x3b,
-0x48, 0x65, 0x69, 0x3b, 0xd6, 0x69, 0x67, 0x3b, 0x48, 0x65, 0x72, 0x3b, 0x57, 0xed, 0x6d, 0x3b, 0x57, 0x69, 0x6e, 0x3b,
-0x43, 0x68, 0x72, 0x4a, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x48, 0x3b, 0xd6, 0x3b, 0x48,
-0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x43, 0x70, 0x69, 0x6b, 0xed, 0x74, 0xed, 0x6b, 0xed, 0x74, 0x69, 0x65, 0x2c, 0x20, 0x6f,
-0xf3, 0x6c, 0xed, 0x20, 0xfa, 0x20, 0x6b, 0x75, 0x74, 0xfa, 0x61, 0x6e, 0x3b, 0x73, 0x69, 0x25b, 0x79, 0x25b, 0x301, 0x2c,
-0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x6e, 0x64, 0xed, 0x25b, 0x3b, 0x254, 0x6e, 0x73, 0xfa, 0x6d,
-0x62, 0x254, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x74, 0xfa, 0x25b, 0x3b,
-0x6d, 0x65, 0x73, 0x69, 0x14b, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe9, 0x6e, 0x69, 0x65, 0x3b,
-0x65, 0x6e, 0x73, 0x69, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x6e, 0x75,
-0x25b, 0x3b, 0x254, 0x73, 0x254, 0x6e, 0x3b, 0x65, 0x66, 0x75, 0x74, 0x65, 0x3b, 0x70, 0x69, 0x73, 0x75, 0x79, 0xfa, 0x3b,
-0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75, 0x254, 0x73, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70,
-0x75, 0x74, 0xfa, 0x6b, 0x2c, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xed, 0x25b, 0x3b, 0x6d, 0x61,
-0x6b, 0x61, 0x6e, 0x64, 0x69, 0x6b, 0x25b, 0x3b, 0x70, 0x69, 0x6c, 0x254, 0x6e, 0x64, 0x254, 0x301, 0x6f, 0x2e, 0x31, 0x3b,
-0x6f, 0x2e, 0x32, 0x3b, 0x6f, 0x2e, 0x33, 0x3b, 0x6f, 0x2e, 0x34, 0x3b, 0x6f, 0x2e, 0x35, 0x3b, 0x6f, 0x2e, 0x36, 0x3b,
-0x6f, 0x2e, 0x37, 0x3b, 0x6f, 0x2e, 0x38, 0x3b, 0x6f, 0x2e, 0x39, 0x3b, 0x6f, 0x2e, 0x31, 0x30, 0x3b, 0x6f, 0x2e, 0x31,
-0x31, 0x3b, 0x6f, 0x2e, 0x31, 0x32, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75,
-0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x78, 0x75,
-0x6e, 0x75, 0x3b, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x73, 0x65, 0x74,
-0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x70, 0x61, 0x79, 0x61, 0x72,
-0x65, 0x73, 0x3b, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x64, 0x65, 0x20, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b,
-0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b,
-0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78,
-0x75, 0x6e, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73,
-0x74, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63,
-0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x2019, 0x61,
-0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x58, 0x69, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62,
-0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x58, 0x75, 0x6e, 0x3b, 0x58, 0x6e, 0x74, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65,
-0x74, 0x3b, 0x4f, 0x63, 0x68, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x41, 0x76, 0x69, 0x78, 0x69, 0x6e, 0x3b, 0x66, 0x65, 0x62,
-0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x78, 0x75, 0x6e, 0x3b, 0x78, 0x6e, 0x74,
-0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x63, 0x68, 0x3b, 0x70, 0x61, 0x79, 0x3b, 0x61, 0x76, 0x69,
-0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
-0x50, 0x3b, 0x41, 0x4e, 0x64, 0x75, 0x14b, 0x6d, 0x62, 0x69, 0x20, 0x53, 0x61, 0x14b, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b,
-0x20, 0x50, 0x25b, 0x301, 0x70, 0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x74, 0xe1, 0x74, 0x3b,
-0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6b, 0x77, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61,
-0x14b, 0x20, 0x50, 0x61, 0x74, 0x61, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301,
-0x6e, 0x74, 0xfa, 0x6b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x53, 0x61, 0x61, 0x6d, 0x62, 0xe1, 0x3b, 0x50,
-0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x66, 0x254, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b,
-0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x70, 0x66, 0xfa, 0xa78b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e,
-0x25b, 0x67, 0x25b, 0x301, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x6d, 0x254,
-0x301, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x70, 0xe1, 0x70, 0x61, 0x6d, 0x62,
-0x61, 0x3b, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x6d, 0x62, 0x69, 0x79, 0x254, 0x20, 0x6d, 0x25b, 0x6e, 0x64, 0x6f, 0x14b,
-0x67, 0x254, 0x3b, 0x4e, 0x79, 0x254, 0x6c, 0x254, 0x6d, 0x62, 0x254, 0x14b, 0x67, 0x254, 0x3b, 0x4d, 0x254, 0x6e, 0x254, 0x20,
-0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x14b, 0x67, 0x77, 0x25b, 0x20, 0x14b, 0x67, 0x62, 0x61,
-0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x75, 0x14b, 0x67, 0x77, 0x25b, 0x3b, 0x66, 0x25b, 0x3b, 0x6e, 0x6a, 0x61, 0x70, 0x69, 0x3b,
-0x6e, 0x79, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x31, 0x31, 0x3b, 0x253, 0x75, 0x6c, 0x253, 0x75, 0x73, 0x25b, 0x69, 0x6d, 0x259,
-0x67, 0x20, 0x6d, 0x62, 0x65, 0x67, 0x74, 0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec,
-0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67,
-0x20, 0x6e, 0x67, 0x77, 0x259, 0x300, 0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259,
-0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x69, 0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d,
-0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259,
-0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d,
-0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x6d, 0x62,
-0x65, 0x67, 0x74, 0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65,
-0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77,
-0x259, 0x300, 0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63,
-0x68, 0x69, 0x69, 0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b,
-0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75,
-0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a,
-0xf2, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x4d, 0x31, 0x3b, 0x41, 0x32, 0x3b,
-0x4d, 0x33, 0x3b, 0x4e, 0x34, 0x3b, 0x46, 0x35, 0x3b, 0x49, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x49, 0x38, 0x3b, 0x4b, 0x39,
-0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300,
-0x25b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6b, 0xe0, 0x67, 0x20, 0x6e, 0x67, 0x77, 0xf3, 0x14b, 0x3b,
-0x73, 0x61, 0x14b, 0x20, 0x6c, 0x65, 0x70, 0x79, 0xe8, 0x20, 0x73, 0x68, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x63,
-0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b,
-0x20, 0x6e, 0x6a, 0xff, 0x6f, 0x6c, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x79, 0x25b, 0x300, 0x62, 0x20, 0x74,
-0x79, 0x25b, 0x300, 0x62, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b,
-0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e, 0x67, 0x77, 0x254, 0x300, 0x2bc, 0x20, 0x6d, 0x62, 0xff, 0x25b, 0x3b, 0x73, 0x61, 0x14b,
-0x20, 0x74, 0xe0, 0x14b, 0x61, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x65,
-0x6a, 0x77, 0x6f, 0x14b, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0xf9, 0x6d, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd2a, 0xd804,
-0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1c, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22,
-0xd804, 0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd0c, 0xd804, 0xdd27, 0x3b,
-0xd804, 0xdd03, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804,
-0xdd2c, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd23, 0xd804, 0xdd2d, 0x3b,
-0xd804, 0xdd03, 0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804,
-0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b,
-0xd804, 0xdd03, 0xd804, 0xdd27, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2e, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34,
-0x3b, 0xd804, 0xdd1a, 0xd804, 0xdd27, 0xd804, 0xdd1e, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804,
-0xdd34, 0x3b, 0xd804, 0xdd13, 0xd804, 0xdd28, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22,
-0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1c, 0xd804, 0xdd2c, 0xd804,
-0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1f,
-0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd0c, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804,
-0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b,
-0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd23, 0xd804, 0xdd2d, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804,
-0xdd11, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34,
-0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd27, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804,
-0xdd2c, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1a, 0xd804, 0xdd27, 0xd804, 0xdd1e, 0xd804, 0xdd2c, 0xd804, 0xdd1f,
-0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd13, 0xd804, 0xdd28, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804,
-0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd1c,
-0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd0c, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd03,
-0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd2c, 0x3b,
-0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd23, 0xd804, 0xdd2d, 0x3b, 0xd804, 0xdd03,
-0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804,
-0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd03,
-0xd804, 0xdd27, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2e, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804,
-0xdd1a, 0xd804, 0xdd27, 0xd804, 0xdd1e, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b,
-0xd804, 0xdd13, 0xd804, 0xdd28, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd0e,
-0x3b, 0xd804, 0xdd1c, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd1f, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd2c, 0x3b, 0xd804,
-0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd03, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2c,
-0x3b, 0xd804, 0xdd03, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd1a, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd13, 0xd804, 0xdd28, 0x57, 0x69, 0xf3, 0x74, 0x68,
-0x65, 0x21f, 0x69, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x68, 0x69, 0x79, 0xf3, 0x21f, 0x65, 0x79, 0x75, 0x14b, 0x6b,
-0x61, 0x20, 0x57, 0xed, 0x3b, 0x49, 0x161, 0x74, 0xe1, 0x77, 0x69, 0x10d, 0x68, 0x61, 0x79, 0x61, 0x7a, 0x61, 0x14b, 0x20,
-0x57, 0xed, 0x3b, 0x50, 0x21f, 0x65, 0x17e, 0xed, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77,
-0xe1, 0x70, 0x65, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x57, 0xed, 0x70, 0x61, 0x7a, 0x75, 0x6b, 0x21f, 0x61, 0x2d,
-0x77, 0x61, 0x161, 0x74, 0xe9, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x70, 0x21f, 0xe1, 0x73, 0x61, 0x70, 0x61,
-0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x73, 0xfa, 0x74, 0x21f, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b,
-0x77, 0xe1, 0x70, 0x65, 0x1e7, 0x69, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65, 0x2d, 0x6b,
-0x61, 0x73, 0x6e, 0xe1, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x6e, 0xed, 0x79, 0x65, 0x74, 0x75, 0x20, 0x57, 0xed, 0x3b,
-0x54, 0x21f, 0x61, 0x68, 0xe9, 0x6b, 0x61, 0x70, 0x161, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x6a9, 0x627, 0x646, 0x648, 0x648, 0x646,
-0x6cc, 0x20, 0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x634, 0x648, 0x628, 0x627, 0x62a, 0x3b, 0x626, 0x627, 0x632, 0x627, 0x631, 0x3b,
-0x646, 0x6cc, 0x633, 0x627, 0x646, 0x3b, 0x626, 0x627, 0x6cc, 0x627, 0x631, 0x3b, 0x62d, 0x648, 0x632, 0x6d5, 0x6cc, 0x631, 0x627, 0x646,
-0x3b, 0x62a, 0x6d5, 0x645, 0x648, 0x648, 0x632, 0x3b, 0x626, 0x627, 0x628, 0x3b, 0x626, 0x6d5, 0x6cc, 0x644, 0x648, 0x648, 0x644, 0x3b,
-0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20,
-0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x6a9, 0x3b,
-0x634, 0x3b, 0x626, 0x3b, 0x646, 0x3b, 0x626, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x626, 0x3b, 0x626, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b,
-0x6a9, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63,
-0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c,
-0x69, 0x6a, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72,
-0x61, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b,
-0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74,
-0x61, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b,
-0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x6a, 0x61, 0x6e,
-0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e,
-0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x77,
-0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72, 0x2e, 0x3b, 0x61,
-0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61,
-0x77, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77, 0x2e, 0x3b, 0x64,
-0x65, 0x63, 0x2e, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b,
-0x72, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x3b, 0x6d, 0x65, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b,
-0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72,
-0x75, 0x61, 0x72, 0x61, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x65,
-0x6a, 0x65, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67,
-0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62,
-0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61,
-0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x65, 0x6a, 0x3b,
-0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b,
-0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72,
-0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x6a, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c,
-0x2e, 0x3b, 0x61, 0x77, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77,
-0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x72, 0x61, 0x67, 0x73, 0x3b, 0x77, 0x61, 0x73, 0x73, 0x61, 0x72, 0x69, 0x6e, 0x73,
-0x3b, 0x70, 0x16b, 0x6c, 0x69, 0x73, 0x3b, 0x73, 0x61, 0x6b, 0x6b, 0x69, 0x73, 0x3b, 0x7a, 0x61, 0x6c, 0x6c, 0x61, 0x77,
-0x73, 0x3b, 0x73, 0x12b, 0x6d, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6c, 0x12b, 0x70, 0x61, 0x3b, 0x64, 0x61, 0x67, 0x67, 0x69,
-0x73, 0x3b, 0x73, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x73, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x73, 0x3b, 0x6c,
-0x61, 0x70, 0x6b, 0x72, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x73, 0x61, 0x6c, 0x6c, 0x61, 0x77, 0x73, 0x72, 0x61, 0x67, 0x3b,
-0x77, 0x61, 0x73, 0x3b, 0x70, 0x16b, 0x6c, 0x3b, 0x73, 0x61, 0x6b, 0x3b, 0x7a, 0x61, 0x6c, 0x3b, 0x73, 0x12b, 0x6d, 0x3b,
-0x6c, 0x12b, 0x70, 0x3b, 0x64, 0x61, 0x67, 0x3b, 0x73, 0x69, 0x6c, 0x3b, 0x73, 0x70, 0x61, 0x3b, 0x6c, 0x61, 0x70, 0x3b,
-0x73, 0x61, 0x6c, 0x52, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x5a, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x44, 0x3b, 0x53,
-0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x53, 0x75, 0x111, 0x111, 0xe2, 0x69, 0x76, 0x65, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b,
-0x75, 0x6f, 0x76, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e,
-0x75, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x6d,
-0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e,
-0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x70, 0x6f, 0x72, 0x67, 0x65, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x10d, 0x6f,
-0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x72, 0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x6d, 0xe1, 0xe1, 0x6e,
-0x75, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2,
-0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x75, 0x111, 0x69, 0x76, 0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x3b, 0x6e, 0x6a, 0x75, 0x68,
-0x10d, 0xe2, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69, 0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x69,
-0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x3b, 0x70, 0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x3b,
-0x72, 0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c,
-0xe2, 0x55, 0x3b, 0x4b, 0x3b, 0x4e, 0x4a, 0x3b, 0x43, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x10c, 0x3b,
-0x52, 0x3b, 0x53, 0x3b, 0x4a, 0x62c, 0x627, 0x646, 0x6a4, 0x6cc, 0x6d5, 0x3b, 0x641, 0x626, 0x6a4, 0x631, 0x6cc, 0x6d5, 0x3b, 0x645,
-0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659, 0x623, 0x646, 0x3b,
-0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b, 0x622, 0x6af, 0x648, 0x633, 0x62a, 0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627, 0x645, 0x631, 0x3b,
-0x626, 0x648, 0x6a9, 0x62a, 0x648, 0x6a4, 0x631, 0x3b, 0x646, 0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b, 0x62f, 0x626, 0x633, 0x627, 0x645,
-0x631, 0x45, 0x6e, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b,
-0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
-0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x48, 0x3b,
-0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44
+static constexpr char16_t months_data[] = {
+0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72,
+0x75, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x68, 0x3b, 0x41,
+0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e,
+0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73,
+0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x4f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72,
+0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e,
+0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70,
+0x3b, 0x4f, 0x63, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63,
+0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b,
+0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x31,
+0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37,
+0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31,
+0x32, 0x410, 0x436, 0x44c, 0x44b, 0x440, 0x43d, 0x44b, 0x4b3, 0x259, 0x430, 0x3b,
+0x416, 0x259, 0x430, 0x431, 0x440, 0x430, 0x43d, 0x3b, 0x425, 0x259, 0x430, 0x436,
+0x259, 0x43a, 0x44b, 0x440, 0x430, 0x3b, 0x41c, 0x448, 0x430, 0x525, 0x44b, 0x3b,
+0x41b, 0x430, 0x4b5, 0x430, 0x440, 0x430, 0x3b, 0x420, 0x430, 0x448, 0x259, 0x430,
+0x440, 0x430, 0x3b, 0x524, 0x445, 0x44b, 0x43d, 0x433, 0x259, 0x44b, 0x3b, 0x41d,
+0x430, 0x43d, 0x4b3, 0x259, 0x430, 0x3b, 0x426, 0x259, 0x44b, 0x431, 0x431, 0x440,
+0x430, 0x3b, 0x416, 0x44c, 0x4ad, 0x430, 0x430, 0x440, 0x430, 0x3b, 0x410, 0x431,
+0x4b5, 0x430, 0x440, 0x430, 0x3b, 0x524, 0x445, 0x44b, 0x43d, 0x4b7, 0x43a, 0x4d9,
+0x44b, 0x43d, 0x410, 0x436, 0x44c, 0x3b, 0x416, 0x259, 0x430, 0x431, 0x3b, 0x425,
+0x259, 0x430, 0x436, 0x4d9, 0x3b, 0x41c, 0x448, 0x3b, 0x41b, 0x430, 0x4b5, 0x3b,
+0x420, 0x430, 0x448, 0x4d9, 0x3b, 0x524, 0x445, 0x44b, 0x43d, 0x433, 0x4d9, 0x3b,
+0x41d, 0x430, 0x43d, 0x4b3, 0x4d9, 0x3b, 0x426, 0x259, 0x44b, 0x431, 0x3b, 0x416,
+0x44c, 0x4ad, 0x3b, 0x410, 0x431, 0x4b5, 0x3b, 0x524, 0x445, 0x44b, 0x43d, 0x4b7,
+0x416, 0x44c, 0x3b, 0x416, 0x259, 0x3b, 0x425, 0x259, 0x3b, 0x41c, 0x3b, 0x41b,
+0x3b, 0x420, 0x3b, 0x413, 0x4d9, 0x3b, 0x41d, 0x3b, 0x426, 0x4d9, 0x3b, 0x4ac,
+0x3b, 0x411, 0x3b, 0x4b6, 0x416, 0x44c, 0x3b, 0x416, 0x259, 0x3b, 0x425, 0x259,
+0x3b, 0x41c, 0x3b, 0x41b, 0x3b, 0x420, 0x3b, 0x413, 0x4d9, 0x3b, 0x41d, 0x3b,
+0x426, 0x259, 0x3b, 0x4ac, 0x3b, 0x411, 0x3b, 0x4b6, 0x51, 0x75, 0x6e, 0x78,
+0x61, 0x20, 0x47, 0x61, 0x72, 0x61, 0x62, 0x6c, 0x75, 0x3b, 0x4b, 0x75,
+0x64, 0x6f, 0x3b, 0x43, 0x69, 0x67, 0x67, 0x69, 0x6c, 0x74, 0x61, 0x20,
+0x4b, 0x75, 0x64, 0x6f, 0x3b, 0x41, 0x67, 0x64, 0x61, 0x20, 0x42, 0x61,
+0x78, 0x69, 0x73, 0x3b, 0x43, 0x61, 0x78, 0x61, 0x68, 0x20, 0x41, 0x6c,
+0x73, 0x61, 0x3b, 0x51, 0x61, 0x73, 0x61, 0x20, 0x44, 0x69, 0x72, 0x72,
+0x69, 0x3b, 0x51, 0x61, 0x64, 0x6f, 0x20, 0x44, 0x69, 0x72, 0x72, 0x69,
+0x3b, 0x4c, 0x69, 0x69, 0x71, 0x65, 0x6e, 0x3b, 0x57, 0x61, 0x79, 0x73,
+0x75, 0x3b, 0x44, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x3b, 0x58, 0x69, 0x6d,
+0x6f, 0x6c, 0x69, 0x3b, 0x4b, 0x61, 0x78, 0x78, 0x61, 0x20, 0x47, 0x61,
+0x72, 0x61, 0x62, 0x6c, 0x75, 0x51, 0x75, 0x6e, 0x3b, 0x4e, 0x61, 0x68,
+0x3b, 0x43, 0x69, 0x67, 0x3b, 0x41, 0x67, 0x64, 0x3b, 0x43, 0x61, 0x78,
+0x3b, 0x51, 0x61, 0x73, 0x3b, 0x51, 0x61, 0x64, 0x3b, 0x4c, 0x65, 0x71,
+0x3b, 0x57, 0x61, 0x79, 0x3b, 0x44, 0x69, 0x74, 0x3b, 0x58, 0x69, 0x6d,
+0x3b, 0x4b, 0x61, 0x78, 0x51, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x41, 0x3b,
+0x43, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x4c, 0x3b, 0x57, 0x3b, 0x44, 0x3b,
+0x58, 0x3b, 0x4b, 0x51, 0x75, 0x6e, 0x78, 0x61, 0x20, 0x47, 0x61, 0x72,
+0x61, 0x62, 0x6c, 0x75, 0x3b, 0x4b, 0x75, 0x64, 0x6f, 0x3b, 0x43, 0x69,
+0x67, 0x67, 0x69, 0x6c, 0x74, 0x61, 0x20, 0x4b, 0x75, 0x64, 0x6f, 0x3b,
+0x41, 0x67, 0x64, 0x61, 0x20, 0x42, 0x61, 0x78, 0x69, 0x73, 0x3b, 0x43,
+0x61, 0x78, 0x61, 0x68, 0x20, 0x41, 0x6c, 0x73, 0x61, 0x3b, 0x51, 0x61,
+0x73, 0x61, 0x20, 0x44, 0x69, 0x72, 0x72, 0x69, 0x3b, 0x51, 0x61, 0x64,
+0x6f, 0x20, 0x44, 0x69, 0x72, 0x72, 0x69, 0x3b, 0x4c, 0x65, 0x71, 0x65,
+0x65, 0x6e, 0x69, 0x3b, 0x57, 0x61, 0x79, 0x73, 0x75, 0x3b, 0x44, 0x69,
+0x74, 0x65, 0x6c, 0x69, 0x3b, 0x58, 0x69, 0x6d, 0x6f, 0x6c, 0x69, 0x3b,
+0x4b, 0x61, 0x78, 0x78, 0x61, 0x20, 0x47, 0x61, 0x72, 0x61, 0x62, 0x6c,
+0x75, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x61, 0x72,
+0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x65, 0x3b,
+0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70,
+0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x2e,
+0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x72, 0x74, 0x2e, 0x3b, 0x41,
+0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e,
+0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53,
+0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76,
+0x2e, 0x3b, 0x44, 0x65, 0x73, 0x2e, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b,
+0x254, 0x300, 0x6e, 0xf9, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b,
+0x254, 0x300, 0x6b, 0x197, 0x300, 0x7a, 0xf9, 0x294, 0x3b, 0x6e, 0x64, 0x7a,
+0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x64, 0x289, 0x300, 0x67,
+0x68, 0xe0, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74,
+0x1ce, 0x61, 0x66, 0x289, 0x304, 0x67, 0x68, 0x101, 0x3b, 0x6e, 0x64, 0x7a,
+0x254, 0x300, 0x14b, 0xe8, 0x73, 0xe8, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254,
+0x300, 0x14b, 0x254, 0x300, 0x6e, 0x7a, 0xf9, 0x67, 0x68, 0xf2, 0x3b, 0x6e,
+0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x64, 0xf9, 0x6d, 0x6c, 0x6f,
+0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x77, 0xee,
+0x66, 0x254, 0x300, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254,
+0x300, 0x74, 0x197, 0x300, 0x66, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x64, 0x7a,
+0x75, 0x67, 0x68, 0xf9, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254,
+0x300, 0x67, 0x68, 0x1d4, 0x75, 0x77, 0x65, 0x6c, 0x254, 0x300, 0x6d, 0x3b,
+0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x63, 0x68, 0x77, 0x61,
+0x294, 0xe0, 0x6b, 0x61, 0x61, 0x20, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a,
+0x254, 0x300, 0x14b, 0xe8, 0x66, 0x77, 0xf2, 0x6f, 0x6e, 0xf9, 0x6d, 0x3b,
+0x6b, 0x268, 0x7a, 0x3b, 0x74, 0x268, 0x64, 0x3b, 0x74, 0x61, 0x61, 0x3b,
+0x73, 0x65, 0x65, 0x3b, 0x6e, 0x7a, 0x75, 0x3b, 0x64, 0x75, 0x6d, 0x3b,
+0x66, 0x254, 0x65, 0x3b, 0x64, 0x7a, 0x75, 0x3b, 0x6c, 0x254, 0x6d, 0x3b,
+0x6b, 0x61, 0x61, 0x3b, 0x66, 0x77, 0x6f, 0x6e, 0x3b, 0x6b, 0x3b, 0x74,
+0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x64,
+0x3b, 0x6c, 0x3b, 0x63, 0x3b, 0x66, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d,
+0x186, 0x70, 0x25b, 0x70, 0x254, 0x6e, 0x3b, 0x4b, 0x77, 0x61, 0x6b, 0x77,
+0x61, 0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75, 0x6f, 0x3b, 0x45,
+0x62, 0x254, 0x77, 0x2d, 0x186, 0x62, 0x65, 0x6e, 0x65, 0x6d, 0x3b, 0x45,
+0x62, 0x254, 0x62, 0x69, 0x72, 0x61, 0x2d, 0x4f, 0x66, 0x6f, 0x72, 0x69,
+0x73, 0x75, 0x6f, 0x3b, 0x45, 0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41,
+0x6b, 0x65, 0x74, 0x73, 0x65, 0x61, 0x62, 0x61, 0x2d, 0x4b, 0x254, 0x74,
+0x254, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62, 0x69, 0x72, 0x61,
+0x64, 0x65, 0x2d, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x6d, 0x75,
+0x6d, 0x75, 0x3b, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x2d, 0x4b,
+0x69, 0x74, 0x61, 0x77, 0x6f, 0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66,
+0x75, 0x75, 0x2d, 0x186, 0x73, 0x61, 0x6e, 0x64, 0x61, 0x61, 0x3b, 0x46,
+0x61, 0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254, 0x3b, 0x186, 0x62,
+0x25b, 0x73, 0x25b, 0x2d, 0x41, 0x68, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x3b,
+0x186, 0x62, 0x65, 0x72, 0x25b, 0x66, 0x25b, 0x77, 0x2d, 0x4f, 0x62, 0x75,
+0x62, 0x75, 0x6f, 0x3b, 0x4d, 0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b,
+0x6e, 0x69, 0x6d, 0x62, 0x61, 0x53, 0x2d, 0x186, 0x3b, 0x4b, 0x2d, 0x186,
+0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f, 0x3b, 0x45, 0x2d, 0x4b,
+0x3b, 0x4f, 0x2d, 0x41, 0x3b, 0x41, 0x2d, 0x4b, 0x3b, 0x44, 0x2d, 0x186,
+0x3b, 0x46, 0x2d, 0x190, 0x3b, 0x186, 0x2d, 0x41, 0x3b, 0x186, 0x2d, 0x4f,
+0x3b, 0x4d, 0x2d, 0x186, 0x4d, 0x30, 0x31, 0x3b, 0x4d, 0x30, 0x32, 0x3b,
+0x4d, 0x30, 0x33, 0x3b, 0x4d, 0x30, 0x34, 0x3b, 0x4d, 0x30, 0x35, 0x3b,
+0x4d, 0x30, 0x36, 0x3b, 0x4d, 0x30, 0x37, 0x3b, 0x4d, 0x30, 0x38, 0x3b,
+0x4d, 0x30, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b,
+0x4d, 0x31, 0x32, 0x6a, 0x61, 0x6e, 0x61, 0x72, 0x3b, 0x73, 0x68, 0x6b,
+0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x70, 0x72, 0x69,
+0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x73, 0x68,
+0x6f, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x67, 0x75,
+0x73, 0x68, 0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b,
+0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x6e, 0xeb, 0x6e, 0x74, 0x6f, 0x72,
+0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x6a, 0x61, 0x6e, 0x3b,
+0x73, 0x68, 0x6b, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x72, 0x69, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72,
+0x3b, 0x67, 0x75, 0x73, 0x68, 0x3b, 0x73, 0x68, 0x74, 0x3b, 0x74, 0x65,
+0x74, 0x3b, 0x6e, 0xeb, 0x6e, 0x3b, 0x64, 0x68, 0x6a, 0x6a, 0x3b, 0x73,
+0x68, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x6d, 0x3b, 0x71, 0x3b, 0x6b, 0x3b,
+0x67, 0x3b, 0x73, 0x68, 0x3b, 0x74, 0x3b, 0x6e, 0x3b, 0x64, 0x68, 0x1303,
+0x1295, 0x12cb, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12cb, 0x122a, 0x3b, 0x121b, 0x122d,
+0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x120d, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295,
+0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355,
+0x1274, 0x121d, 0x1260, 0x122d, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x1260, 0x122d, 0x3b, 0x1296,
+0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x1303, 0x1295,
+0x3b, 0x134c, 0x1265, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x3b,
+0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308,
+0x1235, 0x3b, 0x1234, 0x1355, 0x1274, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x3b, 0x1296, 0x126c,
+0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b, 0x12a4,
+0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6,
+0x3b, 0x1296, 0x3b, 0x12f2, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628,
+0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628,
+0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646,
+0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x633,
+0x637, 0x633, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643,
+0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b,
+0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b,
+0x623, 0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b,
+0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x62c, 0x627, 0x646, 0x641, 0x64a, 0x3b, 0x641,
+0x64a, 0x641, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x641,
+0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x62c, 0x648, 0x627, 0x646,
+0x3b, 0x62c, 0x648, 0x64a, 0x644, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x62a, 0x3b,
+0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628,
+0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633,
+0x645, 0x628, 0x631, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645,
+0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x623, 0x3b, 0x633, 0x3b, 0x623, 0x3b, 0x646,
+0x3b, 0x62f, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627,
+0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631,
+0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b,
+0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b,
+0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631,
+0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631,
+0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627,
+0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x643, 0x627, 0x646,
+0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628,
+0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627,
+0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627,
+0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a,
+0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0xa0, 0x627, 0x644,
+0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644,
+0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627,
+0x644, 0x623, 0x648, 0x644, 0x643, 0x3b, 0x634, 0x3b, 0x622, 0x3b, 0x646, 0x3b,
+0x623, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x622, 0x3b, 0x623, 0x3b, 0x62a, 0x3b,
+0x62a, 0x3b, 0x643, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631,
+0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x625, 0x628, 0x631,
+0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a,
+0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x634, 0x62a,
+0x3b, 0x634, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628,
+0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x645,
+0x628, 0x631, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x625, 0x3b, 0x648, 0x3b,
+0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b,
+0x62f, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a,
+0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644,
+0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a,
+0x648, 0x644, 0x64a, 0x648, 0x632, 0x3b, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a,
+0x646, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646,
+0x648, 0x646, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x646, 0x628, 0x631, 0x64a, 0x3b,
+0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x646, 0x3b, 0x644, 0x3b,
+0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x63, 0x68, 0x69,
+0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f,
+0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x63, 0x68, 0x75, 0x6e, 0x79, 0x6f,
+0x3b, 0x63, 0x68, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67, 0x6f,
+0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f,
+0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x61, 0x76, 0x69, 0x65,
+0x6e, 0x74, 0x6f, 0x64, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72,
+0x6f, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f,
+0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x64, 0x2019,
+0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x79,
+0x6f, 0x3b, 0x64, 0x65, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x79, 0x6f, 0x3b,
+0x64, 0x65, 0x20, 0x63, 0x68, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x64,
+0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x64, 0x65, 0x20, 0x73,
+0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f,
+0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f,
+0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x61, 0x76,
+0x69, 0x65, 0x6e, 0x74, 0x6f, 0x63, 0x68, 0x69, 0x2e, 0x3b, 0x66, 0x65,
+0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e,
+0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x63, 0x68, 0x6e, 0x2e, 0x3b, 0x63,
+0x68, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74,
+0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b,
+0x61, 0x76, 0x69, 0x2e, 0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x3b,
+0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x574, 0x561, 0x580, 0x57f,
+0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d,
+0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x56c,
+0x56b, 0x57d, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x57d,
+0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x570, 0x578, 0x56f,
+0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574,
+0x562, 0x565, 0x580, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565,
+0x580, 0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x583, 0x565,
+0x57f, 0x580, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x56b,
+0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x56b, 0x3b, 0x574, 0x561, 0x575, 0x56b,
+0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x56b, 0x3b, 0x570,
+0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x56b, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f,
+0x578, 0x57d, 0x56b, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565,
+0x580, 0x56b, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580,
+0x56b, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b,
+0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x570, 0x576,
+0x57e, 0x3b, 0x583, 0x57f, 0x57e, 0x3b, 0x574, 0x580, 0x57f, 0x3b, 0x561, 0x57a,
+0x580, 0x3b, 0x574, 0x575, 0x57d, 0x3b, 0x570, 0x576, 0x57d, 0x3b, 0x570, 0x56c,
+0x57d, 0x3b, 0x585, 0x563, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x3b, 0x570, 0x578,
+0x56f, 0x3b, 0x576, 0x578, 0x575, 0x3b, 0x564, 0x565, 0x56f, 0x540, 0x3b, 0x553,
+0x3b, 0x544, 0x3b, 0x531, 0x3b, 0x544, 0x3b, 0x540, 0x3b, 0x540, 0x3b, 0x555,
+0x3b, 0x54d, 0x3b, 0x540, 0x3b, 0x546, 0x3b, 0x534, 0x99c, 0x9be, 0x9a8, 0x9c1,
+0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x9f1,
+0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa,
+0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x2019, 0x3b, 0x99c, 0x9c1, 0x9a8,
+0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f,
+0x3b, 0x99b, 0x9c7, 0x9aa, 0x9cd, 0x9a4, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b,
+0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x9ae,
+0x9cd, 0x9ac, 0x9f0, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0,
+0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b,
+0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2,
+0x3b, 0x9ae, 0x9c7, 0x2019, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2,
+0x9be, 0x987, 0x3b, 0x986, 0x997, 0x3b, 0x99b, 0x9c7, 0x9aa, 0x9cd, 0x9a4, 0x9c7,
+0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x3b, 0x9a1,
+0x9bf, 0x99a, 0x9c7, 0x99c, 0x3b, 0x9ab, 0x3b, 0x9ae, 0x3b, 0x98f, 0x3b, 0x9ae,
+0x3b, 0x99c, 0x3b, 0x99c, 0x3b, 0x986, 0x3b, 0x99b, 0x3b, 0x985, 0x3b, 0x9a8,
+0x3b, 0x9a1, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x66, 0x65, 0x62,
+0x72, 0x65, 0x72, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x61,
+0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x78, 0x75,
+0x6e, 0x75, 0x3b, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x61, 0x67,
+0x6f, 0x73, 0x74, 0x75, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x70,
+0x61, 0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x61, 0x76, 0x69, 0x65, 0x6e,
+0x74, 0x75, 0x64, 0x65, 0x20, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b,
+0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x64,
+0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x62,
+0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x75, 0x3b,
+0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78,
+0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73,
+0x74, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72,
+0x65, 0x3b, 0x64, 0x65, 0x20, 0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73,
+0x3b, 0x64, 0x2019, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x58, 0x69,
+0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62,
+0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x58, 0x75, 0x6e, 0x3b, 0x58, 0x6e,
+0x74, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63,
+0x68, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x41, 0x76, 0x69, 0x78, 0x69, 0x6e,
+0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72,
+0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x78, 0x75, 0x6e, 0x3b, 0x78, 0x6e, 0x74,
+0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x63, 0x68,
+0x3b, 0x70, 0x61, 0x79, 0x3b, 0x61, 0x76, 0x69, 0x58, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x50, 0x3b, 0x41, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b,
+0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x69,
+0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75,
+0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53,
+0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44,
+0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67,
+0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x65, 0x63, 0x50, 0x65, 0x6e, 0x20, 0x44, 0x79, 0x6f,
+0x6e, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x42, 0x61, 0x2bc, 0x61, 0x3b, 0x50,
+0x65, 0x6e, 0x20, 0x41, 0x74, 0x61, 0x74, 0x3b, 0x50, 0x65, 0x6e, 0x20,
+0x41, 0x6e, 0x61, 0x73, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x74, 0x79,
+0x6f, 0x6e, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x63, 0x68, 0x69, 0x72,
+0x69, 0x6d, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x74, 0x61, 0x72, 0x69,
+0x62, 0x61, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x77, 0x75, 0x72, 0x72,
+0x3b, 0x50, 0x65, 0x6e, 0x20, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x6e, 0x3b,
+0x50, 0x65, 0x6e, 0x20, 0x53, 0x68, 0x61, 0x6b, 0x75, 0x72, 0x3b, 0x50,
+0x65, 0x6e, 0x20, 0x4b, 0x75, 0x72, 0x20, 0x4e, 0x61, 0x62, 0x61, 0x3b,
+0x50, 0x65, 0x6e, 0x20, 0x4b, 0x75, 0x72, 0x20, 0x4e, 0x61, 0x74, 0x61,
+0x74, 0x44, 0x79, 0x6f, 0x6e, 0x3b, 0x42, 0x61, 0x61, 0x3b, 0x41, 0x74,
+0x61, 0x74, 0x3b, 0x41, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x74, 0x79, 0x6f,
+0x3b, 0x41, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x72, 0x3b, 0x41,
+0x77, 0x75, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x64, 0x3b, 0x53, 0x68, 0x61,
+0x6b, 0x3b, 0x4e, 0x61, 0x62, 0x61, 0x3b, 0x4e, 0x61, 0x74, 0x61, 0x79,
+0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c,
+0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b,
+0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75,
+0x6c, 0x3b, 0x61, 0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e,
+0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x79, 0x61, 0x62,
+0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b,
+0x61, 0x62, 0x72, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d,
+0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69,
+0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x71, 0x3b, 0x73,
+0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64,
+0x65, 0x6b, 0x408, 0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432,
+0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440,
+0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x458, 0x443, 0x43d, 0x3b,
+0x418, 0x458, 0x443, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b,
+0x421, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442,
+0x458, 0x430, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b,
+0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x458, 0x430, 0x43d, 0x432, 0x430, 0x440,
+0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442,
+0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438,
+0x458, 0x443, 0x43d, 0x3b, 0x438, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433,
+0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440,
+0x3b, 0x43e, 0x43a, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43d, 0x43e, 0x458,
+0x430, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x458, 0x430,
+0x43d, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f,
+0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x43d, 0x3b, 0x438, 0x458,
+0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a,
+0x442, 0x3b, 0x43d, 0x43e, 0x458, 0x3b, 0x434, 0x435, 0x43a, 0x14b, 0x77, 0xed,
+0xed, 0x20, 0x61, 0x20, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x74, 0x254, 0x3b,
+0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x62, 0x25b, 0x301,
+0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x72,
+0xe1, 0xe1, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20,
+0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd,
+0x20, 0x74, 0xe1, 0x61, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61,
+0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x66, 0x254, 0x6b, 0x3b, 0x14b, 0x77,
+0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x62, 0x25b,
+0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74,
+0xe1, 0x61, 0x72, 0x61, 0x61, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61,
+0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77,
+0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x3b,
+0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b,
+0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x254, 0x301, 0x6b, 0x3b, 0x14b, 0x77,
+0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20,
+0x64, 0x69, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x14b, 0x31, 0x3b, 0x14b, 0x32,
+0x3b, 0x14b, 0x33, 0x3b, 0x14b, 0x34, 0x3b, 0x14b, 0x35, 0x3b, 0x14b, 0x36,
+0x3b, 0x14b, 0x37, 0x3b, 0x14b, 0x38, 0x3b, 0x14b, 0x39, 0x3b, 0x14b, 0x31,
+0x30, 0x3b, 0x14b, 0x31, 0x31, 0x3b, 0x14b, 0x31, 0x32, 0x7a, 0x61, 0x6e,
+0x77, 0x75, 0x79, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x72, 0x75, 0x79,
+0x65, 0x3b, 0x6d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x61, 0x77, 0x69,
+0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x25b,
+0x6e, 0x3b, 0x7a, 0x75, 0x6c, 0x75, 0x79, 0x65, 0x3b, 0x75, 0x74, 0x69,
+0x3b, 0x73, 0x25b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x254,
+0x6b, 0x75, 0x74, 0x254, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x6e, 0x6f, 0x77,
+0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6e,
+0x62, 0x75, 0x72, 0x75, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b,
+0x6d, 0x61, 0x72, 0x3b, 0x61, 0x77, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a,
+0x75, 0x77, 0x3b, 0x7a, 0x75, 0x6c, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73,
+0x25b, 0x74, 0x3b, 0x254, 0x6b, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64,
+0x65, 0x73, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e, 0x3b,
+0x44, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab,
+0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae,
+0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b,
+0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987,
+0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f,
+0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac,
+0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf,
+0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab,
+0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd,
+0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c,
+0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8,
+0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995,
+0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac,
+0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x99c, 0x9be,
+0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a,
+0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1,
+0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x3b, 0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa,
+0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x3b, 0x9a1,
+0x9bf, 0x9b8, 0x9c7, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae, 0x9be, 0x3b,
+0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b,
+0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0x99c,
+0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd,
+0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b,
+0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997,
+0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x983, 0x3b,
+0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x983, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x983, 0x3b,
+0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x983, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7,
+0x9ac, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0,
+0x9bf, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2,
+0x3b, 0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x983, 0x3b,
+0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x983, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x983, 0x3b,
+0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x983, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae,
+0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c,
+0x9c1, 0x9b2, 0x3b, 0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b,
+0x9a1, 0x9bf, 0x4b, 0x254, 0x6e, 0x64, 0x254, 0x14b, 0x3b, 0x4d, 0xe0, 0x63,
+0x25b, 0x302, 0x6c, 0x3b, 0x4d, 0xe0, 0x74, 0xf9, 0x6d, 0x62, 0x3b, 0x4d,
+0xe0, 0x74, 0x6f, 0x70, 0x3b, 0x4d, 0x300, 0x70, 0x75, 0x79, 0x25b, 0x3b,
+0x48, 0xec, 0x6c, 0xf2, 0x6e, 0x64, 0x25b, 0x300, 0x3b, 0x4e, 0x6a, 0xe8,
+0x62, 0xe0, 0x3b, 0x48, 0xec, 0x6b, 0x61, 0x14b, 0x3b, 0x44, 0xec, 0x70,
+0x254, 0x300, 0x73, 0x3b, 0x42, 0xec, 0xf2, 0xf4, 0x6d, 0x3b, 0x4d, 0xe0,
+0x79, 0x25b, 0x73, 0xe8, 0x70, 0x3b, 0x4c, 0xec, 0x62, 0x75, 0x79, 0x20,
+0x6c, 0x69, 0x20, 0x144, 0x79, 0xe8, 0x65, 0x6b, 0x254, 0x6e, 0x3b, 0x6d,
+0x61, 0x63, 0x3b, 0x6d, 0x61, 0x74, 0x3b, 0x6d, 0x74, 0x6f, 0x3b, 0x6d,
+0x70, 0x75, 0x3b, 0x68, 0x69, 0x6c, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x68,
+0x69, 0x6b, 0x3b, 0x64, 0x69, 0x70, 0x3b, 0x62, 0x69, 0x6f, 0x3b, 0x6d,
+0x61, 0x79, 0x3b, 0x6c, 0x69, 0x253, 0x6b, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b,
+0x6d, 0x3b, 0x6d, 0x3b, 0x68, 0x3b, 0x6e, 0x3b, 0x68, 0x3b, 0x64, 0x3b,
+0x62, 0x3b, 0x6d, 0x3b, 0x6c, 0x75, 0x72, 0x74, 0x61, 0x72, 0x72, 0x69,
+0x6c, 0x61, 0x3b, 0x6f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x6d,
+0x61, 0x72, 0x74, 0x78, 0x6f, 0x61, 0x3b, 0x61, 0x70, 0x69, 0x72, 0x69,
+0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x65,
+0x6b, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x75, 0x7a, 0x74, 0x61, 0x69, 0x6c,
+0x61, 0x3b, 0x61, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61, 0x3b, 0x69, 0x72,
+0x61, 0x69, 0x6c, 0x61, 0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x61,
+0x7a, 0x61, 0x72, 0x6f, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x6e, 0x64, 0x75,
+0x61, 0x75, 0x72, 0x74, 0x2e, 0x3b, 0x6f, 0x74, 0x73, 0x2e, 0x3b, 0x6d,
+0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x69, 0x2e, 0x3b, 0x6d, 0x61, 0x69,
+0x2e, 0x3b, 0x65, 0x6b, 0x61, 0x2e, 0x3b, 0x75, 0x7a, 0x74, 0x2e, 0x3b,
+0x61, 0x62, 0x75, 0x2e, 0x3b, 0x69, 0x72, 0x61, 0x2e, 0x3b, 0x75, 0x72,
+0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x61, 0x2e, 0x3b, 0x61, 0x62, 0x65, 0x2e,
+0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45, 0x3b,
+0x55, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x441,
+0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442, 0x44b,
+0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a, 0x440, 0x430,
+0x441, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d,
+0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44c,
+0x3b, 0x436, 0x43d, 0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440,
+0x430, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b,
+0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430,
+0x434, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x430, 0x43d, 0x44c, 0x441, 0x442, 0x443,
+0x434, 0x437, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x430, 0x433, 0x430,
+0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43a, 0x440,
+0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b,
+0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x456, 0x43f, 0x435,
+0x43d, 0x44f, 0x3b, 0x436, 0x43d, 0x456, 0x45e, 0x43d, 0x44f, 0x3b, 0x432, 0x435,
+0x440, 0x430, 0x441, 0x43d, 0x44f, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b,
+0x447, 0x43d, 0x456, 0x43a, 0x430, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f,
+0x430, 0x434, 0x430, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x43d, 0x44f, 0x441, 0x442,
+0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440,
+0x430, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456,
+0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430,
+0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x441, 0x442, 0x443,
+0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430,
+0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f,
+0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441,
+0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x441, 0x3b, 0x43b, 0x3b,
+0x441, 0x3b, 0x43a, 0x3b, 0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x436, 0x3b,
+0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b,
+0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6f, 0x3b,
+0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
+0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69,
+0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61,
+0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76,
+0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
+0x4e, 0x3b, 0x44, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
+0x20, 0x67, 0x77, 0x61, 0x20, 0x68, 0x75, 0x74, 0x61, 0x6c, 0x61, 0x3b,
+0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77,
+0x61, 0x20, 0x77, 0x75, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20,
+0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77,
+0x75, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65,
+0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x74, 0x61,
+0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
+0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70,
+0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61,
+0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65,
+0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61,
+0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
+0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x61, 0x20, 0x6d,
+0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x74, 0x69,
+0x73, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
+0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x70, 0x61,
+0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20,
+0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61,
+0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
+0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d,
+0x62, 0x69, 0x6c, 0x69, 0x48, 0x75, 0x74, 0x3b, 0x56, 0x69, 0x6c, 0x3b,
+0x44, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x48, 0x61, 0x6e, 0x3b,
+0x53, 0x69, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b,
+0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4b, 0x6d, 0x6a, 0x3b,
+0x4b, 0x6d, 0x62, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48,
+0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x4b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930,
+0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930,
+0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
+0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f,
+0x924, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x942, 0x92c,
+0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902,
+0x92c, 0x930, 0x120d, 0x12f0, 0x1275, 0x122a, 0x3b, 0x12ab, 0x1265, 0x12bd, 0x1265, 0x1272,
+0x3b, 0x12ad, 0x1265, 0x120b, 0x3b, 0x134b, 0x1305, 0x12ba, 0x122a, 0x3b, 0x12ad, 0x1262,
+0x1245, 0x122a, 0x3b, 0x121d, 0x12aa, 0x12a4, 0x120d, 0x20, 0x1275, 0x131f, 0x1292, 0x122a,
+0x3b, 0x12b0, 0x122d, 0x12a9, 0x3b, 0x121b, 0x122d, 0x12eb, 0x121d, 0x20, 0x1275, 0x122a,
+0x3b, 0x12eb, 0x12b8, 0x1292, 0x20, 0x1218, 0x1233, 0x1245, 0x1208, 0x122a, 0x3b, 0x1218,
+0x1270, 0x1209, 0x3b, 0x121d, 0x12aa, 0x12a4, 0x120d, 0x20, 0x1218, 0x123d, 0x12c8, 0x122a,
+0x3b, 0x1270, 0x1215, 0x1233, 0x1235, 0x122a, 0x120d, 0x12f0, 0x1275, 0x3b, 0x12ab, 0x1265,
+0x12bd, 0x3b, 0x12ad, 0x1265, 0x120b, 0x3b, 0x134b, 0x1305, 0x12ba, 0x3b, 0x12ad, 0x1262,
+0x1245, 0x3b, 0x121d, 0x2f, 0x1275, 0x3b, 0x12b0, 0x122d, 0x3b, 0x121b, 0x122d, 0x12eb,
+0x3b, 0x12eb, 0x12b8, 0x1292, 0x3b, 0x1218, 0x1270, 0x1209, 0x3b, 0x121d, 0x2f, 0x121d,
+0x3b, 0x1270, 0x1215, 0x1233, 0x120d, 0x3b, 0x12ab, 0x3b, 0x12ad, 0x3b, 0x134b, 0x3b,
+0x12ad, 0x3b, 0x121d, 0x3b, 0x12b0, 0x3b, 0x121b, 0x3b, 0x12eb, 0x3b, 0x1218, 0x3b,
+0x121d, 0x3b, 0x1270, 0x91c, 0x93e, 0x928, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b,
+0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x942, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e,
+0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b,
+0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908,
+0x3b, 0x906, 0x917, 0x937, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x925,
+0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x2019, 0x92c,
+0x930, 0x3b, 0x928, 0x935, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x921, 0x93f,
+0x938, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x91c, 0x93e, 0x928, 0x3b, 0x92b, 0x947,
+0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930,
+0x93f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932,
+0x3b, 0x906, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b, 0x905, 0x915, 0x94d, 0x91f,
+0x2019, 0x3b, 0x928, 0x935, 0x947, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x91c, 0x3b,
+0x92b, 0x3b, 0x92e, 0x3b, 0x90f, 0x3b, 0x92e, 0x3b, 0x91c, 0x3b, 0x91c, 0x3b,
+0x906, 0x3b, 0x938, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x921, 0x6a, 0x61, 0x6e,
+0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b,
+0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d,
+0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
+0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61,
+0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64,
+0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66,
+0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
+0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61,
+0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e,
+0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b,
+0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b,
+0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b,
+0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442,
+0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
+0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x443, 0x433,
+0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430,
+0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e,
+0x432, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c,
+0x431, 0x430, 0x440, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c,
+0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
+0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x443, 0x433, 0x3b, 0x441,
+0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434,
+0x435, 0x446, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b,
+0x458, 0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b,
+0x434, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x43, 0x2bc, 0x68, 0x77,
+0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68,
+0x3b, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d,
+0x65, 0x7a, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x47, 0x6f, 0x75, 0x65,
+0x72, 0x65, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e,
+0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75,
+0x3b, 0x4b, 0x65, 0x72, 0x7a, 0x75, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43,
+0x2bc, 0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x2e, 0x3b,
+0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a,
+0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73,
+0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72, 0x65,
+0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x7a, 0x75, 0x2e, 0x30, 0x31, 0x3b, 0x30,
+0x32, 0x3b, 0x30, 0x33, 0x3b, 0x30, 0x34, 0x3b, 0x30, 0x35, 0x3b, 0x30,
+0x36, 0x3b, 0x30, 0x37, 0x3b, 0x30, 0x38, 0x3b, 0x30, 0x39, 0x3b, 0x31,
+0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x44f, 0x43d, 0x443, 0x430, 0x440,
+0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c,
+0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430,
+0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432,
+0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432,
+0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b,
+0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435,
+0x43c, 0x432, 0x440, 0x438, 0x44f, 0x43d, 0x443, 0x3b, 0x444, 0x435, 0x432, 0x3b,
+0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439,
+0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433,
+0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x435,
+0x3b, 0x434, 0x435, 0x43a, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b,
+0x43c, 0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b,
+0x43d, 0x3b, 0x434, 0x1007, 0x1014, 0x103a, 0x1014, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b,
+0x1016, 0x1031, 0x1016, 0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019,
+0x1010, 0x103a, 0x3b, 0x1027, 0x1015, 0x103c, 0x102e, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007,
+0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004, 0x103a, 0x3b,
+0x1029, 0x1002, 0x102f, 0x1010, 0x103a, 0x3b, 0x1005, 0x1000, 0x103a, 0x1010, 0x1004, 0x103a,
+0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x1010, 0x102d, 0x102f, 0x1018,
+0x102c, 0x3b, 0x1014, 0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012,
+0x102e, 0x1007, 0x1004, 0x103a, 0x1018, 0x102c, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031,
+0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d,
+0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b, 0x1005, 0x1000, 0x103a, 0x3b,
+0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x3b, 0x1014, 0x102d, 0x102f, 0x3b, 0x1012, 0x102e,
+0x1007, 0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b,
+0x1007, 0x3b, 0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x31,
+0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35,
+0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39,
+0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32,
+0x6708, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b, 0x4e09, 0x6708, 0x3b, 0x56db, 0x6708,
+0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708, 0x3b, 0x516b, 0x6708,
+0x3b, 0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b, 0x5341, 0x4e00, 0x6708, 0x3b, 0x5341,
+0x4e8c, 0x6708, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72,
+0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69,
+0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b,
+0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74,
+0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63,
+0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x64,
+0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x66,
+0x65, 0x62, 0x72, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65,
+0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e,
+0x79, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b,
+0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x64, 0x65, 0x20, 0x73,
+0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63,
+0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73,
+0x65, 0x6d, 0x62, 0x72, 0x65, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
+0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b,
+0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x74,
+0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b,
+0x64, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x2e, 0x3b,
+0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x64, 0x65, 0x20,
+0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x2e, 0x3b,
+0x64, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a,
+0x75, 0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x2e, 0x3b,
+0x64, 0x2019, 0x61, 0x67, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74,
+0x2e, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x64, 0x65, 0x20,
+0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73, 0x2e,
+0x47, 0x4e, 0x3b, 0x46, 0x42, 0x3b, 0x4d, 0xc7, 0x3b, 0x41, 0x42, 0x3b,
+0x4d, 0x47, 0x3b, 0x4a, 0x4e, 0x3b, 0x4a, 0x4c, 0x3b, 0x41, 0x47, 0x3b,
+0x53, 0x54, 0x3b, 0x4f, 0x43, 0x3b, 0x4e, 0x56, 0x3b, 0x44, 0x53, 0x45,
+0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f,
+0x3b, 0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6e, 0x79, 0x6f, 0x3b,
+0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0x69, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x62,
+0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x45, 0x6e, 0x65, 0x3b, 0x50, 0x65, 0x62, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b,
+0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b,
+0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b,
+0x44, 0x69, 0x73, 0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d,
+0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e,
+0x3b, 0x44, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x59,
+0x65, 0x62, 0x72, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x73,
+0x3b, 0x49, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75,
+0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75,
+0x7a, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x75, 0x74, 0x61, 0x6e,
+0x62, 0x69, 0x72, 0x3b, 0x4b, 0x1e6d, 0x75, 0x62, 0x65, 0x72, 0x3b, 0x4e,
+0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x44, 0x75, 0x6a, 0x61, 0x6e,
+0x62, 0x69, 0x72, 0x59, 0x65, 0x6e, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d,
+0x61, 0x72, 0x3b, 0x49, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59,
+0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43,
+0x75, 0x74, 0x3b, 0x4b, 0x1e6d, 0x75, 0x3b, 0x4e, 0x77, 0x61, 0x3b, 0x44,
+0x75, 0x6a, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d, 0x3b,
+0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b,
+0x44, 0x6a9, 0x627, 0x646, 0x648, 0x648, 0x646, 0x6cc, 0x20, 0x62f, 0x648, 0x648,
+0x6d5, 0x645, 0x3b, 0x634, 0x648, 0x628, 0x627, 0x62a, 0x3b, 0x626, 0x627, 0x632,
+0x627, 0x631, 0x3b, 0x646, 0x6cc, 0x633, 0x627, 0x646, 0x3b, 0x626, 0x627, 0x6cc,
+0x627, 0x631, 0x3b, 0x62d, 0x648, 0x632, 0x6d5, 0x6cc, 0x631, 0x627, 0x646, 0x3b,
+0x62a, 0x6d5, 0x645, 0x648, 0x648, 0x632, 0x3b, 0x626, 0x627, 0x628, 0x3b, 0x626,
+0x6d5, 0x6cc, 0x644, 0x648, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646,
+0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x62a, 0x634, 0x631, 0x6cc,
+0x646, 0x6cc, 0x20, 0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x6a9, 0x627, 0x646,
+0x648, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x6a9, 0x3b, 0x634,
+0x3b, 0x626, 0x3b, 0x646, 0x3b, 0x626, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x626,
+0x3b, 0x626, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b, 0x6a9, 0xd804, 0xdd0e, 0xd804, 0xdd1a,
+0xd804, 0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1c, 0xd804,
+0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804,
+0xdd2a, 0xd804, 0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd22,
+0xd804, 0xdd34, 0xd804, 0xdd0c, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd2c, 0xd804,
+0xdd1b, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd1f, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804,
+0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd23, 0xd804, 0xdd2d, 0x3b, 0xd804,
+0xdd03, 0xd804, 0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804,
+0xdd34, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd11,
+0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22,
+0xd804, 0xdd34, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd27, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804,
+0xdd11, 0xd804, 0xdd2e, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd1a, 0xd804, 0xdd27, 0xd804, 0xdd1e, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34,
+0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd13, 0xd804,
+0xdd28, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804,
+0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd2a, 0xd804,
+0xdd20, 0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1c, 0xd804, 0xdd2c, 0xd804, 0xdd1b,
+0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd2a, 0xd804, 0xdd20,
+0xd804, 0xdd22, 0xd804, 0xdd28, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd22, 0xd804, 0xdd34, 0xd804,
+0xdd0c, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd33,
+0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804,
+0xdd2c, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804,
+0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd23, 0xd804, 0xdd2d, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd09,
+0xd804, 0xdd27, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd34, 0x3b, 0xd804,
+0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2c, 0xd804,
+0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd03, 0xd804, 0xdd27, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2c,
+0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1a, 0xd804,
+0xdd27, 0xd804, 0xdd1e, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804,
+0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd13, 0xd804, 0xdd28, 0xd804, 0xdd25,
+0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22,
+0xd804, 0xdd34, 0xd804, 0xdd0e, 0xd804, 0xdd1a, 0xd804, 0xdd2a, 0x3b, 0xd804, 0xdd1c, 0xd804,
+0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd22, 0xd804, 0xdd34,
+0xd804, 0xdd0c, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804,
+0xdd33, 0xd804, 0xdd22, 0xd804, 0xdd28, 0xd804, 0xdd23, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1f,
+0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd0e, 0xd804, 0xdd2a, 0xd804, 0xdd23, 0xd804, 0xdd2d, 0x3b, 0xd804, 0xdd03, 0xd804,
+0xdd09, 0xd804, 0xdd27, 0xd804, 0xdd0c, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd34, 0x3b,
+0xd804, 0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1b, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804, 0xdd2c,
+0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34,
+0x3b, 0xd804, 0xdd03, 0xd804, 0xdd27, 0xd804, 0xdd07, 0xd804, 0xdd34, 0xd804, 0xdd11, 0xd804,
+0xdd2e, 0xd804, 0xdd1d, 0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd1a,
+0xd804, 0xdd27, 0xd804, 0xdd1e, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d,
+0xd804, 0xdd27, 0xd804, 0xdd22, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd13, 0xd804, 0xdd28, 0xd804,
+0xdd25, 0xd804, 0xdd2c, 0xd804, 0xdd1f, 0xd804, 0xdd34, 0xd804, 0xdd1d, 0xd804, 0xdd22, 0xd804,
+0xdd34, 0xd804, 0xdd0e, 0x3b, 0xd804, 0xdd1c, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd1f, 0x3b,
+0xd804, 0xdd03, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd1f, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd0e,
+0xd804, 0xdd2a, 0xd804, 0xdd1a, 0xd804, 0xdd34, 0x3b, 0xd804, 0xdd0e, 0xd804, 0xdd2a, 0x3b,
+0xd804, 0xdd03, 0x3b, 0xd804, 0xdd25, 0xd804, 0xdd2c, 0x3b, 0xd804, 0xdd03, 0xd804, 0xdd27,
+0x3b, 0xd804, 0xdd1a, 0xd804, 0xdd27, 0x3b, 0xd804, 0xdd13, 0xd804, 0xdd28, 0x44f, 0x43d,
+0x432, 0x430, 0x440, 0x44c, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c,
+0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c,
+0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e,
+0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435,
+0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431,
+0x440, 0x44c, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x434, 0x435,
+0x43a, 0x430, 0x431, 0x440, 0x44c, 0x44f, 0x43d, 0x432, 0x3b, 0x444, 0x435, 0x432,
+0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439,
+0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433,
+0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x44f,
+0x3b, 0x434, 0x435, 0x43a, 0x42f, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b,
+0x41c, 0x3b, 0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b,
+0x41d, 0x3b, 0x414, 0x13a4, 0x13c3, 0x13b8, 0x13d4, 0x13c5, 0x3b, 0x13a7, 0x13a6, 0x13b5,
+0x3b, 0x13a0, 0x13c5, 0x13f1, 0x3b, 0x13a7, 0x13ec, 0x13c2, 0x3b, 0x13a0, 0x13c2, 0x13cd,
+0x13ac, 0x13d8, 0x3b, 0x13d5, 0x13ad, 0x13b7, 0x13f1, 0x3b, 0x13ab, 0x13f0, 0x13c9, 0x13c2,
+0x3b, 0x13a6, 0x13b6, 0x13c2, 0x3b, 0x13da, 0x13b5, 0x13cd, 0x13d7, 0x3b, 0x13da, 0x13c2,
+0x13c5, 0x13d7, 0x3b, 0x13c5, 0x13d3, 0x13d5, 0x13c6, 0x3b, 0x13a5, 0x13cd, 0x13a9, 0x13f1,
+0x13a4, 0x13c3, 0x3b, 0x13a7, 0x13a6, 0x3b, 0x13a0, 0x13c5, 0x3b, 0x13a7, 0x13ec, 0x3b,
+0x13a0, 0x13c2, 0x3b, 0x13d5, 0x13ad, 0x3b, 0x13ab, 0x13f0, 0x3b, 0x13a6, 0x13b6, 0x3b,
+0x13da, 0x13b5, 0x3b, 0x13da, 0x13c2, 0x3b, 0x13c5, 0x13d3, 0x3b, 0x13a5, 0x13cd, 0x13a4,
+0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5, 0x3b, 0x13ab,
+0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a5, 0x48, 0x61,
+0x73, 0x68, 0x69, 0x2bc, 0x20, 0x41, 0x6d, 0x6d, 0x6f, 0x2bc, 0x6e, 0x61,
+0x2bc, 0x3b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x2bc, 0x20, 0x41, 0x74, 0x6f,
+0x6b, 0x6c, 0x6f, 0x2bc, 0x3b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x2bc, 0x20,
+0x41, 0x74, 0x6f, 0x63, 0x68, 0x63, 0x68, 0xed, 0x2bc, 0x6e, 0x61, 0x2bc,
+0x3b, 0x49, 0x69, 0x70, 0x6c, 0x61, 0x6c, 0x3b, 0x4d, 0x69, 0x68, 0x3b,
+0x43, 0x68, 0x6f, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x6f, 0x6f, 0x6c, 0x61,
+0x3b, 0x41, 0x6b, 0x61, 0x61, 0x73, 0x3b, 0x53, 0x69, 0x70, 0x74, 0x69,
+0x6d, 0x70, 0x61, 0x2bc, 0x3b, 0x41, 0x61, 0x6b, 0x74, 0x6f, 0x70, 0x61,
+0x2bc, 0x3b, 0x4e, 0x6f, 0x66, 0x69, 0x6d, 0x70, 0x61, 0x2bc, 0x3b, 0x54,
+0x69, 0x69, 0x73, 0x69, 0x6d, 0x70, 0x61, 0x2bc, 0x4f, 0x6b, 0x77, 0x6f,
+0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61,
+0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b,
+0x61, 0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b,
+0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61,
+0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61,
+0x61, 0x67, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x73, 0x68,
+0x61, 0x6e, 0x6a, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6e,
+0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x77, 0x65,
+0x6e, 0x64, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20,
+0x6e, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x77, 0x65, 0x3b, 0x4f, 0x6b, 0x77,
+0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x62,
+0x69, 0x72, 0x69, 0x4b, 0x42, 0x5a, 0x3b, 0x4b, 0x42, 0x52, 0x3b, 0x4b,
+0x53, 0x54, 0x3b, 0x4b, 0x4b, 0x4e, 0x3b, 0x4b, 0x54, 0x4e, 0x3b, 0x4b,
+0x4d, 0x4b, 0x3b, 0x4b, 0x4d, 0x53, 0x3b, 0x4b, 0x4d, 0x4e, 0x3b, 0x4b,
+0x4d, 0x57, 0x3b, 0x4b, 0x4b, 0x4d, 0x3b, 0x4b, 0x4e, 0x4b, 0x3b, 0x4b,
+0x4e, 0x42, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457,
+0x439, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439,
+0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x44a, 0x3b, 0x430, 0x486, 0x43f, 0x440,
+0x456, 0x301, 0x43b, 0x43b, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x439,
+0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b,
+0x301, 0x43b, 0x457, 0x439, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441,
+0x442, 0x44a, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440,
+0x457, 0x439, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457,
+0x439, 0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b,
+0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x456, 0x486,
+0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x444, 0x435,
+0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301,
+0x440, 0x442, 0x430, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b,
+0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b,
+0x301, 0x43d, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x430,
+0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x430, 0x3b, 0x441,
+0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x47b,
+0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43d, 0x43e,
+0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x434, 0x435, 0x43a, 0x435,
+0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x456, 0x486, 0x430, 0x2de9, 0x487, 0x3b,
+0x444, 0x435, 0x2de1, 0x487, 0x3b, 0x43c, 0x430, 0x2dec, 0x487, 0x3b, 0x430, 0x486,
+0x43f, 0x2dec, 0x487, 0x3b, 0x43c, 0x430, 0xa675, 0x3b, 0x456, 0x486, 0xa64b, 0x2de9,
+0x487, 0x3b, 0x456, 0x486, 0xa64b, 0x2de7, 0x487, 0x3b, 0x430, 0x486, 0x301, 0x475,
+0x2de2, 0x487, 0x3b, 0x441, 0x435, 0x2deb, 0x487, 0x3b, 0x47b, 0x486, 0x43a, 0x2dee,
+0x3b, 0x43d, 0x43e, 0x435, 0x2de8, 0x3b, 0x434, 0x435, 0x2de6, 0x487, 0x406, 0x486,
+0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x486, 0x3b, 0x41c, 0x3b, 0x406, 0x486,
+0x3b, 0x406, 0x486, 0x3b, 0x410, 0x486, 0x3b, 0x421, 0x3b, 0x47a, 0x486, 0x3b,
+0x41d, 0x3b, 0x414, 0x43a, 0x4d1, 0x440, 0x43b, 0x430, 0x447, 0x3b, 0x43d, 0x430,
+0x440, 0x4d1, 0x441, 0x3b, 0x43f, 0x443, 0x448, 0x3b, 0x430, 0x43a, 0x430, 0x3b,
+0x4ab, 0x443, 0x3b, 0x4ab, 0x4d7, 0x440, 0x442, 0x43c, 0x435, 0x3b, 0x443, 0x442,
+0x4d1, 0x3b, 0x4ab, 0x443, 0x440, 0x43b, 0x430, 0x3b, 0x430, 0x432, 0x4d1, 0x43d,
+0x3b, 0x44e, 0x43f, 0x430, 0x3b, 0x447, 0x4f3, 0x43a, 0x3b, 0x440, 0x430, 0x448,
+0x442, 0x430, 0x432, 0x43a, 0x4d1, 0x440, 0x2e, 0x3b, 0x43d, 0x430, 0x440, 0x2e,
+0x3b, 0x43f, 0x443, 0x448, 0x3b, 0x430, 0x43a, 0x430, 0x3b, 0x4ab, 0x443, 0x3b,
+0x4ab, 0x4d7, 0x440, 0x2e, 0x3b, 0x443, 0x442, 0x4d1, 0x3b, 0x4ab, 0x443, 0x440,
+0x2e, 0x3b, 0x430, 0x432, 0x4d1, 0x43d, 0x3b, 0x44e, 0x43f, 0x430, 0x3b, 0x447,
+0x4f3, 0x43a, 0x3b, 0x440, 0x430, 0x448, 0x2e, 0x41a, 0x3b, 0x41d, 0x3b, 0x41f,
+0x3b, 0x410, 0x3b, 0x4aa, 0x3b, 0x4aa, 0x3b, 0x423, 0x3b, 0x4aa, 0x3b, 0x410,
+0x3b, 0x42e, 0x3b, 0x427, 0x3b, 0x420, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77,
+0x61, 0x3b, 0x46, 0xe4, 0x62, 0x72, 0x6f, 0x77, 0x61, 0x3b, 0x4d, 0xe4,
+0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x6c, 0x3b, 0x4d, 0x61,
+0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6c,
+0x69, 0x3b, 0x4f, 0x75, 0x6a, 0x6f, 0xdf, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x68, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x2e,
+0x3b, 0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x7a, 0x2e, 0x3b, 0x41,
+0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e,
+0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f, 0x75, 0x6a, 0x2e, 0x3b, 0x53,
+0xe4, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76,
+0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0xe4,
+0x62, 0x3b, 0x4d, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x75,
+0x6a, 0x3b, 0x53, 0xe4, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x65, 0x6e, 0x76,
+0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x77, 0x65, 0x76, 0x72,
+0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74,
+0x68, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b,
+0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d,
+0x65, 0x74, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20,
+0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x6d, 0x69,
+0x73, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x77,
+0x79, 0x6e, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20,
+0x48, 0x65, 0x64, 0x72, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x44, 0x75,
+0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68,
+0x75, 0x47, 0x65, 0x6e, 0x3b, 0x48, 0x77, 0x65, 0x3b, 0x4d, 0x65, 0x75,
+0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x3b, 0x4d, 0x65, 0x74, 0x3b,
+0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b,
+0x48, 0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x67, 0x68,
+0x6a, 0x65, 0x6e, 0x6e, 0x61, 0x67, 0x68, 0x6a, 0x75, 0x3b, 0x66, 0x65,
+0x72, 0x72, 0x61, 0x67, 0x68, 0x6a, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x7a,
+0x75, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67,
+0x68, 0x6a, 0x75, 0x3b, 0x67, 0x68, 0x6a, 0x75, 0x67, 0x6e, 0x75, 0x3b,
+0x6c, 0x75, 0x67, 0x6c, 0x69, 0x75, 0x3b, 0x61, 0x6f, 0x73, 0x74, 0x75,
+0x3b, 0x73, 0x69, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f,
+0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x75, 0x76, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x64, 0x69, 0x20, 0x67, 0x68, 0x6a, 0x65, 0x6e, 0x6e, 0x61, 0x67, 0x68,
+0x6a, 0x75, 0x3b, 0x64, 0x69, 0x20, 0x66, 0x65, 0x72, 0x72, 0x61, 0x67,
+0x68, 0x6a, 0x75, 0x3b, 0x64, 0x69, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75,
+0x3b, 0x64, 0x2019, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x64, 0x69,
+0x20, 0x6d, 0x61, 0x67, 0x68, 0x6a, 0x75, 0x3b, 0x64, 0x69, 0x20, 0x67,
+0x68, 0x6a, 0x75, 0x67, 0x6e, 0x75, 0x3b, 0x64, 0x69, 0x20, 0x6c, 0x75,
+0x67, 0x6c, 0x69, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x6f, 0x73, 0x74, 0x75,
+0x3b, 0x64, 0x69, 0x20, 0x73, 0x69, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b,
+0x64, 0x69, 0x20, 0x6e, 0x75, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
+0x64, 0x69, 0x20, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x67,
+0x68, 0x6a, 0x2e, 0x3b, 0x66, 0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
+0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x67, 0x2e, 0x3b,
+0x67, 0x68, 0x6a, 0x75, 0x2e, 0x3b, 0x6c, 0x75, 0x67, 0x2e, 0x3b, 0x61,
+0x6f, 0x73, 0x2e, 0x3b, 0x73, 0x69, 0x74, 0x2e, 0x3b, 0x6f, 0x74, 0x74,
+0x2e, 0x3b, 0x6e, 0x75, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x47,
+0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c,
+0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x73, 0x69,
+0x6a, 0x65, 0x10d, 0x61, 0x6e, 0x6a, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61,
+0x10d, 0x61, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x61, 0x6b, 0x3b, 0x74, 0x72,
+0x61, 0x76, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x61, 0x6e,
+0x6a, 0x3b, 0x6c, 0x69, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x72, 0x70,
+0x61, 0x6e, 0x6a, 0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x3b,
+0x72, 0x75, 0x6a, 0x61, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70,
+0x61, 0x64, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x69, 0x3b, 0x70,
+0x72, 0x6f, 0x73, 0x69, 0x6e, 0x61, 0x63, 0x73, 0x69, 0x6a, 0x65, 0x10d,
+0x6e, 0x6a, 0x61, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d, 0x65, 0x3b,
+0x6f, 0x17e, 0x75, 0x6a, 0x6b, 0x61, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x6e,
+0x6a, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x6e, 0x6a, 0x61, 0x3b, 0x6c,
+0x69, 0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x6a, 0x61,
+0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x61, 0x3b, 0x72, 0x75,
+0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64,
+0x61, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x6f, 0x67, 0x61, 0x3b,
+0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x61, 0x73, 0x69, 0x6a, 0x3b,
+0x76, 0x65, 0x6c, 0x6a, 0x3b, 0x6f, 0x17e, 0x75, 0x3b, 0x74, 0x72, 0x61,
+0x3b, 0x73, 0x76, 0x69, 0x3b, 0x6c, 0x69, 0x70, 0x3b, 0x73, 0x72, 0x70,
+0x3b, 0x6b, 0x6f, 0x6c, 0x3b, 0x72, 0x75, 0x6a, 0x3b, 0x6c, 0x69, 0x73,
+0x3b, 0x73, 0x74, 0x75, 0x3b, 0x70, 0x72, 0x6f, 0x31, 0x2e, 0x3b, 0x32,
+0x2e, 0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36,
+0x2e, 0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31,
+0x30, 0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e, 0x6c, 0x65,
+0x64, 0x65, 0x6e, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x3b, 0x62, 0x159, 0x65,
+0x7a, 0x65, 0x6e, 0x3b, 0x64, 0x75, 0x62, 0x65, 0x6e, 0x3b, 0x6b, 0x76,
+0x11b, 0x74, 0x65, 0x6e, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x3b,
+0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x65, 0x63, 0x3b, 0x73, 0x72, 0x70,
+0x65, 0x6e, 0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x65,
+0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x70,
+0x72, 0x6f, 0x73, 0x69, 0x6e, 0x65, 0x63, 0x6c, 0x65, 0x64, 0x6e, 0x61,
+0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x61, 0x3b, 0x62, 0x159, 0x65, 0x7a, 0x6e,
+0x61, 0x3b, 0x64, 0x75, 0x62, 0x6e, 0x61, 0x3b, 0x6b, 0x76, 0x11b, 0x74,
+0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x6e, 0x61, 0x3b, 0x10d, 0x65,
+0x72, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x61,
+0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x6e, 0x61, 0x3b,
+0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x75, 0x3b, 0x70, 0x72,
+0x6f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x3b, 0xfa, 0x6e,
+0x6f, 0x3b, 0x62, 0x159, 0x65, 0x3b, 0x64, 0x75, 0x62, 0x3b, 0x6b, 0x76,
+0x11b, 0x3b, 0x10d, 0x76, 0x6e, 0x3b, 0x10d, 0x76, 0x63, 0x3b, 0x73, 0x72,
+0x70, 0x3b, 0x7a, 0xe1, 0x159, 0x3b, 0x159, 0xed, 0x6a, 0x3b, 0x6c, 0x69,
+0x73, 0x3b, 0x70, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b,
+0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74,
+0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b,
+0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62,
+0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c,
+0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b,
+0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65,
+0x63, 0x2e, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930,
+0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930,
+0x948, 0x932, 0x3b, 0x92e, 0x947, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c,
+0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938,
+0x93f, 0x924, 0x902, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c,
+0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902,
+0x92c, 0x930, 0x91c, 0x928, 0x2e, 0x3b, 0x92b, 0x930, 0x2e, 0x3b, 0x92e, 0x93e,
+0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e,
+0x947, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908,
+0x3b, 0x905, 0x917, 0x2e, 0x3b, 0x938, 0x93f, 0x924, 0x2e, 0x3b, 0x905, 0x915,
+0x94d, 0x924, 0x942, 0x2e, 0x3b, 0x928, 0x935, 0x2e, 0x3b, 0x926, 0x93f, 0x938,
+0x2e, 0x91c, 0x3b, 0x92b, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x947,
+0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x3b, 0x938, 0x93f, 0x3b,
+0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x64, 0x69, 0x6d, 0x254, 0x301, 0x64,
+0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x64, 0x25b, 0x3b, 0x73, 0x254, 0x14b,
+0x25b, 0x3b, 0x64, 0x69, 0x253, 0xe1, 0x253, 0xe1, 0x3b, 0x65, 0x6d, 0x69,
+0x61, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x65, 0x73, 0x254, 0x70, 0x25b, 0x73,
+0x254, 0x70, 0x25b, 0x3b, 0x6d, 0x61, 0x64, 0x69, 0x253, 0x25b, 0x301, 0x64,
+0xed, 0x253, 0x25b, 0x301, 0x3b, 0x64, 0x69, 0x14b, 0x67, 0x69, 0x6e, 0x64,
+0x69, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x25b, 0x6b, 0x69, 0x3b, 0x6d, 0x61,
+0x79, 0xe9, 0x73, 0x25b, 0x301, 0x3b, 0x74, 0x69, 0x6e, 0xed, 0x6e, 0xed,
+0x3b, 0x65, 0x6c, 0xe1, 0x14b, 0x67, 0x25b, 0x301, 0x64, 0x69, 0x3b, 0x14b,
+0x67, 0x254, 0x6e, 0x3b, 0x73, 0x254, 0x14b, 0x3b, 0x64, 0x69, 0x253, 0x3b,
+0x65, 0x6d, 0x69, 0x3b, 0x65, 0x73, 0x254, 0x3b, 0x6d, 0x61, 0x64, 0x3b,
+0x64, 0x69, 0x14b, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x3b, 0x6d, 0x61, 0x79,
+0x3b, 0x74, 0x69, 0x6e, 0x3b, 0x65, 0x6c, 0xe1, 0x64, 0x3b, 0x14b, 0x3b,
+0x73, 0x3b, 0x64, 0x3b, 0x65, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x64, 0x3b,
+0x6e, 0x3b, 0x6d, 0x3b, 0x74, 0x3b, 0x65, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b,
+0x6d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
+0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c,
+0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x73,
+0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61,
+0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x72, 0x74, 0x3b, 0x61, 0x70,
+0x72, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75,
+0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b,
+0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0xf66, 0xfa4, 0xfb1,
+0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66,
+0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
+0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54,
+0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74,
+0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b,
+0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44,
+0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f,
+0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51,
+0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74,
+0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1,
+0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b,
+0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42,
+0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0x3b, 0xf5f,
+0xfb3, 0xf0b, 0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf25, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf26, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf28, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf22, 0xf21, 0x3b, 0xf22, 0x3b,
+0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b,
+0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0x31, 0x32, 0xf21, 0x3b,
+0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b,
+0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22,
+0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0x34, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b,
+0xf27, 0x3b, 0xf28, 0x3b, 0x39, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b,
+0xf21, 0xf22, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d,
+0x62, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x6b, 0x61, 0x129, 0x72, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x68, 0x61, 0x74, 0x169,
+0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61,
+0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x74, 0x61, 0x74,
+0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d,
+0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e,
+0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20,
+0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x4b,
+0x61, 0x129, 0x72, 0x129, 0x4d, 0x62, 0x65, 0x3b, 0x4b, 0x61, 0x69, 0x3b,
+0x4b, 0x61, 0x74, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x47, 0x61, 0x74, 0x3b,
+0x47, 0x61, 0x6e, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x4b, 0x6e, 0x6e, 0x3b,
+0x4b, 0x65, 0x6e, 0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b,
+0x49, 0x67, 0x69, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47,
+0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49,
+0x3b, 0x49, 0xd801, 0xdc16, 0xd801, 0xdc30, 0xd801, 0xdc4c, 0xd801, 0xdc37, 0xd801, 0xdc2d,
+0xd801, 0xdc2f, 0xd801, 0xdc49, 0xd801, 0xdc28, 0x3b, 0xd801, 0xdc19, 0xd801, 0xdc2f, 0xd801,
+0xdc3a, 0xd801, 0xdc49, 0xd801, 0xdc2d, 0xd801, 0xdc2f, 0xd801, 0xdc49, 0xd801, 0xdc28, 0x3b,
+0xd801, 0xdc23, 0xd801, 0xdc2a, 0xd801, 0xdc49, 0xd801, 0xdc3d, 0x3b, 0xd801, 0xdc01, 0xd801,
+0xdc39, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc4a, 0x3b, 0xd801, 0xdc23, 0xd801, 0xdc29,
+0x3b, 0xd801, 0xdc16, 0xd801, 0xdc2d, 0xd801, 0xdc4c, 0x3b, 0xd801, 0xdc16, 0xd801, 0xdc2d,
+0xd801, 0xdc4a, 0xd801, 0xdc34, 0x3b, 0xd801, 0xdc02, 0xd801, 0xdc40, 0xd801, 0xdc32, 0xd801,
+0xdc45, 0xd801, 0xdc3b, 0x3b, 0xd801, 0xdc1d, 0xd801, 0xdc2f, 0xd801, 0xdc39, 0xd801, 0xdc3b,
+0xd801, 0xdc2f, 0xd801, 0xdc4b, 0xd801, 0xdc3a, 0xd801, 0xdc32, 0xd801, 0xdc49, 0x3b, 0xd801,
+0xdc09, 0xd801, 0xdc3f, 0xd801, 0xdc3b, 0xd801, 0xdc2c, 0xd801, 0xdc3a, 0xd801, 0xdc32, 0xd801,
+0xdc49, 0x3b, 0xd801, 0xdc24, 0xd801, 0xdc2c, 0xd801, 0xdc42, 0xd801, 0xdc2f, 0xd801, 0xdc4b,
+0xd801, 0xdc3a, 0xd801, 0xdc32, 0xd801, 0xdc49, 0x3b, 0xd801, 0xdc14, 0xd801, 0xdc28, 0xd801,
+0xdc45, 0xd801, 0xdc2f, 0xd801, 0xdc4b, 0xd801, 0xdc3a, 0xd801, 0xdc32, 0xd801, 0xdc49, 0xd801,
+0xdc16, 0xd801, 0xdc30, 0xd801, 0xdc4c, 0x3b, 0xd801, 0xdc19, 0xd801, 0xdc2f, 0xd801, 0xdc3a,
+0x3b, 0xd801, 0xdc23, 0xd801, 0xdc2a, 0xd801, 0xdc49, 0x3b, 0xd801, 0xdc01, 0xd801, 0xdc39,
+0xd801, 0xdc49, 0x3b, 0xd801, 0xdc23, 0xd801, 0xdc29, 0x3b, 0xd801, 0xdc16, 0xd801, 0xdc2d,
+0xd801, 0xdc4c, 0x3b, 0xd801, 0xdc16, 0xd801, 0xdc2d, 0xd801, 0xdc4a, 0x3b, 0xd801, 0xdc02,
+0xd801, 0xdc40, 0x3b, 0xd801, 0xdc1d, 0xd801, 0xdc2f, 0xd801, 0xdc39, 0x3b, 0xd801, 0xdc09,
+0xd801, 0xdc3f, 0xd801, 0xdc3b, 0x3b, 0xd801, 0xdc24, 0xd801, 0xdc2c, 0xd801, 0xdc42, 0x3b,
+0xd801, 0xdc14, 0xd801, 0xdc28, 0xd801, 0xdc45, 0xd801, 0xdc16, 0x3b, 0xd801, 0xdc19, 0x3b,
+0xd801, 0xdc23, 0x3b, 0xd801, 0xdc01, 0x3b, 0xd801, 0xdc23, 0x3b, 0xd801, 0xdc16, 0x3b,
+0xd801, 0xdc16, 0x3b, 0xd801, 0xdc02, 0x3b, 0xd801, 0xdc1d, 0x3b, 0xd801, 0xdc09, 0x3b,
+0xd801, 0xdc24, 0x3b, 0xd801, 0xdc14, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0x3b, 0x4f, 0x63, 0x74, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x65, 0x63, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79,
+0x3b, 0x4a, 0x75, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41,
+0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x3b, 0x4f, 0x63, 0x74, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0xb7, 0xd801, 0xdc61, 0xd801, 0xdc68,
+0xd801, 0xdc59, 0xd801, 0xdc58, 0xd801, 0xdc6d, 0xd801, 0xdc62, 0xd801, 0xdc7a, 0xd801, 0xdc70,
+0x3b, 0xb7, 0xd801, 0xdc53, 0xd801, 0xdc67, 0xd801, 0xdc5a, 0xd801, 0xdc58, 0xd801, 0xdc75,
+0xd801, 0xdc62, 0xd801, 0xdc7a, 0xd801, 0xdc70, 0x3b, 0xb7, 0xd801, 0xdc65, 0xd801, 0xdc78,
+0xd801, 0xdc57, 0x3b, 0xb7, 0xd801, 0xdc71, 0xd801, 0xdc50, 0xd801, 0xdc6e, 0xd801, 0xdc6d,
+0xd801, 0xdc64, 0x3b, 0xb7, 0xd801, 0xdc65, 0xd801, 0xdc71, 0x3b, 0xb7, 0xd801, 0xdc61,
+0xd801, 0xdc75, 0xd801, 0xdc6f, 0x3b, 0xb7, 0xd801, 0xdc61, 0xd801, 0xdc6b, 0xd801, 0xdc64,
+0xd801, 0xdc72, 0x3b, 0xb7, 0xd801, 0xdc6a, 0xd801, 0xdc5c, 0xd801, 0xdc6d, 0xd801, 0xdc55,
+0xd801, 0xdc51, 0x3b, 0xb7, 0xd801, 0xdc55, 0xd801, 0xdc67, 0xd801, 0xdc50, 0xd801, 0xdc51,
+0xd801, 0xdc67, 0xd801, 0xdc65, 0xd801, 0xdc5a, 0xd801, 0xdc78, 0x3b, 0xb7, 0xd801, 0xdc77,
+0xd801, 0xdc52, 0xd801, 0xdc51, 0xd801, 0xdc74, 0xd801, 0xdc5a, 0xd801, 0xdc78, 0x3b, 0xb7,
+0xd801, 0xdc6f, 0xd801, 0xdc74, 0xd801, 0xdc5d, 0xd801, 0xdc67, 0xd801, 0xdc65, 0xd801, 0xdc5a,
+0xd801, 0xdc78, 0x3b, 0xb7, 0xd801, 0xdc5b, 0xd801, 0xdc6d, 0xd801, 0xdc55, 0xd801, 0xdc67,
+0xd801, 0xdc65, 0xd801, 0xdc5a, 0xd801, 0xdc78, 0xb7, 0xd801, 0xdc61, 0xd801, 0xdc68, 0x3b,
+0xb7, 0xd801, 0xdc53, 0xd801, 0xdc67, 0x3b, 0xb7, 0xd801, 0xdc65, 0xd801, 0xdc78, 0x3b,
+0xb7, 0xd801, 0xdc71, 0xd801, 0xdc50, 0x3b, 0xb7, 0xd801, 0xdc65, 0xd801, 0xdc71, 0x3b,
+0xb7, 0xd801, 0xdc61, 0xd801, 0xdc75, 0x3b, 0xb7, 0xd801, 0xdc61, 0xd801, 0xdc6b, 0x3b,
+0xb7, 0xd801, 0xdc6a, 0xd801, 0xdc5c, 0x3b, 0xb7, 0xd801, 0xdc55, 0xd801, 0xdc67, 0x3b,
+0xb7, 0xd801, 0xdc77, 0xd801, 0xdc52, 0x3b, 0xb7, 0xd801, 0xdc6f, 0xd801, 0xdc74, 0x3b,
+0xb7, 0xd801, 0xdc5b, 0xd801, 0xdc6d, 0xd801, 0xdc61, 0x3b, 0xd801, 0xdc53, 0x3b, 0xd801,
+0xdc65, 0x3b, 0xd801, 0xdc71, 0x3b, 0xd801, 0xdc65, 0x3b, 0xd801, 0xdc61, 0x3b, 0xd801,
+0xdc61, 0x3b, 0xd801, 0xdc6a, 0x3b, 0xd801, 0xdc55, 0x3b, 0xd801, 0xdc77, 0x3b, 0xd801,
+0xdc6f, 0x3b, 0xd801, 0xdc5b, 0x44f, 0x43a, 0x448, 0x430, 0x43c, 0x43a, 0x43e, 0x432,
+0x3b, 0x434, 0x430, 0x432, 0x43e, 0x43b, 0x43a, 0x43e, 0x432, 0x3b, 0x44d, 0x439,
+0x437, 0x44e, 0x440, 0x43a, 0x43e, 0x432, 0x3b, 0x447, 0x430, 0x434, 0x44b, 0x43a,
+0x43e, 0x432, 0x3b, 0x43f, 0x430, 0x43d, 0x436, 0x438, 0x43a, 0x43e, 0x432, 0x3b,
+0x430, 0x448, 0x442, 0x435, 0x43c, 0x43a, 0x43e, 0x432, 0x3b, 0x43c, 0x435, 0x434,
+0x44c, 0x43a, 0x43e, 0x432, 0x3b, 0x443, 0x43c, 0x430, 0x440, 0x44c, 0x43a, 0x43e,
+0x432, 0x3b, 0x442, 0x430, 0x448, 0x442, 0x430, 0x43c, 0x43a, 0x43e, 0x432, 0x3b,
+0x43e, 0x436, 0x43e, 0x43a, 0x43e, 0x432, 0x3b, 0x441, 0x443, 0x43d, 0x434, 0x435,
+0x440, 0x44c, 0x43a, 0x43e, 0x432, 0x3b, 0x430, 0x446, 0x430, 0x43c, 0x43a, 0x43e,
+0x432, 0x44f, 0x43a, 0x448, 0x3b, 0x434, 0x430, 0x432, 0x3b, 0x44d, 0x439, 0x437,
+0x3b, 0x447, 0x430, 0x434, 0x3b, 0x43f, 0x430, 0x43d, 0x3b, 0x430, 0x448, 0x442,
+0x3b, 0x43c, 0x435, 0x434, 0x3b, 0x443, 0x43c, 0x430, 0x3b, 0x442, 0x430, 0x448,
+0x3b, 0x43e, 0x436, 0x43e, 0x3b, 0x441, 0x443, 0x43d, 0x3b, 0x430, 0x446, 0x430,
+0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72,
+0x75, 0x61, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x6f, 0x3b, 0x41,
+0x70, 0x72, 0x69, 0x6c, 0x6f, 0x3b, 0x4d, 0x61, 0x6a, 0x6f, 0x3b, 0x4a,
+0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x41,
+0x16d, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65,
+0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x6f,
+0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65,
+0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61,
+0x6a, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x16d,
+0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x65, 0x63, 0x6a, 0x61, 0x61, 0x6e, 0x75, 0x61, 0x72,
+0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0xe4,
+0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d,
+0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75,
+0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a,
+0x61, 0x61, 0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4,
+0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b,
+0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b,
+0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74,
+0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x4a, 0x3b, 0x56,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41,
+0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x64, 0x7a, 0x6f, 0x76,
+0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64,
+0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254, 0x66, 0x129, 0x65, 0x3b, 0x64,
+0x61, 0x6d, 0x61, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61,
+0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d,
+0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b,
+0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b,
+0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x64, 0x7a,
+0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61, 0x66,
+0x254, 0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69,
+0x61, 0x3b, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b, 0x65,
+0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x64, 0x3b, 0x64,
+0x3b, 0x74, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64,
+0x3b, 0x61, 0x3b, 0x6b, 0x3b, 0x61, 0x3b, 0x64, 0x6e, 0x67, 0x254, 0x6e,
+0x20, 0x6f, 0x73, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x62, 0x25b,
+0x30c, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6c, 0xe1, 0x6c, 0x61, 0x3b,
+0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6e, 0x79, 0x69, 0x6e, 0x61, 0x3b, 0x6e,
+0x67, 0x254, 0x6e, 0x20, 0x74, 0xe1, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254,
+0x6e, 0x20, 0x73, 0x61, 0x6d, 0x259, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254,
+0x6e, 0x20, 0x7a, 0x61, 0x6d, 0x67, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x6e,
+0x67, 0x254, 0x6e, 0x20, 0x6d, 0x77, 0x6f, 0x6d, 0x3b, 0x6e, 0x67, 0x254,
+0x6e, 0x20, 0x65, 0x62, 0x75, 0x6c, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e,
+0x20, 0x61, 0x77, 0xf3, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61,
+0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x64, 0x7a, 0x69, 0xe1, 0x3b,
+0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69,
+0x20, 0x62, 0x25b, 0x30c, 0x6e, 0x67, 0x6f, 0x3b, 0x6e, 0x67, 0x62, 0x3b,
+0x6e, 0x67, 0x6c, 0x3b, 0x6e, 0x67, 0x6e, 0x3b, 0x6e, 0x67, 0x74, 0x3b,
+0x6e, 0x67, 0x73, 0x3b, 0x6e, 0x67, 0x7a, 0x3b, 0x6e, 0x67, 0x6d, 0x3b,
+0x6e, 0x67, 0x65, 0x3b, 0x6e, 0x67, 0x61, 0x3b, 0x6e, 0x67, 0x61, 0x64,
+0x3b, 0x6e, 0x67, 0x61, 0x62, 0x6f, 0x3b, 0x62, 0x3b, 0x6c, 0x3b, 0x6e,
+0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x61,
+0x3b, 0x64, 0x3b, 0x62, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66,
+0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b,
+0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75,
+0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75,
+0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61,
+0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75,
+0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65,
+0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65,
+0x73, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d,
+0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69,
+0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61,
+0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74,
+0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x45,
+0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f,
+0x3b, 0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6e, 0x79, 0x6f, 0x3b,
+0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f,
+0x3b, 0x53, 0x65, 0x74, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f,
+0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x62, 0x79, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x45, 0x6e, 0x65, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48, 0x75,
+0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65,
+0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69,
+0x73, 0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48,
+0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53,
+0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44,
+0x69, 0x73, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x68,
+0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x61, 0x6c,
+0x69, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b,
+0x75, 0x75, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x3b,
+0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x69, 0x6e,
+0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x3b,
+0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6c, 0x6f, 0x6b, 0x61,
+0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x75,
+0x75, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x74, 0x61,
+0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, 0x6c,
+0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6c,
+0x69, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x75, 0x68, 0x74,
+0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f,
+0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75,
+0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75,
+0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b,
+0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6c, 0x6f,
+0x6b, 0x61, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72,
+0x61, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c,
+0x75, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x3b,
+0x68, 0x65, 0x6c, 0x6d, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73,
+0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f,
+0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x3b,
+0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b, 0x6c, 0x6f, 0x6b,
+0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x3b, 0x6a, 0x6f, 0x75,
+0x6c, 0x75, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0x65,
+0x6c, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73,
+0x6b, 0x2e, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x2e, 0x3b, 0x74,
+0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x2e, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b,
+0x2e, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x2e, 0x3b, 0x65, 0x6c,
+0x6f, 0x6b, 0x2e, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x2e, 0x3b, 0x6c,
+0x6f, 0x6b, 0x61, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73,
+0x6b, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x2e, 0x54, 0x3b,
+0x48, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b,
+0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x6a, 0x61, 0x6e,
+0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x69, 0x65, 0x72,
+0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b,
+0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69,
+0x6c, 0x6c, 0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f,
+0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x3b, 0x64, 0xe9, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x6a, 0x61, 0x6e,
+0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
+0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a,
+0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f,
+0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74,
+0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x6a,
+0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d,
+0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69,
+0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x2e,
+0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b,
+0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9,
+0x63, 0x2e, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x2e, 0x3b,
+0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
+0x69, 0x3b, 0x6a, 0x75, 0x69, 0x2e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e,
+0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b,
+0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9,
+0x63, 0x2e, 0x5a, 0x65, 0x6e, 0xe2, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72,
+0xe2, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee,
+0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x6e, 0x3b, 0x4c,
+0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x61, 0x72,
+0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69,
+0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x5a, 0x65, 0x6e, 0x3b, 0x46, 0x65,
+0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x76, 0x72, 0x3b, 0x4d, 0x61,
+0x69, 0x3b, 0x4a, 0x75, 0x67, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76,
+0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x69, 0x63, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x73, 0x69, 0x69, 0x6c, 0x6f, 0x3b, 0x63, 0x6f,
+0x6c, 0x74, 0x65, 0x3b, 0x6d, 0x62, 0x6f, 0x6f, 0x79, 0x3b, 0x73, 0x65,
+0x65, 0x257, 0x74, 0x6f, 0x3b, 0x64, 0x75, 0x75, 0x6a, 0x61, 0x6c, 0x3b,
+0x6b, 0x6f, 0x72, 0x73, 0x65, 0x3b, 0x6d, 0x6f, 0x72, 0x73, 0x6f, 0x3b,
+0x6a, 0x75, 0x6b, 0x6f, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x74, 0x6f, 0x3b,
+0x79, 0x61, 0x72, 0x6b, 0x6f, 0x6d, 0x61, 0x61, 0x3b, 0x6a, 0x6f, 0x6c,
+0x61, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x74, 0x65, 0x73, 0x69, 0x69, 0x3b,
+0x63, 0x6f, 0x6c, 0x3b, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0x65, 0x65, 0x3b,
+0x64, 0x75, 0x75, 0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x3b,
+0x6a, 0x75, 0x6b, 0x3b, 0x73, 0x6c, 0x74, 0x3b, 0x79, 0x61, 0x72, 0x3b,
+0x6a, 0x6f, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x73, 0x3b, 0x63, 0x3b, 0x6d,
+0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73,
+0x3b, 0x79, 0x3b, 0x6a, 0x3b, 0x62, 0xd83a, 0xdd05, 0xd83a, 0xdd2d, 0xd83a, 0xdd45,
+0xd83a, 0xdd24, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd15, 0xd83a, 0xdd2e, 0xd83a, 0xdd24, 0xd83a,
+0xdd3c, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd10, 0xd83a, 0xdd26, 0xd83a, 0xdd2e, 0xd83a, 0xdd45,
+0xd83a, 0xdd34, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd2b, 0xd83a, 0xdd45, 0xd83a,
+0xdd3c, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd01, 0xd83a, 0xdd35, 0xd83a, 0xdd45, 0xd83a, 0xdd36,
+0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd11, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd27, 0xd83a,
+0xdd2e, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0xd83a, 0xdd27, 0xd83a, 0xdd2e,
+0x3b, 0xd83a, 0xdd14, 0xd83a, 0xdd35, 0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd05,
+0xd83a, 0xdd2d, 0xd83a, 0xdd24, 0xd83a, 0xdd3c, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd12, 0xd83a,
+0xdd22, 0xd83a, 0xdd2a, 0xd83a, 0xdd33, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd14, 0xd83a, 0xdd2e,
+0xd83a, 0xdd24, 0xd83a, 0xdd2e, 0x3b, 0xd83a, 0xdd04, 0xd83a, 0xdd2e, 0xd83a, 0xdd31, 0xd83a,
+0xdd3c, 0xd83a, 0xdd2e, 0xd83a, 0xdd05, 0xd83a, 0xdd2d, 0xd83a, 0xdd45, 0xd83a, 0xdd24, 0x3b,
+0xd83a, 0xdd15, 0xd83a, 0xdd2e, 0xd83a, 0xdd24, 0x3b, 0xd83a, 0xdd10, 0xd83a, 0xdd26, 0xd83a,
+0xdd2e, 0xd83a, 0xdd45, 0xd83a, 0xdd34, 0x3b, 0xd83a, 0xdd05, 0xd83a, 0xdd2b, 0xd83a, 0xdd45,
+0xd83a, 0xdd3c, 0x3b, 0xd83a, 0xdd01, 0xd83a, 0xdd35, 0xd83a, 0xdd45, 0xd83a, 0xdd36, 0x3b,
+0xd83a, 0xdd11, 0xd83a, 0xdd2e, 0xd83a, 0xdd2a, 0x3b, 0xd83a, 0xdd03, 0xd83a, 0xdd2e, 0xd83a,
+0xdd2a, 0x3b, 0xd83a, 0xdd14, 0xd83a, 0xdd35, 0xd83a, 0xdd33, 0x3b, 0xd83a, 0xdd05, 0xd83a,
+0xdd2d, 0xd83a, 0xdd24, 0x3b, 0xd83a, 0xdd12, 0xd83a, 0xdd22, 0xd83a, 0xdd2a, 0x3b, 0xd83a,
+0xdd14, 0xd83a, 0xdd2e, 0xd83a, 0xdd24, 0x3b, 0xd83a, 0xdd04, 0xd83a, 0xdd2e, 0xd83a, 0xdd31,
+0xd83a, 0xdd05, 0x3b, 0xd83a, 0xdd15, 0x3b, 0xd83a, 0xdd04, 0x3b, 0xd83a, 0xdd05, 0x3b,
+0xd83a, 0xdd01, 0x3b, 0xd83a, 0xdd11, 0x3b, 0xd83a, 0xdd03, 0x3b, 0xd83a, 0xdd14, 0x3b,
+0xd83a, 0xdd05, 0x3b, 0xd83a, 0xdd12, 0x3b, 0xd83a, 0xdd14, 0x3b, 0xd83a, 0xdd04, 0x41,
+0x6d, 0x20, 0x46, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68,
+0x3b, 0x41, 0x6e, 0x20, 0x47, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b,
+0x41, 0x6d, 0x20, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x41, 0x6e, 0x20, 0x47,
+0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x43, 0xe8,
+0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0xd2,
+0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d,
+0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x4c, 0xf9,
+0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d,
+0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44,
+0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d,
+0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44,
+0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x64, 0x68, 0x65, 0x6e,
+0x20, 0x46, 0x68, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68,
+0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x65, 0x61, 0x72, 0x72,
+0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x4d, 0x68, 0xe0, 0x72,
+0x74, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x69, 0x62, 0x6c,
+0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x43, 0x68, 0xe8,
+0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0xd2,
+0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20,
+0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20,
+0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x65,
+0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b,
+0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72,
+0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d, 0x68,
+0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xf9, 0x62,
+0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x46, 0x61, 0x6f, 0x69, 0x3b, 0x47,
+0x65, 0x61, 0x72, 0x72, 0x3b, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x47, 0x69,
+0x62, 0x6c, 0x3b, 0x43, 0xe8, 0x69, 0x74, 0x3b, 0xd2, 0x67, 0x6d, 0x68,
+0x3b, 0x49, 0x75, 0x63, 0x68, 0x3b, 0x4c, 0xf9, 0x6e, 0x61, 0x3b, 0x53,
+0x75, 0x6c, 0x74, 0x3b, 0x44, 0xe0, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d,
+0x68, 0x3b, 0x44, 0xf9, 0x62, 0x68, 0x46, 0x3b, 0x47, 0x3b, 0x4d, 0x3b,
+0x47, 0x3b, 0x43, 0x3b, 0xd2, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x53, 0x3b,
+0x44, 0x3b, 0x53, 0x3b, 0x44, 0x41, 0x68, 0x61, 0x72, 0x61, 0x62, 0x61,
+0x74, 0x61, 0x3b, 0x4f, 0x66, 0x6c, 0x254, 0x3b, 0x4f, 0x74, 0x73, 0x6f,
+0x6b, 0x72, 0x69, 0x6b, 0x72, 0x69, 0x3b, 0x41, 0x62, 0x65, 0x69, 0x62,
+0x65, 0x3b, 0x41, 0x67, 0x62, 0x69, 0x25b, 0x6e, 0x61, 0x61, 0x3b, 0x4f,
+0x74, 0x75, 0x6b, 0x77, 0x61, 0x6a, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x61,
+0x77, 0x25b, 0x3b, 0x4d, 0x61, 0x6e, 0x79, 0x61, 0x77, 0x61, 0x6c, 0x65,
+0x3b, 0x47, 0x62, 0x6f, 0x3b, 0x41, 0x6e, 0x74, 0x254, 0x14b, 0x3b, 0x41,
+0x6c, 0x65, 0x6d, 0x6c, 0x65, 0x3b, 0x41, 0x66, 0x75, 0x61, 0x62, 0x65,
+0x41, 0x68, 0x61, 0x72, 0x61, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x4f, 0x66,
+0x6c, 0x254, 0x3b, 0x4f, 0x74, 0x73, 0x6f, 0x6b, 0x72, 0x69, 0x6b, 0x72,
+0x69, 0x3b, 0x41, 0x62, 0x65, 0x69, 0x62, 0x65, 0x3b, 0x41, 0x67, 0x62,
+0x69, 0x25b, 0x6e, 0x61, 0x61, 0x3b, 0x4f, 0x74, 0x75, 0x6b, 0x77, 0x61,
+0x6a, 0x61, 0x14b, 0x3b, 0x4d, 0x61, 0x61, 0x77, 0x25b, 0x3b, 0x4d, 0x61,
+0x6e, 0x79, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x3b, 0x47, 0x62, 0x6f, 0x3b,
+0x41, 0x6e, 0x74, 0x254, 0x14b, 0x3b, 0x41, 0x6c, 0x65, 0x6d, 0x6c, 0x65,
+0x3b, 0x41, 0x66, 0x75, 0x61, 0x62, 0x65, 0x41, 0x68, 0x61, 0x3b, 0x4f,
+0x66, 0x6c, 0x3b, 0x4f, 0x74, 0x73, 0x3b, 0x41, 0x62, 0x65, 0x3b, 0x41,
+0x67, 0x62, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4d,
+0x61, 0x6e, 0x3b, 0x47, 0x62, 0x6f, 0x3b, 0x41, 0x6e, 0x74, 0x3b, 0x41,
+0x6c, 0x65, 0x3b, 0x41, 0x66, 0x75, 0x41, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b,
+0x41, 0x3b, 0x41, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b,
+0x41, 0x3b, 0x41, 0x3b, 0x41, 0x78, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f,
+0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61,
+0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61,
+0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x6c,
+0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74,
+0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72,
+0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64,
+0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x78, 0x61, 0x6e, 0x2e, 0x3b,
+0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62,
+0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f,
+0x3b, 0x78, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73,
+0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76,
+0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b,
+0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x78, 0x2e, 0x3b, 0x66, 0x2e, 0x3b, 0x6d,
+0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x78,
+0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x73, 0x2e, 0x3b, 0x6f, 0x2e, 0x3b, 0x6e,
+0x2e, 0x3b, 0x64, 0x2e, 0x4a, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x69, 0x79,
+0x6f, 0x3b, 0x46, 0x65, 0x62, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b,
+0x4d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x70, 0x75, 0x6c, 0x69,
+0x3b, 0x4d, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69,
+0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x75,
+0x73, 0x69, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x62, 0x75, 0x74, 0x74, 0x65,
+0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x62, 0x61,
+0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73,
+0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x75, 0x3b, 0x4d, 0x61, 0x61, 0x3b,
+0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b,
+0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x69, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
+0x44, 0x65, 0x73, 0x1320, 0x1210, 0x1228, 0x3b, 0x12a8, 0x1270, 0x1270, 0x3b, 0x1218,
+0x1308, 0x1260, 0x3b, 0x12a0, 0x1280, 0x12d8, 0x3b, 0x130d, 0x1295, 0x1263, 0x1275, 0x3b,
+0x1220, 0x1295, 0x12e8, 0x3b, 0x1210, 0x1218, 0x1208, 0x3b, 0x1290, 0x1210, 0x1230, 0x3b,
+0x12a8, 0x1228, 0x1218, 0x3b, 0x1320, 0x1240, 0x1218, 0x3b, 0x1280, 0x12f0, 0x1228, 0x3b,
+0x1280, 0x1220, 0x1220, 0x1320, 0x3b, 0x12a8, 0x3b, 0x1218, 0x3b, 0x12a0, 0x3b, 0x130d,
+0x3b, 0x1220, 0x3b, 0x1210, 0x3b, 0x1290, 0x3b, 0x12a8, 0x3b, 0x1320, 0x3b, 0x1280,
+0x3b, 0x1280, 0x10d8, 0x10d0, 0x10dc, 0x10d5, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10d7, 0x10d4,
+0x10d1, 0x10d4, 0x10e0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2,
+0x10d8, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10d8,
+0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5,
+0x10da, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x10d8, 0x10e1, 0x10e2, 0x10dd,
+0x3b, 0x10e1, 0x10d4, 0x10e5, 0x10e2, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b,
+0x10dd, 0x10e5, 0x10e2, 0x10dd, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd,
+0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, 0x10db,
+0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x10d8, 0x10d0, 0x10dc, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x3b,
+0x10db, 0x10d0, 0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b,
+0x10d8, 0x10d5, 0x10dc, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x3b,
+0x10e1, 0x10d4, 0x10e5, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x3b,
+0x10d3, 0x10d4, 0x10d9, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b, 0x10db,
+0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc,
+0x3b, 0x10d3, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62,
+0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70,
+0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69,
+0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f,
+0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b,
+0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b,
+0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b,
+0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a,
+0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72,
+0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67,
+0x2e, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e,
+0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x4a, 0xe4,
+0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72,
+0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b,
+0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
+0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70,
+0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0xe4, 0x6e, 0x3b,
+0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a, 0xe4, 0x6e, 0x2e, 0x3b,
+0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70,
+0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b,
+0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65,
+0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e,
+0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3ac, 0x3c1,
+0x3b9, 0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1,
+0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9, 0x3bf, 0x3c2, 0x3b,
+0x391, 0x3c0, 0x3c1, 0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3b9,
+0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399,
+0x3bf, 0x3cd, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3bf, 0x3c5,
+0x3c3, 0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2,
+0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce, 0x3b2, 0x3c1, 0x3b9,
+0x3bf, 0x3c2, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
+0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x399,
+0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x3a6, 0x3b5,
+0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1,
+0x3c1, 0x3c4, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b9, 0x3bb, 0x3af,
+0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5,
+0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af, 0x3bf, 0x3c5,
+0x3b, 0x391, 0x3c5, 0x3b3, 0x3bf, 0x3cd, 0x3c3, 0x3c4, 0x3bf, 0x3c5, 0x3b, 0x3a3,
+0x3b5, 0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f,
+0x3ba, 0x3c4, 0x3c9, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39d, 0x3bf, 0x3b5,
+0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b5, 0x3bc,
+0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2,
+0x3b, 0x39c, 0x3ac, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3ac, 0x3b9,
+0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b, 0x391,
+0x3cd, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d,
+0x3bf, 0x3ad, 0x3b, 0x394, 0x3b5, 0x3ba, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5,
+0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1,
+0x390, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3b,
+0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b,
+0x39d, 0x3bf, 0x3b5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c,
+0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3,
+0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x4a, 0x61, 0x73, 0x79, 0x74, 0x65,
+0x129, 0x3b, 0x4a, 0x61, 0x73, 0x79, 0x6b, 0xf5, 0x69, 0x3b, 0x4a, 0x61,
+0x73, 0x79, 0x61, 0x70, 0x79, 0x3b, 0x4a, 0x61, 0x73, 0x79, 0x72, 0x75,
+0x6e, 0x64, 0x79, 0x3b, 0x4a, 0x61, 0x73, 0x79, 0x70, 0x6f, 0x3b, 0x4a,
+0x61, 0x73, 0x79, 0x70, 0x6f, 0x74, 0x65, 0x129, 0x3b, 0x4a, 0x61, 0x73,
+0x79, 0x70, 0x6f, 0x6b, 0xf5, 0x69, 0x3b, 0x4a, 0x61, 0x73, 0x79, 0x70,
+0x6f, 0x61, 0x70, 0x79, 0x3b, 0x4a, 0x61, 0x73, 0x79, 0x70, 0x6f, 0x72,
+0x75, 0x6e, 0x64, 0x79, 0x3b, 0x4a, 0x61, 0x73, 0x79, 0x70, 0x61, 0x3b,
+0x4a, 0x61, 0x73, 0x79, 0x70, 0x61, 0x74, 0x65, 0x129, 0x3b, 0x4a, 0x61,
+0x73, 0x79, 0x70, 0x61, 0x6b, 0xf5, 0x69, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf,
+0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0xa86,
+0xab0, 0xac0, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd,
+0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c,
+0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8,
+0xaaa, 0xacd, 0xa9f, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd,
+0xa9f, 0xacb, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0,
+0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0xa9c, 0xabe, 0xaa8,
+0xacd, 0xaaf, 0xac1, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0x3b, 0xaae,
+0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b,
+0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88,
+0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7,
+0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5, 0xac7, 0x3b, 0xaa1,
+0xabf, 0xab8, 0xac7, 0xa9c, 0xabe, 0x3b, 0xaab, 0xac7, 0x3b, 0xaae, 0xabe, 0x3b,
+0xa8f, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0x3b, 0xa9c, 0xac1, 0x3b, 0xa91,
+0x3b, 0xab8, 0x3b, 0xa91, 0x3b, 0xaa8, 0x3b, 0xaa1, 0xabf, 0x43, 0x68, 0x61,
+0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x61,
+0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x69,
+0x72, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
+0x69, 0x3b, 0x43, 0x68, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f,
+0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x62,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61,
+0x43, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b,
+0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b,
+0x43, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b,
+0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x43,
+0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x43,
+0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x61,
+0x6e, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x46, 0x61, 0x62, 0x75, 0x72, 0x61,
+0x69, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x41, 0x66,
+0x69, 0x72, 0x69, 0x6c, 0x75, 0x3b, 0x4d, 0x61, 0x79, 0x75, 0x3b, 0x59,
+0x75, 0x6e, 0x69, 0x3b, 0x59, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75,
+0x73, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b,
+0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x75, 0x77, 0x61, 0x6d,
+0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x4a, 0x61,
+0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x66,
+0x69, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75,
+0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x4e, 0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41,
+0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x62c, 0x64e, 0x646, 0x64e,
+0x64a, 0x652, 0x631, 0x64f, 0x3b, 0x6a2, 0x64e, 0x628, 0x652, 0x631, 0x64e, 0x64a,
+0x652, 0x631, 0x64f, 0x3b, 0x645, 0x64e, 0x631, 0x650, 0x633, 0x652, 0x3b, 0x623,
+0x64e, 0x6a2, 0x652, 0x631, 0x650, 0x644, 0x64f, 0x3b, 0x645, 0x64e, 0x64a, 0x64f,
+0x3b, 0x64a, 0x64f, 0x648, 0x646, 0x650, 0x3b, 0x64a, 0x64f, 0x648, 0x644, 0x650,
+0x3b, 0x623, 0x64e, 0x63a, 0x64f, 0x633, 0x652, 0x62a, 0x64e, 0x3b, 0x633, 0x64e,
+0x62a, 0x64f, 0x645, 0x652, 0x628, 0x64e, 0x3b, 0x623, 0x64f, 0x643, 0x652, 0x62a,
+0x648, 0x64f, 0x628, 0x64e, 0x3b, 0x646, 0x64f, 0x648, 0x64e, 0x645, 0x652, 0x628,
+0x64e, 0x3b, 0x62f, 0x650, 0x633, 0x64e, 0x645, 0x652, 0x628, 0x64e, 0x62c, 0x64e,
+0x646, 0x3b, 0x6a2, 0x64e, 0x628, 0x3b, 0x645, 0x64e, 0x631, 0x3b, 0x623, 0x64e,
+0x6a2, 0x652, 0x631, 0x3b, 0x645, 0x64e, 0x64a, 0x3b, 0x64a, 0x64f, 0x648, 0x646,
+0x3b, 0x64a, 0x64f, 0x648, 0x644, 0x3b, 0x623, 0x64e, 0x63a, 0x64f, 0x3b, 0x633,
+0x64e, 0x62a, 0x3b, 0x623, 0x64f, 0x643, 0x652, 0x62a, 0x3b, 0x646, 0x64f, 0x648,
+0x3b, 0x62f, 0x650, 0x633, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b,
+0x50, 0x65, 0x70, 0x65, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61,
+0x6c, 0x61, 0x6b, 0x69, 0x3b, 0x2bb, 0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c,
+0x61, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49,
+0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b, 0x61, 0x6b, 0x65,
+0x3b, 0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b,
+0x2bb, 0x4f, 0x6b, 0x61, 0x6b, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x77,
+0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61,
+0x70, 0x61, 0x49, 0x61, 0x6e, 0x2e, 0x3b, 0x50, 0x65, 0x70, 0x2e, 0x3b,
+0x4d, 0x61, 0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x49, 0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c, 0x2e, 0x3b,
+0x2bb, 0x41, 0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, 0x3b, 0x2bb, 0x4f,
+0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77, 0x2e, 0x3b, 0x4b, 0x65, 0x6b, 0x2e,
+0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8,
+0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de,
+0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9,
+0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5de,
+0x5d1, 0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0,
+0x5d5, 0x5d1, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5d1, 0x5e8, 0x5d9,
+0x5e0, 0x5d5, 0x5f3, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5e8, 0x5e5,
+0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5,
+0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5f3,
+0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5f3, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5f3, 0x3b, 0x5e0,
+0x5d5, 0x5d1, 0x5f3, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5f3, 0x91c, 0x928, 0x935, 0x930,
+0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930,
+0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908,
+0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905,
+0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x902, 0x92c, 0x930, 0x3b,
+0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c,
+0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x91c, 0x928, 0x970, 0x3b,
+0x92b, 0x93c, 0x930, 0x970, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905,
+0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928,
+0x3b, 0x91c, 0x941, 0x932, 0x970, 0x3b, 0x905, 0x917, 0x970, 0x3b, 0x938, 0x93f,
+0x924, 0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x970, 0x3b, 0x928, 0x935,
+0x970, 0x3b, 0x926, 0x93f, 0x938, 0x970, 0x91c, 0x3b, 0x92b, 0x93c, 0x3b, 0x92e,
+0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b,
+0x905, 0x3b, 0x938, 0x93f, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x6a,
+0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1,
+0x72, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x69, 0x75, 0x73, 0x3b, 0xe1, 0x70,
+0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a, 0x75, 0x73, 0x3b,
+0x6a, 0xfa, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6c, 0x69, 0x75,
+0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x7a, 0x74, 0x75, 0x73, 0x3b,
+0x73, 0x7a, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
+0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d,
+0xe1, 0x72, 0x63, 0x2e, 0x3b, 0xe1, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0xe1,
+0x6a, 0x2e, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e,
+0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x2e,
+0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64,
+0x65, 0x63, 0x2e, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1, 0x3b, 0x4d,
+0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b,
+0x4e, 0x3b, 0x44, 0x6a, 0x61, 0x6e, 0xfa, 0x61, 0x72, 0x3b, 0x66, 0x65,
+0x62, 0x72, 0xfa, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61,
+0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e,
+0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b, 0xe1, 0x67, 0xfa, 0x73, 0x74,
+0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
+0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0xf3, 0x76, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61,
+0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0xed, 0x3b,
+0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0xe1, 0x67,
+0xfa, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e,
+0x3b, 0x6e, 0xf3, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x4a, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b,
+0xc1, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x65, 0x6e,
+0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x1ee5, 0x77,
+0x61, 0x72, 0x1ecb, 0x3b, 0x4d, 0x61, 0x61, 0x63, 0x68, 0x1ecb, 0x3b, 0x45,
+0x70, 0x72, 0x65, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75,
+0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x1ecb, 0x3b, 0x1ecc, 0x67, 0x1ecd,
+0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x1ecc, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a,
+0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x45,
+0x70, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a,
+0x75, 0x6c, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x1ecc,
+0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x4a, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b,
+0x1ecc, 0x3b, 0x53, 0x3b, 0x1ecc, 0x3b, 0x4e, 0x3b, 0x44, 0x75, 0x111, 0x111,
+0xe2, 0x69, 0x76, 0x65, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x75,
+0x6f, 0x76, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75,
+0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0xe1,
+0x14b, 0x75, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x76, 0x79, 0x65,
+0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0x69,
+0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69,
+0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x70, 0x6f, 0x72, 0x67, 0x65, 0x6d,
+0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x6d, 0xe1,
+0xe1, 0x6e, 0x75, 0x3b, 0x72, 0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x6d,
+0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x6d,
+0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x6d,
+0xe1, 0xe1, 0x6e, 0x75, 0x75, 0x111, 0x69, 0x76, 0x3b, 0x6b, 0x75, 0x6f,
+0x76, 0xe2, 0x3b, 0x6e, 0x6a, 0x75, 0x68, 0x10d, 0xe2, 0x3b, 0x63, 0x75,
+0xe1, 0x14b, 0x75, 0x69, 0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x3b, 0x6b,
+0x65, 0x73, 0x69, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x3b, 0x70,
+0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x3b, 0x72,
+0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d,
+0xe2, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x55, 0x3b, 0x4b, 0x3b,
+0x4e, 0x4a, 0x3b, 0x43, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x50,
+0x3b, 0x10c, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4a, 0x4a, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69,
+0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c,
+0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75,
+0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53,
+0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61,
+0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70,
+0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
+0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x6a, 0x61, 0x6e,
+0x75, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
+0x72, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x6f, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75,
+0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b,
+0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x63,
+0x65, 0x6d, 0x62, 0x72, 0x65, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62,
+0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69,
+0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67,
+0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76,
+0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66,
+0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65,
+0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a,
+0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0xed, 0x3b, 0x61, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62,
+0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e,
+0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75,
+0x6c, 0xed, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74,
+0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b,
+0x64, 0x65, 0x63, 0x2e, 0x152d, 0x14d0, 0x14c4, 0x140a, 0x14d5, 0x3b, 0x1555, 0x155d,
+0x1557, 0x140a, 0x14d5, 0x3b, 0x14ab, 0x1466, 0x14ef, 0x3b, 0x140a, 0x1403, 0x1449, 0x1433,
+0x14d7, 0x3b, 0x14aa, 0x1403, 0x3b, 0x152b, 0x14c2, 0x3b, 0x152a, 0x14da, 0x1403, 0x3b,
+0x140a, 0x1405, 0x14a1, 0x148d, 0x14ef, 0x3b, 0x14ef, 0x144e, 0x1431, 0x1546, 0x3b, 0x1406,
+0x1466, 0x1451, 0x155d, 0x1559, 0x3b, 0x14c4, 0x1555, 0x1431, 0x1546, 0x3b, 0x144e, 0x14ef,
+0x1431, 0x1546, 0x45, 0x61, 0x6e, 0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61,
+0x62, 0x68, 0x72, 0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41,
+0x69, 0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x74,
+0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x65, 0x61,
+0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x61,
+0x73, 0x61, 0x3b, 0x4d, 0x65, 0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68,
+0x61, 0x69, 0x72, 0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61, 0x64, 0x68,
+0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53, 0x61, 0x6d,
+0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x61, 0x69, 0x67,
+0x45, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x3b, 0x4d, 0xe1,
+0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65, 0x61, 0x6c,
+0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b,
+0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x44, 0x46,
+0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x4e, 0x6f, 0x6c,
+0x6c, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d,
+0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e,
+0x67, 0x65, 0x6e, 0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62,
+0x72, 0x61, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67, 0x67, 0x69, 0x6f,
+0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x6f, 0x3b, 0x6c, 0x75, 0x67, 0x6c,
+0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65,
+0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f,
+0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x67, 0x65, 0x6e,
+0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72,
+0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x6c, 0x75, 0x67,
+0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74,
+0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x4a, 0x61, 0x6e, 0x3b,
+0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x48, 0x79, 0x77, 0x61, 0x6e,
+0x20, 0x41, 0x331, 0x79, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x48, 0x79, 0x77,
+0x61, 0x6e, 0x20, 0x41, 0x331, 0x68, 0x77, 0x61, 0x3b, 0x48, 0x79, 0x77,
+0x61, 0x6e, 0x20, 0x41, 0x331, 0x74, 0x61, 0x74, 0x3b, 0x48, 0x79, 0x77,
+0x61, 0x6e, 0x20, 0x41, 0x331, 0x6e, 0x61, 0x61, 0x69, 0x3b, 0x48, 0x79,
+0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x70, 0x66, 0x77, 0x6f, 0x6e, 0x3b,
+0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x6b, 0x69, 0x74, 0x61,
+0x74, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x74, 0x79,
+0x69, 0x72, 0x69, 0x6e, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41,
+0x331, 0x6e, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e,
+0x20, 0x41, 0x331, 0x6b, 0x75, 0x6d, 0x76, 0x69, 0x72, 0x69, 0x79, 0x69,
+0x6e, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b,
+0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x20,
+0x42, 0x2019, 0x61, 0x331, 0x79, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x48, 0x79,
+0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x20, 0x42, 0x2019, 0x61,
+0x331, 0x68, 0x77, 0x61, 0x41, 0x331, 0x79, 0x72, 0x3b, 0x41, 0x331, 0x68,
+0x77, 0x3b, 0x41, 0x331, 0x74, 0x61, 0x3b, 0x41, 0x331, 0x6e, 0x61, 0x3b,
+0x41, 0x331, 0x70, 0x66, 0x3b, 0x41, 0x331, 0x6b, 0x69, 0x3b, 0x41, 0x331,
+0x74, 0x79, 0x3b, 0x41, 0x331, 0x6e, 0x69, 0x3b, 0x41, 0x331, 0x6b, 0x75,
+0x3b, 0x53, 0x77, 0x61, 0x3b, 0x53, 0x62, 0x79, 0x3b, 0x53, 0x62, 0x68,
+0x53, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x46, 0xe9, 0x62, 0x69, 0x72,
+0x69, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x62, 0x75, 0x72,
+0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x65, 0x14b, 0x3b,
+0x53, 0xfa, 0x75, 0x79, 0x65, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65,
+0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72,
+0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x72, 0x53, 0x61, 0x3b,
+0x46, 0x65, 0x3b, 0x4d, 0x61, 0x3b, 0x41, 0x62, 0x3b, 0x4d, 0x65, 0x3b,
+0x53, 0x75, 0x3b, 0x53, 0xfa, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x3b,
+0x4f, 0x6b, 0x3b, 0x4e, 0x6f, 0x3b, 0x44, 0x65, 0x53, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x55, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x61, 0x6e, 0x65, 0x72,
+0x75, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x4d, 0x61,
+0x72, 0x73, 0x75, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61,
+0x69, 0x75, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x75, 0x3b, 0x4a, 0x75, 0x6c,
+0x68, 0x75, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x53, 0x65,
+0x74, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72,
+0x75, 0x3b, 0x4e, 0x75, 0x76, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x44,
+0x69, 0x7a, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x4a, 0x61, 0x6e, 0x3b, 0x46,
+0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d,
+0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41,
+0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e,
+0x75, 0x76, 0x3b, 0x44, 0x69, 0x7a, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79,
+0x65, 0x72, 0x3b, 0x46, 0x75, 0x1e5b, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x263,
+0x72, 0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d,
+0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59,
+0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x74,
+0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b,
+0x4e, 0x75, 0x6e, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x44, 0x75, 0x1e7,
+0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72,
+0x3b, 0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79,
+0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63,
+0x3b, 0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x57, 0x61, 0x6d,
+0x3b, 0x44, 0x75, 0x1e7, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b,
+0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79, 0x3b,
+0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b,
+0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x4e, 0x75, 0x6e, 0x3b,
+0x44, 0x75, 0x1e7, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x4d,
+0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e,
+0x3b, 0x44, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b,
+0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x57, 0x3b,
+0x44, 0x70, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x77, 0x61, 0x6e, 0x6a, 0x61,
+0x3b, 0x6d, 0x62, 0x69, 0x79, 0x254, 0x20, 0x6d, 0x25b, 0x6e, 0x64, 0x6f,
+0x14b, 0x67, 0x254, 0x3b, 0x4e, 0x79, 0x254, 0x6c, 0x254, 0x6d, 0x62, 0x254,
+0x14b, 0x67, 0x254, 0x3b, 0x4d, 0x254, 0x6e, 0x254, 0x20, 0x14b, 0x67, 0x62,
+0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x14b, 0x67, 0x77, 0x25b,
+0x20, 0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x75, 0x14b,
+0x67, 0x77, 0x25b, 0x3b, 0x66, 0x25b, 0x3b, 0x6e, 0x6a, 0x61, 0x70, 0x69,
+0x3b, 0x6e, 0x79, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x4d, 0x31, 0x31, 0x3b,
+0x253, 0x75, 0x6c, 0x253, 0x75, 0x73, 0x25b, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x61, 0x72,
+0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x72, 0x69,
+0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75,
+0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x67,
+0x67, 0x75, 0x73, 0x74, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x61, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72,
+0x69, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x3b,
+0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x6a, 0x61, 0x6e,
+0x75, 0x61, 0x61, 0x72, 0x69, 0x70, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75,
+0x61, 0x61, 0x72, 0x69, 0x70, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x69, 0x70,
+0x3b, 0x61, 0x70, 0x72, 0x69, 0x69, 0x6c, 0x69, 0x70, 0x3b, 0x6d, 0x61,
+0x61, 0x6a, 0x69, 0x70, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x70, 0x3b,
+0x6a, 0x75, 0x75, 0x6c, 0x69, 0x70, 0x3b, 0x61, 0x67, 0x67, 0x75, 0x73,
+0x74, 0x69, 0x70, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61,
+0x72, 0x69, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x69,
+0x70, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x70,
+0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x69, 0x70, 0x6a,
+0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
+0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74,
+0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63,
+0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x2019, 0x61, 0x74,
+0x79, 0x61, 0x61, 0x74, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61, 0x61,
+0x6d, 0x6f, 0x3b, 0x49, 0x77, 0x6f, 0x6f, 0x74, 0x6b, 0x75, 0x75, 0x74,
+0x3b, 0x4d, 0x61, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x50, 0x61, 0x61, 0x67,
+0x69, 0x3b, 0x4e, 0x67, 0x2019, 0x65, 0x69, 0x79, 0x65, 0x65, 0x74, 0x3b,
+0x52, 0x6f, 0x6f, 0x70, 0x74, 0x75, 0x69, 0x3b, 0x42, 0x75, 0x72, 0x65,
+0x65, 0x74, 0x3b, 0x45, 0x70, 0x65, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69,
+0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x20, 0x74,
+0x61, 0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64,
+0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20, 0x61, 0x65, 0x6e, 0x67, 0x2019,
+0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x61,
+0x3b, 0x49, 0x77, 0x6f, 0x3b, 0x4d, 0x61, 0x6d, 0x3b, 0x50, 0x61, 0x61,
+0x3b, 0x4e, 0x67, 0x65, 0x3b, 0x52, 0x6f, 0x6f, 0x3b, 0x42, 0x75, 0x72,
+0x3b, 0x45, 0x70, 0x65, 0x3b, 0x4b, 0x70, 0x74, 0x3b, 0x4b, 0x70, 0x61,
+0x4d, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x50, 0x3b,
+0x4e, 0x3b, 0x52, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x4d,
+0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b,
+0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129,
+0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74,
+0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61,
+0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x61, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74,
+0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x75,
+0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61,
+0x20, 0x6e, 0x79, 0x61, 0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x77, 0x61,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d,
+0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69,
+0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75,
+0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x129, 0x6d, 0x77, 0x65, 0x3b, 0x4d,
+0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69,
+0x20, 0x6e, 0x61, 0x20, 0x69, 0x6c, 0x129, 0x4d, 0x62, 0x65, 0x3b, 0x4b,
+0x65, 0x6c, 0x3b, 0x4b, 0x74, 0x169, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b,
+0x74, 0x6e, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x6f, 0x3b, 0x4e,
+0x79, 0x61, 0x3b, 0x4b, 0x6e, 0x64, 0x3b, 0x128, 0x6b, 0x75, 0x3b, 0x128,
+0x6b, 0x6d, 0x3b, 0x128, 0x6b, 0x6c, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b,
+0x128, 0x3b, 0x128, 0x3b, 0x128, 0xc9c, 0xca8, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcab,
+0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd,
+0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae,
+0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b,
+0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f,
+0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0xcac,
+0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1,
+0xcbf, 0xcb8, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0xc9c, 0xca8, 0x3b, 0xcab, 0xcc6,
+0xcac, 0xccd, 0xcb0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f,
+0xcaa, 0xccd, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd,
+0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6, 0xcaa,
+0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8,
+0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xc9c, 0xca8, 0xcb5,
+0xcb0, 0xcbf, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b,
+0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf,
+0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2,
+0xcc8, 0x3b, 0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa,
+0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8,
+0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xc9c, 0x3b, 0xcab,
+0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8f, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2,
+0x3b, 0xc9c, 0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8,
+0x3b, 0xca1, 0xcbf, 0x62c, 0x646, 0x624, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x624,
+0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631,
+0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b,
+0x62c, 0x648, 0x657, 0x644, 0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a,
+0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657,
+0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645,
+0x628, 0x631, 0x62c, 0x646, 0x624, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x624, 0x631,
+0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc,
+0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c,
+0x64f, 0x644, 0x64e, 0x6d2, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a,
+0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657, 0x628, 0x631, 0x3b,
+0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64e, 0x633, 0x64e, 0x645, 0x628,
+0x64e, 0x631, 0x62c, 0x646, 0x624, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x624, 0x631,
+0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc,
+0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c,
+0x64f, 0x644, 0x64e, 0x6d2, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a,
+0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657, 0x628, 0x631, 0x3b,
+0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c,
+0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c,
+0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x91c, 0x928,
+0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e,
+0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b,
+0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908,
+0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x924, 0x941, 0x902, 0x92c,
+0x930, 0x3b, 0x905, 0x915, 0x924, 0x941, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x928,
+0x935, 0x942, 0x92e, 0x92c, 0x930, 0x3b, 0x926, 0x938, 0x942, 0x92e, 0x92c, 0x930,
+0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940,
+0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948,
+0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932,
+0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x924, 0x92e,
+0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928,
+0x935, 0x92e, 0x92c, 0x930, 0x3b, 0x926, 0x938, 0x92e, 0x92c, 0x930, 0x91c, 0x928,
+0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e,
+0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b,
+0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908,
+0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x924, 0x941, 0x902, 0x92c,
+0x930, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935,
+0x942, 0x92e, 0x92c, 0x930, 0x3b, 0x926, 0x938, 0x942, 0x92e, 0x92c, 0x930, 0x91c,
+0x3b, 0x92b, 0x93c, 0x3b, 0x92e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x3b,
+0x91c, 0x3b, 0x905, 0x3b, 0x938, 0x3b, 0x913, 0x3b, 0x928, 0x3b, 0x926, 0x49a,
+0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x410, 0x49b, 0x43f, 0x430, 0x43d, 0x3b,
+0x41d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x421, 0x4d9, 0x443, 0x456, 0x440,
+0x3b, 0x41c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x41c, 0x430, 0x443, 0x441, 0x44b,
+0x43c, 0x3b, 0x428, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x422, 0x430, 0x43c, 0x44b,
+0x437, 0x3b, 0x49a, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49a,
+0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49a, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b,
+0x416, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x49b, 0x430, 0x4a3,
+0x442, 0x430, 0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x43d, 0x430,
+0x443, 0x440, 0x44b, 0x437, 0x3b, 0x441, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x43c,
+0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x43c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b,
+0x448, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b,
+0x49b, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49b, 0x430, 0x437,
+0x430, 0x43d, 0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x436, 0x435,
+0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x49b, 0x430, 0x4a3, 0x2e, 0x3b,
+0x430, 0x49b, 0x43f, 0x2e, 0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9,
+0x443, 0x2e, 0x3b, 0x43c, 0x430, 0x43c, 0x2e, 0x3b, 0x43c, 0x430, 0x443, 0x2e,
+0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, 0x2e, 0x3b, 0x49b,
+0x44b, 0x440, 0x2e, 0x3b, 0x49b, 0x430, 0x437, 0x2e, 0x3b, 0x49b, 0x430, 0x440,
+0x2e, 0x3b, 0x436, 0x435, 0x43b, 0x2e, 0x49a, 0x3b, 0x410, 0x3b, 0x41d, 0x3b,
+0x421, 0x3b, 0x41c, 0x3b, 0x41c, 0x3b, 0x428, 0x3b, 0x422, 0x3b, 0x49a, 0x3b,
+0x49a, 0x3b, 0x49a, 0x3b, 0x416, 0x1798, 0x1780, 0x179a, 0x17b6, 0x3b, 0x1780, 0x17bb,
+0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b8, 0x1793, 0x17b6, 0x3b, 0x1798, 0x17c1,
+0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f, 0x1797, 0x17b6, 0x3b, 0x1798, 0x17b7, 0x1790, 0x17bb,
+0x1793, 0x17b6, 0x3b, 0x1780, 0x1780, 0x17d2, 0x1780, 0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8,
+0x17a0, 0x17b6, 0x3b, 0x1780, 0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, 0x17bb, 0x179b,
+0x17b6, 0x3b, 0x179c, 0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780, 0x17b6, 0x3b, 0x1792,
+0x17d2, 0x1793, 0x17bc, 0x1798, 0x3b, 0x1780, 0x3b, 0x1798, 0x3b, 0x1798, 0x3b, 0x17a7,
+0x3b, 0x1798, 0x3b, 0x1780, 0x3b, 0x179f, 0x3b, 0x1780, 0x3b, 0x178f, 0x3b, 0x179c,
+0x3b, 0x1792, 0x4e, 0x6a, 0x65, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x72, 0x129,
+0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61,
+0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77,
+0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65,
+0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20,
+0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e,
+0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61,
+0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65,
+0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69,
+0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4e, 0x64, 0x69,
+0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x45, 0x4e, 0x3b, 0x57, 0x4b,
+0x52, 0x3b, 0x57, 0x47, 0x54, 0x3b, 0x57, 0x4b, 0x4e, 0x3b, 0x57, 0x54,
+0x4e, 0x3b, 0x57, 0x54, 0x44, 0x3b, 0x57, 0x4d, 0x4a, 0x3b, 0x57, 0x4e,
+0x4e, 0x3b, 0x57, 0x4b, 0x44, 0x3b, 0x57, 0x49, 0x4b, 0x3b, 0x57, 0x4d,
+0x57, 0x3b, 0x44, 0x49, 0x54, 0x4a, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x4b,
+0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49,
+0x3b, 0x49, 0x3b, 0x44, 0x4d, 0x75, 0x74, 0x61, 0x72, 0x61, 0x6d, 0x61,
+0x3b, 0x47, 0x61, 0x73, 0x68, 0x79, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65,
+0x3b, 0x57, 0x65, 0x72, 0x75, 0x72, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x74,
+0x61, 0x3b, 0x47, 0x69, 0x63, 0x75, 0x72, 0x61, 0x73, 0x69, 0x3b, 0x4b,
+0x61, 0x6d, 0x65, 0x6e, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e,
+0x67, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x3b, 0x4e, 0x7a,
+0x65, 0x6c, 0x69, 0x3b, 0x55, 0x6b, 0x77, 0x61, 0x6b, 0x69, 0x72, 0x61,
+0x3b, 0x55, 0x67, 0x75, 0x73, 0x68, 0x79, 0x69, 0x6e, 0x67, 0x6f, 0x3b,
+0x55, 0x6b, 0x75, 0x62, 0x6f, 0x7a, 0x61, 0x6d, 0x75, 0x74, 0x2e, 0x3b,
+0x67, 0x61, 0x73, 0x2e, 0x3b, 0x77, 0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
+0x74, 0x2e, 0x3b, 0x67, 0x69, 0x63, 0x2e, 0x3b, 0x6b, 0x61, 0x6d, 0x2e,
+0x3b, 0x6e, 0x79, 0x61, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x6e,
+0x7a, 0x65, 0x2e, 0x3b, 0x75, 0x6b, 0x77, 0x2e, 0x3b, 0x75, 0x67, 0x75,
+0x2e, 0x3b, 0x75, 0x6b, 0x75, 0x2e, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e,
+0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930,
+0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930,
+0x940, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
+0x932, 0x92f, 0x3b, 0x911, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x92a, 0x94d,
+0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x92c,
+0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b,
+0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x91c, 0x93e, 0x928, 0x947, 0x3b,
+0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a,
+0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x940, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942,
+0x928, 0x3b, 0x91c, 0x941, 0x932, 0x3b, 0x911, 0x917, 0x3b, 0x938, 0x92a, 0x94d,
+0x91f, 0x947, 0x902, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b,
+0x3b, 0x921, 0x93f, 0x938, 0x947, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33,
+0xc6d4, 0x3b, 0x34, 0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37,
+0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b, 0x31, 0x30, 0xc6d4, 0x3b,
+0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x17d, 0x61, 0x6e, 0x77, 0x69,
+0x79, 0x65, 0x3b, 0x46, 0x65, 0x65, 0x77, 0x69, 0x72, 0x69, 0x79, 0x65,
+0x3b, 0x4d, 0x61, 0x72, 0x73, 0x69, 0x3b, 0x41, 0x77, 0x69, 0x72, 0x69,
+0x6c, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x65, 0x14b, 0x3b, 0x17d,
+0x75, 0x79, 0x79, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x74,
+0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62,
+0x75, 0x72, 0x3b, 0x4e, 0x6f, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72,
+0x3b, 0x44, 0x65, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x17d, 0x61,
+0x6e, 0x3b, 0x46, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77,
+0x69, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x3b, 0x17d, 0x75, 0x79,
+0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x6f, 0x3b, 0x44, 0x65, 0x65, 0x17d, 0x3b, 0x46, 0x3b, 0x4d,
+0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x17d, 0x3b, 0x17d, 0x3b, 0x55, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x72, 0xea, 0x62, 0x65, 0x6e, 0x64,
+0x61, 0x6e, 0x3b, 0x73, 0x69, 0x62, 0x61, 0x74, 0x3b, 0x61, 0x64, 0x61,
+0x72, 0x3b, 0x6e, 0xee, 0x73, 0x61, 0x6e, 0x3b, 0x67, 0x75, 0x6c, 0x61,
+0x6e, 0x3b, 0x68, 0x65, 0x7a, 0xee, 0x72, 0x61, 0x6e, 0x3b, 0x74, 0xee,
+0x72, 0x6d, 0x65, 0x68, 0x3b, 0x74, 0x65, 0x62, 0x61, 0x78, 0x3b, 0xee,
+0x6c, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x74, 0x6d, 0x65, 0x68, 0x3b, 0x6d,
+0x69, 0x6a, 0x64, 0x61, 0x72, 0x3b, 0x62, 0x65, 0x72, 0x66, 0x61, 0x6e,
+0x62, 0x61, 0x72, 0x72, 0x62, 0x6e, 0x3b, 0x73, 0x62, 0x74, 0x3b, 0x61,
+0x64, 0x72, 0x3b, 0x6e, 0x73, 0x6e, 0x3b, 0x67, 0x6c, 0x6e, 0x3b, 0x68,
+0x7a, 0x72, 0x3b, 0x74, 0x72, 0x6d, 0x3b, 0x74, 0x62, 0x78, 0x3b, 0xee,
+0x6c, 0x6e, 0x3b, 0x63, 0x6f, 0x74, 0x3b, 0x6d, 0x6a, 0x64, 0x3b, 0x62,
+0x72, 0x66, 0x52, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4e, 0x3b, 0x47, 0x3b,
+0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0xce, 0x3b, 0x43, 0x3b, 0x4d, 0x3b,
+0x42, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0xe1, 0x68,
+0x72, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6d, 0x62,
+0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6c, 0x61, 0x6c,
+0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6e, 0x61, 0x3b, 0x6e,
+0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x61, 0x6e, 0x3b, 0x6e, 0x67,
+0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x75, 0xf3, 0x3b, 0x6e, 0x67, 0x77,
+0x25b, 0x6e, 0x20, 0x68, 0x25b, 0x6d, 0x62, 0x75, 0x25b, 0x72, 0xed, 0x3b,
+0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6c, 0x254, 0x6d, 0x62, 0x69, 0x3b,
+0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x72, 0x25b, 0x62, 0x76, 0x75, 0xe2,
+0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x3b, 0x6e,
+0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x20, 0x6e, 0x61, 0x76,
+0x1d4, 0x72, 0x3b, 0x6b, 0x72, 0xed, 0x73, 0x69, 0x6d, 0x69, 0x6e, 0x6e,
+0x67, 0x31, 0x3b, 0x6e, 0x67, 0x32, 0x3b, 0x6e, 0x67, 0x33, 0x3b, 0x6e,
+0x67, 0x34, 0x3b, 0x6e, 0x67, 0x35, 0x3b, 0x6e, 0x67, 0x36, 0x3b, 0x6e,
+0x67, 0x37, 0x3b, 0x6e, 0x67, 0x38, 0x3b, 0x6e, 0x67, 0x39, 0x3b, 0x6e,
+0x67, 0x31, 0x30, 0x3b, 0x6e, 0x67, 0x31, 0x31, 0x3b, 0x6b, 0x72, 0x69,
+0x73, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440,
+0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440,
+0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c,
+0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442,
+0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a,
+0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c,
+0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x42f, 0x43d, 0x432, 0x3b,
+0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430, 0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b,
+0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b,
+0x410, 0x432, 0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a, 0x442, 0x3b,
+0x41d, 0x43e, 0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x44f, 0x43d, 0x432, 0x2e, 0x3b,
+0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f,
+0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b,
+0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435,
+0x43d, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e,
+0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x57, 0x69, 0xf3, 0x74, 0x68, 0x65, 0x21f,
+0x69, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x68, 0x69, 0x79, 0xf3,
+0x21f, 0x65, 0x79, 0x75, 0x14b, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x49,
+0x161, 0x74, 0xe1, 0x77, 0x69, 0x10d, 0x68, 0x61, 0x79, 0x61, 0x7a, 0x61,
+0x14b, 0x20, 0x57, 0xed, 0x3b, 0x50, 0x21f, 0x65, 0x17e, 0xed, 0x74, 0x21f,
+0x6f, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70,
+0x65, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x57, 0xed, 0x70, 0x61,
+0x7a, 0x75, 0x6b, 0x21f, 0x61, 0x2d, 0x77, 0x61, 0x161, 0x74, 0xe9, 0x20,
+0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x70, 0x21f, 0xe1, 0x73, 0x61,
+0x70, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x73, 0xfa, 0x74, 0x21f,
+0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1,
+0x70, 0x65, 0x1e7, 0x69, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b,
+0x77, 0xe1, 0x70, 0x65, 0x2d, 0x6b, 0x61, 0x73, 0x6e, 0xe1, 0x20, 0x57,
+0xed, 0x3b, 0x57, 0x61, 0x6e, 0xed, 0x79, 0x65, 0x74, 0x75, 0x20, 0x57,
+0xed, 0x3b, 0x54, 0x21f, 0x61, 0x68, 0xe9, 0x6b, 0x61, 0x70, 0x161, 0x75,
+0x14b, 0x20, 0x57, 0xed, 0x4b, 0x289, 0x66, 0xfa, 0x6e, 0x67, 0x61, 0x74,
+0x268, 0x3b, 0x4b, 0x289, 0x6e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x289,
+0x6b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6b,
+0x75, 0x6d, 0x69, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x61, 0x6d,
+0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x64, 0x77, 0x61,
+0x61, 0x74, 0x61, 0x3b, 0x4b, 0x289, 0x6d, 0x289, 0x289, 0x6e, 0x63, 0x68,
+0x268, 0x3b, 0x4b, 0x289, 0x76, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x4b, 0x289,
+0x73, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79,
+0x69, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4b, 0x289,
+0x73, 0x61, 0x73, 0x61, 0x74, 0x289, 0x46, 0xfa, 0x6e, 0x67, 0x61, 0x74,
+0x268, 0x3b, 0x4e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x65, 0x65, 0x6e,
+0x64, 0x61, 0x3b, 0x49, 0x6b, 0xfa, 0x6d, 0x69, 0x3b, 0x49, 0x6e, 0x79,
+0x61, 0x6d, 0x62, 0x61, 0x6c, 0x61, 0x3b, 0x49, 0x64, 0x77, 0x61, 0x61,
+0x74, 0x61, 0x3b, 0x4d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x56,
+0x268, 0x268, 0x72, 0x268, 0x3b, 0x53, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x49,
+0x6e, 0x79, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x53, 0x61,
+0x73, 0x61, 0x74, 0x289, 0x46, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b,
+0x53, 0x3b, 0x53, 0xea1, 0xeb1, 0xe87, 0xe81, 0xead, 0xe99, 0x3b, 0xe81, 0xeb8,
+0xea1, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa,
+0xeb2, 0x3b, 0xe9e, 0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb4,
+0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5, 0xeb0, 0xe81, 0xebb, 0xe94,
+0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, 0x3b, 0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2,
+0x3b, 0xe95, 0xeb8, 0xea5, 0xeb2, 0x3b, 0xe9e, 0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b,
+0xe97, 0xeb1, 0xe99, 0xea7, 0xeb2, 0xea1, 0x2e, 0xe81, 0x2e, 0x3b, 0xe81, 0x2e,
+0xe9e, 0x2e, 0x3b, 0xea1, 0x2e, 0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e,
+0x3b, 0xe9e, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb4, 0x2e, 0xe96, 0x2e, 0x3b,
+0xe81, 0x2e, 0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81, 0x2e,
+0xe8d, 0x2e, 0x3b, 0xe95, 0x2e, 0xea5, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe88, 0x2e,
+0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69,
+0x75, 0x73, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x75,
+0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x75, 0x73, 0x3b, 0x41, 0x70,
+0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x69, 0x75, 0x73, 0x3b,
+0x49, 0x75, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x49, 0x75, 0x6c, 0x69, 0x75,
+0x73, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53,
+0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x63, 0x74,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x61,
+0x6e, 0x75, 0x61, 0x72, 0x69, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75,
+0x61, 0x72, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x69, 0x3b,
+0x41, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x69, 0x69,
+0x3b, 0x49, 0x75, 0x6e, 0x69, 0x69, 0x3b, 0x49, 0x75, 0x6c, 0x69, 0x69,
+0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70,
+0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x4f, 0x63, 0x74, 0x6f,
+0x62, 0x72, 0x69, 0x73, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
+0x69, 0x73, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73,
+0x49, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b,
+0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x3b,
+0x49, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b,
+0x4f, 0x63, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x6a,
+0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x66, 0x65, 0x62, 0x72,
+0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b,
+0x61, 0x70, 0x72, 0x12b, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x69, 0x6a,
+0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6c,
+0x69, 0x6a, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6f,
+0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62,
+0x72, 0x69, 0x73, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0x65, 0x62,
+0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x2e,
+0x3b, 0x6a, 0x16b, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73,
+0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f,
+0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x73, 0xe1, 0x6e, 0x7a, 0xe1,
+0x20, 0x79, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1,
+0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c,
+0xe9, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d,
+0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20,
+0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73, 0xe1, 0x6e,
+0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f,
+0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x6f,
+0x74, 0xf3, 0x62, 0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79,
+0x61, 0x20, 0x6e, 0x73, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e,
+0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d, 0x62, 0x65,
+0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69,
+0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61,
+0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20,
+0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d,
+0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20,
+0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d,
+0xed, 0x62, 0x61, 0x6c, 0xe9, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x62, 0x6c,
+0x3b, 0x6d, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x6c, 0x3b, 0x6d, 0x61, 0x69,
+0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x74,
+0x3b, 0x73, 0x74, 0x62, 0x3b, 0x254, 0x74, 0x62, 0x3b, 0x6e, 0x76, 0x62,
+0x3b, 0x64, 0x73, 0x62, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b,
+0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x254, 0x3b,
+0x6e, 0x3b, 0x64, 0x73, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b, 0x76, 0x61,
+0x73, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x6b, 0x6f, 0x76, 0x61, 0x73, 0x3b,
+0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x3b, 0x67, 0x65, 0x67,
+0x75, 0x17e, 0x117, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73,
+0x3b, 0x6c, 0x69, 0x65, 0x70, 0x61, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x6a,
+0x16b, 0x74, 0x69, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x69,
+0x73, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x61, 0x70,
+0x6b, 0x72, 0x69, 0x74, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64,
+0x69, 0x73, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f, 0x3b, 0x76, 0x61, 0x73,
+0x61, 0x72, 0x69, 0x6f, 0x3b, 0x6b, 0x6f, 0x76, 0x6f, 0x3b, 0x62, 0x61,
+0x6c, 0x61, 0x6e, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65, 0x67, 0x75,
+0x17e, 0x117, 0x73, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f,
+0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x70,
+0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a,
+0x6f, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x61, 0x70,
+0x6b, 0x72, 0x69, 0x10d, 0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64,
+0x17e, 0x69, 0x6f, 0x73, 0x61, 0x75, 0x73, 0x2e, 0x3b, 0x76, 0x61, 0x73,
+0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x2e, 0x3b, 0x62, 0x61, 0x6c, 0x2e, 0x3b,
+0x67, 0x65, 0x67, 0x2e, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x2e, 0x3b, 0x6c,
+0x69, 0x65, 0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x2e, 0x3b, 0x72,
+0x75, 0x67, 0x73, 0x2e, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x2e, 0x3b, 0x6c,
+0x61, 0x70, 0x6b, 0x72, 0x2e, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x2e,
+0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b,
+0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47, 0x6a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
+0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c,
+0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a,
+0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b,
+0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75,
+0x61, 0x72, 0x61, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70,
+0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x6a, 0x75,
+0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x61, 0x3b,
+0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72,
+0x61, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64,
+0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x6a, 0x61, 0x6e, 0x3b, 0x66,
+0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
+0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61,
+0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e,
+0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b,
+0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x77, 0x67, 0x2e, 0x3b, 0x73, 0x65,
+0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77, 0x2e,
+0x3b, 0x64, 0x65, 0x63, 0x2e, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x61, 0x72,
+0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x4d, 0xe4,
+0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41,
+0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x76, 0x65, 0x72, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65,
+0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e,
+0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75,
+0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e,
+0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44,
+0x65, 0x7a, 0x2e, 0x43, 0x69, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0xf9,
+0x69, 0x73, 0x68, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0xf2, 0x6c, 0x6f, 0x3b,
+0x4d, 0xf9, 0x75, 0x79, 0xe0, 0x3b, 0x4c, 0x75, 0x6d, 0xf9, 0x6e, 0x67,
+0xf9, 0x6c, 0xf9, 0x3b, 0x4c, 0x75, 0x66, 0x75, 0x69, 0x6d, 0x69, 0x3b,
+0x4b, 0x61, 0x62, 0xe0, 0x6c, 0xe0, 0x73, 0x68, 0xec, 0x70, 0xf9, 0x3b,
+0x4c, 0xf9, 0x73, 0x68, 0xec, 0x6b, 0xe0, 0x3b, 0x4c, 0x75, 0x74, 0x6f,
+0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x67, 0xf9, 0x64,
+0x69, 0x3b, 0x4b, 0x61, 0x73, 0x77, 0xe8, 0x6b, 0xe8, 0x73, 0xe8, 0x3b,
+0x43, 0x69, 0x73, 0x77, 0xe0, 0x43, 0x69, 0x6f, 0x3b, 0x4c, 0x75, 0x69,
+0x3b, 0x4c, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x75, 0x3b, 0x4c, 0x75, 0x6d,
+0x3b, 0x4c, 0x75, 0x66, 0x3b, 0x4b, 0x61, 0x62, 0x3b, 0x4c, 0x75, 0x73,
+0x68, 0x3b, 0x4c, 0x75, 0x74, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4b, 0x61,
+0x73, 0x3b, 0x43, 0x69, 0x73, 0x43, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4d,
+0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c,
+0x3b, 0x4b, 0x3b, 0x43, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20,
+0x41, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d,
+0x61, 0x72, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65,
+0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x44, 0x77,
+0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65,
+0x6e, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62,
+0x69, 0x63, 0x68, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20,
+0x41, 0x75, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20,
+0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x72, 0x69, 0x79, 0x6f, 0x3b,
+0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x6f, 0x72,
+0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4f, 0x63,
+0x68, 0x69, 0x6b, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0x20, 0x41, 0x70, 0x61, 0x72, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61,
+0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b,
+0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72,
+0x20, 0x67, 0x69, 0x20, 0x61, 0x72, 0x69, 0x79, 0x6f, 0x44, 0x41, 0x43,
+0x3b, 0x44, 0x41, 0x52, 0x3b, 0x44, 0x41, 0x44, 0x3b, 0x44, 0x41, 0x4e,
+0x3b, 0x44, 0x41, 0x48, 0x3b, 0x44, 0x41, 0x55, 0x3b, 0x44, 0x41, 0x4f,
+0x3b, 0x44, 0x41, 0x42, 0x3b, 0x44, 0x4f, 0x43, 0x3b, 0x44, 0x41, 0x50,
+0x3b, 0x44, 0x47, 0x49, 0x3b, 0x44, 0x41, 0x47, 0x43, 0x3b, 0x52, 0x3b,
+0x44, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b, 0x42, 0x3b,
+0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4,
+0x65, 0x72, 0x7a, 0x3b, 0x41, 0x62, 0x72, 0xeb, 0x6c, 0x6c, 0x3b, 0x4d,
+0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
+0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65,
+0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44,
+0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46,
+0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d,
+0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41,
+0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
+0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46,
+0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x65, 0x2e, 0x3b, 0x41, 0x62, 0x72,
+0x2e, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a,
+0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70,
+0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b,
+0x44, 0x65, 0x7a, 0x2e, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b,
+0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
+0x44, 0x65, 0x73, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444,
+0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442,
+0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
+0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433,
+0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440,
+0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d,
+0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c,
+0x432, 0x440, 0x438, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e,
+0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c,
+0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x2e, 0x3b, 0x458, 0x443, 0x43b, 0x2e,
+0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x2e, 0x3b, 0x43e,
+0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x2e, 0x3b, 0x434, 0x435, 0x43a,
+0x2e, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62,
+0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b,
+0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x61, 0x69,
+0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65,
+0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d,
+0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53,
+0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44,
+0x65, 0x73, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930,
+0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930,
+0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
+0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f,
+0x924, 0x902, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x942, 0x92c, 0x930,
+0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c,
+0x930, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930, 0x940,
+0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948,
+0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932,
+0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924,
+0x902, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b,
+0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930,
+0x91c, 0x928, 0x970, 0x3b, 0x92b, 0x930, 0x970, 0x3b, 0x92e, 0x93e, 0x930, 0x94d,
+0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b,
+0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x970, 0x3b, 0x905, 0x917, 0x970,
+0x3b, 0x938, 0x93f, 0x924, 0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x970,
+0x3b, 0x928, 0x935, 0x970, 0x3b, 0x926, 0x93f, 0x938, 0x970, 0x91c, 0x3b, 0x92b,
+0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c,
+0x941, 0x3b, 0x905, 0x3b, 0x938, 0x93f, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926,
+0x93f, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x77,
+0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x6f, 0x20, 0x75, 0x6e, 0x61, 0x79, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x72, 0x61,
+0x72, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20,
+0x75, 0x6e, 0x65, 0x63, 0x68, 0x65, 0x73, 0x68, 0x65, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x74, 0x68,
+0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f,
+0x20, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f,
+0x63, 0x68, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f,
+0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x6f, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d,
+0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20,
+0x6e, 0x61, 0x20, 0x79, 0x65, 0x6c, 0x2019, 0x6c, 0x69, 0x4b, 0x77, 0x61,
+0x3b, 0x55, 0x6e, 0x61, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x43, 0x68, 0x65,
+0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x63, 0x3b, 0x53, 0x61, 0x62,
+0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d,
+0x3b, 0x4d, 0x6f, 0x6a, 0x3b, 0x59, 0x65, 0x6c, 0x4b, 0x3b, 0x55, 0x3b,
+0x52, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x4e, 0x3b,
+0x54, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x59, 0x4d, 0x77, 0x65, 0x64, 0x69,
+0x20, 0x4e, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77,
+0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x54, 0x61, 0x74, 0x75, 0x3b,
+0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x63, 0x68,
+0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65,
+0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f,
+0x20, 0x6e, 0x61, 0x20, 0x55, 0x6d, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20,
+0x6e, 0x61, 0x20, 0x4d, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77,
+0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e,
+0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b,
+0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79,
+0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63,
+0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e,
+0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20,
+0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x3b,
+0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79,
+0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e,
+0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x4a, 0x61, 0x6e, 0x6f, 0x61, 0x72,
+0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x4d,
+0x61, 0x72, 0x74, 0x73, 0x61, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79,
+0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x61, 0x3b, 0x4a, 0x6f,
+0x6c, 0x61, 0x79, 0x3b, 0x41, 0x6f, 0x67, 0x6f, 0x73, 0x69, 0x74, 0x72,
+0x61, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b,
+0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x61,
+0x6d, 0x62, 0x72, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x61, 0x6d, 0x62, 0x72,
+0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72,
+0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e,
+0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x41, 0x6f, 0x67, 0x3b, 0x53, 0x65, 0x70,
+0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73,
+0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30,
+0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0xd1a, 0xd4d, 0xd1a, 0xd4d,
+0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd7d, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d,
+0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17,
+0xd38, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31,
+0xd4d, 0xd31, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd12, 0xd15, 0xd4d, 0x200c, 0xd1f, 0xd4b,
+0xd2c, 0xd7c, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd21, 0xd3f, 0xd38,
+0xd02, 0xd2c, 0xd7c, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30,
+0xd41, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b,
+0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32,
+0xd48, 0x3b, 0xd13, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31,
+0xd02, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0x3b, 0xd28, 0xd35, 0xd02, 0x3b,
+0xd21, 0xd3f, 0xd38, 0xd02, 0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b,
+0xd0f, 0x3b, 0xd2e, 0xd46, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b,
+0xd13, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x4a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75,
+0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x69,
+0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
+0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, 0x70,
+0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b,
+0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x4f, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x62c, 0x627, 0x646, 0x648, 0x627,
+0x631, 0x64a, 0x3b, 0x641, 0x64a, 0x628, 0x648, 0x627, 0x631, 0x64a, 0x3b, 0x645,
+0x686, 0x3b, 0x627, 0x6a4, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x64a, 0x3b, 0x62c,
+0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x64a, 0x3b, 0x762, 0x648, 0x633,
+0x3b, 0x633, 0x64a, 0x6a4, 0x62a, 0x64a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x648,
+0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x6cf, 0x64a, 0x645, 0x628,
+0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x64a, 0x645, 0x628, 0x631, 0x4a, 0x61, 0x6e,
+0x6e, 0x61, 0x72, 0x3b, 0x46, 0x72, 0x61, 0x72, 0x3b, 0x4d, 0x61, 0x72,
+0x7a, 0x75, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x6a,
+0x6a, 0x75, 0x3b, 0x120, 0x75, 0x6e, 0x6a, 0x75, 0x3b, 0x4c, 0x75, 0x6c,
+0x6a, 0x75, 0x3b, 0x41, 0x77, 0x77, 0x69, 0x73, 0x73, 0x75, 0x3b, 0x53,
+0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x74,
+0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
+0x75, 0x3b, 0x44, 0x69, 0x10b, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x4a, 0x61,
+0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70,
+0x72, 0x3b, 0x4d, 0x65, 0x6a, 0x3b, 0x120, 0x75, 0x6e, 0x3b, 0x4c, 0x75,
+0x6c, 0x3b, 0x41, 0x77, 0x77, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74,
+0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x10b, 0x4a, 0x6e, 0x3b,
+0x46, 0x72, 0x3b, 0x4d, 0x7a, 0x3b, 0x41, 0x70, 0x3b, 0x4d, 0x6a, 0x3b,
+0x120, 0x6e, 0x3b, 0x4c, 0x6a, 0x3b, 0x41, 0x77, 0x3b, 0x53, 0x74, 0x3b,
+0x4f, 0x62, 0x3b, 0x4e, 0x76, 0x3b, 0x44, 0x10b, 0x4a, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x120, 0x3b, 0x4c, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9f1,
+0x9be, 0x9b0, 0x9bf, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9f1, 0x9be,
+0x9b0, 0x9bf, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd,
+0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c,
+0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x993, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b, 0x9b8,
+0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x993, 0x995,
+0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ac, 0x9c7, 0x9ae, 0x9cd, 0x9ac,
+0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x99c, 0x9a8,
+0x9c1, 0x9f1, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1,
+0x9f1, 0x9be, 0x9b0, 0x9bf, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f,
+0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8,
+0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x200c, 0x993, 0x997, 0x9b7, 0x9cd,
+0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0,
+0x3b, 0x993, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7,
+0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac,
+0x9b0, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1,
+0x3b, 0x9ae, 0x9be, 0x9b0, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x3b, 0x9ae,
+0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x3b, 0x986,
+0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x993, 0x995, 0x9cd, 0x99f,
+0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x99c, 0x9a8,
+0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9f1, 0x9be, 0x9b0, 0x9bf, 0x3b,
+0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2,
+0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be,
+0x987, 0x3b, 0x993, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae,
+0x9cd, 0x9ac, 0x9b0, 0x3b, 0x993, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b,
+0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7,
+0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae, 0x9be,
+0x9b0, 0x3b, 0x98f, 0x9aa, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b,
+0x99c, 0x9c1, 0x9b2, 0x3b, 0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x993, 0x3b, 0x9a8,
+0x9ac, 0x3b, 0x9a1, 0x9bf, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae, 0x9be,
+0x9b0, 0x3b, 0x98f, 0x9aa, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b,
+0x99c, 0x9c1, 0x9b2, 0x3b, 0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x993, 0x995, 0x3b,
+0x9a8, 0x9ac, 0x3b, 0x9a1, 0x9bf, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d,
+0x67, 0x65, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68, 0x69,
+0x61, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d,
+0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x65, 0x72, 0x69, 0x6c,
+0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61,
+0x6e, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x72,
+0x72, 0x65, 0x79, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c,
+0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61,
+0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x65, 0x72,
+0x72, 0x65, 0x79, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d,
+0x65, 0x65, 0x20, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x65,
+0x65, 0x20, 0x6e, 0x79, 0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b,
+0x4a, 0x2d, 0x67, 0x75, 0x65, 0x72, 0x3b, 0x54, 0x2d, 0x61, 0x72, 0x72,
+0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76,
+0x72, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e,
+0x3b, 0x4d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x2d,
+0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69,
+0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69,
+0x72, 0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d,
+0x2d, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x2d, 0x4e, 0x6f,
+0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x48, 0x101, 0x6e, 0x75, 0x65, 0x72, 0x65,
+0x3b, 0x50, 0x113, 0x70, 0x75, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x101, 0x65,
+0x68, 0x65, 0x3b, 0x100, 0x70, 0x65, 0x72, 0x69, 0x72, 0x61, 0x3b, 0x4d,
+0x65, 0x69, 0x3b, 0x48, 0x75, 0x6e, 0x65, 0x3b, 0x48, 0x16b, 0x72, 0x61,
+0x65, 0x3b, 0x100, 0x6b, 0x75, 0x68, 0x61, 0x74, 0x61, 0x3b, 0x48, 0x65,
+0x70, 0x65, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x4f, 0x6b, 0x65, 0x74, 0x6f,
+0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x65, 0x6d, 0x61, 0x3b, 0x54, 0x12b, 0x68,
+0x65, 0x6d, 0x61, 0x48, 0x101, 0x6e, 0x75, 0x65, 0x72, 0x65, 0x3b, 0x50,
+0x113, 0x70, 0x75, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x101, 0x65, 0x68, 0x65,
+0x3b, 0x100, 0x70, 0x65, 0x72, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x48, 0x75, 0x6e, 0x65, 0x3b, 0x48, 0x16b, 0x72, 0x61, 0x65,
+0x3b, 0x100, 0x6b, 0x75, 0x68, 0x61, 0x74, 0x61, 0x3b, 0x48, 0x65, 0x70,
+0x65, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x4f, 0x6b, 0x65, 0x74, 0x6f, 0x70,
+0x61, 0x3b, 0x4e, 0x6f, 0x65, 0x6d, 0x61, 0x3b, 0x54, 0x12b, 0x68, 0x65,
+0x6d, 0x61, 0x48, 0x101, 0x6e, 0x3b, 0x50, 0x113, 0x70, 0x3b, 0x4d, 0x101,
+0x65, 0x3b, 0x100, 0x70, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x48, 0x75,
+0x6e, 0x3b, 0x48, 0x16b, 0x72, 0x3b, 0x100, 0x6b, 0x75, 0x3b, 0x48, 0x65,
+0x70, 0x3b, 0x4f, 0x6b, 0x65, 0x3b, 0x4e, 0x6f, 0x65, 0x3b, 0x54, 0x12b,
+0x68, 0x48, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x100, 0x3b, 0x4d, 0x3b, 0x48,
+0x3b, 0x48, 0x3b, 0x100, 0x3b, 0x48, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x54,
+0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c,
+0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d,
+0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b,
+0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x911, 0x917, 0x938,
+0x94d, 0x91f, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b,
+0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d,
+0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c,
+0x930, 0x91c, 0x93e, 0x928, 0x947, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941,
+0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f,
+0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948,
+0x3b, 0x911, 0x917, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x3b, 0x911,
+0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902,
+0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x91c, 0x93e, 0x3b, 0x92b, 0x947, 0x3b,
+0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x3b, 0x91c,
+0x941, 0x3b, 0x911, 0x3b, 0x938, 0x3b, 0x911, 0x3b, 0x928, 0x94b, 0x3b, 0x921,
+0x93f, 0x4f, 0x6c, 0x61, 0x64, 0x61, 0x6c, 0x289, 0x301, 0x3b, 0x41, 0x72,
+0xe1, 0x74, 0x3b, 0x186, 0x25b, 0x6e, 0x268, 0x301, 0x254, 0x268, 0x14b, 0x254,
+0x6b, 0x3b, 0x4f, 0x6c, 0x6f, 0x64, 0x6f, 0x79, 0xed, 0xf3, 0x72, 0xed,
+0xea, 0x20, 0x69, 0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4f, 0x6c,
+0x6f, 0x69, 0x6c, 0xe9, 0x70, 0x16b, 0x6e, 0x79, 0x12b, 0x113, 0x20, 0x69,
+0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4b, 0xfa, 0x6a, 0xfa, 0x254,
+0x72, 0x254, 0x6b, 0x3b, 0x4d, 0xf3, 0x72, 0x75, 0x73, 0xe1, 0x73, 0x69,
+0x6e, 0x3b, 0x186, 0x6c, 0x254, 0x301, 0x268, 0x301, 0x62, 0x254, 0x301, 0x72,
+0xe1, 0x72, 0x25b, 0x3b, 0x4b, 0xfa, 0x73, 0x68, 0xee, 0x6e, 0x3b, 0x4f,
+0x6c, 0x67, 0xed, 0x73, 0x61, 0x6e, 0x3b, 0x50, 0x289, 0x73, 0x68, 0x289,
+0x301, 0x6b, 0x61, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x14b, 0x289, 0x301, 0x73,
+0x44, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0xe1, 0x3b, 0x186, 0x25b, 0x6e, 0x3b,
+0x44, 0x6f, 0x79, 0x3b, 0x4c, 0xe9, 0x70, 0x3b, 0x52, 0x6f, 0x6b, 0x3b,
+0x53, 0xe1, 0x73, 0x3b, 0x42, 0x254, 0x301, 0x72, 0x3b, 0x4b, 0xfa, 0x73,
+0x3b, 0x47, 0xed, 0x73, 0x3b, 0x53, 0x68, 0x289, 0x301, 0x3b, 0x4e, 0x74,
+0x289, 0x301, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x3b, 0x641, 0x648, 0x631,
+0x6cc, 0x647, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc,
+0x644, 0x3b, 0x645, 0x647, 0x3b, 0x698, 0x648, 0x626, 0x646, 0x3b, 0x698, 0x648,
+0x626, 0x6cc, 0x647, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627,
+0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648,
+0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631, 0x4a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72,
+0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x128,
+0x70, 0x75, 0x72, 0x169, 0x3b, 0x4d, 0x129, 0x129, 0x3b, 0x4e, 0x6a, 0x75,
+0x6e, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x72, 0x61, 0x129, 0x3b, 0x41, 0x67,
+0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x169, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61,
+0x4a, 0x41, 0x4e, 0x3b, 0x46, 0x45, 0x42, 0x3b, 0x4d, 0x41, 0x43, 0x3b,
+0x128, 0x50, 0x55, 0x3b, 0x4d, 0x128, 0x128, 0x3b, 0x4e, 0x4a, 0x55, 0x3b,
+0x4e, 0x4a, 0x52, 0x3b, 0x41, 0x47, 0x41, 0x3b, 0x53, 0x50, 0x54, 0x3b,
+0x4f, 0x4b, 0x54, 0x3b, 0x4e, 0x4f, 0x56, 0x3b, 0x44, 0x45, 0x43, 0x4a,
+0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e,
+0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x69, 0x6d,
+0x259, 0x67, 0x20, 0x6d, 0x62, 0x65, 0x67, 0x74, 0x75, 0x67, 0x3b, 0x69,
+0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d,
+0x65, 0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69,
+0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77, 0x259, 0x300, 0x74,
+0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d,
+0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x69, 0x62, 0x254, 0x64, 0x3b,
+0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300,
+0x14b, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b,
+0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b, 0x69,
+0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69,
+0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20,
+0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x6d, 0x62, 0x65, 0x67, 0x74,
+0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62,
+0xec, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b, 0x63,
+0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67,
+0x77, 0x259, 0x300, 0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f,
+0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x69,
+0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9,
+0x6d, 0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69,
+0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b,
+0x75, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69,
+0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b, 0x69,
+0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x4d,
+0x31, 0x3b, 0x41, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4e, 0x34, 0x3b, 0x46,
+0x35, 0x3b, 0x49, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x49, 0x38, 0x3b, 0x4b,
+0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x41d, 0x44d,
+0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x425, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441,
+0x430, 0x440, 0x3b, 0x413, 0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430,
+0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x414, 0x4e9, 0x440, 0x4e9, 0x432,
+0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x422,
+0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440,
+0x3b, 0x417, 0x443, 0x440, 0x433, 0x430, 0x430, 0x434, 0x443, 0x433, 0x430, 0x430,
+0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x414, 0x43e, 0x43b, 0x43e, 0x43e, 0x434,
+0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x41d, 0x430,
+0x439, 0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440,
+0x3b, 0x415, 0x441, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x410, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440,
+0x20, 0x441, 0x430, 0x440, 0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d,
+0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440,
+0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e, 0x451, 0x440, 0x434,
+0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x43d, 0x44d, 0x433,
+0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x445,
+0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x433, 0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430,
+0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x434, 0x4e9, 0x440, 0x4e9, 0x432, 0x434,
+0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x442, 0x430,
+0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x437, 0x443, 0x440, 0x433, 0x430, 0x430, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440,
+0x20, 0x441, 0x430, 0x440, 0x3b, 0x434, 0x43e, 0x43b, 0x43e, 0x43e, 0x434, 0x443,
+0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x43d, 0x430, 0x439,
+0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x435, 0x441, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440,
+0x3b, 0x430, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d, 0x44d,
+0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x430, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e, 0x451, 0x440, 0x434, 0x443,
+0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x31, 0x2d, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x33, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x34, 0x2d, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x35, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x36, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x37, 0x2d, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x38, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x39, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x31, 0x30, 0x2d, 0x440,
+0x20, 0x441, 0x430, 0x440, 0x3b, 0x31, 0x31, 0x2d, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x31, 0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x49, 0x3b,
+0x49, 0x49, 0x3b, 0x49, 0x49, 0x49, 0x3b, 0x49, 0x56, 0x3b, 0x56, 0x3b,
+0x56, 0x49, 0x3b, 0x56, 0x49, 0x49, 0x3b, 0x56, 0x49, 0x49, 0x49, 0x3b,
+0x49, 0x58, 0x3b, 0x58, 0x3b, 0x58, 0x49, 0x3b, 0x58, 0x49, 0x49, 0x1828,
+0x1822, 0x182d, 0x1821, 0x1833, 0x1825, 0x182d, 0x1821, 0x1837, 0x20, 0x1830, 0x1820, 0x1837,
+0x180e, 0x1820, 0x3b, 0x182c, 0x1823, 0x1836, 0x1820, 0x1833, 0x1823, 0x182d, 0x1820, 0x1837,
+0x20, 0x1830, 0x1820, 0x1837, 0x202f, 0x1820, 0x3b, 0x182d, 0x1823, 0x1837, 0x182a, 0x1821,
+0x1833, 0x1823, 0x182d, 0x1820, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x202f, 0x1820, 0x3b,
+0x1833, 0x1825, 0x1837, 0x182a, 0x1821, 0x1833, 0x1825, 0x182d, 0x1821, 0x1837, 0x20, 0x1830,
+0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x1832, 0x1820, 0x182a, 0x1823, 0x1833, 0x1823, 0x182d,
+0x1820, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x202f, 0x1820, 0x3b, 0x1835, 0x1822, 0x1837,
+0x182d, 0x1823, 0x182d, 0x1820, 0x1833, 0x1823, 0x182d, 0x1820, 0x1837, 0x20, 0x1830, 0x1820,
+0x1837, 0x180e, 0x1820, 0x3b, 0x1832, 0x1823, 0x182f, 0x1823, 0x182d, 0x1820, 0x1833, 0x1823,
+0x182d, 0x1820, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x1828, 0x1820,
+0x1822, 0x182e, 0x1820, 0x1833, 0x1825, 0x182d, 0x1820, 0x1837, 0x20, 0x1830, 0x1820, 0x1837,
+0x180e, 0x1820, 0x3b, 0x1836, 0x1822, 0x1830, 0x1825, 0x1833, 0x1825, 0x182d, 0x1821, 0x1837,
+0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x1820, 0x1837, 0x182a, 0x1820, 0x1833,
+0x1823, 0x182d, 0x1820, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x1820,
+0x1837, 0x182a, 0x1820, 0x1828, 0x20, 0x1828, 0x1822, 0x182d, 0x1821, 0x1833, 0x1825, 0x182d,
+0x1821, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x1820, 0x1837, 0x182a,
+0x1820, 0x1828, 0x20, 0x182c, 0x1823, 0x1836, 0x1820, 0x1833, 0x1823, 0x182d, 0x1820, 0x1837,
+0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x31, 0x202f, 0x180a, 0x1837, 0x20, 0x1830,
+0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x32, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820,
+0x1837, 0x180e, 0x1820, 0x3b, 0x33, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e,
+0x1820, 0x3b, 0x34, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820,
+0x3b, 0x35, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b,
+0x36, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x37,
+0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x38, 0x202f,
+0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x39, 0x202f, 0x180a,
+0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x31, 0x30, 0x20, 0x180a,
+0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x31, 0x31, 0x180a, 0x1837,
+0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x31, 0x32, 0x180a, 0x1837, 0x20,
+0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x31, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820,
+0x1837, 0x180e, 0x1820, 0x3b, 0x32, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837,
+0x180e, 0x1820, 0x3b, 0x33, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820,
+0x3b, 0x34, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b,
+0x35, 0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x36,
+0x202f, 0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x37, 0x202f,
+0x180a, 0x1837, 0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x38, 0x180a, 0x1837,
+0x20, 0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x39, 0x20, 0x180a, 0x1837, 0x20,
+0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x31, 0x30, 0x20, 0x180a, 0x1837, 0x20,
+0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x31, 0x31, 0x20, 0x180a, 0x1837, 0x20,
+0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x3b, 0x31, 0x32, 0x20, 0x180a, 0x1837, 0x20,
+0x1830, 0x1820, 0x1837, 0x180e, 0x1820, 0x7a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b,
+0x66, 0x65, 0x76, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x73,
+0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69,
+0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x79, 0x65, 0x3b, 0x6f, 0x75, 0x74, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62,
+0x3b, 0x6e, 0x6f, 0x76, 0x61, 0x6d, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6d,
+0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x76, 0x72, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a,
+0x69, 0x6c, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f,
+0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x7a, 0x3b,
+0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x7a, 0x3b,
+0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x46, 0x129, 0x69,
+0x20, 0x4c, 0x6f, 0x6f, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b,
+0x6c, 0x61, 0x14b, 0x6e, 0x65, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61,
+0x6b, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x61, 0x72,
+0x66, 0x6f, 0x6f, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x1dd, 0x75, 0x75, 0x74,
+0x1dd, 0x62, 0x69, 0x6a, 0x61, 0x14b, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b,
+0x67, 0x77, 0xe3, 0x61, 0x66, 0x61, 0x68, 0x62, 0x69, 0x69, 0x3b, 0x4d,
+0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x6c, 0x69, 0x69, 0x3b,
+0x4d, 0x61, 0x64, 0x1dd, 0x6d, 0x62, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69,
+0x20, 0x44, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20,
+0x4d, 0x75, 0x6e, 0x64, 0x61, 0x14b, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x47,
+0x77, 0x61, 0x68, 0x6c, 0x6c, 0x65, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x59,
+0x75, 0x72, 0x75, 0x46, 0x4c, 0x4f, 0x3b, 0x43, 0x4c, 0x41, 0x3b, 0x43,
+0x4b, 0x49, 0x3b, 0x46, 0x4d, 0x46, 0x3b, 0x4d, 0x41, 0x44, 0x3b, 0x4d,
+0x42, 0x49, 0x3b, 0x4d, 0x4c, 0x49, 0x3b, 0x4d, 0x41, 0x4d, 0x3b, 0x46,
+0x44, 0x45, 0x3b, 0x46, 0x4d, 0x55, 0x3b, 0x46, 0x47, 0x57, 0x3b, 0x46,
+0x59, 0x55, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x44, 0x3b,
+0x42, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x57, 0x3b,
+0x59, 0x52, 0x76, 0x66, 0x6f, 0x20, 0x43, 0x75, 0x73, 0x65, 0x3b, 0x48,
+0x6f, 0x74, 0x76, 0x6c, 0x65, 0x20, 0x48, 0x76, 0x73, 0x65, 0x3b, 0x54,
+0x61, 0x73, 0x61, 0x68, 0x63, 0x75, 0x63, 0x65, 0x3b, 0x54, 0x61, 0x73,
+0x61, 0x68, 0x63, 0x65, 0x20, 0x52, 0x61, 0x6b, 0x6b, 0x6f, 0x3b, 0x4b,
+0x65, 0x20, 0x48, 0x76, 0x73, 0x65, 0x3b, 0x4b, 0x76, 0x63, 0x6f, 0x20,
+0x48, 0x76, 0x73, 0x65, 0x3b, 0x48, 0x69, 0x79, 0x75, 0x63, 0x65, 0x3b,
+0x48, 0x69, 0x79, 0x6f, 0x20, 0x52, 0x61, 0x6b, 0x6b, 0x6f, 0x3b, 0x4f,
+0x74, 0x6f, 0x77, 0x6f, 0x73, 0x6b, 0x75, 0x63, 0x65, 0x3b, 0x4f, 0x74,
+0x6f, 0x77, 0x6f, 0x73, 0x6b, 0x76, 0x20, 0x52, 0x61, 0x6b, 0x6b, 0x6f,
+0x3b, 0x45, 0x68, 0x6f, 0x6c, 0x65, 0x3b, 0x52, 0x76, 0x66, 0x6f, 0x20,
+0x52, 0x61, 0x6b, 0x6b, 0x6f, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x6e, 0x69,
+0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x1c0, 0x67, 0xf4, 0x61, 0x62, 0x3b,
+0x1c0, 0x4b, 0x68, 0x75, 0x75, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c3,
+0x48, 0xf4, 0x61, 0x1c2, 0x6b, 0x68, 0x61, 0x69, 0x62, 0x3b, 0x1c3, 0x4b,
+0x68, 0x61, 0x69, 0x74, 0x73, 0xe2, 0x62, 0x3b, 0x47, 0x61, 0x6d, 0x61,
+0x1c0, 0x61, 0x65, 0x62, 0x3b, 0x1c2, 0x4b, 0x68, 0x6f, 0x65, 0x73, 0x61,
+0x6f, 0x62, 0x3b, 0x41, 0x6f, 0x1c1, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb,
+0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x54, 0x61, 0x72, 0x61, 0x1c0, 0x6b,
+0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c2,
+0x4e, 0xfb, 0x1c1, 0x6e, 0xe2, 0x69, 0x73, 0x65, 0x62, 0x3b, 0x1c0, 0x48,
+0x6f, 0x6f, 0x1c2, 0x67, 0x61, 0x65, 0x62, 0x3b, 0x48, 0xf4, 0x61, 0x73,
+0x6f, 0x72, 0x65, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x91c, 0x928, 0x935, 0x930,
+0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x905, 0x930, 0x940, 0x3b,
+0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x932,
+0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e,
+0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d,
+0x91f, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b,
+0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b,
+0x921, 0x93f, 0x938, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x91c, 0x928, 0x3b, 0x92b,
+0x947, 0x947, 0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a,
+0x94d, 0x930, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941,
+0x932, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b, 0x905, 0x915, 0x94d,
+0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f, 0x938, 0x947,
+0x91c, 0x928, 0x3b, 0x92b, 0x947, 0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a,
+0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928,
+0x3b, 0x91c, 0x941, 0x932, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b,
+0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921,
+0x93f, 0x938, 0x947, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73,
+0x25b, 0x300, 0x25b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20,
+0x6b, 0xe0, 0x67, 0x20, 0x6e, 0x67, 0x77, 0xf3, 0x14b, 0x3b, 0x73, 0x61,
+0x14b, 0x20, 0x6c, 0x65, 0x70, 0x79, 0xe8, 0x20, 0x73, 0x68, 0xfa, 0x6d,
+0x3b, 0x73, 0x61, 0x14b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b,
+0x20, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73,
+0x61, 0x14b, 0x20, 0x6e, 0x6a, 0xff, 0x6f, 0x6c, 0xe1, 0x2bc, 0x3b, 0x73,
+0x61, 0x14b, 0x20, 0x74, 0x79, 0x25b, 0x300, 0x62, 0x20, 0x74, 0x79, 0x25b,
+0x300, 0x62, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b,
+0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e,
+0x67, 0x77, 0x254, 0x300, 0x2bc, 0x20, 0x6d, 0x62, 0xff, 0x25b, 0x3b, 0x73,
+0x61, 0x14b, 0x20, 0x74, 0xe0, 0x14b, 0x61, 0x20, 0x74, 0x73, 0x65, 0x74,
+0x73, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x65, 0x6a, 0x77,
+0x6f, 0x14b, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0xf9, 0x6d, 0x4e,
+0x64, 0x75, 0x14b, 0x6d, 0x62, 0x69, 0x20, 0x53, 0x61, 0x14b, 0x3b, 0x50,
+0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x70, 0xe1, 0x3b, 0x50,
+0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x74, 0xe1, 0x74, 0x3b,
+0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301,
+0x6b, 0x77, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x61,
+0x74, 0x61, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b,
+0x301, 0x6e, 0x25b, 0x301, 0x6e, 0x74, 0xfa, 0x6b, 0xfa, 0x3b, 0x50, 0x25b,
+0x73, 0x61, 0x14b, 0x20, 0x53, 0x61, 0x61, 0x6d, 0x62, 0xe1, 0x3b, 0x50,
+0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x66,
+0x254, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301,
+0x6e, 0x25b, 0x301, 0x70, 0x66, 0xfa, 0xa78b, 0xfa, 0x3b, 0x50, 0x25b, 0x73,
+0x61, 0x14b, 0x20, 0x4e, 0x25b, 0x67, 0x25b, 0x301, 0x6d, 0x3b, 0x50, 0x25b,
+0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x6d, 0x254,
+0x301, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254,
+0x30c, 0x70, 0x70, 0xe1, 0x4a, 0xe9, 0x6e, 0xfa, 0xe1, 0x72, 0x69, 0x3b,
+0x46, 0x1eb9, 0x301, 0x62, 0xfa, 0xe1, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63,
+0x68, 0x3b, 0xc9, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b,
+0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x1ecc, 0x67,
+0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x1eb9, 0x70, 0x74, 0x1eb9, 0x301, 0x6d, 0x62,
+0x61, 0x3b, 0x1ecc, 0x6b, 0x74, 0xf3, 0x62, 0x61, 0x3b, 0x4e, 0x1ecd, 0x76,
+0x1eb9, 0x301, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x1eb9, 0x301, 0x6d,
+0x62, 0x61, 0x4a, 0xe9, 0x6e, 0x3b, 0x46, 0x1eb9, 0x301, 0x62, 0x3b, 0x4d,
+0x61, 0x63, 0x68, 0x3b, 0xc9, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b,
+0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x301, 0x67, 0x1ecd,
+0x3b, 0x53, 0x1eb9, 0x70, 0x3b, 0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x1ecd, 0x76,
+0x3b, 0x44, 0x69, 0x73, 0x4a, 0xe9, 0x6e, 0x3b, 0x46, 0x1eb9, 0x301, 0x62,
+0x3b, 0x4d, 0x61, 0x63, 0x68, 0x3b, 0xc9, 0x70, 0x72, 0x3b, 0x4d, 0x65,
+0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x67,
+0x1ecd, 0x3b, 0x53, 0x1eb9, 0x70, 0x3b, 0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x1ecd,
+0x76, 0x3b, 0x44, 0x69, 0x73, 0x7d3, 0x7cc, 0x7f2, 0x7e0, 0x7ca, 0x7e5, 0x7ce,
+0x7df, 0x7cb, 0x7f2, 0x3b, 0x7de, 0x7cf, 0x7f2, 0x7de, 0x7cf, 0x7dc, 0x7cd, 0x3b,
+0x7d5, 0x7d9, 0x7ca, 0x7d3, 0x7ca, 0x3b, 0x7de, 0x7cf, 0x7f2, 0x7de, 0x7cf, 0x7d8,
+0x7cc, 0x7ec, 0x7d3, 0x7cc, 0x3b, 0x7d8, 0x7d3, 0x7ca, 0x7ec, 0x7d5, 0x7ca, 0x3b,
+0x7e5, 0x7ca, 0x7ec, 0x7db, 0x7cc, 0x7ec, 0x7e5, 0x7d9, 0x7ca, 0x3b, 0x7de, 0x7ca,
+0x7ec, 0x7d9, 0x7cc, 0x7dd, 0x7d0, 0x7ed, 0x3b, 0x7d8, 0x7d3, 0x7ca, 0x7ec, 0x7d3,
+0x7cc, 0x7df, 0x7ca, 0x3b, 0x7d5, 0x7ce, 0x7df, 0x7ca, 0x7dd, 0x7cc, 0x7f2, 0x3b,
+0x7de, 0x7cf, 0x7f2, 0x7d3, 0x7cc, 0x7d5, 0x7cc, 0x7ee, 0x3b, 0x7e3, 0x7cd, 0x7e3,
+0x7cd, 0x7d3, 0x7ca, 0x3b, 0x7de, 0x7cf, 0x7df, 0x7cc, 0x7f2, 0x7de, 0x7cf, 0x7df,
+0x7cc, 0x7f2, 0x7d3, 0x7cc, 0x7f2, 0x7e0, 0x3b, 0x7de, 0x7cf, 0x7f2, 0x7de, 0x3b,
+0x7d5, 0x7d9, 0x7ca, 0x3b, 0x7de, 0x7cf, 0x7f2, 0x7d8, 0x3b, 0x7d8, 0x7d3, 0x7ca,
+0x7ec, 0x7d5, 0x3b, 0x7e5, 0x7ca, 0x7ec, 0x7db, 0x3b, 0x7de, 0x7ca, 0x7ec, 0x7d9,
+0x3b, 0x7d8, 0x7d3, 0x7ca, 0x7ec, 0x7d3, 0x3b, 0x7d5, 0x7ce, 0x7df, 0x7ca, 0x7dd,
+0x7cc, 0x7f2, 0x3b, 0x7de, 0x7cf, 0x7f2, 0x7d3, 0x3b, 0x7e3, 0x7cd, 0x7e3, 0x3b,
+0x7de, 0x7cf, 0x7df, 0x7d3, 0x3b, 0x7de, 0x3b, 0x7d5, 0x3b, 0x7de, 0x3b, 0x7d8,
+0x3b, 0x7e5, 0x3b, 0x7de, 0x3b, 0x7d8, 0x3b, 0x7d5, 0x3b, 0x7de, 0x3b, 0x7e3,
+0x3b, 0x7de, 0x62c, 0x627, 0x646, 0x6a4, 0x6cc, 0x6d5, 0x3b, 0x641, 0x626, 0x6a4,
+0x631, 0x6cc, 0x6d5, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4, 0x631,
+0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659, 0x623, 0x646,
+0x3b, 0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b, 0x622, 0x6af, 0x648, 0x633, 0x62a,
+0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627, 0x645, 0x631, 0x3b, 0x626, 0x648, 0x6a9,
+0x62a, 0x648, 0x6a4, 0x631, 0x3b, 0x646, 0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b,
+0x62f, 0x626, 0x633, 0x627, 0x645, 0x631, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61,
+0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x75, 0x6f, 0x76,
+0x76, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x6b,
+0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0x6f, 0x14b,
+0x6f, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73,
+0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73,
+0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x64,
+0x6e, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x62, 0x6f, 0x72, 0x67,
+0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61,
+0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f,
+0x74, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d,
+0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c,
+0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67,
+0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x3b, 0x63, 0x75, 0x6f,
+0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73,
+0x75, 0x6f, 0x69, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b,
+0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x3b,
+0x6a, 0x75, 0x6f, 0x76, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b,
+0x4d, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x10c, 0x3b, 0x47, 0x3b,
+0x53, 0x3b, 0x4a, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76,
+0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x3b, 0x6d,
+0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f,
+0x69, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b,
+0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x3b, 0x6a, 0x75,
+0x6f, 0x76, 0x50, 0x68, 0x65, 0x72, 0x65, 0x6b, 0x67, 0x6f, 0x6e, 0x67,
+0x3b, 0x44, 0x69, 0x62, 0x6f, 0x6b, 0x77, 0x61, 0x6e, 0x65, 0x3b, 0x48,
+0x6c, 0x61, 0x6b, 0x6f, 0x6c, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x61, 0x6e,
+0x61, 0x6e, 0x67, 0x3b, 0x4d, 0x6f, 0x70, 0x69, 0x74, 0x6c, 0x6f, 0x3b,
+0x50, 0x68, 0x75, 0x70, 0x75, 0x3b, 0x4d, 0x6f, 0x73, 0x65, 0x67, 0x65,
+0x6d, 0x61, 0x6e, 0x79, 0x65, 0x3b, 0x50, 0x68, 0x61, 0x74, 0x6f, 0x3b,
+0x4c, 0x65, 0x77, 0x65, 0x64, 0x69, 0x3b, 0x44, 0x69, 0x70, 0x68, 0x61,
+0x6c, 0x61, 0x6e, 0x65, 0x3b, 0x44, 0x69, 0x62, 0x61, 0x74, 0x73, 0x65,
+0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x6e, 0x74, 0x68, 0x6f, 0x6c, 0x65, 0x50,
+0x68, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x62, 0x6f, 0x3b, 0x48, 0x6c,
+0x61, 0x6b, 0x3b, 0x4d, 0x6f, 0x72, 0x61, 0x3b, 0x4d, 0x6f, 0x70, 0x69,
+0x3b, 0x50, 0x68, 0x75, 0x70, 0x75, 0x3b, 0x4d, 0x6f, 0x73, 0x65, 0x3b,
+0x50, 0x68, 0x61, 0x74, 0x6f, 0x3b, 0x4c, 0x65, 0x77, 0x65, 0x3b, 0x44,
+0x69, 0x70, 0x68, 0x61, 0x3b, 0x44, 0x69, 0x62, 0x61, 0x3b, 0x4d, 0x61,
+0x6e, 0x74, 0x68, 0x50, 0x3b, 0x44, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x4d,
+0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x44, 0x3b, 0x44,
+0x3b, 0x4d, 0x5a, 0x69, 0x62, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x6c, 0x61,
+0x3b, 0x4e, 0x68, 0x6c, 0x6f, 0x6c, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d,
+0x62, 0x69, 0x6d, 0x62, 0x69, 0x74, 0x68, 0x6f, 0x3b, 0x4d, 0x61, 0x62,
+0x61, 0x73, 0x61, 0x3b, 0x4e, 0x6b, 0x77, 0x65, 0x6e, 0x6b, 0x77, 0x65,
+0x7a, 0x69, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61,
+0x3b, 0x4e, 0x74, 0x75, 0x6c, 0x69, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4e,
+0x63, 0x77, 0x61, 0x62, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4d, 0x70,
+0x61, 0x6e, 0x64, 0x75, 0x6c, 0x61, 0x3b, 0x4d, 0x66, 0x75, 0x6d, 0x66,
+0x75, 0x3b, 0x4c, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6c,
+0x61, 0x6b, 0x61, 0x7a, 0x69, 0x5a, 0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c,
+0x6f, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b,
+0x77, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x3b, 0x4e,
+0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x3b, 0x4d, 0x66, 0x75, 0x3b,
+0x4c, 0x77, 0x65, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x5a, 0x3b, 0x4e, 0x3b,
+0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b,
+0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61,
+0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69,
+0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61,
+0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
+0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
+0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e,
+0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75,
+0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e,
+0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64,
+0x65, 0x73, 0x2e, 0x54, 0x69, 0x6f, 0x70, 0x20, 0x74, 0x68, 0x61, 0x72,
+0x20, 0x70, 0x25b, 0x74, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254,
+0x331, 0x254, 0x331, 0x14b, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75,
+0xe4, 0x74, 0x3b, 0x4b, 0x6f, 0x72, 0x6e, 0x79, 0x6f, 0x6f, 0x74, 0x3b,
+0x50, 0x61, 0x79, 0x20, 0x79, 0x69, 0x65, 0x331, 0x74, 0x6e, 0x69, 0x3b,
+0x54, 0x68, 0x6f, 0x331, 0x6f, 0x331, 0x72, 0x3b, 0x54, 0x25b, 0x25b, 0x72,
+0x3b, 0x4c, 0x61, 0x61, 0x74, 0x68, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54,
+0x69, 0x6f, 0x331, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x69, 0x331, 0x69,
+0x331, 0x74, 0x54, 0x69, 0x6f, 0x70, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44,
+0x75, 0x254, 0x331, 0x254, 0x331, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44,
+0x75, 0xe4, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x54,
+0x68, 0x6f, 0x6f, 0x3b, 0x54, 0x25b, 0x25b, 0x3b, 0x4c, 0x61, 0x61, 0x3b,
+0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x64, 0x54, 0x3b, 0x50, 0x3b, 0x44,
+0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x54,
+0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x54, 0x4a, 0x61, 0x6e, 0x75, 0x77, 0x61,
+0x6c, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x6c, 0x75, 0x77, 0x61, 0x6c,
+0x65, 0x3b, 0x4d, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70,
+0x75, 0x6c, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69,
+0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x69,
+0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x75, 0x74, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x4f, 0x6b, 0x75, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61,
+0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x6c, 0x3b,
+0x45, 0x70, 0x75, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b,
+0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b,
+0x4f, 0x6b, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x67,
+0x65, 0x6e, 0x69, 0xe8, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x69, 0xe8,
+0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x3b, 0x6a, 0x75,
+0x6c, 0x68, 0x65, 0x74, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73,
+0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0xf2,
+0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x64, 0x65, 0x20,
+0x67, 0x65, 0x6e, 0x69, 0xe8, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65,
+0x62, 0x72, 0x69, 0xe8, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65,
+0x20, 0x6d, 0x61, 0x69, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x68,
+0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x68, 0x65, 0x74, 0x3b, 0x64,
+0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65,
+0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74,
+0xf2, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62,
+0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b,
+0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x3b, 0x6a, 0x75, 0x6c,
+0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b,
+0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65,
+0x63, 0x2e, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x67, 0xe8, 0x72, 0x3b, 0x68, 0x65, 0x72, 0x65, 0x75, 0xe8, 0x72,
+0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x75, 0x3b,
+0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x3b, 0x6a, 0x75, 0x72,
+0x69, 0xf2, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65,
+0x74, 0x65, 0x6d, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65,
+0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x65,
+0x6d, 0x65, 0x67, 0xe8, 0x72, 0x3b, 0x68, 0x65, 0x72, 0x3b, 0x6d, 0x61,
+0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75,
+0x6e, 0x3b, 0x6a, 0x75, 0x72, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65,
+0x74, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65,
+0x63, 0x47, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0xb1c, 0xb3e, 0xb28, 0xb41, 0xb06, 0xb30, 0xb40, 0x3b, 0xb2b, 0xb47, 0xb2c, 0xb43,
+0xb06, 0xb30, 0xb40, 0x3b, 0xb2e, 0xb3e, 0xb30, 0xb4d, 0xb1a, 0xb4d, 0xb1a, 0x3b,
+0xb05, 0xb2a, 0xb4d, 0xb30, 0xb47, 0xb32, 0x3b, 0xb2e, 0xb07, 0x3b, 0xb1c, 0xb41,
+0xb28, 0x3b, 0xb1c, 0xb41, 0xb32, 0xb3e, 0xb07, 0x3b, 0xb05, 0xb17, 0xb37, 0xb4d,
+0xb1f, 0x3b, 0xb38, 0xb47, 0xb2a, 0xb4d, 0xb1f, 0xb47, 0xb2e, 0xb4d, 0xb2c, 0xb30,
+0x3b, 0xb05, 0xb15, 0xb4d, 0xb1f, 0xb4b, 0xb2c, 0xb30, 0x3b, 0xb28, 0xb2d, 0xb47,
+0xb2e, 0xb4d, 0xb2c, 0xb30, 0x3b, 0xb21, 0xb3f, 0xb38, 0xb47, 0xb2e, 0xb4d, 0xb2c,
+0xb30, 0xb1c, 0xb3e, 0x3b, 0xb2b, 0xb47, 0x3b, 0xb2e, 0xb3e, 0x3b, 0xb05, 0x3b,
+0xb2e, 0xb07, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb05, 0x3b, 0xb38,
+0xb47, 0x3b, 0xb05, 0x3b, 0xb28, 0x3b, 0xb21, 0xb3f, 0x41, 0x6d, 0x61, 0x6a,
+0x6a, 0x69, 0x69, 0x3b, 0x47, 0x75, 0x72, 0x61, 0x61, 0x6e, 0x64, 0x68,
+0x61, 0x6c, 0x61, 0x3b, 0x42, 0x69, 0x74, 0x6f, 0x6f, 0x74, 0x65, 0x65,
+0x73, 0x73, 0x61, 0x3b, 0x45, 0x6c, 0x62, 0x61, 0x3b, 0x43, 0x61, 0x61,
+0x6d, 0x73, 0x61, 0x3b, 0x57, 0x61, 0x78, 0x61, 0x62, 0x61, 0x6a, 0x6a,
+0x69, 0x69, 0x3b, 0x41, 0x64, 0x6f, 0x6f, 0x6c, 0x65, 0x65, 0x73, 0x73,
+0x61, 0x3b, 0x48, 0x61, 0x67, 0x61, 0x79, 0x79, 0x61, 0x3b, 0x46, 0x75,
+0x75, 0x6c, 0x62, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6e, 0x6b, 0x6f, 0x6c,
+0x6f, 0x6c, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x53, 0x61, 0x64, 0x61,
+0x61, 0x73, 0x61, 0x3b, 0x4d, 0x75, 0x64, 0x64, 0x65, 0x65, 0x41, 0x6d,
+0x61, 0x3b, 0x47, 0x75, 0x72, 0x3b, 0x42, 0x69, 0x74, 0x3b, 0x45, 0x6c,
+0x62, 0x3b, 0x43, 0x61, 0x6d, 0x3b, 0x57, 0x61, 0x78, 0x3b, 0x41, 0x64,
+0x6f, 0x3b, 0x48, 0x61, 0x67, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4f, 0x6e,
+0x6b, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x4d, 0x75, 0x64, 0x41, 0x3b, 0x47,
+0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x43, 0x3b, 0x57, 0x3b, 0x41, 0x3b, 0x48,
+0x3b, 0x46, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4d, 0xd801, 0xdcc0, 0xd801, 0xdce3,
+0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdcc4, 0xd801,
+0xdcd8, 0xd801, 0xdce1, 0xd801, 0xdcdb, 0x358, 0xd801, 0xdce7, 0xd801, 0xdcdf, 0x3b, 0xd801,
+0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20,
+0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801, 0xdcf5, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801,
+0xdcd8, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801, 0xdcf5, 0xd801, 0xdcd8, 0xd801,
+0xdcdc, 0xd801, 0xdce3, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358,
+0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801, 0xdcf0, 0xd801,
+0xdcea, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801,
+0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801, 0xdcdf, 0xd801,
+0xdcee, 0xd801, 0xdcd8, 0xd801, 0xdcf0, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3,
+0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdccf, 0xd801,
+0xdcdf, 0xd801, 0xdcef, 0xd801, 0xdcd8, 0xd801, 0xdcec, 0xd801, 0xdcdf, 0x3b, 0xd801, 0xdcc0,
+0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801,
+0xdcc4, 0xd801, 0xdcdf, 0xd801, 0xdcf5, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8,
+0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801,
+0xdcd8, 0x20, 0xd801, 0xdcbc, 0xd801, 0xdce3, 0xd801, 0xdcdf, 0xd801, 0xdcf0, 0xd801, 0xdcea,
+0xd801, 0xdcec, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea,
+0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdcbf, 0xd801, 0xdcdf, 0xd801, 0xdcdc,
+0xd801, 0xdcdb, 0xd801, 0xdcf2, 0xd801, 0xdcdf, 0xd801, 0xdcf7, 0xd801, 0xdce3, 0x358, 0xd801,
+0xdce4, 0xd801, 0xdcdf, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358,
+0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801, 0xdcbf, 0xd801, 0xdcdf, 0xd801, 0xdcdc, 0xd801,
+0xdcdb, 0x3b, 0xd801, 0xdcc0, 0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x20, 0xd801, 0xdcb0, 0xd801, 0xdce7, 0xd801, 0xdce3, 0x20, 0xd801, 0xdccf,
+0xd801, 0xdce3, 0x358, 0xd801, 0xdcf8, 0xd801, 0xdcf2, 0xd801, 0xdce3, 0x3b, 0xd801, 0xdcc0,
+0xd801, 0xdce3, 0x358, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x20, 0xd801,
+0xdcb0, 0xd801, 0xdce7, 0xd801, 0xdce3, 0x20, 0xd801, 0xdccd, 0xd801, 0xdcea, 0x358, 0xd801,
+0xdcec, 0xd801, 0xdcd8, 0xd801, 0xdcc4, 0xd801, 0xdcd8, 0xd801, 0xdce1, 0xd801, 0xdcdb, 0x358,
+0xd801, 0xdce7, 0xd801, 0xdcdf, 0x3b, 0xd801, 0xdcf5, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcf5, 0xd801, 0xdcd8, 0xd801, 0xdcdc, 0xd801, 0xdce3, 0x3b,
+0xd801, 0xdcf0, 0xd801, 0xdcea, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcee, 0xd801,
+0xdcd8, 0xd801, 0xdcf0, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcef, 0xd801, 0xdcd8, 0xd801, 0xdcec,
+0xd801, 0xdcdf, 0x3b, 0xd801, 0xdcc4, 0xd801, 0xdcdf, 0xd801, 0xdcf5, 0xd801, 0xdcea, 0x358,
+0xd801, 0xdcec, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcbc, 0xd801, 0xdce3, 0xd801, 0xdcdf, 0xd801,
+0xdcf0, 0xd801, 0xdcea, 0xd801, 0xdcec, 0xd801, 0xdcd8, 0x3b, 0xd801, 0xdcbf, 0xd801, 0xdcdf,
+0xd801, 0xdcdc, 0xd801, 0xdcdb, 0xd801, 0xdcf2, 0xd801, 0xdcdf, 0xd801, 0xdcf7, 0xd801, 0xdce3,
+0x358, 0xd801, 0xdce4, 0xd801, 0xdcdf, 0x3b, 0xd801, 0xdcbf, 0xd801, 0xdcdf, 0xd801, 0xdcdc,
+0xd801, 0xdcdb, 0x3b, 0xd801, 0xdcb0, 0xd801, 0xdce7, 0xd801, 0xdce3, 0x20, 0xd801, 0xdccf,
+0xd801, 0xdce3, 0x358, 0xd801, 0xdcf8, 0xd801, 0xdcf2, 0xd801, 0xdce3, 0x3b, 0xd801, 0xdcb0,
+0xd801, 0xdce7, 0xd801, 0xdce3, 0x20, 0xd801, 0xdccd, 0xd801, 0xdcea, 0x358, 0xd801, 0xdcec,
+0xd801, 0xdcd8, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432,
+0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x44a, 0x438, 0x3b,
+0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418,
+0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433,
+0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c,
+0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f,
+0x431, 0x440, 0x44c, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x44f,
+0x43d, 0x432, 0x430, 0x440, 0x44b, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b,
+0x44b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x44a, 0x438, 0x439, 0x44b, 0x3b, 0x430,
+0x43f, 0x440, 0x435, 0x43b, 0x44b, 0x3b, 0x43c, 0x430, 0x439, 0x44b, 0x3b, 0x438,
+0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432, 0x433,
+0x443, 0x441, 0x442, 0x44b, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440,
+0x44b, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43d, 0x43e,
+0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44b,
+0x42f, 0x43d, 0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x41c,
+0x430, 0x440, 0x442, 0x2e, 0x3b, 0x410, 0x43f, 0x440, 0x2e, 0x3b, 0x41c, 0x430,
+0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b,
+0x410, 0x432, 0x433, 0x2e, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x41e,
+0x43a, 0x442, 0x2e, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x414, 0x435,
+0x43a, 0x2e, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b,
+0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430,
+0x439, 0x44b, 0x3b, 0x438, 0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b,
+0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e,
+0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a,
+0x2e, 0x59, 0x61, 0x6e, 0xfc, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62,
+0x72, 0xfc, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41,
+0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x59, 0xfc, 0x6e,
+0x69, 0x3b, 0x59, 0xfc, 0x6c, 0x69, 0x3b, 0x4f, 0x75, 0x67, 0xf9, 0x73,
+0x74, 0xf9, 0x73, 0x3b, 0x53, 0xe8, 0x70, 0x74, 0xe8, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0xd2, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f,
+0x76, 0xe8, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0xe8, 0x6d,
+0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
+0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x79,
+0xfc, 0x6e, 0x3b, 0x79, 0xfc, 0x6c, 0x3b, 0x6f, 0x75, 0x67, 0x3b, 0x73,
+0xe8, 0x70, 0x3b, 0xf2, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64,
+0x65, 0x73, 0x59, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x59, 0xfc,
+0x6e, 0x3b, 0x59, 0xfc, 0x6c, 0x3b, 0x4f, 0x75, 0x67, 0x3b, 0x53, 0xe8,
+0x70, 0x3b, 0xd2, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65,
+0x73, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x6d0, 0x628, 0x631, 0x648,
+0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc,
+0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644,
+0x627, 0x6cc, 0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645,
+0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
+0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x646, 0x648,
+0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627,
+0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b,
+0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6ab,
+0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627,
+0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b,
+0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641,
+0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627,
+0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b,
+0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, 0x633,
+0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631,
+0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631,
+0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b,
+0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x698,
+0x627, 0x646, 0x648, 0x6cc, 0x647, 0x654, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647,
+0x654, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644,
+0x3b, 0x645, 0x647, 0x654, 0x3b, 0x698, 0x648, 0x626, 0x646, 0x3b, 0x698, 0x648,
+0x626, 0x6cc, 0x647, 0x654, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a,
+0x627, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646,
+0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631,
+0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x3b, 0x698, 0x3b,
+0x698, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x62c,
+0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b,
+0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645,
+0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b,
+0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b,
+0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631,
+0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628,
+0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e,
+0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c,
+0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645,
+0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
+0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x73, 0x74, 0x79, 0x63, 0x7a,
+0x65, 0x144, 0x3b, 0x6c, 0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a,
+0x65, 0x63, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x65, 0x144, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77, 0x69, 0x65, 0x63,
+0x3b, 0x6c, 0x69, 0x70, 0x69, 0x65, 0x63, 0x3b, 0x73, 0x69, 0x65, 0x72,
+0x70, 0x69, 0x65, 0x144, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x73, 0x69, 0x65,
+0x144, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69,
+0x6b, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67,
+0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x73, 0x74, 0x79, 0x63, 0x7a,
+0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d,
+0x61, 0x72, 0x63, 0x61, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69,
+0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77,
+0x63, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x65,
+0x72, 0x70, 0x6e, 0x69, 0x61, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x15b, 0x6e,
+0x69, 0x61, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e,
+0x69, 0x6b, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64,
+0x61, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x6e, 0x69, 0x61, 0x73, 0x74, 0x79,
+0x3b, 0x6c, 0x75, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69,
+0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x3b, 0x6c, 0x69, 0x70,
+0x3b, 0x73, 0x69, 0x65, 0x3b, 0x77, 0x72, 0x7a, 0x3b, 0x70, 0x61, 0x17a,
+0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x53, 0x3b, 0x4c, 0x3b,
+0x4d, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x53, 0x3b,
+0x57, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x47, 0x73, 0x3b, 0x6c, 0x3b, 0x6d,
+0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77,
+0x3b, 0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x6a, 0x61, 0x6e, 0x65, 0x69, 0x72,
+0x6f, 0x3b, 0x66, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b,
+0x6d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b,
+0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x6a,
+0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b,
+0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74,
+0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
+0x6f, 0x3b, 0x64, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x6a, 0x61,
+0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e,
+0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e, 0x3b, 0x6a,
+0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f,
+0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b,
+0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x7a, 0x2e, 0x72, 0x61, 0x67,
+0x73, 0x3b, 0x77, 0x61, 0x73, 0x73, 0x61, 0x72, 0x69, 0x6e, 0x73, 0x3b,
+0x70, 0x16b, 0x6c, 0x69, 0x73, 0x3b, 0x73, 0x61, 0x6b, 0x6b, 0x69, 0x73,
+0x3b, 0x7a, 0x61, 0x6c, 0x6c, 0x61, 0x77, 0x73, 0x3b, 0x73, 0x12b, 0x6d,
+0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6c, 0x12b, 0x70, 0x61, 0x3b, 0x64, 0x61,
+0x67, 0x67, 0x69, 0x73, 0x3b, 0x73, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x73,
+0x3b, 0x73, 0x70, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x73, 0x3b, 0x6c, 0x61,
+0x70, 0x6b, 0x72, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x73, 0x61, 0x6c, 0x6c,
+0x61, 0x77, 0x73, 0x72, 0x61, 0x67, 0x3b, 0x77, 0x61, 0x73, 0x3b, 0x70,
+0x16b, 0x6c, 0x3b, 0x73, 0x61, 0x6b, 0x3b, 0x7a, 0x61, 0x6c, 0x3b, 0x73,
+0x12b, 0x6d, 0x3b, 0x6c, 0x12b, 0x70, 0x3b, 0x64, 0x61, 0x67, 0x3b, 0x73,
+0x69, 0x6c, 0x3b, 0x73, 0x70, 0x61, 0x3b, 0x6c, 0x61, 0x70, 0x3b, 0x73,
+0x61, 0x6c, 0x52, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x5a, 0x3b,
+0x53, 0x3b, 0x4c, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4c, 0x3b,
+0x53, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b, 0xa3c, 0xa30, 0xa35, 0xa30,
+0xa40, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48,
+0xa32, 0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32,
+0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c,
+0xa30, 0x3b, 0xa05, 0xa15, 0xa24, 0xa42, 0xa2c, 0xa30, 0x3b, 0xa28, 0xa35, 0xa70,
+0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30, 0xa1c, 0xa28, 0x3b, 0xa2b,
+0xa3c, 0xa30, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30,
+0xa48, 0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32,
+0xa3e, 0x3b, 0xa05, 0xa17, 0x3b, 0xa38, 0xa24, 0xa70, 0x3b, 0xa05, 0xa15, 0xa24,
+0xa42, 0x3b, 0xa28, 0xa35, 0xa70, 0x3b, 0xa26, 0xa38, 0xa70, 0xa1c, 0x3b, 0xa2b,
+0xa3c, 0x3b, 0xa2e, 0xa3e, 0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b,
+0xa1c, 0xa41, 0x3b, 0xa05, 0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26,
+0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b,
+0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645,
+0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 0x6cc,
+0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b,
+0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631,
+0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b,
+0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a,
+0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f,
+0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x6f,
+0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x69,
+0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x63, 0x74, 0x75, 0x62, 0x72,
+0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
+0x44, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x45, 0x6e, 0x65,
+0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72,
+0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c,
+0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x74,
+0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x63, 0x69, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72,
+0x69, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x65, 0x3b, 0x61, 0x70,
+0x72, 0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75,
+0x6e, 0x69, 0x65, 0x3b, 0x69, 0x75, 0x6c, 0x69, 0x65, 0x3b, 0x61, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x72, 0x69, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69,
+0x65, 0x3b, 0x6e, 0x6f, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b,
+0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x69, 0x61, 0x6e,
+0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b,
+0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e,
+0x2e, 0x3b, 0x69, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e,
+0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x49, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x73, 0x63, 0x68, 0x61, 0x6e,
+0x65, 0x72, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61,
+0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x67, 0x6c, 0x3b, 0x6d, 0x61,
+0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72,
+0x3b, 0x66, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x61, 0x76, 0x75,
+0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x64, 0x61, 0x20, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x65, 0x72,
+0x3b, 0x64, 0x61, 0x20, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x64,
+0x61, 0x20, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x72,
+0x69, 0x67, 0x6c, 0x3b, 0x64, 0x61, 0x20, 0x6d, 0x61, 0x74, 0x67, 0x3b,
+0x64, 0x61, 0x20, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72,
+0x3b, 0x64, 0x61, 0x20, 0x66, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b,
+0x64, 0x2019, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x64, 0x61, 0x20, 0x73,
+0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x2019, 0x6f,
+0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x61, 0x20, 0x6e, 0x6f,
+0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x61, 0x20, 0x64, 0x65,
+0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x2e,
+0x3b, 0x66, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b,
+0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65,
+0x72, 0x63, 0x6c, 0x2e, 0x3b, 0x66, 0x61, 0x6e, 0x2e, 0x3b, 0x61, 0x76,
+0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e,
+0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b,
+0x46, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x4d,
+0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e,
+0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x61, 0x6e, 0x61,
+0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x61,
+0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x73, 0x69, 0x74, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65,
+0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69,
+0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61,
+0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b,
+0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69,
+0x4d, 0x31, 0x3b, 0x4d, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4d, 0x34, 0x3b,
+0x4d, 0x35, 0x3b, 0x4d, 0x36, 0x3b, 0x4d, 0x37, 0x3b, 0x4d, 0x38, 0x3b,
+0x4d, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d,
+0x31, 0x32, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b,
+0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
+0x49, 0x4e, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x52, 0x75, 0x68, 0x75, 0x68,
+0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x74, 0x77, 0x61, 0x72, 0x61, 0x6e, 0x74,
+0x65, 0x3b, 0x4e, 0x64, 0x61, 0x6d, 0x75, 0x6b, 0x69, 0x7a, 0x61, 0x3b,
+0x52, 0x75, 0x73, 0x61, 0x6d, 0x61, 0x3b, 0x52, 0x75, 0x68, 0x65, 0x73,
+0x68, 0x69, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x6b, 0x61, 0x72, 0x6f, 0x3b,
+0x4e, 0x79, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x61, 0x72, 0x6f, 0x3b, 0x4e,
+0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x47, 0x69, 0x74, 0x75,
+0x67, 0x75, 0x74, 0x75, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x6f, 0x6e, 0x79,
+0x6f, 0x3b, 0x4b, 0x69, 0x67, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x4d, 0x75,
+0x74, 0x2e, 0x3b, 0x47, 0x61, 0x73, 0x2e, 0x3b, 0x57, 0x65, 0x72, 0x2e,
+0x3b, 0x4d, 0x61, 0x74, 0x2e, 0x3b, 0x47, 0x69, 0x63, 0x2e, 0x3b, 0x4b,
+0x61, 0x6d, 0x2e, 0x3b, 0x4e, 0x79, 0x61, 0x2e, 0x3b, 0x4b, 0x61, 0x6e,
+0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x2e, 0x3b, 0x55, 0x6b, 0x77, 0x2e, 0x3b,
+0x55, 0x67, 0x75, 0x2e, 0x3b, 0x55, 0x6b, 0x75, 0x2e, 0x44f, 0x43d, 0x432,
+0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b,
+0x43c, 0x430, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44f,
+0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e,
+0x43b, 0x44f, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x430, 0x3b, 0x441,
+0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43e, 0x43a, 0x442, 0x44f,
+0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434,
+0x435, 0x43a, 0x430, 0x431, 0x440, 0x44f, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444,
+0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f,
+0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b,
+0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435,
+0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f,
+0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x44f, 0x43d, 0x432, 0x2e, 0x3b,
+0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430,
+0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x2e,
+0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441,
+0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e,
+0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x442, 0x43e, 0x445, 0x441,
+0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x43e, 0x43b, 0x443, 0x43d, 0x43d, 0x44c,
+0x443, 0x3b, 0x43a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430,
+0x440, 0x3b, 0x43c, 0x443, 0x443, 0x441, 0x20, 0x443, 0x441, 0x442, 0x430, 0x440,
+0x3b, 0x44b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x431, 0x44d, 0x441,
+0x20, 0x44b, 0x439, 0x430, 0x3b, 0x43e, 0x442, 0x20, 0x44b, 0x439, 0x430, 0x3b,
+0x430, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b, 0x445, 0x20, 0x44b, 0x439, 0x430,
+0x3b, 0x431, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x430,
+0x3b, 0x430, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x441, 0x44d,
+0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445, 0x441, 0x44b, 0x43d,
+0x43d, 0x44c, 0x44b, 0x422, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443,
+0x3b, 0x41e, 0x43b, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41a, 0x443, 0x43b,
+0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440, 0x3b, 0x41c, 0x443, 0x443,
+0x441, 0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x42b, 0x430, 0x43c, 0x20,
+0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x44d, 0x441, 0x20, 0x44b, 0x439, 0x44b,
+0x43d, 0x3b, 0x41e, 0x442, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x410, 0x442,
+0x44b, 0x440, 0x434, 0x44c, 0x44b, 0x445, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b,
+0x411, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x44b, 0x43d,
+0x3b, 0x410, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x421, 0x44d,
+0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445, 0x441, 0x44b, 0x43d,
+0x43d, 0x44c, 0x44b, 0x422, 0x43e, 0x445, 0x441, 0x3b, 0x41e, 0x43b, 0x443, 0x43d,
+0x3b, 0x41a, 0x43b, 0x43d, 0x3b, 0x41c, 0x441, 0x443, 0x3b, 0x42b, 0x430, 0x43c,
+0x3b, 0x411, 0x44d, 0x441, 0x3b, 0x41e, 0x442, 0x439, 0x3b, 0x410, 0x442, 0x440,
+0x3b, 0x411, 0x43b, 0x495, 0x3b, 0x410, 0x43b, 0x442, 0x3b, 0x421, 0x44d, 0x442,
+0x3b, 0x410, 0x445, 0x441, 0x422, 0x3b, 0x41e, 0x3b, 0x41a, 0x3b, 0x41c, 0x3b,
+0x42b, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x410, 0x3b, 0x411, 0x3b, 0x410, 0x3b,
+0x421, 0x3b, 0x410, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f,
+0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x77,
+0x61, 0x61, 0x72, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65,
+0x20, 0x6f, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20,
+0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4c,
+0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x65, 0x74, 0x3b,
+0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b,
+0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61,
+0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x69,
+0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73,
+0x61, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20,
+0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c,
+0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x6f, 0x3b,
+0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f,
+0x6e, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x4f, 0x62, 0x6f, 0x3b, 0x57,
+0x61, 0x61, 0x3b, 0x4f, 0x6b, 0x75, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49,
+0x6d, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x49,
+0x73, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x3b, 0x54, 0x6f, 0x6d, 0x3b, 0x54,
+0x6f, 0x62, 0x3b, 0x54, 0x6f, 0x77, 0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b,
+0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b,
+0x54, 0x3b, 0x54, 0x3b, 0x54, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65, 0x3b,
+0x46, 0x75, 0x6c, 0x75, 0x6e, 0x64, 0xef, 0x67, 0x69, 0x3b, 0x4d, 0x62,
+0xe4, 0x6e, 0x67, 0xfc, 0x3b, 0x4e, 0x67, 0x75, 0x62, 0xf9, 0x65, 0x3b,
+0x42, 0xea, 0x6c, 0xe4, 0x77, 0xfc, 0x3b, 0x46, 0xf6, 0x6e, 0x64, 0x6f,
+0x3b, 0x4c, 0x65, 0x6e, 0x67, 0x75, 0x61, 0x3b, 0x4b, 0xfc, 0x6b, 0xfc,
+0x72, 0xfc, 0x3b, 0x4d, 0x76, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x67, 0x62,
+0x65, 0x72, 0x65, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x62, 0xe4, 0x6e, 0x64,
+0xfc, 0x72, 0x75, 0x3b, 0x4b, 0x61, 0x6b, 0x61, 0x75, 0x6b, 0x61, 0x4e,
+0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4d, 0x62, 0xe4, 0x3b, 0x4e,
+0x67, 0x75, 0x3b, 0x42, 0xea, 0x6c, 0x3b, 0x46, 0xf6, 0x6e, 0x3b, 0x4c,
+0x65, 0x6e, 0x3b, 0x4b, 0xfc, 0x6b, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x4e,
+0x67, 0x62, 0x3b, 0x4e, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6b, 0x4e, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b,
+0x4b, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4b, 0x4d, 0x75, 0x70,
+0x61, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x77, 0x61, 0x3b, 0x4d, 0x77,
+0x69, 0x74, 0x6f, 0x70, 0x65, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e,
+0x64, 0x65, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4d, 0x75, 0x73,
+0x68, 0x65, 0x6e, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x67, 0x61, 0x6c, 0x69,
+0x3b, 0x4d, 0x75, 0x6a, 0x69, 0x6d, 0x62, 0x69, 0x3b, 0x4d, 0x75, 0x73,
+0x68, 0x69, 0x70, 0x65, 0x70, 0x6f, 0x3b, 0x4d, 0x75, 0x70, 0x75, 0x67,
+0x75, 0x74, 0x6f, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x65, 0x6e, 0x73, 0x65,
+0x3b, 0x4d, 0x6f, 0x6b, 0x68, 0x75, 0x3b, 0x4d, 0x75, 0x73, 0x6f, 0x6e,
+0x67, 0x61, 0x6e, 0x64, 0x65, 0x6d, 0x62, 0x77, 0x65, 0x3b, 0x4d, 0x75,
+0x68, 0x61, 0x61, 0x6e, 0x6f, 0x4d, 0x75, 0x70, 0x3b, 0x4d, 0x77, 0x69,
+0x3b, 0x4d, 0x73, 0x68, 0x3b, 0x4d, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x67,
+0x3b, 0x4d, 0x75, 0x6a, 0x3b, 0x4d, 0x73, 0x70, 0x3b, 0x4d, 0x70, 0x67,
+0x3b, 0x4d, 0x79, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x4d, 0x75, 0x73,
+0x3b, 0x4d, 0x75, 0x68, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x92e, 0x93e, 0x938,
+0x903, 0x3b, 0x92b, 0x930, 0x935, 0x930, 0x940, 0x92e, 0x93e, 0x938, 0x903, 0x3b,
+0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x905, 0x92a,
+0x94d, 0x930, 0x948, 0x932, 0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x92e, 0x908, 0x92e,
+0x93e, 0x938, 0x903, 0x3b, 0x91c, 0x942, 0x928, 0x92e, 0x93e, 0x938, 0x903, 0x3b,
+0x91c, 0x941, 0x932, 0x93e, 0x908, 0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x905, 0x917,
+0x938, 0x94d, 0x924, 0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x938, 0x93f, 0x924, 0x902,
+0x92c, 0x930, 0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942,
+0x92c, 0x930, 0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930,
+0x92e, 0x93e, 0x938, 0x903, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x92e,
+0x93e, 0x938, 0x903, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3a, 0x3b, 0x92b, 0x930,
+0x935, 0x930, 0x940, 0x3a, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3a, 0x3b,
+0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3a, 0x3b, 0x92e, 0x908, 0x3b, 0x91c,
+0x942, 0x928, 0x3a, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3a, 0x3b, 0x905,
+0x917, 0x938, 0x94d, 0x924, 0x3a, 0x3b, 0x938, 0x93f, 0x924, 0x902, 0x92c, 0x930,
+0x3a, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3a, 0x3b, 0x928,
+0x935, 0x902, 0x92c, 0x930, 0x3a, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930,
+0x3a, 0x1c61, 0x1c5f, 0x1c71, 0x1c63, 0x1c5f, 0x1c68, 0x1c64, 0x3b, 0x1c6f, 0x1c77, 0x1c5f,
+0x1c68, 0x1c63, 0x1c5f, 0x1c68, 0x1c64, 0x3b, 0x1c62, 0x1c5f, 0x1c68, 0x1c6a, 0x3b, 0x1c5f,
+0x1c6f, 0x1c68, 0x1c6e, 0x1c5e, 0x3b, 0x1c62, 0x1c6e, 0x3b, 0x1c61, 0x1c69, 0x1c71, 0x3b,
+0x1c61, 0x1c69, 0x1c5e, 0x1c5f, 0x1c6d, 0x3b, 0x1c5f, 0x1c5c, 0x1c5f, 0x1c65, 0x1c5b, 0x3b,
+0x1c65, 0x1c6e, 0x1c6f, 0x1c74, 0x1c6e, 0x1c62, 0x1c75, 0x1c5f, 0x1c68, 0x3b, 0x1c5a, 0x1c60,
+0x1c74, 0x1c5a, 0x1c75, 0x1c5f, 0x1c68, 0x3b, 0x1c71, 0x1c5f, 0x1c63, 0x1c5f, 0x1c62, 0x1c75,
+0x1c5f, 0x1c68, 0x3b, 0x1c6b, 0x1c64, 0x1c65, 0x1c5f, 0x1c62, 0x1c75, 0x1c5f, 0x1c68, 0x1c61,
+0x1c5f, 0x1c71, 0x3b, 0x1c6f, 0x1c77, 0x1c5f, 0x3b, 0x1c62, 0x1c5f, 0x1c68, 0x3b, 0x1c5f,
+0x1c6f, 0x1c68, 0x3b, 0x1c62, 0x1c6e, 0x3b, 0x1c61, 0x1c69, 0x1c71, 0x3b, 0x1c61, 0x1c69,
+0x1c5e, 0x3b, 0x1c5f, 0x1c5c, 0x1c5f, 0x3b, 0x1c65, 0x1c6e, 0x1c6f, 0x3b, 0x1c5a, 0x1c60,
+0x1c74, 0x3b, 0x1c71, 0x1c5f, 0x1c63, 0x3b, 0x1c6b, 0x1c64, 0x1c65, 0x1c61, 0x3b, 0x1c6f,
+0x3b, 0x1c62, 0x3b, 0x1c5f, 0x3b, 0x1c62, 0x3b, 0x1c61, 0x3b, 0x1c61, 0x3b, 0x1c5f,
+0x3b, 0x1c65, 0x3b, 0x1c5a, 0x3b, 0x1c71, 0x3b, 0x1c6b, 0x67, 0x68, 0x65, 0x6e,
+0x6e, 0xe0, 0x72, 0x67, 0x69, 0x75, 0x3b, 0x66, 0x72, 0x65, 0xe0, 0x72,
+0x67, 0x69, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x7a, 0x75, 0x3b, 0x61,
+0x62, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x6a, 0x75, 0x3b, 0x6c,
+0xe0, 0x6d, 0x70, 0x61, 0x64, 0x61, 0x73, 0x3b, 0x74, 0x72, 0xec, 0x75,
+0x6c, 0x61, 0x73, 0x3b, 0x61, 0x75, 0x73, 0x74, 0x75, 0x3b, 0x63, 0x61,
+0x62, 0x75, 0x64, 0x61, 0x6e, 0x6e, 0x69, 0x3b, 0x73, 0x61, 0x6e, 0x74,
+0x75, 0x67, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x73, 0x61, 0x6e, 0x74, 0x61,
+0x6e, 0x64, 0x72, 0x69, 0x61, 0x3b, 0x6e, 0x61, 0x64, 0x61, 0x6c, 0x65,
+0x67, 0x68, 0x65, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6c, 0xe0, 0x6d, 0x3b,
+0x74, 0x72, 0xec, 0x3b, 0x61, 0x75, 0x73, 0x3b, 0x63, 0x61, 0x62, 0x3b,
+0x73, 0x74, 0x47, 0x3b, 0x73, 0x74, 0x41, 0x3b, 0x6e, 0x61, 0x64, 0x47,
+0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x54,
+0x3b, 0x41, 0x3b, 0x43, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x4a, 0x61,
+0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x65, 0x69,
+0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x6f, 0x3b, 0x41, 0x62, 0x72,
+0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x68,
+0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x41, 0x75, 0x67, 0x75,
+0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f,
+0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72,
+0x6f, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72,
+0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
+0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x74,
+0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63,
+0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x431, 0x440, 0x443,
+0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438,
+0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443,
+0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f,
+0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431,
+0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b,
+0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x458, 0x430, 0x43d, 0x3b,
+0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b,
+0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b,
+0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b,
+0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x458, 0x430, 0x43d, 0x3b, 0x444,
+0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b,
+0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b,
+0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x3b, 0x43e, 0x43a, 0x442,
+0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x6a, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d,
+0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61,
+0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x61, 0x72, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b,
+0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b,
+0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b,
+0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b,
+0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
+0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b,
+0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76,
+0x3b, 0x64, 0x65, 0x63, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b,
+0x46, 0x65, 0x62, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x63,
+0x68, 0x69, 0x3b, 0x41, 0x70, 0x6c, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69,
+0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65,
+0x6d, 0x62, 0x61, 0x4e, 0x64, 0x69, 0x72, 0x61, 0x3b, 0x4b, 0x75, 0x6b,
+0x61, 0x64, 0x7a, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x75, 0x6d, 0x65, 0x3b,
+0x4b, 0x75, 0x62, 0x76, 0x75, 0x6d, 0x62, 0x69, 0x3b, 0x43, 0x68, 0x69,
+0x76, 0x61, 0x62, 0x76, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6e, 0x67, 0x75, 0x72, 0x75,
+0x3b, 0x4e, 0x79, 0x61, 0x6d, 0x61, 0x76, 0x68, 0x75, 0x76, 0x68, 0x75,
+0x3b, 0x47, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x61, 0x3b, 0x47, 0x75, 0x6d,
+0x69, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x4d, 0x62, 0x75, 0x64, 0x7a, 0x69,
+0x3b, 0x5a, 0x76, 0x69, 0x74, 0x61, 0x4e, 0x64, 0x69, 0x3b, 0x4b, 0x75,
+0x6b, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x43, 0x68,
+0x76, 0x3b, 0x43, 0x68, 0x6b, 0x3b, 0x43, 0x68, 0x67, 0x3b, 0x4e, 0x79,
+0x61, 0x3b, 0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62,
+0x75, 0x3b, 0x5a, 0x76, 0x69, 0x4e, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47, 0x3b, 0x47,
+0x3b, 0x4d, 0x3b, 0x5a, 0xa2cd, 0xa1aa, 0x3b, 0xa44d, 0xa1aa, 0x3b, 0xa315, 0xa1aa,
+0x3b, 0xa1d6, 0xa1aa, 0x3b, 0xa26c, 0xa1aa, 0x3b, 0xa0d8, 0xa1aa, 0x3b, 0xa3c3, 0xa1aa,
+0x3b, 0xa246, 0xa1aa, 0x3b, 0xa22c, 0xa1aa, 0x3b, 0xa2b0, 0xa1aa, 0x3b, 0xa2b0, 0xa2aa,
+0xa1aa, 0x3b, 0xa2b0, 0xa44b, 0xa1aa, 0x6a, 0x69, 0x6e, 0x6e, 0x61, 0x72, 0x75,
+0x3b, 0x66, 0x72, 0x69, 0x76, 0x61, 0x72, 0x75, 0x3b, 0x6d, 0x61, 0x72,
+0x7a, 0x75, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61,
+0x6a, 0x75, 0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x75, 0x3b, 0x67, 0x69,
+0x75, 0x67, 0x6e, 0x65, 0x74, 0x74, 0x75, 0x3b, 0x61, 0x67, 0x75, 0x73,
+0x74, 0x75, 0x3b, 0x73, 0x69, 0x74, 0x74, 0xe8, 0x6d, 0x6d, 0x69, 0x72,
+0x75, 0x3b, 0x75, 0x74, 0x74, 0xf2, 0x76, 0x69, 0x72, 0x75, 0x3b, 0x6e,
+0x75, 0x76, 0xe8, 0x6d, 0x6d, 0x69, 0x72, 0x75, 0x3b, 0x64, 0x69, 0x63,
+0xe8, 0x6d, 0x6d, 0x69, 0x72, 0x75, 0x6a, 0x69, 0x6e, 0x3b, 0x66, 0x72,
+0x69, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61,
+0x6a, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x67, 0x6e, 0x74, 0x3b, 0x61, 0x67,
+0x75, 0x3b, 0x73, 0x69, 0x74, 0x3b, 0x75, 0x74, 0x74, 0x3b, 0x6e, 0x75,
+0x76, 0x3b, 0x64, 0x69, 0x63, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x55,
+0x3b, 0x4e, 0x3b, 0x44, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x79, 0x144, 0x3b,
+0x6c, 0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x65, 0x63, 0x3b,
+0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x79, 0x144, 0x3b, 0x6d, 0x6f, 0x6a,
+0x3b, 0x63, 0x7a, 0x79, 0x72, 0x77, 0x69, 0x65, 0x63, 0x3b, 0x6c, 0x69,
+0x70, 0x69, 0x65, 0x63, 0x3b, 0x73, 0x69, 0x79, 0x72, 0x70, 0x69, 0x79,
+0x144, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x73, 0x69, 0x79, 0x144, 0x3b, 0x70,
+0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x3b, 0x6c,
+0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67, 0x72, 0x75, 0x64,
+0x7a, 0x69, 0x79, 0x144, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61,
+0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x63,
+0x61, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x3b, 0x6d,
+0x6f, 0x6a, 0x61, 0x3b, 0x63, 0x7a, 0x79, 0x72, 0x77, 0x63, 0x61, 0x3b,
+0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x79, 0x72, 0x70, 0x6e,
+0x69, 0x61, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x15b, 0x6e, 0x69, 0x61, 0x3b,
+0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x61,
+0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x67,
+0x72, 0x75, 0x64, 0x6e, 0x69, 0x61, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75,
+0x74, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69, 0x3b, 0x6d, 0x6f,
+0x6a, 0x3b, 0x63, 0x7a, 0x79, 0x3b, 0x6c, 0x69, 0x70, 0x3b, 0x73, 0x69,
+0x79, 0x3b, 0x77, 0x72, 0x7a, 0x3b, 0x70, 0x61, 0x17a, 0x3b, 0x6c, 0x69,
+0x73, 0x3b, 0x67, 0x72, 0x75, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641,
+0x64a, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b,
+0x627, 0x67e, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x626, 0x64a, 0x3b, 0x62c, 0x648,
+0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x621, 0x650, 0x3b, 0x622, 0x6af, 0x633,
+0x67d, 0x3b, 0x633, 0x64a, 0x67e, 0x67d, 0x645, 0x628, 0x631, 0x3b, 0x622, 0x6aa,
+0x67d, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x68a,
+0x633, 0x645, 0x628, 0x631, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930,
+0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x941, 0x3b, 0x905,
+0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928,
+0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x91f,
+0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x911, 0x915,
+0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b,
+0x921, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b,
+0x92b, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x941,
+0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c,
+0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938,
+0x94d, 0x91f, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b,
+0x913, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c,
+0x930, 0x3b, 0x921, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x91c, 0x928, 0x3b, 0x92b,
+0x930, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930,
+0x948, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932,
+0x93e, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x3b, 0x911,
+0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x935, 0x902, 0x3b, 0x921, 0x93f, 0x938,
+0x902, 0x91c, 0x928, 0x3b, 0x92b, 0x930, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a,
+0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942,
+0x928, 0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x92a, 0x94d, 0x91f,
+0x947, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x935, 0x902, 0x3b,
+0x921, 0x93f, 0x938, 0x902, 0x91c, 0x3b, 0x92b, 0x93c, 0x3b, 0x92e, 0x3b, 0x905,
+0x3b, 0x92e, 0x93e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x917,
+0x3b, 0x938, 0x3b, 0x911, 0x3b, 0x928, 0x3b, 0x921, 0x93f, 0x91c, 0x3b, 0x92b,
+0x93c, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x93e, 0x3b, 0x91c, 0x942,
+0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x3b, 0x911, 0x3b, 0x928,
+0x3b, 0x921, 0x93f, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb4, 0xdd9,
+0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad,
+0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8,
+0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd,
+0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4, 0x3b, 0xdc3, 0xdd0,
+0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xd94, 0xd9a,
+0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8,
+0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6,
+0xdbb, 0xdca, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb,
+0xdca, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8,
+0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd,
+0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94,
+0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0,
+0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad,
+0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8,
+0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd,
+0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94,
+0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0,
+0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, 0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0,
+0x3b, 0xda2, 0xdd6, 0x3b, 0xda2, 0xdd6, 0x3b, 0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b,
+0xd94, 0x3b, 0xdb1, 0xdd9, 0x3b, 0xdaf, 0xdd9, 0x6a, 0x61, 0x6e, 0x75, 0xe1,
+0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61,
+0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1,
+0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x61, 0x3b,
+0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x6d, 0x61, 0x72,
+0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x61, 0x3b, 0x6d, 0xe1,
+0x6a, 0x61, 0x3b, 0x6a, 0xfa, 0x6e, 0x61, 0x3b, 0x6a, 0xfa, 0x6c, 0x61,
+0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70,
+0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62,
+0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b,
+0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x6a, 0x61, 0x6e, 0x3b,
+0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b,
+0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b,
+0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b,
+0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61,
+0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61,
+0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
+0x6a, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70,
+0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x2e,
+0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61,
+0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e,
+0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73,
+0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76,
+0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x4a, 0x61, 0x6e, 0x6e, 0x61, 0x61,
+0x79, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x61, 0x61, 0x79, 0x6f, 0x3b,
+0x4d, 0x61, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x69,
+0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4c,
+0x75, 0x75, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x74,
+0x6f, 0x3b, 0x53, 0x65, 0x62, 0x74, 0x65, 0x65, 0x6d, 0x62, 0x61, 0x72,
+0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f,
+0x6f, 0x66, 0x65, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x73,
+0x65, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20,
+0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68,
+0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
+0x68, 0x61, 0x20, 0x53, 0x61, 0x64, 0x64, 0x65, 0x78, 0x61, 0x61, 0x64,
+0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61, 0x61,
+0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e,
+0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x69,
+0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54,
+0x6f, 0x64, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68,
+0x61, 0x20, 0x53, 0x69, 0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64, 0x3b,
+0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c,
+0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f,
+0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20,
+0x4b, 0x6f, 0x77, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e,
+0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61,
+0x62, 0x61, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61,
+0x61, 0x64, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75,
+0x6e, 0x3b, 0x4c, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x73, 0x3b, 0x53, 0x65,
+0x62, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x66, 0x3b, 0x44, 0x69,
+0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x4c, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0x50, 0x68, 0x65, 0x73, 0x65, 0x6b, 0x67, 0x6f, 0x6e, 0x67, 0x3b, 0x48,
+0x6c, 0x61, 0x6b, 0x6f, 0x6c, 0x61, 0x3b, 0x48, 0x6c, 0x61, 0x6b, 0x75,
+0x62, 0x65, 0x6c, 0x65, 0x3b, 0x4d, 0x6d, 0x65, 0x73, 0x65, 0x3b, 0x4d,
+0x6f, 0x74, 0x73, 0x68, 0x65, 0x61, 0x6e, 0x6f, 0x6e, 0x67, 0x3b, 0x50,
+0x68, 0x75, 0x70, 0x6a, 0x61, 0x6e, 0x65, 0x3b, 0x50, 0x68, 0x75, 0x70,
+0x75, 0x3b, 0x50, 0x68, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x65, 0x6f, 0x74,
+0x73, 0x68, 0x65, 0x3b, 0x4d, 0x70, 0x68, 0x61, 0x6c, 0x61, 0x6e, 0x65,
+0x3b, 0x50, 0x75, 0x6e, 0x64, 0x75, 0x6e, 0x67, 0x77, 0x61, 0x6e, 0x65,
+0x3b, 0x54, 0x73, 0x68, 0x69, 0x74, 0x77, 0x65, 0x50, 0x68, 0x65, 0x3b,
+0x4b, 0x6f, 0x6c, 0x3b, 0x55, 0x62, 0x65, 0x3b, 0x4d, 0x6d, 0x65, 0x3b,
+0x4d, 0x6f, 0x74, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x55, 0x70, 0x75, 0x3b,
+0x50, 0x68, 0x61, 0x3b, 0x4c, 0x65, 0x6f, 0x3b, 0x4d, 0x70, 0x68, 0x3b,
+0x50, 0x75, 0x6e, 0x3b, 0x54, 0x73, 0x68, 0x4a, 0x61, 0x6e, 0x61, 0x62,
+0x61, 0x72, 0x69, 0x3b, 0x75, 0x46, 0x65, 0x62, 0x65, 0x72, 0x62, 0x61,
+0x72, 0x69, 0x3b, 0x75, 0x4d, 0x61, 0x74, 0x6a, 0x68, 0x69, 0x3b, 0x75,
+0x2d, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69,
+0x3b, 0x41, 0x72, 0x68, 0x6f, 0x73, 0x74, 0x6f, 0x73, 0x69, 0x3b, 0x53,
+0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x62, 0x61, 0x3b, 0x55, 0x73, 0x69, 0x6e, 0x79, 0x69, 0x6b, 0x68, 0x61,
+0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61,
+0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x74, 0x3b, 0x41, 0x70,
+0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
+0x6c, 0x3b, 0x41, 0x72, 0x68, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x55, 0x73, 0x69, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6e, 0x65,
+0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d,
+0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d,
+0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75,
+0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73,
+0x65, 0x70, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63,
+0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x65, 0x6e, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72,
+0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75, 0x6e,
+0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x70,
+0x74, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69,
+0x63, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61,
+0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e,
+0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61,
+0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e,
+0x65, 0x6e, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
+0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x3b,
+0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x65,
+0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f,
+0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b,
+0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f,
+0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f,
+0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x45, 0x6e, 0x65, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b,
+0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61,
+0x79, 0x2e, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e,
+0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f,
+0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x69, 0x63,
+0x2e, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d,
+0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79,
+0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b,
+0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e,
+0x2d49, 0x2d4f, 0x2d4f, 0x2d30, 0x2d62, 0x2d54, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x2d62, 0x2d55,
+0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x2d5a, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x2d49, 0x2d54, 0x3b,
+0x2d4e, 0x2d30, 0x2d62, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x2d62, 0x2d53, 0x3b,
+0x2d62, 0x2d53, 0x2d4d, 0x2d62, 0x2d53, 0x2d63, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x2d5c, 0x3b,
+0x2d5b, 0x2d53, 0x2d5c, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d3d, 0x2d5c, 0x2d53,
+0x2d31, 0x2d54, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b,
+0x2d37, 0x2d53, 0x2d4a, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x2d49, 0x2d4f, 0x2d4f, 0x3b,
+0x2d31, 0x2d55, 0x2d30, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x3b,
+0x2d4e, 0x2d30, 0x2d62, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x3b,
+0x2d56, 0x2d53, 0x2d5b, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x3b,
+0x2d4f, 0x2d53, 0x2d61, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e,
+0x3b, 0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62, 0x3b, 0x2d56, 0x3b, 0x2d5b,
+0x3b, 0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72,
+0x69, 0x3b, 0x50, 0xe9, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d,
+0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d,
+0xe9, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
+0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0xe9, 0x70,
+0x74, 0xe9, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x70, 0xe9, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x44, 0xe9, 0x73, 0xe9, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b,
+0x50, 0xe9, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0xe9, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x67, 0x73, 0x3b, 0x53, 0xe9, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x70, 0x3b, 0x44, 0xe9, 0x73, 0x4a, 0x3b, 0x50, 0x3b, 0x4d,
+0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x42, 0x68, 0x69, 0x6d, 0x62, 0x69,
+0x64, 0x76, 0x77, 0x61, 0x6e, 0x65, 0x3b, 0x69, 0x4e, 0x64, 0x6c, 0x6f,
+0x76, 0x61, 0x6e, 0x61, 0x3b, 0x69, 0x4e, 0x64, 0x6c, 0x6f, 0x76, 0x75,
+0x2d, 0x6c, 0x65, 0x6e, 0x6b, 0x68, 0x75, 0x6c, 0x75, 0x3b, 0x4d, 0x61,
+0x62, 0x61, 0x73, 0x61, 0x3b, 0x69, 0x4e, 0x6b, 0x68, 0x77, 0x65, 0x6b,
+0x68, 0x77, 0x65, 0x74, 0x69, 0x3b, 0x69, 0x4e, 0x68, 0x6c, 0x61, 0x62,
+0x61, 0x3b, 0x4b, 0x68, 0x6f, 0x6c, 0x77, 0x61, 0x6e, 0x65, 0x3b, 0x69,
+0x4e, 0x67, 0x63, 0x69, 0x3b, 0x69, 0x4e, 0x79, 0x6f, 0x6e, 0x69, 0x3b,
+0x69, 0x4d, 0x70, 0x68, 0x61, 0x6c, 0x61, 0x3b, 0x4c, 0x77, 0x65, 0x74,
+0x69, 0x3b, 0x69, 0x4e, 0x67, 0x6f, 0x6e, 0x67, 0x6f, 0x6e, 0x69, 0x42,
+0x68, 0x69, 0x3b, 0x56, 0x61, 0x6e, 0x3b, 0x56, 0x6f, 0x6c, 0x3b, 0x4d,
+0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x68, 0x3b, 0x4e, 0x68, 0x6c, 0x3b, 0x4b,
+0x68, 0x6f, 0x3b, 0x4e, 0x67, 0x63, 0x3b, 0x4e, 0x79, 0x6f, 0x3b, 0x4d,
+0x70, 0x68, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x4e, 0x67, 0x6f, 0x6a, 0x61,
+0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69,
+0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a,
+0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b,
+0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x6a,
+0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
+0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a,
+0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67,
+0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b,
+0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x4a, 0x61, 0x6e,
+0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b,
+0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d,
+0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
+0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x63, 0x68, 0x74, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x71f, 0x722,
+0x718, 0x722, 0x20, 0x710, 0x71a, 0x72a, 0x71d, 0x710, 0x3b, 0x72b, 0x712, 0x71b,
+0x3b, 0x710, 0x715, 0x72a, 0x3b, 0x722, 0x71d, 0x723, 0x722, 0x3b, 0x710, 0x71d,
+0x72a, 0x3b, 0x71a, 0x719, 0x71d, 0x72a, 0x722, 0x3b, 0x72c, 0x721, 0x718, 0x719,
+0x3b, 0x710, 0x712, 0x3b, 0x710, 0x71d, 0x720, 0x718, 0x720, 0x3b, 0x72c, 0x72b,
+0x72a, 0x71d, 0x722, 0x20, 0x729, 0x715, 0x721, 0x71d, 0x710, 0x3b, 0x72c, 0x72b,
+0x72a, 0x71d, 0x722, 0x20, 0x710, 0x71a, 0x72a, 0x71d, 0x710, 0x3b, 0x71f, 0x722,
+0x718, 0x722, 0x20, 0x729, 0x715, 0x721, 0x71d, 0x710, 0x71f, 0x722, 0x718, 0x722,
+0x20, 0x712, 0x3b, 0x72b, 0x712, 0x71b, 0x3b, 0x710, 0x715, 0x72a, 0x3b, 0x722,
+0x71d, 0x723, 0x722, 0x3b, 0x710, 0x71d, 0x72a, 0x3b, 0x71a, 0x719, 0x71d, 0x72a,
+0x722, 0x3b, 0x72c, 0x721, 0x718, 0x719, 0x3b, 0x710, 0x712, 0x3b, 0x710, 0x71d,
+0x720, 0x718, 0x720, 0x3b, 0x72c, 0x72b, 0x72a, 0x71d, 0x722, 0x20, 0x710, 0x3b,
+0x72c, 0x72b, 0x72a, 0x71d, 0x722, 0x20, 0x712, 0x3b, 0x71f, 0x722, 0x718, 0x722,
+0x20, 0x710, 0x71f, 0x3b, 0x72b, 0x3b, 0x710, 0x3b, 0x722, 0x3b, 0x710, 0x3b,
+0x72c, 0x3b, 0x71a, 0x3b, 0x710, 0x3b, 0x710, 0x3b, 0x72c, 0x3b, 0x72c, 0x3b,
+0x71f, 0x71f, 0x3b, 0x72b, 0x3b, 0x710, 0x3b, 0x722, 0x3b, 0x710, 0x3b, 0x71a,
+0x3b, 0x72c, 0x3b, 0x710, 0x3b, 0x710, 0x3b, 0x72c, 0x3b, 0x72c, 0x3b, 0x71f,
+0x69, 0x6e, 0x6e, 0x61, 0x79, 0x72, 0x3b, 0x62, 0x1e5b, 0x61, 0x79, 0x1e5b,
+0x3b, 0x6d, 0x61, 0x1e5b, 0x1e63, 0x3b, 0x69, 0x62, 0x72, 0x69, 0x72, 0x3b,
+0x6d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6e, 0x79, 0x75, 0x3b,
+0x79, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x263, 0x75, 0x63, 0x74, 0x3b,
+0x63, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x6b, 0x74, 0x75,
+0x62, 0x72, 0x3b, 0x6e, 0x75, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b,
+0x64, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x69, 0x6e, 0x6e, 0x3b,
+0x62, 0x1e5b, 0x61, 0x3b, 0x6d, 0x61, 0x1e5b, 0x3b, 0x69, 0x62, 0x72, 0x3b,
+0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b,
+0x263, 0x75, 0x63, 0x3b, 0x63, 0x75, 0x74, 0x3b, 0x6b, 0x74, 0x75, 0x3b,
+0x6e, 0x75, 0x77, 0x3b, 0x64, 0x75, 0x6a, 0x69, 0x3b, 0x62, 0x3b, 0x6d,
+0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x263, 0x3b, 0x63,
+0x3b, 0x6b, 0x3b, 0x6e, 0x3b, 0x64, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67,
+0x68, 0x77, 0x61, 0x20, 0x69, 0x6d, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4d,
+0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x77,
+0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20,
+0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x6f,
+0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61,
+0x6e, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61,
+0x20, 0x6b, 0x61, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d,
+0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6d, 0x66, 0x75,
+0x6e, 0x67, 0x61, 0x64, 0x65, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67,
+0x68, 0x77, 0x61, 0x20, 0x77, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61,
+0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69,
+0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67,
+0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x6f,
+0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b,
+0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b,
+0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x77, 0x69, 0x49, 0x6d,
+0x62, 0x3b, 0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61,
+0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4b, 0x61, 0x72, 0x3b, 0x4d, 0x66,
+0x75, 0x3b, 0x57, 0x75, 0x6e, 0x3b, 0x49, 0x6b, 0x65, 0x3b, 0x49, 0x6b,
+0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x77, 0x69, 0x49, 0x3b, 0x4b,
+0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x57,
+0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x42f, 0x43d, 0x432, 0x430,
+0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440,
+0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b,
+0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443,
+0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41e,
+0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x3b,
+0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0xb9c, 0xba9, 0xbb5, 0xbb0, 0xbbf, 0x3b,
+0xbaa, 0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0,
+0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae,
+0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b,
+0xb86, 0xb95, 0xbb8, 0xbcd, 0xb9f, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f,
+0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd, 0xb9f, 0xbcb, 0xbaa,
+0xbb0, 0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f,
+0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0xb9c, 0xba9, 0x2e, 0x3b, 0xbaa,
+0xbbf, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f,
+0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b,
+0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa,
+0xbcd, 0x2e, 0x3b, 0xb85, 0xb95, 0xbcd, 0x2e, 0x3b, 0xba8, 0xbb5, 0x2e, 0x3b,
+0xb9f, 0xbbf, 0xb9a, 0x2e, 0xb9c, 0x3b, 0xbaa, 0xbbf, 0x3b, 0xbae, 0xbbe, 0x3b,
+0xb8f, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb86,
+0x3b, 0xb9a, 0xbc6, 0x3b, 0xb85, 0x3b, 0xba8, 0x3b, 0xb9f, 0xbbf, 0x4b, 0x69,
+0x6e, 0x67, 0x61, 0x6c, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b, 0x44, 0x68,
+0x61, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b, 0x54, 0x72, 0x75, 0x20, 0x69,
+0x64, 0x61, 0x73, 0x3b, 0x53, 0x70, 0x61, 0x74, 0x20, 0x69, 0x64, 0x61,
+0x73, 0x3b, 0x52, 0x69, 0x6d, 0x61, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b,
+0x4d, 0x61, 0x74, 0x61, 0x72, 0x75, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b,
+0x45, 0x6d, 0x70, 0x69, 0x74, 0x75, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b,
+0x4d, 0x61, 0x73, 0x70, 0x61, 0x74, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b,
+0x4d, 0x6e, 0x67, 0x61, 0x72, 0x69, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b,
+0x4d, 0x61, 0x78, 0x61, 0x6c, 0x20, 0x69, 0x64, 0x61, 0x73, 0x3b, 0x4d,
+0x61, 0x78, 0x61, 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x61, 0x6c, 0x20,
+0x69, 0x64, 0x61, 0x73, 0x3b, 0x4d, 0x61, 0x78, 0x61, 0x6c, 0x20, 0x64,
+0x68, 0x61, 0x20, 0x69, 0x64, 0x61, 0x73, 0x4b, 0x69, 0x69, 0x3b, 0x44,
+0x68, 0x69, 0x3b, 0x54, 0x72, 0x69, 0x3b, 0x53, 0x70, 0x69, 0x3b, 0x52,
+0x69, 0x69, 0x3b, 0x4d, 0x74, 0x69, 0x3b, 0x45, 0x6d, 0x69, 0x3b, 0x4d,
+0x61, 0x69, 0x3b, 0x4d, 0x6e, 0x69, 0x3b, 0x4d, 0x78, 0x69, 0x3b, 0x4d,
+0x78, 0x6b, 0x3b, 0x4d, 0x78, 0x64, 0x4b, 0x3b, 0x44, 0x3b, 0x54, 0x3b,
+0x53, 0x3b, 0x52, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x4b, 0x3b, 0x44, 0x433, 0x44b, 0x439, 0x43d, 0x432, 0x430, 0x440,
+0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440,
+0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x439,
+0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430,
+0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431,
+0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d,
+0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440,
+0x44c, 0x433, 0x44b, 0x439, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b,
+0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430,
+0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b,
+0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e,
+0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435,
+0x43a, 0x2e, 0xc1c, 0xc28, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d,
+0xc30, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b,
+0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0xc32, 0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c,
+0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38,
+0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0xc2c,
+0xc30, 0xc4d, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0xc2c, 0xc30, 0xc4d, 0x3b,
+0xc28, 0xc35, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02,
+0xc2c, 0xc30, 0xc4d, 0xc1c, 0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b,
+0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f,
+0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32,
+0xc48, 0x3b, 0xc06, 0xc17, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02,
+0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21,
+0xc3f, 0xc38, 0xc46, 0xc02, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0x3b,
+0xc0f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06,
+0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21, 0xc3f, 0x4f, 0x72,
+0x61, 0x72, 0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77,
+0x61, 0x6d, 0x67, 0x2019, 0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67, 0x2019, 0x65,
+0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d, 0x6f,
+0x64, 0x6f, 0x6b, 0x2019, 0x6b, 0x69, 0x6e, 0x67, 0x2019, 0x6f, 0x6c, 0x3b,
+0x4f, 0x6a, 0x6f, 0x6c, 0x61, 0x3b, 0x4f, 0x70, 0x65, 0x64, 0x65, 0x6c,
+0x3b, 0x4f, 0x73, 0x6f, 0x6b, 0x6f, 0x73, 0x6f, 0x6b, 0x6f, 0x6d, 0x61,
+0x3b, 0x4f, 0x74, 0x69, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6c, 0x61, 0x62,
+0x6f, 0x72, 0x3b, 0x4f, 0x70, 0x6f, 0x6f, 0x52, 0x61, 0x72, 0x3b, 0x4d,
+0x75, 0x6b, 0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x44, 0x75, 0x6e, 0x3b, 0x4d,
+0x61, 0x72, 0x3b, 0x4d, 0x6f, 0x64, 0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x50,
+0x65, 0x64, 0x3b, 0x53, 0x6f, 0x6b, 0x3b, 0x54, 0x69, 0x62, 0x3b, 0x4c,
+0x61, 0x62, 0x3b, 0x50, 0x6f, 0x6f, 0x52, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b,
+0x44, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b,
+0x54, 0x3b, 0x4c, 0x3b, 0x50, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b,
+0xe01, 0xe38, 0xe21, 0xe20, 0xe32, 0xe1e, 0xe31, 0xe19, 0xe18, 0xe4c, 0x3b, 0xe21,
+0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29, 0xe32, 0xe22, 0xe19,
+0x3b, 0xe1e, 0xe24, 0xe29, 0xe20, 0xe32, 0xe04, 0xe21, 0x3b, 0xe21, 0xe34, 0xe16,
+0xe38, 0xe19, 0xe32, 0xe22, 0xe19, 0x3b, 0xe01, 0xe23, 0xe01, 0xe0e, 0xe32, 0xe04,
+0xe21, 0x3b, 0xe2a, 0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31,
+0xe19, 0xe22, 0xe32, 0xe22, 0xe19, 0x3b, 0xe15, 0xe38, 0xe25, 0xe32, 0xe04, 0xe21,
+0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22, 0xe19, 0x3b, 0xe18,
+0xe31, 0xe19, 0xe27, 0xe32, 0xe04, 0xe21, 0xe21, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01,
+0x2e, 0xe1e, 0x2e, 0x3b, 0xe21, 0xe35, 0x2e, 0xe04, 0x2e, 0x3b, 0xe40, 0xe21,
+0x2e, 0xe22, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e,
+0xe22, 0x2e, 0x3b, 0xe01, 0x2e, 0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04, 0x2e,
+0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04, 0x2e, 0x3b, 0xe1e,
+0x2e, 0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04, 0x2e, 0xf5f, 0xfb3, 0xf0b, 0xf56,
+0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
+0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45,
+0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
+0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51,
+0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf45, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45,
+0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54,
+0x1303, 0x1295, 0x12e9, 0x12c8, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12c8, 0x122a, 0x3b,
+0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x1228, 0x120d, 0x3b, 0x121c, 0x12ed, 0x3b,
+0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b,
+0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b, 0x12a6, 0x12ad, 0x1270, 0x12cd, 0x1260,
+0x122d, 0x3b, 0x1296, 0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260,
+0x122d, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b, 0x122d, 0x127d,
+0x3b, 0x12a4, 0x1355, 0x1228, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301,
+0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x3b, 0x1234, 0x1355, 0x1274, 0x3b, 0x12a6,
+0x12ad, 0x1270, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1325, 0x122a,
+0x3b, 0x1208, 0x12ab, 0x1272, 0x1275, 0x3b, 0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a,
+0x12eb, 0x12dd, 0x12eb, 0x3b, 0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290, 0x3b,
+0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x1228,
+0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b, 0x1215, 0x12f3, 0x122d, 0x3b, 0x1273,
+0x1215, 0x1233, 0x1235, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x3b, 0x1218, 0x130b, 0x3b,
+0x121a, 0x12eb, 0x3b, 0x130d, 0x1295, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x3b,
+0x1290, 0x1213, 0x3b, 0x1218, 0x1235, 0x3b, 0x1325, 0x1245, 0x3b, 0x1215, 0x12f3, 0x3b,
+0x1273, 0x1215, 0x1325, 0x3b, 0x1208, 0x3b, 0x1218, 0x3b, 0x121a, 0x3b, 0x130d, 0x3b,
+0x1230, 0x3b, 0x1213, 0x3b, 0x1290, 0x3b, 0x1218, 0x3b, 0x1325, 0x3b, 0x1215, 0x3b,
+0x1273, 0x4a, 0x61, 0x6e, 0x75, 0x65, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62,
+0x72, 0x75, 0x65, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x45, 0x70,
+0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a,
+0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65,
+0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x3b,
+0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b,
+0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
+0x44, 0x65, 0x73, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46,
+0x113, 0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x73,
+0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65, 0x6c, 0x69, 0x3b, 0x4d,
+0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x75, 0x6c, 0x61,
+0x69, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x65,
+0x70, 0x69, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74,
+0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61, 0x3b, 0x54,
+0x12b, 0x73, 0x65, 0x6d, 0x61, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69,
+0x3b, 0x46, 0x113, 0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb,
+0x61, 0x73, 0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65, 0x6c, 0x69,
+0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x75,
+0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x6f, 0x73, 0x69, 0x3b,
+0x53, 0x113, 0x70, 0x69, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b,
+0x61, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61,
+0x3b, 0x54, 0x12b, 0x73, 0x65, 0x6d, 0x61, 0x53, 0x101, 0x6e, 0x3b, 0x46,
+0x113, 0x70, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x3b, 0x2bb, 0x45, 0x70, 0x65,
+0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75, 0x3b,
+0x2bb, 0x41, 0x6f, 0x6b, 0x3b, 0x53, 0x113, 0x70, 0x3b, 0x2bb, 0x4f, 0x6b,
+0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54, 0x12b, 0x73, 0x53, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x2bb, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b,
+0x2bb, 0x41, 0x3b, 0x53, 0x3b, 0x2bb, 0x4f, 0x3b, 0x4e, 0x3b, 0x54, 0x53,
+0x75, 0x6e, 0x67, 0x75, 0x74, 0x69, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79,
+0x65, 0x6e, 0x79, 0x61, 0x6e, 0x69, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79,
+0x61, 0x6e, 0x6b, 0x75, 0x6c, 0x75, 0x3b, 0x44, 0x7a, 0x69, 0x76, 0x61,
+0x6d, 0x69, 0x73, 0x6f, 0x6b, 0x6f, 0x3b, 0x4d, 0x75, 0x64, 0x79, 0x61,
+0x78, 0x69, 0x68, 0x69, 0x3b, 0x4b, 0x68, 0x6f, 0x74, 0x61, 0x76, 0x75,
+0x78, 0x69, 0x6b, 0x61, 0x3b, 0x4d, 0x61, 0x77, 0x75, 0x77, 0x61, 0x6e,
+0x69, 0x3b, 0x4d, 0x68, 0x61, 0x77, 0x75, 0x72, 0x69, 0x3b, 0x4e, 0x64,
+0x7a, 0x68, 0x61, 0x74, 0x69, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67,
+0x75, 0x6c, 0x61, 0x3b, 0x48, 0x75, 0x6b, 0x75, 0x72, 0x69, 0x3b, 0x4e,
+0x2019, 0x77, 0x65, 0x6e, 0x64, 0x7a, 0x61, 0x6d, 0x68, 0x61, 0x6c, 0x61,
+0x53, 0x75, 0x6e, 0x3b, 0x59, 0x61, 0x6e, 0x3b, 0x4b, 0x75, 0x6c, 0x3b,
+0x44, 0x7a, 0x69, 0x3b, 0x4d, 0x75, 0x64, 0x3b, 0x4b, 0x68, 0x6f, 0x3b,
+0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x68, 0x61, 0x3b, 0x4e, 0x64, 0x7a, 0x3b,
+0x4e, 0x68, 0x6c, 0x3b, 0x48, 0x75, 0x6b, 0x3b, 0x4e, 0x2019, 0x77, 0x46,
+0x65, 0x72, 0x69, 0x6b, 0x67, 0x6f, 0x6e, 0x67, 0x3b, 0x54, 0x6c, 0x68,
+0x61, 0x6b, 0x6f, 0x6c, 0x65, 0x3b, 0x4d, 0x6f, 0x70, 0x69, 0x74, 0x6c,
+0x6f, 0x3b, 0x4d, 0x6f, 0x72, 0x61, 0x6e, 0x61, 0x6e, 0x67, 0x3b, 0x4d,
+0x6f, 0x74, 0x73, 0x68, 0x65, 0x67, 0x61, 0x6e, 0x61, 0x6e, 0x67, 0x3b,
+0x53, 0x65, 0x65, 0x74, 0x65, 0x62, 0x6f, 0x73, 0x69, 0x67, 0x6f, 0x3b,
+0x50, 0x68, 0x75, 0x6b, 0x77, 0x69, 0x3b, 0x50, 0x68, 0x61, 0x74, 0x77,
+0x65, 0x3b, 0x4c, 0x77, 0x65, 0x74, 0x73, 0x65, 0x3b, 0x44, 0x69, 0x70,
+0x68, 0x61, 0x6c, 0x61, 0x6e, 0x65, 0x3b, 0x4e, 0x67, 0x77, 0x61, 0x6e,
+0x61, 0x74, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x53, 0x65, 0x64, 0x69, 0x6d,
+0x6f, 0x6e, 0x74, 0x68, 0x6f, 0x6c, 0x65, 0x46, 0x65, 0x72, 0x3b, 0x54,
+0x6c, 0x68, 0x3b, 0x4d, 0x6f, 0x70, 0x3b, 0x4d, 0x6f, 0x72, 0x3b, 0x4d,
+0x6f, 0x74, 0x3b, 0x53, 0x65, 0x65, 0x3b, 0x50, 0x68, 0x75, 0x3b, 0x50,
+0x68, 0x61, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x44, 0x69, 0x70, 0x3b, 0x4e,
+0x67, 0x77, 0x3b, 0x53, 0x65, 0x64, 0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e,
+0x75, 0x62, 0x61, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x4e, 0x69,
+0x73, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61,
+0x7a, 0x69, 0x72, 0x61, 0x6e, 0x3b, 0x54, 0x65, 0x6d, 0x6d, 0x75, 0x7a,
+0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73, 0x3b, 0x45, 0x79, 0x6c,
+0xfc, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131,
+0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6c, 0x131, 0x6b, 0x4f, 0x63, 0x61, 0x3b,
+0x15e, 0x75, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b,
+0x4d, 0x61, 0x79, 0x3b, 0x48, 0x61, 0x7a, 0x3b, 0x54, 0x65, 0x6d, 0x3b,
+0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x3b,
+0x4b, 0x61, 0x73, 0x3b, 0x41, 0x72, 0x61, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d,
+0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x45,
+0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0xdd, 0x61, 0x6e, 0x77, 0x61, 0x72,
+0x3b, 0x46, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74,
+0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0xfd, 0x3b, 0x49,
+0xfd, 0x75, 0x6e, 0x3b, 0x49, 0xfd, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x67,
+0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0xfd, 0x61, 0x62, 0x72,
+0x3b, 0x4f, 0x6b, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0xfd,
+0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0xfd, 0x61,
+0x6e, 0x77, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b,
+0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d,
+0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c,
+0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74,
+0xfd, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xfd, 0x61, 0x62, 0x72,
+0x3b, 0x6e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61,
+0x62, 0x72, 0xdd, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x77, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0xfd, 0x3b, 0x49, 0xfd,
+0x75, 0x6e, 0x3b, 0x49, 0xfd, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x67, 0x3b,
+0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0xfd, 0x3b,
+0x44, 0x65, 0x6b, 0xfd, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x77, 0x3b, 0x6d,
+0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xfd, 0x3b,
+0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b, 0x61, 0x77,
+0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f,
+0xfd, 0x3b, 0x64, 0x65, 0x6b, 0xdd, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x4a, 0x75, 0x77,
+0x75, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x53, 0x77, 0x69,
+0x79, 0x61, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x54, 0x73,
+0x61, 0x74, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x4e, 0x79, 0x61, 0x69,
+0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x54, 0x73, 0x77, 0x6f, 0x6e, 0x3b,
+0x5a, 0x77, 0x61, 0x74, 0x20, 0x41, 0x74, 0x61, 0x61, 0x68, 0x3b, 0x5a,
+0x77, 0x61, 0x74, 0x20, 0x41, 0x6e, 0x61, 0x74, 0x61, 0x74, 0x3b, 0x5a,
+0x77, 0x61, 0x74, 0x20, 0x41, 0x72, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x5a,
+0x77, 0x61, 0x74, 0x20, 0x41, 0x6b, 0x75, 0x62, 0x75, 0x6e, 0x79, 0x75,
+0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x53, 0x77, 0x61, 0x67,
+0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x4d, 0x61, 0x6e, 0x67, 0x6a, 0x75,
+0x77, 0x61, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x53, 0x77,
+0x61, 0x67, 0x2d, 0x4d, 0x61, 0x2d, 0x53, 0x75, 0x79, 0x61, 0x6e, 0x67,
+0x4a, 0x75, 0x77, 0x3b, 0x53, 0x77, 0x69, 0x3b, 0x54, 0x73, 0x61, 0x3b,
+0x4e, 0x79, 0x61, 0x3b, 0x54, 0x73, 0x77, 0x3b, 0x41, 0x74, 0x61, 0x3b,
+0x41, 0x6e, 0x61, 0x3b, 0x41, 0x72, 0x69, 0x3b, 0x41, 0x6b, 0x75, 0x3b,
+0x53, 0x77, 0x61, 0x3b, 0x4d, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x73, 0x441,
+0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442, 0x438, 0x439, 0x3b,
+0x431, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x432, 0x456,
+0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c,
+0x3b, 0x447, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x43f,
+0x435, 0x43d, 0x44c, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b,
+0x432, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x436, 0x43e, 0x432,
+0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430,
+0x434, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c, 0x441, 0x456, 0x447,
+0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, 0x435,
+0x440, 0x435, 0x437, 0x43d, 0x44f, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x43d, 0x44f,
+0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, 0x3b, 0x447, 0x435, 0x440, 0x432,
+0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440,
+0x43f, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x43d, 0x44f, 0x3b,
+0x436, 0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e,
+0x43f, 0x430, 0x434, 0x430, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x43d, 0x44f, 0x441,
+0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e, 0x442, 0x2e, 0x3b, 0x431, 0x435, 0x440,
+0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, 0x442, 0x440, 0x430, 0x432,
+0x2e, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e,
+0x3b, 0x441, 0x435, 0x440, 0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440, 0x2e, 0x3b,
+0x436, 0x43e, 0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b,
+0x433, 0x440, 0x443, 0x434, 0x2e, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a,
+0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b, 0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416,
+0x3b, 0x41b, 0x3b, 0x413, 0x441, 0x3b, 0x43b, 0x3b, 0x431, 0x3b, 0x43a, 0x3b,
+0x442, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x432, 0x3b, 0x436, 0x3b,
+0x43b, 0x3b, 0x433, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61,
+0x70, 0x72, 0x79, 0x6c, 0x3b, 0x6d, 0x65, 0x6a, 0x61, 0x3b, 0x6a, 0x75,
+0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x77,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e,
+0x6f, 0x77, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x61, 0x3b,
+0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x6d, 0x11b, 0x72,
+0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x65,
+0x6a, 0x65, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75,
+0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61,
+0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f,
+0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d,
+0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61,
+0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b,
+0x61, 0x70, 0x72, 0x3b, 0x6d, 0x65, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
+0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b,
+0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x6a,
+0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72,
+0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x6a, 0x2e, 0x3b,
+0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x77,
+0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e,
+0x3b, 0x6e, 0x6f, 0x77, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x62c, 0x646,
+0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627,
+0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc,
+0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 0x6cc, 0x3b,
+0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627,
+0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b,
+0x62f, 0x633, 0x645, 0x628, 0x631, 0x64a, 0x627, 0x646, 0x6cb, 0x627, 0x631, 0x3b,
+0x641, 0x6d0, 0x6cb, 0x631, 0x627, 0x644, 0x3b, 0x645, 0x627, 0x631, 0x62a, 0x3b,
+0x626, 0x627, 0x67e, 0x631, 0x6d0, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x626,
+0x649, 0x64a, 0x6c7, 0x646, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x644, 0x3b, 0x626,
+0x627, 0x6cb, 0x63a, 0x6c7, 0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x646, 0x62a, 0x6d5,
+0x628, 0x649, 0x631, 0x3b, 0x626, 0x6c6, 0x643, 0x62a, 0x6d5, 0x628, 0x649, 0x631,
+0x3b, 0x646, 0x648, 0x64a, 0x627, 0x628, 0x649, 0x631, 0x3b, 0x62f, 0x6d0, 0x643,
+0x627, 0x628, 0x649, 0x631, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46,
+0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41,
+0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75,
+0x6e, 0x3b, 0x49, 0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73,
+0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b,
+0x74, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b,
+0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72,
+0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74,
+0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69,
+0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67,
+0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b,
+0x6f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62,
+0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x59, 0x61, 0x6e, 0x3b,
+0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x6e, 0x3b, 0x49, 0x79, 0x6c, 0x3b,
+0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x79, 0x3b, 0x44, 0x65, 0x6b, 0x79, 0x61, 0x6e, 0x3b, 0x66,
+0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
+0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61,
+0x76, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e,
+0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b,
+0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631,
+0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627, 0x67e, 0x631, 0x3b, 0x645, 0x6cc, 0x3b,
+0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x3b,
+0x633, 0x67e, 0x62a, 0x3b, 0x627, 0x6a9, 0x62a, 0x3b, 0x646, 0x648, 0x645, 0x3b,
+0x62f, 0x633, 0x645, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432,
+0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440,
+0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438,
+0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435,
+0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440,
+0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431,
+0x440, 0xa5a8, 0xa595, 0x20, 0xa56a, 0xa574, 0x20, 0xa51e, 0xa500, 0xa56e, 0xa54a, 0x3b,
+0xa552, 0xa561, 0xa59d, 0xa595, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595, 0x3b, 0xa591,
+0xa571, 0x3b, 0xa5b1, 0xa60b, 0x3b, 0xa5b1, 0xa55e, 0xa524, 0x3b, 0xa5db, 0xa515, 0x3b,
+0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0xa554, 0xa57f, 0x20, 0xa578,
+0xa583, 0xa5cf, 0x3b, 0xa5a8, 0xa595, 0x20, 0xa56a, 0xa574, 0x20, 0xa5cf, 0xa5ba, 0xa56e,
+0xa54a, 0xa5a8, 0xa595, 0xa51e, 0x3b, 0xa552, 0xa561, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2,
+0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0xa5b1, 0xa60b, 0x3b, 0xa5b1, 0xa55e, 0x3b, 0xa5db,
+0xa515, 0x3b, 0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0x3b, 0xa5a8,
+0xa595, 0xa5cf, 0x50, 0x68, 0x61, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x75, 0x68,
+0x75, 0x68, 0x69, 0x3b, 0x1e70, 0x68, 0x61, 0x66, 0x61, 0x6d, 0x75, 0x68,
+0x77, 0x65, 0x3b, 0x4c, 0x61, 0x6d, 0x62, 0x61, 0x6d, 0x61, 0x69, 0x3b,
+0x53, 0x68, 0x75, 0x6e, 0x64, 0x75, 0x6e, 0x74, 0x68, 0x75, 0x6c, 0x65,
+0x3b, 0x46, 0x75, 0x6c, 0x77, 0x69, 0x3b, 0x46, 0x75, 0x6c, 0x77, 0x61,
+0x6e, 0x61, 0x3b, 0x1e70, 0x68, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x65, 0x3b,
+0x4b, 0x68, 0x75, 0x62, 0x76, 0x75, 0x6d, 0x65, 0x64, 0x7a, 0x69, 0x3b,
+0x54, 0x73, 0x68, 0x69, 0x6d, 0x65, 0x64, 0x7a, 0x69, 0x3b, 0x1e3c, 0x61,
+0x72, 0x61, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x64, 0x61, 0x76, 0x68, 0x75,
+0x73, 0x69, 0x6b, 0x75, 0x50, 0x68, 0x61, 0x3b, 0x4c, 0x75, 0x68, 0x3b,
+0x1e70, 0x68, 0x66, 0x3b, 0x4c, 0x61, 0x6d, 0x3b, 0x53, 0x68, 0x75, 0x3b,
+0x4c, 0x77, 0x69, 0x3b, 0x4c, 0x77, 0x61, 0x3b, 0x1e70, 0x68, 0x61, 0x3b,
+0x4b, 0x68, 0x75, 0x3b, 0x54, 0x73, 0x68, 0x3b, 0x1e3c, 0x61, 0x72, 0x3b,
+0x4e, 0x79, 0x65, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x3b, 0x54,
+0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67,
+0x20, 0x33, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x54,
+0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67,
+0x20, 0x36, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37, 0x3b, 0x54,
+0x68, 0xe1, 0x6e, 0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67,
+0x20, 0x39, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30, 0x3b,
+0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x54, 0x68, 0xe1,
+0x6e, 0x67, 0x20, 0x31, 0x32, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31,
+0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0xe1,
+0x6e, 0x67, 0x20, 0x33, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34,
+0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b, 0x74, 0x68, 0xe1,
+0x6e, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37,
+0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x38, 0x3b, 0x74, 0x68, 0xe1,
+0x6e, 0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31,
+0x30, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x74,
+0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x32, 0x74, 0x68, 0x67, 0x20, 0x31,
+0x3b, 0x74, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x33,
+0x3b, 0x74, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x35,
+0x3b, 0x74, 0x68, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x37,
+0x3b, 0x74, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x39,
+0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x74, 0x68, 0x67, 0x20,
+0x31, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x32, 0x79, 0x61, 0x6e,
+0x75, 0x6c, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x6c, 0x3b, 0x6d, 0xe4, 0x7a,
+0x75, 0x6c, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x75, 0x6c, 0x3b, 0x6d, 0x61,
+0x79, 0x75, 0x6c, 0x3b, 0x79, 0x75, 0x6e, 0x75, 0x6c, 0x3b, 0x79, 0x75,
+0x6c, 0x75, 0x6c, 0x3b, 0x67, 0x75, 0x73, 0x74, 0x75, 0x6c, 0x3b, 0x73,
+0x65, 0x74, 0x75, 0x6c, 0x3b, 0x74, 0x6f, 0x62, 0x75, 0x6c, 0x3b, 0x6e,
+0x6f, 0x76, 0x75, 0x6c, 0x3b, 0x64, 0x65, 0x6b, 0x75, 0x6c, 0x79, 0x61,
+0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0xe4, 0x7a, 0x3b, 0x70, 0x72,
+0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75,
+0x6c, 0x3b, 0x67, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x74, 0x6f,
+0x62, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x6b, 0x79, 0x61, 0x6e,
+0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0xe4, 0x7a, 0x3b, 0x70, 0x72, 0x6c,
+0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c,
+0x3b, 0x67, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x74, 0x6f, 0x6e,
+0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x6b, 0x59, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x47, 0x3b,
+0x53, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x4a, 0x65, 0x6e, 0x6e, 0x65,
+0x72, 0x3b, 0x48, 0x6f, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0x72,
+0x7a, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x65, 0x3b, 0x4d,
+0x65, 0x69, 0x6a, 0x65, 0x3b, 0x42, 0x72, 0xe1, 0x10d, 0x65, 0x74, 0x3b,
+0x48, 0x65, 0x69, 0x77, 0x65, 0x74, 0x3b, 0xd6, 0x69, 0x67, 0x161, 0x74,
+0x65, 0x3b, 0x48, 0x65, 0x72, 0x62, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65,
+0x74, 0x3b, 0x57, 0xed, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0x69,
+0x6e, 0x74, 0x65, 0x72, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x43, 0x68,
+0x72, 0x69, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x4a, 0x65, 0x6e,
+0x3b, 0x48, 0x6f, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x62, 0x72,
+0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x42, 0x72, 0xe1, 0x3b, 0x48, 0x65, 0x69,
+0x3b, 0xd6, 0x69, 0x67, 0x3b, 0x48, 0x65, 0x72, 0x3b, 0x57, 0xed, 0x6d,
+0x3b, 0x57, 0x69, 0x6e, 0x3b, 0x43, 0x68, 0x72, 0x4a, 0x3b, 0x48, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x48, 0x3b, 0xd6, 0x3b,
+0x48, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x43, 0x49, 0x6f, 0x6e, 0x61, 0x77,
+0x72, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x72, 0x6f, 0x72, 0x3b, 0x4d,
+0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x45, 0x62, 0x72, 0x69, 0x6c, 0x6c,
+0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x65, 0x66, 0x69, 0x6e,
+0x3b, 0x47, 0x6f, 0x72, 0x66, 0x66, 0x65, 0x6e, 0x6e, 0x61, 0x66, 0x3b,
+0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79,
+0x64, 0x72, 0x65, 0x66, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x77, 0x65, 0x64,
+0x64, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x66, 0x79, 0x72, 0x49, 0x6f, 0x6e,
+0x3b, 0x43, 0x68, 0x77, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x45, 0x62, 0x72,
+0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x3b, 0x47, 0x6f, 0x72,
+0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48,
+0x79, 0x64, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x3b, 0x52, 0x68, 0x61, 0x67,
+0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x3b, 0x4d, 0x61,
+0x77, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65,
+0x68, 0x3b, 0x47, 0x6f, 0x72, 0x66, 0x66, 0x3b, 0x41, 0x77, 0x73, 0x74,
+0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x3b, 0x54, 0x61,
+0x63, 0x68, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x49, 0x3b, 0x43, 0x68, 0x3b,
+0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x52, 0x68, 0x4a, 0x61, 0x6e, 0x6e,
+0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65,
+0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b,
+0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x61, 0x69, 0x65, 0x3b,
+0x4a, 0x75, 0x6e, 0x79, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x69,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
+0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65,
+0x73, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75,
+0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x65, 0x73, 0x53, 0x61, 0x6d, 0x77, 0x69, 0x79, 0x65,
+0x65, 0x3b, 0x46, 0x65, 0x77, 0x72, 0x69, 0x79, 0x65, 0x65, 0x3b, 0x4d,
+0x61, 0x72, 0x73, 0x3b, 0x41, 0x77, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65,
+0x65, 0x3b, 0x53, 0x75, 0x77, 0x65, 0x3b, 0x53, 0x75, 0x6c, 0x65, 0x74,
+0x3b, 0x55, 0x74, 0x3b, 0x53, 0xe0, 0x74, 0x74, 0x75, 0x6d, 0x62, 0x61,
+0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e,
+0x6f, 0x77, 0xe0, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x73, 0xe0,
+0x6d, 0x62, 0x61, 0x72, 0x53, 0x61, 0x6d, 0x3b, 0x46, 0x65, 0x77, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b,
+0x53, 0x75, 0x77, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x55, 0x74, 0x3b, 0x53,
+0xe0, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x77, 0x3b, 0x44,
+0x65, 0x73, 0x4a, 0x61, 0x6e, 0x79, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b,
+0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61,
+0x74, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b,
+0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75,
+0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b,
+0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74,
+0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x79,
+0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77,
+0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x74, 0x73, 0x68, 0x69, 0x3b, 0x45,
+0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41,
+0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x68, 0x61, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65,
+0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d,
+0x61, 0x74, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a,
+0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x61, 0x3b, 0x53,
+0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44,
+0x69, 0x73, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61,
+0x74, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x75,
+0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x61, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44,
+0x69, 0x73, 0x70, 0x69, 0x6b, 0xed, 0x74, 0xed, 0x6b, 0xed, 0x74, 0x69,
+0x65, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0xed, 0x20, 0xfa, 0x20, 0x6b, 0x75,
+0x74, 0xfa, 0x61, 0x6e, 0x3b, 0x73, 0x69, 0x25b, 0x79, 0x25b, 0x301, 0x2c,
+0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x6e, 0x64,
+0xed, 0x25b, 0x3b, 0x254, 0x6e, 0x73, 0xfa, 0x6d, 0x62, 0x254, 0x6c, 0x2c,
+0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1,
+0x74, 0xfa, 0x25b, 0x3b, 0x6d, 0x65, 0x73, 0x69, 0x14b, 0x2c, 0x20, 0x6f,
+0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe9, 0x6e, 0x69, 0x65, 0x3b,
+0x65, 0x6e, 0x73, 0x69, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20,
+0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x6e, 0x75, 0x25b, 0x3b, 0x254, 0x73,
+0x254, 0x6e, 0x3b, 0x65, 0x66, 0x75, 0x74, 0x65, 0x3b, 0x70, 0x69, 0x73,
+0x75, 0x79, 0xfa, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70,
+0x75, 0x254, 0x73, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70,
+0x75, 0x74, 0xfa, 0x6b, 0x2c, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20,
+0x6b, 0xe1, 0x74, 0xed, 0x25b, 0x3b, 0x6d, 0x61, 0x6b, 0x61, 0x6e, 0x64,
+0x69, 0x6b, 0x25b, 0x3b, 0x70, 0x69, 0x6c, 0x254, 0x6e, 0x64, 0x254, 0x301,
+0x6f, 0x2e, 0x31, 0x3b, 0x6f, 0x2e, 0x32, 0x3b, 0x6f, 0x2e, 0x33, 0x3b,
+0x6f, 0x2e, 0x34, 0x3b, 0x6f, 0x2e, 0x35, 0x3b, 0x6f, 0x2e, 0x36, 0x3b,
+0x6f, 0x2e, 0x37, 0x3b, 0x6f, 0x2e, 0x38, 0x3b, 0x6f, 0x2e, 0x39, 0x3b,
+0x6f, 0x2e, 0x31, 0x30, 0x3b, 0x6f, 0x2e, 0x31, 0x31, 0x3b, 0x6f, 0x2e,
+0x31, 0x32, 0x5d9, 0x5d0, 0x5b7, 0x5e0, 0x5d5, 0x5d0, 0x5b7, 0x5e8, 0x3b, 0x5e4,
+0x5bf, 0x5e2, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5b7, 0x5e8, 0x3b, 0x5de, 0x5e2, 0x5e8,
+0x5e5, 0x3b, 0x5d0, 0x5b7, 0x5e4, 0x5bc, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d9,
+0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b,
+0x5d0, 0x5d5, 0x5d9, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e2, 0x5e4, 0x5bc,
+0x5d8, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x3b, 0x5d0, 0x5e7, 0x5d8, 0x5d0, 0x5d1,
+0x5e2, 0x5e8, 0x3b, 0x5e0, 0x5d0, 0x5d5, 0x5d5, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8,
+0x3b, 0x5d3, 0x5e2, 0x5e6, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x5d9, 0x5d0, 0x5b7,
+0x5e0, 0x3b, 0x5e4, 0x5bf, 0x5e2, 0x5d1, 0x3b, 0x5de, 0x5e2, 0x5e8, 0x5e5, 0x3b,
+0x5d0, 0x5b7, 0x5e4, 0x5bc, 0x5e8, 0x3b, 0x5de, 0x5d9, 0x5d9, 0x3b, 0x5d9, 0x5d5,
+0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d9, 0x5d2,
+0x3b, 0x5e1, 0x5e2, 0x5e4, 0x5bc, 0x3b, 0x5d0, 0x5e7, 0x5d8, 0x3b, 0x5e0, 0x5d0,
+0x5d5, 0x5d5, 0x3b, 0x5d3, 0x5e2, 0x5e6, 0x1e62, 0x1eb9, 0x301, 0x72, 0x1eb9, 0x301,
+0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e,
+0xe0, 0x3b, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x1eb8, 0x300, 0x62, 0x69, 0x62,
+0x69, 0x3b, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x41, 0x67, 0x1eb9, 0x6d,
+0x1ecd, 0x3b, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x77, 0x65, 0x77, 0x65,
+0x3b, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0xfa,
+0x3b, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x4f, 0x1e63, 0xf9, 0x20, 0x1e62, 0x1eb9,
+0x301, 0x72, 0x1eb9, 0x301, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xc8, 0x72, 0xe8,
+0x6c, 0xe8, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e,
+0xe0, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x4f,
+0x1e63, 0xf9, 0x20, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0x4f, 0x1e63,
+0xf9, 0x20, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20,
+0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xd2, 0x67,
+0xfa, 0x6e, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x4f, 0x77, 0x65, 0x77, 0x65,
+0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b,
+0x4f, 0x1e63, 0xf9, 0x20, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x4f, 0x1e63, 0xf9,
+0x20, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x1e62, 0x1eb9, 0x301, 0x3b, 0xc8, 0x72,
+0x3b, 0x1eb8, 0x72, 0x3b, 0xcc, 0x67, 0x3b, 0x1eb8, 0x300, 0x62, 0x3b, 0xd2,
+0x6b, 0x3b, 0x41, 0x67, 0x3b, 0xd2, 0x67, 0x3b, 0x4f, 0x77, 0x3b, 0x1ecc,
+0x300, 0x77, 0x3b, 0x42, 0xe9, 0x3b, 0x1ecc, 0x300, 0x70, 0x1e62, 0x1eb9, 0x301,
+0x72, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0x3b, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e,
+0x3b, 0xcc, 0x67, 0x62, 0x3b, 0x1eb8, 0x300, 0x62, 0x69, 0x3b, 0xd2, 0x6b,
+0xfa, 0x3b, 0x41, 0x67, 0x1eb9, 0x3b, 0xd2, 0x67, 0xfa, 0x3b, 0x4f, 0x77,
+0x65, 0x3b, 0x1ecc, 0x300, 0x77, 0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0x3b, 0x1ecc,
+0x300, 0x70, 0x1eb9, 0x53, 0x3b, 0xc8, 0x3b, 0x1eb8, 0x3b, 0xcc, 0x3b, 0x1eb8,
+0x300, 0x3b, 0xd2, 0x3b, 0x41, 0x3b, 0xd2, 0x3b, 0x4f, 0x3b, 0x1ecc, 0x300,
+0x3b, 0x42, 0x3b, 0x1ecc, 0x300, 0x53, 0x68, 0x25b, 0x301, 0x72, 0x25b, 0x301,
+0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x190, 0x72, 0x25b, 0x300, 0x6e,
+0xe0, 0x3b, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x190, 0x300, 0x62, 0x69, 0x62,
+0x69, 0x3b, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x41, 0x67, 0x25b, 0x6d,
+0x254, 0x3b, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x77, 0x65, 0x77, 0x65,
+0x3b, 0x186, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0xfa,
+0x3b, 0x186, 0x300, 0x70, 0x25b, 0x300, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x53,
+0x68, 0x25b, 0x301, 0x72, 0x25b, 0x301, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20,
+0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x190,
+0x72, 0x25b, 0x300, 0x6e, 0xe0, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xcc,
+0x67, 0x62, 0xe9, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x190, 0x300, 0x62,
+0x69, 0x62, 0x69, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xd2, 0x6b, 0xfa,
+0x64, 0x75, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0x41, 0x67, 0x25b, 0x6d,
+0x254, 0x3b, 0x4f, 0x73, 0x68, 0xf9, 0x20, 0xd2, 0x67, 0xfa, 0x6e, 0x3b,
+0x4f, 0x73, 0x68, 0xf9, 0x20, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x4f,
+0x73, 0x68, 0xf9, 0x20, 0x186, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x4f,
+0x73, 0x68, 0xf9, 0x20, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x4f, 0x73, 0x68,
+0xf9, 0x20, 0x186, 0x300, 0x70, 0x25b, 0x300, 0x53, 0x68, 0x25b, 0x301, 0x3b,
+0xc8, 0x72, 0x3b, 0x190, 0x72, 0x3b, 0xcc, 0x67, 0x3b, 0x190, 0x300, 0x62,
+0x3b, 0xd2, 0x6b, 0x3b, 0x41, 0x67, 0x3b, 0xd2, 0x67, 0x3b, 0x4f, 0x77,
+0x3b, 0x186, 0x300, 0x77, 0x3b, 0x42, 0xe9, 0x3b, 0x186, 0x300, 0x70, 0x53,
+0x68, 0x25b, 0x301, 0x72, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0x3b, 0x190, 0x72,
+0x25b, 0x300, 0x6e, 0x3b, 0xcc, 0x67, 0x62, 0x3b, 0x190, 0x300, 0x62, 0x69,
+0x3b, 0xd2, 0x6b, 0xfa, 0x3b, 0x41, 0x67, 0x25b, 0x3b, 0xd2, 0x67, 0xfa,
+0x3b, 0x4f, 0x77, 0x65, 0x3b, 0x186, 0x300, 0x77, 0xe0, 0x3b, 0x42, 0xe9,
+0x6c, 0x3b, 0x186, 0x300, 0x70, 0x25b, 0x53, 0x3b, 0xc8, 0x3b, 0x190, 0x3b,
+0xcc, 0x3b, 0x190, 0x300, 0x3b, 0xd2, 0x3b, 0x41, 0x3b, 0xd2, 0x3b, 0x4f,
+0x3b, 0x186, 0x300, 0x3b, 0x42, 0x3b, 0x186, 0x300, 0x6e, 0x64, 0x77, 0x65,
+0x6e, 0x69, 0x74, 0x3b, 0x6e, 0x64, 0x77, 0x65, 0x6e, 0x6e, 0x67, 0x65,
+0x69, 0x68, 0x3b, 0x6e, 0x64, 0x77, 0x65, 0x6e, 0x73, 0x61, 0x6d, 0x3b,
+0x6e, 0x64, 0x77, 0x65, 0x6e, 0x73, 0x65, 0x69, 0x71, 0x3b, 0x6e, 0x64,
+0x77, 0x65, 0x6e, 0x6e, 0x67, 0x75, 0x78, 0x3b, 0x6e, 0x64, 0x77, 0x65,
+0x6e, 0x6c, 0x6f, 0x65, 0x67, 0x3b, 0x6e, 0x64, 0x77, 0x65, 0x6e, 0x63,
+0x61, 0x65, 0x74, 0x3b, 0x6e, 0x64, 0x77, 0x65, 0x6e, 0x62, 0x65, 0x74,
+0x3b, 0x6e, 0x64, 0x77, 0x65, 0x6e, 0x67, 0x6f, 0x75, 0x6a, 0x3b, 0x6e,
+0x64, 0x77, 0x65, 0x6e, 0x63, 0x69, 0x62, 0x3b, 0x6e, 0x64, 0x77, 0x65,
+0x6e, 0x63, 0x69, 0x62, 0x2019, 0x69, 0x74, 0x3b, 0x6e, 0x64, 0x77, 0x65,
+0x6e, 0x63, 0x69, 0x62, 0x6e, 0x67, 0x65, 0x69, 0x68, 0x4a, 0x61, 0x6e,
+0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77,
+0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70,
+0x68, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41,
+0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x68, 0x65,
+0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65,
+0x6d, 0x62, 0x61, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d,
+0x61, 0x73, 0x3b, 0x45, 0x70, 0x68, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a,
+0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x61, 0x3b, 0x53,
+0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44,
+0x69, 0x73, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x31, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b, 0x32, 0x2d, 0x4b, 0x79,
+0x73, 0xe3, 0x3b, 0x33, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b, 0x34, 0x2d,
+0x4b, 0x79, 0x73, 0xe3, 0x3b, 0x35, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b,
+0x36, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b, 0x37, 0x2d, 0x4b, 0x79, 0x73,
+0xe3, 0x3b, 0x38, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b, 0x39, 0x2d, 0x4b,
+0x79, 0x73, 0xe3, 0x3b, 0x31, 0x30, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b,
+0x31, 0x31, 0x2d, 0x4b, 0x79, 0x73, 0xe3, 0x3b, 0x31, 0x32, 0x2d, 0x4b,
+0x79, 0x73, 0xe3, 0x31, 0x4b, 0x79, 0x2e, 0x3b, 0x32, 0x4b, 0x79, 0x2e,
+0x3b, 0x33, 0x4b, 0x79, 0x2e, 0x3b, 0x34, 0x4b, 0x79, 0x2e, 0x3b, 0x35,
+0x4b, 0x79, 0x2e, 0x3b, 0x36, 0x4b, 0x79, 0x2e, 0x3b, 0x37, 0x4b, 0x79,
+0x2e, 0x3b, 0x38, 0x4b, 0x79, 0x2e, 0x3b, 0x39, 0x4b, 0x79, 0x2e, 0x3b,
+0x31, 0x30, 0x4b, 0x79, 0x2e, 0x3b, 0x31, 0x31, 0x4b, 0x79, 0x2e, 0x3b,
+0x31, 0x32, 0x4b, 0x79, 0x2e, 0x31, 0x4b, 0x3b, 0x32, 0x4b, 0x3b, 0x33,
+0x4b, 0x3b, 0x34, 0x4b, 0x3b, 0x35, 0x4b, 0x3b, 0x36, 0x4b, 0x3b, 0x37,
+0x4b, 0x3b, 0x38, 0x4b, 0x3b, 0x39, 0x4b, 0x3b, 0x31, 0x30, 0x4b, 0x3b,
+0x31, 0x31, 0x4b, 0x3b, 0x31, 0x32, 0x4b, 0x79, 0x65, 0x70, 0xe9, 0x3b,
+0x6d, 0x75, 0x6b, 0x169, 0x69, 0x3b, 0x6d, 0x75, 0x73, 0x61, 0x70, 0xed,
+0x72, 0x69, 0x3b, 0x69, 0x72, 0x169, 0x64, 0xed, 0x3b, 0x70, 0xfa, 0x3b,
+0x70, 0xfa, 0x2d, 0x79, 0x65, 0x70, 0xe9, 0x3b, 0x70, 0xfa, 0x2d, 0x6d,
+0x75, 0x6b, 0x169, 0x69, 0x3b, 0x70, 0xfa, 0x2d, 0x6d, 0x75, 0x73, 0x61,
+0x70, 0xed, 0x72, 0x69, 0x3b, 0x70, 0xfa, 0x2d, 0x69, 0x72, 0x169, 0x64,
+0xed, 0x3b, 0x79, 0x65, 0x70, 0xe9, 0x2d, 0x70, 0x75, 0x74, 0x69, 0x6d,
+0x61, 0xe3, 0x3b, 0x79, 0x65, 0x70, 0xe9, 0x2d, 0x79, 0x65, 0x70, 0xe9,
+0x3b, 0x79, 0x65, 0x70, 0xe9, 0x2d, 0x6d, 0x75, 0x6b, 0x169, 0x69, 0x79,
+0x65, 0x3b, 0x6d, 0x6b, 0x3b, 0x6d, 0x73, 0x3b, 0x69, 0x64, 0x3b, 0x70,
+0x75, 0x3b, 0x70, 0x79, 0x3b, 0x70, 0x6d, 0x3b, 0x70, 0x73, 0x3b, 0x70,
+0x69, 0x3b, 0x79, 0x70, 0x3b, 0x79, 0x79, 0x3b, 0x79, 0x6d, 0x59, 0x3b,
+0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x50, 0x3b, 0x50, 0x3b, 0x50, 0x3b,
+0x50, 0x3b, 0x50, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x59, 0x91c, 0x928, 0x935,
+0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930,
+0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908,
+0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905,
+0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x92e, 0x94d, 0x92c, 0x930,
+0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x92e,
+0x94d, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x4a, 0x61,
+0x6e, 0x65, 0x77, 0x6f, 0x6f, 0x72, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x72,
+0x65, 0x77, 0x6f, 0x6f, 0x72, 0x65, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74,
+0x73, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0xfc, 0xfc, 0x6e, 0x65, 0x3b, 0x4a, 0xfc, 0xfc, 0x6c, 0x65, 0x3b,
+0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x75, 0x62, 0x65,
+0x72, 0x3b, 0x4e, 0x6f, 0x66, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44,
+0x65, 0x74, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4a, 0x61, 0x6e, 0x3b,
+0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x65, 0x69, 0x3b, 0x4a, 0xfc, 0x6e, 0x3b, 0x4a, 0xfc, 0x6c, 0x3b,
+0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x66, 0x3b, 0x44, 0x65, 0x74, 0x6d, 0x75, 0x6e, 0x20, 0x23,
+0x31, 0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x32, 0x3b, 0x6d, 0x75, 0x6e,
+0x20, 0x23, 0x33, 0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x34, 0x3b, 0x6d,
+0x75, 0x6e, 0x20, 0x23, 0x35, 0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x36,
+0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x37, 0x3b, 0x6d, 0x75, 0x6e, 0x20,
+0x23, 0x38, 0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x39, 0x3b, 0x6d, 0x75,
+0x6e, 0x20, 0x23, 0x31, 0x30, 0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x31,
+0x31, 0x3b, 0x6d, 0x75, 0x6e, 0x20, 0x23, 0x31, 0x32, 0x4a, 0x61, 0x6e,
+0x75, 0x61, 0x72, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x61, 0x72, 0x65,
+0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d,
+0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x65,
+0x3b, 0x4f, 0x67, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f,
+0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62,
+0x61, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x67e, 0x631, 0x648, 0x631, 0x6cc,
+0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6ce, 0x644, 0x3b,
+0x645, 0x626, 0x6cc, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x6c6, 0x644,
+0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645,
+0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x626,
+0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x62c, 0x646,
+0x3b, 0x67e, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627, 0x67e, 0x631, 0x3b,
+0x645, 0x626, 0x6cc, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x6c6, 0x644,
+0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x3b, 0x627, 0x6a9,
+0x62a, 0x3b, 0x646, 0x626, 0x648, 0x645, 0x3b, 0x62f, 0x633, 0x645, 0x4a, 0x61,
+0x6e, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x50, 0x61, 0x72, 0x77, 0x61, 0x72,
+0x69, 0x3b, 0x4d, 0xe1, 0x72, 0x63, 0x68, 0x3b, 0x41, 0x70, 0x72, 0xe9,
+0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0xf3,
+0x6c, 0xe1, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x3b, 0x53, 0x61,
+0x74, 0x61, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x41, 0x6b, 0x74, 0x75, 0x62,
+0x61, 0x72, 0x3b, 0x4e, 0x61, 0x77, 0x61, 0x6d, 0x62, 0x61, 0x72, 0x3b,
+0x44, 0x61, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x72, 0x4a, 0x61, 0x6e, 0x3b,
+0x50, 0x61, 0x72, 0x3b, 0x4d, 0xe1, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0xf3, 0x6c, 0x3b,
+0x41, 0x67, 0x61, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x41, 0x6b, 0x74, 0x3b,
+0x4e, 0x61, 0x77, 0x3b, 0x44, 0x61, 0x73, 0x7a, 0x65, 0x6e, 0xe2, 0x3b,
+0x66, 0x72, 0x65, 0x76, 0xe2, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x6f, 0x3b,
+0x61, 0x72, 0x76, 0xee, 0x3b, 0x6d, 0x61, 0x7a, 0x7a, 0x6f, 0x3b, 0x7a,
+0x75, 0x67, 0x6e, 0x6f, 0x3b, 0x6c, 0x75, 0x67, 0x67, 0x69, 0x6f, 0x3b,
+0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65,
+0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65,
+0x78, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x64, 0x65, 0x20, 0x7a, 0x65, 0x6e,
+0xe2, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x72, 0x65, 0x76, 0xe2, 0x3b, 0x64,
+0x65, 0x20, 0x6d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x64, 0x2019, 0x61, 0x72,
+0x76, 0xee, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x7a, 0x7a, 0x6f, 0x3b,
+0x64, 0x65, 0x20, 0x7a, 0x75, 0x67, 0x6e, 0x6f, 0x3b, 0x64, 0x65, 0x20,
+0x6c, 0x75, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f,
+0x73, 0x74, 0x6f, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x74, 0x74, 0x6f, 0x62,
+0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x78, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x7a, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b,
+0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x72, 0x76, 0x2e, 0x3b, 0x6d, 0x61,
+0x7a, 0x2e, 0x3b, 0x7a, 0x75, 0x67, 0x2e, 0x3b, 0x6c, 0x75, 0x67, 0x2e,
+0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f,
+0x74, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x78,
+0x2e, 0x64, 0x65, 0x20, 0x7a, 0x65, 0x6e, 0x2e, 0x3b, 0x64, 0x65, 0x20,
+0x66, 0x72, 0x65, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x2e,
+0x3b, 0x64, 0x2019, 0x61, 0x72, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d,
+0x61, 0x7a, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x7a, 0x75, 0x67, 0x2e, 0x3b,
+0x64, 0x65, 0x20, 0x6c, 0x75, 0x67, 0x2e, 0x3b, 0x64, 0x2019, 0x61, 0x67,
+0x6f, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x64,
+0x2019, 0x6f, 0x74, 0x74, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76,
+0x2e, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x78, 0x2e, 0x5a, 0x4e, 0x3b,
+0x46, 0x52, 0x3b, 0x4d, 0x52, 0x3b, 0x41, 0x52, 0x3b, 0x4d, 0x5a, 0x3b,
+0x5a, 0x47, 0x3b, 0x4c, 0x47, 0x3b, 0x41, 0x47, 0x3b, 0x53, 0x54, 0x3b,
+0x4f, 0x54, 0x3b, 0x4e, 0x56, 0x3b, 0x44, 0x58, 0x269, 0x6a, 0x69, 0x6b,
+0x61, 0x77, 0x1dd, 0x72, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254, 0x72,
+0x254, 0x3b, 0x269, 0x6a, 0x69, 0x6b, 0x70, 0x61, 0x6b, 0x61, 0x20, 0x6b,
+0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x61, 0x72, 0x25b, 0x301, 0x63, 0x69,
+0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x6e, 0x6a,
+0x269, 0x62, 0x254, 0x20, 0x6e, 0x256, 0x28a, 0x6b, 0x61, 0x20, 0x6b, 0x61,
+0x14b, 0x254, 0x72, 0x254, 0x3b, 0x61, 0x63, 0x61, 0x66, 0x28a, 0x6e, 0x256,
+0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x61,
+0x6e, 0x254, 0x254, 0x256, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254,
+0x72, 0x254, 0x3b, 0x61, 0x6c, 0xe0, 0x6c, 0x61, 0x6b, 0x61, 0x20, 0x6b,
+0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x269, 0x6a, 0x69, 0x6b, 0x1dd, 0x75,
+0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x61, 0x62,
+0x6f, 0x66, 0x28a, 0x6d, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254, 0x72,
+0x254, 0x3b, 0x269, 0x6a, 0x69, 0x63, 0x69, 0x6d, 0x6b, 0x61, 0x20, 0x6b,
+0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x61, 0x63, 0x61, 0x70, 0x6f, 0x6d,
+0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254, 0x72, 0x254, 0x3b, 0x61, 0x6e,
+0x254, 0x254, 0x62, 0x28a, 0x6e, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x14b, 0x254,
+0x72, 0x254, 0x6b, 0x61, 0x77, 0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x63, 0x69,
+0x3b, 0x256, 0x28a, 0x3b, 0x256, 0x75, 0x35, 0x3b, 0x256, 0x75, 0x36, 0x3b,
+0x6c, 0x61, 0x3b, 0x6b, 0x1dd, 0x75, 0x3b, 0x66, 0x28a, 0x6d, 0x3b, 0x63,
+0x69, 0x6d, 0x3b, 0x70, 0x6f, 0x6d, 0x3b, 0x62, 0x28a, 0x6e, 0x6a, 0x65,
+0x6e, 0x61, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x61, 0x72, 0x6f,
+0x3b, 0x6d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c,
+0x65, 0x3b, 0x6d, 0x61, 0x6a, 0x6f, 0x3b, 0x6a, 0x75, 0x67, 0x6e, 0x6f,
+0x3b, 0x6c, 0x75, 0x6a, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f,
+0x3b, 0x73, 0x65, 0x74, 0x65, 0x6e, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74,
+0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6e, 0x62, 0x72,
+0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6e, 0x62, 0x72, 0x65, 0x6a, 0x65,
+0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70,
+0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x67, 0x3b, 0x6c, 0x75,
+0x6a, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74,
+0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x4a, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41,
+0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44
};
// GENERATED PART ENDS HERE
+} // namespace QtPrivate::Roman
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/time/qromancalendar_p.h b/src/corelib/time/qromancalendar_p.h
index 4ba699ffa6..96501ce701 100644
--- a/src/corelib/time/qromancalendar_p.h
+++ b/src/corelib/time/qromancalendar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QROMAN_CALENDAR_P_H
#define QROMAN_CALENDAR_P_H
@@ -65,13 +29,16 @@ public:
bool isLunar() const override;
bool isLuniSolar() const override;
bool isSolar() const override;
+
+ // Names of months (implemented in qlocale.cpp):
+ QString monthName(const QLocale &locale, int month, int year,
+ QLocale::FormatType format) const override;
+ QString standaloneMonthName(const QLocale &locale, int month, int year,
+ QLocale::FormatType format) const override;
protected:
// locale support:
const QCalendarLocale *localeMonthIndexData() const override;
const char16_t *localeMonthData() const override;
- // (The INTEGRITY compiler got upset at: using QCalendarBackend:QCalendarBackend;)
- QRomanCalendar(const QString &name, QCalendar::System id = QCalendar::System::User)
- : QCalendarBackend(name, id) {}
};
QT_END_NAMESPACE
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index 24834d1284..3a68277a6c 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimezone.h"
-#include "qtimezoneprivate_p.h"
+#if QT_CONFIG(timezone)
+# include "qtimezoneprivate_p.h"
+#endif
#include <QtCore/qdatastream.h>
#include <QtCore/qdatetime.h>
@@ -50,56 +16,44 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+#if QT_CONFIG(timezone)
// Create default time zone using appropriate backend
static QTimeZonePrivate *newBackendTimeZone()
{
-#ifdef QT_NO_SYSTEMLOCALE
-#if QT_CONFIG(icu)
- return new QIcuTimeZonePrivate();
-#else
- return new QUtcTimeZonePrivate();
-#endif
-#else
-#if defined Q_OS_MAC
+#if defined(Q_OS_DARWIN)
return new QMacTimeZonePrivate();
-#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#elif defined(Q_OS_ANDROID)
return new QAndroidTimeZonePrivate();
-#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
+#elif defined(Q_OS_UNIX)
return new QTzTimeZonePrivate();
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate();
-#elif defined Q_OS_WIN
+#elif defined(Q_OS_WIN)
return new QWinTimeZonePrivate();
#else
return new QUtcTimeZonePrivate();
-#endif // System Locales
-#endif // QT_NO_SYSTEMLOCALE
+#endif // Backend selection
}
// Create named time zone using appropriate backend
static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
{
-#ifdef QT_NO_SYSTEMLOCALE
-#if QT_CONFIG(icu)
- return new QIcuTimeZonePrivate(ianaId);
-#else
- return new QUtcTimeZonePrivate(ianaId);
-#endif
-#else
-#if defined Q_OS_MAC
+ Q_ASSERT(!ianaId.isEmpty());
+#if defined(Q_OS_DARWIN)
return new QMacTimeZonePrivate(ianaId);
-#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#elif defined(Q_OS_ANDROID)
return new QAndroidTimeZonePrivate(ianaId);
-#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
+#elif defined(Q_OS_UNIX)
return new QTzTimeZonePrivate(ianaId);
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate(ianaId);
-#elif defined Q_OS_WIN
+#elif defined(Q_OS_WIN)
return new QWinTimeZonePrivate(ianaId);
#else
return new QUtcTimeZonePrivate(ianaId);
-#endif // System Locales
-#endif // QT_NO_SYSTEMLOCALE
+#endif // Backend selection
}
class QTimeZoneSingleton
@@ -107,38 +61,89 @@ class QTimeZoneSingleton
public:
QTimeZoneSingleton() : backend(newBackendTimeZone()) {}
- // The backend_tz is the tz to use in static methods such as availableTimeZoneIds() and
- // isTimeZoneIdAvailable() and to create named IANA time zones. This is usually the host
- // system, but may be different if the host resources are insufficient or if
- // QT_NO_SYSTEMLOCALE is set. A simple UTC backend is used if no alternative is available.
- QSharedDataPointer<QTimeZonePrivate> backend;
+ // The global_tz is the tz to use in static methods such as
+ // availableTimeZoneIds() and isTimeZoneIdAvailable() and to create named
+ // IANA time zones. This is usually the host system, but may be different if
+ // the host resources are insufficient. A simple UTC backend is used if no
+ // alternative is available.
+ QExplicitlySharedDataPointer<QTimeZonePrivate> backend;
};
Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
+#endif // feature timezone
/*!
\class QTimeZone
\inmodule QtCore
\since 5.2
-
- \brief The QTimeZone class converts between UTC and local time in a specific
- time zone.
-
\threadsafe
- This class provides a stateless calculator for time zone conversions
- between UTC and the local time in a specific time zone. By default it uses
- the host system time zone data to perform these conversions.
+ \brief QTimeZone identifies how a time representation relates to UTC.
+
+ \compares equality
+
+ When dates and times are combined, the meaning of the result depends on how
+ time is being represented. There are various international standards for
+ representing time; one of these, UTC, corresponds to the traditional
+ standard of solar mean time at Greenwich (a.k.a. GMT). All other time
+ systems supported by Qt are ultimately specified in relation to UTC. An
+ instance of this class provides a stateless calculator for conversions
+ between UTC and other time representations.
+
+ Some time representations are simply defined at a fixed offset to UTC.
+ Others are defined by governments for use within their jurisdictions. The
+ latter are properly known as time zones, but QTimeZone (since Qt 6.5) is
+ unifies their representation with that of general time systems. One time
+ zone generally supported on most operating systems is designated local time;
+ this is presumed to correspond to the time zone within which the user is
+ living.
+
+ For time zones other than local time, UTC and those at fixed offsets from
+ UTC, Qt can only provide support when the operating system provides some way
+ to access that information. When Qt is built, the \c timezone feature
+ controls whether such information is available. When it is not, some
+ constructors and methods of QTimeZone are excluded from its API; these are
+ documented as depending on feature \c timezone. Note that, even when Qt is
+ built with this feature enabled, it may be unavailable to users whose
+ systems are misconfigured, or where some standard packages (for example, the
+ \c tzdata package on Linux) are not installed. This feature is enabled by
+ default when time zone information is available.
This class is primarily designed for use in QDateTime; most applications
- will not need to access this class directly and should instead use
- QDateTime with a Qt::TimeSpec of Qt::TimeZone.
+ will not need to access this class directly and should instead use an
+ instance of it when constructing a QDateTime.
\note For consistency with QDateTime, QTimeZone does not account for leap
seconds.
\section1 Remarks
+ QTimeZone, like QDateTime, measures offsets from UTC in seconds. This
+ contrasts with their measurement of time generally, which they do in
+ milliseconds. Real-world time zones generally have UTC offsets that are
+ whole-number multiples of five minutes (300 seconds), at least since well
+ before 1970. A positive offset from UTC gives a time representation puts
+ noon on any given day before UTC noon on that day; a negative offset puts
+ noon after UTC noon on the same day.
+
+ \section2 Lightweight Time Representations
+
+ QTimeZone can represent UTC, local time and fixed offsets from UTC even when
+ feature \c timezone is disabled. The form in which it does so is also
+ available when the feature is enabled; it is a more lightweight form and
+ processing using it will typically be more efficient, unless methods only
+ available when feature \c timezone is enabled are being exercised. See \l
+ Initialization and \l QTimeZone::fromSecondsAheadOfUtc(int) for how to
+ construct these representations.
+
+ This documentation distinguishes between "time zone", used to describe a
+ time representation described by system-supplied or standard information,
+ and time representations more generally, which include these lightweight
+ forms. The methods available only when feature \c timezone is enabled are
+ apt to be cheaper for time zones than for lightweight time representations,
+ for which these methods may construct a suitable transient time zone object
+ to which to forward the query.
+
\section2 IANA Time Zone IDs
QTimeZone uses the IANA time zone IDs as defined in the IANA Time Zone
@@ -153,25 +158,29 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
availableTimeZoneIds() to determine what IANA IDs are available.
The IANA IDs and database are also know as the Olson IDs and database,
- named after their creator.
+ named after the original compiler of the database.
\section2 UTC Offset Time Zones
- A default UTC time zone backend is provided which is always guaranteed to
- be available. This provides a set of generic Offset From UTC time zones
- in the range UTC-14:00 to UTC+14:00. These time zones can be created
- using either the standard ISO format names "UTC+00:00" as listed by
- availableTimeZoneIds(), or using the number of offset seconds.
+ A default UTC time zone backend is provided which is always available when
+ feature \c timezone is enabled. This provides a set of generic Offset From
+ UTC time zones in the range UTC-16:00 to UTC+16:00. These time zones can be
+ created using either the standard ISO format names, such as "UTC+00:00", as
+ listed by availableTimeZoneIds(), or using a name of similar form in
+ combination with the number of offset seconds.
\section2 Windows Time Zones
Windows native time zone support is severely limited compared to the
standard IANA TZ Database. Windows time zones cover larger geographic
areas and are thus less accurate in their conversions. They also do not
- support as much historic conversion data and so may only be accurate for
- the current year.
+ support as much historical data and so may only be accurate for the
+ current year. In particular, when MS's zone data claims that DST was
+ observed prior to 1900 (this is historically known to be untrue), the
+ claim is ignored and the standard time (allegedly) in force in 1900 is
+ taken to have always been in effect.
- QTimeZone uses a conversion table derived form the Unicode CLDR data to map
+ QTimeZone uses a conversion table derived from the Unicode CLDR data to map
between IANA IDs and Windows IDs. Depending on your version of Windows
and Qt, this table may not be able to provide a valid conversion, in which
"UTC" will be returned.
@@ -181,11 +190,11 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
Exchange EWS ID as well, but is different to the Time Zone Name (TZID) and
COD code used by MS Exchange in versions before 2007.
- \section2 System Time Zone
+ \note When Qt is built with the ICU library, it is used in preference to the
+ Windows system APIs, bypassing all problems with those APIs using different
+ names.
- QTimeZone does not support any concept of a system or default time zone.
- If you require a QDateTime that uses the current system time zone at any
- given moment then you should use a Qt::TimeSpec of Qt::LocalTime.
+ \section2 System Time Zone
The method systemTimeZoneId() returns the current system IANA time zone
ID which on Unix-like systems will always be correct. On Windows this ID is
@@ -196,7 +205,13 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
Creating a new QTimeZone instance using the system time zone ID will only
produce a fixed named copy of the time zone, it will not change if the
- system time zone changes.
+ system time zone changes. QTimeZone::systemTimeZone() will return an
+ instance representing the zone named by this system ID. Note that
+ constructing a QDateTime using this system zone may behave differently than
+ constructing a QDateTime that uses Qt::LocalTime as its Qt::TimeSpec, as the
+ latter directly uses system APIs for accessing local time information, which
+ may behave differently (and, in particular, might adapt if the user adjusts
+ the system zone setting).
\section2 Time Zone Offsets
@@ -208,7 +223,10 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
standard time in the time zone. The daylight-saving time offset is the
number of seconds to add to the standard time offset to obtain
daylight-saving time (abbreviated DST and sometimes called "daylight time"
- or "summer time") in the time zone.
+ or "summer time") in the time zone. The usual case for DST (using
+ standard time in winter, DST in summer) has a positive daylight-saving
+ time offset. However, some zones have negative DST offsets, used in
+ winter, with summer using standard time.
Note that the standard and DST offsets for a time zone may change over time
as countries have changed DST laws or even their standard time offset.
@@ -219,23 +237,41 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
of the Unicode Data Files and Software License. See
\l{unicode-cldr}{Unicode Common Locale Data Repository (CLDR)} for details.
- \sa QDateTime
+ \sa QDateTime, QCalendar
*/
/*!
- \enum QTimeZone::anonymous
+ \variable QTimeZone::MinUtcOffsetSecs
+ \brief Timezone offsets from UTC are expected to be no lower than this.
- Sane UTC offsets range from -14 to +14 hours.
- No known zone > 12 hrs West of Greenwich (Baker Island, USA).
- No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati).
+ The lowest UTC offset of any early 21st century timezone is -12 hours (Baker
+ Island, USA), or 12 hours west of Greenwich.
- \value MinUtcOffsetSecs
- -14 * 3600,
+ Historically, until 1844, The Philippines (then controlled by Spain) used
+ the same date as Spain's American holdings, so had offsets close to 16 hours
+ west of Greenwich. As The Philippines was using local solar mean time, it is
+ possible some outlying territory of it may have been operating at more than
+ 16 hours west of Greenwich, but no early 21st century timezone traces its
+ history back to such an extreme.
- \value MaxUtcOffsetSecs
- +14 * 3600
+ \sa MaxUtcOffsetSecs
+*/
+/*!
+ \variable QTimeZone::MaxUtcOffsetSecs
+ \brief Timezone offsets from UTC are expected to be no higher than this.
+
+ The highest UTC offset of any early 21st century timezone is +14 hours
+ (Christmas Island, Kiribati, Kiritimati), or 14 hours east of Greenwich.
+
+ Historically, before 1867, when Russia sold Alaska to America, Alaska used
+ the same date as Russia, so had offsets over 15 hours east of Greenwich. As
+ Alaska was using local solar mean time, its offsets varied, but all were
+ less than 16 hours east of Greenwich.
+
+ \sa MinUtcOffsetSecs
*/
+#if QT_CONFIG(timezone)
/*!
\enum QTimeZone::TimeType
@@ -256,6 +292,8 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
either an unknown time or a neutral form.
For example when formatting a display name this will show something
like "Pacific Time".
+
+ This type is only available when feature \c timezone is enabled.
*/
/*!
@@ -271,14 +309,20 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
The short form of the time zone name, usually an abbreviation, e.g. "CET"
\value OffsetName
The standard ISO offset form of the time zone name, e.g. "UTC+01:00"
+
+ This type is only available when feature \c timezone is enabled.
*/
/*!
\class QTimeZone::OffsetData
\inmodule QtCore
- The time zone offset data for a given moment in time, i.e. the time zone
- offsets and abbreviation to use at that moment in time.
+ The time zone offset data for a given moment in time.
+
+ This provides the time zone offsets and abbreviation to use at that moment
+ in time. When a function returns this type, it may use an invalid datetime
+ to indicate that the query it is answering has no valid answer, so check
+ \c{atUtc.isValid()} before using the results.
\list
\li OffsetData::atUtc The datetime of the offset data in UTC time.
@@ -291,7 +335,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
For example, for time zone "Europe/Berlin" the OffsetDate in standard and DST might be:
\list
- \li atUtc = QDateTime(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC)
+ \li atUtc = QDateTime(QDate(2013, 1, 1), QTime(0, 0), QTimeZone::UTC)
\li offsetFromUtc = 3600
\li standardTimeOffset = 3600
\li daylightTimeOffset = 0
@@ -299,47 +343,123 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
\endlist
\list
- \li atUtc = QDateTime(QDate(2013, 6, 1), QTime(0, 0, 0), Qt::UTC)
+ \li atUtc = QDateTime(QDate(2013, 6, 1), QTime(0, 0), QTimeZone::UTC)
\li offsetFromUtc = 7200
\li standardTimeOffset = 3600
\li daylightTimeOffset = 3600
\li abbreviation = "CEST"
\endlist
+
+ This type is only available when feature \c timezone is enabled.
*/
/*!
\typedef QTimeZone::OffsetDataList
Synonym for QList<OffsetData>.
+
+ This type is only available when feature \c timezone is enabled.
*/
+#endif // timezone backends
+
+QTimeZone::Data::Data() noexcept : d(nullptr)
+{
+ // Assumed by the conversion between spec and mode:
+ static_assert(int(Qt::TimeZone) == 3);
+}
+
+QTimeZone::Data::Data(const Data &other) noexcept
+{
+#if QT_CONFIG(timezone)
+ if (!other.isShort() && other.d)
+ other.d->ref.ref();
+#endif
+ d = other.d;
+}
+
+QTimeZone::Data::Data(QTimeZonePrivate *dptr) noexcept
+ : d(dptr)
+{
+#if QT_CONFIG(timezone)
+ if (d)
+ d->ref.ref();
+#endif
+}
+
+QTimeZone::Data::~Data()
+{
+#if QT_CONFIG(timezone)
+ if (!isShort() && d && !d->ref.deref())
+ delete d;
+ d = nullptr;
+#endif
+}
+
+QTimeZone::Data &QTimeZone::Data::operator=(const QTimeZone::Data &other) noexcept
+{
+#if QT_CONFIG(timezone)
+ if (!other.isShort())
+ return *this = other.d;
+ if (!isShort() && d && !d->ref.deref())
+ delete d;
+#endif
+ d = other.d;
+ return *this;
+}
/*!
Create a null/invalid time zone instance.
*/
QTimeZone::QTimeZone() noexcept
- : d(nullptr)
{
+ // Assumed by (at least) Data::swap() and {copy,move} {assign,construct}:
+ static_assert(sizeof(ShortData) <= sizeof(Data::d));
+ // Needed for ShortData::offset to represent all valid offsets:
+ static_assert(qintptr(1) << (sizeof(void *) * 8 - 2) >= MaxUtcOffsetSecs);
+}
+
+#if QT_CONFIG(timezone)
+QTimeZone::Data &QTimeZone::Data::operator=(QTimeZonePrivate *dptr) noexcept
+{
+ if (!isShort()) {
+ if (d == dptr)
+ return *this;
+ if (d && !d->ref.deref())
+ delete d;
+ }
+ if (dptr)
+ dptr->ref.ref();
+ d = dptr;
+ Q_ASSERT(!isShort());
+ return *this;
}
/*!
- Creates an instance of the requested time zone \a ianaId.
+ Creates a time zone instance with the requested IANA ID \a ianaId.
The ID must be one of the available system IDs or a valid UTC-with-offset
- ID, otherwise an invalid time zone will be returned.
+ ID, otherwise an invalid time zone will be returned. For UTC-with-offset
+ IDs, when they are not in fact IANA IDs, the \c{id()} of the resulting
+ instance may differ from the ID passed to the constructor.
- \sa availableTimeZoneIds()
+ This constructor is only available when feature \c timezone is enabled.
+
+ \sa availableTimeZoneIds(), id()
*/
QTimeZone::QTimeZone(const QByteArray &ianaId)
{
- // Try and see if it's a CLDR UTC offset ID - just as quick by creating as
- // by looking up.
+ // Try and see if it's a recognized UTC offset ID - just as quick by
+ // creating as by looking up.
d = new QUtcTimeZonePrivate(ianaId);
- // If not a CLDR UTC offset ID then try creating it with the system backend.
- // Relies on backend not creating valid TZ with invalid name.
- if (!d->isValid())
- d = newBackendTimeZone(ianaId);
+ // If not recognized, try creating it with the system backend.
+ if (!d->isValid()) {
+ if (ianaId.isEmpty())
+ d = newBackendTimeZone();
+ else // Constructor MUST produce invalid for unsupported ID.
+ d = newBackendTimeZone(ianaId);
+ }
// Can also handle UTC with arbitrary (valid) offset, but only do so as
// fall-back, since either of the above may handle it more informatively.
if (!d->isValid()) {
@@ -355,11 +475,17 @@ QTimeZone::QTimeZone(const QByteArray &ianaId)
}
/*!
- Creates an instance of a time zone with the requested Offset from UTC of
- \a offsetSeconds.
+ Creates a time zone instance with the given offset, \a offsetSeconds, from UTC.
- The \a offsetSeconds from UTC must be in the range -14 hours to +14 hours
+ The \a offsetSeconds from UTC must be in the range -16 hours to +16 hours
otherwise an invalid time zone will be returned.
+
+ This constructor is only available when feature \c timezone is enabled. The
+ returned instance is equivalent to the lightweight time representation
+ \c{QTimeZone::fromSecondsAfterUtc(offsetSeconds)}, albeit implemented as a
+ time zone.
+
+ \sa MinUtcOffsetSecs, MaxUtcOffsetSecs, id()
*/
QTimeZone::QTimeZone(int offsetSeconds)
@@ -369,33 +495,43 @@ QTimeZone::QTimeZone(int offsetSeconds)
}
/*!
- Creates a custom time zone with an ID of \a ianaId and an offset from UTC
- of \a offsetSeconds. The \a name will be the name used by displayName()
- for the LongName, the \a abbreviation will be used by displayName() for the
- ShortName and by abbreviation(), and the optional \a country will be used
- by country(). The \a comment is an optional note that may be displayed in
+ Creates a custom time zone instance at fixed offset from UTC.
+
+ The returned time zone has an ID of \a zoneId and an offset from UTC of \a
+ offsetSeconds. The \a name will be the name used by displayName() for the
+ LongName, the \a abbreviation will be used by displayName() for the
+ ShortName and by abbreviation(), and the optional \a territory will be used
+ by territory(). The \a comment is an optional note that may be displayed in
a GUI to assist users in selecting a time zone.
- The \a ianaId must not be one of the available system IDs returned by
- availableTimeZoneIds(). The \a offsetSeconds from UTC must be in the range
- -14 hours to +14 hours.
+ The \a zoneId \e{must not} be one of the available system IDs returned by
+ availableTimeZoneIds(). The \a offsetSeconds from UTC must be in the range
+ -16 hours to +16 hours.
- If the custom time zone does not have a specific country then set it to the
- default value of QLocale::AnyCountry.
+ If the custom time zone does not have a specific territory then set it to the
+ default value of QLocale::AnyTerritory.
+
+ This constructor is only available when feature \c timezone is enabled.
+
+ \sa id(), offsetFromUtc(), displayName(), abbreviation(), territory(), comment(),
+ MinUtcOffsetSecs, MaxUtcOffsetSecs
*/
-QTimeZone::QTimeZone(const QByteArray &ianaId, int offsetSeconds, const QString &name,
- const QString &abbreviation, QLocale::Country country, const QString &comment)
- : d()
+QTimeZone::QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
+ const QString &abbreviation, QLocale::Territory territory, const QString &comment)
+ : d(QUtcTimeZonePrivate().isTimeZoneIdAvailable(zoneId)
+ || global_tz->backend->isTimeZoneIdAvailable(zoneId)
+ ? nullptr // Don't let client code hijack a real zone name.
+ : new QUtcTimeZonePrivate(zoneId, offsetSeconds, name, abbreviation, territory, comment))
{
- if (!isTimeZoneIdAvailable(ianaId))
- d = new QUtcTimeZonePrivate(ianaId, offsetSeconds, name, abbreviation, country, comment);
}
/*!
\internal
Private. Create time zone with given private backend
+
+ This constructor is only available when feature \c timezone is enabled.
*/
QTimeZone::QTimeZone(QTimeZonePrivate &dd)
@@ -404,15 +540,154 @@ QTimeZone::QTimeZone(QTimeZonePrivate &dd)
}
/*!
- Copy constructor, copy \a other to this.
+ \since 6.5
+ Converts this QTimeZone to one whose timeSpec() is Qt::TimeZone.
+
+ In all cases, the result's \l timeSpec() is Qt::TimeZone. When this
+ QTimeZone's timeSpec() is Qt::TimeZone, this QTimeZone itself is returned.
+ If timeSpec() is Qt::LocalTime then systemTimeZone() is returned.
+
+ If timeSpec() is Qt::UTC, QTimeZone::utc() is returned. If it is
+ Qt::OffsetFromUTC then QTimeZone(int) is passed its offset and the result is
+ returned.
+
+ When using a lightweight time representation - local time, UTC time or time
+ at a fixed offset from UTC - using methods only supported when feature \c
+ timezone is enabled may be more expensive than using a corresponding time
+ zone. This method maps a lightweight time representation to a corresponding
+ time zone - that is, an instance based on system-supplied or standard data.
+
+ This method is only available when feature \c timezone is enabled.
+
+ \sa QTimeZone(QTimeZone::Initialization), fromSecondsAheadOfUtc()
+*/
+
+QTimeZone QTimeZone::asBackendZone() const
+{
+ switch (timeSpec()) {
+ case Qt::TimeZone:
+ return *this;
+ case Qt::LocalTime:
+ return systemTimeZone();
+ case Qt::UTC:
+ return utc();
+ case Qt::OffsetFromUTC:
+ return QTimeZone(*new QUtcTimeZonePrivate(int(d.s.offset)));
+ }
+ return QTimeZone();
+}
+#endif // timezone backends
+
+/*!
+ \since 6.5
+ \enum QTimeZone::Initialization
+
+ The type of the simplest lightweight time representations.
+
+ This enumeration identifies a type of lightweight time representation to
+ pass to a QTimeZone constructor, where no further data are required. They
+ correspond to the like-named members of Qt::TimeSpec.
+
+ \value LocalTime This time representation corresponds to the one implicitly
+ used by system functions using \c time_t and \c {struct tm}
+ value to map between local time and UTC time.
+
+ \value UTC This time representation, Coordinated Universal Time, is the base
+ representation to which civil time is referred in all supported
+ time representations. It is defined by the International
+ Telecommunication Union.
+*/
+
+/*!
+ \since 6.5
+ \fn QTimeZone::QTimeZone(Initialization spec) noexcept
+
+ Creates a lightweight instance describing UTC or local time.
+
+ \sa fromSecondsAheadOfUtc(), asBackendZone(), utc(), systemTimeZone()
+*/
+
+/*!
+ \since 6.5
+ \fn QTimeZone::fromSecondsAheadOfUtc(int offset)
+ \fn QTimeZone::fromDurationAheadOfUtc(std::chrono::seconds offset)
+
+ Returns a time representation at a fixed \a offset, in seconds, ahead of
+ UTC.
+
+ The \a offset from UTC must be in the range -16 hours to +16 hours otherwise
+ an invalid time zone will be returned. The returned QTimeZone is a
+ lightweight time representation, not a time zone (backed by system-supplied
+ or standard data).
+
+ If the offset is 0, the \l timeSpec() of the returned instance will be
+ Qt::UTC. Otherwise, if \a offset is valid, timeSpec() is
+ Qt::OffsetFromUTC. An invalid time zone, when returned, has Qt::TimeZone as
+ its timeSpec().
+
+ \sa QTimeZone(int), asBackendZone(), fixedSecondsAheadOfUtc(),
+ MinUtcOffsetSecs, MaxUtcOffsetSecs
+*/
+
+/*!
+ \since 6.5
+ \fn Qt::TimeSpec QTimeZone::timeSpec() const noexcept
+
+ Returns a Qt::TimeSpec identifying the type of time representation.
+
+ If the result is Qt::TimeZone, this time description is a time zone (backed
+ by system-supplied or standard data); otherwise, it is a lightweight time
+ representation. If the result is Qt::LocalTime it describes local time: see
+ Qt::TimeSpec for details.
+
+ \sa fixedSecondsAheadOfUtc(), asBackendZone()
+*/
+
+/*!
+ \since 6.5
+ \fn int QTimeZone::fixedSecondsAheadOfUtc() const noexcept
+
+ For a lightweight time representation whose \l timeSpec() is Qt::OffsetFromUTC,
+ this returns the fixed offset from UTC that it describes. For any other time
+ representation it returns 0, even if that time representation does have a
+ constant offset from UTC.
*/
-QTimeZone::QTimeZone(const QTimeZone &other)
+/*!
+ \since 6.5
+ \fn QTimeZone::isUtcOrFixedOffset(Qt::TimeSpec spec) noexcept
+
+ Returns \c true if \a spec is Qt::UTC or Qt::OffsetFromUTC.
+*/
+
+/*!
+ \since 6.5
+ \fn QTimeZone::isUtcOrFixedOffset() const noexcept
+
+ Returns \c true if \l timeSpec() is Qt::UTC or Qt::OffsetFromUTC.
+
+ When it is true, the time description does not change over time, such as
+ having seasonal daylight-saving changes, as may happen for local time or a
+ time zone. Knowing this may save the calling code to need for various other
+ checks.
+*/
+
+/*!
+ Copy constructor: copy \a other to this.
+*/
+
+QTimeZone::QTimeZone(const QTimeZone &other) noexcept
: d(other.d)
{
}
/*!
+ \fn QTimeZone::QTimeZone(QTimeZone &&other) noexcept
+
+ Move constructor of this from \a other.
+*/
+
+/*!
Destroys the time zone.
*/
@@ -421,7 +696,7 @@ QTimeZone::~QTimeZone()
}
/*!
- \fn QTimeZone::swap(QTimeZone &other)
+ \fn QTimeZone::swap(QTimeZone &other) noexcept
Swaps this time zone instance with \a other. This function is very
fast and never fails.
@@ -437,42 +712,49 @@ QTimeZone &QTimeZone::operator=(const QTimeZone &other)
return *this;
}
-/*
- \fn void QTimeZone::swap(QTimeZone &other)
+/*!
+ \fn QTimeZone &QTimeZone::operator=(QTimeZone &&other)
- Swaps this timezone with \a other. This function is very fast and
- never fails.
+ Move-assigns \a other to this QTimeZone instance, transferring the ownership
+ of its data to this instance.
*/
/*!
- \fn QTimeZone &QTimeZone::operator=(QTimeZone &&other)
+ \fn bool QTimeZone::operator==(const QTimeZone &lhs, const QTimeZone &rhs)
- Move-assigns \a other to this QTimeZone instance, transferring the
- ownership of the managed pointer to this instance.
+ Returns \c true if \a lhs time zone is equal to the \a rhs time zone.
+
+ Two representations are different if they are internally described
+ differently, even if they agree in their representation of all moments of
+ time. In particular, a lightweight time representation may coincide with a
+ time zone but the two will not be equal.
*/
/*!
- Returns \c true if this time zone is equal to the \a other time zone.
-*/
+ \fn bool QTimeZone::operator!=(const QTimeZone &lhs, const QTimeZone &rhs)
-bool QTimeZone::operator==(const QTimeZone &other) const
-{
- if (d && other.d)
- return (*d == *other.d);
- else
- return (d == other.d);
-}
+ Returns \c true if \a lhs time zone is not equal to the \a rhs time zone.
-/*!
- Returns \c true if this time zone is not equal to the \a other time zone.
+ Two representations are different if they are internally described
+ differently, even if they agree in their representation of all moments of
+ time. In particular, a lightweight time representation may coincide with a
+ time zone but the two will not be equal.
*/
-bool QTimeZone::operator!=(const QTimeZone &other) const
+bool comparesEqual(const QTimeZone &lhs, const QTimeZone &rhs) noexcept
{
- if (d && other.d)
- return (*d != *other.d);
- else
- return (d != other.d);
+ if (lhs.d.isShort())
+ return rhs.d.isShort() && lhs.d.s == rhs.d.s;
+
+ if (!rhs.d.isShort()) {
+ if (lhs.d.d == rhs.d.d)
+ return true;
+#if QT_CONFIG(timezone)
+ return lhs.d.d && rhs.d.d && *lhs.d.d == *rhs.d.d;
+#endif
+ }
+
+ return false;
}
/*!
@@ -481,38 +763,105 @@ bool QTimeZone::operator!=(const QTimeZone &other) const
bool QTimeZone::isValid() const
{
- if (d)
- return d->isValid();
- else
- return false;
+#if QT_CONFIG(timezone)
+ if (!d.isShort())
+ return d.d && d->isValid();
+#endif
+ return d.isShort();
}
+#if QT_CONFIG(timezone)
/*!
Returns the IANA ID for the time zone.
- IANA IDs are used on all platforms. On Windows these are translated
- from the Windows ID into the closest IANA ID for the time zone and country.
+ IANA IDs are used on all platforms. On Windows these are translated from
+ the Windows ID into the best match IANA ID for the time zone and territory.
+
+ If this timezone instance was not constructed from an IANA ID, its ID is
+ determined by how it was constructed. In most cases, the ID passed when
+ constructing the instance is used. (The constructor for a custom zone uses
+ the ID it is passed, which must not be an IANA ID.) There are two
+ exceptions.
+ \list
+ \li Instances constructed by passing only a UTC offset in seconds have no ID
+ passed when constructing.
+ \li The constructor taking only an IANA ID will also accept some UTC-offset
+ IDs that are not in fact IANA IDs: its handling of these is equivalent
+ to passing the corresponding offset in seconds, as for the first
+ exception.
+ \endlist
+
+ In the two exceptional cases, if there is an IANA UTC-offset zone with the
+ specified offset, the instance constructed uses that IANA zone's ID, even
+ though this may differ from the (non-IANA) UTC-offset ID passed to the
+ constructor. Otherwise, the instance uses an ID synthesized from its offset,
+ with the form UTC±hh:mm:ss, omitting any trailing :00 for zero seconds or
+ minutes. Again, this may differ from the UTC-offset ID passed to the
+ constructor.
+
+ This method is only available when feature \c timezone is enabled.
*/
QByteArray QTimeZone::id() const
{
- if (d)
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::UTC:
+ return QTimeZonePrivate::utcQByteArray();
+ case Qt::LocalTime:
+ return systemTimeZoneId();
+ case Qt::OffsetFromUTC:
+ return QUtcTimeZonePrivate(d.s.offset).id();
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (d.d) {
return d->id();
- else
- return QByteArray();
+ }
+ return QByteArray();
+}
+
+/*!
+ \since 6.2
+
+ Returns the territory for the time zone.
+
+ A return of \l {QLocale::}{AnyTerritory} means the zone has no known
+ territorial association. In some cases this may be because the zone has no
+ associated territory - for example, UTC - or because the zone is used in
+ several territories - for example, CET. In other cases, the QTimeZone
+ backend may not know which territory the zone is associated with - for
+ example, because it is not the primary zone of the territory in which it is
+ used.
+
+ This method is only available when feature \c timezone is enabled.
+*/
+QLocale::Territory QTimeZone::territory() const
+{
+ if (d.isShort()) {
+ if (d.s.spec() == Qt::LocalTime)
+ return systemTimeZone().territory();
+ } else if (isValid()) {
+ return d->territory();
+ }
+ return QLocale::AnyTerritory;
}
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
- Returns the country for the time zone.
+ \deprecated [6.6] Use territory() instead.
+
+ Returns the territory for the time zone.
+
+ This method is only available when feature \c timezone is enabled.
*/
QLocale::Country QTimeZone::country() const
{
- if (isValid())
- return d->country();
- else
- return QLocale::AnyCountry;
+ return territory();
}
+#endif
/*!
Returns any comment for the time zone.
@@ -520,14 +869,18 @@ QLocale::Country QTimeZone::country() const
A comment may be provided by the host platform to assist users in
choosing the correct time zone. Depending on the platform this may not
be localized.
+
+ This method is only available when feature \c timezone is enabled.
*/
QString QTimeZone::comment() const
{
- if (isValid())
+ if (d.isShort()) {
+ // TODO: anything ? Or just stick with empty string ?
+ } else if (isValid()) {
return d->comment();
- else
- return QString();
+ }
+ return QString();
}
/*!
@@ -541,16 +894,31 @@ QString QTimeZone::comment() const
The display name may change depending on DST or historical events.
+ This method is only available when feature \c timezone is enabled.
+
\sa abbreviation()
*/
QString QTimeZone::displayName(const QDateTime &atDateTime, NameType nameType,
const QLocale &locale) const
{
- if (isValid())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().displayName(atDateTime, nameType, locale);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return QUtcTimeZonePrivate(d.s.offset).displayName(
+ atDateTime.toMSecsSinceEpoch(), nameType, locale);
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
return d->displayName(atDateTime.toMSecsSinceEpoch(), nameType, locale);
- else
- return QString();
+ }
+
+ return QString();
}
/*!
@@ -565,16 +933,30 @@ QString QTimeZone::displayName(const QDateTime &atDateTime, NameType nameType,
Where the time zone display names have changed over time then the most
recent names will be used.
+ This method is only available when feature \c timezone is enabled.
+
\sa abbreviation()
*/
QString QTimeZone::displayName(TimeType timeType, NameType nameType,
const QLocale &locale) const
{
- if (isValid())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().displayName(timeType, nameType, locale);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return QUtcTimeZonePrivate(d.s.offset).displayName(timeType, nameType, locale);
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
return d->displayName(timeType, nameType, locale);
- else
- return QString();
+ }
+
+ return QString();
}
/*!
@@ -584,15 +966,29 @@ QString QTimeZone::displayName(TimeType timeType, NameType nameType,
Note that the abbreviation is not guaranteed to be unique to this time zone
and should not be used in place of the ID or display name.
+ This method is only available when feature \c timezone is enabled.
+
\sa displayName()
*/
QString QTimeZone::abbreviation(const QDateTime &atDateTime) const
{
- if (isValid())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().abbreviation(atDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return QUtcTimeZonePrivate(d.s.offset).abbreviation(atDateTime.toMSecsSinceEpoch());
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
return d->abbreviation(atDateTime.toMSecsSinceEpoch());
- else
- return QString();
+ }
+
+ return QString();
}
/*!
@@ -606,15 +1002,30 @@ QString QTimeZone::abbreviation(const QDateTime &atDateTime) const
offsetFromUtc() will return +3600 (UTC+01:00), and during DST it will
return +7200 (UTC+02:00).
+ This method is only available when feature \c timezone is enabled.
+
\sa standardTimeOffset(), daylightTimeOffset()
*/
int QTimeZone::offsetFromUtc(const QDateTime &atDateTime) const
{
- if (isValid())
- return d->offsetFromUtc(atDateTime.toMSecsSinceEpoch());
- else
- return 0;
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().offsetFromUtc(atDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return d.s.offset;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
+ const int offset = d->offsetFromUtc(atDateTime.toMSecsSinceEpoch());
+ if (offset != QTimeZonePrivate::invalidSeconds())
+ return offset;
+ }
+ return 0;
}
/*!
@@ -626,15 +1037,30 @@ int QTimeZone::offsetFromUtc(const QDateTime &atDateTime) const
+3600 seconds. During both standard and DST offsetFromUtc() will return
+3600 (UTC+01:00).
+ This method is only available when feature \c timezone is enabled.
+
\sa offsetFromUtc(), daylightTimeOffset()
*/
int QTimeZone::standardTimeOffset(const QDateTime &atDateTime) const
{
- if (isValid())
- return d->standardTimeOffset(atDateTime.toMSecsSinceEpoch());
- else
- return 0;
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().standardTimeOffset(atDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return d.s.offset;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
+ const int offset = d->standardTimeOffset(atDateTime.toMSecsSinceEpoch());
+ if (offset != QTimeZonePrivate::invalidSeconds())
+ return offset;
+ }
+ return 0;
}
/*!
@@ -646,59 +1072,117 @@ int QTimeZone::standardTimeOffset(const QDateTime &atDateTime) const
seconds. During standard time daylightTimeOffset() will return 0, and when
daylight-saving is in effect it will return +3600.
+ This method is only available when feature \c timezone is enabled.
+
\sa offsetFromUtc(), standardTimeOffset()
*/
int QTimeZone::daylightTimeOffset(const QDateTime &atDateTime) const
{
- if (hasDaylightTime())
- return d->daylightTimeOffset(atDateTime.toMSecsSinceEpoch());
- else
- return 0;
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().daylightTimeOffset(atDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return 0;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (hasDaylightTime()) {
+ const int offset = d->daylightTimeOffset(atDateTime.toMSecsSinceEpoch());
+ if (offset != QTimeZonePrivate::invalidSeconds())
+ return offset;
+ }
+ return 0;
}
/*!
Returns \c true if the time zone has practiced daylight-saving at any time.
+ This method is only available when feature \c timezone is enabled.
+
\sa isDaylightTime(), daylightTimeOffset()
*/
bool QTimeZone::hasDaylightTime() const
{
- if (isValid())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().hasDaylightTime();
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return false;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
return d->hasDaylightTime();
- else
- return false;
+ }
+ return false;
}
/*!
Returns \c true if daylight-saving was in effect at the given \a atDateTime.
+ This method is only available when feature \c timezone is enabled.
+
\sa hasDaylightTime(), daylightTimeOffset()
*/
bool QTimeZone::isDaylightTime(const QDateTime &atDateTime) const
{
- if (hasDaylightTime())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().isDaylightTime(atDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return false;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (hasDaylightTime()) {
return d->isDaylightTime(atDateTime.toMSecsSinceEpoch());
- else
- return false;
+ }
+ return false;
}
/*!
- Returns the effective offset details at the given \a forDateTime. This is
- the equivalent of calling offsetFromUtc(), abbreviation(), etc individually but is
- more efficient.
+ Returns the effective offset details at the given \a forDateTime.
+
+ This is the equivalent of calling abbreviation() and all three offset
+ functions individually but is more efficient. If this data is not available
+ for the given datetime, an invalid OffsetData will be returned with an
+ invalid QDateTime as its \c atUtc.
+
+ This method is only available when feature \c timezone is enabled.
\sa offsetFromUtc(), standardTimeOffset(), daylightTimeOffset(), abbreviation()
*/
QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
{
- if (hasTransitions())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().offsetData(forDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return { abbreviation(forDateTime), forDateTime, int(d.s.offset), int(d.s.offset), 0 };
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+ if (isValid())
return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch()));
- else
- return QTimeZonePrivate::invalidOffsetData();
+
+ return QTimeZonePrivate::invalidOffsetData();
}
/*!
@@ -707,15 +1191,28 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
Transitions are changes in the time-zone: these happen when DST turns on or
off and when authorities alter the offsets for the time-zone.
+ This method is only available when feature \c timezone is enabled.
+
\sa nextTransition(), previousTransition(), transitions()
*/
bool QTimeZone::hasTransitions() const
{
- if (isValid())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().hasTransitions();
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return false;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (isValid()) {
return d->hasTransitions();
- else
- return false;
+ }
+ return false;
}
/*!
@@ -724,19 +1221,33 @@ bool QTimeZone::hasTransitions() const
Transition after it.
If there is no transition after the given \a afterDateTime then an invalid
- OffsetData will be returned with an invalid QDateTime.
+ OffsetData will be returned with an invalid QDateTime as its \c atUtc.
The given \a afterDateTime is exclusive.
+ This method is only available when feature \c timezone is enabled.
+
\sa hasTransitions(), previousTransition(), transitions()
*/
QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime) const
{
- if (hasTransitions())
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().nextTransition(afterDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ break;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (hasTransitions()) {
return QTimeZonePrivate::toOffsetData(d->nextTransition(afterDateTime.toMSecsSinceEpoch()));
- else
- return QTimeZonePrivate::invalidOffsetData();
+ }
+
+ return QTimeZonePrivate::invalidOffsetData();
}
/*!
@@ -745,25 +1256,44 @@ QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime)
Transition before it.
If there is no transition before the given \a beforeDateTime then an invalid
- OffsetData will be returned with an invalid QDateTime.
+ OffsetData will be returned with an invalid QDateTime as its \c atUtc.
The given \a beforeDateTime is exclusive.
+ This method is only available when feature \c timezone is enabled.
+
\sa hasTransitions(), nextTransition(), transitions()
*/
QTimeZone::OffsetData QTimeZone::previousTransition(const QDateTime &beforeDateTime) const
{
- if (hasTransitions())
- return QTimeZonePrivate::toOffsetData(d->previousTransition(beforeDateTime.toMSecsSinceEpoch()));
- else
- return QTimeZonePrivate::invalidOffsetData();
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().previousTransition(beforeDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ break;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (hasTransitions()) {
+ return QTimeZonePrivate::toOffsetData(
+ d->previousTransition(beforeDateTime.toMSecsSinceEpoch()));
+ }
+
+ return QTimeZonePrivate::invalidOffsetData();
}
/*!
Returns a list of all time zone transitions between the given datetimes.
- The given \a fromDateTime and \a toDateTime are inclusive.
+ The given \a fromDateTime and \a toDateTime are inclusive. The \c atUtc
+ member of each entry describes the moment of the transition, at which the
+ offsets and abbreviation given by other members take effect.
+
+ This method is only available when feature \c timezone is enabled.
\sa hasTransitions(), nextTransition(), previousTransition()
*/
@@ -772,10 +1302,21 @@ QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime,
const QDateTime &toDateTime) const
{
OffsetDataList list;
- if (hasTransitions()) {
+ if (d.isShort()) {
+ switch (d.s.spec()) {
+ case Qt::LocalTime:
+ return systemTimeZone().transitions(fromDateTime, toDateTime);
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ break;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (hasTransitions()) {
const QTimeZonePrivate::DataList plist = d->transitions(fromDateTime.toMSecsSinceEpoch(),
toDateTime.toMSecsSinceEpoch());
- list.reserve(plist.count());
+ list.reserve(plist.size());
for (const QTimeZonePrivate::Data &pdata : plist)
list.append(QTimeZonePrivate::toOffsetData(pdata));
}
@@ -787,34 +1328,82 @@ QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime,
/*!
Returns the current system time zone IANA ID.
- On Windows this ID is translated from the Windows ID using an internal
- translation table and the user's selected country. As a consequence there
- is a small chance any Windows install may have IDs not known by Qt, in
- which case "UTC" will be returned.
+ Equivalent to calling systemTimeZone().id(), but may bypass some computation
+ to obtain it. Constructing a QTimeZone from the returned byte array will
+ produce the same result as systemTimeZone().
+
+ If the backend is unable to determine the correct system zone, the result is
+ empty. In this case, systemTimeZone().isValid() is false and a warning is
+ output if either this method of systemTimeZone() is called.
+
+ If the backend is able to determine the correct system zone but not its
+ name, an empty byte array is returned. For example, on Windows, the system
+ native ID is converted to an IANA ID - if the system ID isn't known to the
+ internal translation code, the result shall be empty. In this case,
+ systemTimeZone().isValid() shall be true.
+
+ This method is only available when feature \c timezone is enabled.
+
+ \note Prior to Qt 6.7, when the result could not be determined, the
+ misleading result "UTC" was returned.
+
+ \sa systemTimeZone()
*/
QByteArray QTimeZone::systemTimeZoneId()
{
- return global_tz->backend->systemTimeZoneId();
+ QByteArray sys = global_tz->backend->systemTimeZoneId();
+ if (!sys.isEmpty())
+ return sys;
+ // The system zone, despite the empty ID, may know its real ID anyway:
+ return systemTimeZone().id();
}
/*!
\since 5.5
- Returns a QTimeZone object that refers to the local system time, as
- specified by systemTimeZoneId().
- \sa utc()
+ Returns a QTimeZone object that describes local system time.
+
+ This method is only available when feature \c timezone is enabled. The
+ returned instance is usually equivalent to the lightweight time
+ representation \c {QTimeZone(QTimeZone::LocalTime)}, albeit implemented as a
+ time zone.
+
+ The returned object will not change to reflect any subsequent change to the
+ system time zone. It represents the local time that was in effect when
+ asBackendZone() was called. On misconfigured systems, such as those that
+ lack the timezone data relied on by the backend for which Qt was compiled,
+ it may be invalid. In such a case, a warning is output.
+
+ \sa utc(), Initialization, asBackendZone(), systemTimeZoneId()
*/
QTimeZone QTimeZone::systemTimeZone()
{
- return QTimeZone(QTimeZone::systemTimeZoneId());
+ // Use ID even if empty, as default constructor is invalid but empty-ID
+ // constructor goes to backend's default constructor, which may succeed.
+ const auto sys = QTimeZone(global_tz->backend->systemTimeZoneId());
+ if (!sys.isValid()) {
+ static bool neverWarned = true;
+ if (neverWarned) {
+ // Racey but, at worst, merely repeats the warning.
+ neverWarned = false;
+ qWarning("Unable to determine system time zone: "
+ "please check your system configuration.");
+ }
+ }
+ return sys;
}
/*!
\since 5.5
- Returns a QTimeZone object that refers to UTC (Universal Time Coordinated).
+ Returns a QTimeZone object that describes UTC as a time zone.
- \sa systemTimeZone()
+ This method is only available when feature \c timezone is enabled. It is
+ equivalent to passing 0 to QTimeZone(int offsetSeconds) and to the
+ lightweight time representation QTimeZone(QTimeZone::UTC), albeit
+ implemented as a time zone, unlike the latter.
+
+ \sa systemTimeZone(), Initialization, asBackendZone()
*/
QTimeZone QTimeZone::utc()
{
@@ -824,17 +1413,29 @@ QTimeZone QTimeZone::utc()
/*!
Returns \c true if a given time zone \a ianaId is available on this system.
+ This may include some non-IANA IDs, notably UTC-offset IDs, that are not
+ listed in \l availableTimeZoneIds().
+
+ This method is only available when feature \c timezone is enabled.
+
\sa availableTimeZoneIds()
*/
bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
{
+#if defined(Q_OS_UNIX) && !(defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN))
+ // Keep #if-ery consistent with selection of QTzTimeZonePrivate in
+ // newBackendTimeZone(). Skip the pre-check, as the TZ backend accepts POSIX
+ // zone IDs, which need not be valid IANA IDs. See also QTBUG-112006.
+#else
// isValidId is not strictly required, but faster to weed out invalid
// IDs as availableTimeZoneIds() may be slow
if (!QTimeZonePrivate::isValidId(ianaId))
return false;
- return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) ||
- global_tz->backend->isTimeZoneIdAvailable(ianaId);
+#endif
+ return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId)
+ || QUtcTimeZonePrivate::offsetFromUtcString(ianaId) != QTimeZonePrivate::invalidSeconds()
+ || global_tz->backend->isTimeZoneIdAvailable(ianaId);
}
static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByteArray> &l2)
@@ -850,6 +1451,12 @@ static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByt
/*!
Returns a list of all available IANA time zone IDs on this system.
+ This method is only available when feature \c timezone is enabled.
+
+ \note the QTimeZone constructor will also accept some UTC-offset IDs that
+ are not in the list returned - it would be impractical to list all possible
+ UTC-offset IDs.
+
\sa isTimeZoneIdAvailable()
*/
@@ -860,27 +1467,35 @@ QList<QByteArray> QTimeZone::availableTimeZoneIds()
}
/*!
- Returns a list of all available IANA time zone IDs for a given \a country.
+ Returns a list of all available IANA time zone IDs for a given \a territory.
- As a special case, a \a country of Qt::AnyCountry returns those time zones
- that do not have any country related to them, such as UTC. If you require
- a list of all time zone IDs for all countries then use the standard
- availableTimeZoneIds() method.
+ As a special case, a \a territory of \l {QLocale::}{AnyTerritory} selects
+ those time zones that have no known territorial association, such as UTC. If
+ you require a list of all time zone IDs for all territories then use the
+ standard availableTimeZoneIds() method.
- \sa isTimeZoneIdAvailable()
+ This method is only available when feature \c timezone is enabled.
+
+ \sa isTimeZoneIdAvailable(), territory()
*/
-QList<QByteArray> QTimeZone::availableTimeZoneIds(QLocale::Country country)
+QList<QByteArray> QTimeZone::availableTimeZoneIds(QLocale::Territory territory)
{
- return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(country),
- global_tz->backend->availableTimeZoneIds(country));
+ return set_union(QUtcTimeZonePrivate().availableTimeZoneIds(territory),
+ global_tz->backend->availableTimeZoneIds(territory));
}
/*!
Returns a list of all available IANA time zone IDs with a given standard
time offset of \a offsetSeconds.
- \sa isTimeZoneIdAvailable()
+ Where the given offset is supported, \c{QTimeZone(offsetSeconds).id()} is
+ included in the list, even if it is not an IANA ID. This only arises when
+ there is no IANA UTC-offset ID with the given offset.
+
+ This method is only available when feature \c timezone is enabled.
+
+ \sa isTimeZoneIdAvailable(), QTimeZone(int)
*/
QList<QByteArray> QTimeZone::availableTimeZoneIds(int offsetSeconds)
@@ -892,6 +1507,8 @@ QList<QByteArray> QTimeZone::availableTimeZoneIds(int offsetSeconds)
/*!
Returns the Windows ID equivalent to the given \a ianaId.
+ This method is only available when feature \c timezone is enabled.
+
\sa windowsIdToDefaultIanaId(), windowsIdToIanaIds()
*/
@@ -904,9 +1521,11 @@ QByteArray QTimeZone::ianaIdToWindowsId(const QByteArray &ianaId)
Returns the default IANA ID for a given \a windowsId.
Because a Windows ID can cover several IANA IDs in several different
- countries, this function returns the most frequently used IANA ID with no
- regard for the country and should thus be used with care. It is usually
- best to request the default for a specific country.
+ territories, this function returns the most frequently used IANA ID with no
+ regard for the territory and should thus be used with care. It is usually
+ best to request the default for a specific territory.
+
+ This method is only available when feature \c timezone is enabled.
\sa ianaIdToWindowsId(), windowsIdToIanaIds()
*/
@@ -917,21 +1536,23 @@ QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId)
}
/*!
- Returns the default IANA ID for a given \a windowsId and \a country.
+ Returns the default IANA ID for a given \a windowsId and \a territory.
- Because a Windows ID can cover several IANA IDs within a given country,
- the most frequently used IANA ID in that country is returned.
+ Because a Windows ID can cover several IANA IDs within a given territory,
+ the most frequently used IANA ID in that territory is returned.
- As a special case, QLocale::AnyCountry returns the default of those IANA IDs
- that do not have any specific country.
+ As a special case, \l{QLocale::}{AnyTerritory} returns the default of those
+ IANA IDs that have no known territorial association.
- \sa ianaIdToWindowsId(), windowsIdToIanaIds()
+ This method is only available when feature \c timezone is enabled.
+
+ \sa ianaIdToWindowsId(), windowsIdToIanaIds(), territory()
*/
QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId,
- QLocale::Country country)
+ QLocale::Territory territory)
{
- return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId, country);
+ return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId, territory);
}
/*!
@@ -939,6 +1560,8 @@ QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId,
The returned list is sorted alphabetically.
+ This method is only available when feature \c timezone is enabled.
+
\sa ianaIdToWindowsId(), windowsIdToDefaultIanaId()
*/
@@ -948,27 +1571,81 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId)
}
/*!
- Returns all the IANA IDs for a given \a windowsId and \a country.
+ Returns all the IANA IDs for a given \a windowsId and \a territory.
- As a special case QLocale::AnyCountry returns those IANA IDs that do
- not have any specific country.
+ As a special case, \l{QLocale::}{AnyTerritory} selects those IANA IDs that
+ have no known territorial association.
The returned list is in order of frequency of usage, i.e. larger zones
- within a country are listed first.
+ within a territory are listed first.
- \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId()
+ This method is only available when feature \c timezone is enabled.
+
+ \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId(), territory()
*/
QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
- QLocale::Country country)
+ QLocale::Territory territory)
{
- return QTimeZonePrivate::windowsIdToIanaIds(windowsId, country);
+ return QTimeZonePrivate::windowsIdToIanaIds(windowsId, territory);
+}
+
+/*!
+ \fn QTimeZone QTimeZone::fromStdTimeZonePtr(const std::chrono::time_zone *timeZone)
+ \since 6.4
+
+ Returns a QTimeZone object representing the same time zone as \a timeZone.
+ The IANA ID of \a timeZone must be one of the available system IDs,
+ otherwise an invalid time zone will be returned.
+
+ This method is only available when feature \c timezone is enabled.
+*/
+#endif // feature timezone
+
+template <typename Stream, typename Wrap>
+void QTimeZone::Data::serialize(Stream &out, const Wrap &wrap) const
+{
+ if (isShort()) {
+ switch (s.spec()) {
+ case Qt::UTC:
+ out << wrap("QTimeZone::UTC");
+ break;
+ case Qt::LocalTime:
+ out << wrap("QTimeZone::LocalTime");
+ break;
+ case Qt::OffsetFromUTC:
+ out << wrap("AheadOfUtcBy") << int(s.offset);
+ break;
+ case Qt::TimeZone:
+ Q_UNREACHABLE();
+ break;
+ }
+ return;
+ }
+#if QT_CONFIG(timezone)
+ if constexpr (std::is_same<Stream, QDataStream>::value) {
+ if (d)
+ d->serialize(out);
+ } else {
+ // QDebug, traditionally gets a QString, hence quotes round the (possibly empty) ID:
+ out << QString::fromUtf8(d ? QByteArrayView(d->id()) : QByteArrayView());
+ }
+#endif
}
#ifndef QT_NO_DATASTREAM
+// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it
+static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); }
+
QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
{
- tz.d->serialize(ds);
+ const auto toQString = [](const char *text) {
+ return QString(QLatin1StringView(text));
+ };
+ if (tz.isValid())
+ tz.d.serialize(ds, toQString);
+ else
+ ds << invalidId();
return ds;
}
@@ -976,22 +1653,42 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
{
QString ianaId;
ds >> ianaId;
- if (ianaId == QLatin1String("OffsetFromUtc")) {
+ // That may be various things other than actual IANA IDs:
+ if (ianaId == invalidId()) {
+ tz = QTimeZone();
+ } else if (ianaId == "OffsetFromUtc"_L1) {
int utcOffset;
QString name;
QString abbreviation;
- int country;
+ int territory;
QString comment;
- ds >> ianaId >> utcOffset >> name >> abbreviation >> country >> comment;
+ ds >> ianaId >> utcOffset >> name >> abbreviation >> territory >> comment;
+#if QT_CONFIG(timezone)
// Try creating as a system timezone, which succeeds (producing a valid
- // zone) iff ianaId is valid; we can then ignore the other data.
+ // zone) iff ianaId is valid; use this if it is a plain offset from UTC
+ // zone, with the right offset, ignoring the other data:
tz = QTimeZone(ianaId.toUtf8());
- // If not, then construct a custom timezone using all the saved values:
- if (!tz.isValid())
+ if (!tz.isValid() || tz.hasDaylightTime()
+ || tz.offsetFromUtc(QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC)) != utcOffset) {
+ // Construct a custom timezone using the saved values:
tz = QTimeZone(ianaId.toUtf8(), utcOffset, name, abbreviation,
- QLocale::Country(country), comment);
+ QLocale::Territory(territory), comment);
+ }
+#else
+ tz = QTimeZone::fromSecondsAheadOfUtc(utcOffset);
+#endif
+ } else if (ianaId == "AheadOfUtcBy"_L1) {
+ int utcOffset;
+ ds >> utcOffset;
+ tz = QTimeZone::fromSecondsAheadOfUtc(utcOffset);
+ } else if (ianaId == "QTimeZone::UTC"_L1) {
+ tz = QTimeZone(QTimeZone::UTC);
+ } else if (ianaId == "QTimeZone::LocalTime"_L1) {
+ tz = QTimeZone(QTimeZone::LocalTime);
+#if QT_CONFIG(timezone)
} else {
tz = QTimeZone(ianaId.toUtf8());
+#endif
}
return ds;
}
@@ -1001,8 +1698,11 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
QDebug operator<<(QDebug dbg, const QTimeZone &tz)
{
QDebugStateSaver saver(dbg);
- //TODO Include backend and data version details?
- dbg.nospace() << "QTimeZone(" << QString::fromUtf8(tz.id()) << ')';
+ const auto asIs = [](const char *text) { return text; };
+ // TODO Include backend and data version details?
+ dbg.nospace() << "QTimeZone(";
+ tz.d.serialize(dbg, asIs);
+ dbg.nospace() << ')';
return dbg;
}
#endif
diff --git a/src/corelib/time/qtimezone.h b/src/corelib/time/qtimezone.h
index 11070cc2eb..46c7d6312b 100644
--- a/src/corelib/time/qtimezone.h
+++ b/src/corelib/time/qtimezone.h
@@ -1,53 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTIMEZONE_H
#define QTIMEZONE_H
-#include <QtCore/qshareddata.h>
-#include <QtCore/qlocale.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qlocale.h>
+#include <QtCore/qswap.h>
+#include <QtCore/qtclasshelpermacros.h>
-QT_REQUIRE_CONFIG(timezone);
+#include <chrono>
-#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
+#if QT_CONFIG(timezone) && (defined(Q_OS_DARWIN) || defined(Q_QDOC))
Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone);
Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
#endif
@@ -58,14 +24,125 @@ class QTimeZonePrivate;
class Q_CORE_EXPORT QTimeZone
{
-public:
- // Sane UTC offsets range from -14 to +14 hours:
- enum {
- // No known zone > 12 hrs West of Greenwich (Baker Island, USA)
- MinUtcOffsetSecs = -14 * 3600,
- // No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati)
- MaxUtcOffsetSecs = +14 * 3600
+ struct ShortData
+ {
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ quintptr mode : 2;
+#endif
+ qintptr offset : sizeof(void *) * 8 - 2;
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ quintptr mode : 2;
+#endif
+
+ // mode is a cycled Qt::TimeSpec, (int(spec) + 1) % 4, so that zero
+ // (lowest bits of a pointer) matches spec being Qt::TimeZone, for which
+ // Data holds a QTZP pointer instead of ShortData.
+ // Passing Qt::TimeZone gets the equivalent of a null QTZP; it is not short.
+ constexpr ShortData(Qt::TimeSpec spec, int secondsAhead = 0)
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ : offset(spec == Qt::OffsetFromUTC ? secondsAhead : 0),
+ mode((int(spec) + 1) & 3)
+#else
+ : mode((int(spec) + 1) & 3),
+ offset(spec == Qt::OffsetFromUTC ? secondsAhead : 0)
+#endif
+ {
+ }
+ friend constexpr bool operator==(ShortData lhs, ShortData rhs)
+ { return lhs.mode == rhs.mode && lhs.offset == rhs.offset; }
+ constexpr Qt::TimeSpec spec() const { return Qt::TimeSpec((mode + 3) & 3); }
+ };
+
+ union Data
+ {
+ Data() noexcept;
+ Data(ShortData sd) : s(sd) {}
+ Data(const Data &other) noexcept;
+ Data(Data &&other) noexcept : d(std::exchange(other.d, nullptr)) {}
+ Data &operator=(const Data &other) noexcept;
+ Data &operator=(Data &&other) noexcept { swap(other); return *this; }
+ ~Data();
+
+ void swap(Data &other) noexcept { qt_ptr_swap(d, other.d); }
+ // isShort() is equivalent to s.spec() != Qt::TimeZone
+ bool isShort() const { return s.mode; } // a.k.a. quintptr(d) & 3
+
+ // Typse must support: out << wrap("C-strings");
+ template <typename Stream, typename Wrap>
+ void serialize(Stream &out, const Wrap &wrap) const;
+
+ Data(QTimeZonePrivate *dptr) noexcept;
+ Data &operator=(QTimeZonePrivate *dptr) noexcept;
+ const QTimeZonePrivate *operator->() const { Q_ASSERT(!isShort()); return d; }
+ QTimeZonePrivate *operator->() { Q_ASSERT(!isShort()); return d; }
+
+ QTimeZonePrivate *d = nullptr;
+ ShortData s;
};
+ QTimeZone(ShortData sd) : d(sd) {}
+
+public:
+ // Sane UTC offsets range from -16 to +16 hours:
+ static constexpr int MinUtcOffsetSecs = -16 * 3600;
+ // No known modern zone > 12 hrs West of Greenwich.
+ // Until 1844, Asia/Manila (in The Philippines) was at 15:56 West.
+ static constexpr int MaxUtcOffsetSecs = +16 * 3600;
+ // No known modern zone > 14 hrs East of Greenwich.
+ // Until 1867, America/Metlakatla (in Alaska) was at 15:13:42 East.
+
+ enum Initialization { LocalTime, UTC };
+
+ QTimeZone() noexcept;
+ Q_IMPLICIT QTimeZone(Initialization spec) noexcept
+ : d(ShortData(spec == UTC ? Qt::UTC : Qt::LocalTime)) {}
+
+#if QT_CONFIG(timezone)
+ explicit QTimeZone(int offsetSeconds);
+ explicit QTimeZone(const QByteArray &ianaId);
+ QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
+ const QString &abbreviation, QLocale::Territory territory = QLocale::AnyTerritory,
+ const QString &comment = QString());
+#endif // timezone backends
+
+ QTimeZone(const QTimeZone &other) noexcept;
+ QTimeZone(QTimeZone &&other) noexcept : d(std::move(other.d)) {}
+ ~QTimeZone();
+
+ QTimeZone &operator=(const QTimeZone &other);
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QTimeZone)
+
+ void swap(QTimeZone &other) noexcept
+ { d.swap(other.d); }
+
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ bool operator==(const QTimeZone &other) const;
+ bool operator!=(const QTimeZone &other) const;
+#endif
+
+ bool isValid() const;
+
+ static QTimeZone fromDurationAheadOfUtc(std::chrono::seconds offset)
+ {
+ return QTimeZone((offset.count() >= MinUtcOffsetSecs && offset.count() <= MaxUtcOffsetSecs)
+ ? ShortData(offset.count() ? Qt::OffsetFromUTC : Qt::UTC,
+ int(offset.count()))
+ : ShortData(Qt::TimeZone));
+ }
+ static QTimeZone fromSecondsAheadOfUtc(int offset)
+ {
+ return fromDurationAheadOfUtc(std::chrono::seconds{offset});
+ }
+ constexpr Qt::TimeSpec timeSpec() const noexcept { return d.s.spec(); }
+ constexpr int fixedSecondsAheadOfUtc() const noexcept
+ { return timeSpec() == Qt::OffsetFromUTC ? int(d.s.offset) : 0; }
+
+ static constexpr bool isUtcOrFixedOffset(Qt::TimeSpec spec) noexcept
+ { return spec == Qt::UTC || spec == Qt::OffsetFromUTC; }
+ constexpr bool isUtcOrFixedOffset() const noexcept { return isUtcOrFixedOffset(timeSpec()); }
+
+#if QT_CONFIG(timezone)
+ QTimeZone asBackendZone() const;
enum TimeType {
StandardTime = 0,
@@ -89,28 +166,12 @@ public:
};
typedef QList<OffsetData> OffsetDataList;
- QTimeZone() noexcept;
- explicit QTimeZone(const QByteArray &ianaId);
- explicit QTimeZone(int offsetSeconds);
- /*implicit*/ QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
- const QString &abbreviation, QLocale::Country country = QLocale::AnyCountry,
- const QString &comment = QString());
- QTimeZone(const QTimeZone &other);
- ~QTimeZone();
-
- QTimeZone &operator=(const QTimeZone &other);
- QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; }
-
- void swap(QTimeZone &other) noexcept
- { d.swap(other.d); }
-
- bool operator==(const QTimeZone &other) const;
- bool operator!=(const QTimeZone &other) const;
-
- bool isValid() const;
-
QByteArray id() const;
+ QLocale::Territory territory() const;
+# if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use territory() instead")
QLocale::Country country() const;
+# endif
QString comment() const;
QString displayName(const QDateTime &atDateTime,
@@ -142,36 +203,55 @@ public:
static bool isTimeZoneIdAvailable(const QByteArray &ianaId);
static QList<QByteArray> availableTimeZoneIds();
- static QList<QByteArray> availableTimeZoneIds(QLocale::Country country);
+ static QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory);
static QList<QByteArray> availableTimeZoneIds(int offsetSeconds);
static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
- QLocale::Country country);
+ QLocale::Territory territory);
static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId);
static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
- QLocale::Country country);
+ QLocale::Territory territory);
-#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
+# if defined(Q_OS_DARWIN) || defined(Q_QDOC)
static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone);
CFTimeZoneRef toCFTimeZone() const Q_DECL_CF_RETURNS_RETAINED;
static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone);
NSTimeZone *toNSTimeZone() const Q_DECL_NS_RETURNS_AUTORELEASED;
-#endif
-
+# endif
+
+# if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static QTimeZone fromStdTimeZonePtr(const std::chrono::time_zone *timeZone)
+ {
+ if (!timeZone)
+ return QTimeZone();
+ const std::string_view timeZoneName = timeZone->name();
+ return QTimeZone(QByteArrayView(timeZoneName).toByteArray());
+ }
+# endif
+#endif // feature timezone
private:
- QTimeZone(QTimeZonePrivate &dd);
+ friend Q_CORE_EXPORT bool comparesEqual(const QTimeZone &lhs, const QTimeZone &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QTimeZone)
+
#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
#endif
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QTimeZone &tz);
+#endif
+ QTimeZone(QTimeZonePrivate &dd);
friend class QTimeZonePrivate;
friend class QDateTime;
friend class QDateTimePrivate;
- QSharedDataPointer<QTimeZonePrivate> d;
+ Data d;
};
-Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_MOVABLE_TYPE);
+#if QT_CONFIG(timezone)
+Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_RELOCATABLE_TYPE);
+#endif
Q_DECLARE_SHARED(QTimeZone)
#ifndef QT_NO_DATASTREAM
@@ -183,6 +263,20 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QTimeZone &tz);
Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QTimeZone &tz);
#endif
+#if QT_CONFIG(timezone) && __cpp_lib_chrono >= 201907L
+// zoned_time
+template <typename> // QT_POST_CXX17_API_IN_EXPORTED_CLASS
+inline QDateTime QDateTime::fromStdZonedTime(const std::chrono::zoned_time<
+ std::chrono::milliseconds,
+ const std::chrono::time_zone *
+ > &time)
+{
+ const auto sysTime = time.get_sys_time();
+ const QTimeZone timeZone = QTimeZone::fromStdTimeZonePtr(time.get_time_zone());
+ return fromMSecsSinceEpoch(sysTime.time_since_epoch().count(), timeZone);
+}
+#endif
+
QT_END_NAMESPACE
#endif // QTIMEZONE_H
diff --git a/src/corelib/time/qtimezonelocale.cpp b/src/corelib/time/qtimezonelocale.cpp
new file mode 100644
index 0000000000..5757e55d28
--- /dev/null
+++ b/src/corelib/time/qtimezonelocale.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <private/qtimezonelocale_p.h>
+#include <private/qtimezoneprivate_p.h>
+
+#if !QT_CONFIG(icu) // Use data generated from CLDR:
+# include <private/qtimezonelocale_data_p.h>
+# include <private/qtimezoneprivate_data_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(icu) // Get data from ICU:
+namespace QtTimeZoneLocale {
+
+} // QtTimeZoneLocale
+#else // No ICU, use QTZ[LP}_data_p.h data for feature timezone_locale.
+namespace {
+using namespace QtTimeZoneLocale; // QTZL_data_p.h
+using namespace QtTimeZoneCldr; // QTZP_data_p.h
+// Accessors for the QTZL_data_p.h
+
+// Accessors for the QTZP_data_p.h
+
+} // nameless namespace
+#endif // ICU
+
+QT_END_NAMESPACE
diff --git a/src/corelib/time/qtimezonelocale_data_p.h b/src/corelib/time/qtimezonelocale_data_p.h
new file mode 100644
index 0000000000..1cdbbaa952
--- /dev/null
+++ b/src/corelib/time/qtimezonelocale_data_p.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: Unicode-3.0
+
+#ifndef QTIMEZONELOCALE_DATA_P_H
+#define QTIMEZONELOCALE_DATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Only qtimezonelocale.cpp should #include this (after other things it needs),
+// and even that only when feature icu is disabled.
+#include "qtimezonelocale_p.h"
+
+QT_REQUIRE_CONFIG(timezone_locale);
+#if QT_CONFIG(icu)
+# error "This file should only be needed (or seen) when ICU is not in use"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtTimeZoneLocale {
+
+// GENERATED PART STARTS HERE
+
+// GENERATED PART ENDS HERE
+
+} // QtTimeZoneLocale
+
+QT_END_NAMESPACE
+
+#endif // QTIMEZONELOCALE_DATA_P_H
diff --git a/src/corelib/time/qtimezonelocale_p.h b/src/corelib/time/qtimezonelocale_p.h
new file mode 100644
index 0000000000..adc8e83b35
--- /dev/null
+++ b/src/corelib/time/qtimezonelocale_p.h
@@ -0,0 +1,31 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTIMEZONELOCALE_P_H
+#define QTIMEZONELOCALE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qtimezone.h>
+
+QT_REQUIRE_CONFIG(timezone);
+QT_REQUIRE_CONFIG(timezone_locale);
+
+namespace QtTimeZoneLocale {
+#if QT_CONFIG(icu)
+#else
+// Define data types for QTZL_data_p.h
+
+#endif
+}
+
+#endif // QTIMEZONELOCALE_P_H
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index ebd08ea7db..2ad0d874b6 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimezone.h"
@@ -45,87 +9,108 @@
#include <qdatastream.h>
#include <qdebug.h>
+#include <qstring.h>
+
+#include <private/qcalendarmath_p.h>
+#include <private/qnumeric_p.h>
+#include <private/qtools_p.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
-/*
- Static utilities for looking up Windows ID tables
-*/
-
-static const int windowsDataTableSize = sizeof(windowsDataTable) / sizeof(QWindowsData) - 1;
-static const int zoneDataTableSize = sizeof(zoneDataTable) / sizeof(QZoneData) - 1;
-static const int utcDataTableSize = sizeof(utcDataTable) / sizeof(QUtcData) - 1;
-
+using namespace QtMiscUtils;
+using namespace QtTimeZoneCldr;
+using namespace Qt::StringLiterals;
-static const QZoneData *zoneData(quint16 index)
+// For use with std::is_sorted() in assertions:
+[[maybe_unused]]
+constexpr bool earlierZoneData(const ZoneData &less, const ZoneData &more) noexcept
{
- Q_ASSERT(index < zoneDataTableSize);
- return &zoneDataTable[index];
+ return less.windowsIdKey < more.windowsIdKey
+ || (less.windowsIdKey == more.windowsIdKey && less.territory < more.territory);
}
-static const QWindowsData *windowsData(quint16 index)
+[[maybe_unused]]
+static bool earlierWinData(const WindowsData &less, const WindowsData &more) noexcept
{
- Q_ASSERT(index < windowsDataTableSize);
- return &windowsDataTable[index];
+ // Actually only tested in the negative, to check more < less never happens,
+ // so should be true if more < less in either part; hence || not && combines.
+ return less.windowsIdKey < more.windowsIdKey
+ || less.windowsId().compare(more.windowsId(), Qt::CaseInsensitive) < 0;
}
-static const QUtcData *utcData(quint16 index)
+// For use with std::lower_bound():
+constexpr bool atLowerUtcOffset(const UtcData &entry, qint32 offsetSeconds) noexcept
{
- Q_ASSERT(index < utcDataTableSize);
- return &utcDataTable[index];
+ return entry.offsetFromUtc < offsetSeconds;
}
-// Return the Windows ID literal for a given QWindowsData
-static QByteArray windowsId(const QWindowsData *windowsData)
+constexpr bool atLowerWindowsKey(const WindowsData &entry, qint16 winIdKey) noexcept
{
- return (windowsIdData + windowsData->windowsIdIndex);
+ return entry.windowsIdKey < winIdKey;
}
-// Return the IANA ID literal for a given QWindowsData
-static QByteArray ianaId(const QWindowsData *windowsData)
+static bool earlierWindowsId(const WindowsData &entry, QByteArrayView winId) noexcept
{
- return (ianaIdData + windowsData->ianaIdIndex);
+ return entry.windowsId().compare(winId, Qt::CaseInsensitive) < 0;
}
-// Return the IANA ID literal for a given QZoneData
-static QByteArray ianaId(const QZoneData *zoneData)
+constexpr bool zoneAtLowerWindowsKey(const ZoneData &entry, qint16 winIdKey) noexcept
{
- return (ianaIdData + zoneData->ianaIdIndex);
-}
-
-static QByteArray utcId(const QUtcData *utcData)
-{
- return (ianaIdData + utcData->ianaIdIndex);
+ return entry.windowsIdKey < winIdKey;
}
+// Static table-lookup helpers
static quint16 toWindowsIdKey(const QByteArray &winId)
{
- for (quint16 i = 0; i < windowsDataTableSize; ++i) {
- const QWindowsData *data = windowsData(i);
- if (windowsId(data) == winId)
- return data->windowsIdKey;
- }
+ // Key and winId are monotonic, table is sorted on them.
+ const auto data = std::lower_bound(std::begin(windowsDataTable), std::end(windowsDataTable),
+ winId, earlierWindowsId);
+ if (data != std::end(windowsDataTable) && data->windowsId() == winId)
+ return data->windowsIdKey;
return 0;
}
static QByteArray toWindowsIdLiteral(quint16 windowsIdKey)
{
- for (quint16 i = 0; i < windowsDataTableSize; ++i) {
- const QWindowsData *data = windowsData(i);
- if (data->windowsIdKey == windowsIdKey)
- return windowsId(data);
+ // Caller should be passing a valid (in range) key; and table is sorted in
+ // increasing order, with no gaps in numbering, starting with key = 1 at
+ // index [0]. So this should normally work:
+ if (Q_LIKELY(windowsIdKey > 0 && windowsIdKey <= std::size(windowsDataTable))) {
+ const auto &data = windowsDataTable[windowsIdKey - 1];
+ if (Q_LIKELY(data.windowsIdKey == windowsIdKey))
+ return data.windowsId().toByteArray();
}
+ // Fall back on binary chop - key and winId are monotonic, table is sorted on them:
+ const auto data = std::lower_bound(std::begin(windowsDataTable), std::end(windowsDataTable),
+ windowsIdKey, atLowerWindowsKey);
+ if (data != std::end(windowsDataTable) && data->windowsIdKey == windowsIdKey)
+ return data->windowsId().toByteArray();
+
return QByteArray();
}
+static auto zoneStartForWindowsId(quint16 windowsIdKey) noexcept
+{
+ // Caller must check the resulting iterator isn't std::end(zoneDataTable)
+ // and does match windowsIdKey, since this is just the lower bound.
+ return std::lower_bound(std::begin(zoneDataTable), std::end(zoneDataTable),
+ windowsIdKey, zoneAtLowerWindowsKey);
+}
+
/*
- Base class implementing common utility routines, only intantiate for a null tz.
+ Base class implementing common utility routines, only instantiate for a null tz.
*/
QTimeZonePrivate::QTimeZonePrivate()
{
+ // If std::is_sorted() were constexpr, the first could be a static_assert().
+ // From C++20, we should be able to rework it in terms of std::all_of().
+ Q_ASSERT(std::is_sorted(std::begin(zoneDataTable), std::end(zoneDataTable),
+ earlierZoneData));
+ Q_ASSERT(std::is_sorted(std::begin(windowsDataTable), std::end(windowsDataTable),
+ earlierWinData));
}
QTimeZonePrivate::QTimeZonePrivate(const QTimeZonePrivate &other)
@@ -165,15 +150,17 @@ QByteArray QTimeZonePrivate::id() const
return m_id;
}
-QLocale::Country QTimeZonePrivate::country() const
+QLocale::Territory QTimeZonePrivate::territory() const
{
// Default fall-back mode, use the zoneTable to find Region of known Zones
- for (int i = 0; i < zoneDataTableSize; ++i) {
- const QZoneData *data = zoneData(i);
- if (ianaId(data).split(' ').contains(m_id))
- return (QLocale::Country)data->country;
+ const QLatin1StringView sought(m_id.data(), m_id.size());
+ for (const ZoneData &data : zoneDataTable) {
+ for (QLatin1StringView token : data.ids()) {
+ if (token == sought)
+ return QLocale::Territory(data.territory);
+ }
}
- return QLocale::AnyCountry;
+ return QLocale::AnyTerritory;
}
QString QTimeZonePrivate::comment() const
@@ -198,32 +185,34 @@ QString QTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- Q_UNUSED(timeType)
- Q_UNUSED(nameType)
- Q_UNUSED(locale)
+ Q_UNUSED(timeType);
+ Q_UNUSED(nameType);
+ Q_UNUSED(locale);
return QString();
}
QString QTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
- return QString();
+ return displayName(atMSecsSinceEpoch, QTimeZone::ShortName, QLocale::c());
}
int QTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
{
- return standardTimeOffset(atMSecsSinceEpoch) + daylightTimeOffset(atMSecsSinceEpoch);
+ const int std = standardTimeOffset(atMSecsSinceEpoch);
+ const int dst = daylightTimeOffset(atMSecsSinceEpoch);
+ const int bad = invalidSeconds();
+ return std == bad || dst == bad ? bad : std + dst;
}
int QTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
+ Q_UNUSED(atMSecsSinceEpoch);
return invalidSeconds();
}
int QTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
+ Q_UNUSED(atMSecsSinceEpoch);
return invalidSeconds();
}
@@ -234,40 +223,67 @@ bool QTimeZonePrivate::hasDaylightTime() const
bool QTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
+ Q_UNUSED(atMSecsSinceEpoch);
return false;
}
QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
- Q_UNUSED(forMSecsSinceEpoch)
- return invalidData();
+ Q_UNUSED(forMSecsSinceEpoch);
+ return {};
}
// Private only method for use by QDateTime to convert local msecs to epoch msecs
-QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, int hint) const
+QDateTimePrivate::ZoneState QTimeZonePrivate::stateAtZoneTime(
+ qint64 forLocalMSecs, QDateTimePrivate::TransitionOptions resolve) const
{
- if (!hasDaylightTime()) // No DST means same offset for all local msecs
- return data(forLocalMSecs - standardTimeOffset(forLocalMSecs) * 1000);
+ auto dataToState = [](const QTimeZonePrivate::Data &d) {
+ return QDateTimePrivate::ZoneState(d.atMSecsSinceEpoch + d.offsetFromUtc * 1000,
+ d.offsetFromUtc,
+ d.daylightTimeOffset ? QDateTimePrivate::DaylightTime
+ : QDateTimePrivate::StandardTime);
+ };
/*
We need a UTC time at which to ask for the offset, in order to be able to
- add that offset to forLocalMSecs, to get the UTC time we
- need. Fortunately, no time-zone offset is more than 14 hours; and DST
- transitions happen (much) more than thirty-two hours apart. So sampling
- offset sixteen hours each side gives us information we can be sure
+ add that offset to forLocalMSecs, to get the UTC time we need.
+ Fortunately, all time-zone offsets have been less than 17 hours; and DST
+ transitions happen (much) more than thirty-four hours apart. So sampling
+ offset seventeen hours each side gives us information we can be sure
brackets the correct time and at most one DST transition.
*/
- const qint64 sixteenHoursInMSecs(16 * 3600 * 1000);
- static_assert(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
- && sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
- const qint64 recent = forLocalMSecs - sixteenHoursInMSecs;
- const qint64 imminent = forLocalMSecs + sixteenHoursInMSecs;
+ std::integral_constant<qint64, 17 * 3600 * 1000> seventeenHoursInMSecs;
+ static_assert(-seventeenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
+ && seventeenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
+ qint64 millis;
+ // Clip the bracketing times to the bounds of the supported range.
+ const qint64 recent =
+ qSubOverflow(forLocalMSecs, seventeenHoursInMSecs, &millis) || millis < minMSecs()
+ ? minMSecs() : millis; // Necessarily <= forLocalMSecs + 1.
+ // (Given that minMSecs() is std::numeric_limits<qint64>::min() + 1.)
+ const qint64 imminent =
+ qAddOverflow(forLocalMSecs, seventeenHoursInMSecs, &millis)
+ ? maxMSecs() : millis; // Necessarily >= forLocalMSecs
+ // At most one of those was clipped to its boundary value:
+ Q_ASSERT(recent < imminent && seventeenHoursInMSecs < imminent - recent + 1);
+
+ const Data past = data(recent), future = data(imminent);
+ // > 99% of the time, past and future will agree:
+ if (Q_LIKELY(past.offsetFromUtc == future.offsetFromUtc
+ && past.standardTimeOffset == future.standardTimeOffset
+ // Those two imply same daylightTimeOffset.
+ && past.abbreviation == future.abbreviation)) {
+ Data data = future;
+ data.atMSecsSinceEpoch = forLocalMSecs - future.offsetFromUtc * 1000;
+ return dataToState(data);
+ }
+
/*
Offsets are Local - UTC, positive to the east of Greenwich, negative to
- the west; DST offset always exceeds standard offset, when DST applies.
+ the west; DST offset normally exceeds standard offset, when DST applies.
When we have offsets on either side of a transition, the lower one is
- standard, the higher is DST.
+ standard, the higher is DST, unless we have data telling us it's the other
+ way round.
Non-DST transitions (jurisdictions changing time-zone and time-zones
changing their standard offset, typically) are described below as if they
@@ -279,60 +295,34 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
and take the easy path; with transitions, tran and nextTran get the
correct UTC time as atMSecsSinceEpoch so comparing to nextStart selects
the right one. In all other cases, the transition changes offset and the
- reasoning that applies to DST applies just the same. Aside from hinting,
- the only thing that looks at DST-ness at all, other than inferred from
- offset changes, is the case without transition data handling an invalid
- time in the gap that a transition passed over.
-
- The handling of hint (see below) is apt to go wrong in non-DST
- transitions. There isn't really a great deal we can hope to do about that
- without adding yet more unreliable complexity to the heuristics in use for
- already obscure corner-cases.
- */
-
- /*
- The hint (really a QDateTimePrivate::DaylightStatus) is > 0 if caller
- thinks we're in DST, 0 if in standard. A value of -2 means never-DST, so
- should have been handled above; if it slips through, it's wrong but we
- should probably treat it as standard anyway (never-DST means
- always-standard, after all). If the hint turns out to be wrong, fall back
- on trying the other possibility: which makes it harmless to treat -1
- (meaning unknown) as standard (i.e. try standard first, then try DST). In
- practice, away from a transition, the only difference hint makes is to
- which candidate we try first: if the hint is wrong (or unknown and
- standard fails), we'll try the other candidate and it'll work.
-
- For the obscure (and invalid) case where forLocalMSecs falls in a
- spring-forward's missing hour, a common case is that we started with a
- date/time for which the hint was valid and adjusted it naively; for that
- case, we should correct the adjustment by shunting across the transition
- into where hint is wrong. So half-way through the gap, arrived at from
- the DST side, should be read as an hour earlier, in standard time; but, if
- arrived at from the standard side, should be read as an hour later, in
- DST. (This shall be wrong in some cases; for example, when a country
- changes its transition dates and changing a date/time by more than six
- months lands it on a transition. However, these cases are even more
- obscure than those where the heuristic is good.)
- */
-
+ reasoning that applies to DST applies just the same.
+
+ The resolution of transitions, specified by \a resolve, may be lead astray
+ if (as happens on Windows) the backend has been obliged to guess whether a
+ transition is in fact a DST one or a change to standard offset; or to
+ guess that the higher-offset side is the DST one (the reverse of this is
+ true for Ireland, using negative DST). There's not much we can do about
+ that, though.
+ */
if (hasTransitions()) {
/*
We have transitions.
- Each transition gives the offsets to use until the next; so we need the
- most recent transition before the time forLocalMSecs describes. If it
- describes a time *in* a transition, we'll need both that transition and
- the one before it. So find one transition that's probably after (and not
- much before, otherwise) and another that's definitely before, then work
- out which one to use. When both or neither work on forLocalMSecs, use
- hint to disambiguate.
+ Each transition gives the offsets to use until the next; so we need
+ the most recent transition before the time forLocalMSecs describes. If
+ it describes a time *in* a transition, we'll need both that transition
+ and the one before it. So find one transition that's probably after
+ (and not much before, otherwise) and another that's definitely before,
+ then work out which one to use. When both or neither work on
+ forLocalMSecs, use resolve to disambiguate.
*/
// Get a transition definitely before the local MSecs; usually all we need.
// Only around the transition times might we need another.
- Data tran = previousTransition(recent);
+ Data tran = past; // Data after last transition before our window.
Q_ASSERT(forLocalMSecs < 0 || // Pre-epoch TZ info may be unavailable
forLocalMSecs - tran.offsetFromUtc * 1000 >= tran.atMSecsSinceEpoch);
+ // If offset actually exceeds 17 hours, that assert may trigger.
Data nextTran = nextTransition(tran.atMSecsSinceEpoch);
/*
Now walk those forward until they bracket forLocalMSecs with transitions.
@@ -340,7 +330,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
One of the transitions should then be telling us the right offset to use.
In a transition, we need the transition before it (to describe the run-up
to the transition) and the transition itself; so we need to stop when
- nextTran is that transition.
+ nextTran is (invalid or) that transition.
*/
while (nextTran.atMSecsSinceEpoch != invalidMSecs()
&& forLocalMSecs > nextTran.atMSecsSinceEpoch + nextTran.offsetFromUtc * 1000) {
@@ -356,95 +346,139 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
// Check we do *really* have transitions for this zone:
if (tran.atMSecsSinceEpoch != invalidMSecs()) {
-
- /*
- So now tran is definitely before and nextTran is either after or only
- slightly before. One is standard time; we interpret the other as DST
- (although the transition might in fact by a change in standard offset). Our
- hint tells us which of those to use (defaulting to standard if no hint): try
- it first; if that fails, try the other; if both fail, life's tricky.
- */
+ /* So now tran is definitely before ... */
Q_ASSERT(forLocalMSecs < 0
|| forLocalMSecs - tran.offsetFromUtc * 1000 > tran.atMSecsSinceEpoch);
- const qint64 nextStart = nextTran.atMSecsSinceEpoch;
- // Work out the UTC values it might make sense to return:
- nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
+ // Work out the UTC value it would make sense to return if using tran:
tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
-
- // If both or neither have zero DST, treat the one with lower offset as standard:
- const bool nextIsDst = !nextTran.daylightTimeOffset == !tran.daylightTimeOffset
- ? tran.offsetFromUtc < nextTran.offsetFromUtc : nextTran.daylightTimeOffset;
- // If that agrees with hint > 0, our first guess is to use nextTran; else tran.
- const bool nextFirst = nextIsDst == (hint > 0) && nextStart != invalidMSecs();
- for (int i = 0; i < 2; i++) {
- /*
- On the first pass, the case we consider is what hint told us to expect
- (except when hint was -1 and didn't actually tell us what to expect),
- so it's likely right. We only get a second pass if the first failed,
- by which time the second case, that we're trying, is likely right.
- */
- if (nextFirst ? i == 0 : i) {
- Q_ASSERT(nextStart != invalidMSecs());
- if (nextStart <= nextTran.atMSecsSinceEpoch)
- return nextTran;
- } else {
- // If next is invalid, nextFirst is false, to route us here first:
- if (nextStart == invalidMSecs() || nextStart > tran.atMSecsSinceEpoch)
- return tran;
- }
- }
+ // If we know of no transition after it, the answer is easy:
+ const qint64 nextStart = nextTran.atMSecsSinceEpoch;
+ if (nextStart == invalidMSecs())
+ return dataToState(tran); // Last valid transition.
/*
- Neither is valid (e.g. in a spring-forward's gap) and
- nextTran.atMSecsSinceEpoch < nextStart <= tran.atMSecsSinceEpoch, so
- 0 < tran.atMSecsSinceEpoch - nextTran.atMSecsSinceEpoch
- = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000
+ ... and nextTran is either after or only slightly before. We're
+ going to interpret one as standard time, the other as DST
+ (although the transition might in fact be a change in standard
+ offset, or a change in DST offset, e.g. to/from double-DST).
+
+ Usually exactly one of those shall be relevant and we'll use it;
+ but if we're close to nextTran we may be in a transition, to be
+ settled according to resolve's rules.
*/
- int dstStep = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000;
- Q_ASSERT(dstStep > 0); // How else could we get here ?
- if (nextFirst) { // hint thought we needed nextTran, so use tran
- tran.atMSecsSinceEpoch -= dstStep;
- return tran;
+ // Work out the UTC value it would make sense to return if using nextTran:
+ nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
+
+ bool fallBack = false;
+ if (nextStart > nextTran.atMSecsSinceEpoch) {
+ // If both UTC values are before nextTran's offset applies, use tran:
+ if (nextStart > tran.atMSecsSinceEpoch)
+ return dataToState(tran);
+
+ Q_ASSERT(tran.offsetFromUtc < nextTran.offsetFromUtc);
+ // We're in a spring-forward.
+ } else if (nextStart <= tran.atMSecsSinceEpoch) {
+ // Both UTC values say we should be using nextTran:
+ return dataToState(nextTran);
+ } else {
+ Q_ASSERT(nextTran.offsetFromUtc < tran.offsetFromUtc);
+ fallBack = true; // We're in a fall-back.
+ }
+ // (forLocalMSecs - nextStart) / 1000 lies between the two offsets.
+
+ // Apply resolve:
+ // Determine whether FlipForReverseDst affects the outcome:
+ const bool flipped
+ = resolve.testFlag(QDateTimePrivate::FlipForReverseDst)
+ && (fallBack ? !tran.daylightTimeOffset && nextTran.daylightTimeOffset
+ : tran.daylightTimeOffset && !nextTran.daylightTimeOffset);
+
+ if (fallBack) {
+ if (resolve.testFlag(flipped
+ ? QDateTimePrivate::FoldUseBefore
+ : QDateTimePrivate::FoldUseAfter)) {
+ return dataToState(nextTran);
+ }
+ if (resolve.testFlag(flipped
+ ? QDateTimePrivate::FoldUseAfter
+ : QDateTimePrivate::FoldUseBefore)) {
+ return dataToState(tran);
+ }
+ } else {
+ /* Neither is valid (e.g. in a spring-forward's gap) and
+ nextTran.atMSecsSinceEpoch < nextStart <= tran.atMSecsSinceEpoch.
+ So swap their atMSecsSinceEpoch to give each a moment on the
+ side of the transition that it describes, then select the one
+ after or before according to the option set:
+ */
+ std::swap(tran.atMSecsSinceEpoch, nextTran.atMSecsSinceEpoch);
+ if (resolve.testFlag(flipped
+ ? QDateTimePrivate::GapUseBefore
+ : QDateTimePrivate::GapUseAfter))
+ return dataToState(nextTran);
+ if (resolve.testFlag(flipped
+ ? QDateTimePrivate::GapUseAfter
+ : QDateTimePrivate::GapUseBefore))
+ return dataToState(tran);
}
- nextTran.atMSecsSinceEpoch += dstStep;
- return nextTran;
+ // Reject
+ return {forLocalMSecs};
}
- // System has transitions but not for this zone.
- // Try falling back to offsetFromUtc
+ // Before first transition, or system has transitions but not for this zone.
+ // Try falling back to offsetFromUtc (works for before first transition, at least).
}
/* Bracket and refine to discover offset. */
qint64 utcEpochMSecs;
- int early = offsetFromUtc(recent);
- int late = offsetFromUtc(imminent);
- if (early == late) { // > 99% of the time
- utcEpochMSecs = forLocalMSecs - early * 1000;
+ // We don't have true data on DST-ness, so can't apply FlipForReverseDst.
+ int early = past.offsetFromUtc;
+ int late = future.offsetFromUtc;
+ if (early == late || late == invalidSeconds()) {
+ if (early == invalidSeconds()
+ || qSubOverflow(forLocalMSecs, early * qint64(1000), &utcEpochMSecs)) {
+ return {forLocalMSecs}; // Outside representable range
+ }
} else {
- // Close to a DST transition: early > late is near a fall-back,
- // early < late is near a spring-forward.
- const int offsetInDst = qMax(early, late);
- const int offsetInStd = qMin(early, late);
// Candidate values for utcEpochMSecs (if forLocalMSecs is valid):
- const qint64 forDst = forLocalMSecs - offsetInDst * 1000;
- const qint64 forStd = forLocalMSecs - offsetInStd * 1000;
- // Best guess at the answer:
- const qint64 hinted = hint > 0 ? forDst : forStd;
- if (offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd)) {
- utcEpochMSecs = hinted;
- } else if (hint <= 0 && offsetFromUtc(forDst) == offsetInDst) {
- utcEpochMSecs = forDst;
- } else if (hint > 0 && offsetFromUtc(forStd) == offsetInStd) {
- utcEpochMSecs = forStd;
+ const qint64 forEarly = forLocalMSecs - early * 1000;
+ const qint64 forLate = forLocalMSecs - late * 1000;
+ // If either of those doesn't have the offset we got it from, it's on
+ // the wrong side of the transition (and both may be, for a gap):
+ const bool earlyOk = offsetFromUtc(forEarly) == early;
+ const bool lateOk = offsetFromUtc(forLate) == late;
+
+ if (earlyOk) {
+ if (lateOk) {
+ Q_ASSERT(early > late);
+ // fall-back's repeated interval
+ if (resolve.testFlag(QDateTimePrivate::FoldUseBefore))
+ utcEpochMSecs = forEarly;
+ else if (resolve.testFlag(QDateTimePrivate::FoldUseAfter))
+ utcEpochMSecs = forLate;
+ else
+ return {forLocalMSecs};
+ } else {
+ // Before and clear of the transition:
+ utcEpochMSecs = forEarly;
+ }
+ } else if (lateOk) {
+ // After and clear of the transition:
+ utcEpochMSecs = forLate;
} else {
- // Invalid forLocalMSecs: in spring-forward gap.
- const int dstStep = daylightTimeOffset(early < late ? imminent : recent) * 1000;
- Q_ASSERT(dstStep); // There can't be a transition without it !
- utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep;
+ // forLate <= gap < forEarly
+ Q_ASSERT(late > early);
+ const int dstStep = (late - early) * 1000;
+ if (resolve.testFlag(QDateTimePrivate::GapUseBefore))
+ utcEpochMSecs = forEarly - dstStep;
+ else if (resolve.testFlag(QDateTimePrivate::GapUseAfter))
+ utcEpochMSecs = forLate + dstStep;
+ else
+ return {forLocalMSecs};
}
}
- return data(utcEpochMSecs);
+ return dataToState(data(utcEpochMSecs));
}
bool QTimeZonePrivate::hasTransitions() const
@@ -454,14 +488,14 @@ bool QTimeZonePrivate::hasTransitions() const
QTimeZonePrivate::Data QTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
{
- Q_UNUSED(afterMSecsSinceEpoch)
- return invalidData();
+ Q_UNUSED(afterMSecsSinceEpoch);
+ return {};
}
QTimeZonePrivate::Data QTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
- Q_UNUSED(beforeMSecsSinceEpoch)
- return invalidData();
+ Q_UNUSED(beforeMSecsSinceEpoch);
+ return {};
}
QTimeZonePrivate::DataList QTimeZonePrivate::transitions(qint64 fromMSecsSinceEpoch,
@@ -487,7 +521,8 @@ QByteArray QTimeZonePrivate::systemTimeZoneId() const
bool QTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const
{
- // Fall-back implementation, can be made faster in subclasses
+ // Fall-back implementation, can be made faster in subclasses.
+ // Backends that don't cache the available list SHOULD override this.
const QList<QByteArray> tzIds = availableTimeZoneIds();
return std::binary_search(tzIds.begin(), tzIds.end(), ianaId);
}
@@ -497,27 +532,31 @@ QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const
return QList<QByteArray>();
}
-QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
+static QList<QByteArray> selectAvailable(QList<QByteArray>&& desired, const QList<QByteArray>& all)
+{
+ std::sort(desired.begin(), desired.end());
+ const auto newEnd = std::unique(desired.begin(), desired.end());
+ const auto newSize = std::distance(desired.begin(), newEnd);
+ QList<QByteArray> result;
+ result.reserve(qMin(all.size(), newSize));
+ std::set_intersection(all.begin(), all.end(), desired.cbegin(),
+ std::next(desired.cbegin(), newSize), std::back_inserter(result));
+ return result;
+}
+
+QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Territory territory) const
{
// Default fall-back mode, use the zoneTable to find Region of know Zones
QList<QByteArray> regions;
// First get all Zones in the Zones table belonging to the Region
- for (int i = 0; i < zoneDataTableSize; ++i) {
- if (zoneData(i)->country == country)
- regions += ianaId(zoneData(i)).split(' ');
+ for (const ZoneData &data : zoneDataTable) {
+ if (data.territory == territory) {
+ for (auto l1 : data.ids())
+ regions << QByteArray(l1.data(), l1.size());
+ }
}
-
- std::sort(regions.begin(), regions.end());
- regions.erase(std::unique(regions.begin(), regions.end()), regions.end());
-
- // Then select just those that are available
- const QList<QByteArray> all = availableTimeZoneIds();
- QList<QByteArray> result;
- result.reserve(qMin(all.size(), regions.size()));
- std::set_intersection(all.begin(), all.end(), regions.cbegin(), regions.cend(),
- std::back_inserter(result));
- return result;
+ return selectAvailable(std::move(regions), availableTimeZoneIds());
}
QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const
@@ -525,27 +564,17 @@ QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) cons
// Default fall-back mode, use the zoneTable to find Offset of know Zones
QList<QByteArray> offsets;
// First get all Zones in the table using the Offset
- for (int i = 0; i < windowsDataTableSize; ++i) {
- const QWindowsData *winData = windowsData(i);
- if (winData->offsetFromUtc == offsetFromUtc) {
- for (int j = 0; j < zoneDataTableSize; ++j) {
- const QZoneData *data = zoneData(j);
- if (data->windowsIdKey == winData->windowsIdKey)
- offsets += ianaId(data).split(' ');
+ for (const WindowsData &winData : windowsDataTable) {
+ if (winData.offsetFromUtc == offsetFromUtc) {
+ for (auto data = zoneStartForWindowsId(winData.windowsIdKey);
+ data != std::end(zoneDataTable) && data->windowsIdKey == winData.windowsIdKey;
+ ++data) {
+ for (auto l1 : data->ids())
+ offsets << QByteArray(l1.data(), l1.size());
}
}
}
-
- std::sort(offsets.begin(), offsets.end());
- offsets.erase(std::unique(offsets.begin(), offsets.end()), offsets.end());
-
- // Then select just those that are available
- const QList<QByteArray> all = availableTimeZoneIds();
- QList<QByteArray> result;
- result.reserve(qMin(all.size(), offsets.size()));
- std::set_intersection(all.begin(), all.end(), offsets.cbegin(), offsets.cend(),
- std::back_inserter(result));
- return result;
+ return selectAvailable(std::move(offsets), availableTimeZoneIds());
}
#ifndef QT_NO_DATASTREAM
@@ -557,53 +586,41 @@ void QTimeZonePrivate::serialize(QDataStream &ds) const
// Static Utility Methods
-QTimeZonePrivate::Data QTimeZonePrivate::invalidData()
-{
- Data data;
- data.atMSecsSinceEpoch = invalidMSecs();
- data.offsetFromUtc = invalidSeconds();
- data.standardTimeOffset = invalidSeconds();
- data.daylightTimeOffset = invalidSeconds();
- return data;
-}
-
QTimeZone::OffsetData QTimeZonePrivate::invalidOffsetData()
{
- QTimeZone::OffsetData offsetData;
- offsetData.atUtc = QDateTime();
- offsetData.offsetFromUtc = invalidSeconds();
- offsetData.standardTimeOffset = invalidSeconds();
- offsetData.daylightTimeOffset = invalidSeconds();
- return offsetData;
+ return { QString(), QDateTime(),
+ invalidSeconds(), invalidSeconds(), invalidSeconds() };
}
QTimeZone::OffsetData QTimeZonePrivate::toOffsetData(const QTimeZonePrivate::Data &data)
{
- QTimeZone::OffsetData offsetData = invalidOffsetData();
- if (data.atMSecsSinceEpoch != invalidMSecs()) {
- offsetData.atUtc = QDateTime::fromMSecsSinceEpoch(data.atMSecsSinceEpoch, Qt::UTC);
- offsetData.offsetFromUtc = data.offsetFromUtc;
- offsetData.standardTimeOffset = data.standardTimeOffset;
- offsetData.daylightTimeOffset = data.daylightTimeOffset;
- offsetData.abbreviation = data.abbreviation;
- }
- return offsetData;
+ if (data.atMSecsSinceEpoch == invalidMSecs())
+ return invalidOffsetData();
+
+ return {
+ data.abbreviation,
+ QDateTime::fromMSecsSinceEpoch(data.atMSecsSinceEpoch, QTimeZone::UTC),
+ data.offsetFromUtc, data.standardTimeOffset, data.daylightTimeOffset };
}
// Is the format of the ID valid ?
bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
{
/*
- Main rules for defining TZ/IANA names as per ftp://ftp.iana.org/tz/code/Theory
+ Main rules for defining TZ/IANA names, as per
+ https://www.iana.org/time-zones/repository/theory.html, are:
1. Use only valid POSIX file name components
2. Within a file name component, use only ASCII letters, `.', `-' and `_'.
3. Do not use digits (except in a [+-]\d+ suffix, when used).
4. A file name component must not exceed 14 characters or start with `-'
+
However, the rules are really guidelines - a later one says
- Do not change established names if they only marginally violate the
above rules.
We may, therefore, need to be a bit slack in our check here, if we hit
- legitimate exceptions in real time-zone databases.
+ legitimate exceptions in real time-zone databases. In particular, ICU
+ includes some non-standard names with some components > 14 characters
+ long; so does Android, possibly deriving them from ICU.
In particular, aliases such as "Etc/GMT+7" and "SystemV/EST5EDT" are valid
so we need to accept digits, ':', and '+'; aliases typically have the form
@@ -630,8 +647,8 @@ bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
// Somewhat slack hand-rolled version:
const int MinSectionLength = 1;
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- // Android has its own naming of zones.
+#if defined(Q_OS_ANDROID) || QT_CONFIG(icu)
+ // Android has its own naming of zones. It may well come from ICU.
// "Canada/East-Saskatchewan" has a 17-character second component.
const int MaxSectionLength = 17;
#else
@@ -647,12 +664,12 @@ bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
} else if (ch == '-') {
if (sectionLength == 0)
return false; // violates (4)
- } else if (!(ch >= 'a' && ch <= 'z')
- && !(ch >= 'A' && ch <= 'Z')
+ } else if (!isAsciiLower(ch)
+ && !isAsciiUpper(ch)
&& !(ch == '_')
&& !(ch == '.')
// Should ideally check these only happen as an offset:
- && !(ch >= '0' && ch <= '9')
+ && !isAsciiDigit(ch)
&& !(ch == '+')
&& !(ch == ':')) {
return false; // violates (2)
@@ -663,43 +680,58 @@ bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
return true;
}
-QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc)
+QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc, QTimeZone::NameType mode)
{
- const int mins = offsetFromUtc / 60;
- return QString::fromUtf8("UTC%1%2:%3").arg(mins >= 0 ? QLatin1Char('+') : QLatin1Char('-'))
- .arg(qAbs(mins) / 60, 2, 10, QLatin1Char('0'))
- .arg(qAbs(mins) % 60, 2, 10, QLatin1Char('0'));
+ if (mode == QTimeZone::ShortName && !offsetFromUtc)
+ return utcQString();
+
+ char sign = '+';
+ if (offsetFromUtc < 0) {
+ sign = '-';
+ offsetFromUtc = -offsetFromUtc;
+ }
+ const int secs = offsetFromUtc % 60;
+ const int mins = (offsetFromUtc / 60) % 60;
+ const int hour = offsetFromUtc / 3600;
+ QString result = QString::asprintf("UTC%c%02d", sign, hour);
+ if (mode != QTimeZone::ShortName || secs || mins)
+ result += QString::asprintf(":%02d", mins);
+ if (mode == QTimeZone::LongName || secs)
+ result += QString::asprintf(":%02d", secs);
+ return result;
}
QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
{
- for (int i = 0; i < zoneDataTableSize; ++i) {
- const QZoneData *data = zoneData(i);
- if (ianaId(data).split(' ').contains(id))
- return toWindowsIdLiteral(data->windowsIdKey);
+ const auto idUtf8 = QUtf8StringView(id);
+
+ for (const ZoneData &data : zoneDataTable) {
+ for (auto l1 : data.ids()) {
+ if (l1 == idUtf8)
+ return toWindowsIdLiteral(data.windowsIdKey);
+ }
}
return QByteArray();
}
QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId)
{
- const quint16 windowsIdKey = toWindowsIdKey(windowsId);
- for (int i = 0; i < windowsDataTableSize; ++i) {
- const QWindowsData *data = windowsData(i);
- if (data->windowsIdKey == windowsIdKey)
- return ianaId(data);
+ const auto data = std::lower_bound(std::begin(windowsDataTable), std::end(windowsDataTable),
+ windowsId, earlierWindowsId);
+ if (data != std::end(windowsDataTable) && data->windowsId() == windowsId) {
+ QByteArrayView id = data->ianaId();
+ if (qsizetype cut = id.indexOf(' '); cut >= 0)
+ id = id.first(cut);
+ return id.toByteArray();
}
return QByteArray();
}
QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId,
- QLocale::Country country)
+ QLocale::Territory territory)
{
- const QList<QByteArray> list = windowsIdToIanaIds(windowsId, country);
- if (list.count() > 0)
- return list.first();
- else
- return QByteArray();
+ const QList<QByteArray> list = windowsIdToIanaIds(windowsId, territory);
+ return list.size() > 0 ? list.first() : QByteArray();
}
QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId)
@@ -707,10 +739,11 @@ QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windows
const quint16 windowsIdKey = toWindowsIdKey(windowsId);
QList<QByteArray> list;
- for (int i = 0; i < zoneDataTableSize; ++i) {
- const QZoneData *data = zoneData(i);
- if (data->windowsIdKey == windowsIdKey)
- list << ianaId(data).split(' ');
+ for (auto data = zoneStartForWindowsId(windowsIdKey);
+ data != std::end(zoneDataTable) && data->windowsIdKey == windowsIdKey;
+ ++data) {
+ for (auto l1 : data->ids())
+ list << QByteArray(l1.data(), l1.size());
}
// Return the full list in alpha order
@@ -719,17 +752,23 @@ QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windows
}
QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId,
- QLocale::Country country)
+ QLocale::Territory territory)
{
+ QList<QByteArray> list;
const quint16 windowsIdKey = toWindowsIdKey(windowsId);
- for (int i = 0; i < zoneDataTableSize; ++i) {
- const QZoneData *data = zoneData(i);
+ const qint16 land = static_cast<quint16>(territory);
+ for (auto data = zoneStartForWindowsId(windowsIdKey);
+ data != std::end(zoneDataTable) && data->windowsIdKey == windowsIdKey;
+ ++data) {
// Return the region matches in preference order
- if (data->windowsIdKey == windowsIdKey && data->country == (quint16) country)
- return ianaId(data).split(' ');
+ if (data->territory == land) {
+ for (auto l1 : data->ids())
+ list << QByteArray(l1.data(), l1.size());
+ break;
+ }
}
- return QList<QByteArray>();
+ return list;
}
// Define template for derived classes to reimplement so QSharedDataPointer clone() works correctly
@@ -738,34 +777,46 @@ template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone()
return d->clone();
}
+static bool isEntryInIanaList(QByteArrayView id, QByteArrayView ianaIds)
+{
+ qsizetype cut;
+ while ((cut = ianaIds.indexOf(' ')) >= 0) {
+ if (id == ianaIds.first(cut))
+ return true;
+ ianaIds = ianaIds.sliced(cut + 1);
+ }
+ return id == ianaIds;
+}
+
/*
- UTC Offset implementation, used when QT_NO_SYSTEMLOCALE set and ICU is not being used,
- or for QDateTimes with a Qt:Spec of Qt::OffsetFromUtc.
+ UTC Offset backend.
+
+ Always present, based on UTC-offset zones.
+ Complements platform-specific backends.
+ Equivalent to Qt::OffsetFromUtc lightweight time representations.
*/
// Create default UTC time zone
QUtcTimeZonePrivate::QUtcTimeZonePrivate()
{
const QString name = utcQString();
- init(utcQByteArray(), 0, name, name, QLocale::AnyCountry, name);
+ init(utcQByteArray(), 0, name, name, QLocale::AnyTerritory, name);
}
// Create a named UTC time zone
QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id)
{
// Look for the name in the UTC list, if found set the values
- for (int i = 0; i < utcDataTableSize; ++i) {
- const QUtcData *data = utcData(i);
- const QByteArray uid = utcId(data);
- if (uid == id) {
+ for (const UtcData &data : utcDataTable) {
+ if (isEntryInIanaList(id, data.id())) {
QString name = QString::fromUtf8(id);
- init(id, data->offsetFromUtc, name, name, QLocale::AnyCountry, name);
+ init(id, data.offsetFromUtc, name, name, QLocale::AnyTerritory, name);
break;
}
}
}
-qint64 QUtcTimeZonePrivate::offsetFromUtcString(const QByteArray &id)
+qint64 QUtcTimeZonePrivate::offsetFromUtcString(QByteArrayView id)
{
// Convert reasonable UTC[+-]\d+(:\d+){,2} to offset in seconds.
// Assumption: id has already been tried as a CLDR UTC offset ID (notably
@@ -777,52 +828,61 @@ qint64 QUtcTimeZonePrivate::offsetFromUtcString(const QByteArray &id)
return invalidSeconds(); // No sign
const int sign = signChar == '-' ? -1 : 1;
- const auto offsets = id.mid(4).split(':');
- if (offsets.isEmpty() || offsets.size() > 3)
- return invalidSeconds(); // No numbers, or too many.
-
qint32 seconds = 0;
int prior = 0; // Number of fields parsed thus far
- for (const auto &offset : offsets) {
+ for (auto offset : QLatin1StringView(id.mid(4)).tokenize(':'_L1)) {
bool ok = false;
unsigned short field = offset.toUShort(&ok);
// Bound hour above at 24, minutes and seconds at 60:
if (!ok || field >= (prior ? 60 : 24))
return invalidSeconds();
seconds = seconds * 60 + field;
- ++prior;
+ if (++prior > 3)
+ return invalidSeconds(); // Too many numbers
}
+
+ if (!prior)
+ return invalidSeconds(); // No numbers
+
while (prior++ < 3)
seconds *= 60;
return seconds * sign;
}
-// Create offset from UTC
+// Create from UTC offset:
QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
{
- QString utcId;
-
- if (offsetSeconds == 0)
- utcId = utcQString();
- else
- utcId = isoOffsetFormat(offsetSeconds);
-
- init(utcId.toUtf8(), offsetSeconds, utcId, utcId, QLocale::AnyCountry, utcId);
+ QString name;
+ QByteArray id;
+ // If there's an IANA ID for this offset, use it:
+ const auto data = std::lower_bound(std::begin(utcDataTable), std::end(utcDataTable),
+ offsetSeconds, atLowerUtcOffset);
+ if (data != std::end(utcDataTable) && data->offsetFromUtc == offsetSeconds) {
+ QByteArrayView ianaId = data->id();
+ qsizetype cut = ianaId.indexOf(' ');
+ id = (cut < 0 ? ianaId : ianaId.first(cut)).toByteArray();
+ name = QString::fromUtf8(id);
+ Q_ASSERT(!name.isEmpty());
+ } else { // Fall back to a UTC-offset name:
+ name = isoOffsetFormat(offsetSeconds, QTimeZone::ShortName);
+ id = name.toUtf8();
+ }
+ init(id, offsetSeconds, name, name, QLocale::AnyTerritory, name);
}
QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds,
const QString &name, const QString &abbreviation,
- QLocale::Country country, const QString &comment)
+ QLocale::Territory territory, const QString &comment)
{
- init(zoneId, offsetSeconds, name, abbreviation, country, comment);
+ init(zoneId, offsetSeconds, name, abbreviation, territory, comment);
}
QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other)
: QTimeZonePrivate(other), m_name(other.m_name),
m_abbreviation(other.m_abbreviation),
m_comment(other.m_comment),
- m_country(other.m_country),
+ m_territory(other.m_territory),
m_offsetFromUtc(other.m_offsetFromUtc)
{
}
@@ -852,20 +912,20 @@ void QUtcTimeZonePrivate::init(const QByteArray &zoneId)
}
void QUtcTimeZonePrivate::init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
- const QString &abbreviation, QLocale::Country country,
+ const QString &abbreviation, QLocale::Territory territory,
const QString &comment)
{
m_id = zoneId;
m_offsetFromUtc = offsetSeconds;
m_name = name;
m_abbreviation = abbreviation;
- m_country = country;
+ m_territory = territory;
m_comment = comment;
}
-QLocale::Country QUtcTimeZonePrivate::country() const
+QLocale::Territory QUtcTimeZonePrivate::territory() const
{
- return m_country;
+ return m_territory;
}
QString QUtcTimeZonePrivate::comment() const
@@ -877,8 +937,8 @@ QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- Q_UNUSED(timeType)
- Q_UNUSED(locale)
+ Q_UNUSED(timeType);
+ Q_UNUSED(locale);
if (nameType == QTimeZone::ShortName)
return m_abbreviation;
else if (nameType == QTimeZone::OffsetName)
@@ -888,19 +948,19 @@ QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QString QUtcTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
+ Q_UNUSED(atMSecsSinceEpoch);
return m_abbreviation;
}
qint32 QUtcTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
+ Q_UNUSED(atMSecsSinceEpoch);
return m_offsetFromUtc;
}
qint32 QUtcTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
{
- Q_UNUSED(atMSecsSinceEpoch)
+ Q_UNUSED(atMSecsSinceEpoch);
return 0;
}
@@ -912,12 +972,13 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
{
// Only the zone IDs supplied by CLDR and recognized by constructor.
- for (int i = 0; i < utcDataTableSize; ++i) {
- const QUtcData *data = utcData(i);
- if (utcId(data) == ianaId)
+ for (const UtcData &data : utcDataTable) {
+ if (isEntryInIanaList(ianaId, data.id()))
return true;
}
- // But see offsetFromUtcString(), which lets us accept some "unavailable" IDs.
+ // Callers may want to || offsetFromUtcString(ianaId) != invalidSeconds(),
+ // but those are technically not IANA IDs and the custom QTimeZone
+ // constructor needs the return here to reflect that.
return false;
}
@@ -925,19 +986,26 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const
{
// Only the zone IDs supplied by CLDR and recognized by constructor.
QList<QByteArray> result;
- result.reserve(utcDataTableSize);
- for (int i = 0; i < utcDataTableSize; ++i)
- result << utcId(utcData(i));
+ result.reserve(std::size(utcDataTable));
+ for (const UtcData &data : utcDataTable) {
+ QByteArrayView id = data.id();
+ qsizetype cut;
+ while ((cut = id.indexOf(' ')) >= 0) {
+ result << id.first(cut).toByteArray();
+ id = id.sliced(cut + 1);
+ }
+ result << id.toByteArray();
+ }
// Not guaranteed to be sorted, so sort:
std::sort(result.begin(), result.end());
// ### assuming no duplicates
return result;
}
-QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
+QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Territory country) const
{
- // If AnyCountry then is request for all non-region offset codes
- if (country == QLocale::AnyCountry)
+ // If AnyTerritory then is request for all non-region offset codes
+ if (country == QLocale::AnyTerritory)
return availableTimeZoneIds();
return QList<QByteArray>();
}
@@ -947,11 +1015,23 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds
// Only if it's present in CLDR. (May get more than one ID: UTC, UTC+00:00
// and UTC-00:00 all have the same offset.)
QList<QByteArray> result;
- for (int i = 0; i < utcDataTableSize; ++i) {
- const QUtcData *data = utcData(i);
- if (data->offsetFromUtc == offsetSeconds)
- result << utcId(data);
+ const auto data = std::lower_bound(std::begin(utcDataTable), std::end(utcDataTable),
+ offsetSeconds, atLowerUtcOffset);
+ if (data != std::end(utcDataTable) && data->offsetFromUtc == offsetSeconds) {
+ QByteArrayView id = data->id();
+ qsizetype cut;
+ while ((cut = id.indexOf(' ')) >= 0) {
+ result << id.first(cut).toByteArray();
+ id = id.sliced(cut + 1);
+ }
+ result << id.toByteArray();
}
+ // CLDR only has round multiples of a quarter hour, and only some of
+ // those. For anything else, throw in the ID we would use for this offset
+ // (if we'd accept that ID).
+ QByteArray isoName = isoOffsetFormat(offsetSeconds, QTimeZone::ShortName).toUtf8();
+ if (offsetFromUtcString(isoName) == qint64(offsetSeconds) && !result.contains(isoName))
+ result << isoName;
// Not guaranteed to be sorted, so sort:
std::sort(result.begin(), result.end());
// ### assuming no duplicates
@@ -962,7 +1042,7 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds
void QUtcTimeZonePrivate::serialize(QDataStream &ds) const
{
ds << QStringLiteral("OffsetFromUtc") << QString::fromUtf8(m_id) << m_offsetFromUtc << m_name
- << m_abbreviation << (qint32) m_country << m_comment;
+ << m_abbreviation << static_cast<qint32>(m_territory) << m_comment;
}
#endif // QT_NO_DATASTREAM
diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp
index ba87cf79fe..47fc68b1ac 100644
--- a/src/corelib/time/qtimezoneprivate_android.cpp
+++ b/src/corelib/time/qtimezoneprivate_android.cpp
@@ -1,53 +1,29 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2014 Drew Parsons <dparsons@emerall.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include <QtCore/QSet>
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
+#include <QtCore/QJniEnvironment>
+#include <QtCore/QSet>
+#include <QtCore/qjnitypes.h>
+
QT_BEGIN_NAMESPACE
+Q_DECLARE_JNI_CLASS(TimeZone, "java/util/TimeZone");
+Q_DECLARE_JNI_CLASS(Locale, "java/util/Locale");
+Q_DECLARE_JNI_CLASS(Date, "java/util/Date");
+Q_DECLARE_JNI_TYPE(StringArray, "[Ljava/lang/String;")
+
/*
Private
Android implementation
+
+ Note that a QJniObject manages a global reference, so it serves as an
+ owning smart-pointer, ensuring an object doesn't get garbage-collected
+ before we're done with it.
*/
// Create the system default time zone
@@ -55,9 +31,10 @@ QAndroidTimeZonePrivate::QAndroidTimeZonePrivate()
: QTimeZonePrivate()
{
// Keep in sync with systemTimeZoneId():
- androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
- "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
- m_id = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;").toString().toUtf8();
+ androidTimeZone = QJniObject::callStaticMethod<QtJniTypes::TimeZone>(
+ QtJniTypes::Traits<QtJniTypes::TimeZone>::className(), "getDefault");
+ const QJniObject id = androidTimeZone.callMethod<jstring>("getID");
+ m_id = id.toString().toUtf8();
}
// Create a named time zone
@@ -78,37 +55,28 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
{
}
-static QJNIObjectPrivate getDisplayName(QJNIObjectPrivate zone, jint style, jboolean dst,
+static QString getDisplayName(QJniObject zone, jint style, jboolean dst,
const QLocale &locale)
{
- QJNIObjectPrivate jlanguage
- = QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language()));
- QJNIObjectPrivate jcountry
- = QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country()));
- QJNIObjectPrivate
- jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script()));
- QJNIObjectPrivate jlocale("java.util.Locale",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
- static_cast<jstring>(jlanguage.object()),
- static_cast<jstring>(jcountry.object()),
- static_cast<jstring>(jvariant.object()));
-
- return zone.callObjectMethod("getDisplayName",
- "(ZILjava/util/Locale;)Ljava/lang/String;",
- dst, style, jlocale.object());
+ QJniObject jbcpTag = QJniObject::fromString(locale.bcp47Name());
+ QJniObject jlocale = QJniObject::callStaticMethod<QtJniTypes::Locale>(
+ QtJniTypes::Traits<QtJniTypes::Locale>::className(), "forLanguageTag",
+ jbcpTag.object<jstring>());
+
+ return zone.callMethod<jstring>("getDisplayName", dst, style,
+ jlocale.object<QtJniTypes::Locale>()).toString();
}
void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
{
const QString iana = QString::fromUtf8(ianaId);
- androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
- "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;",
- static_cast<jstring>(QJNIObjectPrivate::fromString(iana).object()));
+ androidTimeZone = QJniObject::callStaticMethod<QtJniTypes::TimeZone>(
+ QtJniTypes::Traits<QtJniTypes::TimeZone>::className(), "getTimeZone",
+ QJniObject::fromString(iana).object<jstring>());
// The ID or display name of the zone we've got, if it looks like what we asked for:
- const auto match = [iana](const QJNIObjectPrivate &jname) -> QByteArray {
- const QString name = jname.toString();
- if (iana.compare(name, Qt::CaseInsensitive))
+ const auto match = [iana](const QString &name) -> QByteArray {
+ if (iana.compare(name, Qt::CaseInsensitive) == 0)
return name.toUtf8();
return QByteArray();
@@ -118,7 +86,7 @@ void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
// recognize the name; so check for whether ianaId is a recognized name of
// the zone object we got and ignore the zone if not.
// Try checking ianaId against getID(), getDisplayName():
- m_id = match(androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"));
+ m_id = match(androidTimeZone.callMethod<jstring>("getID").toString());
for (int style = 1; m_id.isEmpty() && style >= 0; --style) {
for (int dst = 1; m_id.isEmpty() && dst >= 0; --dst) {
for (int pick = 2; m_id.isEmpty() && pick >= 0; --pick) {
@@ -147,7 +115,7 @@ QString QAndroidTimeZonePrivate::displayName(QTimeZone::TimeType timeType, QTime
// treat all NameTypes as java TimeZone style LONG (value 1), except of course QTimeZone::ShortName which is style SHORT (value 0);
jint style = (nameType == QTimeZone::ShortName ? 0 : 1);
- name = getDisplayName(androidTimeZone, style, daylightTime, locale).toString();
+ name = getDisplayName(androidTimeZone, style, daylightTime, locale);
}
return name;
@@ -165,11 +133,13 @@ int QAndroidTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
{
// offsetFromUtc( ) is invoked when androidTimeZone may not yet be set at startup,
// so a validity test is needed here
- if ( androidTimeZone.isValid() )
+ if ( androidTimeZone.isValid() ) {
// the java method getOffset() returns milliseconds, but QTimeZone returns seconds
- return androidTimeZone.callMethod<jint>( "getOffset", "(J)I", static_cast<jlong>(atMSecsSinceEpoch) ) / 1000;
- else
+ return androidTimeZone.callMethod<jint>(
+ "getOffset", static_cast<jlong>(atMSecsSinceEpoch) ) / 1000;
+ } else {
return 0;
+ }
}
int QAndroidTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
@@ -191,7 +161,7 @@ int QAndroidTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
bool QAndroidTimeZonePrivate::hasDaylightTime() const
{
if ( androidTimeZone.isValid() )
- /* note: the Java function only tests for future DST transtions, not past */
+ /* note: the Java function only tests for future DST transitions, not past */
return androidTimeZone.callMethod<jboolean>("useDaylightTime" );
else
return false;
@@ -200,8 +170,10 @@ bool QAndroidTimeZonePrivate::hasDaylightTime() const
bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
{
if ( androidTimeZone.isValid() ) {
- QJNIObjectPrivate jDate( "java/util/Date", "(J)V", static_cast<jlong>(atMSecsSinceEpoch) );
- return androidTimeZone.callMethod<jboolean>("inDaylightTime", "(Ljava/util/Date;)Z", jDate.object() );
+ QJniObject jDate = QJniObject::construct<QtJniTypes::Date>(
+ static_cast<jlong>(atMSecsSinceEpoch));
+ return androidTimeZone.callMethod<jboolean>("inDaylightTime",
+ jDate.object<QtJniTypes::Date>());
}
else
return false;
@@ -210,62 +182,48 @@ bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
QTimeZonePrivate::Data QAndroidTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
if (androidTimeZone.isValid()) {
- Data data;
- data.atMSecsSinceEpoch = forMSecsSinceEpoch;
- data.standardTimeOffset = standardTimeOffset(forMSecsSinceEpoch);
- data.offsetFromUtc = offsetFromUtc(forMSecsSinceEpoch);
- data.daylightTimeOffset = data.offsetFromUtc - data.standardTimeOffset;
- data.abbreviation = abbreviation(forMSecsSinceEpoch);
- return data;
- } else {
- return invalidData();
+ return Data(abbreviation(forMSecsSinceEpoch), forMSecsSinceEpoch,
+ offsetFromUtc(forMSecsSinceEpoch),
+ standardTimeOffset(forMSecsSinceEpoch));
}
+ return {};
}
-bool QAndroidTimeZonePrivate::hasTransitions() const
-{
- // java.util.TimeZone does not directly provide transitions
- return false;
-}
-
-QTimeZonePrivate::Data QAndroidTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
-{
- // transitions not available on Android, so return an invalid data object
- Q_UNUSED( afterMSecsSinceEpoch );
- return invalidData();
-}
+// java.util.TimeZone does not directly provide transitions,
+// so don't over-ride QTZP's base implementation of transition methods.
-QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
+QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
{
- // transitions not available on Android, so return an invalid data object
- Q_UNUSED( beforeMSecsSinceEpoch );
- return invalidData();
+ // Keep in sync with default constructor:
+ QJniObject androidSystemTimeZone = QJniObject::callStaticMethod<QtJniTypes::TimeZone>(
+ QtJniTypes::Traits<QtJniTypes::TimeZone>::className(), "getDefault");
+ const QJniObject id = androidSystemTimeZone.callMethod<jstring>("getID");
+ return id.toString().toUtf8();
}
-QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
+bool QAndroidTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
{
- // Keep in sync with default constructor:
- QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
- "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
- return androidSystemTimeZone.callObjectMethod<jstring>("getID").toString().toUtf8();
+ QAndroidTimeZonePrivate probe(ianaId);
+ return probe.isValid();
}
QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const
{
QList<QByteArray> availableTimeZoneIdList;
- QJNIObjectPrivate androidAvailableIdList = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getAvailableIDs", "()[Ljava/lang/String;");
+ QJniObject androidAvailableIdList = QJniObject::callStaticMethod<QtJniTypes::StringArray>(
+ QtJniTypes::Traits<QtJniTypes::TimeZone>::className(), "getAvailableIDs");
- QJNIEnvironmentPrivate jniEnv;
- int androidTZcount = jniEnv->GetArrayLength( static_cast<jarray>(androidAvailableIdList.object()) );
+ QJniEnvironment jniEnv;
+ int androidTZcount = jniEnv->GetArrayLength(androidAvailableIdList.object<jarray>());
- // need separate jobject and QAndroidJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject
+ // need separate jobject and QJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject
// (or else the JNI reference table fills after 512 entries from GetObjectArrayElement)
jobject androidTZobject;
- QJNIObjectPrivate androidTZ;
- for (int i=0; i<androidTZcount; i++ ) {
- androidTZobject = jniEnv->GetObjectArrayElement( static_cast<jobjectArray>( androidAvailableIdList.object() ), i );
+ QJniObject androidTZ;
+ for (int i = 0; i < androidTZcount; i++) {
+ androidTZobject = jniEnv->GetObjectArrayElement(androidAvailableIdList.object<jobjectArray>(), i);
androidTZ = androidTZobject;
- availableTimeZoneIdList.append( androidTZ.toString().toUtf8() );
+ availableTimeZoneIdList.append(androidTZ.toString().toUtf8());
jniEnv->DeleteLocalRef(androidTZobject);
}
diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h
index 6d2bbc83c1..5174f06a0d 100644
--- a/src/corelib/time/qtimezoneprivate_data_p.h
+++ b/src/corelib/time/qtimezoneprivate_data_p.h
@@ -1,43 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: Unicode-3.0
#ifndef QTIMEZONEPRIVATE_DATA_P_H
#define QTIMEZONEPRIVATE_DATA_P_H
@@ -54,69 +17,68 @@
//
#include <QtCore/private/qglobal_p.h>
+#include "qbytearrayview.h"
+#include "qstring.h"
+QT_REQUIRE_CONFIG(timezone);
QT_BEGIN_NAMESPACE
+namespace QtTimeZoneCldr {
/*
- Windows Zone ID support, included in default base class build so can be used on all platforms,
- e.g. an app running on Linux may need to communicate with a Windows Outlook server. These
- tables can also be used to look-up Region Codes and UTC Offsets on platforms that don't directly
- support them., e.g. Mac does not support availableTimeZones() filtering by region or offset.
+ Recognized UTC-offset zones and CLDR-derived data on Windows IDs.
+
+ The UTC-offset zone table is provided for generic UTC±HH:mm format time
+ zones. The UTC backend can support arbitrary offsets in seconds, but only
+ advertises a limited repertoire of offsets as "available" in the normal
+ sense.
- Another data table is provided for generic UTC+00:00 format time zones to be used as a
- fall-back if no system time zones are available (QT_NO_SYSTEMLOCALE is set) or for QDateTimes
- with a QT:Spec of OffsetFromUTC
+ Windows Zone ID support is included in the default base class, QTZP, so can
+ be used on all platforms, since an app running on Linux may need to
+ communicate with a Windows Outlook server. These tables can also be used to
+ look up Region Codes and UTC Offsets on platforms whose backends don't
+ directly support them. For example, Darwin does not support
+ availableTimeZones() filtering by region or offset. This table is
+ auto-generated from the CLDR supplemental/windowsZones.xml data file.
- These tables are automatically adapted from the CLDR supplemental/windowsZones.xml data file
- using a script in qtbase/util/locale_database. Please do not edit this data directly. In the
- future if ICU is made a hard dependency then the ICU resource can be used directly and this
- table removed
+ Please do not edit this data directly. See the generated section for details
+ of its last update and how to update it.
*/
-struct QZoneData {
- quint16 windowsIdKey; // Windows ID Key
- quint16 country; // Country of IANA ID's, AnyCountry means No Country
- quint16 ianaIdIndex; // All IANA ID's for the Windows ID and Country, space separated
+struct ZoneData
+{
+ // Keys (table is sorted in Windows ID, then on territory enum value):
+ quint16 windowsIdKey; // Windows ID sequence number
+ quint16 territory; // QLocale::Territory, AnyTerritory means No Territory
+ // Values for this Windows zone and territory:
+ quint16 ianaIdIndex; // Index in ianaIdData of space-joined IANA IDs
+ constexpr QLatin1StringView id() const; // Space-joined list of IANA IDs
+ constexpr auto ids() const { return id().tokenize(u' '); } // Iterate IANA IDs
};
-struct QWindowsData {
- quint16 windowsIdKey; // Windows ID Key
- quint16 windowsIdIndex; // Windows ID Literal
- quint16 ianaIdIndex; // Default IANA ID for the Windows ID
+struct WindowsData
+{
+ // Table is sorted on key and this puts the windowsId()s in ascending order.
+ quint16 windowsIdKey; // Windows ID sequence number
+ quint16 windowsIdIndex; // Index of Windows ID in windowsIdData
+ // Values for this Windows zone:
+ quint16 ianaIdIndex; // Index in ianaIdData of space-joined IANA IDs
qint32 offsetFromUtc; // Standard Time Offset from UTC, used for quick look-ups
+ constexpr QByteArrayView windowsId() const;
+ constexpr QByteArrayView ianaId() const; // Space-joined list of IANA IDs
};
-struct QUtcData {
- quint16 ianaIdIndex; // IANA ID's
- qint32 offsetFromUtc; // Offset form UTC is seconds
+struct UtcData
+{
+ quint16 ianaIdIndex; // Index in ianaIdData of space-joined IANA IDs
+ qint32 offsetFromUtc; // Offset form UTC in seconds
+ constexpr QByteArrayView id() const; // Space-joined list of IANA IDs
};
-/*
- COPYRIGHT AND PERMISSION NOTICE
-
- Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under
- the Terms of Use in http://www.unicode.org/copyright.html.
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of the Unicode data files and any associated documentation (the "Data
- Files") or Unicode software and any associated documentation (the "Software")
- to deal in the Data Files or Software without restriction, including without
- limitation the rights to use, copy, modify, merge, publish, distribute, and/or
- sell copies of the Data Files or Software, and to permit persons to whom the
- Data Files or Software are furnished to do so, provided that (a) the above
- copyright notice(s) and this permission notice appear with all copies of the
- Data Files or Software, (b) both the above copyright notice(s) and this
- permission notice appear in associated documentation, and (c) there is clear
- notice in each modified Data File or in the Software as well as in the
- documentation associated with the Data File(s) or Software that the data or
- software has been modified.
-*/
-
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-02-28 from the
- Common Locale Data Repository v36 file supplemental/windowsZones.xml
+ This part of the file was generated on 2024-01-29 from the
+ Common Locale Data Repository v43 file supplemental/windowsZones.xml
http://www.unicode.org/cldr/
@@ -124,1139 +86,1292 @@ struct QUtcData {
edited) CLDR data; see qtbase/util/locale_database/.
*/
-// Windows ID Key, Country Enum, IANA ID Index
-static const QZoneData zoneDataTable[] = {
+// Windows ID Key, Territory Enum, IANA ID Index
+static constexpr ZoneData zoneDataTable[] = {
{ 1, 1, 0 }, // Afghanistan Standard Time / Afghanistan
- { 2, 225, 11 }, // Alaskan Standard Time / United States
- { 3, 225, 106 }, // Aleutian Standard Time / United States
- { 4, 178, 119 }, // Altai Standard Time / Russia
- { 5, 17, 132 }, // Arab Standard Time / Bahrain
- { 5, 115, 145 }, // Arab Standard Time / Kuwait
- { 5, 175, 157 }, // Arab Standard Time / Qatar
- { 5, 186, 168 }, // Arab Standard Time / Saudi Arabia
- { 5, 237, 180 }, // Arab Standard Time / Yemen
- { 6, 0, 190 }, // Arabian Standard Time / AnyCountry
- { 6, 162, 200 }, // Arabian Standard Time / Oman
- { 6, 223, 212 }, // Arabian Standard Time / United Arab Emirates
- { 7, 103, 223 }, // Arabic Standard Time / Iraq
- { 8, 10, 236 }, // Argentina Standard Time / Argentina
- { 9, 178, 509 }, // Astrakhan Standard Time / Russia
- { 10, 24, 543 }, // Atlantic Standard Time / Bermuda
- { 10, 38, 560 }, // Atlantic Standard Time / Canada
- { 10, 86, 628 }, // Atlantic Standard Time / Greenland
- { 11, 13, 642 }, // AUS Central Standard Time / Australia
- { 12, 13, 659 }, // Aus Central W. Standard Time / Australia
- { 13, 13, 675 }, // AUS Eastern Standard Time / Australia
- { 14, 15, 712 }, // Azerbaijan Standard Time / Azerbaijan
- { 15, 86, 722 }, // Azores Standard Time / Greenland
- { 15, 173, 743 }, // Azores Standard Time / Portugal
- { 16, 30, 759 }, // Bahia Standard Time / Brazil
- { 17, 18, 773 }, // Bangladesh Standard Time / Bangladesh
- { 17, 25, 784 }, // Bangladesh Standard Time / Bhutan
- { 18, 20, 797 }, // Belarus Standard Time / Belarus
- { 19, 167, 810 }, // Bougainville Standard Time / Papua New Guinea
- { 20, 38, 831 }, // Canada Central Standard Time / Canada
- { 21, 0, 868 }, // Cape Verde Standard Time / AnyCountry
- { 21, 39, 878 }, // Cape Verde Standard Time / Cape Verde
- { 22, 11, 898 }, // Caucasus Standard Time / Armenia
- { 23, 13, 911 }, // Cen. Australia Standard Time / Australia
- { 24, 0, 952 }, // Central America Standard Time / AnyCountry
- { 24, 22, 962 }, // Central America Standard Time / Belize
- { 24, 52, 977 }, // Central America Standard Time / Costa Rica
- { 24, 63, 996 }, // Central America Standard Time / Ecuador
- { 24, 65, 1014 }, // Central America Standard Time / El Salvador
- { 24, 90, 1034 }, // Central America Standard Time / Guatemala
- { 24, 96, 1052 }, // Central America Standard Time / Honduras
- { 24, 155, 1072 }, // Central America Standard Time / Nicaragua
- { 25, 0, 1088 }, // Central Asia Standard Time / AnyCountry
- { 25, 8, 1098 }, // Central Asia Standard Time / Antarctica
- { 25, 31, 1116 }, // Central Asia Standard Time / British Indian Ocean Territory
- { 25, 44, 1130 }, // Central Asia Standard Time / China
- { 25, 110, 1142 }, // Central Asia Standard Time / Kazakhstan
- { 25, 116, 1168 }, // Central Asia Standard Time / Kyrgyzstan
- { 26, 30, 1181 }, // Central Brazilian Standard Time / Brazil
- { 27, 2, 1217 }, // Central Europe Standard Time / Albania
- { 27, 57, 1231 }, // Central Europe Standard Time / Czech Republic
- { 27, 98, 1245 }, // Central Europe Standard Time / Hungary
- { 27, 191, 1261 }, // Central Europe Standard Time / Slovakia
- { 27, 192, 1279 }, // Central Europe Standard Time / Slovenia
- { 27, 242, 1296 }, // Central Europe Standard Time / Montenegro
- { 27, 243, 1313 }, // Central Europe Standard Time / Serbia
- { 28, 27, 1329 }, // Central European Standard Time / Bosnia And Herzegowina
- { 28, 54, 1345 }, // Central European Standard Time / Croatia
- { 28, 127, 1359 }, // Central European Standard Time / Macedonia
- { 28, 172, 1373 }, // Central European Standard Time / Poland
- { 29, 0, 1387 }, // Central Pacific Standard Time / AnyCountry
- { 29, 13, 1398 }, // Central Pacific Standard Time / Australia
- { 29, 140, 1419 }, // Central Pacific Standard Time / Micronesia
- { 29, 153, 1449 }, // Central Pacific Standard Time / New Caledonia
- { 29, 193, 1464 }, // Central Pacific Standard Time / Solomon Islands
- { 29, 229, 1484 }, // Central Pacific Standard Time / Vanuatu
- { 30, 139, 1498 }, // Central Standard Time (Mexico) / Mexico
- { 31, 0, 1574 }, // Central Standard Time / AnyCountry
- { 31, 38, 1582 }, // Central Standard Time / Canada
- { 31, 139, 1657 }, // Central Standard Time / Mexico
- { 31, 225, 1675 }, // Central Standard Time / United States
- { 32, 44, 1843 }, // China Standard Time / China
- { 32, 97, 1857 }, // China Standard Time / Hong Kong
- { 32, 126, 1872 }, // China Standard Time / Macau
- { 33, 154, 1883 }, // Chatham Islands Standard Time / New Zealand
- { 34, 55, 1899 }, // Cuba Standard Time / Cuba
- { 35, 0, 1914 }, // Dateline Standard Time / AnyCountry
- { 36, 0, 1925 }, // E. Africa Standard Time / AnyCountry
- { 36, 8, 1935 }, // E. Africa Standard Time / Antarctica
- { 36, 48, 1952 }, // E. Africa Standard Time / Comoros
- { 36, 59, 1966 }, // E. Africa Standard Time / Djibouti
- { 36, 67, 1982 }, // E. Africa Standard Time / Eritrea
- { 36, 69, 1996 }, // E. Africa Standard Time / Ethiopia
- { 36, 111, 2015 }, // E. Africa Standard Time / Kenya
- { 36, 128, 2030 }, // E. Africa Standard Time / Madagascar
- { 36, 138, 2050 }, // E. Africa Standard Time / Mayotte
- { 36, 194, 2065 }, // E. Africa Standard Time / Somalia
- { 36, 210, 2082 }, // E. Africa Standard Time / Tanzania
- { 36, 221, 2103 }, // E. Africa Standard Time / Uganda
- { 36, 254, 2118 }, // E. Africa Standard Time / South Sudan
- { 37, 13, 2130 }, // E. Australia Standard Time / Australia
- { 38, 141, 2168 }, // E. Europe Standard Time / Moldova
- { 39, 30, 2184 }, // E. South America Standard Time / Brazil
- { 40, 43, 2202 }, // Easter Island Standard Time / Chile
- { 41, 0, 2217 }, // Eastern Standard Time / AnyCountry
- { 41, 16, 2225 }, // Eastern Standard Time / Bahamas
- { 41, 38, 2240 }, // Eastern Standard Time / Canada
- { 41, 225, 2345 }, // Eastern Standard Time / United States
- { 42, 139, 2502 }, // Eastern Standard Time (Mexico) / Mexico
- { 43, 64, 2517 }, // Egypt Standard Time / Egypt
- { 44, 178, 2530 }, // Ekaterinburg Standard Time / Russia
- { 45, 72, 2549 }, // Fiji Standard Time / Fiji
- { 46, 33, 2562 }, // FLE Standard Time / Bulgaria
- { 46, 68, 2575 }, // FLE Standard Time / Estonia
- { 46, 73, 2590 }, // FLE Standard Time / Finland
- { 46, 118, 2606 }, // FLE Standard Time / Latvia
- { 46, 124, 2618 }, // FLE Standard Time / Lithuania
- { 46, 222, 2633 }, // FLE Standard Time / Ukraine
- { 46, 248, 2679 }, // FLE Standard Time / Aland Islands
- { 47, 81, 2696 }, // Georgian Standard Time / Georgia
- { 48, 71, 2709 }, // GMT Standard Time / Faroe Islands
- { 48, 75, 2725 }, // GMT Standard Time / Guernsey
- { 48, 104, 2741 }, // GMT Standard Time / Ireland
- { 48, 173, 2755 }, // GMT Standard Time / Portugal
- { 48, 197, 2786 }, // GMT Standard Time / Spain
- { 48, 224, 2802 }, // GMT Standard Time / United Kingdom
- { 48, 251, 2816 }, // GMT Standard Time / Isle Of Man
- { 48, 252, 2835 }, // GMT Standard Time / Jersey
- { 49, 86, 2849 }, // Greenland Standard Time / Greenland
- { 50, 34, 2865 }, // Greenwich Standard Time / Burkina Faso
- { 50, 53, 2884 }, // Greenwich Standard Time / Ivory Coast
- { 50, 80, 2899 }, // Greenwich Standard Time / Gambia
- { 50, 83, 2913 }, // Greenwich Standard Time / Ghana
- { 50, 91, 2926 }, // Greenwich Standard Time / Guinea
- { 50, 92, 2941 }, // Greenwich Standard Time / Guinea Bissau
- { 50, 99, 2955 }, // Greenwich Standard Time / Iceland
- { 50, 121, 2974 }, // Greenwich Standard Time / Liberia
- { 50, 132, 2990 }, // Greenwich Standard Time / Mali
- { 50, 136, 3004 }, // Greenwich Standard Time / Mauritania
- { 50, 187, 3022 }, // Greenwich Standard Time / Senegal
- { 50, 189, 3035 }, // Greenwich Standard Time / Sierra Leone
- { 50, 199, 3051 }, // Greenwich Standard Time / Saint Helena
- { 50, 212, 3070 }, // Greenwich Standard Time / Togo
- { 51, 56, 3082 }, // GTB Standard Time / Cyprus
- { 51, 85, 3110 }, // GTB Standard Time / Greece
- { 51, 177, 3124 }, // GTB Standard Time / Romania
- { 52, 94, 3141 }, // Haiti Standard Time / Haiti
- { 53, 0, 3164 }, // Hawaiian Standard Time / AnyCountry
- { 53, 51, 3175 }, // Hawaiian Standard Time / Cook Islands
- { 53, 77, 3193 }, // Hawaiian Standard Time / French Polynesia
- { 53, 225, 3208 }, // Hawaiian Standard Time / United States
- { 53, 226, 3225 }, // Hawaiian Standard Time / United States Minor Outlying Islands
- { 54, 100, 3242 }, // India Standard Time / India
- { 55, 102, 3256 }, // Iran Standard Time / Iran
- { 56, 105, 3268 }, // Israel Standard Time / Israel
- { 57, 109, 3283 }, // Jordan Standard Time / Jordan
- { 58, 178, 3294 }, // Kaliningrad Standard Time / Russia
- { 59, 114, 3313 }, // Korea Standard Time / South Korea
- { 60, 122, 3324 }, // Libya Standard Time / Libya
- { 61, 0, 3339 }, // Line Islands Standard Time / AnyCountry
- { 61, 112, 3350 }, // Line Islands Standard Time / Kiribati
- { 62, 13, 3369 }, // Lord Howe Standard Time / Australia
- { 63, 178, 3389 }, // Magadan Standard Time / Russia
- { 64, 43, 3402 }, // Magallanes Standard Time / Chile
- { 65, 77, 3423 }, // Marquesas Standard Time / French Polynesia
- { 66, 137, 3441 }, // Mauritius Standard Time / Mauritius
- { 66, 176, 3458 }, // Mauritius Standard Time / Reunion
- { 66, 188, 3473 }, // Mauritius Standard Time / Seychelles
- { 67, 119, 3485 }, // Middle East Standard Time / Lebanon
- { 68, 227, 3497 }, // Montevideo Standard Time / Uruguay
- { 69, 145, 3516 }, // Morocco Standard Time / Morocco
- { 69, 236, 3534 }, // Morocco Standard Time / Western Sahara
- { 70, 139, 3550 }, // Mountain Standard Time (Mexico) / Mexico
- { 71, 0, 3585 }, // Mountain Standard Time / AnyCountry
- { 71, 38, 3593 }, // Mountain Standard Time / Canada
- { 71, 139, 3667 }, // Mountain Standard Time / Mexico
- { 71, 225, 3683 }, // Mountain Standard Time / United States
- { 72, 46, 3712 }, // Myanmar Standard Time / Cocos Islands
- { 72, 147, 3725 }, // Myanmar Standard Time / Myanmar
- { 73, 178, 3738 }, // N. Central Asia Standard Time / Russia
- { 74, 148, 3755 }, // Namibia Standard Time / Namibia
- { 75, 150, 3771 }, // Nepal Standard Time / Nepal
- { 76, 8, 3785 }, // New Zealand Standard Time / Antarctica
- { 76, 154, 3804 }, // New Zealand Standard Time / New Zealand
- { 77, 38, 3821 }, // Newfoundland Standard Time / Canada
- { 78, 159, 3838 }, // Norfolk Standard Time / Norfolk Island
- { 79, 178, 3854 }, // North Asia East Standard Time / Russia
- { 80, 178, 3867 }, // North Asia Standard Time / Russia
- { 81, 113, 3902 }, // North Korea Standard Time / North Korea
- { 82, 178, 3917 }, // Omsk Standard Time / Russia
- { 83, 43, 3927 }, // Pacific SA Standard Time / Chile
- { 84, 0, 3944 }, // Pacific Standard Time / AnyCountry
- { 84, 38, 3952 }, // Pacific Standard Time / Canada
- { 84, 225, 4004 }, // Pacific Standard Time / United States
- { 85, 139, 4024 }, // Pacific Standard Time (Mexico) / Mexico
- { 86, 163, 4061 }, // Pakistan Standard Time / Pakistan
- { 87, 168, 4074 }, // Paraguay Standard Time / Paraguay
- { 88, 110, 4091 }, // Qyzylorda Standard Time / Kazakhstan
- { 89, 21, 4106 }, // Romance Standard Time / Belgium
- { 89, 58, 4122 }, // Romance Standard Time / Denmark
- { 89, 74, 4140 }, // Romance Standard Time / France
- { 89, 197, 4153 }, // Romance Standard Time / Spain
- { 90, 178, 4180 }, // Russia Time Zone 3 / Russia
- { 91, 178, 4194 }, // Russia Time Zone 10 / Russia
- { 92, 178, 4213 }, // Russia Time Zone 11 / Russia
- { 93, 178, 4240 }, // Russian Standard Time / Russia
- { 93, 222, 4267 }, // Russian Standard Time / Ukraine
- { 94, 0, 4285 }, // SA Eastern Standard Time / AnyCountry
- { 94, 8, 4295 }, // SA Eastern Standard Time / Antarctica
- { 94, 30, 4332 }, // SA Eastern Standard Time / Brazil
- { 94, 70, 4411 }, // SA Eastern Standard Time / Falkland Islands
- { 94, 76, 4428 }, // SA Eastern Standard Time / French Guiana
- { 94, 202, 4444 }, // SA Eastern Standard Time / Suriname
- { 95, 0, 4463 }, // SA Pacific Standard Time / AnyCountry
- { 95, 30, 4473 }, // SA Pacific Standard Time / Brazil
- { 95, 38, 4509 }, // SA Pacific Standard Time / Canada
- { 95, 40, 4531 }, // SA Pacific Standard Time / Cayman Islands
- { 95, 47, 4546 }, // SA Pacific Standard Time / Colombia
- { 95, 63, 4561 }, // SA Pacific Standard Time / Ecuador
- { 95, 107, 4579 }, // SA Pacific Standard Time / Jamaica
- { 95, 166, 4595 }, // SA Pacific Standard Time / Panama
- { 95, 169, 4610 }, // SA Pacific Standard Time / Peru
- { 96, 0, 4623 }, // SA Western Standard Time / AnyCountry
- { 96, 7, 4633 }, // SA Western Standard Time / Anguilla
- { 96, 9, 4650 }, // SA Western Standard Time / Antigua And Barbuda
- { 96, 12, 4666 }, // SA Western Standard Time / Aruba
- { 96, 19, 4680 }, // SA Western Standard Time / Barbados
- { 96, 26, 4697 }, // SA Western Standard Time / Bolivia
- { 96, 30, 4712 }, // SA Western Standard Time / Brazil
- { 96, 38, 4765 }, // SA Western Standard Time / Canada
- { 96, 60, 4786 }, // SA Western Standard Time / Dominica
- { 96, 61, 4803 }, // SA Western Standard Time / Dominican Republic
- { 96, 87, 4825 }, // SA Western Standard Time / Grenada
- { 96, 88, 4841 }, // SA Western Standard Time / Guadeloupe
- { 96, 93, 4860 }, // SA Western Standard Time / Guyana
- { 96, 135, 4875 }, // SA Western Standard Time / Martinique
- { 96, 144, 4894 }, // SA Western Standard Time / Montserrat
- { 96, 152, 4913 }, // SA Western Standard Time / Cura Sao
- { 96, 174, 4929 }, // SA Western Standard Time / Puerto Rico
- { 96, 180, 4949 }, // SA Western Standard Time / Saint Kitts And Nevis
- { 96, 181, 4966 }, // SA Western Standard Time / Saint Lucia
- { 96, 182, 4983 }, // SA Western Standard Time / Saint Vincent And The Grenadines
- { 96, 215, 5002 }, // SA Western Standard Time / Trinidad And Tobago
- { 96, 233, 5024 }, // SA Western Standard Time / British Virgin Islands
- { 96, 234, 5040 }, // SA Western Standard Time / United States Virgin Islands
- { 96, 244, 5058 }, // SA Western Standard Time / Saint Barthelemy
- { 96, 245, 5080 }, // SA Western Standard Time / Saint Martin
- { 96, 255, 5096 }, // SA Western Standard Time / Bonaire
- { 96, 256, 5115 }, // SA Western Standard Time / Sint Maarten
- { 97, 200, 5137 }, // Saint Pierre Standard Time / Saint Pierre And Miquelon
- { 98, 178, 5154 }, // Sakhalin Standard Time / Russia
- { 99, 183, 5168 }, // Samoa Standard Time / Samoa
- { 100, 185, 5181 }, // Sao Tome Standard Time / Sao Tome And Principe
- { 101, 178, 5197 }, // Saratov Standard Time / Russia
- { 102, 0, 5212 }, // SE Asia Standard Time / AnyCountry
- { 102, 8, 5222 }, // SE Asia Standard Time / Antarctica
- { 102, 36, 5239 }, // SE Asia Standard Time / Cambodia
- { 102, 45, 5255 }, // SE Asia Standard Time / Christmas Island
- { 102, 101, 5272 }, // SE Asia Standard Time / Indonesia
- { 102, 117, 5300 }, // SE Asia Standard Time / Laos
- { 102, 211, 5315 }, // SE Asia Standard Time / Thailand
- { 102, 232, 5328 }, // SE Asia Standard Time / Vietnam
- { 103, 0, 5340 }, // Singapore Standard Time / AnyCountry
- { 103, 8, 5350 }, // Singapore Standard Time / Antarctica
- { 103, 32, 5367 }, // Singapore Standard Time / Brunei
- { 103, 101, 5379 }, // Singapore Standard Time / Indonesia
- { 103, 130, 5393 }, // Singapore Standard Time / Malaysia
- { 103, 170, 5424 }, // Singapore Standard Time / Philippines
- { 103, 190, 5436 }, // Singapore Standard Time / Singapore
- { 104, 0, 5451 }, // South Africa Standard Time / AnyCountry
- { 104, 28, 5461 }, // South Africa Standard Time / Botswana
- { 104, 35, 5477 }, // South Africa Standard Time / Burundi
- { 104, 49, 5494 }, // South Africa Standard Time / Congo Kinshasa
- { 104, 120, 5512 }, // South Africa Standard Time / Lesotho
- { 104, 129, 5526 }, // South Africa Standard Time / Malawi
- { 104, 146, 5542 }, // South Africa Standard Time / Mozambique
- { 104, 179, 5556 }, // South Africa Standard Time / Rwanda
- { 104, 195, 5570 }, // South Africa Standard Time / South Africa
- { 104, 204, 5590 }, // South Africa Standard Time / Swaziland
- { 104, 239, 5605 }, // South Africa Standard Time / Zambia
- { 104, 240, 5619 }, // South Africa Standard Time / Zimbabwe
- { 105, 198, 5633 }, // Sri Lanka Standard Time / Sri Lanka
- { 106, 201, 5646 }, // Sudan Standard Time / Sudan
- { 107, 207, 5662 }, // Syria Standard Time / Syria
- { 108, 208, 5676 }, // Taipei Standard Time / Taiwan
- { 109, 13, 5688 }, // Tasmania Standard Time / Australia
- { 110, 30, 5722 }, // Tocantins Standard Time / Brazil
- { 111, 0, 5740 }, // Tokyo Standard Time / AnyCountry
- { 111, 62, 5750 }, // Tokyo Standard Time / East Timor
- { 111, 101, 5760 }, // Tokyo Standard Time / Indonesia
- { 111, 108, 5774 }, // Tokyo Standard Time / Japan
- { 111, 164, 5785 }, // Tokyo Standard Time / Palau
- { 112, 178, 5799 }, // Tomsk Standard Time / Russia
- { 113, 214, 5810 }, // Tonga Standard Time / Tonga
- { 114, 178, 5828 }, // Transbaikal Standard Time / Russia
- { 115, 217, 5839 }, // Turkey Standard Time / Turkey
- { 116, 219, 5855 }, // Turks And Caicos Standard Time / Turks And Caicos Islands
- { 117, 143, 5874 }, // Ulaanbaatar Standard Time / Mongolia
- { 118, 225, 5907 }, // US Eastern Standard Time / United States
- { 119, 0, 5974 }, // US Mountain Standard Time / AnyCountry
- { 119, 38, 5984 }, // US Mountain Standard Time / Canada
- { 119, 139, 6041 }, // US Mountain Standard Time / Mexico
- { 119, 225, 6060 }, // US Mountain Standard Time / United States
- { 120, 0, 6076 }, // UTC-11 / AnyCountry
- { 120, 4, 6087 }, // UTC-11 / American Samoa
- { 120, 158, 6105 }, // UTC-11 / Niue
- { 120, 226, 6118 }, // UTC-11 / United States Minor Outlying Islands
- { 121, 0, 6133 }, // UTC-09 / AnyCountry
- { 121, 77, 6143 }, // UTC-09 / French Polynesia
- { 122, 0, 6159 }, // UTC-08 / AnyCountry
- { 122, 171, 6169 }, // UTC-08 / Pitcairn
- { 123, 0, 6186 }, // UTC-02 / AnyCountry
- { 123, 30, 6196 }, // UTC-02 / Brazil
- { 123, 196, 6212 }, // UTC-02 / South Georgia And The South Sandwich Islands
- { 124, 0, 6235 }, // UTC / AnyCountry
- { 124, 86, 6251 }, // UTC / Greenland
- { 125, 0, 6272 }, // UTC+12 / AnyCountry
- { 125, 112, 6283 }, // UTC+12 / Kiribati
- { 125, 134, 6298 }, // UTC+12 / Marshall Islands
- { 125, 149, 6331 }, // UTC+12 / Nauru
- { 125, 220, 6345 }, // UTC+12 / Tuvalu
- { 125, 226, 6362 }, // UTC+12 / United States Minor Outlying Islands
- { 125, 235, 6375 }, // UTC+12 / Wallis And Futuna Islands
- { 126, 0, 6390 }, // UTC+13 / AnyCountry
- { 126, 112, 6401 }, // UTC+13 / Kiribati
- { 126, 213, 6419 }, // UTC+13 / Tokelau
- { 127, 231, 6435 }, // Venezuela Standard Time / Venezuela
- { 128, 178, 6451 }, // Vladivostok Standard Time / Russia
- { 129, 178, 6482 }, // Volgograd Standard Time / Russia
- { 130, 13, 6499 }, // W. Australia Standard Time / Australia
- { 131, 0, 6515 }, // W. Central Africa Standard Time / AnyCountry
- { 131, 3, 6525 }, // W. Central Africa Standard Time / Algeria
- { 131, 6, 6540 }, // W. Central Africa Standard Time / Angola
- { 131, 23, 6554 }, // W. Central Africa Standard Time / Benin
- { 131, 37, 6572 }, // W. Central Africa Standard Time / Cameroon
- { 131, 41, 6586 }, // W. Central Africa Standard Time / Central African Republic
- { 131, 42, 6600 }, // W. Central Africa Standard Time / Chad
- { 131, 49, 6616 }, // W. Central Africa Standard Time / Congo Kinshasa
- { 131, 50, 6632 }, // W. Central Africa Standard Time / Congo Brazzaville
- { 131, 66, 6651 }, // W. Central Africa Standard Time / Equatorial Guinea
- { 131, 79, 6665 }, // W. Central Africa Standard Time / Gabon
- { 131, 156, 6683 }, // W. Central Africa Standard Time / Niger
- { 131, 157, 6697 }, // W. Central Africa Standard Time / Nigeria
- { 131, 216, 6710 }, // W. Central Africa Standard Time / Tunisia
- { 132, 5, 6723 }, // W. Europe Standard Time / Andorra
- { 132, 14, 6738 }, // W. Europe Standard Time / Austria
- { 132, 82, 6752 }, // W. Europe Standard Time / Germany
- { 132, 84, 6782 }, // W. Europe Standard Time / Gibraltar
- { 132, 106, 6799 }, // W. Europe Standard Time / Italy
- { 132, 123, 6811 }, // W. Europe Standard Time / Liechtenstein
- { 132, 125, 6824 }, // W. Europe Standard Time / Luxembourg
- { 132, 133, 6842 }, // W. Europe Standard Time / Malta
- { 132, 142, 6855 }, // W. Europe Standard Time / Monaco
- { 132, 151, 6869 }, // W. Europe Standard Time / Netherlands
- { 132, 161, 6886 }, // W. Europe Standard Time / Norway
- { 132, 184, 6898 }, // W. Europe Standard Time / San Marino
- { 132, 203, 6916 }, // W. Europe Standard Time / Svalbard And Jan Mayen Islands
- { 132, 205, 6936 }, // W. Europe Standard Time / Sweden
- { 132, 206, 6953 }, // W. Europe Standard Time / Switzerland
- { 132, 230, 6967 }, // W. Europe Standard Time / Vatican City State
- { 133, 143, 6982 }, // W. Mongolia Standard Time / Mongolia
- { 134, 0, 6992 }, // West Asia Standard Time / AnyCountry
- { 134, 8, 7002 }, // West Asia Standard Time / Antarctica
- { 134, 78, 7020 }, // West Asia Standard Time / French Southern Territories
- { 134, 110, 7037 }, // West Asia Standard Time / Kazakhstan
- { 134, 131, 7082 }, // West Asia Standard Time / Maldives
- { 134, 209, 7098 }, // West Asia Standard Time / Tajikistan
- { 134, 218, 7112 }, // West Asia Standard Time / Turkmenistan
- { 134, 228, 7126 }, // West Asia Standard Time / Uzbekistan
- { 135, 165, 7155 }, // West Bank Standard Time / Palestinian Territories
- { 136, 0, 7177 }, // West Pacific Standard Time / AnyCountry
- { 136, 8, 7188 }, // West Pacific Standard Time / Antarctica
- { 136, 89, 7214 }, // West Pacific Standard Time / Guam
- { 136, 140, 7227 }, // West Pacific Standard Time / Micronesia
- { 136, 160, 7240 }, // West Pacific Standard Time / Northern Mariana Islands
- { 136, 167, 7255 }, // West Pacific Standard Time / Papua New Guinea
- { 137, 178, 7276 }, // Yakutsk Standard Time / Russia
- { 0, 0, 0 } // Trailing zeroes
+ { 2, 248, 11 }, // Alaskan Standard Time / United States
+ { 3, 248, 106 }, // Aleutian Standard Time / United States
+ { 4, 193, 119 }, // Altai Standard Time / Russia
+ { 5, 19, 132 }, // Arab Standard Time / Bahrain
+ { 5, 127, 145 }, // Arab Standard Time / Kuwait
+ { 5, 190, 157 }, // Arab Standard Time / Qatar
+ { 5, 205, 168 }, // Arab Standard Time / Saudi Arabia
+ { 5, 259, 180 }, // Arab Standard Time / Yemen
+ { 6, 0, 190 }, // Arabian Standard Time / AnyTerritory
+ { 6, 176, 200 }, // Arabian Standard Time / Oman
+ { 6, 245, 212 }, // Arabian Standard Time / United Arab Emirates
+ { 7, 113, 223 }, // Arabic Standard Time / Iraq
+ { 8, 11, 236 }, // Argentina Standard Time / Argentina
+ { 9, 193, 509 }, // Astrakhan Standard Time / Russia
+ { 10, 26, 543 }, // Atlantic Standard Time / Bermuda
+ { 10, 41, 560 }, // Atlantic Standard Time / Canada
+ { 10, 95, 628 }, // Atlantic Standard Time / Greenland
+ { 11, 15, 642 }, // AUS Central Standard Time / Australia
+ { 12, 15, 659 }, // Aus Central W. Standard Time / Australia
+ { 13, 15, 675 }, // AUS Eastern Standard Time / Australia
+ { 14, 17, 712 }, // Azerbaijan Standard Time / Azerbaijan
+ { 15, 95, 722 }, // Azores Standard Time / Greenland
+ { 15, 188, 743 }, // Azores Standard Time / Portugal
+ { 16, 32, 759 }, // Bahia Standard Time / Brazil
+ { 17, 20, 773 }, // Bangladesh Standard Time / Bangladesh
+ { 17, 27, 784 }, // Bangladesh Standard Time / Bhutan
+ { 18, 22, 797 }, // Belarus Standard Time / Belarus
+ { 19, 182, 810 }, // Bougainville Standard Time / Papua New Guinea
+ { 20, 41, 831 }, // Canada Central Standard Time / Canada
+ { 21, 0, 868 }, // Cape Verde Standard Time / AnyTerritory
+ { 21, 43, 878 }, // Cape Verde Standard Time / Cape Verde
+ { 22, 12, 898 }, // Caucasus Standard Time / Armenia
+ { 23, 15, 911 }, // Cen. Australia Standard Time / Australia
+ { 24, 0, 952 }, // Central America Standard Time / AnyTerritory
+ { 24, 24, 962 }, // Central America Standard Time / Belize
+ { 24, 59, 977 }, // Central America Standard Time / Costa Rica
+ { 24, 70, 996 }, // Central America Standard Time / Ecuador
+ { 24, 72, 1014 }, // Central America Standard Time / El Salvador
+ { 24, 99, 1034 }, // Central America Standard Time / Guatemala
+ { 24, 106, 1052 }, // Central America Standard Time / Honduras
+ { 24, 168, 1072 }, // Central America Standard Time / Nicaragua
+ { 25, 0, 1088 }, // Central Asia Standard Time / AnyTerritory
+ { 25, 9, 1098 }, // Central Asia Standard Time / Antarctica
+ { 25, 33, 1116 }, // Central Asia Standard Time / British Indian Ocean Territory
+ { 25, 50, 1130 }, // Central Asia Standard Time / China
+ { 25, 123, 1142 }, // Central Asia Standard Time / Kazakhstan
+ { 25, 128, 1168 }, // Central Asia Standard Time / Kyrgyzstan
+ { 26, 32, 1181 }, // Central Brazilian Standard Time / Brazil
+ { 27, 3, 1217 }, // Central Europe Standard Time / Albania
+ { 27, 64, 1231 }, // Central Europe Standard Time / Czechia
+ { 27, 108, 1245 }, // Central Europe Standard Time / Hungary
+ { 27, 157, 1261 }, // Central Europe Standard Time / Montenegro
+ { 27, 207, 1278 }, // Central Europe Standard Time / Serbia
+ { 27, 212, 1294 }, // Central Europe Standard Time / Slovakia
+ { 27, 213, 1312 }, // Central Europe Standard Time / Slovenia
+ { 28, 29, 1329 }, // Central European Standard Time / Bosnia and Herzegovina
+ { 28, 60, 1345 }, // Central European Standard Time / Croatia
+ { 28, 140, 1359 }, // Central European Standard Time / Macedonia
+ { 28, 187, 1373 }, // Central European Standard Time / Poland
+ { 29, 0, 1387 }, // Central Pacific Standard Time / AnyTerritory
+ { 29, 9, 1398 }, // Central Pacific Standard Time / Antarctica
+ { 29, 153, 1415 }, // Central Pacific Standard Time / Micronesia
+ { 29, 166, 1445 }, // Central Pacific Standard Time / New Caledonia
+ { 29, 214, 1460 }, // Central Pacific Standard Time / Solomon Islands
+ { 29, 252, 1480 }, // Central Pacific Standard Time / Vanuatu
+ { 30, 0, 1494 }, // Central Standard Time / AnyTerritory
+ { 30, 41, 1502 }, // Central Standard Time / Canada
+ { 30, 152, 1577 }, // Central Standard Time / Mexico
+ { 30, 248, 1611 }, // Central Standard Time / United States
+ { 31, 152, 1779 }, // Central Standard Time (Mexico) / Mexico
+ { 32, 167, 1873 }, // Chatham Islands Standard Time / New Zealand
+ { 33, 50, 1889 }, // China Standard Time / China
+ { 33, 107, 1903 }, // China Standard Time / Hong Kong
+ { 33, 139, 1918 }, // China Standard Time / Macao
+ { 34, 61, 1929 }, // Cuba Standard Time / Cuba
+ { 35, 0, 1944 }, // Dateline Standard Time / AnyTerritory
+ { 36, 0, 1955 }, // E. Africa Standard Time / AnyTerritory
+ { 36, 9, 1965 }, // E. Africa Standard Time / Antarctica
+ { 36, 55, 1982 }, // E. Africa Standard Time / Comoros
+ { 36, 67, 1996 }, // E. Africa Standard Time / Djibouti
+ { 36, 74, 2012 }, // E. Africa Standard Time / Eritrea
+ { 36, 77, 2026 }, // E. Africa Standard Time / Ethiopia
+ { 36, 124, 2045 }, // E. Africa Standard Time / Kenya
+ { 36, 141, 2060 }, // E. Africa Standard Time / Madagascar
+ { 36, 151, 2080 }, // E. Africa Standard Time / Mayotte
+ { 36, 215, 2095 }, // E. Africa Standard Time / Somalia
+ { 36, 230, 2112 }, // E. Africa Standard Time / Tanzania
+ { 36, 243, 2133 }, // E. Africa Standard Time / Uganda
+ { 37, 15, 2148 }, // E. Australia Standard Time / Australia
+ { 38, 154, 2186 }, // E. Europe Standard Time / Moldova
+ { 39, 32, 2202 }, // E. South America Standard Time / Brazil
+ { 40, 49, 2220 }, // Easter Island Standard Time / Chile
+ { 41, 0, 2235 }, // Eastern Standard Time / AnyTerritory
+ { 41, 18, 2243 }, // Eastern Standard Time / Bahamas
+ { 41, 41, 2258 }, // Eastern Standard Time / Canada
+ { 41, 248, 2363 }, // Eastern Standard Time / United States
+ { 42, 152, 2520 }, // Eastern Standard Time (Mexico) / Mexico
+ { 43, 71, 2535 }, // Egypt Standard Time / Egypt
+ { 44, 193, 2548 }, // Ekaterinburg Standard Time / Russia
+ { 45, 82, 2567 }, // Fiji Standard Time / Fiji
+ { 46, 2, 2580 }, // FLE Standard Time / Aland Islands
+ { 46, 36, 2597 }, // FLE Standard Time / Bulgaria
+ { 46, 75, 2610 }, // FLE Standard Time / Estonia
+ { 46, 83, 2625 }, // FLE Standard Time / Finland
+ { 46, 131, 2641 }, // FLE Standard Time / Latvia
+ { 46, 137, 2653 }, // FLE Standard Time / Lithuania
+ { 46, 244, 2668 }, // FLE Standard Time / Ukraine
+ { 47, 90, 2714 }, // Georgian Standard Time / Georgia
+ { 48, 81, 2727 }, // GMT Standard Time / Faroe Islands
+ { 48, 100, 2743 }, // GMT Standard Time / Guernsey
+ { 48, 114, 2759 }, // GMT Standard Time / Ireland
+ { 48, 115, 2773 }, // GMT Standard Time / Isle of Man
+ { 48, 121, 2792 }, // GMT Standard Time / Jersey
+ { 48, 188, 2806 }, // GMT Standard Time / Portugal
+ { 48, 220, 2837 }, // GMT Standard Time / Spain
+ { 48, 246, 2853 }, // GMT Standard Time / United Kingdom
+ { 49, 95, 2867 }, // Greenland Standard Time / Greenland
+ { 50, 37, 2883 }, // Greenwich Standard Time / Burkina Faso
+ { 50, 89, 2902 }, // Greenwich Standard Time / Gambia
+ { 50, 92, 2916 }, // Greenwich Standard Time / Ghana
+ { 50, 95, 2929 }, // Greenwich Standard Time / Greenland
+ { 50, 101, 2950 }, // Greenwich Standard Time / Guinea-Bissau
+ { 50, 102, 2964 }, // Greenwich Standard Time / Guinea
+ { 50, 109, 2979 }, // Greenwich Standard Time / Iceland
+ { 50, 118, 2998 }, // Greenwich Standard Time / Ivory Coast
+ { 50, 134, 3013 }, // Greenwich Standard Time / Liberia
+ { 50, 145, 3029 }, // Greenwich Standard Time / Mali
+ { 50, 149, 3043 }, // Greenwich Standard Time / Mauritania
+ { 50, 196, 3061 }, // Greenwich Standard Time / Saint Helena
+ { 50, 206, 3080 }, // Greenwich Standard Time / Senegal
+ { 50, 209, 3093 }, // Greenwich Standard Time / Sierra Leone
+ { 50, 233, 3109 }, // Greenwich Standard Time / Togo
+ { 51, 63, 3121 }, // GTB Standard Time / Cyprus
+ { 51, 94, 3149 }, // GTB Standard Time / Greece
+ { 51, 192, 3163 }, // GTB Standard Time / Romania
+ { 52, 104, 3180 }, // Haiti Standard Time / Haiti
+ { 53, 0, 3203 }, // Hawaiian Standard Time / AnyTerritory
+ { 53, 58, 3214 }, // Hawaiian Standard Time / Cook Islands
+ { 53, 86, 3232 }, // Hawaiian Standard Time / French Polynesia
+ { 53, 247, 3247 }, // Hawaiian Standard Time / United States Outlying Islands
+ { 53, 248, 3264 }, // Hawaiian Standard Time / United States
+ { 54, 110, 3281 }, // India Standard Time / India
+ { 55, 112, 3295 }, // Iran Standard Time / Iran
+ { 56, 116, 3307 }, // Israel Standard Time / Israel
+ { 57, 122, 3322 }, // Jordan Standard Time / Jordan
+ { 58, 193, 3333 }, // Kaliningrad Standard Time / Russia
+ { 59, 218, 3352 }, // Korea Standard Time / South Korea
+ { 60, 135, 3363 }, // Libya Standard Time / Libya
+ { 61, 0, 3378 }, // Line Islands Standard Time / AnyTerritory
+ { 61, 125, 3389 }, // Line Islands Standard Time / Kiribati
+ { 62, 15, 3408 }, // Lord Howe Standard Time / Australia
+ { 63, 193, 3428 }, // Magadan Standard Time / Russia
+ { 64, 49, 3441 }, // Magallanes Standard Time / Chile
+ { 65, 86, 3462 }, // Marquesas Standard Time / French Polynesia
+ { 66, 150, 3480 }, // Mauritius Standard Time / Mauritius
+ { 66, 191, 3497 }, // Mauritius Standard Time / Reunion
+ { 66, 208, 3512 }, // Mauritius Standard Time / Seychelles
+ { 67, 132, 3524 }, // Middle East Standard Time / Lebanon
+ { 68, 250, 3536 }, // Montevideo Standard Time / Uruguay
+ { 69, 159, 3555 }, // Morocco Standard Time / Morocco
+ { 69, 257, 3573 }, // Morocco Standard Time / Western Sahara
+ { 70, 0, 3589 }, // Mountain Standard Time / AnyTerritory
+ { 70, 41, 3597 }, // Mountain Standard Time / Canada
+ { 70, 152, 3671 }, // Mountain Standard Time / Mexico
+ { 70, 248, 3693 }, // Mountain Standard Time / United States
+ { 71, 152, 3722 }, // Mountain Standard Time (Mexico) / Mexico
+ { 72, 53, 3739 }, // Myanmar Standard Time / Cocos Islands
+ { 72, 161, 3752 }, // Myanmar Standard Time / Myanmar
+ { 73, 193, 3765 }, // N. Central Asia Standard Time / Russia
+ { 74, 162, 3782 }, // Namibia Standard Time / Namibia
+ { 75, 164, 3798 }, // Nepal Standard Time / Nepal
+ { 76, 9, 3812 }, // New Zealand Standard Time / Antarctica
+ { 76, 167, 3831 }, // New Zealand Standard Time / New Zealand
+ { 77, 41, 3848 }, // Newfoundland Standard Time / Canada
+ { 78, 172, 3865 }, // Norfolk Standard Time / Norfolk Island
+ { 79, 193, 3881 }, // North Asia East Standard Time / Russia
+ { 80, 193, 3894 }, // North Asia Standard Time / Russia
+ { 81, 174, 3929 }, // North Korea Standard Time / North Korea
+ { 82, 193, 3944 }, // Omsk Standard Time / Russia
+ { 83, 49, 3954 }, // Pacific SA Standard Time / Chile
+ { 84, 0, 3971 }, // Pacific Standard Time / AnyTerritory
+ { 84, 41, 3979 }, // Pacific Standard Time / Canada
+ { 84, 248, 3997 }, // Pacific Standard Time / United States
+ { 85, 152, 4017 }, // Pacific Standard Time (Mexico) / Mexico
+ { 86, 178, 4054 }, // Pakistan Standard Time / Pakistan
+ { 87, 183, 4067 }, // Paraguay Standard Time / Paraguay
+ { 88, 123, 4084 }, // Qyzylorda Standard Time / Kazakhstan
+ { 89, 23, 4099 }, // Romance Standard Time / Belgium
+ { 89, 65, 4115 }, // Romance Standard Time / Denmark
+ { 89, 84, 4133 }, // Romance Standard Time / France
+ { 89, 220, 4146 }, // Romance Standard Time / Spain
+ { 90, 193, 4173 }, // Russia Time Zone 10 / Russia
+ { 91, 193, 4192 }, // Russia Time Zone 11 / Russia
+ { 92, 193, 4219 }, // Russia Time Zone 3 / Russia
+ { 93, 193, 4233 }, // Russian Standard Time / Russia
+ { 93, 244, 4260 }, // Russian Standard Time / Ukraine
+ { 94, 0, 4278 }, // SA Eastern Standard Time / AnyTerritory
+ { 94, 9, 4288 }, // SA Eastern Standard Time / Antarctica
+ { 94, 32, 4325 }, // SA Eastern Standard Time / Brazil
+ { 94, 80, 4404 }, // SA Eastern Standard Time / Falkland Islands
+ { 94, 85, 4421 }, // SA Eastern Standard Time / French Guiana
+ { 94, 223, 4437 }, // SA Eastern Standard Time / Suriname
+ { 95, 0, 4456 }, // SA Pacific Standard Time / AnyTerritory
+ { 95, 32, 4466 }, // SA Pacific Standard Time / Brazil
+ { 95, 41, 4502 }, // SA Pacific Standard Time / Canada
+ { 95, 45, 4524 }, // SA Pacific Standard Time / Cayman Islands
+ { 95, 54, 4539 }, // SA Pacific Standard Time / Colombia
+ { 95, 70, 4554 }, // SA Pacific Standard Time / Ecuador
+ { 95, 119, 4572 }, // SA Pacific Standard Time / Jamaica
+ { 95, 181, 4588 }, // SA Pacific Standard Time / Panama
+ { 95, 184, 4603 }, // SA Pacific Standard Time / Peru
+ { 96, 0, 4616 }, // SA Western Standard Time / AnyTerritory
+ { 96, 8, 4626 }, // SA Western Standard Time / Anguilla
+ { 96, 10, 4643 }, // SA Western Standard Time / Antigua and Barbuda
+ { 96, 13, 4659 }, // SA Western Standard Time / Aruba
+ { 96, 21, 4673 }, // SA Western Standard Time / Barbados
+ { 96, 28, 4690 }, // SA Western Standard Time / Bolivia
+ { 96, 32, 4705 }, // SA Western Standard Time / Brazil
+ { 96, 34, 4758 }, // SA Western Standard Time / British Virgin Islands
+ { 96, 41, 4774 }, // SA Western Standard Time / Canada
+ { 96, 44, 4795 }, // SA Western Standard Time / Caribbean Netherlands
+ { 96, 62, 4814 }, // SA Western Standard Time / Curacao
+ { 96, 68, 4830 }, // SA Western Standard Time / Dominica
+ { 96, 69, 4847 }, // SA Western Standard Time / Dominican Republic
+ { 96, 96, 4869 }, // SA Western Standard Time / Grenada
+ { 96, 97, 4885 }, // SA Western Standard Time / Guadeloupe
+ { 96, 103, 4904 }, // SA Western Standard Time / Guyana
+ { 96, 148, 4919 }, // SA Western Standard Time / Martinique
+ { 96, 158, 4938 }, // SA Western Standard Time / Montserrat
+ { 96, 189, 4957 }, // SA Western Standard Time / Puerto Rico
+ { 96, 195, 4977 }, // SA Western Standard Time / Saint Barthelemy
+ { 96, 197, 4999 }, // SA Western Standard Time / Saint Kitts and Nevis
+ { 96, 198, 5016 }, // SA Western Standard Time / Saint Lucia
+ { 96, 199, 5033 }, // SA Western Standard Time / Saint Martin
+ { 96, 201, 5049 }, // SA Western Standard Time / Saint Vincent and Grenadines
+ { 96, 211, 5068 }, // SA Western Standard Time / Sint Maarten
+ { 96, 236, 5090 }, // SA Western Standard Time / Trinidad and Tobago
+ { 96, 249, 5112 }, // SA Western Standard Time / United States Virgin Islands
+ { 97, 200, 5130 }, // Saint Pierre Standard Time / Saint Pierre and Miquelon
+ { 98, 193, 5147 }, // Sakhalin Standard Time / Russia
+ { 99, 202, 5161 }, // Samoa Standard Time / Samoa
+ { 100, 204, 5174 }, // Sao Tome Standard Time / Sao Tome and Principe
+ { 101, 193, 5190 }, // Saratov Standard Time / Russia
+ { 102, 0, 5205 }, // SE Asia Standard Time / AnyTerritory
+ { 102, 9, 5215 }, // SE Asia Standard Time / Antarctica
+ { 102, 39, 5232 }, // SE Asia Standard Time / Cambodia
+ { 102, 51, 5248 }, // SE Asia Standard Time / Christmas Island
+ { 102, 111, 5265 }, // SE Asia Standard Time / Indonesia
+ { 102, 129, 5293 }, // SE Asia Standard Time / Laos
+ { 102, 231, 5308 }, // SE Asia Standard Time / Thailand
+ { 102, 255, 5321 }, // SE Asia Standard Time / Vietnam
+ { 103, 0, 5333 }, // Singapore Standard Time / AnyTerritory
+ { 103, 35, 5343 }, // Singapore Standard Time / Brunei
+ { 103, 111, 5355 }, // Singapore Standard Time / Indonesia
+ { 103, 143, 5369 }, // Singapore Standard Time / Malaysia
+ { 103, 185, 5400 }, // Singapore Standard Time / Philippines
+ { 103, 210, 5412 }, // Singapore Standard Time / Singapore
+ { 104, 0, 5427 }, // South Africa Standard Time / AnyTerritory
+ { 104, 30, 5437 }, // South Africa Standard Time / Botswana
+ { 104, 38, 5453 }, // South Africa Standard Time / Burundi
+ { 104, 57, 5470 }, // South Africa Standard Time / Congo - Kinshasa
+ { 104, 76, 5488 }, // South Africa Standard Time / Eswatini
+ { 104, 133, 5503 }, // South Africa Standard Time / Lesotho
+ { 104, 142, 5517 }, // South Africa Standard Time / Malawi
+ { 104, 160, 5533 }, // South Africa Standard Time / Mozambique
+ { 104, 194, 5547 }, // South Africa Standard Time / Rwanda
+ { 104, 216, 5561 }, // South Africa Standard Time / South Africa
+ { 104, 260, 5581 }, // South Africa Standard Time / Zambia
+ { 104, 261, 5595 }, // South Africa Standard Time / Zimbabwe
+ { 105, 219, 5609 }, // South Sudan Standard Time / South Sudan
+ { 106, 221, 5621 }, // Sri Lanka Standard Time / Sri Lanka
+ { 107, 222, 5634 }, // Sudan Standard Time / Sudan
+ { 108, 227, 5650 }, // Syria Standard Time / Syria
+ { 109, 228, 5664 }, // Taipei Standard Time / Taiwan
+ { 110, 15, 5676 }, // Tasmania Standard Time / Australia
+ { 111, 32, 5731 }, // Tocantins Standard Time / Brazil
+ { 112, 0, 5749 }, // Tokyo Standard Time / AnyTerritory
+ { 112, 111, 5759 }, // Tokyo Standard Time / Indonesia
+ { 112, 120, 5773 }, // Tokyo Standard Time / Japan
+ { 112, 179, 5784 }, // Tokyo Standard Time / Palau
+ { 112, 232, 5798 }, // Tokyo Standard Time / Timor-Leste
+ { 113, 193, 5808 }, // Tomsk Standard Time / Russia
+ { 114, 235, 5819 }, // Tonga Standard Time / Tonga
+ { 115, 193, 5837 }, // Transbaikal Standard Time / Russia
+ { 116, 239, 5848 }, // Turkey Standard Time / Turkey
+ { 117, 241, 5864 }, // Turks And Caicos Standard Time / Turks and Caicos Islands
+ { 118, 156, 5883 }, // Ulaanbaatar Standard Time / Mongolia
+ { 119, 248, 5916 }, // US Eastern Standard Time / United States
+ { 120, 0, 5983 }, // US Mountain Standard Time / AnyTerritory
+ { 120, 41, 5993 }, // US Mountain Standard Time / Canada
+ { 120, 152, 6050 }, // US Mountain Standard Time / Mexico
+ { 120, 248, 6069 }, // US Mountain Standard Time / United States
+ { 121, 0, 6085 }, // UTC / AnyTerritory
+ { 122, 0, 6101 }, // UTC+12 / AnyTerritory
+ { 122, 125, 6112 }, // UTC+12 / Kiribati
+ { 122, 147, 6127 }, // UTC+12 / Marshall Islands
+ { 122, 163, 6160 }, // UTC+12 / Nauru
+ { 122, 242, 6174 }, // UTC+12 / Tuvalu
+ { 122, 247, 6191 }, // UTC+12 / United States Outlying Islands
+ { 122, 256, 6204 }, // UTC+12 / Wallis and Futuna
+ { 123, 0, 6219 }, // UTC+13 / AnyTerritory
+ { 123, 125, 6230 }, // UTC+13 / Kiribati
+ { 123, 234, 6248 }, // UTC+13 / Tokelau
+ { 124, 0, 6264 }, // UTC-02 / AnyTerritory
+ { 124, 32, 6274 }, // UTC-02 / Brazil
+ { 124, 217, 6290 }, // UTC-02 / South Georgia and South Sandwich Islands
+ { 125, 0, 6313 }, // UTC-08 / AnyTerritory
+ { 125, 186, 6323 }, // UTC-08 / Pitcairn
+ { 126, 0, 6340 }, // UTC-09 / AnyTerritory
+ { 126, 86, 6350 }, // UTC-09 / French Polynesia
+ { 127, 0, 6366 }, // UTC-11 / AnyTerritory
+ { 127, 5, 6377 }, // UTC-11 / American Samoa
+ { 127, 171, 6395 }, // UTC-11 / Niue
+ { 127, 247, 6408 }, // UTC-11 / United States Outlying Islands
+ { 128, 254, 6423 }, // Venezuela Standard Time / Venezuela
+ { 129, 193, 6439 }, // Vladivostok Standard Time / Russia
+ { 130, 193, 6470 }, // Volgograd Standard Time / Russia
+ { 131, 15, 6487 }, // W. Australia Standard Time / Australia
+ { 132, 0, 6503 }, // W. Central Africa Standard Time / AnyTerritory
+ { 132, 4, 6513 }, // W. Central Africa Standard Time / Algeria
+ { 132, 7, 6528 }, // W. Central Africa Standard Time / Angola
+ { 132, 25, 6542 }, // W. Central Africa Standard Time / Benin
+ { 132, 40, 6560 }, // W. Central Africa Standard Time / Cameroon
+ { 132, 46, 6574 }, // W. Central Africa Standard Time / Central African Republic
+ { 132, 48, 6588 }, // W. Central Africa Standard Time / Chad
+ { 132, 56, 6604 }, // W. Central Africa Standard Time / Congo - Brazzaville
+ { 132, 57, 6623 }, // W. Central Africa Standard Time / Congo - Kinshasa
+ { 132, 73, 6639 }, // W. Central Africa Standard Time / Equatorial Guinea
+ { 132, 88, 6653 }, // W. Central Africa Standard Time / Gabon
+ { 132, 169, 6671 }, // W. Central Africa Standard Time / Nigeria
+ { 132, 170, 6684 }, // W. Central Africa Standard Time / Niger
+ { 132, 238, 6698 }, // W. Central Africa Standard Time / Tunisia
+ { 133, 6, 6711 }, // W. Europe Standard Time / Andorra
+ { 133, 16, 6726 }, // W. Europe Standard Time / Austria
+ { 133, 91, 6740 }, // W. Europe Standard Time / Germany
+ { 133, 93, 6770 }, // W. Europe Standard Time / Gibraltar
+ { 133, 117, 6787 }, // W. Europe Standard Time / Italy
+ { 133, 136, 6799 }, // W. Europe Standard Time / Liechtenstein
+ { 133, 138, 6812 }, // W. Europe Standard Time / Luxembourg
+ { 133, 146, 6830 }, // W. Europe Standard Time / Malta
+ { 133, 155, 6843 }, // W. Europe Standard Time / Monaco
+ { 133, 165, 6857 }, // W. Europe Standard Time / Netherlands
+ { 133, 175, 6874 }, // W. Europe Standard Time / Norway
+ { 133, 203, 6886 }, // W. Europe Standard Time / San Marino
+ { 133, 224, 6904 }, // W. Europe Standard Time / Svalbard and Jan Mayen
+ { 133, 225, 6924 }, // W. Europe Standard Time / Sweden
+ { 133, 226, 6941 }, // W. Europe Standard Time / Switzerland
+ { 133, 253, 6955 }, // W. Europe Standard Time / Vatican City
+ { 134, 156, 6970 }, // W. Mongolia Standard Time / Mongolia
+ { 135, 0, 6980 }, // West Asia Standard Time / AnyTerritory
+ { 135, 9, 6990 }, // West Asia Standard Time / Antarctica
+ { 135, 87, 7008 }, // West Asia Standard Time / French Southern Territories
+ { 135, 123, 7025 }, // West Asia Standard Time / Kazakhstan
+ { 135, 144, 7070 }, // West Asia Standard Time / Maldives
+ { 135, 229, 7086 }, // West Asia Standard Time / Tajikistan
+ { 135, 240, 7100 }, // West Asia Standard Time / Turkmenistan
+ { 135, 251, 7114 }, // West Asia Standard Time / Uzbekistan
+ { 136, 180, 7143 }, // West Bank Standard Time / Palestinian Territories
+ { 137, 0, 7165 }, // West Pacific Standard Time / AnyTerritory
+ { 137, 9, 7176 }, // West Pacific Standard Time / Antarctica
+ { 137, 98, 7202 }, // West Pacific Standard Time / Guam
+ { 137, 153, 7215 }, // West Pacific Standard Time / Micronesia
+ { 137, 173, 7228 }, // West Pacific Standard Time / Northern Mariana Islands
+ { 137, 182, 7243 }, // West Pacific Standard Time / Papua New Guinea
+ { 138, 193, 7264 }, // Yakutsk Standard Time / Russia
+ { 139, 41, 7291 }, // Yukon Standard Time / Canada
};
// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset
-static const QWindowsData windowsDataTable[] = {
+static constexpr WindowsData windowsDataTable[] = {
{ 1, 0, 0, 16200 }, // Afghanistan Standard Time
- { 2, 26, 7303,-32400 }, // Alaskan Standard Time
+ { 2, 26, 7325,-32400 }, // Alaskan Standard Time
{ 3, 48, 106,-36000 }, // Aleutian Standard Time
{ 4, 71, 119, 25200 }, // Altai Standard Time
{ 5, 91, 168, 10800 }, // Arab Standard Time
{ 6, 110, 212, 14400 }, // Arabian Standard Time
{ 7, 132, 223, 10800 }, // Arabic Standard Time
- { 8, 153, 7321,-10800 }, // Argentina Standard Time
- { 9, 177, 7342, 14400 }, // Astrakhan Standard Time
- { 10, 201, 7359,-14400 }, // Atlantic Standard Time
+ { 8, 153, 7343,-10800 }, // Argentina Standard Time
+ { 9, 177, 7364, 14400 }, // Astrakhan Standard Time
+ { 10, 201, 7381,-14400 }, // Atlantic Standard Time
{ 11, 224, 642, 34200 }, // AUS Central Standard Time
{ 12, 250, 659, 31500 }, // Aus Central W. Standard Time
- { 13, 279, 7375, 36000 }, // AUS Eastern Standard Time
+ { 13, 279, 7397, 36000 }, // AUS Eastern Standard Time
{ 14, 305, 712, 14400 }, // Azerbaijan Standard Time
{ 15, 330, 743, -3600 }, // Azores Standard Time
{ 16, 351, 759,-10800 }, // Bahia Standard Time
{ 17, 371, 773, 21600 }, // Bangladesh Standard Time
{ 18, 396, 797, 10800 }, // Belarus Standard Time
{ 19, 418, 810, 39600 }, // Bougainville Standard Time
- { 20, 445, 7392,-21600 }, // Canada Central Standard Time
+ { 20, 445, 7414,-21600 }, // Canada Central Standard Time
{ 21, 474, 878, -3600 }, // Cape Verde Standard Time
{ 22, 499, 898, 14400 }, // Caucasus Standard Time
- { 23, 522, 7407, 34200 }, // Cen. Australia Standard Time
+ { 23, 522, 7429, 34200 }, // Cen. Australia Standard Time
{ 24, 551, 1034,-21600 }, // Central America Standard Time
- { 25, 581, 7426, 21600 }, // Central Asia Standard Time
- { 26, 608, 7438,-14400 }, // Central Brazilian Standard Time
+ { 25, 581, 7448, 21600 }, // Central Asia Standard Time
+ { 26, 608, 7460,-14400 }, // Central Brazilian Standard Time
{ 27, 640, 1245, 3600 }, // Central Europe Standard Time
{ 28, 669, 1373, 3600 }, // Central European Standard Time
- { 29, 700, 1464, 39600 }, // Central Pacific Standard Time
- { 30, 730, 7453,-21600 }, // Central Standard Time (Mexico)
- { 31, 761, 7473,-21600 }, // Central Standard Time
- { 32, 783, 1843, 28800 }, // China Standard Time
- { 33, 803, 1883, 45900 }, // Chatham Islands Standard Time
- { 34, 833, 1899,-18000 }, // Cuba Standard Time
- { 35, 852, 1914,-43200 }, // Dateline Standard Time
- { 36, 875, 2015, 10800 }, // E. Africa Standard Time
- { 37, 899, 7489, 36000 }, // E. Australia Standard Time
- { 38, 926, 2168, 7200 }, // E. Europe Standard Time
- { 39, 950, 2184,-10800 }, // E. South America Standard Time
- { 40, 981, 2202,-21600 }, // Easter Island Standard Time
- { 41, 1009, 7508,-18000 }, // Eastern Standard Time
- { 42, 1031, 2502,-18000 }, // Eastern Standard Time (Mexico)
- { 43, 1062, 2517, 7200 }, // Egypt Standard Time
- { 44, 1082, 2530, 18000 }, // Ekaterinburg Standard Time
- { 45, 1109, 2549, 43200 }, // Fiji Standard Time
- { 46, 1128, 7525, 7200 }, // FLE Standard Time
- { 47, 1146, 2696, 14400 }, // Georgian Standard Time
- { 48, 1169, 2802, 0 }, // GMT Standard Time
- { 49, 1187, 2849,-10800 }, // Greenland Standard Time
- { 50, 1211, 2955, 0 }, // Greenwich Standard Time
- { 51, 1235, 3124, 7200 }, // GTB Standard Time
- { 52, 1253, 3141,-18000 }, // Haiti Standard Time
- { 53, 1273, 3208,-36000 }, // Hawaiian Standard Time
- { 54, 1296, 3242, 19800 }, // India Standard Time
- { 55, 1316, 3256, 12600 }, // Iran Standard Time
- { 56, 1335, 3268, 7200 }, // Israel Standard Time
- { 57, 1356, 3283, 7200 }, // Jordan Standard Time
- { 58, 1377, 3294, 7200 }, // Kaliningrad Standard Time
- { 59, 1403, 3313, 32400 }, // Korea Standard Time
- { 60, 1423, 3324, 7200 }, // Libya Standard Time
- { 61, 1443, 3350, 50400 }, // Line Islands Standard Time
- { 62, 1470, 3369, 37800 }, // Lord Howe Standard Time
- { 63, 1494, 3389, 36000 }, // Magadan Standard Time
- { 64, 1516, 3402,-10800 }, // Magallanes Standard Time
- { 65, 1541, 3423,-34200 }, // Marquesas Standard Time
- { 66, 1565, 3441, 14400 }, // Mauritius Standard Time
- { 67, 1589, 3485, 7200 }, // Middle East Standard Time
- { 68, 1615, 3497,-10800 }, // Montevideo Standard Time
- { 69, 1640, 3516, 0 }, // Morocco Standard Time
- { 70, 1662, 7537,-25200 }, // Mountain Standard Time (Mexico)
- { 71, 1694, 7555,-25200 }, // Mountain Standard Time
- { 72, 1717, 3725, 23400 }, // Myanmar Standard Time
- { 73, 1739, 3738, 21600 }, // N. Central Asia Standard Time
- { 74, 1769, 3755, 3600 }, // Namibia Standard Time
- { 75, 1791, 3771, 20700 }, // Nepal Standard Time
- { 76, 1811, 3804, 43200 }, // New Zealand Standard Time
- { 77, 1837, 3821,-12600 }, // Newfoundland Standard Time
- { 78, 1864, 3838, 39600 }, // Norfolk Standard Time
- { 79, 1886, 3854, 28800 }, // North Asia East Standard Time
- { 80, 1916, 7570, 25200 }, // North Asia Standard Time
- { 81, 1941, 3902, 30600 }, // North Korea Standard Time
- { 82, 1967, 3917, 21600 }, // Omsk Standard Time
- { 83, 1986, 3927,-10800 }, // Pacific SA Standard Time
- { 84, 2011, 4004,-28800 }, // Pacific Standard Time
- { 85, 2033, 7587,-28800 }, // Pacific Standard Time (Mexico)
- { 86, 2064, 4061, 18000 }, // Pakistan Standard Time
- { 87, 2087, 4074,-14400 }, // Paraguay Standard Time
- { 88, 2110, 4091, 18000 }, // Qyzylorda Standard Time
- { 89, 2134, 4140, 3600 }, // Romance Standard Time
- { 90, 2156, 4180, 14400 }, // Russia Time Zone 3
- { 91, 2175, 4194, 39600 }, // Russia Time Zone 10
- { 92, 2195, 7603, 43200 }, // Russia Time Zone 11
- { 93, 2215, 7618, 10800 }, // Russian Standard Time
- { 94, 2237, 4428,-10800 }, // SA Eastern Standard Time
- { 95, 2262, 4546,-18000 }, // SA Pacific Standard Time
- { 96, 2287, 4697,-14400 }, // SA Western Standard Time
- { 97, 2312, 5137,-10800 }, // Saint Pierre Standard Time
- { 98, 2339, 5154, 39600 }, // Sakhalin Standard Time
- { 99, 2362, 5168, 46800 }, // Samoa Standard Time
- { 100, 2382, 5181, 0 }, // Sao Tome Standard Time
- { 101, 2405, 5197, 14400 }, // Saratov Standard Time
- { 102, 2427, 5315, 25200 }, // SE Asia Standard Time
- { 103, 2449, 5436, 28800 }, // Singapore Standard Time
- { 104, 2473, 5570, 7200 }, // South Africa Standard Time
- { 105, 2500, 5633, 19800 }, // Sri Lanka Standard Time
- { 106, 2524, 5646, 7200 }, // Sudan Standard Time
- { 107, 2544, 5662, 7200 }, // Syria Standard Time
- { 108, 2564, 5676, 28800 }, // Taipei Standard Time
- { 109, 2585, 7632, 36000 }, // Tasmania Standard Time
- { 110, 2608, 5722,-10800 }, // Tocantins Standard Time
- { 111, 2632, 5774, 32400 }, // Tokyo Standard Time
- { 112, 2652, 5799, 25200 }, // Tomsk Standard Time
- { 113, 2672, 5810, 46800 }, // Tonga Standard Time
- { 114, 2692, 5828, 32400 }, // Transbaikal Standard Time
- { 115, 2718, 5839, 7200 }, // Turkey Standard Time
- { 116, 2739, 5855,-14400 }, // Turks And Caicos Standard Time
- { 117, 2770, 7649, 28800 }, // Ulaanbaatar Standard Time
- { 118, 2796, 7666,-18000 }, // US Eastern Standard Time
- { 119, 2821, 6060,-25200 }, // US Mountain Standard Time
- { 120, 2847, 6076,-39600 }, // UTC-11
- { 121, 2854, 6133,-32400 }, // UTC-09
- { 122, 2861, 6159,-28800 }, // UTC-08
- { 123, 2868, 6186, -7200 }, // UTC-02
- { 124, 2875, 7687, 0 }, // UTC
- { 125, 2879, 6272, 43200 }, // UTC+12
- { 126, 2886, 6390, 46800 }, // UTC+13
- { 127, 2893, 6435,-16200 }, // Venezuela Standard Time
- { 128, 2917, 7695, 36000 }, // Vladivostok Standard Time
- { 129, 2943, 6482, 14400 }, // Volgograd Standard Time
- { 130, 2967, 6499, 28800 }, // W. Australia Standard Time
- { 131, 2994, 6697, 3600 }, // W. Central Africa Standard Time
- { 132, 3026, 7712, 3600 }, // W. Europe Standard Time
- { 133, 3050, 6982, 25200 }, // W. Mongolia Standard Time
- { 134, 3076, 7726, 18000 }, // West Asia Standard Time
- { 135, 3100, 7740, 7200 }, // West Bank Standard Time
- { 136, 3124, 7255, 36000 }, // West Pacific Standard Time
- { 137, 3151, 7752, 32400 }, // Yakutsk Standard Time
- { 0, 0, 0, 0 } // Trailing zeroes
+ { 29, 700, 1460, 39600 }, // Central Pacific Standard Time
+ { 30, 730, 7475,-21600 }, // Central Standard Time
+ { 31, 752, 7491,-21600 }, // Central Standard Time (Mexico)
+ { 32, 783, 1873, 45900 }, // Chatham Islands Standard Time
+ { 33, 813, 1889, 28800 }, // China Standard Time
+ { 34, 833, 1929,-18000 }, // Cuba Standard Time
+ { 35, 852, 1944,-43200 }, // Dateline Standard Time
+ { 36, 875, 2045, 10800 }, // E. Africa Standard Time
+ { 37, 899, 7511, 36000 }, // E. Australia Standard Time
+ { 38, 926, 2186, 7200 }, // E. Europe Standard Time
+ { 39, 950, 2202,-10800 }, // E. South America Standard Time
+ { 40, 981, 2220,-21600 }, // Easter Island Standard Time
+ { 41, 1009, 7530,-18000 }, // Eastern Standard Time
+ { 42, 1031, 2520,-18000 }, // Eastern Standard Time (Mexico)
+ { 43, 1062, 2535, 7200 }, // Egypt Standard Time
+ { 44, 1082, 2548, 18000 }, // Ekaterinburg Standard Time
+ { 45, 1109, 2567, 43200 }, // Fiji Standard Time
+ { 46, 1128, 7547, 7200 }, // FLE Standard Time
+ { 47, 1146, 2714, 14400 }, // Georgian Standard Time
+ { 48, 1169, 2853, 0 }, // GMT Standard Time
+ { 49, 1187, 2867,-10800 }, // Greenland Standard Time
+ { 50, 1211, 2979, 0 }, // Greenwich Standard Time
+ { 51, 1235, 3163, 7200 }, // GTB Standard Time
+ { 52, 1253, 3180,-18000 }, // Haiti Standard Time
+ { 53, 1273, 3264,-36000 }, // Hawaiian Standard Time
+ { 54, 1296, 3281, 19800 }, // India Standard Time
+ { 55, 1316, 3295, 12600 }, // Iran Standard Time
+ { 56, 1335, 3307, 7200 }, // Israel Standard Time
+ { 57, 1356, 3322, 7200 }, // Jordan Standard Time
+ { 58, 1377, 3333, 7200 }, // Kaliningrad Standard Time
+ { 59, 1403, 3352, 32400 }, // Korea Standard Time
+ { 60, 1423, 3363, 7200 }, // Libya Standard Time
+ { 61, 1443, 3389, 50400 }, // Line Islands Standard Time
+ { 62, 1470, 3408, 37800 }, // Lord Howe Standard Time
+ { 63, 1494, 3428, 36000 }, // Magadan Standard Time
+ { 64, 1516, 3441,-10800 }, // Magallanes Standard Time
+ { 65, 1541, 3462,-34200 }, // Marquesas Standard Time
+ { 66, 1565, 3480, 14400 }, // Mauritius Standard Time
+ { 67, 1589, 3524, 7200 }, // Middle East Standard Time
+ { 68, 1615, 3536,-10800 }, // Montevideo Standard Time
+ { 69, 1640, 3555, 0 }, // Morocco Standard Time
+ { 70, 1662, 7559,-25200 }, // Mountain Standard Time
+ { 71, 1685, 3722,-25200 }, // Mountain Standard Time (Mexico)
+ { 72, 1717, 3752, 23400 }, // Myanmar Standard Time
+ { 73, 1739, 3765, 21600 }, // N. Central Asia Standard Time
+ { 74, 1769, 3782, 3600 }, // Namibia Standard Time
+ { 75, 1791, 3798, 20700 }, // Nepal Standard Time
+ { 76, 1811, 3831, 43200 }, // New Zealand Standard Time
+ { 77, 1837, 3848,-12600 }, // Newfoundland Standard Time
+ { 78, 1864, 3865, 39600 }, // Norfolk Standard Time
+ { 79, 1886, 3881, 28800 }, // North Asia East Standard Time
+ { 80, 1916, 7574, 25200 }, // North Asia Standard Time
+ { 81, 1941, 3929, 30600 }, // North Korea Standard Time
+ { 82, 1967, 3944, 21600 }, // Omsk Standard Time
+ { 83, 1986, 3954,-10800 }, // Pacific SA Standard Time
+ { 84, 2011, 3997,-28800 }, // Pacific Standard Time
+ { 85, 2033, 7591,-28800 }, // Pacific Standard Time (Mexico)
+ { 86, 2064, 4054, 18000 }, // Pakistan Standard Time
+ { 87, 2087, 4067,-14400 }, // Paraguay Standard Time
+ { 88, 2110, 4084, 18000 }, // Qyzylorda Standard Time
+ { 89, 2134, 4133, 3600 }, // Romance Standard Time
+ { 90, 2156, 4173, 39600 }, // Russia Time Zone 10
+ { 91, 2176, 7607, 43200 }, // Russia Time Zone 11
+ { 92, 2196, 4219, 14400 }, // Russia Time Zone 3
+ { 93, 2215, 7622, 10800 }, // Russian Standard Time
+ { 94, 2237, 4421,-10800 }, // SA Eastern Standard Time
+ { 95, 2262, 4539,-18000 }, // SA Pacific Standard Time
+ { 96, 2287, 4690,-14400 }, // SA Western Standard Time
+ { 97, 2312, 5130,-10800 }, // Saint Pierre Standard Time
+ { 98, 2339, 5147, 39600 }, // Sakhalin Standard Time
+ { 99, 2362, 5161, 46800 }, // Samoa Standard Time
+ { 100, 2382, 5174, 0 }, // Sao Tome Standard Time
+ { 101, 2405, 5190, 14400 }, // Saratov Standard Time
+ { 102, 2427, 5308, 25200 }, // SE Asia Standard Time
+ { 103, 2449, 5412, 28800 }, // Singapore Standard Time
+ { 104, 2473, 5561, 7200 }, // South Africa Standard Time
+ { 105, 2500, 5609, 7200 }, // South Sudan Standard Time
+ { 106, 2526, 5621, 19800 }, // Sri Lanka Standard Time
+ { 107, 2550, 5634, 7200 }, // Sudan Standard Time
+ { 108, 2570, 5650, 7200 }, // Syria Standard Time
+ { 109, 2590, 5664, 28800 }, // Taipei Standard Time
+ { 110, 2611, 7636, 36000 }, // Tasmania Standard Time
+ { 111, 2634, 5731,-10800 }, // Tocantins Standard Time
+ { 112, 2658, 5773, 32400 }, // Tokyo Standard Time
+ { 113, 2678, 5808, 25200 }, // Tomsk Standard Time
+ { 114, 2698, 5819, 46800 }, // Tonga Standard Time
+ { 115, 2718, 5837, 32400 }, // Transbaikal Standard Time
+ { 116, 2744, 5848, 7200 }, // Turkey Standard Time
+ { 117, 2765, 5864,-14400 }, // Turks And Caicos Standard Time
+ { 118, 2796, 7653, 28800 }, // Ulaanbaatar Standard Time
+ { 119, 2822, 7670,-18000 }, // US Eastern Standard Time
+ { 120, 2847, 6069,-25200 }, // US Mountain Standard Time
+ { 121, 2873, 7691, 0 }, // UTC
+ { 122, 2877, 6101, 43200 }, // UTC+12
+ { 123, 2884, 6219, 46800 }, // UTC+13
+ { 124, 2891, 6264, -7200 }, // UTC-02
+ { 125, 2898, 6313,-28800 }, // UTC-08
+ { 126, 2905, 6340,-32400 }, // UTC-09
+ { 127, 2912, 6366,-39600 }, // UTC-11
+ { 128, 2919, 6423,-16200 }, // Venezuela Standard Time
+ { 129, 2943, 7699, 36000 }, // Vladivostok Standard Time
+ { 130, 2969, 6470, 14400 }, // Volgograd Standard Time
+ { 131, 2993, 6487, 28800 }, // W. Australia Standard Time
+ { 132, 3020, 6671, 3600 }, // W. Central Africa Standard Time
+ { 133, 3052, 7716, 3600 }, // W. Europe Standard Time
+ { 134, 3076, 6970, 25200 }, // W. Mongolia Standard Time
+ { 135, 3102, 7730, 18000 }, // West Asia Standard Time
+ { 136, 3126, 7744, 7200 }, // West Bank Standard Time
+ { 137, 3150, 7243, 36000 }, // West Pacific Standard Time
+ { 138, 3177, 7756, 32400 }, // Yakutsk Standard Time
+ { 139, 3199, 7769,-25200 }, // Yukon Standard Time
};
// IANA ID Index, UTC Offset
-static const QUtcData utcDataTable[] = {
- { 7765, 0 }, // UTC
- { 7769,-50400 }, // UTC-14:00
- { 7779,-46800 }, // UTC-13:00
- { 7789,-43200 }, // UTC-12:00
- { 7799,-39600 }, // UTC-11:00
- { 7809,-36000 }, // UTC-10:00
- { 7819,-32400 }, // UTC-09:00
- { 7829,-28800 }, // UTC-08:00
- { 7839,-25200 }, // UTC-07:00
- { 7849,-21600 }, // UTC-06:00
- { 7859,-18000 }, // UTC-05:00
- { 7869,-16200 }, // UTC-04:30
- { 7879,-14400 }, // UTC-04:00
- { 7889,-12600 }, // UTC-03:30
- { 7899,-10800 }, // UTC-03:00
- { 7909, -7200 }, // UTC-02:00
- { 7919, -3600 }, // UTC-01:00
- { 7929, 0 }, // UTC-00:00
- { 7939, 0 }, // UTC+00:00
- { 7949, 3600 }, // UTC+01:00
- { 7959, 7200 }, // UTC+02:00
- { 7969, 10800 }, // UTC+03:00
- { 7979, 12600 }, // UTC+03:30
- { 7989, 14400 }, // UTC+04:00
- { 7999, 16200 }, // UTC+04:30
- { 8009, 18000 }, // UTC+05:00
- { 8019, 19800 }, // UTC+05:30
- { 8029, 20700 }, // UTC+05:45
- { 8039, 21600 }, // UTC+06:00
- { 8049, 23400 }, // UTC+06:30
- { 8059, 25200 }, // UTC+07:00
- { 8069, 28800 }, // UTC+08:00
- { 8079, 30600 }, // UTC+08:30
- { 8089, 32400 }, // UTC+09:00
- { 8099, 34200 }, // UTC+09:30
- { 8109, 36000 }, // UTC+10:00
- { 8119, 39600 }, // UTC+11:00
- { 8129, 43200 }, // UTC+12:00
- { 8139, 46800 }, // UTC+13:00
- { 8149, 50400 }, // UTC+14:00
- { 0, 0 } // Trailing zeroes
+static constexpr UtcData utcDataTable[] = {
+ { 7788,-50400 }, // UTC-14:00
+ { 7798,-46800 }, // UTC-13:00
+ { 7808,-43200 }, // UTC-12:00
+ { 7818,-39600 }, // UTC-11:00
+ { 7828,-36000 }, // UTC-10:00
+ { 7838,-32400 }, // UTC-09:00
+ { 7848,-28800 }, // UTC-08:00
+ { 7858,-25200 }, // UTC-07:00
+ { 7868,-21600 }, // UTC-06:00
+ { 7878,-18000 }, // UTC-05:00
+ { 7888,-16200 }, // UTC-04:30
+ { 7898,-14400 }, // UTC-04:00
+ { 7908,-12600 }, // UTC-03:30
+ { 7918,-10800 }, // UTC-03:00
+ { 7928, -7200 }, // UTC-02:00
+ { 7938, -3600 }, // UTC-01:00
+ { 7948, 0 }, // UTC
+ { 7972, 3600 }, // UTC+01:00
+ { 7982, 7200 }, // UTC+02:00
+ { 7992, 10800 }, // UTC+03:00
+ { 8002, 12600 }, // UTC+03:30
+ { 8012, 14400 }, // UTC+04:00
+ { 8022, 16200 }, // UTC+04:30
+ { 8032, 18000 }, // UTC+05:00
+ { 8042, 19800 }, // UTC+05:30
+ { 8052, 20700 }, // UTC+05:45
+ { 8062, 21600 }, // UTC+06:00
+ { 8072, 23400 }, // UTC+06:30
+ { 8082, 25200 }, // UTC+07:00
+ { 8092, 28800 }, // UTC+08:00
+ { 8102, 30600 }, // UTC+08:30
+ { 8112, 32400 }, // UTC+09:00
+ { 8122, 34200 }, // UTC+09:30
+ { 8132, 36000 }, // UTC+10:00
+ { 8142, 39600 }, // UTC+11:00
+ { 8152, 43200 }, // UTC+12:00
+ { 8162, 46800 }, // UTC+13:00
+ { 8172, 50400 }, // UTC+14:00
};
-static const char windowsIdData[] = {
-0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
-0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x73, 0x74,
-0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61,
-0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41,
-0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73,
-0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61,
-0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x6f,
-0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56,
-0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
-0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a,
-0x69, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72,
-0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29,
-0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45,
-0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f,
-0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61,
-0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69,
-0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65,
-0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64,
-0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c,
-0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f, 0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61,
-0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61,
-0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x6e, 0x74, 0x65,
-0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
-0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x79, 0x61,
-0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e,
-0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
-0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77,
-0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73,
-0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74,
-0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69,
-0x63, 0x6f, 0x29, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63,
-0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73,
-0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69,
-0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69,
-0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69,
-0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20,
-0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x53, 0x41, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69,
-0x65, 0x72, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53,
-0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x53, 0x61, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x53, 0x72, 0x69, 0x20, 0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x53, 0x79, 0x72, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x73, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x62, 0x61, 0x69,
-0x6b, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75,
-0x72, 0x6b, 0x65, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54,
-0x75, 0x72, 0x6b, 0x73, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61,
-0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45,
-0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x55, 0x53, 0x20, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39,
-0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x31, 0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65,
-0x6c, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61,
-0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43, 0x65, 0x6e,
-0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69,
-0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74,
-0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0
+static constexpr char windowsIdData[] = {
+0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61,
+0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72,
+0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
+0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
+0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65,
+0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65,
+0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42,
+0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73, 0x68, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61,
+0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e,
+0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56,
+0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x43, 0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41,
+0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69,
+0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x69, 0x61,
+0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e,
+0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74,
+0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61,
+0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x43,
+0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x68, 0x69,
+0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e,
+0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61,
+0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65,
+0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72,
+0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69,
+0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e,
+0x77, 0x69, 0x63, 0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61,
+0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x49, 0x6e, 0x64, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64,
+0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c,
+0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f,
+0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61,
+0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75,
+0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d,
+0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f,
+0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78,
+0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x79, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x2e, 0x20, 0x43, 0x65,
+0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e,
+0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77,
+0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f,
+0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73, 0x74, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74,
+0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f,
+0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0,
+0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x51, 0x79,
+0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73,
+0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0,
+0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65,
+0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20,
+0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20,
+0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53,
+0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69,
+0x65, 0x72, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
+0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73,
+0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72,
+0x69, 0x20, 0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x79, 0x72, 0x69, 0x61, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61,
+0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74,
+0x69, 0x6e, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72,
+0x61, 0x6e, 0x73, 0x62, 0x61, 0x69, 0x6b, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72,
+0x6b, 0x73, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61,
+0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55,
+0x53, 0x20, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43,
+0x2b, 0x31, 0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30,
+0x32, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x0,
+0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56,
+0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72,
+0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x57, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43,
+0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x61, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65,
+0x73, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e, 0x6b, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65,
+0x73, 0x74, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x59,
+0x75, 0x6b, 0x6f, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0
};
-static const char ianaIdData[] = {
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
-0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6e,
-0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74,
-0x6c, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x61,
-0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x41,
-0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68,
-0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73, 0x63, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62,
-0x61, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69,
-0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e,
-0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e,
-0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74,
-0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68,
-0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72,
-0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72,
-0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76,
-0x73, 0x6b, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c,
-0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x0, 0x41,
-0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63, 0x6c, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
-0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
-0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b,
-0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75,
-0x6e, 0x64, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68,
-0x61, 0x6b, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72,
-0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f,
-0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
-0x65, 0x67, 0x69, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f,
-0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x74,
-0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65, 0x0, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
-0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
-0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
-0x36, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69,
-0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x41, 0x6e,
-0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x49, 0x6e, 0x64, 0x69,
-0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71,
-0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51,
-0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72,
-0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72,
-0x61, 0x67, 0x75, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74,
-0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61,
-0x6a, 0x65, 0x76, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6e,
-0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0, 0x50,
-0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
-0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75,
-0x6d, 0x65, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61,
-0x6e, 0x61, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73,
-0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44,
-0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49,
-0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75,
-0x6c, 0x61, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61,
-0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c,
-0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63,
-0x61, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
-0x54, 0x2b, 0x31, 0x32, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x33, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72,
-0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43,
-0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74,
-0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x41, 0x6e, 0x74,
-0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79,
-0x6f, 0x74, 0x74, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68,
-0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61,
-0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
-0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c,
-0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69,
-0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c,
-0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x53, 0x54,
-0x35, 0x45, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, 0x61, 0x6c, 0x75, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70,
-0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72,
-0x74, 0x75, 0x6e, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72,
-0x5f, 0x42, 0x61, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72,
-0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73,
-0x62, 0x75, 0x72, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
-0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49,
-0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c,
-0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c,
-0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x66, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x6b, 0x61, 0x74,
-0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a,
-0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
-0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c,
-0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x69, 0x67, 0x61, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64,
-0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61,
-0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61,
-0x65, 0x72, 0x6f, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79,
-0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
-0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61,
-0x64, 0x65, 0x69, 0x72, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72,
-0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
-0x65, 0x2f, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64,
-0x74, 0x68, 0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61, 0x64, 0x6f, 0x75,
-0x67, 0x6f, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x41, 0x63, 0x63, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79,
-0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
-0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6d,
-0x61, 0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74,
-0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
-0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d,
-0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68,
-0x65, 0x6e, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50, 0x72, 0x69,
-0x6e, 0x63, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
-0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f,
-0x6c, 0x75, 0x6c, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f,
-0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61,
-0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c,
-0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
-0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65,
-0x6f, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x45,
-0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69,
-0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c,
-0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61,
-0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e,
-0x61, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73,
-0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0, 0x49, 0x6e,
-0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f,
-0x4d, 0x61, 0x68, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68,
-0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61,
-0x74, 0x6c, 0x61, 0x6e, 0x0, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61,
-0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f,
-0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61,
-0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43,
-0x6f, 0x63, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x74, 0x6d,
-0x61, 0x6e, 0x64, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75,
-0x72, 0x64, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x50, 0x61,
-0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49,
-0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61,
-0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73,
-0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69,
-0x61, 0x67, 0x6f, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61,
-0x77, 0x73, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f,
-0x72, 0x73, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65,
-0x6c, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c,
-0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, 0x69, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79, 0x7a, 0x79,
-0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c,
-0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0,
-0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0,
-0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53,
-0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
-0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0,
-0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
-0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65, 0x72,
-0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72,
-0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x20, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63,
-0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65,
-0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6d, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
-0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65,
-0x6e, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69,
-0x62, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72,
-0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
-0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69,
-0x6d, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e,
-0x74, 0x69, 0x67, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62, 0x61, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
-0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56,
-0x65, 0x6c, 0x68, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53,
-0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69,
-0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d,
-0x69, 0x6e, 0x67, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65,
-0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f,
-0x4b, 0x69, 0x74, 0x74, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63,
-0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e,
-0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x53, 0x70,
-0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c, 0x65, 0x6d, 0x79, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53,
-0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61,
-0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72,
-0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
-0x37, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0, 0x41,
-0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
-0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b,
-0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0,
-0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61,
-0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x41,
-0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75,
-0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63, 0x68,
-0x69, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61,
-0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32,
-0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
-0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72,
-0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68,
-0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61,
-0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f,
-0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75,
-0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61,
-0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f,
-0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69,
-0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, 0x61, 0x0,
-0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
-0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41,
-0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f,
-0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55,
-0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69,
-0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
-0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
-0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
-0x54, 0x2b, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43,
-0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e,
-0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x45, 0x74, 0x63, 0x2f,
-0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f,
-0x50, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x50, 0x61,
-0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
-0x2b, 0x39, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x45,
-0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74,
-0x63, 0x61, 0x69, 0x72, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
-0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
-0x4d, 0x54, 0x20, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
-0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
-0x31, 0x32, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0, 0x50, 0x61,
-0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
-0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e,
-0x61, 0x75, 0x72, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74,
-0x69, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33,
-0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0, 0x50,
-0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64,
-0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72,
-0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41,
-0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
-0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0,
-0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
-0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x75, 0x69, 0x0,
-0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
-0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61,
-0x6c, 0x61, 0x62, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c,
-0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79, 0x0, 0x41, 0x66, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e,
-0x69, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
-0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x65,
-0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61,
-0x64, 0x75, 0x7a, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72,
-0x67, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
-0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74,
-0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x41, 0x72, 0x63, 0x74,
-0x69, 0x63, 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61,
-0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
-0x35, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0,
-0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e, 0x0, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61,
-0x75, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68,
-0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x20,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x74, 0x63,
-0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44,
-0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
-0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0,
-0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61,
-0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79,
-0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65,
-0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
-0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
-0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
-0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f,
-0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
-0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
-0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
-0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62,
-0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
-0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
-0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b,
-0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
-0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
+static constexpr char ianaIdData[] = {
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e,
+0x61, 0x75, 0x6c, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79,
+0x61, 0x64, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0, 0x45, 0x74,
+0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73,
+0x63, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73,
+0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
+0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69,
+0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c,
+0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
+0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
+0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d,
+0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
+0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0, 0x41,
+0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
+0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f,
+0x42, 0x61, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63,
+0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c,
+0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x77,
+0x69, 0x6e, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63,
+0x6c, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64,
+0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65,
+0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b,
+0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73,
+0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
+0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
+0x61, 0x68, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
+0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, 0x75, 0x72, 0x72,
+0x65, 0x6e, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x74,
+0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64,
+0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x41,
+0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64,
+0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x6f, 0x6b,
+0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x36, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52,
+0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61,
+0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c,
+0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0,
+0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63,
+0x74, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x49, 0x6e, 0x64, 0x69,
+0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55,
+0x72, 0x75, 0x6d, 0x71, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74,
+0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61, 0x79, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, 0x6f,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
+0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50,
+0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x6f,
+0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75,
+0x6d, 0x65, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64,
+0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
+0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f, 0x52, 0x69, 0x76,
+0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69,
+0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f,
+0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
+0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x43, 0x65, 0x6e,
+0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74,
+0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c,
+0x65, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63,
+0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
+0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61,
+0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x31, 0x32, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x33, 0x0, 0x41, 0x6e, 0x74,
+0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x49, 0x6e,
+0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, 0x0, 0x49, 0x6e, 0x64, 0x69,
+0x61, 0x6e, 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0,
+0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61,
+0x6c, 0x61, 0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70,
+0x61, 0x6c, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72,
+0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
+0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69,
+0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45,
+0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61,
+0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74,
+0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, 0x61, 0x6c, 0x75, 0x69,
+0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
+0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67,
+0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e,
+0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54,
+0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65,
+0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49,
+0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73,
+0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
+0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63,
+0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75,
+0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61,
+0x69, 0x72, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x6b, 0x61, 0x74, 0x65, 0x72,
+0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46,
+0x69, 0x6a, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65,
+0x68, 0x61, 0x6d, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69,
+0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x69, 0x67, 0x61, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55,
+0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a,
+0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
+0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
+0x46, 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x75,
+0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x44, 0x75,
+0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65,
+0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a,
+0x65, 0x72, 0x73, 0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73,
+0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64,
+0x65, 0x69, 0x72, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61,
+0x6e, 0x61, 0x72, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64,
+0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64, 0x74, 0x68,
+0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61, 0x64,
+0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
+0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, 0x61,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b,
+0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73,
+0x73, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b,
+0x72, 0x79, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b,
+0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69,
+0x64, 0x6a, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72,
+0x6f, 0x76, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6d, 0x61,
+0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63,
+0x68, 0x6f, 0x74, 0x74, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74,
+0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
+0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x72, 0x65, 0x65,
+0x74, 0x6f, 0x77, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x20, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50, 0x72, 0x69, 0x6e,
+0x63, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x50, 0x61,
+0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0,
+0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0,
+0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c, 0x75,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41,
+0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69,
+0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f,
+0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c,
+0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0,
+0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48,
+0x6f, 0x77, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41,
+0x72, 0x65, 0x6e, 0x61, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61,
+0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
+0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f,
+0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
+0x61, 0x68, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64,
+0x65, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c,
+0x61, 0x6e, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41,
+0x61, 0x69, 0x75, 0x6e, 0x0, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f,
+0x42, 0x61, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76,
+0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f,
+0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
+0x69, 0x75, 0x64, 0x61, 0x64, 0x5f, 0x4a, 0x75, 0x61, 0x72, 0x65, 0x7a, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
+0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e,
+0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x73, 0x69,
+0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e,
+0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x74, 0x6d, 0x61,
+0x6e, 0x64, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d,
+0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41,
+0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72,
+0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
+0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
+0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79,
+0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73,
+0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61,
+0x67, 0x6f, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61,
+0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49,
+0x73, 0x61, 0x62, 0x65, 0x6c, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63,
+0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63,
+0x69, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72,
+0x64, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65,
+0x6c, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68,
+0x61, 0x67, 0x65, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, 0x69,
+0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x20,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
+0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69,
+0x72, 0x6f, 0x76, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65,
+0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0,
+0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65,
+0x72, 0x61, 0x20, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61,
+0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72,
+0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
+0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63,
+0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69,
+0x66, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61,
+0x72, 0x65, 0x6d, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61,
+0x6e, 0x6c, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79,
+0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72,
+0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72,
+0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72,
+0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f,
+0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c,
+0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67,
+0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62, 0x61,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f,
+0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56, 0x69, 0x73, 0x74,
+0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f,
+0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f,
+0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c,
+0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d,
+0x69, 0x6e, 0x67, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65,
+0x6e, 0x61, 0x64, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61,
+0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
+0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74,
+0x68, 0x65, 0x6c, 0x65, 0x6d, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
+0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65,
+0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f,
+0x66, 0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f,
+0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72,
+0x61, 0x74, 0x6f, 0x76, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x41,
+0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0,
+0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61,
+0x69, 0x67, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75,
+0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6e,
+0x69, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f,
+0x72, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68, 0x69, 0x0,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62,
+0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75,
+0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0, 0x41, 0x75, 0x73, 0x74,
+0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73,
+0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69, 0x65, 0x20, 0x41, 0x6e,
+0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72,
+0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75,
+0x61, 0x69, 0x6e, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
+0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49,
+0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73,
+0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
+0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0, 0x45,
+0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f,
+0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73,
+0x69, 0x6c, 0x6c, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f,
+0x65, 0x6e, 0x69, 0x78, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x20, 0x45, 0x74, 0x63,
+0x2f, 0x47, 0x4d, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x32, 0x0,
+0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x20, 0x50, 0x61,
+0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0,
+0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x50, 0x61,
+0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69,
+0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
+0x4d, 0x54, 0x2d, 0x31, 0x33, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e,
+0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
+0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68,
+0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68,
+0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
+0x2b, 0x38, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, 0x61,
+0x69, 0x72, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0, 0x50, 0x61,
+0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x45, 0x74,
+0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
+0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
+0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64,
+0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74,
+0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c,
+0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31,
+0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x75, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e,
+0x64, 0x6f, 0x72, 0x72, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65,
+0x6e, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69,
+0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x65,
+0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74,
+0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
+0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
+0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e,
+0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, 0x2f, 0x4c,
+0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48,
+0x6f, 0x76, 0x64, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x35, 0x0, 0x41, 0x6e,
+0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0,
+0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62,
+0x65, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61, 0x75, 0x0, 0x49, 0x6e,
+0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
+0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d,
+0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72,
+0x6f, 0x6e, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
+0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c,
+0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69,
+0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69,
+0x72, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61,
+0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c,
+0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53,
+0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65,
+0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41,
+0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d,
+0x61, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61,
+0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61,
+0x67, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63,
+0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
+0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
+0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54,
+0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63,
+0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73,
+0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f,
+0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62,
+0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
+0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x55,
+0x54, 0x43, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73,
+0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69,
+0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d,
+0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0,
+0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31,
+0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54,
+0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30,
+0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d,
+0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0,
+0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34,
+0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54,
+0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30,
+0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x20,
+0x55, 0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x20, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30,
+0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54,
+0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30,
+0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b,
+0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0,
+0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35,
+0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55, 0x54,
+0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33,
+0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b,
+0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0,
+0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39,
+0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54,
+0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30,
+0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b,
+0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
};
// GENERATED PART ENDS HERE
+constexpr QByteArrayView WindowsData::windowsId() const { return windowsIdData + windowsIdIndex; }
+// Each of the following returns a space-joined sequence of IANA IDs:
+constexpr QByteArrayView WindowsData::ianaId() const { return ianaIdData + ianaIdIndex; }
+constexpr QByteArrayView UtcData::id() const { return ianaIdData + ianaIdIndex; }
+constexpr QLatin1StringView ZoneData::id() const
+{ return QLatin1StringView(ianaIdData + ianaIdIndex); }
+
+} // namespace QtTimeZoneCldr
+
QT_END_NAMESPACE
#endif // QTIMEZONEPRIVATE_DATA_P_H
diff --git a/src/corelib/time/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp
index 33518994d1..1a3baa70d0 100644
--- a/src/corelib/time/qtimezoneprivate_icu.cpp
+++ b/src/corelib/time/qtimezoneprivate_icu.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
@@ -182,14 +147,13 @@ static bool ucalOffsetsAtTime(UCalendar *m_ucal, qint64 atMSecsSinceEpoch,
return false;
}
-// ICU Draft api in v50, should be stable in ICU v51. Available in C++ api from ICU v3.8
-#if U_ICU_VERSION_MAJOR_NUM == 50
+#if U_ICU_VERSION_MAJOR_NUM >= 50
// Qt wrapper around qt_ucal_getTimeZoneTransitionDate & ucal_get
static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal,
UTimeZoneTransitionType type,
qint64 atMSecsSinceEpoch)
{
- QTimeZonePrivate::Data tran = QTimeZonePrivate::invalidData();
+ QTimeZonePrivate::Data tran;
// Clone the ucal so we don't change the shared object
UErrorCode status = U_ZERO_ERROR;
@@ -206,6 +170,14 @@ static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal,
status = U_ZERO_ERROR;
bool ok = ucal_getTimeZoneTransitionDate(ucal, type, &tranMSecs, &status);
+ // Catch a known violation (in ICU 67) of the specified behavior:
+ if (U_SUCCESS(status) && ok && type == UCAL_TZ_TRANSITION_NEXT) {
+ // At the end of time, that can "succeed" with tranMSecs ==
+ // atMSecsSinceEpoch, which should be treated as a failure.
+ // (At the start of time, previous correctly fails.)
+ ok = qint64(tranMSecs) > atMSecsSinceEpoch;
+ }
+
// Set the transition time to find the offsets for
if (U_SUCCESS(status) && ok) {
status = U_ZERO_ERROR;
@@ -264,18 +236,17 @@ static QList<QByteArray> uenumToIdList(UEnumeration *uenum)
static int ucalDaylightOffset(const QByteArray &id)
{
UErrorCode status = U_ZERO_ERROR;
- const int32_t dstMSecs = ucal_getDSTSavings(reinterpret_cast<const UChar *>(id.data()), &status);
- if (U_SUCCESS(status))
- return (dstMSecs / 1000);
- else
- return 0;
+ const QString utf16 = QString::fromLatin1(id);
+ const int32_t dstMSecs = ucal_getDSTSavings(
+ reinterpret_cast<const UChar *>(utf16.data()), &status);
+ return U_SUCCESS(status) ? dstMSecs / 1000 : 0;
}
// Create the system default time zone
QIcuTimeZonePrivate::QIcuTimeZonePrivate()
: m_ucal(nullptr)
{
- // TODO No ICU C API to obtain sysem tz, assume default hasn't been changed
+ // TODO No ICU C API to obtain system tz, assume default hasn't been changed
init(ucalDefaultTimeZoneId());
}
@@ -283,8 +254,8 @@ QIcuTimeZonePrivate::QIcuTimeZonePrivate()
QIcuTimeZonePrivate::QIcuTimeZonePrivate(const QByteArray &ianaId)
: m_ucal(nullptr)
{
- // Need to check validity here as ICu will create a GMT tz if name is invalid
- if (availableTimeZoneIds().contains(ianaId))
+ // ICU misleadingly maps invalid IDs to GMT.
+ if (isTimeZoneIdAvailable(ianaId))
init(ianaId);
}
@@ -330,28 +301,25 @@ QString QIcuTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- // Return standard offset format name as ICU C api doesn't support it yet
+ // Base class has handled OffsetName if we came via the other overload.
if (nameType == QTimeZone::OffsetName) {
- const Data nowData = data(QDateTime::currentMSecsSinceEpoch());
- // We can't use transitions reliably to find out right dst offset
- // Instead use dst offset api to try get it if needed
+ int offset = standardTimeOffset(QDateTime::currentMSecsSinceEpoch());
+ // We can't use transitions reliably to find out right DST offset.
+ // Instead use DST offset API to try to get it, when needed:
if (timeType == QTimeZone::DaylightTime)
- return isoOffsetFormat(nowData.standardTimeOffset + ucalDaylightOffset(m_id));
- else
- return isoOffsetFormat(nowData.standardTimeOffset);
+ offset += ucalDaylightOffset(m_id);
+ // This is only valid for times since the most recent standard offset
+ // change; for earlier times, caller must use the other overload.
+
+ // Use our own formating for offset names (ICU C API doesn't support it
+ // and we may as well be self-consistent anyway).
+ return isoOffsetFormat(offset);
}
+ // Technically this may be suspect, if locale isn't QLocale(), since that's
+ // what we used when constructing m_ucal; does ICU cope with inconsistency ?
return ucalTimeZoneDisplayName(m_ucal, timeType, nameType, locale.name());
}
-QString QIcuTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
-{
- // TODO No ICU API, use short name instead
- if (isDaylightTime(atMSecsSinceEpoch))
- return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QLocale());
- else
- return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QLocale());
-}
-
int QIcuTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
{
int stdOffset = 0;
@@ -378,8 +346,17 @@ int QIcuTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
bool QIcuTimeZonePrivate::hasDaylightTime() const
{
- // TODO No direct ICU C api, work-around below not reliable? Find a better way?
- return (ucalDaylightOffset(m_id) != 0);
+ if (ucalDaylightOffset(m_id) != 0)
+ return true;
+#if U_ICU_VERSION_MAJOR_NUM >= 50
+ for (qint64 when = minMSecs(); when != invalidMSecs(); ) {
+ auto data = nextTransition(when);
+ if (data.daylightTimeOffset && data.daylightTimeOffset != invalidSeconds())
+ return true;
+ when = data.atMSecsSinceEpoch;
+ }
+#endif
+ return false;
}
bool QIcuTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
@@ -407,17 +384,18 @@ bool QIcuTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
QTimeZonePrivate::Data QIcuTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
// Available in ICU C++ api, and draft C api in v50
- // TODO When v51 released see if api is stable
- QTimeZonePrivate::Data data = invalidData();
-#if U_ICU_VERSION_MAJOR_NUM == 50
+ QTimeZonePrivate::Data data;
+#if U_ICU_VERSION_MAJOR_NUM >= 50
data = ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE,
forMSecsSinceEpoch);
-#else
- ucalOffsetsAtTime(m_ucal, forMSecsSinceEpoch, &data.standardTimeOffset,
- &data.daylightTimeOffset);
- data.offsetFromUtc = data.standardTimeOffset + data.daylightTimeOffset;
- data.abbreviation = abbreviation(forMSecsSinceEpoch);
-#endif // U_ICU_VERSION_MAJOR_NUM == 50
+ if (data.atMSecsSinceEpoch == invalidMSecs()) // before first transition
+#endif
+ {
+ ucalOffsetsAtTime(m_ucal, forMSecsSinceEpoch, &data.standardTimeOffset,
+ &data.daylightTimeOffset);
+ data.offsetFromUtc = data.standardTimeOffset + data.daylightTimeOffset;
+ data.abbreviation = abbreviation(forMSecsSinceEpoch);
+ }
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
return data;
}
@@ -425,45 +403,61 @@ QTimeZonePrivate::Data QIcuTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
bool QIcuTimeZonePrivate::hasTransitions() const
{
// Available in ICU C++ api, and draft C api in v50
- // TODO When v51 released see if api is stable
-#if U_ICU_VERSION_MAJOR_NUM == 50
+#if U_ICU_VERSION_MAJOR_NUM >= 50
return true;
#else
return false;
-#endif // U_ICU_VERSION_MAJOR_NUM == 50
+#endif
}
QTimeZonePrivate::Data QIcuTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
{
// Available in ICU C++ api, and draft C api in v50
- // TODO When v51 released see if api is stable
-#if U_ICU_VERSION_MAJOR_NUM == 50
+#if U_ICU_VERSION_MAJOR_NUM >= 50
return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_NEXT, afterMSecsSinceEpoch);
#else
- Q_UNUSED(afterMSecsSinceEpoch)
- return invalidData();
-#endif // U_ICU_VERSION_MAJOR_NUM == 50
+ Q_UNUSED(afterMSecsSinceEpoch);
+ return {};
+#endif
}
QTimeZonePrivate::Data QIcuTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
// Available in ICU C++ api, and draft C api in v50
- // TODO When v51 released see if api is stable
-#if U_ICU_VERSION_MAJOR_NUM == 50
+#if U_ICU_VERSION_MAJOR_NUM >= 50
return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS, beforeMSecsSinceEpoch);
#else
- Q_UNUSED(beforeMSecsSinceEpoch)
- return invalidData();
-#endif // U_ICU_VERSION_MAJOR_NUM == 50
+ Q_UNUSED(beforeMSecsSinceEpoch);
+ return {};
+#endif
}
QByteArray QIcuTimeZonePrivate::systemTimeZoneId() const
{
- // No ICU C API to obtain sysem tz
+ // No ICU C API to obtain system tz
// TODO Assume default hasn't been changed and is the latests system
return ucalDefaultTimeZoneId();
}
+bool QIcuTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
+{
+ const QString ianaStr = QString::fromUtf8(ianaId);
+ const UChar *const name = reinterpret_cast<const UChar *>(ianaStr.constData());
+ // We are not interested in the value, but we have to pass something.
+ // No known IANA zone name is (up to 2023) longer than 30 characters.
+ constexpr size_t size = 64;
+ UChar buffer[size];
+
+ // TODO: convert to ucal_getIanaTimeZoneID(), new draft in ICU 74, once we
+ // can rely on its availability, assuming it works the same once not draft.
+ UErrorCode status = U_ZERO_ERROR;
+ UBool isSys = false;
+ // Returns the length of the IANA zone name (but we don't care):
+ ucal_getCanonicalTimeZoneID(name, ianaStr.size(), buffer, size, &isSys, &status);
+ // We're only interested if the result is a "system" (i.e. IANA) ID:
+ return isSys;
+}
+
QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds() const
{
UErrorCode status = U_ZERO_ERROR;
@@ -475,9 +469,9 @@ QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds() const
return result;
}
-QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
+QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Territory territory) const
{
- const QLatin1String regionCode = QLocalePrivate::countryToCode(country);
+ const QLatin1StringView regionCode = QLocalePrivate::territoryToCode(territory);
const QByteArray regionCodeUtf8 = QString(regionCode).toUtf8();
UErrorCode status = U_ZERO_ERROR;
UEnumeration *uenum = ucal_openCountryTimeZones(regionCodeUtf8.data(), &status);
diff --git a/src/corelib/time/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm
index 1fb48a31d3..da7e24d614 100644
--- a/src/corelib/time/qtimezoneprivate_mac.mm
+++ b/src/corelib/time/qtimezoneprivate_mac.mm
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
@@ -55,7 +19,8 @@ QT_BEGIN_NAMESPACE
/*
Private
- OS X system implementation
+ Darwin system implementation
+ https://developer.apple.com/documentation/foundation/nstimezone
*/
// Create the system default time zone
@@ -92,12 +57,10 @@ QMacTimeZonePrivate *QMacTimeZonePrivate::clone() const
void QMacTimeZonePrivate::init(const QByteArray &ianaId)
{
- if (availableTimeZoneIds().contains(ianaId)) {
- m_nstz = [[NSTimeZone timeZoneWithName:QString::fromUtf8(ianaId).toNSString()] retain];
- if (m_nstz)
- m_id = ianaId;
- }
- if (!m_nstz) {
+ m_nstz = [[NSTimeZone timeZoneWithName:QString::fromUtf8(ianaId).toNSString()] retain];
+ if (m_nstz) {
+ m_id = ianaId;
+ } else {
// macOS has been seen returning a systemTimeZone which reports its name
// as Asia/Kolkata, which doesn't appear in knownTimeZoneNames (which
// calls the zone Asia/Calcutta). So explicitly check for the name
@@ -149,7 +112,7 @@ QString QMacTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
style = NSTimeZoneNameStyleStandard;
break;
case QTimeZone::OffsetName :
- // Unreachable
+ Q_UNREACHABLE();
break;
}
@@ -185,7 +148,7 @@ int QMacTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
bool QMacTimeZonePrivate::hasDaylightTime() const
{
- // TODO No Mac API, assume if has transitions
+ // TODO Scan transitions for one after which isDaylightSavingTimeForDate is true.
return hasTransitions();
}
@@ -227,7 +190,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
const NSTimeInterval nextSecs = nextDate.timeIntervalSince1970;
if (nextDate == nil || nextSecs <= seconds) {
[nextDate release];
- return invalidData();
+ return {};
}
tran.atMSecsSinceEpoch = nextSecs * 1000;
tran.offsetFromUtc = [m_nstz secondsFromGMTForDate:nextDate];
@@ -240,7 +203,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
// The native API only lets us search forward, so we need to find an early-enough start:
- const NSTimeInterval lowerBound = std::numeric_limits<NSTimeInterval>::lowest();
+ constexpr NSTimeInterval lowerBound = std::numeric_limits<NSTimeInterval>::lowest();
const qint64 endSecs = beforeMSecsSinceEpoch / 1000;
const int year = 366 * 24 * 3600; // a (long) year, in seconds
NSTimeInterval prevSecs = endSecs; // sentinel for later check
@@ -310,7 +273,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSec
return data(qint64(prevSecs * 1e3));
// No transition data; or first transition later than requested time.
- return invalidData();
+ return {};
}
QByteArray QMacTimeZonePrivate::systemTimeZoneId() const
@@ -321,6 +284,12 @@ QByteArray QMacTimeZonePrivate::systemTimeZoneId() const
return QString::fromNSString(NSTimeZone.systemTimeZone.name).toUtf8();
}
+bool QMacTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const
+{
+ QMacAutoReleasePool pool;
+ return [NSTimeZone timeZoneWithName:QString::fromUtf8(ianaId).toNSString()] != nil;
+}
+
QList<QByteArray> QMacTimeZonePrivate::availableTimeZoneIds() const
{
NSEnumerator *enumerator = NSTimeZone.knownTimeZoneNames.objectEnumerator;
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 3f08fc15a6..506acaa1f7 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTIMEZONEPRIVATE_P_H
@@ -55,6 +20,7 @@
#include "qlist.h"
#include "qtimezone.h"
#include "private/qlocale_p.h"
+#include "private/qdatetime_p.h"
#if QT_CONFIG(icu)
#include <unicode/ucal.h>
@@ -68,22 +34,36 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
#include <qt_windows.h>
#endif // Q_OS_WIN
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
-#include <QtCore/private/qjni_p.h>
+#ifdef Q_OS_ANDROID
+#include <QJniObject>
#endif
+QT_REQUIRE_CONFIG(timezone);
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
{
public:
- //Version of QTimeZone::OffsetData struct using msecs for efficiency
+ // Version of QTimeZone::OffsetData struct using msecs for efficiency
struct Data {
QString abbreviation;
qint64 atMSecsSinceEpoch;
int offsetFromUtc;
int standardTimeOffset;
int daylightTimeOffset;
+ Data()
+ : atMSecsSinceEpoch(QTimeZonePrivate::invalidMSecs()),
+ offsetFromUtc(QTimeZonePrivate::invalidSeconds()),
+ standardTimeOffset(QTimeZonePrivate::invalidSeconds()),
+ daylightTimeOffset(QTimeZonePrivate::invalidSeconds())
+ {}
+ Data(const QString &name, qint64 when, int offset, int standard)
+ : abbreviation(name),
+ atMSecsSinceEpoch(when),
+ offsetFromUtc(offset),
+ standardTimeOffset(standard),
+ daylightTimeOffset(offset - standard)
+ {}
};
typedef QList<Data> DataList;
@@ -100,7 +80,7 @@ public:
bool isValid() const;
QByteArray id() const;
- virtual QLocale::Country country() const;
+ virtual QLocale::Territory territory() const;
virtual QString comment() const;
virtual QString displayName(qint64 atMSecsSinceEpoch,
@@ -119,7 +99,8 @@ public:
virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
virtual Data data(qint64 forMSecsSinceEpoch) const;
- Data dataForLocalTime(qint64 forLocalMSecs, int hint) const;
+ QDateTimePrivate::ZoneState stateAtZoneTime(qint64 forLocalMSecs,
+ QDateTimePrivate::TransitionOptions resolve) const;
virtual bool hasTransitions() const;
virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const;
@@ -130,37 +111,41 @@ public:
virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const;
virtual QList<QByteArray> availableTimeZoneIds() const;
- virtual QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const;
+ virtual QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const;
virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const;
virtual void serialize(QDataStream &ds) const;
// Static Utility Methods
- static inline qint64 maxMSecs() { return std::numeric_limits<qint64>::max(); }
- static inline qint64 minMSecs() { return std::numeric_limits<qint64>::min() + 1; }
- static inline qint64 invalidMSecs() { return std::numeric_limits<qint64>::min(); }
- static inline qint64 invalidSeconds() { return std::numeric_limits<int>::min(); }
- static Data invalidData();
+ [[nodiscard]] static constexpr qint64 maxMSecs()
+ { return (std::numeric_limits<qint64>::max)(); }
+ [[nodiscard]] static constexpr qint64 minMSecs()
+ { return (std::numeric_limits<qint64>::min)() + 1; }
+ [[nodiscard]] static constexpr qint64 invalidMSecs()
+ { return (std::numeric_limits<qint64>::min)(); }
+ [[nodiscard]] static constexpr qint64 invalidSeconds()
+ { return (std::numeric_limits<int>::min)(); }
static QTimeZone::OffsetData invalidOffsetData();
static QTimeZone::OffsetData toOffsetData(const Data &data);
static bool isValidId(const QByteArray &ianaId);
- static QString isoOffsetFormat(int offsetFromUtc);
+ static QString isoOffsetFormat(int offsetFromUtc,
+ QTimeZone::NameType mode = QTimeZone::OffsetName);
static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
- QLocale::Country country);
+ QLocale::Territory territory);
static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId);
static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
- QLocale::Country country);
+ QLocale::Territory territory);
// returns "UTC" QString and QByteArray
- Q_REQUIRED_RESULT static inline QString utcQString()
+ [[nodiscard]] static inline QString utcQString()
{
return QStringLiteral("UTC");
}
- Q_REQUIRED_RESULT static inline QByteArray utcQByteArray()
+ [[nodiscard]] static inline QByteArray utcQByteArray()
{
return QByteArrayLiteral("UTC");
}
@@ -168,7 +153,7 @@ public:
protected:
QByteArray m_id;
};
-Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_RELOCATABLE_TYPE);
template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone();
@@ -180,24 +165,25 @@ public:
// Create named time zone
QUtcTimeZonePrivate(const QByteArray &utcId);
// Create offset from UTC
- QUtcTimeZonePrivate(int offsetSeconds);
+ QUtcTimeZonePrivate(qint32 offsetSeconds);
// Create custom offset from UTC
QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds, const QString &name,
- const QString &abbreviation, QLocale::Country country,
+ const QString &abbreviation, QLocale::Territory territory,
const QString &comment);
QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
virtual ~QUtcTimeZonePrivate();
// Fall-back for UTC[+-]\d+(:\d+){,2} IDs.
- static qint64 offsetFromUtcString(const QByteArray &id);
+ static qint64 offsetFromUtcString(QByteArrayView id);
QUtcTimeZonePrivate *clone() const override;
Data data(qint64 forMSecsSinceEpoch) const override;
- QLocale::Country country() const override;
+ QLocale::Territory territory() const override;
QString comment() const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const override;
@@ -210,7 +196,7 @@ public:
bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
- QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override;
+ QList<QByteArray> availableTimeZoneIds(QLocale::Territory country) const override;
QList<QByteArray> availableTimeZoneIds(int utcOffset) const override;
void serialize(QDataStream &ds) const override;
@@ -218,16 +204,19 @@ public:
private:
void init(const QByteArray &zoneId);
void init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
- const QString &abbreviation, QLocale::Country country,
+ const QString &abbreviation, QLocale::Territory territory,
const QString &comment);
QString m_name;
QString m_abbreviation;
QString m_comment;
- QLocale::Country m_country;
+ QLocale::Territory m_territory;
int m_offsetFromUtc;
};
+// TODO: shuffle (almost reverse) order of and rework #if-ery here to use #elif
+// and match the #if-ery in each of QTZ's newBackendTimeZone() cascades for
+// backend selection.
#if QT_CONFIG(icu)
class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
{
@@ -241,9 +230,9 @@ public:
QIcuTimeZonePrivate *clone() const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const override;
- QString abbreviation(qint64 atMSecsSinceEpoch) const override;
int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
@@ -260,8 +249,9 @@ public:
QByteArray systemTimeZoneId() const override;
+ bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
- QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override;
+ QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const override;
QList<QByteArray> availableTimeZoneIds(int offsetFromUtc) const override;
private:
@@ -269,9 +259,9 @@ private:
UCalendar *m_ucal;
};
-#endif
+#endif // ICU
-#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED))
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID)
struct QTzTransitionTime
{
qint64 atMSecsSinceEpoch;
@@ -280,14 +270,14 @@ struct QTzTransitionTime
Q_DECLARE_TYPEINFO(QTzTransitionTime, Q_PRIMITIVE_TYPE);
struct QTzTransitionRule
{
- int stdOffset;
- int dstOffset;
- quint8 abbreviationIndex;
+ int stdOffset = 0;
+ int dstOffset = 0;
+ quint8 abbreviationIndex = 0;
};
Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
+constexpr inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
{ return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; }
-Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
+constexpr inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
{ return !operator==(lhs, rhs); }
// These are stored separately from QTzTimeZonePrivate so that they can be
@@ -298,6 +288,8 @@ struct QTzTimeZoneCacheEntry
QList<QTzTransitionRule> m_tranRules;
QList<QByteArray> m_abbreviations;
QByteArray m_posixRule;
+ QTzTransitionRule m_preZoneRule;
+ bool m_hasDst = false;
};
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
@@ -312,12 +304,10 @@ public:
QTzTimeZonePrivate *clone() const override;
- QLocale::Country country() const override;
+ QLocale::Territory territory() const override;
QString comment() const override;
- QString displayName(qint64 atMSecsSinceEpoch,
- QTimeZone::NameType nameType,
- const QLocale &locale) const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const override;
@@ -340,22 +330,28 @@ public:
bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
- QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override;
+ QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const override;
private:
- void init(const QByteArray &ianaId);
+ static QByteArray staticSystemTimeZoneId();
QList<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const;
Data dataForTzTransition(QTzTransitionTime tran) const;
+ Data dataFromRule(QTzTransitionRule rule, qint64 msecsSinceEpoch) const;
#if QT_CONFIG(icu)
- mutable QSharedDataPointer<QTimeZonePrivate> m_icu;
+# ifdef __cpp_lib_is_final
+ static_assert(std::is_final<QIcuTimeZonePrivate>::value,
+ "if QIcuTimeZonePrivate isn't final, we may need to specialize "
+ "QExplicitlySharedDataPointer::clone() to call QTimeZonePrivate::clone()");
+# endif
+ mutable QExplicitlySharedDataPointer<const QIcuTimeZonePrivate> m_icu;
#endif
QTzTimeZoneCacheEntry cached_data;
- QList<QTzTransitionTime> tranCache() const { return cached_data.m_tranTimes; }
+ const QList<QTzTransitionTime> &tranCache() const { return cached_data.m_tranTimes; }
};
#endif // Q_OS_UNIX
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
{
public:
@@ -370,6 +366,7 @@ public:
QString comment() const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const override;
QString abbreviation(qint64 atMSecsSinceEpoch) const override;
@@ -388,7 +385,7 @@ public:
Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
QByteArray systemTimeZoneId() const override;
-
+ bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
NSTimeZone *nsTimeZone() const;
@@ -398,9 +395,9 @@ private:
NSTimeZone *m_nstz;
};
-#endif // Q_OS_MAC
+#endif // Q_OS_DARWIN
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) && !QT_CONFIG(icu)
class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
{
public:
@@ -423,6 +420,7 @@ public:
QString comment() const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const override;
QString abbreviation(qint64 atMSecsSinceEpoch) const override;
@@ -444,10 +442,11 @@ public:
QList<QByteArray> availableTimeZoneIds() const override;
-private:
- void init(const QByteArray &ianaId);
+ // For use within implementation's TransitionTimePair:
QTimeZonePrivate::Data ruleToData(const QWinTransitionRule &rule, qint64 atMSecsSinceEpoch,
QTimeZone::TimeType type, bool fakeDst = false) const;
+private:
+ void init(const QByteArray &ianaId);
QByteArray m_windowsId;
QString m_displayName;
@@ -455,9 +454,9 @@ private:
QString m_daylightName;
QList<QWinTransitionRule> m_tranRules;
};
-#endif // Q_OS_WIN
+#endif // Q_OS_WIN && !icu
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
class QAndroidTimeZonePrivate final : public QTimeZonePrivate
{
public:
@@ -470,6 +469,7 @@ public:
QAndroidTimeZonePrivate *clone() const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const override;
QString abbreviation(qint64 atMSecsSinceEpoch) const override;
@@ -483,18 +483,14 @@ public:
Data data(qint64 forMSecsSinceEpoch) const override;
- bool hasTransitions() const override;
- Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
- Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
-
QByteArray systemTimeZoneId() const override;
-
+ bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
private:
void init(const QByteArray &zoneId);
- QJNIObjectPrivate androidTimeZone;
+ QJniObject androidTimeZone;
};
#endif // Q_OS_ANDROID
diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
index 7a31677db0..f6156fe93e 100644
--- a/src/corelib/time/qtimezoneprivate_tz.cpp
+++ b/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -1,58 +1,27 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2019 Crimson AS <info@crimson.no>
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2019 Crimson AS <info@crimson.no>
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
#include "private/qlocale_tools_p.h"
+#include "private/qlocking_p.h"
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
+#include <QtCore/QDirListing>
#include <QtCore/QFile>
-#include <QtCore/QHash>
+#include <QtCore/QCache>
+#include <QtCore/QMap>
#include <QtCore/QMutex>
#include <qdebug.h>
#include <qplatformdefs.h>
#include <algorithm>
+#include <memory>
+
#include <errno.h>
#include <limits.h>
#ifndef Q_OS_INTEGRITY
@@ -62,6 +31,12 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+#if QT_CONFIG(icu)
+Q_CONSTINIT static QBasicMutex s_icu_mutex;
+#endif
+
/*
Private
@@ -69,45 +44,104 @@ QT_BEGIN_NAMESPACE
*/
struct QTzTimeZone {
- QLocale::Country country;
+ QLocale::Territory territory = QLocale::AnyTerritory;
QByteArray comment;
};
// Define as a type as Q_GLOBAL_STATIC doesn't like it
typedef QHash<QByteArray, QTzTimeZone> QTzTimeZoneHash;
-// Parse zone.tab table, assume lists all installed zones, if not will need to read directories
-static QTzTimeZoneHash loadTzTimeZones()
+static bool isTzFile(const QString &name);
+
+// Open a named file under the zone info directory:
+static bool openZoneInfo(const QString &name, QFile *file)
{
- QString path = QStringLiteral("/usr/share/zoneinfo/zone.tab");
- if (!QFile::exists(path))
- path = QStringLiteral("/usr/lib/zoneinfo/zone.tab");
+ // At least on Linux / glibc (see man 3 tzset), $TZDIR overrides the system
+ // default location for zone info:
+ const QString tzdir = qEnvironmentVariable("TZDIR");
+ if (!tzdir.isEmpty()) {
+ file->setFileName(QDir(tzdir).filePath(name));
+ if (file->open(QIODevice::ReadOnly))
+ return true;
+ }
+ // Try modern system path first:
+ constexpr auto zoneShare = "/usr/share/zoneinfo/"_L1;
+ if (tzdir != zoneShare && tzdir != zoneShare.chopped(1)) {
+ file->setFileName(zoneShare + name);
+ if (file->open(QIODevice::ReadOnly))
+ return true;
+ }
+ // Fall back to legacy system path:
+ constexpr auto zoneLib = "/usr/lib/zoneinfo/"_L1;
+ if (tzdir != zoneLib && tzdir != zoneLib.chopped(1)) {
+ file->setFileName(zoneShare + name);
+ if (file->open(QIODevice::ReadOnly))
+ return true;
+ }
+ return false;
+}
- QFile tzif(path);
- if (!tzif.open(QIODevice::ReadOnly))
+// Parse zone.tab table for territory information, read directories to ensure we
+// find all installed zones (many are omitted from zone.tab; even more from
+// zone1970.tab).
+static QTzTimeZoneHash loadTzTimeZones()
+{
+ QFile tzif;
+ if (!openZoneInfo("zone.tab"_L1, &tzif))
return QTzTimeZoneHash();
QTzTimeZoneHash zonesHash;
- // TODO QTextStream inefficient, replace later
- QTextStream ts(&tzif);
- while (!ts.atEnd()) {
- const QString line = ts.readLine();
- // Comment lines are prefixed with a #
- if (!line.isEmpty() && line.at(0) != u'#') {
- // Data rows are tab-separated columns Region, Coordinates, ID, Optional Comments
- const auto parts = QStringView{line}.split(QLatin1Char('\t'));
+ while (!tzif.atEnd()) {
+ const QByteArray line = tzif.readLine().trimmed();
+ if (line.isEmpty() || line.at(0) == '#') // Ignore empty or comment
+ continue;
+ // Data rows are tab-separated columns Region, Coordinates, ID, Optional Comments
+ QByteArrayView text(line);
+ int cut = text.indexOf('\t');
+ if (Q_LIKELY(cut > 0)) {
QTzTimeZone zone;
- zone.country = QLocalePrivate::codeToCountry(parts.at(0));
- if (parts.size() > 3)
- zone.comment = parts.at(3).toUtf8();
- zonesHash.insert(parts.at(2).toUtf8(), zone);
+ // TODO: QLocale & friends could do this look-up without UTF8-conversion:
+ zone.territory = QLocalePrivate::codeToTerritory(QString::fromUtf8(text.first(cut)));
+ text = text.sliced(cut + 1);
+ cut = text.indexOf('\t');
+ if (Q_LIKELY(cut >= 0)) { // Skip over Coordinates, read ID and comment
+ text = text.sliced(cut + 1);
+ cut = text.indexOf('\t'); // < 0 if line has no comment
+ if (Q_LIKELY(cut)) {
+ const QByteArray id = (cut > 0 ? text.first(cut) : text).toByteArray();
+ if (cut > 0)
+ zone.comment = text.sliced(cut + 1).toByteArray();
+ zonesHash.insert(id, zone);
+ }
+ }
+ }
+ }
+
+ const QString path = tzif.fileName();
+ const qsizetype cut = path.lastIndexOf(u'/');
+ Q_ASSERT(cut > 0);
+ const QDir zoneDir = QDir(path.first(cut));
+ for (const auto &info : QDirListing(zoneDir, QDirListing::IteratorFlag::Recursive)) {
+ if (!(info.isFile() || info.isSymLink()))
+ continue;
+ const QString name = zoneDir.relativeFilePath(info.filePath());
+ // Two sub-directories containing (more or less) copies of the zoneinfo tree.
+ if (info.isDir() ? name == "posix"_L1 || name == "right"_L1
+ : name.startsWith("posix/"_L1) || name.startsWith("right/"_L1)) {
+ continue;
}
+ // We could filter out *.* and leapseconds instead of doing the
+ // isTzFile() check; in practice current (2023) zoneinfo/ contains only
+ // actual zone files and matches to that filter.
+ const QByteArray id = QFile::encodeName(name);
+ if (!zonesHash.contains(id) && isTzFile(zoneDir.absoluteFilePath(name)))
+ zonesHash.insert(id, QTzTimeZone());
}
return zonesHash;
}
// Hash of available system tz files as loaded by loadTzTimeZones()
-Q_GLOBAL_STATIC_WITH_ARGS(const QTzTimeZoneHash, tzZones, (loadTzTimeZones()));
+Q_GLOBAL_STATIC(const QTzTimeZoneHash, tzZones, loadTzTimeZones());
/*
The following is copied and modified from tzfile.h which is in the public domain.
@@ -146,6 +180,11 @@ struct QTzType {
};
Q_DECLARE_TYPEINFO(QTzType, Q_PRIMITIVE_TYPE);
+static bool isTzFile(const QString &name)
+{
+ QFile file(name);
+ return file.open(QFile::ReadOnly) && file.read(strlen(TZ_MAGIC)) == TZ_MAGIC;
+}
// TZ File parsing
@@ -351,6 +390,11 @@ static QByteArray parseTzPosixRule(QDataStream &ds)
static QDate calculateDowDate(int year, int month, int dayOfWeek, int week)
{
+ if (dayOfWeek == 0) // Sunday; we represent it as 7, POSIX uses 0
+ dayOfWeek = 7;
+ else if (dayOfWeek & ~7 || month < 1 || month > 12 || week < 1 || week > 5)
+ return QDate();
+
QDate date(year, month, 1);
int startDow = date.dayOfWeek();
if (startDow <= dayOfWeek)
@@ -365,28 +409,39 @@ static QDate calculateDowDate(int year, int month, int dayOfWeek, int week)
static QDate calculatePosixDate(const QByteArray &dateRule, int year)
{
+ Q_ASSERT(!dateRule.isEmpty());
+ bool ok;
// Can start with M, J, or a digit
if (dateRule.at(0) == 'M') {
// nth week in month format "Mmonth.week.dow"
QList<QByteArray> dateParts = dateRule.split('.');
- int month = dateParts.at(0).mid(1).toInt();
- int week = dateParts.at(1).toInt();
- int dow = dateParts.at(2).toInt();
- if (dow == 0)
- ++dow;
- return calculateDowDate(year, month, dow, week);
+ if (dateParts.size() > 2) {
+ Q_ASSERT(!dateParts.at(0).isEmpty()); // the 'M' is its [0].
+ int month = QByteArrayView{ dateParts.at(0) }.sliced(1).toInt(&ok);
+ int week = ok ? dateParts.at(1).toInt(&ok) : 0;
+ int dow = ok ? dateParts.at(2).toInt(&ok) : 0;
+ if (ok)
+ return calculateDowDate(year, month, dow, week);
+ }
} else if (dateRule.at(0) == 'J') {
- // Day of Year ignores Feb 29
- int doy = dateRule.mid(1).toInt();
- QDate date = QDate(year, 1, 1).addDays(doy - 1);
- if (QDate::isLeapYear(date.year()))
- date = date.addDays(-1);
- return date;
+ // Day of Year 1...365, ignores Feb 29.
+ // So March always starts on day 60.
+ int doy = QByteArrayView{ dateRule }.sliced(1).toInt(&ok);
+ if (ok && doy > 0 && doy < 366) {
+ // Subtract 1 because we're adding days *after* the first of
+ // January, unless it's after February in a leap year, when the leap
+ // day cancels that out:
+ if (!QDate::isLeapYear(year) || doy < 60)
+ --doy;
+ return QDate(year, 1, 1).addDays(doy);
+ }
} else {
- // Day of Year includes Feb 29
- int doy = dateRule.toInt();
- return QDate(year, 1, 1).addDays(doy - 1);
+ // Day of Year 0...365, includes Feb 29
+ int doy = dateRule.toInt(&ok);
+ if (ok && doy >= 0 && doy < 366)
+ return QDate(year, 1, 1).addDays(doy);
}
+ return QDate();
}
// returns the time in seconds, INT_MIN if we failed to parse
@@ -395,29 +450,29 @@ static int parsePosixTime(const char *begin, const char *end)
// Format "hh[:mm[:ss]]"
int hour, min = 0, sec = 0;
- // Note that the calls to qstrtoll do *not* check the end pointer, which
- // means they proceed until they find a non-digit. We check that we're
- // still in range at the end, but we may have read from past end. It's the
- // caller's responsibility to ensure that begin is part of a
- // null-terminated string.
-
- bool ok = false;
- hour = qstrtoll(begin, &begin, 10, &ok);
- if (!ok || hour < 0)
+ const int maxHour = 137; // POSIX's extended range.
+ auto r = qstrntoll(begin, end - begin, 10);
+ hour = r.result;
+ if (!r.ok() || hour < -maxHour || hour > maxHour || r.used > 2)
return INT_MIN;
+ begin += r.used;
if (begin < end && *begin == ':') {
// minutes
++begin;
- min = qstrtoll(begin, &begin, 10, &ok);
- if (!ok || min < 0)
+ r = qstrntoll(begin, end - begin, 10);
+ min = r.result;
+ if (!r.ok() || min < 0 || min > 59 || r.used > 2)
return INT_MIN;
+ begin += r.used;
if (begin < end && *begin == ':') {
// seconds
++begin;
- sec = qstrtoll(begin, &begin, 10, &ok);
- if (!ok || sec < 0)
+ r = qstrntoll(begin, end - begin, 10);
+ sec = r.result;
+ if (!r.ok() || sec < 0 || sec > 59 || r.used > 2)
return INT_MIN;
+ begin += r.used;
}
}
@@ -428,15 +483,9 @@ static int parsePosixTime(const char *begin, const char *end)
return (hour * 60 + min) * 60 + sec;
}
-static QTime parsePosixTransitionTime(const QByteArray &timeRule)
+static int parsePosixTransitionTime(const QByteArray &timeRule)
{
- // Format "hh[:mm[:ss]]"
- int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
- if (value == INT_MIN) {
- // if we failed to parse, return 02:00
- return QTime(2, 0, 0);
- }
- return QTime::fromMSecsSinceStartOfDay(value * 1000);
+ return parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
}
static int parsePosixOffset(const char *begin, const char *end)
@@ -472,12 +521,20 @@ struct PosixZone
};
QString name;
- int offset;
+ int offset = InvalidOffset;
+ bool hasValidOffset() const noexcept { return offset != InvalidOffset; }
+ QTimeZonePrivate::Data dataAt(qint64 when)
+ {
+ Q_ASSERT(hasValidOffset());
+ return QTimeZonePrivate::Data(name, when, offset, offset);
+ }
+ QTimeZonePrivate::Data dataAtOffset(qint64 when, int standard)
+ {
+ Q_ASSERT(hasValidOffset());
+ return QTimeZonePrivate::Data(name, when, offset, standard);
+ }
- static PosixZone invalid() { return {QString(), InvalidOffset}; }
static PosixZone parse(const char *&pos, const char *end);
-
- bool hasValidOffset() const noexcept { return offset != InvalidOffset; }
};
} // unnamed namespace
@@ -494,7 +551,7 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
Q_ASSERT(pos < end);
if (*pos == '<') {
- nameBegin = pos + 1; // skip the '<'
+ ++nameBegin; // skip the '<'
nameEnd = nameBegin;
while (nameEnd < end && *nameEnd != '>') {
// POSIX says only alphanumeric, but we allow anything
@@ -502,14 +559,13 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
}
pos = nameEnd + 1; // skip the '>'
} else {
- nameBegin = pos;
nameEnd = nameBegin;
while (nameEnd < end && asciiIsLetter(*nameEnd))
++nameEnd;
pos = nameEnd;
}
if (nameEnd - nameBegin < 3)
- return invalid(); // name must be at least 3 characters long
+ return {}; // name must be at least 3 characters long
// zone offset, form [+-]hh:mm:ss
const char *zoneBegin = pos;
@@ -527,12 +583,66 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
pos = zoneEnd;
// UTC+hh:mm:ss or GMT+hh:mm:ss should be read as offsets from UTC, not as a
// POSIX rule naming a zone as UTC or GMT and specifying a non-zero offset.
- if (offset != 0 && (name == QLatin1String("UTC") || name == QLatin1String("GMT")))
- return invalid();
+ if (offset != 0 && (name =="UTC"_L1 || name == "GMT"_L1))
+ return {};
return {std::move(name), offset};
}
-static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule, int startYear, int endYear,
+/* Parse and check a POSIX rule.
+
+ By default a simple zone abbreviation with no offset information is accepted.
+ Set \a requireOffset to \c true to require that there be offset data present.
+*/
+static auto validatePosixRule(const QByteArray &posixRule, bool requireOffset = false)
+{
+ // Format is described here:
+ // http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
+ // See also calculatePosixTransition()'s reference.
+ const auto parts = posixRule.split(',');
+ const struct { bool isValid, hasDst; } fail{false, false}, good{true, parts.size() > 1};
+ const QByteArray &zoneinfo = parts.at(0);
+ if (zoneinfo.isEmpty())
+ return fail;
+
+ const char *begin = zoneinfo.begin();
+ {
+ // Updates begin to point after the name and offset it parses:
+ const auto posix = PosixZone::parse(begin, zoneinfo.end());
+ if (posix.name.isEmpty())
+ return fail;
+ if (requireOffset && !posix.hasValidOffset())
+ return fail;
+ }
+
+ if (good.hasDst) {
+ if (begin >= zoneinfo.end())
+ return fail;
+ // Expect a second name (and optional offset) after the first:
+ if (PosixZone::parse(begin, zoneinfo.end()).name.isEmpty())
+ return fail;
+ }
+ if (begin < zoneinfo.end())
+ return fail;
+
+ if (good.hasDst) {
+ if (parts.size() != 3 || parts.at(1).isEmpty() || parts.at(2).isEmpty())
+ return fail;
+ for (int i = 1; i < 3; ++i) {
+ const auto tran = parts.at(i).split('/');
+ if (!calculatePosixDate(tran.at(0), 1972).isValid())
+ return fail;
+ if (tran.size() > 1) {
+ const auto time = tran.at(1);
+ if (parsePosixTime(time.begin(), time.end()) == INT_MIN)
+ return fail;
+ }
+ }
+ }
+ return good;
+}
+
+static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
+ int startYear, int endYear,
qint64 lastTranMSecs)
{
QList<QTimeZonePrivate::Data> result;
@@ -541,9 +651,10 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
// i.e. "std offset dst [offset],start[/time],end[/time]"
// See the section about TZ at
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
+ // and the link in validatePosixRule(), above.
QList<QByteArray> parts = posixRule.split(',');
- PosixZone stdZone, dstZone = PosixZone::invalid();
+ PosixZone stdZone, dstZone;
{
const QByteArray &zoneinfo = parts.at(0);
const char *begin = zoneinfo.constBegin();
@@ -560,36 +671,29 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
}
}
- // If only the name part then no transitions
- if (parts.count() == 1) {
- QTimeZonePrivate::Data data;
- data.atMSecsSinceEpoch = lastTranMSecs;
- data.offsetFromUtc = stdZone.offset;
- data.standardTimeOffset = stdZone.offset;
- data.daylightTimeOffset = 0;
- data.abbreviation = stdZone.name;
- result << data;
+ // If only the name part, or no DST specified, then no transitions
+ if (parts.size() == 1 || !dstZone.hasValidOffset()) {
+ result.emplaceBack(
+ stdZone.name.isEmpty() ? QString::fromUtf8(parts.at(0)) : stdZone.name,
+ lastTranMSecs, stdZone.offset, stdZone.offset);
return result;
}
+ if (parts.size() < 3 || parts.at(1).isEmpty() || parts.at(2).isEmpty())
+ return result; // Malformed.
+ // Get the std to dst transition details
+ const int twoOClock = 7200; // Default transition time, when none specified
+ const auto dstParts = parts.at(1).split('/');
+ const QByteArray dstDateRule = dstParts.at(0);
+ const int dstTime = dstParts.size() < 2 ? twoOClock : parsePosixTransitionTime(dstParts.at(1));
- // Get the std to dst transtion details
- QList<QByteArray> dstParts = parts.at(1).split('/');
- QByteArray dstDateRule = dstParts.at(0);
- QTime dstTime;
- if (dstParts.count() > 1)
- dstTime = parsePosixTransitionTime(dstParts.at(1));
- else
- dstTime = QTime(2, 0, 0);
-
- // Get the dst to std transtion details
- QList<QByteArray> stdParts = parts.at(2).split('/');
- QByteArray stdDateRule = stdParts.at(0);
- QTime stdTime;
- if (stdParts.count() > 1)
- stdTime = parsePosixTransitionTime(stdParts.at(1));
- else
- stdTime = QTime(2, 0, 0);
+ // Get the dst to std transition details
+ const auto stdParts = parts.at(2).split('/');
+ const QByteArray stdDateRule = stdParts.at(0);
+ const int stdTime = stdParts.size() < 2 ? twoOClock : parsePosixTransitionTime(stdParts.at(1));
+
+ if (dstDateRule.isEmpty() || stdDateRule.isEmpty() || dstTime == INT_MIN || stdTime == INT_MIN)
+ return result; // Malformed.
// Limit year to the range QDateTime can represent:
const int minYear = int(QDateTime::YearRange::First);
@@ -599,34 +703,57 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
Q_ASSERT(startYear <= endYear);
for (int year = startYear; year <= endYear; ++year) {
- QTimeZonePrivate::Data dstData;
- QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
- dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.offset * 1000);
- dstData.offsetFromUtc = dstZone.offset;
- dstData.standardTimeOffset = stdZone.offset;
- dstData.daylightTimeOffset = dstZone.offset - stdZone.offset;
- dstData.abbreviation = dstZone.name;
- QTimeZonePrivate::Data stdData;
- QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
- stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.offset * 1000);
- stdData.offsetFromUtc = stdZone.offset;
- stdData.standardTimeOffset = stdZone.offset;
- stdData.daylightTimeOffset = 0;
- stdData.abbreviation = stdZone.name;
- // Part of maxYear will overflow (likewise for minYear, below):
- if (year == maxYear && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
- if (dstData.atMSecsSinceEpoch > 0) {
- result << dstData;
- } else if (stdData.atMSecsSinceEpoch > 0) {
- result << stdData;
+ // Note: std and dst, despite being QDateTime(,, UTC), have the
+ // date() and time() of the *zone*'s description of the transition
+ // moments; the atMSecsSinceEpoch values computed from them are
+ // correctly offse to be UTC-based.
+
+ // Transition to daylight-saving time:
+ QDateTime dst(calculatePosixDate(dstDateRule, year)
+ .startOfDay(QTimeZone::UTC).addSecs(dstTime));
+ auto saving = dstZone.dataAtOffset(dst.toMSecsSinceEpoch() - stdZone.offset * 1000,
+ stdZone.offset);
+ // Transition to standard time:
+ QDateTime std(calculatePosixDate(stdDateRule, year)
+ .startOfDay(QTimeZone::UTC).addSecs(stdTime));
+ auto standard = stdZone.dataAt(std.toMSecsSinceEpoch() - dstZone.offset * 1000);
+
+ if (year == startYear) {
+ // Handle the special case of fixed state, which may be represented
+ // by fake transitions at start and end of each year:
+ if (saving.atMSecsSinceEpoch < standard.atMSecsSinceEpoch) {
+ if (dst <= QDate(year, 1, 1).startOfDay(QTimeZone::UTC)
+ && std >= QDate(year, 12, 31).endOfDay(QTimeZone::UTC)) {
+ // Permanent DST:
+ saving.atMSecsSinceEpoch = lastTranMSecs;
+ result.emplaceBack(std::move(saving));
+ return result;
+ }
+ } else {
+ if (std <= QDate(year, 1, 1).startOfDay(QTimeZone::UTC)
+ && dst >= QDate(year, 12, 31).endOfDay(QTimeZone::UTC)) {
+ // Permanent Standard time, perversely described:
+ standard.atMSecsSinceEpoch = lastTranMSecs;
+ result.emplaceBack(std::move(standard));
+ return result;
+ }
}
- } else if (year < 1970) { // We ignore DST before the epoch.
- if (year > minYear || stdData.atMSecsSinceEpoch != QTimeZonePrivate::invalidMSecs())
- result << stdData;
- } else if (dst < std) {
- result << dstData << stdData;
- } else {
- result << stdData << dstData;
+ }
+
+ const bool useStd = std.isValid() && std.date().year() == year && !stdZone.name.isEmpty();
+ const bool useDst = dst.isValid() && dst.date().year() == year && !dstZone.name.isEmpty();
+ if (useStd && useDst) {
+ if (dst < std) {
+ result.emplaceBack(std::move(saving));
+ result.emplaceBack(std::move(standard));
+ } else {
+ result.emplaceBack(std::move(standard));
+ result.emplaceBack(std::move(saving));
+ }
+ } else if (useStd) {
+ result.emplaceBack(std::move(standard));
+ } else if (useDst) {
+ result.emplaceBack(std::move(saving));
}
}
return result;
@@ -634,14 +761,8 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
// Create the system default time zone
QTzTimeZonePrivate::QTzTimeZonePrivate()
+ : QTzTimeZonePrivate(staticSystemTimeZoneId())
{
- init(systemTimeZoneId());
-}
-
-// Create a named time zone
-QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
-{
- init(ianaId.isEmpty() ? systemTimeZoneId() : ianaId);
}
QTzTimeZonePrivate::~QTzTimeZonePrivate()
@@ -650,6 +771,9 @@ QTzTimeZonePrivate::~QTzTimeZonePrivate()
QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
{
+#if QT_CONFIG(icu)
+ const auto lock = qt_scoped_lock(s_icu_mutex);
+#endif
return new QTzTimeZonePrivate(*this);
}
@@ -659,8 +783,8 @@ public:
QTzTimeZoneCacheEntry fetchEntry(const QByteArray &ianaId);
private:
- QTzTimeZoneCacheEntry findEntry(const QByteArray &ianaId);
- QHash<QByteArray, QTzTimeZoneCacheEntry> m_cache;
+ static QTzTimeZoneCacheEntry findEntry(const QByteArray &ianaId);
+ QCache<QByteArray, QTzTimeZoneCacheEntry> m_cache;
QMutex m_mutex;
};
@@ -673,29 +797,21 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
tzif.setFileName(QStringLiteral("/etc/localtime"));
if (!tzif.open(QIODevice::ReadOnly))
return ret;
- } else {
- // Open named tz, try modern path first, if fails try legacy path
- tzif.setFileName(QLatin1String("/usr/share/zoneinfo/") + QString::fromLocal8Bit(ianaId));
- if (!tzif.open(QIODevice::ReadOnly)) {
- tzif.setFileName(QLatin1String("/usr/lib/zoneinfo/") + QString::fromLocal8Bit(ianaId));
- if (!tzif.open(QIODevice::ReadOnly)) {
- // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
- const QByteArray zoneInfo = ianaId.split(',').at(0);
- const char *begin = zoneInfo.constBegin();
- if (PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset()
- && (begin == zoneInfo.constEnd()
- || PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset())) {
- ret.m_posixRule = ianaId;
- }
- return ret;
- }
+ } else if (!openZoneInfo(QString::fromLocal8Bit(ianaId), &tzif)) {
+ // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
+ auto check = validatePosixRule(ianaId);
+ if (check.isValid) {
+ ret.m_hasDst = check.hasDst;
+ ret.m_posixRule = ianaId;
}
+ return ret;
}
QDataStream ds(&tzif);
// Parse the old version block of data
bool ok = false;
+ QByteArray posixRule;
QTzHeader hdr = parseTzHeader(ds, &ok);
if (!ok || ds.status() != QDataStream::Ok)
return ret;
@@ -736,14 +852,21 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
typeList = parseTzIndicators(ds, typeList, hdr2.tzh_ttisstdcnt, hdr2.tzh_ttisgmtcnt);
if (ds.status() != QDataStream::Ok)
return ret;
- ret.m_posixRule = parseTzPosixRule(ds);
+ posixRule = parseTzPosixRule(ds);
if (ds.status() != QDataStream::Ok)
return ret;
}
+ // Translate the TZ file's raw data into our internal form:
- // Translate the TZ file into internal format
+ if (!posixRule.isEmpty()) {
+ auto check = validatePosixRule(posixRule);
+ if (!check.isValid) // We got a POSIX rule, but it was malformed:
+ return ret;
+ ret.m_posixRule = posixRule;
+ ret.m_hasDst = check.hasDst;
+ }
- // Translate the array index based tz_abbrind into list index
+ // Translate the array-index-based tz_abbrind into list index
const int size = abbrevMap.size();
ret.m_abbreviations.clear();
ret.m_abbreviations.reserve(size);
@@ -753,13 +876,19 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
ret.m_abbreviations.append(it.value());
abbrindList.append(it.key());
}
+ // Map tz_abbrind from map's keys (as initially read) to abbrindList's
+ // indices (used hereafter):
for (int i = 0; i < typeList.size(); ++i)
typeList[i].tz_abbrind = abbrindList.indexOf(typeList.at(i).tz_abbrind);
+ // TODO: is typeList[0] always the "before zones" data ? It seems to be ...
+ if (typeList.size())
+ ret.m_preZoneRule = { typeList.at(0).tz_gmtoff, 0, typeList.at(0).tz_abbrind };
+
// Offsets are stored as total offset, want to know separate UTC and DST offsets
// so find the first non-dst transition to use as base UTC Offset
- int utcOffset = 0;
- for (const QTzTransition &tran : qAsConst(tranList)) {
+ int utcOffset = ret.m_preZoneRule.stdOffset;
+ for (const QTzTransition &tran : std::as_const(tranList)) {
if (!typeList.at(tran.tz_typeind).tz_isdst) {
utcOffset = typeList.at(tran.tz_typeind).tz_gmtoff;
break;
@@ -767,7 +896,7 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
}
// Now for each transition time calculate and store our rule:
- const int tranCount = tranList.count();;
+ const int tranCount = tranList.size();
ret.m_tranTimes.reserve(tranCount);
// The DST offset when in effect: usually stable, usually an hour:
int lastDstOff = 3600;
@@ -824,8 +953,10 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
// If the rule already exist then use that, otherwise add it
int ruleIndex = ret.m_tranRules.indexOf(rule);
if (ruleIndex == -1) {
+ if (rule.dstOffset != 0)
+ ret.m_hasDst = true;
+ tran.ruleIndex = ret.m_tranRules.size();
ret.m_tranRules.append(rule);
- tran.ruleIndex = ret.m_tranRules.size() - 1;
} else {
tran.ruleIndex = ruleIndex;
}
@@ -842,33 +973,56 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::fetchEntry(const QByteArray &ianaId)
QMutexLocker locker(&m_mutex);
// search the cache...
- const auto& it = m_cache.find(ianaId);
- if (it != m_cache.constEnd())
- return *it;
+ QTzTimeZoneCacheEntry *obj = m_cache.object(ianaId);
+ if (obj)
+ return *obj;
// ... or build a new entry from scratch
+
+ locker.unlock(); // don't parse files under mutex lock
+
QTzTimeZoneCacheEntry ret = findEntry(ianaId);
- m_cache[ianaId] = ret;
+ auto ptr = std::make_unique<QTzTimeZoneCacheEntry>(ret);
+
+ locker.relock();
+ m_cache.insert(ianaId, ptr.release()); // may overwrite if another thread was faster
+ locker.unlock();
+
return ret;
}
-void QTzTimeZonePrivate::init(const QByteArray &ianaId)
+// Create a named time zone
+QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
{
- // System ID defaults to UTC, so is never empty; and our callers default to
- // the system ID if what they're given is empty.
- Q_ASSERT(!ianaId.isEmpty());
+ if (!isTimeZoneIdAvailable(ianaId)) // Avoid pointlessly creating cache entries
+ return;
static QTzTimeZoneCache tzCache;
- const auto &entry = tzCache.fetchEntry(ianaId);
+ auto entry = tzCache.fetchEntry(ianaId);
if (entry.m_tranTimes.isEmpty() && entry.m_posixRule.isEmpty())
return; // Invalid after all !
cached_data = std::move(entry);
m_id = ianaId;
+ // Avoid empty ID, if we have an abbreviation to use instead
+ if (m_id.isEmpty()) {
+ // This can only happen for the system zone, when we've read the
+ // contents of /etc/localtime because it wasn't a symlink.
+#if QT_CONFIG(icu)
+ // Use ICU's system zone, if only to avoid using the abbreviation as ID
+ // (ICU might mis-recognize it) in displayName().
+ m_icu = new QIcuTimeZonePrivate();
+ // Use its ID, as an alternate source of data:
+ m_id = m_icu->id();
+ if (!m_id.isEmpty())
+ return;
+#endif
+ m_id = abbreviation(QDateTime::currentMSecsSinceEpoch()).toUtf8();
+ }
}
-QLocale::Country QTzTimeZonePrivate::country() const
+QLocale::Territory QTzTimeZonePrivate::territory() const
{
- return tzZones->value(m_id).country;
+ return tzZones->value(m_id).territory;
}
QString QTzTimeZonePrivate::comment() const
@@ -876,41 +1030,27 @@ QString QTzTimeZonePrivate::comment() const
return QString::fromUtf8(tzZones->value(m_id).comment);
}
-QString QTzTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
- QTimeZone::NameType nameType,
- const QLocale &locale) const
-{
-#if QT_CONFIG(icu)
- if (!m_icu)
- m_icu = new QIcuTimeZonePrivate(m_id);
- // TODO small risk may not match if tran times differ due to outdated files
- // TODO Some valid TZ names are not valid ICU names, use translation table?
- if (m_icu->isValid())
- return m_icu->displayName(atMSecsSinceEpoch, nameType, locale);
-#else
- Q_UNUSED(nameType)
- Q_UNUSED(locale)
-#endif
- return abbreviation(atMSecsSinceEpoch);
-}
-
QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
+ // TZ DB lacks localized names (it only has IANA IDs), so delegate to ICU
+ // for those, when available.
#if QT_CONFIG(icu)
- if (!m_icu)
- m_icu = new QIcuTimeZonePrivate(m_id);
- // TODO small risk may not match if tran times differ due to outdated files
- // TODO Some valid TZ names are not valid ICU names, use translation table?
- if (m_icu->isValid())
- return m_icu->displayName(timeType, nameType, locale);
+ {
+ auto lock = qt_scoped_lock(s_icu_mutex);
+ // TODO Some valid TZ names are not valid ICU names, use translation table?
+ if (!m_icu)
+ m_icu = new QIcuTimeZonePrivate(m_id);
+ if (m_icu->isValid())
+ return m_icu->displayName(timeType, nameType, locale);
+ }
#else
- Q_UNUSED(timeType)
- Q_UNUSED(nameType)
- Q_UNUSED(locale)
+ Q_UNUSED(timeType);
+ Q_UNUSED(nameType);
+ Q_UNUSED(locale);
#endif
- // If no ICU available then have to use abbreviations instead
+ // If ICU is unavailable, fall back to abbreviations.
// Abbreviations don't have GenericTime
if (timeType == QTimeZone::GenericTime)
timeType = QTimeZone::StandardTime;
@@ -983,12 +1123,7 @@ int QTzTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
bool QTzTimeZonePrivate::hasDaylightTime() const
{
- // TODO Perhaps cache as frequently accessed?
- for (const QTzTransitionRule &rule : cached_data.m_tranRules) {
- if (rule.dstOffset != 0)
- return true;
- }
- return false;
+ return cached_data.m_hasDst;
}
bool QTzTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
@@ -998,19 +1133,19 @@ bool QTzTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime tran) const
{
- QTimeZonePrivate::Data data;
- data.atMSecsSinceEpoch = tran.atMSecsSinceEpoch;
- QTzTransitionRule rule = cached_data.m_tranRules.at(tran.ruleIndex);
- data.standardTimeOffset = rule.stdOffset;
- data.daylightTimeOffset = rule.dstOffset;
- data.offsetFromUtc = rule.stdOffset + rule.dstOffset;
- data.abbreviation = QString::fromUtf8(cached_data.m_abbreviations.at(rule.abbreviationIndex));
- return data;
+ return dataFromRule(cached_data.m_tranRules.at(tran.ruleIndex), tran.atMSecsSinceEpoch);
+}
+
+QTimeZonePrivate::Data QTzTimeZonePrivate::dataFromRule(QTzTransitionRule rule,
+ qint64 msecsSinceEpoch) const
+{
+ return Data(QString::fromUtf8(cached_data.m_abbreviations.at(rule.abbreviationIndex)),
+ msecsSinceEpoch, rule.stdOffset + rule.dstOffset, rule.stdOffset);
}
QList<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 msNear) const
{
- const int year = QDateTime::fromMSecsSinceEpoch(msNear, Qt::UTC).date().year();
+ const int year = QDateTime::fromMSecsSinceEpoch(msNear, QTimeZone::UTC).date().year();
// The Data::atMSecsSinceEpoch of the single entry if zone is constant:
qint64 atTime = tranCache().isEmpty() ? msNear : tranCache().last().atMSecsSinceEpoch;
return calculatePosixTransitions(cached_data.m_posixRule, year - 1, year + 1, atTime);
@@ -1035,18 +1170,18 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
}
}
if (tranCache().isEmpty()) // Only possible if !isValid()
- return invalidData();
+ return {};
// Otherwise, use the rule for the most recent or first transition:
auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(),
[forMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
});
- if (last > tranCache().cbegin())
- --last;
- Data data = dataForTzTransition(*last);
- data.atMSecsSinceEpoch = forMSecsSinceEpoch;
- return data;
+ if (last == tranCache().cbegin())
+ return dataFromRule(cached_data.m_preZoneRule, forMSecsSinceEpoch);
+
+ --last;
+ return dataFromRule(cached_data.m_tranRules.at(last->ruleIndex), forMSecsSinceEpoch);
}
bool QTzTimeZonePrivate::hasTransitions() const
@@ -1066,7 +1201,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
});
- return it == posixTrans.cend() ? invalidData() : *it;
+ return it == posixTrans.cend() ? Data{} : *it;
}
// Otherwise, if we can find a valid tran, use its rule:
@@ -1074,7 +1209,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
[afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
});
- return last != tranCache().cend() ? dataForTzTransition(*last) : invalidData();
+ return last != tranCache().cend() ? dataForTzTransition(*last) : Data{};
}
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
@@ -1091,7 +1226,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
if (it > posixTrans.cbegin())
return *--it;
// It fell between the last transition (if any) and the first of the POSIX rule:
- return tranCache().isEmpty() ? invalidData() : dataForTzTransition(tranCache().last());
+ return tranCache().isEmpty() ? Data{} : dataForTzTransition(tranCache().last());
}
// Otherwise if we can find a valid tran then use its rule
@@ -1099,12 +1234,16 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
[beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
});
- return last > tranCache().cbegin() ? dataForTzTransition(*--last) : invalidData();
+ return last > tranCache().cbegin() ? dataForTzTransition(*--last) : Data{};
}
bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
{
- return tzZones->contains(ianaId);
+ // Allow a POSIX rule as long as it has offset data. (This needs to reject a
+ // plain abbreviation, without offset, since claiming to support such zones
+ // would prevent the custom QTimeZone constructor from accepting such a
+ // name, as it doesn't want a custom zone to over-ride a "real" one.)
+ return tzZones->contains(ianaId) || validatePosixRule(ianaId, true).isValid;
}
QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const
@@ -1114,12 +1253,12 @@ QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const
return result;
}
-QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
+QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds(QLocale::Territory territory) const
{
- // TODO AnyCountry
+ // TODO AnyTerritory
QList<QByteArray> result;
for (auto it = tzZones->cbegin(), end = tzZones->cend(); it != end; ++it) {
- if (it.value().country == country)
+ if (it.value().territory == territory)
result << it.key();
}
std::sort(result.begin(), result.end());
@@ -1129,7 +1268,7 @@ QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds(QLocale::Country coun
// Getting the system zone's ID:
namespace {
-class ZoneNameReader : public QObject
+class ZoneNameReader
{
public:
QByteArray name()
@@ -1151,8 +1290,11 @@ public:
*/
const StatIdent local = identify("/etc/localtime");
const StatIdent tz = identify("/etc/TZ");
- if (!m_name.isEmpty() && m_last.isValid() && (m_last == local || m_last == tz))
+ const StatIdent timezone = identify("/etc/timezone");
+ if (!m_name.isEmpty() && m_last.isValid()
+ && (m_last == local || m_last == tz || m_last == timezone)) {
return m_name;
+ }
m_name = etcLocalTime();
if (!m_name.isEmpty()) {
@@ -1160,19 +1302,26 @@ public:
return m_name;
}
- m_name = etcTZ();
- m_last = m_name.isEmpty() ? StatIdent() : tz;
+ // Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ:
+ m_name = etcContent(QStringLiteral("/etc/TZ"));
+ if (!m_name.isEmpty()) {
+ m_last = tz;
+ return m_name;
+ }
+
+ // Gentoo still (2020, QTBUG-87326) uses this:
+ m_name = etcContent(QStringLiteral("/etc/timezone"));
+ m_last = m_name.isEmpty() ? StatIdent() : timezone;
return m_name;
}
-
private:
QByteArray m_name;
struct StatIdent
{
static constexpr unsigned long bad = ~0ul;
unsigned long m_dev, m_ino;
- StatIdent() : m_dev(bad), m_ino(bad) {}
+ constexpr StatIdent() : m_dev(bad), m_ino(bad) {}
StatIdent(const QT_STATBUF &data) : m_dev(data.st_dev), m_ino(data.st_ino) {}
bool isValid() { return m_dev != bad || m_ino != bad; }
bool operator==(const StatIdent &other)
@@ -1190,7 +1339,8 @@ private:
{
// On most distros /etc/localtime is a symlink to a real file so extract
// name from the path
- const QLatin1String zoneinfo("/zoneinfo/");
+ const QString tzdir = qEnvironmentVariable("TZDIR");
+ constexpr auto zoneinfo = "/zoneinfo/"_L1;
QString path = QStringLiteral("/etc/localtime");
long iteration = getSymloopMax();
// Symlink may point to another symlink etc. before being under zoneinfo/
@@ -1198,18 +1348,22 @@ private:
// symlink, like America/Montreal pointing to America/Toronto
do {
path = QFile::symLinkTarget(path);
- int index = path.indexOf(zoneinfo);
- if (index >= 0) // Found zoneinfo file; extract zone name from path:
- return path.midRef(index + zoneinfo.size()).toUtf8();
+ // If it's a zoneinfo file, extract the zone name from its path:
+ int index = tzdir.isEmpty() ? -1 : path.indexOf(tzdir);
+ if (index >= 0) {
+ const auto tail = QStringView{ path }.sliced(index + tzdir.size()).toUtf8();
+ return tail.startsWith(u'/') ? tail.sliced(1) : tail;
+ }
+ index = path.indexOf(zoneinfo);
+ if (index >= 0)
+ return QStringView{ path }.sliced(index + zoneinfo.size()).toUtf8();
} while (!path.isEmpty() && --iteration > 0);
return QByteArray();
}
- static QByteArray etcTZ()
+ static QByteArray etcContent(const QString &path)
{
- // Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ:
- const QString path = QStringLiteral("/etc/TZ");
QFile zone(path);
if (zone.open(QIODevice::ReadOnly))
return zone.readAll().trimmed();
@@ -1244,6 +1398,11 @@ private:
QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
{
+ return staticSystemTimeZoneId();
+}
+
+QByteArray QTzTimeZonePrivate::staticSystemTimeZoneId()
+{
// Check TZ env var first, if not populated try find it
QByteArray ianaId = qgetenv("TZ");
@@ -1254,17 +1413,13 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
if (ianaId == ":/etc/localtime")
ianaId.clear();
else if (ianaId.startsWith(':'))
- ianaId = ianaId.mid(1);
+ ianaId = ianaId.sliced(1);
if (ianaId.isEmpty()) {
- thread_local static ZoneNameReader reader;
+ Q_CONSTINIT thread_local static ZoneNameReader reader;
ianaId = reader.name();
}
- // Give up for now and return UTC
- if (ianaId.isEmpty())
- ianaId = utcQByteArray();
-
return ianaId;
}
diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp
index 1dc362e45a..7874c22174 100644
--- a/src/corelib/time/qtimezoneprivate_win.cpp
+++ b/src/corelib/time/qtimezoneprivate_win.cpp
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2013 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
#include "qdatetime.h"
-
#include "qdebug.h"
+#include <private/qnumeric_p.h>
#include <algorithm>
@@ -50,6 +15,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*
Private
@@ -57,7 +24,6 @@ QT_BEGIN_NAMESPACE
*/
#define MAX_KEY_LENGTH 255
-#define FILETIME_UNIX_EPOCH Q_UINT64_C(116444736000000000)
// MSDN home page for Time support
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724962%28v=vs.85%29.aspx
@@ -70,13 +36,35 @@ QT_BEGIN_NAMESPACE
static const wchar_t tzRegPath[] = LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones)";
static const wchar_t currTzRegPath[] = LR"(SYSTEM\CurrentControlSet\Control\TimeZoneInformation)";
-enum {
- MIN_YEAR = -292275056,
- MAX_YEAR = 292278994,
- MSECS_PER_DAY = 86400000,
- TIME_T_MAX = 2145916799, // int maximum 2037-12-31T23:59:59 UTC
- JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
-};
+constexpr qint64 MSECS_PER_DAY = 86400000LL;
+constexpr qint64 JULIAN_DAY_FOR_EPOCH = 2440588LL; // result of julianDayFromDate(1970, 1, 1)
+
+/* Ignore any claims of DST before 1900.
+
+ Daylight-Saving time adjustments were first proposed in 1895 (George Vernon
+ Hudson in New Zealand) and 1905 (William Willett in the UK) and first adopted
+ in 1908 (one town in Ontario, Canada) and 1916 (Germany). Since MS's data
+ tends to pretend the rules in force in 1970ish (or later) had always been in
+ effect, which presents difficulties for the code that selects correct data
+ (for a time close to the earliest we can represent), always ignore any claim
+ a first rule may make of DST starting any time before 1900.
+
+ For southern-hemisphere zones, this implies that a rule claiming 1900 started
+ in DST is overruled to merely start DST later in 1900, having spent the whole
+ part of 1900 prior to that in standard time. This erases 1900's earlier
+ transition out of daylight-saving time so as to prevent a fake change of
+ offset at the start of the year, since 1899 shall be treated as observing
+ standard time throughout.
+
+ In the unlikely event of MS supplying a change in standard time before 1900,
+ however, that should be faithfully represented. If that ever happens, trust
+ that MS gets the start year of any subsequend DST right.
+
+ See:
+ * https://www.timeanddate.com/time/dst/history.html
+ * https://en.wikipedia.org/wiki/Daylight_saving_time#History
+*/
+constexpr int FIRST_DST_YEAR = 1900;
// Copied from MSDN, see above for link
typedef struct _REG_TZI_FORMAT
@@ -95,15 +83,15 @@ namespace {
QDate msecsToDate(qint64 msecs)
{
qint64 jd = JULIAN_DAY_FOR_EPOCH;
-
- if (qAbs(msecs) >= MSECS_PER_DAY) {
- jd += (msecs / MSECS_PER_DAY);
+ // Corner case: don't use qAbs() because msecs may be numeric_limits<qint64>::min()
+ if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
+ jd += msecs / MSECS_PER_DAY;
msecs %= MSECS_PER_DAY;
}
if (msecs < 0) {
- qint64 ds = MSECS_PER_DAY - msecs - 1;
- jd -= ds / MSECS_PER_DAY;
+ Q_ASSERT(msecs > -MSECS_PER_DAY);
+ --jd;
}
return QDate::fromJulianDay(jd);
@@ -157,7 +145,7 @@ TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
TIME_ZONE_INFORMATION tzi;
REG_TZI_FORMAT regTzi;
DWORD regTziSize = sizeof(regTzi);
- const QString tziKeyPath = QString::fromWCharArray(tzRegPath) + QLatin1Char('\\')
+ const QString tziKeyPath = QString::fromWCharArray(tzRegPath) + u'\\'
+ QString::fromUtf8(windowsId);
QWinRegistryKey key(HKEY_LOCAL_MACHINE, tziKeyPath);
@@ -198,22 +186,24 @@ bool isSameRule(const QWinTimeZonePrivate::QWinTransitionRule &last,
QList<QByteArray> availableWindowsIds()
{
- // TODO Consider caching results in a global static, very unlikely to change.
- QList<QByteArray> list;
- QWinRegistryKey key(HKEY_LOCAL_MACHINE, tzRegPath);
- if (key.isValid()) {
- DWORD idCount = 0;
- if (RegQueryInfoKey(key, 0, 0, 0, &idCount, 0, 0, 0, 0, 0, 0, 0) == ERROR_SUCCESS
- && idCount > 0) {
- for (DWORD i = 0; i < idCount; ++i) {
- DWORD maxLen = MAX_KEY_LENGTH;
- TCHAR buffer[MAX_KEY_LENGTH];
- if (RegEnumKeyEx(key, i, buffer, &maxLen, 0, 0, 0, 0) == ERROR_SUCCESS)
- list.append(QString::fromWCharArray(buffer).toUtf8());
+ static const QList<QByteArray> cache = [] {
+ QList<QByteArray> list;
+ QWinRegistryKey key(HKEY_LOCAL_MACHINE, tzRegPath);
+ if (key.isValid()) {
+ DWORD idCount = 0;
+ if (RegQueryInfoKey(key, 0, 0, 0, &idCount, 0, 0, 0, 0, 0, 0, 0) == ERROR_SUCCESS
+ && idCount > 0) {
+ for (DWORD i = 0; i < idCount; ++i) {
+ DWORD maxLen = MAX_KEY_LENGTH;
+ TCHAR buffer[MAX_KEY_LENGTH];
+ if (RegEnumKeyEx(key, i, buffer, &maxLen, 0, 0, 0, 0) == ERROR_SUCCESS)
+ list.append(QString::fromWCharArray(buffer).toUtf8());
+ }
}
}
- }
- return list;
+ return list;
+ }();
+ return cache;
}
QByteArray windowsSystemZoneId()
@@ -275,11 +265,20 @@ QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
return date;
}
-// Converts a date/time value into msecs
-inline qint64 timeToMSecs(QDate date, QTime time)
+// Converts a date/time value into msecs, returns true on overflow:
+inline bool timeToMSecs(QDate date, QTime time, qint64 *msecs)
{
- return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
- + time.msecsSinceStartOfDay();
+ qint64 dayms = 0;
+ qint64 daySinceEpoch = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
+ qint64 msInDay = time.msecsSinceStartOfDay();
+ if (daySinceEpoch < 0 && msInDay > 0) {
+ // In the earliest day with representable parts, take care to not
+ // underflow before an addition that would have fixed it.
+ ++daySinceEpoch;
+ msInDay -= MSECS_PER_DAY;
+ }
+ return qMulOverflow(daySinceEpoch, std::integral_constant<qint64, MSECS_PER_DAY>(), &dayms)
+ || qAddOverflow(dayms, msInDay, msecs);
}
qint64 calculateTransitionForYear(const SYSTEMTIME &rule, int year, int bias)
@@ -289,17 +288,42 @@ qint64 calculateTransitionForYear(const SYSTEMTIME &rule, int year, int bias)
Q_ASSERT(year);
const QDate date = calculateTransitionLocalDate(rule, year);
const QTime time = QTime(rule.wHour, rule.wMinute, rule.wSecond);
- if (date.isValid() && time.isValid())
- return timeToMSecs(date, time) + bias * 60000;
+ qint64 msecs = 0;
+ if (date.isValid() && time.isValid() && !timeToMSecs(date, time, &msecs)) {
+ // If bias pushes us outside the representable range, clip to range
+ // (overflow went past the end bias pushed us towards; and
+ // invalidMSecs() is a representable value less than minMSecs()):
+ return bias && qAddOverflow(msecs, qint64(bias) * 60000, &msecs)
+ ? (bias < 0 ? QTimeZonePrivate::minMSecs() : QTimeZonePrivate::maxMSecs())
+ : qMax(QTimeZonePrivate::minMSecs(), msecs);
+ }
return QTimeZonePrivate::invalidMSecs();
}
+// True precisely if transition represents the start of the year.
+bool isAtStartOfYear(const SYSTEMTIME &transition, int year)
+{
+ /*
+ Note that, here, wDay identifies an instance of a given day-of-week in the
+ month, with 5 meaning last. (December 31st is, incidentally, always the
+ fifth instance of its day of the week in its month. But we aren't testing
+ that - see below.)
+
+ QDate represents Sunday by 7, SYSTEMTIME by 0; so compare day of the week
+ by taking difference mod 7.
+ */
+ return transition.wMonth == 1 && transition.wDay == 1
+ && (QDate(year, 1, 1).dayOfWeek() - transition.wDayOfWeek) % 7 == 0
+ && transition.wHour == 0 && transition.wMinute == 0 && transition.wSecond == 0;
+}
+
struct TransitionTimePair
{
- // Transition times after the epoch, in ms:
+ // Transition times, in ms:
qint64 std, dst;
// If either is invalidMSecs(), which shall then be < the other, there is no
// DST and the other describes a change in actual standard offset.
+ bool fakesDst = false;
TransitionTimePair(const QWinTimeZonePrivate::QWinTransitionRule &rule,
int year, int oldYearOffset)
@@ -315,16 +339,36 @@ struct TransitionTimePair
year, or expresses a transition of each kind, even if standard time
did change in a year with no DST. We've seen year-start fake-DST
(whose offset matches prior standard offset, in which the previous
- year ended); and conjecture that similar might be used at a year-end.
- (This might be used for a southern-hemisphere zone, where the start of
- the year usually is in DST, when applicable.) Note that, here, wDay
- identifies an instance of a given day-of-week in the month, with 5
- meaning last.
+ year ended).
+
+ It is possible there might also be year-end fake-DST but Bangladesh
+ toyed with DST from 2009-06-19 (a Friday) at 23:00 until, according to
+ the Olson database, 2009-12-32 24:00; however, MS represents that by
+ the last millisecond of the year, technically a millisecond early. (MS
+ falsely claims Bhutan did the same.) So we do not attempt to detect an
+ end-of-year fake transition; nor is there any reason to suppose MS
+ would need to do that, as anything it could implement thereby could
+ equally be implemented by a start-of-year fake.
+
+ A fake transition at the start of the year tells us what the offset at
+ the start of the year is; if this doesn't match the offset in effect
+ at the end of the previous year, then it's a real transition. If it
+ does match, then we have a fake transition. (A fake transition of one
+ kind at the end of the year would be paired with a real transition,
+ allegedly of the other kind, part way through the year; that would be
+ a transition away from the offset that would nominally be restored by
+ the fake so, again, the year would have started with the post-fake
+ offset in effect.)
Either the alleged standardTimeRule or the alleged daylightTimeRule
may be faked; either way, the transition is actually a change to the
current standard offset; but the unfaked half of the rule contains the
- useful bias data, so we have to go along with its lies.
+ useful bias data, so we have to go along with its lies. Clients of
+ this class should still use DaylightTime and StandardTime as if the
+ fake were not a lie, selecting which side of the real transition to
+ use the data for, and ruleToData() will take care of extracting the
+ right offset based on that, while tagging the resulting Data as
+ standard time.
Example: Russia/Moscow
Format: -bias +( -stdBias, stdDate | -dstBias, dstDate ) notes
@@ -334,32 +378,47 @@ struct TransitionTimePair
Zone change in 2014: 180 +( 0, 0-10-5 2:0 | 60, 0-1-1 0:0 ) fake DST at year-start
The last of these is missing on Win7 VMs (too old to know about it).
*/
- if (rule.daylightTimeRule.wMonth == 1 && rule.daylightTimeRule.wDay == 1) {
- // Fake "DST transition" at start of year producing the same offset as
- // previous year ended in.
- if (rule.standardTimeBias + rule.daylightTimeBias == oldYearOffset)
- dst = QTimeZonePrivate::invalidMSecs();
- } else if (rule.daylightTimeRule.wMonth == 12 && rule.daylightTimeRule.wDay > 3) {
- // Similar, conjectured, for end of year, not changing offset.
- if (rule.daylightTimeBias == 0)
- dst = QTimeZonePrivate::invalidMSecs();
+ if (rule.standardTimeBias + rule.daylightTimeBias == oldYearOffset
+ && isAtStartOfYear(rule.daylightTimeRule, year)) {
+ dst = QTimeZonePrivate::invalidMSecs();
+ fakesDst = true;
}
- if (rule.standardTimeRule.wMonth == 1 && rule.standardTimeRule.wDay == 1) {
- // Fake "transition out of DST" at start of year producing the same
- // offset as previous year ended in.
- if (rule.standardTimeBias == oldYearOffset)
- std = QTimeZonePrivate::invalidMSecs();
- } else if (rule.standardTimeRule.wMonth == 12 && rule.standardTimeRule.wDay > 3) {
- // Similar, conjectured, for end of year, not changing offset.
- if (rule.daylightTimeBias == 0)
- std = QTimeZonePrivate::invalidMSecs();
+ if (rule.standardTimeBias == oldYearOffset
+ && isAtStartOfYear(rule.standardTimeRule, year)) {
+ Q_ASSERT_X(!fakesDst, "TransitionTimePair",
+ "Year with (DST bias zero and) both transitions fake !");
+ std = QTimeZonePrivate::invalidMSecs();
+ fakesDst = true;
}
}
- bool fakesDst() const
+ bool startsInDst() const
+ {
+ // Year starts in daylightTimeRule iff it has a valid transition out of
+ // DST with no earlier valid transition into it.
+ return std != QTimeZonePrivate::invalidMSecs()
+ && (std < dst || dst == QTimeZonePrivate::invalidMSecs());
+ }
+
+ // Returns true if (assuming this pair was derived from the first rule, and
+ // that has non-zero wMonth values, so is a DST-recurrence or faking it) the
+ // given millis, presumed to be in the given year, is before the first
+ // transition into DST.
+ bool beforeInitialDst(int year, qint64 millis) const
+ {
+ return !fakesDst && (year == FIRST_DST_YEAR ? millis < dst : year < FIRST_DST_YEAR);
+ }
+
+ QTimeZonePrivate::Data ruleToData(const QWinTimeZonePrivate::QWinTransitionRule &rule,
+ const QWinTimeZonePrivate *tzp, bool isDst) const
{
- return std == QTimeZonePrivate::invalidMSecs()
- || dst == QTimeZonePrivate::invalidMSecs();
+ const auto type = isDst ? QTimeZone::DaylightTime : QTimeZone::StandardTime;
+ auto time = isDst ? dst : std;
+ // The isDst we're asked for may be set to the valid one of dst and
+ // std, when fake, but not always - so make sure:
+ if (fakesDst && time == QTimeZonePrivate::invalidMSecs())
+ time = isDst ? std : dst;
+ return tzp->ruleToData(rule, time, type, fakesDst);
}
};
@@ -376,16 +435,16 @@ int yearEndOffset(const QWinTimeZonePrivate::QWinTransitionRule &rule, int year)
return offset;
}
-QLocale::Country userCountry()
+QLocale::Territory userTerritory()
{
const GEOID id = GetUserGeoID(GEOCLASS_NATION);
wchar_t code[3];
const int size = GetGeoInfo(id, GEO_ISO2, code, 3, 0);
- return (size == 3) ? QLocalePrivate::codeToCountry(QStringView(code, size))
- : QLocale::AnyCountry;
+ return (size == 3) ? QLocalePrivate::codeToTerritory(QStringView(code, size))
+ : QLocale::AnyTerritory;
}
-// Index of last rule in rules with .startYear <= year:
+// Index of last rule in rules with .startYear <= year, or 0 if none satisfies that:
int ruleIndexForYear(const QList<QWinTimeZonePrivate::QWinTransitionRule> &rules, int year)
{
if (rules.last().startYear <= year)
@@ -454,11 +513,19 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
m_windowsId = ianaIdToWindowsId(ianaId);
m_id = ianaId;
}
+ const auto initialYear = [](const QWinTransitionRule &rule) {
+ // Only applicable to the first rule, and only if not faking DST.
+ // The rule starts in FIRST_DST_YEAR if it is a DST recurrence (with
+ // non-zero wMonth fields), otherwise read as a constant
+ // offset rule dating back to the start of time.
+ return (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0
+ ? FIRST_DST_YEAR : int(QDateTime::YearRange::First));
+ };
bool badMonth = false; // Only warn once per zone, if at all.
if (!m_windowsId.isEmpty()) {
// Open the base TZI for the time zone
- const QString baseKeyPath = QString::fromWCharArray(tzRegPath) + QLatin1Char('\\')
+ const QString baseKeyPath = QString::fromWCharArray(tzRegPath) + u'\\'
+ QString::fromUtf8(m_windowsId);
QWinRegistryKey baseKey(HKEY_LOCAL_MACHINE, baseKeyPath);
if (baseKey.isValid()) {
@@ -467,7 +534,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
m_standardName = baseKey.stringValue(L"Std");
m_daylightName = baseKey.stringValue(L"Dlt");
// On Vista and later the optional dynamic key holds historic data
- const QString dynamicKeyPath = baseKeyPath + QLatin1String("\\Dynamic DST");
+ const QString dynamicKeyPath = baseKeyPath + "\\Dynamic DST"_L1;
QWinRegistryKey dynamicKey(HKEY_LOCAL_MACHINE, dynamicKeyPath);
if (dynamicKey.isValid()) {
// Find out the start and end years stored, then iterate over them
@@ -475,9 +542,10 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
const auto endYear = dynamicKey.dwordValue(L"LastEntry");
for (int year = int(startYear.first); year <= int(endYear.first); ++year) {
bool ruleOk;
- QWinTransitionRule rule = readRegistryRule(dynamicKey,
- reinterpret_cast<LPCWSTR>(QString::number(year).utf16()),
- &ruleOk);
+ QWinTransitionRule rule =
+ readRegistryRule(dynamicKey,
+ reinterpret_cast<LPCWSTR>(QString::number(year).utf16()),
+ &ruleOk);
if (ruleOk
// Don't repeat a recurrent rule:
&& (m_tranRules.isEmpty()
@@ -490,7 +558,10 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
"this may cause mistakes for %s from %d",
ianaId.constData(), year);
}
- rule.startYear = m_tranRules.isEmpty() ? MIN_YEAR : year;
+ const TransitionTimePair pair(rule, year, rule.standardTimeBias);
+ // First rule may be a standard offset change, for which fakesDst is true.
+ rule.startYear
+ = m_tranRules.size() || pair.fakesDst ? year : initialYear(rule);
m_tranRules.append(rule);
}
}
@@ -498,9 +569,10 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
// No dynamic data so use the base data
bool ruleOk;
QWinTransitionRule rule = readRegistryRule(baseKey, L"TZI", &ruleOk);
- rule.startYear = MIN_YEAR;
- if (ruleOk)
+ if (ruleOk) {
+ rule.startYear = initialYear(rule);
m_tranRules.append(rule);
+ }
}
}
}
@@ -510,6 +582,8 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
m_id.clear();
m_windowsId.clear();
m_displayName.clear();
+ } else if (m_id.isEmpty()) {
+ m_id = m_standardName.toUtf8();
}
}
@@ -581,42 +655,44 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
ruleIndex >= 0; --ruleIndex) {
const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
- // Does this rule's period include any transition at all ?
- if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
- int prior = year == 1 ? -1 : year - 1; // No year 0.
- const int endYear = qMax(rule.startYear, prior);
- while (year >= endYear) {
- const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
- ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
- : yearEndOffset(rule, prior);
- const TransitionTimePair pair(rule, year, newYearOffset);
- bool isDst = false;
- if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) {
- isDst = pair.std < pair.dst && pair.dst <= forMSecsSinceEpoch;
- } else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) {
- isDst = true;
- } else {
- year = prior; // Try an earlier year for this rule (once).
- prior = year == 1 ? -1 : year - 1; // No year 0.
- continue;
- }
- return ruleToData(rule, forMSecsSinceEpoch,
- isDst ? QTimeZone::DaylightTime : QTimeZone::StandardTime,
- pair.fakesDst());
- }
- // Fell off start of rule, try previous rule.
- } else {
- // No transition, no DST, use the year's standard time.
+ Q_ASSERT(ruleIndex == 0 || year >= rule.startYear);
+ if (year < rule.startYear
+ || !(rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0)) {
+ // No transition (or before first rule), no DST, use the rule's standard time.
return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::StandardTime);
}
- if (year >= rule.startYear) {
- year = rule.startYear - 1; // Seek last transition in new rule.
- if (!year)
- --year;
+
+ int prior = year == 1 ? -1 : year - 1; // No year 0.
+ const int endYear = qMax(rule.startYear, prior);
+ while (year >= endYear) {
+ const int newYearOffset = (prior < rule.startYear && ruleIndex > 0)
+ ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
+ : yearEndOffset(rule, prior);
+ const TransitionTimePair pair(rule, year, newYearOffset);
+ bool isDst = false;
+ if (ruleIndex == 0 && pair.beforeInitialDst(year, forMSecsSinceEpoch)) {
+ // We're before DST first started and have no earlier rule that
+ // might give better data on this year, so just extrapolate
+ // standard time backwards.
+ } else if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) {
+ isDst = pair.std < pair.dst && pair.dst <= forMSecsSinceEpoch;
+ } else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) {
+ isDst = true;
+ } else {
+ year = prior; // Try an earlier year for this rule (once).
+ prior = year == 1 ? -1 : year - 1; // No year 0.
+ continue;
+ }
+ return ruleToData(rule, forMSecsSinceEpoch,
+ isDst ? QTimeZone::DaylightTime : QTimeZone::StandardTime,
+ pair.fakesDst);
}
+ // We can only fall off the end of that loop if endYear is rule.startYear:
+ Q_ASSERT(year < rule.startYear);
+ // Fell off start of rule, try previous rule.
}
// We don't have relevant data :-(
- return invalidData();
+ return {};
}
bool QWinTimeZonePrivate::hasTransitions() const
@@ -631,24 +707,46 @@ bool QWinTimeZonePrivate::hasTransitions() const
QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
{
int year = msecsToDate(afterMSecsSinceEpoch).year();
+ int newYearOffset = invalidSeconds();
for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
ruleIndex < m_tranRules.count(); ++ruleIndex) {
const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
// Does this rule's period include any transition at all ?
if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
- if (year < rule.startYear)
- year = rule.startYear; // Seek first transition in this rule.
+ int prior = year == 1 ? -1 : year - 1; // No year 0.
+ if (newYearOffset == invalidSeconds()) {
+ // First rule tried. (Will revise newYearOffset before any
+ // fall-back to a later rule.)
+ newYearOffset = (prior < rule.startYear && ruleIndex > 0)
+ ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
+ : yearEndOffset(rule, prior);
+ }
+ if (year < rule.startYear) {
+ // Either before first rule's start, or we fell off the end of
+ // the rule for year because afterMSecsSinceEpoch is after any
+ // transitions in it. Find first transition in this rule.
+ TransitionTimePair pair(rule, rule.startYear, newYearOffset);
+ // First transition is to DST precisely if the year started in
+ // standard time. If the year is FIRST_DST_YEAR or earlier, it
+ // definitely started in standard time.
+ return pair.ruleToData(rule, this, !(year > FIRST_DST_YEAR && pair.startsInDst()));
+ }
const int endYear = ruleIndex + 1 < m_tranRules.count()
? qMin(m_tranRules.at(ruleIndex + 1).startYear, year + 2) : (year + 2);
- int prior = year == 1 ? -1 : year - 1; // No year 0.
- int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
- ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
- : yearEndOffset(rule, prior);
while (year < endYear) {
const TransitionTimePair pair(rule, year, newYearOffset);
bool isDst = false;
Q_ASSERT(invalidMSecs() <= afterMSecsSinceEpoch); // invalid is min qint64
- if (pair.std > afterMSecsSinceEpoch) {
+ if (ruleIndex == 0 && pair.beforeInitialDst(year, afterMSecsSinceEpoch)) {
+ // This is an initial recurrence rule, whose startYear
+ // (which we know is <= year) is FIRST_DST_YEAR:
+ Q_ASSERT(year == FIRST_DST_YEAR);
+ // This year's DST transition is the first ever DST
+ // transition, and we're before it. The transition back to
+ // standard time is a lie unless the DST one comes before
+ // it; either way, the DST one is next.
+ isDst = true;
+ } else if (pair.std > afterMSecsSinceEpoch) {
isDst = pair.std > pair.dst && pair.dst > afterMSecsSinceEpoch;
} else if (pair.dst > afterMSecsSinceEpoch) {
isDst = true;
@@ -662,36 +760,50 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
continue;
}
- if (isDst)
- return ruleToData(rule, pair.dst, QTimeZone::DaylightTime, pair.fakesDst());
- return ruleToData(rule, pair.std, QTimeZone::StandardTime, pair.fakesDst());
+ return pair.ruleToData(rule, this, isDst);
}
// Fell off end of rule, try next rule.
- } // else: no transition during rule's period
+ } else {
+ // No transition during rule's period. If this is our first rule,
+ // record its standard time as newYearOffset for the next rule;
+ // otherwise, it should be consistent with what we have.
+ if (newYearOffset == invalidSeconds())
+ newYearOffset = rule.standardTimeBias;
+ else
+ Q_ASSERT(newYearOffset == rule.standardTimeBias);
+ }
}
// Apparently no transition after the given time:
- return invalidData();
+ return {};
}
QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
- const qint64 startOfTime = invalidMSecs() + 1;
- if (beforeMSecsSinceEpoch <= startOfTime)
- return invalidData();
+ if (beforeMSecsSinceEpoch <= minMSecs())
+ return {};
int year = msecsToDate(beforeMSecsSinceEpoch).year();
for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
ruleIndex >= 0; --ruleIndex) {
const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
+ Q_ASSERT(ruleIndex == 0 || year >= rule.startYear);
// Does this rule's period include any transition at all ?
- if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
+ if (year >= rule.startYear
+ && (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0)) {
int prior = year == 1 ? -1 : year - 1; // No year 0.
const int endYear = qMax(rule.startYear, prior);
while (year >= endYear) {
- const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
+ const int newYearOffset = (prior < rule.startYear && ruleIndex > 0)
? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
: yearEndOffset(rule, prior);
const TransitionTimePair pair(rule, year, newYearOffset);
+ // A recurrent DST rule, before DST first started, is a lie:
+ // fake a first transition at the start of time, as for the
+ // other (ruleIndex == 0) case below. Same applies to first
+ // instant of DST; there is no prior (real) transition.
+ if (ruleIndex == 0 && pair.beforeInitialDst(year, beforeMSecsSinceEpoch - 1))
+ return ruleToData(rule, minMSecs(), QTimeZone::StandardTime, false);
+
bool isDst = false;
if (pair.std != invalidMSecs() && pair.std < beforeMSecsSinceEpoch) {
isDst = pair.std < pair.dst && pair.dst < beforeMSecsSinceEpoch;
@@ -702,16 +814,14 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec
prior = year == 1 ? -1 : year - 1; // No year 0.
continue;
}
- if (isDst)
- return ruleToData(rule, pair.dst, QTimeZone::DaylightTime, pair.fakesDst());
- return ruleToData(rule, pair.std, QTimeZone::StandardTime, pair.fakesDst());
+ return pair.ruleToData(rule, this, isDst);
}
// Fell off start of rule, try previous rule.
} else if (ruleIndex == 0) {
- // Treat a no-transition first rule as a transition at the start of
- // time, so that a scan through all rules *does* see it as the first
- // rule:
- return ruleToData(rule, startOfTime, QTimeZone::StandardTime, false);
+ // Describe time before the first transition in terms of a fictional
+ // transition at the start of time, so that a scan through all rules
+ // *does* see a first rule that supplies the offset for such times:
+ return ruleToData(rule, minMSecs(), QTimeZone::StandardTime, false);
} // else: no transition during rule's period
if (year >= rule.startYear) {
year = rule.startYear - 1; // Seek last transition in new rule
@@ -720,36 +830,35 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec
}
}
// Apparently no transition before the given time:
- return invalidData();
+ return {};
}
QByteArray QWinTimeZonePrivate::systemTimeZoneId() const
{
- const QLocale::Country country = userCountry();
+ const QLocale::Territory territory = userTerritory();
const QByteArray windowsId = windowsSystemZoneId();
QByteArray ianaId;
- // If we have a real country, then try get a specific match for that country
- if (country != QLocale::AnyCountry)
- ianaId = windowsIdToDefaultIanaId(windowsId, country);
- // If we don't have a real country, or there wasn't a specific match, try the global default
- if (ianaId.isEmpty()) {
+ // If we have a real territory, then try get a specific match for that territory
+ if (territory != QLocale::AnyTerritory)
+ ianaId = windowsIdToDefaultIanaId(windowsId, territory);
+ // If we don't have a real territory, or there wasn't a specific match, try the global default
+ if (ianaId.isEmpty())
ianaId = windowsIdToDefaultIanaId(windowsId);
- // If no global default then probably an unknown Windows ID so return UTC
- if (ianaId.isEmpty())
- return utcQByteArray();
- }
return ianaId;
}
QList<QByteArray> QWinTimeZonePrivate::availableTimeZoneIds() const
{
- QList<QByteArray> result;
- const auto winIds = availableWindowsIds();
- for (const QByteArray &winId : winIds)
- result += windowsIdToIanaIds(winId);
- std::sort(result.begin(), result.end());
- result.erase(std::unique(result.begin(), result.end()), result.end());
- return result;
+ static const QList<QByteArray> cache = [] {
+ QList<QByteArray> result;
+ const auto winIds = availableWindowsIds();
+ for (const QByteArray &winId : winIds)
+ result += windowsIdToIanaIds(winId);
+ std::sort(result.begin(), result.end());
+ result.erase(std::unique(result.begin(), result.end()), result.end());
+ return result;
+ }();
+ return cache;
}
QTimeZonePrivate::Data QWinTimeZonePrivate::ruleToData(const QWinTransitionRule &rule,
@@ -757,7 +866,7 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::ruleToData(const QWinTransitionRule
QTimeZone::TimeType type,
bool fakeDst) const
{
- Data tran = invalidData();
+ Data tran;
tran.atMSecsSinceEpoch = atMSecsSinceEpoch;
tran.standardTimeOffset = rule.standardTimeBias * -60;
if (fakeDst) {
diff --git a/src/corelib/time/time.pri b/src/corelib/time/time.pri
deleted file mode 100644
index 84efbfbfd2..0000000000
--- a/src/corelib/time/time.pri
+++ /dev/null
@@ -1,71 +0,0 @@
-# Qt time / date / zone / calendar module
-
-HEADERS += \
- time/qcalendar.h \
- time/qcalendarbackend_p.h \
- time/qcalendarmath_p.h \
- time/qdatetime.h \
- time/qdatetime_p.h \
- time/qgregoriancalendar_p.h \
- time/qjuliancalendar_p.h \
- time/qmilankoviccalendar_p.h \
- time/qromancalendar_p.h \
- time/qromancalendar_data_p.h
-
-SOURCES += \
- time/qdatetime.cpp \
- time/qcalendar.cpp \
- time/qgregoriancalendar.cpp \
- time/qjuliancalendar.cpp \
- time/qmilankoviccalendar.cpp \
- time/qromancalendar.cpp
-
-qtConfig(hijricalendar) {
- SOURCES += \
- time/qhijricalendar.cpp
- HEADERS += \
- time/qhijricalendar_p.h \
- time/qhijricalendar_data_p.h
-}
-
-qtConfig(islamiccivilcalendar) {
- SOURCES += \
- time/qislamiccivilcalendar.cpp
- HEADERS += \
- time/qislamiccivilcalendar_p.h
-}
-
-qtConfig(jalalicalendar) {
- SOURCES += \
- time/qjalalicalendar.cpp
- HEADERS += \
- time/qjalalicalendar_p.h \
- time/qjalalicalendar_data_p.h
-}
-
-qtConfig(timezone) {
- HEADERS += \
- time/qtimezone.h \
- time/qtimezoneprivate_p.h \
- time/qtimezoneprivate_data_p.h
- SOURCES += \
- time/qtimezone.cpp \
- time/qtimezoneprivate.cpp
- !nacl:darwin: {
- SOURCES += time/qtimezoneprivate_mac.mm
- } else: android:!android-embedded: {
- SOURCES += time/qtimezoneprivate_android.cpp
- } else: unix: {
- SOURCES += time/qtimezoneprivate_tz.cpp
- qtConfig(icu): SOURCES += time/qtimezoneprivate_icu.cpp
- } else: qtConfig(icu): {
- SOURCES += time/qtimezoneprivate_icu.cpp
- } else: win32: {
- SOURCES += time/qtimezoneprivate_win.cpp
- }
-}
-
-qtConfig(datetimeparser) {
- HEADERS += time/qdatetimeparser_p.h
- SOURCES += time/qdatetimeparser.cpp
-}
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index 838e8472d8..8889effece 100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -1,317 +1,24 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QALGORITHMS_H
#define QALGORITHMS_H
-#include <QtCore/qglobal.h>
-
-#ifdef Q_CC_MSVC
-#include <intrin.h>
+#if 0
+#pragma qt_class(QtAlgorithms)
#endif
-QT_BEGIN_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-
-/*
- Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
- and may be changed from version to version or even be completely removed.
-*/
-namespace QAlgorithmsPrivate {
-
-#if QT_DEPRECATED_SINCE(5, 2)
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::sort") Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy);
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::stable_sort") Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &);
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
-#endif // QT_DEPRECATED_SINCE(5, 2)
-
-}
-
-#if QT_DEPRECATED_SINCE(5, 2)
-template <typename InputIterator, typename OutputIterator>
-QT_DEPRECATED_X("Use std::copy") inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest)
-{
- while (begin != end)
- *dest++ = *begin++;
- return dest;
-}
-
-template <typename BiIterator1, typename BiIterator2>
-QT_DEPRECATED_X("Use std::copy_backward") inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest)
-{
- while (begin != end)
- *--dest = *--end;
- return dest;
-}
-
-template <typename InputIterator1, typename InputIterator2>
-QT_DEPRECATED_X("Use std::equal") inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
-{
- for (; first1 != last1; ++first1, ++first2)
- if (!(*first1 == *first2))
- return false;
- return true;
-}
-
-template <typename ForwardIterator, typename T>
-QT_DEPRECATED_X("Use std::fill") inline void qFill(ForwardIterator first, ForwardIterator last, const T &val)
-{
- for (; first != last; ++first)
- *first = val;
-}
-
-template <typename Container, typename T>
-QT_DEPRECATED_X("Use std::fill") inline void qFill(Container &container, const T &val)
-{
- qFill(container.begin(), container.end(), val);
-}
-
-template <typename InputIterator, typename T>
-QT_DEPRECATED_X("Use std::find") inline InputIterator qFind(InputIterator first, InputIterator last, const T &val)
-{
- while (first != last && !(*first == val))
- ++first;
- return first;
-}
-
-template <typename Container, typename T>
-QT_DEPRECATED_X("Use std::find") inline typename Container::const_iterator qFind(const Container &container, const T &val)
-{
- return qFind(container.constBegin(), container.constEnd(), val);
-}
-
-template <typename InputIterator, typename T, typename Size>
-QT_DEPRECATED_X("Use std::count") inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n)
-{
- for (; first != last; ++first)
- if (*first == value)
- ++n;
-}
-
-template <typename Container, typename T, typename Size>
-QT_DEPRECATED_X("Use std::count") inline void qCount(const Container &container, const T &value, Size &n)
-{
- qCount(container.constBegin(), container.constEnd(), value, n);
-}
-
-#ifdef Q_QDOC
-typedef void* LessThan;
-template <typename T> LessThan qLess();
-template <typename T> LessThan qGreater();
-#else
-template <typename T>
-class QT_DEPRECATED_X("Use std::less") qLess
-{
-public:
- inline bool operator()(const T &t1, const T &t2) const
- {
- return (t1 < t2);
- }
-};
-
-template <typename T>
-class QT_DEPRECATED_X("Use std::greater") qGreater
-{
-public:
- inline bool operator()(const T &t1, const T &t2) const
- {
- return (t2 < t1);
- }
-};
-#endif
-
-template <typename RandomAccessIterator>
-QT_DEPRECATED_X("Use std::sort") inline void qSort(RandomAccessIterator start, RandomAccessIterator end)
-{
- if (start != end)
- QAlgorithmsPrivate::qSortHelper(start, end, *start);
-}
-
-template <typename RandomAccessIterator, typename LessThan>
-QT_DEPRECATED_X("Use std::sort") inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
-{
- if (start != end)
- QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan);
-}
+#include <QtCore/qglobal.h>
-template<typename Container>
-QT_DEPRECATED_X("Use std::sort") inline void qSort(Container &c)
-{
-#ifdef Q_CC_BOR
- // Work around Borland 5.5 optimizer bug
- c.detach();
+#if __has_include(<bit>) && __cplusplus > 201703L
+#include <bit>
#endif
- if (!c.empty())
- QAlgorithmsPrivate::qSortHelper(c.begin(), c.end(), *c.begin());
-}
-
-template <typename RandomAccessIterator>
-QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end)
-{
- if (start != end)
- QAlgorithmsPrivate::qStableSortHelper(start, end, *start);
-}
-template <typename RandomAccessIterator, typename LessThan>
-QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
-{
- if (start != end)
- QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan);
-}
-
-template<typename Container>
-QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSort(Container &c)
-{
-#ifdef Q_CC_BOR
- // Work around Borland 5.5 optimizer bug
- c.detach();
+#ifdef Q_CC_MSVC
+#include <intrin.h>
#endif
- if (!c.empty())
- QAlgorithmsPrivate::qStableSortHelper(c.begin(), c.end(), *c.begin());
-}
-
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
-{
- // Implementation is duplicated from QAlgorithmsPrivate to keep existing code
- // compiling. We have to allow using *begin and value with different types,
- // and then implementing operator< for those types.
- RandomAccessIterator middle;
- int n = end - begin;
- int half;
-
- while (n > 0) {
- half = n >> 1;
- middle = begin + half;
- if (*middle < value) {
- begin = middle + 1;
- n -= half + 1;
- } else {
- n = half;
- }
- }
- return begin;
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
-{
- return QAlgorithmsPrivate::qLowerBoundHelper(begin, end, value, lessThan);
-}
-
-template <typename Container, typename T>
-QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value)
-{
- return QAlgorithmsPrivate::qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
-}
-
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
-{
- // Implementation is duplicated from QAlgorithmsPrivate.
- RandomAccessIterator middle;
- int n = end - begin;
- int half;
-
- while (n > 0) {
- half = n >> 1;
- middle = begin + half;
- if (value < *middle) {
- n = half;
- } else {
- begin = middle + 1;
- n -= half + 1;
- }
- }
- return begin;
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
-{
- return QAlgorithmsPrivate::qUpperBoundHelper(begin, end, value, lessThan);
-}
-
-template <typename Container, typename T>
-QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value)
-{
- return QAlgorithmsPrivate::qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
-}
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
-{
- // Implementation is duplicated from QAlgorithmsPrivate.
- RandomAccessIterator it = qLowerBound(begin, end, value);
-
- if (it == end || value < *it)
- return end;
-
- return it;
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
-{
- return QAlgorithmsPrivate::qBinaryFindHelper(begin, end, value, lessThan);
-}
-
-template <typename Container, typename T>
-QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value)
-{
- return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
-}
-#endif // QT_DEPRECATED_SINCE(5, 2)
+QT_BEGIN_NAMESPACE
template <typename ForwardIterator>
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
@@ -334,206 +41,13 @@ inline void qDeleteAll(const Container &c)
*/
namespace QAlgorithmsPrivate {
-#if QT_DEPRECATED_SINCE(5, 2)
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::sort") Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
-{
-top:
- int span = int(end - start);
- if (span < 2)
- return;
-
- --end;
- RandomAccessIterator low = start, high = end - 1;
- RandomAccessIterator pivot = start + span / 2;
-
- if (lessThan(*end, *start))
- qSwap(*end, *start);
- if (span == 2)
- return;
-
- if (lessThan(*pivot, *start))
- qSwap(*pivot, *start);
- if (lessThan(*end, *pivot))
- qSwap(*end, *pivot);
- if (span == 3)
- return;
-
- qSwap(*pivot, *end);
-
- while (low < high) {
- while (low < high && lessThan(*low, *end))
- ++low;
-
- while (high > low && lessThan(*end, *high))
- --high;
-
- if (low < high) {
- qSwap(*low, *high);
- ++low;
- --high;
- } else {
- break;
- }
- }
-
- if (lessThan(*low, *end))
- ++low;
-
- qSwap(*end, *low);
- qSortHelper(start, low, t, lessThan);
-
- start = low + 1;
- ++end;
- goto top;
-}
-
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::sort") inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
-{
- qSortHelper(begin, end, dummy, qLess<T>());
-}
-
-template <typename RandomAccessIterator>
-QT_DEPRECATED_X("Use std::reverse") Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end)
-{
- --end;
- while (begin < end)
- qSwap(*begin++, *end--);
-}
-
-template <typename RandomAccessIterator>
-QT_DEPRECATED_X("Use std::rotate") Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end)
-{
- qReverse(begin, middle);
- qReverse(middle, end);
- qReverse(begin, end);
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::merge") Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan)
-{
- const int len1 = pivot - begin;
- const int len2 = end - pivot;
-
- if (len1 == 0 || len2 == 0)
- return;
-
- if (len1 + len2 == 2) {
- if (lessThan(*(begin + 1), *(begin)))
- qSwap(*begin, *(begin + 1));
- return;
- }
-
- RandomAccessIterator firstCut;
- RandomAccessIterator secondCut;
- int len2Half;
- if (len1 > len2) {
- const int len1Half = len1 / 2;
- firstCut = begin + len1Half;
- secondCut = qLowerBound(pivot, end, *firstCut, lessThan);
- len2Half = secondCut - pivot;
- } else {
- len2Half = len2 / 2;
- secondCut = pivot + len2Half;
- firstCut = qUpperBound(begin, pivot, *secondCut, lessThan);
- }
-
- qRotate(firstCut, pivot, secondCut);
- const RandomAccessIterator newPivot = firstCut + len2Half;
- qMerge(begin, firstCut, newPivot, t, lessThan);
- qMerge(newPivot, secondCut, end, t, lessThan);
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::stable_sort") Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan)
-{
- const int span = end - begin;
- if (span < 2)
- return;
-
- const RandomAccessIterator middle = begin + span / 2;
- qStableSortHelper(begin, middle, t, lessThan);
- qStableSortHelper(middle, end, t, lessThan);
- qMerge(begin, middle, end, t, lessThan);
-}
-
-template <typename RandomAccessIterator, typename T>
-QT_DEPRECATED_X("Use std::stable_sort") inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
-{
- qStableSortHelper(begin, end, dummy, qLess<T>());
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::lower_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
-{
- RandomAccessIterator middle;
- int n = int(end - begin);
- int half;
-
- while (n > 0) {
- half = n >> 1;
- middle = begin + half;
- if (lessThan(*middle, value)) {
- begin = middle + 1;
- n -= half + 1;
- } else {
- n = half;
- }
- }
- return begin;
-}
-
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::upper_bound") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
-{
- RandomAccessIterator middle;
- int n = end - begin;
- int half;
-
- while (n > 0) {
- half = n >> 1;
- middle = begin + half;
- if (lessThan(value, *middle)) {
- n = half;
- } else {
- begin = middle + 1;
- n -= half + 1;
- }
- }
- return begin;
-}
-
-template <typename RandomAccessIterator, typename T, typename LessThan>
-QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
-{
- RandomAccessIterator it = qLowerBoundHelper(begin, end, value, lessThan);
-
- if (it == end || lessThan(value, *it))
- return end;
-
- return it;
-}
-
-#endif // QT_DEPRECATED_SINCE(5, 2)
-
-#ifdef Q_CC_CLANG
-// Clang had a bug where __builtin_ctz/clz/popcount were not marked as constexpr.
-# if (defined __apple_build_version__ && __clang_major__ >= 7) || (Q_CC_CLANG >= 307)
-# define QT_HAS_CONSTEXPR_BUILTINS
-# endif
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_INTEL) && !defined(Q_PROCESSOR_ARM)
-# define QT_HAS_CONSTEXPR_BUILTINS
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+// We use C++20 <bit> operations instead which ensures constexpr bit ops
+# define QT_HAS_CONSTEXPR_BITOPS
#elif defined(Q_CC_GNU)
-# define QT_HAS_CONSTEXPR_BUILTINS
-#endif
-
-#if defined QT_HAS_CONSTEXPR_BUILTINS
-#if defined(Q_CC_GNU) || defined(Q_CC_CLANG)
+# define QT_HAS_CONSTEXPR_BITOPS
# define QT_HAS_BUILTIN_CTZS
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
{
# if __has_builtin(__builtin_ctzs)
return __builtin_ctzs(v);
@@ -542,7 +56,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
# endif
}
#define QT_HAS_BUILTIN_CLZS
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
{
# if __has_builtin(__builtin_clzs)
return __builtin_clzs(v);
@@ -551,46 +65,44 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
# endif
}
#define QT_HAS_BUILTIN_CTZ
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctz(quint32 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_ctz(quint32 v) noexcept
{
return __builtin_ctz(v);
}
#define QT_HAS_BUILTIN_CLZ
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clz(quint32 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_clz(quint32 v) noexcept
{
return __builtin_clz(v);
}
#define QT_HAS_BUILTIN_CTZLL
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzll(quint64 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_ctzll(quint64 v) noexcept
{
return __builtin_ctzll(v);
}
#define QT_HAS_BUILTIN_CLZLL
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzll(quint64 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_clzll(quint64 v) noexcept
{
return __builtin_clzll(v);
}
#define QALGORITHMS_USE_BUILTIN_POPCOUNT
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
{
return __builtin_popcount(v);
}
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) noexcept
{
return __builtin_popcount(v);
}
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) noexcept
{
return __builtin_popcount(v);
}
#define QALGORITHMS_USE_BUILTIN_POPCOUNTLL
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
+constexpr Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
{
return __builtin_popcountll(v);
}
#elif defined(Q_CC_MSVC) && !defined(Q_PROCESSOR_ARM)
-#define QT_POPCOUNT_CONSTEXPR
-#define QT_POPCOUNT_RELAXED_CONSTEXPR
#define QT_HAS_BUILTIN_CTZ
Q_ALWAYS_INLINE unsigned long qt_builtin_ctz(quint32 val)
{
@@ -650,6 +162,8 @@ Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
// to generate code for those processors.
// So it's an acceptable compromise.
#if defined(__AVX__) || defined(__SSE4_2__) || defined(__POPCNT__)
+#define QT_POPCOUNT_CONSTEXPR
+#define QT_POPCOUNT_RELAXED_CONSTEXPR
#define QALGORITHMS_USE_BUILTIN_POPCOUNT
#define QALGORITHMS_USE_BUILTIN_POPCOUNTLL
Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
@@ -676,18 +190,19 @@ Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
#endif // __AVX__ || __SSE4_2__ || __POPCNT__
#endif // MSVC
-#endif // QT_HAS_CONSTEXPR_BUILTINS
#ifndef QT_POPCOUNT_CONSTEXPR
-#define QT_POPCOUNT_CONSTEXPR Q_DECL_CONSTEXPR
-#define QT_POPCOUNT_RELAXED_CONSTEXPR Q_DECL_RELAXED_CONSTEXPR
+#define QT_POPCOUNT_CONSTEXPR constexpr
+#define QT_POPCOUNT_RELAXED_CONSTEXPR constexpr
#endif
} //namespace QAlgorithmsPrivate
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint32 v) noexcept
{
-#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::popcount(v);
+#elif defined QALGORITHMS_USE_BUILTIN_POPCOUNT
return QAlgorithmsPrivate::qt_builtin_popcount(v);
#else
// See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
@@ -700,7 +215,9 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint32
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint8 v) noexcept
{
-#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::popcount(v);
+#elif defined QALGORITHMS_USE_BUILTIN_POPCOUNT
return QAlgorithmsPrivate::qt_builtin_popcount(v);
#else
return
@@ -710,7 +227,9 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint8
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint16 v) noexcept
{
-#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::popcount(v);
+#elif defined QALGORITHMS_USE_BUILTIN_POPCOUNT
return QAlgorithmsPrivate::qt_builtin_popcount(v);
#else
return
@@ -721,7 +240,9 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint16
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint64 v) noexcept
{
-#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNTLL
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::popcount(v);
+#elif defined QALGORITHMS_USE_BUILTIN_POPCOUNTLL
return QAlgorithmsPrivate::qt_builtin_popcountll(v);
#else
return
@@ -739,7 +260,7 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(long un
return qPopulationCount(static_cast<quint64>(v));
}
-#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
+#if defined(QALGORITHMS_USE_BUILTIN_POPCOUNT)
#undef QALGORITHMS_USE_BUILTIN_POPCOUNT
#endif
#undef QT_POPCOUNT_CONSTEXPR
@@ -769,7 +290,7 @@ constexpr inline uint qConstexprCountTrailingZeroBits(quint64 v) noexcept
constexpr inline uint qConstexprCountTrailingZeroBits(quint8 v) noexcept
{
unsigned int c = 8; // c will be the number of zero bits on the right
- v &= -signed(v);
+ v &= quint8(-signed(v));
if (v) c--;
if (v & 0x0000000F) c -= 4;
if (v & 0x00000033) c -= 2;
@@ -780,7 +301,7 @@ constexpr inline uint qConstexprCountTrailingZeroBits(quint8 v) noexcept
constexpr inline uint qConstexprCountTrailingZeroBits(quint16 v) noexcept
{
unsigned int c = 16; // c will be the number of zero bits on the right
- v &= -signed(v);
+ v &= quint16(-signed(v));
if (v) c--;
if (v & 0x000000FF) c -= 8;
if (v & 0x00000F0F) c -= 4;
@@ -797,7 +318,9 @@ constexpr inline uint qConstexprCountTrailingZeroBits(unsigned long v) noexcept
constexpr inline uint qCountTrailingZeroBits(quint32 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CTZ)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countr_zero(v);
+#elif defined(QT_HAS_BUILTIN_CTZ)
return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 32U;
#else
return QtPrivate::qConstexprCountTrailingZeroBits(v);
@@ -806,7 +329,9 @@ constexpr inline uint qCountTrailingZeroBits(quint32 v) noexcept
constexpr inline uint qCountTrailingZeroBits(quint8 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CTZ)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countr_zero(v);
+#elif defined(QT_HAS_BUILTIN_CTZ)
return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 8U;
#else
return QtPrivate::qConstexprCountTrailingZeroBits(v);
@@ -815,7 +340,9 @@ constexpr inline uint qCountTrailingZeroBits(quint8 v) noexcept
constexpr inline uint qCountTrailingZeroBits(quint16 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CTZS)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countr_zero(v);
+#elif defined(QT_HAS_BUILTIN_CTZS)
return v ? QAlgorithmsPrivate::qt_builtin_ctzs(v) : 16U;
#else
return QtPrivate::qConstexprCountTrailingZeroBits(v);
@@ -824,7 +351,9 @@ constexpr inline uint qCountTrailingZeroBits(quint16 v) noexcept
constexpr inline uint qCountTrailingZeroBits(quint64 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CTZLL)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countr_zero(v);
+#elif defined(QT_HAS_BUILTIN_CTZLL)
return v ? QAlgorithmsPrivate::qt_builtin_ctzll(v) : 64;
#else
return QtPrivate::qConstexprCountTrailingZeroBits(v);
@@ -836,9 +365,11 @@ constexpr inline uint qCountTrailingZeroBits(unsigned long v) noexcept
return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) noexcept
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CLZ)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countl_zero(v);
+#elif defined(QT_HAS_BUILTIN_CLZ)
return v ? QAlgorithmsPrivate::qt_builtin_clz(v) : 32U;
#else
// Hacker's Delight, 2nd ed. Fig 5-16, p. 102
@@ -853,7 +384,9 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) noexcept
QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CLZ)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countl_zero(v);
+#elif defined(QT_HAS_BUILTIN_CLZ)
return v ? QAlgorithmsPrivate::qt_builtin_clz(v)-24U : 8U;
#else
v = v | (v >> 1);
@@ -865,7 +398,9 @@ QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) noexce
QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CLZS)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countl_zero(v);
+#elif defined(QT_HAS_BUILTIN_CLZS)
return v ? QAlgorithmsPrivate::qt_builtin_clzs(v) : 16U;
#else
v = v | (v >> 1);
@@ -878,7 +413,9 @@ QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) noexc
QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) noexcept
{
-#if defined(QT_HAS_BUILTIN_CLZLL)
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+ return std::countl_zero(v);
+#elif defined(QT_HAS_BUILTIN_CLZLL)
return v ? QAlgorithmsPrivate::qt_builtin_clzll(v) : 64U;
#else
v = v | (v >> 1);
@@ -896,7 +433,8 @@ QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v)
return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
-QT_WARNING_POP
+#undef QT_POPCOUNT_RELAXED_CONSTEXPR
+
QT_END_NAMESPACE
#endif // QALGORITHMS_H
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
index d480f2b487..5fe0b3e8c3 100644
--- a/src/corelib/tools/qalgorithms.qdoc
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -1,32 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\headerfile <QtAlgorithms>
+ \inmodule QtCore
\title Generic Algorithms
\ingroup funclists
\keyword generic algorithms
@@ -47,38 +24,22 @@
meet a certain set of requirements.
Different algorithms can have different requirements for the
- iterators they accept. For example, qFill() accepts two
- \l {forward iterators}. The iterator types required are specified
+ iterators they accept. The iterator types required are specified
for each algorithm. If an iterator of the wrong type is passed (for
example, if QList::ConstIterator is passed as an
\l {Output Iterators}{output iterator}), you will always get a
compiler error, although not necessarily a very informative one.
- Some algorithms have special requirements on the value type
- stored in the containers. For example,
- qDeleteAll() requires that the value type is a
- non-const pointer type (for example, QWidget *). The value type
- requirements are specified for each algorithm, and the compiler
- will produce an error if a requirement isn't met.
+ Some algorithms have special requirements on the value type stored
+ in the containers. For example, qDeleteAll() requires that the
+ value type is a non-const pointer type (for example, QWidget
+ *). The value type requirements are specified for each algorithm,
+ and the compiler will produce an error if a requirement isn't met.
The generic algorithms can be used on other container classes
than those provided by Qt and STL. The syntax of STL-style
iterators is modeled after C++ pointers, so it's possible to use
- plain arrays as containers and plain pointers as iterators. A
- common idiom is to use qBinaryFind() together with two static
- arrays: one that contains a list of keys, and another that
- contains a list of associated values. For example, the following
- code will look up an HTML entity (e.g., \c &amp;) in the \c
- name_table array and return the corresponding Unicode value from
- the \c value_table if the entity is recognized:
-
- \snippet code/doc_src_qalgorithms.cpp 2
-
- This kind of code is for advanced users only; for most
- applications, a QMap- or QHash-based approach would work just as
- well:
-
- \snippet code/doc_src_qalgorithms.cpp 3
+ plain arrays as containers and plain pointers as iterators.
\section1 Types of Iterators
@@ -145,553 +106,9 @@
QList's non-const iterator type is random access iterator.
- \section1 Qt and the STL Algorithms
-
- Historically, Qt used to provide functions which were direct equivalents of
- many STL algorithmic functions. Starting with Qt 5.0, you are instead
- encouraged to use directly the implementations available in the STL; most
- of the Qt ones have been deprecated (although they are still available to
- keep the old code compiling).
-
- \section2 Porting guidelines
-
- Most of the time, an application using the deprecated Qt algorithmic functions
- can be easily ported to use the equivalent STL functions. You need to:
-
- \list 1
- \li add the \c{#include <algorithm>} preprocessor directive;
- \li replace the Qt functions with the STL counterparts, according to the table below.
- \endlist
-
- \table
- \header
- \li Qt function
- \li STL function
- \row
- \li qBinaryFind
- \li \c std::binary_search or \c std::lower_bound
- \row
- \li qCopy
- \li \c std::copy
- \row
- \li qCopyBackward
- \li \c std::copy_backward
- \row
- \li qEqual
- \li \c std::equal
- \row
- \li qFill
- \li \c std::fill
- \row
- \li qFind
- \li \c std::find
- \row
- \li qCount
- \li \c std::count
- \row
- \li qSort
- \li \c std::sort
- \row
- \li qStableSort
- \li \c std::stable_sort
- \row
- \li qLowerBound
- \li \c std::lower_bound
- \row
- \li qUpperBound
- \li \c std::upper_bound
- \row
- \li qLess
- \li \c std::less
- \row
- \li qGreater
- \li \c std::greater
-
- \endtable
-
- The only cases in which the port may not be straightforward is if the old
- code relied on template specializations of the qLess() and/or the qSwap()
- functions, which were used internally by the implementations of the Qt
- algorithmic functions, but are instead ignored by the STL ones.
-
- In case the old code relied on the specialization of the qLess() functor,
- then a workaround is explicitly passing an instance of the qLess() class
- to the STL function, for instance like this:
-
- \code
- std::sort(container.begin(), container.end(), qLess<T>());
- \endcode
-
- Instead, since it's not possible to pass a custom swapper functor to STL
- functions, the only workaround for a template specialization for qSwap() is
- providing the same specialization for \c std::swap().
-
\sa {container classes}, <QtGlobal>
*/
-/*! \fn template <typename InputIterator, typename OutputIterator> OutputIterator qCopy(InputIterator begin1, InputIterator end1, OutputIterator begin2)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::copy instead.
-
- Copies the items from range [\a begin1, \a end1) to range [\a
- begin2, ...), in the order in which they appear.
-
- The item at position \a begin1 is assigned to that at position \a
- begin2; the item at position \a begin1 + 1 is assigned to that at
- position \a begin2 + 1; and so on.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 4
-
- \sa qCopyBackward(), {input iterators}, {output iterators}
-*/
-
-/*! \fn template <typename BiIterator1, typename BiIterator2> BiIterator2 qCopyBackward(BiIterator1 begin1, BiIterator1 end1, BiIterator2 end2)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::copy_backward instead.
-
- Copies the items from range [\a begin1, \a end1) to range [...,
- \a end2).
-
- The item at position \a end1 - 1 is assigned to that at position
- \a end2 - 1; the item at position \a end1 - 2 is assigned to that
- at position \a end2 - 2; and so on.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 5
-
- \sa qCopy(), {bidirectional iterators}
-*/
-
-/*! \fn template <typename InputIterator1, typename InputIterator2> bool qEqual(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::equal instead.
-
- Compares the items in the range [\a begin1, \a end1) with the
- items in the range [\a begin2, ...). Returns \c true if all the
- items compare equal; otherwise returns \c false.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 6
-
- This function requires the item type (in the example above,
- QString) to implement \c operator==().
-
- \sa {input iterators}
-*/
-
-/*! \fn template <typename ForwardIterator, typename T> void qFill(ForwardIterator begin, ForwardIterator end, const T &value)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::fill instead.
-
- Fills the range [\a begin, \a end) with \a value.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 7
-
- \sa qCopy(), {forward iterators}
-*/
-
-/*! \fn template <typename Container, typename T> void qFill(Container &container, const T &value)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::fill instead.
-
- This is the same as qFill(\a{container}.begin(), \a{container}.end(), \a value);
-*/
-
-/*! \fn template <typename InputIterator, typename T> InputIterator qFind(InputIterator begin, InputIterator end, const T &value)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::find instead.
-
- Returns an iterator to the first occurrence of \a value in a
- container in the range [\a begin, \a end). Returns \a end if \a
- value isn't found.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 8
-
- This function requires the item type (in the example above,
- QString) to implement \c operator==().
-
- If the items in the range are in ascending order, you can get
- faster results by using qLowerBound() or qBinaryFind() instead of
- qFind().
-
- \sa qBinaryFind(), {input iterators}
-*/
-
-/*! \fn template <typename Container, typename T> void qFind(const Container &container, const T &value)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::find instead.
-
- This is the same as qFind(\a{container}.constBegin(), \a{container}.constEnd(), \a value);
-*/
-
-/*! \fn template <typename InputIterator, typename T, typename Size> void qCount(InputIterator begin, InputIterator end, const T &value, Size &n)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::count instead.
-
- Returns the number of occurrences of \a value in the range [\a begin, \a end),
- which is returned in \a n. \a n is never initialized, the count is added to \a n.
- It is the caller's responsibility to initialize \a n.
-
- Example:
-
- \snippet code/doc_src_qalgorithms.cpp 9
-
- This function requires the item type (in the example above,
- \c int) to implement \c operator==().
-
- \sa {input iterators}
-*/
-
-/*! \fn template <typename Container, typename T, typename Size> void qCount(const Container &container, const T &value, Size &n)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::count instead.
-
- Instead of operating on iterators, as in the other overload, this function
- operates on the specified \a container to obtain the number of instances
- of \a value in the variable passed as a reference in argument \a n.
-*/
-
-/*! \fn template <typename T> void qSwap(T &var1, T &var2)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::swap instead.
-
- Exchanges the values of variables \a var1 and \a var2.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 10
-*/
-
-/*! \fn template <typename RandomAccessIterator> void qSort(RandomAccessIterator begin, RandomAccessIterator end)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::sort instead.
-
- Sorts the items in range [\a begin, \a end) in ascending order
- using the quicksort algorithm.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 11
-
- The sort algorithm is efficient on large data sets. It operates
- in \l {linear-logarithmic time}, O(\e{n} log \e{n}).
-
- This function requires the item type (in the example above,
- \c{int}) to implement \c operator<().
-
- If neither of the two items is "less than" the other, the items are
- taken to be equal. It is then undefined which one of the two
- items will appear before the other after the sort.
-
- \sa qStableSort(), {random access iterators}
-*/
-
-/*! \fn template <typename RandomAccessIterator, typename LessThan> void qSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::sort instead.
-
- Uses the \a lessThan function instead of \c operator<() to
- compare the items.
-
- For example, here's how to sort the strings in a QStringList
- in case-insensitive alphabetical order:
-
- \snippet code/doc_src_qalgorithms.cpp 12
-
- To sort values in reverse order, pass
- \l{qGreater()}{qGreater<T>()} as the \a lessThan parameter. For
- example:
-
- \snippet code/doc_src_qalgorithms.cpp 13
-
- If neither of the two items is "less than" the other, the items are
- taken to be equal. It is then undefined which one of the two
- items will appear before the other after the sort.
-
- An alternative to using qSort() is to put the items to sort in a
- QMap, using the sort key as the QMap key. This is often more
- convenient than defining a \a lessThan function. For example, the
- following code shows how to sort a list of strings case
- insensitively using QMap:
-
- \snippet code/doc_src_qalgorithms.cpp 14
-
- \sa QMap
-*/
-
-/*! \fn template<typename Container> void qSort(Container &container)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::sort instead.
-
- This is the same as qSort(\a{container}.begin(), \a{container}.end());
-*/
-
-/*!
- \fn template <typename RandomAccessIterator> void qStableSort(RandomAccessIterator begin, RandomAccessIterator end)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::stable_sort instead.
-
- Sorts the items in range [\a begin, \a end) in ascending order
- using a stable sorting algorithm.
-
- If neither of the two items is "less than" the other, the items are
- taken to be equal. The item that appeared before the other in the
- original container will still appear first after the sort. This
- property is often useful when sorting user-visible data.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 15
-
- The sort algorithm is efficient on large data sets. It operates
- in \l {linear-logarithmic time}, O(\e{n} log \e{n}).
-
- This function requires the item type (in the example above,
- \c{int}) to implement \c operator<().
-
- \sa qSort(), {random access iterators}
-*/
-
-/*!
- \fn template <typename RandomAccessIterator, typename LessThan> void qStableSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::stable_sort instead.
-
- Uses the \a lessThan function instead of \c operator<() to
- compare the items.
-
- For example, here's how to sort the strings in a QStringList
- in case-insensitive alphabetical order:
-
- \snippet code/doc_src_qalgorithms.cpp 16
-
- Note that earlier versions of Qt allowed using a lessThan function that took its
- arguments by non-const reference. From 4.3 and on this is no longer possible,
- the arguments has to be passed by const reference or value.
-
- To sort values in reverse order, pass
- \l{qGreater()}{qGreater<T>()} as the \a lessThan parameter. For
- example:
-
- \snippet code/doc_src_qalgorithms.cpp 17
-
- If neither of the two items is "less than" the other, the items are
- taken to be equal. The item that appeared before the other in the
- original container will still appear first after the sort. This
- property is often useful when sorting user-visible data.
-*/
-
-/*!
- \fn template <typename Container> void qStableSort(Container &container)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::stable_sort instead.
-
- This is the same as qStableSort(\a{container}.begin(), \a{container}.end());
-*/
-
-/*! \fn template <typename RandomAccessIterator, typename T> RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::lower_bound instead.
-
- Performs a binary search of the range [\a begin, \a end) and
- returns the position of the first occurrence of \a value. If no
- such item is found, returns the position where it should be
- inserted.
-
- The items in the range [\a begin, \e end) must be sorted in
- ascending order; see qSort().
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 18
-
- This function requires the item type (in the example above,
- \c{int}) to implement \c operator<().
-
- qLowerBound() can be used in conjunction with qUpperBound() to
- iterate over all occurrences of the same value:
-
- \snippet code/doc_src_qalgorithms.cpp 19
-
- \sa qUpperBound(), qBinaryFind()
-*/
-
-/*!
- \fn template <typename RandomAccessIterator, typename T, typename LessThan> RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::lower_bound instead.
-
- Uses the \a lessThan function instead of \c operator<() to
- compare the items.
-
- Note that the items in the range must be sorted according to the order
- specified by the \a lessThan object.
-*/
-
-/*!
- \fn template <typename Container, typename T> void qLowerBound(const Container &container, const T &value)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::lower_bound instead.
-
- For read-only iteration over containers, this function is broadly equivalent to
- qLowerBound(\a{container}.begin(), \a{container}.end(), value). However, since it
- returns a const iterator, you cannot use it to modify the container; for example,
- to insert items.
-*/
-
-/*! \fn template <typename RandomAccessIterator, typename T> RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::upper_bound instead.
-
- Performs a binary search of the range [\a begin, \a end) and
- returns the position of the one-past-the-last occurrence of \a
- value. If no such item is found, returns the position where the
- item should be inserted.
-
- The items in the range [\a begin, \e end) must be sorted in
- ascending order; see qSort().
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 20
-
- This function requires the item type (in the example above,
- \c{int}) to implement \c operator<().
-
- qUpperBound() can be used in conjunction with qLowerBound() to
- iterate over all occurrences of the same value:
-
- \snippet code/doc_src_qalgorithms.cpp 21
-
- \sa qLowerBound(), qBinaryFind()
-*/
-
-/*!
- \fn template <typename RandomAccessIterator, typename T, typename LessThan> RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::upper_bound instead.
-
- Uses the \a lessThan function instead of \c operator<() to
- compare the items.
-
- Note that the items in the range must be sorted according to the order
- specified by the \a lessThan object.
-*/
-
-/*!
- \fn template <typename Container, typename T> void qUpperBound(const Container &container, const T &value)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::upper_bound instead.
-
- This is the same as qUpperBound(\a{container}.begin(), \a{container}.end(), \a value);
-*/
-
-
-/*! \fn template <typename RandomAccessIterator, typename T> RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::binary_search or \c std::lower_bound instead.
-
- Performs a binary search of the range [\a begin, \a end) and
- returns the position of an occurrence of \a value. If there are
- no occurrences of \a value, returns \a end.
-
- The items in the range [\a begin, \a end) must be sorted in
- ascending order; see qSort().
-
- If there are many occurrences of the same value, any one of them
- could be returned. Use qLowerBound() or qUpperBound() if you need
- finer control.
-
- Example:
- \snippet code/doc_src_qalgorithms.cpp 22
-
- This function requires the item type (in the example above,
- QString) to implement \c operator<().
-
- \sa qLowerBound(), qUpperBound(), {random access iterators}
-*/
-
-/*! \fn template <typename RandomAccessIterator, typename T, typename LessThan> RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::binary_search or \c std::lower_bound instead.
-
- Uses the \a lessThan function instead of \c operator<() to
- compare the items.
-
- Note that the items in the range must be sorted according to the order
- specified by the \a lessThan object.
-*/
-
-/*!
- \fn template <typename Container, typename T> void qBinaryFind(const Container &container, const T &value)
- \relates <QtAlgorithms>
- \deprecated
- \overload
-
- Use \c std::binary_search or \c std::lower_bound instead.
-
- This is the same as qBinaryFind(\a{container}.begin(), \a{container}.end(), \a value);
-*/
-
-
/*!
\fn template <typename ForwardIterator> void qDeleteAll(ForwardIterator begin, ForwardIterator end)
\relates <QtAlgorithms>
@@ -701,7 +118,7 @@
example, \c{QWidget *}).
Example:
- \snippet code/doc_src_qalgorithms.cpp 23
+ \snippet code/doc_src_qalgorithms.cpp 1
Notice that qDeleteAll() doesn't remove the items from the
container; it merely calls \c delete on them. In the example
@@ -724,39 +141,6 @@
This is the same as qDeleteAll(\a{c}.begin(), \a{c}.end()).
*/
-/*! \fn template <typename LessThan> LessThan qLess()
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::less instead.
-
- Returns a functional object, or functor, that can be passed to qSort()
- or qStableSort().
-
- Example:
-
- \snippet code/doc_src_qalgorithms.cpp 24
-
- \sa {qGreater()}{qGreater<T>()}
-*/
-
-/*! \fn template <typename LessThan> LessThan qGreater()
- \relates <QtAlgorithms>
- \deprecated
-
- Use \c std::greater instead.
-
- Returns a functional object, or functor, that can be passed to qSort()
- or qStableSort().
-
- Example:
-
- \snippet code/doc_src_qalgorithms.cpp 25
-
- \sa {qLess()}{qLess<T>()}
-*/
-
-
/*!
\fn uint qPopulationCount(quint8 v)
\relates <QtAlgorithms>
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index b72ca20131..6aebd4306a 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -1,48 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qarraydata.h>
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/private/qtools_p.h>
#include <QtCore/qmath.h>
+#include <QtCore/qbytearray.h> // QBA::value_type
+#include <QtCore/qstring.h> // QString::value_type
+
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -52,7 +19,7 @@ QT_BEGIN_NAMESPACE
* containers to allocate memory and grow the memory block during append
* operations.
*
- * They take size_t parameters and return size_t so they will change sizes
+ * They take qsizetype parameters and return qsizetype so they will change sizes
* according to the pointer width. However, knowing Qt containers store the
* container size and element indexes in ints, these functions never return a
* size larger than INT_MAX. This is done by casting the element count and
@@ -79,29 +46,21 @@ QT_BEGIN_NAMESPACE
Both \a elementCount and \a headerSize can be zero, but \a elementSize
cannot.
- This function returns SIZE_MAX (~0) on overflow or if the memory block size
- would not fit an int.
+ This function returns -1 on overflow or if the memory block size
+ would not fit a qsizetype.
*/
-size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
+qsizetype qCalculateBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize) noexcept
{
- unsigned count = unsigned(elementCount);
- unsigned size = unsigned(elementSize);
- unsigned header = unsigned(headerSize);
Q_ASSERT(elementSize);
- Q_ASSERT(size == elementSize);
- Q_ASSERT(header == headerSize);
-
- if (Q_UNLIKELY(count != elementCount))
- return std::numeric_limits<size_t>::max();
- unsigned bytes;
- if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) ||
- Q_UNLIKELY(add_overflow(bytes, header, &bytes)))
- return std::numeric_limits<size_t>::max();
- if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB
- return std::numeric_limits<size_t>::max();
+ size_t bytes;
+ if (Q_UNLIKELY(qMulOverflow(size_t(elementSize), size_t(elementCount), &bytes)) ||
+ Q_UNLIKELY(qAddOverflow(bytes, size_t(headerSize), &bytes)))
+ return -1;
+ if (Q_UNLIKELY(qsizetype(bytes) < 0))
+ return -1;
- return bytes;
+ return qsizetype(bytes);
}
/*!
@@ -116,168 +75,191 @@ size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t heade
Both \a elementCount and \a headerSize can be zero, but \a elementSize
cannot.
- This function returns SIZE_MAX (~0) on overflow or if the memory block size
- would not fit an int.
+ This function returns -1 on overflow or if the memory block size
+ would not fit a qsizetype.
\note The memory block may contain up to \a elementSize - 1 bytes more than
needed.
*/
CalculateGrowingBlockSizeResult
-qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
+qCalculateGrowingBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize) noexcept
{
CalculateGrowingBlockSizeResult result = {
- std::numeric_limits<size_t>::max(),std::numeric_limits<size_t>::max()
+ qsizetype(-1), qsizetype(-1)
};
- unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize));
- if (int(bytes) < 0) // catches std::numeric_limits<size_t>::max()
+ qsizetype bytes = qCalculateBlockSize(elementCount, elementSize, headerSize);
+ if (bytes < 0)
return result;
- unsigned morebytes = qNextPowerOfTwo(bytes);
- if (Q_UNLIKELY(int(morebytes) < 0)) {
- // catches morebytes == 2GB
+ size_t morebytes = static_cast<size_t>(qNextPowerOfTwo(quint64(bytes)));
+ if (Q_UNLIKELY(qsizetype(morebytes) < 0)) {
// grow by half the difference between bytes and morebytes
+ // this slows the growth and avoids trying to allocate exactly
+ // 2G of memory (on 32bit), something that many OSes can't deliver
bytes += (morebytes - bytes) / 2;
} else {
- bytes = morebytes;
+ bytes = qsizetype(morebytes);
}
- result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize);
+ result.elementCount = (bytes - headerSize) / elementSize;
result.size = result.elementCount * elementSize + headerSize;
return result;
}
-// End of qtools_p.h implementation
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")
-
-const QArrayData QArrayData::shared_null[2] = {
- { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }, // shared null
- /* zero initialized terminator */};
-
-static const QArrayData emptyNotNullShared[2] = {
- { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }, // shared empty
- /* zero initialized terminator */};
-
-QT_WARNING_POP
-
-static const QArrayData &qt_array_empty = emptyNotNullShared[0];
+/*
+ Calculate the byte size for a block of \a capacity objects of size \a
+ objectSize, with a header of size \a headerSize. If the \a option is
+ QArrayData::Grow, the capacity itself adjusted up, preallocating room for
+ more elements to be added later; otherwise, it is an exact calculation.
-static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize,
- uint options)
+ Returns a structure containing the size in bytes and elements available.
+*/
+static inline CalculateGrowingBlockSizeResult
+calculateBlockSize(qsizetype capacity, qsizetype objectSize, qsizetype headerSize, QArrayData::AllocationOption option)
{
- // Calculate the byte size
+ // Adjust the header size up to account for the trailing null for QString
+ // and QByteArray. This is not checked for overflow because headers sizes
+ // should not be anywhere near the overflow limit.
+ constexpr qsizetype FooterSize = qMax(sizeof(QString::value_type), sizeof(QByteArray::value_type));
+ if (objectSize <= FooterSize)
+ headerSize += FooterSize;
+
// allocSize = objectSize * capacity + headerSize, but checked for overflow
// plus padded to grow in size
- if (options & QArrayData::GrowsForward) {
- auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
- capacity = r.elementCount;
- return r.size;
+ if (option == QArrayData::Grow) {
+ return qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
} else {
- return qCalculateBlockSize(capacity, objectSize, headerSize);
+ return { qCalculateBlockSize(capacity, objectSize, headerSize), capacity };
}
}
-static QArrayData *allocateData(size_t allocSize, uint options)
+static QArrayData *allocateData(qsizetype allocSize)
{
- QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
+ QArrayData *header = static_cast<QArrayData *>(::malloc(size_t(allocSize)));
if (header) {
header->ref_.storeRelaxed(1);
- header->flags = options;
+ header->flags = {};
header->alloc = 0;
}
return header;
}
-static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options)
-{
- header = static_cast<QArrayData *>(::realloc(header, allocSize));
- if (header)
- header->flags = options;
- return header;
+namespace {
+struct AllocationResult {
+ void *data;
+ QArrayData *header;
+};
}
+using QtPrivate::AlignedQArrayData;
-void *QArrayData::allocate(QArrayData **dptr, size_t objectSize, size_t alignment,
- size_t capacity, ArrayOptions options) noexcept
+static inline AllocationResult
+allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity,
+ QArrayData::AllocationOption option) noexcept
{
- Q_ASSERT(dptr);
- // Alignment is a power of two
- Q_ASSERT(alignment >= alignof(QArrayData)
- && !(alignment & (alignment - 1)));
-
- if (capacity == 0) {
- // optimization for empty headers
- *dptr = const_cast<QArrayData *>(&qt_array_empty);
- return sharedNullData();
- }
-
- size_t headerSize = sizeof(QArrayData);
-
- if (alignment > alignof(QArrayData)) {
- // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we
- // can properly align the data array. This assumes malloc is able to
- // provide appropriate alignment for the header -- as it should!
- headerSize += alignment - alignof(QArrayData);
+ if (capacity == 0)
+ return {};
+
+ qsizetype headerSize = sizeof(AlignedQArrayData);
+ const qsizetype headerAlignment = alignof(AlignedQArrayData);
+
+ if (alignment > headerAlignment) {
+ // Allocate extra (alignment - Q_ALIGNOF(AlignedQArrayData)) padding
+ // bytes so we can properly align the data array. This assumes malloc is
+ // able to provide appropriate alignment for the header -- as it should!
+ // Effectively, we allocate one QTypedArrayData<T>::AlignmentDummy.
+ headerSize += alignment - headerAlignment;
}
+ Q_ASSERT(headerSize > 0);
- if (headerSize > size_t(MaxAllocSize))
- return nullptr;
+ auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option);
+ capacity = blockSize.elementCount;
+ qsizetype allocSize = blockSize.size;
+ if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot allocate reliably
+ return {};
- size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- options |= AllocatedDataType | MutableData;
- options &= ~ImmutableHeader;
- QArrayData *header = allocateData(allocSize, options);
- quintptr data = 0;
+ QArrayData *header = allocateData(allocSize);
+ void *data = nullptr;
if (header) {
// find where offset should point to so that data() is aligned to alignment bytes
- data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
- & ~(alignment - 1);
- header->alloc = uint(capacity);
+ data = QTypedArrayData<void>::dataStart(header, alignment);
+ header->alloc = qsizetype(capacity);
}
- *dptr = header;
- return reinterpret_cast<void *>(data);
+ return { data, header };
}
-QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW
+// Generic size and alignment allocation function
+void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
+ qsizetype capacity, AllocationOption option) noexcept
{
- QArrayData *header = allocateData(sizeof(QArrayData), (options & ~DataTypeBits) | RawDataType);
- if (header)
- header->alloc = 0;
- return header;
+ Q_ASSERT(dptr);
+ // Alignment is a power of two
+ Q_ASSERT(alignment >= qsizetype(alignof(QArrayData))
+ && !(alignment & (alignment - 1)));
+
+ auto r = allocateHelper(objectSize, alignment, capacity, option);
+ *dptr = r.header;
+ return r.data;
+}
+
+// Fixed size and alignment allocation functions
+void *QArrayData::allocate1(QArrayData **dptr, qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+
+ auto r = allocateHelper(1, alignof(AlignedQArrayData), capacity, option);
+ *dptr = r.header;
+ return r.data;
}
-QPair<QArrayData *, void *>
+void *QArrayData::allocate2(QArrayData **dptr, qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+
+ auto r = allocateHelper(2, alignof(AlignedQArrayData), capacity, option);
+ *dptr = r.header;
+ return r.data;
+}
+
+std::pair<QArrayData *, void *>
QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
- size_t objectSize, size_t capacity, ArrayOptions options) noexcept
+ qsizetype objectSize, qsizetype capacity, AllocationOption option) noexcept
{
- Q_ASSERT(data);
- Q_ASSERT(data->isMutable());
- Q_ASSERT(!data->isShared());
-
- size_t headerSize = sizeof(QArrayData);
- size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- qptrdiff offset = reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data);
- options |= AllocatedDataType | MutableData;
- QArrayData *header = reallocateData(data, allocSize, options);
+ Q_ASSERT(!data || !data->isShared());
+
+ const qsizetype headerSize = sizeof(AlignedQArrayData);
+ auto r = calculateBlockSize(capacity, objectSize, headerSize, option);
+ qsizetype allocSize = r.size;
+ capacity = r.elementCount;
+ if (Q_UNLIKELY(allocSize < 0))
+ return {};
+
+ const qptrdiff offset = dataPointer
+ ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data)
+ : headerSize;
+ Q_ASSERT(offset > 0);
+ Q_ASSERT(offset <= allocSize); // equals when all free space is at the beginning
+
+ QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize)));
if (header) {
- header->alloc = uint(capacity);
+ header->alloc = capacity;
dataPointer = reinterpret_cast<char *>(header) + offset;
+ } else {
+ dataPointer = nullptr;
}
- return qMakePair(static_cast<QArrayData *>(header), dataPointer);
+ return {header, dataPointer};
}
-void QArrayData::deallocate(QArrayData *data, size_t objectSize,
- size_t alignment) noexcept
+void QArrayData::deallocate(QArrayData *data, qsizetype objectSize,
+ qsizetype alignment) noexcept
{
// Alignment is a power of two
- Q_ASSERT(alignment >= alignof(QArrayData)
+ Q_ASSERT(alignment >= qsizetype(alignof(QArrayData))
&& !(alignment & (alignment - 1)));
- Q_UNUSED(objectSize) Q_UNUSED(alignment)
+ Q_UNUSED(objectSize);
+ Q_UNUSED(alignment);
- Q_ASSERT_X(data == nullptr || !data->isStatic(), "QArrayData::deallocate",
- "Static data cannot be deleted");
::free(data);
}
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 2515c1ae5a..da83fc1a21 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -1,120 +1,72 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QARRAYDATA_H
#define QARRAYDATA_H
#include <QtCore/qpair.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qflags.h>
+#include <QtCore/qcontainerfwd.h>
#include <string.h>
QT_BEGIN_NAMESPACE
+#if __has_cpp_attribute(gnu::malloc)
+# define Q_DECL_MALLOCLIKE [[nodiscard, gnu::malloc]]
+#else
+# define Q_DECL_MALLOCLIKE [[nodiscard]]
+#endif
+
template <class T> struct QTypedArrayData;
-struct Q_CORE_EXPORT QArrayData
+struct QArrayData
{
- enum ArrayOption {
- RawDataType = 0x0001, //!< this class is really a QArrayData
- AllocatedDataType = 0x0002, //!< this class is really a QArrayAllocatedData
- DataTypeBits = 0x000f,
-
- CapacityReserved = 0x0010, //!< the capacity was reserved by the user, try to keep it
- GrowsForward = 0x0020, //!< allocate with eyes towards growing through append()
- GrowsBackwards = 0x0040, //!< allocate with eyes towards growing through prepend()
- MutableData = 0x0080, //!< the data can be changed; doesn't say anything about the header
- ImmutableHeader = 0x0100, //!< the header is static, it can't be changed
-
- /// this option is used by the Q_ARRAY_LITERAL and similar macros
- StaticDataFlags = RawDataType | ImmutableHeader,
- /// this option is used by the allocate() function
- DefaultAllocationFlags = MutableData,
- /// this option is used by the prepareRawData() function
- DefaultRawFlags = 0
+ enum AllocationOption {
+ Grow,
+ KeepSize
+ };
+
+ enum GrowthPosition {
+ GrowsAtEnd,
+ GrowsAtBeginning
+ };
+
+ enum ArrayOption {
+ ArrayOptionDefault = 0,
+ CapacityReserved = 0x1 //!< the capacity was reserved by the user, try to keep it
};
Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
QBasicAtomicInt ref_;
- uint flags;
- uint alloc;
+ ArrayOptions flags;
+ qsizetype alloc;
- inline size_t allocatedCapacity()
+ qsizetype allocatedCapacity() noexcept
{
return alloc;
}
- inline size_t constAllocatedCapacity() const
+ qsizetype constAllocatedCapacity() const noexcept
{
return alloc;
}
/// Returns true if sharing took place
- bool ref()
+ bool ref() noexcept
{
- if (!isStatic())
- ref_.ref();
+ ref_.ref();
return true;
}
/// Returns false if deallocation is necessary
- bool deref()
+ bool deref() noexcept
{
- if (isStatic())
- return true;
return ref_.deref();
}
- // This refers to array data mutability, not "header data" represented by
- // data members in QArrayData. Shared data (array and header) must still
- // follow COW principles.
- bool isMutable() const
- {
- return flags & MutableData;
- }
-
- bool isStatic() const
- {
- return flags & ImmutableHeader;
- }
-
- bool isShared() const
+ bool isShared() const noexcept
{
return ref_.loadRelaxed() != 1;
}
@@ -122,186 +74,110 @@ struct Q_CORE_EXPORT QArrayData
// Returns true if a detach is necessary before modifying the data
// This method is intentionally not const: if you want to know whether
// detaching is necessary, you should be in a non-const function already
- bool needsDetach()
+ bool needsDetach() noexcept
{
- // requires two conditionals
- return !isMutable() || isShared();
+ return ref_.loadRelaxed() > 1;
}
- size_t detachCapacity(size_t newSize) const
+ qsizetype detachCapacity(qsizetype newSize) const noexcept
{
if (flags & CapacityReserved && newSize < constAllocatedCapacity())
return constAllocatedCapacity();
return newSize;
}
- ArrayOptions detachFlags() const
- {
- ArrayOptions result = DefaultAllocationFlags;
- if (flags & CapacityReserved)
- result |= CapacityReserved;
- return result;
- }
-
- ArrayOptions cloneFlags() const
- {
- ArrayOptions result = DefaultAllocationFlags;
- if (flags & CapacityReserved)
- result |= CapacityReserved;
- return result;
- }
-
- Q_REQUIRED_RESULT
-#if defined(Q_CC_GNU)
- __attribute__((__malloc__))
-#endif
- static void *allocate(QArrayData **pdata, size_t objectSize, size_t alignment,
- size_t capacity, ArrayOptions options = DefaultAllocationFlags) noexcept;
- Q_REQUIRED_RESULT static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,
- size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) noexcept;
- Q_REQUIRED_RESULT static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
- size_t objectSize, size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT static QArrayData *prepareRawData(ArrayOptions options = ArrayOptions(RawDataType))
- Q_DECL_NOTHROW;
- static void deallocate(QArrayData *data, size_t objectSize,
- size_t alignment) noexcept;
-
- static const QArrayData shared_null[2];
- static QArrayData *sharedNull() noexcept { return const_cast<QArrayData*>(shared_null); }
- static void *sharedNullData()
- {
- QArrayData *const null = const_cast<QArrayData *>(&shared_null[1]);
- return null;
- }
+ Q_DECL_MALLOCLIKE
+ static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
+ qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept;
+ Q_DECL_MALLOCLIKE
+ static Q_CORE_EXPORT void *allocate1(QArrayData **pdata, qsizetype capacity,
+ AllocationOption option = QArrayData::KeepSize) noexcept;
+ Q_DECL_MALLOCLIKE
+ static Q_CORE_EXPORT void *allocate2(QArrayData **pdata, qsizetype capacity,
+ AllocationOption option = QArrayData::KeepSize) noexcept;
+
+ [[nodiscard]] static Q_CORE_EXPORT std::pair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
+ qsizetype objectSize, qsizetype newCapacity, AllocationOption option) noexcept;
+ static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize,
+ qsizetype alignment) noexcept;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions)
-template <class T, size_t N>
-struct QStaticArrayData
-{
- // static arrays are of type RawDataType
- QArrayData header;
- T data[N];
-};
+namespace QtPrivate {
+// QArrayData with strictest alignment requirements supported by malloc()
+#if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU)
+// GCC's definition is incorrect since GCC 8 (commit r240248 in SVN; commit
+// 63012d9a57edc950c5f30242d1e19318b5708060 in Git). This is applied to all
+// GCC-like compilers in case they decide to follow GCC's lead in being wrong.
+constexpr size_t MaxPrimitiveAlignment = 2 * sizeof(void *);
+#else
+constexpr size_t MaxPrimitiveAlignment = alignof(std::max_align_t);
+#endif
-// Support for returning QArrayDataPointer<T> from functions
-template <class T>
-struct QArrayDataPointerRef
+struct alignas(MaxPrimitiveAlignment) AlignedQArrayData : QArrayData
{
- QTypedArrayData<T> *ptr;
- T *data;
- uint size;
};
+}
template <class T>
struct QTypedArrayData
: QArrayData
{
- typedef T* iterator;
- typedef const T* const_iterator;
+ struct AlignmentDummy { QtPrivate::AlignedQArrayData header; T data; };
- class AlignmentDummy { QArrayData header; T data; };
-
- Q_REQUIRED_RESULT static QPair<QTypedArrayData *, T *> allocate(size_t capacity,
- ArrayOptions options = DefaultAllocationFlags)
+ [[nodiscard]] static std::pair<QTypedArrayData *, T *> allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize)
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QArrayData *d;
- void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, options);
-#if (defined(Q_CC_GNU) && Q_CC_GNU >= 407) || QT_HAS_BUILTIN(__builtin_assume_aligned)
+ void *result;
+ if constexpr (sizeof(T) == 1) {
+ // necessarily, alignof(T) == 1
+ result = allocate1(&d, capacity, option);
+ } else if constexpr (sizeof(T) == 2) {
+ // alignof(T) may be 1, but that makes no difference
+ result = allocate2(&d, capacity, option);
+ } else {
+ result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
+ }
+#if __has_builtin(__builtin_assume_aligned)
+ // and yet we do offer results that have stricter alignment
result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
#endif
- return qMakePair(static_cast<QTypedArrayData *>(d), static_cast<T *>(result));
+ return {static_cast<QTypedArrayData *>(d), static_cast<T *>(result)};
}
- static QPair<QTypedArrayData *, T *>
- reallocateUnaligned(QTypedArrayData *data, T *dataPointer, size_t capacity,
- ArrayOptions options = DefaultAllocationFlags)
+ static std::pair<QTypedArrayData *, T *>
+ reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- QPair<QArrayData *, void *> pair =
- QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, options);
- return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second));
+ std::pair<QArrayData *, void *> pair =
+ QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option);
+ return {static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)};
}
- static void deallocate(QArrayData *data)
+ static void deallocate(QArrayData *data) noexcept
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
}
- static QArrayDataPointerRef<T> fromRawData(const T *data, size_t n,
- ArrayOptions options = DefaultRawFlags)
+ static T *dataStart(QArrayData *data, qsizetype alignment) noexcept
{
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- QArrayDataPointerRef<T> result = {
- static_cast<QTypedArrayData *>(prepareRawData(options)), const_cast<T *>(data), uint(n)
- };
- if (result.ptr) {
- Q_ASSERT(!result.ptr->isShared()); // No shared empty, please!
- }
- return result;
+ // Alignment is a power of two
+ Q_ASSERT(alignment >= qsizetype(alignof(QArrayData)) && !(alignment & (alignment - 1)));
+ void *start = reinterpret_cast<void *>(
+ (quintptr(data) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1));
+ return static_cast<T *>(start);
}
- static QTypedArrayData *sharedNull() noexcept
+ constexpr static qsizetype max_size() noexcept
{
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return static_cast<QTypedArrayData *>(QArrayData::sharedNull());
- }
-
- static QTypedArrayData *sharedEmpty()
- {
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return allocate(/* capacity */ 0);
- }
-
- static T *sharedNullData()
- {
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return static_cast<T *>(QArrayData::sharedNullData());
+ // -1 to deal with the pointer one-past-the-end
+ return (QtPrivate::MaxAllocSize - sizeof(QtPrivate::AlignedQArrayData) - 1) / sizeof(T);
}
};
-////////////////////////////////////////////////////////////////////////////////
-// Q_ARRAY_LITERAL
-
-// The idea here is to place a (read-only) copy of header and array data in an
-// mmappable portion of the executable (typically, .rodata section). This is
-// accomplished by hiding a static const instance of QStaticArrayData, which is
-// POD.
-
-// Hide array inside a lambda
-#define Q_ARRAY_LITERAL(Type, ...) \
- ([]() -> QArrayDataPointerRef<Type> { \
- /* MSVC 2010 Doesn't support static variables in a lambda, but */ \
- /* happily accepts them in a static function of a lambda-local */ \
- /* struct :-) */ \
- struct StaticWrapper { \
- static QArrayDataPointerRef<Type> get() \
- { \
- Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__) \
- return ref; \
- } \
- }; \
- return StaticWrapper::get(); \
- }()) \
- /**/
-
-#define Q_ARRAY_LITERAL_IMPL(Type, ...) \
- /* Portable compile-time array size computation */ \
- static constexpr Type data[] = { __VA_ARGS__ }; \
- enum { Size = sizeof(data) / sizeof(data[0]) }; \
- \
- static constexpr QArrayData literal = { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 };\
- \
- QArrayDataPointerRef<Type> ref = \
- { static_cast<QTypedArrayData<Type> *>( \
- const_cast<QArrayData *>(&literal)), \
- const_cast<Type *>(data), \
- Size }; \
- /**/
-
namespace QtPrivate {
struct Q_CORE_EXPORT QContainerImplHelper
{
@@ -340,6 +216,8 @@ struct Q_CORE_EXPORT QContainerImplHelper
};
}
+#undef Q_DECL_MALLOCLIKE
+
QT_END_NAMESPACE
#endif // include guard
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 1d74f49993..c3e9821e81 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -1,51 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QARRAYDATAOPS_H
#define QARRAYDATAOPS_H
#include <QtCore/qarraydata.h>
#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qnamespace.h>
+#include <memory>
#include <new>
#include <string.h>
+#include <utility>
+#include <iterator>
+#include <tuple>
+#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -53,157 +23,245 @@ template <class T> struct QArrayDataPointer;
namespace QtPrivate {
-QT_WARNING_PUSH
-#if defined(Q_CC_GNU) && Q_CC_GNU >= 700
-QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
-#endif
-
template <class T>
struct QPodArrayOps
: public QArrayDataPointer<T>
{
+ static_assert (std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
+protected:
+ typedef QTypedArrayData<T> Data;
+ using DataPointer = QArrayDataPointer<T>;
+
+public:
typedef typename QArrayDataPointer<T>::parameter_type parameter_type;
- void appendInitialize(size_t newSize)
+ using QArrayDataPointer<T>::QArrayDataPointer;
+
+ void appendInitialize(qsizetype newSize) noexcept
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
- Q_ASSERT(newSize > uint(this->size));
- Q_ASSERT(newSize <= this->allocatedCapacity());
-
- ::memset(static_cast<void *>(this->end()), 0, (newSize - this->size) * sizeof(T));
- this->size = int(newSize);
+ Q_ASSERT(newSize > this->size);
+ Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd());
+
+ T *where = this->end();
+ this->size = newSize;
+ const T *e = this->end();
+ while (where != e)
+ *where++ = T();
}
- template<typename iterator>
- void copyAppend(iterator b, iterator e, QtPrivate::IfIsForwardIterator<iterator> = true)
- {
- Q_ASSERT(this->isMutable() || b == e);
- Q_ASSERT(!this->isShared() || b == e);
- Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
-
- T *iter = this->end();
- for (; b != e; ++iter, ++b) {
- new (iter) T(*b);
- ++this->size;
- }
- }
-
- void copyAppend(const T *b, const T *e)
+ void copyAppend(const T *b, const T *e) noexcept
{
Q_ASSERT(this->isMutable() || b == e);
Q_ASSERT(!this->isShared() || b == e);
Q_ASSERT(b <= e);
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
+ Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
- ::memcpy(static_cast<void *>(this->end()), static_cast<const void *>(b),
- (e - b) * sizeof(T));
- this->size += e - b;
- }
+ if (b == e)
+ return;
- void moveAppend(T *b, T *e)
- { copyAppend(b, e); }
+ ::memcpy(static_cast<void *>(this->end()), static_cast<const void *>(b), (e - b) * sizeof(T));
+ this->size += (e - b);
+ }
- void copyAppend(size_t n, parameter_type t)
+ void copyAppend(qsizetype n, parameter_type t) noexcept
{
- Q_ASSERT(this->isMutable() || n == 0);
Q_ASSERT(!this->isShared() || n == 0);
- Q_ASSERT(n <= uint(this->allocatedCapacity() - this->size));
+ Q_ASSERT(this->freeSpaceAtEnd() >= n);
+ if (!n)
+ return;
- T *iter = this->end();
- const T *const end = iter + n;
- for (; iter != end; ++iter)
- *iter = t;
- this->size += int(n);
+ T *where = this->end();
+ this->size += qsizetype(n);
+ while (n--)
+ *where++ = t;
}
- template <typename ...Args>
- void emplaceBack(Args&&... args) { this->emplace(this->end(), T(std::forward<Args>(args)...)); }
+ void moveAppend(T *b, T *e) noexcept
+ {
+ copyAppend(b, e);
+ }
- void truncate(size_t newSize)
+ void truncate(size_t newSize) noexcept
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
Q_ASSERT(newSize < size_t(this->size));
- this->size = int(newSize);
+ this->size = qsizetype(newSize);
}
- void destroyAll() // Call from destructors, ONLY!
+ void destroyAll() noexcept // Call from destructors, ONLY!
{
- Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->d);
Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
}
- void insert(T *where, const T *b, const T *e)
+ T *createHole(QArrayData::GrowthPosition pos, qsizetype where, qsizetype n)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
+ Q_ASSERT((pos == QArrayData::GrowsAtBeginning && n <= this->freeSpaceAtBegin()) ||
+ (pos == QArrayData::GrowsAtEnd && n <= this->freeSpaceAtEnd()));
- ::memmove(static_cast<void *>(where + (e - b)), static_cast<void *>(where),
- (static_cast<const T*>(this->end()) - where) * sizeof(T));
- ::memcpy(static_cast<void *>(where), static_cast<const void *>(b), (e - b) * sizeof(T));
- this->size += (e - b);
+ T *insertionPoint = this->ptr + where;
+ if (pos == QArrayData::GrowsAtEnd) {
+ if (where < this->size)
+ ::memmove(static_cast<void *>(insertionPoint + n), static_cast<void *>(insertionPoint), (this->size - where) * sizeof(T));
+ } else {
+ Q_ASSERT(where == 0);
+ this->ptr -= n;
+ insertionPoint -= n;
+ }
+ this->size += n;
+ return insertionPoint;
}
- void insert(T *where, size_t n, parameter_type t)
+ void insert(qsizetype i, const T *data, qsizetype n)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(this->allocatedCapacity() - this->size >= n);
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i == 0)
+ pos = Data::GrowsAtBeginning;
- ::memmove(static_cast<void *>(where + n), static_cast<void *>(where),
- (static_cast<const T*>(this->end()) - where) * sizeof(T));
- this->size += int(n); // PODs can't throw on copy
- while (n--)
- *where++ = t;
- }
+ DataPointer oldData;
+ this->detachAndGrow(pos, n, &data, &oldData);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- template <typename ...Args>
- void createInPlace(T *where, Args&&... args) { new (where) T(std::forward<Args>(args)...); }
+ T *where = createHole(pos, i, n);
+ ::memcpy(static_cast<void *>(where), static_cast<const void *>(data), n * sizeof(T));
+ }
- template <typename ...Args>
- void emplace(T *where, Args&&... args)
+ void insert(qsizetype i, qsizetype n, parameter_type t)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->allocatedCapacity() - this->size >= 1);
+ T copy(t);
- if (where == this->end()) {
- new (this->end()) T(std::forward<Args>(args)...);
- } else {
- // Preserve the value, because it might be a reference to some part of the moved chunk
- T t(std::forward<Args>(args)...);
+ typename Data::GrowthPosition pos = Data::GrowsAtEnd;
+ if (this->size != 0 && i == 0)
+ pos = Data::GrowsAtBeginning;
- ::memmove(static_cast<void *>(where + 1), static_cast<void *>(where),
- (static_cast<const T*>(this->end()) - where) * sizeof(T));
- *where = t;
- }
+ this->detachAndGrow(pos, n, nullptr, nullptr);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
- ++this->size;
+ T *where = createHole(pos, i, n);
+ while (n--)
+ *where++ = copy;
}
+ template<typename... Args>
+ void emplace(qsizetype i, Args &&... args)
+ {
+ bool detach = this->needsDetach();
+ if (!detach) {
+ if (i == this->size && this->freeSpaceAtEnd()) {
+ new (this->end()) T(std::forward<Args>(args)...);
+ ++this->size;
+ return;
+ }
+ if (i == 0 && this->freeSpaceAtBegin()) {
+ new (this->begin() - 1) T(std::forward<Args>(args)...);
+ --this->ptr;
+ ++this->size;
+ return;
+ }
+ }
+ T tmp(std::forward<Args>(args)...);
+ typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
+ if (this->size != 0 && i == 0)
+ pos = QArrayData::GrowsAtBeginning;
+
+ this->detachAndGrow(pos, 1, nullptr, nullptr);
- void erase(T *b, T *e)
+ T *where = createHole(pos, i, 1);
+ new (where) T(std::move(tmp));
+ }
+
+ void erase(T *b, qsizetype n)
{
+ T *e = b + n;
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e <= this->end());
- ::memmove(static_cast<void *>(b), static_cast<void *>(e),
- (static_cast<T *>(this->end()) - e) * sizeof(T));
- this->size -= (e - b);
+ // Comply with std::vector::erase(): erased elements and all after them
+ // are invalidated. However, erasing from the beginning effectively
+ // means that all iterators are invalidated. We can use this freedom to
+ // erase by moving towards the end.
+ if (b == this->begin() && e != this->end()) {
+ this->ptr = e;
+ } else if (e != this->end()) {
+ ::memmove(static_cast<void *>(b), static_cast<void *>(e),
+ (static_cast<T *>(this->end()) - e) * sizeof(T));
+ }
+ this->size -= n;
}
- void assign(T *b, T *e, parameter_type t)
+ void eraseFirst() noexcept
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->size);
+ ++this->ptr;
+ --this->size;
+ }
+
+ void eraseLast() noexcept
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->size);
+ --this->size;
+ }
+
+ template <typename Predicate>
+ qsizetype eraseIf(Predicate pred)
+ {
+ qsizetype result = 0;
+ if (this->size == 0)
+ return result;
+
+ if (!this->needsDetach()) {
+ auto end = this->end();
+ auto it = std::remove_if(this->begin(), end, pred);
+ if (it != end) {
+ result = std::distance(it, end);
+ erase(it, result);
+ }
+ } else {
+ const auto begin = this->begin();
+ const auto end = this->end();
+ auto it = std::find_if(begin, end, pred);
+ if (it == end)
+ return result;
+
+ QPodArrayOps<T> other(this->size);
+ Q_CHECK_PTR(other.data());
+ auto dest = other.begin();
+ // std::uninitialized_copy will fallback to ::memcpy/memmove()
+ dest = std::uninitialized_copy(begin, it, dest);
+ dest = q_uninitialized_remove_copy_if(std::next(it), end, dest, pred);
+ other.size = std::distance(other.data(), dest);
+ result = this->size - other.size;
+ this->swap(other);
+ }
+ return result;
+ }
+
+ struct Span { T *begin; T *end; };
+
+ void copyRanges(std::initializer_list<Span> ranges)
+ {
+ auto it = this->begin();
+ std::for_each(ranges.begin(), ranges.end(), [&it](const auto &span) {
+ it = std::copy(span.begin, span.end, it);
+ });
+ this->size = std::distance(this->begin(), it);
+ }
+
+ void assign(T *b, T *e, parameter_type t) noexcept
{
Q_ASSERT(b <= e);
Q_ASSERT(b >= this->begin() && e <= this->end());
@@ -217,63 +275,88 @@ struct QPodArrayOps
// only use memcmp for fundamental types or pointers.
// Other types could have padding in the data structure or custom comparison
// operators that would break the comparison using memcmp
- if (QArrayDataPointer<T>::pass_parameter_by_value)
+ if constexpr (QArrayDataPointer<T>::pass_parameter_by_value) {
return ::memcmp(begin1, begin2, n * sizeof(T)) == 0;
- const T *end1 = begin1 + n;
- while (begin1 != end1) {
- if (*begin1 == *begin2)
- ++begin1, ++begin2;
- else
- return false;
+ } else {
+ const T *end1 = begin1 + n;
+ while (begin1 != end1) {
+ if (*begin1 == *begin2) {
+ ++begin1;
+ ++begin2;
+ } else {
+ return false;
+ }
+ }
+ return true;
}
- return true;
+ }
+
+ void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
+ {
+ auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, option);
+ Q_CHECK_PTR(pair.second);
+ Q_ASSERT(pair.first != nullptr);
+ this->d = pair.first;
+ this->ptr = pair.second;
}
};
-QT_WARNING_POP
template <class T>
struct QGenericArrayOps
: public QArrayDataPointer<T>
{
+ static_assert (std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
+protected:
+ typedef QTypedArrayData<T> Data;
+ using DataPointer = QArrayDataPointer<T>;
+
+public:
typedef typename QArrayDataPointer<T>::parameter_type parameter_type;
- void appendInitialize(size_t newSize)
+ void appendInitialize(qsizetype newSize)
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
- Q_ASSERT(newSize > uint(this->size));
- Q_ASSERT(newSize <= this->allocatedCapacity());
+ Q_ASSERT(newSize > this->size);
+ Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd());
T *const b = this->begin();
do {
new (b + this->size) T;
- } while (uint(++this->size) != newSize);
+ } while (++this->size != newSize);
}
- template<typename iterator>
- void copyAppend(iterator b, iterator e, QtPrivate::IfIsForwardIterator<iterator> = true)
+ void copyAppend(const T *b, const T *e)
{
Q_ASSERT(this->isMutable() || b == e);
Q_ASSERT(!this->isShared() || b == e);
- Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
+ Q_ASSERT(b <= e);
+ Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
+
+ if (b == e) // short-cut and handling the case b and e == nullptr
+ return;
- T *iter = this->end();
- for (; b != e; ++iter, ++b) {
- new (iter) T(*b);
+ T *data = this->begin();
+ while (b < e) {
+ new (data + this->size) T(*b);
+ ++b;
++this->size;
}
}
- void copyAppend(const T *b, const T *e)
+ void copyAppend(qsizetype n, parameter_type t)
{
- Q_ASSERT(this->isMutable() || b == e);
- Q_ASSERT(!this->isShared() || b == e);
- Q_ASSERT(std::distance(b, e) >= 0 && size_t(std::distance(b, e)) <= this->allocatedCapacity() - this->size);
+ Q_ASSERT(!this->isShared() || n == 0);
+ Q_ASSERT(this->freeSpaceAtEnd() >= n);
+ if (!n)
+ return;
- T *iter = this->end();
- this->size += e - b;
- for (; b != e; ++iter, ++b)
- new (iter) T(*b);
+ T *data = this->begin();
+ while (n--) {
+ new (data + this->size) T(t);
+ ++this->size;
+ }
}
void moveAppend(T *b, T *e)
@@ -281,230 +364,295 @@ struct QGenericArrayOps
Q_ASSERT(this->isMutable() || b == e);
Q_ASSERT(!this->isShared() || b == e);
Q_ASSERT(b <= e);
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
+ Q_ASSERT((e - b) <= this->freeSpaceAtEnd());
- T *iter = this->end();
- for (; b != e; ++iter, ++b) {
- new (iter) T(std::move(*b));
- ++this->size;
- }
- }
-
- void copyAppend(size_t n, parameter_type t)
- {
- Q_ASSERT(this->isMutable() || n == 0);
- Q_ASSERT(!this->isShared() || n == 0);
- Q_ASSERT(n <= size_t(this->allocatedCapacity() - this->size));
+ if (b == e)
+ return;
- T *iter = this->end();
- const T *const end = iter + n;
- for (; iter != end; ++iter) {
- new (iter) T(t);
+ T *data = this->begin();
+ while (b < e) {
+ new (data + this->size) T(std::move(*b));
+ ++b;
++this->size;
}
}
- template <typename ...Args>
- void emplaceBack(Args&&... args)
- {
- this->emplace(this->end(), std::forward<Args>(args)...);
- }
-
void truncate(size_t newSize)
{
Q_ASSERT(this->isMutable());
Q_ASSERT(!this->isShared());
Q_ASSERT(newSize < size_t(this->size));
- const T *const b = this->begin();
- do {
- (b + --this->size)->~T();
- } while (uint(this->size) != newSize);
+ std::destroy(this->begin() + newSize, this->end());
+ this->size = newSize;
}
void destroyAll() // Call from destructors, ONLY
{
- Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->d);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
- const T *const b = this->begin();
- const T *i = this->end();
-
- while (i != b)
- (--i)->~T();
+ std::destroy(this->begin(), this->end());
}
- void insert(T *where, const T *b, const T *e)
+ struct Inserter
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
-
- // Array may be truncated at where in case of exceptions
+ QArrayDataPointer<T> *data;
+ T *begin;
+ qsizetype size;
- T *const end = this->end();
- const T *readIter = end;
- T *writeIter = end + (e - b);
+ qsizetype sourceCopyConstruct = 0, nSource = 0, move = 0, sourceCopyAssign = 0;
+ T *end = nullptr, *last = nullptr, *where = nullptr;
- const T *const step1End = where + qMax(e - b, end - where);
-
- struct Destructor
+ Inserter(QArrayDataPointer<T> *d) : data(d)
{
- Destructor(T *&it)
- : iter(&it)
- , end(it)
- {
- }
-
- void commit()
- {
- iter = &end;
- }
+ begin = d->ptr;
+ size = d->size;
+ }
+ ~Inserter() {
+ data->ptr = begin;
+ data->size = size;
+ }
+ Q_DISABLE_COPY(Inserter)
- ~Destructor()
- {
- for (; *iter != end; --*iter)
- (*iter)->~T();
+ void setup(qsizetype pos, qsizetype n)
+ {
+ end = begin + size;
+ last = end - 1;
+ where = begin + pos;
+ qsizetype dist = size - pos;
+ sourceCopyConstruct = 0;
+ nSource = n;
+ move = n - dist; // smaller 0
+ sourceCopyAssign = n;
+ if (n > dist) {
+ sourceCopyConstruct = n - dist;
+ move = 0;
+ sourceCopyAssign -= sourceCopyConstruct;
}
-
- T **iter;
- T *end;
- } destroyer(writeIter);
-
- // Construct new elements in array
- do {
- --readIter, --writeIter;
- new (writeIter) T(*readIter);
- } while (writeIter != step1End);
-
- while (writeIter != end) {
- --e, --writeIter;
- new (writeIter) T(*e);
}
- destroyer.commit();
- this->size += destroyer.end - end;
+ void insert(qsizetype pos, const T *source, qsizetype n)
+ {
+ qsizetype oldSize = size;
+ Q_UNUSED(oldSize);
- // Copy assign over existing elements
- while (readIter != where) {
- --readIter, --writeIter;
- *writeIter = *readIter;
- }
+ setup(pos, n);
- while (writeIter != where) {
- --e, --writeIter;
- *writeIter = *e;
- }
- }
+ // first create new elements at the end, by copying from elements
+ // to be inserted (if they extend past the current end of the array)
+ for (qsizetype i = 0; i != sourceCopyConstruct; ++i) {
+ new (end + i) T(source[nSource - sourceCopyConstruct + i]);
+ ++size;
+ }
+ Q_ASSERT(size <= oldSize + n);
- void insert(T *where, size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->allocatedCapacity() - this->size >= n);
+ // now move construct new elements at the end from existing elements inside
+ // the array.
+ for (qsizetype i = sourceCopyConstruct; i != nSource; ++i) {
+ new (end + i) T(std::move(*(end + i - nSource)));
+ ++size;
+ }
+ // array has the new size now!
+ Q_ASSERT(size == oldSize + n);
- // Array may be truncated at where in case of exceptions
- T *const end = this->end();
- const T *readIter = end;
- T *writeIter = end + n;
+ // now move assign existing elements towards the end
+ for (qsizetype i = 0; i != move; --i)
+ last[i] = std::move(last[i - nSource]);
- const T *const step1End = where + qMax<size_t>(n, end - where);
+ // finally copy the remaining elements from source over
+ for (qsizetype i = 0; i != sourceCopyAssign; ++i)
+ where[i] = source[i];
+ }
- struct Destructor
+ void insert(qsizetype pos, const T &t, qsizetype n)
{
- Destructor(T *&it)
- : iter(&it)
- , end(it)
- {
- }
+ const qsizetype oldSize = size;
+ Q_UNUSED(oldSize);
- void commit()
- {
- iter = &end;
- }
+ setup(pos, n);
- ~Destructor()
- {
- for (; *iter != end; --*iter)
- (*iter)->~T();
+ // first create new elements at the end, by copying from elements
+ // to be inserted (if they extend past the current end of the array)
+ for (qsizetype i = 0; i != sourceCopyConstruct; ++i) {
+ new (end + i) T(t);
+ ++size;
}
+ Q_ASSERT(size <= oldSize + n);
- T **iter;
- T *end;
- } destroyer(writeIter);
+ // now move construct new elements at the end from existing elements inside
+ // the array.
+ for (qsizetype i = sourceCopyConstruct; i != nSource; ++i) {
+ new (end + i) T(std::move(*(end + i - nSource)));
+ ++size;
+ }
+ // array has the new size now!
+ Q_ASSERT(size == oldSize + n);
- // Construct new elements in array
- do {
- --readIter, --writeIter;
- new (writeIter) T(*readIter);
- } while (writeIter != step1End);
+ // now move assign existing elements towards the end
+ for (qsizetype i = 0; i != move; --i)
+ last[i] = std::move(last[i - nSource]);
- while (writeIter != end) {
- --n, --writeIter;
- new (writeIter) T(t);
+ // finally copy the remaining elements from source over
+ for (qsizetype i = 0; i != sourceCopyAssign; ++i)
+ where[i] = t;
}
- destroyer.commit();
- this->size += destroyer.end - end;
-
- // Copy assign over existing elements
- while (readIter != where) {
- --readIter, --writeIter;
- *writeIter = *readIter;
+ void insertOne(qsizetype pos, T &&t)
+ {
+ setup(pos, 1);
+
+ if (sourceCopyConstruct) {
+ Q_ASSERT(sourceCopyConstruct == 1);
+ new (end) T(std::move(t));
+ ++size;
+ } else {
+ // create a new element at the end by move constructing one existing element
+ // inside the array.
+ new (end) T(std::move(*(end - 1)));
+ ++size;
+
+ // now move assign existing elements towards the end
+ for (qsizetype i = 0; i != move; --i)
+ last[i] = std::move(last[i - 1]);
+
+ // and move the new item into place
+ *where = std::move(t);
+ }
}
+ };
- while (writeIter != where) {
- --n, --writeIter;
- *writeIter = t;
+ void insert(qsizetype i, const T *data, qsizetype n)
+ {
+ const bool growsAtBegin = this->size != 0 && i == 0;
+ const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
+
+ DataPointer oldData;
+ this->detachAndGrow(pos, n, &data, &oldData);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
+
+ if (growsAtBegin) {
+ // copy construct items in reverse order at the begin
+ Q_ASSERT(this->freeSpaceAtBegin() >= n);
+ while (n) {
+ --n;
+ new (this->begin() - 1) T(data[n]);
+ --this->ptr;
+ ++this->size;
+ }
+ } else {
+ Inserter(this).insert(i, data, n);
}
}
- template <typename ...Args>
- void createInPlace(T *where, Args&&... args) { new (where) T(std::forward<Args>(args)...); }
+ void insert(qsizetype i, qsizetype n, parameter_type t)
+ {
+ T copy(t);
+
+ const bool growsAtBegin = this->size != 0 && i == 0;
+ const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
+
+ this->detachAndGrow(pos, n, nullptr, nullptr);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
+
+ if (growsAtBegin) {
+ // copy construct items in reverse order at the begin
+ Q_ASSERT(this->freeSpaceAtBegin() >= n);
+ while (n--) {
+ new (this->begin() - 1) T(copy);
+ --this->ptr;
+ ++this->size;
+ }
+ } else {
+ Inserter(this).insert(i, copy, n);
+ }
+ }
- template <typename iterator, typename ...Args>
- void emplace(iterator where, Args&&... args)
+ template<typename... Args>
+ void emplace(qsizetype i, Args &&... args)
{
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->allocatedCapacity() - this->size >= 1);
+ bool detach = this->needsDetach();
+ if (!detach) {
+ if (i == this->size && this->freeSpaceAtEnd()) {
+ new (this->end()) T(std::forward<Args>(args)...);
+ ++this->size;
+ return;
+ }
+ if (i == 0 && this->freeSpaceAtBegin()) {
+ new (this->begin() - 1) T(std::forward<Args>(args)...);
+ --this->ptr;
+ ++this->size;
+ return;
+ }
+ }
+ T tmp(std::forward<Args>(args)...);
+ const bool growsAtBegin = this->size != 0 && i == 0;
+ const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
- createInPlace(this->end(), std::forward<Args>(args)...);
- ++this->size;
+ this->detachAndGrow(pos, 1, nullptr, nullptr);
- std::rotate(where, this->end() - 1, this->end());
+ if (growsAtBegin) {
+ Q_ASSERT(this->freeSpaceAtBegin());
+ new (this->begin() - 1) T(std::move(tmp));
+ --this->ptr;
+ ++this->size;
+ } else {
+ Inserter(this).insertOne(i, std::move(tmp));
+ }
}
- void erase(T *b, T *e)
+ void erase(T *b, qsizetype n)
{
+ T *e = b + n;
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e <= this->end());
- const T *const end = this->end();
-
- // move (by assignment) the elements from e to end
- // onto b to the new end
- while (e != end) {
- *b = *e;
- ++b, ++e;
+ // Comply with std::vector::erase(): erased elements and all after them
+ // are invalidated. However, erasing from the beginning effectively
+ // means that all iterators are invalidated. We can use this freedom to
+ // erase by moving towards the end.
+ if (b == this->begin() && e != this->end()) {
+ this->ptr = e;
+ } else {
+ const T *const end = this->end();
+
+ // move (by assignment) the elements from e to end
+ // onto b to the new end
+ while (e != end) {
+ *b = std::move(*e);
+ ++b;
+ ++e;
+ }
}
+ this->size -= n;
+ std::destroy(b, e);
+ }
- // destroy the final elements at the end
- // here, b points to the new end and e to the actual end
- do {
- (--e)->~T();
- --this->size;
- } while (e != b);
+ void eraseFirst() noexcept
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->size);
+ this->begin()->~T();
+ ++this->ptr;
+ --this->size;
+ }
+
+ void eraseLast() noexcept
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->size);
+ (this->end() - 1)->~T();
+ --this->size;
}
+
void assign(T *b, T *e, parameter_type t)
{
Q_ASSERT(b <= e);
@@ -518,10 +666,12 @@ struct QGenericArrayOps
{
const T *end1 = begin1 + n;
while (begin1 != end1) {
- if (*begin1 == *begin2)
- ++begin1, ++begin2;
- else
+ if (*begin1 == *begin2) {
+ ++begin1;
+ ++begin2;
+ } else {
return false;
+ }
}
return true;
}
@@ -531,219 +681,195 @@ template <class T>
struct QMovableArrayOps
: QGenericArrayOps<T>
{
- // using QGenericArrayOps<T>::appendInitialize;
+ static_assert (std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
+protected:
+ typedef QTypedArrayData<T> Data;
+ using DataPointer = QArrayDataPointer<T>;
+
+public:
// using QGenericArrayOps<T>::copyAppend;
+ // using QGenericArrayOps<T>::moveAppend;
// using QGenericArrayOps<T>::truncate;
// using QGenericArrayOps<T>::destroyAll;
typedef typename QGenericArrayOps<T>::parameter_type parameter_type;
- void insert(T *where, const T *b, const T *e)
+ struct Inserter
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= where || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
-
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
+ QArrayDataPointer<T> *data;
+ T *displaceFrom;
+ T *displaceTo;
+ qsizetype nInserts = 0;
+ qsizetype bytes;
+
+ Inserter(QArrayDataPointer<T> *d) : data(d) { }
+ ~Inserter() {
+ if constexpr (!std::is_nothrow_copy_constructible_v<T>) {
+ if (displaceFrom != displaceTo) {
+ ::memmove(static_cast<void *>(displaceFrom), static_cast<void *>(displaceTo), bytes);
+ nInserts -= qAbs(displaceFrom - displaceTo);
+ }
+ }
+ data->size += nInserts;
+ }
+ Q_DISABLE_COPY(Inserter)
- struct ReversibleDisplace
+ T *displace(qsizetype pos, qsizetype n)
{
- ReversibleDisplace(T *start, T *finish, size_t diff)
- : begin(start)
- , end(finish)
- , displace(diff)
- {
- ::memmove(static_cast<void *>(begin + displace), static_cast<void *>(begin),
- (end - begin) * sizeof(T));
- }
+ nInserts = n;
+ T *insertionPoint = data->ptr + pos;
+ displaceFrom = data->ptr + pos;
+ displaceTo = displaceFrom + n;
+ bytes = data->size - pos;
+ bytes *= sizeof(T);
+ ::memmove(static_cast<void *>(displaceTo), static_cast<void *>(displaceFrom), bytes);
+ return insertionPoint;
+ }
- void commit() { displace = 0; }
+ void insert(qsizetype pos, const T *source, qsizetype n)
+ {
+ T *where = displace(pos, n);
- ~ReversibleDisplace()
- {
- if (displace)
- ::memmove(static_cast<void *>(begin), static_cast<void *>(begin + displace),
- (end - begin) * sizeof(T));
+ while (n--) {
+ new (where) T(*source);
+ ++where;
+ ++source;
+ ++displaceFrom;
}
+ }
- T *const begin;
- T *const end;
- size_t displace;
-
- } displace(where, this->end(), size_t(e - b));
-
- struct CopyConstructor
+ void insert(qsizetype pos, const T &t, qsizetype n)
{
- CopyConstructor(T *w) : where(w) {}
-
- void copy(const T *src, const T *const srcEnd)
- {
- n = 0;
- for (; src != srcEnd; ++src) {
- new (where + n) T(*src);
- ++n;
- }
- n = 0;
- }
+ T *where = displace(pos, n);
- ~CopyConstructor()
- {
- while (n)
- where[--n].~T();
+ while (n--) {
+ new (where) T(t);
+ ++where;
+ ++displaceFrom;
}
+ }
- T *const where;
- size_t n;
- } copier(where);
-
- copier.copy(b, e);
- displace.commit();
- this->size += (e - b);
- }
+ void insertOne(qsizetype pos, T &&t)
+ {
+ T *where = displace(pos, 1);
+ new (where) T(std::move(t));
+ ++displaceFrom;
+ Q_ASSERT(displaceFrom == displaceTo);
+ }
- void insert(T *where, size_t n, parameter_type t)
- {
- Q_ASSERT(!this->isShared());
- Q_ASSERT(where >= this->begin() && where <= this->end());
- Q_ASSERT(this->allocatedCapacity() - this->size >= n);
+ };
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
- struct ReversibleDisplace
- {
- ReversibleDisplace(T *start, T *finish, size_t diff)
- : begin(start)
- , end(finish)
- , displace(diff)
- {
- ::memmove(static_cast<void *>(begin + displace), static_cast<void *>(begin),
- (end - begin) * sizeof(T));
+ void insert(qsizetype i, const T *data, qsizetype n)
+ {
+ const bool growsAtBegin = this->size != 0 && i == 0;
+ const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
+
+ DataPointer oldData;
+ this->detachAndGrow(pos, n, &data, &oldData);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
+
+ if (growsAtBegin) {
+ // copy construct items in reverse order at the begin
+ Q_ASSERT(this->freeSpaceAtBegin() >= n);
+ while (n) {
+ --n;
+ new (this->begin() - 1) T(data[n]);
+ --this->ptr;
+ ++this->size;
}
+ } else {
+ Inserter(this).insert(i, data, n);
+ }
+ }
- void commit() { displace = 0; }
-
- ~ReversibleDisplace()
- {
- if (displace)
- ::memmove(static_cast<void *>(begin), static_cast<void *>(begin + displace),
- (end - begin) * sizeof(T));
+ void insert(qsizetype i, qsizetype n, parameter_type t)
+ {
+ T copy(t);
+
+ const bool growsAtBegin = this->size != 0 && i == 0;
+ const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
+
+ this->detachAndGrow(pos, n, nullptr, nullptr);
+ Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
+ (pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
+
+ if (growsAtBegin) {
+ // copy construct items in reverse order at the begin
+ Q_ASSERT(this->freeSpaceAtBegin() >= n);
+ while (n--) {
+ new (this->begin() - 1) T(copy);
+ --this->ptr;
+ ++this->size;
}
+ } else {
+ Inserter(this).insert(i, copy, n);
+ }
+ }
- T *const begin;
- T *const end;
- size_t displace;
-
- } displace(where, this->end(), n);
-
- struct CopyConstructor
- {
- CopyConstructor(T *w) : where(w) {}
-
- void copy(size_t count, parameter_type proto)
- {
- n = 0;
- while (count--) {
- new (where + n) T(proto);
- ++n;
- }
- n = 0;
+ template<typename... Args>
+ void emplace(qsizetype i, Args &&... args)
+ {
+ bool detach = this->needsDetach();
+ if (!detach) {
+ if (i == this->size && this->freeSpaceAtEnd()) {
+ new (this->end()) T(std::forward<Args>(args)...);
+ ++this->size;
+ return;
}
-
- ~CopyConstructor()
- {
- while (n)
- where[--n].~T();
+ if (i == 0 && this->freeSpaceAtBegin()) {
+ new (this->begin() - 1) T(std::forward<Args>(args)...);
+ --this->ptr;
+ ++this->size;
+ return;
}
-
- T *const where;
- size_t n;
- } copier(where);
-
- copier.copy(n, t);
- displace.commit();
- this->size += int(n);
+ }
+ T tmp(std::forward<Args>(args)...);
+ const bool growsAtBegin = this->size != 0 && i == 0;
+ const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
+
+ this->detachAndGrow(pos, 1, nullptr, nullptr);
+ if (growsAtBegin) {
+ Q_ASSERT(this->freeSpaceAtBegin());
+ new (this->begin() - 1) T(std::move(tmp));
+ --this->ptr;
+ ++this->size;
+ } else {
+ Inserter(this).insertOne(i, std::move(tmp));
+ }
}
- // use moving insert
- using QGenericArrayOps<T>::insert;
-
- void erase(T *b, T *e)
+ void erase(T *b, qsizetype n)
{
+ T *e = b + n;
+
Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e <= this->end());
- struct Mover
- {
- Mover(T *&start, const T *finish, int &sz)
- : destination(start)
- , source(start)
- , n(finish - start)
- , size(sz)
- {
- }
-
- ~Mover()
- {
- ::memmove(static_cast<void *>(destination), static_cast<const void *>(source), n * sizeof(T));
- size -= (source - destination);
- }
-
- T *&destination;
- const T *const source;
- size_t n;
- int &size;
- } mover(e, this->end(), this->size);
+ // Comply with std::vector::erase(): erased elements and all after them
+ // are invalidated. However, erasing from the beginning effectively
+ // means that all iterators are invalidated. We can use this freedom to
+ // erase by moving towards the end.
- // destroy the elements we're erasing
- do {
- // Exceptions or not, dtor called once per instance
- (--e)->~T();
- } while (e != b);
+ std::destroy(b, e);
+ if (b == this->begin() && e != this->end()) {
+ this->ptr = e;
+ } else if (e != this->end()) {
+ memmove(static_cast<void *>(b), static_cast<const void *>(e), (static_cast<const T *>(this->end()) - e)*sizeof(T));
+ }
+ this->size -= n;
}
- void moveAppend(T *b, T *e)
+ void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
{
- Q_ASSERT(this->isMutable());
- Q_ASSERT(!this->isShared());
- Q_ASSERT(b <= e);
- Q_ASSERT(e <= this->begin() || b > this->end()); // No overlap
- Q_ASSERT(size_t(e - b) <= this->allocatedCapacity() - this->size);
-
- // Provides strong exception safety guarantee,
- // provided T::~T() nothrow
-
- struct CopyConstructor
- {
- CopyConstructor(T *w) : where(w) {}
-
- void copy(T *src, const T *const srcEnd)
- {
- n = 0;
- for (; src != srcEnd; ++src) {
- new (where + n) T(std::move(*src));
- ++n;
- }
- n = 0;
- }
-
- ~CopyConstructor()
- {
- while (n)
- where[--n].~T();
- }
-
- T *const where;
- size_t n;
- } copier(this->end());
-
- copier.copy(b, e);
- this->size += (e - b);
+ auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, option);
+ Q_CHECK_PTR(pair.second);
+ Q_ASSERT(pair.first != nullptr);
+ this->d = pair.first;
+ this->ptr = pair.second;
}
};
@@ -756,7 +882,7 @@ struct QArrayOpsSelector
template <class T>
struct QArrayOpsSelector<T,
typename std::enable_if<
- !QTypeInfoQuery<T>::isComplex && QTypeInfoQuery<T>::isRelocatable
+ !QTypeInfo<T>::isComplex && QTypeInfo<T>::isRelocatable
>::type>
{
typedef QPodArrayOps<T> Type;
@@ -765,17 +891,101 @@ struct QArrayOpsSelector<T,
template <class T>
struct QArrayOpsSelector<T,
typename std::enable_if<
- QTypeInfoQuery<T>::isComplex && QTypeInfoQuery<T>::isRelocatable
+ QTypeInfo<T>::isComplex && QTypeInfo<T>::isRelocatable
>::type>
{
typedef QMovableArrayOps<T> Type;
};
+template <class T>
+struct QCommonArrayOps : QArrayOpsSelector<T>::Type
+{
+ using Base = typename QArrayOpsSelector<T>::Type;
+ using Data = QTypedArrayData<T>;
+ using DataPointer = QArrayDataPointer<T>;
+ using parameter_type = typename Base::parameter_type;
+
+protected:
+ using Self = QCommonArrayOps<T>;
+
+public:
+ // using Base::truncate;
+ // using Base::destroyAll;
+ // using Base::assign;
+ // using Base::compare;
+
+ template<typename It>
+ void appendIteratorRange(It b, It e, QtPrivate::IfIsForwardIterator<It> = true)
+ {
+ Q_ASSERT(this->isMutable() || b == e);
+ Q_ASSERT(!this->isShared() || b == e);
+ const qsizetype distance = std::distance(b, e);
+ Q_ASSERT(distance >= 0 && distance <= this->allocatedCapacity() - this->size);
+ Q_UNUSED(distance);
+
+#if __cplusplus >= 202002L && defined(__cpp_concepts) && defined(__cpp_lib_concepts)
+ constexpr bool canUseCopyAppend =
+ std::contiguous_iterator<It> &&
+ std::is_same_v<
+ std::remove_cv_t<typename std::iterator_traits<It>::value_type>,
+ T
+ >;
+ if constexpr (canUseCopyAppend) {
+ this->copyAppend(std::to_address(b), std::to_address(e));
+ } else
+#endif
+ {
+ T *iter = this->end();
+ for (; b != e; ++iter, ++b) {
+ new (iter) T(*b);
+ ++this->size;
+ }
+ }
+ }
+
+ // slightly higher level API than copyAppend() that also preallocates space
+ void growAppend(const T *b, const T *e)
+ {
+ if (b == e)
+ return;
+ Q_ASSERT(b < e);
+ const qsizetype n = e - b;
+ DataPointer old;
+
+ // points into range:
+ if (QtPrivate::q_points_into_range(b, *this))
+ this->detachAndGrow(QArrayData::GrowsAtEnd, n, &b, &old);
+ else
+ this->detachAndGrow(QArrayData::GrowsAtEnd, n, nullptr, nullptr);
+ Q_ASSERT(this->freeSpaceAtEnd() >= n);
+ // b might be updated so use [b, n)
+ this->copyAppend(b, b + n);
+ }
+
+ void appendUninitialized(qsizetype newSize)
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(newSize > this->size);
+ Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd());
+
+ T *const b = this->begin();
+ do {
+ auto ptr = b + this->size;
+
+ if constexpr (std::is_constructible_v<T, Qt::Initialization>)
+ new (ptr) T(Qt::Uninitialized);
+ else
+ new (ptr) T; // not T() -- default-construct
+ } while (++this->size != newSize);
+ }
+};
+
} // namespace QtPrivate
template <class T>
struct QArrayDataOps
- : QtPrivate::QArrayOpsSelector<T>::Type
+ : QtPrivate::QCommonArrayOps<T>
{
};
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index a17cf4a101..6657d40cf9 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QARRAYDATAPOINTER_H
#define QARRAYDATAPOINTER_H
@@ -43,6 +7,9 @@
#include <QtCore/qarraydataops.h>
#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/q20functional.h>
+#include <QtCore/q20memory.h>
+
QT_BEGIN_NAMESPACE
template <class T>
@@ -53,39 +20,52 @@ private:
typedef QArrayDataOps<T> DataOps;
public:
- typedef typename Data::iterator iterator;
- typedef typename Data::const_iterator const_iterator;
- enum { pass_parameter_by_value = std::is_fundamental<T>::value || std::is_pointer<T>::value };
+ enum {
+ pass_parameter_by_value =
+ std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_enum<T>::value
+ };
typedef typename std::conditional<pass_parameter_by_value, T, const T &>::type parameter_type;
- QArrayDataPointer() noexcept
- : d(Data::sharedNull()), ptr(Data::sharedNullData()), size(0)
+ Q_NODISCARD_CTOR
+ constexpr QArrayDataPointer() noexcept
+ : d(nullptr), ptr(nullptr), size(0)
{
}
+ Q_NODISCARD_CTOR
QArrayDataPointer(const QArrayDataPointer &other) noexcept
: d(other.d), ptr(other.ptr), size(other.size)
{
- other.d->ref();
+ ref();
}
- QArrayDataPointer(Data *header, T *adata, size_t n = 0) noexcept
- : d(header), ptr(adata), size(int(n))
+ Q_NODISCARD_CTOR
+ constexpr QArrayDataPointer(Data *header, T *adata, qsizetype n = 0) noexcept
+ : d(header), ptr(adata), size(n)
{
}
- explicit QArrayDataPointer(QPair<QTypedArrayData<T> *, T *> adata, size_t n = 0)
- : d(adata.first), ptr(adata.second), size(int(n))
+ Q_NODISCARD_CTOR
+ explicit QArrayDataPointer(std::pair<QTypedArrayData<T> *, T *> adata, qsizetype n = 0) noexcept
+ : d(adata.first), ptr(adata.second), size(n)
{
- Q_CHECK_PTR(d);
}
- QArrayDataPointer(QArrayDataPointerRef<T> dd) noexcept
- : d(dd.ptr), ptr(dd.data), size(dd.size)
+ Q_NODISCARD_CTOR explicit
+ QArrayDataPointer(qsizetype alloc, qsizetype n = 0,
+ QArrayData::AllocationOption option = QArrayData::KeepSize)
+ : QArrayDataPointer(Data::allocate(alloc, option), n)
{
}
+ Q_NODISCARD_CTOR
+ static QArrayDataPointer fromRawData(const T *rawData, qsizetype length) noexcept
+ {
+ Q_ASSERT(rawData || !length);
+ return { nullptr, const_cast<T *>(rawData), length };
+ }
+
QArrayDataPointer &operator=(const QArrayDataPointer &other) noexcept
{
QArrayDataPointer tmp(other);
@@ -93,160 +73,457 @@ public:
return *this;
}
+ Q_NODISCARD_CTOR
QArrayDataPointer(QArrayDataPointer &&other) noexcept
- : d(other.d), ptr(other.ptr), size(other.size)
+ : d(std::exchange(other.d, nullptr)),
+ ptr(std::exchange(other.ptr, nullptr)),
+ size(std::exchange(other.size, 0))
{
- other.d = Data::sharedNull();
- other.ptr = Data::sharedNullData();
- other.size = 0;
}
- QArrayDataPointer &operator=(QArrayDataPointer &&other) noexcept
- {
- QArrayDataPointer moved(std::move(other));
- this->swap(moved);
- return *this;
- }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QArrayDataPointer)
DataOps &operator*() noexcept
{
- Q_ASSERT(d);
return *static_cast<DataOps *>(this);
}
DataOps *operator->() noexcept
{
- Q_ASSERT(d);
return static_cast<DataOps *>(this);
}
const DataOps &operator*() const noexcept
{
- Q_ASSERT(d);
return *static_cast<const DataOps *>(this);
}
const DataOps *operator->() const noexcept
{
- Q_ASSERT(d);
return static_cast<const DataOps *>(this);
}
~QArrayDataPointer()
{
if (!deref()) {
- if (isMutable())
- (*this)->destroyAll();
- Data::deallocate(d);
+ (*this)->destroyAll();
+ free(d);
}
}
bool isNull() const noexcept
{
- return d == Data::sharedNull();
+ return !ptr;
}
T *data() noexcept { return ptr; }
const T *data() const noexcept { return ptr; }
- iterator begin(iterator = iterator()) noexcept { return data(); }
- iterator end(iterator = iterator()) noexcept { return data() + size; }
- const_iterator begin(const_iterator = const_iterator()) const noexcept { return data(); }
- const_iterator end(const_iterator = const_iterator()) const noexcept { return data() + size; }
- const_iterator constBegin(const_iterator = const_iterator()) const noexcept { return data(); }
- const_iterator constEnd(const_iterator = const_iterator()) const noexcept { return data() + size; }
+ T *begin() noexcept { return data(); }
+ T *end() noexcept { return data() + size; }
+ const T *begin() const noexcept { return data(); }
+ const T *end() const noexcept { return data() + size; }
+ const T *constBegin() const noexcept { return data(); }
+ const T *constEnd() const noexcept { return data() + size; }
void swap(QArrayDataPointer &other) noexcept
{
- qSwap(d, other.d);
- qSwap(ptr, other.ptr);
- qSwap(size, other.size);
+ qt_ptr_swap(d, other.d);
+ qt_ptr_swap(ptr, other.ptr);
+ std::swap(size, other.size);
}
- void clear() Q_DECL_NOEXCEPT_EXPR(std::is_nothrow_destructible<T>::value)
+ void clear() noexcept(std::is_nothrow_destructible<T>::value)
{
QArrayDataPointer tmp;
swap(tmp);
}
- bool detach()
+ void detach(QArrayDataPointer *old = nullptr)
+ {
+ if (needsDetach())
+ reallocateAndGrow(QArrayData::GrowsAtEnd, 0, old);
+ }
+
+ /*! \internal
+
+ Reinterprets the data of this QArrayDataPointer to type X. It's the
+ caller's responsibility to ensure that the data contents are valid and
+ properly aligned, particularly if T and X are not trivial types (i.e,
+ don't do that). The current size is kept and the allocated capacity is
+ updated to account for the difference in the element type's size.
+
+ This is used in QString::fromLatin1 to perform in-place conversion of
+ QString to QByteArray.
+ */
+ template <typename X> QArrayDataPointer<X> reinterpreted() &&
+ {
+ if (sizeof(T) != sizeof(X)) {
+ Q_ASSERT(!d->isShared());
+ d->alloc = d->alloc * sizeof(T) / sizeof(X);
+ }
+ auto od = reinterpret_cast<QTypedArrayData<X> *>(std::exchange(d, nullptr));
+ auto optr = reinterpret_cast<X *>(std::exchange(ptr, nullptr));
+ return { od, optr, std::exchange(size, 0) };
+ }
+
+ /*! \internal
+
+ Detaches this (optionally) and grows to accommodate the free space for
+ \a n elements at the required side. The side is determined from \a pos.
+
+ \a data pointer can be provided when the caller knows that \a data
+ points into range [this->begin(), this->end()). In case it is, *data
+ would be updated so that it continues to point to the element it was
+ pointing to before the data move. if \a data does not point into range,
+ one can/should pass \c nullptr.
+
+ Similarly to \a data, \a old, pointer to a default-constructed QADP, can
+ be provided when the caller expects to e.g. copy the data from this to
+ itself:
+ \code
+ QList<T> list(5);
+ qsizetype pos = getArbitraryPos();
+ list.insert(pos, list.begin(), list.end());
+ \endcode
+
+ The default rule would be: \a data and \a old must either both be valid
+ pointers, or both equal to \c nullptr.
+ */
+ void detachAndGrow(QArrayData::GrowthPosition where, qsizetype n, const T **data,
+ QArrayDataPointer *old)
{
- if (d->needsDetach()) {
- QPair<Data *, T *> copy = clone(d->detachFlags());
- QArrayDataPointer old(d, ptr, size);
- d = copy.first;
- ptr = copy.second;
- return true;
+ const bool detach = needsDetach();
+ bool readjusted = false;
+ if (!detach) {
+ if (!n || (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n)
+ || (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n))
+ return;
+ readjusted = tryReadjustFreeSpace(where, n, data);
+ Q_ASSERT(!readjusted
+ || (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n)
+ || (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n));
}
- return false;
+ if (!readjusted)
+ reallocateAndGrow(where, n, old);
+ }
+
+ /*! \internal
+
+ Reallocates to accommodate the free space for \a n elements at the
+ required side. The side is determined from \a pos. Might also shrink
+ when n < 0.
+ */
+ Q_NEVER_INLINE void reallocateAndGrow(QArrayData::GrowthPosition where, qsizetype n,
+ QArrayDataPointer *old = nullptr)
+ {
+ if constexpr (QTypeInfo<T>::isRelocatable && alignof(T) <= alignof(std::max_align_t)) {
+ if (where == QArrayData::GrowsAtEnd && !old && !needsDetach() && n > 0) {
+ (*this)->reallocate(constAllocatedCapacity() - freeSpaceAtEnd() + n, QArrayData::Grow); // fast path
+ return;
+ }
+ }
+
+ QArrayDataPointer dp(allocateGrow(*this, n, where));
+ if (n > 0)
+ Q_CHECK_PTR(dp.data());
+ if (where == QArrayData::GrowsAtBeginning) {
+ Q_ASSERT(dp.freeSpaceAtBegin() >= n);
+ } else {
+ Q_ASSERT(dp.freeSpaceAtEnd() >= n);
+ }
+ if (size) {
+ qsizetype toCopy = size;
+ if (n < 0)
+ toCopy += n;
+ if (needsDetach() || old)
+ dp->copyAppend(begin(), begin() + toCopy);
+ else
+ dp->moveAppend(begin(), begin() + toCopy);
+ Q_ASSERT(dp.size == toCopy);
+ }
+
+ swap(dp);
+ if (old)
+ old->swap(dp);
+ }
+
+ /*! \internal
+
+ Attempts to relocate [begin(), end()) to accommodate the free space for
+ \a n elements at the required side. The side is determined from \a pos.
+
+ Returns \c true if the internal data is moved. Returns \c false when
+ there is no point in moving the data or the move is impossible. If \c
+ false is returned, it is the responsibility of the caller to figure out
+ how to accommodate the free space for \a n elements at \a pos.
+
+ This function expects that certain preconditions are met, e.g. the
+ detach is not needed, n > 0 and so on. This is intentional to reduce the
+ number of if-statements when the caller knows that preconditions would
+ be satisfied.
+
+ \sa reallocateAndGrow
+ */
+ bool tryReadjustFreeSpace(QArrayData::GrowthPosition pos, qsizetype n, const T **data = nullptr)
+ {
+ Q_ASSERT(!this->needsDetach());
+ Q_ASSERT(n > 0);
+ Q_ASSERT((pos == QArrayData::GrowsAtEnd && this->freeSpaceAtEnd() < n)
+ || (pos == QArrayData::GrowsAtBeginning && this->freeSpaceAtBegin() < n));
+
+ const qsizetype capacity = this->constAllocatedCapacity();
+ const qsizetype freeAtBegin = this->freeSpaceAtBegin();
+ const qsizetype freeAtEnd = this->freeSpaceAtEnd();
+
+ qsizetype dataStartOffset = 0;
+ // algorithm:
+ // a. GrowsAtEnd: relocate if space at begin AND size < (capacity * 2) / 3
+ // [all goes to free space at end]:
+ // new free space at begin = 0
+ //
+ // b. GrowsAtBeginning: relocate if space at end AND size < capacity / 3
+ // [balance the free space]:
+ // new free space at begin = n + (total free space - n) / 2
+ if (pos == QArrayData::GrowsAtEnd && freeAtBegin >= n
+ && ((3 * this->size) < (2 * capacity))) {
+ // dataStartOffset = 0; - done in declaration
+ } else if (pos == QArrayData::GrowsAtBeginning && freeAtEnd >= n
+ && ((3 * this->size) < capacity)) {
+ // total free space == capacity - size
+ dataStartOffset = n + qMax(0, (capacity - this->size - n) / 2);
+ } else {
+ // nothing to do otherwise
+ return false;
+ }
+
+ relocate(dataStartOffset - freeAtBegin, data);
+
+ Q_ASSERT((pos == QArrayData::GrowsAtEnd && this->freeSpaceAtEnd() >= n)
+ || (pos == QArrayData::GrowsAtBeginning && this->freeSpaceAtBegin() >= n));
+ return true;
+ }
+
+ /*! \internal
+
+ Relocates [begin(), end()) by \a offset and updates \a data if it is not
+ \c nullptr and points into [begin(), end()).
+ */
+ void relocate(qsizetype offset, const T **data = nullptr)
+ {
+ T *res = this->ptr + offset;
+ QtPrivate::q_relocate_overlap_n(this->ptr, this->size, res);
+ // first update data pointer, then this->ptr
+ if (data && QtPrivate::q_points_into_range(*data, *this))
+ *data += offset;
+ this->ptr = res;
+ }
+
+ template <typename InputIterator, typename Projection = q20::identity>
+ void assign(InputIterator first, InputIterator last, Projection proj = {})
+ {
+ // This function only provides the basic exception guarantee.
+ constexpr bool IsFwdIt = std::is_convertible_v<
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ std::forward_iterator_tag>;
+ constexpr bool IsIdentity = std::is_same_v<Projection, q20::identity>;
+
+ if constexpr (IsFwdIt) {
+ const qsizetype n = std::distance(first, last);
+ if (needsDetach() || n > constAllocatedCapacity()) {
+ QArrayDataPointer allocated(detachCapacity(n));
+ swap(allocated);
+ }
+ } else if (needsDetach()) {
+ QArrayDataPointer allocated(allocatedCapacity());
+ swap(allocated);
+ // We don't want to copy data that we know we'll overwrite
+ }
+
+ auto offset = freeSpaceAtBegin();
+ const auto capacityBegin = begin() - offset;
+ const auto prependBufferEnd = begin();
+
+ if constexpr (!std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) {
+ // If construction can throw, and we have freeSpaceAtBegin(),
+ // it's easiest to just clear the container and start fresh.
+ // The alternative would be to keep track of two active, disjoint ranges.
+ if (offset) {
+ (*this)->truncate(0);
+ setBegin(capacityBegin);
+ offset = 0;
+ }
+ }
+
+ auto dst = capacityBegin;
+ const auto dend = end();
+ if (offset) { // avoids dead stores
+ setBegin(capacityBegin); // undo prepend optimization
+
+ // By construction, the following loop is nothrow!
+ // (otherwise, we can't reach here)
+ // Assumes InputIterator operations don't throw.
+ // (but we can't statically assert that, as these operations
+ // have preconditons, so typically aren't noexcept)
+ while (true) {
+ if (dst == prependBufferEnd) { // ran out of prepend buffer space
+ size += offset;
+ // we now have a contiguous buffer, continue with the main loop:
+ break;
+ }
+ if (first == last) { // ran out of elements to assign
+ std::destroy(prependBufferEnd, dend);
+ size = dst - begin();
+ return;
+ }
+ // construct element in prepend buffer
+ q20::construct_at(dst, std::invoke(proj, *first));
+ ++dst;
+ ++first;
+ }
+ }
+
+ while (true) {
+ if (first == last) { // ran out of elements to assign
+ std::destroy(dst, dend);
+ break;
+ }
+ if (dst == dend) { // ran out of existing elements to overwrite
+ if constexpr (IsFwdIt && IsIdentity) {
+ dst = std::uninitialized_copy(first, last, dst);
+ break;
+ } else if constexpr (IsFwdIt && !IsIdentity
+ && std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) {
+ for (; first != last; ++dst, ++first) // uninitialized_copy with projection
+ q20::construct_at(dst, std::invoke(proj, *first));
+ break;
+ } else {
+ do {
+ (*this)->emplace(size, std::invoke(proj, *first));
+ } while (++first != last);
+ return; // size() is already correct (and dst invalidated)!
+ }
+ }
+ *dst = std::invoke(proj, *first); // overwrite existing element
+ ++dst;
+ ++first;
+ }
+ size = dst - begin();
+ }
+
+ QArrayDataPointer sliced(qsizetype pos, qsizetype n) const &
+ {
+ QArrayDataPointer result(n);
+ std::uninitialized_copy_n(begin() + pos, n, result.begin());
+ result.size = n;
+ return result;
+ }
+
+ QArrayDataPointer sliced(qsizetype pos, qsizetype n) &&
+ {
+ if (needsDetach())
+ return sliced(pos, n);
+ T *newBeginning = begin() + pos;
+ std::destroy(begin(), newBeginning);
+ std::destroy(newBeginning + n, end());
+ setBegin(newBeginning);
+ size = n;
+ return std::move(*this);
}
// forwards from QArrayData
- size_t allocatedCapacity() noexcept { return d->allocatedCapacity(); }
- size_t constAllocatedCapacity() const noexcept { return d->constAllocatedCapacity(); }
- int refCounterValue() const noexcept { return d->refCounterValue(); }
- bool ref() noexcept { return d->ref(); }
- bool deref() noexcept { return d->deref(); }
- bool isMutable() const noexcept { return d->isMutable(); }
- bool isStatic() const noexcept { return d->isStatic(); }
- bool isShared() const noexcept { return d->isShared(); }
+ qsizetype allocatedCapacity() noexcept { return d ? d->allocatedCapacity() : 0; }
+ qsizetype constAllocatedCapacity() const noexcept { return d ? d->constAllocatedCapacity() : 0; }
+ void ref() noexcept { if (d) d->ref(); }
+ bool deref() noexcept { return !d || d->deref(); }
+ bool isMutable() const noexcept { return d; }
+ bool isShared() const noexcept { return !d || d->isShared(); }
bool isSharedWith(const QArrayDataPointer &other) const noexcept { return d && d == other.d; }
- bool needsDetach() const noexcept { return d->needsDetach(); }
- size_t detachCapacity(size_t newSize) const noexcept { return d->detachCapacity(newSize); }
- typename Data::ArrayOptions &flags() noexcept { return reinterpret_cast<typename Data::ArrayOptions &>(d->flags); }
- typename Data::ArrayOptions flags() const noexcept { return typename Data::ArrayOption(d->flags); }
- typename Data::ArrayOptions detachFlags() const noexcept { return d->detachFlags(); }
- typename Data::ArrayOptions cloneFlags() const noexcept { return d->cloneFlags(); }
+ bool needsDetach() const noexcept { return !d || d->needsDetach(); }
+ qsizetype detachCapacity(qsizetype newSize) const noexcept { return d ? d->detachCapacity(newSize) : newSize; }
+ const typename Data::ArrayOptions flags() const noexcept { return d ? d->flags : Data::ArrayOptionDefault; }
+ void setFlag(typename Data::ArrayOptions f) noexcept { Q_ASSERT(d); d->flags |= f; }
+ void clearFlag(typename Data::ArrayOptions f) noexcept { if (d) d->flags &= ~f; }
- void reallocate(uint alloc, typename Data::ArrayOptions options)
+ Data *d_ptr() noexcept { return d; }
+ void setBegin(T *begin) noexcept { ptr = begin; }
+
+ qsizetype freeSpaceAtBegin() const noexcept
{
- auto pair = Data::reallocateUnaligned(d, ptr, alloc, options);
- d = pair.first;
- ptr = pair.second;
+ if (d == nullptr)
+ return 0;
+ return this->ptr - Data::dataStart(d, alignof(typename Data::AlignmentDummy));
}
- Data *d_ptr() { return d; }
-private:
- Q_REQUIRED_RESULT QPair<Data *, T *> clone(QArrayData::ArrayOptions options) const
+ qsizetype freeSpaceAtEnd() const noexcept
{
- QPair<Data *, T *> pair = Data::allocate(d->detachCapacity(size),
- options);
- Q_CHECK_PTR(pair.first);
- QArrayDataPointer copy(pair.first, pair.second, 0);
- if (size)
- copy->copyAppend(begin(), end());
+ if (d == nullptr)
+ return 0;
+ return d->constAllocatedCapacity() - freeSpaceAtBegin() - this->size;
+ }
+
+ // allocate and grow. Ensure that at the minimum requiredSpace is available at the requested end
+ static QArrayDataPointer allocateGrow(const QArrayDataPointer &from, qsizetype n, QArrayData::GrowthPosition position)
+ {
+ // calculate new capacity. We keep the free capacity at the side that does not have to grow
+ // to avoid quadratic behavior with mixed append/prepend cases
+
+ // use qMax below, because constAllocatedCapacity() can be 0 when using fromRawData()
+ qsizetype minimalCapacity = qMax(from.size, from.constAllocatedCapacity()) + n;
+ // subtract the free space at the side we want to allocate. This ensures that the total size requested is
+ // the existing allocation at the other side + size + n.
+ minimalCapacity -= (position == QArrayData::GrowsAtEnd) ? from.freeSpaceAtEnd() : from.freeSpaceAtBegin();
+ qsizetype capacity = from.detachCapacity(minimalCapacity);
+ const bool grows = capacity > from.constAllocatedCapacity();
+ auto [header, dataPtr] = Data::allocate(capacity, grows ? QArrayData::Grow : QArrayData::KeepSize);
+ const bool valid = header != nullptr && dataPtr != nullptr;
+ if (!valid)
+ return QArrayDataPointer(header, dataPtr);
+
+ // Idea: * when growing backwards, adjust pointer to prepare free space at the beginning
+ // * when growing forward, adjust by the previous data pointer offset
+ dataPtr += (position == QArrayData::GrowsAtBeginning)
+ ? n + qMax(0, (header->alloc - from.size - n) / 2)
+ : from.freeSpaceAtBegin();
+ header->flags = from.flags();
+ return QArrayDataPointer(header, dataPtr);
+ }
+
+ friend bool operator==(const QArrayDataPointer &lhs, const QArrayDataPointer &rhs) noexcept
+ {
+ return lhs.data() == rhs.data() && lhs.size == rhs.size;
+ }
- pair.first = copy.d;
- copy.d = Data::sharedNull();
- return pair;
+ friend bool operator!=(const QArrayDataPointer &lhs, const QArrayDataPointer &rhs) noexcept
+ {
+ return lhs.data() != rhs.data() || lhs.size != rhs.size;
}
-protected:
Data *d;
T *ptr;
-
-public:
- int size;
+ qsizetype size;
};
template <class T>
-inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs) noexcept
+inline void swap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2) noexcept
{
- return lhs.data() == rhs.data() && lhs.size == rhs.size;
+ p1.swap(p2);
}
-template <class T>
-inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs) noexcept
-{
- return lhs.data() != rhs.data() || lhs.size != rhs.size;
-}
+////////////////////////////////////////////////////////////////////////////////
+// Q_ARRAY_LITERAL
-template <class T>
-inline void qSwap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2) noexcept
-{
- p1.swap(p2);
-}
+// The idea here is to place a (read-only) copy of header and array data in an
+// mmappable portion of the executable (typically, .rodata section).
+
+// Hide array inside a lambda
+#define Q_ARRAY_LITERAL(Type, ...) \
+ ([]() -> QArrayDataPointer<Type> { \
+ static Type const data[] = { __VA_ARGS__ }; \
+ return QArrayDataPointer<Type>::fromRawData(const_cast<Type *>(data), std::size(data)); \
+ }())
+/**/
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qatomicscopedvaluerollback.h b/src/corelib/tools/qatomicscopedvaluerollback.h
new file mode 100644
index 0000000000..8f653acba5
--- /dev/null
+++ b/src/corelib/tools/qatomicscopedvaluerollback.h
@@ -0,0 +1,127 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QATOMICSCOPEDVALUEROLLBACK_H
+#define QATOMICSCOPEDVALUEROLLBACK_H
+
+#include <QtCore/qassert.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/qtconfigmacros.h>
+
+#include <atomic>
+
+QT_BEGIN_NAMESPACE
+
+template <typename T>
+class QAtomicScopedValueRollback
+{
+ std::atomic<T> &m_atomic;
+ T m_value;
+ std::memory_order m_mo;
+
+ Q_DISABLE_COPY_MOVE(QAtomicScopedValueRollback)
+
+ static constexpr std::memory_order store_part(std::memory_order mo) noexcept
+ {
+ switch (mo) {
+ case std::memory_order_relaxed:
+ case std::memory_order_consume:
+ case std::memory_order_acquire: return std::memory_order_relaxed;
+ case std::memory_order_release:
+ case std::memory_order_acq_rel: return std::memory_order_release;
+ case std::memory_order_seq_cst: return std::memory_order_seq_cst;
+ }
+ // GCC 8.x does not treat __builtin_unreachable() as constexpr
+#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
+ // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
+ Q_UNREACHABLE();
+#endif
+ return std::memory_order_seq_cst;
+ }
+
+ static constexpr std::memory_order load_part(std::memory_order mo) noexcept
+ {
+ switch (mo) {
+ case std::memory_order_relaxed:
+ case std::memory_order_release: return std::memory_order_relaxed;
+ case std::memory_order_consume: return std::memory_order_consume;
+ case std::memory_order_acquire:
+ case std::memory_order_acq_rel: return std::memory_order_acquire;
+ case std::memory_order_seq_cst: return std::memory_order_seq_cst;
+ }
+ // GCC 8.x does not treat __builtin_unreachable() as constexpr
+#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
+ // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
+ Q_UNREACHABLE();
+#endif
+ return std::memory_order_seq_cst;
+ }
+public:
+ //
+ // std::atomic:
+ //
+ Q_NODISCARD_CTOR
+ explicit constexpr
+ QAtomicScopedValueRollback(std::atomic<T> &var,
+ std::memory_order mo = std::memory_order_seq_cst)
+ : m_atomic(var), m_value(var.load(load_part(mo))), m_mo(mo) {}
+
+ Q_NODISCARD_CTOR
+ explicit constexpr
+ QAtomicScopedValueRollback(std::atomic<T> &var, T value,
+ std::memory_order mo = std::memory_order_seq_cst)
+ : m_atomic(var), m_value(var.exchange(value, mo)), m_mo(mo) {}
+
+ //
+ // Q(Basic)AtomicInteger:
+ //
+ Q_NODISCARD_CTOR
+ explicit constexpr
+ QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var,
+ std::memory_order mo = std::memory_order_seq_cst)
+ : QAtomicScopedValueRollback(var._q_value, mo) {}
+
+ Q_NODISCARD_CTOR
+ explicit constexpr
+ QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var, T value,
+ std::memory_order mo = std::memory_order_seq_cst)
+ : QAtomicScopedValueRollback(var._q_value, value, mo) {}
+
+ //
+ // Q(Basic)AtomicPointer:
+ //
+ Q_NODISCARD_CTOR
+ explicit constexpr
+ QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var,
+ std::memory_order mo = std::memory_order_seq_cst)
+ : QAtomicScopedValueRollback(var._q_value, mo) {}
+
+ Q_NODISCARD_CTOR
+ explicit constexpr
+ QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var, T value,
+ std::memory_order mo = std::memory_order_seq_cst)
+ : QAtomicScopedValueRollback(var._q_value, value, mo) {}
+
+ ~QAtomicScopedValueRollback()
+ {
+ m_atomic.store(m_value, store_part(m_mo));
+ }
+
+ void commit()
+ {
+ m_value = m_atomic.load(load_part(m_mo));
+ }
+};
+
+template <typename T>
+QAtomicScopedValueRollback(QBasicAtomicPointer<T> &)
+ -> QAtomicScopedValueRollback<T*>;
+template <typename T>
+QAtomicScopedValueRollback(QBasicAtomicPointer<T> &, std::memory_order)
+ -> QAtomicScopedValueRollback<T*>;
+
+QT_END_NAMESPACE
+
+#endif // QATOMICASCOPEDVALUEROLLBACK_H
diff --git a/src/corelib/tools/qatomicscopedvaluerollback.qdoc b/src/corelib/tools/qatomicscopedvaluerollback.qdoc
new file mode 100644
index 0000000000..8c8161cb35
--- /dev/null
+++ b/src/corelib/tools/qatomicscopedvaluerollback.qdoc
@@ -0,0 +1,123 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAtomicScopedValueRollback
+ \inmodule QtCore
+ \brief Provides a QScopedValueRollback for atomic variables.
+ \ingroup misc
+ \ingroup tools
+ \since 6.7
+
+ The QAtomicScopedValueRollback class resets an atomic variable to its
+ prior value on destruction. It can be used to revert state when an
+ exception is thrown without the need to write try-catch blocks.
+
+ It can also be used to manage variables that are temporarily set, such as
+ reentrancy guards. By using this class, the variable will be reset whether the
+ function is exited normally, exited early by a return statement, or exited by
+ an exception.
+
+ The class works on std::atomic and the Qt atomic classes: QBasicAtomicInteger,
+ \l QAtomicInteger, \l QAtomicInt, QBasicAtomicPointer and \l QAtomicPointer.
+
+ \target Memory Order
+ The memory accesses to the atomic variable \a var are specified using the value
+ of \c mo. The memory order follows this mapping:
+ \br
+ \list
+ \li When writing to the atomic variable:
+ \list
+ \li An acquire ordering performs a relaxed operation instead.
+ \li A hybrid acquire-release ordering performs a release operation instead.
+ \endlist
+ \li When reading from the atomic variable:
+ \list
+ \li A release ordering performs a relaxed operation instead.
+ \li A consume ordering performs a consume operation.
+ \li A hybrid acquire-release ordering performs an acquire operation instead.
+ \endlist
+ \endlist
+ \br
+ Otherwise, the default memory order is sequential consistent ordering.
+
+ \note You should never name the template arguments explicitly, but exclusively
+ use Class Template Argument Deduction (CTAD) and let the compiler pick the
+ template argument.
+
+ \note There is a chance that other threads modify the variable too, which means
+ you may lose updates performed by other threads between the call to the
+ QAtomicScopedValueRollback constructor and commit() or between commit() and the
+ destructor.
+
+ \sa QScopedValueRollback
+*/
+
+/*!
+ \fn template <typename T> QAtomicScopedValueRollback<T>::QAtomicScopedValueRollback(std::atomic<T> &var, std::memory_order mo = std::memory_order_seq_cst)
+ \fn template <typename T> QAtomicScopedValueRollback<T>::QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var, std::memory_order mo = std::memory_order_seq_cst)
+ \fn template <typename T> QAtomicScopedValueRollback<T>::QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var, std::memory_order mo = std::memory_order_seq_cst)
+
+ Records the value of \a var in order to restore it on destruction.
+
+ This is equivalent to:
+ \code
+ T old_value = var.load(mo);
+ // And in the destructor: var.store(old_value, mo);
+ \endcode
+ The \c{mo} adjustment for the load is described in the \l {Memory Order} section.
+*/
+
+/*!
+ \fn template <typename T> QAtomicScopedValueRollback<T>::QAtomicScopedValueRollback(std::atomic<T> &var, T value, std::memory_order mo = std::memory_order_seq_cst)
+ \fn template <typename T> QAtomicScopedValueRollback<T>::QAtomicScopedValueRollback(QBasicAtomicInteger<T> &var, T value, std::memory_order mo = std::memory_order_seq_cst)
+ \fn template <typename T> QAtomicScopedValueRollback<T>::QAtomicScopedValueRollback(QBasicAtomicPointer<std::remove_pointer_t<T>> &var, T value, std::memory_order mo = std::memory_order_seq_cst)
+
+ Assigns \a value to \a var and stores the prior value of \a var internally for
+ reverting on destruction.
+
+ This is equivalent to:
+ \code
+ T old_value = var.exchange(new_value, mo);
+ // And in the destructor: var.store(old_value, mo);
+ \endcode
+*/
+
+/*!
+ \fn template <typename T> QAtomicScopedValueRollback<T>::~QAtomicScopedValueRollback()
+
+ Restores the stored value that was current at construction time, or
+ at the last call to commit(), to the managed variable.
+
+ This is equivalent to:
+ \code
+ // In the constructor: T old_value = var.load(mo);
+ // or: T old_value = exchange(new_value, mo);
+ var.store(old_value, mo);
+ \endcode
+ Where \c{mo} is the same as the one initially passed to the constructor.
+ See \l{Memory Order} for the meaning of \c{mo}.
+*/
+
+/*!
+ \fn template <typename T> void QAtomicScopedValueRollback<T>::commit()
+
+ Updates the stored value to the managed variable's current value, loaded
+ with the same memory order as on construction.
+
+ This updated value will be restored on destruction, instead of the original
+ prior value.
+
+ This is equivalent to:
+ \code
+ // Given constructor: T old_value = var.load(mo);
+ old_value = var.load(mo); // referesh it
+ // And, in the destructor: var.store(old_value, mo);
+ \endcode
+ Where \c{mo} is the same as the one initially passed to the constructor.
+ See \l{Memory Order} for the meaning of \c{mo}.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index 9bcd6a9306..e4276d383d 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -1,48 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbitarray.h"
#include <qalgorithms.h>
#include <qdatastream.h>
#include <qdebug.h>
#include <qendian.h>
+
+#include <limits>
+
#include <string.h>
QT_BEGIN_NAMESPACE
@@ -56,6 +23,8 @@ QT_BEGIN_NAMESPACE
\ingroup shared
\reentrant
+ \compares equality
+
A QBitArray is an array that gives access to individual bits and
provides operators (\l{operator&()}{AND}, \l{operator|()}{OR},
\l{operator^()}{XOR}, and \l{operator~()}{NOT}) that work on
@@ -110,6 +79,7 @@ QT_BEGIN_NAMESPACE
\sa QByteArray, QList
*/
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*!
\fn QBitArray::QBitArray(QBitArray &&other)
@@ -118,6 +88,7 @@ QT_BEGIN_NAMESPACE
\since 5.2
*/
+#endif
/*! \fn QBitArray::QBitArray()
@@ -137,35 +108,52 @@ QT_BEGIN_NAMESPACE
* *d.constData() is the QByteArray's terminating NUL (0) byte.
*
* This allows for fast calculation of the bit array size:
- * inline int size() const { return (d.size() << 3) - *d.constData(); }
+ * inline qsizetype size() const { return (d.size() << 3) - *d.constData(); }
*/
+static constexpr qsizetype storage_size(qsizetype size)
+{
+ // avoid overflow when adding 7, by doing the arithmetic in unsigned space:
+ return qsizetype((size_t(size) + 7) / 8);
+}
+
+static constexpr qsizetype allocation_size(qsizetype size)
+{
+ return size <= 0 ? 0 : storage_size(size) + 1;
+}
+
+static void adjust_head_and_tail(char *data, qsizetype storageSize, qsizetype logicalSize)
+{
+ quint8 *c = reinterpret_cast<quint8 *>(data);
+ // store the difference between storage and logical size in d[0]:
+ *c = quint8(size_t(storageSize) * 8 - logicalSize);
+ // reset unallocated bits to 0:
+ if (logicalSize & 7)
+ *(c + 1 + logicalSize / 8) &= (1 << (logicalSize & 7)) - 1;
+}
+
/*!
Constructs a bit array containing \a size bits. The bits are
initialized with \a value, which defaults to false (0).
*/
-QBitArray::QBitArray(int size, bool value)
- : d(size <= 0 ? 0 : 1 + (size + 7)/8, Qt::Uninitialized)
+QBitArray::QBitArray(qsizetype size, bool value)
+ : d(allocation_size(size), value ? 0xFF : 0x00)
{
Q_ASSERT_X(size >= 0, "QBitArray::QBitArray", "Size must be greater than or equal to 0.");
if (size <= 0)
return;
- uchar* c = reinterpret_cast<uchar*>(d.data());
- memset(c + 1, value ? 0xff : 0, d.size() - 1);
- *c = d.size()*8 - size;
- if (value && size && size & 7)
- *(c+1+size/8) &= (1 << (size & 7)) - 1;
+ adjust_head_and_tail(d.data(), d.size(), size);
}
-/*! \fn int QBitArray::size() const
+/*! \fn qsizetype QBitArray::size() const
Returns the number of bits stored in the bit array.
\sa resize()
*/
-/*! \fn int QBitArray::count() const
+/*! \fn qsizetype QBitArray::count() const
Same as size().
*/
@@ -175,9 +163,9 @@ QBitArray::QBitArray(int size, bool value)
1-bits stored in the bit array; otherwise the number
of 0-bits is returned.
*/
-int QBitArray::count(bool on) const
+qsizetype QBitArray::count(bool on) const
{
- int numBits = 0;
+ qsizetype numBits = 0;
const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1;
// the loops below will try to read from *end
@@ -187,20 +175,20 @@ int QBitArray::count(bool on) const
while (bits + 7 <= end) {
quint64 v = qFromUnaligned<quint64>(bits);
bits += 8;
- numBits += int(qPopulationCount(v));
+ numBits += qsizetype(qPopulationCount(v));
}
if (bits + 3 <= end) {
quint32 v = qFromUnaligned<quint32>(bits);
bits += 4;
- numBits += int(qPopulationCount(v));
+ numBits += qsizetype(qPopulationCount(v));
}
if (bits + 1 < end) {
quint16 v = qFromUnaligned<quint16>(bits);
bits += 2;
- numBits += int(qPopulationCount(v));
+ numBits += qsizetype(qPopulationCount(v));
}
if (bits < end)
- numBits += int(qPopulationCount(bits[0]));
+ numBits += qsizetype(qPopulationCount(bits[0]));
return on ? numBits : size() - numBits;
}
@@ -217,19 +205,14 @@ int QBitArray::count(bool on) const
\sa size()
*/
-void QBitArray::resize(int size)
+void QBitArray::resize(qsizetype size)
{
- if (!size) {
+ Q_ASSERT_X(size >= 0, "QBitArray::resize", "Size must be greater than or equal to 0.");
+ if (size <= 0) {
d.resize(0);
} else {
- int s = d.size();
- d.resize(1 + (size+7)/8);
- uchar* c = reinterpret_cast<uchar*>(d.data());
- if (size > (s << 3))
- memset(c + s, 0, d.size() - s);
- else if (size & 7)
- *(c+1+size/8) &= (1 << (size & 7)) - 1;
- *c = d.size()*8 - size;
+ d.resize(allocation_size(size), 0x00);
+ adjust_head_and_tail(d.data(), d.size(), size);
}
}
@@ -256,7 +239,7 @@ void QBitArray::resize(int size)
\sa isEmpty()
*/
-/*! \fn bool QBitArray::fill(bool value, int size = -1)
+/*! \fn bool QBitArray::fill(bool value, qsizetype size = -1)
Sets every bit in the bit array to \a value, returning true if successful;
otherwise returns \c false. If \a size is different from -1 (the default),
@@ -285,15 +268,15 @@ void QBitArray::resize(int size)
\snippet code/src_corelib_tools_qbitarray.cpp 15
*/
-void QBitArray::fill(bool value, int begin, int end)
+void QBitArray::fill(bool value, qsizetype begin, qsizetype end)
{
while (begin < end && begin & 0x7)
setBit(begin++, value);
- int len = end - begin;
+ qsizetype len = end - begin;
if (len <= 0)
return;
- int s = len & ~0x7;
- uchar *c = reinterpret_cast<uchar*>(d.data());
+ qsizetype s = len & ~qsizetype(0x7);
+ uchar *c = reinterpret_cast<uchar *>(d.data());
memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3);
begin += s;
while (begin < end)
@@ -325,20 +308,15 @@ void QBitArray::fill(bool value, int begin, int end)
*/
QBitArray QBitArray::fromBits(const char *data, qsizetype size)
{
+ Q_ASSERT_X(size >= 0, "QBitArray::fromBits", "Size must be greater than or equal to 0.");
QBitArray result;
- if (size == 0)
+ if (size <= 0)
return result;
- qsizetype nbytes = (size + 7) / 8;
-
- result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
- char *bits = result.d.data();
- memcpy(bits + 1, data, nbytes);
-
- // clear any unused bits from the last byte
- if (size & 7)
- bits[nbytes] &= 0xffU >> (8 - (size & 7));
- *bits = result.d.size() * 8 - size;
+ auto &d = result.d;
+ d.resize(allocation_size(size));
+ memcpy(d.data() + 1, data, d.size() - 1);
+ adjust_head_and_tail(d.data(), d.size(), size);
return result;
}
@@ -391,7 +369,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa resize(), isEmpty()
*/
-/*! \fn void QBitArray::truncate(int pos)
+/*! \fn void QBitArray::truncate(qsizetype pos)
Truncates the bit array at index position \a pos.
@@ -400,7 +378,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa resize()
*/
-/*! \fn bool QBitArray::toggleBit(int i)
+/*! \fn bool QBitArray::toggleBit(qsizetype i)
Inverts the value of the bit at index position \a i, returning the
previous value of that bit as either true (if it was set) or false (if
@@ -415,7 +393,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa setBit(), clearBit()
*/
-/*! \fn bool QBitArray::testBit(int i) const
+/*! \fn bool QBitArray::testBit(qsizetype i) const
Returns \c true if the bit at index position \a i is 1; otherwise
returns \c false.
@@ -426,7 +404,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa setBit(), clearBit()
*/
-/*! \fn bool QBitArray::setBit(int i)
+/*! \fn bool QBitArray::setBit(qsizetype i)
Sets the bit at index position \a i to 1.
@@ -436,14 +414,14 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa clearBit(), toggleBit()
*/
-/*! \fn void QBitArray::setBit(int i, bool value)
+/*! \fn void QBitArray::setBit(qsizetype i, bool value)
\overload
Sets the bit at index position \a i to \a value.
*/
-/*! \fn void QBitArray::clearBit(int i)
+/*! \fn void QBitArray::clearBit(qsizetype i)
Sets the bit at index position \a i to 0.
@@ -453,7 +431,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa setBit(), toggleBit()
*/
-/*! \fn bool QBitArray::at(int i) const
+/*! \fn bool QBitArray::at(qsizetype i) const
Returns the value of the bit at index position \a i.
@@ -463,7 +441,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa operator[]()
*/
-/*! \fn QBitRef QBitArray::operator[](int i)
+/*! \fn QBitRef QBitArray::operator[](qsizetype i)
Returns the bit at index position \a i as a modifiable reference.
@@ -484,22 +462,13 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa at(), testBit(), setBit(), clearBit()
*/
-/*! \fn bool QBitArray::operator[](int i) const
+/*! \fn bool QBitArray::operator[](qsizetype i) const
\overload
*/
-/*! \fn QBitRef QBitArray::operator[](uint i)
-
- \overload
-*/
-
-/*! \fn bool QBitArray::operator[](uint i) const
-
- \overload
-*/
-
-/*! \fn QBitArray::QBitArray(const QBitArray &other)
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+/*! \fn QBitArray::QBitArray(const QBitArray &other) noexcept
Constructs a copy of \a other.
@@ -511,7 +480,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa operator=()
*/
-/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other)
+/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other) noexcept
Assigns \a other to this bit array and returns a reference to
this bit array.
@@ -523,6 +492,7 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
Moves \a other to this bit array and returns a reference to
this bit array.
*/
+#endif // Qt 6
/*! \fn void QBitArray::swap(QBitArray &other)
\since 4.8
@@ -531,23 +501,145 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
fast and never fails.
*/
-/*! \fn bool QBitArray::operator==(const QBitArray &other) const
+/*! \fn bool QBitArray::operator==(const QBitArray &lhs, const QBitArray &rhs)
- Returns \c true if \a other is equal to this bit array; otherwise
+ Returns \c true if \a lhs is equal to \a rhs bit array; otherwise
returns \c false.
\sa operator!=()
*/
-/*! \fn bool QBitArray::operator!=(const QBitArray &other) const
+/*! \fn bool QBitArray::operator!=(const QBitArray &lhs, const QBitArray &rhs)
- Returns \c true if \a other is not equal to this bit array;
+ Returns \c true if \a lhs is not equal to \a rhs bit array;
otherwise returns \c false.
\sa operator==()
*/
+// Returns a new QBitArray that has the same size as the bigger of \a a1 and
+// \a a2, but whose contents are uninitialized.
+static QBitArray sizedForOverwrite(const QBitArray &a1, const QBitArray &a2)
+{
+ QBitArray result;
+ const QByteArrayData &d1 = a1.data_ptr();
+ const QByteArrayData &d2 = a2.data_ptr();
+ qsizetype n1 = d1.size;
+ qsizetype n2 = d2.size;
+ qsizetype n = qMax(n1, n2);
+
+ QByteArrayData bytes(n, n);
+
+ // initialize the count of bits in the last byte (see construction note)
+ if (n1 > n2)
+ *bytes.ptr = *d1.ptr;
+ else if (n2 > n1)
+ *bytes.ptr = *d2.ptr;
+ else if (n1) // n1 == n2
+ *bytes.ptr = qMin(*d1.ptr, *d2.ptr);
+
+ result.data_ptr() = std::move(bytes);
+ return result;
+}
+
+template <typename BitwiseOp> static Q_NEVER_INLINE
+QBitArray &performBitwiseOperationHelper(QBitArray &out, const QBitArray &a1,
+ const QBitArray &a2, BitwiseOp op)
+{
+ const QByteArrayData &d1 = a1.data_ptr();
+ const QByteArrayData &d2 = a2.data_ptr();
+
+ // Sizes in bytes (including the initial bit difference counter)
+ qsizetype n1 = d1.size;
+ qsizetype n2 = d2.size;
+ Q_ASSERT(out.data_ptr().size == qMax(n1, n2));
+ Q_ASSERT(out.data_ptr().size == 0 || !out.data_ptr().needsDetach());
+
+ // Bypass QByteArray's emptiness verification; we won't dereference
+ // these pointers if their size is zero.
+ auto dst = reinterpret_cast<uchar *>(out.data_ptr().data());
+ auto p1 = reinterpret_cast<const uchar *>(d1.data());
+ auto p2 = reinterpret_cast<const uchar *>(d2.data());
+
+ // Main: perform the operation in the range where both arrays have data
+ if (n1 < n2) {
+ std::swap(n1, n2);
+ std::swap(p1, p2);
+ }
+ for (qsizetype i = 1; i < n2; ++i)
+ dst[i] = op(p1[i], p2[i]);
+
+ // Tail: operate as if both arrays had the same data by padding zeroes to
+ // the end of the shorter of the two (for std::bit_or and std::bit_xor, this is
+ // a memmove; for std::bit_and, it's memset to 0).
+ for (qsizetype i = qMax(n2, qsizetype(1)); i < n1; ++i)
+ dst[i] = op(p1[i], uchar(0));
+
+ return out;
+}
+
+template <typename BitwiseOp> static Q_NEVER_INLINE
+QBitArray &performBitwiseOperationInCopy(QBitArray &self, const QBitArray &other, BitwiseOp op)
+{
+ QBitArray tmp(std::move(self));
+ self = sizedForOverwrite(tmp, other);
+ return performBitwiseOperationHelper(self, tmp, other, op);
+}
+
+template <typename BitwiseOp> static Q_NEVER_INLINE
+QBitArray &performBitwiseOperationInPlace(QBitArray &self, const QBitArray &other, BitwiseOp op)
+{
+ if (self.size() < other.size())
+ self.resize(other.size());
+ return performBitwiseOperationHelper(self, self, other, op);
+}
+
+template <typename BitwiseOp> static
+QBitArray &performBitwiseOperation(QBitArray &self, const QBitArray &other, BitwiseOp op)
+{
+ if (self.data_ptr().needsDetach())
+ return performBitwiseOperationInCopy(self, other, op);
+ return performBitwiseOperationInPlace(self, other, op);
+}
+
+// SCARY helper
+enum { InCopy, InPlace };
+static auto prepareForBitwiseOperation(QBitArray &self, QBitArray &other)
+{
+ QByteArrayData &d1 = self.data_ptr();
+ QByteArrayData &d2 = other.data_ptr();
+ bool detached1 = !d1.needsDetach();
+ bool detached2 = !d2.needsDetach();
+ if (!detached1 && !detached2)
+ return InCopy;
+
+ // at least one of the two is detached, we'll reuse its buffer
+ bool swap = false;
+ if (detached1 && detached2) {
+ // both are detached, so choose the larger of the two
+ swap = d1.allocatedCapacity() < d2.allocatedCapacity();
+ } else if (detached2) {
+ // we can re-use other's buffer but not self's, so swap the two
+ swap = true;
+ }
+ if (swap)
+ self.swap(other);
+ return InPlace;
+}
+
+template <typename BitwiseOp> static
+QBitArray &performBitwiseOperation(QBitArray &self, QBitArray &other, BitwiseOp op)
+{
+ auto choice = prepareForBitwiseOperation(self, other);
+ if (choice == InCopy)
+ return performBitwiseOperationInCopy(self, other, std::move(op));
+ return performBitwiseOperationInPlace(self, other, std::move(op));
+}
+
/*!
+ \fn QBitArray &QBitArray::operator&=(const QBitArray &other)
+ \fn QBitArray &QBitArray::operator&=(QBitArray &&other)
+
Performs the AND operation between all bits in this bit array and
\a other. Assigns the result to this bit array, and returns a
reference to it.
@@ -562,21 +654,20 @@ quint32 QBitArray::toUInt32(QSysInfo::Endian endianness, bool *ok) const noexcep
\sa operator&(), operator|=(), operator^=(), operator~()
*/
+QBitArray &QBitArray::operator&=(QBitArray &&other)
+{
+ return performBitwiseOperation(*this, other, std::bit_and<uchar>());
+}
+
QBitArray &QBitArray::operator&=(const QBitArray &other)
{
- resize(qMax(size(), other.size()));
- uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
- const uchar *a2 = reinterpret_cast<const uchar*>(other.d.constData()) + 1;
- int n = other.d.size() -1 ;
- int p = d.size() - 1 - n;
- while (n-- > 0)
- *a1++ &= *a2++;
- while (p-- > 0)
- *a1++ = 0;
- return *this;
+ return performBitwiseOperation(*this, other, std::bit_and<uchar>());
}
/*!
+ \fn QBitArray &QBitArray::operator|=(const QBitArray &other)
+ \fn QBitArray &QBitArray::operator|=(QBitArray &&other)
+
Performs the OR operation between all bits in this bit array and
\a other. Assigns the result to this bit array, and returns a
reference to it.
@@ -591,18 +682,20 @@ QBitArray &QBitArray::operator&=(const QBitArray &other)
\sa operator|(), operator&=(), operator^=(), operator~()
*/
+QBitArray &QBitArray::operator|=(QBitArray &&other)
+{
+ return performBitwiseOperation(*this, other, std::bit_or<uchar>());
+}
+
QBitArray &QBitArray::operator|=(const QBitArray &other)
{
- resize(qMax(size(), other.size()));
- uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
- const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
- int n = other.d.size() - 1;
- while (n-- > 0)
- *a1++ |= *a2++;
- return *this;
+ return performBitwiseOperation(*this, other, std::bit_or<uchar>());
}
/*!
+ \fn QBitArray &QBitArray::operator^=(const QBitArray &other)
+ \fn QBitArray &QBitArray::operator^=(QBitArray &&other)
+
Performs the XOR operation between all bits in this bit array and
\a other. Assigns the result to this bit array, and returns a
reference to it.
@@ -617,20 +710,20 @@ QBitArray &QBitArray::operator|=(const QBitArray &other)
\sa operator^(), operator&=(), operator|=(), operator~()
*/
+QBitArray &QBitArray::operator^=(QBitArray &&other)
+{
+ return performBitwiseOperation(*this, other, std::bit_xor<uchar>());
+}
+
QBitArray &QBitArray::operator^=(const QBitArray &other)
{
- resize(qMax(size(), other.size()));
- uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1;
- const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1;
- int n = other.d.size() - 1;
- while (n-- > 0)
- *a1++ ^= *a2++;
- return *this;
+ return performBitwiseOperation(*this, other, std::bit_xor<uchar>());
}
/*!
- Returns a bit array that contains the inverted bits of this bit
- array.
+ \fn QBitArray QBitArray::operator~(QBitArray a)
+ Returns a bit array that contains the inverted bits of the bit
+ array \a a.
Example:
\snippet code/src_corelib_tools_qbitarray.cpp 11
@@ -638,24 +731,42 @@ QBitArray &QBitArray::operator^=(const QBitArray &other)
\sa operator&(), operator|(), operator^()
*/
-QBitArray QBitArray::operator~() const
+Q_NEVER_INLINE QBitArray QBitArray::inverted_inplace() &&
{
- int sz = size();
- QBitArray a(sz);
- const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1;
- uchar *a2 = reinterpret_cast<uchar*>(a.d.data()) + 1;
- int n = d.size() - 1;
-
- while (n-- > 0)
- *a2++ = ~*a1++;
-
- if (sz && sz%8)
- *(a2-1) &= (1 << (sz%8)) - 1;
- return a;
+ qsizetype n = d.size();
+ uchar *dst = reinterpret_cast<uchar *>(data_ptr().data());
+ const uchar *src = dst;
+ QBitArray result([&] {
+ if (d.isDetached() || n == 0)
+ return std::move(d.data_ptr()); // invert in-place
+
+ QByteArrayData tmp(n, n);
+ dst = reinterpret_cast<uchar *>(tmp.data());
+ return tmp;
+ }());
+
+ uchar bitdiff = 8;
+ if (n)
+ bitdiff = dst[0] = src[0]; // copy the count of bits in the last byte
+
+ for (qsizetype i = 1; i < n; ++i)
+ dst[i] = ~src[i];
+
+ if (int tailCount = 16 - bitdiff; tailCount != 8) {
+ // zero the bits beyond our size in the last byte
+ Q_ASSERT(n > 1);
+ uchar tailMask = (1U << tailCount) - 1;
+ dst[n - 1] &= tailMask;
+ }
+
+ return result;
}
/*!
- \relates QBitArray
+ \fn QBitArray QBitArray::operator&(const QBitArray &a1, const QBitArray &a2)
+ \fn QBitArray QBitArray::operator&(QBitArray &&a1, const QBitArray &a2)
+ \fn QBitArray QBitArray::operator&(const QBitArray &a1, QBitArray &&a2)
+ \fn QBitArray QBitArray::operator&(QBitArray &&a1, QBitArray &&a2)
Returns a bit array that is the AND of the bit arrays \a a1 and \a
a2.
@@ -672,13 +783,16 @@ QBitArray QBitArray::operator~() const
QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
{
- QBitArray tmp = a1;
- tmp &= a2;
+ QBitArray tmp = sizedForOverwrite(a1, a2);
+ performBitwiseOperationHelper(tmp, a1, a2, std::bit_and<uchar>());
return tmp;
}
/*!
- \relates QBitArray
+ \fn QBitArray QBitArray::operator|(const QBitArray &a1, const QBitArray &a2)
+ \fn QBitArray QBitArray::operator|(QBitArray &&a1, const QBitArray &a2)
+ \fn QBitArray QBitArray::operator|(const QBitArray &a1, QBitArray &&a2)
+ \fn QBitArray QBitArray::operator|(QBitArray &&a1, QBitArray &&a2)
Returns a bit array that is the OR of the bit arrays \a a1 and \a
a2.
@@ -695,13 +809,16 @@ QBitArray operator&(const QBitArray &a1, const QBitArray &a2)
QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
{
- QBitArray tmp = a1;
- tmp |= a2;
+ QBitArray tmp = sizedForOverwrite(a1, a2);
+ performBitwiseOperationHelper(tmp, a1, a2, std::bit_or<uchar>());
return tmp;
}
/*!
- \relates QBitArray
+ \fn QBitArray QBitArray::operator^(const QBitArray &a1, const QBitArray &a2)
+ \fn QBitArray QBitArray::operator^(QBitArray &&a1, const QBitArray &a2)
+ \fn QBitArray QBitArray::operator^(const QBitArray &a1, QBitArray &&a2)
+ \fn QBitArray QBitArray::operator^(QBitArray &&a1, QBitArray &&a2)
Returns a bit array that is the XOR of the bit arrays \a a1 and \a
a2.
@@ -718,8 +835,8 @@ QBitArray operator|(const QBitArray &a1, const QBitArray &a2)
QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
{
- QBitArray tmp = a1;
- tmp ^= a2;
+ QBitArray tmp = sizedForOverwrite(a1, a2);
+ performBitwiseOperationHelper(tmp, a1, a2, std::bit_xor<uchar>());
return tmp;
}
@@ -735,7 +852,7 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
It is not for use in any other context.
*/
-/*! \fn QBitRef::QBitRef (QBitArray& a, int i)
+/*! \fn QBitRef::QBitRef (QBitArray& a, qsizetype i)
Constructs a reference to element \a i in the QBitArray \a a.
This is what QBitArray::operator[] constructs its return value
@@ -764,7 +881,6 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
Sets the value referenced by the QBitRef to \a v.
*/
-
/*****************************************************************************
QBitArray stream functions
*****************************************************************************/
@@ -780,10 +896,18 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
{
- quint32 len = ba.size();
- out << len;
+ const qsizetype len = ba.size();
+ if (out.version() < QDataStream::Qt_6_0) {
+ if (Q_UNLIKELY(len > qsizetype{(std::numeric_limits<qint32>::max)()})) {
+ out.setStatus(QDataStream::Status::SizeLimitExceeded);
+ return out;
+ }
+ out << quint32(len);
+ } else {
+ out << quint64(len);
+ }
if (len > 0)
- out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1);
+ out.writeRawData(ba.d.data() + 1, ba.d.size() - 1);
return out;
}
@@ -798,19 +922,35 @@ QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
QDataStream &operator>>(QDataStream &in, QBitArray &ba)
{
ba.clear();
- quint32 len;
- in >> len;
+ qsizetype len;
+ if (in.version() < QDataStream::Qt_6_0) {
+ quint32 tmp;
+ in >> tmp;
+ if (Q_UNLIKELY(tmp > quint32((std::numeric_limits<qint32>::max)()))) {
+ in.setStatus(QDataStream::ReadCorruptData);
+ return in;
+ }
+ len = tmp;
+ } else {
+ quint64 tmp;
+ in >> tmp;
+ if (Q_UNLIKELY(tmp > quint64((std::numeric_limits<qsizetype>::max)()))) {
+ in.setStatus(QDataStream::Status::SizeLimitExceeded);
+ return in;
+ }
+ len = tmp;
+ }
if (len == 0) {
ba.clear();
return in;
}
- const quint32 Step = 8 * 1024 * 1024;
- quint32 totalBytes = (len + 7) / 8;
- quint32 allocated = 0;
+ const qsizetype Step = 8 * 1024 * 1024;
+ const qsizetype totalBytes = storage_size(len);
+ qsizetype allocated = 0;
while (allocated < totalBytes) {
- int blockSize = qMin(Step, totalBytes - allocated);
+ qsizetype blockSize = qMin(Step, totalBytes - allocated);
ba.d.resize(allocated + blockSize + 1);
if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) {
ba.clear();
@@ -820,14 +960,13 @@ QDataStream &operator>>(QDataStream &in, QBitArray &ba)
allocated += blockSize;
}
- int paddingMask = ~((0x1 << (len & 0x7)) - 1);
- if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) {
+ const auto fromStream = ba.d.back();
+ adjust_head_and_tail(ba.d.data(), ba.d.size(), len);
+ if (ba.d.back() != fromStream) {
ba.clear();
in.setStatus(QDataStream::ReadCorruptData);
return in;
}
-
- *ba.d.data() = ba.d.size() * 8 - len;
return in;
}
#endif // QT_NO_DATASTREAM
@@ -837,7 +976,7 @@ QDebug operator<<(QDebug dbg, const QBitArray &array)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "QBitArray(";
- for (int i = 0; i < array.size();) {
+ for (qsizetype i = 0; i < array.size();) {
if (array.testBit(i))
dbg << '1';
else
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
index e8ef032c24..b9c36b5320 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBITARRAY_H
#define QBITARRAY_H
@@ -44,63 +8,124 @@
QT_BEGIN_NAMESPACE
-
class QBitRef;
class Q_CORE_EXPORT QBitArray
{
+ Q_CORE_EXPORT friend QBitArray operator&(const QBitArray &a1, const QBitArray &a2);
+ friend QBitArray operator&(QBitArray &&a1, const QBitArray &a2)
+ { return a1 &= a2; }
+ friend QBitArray operator&(const QBitArray &a1, QBitArray &&a2)
+ { return a2 &= a1; }
+ friend QBitArray operator&(QBitArray &&a1, QBitArray &&a2)
+ { return a1 &= a2; }
+
+ Q_CORE_EXPORT friend QBitArray operator|(const QBitArray &a1, const QBitArray &a2);
+ friend QBitArray operator|(QBitArray &&a1, const QBitArray &a2)
+ { return a1 |= a2; }
+ friend QBitArray operator|(const QBitArray &a1, QBitArray &&a2)
+ { return a2 |= a1; }
+ friend QBitArray operator|(QBitArray &&a1, QBitArray &&a2)
+ { return a1 |= a2; }
+
+ Q_CORE_EXPORT friend QBitArray operator^(const QBitArray &a1, const QBitArray &a2);
+ friend QBitArray operator^(QBitArray &&a1, const QBitArray &a2)
+ { return a1 ^= a2; }
+ friend QBitArray operator^(const QBitArray &a1, QBitArray &&a2)
+ { return a2 ^= a1; }
+ friend QBitArray operator^(QBitArray &&a1, QBitArray &&a2)
+ { return a1 ^= a2; }
+
+#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
+#endif
friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept;
+ friend QBitArray operator~(QBitArray a)
+ { return std::move(a).inverted_inplace(); }
QByteArray d;
+ QBitArray(QByteArrayData &&dd) : d(std::move(dd)) {}
+
+ template <typename BitArray> static auto bitLocation(BitArray &ba, qsizetype i)
+ {
+ Q_ASSERT(size_t(i) < size_t(ba.size()));
+ struct R {
+ decltype(ba.d[1]) byte;
+ uchar bitMask;
+ };
+ qsizetype byteIdx = i >> 3;
+ qsizetype bitIdx = i & 7;
+ return R{ ba.d[1 + byteIdx], uchar(1U << bitIdx) };
+ }
+
+ QBitArray inverted_inplace() &&;
+
public:
inline QBitArray() noexcept {}
- explicit QBitArray(int size, bool val = false);
- QBitArray(const QBitArray &other) : d(other.d) {}
- inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; }
+ explicit QBitArray(qsizetype size, bool val = false);
+ // Rule Of Zero applies
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QBitArray(const QBitArray &other) noexcept : d(other.d) {}
+ inline QBitArray &operator=(const QBitArray &other) noexcept { d = other.d; return *this; }
inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {}
- inline QBitArray &operator=(QBitArray &&other) noexcept
- { qSwap(d, other.d); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBitArray)
+#endif // Qt 6
- inline void swap(QBitArray &other) noexcept { qSwap(d, other.d); }
+ void swap(QBitArray &other) noexcept { d.swap(other.d); }
- inline int size() const { return (d.size() << 3) - *d.constData(); }
- inline int count() const { return (d.size() << 3) - *d.constData(); }
- int count(bool on) const;
+ qsizetype size() const { return qsizetype((size_t(d.size()) << 3) - *d.constData()); }
+ qsizetype count() const { return size(); }
+ qsizetype count(bool on) const;
inline bool isEmpty() const { return d.isEmpty(); }
inline bool isNull() const { return d.isNull(); }
- void resize(int size);
+ void resize(qsizetype size);
inline void detach() { d.detach(); }
inline bool isDetached() const { return d.isDetached(); }
inline void clear() { d.clear(); }
- bool testBit(int i) const;
- void setBit(int i);
- void setBit(int i, bool val);
- void clearBit(int i);
- bool toggleBit(int i);
-
- bool at(int i) const;
- QBitRef operator[](int i);
- bool operator[](int i) const;
- QBitRef operator[](uint i);
- bool operator[](uint i) const;
-
- QBitArray& operator&=(const QBitArray &);
- QBitArray& operator|=(const QBitArray &);
- QBitArray& operator^=(const QBitArray &);
- QBitArray operator~() const;
+ bool testBit(qsizetype i) const
+ { auto r = bitLocation(*this, i); return r.byte & r.bitMask; }
+ void setBit(qsizetype i)
+ { auto r = bitLocation(*this, i); r.byte |= r.bitMask; }
+ void setBit(qsizetype i, bool val)
+ { if (val) setBit(i); else clearBit(i); }
+ void clearBit(qsizetype i)
+ { auto r = bitLocation(*this, i); r.byte &= ~r.bitMask; }
+ bool toggleBit(qsizetype i)
+ {
+ auto r = bitLocation(*this, i);
+ bool cl = r.byte & r.bitMask;
+ r.byte ^= r.bitMask;
+ return cl;
+ }
+
+ bool at(qsizetype i) const { return testBit(i); }
+ inline QBitRef operator[](qsizetype i);
+ bool operator[](qsizetype i) const { return testBit(i); }
+
+ QBitArray &operator&=(QBitArray &&);
+ QBitArray &operator|=(QBitArray &&);
+ QBitArray &operator^=(QBitArray &&);
+ QBitArray &operator&=(const QBitArray &);
+ QBitArray &operator|=(const QBitArray &);
+ QBitArray &operator^=(const QBitArray &);
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ QBitArray operator~() const;
+#endif
- inline bool operator==(const QBitArray& other) const { return d == other.d; }
- inline bool operator!=(const QBitArray& other) const { return d != other.d; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QBitArray &other) const { return comparesEqual(d, other.d); }
+ inline bool operator!=(const QBitArray &other) const { return !operator==(other); }
+#endif
- inline bool fill(bool val, int size = -1);
- void fill(bool val, int first, int last);
+ bool fill(bool aval, qsizetype asize = -1)
+ { *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; }
+ void fill(bool val, qsizetype first, qsizetype last);
- inline void truncate(int pos) { if (pos < size()) resize(pos); }
+ inline void truncate(qsizetype pos) { if (pos < size()) resize(pos); }
const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; }
static QBitArray fromBits(const char *data, qsizetype len);
@@ -110,58 +135,33 @@ public:
public:
typedef QByteArray::DataPointer DataPtr;
inline DataPtr &data_ptr() { return d.data_ptr(); }
-};
+ inline const DataPtr &data_ptr() const { return d.data_ptr(); }
-inline bool QBitArray::fill(bool aval, int asize)
-{ *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; }
-
-Q_CORE_EXPORT QBitArray operator&(const QBitArray &, const QBitArray &);
-Q_CORE_EXPORT QBitArray operator|(const QBitArray &, const QBitArray &);
-Q_CORE_EXPORT QBitArray operator^(const QBitArray &, const QBitArray &);
-
-inline bool QBitArray::testBit(int i) const
-{ Q_ASSERT(uint(i) < uint(size()));
- return (*(reinterpret_cast<const uchar*>(d.constData())+1+(i>>3)) & (1 << (i & 7))) != 0; }
-
-inline void QBitArray::setBit(int i)
-{ Q_ASSERT(uint(i) < uint(size()));
- *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) |= uchar(1 << (i & 7)); }
-
-inline void QBitArray::clearBit(int i)
-{ Q_ASSERT(uint(i) < uint(size()));
- *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) &= ~uchar(1 << (i & 7)); }
-
-inline void QBitArray::setBit(int i, bool val)
-{ if (val) setBit(i); else clearBit(i); }
-
-inline bool QBitArray::toggleBit(int i)
-{ Q_ASSERT(uint(i) < uint(size()));
- uchar b = uchar(1<<(i&7)); uchar* p = reinterpret_cast<uchar*>(d.data())+1+(i>>3);
- uchar c = uchar(*p&b); *p^=b; return c!=0; }
-
-inline bool QBitArray::operator[](int i) const { return testBit(i); }
-inline bool QBitArray::operator[](uint i) const { return testBit(i); }
-inline bool QBitArray::at(int i) const { return testBit(i); }
+private:
+ friend bool comparesEqual(const QBitArray &lhs, const QBitArray &rhs) noexcept
+ {
+ return lhs.d == rhs.d;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QBitArray)
+};
-class Q_CORE_EXPORT QBitRef
+class QT6_ONLY(Q_CORE_EXPORT) QBitRef
{
private:
- QBitArray& a;
- int i;
- inline QBitRef(QBitArray& array, int idx) : a(array), i(idx) {}
+ QBitArray &a;
+ qsizetype i;
+ inline QBitRef(QBitArray &array, qsizetype idx) : a(array), i(idx) { }
friend class QBitArray;
+
public:
inline operator bool() const { return a.testBit(i); }
inline bool operator!() const { return !a.testBit(i); }
- QBitRef& operator=(const QBitRef& val) { a.setBit(i, val); return *this; }
- QBitRef& operator=(bool val) { a.setBit(i, val); return *this; }
+ QBitRef &operator=(const QBitRef &val) { a.setBit(i, val); return *this; }
+ QBitRef &operator=(bool val) { a.setBit(i, val); return *this; }
};
-inline QBitRef QBitArray::operator[](int i)
+QBitRef QBitArray::operator[](qsizetype i)
{ Q_ASSERT(i >= 0); return QBitRef(*this, i); }
-inline QBitRef QBitArray::operator[](uint i)
-{ return QBitRef(*this, i); }
-
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h
index ac7760be0b..952b88bafb 100644
--- a/src/corelib/tools/qcache.h
+++ b/src/corelib/tools/qcache.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCACHE_H
#define QCACHE_H
@@ -48,11 +12,12 @@ QT_BEGIN_NAMESPACE
template <class Key, class T>
class QCache
{
- struct Value {
+ struct Value
+ {
T *t = nullptr;
- int cost = 0;
+ qsizetype cost = 0;
Value() noexcept = default;
- Value(T *tt, int c) noexcept
+ Value(T *tt, qsizetype c) noexcept
: t(tt), cost(c)
{}
Value(Value &&other) noexcept
@@ -63,24 +28,25 @@ class QCache
}
Value &operator=(Value &&other) noexcept
{
- qSwap(t, other.t);
- qSwap(cost, other.cost);
+ qt_ptr_swap(t, other.t);
+ std::swap(cost, other.cost);
return *this;
}
~Value() { delete t; }
+
private:
Q_DISABLE_COPY(Value)
};
- struct Chain {
- Chain() noexcept
- : prev(this), next(this)
- {}
+ struct Chain
+ {
+ Chain() noexcept : prev(this), next(this) { }
Chain *prev;
Chain *next;
};
- struct Node : public Chain {
+ struct Node : public Chain
+ {
using KeyType = Key;
using ValueType = Value;
@@ -99,31 +65,14 @@ class QCache
value(std::move(t))
{
}
- static void createInPlace(Node *n, const Key &k, T *o, int cost)
+ static void createInPlace(Node *n, const Key &k, T *o, qsizetype cost)
{
new (n) Node{ Key(k), Value(o, cost) };
}
- void emplace(T *o, int cost)
+ void emplace(T *o, qsizetype cost)
{
value = Value(o, cost);
}
- static Node create(const Key &k, Value &&t) noexcept(std::is_nothrow_move_assignable_v<Key> && std::is_nothrow_move_assignable_v<T>)
- {
- return Node(k, std::move(t));
- }
- void replace(const Value &t) noexcept(std::is_nothrow_assignable_v<T>)
- {
- value = t;
- }
- void replace(Value &&t) noexcept(std::is_nothrow_move_assignable_v<T>)
- {
- value = std::move(t);
- }
- Value takeValue() noexcept(std::is_nothrow_move_constructible_v<T>)
- {
- return std::move(value);
- }
- bool valuesEqual(const Node *other) const { return value == other->value; }
Node(Node &&other)
: Chain(other),
@@ -143,8 +92,8 @@ class QCache
mutable Chain chain;
Data d;
- int mx = 0;
- int total = 0;
+ qsizetype mx = 0;
+ qsizetype total = 0;
void unlink(Node *n) noexcept(std::is_nothrow_destructible_v<Node>)
{
@@ -153,11 +102,13 @@ class QCache
n->prev->next = n->next;
n->next->prev = n->prev;
total -= n->value.cost;
- auto it = d.find(n->key);
+ auto it = d.findBucket(n->key);
d.erase(it);
}
T *relink(const Key &key) const noexcept
{
+ if (isEmpty())
+ return nullptr;
Node *n = d.findNode(key);
if (!n)
return nullptr;
@@ -175,13 +126,11 @@ class QCache
return n->value.t;
}
- void trim(int m) noexcept(std::is_nothrow_destructible_v<Node>)
+ void trim(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
{
- Chain *n = chain.prev;
- while (n != &chain && total > m) {
- Node *u = static_cast<Node *>(n);
- n = n->prev;
- unlink(u);
+ while (chain.prev != &chain && total > m) {
+ Node *n = static_cast<Node *>(chain.prev);
+ unlink(n);
}
}
@@ -189,31 +138,38 @@ class QCache
Q_DISABLE_COPY(QCache)
public:
- inline explicit QCache(int maxCost = 100) noexcept
+ inline explicit QCache(qsizetype maxCost = 100) noexcept
: mx(maxCost)
- {}
- inline ~QCache() { clear(); }
+ {
+ }
+ inline ~QCache()
+ {
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
- inline int maxCost() const noexcept { return mx; }
- void setMaxCost(int m) noexcept(std::is_nothrow_destructible_v<Node>)
+ clear();
+ }
+
+ inline qsizetype maxCost() const noexcept { return mx; }
+ void setMaxCost(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
{
mx = m;
trim(mx);
}
- inline int totalCost() const noexcept { return total; }
+ inline qsizetype totalCost() const noexcept { return total; }
- inline qsizetype size() const noexcept { return d.size; }
- inline qsizetype count() const noexcept { return d.size; }
+ inline qsizetype size() const noexcept { return qsizetype(d.size); }
+ inline qsizetype count() const noexcept { return qsizetype(d.size); }
inline bool isEmpty() const noexcept { return !d.size; }
inline QList<Key> keys() const
{
QList<Key> k;
- if (d.size) {
- k.reserve(typename QList<Key>::size_type(d.size));
+ if (size()) {
+ k.reserve(size());
for (auto it = d.begin(); it != d.end(); ++it)
k << it.node()->key;
}
- Q_ASSERT(k.size() == qsizetype(d.size));
+ Q_ASSERT(k.size() == size());
return k;
}
@@ -225,11 +181,10 @@ public:
chain.prev = &chain;
}
- bool insert(const Key &key, T *object, int cost = 1)
+ bool insert(const Key &key, T *object, qsizetype cost = 1)
{
- remove(key);
-
if (cost > mx) {
+ remove(key);
delete object;
return false;
}
@@ -237,16 +192,18 @@ public:
auto result = d.findOrInsert(key);
Node *n = result.it.node();
if (result.initialized) {
- cost -= n->value.cost;
+ auto prevCost = n->value.cost;
result.it.node()->emplace(object, cost);
+ cost -= prevCost;
+ relink(key);
} else {
Node::createInPlace(n, key, object, cost);
+ n->prev = &chain;
+ n->next = chain.next;
+ chain.next->prev = n;
+ chain.next = n;
}
total += cost;
- n->prev = &chain;
- n->next = chain.next;
- chain.next->prev = n;
- chain.next = n;
return true;
}
T *object(const Key &key) const noexcept
@@ -259,11 +216,13 @@ public:
}
inline bool contains(const Key &key) const noexcept
{
- return d.findNode(key) != nullptr;
+ return !isEmpty() && d.findNode(key) != nullptr;
}
bool remove(const Key &key) noexcept(std::is_nothrow_destructible_v<Node>)
{
+ if (isEmpty())
+ return false;
Node *n = d.findNode(key);
if (!n) {
return false;
@@ -275,6 +234,8 @@ public:
T *take(const Key &key) noexcept(std::is_nothrow_destructible_v<Key>)
{
+ if (isEmpty())
+ return nullptr;
Node *n = d.findNode(key);
if (!n)
return nullptr;
diff --git a/src/corelib/tools/qcache.qdoc b/src/corelib/tools/qcache.qdoc
index ffc21318f4..9a4b86aa67 100644
--- a/src/corelib/tools/qcache.qdoc
+++ b/src/corelib/tools/qcache.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QCache
@@ -80,7 +56,7 @@
\sa QPixmapCache, QHash, QMap
*/
-/*! \fn template <class Key, class T> QCache<Key, T>::QCache(int maxCost = 100)
+/*! \fn template <class Key, class T> QCache<Key, T>::QCache(qsizetype maxCost = 100)
Constructs a cache whose contents will never have a total cost
greater than \a maxCost.
@@ -91,14 +67,14 @@
Destroys the cache. Deletes all the objects in the cache.
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::maxCost() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::maxCost() const
Returns the maximum allowed total cost of the cache.
\sa setMaxCost(), totalCost()
*/
-/*! \fn template <class Key, class T> void QCache<Key, T>::setMaxCost(int cost)
+/*! \fn template <class Key, class T> void QCache<Key, T>::setMaxCost(qsizetype cost)
Sets the maximum allowed total cost of the cache to \a cost. If
the current total cost is greater than \a cost, some objects are
@@ -107,7 +83,7 @@
\sa maxCost(), totalCost()
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::totalCost() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::totalCost() const
Returns the total cost of the objects in the cache.
@@ -120,14 +96,14 @@
\sa setMaxCost()
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::size() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::size() const
Returns the number of objects in the cache.
\sa isEmpty()
*/
-/*! \fn template <class Key, class T> int QCache<Key, T>::count() const
+/*! \fn template <class Key, class T> qsizetype QCache<Key, T>::count() const
Same as size().
*/
@@ -153,7 +129,7 @@
*/
-/*! \fn template <class Key, class T> bool QCache<Key, T>::insert(const Key &key, T *object, int cost = 1)
+/*! \fn template <class Key, class T> bool QCache<Key, T>::insert(const Key &key, T *object, qsizetype cost = 1)
Inserts \a object into the cache with key \a key and
associated cost \a cost. Any object with the same key already in
diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp
index aff684fad2..6b990cecf1 100644
--- a/src/corelib/tools/qcommandlineoption.cpp
+++ b/src/corelib/tools/qcommandlineoption.cpp
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
-** Copyright (C) 2013 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+// Copyright (C) 2013 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcommandlineoption.h"
@@ -151,8 +116,7 @@ QCommandLineOption::QCommandLineOption(const QStringList &names)
The default value for the option is set to \a defaultValue.
In Qt versions before 5.4, this constructor was \c explicit. In Qt 5.4
- and later, it no longer is and can be used for C++11-style uniform
- initialization:
+ and later, it no longer is and can be used for uniform initialization:
\snippet code/src_corelib_tools_qcommandlineoption.cpp cxx11-init
@@ -187,8 +151,7 @@ QCommandLineOption::QCommandLineOption(const QString &name, const QString &descr
The default value for the option is set to \a defaultValue.
In Qt versions before 5.4, this constructor was \c explicit. In Qt 5.4
- and later, it no longer is and can be used for C++11-style uniform
- initialization:
+ and later, it no longer is and can be used for uniform initialization:
\snippet code/src_corelib_tools_qcommandlineoption.cpp cxx11-init-list
@@ -260,11 +223,11 @@ namespace {
return warn("be empty");
const QChar c = name.at(0);
- if (Q_UNLIKELY(c == QLatin1Char('-')))
+ if (Q_UNLIKELY(c == u'-'))
return warn("start with a '-'");
- if (Q_UNLIKELY(c == QLatin1Char('/')))
+ if (Q_UNLIKELY(c == u'/'))
return warn("start with a '/'");
- if (Q_UNLIKELY(name.contains(QLatin1Char('='))))
+ if (Q_UNLIKELY(name.contains(u'=')))
return warn("contain a '='");
return false;
@@ -285,8 +248,7 @@ QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList)
if (Q_UNLIKELY(nameList.isEmpty()))
qWarning("QCommandLineOption: Options must have at least one name");
else
- nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()),
- nameList.end());
+ nameList.removeIf(IsInvalidName());
return nameList;
}
@@ -391,36 +353,6 @@ QStringList QCommandLineOption::defaultValues() const
return d->defaultValues;
}
-#if QT_DEPRECATED_SINCE(5, 8)
-/*!
- Sets whether to hide this option in the user-visible help output.
-
- All options are visible by default. Setting \a hide to true for
- a particular option makes it internal, i.e. not listed in the help output.
-
- \since 5.6
- \obsolete Use setFlags(QCommandLineOption::HiddenFromHelp), QCommandLineOption::HiddenFromHelp
- \sa isHidden
- */
-void QCommandLineOption::setHidden(bool hide)
-{
- d->flags.setFlag(HiddenFromHelp, hide);
-}
-
-/*!
- Returns true if this option is omitted from the help output,
- false if the option is listed.
-
- \since 5.6
- \obsolete Use flags() & QCommandLineOption::HiddenFromHelp
- \sa setHidden(), QCommandLineOption::HiddenFromHelp
- */
-bool QCommandLineOption::isHidden() const
-{
- return d->flags & HiddenFromHelp;
-}
-#endif
-
/*!
Returns a set of flags that affect this command-line option.
diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h
index e2ca64acef..63c90a4005 100644
--- a/src/corelib/tools/qcommandlineoption.h
+++ b/src/corelib/tools/qcommandlineoption.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOMMANDLINEOPTION_H
#define QCOMMANDLINEOPTION_H
@@ -71,10 +36,10 @@ public:
~QCommandLineOption();
QCommandLineOption &operator=(const QCommandLineOption &other);
- QCommandLineOption &operator=(QCommandLineOption &&other) noexcept { swap(other); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCommandLineOption)
void swap(QCommandLineOption &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
QStringList names() const;
@@ -91,14 +56,6 @@ public:
Flags flags() const;
void setFlags(Flags aflags);
-#if QT_DEPRECATED_SINCE(5, 8)
- QT_DEPRECATED_X("Use setFlags() with HiddenFromHelp")
- void setHidden(bool hidden);
- QT_DEPRECATED_X("Use flags() and HiddenFromHelp")
- bool isHidden() const;
-#endif
-
-
private:
QSharedDataPointer<QCommandLineOptionPrivate> d;
};
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 1b93fb84cf..2880eedf77 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
-** Copyright (C) 2013 David Faure <faure@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+// Copyright (C) 2013 David Faure <faure@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcommandlineparser.h"
#include <qcoreapplication.h>
#include <private/qcoreapplication_p.h>
#include <qhash.h>
+#include <qvarlengtharray.h>
#include <qlist.h>
#include <qdebug.h>
#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
@@ -53,9 +18,11 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
extern void Q_CORE_EXPORT qt_call_post_routines();
-typedef QHash<QString, int> NameHash_t;
+typedef QHash<QString, qsizetype> NameHash_t;
class QCommandLineParserPrivate
{
@@ -88,7 +55,7 @@ public:
NameHash_t nameHash;
//! Option values found (only for options with a value)
- QHash<int, QStringList> optionValuesHash;
+ QHash<qsizetype, QStringList> optionValuesHash;
//! Names of options found on the command line.
QStringList optionNames;
@@ -126,7 +93,7 @@ public:
//! True if parse() needs to be called
bool needsParsing;
};
-Q_DECLARE_TYPEINFO(QCommandLineParserPrivate::PositionalArgumentDefinition, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QCommandLineParserPrivate::PositionalArgumentDefinition, Q_RELOCATABLE_TYPE);
QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
{
@@ -158,24 +125,24 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
The parser handles short names, long names, more than one name for the same
option, and option values.
- Options on the command line are recognized as starting with a single or
- double \c{-} character(s).
+ Options on the command line are recognized as starting with one or two
+ \c{-} characters, followed by the option name.
The option \c{-} (single dash alone) is a special case, often meaning standard
- input, and not treated as an option. The parser will treat everything after the
+ input, and is not treated as an option. The parser will treat everything after the
option \c{--} (double dash) as positional arguments.
Short options are single letters. The option \c{v} would be specified by
passing \c{-v} on the command line. In the default parsing mode, short options
can be written in a compact form, for instance \c{-abc} is equivalent to \c{-a -b -c}.
- The parsing mode for can be set to ParseAsLongOptions, in which case \c{-abc}
+ The parsing mode can be changed to ParseAsLongOptions, in which case \c{-abc}
will be parsed as the long option \c{abc}.
Long options are more than one letter long and cannot be compacted together.
The long option \c{verbose} would be passed as \c{--verbose} or \c{-verbose}.
- Passing values to options can be done using the assignment operator: \c{-v=value}
- \c{--verbose=value}, or a space: \c{-v value} \c{--verbose value}, i.e. the next
- argument is used as value (even if it starts with a \c{-}).
+ Passing values to options can be done by using the assignment operator (\c{-v=value},
+ \c{--verbose=value}), or with a space (\c{-v value}, \c{--verbose value}). This
+ works even if the the value starts with a \c{-}.
The parser does not support optional values - if an option is set to
require a value, one must be present. If such an option is placed last
@@ -190,13 +157,13 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
Example:
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
- If your compiler supports the C++11 standard, the three addOption() calls in
- the above example can be simplified:
+ The three addOption() calls in the above example can be made more compact
+ by using addOptions():
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp cxx11
Known limitation: the parsing of Qt options inside QCoreApplication and subclasses
happens before QCommandLineParser exists, so it can't take it into account. This
- means any option value that looks like a builtin Qt option, will be treated by
+ means any option value that looks like a builtin Qt option will be treated by
QCoreApplication as a builtin Qt option. Example: \c{--profile -reverse} will
lead to QGuiApplication seeing the -reverse option set, and removing it from
QCoreApplication::arguments() before QCommandLineParser defines the \c{profile}
@@ -209,7 +176,7 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
It is then advisable to introduce a function to do the command line parsing
which takes a struct or class receiving the option values returning an
- enumeration representing the result. The dnslookup example of the QtNetwork
+ object representing the result. The dnslookup example of the QtNetwork
module illustrates this:
\snippet dnslookup.h 0
@@ -237,20 +204,22 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
\code
- switch (parseCommandLine(parser, &query, &errorMessage)) {
- case CommandLineOk:
+ switch (parseResult.statusCode) {
+ case Status::Ok:
break;
- case CommandLineError:
+ case Status::Error: {
+ QString errorMessage = parseResult.errorString.value_or(u"Unknown error occurred"_qs);
QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
"<html><head/><body><h2>" + errorMessage + "</h2><pre>"
+ parser.helpText() + "</pre></body></html>");
return 1;
- case CommandLineVersionRequested:
+ }
+ case Status::VersionRequested:
QMessageBox::information(0, QGuiApplication::applicationDisplayName(),
QGuiApplication::applicationDisplayName() + ' '
+ QCoreApplication::applicationVersion());
return 0;
- case CommandLineHelpRequested:
+ case Status::HelpRequested:
QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
"<html><head/><body><pre>"
+ parser.helpText() + "</pre></body></html>");
@@ -284,7 +253,7 @@ QCommandLineParser::~QCommandLineParser()
\enum QCommandLineParser::SingleDashWordOptionMode
This enum describes the way the parser interprets command-line
- options that use a single dash followed by multiple letters, as as \c{-abc}.
+ options that use a single dash followed by multiple letters, as \c{-abc}.
\value ParseAsCompactedShortOptions \c{-abc} is interpreted as \c{-a -b -c},
i.e. as three short options that have been compacted on the command-line,
@@ -372,7 +341,7 @@ bool QCommandLineParser::addOption(const QCommandLineOption &option)
d->commandLineOptionList.append(option);
- const int offset = d->commandLineOptionList.size() - 1;
+ const qsizetype offset = d->commandLineOptionList.size() - 1;
for (const QString &name : optionNames)
d->nameHash.insert(name, offset);
@@ -420,13 +389,17 @@ QCommandLineOption QCommandLineParser::addVersionOption()
}
/*!
- Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows)
- as well as an option \c{--help-all} to include Qt-specific options in the output.
+ Adds help options to the command-line parser.
+
+ The options specified for this command-line are described by \c{-h} or
+ \c{--help}. On Windows, the alternative \c{-?} is also supported. The option
+ \c{--help-all} extends that to include generic Qt options, not defined by
+ this command, in the output.
These options are handled automatically by QCommandLineParser.
- Remember to use setApplicationDescription to set the application description,
- which will be displayed when this option is used.
+ Remember to use setApplicationDescription() to set the application
+ description, which will be displayed when this option is used.
Example:
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
@@ -442,7 +415,8 @@ QCommandLineOption QCommandLineParser::addHelpOption()
<< QStringLiteral("h")
<< QStringLiteral("help"), tr("Displays help on commandline options."));
addOption(opt);
- QCommandLineOption optHelpAll(QStringLiteral("help-all"), tr("Displays help including Qt specific options."));
+ QCommandLineOption optHelpAll(QStringLiteral("help-all"),
+ tr("Displays help, including generic Qt options."));
addOption(optHelpAll);
d->builtinHelpOption = true;
return opt;
@@ -533,9 +507,9 @@ QString QCommandLineParser::errorText() const
{
if (!d->errorText.isEmpty())
return d->errorText;
- if (d->unknownOptionNames.count() == 1)
- return tr("Unknown option '%1'.").arg(d->unknownOptionNames.first());
- if (d->unknownOptionNames.count() > 1)
+ if (d->unknownOptionNames.size() == 1)
+ return tr("Unknown option '%1'.").arg(d->unknownOptionNames.constFirst());
+ if (d->unknownOptionNames.size() > 1)
return tr("Unknown options: %1.").arg(d->unknownOptionNames.join(QStringLiteral(", ")));
return QString();
}
@@ -547,7 +521,8 @@ enum MessageType { UsageMessage, ErrorMessage };
// or we are run with redirected handles (for example, by QProcess).
static inline bool displayMessageBox()
{
- if (GetConsoleWindow())
+ if (GetConsoleWindow()
+ || qEnvironmentVariableIsSet("QT_COMMAND_LINE_PARSER_NO_GUI_MESSAGE_BOXES"))
return false;
STARTUPINFO startupInfo;
startupInfo.cb = sizeof(STARTUPINFO);
@@ -592,7 +567,7 @@ static void showParserMessage(const QString &message, MessageType type)
void QCommandLineParser::process(const QStringList &arguments)
{
if (!d->parse(arguments)) {
- showParserMessage(QCoreApplication::applicationName() + QLatin1String(": ") + errorText() + QLatin1Char('\n'), ErrorMessage);
+ showParserMessage(QCoreApplication::applicationName() + ": "_L1 + errorText() + u'\n', ErrorMessage);
qt_call_post_routines();
::exit(EXIT_FAILURE);
}
@@ -659,7 +634,7 @@ bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, cons
const QLatin1Char assignChar('=');
const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
if (nameHashIt != nameHash.constEnd()) {
- const int assignPos = argument.indexOf(assignChar);
+ const qsizetype assignPos = argument.indexOf(assignChar);
const NameHash_t::mapped_type optionOffset = *nameHashIt;
const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
if (withValue) {
@@ -699,7 +674,6 @@ bool QCommandLineParserPrivate::parse(const QStringList &args)
needsParsing = false;
bool error = false;
- const QString doubleDashString(QStringLiteral("--"));
const QLatin1Char dashChar('-');
const QLatin1Char assignChar('=');
@@ -723,8 +697,8 @@ bool QCommandLineParserPrivate::parse(const QStringList &args)
if (forcePositional) {
positionalArgumentList.append(argument);
- } else if (argument.startsWith(doubleDashString)) {
- if (argument.length() > 2) {
+ } else if (argument.startsWith("--"_L1)) {
+ if (argument.size() > 2) {
QString optionName = argument.mid(2).section(assignChar, 0, 0);
if (registerFoundOption(optionName)) {
if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
@@ -812,7 +786,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args)
Returns \c true if the option \a name was set, false otherwise.
The name provided can be any long or short name of any option that was
- added with \c addOption(). All the options names are treated as being
+ added with addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present,
false is returned.
@@ -826,7 +800,7 @@ bool QCommandLineParser::isSet(const QString &name) const
if (d->optionNames.contains(name))
return true;
const QStringList aliases = d->aliases(name);
- for (const QString &optionName : qAsConst(d->optionNames)) {
+ for (const QString &optionName : std::as_const(d->optionNames)) {
if (aliases.contains(optionName))
return true;
}
@@ -838,7 +812,7 @@ bool QCommandLineParser::isSet(const QString &name) const
an empty string if not found.
The name provided can be any long or short name of any option that was
- added with \c addOption(). All the option names are treated as being
+ added with addOption(). All the option names are treated as being
equivalent. If the name is not recognized or that option was not present, an
empty string is returned.
@@ -846,7 +820,7 @@ bool QCommandLineParser::isSet(const QString &name) const
that option is returned. If the option wasn't specified on the command line,
the default value is returned.
- An empty string is returned if the option does not take a value.
+ If the option does not take a value, a warning is printed, and an empty string is returned.
\sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
@@ -867,7 +841,7 @@ QString QCommandLineParser::value(const QString &optionName) const
optionName, or an empty list if not found.
The name provided can be any long or short name of any option that was
- added with \c addOption(). All the options names are treated as being
+ added with addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present, an
empty list is returned.
@@ -883,12 +857,18 @@ QString QCommandLineParser::value(const QString &optionName) const
QStringList QCommandLineParser::values(const QString &optionName) const
{
d->checkParsed("values");
- const NameHash_t::const_iterator it = d->nameHash.constFind(optionName);
+ auto it = d->nameHash.constFind(optionName);
if (it != d->nameHash.cend()) {
- const int optionOffset = *it;
+ const qsizetype optionOffset = *it;
QStringList values = d->optionValuesHash.value(optionOffset);
- if (values.isEmpty())
- values = d->commandLineOptionList.at(optionOffset).defaultValues();
+ if (values.isEmpty()) {
+ const auto &option = d->commandLineOptionList.at(optionOffset);
+ if (option.valueName().isEmpty()) {
+ qWarning("QCommandLineParser: option not expecting values: \"%ls\"",
+ qUtf16Printable(optionName));
+ }
+ values = option.defaultValues();
+ }
return values;
}
@@ -975,8 +955,8 @@ QStringList QCommandLineParser::positionalArguments() const
Names may appear more than once in this list if they were encountered
more than once by the parser.
- Any entry in the list can be used with \c value() or with
- \c values() to get any relevant option values.
+ Any entry in the list can be used with value() or with
+ values() to get any relevant option values.
*/
QStringList QCommandLineParser::optionNames() const
@@ -1017,8 +997,8 @@ QStringList QCommandLineParser::unknownOptionNames() const
*/
Q_NORETURN void QCommandLineParser::showVersion()
{
- showParserMessage(QCoreApplication::applicationName() + QLatin1Char(' ')
- + QCoreApplication::applicationVersion() + QLatin1Char('\n'),
+ showParserMessage(QCoreApplication::applicationName() + u' '
+ + QCoreApplication::applicationVersion() + u'\n',
UsageMessage);
qt_call_post_routines();
::exit(EXIT_SUCCESS);
@@ -1059,8 +1039,8 @@ QString QCommandLineParser::helpText() const
static QString wrapText(const QString &names, int optionNameMaxWidth, const QString &description)
{
- const QLatin1Char nl('\n');
- const QLatin1String indentation(" ");
+ const auto nl = u'\n';
+ const auto indentation = " "_L1;
// In case the list of option names is very long, wrap it as well
int nameIndex = 0;
@@ -1071,20 +1051,20 @@ static QString wrapText(const QString &names, int optionNameMaxWidth, const QStr
};
QString text;
- int lineStart = 0;
- int lastBreakable = -1;
+ qsizetype lineStart = 0;
+ qsizetype lastBreakable = -1;
const int max = 79 - (indentation.size() + optionNameMaxWidth + 1);
int x = 0;
- const int len = description.length();
+ const qsizetype len = description.size();
- for (int i = 0; i < len; ++i) {
+ for (qsizetype i = 0; i < len; ++i) {
++x;
const QChar c = description.at(i);
if (c.isSpace())
lastBreakable = i;
- int breakAt = -1;
- int nextLineStart = -1;
+ qsizetype breakAt = -1;
+ qsizetype nextLineStart = -1;
if (x > max && lastBreakable != -1) {
// time to break and we know where
breakAt = lastBreakable;
@@ -1100,9 +1080,9 @@ static QString wrapText(const QString &names, int optionNameMaxWidth, const QStr
}
if (breakAt != -1) {
- const int numChars = breakAt - lineStart;
+ const qsizetype numChars = breakAt - lineStart;
//qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars);
- text += indentation + nextNameSection().leftJustified(optionNameMaxWidth) + QLatin1Char(' ');
+ text += indentation + nextNameSection().leftJustified(optionNameMaxWidth) + u' ';
text += QStringView{description}.mid(lineStart, numChars) + nl;
x = 0;
lastBreakable = -1;
@@ -1125,44 +1105,46 @@ QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const
const QLatin1Char nl('\n');
QString text;
QString usage;
- usage += QCoreApplication::instance()->arguments().constFirst(); // executable name
+ // executable name
+ usage += qApp ? QStringView(QCoreApplication::arguments().constFirst())
+ : QStringView(u"<executable_name>");
QList<QCommandLineOption> options = commandLineOptionList;
- if (includeQtOptions)
- QCoreApplication::instance()->d_func()->addQtOptions(&options);
+ if (includeQtOptions && qApp)
+ qApp->d_func()->addQtOptions(&options);
if (!options.isEmpty())
- usage += QLatin1Char(' ') + QCommandLineParser::tr("[options]");
+ usage += u' ' + QCommandLineParser::tr("[options]");
for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions)
- usage += QLatin1Char(' ') + arg.syntax;
+ usage += u' ' + arg.syntax;
text += QCommandLineParser::tr("Usage: %1").arg(usage) + nl;
if (!description.isEmpty())
- text += description + nl;
+ text += description + nl;
text += nl;
if (!options.isEmpty())
text += QCommandLineParser::tr("Options:") + nl;
QStringList optionNameList;
optionNameList.reserve(options.size());
- int longestOptionNameString = 0;
- for (const QCommandLineOption &option : qAsConst(options)) {
+ qsizetype longestOptionNameString = 0;
+ for (const QCommandLineOption &option : std::as_const(options)) {
if (option.flags() & QCommandLineOption::HiddenFromHelp)
continue;
const QStringList optionNames = option.names();
QString optionNamesString;
for (const QString &optionName : optionNames) {
- const int numDashes = optionName.length() == 1 ? 1 : 2;
- optionNamesString += QLatin1String("--", numDashes) + optionName + QLatin1String(", ");
+ const int numDashes = optionName.size() == 1 ? 1 : 2;
+ optionNamesString += QLatin1StringView("--", numDashes) + optionName + ", "_L1;
}
if (!optionNames.isEmpty())
optionNamesString.chop(2); // remove trailing ", "
const auto valueName = option.valueName();
if (!valueName.isEmpty())
- optionNamesString += QLatin1String(" <") + valueName + QLatin1Char('>');
+ optionNamesString += " <"_L1 + valueName + u'>';
optionNameList.append(optionNamesString);
- longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length());
+ longestOptionNameString = qMax(longestOptionNameString, optionNamesString.size());
}
++longestOptionNameString;
- const int optionNameMaxWidth = qMin(50, longestOptionNameString);
+ const int optionNameMaxWidth = qMin(50, int(longestOptionNameString));
auto optionNameIterator = optionNameList.cbegin();
- for (const QCommandLineOption &option : qAsConst(options)) {
+ for (const QCommandLineOption &option : std::as_const(options)) {
if (option.flags() & QCommandLineOption::HiddenFromHelp)
continue;
text += wrapText(*optionNameIterator, optionNameMaxWidth, option.description());
diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h
index 4584c384cc..332a2f9568 100644
--- a/src/corelib/tools/qcommandlineparser.h
+++ b/src/corelib/tools/qcommandlineparser.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOMMANDLINEPARSER_H
#define QCOMMANDLINEPARSER_H
diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h
index 715583e03b..d5590553fa 100644
--- a/src/corelib/tools/qcontainerfwd.h
+++ b/src/corelib/tools/qcontainerfwd.h
@@ -1,63 +1,63 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCONTAINERFWD_H
#define QCONTAINERFWD_H
-#include <QtCore/qglobal.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtypes.h>
-QT_BEGIN_NAMESPACE
+#if 0
+#pragma qt_class(QtContainerFwd)
+#endif
+
+// std headers can unfortunately not be forward declared
+#include <cstddef> // std::size_t
+#include <utility>
+#include <limits>
+QT_BEGIN_NAMESPACE
-template <class Key, class T> class QCache;
-template <class Key, class T> class QHash;
-template <class Key, class T> class QMap;
-template <class Key, class T> class QMultiHash;
-template <class Key, class T> class QMultiMap;
+template <typename Key, typename T> class QCache;
+template <typename Key, typename T> class QHash;
+template <typename Key, typename T> class QMap;
+template <typename Key, typename T> class QMultiHash;
+template <typename Key, typename T> class QMultiMap;
+#ifndef QT_NO_QPAIR
template <typename T1, typename T2>
using QPair = std::pair<T1, T2>;
-template <class T> class QQueue;
-template <class T> class QSet;
-template <class T> class QStack;
-template<class T, qsizetype Prealloc = 256> class QVarLengthArray;
-template <class T> class QList;
+#endif
+template <typename T> class QQueue;
+template <typename T> class QSet;
+template <typename T, std::size_t E = std::size_t(-1) /* = std::dynamic_extent*/> class QSpan;
+template <typename T> class QStack;
+constexpr qsizetype QVarLengthArrayDefaultPrealloc = 256;
+template <typename T, qsizetype Prealloc = QVarLengthArrayDefaultPrealloc> class QVarLengthArray;
+template <typename T> class QList;
+class QString;
+#ifndef Q_QDOC
template<typename T> using QVector = QList<T>;
+using QStringList = QList<QString>;
+class QByteArray;
+using QByteArrayList = QList<QByteArray>;
+#else
+template<typename T> class QVector;
+class QStringList;
+class QByteArrayList;
+#endif
+class QMetaType;
+class QVariant;
+
+using QVariantList = QList<QVariant>;
+using QVariantMap = QMap<QString, QVariant>;
+using QVariantHash = QHash<QString, QVariant>;
+using QVariantPair = std::pair<QVariant, QVariant>;
+
+namespace QtPrivate
+{
+[[maybe_unused]]
+constexpr qsizetype MaxAllocSize = (std::numeric_limits<qsizetype>::max)();
+}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h
index 44cfdc444e..998bc292d4 100644
--- a/src/corelib/tools/qcontainertools_impl.h
+++ b/src/corelib/tools/qcontainertools_impl.h
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#if 0
#pragma qt_sync_skip_header_check
@@ -49,31 +14,252 @@
#include <QtCore/qglobal.h>
#include <QtCore/qtypeinfo.h>
+#include <QtCore/qxptype_traits.h>
+
#include <cstring>
#include <iterator>
#include <memory>
+#include <algorithm>
QT_BEGIN_NAMESPACE
namespace QtPrivate
{
+/*!
+ \internal
+
+ Returns whether \a p is within a range [b, e). In simplest form equivalent to:
+ b <= p < e.
+*/
+template<typename T, typename Cmp = std::less<>>
+static constexpr bool q_points_into_range(const T *p, const T *b, const T *e,
+ Cmp less = {}) noexcept
+{
+ return !less(p, b) && less(p, e);
+}
+
+/*!
+ \internal
+
+ Returns whether \a p is within container \a c. In its simplest form equivalent to:
+ c.data() <= p < c.data() + c.size()
+*/
+template <typename C, typename T>
+static constexpr bool q_points_into_range(const T &p, const C &c) noexcept
+{
+ static_assert(std::is_same_v<decltype(std::data(c)), T>);
+
+ // std::distance because QArrayDataPointer has a "qsizetype size"
+ // member but no size() function
+ return q_points_into_range(p, std::data(c),
+ std::data(c) + std::distance(std::begin(c), std::end(c)));
+}
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
+
+template <typename T, typename N>
+void q_uninitialized_move_if_noexcept_n(T* first, N n, T* out)
+{
+ if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>)
+ std::uninitialized_move_n(first, n, out);
+ else
+ std::uninitialized_copy_n(first, n, out);
+}
+
template <typename T, typename N>
void q_uninitialized_relocate_n(T* first, N n, T* out)
{
- if constexpr (QTypeInfoQuery<T>::isRelocatable) {
- if (n != N(0)) { // even if N == 0, out == nullptr or first == nullptr are UB for memmove()
- std::memmove(static_cast<void*>(out),
- static_cast<const void*>(first),
- n * sizeof(T));
+ if constexpr (QTypeInfo<T>::isRelocatable) {
+ static_assert(std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>,
+ "Refusing to relocate this non-copy/non-move-constructible type.");
+ if (n != N(0)) { // even if N == 0, out == nullptr or first == nullptr are UB for memcpy()
+ std::memcpy(static_cast<void *>(out),
+ static_cast<const void *>(first),
+ n * sizeof(T));
}
} else {
- std::uninitialized_move_n(first, n, out);
- if constexpr (QTypeInfoQuery<T>::isComplex)
+ q_uninitialized_move_if_noexcept_n(first, n, out);
+ if constexpr (QTypeInfo<T>::isComplex)
std::destroy_n(first, n);
}
}
+QT_WARNING_POP
+
+/*!
+ \internal
+
+ A wrapper around std::rotate(), with an optimization for
+ Q_RELOCATABLE_TYPEs. We omit the return value, as it would be more work to
+ compute in the Q_RELOCATABLE_TYPE case and, unlike std::rotate on
+ ForwardIterators, callers can compute the result in constant time
+ themselves.
+*/
+template <typename T>
+void q_rotate(T *first, T *mid, T *last)
+{
+ if constexpr (QTypeInfo<T>::isRelocatable) {
+ const auto cast = [](T *p) { return reinterpret_cast<uchar*>(p); };
+ std::rotate(cast(first), cast(mid), cast(last));
+ } else {
+ std::rotate(first, mid, last);
+ }
+}
+
+/*!
+ \internal
+ Copies all elements, except the ones for which \a pred returns \c true, from
+ range [first, last), to the uninitialized memory buffer starting at \a out.
+
+ It's undefined behavior if \a out points into [first, last).
+
+ Returns a pointer one past the last copied element.
+
+ If an exception is thrown, all the already copied elements in the destination
+ buffer are destroyed.
+*/
+template <typename T, typename Predicate>
+T *q_uninitialized_remove_copy_if(T *first, T *last, T *out, Predicate &pred)
+{
+ static_assert(std::is_nothrow_destructible_v<T>,
+ "This algorithm requires that T has a non-throwing destructor");
+ Q_ASSERT(!q_points_into_range(out, first, last));
+
+ T *dest_begin = out;
+ QT_TRY {
+ while (first != last) {
+ if (!pred(*first)) {
+ new (std::addressof(*out)) T(*first);
+ ++out;
+ }
+ ++first;
+ }
+ } QT_CATCH (...) {
+ std::destroy(std::reverse_iterator(out), std::reverse_iterator(dest_begin));
+ QT_RETHROW;
+ }
+ return out;
+}
+
+template<typename iterator, typename N>
+void q_relocate_overlap_n_left_move(iterator first, N n, iterator d_first)
+{
+ // requires: [first, n) is a valid range
+ // requires: d_first + n is reachable from d_first
+ // requires: iterator is at least a random access iterator
+ // requires: value_type(iterator) has a non-throwing destructor
+
+ Q_ASSERT(n);
+ Q_ASSERT(d_first < first); // only allow moves to the "left"
+ using T = typename std::iterator_traits<iterator>::value_type;
+
+ // Watches passed iterator. Unless commit() is called, all the elements that
+ // the watched iterator passes through are deleted at the end of object
+ // lifetime. freeze() could be used to stop watching the passed iterator and
+ // remain at current place.
+ //
+ // requires: the iterator is expected to always point to an invalid object
+ // (to uninitialized memory)
+ struct Destructor
+ {
+ iterator *iter;
+ iterator end;
+ iterator intermediate;
+
+ Destructor(iterator &it) noexcept : iter(std::addressof(it)), end(it) { }
+ void commit() noexcept { iter = std::addressof(end); }
+ void freeze() noexcept
+ {
+ intermediate = *iter;
+ iter = std::addressof(intermediate);
+ }
+ ~Destructor() noexcept
+ {
+ for (const int step = *iter < end ? 1 : -1; *iter != end;) {
+ std::advance(*iter, step);
+ (*iter)->~T();
+ }
+ }
+ } destroyer(d_first);
+
+ const iterator d_last = d_first + n;
+ // Note: use pair and explicitly copy iterators from it to prevent
+ // accidental reference semantics instead of copy. equivalent to:
+ //
+ // auto [overlapBegin, overlapEnd] = std::minmax(d_last, first);
+ auto pair = std::minmax(d_last, first);
+
+ // overlap area between [d_first, d_first + n) and [first, first + n) or an
+ // uninitialized memory area between the two ranges
+ iterator overlapBegin = pair.first;
+ iterator overlapEnd = pair.second;
+
+ // move construct elements in uninitialized region
+ while (d_first != overlapBegin) {
+ // account for std::reverse_iterator, cannot use new(d_first) directly
+ new (std::addressof(*d_first)) T(std::move_if_noexcept(*first));
+ ++d_first;
+ ++first;
+ }
+
+ // cannot commit but have to stop - there might be an overlap region
+ // which we don't want to delete (because it's part of existing data)
+ destroyer.freeze();
+
+ // move assign elements in overlap region
+ while (d_first != d_last) {
+ *d_first = std::move_if_noexcept(*first);
+ ++d_first;
+ ++first;
+ }
+
+ Q_ASSERT(d_first == destroyer.end + n);
+ destroyer.commit(); // can commit here as ~T() below does not throw
+
+ while (first != overlapEnd)
+ (--first)->~T();
+}
+
+/*!
+ \internal
+
+ Relocates a range [first, n) to [d_first, n) taking care of potential memory
+ overlaps. This is a generic equivalent of memmove.
+
+ If an exception is thrown during the relocation, all the relocated elements
+ are destroyed and [first, n) may contain valid but unspecified values,
+ including moved-from values (basic exception safety).
+*/
+template<typename T, typename N>
+void q_relocate_overlap_n(T *first, N n, T *d_first)
+{
+ static_assert(std::is_nothrow_destructible_v<T>,
+ "This algorithm requires that T has a non-throwing destructor");
+
+ if (n == N(0) || first == d_first || first == nullptr || d_first == nullptr)
+ return;
+
+ if constexpr (QTypeInfo<T>::isRelocatable) {
+ std::memmove(static_cast<void *>(d_first), static_cast<const void *>(first), n * sizeof(T));
+ } else { // generic version has to be used
+ if (d_first < first) {
+ q_relocate_overlap_n_left_move(first, n, d_first);
+ } else { // first < d_first
+ auto rfirst = std::make_reverse_iterator(first + n);
+ auto rd_first = std::make_reverse_iterator(d_first + n);
+ q_relocate_overlap_n_left_move(rfirst, n, rd_first);
+ }
+ }
+}
+
+template <typename T>
+struct ArrowProxy
+{
+ T t;
+ T *operator->() noexcept { return &t; }
+};
template <typename Iterator>
using IfIsInputIterator = typename std::enable_if<
@@ -105,47 +291,177 @@ void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l
c->reserve(static_cast<typename Container::size_type>(std::distance(f, l)));
}
-// for detecting expression validity
-template <typename ... T>
-using void_t = void;
+template <typename Iterator>
+using KeyAndValueTest = decltype(
+ std::declval<Iterator &>().key(),
+ std::declval<Iterator &>().value()
+);
-template <typename Iterator, typename = void_t<>>
-struct AssociativeIteratorHasKeyAndValue : std::false_type
-{
-};
+template <typename Iterator>
+using FirstAndSecondTest = decltype(
+ std::declval<Iterator &>()->first,
+ std::declval<Iterator &>()->second
+);
+
+template <typename Iterator>
+using IfAssociativeIteratorHasKeyAndValue =
+ std::enable_if_t<qxp::is_detected_v<KeyAndValueTest, Iterator>, bool>;
+
+template <typename Iterator>
+using IfAssociativeIteratorHasFirstAndSecond =
+ std::enable_if_t<
+ std::conjunction_v<
+ std::negation<qxp::is_detected<KeyAndValueTest, Iterator>>,
+ qxp::is_detected<FirstAndSecondTest, Iterator>
+ >, bool>;
+
+template <typename Iterator>
+using MoveBackwardsTest = decltype(
+ std::declval<Iterator &>().operator--()
+);
template <typename Iterator>
-struct AssociativeIteratorHasKeyAndValue<
- Iterator,
- void_t<decltype(std::declval<Iterator &>().key()),
- decltype(std::declval<Iterator &>().value())>
- >
- : std::true_type
+using IfIteratorCanMoveBackwards =
+ std::enable_if_t<qxp::is_detected_v<MoveBackwardsTest, Iterator>, bool>;
+
+template <typename T, typename U>
+using IfIsNotSame =
+ typename std::enable_if<!std::is_same<T, U>::value, bool>::type;
+
+template<typename T, typename U>
+using IfIsNotConvertible = typename std::enable_if<!std::is_convertible<T, U>::value, bool>::type;
+
+template <typename Container, typename Predicate>
+auto sequential_erase_if(Container &c, Predicate &pred)
{
-};
+ // This is remove_if() modified to perform the find_if step on
+ // const_iterators to avoid shared container detaches if nothing needs to
+ // be removed. We cannot run remove_if after find_if: doing so would apply
+ // the predicate to the first matching element twice!
-template <typename Iterator, typename = void_t<>, typename = void_t<>>
-struct AssociativeIteratorHasFirstAndSecond : std::false_type
+ const auto cbegin = c.cbegin();
+ const auto cend = c.cend();
+ const auto t_it = std::find_if(cbegin, cend, pred);
+ auto result = std::distance(cbegin, t_it);
+ if (result == c.size())
+ return result - result; // `0` of the right type
+
+ // now detach:
+ const auto e = c.end();
+
+ auto it = std::next(c.begin(), result);
+ auto dest = it;
+
+ // Loop Invariants:
+ // - it != e
+ // - [next(it), e[ still to be checked
+ // - [c.begin(), dest[ are result
+ while (++it != e) {
+ if (!pred(*it)) {
+ *dest = std::move(*it);
+ ++dest;
+ }
+ }
+
+ result = std::distance(dest, e);
+ c.erase(dest, e);
+ return result;
+}
+
+template <typename Container, typename T>
+auto sequential_erase(Container &c, const T &t)
{
-};
+ // use the equivalence relation from http://eel.is/c++draft/list.erasure#1
+ auto cmp = [&](auto &e) { return e == t; };
+ return sequential_erase_if(c, cmp); // can't pass rvalues!
+}
-template <typename Iterator>
-struct AssociativeIteratorHasFirstAndSecond<
- Iterator,
- void_t<decltype(std::declval<Iterator &>()->first),
- decltype(std::declval<Iterator &>()->second)>
- >
- : std::true_type
+template <typename Container, typename T>
+auto sequential_erase_with_copy(Container &c, const T &t)
{
-};
+ using CopyProxy = std::conditional_t<std::is_copy_constructible_v<T>, T, const T &>;
+ return sequential_erase(c, CopyProxy(t));
+}
-template <typename Iterator>
-using IfAssociativeIteratorHasKeyAndValue =
- typename std::enable_if<AssociativeIteratorHasKeyAndValue<Iterator>::value, bool>::type;
+template <typename Container, typename T>
+auto sequential_erase_one(Container &c, const T &t)
+{
+ const auto cend = c.cend();
+ const auto it = std::find(c.cbegin(), cend, t);
+ if (it == cend)
+ return false;
+ c.erase(it);
+ return true;
+}
-template <typename Iterator>
-using IfAssociativeIteratorHasFirstAndSecond =
- typename std::enable_if<AssociativeIteratorHasFirstAndSecond<Iterator>::value, bool>::type;
+template <typename T, typename Predicate>
+qsizetype qset_erase_if(QSet<T> &set, Predicate &pred)
+{
+ qsizetype result = 0;
+ auto it = set.begin();
+ const auto e = set.end();
+ while (it != e) {
+ if (pred(*it)) {
+ ++result;
+ it = set.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ return result;
+}
+
+
+// Prerequisite: F is invocable on ArgTypes
+template <typename R, typename F, typename ... ArgTypes>
+struct is_invoke_result_explicitly_convertible : std::is_constructible<R, std::invoke_result_t<F, ArgTypes...>>
+{};
+
+// is_invocable_r checks for implicit conversions, but we need to check
+// for explicit conversions in remove_if. So, roll our own trait.
+template <typename R, typename F, typename ... ArgTypes>
+constexpr bool is_invocable_explicit_r_v = std::conjunction_v<
+ std::is_invocable<F, ArgTypes...>,
+ is_invoke_result_explicitly_convertible<R, F, ArgTypes...>
+>;
+
+template <typename Container, typename Predicate>
+auto associative_erase_if(Container &c, Predicate &pred)
+{
+ // we support predicates callable with either Container::iterator
+ // or with std::pair<const Key &, Value &>
+ using Iterator = typename Container::iterator;
+ using Key = typename Container::key_type;
+ using Value = typename Container::mapped_type;
+ using KeyValuePair = std::pair<const Key &, Value &>;
+
+ typename Container::size_type result = 0;
+
+ auto it = c.begin();
+ const auto e = c.end();
+ while (it != e) {
+ if constexpr (is_invocable_explicit_r_v<bool, Predicate &, Iterator &>) {
+ if (pred(it)) {
+ it = c.erase(it);
+ ++result;
+ } else {
+ ++it;
+ }
+ } else if constexpr (is_invocable_explicit_r_v<bool, Predicate &, KeyValuePair &&>) {
+ KeyValuePair p(it.key(), it.value());
+ if (pred(std::move(p))) {
+ it = c.erase(it);
+ ++result;
+ } else {
+ ++it;
+ }
+ } else {
+ static_assert(sizeof(Container) == 0, "Predicate has an incompatible signature");
+ }
+ }
+
+ return result;
+}
} // namespace QtPrivate
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
index cc3510ef88..d28d1e7153 100644
--- a/src/corelib/tools/qcontiguouscache.cpp
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcontiguouscache.h"
#ifdef QT_QCONTIGUOUSCACHE_DEBUG
#include <QDebug>
#endif
+#include <QtCore/qmalloc.h>
+
QT_BEGIN_NAMESPACE
#ifdef QT_QCONTIGUOUSCACHE_DEBUG
@@ -119,7 +85,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
See the \l{Contiguous Cache Example}{Contiguous Cache} example.
*/
-/*! \fn template<typename T> QContiguousCache<T>::QContiguousCache(int capacity)
+/*! \fn template<typename T> QContiguousCache<T>::QContiguousCache(qsizetype capacity)
Constructs a cache with the given \a capacity.
@@ -224,7 +190,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa operator==()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::capacity() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::capacity() const
Returns the number of items the cache can store before it is full.
When a cache contains a number of items equal to its capacity, adding new
@@ -233,12 +199,12 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa setCapacity(), size()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::count() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::count() const
Same as size().
*/
-/*! \fn template<typename T> int QContiguousCache<T>::size() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::size() const
Returns the number of items contained within the cache.
@@ -260,7 +226,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa size(), capacity()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::available() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::available() const
Returns the number of items that can be added to the cache before it becomes full.
@@ -272,7 +238,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
Removes all items from the cache. The capacity is unchanged.
*/
-/*! \fn template<typename T> void QContiguousCache<T>::setCapacity(int size)
+/*! \fn template<typename T> void QContiguousCache<T>::setCapacity(qsizetype size)
Sets the capacity of the cache to the given \a size. A cache can hold a
number of items equal to its capacity. When inserting, appending or prepending
@@ -285,7 +251,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa capacity(), isFull()
*/
-/*! \fn template<typename T> const T &QContiguousCache<T>::at(int i) const
+/*! \fn template<typename T> const T &QContiguousCache<T>::at(qsizetype i) const
Returns the item at index position \a i in the cache. \a i must
be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
@@ -299,7 +265,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa firstIndex(), lastIndex(), insert(), operator[]()
*/
-/*! \fn template<typename T> T &QContiguousCache<T>::operator[](int i)
+/*! \fn template<typename T> T &QContiguousCache<T>::operator[](qsizetype i)
Returns the item at index position \a i as a modifiable reference. If
the cache does not contain an item at the given index position \a i
@@ -314,7 +280,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa insert(), at()
*/
-/*! \fn template<typename T> const T &QContiguousCache<T>::operator[](int i) const
+/*! \fn template<typename T> const T &QContiguousCache<T>::operator[](qsizetype i) const
\overload
@@ -337,7 +303,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa append(), insert(), isFull()
*/
-/*! \fn template<typename T> void QContiguousCache<T>::insert(int i, const T &value)
+/*! \fn template<typename T> void QContiguousCache<T>::insert(qsizetype i, const T &value)
Inserts the \a value at the index position \a i. If the cache already contains
an item at \a i then that value is replaced. If \a i is either one more than
@@ -357,14 +323,14 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa prepend(), append(), isFull(), firstIndex(), lastIndex()
*/
-/*! \fn template<typename T> bool QContiguousCache<T>::containsIndex(int i) const
+/*! \fn template<typename T> bool QContiguousCache<T>::containsIndex(qsizetype i) const
Returns \c true if the cache's index range includes the given index \a i.
\sa firstIndex(), lastIndex()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::firstIndex() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::firstIndex() const
Returns the first valid index in the cache. The index will be invalid if the
cache is empty.
@@ -372,7 +338,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
\sa capacity(), size(), lastIndex()
*/
-/*! \fn template<typename T> int QContiguousCache<T>::lastIndex() const
+/*! \fn template<typename T> qsizetype QContiguousCache<T>::lastIndex() const
Returns the last valid index in the cache. The index will be invalid if the cache is empty.
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index 81361f219a..c01dbb9390 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -1,47 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCONTIGUOUSCACHE_H
#define QCONTIGUOUSCACHE_H
#include <QtCore/qatomic.h>
-#include <limits.h>
+#include <QtCore/qassert.h>
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/qtcoreexports.h>
+#include <QtCore/qtypeinfo.h>
+
+#include <climits>
+#include <limits>
#include <new>
QT_BEGIN_NAMESPACE
@@ -73,6 +43,8 @@ struct QContiguousCacheTypedData : public QContiguousCacheData
template<typename T>
class QContiguousCache {
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
typedef QContiguousCacheTypedData<T> Data;
Data *d;
public:
@@ -94,11 +66,32 @@ public:
inline bool isDetached() const { return d->ref.loadRelaxed() == 1; }
QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
- inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) noexcept
- { qSwap(d, other.d); return *this; }
- inline void swap(QContiguousCache<T> &other) noexcept { qSwap(d, other.d); }
- bool operator==(const QContiguousCache<T> &other) const;
- inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QContiguousCache)
+ void swap(QContiguousCache &other) noexcept { qt_ptr_swap(d, other.d); }
+
+#ifndef Q_QDOC
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator==(const QContiguousCache<T> &other) const
+ {
+ if (other.d == d)
+ return true;
+ if (other.d->start != d->start
+ || other.d->count != d->count
+ || other.d->offset != d->offset
+ || other.d->alloc != d->alloc)
+ return false;
+ for (qsizetype i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+ }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator!=(const QContiguousCache<T> &other) const
+ { return !(*this == other); }
+#else
+ bool operator==(const QContiguousCache &other) const;
+ bool operator!=(const QContiguousCache &other) const;
+#endif // Q_QDOC
inline qsizetype capacity() const {return d->alloc; }
inline qsizetype count() const { return d->count; }
@@ -193,13 +186,13 @@ void QContiguousCache<T>::setCapacity(qsizetype asize)
x->alloc = asize;
x->count = qMin(d->count, asize);
x->offset = d->offset + d->count - x->count;
- if(asize)
+ if (asize)
x->start = x->offset % x->alloc;
else
x->start = 0;
qsizetype oldcount = x->count;
- if(oldcount)
+ if (oldcount)
{
T *dest = x->array + (x->start + x->count-1) % x->alloc;
T *src = d->array + (d->start + d->count-1) % d->alloc;
@@ -272,22 +265,6 @@ QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &o
}
template <typename T>
-bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const
-{
- if (other.d == d)
- return true;
- if (other.d->start != d->start
- || other.d->count != d->count
- || other.d->offset != d->offset
- || other.d->alloc != d->alloc)
- return false;
- for (qsizetype i = firstIndex(); i <= lastIndex(); ++i)
- if (!(at(i) == other.at(i)))
- return false;
- return true;
-}
-
-template <typename T>
void QContiguousCache<T>::freeData(Data *x)
{
if (QTypeInfo<T>::isComplex) {
@@ -356,8 +333,7 @@ void QContiguousCache<T>::prepend(T &&value)
if (d->count != d->alloc)
d->count++;
else
- if (d->count == d->alloc)
- (d->array + d->start)->~T();
+ (d->array + d->start)->~T();
new (d->array + d->start) T(std::move(value));
}
@@ -377,7 +353,6 @@ void QContiguousCache<T>::prepend(const T &value)
if (d->count != d->alloc)
d->count++;
else
- if (d->count == d->alloc)
(d->array + d->start)->~T();
new (d->array + d->start) T(value);
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 1d4afabedd..2e82a394ee 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -1,45 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Richard J. Moore <rich@kde.org>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru>
+// Copyright (C) 2013 Richard J. Moore <rich@kde.org>.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qcryptographichash.h>
+#include <qmessageauthenticationcode.h>
+
#include <qiodevice.h>
+#include <qmutex.h>
+#include <qvarlengtharray.h>
+#include <private/qlocking_p.h>
+
+#include <array>
+#include <climits>
+#include <numeric>
#include "../../3rdparty/sha1/sha1.cpp"
@@ -47,12 +21,17 @@
# error "Are you sure you need the other hashing algorithms besides SHA-1?"
#endif
+// Header from rfc6234
+#include "../../3rdparty/rfc6234/sha.h"
+
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+#if !QT_CONFIG(openssl_hash)
// qdoc and qmake only need SHA-1
#include "../../3rdparty/md5/md5.h"
#include "../../3rdparty/md5/md5.cpp"
#include "../../3rdparty/md4/md4.h"
#include "../../3rdparty/md4/md4.cpp"
+#endif // !QT_CONFIG(openssl_hash)
typedef unsigned char BitSequence;
typedef unsigned long long DataLength;
@@ -79,55 +58,21 @@ typedef HashReturn (SHA3Final)(hashState *state, BitSequence *hashval);
#include "../../3rdparty/sha3/KeccakF-1600-opt64.c"
-static SHA3Init * const sha3Init = Init;
-static SHA3Update * const sha3Update = Update;
-static SHA3Final * const sha3Final = Final;
+Q_CONSTINIT static SHA3Init * const sha3Init = Init;
+Q_CONSTINIT static SHA3Update * const sha3Update = Update;
+Q_CONSTINIT static SHA3Final * const sha3Final = Final;
#else // 32 bit optimised fallback
#include "../../3rdparty/sha3/KeccakF-1600-opt32.c"
-static SHA3Init * const sha3Init = Init;
-static SHA3Update * const sha3Update = Update;
-static SHA3Final * const sha3Final = Final;
-
-#endif
-
-/*
- These #defines replace the typedefs needed by the RFC6234 code. Normally
- the typedefs would come from from stdint.h, but since this header is not
- available on all platforms (MSVC 2008, for example), we #define them to the
- Qt equivalents.
-*/
-
-#ifdef uint64_t
-#undef uint64_t
-#endif
-
-#define uint64_t QT_PREPEND_NAMESPACE(quint64)
-
-#ifdef uint32_t
-#undef uint32_t
-#endif
-
-#define uint32_t QT_PREPEND_NAMESPACE(quint32)
-
-#ifdef uint8_t
-#undef uint8_t
-#endif
-
-#define uint8_t QT_PREPEND_NAMESPACE(quint8)
+Q_CONSTINIT static SHA3Init * const sha3Init = Init;
+Q_CONSTINIT static SHA3Update * const sha3Update = Update;
+Q_CONSTINIT static SHA3Final * const sha3Final = Final;
-#ifdef int_least16_t
-#undef int_least16_t
#endif
-#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
-
-// Header from rfc6234 with 1 modification:
-// sha1.h - commented out '#include <stdint.h>' on line 74
-#include "../../3rdparty/rfc6234/sha.h"
-
+#if !QT_CONFIG(openssl_hash)
/*
These 2 functions replace macros of the same name in sha224-256.c and
sha384-512.c. Originally, these macros relied on a global static 'addTemp'
@@ -149,54 +94,301 @@ static int SHA384_512AddLength(SHA512Context *context, unsigned int length);
// sha384-512.c - appended 'M' to the SHA224_256AddLength macro on line 304
#include "../../3rdparty/rfc6234/sha384-512.c"
-#undef uint64_t
-#undef uint32_t
-#undef uint68_t
-#undef int_least16_t
-
static inline int SHA224_256AddLength(SHA256Context *context, unsigned int length)
{
- QT_PREPEND_NAMESPACE(quint32) addTemp;
+ uint32_t addTemp;
return SHA224_256AddLengthM(context, length);
}
static inline int SHA384_512AddLength(SHA512Context *context, unsigned int length)
{
- QT_PREPEND_NAMESPACE(quint64) addTemp;
+ uint64_t addTemp;
return SHA384_512AddLengthM(context, length);
}
+#endif // !QT_CONFIG(opensslv30)
+
+#include "qtcore-config_p.h"
+
+#if QT_CONFIG(system_libb2)
+#include <blake2.h>
+#else
+#include "../../3rdparty/blake2/src/blake2b-ref.c"
+#include "../../3rdparty/blake2/src/blake2s-ref.c"
+#endif
#endif // QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(openssl_hash)
+#define USING_OPENSSL30
+#include <openssl/evp.h>
+#include <openssl/provider.h>
+#endif
+
QT_BEGIN_NAMESPACE
+template <size_t N>
+class QSmallByteArray
+{
+ std::array<quint8, N> m_data;
+ static_assert(N <= std::numeric_limits<std::uint8_t>::max());
+ quint8 m_size = 0;
+public:
+ QSmallByteArray() = default;
+ // all compiler-generated SMFs are ok!
+ template <std::size_t M, std::enable_if_t<M < N, bool> = true> // M == N is for copy ctor!
+ constexpr QSmallByteArray(const QSmallByteArray<M> &other) noexcept
+ {
+ assign(other);
+ }
+ template <std::size_t M, std::enable_if_t<M < N, bool> = true> // M == N is for copy-assignment op!
+ constexpr QSmallByteArray &operator=(const QSmallByteArray<M> &other) noexcept
+ {
+ assign(other);
+ return *this;
+ }
+
+ template <typename Container> // ### underconstrained
+ constexpr void assign(const Container &c)
+ {
+ const size_t otherSize = size_t(std::size(c));
+ Q_ASSERT(otherSize < N);
+ memcpy(data(), std::data(c), otherSize);
+ m_size = quint8(otherSize);
+ }
+
+ constexpr quint8 *data() noexcept { return m_data.data(); }
+ constexpr const quint8 *data() const noexcept { return m_data.data(); }
+ constexpr qsizetype size() const noexcept { return qsizetype{m_size}; }
+ constexpr quint8 &operator[](qsizetype n)
+ {
+ Q_ASSERT(n < size());
+ return data()[n];
+ }
+ constexpr const quint8 &operator[](qsizetype n) const
+ {
+ Q_ASSERT(n < size());
+ return data()[n];
+ }
+ constexpr bool isEmpty() const noexcept { return size() == 0; }
+ constexpr void clear() noexcept { m_size = 0; }
+ constexpr void resizeForOverwrite(qsizetype s)
+ {
+ Q_ASSERT(s >= 0);
+ Q_ASSERT(size_t(s) <= N);
+ m_size = std::uint8_t(s);
+ }
+ constexpr void resize(qsizetype s, quint8 v)
+ {
+ const auto oldSize = size();
+ resizeForOverwrite(s);
+ if (s > oldSize)
+ memset(data() + oldSize, v, size() - oldSize);
+ }
+ constexpr QByteArrayView toByteArrayView() const noexcept
+ { return *this; }
+
+ constexpr auto begin() noexcept { return data(); }
+ constexpr auto begin() const noexcept { return data(); }
+ constexpr auto cbegin() const noexcept { return begin(); }
+ constexpr auto end() noexcept { return data() + size(); }
+ constexpr auto end() const noexcept { return data() + size(); }
+ constexpr auto cend() const noexcept { return end(); }
+};
+
+static constexpr int hashLengthInternal(QCryptographicHash::Algorithm method) noexcept
+{
+ switch (method) {
+#define CASE(Enum, Size) \
+ case QCryptographicHash:: Enum : \
+ return Size \
+ /*end*/
+ CASE(Sha1, 20);
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ CASE(Md4, 16);
+ CASE(Md5, 16);
+ CASE(Sha224, SHA224HashSize);
+ CASE(Sha256, SHA256HashSize);
+ CASE(Sha384, SHA384HashSize);
+ CASE(Sha512, SHA512HashSize);
+ CASE(Blake2s_128, 128 / 8);
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2s_160:
+ return 160 / 8;
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::Keccak_224:
+ case QCryptographicHash::Blake2s_224:
+ return 224 / 8;
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::Keccak_256:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2s_256:
+ return 256 / 8;
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::Keccak_384:
+ case QCryptographicHash::Blake2b_384:
+ return 384 / 8;
+ case QCryptographicHash::RealSha3_512:
+ case QCryptographicHash::Keccak_512:
+ case QCryptographicHash::Blake2b_512:
+ return 512 / 8;
+#endif
+#undef CASE
+ case QCryptographicHash::NumAlgorithms: ;
+ // fall through
+ // Q_UNREACHABLE() would be BiC here, as hashLength(~~invalid~~) worked in 6.4
+ }
+ return 0;
+}
+
+static constexpr int maxHashLength()
+{
+ int result = 0;
+ using A = QCryptographicHash::Algorithm;
+ for (int i = 0; i < A::NumAlgorithms; ++i)
+ result = std::max(result, hashLengthInternal(A(i)));
+ return result;
+}
+
+using HashResult = QSmallByteArray<maxHashLength()>;
+
+#ifdef USING_OPENSSL30
+static constexpr const char * methodToName(QCryptographicHash::Algorithm method) noexcept
+{
+ switch (method) {
+#define CASE(Enum, Name) \
+ case QCryptographicHash:: Enum : \
+ return Name \
+ /*end*/
+ CASE(Sha1, "SHA1");
+ CASE(Md4, "MD4");
+ CASE(Md5, "MD5");
+ CASE(Sha224, "SHA224");
+ CASE(Sha256, "SHA256");
+ CASE(Sha384, "SHA384");
+ CASE(Sha512, "SHA512");
+ CASE(RealSha3_224, "SHA3-224");
+ CASE(RealSha3_256, "SHA3-256");
+ CASE(RealSha3_384, "SHA3-384");
+ CASE(RealSha3_512, "SHA3-512");
+ CASE(Blake2b_512, "BLAKE2B512");
+ CASE(Blake2s_256, "BLAKE2S256");
+#undef CASE
+ default: return nullptr;
+ }
+}
+
+/*
+ Checks whether given method is not provided by OpenSSL and whether we will
+ have a fallback to non-OpenSSL implementation.
+*/
+static constexpr bool useNonOpenSSLFallback(QCryptographicHash::Algorithm method) noexcept
+{
+ if (method == QCryptographicHash::Keccak_224 || method == QCryptographicHash::Keccak_256 ||
+ method == QCryptographicHash::Keccak_384 || method == QCryptographicHash::Keccak_512 ||
+ method == QCryptographicHash::Blake2b_160 || method == QCryptographicHash::Blake2b_256 ||
+ method == QCryptographicHash::Blake2b_384 || method == QCryptographicHash::Blake2s_128 ||
+ method == QCryptographicHash::Blake2s_160 || method == QCryptographicHash::Blake2s_224)
+ return true;
+
+ return false;
+}
+#endif // USING_OPENSSL30
+
class QCryptographicHashPrivate
{
public:
- QCryptographicHash::Algorithm method;
- union {
+ explicit QCryptographicHashPrivate(QCryptographicHash::Algorithm method) noexcept
+ : state(method), method(method)
+ {
+ }
+ ~QCryptographicHashPrivate()
+ {
+ state.destroy(method);
+ }
+
+ void reset() noexcept;
+ void addData(QByteArrayView bytes) noexcept;
+ bool addData(QIODevice *dev);
+ void finalize() noexcept;
+ // when not called from the static hash() function, this function needs to be
+ // called with finalizeMutex held (finalize() will do that):
+ void finalizeUnchecked() noexcept;
+ // END functions that need to be called with finalizeMutex held
+ QByteArrayView resultView() const noexcept { return result.toByteArrayView(); }
+ static bool supportsAlgorithm(QCryptographicHash::Algorithm method);
+
+#ifdef USING_OPENSSL30
+ struct EVP_MD_CTX_deleter {
+ void operator()(EVP_MD_CTX *ctx) const noexcept {
+ EVP_MD_CTX_free(ctx);
+ }
+ };
+ struct EVP_MD_deleter {
+ void operator()(EVP_MD *md) const noexcept {
+ EVP_MD_free(md);
+ }
+ };
+ struct OSSL_PROVIDER_deleter {
+ void operator()(OSSL_PROVIDER *provider) const noexcept {
+ OSSL_PROVIDER_unload(provider);
+ }
+ };
+
+ using EVP_MD_CTX_ptr = std::unique_ptr<EVP_MD_CTX, EVP_MD_CTX_deleter>;
+ using EVP_MD_ptr = std::unique_ptr<EVP_MD, EVP_MD_deleter>;
+ using OSSL_PROVIDER_ptr = std::unique_ptr<OSSL_PROVIDER, OSSL_PROVIDER_deleter>;
+ struct EVP {
+ EVP_MD_ptr algorithm;
+ EVP_MD_CTX_ptr context;
+ OSSL_PROVIDER_ptr defaultProvider;
+ OSSL_PROVIDER_ptr legacyProvider;
+ bool initializationFailed;
+
+ explicit EVP(QCryptographicHash::Algorithm method);
+ void reset() noexcept;
+ void finalizeUnchecked(HashResult &result) noexcept;
+ };
+#endif
+
+ union State {
+ explicit State(QCryptographicHash::Algorithm method);
+ void destroy(QCryptographicHash::Algorithm method);
+#ifdef USING_OPENSSL30
+ ~State() {}
+#endif
+
+ void reset(QCryptographicHash::Algorithm method) noexcept;
+ void addData(QCryptographicHash::Algorithm method, QByteArrayView data) noexcept;
+ void finalizeUnchecked(QCryptographicHash::Algorithm method, HashResult &result) noexcept;
+
Sha1State sha1Context;
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+#ifdef USING_OPENSSL30
+ EVP evp;
+#else
MD5Context md5Context;
md4_context md4Context;
SHA224Context sha224Context;
SHA256Context sha256Context;
SHA384Context sha384Context;
SHA512Context sha512Context;
- SHA3Context sha3Context;
#endif
- };
-#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
- enum class Sha3Variant
- {
- Sha3,
- Keccak
- };
- void sha3Finish(int bitCount, Sha3Variant sha3Variant);
+ SHA3Context sha3Context;
+
+ enum class Sha3Variant { Sha3, Keccak };
+ void sha3Finish(HashResult &result, int bitCount, Sha3Variant sha3Variant);
+ blake2b_state blake2bContext;
+ blake2s_state blake2sContext;
#endif
- QByteArray result;
+ } state;
+ // protects result in finalize()
+ QBasicMutex finalizeMutex;
+ HashResult result;
+
+ const QCryptographicHash::Algorithm method;
};
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
-void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant)
+void QCryptographicHashPrivate::State::sha3Finish(HashResult &result, int bitCount,
+ Sha3Variant sha3Variant)
{
/*
FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function
@@ -220,7 +412,7 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant
*/
static const unsigned char sha3FinalSuffix = 0x80;
- result.resize(bitCount / 8);
+ result.resizeForOverwrite(bitCount / 8);
SHA3Context copy = sha3Context;
@@ -232,7 +424,7 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant
break;
}
- sha3Final(&copy, reinterpret_cast<BitSequence *>(result.data()));
+ sha3Final(&copy, result.data());
}
#endif
@@ -277,23 +469,42 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant
\value Keccak_256 Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2
\value Keccak_384 Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2
\value Keccak_512 Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2
+ \value Blake2b_160 Generate a BLAKE2b-160 hash sum. Introduced in Qt 6.0
+ \value Blake2b_256 Generate a BLAKE2b-256 hash sum. Introduced in Qt 6.0
+ \value Blake2b_384 Generate a BLAKE2b-384 hash sum. Introduced in Qt 6.0
+ \value Blake2b_512 Generate a BLAKE2b-512 hash sum. Introduced in Qt 6.0
+ \value Blake2s_128 Generate a BLAKE2s-128 hash sum. Introduced in Qt 6.0
+ \value Blake2s_160 Generate a BLAKE2s-160 hash sum. Introduced in Qt 6.0
+ \value Blake2s_224 Generate a BLAKE2s-224 hash sum. Introduced in Qt 6.0
+ \value Blake2s_256 Generate a BLAKE2s-256 hash sum. Introduced in Qt 6.0
\omitvalue RealSha3_224
\omitvalue RealSha3_256
\omitvalue RealSha3_384
\omitvalue RealSha3_512
+ \omitvalue NumAlgorithms
*/
/*!
Constructs an object that can be used to create a cryptographic hash from data using \a method.
*/
QCryptographicHash::QCryptographicHash(Algorithm method)
- : d(new QCryptographicHashPrivate)
+ : d(new QCryptographicHashPrivate{method})
{
- d->method = method;
- reset();
}
/*!
+ \fn QCryptographicHash::QCryptographicHash(QCryptographicHash &&other)
+
+ Move-constructs a new QCryptographicHash from \a other.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 6.5
+*/
+
+/*!
Destroys the object.
*/
QCryptographicHash::~QCryptographicHash()
@@ -302,13 +513,129 @@ QCryptographicHash::~QCryptographicHash()
}
/*!
+ \fn QCryptographicHash &QCryptographicHash::operator=(QCryptographicHash &&other)
+
+ Move-assigns \a other to this QCryptographicHash instance.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 6.5
+*/
+
+/*!
+ \fn void QCryptographicHash::swap(QCryptographicHash &other)
+
+ Swaps cryptographic hash \a other with this cryptographic hash. This
+ operation is very fast and never fails.
+
+ \since 6.5
+*/
+
+/*!
Resets the object.
*/
-void QCryptographicHash::reset()
+void QCryptographicHash::reset() noexcept
+{
+ d->reset();
+}
+
+/*!
+ Returns the algorithm used to generate the cryptographic hash.
+
+ \since 6.5
+*/
+QCryptographicHash::Algorithm QCryptographicHash::algorithm() const noexcept
+{
+ return d->method;
+}
+
+#ifdef USING_OPENSSL30
+
+QCryptographicHashPrivate::State::State(QCryptographicHash::Algorithm method)
+{
+ if (method == QCryptographicHash::Keccak_224 ||
+ method == QCryptographicHash::Keccak_256 ||
+ method == QCryptographicHash::Keccak_384 ||
+ method == QCryptographicHash::Keccak_512) {
+ new (&sha3Context) SHA3Context;
+ reset(method);
+ } else if (method == QCryptographicHash::Blake2b_160 ||
+ method == QCryptographicHash::Blake2b_256 ||
+ method == QCryptographicHash::Blake2b_384) {
+ new (&blake2bContext) blake2b_state;
+ reset(method);
+ } else if (method == QCryptographicHash::Blake2s_128 ||
+ method == QCryptographicHash::Blake2s_160 ||
+ method == QCryptographicHash::Blake2s_224) {
+ new (&blake2sContext) blake2s_state;
+ reset(method);
+ } else {
+ new (&evp) EVP(method);
+ }
+}
+
+void QCryptographicHashPrivate::State::destroy(QCryptographicHash::Algorithm method)
+{
+ if (method != QCryptographicHash::Keccak_224 &&
+ method != QCryptographicHash::Keccak_256 &&
+ method != QCryptographicHash::Keccak_384 &&
+ method != QCryptographicHash::Keccak_512 &&
+ method != QCryptographicHash::Blake2b_160 &&
+ method != QCryptographicHash::Blake2b_256 &&
+ method != QCryptographicHash::Blake2b_384 &&
+ method != QCryptographicHash::Blake2s_128 &&
+ method != QCryptographicHash::Blake2s_160 &&
+ method != QCryptographicHash::Blake2s_224) {
+ evp.~EVP();
+ }
+}
+
+QCryptographicHashPrivate::EVP::EVP(QCryptographicHash::Algorithm method)
+ : initializationFailed{true}
+{
+ if (method == QCryptographicHash::Md4) {
+ /*
+ * We need to load the legacy provider in order to have the MD4
+ * algorithm available.
+ */
+ legacyProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_load(nullptr, "legacy"));
+
+ if (!legacyProvider)
+ return;
+ }
+
+ defaultProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_load(nullptr, "default"));
+ if (!defaultProvider)
+ return;
+
+ context = EVP_MD_CTX_ptr(EVP_MD_CTX_new());
+
+ if (!context) {
+ return;
+ }
+
+ /*
+ * Using the "-fips" option will disable the global "fips=yes" for
+ * this one lookup and the algorithm can be fetched from any provider
+ * that implements the algorithm (including the FIPS provider).
+ */
+ algorithm = EVP_MD_ptr(EVP_MD_fetch(nullptr, methodToName(method), "-fips"));
+ if (!algorithm) {
+ return;
+ }
+
+ initializationFailed = !EVP_DigestInit_ex(context.get(), algorithm.get(), nullptr);
+}
+
+#else // USING_OPENSSL30
+
+QCryptographicHashPrivate::State::State(QCryptographicHash::Algorithm method)
{
- switch (d->method) {
- case Sha1:
- sha1InitState(&d->sha1Context);
+ switch (method) {
+ case QCryptographicHash::Sha1:
+ new (&sha1Context) Sha1State;
break;
#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
default:
@@ -316,67 +643,241 @@ void QCryptographicHash::reset()
Q_UNREACHABLE();
break;
#else
- case Md4:
- md4_init(&d->md4Context);
+ case QCryptographicHash::Md4:
+ new (&md4Context) md4_context;
+ break;
+ case QCryptographicHash::Md5:
+ new (&md5Context) MD5Context;
+ break;
+ case QCryptographicHash::Sha224:
+ new (&sha224Context) SHA224Context;
+ break;
+ case QCryptographicHash::Sha256:
+ new (&sha256Context) SHA256Context;
+ break;
+ case QCryptographicHash::Sha384:
+ new (&sha384Context) SHA384Context;
+ break;
+ case QCryptographicHash::Sha512:
+ new (&sha512Context) SHA512Context;
+ break;
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::Keccak_224:
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::Keccak_256:
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::Keccak_384:
+ case QCryptographicHash::RealSha3_512:
+ case QCryptographicHash::Keccak_512:
+ new (&sha3Context) SHA3Context;
+ break;
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2b_384:
+ case QCryptographicHash::Blake2b_512:
+ new (&blake2bContext) blake2b_state;
+ break;
+ case QCryptographicHash::Blake2s_128:
+ case QCryptographicHash::Blake2s_160:
+ case QCryptographicHash::Blake2s_224:
+ case QCryptographicHash::Blake2s_256:
+ new (&blake2sContext) blake2s_state;
+ break;
+#endif
+ case QCryptographicHash::NumAlgorithms:
+ Q_UNREACHABLE();
+ }
+ reset(method);
+}
+
+void QCryptographicHashPrivate::State::destroy(QCryptographicHash::Algorithm)
+{
+ static_assert(std::is_trivially_destructible_v<State>); // so nothing to do here
+}
+#endif // !USING_OPENSSL30
+
+void QCryptographicHashPrivate::reset() noexcept
+{
+ result.clear();
+ state.reset(method);
+}
+
+#ifdef USING_OPENSSL30
+
+void QCryptographicHashPrivate::State::reset(QCryptographicHash::Algorithm method) noexcept
+{
+ if (method == QCryptographicHash::Keccak_224 ||
+ method == QCryptographicHash::Keccak_256 ||
+ method == QCryptographicHash::Keccak_384 ||
+ method == QCryptographicHash::Keccak_512) {
+ sha3Init(&sha3Context, hashLengthInternal(method) * 8);
+ } else if (method == QCryptographicHash::Blake2b_160 ||
+ method == QCryptographicHash::Blake2b_256 ||
+ method == QCryptographicHash::Blake2b_384) {
+ blake2b_init(&blake2bContext, hashLengthInternal(method));
+ } else if (method == QCryptographicHash::Blake2s_128 ||
+ method == QCryptographicHash::Blake2s_160 ||
+ method == QCryptographicHash::Blake2s_224) {
+ blake2s_init(&blake2sContext, hashLengthInternal(method));
+ } else {
+ evp.reset();
+ }
+}
+
+void QCryptographicHashPrivate::EVP::reset() noexcept
+{
+ if (!initializationFailed) {
+ Q_ASSERT(context);
+ Q_ASSERT(algorithm);
+ // everything already set up - just reset the context
+ EVP_MD_CTX_reset(context.get());
+ initializationFailed = !EVP_DigestInit_ex(context.get(), algorithm.get(), nullptr);
+ }
+ // if initializationFailed first time around, it will not succeed this time, either
+}
+
+#else // USING_OPENSSL30
+
+void QCryptographicHashPrivate::State::reset(QCryptographicHash::Algorithm method) noexcept
+{
+ switch (method) {
+ case QCryptographicHash::Sha1:
+ sha1InitState(&sha1Context);
break;
- case Md5:
- MD5Init(&d->md5Context);
+#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ default:
+ Q_ASSERT_X(false, "QCryptographicHash", "Method not compiled in");
+ Q_UNREACHABLE();
break;
- case Sha224:
- SHA224Reset(&d->sha224Context);
+#else
+ case QCryptographicHash::Md4:
+ md4_init(&md4Context);
break;
- case Sha256:
- SHA256Reset(&d->sha256Context);
+ case QCryptographicHash::Md5:
+ MD5Init(&md5Context);
break;
- case Sha384:
- SHA384Reset(&d->sha384Context);
+ case QCryptographicHash::Sha224:
+ SHA224Reset(&sha224Context);
break;
- case Sha512:
- SHA512Reset(&d->sha512Context);
+ case QCryptographicHash::Sha256:
+ SHA256Reset(&sha256Context);
break;
- case RealSha3_224:
- case Keccak_224:
- sha3Init(&d->sha3Context, 224);
+ case QCryptographicHash::Sha384:
+ SHA384Reset(&sha384Context);
+ break;
+ case QCryptographicHash::Sha512:
+ SHA512Reset(&sha512Context);
break;
- case RealSha3_256:
- case Keccak_256:
- sha3Init(&d->sha3Context, 256);
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::Keccak_224:
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::Keccak_256:
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::Keccak_384:
+ case QCryptographicHash::RealSha3_512:
+ case QCryptographicHash::Keccak_512:
+ sha3Init(&sha3Context, hashLengthInternal(method) * 8);
break;
- case RealSha3_384:
- case Keccak_384:
- sha3Init(&d->sha3Context, 384);
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2b_384:
+ case QCryptographicHash::Blake2b_512:
+ blake2b_init(&blake2bContext, hashLengthInternal(method));
break;
- case RealSha3_512:
- case Keccak_512:
- sha3Init(&d->sha3Context, 512);
+ case QCryptographicHash::Blake2s_128:
+ case QCryptographicHash::Blake2s_160:
+ case QCryptographicHash::Blake2s_224:
+ case QCryptographicHash::Blake2s_256:
+ blake2s_init(&blake2sContext, hashLengthInternal(method));
break;
#endif
+ case QCryptographicHash::NumAlgorithms:
+ Q_UNREACHABLE();
}
- d->result.clear();
}
+#endif // USING_OPENSSL30
+
+#if QT_DEPRECATED_SINCE(6, 4)
/*!
Adds the first \a length chars of \a data to the cryptographic
hash.
+
+ \obsolete
+ Use the QByteArrayView overload instead.
*/
void QCryptographicHash::addData(const char *data, qsizetype length)
{
Q_ASSERT(length >= 0);
+ addData(QByteArrayView{data, length});
+}
+#endif
+
+/*!
+ Adds the characters in \a bytes to the cryptographic hash.
+
+ \note In Qt versions prior to 6.3, this function took QByteArray,
+ not QByteArrayView.
+*/
+void QCryptographicHash::addData(QByteArrayView bytes) noexcept
+{
+ d->addData(bytes);
+}
+
+void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
+{
+ state.addData(method, bytes);
+ result.clear();
+}
+
+#ifdef USING_OPENSSL30
+
+void QCryptographicHashPrivate::State::addData(QCryptographicHash::Algorithm method,
+ QByteArrayView bytes) noexcept
+{
+ const char *data = bytes.data();
+ auto length = bytes.size();
+ // all functions take size_t length, so we don't need to loop around them:
+ {
+ if (method == QCryptographicHash::Keccak_224 ||
+ method == QCryptographicHash::Keccak_256 ||
+ method == QCryptographicHash::Keccak_384 ||
+ method == QCryptographicHash::Keccak_512) {
+ sha3Update(&sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
+ } else if (method == QCryptographicHash::Blake2b_160 ||
+ method == QCryptographicHash::Blake2b_256 ||
+ method == QCryptographicHash::Blake2b_384) {
+ blake2b_update(&blake2bContext, reinterpret_cast<const uint8_t *>(data), length);
+ } else if (method == QCryptographicHash::Blake2s_128 ||
+ method == QCryptographicHash::Blake2s_160 ||
+ method == QCryptographicHash::Blake2s_224) {
+ blake2s_update(&blake2sContext, reinterpret_cast<const uint8_t *>(data), length);
+ } else if (!evp.initializationFailed) {
+ EVP_DigestUpdate(evp.context.get(), (const unsigned char *)data, length);
+ }
+ }
+}
+
+#else // USING_OPENSSL30
+
+void QCryptographicHashPrivate::State::addData(QCryptographicHash::Algorithm method,
+ QByteArrayView bytes) noexcept
+{
+ const char *data = bytes.data();
+ auto length = bytes.size();
#if QT_POINTER_SIZE == 8
// feed the data UINT_MAX bytes at a time, as some of the methods below
// take a uint (of course, feeding more than 4G of data into the hashing
// functions will be pretty slow anyway)
- qsizetype remaining = length;
- while (remaining) {
+ for (auto remaining = length; remaining; remaining -= length, data += length) {
length = qMin(qsizetype(std::numeric_limits<uint>::max()), remaining);
- remaining -= length;
#else
{
#endif
- switch (d->method) {
- case Sha1:
- sha1Update(&d->sha1Context, (const unsigned char *)data, length);
+ switch (method) {
+ case QCryptographicHash::Sha1:
+ sha1Update(&sha1Context, (const unsigned char *)data, length);
break;
#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
default:
@@ -384,60 +885,65 @@ void QCryptographicHash::addData(const char *data, qsizetype length)
Q_UNREACHABLE();
break;
#else
- case Md4:
- md4_update(&d->md4Context, (const unsigned char *)data, length);
- break;
- case Md5:
- MD5Update(&d->md5Context, (const unsigned char *)data, length);
+ case QCryptographicHash::Md4:
+ md4_update(&md4Context, (const unsigned char *)data, length);
break;
- case Sha224:
- SHA224Input(&d->sha224Context, reinterpret_cast<const unsigned char *>(data), length);
+ case QCryptographicHash::Md5:
+ MD5Update(&md5Context, (const unsigned char *)data, length);
break;
- case Sha256:
- SHA256Input(&d->sha256Context, reinterpret_cast<const unsigned char *>(data), length);
+ case QCryptographicHash::Sha224:
+ SHA224Input(&sha224Context, reinterpret_cast<const unsigned char *>(data), length);
break;
- case Sha384:
- SHA384Input(&d->sha384Context, reinterpret_cast<const unsigned char *>(data), length);
+ case QCryptographicHash::Sha256:
+ SHA256Input(&sha256Context, reinterpret_cast<const unsigned char *>(data), length);
break;
- case Sha512:
- SHA512Input(&d->sha512Context, reinterpret_cast<const unsigned char *>(data), length);
+ case QCryptographicHash::Sha384:
+ SHA384Input(&sha384Context, reinterpret_cast<const unsigned char *>(data), length);
break;
- case RealSha3_224:
- case Keccak_224:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ case QCryptographicHash::Sha512:
+ SHA512Input(&sha512Context, reinterpret_cast<const unsigned char *>(data), length);
break;
- case RealSha3_256:
- case Keccak_256:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::Keccak_224:
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::Keccak_256:
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::Keccak_384:
+ case QCryptographicHash::RealSha3_512:
+ case QCryptographicHash::Keccak_512:
+ sha3Update(&sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
break;
- case RealSha3_384:
- case Keccak_384:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2b_384:
+ case QCryptographicHash::Blake2b_512:
+ blake2b_update(&blake2bContext, reinterpret_cast<const uint8_t *>(data), length);
break;
- case RealSha3_512:
- case Keccak_512:
- sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
+ case QCryptographicHash::Blake2s_128:
+ case QCryptographicHash::Blake2s_160:
+ case QCryptographicHash::Blake2s_224:
+ case QCryptographicHash::Blake2s_256:
+ blake2s_update(&blake2sContext, reinterpret_cast<const uint8_t *>(data), length);
break;
#endif
+ case QCryptographicHash::NumAlgorithms:
+ Q_UNREACHABLE();
}
}
- d->result.clear();
-}
-
-/*!
- \overload addData()
-*/
-void QCryptographicHash::addData(const QByteArray &data)
-{
- addData(data.constData(), data.length());
}
+#endif // !USING_OPENSSL30
/*!
Reads the data from the open QIODevice \a device until it ends
and hashes it. Returns \c true if reading was successful.
\since 5.0
*/
-bool QCryptographicHash::addData(QIODevice* device)
+bool QCryptographicHash::addData(QIODevice *device)
+{
+ return d->addData(device);
+}
+
+bool QCryptographicHashPrivate::addData(QIODevice *device)
{
if (!device->isReadable())
return false;
@@ -446,10 +952,10 @@ bool QCryptographicHash::addData(QIODevice* device)
return false;
char buffer[1024];
- int length;
+ qint64 length;
- while ((length = device->read(buffer,sizeof(buffer))) > 0)
- addData(buffer,length);
+ while ((length = device->read(buffer, sizeof(buffer))) > 0)
+ addData({buffer, qsizetype(length)}); // length always <= 1024
return device->atEnd();
}
@@ -458,19 +964,105 @@ bool QCryptographicHash::addData(QIODevice* device)
/*!
Returns the final hash value.
- \sa QByteArray::toHex()
+ \sa resultView(), QByteArray::toHex()
*/
QByteArray QCryptographicHash::result() const
{
- if (!d->result.isEmpty())
- return d->result;
+ return resultView().toByteArray();
+}
+
+/*!
+ \since 6.3
+
+ Returns the final hash value.
+
+ Note that the returned view remains valid only as long as the QCryptographicHash object is
+ not modified by other means.
+
+ \sa result()
+*/
+QByteArrayView QCryptographicHash::resultView() const noexcept
+{
+ // resultView() is a const function, so concurrent calls are allowed; protect:
+ d->finalize();
+ // resultView() remains(!) valid even after we dropped the mutex in finalize()
+ return d->resultView();
+}
+
+/*!
+ \internal
+
+ Calls finalizeUnchecked(), if needed, under finalizeMutex protection.
+*/
+void QCryptographicHashPrivate::finalize() noexcept
+{
+ const auto lock = qt_scoped_lock(finalizeMutex);
+ // check that no other thread already finalizeUnchecked()'ed before us:
+ if (!result.isEmpty())
+ return;
+ finalizeUnchecked();
+}
+
+/*!
+ \internal
+
+ Must be called with finalizeMutex held (except from static hash() function,
+ where no sharing can take place).
+*/
+void QCryptographicHashPrivate::finalizeUnchecked() noexcept
+{
+ state.finalizeUnchecked(method, result);
+}
+
+#ifdef USING_OPENSSL30
+void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
+ HashResult &result) noexcept
+{
+ if (method == QCryptographicHash::Keccak_224 ||
+ method == QCryptographicHash::Keccak_256 ||
+ method == QCryptographicHash::Keccak_384 ||
+ method == QCryptographicHash::Keccak_512) {
+ sha3Finish(result, 8 * hashLengthInternal(method), Sha3Variant::Keccak);
+ } else if (method == QCryptographicHash::Blake2b_160 ||
+ method == QCryptographicHash::Blake2b_256 ||
+ method == QCryptographicHash::Blake2b_384) {
+ const auto length = hashLengthInternal(method);
+ blake2b_state copy = blake2bContext;
+ result.resizeForOverwrite(length);
+ blake2b_final(&copy, result.data(), length);
+ } else if (method == QCryptographicHash::Blake2s_128 ||
+ method == QCryptographicHash::Blake2s_160 ||
+ method == QCryptographicHash::Blake2s_224) {
+ const auto length = hashLengthInternal(method);
+ blake2s_state copy = blake2sContext;
+ result.resizeForOverwrite(length);
+ blake2s_final(&copy, result.data(), length);
+ } else {
+ evp.finalizeUnchecked(result);
+ }
+}
+
+void QCryptographicHashPrivate::EVP::finalizeUnchecked(HashResult &result) noexcept
+{
+ if (!initializationFailed) {
+ EVP_MD_CTX_ptr copy = EVP_MD_CTX_ptr(EVP_MD_CTX_new());
+ EVP_MD_CTX_copy_ex(copy.get(), context.get());
+ result.resizeForOverwrite(EVP_MD_get_size(algorithm.get()));
+ EVP_DigestFinal_ex(copy.get(), result.data(), nullptr);
+ }
+}
- switch (d->method) {
- case Sha1: {
- Sha1State copy = d->sha1Context;
- d->result.resize(20);
+#else // USING_OPENSSL30
+
+void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
+ HashResult &result) noexcept
+{
+ switch (method) {
+ case QCryptographicHash::Sha1: {
+ Sha1State copy = sha1Context;
+ result.resizeForOverwrite(20);
sha1FinalizeState(&copy);
- sha1ToHash(&copy, (unsigned char *)d->result.data());
+ sha1ToHash(&copy, result.data());
break;
}
#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
@@ -479,87 +1071,95 @@ QByteArray QCryptographicHash::result() const
Q_UNREACHABLE();
break;
#else
- case Md4: {
- md4_context copy = d->md4Context;
- d->result.resize(MD4_RESULTLEN);
- md4_final(&copy, (unsigned char *)d->result.data());
- break;
- }
- case Md5: {
- MD5Context copy = d->md5Context;
- d->result.resize(16);
- MD5Final(&copy, (unsigned char *)d->result.data());
+ case QCryptographicHash::Md4: {
+ md4_context copy = md4Context;
+ result.resizeForOverwrite(MD4_RESULTLEN);
+ md4_final(&copy, result.data());
break;
}
- case Sha224: {
- SHA224Context copy = d->sha224Context;
- d->result.resize(SHA224HashSize);
- SHA224Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
+ case QCryptographicHash::Md5: {
+ MD5Context copy = md5Context;
+ result.resizeForOverwrite(16);
+ MD5Final(&copy, result.data());
break;
}
- case Sha256:{
- SHA256Context copy = d->sha256Context;
- d->result.resize(SHA256HashSize);
- SHA256Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
+ case QCryptographicHash::Sha224: {
+ SHA224Context copy = sha224Context;
+ result.resizeForOverwrite(SHA224HashSize);
+ SHA224Result(&copy, result.data());
break;
}
- case Sha384:{
- SHA384Context copy = d->sha384Context;
- d->result.resize(SHA384HashSize);
- SHA384Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
+ case QCryptographicHash::Sha256: {
+ SHA256Context copy = sha256Context;
+ result.resizeForOverwrite(SHA256HashSize);
+ SHA256Result(&copy, result.data());
break;
}
- case Sha512:{
- SHA512Context copy = d->sha512Context;
- d->result.resize(SHA512HashSize);
- SHA512Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
+ case QCryptographicHash::Sha384: {
+ SHA384Context copy = sha384Context;
+ result.resizeForOverwrite(SHA384HashSize);
+ SHA384Result(&copy, result.data());
break;
}
- case RealSha3_224: {
- d->sha3Finish(224, QCryptographicHashPrivate::Sha3Variant::Sha3);
+ case QCryptographicHash::Sha512: {
+ SHA512Context copy = sha512Context;
+ result.resizeForOverwrite(SHA512HashSize);
+ SHA512Result(&copy, result.data());
break;
}
- case RealSha3_256: {
- d->sha3Finish(256, QCryptographicHashPrivate::Sha3Variant::Sha3);
- break;
- }
- case RealSha3_384: {
- d->sha3Finish(384, QCryptographicHashPrivate::Sha3Variant::Sha3);
- break;
- }
- case RealSha3_512: {
- d->sha3Finish(512, QCryptographicHashPrivate::Sha3Variant::Sha3);
- break;
- }
- case Keccak_224: {
- d->sha3Finish(224, QCryptographicHashPrivate::Sha3Variant::Keccak);
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::RealSha3_512: {
+ sha3Finish(result, 8 * hashLengthInternal(method), Sha3Variant::Sha3);
break;
}
- case Keccak_256: {
- d->sha3Finish(256, QCryptographicHashPrivate::Sha3Variant::Keccak);
+ case QCryptographicHash::Keccak_224:
+ case QCryptographicHash::Keccak_256:
+ case QCryptographicHash::Keccak_384:
+ case QCryptographicHash::Keccak_512: {
+ sha3Finish(result, 8 * hashLengthInternal(method), Sha3Variant::Keccak);
break;
}
- case Keccak_384: {
- d->sha3Finish(384, QCryptographicHashPrivate::Sha3Variant::Keccak);
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2b_384:
+ case QCryptographicHash::Blake2b_512: {
+ const auto length = hashLengthInternal(method);
+ blake2b_state copy = blake2bContext;
+ result.resizeForOverwrite(length);
+ blake2b_final(&copy, result.data(), length);
break;
}
- case Keccak_512: {
- d->sha3Finish(512, QCryptographicHashPrivate::Sha3Variant::Keccak);
+ case QCryptographicHash::Blake2s_128:
+ case QCryptographicHash::Blake2s_160:
+ case QCryptographicHash::Blake2s_224:
+ case QCryptographicHash::Blake2s_256: {
+ const auto length = hashLengthInternal(method);
+ blake2s_state copy = blake2sContext;
+ result.resizeForOverwrite(length);
+ blake2s_final(&copy, result.data(), length);
break;
}
#endif
+ case QCryptographicHash::NumAlgorithms:
+ Q_UNREACHABLE();
}
- return d->result;
}
+#endif // !USING_OPENSSL30
/*!
Returns the hash of \a data using \a method.
+
+ \note In Qt versions prior to 6.3, this function took QByteArray,
+ not QByteArrayView.
*/
-QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
+QByteArray QCryptographicHash::hash(QByteArrayView data, Algorithm method)
{
- QCryptographicHash hash(method);
+ QCryptographicHashPrivate hash(method);
hash.addData(data);
- return hash.result();
+ hash.finalizeUnchecked(); // no mutex needed: no-one but us has access to 'hash'
+ return hash.resultView().toByteArray();
}
/*!
@@ -569,39 +1169,483 @@ QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
*/
int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method)
{
+ return hashLengthInternal(method);
+}
+
+/*!
+ Returns whether the selected algorithm \a method is supported and if
+ result() will return a value when the \a method is used.
+
+ \note OpenSSL will be responsible for providing this information when
+ used as a provider, otherwise \c true will be returned as the non-OpenSSL
+ implementation doesn't have any restrictions.
+ We return \c false if we fail to query OpenSSL.
+
+ \since 6.5
+*/
+
+
+bool QCryptographicHash::supportsAlgorithm(QCryptographicHash::Algorithm method)
+{
+ return QCryptographicHashPrivate::supportsAlgorithm(method);
+}
+
+bool QCryptographicHashPrivate::supportsAlgorithm(QCryptographicHash::Algorithm method)
+{
+#ifdef USING_OPENSSL30
+ // OpenSSL doesn't support Blake2b{60,236,384} and Blake2s{128,160,224}
+ // and these would automatically return FALSE in that case, while they are
+ // actually supported by our non-OpenSSL implementation.
+ if (useNonOpenSSLFallback(method))
+ return true;
+
+ auto legacyProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_load(nullptr, "legacy"));
+ auto defaultProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_load(nullptr, "default"));
+
+ const char *restriction = "-fips";
+ EVP_MD_ptr algorithm = EVP_MD_ptr(EVP_MD_fetch(nullptr, methodToName(method), restriction));
+
+ return algorithm != nullptr;
+#else
switch (method) {
case QCryptographicHash::Sha1:
- return 20;
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
case QCryptographicHash::Md4:
- return 16;
case QCryptographicHash::Md5:
- return 16;
case QCryptographicHash::Sha224:
- return SHA224HashSize;
case QCryptographicHash::Sha256:
- return SHA256HashSize;
case QCryptographicHash::Sha384:
- return SHA384HashSize;
case QCryptographicHash::Sha512:
- return SHA512HashSize;
case QCryptographicHash::RealSha3_224:
case QCryptographicHash::Keccak_224:
- return 224 / 8;
case QCryptographicHash::RealSha3_256:
case QCryptographicHash::Keccak_256:
- return 256 / 8;
case QCryptographicHash::RealSha3_384:
case QCryptographicHash::Keccak_384:
- return 384 / 8;
case QCryptographicHash::RealSha3_512:
case QCryptographicHash::Keccak_512:
- return 512 / 8;
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2b_384:
+ case QCryptographicHash::Blake2b_512:
+ case QCryptographicHash::Blake2s_128:
+ case QCryptographicHash::Blake2s_160:
+ case QCryptographicHash::Blake2s_224:
+ case QCryptographicHash::Blake2s_256:
+#endif
+ return true;
+ case QCryptographicHash::NumAlgorithms: ;
+ };
+ return false;
+#endif // !USING_OPENSSL3
+}
+
+static constexpr int qt_hash_block_size(QCryptographicHash::Algorithm method)
+{
+ switch (method) {
+ case QCryptographicHash::Sha1:
+ return SHA1_Message_Block_Size;
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ case QCryptographicHash::Md4:
+ return 64;
+ case QCryptographicHash::Md5:
+ return 64;
+ case QCryptographicHash::Sha224:
+ return SHA224_Message_Block_Size;
+ case QCryptographicHash::Sha256:
+ return SHA256_Message_Block_Size;
+ case QCryptographicHash::Sha384:
+ return SHA384_Message_Block_Size;
+ case QCryptographicHash::Sha512:
+ return SHA512_Message_Block_Size;
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::Keccak_224:
+ return 144;
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::Keccak_256:
+ return 136;
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::Keccak_384:
+ return 104;
+ case QCryptographicHash::RealSha3_512:
+ case QCryptographicHash::Keccak_512:
+ return 72;
+ case QCryptographicHash::Blake2b_160:
+ case QCryptographicHash::Blake2b_256:
+ case QCryptographicHash::Blake2b_384:
+ case QCryptographicHash::Blake2b_512:
+ return BLAKE2B_BLOCKBYTES;
+ case QCryptographicHash::Blake2s_128:
+ case QCryptographicHash::Blake2s_160:
+ case QCryptographicHash::Blake2s_224:
+ case QCryptographicHash::Blake2s_256:
+ return BLAKE2S_BLOCKBYTES;
+#endif // QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ case QCryptographicHash::NumAlgorithms:
+#if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU >= 900
+ // GCC 8 has trouble with Q_UNREACHABLE() in constexpr functions
+ Q_UNREACHABLE();
#endif
+ break;
}
return 0;
}
+constexpr int maxHashBlockSize()
+{
+ int result = 0;
+ using A = QCryptographicHash::Algorithm;
+ for (int i = 0; i < A::NumAlgorithms ; ++i)
+ result = std::max(result, qt_hash_block_size(A(i)));
+ return result;
+}
+
+[[maybe_unused]]
+constexpr int minHashBlockSize()
+{
+ int result = INT_MAX;
+ using A = QCryptographicHash::Algorithm;
+ for (int i = 0; i < A::NumAlgorithms ; ++i)
+ result = std::min(result, qt_hash_block_size(A(i)));
+ return result;
+}
+
+[[maybe_unused]]
+constexpr int gcdHashBlockSize()
+{
+ int result = 0;
+ using A = QCryptographicHash::Algorithm;
+ for (int i = 0; i < A::NumAlgorithms ; ++i)
+ result = std::gcd(result, qt_hash_block_size(A(i)));
+ return result;
+}
+
+using HashBlock = QSmallByteArray<maxHashBlockSize()>;
+
+static HashBlock xored(const HashBlock &block, quint8 val) noexcept
+{
+ // some hints for the optimizer:
+ Q_ASSERT(block.size() >= minHashBlockSize());
+ Q_ASSERT(block.size() <= maxHashBlockSize());
+ Q_ASSERT(block.size() % gcdHashBlockSize() == 0);
+ HashBlock result;
+ result.resizeForOverwrite(block.size());
+ for (qsizetype i = 0; i < block.size(); ++i)
+ result[i] = block[i] ^ val;
+ return result;
+}
+
+class QMessageAuthenticationCodePrivate
+{
+public:
+ QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m)
+ : messageHash(m)
+ {
+ }
+
+ HashBlock key;
+ QCryptographicHashPrivate messageHash;
+
+ void setKey(QByteArrayView k) noexcept;
+ void initMessageHash() noexcept;
+ void finalize();
+
+ // when not called from the static hash() function, this function needs to be
+ // called with messageHash.finalizeMutex held:
+ void finalizeUnchecked() noexcept;
+ // END functions that need to be called with finalizeMutex held
+};
+
+/*!
+ \internal
+
+ Transforms key \a newKey into a block-sized format and stores it in member
+ \c key.
+
+ This function assumes it can use messageHash (i.e. it's in its initial
+ state (reset() has been called)).
+*/
+void QMessageAuthenticationCodePrivate::setKey(QByteArrayView newKey) noexcept
+{
+ const int blockSize = qt_hash_block_size(messageHash.method);
+
+ if (newKey.size() > blockSize) {
+ messageHash.addData(newKey);
+ messageHash.finalizeUnchecked();
+ static_assert([] {
+ using A = QCryptographicHash::Algorithm;
+ for (int i = 0; i < A::NumAlgorithms; ++i) {
+ if (hashLengthInternal(A(i)) > qt_hash_block_size(A(i)))
+ return false;
+ }
+ return true;
+ }(), "this code assumes that a hash's result always fits into that hash's block size");
+ key = messageHash.result;
+ messageHash.reset();
+ } else {
+ key.assign(newKey);
+ }
+
+ if (key.size() < blockSize)
+ key.resize(blockSize, '\0');
+
+ initMessageHash();
+}
+
+/*!
+ \internal
+
+ Seeds messageHash from \c key.
+
+ This function assumes that messageHash is in its initial state (reset() has
+ been called).
+*/
+void QMessageAuthenticationCodePrivate::initMessageHash() noexcept
+{
+ messageHash.addData(xored(key, 0x36));
+}
+
+/*!
+ \class QMessageAuthenticationCode
+ \inmodule QtCore
+
+ \brief The QMessageAuthenticationCode class provides a way to generate
+ hash-based message authentication codes.
+
+ \since 5.1
+
+ \ingroup tools
+ \reentrant
+
+ Use the QMessageAuthenticationCode class to generate hash-based message
+ authentication codes (HMACs). The class supports all cryptographic
+ hash algorithms from \l QCryptographicHash (see also
+ \l{QCryptographicHash::Algorithm}).
+
+ To generate a message authentication code, pass a suitable hash
+ algorithm and secret key to the constructor. Then process the message
+ data by calling \l addData() one or more times. After the full
+ message has been processed, get the final authentication code
+ via the \l result() function:
+
+ \snippet qmessageauthenticationcode/main.cpp 0
+ \dots
+ \snippet qmessageauthenticationcode/main.cpp 1
+
+ For simple cases like above, you can also use the static
+ \l hash() function:
+
+ \snippet qmessageauthenticationcode/main.cpp 2
+
+
+ \note The cryptographic strength of the HMAC depends upon the
+ size of the secret key, and the security of the
+ underlying hash function.
+
+ \sa QCryptographicHash, QCryptographicHash::Algorithm
+*/
+
+/*!
+ Constructs an object that can be used to create a cryptographic hash from data
+ using method \a method and key \a key.
+
+//! [qba-to-qbav-6.6]
+ \note In Qt versions prior to 6.6, this function took its arguments as
+ QByteArray, not QByteArrayView. If you experience compile errors, it's
+ because your code is passing objects that are implicitly convertible to
+ QByteArray, but not QByteArrayView. Wrap the corresponding argument in
+ \c{QByteArray{~~~}} to make the cast explicit. This is backwards-compatible
+ with old Qt versions.
+//! [qba-to-qbav-6.6]
+*/
+QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
+ QByteArrayView key)
+ : d(new QMessageAuthenticationCodePrivate(method))
+{
+ d->setKey(key);
+}
+
+/*!
+ Destroys the object.
+*/
+QMessageAuthenticationCode::~QMessageAuthenticationCode()
+{
+ delete d;
+}
+
+/*!
+ \fn QMessageAuthenticationCode::QMessageAuthenticationCode(QMessageAuthenticationCode &&other)
+
+ Move-constructs a new QMessageAuthenticationCode from \a other.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new object.
+
+ \since 6.6
+*/
+
+/*!
+ \fn QMessageAuthenticationCode &QMessageAuthenticationCode::operator=(QMessageAuthenticationCode &&other)
+
+ Move-assigns \a other to this QMessageAuthenticationCode instance.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new object.
+
+ \since 6.6
+*/
+
+/*!
+ \fn void QMessageAuthenticationCode::swap(QMessageAuthenticationCode &other)
+
+ Swaps message authentication code \a other with this message authentication
+ code. This operation is very fast and never fails.
+
+ \since 6.6
+*/
+
+/*!
+ Resets message data. Calling this function doesn't affect the key.
+*/
+void QMessageAuthenticationCode::reset() noexcept
+{
+ d->messageHash.reset();
+ d->initMessageHash();
+}
+
+/*!
+ Sets secret \a key. Calling this function automatically resets the object state.
+
+ For optimal performance, call this function only to \e change the active key,
+ not to set an \e initial key, as in
+
+ \code
+ QMessageAuthenticationCode mac(method);
+ mac.setKey(key); // does extra work
+ use(mac);
+ \endcode
+
+ Prefer to pass initial keys as the constructor argument:
+
+ \code
+ QMessageAuthenticationCode mac(method, key); // OK, optimal
+ use(mac);
+ \endcode
+
+ You can use std::optional to delay construction of a
+ QMessageAuthenticationCode until you know the key:
+
+ \code
+ std::optional<QMessageAuthenticationCode> mac;
+ ~~~
+ key = ~~~;
+ mac.emplace(method, key);
+ use(*mac);
+ \endcode
+
+ \include qcryptographichash.cpp {qba-to-qbav-6.6}
+*/
+void QMessageAuthenticationCode::setKey(QByteArrayView key) noexcept
+{
+ d->messageHash.reset();
+ d->setKey(key);
+}
+
+/*!
+ \overload
+ Adds the first \a length chars of \a data to the message.
+*/
+void QMessageAuthenticationCode::addData(const char *data, qsizetype length)
+{
+ d->messageHash.addData({data, length});
+}
+
+/*!
+ Adds \a data to the message.
+
+ \include qcryptographichash.cpp {qba-to-qbav-6.6}
+
+ \sa resultView(), result()
+*/
+void QMessageAuthenticationCode::addData(QByteArrayView data) noexcept
+{
+ d->messageHash.addData(data);
+}
+
+/*!
+ Reads the data from the open QIODevice \a device until it ends
+ and adds it to message. Returns \c true if reading was successful.
+
+ \note \a device must be already opened.
+ */
+bool QMessageAuthenticationCode::addData(QIODevice *device)
+{
+ return d->messageHash.addData(device);
+}
+
+/*!
+ \since 6.6
+
+ Returns the final hash value.
+
+ Note that the returned view remains valid only as long as the
+ QMessageAuthenticationCode object is not modified by other means.
+
+ \sa result()
+*/
+QByteArrayView QMessageAuthenticationCode::resultView() const noexcept
+{
+ d->finalize();
+ return d->messageHash.resultView();
+}
+
+/*!
+ Returns the final authentication code.
+
+ \sa resultView(), QByteArray::toHex()
+*/
+QByteArray QMessageAuthenticationCode::result() const
+{
+ return resultView().toByteArray();
+}
+
+void QMessageAuthenticationCodePrivate::finalize()
+{
+ const auto lock = qt_scoped_lock(messageHash.finalizeMutex);
+ if (!messageHash.result.isEmpty())
+ return;
+ finalizeUnchecked();
+}
+
+void QMessageAuthenticationCodePrivate::finalizeUnchecked() noexcept
+{
+ messageHash.finalizeUnchecked();
+ const HashResult hashedMessage = messageHash.result;
+
+ messageHash.reset();
+ messageHash.addData(xored(key, 0x5c));
+ messageHash.addData(hashedMessage);
+ messageHash.finalizeUnchecked();
+}
+
+/*!
+ Returns the authentication code for the message \a message using
+ the key \a key and the method \a method.
+
+ \include qcryptographichash.cpp {qba-to-qbav-6.6}
+*/
+QByteArray QMessageAuthenticationCode::hash(QByteArrayView message, QByteArrayView key,
+ QCryptographicHash::Algorithm method)
+{
+ QMessageAuthenticationCodePrivate mac(method);
+ mac.setKey(key);
+ mac.messageHash.addData(message);
+ mac.finalizeUnchecked();
+ return mac.messageHash.resultView().toByteArray();
+}
+
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h
index f76fe2d013..294453adce 100644
--- a/src/corelib/tools/qcryptographichash.h
+++ b/src/corelib/tools/qcryptographichash.h
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Richard J. Moore <rich@kde.org>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Richard J. Moore <rich@kde.org>.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCRYPTOGRAPHICHASH_H
#define QCRYPTOGRAPHICHASH_H
@@ -78,30 +43,56 @@ public:
Sha3_224 = RealSha3_224,
Sha3_256 = RealSha3_256,
Sha3_384 = RealSha3_384,
- Sha3_512 = RealSha3_512
+ Sha3_512 = RealSha3_512,
# else
Sha3_224 = Keccak_224,
Sha3_256 = Keccak_256,
Sha3_384 = Keccak_384,
- Sha3_512 = Keccak_512
+ Sha3_512 = Keccak_512,
# endif
+
+ Blake2b_160 = 15,
+ Blake2b_256,
+ Blake2b_384,
+ Blake2b_512,
+ Blake2s_128,
+ Blake2s_160,
+ Blake2s_224,
+ Blake2s_256,
#endif
+ NumAlgorithms
};
Q_ENUM(Algorithm)
explicit QCryptographicHash(Algorithm method);
+ QCryptographicHash(QCryptographicHash &&other) noexcept : d(std::exchange(other.d, nullptr)) {}
~QCryptographicHash();
- void reset();
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCryptographicHash)
+ void swap(QCryptographicHash &other) noexcept { qt_ptr_swap(d, other.d); }
+
+ void reset() noexcept;
+ [[nodiscard]] Algorithm algorithm() const noexcept;
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use the QByteArrayView overload instead")
void addData(const char *data, qsizetype length);
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 3)
void addData(const QByteArray &data);
- bool addData(QIODevice* device);
+#endif
+ void addData(QByteArrayView data) noexcept;
+ bool addData(QIODevice *device);
QByteArray result() const;
+ QByteArrayView resultView() const noexcept;
+#if QT_CORE_REMOVED_SINCE(6, 3)
static QByteArray hash(const QByteArray &data, Algorithm method);
+#endif
+ static QByteArray hash(QByteArrayView data, Algorithm method);
static int hashLength(Algorithm method);
+ static bool supportsAlgorithm(Algorithm method);
private:
Q_DISABLE_COPY(QCryptographicHash)
QCryptographicHashPrivate *d;
diff --git a/src/corelib/tools/qduplicatetracker_p.h b/src/corelib/tools/qduplicatetracker_p.h
index baf21bfd12..23465ecffe 100644
--- a/src/corelib/tools/qduplicatetracker_p.h
+++ b/src/corelib/tools/qduplicatetracker_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDUPLICATETRACKER_P_H
#define QDUPLICATETRACKER_P_H
@@ -50,11 +14,12 @@
// We mean it.
//
-#include <qglobal.h>
+#include <private/qglobal_p.h>
-#if QT_HAS_INCLUDE(<memory_resource>) && __cplusplus > 201402L
+#ifdef __cpp_lib_memory_resource
# include <unordered_set>
# include <memory_resource>
+# include <qhash.h> // for the hashing helpers
#else
# include <qset.h>
#endif
@@ -64,40 +29,70 @@ QT_BEGIN_NAMESPACE
template <typename T, size_t Prealloc = 32>
class QDuplicateTracker {
#ifdef __cpp_lib_memory_resource
- char buffer[Prealloc * sizeof(T)];
+ template <typename HT>
+ struct QHasher {
+ size_t storedSeed = QHashSeed::globalSeed();
+ size_t operator()(const HT &t) const {
+ return QHashPrivate::calculateHash(t, storedSeed);
+ }
+ };
+
+ struct node_guesstimate { void *next; size_t hash; T value; };
+ static constexpr size_t bufferSize(size_t N) {
+ return N * sizeof(void*) // bucket list
+ + N * sizeof(node_guesstimate); // nodes
+ }
+
+ char buffer[bufferSize(Prealloc)];
std::pmr::monotonic_buffer_resource res{buffer, sizeof buffer};
- std::pmr::unordered_set<T> set{&res};
+ std::pmr::unordered_set<T, QHasher<T>> set{Prealloc, &res};
#else
- QSet<T> set;
- int setSize = 0;
+ class Set : public QSet<T> {
+ qsizetype setSize = 0;
+ public:
+ explicit Set(qsizetype n) : QSet<T>{}
+ { this->reserve(n); }
+
+ auto insert(const T &e) {
+ auto it = QSet<T>::insert(e);
+ const auto n = this->size();
+ return std::pair{it, std::exchange(setSize, n) != n};
+ }
+
+ auto insert(T &&e) {
+ auto it = QSet<T>::insert(std::move(e));
+ const auto n = this->size();
+ return std::pair{it, std::exchange(setSize, n) != n};
+ }
+ };
+ Set set{Prealloc};
#endif
Q_DISABLE_COPY_MOVE(QDuplicateTracker);
public:
+ static constexpr inline bool uses_pmr =
+ #ifdef __cpp_lib_memory_resource
+ true
+ #else
+ false
+ #endif
+ ;
QDuplicateTracker() = default;
- void reserve(int n) { set.reserve(n); }
- Q_REQUIRED_RESULT bool hasSeen(const T &s)
- {
- bool inserted;
+ explicit QDuplicateTracker(qsizetype n)
#ifdef __cpp_lib_memory_resource
- inserted = set.insert(s).second;
+ : set{size_t(n), &res}
#else
- set.insert(s);
- const int n = set.size();
- inserted = qExchange(setSize, n) != n;
+ : set{n}
#endif
- return !inserted;
+ {}
+ Q_DECL_DEPRECATED_X("Pass the capacity to reserve() to the ctor instead.")
+ void reserve(qsizetype n) { set.reserve(n); }
+ [[nodiscard]] bool hasSeen(const T &s)
+ {
+ return !set.insert(s).second;
}
- Q_REQUIRED_RESULT bool hasSeen(T &&s)
+ [[nodiscard]] bool hasSeen(T &&s)
{
- bool inserted;
-#ifdef __cpp_lib_memory_resource
- inserted = set.insert(std::move(s)).second;
-#else
- set.insert(std::move(s));
- const int n = set.size();
- inserted = qExchange(setSize, n) != n;
-#endif
- return !inserted;
+ return !set.insert(std::move(s)).second;
}
template <typename C>
@@ -110,8 +105,17 @@ public:
template <typename C>
void appendTo(C &c) &&
{
- for (auto &e : set)
- c.push_back(std::move(e));
+ if constexpr (uses_pmr) {
+ while (!set.empty())
+ c.push_back(std::move(set.extract(set.begin()).value()));
+ } else {
+ return appendTo(c); // lvalue version
+ }
+ }
+
+ void clear()
+ {
+ set.clear();
}
};
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index b9bde51d21..52602a0256 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
@@ -320,7 +284,8 @@ static bool isConfigFunction(QEasingCurve::Type type)
type == QEasingCurve::TCBSpline;
}
-struct TCBPoint {
+struct TCBPoint
+{
QPointF _point;
qreal _t;
qreal _c;
@@ -482,7 +447,7 @@ struct BezierEase : public QEasingCurveFunction
{
if (_bezierCurves.constLast() == QPointF(1.0, 1.0)) {
_init = true;
- _curveCount = _bezierCurves.count() / 3;
+ _curveCount = _bezierCurves.size() / 3;
for (int i=0; i < _curveCount; i++) {
_intervals[i] = _bezierCurves.at(i * 3 + 2).x();
@@ -501,17 +466,17 @@ struct BezierEase : public QEasingCurveFunction
_curves[0].p3y = _bezierCurves.at(2).y();
} else if (i == (_curveCount - 1)) {
- _curves[i].p0x = _bezierCurves.at(_bezierCurves.count() - 4).x();
- _curves[i].p0y = _bezierCurves.at(_bezierCurves.count() - 4).y();
+ _curves[i].p0x = _bezierCurves.at(_bezierCurves.size() - 4).x();
+ _curves[i].p0y = _bezierCurves.at(_bezierCurves.size() - 4).y();
- _curves[i].p1x = _bezierCurves.at(_bezierCurves.count() - 3).x();
- _curves[i].p1y = _bezierCurves.at(_bezierCurves.count() - 3).y();
+ _curves[i].p1x = _bezierCurves.at(_bezierCurves.size() - 3).x();
+ _curves[i].p1y = _bezierCurves.at(_bezierCurves.size() - 3).y();
- _curves[i].p2x = _bezierCurves.at(_bezierCurves.count() - 2).x();
- _curves[i].p2y = _bezierCurves.at(_bezierCurves.count() - 2).y();
+ _curves[i].p2x = _bezierCurves.at(_bezierCurves.size() - 2).x();
+ _curves[i].p2y = _bezierCurves.at(_bezierCurves.size() - 2).y();
- _curves[i].p3x = _bezierCurves.at(_bezierCurves.count() - 1).x();
- _curves[i].p3y = _bezierCurves.at(_bezierCurves.count() - 1).y();
+ _curves[i].p3x = _bezierCurves.at(_bezierCurves.size() - 1).x();
+ _curves[i].p3y = _bezierCurves.at(_bezierCurves.size() - 1).y();
} else {
_curves[i].p0x = _bezierCurves.at(i * 3 - 1).x();
_curves[i].p0y = _bezierCurves.at(i * 3 - 1).y();
@@ -570,7 +535,7 @@ struct BezierEase : public QEasingCurveFunction
qreal value(qreal x) override
{
- Q_ASSERT(_bezierCurves.count() % 3 == 0);
+ Q_ASSERT(_bezierCurves.size() % 3 == 0);
if (_bezierCurves.isEmpty()) {
return x;
@@ -605,8 +570,8 @@ struct BezierEase : public QEasingCurveFunction
const qreal s = 1 - t;
- const qreal s_squared = s*s;
- const qreal t_squared = t*t;
+ const qreal s_squared = s * s;
+ const qreal t_squared = t * t;
const qreal s_cubic = s_squared * s;
const qreal t_cubic = t_squared * t;
@@ -623,8 +588,8 @@ struct BezierEase : public QEasingCurveFunction
const qreal s = 1 - t;
- const qreal s_squared = s*s;
- const qreal t_squared = t*t;
+ const qreal s_squared = s * s;
+ const qreal t_squared = t * t;
const qreal s_cubic = s_squared * s;
const qreal t_cubic = t_squared * t;
@@ -639,7 +604,7 @@ struct BezierEase : public QEasingCurveFunction
const qreal p2 = singleCubicBezier.p2x;
const qreal p3 = singleCubicBezier.p3x;
- const qreal t_squared = t*t;
+ const qreal t_squared = t * t;
return -3*p0 + 3*p1 + 6*p0*t - 12*p1*t + 6*p2*t + 3*p3*t_squared - 3*p0*t_squared + 9*p1*t_squared - 9*p2*t_squared;
}
@@ -739,7 +704,7 @@ struct BezierEase : public QEasingCurveFunction
qreal cos = b * x - a * x_squared;
if (cos < 0)
- return 0.225 * (cos * 1 *-cos - cos) + cos;
+ return 0.225 * (cos * 1 * -cos - cos) + cos;
return 0.225 * (cos * cos - cos) + cos;
}
@@ -794,15 +759,15 @@ struct BezierEase : public QEasingCurveFunction
if (D >= 0) {
const qreal D_sqrt = qSqrt(D);
- qreal u = _cbrt( -q * 0.5 + D_sqrt);
- qreal v = _cbrt( -q * 0.5 - D_sqrt);
+ qreal u = _cbrt(-q * 0.5 + D_sqrt);
+ qreal v = _cbrt(-q * 0.5 - D_sqrt);
qreal z1 = u + v;
qreal t1 = z1 - a_by3;
if (inRange(t1))
return t1;
- qreal z2 = -1 *u;
+ qreal z2 = -1 * u;
qreal t2 = z2 - a_by3;
return t2;
}
@@ -825,7 +790,7 @@ struct BezierEase : public QEasingCurveFunction
cosacos(g, s1, s2, s3);
- qreal z1 = -1* f * s2;
+ qreal z1 = -1 * f * s2;
qreal t1 = z1 - a_by3;
if (inRange(t1))
return t1;
@@ -904,7 +869,7 @@ struct TCBEase : public BezierEase
qreal value(qreal x) override
{
- Q_ASSERT(_bezierCurves.count() % 3 == 0);
+ Q_ASSERT(_bezierCurves.size() % 3 == 0);
if (_bezierCurves.isEmpty()) {
qWarning("QEasingCurve: Invalid tcb curve");
@@ -940,7 +905,7 @@ struct ElasticEase : public QEasingCurveFunction
{
qreal p = (_p < 0) ? qreal(0.3) : _p;
qreal a = (_a < 0) ? qreal(1.0) : _a;
- switch(_t) {
+ switch (_t) {
case QEasingCurve::InElastic:
return easeInElastic(t, a, p);
case QEasingCurve::OutElastic:
@@ -973,7 +938,7 @@ struct BounceEase : public QEasingCurveFunction
qreal value(qreal t) override
{
qreal a = (_a < 0) ? qreal(1.0) : _a;
- switch(_t) {
+ switch (_t) {
case QEasingCurve::InBounce:
return easeInBounce(t, a);
case QEasingCurve::OutBounce:
@@ -1011,7 +976,7 @@ struct BackEase : public QEasingCurveFunction
if (!(t < 1))
return 1;
qreal o = (_o < 0) ? qreal(1.70158) : _o;
- switch(_t) {
+ switch (_t) {
case QEasingCurve::InBack:
return easeInBack(t, o);
case QEasingCurve::OutBack:
@@ -1028,7 +993,7 @@ struct BackEase : public QEasingCurveFunction
static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
{
- switch(curve) {
+ switch (curve) {
case QEasingCurve::Linear:
return &easeNone;
case QEasingCurve::InQuad:
@@ -1087,7 +1052,7 @@ static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
return &easeInOutCirc;
case QEasingCurve::OutInCirc:
return &easeOutInCirc;
- // Internal for, compatibility with QTimeLine only ??
+ // Internal - needed for QTimeLine backward-compatibility:
case QEasingCurve::InCurve:
return &easeInCurve;
case QEasingCurve::OutCurve:
@@ -1103,7 +1068,7 @@ static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type)
{
- switch(type) {
+ switch (type) {
case QEasingCurve::InElastic:
case QEasingCurve::OutElastic:
case QEasingCurve::InOutElastic:
@@ -1188,32 +1153,37 @@ QEasingCurve::~QEasingCurve()
*/
/*!
- Compare this easing curve with \a other and returns \c true if they are
- equal. It will also compare the properties of a curve.
+ \fn bool QEasingCurve::operator==(const QEasingCurve &lhs, const QEasingCurve &rhs)
+
+ Compares easing curve \a lhs with \a rhs and returns \c true if they are
+ equal; otherwise returns \c false.
+ It will also compare the properties of the curves.
*/
-bool QEasingCurve::operator==(const QEasingCurve &other) const
+bool comparesEqual(const QEasingCurve &lhs, const QEasingCurve &rhs) noexcept
{
- bool res = d_ptr->func == other.d_ptr->func
- && d_ptr->type == other.d_ptr->type;
+ bool res = lhs.d_ptr->func == rhs.d_ptr->func
+ && lhs.d_ptr->type == rhs.d_ptr->type;
if (res) {
- if (d_ptr->config && other.d_ptr->config) {
- // catch the config content
- res = d_ptr->config->operator==(*(other.d_ptr->config));
-
- } else if (d_ptr->config || other.d_ptr->config) {
- // one one has a config object, which could contain default values
- res = qFuzzyCompare(amplitude(), other.amplitude()) &&
- qFuzzyCompare(period(), other.period()) &&
- qFuzzyCompare(overshoot(), other.overshoot());
+ if (lhs.d_ptr->config && rhs.d_ptr->config) {
+ // catch the config content
+ res = lhs.d_ptr->config->operator==(*(rhs.d_ptr->config));
+
+ } else if (lhs.d_ptr->config || rhs.d_ptr->config) {
+ // one one has a config object, which could contain default values
+ res = qFuzzyCompare(lhs.amplitude(), rhs.amplitude())
+ && qFuzzyCompare(lhs.period(), rhs.period())
+ && qFuzzyCompare(lhs.overshoot(), rhs.overshoot());
}
}
return res;
}
/*!
- \fn bool QEasingCurve::operator!=(const QEasingCurve &other) const
- Compare this easing curve with \a other and returns \c true if they are not equal.
- It will also compare the properties of a curve.
+ \fn bool QEasingCurve::operator!=(const QEasingCurve &lhs, const QEasingCurve &rhs)
+
+ Compares easing curve \a lhs with \a rhs and returns \c true if they are
+ not equal; otherwise returns \c false.
+ It will also compare the properties of the curves.
\sa operator==()
*/
@@ -1275,7 +1245,7 @@ void QEasingCurve::setPeriod(qreal period)
*/
qreal QEasingCurve::overshoot() const
{
- return d_ptr->config ? d_ptr->config->_o : qreal(1.70158) ;
+ return d_ptr->config ? d_ptr->config->_o : qreal(1.70158);
}
/*!
@@ -1309,7 +1279,7 @@ void QEasingCurve::addCubicBezierSegment(const QPointF & c1, const QPointF & c2,
QList<QPointF> static inline tcbToBezier(const TCBPoints &tcbPoints)
{
- const int count = tcbPoints.count();
+ const int count = tcbPoints.size();
QList<QPointF> bezierPoints;
bezierPoints.reserve(3 * (count - 1));
@@ -1356,7 +1326,7 @@ QList<QPointF> static inline tcbToBezier(const TCBPoints &tcbPoints)
/*!
Adds a segment of a TCB bezier spline to define a custom easing curve.
It is only applicable if type() is QEasingCurve::TCBSpline.
- The spline has to start explitly at (0.0, 0.0) and has to end at (1.0, 1.0) to
+ The spline has to start explicitly at (0.0, 0.0) and has to end at (1.0, 1.0) to
be a valid easing curve.
The tension \a t changes the length of the tangent vector.
The continuity \a c changes the sharpness in change between the tangents.
@@ -1372,7 +1342,7 @@ void QEasingCurve::addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qre
if (!d_ptr->config)
d_ptr->config = curveToFunctionObject(d_ptr->type);
- d_ptr->config->_tcbPoints.append(TCBPoint(nextPoint, t, c ,b));
+ d_ptr->config->_tcbPoints.append(TCBPoint(nextPoint, t, c, b));
if (nextPoint == QPointF(1.0, 1.0)) {
d_ptr->config->_bezierCurves = tcbToBezier(d_ptr->config->_tcbPoints);
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
index e6ee7b56d5..61e9aa247d 100644
--- a/src/corelib/tools/qeasingcurve.h
+++ b/src/corelib/tools/qeasingcurve.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEASINGCURVE_H
#define QEASINGCURVE_H
@@ -44,12 +8,12 @@
QT_REQUIRE_CONFIG(easingcurve);
+#include <QtCore/qcompare.h>
#include <QtCore/qlist.h>
#include <QtCore/qobjectdefs.h>
QT_BEGIN_NAMESPACE
-
class QEasingCurvePrivate;
class QPointF;
class Q_CORE_EXPORT QEasingCurve
@@ -80,14 +44,15 @@ public:
QEasingCurve &operator=(const QEasingCurve &other)
{ if ( this != &other ) { QEasingCurve copy(other); swap(copy); } return *this; }
QEasingCurve(QEasingCurve &&other) noexcept : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
- QEasingCurve &operator=(QEasingCurve &&other) noexcept
- { qSwap(d_ptr, other.d_ptr); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QEasingCurve)
- void swap(QEasingCurve &other) noexcept { qSwap(d_ptr, other.d_ptr); }
+ void swap(QEasingCurve &other) noexcept { qt_ptr_swap(d_ptr, other.d_ptr); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QEasingCurve &other) const;
inline bool operator!=(const QEasingCurve &other) const
{ return !(this->operator==(other)); }
+#endif
qreal amplitude() const;
void setAmplitude(qreal amplitude);
@@ -98,7 +63,7 @@ public:
qreal overshoot() const;
void setOvershoot(qreal overshoot);
- void addCubicBezierSegment(const QPointF & c1, const QPointF & c2, const QPointF & endPoint);
+ void addCubicBezierSegment(const QPointF &c1, const QPointF &c2, const QPointF &endPoint);
void addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qreal b);
QList<QPointF> toCubicSpline() const;
@@ -109,15 +74,21 @@ public:
EasingFunction customType() const;
qreal valueForProgress(qreal progress) const;
+
private:
QEasingCurvePrivate *d_ptr;
#ifndef QT_NO_DEBUG_STREAM
friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
#endif
#ifndef QT_NO_DATASTREAM
- friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve&);
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve &);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QEasingCurve &);
#endif
+ friend Q_CORE_EXPORT bool
+ comparesEqual(const QEasingCurve &lhs, const QEasingCurve &rhs) noexcept;
+#if !QT_CORE_REMOVED_SINCE(6, 8)
+ Q_DECLARE_EQUALITY_COMPARABLE(QEasingCurve)
+#endif
};
Q_DECLARE_SHARED(QEasingCurve)
@@ -126,7 +97,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
#endif
#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve&);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QEasingCurve &);
#endif
diff --git a/src/corelib/tools/qflatmap_p.h b/src/corelib/tools/qflatmap_p.h
index bf0efb2543..d2c0d45b79 100644
--- a/src/corelib/tools/qflatmap_p.h
+++ b/src/corelib/tools/qflatmap_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFLATMAP_P_H
#define QFLATMAP_P_H
@@ -52,6 +16,7 @@
//
#include "qlist.h"
+#include "private/qglobal_p.h"
#include <algorithm>
#include <functional>
@@ -77,6 +42,19 @@ QT_BEGIN_NAMESPACE
QFlatMap<float, int, std::less<float>, std::vector<float>, std::vector<int>>
*/
+// Qt 6.4:
+// - removed QFlatMap API which was incompatible with STL semantics
+// - will be released with said API disabled, to catch any out-of-tree users
+// - also allows opting in to the new API using QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
+// Qt 6.5
+// - will make QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT the default:
+
+#ifndef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
+# if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
+# define QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
+# endif
+#endif
+
namespace Qt {
struct OrderedUniqueRange_t {};
@@ -96,7 +74,7 @@ public:
using value_type = std::pair<const Key, T>;
static constexpr bool is_comparator_noexcept = noexcept(
- std::declval<Compare>()(std::declval<Key>(), std::declval<Key>()));
+ std::declval<Compare>()(std::declval<const Key &>(), std::declval<const Key &>()));
bool operator()(const value_type &lhs, const value_type &rhs) const
noexcept(is_comparator_noexcept)
@@ -105,27 +83,34 @@ public:
}
};
+namespace qflatmap {
+namespace detail {
+template <class T>
+class QFlatMapMockPointer
+{
+ T ref;
+public:
+ QFlatMapMockPointer(T r)
+ : ref(r)
+ {
+ }
+
+ T *operator->()
+ {
+ return &ref;
+ }
+};
+} // namespace detail
+} // namespace qflatmap
+
template<class Key, class T, class Compare = std::less<Key>, class KeyContainer = QList<Key>,
class MappedContainer = QList<T>>
class QFlatMap : private QFlatMapValueCompare<Key, T, Compare>
{
- using full_map_t = QFlatMap<Key, T, Compare, KeyContainer, MappedContainer>;
-
- template <class U>
- class mock_pointer
- {
- U ref;
- public:
- mock_pointer(U r)
- : ref(r)
- {
- }
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
- U *operator->()
- {
- return &ref;
- }
- };
+ template<class U>
+ using mock_pointer = qflatmap::detail::QFlatMapMockPointer<U>;
public:
using key_type = Key;
@@ -159,12 +144,12 @@ public:
{
}
- reference operator*()
+ reference operator*() const
{
return { c->keys[i], c->values[i] };
}
- pointer operator->()
+ pointer operator->() const
{
return { operator*() };
}
@@ -189,7 +174,7 @@ public:
{
iterator r = *this;
- i++;
+ ++*this;
return r;
}
@@ -202,7 +187,7 @@ public:
iterator operator--(int)
{
iterator r = *this;
- i--;
+ --*this;
return r;
}
@@ -240,7 +225,7 @@ public:
return b.i - a.i;
}
- reference operator[](size_type n)
+ reference operator[](size_type n) const
{
size_type k = i + n;
return { c->keys[k], c->values[k] };
@@ -267,12 +252,12 @@ public:
}
const Key &key() const { return c->keys[i]; }
- T &value() { return c->values[i]; }
+ T &value() const { return c->values[i]; }
private:
containers *c = nullptr;
size_type i = 0;
- friend full_map_t;
+ friend QFlatMap;
};
class const_iterator
@@ -296,12 +281,12 @@ public:
{
}
- reference operator*()
+ reference operator*() const
{
return { c->keys[i], c->values[i] };
}
- pointer operator->()
+ pointer operator->() const
{
return { operator*() };
}
@@ -326,7 +311,7 @@ public:
{
const_iterator r = *this;
- i++;
+ ++*this;
return r;
}
@@ -339,7 +324,7 @@ public:
const_iterator operator--(int)
{
const_iterator r = *this;
- i--;
+ --*this;
return r;
}
@@ -377,7 +362,7 @@ public:
return b.i - a.i;
}
- reference operator[](size_type n)
+ reference operator[](size_type n) const
{
size_type k = i + n;
return { c->keys[k], c->values[k] };
@@ -404,12 +389,12 @@ public:
}
const Key &key() const { return c->keys[i]; }
- const T &value() { return c->values[i]; }
+ const T &value() const { return c->values[i]; }
private:
const containers *c = nullptr;
size_type i = 0;
- friend full_map_t;
+ friend QFlatMap;
};
private:
@@ -417,7 +402,7 @@ private:
struct is_marked_transparent_type : std::false_type { };
template <class X>
- struct is_marked_transparent_type<X, typename X::is_transparent> : std::true_type { };
+ struct is_marked_transparent_type<X, std::void_t<typename X::is_transparent>> : std::true_type { };
template <class X>
using is_marked_transparent = typename std::enable_if<
@@ -430,6 +415,7 @@ private:
public:
QFlatMap() = default;
+#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
explicit QFlatMap(const key_container_type &keys, const mapped_container_type &values)
: c{keys, values}
{
@@ -437,23 +423,20 @@ public:
}
explicit QFlatMap(key_container_type &&keys, const mapped_container_type &values)
+ : c{std::move(keys), values}
{
- c.keys = std::move(keys);
- c.values = values;
ensureOrderedUnique();
}
explicit QFlatMap(const key_container_type &keys, mapped_container_type &&values)
+ : c{keys, std::move(values)}
{
- c.keys = keys;
- c.values = std::move(values);
ensureOrderedUnique();
}
explicit QFlatMap(key_container_type &&keys, mapped_container_type &&values)
+ : c{std::move(keys), std::move(values)}
{
- c.keys = std::move(keys);
- c.values = std::move(values);
ensureOrderedUnique();
}
@@ -468,37 +451,34 @@ public:
initWithRange(first, last);
ensureOrderedUnique();
}
+#endif
explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
const mapped_container_type &values)
+ : c{keys, values}
{
- c.keys = keys;
- c.values = values;
}
explicit QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys,
const mapped_container_type &values)
+ : c{std::move(keys), values}
{
- c.keys = std::move(keys);
- c.values = values;
}
explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
mapped_container_type &&values)
+ : c{keys, std::move(values)}
{
- c.keys = keys;
- c.values = std::move(values);
}
explicit QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys,
mapped_container_type &&values)
+ : c{std::move(keys), std::move(values)}
{
- c.keys = std::move(keys);
- c.values = std::move(values);
}
explicit QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list<value_type> lst)
- : QFlatMap(lst.begin(), lst.end())
+ : QFlatMap(Qt::OrderedUniqueRange, lst.begin(), lst.end())
{
}
@@ -513,6 +493,7 @@ public:
{
}
+#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
explicit QFlatMap(const key_container_type &keys, const mapped_container_type &values,
const Compare &compare)
: value_compare(compare), c{keys, values}
@@ -553,6 +534,7 @@ public:
initWithRange(first, last);
ensureOrderedUnique();
}
+#endif
explicit QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys,
const mapped_container_type &values, const Compare &compare)
@@ -614,13 +596,13 @@ public:
bool remove(const Key &key)
{
- auto it = binary_find(key);
- if (it != end()) {
- c.keys.erase(toKeysIterator(it));
- c.values.erase(toValuesIterator(it));
- return true;
- }
- return false;
+ return do_remove(find(key));
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ bool remove(const X &key)
+ {
+ return do_remove(find(key));
}
iterator erase(iterator it)
@@ -631,50 +613,60 @@ public:
T take(const Key &key)
{
- auto it = binary_find(key);
- if (it != end()) {
- T result = std::move(it.value());
- erase(it);
- return result;
- }
- return {};
+ return do_take(find(key));
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ T take(const X &key)
+ {
+ return do_take(find(key));
}
bool contains(const Key &key) const
{
- return binary_find(key) != end();
+ return find(key) != end();
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ bool contains(const X &key) const
+ {
+ return find(key) != end();
}
T value(const Key &key, const T &defaultValue) const
{
- auto it = binary_find(key);
+ auto it = find(key);
+ return it == end() ? defaultValue : it.value();
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ T value(const X &key, const T &defaultValue) const
+ {
+ auto it = find(key);
return it == end() ? defaultValue : it.value();
}
T value(const Key &key) const
{
- auto it = binary_find(key);
+ auto it = find(key);
+ return it == end() ? T() : it.value();
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ T value(const X &key) const
+ {
+ auto it = find(key);
return it == end() ? T() : it.value();
}
T &operator[](const Key &key)
{
- auto it = lower_bound(key);
- if (it == end() || key_compare::operator()(key, it.key())) {
- c.keys.insert(toKeysIterator(it), key);
- return *c.values.insert(toValuesIterator(it), T());
- }
- return it.value();
+ return try_emplace(key).first.value();
}
T &operator[](Key &&key)
{
- auto it = lower_bound(key);
- if (it == end() || key_compare::operator()(key, it.key())) {
- c.keys.insert(toKeysIterator(it), key);
- return *c.values.insert(toValuesIterator(it), T());
- }
- return it.value();
+ return try_emplace(std::move(key)).first.value();
}
T operator[](const Key &key) const
@@ -682,55 +674,71 @@ public:
return value(key);
}
+#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
std::pair<iterator, bool> insert(const Key &key, const T &value)
{
- auto it = lower_bound(key);
- if (it == end() || key_compare::operator()(key, it.key())) {
- c.values.insert(toValuesIterator(it), value);
- auto k = c.keys.insert(toKeysIterator(it), key);
- return { fromKeysIterator(k), true };
- } else {
- it.value() = value;
- return {it, false};
- }
+ return try_emplace(key, value);
}
std::pair<iterator, bool> insert(Key &&key, const T &value)
{
- auto it = lower_bound(key);
- if (it == end() || key_compare::operator()(key, it.key())) {
- c.values.insert(toValuesIterator(it), value);
- return { c.keys.insert(it, std::move(key)), true };
- } else {
- *toValuesIterator(it) = value;
- return {it, false};
- }
+ return try_emplace(std::move(key), value);
}
std::pair<iterator, bool> insert(const Key &key, T &&value)
{
+ return try_emplace(key, std::move(value));
+ }
+
+ std::pair<iterator, bool> insert(Key &&key, T &&value)
+ {
+ return try_emplace(std::move(key), std::move(value));
+ }
+#endif
+
+ template <typename...Args>
+ std::pair<iterator, bool> try_emplace(const Key &key, Args&&...args)
+ {
auto it = lower_bound(key);
if (it == end() || key_compare::operator()(key, it.key())) {
- c.values.insert(toValuesIterator(it), std::move(value));
- return { c.keys.insert(it, key), true };
+ c.values.emplace(toValuesIterator(it), std::forward<Args>(args)...);
+ return { fromKeysIterator(c.keys.insert(toKeysIterator(it), key)), true };
} else {
- *toValuesIterator(it) = std::move(value);
return {it, false};
}
}
- std::pair<iterator, bool> insert(Key &&key, T &&value)
+ template <typename...Args>
+ std::pair<iterator, bool> try_emplace(Key &&key, Args&&...args)
{
auto it = lower_bound(key);
if (it == end() || key_compare::operator()(key, it.key())) {
- c.values.insert(toValuesIterator(it), std::move(value));
+ c.values.emplace(toValuesIterator(it), std::forward<Args>(args)...);
return { fromKeysIterator(c.keys.insert(toKeysIterator(it), std::move(key))), true };
} else {
- *toValuesIterator(it) = std::move(value);
return {it, false};
}
}
+ template <typename M>
+ std::pair<iterator, bool> insert_or_assign(const Key &key, M &&obj)
+ {
+ auto r = try_emplace(key, std::forward<M>(obj));
+ if (!r.second)
+ *toValuesIterator(r.first) = std::forward<M>(obj);
+ return r;
+ }
+
+ template <typename M>
+ std::pair<iterator, bool> insert_or_assign(Key &&key, M &&obj)
+ {
+ auto r = try_emplace(std::move(key), std::forward<M>(obj));
+ if (!r.second)
+ *toValuesIterator(r.first) = std::forward<M>(obj);
+ return r;
+ }
+
+#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
void insert(InputIt first, InputIt last)
{
@@ -756,6 +764,7 @@ public:
{
insertOrderedUniqueRange(first, last);
}
+#endif
iterator begin() { return { &c, 0 }; }
const_iterator begin() const { return { &c, 0 }; }
@@ -782,14 +791,14 @@ public:
iterator lower_bound(const Key &key)
{
- auto cit = const_cast<const full_map_t *>(this)->lower_bound(key);
+ auto cit = std::as_const(*this).lower_bound(key);
return { &c, cit.i };
}
template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
iterator lower_bound(const X &key)
{
- auto cit = const_cast<const full_map_t *>(this)->lower_bound(key);
+ auto cit = std::as_const(*this).lower_bound(key);
return { &c, cit.i };
}
@@ -804,14 +813,112 @@ public:
return fromKeysIterator(std::lower_bound(c.keys.begin(), c.keys.end(), key, key_comp()));
}
- iterator find(const key_type &k)
+ iterator find(const Key &key)
+ {
+ return { &c, std::as_const(*this).find(key).i };
+ }
+
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ iterator find(const X &key)
+ {
+ return { &c, std::as_const(*this).find(key).i };
+ }
+
+ const_iterator find(const Key &key) const
{
- return binary_find(k);
+ auto it = lower_bound(key);
+ if (it != end()) {
+ if (!key_compare::operator()(key, it.key()))
+ return it;
+ it = end();
+ }
+ return it;
}
- const_iterator find(const key_type &k) const
+ template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
+ const_iterator find(const X &key) const
{
- return binary_find(k);
+ auto it = lower_bound(key);
+ if (it != end()) {
+ if (!key_compare::operator()(key, it.key()))
+ return it;
+ it = end();
+ }
+ return it;
+ }
+
+ template <typename Predicate>
+ size_type remove_if(Predicate pred)
+ {
+ const auto indirect_call_to_pred = [pred = std::move(pred)](iterator it) {
+ using Pair = decltype(*it);
+ using K = decltype(it.key());
+ using V = decltype(it.value());
+ using P = Predicate;
+ if constexpr (std::is_invocable_v<P, K, V>) {
+ return pred(it.key(), it.value());
+ } else if constexpr (std::is_invocable_v<P, Pair> && !std::is_invocable_v<P, K>) {
+ return pred(*it);
+ } else if constexpr (std::is_invocable_v<P, K> && !std::is_invocable_v<P, Pair>) {
+ return pred(it.key());
+ } else {
+ static_assert(QtPrivate::type_dependent_false<Predicate>(),
+ "Don't know how to call the predicate.\n"
+ "Options:\n"
+ "- pred(*it)\n"
+ "- pred(it.key(), it.value())\n"
+ "- pred(it.key())");
+ }
+ };
+
+ auto first = begin();
+ const auto last = end();
+
+ // find_if prefix loop
+ while (first != last && !indirect_call_to_pred(first))
+ ++first;
+
+ if (first == last)
+ return 0; // nothing to do
+
+ // we know that we need to remove *first
+
+ auto kdest = toKeysIterator(first);
+ auto vdest = toValuesIterator(first);
+
+ ++first;
+
+ auto k = std::next(kdest);
+ auto v = std::next(vdest);
+
+ // Main Loop
+ // - first is used only for indirect_call_to_pred
+ // - operations are done on k, v
+ // Loop invariants:
+ // - first, k, v are pointing to the same element
+ // - [begin(), first[, [c.keys.begin(), k[, [c.values.begin(), v[: already processed
+ // - [first, end()[, [k, c.keys.end()[, [v, c.values.end()[: still to be processed
+ // - [c.keys.begin(), kdest[ and [c.values.begin(), vdest[ are keepers
+ // - [kdest, k[, [vdest, v[ are considered removed
+ // - kdest is not c.keys.end()
+ // - vdest is not v.values.end()
+ while (first != last) {
+ if (!indirect_call_to_pred(first)) {
+ // keep *first, aka {*k, *v}
+ *kdest = std::move(*k);
+ *vdest = std::move(*v);
+ ++kdest;
+ ++vdest;
+ }
+ ++k;
+ ++v;
+ ++first;
+ }
+
+ const size_type r = std::distance(kdest, c.keys.end());
+ c.keys.erase(kdest, c.keys.end());
+ c.values.erase(vdest, c.values.end());
+ return r;
}
key_compare key_comp() const noexcept
@@ -825,6 +932,25 @@ public:
}
private:
+ bool do_remove(iterator it)
+ {
+ if (it != end()) {
+ erase(it);
+ return true;
+ }
+ return false;
+ }
+
+ T do_take(iterator it)
+ {
+ if (it != end()) {
+ T result = std::move(it.value());
+ erase(it);
+ return result;
+ }
+ return {};
+ }
+
template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
void initWithRange(InputIt first, InputIt last)
{
@@ -872,7 +998,7 @@ private:
class IndexedKeyComparator
{
public:
- IndexedKeyComparator(const full_map_t *am)
+ IndexedKeyComparator(const QFlatMap *am)
: m(am)
{
}
@@ -883,7 +1009,7 @@ private:
}
private:
- const full_map_t *m;
+ const QFlatMap *m;
};
template <class InputIt>
@@ -904,22 +1030,6 @@ private:
makeUnique();
}
- iterator binary_find(const Key &key)
- {
- return { &c, const_cast<const full_map_t *>(this)->binary_find(key).i };
- }
-
- const_iterator binary_find(const Key &key) const
- {
- auto it = lower_bound(key);
- if (it != end()) {
- if (!key_compare::operator()(key, it.key()))
- return it;
- it = end();
- }
- return it;
- }
-
void ensureOrderedUnique()
{
std::vector<size_type> p(size_t(c.keys.size()));
@@ -951,31 +1061,49 @@ private:
void makeUnique()
{
- if (c.keys.size() < 2)
+ // std::unique, but over two ranges
+ auto equivalent = [this](const auto &lhs, const auto &rhs) {
+ return !key_compare::operator()(lhs, rhs) && !key_compare::operator()(rhs, lhs);
+ };
+ const auto kb = c.keys.begin();
+ const auto ke = c.keys.end();
+ auto k = std::adjacent_find(kb, ke, equivalent);
+ if (k == ke)
return;
- auto k = std::end(c.keys) - 1;
- auto i = k - 1;
- for (;;) {
- if (key_compare::operator()(*i, *k) || key_compare::operator()(*k, *i)) {
- if (i == std::begin(c.keys))
- break;
- --i;
- --k;
- } else {
- c.values.erase(std::begin(c.values) + std::distance(std::begin(c.keys), i));
- i = c.keys.erase(i);
- if (i == std::begin(c.keys))
- break;
- k = i + 1;
+
+ // equivalent keys found, we need to do actual work:
+ auto v = std::next(c.values.begin(), std::distance(kb, k));
+
+ auto kdest = k;
+ auto vdest = v;
+
+ ++k;
+ ++v;
+
+ // Loop Invariants:
+ //
+ // - [keys.begin(), kdest] and [values.begin(), vdest] are unique
+ // - k is not keys.end(), v is not values.end()
+ // - [next(k), keys.end()[ and [next(v), values.end()[ still need to be checked
+ while ((++v, ++k) != ke) {
+ if (!equivalent(*kdest, *k)) {
+ *++kdest = std::move(*k);
+ *++vdest = std::move(*v);
}
}
- c.keys.shrink_to_fit();
- c.values.shrink_to_fit();
+
+ c.keys.erase(std::next(kdest), ke);
+ c.values.erase(std::next(vdest), c.values.end());
}
containers c;
};
+template <class Key, class T,
+ qsizetype N = QVarLengthArrayDefaultPrealloc,
+ class Compare = std::less<Key>>
+using QVarLengthFlatMap = QFlatMap<Key, T, Compare, QVarLengthArray<Key, N>, QVarLengthArray<T, N>>;
+
QT_END_NAMESPACE
#endif // QFLATMAP_P_H
diff --git a/src/corelib/tools/qfreelist.cpp b/src/corelib/tools/qfreelist.cpp
index dd584413fc..db15fac5d6 100644
--- a/src/corelib/tools/qfreelist.cpp
+++ b/src/corelib/tools/qfreelist.cpp
@@ -1,64 +1,30 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfreelist_p.h"
QT_BEGIN_NAMESPACE
// default sizes and offsets (no need to define these when customizing)
+namespace QFreeListDefaultConstantsPrivate {
enum {
Offset0 = 0x00000000,
Offset1 = 0x00008000,
Offset2 = 0x00080000,
Offset3 = 0x00800000,
- Size0 = Offset1 - Offset0,
- Size1 = Offset2 - Offset1,
- Size2 = Offset3 - Offset2,
+ Size0 = Offset1 - Offset0,
+ Size1 = Offset2 - Offset1,
+ Size2 = Offset3 - Offset2,
Size3 = QFreeListDefaultConstants::MaxIndex - Offset3
};
+}
-const int QFreeListDefaultConstants::Sizes[QFreeListDefaultConstants::BlockCount] = {
- Size0,
- Size1,
- Size2,
- Size3
+Q_CONSTINIT const int QFreeListDefaultConstants::Sizes[QFreeListDefaultConstants::BlockCount] = {
+ QFreeListDefaultConstantsPrivate::Size0,
+ QFreeListDefaultConstantsPrivate::Size1,
+ QFreeListDefaultConstantsPrivate::Size2,
+ QFreeListDefaultConstantsPrivate::Size3
};
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
index 5ba23b344b..6bbde5b4b6 100644
--- a/src/corelib/tools/qfreelist_p.h
+++ b/src/corelib/tools/qfreelist_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFREELIST_P_H
#define QFREELIST_P_H
@@ -56,7 +20,6 @@
QT_BEGIN_NAMESPACE
-
/*! \internal
Element in a QFreeList. ConstReferenceType and ReferenceType are used as
@@ -161,8 +124,7 @@ class QFreeList
return i;
x -= size;
}
- Q_ASSERT(false);
- return -1;
+ Q_UNREACHABLE_RETURN(-1);
}
// allocate a block of the given \a size, initialized starting with the given \a offset
@@ -190,7 +152,7 @@ class QFreeList
Q_DISABLE_COPY_MOVE(QFreeList)
public:
- Q_DECL_CONSTEXPR inline QFreeList();
+ constexpr inline QFreeList();
inline ~QFreeList();
// returns the payload for the given index \a x
@@ -206,11 +168,9 @@ public:
};
template <typename T, typename ConstantsType>
-Q_DECL_CONSTEXPR inline QFreeList<T, ConstantsType>::QFreeList()
+constexpr inline QFreeList<T, ConstantsType>::QFreeList()
:
-#if defined(Q_COMPILER_CONSTEXPR)
_v{}, // uniform initialization required
-#endif
_next(ConstantsType::InitialNextValue)
{ }
@@ -251,7 +211,7 @@ inline int QFreeList<T, ConstantsType>::next()
v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
if (!_v[block].testAndSetRelease(nullptr, v)) {
// race with another thread lost
- delete [] v;
+ delete[] v;
v = _v[block].loadAcquire();
Q_ASSERT(v != nullptr);
}
diff --git a/src/corelib/tools/qfunctionaltools_impl.cpp b/src/corelib/tools/qfunctionaltools_impl.cpp
new file mode 100644
index 0000000000..28148c39a2
--- /dev/null
+++ b/src/corelib/tools/qfunctionaltools_impl.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qfunctionaltools_impl.h>
+
+// Remove this file once we have tests that implicitly test all aspects of
+// CompactStorage
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+#define FOR_EACH_CVREF(op) \
+ op(&) \
+ op(const &) \
+ op(&&) \
+ op(const &&) \
+ /* end */
+
+namespace _testing {
+ struct empty {};
+ struct final final {};
+ static_assert(std::is_same_v<CompactStorage<empty>,
+ detail::StorageEmptyBaseClassOptimization<empty>>);
+ static_assert(std::is_same_v<CompactStorage<final>,
+ detail::StorageByValue<final>>);
+ static_assert(std::is_same_v<CompactStorage<int>,
+ detail::StorageByValue<int>>);
+#define CHECK1(Obj, cvref) \
+ static_assert(std::is_same_v<decltype(std::declval<CompactStorage< Obj > cvref>().object()), \
+ Obj cvref>);
+#define CHECK(cvref) \
+ CHECK1(empty, cvref) \
+ CHECK1(final, cvref) \
+ CHECK1(int, cvref) \
+ /* end */
+
+ FOR_EACH_CVREF(CHECK)
+#undef CHECK
+#undef CHECK1
+} // namespace _testing
+
+} // namespace QtPrivate
+
+#undef FOR_EACH_CVREF
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qfunctionaltools_impl.h b/src/corelib/tools/qfunctionaltools_impl.h
new file mode 100644
index 0000000000..0942d5fe7d
--- /dev/null
+++ b/src/corelib/tools/qfunctionaltools_impl.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#if 0
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
+#endif
+
+#ifndef QFUNCTIONALTOOLS_IMPL_H
+#define QFUNCTIONALTOOLS_IMPL_H
+
+#include <QtCore/qtconfigmacros.h>
+
+#include <type_traits>
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+namespace detail {
+
+#define FOR_EACH_CVREF(op) \
+ op(&) \
+ op(const &) \
+ op(&&) \
+ op(const &&) \
+ /* end */
+
+
+template <typename Object, typename = void>
+struct StorageByValue
+{
+ Object o;
+#define MAKE_GETTER(cvref) \
+ constexpr Object cvref object() cvref noexcept \
+ { return static_cast<Object cvref>(o); }
+ FOR_EACH_CVREF(MAKE_GETTER)
+#undef MAKE_GETTER
+};
+
+template <typename Object, typename Tag = void>
+struct StorageEmptyBaseClassOptimization : Object
+{
+ StorageEmptyBaseClassOptimization() = default;
+ StorageEmptyBaseClassOptimization(Object &&o)
+ : Object(std::move(o))
+ {}
+ StorageEmptyBaseClassOptimization(const Object &o)
+ : Object(o)
+ {}
+
+#define MAKE_GETTER(cvref) \
+ constexpr Object cvref object() cvref noexcept \
+ { return static_cast<Object cvref>(*this); }
+ FOR_EACH_CVREF(MAKE_GETTER)
+#undef MAKE_GETTER
+};
+} // namespace detail
+
+template <typename Object, typename Tag = void>
+using CompactStorage = typename std::conditional_t<
+ std::conjunction_v<
+ std::is_empty<Object>,
+ std::negation<std::is_final<Object>>
+ >,
+ detail::StorageEmptyBaseClassOptimization<Object, Tag>,
+ detail::StorageByValue<Object, Tag>
+ >;
+
+} // namespace QtPrivate
+
+#undef FOR_EACH_CVREF
+
+QT_END_NAMESPACE
+
+#endif // QFUNCTIONALTOOLS_IMPL_H
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index f52d46a9e8..12e90daecf 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// for rand_s, _CRT_RAND_S must be #defined before #including stdlib.h.
// put it at the beginning so some indirect inclusion doesn't break it
@@ -60,27 +24,161 @@
#include <qdatetime.h>
#include <qbasicatomic.h>
#include <qendian.h>
+#include <private/qrandom_p.h>
#include <private/qsimd_p.h>
#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
#include <qrandom.h>
+#include <private/qlocale_tools_p.h>
#endif // QT_BOOTSTRAPPED
+#include <array>
#include <limits.h>
+#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
+# define NDEBUG
+#endif
+#include <assert.h>
+
+#ifdef Q_CC_GNU
+# define Q_DECL_HOT_FUNCTION __attribute__((hot))
+#else
+# define Q_DECL_HOT_FUNCTION
+#endif
+
QT_BEGIN_NAMESPACE
+void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept; // qstring.cpp
+
// We assume that pointers and size_t have the same size. If that assumption should fail
// on a platform the code selecting the different methods below needs to be fixed.
static_assert(sizeof(size_t) == QT_POINTER_SIZE, "size_t and pointers have different size.");
+namespace {
+struct HashSeedStorage
+{
+ static constexpr int SeedCount = 2;
+ QBasicAtomicInteger<quintptr> seeds[SeedCount] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };
+
+#if !QT_SUPPORTS_INIT_PRIORITY || defined(QT_BOOTSTRAPPED)
+ constexpr HashSeedStorage() = default;
+#else
+ HashSeedStorage() { initialize(0); }
+#endif
+
+ enum State {
+ OverriddenByEnvironment = -1,
+ JustInitialized,
+ AlreadyInitialized
+ };
+ struct StateResult {
+ quintptr requestedSeed;
+ State state;
+ };
+
+ StateResult state(int which = -1);
+ Q_DECL_HOT_FUNCTION QHashSeed currentSeed(int which)
+ {
+ return { state(which).requestedSeed };
+ }
+
+ void resetSeed()
+ {
+#ifndef QT_BOOTSTRAPPED
+ if (state().state < AlreadyInitialized)
+ return;
+
+ // update the public seed
+ QRandomGenerator *generator = QRandomGenerator::system();
+ seeds[0].storeRelaxed(sizeof(size_t) > sizeof(quint32)
+ ? generator->generate64() : generator->generate());
+#endif
+ }
+
+ void clearSeed()
+ {
+ state();
+ seeds[0].storeRelaxed(0); // always write (smaller code)
+ }
+
+private:
+ Q_DECL_COLD_FUNCTION Q_NEVER_INLINE StateResult initialize(int which) noexcept;
+};
+
+[[maybe_unused]] HashSeedStorage::StateResult HashSeedStorage::initialize(int which) noexcept
+{
+ StateResult result = { 0, OverriddenByEnvironment };
+#ifdef QT_BOOTSTRAPPED
+ Q_UNUSED(which);
+ Q_UNREACHABLE_RETURN(result);
+#else
+ // can't use qEnvironmentVariableIntValue (reentrancy)
+ const char *seedstr = getenv("QT_HASH_SEED");
+ if (seedstr) {
+ auto r = qstrntoll(seedstr, strlen(seedstr), 10);
+ if (r.used > 0 && size_t(r.used) == strlen(seedstr)) {
+ if (r.result) {
+ // can't use qWarning here (reentrancy)
+ fprintf(stderr, "QT_HASH_SEED: forced seed value is not 0; ignored.\n");
+ }
+
+ // we don't have to store to the seed, since it's pre-initialized by
+ // the compiler to zero
+ return result;
+ }
+ }
+
+ // update the full seed
+ auto x = qt_initial_random_value();
+ for (int i = 0; i < SeedCount; ++i) {
+ seeds[i].storeRelaxed(x.data[i]);
+ if (which == i)
+ result.requestedSeed = x.data[i];
+ }
+ result.state = JustInitialized;
+ return result;
+#endif
+}
+
+inline HashSeedStorage::StateResult HashSeedStorage::state(int which)
+{
+ constexpr quintptr BadSeed = quintptr(Q_UINT64_C(0x5555'5555'5555'5555));
+ StateResult result = { BadSeed, AlreadyInitialized };
+
+#if defined(QT_BOOTSTRAPPED)
+ result = { 0, OverriddenByEnvironment };
+#elif !QT_SUPPORTS_INIT_PRIORITY
+ // dynamic initialization
+ static auto once = [&]() {
+ result = initialize(which);
+ return true;
+ }();
+ Q_UNUSED(once);
+#endif
+
+ if (result.state == AlreadyInitialized && which >= 0)
+ return { seeds[which].loadRelaxed(), AlreadyInitialized };
+ return result;
+}
+} // unnamed namespace
+
+/*
+ The QHash seed itself.
+*/
+#ifdef Q_DECL_INIT_PRIORITY
+Q_DECL_INIT_PRIORITY(05)
+#else
+Q_CONSTINIT
+#endif
+static HashSeedStorage qt_qhash_seed;
+
/*
* Hashing for memory segments is based on the public domain MurmurHash2 by
* Austin Appleby. See http://murmurhash.googlepages.com/
*/
#if QT_POINTER_SIZE == 4
-
+Q_NEVER_INLINE Q_DECL_HOT_FUNCTION
static inline uint murmurhash(const void *key, uint len, uint seed) noexcept
{
// 'm' and 'r' are mixing constants generated offline.
@@ -138,7 +236,7 @@ static inline uint murmurhash(const void *key, uint len, uint seed) noexcept
}
#else
-
+Q_NEVER_INLINE Q_DECL_HOT_FUNCTION
static inline uint64_t murmurhash(const void *key, uint64_t len, uint64_t seed) noexcept
{
const uint64_t m = 0xc6a4a7935bd1e995ULL;
@@ -187,20 +285,11 @@ static inline uint64_t murmurhash(const void *key, uint64_t len, uint64_t seed)
#endif
-#if QT_POINTER_SIZE == 8
+namespace {
// This is an inlined version of the SipHash implementation that is
// trying to avoid some memcpy's from uint64 to uint8[] and back.
-//
-// The original algorithm uses a 128bit seed. Our public API only allows
-// for a 64bit seed, so we mix in the length of the string to get some more
-// bits for the seed.
-//
-// Use SipHash-1-2, which has similar performance characteristics as
-// stablehash() above, instead of the SipHash-2-4 default
-#define cROUNDS 1
-#define dROUNDS 2
-#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+#define ROTL(x, b) (((x) << (b)) | ((x) >> (sizeof(x) * 8 - (b))))
#define SIPROUND \
do { \
@@ -220,8 +309,7 @@ static inline uint64_t murmurhash(const void *key, uint64_t len, uint64_t seed)
v2 = ROTL(v2, 32); \
} while (0)
-
-static uint64_t siphash(const uint8_t *in, uint64_t inlen, const uint64_t seed)
+template <int cROUNDS = 2, int dROUNDS = 4> struct SipHash64
{
/* "somepseudorandomlygeneratedbytes" */
uint64_t v0 = 0x736f6d6570736575ULL;
@@ -229,17 +317,32 @@ static uint64_t siphash(const uint8_t *in, uint64_t inlen, const uint64_t seed)
uint64_t v2 = 0x6c7967656e657261ULL;
uint64_t v3 = 0x7465646279746573ULL;
uint64_t b;
- uint64_t k0 = seed;
- uint64_t k1 = seed ^ inlen;
- int i;
- const uint8_t *end = in + (inlen & ~7ULL);
- const int left = inlen & 7;
+ uint64_t k0;
+ uint64_t k1;
+
+ inline SipHash64(uint64_t fulllen, uint64_t seed, uint64_t seed2);
+ inline void addBlock(const uint8_t *in, size_t inlen);
+ inline uint64_t finalize(const uint8_t *in, size_t left);
+};
+
+template <int cROUNDS, int dROUNDS>
+SipHash64<cROUNDS, dROUNDS>::SipHash64(uint64_t inlen, uint64_t seed, uint64_t seed2)
+{
b = inlen << 56;
+ k0 = seed;
+ k1 = seed2;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
+}
+template <int cROUNDS, int dROUNDS> Q_DECL_HOT_FUNCTION void
+SipHash64<cROUNDS, dROUNDS>::addBlock(const uint8_t *in, size_t inlen)
+{
+ Q_ASSERT((inlen & 7ULL) == 0);
+ int i;
+ const uint8_t *end = in + inlen;
for (; in != end; in += 8) {
uint64_t m = qFromUnaligned<uint64_t>(in);
v3 ^= m;
@@ -249,24 +352,31 @@ static uint64_t siphash(const uint8_t *in, uint64_t inlen, const uint64_t seed)
v0 ^= m;
}
+}
-
-#if defined(Q_CC_GNU) && Q_CC_GNU >= 700
- QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough")
-#endif
+template <int cROUNDS, int dROUNDS> Q_DECL_HOT_FUNCTION uint64_t
+SipHash64<cROUNDS, dROUNDS>::finalize(const uint8_t *in, size_t left)
+{
+ int i;
switch (left) {
case 7:
b |= ((uint64_t)in[6]) << 48;
+ Q_FALLTHROUGH();
case 6:
b |= ((uint64_t)in[5]) << 40;
+ Q_FALLTHROUGH();
case 5:
b |= ((uint64_t)in[4]) << 32;
+ Q_FALLTHROUGH();
case 4:
b |= ((uint64_t)in[3]) << 24;
+ Q_FALLTHROUGH();
case 3:
b |= ((uint64_t)in[2]) << 16;
+ Q_FALLTHROUGH();
case 2:
b |= ((uint64_t)in[1]) << 8;
+ Q_FALLTHROUGH();
case 1:
b |= ((uint64_t)in[0]);
break;
@@ -289,7 +399,8 @@ static uint64_t siphash(const uint8_t *in, uint64_t inlen, const uint64_t seed)
b = v0 ^ v1 ^ v2 ^ v3;
return b;
}
-#else
+#undef SIPROUND
+
// This is a "SipHash" implementation adopted for 32bit platforms. It performs
// basically the same operations as the 64bit version using 4 byte at a time
// instead of 8.
@@ -300,12 +411,6 @@ static uint64_t siphash(const uint8_t *in, uint64_t inlen, const uint64_t seed)
//
// For the v0-v4 constants, simply use the first four bytes of the 64 bit versions.
//
-// Use SipHash-1-2, which has similar performance characteristics as
-// stablehash() above, instead of the SipHash-2-4 default
-#define cROUNDS 1
-#define dROUNDS 2
-
-#define ROTL(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
#define SIPROUND \
do { \
@@ -325,8 +430,7 @@ static uint64_t siphash(const uint8_t *in, uint64_t inlen, const uint64_t seed)
v2 = ROTL(v2, 16); \
} while (0)
-
-static uint siphash(const uint8_t *in, uint inlen, const uint seed)
+template <int cROUNDS = 2, int dROUNDS = 4> struct SipHash32
{
/* "somepseudorandomlygeneratedbytes" */
uint v0 = 0x736f6d65U;
@@ -334,17 +438,32 @@ static uint siphash(const uint8_t *in, uint inlen, const uint seed)
uint v2 = 0x6c796765U;
uint v3 = 0x74656462U;
uint b;
+ uint k0;
+ uint k1;
+
+ inline SipHash32(size_t fulllen, uint seed, uint seed2);
+ inline void addBlock(const uint8_t *in, size_t inlen);
+ inline uint finalize(const uint8_t *in, size_t left);
+};
+
+template <int cROUNDS, int dROUNDS> inline
+SipHash32<cROUNDS, dROUNDS>::SipHash32(size_t inlen, uint seed, uint seed2)
+{
uint k0 = seed;
- uint k1 = seed ^ inlen;
- int i;
- const uint8_t *end = in + (inlen & ~3ULL);
- const int left = inlen & 3;
+ uint k1 = seed2;
b = inlen << 24;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
+}
+template <int cROUNDS, int dROUNDS> inline Q_DECL_HOT_FUNCTION void
+SipHash32<cROUNDS, dROUNDS>::addBlock(const uint8_t *in, size_t inlen)
+{
+ Q_ASSERT((inlen & 3ULL) == 0);
+ int i;
+ const uint8_t *end = in + inlen;
for (; in != end; in += 4) {
uint m = qFromUnaligned<uint>(in);
v3 ^= m;
@@ -354,15 +473,19 @@ static uint siphash(const uint8_t *in, uint inlen, const uint seed)
v0 ^= m;
}
+}
-#if defined(Q_CC_GNU) && Q_CC_GNU >= 700
- QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough")
-#endif
+template <int cROUNDS, int dROUNDS> inline Q_DECL_HOT_FUNCTION uint
+SipHash32<cROUNDS, dROUNDS>::finalize(const uint8_t *in, size_t left)
+{
+ int i;
switch (left) {
case 3:
b |= ((uint)in[2]) << 16;
+ Q_FALLTHROUGH();
case 2:
b |= ((uint)in[1]) << 8;
+ Q_FALLTHROUGH();
case 1:
b |= ((uint)in[0]);
break;
@@ -385,17 +508,610 @@ static uint siphash(const uint8_t *in, uint inlen, const uint seed)
b = v0 ^ v1 ^ v2 ^ v3;
return b;
}
-#endif
+#undef SIPROUND
+#undef ROTL
-size_t qHashBits(const void *p, size_t size, size_t seed) noexcept
+// Use SipHash-1-2, which has similar performance characteristics as
+// stablehash() above, instead of the SipHash-2-4 default
+template <int cROUNDS = 1, int dROUNDS = 2>
+using SipHash = std::conditional_t<sizeof(void *) == 8,
+ SipHash64<cROUNDS, dROUNDS>, SipHash32<cROUNDS, dROUNDS>>;
+} // unnamed namespace
+
+Q_NEVER_INLINE Q_DECL_HOT_FUNCTION
+static size_t siphash(const uint8_t *in, size_t inlen, size_t seed, size_t seed2)
+{
+ constexpr size_t TailSizeMask = sizeof(void *) - 1;
+ SipHash<> hasher(inlen, seed, seed2);
+ hasher.addBlock(in, inlen & ~TailSizeMask);
+ return hasher.finalize(in + (inlen & ~TailSizeMask), inlen & TailSizeMask);
+}
+
+enum ZeroExtension {
+ None = 0,
+ ByteToWord = 1,
+};
+
+template <ZeroExtension = None> static size_t
+qHashBits_fallback(const uchar *p, size_t size, size_t seed, size_t seed2) noexcept;
+template <> size_t qHashBits_fallback<None>(const uchar *p, size_t size, size_t seed, size_t seed2) noexcept
{
if (size <= QT_POINTER_SIZE)
return murmurhash(p, size, seed);
- return siphash(reinterpret_cast<const uchar *>(p), size, seed);
+ return siphash(reinterpret_cast<const uchar *>(p), size, seed, seed2);
+}
+
+template <> size_t qHashBits_fallback<ByteToWord>(const uchar *data, size_t size, size_t seed, size_t seed2) noexcept
+{
+ auto quick_from_latin1 = [](char16_t *dest, const uchar *data, size_t size) {
+ // Quick, "inlined" version for very short blocks
+ std::copy_n(data, size, dest);
+ };
+ if (size <= QT_POINTER_SIZE / 2) {
+ std::array<char16_t, QT_POINTER_SIZE / 2> buf;
+ quick_from_latin1(buf.data(), data, size);
+ return murmurhash(buf.data(), size * 2, seed);
+ }
+
+ constexpr size_t TailSizeMask = sizeof(void *) / 2 - 1;
+ std::array<char16_t, 256> buf;
+ SipHash<> siphash(size * 2, seed, seed2);
+ ptrdiff_t offset = 0;
+ for ( ; offset + buf.size() < size; offset += buf.size()) {
+ qt_from_latin1(buf.data(), reinterpret_cast<const char *>(data) + offset, buf.size());
+ siphash.addBlock(reinterpret_cast<uint8_t *>(buf.data()), sizeof(buf));
+ }
+ if (size_t n = size - offset; n > TailSizeMask) {
+ n &= ~TailSizeMask;
+ qt_from_latin1(buf.data(), reinterpret_cast<const char *>(data) + offset, n);
+ siphash.addBlock(reinterpret_cast<uint8_t *>(buf.data()), n * 2);
+ offset += n;
+ }
+
+ quick_from_latin1(buf.data(), data + offset, size - offset);
+ return siphash.finalize(reinterpret_cast<uint8_t *>(buf.data()), (size - offset) * 2);
+}
+
+#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__) // GCC
+# define QHASH_AES_SANITIZER_BUILD
+#elif __has_feature(address_sanitizer) || __has_feature(thread_sanitizer) // Clang
+# define QHASH_AES_SANITIZER_BUILD
+#endif
+
+// When built with a sanitizer, aeshash() is rightfully reported to have a
+// heap-buffer-overflow issue. However, we consider it to be safe in this
+// specific case and overcome the problem by correctly discarding the
+// out-of-range bits. To allow building the code with sanitizer,
+// QHASH_AES_SANITIZER_BUILD is used to disable aeshash() usage.
+#if QT_COMPILER_SUPPORTS_HERE(AES) && QT_COMPILER_SUPPORTS_HERE(SSE4_2) && \
+ !defined(QHASH_AES_SANITIZER_BUILD)
+# define AESHASH
+# define QT_FUNCTION_TARGET_STRING_AES_AVX2 "avx2,aes"
+# define QT_FUNCTION_TARGET_STRING_AES_AVX512 \
+ QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 "," \
+ QT_FUNCTION_TARGET_STRING_AES
+# define QT_FUNCTION_TARGET_STRING_VAES_AVX512 \
+ QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 "," \
+ QT_FUNCTION_TARGET_STRING_VAES
+# undef QHASH_AES_SANITIZER_BUILD
+# if QT_POINTER_SIZE == 8
+# define mm_set1_epz _mm_set1_epi64x
+# define mm_cvtsz_si128 _mm_cvtsi64_si128
+# define mm_cvtsi128_sz _mm_cvtsi128_si64
+# define mm256_set1_epz _mm256_set1_epi64x
+# else
+# define mm_set1_epz _mm_set1_epi32
+# define mm_cvtsz_si128 _mm_cvtsi32_si128
+# define mm_cvtsi128_sz _mm_cvtsi128_si32
+# define mm256_set1_epz _mm256_set1_epi32
+# endif
+
+namespace {
+ // This is inspired by the algorithm in the Go language. See:
+ // https://github.com/golang/go/blob/01b6cf09fc9f272d9db3d30b4c93982f4911d120/src/runtime/asm_amd64.s#L1105
+ // https://github.com/golang/go/blob/01b6cf09fc9f272d9db3d30b4c93982f4911d120/src/runtime/asm_386.s#L908
+ //
+ // Even though we're using the AESENC instruction from the CPU, this code
+ // is not encryption and this routine makes no claim to be
+ // cryptographically secure. We're simply using the instruction that performs
+ // the scrambling round (step 3 in [1]) because it's just very good at
+ // spreading the bits around.
+ //
+ // Note on Latin-1 hashing (ZX == ByteToWord): for simplicity of the
+ // algorithm, we pass sizes equivalent to the UTF-16 content (ZX == None).
+ // That means we must multiply by 2 on entry, divide by 2 on pointer
+ // advancing, and load half as much data from memory (though we produce
+ // exactly as much data in registers). The compilers appear to optimize
+ // this out.
+ //
+ // [1] https://en.wikipedia.org/wiki/Advanced_Encryption_Standard#High-level_description_of_the_algorithm
+
+ template <ZeroExtension ZX, typename T> static const T *advance(const T *ptr, ptrdiff_t n)
+ {
+ if constexpr (ZX == None)
+ return ptr + n;
+
+ // see note above on ZX == ByteToWord hashing
+ auto p = reinterpret_cast<const uchar *>(ptr);
+ n *= sizeof(T);
+ return reinterpret_cast<const T *>(p + n/2);
+ }
+
+ template <ZeroExtension> static __m128i loadu128(const void *ptr);
+ template <> Q_ALWAYS_INLINE QT_FUNCTION_TARGET(AES) __m128i loadu128<None>(const void *ptr)
+ {
+ return _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ }
+ template <> Q_ALWAYS_INLINE QT_FUNCTION_TARGET(AES) __m128i loadu128<ByteToWord>(const void *ptr)
+ {
+ // use a MOVQ followed by PMOVZXBW
+ // the compiler usually combines them as a single, loading PMOVZXBW
+ __m128i data = _mm_loadl_epi64(static_cast<const __m128i *>(ptr));
+ return _mm_cvtepu8_epi16(data);
+ }
+
+ // hash 16 bytes, running 3 scramble rounds of AES on itself (like label "final1")
+ static void Q_ALWAYS_INLINE QT_FUNCTION_TARGET(AES) QT_VECTORCALL
+ hash16bytes(__m128i &state0, __m128i data)
+ {
+ state0 = _mm_xor_si128(state0, data);
+ state0 = _mm_aesenc_si128(state0, state0);
+ state0 = _mm_aesenc_si128(state0, state0);
+ state0 = _mm_aesenc_si128(state0, state0);
+ }
+
+ // hash twice 16 bytes, running 2 scramble rounds of AES on itself
+ template <ZeroExtension ZX>
+ static void QT_FUNCTION_TARGET(AES) QT_VECTORCALL
+ hash2x16bytes(__m128i &state0, __m128i &state1, const __m128i *src0, const __m128i *src1)
+ {
+ __m128i data0 = loadu128<ZX>(src0);
+ __m128i data1 = loadu128<ZX>(src1);
+ state0 = _mm_xor_si128(data0, state0);
+ state1 = _mm_xor_si128(data1, state1);
+ state0 = _mm_aesenc_si128(state0, state0);
+ state1 = _mm_aesenc_si128(state1, state1);
+ state0 = _mm_aesenc_si128(state0, state0);
+ state1 = _mm_aesenc_si128(state1, state1);
+ }
+
+ struct AESHashSeed
+ {
+ __m128i state0;
+ __m128i mseed2;
+ AESHashSeed(size_t seed, size_t seed2) QT_FUNCTION_TARGET(AES);
+ __m128i state1() const QT_FUNCTION_TARGET(AES);
+ __m256i state0_256() const QT_FUNCTION_TARGET(AES_AVX2)
+ { return _mm256_set_m128i(state1(), state0); }
+ };
+} // unnamed namespace
+
+Q_ALWAYS_INLINE AESHashSeed::AESHashSeed(size_t seed, size_t seed2)
+{
+ __m128i mseed = mm_cvtsz_si128(seed);
+ mseed2 = mm_set1_epz(seed2);
+
+ // mseed (epi16) = [ seed, seed >> 16, seed >> 32, seed >> 48, len, 0, 0, 0 ]
+ mseed = _mm_insert_epi16(mseed, short(seed), 4);
+ // mseed (epi16) = [ seed, seed >> 16, seed >> 32, seed >> 48, len, len, len, len ]
+ mseed = _mm_shufflehi_epi16(mseed, 0);
+
+ // merge with the process-global seed
+ __m128i key = _mm_xor_si128(mseed, mseed2);
+
+ // scramble the key
+ __m128i state0 = _mm_aesenc_si128(key, key);
+ this->state0 = state0;
+}
+
+Q_ALWAYS_INLINE __m128i AESHashSeed::state1() const
+{
+ {
+ // unlike the Go code, we don't have more per-process seed
+ __m128i state1 = _mm_aesenc_si128(state0, mseed2);
+ return state1;
+ }
+}
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(AES) QT_VECTORCALL
+aeshash128_16to32(__m128i state0, __m128i state1, const __m128i *src, const __m128i *srcend)
+{
+ {
+ const __m128i *src2 = advance<ZX>(srcend, -1);
+ if (advance<ZX>(src, 1) < srcend) {
+ // epilogue: between 16 and 31 bytes
+ hash2x16bytes<ZX>(state0, state1, src, src2);
+ } else if (src != srcend) {
+ // epilogue: between 1 and 16 bytes, overlap with the end
+ __m128i data = loadu128<ZX>(src2);
+ hash16bytes(state0, data);
+ }
+
+ // combine results:
+ state0 = _mm_xor_si128(state0, state1);
+ }
+
+ return mm_cvtsi128_sz(state0);
+}
+
+// load all 16 bytes and mask off the bytes past the end of the source
+static const qint8 maskarray[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+// load 16 bytes ending at the data end, then shuffle them to the beginning
+static const qint8 shufflecontrol[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(AES) QT_VECTORCALL
+aeshash128_lt16(__m128i state0, const __m128i *src, const __m128i *srcend, size_t len)
+{
+ if (len) {
+ // We're going to load 16 bytes and mask zero the part we don't care
+ // (the hash of a short string is different from the hash of a longer
+ // including NULLs at the end because the length is in the key)
+ // WARNING: this may produce valgrind warnings, but it's safe
+
+ constexpr quintptr CachelineSize = 64;
+ __m128i data;
+
+ if ((quintptr(src) & (CachelineSize / 2)) == 0) {
+ // lower half of the cacheline:
+ __m128i mask = _mm_loadu_si128(reinterpret_cast<const __m128i *>(maskarray + 15 - len));
+ data = loadu128<ZX>(src);
+ data = _mm_and_si128(data, mask);
+ } else {
+ // upper half of the cacheline:
+ __m128i control = _mm_loadu_si128(reinterpret_cast<const __m128i *>(shufflecontrol + 15 - len));
+ data = loadu128<ZX>(advance<ZX>(srcend, -1));
+ data = _mm_shuffle_epi8(data, control);
+ }
+
+ hash16bytes(state0, data);
+ }
+ return mm_cvtsi128_sz(state0);
+}
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(AES) QT_VECTORCALL
+aeshash128_ge32(__m128i state0, __m128i state1, const __m128i *src, const __m128i *srcend)
+{
+ // main loop: scramble two 16-byte blocks
+ for ( ; advance<ZX>(src, 2) < srcend; src = advance<ZX>(src, 2))
+ hash2x16bytes<ZX>(state0, state1, src, advance<ZX>(src, 1));
+
+ return aeshash128_16to32<ZX>(state0, state1, src, srcend);
+}
+
+# if QT_COMPILER_SUPPORTS_HERE(VAES)
+template <ZeroExtension> static __m256i loadu256(const void *ptr);
+template <> Q_ALWAYS_INLINE QT_FUNCTION_TARGET(VAES) __m256i loadu256<None>(const void *ptr)
+{
+ return _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
+}
+template <> Q_ALWAYS_INLINE QT_FUNCTION_TARGET(VAES) __m256i loadu256<ByteToWord>(const void *ptr)
+{
+ // VPMOVZXBW xmm, ymm
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ return _mm256_cvtepu8_epi16(data);
+}
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(VAES_AVX512) QT_VECTORCALL
+aeshash256_lt32_avx256(__m256i state0, const uchar *p, size_t len)
+{
+ __m128i state0_128 = _mm256_castsi256_si128(state0);
+ if (len) {
+ __m256i data;
+ if constexpr (ZX == None) {
+ __mmask32 mask = _bzhi_u32(-1, unsigned(len));
+ data = _mm256_maskz_loadu_epi8(mask, p);
+ } else {
+ __mmask16 mask = _bzhi_u32(-1, unsigned(len) / 2);
+ __m128i data0 = _mm_maskz_loadu_epi8(mask, p);
+ data = _mm256_cvtepu8_epi16(data0);
+ }
+ __m128i data0 = _mm256_castsi256_si128(data);
+ if (len >= sizeof(__m128i)) {
+ state0 = _mm256_xor_si256(state0, data);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ // we're XOR'ing the two halves so we skip the third AESENC
+ // state0 = _mm256_aesenc_epi128(state0, state0);
+
+ // XOR the two halves and extract
+ __m128i low = _mm256_extracti128_si256(state0, 0);
+ __m128i high = _mm256_extracti128_si256(state0, 1);
+ state0_128 = _mm_xor_si128(low, high);
+ } else {
+ hash16bytes(state0_128, data0);
+ }
+ }
+ return mm_cvtsi128_sz(state0_128);
+}
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(VAES) QT_VECTORCALL
+aeshash256_ge32(__m256i state0, const __m128i *s, const __m128i *end, size_t len)
+{
+ static const auto hash32bytes = [](__m256i &state0, __m256i data) QT_FUNCTION_TARGET(VAES) {
+ state0 = _mm256_xor_si256(state0, data);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ };
+
+ // hash twice 32 bytes, running 2 scramble rounds of AES on itself
+ const auto hash2x32bytes = [](__m256i &state0, __m256i &state1, const void *src0,
+ const void *src1) QT_FUNCTION_TARGET(VAES) {
+ __m256i data0 = loadu256<ZX>(src0);
+ __m256i data1 = loadu256<ZX>(src1);
+ state0 = _mm256_xor_si256(data0, state0);
+ state1 = _mm256_xor_si256(data1, state1);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ state1 = _mm256_aesenc_epi128(state1, state1);
+ state0 = _mm256_aesenc_epi128(state0, state0);
+ state1 = _mm256_aesenc_epi128(state1, state1);
+ };
+
+ const __m256i *src = reinterpret_cast<const __m256i *>(s);
+ const __m256i *srcend = reinterpret_cast<const __m256i *>(end);
+
+ __m256i state1 = _mm256_aesenc_epi128(state0, mm256_set1_epz(len));
+
+ // main loop: scramble two 32-byte blocks
+ for ( ; advance<ZX>(src, 2) < srcend; src = advance<ZX>(src, 2))
+ hash2x32bytes(state0, state1, src, advance<ZX>(src, 1));
+
+ const __m256i *src2 = advance<ZX>(srcend, -1);
+ if (advance<ZX>(src, 1) < srcend) {
+ // epilogue: between 32 and 31 bytes
+ hash2x32bytes(state0, state1, src, src2);
+ } else if (src != srcend) {
+ // epilogue: between 1 and 32 bytes, overlap with the end
+ __m256i data = loadu256<ZX>(src2);
+ hash32bytes(state0, data);
+ }
+
+ // combine results:
+ state0 = _mm256_xor_si256(state0, state1);
+
+ // XOR the two halves and extract
+ __m128i low = _mm256_extracti128_si256(state0, 0);
+ __m128i high = _mm256_extracti128_si256(state0, 1);
+ return mm_cvtsi128_sz(_mm_xor_si128(low, high));
+}
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(VAES)
+aeshash256(const uchar *p, size_t len, size_t seed, size_t seed2) noexcept
+{
+ AESHashSeed state(seed, seed2);
+ auto src = reinterpret_cast<const __m128i *>(p);
+ const auto srcend = reinterpret_cast<const __m128i *>(advance<ZX>(p, len));
+
+ if (len < sizeof(__m128i))
+ return aeshash128_lt16<ZX>(state.state0, src, srcend, len);
+
+ if (len <= sizeof(__m256i))
+ return aeshash128_16to32<ZX>(state.state0, state.state1(), src, srcend);
+
+ return aeshash256_ge32<ZX>(state.state0_256(), src, srcend, len);
+}
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(VAES_AVX512)
+aeshash256_avx256(const uchar *p, size_t len, size_t seed, size_t seed2) noexcept
+{
+ AESHashSeed state(seed, seed2);
+ auto src = reinterpret_cast<const __m128i *>(p);
+ const auto srcend = reinterpret_cast<const __m128i *>(advance<ZX>(p, len));
+
+ if (len <= sizeof(__m256i))
+ return aeshash256_lt32_avx256<ZX>(state.state0_256(), p, len);
+
+ return aeshash256_ge32<ZX>(state.state0_256(), src, srcend, len);
+}
+# endif // VAES
+
+template <ZeroExtension ZX>
+static size_t QT_FUNCTION_TARGET(AES)
+aeshash128(const uchar *p, size_t len, size_t seed, size_t seed2) noexcept
+{
+ AESHashSeed state(seed, seed2);
+ auto src = reinterpret_cast<const __m128i *>(p);
+ const auto srcend = reinterpret_cast<const __m128i *>(advance<ZX>(p, len));
+
+ if (len < sizeof(__m128i))
+ return aeshash128_lt16<ZX>(state.state0, src, srcend, len);
+
+ if (len <= sizeof(__m256i))
+ return aeshash128_16to32<ZX>(state.state0, state.state1(), src, srcend);
+
+ return aeshash128_ge32<ZX>(state.state0, state.state1(), src, srcend);
+}
+
+template <ZeroExtension ZX = None>
+static size_t aeshash(const uchar *p, size_t len, size_t seed, size_t seed2) noexcept
+{
+ if constexpr (ZX == ByteToWord)
+ len *= 2; // see note above on ZX == ByteToWord hashing
+
+# if QT_COMPILER_SUPPORTS_HERE(VAES)
+ if (qCpuHasFeature(VAES)) {
+ if (qCpuHasFeature(AVX512VL))
+ return aeshash256_avx256<ZX>(p, len, seed, seed2);
+ return aeshash256<ZX>(p, len, seed, seed2);
+ }
+# endif
+ return aeshash128<ZX>(p, len, seed, seed2);
+}
+#endif // x86 AESNI
+
+#if defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED)
+QT_FUNCTION_TARGET(AES)
+static size_t aeshash(const uchar *p, size_t len, size_t seed, size_t seed2) noexcept
+{
+ uint8x16_t key;
+# if QT_POINTER_SIZE == 8
+ uint64x2_t vseed = vcombine_u64(vcreate_u64(seed), vcreate_u64(seed2));
+ key = vreinterpretq_u8_u64(vseed);
+# else
+
+ uint32x2_t vseed = vmov_n_u32(seed);
+ vseed = vset_lane_u32(seed2, vseed, 1);
+ key = vreinterpretq_u8_u32(vcombine_u32(vseed, vseed));
+# endif
+
+ // Compared to x86 AES, ARM splits each round into two instructions
+ // and includes the pre-xor instead of the post-xor.
+ const auto hash16bytes = [](uint8x16_t &state0, uint8x16_t data) {
+ auto state1 = state0;
+ state0 = vaeseq_u8(state0, data);
+ state0 = vaesmcq_u8(state0);
+ auto state2 = state0;
+ state0 = vaeseq_u8(state0, state1);
+ state0 = vaesmcq_u8(state0);
+ auto state3 = state0;
+ state0 = vaeseq_u8(state0, state2);
+ state0 = vaesmcq_u8(state0);
+ state0 = veorq_u8(state0, state3);
+ };
+
+ uint8x16_t state0 = key;
+
+ if (len < 8)
+ goto lt8;
+ if (len < 16)
+ goto lt16;
+ if (len < 32)
+ goto lt32;
+
+ // rounds of 32 bytes
+ {
+ // Make state1 = ~state0:
+ uint8x16_t state1 = veorq_u8(state0, vdupq_n_u8(255));
+
+ // do simplified rounds of 32 bytes: unlike the Go code, we only
+ // scramble twice and we keep 256 bits of state
+ const auto *e = p + len - 31;
+ while (p < e) {
+ uint8x16_t data0 = vld1q_u8(p);
+ uint8x16_t data1 = vld1q_u8(p + 16);
+ auto oldstate0 = state0;
+ auto oldstate1 = state1;
+ state0 = vaeseq_u8(state0, data0);
+ state1 = vaeseq_u8(state1, data1);
+ state0 = vaesmcq_u8(state0);
+ state1 = vaesmcq_u8(state1);
+ auto laststate0 = state0;
+ auto laststate1 = state1;
+ state0 = vaeseq_u8(state0, oldstate0);
+ state1 = vaeseq_u8(state1, oldstate1);
+ state0 = vaesmcq_u8(state0);
+ state1 = vaesmcq_u8(state1);
+ state0 = veorq_u8(state0, laststate0);
+ state1 = veorq_u8(state1, laststate1);
+ p += 32;
+ }
+ state0 = veorq_u8(state0, state1);
+ }
+ len &= 0x1f;
+
+ // do we still have 16 or more bytes?
+ if (len & 0x10) {
+lt32:
+ uint8x16_t data = vld1q_u8(p);
+ hash16bytes(state0, data);
+ p += 16;
+ }
+ len &= 0xf;
+
+ if (len & 0x08) {
+lt16:
+ uint8x8_t data8 = vld1_u8(p);
+ uint8x16_t data = vcombine_u8(data8, vdup_n_u8(0));
+ hash16bytes(state0, data);
+ p += 8;
+ }
+ len &= 0x7;
+
+lt8:
+ if (len) {
+ // load the last chunk of data
+ // We're going to load 8 bytes and mask zero the part we don't care
+ // (the hash of a short string is different from the hash of a longer
+ // including NULLs at the end because the length is in the key)
+ // WARNING: this may produce valgrind warnings, but it's safe
+
+ uint8x8_t data8;
+
+ if (Q_LIKELY(quintptr(p + 8) & 0xff8)) {
+ // same page, we definitely can't fault:
+ // load all 8 bytes and mask off the bytes past the end of the source
+ static const qint8 maskarray[] = {
+ -1, -1, -1, -1, -1, -1, -1,
+ 0, 0, 0, 0, 0, 0, 0,
+ };
+ uint8x8_t mask = vld1_u8(reinterpret_cast<const quint8 *>(maskarray) + 7 - len);
+ data8 = vld1_u8(p);
+ data8 = vand_u8(data8, mask);
+ } else {
+ // too close to the end of the page, it could fault:
+ // load 8 bytes ending at the data end, then shuffle them to the beginning
+ static const qint8 shufflecontrol[] = {
+ 1, 2, 3, 4, 5, 6, 7,
+ -1, -1, -1, -1, -1, -1, -1,
+ };
+ uint8x8_t control = vld1_u8(reinterpret_cast<const quint8 *>(shufflecontrol) + 7 - len);
+ data8 = vld1_u8(p - 8 + len);
+ data8 = vtbl1_u8(data8, control);
+ }
+ uint8x16_t data = vcombine_u8(data8, vdup_n_u8(0));
+ hash16bytes(state0, data);
+ }
+
+ // extract state0
+# if QT_POINTER_SIZE == 8
+ return vgetq_lane_u64(vreinterpretq_u64_u8(state0), 0);
+# else
+ return vgetq_lane_u32(vreinterpretq_u32_u8(state0), 0);
+# endif
+}
+#endif
+
+size_t qHashBits(const void *p, size_t size, size_t seed) noexcept
+{
+#ifdef QT_BOOTSTRAPPED
+ // the seed is always 0 in bootstrapped mode (no seed generation code),
+ // so help the compiler do dead code elimination
+ seed = 0;
+#endif
+ // mix in the length as a secondary seed. For seed == 0, seed2 must be
+ // size, to match what we used to do prior to Qt 6.2.
+ size_t seed2 = size;
+ if (seed)
+ seed2 = qt_qhash_seed.currentSeed(1);
+
+ auto data = reinterpret_cast<const uchar *>(p);
+#ifdef AESHASH
+ if (seed && qCpuHasFeature(AES) && qCpuHasFeature(SSE4_2))
+ return aeshash(data, size, seed, seed2);
+#elif defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED)
+ if (seed && qCpuHasFeature(AES))
+ return aeshash(data, size, seed, seed2);
+#endif
+
+ return qHashBits_fallback<>(data, size, seed, seed2);
}
-size_t qHash(const QByteArray &key, size_t seed) noexcept
+size_t qHash(QByteArrayView key, size_t seed) noexcept
{
return qHashBits(key.constData(), size_t(key.size()), seed);
}
@@ -405,92 +1121,157 @@ size_t qHash(QStringView key, size_t seed) noexcept
return qHashBits(key.data(), key.size()*sizeof(QChar), seed);
}
+#ifndef QT_BOOTSTRAPPED
size_t qHash(const QBitArray &bitArray, size_t seed) noexcept
{
- int m = bitArray.d.size() - 1;
+ qsizetype m = bitArray.d.size() - 1;
size_t result = qHashBits(reinterpret_cast<const uchar *>(bitArray.d.constData()), size_t(qMax(0, m)), seed);
// deal with the last 0 to 7 bits manually, because we can't trust that
// the padding is initialized to 0 in bitArray.d
- int n = bitArray.size();
+ qsizetype n = bitArray.size();
if (n & 0x7)
result = ((result << 4) + bitArray.d.at(m)) & ((1 << n) - 1);
return result;
}
+#endif
-size_t qHash(QLatin1String key, size_t seed) noexcept
+size_t qHash(QLatin1StringView key, size_t seed) noexcept
{
- return qHashBits(reinterpret_cast<const uchar *>(key.data()), size_t(key.size()), seed);
+#ifdef QT_BOOTSTRAPPED
+ // the seed is always 0 in bootstrapped mode (no seed generation code),
+ // so help the compiler do dead code elimination
+ seed = 0;
+#endif
+
+ auto data = reinterpret_cast<const uchar *>(key.data());
+ size_t size = key.size();
+
+ // Mix in the length as a secondary seed.
+ // Multiplied by 2 to match the byte size of the equiavlent UTF-16 string.
+ size_t seed2 = size * 2;
+ if (seed)
+ seed2 = qt_qhash_seed.currentSeed(1);
+
+#if defined(AESHASH)
+ if (seed && qCpuHasFeature(AES) && qCpuHasFeature(SSE4_2))
+ return aeshash<ByteToWord>(data, size, seed, seed2);
+#endif
+ return qHashBits_fallback<ByteToWord>(data, size, seed, seed2);
}
/*!
- \internal
+ \class QHashSeed
+ \inmodule QtCore
+ \since 6.2
+
+ The QHashSeed class is used to convey the QHash seed. This is used
+ internally by QHash and provides three static member functions to allow
+ users to obtain the hash and to reset it.
+
+ QHash and the qHash() functions implement what is called as "salted hash".
+ The intent is that different applications and different instances of the
+ same application will produce different hashing values for the same input,
+ thus causing the ordering of elements in QHash to be unpredictable by
+ external observers. This improves the applications' resilience against
+ attacks that attempt to force hashing tables into degenerate mode.
+
+ Most applications will not need to deal directly with the hash seed, as
+ QHash will do so when needed. However, applications may wish to use this
+ for their own purposes in the same way as QHash does: as an
+ application-global random value (but see \l QRandomGenerator too). Note
+ that the global hash seed may change during the application's lifetime, if
+ the resetRandomGlobalSeed() function is called. Users of the global hash
+ need to store the value they are using and not rely on getting it again.
+
+ This class also implements functionality to set the hash seed to a
+ deterministic value, which the qHash() functions will take to mean that
+ they should use a fixed hashing function on their data too. This
+ functionality is only meant to be used in debugging applications. This
+ behavior can also be controlled by setting the \c QT_HASH_SEED environment
+ variable to the value zero (any other value is ignored).
+
+ \sa QHash, QRandomGenerator
*/
-static uint qt_create_qhash_seed()
-{
- uint seed = 0;
-#ifndef QT_BOOTSTRAPPED
- QByteArray envSeed = qgetenv("QT_HASH_SEED");
- if (!envSeed.isNull()) {
- uint seed = envSeed.toUInt();
- if (seed) {
- // can't use qWarning here (reentrancy)
- fprintf(stderr, "QT_HASH_SEED: forced seed value is not 0, cannot guarantee that the "
- "hashing functions will produce a stable value.");
- }
- return seed;
- }
+/*!
+ \fn QHashSeed::QHashSeed(size_t data)
- seed = QRandomGenerator::system()->generate();
-#endif // QT_BOOTSTRAPPED
+ Constructs a new QHashSeed object using \a data as the seed.
+ */
+
+/*!
+ \fn QHashSeed::operator size_t() const
- return seed;
+ Converts the returned hash seed into a \c size_t.
+ */
+
+/*!
+ \threadsafe
+
+ Returns the current global QHash seed. The value returned by this function
+ will be zero if setDeterministicGlobalSeed() has been called or if the
+ \c{QT_HASH_SEED} environment variable is set to zero.
+ */
+QHashSeed QHashSeed::globalSeed() noexcept
+{
+ return qt_qhash_seed.currentSeed(0);
}
-/*
- The QHash seed itself.
-*/
-static QBasicAtomicInt qt_qhash_seed = Q_BASIC_ATOMIC_INITIALIZER(-1);
+/*!
+ \threadsafe
+
+ Forces the Qt hash seed to a deterministic value (zero) and asks the
+ qHash() functions to use a pre-determined hashing function. This mode is
+ only useful for debugging and should not be used in production code.
+
+ Regular operation can be restored by calling resetRandomGlobalSeed().
+ */
+void QHashSeed::setDeterministicGlobalSeed()
+{
+ qt_qhash_seed.clearSeed();
+}
/*!
- \internal
+ \threadsafe
- Seed == -1 means it that it was not initialized yet.
+ Reseeds the Qt hashing seed to a new, random value. Calling this function
+ is not necessary, but long-running applications may want to do so after a
+ long period of time in which information about its hash may have been
+ exposed to potential attackers.
- We let qt_create_qhash_seed return any unsigned integer,
- but convert it to signed in order to initialize the seed.
+ If the environment variable \c QT_HASH_SEED is set to zero, calling this
+ function will result in a no-op.
- We don't actually care about the fact that different calls to
- qt_create_qhash_seed() might return different values,
- as long as in the end everyone uses the very same value.
-*/
-static void qt_initialize_qhash_seed()
+ Qt never calls this function during the execution of the application, but
+ unless the \c QT_HASH_SEED variable is set to 0, the hash seed returned by
+ globalSeed() will be a random value as if this function had been called.
+ */
+void QHashSeed::resetRandomGlobalSeed()
{
- if (qt_qhash_seed.loadRelaxed() == -1) {
- int x(qt_create_qhash_seed() & INT_MAX);
- qt_qhash_seed.testAndSetRelaxed(-1, x);
- }
+ qt_qhash_seed.resetSeed();
}
+#if QT_DEPRECATED_SINCE(6,6)
/*! \relates QHash
\since 5.6
+ \deprecated [6.6] Use QHashSeed::globalSeed() instead.
Returns the current global QHash seed.
The seed is set in any newly created QHash. See \l{qHash} about how this seed
is being used by QHash.
- \sa qSetGlobalQHashSeed
+ \sa QHashSeed, QHashSeed::globalSeed()
*/
int qGlobalQHashSeed()
{
- qt_initialize_qhash_seed();
- return qt_qhash_seed.loadRelaxed();
+ return int(QHashSeed::globalSeed() & INT_MAX);
}
/*! \relates QHash
\since 5.6
+ \deprecated [6.6] Use QHashSeed instead.
Sets the global QHash seed to \a newSeed.
@@ -510,24 +1291,21 @@ int qGlobalQHashSeed()
If the environment variable \c QT_HASH_SEED is set, calling this function will
result in a no-op.
- \sa qGlobalQHashSeed
+ \sa QHashSeed::globalSeed(), QHashSeed
*/
void qSetGlobalQHashSeed(int newSeed)
{
- if (qEnvironmentVariableIsSet("QT_HASH_SEED"))
- return;
- if (newSeed == -1) {
- int x(qt_create_qhash_seed() & INT_MAX);
- qt_qhash_seed.storeRelaxed(x);
+ if (Q_LIKELY(newSeed == 0 || newSeed == -1)) {
+ if (newSeed == 0)
+ QHashSeed::setDeterministicGlobalSeed();
+ else
+ QHashSeed::resetRandomGlobalSeed();
} else {
- if (newSeed) {
- // can't use qWarning here (reentrancy)
- fprintf(stderr, "qSetGlobalQHashSeed: forced seed value is not 0, cannot guarantee that the "
- "hashing functions will produce a stable value.");
- }
- qt_qhash_seed.storeRelaxed(newSeed & INT_MAX);
+ // can't use qWarning here (reentrancy)
+ fprintf(stderr, "qSetGlobalQHashSeed: forced seed value is not 0; ignoring call\n");
}
}
+#endif // QT_DEPRECATED_SINCE(6,6)
/*!
\internal
@@ -560,16 +1338,6 @@ uint qt_hash(QStringView key, uint chained) noexcept
}
/*!
- \fn template <typename T1, typename T2> size_t qHash(const QPair<T1, T2> &key, size_t seed = 0)
- \since 5.0
- \relates QHash
-
- Returns the hash value for the \a key, using \a seed to seed the calculation.
-
- Types \c T1 and \c T2 must be supported by qHash().
-*/
-
-/*!
\fn template <typename T1, typename T2> size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
\since 5.7
\relates QHash
@@ -577,11 +1345,6 @@ uint qt_hash(QStringView key, uint chained) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
Types \c T1 and \c T2 must be supported by qHash().
-
- \note The return type of this function is \e{not} the same as that of
- \snippet code/src_corelib_tools_qhash.cpp 29
- The two functions use different hashing algorithms; due to binary compatibility
- constraints, we cannot change the QPair algorithm to match the std::pair one before Qt 6.
*/
/*!
@@ -799,6 +1562,26 @@ uint qt_hash(QStringView key, uint chained) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
+/*! \fn size_t qHash(quint128 key, size_t seed = 0)
+ \relates QHash
+ \since 6.8
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+
+ \note This function is only available on platforms that support a native
+ 128-bit integer type.
+*/
+
+/*! \fn size_t qHash(qint128 key, size_t seed = 0)
+ \relates QHash
+ \since 6.8
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+
+ \note This function is only available on platforms that support a native
+ 128-bit integer type.
+ */
+
/*! \fn size_t qHash(char8_t key, size_t seed = 0)
\relates QHash
\since 6.0
@@ -827,7 +1610,7 @@ uint qt_hash(QStringView key, uint chained) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-/*! \fn size_t qHash(float key, size_t seed) noexcept
+/*! \fn size_t qHash(float key, size_t seed = 0) noexcept
\relates QHash
\since 5.3
@@ -852,7 +1635,6 @@ size_t qHash(double key, size_t seed) noexcept
}
}
-#if !defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC)
/*! \relates QHash
\since 5.3
@@ -870,7 +1652,6 @@ size_t qHash(long double key, size_t seed) noexcept
return murmurhash(&key, sizeof(key), seed);
}
}
-#endif
/*! \fn size_t qHash(const QChar key, size_t seed = 0)
\relates QHash
@@ -886,21 +1667,21 @@ size_t qHash(long double key, size_t seed) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-/*! \fn size_t qHash(const QBitArray &key, size_t seed = 0)
+/*! \fn size_t qHash(const QByteArrayView &key, size_t seed = 0)
\relates QHash
- \since 5.0
+ \since 6.0
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-/*! \fn size_t qHash(const QString &key, size_t seed = 0)
+/*! \fn size_t qHash(const QBitArray &key, size_t seed = 0)
\relates QHash
\since 5.0
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-/*! \fn size_t qHash(const QStringRef &key, size_t seed = 0)
+/*! \fn size_t qHash(const QString &key, size_t seed = 0)
\relates QHash
\since 5.0
@@ -914,7 +1695,7 @@ size_t qHash(long double key, size_t seed) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-/*! \fn size_t qHash(QLatin1String key, size_t seed = 0)
+/*! \fn size_t qHash(QLatin1StringView key, size_t seed = 0)
\relates QHash
\since 5.0
@@ -928,13 +1709,28 @@ size_t qHash(long double key, size_t seed) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-/*! \fn template <class T> size_t qHash(std::nullptr_t key, size_t seed = 0)
+/*! \fn size_t qHash(std::nullptr_t key, size_t seed = 0)
\relates QHash
\since 6.0
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
+/*! \fn template<typename T> bool qHashEquals(const T &a, const T &b)
+ \relates QHash
+ \since 6.0
+ \internal
+
+ This method is being used by QHash to compare two keys. Returns true if the
+ keys \a a and \a b are considered equal for hashing purposes.
+
+ The default implementation returns the result of (a == b). It can be reimplemented
+ for a certain type if the equality operator is not suitable for hashing purposes.
+ This is for example the case if the equality operator uses qFuzzyCompare to compare
+ floating point values.
+*/
+
+
/*!
\class QHash
\inmodule QtCore
@@ -1041,7 +1837,7 @@ size_t qHash(long double key, size_t seed) noexcept
hash table, use \l{QMultiHash}.
If you only need to extract the values from a hash (not the keys),
- you can also use \l{foreach}:
+ you can also use range-based for:
\snippet code/src_corelib_tools_qhash.cpp 12
@@ -1055,31 +1851,54 @@ size_t qHash(long double key, size_t seed) noexcept
instead, store a QWidget *.
\target qHash
- \section2 The qHash() hashing function
+ \section2 The hashing function
A QHash's key type has additional requirements other than being an
assignable data type: it must provide operator==(), and there must also be
- a qHash() function in the type's namespace that returns a hash value for an
- argument of the key's type.
+ a hashing function that returns a hash value for an argument of the
+ key's type.
- The qHash() function computes a numeric value based on a key. It
+ The hashing function computes a numeric value based on a key. It
can use any algorithm imaginable, as long as it always returns
the same value if given the same argument. In other words, if
- \c{e1 == e2}, then \c{qHash(e1) == qHash(e2)} must hold as well.
- However, to obtain good performance, the qHash() function should
+ \c{e1 == e2}, then \c{hash(e1) == hash(e2)} must hold as well.
+ However, to obtain good performance, the hashing function should
attempt to return different hash values for different keys to the
largest extent possible.
- For a key type \c{K}, the qHash function must have one of these signatures:
+ A hashing function for a key type \c{K} may be provided in two
+ different ways.
+
+ The first way is by having an overload of \c{qHash()} in \c{K}'s
+ namespace. The \c{qHash()} function must have one of these signatures:
\snippet code/src_corelib_tools_qhash.cpp 32
The two-arguments overloads take an unsigned integer that should be used to
seed the calculation of the hash function. This seed is provided by QHash
- in order to prevent a family of \l{algorithmic complexity attacks}. If both
- a one-argument and a two-arguments overload are defined for a key type,
- the latter is used by QHash (note that you can simply define a
- two-arguments version, and use a default value for the seed parameter).
+ in order to prevent a family of \l{algorithmic complexity attacks}.
+
+ \note In Qt 6 it is possible to define a \c{qHash()} overload
+ taking only one argument; support for this is deprecated. Starting
+ with Qt 7, it will be mandatory to use a two-arguments overload. If
+ both a one-argument and a two-arguments overload are defined for a
+ key type, the latter is used by QHash (note that you can simply
+ define a two-arguments version, and use a default value for the
+ seed parameter).
+
+ The second way to provide a hashing function is by specializing
+ the \c{std::hash} class for the key type \c{K}, and providing a
+ suitable function call operator for it:
+
+ \snippet code/src_corelib_tools_qhash.cpp 33
+
+ The seed argument has the same meaning as for \c{qHash()},
+ and may be left out.
+
+ This second way allows to reuse the same hash function between
+ QHash and the C++ Standard Library unordered associative containers.
+ If both a \c{qHash()} overload and a \c{std::hash} specializations
+ are provided for a type, then the \c{qHash()} overload is preferred.
Here's a partial list of the C++ and Qt types that can serve as keys in a
QHash: any integer type (char, unsigned long, etc.), any pointer type,
@@ -1089,9 +1908,11 @@ size_t qHash(long double key, size_t seed) noexcept
the documentation of each class.
If you want to use other types as the key, make sure that you provide
- operator==() and a qHash() implementation. The convenience qHashMulti()
- function can be used to implement qHash() for a custom type, where
- one usually wants to produce a hash value from multiple fields:
+ operator==() and a hash implementation.
+
+ The convenience qHashMulti() function can be used to implement
+ qHash() for a custom type, where one usually wants to produce a
+ hash value from multiple fields:
Example:
\snippet code/src_corelib_tools_qhash.cpp 13
@@ -1126,7 +1947,7 @@ size_t qHash(long double key, size_t seed) noexcept
where you temporarily need deterministic behavior, for example for debugging or
regression testing. To disable the randomization, define the environment
variable \c QT_HASH_SEED to have the value 0. Alternatively, you can call
- the qSetGlobalQHashSeed() function with the value 0.
+ the QHashSeed::setDeterministicGlobalSeed() function.
\sa QHashIterator, QMutableHashIterator, QMap, QSet
*/
@@ -1159,8 +1980,8 @@ size_t qHash(long double key, size_t seed) noexcept
Constructs a hash with a copy of each of the elements in the iterator range
[\a begin, \a end). Either the elements iterated by the range must be
- objects with \c{first} and \c{second} data members (like \c{QPair},
- \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the
+ objects with \c{first} and \c{second} data members (like \c{std::pair}),
+ convertible to \c Key and to \c T respectively; or the
iterators must have \c{key()} and \c{value()} member functions, returning a
key convertible to \c Key and a value convertible to \c T respectively.
*/
@@ -1236,7 +2057,7 @@ size_t qHash(long double key, size_t seed) noexcept
\sa operator==()
*/
-/*! \fn template <class Key, class T> int QHash<Key, T>::size() const
+/*! \fn template <class Key, class T> qsizetype QHash<Key, T>::size() const
Returns the number of items in the hash.
@@ -1251,7 +2072,7 @@ size_t qHash(long double key, size_t seed) noexcept
\sa size()
*/
-/*! \fn template <class Key, class T> int QHash<Key, T>::capacity() const
+/*! \fn template <class Key, class T> qsizetype QHash<Key, T>::capacity() const
Returns the number of buckets in the QHash's internal hash table.
@@ -1280,7 +2101,7 @@ size_t qHash(long double key, size_t seed) noexcept
*/
-/*! \fn template <class Key, class T> void QHash<Key, T>::reserve(int size)
+/*! \fn template <class Key, class T> void QHash<Key, T>::reserve(qsizetype size)
Ensures that the QHash's internal hash table has space to store at
least \a size items without having to grow the hash table.
@@ -1362,6 +2183,21 @@ size_t qHash(long double key, size_t seed) noexcept
\sa clear(), take()
*/
+/*! \fn template <class Key, class T> template <typename Predicate> qsizetype QHash<Key, T>::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the hash.
+
+ The function supports predicates which take either an argument of
+ type \c{QHash<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+
+ \sa clear(), take()
+*/
+
/*! \fn template <class Key, class T> T QHash<Key, T>::take(const Key &key)
Removes the item with the \a key from the hash and returns
@@ -1380,17 +2216,18 @@ size_t qHash(long double key, size_t seed) noexcept
Returns \c true if the hash contains an item with the \a key;
otherwise returns \c false.
- \sa count(), QMultiHash::contains()
+ \sa count()
*/
-/*! \fn template <class Key, class T> T QHash<Key, T>::value(const Key &key, const T &defaultValue = T()) const
+/*! \fn template <class Key, class T> T QHash<Key, T>::value(const Key &key) const
+ \fn template <class Key, class T> T QHash<Key, T>::value(const Key &key, const T &defaultValue) const
\overload
Returns the value associated with the \a key.
If the hash contains no item with the \a key, the function
- returns \a defaultValue, which is a \l{default-constructed value} if the
- parameter has not been specified.
+ returns \a defaultValue, or a \l{default-constructed value} if this
+ parameter has not been supplied.
*/
/*! \fn template <class Key, class T> T &QHash<Key, T>::operator[](const Key &key)
@@ -1402,6 +2239,12 @@ size_t qHash(long double key, size_t seed) noexcept
a \l{default-constructed value} into the hash with the \a key, and
returns a reference to it.
+//! [qhash-iterator-invalidation-func-desc]
+ \warning Returned iterators/references should be considered invalidated
+ the next time you call a non-const function on the hash, or when the
+ hash is destroyed.
+//! [qhash-iterator-invalidation-func-desc]
+
\sa insert(), value()
*/
@@ -1419,6 +2262,10 @@ size_t qHash(long double key, size_t seed) noexcept
The order is guaranteed to be the same as that used by values().
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyBegin() to
+ \l keyEnd().
+
\sa values(), key()
*/
@@ -1441,29 +2288,35 @@ size_t qHash(long double key, size_t seed) noexcept
The order is guaranteed to be the same as that used by keys().
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyValueBegin() to
+ \l keyValueEnd().
+
\sa keys(), value()
*/
/*!
- \fn template <class Key, class T> Key QHash<Key, T>::key(const T &value, const Key &defaultKey = Key()) const
+ \fn template <class Key, class T> Key QHash<Key, T>::key(const T &value) const
+ \fn template <class Key, class T> Key QHash<Key, T>::key(const T &value, const Key &defaultKey) const
\since 4.3
- Returns the first key mapped to \a value, or \a defaultKey if the
- hash contains no item mapped to \a value.
+ Returns the first key mapped to \a value. If the hash contains no item
+ mapped to \a value, returns \a defaultKey, or a \l{default-constructed
+ value}{default-constructed key} if this parameter has not been supplied.
This function can be slow (\l{linear time}), because QHash's
internal data structure is optimized for fast lookup by key, not
by value.
*/
-/*! \fn template <class Key, class T> int QHash<Key, T>::count(const Key &key) const
+/*! \fn template <class Key, class T> qsizetype QHash<Key, T>::count(const Key &key) const
Returns the number of items associated with the \a key.
\sa contains()
*/
-/*! \fn template <class Key, class T> int QHash<Key, T>::count() const
+/*! \fn template <class Key, class T> qsizetype QHash<Key, T>::count() const
\overload
@@ -1475,12 +2328,16 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa constBegin(), end()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::begin() const
\overload
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::cbegin() const
@@ -1489,6 +2346,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa begin(), cend()
*/
@@ -1497,6 +2356,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa begin(), constEnd()
*/
@@ -1506,6 +2367,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyEnd()
*/
@@ -1514,12 +2377,16 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
after the last item in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa begin(), constEnd()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::end() const
\overload
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::constEnd() const
@@ -1527,6 +2394,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
item after the last item in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa constBegin(), end()
*/
@@ -1536,6 +2405,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
item after the last item in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa cbegin(), end()
*/
@@ -1545,6 +2416,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
item after the last key in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyBegin()
*/
@@ -1554,6 +2427,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueEnd()
*/
@@ -1563,6 +2438,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
entry after the last entry in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueBegin()
*/
@@ -1572,6 +2449,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueEnd()
*/
@@ -1581,6 +2460,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueBegin()
*/
@@ -1590,6 +2471,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
entry after the last entry in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueBegin()
*/
@@ -1599,9 +2482,32 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
entry after the last entry in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa constKeyValueBegin()
*/
+/*! \fn template <class Key, class T> auto QHash<Key, T>::asKeyValueRange() &
+ \fn template <class Key, class T> auto QHash<Key, T>::asKeyValueRange() const &
+ \fn template <class Key, class T> auto QHash<Key, T>::asKeyValueRange() &&
+ \fn template <class Key, class T> auto QHash<Key, T>::asKeyValueRange() const &&
+ \since 6.4
+
+ Returns a range object that allows iteration over this hash as
+ key/value pairs. For instance, this range object can be used in a
+ range-based for loop, in combination with a structured binding declaration:
+
+ \snippet code/src_corelib_tools_qhash.cpp 34
+
+ Note that both the key and the value obtained this way are
+ references to the ones in the hash. Specifically, mutating the value
+ will modify the hash itself.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
+ \sa QKeyValueIterator
+*/
+
/*! \fn template <class Key, class T> QHash<Key, T>::iterator QHash<Key, T>::erase(const_iterator pos)
\since 5.7
@@ -1616,11 +2522,9 @@ size_t qHash(long double key, size_t seed) noexcept
\snippet code/src_corelib_tools_qhash.cpp 15
- \sa remove(), take(), find()
-*/
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
-/*! \fn template <class Key, class T> QHash<Key, T>::iterator QHash<Key, T>::erase(iterator pos)
- \overload
+ \sa remove(), take(), find()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::iterator QHash<Key, T>::find(const Key &key)
@@ -1639,12 +2543,16 @@ size_t qHash(long double key, size_t seed) noexcept
\snippet code/src_corelib_tools_qhash.cpp 16
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa value(), values()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::find(const Key &key) const
\overload
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::constFind(const Key &key) const
@@ -1656,6 +2564,8 @@ size_t qHash(long double key, size_t seed) noexcept
If the hash contains no item with the \a key, the function
returns constEnd().
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa find()
*/
@@ -1665,17 +2575,23 @@ size_t qHash(long double key, size_t seed) noexcept
If there is already an item with the \a key, that item's value
is replaced with \a value.
+
+ Returns an iterator pointing to the new/updated element.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*!
- \fn template <typename T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(const Key &key, Args&&... args)
- \fn template <typename T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(Key &&key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(const Key &key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QHash<Key, T>::iterator QHash<Key, T>::emplace(Key &&key, Args&&... args)
Inserts a new element into the container. This new element
is constructed in-place using \a args as the arguments for its
construction.
Returns an iterator pointing to the new element.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
@@ -1686,9 +2602,6 @@ size_t qHash(long double key, size_t seed) noexcept
If a key is common to both hashes, its value will be replaced with the
value stored in \a other.
-
- \note If \a other contains multiple entries with the same key then the
- final value of the key is undefined.
*/
/*! \fn template <class Key, class T> bool QHash<Key, T>::empty() const
@@ -1698,17 +2611,21 @@ size_t qHash(long double key, size_t seed) noexcept
returns \c false.
*/
-/*! \fn template <class Key, class T> QPair<iterator, iterator> QMultiHash<Key, T>::equal_range(const Key &key)
+/*! \fn template <class Key, class T> std::pair<iterator, iterator> QMultiHash<Key, T>::equal_range(const Key &key)
\since 5.7
Returns a pair of iterators delimiting the range of values \c{[first, second)}, that
are stored under \a key. If the range is empty then both iterators will be equal to end().
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*!
- \fn template <class Key, class T> QPair<const_iterator, const_iterator> QMultiHash<Key, T>::equal_range(const Key &key) const
+ \fn template <class Key, class T> std::pair<const_iterator, const_iterator> QMultiHash<Key, T>::equal_range(const Key &key) const
\overload
\since 5.7
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*! \typedef QHash::ConstIterator
@@ -1805,12 +2722,6 @@ size_t qHash(long double key, size_t seed) noexcept
\inmodule QtCore
\brief The QHash::iterator class provides an STL-style non-const iterator for QHash.
- QHash features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
QHash\<Key, T\>::iterator allows you to iterate over a QHash
and to modify the value (but not the key) associated
with a particular key. If you want to iterate over a const QHash,
@@ -1831,31 +2742,15 @@ size_t qHash(long double key, size_t seed) noexcept
Unlike QMap, which orders its items by key, QHash stores its
items in an arbitrary order.
- Let's see a few examples of things we can do with a
- QHash::iterator that we cannot do with a QHash::const_iterator.
Here's an example that increments every value stored in the QHash
by 2:
\snippet code/src_corelib_tools_qhash.cpp 18
- Here's an example that removes all the items whose key is a
- string that starts with an underscore character:
-
- \snippet code/src_corelib_tools_qhash.cpp 19
-
- The call to QHash::erase() removes the item pointed to by the
- iterator from the hash, and returns an iterator to the next item.
- Here's another way of removing an item while iterating:
-
- \snippet code/src_corelib_tools_qhash.cpp 20
-
- It might be tempting to write code like this:
+ To remove elements from a QHash you can use erase_if(QHash\<Key, T\> &map, Predicate pred):
\snippet code/src_corelib_tools_qhash.cpp 21
- However, this will potentially crash in \c{++i}, because \c i is
- a dangling iterator after the call to erase().
-
Multiple iterators can be used on the same hash. However, be aware
that any modification performed directly on the QHash (inserting and
removing items) can cause the iterators to become invalid.
@@ -1866,10 +2761,6 @@ size_t qHash(long double key, size_t seed) noexcept
to grow/shrink its internal hash table.
Using any iterator after a rehashing operation has occurred will lead to undefined behavior.
- You can however safely use iterators to remove entries from the hash
- using the QHash::erase() method. This function can safely be called while
- iterating, and won't affect the order of items in the hash.
-
If you need to keep iterators over a long period of time, we recommend
that you use QMap rather than QHash.
@@ -1878,7 +2769,7 @@ size_t qHash(long double key, size_t seed) noexcept
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
- \sa QHash::const_iterator, QHash::key_iterator, QMutableHashIterator
+ \sa QHash::const_iterator, QHash::key_iterator, QHash::key_value_iterator
*/
/*! \fn template <class Key, class T> QHash<Key, T>::iterator::iterator()
@@ -1974,12 +2865,6 @@ size_t qHash(long double key, size_t seed) noexcept
\inmodule QtCore
\brief The QHash::const_iterator class provides an STL-style const iterator for QHash.
- QHash features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
QHash\<Key, T\>::const_iterator allows you to iterate over a
QHash. If you want to modify the QHash as you
iterate over it, you must use QHash::iterator instead. It is
@@ -1990,8 +2875,8 @@ size_t qHash(long double key, size_t seed) noexcept
The default QHash::const_iterator constructor creates an
uninitialized iterator. You must initialize it using a QHash
- function like QHash::constBegin(), QHash::constEnd(), or
- QHash::find() before you can start iterating. Here's a typical
+ function like QHash::cbegin(), QHash::cend(), or
+ QHash::constFind() before you can start iterating. Here's a typical
loop that prints all the (key, value) pairs stored in a hash:
\snippet code/src_corelib_tools_qhash.cpp 23
@@ -2012,12 +2897,16 @@ size_t qHash(long double key, size_t seed) noexcept
to grow/shrink its internal hash table.
Using any iterator after a rehashing operation has occurred will lead to undefined behavior.
+ You can however safely use iterators to remove entries from the hash
+ using the QHash::erase() method. This function can safely be called while
+ iterating, and won't affect the order of items in the hash.
+
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
- \sa QHash::iterator, QHashIterator
+ \sa QHash::iterator, QHash::key_iterator, QHash::const_key_value_iterator
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator::const_iterator()
@@ -2090,8 +2979,6 @@ size_t qHash(long double key, size_t seed) noexcept
item.
Calling this function on QHash::end() leads to undefined results.
-
- \sa operator--()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::const_iterator QHash<Key, T>::const_iterator::operator++(int)
@@ -2175,7 +3062,6 @@ size_t qHash(long double key, size_t seed) noexcept
Calling this function on QHash::keyEnd() leads to undefined results.
- \sa operator--()
*/
/*! \fn template <class Key, class T> QHash<Key, T>::key_iterator QHash<Key, T>::key_iterator::operator++(int)
@@ -2252,11 +3138,10 @@ size_t qHash(long double key, size_t seed) noexcept
hashes. A multi-valued hash is a hash that allows multiple values
with the same key.
- Because QMultiHash inherits QHash, all of QHash's functionality also
- applies to QMultiHash. For example, you can use isEmpty() to test
+ QMultiHash mostly mirrors QHash's API. For example, you can use isEmpty() to test
whether the hash is empty, and you can traverse a QMultiHash using
QHash's iterator classes (for example, QHashIterator). But opposed to
- QHash, it provides an insert() function will allow the insertion of
+ QHash, it provides an insert() function that allows the insertion of
multiple items with the same key. The replace() function corresponds to
QHash::insert(). It also provides convenient operator+() and
operator+=().
@@ -2307,17 +3192,12 @@ size_t qHash(long double key, size_t seed) noexcept
Constructs a multi-hash with a copy of each of the elements in the
initializer list \a list.
-
- This function is only available if the program is being
- compiled in C++11 mode.
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::QMultiHash(const QHash<Key, T> &other)
Constructs a copy of \a other (which can be a QHash or a
QMultiHash).
-
- \sa operator=()
*/
/*! \fn template <class Key, class T> template <class InputIterator> QMultiHash<Key, T>::QMultiHash(InputIterator begin, InputIterator end)
@@ -2325,8 +3205,8 @@ size_t qHash(long double key, size_t seed) noexcept
Constructs a multi-hash with a copy of each of the elements in the iterator range
[\a begin, \a end). Either the elements iterated by the range must be
- objects with \c{first} and \c{second} data members (like \c{QPair},
- \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the
+ objects with \c{first} and \c{second} data members (like \c{std::pair}),
+ convertible to \c Key and to \c T respectively; or the
iterators must have \c{key()} and \c{value()} member functions, returning a
key convertible to \c Key and a value convertible to \c T respectively.
*/
@@ -2341,6 +3221,10 @@ size_t qHash(long double key, size_t seed) noexcept
If there are multiple items with the \a key, the most
recently inserted item's value is replaced with \a value.
+ Returns an iterator pointing to the new/updated element.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa insert()
*/
@@ -2353,12 +3237,16 @@ size_t qHash(long double key, size_t seed) noexcept
different from replace(), which overwrites the value of an
existing item.)
+ Returns an iterator pointing to the new element.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa replace()
*/
/*!
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(const Key &key, Args&&... args)
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(Key &&key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(const Key &key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplace(Key &&key, Args&&... args)
Inserts a new element into the container. This new element
is constructed in-place using \a args as the arguments for its
@@ -2371,12 +3259,14 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an iterator pointing to the new element.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa insert
*/
/*!
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(const Key &key, Args&&... args)
- \fn template <typename T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(Key &&key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(const Key &key, Args&&... args)
+ \fn template <class Key, class T> template <typename ...Args> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::emplaceReplace(Key &&key, Args&&... args)
Inserts a new element into the container. This new element
is constructed in-place using \a args as the arguments for its
@@ -2387,6 +3277,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an iterator pointing to the new element.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa replace, emplace
*/
@@ -2400,6 +3292,16 @@ size_t qHash(long double key, size_t seed) noexcept
\sa insert()
*/
+
+/*! \fn template <class Key, class T> QMultiHash &QMultiHash<Key, T>::unite(const QHash<Key, T> &other)
+ \since 6.0
+
+ Inserts all the items in the \a other hash into this hash
+ and returns a reference to this hash.
+
+ \sa insert()
+*/
+
/*! \fn template <class Key, class T> QList<Key> QMultiHash<Key, T>::uniqueKeys() const
\since 5.13
@@ -2409,14 +3311,14 @@ size_t qHash(long double key, size_t seed) noexcept
\sa keys(), values()
*/
-/*! \fn template <class Key, class T> T QMultiHash<Key, T>::value(const Key &key, const T &defaultValue = T()) const
- \overload
+/*! \fn template <class Key, class T> T QMultiHash<Key, T>::value(const Key &key) const
+ \fn template <class Key, class T> T QMultiHash<Key, T>::value(const Key &key, const T &defaultValue) const
Returns the value associated with the \a key.
If the hash contains no item with the \a key, the function
- returns \a defaultValue, which is a \l{default-constructed value} if the
- parameter has not been specified.
+ returns \a defaultValue, or a \l{default-constructed value} if this
+ parameter has not been supplied.
If there are multiple
items for the \a key in the hash, the value of the most recently
@@ -2443,6 +3345,8 @@ size_t qHash(long double key, size_t seed) noexcept
If the hash contains multiple items with the \a key, this function returns
a reference to the most recently inserted value.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa insert(), value()
*/
@@ -2474,7 +3378,17 @@ size_t qHash(long double key, size_t seed) noexcept
*/
/*!
- \fn template <class Key, class T> int QMultiHash<Key, T>::remove(const Key &key, const T &value)
+ \fn template <class Key, class T> qsizetype QMultiHash<Key, T>::remove(const Key &key)
+ \since 4.3
+
+ Removes all the items that have the \a key from the hash.
+ Returns the number of items removed.
+
+ \sa remove()
+*/
+
+/*!
+ \fn template <class Key, class T> qsizetype QMultiHash<Key, T>::remove(const Key &key, const T &value)
\since 4.3
Removes all the items that have the \a key and the value \a
@@ -2483,6 +3397,30 @@ size_t qHash(long double key, size_t seed) noexcept
\sa remove()
*/
+/*!
+ \fn template <class Key, class T> void QMultiHash<Key, T>::clear()
+ \since 4.3
+
+ Removes all items from the hash and frees up all memory used by it.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> template <typename Predicate> qsizetype QMultiHash<Key, T>::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the multi hash.
+
+ The function supports predicates which take either an argument of
+ type \c{QMultiHash<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+
+ \sa clear(), take()
+*/
+
/*! \fn template <class Key, class T> T QMultiHash<Key, T>::take(const Key &key)
Removes the item with the \a key from the hash and returns
@@ -2506,6 +3444,10 @@ size_t qHash(long double key, size_t seed) noexcept
The order is guaranteed to be the same as that used by values().
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyBegin() to
+ \l keyEnd().
+
\sa values(), key()
*/
@@ -2518,15 +3460,21 @@ size_t qHash(long double key, size_t seed) noexcept
The order is guaranteed to be the same as that used by keys().
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyValueBegin() to
+ \l keyValueEnd().
+
\sa keys(), value()
*/
/*!
- \fn template <class Key, class T> Key QMultiHash<Key, T>::key(const T &value, const Key &defaultKey = Key()) const
+ \fn template <class Key, class T> Key QMultiHash<Key, T>::key(const T &value) const
+ \fn template <class Key, class T> Key QMultiHash<Key, T>::key(const T &value, const Key &defaultKey) const
\since 4.3
- Returns the first key mapped to \a value, or \a defaultKey if the
- hash contains no item mapped to \a value.
+ Returns the first key mapped to \a value. If the hash contains no item
+ mapped to \a value, returns \a defaultKey, or a \l{default-constructed
+ value}{default-constructed key} if this parameter has not been supplied.
This function can be slow (\l{linear time}), because QMultiHash's
internal data structure is optimized for fast lookup by key, not
@@ -2534,7 +3482,7 @@ size_t qHash(long double key, size_t seed) noexcept
*/
/*!
- \fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key, const T &value) const
+ \fn template <class Key, class T> qsizetype QMultiHash<Key, T>::count(const Key &key, const T &value) const
\since 4.3
Returns the number of items with the \a key and \a value.
@@ -2551,12 +3499,16 @@ size_t qHash(long double key, size_t seed) noexcept
If the hash contains multiple items with the \a key and \a value, the
iterator returned points to the most recently inserted item.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*!
\fn template <class Key, class T> typename QMultiHash<Key, T>::const_iterator QMultiHash<Key, T>::find(const Key &key, const T &value) const
\since 4.3
\overload
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*!
@@ -2568,6 +3520,8 @@ size_t qHash(long double key, size_t seed) noexcept
If the hash contains no such item, the function returns
constEnd().
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::begin()
@@ -2575,12 +3529,16 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa constBegin(), end()
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::const_iterator QMultiHash<Key, T>::begin() const
\overload
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::const_iterator QMultiHash<Key, T>::cbegin() const
@@ -2589,6 +3547,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa begin(), cend()
*/
@@ -2597,6 +3557,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa begin(), constEnd()
*/
@@ -2606,6 +3568,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyEnd()
*/
@@ -2614,6 +3578,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
after the last item in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa begin(), constEnd()
*/
@@ -2627,6 +3593,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
item after the last item in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa constBegin(), end()
*/
@@ -2636,6 +3604,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
item after the last item in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa cbegin(), end()
*/
@@ -2645,6 +3615,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
item after the last key in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyBegin()
*/
@@ -2654,6 +3626,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueEnd()
*/
@@ -2663,6 +3637,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
entry after the last entry in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueBegin()
*/
@@ -2672,6 +3648,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueEnd()
*/
@@ -2681,6 +3659,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueBegin()
*/
@@ -2690,6 +3670,8 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
entry after the last entry in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa keyValueBegin()
*/
@@ -2699,20 +3681,36 @@ size_t qHash(long double key, size_t seed) noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
entry after the last entry in the hash.
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
\sa constKeyValueBegin()
*/
+/*! \fn template <class Key, class T> auto QMultiHash<Key, T>::asKeyValueRange() &
+ \fn template <class Key, class T> auto QMultiHash<Key, T>::asKeyValueRange() const &
+ \fn template <class Key, class T> auto QMultiHash<Key, T>::asKeyValueRange() &&
+ \fn template <class Key, class T> auto QMultiHash<Key, T>::asKeyValueRange() const &&
+ \since 6.4
+
+ Returns a range object that allows iteration over this hash as
+ key/value pairs. For instance, this range object can be used in a
+ range-based for loop, in combination with a structured binding declaration:
+
+ \snippet code/src_corelib_tools_qhash.cpp 35
+
+ Note that both the key and the value obtained this way are
+ references to the ones in the hash. Specifically, mutating the value
+ will modify the hash itself.
+
+ \include qhash.cpp qhash-iterator-invalidation-func-desc
+
+ \sa QKeyValueIterator
+*/
/*! \class QMultiHash::iterator
\inmodule QtCore
\brief The QMultiHash::iterator class provides an STL-style non-const iterator for QMultiHash.
- QMultiHash features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
QMultiHash\<Key, T\>::iterator allows you to iterate over a QMultiHash
and to modify the value (but not the key) associated
with a particular key. If you want to iterate over a const QMultiHash,
@@ -2733,31 +3731,15 @@ size_t qHash(long double key, size_t seed) noexcept
Unlike QMap, which orders its items by key, QMultiHash stores its
items in an arbitrary order.
- Let's see a few examples of things we can do with a
- QMultiHash::iterator that we cannot do with a QMultiHash::const_iterator.
Here's an example that increments every value stored in the QMultiHash
by 2:
\snippet code/src_corelib_tools_qhash.cpp 18
- Here's an example that removes all the items whose key is a
- string that starts with an underscore character:
-
- \snippet code/src_corelib_tools_qhash.cpp 19
-
- The call to QMultiHash::erase() removes the item pointed to by the
- iterator from the hash, and returns an iterator to the next item.
- Here's another way of removing an item while iterating:
-
- \snippet code/src_corelib_tools_qhash.cpp 20
-
- It might be tempting to write code like this:
+ To remove elements from a QMultiHash you can use erase_if(QMultiHash\<Key, T\> &map, Predicate pred):
\snippet code/src_corelib_tools_qhash.cpp 21
- However, this will potentially crash in \c{++i}, because \c i is
- a dangling iterator after the call to erase().
-
Multiple iterators can be used on the same hash. However, be aware
that any modification performed directly on the QHash (inserting and
removing items) can cause the iterators to become invalid.
@@ -2768,10 +3750,6 @@ size_t qHash(long double key, size_t seed) noexcept
to grow/shrink its internal hash table.
Using any iterator after a rehashing operation has occurred will lead to undefined behavior.
- You can however safely use iterators to remove entries from the hash
- using the QHash::erase() method. This function can safely be called while
- iterating, and won't affect the order of items in the hash.
-
If you need to keep iterators over a long period of time, we recommend
that you use QMultiMap rather than QHash.
@@ -2780,7 +3758,7 @@ size_t qHash(long double key, size_t seed) noexcept
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
- \sa QMultiHash::const_iterator, QMultiHash::key_iterator, QMutableHashIterator
+ \sa QMultiHash::const_iterator, QMultiHash::key_iterator, QMultiHash::key_value_iterator
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::iterator::iterator()
@@ -2876,12 +3854,6 @@ size_t qHash(long double key, size_t seed) noexcept
\inmodule QtCore
\brief The QMultiHash::const_iterator class provides an STL-style const iterator for QMultiHash.
- QMultiHash features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
QMultiHash\<Key, T\>::const_iterator allows you to iterate over a
QMultiHash. If you want to modify the QMultiHash as you
iterate over it, you must use QMultiHash::iterator instead. It is
@@ -2892,8 +3864,8 @@ size_t qHash(long double key, size_t seed) noexcept
The default QMultiHash::const_iterator constructor creates an
uninitialized iterator. You must initialize it using a QMultiHash
- function like QMultiHash::constBegin(), QMultiHash::constEnd(), or
- QMultiHash::find() before you can start iterating. Here's a typical
+ function like QMultiHash::cbegin(), QMultiHash::cend(), or
+ QMultiHash::constFind() before you can start iterating. Here's a typical
loop that prints all the (key, value) pairs stored in a hash:
\snippet code/src_corelib_tools_qhash.cpp 23
@@ -2905,28 +3877,24 @@ size_t qHash(long double key, size_t seed) noexcept
recently to the least recently inserted value.
Multiple iterators can be used on the same hash. However, be aware
- that any modification performed directly on the QHash (inserting and
+ that any modification performed directly on the QMultiHash (inserting and
removing items) can cause the iterators to become invalid.
- Inserting items into the hash or calling methods such as QHash::reserve()
- or QHash::squeeze() can invalidate all iterators pointing into the hash.
- Iterators are guaranteed to stay valid only as long as the QHash doesn't have
+ Inserting items into the hash or calling methods such as QMultiHash::reserve()
+ or QMultiHash::squeeze() can invalidate all iterators pointing into the hash.
+ Iterators are guaranteed to stay valid only as long as the QMultiHash doesn't have
to grow/shrink it's internal hash table.
Using any iterator after a rehashing operation ahs occurred will lead to undefined behavior.
- You can however safely use iterators to remove entries from the hash
- using the QHash::erase() method. This function can safely be called while
- iterating, and won't affect the order of items in the hash.
-
If you need to keep iterators over a long period of time, we recommend
- that you use QMap rather than QHash.
+ that you use QMultiMap rather than QMultiHash.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
- \sa QMultiHash::iterator, QMultiHashIterator
+ \sa QMultiHash::iterator, QMultiHash::key_iterator, QMultiHash::const_key_value_iterator
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::const_iterator::const_iterator()
@@ -2999,8 +3967,6 @@ size_t qHash(long double key, size_t seed) noexcept
item.
Calling this function on QMultiHash::end() leads to undefined results.
-
- \sa operator--()
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::const_iterator QMultiHash<Key, T>::const_iterator::operator++(int)
@@ -3083,8 +4049,6 @@ size_t qHash(long double key, size_t seed) noexcept
item.
Calling this function on QMultiHash::keyEnd() leads to undefined results.
-
- \sa operator--()
*/
/*! \fn template <class Key, class T> QMultiHash<Key, T>::key_iterator QMultiHash<Key, T>::key_iterator::operator++(int)
@@ -3166,4 +4130,64 @@ size_t qHash(long double key, size_t seed) noexcept
Type \c T must be supported by qHash().
*/
+/*! \fn template <typename Key, typename T, typename Predicate> qsizetype erase_if(QHash<Key, T> &hash, Predicate pred)
+ \relates QHash
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the hash \a hash.
+
+ The function supports predicates which take either an argument of
+ type \c{QHash<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+*/
+
+/*! \fn template <typename Key, typename T, typename Predicate> qsizetype erase_if(QMultiHash<Key, T> &hash, Predicate pred)
+ \relates QMultiHash
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the multi hash \a hash.
+
+ The function supports predicates which take either an argument of
+ type \c{QMultiHash<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+*/
+
+#ifdef QT_HAS_CONSTEXPR_BITOPS
+namespace QHashPrivate {
+static_assert(qPopulationCount(SpanConstants::NEntries) == 1,
+ "NEntries must be a power of 2 for bucketForHash() to work.");
+
+// ensure the size of a Span does not depend on the template parameters
+using Node1 = Node<int, int>;
+static_assert(sizeof(Span<Node1>) == sizeof(Span<Node<char, void *>>));
+static_assert(sizeof(Span<Node1>) == sizeof(Span<Node<qsizetype, QHashDummyValue>>));
+static_assert(sizeof(Span<Node1>) == sizeof(Span<Node<QString, QVariant>>));
+static_assert(sizeof(Span<Node1>) > SpanConstants::NEntries);
+static_assert(qNextPowerOfTwo(sizeof(Span<Node1>)) == SpanConstants::NEntries * 2);
+
+// ensure allocations are always a power of two, at a minimum NEntries,
+// obeying the fomula
+// qNextPowerOfTwo(2 * N);
+// without overflowing
+static constexpr size_t NEntries = SpanConstants::NEntries;
+static_assert(GrowthPolicy::bucketsForCapacity(1) == NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries / 2 + 0) == NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries / 2 + 1) == 2 * NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries * 1 - 1) == 2 * NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries * 1 + 0) == 4 * NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries * 1 + 1) == 4 * NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries * 2 - 1) == 4 * NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(NEntries * 2 + 0) == 8 * NEntries);
+static_assert(GrowthPolicy::bucketsForCapacity(SIZE_MAX / 4) == SIZE_MAX / 2 + 1);
+static_assert(GrowthPolicy::bucketsForCapacity(SIZE_MAX / 2) == SIZE_MAX);
+static_assert(GrowthPolicy::bucketsForCapacity(SIZE_MAX) == SIZE_MAX);
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 2de3989eb2..e7cd4123fb 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -1,53 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QHASH_H
#define QHASH_H
+#include <QtCore/qalgorithms.h>
#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qhashfunctions.h>
#include <QtCore/qiterator.h>
#include <QtCore/qlist.h>
-#include <QtCore/qmath.h>
#include <QtCore/qrefcount.h>
#include <initializer_list>
+#include <functional> // for std::hash
+
+class tst_QHash; // for befriending
QT_BEGIN_NAMESPACE
@@ -58,25 +26,44 @@ struct QHashDummyValue
namespace QHashPrivate {
-// QHash uses a power of two growth policy.
-namespace GrowthPolicy
-{
-inline constexpr size_t maxNumBuckets() noexcept
-{
- return size_t(1) << (8*sizeof(size_t) - 1);
-}
-inline constexpr size_t bucketsForCapacity(size_t requestedCapacity) noexcept
-{
- if (requestedCapacity <= 8)
- return 16;
- if (requestedCapacity >= maxNumBuckets())
- return maxNumBuckets();
- return qNextPowerOfTwo(QIntegerForSize<sizeof(size_t)>::Unsigned(2*requestedCapacity - 1));
-}
-inline constexpr size_t bucketForHash(size_t nBuckets, size_t hash) noexcept
+template <typename T, typename = void>
+constexpr inline bool HasQHashOverload = false;
+
+template <typename T>
+constexpr inline bool HasQHashOverload<T, std::enable_if_t<
+ std::is_convertible_v<decltype(qHash(std::declval<const T &>(), std::declval<size_t>())), size_t>
+>> = true;
+
+template <typename T, typename = void>
+constexpr inline bool HasStdHashSpecializationWithSeed = false;
+
+template <typename T>
+constexpr inline bool HasStdHashSpecializationWithSeed<T, std::enable_if_t<
+ std::is_convertible_v<decltype(std::hash<T>()(std::declval<const T &>(), std::declval<size_t>())), size_t>
+>> = true;
+
+template <typename T, typename = void>
+constexpr inline bool HasStdHashSpecializationWithoutSeed = false;
+
+template <typename T>
+constexpr inline bool HasStdHashSpecializationWithoutSeed<T, std::enable_if_t<
+ std::is_convertible_v<decltype(std::hash<T>()(std::declval<const T &>())), size_t>
+>> = true;
+
+template <typename T>
+size_t calculateHash(const T &t, size_t seed = 0)
{
- return hash & (nBuckets - 1);
-}
+ if constexpr (HasQHashOverload<T>) {
+ return qHash(t, seed);
+ } else if constexpr (HasStdHashSpecializationWithSeed<T>) {
+ return std::hash<T>()(t, seed);
+ } else if constexpr (HasStdHashSpecializationWithoutSeed<T>) {
+ Q_UNUSED(seed);
+ return std::hash<T>()(t);
+ } else {
+ static_assert(sizeof(T) == 0, "The key type must have a qHash overload or a std::hash specialization");
+ return 0;
+ }
}
template <typename Key, typename T>
@@ -185,9 +172,8 @@ struct MultiNode
MultiNode(MultiNode &&other)
: key(other.key),
- value(other.value)
+ value(std::exchange(other.value, nullptr))
{
- other.value = nullptr;
}
MultiNode(const MultiNode &other)
@@ -217,16 +203,13 @@ struct MultiNode
void insertMulti(Args &&... args)
{
Chain *e = new Chain{ T(std::forward<Args>(args)...), nullptr };
- e->next = value;
- value = e;
+ e->next = std::exchange(value, e);
}
template<typename ...Args>
void emplaceValue(Args &&... args)
{
value->value = T(std::forward<Args>(args)...);
}
-
- // compiler generated move operators are fine
};
template<typename Node>
@@ -235,6 +218,15 @@ constexpr bool isRelocatable()
return QTypeInfo<typename Node::KeyType>::isRelocatable && QTypeInfo<typename Node::ValueType>::isRelocatable;
}
+struct SpanConstants {
+ static constexpr size_t SpanShift = 7;
+ static constexpr size_t NEntries = (1 << SpanShift);
+ static constexpr size_t LocalBucketMask = (NEntries - 1);
+ static constexpr size_t UnusedEntry = 0xff;
+
+ static_assert ((NEntries & LocalBucketMask) == 0, "NEntries must be a power of two.");
+};
+
// Regular hash tables consist of a list of buckets that can store Nodes. But simply allocating one large array of buckets
// would waste a lot of memory. To avoid this, we split the vector of buckets up into a vector of Spans. Each Span represents
// NEntries buckets. To quickly find the correct Span that holds a bucket, NEntries must be a power of two.
@@ -245,13 +237,6 @@ constexpr bool isRelocatable()
// table have a very small memory overhead compared to many other implementations.
template<typename Node>
struct Span {
- enum {
- NEntries = 128,
- LocalBucketMask = (NEntries - 1),
- UnusedEntry = 0xff
- };
- static_assert ((NEntries & LocalBucketMask) == 0, "EntriesPerSpan must be a power of two.");
-
// Entry is a slot available for storing a Node. The Span holds a pointer to
// an array of Entries. Upon construction of the array, those entries are
// unused, and nextFree() is being used to set up a singly linked list
@@ -259,19 +244,19 @@ struct Span {
// When a node gets inserted, the first free entry is being picked, removed
// from the singly linked list and the Node gets constructed in place.
struct Entry {
- typename std::aligned_storage<sizeof(Node), alignof(Node)>::type storage;
+ struct { alignas(Node) unsigned char data[sizeof(Node)]; } storage;
unsigned char &nextFree() { return *reinterpret_cast<unsigned char *>(&storage); }
Node &node() { return *reinterpret_cast<Node *>(&storage); }
};
- unsigned char offsets[NEntries];
+ unsigned char offsets[SpanConstants::NEntries];
Entry *entries = nullptr;
unsigned char allocated = 0;
unsigned char nextFree = 0;
Span() noexcept
{
- memset(offsets, UnusedEntry, sizeof(offsets));
+ memset(offsets, SpanConstants::UnusedEntry, sizeof(offsets));
}
~Span()
{
@@ -282,18 +267,18 @@ struct Span {
if (entries) {
if constexpr (!std::is_trivially_destructible<Node>::value) {
for (auto o : offsets) {
- if (o != UnusedEntry)
+ if (o != SpanConstants::UnusedEntry)
entries[o].node().~Node();
}
}
- delete [] entries;
+ delete[] entries;
entries = nullptr;
}
}
Node *insert(size_t i)
{
- Q_ASSERT(i <= NEntries);
- Q_ASSERT(offsets[i] == UnusedEntry);
+ Q_ASSERT(i < SpanConstants::NEntries);
+ Q_ASSERT(offsets[i] == SpanConstants::UnusedEntry);
if (nextFree == allocated)
addStorage();
unsigned char entry = nextFree;
@@ -304,11 +289,11 @@ struct Span {
}
void erase(size_t bucket) noexcept(std::is_nothrow_destructible<Node>::value)
{
- Q_ASSERT(bucket <= NEntries);
- Q_ASSERT(offsets[bucket] != UnusedEntry);
+ Q_ASSERT(bucket < SpanConstants::NEntries);
+ Q_ASSERT(offsets[bucket] != SpanConstants::UnusedEntry);
unsigned char entry = offsets[bucket];
- offsets[bucket] = UnusedEntry;
+ offsets[bucket] = SpanConstants::UnusedEntry;
entries[entry].node().~Node();
entries[entry].nextFree() = nextFree;
@@ -320,19 +305,19 @@ struct Span {
}
bool hasNode(size_t i) const noexcept
{
- return (offsets[i] != UnusedEntry);
+ return (offsets[i] != SpanConstants::UnusedEntry);
}
Node &at(size_t i) noexcept
{
- Q_ASSERT(i <= NEntries);
- Q_ASSERT(offsets[i] != UnusedEntry);
+ Q_ASSERT(i < SpanConstants::NEntries);
+ Q_ASSERT(offsets[i] != SpanConstants::UnusedEntry);
return entries[offsets[i]].node();
}
const Node &at(size_t i) const noexcept
{
- Q_ASSERT(i <= NEntries);
- Q_ASSERT(offsets[i] != UnusedEntry);
+ Q_ASSERT(i < SpanConstants::NEntries);
+ Q_ASSERT(offsets[i] != SpanConstants::UnusedEntry);
return entries[offsets[i]].node();
}
@@ -350,17 +335,17 @@ struct Span {
}
void moveLocal(size_t from, size_t to) noexcept
{
- Q_ASSERT(offsets[from] != UnusedEntry);
- Q_ASSERT(offsets[to] == UnusedEntry);
+ Q_ASSERT(offsets[from] != SpanConstants::UnusedEntry);
+ Q_ASSERT(offsets[to] == SpanConstants::UnusedEntry);
offsets[to] = offsets[from];
- offsets[from] = UnusedEntry;
+ offsets[from] = SpanConstants::UnusedEntry;
}
void moveFromSpan(Span &fromSpan, size_t fromIndex, size_t to) noexcept(std::is_nothrow_move_constructible_v<Node>)
{
- Q_ASSERT(to <= NEntries);
- Q_ASSERT(offsets[to] == UnusedEntry);
- Q_ASSERT(fromIndex <= NEntries);
- Q_ASSERT(fromSpan.offsets[fromIndex] != UnusedEntry);
+ Q_ASSERT(to < SpanConstants::NEntries);
+ Q_ASSERT(offsets[to] == SpanConstants::UnusedEntry);
+ Q_ASSERT(fromIndex < SpanConstants::NEntries);
+ Q_ASSERT(fromSpan.offsets[fromIndex] != SpanConstants::UnusedEntry);
if (nextFree == allocated)
addStorage();
Q_ASSERT(nextFree < allocated);
@@ -369,7 +354,7 @@ struct Span {
nextFree = toEntry.nextFree();
size_t fromOffset = fromSpan.offsets[fromIndex];
- fromSpan.offsets[fromIndex] = UnusedEntry;
+ fromSpan.offsets[fromIndex] = SpanConstants::UnusedEntry;
Entry &fromEntry = fromSpan.entries[fromOffset];
if constexpr (isRelocatable<Node>()) {
@@ -384,35 +369,77 @@ struct Span {
void addStorage()
{
- Q_ASSERT(allocated < NEntries);
+ Q_ASSERT(allocated < SpanConstants::NEntries);
Q_ASSERT(nextFree == allocated);
// the hash table should always be between 25 and 50% full
// this implies that we on average have between 32 and 64 entries
- // in here. The likelihood of having below 16 entries is very small,
- // so start with that and increment by 16 each time we need to add
- // some more space
- const size_t increment = NEntries/8;
- size_t alloc = allocated + increment;
+ // in here. More exactly, we have a binominal distribution of the amount of
+ // occupied entries.
+ // For a 25% filled table, the average is 32 entries, with a 95% chance that we have between
+ // 23 and 41 entries.
+ // For a 50% filled table, the average is 64 entries, with a 95% chance that we have between
+ // 53 and 75 entries.
+ // Since we only resize the table once it's 50% filled and we want to avoid copies of
+ // data where possible, we initially allocate 48 entries, then resize to 80 entries, after that
+ // resize by increments of 16. That way, we usually only get one resize of the table
+ // while filling it.
+ size_t alloc;
+ static_assert(SpanConstants::NEntries % 8 == 0);
+ if (!allocated)
+ alloc = SpanConstants::NEntries / 8 * 3;
+ else if (allocated == SpanConstants::NEntries / 8 * 3)
+ alloc = SpanConstants::NEntries / 8 * 5;
+ else
+ alloc = allocated + SpanConstants::NEntries/8;
Entry *newEntries = new Entry[alloc];
// we only add storage if the previous storage was fully filled, so
// simply copy the old data over
if constexpr (isRelocatable<Node>()) {
- memcpy(newEntries, entries, allocated*sizeof(Entry));
+ if (allocated)
+ memcpy(newEntries, entries, allocated * sizeof(Entry));
} else {
for (size_t i = 0; i < allocated; ++i) {
new (&newEntries[i].node()) Node(std::move(entries[i].node()));
entries[i].node().~Node();
}
}
- for (size_t i = allocated; i < allocated + increment; ++i) {
+ for (size_t i = allocated; i < alloc; ++i) {
newEntries[i].nextFree() = uchar(i + 1);
}
- delete [] entries;
+ delete[] entries;
entries = newEntries;
allocated = uchar(alloc);
}
};
+// QHash uses a power of two growth policy.
+namespace GrowthPolicy {
+inline constexpr size_t bucketsForCapacity(size_t requestedCapacity) noexcept
+{
+ constexpr int SizeDigits = std::numeric_limits<size_t>::digits;
+
+ // We want to use at minimum a full span (128 entries), so we hardcode it for any requested
+ // capacity <= 64. Any capacity above that gets rounded to a later power of two.
+ if (requestedCapacity <= 64)
+ return SpanConstants::NEntries;
+
+ // Same as
+ // qNextPowerOfTwo(2 * requestedCapacity);
+ //
+ // but ensuring neither our multiplication nor the function overflow.
+ // Additionally, the maximum memory allocation is 2^31-1 or 2^63-1 bytes
+ // (limited by qsizetype and ptrdiff_t).
+ int count = qCountLeadingZeroBits(requestedCapacity);
+ if (count < 2)
+ return (std::numeric_limits<size_t>::max)(); // will cause std::bad_alloc
+ return size_t(1) << (SizeDigits - count + 1);
+}
+inline constexpr size_t bucketForHash(size_t nBuckets, size_t hash) noexcept
+{
+ return hash & (nBuckets - 1);
+}
+} // namespace GrowthPolicy
+
template <typename Node>
struct iterator;
@@ -428,43 +455,148 @@ struct Data
size_t size = 0;
size_t numBuckets = 0;
size_t seed = 0;
+ Span *spans = nullptr;
+ static constexpr size_t maxNumBuckets() noexcept
+ {
+ return (std::numeric_limits<ptrdiff_t>::max)() / sizeof(Span);
+ }
- Span *spans = nullptr;
+ struct Bucket {
+ Span *span;
+ size_t index;
+
+ Bucket(Span *s, size_t i) noexcept
+ : span(s), index(i)
+ {}
+ Bucket(const Data *d, size_t bucket) noexcept
+ : span(d->spans + (bucket >> SpanConstants::SpanShift)),
+ index(bucket & SpanConstants::LocalBucketMask)
+ {}
+ Bucket(iterator it) noexcept
+ : Bucket(it.d, it.bucket)
+ {}
+
+ size_t toBucketIndex(const Data *d) const noexcept
+ {
+ return ((span - d->spans) << SpanConstants::SpanShift) | index;
+ }
+ iterator toIterator(const Data *d) const noexcept { return iterator{d, toBucketIndex(d)}; }
+ void advanceWrapped(const Data *d) noexcept
+ {
+ advance_impl(d, d->spans);
+ }
+ void advance(const Data *d) noexcept
+ {
+ advance_impl(d, nullptr);
+ }
+ bool isUnused() const noexcept
+ {
+ return !span->hasNode(index);
+ }
+ size_t offset() const noexcept
+ {
+ return span->offset(index);
+ }
+ Node &nodeAtOffset(size_t offset)
+ {
+ return span->atOffset(offset);
+ }
+ Node *node()
+ {
+ return &span->at(index);
+ }
+ Node *insert() const
+ {
+ return span->insert(index);
+ }
+
+ private:
+ friend bool operator==(Bucket lhs, Bucket rhs) noexcept
+ {
+ return lhs.span == rhs.span && lhs.index == rhs.index;
+ }
+ friend bool operator!=(Bucket lhs, Bucket rhs) noexcept { return !(lhs == rhs); }
+
+ void advance_impl(const Data *d, Span *whenAtEnd) noexcept
+ {
+ Q_ASSERT(span);
+ ++index;
+ if (Q_UNLIKELY(index == SpanConstants::NEntries)) {
+ index = 0;
+ ++span;
+ if (span - d->spans == ptrdiff_t(d->numBuckets >> SpanConstants::SpanShift))
+ span = whenAtEnd;
+ }
+ }
+ };
+
+ static auto allocateSpans(size_t numBuckets)
+ {
+ struct R {
+ Span *spans;
+ size_t nSpans;
+ };
+
+ constexpr qptrdiff MaxSpanCount = (std::numeric_limits<qptrdiff>::max)() / sizeof(Span);
+ constexpr size_t MaxBucketCount = MaxSpanCount << SpanConstants::SpanShift;
+
+ if (numBuckets > MaxBucketCount) {
+ Q_CHECK_PTR(false);
+ Q_UNREACHABLE(); // no exceptions and no assertions -> no error reporting
+ }
+
+ size_t nSpans = numBuckets >> SpanConstants::SpanShift;
+ return R{ new Span[nSpans], nSpans };
+ }
Data(size_t reserve = 0)
{
numBuckets = GrowthPolicy::bucketsForCapacity(reserve);
- size_t nSpans = (numBuckets + Span::LocalBucketMask) / Span::NEntries;
- spans = new Span[nSpans];
- seed = qGlobalQHashSeed();
+ spans = allocateSpans(numBuckets).spans;
+ seed = QHashSeed::globalSeed();
}
- Data(const Data &other, size_t reserved = 0)
- : size(other.size),
- numBuckets(other.numBuckets),
- seed(other.seed)
- {
- if (reserved)
- numBuckets = GrowthPolicy::bucketsForCapacity(qMax(size, reserved));
- bool resized = numBuckets != other.numBuckets;
- size_t nSpans = (numBuckets + Span::LocalBucketMask) / Span::NEntries;
- spans = new Span[nSpans];
+ void reallocationHelper(const Data &other, size_t nSpans, bool resized)
+ {
for (size_t s = 0; s < nSpans; ++s) {
const Span &span = other.spans[s];
- for (size_t index = 0; index < Span::NEntries; ++index) {
+ for (size_t index = 0; index < SpanConstants::NEntries; ++index) {
if (!span.hasNode(index))
continue;
const Node &n = span.at(index);
- iterator it = resized ? find(n.key) : iterator{ this, s*Span::NEntries + index };
+ auto it = resized ? findBucket(n.key) : Bucket { spans + s, index };
Q_ASSERT(it.isUnused());
- Node *newNode = spans[it.span()].insert(it.index());
+ Node *newNode = it.insert();
new (newNode) Node(n);
}
}
}
- static Data *detached(Data *d, size_t size = 0)
+ Data(const Data &other) : size(other.size), numBuckets(other.numBuckets), seed(other.seed)
+ {
+ auto r = allocateSpans(numBuckets);
+ spans = r.spans;
+ reallocationHelper(other, r.nSpans, false);
+ }
+ Data(const Data &other, size_t reserved) : size(other.size), seed(other.seed)
+ {
+ numBuckets = GrowthPolicy::bucketsForCapacity(qMax(size, reserved));
+ spans = allocateSpans(numBuckets).spans;
+ size_t otherNSpans = other.numBuckets >> SpanConstants::SpanShift;
+ reallocationHelper(other, otherNSpans, numBuckets != other.numBuckets);
+ }
+
+ static Data *detached(Data *d)
+ {
+ if (!d)
+ return new Data;
+ Data *dd = new Data(*d);
+ if (!d->ref.deref())
+ delete d;
+ return dd;
+ }
+ static Data *detached(Data *d, size_t size)
{
if (!d)
return new Data(size);
@@ -474,10 +606,9 @@ struct Data
return dd;
}
-
void clear()
{
- delete [] spans;
+ delete[] spans;
spans = nullptr;
size = 0;
numBuckets = 0;
@@ -509,25 +640,24 @@ struct Data
Span *oldSpans = spans;
size_t oldBucketCount = numBuckets;
- size_t nSpans = (newBucketCount + Span::LocalBucketMask) / Span::NEntries;
- spans = new Span[nSpans];
+ spans = allocateSpans(newBucketCount).spans;
numBuckets = newBucketCount;
- size_t oldNSpans = (oldBucketCount + Span::LocalBucketMask) / Span::NEntries;
+ size_t oldNSpans = oldBucketCount >> SpanConstants::SpanShift;
for (size_t s = 0; s < oldNSpans; ++s) {
Span &span = oldSpans[s];
- for (size_t index = 0; index < Span::NEntries; ++index) {
+ for (size_t index = 0; index < SpanConstants::NEntries; ++index) {
if (!span.hasNode(index))
continue;
Node &n = span.at(index);
- iterator it = find(n.key);
+ auto it = findBucket(n.key);
Q_ASSERT(it.isUnused());
- Node *newNode = spans[it.span()].insert(it.index());
+ Node *newNode = it.insert();
new (newNode) Node(std::move(n));
}
span.freeData();
}
- delete [] oldSpans;
+ delete[] oldSpans;
}
size_t nextBucket(size_t bucket) const noexcept
@@ -547,104 +677,94 @@ struct Data
return size >= (numBuckets >> 1);
}
- iterator find(const Key &key) const noexcept
+ template <typename K> Bucket findBucket(const K &key) const noexcept
{
+ static_assert(std::is_same_v<std::remove_cv_t<Key>, K> ||
+ QHashHeterogeneousSearch<std::remove_cv_t<Key>, K>::value);
Q_ASSERT(numBuckets > 0);
- size_t hash = qHash(key, seed);
- size_t bucket = GrowthPolicy::bucketForHash(numBuckets, hash);
+ size_t hash = QHashPrivate::calculateHash(key, seed);
+ Bucket bucket(this, GrowthPolicy::bucketForHash(numBuckets, hash));
// loop over the buckets until we find the entry we search for
// or an empty slot, in which case we know the entry doesn't exist
while (true) {
- // Split the bucket into the indexex of span array, and the local
- // offset inside the span
- size_t span = bucket / Span::NEntries;
- size_t index = bucket & Span::LocalBucketMask;
- Span &s = spans[span];
- size_t offset = s.offset(index);
- if (offset == Span::UnusedEntry) {
- return iterator{ this, bucket };
+ size_t offset = bucket.offset();
+ if (offset == SpanConstants::UnusedEntry) {
+ return bucket;
} else {
- Node &n = s.atOffset(offset);
- if (n.key == key)
- return iterator{ this, bucket };
+ Node &n = bucket.nodeAtOffset(offset);
+ if (qHashEquals(n.key, key))
+ return bucket;
}
- bucket = nextBucket(bucket);
+ bucket.advanceWrapped(this);
}
}
- Node *findNode(const Key &key) const noexcept
+ template <typename K> Node *findNode(const K &key) const noexcept
{
- if (!size)
+ auto bucket = findBucket(key);
+ if (bucket.isUnused())
return nullptr;
- iterator it = find(key);
- if (it.isUnused())
- return nullptr;
- return it.node();
+ return bucket.node();
}
- struct InsertionResult {
+ struct InsertionResult
+ {
iterator it;
bool initialized;
};
- InsertionResult findOrInsert(const Key &key) noexcept
+ template <typename K> InsertionResult findOrInsert(const K &key) noexcept
{
- if (shouldGrow())
+ Bucket it(static_cast<Span *>(nullptr), 0);
+ if (numBuckets > 0) {
+ it = findBucket(key);
+ if (!it.isUnused())
+ return { it.toIterator(this), true };
+ }
+ if (shouldGrow()) {
rehash(size + 1);
- iterator it = find(key);
- if (it.isUnused()) {
- spans[it.span()].insert(it.index());
- ++size;
- return { it, false };
+ it = findBucket(key); // need to get a new iterator after rehashing
}
- return { it, true };
+ Q_ASSERT(it.span != nullptr);
+ Q_ASSERT(it.isUnused());
+ it.insert();
+ ++size;
+ return { it.toIterator(this), false };
}
- iterator erase(iterator it) noexcept(std::is_nothrow_destructible<Node>::value)
+ void erase(Bucket bucket) noexcept(std::is_nothrow_destructible<Node>::value)
{
- size_t bucket = it.bucket;
- size_t span = bucket / Span::NEntries;
- size_t index = bucket & Span::LocalBucketMask;
- Q_ASSERT(spans[span].hasNode(index));
- spans[span].erase(index);
+ Q_ASSERT(bucket.span->hasNode(bucket.index));
+ bucket.span->erase(bucket.index);
--size;
// re-insert the following entries to avoid holes
- size_t hole = bucket;
- size_t next = bucket;
+ Bucket next = bucket;
while (true) {
- next = nextBucket(next);
- size_t nextSpan = next / Span::NEntries;
- size_t nextIndex = next & Span::LocalBucketMask;
- if (!spans[nextSpan].hasNode(nextIndex))
- break;
- size_t hash = qHash(spans[nextSpan].at(nextIndex).key, seed);
- size_t newBucket = GrowthPolicy::bucketForHash(numBuckets, hash);
+ next.advanceWrapped(this);
+ size_t offset = next.offset();
+ if (offset == SpanConstants::UnusedEntry)
+ return;
+ size_t hash = QHashPrivate::calculateHash(next.nodeAtOffset(offset).key, seed);
+ Bucket newBucket(this, GrowthPolicy::bucketForHash(numBuckets, hash));
while (true) {
if (newBucket == next) {
// nothing to do, item is at the right plae
break;
- } else if (newBucket == hole) {
- // move into hole
- size_t holeSpan = hole / Span::NEntries;
- size_t holeIndex = hole & Span::LocalBucketMask;
- if (nextSpan == holeSpan) {
- spans[holeSpan].moveLocal(nextIndex, holeIndex);
+ } else if (newBucket == bucket) {
+ // move into the hole we created earlier
+ if (next.span == bucket.span) {
+ bucket.span->moveLocal(next.index, bucket.index);
} else {
// move between spans, more expensive
- spans[holeSpan].moveFromSpan(spans[nextSpan], nextIndex, holeIndex);
+ bucket.span->moveFromSpan(*next.span, next.index, bucket.index);
}
- hole = next;
+ bucket = next;
break;
}
- newBucket = nextBucket(newBucket);
+ newBucket.advanceWrapped(this);
}
}
-
- // return correct position of the next element
- if (!spans[span].hasNode(index))
- ++it;
- return it;
}
~Data()
@@ -660,8 +780,8 @@ struct iterator {
const Data<Node> *d = nullptr;
size_t bucket = 0;
- size_t span() const noexcept { return bucket / Span::NEntries; }
- size_t index() const noexcept { return bucket & Span::LocalBucketMask; }
+ size_t span() const noexcept { return bucket >> SpanConstants::SpanShift; }
+ size_t index() const noexcept { return bucket & SpanConstants::LocalBucketMask; }
inline bool isUnused() const noexcept { return !d->spans[span()].hasNode(index()); }
inline Node *node() const noexcept
@@ -695,12 +815,14 @@ struct iterator {
} // namespace QHashPrivate
-template <class Key, class T>
+template <typename Key, typename T>
class QHash
{
using Node = QHashPrivate::Node<Key, T>;
using Data = QHashPrivate::Data<Node>;
friend class QSet<Key>;
+ friend class QMultiHash<Key, T>;
+ friend tst_QHash;
Data *d = nullptr;
@@ -728,6 +850,9 @@ public:
}
~QHash()
{
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
if (d && !d->ref.deref())
delete d;
}
@@ -749,15 +874,7 @@ public:
: d(std::exchange(other.d, nullptr))
{
}
- QHash &operator=(QHash &&other) noexcept(std::is_nothrow_destructible<Node>::value)
- {
- if (d != other.d) {
- if (d && !d->ref.deref())
- delete d;
- d = std::exchange(other.d, nullptr);
- }
- return *this;
- }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QHash)
#ifdef Q_QDOC
template <typename InputIterator>
QHash(InputIterator f, InputIterator l);
@@ -780,9 +897,11 @@ public:
insert(f->first, f->second);
}
#endif
- void swap(QHash &other) noexcept { qSwap(d, other.d); }
+ void swap(QHash &other) noexcept { qt_ptr_swap(d, other.d); }
- bool operator==(const QHash &other) const noexcept
+#ifndef Q_QDOC
+ template <typename AKey = Key, typename AT = T>
+ QTypeTraits::compare_eq_result_container<QHash, AKey, AT> operator==(const QHash &other) const noexcept
{
if (d == other.d)
return true;
@@ -797,7 +916,13 @@ public:
// all values must be the same as size is the same
return true;
}
- bool operator!=(const QHash &other) const noexcept { return !(*this == other); }
+ template <typename AKey = Key, typename AT = T>
+ QTypeTraits::compare_eq_result_container<QHash, AKey, AT> operator!=(const QHash &other) const noexcept
+ { return !(*this == other); }
+#else
+ bool operator==(const QHash &other) const;
+ bool operator!=(const QHash &other) const;
+#endif // Q_QDOC
inline qsizetype size() const noexcept { return d ? qsizetype(d->size) : 0; }
inline bool isEmpty() const noexcept { return !d || d->size == 0; }
@@ -805,12 +930,19 @@ public:
inline qsizetype capacity() const noexcept { return d ? qsizetype(d->numBuckets >> 1) : 0; }
void reserve(qsizetype size)
{
+ // reserve(0) is used in squeeze()
+ if (size && (this->capacity() >= size))
+ return;
if (isDetached())
d->rehash(size);
else
d = Data::detached(d, size_t(size));
}
- inline void squeeze() { reserve(0); }
+ inline void squeeze()
+ {
+ if (capacity())
+ reserve(0);
+ }
inline void detach() { if (!d || d->ref.isShared()) d = Data::detached(d); }
inline bool isDetached() const noexcept { return d && !d->ref.isShared(); }
@@ -825,23 +957,45 @@ public:
bool remove(const Key &key)
{
+ return removeImpl(key);
+ }
+private:
+ template <typename K> bool removeImpl(const K &key)
+ {
if (isEmpty()) // prevents detaching shared null
return false;
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
- auto it = d->find(key);
if (it.isUnused())
return false;
d->erase(it);
return true;
}
+
+public:
+ template <typename Predicate>
+ qsizetype removeIf(Predicate pred)
+ {
+ return QtPrivate::associative_erase_if(*this, pred);
+ }
+
T take(const Key &key)
{
+ return takeImpl(key);
+ }
+private:
+ template <typename K> T takeImpl(const K &key)
+ {
if (isEmpty()) // prevents detaching shared null
return T();
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
- auto it = d->find(key);
if (it.isUnused())
return T();
T value = it.node()->takeValue();
@@ -849,6 +1003,7 @@ public:
return value;
}
+public:
bool contains(const Key &key) const noexcept
{
if (!d)
@@ -860,7 +1015,8 @@ public:
return contains(key) ? 1 : 0;
}
- Key key(const T &value, const Key &defaultKey = Key()) const noexcept
+private:
+ template <typename Fn> Key keyImpl(const T &value, Fn &&defaultFn) const noexcept
{
if (d) {
const_iterator i = begin();
@@ -871,27 +1027,57 @@ public:
}
}
- return defaultKey;
+ return defaultFn();
}
- T value(const Key &key, const T &defaultValue = T()) const noexcept
+
+public:
+ Key key(const T &value) const noexcept
+ {
+ return keyImpl(value, [] { return Key(); });
+ }
+ Key key(const T &value, const Key &defaultKey) const noexcept
+ {
+ return keyImpl(value, [&] { return defaultKey; });
+ }
+
+private:
+ template <typename K, typename Fn> T valueImpl(const K &key, Fn &&defaultValue) const noexcept
{
if (d) {
Node *n = d->findNode(key);
if (n)
return n->value;
}
- return defaultValue;
+ return defaultValue();
+ }
+public:
+ T value(const Key &key) const noexcept
+ {
+ return valueImpl(key, [] { return T(); });
+ }
+
+ T value(const Key &key, const T &defaultValue) const noexcept
+ {
+ return valueImpl(key, [&] { return defaultValue; });
}
+
T &operator[](const Key &key)
{
+ return operatorIndexImpl(key);
+ }
+private:
+ template <typename K> T &operatorIndexImpl(const K &key)
+ {
+ const auto copy = isDetached() ? QHash() : *this; // keep 'key' alive across the detach
detach();
auto result = d->findOrInsert(key);
Q_ASSERT(!result.it.atEnd());
if (!result.initialized)
- Node::createInPlace(result.it.node(), key, T());
+ Node::createInPlace(result.it.node(), Key(key), T());
return result.it.node()->value;
}
+public:
const T operator[](const Key &key) const noexcept
{
return value(key);
@@ -1039,6 +1225,10 @@ public:
inline const_key_value_iterator constKeyValueBegin() const noexcept { return const_key_value_iterator(begin()); }
inline const_key_value_iterator keyValueEnd() const noexcept { return const_key_value_iterator(end()); }
inline const_key_value_iterator constKeyValueEnd() const noexcept { return const_key_value_iterator(end()); }
+ auto asKeyValueRange() & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() && { return QtPrivate::QKeyValueRange(std::move(*this)); }
+ auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange(std::move(*this)); }
iterator erase(const_iterator it)
{
@@ -1046,50 +1236,65 @@ public:
detach();
// ensure a valid iterator across the detach:
iterator i = iterator{d->detachedIterator(it.i)};
+ typename Data::Bucket bucket(i.i);
- i.i = d->erase(i.i);
+ d->erase(bucket);
+ if (bucket.toBucketIndex(d) == d->numBuckets - 1 || bucket.isUnused())
+ ++i;
return i;
}
- QPair<iterator, iterator> equal_range(const Key &key)
+ std::pair<iterator, iterator> equal_range(const Key &key)
{
- auto first = find(key);
- auto second = first;
- if (second != iterator())
- ++second;
- return qMakePair(first, second);
+ return equal_range_impl(*this, key);
}
-
- QPair<const_iterator, const_iterator> equal_range(const Key &key) const noexcept
+ std::pair<const_iterator, const_iterator> equal_range(const Key &key) const noexcept
{
- auto first = find(key);
+ return equal_range_impl(*this, key);
+ }
+private:
+ template <typename Hash, typename K> static auto equal_range_impl(Hash &self, const K &key)
+ {
+ auto first = self.find(key);
auto second = first;
- if (second != iterator())
+ if (second != decltype(first){})
++second;
- return qMakePair(first, second);
+ return std::make_pair(first, second);
}
- typedef iterator Iterator;
- typedef const_iterator ConstIterator;
- inline qsizetype count() const noexcept { return d ? qsizetype(d->size) : 0; }
- iterator find(const Key &key)
+ template <typename K> iterator findImpl(const K &key)
{
if (isEmpty()) // prevents detaching shared null
return end();
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
- auto it = d->find(key);
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
if (it.isUnused())
- it = d->end();
- return iterator(it);
+ return end();
+ return iterator(it.toIterator(d));
}
- const_iterator find(const Key &key) const noexcept
+ template <typename K> const_iterator constFindImpl(const K &key) const noexcept
{
if (isEmpty())
return end();
- auto it = d->find(key);
+ auto it = d->findBucket(key);
if (it.isUnused())
- it = d->end();
- return const_iterator(it);
+ return end();
+ return const_iterator({d, it.toBucketIndex(d)});
+ }
+
+public:
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ inline qsizetype count() const noexcept { return d ? qsizetype(d->size) : 0; }
+ iterator find(const Key &key)
+ {
+ return findImpl(key);
+ }
+ const_iterator find(const Key &key) const noexcept
+ {
+ return constFindImpl(key);
}
const_iterator constFind(const Key &key) const noexcept
{
@@ -1118,14 +1323,35 @@ public:
template <typename ...Args>
iterator emplace(const Key &key, Args &&... args)
{
- return emplace(Key(key), std::forward<Args>(args)...);
+ Key copy = key; // Needs to be explicit for MSVC 2019
+ return emplace(std::move(copy), std::forward<Args>(args)...);
}
template <typename ...Args>
iterator emplace(Key &&key, Args &&... args)
{
+ if (isDetached()) {
+ if (d->shouldGrow()) // Construct the value now so that no dangling references are used
+ return emplace_helper(std::move(key), T(std::forward<Args>(args)...));
+ return emplace_helper(std::move(key), std::forward<Args>(args)...);
+ }
+ // else: we must detach
+ const auto copy = *this; // keep 'args' alive across the detach/growth
detach();
+ return emplace_helper(std::move(key), std::forward<Args>(args)...);
+ }
+ float load_factor() const noexcept { return d ? d->loadFactor() : 0; }
+ static float max_load_factor() noexcept { return 0.5; }
+ size_t bucket_count() const noexcept { return d ? d->numBuckets : 0; }
+ static size_t max_bucket_count() noexcept { return Data::maxNumBuckets(); }
+
+ inline bool empty() const noexcept { return isEmpty(); }
+
+private:
+ template <typename ...Args>
+ iterator emplace_helper(Key &&key, Args &&... args)
+ {
auto result = d->findOrInsert(key);
if (!result.initialized)
Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
@@ -1134,24 +1360,74 @@ public:
return iterator(result.it);
}
- float load_factor() const noexcept { return d ? d->loadFactor() : 0; }
- static float max_load_factor() noexcept { return 0.5; }
- size_t bucket_count() const noexcept { return d ? d->numBuckets : 0; }
- static size_t max_bucket_count() noexcept { return QHashPrivate::GrowthPolicy::maxNumBuckets(); }
-
- inline bool empty() const noexcept { return isEmpty(); }
+public:
+#ifdef __cpp_concepts
+ bool remove(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return removeImpl(key);
+ }
+ T take(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return takeImpl(key);
+ }
+ bool contains(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return d ? d->findNode(key) != nullptr : false;
+ }
+ qsizetype count(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return contains(key) ? 1 : 0;
+ }
+ T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
+ {
+ return valueImpl(key, [] { return T(); });
+ }
+ T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &defaultValue) const noexcept
+ {
+ return valueImpl(key, [&] { return defaultValue; });
+ }
+ T &operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return operatorIndexImpl(key);
+ }
+ const T operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
+ {
+ return value(key);
+ }
+ std::pair<iterator, iterator>
+ equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return equal_range_impl(*this, key);
+ }
+ std::pair<const_iterator, const_iterator>
+ equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
+ {
+ return equal_range_impl(*this, key);
+ }
+ iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return findImpl(key);
+ }
+ const_iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
+ {
+ return constFindImpl(key);
+ }
+ const_iterator constFind(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
+ {
+ return find(key);
+ }
+#endif // __cpp_concepts
};
-
-template <class Key, class T>
+template <typename Key, typename T>
class QMultiHash
{
using Node = QHashPrivate::MultiNode<Key, T>;
using Data = QHashPrivate::Data<Node>;
using Chain = QHashPrivate::MultiNodeChain<T>;
- Data *d = nullptr;
+ Data *d = nullptr;
qsizetype m_size = 0;
public:
@@ -1198,6 +1474,9 @@ public:
}
~QMultiHash()
{
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
if (d && !d->ref.deref())
delete d;
}
@@ -1215,10 +1494,10 @@ public:
}
return *this;
}
- QMultiHash(QMultiHash &&other) noexcept : d(other.d), m_size(other.m_size)
+ QMultiHash(QMultiHash &&other) noexcept
+ : d(std::exchange(other.d, nullptr)),
+ m_size(std::exchange(other.m_size, 0))
{
- other.d = nullptr;
- other.m_size = 0;
}
QMultiHash &operator=(QMultiHash &&other) noexcept(std::is_nothrow_destructible<Node>::value)
{
@@ -1227,26 +1506,43 @@ public:
return *this;
}
- QMultiHash(const QHash<Key, T> &other)
+ explicit QMultiHash(const QHash<Key, T> &other)
: QMultiHash(other.begin(), other.end())
{}
- void swap(QMultiHash &other) noexcept { qSwap(d, other.d); qSwap(m_size, other.m_size); }
- bool operator==(const QMultiHash &other) const noexcept
+ explicit QMultiHash(QHash<Key, T> &&other)
+ {
+ unite(std::move(other));
+ }
+
+ void swap(QMultiHash &other) noexcept
+ {
+ qt_ptr_swap(d, other.d);
+ std::swap(m_size, other.m_size);
+ }
+
+#ifndef Q_QDOC
+ template <typename AKey = Key, typename AT = T>
+ QTypeTraits::compare_eq_result_container<QMultiHash, AKey, AT> operator==(const QMultiHash &other) const noexcept
{
if (d == other.d)
return true;
- if (!d || ! other.d)
+ if (m_size != other.m_size)
return false;
- if (m_size != other.m_size || d->size != other.d->size)
+ if (m_size == 0)
+ return true;
+ // equal size, and both non-zero size => d pointers allocated for both
+ Q_ASSERT(d);
+ Q_ASSERT(other.d);
+ if (d->size != other.d->size)
return false;
for (auto it = other.d->begin(); it != other.d->end(); ++it) {
- auto i = d->find(it.node()->key);
- if (i == d->end())
+ auto *n = d->findNode(it.node()->key);
+ if (!n)
return false;
Chain *e = it.node()->value;
while (e) {
- Chain *oe = i.node()->value;
+ Chain *oe = n->value;
while (oe) {
if (oe->value == e->value)
break;
@@ -1260,7 +1556,13 @@ public:
// all values must be the same as size is the same
return true;
}
- bool operator!=(const QMultiHash &other) const noexcept { return !(*this == other); }
+ template <typename AKey = Key, typename AT = T>
+ QTypeTraits::compare_eq_result_container<QMultiHash, AKey, AT> operator!=(const QMultiHash &other) const noexcept
+ { return !(*this == other); }
+#else
+ bool operator==(const QMultiHash &other) const;
+ bool operator!=(const QMultiHash &other) const;
+#endif // Q_QDOC
inline qsizetype size() const noexcept { return m_size; }
@@ -1269,6 +1571,9 @@ public:
inline qsizetype capacity() const noexcept { return d ? qsizetype(d->numBuckets >> 1) : 0; }
void reserve(qsizetype size)
{
+ // reserve(0) is used in squeeze()
+ if (size && (this->capacity() >= size))
+ return;
if (isDetached())
d->rehash(size);
else
@@ -1290,11 +1595,18 @@ public:
qsizetype remove(const Key &key)
{
+ return removeImpl(key);
+ }
+private:
+ template <typename K> qsizetype removeImpl(const K &key)
+ {
if (isEmpty()) // prevents detaching shared null
return 0;
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
- auto it = d->find(key);
if (it.isUnused())
return 0;
qsizetype n = Node::freeChain(it.node());
@@ -1303,13 +1615,28 @@ public:
d->erase(it);
return n;
}
+
+public:
+ template <typename Predicate>
+ qsizetype removeIf(Predicate pred)
+ {
+ return QtPrivate::associative_erase_if(*this, pred);
+ }
+
T take(const Key &key)
{
+ return takeImpl(key);
+ }
+private:
+ template <typename K> T takeImpl(const K &key)
+ {
if (isEmpty()) // prevents detaching shared null
return T();
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
- auto it = d->find(key);
if (it.isUnused())
return T();
Chain *e = it.node()->value;
@@ -1327,6 +1654,7 @@ public:
return t;
}
+public:
bool contains(const Key &key) const noexcept
{
if (!d)
@@ -1334,7 +1662,8 @@ public:
return d->findNode(key) != nullptr;
}
- Key key(const T &value, const Key &defaultKey = Key()) const noexcept
+private:
+ template <typename Fn> Key keyImpl(const T &value, Fn &&defaultValue) const noexcept
{
if (d) {
auto i = d->begin();
@@ -1346,9 +1675,20 @@ public:
}
}
- return defaultKey;
+ return defaultValue();
+ }
+public:
+ Key key(const T &value) const noexcept
+ {
+ return keyImpl(value, [] { return Key(); });
}
- T value(const Key &key, const T &defaultValue = T()) const noexcept
+ Key key(const T &value, const Key &defaultKey) const noexcept
+ {
+ return keyImpl(value, [&] { return defaultKey; });
+ }
+
+private:
+ template <typename K, typename Fn> T valueImpl(const K &key, Fn &&defaultValue) const noexcept
{
if (d) {
Node *n = d->findNode(key);
@@ -1357,19 +1697,37 @@ public:
return n->value->value;
}
}
- return defaultValue;
+ return defaultValue();
+ }
+public:
+ T value(const Key &key) const noexcept
+ {
+ return valueImpl(key, [] { return T(); });
+ }
+ T value(const Key &key, const T &defaultValue) const noexcept
+ {
+ return valueImpl(key, [&] { return defaultValue; });
}
T &operator[](const Key &key)
{
+ return operatorIndexImpl(key);
+ }
+private:
+ template <typename K> T &operatorIndexImpl(const K &key)
+ {
+ const auto copy = isDetached() ? QMultiHash() : *this; // keep 'key' alive across the detach
detach();
auto result = d->findOrInsert(key);
Q_ASSERT(!result.it.atEnd());
- if (!result.initialized)
- Node::createInPlace(result.it.node(), key, T());
+ if (!result.initialized) {
+ Node::createInPlace(result.it.node(), Key(key), T());
+ ++m_size;
+ }
return result.it.node()->value->value;
}
+public:
const T operator[](const Key &key) const noexcept
{
return value(key);
@@ -1394,15 +1752,21 @@ public:
QList<Key> res;
const_iterator i = begin();
while (i != end()) {
- if (i.value()->contains(value))
+ if (i.value() == value)
res.append(i.key());
++i;
}
return res;
}
+
QList<T> values() const { return QList<T>(begin(), end()); }
QList<T> values(const Key &key) const
{
+ return valuesImpl(key);
+ }
+private:
+ template <typename K> QList<T> valuesImpl(const K &key) const
+ {
QList<T> values;
if (d) {
Node *n = d->findNode(key);
@@ -1417,6 +1781,7 @@ public:
return values;
}
+public:
class const_iterator;
class iterator
@@ -1566,6 +1931,10 @@ public:
inline const_key_value_iterator constKeyValueBegin() const noexcept { return const_key_value_iterator(begin()); }
inline const_key_value_iterator keyValueEnd() const noexcept { return const_key_value_iterator(end()); }
inline const_key_value_iterator constKeyValueEnd() const noexcept { return const_key_value_iterator(end()); }
+ auto asKeyValueRange() & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() && { return QtPrivate::QKeyValueRange(std::move(*this)); }
+ auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange(std::move(*this)); }
iterator detach(const_iterator it)
{
@@ -1596,7 +1965,8 @@ public:
iterator erase(const_iterator it)
{
Q_ASSERT(d);
- iterator i = detach(it);
+ iterator iter = detach(it);
+ iterator i = iter;
Chain *e = *i.e;
Chain *next = e->next;
*i.e = next;
@@ -1604,9 +1974,14 @@ public:
if (!next) {
if (i.e == &i.i.node()->value) {
// last remaining entry, erase
- i = iterator(d->erase(i.i));
+ typename Data::Bucket bucket(i.i);
+ d->erase(bucket);
+ if (bucket.toBucketIndex(d) == d->numBuckets - 1 || bucket.isUnused())
+ i = iterator(++iter.i);
+ else // 'i' currently has a nullptr chain. So, we must recreate it
+ i = iterator(bucket.toIterator(d));
} else {
- i = iterator(++it.i);
+ i = iterator(++iter.i);
}
}
--m_size;
@@ -1618,29 +1993,44 @@ public:
typedef iterator Iterator;
typedef const_iterator ConstIterator;
inline qsizetype count() const noexcept { return size(); }
- iterator find(const Key &key)
+
+private:
+ template <typename K> iterator findImpl(const K &key)
{
if (isEmpty())
return end();
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
- auto it = d->find(key);
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
+
if (it.isUnused())
- it = d->end();
- return iterator(it);
- }
- const_iterator find(const Key &key) const noexcept
- {
- return constFind(key);
+ return end();
+ return iterator(it.toIterator(d));
}
- const_iterator constFind(const Key &key) const noexcept
+ template <typename K> const_iterator constFindImpl(const K &key) const noexcept
{
if (isEmpty())
return end();
- auto it = d->find(key);
+ auto it = d->findBucket(key);
if (it.isUnused())
- it = d->end();
- return const_iterator(it);
+ return constEnd();
+ return const_iterator(it.toIterator(d));
}
+public:
+ iterator find(const Key &key)
+ {
+ return findImpl(key);
+ }
+ const_iterator constFind(const Key &key) const noexcept
+ {
+ return constFindImpl(key);
+ }
+ const_iterator find(const Key &key) const noexcept
+ {
+ return constFindImpl(key);
+ }
+
iterator insert(const Key &key, const T &value)
{
return emplace(key, value);
@@ -1655,22 +2045,22 @@ public:
template <typename ...Args>
iterator emplace(Key &&key, Args &&... args)
{
+ if (isDetached()) {
+ if (d->shouldGrow()) // Construct the value now so that no dangling references are used
+ return emplace_helper(std::move(key), T(std::forward<Args>(args)...));
+ return emplace_helper(std::move(key), std::forward<Args>(args)...);
+ }
+ // else: we must detach
+ const auto copy = *this; // keep 'args' alive across the detach/growth
detach();
-
- auto result = d->findOrInsert(key);
- if (!result.initialized)
- Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
- else
- result.it.node()->insertMulti(std::forward<Args>(args)...);
- ++m_size;
- return iterator(result.it);
+ return emplace_helper(std::move(key), std::forward<Args>(args)...);
}
float load_factor() const noexcept { return d ? d->loadFactor() : 0; }
static float max_load_factor() noexcept { return 0.5; }
size_t bucket_count() const noexcept { return d ? d->numBuckets : 0; }
- static size_t max_bucket_count() noexcept { return QHashPrivate::GrowthPolicy::maxNumBuckets(); }
+ static size_t max_bucket_count() noexcept { return Data::maxNumBuckets(); }
inline bool empty() const noexcept { return isEmpty(); }
@@ -1688,16 +2078,15 @@ public:
template <typename ...Args>
iterator emplaceReplace(Key &&key, Args &&... args)
{
- detach();
-
- auto result = d->findOrInsert(key);
- if (!result.initialized) {
- ++m_size;
- Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
- } else {
- result.it.node()->emplaceValue(std::forward<Args>(args)...);
+ if (isDetached()) {
+ if (d->shouldGrow()) // Construct the value now so that no dangling references are used
+ return emplaceReplace_helper(std::move(key), T(std::forward<Args>(args)...));
+ return emplaceReplace_helper(std::move(key), std::forward<Args>(args)...);
}
- return iterator(result.it);
+ // else: we must detach
+ const auto copy = *this; // keep 'args' alive across the detach/growth
+ detach();
+ return emplaceReplace_helper(std::move(key), std::forward<Args>(args)...);
}
inline QMultiHash &operator+=(const QMultiHash &other)
@@ -1707,6 +2096,11 @@ public:
bool contains(const Key &key, const T &value) const noexcept
{
+ return containsImpl(key, value);
+ }
+private:
+ template <typename K> bool containsImpl(const K &key, const T &value) const noexcept
+ {
if (isEmpty())
return false;
auto n = d->findNode(key);
@@ -1715,13 +2109,21 @@ public:
return n->value->contains(value);
}
+public:
qsizetype remove(const Key &key, const T &value)
{
+ return removeImpl(key, value);
+ }
+private:
+ template <typename K> qsizetype removeImpl(const K &key, const T &value)
+ {
if (isEmpty()) // prevents detaching shared null
- return false;
+ return 0;
+ auto it = d->findBucket(key);
+ size_t bucket = it.toBucketIndex(d);
detach();
+ it = typename Data::Bucket(d, bucket); // reattach in case of detach
- auto it = d->find(key);
if (it.isUnused())
return 0;
qsizetype n = 0;
@@ -1743,9 +2145,17 @@ public:
return n;
}
+public:
qsizetype count(const Key &key) const noexcept
{
- auto it = d->find(key);
+ return countImpl(key);
+ }
+private:
+ template <typename K> qsizetype countImpl(const K &key) const noexcept
+ {
+ if (!d)
+ return 0;
+ auto it = d->findBucket(key);
if (it.isUnused())
return 0;
qsizetype n = 0;
@@ -1758,9 +2168,17 @@ public:
return n;
}
+public:
qsizetype count(const Key &key, const T &value) const noexcept
{
- auto it = d->find(key);
+ return countImpl(key, value);
+ }
+private:
+ template <typename K> qsizetype countImpl(const K &key, const T &value) const noexcept
+ {
+ if (!d)
+ return 0;
+ auto it = d->findBucket(key);
if (it.isUnused())
return 0;
qsizetype n = 0;
@@ -1774,17 +2192,16 @@ public:
return n;
}
- iterator find(const Key &key, const T &value)
+ template <typename K> iterator findImpl(const K &key, const T &value)
{
+ if (isEmpty())
+ return end();
+ const auto copy = isDetached() ? QMultiHash() : *this; // keep 'key'/'value' alive across the detach
detach();
auto it = constFind(key, value);
return iterator(it.i, it.e);
}
- const_iterator find(const Key &key, const T &value) const noexcept
- {
- return constFind(key, value);
- }
- const_iterator constFind(const Key &key, const T &value) const noexcept
+ template <typename K> const_iterator constFindImpl(const K &key, const T &value) const noexcept
{
const_iterator i(constFind(key));
const_iterator end(constEnd());
@@ -1796,6 +2213,21 @@ public:
return end;
}
+public:
+ iterator find(const Key &key, const T &value)
+ {
+ return findImpl(key, value);
+ }
+
+ const_iterator constFind(const Key &key, const T &value) const noexcept
+ {
+ return constFindImpl(key, value);
+ }
+ const_iterator find(const Key &key, const T &value) const noexcept
+ {
+ return constFind(key, value);
+ }
+
QMultiHash &unite(const QMultiHash &other)
{
if (isEmpty()) {
@@ -1811,24 +2243,59 @@ public:
return *this;
}
- QPair<iterator, iterator> equal_range(const Key &key)
+ QMultiHash &unite(const QHash<Key, T> &other)
+ {
+ for (auto cit = other.cbegin(); cit != other.cend(); ++cit)
+ insert(cit.key(), *cit);
+ return *this;
+ }
+
+ QMultiHash &unite(QHash<Key, T> &&other)
+ {
+ if (!other.isDetached()) {
+ unite(other);
+ return *this;
+ }
+ auto it = other.d->begin();
+ for (const auto end = other.d->end(); it != end; ++it)
+ emplace(std::move(it.node()->key), std::move(it.node()->takeValue()));
+ other.clear();
+ return *this;
+ }
+
+ std::pair<iterator, iterator> equal_range(const Key &key)
{
+ return equal_range_impl(key);
+ }
+private:
+ template <typename K> std::pair<iterator, iterator> equal_range_impl(const K &key)
+ {
+ const auto copy = isDetached() ? QMultiHash() : *this; // keep 'key' alive across the detach
detach();
- auto pair = qAsConst(*this).equal_range(key);
- return qMakePair(iterator(pair.first.i), iterator(pair.second.i));
+ auto pair = std::as_const(*this).equal_range(key);
+ return {iterator(pair.first.i), iterator(pair.second.i)};
}
- QPair<const_iterator, const_iterator> equal_range(const Key &key) const noexcept
+public:
+ std::pair<const_iterator, const_iterator> equal_range(const Key &key) const noexcept
{
- auto it = d->find(key);
- if (it.isUnused())
- return qMakePair(end(), end());
+ return equal_range_impl(key);
+ }
+private:
+ template <typename K> std::pair<const_iterator, const_iterator> equal_range_impl(const K &key) const noexcept
+ {
+ if (!d)
+ return {end(), end()};
+
+ auto bucket = d->findBucket(key);
+ if (bucket.isUnused())
+ return {end(), end()};
+ auto it = bucket.toIterator(d);
auto end = it;
++end;
- return qMakePair(const_iterator(it), const_iterator(end));
+ return {const_iterator(it), const_iterator(end)};
}
-private:
void detach_helper()
{
if (!d) {
@@ -1840,162 +2307,164 @@ private:
delete d;
d = dd;
}
-};
-#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
-template<class Key, class T>
-class QHashIterator
-{
- typedef typename QHash<Key, T>::const_iterator const_iterator;
- typedef const_iterator Item;
- QHash<Key, T> c;
- const_iterator i, n;
- inline bool item_exists() const noexcept { return n != c.constEnd(); }
+ template<typename... Args>
+ iterator emplace_helper(Key &&key, Args &&...args)
+ {
+ auto result = d->findOrInsert(key);
+ if (!result.initialized)
+ Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
+ else
+ result.it.node()->insertMulti(std::forward<Args>(args)...);
+ ++m_size;
+ return iterator(result.it);
+ }
+
+ template<typename... Args>
+ iterator emplaceReplace_helper(Key &&key, Args &&...args)
+ {
+ auto result = d->findOrInsert(key);
+ if (!result.initialized) {
+ Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
+ ++m_size;
+ } else {
+ result.it.node()->emplaceValue(std::forward<Args>(args)...);
+ }
+ return iterator(result.it);
+ }
public:
- inline QHashIterator(const QHash<Key, T> &container) noexcept
- : c(container), i(c.constBegin()), n(c.constEnd())
- { }
- inline QHashIterator &operator=(const QHash<Key, T> &container) noexcept
- {
- c = container;
- i = c.constBegin();
- n = c.constEnd();
- return *this;
+#ifdef __cpp_concepts
+ qsizetype remove(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return removeImpl(key);
}
- inline void toFront() noexcept
+ T take(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
{
- i = c.constBegin();
- n = c.constEnd();
+ return takeImpl(key);
}
- inline void toBack() noexcept
+ bool contains(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
{
- i = c.constEnd();
- n = c.constEnd();
+ if (!d)
+ return false;
+ return d->findNode(key) != nullptr;
}
- inline bool hasNext() const noexcept { return i != c.constEnd(); }
- inline Item next() noexcept
+ T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
{
- n = i++;
- return n;
+ return valueImpl(key, [] { return T(); });
}
- inline Item peekNext() const noexcept { return i; }
- inline const T &value() const noexcept
+ T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &defaultValue) const noexcept
{
- Q_ASSERT(item_exists());
- return *n;
+ return valueImpl(key, [&] { return defaultValue; });
}
- inline const Key &key() const noexcept
+ T &operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
{
- Q_ASSERT(item_exists());
- return n.key();
+ return operatorIndexImpl(key);
}
- inline bool findNext(const T &t) noexcept
+ const T operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
{
- while ((n = i) != c.constEnd())
- if (*i++ == t)
- return true;
- return false;
+ return value(key);
}
-};
-
-template<class Key, class T>
-class QMutableHashIterator
-{
- typedef typename QHash<Key, T>::iterator iterator;
- typedef typename QHash<Key, T>::const_iterator const_iterator;
- typedef iterator Item;
- QHash<Key, T> *c;
- iterator i, n;
- inline bool item_exists() const noexcept { return const_iterator(n) != c->constEnd(); }
-
-public:
- inline QMutableHashIterator(QHash<Key, T> &container)
- : c(&container)
+ QList<T> values(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
{
- i = c->begin();
- n = c->end();
+ return valuesImpl(key);
}
- inline QMutableHashIterator &operator=(QHash<Key, T> &container)
+ iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
{
- c = &container;
- i = c->begin();
- n = c->end();
- return *this;
+ return findImpl(key);
}
- inline void toFront()
+ const_iterator constFind(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
{
- i = c->begin();
- n = c->end();
+ return constFindImpl(key);
}
- inline void toBack() noexcept
+ const_iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
{
- i = c->end();
- n = c->end();
+ return constFindImpl(key);
}
- inline bool hasNext() const noexcept { return const_iterator(i) != c->constEnd(); }
- inline Item next() noexcept
+ bool contains(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
{
- n = i++;
- return n;
+ return containsImpl(key, value);
}
- inline Item peekNext() const noexcept { return i; }
- inline void remove()
+ qsizetype remove(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value)
{
- if (const_iterator(n) != c->constEnd()) {
- i = c->erase(n);
- n = c->end();
- }
+ return removeImpl(key, value);
}
- inline void setValue(const T &t)
+ qsizetype count(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
{
- if (const_iterator(n) != c->constEnd())
- *n = t;
+ return countImpl(key);
}
- inline T &value() noexcept
+ qsizetype count(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
{
- Q_ASSERT(item_exists());
- return *n;
+ return countImpl(key, value);
}
- inline const T &value() const noexcept
+ iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value)
{
- Q_ASSERT(item_exists());
- return *n;
+ return findImpl(key, value);
}
- inline const Key &key() const noexcept
+ const_iterator constFind(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
{
- Q_ASSERT(item_exists());
- return n.key();
+ return constFindImpl(key, value);
}
- inline bool findNext(const T &t) noexcept
+ const_iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
{
- while (const_iterator(n = i) != c->constEnd())
- if (*i++ == t)
- return true;
- return false;
+ return constFind(key, value);
}
+ std::pair<iterator, iterator>
+ equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
+ {
+ return equal_range_impl(key);
+ }
+ std::pair<const_iterator, const_iterator>
+ equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
+ {
+ return equal_range_impl(key);
+ }
+#endif // __cpp_concepts
};
-#endif // !QT_NO_JAVA_STYLE_ITERATORS
+
+Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
+Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(MultiHash)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(MultiHash)
template <class Key, class T>
size_t qHash(const QHash<Key, T> &key, size_t seed = 0)
noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
- QtPrivate::QHashCombineCommutative hash;
+ size_t hash = 0;
for (auto it = key.begin(), end = key.end(); it != end; ++it) {
- const Key &k = it.key();
- const T &v = it.value();
- seed = hash(seed, std::pair<const Key&, const T&>(k, v));
+ QtPrivate::QHashCombine combine;
+ size_t h = combine(seed, it.key());
+ // use + to keep the result independent of the ordering of the keys
+ hash += combine(h, it.value());
}
- return seed;
+ return hash;
}
template <class Key, class T>
inline size_t qHash(const QMultiHash<Key, T> &key, size_t seed = 0)
noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
- const QHash<Key, T> &key2 = key;
- return qHash(key2, seed);
+ size_t hash = 0;
+ for (auto it = key.begin(), end = key.end(); it != end; ++it) {
+ QtPrivate::QHashCombine combine;
+ size_t h = combine(seed, it.key());
+ // use + to keep the result independent of the ordering of the keys
+ hash += combine(h, it.value());
+ }
+ return hash;
+}
+
+template <typename Key, typename T, typename Predicate>
+qsizetype erase_if(QHash<Key, T> &hash, Predicate pred)
+{
+ return QtPrivate::associative_erase_if(hash, pred);
+}
+
+template <typename Key, typename T, typename Predicate>
+qsizetype erase_if(QMultiHash<Key, T> &hash, Predicate pred)
+{
+ return QtPrivate::associative_erase_if(hash, pred);
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index b48a665383..90a269deaa 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -1,51 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+// Copyright (C) 2024 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QHASHFUNCTIONS_H
#define QHASHFUNCTIONS_H
#include <QtCore/qstring.h>
-#include <QtCore/qpair.h>
+#include <QtCore/qstringfwd.h>
#include <numeric> // for std::accumulate
#include <functional> // for std::hash
+#include <utility> // For std::pair
+
+#ifdef __cpp_concepts
+# include <concepts>
+#endif
#if 0
#pragma qt_class(QHashFunctions)
@@ -60,13 +30,40 @@
QT_BEGIN_NAMESPACE
class QBitArray;
-class QByteArray;
-class QString;
-class QStringRef;
-class QLatin1String;
+#if QT_DEPRECATED_SINCE(6,6)
+QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
Q_CORE_EXPORT int qGlobalQHashSeed();
+QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed);
+#endif
+
+struct QHashSeed
+{
+ constexpr QHashSeed(size_t d = 0) : data(d) {}
+ constexpr operator size_t() const noexcept { return data; }
+
+ static Q_CORE_EXPORT QHashSeed globalSeed() noexcept;
+ static Q_CORE_EXPORT void setDeterministicGlobalSeed();
+ static Q_CORE_EXPORT void resetRandomGlobalSeed();
+private:
+ size_t data;
+};
+
+// Whether, ∀ t of type T && ∀ seed, qHash(Key(t), seed) == qHash(t, seed)
+template <typename Key, typename T> struct QHashHeterogeneousSearch : std::false_type {};
+
+// Specializations
+template <> struct QHashHeterogeneousSearch<QString, QStringView> : std::true_type {};
+template <> struct QHashHeterogeneousSearch<QStringView, QString> : std::true_type {};
+template <> struct QHashHeterogeneousSearch<QByteArray, QByteArrayView> : std::true_type {};
+template <> struct QHashHeterogeneousSearch<QByteArrayView, QByteArray> : std::true_type {};
+#ifndef Q_PROCESSOR_ARM
+template <> struct QHashHeterogeneousSearch<QString, QLatin1StringView> : std::true_type {};
+template <> struct QHashHeterogeneousSearch<QStringView, QLatin1StringView> : std::true_type {};
+template <> struct QHashHeterogeneousSearch<QLatin1StringView, QString> : std::true_type {};
+template <> struct QHashHeterogeneousSearch<QLatin1StringView, QStringView> : std::true_type {};
+#endif
namespace QHashPrivate {
@@ -91,36 +88,73 @@ Q_DECL_CONST_FUNCTION constexpr size_t hash(size_t key, size_t seed) noexcept
}
}
+template <typename T1, typename T2> static constexpr bool noexceptPairHash();
}
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHashBits(const void *p, size_t size, size_t seed = 0) noexcept;
+// implementation below qHashMulti
+template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
+ noexcept(QHashPrivate::noexceptPairHash<T1, T2>());
+
// C++ builtin types
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(char key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(uchar key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(uchar key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(signed char key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(signed char key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(ushort key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(ushort key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(short key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(short key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(uint key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(uint key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(int key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(int key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(ulong key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(ulong key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(long key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(long key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(quint64 key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(quint64 key, size_t seed = 0) noexcept
{
if constexpr (sizeof(quint64) > sizeof(size_t))
key ^= (key >> 32);
return QHashPrivate::hash(size_t(key), seed);
}
-Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(qint64 key, size_t seed = 0) noexcept { return qHash(quint64(key), seed); }
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(qint64 key, size_t seed = 0) noexcept
+{
+ if constexpr (sizeof(qint64) > sizeof(size_t)) {
+ // Avoid QTBUG-116080: we XOR the top half with its own sign bit:
+ // - if the qint64 is in range of qint32, then signmask ^ high == 0
+ // (for Qt 7 only)
+ // - if the qint64 is in range of quint32, then signmask == 0 and we
+ // do the same as the quint64 overload above
+ quint32 high = quint32(quint64(key) >> 32);
+ quint32 low = quint32(quint64(key));
+ quint32 signmask = qint32(high) >> 31; // all zeroes or all ones
+ signmask = QT_VERSION_MAJOR > 6 ? signmask : 0;
+ low ^= signmask ^ high;
+ return qHash(low, seed);
+ }
+ return qHash(quint64(key), seed);
+}
+#if QT_SUPPORTS_INT128
+constexpr size_t qHash(quint128 key, size_t seed = 0) noexcept
+{
+ return qHash(quint64(key + (key >> 64)), seed);
+}
+constexpr size_t qHash(qint128 key, size_t seed = 0) noexcept
+{
+ // Avoid QTBUG-116080: same as above, but with double the sizes and without
+ // the need for compatibility
+ quint64 high = quint64(quint128(key) >> 64);
+ quint64 low = quint64(quint128(key));
+ quint64 signmask = qint64(high) >> 63; // all zeroes or all ones
+ low += signmask ^ high;
+ return qHash(low, seed);
+}
+#endif // QT_SUPPORTS_INT128
Q_DECL_CONST_FUNCTION inline size_t qHash(float key, size_t seed = 0) noexcept
{
// ensure -0 gets mapped to 0
@@ -130,17 +164,15 @@ Q_DECL_CONST_FUNCTION inline size_t qHash(float key, size_t seed = 0) noexcept
return QHashPrivate::hash(k, seed);
}
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(double key, size_t seed = 0) noexcept;
-#if !defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(long double key, size_t seed = 0) noexcept;
-#endif
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(wchar_t key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(wchar_t key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(char16_t key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char16_t key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(char32_t key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char32_t key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
#ifdef __cpp_char8_t
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline size_t qHash(char8_t key, size_t seed = 0) noexcept
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(char8_t key, size_t seed = 0) noexcept
{ return QHashPrivate::hash(size_t(key), seed); }
#endif
template <class T> inline size_t qHash(const T *key, size_t seed = 0) noexcept
@@ -151,28 +183,92 @@ Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(std::nullptr_t, size_t seed
{
return seed;
}
+template <class Enum, std::enable_if_t<std::is_enum_v<Enum>, bool> = true>
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(Enum e, size_t seed = 0) noexcept
+{ return QHashPrivate::hash(qToUnderlying(e), seed); }
// (some) Qt types
Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(const QChar key, size_t seed = 0) noexcept { return qHash(key.unicode(), seed); }
+
+#if QT_CORE_REMOVED_SINCE(6, 4)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArrayView &key, size_t seed = 0) noexcept;
+#else
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QByteArrayView key, size_t seed = 0) noexcept;
+inline Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0
+ QT6_DECL_NEW_OVERLOAD_TAIL) noexcept
+{ return qHash(qToByteArrayViewIgnoringNull(key), seed); }
+#endif
+
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QStringView key, size_t seed = 0) noexcept;
-#if QT_STRINGVIEW_LEVEL < 2
inline Q_DECL_PURE_FUNCTION size_t qHash(const QString &key, size_t seed = 0) noexcept
{ return qHash(QStringView{key}, seed); }
-inline Q_DECL_PURE_FUNCTION size_t qHash(const QStringRef &key, size_t seed = 0) noexcept
-{ return qHash(QStringView{key}, seed); }
-#endif
+#ifndef QT_BOOTSTRAPPED
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QBitArray &key, size_t seed = 0) noexcept;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QLatin1String key, size_t seed = 0) noexcept;
+#endif
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QLatin1StringView key, size_t seed = 0) noexcept;
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(QKeyCombination key, size_t seed = 0) noexcept
+{ return qHash(key.toCombined(), seed); }
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) noexcept;
-template<typename T> inline size_t qHash(const T &t, size_t seed)
- noexcept(noexcept(qHash(t)))
+template <typename Enum>
+Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(QFlags<Enum> flags, size_t seed = 0) noexcept
+{ return qHash(flags.toInt(), seed); }
+
+// ### Qt 7: remove this "catch-all" overload logic, and require users
+// to provide the two-argument version of qHash.
+#if (QT_VERSION < QT_VERSION_CHECK(7, 0, 0))
+// Beware of moving this code from here. It needs to see all the
+// declarations of qHash overloads for C++ fundamental types *before*
+// its own declaration.
+namespace QHashPrivate {
+template <typename T, typename = void>
+constexpr inline bool HasQHashSingleArgOverload = false;
+
+template <typename T>
+constexpr inline bool HasQHashSingleArgOverload<T, std::enable_if_t<
+ std::is_convertible_v<decltype(qHash(std::declval<const T &>())), size_t>
+>> = true;
+}
+
+template <typename T, std::enable_if_t<QHashPrivate::HasQHashSingleArgOverload<T> && !std::is_enum_v<T>, bool> = true>
+size_t qHash(const T &t, size_t seed) noexcept(noexcept(qHash(t)))
{ return qHash(t) ^ seed; }
+#endif // < Qt 7
+
+namespace QHashPrivate {
+#ifdef __cpp_concepts
+template <typename Key, typename T> concept HeterogeneouslySearchableWithHelper =
+ // if Key and T are not the same (member already exists)
+ !std::is_same_v<Key, T>
+ // but are comparable amongst each other
+ && std::equality_comparable_with<Key, T>
+ // and supports heteregenous hashing
+ && QHashHeterogeneousSearch<Key, T>::value;
+template <typename Key, typename T> concept HeterogeneouslySearchableWith =
+ HeterogeneouslySearchableWithHelper<q20::remove_cvref_t<Key>, q20::remove_cvref_t<T>>;
+#else
+template <typename Key, typename T> constexpr bool HeterogeneouslySearchableWith = false;
+#endif
+}
+
+template<typename T>
+bool qHashEquals(const T &a, const T &b)
+{
+ return a == b;
+}
+
+template <typename T1, typename T2>
+std::enable_if_t<QHashPrivate::HeterogeneouslySearchableWith<T1, T2>, bool>
+qHashEquals(const T1 &a, const T2 &b)
+{
+ return a == b;
+}
namespace QtPrivate {
-struct QHashCombine {
+struct QHashCombine
+{
typedef size_t result_type;
template <typename T>
constexpr result_type operator()(size_t seed, const T &t) const noexcept(noexcept(qHash(t)))
@@ -180,7 +276,8 @@ struct QHashCombine {
{ return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; }
};
-struct QHashCombineCommutative {
+struct QHashCombineCommutative
+{
// QHashCombine is a good hash combiner, but is not commutative,
// ie. it depends on the order of the input elements. That is
// usually what we want: {0,1,3} should hash differently than
@@ -210,6 +307,9 @@ struct QNothrowHashable : std::false_type {};
template <typename T>
struct QNothrowHashable<T, std::enable_if_t<QNothrowHashableHelper_v<T>>> : std::true_type {};
+template <typename T>
+constexpr inline bool QNothrowHashable_v = QNothrowHashable<T>::value;
+
} // namespace QtPrivate
template <typename... T>
@@ -254,8 +354,16 @@ inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, siz
return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative());
}
-template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
- noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
+namespace QHashPrivate {
+template <typename T1, typename T2> static constexpr bool noexceptPairHash()
+{
+ size_t seed = 0;
+ return noexcept(qHash(std::declval<T1>(), seed)) && noexcept(qHash(std::declval<T2>(), seed));
+}
+} // QHashPrivate
+
+template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed)
+ noexcept(QHashPrivate::noexceptPairHash<T1, T2>())
{
return qHashMulti(seed, key.first, key.second);
}
@@ -268,15 +376,15 @@ template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2>
using argument_type = QT_PREPEND_NAMESPACE(Class); \
using result_type = size_t; \
size_t operator()(Arguments s) const \
- noexcept(noexcept(QT_PREPEND_NAMESPACE(qHash)(s))) \
+ noexcept(QT_PREPEND_NAMESPACE( \
+ QtPrivate::QNothrowHashable_v)<argument_type>) \
{ \
/* this seeds qHash with the result of */ \
/* std::hash applied to an int, to reap */ \
/* any protection against predictable hash */ \
/* values the std implementation may provide */ \
- return QT_PREPEND_NAMESPACE(qHash)(s, \
- QT_PREPEND_NAMESPACE(qHash)( \
- std::hash<int>{}(0))); \
+ using QT_PREPEND_NAMESPACE(qHash); \
+ return qHash(s, qHash(std::hash<int>{}(0))); \
} \
}; \
} \
@@ -289,11 +397,13 @@ template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2>
QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, argument_type)
QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QString)
-QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QStringRef)
QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QStringView)
-QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QLatin1String)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QLatin1StringView)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QByteArrayView)
QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QByteArray)
+#ifndef QT_BOOTSTRAPPED
QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QBitArray)
+#endif
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index c4665c7c87..8a2b493ef4 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -1,51 +1,23 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QITERATOR_H
#define QITERATOR_H
#include <QtCore/qglobal.h>
+#include <QtCore/qcontainertools_impl.h>
QT_BEGIN_NAMESPACE
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
+#ifdef Q_QDOC
+#define Q_DISABLE_BACKWARD_ITERATOR
+#else
+#define Q_DISABLE_BACKWARD_ITERATOR \
+ template<typename It = decltype(i), QtPrivate::IfIteratorCanMoveBackwards<It> = true>
+#endif
+
#define Q_DECLARE_SEQUENTIAL_ITERATOR(C) \
\
template <class T> \
@@ -64,11 +36,15 @@ public: \
inline bool hasNext() const { return i != c.constEnd(); } \
inline const T &next() { return *i++; } \
inline const T &peekNext() const { return *i; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool hasPrevious() const { return i != c.constBegin(); } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline const T &previous() { return *--i; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline const T &peekPrevious() const { const_iterator p = i; return *--p; } \
inline bool findNext(const T &t) \
{ while (i != c.constEnd()) if (*i++ == t) return true; return false; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool findPrevious(const T &t) \
{ while (i != c.constBegin()) if (*(--i) == t) return true; \
return false; } \
@@ -95,8 +71,11 @@ public: \
inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
inline T &next() { n = i++; return *n; } \
inline T &peekNext() const { return *i; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline T &previous() { n = --i; return *n; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline T &peekPrevious() const { iterator p = i; return *--p; } \
inline void remove() \
{ if (c->constEnd() != const_iterator(n)) { i = c->erase(n); n = c->end(); } } \
@@ -106,6 +85,7 @@ public: \
inline void insert(const T &t) { n = i = c->insert(i, t); ++i; } \
inline bool findNext(const T &t) \
{ while (c->constEnd() != const_iterator(n = i)) if (*i++ == t) return true; return false; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool findPrevious(const T &t) \
{ while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true; \
n = c->end(); return false; } \
@@ -131,13 +111,17 @@ public: \
inline bool hasNext() const { return i != c.constEnd(); } \
inline Item next() { n = i++; return n; } \
inline Item peekNext() const { return i; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool hasPrevious() const { return i != c.constBegin(); } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline Item previous() { n = --i; return n; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline Item peekPrevious() const { const_iterator p = i; return --p; } \
inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
inline bool findNext(const T &t) \
{ while ((n = i) != c.constEnd()) if (*i++ == t) return true; return false; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool findPrevious(const T &t) \
{ while (i != c.constBegin()) if (*(n = --i) == t) return true; \
n = c.constEnd(); return false; } \
@@ -165,8 +149,11 @@ public: \
inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
inline Item next() { n = i++; return n; } \
inline Item peekNext() const { return i; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool hasPrevious() const { return const_iterator(i) != c->constBegin(); } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline Item previous() { n = --i; return n; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline Item peekPrevious() const { iterator p = i; return --p; } \
inline void remove() \
{ if (const_iterator(n) != c->constEnd()) { i = c->erase(n); n = c->end(); } } \
@@ -176,16 +163,78 @@ public: \
inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
inline bool findNext(const T &t) \
{ while (const_iterator(n = i) != c->constEnd()) if (*i++ == t) return true; return false; } \
+ Q_DISABLE_BACKWARD_ITERATOR \
inline bool findPrevious(const T &t) \
{ while (const_iterator(i) != c->constBegin()) if (*(n = --i) == t) return true; \
n = c->end(); return false; } \
};
+#define Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(C) \
+\
+template <class Key, class T> \
+class Q##C##Iterator \
+{ \
+ typedef typename Q##C<Key,T>::const_iterator const_iterator; \
+ Q##C<Key,T> c; \
+ const_iterator i, n; \
+ inline bool item_exists() const { return n != c.constEnd(); } \
+public: \
+ typedef const_iterator Item; \
+ inline Q##C##Iterator(const Q##C<Key,T> &container) \
+ : c(container), i(c.constBegin()), n(c.constEnd()) {} \
+ inline Q##C##Iterator &operator=(const Q##C<Key,T> &container) \
+ { c = container; i = c.constBegin(); n = c.constEnd(); return *this; } \
+ inline void toFront() { i = c.constBegin(); n = c.constEnd(); } \
+ inline void toBack() { i = c.constEnd(); n = c.constEnd(); } \
+ inline bool hasNext() const { return i != c.constEnd(); } \
+ inline Item next() { n = i++; return n; } \
+ inline Item peekNext() const { return i; } \
+ inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
+ inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
+ inline bool findNext(const T &t) \
+ { while ((n = i) != c.constEnd()) if (*i++ == t) return true; return false; } \
+};
+
+#define Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(C) \
+\
+template <class Key, class T> \
+class QMutable##C##Iterator \
+{ \
+ typedef typename Q##C<Key,T>::iterator iterator; \
+ typedef typename Q##C<Key,T>::const_iterator const_iterator; \
+ Q##C<Key,T> *c; \
+ iterator i, n; \
+ inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
+public: \
+ typedef iterator Item; \
+ inline QMutable##C##Iterator(Q##C<Key,T> &container) \
+ : c(&container) \
+ { i = c->begin(); n = c->end(); } \
+ inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
+ { c = &container; i = c->begin(); n = c->end(); return *this; } \
+ inline void toFront() { i = c->begin(); n = c->end(); } \
+ inline void toBack() { i = c->end(); n = c->end(); } \
+ inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
+ inline Item next() { n = i++; return n; } \
+ inline Item peekNext() const { return i; } \
+ inline void remove() \
+ { if (const_iterator(n) != c->constEnd()) { i = c->erase(n); n = c->end(); } } \
+ inline void setValue(const T &t) { if (const_iterator(n) != c->constEnd()) *n = t; } \
+ inline T &value() { Q_ASSERT(item_exists()); return *n; } \
+ inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
+ inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \
+ inline bool findNext(const T &t) \
+ { while (const_iterator(n = i) != c->constEnd()) if (*i++ == t) return true; return false; } \
+};
+
+
#else // QT_NO_JAVA_STYLE_ITERATORS
#define Q_DECLARE_SEQUENTIAL_ITERATOR(C)
#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C)
#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C)
#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C)
+#define Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(C)
+#define Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(C)
#endif // QT_NO_JAVA_STYLE_ITERATORS
template<typename Key, typename T, class Iterator>
@@ -198,36 +247,17 @@ public:
typedef const value_type &reference;
QKeyValueIterator() = default;
- Q_DECL_CONSTEXPR explicit QKeyValueIterator(Iterator o) noexcept(std::is_nothrow_move_constructible<Iterator>::value)
+ constexpr explicit QKeyValueIterator(Iterator o) noexcept(std::is_nothrow_move_constructible<Iterator>::value)
: i(std::move(o)) {}
std::pair<Key, T> operator*() const {
return std::pair<Key, T>(i.key(), i.value());
}
- struct pointer {
- pointer(value_type&& r_)
- : r(std::move(r_))
- {}
-
- pointer() = default;
- pointer(const pointer &other) = default;
- pointer(pointer &&other) = default;
- pointer& operator=(const pointer &other) = default;
- pointer& operator=(pointer &&other) = default;
-
- value_type& operator*() const {
- return r;
- }
-
- value_type r;
- const value_type *operator->() const {
- return &r;
- }
- };
+ using pointer = QtPrivate::ArrowProxy<value_type>;
pointer operator->() const {
- return pointer(std::pair<Key, T>(i.key(), i.value()));
+ return pointer{std::pair<Key, T>(i.key(), i.value())};
}
friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; }
@@ -243,6 +273,47 @@ private:
Iterator i;
};
+namespace QtPrivate {
+
+template <typename Map>
+class QKeyValueRangeStorage
+{
+protected:
+ Map m_map;
+public:
+ explicit QKeyValueRangeStorage(const Map &map) : m_map(map) {}
+ explicit QKeyValueRangeStorage(Map &&map) : m_map(std::move(map)) {}
+};
+
+template <typename Map>
+class QKeyValueRangeStorage<Map &>
+{
+protected:
+ Map &m_map;
+public:
+ explicit QKeyValueRangeStorage(Map &map) : m_map(map) {}
+};
+
+template <typename Map>
+class QKeyValueRange : public QKeyValueRangeStorage<Map>
+{
+public:
+ using QKeyValueRangeStorage<Map>::QKeyValueRangeStorage;
+ auto begin() { return this->m_map.keyValueBegin(); }
+ auto begin() const { return this->m_map.keyValueBegin(); }
+ auto end() { return this->m_map.keyValueEnd(); }
+ auto end() const { return this->m_map.keyValueEnd(); }
+};
+
+template <typename Map>
+QKeyValueRange(Map &) -> QKeyValueRange<Map &>;
+
+template <typename Map, std::enable_if_t<!std::is_reference_v<Map>, bool> = false>
+QKeyValueRange(Map &&) -> QKeyValueRange<std::remove_const_t<Map>>;
+
+} // namespace QtPrivate
+
+
QT_END_NAMESPACE
#endif // QITERATOR_H
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 174837ad08..041fb0701d 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \class QKeyValueIterator
\inmodule QtCore
@@ -89,8 +65,7 @@
\sa operator*()
*/
-/*! \fn template<typename Key, typename T, class Iterator> bool operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
- \relates QKeyValueIterator
+/*! \fn template<typename Key, typename T, class Iterator> bool QKeyValueIterator<Key, T, Iterator>::operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
Returns \c true if \a rhs points to the same item as \a lhs otherwise returns
\c false.
@@ -98,8 +73,7 @@
\sa operator!=()
*/
-/*! \fn template<typename Key, typename T, class Iterator> bool operator!=(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs) const
- \relates QKeyValueIterator
+/*! \fn template<typename Key, typename T, class Iterator> bool QKeyValueIterator<Key, T, Iterator>::operator!=(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
Returns \c true if \a rhs points to a different item than \a lhs otherwise
returns \c false.
@@ -110,7 +84,7 @@
/*!
\fn template<typename Key, typename T, class Iterator> QKeyValueIterator &QKeyValueIterator<Key, T, Iterator>::operator++()
- The prefix ++ operator (\c{++i}) advances the iterator to the
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
next item in the container and returns the iterator.
\note Advancing the iterator past its container's end() constitutes
@@ -123,7 +97,7 @@
\overload
- The postfix ++ operator (\c{i++}) advances the iterator to the
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
next item in the container and returns the iterator's prior value.
\note Advancing the iterator past its container's end() constitutes
@@ -132,7 +106,7 @@
/*! \fn template<typename Key, typename T, class Iterator> QKeyValueIterator &QKeyValueIterator<Key, T, Iterator>::operator--()
- The prefix -- operator (\c{--i}) backs the iterator up to the previous item
+ The prefix c{--} operator (\c{--i}) backs the iterator up to the previous item
in the container and returns the iterator.
\note Backing up an iterator to before its container's begin() constitutes
@@ -145,7 +119,7 @@
\overload
- The postfix -- operator (\c{i--}) backs the iterator up to the previous item
+ The postfix c{--} operator (\c{i--}) backs the iterator up to the previous item
in the container and returns the iterator's prior value.
\note Backing up an iterator to before its container's begin() constitutes
@@ -163,9 +137,8 @@
\brief The QListIterator class provides a Java-style const iterator for QList and QQueue.
QList has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
An alternative to using iterators is to use index positions. Most
QList member functions take an index as their first parameter,
@@ -210,22 +183,13 @@
*/
/*!
- \class QVectorIterator
- \inmodule QtCore
- \brief QVectorIterator is an alias for QListIterator.
-
- Please see the QListIterator documentation for details.
-*/
-
-/*!
\class QSetIterator
\inmodule QtCore
\brief The QSetIterator class provides a Java-style const iterator for QSet.
- QSet supports both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ QSet has both \l{Java-style iterators} and \l{STL-style
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QSetIterator\<T\> allows you to iterate over a QSet\<T\>. If you
want to modify the set as you iterate over it, use
@@ -249,12 +213,8 @@
\image javaiterators1.png
- Here's how to iterate over the elements in reverse order:
-
- \snippet code/doc_src_qiterator.cpp 7
-
If you want to find all occurrences of a particular value, use
- findNext() or findPrevious() in a loop.
+ findNext() in a loop.
Multiple iterators can be used on the same set. If the set
is modified while a QSetIterator is active, the QSetIterator
@@ -271,9 +231,8 @@
\brief The QMutableListIterator class provides a Java-style non-const iterator for QList, QQueue and QStack.
QList has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
An alternative to using iterators is to use index positions. Most
QList member functions take an index as their first parameter,
@@ -331,14 +290,6 @@
*/
/*!
- \class QMutableVectorIterator
- \inmodule QtCore
- \brief QMutableVectorIterator is an alias for QMutableListIterator.
-
- Please see the QMutableListIterator documentation for details.
-*/
-
-/*!
\class QMutableSetIterator
\inmodule QtCore
\since 4.2
@@ -346,9 +297,8 @@
\brief The QMutableSetIterator class provides a Java-style non-const iterator for QSet.
QSet has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableSetIterator\<T\> allows you to iterate over a QSet\<T\>
and remove items from the set as you iterate. If you don't want
@@ -373,10 +323,6 @@
\image javaiterators1.png
- Here's how to iterate over the elements in reverse order:
-
- \snippet code/doc_src_qiterator.cpp 18
-
If you want to remove items as you iterate over the set, use
remove().
@@ -439,40 +385,92 @@
*/
/*! \fn template <class T> void QListIterator<T>::toBack()
- \fn template <class T> void QSetIterator<T>::toBack()
\fn template <class T> void QMutableListIterator<T>::toBack()
- \fn template <class T> void QMutableSetIterator<T>::toBack()
+//! [toBack]
Moves the iterator to the back of the container (after the last
item).
+//! [toBack]
\sa toFront(), previous()
*/
+/*! \fn template <class T> void QSetIterator<T>::toBack()
+ \include qiterator.qdoc toBack
+ \sa toFront()
+*/
+
+/*! \fn template <class T> void QMutableSetIterator<T>::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront()
+*/
+
/*! \fn template <class T> bool QListIterator<T>::hasNext() const
- \fn template <class T> bool QSetIterator<T>::hasNext() const
\fn template <class T> bool QMutableListIterator<T>::hasNext() const
- \fn template <class T> bool QMutableSetIterator<T>::hasNext() const
+//! [hasNext]
Returns \c true if there is at least one item ahead of the iterator,
i.e. the iterator is \e not at the back of the container;
otherwise returns \c false.
+//! [hasNext]
\sa hasPrevious(), next()
*/
+/*! \fn template <class T> bool QSetIterator<T>::hasNext() const
+ \include qiterator.qdoc hasNext
+ \sa next()
+*/
+
+/*! \fn template <class T> bool QMutableSetIterator<T>::hasNext() const
+
+ Returns \c true if there is at least one item ahead of the iterator,
+ i.e. the iterator is \e not at the back of the container;
+ otherwise returns \c false.
+
+ \sa next()
+*/
+
/*! \fn template <class T> const T &QListIterator<T>::next()
- \fn template <class T> const T &QSetIterator<T>::next()
- \fn template <class T> const T &QMutableSetIterator<T>::next()
+//! [next]
Returns the next item and advances the iterator by one position.
Calling this function on an iterator located at the back of the
container leads to undefined results.
+//! [next]
\sa hasNext(), peekNext(), previous()
*/
+/*!
+ \fn template <class T> const T &QSetIterator<T>::next()
+ \include qiterator.qdoc next
+ \sa hasNext(), peekNext()
+*/
+
+/* \fn template <class T> const T &QMutableSetIterator<T>::next()
+ Returns the next item and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext()
+*/
+
+/*! \fn template <class T> const T &QMutableSetIterator<T>::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext()
+*/
+
/*! \fn template <class T> T &QMutableListIterator<T>::next()
Returns a reference to the next item, and advances the iterator
@@ -485,40 +483,45 @@
*/
/*! \fn template <class T> const T &QListIterator<T>::peekNext() const
- \fn template <class T> const T &QSetIterator<T>::peekNext() const
- \fn template <class T> const T &QMutableSetIterator<T>::peekNext() const
+//! [peekNext]
Returns the next item without moving the iterator.
Calling this function on an iterator located at the back of the
container leads to undefined results.
+//! [peekNext]
\sa hasNext(), next(), peekPrevious()
*/
-/*! \fn template <class T> T &QMutableListIterator<T>::peekNext() const
+/*!
+ \fn template <class T> const T &QSetIterator<T>::peekNext() const
+ \include qiterator.qdoc peekNext
+ \sa hasNext(), next()
+*/
- Returns a reference to the next item, without moving the iterator.
+/*!
+ \fn template <class T> const T &QMutableSetIterator<T>::peekNext() const
+
+ Returns the next item without moving the iterator.
Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasNext(), next(), peekPrevious()
+ \sa hasNext(), next()
*/
-/*!
- \fn template <class T> bool QMutableSetIterator<T>::hasPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
+/*! \fn template <class T> T &QMutableListIterator<T>::peekNext() const
- Returns \c true if there is at least one item behind the iterator,
- i.e. the iterator is \e not at the front of the container;
- otherwise returns \c false.
+ Returns a reference to the next item, without moving the iterator.
- \sa hasNext(), previous()
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
*/
/*! \fn template <class T> bool QListIterator<T>::hasPrevious() const
- \fn template <class T> bool QSetIterator<T>::hasPrevious() const
\fn template <class T> bool QMutableListIterator<T>::hasPrevious() const
Returns \c true if there is at least one item behind the iterator,
@@ -528,21 +531,7 @@
\sa hasNext(), previous()
*/
-/*!
- \fn template <class T> const T &QMutableSetIterator<T>::previous()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item and moves the iterator back by one
- position.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), peekPrevious(), next()
-*/
-
/*! \fn template <class T> const T &QListIterator<T>::previous()
- \fn template <class T> const T &QSetIterator<T>::previous()
Returns the previous item and moves the iterator back by one
position.
@@ -564,20 +553,7 @@
\sa hasPrevious(), peekPrevious(), next()
*/
-/*!
- \fn template <class T> const T &QMutableSetIterator<T>::peekPrevious() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- Returns the previous item without moving the iterator.
-
- Calling this function on an iterator located at the front of the
- container leads to undefined results.
-
- \sa hasPrevious(), previous(), peekNext()
-*/
-
/*! \fn template <class T> const T &QListIterator<T>::peekPrevious() const
- \fn template <class T> const T &QSetIterator<T>::peekPrevious() const
Returns the previous item without moving the iterator.
@@ -599,7 +575,6 @@
/*!
\fn template <class T> bool QMutableSetIterator<T>::findNext(const T &value)
- \obsolete Deprecated in order to align with std::unordered_set functionality.
Searches for \a value starting from the current iterator position
forward. Returns \c true if \a value is found; otherwise returns \c false.
@@ -607,28 +582,29 @@
After the call, if \a value was found, the iterator is positioned
just after the matching item; otherwise, the iterator is
positioned at the back of the container.
-
- \sa findPrevious()
*/
/*! \fn template <class T> bool QListIterator<T>::findNext(const T &value)
- \fn template <class T> bool QSetIterator<T>::findNext(const T &value)
\fn template <class T> bool QMutableListIterator<T>::findNext(const T &value)
+//! [findNext]
Searches for \a value starting from the current iterator position
forward. Returns \c true if \a value is found; otherwise returns \c false.
After the call, if \a value was found, the iterator is positioned
just after the matching item; otherwise, the iterator is
positioned at the back of the container.
+//! [findNext]
\sa findPrevious()
*/
+/*! \fn template <class T> bool QSetIterator<T>::findNext(const T &value)
+ \include qiterator.qdoc findNext
+*/
+
/*! \fn template <class T> bool QListIterator<T>::findPrevious(const T &value)
- \fn template <class T> bool QSetIterator<T>::findPrevious(const T &value)
\fn template <class T> bool QMutableListIterator<T>::findPrevious(const T &value)
- \fn template <class T> bool QMutableSetIterator<T>::findPrevious(const T &value)
Searches for \a value starting from the current iterator position
backward. Returns \c true if \a value is found; otherwise returns
@@ -655,7 +631,7 @@
/*! \fn template <class T> void QMutableSetIterator<T>::remove()
Removes the last item that was jumped over using one of the
- traversal functions (next(), previous(), findNext(), findPrevious()).
+ traversal functions (next(), findNext()).
Example:
\snippet code/doc_src_qiterator.cpp 22
@@ -678,7 +654,6 @@
*/
/*! \fn template <class T> const T &QMutableListIterator<T>::value() const
- \fn template <class T> const T &QMutableSetIterator<T>::value() const
Returns the value of the last item that was jumped over using one
of the traversal functions (next(), previous(), findNext(),
@@ -689,6 +664,12 @@
equivalent to peekNext().
*/
+/*! \fn template <class T> const T &QMutableSetIterator<T>::value() const
+
+ Returns the value of the last item that was jumped over using
+ next() or findNext().
+*/
+
/*!
\fn template <class T> T &QMutableListIterator<T>::value()
\overload
@@ -709,15 +690,14 @@
\class QMapIterator
\inmodule QtCore
- \brief The QMapIterator class provides a Java-style const iterator for QMap and QMultiMap.
+ \brief The QMapIterator class provides a Java-style const iterator for QMap.
QMap has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
- QMapIterator\<Key, T\> allows you to iterate over a QMap (or a
- QMultiMap). If you want to modify the map as you iterate over
+ QMapIterator\<Key, T\> allows you to iterate over a QMap.
+ If you want to modify the map as you iterate over
it, use QMutableMapIterator instead.
The QMapIterator constructor takes a QMap as argument. After
@@ -758,15 +738,64 @@
*/
/*!
+ \class QMultiMapIterator
+ \inmodule QtCore
+
+ \brief The QMultiMapIterator class provides a Java-style const iterator for QMultiMap.
+ QMultiMap has both \l{Java-style iterators} and \l{STL-style
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
+
+ QMultiMapIterator\<Key, T\> allows you to iterate over a QMultiMap.
+ If you want to modify the map as you iterate over
+ it, use QMutableMultiMapIterator instead.
+
+ The QMultiMapIterator constructor takes a QMultiMap as argument. After
+ construction, the iterator is located at the very beginning of
+ the map (before the first item). Here's how to iterate over all
+ the elements sequentially:
+
+ \snippet code/doc_src_qiterator.cpp 26multi
+
+ The next() function returns the next item in the map and
+ advances the iterator. The key() and value() functions return the
+ key and value of the last item that was jumped over.
+
+ Unlike STL-style iterators, Java-style iterators point \e between
+ items rather than directly \e at items. The first call to next()
+ advances the iterator to the position between the first and
+ second item, and returns the first item; the second call to
+ next() advances the iterator to the position between the second
+ and third item; and so on.
+
+ \image javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet code/doc_src_qiterator.cpp 27multi
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet code/doc_src_qiterator.cpp 28multi
+
+ Multiple iterators can be used on the same map. If the map is
+ modified while a QMultiMapIterator is active, the QMultiMapIterator will
+ continue iterating over the original map, ignoring the modified
+ copy.
+
+ \sa QMutableMultiMapIterator
+*/
+
+/*!
\class QHashIterator
\inmodule QtCore
\brief The QHashIterator class provides a Java-style const iterator for QHash and QMultiHash.
QHash has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QHashIterator\<Key, T\> allows you to iterate over a QHash (or a
QMultiHash). If you want to modify the hash as you iterate over
@@ -792,12 +821,8 @@
\image javaiterators1.png
- Here's how to iterate over the elements in reverse order:
-
- \snippet code/doc_src_qiterator.cpp 30
-
If you want to find all occurrences of a particular value, use
- findNext() or findPrevious() in a loop. For example:
+ findNext() in a loop. For example:
\snippet code/doc_src_qiterator.cpp 31
@@ -813,15 +838,14 @@
\class QMutableMapIterator
\inmodule QtCore
- \brief The QMutableMapIterator class provides a Java-style non-const iterator for QMap and QMultiMap.
+ \brief The QMutableMapIterator class provides a Java-style non-const iterator for QMap.
QMap has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableMapIterator\<Key, T\> allows you to iterate over a QMap
- (or a QMultiMap) and modify the map. If you don't want to modify
+ and modify the map. If you don't want to modify
the map (or have a const QMap), use the slightly faster
QMapIterator instead.
@@ -875,20 +899,82 @@
*/
/*!
+ \class QMutableMultiMapIterator
+ \inmodule QtCore
+
+ \brief The QMutableMultiMapIterator class provides a Java-style non-const iterator for QMultiMap.
+
+ QMultiMap has both \l{Java-style iterators} and \l{STL-style
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
+
+ QMutableMultiMapIterator\<Key, T\> allows you to iterate over a QMultiMap
+ and modify the map. If you don't want to modify
+ the map (or have a const QMultiMap), use the slightly faster
+ QMultiMapIterator instead.
+
+ The QMutableMultiMapIterator constructor takes a QMultiMap as argument.
+ After construction, the iterator is located at the very beginning
+ of the map (before the first item). Here's how to iterate over
+ all the elements sequentially:
+
+ \snippet code/doc_src_qiterator.cpp 32multi
+
+ The next() function returns the next item in the map and
+ advances the iterator. The key() and value() functions return the
+ key and value of the last item that was jumped over.
+
+ Unlike STL-style iterators, Java-style iterators point \e between
+ items rather than directly \e at items. The first call to next()
+ advances the iterator to the position between the first and
+ second item, and returns the first item; the second call to
+ next() advances the iterator to the position between the second
+ and third item; and so on.
+
+ \image javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet code/doc_src_qiterator.cpp 33multi
+
+ If you want to find all occurrences of a particular value, use
+ findNext() or findPrevious() in a loop. For example:
+
+ \snippet code/doc_src_qiterator.cpp 34multi
+
+ If you want to remove items as you iterate over the map, use
+ remove(). If you want to modify the value of an item, use
+ setValue().
+
+ Example:
+
+ \snippet code/doc_src_qiterator.cpp 35multi
+
+ The example removes all (key, value) pairs where the key and the
+ value are the same.
+
+ Only one mutable iterator can be active on a given map at any
+ time. Furthermore, no changes should be done directly to the map
+ while the iterator is active (as opposed to through the
+ iterator), since this could invalidate the iterator and lead to
+ undefined behavior.
+
+ \sa QMultiMapIterator, QMultiMap::iterator
+*/
+
+/*!
\class QMutableHashIterator
\inmodule QtCore
\brief The QMutableHashIterator class provides a Java-style non-const iterator for QHash and QMultiHash.
QHash has both \l{Java-style iterators} and \l{STL-style
- iterators}. The Java-style iterators are more high-level and
- easier to use than the STL-style iterators; on the other hand,
- they are slightly less efficient.
+ iterators}. STL-style iterators are more efficient and should
+ be preferred.
QMutableHashIterator\<Key, T\> allows you to iterate over a QHash
- (or a QMultiHash) and modify the hash. If you don't want to modify
- the hash (or have a const QHash), use the slightly faster
- QHashIterator instead.
+ and modify the hash. If you don't want to modify the hash (or have
+ a const QHash), use the slightly faster QHashIterator instead.
The QMutableHashIterator constructor takes a QHash as argument.
After construction, the iterator is located at the very beginning
@@ -910,12 +996,8 @@
\image javaiterators1.png
- Here's how to iterate over the elements in reverse order:
-
- \snippet code/doc_src_qiterator.cpp 37
-
If you want to find all occurrences of a particular value, use
- findNext() or findPrevious() in a loop. For example:
+ findNext() in a loop. For example:
\snippet code/doc_src_qiterator.cpp 38
@@ -941,6 +1023,8 @@
/*! \fn template <class Key, class T> QMapIterator<Key, T>::QMapIterator(const QMap<Key, T> &map)
\fn template <class Key, class T> QMutableMapIterator<Key, T>::QMutableMapIterator(QMap<Key, T> &map)
+ \fn template <class Key, class T> QMultiMapIterator<Key, T>::QMultiMapIterator(const QMultiMap<Key, T> &map)
+ \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::QMutableMultiMapIterator(QMultiMap<Key, T> &map)
Constructs an iterator for traversing \a map. The iterator is set
to be at the front of the map (before the first item).
@@ -959,6 +1043,8 @@
/*! \fn template <class Key, class T> QMapIterator &QMapIterator<Key, T>::operator=(const QMap<Key, T> &map)
\fn template <class Key, class T> QMutableMapIterator &QMutableMapIterator<Key, T>::operator=(QMap<Key, T> &map)
+ \fn template <class Key, class T> QMultiMapIterator &QMultiMapIterator<Key, T>::operator=(const QMultiMap<Key, T> &map)
+ \fn template <class Key, class T> QMutableMultiMapIterator &QMutableMultiMapIterator<Key, T>::operator=(QMultiMap<Key, T> &map)
Makes the iterator operate on \a map. The iterator is set to be
at the front of the map (before the first item).
@@ -976,8 +1062,10 @@
*/
/*! \fn template <class Key, class T> void QMapIterator<Key, T>::toFront()
+ \fn template <class Key, class T> void QMultiMapIterator<Key, T>::toFront()
\fn template <class Key, class T> void QHashIterator<Key, T>::toFront()
\fn template <class Key, class T> void QMutableMapIterator<Key, T>::toFront()
+ \fn template <class Key, class T> void QMutableMultiMapIterator<Key, T>::toFront()
\fn template <class Key, class T> void QMutableHashIterator<Key, T>::toFront()
Moves the iterator to the front of the container (before the
@@ -987,9 +1075,9 @@
*/
/*! \fn template <class Key, class T> void QMapIterator<Key, T>::toBack()
- \fn template <class Key, class T> void QHashIterator<Key, T>::toBack()
+ \fn template <class Key, class T> void QMultiMapIterator<Key, T>::toBack()
\fn template <class Key, class T> void QMutableMapIterator<Key, T>::toBack()
- \fn template <class Key, class T> void QMutableHashIterator<Key, T>::toBack()
+ \fn template <class Key, class T> void QMutableMultiMapIterator<Key, T>::toBack()
Moves the iterator to the back of the container (after the last
item).
@@ -997,10 +1085,20 @@
\sa toFront(), previous()
*/
+/*!
+ \fn template <class Key, class T> void QHashIterator<Key, T>::toBack()
+ \fn template <class Key, class T> void QMutableHashIterator<Key, T>::toBack()
+
+ Moves the iterator to the back of the container (after the last
+ item).
+
+ \sa toFront()
+*/
+
/*! \fn template <class Key, class T> bool QMapIterator<Key, T>::hasNext() const
- \fn template <class Key, class T> bool QHashIterator<Key, T>::hasNext() const
+ \fn template <class Key, class T> bool QMultiMapIterator<Key, T>::hasNext() const
\fn template <class Key, class T> bool QMutableMapIterator<Key, T>::hasNext() const
- \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::hasNext() const
+ \fn template <class Key, class T> bool QMutableMultiMapIterator<Key, T>::hasNext() const
Returns \c true if there is at least one item ahead of the iterator,
i.e. the iterator is \e not at the back of the container;
@@ -1009,8 +1107,19 @@
\sa hasPrevious(), next()
*/
+/*!
+ \fn template <class Key, class T> bool QHashIterator<Key, T>::hasNext() const
+ \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::hasNext() const
+
+ Returns \c true if there is at least one item ahead of the iterator,
+ i.e. the iterator is \e not at the back of the container;
+ otherwise returns \c false.
+
+ \sa next()
+*/
+
/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::next()
- \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::next()
+ \fn template <class Key, class T> QMultiMapIterator<Key, T>::Item QMultiMapIterator<Key, T>::next()
Returns the next item and advances the iterator by one position.
@@ -1020,11 +1129,11 @@
Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasNext(), peekNext(), previous()
+ \sa hasNext(), {QMapIterator::}{peekNext()}, previous()
*/
/*! \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::next()
- \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::next()
+ \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::Item QMutableMultiMapIterator<Key, T>::next()
Returns the next item and advances the iterator by one position.
@@ -1037,8 +1146,36 @@
\sa hasNext(), peekNext(), previous()
*/
+/*!
+ \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext()
+*/
+
+/*!
+ \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::next()
+
+ Returns the next item and advances the iterator by one position.
+
+ Call key() on the return value to obtain the item's key, and
+ value() to obtain the value.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), peekNext()
+*/
+
/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::peekNext() const
- \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::peekNext() const
+ \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekNext() const
Returns the next item without moving the iterator.
@@ -1052,7 +1189,7 @@
*/
/*! \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekNext() const
- \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::peekNext() const
+ \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::Item QMutableMultiMapIterator<Key, T>::peekNext() const
Returns a reference to the next item without moving the iterator.
@@ -1065,52 +1202,53 @@
\sa hasNext(), next(), peekPrevious()
*/
-/*! \fn template <class Key, class T> bool QMapIterator<Key, T>::hasPrevious() const
- \fn template <class Key, class T> bool QHashIterator<Key, T>::hasPrevious() const
- \fn template <class Key, class T> bool QMutableMapIterator<Key, T>::hasPrevious() const
- \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::hasPrevious() const
-
- Returns \c true if there is at least one item behind the iterator,
- i.e. the iterator is \e not at the front of the container;
- otherwise returns \c false.
-
- \sa hasNext(), previous()
-*/
-
-/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::previous()
- \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::previous()
+/*!
+ \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::peekNext() const
- Returns the previous item and moves the iterator back by one
- position.
+ Returns the next item without moving the iterator.
Call key() on the return value to obtain the item's key, and
value() to obtain the value.
- Calling this function on an iterator located at the front of the
+ Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasPrevious(), peekPrevious(), next()
+ \sa hasNext(), next()
*/
-/*! \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::previous()
- \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::previous()
+/*!
+ \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::peekNext() const
- Returns the previous item and moves the iterator back by one
- position.
+ Returns a reference to the next item without moving the iterator.
Call key() on the return value to obtain the item's key, and
value() to obtain the value.
- Calling this function on an iterator located at the front of the
+ Calling this function on an iterator located at the back of the
container leads to undefined results.
- \sa hasPrevious(), peekPrevious(), next()
+ \sa hasNext(), next()
*/
-/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::peekPrevious() const
- \fn template <class Key, class T> QHashIterator<Key, T>::Item QHashIterator<Key, T>::peekPrevious() const
+/*! \fn template <class Key, class T> bool QMapIterator<Key, T>::hasPrevious() const
+ \fn template <class Key, class T> bool QMultiMapIterator<Key, T>::hasPrevious() const
+ \fn template <class Key, class T> bool QMutableMapIterator<Key, T>::hasPrevious() const
+ \fn template <class Key, class T> bool QMutableMultiMapIterator<Key, T>::hasPrevious() const
- Returns the previous item without moving the iterator.
+ Returns \c true if there is at least one item behind the iterator,
+ i.e. the iterator is \e not at the front of the container;
+ otherwise returns \c false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::previous()
+ \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::previous()
+ \fn template <class Key, class T> QMultiMapIterator<Key, T>::Item QMultiMapIterator<Key, T>::previous()
+ \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::Item QMutableMultiMapIterator<Key, T>::previous()
+
+ Returns the previous item and moves the iterator back by one
+ position.
Call key() on the return value to obtain the item's key, and
value() to obtain the value.
@@ -1118,11 +1256,13 @@
Calling this function on an iterator located at the front of the
container leads to undefined results.
- \sa hasPrevious(), previous(), peekNext()
+ \sa hasPrevious(), peekPrevious(), next()
*/
-/*! \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekPrevious() const
- \fn template <class Key, class T> QMutableHashIterator<Key, T>::Item QMutableHashIterator<Key, T>::peekPrevious() const
+/*! \fn template <class Key, class T> QMapIterator<Key, T>::Item QMapIterator<Key, T>::peekPrevious() const
+ \fn template <class Key, class T> QMutableMapIterator<Key, T>::Item QMutableMapIterator<Key, T>::peekPrevious() const
+ \fn template <class Key, class T> QMultiMapIterator<Key, T>::Item QMultiMapIterator<Key, T>::peekPrevious() const
+ \fn template <class Key, class T> QMutableMultiMapIterator<Key, T>::Item QMutableMultiMapIterator<Key, T>::peekPrevious() const
Returns the previous item without moving the iterator.
@@ -1132,11 +1272,11 @@
Calling this function on an iterator located at the front of the
container leads to undefined results.
- \sa hasPrevious(), previous(), peekNext()
+ \sa hasPrevious(), previous(), {QMapIterator::}{peekNext()}
*/
/*! \fn template <class Key, class T> const T &QMapIterator<Key, T>::value() const
- \fn template <class Key, class T> const T &QHashIterator<Key, T>::value() const
+ \fn template <class Key, class T> const T &QMultiMapIterator<Key, T>::value() const
Returns the value of the last item that was jumped over using one
of the traversal functions (next(), previous(), findNext(),
@@ -1151,7 +1291,7 @@
/*!
\fn template <class Key, class T> const T &QMutableMapIterator<Key, T>::value() const
- \fn template <class Key, class T> const T &QMutableHashIterator<Key, T>::value() const
+ \fn template <class Key, class T> const T &QMutableMultiMapIterator<Key, T>::value() const
Returns the value of the last item that was jumped over using one
of the traversal functions (next(), previous(), findNext(),
@@ -1164,8 +1304,26 @@
\sa key(), setValue()
*/
+/*! \fn template <class Key, class T> const T &QHashIterator<Key, T>::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), findNext()).
+
+ \sa key()
+*/
+
+/*!
+ \fn template <class Key, class T> const T &QMutableHashIterator<Key, T>::value() const
+
+ Returns the value of the last item that was jumped over using one
+ of the traversal functions (next(), findNext()).
+
+ \sa key(), setValue()
+*/
+
/*!
\fn template <class Key, class T> T &QMutableMapIterator<Key, T>::value()
+ \fn template <class Key, class T> T &QMutableMultiMapIterator<Key, T>::value()
\fn template <class Key, class T> T &QMutableHashIterator<Key, T>::value()
\overload
@@ -1175,9 +1333,9 @@
*/
/*! \fn template <class Key, class T> const Key &QMapIterator<Key, T>::key() const
- \fn template <class Key, class T> const Key &QHashIterator<Key, T>::key() const
\fn template <class Key, class T> const Key &QMutableMapIterator<Key, T>::key() const
- \fn template <class Key, class T> const Key &QMutableHashIterator<Key, T>::key() const
+ \fn template <class Key, class T> const Key &QMultiMapIterator<Key, T>::key() const
+ \fn template <class Key, class T> const Key &QMutableMultiMapIterator<Key, T>::key() const
Returns the key of the last item that was jumped over using one
of the traversal functions (next(), previous(), findNext(),
@@ -1190,10 +1348,19 @@
\sa value()
*/
+/*! \fn template <class Key, class T> const Key &QHashIterator<Key, T>::key() const
+ \fn template <class Key, class T> const Key &QMutableHashIterator<Key, T>::key() const
+
+ Returns the key of the last item that was jumped over using one
+ of the traversal functions (next(), findNext()).
+
+ \sa value()
+*/
+
/*! \fn template <class Key, class T> bool QMapIterator<Key, T>::findNext(const T &value)
- \fn template <class Key, class T> bool QHashIterator<Key, T>::findNext(const T &value)
\fn template <class Key, class T> bool QMutableMapIterator<Key, T>::findNext(const T &value)
- \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::findNext(const T &value)
+ \fn template <class Key, class T> bool QMultiMapIterator<Key, T>::findNext(const T &value)
+ \fn template <class Key, class T> bool QMutableMultiMapIterator<Key, T>::findNext(const T &value)
Searches for \a value starting from the current iterator position
forward. Returns \c true if a (key, value) pair with value \a value
@@ -1206,10 +1373,22 @@
\sa findPrevious()
*/
+/*! \fn template <class Key, class T> bool QHashIterator<Key, T>::findNext(const T &value)
+ \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ forward. Returns \c true if a (key, value) pair with value \a value
+ is found; otherwise returns \c false.
+
+ After the call, if \a value was found, the iterator is positioned
+ just after the matching item; otherwise, the iterator is
+ positioned at the back of the container.
+*/
+
/*! \fn template <class Key, class T> bool QMapIterator<Key, T>::findPrevious(const T &value)
- \fn template <class Key, class T> bool QHashIterator<Key, T>::findPrevious(const T &value)
\fn template <class Key, class T> bool QMutableMapIterator<Key, T>::findPrevious(const T &value)
- \fn template <class Key, class T> bool QMutableHashIterator<Key, T>::findPrevious(const T &value)
+ \fn template <class Key, class T> bool QMultiMapIterator<Key, T>::findPrevious(const T &value)
+ \fn template <class Key, class T> bool QMutableMultiMapIterator<Key, T>::findPrevious(const T &value)
Searches for \a value starting from the current iterator position
backward. Returns \c true if a (key, value) pair with value \a value
@@ -1223,7 +1402,7 @@
*/
/*! \fn template <class Key, class T> void QMutableMapIterator<Key, T>::remove()
- \fn template <class Key, class T> void QMutableHashIterator<Key, T>::remove()
+ \fn template <class Key, class T> void QMutableMultiMapIterator<Key, T>::remove()
Removes the last item that was jumped over using one of the
traversal functions (next(), previous(), findNext(), findPrevious()).
@@ -1231,8 +1410,16 @@
\sa setValue()
*/
+/*! \fn template <class Key, class T> void QMutableHashIterator<Key, T>::remove()
+
+ Removes the last item that was jumped over using one of the
+ traversal functions (next(), findNext()).
+
+ \sa setValue()
+*/
+
/*! \fn template <class Key, class T> void QMutableMapIterator<Key, T>::setValue(const T &value)
- \fn template <class Key, class T> void QMutableHashIterator<Key, T>::setValue(const T &value)
+ \fn template <class Key, class T> void QMutableMultiMapIterator<Key, T>::setValue(const T &value)
Replaces the value of the last item that was jumped over using
one of the traversal functions with \a value.
@@ -1242,3 +1429,14 @@
\sa key(), value(), remove()
*/
+
+/*!
+ \fn template <class Key, class T> void QMutableHashIterator<Key, T>::setValue(const T &value)
+
+ Replaces the value of the last item that was jumped over using
+ one of the traversal functions with \a value.
+
+ The traversal functions are next() and findNext().
+
+ \sa key(), value(), remove()
+*/
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index 40a69173c4..e313b06aa9 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qline.h"
+
#include "qdebug.h"
#include "qdatastream.h"
#include "qmath.h"
@@ -49,6 +14,9 @@ QT_BEGIN_NAMESPACE
\class QLine
\inmodule QtCore
\ingroup painting
+ \compares equality
+ \compareswith equality QLineF
+ \endcompareswith
\brief The QLine class provides a two-dimensional vector using
integer precision.
@@ -99,7 +67,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn bool QLine::isNull() const
- Returns \c true if the line is not set up with valid start and end point;
+ Returns \c true if the line does not have distinct start and end points;
otherwise returns \c false.
*/
@@ -168,18 +136,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool QLine::operator!=(const QLine &line) const
+ \fn bool QLine::operator!=(const QLine &lhs, const QLine &rhs)
- Returns \c true if the given \a line is not the same as \e this line.
+ Returns \c true if the line \a lhs is not the same as line \a rhs.
A line is different from another line if any of their start or
end points differ, or the internal order of the points is different.
*/
/*!
- \fn bool QLine::operator==(const QLine &line) const
+ \fn bool QLine::operator==(const QLine &lhs, const QLine &rhs)
- Returns \c true if the given \a line is the same as \e this line.
+ Returns \c true if the line \a lhs is the same as line \a rhs.
A line is identical to another line if the start and end points
are identical, and the internal order of the points is the same.
@@ -262,6 +230,15 @@ QT_BEGIN_NAMESPACE
\sa setP1(), setP2(), p1(), p2()
*/
+/*!
+ \fn QLine::toLineF() const
+ \since 6.4
+
+ Returns this line as a line with floating point accuracy.
+
+ \sa QLineF::toLine()
+*/
+
#ifndef QT_NO_DEBUG_STREAM
@@ -310,15 +287,13 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
#endif // QT_NO_DATASTREAM
-
-#ifndef M_2PI
-#define M_2PI 6.28318530717958647692528676655900576
-#endif
-
/*!
\class QLineF
\inmodule QtCore
\ingroup painting
+ \compares equality
+ \compareswith equality QLine
+ \endcompareswith
\brief The QLineF class provides a two-dimensional vector using
floating point precision.
@@ -326,7 +301,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
A QLineF describes a finite length line (or line segment) on a
two-dimensional surface. QLineF defines the start and end points
of the line using floating point accuracy for coordinates. Use
- the toLine() function to retrieve an integer based copy of this
+ the toLine() function to retrieve an integer-based copy of this
line.
\table
@@ -369,19 +344,12 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
*/
/*!
- \enum QLineF::IntersectType
- \obsolete Use QLineF::IntersectionType instead.
-
- \value NoIntersection
- Lines do not intersect.
- \value UnboundedIntersection
- Lines intersect, but not within the range defined by their lengths.
- \value BoundedIntersection
- Lnes intersect within the range defined by their lengths.
+ \typealias QLineF::IntersectType
+ \deprecated Use QLineF::IntersectionType instead.
*/
/*!
- \typealias QLineF::IntersectionType
+ \enum QLineF::IntersectionType
Describes the intersection between two lines.
@@ -406,7 +374,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
\value BoundedIntersection The two lines intersect with each other
within the start and end points of each line.
- \sa intersect()
+ \sa intersects()
*/
/*!
@@ -434,14 +402,20 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
Construct a QLineF object from the given integer-based \a line.
- \sa toLine()
+ \sa toLine(), QLine::toLineF()
*/
/*!
\fn bool QLineF::isNull() const
- Returns \c true if the line is not set up with valid start and end point;
- otherwise returns \c false.
+ Returns \c true if the line does not have distinct start and end points;
+ otherwise returns \c false. The start and end points are considered distinct
+ if qFuzzyCompare() can distinguish them in at least one coordinate.
+
+ \note Due to the use of fuzzy comparison, isNull() may return \c true for
+ lines whose length() is not zero.
+
+ \sa qFuzzyCompare(), length()
*/
/*!
@@ -463,12 +437,12 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
\fn QLine QLineF::toLine() const
- Returns an integer based copy of this line.
+ Returns an integer-based copy of this line.
Note that the returned line's start and end points are rounded to
the nearest integer.
- \sa QLineF()
+ \sa QLineF(), QLine::toLineF()
*/
/*!
\fn qreal QLineF::x1() const
@@ -521,13 +495,11 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
\fn void QLineF::setLength(qreal length)
- Sets the length of the line to the given \a length. QLineF will
- move the end point - p2() - of the line to give the line its new length.
+ Sets the length of the line to the given finite \a length. QLineF will move
+ the end point - p2() - of the line to give the line its new length, unless
+ length() was previously zero, in which case no scaling is attempted.
- If the line is a null line, the length will remain zero regardless
- of the length specified.
-
- \sa length(), isNull()
+ \sa length(), unitVector()
*/
/*!
@@ -542,18 +514,18 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
*/
/*!
- \fn bool QLineF::operator!=(const QLineF &line) const
+ \fn bool QLineF::operator!=(const QLineF &lhs, const QLineF &rhs)
- Returns \c true if the given \a line is not the same as \e this line.
+ Returns \c true if the line \a lhs is not the same as line \a rhs.
A line is different from another line if their start or end points
differ, or the internal order of the points is different.
*/
/*!
- \fn bool QLineF::operator==(const QLineF &line) const
+ \fn bool QLineF::operator==(const QLineF &lhs, const QLineF &rhs)
- Returns \c true if the given \a line is the same as this line.
+ Returns \c true if the line \a lhs is the same as line \a rhs.
A line is identical to another line if the start and end points
are identical, and the internal order of the points is the same.
@@ -562,9 +534,8 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
\fn qreal QLineF::pointAt(qreal t) const
- Returns the point at the parameterized position specified by \a
- t. The function returns the line's start point if t = 0, and its end
- point if t = 1.
+ Returns the point at the position specified by finite parameter \a t. The
+ function returns the line's start point if t = 0, and its end point if t = 1.
\sa dx(), dy()
*/
@@ -572,13 +543,11 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
Returns the length of the line.
- \sa setLength()
+ \sa setLength(), isNull()
*/
qreal QLineF::length() const
{
- qreal x = pt2.x() - pt1.x();
- qreal y = pt2.y() - pt1.y();
- return qSqrt(x*x + y*y);
+ return qHypot(dx(), dy());
}
/*!
@@ -597,7 +566,7 @@ qreal QLineF::angle() const
const qreal dx = pt2.x() - pt1.x();
const qreal dy = pt2.y() - pt1.y();
- const qreal theta = qAtan2(-dy, dx) * 360.0 / M_2PI;
+ const qreal theta = qRadiansToDegrees(qAtan2(-dy, dx));
const qreal theta_normalized = theta < 0 ? theta + 360 : theta;
@@ -621,7 +590,7 @@ qreal QLineF::angle() const
*/
void QLineF::setAngle(qreal angle)
{
- const qreal angleR = angle * M_2PI / 360.0;
+ const qreal angleR = qDegreesToRadians(angle);
const qreal l = length();
const qreal dx = qCos(angleR) * l;
@@ -643,23 +612,24 @@ void QLineF::setAngle(qreal angle)
*/
QLineF QLineF::fromPolar(qreal length, qreal angle)
{
- const qreal angleR = angle * M_2PI / 360.0;
+ const qreal angleR = qDegreesToRadians(angle);
return QLineF(0, 0, qCos(angleR) * length, -qSin(angleR) * length);
}
/*!
Returns the unit vector for this line, i.e a line starting at the
- same point as \e this line with a length of 1.0.
+ same point as \e this line with a length of 1.0, provided the line
+ is non-null.
- \sa normalVector()
+ \sa normalVector(), setLength()
*/
QLineF QLineF::unitVector() const
{
- qreal x = pt2.x() - pt1.x();
- qreal y = pt2.y() - pt1.y();
+ const qreal x = dx();
+ const qreal y = dy();
- qreal len = qSqrt(x*x + y*y);
- QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len));
+ const qreal len = qHypot(x, y);
+ QLineF f(p1(), QPointF(pt1.x() + x / len, pt1.y() + y / len));
#ifndef QT_NO_DEBUG
if (qAbs(f.length() - 1) >= 0.001)
@@ -669,25 +639,6 @@ QLineF QLineF::unitVector() const
return f;
}
-#if QT_DEPRECATED_SINCE(5, 14)
-/*!
- \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const
- \obsolete Use intersects() instead
-
- Returns a value indicating whether or not \e this line intersects
- with the given \a line.
-
- The actual intersection point is extracted to \a intersectionPoint
- (if the pointer is valid). If the lines are parallel, the
- intersection point is undefined.
-*/
-
-QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const
-{
- return intersects(l, intersectionPoint);
-}
-#endif
-
/*!
\fn QLineF::IntersectionType QLineF::intersects(const QLineF &line, QPointF *intersectionPoint) const
\since 5.14
@@ -809,15 +760,15 @@ QLineF::IntersectionType QLineF::intersects(const QLineF &l, QPointF *intersecti
Returns the angle (in degrees) from this line to the given \a
line, taking the direction of the lines into account. If the lines
- do not intersect within their range, it is the intersection point of
- the extended lines that serves as origin (see
+ do not \l{intersects()}{intersect} within their range, it is the
+ intersection point of the extended lines that serves as origin (see
QLineF::UnboundedIntersection).
The returned value represents the number of degrees you need to add
to this line to make it have the same angle as the given \a line,
going counter-clockwise.
- \sa intersect()
+ \sa intersects()
*/
qreal QLineF::angleTo(const QLineF &l) const
{
@@ -836,41 +787,24 @@ qreal QLineF::angleTo(const QLineF &l) const
return delta_normalized;
}
-#if QT_DEPRECATED_SINCE(5, 14)
/*!
- \fn qreal QLineF::angle(const QLineF &line) const
+ \fn bool QLineF::qFuzzyCompare(const QLineF &lhs, const QLineF &rhs)
+ \since 6.8
- \obsolete
-
- Returns the angle (in degrees) between this line and the given \a
- line, taking the direction of the lines into account. If the lines
- do not intersect within their range, it is the intersection point of
- the extended lines that serves as origin (see
- QLineF::UnboundedIntersection).
+ Returns \c true if line \a lhs is approximately equal to line \a rhs;
+ otherwise returns \c false.
- \table
- \row
- \li \inlineimage qlinef-angle-identicaldirection.png
- \li \inlineimage qlinef-angle-oppositedirection.png
- \endtable
+ The lines are considered approximately equal if their start and end
+ points are approximately equal.
+*/
- When the lines are parallel, this function returns 0 if they have
- the same direction; otherwise it returns 180.
+/*!
+ \fn bool QLineF::qFuzzyIsNull(const QLineF &line)
+ \since 6.8
- \sa intersect()
+ Returns \c true if the start point of line \a line is approximately
+ equal to its end point; otherwise returns \c false.
*/
-qreal QLineF::angle(const QLineF &l) const
-{
- if (isNull() || l.isNull())
- return 0;
- qreal cos_line = (dx()*l.dx() + dy()*l.dy()) / (length()*l.length());
- qreal rad = 0;
- // only accept cos_line in the range [-1,1], if it is outside, use 0 (we return 0 rather than PI for those cases)
- if (cos_line >= -1.0 && cos_line <= 1.0) rad = qAcos( cos_line );
- return rad * 360 / M_2PI;
-}
-#endif
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QLineF &p)
diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h
index d4f62024d1..03dac30e16 100644
--- a/src/corelib/tools/qline.h
+++ b/src/corelib/tools/qline.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLINE_H
#define QLINE_H
@@ -44,6 +8,7 @@
QT_BEGIN_NAMESPACE
+class QLineF;
/*******************************************************************************
* class QLine
@@ -52,96 +17,106 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QLine
{
public:
- Q_DECL_CONSTEXPR inline QLine();
- Q_DECL_CONSTEXPR inline QLine(const QPoint &pt1, const QPoint &pt2);
- Q_DECL_CONSTEXPR inline QLine(int x1, int y1, int x2, int y2);
+ constexpr inline QLine();
+ constexpr inline QLine(const QPoint &pt1, const QPoint &pt2);
+ constexpr inline QLine(int x1, int y1, int x2, int y2);
- Q_DECL_CONSTEXPR inline bool isNull() const;
+ constexpr inline bool isNull() const;
- Q_DECL_CONSTEXPR inline QPoint p1() const;
- Q_DECL_CONSTEXPR inline QPoint p2() const;
+ constexpr inline QPoint p1() const;
+ constexpr inline QPoint p2() const;
- Q_DECL_CONSTEXPR inline int x1() const;
- Q_DECL_CONSTEXPR inline int y1() const;
+ constexpr inline int x1() const;
+ constexpr inline int y1() const;
- Q_DECL_CONSTEXPR inline int x2() const;
- Q_DECL_CONSTEXPR inline int y2() const;
+ constexpr inline int x2() const;
+ constexpr inline int y2() const;
- Q_DECL_CONSTEXPR inline int dx() const;
- Q_DECL_CONSTEXPR inline int dy() const;
+ constexpr inline int dx() const;
+ constexpr inline int dy() const;
inline void translate(const QPoint &p);
inline void translate(int dx, int dy);
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLine translated(const QPoint &p) const;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLine translated(int dx, int dy) const;
+ [[nodiscard]] constexpr inline QLine translated(const QPoint &p) const;
+ [[nodiscard]] constexpr inline QLine translated(int dx, int dy) const;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QPoint center() const;
+ [[nodiscard]] constexpr inline QPoint center() const;
inline void setP1(const QPoint &p1);
inline void setP2(const QPoint &p2);
inline void setPoints(const QPoint &p1, const QPoint &p2);
inline void setLine(int x1, int y1, int x2, int y2);
- Q_DECL_CONSTEXPR inline bool operator==(const QLine &d) const;
- Q_DECL_CONSTEXPR inline bool operator!=(const QLine &d) const { return !(*this == d); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ constexpr inline bool operator==(const QLine &d) const noexcept;
+ constexpr inline bool operator!=(const QLine &d) const noexcept { return !operator==(d); }
+#endif
+
+ [[nodiscard]] constexpr inline QLineF toLineF() const noexcept;
private:
+ friend constexpr bool comparesEqual(const QLine &lhs, const QLine &rhs) noexcept
+ { return lhs.pt1 == rhs.pt1 && lhs.pt2 == rhs.pt2; }
+#if !QT_CORE_REMOVED_SINCE(6, 8)
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QLine)
+#endif
+
QPoint pt1, pt2;
};
-Q_DECLARE_TYPEINFO(QLine, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QLine, Q_PRIMITIVE_TYPE);
/*******************************************************************************
* class QLine inline members
*******************************************************************************/
-Q_DECL_CONSTEXPR inline QLine::QLine() { }
+constexpr inline QLine::QLine() { }
-Q_DECL_CONSTEXPR inline QLine::QLine(const QPoint &pt1_, const QPoint &pt2_) : pt1(pt1_), pt2(pt2_) { }
+constexpr inline QLine::QLine(const QPoint &pt1_, const QPoint &pt2_) : pt1(pt1_), pt2(pt2_) { }
-Q_DECL_CONSTEXPR inline QLine::QLine(int x1pos, int y1pos, int x2pos, int y2pos) : pt1(QPoint(x1pos, y1pos)), pt2(QPoint(x2pos, y2pos)) { }
+constexpr inline QLine::QLine(int x1pos, int y1pos, int x2pos, int y2pos) : pt1(QPoint(x1pos, y1pos)), pt2(QPoint(x2pos, y2pos)) { }
-Q_DECL_CONSTEXPR inline bool QLine::isNull() const
+constexpr inline bool QLine::isNull() const
{
return pt1 == pt2;
}
-Q_DECL_CONSTEXPR inline int QLine::x1() const
+constexpr inline int QLine::x1() const
{
return pt1.x();
}
-Q_DECL_CONSTEXPR inline int QLine::y1() const
+constexpr inline int QLine::y1() const
{
return pt1.y();
}
-Q_DECL_CONSTEXPR inline int QLine::x2() const
+constexpr inline int QLine::x2() const
{
return pt2.x();
}
-Q_DECL_CONSTEXPR inline int QLine::y2() const
+constexpr inline int QLine::y2() const
{
return pt2.y();
}
-Q_DECL_CONSTEXPR inline QPoint QLine::p1() const
+constexpr inline QPoint QLine::p1() const
{
return pt1;
}
-Q_DECL_CONSTEXPR inline QPoint QLine::p2() const
+constexpr inline QPoint QLine::p2() const
{
return pt2;
}
-Q_DECL_CONSTEXPR inline int QLine::dx() const
+constexpr inline int QLine::dx() const
{
return pt2.x() - pt1.x();
}
-Q_DECL_CONSTEXPR inline int QLine::dy() const
+constexpr inline int QLine::dy() const
{
return pt2.y() - pt1.y();
}
@@ -157,17 +132,17 @@ inline void QLine::translate(int adx, int ady)
this->translate(QPoint(adx, ady));
}
-Q_DECL_CONSTEXPR inline QLine QLine::translated(const QPoint &p) const
+constexpr inline QLine QLine::translated(const QPoint &p) const
{
return QLine(pt1 + p, pt2 + p);
}
-Q_DECL_CONSTEXPR inline QLine QLine::translated(int adx, int ady) const
+constexpr inline QLine QLine::translated(int adx, int ady) const
{
return translated(QPoint(adx, ady));
}
-Q_DECL_CONSTEXPR inline QPoint QLine::center() const
+constexpr inline QPoint QLine::center() const
{
return QPoint(int((qint64(pt1.x()) + pt2.x()) / 2), int((qint64(pt1.y()) + pt2.y()) / 2));
}
@@ -194,10 +169,12 @@ inline void QLine::setLine(int aX1, int aY1, int aX2, int aY2)
pt2 = QPoint(aX2, aY2);
}
-Q_DECL_CONSTEXPR inline bool QLine::operator==(const QLine &d) const
+#if QT_CORE_REMOVED_SINCE(6, 8)
+constexpr inline bool QLine::operator==(const QLine &d) const noexcept
{
- return pt1 == d.pt1 && pt2 == d.pt2;
+ return comparesEqual(*this, d);
}
+#endif
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug d, const QLine &p);
@@ -211,32 +188,33 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLine &);
/*******************************************************************************
* class QLineF
*******************************************************************************/
-class Q_CORE_EXPORT QLineF {
+class Q_CORE_EXPORT QLineF
+{
public:
- enum IntersectType { NoIntersection, BoundedIntersection, UnboundedIntersection };
- using IntersectionType = IntersectType;
+ enum IntersectionType { NoIntersection, BoundedIntersection, UnboundedIntersection };
+ using IntersectType = IntersectionType; // deprecated name
- Q_DECL_CONSTEXPR inline QLineF();
- Q_DECL_CONSTEXPR inline QLineF(const QPointF &pt1, const QPointF &pt2);
- Q_DECL_CONSTEXPR inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2);
- Q_DECL_CONSTEXPR inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { }
+ constexpr inline QLineF();
+ constexpr inline QLineF(const QPointF &pt1, const QPointF &pt2);
+ constexpr inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2);
+ constexpr inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { }
- Q_REQUIRED_RESULT static QLineF fromPolar(qreal length, qreal angle);
+ [[nodiscard]] static QLineF fromPolar(qreal length, qreal angle);
- Q_DECL_CONSTEXPR bool isNull() const;
+ constexpr bool isNull() const;
- Q_DECL_CONSTEXPR inline QPointF p1() const;
- Q_DECL_CONSTEXPR inline QPointF p2() const;
+ constexpr inline QPointF p1() const;
+ constexpr inline QPointF p2() const;
- Q_DECL_CONSTEXPR inline qreal x1() const;
- Q_DECL_CONSTEXPR inline qreal y1() const;
+ constexpr inline qreal x1() const;
+ constexpr inline qreal y1() const;
- Q_DECL_CONSTEXPR inline qreal x2() const;
- Q_DECL_CONSTEXPR inline qreal y2() const;
+ constexpr inline qreal x2() const;
+ constexpr inline qreal y2() const;
- Q_DECL_CONSTEXPR inline qreal dx() const;
- Q_DECL_CONSTEXPR inline qreal dy() const;
+ constexpr inline qreal dx() const;
+ constexpr inline qreal dy() const;
qreal length() const;
void setLength(qreal len);
@@ -246,106 +224,117 @@ public:
qreal angleTo(const QLineF &l) const;
- Q_REQUIRED_RESULT QLineF unitVector() const;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLineF normalVector() const;
-
- IntersectionType intersects(const QLineF &l, QPointF *intersectionPoint) const;
+ [[nodiscard]] QLineF unitVector() const;
+ [[nodiscard]] constexpr inline QLineF normalVector() const;
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_VERSION_X(5, 14, "Use intersects() instead")
- IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const;
- QT_DEPRECATED_X("Use qMin(l1.angleTo(l2), l2.angleTo(l1)) instead")
- qreal angle(const QLineF &l) const;
-#endif
+ IntersectionType intersects(const QLineF &l, QPointF *intersectionPoint = nullptr) const;
- Q_DECL_CONSTEXPR inline QPointF pointAt(qreal t) const;
+ constexpr inline QPointF pointAt(qreal t) const;
inline void translate(const QPointF &p);
inline void translate(qreal dx, qreal dy);
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLineF translated(const QPointF &p) const;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLineF translated(qreal dx, qreal dy) const;
+ [[nodiscard]] constexpr inline QLineF translated(const QPointF &p) const;
+ [[nodiscard]] constexpr inline QLineF translated(qreal dx, qreal dy) const;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QPointF center() const;
+ [[nodiscard]] constexpr inline QPointF center() const;
inline void setP1(const QPointF &p1);
inline void setP2(const QPointF &p2);
inline void setPoints(const QPointF &p1, const QPointF &p2);
inline void setLine(qreal x1, qreal y1, qreal x2, qreal y2);
- Q_DECL_CONSTEXPR inline bool operator==(const QLineF &d) const;
- Q_DECL_CONSTEXPR inline bool operator!=(const QLineF &d) const { return !(*this == d); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ constexpr inline bool operator==(const QLineF &d) const;
+ constexpr inline bool operator!=(const QLineF &d) const { return !operator==(d); }
+#endif
- Q_DECL_CONSTEXPR QLine toLine() const;
+ constexpr QLine toLine() const;
private:
+ friend constexpr bool comparesEqual(const QLineF &lhs, const QLineF &rhs) noexcept
+ { return lhs.pt1 == rhs.pt1 && lhs.pt2 == rhs.pt2; }
+#if !QT_CORE_REMOVED_SINCE(6, 8)
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QLineF)
+#endif
+
+ friend constexpr bool comparesEqual(const QLineF &lhs, const QLine &rhs) noexcept
+ { return comparesEqual(lhs, rhs.toLineF()); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QLineF, QLine)
+
+ friend constexpr bool qFuzzyCompare(const QLineF &lhs, const QLineF &rhs) noexcept
+ { return qFuzzyCompare(lhs.pt1, rhs.pt1) && qFuzzyCompare(lhs.pt2, rhs.pt2); }
+
+ friend constexpr bool qFuzzyIsNull(const QLineF &line) noexcept
+ { return qFuzzyCompare(line.pt1, line.pt2); }
+
QPointF pt1, pt2;
};
-Q_DECLARE_TYPEINFO(QLineF, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QLineF, Q_PRIMITIVE_TYPE);
/*******************************************************************************
* class QLineF inline members
*******************************************************************************/
-Q_DECL_CONSTEXPR inline QLineF::QLineF()
+constexpr inline QLineF::QLineF()
{
}
-Q_DECL_CONSTEXPR inline QLineF::QLineF(const QPointF &apt1, const QPointF &apt2)
+constexpr inline QLineF::QLineF(const QPointF &apt1, const QPointF &apt2)
: pt1(apt1), pt2(apt2)
{
}
-Q_DECL_CONSTEXPR inline QLineF::QLineF(qreal x1pos, qreal y1pos, qreal x2pos, qreal y2pos)
+constexpr inline QLineF::QLineF(qreal x1pos, qreal y1pos, qreal x2pos, qreal y2pos)
: pt1(x1pos, y1pos), pt2(x2pos, y2pos)
{
}
-Q_DECL_CONSTEXPR inline qreal QLineF::x1() const
+constexpr inline qreal QLineF::x1() const
{
return pt1.x();
}
-Q_DECL_CONSTEXPR inline qreal QLineF::y1() const
+constexpr inline qreal QLineF::y1() const
{
return pt1.y();
}
-Q_DECL_CONSTEXPR inline qreal QLineF::x2() const
+constexpr inline qreal QLineF::x2() const
{
return pt2.x();
}
-Q_DECL_CONSTEXPR inline qreal QLineF::y2() const
+constexpr inline qreal QLineF::y2() const
{
return pt2.y();
}
-Q_DECL_CONSTEXPR inline bool QLineF::isNull() const
+constexpr inline bool QLineF::isNull() const
{
- return qFuzzyCompare(pt1.x(), pt2.x()) && qFuzzyCompare(pt1.y(), pt2.y());
+ return qFuzzyCompare(pt1, pt2);
}
-Q_DECL_CONSTEXPR inline QPointF QLineF::p1() const
+constexpr inline QPointF QLineF::p1() const
{
return pt1;
}
-Q_DECL_CONSTEXPR inline QPointF QLineF::p2() const
+constexpr inline QPointF QLineF::p2() const
{
return pt2;
}
-Q_DECL_CONSTEXPR inline qreal QLineF::dx() const
+constexpr inline qreal QLineF::dx() const
{
return pt2.x() - pt1.x();
}
-Q_DECL_CONSTEXPR inline qreal QLineF::dy() const
+constexpr inline qreal QLineF::dy() const
{
return pt2.y() - pt1.y();
}
-Q_DECL_CONSTEXPR inline QLineF QLineF::normalVector() const
+constexpr inline QLineF QLineF::normalVector() const
{
return QLineF(p1(), p1() + QPointF(dy(), -dx()));
}
@@ -361,35 +350,40 @@ inline void QLineF::translate(qreal adx, qreal ady)
this->translate(QPointF(adx, ady));
}
-Q_DECL_CONSTEXPR inline QLineF QLineF::translated(const QPointF &p) const
+constexpr inline QLineF QLineF::translated(const QPointF &p) const
{
return QLineF(pt1 + p, pt2 + p);
}
-Q_DECL_CONSTEXPR inline QLineF QLineF::translated(qreal adx, qreal ady) const
+constexpr inline QLineF QLineF::translated(qreal adx, qreal ady) const
{
return translated(QPointF(adx, ady));
}
-Q_DECL_CONSTEXPR inline QPointF QLineF::center() const
+constexpr inline QPointF QLineF::center() const
{
return QPointF(0.5 * pt1.x() + 0.5 * pt2.x(), 0.5 * pt1.y() + 0.5 * pt2.y());
}
inline void QLineF::setLength(qreal len)
{
- if (isNull())
- return;
- QLineF v = unitVector();
- pt2 = QPointF(pt1.x() + v.dx() * len, pt1.y() + v.dy() * len);
+ Q_ASSERT(qIsFinite(len));
+ const qreal oldLength = length();
+ Q_ASSERT(qIsFinite(oldLength));
+ // Scale len by dx() / length() and dy() / length(), two O(1) quantities,
+ // rather than scaling dx() and dy() by len / length(), which might overflow.
+ if (oldLength > 0)
+ pt2 = QPointF(pt1.x() + len * (dx() / oldLength), pt1.y() + len * (dy() / oldLength));
}
-Q_DECL_CONSTEXPR inline QPointF QLineF::pointAt(qreal t) const
+constexpr inline QPointF QLineF::pointAt(qreal t) const
{
return QPointF(pt1.x() + (pt2.x() - pt1.x()) * t, pt1.y() + (pt2.y() - pt1.y()) * t);
}
-Q_DECL_CONSTEXPR inline QLine QLineF::toLine() const
+constexpr inline QLineF QLine::toLineF() const noexcept { return *this; }
+
+constexpr inline QLine QLineF::toLine() const
{
return QLine(pt1.toPoint(), pt2.toPoint());
}
@@ -417,12 +411,12 @@ inline void QLineF::setLine(qreal aX1, qreal aY1, qreal aX2, qreal aY2)
pt2 = QPointF(aX2, aY2);
}
-
-Q_DECL_CONSTEXPR inline bool QLineF::operator==(const QLineF &d) const
+#if QT_CORE_REMOVED_SINCE(6, 8)
+constexpr inline bool QLineF::operator==(const QLineF &d) const
{
- return pt1 == d.pt1 && pt2 == d.pt2;
+ return comparesEqual(*this, d);
}
-
+#endif
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
deleted file mode 100644
index cdcfc30f28..0000000000
--- a/src/corelib/tools/qlist.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <new>
-#include "qlist.h"
-#include "qtools_p.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-QT_BEGIN_NAMESPACE
-
-/*
- ### Qt 5:
- ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
- ### Qt exports QPolygon and QPolygonF that inherit QList<QPoint> and
- ### QList<QPointF> respectively.
-*/
-
-#if defined(Q_CC_MSVC) && defined(QT_BUILD_CORE_LIB)
-QT_BEGIN_INCLUDE_NAMESPACE
-#include <QtCore/qpoint.h>
-QT_END_INCLUDE_NAMESPACE
-
-template class Q_CORE_EXPORT QList<QPointF>;
-template class Q_CORE_EXPORT QList<QPoint>;
-#endif
-
-QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 8a63e1283b..89e0e3f380 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2019 Intel Corporation
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Intel Corporation
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLIST_H
#define QLIST_H
@@ -45,67 +9,262 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qhashfunctions.h>
#include <QtCore/qiterator.h>
+#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qnamespace.h>
#include <functional>
#include <limits>
#include <initializer_list>
#include <type_traits>
+class tst_QList;
+
QT_BEGIN_NAMESPACE
namespace QtPrivate {
- template <typename V, typename U> int indexOf(const QList<V> &list, const U &u, int from);
- template <typename V, typename U> int lastIndexOf(const QList<V> &list, const U &u, int from);
+ template <typename V, typename U> qsizetype indexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
+ template <typename V, typename U> qsizetype lastIndexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
}
-template <typename T> struct QListSpecialMethods
+template <typename T> struct QListSpecialMethodsBase
+{
+protected:
+ ~QListSpecialMethodsBase() = default;
+
+ using Self = QList<T>;
+ Self *self() { return static_cast<Self *>(this); }
+ const Self *self() const { return static_cast<const Self *>(this); }
+
+public:
+ template <typename AT = T>
+ qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept;
+ template <typename AT = T>
+ qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept;
+
+ template <typename AT = T>
+ bool contains(const AT &t) const noexcept
+ {
+ return self()->indexOf(t) != -1;
+ }
+};
+template <typename T> struct QListSpecialMethods : QListSpecialMethodsBase<T>
{
protected:
~QListSpecialMethods() = default;
+public:
+ using QListSpecialMethodsBase<T>::indexOf;
+ using QListSpecialMethodsBase<T>::lastIndexOf;
+ using QListSpecialMethodsBase<T>::contains;
};
template <> struct QListSpecialMethods<QByteArray>;
template <> struct QListSpecialMethods<QString>;
+#if !defined(QT_STRICT_QLIST_ITERATORS) && (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) && !defined(Q_OS_WIN)
+#define QT_STRICT_QLIST_ITERATORS
+#endif
+
+#ifdef Q_QDOC // define QVector for QDoc
+template<typename T> class QVector : public QList<T> {};
+#endif
+
template <typename T>
class QList
#ifndef Q_QDOC
: public QListSpecialMethods<T>
#endif
{
- typedef QTypedArrayData<T> Data;
- typedef QArrayDataOps<T> DataOps;
- typedef QArrayDataPointer<T> DataPointer;
+ using Data = QTypedArrayData<T>;
+ using DataOps = QArrayDataOps<T>;
+ using DataPointer = QArrayDataPointer<T>;
class DisableRValueRefs {};
+ friend class ::tst_QList;
+
DataPointer d;
- template <typename V, typename U> friend int QtPrivate::indexOf(const QList<V> &list, const U &u, int from);
- template <typename V, typename U> friend int QtPrivate::lastIndexOf(const QList<V> &list, const U &u, int from);
+ template <typename V, typename U> friend qsizetype QtPrivate::indexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
+ template <typename V, typename U> friend qsizetype QtPrivate::lastIndexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
+ // This alias prevents the QtPrivate namespace from being exposed into the docs.
+ template <typename InputIterator>
+ using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>;
public:
- typedef T Type;
- typedef T value_type;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- typedef int size_type;
- typedef qptrdiff difference_type;
- typedef typename Data::iterator iterator;
- typedef typename Data::const_iterator const_iterator;
- typedef iterator Iterator;
- typedef const_iterator ConstIterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef typename DataPointer::parameter_type parameter_type;
+ using Type = T;
+ using value_type = T;
+ using pointer = T *;
+ using const_pointer = const T *;
+ using reference = T &;
+ using const_reference = const T &;
+ using size_type = qsizetype;
+ using difference_type = qptrdiff;
+#ifndef Q_QDOC
+ using parameter_type = typename DataPointer::parameter_type;
using rvalue_ref = typename std::conditional<DataPointer::pass_parameter_by_value, DisableRValueRefs, T &&>::type;
+#else // simplified aliases for QDoc
+ using parameter_type = const T &;
+ using rvalue_ref = T &&;
+#endif
+
+ class const_iterator;
+ class iterator {
+ friend class QList<T>;
+ friend class const_iterator;
+ T *i = nullptr;
+#ifdef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit iterator(T *n) : i(n) {}
+#endif
+
+ public:
+ using difference_type = qsizetype;
+ using value_type = T;
+#ifdef QT_COMPILER_HAS_LWG3346
+ using iterator_concept = std::contiguous_iterator_tag;
+ using element_type = value_type;
+#endif
+ using iterator_category = std::random_access_iterator_tag;
+ using pointer = T *;
+ using reference = T &;
+
+ inline constexpr iterator() = default;
+#ifndef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit iterator(T *n) : i(n) {}
+#endif
+ inline T &operator*() const { return *i; }
+ inline T *operator->() const { return i; }
+ inline T &operator[](qsizetype j) const { return *(i + j); }
+ inline constexpr bool operator==(iterator o) const { return i == o.i; }
+ inline constexpr bool operator!=(iterator o) const { return i != o.i; }
+ inline constexpr bool operator<(iterator other) const { return i < other.i; }
+ inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
+ inline constexpr bool operator>(iterator other) const { return i > other.i; }
+ inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
+ inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
+ inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
+ inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
+ inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
+ inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
+ inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
+ inline constexpr bool operator==(pointer p) const { return i == p; }
+ inline constexpr bool operator!=(pointer p) const { return i != p; }
+ inline iterator &operator++() { ++i; return *this; }
+ inline iterator operator++(int) { auto copy = *this; ++*this; return copy; }
+ inline iterator &operator--() { --i; return *this; }
+ inline iterator operator--(int) { auto copy = *this; --*this; return copy; }
+ inline qsizetype operator-(iterator j) const { return i - j.i; }
+#if QT_DEPRECATED_SINCE(6, 3) && !defined(QT_STRICT_QLIST_ITERATORS)
+ QT_DEPRECATED_VERSION_X_6_3("Use operator* or operator-> rather than relying on "
+ "the implicit conversion between a QList/QVector::iterator "
+ "and a raw pointer")
+ inline operator T*() const { return i; }
+
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
+ &operator+=(Int j) { i+=j; return *this; }
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
+ &operator-=(Int j) { i-=j; return *this; }
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
+ operator+(Int j) const { return iterator(i+j); }
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
+ operator-(Int j) const { return iterator(i-j); }
+ template <typename Int> friend std::enable_if_t<std::is_integral_v<Int>, iterator>
+ operator+(Int j, iterator k) { return k + j; }
+#else
+ inline iterator &operator+=(qsizetype j) { i += j; return *this; }
+ inline iterator &operator-=(qsizetype j) { i -= j; return *this; }
+ inline iterator operator+(qsizetype j) const { return iterator(i + j); }
+ inline iterator operator-(qsizetype j) const { return iterator(i - j); }
+ friend inline iterator operator+(qsizetype j, iterator k) { return k + j; }
+#endif
+ };
+
+ class const_iterator {
+ friend class QList<T>;
+ friend class iterator;
+ const T *i = nullptr;
+#ifdef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit const_iterator(const T *n) : i(n) {}
+#endif
+
+ public:
+ using difference_type = qsizetype;
+ using value_type = T;
+#ifdef QT_COMPILER_HAS_LWG3346
+ using iterator_concept = std::contiguous_iterator_tag;
+ using element_type = const value_type;
+#endif
+ using iterator_category = std::random_access_iterator_tag;
+ using pointer = const T *;
+ using reference = const T &;
+
+ inline constexpr const_iterator() = default;
+#ifndef QT_STRICT_QLIST_ITERATORS
+ inline constexpr explicit const_iterator(const T *n) : i(n) {}
+#endif
+ inline constexpr const_iterator(iterator o): i(o.i) {}
+ inline const T &operator*() const { return *i; }
+ inline const T *operator->() const { return i; }
+ inline const T &operator[](qsizetype j) const { return *(i + j); }
+ inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
+ inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
+ inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
+ inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
+ inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
+ inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
+ inline constexpr bool operator==(iterator o) const { return i == o.i; }
+ inline constexpr bool operator!=(iterator o) const { return i != o.i; }
+ inline constexpr bool operator<(iterator other) const { return i < other.i; }
+ inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
+ inline constexpr bool operator>(iterator other) const { return i > other.i; }
+ inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
+ inline constexpr bool operator==(pointer p) const { return i == p; }
+ inline constexpr bool operator!=(pointer p) const { return i != p; }
+ inline const_iterator &operator++() { ++i; return *this; }
+ inline const_iterator operator++(int) { auto copy = *this; ++*this; return copy; }
+ inline const_iterator &operator--() { --i; return *this; }
+ inline const_iterator operator--(int) { auto copy = *this; --*this; return copy; }
+ inline qsizetype operator-(const_iterator j) const { return i - j.i; }
+#if QT_DEPRECATED_SINCE(6, 3) && !defined(QT_STRICT_QLIST_ITERATORS)
+ QT_DEPRECATED_VERSION_X_6_3("Use operator* or operator-> rather than relying on "
+ "the implicit conversion between a QList/QVector::const_iterator "
+ "and a raw pointer")
+ inline operator const T*() const { return i; }
+
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
+ &operator+=(Int j) { i+=j; return *this; }
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
+ &operator-=(Int j) { i-=j; return *this; }
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
+ operator+(Int j) const { return const_iterator(i+j); }
+ template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
+ operator-(Int j) const { return const_iterator(i-j); }
+ template <typename Int> friend std::enable_if_t<std::is_integral_v<Int>, const_iterator>
+ operator+(Int j, const_iterator k) { return k + j; }
+#else
+ inline const_iterator &operator+=(qsizetype j) { i += j; return *this; }
+ inline const_iterator &operator-=(qsizetype j) { i -= j; return *this; }
+ inline const_iterator operator+(qsizetype j) const { return const_iterator(i + j); }
+ inline const_iterator operator-(qsizetype j) const { return const_iterator(i - j); }
+ friend inline const_iterator operator+(qsizetype j, const_iterator k) { return k + j; }
+#endif
+ };
+ using Iterator = iterator;
+ using ConstIterator = const_iterator;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private:
- void resize_internal(int i, Qt::Initialization);
+ void resize_internal(qsizetype i);
bool isValidIterator(const_iterator i) const
{
const std::less<const T*> less = {};
- return !less(d->end(), i) && !less(i, d->begin());
+ return !less(d->end(), i.i) && !less(i.i, d->begin());
+ }
+
+ void verify([[maybe_unused]] qsizetype pos = 0, [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
}
public:
QList(DataPointer dd) noexcept
@@ -115,96 +274,153 @@ public:
public:
QList() = default;
- explicit QList(int size)
- : d(Data::allocate(size))
+ explicit QList(qsizetype size)
+ : d(size)
{
if (size)
d->appendInitialize(size);
}
- QList(int size, const T &t)
- : d(Data::allocate(size))
+ QList(qsizetype size, parameter_type t)
+ : d(size)
{
if (size)
d->copyAppend(size, t);
}
- inline QList(const QList<T> &other) noexcept : d(other.d) {}
- QList(QList<T> &&other) noexcept : d(std::move(other.d)) {}
inline QList(std::initializer_list<T> args)
- : d(Data::allocate(args.size()))
+ : d(qsizetype(args.size()))
{
if (args.size())
d->copyAppend(args.begin(), args.end());
}
- ~QList() /*noexcept(std::is_nothrow_destructible<T>::value)*/ {}
- QList<T> &operator=(const QList<T> &other) { d = other.d; return *this; }
- QList &operator=(QList &&other) noexcept(std::is_nothrow_destructible<T>::value)
- {
- d = std::move(other.d);
- return *this;
- }
QList<T> &operator=(std::initializer_list<T> args)
{
- d = DataPointer(Data::allocate(args.size()));
- if (args.size())
- d->copyAppend(args.begin(), args.end());
- return *this;
+ return assign(args);
}
- template <typename InputIterator, QtPrivate::IfIsForwardIterator<InputIterator> = true>
+
+ template <typename InputIterator, if_input_iterator<InputIterator> = true>
QList(InputIterator i1, InputIterator i2)
- : d(Data::allocate(std::distance(i1, i2)))
{
- if (std::distance(i1, i2))
- d->copyAppend(i1, i2);
+ if constexpr (!std::is_convertible_v<typename std::iterator_traits<InputIterator>::iterator_category, std::forward_iterator_tag>) {
+ std::copy(i1, i2, std::back_inserter(*this));
+ } else {
+ const auto distance = std::distance(i1, i2);
+ if (distance) {
+ d = DataPointer(qsizetype(distance));
+ // appendIteratorRange can deal with contiguous iterators on its own,
+ // this is an optimization for C++17 code.
+ if constexpr (std::is_same_v<std::decay_t<InputIterator>, iterator> ||
+ std::is_same_v<std::decay_t<InputIterator>, const_iterator>) {
+ d->copyAppend(i1.i, i2.i);
+ } else {
+ d->appendIteratorRange(i1, i2);
+ }
+ }
+ }
}
- template <typename InputIterator, QtPrivate::IfIsNotForwardIterator<InputIterator> = true>
- QList(InputIterator i1, InputIterator i2)
- : QList()
+ // This constructor is here for compatibility with QStringList in Qt 5, that has a QStringList(const QString &) constructor
+ template<typename String, typename = std::enable_if_t<std::is_same_v<T, QString> && std::is_convertible_v<String, QString>>>
+ inline explicit QList(const String &str)
+ { append(str); }
+
+ QList(qsizetype size, Qt::Initialization)
+ : d(size)
{
- QtPrivate::reserveIfForwardIterator(this, i1, i2);
- std::copy(i1, i2, std::back_inserter(*this));
+ if (size)
+ d->appendUninitialized(size);
}
- void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
+ // compiler-generated special member functions are fine!
+
+ void swap(QList &other) noexcept { d.swap(other.d); }
- friend bool operator==(const QList &l, const QList &r)
+#ifndef Q_QDOC
+ template <typename U = T>
+ QTypeTraits::compare_eq_result_container<QList, U> operator==(const QList &other) const
{
- if (l.size() != r.size())
+ if (size() != other.size())
return false;
- if (l.begin() == r.begin())
+ if (begin() == other.begin())
return true;
// do element-by-element comparison
- return l.d->compare(l.begin(), r.begin(), l.size());
+ return d->compare(data(), other.data(), size());
}
- friend bool operator!=(const QList &l, const QList &r)
+ template <typename U = T>
+ QTypeTraits::compare_eq_result_container<QList, U> operator!=(const QList &other) const
{
- return !(l == r);
+ return !(*this == other);
}
- int size() const noexcept { return int(d->size); }
- int count() const noexcept { return size(); }
- int length() const noexcept { return size(); }
+ template <typename U = T>
+ QTypeTraits::compare_lt_result_container<QList, U> operator<(const QList &other) const
+ noexcept(noexcept(std::lexicographical_compare<typename QList<U>::const_iterator,
+ typename QList::const_iterator>(
+ std::declval<QList<U>>().begin(), std::declval<QList<U>>().end(),
+ other.begin(), other.end())))
+ {
+ return std::lexicographical_compare(begin(), end(),
+ other.begin(), other.end());
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result_container<QList, U> operator>(const QList &other) const
+ noexcept(noexcept(other < std::declval<QList<U>>()))
+ {
+ return other < *this;
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result_container<QList, U> operator<=(const QList &other) const
+ noexcept(noexcept(other < std::declval<QList<U>>()))
+ {
+ return !(other < *this);
+ }
+
+ template <typename U = T>
+ QTypeTraits::compare_lt_result_container<QList, U> operator>=(const QList &other) const
+ noexcept(noexcept(std::declval<QList<U>>() < other))
+ {
+ return !(*this < other);
+ }
+#else
+ bool operator==(const QList &other) const;
+ bool operator!=(const QList &other) const;
+ bool operator<(const QList &other) const;
+ bool operator>(const QList &other) const;
+ bool operator<=(const QList &other) const;
+ bool operator>=(const QList &other) const;
+#endif // Q_QDOC
+
+ qsizetype size() const noexcept { return d->size; }
+ qsizetype count() const noexcept { return size(); }
+ qsizetype length() const noexcept { return size(); }
inline bool isEmpty() const noexcept { return d->size == 0; }
- void resize(int size)
+ void resize(qsizetype size)
{
- resize_internal(size, Qt::Uninitialized);
+ resize_internal(size);
if (size > this->size())
d->appendInitialize(size);
}
- void resize(int size, parameter_type c)
+ void resize(qsizetype size, parameter_type c)
{
- resize_internal(size, Qt::Uninitialized);
+ resize_internal(size);
if (size > this->size())
d->copyAppend(size - this->size(), c);
}
+ void resizeForOverwrite(qsizetype size)
+ {
+ resize_internal(size);
+ if (size > this->size())
+ d->appendUninitialized(size);
+ }
- inline int capacity() const { return int(d->constAllocatedCapacity()); }
- void reserve(int size);
+ inline qsizetype capacity() const { return qsizetype(d->constAllocatedCapacity()); }
+ void reserve(qsizetype size);
inline void squeeze();
void detach() { d.detach(); }
@@ -220,45 +436,64 @@ public:
return;
if (d->needsDetach()) {
// must allocate memory
- DataPointer detached(Data::allocate(d.allocatedCapacity(), d->detachFlags()));
+ DataPointer detached(d.allocatedCapacity());
d.swap(detached);
} else {
d->truncate(0);
}
}
- const_reference at(int i) const noexcept
+ const_reference at(qsizetype i) const noexcept
{
Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::at", "index out of range");
return data()[i];
}
- reference operator[](int i)
+ reference operator[](qsizetype i)
{
Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::operator[]", "index out of range");
- detach();
+ // don't detach() here, we detach in data below:
return data()[i];
}
- const_reference operator[](int i) const noexcept { return at(i); }
- void append(const_reference t)
- { append(const_iterator(std::addressof(t)), const_iterator(std::addressof(t)) + 1); }
+ const_reference operator[](qsizetype i) const noexcept { return at(i); }
+ void append(parameter_type t) { emplaceBack(t); }
void append(const_iterator i1, const_iterator i2);
- void append(rvalue_ref t) { emplaceBack(std::move(t)); }
- void append(const QList<T> &l) { append(l.constBegin(), l.constEnd()); }
- void prepend(rvalue_ref t);
- void prepend(const T &t);
+ void append(rvalue_ref t)
+ {
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(t);
+ } else {
+ emplaceBack(std::move(t));
+ }
+ }
+ void append(const QList<T> &l)
+ {
+ append(l.constBegin(), l.constEnd());
+ }
+ void append(QList<T> &&l);
+ void prepend(rvalue_ref t) {
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(t);
+ } else {
+ emplaceFront(std::move(t));
+ }
+ }
+ void prepend(parameter_type t) { emplaceFront(t); }
+
+ template<typename... Args>
+ inline reference emplaceBack(Args &&... args);
template <typename ...Args>
- reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward<Args>(args)...); }
+ inline reference emplaceFront(Args&&... args);
- iterator insert(int i, parameter_type t)
- { return insert(i, 1, t); }
- iterator insert(int i, int n, parameter_type t);
+ iterator insert(qsizetype i, parameter_type t)
+ { return emplace(i, t); }
+ iterator insert(qsizetype i, qsizetype n, parameter_type t);
iterator insert(const_iterator before, parameter_type t)
{
Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
return insert(before, 1, t);
}
- iterator insert(const_iterator before, int n, parameter_type t)
+ iterator insert(const_iterator before, qsizetype n, parameter_type t)
{
Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
return insert(std::distance(constBegin(), before), n, t);
@@ -268,7 +503,28 @@ public:
Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
return insert(std::distance(constBegin(), before), std::move(t));
}
- iterator insert(int i, rvalue_ref t) { return emplace(i, std::move(t)); }
+ iterator insert(qsizetype i, rvalue_ref t) {
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(i);
+ Q_UNUSED(t);
+ return end();
+ } else {
+ return emplace(i, std::move(t));
+ }
+ }
+
+ QList &assign(qsizetype n, parameter_type t)
+ {
+ Q_ASSERT(n >= 0);
+ return fill(t, n);
+ }
+
+ template <typename InputIterator, if_input_iterator<InputIterator> = true>
+ QList &assign(InputIterator first, InputIterator last)
+ { d.assign(first, last); return *this; }
+
+ QList &assign(std::initializer_list<T> l)
+ { return assign(l.begin(), l.end()); }
template <typename ...Args>
iterator emplace(const_iterator before, Args&&... args)
@@ -278,72 +534,83 @@ public:
}
template <typename ...Args>
- iterator emplace(int i, Args&&... args);
+ iterator emplace(qsizetype i, Args&&... args);
#if 0
template< class InputIt >
iterator insert( const_iterator pos, InputIt first, InputIt last );
iterator insert( const_iterator pos, std::initializer_list<T> ilist );
#endif
- void replace(int i, const T &t)
+ void replace(qsizetype i, parameter_type t)
{
Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
- const T copy(t);
- data()[i] = copy;
+ DataPointer oldData;
+ d.detach(&oldData);
+ d.data()[i] = t;
}
- void replace(int i, rvalue_ref t)
+ void replace(qsizetype i, rvalue_ref t)
{
- Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
- const T copy(std::move(t));
- data()[i] = std::move(copy);
+ if constexpr (DataPointer::pass_parameter_by_value) {
+ Q_UNUSED(i);
+ Q_UNUSED(t);
+ } else {
+ Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
+ DataPointer oldData;
+ d.detach(&oldData);
+ d.data()[i] = std::move(t);
+ }
}
- void remove(int i, int n = 1);
- void removeFirst() { Q_ASSERT(!isEmpty()); remove(0); }
- void removeLast() { Q_ASSERT(!isEmpty()); remove(size() - 1); }
- value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); remove(0); return v; }
- value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); remove(size() - 1); return v; }
+ void remove(qsizetype i, qsizetype n = 1);
+ void removeFirst() noexcept;
+ void removeLast() noexcept;
+ value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); d->eraseFirst(); return v; }
+ value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); d->eraseLast(); return v; }
- QList<T> &fill(parameter_type t, int size = -1);
+ QList<T> &fill(parameter_type t, qsizetype size = -1);
+
+#ifndef Q_QDOC
+ using QListSpecialMethods<T>::contains;
+ using QListSpecialMethods<T>::indexOf;
+ using QListSpecialMethods<T>::lastIndexOf;
+#else
+ template <typename AT>
+ qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept;
+ template <typename AT>
+ qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept;
+ template <typename AT>
+ bool contains(const AT &t) const noexcept;
+#endif
- int indexOf(const T &t, int from = 0) const noexcept;
- int lastIndexOf(const T &t, int from = -1) const noexcept;
- bool contains(const T &t) const noexcept
+ template <typename AT = T>
+ qsizetype count(const AT &t) const noexcept
{
- return indexOf(t) != -1;
+ return qsizetype(std::count(data(), data() + size(), t));
}
- int count(const T &t) const noexcept
+
+ void removeAt(qsizetype i) { remove(i); }
+ template <typename AT = T>
+ qsizetype removeAll(const AT &t)
{
- return int(std::count(&*cbegin(), &*cend(), t));
+ return QtPrivate::sequential_erase_with_copy(*this, t);
}
- // QList compatibility
- void removeAt(int i) { remove(i); }
- int removeAll(const T &t)
+ template <typename AT = T>
+ bool removeOne(const AT &t)
{
- const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
- if (cit == ce)
- return 0;
- int index = cit - this->cbegin();
- // next operation detaches, so ce, cit, t may become invalidated:
- const T tCopy = t;
- const iterator e = end(), it = std::remove(begin() + index, e, tCopy);
- const int result = std::distance(it, e);
- erase(it, e);
- return result;
+ return QtPrivate::sequential_erase_one(*this, t);
}
- bool removeOne(const T &t)
+
+ template <typename Predicate>
+ qsizetype removeIf(Predicate pred)
{
- const int i = indexOf(t);
- if (i < 0)
- return false;
- remove(i);
- return true;
+ return QtPrivate::sequential_erase_if(*this, pred);
}
- T takeAt(int i) { T t = std::move((*this)[i]); remove(i); return t; }
- void move(int from, int to)
+
+ T takeAt(qsizetype i) { T t = std::move((*this)[i]); remove(i); return t; }
+ void move(qsizetype from, qsizetype to)
{
- Q_ASSERT_X(from >= 0 && from < size(), "QList::move(int,int)", "'from' is out-of-range");
- Q_ASSERT_X(to >= 0 && to < size(), "QList::move(int,int)", "'to' is out-of-range");
+ Q_ASSERT_X(from >= 0 && from < size(), "QList::move(qsizetype, qsizetype)", "'from' is out-of-range");
+ Q_ASSERT_X(to >= 0 && to < size(), "QList::move(qsizetype, qsizetype)", "'to' is out-of-range");
if (from == to) // don't detach when no-op
return;
detach();
@@ -355,15 +622,15 @@ public:
}
// STL-style
- iterator begin() { detach(); return d->begin(); }
- iterator end() { detach(); return d->end(); }
-
- const_iterator begin() const noexcept { return d->constBegin(); }
- const_iterator end() const noexcept { return d->constEnd(); }
- const_iterator cbegin() const noexcept { return d->constBegin(); }
- const_iterator cend() const noexcept { return d->constEnd(); }
- const_iterator constBegin() const noexcept { return d->constBegin(); }
- const_iterator constEnd() const noexcept { return d->constEnd(); }
+ iterator begin() { detach(); return iterator(d->begin()); }
+ iterator end() { detach(); return iterator(d->end()); }
+
+ const_iterator begin() const noexcept { return const_iterator(d->constBegin()); }
+ const_iterator end() const noexcept { return const_iterator(d->constEnd()); }
+ const_iterator cbegin() const noexcept { return const_iterator(d->constBegin()); }
+ const_iterator cend() const noexcept { return const_iterator(d->constEnd()); }
+ const_iterator constBegin() const noexcept { return const_iterator(d->constBegin()); }
+ const_iterator constEnd() const noexcept { return const_iterator(d->constEnd()); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
@@ -376,19 +643,28 @@ public:
// more Qt
inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &first() const noexcept { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &constFirst() const noexcept { Q_ASSERT(!isEmpty()); return *begin(); }
inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
- inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
- inline const T &constLast() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
- inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
- inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
- QList<T> mid(int pos, int len = -1) const;
-
- T value(int i) const { return value(i, T()); }
- T value(int i, const T &defaultValue) const;
-
- void swapItemsAt(int i, int j) {
+ inline const T &last() const noexcept { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline const T &constLast() const noexcept { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline bool startsWith(parameter_type t) const { return !isEmpty() && first() == t; }
+ inline bool endsWith(parameter_type t) const { return !isEmpty() && last() == t; }
+ QList<T> mid(qsizetype pos, qsizetype len = -1) const;
+
+ QList<T> first(qsizetype n) const
+ { verify(0, n); return QList<T>(begin(), begin() + n); }
+ QList<T> last(qsizetype n) const
+ { verify(0, n); return QList<T>(end() - n, end()); }
+ QList<T> sliced(qsizetype pos) const
+ { verify(pos, 0); return QList<T>(begin() + pos, end()); }
+ QList<T> sliced(qsizetype pos, qsizetype n) const
+ { verify(pos, n); return QList<T>(begin() + pos, begin() + pos + n); }
+
+ T value(qsizetype i) const { return value(i, T()); }
+ T value(qsizetype i, parameter_type defaultValue) const;
+
+ void swapItemsAt(qsizetype i, qsizetype j) {
Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(),
"QList<T>::swap", "index out of range");
detach();
@@ -396,108 +672,126 @@ public:
}
// STL compatibility
- inline void push_back(const T &t) { append(t); }
+ inline void push_back(parameter_type t) { append(t); }
void push_back(rvalue_ref t) { append(std::move(t)); }
void push_front(rvalue_ref t) { prepend(std::move(t)); }
- inline void push_front(const T &t) { prepend(t); }
- void pop_back() { removeLast(); }
- void pop_front() { removeFirst(); }
+ inline void push_front(parameter_type t) { prepend(t); }
+ void pop_back() noexcept { removeLast(); }
+ void pop_front() noexcept { removeFirst(); }
template <typename ...Args>
reference emplace_back(Args&&... args) { return emplaceBack(std::forward<Args>(args)...); }
- inline bool empty() const
+ inline bool empty() const noexcept
{ return d->size == 0; }
inline reference front() { return first(); }
- inline const_reference front() const { return first(); }
+ inline const_reference front() const noexcept { return first(); }
inline reference back() { return last(); }
- inline const_reference back() const { return last(); }
+ inline const_reference back() const noexcept { return last(); }
void shrink_to_fit() { squeeze(); }
+ static qsizetype max_size() noexcept
+ {
+ return Data::max_size();
+ }
// comfort
- QList<T> &operator+=(const QList<T> &l) { append(l.cbegin(), l.cend()); return *this; }
- inline QList<T> operator+(const QList<T> &l) const
+ QList<T> &operator+=(const QList<T> &l) { append(l); return *this; }
+ QList<T> &operator+=(QList<T> &&l) { append(std::move(l)); return *this; }
+ inline QList<T> operator+(const QList<T> &l) const &
{ QList n = *this; n += l; return n; }
- inline QList<T> &operator+=(const T &t)
+ QList<T> operator+(const QList<T> &l) &&
+ { return std::move(*this += l); }
+ inline QList<T> operator+(QList<T> &&l) const &
+ { QList n = *this; n += std::move(l); return n; }
+ QList<T> operator+(QList<T> &&l) &&
+ { return std::move(*this += std::move(l)); }
+ inline QList<T> &operator+=(parameter_type t)
{ append(t); return *this; }
- inline QList<T> &operator<< (const T &t)
+ inline QList<T> &operator<< (parameter_type t)
{ append(t); return *this; }
inline QList<T> &operator<<(const QList<T> &l)
{ *this += l; return *this; }
+ inline QList<T> &operator<<(QList<T> &&l)
+ { *this += std::move(l); return *this; }
inline QList<T> &operator+=(rvalue_ref t)
{ append(std::move(t)); return *this; }
inline QList<T> &operator<<(rvalue_ref t)
{ append(std::move(t)); return *this; }
// Consider deprecating in 6.4 or later
- static QList<T> fromList(const QList<T> &list) { return list; }
- QList<T> toList() const { return *this; }
+ static QList<T> fromList(const QList<T> &list) noexcept { return list; }
+ QList<T> toList() const noexcept { return *this; }
- static inline QList<T> fromVector(const QList<T> &vector) { return vector; }
- inline QList<T> toVector() const { return *this; }
+ static inline QList<T> fromVector(const QList<T> &vector) noexcept { return vector; }
+ inline QList<T> toVector() const noexcept { return *this; }
+
+ template<qsizetype N>
+ static QList<T> fromReadOnlyData(const T (&t)[N]) noexcept
+ {
+ return QList<T>({ nullptr, const_cast<T *>(t), N });
+ }
};
-#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
template <typename InputIterator,
typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
QtPrivate::IfIsInputIterator<InputIterator> = true>
QList(InputIterator, InputIterator) -> QList<ValueType>;
-#endif
template <typename T>
-inline void QList<T>::resize_internal(int newSize, Qt::Initialization)
+inline void QList<T>::resize_internal(qsizetype newSize)
{
Q_ASSERT(newSize >= 0);
- if (d->needsDetach() || newSize > capacity()) {
- // must allocate memory
- DataPointer detached(Data::allocate(d->detachCapacity(newSize),
- d->detachFlags()));
- if (size() && newSize) {
- detached->copyAppend(constBegin(), constBegin() + qMin(newSize, size()));
- }
- d.swap(detached);
- }
-
- if (newSize < size())
+ if (d->needsDetach() || newSize > capacity() - d.freeSpaceAtBegin()) {
+ d.detachAndGrow(QArrayData::GrowsAtEnd, newSize - d.size, nullptr, nullptr);
+ } else if (newSize < size()) {
d->truncate(newSize);
+ }
}
template <typename T>
-void QList<T>::reserve(int asize)
+void QList<T>::reserve(qsizetype asize)
{
// capacity() == 0 for immutable data, so this will force a detaching below
- if (asize <= capacity()) {
+ if (asize <= capacity() - d.freeSpaceAtBegin()) {
if (d->flags() & Data::CapacityReserved)
return; // already reserved, don't shrink
if (!d->isShared()) {
// accept current allocation, don't shrink
- d->flags() |= Data::CapacityReserved;
+ d->setFlag(Data::CapacityReserved);
return;
}
}
- DataPointer detached(Data::allocate(qMax(asize, size()),
- d->detachFlags() | Data::CapacityReserved));
- detached->copyAppend(constBegin(), constEnd());
+ DataPointer detached(qMax(asize, size()));
+ detached->copyAppend(d->begin(), d->end());
+ if (detached.d_ptr())
+ detached->setFlag(Data::CapacityReserved);
d.swap(detached);
}
template <typename T>
inline void QList<T>::squeeze()
{
- if (d->needsDetach() || size() != capacity()) {
+ if (!d.isMutable())
+ return;
+ if (d->needsDetach() || size() < capacity()) {
// must allocate memory
- DataPointer detached(Data::allocate(size(), d->detachFlags() & ~Data::CapacityReserved));
+ DataPointer detached(size());
if (size()) {
- detached->copyAppend(constBegin(), constEnd());
+ if (d.needsDetach())
+ detached->copyAppend(d.data(), d.data() + d.size);
+ else
+ detached->moveAppend(d.data(), d.data() + d.size);
}
d.swap(detached);
}
+ // We're detached so this is fine
+ d->clearFlag(Data::CapacityReserved);
}
template <typename T>
-inline void QList<T>::remove(int i, int n)
+inline void QList<T>::remove(qsizetype i, qsizetype n)
{
Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(d->size), "QList::remove", "index out of range");
Q_ASSERT_X(n >= 0, "QList::remove", "invalid count");
@@ -505,34 +799,29 @@ inline void QList<T>::remove(int i, int n)
if (n == 0)
return;
- const size_t newSize = size() - n;
- if (d->needsDetach() ||
- ((d->flags() & Data::CapacityReserved) == 0
- && newSize < d->allocatedCapacity()/2)) {
- // allocate memory
- DataPointer detached(Data::allocate(d->detachCapacity(newSize),
- d->detachFlags() & ~(Data::GrowsBackwards | Data::GrowsForward)));
- const_iterator where = constBegin() + i;
- if (newSize) {
- detached->copyAppend(constBegin(), where);
- detached->copyAppend(where + n, constEnd());
- }
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- d->erase(d->begin() + i, d->begin() + i + n);
- }
+ d.detach();
+ d->erase(d->begin() + i, n);
}
template <typename T>
-inline void QList<T>::prepend(const T &t)
-{ insert(0, 1, t); }
+inline void QList<T>::removeFirst() noexcept
+{
+ Q_ASSERT(!isEmpty());
+ d.detach();
+ d->eraseFirst();
+}
+
template <typename T>
-void QList<T>::prepend(rvalue_ref t)
-{ insert(0, std::move(t)); }
+inline void QList<T>::removeLast() noexcept
+{
+ Q_ASSERT(!isEmpty());
+ d.detach();
+ d->eraseLast();
+}
+
template<typename T>
-inline T QList<T>::value(int i, const T &defaultValue) const
+inline T QList<T>::value(qsizetype i, parameter_type defaultValue) const
{
return size_t(i) < size_t(d->size) ? at(i) : defaultValue;
}
@@ -540,89 +829,60 @@ inline T QList<T>::value(int i, const T &defaultValue) const
template <typename T>
inline void QList<T>::append(const_iterator i1, const_iterator i2)
{
- if (i1 == i2)
- return;
- const size_t newSize = size() + std::distance(i1, i2);
- if (d->needsDetach() || newSize > d->allocatedCapacity()) {
- DataPointer detached(Data::allocate(d->detachCapacity(newSize),
- d->detachFlags() | Data::GrowsForward));
- detached->copyAppend(constBegin(), constEnd());
- detached->copyAppend(i1, i2);
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- d->copyAppend(i1, i2);
- }
+ d->growAppend(i1.i, i2.i);
}
template <typename T>
-inline typename QList<T>::iterator
-QList<T>::insert(int i, int n, parameter_type t)
+inline void QList<T>::append(QList<T> &&other)
{
- Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList<T>::insert", "index out of range");
+ Q_ASSERT(&other != this);
+ if (other.isEmpty())
+ return;
+ if (other.d->needsDetach() || !std::is_nothrow_move_constructible_v<T>)
+ return append(other);
- // we don't have a quick exit for n == 0
- // it's not worth wasting CPU cycles for that
+ // due to precondition &other != this, we can unconditionally modify 'this'
+ d.detachAndGrow(QArrayData::GrowsAtEnd, other.size(), nullptr, nullptr);
+ Q_ASSERT(d.freeSpaceAtEnd() >= other.size());
+ d->moveAppend(other.d->begin(), other.d->end());
+}
- const size_t newSize = size() + n;
- if (d->needsDetach() || newSize > d->allocatedCapacity()) {
- typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
- if (size_t(i) <= newSize / 4)
- flags |= Data::GrowsBackwards;
+template<typename T>
+template<typename... Args>
+inline typename QList<T>::reference QList<T>::emplaceFront(Args &&... args)
+{
+ d->emplace(0, std::forward<Args>(args)...);
+ return *d.begin();
+}
- DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
- const_iterator where = constBegin() + i;
- detached->copyAppend(constBegin(), where);
- detached->copyAppend(n, t);
- detached->copyAppend(where, constEnd());
- d.swap(detached);
- } else {
- // we're detached and we can just move data around
- if (i == size()) {
- d->copyAppend(n, t);
- } else {
- T copy(t);
- d->insert(d.begin() + i, n, copy);
- }
- }
- return d.begin() + i;
+
+template <typename T>
+inline typename QList<T>::iterator
+QList<T>::insert(qsizetype i, qsizetype n, parameter_type t)
+{
+ Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList<T>::insert", "index out of range");
+ Q_ASSERT_X(n >= 0, "QList::insert", "invalid count");
+ if (Q_LIKELY(n))
+ d->insert(i, n, t);
+ return begin() + i;
}
template <typename T>
template <typename ...Args>
typename QList<T>::iterator
-QList<T>::emplace(int i, Args&&... args)
+QList<T>::emplace(qsizetype i, Args&&... args)
{
- Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
-
- const size_t newSize = size() + 1;
- if (d->needsDetach() || newSize > d->allocatedCapacity()) {
- typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
- if (size_t(i) <= newSize / 4)
- flags |= Data::GrowsBackwards;
-
- DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
- const_iterator where = constBegin() + i;
-
- // First, create an element to handle cases, when a user moves
- // the element from a container to the same container
- detached->createInPlace(detached.begin() + i, std::forward<Args>(args)...);
-
- // Then, put the first part of the elements to the new location
- detached->copyAppend(constBegin(), where);
-
- // After that, increase the actual size, because we created
- // one extra element
- ++detached.size;
-
- // Finally, put the rest of the elements to the new location
- detached->copyAppend(where, constEnd());
+ Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
+ d->emplace(i, std::forward<Args>(args)...);
+ return begin() + i;
+}
- d.swap(detached);
- } else {
- d->emplace(d.begin() + i, std::forward<Args>(args)...);
- }
- return d.begin() + i;
+template<typename T>
+template<typename... Args>
+inline typename QList<T>::reference QList<T>::emplaceBack(Args &&... args)
+{
+ d->emplace(d->size, std::forward<Args>(args)...);
+ return *(end() - 1);
}
template <typename T>
@@ -632,52 +892,54 @@ typename QList<T>::iterator QList<T>::erase(const_iterator abegin, const_iterato
Q_ASSERT_X(isValidIterator(aend), "QList::erase", "The specified iterator argument 'aend' is invalid");
Q_ASSERT(aend >= abegin);
- int i = std::distance(d.constBegin(), abegin);
- int n = std::distance(abegin, aend);
+ qsizetype i = std::distance(constBegin(), abegin);
+ qsizetype n = std::distance(abegin, aend);
remove(i, n);
- return d.begin() + i;
+ return begin() + i;
}
template <typename T>
-inline QList<T> &QList<T>::fill(parameter_type t, int newSize)
+inline QList<T> &QList<T>::fill(parameter_type t, qsizetype newSize)
{
if (newSize == -1)
newSize = size();
if (d->needsDetach() || newSize > capacity()) {
// must allocate memory
- DataPointer detached(Data::allocate(d->detachCapacity(newSize),
- d->detachFlags()));
+ DataPointer detached(d->detachCapacity(newSize));
detached->copyAppend(newSize, t);
d.swap(detached);
} else {
// we're detached
const T copy(t);
d->assign(d.begin(), d.begin() + qMin(size(), newSize), t);
- if (newSize > size())
+ if (newSize > size()) {
d->copyAppend(newSize - size(), copy);
+ } else if (newSize < size()) {
+ d->truncate(newSize);
+ }
}
return *this;
}
namespace QtPrivate {
template <typename T, typename U>
-int indexOf(const QList<T> &vector, const U &u, int from)
+qsizetype indexOf(const QList<T> &vector, const U &u, qsizetype from) noexcept
{
if (from < 0)
- from = qMax(from + vector.size(), 0);
+ from = qMax(from + vector.size(), qsizetype(0));
if (from < vector.size()) {
auto n = vector.begin() + from - 1;
auto e = vector.end();
while (++n != e)
if (*n == u)
- return int(n - vector.begin());
+ return qsizetype(n - vector.begin());
}
return -1;
}
template <typename T, typename U>
-int lastIndexOf(const QList<T> &vector, const U &u, int from)
+qsizetype lastIndexOf(const QList<T> &vector, const U &u, qsizetype from) noexcept
{
if (from < 0)
from += vector.d->size;
@@ -688,7 +950,7 @@ int lastIndexOf(const QList<T> &vector, const U &u, int from)
auto n = vector.begin() + from + 1;
while (n != b) {
if (*--n == u)
- return int(n - b);
+ return qsizetype(n - b);
}
}
return -1;
@@ -696,19 +958,21 @@ int lastIndexOf(const QList<T> &vector, const U &u, int from)
}
template <typename T>
-int QList<T>::indexOf(const T &t, int from) const noexcept
+template <typename AT>
+qsizetype QListSpecialMethodsBase<T>::indexOf(const AT &t, qsizetype from) const noexcept
{
- return QtPrivate::indexOf<T, T>(*this, t, from);
+ return QtPrivate::indexOf(*self(), t, from);
}
template <typename T>
-int QList<T>::lastIndexOf(const T &t, int from) const noexcept
+template <typename AT>
+qsizetype QListSpecialMethodsBase<T>::lastIndexOf(const AT &t, qsizetype from) const noexcept
{
- return QtPrivate::lastIndexOf(*this, t, from);
+ return QtPrivate::lastIndexOf(*self(), t, from);
}
template <typename T>
-inline QList<T> QList<T>::mid(int pos, int len) const
+inline QList<T> QList<T>::mid(qsizetype pos, qsizetype len) const
{
qsizetype p = pos;
qsizetype l = len;
@@ -724,8 +988,8 @@ inline QList<T> QList<T>::mid(int pos, int len) const
}
// Allocate memory
- DataPointer copied(Data::allocate(l));
- copied->copyAppend(constBegin() + p, constBegin() + p + l);
+ DataPointer copied(l);
+ copied->copyAppend(data() + p, data() + p + l);
return copied;
}
@@ -739,55 +1003,19 @@ size_t qHash(const QList<T> &key, size_t seed = 0)
return qHashRange(key.cbegin(), key.cend(), seed);
}
-template <typename T>
-auto operator<(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end())))
- -> decltype(std::declval<T>() < std::declval<T>())
-{
- return std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end());
-}
-
-template <typename T>
-auto operator>(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
- -> decltype(lhs < rhs)
-{
- return rhs < lhs;
-}
-
-template <typename T>
-auto operator<=(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
- -> decltype(lhs < rhs)
+template <typename T, typename AT>
+qsizetype erase(QList<T> &list, const AT &t)
{
- return !(lhs > rhs);
+ return QtPrivate::sequential_erase(list, t);
}
-template <typename T>
-auto operator>=(const QList<T> &lhs, const QList<T> &rhs)
- noexcept(noexcept(lhs < rhs))
- -> decltype(lhs < rhs)
+template <typename T, typename Predicate>
+qsizetype erase_if(QList<T> &list, Predicate pred)
{
- return !(lhs < rhs);
+ return QtPrivate::sequential_erase_if(list, pred);
}
-/*
- ### Qt 5:
- ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
- ### Qt exports QPolygon and QPolygonF that inherit QList<QPoint> and
- ### QList<QPointF> respectively.
-*/
-
-#if defined(Q_CC_MSVC) && !defined(QT_BUILD_CORE_LIB)
-QT_BEGIN_INCLUDE_NAMESPACE
-#include <QtCore/qpoint.h>
-QT_END_INCLUDE_NAMESPACE
-extern template class Q_CORE_EXPORT QList<QPointF>;
-extern template class Q_CORE_EXPORT QList<QPoint>;
-#endif
-
+// ### Qt 7 char32_t
QList<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlist.qdoc b/src/corelib/tools/qlist.qdoc
index 1a94bf4315..e07b74cd53 100644
--- a/src/corelib/tools/qlist.qdoc
+++ b/src/corelib/tools/qlist.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QVector
@@ -124,12 +100,11 @@
many times a particular value occurs in the list, use count().
QList provides these basic functions to add, move, and remove
- items: insert(), replace(), remove(), prepend(), append(). With
- the exception of append() and replace(), these functions can be slow
- (\l{linear time}) for large lists, because they require moving many
- items in the list by one position in memory. If you want a container
- class that provides fast insertion/removal in the middle, use
- std::list instead.
+ items: insert(), replace(), remove(), prepend(), append(). With the
+ exception of append(), prepend() and replace(), these functions can be slow
+ (\l{linear time}) for large lists, because they require moving many items in
+ the list by one position in memory. If you want a container class that
+ provides fast insertion/removal in the middle, use std::list instead.
Unlike plain C++ arrays, QLists can be resized at any time by
calling resize(). If the new size is larger than the old size,
@@ -137,14 +112,14 @@
to reduce the number of reallocations by preallocating up to twice
as much memory as the actual data needs.
- If you know in advance approximately how many items the QList
- will contain, you can call reserve(), asking QList to
- preallocate a certain amount of memory. You can also call
- capacity() to find out how much memory QList actually
- allocated.
+ If you're building a QList gradually and know in advance
+ approximately how many elements it will contain, you can call reserve(),
+ asking QList to preallocate a certain amount of memory.
+ You can also call capacity() to find out how much memory the
+ QList actually has allocated.
- Note that using non-const operators and functions can cause
- QList to do a deep copy of the data. This is due to \l{implicit sharing}.
+ Note that using non-const operators and functions can cause QList
+ to do a deep copy of the data, due to \l{implicit sharing}.
QList's value type must be an \l{assignable data type}. This
covers most data types that are commonly used, but the compiler
@@ -154,20 +129,12 @@
support \c operator==(). These requirements are documented on a
per-function basis.
- Like the other container classes, QList provides \l{Java-style
- iterators} (QListIterator and QMutableListIterator) and
- \l{STL-style iterators} (QList::const_iterator and
- QList::iterator). In practice, these are rarely used, because
- you can use indexes into the QList.
+ For iterating over the items, see \l {Iterating over Containers}.
In addition to QList, Qt also provides QVarLengthArray, a very
low-level class with little functionality that is optimized for
speed.
- QList does \e not support inserting, prepending, appending or replacing
- with references to its own values. Doing so will cause your application to
- abort with an error message.
-
\section2 More Information on Using Qt Containers
For a detailed discussion comparing Qt containers with each other and
@@ -175,14 +142,16 @@
\section1 Maximum size and out-of-memory conditions
- The current version of QList is limited to just under 2 GB (2^31 bytes)
- in size. The exact value is architecture-dependent, since it depends on the
- overhead required for managing the data block, but is no more than 32
- bytes. The number of elements that can be stored in a QList is that size
- divided by the size of each element.
+ The maximum size of QList depends on the architecture. Most 64-bit
+ systems can allocate more than 2 GB of memory, with a typical limit
+ of 2^63 bytes. The actual value also depends on the overhead required for
+ managing the data block. As a result, you can expect the maximum size
+ of 2 GB minus overhead on 32-bit platforms, and 2^63 bytes minus overhead
+ on 64-bit platforms. The number of elements that can be stored in a
+ QList is this maximum size divided by the size of a stored element.
- In case memory allocation fails, QList will use the \l Q_CHECK_PTR macro,
- which will throw a \c std::bad_alloc exception if the application is being
+ When memory allocation fails, QList uses the \l Q_CHECK_PTR macro,
+ which throws a \c std::bad_alloc exception if the application is being
compiled with exception support. If exceptions are disabled, then running
out of memory is undefined behavior.
@@ -193,7 +162,7 @@
*/
/*!
- \fn template <typename T> QList<T> QList<T>::mid(int pos, int length = -1) const
+ \fn template <typename T> QList<T> QList<T>::mid(qsizetype pos, qsizetype length = -1) const
Returns a sub-list which contains elements from this list,
starting at position \a pos. If \a length is -1 (the default), all
@@ -202,6 +171,55 @@
are included.
*/
+/*!
+ \fn template <typename T> QList<T> QList<T>::first(qsizetype n) const
+ \since 6.0
+
+ Returns a sub-list that contains the first \a n elements
+ of this list.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa last(), sliced()
+*/
+
+/*!
+ \fn template <typename T> QList<T> QList<T>::last(qsizetype n) const
+ \since 6.0
+
+ Returns a sub-list that contains the last \a n elements of this list.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa first(), sliced()
+*/
+
+/*!
+ \fn template <typename T> QList<T> QList<T>::sliced(qsizetype pos, qsizetype n) const
+ \since 6.0
+
+ Returns a sub-list that contains \a n elements of this list,
+ starting at position \a pos.
+
+ \note The behavior is undefined when \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+
+ \sa first(), last()
+*/
+
+/*!
+ \fn template <typename T> QList<T> QList<T>::sliced(qsizetype pos) const
+ \since 6.0
+ \overload
+
+ Returns a sub-list that contains the elements of this list starting at
+ position \a pos and extending to its end.
+
+ \note The behavior is undefined when \a pos < 0 or \a pos > size().
+
+ \sa first(), last()
+*/
+
/*! \fn template <typename T> QList<T>::QList()
@@ -219,7 +237,7 @@
\since 5.2
*/
-/*! \fn template <typename T> QList<T>::QList(int size)
+/*! \fn template <typename T> QList<T>::QList(qsizetype size)
Constructs a list with an initial size of \a size elements.
@@ -229,7 +247,32 @@
\sa resize()
*/
-/*! \fn template <typename T> QList<T>::QList(int size, const T &value)
+/*! \fn template <typename T> QList<T>::QList(qsizetype size, Qt::Initialization)
+ \since 6.8
+
+ Constructs a list with an initial size of \a size elements.
+
+ QList will make an attempt at \b{not initializing} the elements.
+
+//! [qlist-uninitialized-strategy]
+ Specifically:
+
+ \list
+
+ \li if \c{T} has a constructor that accepts \c{Qt::Uninitialized},
+ that constructor will be used to initialize the elements;
+
+ \li otherwise, each element is default constructed. For
+ trivially constructible types (such as \c{int}, \c{float}, etc.)
+ this is equivalent to not initializing them.
+
+ \endlist
+//! [qlist-uninitialized-strategy]
+
+ \sa resizeForOverwrite()
+*/
+
+/*! \fn template <typename T> QList<T>::QList(qsizetype size, parameter_type value)
Constructs a list with an initial size of \a size elements.
Each element is initialized with \a value.
@@ -254,22 +297,18 @@
\since 4.8
Constructs a list from the std::initializer_list given by \a args.
-
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
*/
-/*! \fn template <typename T> template<typename InputIterator> QList<T>::QList(InputIterator first, InputIterator last)
+/*! \fn template<typename T> template <typename InputIterator, QList<T>::if_input_iterator<InputIterator> = true> QList<T>::QList(InputIterator first, InputIterator last)
\since 5.14
Constructs a list with the contents in the iterator range [\a first, \a last).
- The value type of \c InputIterator must be convertible to \c T.
-*/
+ \note This constructor only participates in overload resolution if
+ \c InputIterator meets the requirements of a
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}.
-/*!
- \fn template <typename T> QList<T>::QList(QArrayDataPointerRef<T> ref)
- \internal
+ The value type of \c InputIterator must be convertible to \c T.
*/
/*! \fn template <typename T> QList<T>::~QList()
@@ -293,13 +332,9 @@
/*!
\fn template <typename T> QList<T> &QList<T>::operator=(std::initializer_list<T> args)
+ \since 5.14
Assigns the collection of values in \a args to this QList instance.
-
- This operator is only enabled if the compiler supports C++11 initializer
- lists.
-
- \since 5.14
*/
/*! \fn template <typename T> void QList<T>::swap(QList<T> &other)
@@ -309,8 +344,7 @@
never fails.
*/
-/*! \fn template <typename T> void QList<T>::swapItemsAt(int i, int j)
- \since 5.14
+/*! \fn template <typename T> void QList<T>::swapItemsAt(qsizetype i, qsizetype j)
Exchange the item at index position \a i with the item at index
position \a j. This function assumes that both \a i and \a j are
@@ -347,49 +381,45 @@
\sa operator==()
*/
-/*! \fn template <typename T> bool operator<(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator<(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically less than} \a rhs; otherwise returns \c false.
+ {lexically less than} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
*/
-/*! \fn template <typename T> bool operator<=(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator<=(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically less than or equal to} \a rhs; otherwise returns \c false.
+ {lexically less than or equal to} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
*/
-/*! \fn template <typename T> bool operator>(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator>(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically greater than} \a rhs; otherwise returns \c false.
+ {lexically greater than} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
*/
-/*! \fn template <typename T> bool operator>=(const QList<T> &lhs, const QList<T> &rhs)
+/*! \fn template <typename T> bool QList<T>::operator>=(const QList<T> &other) const
\since 5.6
- \relates QList
- Returns \c true if list \a lhs is
+ Returns \c true if this list is
\l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare}
- {lexicographically greater than or equal to} \a rhs; otherwise returns \c false.
+ {lexically greater than or equal to} \a other; otherwise returns \c false.
This function requires the value type to have an implementation
of \c operator<().
@@ -406,7 +436,7 @@
This function requires qHash() to be overloaded for the value type \c T.
*/
-/*! \fn template <typename T> int QList<T>::size() const
+/*! \fn template <typename T> qsizetype QList<T>::size() const
Returns the number of items in the list.
@@ -420,20 +450,37 @@
\sa size(), resize()
*/
-/*! \fn template <typename T> void QList<T>::resize(int size)
+/*! \fn template <typename T> void QList<T>::resize(qsizetype size)
+ \fn template <typename T> void QList<T>::resize(qsizetype size, parameter_type c)
+ \since 6.0
Sets the size of the list to \a size. If \a size is greater than the
current size, elements are added to the end; the new elements are
- initialized with a \l{default-constructed value}. If \a size is less
- than the current size, elements are removed from the end.
+ initialized with either a \l{default-constructed value} or \a c. If \a size
+ is less than the current size, elements are removed from the end.
+
+ If this list is not shared, the capacity() is preserved. Use squeeze()
+ to shed excess capacity.
- Since Qt 5.6, resize() doesn't shrink the capacity anymore.
- To shed excess capacity, use squeeze().
+ \note In Qt versions prior to 5.7 (for QVector; QList lacked a resize()
+ until 6.0), this function released the memory used by the list instead of
+ preserving the capacity.
\sa size()
*/
-/*! \fn template <typename T> int QList<T>::capacity() const
+/*! \fn template <typename T> void QList<T>::resizeForOverwrite(qsizetype size)
+ \since 6.8
+
+ Sets the size of the list to \a size. If \a size is less than the
+ current size, elements are removed from the end. If \a size is
+ greater than the current size, elements are added to the end; QList
+ will make an attempt at \b{not initializing} these new elements.
+
+ \include qlist.qdoc qlist-uninitialized-strategy
+*/
+
+/*! \fn template <typename T> qsizetype QList<T>::capacity() const
Returns the maximum number of items that can be stored in the
list without forcing a reallocation.
@@ -446,32 +493,35 @@
\note a statically allocated list will report a capacity of 0,
even if it's not empty.
+ \warning The free space position in the allocated memory block is undefined.
+ In other words, you should not assume that the free memory is always located
+ at the end of the list. You can call reserve() to ensure that there is
+ enough space at the end.
+
\sa reserve(), squeeze()
*/
-/*! \fn template <typename T> void QList<T>::reserve(int size)
+/*! \fn template <typename T> void QList<T>::reserve(qsizetype size)
- Attempts to allocate memory for at least \a size elements. If you
- know in advance how large the list will be, you should call this
- function to prevent reallocations and memory fragmentation.
+ Attempts to allocate memory for at least \a size elements.
- If \a size is an underestimate, the worst that will happen is that
- the QList will be a bit slower. If \a size is an overestimate, you
- may have used more memory than the normal QList growth strategy
- would have allocated—or you may have used less.
+ If you know in advance how large the list will be, you should call this
+ function to prevent reallocations and memory fragmentation. If you resize
+ the list often, you are also likely to get better performance.
- An alternative to reserve() is calling resize(). Whether or not that is
- faster than reserve() depends on the element type, because resize()
- default-constructs all elements, and requires assignment to existing
- entries rather than calling append(), which copy- or move-constructs.
- For simple types, like \c int or \c double, resize() is typically faster,
- but for anything more complex, you should prefer reserve().
+ If in doubt about how much space shall be needed, it is usually better to
+ use an upper bound as \a size, or a high estimate of the most likely size,
+ if a strict upper bound would be much bigger than this. If \a size is an
+ underestimate, the list will grow as needed once the reserved size is
+ exceeded, which may lead to a larger allocation than your best overestimate
+ would have and will slow the operation that triggers it.
- \warning If the size passed to resize() was underestimated, you run out
- of allocated space and into undefined behavior. This problem does not
- exist with reserve(), because it treats the size as just a hint.
+ \warning reserve() reserves memory but does not change the size of the
+ list. Accessing data beyond the current end of the list is
+ undefined behavior. If you need to access memory beyond the current end of
+ the list, use resize().
- \sa squeeze(), capacity()
+ \sa squeeze(), capacity(), resize()
*/
/*! \fn template <typename T> void QList<T>::squeeze()
@@ -513,8 +563,8 @@
Example:
\snippet code/src_corelib_tools_qlist.cpp 6
- The pointer remains valid as long as the list isn't
- reallocated.
+ \warning The pointer is invalidated on detachment or when the QList is
+ modified.
This function is mostly useful to pass a list to a function
that accepts a plain C++ array.
@@ -531,8 +581,9 @@
Returns a const pointer to the data stored in the list. The
pointer can be used to access the items in the list.
- The pointer remains valid as long as the list isn't
- reallocated.
+
+ \warning The pointer is invalidated on detachment or when the QList is
+ modified.
This function is mostly useful to pass a list to a function
that accepts a plain C++ array.
@@ -544,20 +595,17 @@
Removes all the elements from the list.
- \note Until Qt 5.6, this also released the memory used by
- the list. From Qt 5.7, the capacity is preserved. To shed
- all capacity, swap with a default-constructed list:
- \code
- QList<T> v ...;
- QList<T>().swap(v);
- Q_ASSERT(v.capacity() == 0);
- \endcode
- or call squeeze().
+ If this list is not shared, the capacity() is preserved. Use squeeze() to
+ shed excess capacity.
+
+ \note In Qt versions prior to 5.7 (for QVector) and 6.0 (for QList), this
+ function released the memory used by the list instead of preserving the
+ capacity.
- \sa squeeze()
+ \sa resize(), squeeze()
*/
-/*! \fn template <typename T> const T &QList<T>::at(int i) const
+/*! \fn template <typename T> const T &QList<T>::at(qsizetype i) const
Returns the item at index position \a i in the list.
@@ -567,7 +615,7 @@
\sa value(), operator[]()
*/
-/*! \fn template <typename T> T &QList<T>::operator[](int i)
+/*! \fn template <typename T> T &QList<T>::operator[](qsizetype i)
Returns the item at index position \a i as a modifiable reference.
@@ -580,7 +628,7 @@
\sa at(), value()
*/
-/*! \fn template <typename T> const T &QList<T>::operator[](int i) const
+/*! \fn template <typename T> const T &QList<T>::operator[](qsizetype i) const
\overload
@@ -588,7 +636,7 @@
*/
/*!
- \fn template <typename T> void QList<T>::append(const T &value)
+ \fn template <typename T> void QList<T>::append(parameter_type value)
Inserts \a value at the end of the list.
@@ -606,7 +654,7 @@
*/
/*!
- \fn template <typename T> void QList<T>::append(T &&value)
+ \fn template <typename T> void QList<T>::append(rvalue_ref value)
\since 5.6
\overload
@@ -626,10 +674,19 @@
\sa operator<<(), operator+=()
*/
+/*! \fn template <typename T> void QList<T>::append(QList<T> &&value)
+ \overload
+
+ \since 6.0
+
+ Moves the items of the \a value list to the end of this list.
+
+ \sa operator<<(), operator+=()
+*/
/*!
- \fn template <typename T> void QList<T>::prepend(const T &value)
- \fn template <typename T> void QList<T>::prepend(T &&value)
+ \fn template <typename T> void QList<T>::prepend(parameter_type value)
+ \fn template <typename T> void QList<T>::prepend(rvalue_ref value)
Inserts \a value at the beginning of the list.
@@ -638,11 +695,12 @@
This is the same as list.insert(0, \a value).
- For large lists, this operation can be slow (\l{linear time}),
- because it requires moving all the items in the list by one
- position further in memory. If you want a container class that
- provides a fast prepend operation, use std::list
- instead.
+ Normally this operation is relatively fast (amortized \l{constant time}).
+ QList is able to allocate extra memory at the beginning of the list data
+ and grow in that direction without reallocating or moving the data on each
+ operation. However if you want a container class with a guarantee of
+ \l{constant time} prepend, use std::list instead,
+ but prefer QList otherwise.
\sa append(), insert()
*/
@@ -669,8 +727,8 @@
\sa emplace
*/
-/*! \fn template <typename T> void QList<T>::insert(int i, const T &value)
- \fn template <typename T> void QList<T>::insert(int i, T &&value)
+/*! \fn template <typename T> void QList<T>::insert(qsizetype i, parameter_type value)
+ \fn template <typename T> void QList<T>::insert(qsizetype i, rvalue_ref value)
Inserts \a value at index position \a i in the list. If \a i is
0, the value is prepended to the list. If \a i is size(), the
@@ -688,7 +746,7 @@
\sa append(), prepend(), remove()
*/
-/*! \fn template <typename T> void QList<T>::insert(int i, int count, const T &value)
+/*! \fn template <typename T> void QList<T>::insert(qsizetype i, qsizetype count, parameter_type value)
\overload
@@ -699,9 +757,8 @@
\snippet code/src_corelib_tools_qlist.cpp 10
*/
-/*!
- \fn template <typename T> QList<T>::iterator QList<T>::insert(iterator before, const T &value)
- \fn template <typename T> QList<T>::iterator QList<T>::insert(iterator before, T &&value)
+/*! \fn template <typename T> QList<T>::iterator QList<T>::insert(const_iterator before, parameter_type value)
+ \fn template <typename T> QList<T>::iterator QList<T>::insert(const_iterator before, rvalue_ref value)
\overload
@@ -709,7 +766,7 @@
\a before. Returns an iterator pointing at the inserted item.
*/
-/*! \fn template <typename T> QList<T>::iterator QList<T>::insert(iterator before, int count, const T &value)
+/*! \fn template <typename T> QList<T>::iterator QList<T>::insert(const_iterator before, qsizetype count, parameter_type value)
Inserts \a count copies of \a value in front of the item pointed to
by the iterator \a before. Returns an iterator pointing at the
@@ -717,7 +774,7 @@
*/
/*!
- \fn template <typename T> template <typename ...Args> QList<T>::iterator QList<T>::emplace(int i, Args&&... args)
+ \fn template <typename T> template <typename ...Args> QList<T>::iterator QList<T>::emplace(qsizetype i, Args&&... args)
Extends the container by inserting a new element at position \a i.
This new element is constructed in-place using \a args as the
@@ -728,7 +785,7 @@
Example:
\snippet code/src_corelib_tools_qlist.cpp emplace
- \note It is garanteed that the element will be created in place
+ \note It is guaranteed that the element will be created in place
at the beginning, but after that it might be copied or
moved to the right position.
@@ -736,7 +793,8 @@
*/
-/*! \fn template <typename T> void QList<T>::replace(int i, const T &value)
+/*! \fn template <typename T> void QList<T>::replace(qsizetype i, parameter_type value)
+ \fn template <typename T> void QList<T>::replace(qsizetype i, rvalue_ref value)
Replaces the item at index position \a i with \a value.
@@ -746,26 +804,25 @@
\sa operator[](), remove()
*/
-/*! \fn template <typename T> void QList<T>::remove(int i)
-
- \overload
-
- Removes the element at index position \a i.
-
- \sa insert(), replace(), fill()
-*/
+/*! \fn template <typename T> void QList<T>::remove(qsizetype i, qsizetype n = 1)
-/*! \fn template <typename T> void QList<T>::remove(int i, int count)
+ Removes \a n elements from the list, starting at index position \a i.
- \overload
+//! [shrinking-erase]
+ Element removal will preserve the list's capacity and not reduce the amount of
+ allocated memory. To shed extra capacity and free as much memory as possible,
+ call squeeze().
+//! [shrinking-erase]
- Removes \a count elements from the middle of the list, starting at
- index position \a i.
+//! [iterator-invalidation-erase]
+ \note When QList is not \l{implicitly shared}, this function only
+ invalidates iterators at or after the specified position.
+//! [iterator-invalidation-erase]
\sa insert(), replace(), fill()
*/
-/*! \fn template <typename T> void QList<T>::removeAt(int i)
+/*! \fn template <typename T> void QList<T>::removeAt(qsizetype i)
\since 5.2
Removes the element at index position \a i.
@@ -774,44 +831,52 @@
remove(i);
\endcode
- Provided for compatibility with QList.
+ \include qlist.qdoc shrinking-erase
+ \include qlist.qdoc iterator-invalidation-erase
- \sa remove(), QList::removeAt()
+ \sa remove()
*/
-/*! \fn template <typename T> int QList<T>::removeAll(const T &t)
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::removeAll(const AT &t)
\since 5.4
Removes all elements that compare equal to \a t from the
list. Returns the number of elements removed, if any.
- Provided for compatibility with QList.
+ \include qlist.qdoc shrinking-erase
- \sa removeOne(), QList::removeAll()
+ \sa removeOne()
*/
-/*! \fn template <typename T> bool QList<T>::removeOne(const T &t)
+/*! \fn template <typename T> template <typename AT = T> bool QList<T>::removeOne(const AT &t)
\since 5.4
Removes the first element that compares equal to \a t from the
list. Returns whether an element was, in fact, removed.
- Provided for compatibility with QList.
+ \include qlist.qdoc shrinking-erase
- \sa removeAll(), QList::removeOne()
+ \sa removeAll()
*/
-/*! \fn template <typename T> int QList<T>::length() const
+/*! \fn template <typename T> template <typename Predicate> qsizetype QList<T>::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the list. Returns the number of elements removed, if any.
+
+ \sa removeAll()
+*/
+
+/*! \fn template <typename T> qsizetype QList<T>::length() const
\since 5.2
Same as size() and count().
- Provided for compatibility with QList.
-
- \sa size(), count(), QList::length()
+ \sa size(), count()
*/
-/*! \fn template <typename T> T QList<T>::takeAt(int i)
+/*! \fn template <typename T> T QList<T>::takeAt(qsizetype i)
\since 5.2
Removes the element at index position \a i and returns it.
@@ -823,19 +888,15 @@
return t;
\endcode
- Provided for compatibility with QList.
+ \include qlist.qdoc iterator-invalidation-erase
- \sa takeFirst(), takeLast(), QList::takeAt()
+ \sa takeFirst(), takeLast()
*/
-/*! \fn template <typename T> void QList<T>::move(int from, int to)
+/*! \fn template <typename T> void QList<T>::move(qsizetype from, qsizetype to)
\since 5.6
Moves the item at index position \a from to index position \a to.
-
- Provided for compatibility with QList.
-
- \sa QList::move()
*/
/*! \fn template <typename T> void QList<T>::removeFirst()
@@ -845,6 +906,8 @@
the list can be empty, call isEmpty() before calling this
function.
+ \include qlist.qdoc shrinking-erase
+
\sa remove(), takeFirst(), isEmpty()
*/
@@ -855,6 +918,8 @@
empty. If the list can be empty, call isEmpty() before calling
this function.
+ \include qlist.qdoc shrinking-erase
+
\sa remove(), takeLast(), removeFirst(), isEmpty()
*/
@@ -882,7 +947,7 @@
*/
/*!
- \fn template <typename T> template <typename ...Args> QList<T>::iterator QList<T>::emplace(QList<T>::iterator before, Args&&... args)
+ \fn template <typename T> template <typename ...Args> QList<T>::iterator QList<T>::emplace(const_iterator before, Args&&... args)
\overload
@@ -893,11 +958,10 @@
Returns an iterator to the new element.
*/
-/*! \fn template <typename T> QList<T> &QList<T>::fill(const T &value, int size = -1)
+/*! \fn template <typename T> QList<T> &QList<T>::fill(parameter_type value, qsizetype size = -1)
Assigns \a value to all items in the list. If \a size is
- different from -1 (the default), the list is resized to size \a
- size beforehand.
+ different from -1 (the default), the list is resized to \a size beforehand.
Example:
\snippet code/src_corelib_tools_qlist.cpp 11
@@ -905,7 +969,7 @@
\sa resize()
*/
-/*! \fn template <typename T> int QList<T>::indexOf(const T &value, int from = 0) const
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::indexOf(const AT &value, qsizetype from = 0) const
Returns the index position of the first occurrence of \a value in
the list, searching forward from index position \a from.
@@ -920,7 +984,7 @@
\sa lastIndexOf(), contains()
*/
-/*! \fn template <typename T> int QList<T>::lastIndexOf(const T &value, int from = -1) const
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::lastIndexOf(const AT &value, qsizetype from = -1) const
Returns the index position of the last occurrence of the value \a
value in the list, searching backward from index position \a
@@ -936,7 +1000,7 @@
\sa indexOf()
*/
-/*! \fn template <typename T> bool QList<T>::contains(const T &value) const
+/*! \fn template <typename T> template <typename AT = T> bool QList<T>::contains(const AT &value) const
Returns \c true if the list contains an occurrence of \a value;
otherwise returns \c false.
@@ -947,7 +1011,7 @@
\sa indexOf(), count()
*/
-/*! \fn template <typename T> bool QList<T>::startsWith(const T &value) const
+/*! \fn template <typename T> bool QList<T>::startsWith(parameter_type value) const
\since 4.5
Returns \c true if this list is not empty and its first
@@ -956,7 +1020,7 @@
\sa isEmpty(), first()
*/
-/*! \fn template <typename T> bool QList<T>::endsWith(const T &value) const
+/*! \fn template <typename T> bool QList<T>::endsWith(parameter_type value) const
\since 4.5
Returns \c true if this list is not empty and its last
@@ -966,7 +1030,7 @@
*/
-/*! \fn template <typename T> int QList<T>::count(const T &value) const
+/*! \fn template <typename T> template <typename AT = T> qsizetype QList<T>::count(const AT &value) const
Returns the number of occurrences of \a value in the list.
@@ -976,7 +1040,7 @@
\sa contains(), indexOf()
*/
-/*! \fn template <typename T> int QList<T>::count() const
+/*! \fn template <typename T> qsizetype QList<T>::count() const
\overload
@@ -988,6 +1052,11 @@
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the
first item in the list.
+//! [iterator-invalidation-func-desc]
+ \warning The returned iterator is invalidated on detachment or when the
+ QList is modified.
+//! [iterator-invalidation-func-desc]
+
\sa constBegin(), end()
*/
@@ -999,24 +1068,30 @@
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::cbegin() const
\since 5.0
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first item in the list.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa begin(), cend()
*/
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::constBegin() const
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first item in the list.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa begin(), constEnd()
*/
/*! \fn template <typename T> QList<T>::iterator QList<T>::end()
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
- after the last item in the list.
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing just after
+ the last item in the list.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa begin(), constEnd()
*/
@@ -1029,16 +1104,20 @@
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::cend() const
\since 5.0
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
+ after the last item in the list.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa cbegin(), end()
*/
/*! \fn template <typename T> QList<T>::const_iterator QList<T>::constEnd() const
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the list.
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing just
+ after the last item in the list.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa constBegin(), end()
*/
@@ -1046,8 +1125,10 @@
/*! \fn template <typename T> QList<T>::reverse_iterator QList<T>::rbegin()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the list, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to
+ the first item in the list, in reverse order.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa begin(), crbegin(), rend()
*/
@@ -1060,8 +1141,10 @@
/*! \fn template <typename T> QList<T>::const_reverse_iterator QList<T>::crbegin() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the list, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to the first item in the list, in reverse order.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa begin(), rbegin(), rend()
*/
@@ -1069,8 +1152,10 @@
/*! \fn template <typename T> QList<T>::reverse_iterator QList<T>::rend()
\since 5.6
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last item in the list, in reverse order.
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing just
+ after the last item in the list, in reverse order.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa end(), crend(), rbegin()
*/
@@ -1083,28 +1168,36 @@
/*! \fn template <typename T> QList<T>::const_reverse_iterator QList<T>::crend() const
\since 5.6
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last item in the list, in reverse order.
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ just after the last item in the list, in reverse order.
+
+ \include qlist.qdoc iterator-invalidation-func-desc
\sa end(), rend(), rbegin()
*/
-/*! \fn template <typename T> QList<T>::iterator QList<T>::erase(iterator pos)
+/*! \fn template <typename T> QList<T>::iterator QList<T>::erase(const_iterator pos)
Removes the item pointed to by the iterator \a pos from the
list, and returns an iterator to the next item in the list
(which may be end()).
+ \include qlist.qdoc shrinking-erase
+ \include qlist.qdoc iterator-invalidation-erase
+
\sa insert(), remove()
*/
-/*! \fn template <typename T> QList<T>::iterator QList<T>::erase(iterator begin, iterator end)
+/*! \fn template <typename T> QList<T>::iterator QList<T>::erase(const_iterator begin, const_iterator end)
\overload
Removes all the items from \a begin up to (but not including) \a
end. Returns an iterator to the same item that \a end referred to
before the call.
+
+ \include qlist.qdoc shrinking-erase
+ \include qlist.qdoc iterator-invalidation-erase
*/
/*! \fn template <typename T> T& QList<T>::first()
@@ -1151,40 +1244,38 @@
\sa constFirst(), isEmpty(), last()
*/
-/*! \fn template <typename T> T QList<T>::value(int i) const
+/*! \fn template <typename T> T QList<T>::value(qsizetype i) const
Returns the value at index position \a i in the list.
- If the index \a i is out of bounds, the function returns
- a \l{default-constructed value}. If you are certain that
- \a i is within bounds, you can use at() instead, which is slightly
- faster.
+ If the index \a i is out of bounds, the function returns a
+ \l{default-constructed value}. If you are certain that \a i is within
+ bounds, you can use at() instead, which is slightly faster.
\sa at(), operator[]()
*/
-/*! \fn template <typename T> T QList<T>::value(int i, const T &defaultValue) const
+/*! \fn template <typename T> T QList<T>::value(qsizetype i, parameter_type defaultValue) const
\overload
- If the index \a i is out of bounds, the function returns
- \a defaultValue.
+ If the index \a i is out of bounds, the function returns \a defaultValue.
*/
-/*! \fn template <typename T> void QList<T>::push_back(const T &value)
+/*! \fn template <typename T> void QList<T>::push_back(parameter_type value)
This function is provided for STL compatibility. It is equivalent
to append(\a value).
*/
-/*! \fn template <typename T> void QList<T>::push_back(T &&value)
+/*! \fn template <typename T> void QList<T>::push_back(rvalue_ref value)
\since 5.6
\overload
*/
/*!
- \fn template <typename T> void QList<T>::push_front(const T &value)
- \fn template <typename T> void QList<T>::push_front(T &&value)
+ \fn template <typename T> void QList<T>::push_front(parameter_type value)
+ \fn template <typename T> void QList<T>::push_front(rvalue_ref value)
This function is provided for STL compatibility. It is equivalent
to prepend(\a value).
@@ -1238,6 +1329,15 @@
returns \c false.
*/
+/*! \fn template <typename T> qsizetype QList<T>::max_size()
+ \since 6.8
+
+ This function is provided for STL compatibility.
+ It returns the maximum number of elements that the list can
+ theoretically hold. In practice, the number can be much smaller,
+ limited by the amount of memory available to the system.
+*/
+
/*! \fn template <typename T> QList<T> &QList<T>::operator+=(const QList<T> &other)
Appends the items of the \a other list to this list and
@@ -1246,7 +1346,15 @@
\sa operator+(), append()
*/
-/*! \fn template <typename T> void QList<T>::operator+=(const T &value)
+/*! \fn template <typename T> QList<T> &QList<T>::operator+=(QList<T> &&other)
+ \since 6.0
+
+ \overload
+
+ \sa operator+(), append()
+*/
+
+/*! \fn template <typename T> void QList<T>::operator+=(parameter_type value)
\overload
@@ -1255,7 +1363,7 @@
\sa append(), operator<<()
*/
-/*! \fn template <typename T> void QList<T>::operator+=(T &&value)
+/*! \fn template <typename T> void QList<T>::operator+=(rvalue_ref value)
\since 5.11
\overload
@@ -1263,7 +1371,11 @@
\sa append(), operator<<()
*/
-/*! \fn template <typename T> QList<T> QList<T>::operator+(const QList<T> &other) const
+/*!
+ \fn template <typename T> QList<T> QList<T>::operator+(const QList<T> &other) const &
+ \fn template <typename T> QList<T> QList<T>::operator+(const QList<T> &other) &&
+ \fn template <typename T> QList<T> QList<T>::operator+(QList<T> &&other) const &
+ \fn template <typename T> QList<T> QList<T>::operator+(QList<T> &&other) &&
Returns a list that contains all the items in this list
followed by all the items in the \a other list.
@@ -1271,14 +1383,14 @@
\sa operator+=()
*/
-/*! \fn template <typename T> QList<T> &QList<T>::operator<<(const T &value)
+/*! \fn template <typename T> QList<T> &QList<T>::operator<<(parameter_type value)
Appends \a value to the list and returns a reference to this list.
\sa append(), operator+=()
*/
-/*! \fn template <typename T> QList<T> &QList<T>::operator<<(T &&value)
+/*! \fn template <typename T> QList<T> &QList<T>::operator<<(rvalue_ref value)
\since 5.11
\overload
@@ -1292,36 +1404,41 @@
Appends \a other to the list and returns a reference to the list.
*/
-/*! \typedef QList::iterator
+/*! \fn template <typename T> QList<T> &QList<T>::operator<<(QList<T> &&other)
+ \since 6.0
+
+ \overload
+*/
- The QList::iterator typedef provides an STL-style non-const
- iterator for QList and QStack.
+/*! \class QList::iterator
+ \inmodule QtCore
+ \brief Provides an STL-style non-const iterator for QList and QStack.
QList provides both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style non-const iterator is simply a typedef
- for "T *" (pointer to T).
+ iterators}.
+//! [iterator-invalidation-class-desc]
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
+ \warning Iterators are invalidated when QList is modified. Consider that all
+ iterators are invalidated by default. Exceptions to this rule are explicitly
+ documented.
+//! [iterator-invalidation-class-desc]
+
\sa QList::begin(), QList::end(), QList::const_iterator, QMutableListIterator
*/
-/*! \typedef QList::const_iterator
-
- The QList::const_iterator typedef provides an STL-style const
- iterator for QList and QStack.
+/*! \class QList::const_iterator
+ \inmodule QtCore
+ \brief Provides an STL-style const iterator for QList and QStack.
QList provides both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style const iterator is simply a typedef for
- "const T *" (pointer to const T).
+ iterators}.
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
+ \include qlist.qdoc iterator-invalidation-class-desc
\sa QList::constBegin(), QList::constEnd(), QList::iterator, QListIterator
*/
@@ -1332,12 +1449,7 @@
The QList::reverse_iterator typedef provides an STL-style non-const
reverse iterator for QList.
- It is simply a typedef for \c{std::reverse_iterator<T*>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
+ \include qlist.qdoc iterator-invalidation-class-desc
\sa QList::rbegin(), QList::rend(), QList::const_reverse_iterator, QList::iterator
*/
@@ -1348,12 +1460,7 @@
The QList::const_reverse_iterator typedef provides an STL-style const
reverse iterator for QList.
- It is simply a typedef for \c{std::reverse_iterator<const T*>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
+ \include qlist.qdoc iterator-invalidation-class-desc
\sa QList::rbegin(), QList::rend(), QList::reverse_iterator, QList::const_iterator
*/
@@ -1370,42 +1477,50 @@
/*! \typedef QList::const_pointer
- Typedef for const T *. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::const_reference
- Typedef for T &. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::difference_type
- Typedef for ptrdiff_t. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::pointer
- Typedef for T *. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::reference
- Typedef for T &. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::size_type
- Typedef for int. Provided for STL compatibility.
+ Provided for STL compatibility.
*/
/*! \typedef QList::value_type
- Typedef for T. Provided for STL compatibility.
+ Provided for STL compatibility.
+*/
+
+/*! \typedef QList::parameter_type
+
+*/
+
+/*! \typedef QList::rvalue_ref
+
*/
/*! \fn template <typename T> QList<T> QList<T>::toList() const
\fn template <typename T> QList<T> QList<T>::toVector() const
- \obsolete
+ \deprecated
A no-op in Qt 6. Provided for backwards compatibility with
Qt 5, where QList and QVector where two different types.
@@ -1415,56 +1530,100 @@
/*! \fn template <typename T> QList<T> QList<T>::fromList(const QList<T> &list)
\fn template <typename T> QList<T> QList<T>::fromVector(const QList<T> &list)
- \obsolete
+ \deprecated
A no-op in Qt 6. Provided for backwards compatibility with
- Qt 5, where QList and QVector where two different types.
+ Qt 5, where QList and QVector were two different types.
Returns this list.
*/
-/*! \fn template <typename T> QList<T> QList<T>::fromStdVector(const std::vector<T> &vector)
+/*! \fn template <typename T> QDataStream &operator<<(QDataStream &out, const QList<T> &list)
+ \relates QList
- Returns a QList object with the data contained in \a vector. The
- order of the elements in the QList is the same as in \a vector.
+ Writes the list \a list to stream \a out.
- Example:
+ This function requires the value type to implement \c operator<<().
- \snippet code/src_corelib_tools_qlist.cpp 16
+ \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
- \include containers-range-constructor.qdocinc
+/*! \fn template <typename T> QDataStream &operator>>(QDataStream &in, QList<T> &list)
+ \relates QList
- \sa toStdVector(), QList::fromStdList()
-*/
+ Reads a list from stream \a in into \a list.
-/*! \fn template <typename T> std::vector<T> QList<T>::toStdVector() const
+ This function requires the value type to implement \c operator>>().
- Returns a std::vector object with the data contained in this QList.
- Example:
+ \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
- \snippet code/src_corelib_tools_qlist.cpp 17
+/*! \fn template <typename T, typename AT> qsizetype erase(QList<T> &list, const AT &t)
+ \relates QList
+ \since 6.1
- \include containers-range-constructor.qdocinc
+ Removes all elements that compare equal to \a t from the
+ list \a list. Returns the number of elements removed, if any.
+
+ \note Unlike QList::removeAll, \a t is not allowed to be a
+ reference to an element inside \a list. If you cannot be sure that
+ this is not the case, take a copy of \a t and call this function
+ with the copy.
- \sa fromStdVector(), QList::toStdList()
+ \sa QList::removeAll(), erase_if
*/
-/*! \fn template <typename T> QDataStream &operator<<(QDataStream &out, const QList<T> &list)
+/*! \fn template <typename T, typename Predicate> qsizetype erase_if(QList<T> &list, Predicate pred)
\relates QList
+ \since 6.1
- Writes the list \a list to stream \a out.
+ Removes all elements for which the predicate \a pred returns true
+ from the list \a list. Returns the number of elements removed, if
+ any.
- This function requires the value type to implement \c operator<<().
+ \sa erase
+*/
- \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+/*! \fn template <typename T> QList<T>& QList<T>::assign(qsizetype n, parameter_type t)
+ \since 6.6
+
+ Replaces the contents of this list with \a n copies of \a t.
+
+ The size of this list will be equal to \a n.
+
+ This function will only allocate memory if \a n exceeds the capacity of the
+ list or this list is shared.
*/
-/*! \fn template <typename T> QDataStream &operator>>(QDataStream &in, QList<T> &list)
- \relates QList
+/*! \fn template <typename T> template <typename InputIterator, QList<T>::if_input_iterator<InputIterator>> QList<T>& QList<T>::assign(InputIterator first, InputIterator last)
+ \since 6.6
- Reads a list from stream \a in into \a list.
+ Replaces the contents of this list with a copy of the elements in the
+ iterator range [\a first, \a last).
- This function requires the value type to implement \c operator>>().
+ The size of this list will be equal to the number of elements in the
+ range [\a first, \a last).
- \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+ This function will only allocate memory if the number of elements in the
+ range exceeds the capacity of this list or this list is shared.
+
+ \note This function overload only participates in overload resolution if
+ \c InputIterator meets the requirements of a
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}.
+
+ \note The behavior is undefined if either argument is an iterator into
+ *this.
+*/
+
+/*! \fn template <typename T> QList<T>& QList<T>::assign(std::initializer_list<T> l)
+ \since 6.6
+
+ Replaces the contents of this list with a copy of the elements of
+ \a l.
+
+ The size of this list will be equal to the number of elements in
+ \a l.
+
+ This function only allocates memory if the number of elements in \a l
+ exceeds the capacity of this list or this list is shared.
*/
diff --git a/src/corelib/tools/qmakearray_p.h b/src/corelib/tools/qmakearray_p.h
index 71441c2c27..17014c23b9 100644
--- a/src/corelib/tools/qmakearray_p.h
+++ b/src/corelib/tools/qmakearray_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMAKEARRAY_P_H
#define QMAKEARRAY_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include "QtCore/qglobal.h"
+#include "QtCore/private/qglobal_p.h"
#include <array>
#include <type_traits>
@@ -61,17 +25,17 @@ QT_BEGIN_NAMESPACE
namespace QtPrivate {
template<typename T>
-constexpr T&& Forward(typename std::remove_reference<T>::type& t) noexcept
+constexpr T &&Forward(typename std::remove_reference<T>::type &t) noexcept
{
- return static_cast<T&&>(t);
+ return static_cast<T &&>(t);
}
template<typename T>
-constexpr T&& Forward(typename std::remove_reference<T>::type&& t) noexcept
+constexpr T &&Forward(typename std::remove_reference<T>::type &&t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value,
"template argument substituting T is an lvalue reference type");
- return static_cast<T&&>(t);
+ return static_cast<T &&>(t);
}
template <typename ManualType, typename ...>
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
deleted file mode 100644
index fd2136c8ef..0000000000
--- a/src/corelib/tools/qmap.cpp
+++ /dev/null
@@ -1,2132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmap.h"
-
-#include <stdlib.h>
-
-#ifdef QT_QMAP_DEBUG
-# include <qstring.h>
-# include <qlist.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-const QMapDataBase QMapDataBase::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, { 0, nullptr, nullptr }, nullptr };
-
-const QMapNodeBase *QMapNodeBase::nextNode() const
-{
- const QMapNodeBase *n = this;
- if (n->right) {
- n = n->right;
- while (n->left)
- n = n->left;
- } else {
- const QMapNodeBase *y = n->parent();
- while (y && n == y->right) {
- n = y;
- y = n->parent();
- }
- n = y;
- }
- return n;
-}
-
-const QMapNodeBase *QMapNodeBase::previousNode() const
-{
- const QMapNodeBase *n = this;
- if (n->left) {
- n = n->left;
- while (n->right)
- n = n->right;
- } else {
- const QMapNodeBase *y = n->parent();
- while (y && n == y->left) {
- n = y;
- y = n->parent();
- }
- n = y;
- }
- return n;
-}
-
-
-void QMapDataBase::rotateLeft(QMapNodeBase *x)
-{
- QMapNodeBase *&root = header.left;
- QMapNodeBase *y = x->right;
- x->right = y->left;
- if (y->left != nullptr)
- y->left->setParent(x);
- y->setParent(x->parent());
- if (x == root)
- root = y;
- else if (x == x->parent()->left)
- x->parent()->left = y;
- else
- x->parent()->right = y;
- y->left = x;
- x->setParent(y);
-}
-
-
-void QMapDataBase::rotateRight(QMapNodeBase *x)
-{
- QMapNodeBase *&root = header.left;
- QMapNodeBase *y = x->left;
- x->left = y->right;
- if (y->right != nullptr)
- y->right->setParent(x);
- y->setParent(x->parent());
- if (x == root)
- root = y;
- else if (x == x->parent()->right)
- x->parent()->right = y;
- else
- x->parent()->left = y;
- y->right = x;
- x->setParent(y);
-}
-
-
-void QMapDataBase::rebalance(QMapNodeBase *x)
-{
- QMapNodeBase *&root = header.left;
- x->setColor(QMapNodeBase::Red);
- while (x != root && x->parent()->color() == QMapNodeBase::Red) {
- if (x->parent() == x->parent()->parent()->left) {
- QMapNodeBase *y = x->parent()->parent()->right;
- if (y && y->color() == QMapNodeBase::Red) {
- x->parent()->setColor(QMapNodeBase::Black);
- y->setColor(QMapNodeBase::Black);
- x->parent()->parent()->setColor(QMapNodeBase::Red);
- x = x->parent()->parent();
- } else {
- if (x == x->parent()->right) {
- x = x->parent();
- rotateLeft(x);
- }
- x->parent()->setColor(QMapNodeBase::Black);
- x->parent()->parent()->setColor(QMapNodeBase::Red);
- rotateRight (x->parent()->parent());
- }
- } else {
- QMapNodeBase *y = x->parent()->parent()->left;
- if (y && y->color() == QMapNodeBase::Red) {
- x->parent()->setColor(QMapNodeBase::Black);
- y->setColor(QMapNodeBase::Black);
- x->parent()->parent()->setColor(QMapNodeBase::Red);
- x = x->parent()->parent();
- } else {
- if (x == x->parent()->left) {
- x = x->parent();
- rotateRight(x);
- }
- x->parent()->setColor(QMapNodeBase::Black);
- x->parent()->parent()->setColor(QMapNodeBase::Red);
- rotateLeft(x->parent()->parent());
- }
- }
- }
- root->setColor(QMapNodeBase::Black);
-}
-
-void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z)
-{
- QMapNodeBase *&root = header.left;
- QMapNodeBase *y = z;
- QMapNodeBase *x;
- QMapNodeBase *x_parent;
- if (y->left == nullptr) {
- x = y->right;
- if (y == mostLeftNode) {
- if (x)
- mostLeftNode = x; // It cannot have (left) children due the red black invariant.
- else
- mostLeftNode = y->parent();
- }
- } else {
- if (y->right == nullptr) {
- x = y->left;
- } else {
- y = y->right;
- while (y->left != nullptr)
- y = y->left;
- x = y->right;
- }
- }
- if (y != z) {
- z->left->setParent(y);
- y->left = z->left;
- if (y != z->right) {
- x_parent = y->parent();
- if (x)
- x->setParent(y->parent());
- y->parent()->left = x;
- y->right = z->right;
- z->right->setParent(y);
- } else {
- x_parent = y;
- }
- if (root == z)
- root = y;
- else if (z->parent()->left == z)
- z->parent()->left = y;
- else
- z->parent()->right = y;
- y->setParent(z->parent());
- // Swap the colors
- QMapNodeBase::Color c = y->color();
- y->setColor(z->color());
- z->setColor(c);
- y = z;
- } else {
- x_parent = y->parent();
- if (x)
- x->setParent(y->parent());
- if (root == z)
- root = x;
- else if (z->parent()->left == z)
- z->parent()->left = x;
- else
- z->parent()->right = x;
- }
- if (y->color() != QMapNodeBase::Red) {
- while (x != root && (x == nullptr || x->color() == QMapNodeBase::Black)) {
- if (x == x_parent->left) {
- QMapNodeBase *w = x_parent->right;
- if (w->color() == QMapNodeBase::Red) {
- w->setColor(QMapNodeBase::Black);
- x_parent->setColor(QMapNodeBase::Red);
- rotateLeft(x_parent);
- w = x_parent->right;
- }
- if ((w->left == nullptr || w->left->color() == QMapNodeBase::Black) &&
- (w->right == nullptr || w->right->color() == QMapNodeBase::Black)) {
- w->setColor(QMapNodeBase::Red);
- x = x_parent;
- x_parent = x_parent->parent();
- } else {
- if (w->right == nullptr || w->right->color() == QMapNodeBase::Black) {
- if (w->left)
- w->left->setColor(QMapNodeBase::Black);
- w->setColor(QMapNodeBase::Red);
- rotateRight(w);
- w = x_parent->right;
- }
- w->setColor(x_parent->color());
- x_parent->setColor(QMapNodeBase::Black);
- if (w->right)
- w->right->setColor(QMapNodeBase::Black);
- rotateLeft(x_parent);
- break;
- }
- } else {
- QMapNodeBase *w = x_parent->left;
- if (w->color() == QMapNodeBase::Red) {
- w->setColor(QMapNodeBase::Black);
- x_parent->setColor(QMapNodeBase::Red);
- rotateRight(x_parent);
- w = x_parent->left;
- }
- if ((w->right == nullptr || w->right->color() == QMapNodeBase::Black) &&
- (w->left == nullptr|| w->left->color() == QMapNodeBase::Black)) {
- w->setColor(QMapNodeBase::Red);
- x = x_parent;
- x_parent = x_parent->parent();
- } else {
- if (w->left == nullptr || w->left->color() == QMapNodeBase::Black) {
- if (w->right)
- w->right->setColor(QMapNodeBase::Black);
- w->setColor(QMapNodeBase::Red);
- rotateLeft(w);
- w = x_parent->left;
- }
- w->setColor(x_parent->color());
- x_parent->setColor(QMapNodeBase::Black);
- if (w->left)
- w->left->setColor(QMapNodeBase::Black);
- rotateRight(x_parent);
- break;
- }
- }
- }
- if (x)
- x->setColor(QMapNodeBase::Black);
- }
- free(y);
- --size;
-}
-
-void QMapDataBase::recalcMostLeftNode()
-{
- mostLeftNode = &header;
- while (mostLeftNode->left)
- mostLeftNode = mostLeftNode->left;
-}
-
-static inline size_t qMapAlignmentThreshold()
-{
- // malloc on 32-bit platforms should return pointers that are 8-byte
- // aligned or more while on 64-bit platforms they should be 16-byte aligned
- // or more
- return 2 * sizeof(void*);
-}
-
-static inline void *qMapAllocate(size_t alloc, size_t alignment)
-{
- return alignment > qMapAlignmentThreshold()
- ? qMallocAligned(alloc, alignment)
- : ::malloc(alloc);
-}
-
-static inline void qMapDeallocate(QMapNodeBase *node, size_t alignment)
-{
- if (alignment > qMapAlignmentThreshold())
- qFreeAligned(node);
- else
- ::free(node);
-}
-
-QMapNodeBase *QMapDataBase::createNode(size_t alloc, size_t alignment, QMapNodeBase *parent, bool left)
-{
- QMapNodeBase *node = static_cast<QMapNodeBase *>(qMapAllocate(alloc, alignment));
- Q_CHECK_PTR(node);
-
- memset(node, 0, alloc);
- ++size;
-
- if (parent) {
- if (left) {
- parent->left = node;
- if (parent == mostLeftNode)
- mostLeftNode = node;
- } else {
- parent->right = node;
- }
- node->setParent(parent);
- rebalance(node);
- }
- return node;
-}
-
-void QMapDataBase::freeTree(QMapNodeBase *root, size_t alignment)
-{
- if (root->left)
- freeTree(root->left, alignment);
- if (root->right)
- freeTree(root->right, alignment);
- qMapDeallocate(root, alignment);
-}
-
-QMapDataBase *QMapDataBase::createData()
-{
- QMapDataBase *d = new QMapDataBase;
-
- d->ref.initializeOwned();
- d->size = 0;
-
- d->header.p = 0;
- d->header.left = nullptr;
- d->header.right = nullptr;
- d->mostLeftNode = &(d->header);
-
- return d;
-}
-
-void QMapDataBase::freeData(QMapDataBase *d)
-{
- delete d;
-}
-
-/*!
- \class QMap
- \inmodule QtCore
- \brief The QMap class is a template class that provides a red-black-tree-based dictionary.
-
- \ingroup tools
- \ingroup shared
-
- \reentrant
-
- QMap\<Key, T\> is one of Qt's generic \l{container classes}. It
- stores (key, value) pairs and provides fast lookup of the
- value associated with a key.
-
- QMap and QHash provide very similar functionality. The
- differences are:
-
- \list
- \li QHash provides average faster lookups than QMap. (See \l{Algorithmic
- Complexity} for details.)
- \li When iterating over a QHash, the items are arbitrarily ordered.
- With QMap, the items are always sorted by key.
- \li The key type of a QHash must provide operator==() and a global
- qHash(Key) function. The key type of a QMap must provide
- operator<() specifying a total order. Since Qt 5.8.1 it is also safe
- to use a pointer type as key, even if the underlying operator<()
- does not provide a total order.
- \endlist
-
- Here's an example QMap with QString keys and \c int values:
- \snippet code/src_corelib_tools_qmap.cpp 0
-
- To insert a (key, value) pair into the map, you can use operator[]():
-
- \snippet code/src_corelib_tools_qmap.cpp 1
-
- This inserts the following three (key, value) pairs into the
- QMap: ("one", 1), ("three", 3), and ("seven", 7). Another way to
- insert items into the map is to use insert():
-
- \snippet code/src_corelib_tools_qmap.cpp 2
-
- To look up a value, use operator[]() or value():
-
- \snippet code/src_corelib_tools_qmap.cpp 3
-
- If there is no item with the specified key in the map, these
- functions return a \l{default-constructed value}.
-
- If you want to check whether the map contains a certain key, use
- contains():
-
- \snippet code/src_corelib_tools_qmap.cpp 4
-
- There is also a value() overload that uses its second argument as
- a default value if there is no item with the specified key:
-
- \snippet code/src_corelib_tools_qmap.cpp 5
-
- In general, we recommend that you use contains() and value()
- rather than operator[]() for looking up a key in a map. The
- reason is that operator[]() silently inserts an item into the
- map if no item exists with the same key (unless the map is
- const). For example, the following code snippet will create 1000
- items in memory:
-
- \snippet code/src_corelib_tools_qmap.cpp 6
-
- To avoid this problem, replace \c map[i] with \c map.value(i)
- in the code above.
-
- If you want to navigate through all the (key, value) pairs stored
- in a QMap, you can use an iterator. QMap provides both
- \l{Java-style iterators} (QMapIterator and QMutableMapIterator)
- and \l{STL-style iterators} (QMap::const_iterator and
- QMap::iterator). Here's how to iterate over a QMap<QString, int>
- using a Java-style iterator:
-
- \snippet code/src_corelib_tools_qmap.cpp 7
-
- Here's the same code, but using an STL-style iterator this time:
-
- \snippet code/src_corelib_tools_qmap.cpp 8
-
- The items are traversed in ascending key order.
-
- Normally, a QMap allows only one value per key. If you call
- insert() with a key that already exists in the QMap, the
- previous value will be erased. For example:
-
- \snippet code/src_corelib_tools_qmap.cpp 9
-
- However, you can store multiple values per key by using
- using the subclass QMultiMap. If you want
- to retrieve all the values for a single key, you can use
- values(const Key &key), which returns a QList<T>:
-
- \snippet code/src_corelib_tools_qmap.cpp 10
-
- The items that share the same key are available from most
- recently to least recently inserted. Another approach is to call
- find() to get the STL-style iterator for the first item with a
- key and iterate from there:
-
- \snippet code/src_corelib_tools_qmap.cpp 11
-
- If you only need to extract the values from a map (not the keys),
- you can also use \l{foreach}:
-
- \snippet code/src_corelib_tools_qmap.cpp 12
-
- Items can be removed from the map in several ways. One way is to
- call remove(); this will remove any item with the given key.
- Another way is to use QMutableMapIterator::remove(). In addition,
- you can clear the entire map using clear().
-
- QMap's key and value data types must be \l{assignable data
- types}. This covers most data types you are likely to encounter,
- but the compiler won't let you, for example, store a QWidget as a
- value; instead, store a QWidget *. In addition, QMap's key type
- must provide operator<(). QMap uses it to keep its items sorted,
- and assumes that two keys \c x and \c y are equal if neither \c{x
- < y} nor \c{y < x} is true.
-
- Example:
- \snippet code/src_corelib_tools_qmap.cpp 13
-
- In the example, we start by comparing the employees' names. If
- they're equal, we compare their dates of birth to break the tie.
-
- \sa QMapIterator, QMutableMapIterator, QHash, QSet
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::QMap()
-
- Constructs an empty map.
-
- \sa clear()
-*/
-
-/*!
- \fn template <class Key, class T> QMap<Key, T>::QMap(QMap<Key, T> &&other)
-
- Move-constructs a QMap instance, making it point at the same
- object that \a other was pointing to.
-
- \since 5.2
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::QMap(const QMap<Key, T> &other)
-
- Constructs a copy of \a other.
-
- This operation occurs in \l{constant time}, because QMap is
- \l{implicitly shared}. This makes returning a QMap from a
- function very fast. If a shared instance is modified, it will be
- copied (copy-on-write), and this takes \l{linear time}.
-
- \sa operator=()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::QMap(const typename std::map<Key, T> & other)
-
- Constructs a copy of \a other.
-
- \sa toStdMap()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::QMap(std::initializer_list<std::pair<Key,T> > list)
- \since 5.1
-
- Constructs a map with a copy of each of the elements in the
- initializer list \a list.
-
- This function is only available if the program is being
- compiled in C++11 mode.
-*/
-
-/*! \fn template <class Key, class T> std::map<Key, T> QMap<Key, T>::toStdMap() const
-
- Returns an STL map equivalent to this QMap.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::~QMap()
-
- Destroys the map. References to the values in the map, and all
- iterators over this map, become invalid.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other)
-
- Assigns \a other to this map and returns a reference to this map.
-*/
-
-/*!
- \fn template <class Key, class T> QMap<Key, T> &QMap<Key, T>::operator=(QMap<Key, T> &&other)
-
- Move-assigns \a other to this QMap instance.
-
- \since 5.2
-*/
-
-/*! \fn template <class Key, class T> void QMap<Key, T>::swap(QMap<Key, T> &other)
- \since 4.8
-
- Swaps map \a other with this map. This operation is very
- fast and never fails.
-*/
-
-/*! \fn template <class Key, class T> void QMultiMap<Key, T>::swap(QMultiMap<Key, T> &other)
- \since 4.8
-
- Swaps map \a other with this map. This operation is very
- fast and never fails.
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::operator==(const QMap<Key, T> &other) const
-
- Returns \c true if \a other is equal to this map; otherwise returns
- false.
-
- Two maps are considered equal if they contain the same (key,
- value) pairs.
-
- This function requires the value type to implement \c
- operator==().
-
- \sa operator!=()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::operator!=(const QMap<Key, T> &other) const
-
- Returns \c true if \a other is not equal to this map; otherwise
- returns \c false.
-
- Two maps are considered equal if they contain the same (key,
- value) pairs.
-
- This function requires the value type to implement \c
- operator==().
-
- \sa operator==()
-*/
-
-/*! \fn template <class Key, class T> qsizetype QMap<Key, T>::size() const
-
- Returns the number of (key, value) pairs in the map.
-
- \sa isEmpty(), count()
-*/
-
-/*!
- \fn template <class Key, class T> bool QMap<Key, T>::isEmpty() const
-
- Returns \c true if the map contains no items; otherwise returns
- false.
-
- \sa size()
-*/
-
-/*! \fn template <class Key, class T> void QMap<Key, T>::detach()
-
- \internal
-
- Detaches this map from any other maps with which it may share
- data.
-
- \sa isDetached()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::isDetached() const
-
- \internal
-
- Returns \c true if the map's internal data isn't shared with any
- other map object; otherwise returns \c false.
-
- \sa detach()
-*/
-
-/*! \fn template <class Key, class T> void QMap<Key, T>::setSharable(bool sharable)
-
- \internal
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::isSharedWith(const QMap<Key, T> &other) const
-
- \internal
-*/
-
-/*! \fn template <class Key, class T> void QMap<Key, T>::clear()
-
- Removes all items from the map.
-
- \sa remove()
-*/
-
-/*! \fn template <class Key, class T> qsizetype QMap<Key, T>::remove(const Key &key)
-
- Removes all the items that have the key \a key from the map.
- Returns the number of items removed which will be 1 if the key
- exists in the map, and 0 otherwise.
-
- \sa clear(), take(), QMultiMap::remove()
-*/
-
-/*! \fn template <class Key, class T> T QMap<Key, T>::take(const Key &key)
-
- Removes the item with the key \a key from the map and returns
- the value associated with it.
-
- If the item does not exist in the map, the function simply
- returns a \l{default-constructed value}. If there are multiple
- items for \a key in the map, only the most recently inserted one
- is removed and returned.
-
- If you don't use the return value, remove() is more efficient.
-
- \sa remove()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::contains(const Key &key) const
-
- Returns \c true if the map contains an item with key \a key;
- otherwise returns \c false.
-
- \sa count(), QMultiMap::contains()
-*/
-
-/*! \fn template <class Key, class T> T QMap<Key, T>::value(const Key &key, const T &defaultValue) const
-
- Returns the value associated with the key \a key.
-
- If the map contains no item with key \a key, the function returns
- \a defaultValue. If no \a defaultValue is specified, the function
- returns a \l{default-constructed value}. If there are multiple
- items for \a key in the map, the value of the most recently
- inserted one is returned.
-
- \sa key(), values(), contains(), operator[]()
-*/
-
-/*! \fn template <class Key, class T> T &QMap<Key, T>::operator[](const Key &key)
-
- Returns the value associated with the key \a key as a modifiable
- reference.
-
- If the map contains no item with key \a key, the function inserts
- a \l{default-constructed value} into the map with key \a key, and
- returns a reference to it. If the map contains multiple items
- with key \a key, this function returns a reference to the most
- recently inserted value.
-
- \sa insert(), value()
-*/
-
-/*! \fn template <class Key, class T> const T QMap<Key, T>::operator[](const Key &key) const
-
- \overload
-
- Same as value().
-*/
-
-/*! \fn template <class Key, class T> QList<Key> QMap<Key, T>::uniqueKeys() const
- \since 4.2
- \obsolete Use QMultiMap for storing multiple values with the same key.
-
- Returns a list containing all the keys in the map in ascending
- order. Keys that occur multiple times in the map (because items
- were inserted with insertMulti(), or unite() was used) occur only
- once in the returned list.
-
- \sa QMultiMap::uniqueKeys()
-*/
-
-/*! \fn template <class Key, class T> QList<Key> QMap<Key, T>::keys() const
-
- Returns a list containing all the keys in the map in ascending
- order. Keys that occur multiple times in the map (because the
- method is operating on a QMultiMap) also occur multiple times
- in the list.
-
- The order is guaranteed to be the same as that used by values().
-
- \sa QMultiMap::uniqueKeys(), values(), key()
-*/
-
-/*! \fn template <class Key, class T> QList<Key> QMap<Key, T>::keys(const T &value) const
-
- \overload
-
- Returns a list containing all the keys associated with value \a
- value in ascending order.
-
- This function can be slow (\l{linear time}), because QMap's
- internal data structure is optimized for fast lookup by key, not
- by value.
-*/
-
-/*!
- \fn template <class Key, class T> Key QMap<Key, T>::key(const T &value, const Key &defaultKey) const
- \since 4.3
- \overload
-
- Returns the first key with value \a value, or \a defaultKey if
- the map contains no item with value \a value. If no \a defaultKey
- is provided the function returns a
- \l{default-constructed value}{default-constructed key}.
-
- This function can be slow (\l{linear time}), because QMap's
- internal data structure is optimized for fast lookup by key, not
- by value.
-
- \sa value(), keys()
-*/
-
-/*! \fn template <class Key, class T> QList<T> QMap<Key, T>::values() const
-
- Returns a list containing all the values in the map, in ascending
- order of their keys. If a key is associated with multiple values,
- all of its values will be in the list, and not just the most
- recently inserted one.
-
- \sa keys(), value()
-*/
-
-/*! \fn template <class Key, class T> QList<T> QMap<Key, T>::values(const Key &key) const
- \overload
- \obsolete Use QMultiMap for maps storing multiple values with the same key.
-
- Returns a list containing all the values associated with key
- \a key, from the most recently inserted to the least recently
- inserted one.
-
- \sa QMultiMap::values()
-*/
-
-/*! \fn template <class Key, class T> qsizetype QMap<Key, T>::count(const Key &key) const
-
- Returns the number of items associated with key \a key.
-
- \sa contains(), QMultiMap::count()
-*/
-
-/*! \fn template <class Key, class T> qsizetype QMap<Key, T>::count() const
-
- \overload
-
- Same as size().
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::begin()
-
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
- the map.
-
- \sa constBegin(), end()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::begin() const
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::cbegin() const
- \since 5.0
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the map.
-
- \sa begin(), cend()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::constBegin() const
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
- in the map.
-
- \sa begin(), constEnd()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::keyBegin() const
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key
- in the map.
-
- \sa keyEnd(), firstKey()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::end()
-
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
- after the last item in the map.
-
- \sa begin(), constEnd()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::end() const
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::cend() const
- \since 5.0
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the map.
-
- \sa cbegin(), end()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::constEnd() const
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last item in the map.
-
- \sa constBegin(), end()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::keyEnd() const
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- item after the last key in the map.
-
- \sa keyBegin(), lastKey()
-*/
-
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_value_iterator QMap<Key, T>::keyValueBegin()
- \since 5.10
-
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
- in the map.
-
- \sa keyValueEnd()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_value_iterator QMap<Key, T>::keyValueEnd()
- \since 5.10
-
- Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- entry after the last entry in the map.
-
- \sa keyValueBegin()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::keyValueBegin() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
- in the map.
-
- \sa keyValueEnd()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::constKeyValueBegin() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
- in the map.
-
- \sa keyValueBegin()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::keyValueEnd() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- entry after the last entry in the map.
-
- \sa keyValueBegin()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::constKeyValueEnd() const
- \since 5.10
-
- Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
- entry after the last entry in the map.
-
- \sa constKeyValueBegin()
-*/
-
-/*! \fn template <class Key, class T> const Key &QMap<Key, T>::firstKey() const
- \since 5.2
-
- Returns a reference to the smallest key in the map.
- This function assumes that the map is not empty.
-
- This executes in \l{constant time}.
-
- \sa lastKey(), first(), keyBegin(), isEmpty()
-*/
-
-/*! \fn template <class Key, class T> const Key &QMap<Key, T>::lastKey() const
- \since 5.2
-
- Returns a reference to the largest key in the map.
- This function assumes that the map is not empty.
-
- This executes in \l{logarithmic time}.
-
- \sa firstKey(), last(), keyEnd(), isEmpty()
-*/
-
-/*! \fn template <class Key, class T> T &QMap<Key, T>::first()
- \since 5.2
-
- Returns a reference to the first value in the map, that is the value mapped
- to the smallest key. This function assumes that the map is not empty.
-
- When unshared (or const version is called), this executes in \l{constant time}.
-
- \sa last(), firstKey(), isEmpty()
-*/
-
-/*! \fn template <class Key, class T> const T &QMap<Key, T>::first() const
- \since 5.2
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> T &QMap<Key, T>::last()
- \since 5.2
-
- Returns a reference to the last value in the map, that is the value mapped
- to the largest key. This function assumes that the map is not empty.
-
- When unshared (or const version is called), this executes in \l{logarithmic time}.
-
- \sa first(), lastKey(), isEmpty()
-*/
-
-/*! \fn template <class Key, class T> const T &QMap<Key, T>::last() const
- \since 5.2
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::erase(iterator pos)
-
- Removes the (key, value) pair pointed to by the iterator \a pos
- from the map, and returns an iterator to the next item in the
- map.
-
- \sa remove()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::find(const Key &key)
-
- Returns an iterator pointing to the item with key \a key in the
- map.
-
- If the map contains no item with key \a key, the function
- returns end().
-
- If the map contains multiple items with key \a key, this
- function returns an iterator that points to the most recently
- inserted value. The other values are accessible by incrementing
- the iterator. For example, here's some code that iterates over all
- the items with the same key:
-
- \snippet code/src_corelib_tools_qmap.cpp 14
-
- \sa constFind(), value(), values(), lowerBound(), upperBound(), QMultiMap::find()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &key) const
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &key) const
- \since 4.1
-
- Returns an const iterator pointing to the item with key \a key in the
- map.
-
- If the map contains no item with key \a key, the function
- returns constEnd().
-
- \sa find(), QMultiMap::constFind()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &key)
-
- Returns an iterator pointing to the first item with key \a key in
- the map. If the map contains no item with key \a key, the
- function returns an iterator to the nearest item with a greater
- key.
-
- Example:
- \snippet code/src_corelib_tools_qmap.cpp 15
-
- If the map contains multiple items with key \a key, this
- function returns an iterator that points to the most recently
- inserted value. The other values are accessible by incrementing
- the iterator. For example, here's some code that iterates over all
- the items with the same key:
-
- \snippet code/src_corelib_tools_qmap.cpp 16
-
- \sa upperBound(), find()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::lowerBound(const Key &key) const
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &key)
-
- Returns an iterator pointing to the item that immediately follows
- the last item with key \a key in the map. If the map contains no
- item with key \a key, the function returns an iterator to the
- nearest item with a greater key.
-
- Example:
- \snippet code/src_corelib_tools_qmap.cpp 17
-
- \sa lowerBound(), find()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::upperBound(const Key &key) const
-
- \overload
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &key, const T &value)
-
- Inserts a new item with the key \a key and a value of \a value.
-
- If there is already an item with the key \a key, that item's value
- is replaced with \a value.
-
- If there are multiple items with the key \a key, the most
- recently inserted item's value is replaced with \a value.
-
- \sa QMultiMap::insert()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const Key &key, const T &value)
- \overload
- \since 5.1
- Inserts a new item with the key \a key and value \a value and with hint \a pos
- suggesting where to do the insert.
-
- If constBegin() is used as hint it indicates that the \a key is less than any key in the map
- while constEnd() suggests that the \a key is (strictly) larger than any key in the map.
- Otherwise the hint should meet the condition (\a pos - 1).key() < \a key <= pos.key().
- If the hint \a pos is wrong it is ignored and a regular insert is done.
-
- If there is already an item with the key \a key, that item's value
- is replaced with \a value.
-
- If there are multiple items with the key \a key, then exactly one of them
- is replaced with \a value.
-
- If the hint is correct and the map is unshared, the insert executes in amortized \l{constant time}.
-
- When creating a map from sorted data inserting the largest key first with constBegin()
- is faster than inserting in sorted order with constEnd(), since constEnd() - 1 (which is needed
- to check if the hint is valid) needs \l{logarithmic time}.
-
- \b {Note:} Be careful with the hint. Providing an iterator from an older shared instance might
- crash but there is also a risk that it will silently corrupt both the map and the \a pos map.
-
- \sa QMultiMap::insert()
-*/
-
-/*! \fn template <class Key, class T> void QMap<Key, T>::insert(const QMap<Key, T> &map)
- \since 5.15
-
- Inserts all the items in \a map into this map.
-
- If a key is common to both maps, its value will be replaced with
- the value stored in \a map.
-
- \note If \a map contains multiple entries with the same key then the
- final value of the key is undefined.
-
- \sa QMultiMap::insert()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
- \obsolete Use QMultiMap for storing multiple values with the same key.
-
- Inserts a new item with the key \a key and a value of \a value.
-
- If there is already an item with the same key in the map, this
- function will simply create a new one. (This behavior is
- different from insert(), which overwrites the value of an
- existing item.)
-
- \sa QMultiMap::insert()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const_iterator pos, const Key &key, const T &value)
- \overload
- \since 5.1
- \obsolete Use QMultiMap for storing multiple values with the same key.
- Inserts a new item with the key \a key and value \a value and with hint \a pos
- suggesting where to do the insert.
-
- If constBegin() is used as hint it indicates that the \a key is less than any key in the map
- while constEnd() suggests that the \a key is larger than any key in the map.
- Otherwise the hint should meet the condition (\a pos - 1).key() < \a key <= pos.key().
- If the hint \a pos is wrong it is ignored and a regular insertMulti is done.
-
- If there is already an item with the same key in the map, this function will simply create a new one.
-
- \b {Note:} Be careful with the hint. Providing an iterator from an older shared instance might
- crash but there is also a risk that it will silently corrupt both the map and the \a pos map.
-
- \sa QMultiMap::insert()
-*/
-
-
-/*! \fn template <class Key, class T> QMap<Key, T> &QMap<Key, T>::unite(const QMap<Key, T> &other)
- \obsolete Use QMultiMap for storing multiple values with the same key.
-
- Inserts all the items in the \a other map into this map. If a
- key is common to both maps, the resulting map will contain the
- key multiple times.
-
- \sa QMultiMap::unite()
-*/
-
-/*! \typedef QMap::Iterator
-
- Qt-style synonym for QMap<Key, T>::iterator.
-*/
-
-/*! \typedef QMap::ConstIterator
-
- Qt-style synonym for QMap<Key, T>::const_iterator.
-*/
-
-/*! \typedef QMap::difference_type
-
- Typedef for ptrdiff_t. Provided for STL compatibility.
-*/
-
-/*! \typedef QMap::key_type
-
- Typedef for Key. Provided for STL compatibility.
-*/
-
-/*! \typedef QMap::mapped_type
-
- Typedef for T. Provided for STL compatibility.
-*/
-
-/*! \typedef QMap::size_type
-
- Typedef for int. Provided for STL compatibility.
-*/
-
-/*!
- \fn template <class Key, class T> bool QMap<Key, T>::empty() const
-
- This function is provided for STL compatibility. It is equivalent
- to isEmpty(), returning true if the map is empty; otherwise
- returning false.
-*/
-
-/*!
- \fn template <class Key, class T> QPair<typename QMap<Key, T>::iterator, typename QMap<Key, T>::iterator> QMap<Key, T>::equal_range(const Key &key)
-
- Returns a pair of iterators delimiting the range of values \c{[first, second)}, that
- are stored under \a key.
-*/
-
-/*!
- \fn template <class Key, class T> QPair<typename QMap<Key, T>::const_iterator, typename QMap<Key, T>::const_iterator> QMap<Key, T>::equal_range(const Key &key) const
- \overload
- \since 5.6
-*/
-
-
-/*! \class QMap::iterator
- \inmodule QtCore
- \brief The QMap::iterator class provides an STL-style non-const iterator for QMap and QMultiMap.
-
- QMap features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
- QMap\<Key, T\>::iterator allows you to iterate over a QMap (or
- QMultiMap) and to modify the value (but not the key) stored under
- a particular key. If you want to iterate over a const QMap, you
- should use QMap::const_iterator. It is generally good practice to
- use QMap::const_iterator on a non-const QMap as well, unless you
- need to change the QMap through the iterator. Const iterators are
- slightly faster, and can improve code readability.
-
- The default QMap::iterator constructor creates an uninitialized
- iterator. You must initialize it using a QMap function like
- QMap::begin(), QMap::end(), or QMap::find() before you can
- start iterating. Here's a typical loop that prints all the (key,
- value) pairs stored in a map:
-
- \snippet code/src_corelib_tools_qmap.cpp 18
-
- Unlike QHash, which stores its items in an arbitrary order, QMap
- stores its items ordered by key. Items that share the same key
- (because the map is a QMultiMap) will appear consecutively,
- from the most recently to the least recently inserted value.
-
- Let's see a few examples of things we can do with a
- QMap::iterator that we cannot do with a QMap::const_iterator.
- Here's an example that increments every value stored in the QMap
- by 2:
-
- \snippet code/src_corelib_tools_qmap.cpp 19
-
- Here's an example that removes all the items whose key is a
- string that starts with an underscore character:
-
- \snippet code/src_corelib_tools_qmap.cpp 20
-
- The call to QMap::erase() removes the item pointed to by the
- iterator from the map, and returns an iterator to the next item.
- Here's another way of removing an item while iterating:
-
- \snippet code/src_corelib_tools_qmap.cpp 21
-
- It might be tempting to write code like this:
-
- \snippet code/src_corelib_tools_qmap.cpp 22
-
- However, this will potentially crash in \c{++i}, because \c i is
- a dangling iterator after the call to erase().
-
- Multiple iterators can be used on the same map. If you add items
- to the map, existing iterators will remain valid. If you remove
- items from the map, iterators that point to the removed items
- will become dangling iterators.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QMap::const_iterator, QMap::key_iterator, QMutableMapIterator
-*/
-
-/*! \typedef QMap::iterator::difference_type
-
- \internal
-*/
-
-/*! \typedef QMap::iterator::iterator_category
-
- A synonym for \e {std::bidirectional_iterator_tag} indicating
- this iterator is a bidirectional iterator.
-*/
-
-/*! \typedef QMap::iterator::pointer
-
- \internal
-*/
-
-/*! \typedef QMap::iterator::reference
-
- \internal
-*/
-
-/*! \typedef QMap::iterator::value_type
-
- \internal
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator::iterator()
-
- Constructs an uninitialized iterator.
-
- Functions like key(), value(), and operator++() must not be
- called on an uninitialized iterator. Use operator=() to assign a
- value to it before using it.
-
- \sa QMap::begin(), QMap::end()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator::iterator(Node *)
-
- \internal
-*/
-
-/*! \fn template <class Key, class T> const Key &QMap<Key, T>::iterator::key() const
-
- Returns the current item's key as a const reference.
-
- There is no direct way of changing an item's key through an
- iterator, although it can be done by calling QMap::erase()
- followed by QMap::insert() or QMap::insertMulti().
-
- \sa value()
-*/
-
-/*! \fn template <class Key, class T> T &QMap<Key, T>::iterator::value() const
-
- Returns a modifiable reference to the current item's value.
-
- You can change the value of an item by using value() on
- the left side of an assignment, for example:
-
- \snippet code/src_corelib_tools_qmap.cpp 23
-
- \sa key(), operator*()
-*/
-
-/*! \fn template <class Key, class T> T &QMap<Key, T>::iterator::operator*() const
-
- Returns a modifiable reference to the current item's value.
-
- Same as value().
-
- \sa key()
-*/
-
-/*! \fn template <class Key, class T> T *QMap<Key, T>::iterator::operator->() const
-
- Returns a pointer to the current item's value.
-
- \sa value()
-*/
-
-/*!
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator==(const iterator &other) const
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator==(const const_iterator &other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*!
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator!=(const iterator &other) const
- \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator!=(const const_iterator &other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator++()
-
- The prefix ++ operator (\c{++i}) advances the iterator to the
- next item in the map and returns an iterator to the new current
- item.
-
- Calling this function on QMap::end() leads to undefined results.
-
- \sa operator--()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator++(int)
-
- \overload
-
- The postfix ++ operator (\c{i++}) advances the iterator to the
- next item in the map and returns an iterator to the previously
- current item.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator--()
-
- The prefix -- operator (\c{--i}) makes the preceding item
- current and returns an iterator pointing to the new current item.
-
- Calling this function on QMap::begin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator--(int)
-
- \overload
-
- The postfix -- operator (\c{i--}) makes the preceding item
- current and returns an iterator pointing to the previously
- current item.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator+(qsizetype j) const
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-()
-
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator-(qsizetype j) const
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator &QMap<Key, T>::iterator::operator+=(qsizetype j)
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- \sa operator-=(), operator+()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::iterator &QMap<Key, T>::iterator::operator-=(qsizetype j)
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- \sa operator+=(), operator-()
-*/
-
-/*! \class QMap::const_iterator
- \inmodule QtCore
- \brief The QMap::const_iterator class provides an STL-style const iterator for QMap and QMultiMap.
-
- QMap features both \l{STL-style iterators} and \l{Java-style
- iterators}. The STL-style iterators are more low-level and more
- cumbersome to use; on the other hand, they are slightly faster
- and, for developers who already know STL, have the advantage of
- familiarity.
-
- QMap\<Key, T\>::const_iterator allows you to iterate over a QMap
- (or a QMultiMap). If you want to modify the QMap as you iterate
- over it, you must use QMap::iterator instead. It is generally
- good practice to use QMap::const_iterator on a non-const QMap as
- well, unless you need to change the QMap through the iterator.
- Const iterators are slightly faster, and can improve code
- readability.
-
- The default QMap::const_iterator constructor creates an
- uninitialized iterator. You must initialize it using a QMap
- function like QMap::constBegin(), QMap::constEnd(), or
- QMap::find() before you can start iterating. Here's a typical
- loop that prints all the (key, value) pairs stored in a map:
-
- \snippet code/src_corelib_tools_qmap.cpp 24
-
- Unlike QHash, which stores its items in an arbitrary order, QMap
- stores its items ordered by key. Items that share the same key
- (because the map is a QMultiMap) will appear consecutively,
- from the most recently to the least recently inserted value.
-
- Multiple iterators can be used on the same map. If you add items
- to the map, existing iterators will remain valid. If you remove
- items from the map, iterators that point to the removed items
- will become dangling iterators.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QMap::iterator, QMap::key_iterator, QMapIterator
-*/
-
-/*! \typedef QMap::const_iterator::difference_type
-
- \internal
-*/
-
-/*! \typedef QMap::const_iterator::iterator_category
-
- A synonym for \e {std::bidirectional_iterator_tag} indicating
- this iterator is a bidirectional iterator.
-*/
-
-/*! \typedef QMap::const_iterator::pointer
-
- \internal
-*/
-
-/*! \typedef QMap::const_iterator::reference
-
- \internal
-*/
-
-/*! \typedef QMap::const_iterator::value_type
-
- \internal
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator::const_iterator()
-
- Constructs an uninitialized iterator.
-
- Functions like key(), value(), and operator++() must not be
- called on an uninitialized iterator. Use operator=() to assign a
- value to it before using it.
-
- \sa QMap::constBegin(), QMap::constEnd()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator::const_iterator(const Node *)
-
- \internal
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator::const_iterator(const iterator &other)
-
- Constructs a copy of \a other.
-*/
-
-/*! \fn template <class Key, class T> const Key &QMap<Key, T>::const_iterator::key() const
-
- Returns the current item's key.
-
- \sa value()
-*/
-
-/*! \fn template <class Key, class T> const T &QMap<Key, T>::const_iterator::value() const
-
- Returns the current item's value.
-
- \sa key(), operator*()
-*/
-
-/*! \fn template <class Key, class T> const T &QMap<Key, T>::const_iterator::operator*() const
-
- Returns the current item's value.
-
- Same as value().
-
- \sa key()
-*/
-
-/*! \fn template <class Key, class T> const T *QMap<Key, T>::const_iterator::operator->() const
-
- Returns a pointer to the current item's value.
-
- \sa value()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator==(const const_iterator &other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator!=(const const_iterator &other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator++()
-
- The prefix ++ operator (\c{++i}) advances the iterator to the
- next item in the map and returns an iterator to the new current
- item.
-
- Calling this function on QMap::end() leads to undefined results.
-
- \sa operator--()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator++(int)
-
- \overload
-
- The postfix ++ operator (\c{i++}) advances the iterator to the
- next item in the map and returns an iterator to the previously
- current item.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator &QMap<Key, T>::const_iterator::operator--()
-
- The prefix -- operator (\c{--i}) makes the preceding item
- current and returns an iterator pointing to the new current item.
-
- Calling this function on QMap::begin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator--(int)
-
- \overload
-
- The postfix -- operator (\c{i--}) makes the preceding item
- current and returns an iterator pointing to the previously
- current item.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator+(qsizetype j) const
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator-(qsizetype j) const
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator &QMap<Key, T>::const_iterator::operator+=(qsizetype j)
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-=(), operator+()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator &QMap<Key, T>::const_iterator::operator-=(qsizetype j)
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+=(), operator-()
-*/
-
-/*! \class QMap::key_iterator
- \inmodule QtCore
- \since 5.6
- \brief The QMap::key_iterator class provides an STL-style const iterator for QMap and QMultiMap keys.
-
- QMap::key_iterator is essentially the same as QMap::const_iterator
- with the difference that operator*() and operator->() return a key
- instead of a value.
-
- For most uses QMap::iterator and QMap::const_iterator should be used,
- you can easily access the key by calling QMap::iterator::key():
-
- \snippet code/src_corelib_tools_qmap.cpp keyiterator1
-
- However, to have interoperability between QMap's keys and STL-style
- algorithms we need an iterator that dereferences to a key instead
- of a value. With QMap::key_iterator we can apply an algorithm to a
- range of keys without having to call QMap::keys(), which is inefficient
- as it costs one QMap iteration and memory allocation to create a temporary
- QList.
-
- \snippet code/src_corelib_tools_qmap.cpp keyiterator2
-
- QMap::key_iterator is const, it's not possible to modify the key.
-
- The default QMap::key_iterator constructor creates an uninitialized
- iterator. You must initialize it using a QMap function like
- QMap::keyBegin() or QMap::keyEnd().
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QMap::const_iterator, QMap::iterator
-*/
-
-/*! \typedef QMap::key_iterator::difference_type
- \internal
-*/
-
-/*! \typedef QMap::key_iterator::iterator_category
- \internal
-*/
-
-/*! \typedef QMap::key_iterator::pointer
- \internal
-*/
-
-/*! \typedef QMap::key_iterator::reference
- \internal
-*/
-
-/*! \typedef QMap::key_iterator::value_type
- \internal
-*/
-
-/*! \fn template <class Key, class T> const T &QMap<Key, T>::key_iterator::operator*() const
-
- Returns the current item's key.
-*/
-
-/*! \fn template <class Key, class T> const T *QMap<Key, T>::key_iterator::operator->() const
-
- Returns a pointer to the current item's key.
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::key_iterator::operator==(key_iterator other) const
-
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-/*! \fn template <class Key, class T> bool QMap<Key, T>::key_iterator::operator!=(key_iterator other) const
-
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-
-/*!
- \fn template <class Key, class T> QMap<Key, T>::key_iterator &QMap<Key, T>::key_iterator::operator++()
-
- The prefix ++ operator (\c{++i}) advances the iterator to the
- next item in the hash and returns an iterator to the new current
- item.
-
- Calling this function on QMap::keyEnd() leads to undefined results.
-
- \sa operator--()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::key_iterator::operator++(int)
-
- \overload
-
- The postfix ++ operator (\c{i++}) advances the iterator to the
- next item in the hash and returns an iterator to the previous
- item.
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator &QMap<Key, T>::key_iterator::operator--()
-
- The prefix -- operator (\c{--i}) makes the preceding item
- current and returns an iterator pointing to the new current item.
-
- Calling this function on QMap::keyBegin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::key_iterator::operator--(int)
-
- \overload
-
- The postfix -- operator (\c{i--}) makes the preceding item
- current and returns an iterator pointing to the previous
- item.
-*/
-
-/*! \fn template <class Key, class T> const_iterator QMap<Key, T>::key_iterator::base() const
- Returns the underlying const_iterator this key_iterator is based on.
-*/
-
-/*! \typedef QMap::const_key_value_iterator
- \inmodule QtCore
- \since 5.10
- \brief The QMap::const_key_value_iterator typedef provides an STL-style iterator for QMap and QMultiMap.
-
- QMap::const_key_value_iterator is essentially the same as QMap::const_iterator
- with the difference that operator*() returns a key/value pair instead of a
- value.
-
- \sa QKeyValueIterator
-*/
-
-/*! \typedef QMap::key_value_iterator
- \inmodule QtCore
- \since 5.10
- \brief The QMap::key_value_iterator typedef provides an STL-style iterator for QMap and QMultiMap.
-
- QMap::key_value_iterator is essentially the same as QMap::iterator
- with the difference that operator*() returns a key/value pair instead of a
- value.
-
- \sa QKeyValueIterator
-*/
-
-/*! \fn template <class Key, class T> QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
- \relates QMap
-
- Writes the map \a map to stream \a out.
-
- This function requires the key and value types to implement \c
- operator<<().
-
- \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
-*/
-
-/*! \fn template <class Key, class T> QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map)
- \relates QMap
-
- Reads a map from stream \a in into \a map.
-
- This function requires the key and value types to implement \c
- operator>>().
-
- \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
-*/
-
-/*! \class QMultiMap
- \inmodule QtCore
- \brief The QMultiMap class is a convenience QMap subclass that provides multi-valued maps.
-
- \ingroup tools
- \ingroup shared
-
- \reentrant
-
- QMultiMap\<Key, T\> is one of Qt's generic \l{container classes}.
- It inherits QMap and extends it with a few functions
- that make it able to store multi-valued maps. A multi-valued map
- is a map that allows multiple values with the same key; QMap
- doesn't allow that.
-
- Because QMultiMap inherits QMap, all of QMap's functionality also
- applies to QMultiMap. For example, you can use isEmpty() to test
- whether the map is empty, and you can traverse a QMultiMap using
- QMap's iterator classes (for example, QMapIterator). But in
- addition, it provides an insert() function that inserts but does
- not overwrite any previous value if the key already exists,
- and a replace() function that corresponds which does overwite
- an existing value if they key is already in the map.
- It also provides convenient operator+() and operator+=().
-
- Example:
- \snippet code/src_corelib_tools_qmap.cpp 25
-
- Unlike QMap, QMultiMap provides no operator[]. Use value() or
- replace() if you want to access the most recently inserted item
- with a certain key.
-
- If you want to retrieve all the values for a single key, you can
- use values(const Key &key), which returns a QList<T>:
-
- \snippet code/src_corelib_tools_qmap.cpp 26
-
- The items that share the same key are available from most
- recently to least recently inserted.
-
- If you prefer the STL-style iterators, you can call find() to get
- the iterator for the first item with a key and iterate from
- there:
-
- \snippet code/src_corelib_tools_qmap.cpp 27
-
- QMultiMap's key and value data types must be \l{assignable data
- types}. This covers most data types you are likely to encounter,
- but the compiler won't let you, for example, store a QWidget as a
- value; instead, store a QWidget *. In addition, QMultiMap's key type
- must provide operator<(). See the QMap documentation for details.
-
- \sa QMap, QMapIterator, QMutableMapIterator, QMultiHash
-*/
-
-/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap()
-
- Constructs an empty map.
-*/
-
-/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(std::initializer_list<std::pair<Key,T> > list)
- \since 5.1
-
- Constructs a multi-map with a copy of each of the elements in the
- initializer list \a list.
-
- This function is only available if the program is being
- compiled in C++11 mode.
-*/
-
-/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(const QMap<Key, T> &other)
-
- Constructs a copy of \a other (which can be a QMap or a
- QMultiMap).
-
- \sa operator=()
-*/
-
-/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::replace(const Key &key, const T &value)
-
- Inserts a new item with the key \a key and a value of \a value.
-
- If there is already an item with the key \a key, that item's value
- is replaced with \a value.
-
- If there are multiple items with the key \a key, the most
- recently inserted item's value is replaced with \a value.
-
- \sa insert()
-*/
-
-/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(const Key &key, const T &value)
-
- Inserts a new item with the key \a key and a value of \a value.
-
- If there is already an item with the same key in the map, this
- function will simply create a new one. (This behavior is
- different from replace(), which overwrites the value of an
- existing item.)
-
- \sa replace()
-*/
-
-/*! \fn [qmultimap-insert-pos] template <class Key, class T> typename QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(typename QMultiMap<Key, T>::const_iterator pos, const Key &key, const T &value)
-
- \since 5.1
- Inserts a new item with the key \a key and value \a value and with hint \a pos
- suggesting where to do the insert.
-
- If constBegin() is used as hint it indicates that the \a key is less than any key in the map
- while constEnd() suggests that the \a key is larger than any key in the map.
- Otherwise the hint should meet the condition (\a pos - 1).key() < \a key <= pos.key().
- If the hint \a pos is wrong it is ignored and a regular insert is done.
-
- If there is already an item with the same key in the map, this function will simply create a new one.
-
- \b {Note:} Be careful with the hint. Providing an iterator from an older shared instance might
- crash but there is also a risk that it will silently corrupt both the map and the \a pos map.
-*/
-
-/*! \fn template <class Key, class T> QMultiMap &QMultiMap<Key, T>::operator+=(const QMultiMap &other)
-
- Inserts all the items in the \a other map into this map and
- returns a reference to this map.
-
- \sa insert(), operator+()
-*/
-
-/*! \fn template <class Key, class T> QMultiMap QMultiMap<Key, T>::operator+(const QMultiMap &other) const
-
- Returns a map that contains all the items in this map in
- addition to all the items in \a other. If a key is common to both
- maps, the resulting map will contain the key multiple times.
-
- \sa operator+=()
-*/
-
-/*!
- \fn template <class Key, class T> bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const
- \since 4.3
-
- Returns \c true if the map contains an item with key \a key and
- value \a value; otherwise returns \c false.
-
- \sa QMap::contains()
-*/
-
-/*!
- \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::remove(const Key &key, const T &value)
- \since 4.3
-
- Removes all the items that have the key \a key and the value \a
- value from the map. Returns the number of items removed.
-
- \sa QMap::remove()
-*/
-
-/*!
- \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::count(const Key &key, const T &value) const
- \since 4.3
-
- Returns the number of items with key \a key and value \a value.
-
- \sa QMap::count()
-*/
-
-/*!
- \fn template <class Key, class T> typename QMap<Key, T>::iterator QMultiMap<Key, T>::find(const Key &key, const T &value)
- \since 4.3
-
- Returns an iterator pointing to the item with key \a key and
- value \a value in the map.
-
- If the map contains no such item, the function returns end().
-
- If the map contains multiple items with key \a key, this
- function returns an iterator that points to the most recently
- inserted value.
-
- \sa QMap::find()
-*/
-
-/*!
- \fn template <class Key, class T> typename QMap<Key, T>::const_iterator QMultiMap<Key, T>::find(const Key &key, const T &value) const
- \since 4.3
- \overload
-
- Returns a const iterator pointing to the item with the given \a key and
- \a value in the map.
-
- If the map contains no such item, the function returns end().
-
- If the map contains multiple items with the specified \a key, this
- function returns a const iterator that points to the most recently
- inserted value.
-
- \sa QMap::find()
-*/
-
-/*!
- \fn template <class Key, class T> typename QMap<Key, T>::const_iterator QMultiMap<Key, T>::constFind(const Key &key, const T &value) const
- \since 4.3
-
- Returns an iterator pointing to the item with key \a key and the
- value \a value in the map.
-
- If the map contains no such item, the function returns
- constEnd().
-
- \sa QMap::constFind()
-*/
-
-/*! \fn template <class Key, class T> QList<T> QMultiMap<Key, T>::values(const Key &key) const
-
- Returns a list containing all the values associated with key
- \a key, from the most recently inserted to the least recently
- inserted one.
-*/
-
-/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::uniqueKeys() const
- \since 4.2
-
- Returns a list containing all the keys in the map in ascending
- order. Keys that occur multiple times in the map occur only
- once in the returned list.
-*/
-
-/*!
- \fn [qmultimap-unite] template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::unite(const QMultiMap<Key, T> &other)
-
- Inserts all the items in the \a other map into this map. If a
- key is common to both maps, the resulting map will contain the
- key multiple times.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 848ba5c4d4..7ee0be1e51 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -1,500 +1,569 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMAP_H
#define QMAP_H
+#include <QtCore/qhashfunctions.h>
#include <QtCore/qiterator.h>
#include <QtCore/qlist.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qpair.h>
-
-#ifdef Q_MAP_DEBUG
-#include <QtCore/qdebug.h>
-#endif
+#include <QtCore/qshareddata.h>
+#include <QtCore/qshareddata_impl.h>
#include <functional>
#include <initializer_list>
#include <map>
-#include <new>
+#include <algorithm>
QT_BEGIN_NAMESPACE
-/*
- QMap uses qMapLessThanKey() to compare keys. The default
- implementation uses operator<(). For pointer types,
- qMapLessThanKey() uses std::less (because operator<() on
- pointers can be used only between pointers in the same array).
-*/
-
-template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
+// common code shared between QMap and QMultimap
+template <typename AMap>
+class QMapData : public QSharedData
{
- return key1 < key2;
-}
+public:
+ using Map = AMap;
+ using Key = typename Map::key_type;
+ using T = typename Map::mapped_type;
+ using value_type = typename Map::value_type;
+ using size_type = typename Map::size_type;
+ using iterator = typename Map::iterator;
+ using const_iterator = typename Map::const_iterator;
+
+ static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+
+ Map m;
+
+ QMapData() = default;
+ explicit QMapData(const Map &other)
+ : m(other)
+ {}
+
+ explicit QMapData(Map &&other)
+ : m(std::move(other))
+ {}
+
+ // used in remove(); copies from source all the values not matching key.
+ // returns how many were NOT copied (removed).
+ size_type copyIfNotEquivalentTo(const Map &source, const Key &key)
+ {
+ Q_ASSERT(m.empty());
+
+ size_type result = 0;
+ const auto &keyCompare = source.key_comp();
+ const auto filter = [&result, &key, &keyCompare](const auto &v)
+ {
+ if (!keyCompare(key, v.first) && !keyCompare(v.first, key)) {
+ // keys are equivalent (neither a<b nor b<a) => found it
+ ++result;
+ return true;
+ }
+ return false;
+ };
-template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
-{
- return std::less<const Ptr *>()(key1, key2);
-}
+ std::remove_copy_if(source.cbegin(), source.cend(),
+ std::inserter(m, m.end()),
+ filter);
+ return result;
+ }
-struct QMapDataBase;
-template <class Key, class T> struct QMapData;
+ // used in key(T), count(Key, T), find(key, T), etc; returns a
+ // comparator object suitable for algorithms with std::(multi)map
+ // iterators.
+ static auto valueIsEqualTo(const T &value)
+ {
+ return [&value](const auto &v) { return v.second == value; };
+ }
-struct Q_CORE_EXPORT QMapNodeBase
-{
- quintptr p;
- QMapNodeBase *left;
- QMapNodeBase *right;
-
- enum Color { Red = 0, Black = 1 };
- enum { Mask = 3 }; // reserve the second bit as well
-
- const QMapNodeBase *nextNode() const;
- QMapNodeBase *nextNode() { return const_cast<QMapNodeBase *>(const_cast<const QMapNodeBase *>(this)->nextNode()); }
- const QMapNodeBase *previousNode() const;
- QMapNodeBase *previousNode() { return const_cast<QMapNodeBase *>(const_cast<const QMapNodeBase *>(this)->previousNode()); }
-
- Color color() const { return Color(p & 1); }
- void setColor(Color c) { if (c == Black) p |= Black; else p &= ~Black; }
- QMapNodeBase *parent() const { return reinterpret_cast<QMapNodeBase *>(p & ~Mask); }
- void setParent(QMapNodeBase *pp) { p = (p & Mask) | quintptr(pp); }
-
- template <typename T>
- static typename std::enable_if<QTypeInfo<T>::isComplex>::type
- callDestructorIfNecessary(T &t) noexcept { Q_UNUSED(t); t.~T(); } // Q_UNUSED: silence MSVC unused 't' warning
- template <typename T>
- static typename std::enable_if<!QTypeInfo<T>::isComplex>::type
- callDestructorIfNecessary(T &) noexcept {}
-};
+ Key key(const T &value, const Key &defaultKey) const
+ {
+ auto i = std::find_if(m.cbegin(),
+ m.cend(),
+ valueIsEqualTo(value));
+ if (i != m.cend())
+ return i->first;
-template <class Key, class T>
-struct QMapNode : public QMapNodeBase
-{
- Key key;
- T value;
+ return defaultKey;
+ }
- inline QMapNode *leftNode() const { return static_cast<QMapNode *>(left); }
- inline QMapNode *rightNode() const { return static_cast<QMapNode *>(right); }
+ QList<Key> keys() const
+ {
+ QList<Key> result;
+ result.reserve(m.size());
- inline const QMapNode *nextNode() const { return reinterpret_cast<const QMapNode *>(QMapNodeBase::nextNode()); }
- inline const QMapNode *previousNode() const { return static_cast<const QMapNode *>(QMapNodeBase::previousNode()); }
- inline QMapNode *nextNode() { return reinterpret_cast<QMapNode *>(QMapNodeBase::nextNode()); }
- inline QMapNode *previousNode() { return static_cast<QMapNode *>(QMapNodeBase::previousNode()); }
+ const auto extractKey = [](const auto &v) { return v.first; };
- QMapNode<Key, T> *copy(QMapData<Key, T> *d) const;
+ std::transform(m.cbegin(),
+ m.cend(),
+ std::back_inserter(result),
+ extractKey);
+ return result;
+ }
- void destroySubTree()
+ QList<Key> keys(const T &value) const
{
- callDestructorIfNecessary(key);
- callDestructorIfNecessary(value);
- doDestroySubTree(std::integral_constant<bool, QTypeInfo<T>::isComplex || QTypeInfo<Key>::isComplex>());
+ QList<Key> result;
+ result.reserve(m.size());
+ // no std::transform_if...
+ for (const auto &v : m) {
+ if (v.second == value)
+ result.append(v.first);
+ }
+ result.shrink_to_fit();
+ return result;
}
- QMapNode<Key, T> *lowerBound(const Key &key);
- QMapNode<Key, T> *upperBound(const Key &key);
+ QList<T> values() const
+ {
+ QList<T> result;
+ result.reserve(m.size());
-private:
- void doDestroySubTree(std::false_type) {}
- void doDestroySubTree(std::true_type)
+ const auto extractValue = [](const auto &v) { return v.second; };
+
+ std::transform(m.cbegin(),
+ m.cend(),
+ std::back_inserter(result),
+ extractValue);
+ return result;
+ }
+
+ size_type count(const Key &key) const
{
- if (left)
- leftNode()->destroySubTree();
- if (right)
- rightNode()->destroySubTree();
+ return m.count(key);
}
- QMapNode() = delete;
- Q_DISABLE_COPY(QMapNode)
-};
+ // Used in erase. Allocates a new QMapData and copies, from this->m,
+ // the elements not in the [first, last) range. The return contains
+ // the new QMapData and an iterator in its map pointing at the first
+ // element after the erase.
+ struct EraseResult {
+ QMapData *data;
+ iterator it;
+ };
-template <class Key, class T>
-inline QMapNode<Key, T> *QMapNode<Key, T>::lowerBound(const Key &akey)
-{
- QMapNode<Key, T> *n = this;
- QMapNode<Key, T> *lastNode = nullptr;
- while (n) {
- if (!qMapLessThanKey(n->key, akey)) {
- lastNode = n;
- n = n->leftNode();
- } else {
- n = n->rightNode();
+ EraseResult erase(const_iterator first, const_iterator last) const
+ {
+ EraseResult result;
+ result.data = new QMapData;
+ result.it = result.data->m.end();
+ const auto newDataEnd = result.it;
+
+ auto i = m.begin();
+ const auto e = m.end();
+
+ // copy over all the elements before first
+ while (i != first) {
+ result.it = result.data->m.insert(newDataEnd, *i);
+ ++i;
+ }
+
+ // skip until last
+ while (i != last)
+ ++i;
+
+ // copy from last to the end
+ while (i != e) {
+ result.data->m.insert(newDataEnd, *i);
+ ++i;
}
+
+ if (result.it != newDataEnd)
+ ++result.it;
+
+ return result;
}
- return lastNode;
-}
+};
+
+//
+// QMap
+//
template <class Key, class T>
-inline QMapNode<Key, T> *QMapNode<Key, T>::upperBound(const Key &akey)
+class QMap
{
- QMapNode<Key, T> *n = this;
- QMapNode<Key, T> *lastNode = nullptr;
- while (n) {
- if (qMapLessThanKey(akey, n->key)) {
- lastNode = n;
- n = n->leftNode();
- } else {
- n = n->rightNode();
- }
- }
- return lastNode;
-}
+ using Map = std::map<Key, T>;
+ using MapData = QMapData<Map>;
+ QtPrivate::QExplicitlySharedDataPointerV2<MapData> d;
+ friend class QMultiMap<Key, T>;
+public:
+ using key_type = Key;
+ using mapped_type = T;
+ using difference_type = qptrdiff;
+ using size_type = qsizetype;
-struct Q_CORE_EXPORT QMapDataBase
-{
- QtPrivate::RefCount ref;
- qsizetype size;
- QMapNodeBase header;
- QMapNodeBase *mostLeftNode;
+ QMap() = default;
- void rotateLeft(QMapNodeBase *x);
- void rotateRight(QMapNodeBase *x);
- void rebalance(QMapNodeBase *x);
- void freeNodeAndRebalance(QMapNodeBase *z);
- void recalcMostLeftNode();
+ // implicitly generated special member functions are OK!
- QMapNodeBase *createNode(size_t size, size_t alignment, QMapNodeBase *parent, bool left);
- void freeTree(QMapNodeBase *root, size_t alignment);
+ void swap(QMap<Key, T> &other) noexcept
+ {
+ d.swap(other.d);
+ }
- static const QMapDataBase shared_null;
+ QMap(std::initializer_list<std::pair<Key, T>> list)
+ {
+ for (auto &p : list)
+ insert(p.first, p.second);
+ }
- static QMapDataBase *createData();
- static void freeData(QMapDataBase *d);
-};
+ explicit QMap(const std::map<Key, T> &other)
+ : d(other.empty() ? nullptr : new MapData(other))
+ {
+ }
-template <class Key, class T>
-struct QMapData : public QMapDataBase
-{
- typedef QMapNode<Key, T> Node;
-
- Node *root() const { return static_cast<Node *>(header.left); }
-
- // using reinterpret_cast because QMapDataBase::header is not
- // actually a QMapNode.
- const Node *end() const { return reinterpret_cast<const Node *>(&header); }
- Node *end() { return reinterpret_cast<Node *>(&header); }
- const Node *begin() const { if (root()) return static_cast<const Node*>(mostLeftNode); return end(); }
- Node *begin() { if (root()) return static_cast<Node*>(mostLeftNode); return end(); }
-
- void deleteNode(Node *z);
- Node *findNode(const Key &akey) const;
- void nodeRange(const Key &akey, Node **firstNode, Node **lastNode);
-
- Node *createNode(const Key &k, const T &v, Node *parent = nullptr, bool left = false)
- {
- Node *n = static_cast<Node *>(QMapDataBase::createNode(sizeof(Node), alignof(Node),
- parent, left));
- QT_TRY {
- new (&n->key) Key(k);
- QT_TRY {
- new (&n->value) T(v);
- } QT_CATCH(...) {
- n->key.~Key();
- QT_RETHROW;
- }
- } QT_CATCH(...) {
- QMapDataBase::freeNodeAndRebalance(n);
- QT_RETHROW;
- }
- return n;
+ explicit QMap(std::map<Key, T> &&other)
+ : d(other.empty() ? nullptr : new MapData(std::move(other)))
+ {
}
- static QMapData *create() {
- return static_cast<QMapData *>(createData());
+ std::map<Key, T> toStdMap() const &
+ {
+ if (d)
+ return d->m;
+ return {};
}
- void destroy() {
- if (root()) {
- root()->destroySubTree();
- freeTree(header.left, alignof(Node));
+ std::map<Key, T> toStdMap() &&
+ {
+ if (d) {
+ if (d.isShared())
+ return d->m;
+ else
+ return std::move(d->m);
}
- freeData(this);
+
+ return {};
}
-};
-template <class Key, class T>
-QMapNode<Key, T> *QMapNode<Key, T>::copy(QMapData<Key, T> *d) const
-{
- QMapNode<Key, T> *n = d->createNode(key, value);
- n->setColor(color());
- if (left) {
- n->left = leftNode()->copy(d);
- n->left->setParent(n);
- } else {
- n->left = nullptr;
- }
- if (right) {
- n->right = rightNode()->copy(d);
- n->right->setParent(n);
- } else {
- n->right = nullptr;
- }
- return n;
-}
+#ifndef Q_QDOC
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result_container<QMap, AKey, AT> operator==(const QMap &lhs, const QMap &rhs)
+ {
+ if (lhs.d == rhs.d)
+ return true;
+ if (!lhs.d)
+ return rhs == lhs;
+ Q_ASSERT(lhs.d);
+ return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
+ }
-template <class Key, class T>
-void QMapData<Key, T>::deleteNode(QMapNode<Key, T> *z)
-{
- QMapNodeBase::callDestructorIfNecessary(z->key);
- QMapNodeBase::callDestructorIfNecessary(z->value);
- freeNodeAndRebalance(z);
-}
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result_container<QMap, AKey, AT> operator!=(const QMap &lhs, const QMap &rhs)
+ {
+ return !(lhs == rhs);
+ }
+ // TODO: add the other comparison operators; std::map has them.
+#else
+ friend bool operator==(const QMap &lhs, const QMap &rhs);
+ friend bool operator!=(const QMap &lhs, const QMap &rhs);
+#endif // Q_QDOC
-template <class Key, class T>
-QMapNode<Key, T> *QMapData<Key, T>::findNode(const Key &akey) const
-{
- if (Node *r = root()) {
- Node *lb = r->lowerBound(akey);
- if (lb && !qMapLessThanKey(akey, lb->key))
- return lb;
+ size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
+
+ bool isEmpty() const { return d ? d->m.empty() : true; }
+
+ void detach()
+ {
+ if (d)
+ d.detach();
+ else
+ d.reset(new MapData);
+ }
+
+ bool isDetached() const noexcept
+ {
+ return d ? !d.isShared() : false; // false makes little sense, but that's shared_null's behavior...
}
- return nullptr;
-}
+ bool isSharedWith(const QMap<Key, T> &other) const noexcept
+ {
+ return d == other.d; // also this makes little sense?
+ }
-template <class Key, class T>
-void QMapData<Key, T>::nodeRange(const Key &akey, QMapNode<Key, T> **firstNode, QMapNode<Key, T> **lastNode)
-{
- Node *n = root();
- Node *l = end();
- while (n) {
- if (qMapLessThanKey(akey, n->key)) {
- l = n;
- n = n->leftNode();
- } else if (qMapLessThanKey(n->key, akey)) {
- n = n->rightNode();
- } else {
- *firstNode = n->leftNode() ? n->leftNode()->lowerBound(akey) : nullptr;
- if (!*firstNode)
- *firstNode = n;
- *lastNode = n->rightNode() ? n->rightNode()->upperBound(akey) : nullptr;
- if (!*lastNode)
- *lastNode = l;
+ void clear()
+ {
+ if (!d)
return;
- }
+
+ if (!d.isShared())
+ d->m.clear();
+ else
+ d.reset();
}
- *firstNode = *lastNode = l;
-}
+ size_type remove(const Key &key)
+ {
+ if (!d)
+ return 0;
-template <class Key, class T>
-class QMap
-{
- typedef QMapNode<Key, T> Node;
+ if (!d.isShared())
+ return size_type(d->m.erase(key));
- QMapData<Key, T> *d;
+ MapData *newData = new MapData;
+ size_type result = newData->copyIfNotEquivalentTo(d->m, key);
-public:
- inline QMap() noexcept : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null))) { }
- inline QMap(std::initializer_list<std::pair<Key,T> > list)
- : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null)))
+ d.reset(newData);
+
+ return result;
+ }
+
+ template <typename Predicate>
+ size_type removeIf(Predicate pred)
{
- for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
- insert(it->first, it->second);
+ return QtPrivate::associative_erase_if(*this, pred);
}
- QMap(const QMap<Key, T> &other);
- inline ~QMap() { if (!d->ref.deref()) d->destroy(); }
+ T take(const Key &key)
+ {
+ if (!d)
+ return T();
+
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ // TODO: improve. There is no need of copying all the
+ // elements (the one to be removed can be skipped).
+ detach();
+
+ auto i = d->m.find(key);
+ if (i != d->m.end()) {
+ T result(std::move(i->second));
+ d->m.erase(i);
+ return result;
+ }
+ return T();
+ }
- QMap<Key, T> &operator=(const QMap<Key, T> &other);
- inline QMap(QMap<Key, T> &&other) noexcept
- : d(other.d)
+ bool contains(const Key &key) const
{
- other.d = static_cast<QMapData<Key, T> *>(
- const_cast<QMapDataBase *>(&QMapDataBase::shared_null));
+ if (!d)
+ return false;
+ auto i = d->m.find(key);
+ return i != d->m.end();
}
- inline QMap<Key, T> &operator=(QMap<Key, T> &&other) noexcept
- { QMap moved(std::move(other)); swap(moved); return *this; }
- inline void swap(QMap<Key, T> &other) noexcept { qSwap(d, other.d); }
- explicit QMap(const typename std::map<Key, T> &other);
- std::map<Key, T> toStdMap() const;
+ Key key(const T &value, const Key &defaultKey = Key()) const
+ {
+ if (!d)
+ return defaultKey;
- bool operator==(const QMap<Key, T> &other) const;
- inline bool operator!=(const QMap<Key, T> &other) const { return !(*this == other); }
+ return d->key(value, defaultKey);
+ }
- inline qsizetype size() const { return d->size; }
+ T value(const Key &key, const T &defaultValue = T()) const
+ {
+ if (!d)
+ return defaultValue;
+ const auto i = d->m.find(key);
+ if (i != d->m.cend())
+ return i->second;
+ return defaultValue;
+ }
- inline bool isEmpty() const { return d->size == 0; }
+ T &operator[](const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ detach();
+ auto i = d->m.find(key);
+ if (i == d->m.end())
+ i = d->m.insert({key, T()}).first;
+ return i->second;
+ }
- inline void detach() { if (d->ref.isShared()) detach_helper(); }
- inline bool isDetached() const { return !d->ref.isShared(); }
- inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
+ // CHANGE: return T, not const T!
+ T operator[](const Key &key) const
+ {
+ return value(key);
+ }
- void clear();
+ QList<Key> keys() const
+ {
+ if (!d)
+ return {};
+ return d->keys();
+ }
- qsizetype remove(const Key &key);
- T take(const Key &key);
+ QList<Key> keys(const T &value) const
+ {
+ if (!d)
+ return {};
+ return d->keys(value);
+ }
- bool contains(const Key &key) const;
- Key key(const T &value, const Key &defaultKey = Key()) const;
- T value(const Key &key, const T &defaultValue = T()) const;
- T &operator[](const Key &key);
- const T operator[](const Key &key) const;
+ QList<T> values() const
+ {
+ if (!d)
+ return {};
+ return d->values();
+ }
- QList<Key> keys() const;
- QList<Key> keys(const T &value) const;
- QList<T> values() const;
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
- QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
-#endif
- qsizetype count(const Key &key) const;
+ size_type count(const Key &key) const
+ {
+ if (!d)
+ return 0;
+ return d->count(key);
+ }
+ size_type count() const
+ {
+ return size();
+ }
inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
- inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return (constEnd() - 1).key(); }
+ inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return (--constEnd()).key(); }
inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
- inline T &last() { Q_ASSERT(!isEmpty()); return *(end() - 1); }
- inline const T &last() const { Q_ASSERT(!isEmpty()); return *(constEnd() - 1); }
+ inline T &last() { Q_ASSERT(!isEmpty()); return *(--end()); }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return *(--constEnd()); }
class const_iterator;
class iterator
{
+ friend class QMap<Key, T>;
friend class const_iterator;
- Node *i;
+ typename Map::iterator i;
+ explicit iterator(typename Map::iterator it) : i(it) {}
public:
- typedef std::bidirectional_iterator_tag iterator_category;
- typedef qptrdiff difference_type;
- typedef T value_type;
- typedef T *pointer;
- typedef T &reference;
-
- inline iterator() : i(nullptr) { }
- inline iterator(Node *node) : i(node) { }
-
- inline const Key &key() const { return i->key; }
- inline T &value() const { return i->value; }
- inline T &operator*() const { return i->value; }
- inline T *operator->() const { return &i->value; }
- inline bool operator==(const iterator &o) const { return i == o.i; }
- inline bool operator!=(const iterator &o) const { return i != o.i; }
-
- inline iterator &operator++() {
- i = i->nextNode();
+ using iterator_category = std::bidirectional_iterator_tag;
+ using difference_type = qptrdiff;
+ using value_type = T;
+ using pointer = T *;
+ using reference = T &;
+
+ iterator() = default;
+
+ const Key &key() const { return i->first; }
+ T &value() const { return i->second; }
+ T &operator*() const { return i->second; }
+ T *operator->() const { return &i->second; }
+ friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
+ friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
+
+ iterator &operator++()
+ {
+ ++i;
return *this;
}
- inline iterator operator++(int) {
+ iterator operator++(int)
+ {
iterator r = *this;
- i = i->nextNode();
+ ++i;
return r;
}
- inline iterator &operator--() {
- i = i->previousNode();
+ iterator &operator--()
+ {
+ --i;
return *this;
}
- inline iterator operator--(int) {
+ iterator operator--(int)
+ {
iterator r = *this;
- i = i->previousNode();
+ --i;
return r;
}
- inline iterator operator+(qsizetype j) const
- { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
- inline iterator operator-(qsizetype j) const { return operator+(-j); }
- inline iterator &operator+=(qsizetype j) { return *this = *this + j; }
- inline iterator &operator-=(qsizetype j) { return *this = *this - j; }
- friend inline iterator operator+(qsizetype j, iterator k) { return k + j; }
-
- inline bool operator==(const const_iterator &o) const { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const { return i != o.i; }
- friend class QMap<Key, T>;
- friend class QMultiMap<Key, T>;
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
+ //! [qmap-op-it-plus-step]
+ friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
+ //! [qmap-op-it-minus-step]
+ friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
+ iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
+ iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
+ //! [qmap-op-step-plus-it]
+ friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
+ //! [qmap-op-step-minus-it]
+ friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
+#endif
};
- friend class iterator;
class const_iterator
{
- friend class iterator;
- const Node *i;
+ friend class QMap<Key, T>;
+ typename Map::const_iterator i;
+ explicit const_iterator(typename Map::const_iterator it) : i(it) {}
public:
- typedef std::bidirectional_iterator_tag iterator_category;
- typedef qptrdiff difference_type;
- typedef T value_type;
- typedef const T *pointer;
- typedef const T &reference;
-
- Q_DECL_CONSTEXPR inline const_iterator() : i(nullptr) { }
- inline const_iterator(const Node *node) : i(node) { }
- inline const_iterator(const iterator &o) { i = o.i; }
-
- inline const Key &key() const { return i->key; }
- inline const T &value() const { return i->value; }
- inline const T &operator*() const { return i->value; }
- inline const T *operator->() const { return &i->value; }
- Q_DECL_CONSTEXPR inline bool operator==(const const_iterator &o) const { return i == o.i; }
- Q_DECL_CONSTEXPR inline bool operator!=(const const_iterator &o) const { return i != o.i; }
-
- inline const_iterator &operator++() {
- i = i->nextNode();
+ using iterator_category = std::bidirectional_iterator_tag;
+ using difference_type = qptrdiff;
+ using value_type = T;
+ using pointer = const T *;
+ using reference = const T &;
+
+ const_iterator() = default;
+ Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
+
+ const Key &key() const { return i->first; }
+ const T &value() const { return i->second; }
+ const T &operator*() const { return i->second; }
+ const T *operator->() const { return &i->second; }
+ friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
+ friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
+
+ const_iterator &operator++()
+ {
+ ++i;
return *this;
}
- inline const_iterator operator++(int) {
+ const_iterator operator++(int)
+ {
const_iterator r = *this;
- i = i->nextNode();
+ ++i;
return r;
}
- inline const_iterator &operator--() {
- i = i->previousNode();
+ const_iterator &operator--()
+ {
+ --i;
return *this;
}
- inline const_iterator operator--(int) {
+ const_iterator operator--(int)
+ {
const_iterator r = *this;
- i = i->previousNode();
+ --i;
return r;
}
- inline const_iterator operator+(qsizetype j) const
- { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
- inline const_iterator operator-(qsizetype j) const { return operator+(-j); }
- inline const_iterator &operator+=(qsizetype j) { return *this = *this + j; }
- inline const_iterator &operator-=(qsizetype j) { return *this = *this - j; }
- friend inline const_iterator operator+(qsizetype j, const_iterator k) { return k + j; }
- friend class QMap<Key, T>;
- friend class QMultiMap<Key, T>;
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
+ //! [qmap-op-it-plus-step-const]
+ friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
+ //! [qmap-op-it-minus-step-const]
+ friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
+ const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
+ const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
+ //! [qmap-op-step-plus-it-const]
+ friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
+ //! [qmap-op-step-minus-it-const]
+ friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
+#endif
};
- friend class const_iterator;
class key_iterator
{
@@ -526,833 +595,1010 @@ public:
typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
// STL style
- inline iterator begin() { detach(); return iterator(d->begin()); }
- inline const_iterator begin() const { return const_iterator(d->begin()); }
- inline const_iterator constBegin() const { return const_iterator(d->begin()); }
- inline const_iterator cbegin() const { return const_iterator(d->begin()); }
- inline iterator end() { detach(); return iterator(d->end()); }
- inline const_iterator end() const { return const_iterator(d->end()); }
- inline const_iterator constEnd() const { return const_iterator(d->end()); }
- inline const_iterator cend() const { return const_iterator(d->end()); }
- inline key_iterator keyBegin() const { return key_iterator(begin()); }
- inline key_iterator keyEnd() const { return key_iterator(end()); }
- inline key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
- inline key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
- inline const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
- inline const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
- inline const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
- inline const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
- iterator erase(iterator it);
+ iterator begin() { detach(); return iterator(d->m.begin()); }
+ const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
+ const_iterator constBegin() const { return begin(); }
+ const_iterator cbegin() const { return begin(); }
+ iterator end() { detach(); return iterator(d->m.end()); }
+ const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
+ const_iterator constEnd() const { return end(); }
+ const_iterator cend() const { return end(); }
+ key_iterator keyBegin() const { return key_iterator(begin()); }
+ key_iterator keyEnd() const { return key_iterator(end()); }
+ key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
+ key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
+ const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
+ const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
+ const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
+ const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
+ auto asKeyValueRange() & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() && { return QtPrivate::QKeyValueRange(std::move(*this)); }
+ auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange(std::move(*this)); }
+
+ iterator erase(const_iterator it)
+ {
+ return erase(it, std::next(it));
+ }
+
+ iterator erase(const_iterator afirst, const_iterator alast)
+ {
+ if (!d)
+ return iterator();
+
+ if (!d.isShared())
+ return iterator(d->m.erase(afirst.i, alast.i));
+
+ auto result = d->erase(afirst.i, alast.i);
+ d.reset(result.data);
+ return iterator(result.it);
+ }
// more Qt
typedef iterator Iterator;
typedef const_iterator ConstIterator;
- inline qsizetype count() const { return d->size; }
- iterator find(const Key &key);
- const_iterator find(const Key &key) const;
- const_iterator constFind(const Key &key) const;
- iterator lowerBound(const Key &key);
- const_iterator lowerBound(const Key &key) const;
- iterator upperBound(const Key &key);
- const_iterator upperBound(const Key &key) const;
- iterator insert(const Key &key, const T &value);
- iterator insert(const_iterator pos, const Key &key, const T &value);
- void insert(const QMap<Key, T> &map);
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
- QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
- QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
-#endif
- // STL compatibility
- typedef Key key_type;
- typedef T mapped_type;
- typedef qptrdiff difference_type;
- typedef qsizetype size_type;
- inline bool empty() const { return isEmpty(); }
- QPair<iterator, iterator> equal_range(const Key &akey);
- QPair<const_iterator, const_iterator> equal_range(const Key &akey) const;
+ iterator find(const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ detach();
+ return iterator(d->m.find(key));
+ }
-#ifdef Q_MAP_DEBUG
- void dump() const;
-#endif
+ const_iterator find(const Key &key) const
+ {
+ if (!d)
+ return const_iterator();
+ return const_iterator(d->m.find(key));
+ }
-private:
- void detach_helper();
- bool isValidIterator(const const_iterator &ci) const
- {
-#if defined(QT_DEBUG) && !defined(Q_MAP_NO_ITERATOR_DEBUG)
- const QMapNodeBase *n = ci.i;
- while (n->parent())
- n = n->parent();
- return n->left == d->root();
+ const_iterator constFind(const Key &key) const
+ {
+ return find(key);
+ }
+
+ iterator lowerBound(const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ detach();
+ return iterator(d->m.lower_bound(key));
+ }
+
+ const_iterator lowerBound(const Key &key) const
+ {
+ if (!d)
+ return const_iterator();
+ return const_iterator(d->m.lower_bound(key));
+ }
+
+ iterator upperBound(const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ detach();
+ return iterator(d->m.upper_bound(key));
+ }
+
+ const_iterator upperBound(const Key &key) const
+ {
+ if (!d)
+ return const_iterator();
+ return const_iterator(d->m.upper_bound(key));
+ }
+
+ iterator insert(const Key &key, const T &value)
+ {
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ // TODO: improve. In case of assignment, why copying first?
+ detach();
+ return iterator(d->m.insert_or_assign(key, value).first);
+ }
+
+ iterator insert(const_iterator pos, const Key &key, const T &value)
+ {
+ // TODO: improve. In case of assignment, why copying first?
+ typename Map::const_iterator dpos;
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key`/`value` alive across the detach
+ if (!d || d.isShared()) {
+ auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
+ detach();
+ dpos = std::next(d->m.cbegin(), posDistance);
+ } else {
+ dpos = pos.i;
+ }
+ return iterator(d->m.insert_or_assign(dpos, key, value));
+ }
+
+ void insert(const QMap<Key, T> &map)
+ {
+ // TODO: improve. In case of assignment, why copying first?
+ if (map.isEmpty())
+ return;
+
+ detach();
+
+#ifdef __cpp_lib_node_extract
+ auto copy = map.d->m;
+ copy.merge(std::move(d->m));
+ d->m = std::move(copy);
#else
- Q_UNUSED(ci);
- return true;
+ // this is a std::copy, but we can't use std::inserter (need insert_or_assign...).
+ // copy in reverse order, trying to make effective use of insertionHint.
+ auto insertionHint = d->m.end();
+ auto mapIt = map.d->m.crbegin();
+ auto end = map.d->m.crend();
+ for (; mapIt != end; ++mapIt)
+ insertionHint = d->m.insert_or_assign(insertionHint, mapIt->first, mapIt->second);
#endif
}
- friend class QMultiMap<Key, T>;
-};
+ void insert(QMap<Key, T> &&map)
+ {
+ if (!map.d || map.d->m.empty())
+ return;
-template <class Key, class T>
-inline QMap<Key, T>::QMap(const QMap<Key, T> &other)
-{
- if (other.d->ref.ref()) {
- d = other.d;
- } else {
- d = QMapData<Key, T>::create();
- if (other.d->header.left) {
- d->header.left = static_cast<Node *>(other.d->header.left)->copy(d);
- d->header.left->setParent(&d->header);
- d->recalcMostLeftNode();
+ if (map.d.isShared()) {
+ // fall back to a regular copy
+ insert(map);
+ return;
}
+
+ detach();
+
+#ifdef __cpp_lib_node_extract
+ map.d->m.merge(std::move(d->m));
+ *this = std::move(map);
+#else
+ // same as above
+ auto insertionHint = d->m.end();
+ auto mapIt = map.d->m.crbegin();
+ auto end = map.d->m.crend();
+ for (; mapIt != end; ++mapIt)
+ insertionHint = d->m.insert_or_assign(insertionHint, std::move(mapIt->first), std::move(mapIt->second));
+#endif
}
-}
-template <class Key, class T>
-Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other)
-{
- if (d != other.d) {
- QMap<Key, T> tmp(other);
- tmp.swap(*this);
+ // STL compatibility
+ inline bool empty() const
+ {
+ return isEmpty();
}
- return *this;
-}
-template <class Key, class T>
-Q_INLINE_TEMPLATE void QMap<Key, T>::clear()
-{
- *this = QMap<Key, T>();
-}
+ std::pair<iterator, iterator> equal_range(const Key &akey)
+ {
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
+ detach();
+ auto result = d->m.equal_range(akey);
+ return {iterator(result.first), iterator(result.second)};
+ }
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_CLANG("-Wreturn-stack-address")
+ std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
+ {
+ if (!d)
+ return {};
+ auto result = d->m.equal_range(akey);
+ return {const_iterator(result.first), const_iterator(result.second)};
+ }
-template <class Key, class T>
-Q_INLINE_TEMPLATE T QMap<Key, T>::value(const Key &akey, const T &adefaultValue) const
-{
- Node *n = d->findNode(akey);
- return n ? n->value : adefaultValue;
-}
+private:
+#ifdef Q_QDOC
+ friend size_t qHash(const QMap &key, size_t seed = 0);
+#else
+# if defined(Q_CC_GHS) || defined (Q_CC_MSVC)
+ // GHS and MSVC tries to intantiate qHash() for the noexcept running into a
+ // non-SFINAE'ed hard error... Create an artificial SFINAE context as a
+ // work-around:
+ template <typename M, std::enable_if_t<std::is_same_v<M, QMap>, bool> = true>
+ friend QtPrivate::QHashMultiReturnType<typename M::key_type, typename M::mapped_type>
+# else
+ using M = QMap;
+ friend size_t
+# endif
+ qHash(const M &key, size_t seed = 0)
+ noexcept(QHashPrivate::noexceptPairHash<typename M::key_type, typename M::mapped_type>())
+ {
+ if (!key.d)
+ return seed;
+ // don't use qHashRange to avoid its compile-time overhead:
+ return std::accumulate(key.d->m.begin(), key.d->m.end(), seed,
+ QtPrivate::QHashCombine{});
+ }
+#endif // !Q_QDOC
+};
-QT_WARNING_POP
+Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)
-template <class Key, class T>
-Q_INLINE_TEMPLATE const T QMap<Key, T>::operator[](const Key &akey) const
+template <typename Key, typename T, typename Predicate>
+qsizetype erase_if(QMap<Key, T> &map, Predicate pred)
{
- return value(akey);
+ return QtPrivate::associative_erase_if(map, pred);
}
-template <class Key, class T>
-Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
-{
- detach();
- Node *n = d->findNode(akey);
- if (!n)
- return *insert(akey, T());
- return n->value;
-}
-template <class Key, class T>
-Q_INLINE_TEMPLATE qsizetype QMap<Key, T>::count(const Key &akey) const
-{
- Node *firstNode;
- Node *lastNode;
- d->nodeRange(akey, &firstNode, &lastNode);
-
- const_iterator ci_first(firstNode);
- const const_iterator ci_last(lastNode);
- int cnt = 0;
- while (ci_first != ci_last) {
- ++cnt;
- ++ci_first;
- }
- return cnt;
-}
+//
+// QMultiMap
+//
template <class Key, class T>
-Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
+class QMultiMap
{
- return d->findNode(akey) != nullptr;
-}
+ using Map = std::multimap<Key, T>;
+ using MapData = QMapData<Map>;
+ QtPrivate::QExplicitlySharedDataPointerV2<MapData> d;
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey, const T &avalue)
-{
- detach();
- Node *n = d->root();
- Node *y = d->end();
- Node *lastNode = nullptr;
- bool left = true;
- while (n) {
- y = n;
- if (!qMapLessThanKey(n->key, akey)) {
- lastNode = n;
- left = true;
- n = n->leftNode();
- } else {
- left = false;
- n = n->rightNode();
- }
- }
- if (lastNode && !qMapLessThanKey(akey, lastNode->key)) {
- lastNode->value = avalue;
- return iterator(lastNode);
+public:
+ using key_type = Key;
+ using mapped_type = T;
+ using difference_type = qptrdiff;
+ using size_type = qsizetype;
+
+ QMultiMap() = default;
+
+ // implicitly generated special member functions are OK!
+
+ QMultiMap(std::initializer_list<std::pair<Key,T>> list)
+ {
+ for (auto &p : list)
+ insert(p.first, p.second);
}
- Node *z = d->createNode(akey, avalue, y, left);
- return iterator(z);
-}
-template <class Key, class T>
-typename QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const Key &akey, const T &avalue)
-{
- if (d->ref.isShared())
- return this->insert(akey, avalue);
-
- Q_ASSERT_X(isValidIterator(pos), "QMap::insert", "The specified const_iterator argument 'it' is invalid");
-
- if (pos == constEnd()) {
- // Hint is that the Node is larger than (or equal to) the largest value.
- Node *n = static_cast<Node *>(pos.i->left);
- if (n) {
- while (n->right)
- n = static_cast<Node *>(n->right);
-
- if (!qMapLessThanKey(n->key, akey))
- return this->insert(akey, avalue); // ignore hint
- // This can be optimized by checking equal too.
- // we can overwrite if previous node key is strictly smaller
- // (or there is no previous node)
-
- Node *z = d->createNode(akey, avalue, n, false); // insert right most
- return iterator(z);
- }
- return this->insert(akey, avalue);
- } else {
- // Hint indicates that the node should be less (or equal to) the hint given
- // but larger than the previous value.
- Node *next = const_cast<Node*>(pos.i);
- if (qMapLessThanKey(next->key, akey))
- return this->insert(akey, avalue); // ignore hint
-
- if (pos == constBegin()) {
- // There is no previous value
- // Maybe overwrite left most value
- if (!qMapLessThanKey(akey, next->key)) {
- next->value = avalue; // overwrite current iterator
- return iterator(next);
- }
- // insert left most.
- Node *z = d->createNode(akey, avalue, begin().i, true);
- return iterator(z);
- } else {
- Node *prev = const_cast<Node*>(pos.i->previousNode());
- if (!qMapLessThanKey(prev->key, akey)) {
- return this->insert(akey, avalue); // ignore hint
- }
- // Hint is ok
- if (!qMapLessThanKey(akey, next->key)) {
- next->value = avalue; // overwrite current iterator
- return iterator(next);
- }
+ void swap(QMultiMap<Key, T> &other) noexcept
+ {
+ d.swap(other.d);
+ }
- // we need to insert (not overwrite)
- if (prev->right == nullptr) {
- Node *z = d->createNode(akey, avalue, prev, false);
- return iterator(z);
- }
- if (next->left == nullptr) {
- Node *z = d->createNode(akey, avalue, next, true);
- return iterator(z);
- }
- Q_ASSERT(false); // We should have prev->right == nullptr or next->left == nullptr.
- return this->insert(akey, avalue);
+ explicit QMultiMap(const QMap<Key, T> &other)
+ : d(other.isEmpty() ? nullptr : new MapData)
+ {
+ if (d) {
+ Q_ASSERT(other.d);
+ d->m.insert(other.d->m.begin(),
+ other.d->m.end());
}
}
-}
-template <class Key, class T>
-Q_INLINE_TEMPLATE void QMap<Key, T>::insert(const QMap<Key, T> &map)
-{
- if (d == map.d)
- return;
-
- detach();
-
- Node *n = d->root();
- auto it = map.cbegin();
- const auto e = map.cend();
- while (it != e) {
- // Insertion here is based on insert(Key, T)
- auto parent = d->end();
- bool left = true;
- Node *lastNode = nullptr;
- while (n) {
- parent = n;
- if (!qMapLessThanKey(n->key, it.key())) {
- lastNode = n;
- n = n->leftNode();
- left = true;
+ explicit QMultiMap(QMap<Key, T> &&other)
+ : d(other.isEmpty() ? nullptr : new MapData)
+ {
+ if (d) {
+ Q_ASSERT(other.d);
+ if (other.d.isShared()) {
+ d->m.insert(other.d->m.begin(),
+ other.d->m.end());
} else {
- n = n->rightNode();
- left = false;
+#ifdef __cpp_lib_node_extract
+ d->m.merge(std::move(other.d->m));
+#else
+ d->m.insert(std::make_move_iterator(other.d->m.begin()),
+ std::make_move_iterator(other.d->m.end()));
+#endif
}
}
- if (lastNode && !qMapLessThanKey(it.key(), lastNode->key)) {
- lastNode->value = it.value();
- n = lastNode;
- } else {
- n = d->createNode(it.key(), it.value(), parent, left);
- }
- ++it;
- if (it != e) {
- // Move back up the tree until we find the next branch or node which is
- // relevant for the next key.
- while (n != d->root() && qMapLessThanKey(n->key, it.key()))
- n = static_cast<Node *>(n->parent());
+ }
+
+ explicit QMultiMap(const std::multimap<Key, T> &other)
+ : d(other.empty() ? nullptr : new MapData(other))
+ {
+ }
+
+ explicit QMultiMap(std::multimap<Key, T> &&other)
+ : d(other.empty() ? nullptr : new MapData(std::move(other)))
+ {
+ }
+
+ // CHANGE: return type
+ Q_DECL_DEPRECATED_X("Use toStdMultiMap instead")
+ std::multimap<Key, T> toStdMap() const
+ {
+ return toStdMultiMap();
+ }
+
+ std::multimap<Key, T> toStdMultiMap() const &
+ {
+ if (d)
+ return d->m;
+ return {};
+ }
+
+ std::multimap<Key, T> toStdMultiMap() &&
+ {
+ if (d) {
+ if (d.isShared())
+ return d->m;
+ else
+ return std::move(d->m);
}
+
+ return {};
}
-}
+#ifndef Q_QDOC
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> operator==(const QMultiMap &lhs, const QMultiMap &rhs)
+ {
+ if (lhs.d == rhs.d)
+ return true;
+ if (!lhs.d)
+ return rhs == lhs;
+ Q_ASSERT(lhs.d);
+ return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
+ }
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &akey) const
-{
- Node *n = d->findNode(akey);
- return const_iterator(n ? n : d->end());
-}
+ template <typename AKey = Key, typename AT = T> friend
+ QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> operator!=(const QMultiMap &lhs, const QMultiMap &rhs)
+ {
+ return !(lhs == rhs);
+ }
+ // TODO: add the other comparison operators; std::multimap has them.
+#else
+ friend bool operator==(const QMultiMap &lhs, const QMultiMap &rhs);
+ friend bool operator!=(const QMultiMap &lhs, const QMultiMap &rhs);
+#endif // Q_QDOC
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &akey) const
-{
- return constFind(akey);
-}
+ size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::find(const Key &akey)
-{
- detach();
- Node *n = d->findNode(akey);
- return iterator(n ? n : d->end());
-}
+ bool isEmpty() const { return d ? d->m.empty() : true; }
-template <class Key, class T>
-QPair<typename QMap<Key, T>::iterator, typename QMap<Key, T>::iterator> QMap<Key, T>::equal_range(const Key &akey)
-{
- detach();
- Node *firstNode, *lastNode;
- d->nodeRange(akey, &firstNode, &lastNode);
- return QPair<iterator, iterator>(iterator(firstNode), iterator(lastNode));
-}
+ void detach()
+ {
+ if (d)
+ d.detach();
+ else
+ d.reset(new MapData);
+ }
-template <class Key, class T>
-QPair<typename QMap<Key, T>::const_iterator, typename QMap<Key, T>::const_iterator>
-QMap<Key, T>::equal_range(const Key &akey) const
-{
- Node *firstNode, *lastNode;
- d->nodeRange(akey, &firstNode, &lastNode);
- return qMakePair(const_iterator(firstNode), const_iterator(lastNode));
-}
+ bool isDetached() const noexcept
+ {
+ return d ? !d.isShared() : false; // false makes little sense, but that's shared_null's behavior...
+ }
-#ifdef Q_MAP_DEBUG
-template <class Key, class T>
-void QMap<Key, T>::dump() const
-{
- const_iterator it = begin();
- qDebug("map dump:");
- while (it != end()) {
- const QMapNodeBase *n = it.i;
- int depth = 0;
- while (n && n != d->root()) {
- ++depth;
- n = n->parent();
- }
- QByteArray space(4*depth, ' ');
- qDebug() << space << (it.i->color() == Node::Red ? "Red " : "Black") << it.i << it.i->left << it.i->right
- << it.key() << it.value();
- ++it;
+ bool isSharedWith(const QMultiMap<Key, T> &other) const noexcept
+ {
+ return d == other.d; // also this makes little sense?
}
- qDebug("---------");
-}
-#endif
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE qsizetype QMap<Key, T>::remove(const Key &akey)
-{
- detach();
- qsizetype n = 0;
- while (Node *node = d->findNode(akey)) {
- d->deleteNode(node);
- ++n;
+ void clear()
+ {
+ if (!d)
+ return;
+
+ if (!d.isShared())
+ d->m.clear();
+ else
+ d.reset();
}
- return n;
-}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE T QMap<Key, T>::take(const Key &akey)
-{
- detach();
+ size_type remove(const Key &key)
+ {
+ if (!d)
+ return 0;
+
+ if (!d.isShared())
+ return size_type(d->m.erase(key));
+
+ MapData *newData = new MapData;
+ size_type result = newData->copyIfNotEquivalentTo(d->m, key);
- Node *node = d->findNode(akey);
- if (node) {
- T t = std::move(node->value);
- d->deleteNode(node);
- return t;
+ d.reset(newData);
+
+ return result;
}
- return T();
-}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterator it)
-{
- if (it == iterator(d->end()))
- return it;
+ size_type remove(const Key &key, const T &value)
+ {
+ if (!d)
+ return 0;
- Q_ASSERT_X(isValidIterator(const_iterator(it)), "QMap::erase", "The specified iterator argument 'it' is invalid");
+ // key and value may belong to this map. As such, we need to copy
+ // them to ensure they stay valid throughout the iteration below
+ // (which may destroy them)
+ const Key keyCopy = key;
+ const T valueCopy = value;
- if (d->ref.isShared()) {
- const_iterator oldBegin = constBegin();
- const_iterator old = const_iterator(it);
- qsizetype backStepsWithSameKey = 0;
+ // TODO: improve. Copy over only the elements not to be removed.
+ detach();
- while (old != oldBegin) {
- --old;
- if (qMapLessThanKey(old.key(), it.key()))
- break;
- ++backStepsWithSameKey;
- }
+ size_type result = 0;
+ const auto &keyCompare = d->m.key_comp();
- it = find(old.key()); // ensures detach
- Q_ASSERT_X(it != iterator(d->end()), "QMap::erase", "Unable to locate same key in erase after detach.");
+ auto i = d->m.find(keyCopy);
+ const auto e = d->m.end();
- while (backStepsWithSameKey > 0) {
- ++it;
- --backStepsWithSameKey;
+ while (i != e && !keyCompare(keyCopy, i->first)) {
+ if (i->second == valueCopy) {
+ i = d->m.erase(i);
+ ++result;
+ } else {
+ ++i;
+ }
}
+
+ return result;
}
- Node *n = it.i;
- ++it;
- d->deleteNode(n);
- return it;
-}
+ template <typename Predicate>
+ size_type removeIf(Predicate pred)
+ {
+ return QtPrivate::associative_erase_if(*this, pred);
+ }
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
-{
- QMapData<Key, T> *x = QMapData<Key, T>::create();
- if (d->header.left) {
- x->header.left = static_cast<Node *>(d->header.left)->copy(x);
- x->header.left->setParent(&x->header);
- }
- if (!d->ref.deref())
- d->destroy();
- d = x;
- d->recalcMostLeftNode();
-}
+ T take(const Key &key)
+ {
+ if (!d)
+ return T();
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys() const
-{
- QList<Key> res;
- res.reserve(size());
- const_iterator i = begin();
- while (i != end()) {
- res.append(i.key());
- ++i;
- }
- return res;
-}
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys(const T &avalue) const
-{
- QList<Key> res;
- const_iterator i = begin();
- while (i != end()) {
- if (i.value() == avalue)
- res.append(i.key());
- ++i;
- }
- return res;
-}
+ // TODO: improve. There is no need of copying all the
+ // elements (the one to be removed can be skipped).
+ detach();
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE Key QMap<Key, T>::key(const T &avalue, const Key &defaultKey) const
-{
- const_iterator i = begin();
- while (i != end()) {
- if (i.value() == avalue)
- return i.key();
- ++i;
+ auto i = d->m.find(key);
+ if (i != d->m.end()) {
+ T result(std::move(i->second));
+ d->m.erase(i);
+ return result;
+ }
+ return T();
}
- return defaultKey;
-}
+ bool contains(const Key &key) const
+ {
+ if (!d)
+ return false;
+ auto i = d->m.find(key);
+ return i != d->m.end();
+ }
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values() const
-{
- QList<T> res;
- res.reserve(size());
- const_iterator i = begin();
- while (i != end()) {
- res.append(i.value());
- ++i;
- }
- return res;
-}
+ bool contains(const Key &key, const T &value) const
+ {
+ return find(key, value) != end();
+ }
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::lowerBound(const Key &akey) const
-{
- Node *lb = d->root() ? d->root()->lowerBound(akey) : nullptr;
- if (!lb)
- lb = d->end();
- return const_iterator(lb);
-}
+ Key key(const T &value, const Key &defaultKey = Key()) const
+ {
+ if (!d)
+ return defaultKey;
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &akey)
-{
- detach();
- Node *lb = d->root() ? d->root()->lowerBound(akey) : nullptr;
- if (!lb)
- lb = d->end();
- return iterator(lb);
-}
+ return d->key(value, defaultKey);
+ }
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator
-QMap<Key, T>::upperBound(const Key &akey) const
-{
- Node *ub = d->root() ? d->root()->upperBound(akey) : nullptr;
- if (!ub)
- ub = d->end();
- return const_iterator(ub);
-}
+ T value(const Key &key, const T &defaultValue = T()) const
+ {
+ if (!d)
+ return defaultValue;
+ const auto i = d->m.find(key);
+ if (i != d->m.cend())
+ return i->second;
+ return defaultValue;
+ }
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &akey)
-{
- detach();
- Node *ub = d->root() ? d->root()->upperBound(akey) : nullptr;
- if (!ub)
- ub = d->end();
- return iterator(ub);
-}
+ QList<Key> keys() const
+ {
+ if (!d)
+ return {};
+ return d->keys();
+ }
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE bool QMap<Key, T>::operator==(const QMap<Key, T> &other) const
-{
- if (size() != other.size())
- return false;
- if (d == other.d)
- return true;
+ QList<Key> keys(const T &value) const
+ {
+ if (!d)
+ return {};
+ return d->keys(value);
+ }
- const_iterator it1 = begin();
- const_iterator it2 = other.begin();
+ QList<Key> uniqueKeys() const
+ {
+ QList<Key> result;
+ if (!d)
+ return result;
- while (it1 != end()) {
- if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key()))
- return false;
- ++it2;
- ++it1;
+ result.reserve(size());
+
+ std::unique_copy(keyBegin(), keyEnd(),
+ std::back_inserter(result));
+
+ result.shrink_to_fit();
+ return result;
}
- return true;
-}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other)
-{
- d = QMapData<Key, T>::create();
- typename std::map<Key,T>::const_iterator it = other.end();
- while (it != other.begin()) {
- --it;
- d->createNode((*it).first, (*it).second, d->begin(), true); // insert on most left node.
+ QList<T> values() const
+ {
+ if (!d)
+ return {};
+ return d->values();
}
-}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE std::map<Key, T> QMap<Key, T>::toStdMap() const
-{
- std::map<Key, T> map;
- const_iterator it = end();
- while (it != begin()) {
- --it;
- map.insert(map.begin(), std::pair<Key, T>(it.key(), it.value()));
+ QList<T> values(const Key &key) const
+ {
+ QList<T> result;
+ const auto range = equal_range(key);
+ result.reserve(std::distance(range.first, range.second));
+ std::copy(range.first, range.second, std::back_inserter(result));
+ return result;
}
- return map;
-}
-template <class Key, class T>
-class QMultiMap : public QMap<Key, T>
-{
-public:
- QMultiMap() noexcept {}
- inline QMultiMap(std::initializer_list<std::pair<Key,T> > list)
- {
- for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
- insert(it->first, it->second);
- }
- QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {}
- QMultiMap(QMap<Key, T> &&other) noexcept : QMap<Key, T>(std::move(other)) {}
- void swap(QMultiMap<Key, T> &other) noexcept { QMap<Key, T>::swap(other); }
-
- QList<Key> uniqueKeys() const;
- QList<T> values(const Key &key) const;
-
- inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value)
- { return QMap<Key, T>::insert(key, value); }
- typename QMap<Key, T>::iterator insert(const Key &key, const T &value);
- //! [qmultimap-insert-pos]
- typename QMap<Key, T>::iterator insert(typename QMap<Key, T>::const_iterator pos,
- const Key &key, const T &value);
-
- //! [qmultimap-unite]
- QMultiMap &unite(const QMultiMap &other);
- inline QMultiMap &operator+=(const QMultiMap &other)
- { return unite(other); }
- inline QMultiMap operator+(const QMultiMap &other) const
- { QMultiMap result = *this; result += other; return result; }
-
- using QMap<Key, T>::contains;
- using QMap<Key, T>::remove;
- using QMap<Key, T>::count;
- using QMap<Key, T>::find;
- using QMap<Key, T>::constFind;
- using QMap<Key, T>::values;
- using QMap<Key, T>::size;
- using QMap<Key, T>::detach;
- using QMap<Key, T>::erase;
- using QMap<Key, T>::isValidIterator;
- using typename QMap<Key, T>::Node;
-
- bool contains(const Key &key, const T &value) const;
-
- qsizetype remove(const Key &key, const T &value);
-
- qsizetype count(const Key &key, const T &value) const;
-
- typename QMap<Key, T>::iterator find(const Key &key, const T &value) {
- typename QMap<Key, T>::iterator i(find(key));
- typename QMap<Key, T>::iterator end(this->end());
- while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
- if (i.value() == value)
- return i;
+ size_type count(const Key &key) const
+ {
+ if (!d)
+ return 0;
+ return d->count(key);
+ }
+
+ size_type count(const Key &key, const T &value) const
+ {
+ if (!d)
+ return 0;
+
+ // TODO: improve; no need of scanning the equal_range twice.
+ auto range = d->m.equal_range(key);
+
+ return size_type(std::count_if(range.first,
+ range.second,
+ MapData::valueIsEqualTo(value)));
+ }
+
+ inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
+ inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return std::next(constEnd(), -1).key(); }
+
+ inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
+ inline T &last() { Q_ASSERT(!isEmpty()); return *std::next(end(), -1); }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return *std::next(constEnd(), -1); }
+
+ class const_iterator;
+
+ class iterator
+ {
+ friend class QMultiMap<Key, T>;
+ friend class const_iterator;
+
+ typename Map::iterator i;
+ explicit iterator(typename Map::iterator it) : i(it) {}
+ public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using difference_type = qptrdiff;
+ using value_type = T;
+ using pointer = T *;
+ using reference = T &;
+
+ iterator() = default;
+
+ const Key &key() const { return i->first; }
+ T &value() const { return i->second; }
+ T &operator*() const { return i->second; }
+ T *operator->() const { return &i->second; }
+ friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
+ friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
+
+ iterator &operator++()
+ {
++i;
+ return *this;
}
- return end;
- }
- typename QMap<Key, T>::const_iterator find(const Key &key, const T &value) const {
- typename QMap<Key, T>::const_iterator i(constFind(key));
- typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
- while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
- if (i.value() == value)
- return i;
+ iterator operator++(int)
+ {
+ iterator r = *this;
++i;
+ return r;
}
- return end;
- }
- typename QMap<Key, T>::const_iterator constFind(const Key &key, const T &value) const
- { return find(key, value); }
-private:
- T &operator[](const Key &key);
- const T operator[](const Key &key) const;
-};
-
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<Key> QMultiMap<Key, T>::uniqueKeys() const
-{
- QList<Key> res;
- res.reserve(size()); // May be too much, but assume short lifetime
- typename QMap<Key, T>::const_iterator i = this->begin();
- if (i != this->end()) {
- for (;;) {
- const Key &aKey = i.key();
- res.append(aKey);
- do {
- if (++i == this->end())
- goto break_out_of_outer_loop;
- } while (!qMapLessThanKey(aKey, i.key())); // loop while (key == i.key())
+ iterator &operator--()
+ {
+ --i;
+ return *this;
+ }
+ iterator operator--(int)
+ {
+ iterator r = *this;
+ --i;
+ return r;
}
- }
-break_out_of_outer_loop:
- return res;
-}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<T> QMultiMap<Key, T>::values(const Key &akey) const
-{
- QList<T> res;
- Node *n = this->d->findNode(akey);
- if (n) {
- typename QMap<Key, T>::const_iterator it(n);
- do {
- res.append(*it);
- ++it;
- } while (it != this->constEnd() && !qMapLessThanKey<Key>(akey, it.key()));
- }
- return res;
-}
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
+ //! [qmultimap-op-it-plus-step]
+ friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
-template <class Key, class T>
-Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMultiMap<Key, T>::insert(const Key &akey,
- const T &avalue)
-{
- detach();
- Node* y = this->d->end();
- Node* x = static_cast<Node *>(this->d->root());
- bool left = true;
- while (x != nullptr) {
- left = !qMapLessThanKey(x->key, akey);
- y = x;
- x = left ? x->leftNode() : x->rightNode();
- }
- Node *z = this->d->createNode(akey, avalue, y, left);
- return typename QMap<Key, T>::iterator(z);
-}
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
+ //! [qmultimap-op-it-minus-step]
+ friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
-#ifndef Q_CLANG_QDOC
-template <class Key, class T>
-typename QMap<Key, T>::iterator QMultiMap<Key, T>::insert(typename QMap<Key, T>::const_iterator pos,
- const Key &akey, const T &avalue)
-{
- if (this->d->ref.isShared())
- return insert(akey, avalue);
-
- Q_ASSERT_X(isValidIterator(pos), "QMap::insert", "The specified const_iterator argument 'pos' is invalid");
-
- if (pos == this->constEnd()) {
- // Hint is that the Node is larger than (or equal to) the largest value.
- Node *n = static_cast<Node *>(pos.i->left);
- if (n) {
- while (n->right)
- n = static_cast<Node *>(n->right);
-
- if (!qMapLessThanKey(n->key, akey))
- return insert(akey, avalue); // ignore hint
- Node *z = this->d->createNode(akey, avalue, n, false); // insert right most
- return typename QMap<Key, T>::iterator(z);
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
+ iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
+ iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
+ //! [qmultimap-op-step-plus-it]
+ friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
+ //! [qmultimap-op-step-minus-it]
+ friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
+#endif
+ };
+
+ class const_iterator
+ {
+ friend class QMultiMap<Key, T>;
+ typename Map::const_iterator i;
+ explicit const_iterator(typename Map::const_iterator it) : i(it) {}
+
+ public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using difference_type = qptrdiff;
+ using value_type = T;
+ using pointer = const T *;
+ using reference = const T &;
+
+ const_iterator() = default;
+ Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
+
+ const Key &key() const { return i->first; }
+ const T &value() const { return i->second; }
+ const T &operator*() const { return i->second; }
+ const T *operator->() const { return &i->second; }
+ friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
+ friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
+
+ const_iterator &operator++()
+ {
+ ++i;
+ return *this;
}
- return insert(akey, avalue);
- } else {
- // Hint indicates that the node should be less (or equal to) the hint given
- // but larger than the previous value.
- Node *next = const_cast<Node*>(pos.i);
- if (qMapLessThanKey(next->key, akey))
- return insert(akey, avalue); // ignore hint
-
- if (pos == this->constBegin()) {
- // There is no previous value (insert left most)
- Node *z = this->d->createNode(akey, avalue, this->begin().i, true);
- return typename QMap<Key, T>::iterator(z);
- } else {
- Node *prev = const_cast<Node*>(pos.i->previousNode());
- if (!qMapLessThanKey(prev->key, akey))
- return insert(akey, avalue); // ignore hint
-
- // Hint is ok - do insert
- if (prev->right == nullptr) {
- Node *z = this->d->createNode(akey, avalue, prev, false);
- return typename QMap<Key, T>::iterator(z);
- }
- if (next->left == nullptr) {
- Node *z = this->d->createNode(akey, avalue, next, true);
- return typename QMap<Key, T>::iterator(z);
- }
- Q_ASSERT(false); // We should have prev->right == nullptr or next->left == nullptr.
- return insert(akey, avalue);
+ const_iterator operator++(int)
+ {
+ const_iterator r = *this;
+ ++i;
+ return r;
+ }
+ const_iterator &operator--()
+ {
+ --i;
+ return *this;
}
+ const_iterator operator--(int)
+ {
+ const_iterator r = *this;
+ --i;
+ return r;
+ }
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
+ //! [qmultimap-op-it-plus-step-const]
+ friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
+ //! [qmultimap-op-it-minus-step-const]
+ friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
+ const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
+ const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
+ //! [qmultimap-op-step-plus-it-const]
+ friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
+
+ QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
+ //! [qmultimap-op-step-minus-it-const]
+ friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
+#endif
+ };
+
+ class key_iterator
+ {
+ const_iterator i;
+
+ public:
+ typedef typename const_iterator::iterator_category iterator_category;
+ typedef typename const_iterator::difference_type difference_type;
+ typedef Key value_type;
+ typedef const Key *pointer;
+ typedef const Key &reference;
+
+ key_iterator() = default;
+ explicit key_iterator(const_iterator o) : i(o) { }
+
+ const Key &operator*() const { return i.key(); }
+ const Key *operator->() const { return &i.key(); }
+ bool operator==(key_iterator o) const { return i == o.i; }
+ bool operator!=(key_iterator o) const { return i != o.i; }
+
+ inline key_iterator &operator++() { ++i; return *this; }
+ inline key_iterator operator++(int) { return key_iterator(i++);}
+ inline key_iterator &operator--() { --i; return *this; }
+ inline key_iterator operator--(int) { return key_iterator(i--); }
+ const_iterator base() const { return i; }
+ };
+
+ typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
+ typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
+
+ // STL style
+ iterator begin() { detach(); return iterator(d->m.begin()); }
+ const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
+ const_iterator constBegin() const { return begin(); }
+ const_iterator cbegin() const { return begin(); }
+ iterator end() { detach(); return iterator(d->m.end()); }
+ const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
+ const_iterator constEnd() const { return end(); }
+ const_iterator cend() const { return end(); }
+ key_iterator keyBegin() const { return key_iterator(begin()); }
+ key_iterator keyEnd() const { return key_iterator(end()); }
+ key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
+ key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
+ const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
+ const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
+ const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
+ const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
+ auto asKeyValueRange() & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange(*this); }
+ auto asKeyValueRange() && { return QtPrivate::QKeyValueRange(std::move(*this)); }
+ auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange(std::move(*this)); }
+
+ iterator erase(const_iterator it)
+ {
+ return erase(it, std::next(it));
}
-}
-template <class Key, class T>
-Q_INLINE_TEMPLATE QMultiMap<Key, T> &QMultiMap<Key, T>::unite(const QMultiMap<Key, T> &other)
-{
- QMultiMap<Key, T> copy(other);
- typename QMap<Key, T>::const_iterator it = copy.constEnd();
- const typename QMap<Key, T>::const_iterator b = copy.constBegin();
- while (it != b) {
- --it;
- insert(it.key(), it.value());
- }
- return *this;
-}
-#endif // Q_CLANG_QDOC
+ iterator erase(const_iterator afirst, const_iterator alast)
+ {
+ if (!d)
+ return iterator();
-template <class Key, class T>
-Q_INLINE_TEMPLATE bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const
-{
- return constFind(key, value) != QMap<Key, T>::constEnd();
-}
+ if (!d.isShared())
+ return iterator(d->m.erase(afirst.i, alast.i));
-template <class Key, class T>
-Q_INLINE_TEMPLATE qsizetype QMultiMap<Key, T>::remove(const Key &key, const T &value)
-{
- qsizetype n = 0;
- typename QMap<Key, T>::iterator i(find(key));
- typename QMap<Key, T>::iterator end(QMap<Key, T>::end());
- while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
- if (i.value() == value) {
- i = erase(i);
- ++n;
+ auto result = d->erase(afirst.i, alast.i);
+ d.reset(result.data);
+ return iterator(result.it);
+ }
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+
+ size_type count() const
+ {
+ return size();
+ }
+
+ iterator find(const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
+ detach();
+ return iterator(d->m.find(key));
+ }
+
+ const_iterator find(const Key &key) const
+ {
+ if (!d)
+ return const_iterator();
+ return const_iterator(d->m.find(key));
+ }
+
+ const_iterator constFind(const Key &key) const
+ {
+ return find(key);
+ }
+
+ iterator find(const Key &key, const T &value)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
+
+ detach();
+
+ auto range = d->m.equal_range(key);
+ auto i = std::find_if(range.first, range.second,
+ MapData::valueIsEqualTo(value));
+
+ if (i != range.second)
+ return iterator(i);
+ return iterator(d->m.end());
+ }
+
+ const_iterator find(const Key &key, const T &value) const
+ {
+ if (!d)
+ return const_iterator();
+
+ auto range = d->m.equal_range(key);
+ auto i = std::find_if(range.first, range.second,
+ MapData::valueIsEqualTo(value));
+
+ if (i != range.second)
+ return const_iterator(i);
+ return const_iterator(d->m.end());
+ }
+
+ const_iterator constFind(const Key &key, const T &value) const
+ {
+ return find(key, value);
+ }
+
+ iterator lowerBound(const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
+ detach();
+ return iterator(d->m.lower_bound(key));
+ }
+
+ const_iterator lowerBound(const Key &key) const
+ {
+ if (!d)
+ return const_iterator();
+ return const_iterator(d->m.lower_bound(key));
+ }
+
+ iterator upperBound(const Key &key)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
+ detach();
+ return iterator(d->m.upper_bound(key));
+ }
+
+ const_iterator upperBound(const Key &key) const
+ {
+ if (!d)
+ return const_iterator();
+ return const_iterator(d->m.upper_bound(key));
+ }
+
+ iterator insert(const Key &key, const T &value)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
+ detach();
+ // note that std::multimap inserts at the end of an equal_range for a key,
+ // QMultiMap at the beginning.
+ auto i = d->m.lower_bound(key);
+ return iterator(d->m.insert(i, {key, value}));
+ }
+
+ iterator insert(const_iterator pos, const Key &key, const T &value)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
+ typename Map::const_iterator dpos;
+ if (!d || d.isShared()) {
+ auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
+ detach();
+ dpos = std::next(d->m.cbegin(), posDistance);
} else {
- ++i;
+ dpos = pos.i;
}
+ return iterator(d->m.insert(dpos, {key, value}));
}
- return n;
-}
-template <class Key, class T>
-Q_INLINE_TEMPLATE qsizetype QMultiMap<Key, T>::count(const Key &key, const T &value) const
-{
- qsizetype n = 0;
- typename QMap<Key, T>::const_iterator i(constFind(key));
- typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
- while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
- if (i.value() == value)
- ++n;
- ++i;
- }
- return n;
-}
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
+ iterator insertMulti(const Key &key, const T &value)
+ {
+ return insert(key, value);
+ }
+ QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
+ iterator insertMulti(const_iterator pos, const Key &key, const T &value)
+ {
+ return insert(pos, key, value);
+ }
-#if QT_DEPRECATED_SINCE(5, 15)
-template<class Key, class T>
-QList<Key> QMap<Key, T>::uniqueKeys() const
-{
- return static_cast<const QMultiMap<Key, T> *>(this)->uniqueKeys();
-}
+ QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
+ void insert(const QMultiMap<Key, T> &map)
+ {
+ unite(map);
+ }
-template<class Key, class T>
-QList<T> QMap<Key, T>::values(const Key &key) const
-{
- return static_cast<const QMultiMap<Key, T> *>(this)->values(key);
-}
+ QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
+ void insert(QMultiMap<Key, T> &&map)
+ {
+ unite(std::move(map));
+ }
+#endif
+
+ iterator replace(const Key &key, const T &value)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
-template<class Key, class T>
-typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
+ // TODO: improve. No need of copying and then overwriting.
+ detach();
+
+ // Similarly, improve here (e.g. lower_bound and hinted insert);
+ // there's no insert_or_assign on multimaps
+ auto i = d->m.find(key);
+ if (i != d->m.end())
+ i->second = value;
+ else
+ i = d->m.insert({key, value});
+
+ return iterator(i);
+ }
+
+ // STL compatibility
+ inline bool empty() const { return isEmpty(); }
+
+ std::pair<iterator, iterator> equal_range(const Key &akey)
+ {
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
+ detach();
+ auto result = d->m.equal_range(akey);
+ return {iterator(result.first), iterator(result.second)};
+ }
+
+ std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
+ {
+ if (!d)
+ return {};
+ auto result = d->m.equal_range(akey);
+ return {const_iterator(result.first), const_iterator(result.second)};
+ }
+
+ QMultiMap &unite(const QMultiMap &other)
+ {
+ if (other.isEmpty())
+ return *this;
+
+ detach();
+
+ auto copy = other.d->m;
+#ifdef __cpp_lib_node_extract
+ copy.merge(std::move(d->m));
+#else
+ copy.insert(std::make_move_iterator(d->m.begin()),
+ std::make_move_iterator(d->m.end()));
+#endif
+ d->m = std::move(copy);
+ return *this;
+ }
+
+ QMultiMap &unite(QMultiMap<Key, T> &&other)
+ {
+ if (!other.d || other.d->m.empty())
+ return *this;
+
+ if (other.d.isShared()) {
+ // fall back to a regular copy
+ unite(other);
+ return *this;
+ }
+
+ detach();
+
+#ifdef __cpp_lib_node_extract
+ other.d->m.merge(std::move(d->m));
+#else
+ other.d->m.insert(std::make_move_iterator(d->m.begin()),
+ std::make_move_iterator(d->m.end()));
+#endif
+ *this = std::move(other);
+ return *this;
+ }
+};
+
+Q_DECLARE_ASSOCIATIVE_ITERATOR(MultiMap)
+Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(MultiMap)
+
+template <typename Key, typename T>
+QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
{
- return static_cast<QMultiMap<Key, T> *>(this)->insert(key, value);
+ auto result = lhs;
+ result += rhs;
+ return result;
}
-template<class Key, class T>
-typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const_iterator pos, const Key &akey, const T &avalue)
+template <typename Key, typename T>
+QMultiMap<Key, T> operator+=(QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
{
- return static_cast<QMultiMap<Key, T> *>(this)->insert(pos, akey, avalue);
+ return lhs.unite(rhs);
}
-template<class Key, class T>
-QMap<Key, T> &QMap<Key, T>::unite(const QMap<Key, T> &other)
+template <typename Key, typename T, typename Predicate>
+qsizetype erase_if(QMultiMap<Key, T> &map, Predicate pred)
{
- return static_cast<QMultiMap<Key, T> *>(this)->unite(other);
+ return QtPrivate::associative_erase_if(map, pred);
}
-#endif
-
-Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
-Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmap.qdoc b/src/corelib/tools/qmap.qdoc
new file mode 100644
index 0000000000..0cabf3df38
--- /dev/null
+++ b/src/corelib/tools/qmap.qdoc
@@ -0,0 +1,1400 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \class QMap
+ \inmodule QtCore
+ \brief The QMap class is a template class that provides an associative array.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QMap\<Key, T\> is one of Qt's generic \l{container classes}. It
+ stores (key, value) pairs and provides fast lookup by key.
+
+ QMap and QHash provide very similar functionality. The
+ differences are:
+
+ \list
+ \li QHash provides average faster lookups than QMap. (See \l{Algorithmic
+ Complexity} for details.)
+ \li When iterating over a QHash, the items are arbitrarily ordered.
+ With QMap, the items are always sorted by key.
+ \li The key type of a QHash must provide operator==() and a global
+ qHash(Key) function. The key type of a QMap must provide
+ operator<() specifying a total order. Since Qt 5.8.1 it is also safe
+ to use a pointer type as key, even if the underlying operator<()
+ does not provide a total order.
+ \endlist
+
+ Here's an example QMap with QString keys and \c int values:
+ \snippet code/src_corelib_tools_qmap.cpp 0
+
+ To insert a (key, value) pair into the map, you can use operator[]():
+
+ \snippet code/src_corelib_tools_qmap.cpp 1
+
+ This inserts the following three (key, value) pairs into the
+ QMap: ("one", 1), ("three", 3), and ("seven", 7). Another way to
+ insert items into the map is to use insert():
+
+ \snippet code/src_corelib_tools_qmap.cpp 2
+
+ To look up a value, use operator[]() or value():
+
+ \snippet code/src_corelib_tools_qmap.cpp 3
+
+ If there is no item with the specified key in the map, these
+ functions return a \l{default-constructed value}.
+
+ If you want to check whether the map contains a certain key, use
+ contains():
+
+ \snippet code/src_corelib_tools_qmap.cpp 4
+
+ There is also a value() overload that uses its second argument as
+ a default value if there is no item with the specified key:
+
+ \snippet code/src_corelib_tools_qmap.cpp 5
+
+ In general, we recommend that you use contains() and value()
+ rather than operator[]() for looking up a key in a map. The
+ reason is that operator[]() silently inserts an item into the
+ map if no item exists with the same key (unless the map is
+ const). For example, the following code snippet will create 1000
+ items in memory:
+
+ \snippet code/src_corelib_tools_qmap.cpp 6
+
+ To avoid this problem, replace \c map[i] with \c map.value(i)
+ in the code above.
+
+ If you want to navigate through all the (key, value) pairs stored
+ in a QMap, you can use an iterator. QMap provides both
+ \l{Java-style iterators} (QMapIterator and QMutableMapIterator)
+ and \l{STL-style iterators} (QMap::const_iterator and
+ QMap::iterator). Here's how to iterate over a QMap<QString, int>
+ using a Java-style iterator:
+
+ \snippet code/src_corelib_tools_qmap.cpp 7
+
+ Here's the same code, but using an STL-style iterator this time:
+
+ \snippet code/src_corelib_tools_qmap.cpp 8
+
+ The items are traversed in ascending key order.
+
+ A QMap allows only one value per key. If you call
+ insert() with a key that already exists in the QMap, the
+ previous value will be erased. For example:
+
+ \snippet code/src_corelib_tools_qmap.cpp 9
+
+ However, you can store multiple values per key by using
+ QMultiMap.
+
+ If you only need to extract the values from a map (not the keys),
+ you can also use range-based for:
+
+ \snippet code/src_corelib_tools_qmap.cpp 12
+
+ Items can be removed from the map in several ways. One way is to
+ call remove(); this will remove any item with the given key.
+ Another way is to use QMutableMapIterator::remove(). In addition,
+ you can clear the entire map using clear().
+
+ QMap's key and value data types must be \l{assignable data
+ types}. This covers most data types you are likely to encounter,
+ but the compiler won't let you, for example, store a QWidget as a
+ value; instead, store a QWidget *. In addition, QMap's key type
+ must provide operator<(). QMap uses it to keep its items sorted,
+ and assumes that two keys \c x and \c y are equivalent if neither \c{x
+ < y} nor \c{y < x} is true.
+
+ Example:
+ \snippet code/src_corelib_tools_qmap.cpp 13
+
+ In the example, we start by comparing the employees' names. If
+ they're equal, we compare their dates of birth to break the tie.
+
+ \sa QMapIterator, QMutableMapIterator, QHash, QSet
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::QMap()
+
+ Constructs an empty map.
+
+ \sa clear()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::QMap(const QMap<Key, T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation occurs in \l{constant time}, because QMap is
+ \l{implicitly shared}. This makes returning a QMap from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and this takes \l{linear time}.
+
+ \sa operator=
+*/
+
+/*!
+ \fn template <class Key, class T> QMap<Key, T>::QMap(QMap<Key, T> &&other)
+
+ Move-constructs a QMap instance.
+
+ \since 5.2
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other)
+
+ Assigns \a other to this map and returns a reference to this map.
+*/
+
+/*!
+ \fn template <class Key, class T> QMap<Key, T> &QMap<Key, T>::operator=(QMap<Key, T> &&other)
+
+ Move-assigns \a other to this QMap instance.
+
+ \since 5.2
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::~QMap()
+
+ Destroys the map. References to the values in the map, and all
+ iterators over this map, become invalid.
+*/
+
+/*! \fn template <class Key, class T> void QMap<Key, T>::swap(QMap<Key, T> &other) noexcept
+ \since 4.8
+
+ Swaps map \a other with this map. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::QMap(std::initializer_list<std::pair<Key,T> > list)
+ \since 5.1
+
+ Constructs a map with a copy of each of the elements in the
+ initializer list \a list.
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::QMap(const std::map<Key, T> & other)
+
+ Constructs a copy of \a other.
+
+ \sa toStdMap()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::QMap(std::map<Key, T> && other)
+
+ Constructs a map by moving from \a other.
+
+ \sa toStdMap()
+*/
+
+/*! \fn template <class Key, class T> std::map<Key, T> QMap<Key, T>::toStdMap() const &
+
+ Returns an STL map equivalent to this QMap.
+*/
+
+/*! \fn template <class Key, class T> std::map<Key, T> QMap<Key, T>::toStdMap() &&
+
+ \overload
+ \since 6.0
+
+ \note Calling this function will leave this QMap in the partially-formed state, in which
+ the only valid operations are destruction or assignment of a new value.
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::operator==(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs)
+
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns
+ false.
+
+ Two maps are considered equal if they contain the same (key,
+ value) pairs.
+
+ This function requires the key and the value types to implement \c
+ operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::operator!=(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs)
+
+ Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
+ false.
+
+ Two maps are considered equal if they contain the same (key,
+ value) pairs.
+
+ This function requires the key and the value types to implement \c
+ operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn template <class Key, class T> size_type QMap<Key, T>::size() const
+
+ Returns the number of (key, value) pairs in the map.
+
+ \sa isEmpty(), count()
+*/
+
+/*!
+ \fn template <class Key, class T> bool QMap<Key, T>::isEmpty() const
+
+ Returns \c true if the map contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn template <class Key, class T> void QMap<Key, T>::detach()
+
+ \internal
+
+ Detaches this map from any other maps with which it may share
+ data.
+
+ \sa isDetached()
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::isDetached() const
+
+ \internal
+
+ Returns \c true if the map's internal data isn't shared with any
+ other map object; otherwise returns \c false.
+
+ \sa detach()
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::isSharedWith(const QMap<Key, T> &other) const
+
+ \internal
+*/
+
+/*! \fn template <class Key, class T> void QMap<Key, T>::clear()
+
+ Removes all items from the map.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> size_type QMap<Key, T>::remove(const Key &key)
+
+ Removes all the items that have the key \a key from the map.
+ Returns the number of items removed which will be 1 if the key
+ exists in the map, and 0 otherwise.
+
+ \sa clear(), take()
+*/
+
+/*! \fn template <class Key, class T> template <typename Predicate> size_type QMap<Key, T>::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the map.
+
+ The function supports predicates which take either an argument of
+ type \c{QMap<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+
+ \sa clear(), take()
+*/
+
+/*! \fn template <class Key, class T> T QMap<Key, T>::take(const Key &key)
+
+ Removes the item with the key \a key from the map and returns
+ the value associated with it.
+
+ If the item does not exist in the map, the function simply
+ returns a \l{default-constructed value}.
+
+ If you don't use the return value, remove() is more efficient.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::contains(const Key &key) const
+
+ Returns \c true if the map contains an item with key \a key;
+ otherwise returns \c false.
+
+ \sa count()
+*/
+
+/*!
+ \fn template <class Key, class T> Key QMap<Key, T>::key(const T &value, const Key &defaultKey) const
+ \since 4.3
+ \overload
+
+ Returns the first key with value \a value, or \a defaultKey if
+ the map contains no item with value \a value. If no \a defaultKey
+ is provided the function returns a
+ \l{default-constructed value}{default-constructed key}.
+
+ This function can be slow (\l{linear time}), because QMap's
+ internal data structure is optimized for fast lookup by key, not
+ by value.
+
+ \sa value(), keys()
+*/
+
+/*! \fn template <class Key, class T> T QMap<Key, T>::value(const Key &key, const T &defaultValue) const
+
+ Returns the value associated with the key \a key.
+
+ If the map contains no item with key \a key, the function returns
+ \a defaultValue. If no \a defaultValue is specified, the function
+ returns a \l{default-constructed value}.
+
+ \sa key(), values(), contains(), operator[]()
+*/
+
+/*! \fn template <class Key, class T> T &QMap<Key, T>::operator[](const Key &key)
+
+ Returns the value associated with the key \a key as a modifiable
+ reference.
+
+ If the map contains no item with key \a key, the function inserts
+ a \l{default-constructed value} into the map with key \a key, and
+ returns a reference to it.
+
+ \sa insert(), value()
+*/
+
+/*! \fn template <class Key, class T> T QMap<Key, T>::operator[](const Key &key) const
+
+ \overload
+
+ Same as value().
+*/
+
+/*! \fn template <class Key, class T> QList<Key> QMap<Key, T>::keys() const
+
+ Returns a list containing all the keys in the map in ascending
+ order.
+
+ The order is guaranteed to be the same as that used by values().
+
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyBegin() to
+ \l keyEnd().
+
+ \sa values(), key()
+*/
+
+/*! \fn template <class Key, class T> QList<Key> QMap<Key, T>::keys(const T &value) const
+
+ \overload
+
+ Returns a list containing all the keys associated with value \a
+ value in ascending order.
+
+ This function can be slow (\l{linear time}), because QMap's
+ internal data structure is optimized for fast lookup by key, not
+ by value.
+*/
+
+/*! \fn template <class Key, class T> QList<T> QMap<Key, T>::values() const
+
+ Returns a list containing all the values in the map, in ascending
+ order of their keys.
+
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyValueBegin() to
+ \l keyValueEnd().
+
+ \sa keys(), value()
+*/
+
+/*! \fn template <class Key, class T> size_type QMap<Key, T>::count(const Key &key) const
+
+ Returns the number of items associated with key \a key.
+
+ \sa contains()
+*/
+
+/*! \fn template <class Key, class T> size_type QMap<Key, T>::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn template <class Key, class T> const Key &QMap<Key, T>::firstKey() const
+ \since 5.2
+
+ Returns a reference to the smallest key in the map.
+ This function assumes that the map is not empty.
+
+ This executes in \l{constant time}.
+
+ \sa lastKey(), first(), keyBegin(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> const Key &QMap<Key, T>::lastKey() const
+ \since 5.2
+
+ Returns a reference to the largest key in the map.
+ This function assumes that the map is not empty.
+
+ This executes in \l{logarithmic time}.
+
+ \sa firstKey(), last(), keyEnd(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> T &QMap<Key, T>::first()
+ \since 5.2
+
+ Returns a reference to the first value in the map, that is the value mapped
+ to the smallest key. This function assumes that the map is not empty.
+
+ When unshared (or const version is called), this executes in \l{constant time}.
+
+ \sa last(), firstKey(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> const T &QMap<Key, T>::first() const
+ \since 5.2
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> T &QMap<Key, T>::last()
+ \since 5.2
+
+ Returns a reference to the last value in the map, that is the value mapped
+ to the largest key. This function assumes that the map is not empty.
+
+ When unshared (or const version is called), this executes in \l{logarithmic time}.
+
+ \sa first(), lastKey(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> const T &QMap<Key, T>::last() const
+ \since 5.2
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::begin()
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
+ the map.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::begin() const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::cbegin() const
+ \since 5.0
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
+ in the map.
+
+ \sa begin(), cend()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::constBegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
+ in the map.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::keyBegin() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key
+ in the map.
+
+ \sa keyEnd(), firstKey()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::end()
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
+ after the last item in the map.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::end() const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::cend() const
+ \since 5.0
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last item in the map.
+
+ \sa cbegin(), end()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::constEnd() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last item in the map.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::keyEnd() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last key in the map.
+
+ \sa keyBegin(), lastKey()
+*/
+
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_value_iterator QMap<Key, T>::keyValueBegin()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the map.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_value_iterator QMap<Key, T>::keyValueEnd()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::keyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the map.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::constKeyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::keyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_key_value_iterator QMap<Key, T>::constKeyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the map.
+
+ \sa constKeyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> auto QMap<Key, T>::asKeyValueRange() &
+ \fn template <class Key, class T> auto QMap<Key, T>::asKeyValueRange() const &
+ \fn template <class Key, class T> auto QMap<Key, T>::asKeyValueRange() &&
+ \fn template <class Key, class T> auto QMap<Key, T>::asKeyValueRange() const &&
+ \since 6.4
+
+ Returns a range object that allows iteration over this map as
+ key/value pairs. For instance, this range object can be used in a
+ range-based for loop, in combination with a structured binding declaration:
+
+ \snippet code/src_corelib_tools_qmap.cpp 28
+
+ Note that both the key and the value obtained this way are
+ references to the ones in the map. Specifically, mutating the value
+ will modify the map itself.
+
+ \sa QKeyValueIterator
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::erase(const_iterator pos)
+
+ Removes the (key, value) pair pointed to by the iterator \a pos
+ from the map, and returns an iterator to the next item in the
+ map.
+
+ \note The iterator \a pos \e must be valid and dereferenceable.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::erase(const_iterator first, const_iterator last)
+ \since 6.0
+
+ Removes the (key, value) pairs pointed to by the iterator range
+ [\a first, \a last) from the map.
+ Returns an iterator to the item in the map following the last removed element.
+
+ \note The range \c {[first, last)} \e must be a valid range in \c {*this}.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::find(const Key &key)
+
+ Returns an iterator pointing to the item with key \a key in the
+ map.
+
+ If the map contains no item with key \a key, the function
+ returns end().
+
+ \sa constFind(), value(), values(), lowerBound(), upperBound()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &key) const
+ \since 4.1
+
+ Returns an const iterator pointing to the item with key \a key in the
+ map.
+
+ If the map contains no item with key \a key, the function
+ returns constEnd().
+
+ \sa find()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &key)
+
+ Returns an iterator pointing to the first item with key \a key in
+ the map. If the map contains no item with key \a key, the
+ function returns an iterator to the nearest item with a greater
+ key.
+
+ \sa upperBound(), find()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::lowerBound(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &key)
+
+ Returns an iterator pointing to the item that immediately follows
+ the last item with key \a key in the map. If the map contains no
+ item with key \a key, the function returns an iterator to the
+ nearest item with a greater key.
+
+ Example:
+ \snippet code/src_corelib_tools_qmap.cpp 17
+
+ \sa lowerBound(), find()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::upperBound(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &key, const T &value)
+
+ Inserts a new item with the key \a key and a value of \a value.
+
+ If there is already an item with the key \a key, that item's value
+ is replaced with \a value.
+
+ Returns an iterator pointing to the new/updated element.
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const Key &key, const T &value)
+ \overload
+ \since 5.1
+ Inserts a new item with the key \a key and value \a value and with hint \a pos
+ suggesting where to do the insert.
+
+ If constBegin() is used as hint it indicates that the \a key is less than any key in the map
+ while constEnd() suggests that the \a key is (strictly) larger than any key in the map.
+ Otherwise the hint should meet the condition (\a pos - 1).key() < \a key <= pos.key().
+ If the hint \a pos is wrong it is ignored and a regular insert is done.
+
+ If there is already an item with the key \a key, that item's value
+ is replaced with \a value.
+
+ If the hint is correct and the map is unshared, the insert executes in amortized \l{constant time}.
+
+ When creating a map from sorted data inserting the largest key first with constBegin()
+ is faster than inserting in sorted order with constEnd(), since constEnd() - 1 (which is needed
+ to check if the hint is valid) needs \l{logarithmic time}.
+
+ \b {Note:} Be careful with the hint. Providing an iterator from an older shared instance might
+ crash but there is also a risk that it will silently corrupt both the map and the \a pos map.
+
+ Returns an iterator pointing to the new/updated element.
+*/
+
+/*! \fn template <class Key, class T> void QMap<Key, T>::insert(const QMap<Key, T> &map)
+ \since 5.15
+
+ Inserts all the items in \a map into this map.
+
+ If a key is common to both maps, its value will be replaced with
+ the value stored in \a map.
+*/
+
+/*! \fn template <class Key, class T> void QMap<Key, T>::insert(QMap<Key, T> &&map)
+ \since 5.15
+
+ Moves all the items from \a map into this map.
+
+ If a key is common to both maps, its value will be replaced with
+ the value stored in \a map.
+
+ If \a map is shared, then the items will be copied instead.
+*/
+
+/*! \typedef QMap::Iterator
+
+ Qt-style synonym for QMap::iterator.
+*/
+
+/*! \typedef QMap::ConstIterator
+
+ Qt-style synonym for QMap::const_iterator.
+*/
+
+/*! \typedef QMap::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \typedef QMap::key_type
+
+ Typedef for Key. Provided for STL compatibility.
+*/
+
+/*! \typedef QMap::mapped_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*! \typedef QMap::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \fn template <class Key, class T> bool QMap<Key, T>::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty(), returning true if the map is empty; otherwise
+ returning false.
+*/
+
+/*!
+ \fn template <class Key, class T> std::pair<typename QMap<Key, T>::iterator, typename QMap<Key, T>::iterator> QMap<Key, T>::equal_range(const Key &key)
+
+ Returns a pair of iterators delimiting the range of values \c{[first, second)}, that
+ are stored under \a key.
+*/
+
+/*!
+ \fn template <class Key, class T> std::pair<typename QMap<Key, T>::const_iterator, typename QMap<Key, T>::const_iterator> QMap<Key, T>::equal_range(const Key &key) const
+ \overload
+ \since 5.6
+*/
+
+
+/*! \class QMap::iterator
+ \inmodule QtCore
+ \brief The QMap::iterator class provides an STL-style non-const iterator for QMap.
+
+ QMap\<Key, T\>::iterator allows you to iterate over a QMap
+ and to modify the value (but not the key) stored under
+ a particular key. If you want to iterate over a const QMap, you
+ should use QMap::const_iterator. It is generally good practice to
+ use QMap::const_iterator on a non-const QMap as well, unless you
+ need to change the QMap through the iterator. Const iterators are
+ slightly faster, and can improve code readability.
+
+ The default QMap::iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QMap function like
+ QMap::begin(), QMap::end(), or QMap::find() before you can
+ start iterating. Here's a typical loop that prints all the (key,
+ value) pairs stored in a map:
+
+ \snippet code/src_corelib_tools_qmap.cpp 18
+
+ Unlike QHash, which stores its items in an arbitrary order, QMap
+ stores its items ordered by key.
+
+ Here's an example that increments every value stored in the QMap
+ by 2:
+
+ \snippet code/src_corelib_tools_qmap.cpp 19
+
+ To remove elements from a QMap you can use erase_if(QMap\<Key, T\> &map, Predicate pred):
+
+ \snippet code/src_corelib_tools_qmap.cpp 21
+
+ Multiple iterators can be used on the same map. If you add items
+ to the map, existing iterators will remain valid. If you remove
+ items from the map, iterators that point to the removed items
+ will become dangling iterators.
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+
+ \sa QMap::const_iterator, QMap::key_iterator, QMap::key_value_iterator
+*/
+
+/*! \typedef QMap::iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QMap::iterator::iterator_category
+
+ A synonym for \e {std::bidirectional_iterator_tag} indicating
+ this iterator is a bidirectional iterator.
+*/
+
+/*! \typedef QMap::iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QMap::iterator::reference
+
+ \internal
+*/
+
+/*! \typedef QMap::iterator::value_type
+
+ \internal
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator::iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like key(), value(), and operator++() must not be
+ called on an uninitialized iterator. Use operator=() to assign a
+ value to it before using it.
+
+ \sa QMap::begin(), QMap::end()
+*/
+
+/*! \fn template <class Key, class T> const Key &QMap<Key, T>::iterator::key() const
+
+ Returns the current item's key as a const reference.
+
+ There is no direct way of changing an item's key through an
+ iterator, although it can be done by calling QMap::erase()
+ followed by QMap::insert().
+
+ \sa value()
+*/
+
+/*! \fn template <class Key, class T> T &QMap<Key, T>::iterator::value() const
+
+ Returns a modifiable reference to the current item's value.
+
+ You can change the value of an item by using value() on
+ the left side of an assignment, for example:
+
+ \snippet code/src_corelib_tools_qmap.cpp 23
+
+ \sa key(), operator*()
+*/
+
+/*! \fn template <class Key, class T> T &QMap<Key, T>::iterator::operator*() const
+
+ Returns a modifiable reference to the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn template <class Key, class T> T *QMap<Key, T>::iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*!
+ \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
+
+ Returns \c true if \a lhs points to the same item as the \a rhs iterator;
+ otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn template <class Key, class T> bool QMap<Key, T>::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn template <class Key, class T> bool QMap<Key, T>::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
+
+ Returns \c true if \a lhs points to a different item than the \a rhs iterator;
+ otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator &QMap<Key, T>::iterator::operator++()
+
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
+ next item in the map and returns an iterator to the new current
+ item.
+
+ Calling this function on QMap::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
+ next item in the map and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator &QMap<Key, T>::iterator::operator--()
+
+ The prefix \c{--} operator (\c{--i}) makes the preceding item
+ current and returns an iterator pointing to the new current item.
+
+ Calling this function on QMap::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{i--}) makes the preceding item
+ current and returns an iterator pointing to the previously
+ current item.
+*/
+
+/*! //! friends
+ \fn [qmap-op-it-plus-step] template <class Key, class T> typename QMap<Key, T>::iterator QMap<Key, T>::iterator::operator+(QMap<Key, T>::iterator, difference_type n)
+ \fn [qmap-op-step-plus-it] template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator+(difference_type n, QMap<Key, T>::iterator)
+ \fn [qmap-op-it-minus-step] template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator-(QMap<Key, T>::iterator, difference_type n)
+ \fn [qmap-op-step-minus-it] template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::iterator::operator-(difference_type n, QMap<Key, T>::iterator)
+
+ //! members
+ \fn template <class Key, class T> typename QMap<Key, T>::iterator QMap<Key, T>::iterator::operator+=(QMap<Key, T>::iterator::difference_type n)
+ \fn template <class Key, class T> typename QMap<Key, T>::iterator QMap<Key, T>::iterator::operator-=(QMap<Key, T>::iterator::difference_type n)
+
+ \deprecated [6.2] Use \c{std::next}, \c{std::prev} or \c{std::advance} instead.
+
+ Moves an iterator by \e{n} positions. These operations can be
+ expensive for large values of \e{n}; QMap iterators are not
+ random access.
+*/
+
+/*! \class QMap::const_iterator
+ \inmodule QtCore
+ \brief The QMap::const_iterator class provides an STL-style const iterator for QMap.
+
+ QMap\<Key, T\>::const_iterator allows you to iterate over a QMap.
+ If you want to modify the QMap as you iterate
+ over it, you must use QMap::iterator instead. It is generally
+ good practice to use QMap::const_iterator on a non-const QMap as
+ well, unless you need to change the QMap through the iterator.
+ Const iterators are slightly faster, and can improve code
+ readability.
+
+ The default QMap::const_iterator constructor creates an
+ uninitialized iterator. You must initialize it using a QMap
+ function like QMap::cbegin(), QMap::cend(), or
+ QMap::constFind() before you can start iterating. Here's a typical
+ loop that prints all the (key, value) pairs stored in a map:
+
+ \snippet code/src_corelib_tools_qmap.cpp 24
+
+ Here's an example that removes all the items whose value is greater than 10:
+
+ \snippet code/src_corelib_tools_qmap.cpp 20
+
+ And here the same behavior with erase_if()
+
+ \snippet code/src_corelib_tools_qmap.cpp 21
+
+ Unlike QHash, which stores its items in an arbitrary order, QMap
+ stores its items ordered by key.
+
+ Multiple iterators can be used on the same map. If you add items
+ to the map, existing iterators will remain valid. If you remove
+ items from the map, iterators that point to the removed items
+ will become dangling iterators.
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+
+ \sa QMap::iterator, QMap::key_iterator, QMap::const_key_value_iterator
+*/
+
+/*! \typedef QMap::const_iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QMap::const_iterator::iterator_category
+
+ A synonym for \e {std::bidirectional_iterator_tag} indicating
+ this iterator is a bidirectional iterator.
+*/
+
+/*! \typedef QMap::const_iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QMap::const_iterator::reference
+
+ \internal
+*/
+
+/*! \typedef QMap::const_iterator::value_type
+
+ \internal
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like key(), value(), and operator++() must not be
+ called on an uninitialized iterator. Use operator=() to assign a
+ value to it before using it.
+
+ \sa QMap::constBegin(), QMap::constEnd()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator::const_iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn template <class Key, class T> const Key &QMap<Key, T>::const_iterator::key() const
+
+ Returns the current item's key.
+
+ \sa value()
+*/
+
+/*! \fn template <class Key, class T> const T &QMap<Key, T>::const_iterator::value() const
+
+ Returns the current item's value.
+
+ \sa key(), operator*()
+*/
+
+/*! \fn template <class Key, class T> const T &QMap<Key, T>::const_iterator::operator*() const
+
+ Returns the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn template <class Key, class T> const T *QMap<Key, T>::const_iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator &QMap<Key, T>::const_iterator::operator++()
+
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
+ next item in the map and returns an iterator to the new current
+ item.
+
+ Calling this function on QMap::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
+ next item in the map and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator &QMap<Key, T>::const_iterator::operator--()
+
+ The prefix \c{--} operator (\c{--i}) makes the preceding item
+ current and returns an iterator pointing to the new current item.
+
+ Calling this function on QMap::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{i--}) makes the preceding item
+ current and returns an iterator pointing to the previously
+ current item.
+*/
+
+/*! //! friends
+ \fn [qmap-op-it-plus-step-const] template <class Key, class T> QMap<Key, T>::const_iterator::operator+(QMap<Key, T>::const_iterator, difference_type n)
+ \fn [qmap-op-step-plus-it-const] template <class Key, class T> QMap<Key, T>::operator+(difference_type n, QMap<Key, T>::const_iterator)
+ \fn [qmap-op-it-minus-step-const] template <class Key, class T> QMap<Key, T>::operator-(QMap<Key, T>::const_iterator, difference_type n)
+ \fn [qmap-op-step-minus-it-const] template <class Key, class T> QMap<Key, T>::operator-(difference_type n, QMap<Key, T>::const_iterator)
+
+ //! members
+ \fn template <class Key, class T> typename QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator+=(QMap<Key, T>::const_iterator::difference_type n)
+ \fn template <class Key, class T> typename QMap<Key, T>::const_iterator QMap<Key, T>::const_iterator::operator-=(QMap<Key, T>::const_iterator::difference_type n)
+
+ \deprecated [6.2] Use \c{std::next}, \c{std::prev} or \c{std::advance} instead.
+
+ Moves an iterator by \e{n} positions. These operations can be
+ expensive for large values of \e{n}. QMap iterators are not
+ random access.
+*/
+
+/*! \class QMap::key_iterator
+ \inmodule QtCore
+ \since 5.6
+ \brief The QMap::key_iterator class provides an STL-style const iterator for QMap keys.
+
+ QMap::key_iterator is essentially the same as QMap::const_iterator
+ with the difference that operator*() and operator->() return a key
+ instead of a value.
+
+ For most uses QMap::iterator and QMap::const_iterator should be used,
+ you can easily access the key by calling QMap::iterator::key():
+
+ \snippet code/src_corelib_tools_qmap.cpp keyiterator1
+
+ However, to have interoperability between QMap's keys and STL-style
+ algorithms we need an iterator that dereferences to a key instead
+ of a value. With QMap::key_iterator we can apply an algorithm to a
+ range of keys without having to call QMap::keys(), which is inefficient
+ as it costs one QMap iteration and memory allocation to create a temporary
+ QList.
+
+ \snippet code/src_corelib_tools_qmap.cpp keyiterator2
+
+ QMap::key_iterator is const, it's not possible to modify the key.
+
+ The default QMap::key_iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QMap function like
+ QMap::keyBegin() or QMap::keyEnd().
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+
+ \sa QMap::const_iterator, QMap::iterator
+*/
+
+/*! \typedef QMap::key_iterator::difference_type
+ \internal
+*/
+
+/*! \typedef QMap::key_iterator::iterator_category
+ \internal
+*/
+
+/*! \typedef QMap::key_iterator::pointer
+ \internal
+*/
+
+/*! \typedef QMap::key_iterator::reference
+ \internal
+*/
+
+/*! \typedef QMap::key_iterator::value_type
+ \internal
+*/
+
+/*! \fn template <class Key, class T> const T &QMap<Key, T>::key_iterator::operator*() const
+
+ Returns the current item's key.
+*/
+
+/*! \fn template <class Key, class T> const T *QMap<Key, T>::key_iterator::operator->() const
+
+ Returns a pointer to the current item's key.
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::key_iterator::operator==(key_iterator other) const
+
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*! \fn template <class Key, class T> bool QMap<Key, T>::key_iterator::operator!=(key_iterator other) const
+
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn template <class Key, class T> QMap<Key, T>::key_iterator &QMap<Key, T>::key_iterator::operator++()
+
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
+ next item in the hash and returns an iterator to the new current
+ item.
+
+ Calling this function on QMap::keyEnd() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::key_iterator::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
+ next item in the hash and returns an iterator to the previous
+ item.
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator &QMap<Key, T>::key_iterator::operator--()
+
+ The prefix \c{--} operator (\c{--i}) makes the preceding item
+ current and returns an iterator pointing to the new current item.
+
+ Calling this function on QMap::keyBegin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn template <class Key, class T> QMap<Key, T>::key_iterator QMap<Key, T>::key_iterator::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{i--}) makes the preceding item
+ current and returns an iterator pointing to the previous
+ item.
+*/
+
+/*! \fn template <class Key, class T> const_iterator QMap<Key, T>::key_iterator::base() const
+ Returns the underlying const_iterator this key_iterator is based on.
+*/
+
+/*! \typedef QMap::const_key_value_iterator
+ \inmodule QtCore
+ \since 5.10
+ \brief The QMap::const_key_value_iterator typedef provides an STL-style iterator for QMap.
+
+ QMap::const_key_value_iterator is essentially the same as QMap::const_iterator
+ with the difference that operator*() returns a key/value pair instead of a
+ value.
+
+ \sa QKeyValueIterator
+*/
+
+/*! \typedef QMap::key_value_iterator
+ \inmodule QtCore
+ \since 5.10
+ \brief The QMap::key_value_iterator typedef provides an STL-style iterator for QMap.
+
+ QMap::key_value_iterator is essentially the same as QMap::iterator
+ with the difference that operator*() returns a key/value pair instead of a
+ value.
+
+ \sa QKeyValueIterator
+*/
+
+/*! \fn template <class Key, class T> QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
+ \relates QMap
+
+ Writes the map \a map to stream \a out.
+
+ This function requires the key and value types to implement \c
+ operator<<().
+
+ \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
+
+/*! \fn template <class Key, class T> QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map)
+ \relates QMap
+
+ Reads a map from stream \a in into \a map.
+
+ This function requires the key and value types to implement \c
+ operator>>().
+
+ \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
+
+/*! \fn template <typename Key, typename T, typename Predicate> qsizetype erase_if(QMap<Key, T> &map, Predicate pred)
+ \relates QMap
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the map \a map.
+
+ The function supports predicates which take either an argument of
+ type \c{QMap<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+*/
+
+/*!
+ \fn template <class Key, class T> size_t QMap<Key, T>::qHash(const QMap &key, size_t seed) noexcept
+ \since 6.8
+
+ Returns the hash value for \a key, using \a seed to seed the calculation.
+
+ Types \c Key and \c T must be supported by qHash().
+*/
diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp
index 2d7816e217..c4cd0da30d 100644
--- a/src/corelib/tools/qmargins.cpp
+++ b/src/corelib/tools/qmargins.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmargins.h"
#include "qdatastream.h"
@@ -50,9 +14,13 @@ QT_BEGIN_NAMESPACE
\ingroup painting
\since 4.6
+ \compares equality
+ \compareswith equality QMarginsF
+ \endcompareswith
+
\brief The QMargins class defines the four margins of a rectangle.
- QMargin defines a set of four margins; left, top, right and bottom,
+ QMargin defines a set of four margins; left, top, right, and bottom,
that describe the size of the borders surrounding a rectangle.
The isNull() function returns \c true only if all margins are set to zero.
@@ -76,7 +44,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QMargins::QMargins(int left, int top, int right, int bottom)
- Constructs margins with the given \a left, \a top, \a right, \a bottom
+ Constructs margins with the given \a left, \a top, \a right, and \a bottom
\sa setLeft(), setRight(), setTop(), setBottom()
*/
@@ -143,17 +111,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool operator==(const QMargins &m1, const QMargins &m2)
- \relates QMargins
+ \fn bool QMargins::operator==(const QMargins &lhs, const QMargins &rhs)
- Returns \c true if \a m1 and \a m2 are equal; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
*/
/*!
- \fn bool operator!=(const QMargins &m1, const QMargins &m2)
- \relates QMargins
+ \fn bool QMargins::operator!=(const QMargins &lhs, const QMargins &rhs)
- Returns \c true if \a m1 and \a m2 are different; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are different; otherwise returns \c false.
*/
/*!
@@ -315,7 +281,7 @@ QT_BEGIN_NAMESPACE
\relates QMargins
Returns a QMargins object that is formed from the maximum of each
- component of \a m2 and a m1.
+ component of \a m2 and \a m1.
\sa QMargins::operator+=(), QMargins::operator-=()
@@ -408,6 +374,15 @@ QT_BEGIN_NAMESPACE
\since 5.1
*/
+/*!
+ \fn QMargins::toMarginsF() const
+ \since 6.4
+
+ Returns these margins as margins with floating point accuracy.
+
+ \sa QMarginsF::toMargins()
+*/
+
/*****************************************************************************
QMargins stream functions
*****************************************************************************/
@@ -467,12 +442,16 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\ingroup painting
\since 5.3
+ \compares equality
+ \compareswith equality QMargins
+ \endcompareswith
+
\brief The QMarginsF class defines the four margins of a rectangle.
- QMarginsF defines a set of four margins; left, top, right and bottom,
- that describe the size of the borders surrounding a rectangle.
+ QMarginsF defines a set of four margins; left, top, right, and bottom,
+ that describe the finite size of the borders surrounding a rectangle.
- The isNull() function returns \c true only if all margins are set to zero.
+ The isNull() function returns \c true only if all margins are very close to zero.
QMarginsF objects can be streamed as well as compared.
*/
@@ -493,7 +472,8 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
\fn QMarginsF::QMarginsF(qreal left, qreal top, qreal right, qreal bottom)
- Constructs margins with the given \a left, \a top, \a right, \a bottom
+ Constructs margins with the given \a left, \a top, \a right, and \a bottom.
+ All parameters must be finite.
\sa setLeft(), setRight(), setTop(), setBottom()
*/
@@ -501,14 +481,18 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
\fn QMarginsF::QMarginsF(const QMargins &margins)
- Constructs margins copied from the given \a margins
+ Constructs margins copied from the given \a margins.
+
+ \sa QMargins::toMarginsF()
*/
/*!
\fn bool QMarginsF::isNull() const
- Returns \c true if all margins are 0; otherwise returns
+ Returns \c true if all margins are very close to 0; otherwise returns
false.
+
+ \sa {<QtNumeric>::}{qFuzzyIsNull()}
*/
@@ -542,41 +526,51 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
- \fn void QMarginsF::setLeft(qreal left)
+ \fn void QMarginsF::setLeft(qreal aleft)
- Sets the left margin to \a left.
+ Sets the left margin to \a aleft (which must be finite).
*/
/*!
- \fn void QMarginsF::setTop(qreal Top)
+ \fn void QMarginsF::setTop(qreal atop)
- Sets the Top margin to \a Top.
+ Sets the top margin to \a atop (which must be finite).
*/
/*!
- \fn void QMarginsF::setRight(qreal right)
+ \fn void QMarginsF::setRight(qreal aright)
- Sets the right margin to \a right.
+ Sets the right margin to \a aright (which must be finite).
*/
/*!
- \fn void QMarginsF::setBottom(qreal bottom)
+ \fn void QMarginsF::setBottom(qreal abottom)
- Sets the bottom margin to \a bottom.
+ Sets the bottom margin to \a abottom (which must be finite).
*/
/*!
- \fn bool operator==(const QMarginsF &lhs, const QMarginsF &rhs)
- \relates QMarginsF
+ \fn bool QMarginsF::operator==(const QMarginsF &lhs, const QMarginsF &rhs)
- Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are approximately equal; otherwise
+ returns false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the margins.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs)
- \relates QMarginsF
+ \fn bool QMarginsF::operator!=(const QMarginsF &lhs, const QMarginsF &rhs)
- Returns \c true if \a lhs and \a rhs are different; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are sufficiently different; otherwise
+ returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the margins.
+
+ \sa qFuzzyCompare
*/
/*!
@@ -603,8 +597,8 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\fn const QMarginsF operator+(const QMarginsF &lhs, qreal rhs)
\relates QMarginsF
- Returns a QMarginsF object that is formed by adding \a rhs to
- \a lhs.
+ Returns a QMarginsF object that is formed by adding \a rhs (which must be
+ finite) to each component of \a lhs.
\sa QMarginsF::operator+=(), QMarginsF::operator-=()
*/
@@ -613,8 +607,8 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\fn const QMarginsF operator+(qreal lhs, const QMarginsF &rhs)
\relates QMarginsF
- Returns a QMarginsF object that is formed by adding \a lhs to
- \a rhs.
+ Returns a QMarginsF object that is formed by adding \a lhs (which must be
+ finite) to each component of \a rhs.
\sa QMarginsF::operator+=(), QMarginsF::operator-=()
*/
@@ -623,8 +617,8 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\fn const QMarginsF operator-(const QMarginsF &lhs, qreal rhs)
\relates QMarginsF
- Returns a QMarginsF object that is formed by subtracting \a rhs from
- \a lhs.
+ Returns a QMarginsF object that is formed by subtracting \a rhs (which must
+ be finite) from each component of \a lhs.
\sa QMarginsF::operator+=(), QMarginsF::operator-=()
*/
@@ -635,7 +629,7 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\overload
Returns a QMarginsF object that is formed by multiplying each component
- of the given \a lhs margins by \a rhs factor.
+ of the given \a lhs margins by finite factor \a rhs.
\sa QMarginsF::operator*=(), QMarginsF::operator/=()
*/
@@ -646,7 +640,7 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\overload
Returns a QMarginsF object that is formed by multiplying each component
- of the given \a lhs margins by \a rhs factor.
+ of the given \a lhs margins by finite factor \a rhs.
\sa QMarginsF::operator*=(), QMarginsF::operator/=()
*/
@@ -659,16 +653,18 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
Returns a QMarginsF object that is formed by dividing the components of
the given \a lhs margins by the given \a rhs divisor.
+ The divisor must not be either zero or NaN.
+
\sa QMarginsF::operator*=(), QMarginsF::operator/=()
*/
/*!
- \fn QMargins operator|(const QMargins &m1, const QMargins &m2)
+ \fn QMarginsF operator|(const QMarginsF &m1, const QMarginsF &m2)
\relates QMarginsF
\overload
Returns a QMarginsF object that is formed from the maximum of each
- component of \a m2 and a m1.
+ component of \a m2 and \a m1.
\sa QMarginsF::operator+=(), QMarginsF::operator-=()
@@ -711,7 +707,7 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\fn QMarginsF &QMarginsF::operator+=(qreal addend)
\overload
- Adds the \a addend to each component of this object
+ Adds the given finite \a addend to each component of this object
and returns a reference to it.
\sa operator-=()
@@ -721,7 +717,7 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
\fn QMarginsF &QMarginsF::operator-=(qreal subtrahend)
\overload
- Subtracts the \a subtrahend from each component of this object
+ Subtracts the given finite \a subtrahend from each component of this object
and returns a reference to it.
\sa operator+=()
@@ -730,8 +726,8 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
\fn QMarginsF &QMarginsF::operator*=(qreal factor)
- Multiplies each component of this object by \a factor
- and returns a reference to it.
+ Multiplies each component of this object by the given finite \a factor
+ and returns a reference to this object.
\sa operator/=()
*/
@@ -739,8 +735,10 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
\fn QMarginsF &QMarginsF::operator/=(qreal divisor)
- Divides each component of this object by \a divisor
- and returns a reference to it.
+ Divides each component of this object by \a divisor and returns a reference
+ to this object.
+
+ The \a divisor must not be either zero or NaN.
\sa operator*=()
*/
@@ -748,12 +746,28 @@ QDebug operator<<(QDebug dbg, const QMargins &m)
/*!
\fn QMargins QMarginsF::toMargins() const
- Returns an integer based copy of this margins object.
+ Returns an integer-based copy of this margins object.
Note that the components in the returned margins will be rounded to
the nearest integer.
- \sa QMarginsF()
+ \sa QMarginsF(), QMargins::toMarginsF()
+*/
+
+/*!
+ \fn bool QMarginsF::qFuzzyCompare(const QMarginsF &lhs, const QMarginsF &rhs)
+ \since 6.8
+
+ Returns \c true if \a lhs is approximately equal to \a rhs;
+ otherwise returns \c false.
+*/
+
+/*!
+ \fn bool QMarginsF::qFuzzyIsNull(const QMarginsF &margins)
+ \since 6.8
+
+ Returns \c true if all components of margsins \a margins are
+ approximately equal to zero; otherwise returns \c false.
*/
/*****************************************************************************
diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h
index bc1fa3cb61..3b29860d66 100644
--- a/src/corelib/tools/qmargins.h
+++ b/src/corelib/tools/qmargins.h
@@ -1,49 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMARGINS_H
#define QMARGINS_H
+#include <QtCore/qcompare.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/q20type_traits.h>
+#include <QtCore/q23utility.h>
+
QT_BEGIN_NAMESPACE
+QT_ENABLE_P0846_SEMANTICS_FOR(get)
+
+class QMarginsF;
+
/*****************************************************************************
QMargins class
*****************************************************************************/
@@ -51,29 +23,31 @@ QT_BEGIN_NAMESPACE
class QMargins
{
public:
- Q_DECL_CONSTEXPR QMargins() noexcept;
- Q_DECL_CONSTEXPR QMargins(int left, int top, int right, int bottom) noexcept;
-
- Q_DECL_CONSTEXPR bool isNull() const noexcept;
-
- Q_DECL_CONSTEXPR int left() const noexcept;
- Q_DECL_CONSTEXPR int top() const noexcept;
- Q_DECL_CONSTEXPR int right() const noexcept;
- Q_DECL_CONSTEXPR int bottom() const noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR void setLeft(int left) noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setTop(int top) noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setRight(int right) noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setBottom(int bottom) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(const QMargins &margins) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(const QMargins &margins) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(int) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(int) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(int) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator/=(int);
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(qreal) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator/=(qreal);
+ constexpr QMargins() noexcept;
+ constexpr QMargins(int left, int top, int right, int bottom) noexcept;
+
+ constexpr bool isNull() const noexcept;
+
+ constexpr int left() const noexcept;
+ constexpr int top() const noexcept;
+ constexpr int right() const noexcept;
+ constexpr int bottom() const noexcept;
+
+ constexpr void setLeft(int left) noexcept;
+ constexpr void setTop(int top) noexcept;
+ constexpr void setRight(int right) noexcept;
+ constexpr void setBottom(int bottom) noexcept;
+
+ constexpr QMargins &operator+=(const QMargins &margins) noexcept;
+ constexpr QMargins &operator-=(const QMargins &margins) noexcept;
+ constexpr QMargins &operator+=(int) noexcept;
+ constexpr QMargins &operator-=(int) noexcept;
+ constexpr QMargins &operator*=(int) noexcept;
+ constexpr QMargins &operator/=(int);
+ constexpr QMargins &operator*=(qreal) noexcept;
+ constexpr QMargins &operator/=(qreal);
+
+ [[nodiscard]] constexpr inline QMarginsF toMarginsF() const noexcept;
private:
int m_left;
@@ -81,11 +55,33 @@ private:
int m_right;
int m_bottom;
- friend Q_DECL_CONSTEXPR inline bool operator==(const QMargins &, const QMargins &) noexcept;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &, const QMargins &) noexcept;
+ friend constexpr bool comparesEqual(const QMargins &lhs, const QMargins &rhs) noexcept
+ {
+ return lhs.m_left == rhs.m_left
+ && lhs.m_top == rhs.m_top
+ && lhs.m_right == rhs.m_right
+ && lhs.m_bottom == rhs.m_bottom;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QMargins)
+
+ template <std::size_t I,
+ typename M,
+ std::enable_if_t<(I < 4), bool> = true,
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<M>, QMargins>, bool> = true>
+ friend constexpr decltype(auto) get(M &&m) noexcept
+ {
+ if constexpr (I == 0)
+ return q23::forward_like<M>(m.m_left);
+ else if constexpr (I == 1)
+ return q23::forward_like<M>(m.m_top);
+ else if constexpr (I == 2)
+ return q23::forward_like<M>(m.m_right);
+ else if constexpr (I == 3)
+ return q23::forward_like<M>(m.m_bottom);
+ }
};
-Q_DECLARE_TYPEINFO(QMargins, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMargins, Q_RELOCATABLE_TYPE);
/*****************************************************************************
QMargins stream functions
@@ -99,140 +95,122 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QMargins &);
QMargins inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QMargins::QMargins() noexcept : m_left(0), m_top(0), m_right(0), m_bottom(0) {}
+constexpr inline QMargins::QMargins() noexcept : m_left(0), m_top(0), m_right(0), m_bottom(0) {}
-Q_DECL_CONSTEXPR inline QMargins::QMargins(int aleft, int atop, int aright, int abottom) noexcept
+constexpr inline QMargins::QMargins(int aleft, int atop, int aright, int abottom) noexcept
: m_left(aleft), m_top(atop), m_right(aright), m_bottom(abottom) {}
-Q_DECL_CONSTEXPR inline bool QMargins::isNull() const noexcept
+constexpr inline bool QMargins::isNull() const noexcept
{ return m_left==0 && m_top==0 && m_right==0 && m_bottom==0; }
-Q_DECL_CONSTEXPR inline int QMargins::left() const noexcept
+constexpr inline int QMargins::left() const noexcept
{ return m_left; }
-Q_DECL_CONSTEXPR inline int QMargins::top() const noexcept
+constexpr inline int QMargins::top() const noexcept
{ return m_top; }
-Q_DECL_CONSTEXPR inline int QMargins::right() const noexcept
+constexpr inline int QMargins::right() const noexcept
{ return m_right; }
-Q_DECL_CONSTEXPR inline int QMargins::bottom() const noexcept
+constexpr inline int QMargins::bottom() const noexcept
{ return m_bottom; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setLeft(int aleft) noexcept
+constexpr inline void QMargins::setLeft(int aleft) noexcept
{ m_left = aleft; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setTop(int atop) noexcept
+constexpr inline void QMargins::setTop(int atop) noexcept
{ m_top = atop; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setRight(int aright) noexcept
+constexpr inline void QMargins::setRight(int aright) noexcept
{ m_right = aright; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setBottom(int abottom) noexcept
+constexpr inline void QMargins::setBottom(int abottom) noexcept
{ m_bottom = abottom; }
-Q_DECL_CONSTEXPR inline bool operator==(const QMargins &m1, const QMargins &m2) noexcept
-{
- return
- m1.m_left == m2.m_left &&
- m1.m_top == m2.m_top &&
- m1.m_right == m2.m_right &&
- m1.m_bottom == m2.m_bottom;
-}
-
-Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &m1, const QMargins &m2) noexcept
-{
- return
- m1.m_left != m2.m_left ||
- m1.m_top != m2.m_top ||
- m1.m_right != m2.m_right ||
- m1.m_bottom != m2.m_bottom;
-}
-
-Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &m1, const QMargins &m2) noexcept
+constexpr inline QMargins operator+(const QMargins &m1, const QMargins &m2) noexcept
{
return QMargins(m1.left() + m2.left(), m1.top() + m2.top(),
m1.right() + m2.right(), m1.bottom() + m2.bottom());
}
-Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &m1, const QMargins &m2) noexcept
+constexpr inline QMargins operator-(const QMargins &m1, const QMargins &m2) noexcept
{
return QMargins(m1.left() - m2.left(), m1.top() - m2.top(),
m1.right() - m2.right(), m1.bottom() - m2.bottom());
}
-Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &lhs, int rhs) noexcept
+constexpr inline QMargins operator+(const QMargins &lhs, int rhs) noexcept
{
return QMargins(lhs.left() + rhs, lhs.top() + rhs,
lhs.right() + rhs, lhs.bottom() + rhs);
}
-Q_DECL_CONSTEXPR inline QMargins operator+(int lhs, const QMargins &rhs) noexcept
+constexpr inline QMargins operator+(int lhs, const QMargins &rhs) noexcept
{
return QMargins(rhs.left() + lhs, rhs.top() + lhs,
rhs.right() + lhs, rhs.bottom() + lhs);
}
-Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &lhs, int rhs) noexcept
+constexpr inline QMargins operator-(const QMargins &lhs, int rhs) noexcept
{
return QMargins(lhs.left() - rhs, lhs.top() - rhs,
lhs.right() - rhs, lhs.bottom() - rhs);
}
-Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, int factor) noexcept
+constexpr inline QMargins operator*(const QMargins &margins, int factor) noexcept
{
return QMargins(margins.left() * factor, margins.top() * factor,
margins.right() * factor, margins.bottom() * factor);
}
-Q_DECL_CONSTEXPR inline QMargins operator*(int factor, const QMargins &margins) noexcept
+constexpr inline QMargins operator*(int factor, const QMargins &margins) noexcept
{
return QMargins(margins.left() * factor, margins.top() * factor,
margins.right() * factor, margins.bottom() * factor);
}
-Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, qreal factor) noexcept
+constexpr inline QMargins operator*(const QMargins &margins, qreal factor) noexcept
{
return QMargins(qRound(margins.left() * factor), qRound(margins.top() * factor),
qRound(margins.right() * factor), qRound(margins.bottom() * factor));
}
-Q_DECL_CONSTEXPR inline QMargins operator*(qreal factor, const QMargins &margins) noexcept
+constexpr inline QMargins operator*(qreal factor, const QMargins &margins) noexcept
{
return QMargins(qRound(margins.left() * factor), qRound(margins.top() * factor),
qRound(margins.right() * factor), qRound(margins.bottom() * factor));
}
-Q_DECL_CONSTEXPR inline QMargins operator/(const QMargins &margins, int divisor)
+constexpr inline QMargins operator/(const QMargins &margins, int divisor)
{
return QMargins(margins.left() / divisor, margins.top() / divisor,
margins.right() / divisor, margins.bottom() / divisor);
}
-Q_DECL_CONSTEXPR inline QMargins operator/(const QMargins &margins, qreal divisor)
+constexpr inline QMargins operator/(const QMargins &margins, qreal divisor)
{
return QMargins(qRound(margins.left() / divisor), qRound(margins.top() / divisor),
qRound(margins.right() / divisor), qRound(margins.bottom() / divisor));
}
-Q_DECL_CONSTEXPR inline QMargins operator|(const QMargins &m1, const QMargins &m2) noexcept
+constexpr inline QMargins operator|(const QMargins &m1, const QMargins &m2) noexcept
{
return QMargins(qMax(m1.left(), m2.left()), qMax(m1.top(), m2.top()),
qMax(m1.right(), m2.right()), qMax(m1.bottom(), m2.bottom()));
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(const QMargins &margins) noexcept
+constexpr inline QMargins &QMargins::operator+=(const QMargins &margins) noexcept
{
return *this = *this + margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(const QMargins &margins) noexcept
+constexpr inline QMargins &QMargins::operator-=(const QMargins &margins) noexcept
{
return *this = *this - margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(int margin) noexcept
+constexpr inline QMargins &QMargins::operator+=(int margin) noexcept
{
m_left += margin;
m_top += margin;
@@ -241,7 +219,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(int margin) noexc
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(int margin) noexcept
+constexpr inline QMargins &QMargins::operator-=(int margin) noexcept
{
m_left -= margin;
m_top -= margin;
@@ -250,32 +228,32 @@ Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(int margin) noexc
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(int factor) noexcept
+constexpr inline QMargins &QMargins::operator*=(int factor) noexcept
{
return *this = *this * factor;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator/=(int divisor)
+constexpr inline QMargins &QMargins::operator/=(int divisor)
{
return *this = *this / divisor;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(qreal factor) noexcept
+constexpr inline QMargins &QMargins::operator*=(qreal factor) noexcept
{
return *this = *this * factor;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator/=(qreal divisor)
+constexpr inline QMargins &QMargins::operator/=(qreal divisor)
{
return *this = *this / divisor;
}
-Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &margins) noexcept
+constexpr inline QMargins operator+(const QMargins &margins) noexcept
{
return margins;
}
-Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &margins) noexcept
+constexpr inline QMargins operator-(const QMargins &margins) noexcept
{
return QMargins(-margins.left(), -margins.top(), -margins.right(), -margins.bottom());
}
@@ -291,39 +269,85 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QMargins &);
class QMarginsF
{
public:
- Q_DECL_CONSTEXPR QMarginsF() noexcept;
- Q_DECL_CONSTEXPR QMarginsF(qreal left, qreal top, qreal right, qreal bottom) noexcept;
- Q_DECL_CONSTEXPR QMarginsF(const QMargins &margins) noexcept;
+ constexpr QMarginsF() noexcept;
+ constexpr QMarginsF(qreal left, qreal top, qreal right, qreal bottom) noexcept;
+ constexpr QMarginsF(const QMargins &margins) noexcept;
- Q_DECL_CONSTEXPR bool isNull() const noexcept;
+ constexpr bool isNull() const noexcept;
- Q_DECL_CONSTEXPR qreal left() const noexcept;
- Q_DECL_CONSTEXPR qreal top() const noexcept;
- Q_DECL_CONSTEXPR qreal right() const noexcept;
- Q_DECL_CONSTEXPR qreal bottom() const noexcept;
+ constexpr qreal left() const noexcept;
+ constexpr qreal top() const noexcept;
+ constexpr qreal right() const noexcept;
+ constexpr qreal bottom() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setLeft(qreal left) noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setTop(qreal top) noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setRight(qreal right) noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setBottom(qreal bottom) noexcept;
+ constexpr void setLeft(qreal aleft) noexcept;
+ constexpr void setTop(qreal atop) noexcept;
+ constexpr void setRight(qreal aright) noexcept;
+ constexpr void setBottom(qreal abottom) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(const QMarginsF &margins) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(const QMarginsF &margins) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(qreal addend) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(qreal subtrahend) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator*=(qreal factor) noexcept;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator/=(qreal divisor);
+ constexpr QMarginsF &operator+=(const QMarginsF &margins) noexcept;
+ constexpr QMarginsF &operator-=(const QMarginsF &margins) noexcept;
+ constexpr QMarginsF &operator+=(qreal addend) noexcept;
+ constexpr QMarginsF &operator-=(qreal subtrahend) noexcept;
+ constexpr QMarginsF &operator*=(qreal factor) noexcept;
+ constexpr QMarginsF &operator/=(qreal divisor);
- Q_DECL_CONSTEXPR inline QMargins toMargins() const noexcept;
+ constexpr inline QMargins toMargins() const noexcept;
private:
qreal m_left;
qreal m_top;
qreal m_right;
qreal m_bottom;
+
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_FLOAT_COMPARE
+ friend constexpr bool qFuzzyCompare(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
+ {
+ return ((!lhs.m_left || !rhs.m_left) ? qFuzzyIsNull(lhs.m_left - rhs.m_left)
+ : qFuzzyCompare(lhs.m_left, rhs.m_left))
+ && ((!lhs.m_top || !rhs.m_top) ? qFuzzyIsNull(lhs.m_top - rhs.m_top)
+ : qFuzzyCompare(lhs.m_top, rhs.m_top))
+ && ((!lhs.m_right || !rhs.m_right) ? qFuzzyIsNull(lhs.m_right - rhs.m_right)
+ : qFuzzyCompare(lhs.m_right, rhs.m_right))
+ && ((!lhs.m_bottom || !rhs.m_bottom) ? qFuzzyIsNull(lhs.m_bottom - rhs.m_bottom)
+ : qFuzzyCompare(lhs.m_bottom, rhs.m_bottom));
+ }
+ QT_WARNING_POP
+ friend constexpr bool qFuzzyIsNull(const QMarginsF &m) noexcept
+ {
+ return qFuzzyIsNull(m.m_left) && qFuzzyIsNull(m.m_top)
+ && qFuzzyIsNull(m.m_right) && qFuzzyIsNull(m.m_bottom);
+ }
+
+ friend constexpr bool comparesEqual(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
+ {
+ return qFuzzyCompare(lhs, rhs);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QMarginsF)
+
+ friend constexpr bool comparesEqual(const QMarginsF &lhs, const QMargins &rhs) noexcept
+ { return comparesEqual(lhs, rhs.toMarginsF()); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QMarginsF, QMargins)
+
+ template <std::size_t I,
+ typename M,
+ std::enable_if_t<(I < 4), bool> = true,
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<M>, QMarginsF>, bool> = true>
+ friend constexpr decltype(auto) get(M &&m) noexcept
+ {
+ if constexpr (I == 0)
+ return q23::forward_like<M>(m.m_left);
+ else if constexpr (I == 1)
+ return q23::forward_like<M>(m.m_top);
+ else if constexpr (I == 2)
+ return q23::forward_like<M>(m.m_right);
+ else if constexpr (I == 3)
+ return q23::forward_like<M>(m.m_bottom);
+ }
};
-Q_DECLARE_TYPEINFO(QMarginsF, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QMarginsF, Q_RELOCATABLE_TYPE);
/*****************************************************************************
QMarginsF stream functions
@@ -338,121 +362,109 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QMarginsF &);
QMarginsF inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF() noexcept
+constexpr inline QMarginsF::QMarginsF() noexcept
: m_left(0), m_top(0), m_right(0), m_bottom(0) {}
-Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(qreal aleft, qreal atop, qreal aright, qreal abottom) noexcept
+constexpr inline QMarginsF::QMarginsF(qreal aleft, qreal atop, qreal aright, qreal abottom) noexcept
: m_left(aleft), m_top(atop), m_right(aright), m_bottom(abottom) {}
-Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(const QMargins &margins) noexcept
+constexpr inline QMarginsF::QMarginsF(const QMargins &margins) noexcept
: m_left(margins.left()), m_top(margins.top()), m_right(margins.right()), m_bottom(margins.bottom()) {}
-Q_DECL_CONSTEXPR inline bool QMarginsF::isNull() const noexcept
+constexpr inline bool QMarginsF::isNull() const noexcept
{ return qFuzzyIsNull(m_left) && qFuzzyIsNull(m_top) && qFuzzyIsNull(m_right) && qFuzzyIsNull(m_bottom); }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::left() const noexcept
+constexpr inline qreal QMarginsF::left() const noexcept
{ return m_left; }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::top() const noexcept
+constexpr inline qreal QMarginsF::top() const noexcept
{ return m_top; }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::right() const noexcept
+constexpr inline qreal QMarginsF::right() const noexcept
{ return m_right; }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::bottom() const noexcept
+constexpr inline qreal QMarginsF::bottom() const noexcept
{ return m_bottom; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setLeft(qreal aleft) noexcept
+constexpr inline void QMarginsF::setLeft(qreal aleft) noexcept
{ m_left = aleft; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setTop(qreal atop) noexcept
+constexpr inline void QMarginsF::setTop(qreal atop) noexcept
{ m_top = atop; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setRight(qreal aright) noexcept
+constexpr inline void QMarginsF::setRight(qreal aright) noexcept
{ m_right = aright; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setBottom(qreal abottom) noexcept
+constexpr inline void QMarginsF::setBottom(qreal abottom) noexcept
{ m_bottom = abottom; }
-Q_DECL_CONSTEXPR inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
-{
- return qFuzzyCompare(lhs.left(), rhs.left())
- && qFuzzyCompare(lhs.top(), rhs.top())
- && qFuzzyCompare(lhs.right(), rhs.right())
- && qFuzzyCompare(lhs.bottom(), rhs.bottom());
-}
-
-Q_DECL_CONSTEXPR inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
-{
- return !operator==(lhs, rhs);
-}
-
-Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
+constexpr inline QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(lhs.left() + rhs.left(), lhs.top() + rhs.top(),
lhs.right() + rhs.right(), lhs.bottom() + rhs.bottom());
}
-Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
+constexpr inline QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(lhs.left() - rhs.left(), lhs.top() - rhs.top(),
lhs.right() - rhs.right(), lhs.bottom() - rhs.bottom());
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, qreal rhs) noexcept
+constexpr inline QMarginsF operator+(const QMarginsF &lhs, qreal rhs) noexcept
{
return QMarginsF(lhs.left() + rhs, lhs.top() + rhs,
lhs.right() + rhs, lhs.bottom() + rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(qreal lhs, const QMarginsF &rhs) noexcept
+constexpr inline QMarginsF operator+(qreal lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(rhs.left() + lhs, rhs.top() + lhs,
rhs.right() + lhs, rhs.bottom() + lhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, qreal rhs) noexcept
+constexpr inline QMarginsF operator-(const QMarginsF &lhs, qreal rhs) noexcept
{
return QMarginsF(lhs.left() - rhs, lhs.top() - rhs,
lhs.right() - rhs, lhs.bottom() - rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator*(const QMarginsF &lhs, qreal rhs) noexcept
+constexpr inline QMarginsF operator*(const QMarginsF &lhs, qreal rhs) noexcept
{
return QMarginsF(lhs.left() * rhs, lhs.top() * rhs,
lhs.right() * rhs, lhs.bottom() * rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator*(qreal lhs, const QMarginsF &rhs) noexcept
+constexpr inline QMarginsF operator*(qreal lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(rhs.left() * lhs, rhs.top() * lhs,
rhs.right() * lhs, rhs.bottom() * lhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator/(const QMarginsF &lhs, qreal divisor)
+constexpr inline QMarginsF operator/(const QMarginsF &lhs, qreal divisor)
{
+ Q_ASSERT(divisor < 0 || divisor > 0);
return QMarginsF(lhs.left() / divisor, lhs.top() / divisor,
lhs.right() / divisor, lhs.bottom() / divisor);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator|(const QMarginsF &m1, const QMarginsF &m2) noexcept
+constexpr inline QMarginsF operator|(const QMarginsF &m1, const QMarginsF &m2) noexcept
{
return QMarginsF(qMax(m1.left(), m2.left()), qMax(m1.top(), m2.top()),
qMax(m1.right(), m2.right()), qMax(m1.bottom(), m2.bottom()));
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) noexcept
+constexpr inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) noexcept
{
return *this = *this + margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) noexcept
+constexpr inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) noexcept
{
return *this = *this - margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(qreal addend) noexcept
+constexpr inline QMarginsF &QMarginsF::operator+=(qreal addend) noexcept
{
m_left += addend;
m_top += addend;
@@ -461,7 +473,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(qreal addend) n
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) noexcept
+constexpr inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) noexcept
{
m_left -= subtrahend;
m_top -= subtrahend;
@@ -470,27 +482,29 @@ Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(qreal subtrahen
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator*=(qreal factor) noexcept
+constexpr inline QMarginsF &QMarginsF::operator*=(qreal factor) noexcept
{
return *this = *this * factor;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator/=(qreal divisor)
+constexpr inline QMarginsF &QMarginsF::operator/=(qreal divisor)
{
return *this = *this / divisor;
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &margins) noexcept
+constexpr inline QMarginsF operator+(const QMarginsF &margins) noexcept
{
return margins;
}
-Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &margins) noexcept
+constexpr inline QMarginsF operator-(const QMarginsF &margins) noexcept
{
return QMarginsF(-margins.left(), -margins.top(), -margins.right(), -margins.bottom());
}
-Q_DECL_CONSTEXPR inline QMargins QMarginsF::toMargins() const noexcept
+constexpr QMarginsF QMargins::toMarginsF() const noexcept { return *this; }
+
+constexpr inline QMargins QMarginsF::toMargins() const noexcept
{
return QMargins(qRound(m_left), qRound(m_top), qRound(m_right), qRound(m_bottom));
}
@@ -501,4 +515,32 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QMarginsF &);
QT_END_NAMESPACE
+/*****************************************************************************
+ QMargins/QMarginsF tuple protocol
+ *****************************************************************************/
+
+namespace std {
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QMargins)> : public integral_constant<size_t, 4> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+ template <>
+ class tuple_element<2, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+ template <>
+ class tuple_element<3, QT_PREPEND_NAMESPACE(QMargins)> { public: using type = int; };
+
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QMarginsF)> : public integral_constant<size_t, 4> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<2, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<3, QT_PREPEND_NAMESPACE(QMarginsF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+}
+
#endif // QMARGINS_H
diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp
deleted file mode 100644
index 40a1193622..0000000000
--- a/src/corelib/tools/qmessageauthenticationcode.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmessageauthenticationcode.h"
-#include "qvarlengtharray.h"
-
-/*
- These #defines replace the typedefs needed by the RFC6234 code. Normally
- the typedefs would come from from stdint.h, but since this header is not
- available on all platforms (MSVC 2008, for example), we #define them to the
- Qt equivalents.
-*/
-
-#ifdef uint64_t
-#undef uint64_t
-#endif
-
-#define uint64_t QT_PREPEND_NAMESPACE(quint64)
-
-#ifdef uint32_t
-#undef uint32_t
-#endif
-
-#define uint32_t QT_PREPEND_NAMESPACE(quint32)
-
-#ifdef uint8_t
-#undef uint8_t
-#endif
-
-#define uint8_t QT_PREPEND_NAMESPACE(quint8)
-
-#ifdef int_least16_t
-#undef int_least16_t
-#endif
-
-#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
-
-// Header from rfc6234 with 1 modification:
-// sha1.h - commented out '#include <stdint.h>' on line 74
-#include "../../3rdparty/rfc6234/sha.h"
-
-#undef uint64_t
-#undef uint32_t
-#undef uint68_t
-#undef int_least16_t
-
-QT_BEGIN_NAMESPACE
-
-static int qt_hash_block_size(QCryptographicHash::Algorithm method)
-{
- switch (method) {
- case QCryptographicHash::Md4:
- return 64;
- case QCryptographicHash::Md5:
- return 64;
- case QCryptographicHash::Sha1:
- return SHA1_Message_Block_Size;
- case QCryptographicHash::Sha224:
- return SHA224_Message_Block_Size;
- case QCryptographicHash::Sha256:
- return SHA256_Message_Block_Size;
- case QCryptographicHash::Sha384:
- return SHA384_Message_Block_Size;
- case QCryptographicHash::Sha512:
- return SHA512_Message_Block_Size;
- case QCryptographicHash::RealSha3_224:
- case QCryptographicHash::Keccak_224:
- return 144;
- case QCryptographicHash::RealSha3_256:
- case QCryptographicHash::Keccak_256:
- return 136;
- case QCryptographicHash::RealSha3_384:
- case QCryptographicHash::Keccak_384:
- return 104;
- case QCryptographicHash::RealSha3_512:
- case QCryptographicHash::Keccak_512:
- return 72;
- }
- return 0;
-}
-
-class QMessageAuthenticationCodePrivate
-{
-public:
- QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m)
- : messageHash(m), method(m), messageHashInited(false)
- {
- }
-
- QByteArray key;
- QByteArray result;
- QCryptographicHash messageHash;
- QCryptographicHash::Algorithm method;
- bool messageHashInited;
-
- void initMessageHash();
-};
-
-void QMessageAuthenticationCodePrivate::initMessageHash()
-{
- if (messageHashInited)
- return;
- messageHashInited = true;
-
- const int blockSize = qt_hash_block_size(method);
-
- if (key.size() > blockSize) {
- QCryptographicHash hash(method);
- hash.addData(key);
- key = hash.result();
- hash.reset();
- }
-
- if (key.size() < blockSize) {
- const int size = key.size();
- key.resize(blockSize);
- memset(key.data() + size, 0, blockSize - size);
- }
-
- QVarLengthArray<char> iKeyPad(blockSize);
- const char * const keyData = key.constData();
-
- for (int i = 0; i < blockSize; ++i)
- iKeyPad[i] = keyData[i] ^ 0x36;
-
- messageHash.addData(iKeyPad.data(), iKeyPad.size());
-}
-
-/*!
- \class QMessageAuthenticationCode
- \inmodule QtCore
-
- \brief The QMessageAuthenticationCode class provides a way to generate
- hash-based message authentication codes.
-
- \since 5.1
-
- \ingroup tools
- \reentrant
-
- QMessageAuthenticationCode supports all cryptographic hashes which are supported by
- QCryptographicHash.
-
- To generate message authentication code, pass hash algorithm QCryptographicHash::Algorithm
- to constructor, then set key and message by setKey() and addData() functions. Result
- can be acquired by result() function.
- \snippet qmessageauthenticationcode/main.cpp 0
- \dots
- \snippet qmessageauthenticationcode/main.cpp 1
-
- Alternatively, this effect can be achieved by providing message,
- key and method to hash() method.
- \snippet qmessageauthenticationcode/main.cpp 2
-
- \sa QCryptographicHash
-*/
-
-/*!
- Constructs an object that can be used to create a cryptographic hash from data
- using method \a method and key \a key.
-*/
-QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
- const QByteArray &key)
- : d(new QMessageAuthenticationCodePrivate(method))
-{
- d->key = key;
-}
-
-/*!
- Destroys the object.
-*/
-QMessageAuthenticationCode::~QMessageAuthenticationCode()
-{
- delete d;
-}
-
-/*!
- Resets message data. Calling this method doesn't affect the key.
-*/
-void QMessageAuthenticationCode::reset()
-{
- d->result.clear();
- d->messageHash.reset();
- d->messageHashInited = false;
-}
-
-/*!
- Sets secret \a key. Calling this method automatically resets the object state.
-*/
-void QMessageAuthenticationCode::setKey(const QByteArray &key)
-{
- reset();
- d->key = key;
-}
-
-/*!
- Adds the first \a length chars of \a data to the message.
-*/
-void QMessageAuthenticationCode::addData(const char *data, int length)
-{
- d->initMessageHash();
- d->messageHash.addData(data, length);
-}
-
-/*!
- \overload addData()
-*/
-void QMessageAuthenticationCode::addData(const QByteArray &data)
-{
- d->initMessageHash();
- d->messageHash.addData(data);
-}
-
-/*!
- Reads the data from the open QIODevice \a device until it ends
- and adds it to message. Returns \c true if reading was successful.
-
- \note \a device must be already opened.
- */
-bool QMessageAuthenticationCode::addData(QIODevice *device)
-{
- d->initMessageHash();
- return d->messageHash.addData(device);
-}
-
-/*!
- Returns the final authentication code.
-
- \sa QByteArray::toHex()
-*/
-QByteArray QMessageAuthenticationCode::result() const
-{
- if (!d->result.isEmpty())
- return d->result;
-
- d->initMessageHash();
-
- const int blockSize = qt_hash_block_size(d->method);
-
- QByteArray hashedMessage = d->messageHash.result();
-
- QVarLengthArray<char> oKeyPad(blockSize);
- const char * const keyData = d->key.constData();
-
- for (int i = 0; i < blockSize; ++i)
- oKeyPad[i] = keyData[i] ^ 0x5c;
-
- QCryptographicHash hash(d->method);
- hash.addData(oKeyPad.data(), oKeyPad.size());
- hash.addData(hashedMessage);
-
- d->result = hash.result();
- return d->result;
-}
-
-/*!
- Returns the authentication code for the message \a message using
- the key \a key and the method \a method.
-*/
-QByteArray QMessageAuthenticationCode::hash(const QByteArray &message, const QByteArray &key,
- QCryptographicHash::Algorithm method)
-{
- QMessageAuthenticationCode mac(method);
- mac.setKey(key);
- mac.addData(message);
- return mac.result();
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/tools/qmessageauthenticationcode.h b/src/corelib/tools/qmessageauthenticationcode.h
index a13a3d2acf..4e88138763 100644
--- a/src/corelib/tools/qmessageauthenticationcode.h
+++ b/src/corelib/tools/qmessageauthenticationcode.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMESSAGEAUTHENTICATIONCODE_H
#define QMESSAGEAUTHENTICATIONCODE_H
@@ -48,25 +12,48 @@ QT_BEGIN_NAMESPACE
class QMessageAuthenticationCodePrivate;
class QIODevice;
+// implemented in qcryptographichash.cpp
class Q_CORE_EXPORT QMessageAuthenticationCode
{
public:
+#if QT_CORE_REMOVED_SINCE(6, 6)
explicit QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
- const QByteArray &key = QByteArray());
+ const QByteArray &key);
+#endif
+ explicit QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
+ QByteArrayView key = {});
+
+ QMessageAuthenticationCode(QMessageAuthenticationCode &&other) noexcept
+ : d{std::exchange(other.d, nullptr)} {}
~QMessageAuthenticationCode();
- void reset();
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMessageAuthenticationCode)
+ void swap(QMessageAuthenticationCode &other) noexcept
+ { qt_ptr_swap(d, other.d); }
+
+ void reset() noexcept;
+#if QT_CORE_REMOVED_SINCE(6, 6)
void setKey(const QByteArray &key);
+#endif
+ void setKey(QByteArrayView key) noexcept;
- void addData(const char *data, int length);
+ void addData(const char *data, qsizetype length);
+#if QT_CORE_REMOVED_SINCE(6, 6)
void addData(const QByteArray &data);
+#endif
+ void addData(QByteArrayView data) noexcept;
bool addData(QIODevice *device);
+ QByteArrayView resultView() const noexcept;
QByteArray result() const;
+#if QT_CORE_REMOVED_SINCE(6, 6)
static QByteArray hash(const QByteArray &message, const QByteArray &key,
QCryptographicHash::Algorithm method);
+#endif
+ static QByteArray hash(QByteArrayView message, QByteArrayView key,
+ QCryptographicHash::Algorithm method);
private:
Q_DISABLE_COPY(QMessageAuthenticationCode)
diff --git a/src/corelib/tools/qminimalflatset_p.h b/src/corelib/tools/qminimalflatset_p.h
new file mode 100644
index 0000000000..6074688f6e
--- /dev/null
+++ b/src/corelib/tools/qminimalflatset_p.h
@@ -0,0 +1,156 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTCORE_QMINIMALFLATSET_P_H
+#define QTCORE_QMINIMALFLATSET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qfunctionaltools_impl.h> // CompactStorage
+#include <QtCore/private/qglobal_p.h>
+
+//#define QMINIMAL_FLAT_SET_DEBUG
+#ifdef QMINIMAL_FLAT_SET_DEBUG
+# include <QtCore/qscopeguard.h>
+# include <QtCore/qdebug.h>
+# define QMINIMAL_FLAT_SET_PRINT_AT_END \
+ const auto sg = qScopeGuard([&] { qDebug() << this << *this; });
+#else
+# define QMINIMAL_FLAT_SET_PRINT_AT_END
+#endif
+
+#include <algorithm> // for std::lower_bound
+#include <functional> // for std::less, std::ref
+
+QT_BEGIN_NAMESPACE
+
+/*
+ This is a minimal version of a QFlatSet, the std::set version of QFlatMap.
+ Like QFlatMap, it has linear insertion and removal, not logarithmic, like
+ real QMap and std::set, so it's only a good container if you either have
+ very few entries or lots, but with separate setup and lookup stages.
+ Because a full QFlatSet would be 10x the work on writing this minimal one,
+ we keep it here for now. When more users pop up and the class has matured a
+ bit, we can consider moving it as QFlatSet alongside QFlatMap.
+*/
+
+template <typename T, typename Container = QList<T>, typename Compare = std::less<T>>
+class QMinimalFlatSet : QtPrivate::CompactStorage<Compare>
+{
+ Container c;
+ using CompareStorage = QtPrivate::CompactStorage<Compare>;
+public:
+ QMinimalFlatSet() = default;
+ explicit QMinimalFlatSet(const Compare &cmp) : CompareStorage{cmp} {}
+ // Rule Of Zero applies
+
+ using const_iterator = typename Container::const_iterator;
+ using iterator = const_iterator;
+ using const_reverse_iterator = typename Container::const_reverse_iterator;
+ using reverse_iterator = const_reverse_iterator;
+ using value_type = T;
+ using key_compare = Compare;
+ using value_compare = Compare;
+
+ key_compare key_comp() const { return this->object(); }
+ value_compare value_comp() const { return key_comp(); }
+
+ iterator begin() const { return c.cbegin(); }
+ iterator end() const { return c.cend(); }
+ iterator cbegin() const { return begin(); }
+ iterator cend() const { return cend(); }
+
+ reverse_iterator rbegin() const { return c.crbegin(); }
+ reverse_iterator rend() const { return c.crend(); }
+ reverse_iterator crbegin() const { return rbegin(); }
+ reverse_iterator crend() const { return rend(); }
+
+ void clear() {
+ QMINIMAL_FLAT_SET_PRINT_AT_END
+ c.clear();
+ }
+ auto size() const { return c.size(); }
+ auto count() const { return size(); }
+ bool isEmpty() const { return size() == 0; }
+
+ std::pair<iterator, bool> insert(value_type &&v)
+ {
+ QMINIMAL_FLAT_SET_PRINT_AT_END
+ const auto r = lookup(v);
+ if (r.exists)
+ return {r.it, false};
+ else
+ return {c.insert(r.it, std::move(v)), true};
+ }
+
+ std::pair<iterator, bool> insert(const value_type &v)
+ {
+ QMINIMAL_FLAT_SET_PRINT_AT_END
+ const auto r = lookup(v);
+ if (r.exists)
+ return {r.it, false};
+ else
+ return {c.insert(r.it, v), true};
+ }
+
+ void erase(const value_type &v)
+ {
+ QMINIMAL_FLAT_SET_PRINT_AT_END
+ const auto r = lookup(v);
+ if (r.exists)
+ c.erase(r.it);
+ }
+ void remove(const value_type &v) { erase(v); }
+
+ bool contains(const value_type &v) const
+ {
+ return lookup(v).exists;
+ }
+
+ const Container &values() const & { return c; }
+ Container values() && { return std::move(c); }
+
+private:
+ auto lookup(const value_type &v) const
+ {
+ struct R {
+ iterator it;
+ bool exists;
+ };
+
+ auto cmp = std::ref(this->object()); // don't let std::lower_bound copy it
+
+ const auto it = std::lower_bound(c.cbegin(), c.cend(), v, cmp);
+ return R{it, it != c.cend() && !cmp(v, *it)};
+ }
+
+#ifdef QMINIMAL_FLAT_SET_DEBUG
+ friend QDebug operator<<(QDebug dbg, const QMinimalFlatSet &set)
+ {
+ const QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QMinimalFlatSet{";
+ for (auto &e : set)
+ dbg << e << ", ";
+ return dbg << "}";
+ }
+#endif
+};
+
+#undef QMINIMAL_FLAT_SET_PRINT_AT_END
+
+template <typename T, qsizetype N = QVarLengthArrayDefaultPrealloc>
+using QMinimalVarLengthFlatSet = QMinimalFlatSet<T, QVarLengthArray<T, N>>;
+
+QT_END_NAMESPACE
+
+#endif // QTCORE_QMINIMALFLATSET_P_H
diff --git a/src/corelib/tools/qmultimap.qdoc b/src/corelib/tools/qmultimap.qdoc
new file mode 100644
index 0000000000..0b05192817
--- /dev/null
+++ b/src/corelib/tools/qmultimap.qdoc
@@ -0,0 +1,1543 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \class QMultiMap
+ \inmodule QtCore
+ \brief The QMultiMap class is a template class that provides an associative array with multiple equivalent keys.
+
+ \ingroup tools
+ \ingroup shared
+
+ \reentrant
+
+ QMultiMap\<Key, T\> is one of Qt's generic \l{container classes}. It
+ stores (key, value) pairs and provides fast lookup by key.
+
+ QMultiMap and QMultiHash provide very similar functionality. The
+ differences are:
+
+ \list
+ \li QMultiHash provides average faster lookups than QMultiMap. (See \l{Algorithmic
+ Complexity} for details.)
+ \li When iterating over a QMultiHash, the items are arbitrarily ordered.
+ With QMultiMap, the items are always sorted by key.
+ \li The key type of a QMultiHash must provide operator==() and a global
+ qHash(Key) function. The key type of a QMultiMap must provide
+ operator<() specifying a total order. Since Qt 5.8.1 it is also safe
+ to use a pointer type as key, even if the underlying operator<()
+ does not provide a total order.
+ \endlist
+
+ Here's an example QMultiMap with QString keys and \c int values:
+ \snippet code/src_corelib_tools_qmultimap.cpp 0
+
+ To insert a (key, value) pair into the multi map, you can use insert():
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 2
+
+ This inserts the following three (key, value) pairs into the
+ QMultiMap: ("a", 1), ("b", 3), ("c", 7), and ("c", -5); note
+ that duplicate keys are allowed.
+
+ To look up a value, use find() or value():
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 3
+
+ If there is no item with the specified key in the map, these
+ functions return a \l{default-constructed value}.
+
+ If you want to check whether the map contains a certain key, use
+ contains():
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 4
+
+ There is also a value() overload that uses its second argument as
+ a default value if there is no item with the specified key:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 5
+
+ If you want to navigate through all the (key, value) pairs stored
+ in a QMultiMap, you can use an iterator. QMultiMap provides both
+ \l{Java-style iterators} (QMultiMapIterator and QMutableMultiMapIterator)
+ and \l{STL-style iterators} (QMultiMap::const_iterator and
+ QMultiMap::iterator). Here's how to iterate over a QMultiMap<QString, int>
+ using a Java-style iterator:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 7
+
+ Here's the same code, but using an STL-style iterator this time:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 8
+
+ The items are traversed in ascending key order.
+
+ A QMultiMap allows multiple values per key. If you call
+ insert() with a key that already exists in the map, a
+ new (key, value) pair will be inserted. For example:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 9
+
+ If you want to retrieve all the values for a single key, you can
+ use values(const Key &key), which returns a QList<T>:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 10
+
+ The items that share the same key are available from most
+ recently to least recently inserted. Another approach is to call
+ find() to get the STL-style iterator for the first item with a
+ key and iterate from there:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 11
+
+ If you only need to extract the values from a map (not the keys),
+ you can also use range-based for:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 12
+
+ Items can be removed from the multi map in several ways. One way is to
+ call remove(); this will remove any item with the given key.
+ Another way is to use QMutableMultiMapIterator::remove(). In addition,
+ you can clear the entire map using clear().
+
+ It is possible to merge two multi maps by calling unite(), by
+ using operator+(), and by using operator+=(). Example:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 25
+
+ QMultiMap's key and value data types must be \l{assignable data
+ types}. This covers most data types you are likely to encounter,
+ but the compiler won't let you, for example, store a QWidget as a
+ value; instead, store a QWidget *. In addition, QMultiMap's key type
+ must provide operator<(). QMap uses it to keep its items sorted,
+ and assumes that two keys \c x and \c y are equal if neither \c{x
+ < y} nor \c{y < x} is true.
+
+ Example:
+ \snippet code/src_corelib_tools_qmultimap.cpp 13
+
+ In the example, we start by comparing the employees' names. If
+ they're equal, we compare their dates of birth to break the tie.
+
+ \sa QMultiMapIterator, QMutableMultiMapIterator, QMultiHash
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap()
+
+ Constructs an empty multi map.
+
+ \sa clear()
+*/
+
+/*!
+ \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(QMultiMap<Key, T> &&other)
+
+ Move-constructs a QMultiMap instance, making it point at the same
+ object that \a other was pointing to.
+
+ \since 5.2
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(const QMultiMap<Key, T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation occurs in \l{constant time}, because QMultiMap is
+ \l{implicitly shared}. This makes returning a QMultiMap from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and this takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::operator=(const QMultiMap<Key, T> &other)
+
+ Assigns \a other to this multi map and returns a reference to this multi map.
+*/
+
+/*!
+ \fn template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::operator=(QMultiMap<Key, T> &&other)
+
+ Move-assigns \a other to this QMultiMap instance.
+
+ \since 5.2
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::~QMultiMap()
+
+ Destroys the multi map. References to the values in the multi map, and all
+ iterators over this multi map, become invalid.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(std::initializer_list<std::pair<Key,T> > list)
+ \since 5.1
+
+ Constructs a multi map with a copy of each of the elements in the
+ initializer list \a list.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(const QMap<Key, T> &other)
+ \since 6.0
+
+ Constructs a multi map as a copy of \a other.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(QMap<Key, T> &&other)
+ \since 6.0
+
+ If \a other is shared, constructs a multi map as a copy of \a other.
+ Otherwise, constructs a multi map by moving the elements from \a other.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(const std::multimap<Key, T> &other)
+
+ Constructs a copy of \a other.
+
+ \sa toStdMultiMap()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::QMultiMap(std::multimap<Key, T> &&other)
+
+ Constructs a multi map by moving from \a other.
+
+ \sa toStdMultiMap()
+*/
+
+/*! \fn template <class Key, class T> std::multimap<Key, T> QMultiMap<Key, T>::toStdMap() const
+ \deprecated Use toStdMultiMap() instead.
+
+ Returns an STL multi map equivalent to this QMultiMap.
+*/
+
+/*! \fn template <class Key, class T> std::multimap<Key, T> QMultiMap<Key, T>::toStdMultiMap() const &
+
+ Returns an STL multi map equivalent to this QMultiMap.
+*/
+
+/*! \fn template <class Key, class T> void QMultiMap<Key, T>::swap(QMultiMap<Key, T> &other)
+ \since 4.8
+
+ Swaps multi map \a other with this multi map. This operation is very
+ fast and never fails.
+*/
+
+/*! \fn template<class Key, class T> bool QMultiMap<Key, T>::operator==(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
+
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns
+ false.
+
+ Two multi maps are considered equal if they contain the same (key,
+ value) pairs, in the same order (which matters for duplicate keys).
+
+ This function requires the key and the value types to implement \c
+ operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn template<class Key, class T> bool QMultiMap<Key, T>::operator!=(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
+
+ Returns \c true if \a lhs is not equal to \a rhs; otherwise
+ returns \c false.
+
+ Two multi maps are considered equal if they contain the same (key,
+ value) pairs, in the same order (which matters for duplicate keys).
+
+ This function requires the key and the value types to implement \c
+ operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::size() const
+
+ Returns the number of (key, value) pairs in the multi map.
+
+ \sa isEmpty(), count()
+*/
+
+/*!
+ \fn template <class Key, class T> bool QMultiMap<Key, T>::isEmpty() const
+
+ Returns \c true if the multi map contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn template <class Key, class T> void QMultiMap<Key, T>::detach()
+
+ \internal
+
+ Detaches this map from any other multi maps with which it may share
+ data.
+
+ \sa isDetached()
+*/
+
+/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::isDetached() const
+
+ \internal
+
+ Returns \c true if the multi map's internal data isn't shared with any
+ other map object; otherwise returns \c false.
+
+ \sa detach()
+*/
+
+/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::isSharedWith(const QMultiMap<Key, T> &other) const
+
+ \internal
+*/
+
+/*! \fn template <class Key, class T> void QMultiMap<Key, T>::clear()
+
+ Removes all items from the multi map.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::remove(const Key &key)
+
+ Removes all the items that have the key \a key from the multi map.
+ Returns the number of items removed.
+
+ \sa clear(), take()
+*/
+
+/*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::remove(const Key &key, const T &value)
+
+ Removes all the items that have the key \a key and value \a value
+ from the multi map.
+ Returns the number of items removed.
+
+ \sa clear(), take()
+*/
+
+/*! \fn template <class Key, class T> template <typename Predicate> size_type QMultiMap<Key, T>::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the multi map.
+
+ The function supports predicates which take either an argument of
+ type \c{QMultiMap<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+
+ \sa clear(), take()
+*/
+
+/*! \fn template <class Key, class T> T QMultiMap<Key, T>::take(const Key &key)
+
+ Removes the item with the key \a key from the multi map and returns
+ the value associated with it.
+
+ If the item does not exist in the multi map, the function simply
+ returns a \l{default-constructed value}. If there are multiple
+ items for \a key in the map, only the most recently inserted one
+ is removed and returned.
+
+ If you don't use the return value, remove() is more efficient.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::contains(const Key &key) const
+
+ Returns \c true if the multi map contains an item with key \a key;
+ otherwise returns \c false.
+
+ \sa count()
+*/
+
+/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const
+ \since 4.3
+
+ Returns \c true if the multi map contains an item with key \a key
+ and value \a value; otherwise returns \c false.
+
+ \sa count()
+*/
+
+/*!
+ \fn template <class Key, class T> Key QMultiMap<Key, T>::key(const T &value, const Key &defaultKey) const
+ \since 4.3
+ \overload
+
+ Returns the first key with value \a value, or \a defaultKey if
+ the multi map contains no item with value \a value. If no \a defaultKey
+ is provided the function returns a
+ \l{default-constructed value}{default-constructed key}.
+
+ This function can be slow (\l{linear time}), because QMultiMap's
+ internal data structure is optimized for fast lookup by key, not
+ by value.
+
+ \sa value(), keys()
+*/
+
+/*! \fn template <class Key, class T> T QMultiMap<Key, T>::value(const Key &key, const T &defaultValue) const
+
+ Returns the value associated with the key \a key.
+
+ If the multi map contains no item with key \a key, the function returns
+ \a defaultValue. If no \a defaultValue is specified, the function
+ returns a \l{default-constructed value}. If there are multiple
+ items for \a key in the multi map, the value of the most recently
+ inserted one is returned.
+
+ \sa key(), values(), contains()
+*/
+
+/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::keys() const
+
+ Returns a list containing all the keys in the multi map in ascending
+ order. Keys that occur multiple times in the multi map
+ also occur multiple times in the list.
+
+ The order is guaranteed to be the same as that used by values().
+
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l keyBegin() to
+ \l keyEnd().
+
+ \sa values(), key()
+*/
+
+/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::keys(const T &value) const
+
+ \overload
+
+ Returns a list containing all the keys associated with value \a
+ value in ascending order.
+
+ This function can be slow (\l{linear time}), because QMultiMap's
+ internal data structure is optimized for fast lookup by key, not
+ by value.
+*/
+
+/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::uniqueKeys() const
+ \since 4.2
+
+ Returns a list containing all the keys in the map in ascending
+ order. Keys that occur multiple times in the map occur only
+ once in the returned list.
+*/
+
+/*! \fn template <class Key, class T> QList<T> QMultiMap<Key, T>::values() const
+
+ Returns a list containing all the values in the map, in ascending
+ order of their keys. If a key is associated with multiple values,
+ all of its values will be in the list, and not just the most
+ recently inserted one.
+
+ \sa keys(), value()
+*/
+
+/*! \fn template <class Key, class T> QList<T> QMultiMap<Key, T>::values(const Key &key) const
+
+ Returns a list containing all the values associated with key
+ \a key, from the most recently inserted to the least recently
+ inserted one.
+
+ \sa keys(), value()
+*/
+
+/*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::count(const Key &key) const
+
+ Returns the number of items associated with key \a key.
+
+ \sa contains(), QMultiMap::count()
+*/
+
+/*! \fn template <class Key, class T> qsizetype QMultiMap<Key, T>::count(const Key &key, const T &value) const
+
+ Returns the number of items with key \a key and value \a value.
+
+ \sa contains(), QMultiMap::count()
+*/
+
+
+/*! \fn template <class Key, class T> const Key &QMultiMap<Key, T>::firstKey() const
+ \since 5.2
+
+ Returns a reference to the smallest key in the multi map.
+ This function assumes that the multi map is not empty.
+
+ This executes in \l{constant time}.
+
+ \sa lastKey(), first(), keyBegin(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> const Key &QMultiMap<Key, T>::lastKey() const
+ \since 5.2
+
+ Returns a reference to the largest key in the multi map.
+ This function assumes that the multi map is not empty.
+
+ This executes in \l{logarithmic time}.
+
+ \sa firstKey(), last(), keyEnd(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> T &QMultiMap<Key, T>::first()
+ \since 5.2
+
+ Returns a reference to the first value in the multi map, that is the value mapped
+ to the smallest key. This function assumes that the multi map is not empty.
+
+ When unshared (or const version is called), this executes in \l{constant time}.
+
+ \sa last(), firstKey(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> const T &QMultiMap<Key, T>::first() const
+ \since 5.2
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> T &QMultiMap<Key, T>::last()
+ \since 5.2
+
+ Returns a reference to the last value in the multi map, that is the value mapped
+ to the largest key. This function assumes that the map is not empty.
+
+ When unshared (or const version is called), this executes in \l{logarithmic time}.
+
+ \sa first(), lastKey(), isEmpty()
+*/
+
+/*! \fn template <class Key, class T> const T &QMultiMap<Key, T>::last() const
+ \since 5.2
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::begin()
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
+ the multi map.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::begin() const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::cbegin() const
+ \since 5.0
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
+ in the multi map.
+
+ \sa begin(), cend()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::constBegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
+ in the multi map.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_iterator QMultiMap<Key, T>::keyBegin() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key
+ in the multi map.
+
+ \sa keyEnd(), firstKey()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::end()
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
+ after the last item in the multi map.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::end() const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::cend() const
+ \since 5.0
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last item in the multi map.
+
+ \sa cbegin(), end()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::constEnd() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last item in the multi map.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_iterator QMultiMap<Key, T>::keyEnd() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last key in the multi map.
+
+ \sa keyBegin(), lastKey()
+*/
+
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_value_iterator QMultiMap<Key, T>::keyValueBegin()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the multi map.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_value_iterator QMultiMap<Key, T>::keyValueEnd()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the multi map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_key_value_iterator QMultiMap<Key, T>::keyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the multi map.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_key_value_iterator QMultiMap<Key, T>::constKeyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the multi map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_key_value_iterator QMultiMap<Key, T>::keyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the multi map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_key_value_iterator QMultiMap<Key, T>::constKeyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the multi map.
+
+ \sa constKeyValueBegin()
+*/
+
+/*! \fn template <class Key, class T> auto QMultiMap<Key, T>::asKeyValueRange() &
+ \fn template <class Key, class T> auto QMultiMap<Key, T>::asKeyValueRange() const &
+ \fn template <class Key, class T> auto QMultiMap<Key, T>::asKeyValueRange() &&
+ \fn template <class Key, class T> auto QMultiMap<Key, T>::asKeyValueRange() const &&
+ \since 6.4
+
+ Returns a range object that allows iteration over this multi map as
+ key/value pairs. For instance, this range object can be used in a
+ range-based for loop, in combination with a structured binding declaration:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 26
+
+ Note that both the key and the value obtained this way are
+ references to the ones in the multi map. Specifically, mutating the value
+ will modify the map itself.
+
+ \sa QKeyValueIterator
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::erase(const_iterator pos)
+
+ Removes the (key, value) pair pointed to by the iterator \a pos
+ from the multi map, and returns an iterator to the next item in the
+ map.
+
+ \note The iterator \a pos must be valid and dereferenceable.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::erase(const_iterator first, const_iterator last)
+ \since 6.0
+
+ Removes the (key, value) pairs pointed to by the iterator range
+ [\a first, \a last) from the multi map.
+ Returns an iterator to the item in the multi map following the last
+ removed element.
+
+ \note The range \c {[first, last)} \e must be a valid range in \c {*this}.
+
+ \sa remove()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::find(const Key &key)
+
+ Returns an iterator pointing to the item with key \a key in the
+ multi map.
+
+ If the multi map contains no item with key \a key, the function
+ returns end().
+
+ If the map contains multiple items with key \a key, this
+ function returns an iterator that points to the most recently
+ inserted value. The other values are accessible by incrementing
+ the iterator. For example, here's some code that iterates over all
+ the items with the same key:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 11
+
+ \sa constFind(), value(), values(), lowerBound(), upperBound()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::find(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::constFind(const Key &key) const
+ \since 4.1
+
+ Returns an const iterator pointing to the item with key \a key in the
+ multi map.
+
+ If the multi map contains no item with key \a key, the function
+ returns constEnd().
+
+ \sa find(), QMultiMap::constFind()
+*/
+
+/*!
+ \fn template <class Key, class T> typename QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::find(const Key &key, const T &value) const
+ \since 4.3
+ \overload
+
+ Returns a const iterator pointing to the item with the given \a key and
+ \a value in the map.
+
+ If the map contains no such item, the function returns end().
+
+ If the map contains multiple items with the specified \a key, this
+ function returns a const iterator that points to the most recently
+ inserted value.
+*/
+
+/*!
+ \fn template <class Key, class T> typename QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::constFind(const Key &key, const T &value) const
+ \since 4.3
+
+ Returns an iterator pointing to the item with key \a key and the
+ value \a value in the map.
+
+ If the map contains no such item, the function returns
+ constEnd().
+
+ \sa QMap::constFind()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::lowerBound(const Key &key)
+
+ Returns an iterator pointing to the first item with key \a key in
+ the map. If the map contains no item with key \a key, the
+ function returns an iterator to the nearest item with a greater
+ key.
+
+ Example:
+ \snippet code/src_corelib_tools_qmultimap.cpp 15
+
+ If the map contains multiple items with key \a key, this
+ function returns an iterator that points to the most recently
+ inserted value. The other values are accessible by incrementing
+ the iterator. For example, here's some code that iterates over all
+ the items with the same key:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 16
+
+ \sa upperBound(), find()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::lowerBound(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::upperBound(const Key &key)
+
+ Returns an iterator pointing to the item that immediately follows
+ the last item with key \a key in the map. If the map contains no
+ item with key \a key, the function returns an iterator to the
+ nearest item with a greater key.
+
+ Example:
+ \snippet code/src_corelib_tools_qmultimap.cpp 17
+
+ \sa lowerBound(), find()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::upperBound(const Key &key) const
+
+ \overload
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(const Key &key, const T &value)
+
+ Inserts a new item with the key \a key and a value of \a value.
+
+ If there is already an item with the same key in the map, this
+ function will simply create a new one. (This behavior is
+ different from replace(), which overwrites the value of an
+ existing item.)
+
+ Returns an iterator pointing to the new element.
+
+ \sa replace()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(const_iterator pos, const Key &key, const T &value)
+ \overload
+ \since 5.1
+ Inserts a new item with the key \a key and value \a value and with hint \a pos
+ suggesting where to do the insert.
+
+ If constBegin() is used as hint it indicates that the \a key is less than any key in the multi map
+ while constEnd() suggests that the \a key is (strictly) larger than any key in the multi map.
+ Otherwise the hint should meet the condition (\a pos - 1).key() < \a key <= pos.key().
+ If the hint \a pos is wrong it is ignored and a regular insert is done.
+
+ If the hint is correct and the multi map is unshared, the insert executes in amortized \l{constant time}.
+
+ If there is already an item with the same key in the map, this function will simply create a new one.
+
+ When creating a multi map from sorted data inserting the largest key first with constBegin()
+ is faster than inserting in sorted order with constEnd(), since constEnd() - 1 (which is needed
+ to check if the hint is valid) needs \l{logarithmic time}.
+
+ Returns an iterator pointing to the new element.
+
+ \b {Note:} Be careful with the hint. Providing an iterator from an older shared instance might
+ crash but there is also a risk that it will silently corrupt both the multi map and the \a pos multi map.
+*/
+
+#if QT_DEPRECATED_SINCE(6, 0)
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insertMulti(const Key &key, const T &value)
+ \deprecated Use insert() instead.
+
+ Inserts a new item with the key \a key and a value of \a value, and returns an iterator pointing to the new item.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insertMulti(const_iterator pos, const Key &key, const T &value)
+ \deprecated Use insert() instead.
+ \overload
+
+ Inserts a new item with the key \a key and value \a value and with hint \a pos
+ suggesting where to do the insert.
+*/
+
+/*! \fn template <class Key, class T> void QMultiMap<Key, T>::insert(const QMultiMap<Key, T> &map)
+ \since 5.15
+ \deprecated Use unite() instead.
+
+ Inserts all the items in \a map into this map.
+*/
+
+/*! \fn template <class Key, class T> void QMultiMap<Key, T>::insert(QMultiMap<Key, T> &&map)
+ \since 5.15
+ \deprecated Use unite() instead.
+ \overload
+
+ Moves all the items from \a map into this map.
+
+ If \a map is shared, then the items will be copied instead.
+*/
+#endif
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::replace(const Key &key, const T &value)
+
+ Inserts a new item with the key \a key and a value of \a value.
+
+ If there is already an item with the key \a key, that item's value
+ is replaced with \a value.
+
+ If there are multiple items with the key \a key, the most
+ recently inserted item's value is replaced with \a value.
+
+ Returns an iterator pointing to the new/updated element.
+
+ \sa insert()
+*/
+
+/*! \typedef QMultiMap::Iterator
+
+ Qt-style synonym for QMultiMap::iterator.
+*/
+
+/*! \typedef QMultiMap::ConstIterator
+
+ Qt-style synonym for QMultiMap::const_iterator.
+*/
+
+/*! \typedef QMultiMap::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \typedef QMultiMap::key_type
+
+ Typedef for Key. Provided for STL compatibility.
+*/
+
+/*! \typedef QMultiMap::mapped_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*! \typedef QMultiMap::size_type
+
+ Typedef for int. Provided for STL compatibility.
+*/
+
+/*!
+ \fn template <class Key, class T> bool QMultiMap<Key, T>::empty() const
+
+ This function is provided for STL compatibility. It is equivalent
+ to isEmpty(), returning true if the map is empty; otherwise
+ returning false.
+*/
+
+/*!
+ \fn template <class Key, class T> std::pair<typename QMultiMap<Key, T>::iterator, typename QMultiMap<Key, T>::iterator> QMultiMap<Key, T>::equal_range(const Key &key)
+
+ Returns a pair of iterators delimiting the range of values \c{[first, second)}, that
+ are stored under \a key.
+*/
+
+/*!
+ \fn template <class Key, class T> std::pair<typename QMultiMap<Key, T>::const_iterator, typename QMultiMap<Key, T>::const_iterator> QMultiMap<Key, T>::equal_range(const Key &key) const
+ \overload
+ \since 5.6
+*/
+
+/*!
+ \fn template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::unite(const QMultiMap<Key, T> &other)
+
+ Inserts all the items in the \a other map into this map. If a
+ key is common to both maps, the resulting map will contain the
+ key multiple times.
+*/
+
+/*!
+ \fn template <class Key, class T> QMultiMap<Key, T> &QMultiMap<Key, T>::unite(QMultiMap<Key, T> &&other)
+
+ Moves all the items from the \a other map into this map. If a
+ key is common to both maps, the resulting map will contain the
+ key multiple times.
+
+ If \a other is shared, then the items will be copied instead.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T> operator+=(QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
+ \relates QMultiMap
+
+ Inserts all the items in the \a rhs map into the \a lhs map and
+ returns the resulting map.
+
+ \sa insert(), operator+()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
+ \relates QMultiMap
+
+ Returns a map that contains all the items in the \a lhs map in
+ addition to all the items in \a rhs. If a key is common to both
+ maps, the resulting map will contain the key multiple times.
+
+ \sa operator+=()
+*/
+
+/*! \class QMultiMap::iterator
+ \inmodule QtCore
+ \brief The QMultiMap::iterator class provides an STL-style non-const iterator for QMultiMap.
+
+ QMultiMap\<Key, T\>::iterator allows you to iterate over a QMultiMap
+ and to modify the value (but not the key) stored under
+ a particular key. If you want to iterate over a const QMultiMap, you
+ should use QMultiMap::const_iterator. It is generally good practice to
+ use QMultiMap::const_iterator on a non-const QMultiMap as well, unless you
+ need to change the QMultiMap through the iterator. Const iterators are
+ slightly faster, and can improve code readability.
+
+ The default QMultiMap::iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QMultiMap function like
+ QMultiMap::begin(), QMultiMap::end(), or QMultiMap::find() before you can
+ start iterating. Here's a typical loop that prints all the (key,
+ value) pairs stored in a map:
+
+ Unlike QMultiHash, which stores its items in an arbitrary order, QMultiMap
+ stores its items ordered by key. Items that share the same key
+ will appear consecutively,
+ from the most recently to the least recently inserted value.
+
+ Here's an example that increments every value stored in the QMultiMap
+ by 2:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 19
+
+ To remove elements from a QMultiMap you can use erase_if(QMultiMap\<Key, T\> &map, Predicate pred):
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 21
+
+ Multiple iterators can be used on the same map. If you add items
+ to the map, existing iterators will remain valid. If you remove
+ items from the map, iterators that point to the removed items
+ will become dangling iterators.
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+
+ \sa QMultiMap::const_iterator, QMultiMap::key_iterator, QMultiMap::key_value_iterator
+*/
+
+/*! \typedef QMultiMap::iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QMultiMap::iterator::iterator_category
+
+ A synonym for \e {std::bidirectional_iterator_tag} indicating
+ this iterator is a bidirectional iterator.
+*/
+
+/*! \typedef QMultiMap::iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QMultiMap::iterator::reference
+
+ \internal
+*/
+
+/*! \typedef QMultiMap::iterator::value_type
+
+ \internal
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator::iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like key(), value(), and operator++() must not be
+ called on an uninitialized iterator. Use operator=() to assign a
+ value to it before using it.
+
+ \sa QMultiMap::begin(), QMultiMap::end()
+*/
+
+/*! \fn template <class Key, class T> const Key &QMultiMap<Key, T>::iterator::key() const
+
+ Returns the current item's key as a const reference.
+
+ There is no direct way of changing an item's key through an
+ iterator, although it can be done by calling QMultiMap::erase()
+ followed by QMultiMap::insert().
+
+ \sa value()
+*/
+
+/*! \fn template <class Key, class T> T &QMultiMap<Key, T>::iterator::value() const
+
+ Returns a modifiable reference to the current item's value.
+
+ You can change the value of an item by using value() on
+ the left side of an assignment, for example:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 23
+
+ \sa key(), operator*()
+*/
+
+/*! \fn template <class Key, class T> T &QMultiMap<Key, T>::iterator::operator*() const
+
+ Returns a modifiable reference to the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn template <class Key, class T> T *QMultiMap<Key, T>::iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*!
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
+
+ Returns \c true if \a lhs points to the same item as the \a rhs iterator;
+ otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn template<class Key, class T> bool QMultiMap<Key, T>::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
+
+ Returns \c true if \a lhs points to a different item than the \a rhs iterator;
+ otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator &QMultiMap<Key, T>::iterator::operator++()
+
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
+ next item in the multi map and returns an iterator to the new current
+ item.
+
+ Calling this function on QMultiMap::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
+ next item in the multi map and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator &QMultiMap<Key, T>::iterator::operator--()
+
+ The prefix \c{--} operator (\c{--i}) makes the preceding item
+ current and returns an iterator pointing to the new current item.
+
+ Calling this function on QMultiMap::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{i--}) makes the preceding item
+ current and returns an iterator pointing to the previously
+ current item.
+*/
+
+/*!
+ //! friends
+ \fn [qmultimap-op-it-plus-step] template <class Key, class T> typename QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator+(QMultiMap<Key, T>::iterator, difference_type n)
+ \fn [qmultimap-op-step-plus-it] template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator+(difference_type n, QMultiMap<Key, T>::iterator)
+ \fn [qmultimap-op-it-minus-step] template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator-(QMultiMap<Key, T>::iterator, difference_type n)
+ \fn [qmultimap-op-step-minus-it] template <class Key, class T> QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator-(difference_type n, QMultiMap<Key, T>::iterator)
+
+ //! members
+ \fn template <class Key, class T> typename QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator+=(QMultiMap<Key, T>::iterator::difference_type n)
+ \fn template <class Key, class T> typename QMultiMap<Key, T>::iterator QMultiMap<Key, T>::iterator::operator-=(QMultiMap<Key, T>::iterator::difference_type n)
+
+ \deprecated [6.2] Use \c{std::next}, \c{std::prev} or \c{std::advance} instead.
+
+ Move an iterator by \e{n} positions. These operations can be
+ expensive for large values of \e{n}; QMultiMap iterators are not
+ random access.
+*/
+
+/*! \class QMultiMap::const_iterator
+ \inmodule QtCore
+ \brief The QMultiMap::const_iterator class provides an STL-style const iterator for QMultiMap.
+
+ QMultiMap\<Key, T\>::const_iterator allows you to iterate over a QMultiMap.
+ If you want to modify the QMultiMap as you iterate
+ over it, you must use QMultiMap::iterator instead. It is generally
+ good practice to use QMultiMap::const_iterator on a non-const QMultiMap as
+ well, unless you need to change the QMultiMap through the iterator.
+ Const iterators are slightly faster, and can improve code
+ readability.
+
+ The default QMultiMap::const_iterator constructor creates an
+ uninitialized iterator. You must initialize it using a QMultiMap
+ function like QMultiMap::cbegin(), QMultiMap::cend(), or
+ QMultiMap::constFind() before you can start iterating. Here's a typical
+ loop that prints all the (key, value) pairs stored in a map:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 24
+
+ Here's an example that removes all the items whose value is greater than 10:
+
+ \snippet code/src_corelib_tools_qmultimap.cpp 20
+
+ Unlike QMultiHash, which stores its items in an arbitrary order, QMultiMap
+ stores its items ordered by key. Items that share the same key
+ will appear consecutively,
+ from the most recently to the least recently inserted value.
+
+ Multiple iterators can be used on the same multi map. If you add items
+ to the map, existing iterators will remain valid. If you remove
+ items from the map, iterators that point to the removed items
+ will become dangling iterators.
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+
+ \sa QMultiMap::iterator, QMultiMap::key_iterator, QMultiMap::const_key_value_iterator
+*/
+
+/*! \typedef QMultiMap::const_iterator::difference_type
+
+ \internal
+*/
+
+/*! \typedef QMultiMap::const_iterator::iterator_category
+
+ A synonym for \e {std::bidirectional_iterator_tag} indicating
+ this iterator is a bidirectional iterator.
+*/
+
+/*! \typedef QMultiMap::const_iterator::pointer
+
+ \internal
+*/
+
+/*! \typedef QMultiMap::const_iterator::reference
+
+ \internal
+*/
+
+/*! \typedef QMultiMap::const_iterator::value_type
+
+ \internal
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like key(), value(), and operator++() must not be
+ called on an uninitialized iterator. Use operator=() to assign a
+ value to it before using it.
+
+ \sa QMultiMap::constBegin(), QMultiMap::constEnd()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator::const_iterator(const iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn template <class Key, class T> const Key &QMultiMap<Key, T>::const_iterator::key() const
+
+ Returns the current item's key.
+
+ \sa value()
+*/
+
+/*! \fn template <class Key, class T> const T &QMultiMap<Key, T>::const_iterator::value() const
+
+ Returns the current item's value.
+
+ \sa key(), operator*()
+*/
+
+/*! \fn template <class Key, class T> const T &QMultiMap<Key, T>::const_iterator::operator*() const
+
+ Returns the current item's value.
+
+ Same as value().
+
+ \sa key()
+*/
+
+/*! \fn template <class Key, class T> const T *QMultiMap<Key, T>::const_iterator::operator->() const
+
+ Returns a pointer to the current item's value.
+
+ \sa value()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator &QMultiMap<Key, T>::const_iterator::operator++()
+
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
+ next item in the map and returns an iterator to the new current
+ item.
+
+ Calling this function on QMultiMap::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
+ next item in the map and returns an iterator to the previously
+ current item.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator &QMultiMap<Key, T>::const_iterator::operator--()
+
+ The prefix \c{--} operator (\c{--i}) makes the preceding item
+ current and returns an iterator pointing to the new current item.
+
+ Calling this function on QMultiMap::begin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{i--}) makes the preceding item
+ current and returns an iterator pointing to the previously
+ current item.
+*/
+
+/*!
+ //! friends
+ \fn [qmultimap-op-it-plus-step-const] template <class Key, class T> typename QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator+(QMultiMap<Key, T>::const_iterator, difference_type n)
+ \fn [qmultimap-op-step-plus-it-const] template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator+(difference_type n, QMultiMap<Key, T>::const_iterator)
+ \fn [qmultimap-op-it-minus-step-const] template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator-(QMultiMap<Key, T>::const_iterator, difference_type n)
+ \fn [qmultimap-op-step-minus-it-const] template <class Key, class T> QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator-(difference_type n, QMultiMap<Key, T>::const_iterator)
+
+ //! members
+ \fn template <class Key, class T> typename QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator+=(QMultiMap<Key, T>::const_iterator::difference_type n)
+ \fn template <class Key, class T> typename QMultiMap<Key, T>::const_iterator QMultiMap<Key, T>::const_iterator::operator-=(QMultiMap<Key, T>::const_iterator::difference_type n)
+
+ \deprecated [6.2] Use \c{std::next}, \c{std::prev} or \c{std::advance} instead.
+
+ Move an iterator by \e{n} positions. These operations can be
+ expensive for large values of \e{n}. QMultiMap iterators are not
+ random access.
+*/
+
+/*! \class QMultiMap::key_iterator
+ \inmodule QtCore
+ \since 5.6
+ \brief The QMultiMap::key_iterator class provides an STL-style const iterator for QMultiMap keys.
+
+ QMultiMap::key_iterator is essentially the same as QMultiMap::const_iterator
+ with the difference that operator*() and operator->() return a key
+ instead of a value.
+
+ For most uses QMultiMap::iterator and QMultiMap::const_iterator should be used,
+ you can easily access the key by calling QMultiMap::iterator::key():
+
+ \snippet code/src_corelib_tools_qmultimap.cpp keyiterator1
+
+ However, to have interoperability between QMultiMap's keys and STL-style
+ algorithms we need an iterator that dereferences to a key instead
+ of a value. With QMultiMap::key_iterator we can apply an algorithm to a
+ range of keys without having to call QMultiMap::keys(), which is inefficient
+ as it costs one QMultiMap iteration and memory allocation to create a temporary
+ QList.
+
+ \snippet code/src_corelib_tools_qmultimap.cpp keyiterator2
+
+ QMultiMap::key_iterator is const, it's not possible to modify the key.
+
+ The default QMultiMap::key_iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QMultiMap function like
+ QMultiMap::keyBegin() or QMultiMap::keyEnd().
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+
+ \sa QMultiMap::const_iterator, QMultiMap::iterator
+*/
+
+/*! \typedef QMultiMap::key_iterator::difference_type
+ \internal
+*/
+
+/*! \typedef QMultiMap::key_iterator::iterator_category
+ \internal
+*/
+
+/*! \typedef QMultiMap::key_iterator::pointer
+ \internal
+*/
+
+/*! \typedef QMultiMap::key_iterator::reference
+ \internal
+*/
+
+/*! \typedef QMultiMap::key_iterator::value_type
+ \internal
+*/
+
+/*! \fn template <class Key, class T> const T &QMultiMap<Key, T>::key_iterator::operator*() const
+
+ Returns the current item's key.
+*/
+
+/*! \fn template <class Key, class T> const T *QMultiMap<Key, T>::key_iterator::operator->() const
+
+ Returns a pointer to the current item's key.
+*/
+
+/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::key_iterator::operator==(key_iterator other) const
+
+ Returns \c true if \a other points to the same item as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*! \fn template <class Key, class T> bool QMultiMap<Key, T>::key_iterator::operator!=(key_iterator other) const
+
+ Returns \c true if \a other points to a different item than this
+ iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn template <class Key, class T> QMultiMap<Key, T>::key_iterator &QMultiMap<Key, T>::key_iterator::operator++()
+
+ The prefix \c{++} operator (\c{++i}) advances the iterator to the
+ next item in the hash and returns an iterator to the new current
+ item.
+
+ Calling this function on QMultiMap::keyEnd() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_iterator QMultiMap<Key, T>::key_iterator::operator++(int)
+
+ \overload
+
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
+ next item in the hash and returns an iterator to the previous
+ item.
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_iterator &QMultiMap<Key, T>::key_iterator::operator--()
+
+ The prefix \c{--} operator (\c{--i}) makes the preceding item
+ current and returns an iterator pointing to the new current item.
+
+ Calling this function on QMultiMap::keyBegin() leads to undefined
+ results.
+
+ \sa operator++()
+*/
+
+/*! \fn template <class Key, class T> QMultiMap<Key, T>::key_iterator QMultiMap<Key, T>::key_iterator::operator--(int)
+
+ \overload
+
+ The postfix \c{--} operator (\c{i--}) makes the preceding item
+ current and returns an iterator pointing to the previous
+ item.
+*/
+
+/*! \fn template <class Key, class T> const_iterator QMultiMap<Key, T>::key_iterator::base() const
+ Returns the underlying const_iterator this key_iterator is based on.
+*/
+
+/*! \typedef QMultiMap::const_key_value_iterator
+ \inmodule QtCore
+ \since 5.10
+ \brief The QMultiMap::const_key_value_iterator typedef provides an STL-style iterator for QMultiMap.
+
+ QMultiMap::const_key_value_iterator is essentially the same as QMultiMap::const_iterator
+ with the difference that operator*() returns a key/value pair instead of a
+ value.
+
+ \sa QKeyValueIterator
+*/
+
+/*! \typedef QMultiMap::key_value_iterator
+ \inmodule QtCore
+ \since 5.10
+ \brief The QMultiMap::key_value_iterator typedef provides an STL-style iterator for QMultiMap.
+
+ QMultiMap::key_value_iterator is essentially the same as QMultiMap::iterator
+ with the difference that operator*() returns a key/value pair instead of a
+ value.
+
+ \sa QKeyValueIterator
+*/
+
+/*! \fn template <class Key, class T> QDataStream &operator<<(QDataStream &out, const QMultiMap<Key, T> &map)
+ \relates QMultiMap
+
+ Writes the multi map \a map to stream \a out.
+
+ This function requires the key and value types to implement \c
+ operator<<().
+
+ \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
+
+/*! \fn template <class Key, class T> QDataStream &operator>>(QDataStream &in, QMultiMap<Key, T> &map)
+ \relates QMultiMap
+
+ Reads a map from stream \a in into \a map.
+
+ This function requires the key and value types to implement \c
+ operator>>().
+
+ \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
+
+/*! \fn template <typename Key, typename T, typename Predicate> qsizetype erase_if(QMultiMap<Key, T> &map, Predicate pred)
+ \relates QMultiMap
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the multi map \a map.
+
+ The function supports predicates which take either an argument of
+ type \c{QMultiMap<Key, T>::iterator}, or an argument of type
+ \c{std::pair<const Key &, T &>}.
+
+ Returns the number of elements removed, if any.
+*/
diff --git a/src/corelib/tools/qoffsetstringarray_p.h b/src/corelib/tools/qoffsetstringarray_p.h
index 4dd9e9603b..9103606a13 100644
--- a/src/corelib/tools/qoffsetstringarray_p.h
+++ b/src/corelib/tools/qoffsetstringarray_p.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOFFSETSTRINGARRAY_P_H
#define QOFFSETSTRINGARRAY_P_H
@@ -53,146 +18,143 @@
#include "private/qglobal_p.h"
-#include <tuple>
+#include <QByteArrayView>
+
+#include <QtCore/q20algorithm.h>
#include <array>
+#include <limits>
+#include <string_view>
+#include <tuple>
-QT_BEGIN_NAMESPACE
+class tst_QOffsetStringArray;
-namespace QtPrivate {
-template<int N, int O, int I, int ... Idx>
-struct OffsetSequenceHelper : OffsetSequenceHelper<N - 1, O + I, Idx..., O> { };
+QT_BEGIN_NAMESPACE
-template<int Last, int I, int S, int ... Idx>
-struct OffsetSequenceHelper<1, Last, I, S, Idx...> : IndexesList<Last + I, Idx..., Last>
-{
- static const constexpr auto Length = Last + I;
- using Type = typename std::conditional<
- Last <= std::numeric_limits<quint8>::max(),
- quint8,
- typename std::conditional<
- Last <= std::numeric_limits<quint16>::max(),
- quint16,
- int>::type
- >::type;
-};
+QT_WARNING_PUSH
+#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
+// we usually don't overread, but GCC has a false positive
+QT_WARNING_DISABLE_GCC("-Wstringop-overread")
+#endif
-template<int ... Idx>
-struct OffsetSequence : OffsetSequenceHelper<sizeof ... (Idx), 0, Idx..., 0> { };
-template<int N>
-struct StaticString
+template <typename StaticString, typename OffsetList>
+class QOffsetStringArray
{
- const char data[N];
-};
+public:
+ constexpr QOffsetStringArray(const StaticString &string, const OffsetList &offsets)
+ : m_string(string), m_offsets(offsets)
+ {}
+ constexpr const char *operator[](const int index) const noexcept
+ {
+ return m_string.data() + m_offsets[qBound(int(0), index, count())];
+ }
-template<>
-struct StaticString<0>
-{
- static constexpr int size() noexcept
+ constexpr const char *at(const int index) const noexcept
{
- return 0;
+ return m_string.data() + m_offsets[index];
}
-};
-template<typename, typename>
-struct StaticStringBuilder;
+ constexpr QByteArrayView viewAt(qsizetype index) const noexcept
+ {
+ return { m_string.data() + m_offsets[index],
+ qsizetype(m_offsets[index + 1]) - qsizetype(m_offsets[index]) - 1 };
+ }
-template<int ... I1, int ... I2>
-struct StaticStringBuilder<IndexesList<I1...>, IndexesList<I2...>>
-{
+ constexpr int count() const { return int(m_offsets.size()) - 1; }
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4100) // The formal parameter is not referenced in the body of the function.
- // The unreferenced parameter is ignored.
- // It happens when 'rs' is StaticString<0>
- template<int N1, int N2>
- static constexpr StaticString<N1 + N2> concatenate(
- const char (&ls)[N1], const StaticString<N2> &rs) noexcept
+ bool contains(QByteArrayView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{
- return StaticString<N1 + N2>{{ls[I1]..., rs.data[I2]...}};
+ for (qsizetype i = 0; i < count(); ++i) {
+ if (viewAt(i).compare(needle, cs) == 0)
+ return true;
+ }
+ return false;
}
-QT_WARNING_POP
+
+private:
+ StaticString m_string;
+ OffsetList m_offsets;
+ friend tst_QOffsetStringArray;
};
-template<int Sum>
-constexpr StaticString<0> staticString() noexcept
+namespace QtPrivate {
+template <size_t Highest> constexpr auto minifyValue()
{
- return StaticString<0>{};
+ constexpr size_t max8 = (std::numeric_limits<quint8>::max)();
+ constexpr size_t max16 = (std::numeric_limits<quint16>::max)();
+ if constexpr (Highest <= max8) {
+ return quint8(Highest);
+ } else if constexpr (Highest <= max16) {
+ return quint16(Highest);
+ } else {
+ // int is probably enough for everyone
+ return int(Highest);
+ }
}
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4503)
-template<int Sum, int I, int ... Ix>
-constexpr StaticString<Sum> staticString(const char (&s)[I], const char (&...sx)[Ix]) noexcept
+template <size_t StringLength, typename Extractor, typename... T>
+constexpr auto makeStaticString(Extractor extract, const T &... entries)
{
- return StaticStringBuilder<
- makeIndexSequence<I>,
- makeIndexSequence<Sum - I>>::concatenate(s, staticString<Sum - I>(sx...));
+ std::array<char, StringLength> result = {};
+ qptrdiff offset = 0;
+
+ const char *strings[] = { extract(entries).operator const char *()... };
+ size_t lengths[] = { sizeof(extract(T{}))... };
+ for (size_t i = 0; i < std::size(strings); ++i) {
+ q20::copy_n(strings[i], lengths[i], result.begin() + offset);
+ offset += lengths[i];
+ }
+ return result;
}
-QT_WARNING_POP
-} // namespace QtPrivate
-template<typename T, int SizeString, int SizeOffsets>
-class QOffsetStringArray
+template <size_t N> struct StaticString
{
-public:
- using Type = T;
-
- template<int ... Ox>
- constexpr QOffsetStringArray(const QtPrivate::StaticString<SizeString> &str,
- QtPrivate::IndexesList<SizeString, Ox...>) noexcept
- : m_string(str),
- m_offsets{Ox...}
- { }
-
- constexpr inline const char *operator[](const int index) const noexcept
- {
- return m_string.data + m_offsets[qBound(int(0), index, SizeOffsets - 1)];
- }
+ char value[N] = {};
+ constexpr StaticString() = default;
+ constexpr StaticString(const char (&s)[N]) { q20::copy_n(s, N, value); }
+ constexpr operator const char *() const { return value; }
+};
- constexpr inline const char *at(const int index) const noexcept
- {
- return m_string.data + m_offsets[index];
- }
+template <size_t KL, size_t VL> struct StaticMapEntry
+{
+ StaticString<KL> key = {};
+ StaticString<VL> value = {};
+ constexpr StaticMapEntry() = default;
+ constexpr StaticMapEntry(const char (&k)[KL], const char (&v)[VL])
+ : key(k), value(v)
+ {}
+};
- constexpr inline const char *str() const { return m_string.data; }
- constexpr inline const T *offsets() const { return m_offsets; }
- constexpr inline int count() const { return SizeOffsets; };
+template <typename StringExtractor, typename... T>
+constexpr auto makeOffsetStringArray(StringExtractor extractString, const T &... entries)
+{
+ constexpr size_t Count = sizeof...(T);
+ constexpr size_t StringLength = (sizeof(extractString(T{})) + ...);
+ using MinifiedOffsetType = decltype(QtPrivate::minifyValue<StringLength>());
- static constexpr const auto sizeString = SizeString;
- static constexpr const auto sizeOffsets = SizeOffsets;
+ size_t offset = 0;
+ std::array fullOffsetList = { offset += sizeof(extractString(T{}))... };
-private:
- QtPrivate::StaticString<SizeString> m_string;
- const T m_offsets[SizeOffsets];
-};
+ // prepend zero
+ std::array<MinifiedOffsetType, Count + 1> minifiedOffsetList = {};
+ q20::transform(fullOffsetList.begin(), fullOffsetList.end(),
+ minifiedOffsetList.begin() + 1,
+ [] (auto e) { return MinifiedOffsetType(e); });
-template<typename T, int N, int ... Ox>
-constexpr QOffsetStringArray<T, N, sizeof ... (Ox)> qOffsetStringArray(
- const QtPrivate::StaticString<N> &string,
- QtPrivate::IndexesList<N, Ox...> offsets) noexcept
-{
- return QOffsetStringArray<T, N, sizeof ... (Ox)>(
- string,
- offsets);
+ std::array staticString = QtPrivate::makeStaticString<StringLength>(extractString, entries...);
+ return QOffsetStringArray(staticString, minifiedOffsetList);
}
+} // namespace QtPrivate
template<int ... Nx>
-struct QOffsetStringArrayRet
-{
- using Offsets = QtPrivate::OffsetSequence<Nx...>;
- using Type = QOffsetStringArray<typename Offsets::Type, Offsets::Length, sizeof ... (Nx)>;
-};
-
-template<int ... Nx>
-constexpr auto qOffsetStringArray(const char (&...strings)[Nx]) noexcept -> typename QOffsetStringArrayRet<Nx...>::Type
+constexpr auto qOffsetStringArray(const char (&...strings)[Nx]) noexcept
{
- using Offsets = QtPrivate::OffsetSequence<Nx...>;
- return qOffsetStringArray<typename Offsets::Type>(
- QtPrivate::staticString<Offsets::Length>(strings...), Offsets{});
+ auto extractString = [](const auto &s) -> decltype(auto) { return s; };
+ return QtPrivate::makeOffsetStringArray(extractString, QtPrivate::StaticString(strings)...);
}
+QT_WARNING_POP
QT_END_NAMESPACE
#endif // QOFFSETSTRINGARRAY_P_H
diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h
index 6cb7fc5079..84f99075e1 100644
--- a/src/corelib/tools/qpair.h
+++ b/src/corelib/tools/qpair.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAIR_H
#define QPAIR_H
+#include <QtCore/qcontainerfwd.h>
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
@@ -48,8 +13,7 @@ QT_BEGIN_NAMESPACE
#pragma qt_class(QPair)
#endif
-template <typename T1, typename T2>
-using QPair = std::pair<T1, T2>;
+#ifndef QT_NO_QPAIR
template <typename T1, typename T2>
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2)
@@ -58,8 +22,7 @@ constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2)
return std::make_pair(std::forward<T1>(value1), std::forward<T2>(value2));
}
-template<class T1, class T2>
-class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
+#endif // QT_NO_QPAIR
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc
index 0e17b6c3b9..3aaee157d4 100644
--- a/src/corelib/tools/qpair.qdoc
+++ b/src/corelib/tools/qpair.qdoc
@@ -1,48 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
- \class QPair
- \inmodule QtCore
- \obsolete
- \brief QPair is an alias for std::pair.
-
- \ingroup tools
-
- QPair\<T1, T2\> is a typedef for std::pair\<T1, T2\>.
- It is provided for backwards compatibility. Use std::pair directly
- instead.
-
- \sa {Container Classes}
+ \typealias QPair
+ \relates QPair
+ \since 6.0
+ Typedef for std::pair\<T1, T2\>.
*/
/*!
\fn template <class T1, class T2> QPair<T1, T2> qMakePair(T1 &&value1, T2 &&value2)
- \obsolete
+ \deprecated
\relates QPair
qMakePair forwards its arguments to std::make_pair, and returns
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index 432fb33297..775a354469 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpoint.h"
#include "qdatastream.h"
#include <private/qdebug_p.h>
+#include <QtCore/qhashfunctions.h>
QT_BEGIN_NAMESPACE
@@ -50,6 +15,10 @@ QT_BEGIN_NAMESPACE
\ingroup painting
\reentrant
+ \compares equality
+ \compareswith equality QPointF
+ \endcompareswith
+
\brief The QPoint class defines a point in the plane using integer
precision.
@@ -243,23 +212,21 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool operator==(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn bool QPoint::operator==(const QPoint &lhs, const QPoint &rhs)
- Returns \c true if \a p1 and \a p2 are equal; otherwise returns
- false.
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns
+ \c false.
*/
/*!
- \fn bool operator!=(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn bool QPoint::operator!=(const QPoint &lhs, const QPoint &rhs)
- Returns \c true if \a p1 and \a p2 are not equal; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are not equal; otherwise returns
+ \c false.
*/
/*!
- \fn const QPoint operator+(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn QPoint QPoint::operator+(const QPoint &p1, const QPoint &p2)
Returns a QPoint object that is the sum of the given points, \a p1
and \a p2; each component is added separately.
@@ -268,8 +235,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator-(const QPoint &p1, const QPoint &p2)
- \relates QPoint
+ \fn Point QPoint::operator-(const QPoint &p1, const QPoint &p2)
Returns a QPoint object that is formed by subtracting \a p2 from
\a p1; each component is subtracted separately.
@@ -278,8 +244,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(const QPoint &point, float factor)
- \relates QPoint
+ \fn QPoint QPoint::operator*(const QPoint &point, float factor)
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -290,8 +255,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(const QPoint &point, double factor)
- \relates QPoint
+ \fn QPoint QPoint::operator*(const QPoint &point, double factor)
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -302,8 +266,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(const QPoint &point, int factor)
- \relates QPoint
+ \fn QPoint QPoint::operator*(const QPoint &point, int factor)
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -311,9 +274,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(float factor, const QPoint &point)
+ \fn QPoint QPoint::operator*(float factor, const QPoint &point)
\overload
- \relates QPoint
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -324,9 +286,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(double factor, const QPoint &point)
+ \fn QPoint QPoint::operator*(double factor, const QPoint &point)
\overload
- \relates QPoint
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -337,9 +298,8 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator*(int factor, const QPoint &point)
+ \fn QPoint QPoint::operator*(int factor, const QPoint &point)
\overload
- \relates QPoint
Returns a copy of the given \a point multiplied by the given \a factor.
@@ -347,17 +307,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator+(const QPoint &point)
- \relates QPoint
+ \fn QPoint QPoint::operator+(const QPoint &point)
\since 5.0
Returns \a point unmodified.
*/
/*!
- \fn const QPoint operator-(const QPoint &point)
+ \fn QPoint QPoint::operator-(const QPoint &point)
\overload
- \relates QPoint
Returns a QPoint object that is formed by changing the sign of
both components of the given \a point.
@@ -381,8 +339,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QPoint operator/(const QPoint &point, qreal divisor)
- \relates QPoint
+ \fn const QPoint QPoint::operator/(const QPoint &point, qreal divisor)
Returns the QPoint formed by dividing both components of the given \a point
by the given \a divisor.
@@ -393,6 +350,15 @@ QT_BEGIN_NAMESPACE
\sa QPoint::operator/=()
*/
+/*!
+ \fn QPoint::toPointF() const
+ \since 6.4
+
+ Returns this point as a point with floating point accuracy.
+
+ \sa QPointF::toPoint()
+*/
+
/*****************************************************************************
QPoint stream functions
*****************************************************************************/
@@ -484,17 +450,34 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
#endif
/*!
+ \fn size_t qHash(QPoint key, size_t seed = 0)
+ \relates QHash
+ \since 6.0
+
+ Returns the hash value for the \a key, using \a seed to seed the
+ calculation.
+*/
+size_t qHash(QPoint key, size_t seed) noexcept
+{
+ return qHashMulti(seed, key.x(), key.y());
+}
+
+/*!
\class QPointF
\inmodule QtCore
\ingroup painting
\reentrant
+ \compares equality
+ \compareswith equality QPoint
+ \endcompareswith
+
\brief The QPointF class defines a point in the plane using
floating point precision.
A point is specified by a x coordinate and an y coordinate which
can be accessed using the x() and y() functions. The coordinates
- of the point are specified using floating point numbers for
+ of the point are specified using finite floating point numbers for
accuracy. The isNull() function returns \c true if both x and y are
set to 0.0. The coordinates can be set (or altered) using the setX()
and setY() functions, or alternatively the rx() and ry() functions which
@@ -531,7 +514,7 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
Constructs a copy of the given \a point.
- \sa toPoint()
+ \sa toPoint(), QPoint::toPointF()
*/
/*!
@@ -580,7 +563,7 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
/*!
\fn void QPointF::setX(qreal x)
- Sets the x coordinate of this point to the given \a x coordinate.
+ Sets the x coordinate of this point to the given finite \a x coordinate.
\sa x(), setY()
*/
@@ -588,7 +571,7 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
/*!
\fn void QPointF::setY(qreal y)
- Sets the y coordinate of this point to the given \a y coordinate.
+ Sets the y coordinate of this point to the given finite \a y coordinate.
\sa y(), setX()
*/
@@ -654,7 +637,7 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
/*!
\fn QPointF& QPointF::operator*=(qreal factor)
- Multiplies this point's coordinates by the given \a factor, and
+ Multiplies this point's coordinates by the given finite \a factor, and
returns a reference to this point. For example:
\snippet code/src_corelib_tools_qpoint.cpp 14
@@ -670,12 +653,13 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
\snippet code/src_corelib_tools_qpoint.cpp 15
+ The \a divisor must not be zero or NaN.
+
\sa operator*=()
*/
/*!
- \fn const QPointF operator+(const QPointF &p1, const QPointF &p2)
- \relates QPointF
+ \fn QPointF QPointF::operator+(const QPointF &p1, const QPointF &p2)
Returns a QPointF object that is the sum of the given points, \a p1
and \a p2; each component is added separately.
@@ -684,8 +668,7 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
*/
/*!
- \fn const QPointF operator-(const QPointF &p1, const QPointF &p2)
- \relates QPointF
+ \fn QPointF QPointF::operator-(const QPointF &p1, const QPointF &p2)
Returns a QPointF object that is formed by subtracting \a p2 from \a p1;
each component is subtracted separately.
@@ -694,49 +677,46 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
*/
/*!
- \fn const QPointF operator*(const QPointF &point, qreal factor)
- \relates QPointF
+ \fn QPointF QPointF::operator*(const QPointF &point, qreal factor)
- Returns a copy of the given \a point, multiplied by the given \a factor.
+ Returns a copy of the given \a point, multiplied by the given finite \a factor.
\sa QPointF::operator*=()
*/
/*!
- \fn const QPointF operator*(qreal factor, const QPointF &point)
- \relates QPointF
+ \fn QPointF QPointF::operator*(qreal factor, const QPointF &point)
\overload
- Returns a copy of the given \a point, multiplied by the given \a factor.
+ Returns a copy of the given \a point, multiplied by the given finite \a factor.
*/
/*!
- \fn const QPointF operator+(const QPointF &point)
- \relates QPointF
+ \fn QPointF QPointF::operator+(const QPointF &point)
\since 5.0
Returns \a point unmodified.
*/
/*!
- \fn const QPointF operator-(const QPointF &point)
- \relates QPointF
+ \fn QPointF QPointF::operator-(const QPointF &point)
\overload
Returns a QPointF object that is formed by changing the sign of
- both components of the given \a point.
+ each component of the given \a point.
Equivalent to \c {QPointF(0,0) - point}.
*/
/*!
- \fn const QPointF operator/(const QPointF &point, qreal divisor)
- \relates QPointF
+ \fn QPointF QPointF::operator/(const QPointF &point, qreal divisor)
- Returns the QPointF object formed by dividing both components of
+ Returns the QPointF object formed by dividing each component of
the given \a point by the given \a divisor.
+ The \a divisor must not be zero or NaN.
+
\sa QPointF::operator/=()
*/
@@ -746,7 +726,7 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
Rounds the coordinates of this point to the nearest integer, and
returns a QPoint object with the rounded coordinates.
- \sa QPointF()
+ \sa QPointF(), QPoint::toPointF()
*/
/*!
@@ -759,17 +739,47 @@ QDebug operator<<(QDebug dbg, const QPointF &p)
*/
/*!
- \fn bool operator==(const QPointF &p1, const QPointF &p2)
- \relates QPointF
+ \fn bool QPointF::operator==(const QPointF &lhs, const QPointF &rhs)
+
+ Returns \c true if \a lhs is approximately equal to \a rhs; otherwise
+ returns \c false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the points' coordinates.
- Returns \c true if \a p1 is equal to \a p2; otherwise returns \c false.
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QPointF &p1, const QPointF &p2);
- \relates QPointF
+ \fn bool QPointF::operator!=(const QPointF &lhs, const QPointF &rhs)
+
+ Returns \c true if \a lhs is sufficiently different from \a rhs;
+ otherwise returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the points' coordinates.
+
+ \sa qFuzzyCompare
+*/
+
+/*!
+ \fn bool QPointF::qFuzzyCompare(const QPointF &p1, const QPointF &p2)
+ \since 6.8
+
+ Returns \c true if \a p1 is approximately equal to \a p2; otherwise
+ returns \c false.
+
+ \sa qFuzzyIsNull
+*/
+
+/*!
+ \fn bool QPointF::qFuzzyIsNull(const QPointF &point)
+ \since 6.8
+
+ Returns \c true if \a point is approximately equal to a point
+ \c {(0.0, 0.0)}.
- Returns \c true if \a p1 is not equal to \a p2; otherwise returns \c false.
+ \sa qFuzzyCompare
*/
#ifndef QT_NO_DATASTREAM
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index 725787265f..50b4c864be 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -1,46 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPOINT_H
#define QPOINT_H
+#include <QtCore/qcompare.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qnumeric.h>
+
+#include <QtCore/q20type_traits.h>
+#include <QtCore/q23utility.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGPoint;
@@ -48,6 +17,9 @@ struct CGPoint;
QT_BEGIN_NAMESPACE
+QT_ENABLE_P0846_SEMANTICS_FOR(get)
+
+class QPointF;
class QPoint
{
@@ -67,7 +39,7 @@ public:
constexpr QPoint transposed() const noexcept { return {yp, xp}; }
constexpr inline int &rx() noexcept;
- constexpr inline int &ry()noexcept;
+ constexpr inline int &ry() noexcept;
constexpr inline QPoint &operator+=(const QPoint &p);
constexpr inline QPoint &operator-=(const QPoint &p);
@@ -81,31 +53,58 @@ public:
constexpr static inline int dotProduct(const QPoint &p1, const QPoint &p2)
{ return p1.xp * p2.xp + p1.yp * p2.yp; }
- friend constexpr inline bool operator==(const QPoint &, const QPoint &) noexcept;
- friend constexpr inline bool operator!=(const QPoint &, const QPoint &) noexcept;
- friend constexpr inline const QPoint operator+(const QPoint &, const QPoint &);
- friend constexpr inline const QPoint operator-(const QPoint &, const QPoint &);
- friend constexpr inline const QPoint operator*(const QPoint &, float);
- friend constexpr inline const QPoint operator*(float, const QPoint &);
- friend constexpr inline const QPoint operator*(const QPoint &, double);
- friend constexpr inline const QPoint operator*(double, const QPoint &);
- friend constexpr inline const QPoint operator*(const QPoint &, int);
- friend constexpr inline const QPoint operator*(int, const QPoint &);
- friend constexpr inline const QPoint operator+(const QPoint &);
- friend constexpr inline const QPoint operator-(const QPoint &);
- friend constexpr inline const QPoint operator/(const QPoint &, qreal);
+private:
+ friend constexpr bool comparesEqual(const QPoint &p1, const QPoint &p2) noexcept
+ { return p1.xp == p2.xp && p1.yp == p2.yp; }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QPoint)
+ friend constexpr inline QPoint operator+(const QPoint &p1, const QPoint &p2) noexcept
+ { return QPoint(p1.xp + p2.xp, p1.yp + p2.yp); }
+ friend constexpr inline QPoint operator-(const QPoint &p1, const QPoint &p2) noexcept
+ { return QPoint(p1.xp - p2.xp, p1.yp - p2.yp); }
+ friend constexpr inline QPoint operator*(const QPoint &p, float factor)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(const QPoint &p, double factor)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(const QPoint &p, int factor) noexcept
+ { return QPoint(p.xp * factor, p.yp * factor); }
+ friend constexpr inline QPoint operator*(float factor, const QPoint &p)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(double factor, const QPoint &p)
+ { return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
+ friend constexpr inline QPoint operator*(int factor, const QPoint &p) noexcept
+ { return QPoint(p.xp * factor, p.yp * factor); }
+ friend constexpr inline QPoint operator+(const QPoint &p) noexcept
+ { return p; }
+ friend constexpr inline QPoint operator-(const QPoint &p) noexcept
+ { return QPoint(-p.xp, -p.yp); }
+ friend constexpr inline QPoint operator/(const QPoint &p, qreal c)
+ { return QPoint(qRound(p.xp / c), qRound(p.yp / c)); }
+public:
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
+ [[nodiscard]] Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
#endif
+ [[nodiscard]] constexpr inline QPointF toPointF() const noexcept;
private:
friend class QTransform;
int xp;
int yp;
+
+ template <std::size_t I,
+ typename P,
+ std::enable_if_t<(I < 2), bool> = true,
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<P>, QPoint>, bool> = true>
+ friend constexpr decltype(auto) get(P &&p) noexcept
+ {
+ if constexpr (I == 0)
+ return q23::forward_like<P>(p.xp);
+ else if constexpr (I == 1)
+ return q23::forward_like<P>(p.yp);
+ }
};
-Q_DECLARE_TYPEINFO(QPoint, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QPoint, Q_PRIMITIVE_TYPE);
/*****************************************************************************
QPoint stream functions
@@ -124,96 +123,92 @@ constexpr inline QPoint::QPoint() noexcept : xp(0), yp(0) {}
constexpr inline QPoint::QPoint(int xpos, int ypos) noexcept : xp(xpos), yp(ypos) {}
constexpr inline bool QPoint::isNull() const noexcept
-{ return xp == 0 && yp == 0; }
+{
+ return xp == 0 && yp == 0;
+}
constexpr inline int QPoint::x() const noexcept
-{ return xp; }
+{
+ return xp;
+}
constexpr inline int QPoint::y() const noexcept
-{ return yp; }
+{
+ return yp;
+}
constexpr inline void QPoint::setX(int xpos) noexcept
-{ xp = xpos; }
+{
+ xp = xpos;
+}
constexpr inline void QPoint::setY(int ypos) noexcept
-{ yp = ypos; }
+{
+ yp = ypos;
+}
inline int constexpr QPoint::manhattanLength() const
-{ return qAbs(x())+qAbs(y()); }
+{
+ return qAbs(x()) + qAbs(y());
+}
constexpr inline int &QPoint::rx() noexcept
-{ return xp; }
+{
+ return xp;
+}
constexpr inline int &QPoint::ry() noexcept
-{ return yp; }
+{
+ return yp;
+}
constexpr inline QPoint &QPoint::operator+=(const QPoint &p)
-{ xp+=p.xp; yp+=p.yp; return *this; }
+{
+ xp += p.xp;
+ yp += p.yp;
+ return *this;
+}
constexpr inline QPoint &QPoint::operator-=(const QPoint &p)
-{ xp-=p.xp; yp-=p.yp; return *this; }
+{
+ xp -= p.xp;
+ yp -= p.yp;
+ return *this;
+}
constexpr inline QPoint &QPoint::operator*=(float factor)
-{ xp = qRound(xp*factor); yp = qRound(yp*factor); return *this; }
+{
+ xp = qRound(xp * factor);
+ yp = qRound(yp * factor);
+ return *this;
+}
constexpr inline QPoint &QPoint::operator*=(double factor)
-{ xp = qRound(xp*factor); yp = qRound(yp*factor); return *this; }
+{
+ xp = qRound(xp * factor);
+ yp = qRound(yp * factor);
+ return *this;
+}
constexpr inline QPoint &QPoint::operator*=(int factor)
-{ xp = xp*factor; yp = yp*factor; return *this; }
-
-constexpr inline bool operator==(const QPoint &p1, const QPoint &p2) noexcept
-{ return p1.xp == p2.xp && p1.yp == p2.yp; }
-
-constexpr inline bool operator!=(const QPoint &p1, const QPoint &p2) noexcept
-{ return p1.xp != p2.xp || p1.yp != p2.yp; }
-
-constexpr inline const QPoint operator+(const QPoint &p1, const QPoint &p2)
-{ return QPoint(p1.xp+p2.xp, p1.yp+p2.yp); }
-
-constexpr inline const QPoint operator-(const QPoint &p1, const QPoint &p2)
-{ return QPoint(p1.xp-p2.xp, p1.yp-p2.yp); }
-
-constexpr inline const QPoint operator*(const QPoint &p, float factor)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(const QPoint &p, double factor)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(const QPoint &p, int factor)
-{ return QPoint(p.xp*factor, p.yp*factor); }
-
-constexpr inline const QPoint operator*(float factor, const QPoint &p)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(double factor, const QPoint &p)
-{ return QPoint(qRound(p.xp*factor), qRound(p.yp*factor)); }
-
-constexpr inline const QPoint operator*(int factor, const QPoint &p)
-{ return QPoint(p.xp*factor, p.yp*factor); }
-
-constexpr inline const QPoint operator+(const QPoint &p)
-{ return p; }
-
-constexpr inline const QPoint operator-(const QPoint &p)
-{ return QPoint(-p.xp, -p.yp); }
-
-constexpr inline QPoint &QPoint::operator/=(qreal c)
{
- xp = qRound(xp/c);
- yp = qRound(yp/c);
+ xp = xp * factor;
+ yp = yp * factor;
return *this;
}
-constexpr inline const QPoint operator/(const QPoint &p, qreal c)
+constexpr inline QPoint &QPoint::operator/=(qreal c)
{
- return QPoint(qRound(p.xp/c), qRound(p.yp/c));
+ xp = qRound(xp / c);
+ yp = qRound(yp / c);
+ return *this;
}
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QPoint &);
#endif
+Q_CORE_EXPORT size_t qHash(QPoint key, size_t seed = 0) noexcept;
@@ -245,23 +240,53 @@ public:
constexpr inline QPointF &operator/=(qreal c);
constexpr static inline qreal dotProduct(const QPointF &p1, const QPointF &p2)
- { return p1.xp * p2.xp + p1.yp * p2.yp; }
+ {
+ return p1.xp * p2.xp + p1.yp * p2.yp;
+ }
- friend constexpr inline bool operator==(const QPointF &, const QPointF &);
- friend constexpr inline bool operator!=(const QPointF &, const QPointF &);
- friend constexpr inline const QPointF operator+(const QPointF &, const QPointF &);
- friend constexpr inline const QPointF operator-(const QPointF &, const QPointF &);
- friend constexpr inline const QPointF operator*(qreal, const QPointF &);
- friend constexpr inline const QPointF operator*(const QPointF &, qreal);
- friend constexpr inline const QPointF operator+(const QPointF &);
- friend constexpr inline const QPointF operator-(const QPointF &);
- friend constexpr inline const QPointF operator/(const QPointF &, qreal);
+private:
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_FLOAT_COMPARE
+ friend constexpr bool qFuzzyCompare(const QPointF &p1, const QPointF &p2) noexcept
+ {
+ return ((!p1.xp || !p2.xp) ? qFuzzyIsNull(p1.xp - p2.xp) : qFuzzyCompare(p1.xp, p2.xp))
+ && ((!p1.yp || !p2.yp) ? qFuzzyIsNull(p1.yp - p2.yp) : qFuzzyCompare(p1.yp, p2.yp));
+ }
+ QT_WARNING_POP
+ friend constexpr bool qFuzzyIsNull(const QPointF &point) noexcept
+ {
+ return qFuzzyIsNull(point.xp) && qFuzzyIsNull(point.yp);
+ }
+ friend constexpr bool comparesEqual(const QPointF &p1, const QPointF &p2) noexcept
+ { return qFuzzyCompare(p1, p2); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QPointF)
+ friend constexpr bool comparesEqual(const QPointF &p1, const QPoint &p2) noexcept
+ { return comparesEqual(p1, p2.toPointF()); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QPointF, QPoint)
+ friend constexpr inline QPointF operator+(const QPointF &p1, const QPointF &p2)
+ { return QPointF(p1.xp + p2.xp, p1.yp + p2.yp); }
+ friend constexpr inline QPointF operator-(const QPointF &p1, const QPointF &p2)
+ { return QPointF(p1.xp - p2.xp, p1.yp - p2.yp); }
+ friend constexpr inline QPointF operator*(const QPointF &p, qreal c)
+ { return QPointF(p.xp * c, p.yp * c); }
+ friend constexpr inline QPointF operator*(qreal c, const QPointF &p)
+ { return QPointF(p.xp * c, p.yp * c); }
+ friend constexpr inline QPointF operator+(const QPointF &p)
+ { return p; }
+ friend constexpr inline QPointF operator-(const QPointF &p)
+ { return QPointF(-p.xp, -p.yp); }
+ friend constexpr inline QPointF operator/(const QPointF &p, qreal divisor)
+ {
+ Q_ASSERT(divisor < 0 || divisor > 0);
+ return QPointF(p.xp / divisor, p.yp / divisor);
+ }
+public:
constexpr QPoint toPoint() const;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT Q_CORE_EXPORT static QPointF fromCGPoint(CGPoint point) noexcept;
- Q_REQUIRED_RESULT Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
+ [[nodiscard]] Q_CORE_EXPORT static QPointF fromCGPoint(CGPoint point) noexcept;
+ [[nodiscard]] Q_CORE_EXPORT CGPoint toCGPoint() const noexcept;
#endif
private:
@@ -269,9 +294,23 @@ private:
qreal xp;
qreal yp;
+
+ template <std::size_t I,
+ typename P,
+ std::enable_if_t<(I < 2), bool> = true,
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<P>, QPointF>, bool> = true>
+ friend constexpr decltype(auto) get(P &&p) noexcept
+ {
+ if constexpr (I == 0)
+ return q23::forward_like<P>(p.xp);
+ else if constexpr (I == 1)
+ return q23::forward_like<P>(p.yp);
+ }
};
-Q_DECLARE_TYPEINFO(QPointF, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QPointF, Q_PRIMITIVE_TYPE);
+
+size_t qHash(QPointF, size_t seed = 0) = delete;
/*****************************************************************************
QPointF stream functions
@@ -293,7 +332,7 @@ constexpr inline QPointF::QPointF(const QPoint &p) noexcept : xp(p.x()), yp(p.y(
constexpr inline qreal QPointF::manhattanLength() const
{
- return qAbs(x())+qAbs(y());
+ return qAbs(x()) + qAbs(y());
}
inline bool QPointF::isNull() const noexcept
@@ -333,78 +372,34 @@ constexpr inline qreal &QPointF::ry() noexcept
constexpr inline QPointF &QPointF::operator+=(const QPointF &p)
{
- xp+=p.xp;
- yp+=p.yp;
+ xp += p.xp;
+ yp += p.yp;
return *this;
}
constexpr inline QPointF &QPointF::operator-=(const QPointF &p)
{
- xp-=p.xp; yp-=p.yp; return *this;
+ xp -= p.xp;
+ yp -= p.yp;
+ return *this;
}
constexpr inline QPointF &QPointF::operator*=(qreal c)
{
- xp*=c; yp*=c; return *this;
-}
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_FLOAT_COMPARE
-
-constexpr inline bool operator==(const QPointF &p1, const QPointF &p2)
-{
- return ((!p1.xp || !p2.xp) ? qFuzzyIsNull(p1.xp - p2.xp) : qFuzzyCompare(p1.xp, p2.xp))
- && ((!p1.yp || !p2.yp) ? qFuzzyIsNull(p1.yp - p2.yp) : qFuzzyCompare(p1.yp, p2.yp));
-}
-
-constexpr inline bool operator!=(const QPointF &p1, const QPointF &p2)
-{
- return !(p1 == p2);
-}
-
-QT_WARNING_POP
-
-constexpr inline const QPointF operator+(const QPointF &p1, const QPointF &p2)
-{
- return QPointF(p1.xp+p2.xp, p1.yp+p2.yp);
-}
-
-constexpr inline const QPointF operator-(const QPointF &p1, const QPointF &p2)
-{
- return QPointF(p1.xp-p2.xp, p1.yp-p2.yp);
-}
-
-constexpr inline const QPointF operator*(const QPointF &p, qreal c)
-{
- return QPointF(p.xp*c, p.yp*c);
-}
-
-constexpr inline const QPointF operator*(qreal c, const QPointF &p)
-{
- return QPointF(p.xp*c, p.yp*c);
-}
-
-constexpr inline const QPointF operator+(const QPointF &p)
-{
- return p;
-}
-
-constexpr inline const QPointF operator-(const QPointF &p)
-{
- return QPointF(-p.xp, -p.yp);
+ xp *= c;
+ yp *= c;
+ return *this;
}
constexpr inline QPointF &QPointF::operator/=(qreal divisor)
{
- xp/=divisor;
- yp/=divisor;
+ Q_ASSERT(divisor > 0 || divisor < 0);
+ xp /= divisor;
+ yp /= divisor;
return *this;
}
-constexpr inline const QPointF operator/(const QPointF &p, qreal divisor)
-{
- return QPointF(p.xp/divisor, p.yp/divisor);
-}
+constexpr QPointF QPoint::toPointF() const noexcept { return *this; }
constexpr inline QPoint QPointF::toPoint() const
{
@@ -417,4 +412,24 @@ Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p);
QT_END_NAMESPACE
+/*****************************************************************************
+ QPoint/QPointF tuple protocol
+ *****************************************************************************/
+
+namespace std {
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QPoint)> : public integral_constant<size_t, 2> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; };
+
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QPointF)> : public integral_constant<size_t, 2> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+}
+
#endif // QPOINT_H
diff --git a/src/corelib/tools/qqueue.cpp b/src/corelib/tools/qqueue.cpp
index ffc48d6714..82095faa3d 100644
--- a/src/corelib/tools/qqueue.cpp
+++ b/src/corelib/tools/qqueue.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QQueue
diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h
index d5a60ada56..4863499f2a 100644
--- a/src/corelib/tools/qqueue.h
+++ b/src/corelib/tools/qqueue.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QQUEUE_H
#define QQUEUE_H
@@ -51,11 +15,6 @@ class QQueue : public QList<T>
public:
// compiler-generated special member functions are fine!
inline void swap(QQueue<T> &other) noexcept { QList<T>::swap(other); } // prevent QList<->QQueue swaps
-#ifndef Q_QDOC
- // bring in QList::swap(int, int). We cannot say using QList<T>::swap,
- // because we don't want to make swap(QList&) available.
- Q_DECL_DEPRECATED inline void swap(int i, int j) { QList<T>::swapItemsAt(i, j); }
-#endif
inline void enqueue(const T &t) { QList<T>::append(t); }
inline T dequeue() { return QList<T>::takeFirst(); }
inline T &head() { return QList<T>::first(); }
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 4aa9897b5d..ce28a6d887 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qrect.h"
#include "qdatastream.h"
@@ -51,6 +15,10 @@ QT_BEGIN_NAMESPACE
\ingroup painting
\reentrant
+ \compares equality
+ \compareswith equality QRectF
+ \endcompareswith
+
\brief The QRect class defines a rectangle in the plane using
integer precision.
@@ -81,7 +49,7 @@ QT_BEGIN_NAMESPACE
position, and the translated() function returns a translated copy
of this rectangle.
- The size() function returns the rectange's dimensions as a
+ The size() function returns the rectangle's dimensions as a
QSize. The dimensions can also be retrieved separately using the
width() and height() functions. To manipulate the dimensions use
the setSize(), setWidth() or setHeight() functions. Alternatively,
@@ -223,9 +191,14 @@ QT_BEGIN_NAMESPACE
/*!
\fn QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight)
- Constructs a rectangle with the given \a topLeft and \a bottomRight corners.
+ Constructs a rectangle with the given \a topLeft and \a bottomRight corners, both included.
- \sa setTopLeft(), setBottomRight()
+ If \a bottomRight is to higher and to the left of \a topLeft, the rectangle defined
+ is instead non-inclusive of the corners.
+
+ \note To ensure both points are included regardless of relative order, use span().
+
+ \sa setTopLeft(), setBottomRight(), span()
*/
@@ -295,27 +268,22 @@ QT_BEGIN_NAMESPACE
non-negative width and height.
If width() < 0 the function swaps the left and right corners, and
- it swaps the top and bottom corners if height() < 0.
+ it swaps the top and bottom corners if height() < 0. The corners
+ are at the same time changed from being non-inclusive to inclusive.
\sa isValid(), isEmpty()
*/
QRect QRect::normalized() const noexcept
{
- QRect r;
- if (x2 < x1 - 1) { // swap bad x values
- r.x1 = x2;
- r.x2 = x1;
- } else {
- r.x1 = x1;
- r.x2 = x2;
+ QRect r(*this);
+ if (x2 < x1) { // swap bad x values
+ r.x1 = x2 + 1;
+ r.x2 = x1 - 1;
}
- if (y2 < y1 - 1) { // swap bad y values
- r.y1 = y2;
- r.y2 = y1;
- } else {
- r.y1 = y1;
- r.y2 = y2;
+ if (y2 < y1) { // swap bad y values
+ r.y1 = y2 + 1;
+ r.y2 = y1 - 1;
}
return r;
}
@@ -824,8 +792,8 @@ bool QRect::contains(const QPoint &p, bool proper) const noexcept
{
int l, r;
if (x2 < x1 - 1) {
- l = x2;
- r = x1;
+ l = x2 + 1;
+ r = x1 - 1;
} else {
l = x1;
r = x2;
@@ -839,8 +807,8 @@ bool QRect::contains(const QPoint &p, bool proper) const noexcept
}
int t, b;
if (y2 < y1 - 1) {
- t = y2;
- b = y1;
+ t = y2 + 1;
+ b = y1 - 1;
} else {
t = y1;
b = y2;
@@ -890,16 +858,16 @@ bool QRect::contains(const QRect &r, bool proper) const noexcept
return false;
int l1 = x1;
- int r1 = x1;
- if (x2 - x1 + 1 < 0)
- l1 = x2;
+ int r1 = x1 - 1;
+ if (x2 < x1 - 1)
+ l1 = x2 + 1;
else
r1 = x2;
int l2 = r.x1;
- int r2 = r.x1;
- if (r.x2 - r.x1 + 1 < 0)
- l2 = r.x2;
+ int r2 = r.x1 - 1;
+ if (r.x2 < r.x1 - 1)
+ l2 = r.x2 + 1;
else
r2 = r.x2;
@@ -912,16 +880,16 @@ bool QRect::contains(const QRect &r, bool proper) const noexcept
}
int t1 = y1;
- int b1 = y1;
- if (y2 - y1 + 1 < 0)
- t1 = y2;
+ int b1 = y1 - 1;
+ if (y2 < y1 - 1)
+ t1 = y2 + 1;
else
b1 = y2;
int t2 = r.y1;
- int b2 = r.y1;
- if (r.y2 - r.y1 + 1 < 0)
- t2 = r.y2;
+ int b2 = r.y1 - 1;
+ if (r.y2 < r.y1 - 1)
+ t2 = r.y2 + 1;
else
b2 = r.y2;
@@ -970,30 +938,30 @@ QRect QRect::operator|(const QRect &r) const noexcept
return *this;
int l1 = x1;
- int r1 = x1;
- if (x2 - x1 + 1 < 0)
- l1 = x2;
+ int r1 = x1 - 1;
+ if (x2 < x1 - 1)
+ l1 = x2 + 1;
else
r1 = x2;
int l2 = r.x1;
- int r2 = r.x1;
- if (r.x2 - r.x1 + 1 < 0)
- l2 = r.x2;
+ int r2 = r.x1 - 1;
+ if (r.x2 < r.x1 - 1)
+ l2 = r.x2 + 1;
else
r2 = r.x2;
int t1 = y1;
- int b1 = y1;
- if (y2 - y1 + 1 < 0)
- t1 = y2;
+ int b1 = y1 - 1;
+ if (y2 < y1 - 1)
+ t1 = y2 + 1;
else
b1 = y2;
int t2 = r.y1;
- int b2 = r.y1;
- if (r.y2 - r.y1 + 1 < 0)
- t2 = r.y2;
+ int b2 = r.y1 - 1;
+ if (r.y2 < r.y1 - 1)
+ t2 = r.y2 + 1;
else
b2 = r.y2;
@@ -1032,35 +1000,35 @@ QRect QRect::operator&(const QRect &r) const noexcept
return QRect();
int l1 = x1;
- int r1 = x1;
- if (x2 - x1 + 1 < 0)
- l1 = x2;
- else
- r1 = x2;
+ int r1 = x2;
+ if (x2 < x1 - 1) {
+ l1 = x2 + 1;
+ r1 = x1 - 1;
+ }
int l2 = r.x1;
- int r2 = r.x1;
- if (r.x2 - r.x1 + 1 < 0)
- l2 = r.x2;
- else
- r2 = r.x2;
+ int r2 = r.x2;
+ if (r.x2 < r.x1 - 1) {
+ l2 = r.x2 + 1;
+ r2 = r.x1 - 1;
+ }
if (l1 > r2 || l2 > r1)
return QRect();
int t1 = y1;
- int b1 = y1;
- if (y2 - y1 + 1 < 0)
- t1 = y2;
- else
- b1 = y2;
+ int b1 = y2;
+ if (y2 < y1 - 1) {
+ t1 = y2 + 1;
+ b1 = y1 - 1;
+ }
int t2 = r.y1;
- int b2 = r.y1;
- if (r.y2 - r.y1 + 1 < 0)
- t2 = r.y2;
- else
- b2 = r.y2;
+ int b2 = r.y2;
+ if (r.y2 < r.y1 - 1) {
+ t2 = r.y2 + 1;
+ b2 = r.y1 - 1;
+ }
if (t1 > b2 || t2 > b1)
return QRect();
@@ -1104,35 +1072,35 @@ bool QRect::intersects(const QRect &r) const noexcept
return false;
int l1 = x1;
- int r1 = x1;
- if (x2 - x1 + 1 < 0)
- l1 = x2;
- else
- r1 = x2;
+ int r1 = x2;
+ if (x2 < x1 - 1) {
+ l1 = x2 + 1;
+ r1 = x1 - 1;
+ }
int l2 = r.x1;
- int r2 = r.x1;
- if (r.x2 - r.x1 + 1 < 0)
- l2 = r.x2;
- else
- r2 = r.x2;
+ int r2 = r.x2;
+ if (r.x2 < r.x1 - 1) {
+ l2 = r.x2 + 1;
+ r2 = r.x1 - 1;
+ }
if (l1 > r2 || l2 > r1)
return false;
int t1 = y1;
- int b1 = y1;
- if (y2 - y1 + 1 < 0)
- t1 = y2;
- else
- b1 = y2;
+ int b1 = y2;
+ if (y2 < y1 - 1) {
+ t1 = y2 + 1;
+ b1 = y1 - 1;
+ }
int t2 = r.y1;
- int b2 = r.y1;
- if (r.y2 - r.y1 + 1 < 0)
- t2 = r.y2;
- else
- b2 = r.y2;
+ int b2 = r.y2;
+ if (r.y2 < r.y1 - 1) {
+ t2 = r.y2 + 1;
+ b2 = r.y1 - 1;
+ }
if (t1 > b2 || t2 > b1)
return false;
@@ -1141,20 +1109,18 @@ bool QRect::intersects(const QRect &r) const noexcept
}
/*!
- \fn bool operator==(const QRect &r1, const QRect &r2)
- \relates QRect
+ \fn bool QRect::operator==(const QRect &lhs, const QRect &rhs)
- Returns \c true if the rectangles \a r1 and \a r2 are equal,
+ Returns \c true if the rectangles \a lhs and \a rhs are equal,
otherwise returns \c false.
*/
/*!
- \fn bool operator!=(const QRect &r1, const QRect &r2)
- \relates QRect
+ \fn bool QRect::operator!=(const QRect &lhs, const QRect &rhs)
- Returns \c true if the rectangles \a r1 and \a r2 are different, otherwise
- returns \c false.
+ Returns \c true if the rectangles \a lhs and \a rhs are different,
+ otherwise returns \c false.
*/
/*!
@@ -1225,6 +1191,26 @@ bool QRect::intersects(const QRect &r) const noexcept
\since 5.1
*/
+/*!
+ \fn static QRect QRect::span(const QPoint &p1, const QPoint &p2)
+
+ Returns a rectangle spanning the two points \a p1 and \a p2, including both and
+ everything in between.
+
+ \since 6.0
+*/
+
+/*!
+ \fn QRect::toRectF() const
+ \since 6.4
+
+ Returns this rectangle as a rectangle with floating point accuracy.
+
+ \note This function, like the QRectF(QRect) constructor, preserves the
+ size() of the rectangle, not its bottomRight() corner.
+
+ \sa QRectF::toRect()
+*/
/*****************************************************************************
QRect stream functions
@@ -1297,8 +1283,12 @@ QDebug operator<<(QDebug dbg, const QRect &r)
\ingroup painting
\reentrant
- \brief The QRectF class defines a rectangle in the plane using floating
- point precision.
+ \compares equality
+ \compareswith equality QRect
+ \endcompareswith
+
+ \brief The QRectF class defines a finite rectangle in the plane using
+ floating point precision.
A rectangle is normally expressed as a top-left corner and a
size. The size (width and height) of a QRectF is always equivalent
@@ -1326,7 +1316,7 @@ QDebug operator<<(QDebug dbg, const QRect &r)
current position, and the translated() function returns a
translated copy of this rectangle.
- The size() function returns the rectange's dimensions as a
+ The size() function returns the rectangle's dimensions as a
QSizeF. The dimensions can also be retrieved separately using the
width() and height() functions. To manipulate the dimensions use
the setSize(), setWidth() or setHeight() functions. Alternatively,
@@ -1463,8 +1453,8 @@ QDebug operator<<(QDebug dbg, const QRect &r)
/*!
\fn QRectF::QRectF(qreal x, qreal y, qreal width, qreal height)
- Constructs a rectangle with (\a x, \a y) as its top-left corner
- and the given \a width and \a height.
+ Constructs a rectangle with (\a x, \a y) as its top-left corner and the
+ given \a width and \a height. All parameters must be finite.
\sa setRect()
*/
@@ -1474,7 +1464,10 @@ QDebug operator<<(QDebug dbg, const QRect &r)
Constructs a QRectF rectangle from the given QRect \a rectangle.
- \sa toRect()
+ \note This function, like QRect::toRectF(), preserves the size() of
+ \a rectangle, not its bottomRight() corner.
+
+ \sa toRect(), QRect::toRectF()
*/
/*!
@@ -1563,7 +1556,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setLeft(qreal x)
- Sets the left edge of the rectangle to the given \a x
+ Sets the left edge of the rectangle to the given finite \a x
coordinate. May change the width, but will never change the right
edge of the rectangle.
@@ -1575,7 +1568,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setTop(qreal y)
- Sets the top edge of the rectangle to the given \a y coordinate. May
+ Sets the top edge of the rectangle to the given finite \a y coordinate. May
change the height, but will never change the bottom edge of the
rectangle.
@@ -1587,7 +1580,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setRight(qreal x)
- Sets the right edge of the rectangle to the given \a x
+ Sets the right edge of the rectangle to the given finite \a x
coordinate. May change the width, but will never change the left
edge of the rectangle.
@@ -1597,7 +1590,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setBottom(qreal y)
- Sets the bottom edge of the rectangle to the given \a y
+ Sets the bottom edge of the rectangle to the given finite \a y
coordinate. May change the height, but will never change the top
edge of the rectangle.
@@ -1607,7 +1600,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setX(qreal x)
- Sets the left edge of the rectangle to the given \a x
+ Sets the left edge of the rectangle to the given finite \a x
coordinate. May change the width, but will never change the right
edge of the rectangle.
@@ -1619,7 +1612,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setY(qreal y)
- Sets the top edge of the rectangle to the given \a y
+ Sets the top edge of the rectangle to the given finite \a y
coordinate. May change the height, but will never change the
bottom edge of the rectangle.
@@ -1701,7 +1694,7 @@ QRectF QRectF::normalized() const noexcept
\fn void QRectF::moveLeft(qreal x)
Moves the rectangle horizontally, leaving the rectangle's left
- edge at the given \a x coordinate. The rectangle's size is
+ edge at the given finite \a x coordinate. The rectangle's size is
unchanged.
\sa left(), setLeft(), moveRight()
@@ -1711,7 +1704,7 @@ QRectF QRectF::normalized() const noexcept
\fn void QRectF::moveTop(qreal y)
Moves the rectangle vertically, leaving the rectangle's top line
- at the given \a y coordinate. The rectangle's size is unchanged.
+ at the given finite \a y coordinate. The rectangle's size is unchanged.
\sa top(), setTop(), moveBottom()
*/
@@ -1721,7 +1714,7 @@ QRectF QRectF::normalized() const noexcept
\fn void QRectF::moveRight(qreal x)
Moves the rectangle horizontally, leaving the rectangle's right
- edge at the given \a x coordinate. The rectangle's size is
+ edge at the given finite \a x coordinate. The rectangle's size is
unchanged.
\sa right(), setRight(), moveLeft()
@@ -1732,7 +1725,7 @@ QRectF QRectF::normalized() const noexcept
\fn void QRectF::moveBottom(qreal y)
Moves the rectangle vertically, leaving the rectangle's bottom
- edge at the given \a y coordinate. The rectangle's size is
+ edge at the given finite \a y coordinate. The rectangle's size is
unchanged.
\sa bottom(), setBottom(), moveTop()
@@ -1782,8 +1775,8 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::moveTo(qreal x, qreal y)
- Moves the rectangle, leaving the top-left corner at the given
- position (\a x, \a y). The rectangle's size is unchanged.
+ Moves the rectangle, leaving the top-left corner at the given position (\a
+ x, \a y). The rectangle's size is unchanged. Both parameters must be finite.
\sa translate(), moveTopLeft()
*/
@@ -1801,7 +1794,7 @@ QRectF QRectF::normalized() const noexcept
Moves the rectangle \a dx along the x-axis and \a dy along the y-axis,
relative to the current position. Positive values move the rectangle to the
- right and downwards.
+ right and downwards. Both parameters must be finite.
\sa moveTopLeft(), moveTo(), translated()
*/
@@ -1823,7 +1816,7 @@ QRectF QRectF::normalized() const noexcept
Returns a copy of the rectangle that is translated \a dx along the
x axis and \a dy along the y axis, relative to the current
position. Positive values move the rectangle to the right and
- down.
+ down. Both parameters must be finite.
\sa translate()
*/
@@ -1854,8 +1847,8 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setRect(qreal x, qreal y, qreal width, qreal height)
- Sets the coordinates of the rectangle's top-left corner to (\a x,
- \a y), and its size to the given \a width and \a height.
+ Sets the coordinates of the rectangle's top-left corner to (\a x, \a y), and
+ its size to the given \a width and \a height. All parameters must be finite.
\sa getRect(), setCoords()
*/
@@ -1866,7 +1859,7 @@ QRectF QRectF::normalized() const noexcept
Sets the coordinates of the rectangle's top-left corner to (\a x1,
\a y1), and the coordinates of its bottom-right corner to (\a x2,
- \a y2).
+ \a y2). All parameters must be finite.
\sa getCoords(), setRect()
*/
@@ -1876,6 +1869,7 @@ QRectF QRectF::normalized() const noexcept
Returns a new rectangle with \a dx1, \a dy1, \a dx2 and \a dy2
added respectively to the existing coordinates of this rectangle.
+ All parameters must be finite.
\sa adjust()
*/
@@ -1883,7 +1877,7 @@ QRectF QRectF::normalized() const noexcept
/*! \fn void QRectF::adjust(qreal dx1, qreal dy1, qreal dx2, qreal dy2)
Adds \a dx1, \a dy1, \a dx2 and \a dy2 respectively to the
- existing coordinates of the rectangle.
+ existing coordinates of the rectangle. All parameters must be finite.
\sa adjusted(), setRect()
*/
@@ -1914,7 +1908,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setWidth(qreal width)
- Sets the width of the rectangle to the given \a width. The right
+ Sets the width of the rectangle to the given finite \a width. The right
edge is changed, but not the left one.
\sa width(), setSize()
@@ -1924,7 +1918,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setHeight(qreal height)
- Sets the height of the rectangle to the given \a height. The bottom
+ Sets the height of the rectangle to the given finite \a height. The bottom
edge is changed, but not the top one.
\sa height(), setSize()
@@ -1934,7 +1928,7 @@ QRectF QRectF::normalized() const noexcept
/*!
\fn void QRectF::setSize(const QSizeF &size)
- Sets the size of the rectangle to the given \a size. The top-left
+ Sets the size of the rectangle to the given finite \a size. The top-left
corner is not moved.
\sa size(), setWidth(), setHeight()
@@ -2122,7 +2116,7 @@ bool QRectF::contains(const QRectF &r) const noexcept
Intersects this rectangle with the given \a rectangle.
- \sa intersected(), operator|=()
+ \sa intersected(), operator&()
*/
@@ -2327,7 +2321,7 @@ bool QRectF::intersects(const QRectF &r) const noexcept
Returns a QRect based on the values of this rectangle. Note that the
coordinates in the returned rectangle are rounded to the nearest integer.
- \sa QRectF(), toAlignedRect()
+ \sa QRectF(), toAlignedRect(), QRect::toRectF()
*/
/*!
@@ -2360,20 +2354,26 @@ QRect QRectF::toAlignedRect() const noexcept
*/
/*!
- \fn bool operator==(const QRectF &r1, const QRectF &r2)
- \relates QRectF
+ \fn bool QRectF::operator==(const QRectF &lhs, const QRectF &rhs)
- Returns \c true if the rectangles \a r1 and \a r2 are equal,
- otherwise returns \c false.
+ Returns \c true if the rectangles \a lhs and \a rhs are \b approximately
+ equal, otherwise returns \c false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the rectangles' coordinates.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QRectF &r1, const QRectF &r2)
- \relates QRectF
+ \fn bool QRectF::operator!=(const QRectF &lhs, const QRectF &rhs)
- Returns \c true if the rectangles \a r1 and \a r2 are different, otherwise
- returns \c false.
+ Returns \c true if the rectangles \a lhs and \a rhs are sufficiently
+ different, otherwise returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the rectangles' coordinates.
*/
/*!
@@ -2437,6 +2437,22 @@ QRect QRectF::toAlignedRect() const noexcept
\sa marginsRemoved(), operator+=(), marginsAdded()
*/
+/*!
+ \fn bool QRectF::qFuzzyCompare(const QRectF &lhs, const QRectF &rhs)
+ \since 6.8
+
+ Returns \c true if the rectangle \a lhs is approximately equal to the
+ rectangle \a rhs; otherwise returns \c false.
+*/
+
+/*!
+ \fn bool QRectF::qFuzzyIsNull(const QRectF &rect)
+ \since 6.8
+
+ Returns \c true if both width and height of the rectangle \a rect are
+ approximately equal to zero; otherwise returns \c false.
+*/
+
/*****************************************************************************
QRectF stream functions
*****************************************************************************/
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 4fd9e7c0c9..fb938b0056 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRECT_H
#define QRECT_H
+#include <QtCore/qhashfunctions.h>
#include <QtCore/qmargins.h>
#include <QtCore/qsize.h>
#include <QtCore/qpoint.h>
@@ -51,106 +16,120 @@
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGRect;
#endif
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+namespace emscripten {
+class val;
+}
+#endif
QT_BEGIN_NAMESPACE
+class QRectF;
+
class Q_CORE_EXPORT QRect
{
public:
- Q_DECL_CONSTEXPR QRect() noexcept : x1(0), y1(0), x2(-1), y2(-1) {}
- Q_DECL_CONSTEXPR QRect(const QPoint &topleft, const QPoint &bottomright) noexcept;
- Q_DECL_CONSTEXPR QRect(const QPoint &topleft, const QSize &size) noexcept;
- Q_DECL_CONSTEXPR QRect(int left, int top, int width, int height) noexcept;
-
- Q_DECL_CONSTEXPR inline bool isNull() const noexcept;
- Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
- Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
-
- Q_DECL_CONSTEXPR inline int left() const noexcept;
- Q_DECL_CONSTEXPR inline int top() const noexcept;
- Q_DECL_CONSTEXPR inline int right() const noexcept;
- Q_DECL_CONSTEXPR inline int bottom() const noexcept;
- Q_REQUIRED_RESULT QRect normalized() const noexcept;
-
- Q_DECL_CONSTEXPR inline int x() const noexcept;
- Q_DECL_CONSTEXPR inline int y() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setLeft(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setTop(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setRight(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottom(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setX(int x) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setY(int y) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPoint &p) noexcept;
-
- Q_DECL_CONSTEXPR inline QPoint topLeft() const noexcept;
- Q_DECL_CONSTEXPR inline QPoint bottomRight() const noexcept;
- Q_DECL_CONSTEXPR inline QPoint topRight() const noexcept;
- Q_DECL_CONSTEXPR inline QPoint bottomLeft() const noexcept;
- Q_DECL_CONSTEXPR inline QPoint center() const noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTop(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveRight(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(int pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPoint &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPoint &p) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void translate(int dx, int dy) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPoint &p) noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect transposed() const noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(int x, int t) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPoint &p) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setRect(int x, int y, int w, int h) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void getRect(int *x, int *y, int *w, int *h) const;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setCoords(int x1, int y1, int x2, int y2) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
-
- Q_DECL_RELAXED_CONSTEXPR inline void adjust(int x1, int y1, int x2, int y2) noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const noexcept;
-
- Q_DECL_CONSTEXPR inline QSize size() const noexcept;
- Q_DECL_CONSTEXPR inline int width() const noexcept;
- Q_DECL_CONSTEXPR inline int height() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSize &s) noexcept;
+ constexpr QRect() noexcept : x1(0), y1(0), x2(-1), y2(-1) {}
+ constexpr QRect(const QPoint &topleft, const QPoint &bottomright) noexcept;
+ constexpr QRect(const QPoint &topleft, const QSize &size) noexcept;
+ constexpr QRect(int left, int top, int width, int height) noexcept;
+
+ constexpr inline bool isNull() const noexcept;
+ constexpr inline bool isEmpty() const noexcept;
+ constexpr inline bool isValid() const noexcept;
+
+ constexpr inline int left() const noexcept;
+ constexpr inline int top() const noexcept;
+ constexpr inline int right() const noexcept;
+ constexpr inline int bottom() const noexcept;
+ [[nodiscard]] QRect normalized() const noexcept;
+
+ constexpr inline int x() const noexcept;
+ constexpr inline int y() const noexcept;
+ constexpr inline void setLeft(int pos) noexcept;
+ constexpr inline void setTop(int pos) noexcept;
+ constexpr inline void setRight(int pos) noexcept;
+ constexpr inline void setBottom(int pos) noexcept;
+ constexpr inline void setX(int x) noexcept;
+ constexpr inline void setY(int y) noexcept;
+
+ constexpr inline void setTopLeft(const QPoint &p) noexcept;
+ constexpr inline void setBottomRight(const QPoint &p) noexcept;
+ constexpr inline void setTopRight(const QPoint &p) noexcept;
+ constexpr inline void setBottomLeft(const QPoint &p) noexcept;
+
+ constexpr inline QPoint topLeft() const noexcept;
+ constexpr inline QPoint bottomRight() const noexcept;
+ constexpr inline QPoint topRight() const noexcept;
+ constexpr inline QPoint bottomLeft() const noexcept;
+ constexpr inline QPoint center() const noexcept;
+
+ constexpr inline void moveLeft(int pos) noexcept;
+ constexpr inline void moveTop(int pos) noexcept;
+ constexpr inline void moveRight(int pos) noexcept;
+ constexpr inline void moveBottom(int pos) noexcept;
+ constexpr inline void moveTopLeft(const QPoint &p) noexcept;
+ constexpr inline void moveBottomRight(const QPoint &p) noexcept;
+ constexpr inline void moveTopRight(const QPoint &p) noexcept;
+ constexpr inline void moveBottomLeft(const QPoint &p) noexcept;
+ constexpr inline void moveCenter(const QPoint &p) noexcept;
+
+ constexpr inline void translate(int dx, int dy) noexcept;
+ constexpr inline void translate(const QPoint &p) noexcept;
+ [[nodiscard]] constexpr inline QRect translated(int dx, int dy) const noexcept;
+ [[nodiscard]] constexpr inline QRect translated(const QPoint &p) const noexcept;
+ [[nodiscard]] constexpr inline QRect transposed() const noexcept;
+
+ constexpr inline void moveTo(int x, int t) noexcept;
+ constexpr inline void moveTo(const QPoint &p) noexcept;
+
+ constexpr inline void setRect(int x, int y, int w, int h) noexcept;
+ constexpr inline void getRect(int *x, int *y, int *w, int *h) const;
+
+ constexpr inline void setCoords(int x1, int y1, int x2, int y2) noexcept;
+ constexpr inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
+
+ constexpr inline void adjust(int x1, int y1, int x2, int y2) noexcept;
+ [[nodiscard]] constexpr inline QRect adjusted(int x1, int y1, int x2, int y2) const noexcept;
+
+ constexpr inline QSize size() const noexcept;
+ constexpr inline int width() const noexcept;
+ constexpr inline int height() const noexcept;
+ constexpr inline void setWidth(int w) noexcept;
+ constexpr inline void setHeight(int h) noexcept;
+ constexpr inline void setSize(const QSize &s) noexcept;
QRect operator|(const QRect &r) const noexcept;
QRect operator&(const QRect &r) const noexcept;
- inline QRect& operator|=(const QRect &r) noexcept;
- inline QRect& operator&=(const QRect &r) noexcept;
+ inline QRect &operator|=(const QRect &r) noexcept;
+ inline QRect &operator&=(const QRect &r) noexcept;
bool contains(const QRect &r, bool proper = false) const noexcept;
- bool contains(const QPoint &p, bool proper=false) const noexcept;
+ bool contains(const QPoint &p, bool proper = false) const noexcept;
inline bool contains(int x, int y) const noexcept;
inline bool contains(int x, int y, bool proper) const noexcept;
- Q_REQUIRED_RESULT inline QRect united(const QRect &other) const noexcept;
- Q_REQUIRED_RESULT inline QRect intersected(const QRect &other) const noexcept;
+ [[nodiscard]] inline QRect united(const QRect &other) const noexcept;
+ [[nodiscard]] inline QRect intersected(const QRect &other) const noexcept;
bool intersects(const QRect &r) const noexcept;
- Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const noexcept;
- Q_DECL_CONSTEXPR inline QRect marginsRemoved(const QMargins &margins) const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QRect &operator+=(const QMargins &margins) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QRect &operator-=(const QMargins &margins) noexcept;
+ constexpr inline QRect marginsAdded(const QMargins &margins) const noexcept;
+ constexpr inline QRect marginsRemoved(const QMargins &margins) const noexcept;
+ constexpr inline QRect &operator+=(const QMargins &margins) noexcept;
+ constexpr inline QRect &operator-=(const QMargins &margins) noexcept;
+
+ [[nodiscard]] static constexpr inline QRect span(const QPoint &p1, const QPoint &p2) noexcept;
- friend Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &) noexcept;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QRect &, const QRect &) noexcept;
+private:
+ friend constexpr bool comparesEqual(const QRect &r1, const QRect &r2) noexcept
+ { return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2; }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QRect)
+ friend constexpr inline size_t qHash(const QRect &, size_t) noexcept;
+public:
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGRect toCGRect() const noexcept;
+ [[nodiscard]] CGRect toCGRect() const noexcept;
#endif
+ [[nodiscard]] constexpr inline QRectF toRectF() const noexcept;
private:
int x1;
@@ -158,10 +137,7 @@ private:
int x2;
int y2;
};
-Q_DECLARE_TYPEINFO(QRect, Q_MOVABLE_TYPE);
-
-Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &) noexcept;
-Q_DECL_CONSTEXPR inline bool operator!=(const QRect &, const QRect &) noexcept;
+Q_DECLARE_TYPEINFO(QRect, Q_RELOCATABLE_TYPE);
/*****************************************************************************
@@ -176,97 +152,97 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRect &);
QRect inline member functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QRect::QRect(int aleft, int atop, int awidth, int aheight) noexcept
+constexpr inline QRect::QRect(int aleft, int atop, int awidth, int aheight) noexcept
: x1(aleft), y1(atop), x2(aleft + awidth - 1), y2(atop + aheight - 1) {}
-Q_DECL_CONSTEXPR inline QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight) noexcept
+constexpr inline QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight) noexcept
: x1(atopLeft.x()), y1(atopLeft.y()), x2(abottomRight.x()), y2(abottomRight.y()) {}
-Q_DECL_CONSTEXPR inline QRect::QRect(const QPoint &atopLeft, const QSize &asize) noexcept
+constexpr inline QRect::QRect(const QPoint &atopLeft, const QSize &asize) noexcept
: x1(atopLeft.x()), y1(atopLeft.y()), x2(atopLeft.x()+asize.width() - 1), y2(atopLeft.y()+asize.height() - 1) {}
-Q_DECL_CONSTEXPR inline bool QRect::isNull() const noexcept
+constexpr inline bool QRect::isNull() const noexcept
{ return x2 == x1 - 1 && y2 == y1 - 1; }
-Q_DECL_CONSTEXPR inline bool QRect::isEmpty() const noexcept
+constexpr inline bool QRect::isEmpty() const noexcept
{ return x1 > x2 || y1 > y2; }
-Q_DECL_CONSTEXPR inline bool QRect::isValid() const noexcept
+constexpr inline bool QRect::isValid() const noexcept
{ return x1 <= x2 && y1 <= y2; }
-Q_DECL_CONSTEXPR inline int QRect::left() const noexcept
+constexpr inline int QRect::left() const noexcept
{ return x1; }
-Q_DECL_CONSTEXPR inline int QRect::top() const noexcept
+constexpr inline int QRect::top() const noexcept
{ return y1; }
-Q_DECL_CONSTEXPR inline int QRect::right() const noexcept
+constexpr inline int QRect::right() const noexcept
{ return x2; }
-Q_DECL_CONSTEXPR inline int QRect::bottom() const noexcept
+constexpr inline int QRect::bottom() const noexcept
{ return y2; }
-Q_DECL_CONSTEXPR inline int QRect::x() const noexcept
+constexpr inline int QRect::x() const noexcept
{ return x1; }
-Q_DECL_CONSTEXPR inline int QRect::y() const noexcept
+constexpr inline int QRect::y() const noexcept
{ return y1; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setLeft(int pos) noexcept
+constexpr inline void QRect::setLeft(int pos) noexcept
{ x1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTop(int pos) noexcept
+constexpr inline void QRect::setTop(int pos) noexcept
{ y1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRight(int pos) noexcept
+constexpr inline void QRect::setRight(int pos) noexcept
{ x2 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottom(int pos) noexcept
+constexpr inline void QRect::setBottom(int pos) noexcept
{ y2 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopLeft(const QPoint &p) noexcept
+constexpr inline void QRect::setTopLeft(const QPoint &p) noexcept
{ x1 = p.x(); y1 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomRight(const QPoint &p) noexcept
+constexpr inline void QRect::setBottomRight(const QPoint &p) noexcept
{ x2 = p.x(); y2 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopRight(const QPoint &p) noexcept
+constexpr inline void QRect::setTopRight(const QPoint &p) noexcept
{ x2 = p.x(); y1 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomLeft(const QPoint &p) noexcept
+constexpr inline void QRect::setBottomLeft(const QPoint &p) noexcept
{ x1 = p.x(); y2 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setX(int ax) noexcept
+constexpr inline void QRect::setX(int ax) noexcept
{ x1 = ax; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setY(int ay) noexcept
+constexpr inline void QRect::setY(int ay) noexcept
{ y1 = ay; }
-Q_DECL_CONSTEXPR inline QPoint QRect::topLeft() const noexcept
+constexpr inline QPoint QRect::topLeft() const noexcept
{ return QPoint(x1, y1); }
-Q_DECL_CONSTEXPR inline QPoint QRect::bottomRight() const noexcept
+constexpr inline QPoint QRect::bottomRight() const noexcept
{ return QPoint(x2, y2); }
-Q_DECL_CONSTEXPR inline QPoint QRect::topRight() const noexcept
+constexpr inline QPoint QRect::topRight() const noexcept
{ return QPoint(x2, y1); }
-Q_DECL_CONSTEXPR inline QPoint QRect::bottomLeft() const noexcept
+constexpr inline QPoint QRect::bottomLeft() const noexcept
{ return QPoint(x1, y2); }
-Q_DECL_CONSTEXPR inline QPoint QRect::center() const noexcept
+constexpr inline QPoint QRect::center() const noexcept
{ return QPoint(int((qint64(x1)+x2)/2), int((qint64(y1)+y2)/2)); } // cast avoids overflow on addition
-Q_DECL_CONSTEXPR inline int QRect::width() const noexcept
+constexpr inline int QRect::width() const noexcept
{ return x2 - x1 + 1; }
-Q_DECL_CONSTEXPR inline int QRect::height() const noexcept
+constexpr inline int QRect::height() const noexcept
{ return y2 - y1 + 1; }
-Q_DECL_CONSTEXPR inline QSize QRect::size() const noexcept
+constexpr inline QSize QRect::size() const noexcept
{ return QSize(width(), height()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(int dx, int dy) noexcept
+constexpr inline void QRect::translate(int dx, int dy) noexcept
{
x1 += dx;
y1 += dy;
@@ -274,7 +250,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(int dx, int dy) noexcept
y2 += dy;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(const QPoint &p) noexcept
+constexpr inline void QRect::translate(const QPoint &p) noexcept
{
x1 += p.x();
y1 += p.y();
@@ -282,16 +258,16 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(const QPoint &p) noexcept
y2 += p.y();
}
-Q_DECL_CONSTEXPR inline QRect QRect::translated(int dx, int dy) const noexcept
+constexpr inline QRect QRect::translated(int dx, int dy) const noexcept
{ return QRect(QPoint(x1 + dx, y1 + dy), QPoint(x2 + dx, y2 + dy)); }
-Q_DECL_CONSTEXPR inline QRect QRect::translated(const QPoint &p) const noexcept
+constexpr inline QRect QRect::translated(const QPoint &p) const noexcept
{ return QRect(QPoint(x1 + p.x(), y1 + p.y()), QPoint(x2 + p.x(), y2 + p.y())); }
-Q_DECL_CONSTEXPR inline QRect QRect::transposed() const noexcept
+constexpr inline QRect QRect::transposed() const noexcept
{ return QRect(topLeft(), size().transposed()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(int ax, int ay) noexcept
+constexpr inline void QRect::moveTo(int ax, int ay) noexcept
{
x2 += ax - x1;
y2 += ay - y1;
@@ -299,7 +275,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(int ax, int ay) noexcept
y1 = ay;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(const QPoint &p) noexcept
+constexpr inline void QRect::moveTo(const QPoint &p) noexcept
{
x2 += p.x() - x1;
y2 += p.y() - y1;
@@ -307,49 +283,49 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(const QPoint &p) noexcept
y1 = p.y();
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveLeft(int pos) noexcept
+constexpr inline void QRect::moveLeft(int pos) noexcept
{ x2 += (pos - x1); x1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTop(int pos) noexcept
+constexpr inline void QRect::moveTop(int pos) noexcept
{ y2 += (pos - y1); y1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveRight(int pos) noexcept
+constexpr inline void QRect::moveRight(int pos) noexcept
{
x1 += (pos - x2);
x2 = pos;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottom(int pos) noexcept
+constexpr inline void QRect::moveBottom(int pos) noexcept
{
y1 += (pos - y2);
y2 = pos;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopLeft(const QPoint &p) noexcept
+constexpr inline void QRect::moveTopLeft(const QPoint &p) noexcept
{
moveLeft(p.x());
moveTop(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomRight(const QPoint &p) noexcept
+constexpr inline void QRect::moveBottomRight(const QPoint &p) noexcept
{
moveRight(p.x());
moveBottom(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopRight(const QPoint &p) noexcept
+constexpr inline void QRect::moveTopRight(const QPoint &p) noexcept
{
moveRight(p.x());
moveTop(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomLeft(const QPoint &p) noexcept
+constexpr inline void QRect::moveBottomLeft(const QPoint &p) noexcept
{
moveLeft(p.x());
moveBottom(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveCenter(const QPoint &p) noexcept
+constexpr inline void QRect::moveCenter(const QPoint &p) noexcept
{
int w = x2 - x1;
int h = y2 - y1;
@@ -359,7 +335,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveCenter(const QPoint &p) noexcept
y2 = y1 + h;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const
+constexpr inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const
{
*ax = x1;
*ay = y1;
@@ -367,7 +343,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::getRect(int *ax, int *ay, int *aw, i
*ah = y2 - y1 + 1;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRect(int ax, int ay, int aw, int ah) noexcept
+constexpr inline void QRect::setRect(int ax, int ay, int aw, int ah) noexcept
{
x1 = ax;
y1 = ay;
@@ -375,7 +351,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRect(int ax, int ay, int aw, int
y2 = (ay + ah - 1);
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const
+constexpr inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const
{
*xp1 = x1;
*yp1 = y1;
@@ -383,7 +359,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::getCoords(int *xp1, int *yp1, int *x
*yp2 = y2;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) noexcept
+constexpr inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) noexcept
{
x1 = xp1;
y1 = yp1;
@@ -391,10 +367,10 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::setCoords(int xp1, int yp1, int xp2,
y2 = yp2;
}
-Q_DECL_CONSTEXPR inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const noexcept
+constexpr inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const noexcept
{ return QRect(QPoint(x1 + xp1, y1 + yp1), QPoint(x2 + xp2, y2 + yp2)); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) noexcept
+constexpr inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) noexcept
{
x1 += dx1;
y1 += dy1;
@@ -402,13 +378,13 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::adjust(int dx1, int dy1, int dx2, in
y2 += dy2;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setWidth(int w) noexcept
+constexpr inline void QRect::setWidth(int w) noexcept
{ x2 = (x1 + w - 1); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setHeight(int h) noexcept
+constexpr inline void QRect::setHeight(int h) noexcept
{ y2 = (y1 + h - 1); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setSize(const QSize &s) noexcept
+constexpr inline void QRect::setSize(const QSize &s) noexcept
{
x2 = (s.width() + x1 - 1);
y2 = (s.height() + y1 - 1);
@@ -424,13 +400,13 @@ inline bool QRect::contains(int ax, int ay) const noexcept
return contains(QPoint(ax, ay), false);
}
-inline QRect& QRect::operator|=(const QRect &r) noexcept
+inline QRect &QRect::operator|=(const QRect &r) noexcept
{
*this = *this | r;
return *this;
}
-inline QRect& QRect::operator&=(const QRect &r) noexcept
+inline QRect &QRect::operator&=(const QRect &r) noexcept
{
*this = *this & r;
return *this;
@@ -446,58 +422,59 @@ inline QRect QRect::united(const QRect &r) const noexcept
return *this | r;
}
-Q_DECL_CONSTEXPR inline bool operator==(const QRect &r1, const QRect &r2) noexcept
+constexpr inline size_t qHash(const QRect &r, size_t seed = 0) noexcept
{
- return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2;
+ return qHashMulti(seed, r.x1, r.x2, r.y1, r.y2);
}
-Q_DECL_CONSTEXPR inline bool operator!=(const QRect &r1, const QRect &r2) noexcept
-{
- return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2;
-}
-
-Q_DECL_CONSTEXPR inline QRect operator+(const QRect &rectangle, const QMargins &margins) noexcept
+constexpr inline QRect operator+(const QRect &rectangle, const QMargins &margins) noexcept
{
return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()),
QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect operator+(const QMargins &margins, const QRect &rectangle) noexcept
+constexpr inline QRect operator+(const QMargins &margins, const QRect &rectangle) noexcept
{
return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()),
QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect operator-(const QRect &lhs, const QMargins &rhs) noexcept
+constexpr inline QRect operator-(const QRect &lhs, const QMargins &rhs) noexcept
{
return QRect(QPoint(lhs.left() + rhs.left(), lhs.top() + rhs.top()),
QPoint(lhs.right() - rhs.right(), lhs.bottom() - rhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect QRect::marginsAdded(const QMargins &margins) const noexcept
+constexpr inline QRect QRect::marginsAdded(const QMargins &margins) const noexcept
{
return QRect(QPoint(x1 - margins.left(), y1 - margins.top()),
QPoint(x2 + margins.right(), y2 + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect QRect::marginsRemoved(const QMargins &margins) const noexcept
+constexpr inline QRect QRect::marginsRemoved(const QMargins &margins) const noexcept
{
return QRect(QPoint(x1 + margins.left(), y1 + margins.top()),
QPoint(x2 - margins.right(), y2 - margins.bottom()));
}
-Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator+=(const QMargins &margins) noexcept
+constexpr inline QRect &QRect::operator+=(const QMargins &margins) noexcept
{
*this = marginsAdded(margins);
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator-=(const QMargins &margins) noexcept
+constexpr inline QRect &QRect::operator-=(const QMargins &margins) noexcept
{
*this = marginsRemoved(margins);
return *this;
}
+constexpr QRect QRect::span(const QPoint &p1, const QPoint &p2) noexcept
+{
+ return QRect(QPoint(qMin(p1.x(), p2.x()), qMin(p1.y(), p2.y())),
+ QPoint(qMax(p1.x(), p2.x()), qMax(p1.y(), p2.y())));
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &);
#endif
@@ -506,105 +483,131 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &);
class Q_CORE_EXPORT QRectF
{
public:
- Q_DECL_CONSTEXPR QRectF() noexcept : xp(0.), yp(0.), w(0.), h(0.) {}
- Q_DECL_CONSTEXPR QRectF(const QPointF &topleft, const QSizeF &size) noexcept;
- Q_DECL_CONSTEXPR QRectF(const QPointF &topleft, const QPointF &bottomRight) noexcept;
- Q_DECL_CONSTEXPR QRectF(qreal left, qreal top, qreal width, qreal height) noexcept;
- Q_DECL_CONSTEXPR QRectF(const QRect &rect) noexcept;
-
- Q_DECL_CONSTEXPR inline bool isNull() const noexcept;
- Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
- Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
- Q_REQUIRED_RESULT QRectF normalized() const noexcept;
-
- Q_DECL_CONSTEXPR inline qreal left() const noexcept { return xp; }
- Q_DECL_CONSTEXPR inline qreal top() const noexcept { return yp; }
- Q_DECL_CONSTEXPR inline qreal right() const noexcept { return xp + w; }
- Q_DECL_CONSTEXPR inline qreal bottom() const noexcept { return yp + h; }
-
- Q_DECL_CONSTEXPR inline qreal x() const noexcept;
- Q_DECL_CONSTEXPR inline qreal y() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setLeft(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setTop(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setRight(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottom(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setX(qreal pos) noexcept { setLeft(pos); }
- Q_DECL_RELAXED_CONSTEXPR inline void setY(qreal pos) noexcept { setTop(pos); }
-
- Q_DECL_CONSTEXPR inline QPointF topLeft() const noexcept { return QPointF(xp, yp); }
- Q_DECL_CONSTEXPR inline QPointF bottomRight() const noexcept { return QPointF(xp+w, yp+h); }
- Q_DECL_CONSTEXPR inline QPointF topRight() const noexcept { return QPointF(xp+w, yp); }
- Q_DECL_CONSTEXPR inline QPointF bottomLeft() const noexcept { return QPointF(xp, yp+h); }
- Q_DECL_CONSTEXPR inline QPointF center() const noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPointF &p) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTop(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveRight(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(qreal pos) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPointF &p) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPointF &p) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void translate(qreal dx, qreal dy) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPointF &p) noexcept;
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const noexcept;
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF transposed() const noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(qreal x, qreal y) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPointF &p) noexcept;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setRect(qreal x, qreal y, qreal w, qreal h) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setCoords(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
-
- Q_DECL_RELAXED_CONSTEXPR inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept;
-
- Q_DECL_CONSTEXPR inline QSizeF size() const noexcept;
- Q_DECL_CONSTEXPR inline qreal width() const noexcept;
- Q_DECL_CONSTEXPR inline qreal height() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSizeF &s) noexcept;
+ constexpr QRectF() noexcept : xp(0.), yp(0.), w(0.), h(0.) {}
+ constexpr QRectF(const QPointF &topleft, const QSizeF &size) noexcept;
+ constexpr QRectF(const QPointF &topleft, const QPointF &bottomRight) noexcept;
+ constexpr QRectF(qreal left, qreal top, qreal width, qreal height) noexcept;
+ constexpr QRectF(const QRect &rect) noexcept;
+
+ constexpr inline bool isNull() const noexcept;
+ constexpr inline bool isEmpty() const noexcept;
+ constexpr inline bool isValid() const noexcept;
+ [[nodiscard]] QRectF normalized() const noexcept;
+
+ constexpr inline qreal left() const noexcept { return xp; }
+ constexpr inline qreal top() const noexcept { return yp; }
+ constexpr inline qreal right() const noexcept { return xp + w; }
+ constexpr inline qreal bottom() const noexcept { return yp + h; }
+
+ constexpr inline qreal x() const noexcept;
+ constexpr inline qreal y() const noexcept;
+ constexpr inline void setLeft(qreal pos) noexcept;
+ constexpr inline void setTop(qreal pos) noexcept;
+ constexpr inline void setRight(qreal pos) noexcept;
+ constexpr inline void setBottom(qreal pos) noexcept;
+ constexpr inline void setX(qreal pos) noexcept { setLeft(pos); }
+ constexpr inline void setY(qreal pos) noexcept { setTop(pos); }
+
+ constexpr inline QPointF topLeft() const noexcept { return QPointF(xp, yp); }
+ constexpr inline QPointF bottomRight() const noexcept { return QPointF(xp+w, yp+h); }
+ constexpr inline QPointF topRight() const noexcept { return QPointF(xp+w, yp); }
+ constexpr inline QPointF bottomLeft() const noexcept { return QPointF(xp, yp+h); }
+ constexpr inline QPointF center() const noexcept;
+
+ constexpr inline void setTopLeft(const QPointF &p) noexcept;
+ constexpr inline void setBottomRight(const QPointF &p) noexcept;
+ constexpr inline void setTopRight(const QPointF &p) noexcept;
+ constexpr inline void setBottomLeft(const QPointF &p) noexcept;
+
+ constexpr inline void moveLeft(qreal pos) noexcept;
+ constexpr inline void moveTop(qreal pos) noexcept;
+ constexpr inline void moveRight(qreal pos) noexcept;
+ constexpr inline void moveBottom(qreal pos) noexcept;
+ constexpr inline void moveTopLeft(const QPointF &p) noexcept;
+ constexpr inline void moveBottomRight(const QPointF &p) noexcept;
+ constexpr inline void moveTopRight(const QPointF &p) noexcept;
+ constexpr inline void moveBottomLeft(const QPointF &p) noexcept;
+ constexpr inline void moveCenter(const QPointF &p) noexcept;
+
+ constexpr inline void translate(qreal dx, qreal dy) noexcept;
+ constexpr inline void translate(const QPointF &p) noexcept;
+
+ [[nodiscard]] constexpr inline QRectF translated(qreal dx, qreal dy) const noexcept;
+ [[nodiscard]] constexpr inline QRectF translated(const QPointF &p) const noexcept;
+
+ [[nodiscard]] constexpr inline QRectF transposed() const noexcept;
+
+ constexpr inline void moveTo(qreal x, qreal y) noexcept;
+ constexpr inline void moveTo(const QPointF &p) noexcept;
+
+ constexpr inline void setRect(qreal x, qreal y, qreal w, qreal h) noexcept;
+ constexpr inline void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const;
+
+ constexpr inline void setCoords(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
+ constexpr inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
+
+ constexpr inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
+ [[nodiscard]] constexpr inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept;
+
+ constexpr inline QSizeF size() const noexcept;
+ constexpr inline qreal width() const noexcept;
+ constexpr inline qreal height() const noexcept;
+ constexpr inline void setWidth(qreal w) noexcept;
+ constexpr inline void setHeight(qreal h) noexcept;
+ constexpr inline void setSize(const QSizeF &s) noexcept;
QRectF operator|(const QRectF &r) const noexcept;
QRectF operator&(const QRectF &r) const noexcept;
- inline QRectF& operator|=(const QRectF &r) noexcept;
- inline QRectF& operator&=(const QRectF &r) noexcept;
+ inline QRectF &operator|=(const QRectF &r) noexcept;
+ inline QRectF &operator&=(const QRectF &r) noexcept;
bool contains(const QRectF &r) const noexcept;
bool contains(const QPointF &p) const noexcept;
inline bool contains(qreal x, qreal y) const noexcept;
- Q_REQUIRED_RESULT inline QRectF united(const QRectF &other) const noexcept;
- Q_REQUIRED_RESULT inline QRectF intersected(const QRectF &other) const noexcept;
+ [[nodiscard]] inline QRectF united(const QRectF &other) const noexcept;
+ [[nodiscard]] inline QRectF intersected(const QRectF &other) const noexcept;
bool intersects(const QRectF &r) const noexcept;
- Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const noexcept;
- Q_DECL_CONSTEXPR inline QRectF marginsRemoved(const QMarginsF &margins) const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator+=(const QMarginsF &margins) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator-=(const QMarginsF &margins) noexcept;
+ constexpr inline QRectF marginsAdded(const QMarginsF &margins) const noexcept;
+ constexpr inline QRectF marginsRemoved(const QMarginsF &margins) const noexcept;
+ constexpr inline QRectF &operator+=(const QMarginsF &margins) noexcept;
+ constexpr inline QRectF &operator-=(const QMarginsF &margins) noexcept;
- friend Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &) noexcept;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &) noexcept;
+private:
+ friend constexpr bool comparesEqual(const QRectF &r1, const QRectF &r2) noexcept
+ {
+ return r1.topLeft() == r2.topLeft()
+ && r1.size() == r2.size();
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QRectF)
+
+ friend constexpr bool comparesEqual(const QRectF &r1, const QRect &r2) noexcept
+ { return r1.topLeft() == r2.topLeft() && r1.size() == r2.size(); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QRectF, QRect)
+
+ friend constexpr bool qFuzzyCompare(const QRectF &lhs, const QRectF &rhs) noexcept
+ {
+ return qFuzzyCompare(lhs.topLeft(), rhs.topLeft())
+ && qFuzzyCompare(lhs.bottomRight(), rhs.bottomRight());
+ }
+
+ friend constexpr bool qFuzzyIsNull(const QRectF &rect) noexcept
+ {
+ return qFuzzyIsNull(rect.w) && qFuzzyIsNull(rect.h);
+ }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect toRect() const noexcept;
- Q_REQUIRED_RESULT QRect toAlignedRect() const noexcept;
+public:
+ [[nodiscard]] constexpr inline QRect toRect() const noexcept;
+ [[nodiscard]] QRect toAlignedRect() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QRectF fromCGRect(CGRect rect) noexcept;
- Q_REQUIRED_RESULT CGRect toCGRect() const noexcept;
+ [[nodiscard]] static QRectF fromCGRect(CGRect rect) noexcept;
+ [[nodiscard]] CGRect toCGRect() const noexcept;
+#endif
+
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+ [[nodiscard]] static QRectF fromDOMRect(emscripten::val domRect);
+ [[nodiscard]] emscripten::val toDOMRect() const;
#endif
private:
@@ -613,10 +616,7 @@ private:
qreal w;
qreal h;
};
-Q_DECLARE_TYPEINFO(QRectF, Q_MOVABLE_TYPE);
-
-Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &) noexcept;
-Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &) noexcept;
+Q_DECLARE_TYPEINFO(QRectF, Q_RELOCATABLE_TYPE);
/*****************************************************************************
@@ -631,23 +631,23 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRectF &);
QRectF inline member functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QRectF::QRectF(qreal aleft, qreal atop, qreal awidth, qreal aheight) noexcept
+constexpr inline QRectF::QRectF(qreal aleft, qreal atop, qreal awidth, qreal aheight) noexcept
: xp(aleft), yp(atop), w(awidth), h(aheight)
{
}
-Q_DECL_CONSTEXPR inline QRectF::QRectF(const QPointF &atopLeft, const QSizeF &asize) noexcept
+constexpr inline QRectF::QRectF(const QPointF &atopLeft, const QSizeF &asize) noexcept
: xp(atopLeft.x()), yp(atopLeft.y()), w(asize.width()), h(asize.height())
{
}
-Q_DECL_CONSTEXPR inline QRectF::QRectF(const QPointF &atopLeft, const QPointF &abottomRight) noexcept
+constexpr inline QRectF::QRectF(const QPointF &atopLeft, const QPointF &abottomRight) noexcept
: xp(atopLeft.x()), yp(atopLeft.y()), w(abottomRight.x() - atopLeft.x()), h(abottomRight.y() - atopLeft.y())
{
}
-Q_DECL_CONSTEXPR inline QRectF::QRectF(const QRect &r) noexcept
+constexpr inline QRectF::QRectF(const QRect &r) noexcept
: xp(r.x()), yp(r.y()), w(r.width()), h(r.height())
{
}
@@ -655,120 +655,122 @@ Q_DECL_CONSTEXPR inline QRectF::QRectF(const QRect &r) noexcept
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
-Q_DECL_CONSTEXPR inline bool QRectF::isNull() const noexcept
+constexpr inline bool QRectF::isNull() const noexcept
{ return w == 0. && h == 0.; }
-Q_DECL_CONSTEXPR inline bool QRectF::isEmpty() const noexcept
+constexpr inline bool QRectF::isEmpty() const noexcept
{ return w <= 0. || h <= 0.; }
QT_WARNING_POP
-Q_DECL_CONSTEXPR inline bool QRectF::isValid() const noexcept
+constexpr inline bool QRectF::isValid() const noexcept
{ return w > 0. && h > 0.; }
-Q_DECL_CONSTEXPR inline qreal QRectF::x() const noexcept
+constexpr inline qreal QRectF::x() const noexcept
{ return xp; }
-Q_DECL_CONSTEXPR inline qreal QRectF::y() const noexcept
+constexpr inline qreal QRectF::y() const noexcept
{ return yp; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setLeft(qreal pos) noexcept
+constexpr inline void QRectF::setLeft(qreal pos) noexcept
{ qreal diff = pos - xp; xp += diff; w -= diff; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRight(qreal pos) noexcept
+constexpr inline void QRectF::setRight(qreal pos) noexcept
{ w = pos - xp; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTop(qreal pos) noexcept
+constexpr inline void QRectF::setTop(qreal pos) noexcept
{ qreal diff = pos - yp; yp += diff; h -= diff; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottom(qreal pos) noexcept
+constexpr inline void QRectF::setBottom(qreal pos) noexcept
{ h = pos - yp; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopLeft(const QPointF &p) noexcept
+constexpr inline void QRectF::setTopLeft(const QPointF &p) noexcept
{ setLeft(p.x()); setTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopRight(const QPointF &p) noexcept
+constexpr inline void QRectF::setTopRight(const QPointF &p) noexcept
{ setRight(p.x()); setTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomLeft(const QPointF &p) noexcept
+constexpr inline void QRectF::setBottomLeft(const QPointF &p) noexcept
{ setLeft(p.x()); setBottom(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomRight(const QPointF &p) noexcept
+constexpr inline void QRectF::setBottomRight(const QPointF &p) noexcept
{ setRight(p.x()); setBottom(p.y()); }
-Q_DECL_CONSTEXPR inline QPointF QRectF::center() const noexcept
+constexpr inline QPointF QRectF::center() const noexcept
{ return QPointF(xp + w/2, yp + h/2); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveLeft(qreal pos) noexcept
+constexpr inline void QRectF::moveLeft(qreal pos) noexcept
{ xp = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTop(qreal pos) noexcept
+constexpr inline void QRectF::moveTop(qreal pos) noexcept
{ yp = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveRight(qreal pos) noexcept
+constexpr inline void QRectF::moveRight(qreal pos) noexcept
{ xp = pos - w; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottom(qreal pos) noexcept
+constexpr inline void QRectF::moveBottom(qreal pos) noexcept
{ yp = pos - h; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopLeft(const QPointF &p) noexcept
+constexpr inline void QRectF::moveTopLeft(const QPointF &p) noexcept
{ moveLeft(p.x()); moveTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopRight(const QPointF &p) noexcept
+constexpr inline void QRectF::moveTopRight(const QPointF &p) noexcept
{ moveRight(p.x()); moveTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomLeft(const QPointF &p) noexcept
+constexpr inline void QRectF::moveBottomLeft(const QPointF &p) noexcept
{ moveLeft(p.x()); moveBottom(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomRight(const QPointF &p) noexcept
+constexpr inline void QRectF::moveBottomRight(const QPointF &p) noexcept
{ moveRight(p.x()); moveBottom(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveCenter(const QPointF &p) noexcept
+constexpr inline void QRectF::moveCenter(const QPointF &p) noexcept
{ xp = p.x() - w/2; yp = p.y() - h/2; }
-Q_DECL_CONSTEXPR inline qreal QRectF::width() const noexcept
+constexpr inline qreal QRectF::width() const noexcept
{ return w; }
-Q_DECL_CONSTEXPR inline qreal QRectF::height() const noexcept
+constexpr inline qreal QRectF::height() const noexcept
{ return h; }
-Q_DECL_CONSTEXPR inline QSizeF QRectF::size() const noexcept
+constexpr inline QSizeF QRectF::size() const noexcept
{ return QSizeF(w, h); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(qreal dx, qreal dy) noexcept
+constexpr inline void QRectF::translate(qreal dx, qreal dy) noexcept
{
xp += dx;
yp += dy;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(const QPointF &p) noexcept
+constexpr inline void QRectF::translate(const QPointF &p) noexcept
{
xp += p.x();
yp += p.y();
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(qreal ax, qreal ay) noexcept
+constexpr inline void QRectF::moveTo(qreal ax, qreal ay) noexcept
{
xp = ax;
yp = ay;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(const QPointF &p) noexcept
+constexpr inline void QRectF::moveTo(const QPointF &p) noexcept
{
xp = p.x();
yp = p.y();
}
-Q_DECL_CONSTEXPR inline QRectF QRectF::translated(qreal dx, qreal dy) const noexcept
-{ return QRectF(xp + dx, yp + dy, w, h); }
+constexpr inline QRectF QRectF::translated(qreal dx, qreal dy) const noexcept
+{
+ return QRectF(xp + dx, yp + dy, w, h);
+}
-Q_DECL_CONSTEXPR inline QRectF QRectF::translated(const QPointF &p) const noexcept
+constexpr inline QRectF QRectF::translated(const QPointF &p) const noexcept
{ return QRectF(xp + p.x(), yp + p.y(), w, h); }
-Q_DECL_CONSTEXPR inline QRectF QRectF::transposed() const noexcept
+constexpr inline QRectF QRectF::transposed() const noexcept
{ return QRectF(topLeft(), size().transposed()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const
+constexpr inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const
{
*ax = this->xp;
*ay = this->yp;
@@ -776,7 +778,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getRect(qreal *ax, qreal *ay, qreal
*aah = this->h;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) noexcept
+constexpr inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) noexcept
{
this->xp = ax;
this->yp = ay;
@@ -784,7 +786,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRect(qreal ax, qreal ay, qreal a
this->h = aah;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) const
+constexpr inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) const
{
*xp1 = xp;
*yp1 = yp;
@@ -792,7 +794,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getCoords(qreal *xp1, qreal *yp1, q
*yp2 = yp + h;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) noexcept
+constexpr inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) noexcept
{
xp = xp1;
yp = yp1;
@@ -800,19 +802,26 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setCoords(qreal xp1, qreal yp1, qre
h = yp2 - yp1;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) noexcept
-{ xp += xp1; yp += yp1; w += xp2 - xp1; h += yp2 - yp1; }
+constexpr inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) noexcept
+{
+ xp += xp1;
+ yp += yp1;
+ w += xp2 - xp1;
+ h += yp2 - yp1;
+}
-Q_DECL_CONSTEXPR inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const noexcept
-{ return QRectF(xp + xp1, yp + yp1, w + xp2 - xp1, h + yp2 - yp1); }
+constexpr inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const noexcept
+{
+ return QRectF(xp + xp1, yp + yp1, w + xp2 - xp1, h + yp2 - yp1);
+}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setWidth(qreal aw) noexcept
+constexpr inline void QRectF::setWidth(qreal aw) noexcept
{ this->w = aw; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setHeight(qreal ah) noexcept
+constexpr inline void QRectF::setHeight(qreal ah) noexcept
{ this->h = ah; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setSize(const QSizeF &s) noexcept
+constexpr inline void QRectF::setSize(const QSizeF &s) noexcept
{
w = s.width();
h = s.height();
@@ -823,13 +832,13 @@ inline bool QRectF::contains(qreal ax, qreal ay) const noexcept
return contains(QPointF(ax, ay));
}
-inline QRectF& QRectF::operator|=(const QRectF &r) noexcept
+inline QRectF &QRectF::operator|=(const QRectF &r) noexcept
{
*this = *this | r;
return *this;
}
-inline QRectF& QRectF::operator&=(const QRectF &r) noexcept
+inline QRectF &QRectF::operator&=(const QRectF &r) noexcept
{
*this = *this & r;
return *this;
@@ -845,60 +854,57 @@ inline QRectF QRectF::united(const QRectF &r) const noexcept
return *this | r;
}
-Q_DECL_CONSTEXPR inline bool operator==(const QRectF &r1, const QRectF &r2) noexcept
-{
- return qFuzzyCompare(r1.xp, r2.xp) && qFuzzyCompare(r1.yp, r2.yp)
- && qFuzzyCompare(r1.w, r2.w) && qFuzzyCompare(r1.h, r2.h);
-}
-
-Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &r1, const QRectF &r2) noexcept
-{
- return !qFuzzyCompare(r1.xp, r2.xp) || !qFuzzyCompare(r1.yp, r2.yp)
- || !qFuzzyCompare(r1.w, r2.w) || !qFuzzyCompare(r1.h, r2.h);
-}
+constexpr QRectF QRect::toRectF() const noexcept { return *this; }
-Q_DECL_CONSTEXPR inline QRect QRectF::toRect() const noexcept
+constexpr inline QRect QRectF::toRect() const noexcept
{
- return QRect(QPoint(qRound(xp), qRound(yp)), QPoint(qRound(xp + w) - 1, qRound(yp + h) - 1));
+ // This rounding is designed to minimize the maximum possible difference
+ // in topLeft(), bottomRight(), and size() after rounding.
+ // All dimensions are at most off by 0.75, and topLeft by at most 0.5.
+ const int nxp = qRound(xp);
+ const int nyp = qRound(yp);
+ const int nw = qRound(w + (xp - nxp) / 2);
+ const int nh = qRound(h + (yp - nyp) / 2);
+ return QRect(nxp, nyp, nw, nh);
}
-Q_DECL_CONSTEXPR inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) noexcept
+constexpr inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) noexcept
{
return QRectF(QPointF(lhs.left() - rhs.left(), lhs.top() - rhs.top()),
QSizeF(lhs.width() + rhs.left() + rhs.right(), lhs.height() + rhs.top() + rhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF operator+(const QMarginsF &lhs, const QRectF &rhs) noexcept
+constexpr inline QRectF operator+(const QMarginsF &lhs, const QRectF &rhs) noexcept
{
return QRectF(QPointF(rhs.left() - lhs.left(), rhs.top() - lhs.top()),
QSizeF(rhs.width() + lhs.left() + lhs.right(), rhs.height() + lhs.top() + lhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) noexcept
+constexpr inline QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) noexcept
{
return QRectF(QPointF(lhs.left() + rhs.left(), lhs.top() + rhs.top()),
QSizeF(lhs.width() - rhs.left() - rhs.right(), lhs.height() - rhs.top() - rhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF QRectF::marginsAdded(const QMarginsF &margins) const noexcept
+constexpr inline QRectF QRectF::marginsAdded(const QMarginsF &margins) const noexcept
{
return QRectF(QPointF(xp - margins.left(), yp - margins.top()),
QSizeF(w + margins.left() + margins.right(), h + margins.top() + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF QRectF::marginsRemoved(const QMarginsF &margins) const noexcept
+constexpr inline QRectF QRectF::marginsRemoved(const QMarginsF &margins) const noexcept
{
return QRectF(QPointF(xp + margins.left(), yp + margins.top()),
QSizeF(w - margins.left() - margins.right(), h - margins.top() - margins.bottom()));
}
-Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator+=(const QMarginsF &margins) noexcept
+constexpr inline QRectF &QRectF::operator+=(const QMarginsF &margins) noexcept
{
*this = marginsAdded(margins);
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator-=(const QMarginsF &margins) noexcept
+constexpr inline QRectF &QRectF::operator-=(const QMarginsF &margins) noexcept
{
*this = marginsRemoved(margins);
return *this;
diff --git a/src/corelib/tools/qrefcount.cpp b/src/corelib/tools/qrefcount.cpp
index 1986cce9ca..c33b34594b 100644
--- a/src/corelib/tools/qrefcount.cpp
+++ b/src/corelib/tools/qrefcount.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QtPrivate::RefCount
diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h
index 982a9c2bbf..9472716a72 100644
--- a/src/corelib/tools/qrefcount.h
+++ b/src/corelib/tools/qrefcount.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QREFCOUNT_H
#define QREFCOUNT_H
diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp
index 311058a776..0645759118 100644
--- a/src/corelib/tools/qringbuffer.cpp
+++ b/src/corelib/tools/qringbuffer.cpp
@@ -1,50 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Alex Trotsenko <alex1973tr@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2015 Alex Trotsenko <alex1973tr@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qringbuffer_p.h"
-#include "private/qbytearray_p.h"
+
+#include <type_traits>
+
#include <string.h>
QT_BEGIN_NAMESPACE
-void QRingChunk::allocate(int alloc)
+static_assert(std::is_nothrow_default_constructible_v<QRingChunk>);
+static_assert(std::is_nothrow_move_constructible_v<QRingChunk>);
+static_assert(std::is_nothrow_move_assignable_v<QRingChunk>);
+
+void QRingChunk::allocate(qsizetype alloc)
{
Q_ASSERT(alloc > 0 && size() == 0);
@@ -56,32 +26,24 @@ void QRingChunk::detach()
{
Q_ASSERT(isShared());
- const int chunkSize = size();
- QByteArray x(chunkSize, Qt::Uninitialized);
- ::memcpy(x.data(), chunk.constData() + headOffset, chunkSize);
- chunk = std::move(x);
+ const qsizetype chunkSize = size();
+ chunk = QByteArray(std::as_const(*this).data(), chunkSize);
headOffset = 0;
tailOffset = chunkSize;
}
-QByteArray QRingChunk::toByteArray()
+QByteArray QRingChunk::toByteArray() &&
{
+ // ### Replace with std::move(chunk).sliced(head(), size()) once sliced()&& is available
if (headOffset != 0 || tailOffset != chunk.size()) {
if (isShared())
- return chunk.mid(headOffset, size());
-
- if (headOffset != 0) {
- char *ptr = chunk.data();
- ::memmove(ptr, ptr + headOffset, size());
- tailOffset -= headOffset;
- headOffset = 0;
- }
+ return chunk.sliced(head(), size());
- chunk.reserve(0); // avoid that resizing needlessly reallocates
chunk.resize(tailOffset);
+ chunk.remove(0, headOffset);
}
- return chunk;
+ return std::move(chunk);
}
/*!
@@ -128,7 +90,7 @@ void QRingBuffer::free(qint64 bytes)
clear(); // try to minify/squeeze us
}
} else {
- Q_ASSERT(bytes < MaxByteArraySize);
+ Q_ASSERT(bytes < QByteArray::max_size());
chunk.advance(bytes);
bufferSize -= bytes;
}
@@ -143,10 +105,10 @@ void QRingBuffer::free(qint64 bytes)
char *QRingBuffer::reserve(qint64 bytes)
{
- Q_ASSERT(bytes > 0 && bytes < MaxByteArraySize);
+ Q_ASSERT(bytes > 0 && bytes < QByteArray::max_size());
- const int chunkSize = qMax(basicBlockSize, int(bytes));
- int tail = 0;
+ const qsizetype chunkSize = qMax(qint64(basicBlockSize), bytes);
+ qsizetype tail = 0;
if (bufferSize == 0) {
if (buffers.isEmpty())
buffers.append(QRingChunk(chunkSize));
@@ -173,9 +135,9 @@ char *QRingBuffer::reserve(qint64 bytes)
*/
char *QRingBuffer::reserveFront(qint64 bytes)
{
- Q_ASSERT(bytes > 0 && bytes < MaxByteArraySize);
+ Q_ASSERT(bytes > 0 && bytes < QByteArray::max_size());
- const int chunkSize = qMax(basicBlockSize, int(bytes));
+ const qsizetype chunkSize = qMax(qint64(basicBlockSize), bytes);
if (bufferSize == 0) {
if (buffers.isEmpty())
buffers.prepend(QRingChunk(chunkSize));
@@ -204,7 +166,7 @@ void QRingBuffer::chop(qint64 bytes)
Q_ASSERT(bytes <= bufferSize);
while (bytes > 0) {
- const qint64 chunkSize = buffers.constLast().size();
+ const qsizetype chunkSize = buffers.constLast().size();
if (buffers.size() == 1 || chunkSize > bytes) {
QRingChunk &chunk = buffers.last();
@@ -219,7 +181,7 @@ void QRingBuffer::chop(qint64 bytes)
clear(); // try to minify/squeeze us
}
} else {
- Q_ASSERT(bytes < MaxByteArraySize);
+ Q_ASSERT(bytes < QByteArray::max_size());
chunk.grow(-bytes);
bufferSize -= bytes;
}
@@ -363,6 +325,21 @@ void QRingBuffer::append(const QByteArray &qba)
bufferSize += qba.size();
}
+/*!
+ \internal
+
+ Append a new buffer to the end
+*/
+void QRingBuffer::append(QByteArray &&qba)
+{
+ const auto qbaSize = qba.size();
+ if (bufferSize != 0 || buffers.isEmpty())
+ buffers.emplace_back(std::move(qba));
+ else
+ buffers.last().assign(std::move(qba));
+ bufferSize += qbaSize;
+}
+
qint64 QRingBuffer::readLine(char *data, qint64 maxLength)
{
Q_ASSERT(data != nullptr && maxLength > 1);
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 85a3882a3c..25113213c9 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRINGBUFFER_P_H
#define QRINGBUFFER_P_H
@@ -65,39 +29,18 @@ class QRingChunk
{
public:
// initialization and cleanup
- inline QRingChunk() noexcept :
- headOffset(0), tailOffset(0)
- {
- }
- inline QRingChunk(const QRingChunk &other) noexcept :
- chunk(other.chunk), headOffset(other.headOffset), tailOffset(other.tailOffset)
- {
- }
- explicit inline QRingChunk(int alloc) :
- chunk(alloc, Qt::Uninitialized), headOffset(0), tailOffset(0)
+ QRingChunk() noexcept = default;
+ explicit inline QRingChunk(qsizetype alloc) :
+ chunk(alloc, Qt::Uninitialized), tailOffset(0)
{
}
explicit inline QRingChunk(const QByteArray &qba) noexcept :
- chunk(qba), headOffset(0), tailOffset(qba.size())
+ chunk(qba), tailOffset(qba.size())
{
}
-
- inline QRingChunk &operator=(const QRingChunk &other) noexcept
- {
- chunk = other.chunk;
- headOffset = other.headOffset;
- tailOffset = other.tailOffset;
- return *this;
- }
- inline QRingChunk(QRingChunk &&other) noexcept :
- chunk(other.chunk), headOffset(other.headOffset), tailOffset(other.tailOffset)
+ explicit QRingChunk(QByteArray &&qba) noexcept :
+ chunk(std::move(qba)), tailOffset(chunk.size())
{
- other.headOffset = other.tailOffset = 0;
- }
- inline QRingChunk &operator=(QRingChunk &&other) noexcept
- {
- swap(other);
- return *this;
}
inline void swap(QRingChunk &other) noexcept
@@ -108,28 +51,28 @@ public:
}
// allocating and sharing
- void allocate(int alloc);
+ void allocate(qsizetype alloc);
inline bool isShared() const
{
return !chunk.isDetached();
}
Q_CORE_EXPORT void detach();
- QByteArray toByteArray();
+ QByteArray toByteArray() &&;
// getters
- inline int head() const
+ inline qsizetype head() const
{
return headOffset;
}
- inline int size() const
+ inline qsizetype size() const
{
return tailOffset - headOffset;
}
- inline int capacity() const
+ inline qsizetype capacity() const
{
return chunk.size();
}
- inline int available() const
+ inline qsizetype available() const
{
return chunk.size() - tailOffset;
}
@@ -145,14 +88,14 @@ public:
}
// array management
- inline void advance(int offset)
+ inline void advance(qsizetype offset)
{
Q_ASSERT(headOffset + offset >= 0);
Q_ASSERT(size() - offset > 0);
headOffset += offset;
}
- inline void grow(int offset)
+ inline void grow(qsizetype offset)
{
Q_ASSERT(size() + offset > 0);
Q_ASSERT(head() + size() + offset <= capacity());
@@ -165,26 +108,38 @@ public:
headOffset = 0;
tailOffset = qba.size();
}
+ void assign(QByteArray &&qba)
+ {
+ chunk = std::move(qba);
+ headOffset = 0;
+ tailOffset = chunk.size();
+ }
inline void reset()
{
headOffset = tailOffset = 0;
}
inline void clear()
{
- assign(QByteArray());
+ *this = {};
}
private:
QByteArray chunk;
- int headOffset, tailOffset;
+ qsizetype headOffset = 0;
+ qsizetype tailOffset = 0;
};
+Q_DECLARE_SHARED(QRingChunk)
class QRingBuffer
{
+ Q_DISABLE_COPY(QRingBuffer)
public:
explicit inline QRingBuffer(int growth = QRINGBUFFER_CHUNKSIZE) :
bufferSize(0), basicBlockSize(growth) { }
+ QRingBuffer(QRingBuffer &&) noexcept = default;
+ QRingBuffer &operator=(QRingBuffer &&) noexcept = default;
+
inline void setChunkSize(int size) {
basicBlockSize = size;
}
@@ -250,6 +205,7 @@ public:
Q_CORE_EXPORT qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const;
Q_CORE_EXPORT void append(const char *data, qint64 size);
Q_CORE_EXPORT void append(const QByteArray &qba);
+ Q_CORE_EXPORT void append(QByteArray &&qba);
inline qint64 skip(qint64 length) {
qint64 bytesToSkip = qMin(length, bufferSize);
@@ -270,8 +226,7 @@ private:
int basicBlockSize;
};
-Q_DECLARE_SHARED(QRingChunk)
-Q_DECLARE_TYPEINFO(QRingBuffer, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRingBuffer, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
index eb08bdba62..515eb9dc75 100644
--- a/src/corelib/tools/qscopedpointer.cpp
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qscopedpointer.h"
@@ -126,7 +90,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> QScopedPointer<T, Cleanup>::QScopedPointer(T *p = 0)
+ \fn template <typename T, typename Cleanup> QScopedPointer<T, Cleanup>::QScopedPointer(T *p = nullptr)
Constructs this QScopedPointer instance and sets its pointer to \a p.
*/
@@ -183,21 +147,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
- Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
+ Returns \c true if \a lhs and \a rhs refer to the same pointer.
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
Returns \c true if \a lhs and \a rhs refer to distinct pointers.
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
\since 5.8
Returns \c true if \a lhs refers to \nullptr.
@@ -206,8 +169,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
\since 5.8
Returns \c true if \a rhs refers to \nullptr.
@@ -216,8 +178,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
\since 5.8
Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
@@ -226,8 +187,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
- \relates QScopedPointer
+ \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
\since 5.8
Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
@@ -242,19 +202,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::reset(T *other = 0)
+ \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::reset(T *other = nullptr)
Deletes the existing object it is pointing to (if any), and sets its pointer to
\a other. QScopedPointer now owns \a other and will delete it in its
destructor.
-
- To clear the pointer held without deleting the object it points to (and hence take ownership
- of the object), use \l take() instead.
*/
/*!
\fn template <typename T, typename Cleanup> T *QScopedPointer<T, Cleanup>::take()
+ \deprecated [6.1] Use \c std::unique_ptr and \c release() instead.
+
Returns the value of the pointer referenced by this object. The pointer of this
QScopedPointer object will be reset to \nullptr.
@@ -268,8 +227,12 @@ QT_BEGIN_NAMESPACE
\sa isNull()
*/
-/*! \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::swap(QScopedPointer<T, Cleanup> &other)
- Swap this pointer with \a other.
+/*! \fn template <typename T, typename Cleanup> void QScopedPointer<T, Cleanup>::swap(QScopedPointer<T, Cleanup> &lhs, QScopedPointer<T, Cleanup> &rhs)
+
+ \deprecated [6.1] Use \c std::unique_ptr instead; this function may let a pointer
+ escape its scope.
+
+ Swaps \a lhs with \a rhs.
*/
/*!
@@ -306,36 +269,46 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template <typename T, typename Cleanup> template <typename D> QScopedArrayPointer<T, Cleanup>::QScopedArrayPointer(D * p)
+ \fn template <typename T, typename Cleanup> template <typename D, QScopedArrayPointer<T, Cleanup>::if_same_type<D> = true> QScopedArrayPointer<T, Cleanup>::QScopedArrayPointer(D * p)
Constructs a QScopedArrayPointer and stores the array of objects
pointed to by \a p.
*/
/*!
- \fn template <typename T, typename Cleanup> T *QScopedArrayPointer<T, Cleanup>::operator[](int i)
+ \fn template <typename T, typename Cleanup> T *QScopedArrayPointer<T, Cleanup>::operator[](qsizetype i)
Provides access to entry \a i of the scoped pointer's array of
objects.
If the contained pointer is \nullptr, behavior is undefined.
+ \note In Qt versions prior to 6.5, \a i was of type \c{int}, not
+ \c{qsizetype}, possibly causing truncation on 64-bit platforms.
+
\sa isNull()
*/
/*!
- \fn template <typename T, typename Cleanup> T *QScopedArrayPointer<T, Cleanup>::operator[](int i) const
+ \fn template <typename T, typename Cleanup> T *QScopedArrayPointer<T, Cleanup>::operator[](qsizetype i) const
Provides access to entry \a i of the scoped pointer's array of
objects.
If the contained pointer is \nullptr behavior is undefined.
+ \note In Qt versions prior to 6.5, \a i was of type \c{int}, not
+ \c{qsizetype}, possibly causing truncation on 64-bit platforms.
+
\sa isNull()
*/
/*! \fn template <typename T, typename Cleanup> void QScopedArrayPointer<T, Cleanup>::swap(QScopedArrayPointer<T, Cleanup> &other)
- Swap this pointer with \a other.
+
+ \deprecated [6.1] Use \c std::unique_ptr instead; this function may let a pointer
+ escape its scope.
+
+ Swap this pointer with \a other.
*/
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
index af0c0ed336..59bae9b967 100644
--- a/src/corelib/tools/qscopedpointer.h
+++ b/src/corelib/tools/qscopedpointer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCOPEDPOINTER_H
#define QSCOPEDPOINTER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
template <typename T>
struct QScopedPointerDeleter
{
- static inline void cleanup(T *pointer)
+ static inline void cleanup(T *pointer) noexcept
{
// Enforce a complete type.
// If you get a compile error here, read the section on forward declared
@@ -59,12 +23,16 @@ struct QScopedPointerDeleter
delete pointer;
}
+ void operator()(T *pointer) const noexcept
+ {
+ cleanup(pointer);
+ }
};
template <typename T>
struct QScopedPointerArrayDeleter
{
- static inline void cleanup(T *pointer)
+ static inline void cleanup(T *pointer) noexcept
{
// Enforce a complete type.
// If you get a compile error here, read the section on forward declared
@@ -72,13 +40,18 @@ struct QScopedPointerArrayDeleter
typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];
(void) sizeof(IsIncompleteType);
- delete [] pointer;
+ delete[] pointer;
+ }
+ void operator()(T *pointer) const noexcept
+ {
+ cleanup(pointer);
}
};
struct QScopedPointerPodDeleter
{
- static inline void cleanup(void *pointer) { if (pointer) free(pointer); }
+ static inline void cleanup(void *pointer) noexcept { free(pointer); }
+ void operator()(void *pointer) const noexcept { cleanup(pointer); }
};
#ifndef QT_NO_QOBJECT
@@ -86,6 +59,7 @@ template <typename T>
struct QScopedPointerObjectDeleteLater
{
static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); }
+ void operator()(T *pointer) const { cleanup(pointer); }
};
class QObject;
@@ -95,8 +69,8 @@ typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater;
template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer
{
- typedef T *QScopedPointer:: *RestrictedBool;
public:
+ Q_NODISCARD_CTOR
explicit QScopedPointer(T *p = nullptr) noexcept : d(p)
{
}
@@ -123,17 +97,10 @@ public:
return !d;
}
-#if defined(Q_QDOC)
- inline operator bool() const
- {
- return isNull() ? nullptr : &QScopedPointer::d;
- }
-#else
- operator RestrictedBool() const noexcept
+ explicit operator bool() const
{
- return isNull() ? nullptr : &QScopedPointer::d;
+ return !isNull();
}
-#endif
T *data() const noexcept
{
@@ -154,71 +121,71 @@ public:
{
if (d == other)
return;
- T *oldD = d;
- d = other;
+ T *oldD = std::exchange(d, other);
Cleanup::cleanup(oldD);
}
+#if QT_DEPRECATED_SINCE(6, 1)
+ QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().")
T *take() noexcept
{
- T *oldD = d;
- d = nullptr;
+ T *oldD = std::exchange(d, nullptr);
return oldD;
}
+#endif
+#if QT_DEPRECATED_SINCE(6, 2)
+ QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.")
void swap(QScopedPointer<T, Cleanup> &other) noexcept
{
- qSwap(d, other.d);
+ qt_ptr_swap(d, other.d);
}
+#endif
typedef T *pointer;
-protected:
- T *d;
+ friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return lhs.data() == rhs.data();
+ }
-private:
- Q_DISABLE_COPY(QScopedPointer)
-};
+ friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return lhs.data() != rhs.data();
+ }
-template <class T, class Cleanup>
-inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return lhs.data() == rhs.data();
-}
+ friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
+ {
+ return lhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return lhs.data() != rhs.data();
-}
+ friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return rhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
-{
- return lhs.isNull();
-}
+ friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
+ {
+ return !lhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return rhs.isNull();
-}
+ friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
+ {
+ return !rhs.isNull();
+ }
-template <class T, class Cleanup>
-inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
-{
- return !lhs.isNull();
-}
+#if QT_DEPRECATED_SINCE(6, 2)
+ QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.")
+ friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept
+ { p1.swap(p2); }
+#endif
-template <class T, class Cleanup>
-inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
-{
- return !rhs.isNull();
-}
+protected:
+ T *d;
-template <class T, class Cleanup>
-inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept
-{ p1.swap(p2); }
+private:
+ Q_DISABLE_COPY_MOVE(QScopedPointer)
+};
template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
class QScopedArrayPointer : public QScopedPointer<T, Cleanup>
@@ -226,29 +193,36 @@ class QScopedArrayPointer : public QScopedPointer<T, Cleanup>
template <typename Ptr>
using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type;
public:
+ Q_NODISCARD_CTOR
inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {}
+ inline ~QScopedArrayPointer() = default;
template <typename D, if_same_type<D> = true>
+ Q_NODISCARD_CTOR
explicit QScopedArrayPointer(D *p)
: QScopedPointer<T, Cleanup>(p)
{
}
- inline T &operator[](int i)
+ T &operator[](qsizetype i)
{
return this->d[i];
}
- inline const T &operator[](int i) const
+ const T &operator[](qsizetype i) const
{
return this->d[i];
}
+#if QT_DEPRECATED_SINCE(6, 2)
+ QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.")
void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps
{ QScopedPointer<T, Cleanup>::swap(other); }
+#endif
private:
- explicit inline QScopedArrayPointer(void *) {
+ explicit inline QScopedArrayPointer(void *)
+ {
// Enforce the same type.
// If you get a compile error here, make sure you declare
@@ -259,12 +233,15 @@ private:
// allowed and results in undefined behavior.
}
- Q_DISABLE_COPY(QScopedArrayPointer)
+ Q_DISABLE_COPY_MOVE(QScopedArrayPointer)
};
+#if QT_DEPRECATED_SINCE(6, 2)
template <typename T, typename Cleanup>
+QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.")
inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept
{ lhs.swap(rhs); }
+#endif
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedpointer_p.h b/src/corelib/tools/qscopedpointer_p.h
deleted file mode 100644
index c1c44e7695..0000000000
--- a/src/corelib/tools/qscopedpointer_p.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of internal files. This header file may change from version to version
-// without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-
-#ifndef QSCOPEDPOINTER_P_H
-#define QSCOPEDPOINTER_P_H
-
-#include "QtCore/qscopedpointer.h"
-
-QT_BEGIN_NAMESPACE
-
-
-/* Internal helper class - exposes the data through data_ptr (legacy from QShared).
- Required for some internal Qt classes, do not use otherwise. */
-template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
-class QCustomScopedPointer : public QScopedPointer<T, Cleanup>
-{
-public:
- explicit inline QCustomScopedPointer(T *p = 0)
- : QScopedPointer<T, Cleanup>(p)
- {
- }
-
- inline T *&data_ptr()
- {
- return this->d;
- }
-
- inline bool operator==(const QCustomScopedPointer<T, Cleanup> &other) const
- {
- return this->d == other.d;
- }
-
- inline bool operator!=(const QCustomScopedPointer<T, Cleanup> &other) const
- {
- return this->d != other.d;
- }
-
-private:
- Q_DISABLE_COPY(QCustomScopedPointer)
-};
-
-/* Internal helper class - a handler for QShared* classes, to be used in QCustomScopedPointer */
-template <typename T>
-class QScopedPointerSharedDeleter
-{
-public:
- static inline void cleanup(T *d)
- {
- if (d && !d->ref.deref())
- delete d;
- }
-};
-
-/* Internal.
- This class is basically a scoped pointer pointing to a ref-counted object
- */
-template <typename T>
-class QScopedSharedPointer : public QCustomScopedPointer<T, QScopedPointerSharedDeleter<T> >
-{
-public:
- explicit inline QScopedSharedPointer(T *p = 0)
- : QCustomScopedPointer<T, QScopedPointerSharedDeleter<T> >(p)
- {
- }
-
- inline void detach()
- {
- qAtomicDetach(this->d);
- }
-
- inline void assign(T *other)
- {
- if (this->d == other)
- return;
- if (other)
- other->ref.ref();
- T *oldD = this->d;
- this->d = other;
- QScopedPointerSharedDeleter<T>::cleanup(oldD);
- }
-
- inline bool operator==(const QScopedSharedPointer<T> &other) const
- {
- return this->d == other.d;
- }
-
- inline bool operator!=(const QScopedSharedPointer<T> &other) const
- {
- return this->d != other.d;
- }
-
-private:
- Q_DISABLE_COPY(QScopedSharedPointer)
-};
-
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp
index baca7c8229..ce3c845cc3 100644
--- a/src/corelib/tools/qscopedvaluerollback.cpp
+++ b/src/corelib/tools/qscopedvaluerollback.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qscopedvaluerollback.h"
@@ -58,7 +22,7 @@ QT_BEGIN_NAMESPACE
The template can only be instantiated with a type that supports assignment.
- \sa QScopedPointer
+ \sa QScopedPointer, QScopeGuard
*/
/*!
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
index b8ceff6665..0ae3efd0c0 100644
--- a/src/corelib/tools/qscopedvaluerollback.h
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCOPEDVALUEROLLBACK_H
#define QSCOPEDVALUEROLLBACK_H
@@ -45,30 +9,31 @@
QT_BEGIN_NAMESPACE
template <typename T>
-class
-#if QT_HAS_CPP_ATTRIBUTE(nodiscard) && __cplusplus >= 201703L
-[[nodiscard]]
-#endif
-QScopedValueRollback
+class QScopedValueRollback
{
public:
- explicit QScopedValueRollback(T &var)
+ Q_NODISCARD_CTOR
+ explicit constexpr QScopedValueRollback(T &var)
: varRef(var), oldValue(var)
{
}
- explicit QScopedValueRollback(T &var, T value)
- : varRef(var), oldValue(std::move(var))
+ Q_NODISCARD_CTOR
+ explicit constexpr QScopedValueRollback(T &var, T value)
+ : varRef(var), oldValue(std::move(var)) // ### C++20: std::exchange(var, std::move(value))
{
- varRef = std::move(value);
+ var = std::move(value);
}
+#if __cpp_constexpr >= 201907L
+ constexpr
+#endif
~QScopedValueRollback()
{
varRef = std::move(oldValue);
}
- void commit()
+ constexpr void commit()
{
oldValue = varRef;
}
@@ -77,7 +42,7 @@ private:
T &varRef;
T oldValue;
- Q_DISABLE_COPY(QScopedValueRollback)
+ Q_DISABLE_COPY_MOVE(QScopedValueRollback)
};
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h
index d288fd63fc..9be6634cc8 100644
--- a/src/corelib/tools/qscopeguard.h
+++ b/src/corelib/tools/qscopeguard.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCOPEGUARD_H
#define QSCOPEGUARD_H
@@ -49,28 +13,25 @@
QT_BEGIN_NAMESPACE
template <typename F>
-class
-#if __has_cpp_attribute(nodiscard)
-// Q_REQUIRED_RESULT can be defined as __warn_unused_result__ or as [[nodiscard]]
-// but the 1st one has some limitations for example can be placed only on functions.
-Q_REQUIRED_RESULT
-#endif
-QScopeGuard
+class QScopeGuard
{
public:
+ Q_NODISCARD_CTOR
explicit QScopeGuard(F &&f) noexcept
: m_func(std::move(f))
{
}
+ Q_NODISCARD_CTOR
explicit QScopeGuard(const F &f) noexcept
: m_func(f)
{
}
+ Q_NODISCARD_CTOR
QScopeGuard(QScopeGuard &&other) noexcept
: m_func(std::move(other.m_func))
- , m_invoke(qExchange(other.m_invoke, false))
+ , m_invoke(std::exchange(other.m_invoke, false))
{
}
@@ -92,16 +53,11 @@ private:
bool m_invoke = true;
};
-#ifdef __cpp_deduction_guides
template <typename F> QScopeGuard(F(&)()) -> QScopeGuard<F(*)()>;
-#endif
//! [qScopeGuard]
template <typename F>
-#if __has_cpp_attribute(nodiscard)
-Q_REQUIRED_RESULT
-#endif
-QScopeGuard<typename std::decay<F>::type> qScopeGuard(F &&f)
+[[nodiscard]] QScopeGuard<typename std::decay<F>::type> qScopeGuard(F &&f)
{
return QScopeGuard<typename std::decay<F>::type>(std::forward<F>(f));
}
diff --git a/src/corelib/tools/qscopeguard.qdoc b/src/corelib/tools/qscopeguard.qdoc
index b36299d296..6d9874842a 100644
--- a/src/corelib/tools/qscopeguard.qdoc
+++ b/src/corelib/tools/qscopeguard.qdoc
@@ -1,30 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
#include "qscopeguard.h"
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index f078e62999..7330b5e91c 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSET_H
#define QSET_H
@@ -71,17 +35,24 @@ public:
inline void swap(QSet<T> &other) noexcept { q_hash.swap(other.q_hash); }
- inline bool operator==(const QSet<T> &other) const
- { return q_hash == other.q_hash; }
- inline bool operator!=(const QSet<T> &other) const
- { return q_hash != other.q_hash; }
+#ifndef Q_QDOC
+ template <typename U = T>
+ QTypeTraits::compare_eq_result_container<QSet, U> operator==(const QSet<T> &other) const
+ { return q_hash == other.q_hash; }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result_container<QSet, U> operator!=(const QSet<T> &other) const
+ { return q_hash != other.q_hash; }
+#else
+ bool operator==(const QSet &other) const;
+ bool operator!=(const QSet &other) const;
+#endif
- inline int size() const { return q_hash.size(); }
+ inline qsizetype size() const { return q_hash.size(); }
inline bool isEmpty() const { return q_hash.isEmpty(); }
- inline int capacity() const { return q_hash.capacity(); }
- inline void reserve(int size);
+ inline qsizetype capacity() const { return q_hash.capacity(); }
+ inline void reserve(qsizetype size);
inline void squeeze() { q_hash.squeeze(); }
inline void detach() { q_hash.detach(); }
@@ -91,6 +62,12 @@ public:
inline bool remove(const T &value) { return q_hash.remove(value) != 0; }
+ template <typename Pred>
+ inline qsizetype removeIf(Pred predicate)
+ {
+ return QtPrivate::qset_erase_if(*this, predicate);
+ }
+
inline bool contains(const T &value) const { return q_hash.contains(value); }
bool contains(const QSet<T> &set) const;
@@ -174,9 +151,11 @@ public:
// more Qt
typedef iterator Iterator;
typedef const_iterator ConstIterator;
- inline int count() const { return q_hash.count(); }
+ inline qsizetype count() const { return q_hash.size(); }
inline iterator insert(const T &value)
- { return static_cast<typename Hash::iterator>(q_hash.insert(value, QHashDummyValue())); }
+ { return q_hash.insert(value, QHashDummyValue()); }
+ inline iterator insert(T &&value)
+ { return q_hash.emplace(std::move(value), QHashDummyValue()); }
iterator find(const T &value) { return q_hash.find(value); }
const_iterator find(const T &value) const { return q_hash.find(value); }
inline const_iterator constFind(const T &value) const { return find(value); }
@@ -193,9 +172,12 @@ public:
typedef value_type &reference;
typedef const value_type &const_reference;
typedef qptrdiff difference_type;
- typedef int size_type;
+ typedef qsizetype size_type;
inline bool empty() const { return isEmpty(); }
+
+ iterator insert(const_iterator, const T &value) { return insert(value); }
+
// comfort
inline QSet<T> &operator<<(const T &value) { insert(value); return *this; }
inline QSet<T> &operator|=(const QSet<T> &other) { unite(other); return *this; }
@@ -207,14 +189,18 @@ public:
inline QSet<T> &operator+=(const T &value) { insert(value); return *this; }
inline QSet<T> &operator-=(const QSet<T> &other) { subtract(other); return *this; }
inline QSet<T> &operator-=(const T &value) { remove(value); return *this; }
- inline QSet<T> operator|(const QSet<T> &other) const
- { QSet<T> result = *this; result |= other; return result; }
- inline QSet<T> operator&(const QSet<T> &other) const
- { QSet<T> result = *this; result &= other; return result; }
- inline QSet<T> operator+(const QSet<T> &other) const
- { QSet<T> result = *this; result += other; return result; }
- inline QSet<T> operator-(const QSet<T> &other) const
- { QSet<T> result = *this; result -= other; return result; }
+
+ friend QSet operator|(const QSet &lhs, const QSet &rhs) { return QSet(lhs) |= rhs; }
+ friend QSet operator|(QSet &&lhs, const QSet &rhs) { lhs |= rhs; return std::move(lhs); }
+
+ friend QSet operator&(const QSet &lhs, const QSet &rhs) { return QSet(lhs) &= rhs; }
+ friend QSet operator&(QSet &&lhs, const QSet &rhs) { lhs &= rhs; return std::move(lhs); }
+
+ friend QSet operator+(const QSet &lhs, const QSet &rhs) { return QSet(lhs) += rhs; }
+ friend QSet operator+(QSet &&lhs, const QSet &rhs) { lhs += rhs; return std::move(lhs); }
+
+ friend QSet operator-(const QSet &lhs, const QSet &rhs) { return QSet(lhs) -= rhs; }
+ friend QSet operator-(QSet &&lhs, const QSet &rhs) { lhs -= rhs; return std::move(lhs); }
QList<T> values() const;
@@ -222,12 +208,10 @@ private:
Hash q_hash;
};
-#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
template <typename InputIterator,
typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
QtPrivate::IfIsInputIterator<InputIterator> = true>
QSet(InputIterator, InputIterator) -> QSet<ValueType>;
-#endif
template <typename T>
size_t qHash(const QSet<T> &key, size_t seed = 0)
@@ -239,15 +223,18 @@ noexcept(noexcept(qHashRangeCommutative(key.begin(), key.end(), seed)))
// inline function implementations
template <class T>
-Q_INLINE_TEMPLATE void QSet<T>::reserve(int asize) { q_hash.reserve(asize); }
+Q_INLINE_TEMPLATE void QSet<T>::reserve(qsizetype asize) { q_hash.reserve(asize); }
template <class T>
Q_INLINE_TEMPLATE QSet<T> &QSet<T>::unite(const QSet<T> &other)
{
- if (!q_hash.isSharedWith(other.q_hash)) {
- for (const T &e : other)
- insert(e);
- }
+ if (q_hash.isSharedWith(other.q_hash))
+ return *this;
+ QSet<T> tmp = other;
+ if (size() < other.size())
+ swap(tmp);
+ for (const auto &e : std::as_const(tmp))
+ insert(e);
return *this;
}
@@ -264,7 +251,7 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other)
copy2 = *this;
*this = copy1;
}
- for (const auto &e : qAsConst(copy1)) {
+ for (const auto &e : std::as_const(copy1)) {
if (!copy2.contains(e))
remove(e);
}
@@ -356,6 +343,12 @@ public:
};
#endif // QT_NO_JAVA_STYLE_ITERATORS
+template <typename T, typename Predicate>
+qsizetype erase_if(QSet<T> &set, Predicate pred)
+{
+ return QtPrivate::qset_erase_if(set, pred);
+}
+
QT_END_NAMESPACE
#endif // QSET_H
diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc
index eb6b542181..4ef7a80a52 100644
--- a/src/corelib/tools/qset.qdoc
+++ b/src/corelib/tools/qset.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QSet
@@ -47,7 +23,7 @@
\snippet code/doc_src_qset.cpp 1
- Another way to insert items into the set is to use operator<<():
+ Another way to insert items into the set is to use \l operator<<():
\snippet code/doc_src_qset.cpp 2
@@ -70,7 +46,7 @@
QSet is unordered, so an iterator's sequence cannot be assumed to
be predictable. If ordering by key is required, use a QMap.
- To navigate through a QSet, you can also use \l{foreach}:
+ To navigate through a QSet, you can also use range-based for:
\snippet code/doc_src_qset.cpp 6
@@ -110,7 +86,7 @@
initializer list \a list.
*/
-/*! \fn template <class T> template<typename InputIterator> QSet<T>::QSet(InputIterator first, InputIterator last)
+/*! \fn template <class T> template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true> QSet<T>::QSet(InputIterator first, InputIterator last)
\since 5.14
Constructs a set with the contents in the iterator range [\a first, \a last).
@@ -185,7 +161,7 @@
\sa reserve(), squeeze()
*/
-/*! \fn template <class T> void QSet<T>::reserve(int size)
+/*! \fn template <class T> void QSet<T>::reserve(qsizetype size)
Ensures that the set's internal hash table consists of at
least \a size buckets.
@@ -275,13 +251,12 @@
internal data structure. This means that it can safely be called
while iterating, and won't affect the order of items in the set.
- \sa remove(), find()
-*/
+ \note The iterator \a pos \e must be valid and dereferenceable. Calling this
+ method on any other iterator, including its own \l end(), results in
+ undefined behavior. In particular, even the \l begin() iterator of an empty
+ set cannot be dereferenced.
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::erase(iterator pos)
- \since 4.2
- \overload
+ \sa remove(), find()
*/
/*! \fn template <class T> QSet<T>::const_iterator QSet<T>::find(const T &value) const
@@ -398,58 +373,6 @@
\sa constBegin(), end()
*/
-/*! \fn template <class T> QSet<T>::reverse_iterator QSet<T>::rbegin()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the set, in reverse order.
-
- \sa begin(), crbegin(), rend()
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::rbegin() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
- \overload
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::crbegin() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
- item in the set, in reverse order.
-
- \sa begin(), rbegin(), rend()
-*/
-
-/*! \fn template <class T> QSet<T>::reverse_iterator QSet<T>::rend()
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
- the last item in the set, in reverse order.
-
- \sa end(), crend(), rbegin()
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::rend() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
- \overload
-*/
-
-/*! \fn template <class T> QSet<T>::const_reverse_iterator QSet<T>::crend() const
- \obsolete Deprecated in order to align with std::unordered_set functionality.
- \since 5.6
-
- Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one
- past the last item in the set, in reverse order.
-
- \sa end(), rend(), rbegin()
-*/
-
/*!
\typedef QSet::Iterator
\since 4.2
@@ -511,42 +434,8 @@
Typedef for T. Provided for STL compatibility.
*/
-/*! \typedef QSet::reverse_iterator
- \since 5.6
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- The QSet::reverse_iterator typedef provides an STL-style non-const
- reverse iterator for QSet.
-
- It is simply a typedef for \c{std::reverse_iterator<QSet::iterator>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QSet::rbegin(), QSet::rend(), QSet::const_reverse_iterator, QSet::iterator
-*/
-
-/*! \typedef QSet::const_reverse_iterator
- \since 5.6
- \obsolete Deprecated in order to align with std::unordered_set functionality.
-
- The QSet::const_reverse_iterator typedef provides an STL-style const
- reverse iterator for QSet.
-
- It is simply a typedef for \c{std::reverse_iterator<QSet::const_iterator>}.
-
- \warning Iterators on implicitly shared containers do not work
- exactly like STL-iterators. You should avoid copying a container
- while iterators are active on that container. For more information,
- read \l{Implicit sharing iterator problem}.
-
- \sa QSet::rbegin(), QSet::rend(), QSet::reverse_iterator, QSet::const_iterator
-*/
-
/*!
- \fn template <class T> QSet<T>::insert(const T &value)
+ \fn template <class T> QSet<T>::iterator QSet<T>::insert(const T &value)
Inserts item \a value into the set, if \a value isn't already
in the set, and returns an iterator pointing at the inserted
@@ -600,6 +489,22 @@
*/
/*!
+ \fn template <class T> QSet<T>::iterator QSet<T>::insert(const_iterator it, const T &value)
+ \overload
+ \since 6.1
+
+ Inserts item \a value into the set, if \a value isn't already
+ in the set, and returns an iterator pointing at the inserted
+ item.
+
+ The iterator \a it is ignored.
+
+ This function is provided for compatibility with the STL.
+
+ \sa operator<<(), remove(), contains()
+*/
+
+/*!
\fn template <class T> bool QSet<T>::count() const
Same as size().
@@ -630,7 +535,7 @@
\fn template <class T> QSet<T> &QSet<T>::operator|=(const QSet<T> &other)
\fn template <class T> QSet<T> &QSet<T>::operator+=(const QSet<T> &other)
- Same as unite(\a other).
+ Same as \l {unite()} {unite(\a other)}.
\sa operator|(), operator&=(), operator-=()
*/
@@ -638,7 +543,7 @@
/*!
\fn template <class T> QSet<T> &QSet<T>::operator&=(const QSet<T> &other)
- Same as intersect(\a other).
+ Same as \l {intersect()} {intersect(\a other)}.
\sa operator&(), operator|=(), operator-=()
*/
@@ -648,7 +553,7 @@
\overload
- Same as intersect(\e{other}), if we consider \e{other} to be a set
+ Same as \l {intersect()} {intersect(\e{other})}, if we consider \e other to be a set
that contains the singleton \a value.
*/
@@ -656,35 +561,36 @@
/*!
\fn template <class T> QSet<T> &QSet<T>::operator-=(const QSet<T> &other)
- Same as subtract(\a{other}).
+ Same as \l {subtract()} {subtract(\a{other})}.
\sa operator-(), operator|=(), operator&=()
*/
/*!
- \fn template <class T> QSet<T> QSet<T>::operator|(const QSet<T> &other) const
- \fn template <class T> QSet<T> QSet<T>::operator+(const QSet<T> &other) const
+ \fn template <class T> QSet<T> QSet<T>::operator|(const QSet &lhs, const QSet &rhs)
+ \fn template <class T> QSet<T> QSet<T>::operator|(QSet &&lhs, const QSet &rhs)
+ \fn template <class T> QSet<T> QSet<T>::operator+(const QSet &lhs, const QSet &rhs)
+ \fn template <class T> QSet<T> QSet<T>::operator+(QSet &&lhs, const QSet &rhs)
- Returns a new QSet that is the union of this set and the
- \a other set.
+ Returns a new QSet that is the union of sets \a lhs and \a rhs.
\sa unite(), operator|=(), operator&(), operator-()
*/
/*!
- \fn template <class T> QSet<T> QSet<T>::operator&(const QSet<T> &other) const
+ \fn template <class T> QSet<T> QSet<T>::operator&(const QSet &lhs, const QSet &rhs)
+ \fn template <class T> QSet<T> QSet<T>::operator&(QSet &&lhs, const QSet &rhs)
- Returns a new QSet that is the intersection of this set and the
- \a other set.
+ Returns a new QSet that is the intersection of sets \a lhs and \a rhs.
\sa intersect(), operator&=(), operator|(), operator-()
*/
/*!
- \fn template <class T> QSet<T> QSet<T>::operator-(const QSet<T> &other) const
+ \fn template <class T> QSet<T> QSet<T>::operator-(const QSet &lhs, const QSet &rhs)
+ \fn template <class T> QSet<T> QSet<T>::operator-(QSet &&lhs, const QSet &rhs)
- Returns a new QSet that is the set difference of this set and
- the \a other set, i.e., this set - \a other set.
+ Returns a new QSet that is the set difference of sets \a lhs and \a rhs.
\sa subtract(), operator-=(), operator|(), operator&()
*/
@@ -927,192 +833,19 @@
current item.
*/
-/*!
- \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator--()
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QSet::begin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator--()
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QSet::begin() leads to undefined
- results.
-
- \sa operator++()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator--(int)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator--(int)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator+(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator+(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions forward from
- this iterator. (If \a j is negative, the iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator QSet<T>::iterator::operator-(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator QSet<T>::const_iterator::operator-(int j) const
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Returns an iterator to the item at \a j positions backward from
- this iterator. (If \a j is negative, the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator+=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-=(), operator+()
-
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator+=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Advances the iterator by \a j items. (If \a j is negative, the
- iterator goes backward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator-=(), operator+()
-*/
-
-/*!
- \fn template <class T> QSet<T>::iterator &QSet<T>::iterator::operator-=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+=(), operator-()
-*/
-
-/*!
- \fn template <class T> QSet<T>::const_iterator &QSet<T>::const_iterator::operator-=(int j)
- \obsolete This operator is deprecated in order to align with std::unordered_set functionality.
-
- Makes the iterator go back by \a j items. (If \a j is negative,
- the iterator goes forward.)
-
- This operation can be slow for large \a j values.
-
- \sa operator+=(), operator-()
-*/
-
-/*! \fn template <class T> QList<T> QSet<T>::toList() const
-
- Returns a new QList containing the elements in the set. The
- order of the elements in the QList is undefined.
-
- Example:
-
- \snippet code/doc_src_qset.cpp 13
-
- \include containers-range-constructor.qdocinc
-
- \sa fromList(), QList::fromSet()
-*/
-
/*! \fn template <class T> QList<T> QSet<T>::values() const
Returns a new QList containing the elements in the set. The
order of the elements in the QList is undefined.
- This is the same as toList().
-
\include containers-range-constructor.qdocinc
- \sa fromList(), QList::fromSet()
+ This function creates a new list, in \l {linear time}. The time and memory
+ use that entails can be avoided by iterating from \l constBegin() to
+ \l constEnd().
*/
-/*! \fn template <class T> QSet<T> QSet<T>::fromList(const QList<T> &list)
-
- Returns a new QSet object containing the data contained in \a
- list. Since QSet doesn't allow duplicates, the resulting QSet
- might be smaller than the \a list, because QList can contain
- duplicates.
-
- Example:
-
- \snippet code/doc_src_qset.cpp 14
-
- \include containers-range-constructor.qdocinc
-
- \sa toList(), QList::toSet()
-*/
-
/*!
\fn template <class T> QDataStream &operator<<(QDataStream &out, const QSet<T> &set)
\relates QSet
@@ -1145,3 +878,19 @@
The hash value is independent of the order of elements in \a key, that is, sets
that contain the same elements hash to the same value.
*/
+
+/*! \fn template <class T, class Predicate> qsizetype erase_if(QSet<T> &set, Predicate pred)
+ \relates QSet
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the set \a set. Returns the number of elements removed, if
+ any.
+*/
+
+/*! \fn template <class T> template <class Pred> qsizetype QSet<T>::removeIf(Pred pred)
+ \since 6.1
+
+ Removes, from this set, all elements for which the predicate \a pred
+ returns \c true. Returns the number of elements removed, if any.
+*/
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index 187bfa7a5d..8ef174ebfc 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qshareddata.h>
@@ -65,6 +29,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \class QAdoptSharedDataTag
+ \inmodule QtCore
+ \threadsafe
+ \brief The QAdoptSharedDataTag is a helper tag class.
+ \since 6.0
+
+ QAdoptSharedDataTag objects are used in QSharedDataPointer
+ and QExplicitlySharedDataPointer to adopt a pointer to
+ shared data.
+
+ See QSharedDataPointer and QExplicitlySharedDataPointer for details.
+*/
+
+/*!
\class QSharedDataPointer
\inmodule QtCore
\brief The QSharedDataPointer class represents a pointer to an implicitly shared object.
@@ -302,6 +280,18 @@ QT_BEGIN_NAMESPACE
Same as data(). This function is provided for STL compatibility.
*/
+/*! \fn template <class T> const T* QSharedDataPointer<T>::take()
+ \since 6.0
+
+ Returns a pointer to the shared object, and resets \e this to be \nullptr.
+ (That is, this function sets the \e{d pointer} of \e this to \nullptr.)
+
+ \note The reference count of the returned object will \b{not} be
+ decremented. This function can be used together with the
+ constructor that takes a QAdoptSharedDataTag tag object to transfer
+ the shared data object without intervening atomic operations.
+*/
+
/*! \fn template <class T> const T* QSharedDataPointer<T>::constData() const
Returns a const pointer to the shared data object.
This function does \e not call detach().
@@ -309,6 +299,15 @@ QT_BEGIN_NAMESPACE
\sa data()
*/
+/*! \fn template <class T> void QSharedDataPointer<T>::reset(T *ptr = nullptr)
+ \since 6.0
+
+ Sets the \e{d pointer} of \e this to \a ptr and increments \a{ptr}'s reference
+ count if \a ptr is not \nullptr.
+ The reference count of the old shared data object is decremented,
+ and the object deleted if the reference count reaches 0.
+ */
+
/*! \fn template <class T> void QSharedDataPointer<T>::swap(QSharedDataPointer &other)
Swap this instance's shared data pointer with the shared
data pointer in \a other.
@@ -322,13 +321,23 @@ QT_BEGIN_NAMESPACE
\since 5.2
*/
-/*! \fn template <class T> bool QSharedDataPointer<T>::operator==(const QSharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this have the same \e{d pointer}.
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator==(const QSharedDataPointer<T>& lhs, const QSharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs have the same \e{d pointer}.
+ This function does \e not call detach().
+*/
+
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator!=(const QSharedDataPointer<T>& lhs, const QSharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs do \e not have the same
+ \e{d pointer}. This function does \e not call detach().
+*/
+
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator==(const T *ptr, const QSharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \a ptr.
This function does \e not call detach().
*/
-/*! \fn template <class T> bool QSharedDataPointer<T>::operator!=(const QSharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this do \e not have the same
+/*! \fn template <class T> bool QSharedDataPointer<T>::operator!=(const T *ptr, const QSharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \e not \a ptr.
\e{d pointer}. This function does \e not call detach().
*/
@@ -356,6 +365,15 @@ QT_BEGIN_NAMESPACE
\a data and increments \a{data}'s reference count.
*/
+/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer(T* data, QAdoptSharedDataTag)
+ \since 6.0
+ Constructs a QSharedDataPointer with \e{d pointer} set to
+ \a data. \a data's reference counter is \b{not} incremented;
+ this can be used to adopt pointers obtained from take().
+
+ \sa take()
+*/
+
/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer(const QSharedDataPointer<T>& o)
Sets the \e{d pointer} of \e this to the \e{d pointer} in
\a o and increments the reference count of the shared
@@ -486,8 +504,8 @@ QT_BEGIN_NAMESPACE
the explicitly shared data pointer in \a other.
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const QExplicitlySharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this have the same \e{d pointer}.
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const QExplicitlySharedDataPointer<T>& lhs, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs have the same \e{d pointer}.
*/
/*!
@@ -498,17 +516,17 @@ QT_BEGIN_NAMESPACE
\since 5.2
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const T* ptr) const
- Returns \c true if the \e{d pointer} of \e this is \a ptr.
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator==(const T* ptr, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \a ptr.
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const QExplicitlySharedDataPointer<T>& other) const
- Returns \c true if \a other and \e this do \e not have the same
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const QExplicitlySharedDataPointer<T>& lhs, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if \a lhs and \a rhs do \e not have the same
\e{d pointer}.
*/
-/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const T* ptr) const
- Returns \c true if the \e{d pointer} of \e this is \e not \a ptr.
+/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!=(const T* ptr, const QExplicitlySharedDataPointer<T>& rhs)
+ Returns \c true if the \e{d pointer} of \a rhs is \e not \a ptr.
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer()
@@ -590,18 +608,25 @@ QT_BEGIN_NAMESPACE
0, the old shared data object is deleted.
*/
-/*! \fn template <class T> void QExplicitlySharedDataPointer<T>::reset()
- Resets \e this to be null - i.e., this function sets the
- \e{d pointer} of \e this to \nullptr, but first it decrements
- the reference count of the shared data object and deletes
- the shared data object if the reference count became 0.
+/*! \fn template <class T> void QExplicitlySharedDataPointer<T>::reset(T *ptr = nullptr)
+ \since 6.0
+
+ Sets the \e{d pointer} of \e this to \a ptr and increments \a{ptr}'s reference
+ count if \a ptr is not \nullptr.
+ The reference count of the old shared data object is decremented,
+ and the object deleted if the reference count reaches 0.
*/
/*! \fn template <class T> T *QExplicitlySharedDataPointer<T>::take()
\since 5.12
Returns a pointer to the shared object, and resets \e this to be \nullptr.
- That is, this function sets the \e{d pointer} of \e this to \nullptr.
+ (That is, this function sets the \e{d pointer} of \e this to \nullptr.)
+
+ \note The reference count of the returned object will \b{not} be
+ decremented. This function can be used together with the
+ constructor that takes a QAdoptSharedDataTag tag object to transfer
+ the shared data object without intervening atomic operations.
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::operator bool () const
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 38b6d61efa..4c4153a506 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -1,135 +1,120 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHAREDDATA_H
#define QSHAREDDATA_H
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
-#if QT_DEPRECATED_SINCE(5, 6)
-#include <QtCore/qhash.h>
-#endif
#include <QtCore/qhashfunctions.h>
+#include <functional>
+
QT_BEGIN_NAMESPACE
template <class T> class QSharedDataPointer;
-class
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-Q_CORE_EXPORT
-#endif
-QSharedData
+class QSharedData
{
public:
mutable QAtomicInt ref;
- inline QSharedData() noexcept : ref(0) { }
- inline QSharedData(const QSharedData &) noexcept : ref(0) { }
+ QSharedData() noexcept : ref(0) { }
+ QSharedData(const QSharedData &) noexcept : ref(0) { }
// using the assignment operator would lead to corruption in the ref-counting
QSharedData &operator=(const QSharedData &) = delete;
~QSharedData() = default;
};
-template <class T> class QSharedDataPointer
+struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
+
+template <typename T>
+class QSharedDataPointer
{
public:
typedef T Type;
typedef T *pointer;
- inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
- inline T &operator*() { detach(); return *d; }
- inline const T &operator*() const { return *d; }
- inline T *operator->() { detach(); return d; }
- inline const T *operator->() const { return d; }
- inline operator T *() { detach(); return d; }
- inline operator const T *() const { return d; }
- inline T *data() { detach(); return d; }
- inline T *get() { detach(); return d; }
- inline const T *data() const { return d; }
- inline const T *get() const { return d; }
- inline const T *constData() const { return d; }
-
- inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; }
- inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; }
-
- inline QSharedDataPointer() { d = nullptr; }
- inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
-
- explicit QSharedDataPointer(T *data) noexcept;
- inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
- inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) {
- if (o.d != d) {
- if (o.d)
- o.d->ref.ref();
- T *old = d;
- d = o.d;
+ void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
+ T &operator*() { detach(); return *d; }
+ const T &operator*() const { return *d; }
+ T *operator->() { detach(); return d; }
+ const T *operator->() const noexcept { return d; }
+ operator T *() { detach(); return d; }
+ operator const T *() const noexcept { return d; }
+ T *data() { detach(); return d; }
+ T *get() { detach(); return d; }
+ const T *data() const noexcept { return d; }
+ const T *get() const noexcept { return d; }
+ const T *constData() const noexcept { return d; }
+ T *take() noexcept { return std::exchange(d, nullptr); }
+
+ Q_NODISCARD_CTOR
+ QSharedDataPointer() noexcept : d(nullptr) { }
+ ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+ Q_NODISCARD_CTOR
+ explicit QSharedDataPointer(T *data) noexcept : d(data)
+ { if (d) d->ref.ref(); }
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
+ {}
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(const QSharedDataPointer &o) noexcept : d(o.d)
+ { if (d) d->ref.ref(); }
+
+ void reset(T *ptr = nullptr) noexcept
+ {
+ if (ptr != d) {
+ if (ptr)
+ ptr->ref.ref();
+ T *old = std::exchange(d, ptr);
if (old && !old->ref.deref())
delete old;
}
- return *this;
}
- inline QSharedDataPointer &operator=(T *o) {
- if (o != d) {
- if (o)
- o->ref.ref();
- T *old = d;
- d = o;
- if (old && !old->ref.deref())
- delete old;
- }
+
+ QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
+ {
+ reset(o.d);
return *this;
}
- QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
- inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept
+ inline QSharedDataPointer &operator=(T *o) noexcept
{
- QSharedDataPointer moved(std::move(other));
- swap(moved);
+ reset(o);
return *this;
}
-
- inline bool operator!() const { return !d; }
-
- inline void swap(QSharedDataPointer &other) noexcept
- { qSwap(d, other.d); }
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
+
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
+
+ void swap(QSharedDataPointer &other) noexcept
+ { qt_ptr_swap(d, other.d); }
+
+#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
+ friend bool operator<(T1, T2) noexcept \
+ { return std::less<T*>{}(A1, A2); } \
+ friend bool operator<=(T1, T2) noexcept \
+ { return !std::less<T*>{}(A2, A1); } \
+ friend bool operator>(T1, T2) noexcept \
+ { return std::less<T*>{}(A2, A1); } \
+ friend bool operator>=(T1, T2) noexcept \
+ { return !std::less<T*>{}(A1, A2); } \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; } \
+
+ DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, const QSharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, const T *ptr, ptr)
+ DECLARE_COMPARE_SET(const T *ptr, ptr, const QSharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QSharedDataPointer &p1, p1.d, std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedDataPointer &p2, p2.d)
protected:
T *clone();
@@ -140,101 +125,87 @@ private:
T *d;
};
-template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2)
-{
- Q_UNUSED(p1);
- return !p2;
-}
-
-template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2)
-{
- Q_UNUSED(p2);
- return !p1;
-}
-
-template <class T> class QExplicitlySharedDataPointer
+template <typename T>
+class QExplicitlySharedDataPointer
{
public:
typedef T Type;
typedef T *pointer;
- inline T &operator*() const { return *d; }
- inline T *operator->() { return d; }
- inline T *operator->() const { return d; }
- inline T *data() const { return d; }
- inline T *get() const { return d; }
- inline const T *constData() const { return d; }
- inline T *take() { T *x = d; d = nullptr; return x; }
-
- inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
-
- inline void reset()
- {
- if(d && !d->ref.deref())
- delete d;
-
- d = nullptr;
- }
-
- inline operator bool () const { return d != nullptr; }
-
- inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; }
- inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; }
- inline bool operator==(const T *ptr) const { return d == ptr; }
- inline bool operator!=(const T *ptr) const { return d != ptr; }
-
- inline QExplicitlySharedDataPointer() { d = nullptr; }
- inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
-
- explicit QExplicitlySharedDataPointer(T *data) noexcept;
- inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
-
- template<class X>
- inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o)
+ T &operator*() const { return *d; }
+ T *operator->() noexcept { return d; }
+ T *operator->() const noexcept { return d; }
+ explicit operator T *() { return d; }
+ explicit operator const T *() const noexcept { return d; }
+ T *data() const noexcept { return d; }
+ T *get() const noexcept { return d; }
+ const T *constData() const noexcept { return d; }
+ T *take() noexcept { return std::exchange(d, nullptr); }
+
+ void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
+
+ Q_NODISCARD_CTOR
+ QExplicitlySharedDataPointer() noexcept : d(nullptr) { }
+ ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+ Q_NODISCARD_CTOR
+ explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
+ { if (d) d->ref.ref(); }
+ Q_NODISCARD_CTOR
+ QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
+ {}
+ Q_NODISCARD_CTOR
+ QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
+ { if (d) d->ref.ref(); }
+
+ template<typename X>
+ Q_NODISCARD_CTOR
+ QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) noexcept
#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
: d(static_cast<T *>(o.data()))
#else
: d(o.data())
#endif
- {
- if(d)
- d->ref.ref();
- }
+ { if (d) d->ref.ref(); }
- inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) {
- if (o.d != d) {
- if (o.d)
- o.d->ref.ref();
- T *old = d;
- d = o.d;
+ void reset(T *ptr = nullptr) noexcept
+ {
+ if (ptr != d) {
+ if (ptr)
+ ptr->ref.ref();
+ T *old = std::exchange(d, ptr);
if (old && !old->ref.deref())
delete old;
}
- return *this;
}
- inline QExplicitlySharedDataPointer &operator=(T *o) {
- if (o != d) {
- if (o)
- o->ref.ref();
- T *old = d;
- d = o;
- if (old && !old->ref.deref())
- delete old;
- }
+
+ QExplicitlySharedDataPointer &operator=(const QExplicitlySharedDataPointer &o) noexcept
+ {
+ reset(o.d);
return *this;
}
- inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
- inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept
+ QExplicitlySharedDataPointer &operator=(T *o) noexcept
{
- QExplicitlySharedDataPointer moved(std::move(other));
- swap(moved);
+ reset(o);
return *this;
}
+ Q_NODISCARD_CTOR
+ QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QExplicitlySharedDataPointer)
+
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
- inline bool operator!() const { return !d; }
+ void swap(QExplicitlySharedDataPointer &other) noexcept
+ { qt_ptr_swap(d, other.d); }
- inline void swap(QExplicitlySharedDataPointer &other) noexcept
- { qSwap(d, other.d); }
+ DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, const QExplicitlySharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, const T *ptr, ptr)
+ DECLARE_COMPARE_SET(const T *ptr, ptr, const QExplicitlySharedDataPointer &p2, p2.d)
+ DECLARE_COMPARE_SET(const QExplicitlySharedDataPointer &p1, p1.d, std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QExplicitlySharedDataPointer &p2, p2.d)
+
+#undef DECLARE_COMPARE_SET
protected:
T *clone();
@@ -245,18 +216,14 @@ private:
T *d;
};
-template <class T>
-Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) noexcept
- : d(adata)
-{ if (d) d->ref.ref(); }
-
-template <class T>
+// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
+template <typename T>
Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
{
return new T(*d);
}
-template <class T>
+template <typename T>
Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
{
T *x = clone();
@@ -266,13 +233,13 @@ Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
d = x;
}
-template <class T>
+template <typename T>
Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
{
return new T(*d);
}
-template <class T>
+template <typename T>
Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
{
T *x = clone();
@@ -282,44 +249,53 @@ Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
d = x;
}
-template <class T>
-Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) noexcept
- : d(adata)
-{ if (d) d->ref.ref(); }
-
-template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2)
-{
- Q_UNUSED(p1);
- return !p2;
-}
-
-template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2)
-{
- Q_UNUSED(p2);
- return !p1;
-}
-
-template <class T>
-Q_INLINE_TEMPLATE void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
+template <typename T>
+void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
{ p1.swap(p2); }
-template <class T>
-Q_INLINE_TEMPLATE void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
+template <typename T>
+void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) noexcept
{ p1.swap(p2); }
-template <class T>
-Q_INLINE_TEMPLATE size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
+template <typename T>
+size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
{
return qHash(ptr.data(), seed);
}
-template <class T>
-Q_INLINE_TEMPLATE size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
+template <typename T>
+size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
{
return qHash(ptr.data(), seed);
}
-template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
-template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
+template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
+template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_RELOCATABLE_TYPE);
+
+#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class) \
+ template<> QSharedDataPointer<Class>::~QSharedDataPointer();
+
+#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
+ template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
+
+#define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class) \
+ template<> QSharedDataPointer<Class>::~QSharedDataPointer() \
+ { \
+ if (d && !d->ref.deref()) \
+ delete d; \
+ }
+
+#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class) \
+ template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
+
+#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro) \
+ template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
+
+#define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class) \
+ template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer() \
+ { \
+ if (d && !d->ref.deref()) \
+ delete d; \
+ }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qshareddata_impl.h b/src/corelib/tools/qshareddata_impl.h
new file mode 100644
index 0000000000..e0b4695e36
--- /dev/null
+++ b/src/corelib/tools/qshareddata_impl.h
@@ -0,0 +1,142 @@
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#if 0
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
+#endif
+
+#ifndef QSHAREDDATA_IMPL_H
+#define QSHAREDDATA_IMPL_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+template <typename T>
+class QExplicitlySharedDataPointerV2
+{
+ T *d;
+
+public:
+ constexpr QExplicitlySharedDataPointerV2() noexcept : d(nullptr) {}
+
+ explicit QExplicitlySharedDataPointerV2(T *t) noexcept
+ : d(t)
+ {
+ if (d)
+ d->ref.ref();
+ }
+
+ QExplicitlySharedDataPointerV2(T *t, QAdoptSharedDataTag) noexcept
+ : d(t)
+ {
+ }
+
+ QExplicitlySharedDataPointerV2(const QExplicitlySharedDataPointerV2 &other) noexcept
+ : d(other.d)
+ {
+ if (d)
+ d->ref.ref();
+ }
+
+ QExplicitlySharedDataPointerV2 &operator=(const QExplicitlySharedDataPointerV2 &other) noexcept
+ {
+ QExplicitlySharedDataPointerV2 copy(other);
+ swap(copy);
+ return *this;
+ }
+
+ QExplicitlySharedDataPointerV2(QExplicitlySharedDataPointerV2 &&other) noexcept
+ : d(std::exchange(other.d, nullptr))
+ {
+ }
+
+ QExplicitlySharedDataPointerV2 &operator=(QExplicitlySharedDataPointerV2 &&other) noexcept
+ {
+ QExplicitlySharedDataPointerV2 moved(std::move(other));
+ swap(moved);
+ return *this;
+ }
+
+ ~QExplicitlySharedDataPointerV2()
+ {
+ if (d && !d->ref.deref())
+ delete d;
+ }
+
+ void detach()
+ {
+ if (!d) {
+ // should this codepath be here on in all user's detach()?
+ d = new T;
+ d->ref.ref();
+ } else if (d->ref.loadRelaxed() != 1) {
+ // TODO: qAtomicDetach here...?
+ QExplicitlySharedDataPointerV2 copy(new T(*d));
+ swap(copy);
+ }
+ }
+
+ void reset(T *t = nullptr) noexcept
+ {
+ if (d && !d->ref.deref())
+ delete d;
+ d = t;
+ if (d)
+ d->ref.ref();
+ }
+
+ constexpr T *take() noexcept
+ {
+ return std::exchange(d, nullptr);
+ }
+
+ bool isShared() const noexcept
+ {
+ return d && d->ref.loadRelaxed() != 1;
+ }
+
+ constexpr void swap(QExplicitlySharedDataPointerV2 &other) noexcept
+ {
+ qt_ptr_swap(d, other.d);
+ }
+
+ // important change from QExplicitlySharedDataPointer: deep const
+ constexpr T &operator*() { return *d; }
+ constexpr T *operator->() { return d; }
+ constexpr const T &operator*() const { return *d; }
+ constexpr const T *operator->() const { return d; }
+
+ constexpr T *data() noexcept { return d; }
+ constexpr const T *data() const noexcept { return d; }
+
+ constexpr explicit operator bool() const noexcept { return d; }
+
+ constexpr friend bool operator==(const QExplicitlySharedDataPointerV2 &lhs,
+ const QExplicitlySharedDataPointerV2 &rhs) noexcept
+ {
+ return lhs.d == rhs.d;
+ }
+
+ constexpr friend bool operator!=(const QExplicitlySharedDataPointerV2 &lhs,
+ const QExplicitlySharedDataPointerV2 &rhs) noexcept
+ {
+ return lhs.d != rhs.d;
+ }
+};
+
+template <typename T>
+constexpr void swap(QExplicitlySharedDataPointerV2<T> &lhs, QExplicitlySharedDataPointerV2<T> &rhs) noexcept
+{
+ lhs.swap(rhs);
+}
+
+} // namespace QtPrivate
+
+QT_END_NAMESPACE
+
+#endif // QSHAREDDATA_IMPL_H
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 499546da4b..217a3a4ff4 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Intel Corporation.
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsharedpointer.h"
@@ -174,8 +139,7 @@
can also exceptionally be -1, indicating that there are no QSharedPointers
attached to an object, which is tracked too. The only case where this is
possible is that of QWeakPointers and QPointers tracking a QObject. Note
- that QWeakPointers tracking a QObject is a deprecated feature as of Qt 5.0,
- kept only for compatibility with Qt 4.x.
+ that QWeakPointers tracking a QObject is deprecated.
The weak reference count controls the lifetime of the d-pointer itself.
It can be thought of as an internal/intrusive reference count for
@@ -210,7 +174,7 @@
last QSharedPointer instance had.
This class is never instantiated directly: the constructors and
- destructor are private and, in C++11, deleted. Only the create() function
+ destructor are deleted. Only the create() function
may be called to return an object of this type. See below for construction
details.
@@ -249,8 +213,7 @@
Like ExternalRefCountWithCustomDeleter, this class is never instantiated
directly. This class also provides a create() member that returns the
- pointer, and hides its constructors and destructor. With C++11, they're
- deleted.
+ pointer, and deletes its constructors and destructor.
The size of this class depends on the size of \tt T.
@@ -478,6 +441,46 @@
*/
/*!
+ \fn template <class T> QSharedPointer<T>::QSharedPointer(QSharedPointer &&other)
+
+ Move-constructs a QSharedPointer instance, making it point at the same
+ object that \a other was pointing to.
+
+ \since 5.4
+*/
+
+/*!
+ \fn template <class T> QSharedPointer<T>::operator=(QSharedPointer &&other)
+
+ Move-assigns \a other to this QSharedPointer instance.
+
+ \since 5.0
+*/
+
+/*!
+ \fn template <class T> template <class X> QSharedPointer<T>::QSharedPointer(QSharedPointer<X> &&other)
+
+ Move-constructs a QSharedPointer instance, making it point at the same
+ object that \a other was pointing to.
+
+ This constructor participates in overload resolution only if \c{X*}
+ implicitly converts to \c{T*}.
+
+ \since 5.6
+*/
+
+/*!
+ \fn template <class T> template <class X> QSharedPointer<T>::operator=(QSharedPointer<X> &&other)
+
+ Move-assigns \a other to this QSharedPointer instance.
+
+ This assignment operator participates in overload resolution only if \c{X*}
+ implicitly converts to \c{T*}.
+
+ \since 5.6
+*/
+
+/*!
\fn template <class T> QSharedPointer<T>::QSharedPointer(const QWeakPointer<T> &other)
Creates a QSharedPointer by promoting the weak reference \a other
@@ -706,6 +709,49 @@
*/
/*!
+ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_before(const QSharedPointer<X> &other) const noexcept
+ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_before(const QWeakPointer<X> &other) const noexcept
+ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_before(const QSharedPointer<X> &other) const noexcept
+ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_before(const QWeakPointer<X> &other) const noexcept
+ \since 6.7
+
+ Returns \c true if and only if this smart pointer precedes \a other
+ in an implementation-defined owner-based ordering. The ordering is such
+ that two smart pointers are considered equivalent if they are both
+ empty or if they both own the same object (even if their apparent type
+ and pointer are different).
+
+ \sa owner_equal
+*/
+
+/*!
+ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_equal(const QSharedPointer<X> &other) const noexcept
+ \fn template <class T> template <class X> bool QSharedPointer<T>::owner_equal(const QWeakPointer<X> &other) const noexcept
+ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_equal(const QSharedPointer<X> &other) const noexcept
+ \fn template <class T> template <class X> bool QWeakPointer<T>::owner_equal(const QWeakPointer<X> &other) const noexcept
+
+ \since 6.7
+
+ Returns \c true if and only if this smart pointer and \a other
+ share ownership.
+
+ \sa owner_before, owner_hash
+*/
+
+/*!
+ \fn template <class T> size_t QSharedPointer<T>::owner_hash() const noexcept
+ \fn template <class T> size_t QWeakPointer<T>::owner_hash() const noexcept
+
+ \since 6.7
+
+ Returns a owner-based hash value for this smart pointer object.
+ Smart pointers that compare equal (as per \c{owner_equal}) will
+ have an identical owner-based hash.
+
+ \sa owner_equal
+*/
+
+/*!
\fn template <class T> QWeakPointer<T>::QWeakPointer()
Creates a QWeakPointer that points to nothing.
@@ -847,7 +893,7 @@
/*!
\fn template <class T> T *QWeakPointer<T>::data() const
\since 4.6
- \obsolete Use toStrongRef() instead, and data() on the returned QSharedPointer.
+ \deprecated Use toStrongRef() instead, and data() on the returned QSharedPointer.
Returns the value of the pointer being tracked by this QWeakPointer,
\b without ensuring that it cannot get deleted. To have that guarantee,
@@ -931,7 +977,16 @@
*/
/*!
- \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \fn template <class T> qHash(const QSharedPointer<T> &key, size_t seed)
+ \relates QSharedPointer
+
+ Returns the hash value for \a key, using \a seed to seed the calculation.
+
+ \since 5.0
+*/
+
+/*!
+ \fn template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
@@ -944,7 +999,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
@@ -957,7 +1012,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
+ \fn template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
\relates QSharedPointer
Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
@@ -970,7 +1025,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
+ \fn template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
\relates QSharedPointer
Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
@@ -983,7 +1038,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
Returns \c true if the pointer \a ptr1 is the
@@ -997,7 +1052,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
Returns \c true if the pointer \a ptr1 is not the
@@ -1011,7 +1066,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
\relates QWeakPointer
Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
@@ -1024,7 +1079,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
\relates QWeakPointer
Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
@@ -1037,7 +1092,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QWeakPointer
Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
@@ -1130,7 +1185,7 @@
*/
/*!
- \fn template <class T> template <class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \fn template<class T, class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QWeakPointer
Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
@@ -1143,7 +1198,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other)
\relates QSharedPointer
Returns a shared pointer to the pointer held by \a other, cast to
@@ -1158,7 +1213,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other)
\relates QSharedPointer
\relates QWeakPointer
@@ -1179,7 +1234,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
\relates QSharedPointer
Returns a shared pointer to the pointer held by \a src, using a
@@ -1195,7 +1250,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
\relates QSharedPointer
\relates QWeakPointer
@@ -1217,7 +1272,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
\relates QSharedPointer
Returns a shared pointer to the pointer held by \a src, cast to
@@ -1229,7 +1284,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
\relates QSharedPointer
\relates QWeakPointer
@@ -1247,7 +1302,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
\relates QSharedPointer
\since 4.6
@@ -1319,7 +1374,7 @@
*/
/*!
- \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
+ \fn template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
\relates QSharedPointer
\relates QWeakPointer
\since 4.6
@@ -1345,7 +1400,7 @@
/*!
- \fn template <class X> template <class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src)
+ \fn template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src)
\relates QWeakPointer
Returns a weak pointer to the pointer held by \a src, cast to
@@ -1365,6 +1420,7 @@
QT_BEGIN_NAMESPACE
+QT6_ONLY(
/*!
\internal
This function is called for a just-created QObject \a obj, to enable
@@ -1372,7 +1428,9 @@ QT_BEGIN_NAMESPACE
*/
void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *, bool)
{}
+)
+QT6_ONLY(
/*!
\internal
This function is called when a QSharedPointer is created from a QWeakPointer
@@ -1385,6 +1443,7 @@ void QtSharedPointer::ExternalRefCountData::checkQObjectShared(const QObject *)
if (strongref.loadRelaxed() < 0)
qWarning("QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
}
+)
QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj)
{
@@ -1399,7 +1458,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
}
// we can create the refcount data because it doesn't exist
- ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized);
+ ExternalRefCountData *x = ::new ExternalRefCountData(Qt::Uninitialized);
x->strongref.storeRelaxed(-1);
x->weakref.storeRelaxed(2); // the QWeakPointer that called us plus the QObject itself
@@ -1410,7 +1469,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
// ~ExternalRefCountData has a Q_ASSERT, so we use this trick to
// only execute this if Q_ASSERTs are enabled
Q_ASSERT((x->weakref.storeRelaxed(0), true));
- delete x;
+ ::delete x;
ret->weakref.ref();
}
return ret;
@@ -1423,7 +1482,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
*/
QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant)
{
- Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject);
+ Q_ASSERT(variant.metaType().flags() & QMetaType::SharedPointerToQObject);
return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData());
}
@@ -1434,7 +1493,8 @@ QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const
*/
QWeakPointer<QObject> QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant)
{
- Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::WeakPointerToQObject || QMetaType::typeFlags(variant.userType()) & QMetaType::TrackingPointerToQObject);
+ Q_ASSERT(variant.metaType().flags() & QMetaType::WeakPointerToQObject ||
+ variant.metaType().flags() & QMetaType::TrackingPointerToQObject);
return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData());
}
@@ -1448,7 +1508,7 @@ QT_END_NAMESPACE
# ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT
# if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
# define BACKTRACE_SUPPORTED
-# elif defined(Q_OS_MAC)
+# elif defined(Q_OS_DARWIN)
# define BACKTRACE_SUPPORTED
# endif
# endif
@@ -1562,12 +1622,18 @@ void QtSharedPointer::internalSafetyCheckAdd(const void *d_ptr, const volatile v
if (!kp)
return; // end-game: the application is being destroyed already
+ if (!ptr) {
+ // nullptr is allowed to be tracked by more than one QSharedPointer, so we
+ // need something else to put in our tracking structures
+ ptr = d_ptr;
+ }
+
QMutexLocker lock(&kp->mutex);
Q_ASSERT(!kp->dPointers.contains(d_ptr));
//qDebug("Adding d=%p value=%p", d_ptr, ptr);
- const void *other_d_ptr = kp->dataPointers.value(ptr, 0);
+ const void *other_d_ptr = kp->dataPointers.value(ptr, nullptr);
if (Q_UNLIKELY(other_d_ptr)) {
# ifdef BACKTRACE_SUPPORTED
printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace);
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 5d47369687..116c9afa00 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHAREDPOINTER_H
#define QSHAREDPOINTER_H
@@ -66,7 +30,7 @@ public:
operator bool() const;
bool operator!() const;
T &operator*() const;
- T *operator ->() const;
+ T *operator->() const;
// constructors
QSharedPointer();
@@ -76,13 +40,20 @@ public:
template <typename Deleter> QSharedPointer(std::nullptr_t, Deleter d);
QSharedPointer(const QSharedPointer<T> &other);
QSharedPointer(const QWeakPointer<T> &other);
+ QSharedPointer(QSharedPointer<T> &&other) noexcept;
~QSharedPointer() { }
QSharedPointer<T> &operator=(const QSharedPointer<T> &other);
+ QSharedPointer<T> &operator=(QSharedPointer<T> &&other) noexcept;
QSharedPointer<T> &operator=(const QWeakPointer<T> &other);
- void swap(QSharedPointer<T> &other);
+ template <class X>
+ QSharedPointer(QSharedPointer<X> && other) noexcept;
+ template <class X>
+ QSharedPointer &operator=(QSharedPointer<X> && other) noexcept;
+
+ void swap(QSharedPointer<T> &other) noexcept;
QWeakPointer<T> toWeakRef() const;
@@ -101,9 +72,25 @@ public:
template <typename... Args>
static inline QSharedPointer<T> create(Args &&... args);
+
+ // owner-based comparisons
+ template <typename X>
+ bool owner_before(const QSharedPointer<X> &other) const noexcept;
+ template <typename X>
+ bool owner_before(const QWeakPointer<X> &other) const noexcept;
+
+ template <typename X>
+ bool owner_equal(const QSharedPointer<X> &other) const noexcept;
+ template <typename X>
+ bool owner_equal(const QWeakPointer<X> &other) const noexcept;
+
+ size_t owner_hash() const noexcept;
};
template <class T>
+size_t qHash(const QSharedPointer<T> &key, size_t seed = 0) noexcept;
+
+template <class T>
class QWeakPointer
{
public:
@@ -114,24 +101,39 @@ public:
// constructors:
QWeakPointer();
- QWeakPointer(const QWeakPointer<T> &other);
+ QWeakPointer(const QWeakPointer<T> &other) noexcept;
+ QWeakPointer(QWeakPointer<T> &&other) noexcept;
QWeakPointer(const QSharedPointer<T> &other);
~QWeakPointer();
- QWeakPointer<T> &operator=(const QWeakPointer<T> &other);
+ QWeakPointer<T> &operator=(const QWeakPointer<T> &other) noexcept;
+ QWeakPointer<T> &operator=(QWeakPointer<T> &&other) noexcept;
QWeakPointer<T> &operator=(const QSharedPointer<T> &other);
QWeakPointer(const QObject *other);
QWeakPointer<T> &operator=(const QObject *other);
- void swap(QWeakPointer<T> &other);
+ void swap(QWeakPointer<T> &other) noexcept;
T *data() const;
void clear();
QSharedPointer<T> toStrongRef() const;
QSharedPointer<T> lock() const;
+
+ // owner-based comparisons
+ template <typename X>
+ bool owner_before(const QWeakPointer<X> &other) const noexcept;
+ template <typename X>
+ bool owner_before(const QSharedPointer<X> &other) const noexcept;
+
+ template <typename X>
+ bool owner_equal(const QWeakPointer<X> &other) const noexcept;
+ template <typename X>
+ bool owner_equal(const QSharedPointer<X> &other) const noexcept;
+
+ size_t owner_hash() const noexcept;
};
template <class T>
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index b6aad5ff73..456be91d03 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef Q_QDOC
@@ -61,16 +26,18 @@ QT_END_NAMESPACE
#include <new>
#include <QtCore/qatomic.h>
-#include <QtCore/qobject.h> // for qobject_cast
-#if QT_DEPRECATED_SINCE(5, 6)
-#include <QtCore/qhash.h>
-#endif
#include <QtCore/qhashfunctions.h>
+#include <QtCore/qmetatype.h> // for IsPointerToTypeDerivedFromQObject
+#include <QtCore/qxptype_traits.h>
#include <memory>
QT_BEGIN_NAMESPACE
+class QObject;
+template <class T>
+T qobject_cast(const QObject *object);
+
//
// forward declarations
//
@@ -107,7 +74,7 @@ namespace QtSharedPointer {
template <class T, typename Klass, typename RetVal>
inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
- { (t->*memberDeleter)(); }
+ { if (t) (t->*memberDeleter)(); }
template <class T, typename Deleter>
inline void executeDeleter(T *t, Deleter d)
{ d(t); }
@@ -149,12 +116,20 @@ namespace QtSharedPointer {
#ifndef QT_NO_QOBJECT
Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
+ QT6_ONLY(
Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
- Q_CORE_EXPORT void checkQObjectShared(const QObject *);
+ )
+ QT6_ONLY(Q_CORE_EXPORT void checkQObjectShared(const QObject *);)
#endif
inline void checkQObjectShared(...) { }
inline void setQObjectShared(...) { }
+ // Normally, only subclasses of ExternalRefCountData are allocated
+ // One exception exists in getAndRef; that uses the global operator new
+ // to prevent a mismatch with the custom operator delete
+ inline void *operator new(std::size_t) = delete;
+ // placement new
+ inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
inline void operator delete(void *ptr) { ::operator delete(ptr); }
inline void operator delete(void *, void *) { }
};
@@ -282,7 +257,6 @@ namespace QtSharedPointer {
template <class T> class QSharedPointer
{
- typedef T *QSharedPointer:: *RestrictedBool;
typedef QtSharedPointer::ExternalRefCountData Data;
template <typename X>
using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
@@ -300,27 +274,34 @@ public:
T *data() const noexcept { return value; }
T *get() const noexcept { return value; }
bool isNull() const noexcept { return !data(); }
- operator RestrictedBool() const noexcept { return isNull() ? nullptr : &QSharedPointer::value; }
+ explicit operator bool() const noexcept { return !isNull(); }
bool operator !() const noexcept { return isNull(); }
T &operator*() const { return *data(); }
T *operator->() const noexcept { return data(); }
- Q_DECL_CONSTEXPR QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
+ Q_NODISCARD_CTOR
+ constexpr QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
~QSharedPointer() { deref(); }
- Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
+ Q_NODISCARD_CTOR
+ constexpr QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
{ internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
template <class X, typename Deleter, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
{ internalConstruct(ptr, deleter); }
template <typename Deleter>
- QSharedPointer(std::nullptr_t, Deleter) : value(nullptr), d(nullptr) { }
+ Q_NODISCARD_CTOR
+ QSharedPointer(std::nullptr_t, Deleter deleter) : value(nullptr)
+ { internalConstruct(static_cast<T *>(nullptr), deleter); }
+ Q_NODISCARD_CTOR
QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d)
{ if (d) ref(); }
QSharedPointer &operator=(const QSharedPointer &other) noexcept
@@ -329,20 +310,17 @@ public:
swap(copy);
return *this;
}
+ Q_NODISCARD_CTOR
QSharedPointer(QSharedPointer &&other) noexcept
: value(other.value), d(other.d)
{
other.d = nullptr;
other.value = nullptr;
}
- QSharedPointer &operator=(QSharedPointer &&other) noexcept
- {
- QSharedPointer moved(std::move(other));
- swap(moved);
- return *this;
- }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedPointer)
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
QSharedPointer(QSharedPointer<X> &&other) noexcept
: value(other.value), d(other.d)
{
@@ -359,6 +337,7 @@ public:
}
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d)
{ if (d) ref(); }
@@ -371,6 +350,7 @@ public:
}
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
{ *this = other; }
@@ -416,10 +396,10 @@ public:
inline void clear() { QSharedPointer copy; swap(copy); }
- QWeakPointer<T> toWeakRef() const;
+ [[nodiscard]] QWeakPointer<T> toWeakRef() const;
template <typename... Args>
- static QSharedPointer create(Args && ...arguments)
+ [[nodiscard]] static QSharedPointer create(Args && ...arguments)
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -444,7 +424,47 @@ public:
return result;
}
+#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; }
+
+#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \
+ template <typename X> \
+ friend bool operator==(T1, T2) noexcept \
+ { return A1 == A2; } \
+ template <typename X> \
+ friend bool operator!=(T1, T2) noexcept \
+ { return A1 != A2; }
+
+ DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), const QSharedPointer<X> &p2, p2.data())
+ DECLARE_TEMPLATE_COMPARE_SET(const QSharedPointer &p1, p1.data(), X *ptr, ptr)
+ DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QSharedPointer &p2, p2.data())
+ DECLARE_COMPARE_SET(const QSharedPointer &p1, p1.data(), std::nullptr_t, nullptr)
+ DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QSharedPointer &p2, p2.data())
+#undef DECLARE_TEMPLATE_COMPARE_SET
+#undef DECLARE_COMPARE_SET
+
+ template <typename X>
+ bool owner_before(const QSharedPointer<X> &other) const noexcept
+ { return std::less<>()(d, other.d); }
+ template <typename X>
+ bool owner_before(const QWeakPointer<X> &other) const noexcept
+ { return std::less<>()(d, other.d); }
+
+ template <typename X>
+ bool owner_equal(const QSharedPointer<X> &other) const noexcept
+ { return d == other.d; }
+ template <typename X>
+ bool owner_equal(const QWeakPointer<X> &other) const noexcept
+ { return d == other.d; }
+
+ size_t owner_hash() const noexcept
+ { return std::hash<Data *>()(d); }
+
private:
+ Q_NODISCARD_CTOR
explicit QSharedPointer(Qt::Initialization) {}
void deref() noexcept
@@ -470,11 +490,6 @@ private:
template <typename X, typename Deleter>
inline void internalConstruct(X *ptr, Deleter deleter)
{
- if (!ptr) {
- d = nullptr;
- return;
- }
-
typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
@@ -486,23 +501,18 @@ private:
#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
internalSafetyCheckAdd(d, ptr);
#endif
- d->setQObjectShared(ptr, true);
enableSharedFromThis(ptr);
}
void internalSwap(QSharedPointer &other) noexcept
{
- qSwap(d, other.d);
- qSwap(this->value, other.value);
+ qt_ptr_swap(d, other.d);
+ qt_ptr_swap(this->value, other.value);
}
-#if defined(Q_NO_TEMPLATE_FRIENDS)
-public:
-#else
template <class X> friend class QSharedPointer;
template <class X> friend class QWeakPointer;
template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
-#endif
void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
inline void internalSet(Data *o, T *actual)
@@ -518,16 +528,14 @@ public:
tmp = o->strongref.loadRelaxed(); // failed, try again
}
- if (tmp > 0) {
+ if (tmp > 0)
o->weakref.ref();
- } else {
- o->checkQObjectShared(actual);
+ else
o = nullptr;
- }
}
- qSwap(d, o);
- qSwap(this->value, actual);
+ qt_ptr_swap(d, o);
+ qt_ptr_swap(this->value, actual);
if (!d || d->strongref.loadRelaxed() == 0)
this->value = nullptr;
@@ -542,11 +550,16 @@ public:
template <class T>
class QWeakPointer
{
- typedef T *QWeakPointer:: *RestrictedBool;
typedef QtSharedPointer::ExternalRefCountData Data;
template <typename X>
using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
+ template <typename X>
+ using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
+
+ template <typename X>
+ using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
+
public:
typedef T element_type;
typedef T value_type;
@@ -557,42 +570,50 @@ public:
typedef qptrdiff difference_type;
bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
- operator RestrictedBool() const noexcept { return isNull() ? nullptr : &QWeakPointer::value; }
+ explicit operator bool() const noexcept { return !isNull(); }
bool operator !() const noexcept { return isNull(); }
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_X("Use toStrongRef() instead, and data() on the returned QSharedPointer")
- T *data() const noexcept { return internalData(); }
-#endif
-
- inline QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
+ Q_NODISCARD_CTOR
+ constexpr QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
-#ifndef QT_NO_QOBJECT
- // special constructor that is enabled only if X derives from QObject
-#if QT_DEPRECATED_SINCE(5, 0)
- template <class X, IfCompatible<X> = true>
- QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
- { }
-#endif
-#endif
-
-#if QT_DEPRECATED_SINCE(5, 0)
- template <class X, IfCompatible<X> = true>
- QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
- { return *this = QWeakPointer(ptr); }
-#endif
-
+ Q_NODISCARD_CTOR
QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
{ if (d) d->weakref.ref(); }
+ Q_NODISCARD_CTOR
QWeakPointer(QWeakPointer &&other) noexcept
: d(other.d), value(other.value)
{
other.d = nullptr;
other.value = nullptr;
}
- QWeakPointer &operator=(QWeakPointer &&other) noexcept
- { QWeakPointer moved(std::move(other)); swap(moved); return *this; }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWeakPointer)
+
+ template <class X, IfCompatible<X> = true, IfNotVirtualBase<X> = true>
+ Q_NODISCARD_CTOR
+ QWeakPointer(QWeakPointer<X> &&other) noexcept
+ : d(std::exchange(other.d, nullptr)),
+ value(std::exchange(other.value, nullptr))
+ {
+ }
+
+ template <class X, IfCompatible<X> = true, IfVirtualBase<X> = true>
+ Q_NODISCARD_CTOR
+ QWeakPointer(QWeakPointer<X> &&other) noexcept
+ : d(other.d), value(other.toStrongRef().get()) // must go through QSharedPointer, see below
+ {
+ other.d = nullptr;
+ other.value = nullptr;
+ }
+
+ template <class X, IfCompatible<X> = true>
+ QWeakPointer &operator=(QWeakPointer<X> &&other) noexcept
+ {
+ QWeakPointer moved(std::move(other));
+ swap(moved);
+ return *this;
+ }
+
QWeakPointer &operator=(const QWeakPointer &other) noexcept
{
QWeakPointer copy(other);
@@ -602,10 +623,11 @@ public:
void swap(QWeakPointer &other) noexcept
{
- qSwap(this->d, other.d);
- qSwap(this->value, other.value);
+ qt_ptr_swap(this->d, other.d);
+ qt_ptr_swap(this->value, other.value);
}
+ Q_NODISCARD_CTOR
inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
{ if (d) d->weakref.ref();}
inline QWeakPointer &operator=(const QSharedPointer<T> &o)
@@ -615,6 +637,7 @@ public:
}
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
{ *this = o; }
@@ -627,15 +650,8 @@ public:
return *this;
}
- template <class X>
- bool operator==(const QWeakPointer<X> &o) const noexcept
- { return d == o.d && value == static_cast<const T *>(o.value); }
-
- template <class X>
- bool operator!=(const QWeakPointer<X> &o) const noexcept
- { return !(*this == o); }
-
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
{ *this = o; }
@@ -646,6 +662,20 @@ public:
return *this;
}
+ inline void clear() { *this = QWeakPointer(); }
+
+ [[nodiscard]] QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
+ // std::weak_ptr compatibility:
+ [[nodiscard]] QSharedPointer<T> lock() const { return toStrongRef(); }
+
+ template <class X>
+ bool operator==(const QWeakPointer<X> &o) const noexcept
+ { return d == o.d && value == static_cast<const T *>(o.value); }
+
+ template <class X>
+ bool operator!=(const QWeakPointer<X> &o) const noexcept
+ { return !(*this == o); }
+
template <class X>
bool operator==(const QSharedPointer<X> &o) const noexcept
{ return d == o.d; }
@@ -654,31 +684,52 @@ public:
bool operator!=(const QSharedPointer<X> &o) const noexcept
{ return !(*this == o); }
- inline void clear() { *this = QWeakPointer(); }
+ template <typename X>
+ friend bool operator==(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
+ { return p2 == p1; }
+ template <typename X>
+ friend bool operator!=(const QSharedPointer<X> &p1, const QWeakPointer &p2) noexcept
+ { return p2 != p1; }
+
+ friend bool operator==(const QWeakPointer &p, std::nullptr_t)
+ { return p.isNull(); }
+ friend bool operator==(std::nullptr_t, const QWeakPointer &p)
+ { return p.isNull(); }
+ friend bool operator!=(const QWeakPointer &p, std::nullptr_t)
+ { return !p.isNull(); }
+ friend bool operator!=(std::nullptr_t, const QWeakPointer &p)
+ { return !p.isNull(); }
- inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
- // std::weak_ptr compatibility:
- inline QSharedPointer<T> lock() const { return toStrongRef(); }
+ template <typename X>
+ bool owner_before(const QWeakPointer<X> &other) const noexcept
+ { return std::less<>()(d, other.d); }
+ template <typename X>
+ bool owner_before(const QSharedPointer<X> &other) const noexcept
+ { return std::less<>()(d, other.d); }
-#if defined(QWEAKPOINTER_ENABLE_ARROW)
- inline T *operator->() const { return data(); }
-#endif
+ template <typename X>
+ bool owner_equal(const QWeakPointer<X> &other) const noexcept
+ { return d == other.d; }
+ template <typename X>
+ bool owner_equal(const QSharedPointer<X> &other) const noexcept
+ { return d == other.d; }
+
+ size_t owner_hash() const noexcept
+ { return std::hash<Data *>()(d); }
private:
friend struct QtPrivate::EnableInternalData;
-#if defined(Q_NO_TEMPLATE_FRIENDS)
-public:
-#else
template <class X> friend class QSharedPointer;
+ template <class X> friend class QWeakPointer;
template <class X> friend class QPointer;
-#endif
template <class X>
inline QWeakPointer &assign(X *ptr)
- { return *this = QWeakPointer<X>(ptr, true); }
+ { return *this = QWeakPointer<T>(ptr, true); }
#ifndef QT_NO_QOBJECT
template <class X, IfCompatible<X> = true>
+ Q_NODISCARD_CTOR
inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
{ }
#endif
@@ -694,8 +745,8 @@ public:
value = actual;
}
- // ### Qt 6: remove users of this API; no one should ever access
- // a weak pointer's data but the weak pointer itself
+ // ### TODO - QTBUG-88102: remove all users of this API; no one should ever
+ // access a weak pointer's data but the weak pointer itself
inline T *internalData() const noexcept
{
return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
@@ -728,12 +779,8 @@ public:
inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
-#ifndef Q_NO_TEMPLATE_FRIENDS
private:
template <class X> friend class QSharedPointer;
-#else
-public:
-#endif
template <class X>
inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
{
@@ -744,100 +791,6 @@ public:
};
//
-// operator== and operator!=
-//
-template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return ptr1.data() == ptr2.data();
-}
-template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return ptr1.data() != ptr2.data();
-}
-
-template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
-{
- return ptr1.data() == ptr2;
-}
-template <class T, class X>
-bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return ptr1 == ptr2.data();
-}
-template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
-{
- return !(ptr1 == ptr2);
-}
-template <class T, class X>
-bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
-{
- return !(ptr2 == ptr1);
-}
-
-template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
-{
- return ptr2 == ptr1;
-}
-template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
-{
- return ptr2 != ptr1;
-}
-
-template<class T>
-inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return lhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return !lhs.isNull();
-}
-
-template<class T>
-inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
-{
- return rhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
-{
- return !rhs.isNull();
-}
-
-template<class T>
-inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return lhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
-{
- return !lhs.isNull();
-}
-
-template<class T>
-inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
-{
- return rhs.isNull();
-}
-
-template<class T>
-inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
-{
- return !rhs.isNull();
-}
-
-//
// operator-
//
template <class T, class X>
@@ -884,7 +837,7 @@ Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
template <class T>
Q_INLINE_TEMPLATE size_t qHash(const QSharedPointer<T> &ptr, size_t seed = 0)
{
- return QT_PREPEND_NAMESPACE(qHash)(ptr.data(), seed);
+ return qHash(ptr.data(), seed);
}
@@ -985,8 +938,8 @@ qobject_cast(const QWeakPointer<T> &src)
return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
}
-/// ### Qt 6: make this use toStrongRef() (once support for storing
-/// non-managed QObjects in QWeakPointer is removed)
+/// ### TODO - QTBUG-88102: make this use toStrongRef() (once support for
+/// storing non-managed QObjects in QWeakPointer is removed)
template<typename T>
QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
qWeakPointerFromVariant(const QVariant &variant)
@@ -1015,15 +968,11 @@ std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
using element_type = typename std::shared_ptr<X>::element_type;
auto castResult = qobject_cast<element_type *>(src.get());
if (castResult) {
- auto result = std::shared_ptr<X>(std::move(src), castResult);
-#if __cplusplus <= 201703L
// C++2a's move aliasing constructor will leave src empty.
// Before C++2a we don't really know if the compiler has support for it.
// The move aliasing constructor is the resolution for LWG2996,
// which does not impose a feature-testing macro. So: clear src.
- src.reset();
-#endif
- return result;
+ return std::shared_ptr<X>(std::exchange(src, nullptr), castResult);
}
return std::shared_ptr<X>();
}
@@ -1042,8 +991,8 @@ std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
#endif
-template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
-template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE);
+template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_RELOCATABLE_TYPE);
+template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index 2cbaae117d..d5e8e4c71b 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsize.h"
#include "qdatastream.h"
@@ -302,37 +266,32 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn bool operator==(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn bool QSize::operator==(const QSize &s1, const QSize &s2)
Returns \c true if \a s1 and \a s2 are equal; otherwise returns \c false.
*/
/*!
- \fn bool operator!=(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn bool QSize::operator!=(const QSize &s1, const QSize &s2)
Returns \c true if \a s1 and \a s2 are different; otherwise returns \c false.
*/
/*!
- \fn const QSize operator+(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn QSize QSize::operator+(const QSize &s1, const QSize &s2)
Returns the sum of \a s1 and \a s2; each component is added separately.
*/
/*!
- \fn const QSize operator-(const QSize &s1, const QSize &s2)
- \relates QSize
+ \fn QSize QSize::operator-(const QSize &s1, const QSize &s2)
Returns \a s2 subtracted from \a s1; each component is subtracted
separately.
*/
/*!
- \fn const QSize operator*(const QSize &size, qreal factor)
- \relates QSize
+ \fn QSize QSize::operator*(const QSize &size, qreal factor)
Multiplies the given \a size by the given \a factor, and returns
the result rounded to the nearest integer.
@@ -341,9 +300,8 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn const QSize operator*(qreal factor, const QSize &size)
+ \fn QSize QSize::operator*(qreal factor, const QSize &size)
\overload
- \relates QSize
Multiplies the given \a size by the given \a factor, and returns
the result rounded to the nearest integer.
@@ -362,8 +320,7 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn const QSize operator/(const QSize &size, qreal divisor)
- \relates QSize
+ \fn QSize QSize::operator/(const QSize &size, qreal divisor)
\overload
Divides the given \a size by the given \a divisor, and returns the
@@ -410,6 +367,15 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
\sa grownBy()
*/
+/*!
+ \fn QSize::toSizeF() const
+ \since 6.4
+
+ Returns this size as a size with floating point accuracy.
+
+ \sa QSizeF::toSize()
+*/
+
/*****************************************************************************
QSize stream functions
*****************************************************************************/
@@ -527,13 +493,13 @@ QDebug operator<<(QDebug dbg, const QSize &s)
Constructs a size with floating point accuracy from the given \a
size.
- \sa toSize()
+ \sa toSize(), QSize::toSizeF()
*/
/*!
\fn QSizeF::QSizeF(qreal width, qreal height)
- Constructs a size with the given \a width and \a height.
+ Constructs a size with the given finite \a width and \a height.
*/
/*!
@@ -557,7 +523,7 @@ QDebug operator<<(QDebug dbg, const QSize &s)
/*!
\fn bool QSizeF::isValid() const
- Returns \c true if both the width and height is equal to or greater
+ Returns \c true if both the width and height are equal to or greater
than 0; otherwise returns \c false.
\sa isNull(), isEmpty()
@@ -582,7 +548,7 @@ QDebug operator<<(QDebug dbg, const QSize &s)
/*!
\fn void QSizeF::setWidth(qreal width)
- Sets the width to the given \a width.
+ Sets the width to the given finite \a width.
\sa width(), rwidth(), setHeight()
*/
@@ -590,7 +556,7 @@ QDebug operator<<(QDebug dbg, const QSize &s)
/*!
\fn void QSizeF::setHeight(qreal height)
- Sets the height to the given \a height.
+ Sets the height to the given finite \a height.
\sa height(), rheight(), setWidth()
*/
@@ -603,7 +569,7 @@ QDebug operator<<(QDebug dbg, const QSize &s)
Note that the coordinates in the returned size will be rounded to
the nearest integer.
- \sa QSizeF()
+ \sa QSizeF(), QSize::toSizeF()
*/
/*!
@@ -741,61 +707,64 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
\fn QSizeF &QSizeF::operator*=(qreal factor)
\overload
- Multiplies both the width and height by the given \a factor and
+ Multiplies both the width and height by the given finite \a factor and
returns a reference to the size.
\sa scale()
*/
/*!
- \fn bool operator==(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn bool QSizeF::operator==(const QSizeF &s1, const QSizeF &s2)
- Returns \c true if \a s1 and \a s2 are equal; otherwise returns
- false.
+ Returns \c true if \a s1 and \a s2 are approximately equal; otherwise
+ returns false.
+
+ \warning This function does not check for strict equality; instead,
+ it uses a fuzzy comparison to compare the sizes' extents.
+
+ \sa qFuzzyCompare
*/
/*!
- \fn bool operator!=(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn bool QSizeF::operator!=(const QSizeF &s1, const QSizeF &s2)
- Returns \c true if \a s1 and \a s2 are different; otherwise returns \c false.
+ Returns \c true if \a s1 and \a s2 are sufficiently different; otherwise
+ returns \c false.
+
+ \warning This function does not check for strict inequality; instead,
+ it uses a fuzzy comparison to compare the sizes' extents.
*/
/*!
- \fn const QSizeF operator+(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn QSizeF QSizeF::operator+(const QSizeF &s1, const QSizeF &s2)
Returns the sum of \a s1 and \a s2; each component is added separately.
*/
/*!
- \fn const QSizeF operator-(const QSizeF &s1, const QSizeF &s2)
- \relates QSizeF
+ \fn QSizeF QSizeF::operator-(const QSizeF &s1, const QSizeF &s2)
Returns \a s2 subtracted from \a s1; each component is subtracted
separately.
*/
/*!
- \fn const QSizeF operator*(const QSizeF &size, qreal factor)
+ \fn QSizeF QSizeF::operator*(const QSizeF &size, qreal factor)
\overload
- \relates QSizeF
- Multiplies the given \a size by the given \a factor and returns
+ Multiplies the given \a size by the given finite \a factor and returns
the result.
\sa QSizeF::scale()
*/
/*!
- \fn const QSizeF operator*(qreal factor, const QSizeF &size)
+ \fn QSizeF QSizeF::operator*(qreal factor, const QSizeF &size)
\overload
- \relates QSizeF
- Multiplies the given \a size by the given \a factor and returns
+ Multiplies the given \a size by the given finite \a factor and returns
the result.
*/
@@ -804,20 +773,19 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
\overload
- Divides both the width and height by the given \a divisor and
- returns a reference to the size.
+ Divides both the width and height by the given \a divisor and returns a
+ reference to the size. The \a divisor must not be either zero or NaN.
\sa scale()
*/
/*!
- \fn const QSizeF operator/(const QSizeF &size, qreal divisor)
+ \fn QSizeF QSizeF::operator/(const QSizeF &size, qreal divisor)
- \relates QSizeF
\overload
Divides the given \a size by the given \a divisor and returns the
- result.
+ result. The \a divisor must not be either zero or NaN.
\sa QSizeF::scale()
*/
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index 06de1cd63f..a5eaf34afe 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -1,110 +1,103 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIZE_H
#define QSIZE_H
#include <QtCore/qnamespace.h>
+#include <QtCore/qhashfunctions.h>
#include <QtCore/qmargins.h>
+#include <QtCore/q20type_traits.h>
+#include <QtCore/q23utility.h>
+
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGSize;
#endif
QT_BEGIN_NAMESPACE
+// QT_ENABLE_P0846_SEMANTICS_FOR(get) // from qmargins.h
+
+class QSizeF;
class Q_CORE_EXPORT QSize
{
public:
- Q_DECL_CONSTEXPR QSize() noexcept;
- Q_DECL_CONSTEXPR QSize(int w, int h) noexcept;
+ constexpr QSize() noexcept;
+ constexpr QSize(int w, int h) noexcept;
- Q_DECL_CONSTEXPR inline bool isNull() const noexcept;
- Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
- Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
+ constexpr inline bool isNull() const noexcept;
+ constexpr inline bool isEmpty() const noexcept;
+ constexpr inline bool isValid() const noexcept;
- Q_DECL_CONSTEXPR inline int width() const noexcept;
- Q_DECL_CONSTEXPR inline int height() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) noexcept;
+ constexpr inline int width() const noexcept;
+ constexpr inline int height() const noexcept;
+ constexpr inline void setWidth(int w) noexcept;
+ constexpr inline void setHeight(int h) noexcept;
void transpose() noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize transposed() const noexcept;
+ [[nodiscard]] constexpr inline QSize transposed() const noexcept;
inline void scale(int w, int h, Qt::AspectRatioMode mode) noexcept;
inline void scale(const QSize &s, Qt::AspectRatioMode mode) noexcept;
- Q_REQUIRED_RESULT QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const noexcept;
+ [[nodiscard]] constexpr inline QSize expandedTo(const QSize &) const noexcept;
+ [[nodiscard]] constexpr inline QSize boundedTo(const QSize &) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSize grownBy(QMargins m) const noexcept
+ [[nodiscard]] constexpr QSize grownBy(QMargins m) const noexcept
{ return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSize shrunkBy(QMargins m) const noexcept
+ [[nodiscard]] constexpr QSize shrunkBy(QMargins m) const noexcept
{ return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
- Q_DECL_RELAXED_CONSTEXPR inline int &rwidth() noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline int &rheight() noexcept;
+ constexpr inline int &rwidth() noexcept;
+ constexpr inline int &rheight() noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QSize &operator+=(const QSize &) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QSize &operator-=(const QSize &) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QSize &operator*=(qreal c) noexcept;
+ constexpr inline QSize &operator+=(const QSize &) noexcept;
+ constexpr inline QSize &operator-=(const QSize &) noexcept;
+ constexpr inline QSize &operator*=(qreal c) noexcept;
inline QSize &operator/=(qreal c);
- friend inline Q_DECL_CONSTEXPR bool operator==(const QSize &, const QSize &) noexcept;
- friend inline Q_DECL_CONSTEXPR bool operator!=(const QSize &, const QSize &) noexcept;
- friend inline Q_DECL_CONSTEXPR const QSize operator+(const QSize &, const QSize &) noexcept;
- friend inline Q_DECL_CONSTEXPR const QSize operator-(const QSize &, const QSize &) noexcept;
- friend inline Q_DECL_CONSTEXPR const QSize operator*(const QSize &, qreal) noexcept;
- friend inline Q_DECL_CONSTEXPR const QSize operator*(qreal, const QSize &) noexcept;
- friend inline const QSize operator/(const QSize &, qreal);
+ friend inline constexpr bool operator==(const QSize &s1, const QSize &s2) noexcept
+ { return s1.wd == s2.wd && s1.ht == s2.ht; }
+ friend inline constexpr bool operator!=(const QSize &s1, const QSize &s2) noexcept
+ { return s1.wd != s2.wd || s1.ht != s2.ht; }
+ friend inline constexpr QSize operator+(const QSize &s1, const QSize &s2) noexcept
+ { return QSize(s1.wd + s2.wd, s1.ht + s2.ht); }
+ friend inline constexpr QSize operator-(const QSize &s1, const QSize &s2) noexcept
+ { return QSize(s1.wd - s2.wd, s1.ht - s2.ht); }
+ friend inline constexpr QSize operator*(const QSize &s, qreal c) noexcept
+ { return QSize(qRound(s.wd * c), qRound(s.ht * c)); }
+ friend inline constexpr QSize operator*(qreal c, const QSize &s) noexcept
+ { return s * c; }
+ friend inline QSize operator/(const QSize &s, qreal c)
+ { Q_ASSERT(!qFuzzyIsNull(c)); return QSize(qRound(s.wd / c), qRound(s.ht / c)); }
+ friend inline constexpr size_t qHash(const QSize &, size_t) noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGSize toCGSize() const noexcept;
+ [[nodiscard]] CGSize toCGSize() const noexcept;
#endif
+ [[nodiscard]] inline constexpr QSizeF toSizeF() const noexcept;
+
private:
int wd;
int ht;
+
+ template <std::size_t I,
+ typename S,
+ std::enable_if_t<(I < 2), bool> = true,
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<S>, QSize>, bool> = true>
+ friend constexpr decltype(auto) get(S &&s) noexcept
+ {
+ if constexpr (I == 0)
+ return q23::forward_like<S>(s.wd);
+ else if constexpr (I == 1)
+ return q23::forward_like<S>(s.ht);
+ }
};
-Q_DECLARE_TYPEINFO(QSize, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSize, Q_RELOCATABLE_TYPE);
/*****************************************************************************
QSize stream functions
@@ -120,32 +113,32 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &);
QSize inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QSize::QSize() noexcept : wd(-1), ht(-1) {}
+constexpr inline QSize::QSize() noexcept : wd(-1), ht(-1) {}
-Q_DECL_CONSTEXPR inline QSize::QSize(int w, int h) noexcept : wd(w), ht(h) {}
+constexpr inline QSize::QSize(int w, int h) noexcept : wd(w), ht(h) {}
-Q_DECL_CONSTEXPR inline bool QSize::isNull() const noexcept
-{ return wd==0 && ht==0; }
+constexpr inline bool QSize::isNull() const noexcept
+{ return wd == 0 && ht == 0; }
-Q_DECL_CONSTEXPR inline bool QSize::isEmpty() const noexcept
-{ return wd<1 || ht<1; }
+constexpr inline bool QSize::isEmpty() const noexcept
+{ return wd < 1 || ht < 1; }
-Q_DECL_CONSTEXPR inline bool QSize::isValid() const noexcept
-{ return wd>=0 && ht>=0; }
+constexpr inline bool QSize::isValid() const noexcept
+{ return wd >= 0 && ht >= 0; }
-Q_DECL_CONSTEXPR inline int QSize::width() const noexcept
+constexpr inline int QSize::width() const noexcept
{ return wd; }
-Q_DECL_CONSTEXPR inline int QSize::height() const noexcept
+constexpr inline int QSize::height() const noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSize::setWidth(int w) noexcept
+constexpr inline void QSize::setWidth(int w) noexcept
{ wd = w; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSize::setHeight(int h) noexcept
+constexpr inline void QSize::setHeight(int h) noexcept
{ ht = h; }
-Q_DECL_CONSTEXPR inline QSize QSize::transposed() const noexcept
+constexpr inline QSize QSize::transposed() const noexcept
{ return QSize(ht, wd); }
inline void QSize::scale(int w, int h, Qt::AspectRatioMode mode) noexcept
@@ -157,58 +150,50 @@ inline void QSize::scale(const QSize &s, Qt::AspectRatioMode mode) noexcept
inline QSize QSize::scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept
{ return scaled(QSize(w, h), mode); }
-Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rwidth() noexcept
+constexpr inline int &QSize::rwidth() noexcept
{ return wd; }
-Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rheight() noexcept
+constexpr inline int &QSize::rheight() noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator+=(const QSize &s) noexcept
-{ wd+=s.wd; ht+=s.ht; return *this; }
-
-Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator-=(const QSize &s) noexcept
-{ wd-=s.wd; ht-=s.ht; return *this; }
-
-Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator*=(qreal c) noexcept
-{ wd = qRound(wd*c); ht = qRound(ht*c); return *this; }
-
-Q_DECL_CONSTEXPR inline bool operator==(const QSize &s1, const QSize &s2) noexcept
-{ return s1.wd == s2.wd && s1.ht == s2.ht; }
-
-Q_DECL_CONSTEXPR inline bool operator!=(const QSize &s1, const QSize &s2) noexcept
-{ return s1.wd != s2.wd || s1.ht != s2.ht; }
-
-Q_DECL_CONSTEXPR inline const QSize operator+(const QSize & s1, const QSize & s2) noexcept
-{ return QSize(s1.wd+s2.wd, s1.ht+s2.ht); }
-
-Q_DECL_CONSTEXPR inline const QSize operator-(const QSize &s1, const QSize &s2) noexcept
-{ return QSize(s1.wd-s2.wd, s1.ht-s2.ht); }
-
-Q_DECL_CONSTEXPR inline const QSize operator*(const QSize &s, qreal c) noexcept
-{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
+constexpr inline QSize &QSize::operator+=(const QSize &s) noexcept
+{
+ wd += s.wd;
+ ht += s.ht;
+ return *this;
+}
-Q_DECL_CONSTEXPR inline const QSize operator*(qreal c, const QSize &s) noexcept
-{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
+constexpr inline QSize &QSize::operator-=(const QSize &s) noexcept
+{
+ wd -= s.wd;
+ ht -= s.ht;
+ return *this;
+}
-inline QSize &QSize::operator/=(qreal c)
+constexpr inline QSize &QSize::operator*=(qreal c) noexcept
{
- Q_ASSERT(!qFuzzyIsNull(c));
- wd = qRound(wd/c); ht = qRound(ht/c);
+ wd = qRound(wd * c);
+ ht = qRound(ht * c);
return *this;
}
-inline const QSize operator/(const QSize &s, qreal c)
+constexpr inline size_t qHash(const QSize &s, size_t seed = 0) noexcept
+{ return qHashMulti(seed, s.wd, s.ht); }
+
+inline QSize &QSize::operator/=(qreal c)
{
Q_ASSERT(!qFuzzyIsNull(c));
- return QSize(qRound(s.wd/c), qRound(s.ht/c));
+ wd = qRound(wd / c);
+ ht = qRound(ht / c);
+ return *this;
}
-Q_DECL_CONSTEXPR inline QSize QSize::expandedTo(const QSize & otherSize) const noexcept
+constexpr inline QSize QSize::expandedTo(const QSize & otherSize) const noexcept
{
return QSize(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
}
-Q_DECL_CONSTEXPR inline QSize QSize::boundedTo(const QSize & otherSize) const noexcept
+constexpr inline QSize QSize::boundedTo(const QSize & otherSize) const noexcept
{
return QSize(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
}
@@ -221,62 +206,87 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QSize &);
class Q_CORE_EXPORT QSizeF
{
public:
- Q_DECL_CONSTEXPR QSizeF() noexcept;
- Q_DECL_CONSTEXPR QSizeF(const QSize &sz) noexcept;
- Q_DECL_CONSTEXPR QSizeF(qreal w, qreal h) noexcept;
+ constexpr QSizeF() noexcept;
+ constexpr QSizeF(const QSize &sz) noexcept;
+ constexpr QSizeF(qreal w, qreal h) noexcept;
inline bool isNull() const noexcept;
- Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
- Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
+ constexpr inline bool isEmpty() const noexcept;
+ constexpr inline bool isValid() const noexcept;
- Q_DECL_CONSTEXPR inline qreal width() const noexcept;
- Q_DECL_CONSTEXPR inline qreal height() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) noexcept;
+ constexpr inline qreal width() const noexcept;
+ constexpr inline qreal height() const noexcept;
+ constexpr inline void setWidth(qreal w) noexcept;
+ constexpr inline void setHeight(qreal h) noexcept;
void transpose() noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF transposed() const noexcept;
+ [[nodiscard]] constexpr inline QSizeF transposed() const noexcept;
inline void scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept;
inline void scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept;
- Q_REQUIRED_RESULT QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept;
+ [[nodiscard]] QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const noexcept;
+ [[nodiscard]] constexpr inline QSizeF expandedTo(const QSizeF &) const noexcept;
+ [[nodiscard]] constexpr inline QSizeF boundedTo(const QSizeF &) const noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSizeF grownBy(QMarginsF m) const noexcept
+ [[nodiscard]] constexpr QSizeF grownBy(QMarginsF m) const noexcept
{ return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSizeF shrunkBy(QMarginsF m) const noexcept
+ [[nodiscard]] constexpr QSizeF shrunkBy(QMarginsF m) const noexcept
{ return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
- Q_DECL_RELAXED_CONSTEXPR inline qreal &rwidth() noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline qreal &rheight() noexcept;
+ constexpr inline qreal &rwidth() noexcept;
+ constexpr inline qreal &rheight() noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator+=(const QSizeF &) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator-=(const QSizeF &) noexcept;
- Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator*=(qreal c) noexcept;
+ constexpr inline QSizeF &operator+=(const QSizeF &) noexcept;
+ constexpr inline QSizeF &operator-=(const QSizeF &) noexcept;
+ constexpr inline QSizeF &operator*=(qreal c) noexcept;
inline QSizeF &operator/=(qreal c);
- friend Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &, const QSizeF &) noexcept;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &, const QSizeF &) noexcept;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator+(const QSizeF &, const QSizeF &) noexcept;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &, const QSizeF &) noexcept;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator*(const QSizeF &, qreal) noexcept;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator*(qreal, const QSizeF &) noexcept;
- friend inline const QSizeF operator/(const QSizeF &, qreal);
-
- Q_DECL_CONSTEXPR inline QSize toSize() const noexcept;
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_FLOAT_COMPARE
+ friend constexpr inline bool operator==(const QSizeF &s1, const QSizeF &s2)
+ {
+ return ((!s1.wd || !s2.wd) ? qFuzzyIsNull(s1.wd - s2.wd) : qFuzzyCompare(s1.wd, s2.wd))
+ && ((!s1.ht || !s2.ht) ? qFuzzyIsNull(s1.ht - s2.ht) : qFuzzyCompare(s1.ht, s2.ht));
+ }
+ QT_WARNING_POP
+ friend constexpr inline bool operator!=(const QSizeF &s1, const QSizeF &s2)
+ { return !(s1 == s2); }
+ friend constexpr inline QSizeF operator+(const QSizeF &s1, const QSizeF &s2) noexcept
+ { return QSizeF(s1.wd + s2.wd, s1.ht + s2.ht); }
+ friend constexpr inline QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
+ { return QSizeF(s1.wd - s2.wd, s1.ht - s2.ht); }
+ friend constexpr inline QSizeF operator*(const QSizeF &s, qreal c) noexcept
+ { return QSizeF(s.wd * c, s.ht * c); }
+ friend constexpr inline QSizeF operator*(qreal c, const QSizeF &s) noexcept
+ { return s * c; }
+ friend inline QSizeF operator/(const QSizeF &s, qreal c)
+ { Q_ASSERT(!qFuzzyIsNull(c)); return QSizeF(s.wd / c, s.ht / c); }
+
+ constexpr inline QSize toSize() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QSizeF fromCGSize(CGSize size) noexcept;
- Q_REQUIRED_RESULT CGSize toCGSize() const noexcept;
+ [[nodiscard]] static QSizeF fromCGSize(CGSize size) noexcept;
+ [[nodiscard]] CGSize toCGSize() const noexcept;
#endif
private:
qreal wd;
qreal ht;
+
+ template <std::size_t I,
+ typename S,
+ std::enable_if_t<(I < 2), bool> = true,
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<S>, QSizeF>, bool> = true>
+ friend constexpr decltype(auto) get(S &&s) noexcept
+ {
+ if constexpr (I == 0)
+ return q23::forward_like<S>(s.wd);
+ else if constexpr (I == 1)
+ return q23::forward_like<S>(s.ht);
+ }
};
-Q_DECLARE_TYPEINFO(QSizeF, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSizeF, Q_RELOCATABLE_TYPE);
/*****************************************************************************
@@ -293,34 +303,34 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &);
QSizeF inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QSizeF::QSizeF() noexcept : wd(-1.), ht(-1.) {}
+constexpr inline QSizeF::QSizeF() noexcept : wd(-1.), ht(-1.) {}
-Q_DECL_CONSTEXPR inline QSizeF::QSizeF(const QSize &sz) noexcept : wd(sz.width()), ht(sz.height()) {}
+constexpr inline QSizeF::QSizeF(const QSize &sz) noexcept : wd(sz.width()), ht(sz.height()) {}
-Q_DECL_CONSTEXPR inline QSizeF::QSizeF(qreal w, qreal h) noexcept : wd(w), ht(h) {}
+constexpr inline QSizeF::QSizeF(qreal w, qreal h) noexcept : wd(w), ht(h) {}
inline bool QSizeF::isNull() const noexcept
{ return qIsNull(wd) && qIsNull(ht); }
-Q_DECL_CONSTEXPR inline bool QSizeF::isEmpty() const noexcept
+constexpr inline bool QSizeF::isEmpty() const noexcept
{ return wd <= 0. || ht <= 0.; }
-Q_DECL_CONSTEXPR inline bool QSizeF::isValid() const noexcept
+constexpr inline bool QSizeF::isValid() const noexcept
{ return wd >= 0. && ht >= 0.; }
-Q_DECL_CONSTEXPR inline qreal QSizeF::width() const noexcept
+constexpr inline qreal QSizeF::width() const noexcept
{ return wd; }
-Q_DECL_CONSTEXPR inline qreal QSizeF::height() const noexcept
+constexpr inline qreal QSizeF::height() const noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setWidth(qreal w) noexcept
+constexpr inline void QSizeF::setWidth(qreal w) noexcept
{ wd = w; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setHeight(qreal h) noexcept
+constexpr inline void QSizeF::setHeight(qreal h) noexcept
{ ht = h; }
-Q_DECL_CONSTEXPR inline QSizeF QSizeF::transposed() const noexcept
+constexpr inline QSizeF QSizeF::transposed() const noexcept
{ return QSizeF(ht, wd); }
inline void QSizeF::scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept
@@ -332,71 +342,82 @@ inline void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept
inline QSizeF QSizeF::scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept
{ return scaled(QSizeF(w, h), mode); }
-Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rwidth() noexcept
+constexpr inline qreal &QSizeF::rwidth() noexcept
{ return wd; }
-Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rheight() noexcept
+constexpr inline qreal &QSizeF::rheight() noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator+=(const QSizeF &s) noexcept
-{ wd += s.wd; ht += s.ht; return *this; }
-
-Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator-=(const QSizeF &s) noexcept
-{ wd -= s.wd; ht -= s.ht; return *this; }
-
-Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator*=(qreal c) noexcept
-{ wd *= c; ht *= c; return *this; }
-
-Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &s1, const QSizeF &s2) noexcept
-{ return qFuzzyCompare(s1.wd, s2.wd) && qFuzzyCompare(s1.ht, s2.ht); }
-
-Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &s1, const QSizeF &s2) noexcept
-{ return !qFuzzyCompare(s1.wd, s2.wd) || !qFuzzyCompare(s1.ht, s2.ht); }
-
-Q_DECL_CONSTEXPR inline const QSizeF operator+(const QSizeF & s1, const QSizeF & s2) noexcept
-{ return QSizeF(s1.wd+s2.wd, s1.ht+s2.ht); }
-
-Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
-{ return QSizeF(s1.wd-s2.wd, s1.ht-s2.ht); }
-
-Q_DECL_CONSTEXPR inline const QSizeF operator*(const QSizeF &s, qreal c) noexcept
-{ return QSizeF(s.wd*c, s.ht*c); }
+constexpr inline QSizeF &QSizeF::operator+=(const QSizeF &s) noexcept
+{
+ wd += s.wd;
+ ht += s.ht;
+ return *this;
+}
-Q_DECL_CONSTEXPR inline const QSizeF operator*(qreal c, const QSizeF &s) noexcept
-{ return QSizeF(s.wd*c, s.ht*c); }
+constexpr inline QSizeF &QSizeF::operator-=(const QSizeF &s) noexcept
+{
+ wd -= s.wd;
+ ht -= s.ht;
+ return *this;
+}
-inline QSizeF &QSizeF::operator/=(qreal c)
+constexpr inline QSizeF &QSizeF::operator*=(qreal c) noexcept
{
- Q_ASSERT(!qFuzzyIsNull(c));
- wd = wd/c; ht = ht/c;
+ wd *= c;
+ ht *= c;
return *this;
}
-inline const QSizeF operator/(const QSizeF &s, qreal c)
+inline QSizeF &QSizeF::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyIsNull(c));
- return QSizeF(s.wd/c, s.ht/c);
+ Q_ASSERT(!qFuzzyIsNull(c) && qIsFinite(c));
+ wd = wd / c;
+ ht = ht / c;
+ return *this;
}
-Q_DECL_CONSTEXPR inline QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const noexcept
+constexpr inline QSizeF QSizeF::expandedTo(const QSizeF &otherSize) const noexcept
{
- return QSizeF(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
+ return QSizeF(qMax(wd, otherSize.wd), qMax(ht, otherSize.ht));
}
-Q_DECL_CONSTEXPR inline QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const noexcept
+constexpr inline QSizeF QSizeF::boundedTo(const QSizeF &otherSize) const noexcept
{
- return QSizeF(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
+ return QSizeF(qMin(wd, otherSize.wd), qMin(ht, otherSize.ht));
}
-Q_DECL_CONSTEXPR inline QSize QSizeF::toSize() const noexcept
+constexpr inline QSize QSizeF::toSize() const noexcept
{
return QSize(qRound(wd), qRound(ht));
}
+constexpr QSizeF QSize::toSizeF() const noexcept { return *this; }
+
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QSizeF &);
#endif
QT_END_NAMESPACE
+/*****************************************************************************
+ QSize/QSizeF tuple protocol
+ *****************************************************************************/
+
+namespace std {
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QSize)> : public integral_constant<size_t, 2> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QSize)> { public: using type = int; };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QSize)> { public: using type = int; };
+
+ template <>
+ class tuple_size<QT_PREPEND_NAMESPACE(QSizeF)> : public integral_constant<size_t, 2> {};
+ template <>
+ class tuple_element<0, QT_PREPEND_NAMESPACE(QSizeF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+ template <>
+ class tuple_element<1, QT_PREPEND_NAMESPACE(QSizeF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
+}
+
#endif // QSIZE_H
diff --git a/src/corelib/tools/qspan.h b/src/corelib/tools/qspan.h
new file mode 100644
index 0000000000..d6ae2570ae
--- /dev/null
+++ b/src/corelib/tools/qspan.h
@@ -0,0 +1,452 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSPAN_H
+#define QSPAN_H
+
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtypes.h>
+#include <QtCore/qcontainerfwd.h>
+
+#include <array>
+#include <cstddef>
+#include <cassert>
+#include <initializer_list>
+#include <QtCore/q20iterator.h>
+#include <QtCore/q20memory.h>
+#ifdef __cpp_lib_span
+#include <span>
+#endif
+#include <QtCore/q20type_traits.h>
+
+QT_BEGIN_NAMESPACE
+
+// like std::dynamic_extent
+namespace q20 {
+ inline constexpr auto dynamic_extent = std::size_t(-1);
+} // namespace q20
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#ifdef __cpp_lib_span
+#ifdef __cpp_lib_concepts
+namespace std::ranges {
+// Officially, these are defined in <ranges>, but that is a heavy-hitter header.
+// OTOH, <span> must specialize these variable templates, too, so we assume that
+// <span> includes some meaningful subset of <ranges> and just go ahead and use them:
+template <typename T, std::size_t E>
+constexpr inline bool enable_borrowed_range<QT_PREPEND_NAMESPACE(QSpan)<T, E>> = true;
+template <typename T, std::size_t E>
+constexpr inline bool enable_view<QT_PREPEND_NAMESPACE(QSpan)<T, E>> = true;
+} // namespace std::ranges
+#endif // __cpp_lib_concepts
+#endif // __cpp_lib_span
+QT_END_INCLUDE_NAMESPACE
+
+namespace QSpanPrivate {
+
+template <typename T, std::size_t E> class QSpanBase;
+
+template <typename T>
+struct is_qspan_helper : std::false_type {};
+template <typename T, std::size_t E>
+struct is_qspan_helper<QSpan<T, E>> : std::true_type {};
+template <typename T, std::size_t E>
+struct is_qspan_helper<QSpanBase<T, E>> : std::true_type {};
+template <typename T>
+using is_qspan = is_qspan_helper<q20::remove_cvref_t<T>>;
+
+template <typename T>
+struct is_std_span_helper : std::false_type {};
+#ifdef __cpp_lib_span
+template <typename T, std::size_t E>
+struct is_std_span_helper<std::span<T, E>> : std::true_type {};
+#endif // __cpp_lib_span
+template <typename T>
+using is_std_span = is_std_span_helper<q20::remove_cvref_t<T>>;
+
+template <typename T>
+struct is_std_array_helper : std::false_type {};
+template <typename T, std::size_t N>
+struct is_std_array_helper<std::array<T, N>> : std::true_type {};
+template <typename T>
+using is_std_array = is_std_array_helper<q20::remove_cvref_t<T>>;
+
+template <typename From, typename To>
+using is_qualification_conversion =
+ std::is_convertible<From(*)[], To(*)[]>; // https://eel.is/c++draft/span.cons#note-1
+template <typename From, typename To>
+constexpr inline bool is_qualification_conversion_v = is_qualification_conversion<From, To>::value;
+
+namespace AdlTester {
+#define MAKE_ADL_TEST(what) \
+ using std:: what; /* bring into scope */ \
+ template <typename T> using what ## _result = decltype( what (std::declval<T&&>())); \
+ /* end */
+MAKE_ADL_TEST(begin)
+MAKE_ADL_TEST(data)
+MAKE_ADL_TEST(size)
+#undef MAKE_ADL_TEST
+}
+
+// Replacements for std::ranges::XXX(), but only bringing in ADL XXX()s,
+// not doing the extra work C++20 requires
+template <typename Range>
+AdlTester::begin_result<Range> adl_begin(Range &&r) { using std::begin; return begin(r); }
+template <typename Range>
+AdlTester::data_result<Range> adl_data(Range &&r) { using std::data; return data(r); }
+template <typename Range>
+AdlTester::size_result<Range> adl_size(Range &&r) { using std::size; return size(r); }
+
+// Replacement for std::ranges::iterator_t (which depends on C++20 std::ranges::begin)
+// This one uses adl_begin() instead.
+template <typename Range>
+using iterator_t = decltype(QSpanPrivate::adl_begin(std::declval<Range&>()));
+template <typename Range>
+using range_reference_t = q20::iter_reference_t<QSpanPrivate::iterator_t<Range>>;
+
+template <typename T>
+class QSpanCommon {
+protected:
+ template <typename Iterator>
+ using is_compatible_iterator = std::conjunction<
+ // ### C++20: extend to contiguous_iteratorss
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<Iterator>::iterator_category
+ >,
+ is_qualification_conversion<
+ std::remove_reference_t<q20::iter_reference_t<Iterator>>,
+ T
+ >
+ >;
+ template <typename Iterator, typename End>
+ using is_compatible_iterator_and_sentinel = std::conjunction<
+ // ### C++20: extend to contiguous_iterators and real sentinels
+ is_compatible_iterator<Iterator>,
+ std::negation<std::is_convertible<End, std::size_t>>
+ >;
+ template <typename Range, typename = void> // wrap use of SFINAE-unfriendly iterator_t:
+ struct is_compatible_range_helper : std::false_type {};
+ template <typename Range>
+ struct is_compatible_range_helper<Range, std::void_t<QSpanPrivate::iterator_t<Range>>>
+ : is_compatible_iterator<QSpanPrivate::iterator_t<Range>> {};
+ template <typename Range>
+ using is_compatible_range = std::conjunction<
+ // ### C++20: extend to contiguous_iterators
+ std::negation<is_qspan<Range>>,
+ std::negation<is_std_span<Range>>,
+ std::negation<is_std_array<Range>>,
+ std::negation<std::is_array<q20::remove_cvref_t<Range>>>,
+ is_compatible_range_helper<Range>
+ >;
+
+ // constraints
+ template <typename Iterator>
+ using if_compatible_iterator = std::enable_if_t<
+ is_compatible_iterator<Iterator>::value
+ , bool>;
+ template <typename Iterator, typename End>
+ using if_compatible_iterator_and_sentinel = std::enable_if_t<
+ is_compatible_iterator_and_sentinel<Iterator, End>::value
+ , bool>;
+ template <typename Range>
+ using if_compatible_range = std::enable_if_t<is_compatible_range<Range>::value, bool>;
+}; // class QSpanCommon
+
+template <typename T, std::size_t E>
+class QSpanBase : protected QSpanCommon<T>
+{
+ static_assert(E < size_t{(std::numeric_limits<qsizetype>::max)()},
+ "QSpan only supports extents that fit into the signed size type (qsizetype).");
+
+ struct Enabled_t { explicit Enabled_t() = default; };
+ static inline constexpr Enabled_t Enable{};
+
+ template <typename S, std::size_t N>
+ using if_compatible_array = std::enable_if_t<
+ N == E && is_qualification_conversion_v<S, T>
+ , bool>;
+
+ template <typename S>
+ using if_qualification_conversion = std::enable_if_t<
+ is_qualification_conversion_v<S, T>
+ , bool>;
+protected:
+ using Base = QSpanCommon<T>;
+
+ // data members:
+ T *m_data;
+ static constexpr qsizetype m_size = qsizetype(E);
+
+ // types and constants:
+ // (in QSpan only)
+
+ // constructors (need to be public d/t the way ctor inheriting works):
+public:
+ template <std::size_t E2 = E, std::enable_if_t<E2 == 0, bool> = true>
+ Q_IMPLICIT constexpr QSpanBase() noexcept : m_data{nullptr} {}
+
+ template <typename It, typename Base::template if_compatible_iterator<It> = true>
+ explicit constexpr QSpanBase(It first, qsizetype count)
+ : m_data{q20::to_address(first)}
+ {
+ Q_ASSERT(count == m_size);
+ }
+
+ template <typename It, typename End, typename Base::template if_compatible_iterator_and_sentinel<It, End> = true>
+ explicit constexpr QSpanBase(It first, End last)
+ : QSpanBase(first, last - first) {}
+
+ template <size_t N, std::enable_if_t<N == E, bool> = true>
+ Q_IMPLICIT constexpr QSpanBase(q20::type_identity_t<T> (&arr)[N]) noexcept
+ : QSpanBase(arr, N) {}
+
+ template <typename S, size_t N, if_compatible_array<S, N> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::array<S, N> &arr) noexcept
+ : QSpanBase(arr.data(), N) {}
+
+ template <typename S, size_t N, if_compatible_array<S, N> = true>
+ Q_IMPLICIT constexpr QSpanBase(const std::array<S, N> &arr) noexcept
+ : QSpanBase(arr.data(), N) {}
+
+ template <typename Range, typename Base::template if_compatible_range<Range> = true>
+ Q_IMPLICIT constexpr QSpanBase(Range &&r)
+ : QSpanBase(QSpanPrivate::adl_data(r), // no forward<>() here (std doesn't have it, either)
+ qsizetype(QSpanPrivate::adl_size(r))) // ditto, no forward<>()
+ {}
+
+ template <typename S, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(QSpan<S, E> other) noexcept
+ : QSpanBase(other.data(), other.size())
+ {}
+
+ template <typename S, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(QSpan<S> other)
+ : QSpanBase(other.data(), other.size())
+ {}
+
+ template <typename U = T, std::enable_if_t<std::is_const_v<U>, bool> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::initializer_list<std::remove_cv_t<T>> il)
+ : QSpanBase(il.begin(), il.size())
+ {}
+
+#ifdef __cpp_lib_span
+ template <typename S, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::span<S, E> other) noexcept
+ : QSpanBase(other.data(), other.size())
+ {}
+
+ template <typename S, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::span<S> other)
+ : QSpanBase(other.data(), other.size())
+ {}
+#endif // __cpp_lib_span
+}; // class QSpanBase (fixed extent)
+
+template <typename T>
+class QSpanBase<T, q20::dynamic_extent> : protected QSpanCommon<T>
+{
+ template <typename S>
+ using if_qualification_conversion = std::enable_if_t<
+ is_qualification_conversion_v<S, T>
+ , bool>;
+protected:
+ using Base = QSpanCommon<T>;
+
+ // data members:
+ T *m_data;
+ qsizetype m_size;
+
+ // constructors (need to be public d/t the way ctor inheriting works):
+public:
+ Q_IMPLICIT constexpr QSpanBase() noexcept : m_data{nullptr}, m_size{0} {}
+
+ template <typename It, typename Base::template if_compatible_iterator<It> = true>
+ Q_IMPLICIT constexpr QSpanBase(It first, qsizetype count)
+ : m_data{q20::to_address(first)}, m_size{count} {}
+
+ template <typename It, typename End, typename Base::template if_compatible_iterator_and_sentinel<It, End> = true>
+ Q_IMPLICIT constexpr QSpanBase(It first, End last)
+ : QSpanBase(first, last - first) {}
+
+ template <size_t N>
+ Q_IMPLICIT constexpr QSpanBase(q20::type_identity_t<T> (&arr)[N]) noexcept
+ : QSpanBase(arr, N) {}
+
+ template <typename S, size_t N, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::array<S, N> &arr) noexcept
+ : QSpanBase(arr.data(), N) {}
+
+ template <typename S, size_t N, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(const std::array<S, N> &arr) noexcept
+ : QSpanBase(arr.data(), N) {}
+
+ template <typename Range, typename Base::template if_compatible_range<Range> = true>
+ Q_IMPLICIT constexpr QSpanBase(Range &&r)
+ : QSpanBase(QSpanPrivate::adl_data(r), // no forward<>() here (std doesn't have it, either)
+ qsizetype(QSpanPrivate::adl_size(r))) // ditto, no forward<>()
+ {}
+
+ template <typename S, size_t N, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(QSpan<S, N> other) noexcept
+ : QSpanBase(other.data(), other.size())
+ {}
+
+ template <typename U = T, std::enable_if_t<std::is_const_v<U>, bool> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::initializer_list<std::remove_cv_t<T>> il) noexcept
+ : QSpanBase(il.begin(), il.size())
+ {}
+
+#ifdef __cpp_lib_span
+ template <typename S, size_t N, if_qualification_conversion<S> = true>
+ Q_IMPLICIT constexpr QSpanBase(std::span<S, N> other) noexcept
+ : QSpanBase(other.data(), other.size())
+ {}
+#endif // __cpp_lib_span
+}; // class QSpanBase (dynamic extent)
+
+} // namespace QSpanPrivate
+
+template <typename T, std::size_t E>
+class QSpan
+#ifndef Q_QDOC
+ : private QSpanPrivate::QSpanBase<T, E>
+#endif
+{
+ using Base = QSpanPrivate::QSpanBase<T, E>;
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+
+ template <std::size_t N>
+ static constexpr bool subspan_always_succeeds_v = N <= E && E != q20::dynamic_extent;
+public:
+ // constants and types
+ using value_type = std::remove_cv_t<T>;
+#ifdef QT_COMPILER_HAS_LWG3346
+ using iterator_concept = std::contiguous_iterator_tag;
+ using element_type = T;
+#endif
+ using size_type = qsizetype; // difference to std::span
+ using difference_type = qptrdiff; // difference to std::span
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using iterator = pointer; // implementation-defined choice
+ using const_iterator = const_pointer; // implementation-defined choice
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ static constexpr std::size_t extent = E;
+
+ // [span.cons], constructors, copy, and assignment
+ using Base::Base;
+#ifdef Q_QDOC
+ template <typename It> using if_compatible_iterator = bool;
+ template <typename S> using if_qualification_conversion = bool;
+ template <typename Range> using if_compatible_range = bool;
+ template <typename It, if_compatible_iterator<It> = true> constexpr QSpan(It first, qsizetype count);
+ template <typename It, if_compatible_iterator<It> = true> constexpr QSpan(It first, It last);
+ template <size_t N> constexpr QSpan(q20::type_identity_t<T> (&arr)[N]) noexcept;
+ template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(std::array<S, N> &arr) noexcept;
+ template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(const std::array<S, N> &arr) noexcept;
+ template <typename Range, if_compatible_range<Range> = true> constexpr QSpan(Range &&r);
+ template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(QSpan<S, N> other) noexcept;
+ template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(std::span<S, N> other) noexcept;
+ constexpr QSpan(std::initializer_list<value_type> il);
+#endif // Q_QDOC
+
+ // [span.obs]
+ [[nodiscard]] constexpr size_type size() const noexcept { return this->m_size; }
+ [[nodiscard]] constexpr size_type size_bytes() const noexcept { return size() * sizeof(T); }
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+
+ // [span.elem]
+ [[nodiscard]] constexpr reference operator[](size_type idx) const
+ { verify(idx); return data()[idx]; }
+ [[nodiscard]] constexpr reference front() const { verify(); return *data(); }
+ [[nodiscard]] constexpr reference back() const { verify(); return data()[size() - 1]; }
+ [[nodiscard]] constexpr pointer data() const noexcept { return this->m_data; }
+
+ // [span.iterators]
+ [[nodiscard]] constexpr iterator begin() const noexcept { return data(); }
+ [[nodiscard]] constexpr iterator end() const noexcept { return data() + size(); }
+ [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
+ [[nodiscard]] constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
+ [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // [span.sub]
+ template <std::size_t Count>
+ [[nodiscard]] constexpr QSpan<T, Count> first() const
+ noexcept(subspan_always_succeeds_v<Count>)
+ {
+ static_assert(Count <= E,
+ "Count cannot be larger than the span's extent.");
+ verify(0, Count);
+ return QSpan<T, Count>{data(), Count};
+ }
+
+ template <std::size_t Count>
+ [[nodiscard]] constexpr QSpan<T, Count> last() const
+ noexcept(subspan_always_succeeds_v<Count>)
+ {
+ static_assert(Count <= E,
+ "Count cannot be larger than the span's extent.");
+ verify(0, Count);
+ return QSpan<T, Count>{data() + (size() - Count), Count};
+ }
+
+ template <std::size_t Offset>
+ [[nodiscard]] constexpr auto subspan() const
+ noexcept(subspan_always_succeeds_v<Offset>)
+ {
+ static_assert(Offset <= E,
+ "Offset cannot be larger than the span's extent.");
+ verify(Offset, 0);
+ if constexpr (E == q20::dynamic_extent)
+ return QSpan<T>{data() + Offset, qsizetype(size() - Offset)};
+ else
+ return QSpan<T, E - Offset>{data() + Offset, qsizetype(E - Offset)};
+ }
+
+ template <std::size_t Offset, std::size_t Count>
+ [[nodiscard]] constexpr auto subspan() const
+ noexcept(subspan_always_succeeds_v<Offset + Count>)
+ { return subspan<Offset>().template first<Count>(); }
+
+ [[nodiscard]] constexpr QSpan<T> first(size_type n) const { verify(0, n); return {data(), n}; }
+ [[nodiscard]] constexpr QSpan<T> last(size_type n) const { verify(0, n); return {data() + (size() - n), n}; }
+ [[nodiscard]] constexpr QSpan<T> subspan(size_type pos) const { verify(pos, 0); return {data() + pos, size() - pos}; }
+ [[nodiscard]] constexpr QSpan<T> subspan(size_type pos, size_type n) const { return subspan(pos).first(n); }
+
+ // Qt-compatibility API:
+ [[nodiscard]] bool isEmpty() const noexcept { return empty(); }
+ // nullary first()/last() clash with first<>() and last<>(), so they're not provided for QSpan
+ [[nodiscard]] constexpr QSpan<T> sliced(size_type pos) const { return subspan(pos); }
+ [[nodiscard]] constexpr QSpan<T> sliced(size_type pos, size_type n) const { return subspan(pos, n); }
+
+}; // class QSpan
+
+// [span.deduct]
+template <class It, class EndOrSize>
+QSpan(It, EndOrSize) -> QSpan<std::remove_reference_t<q20::iter_reference_t<It>>>;
+template <class T, std::size_t N>
+QSpan(T (&)[N]) -> QSpan<T, N>;
+template <class T, std::size_t N>
+QSpan(std::array<T, N> &) -> QSpan<T, N>;
+template <class T, std::size_t N>
+QSpan(const std::array<T, N> &) -> QSpan<const T, N>;
+template <class R>
+QSpan(R&&) -> QSpan<std::remove_reference_t<QSpanPrivate::range_reference_t<R>>>;
+
+QT_END_NAMESPACE
+
+#endif // QSPAN_H
diff --git a/src/corelib/tools/qspan.qdoc b/src/corelib/tools/qspan.qdoc
new file mode 100644
index 0000000000..472f122877
--- /dev/null
+++ b/src/corelib/tools/qspan.qdoc
@@ -0,0 +1,651 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \class QSpan
+ \inmodule QtCore
+ \since 6.7
+ \brief A non-owning container over contiguous data.
+ \ingroup tools
+ \reentrant
+
+ A QSpan references a contiguous portion of another contiguous container.
+ It acts as an interface type for all kinds of contiguous containers,
+ without the need to construct an owning container such as QList or
+ std::vector first.
+
+ The data referenced by a QSpan may be represented as an array (or
+ array-compatible data-structure such as QList, std::vector,
+ QVarLengthArray, etc.). QSpan itself merely stores a pointer to the data,
+ so users must ensure that QSpan objects do not outlive the data they
+ reference.
+
+ Unlike views such as QStringView, QLatin1StringView and QUtf8StringView,
+ referenced data can be modified through a QSpan object. To prevent this,
+ construct a QSpan over a \c{const T}:
+
+ \code
+ int numbers[] = {0, 1, 2};
+ QSpan<int> span = numbers;
+ span[0] = 42;
+ // numbers == {42, 1, 2};
+ QSpan<const int> cspan = numbers;
+ cspan[0] = 0; // ERROR: cspan[0] is read-only
+ \endcode
+
+ A QSpan can be \e{fixed-size} or \e{variable-sized}.
+
+ A variable-sized span is formed by omitting the second template argument
+ (or setting it to \c{std::dynamic_extent}, which is, however, only
+ available in C++20 builds), as seen in the example above.
+
+ A fixed-size span is formed by passing a number as the second template
+ argument:
+
+ \code
+ int numbers[] = {0, 1, 2};
+ QSpan<int, 3> span = numbers;
+ QSpan<const int, 3> = numbers; // also OK
+ \endcode
+
+ As the name suggests, a fixed-size span's size() is fixed at compile-time
+ whereas the size() of a variable-sized span is determined only at run-time.
+
+ A fixed-size span is not default-constructible (unless its \l extent is zero
+ (0)). A variable-sized span \e{is} default-constructible and will have
+ \c{data() == nullptr} and \c{size() == 0}.
+
+ A fixed-size span can be implicitly converted into a variable-sized one.
+ The opposite direction (variable-length into fixed-length) has the
+ precondition that both span's sizes must match.
+
+ Unlike with owning containers, \c{const} is \e{shallow} in QSpan: you can
+ still modify the data through a const QSpan (but not through a
+ \c{QSpan<const T>}), and begin() and end() are not overloaded on
+ \c{const}/non-\c{const}. There are cbegin() and cend(), though, that return
+ const_iterators which prevent modification of the data even though \c{T} is
+ not const:
+ \code
+ int numbers[] = {0, 1, 2};
+ const QSpan<int> span = numbers;
+ span.front() = 42; // OK, numbers[0] == 42 now
+ *span.begin() = 31; // OK, numbers[0] == 31 now
+ *span.cbegin() = -1; // ERROR: cannot assign through a const_iterator
+ \endcode
+
+ QSpan should be passed by value, not by reference-to-const:
+
+ \code
+ void consume(QSpan<const int> data); // OK
+ void consume(const QSpan<const int> &data); // works, but is non-idiomatic and less efficient
+ \endcode
+
+ \c{QSpan<T,N>} is a \e{Literal Type}, regardless of whether \c{T} is a
+ Literal Type or not.
+
+ \section2 QSpan vs. std::span
+ \target span-STL
+
+ QSpan is closely modelled after
+ \l{https://en.cppreference.com/w/cpp/container/span}{std::span}, but has a
+ few differences which we'll discuss here. Since they both implicitly
+ convert into each other, you're free to choose whichever one you like best
+ in your own code.
+
+ \list
+ \li QSpan is using the signed qsizetype as \c{size_type}
+ whereas \c{std::span} uses \c{size_t}.
+ \li All QSpan constructors are implicit;
+ many \c{std::span} ones are \c{explicit}.
+ \li QSpan can be constructed from rvalue owning containers, \c{std::span} can not.
+ \endlist
+
+ The last two are required for source-compatibility when functions that took
+ owning containers are converted to take QSpan instead, which is a
+ vitally-important use-case in Qt. The use of qsizetype is for consistency
+ with the rest of Qt containers. QSpan template arguments still use size_t
+ to avoid introducing unnecessary error conditions (negative sizes).
+
+ \section2 Compatible Iterators
+ \target span-compatible-iterators
+
+ QSpan can be constructed from an iterator and size or from an
+ iterator pair, provided the iterators are \e{compatible} ones.
+ Eventually, this should mean C++20 \c{std::contiguous_iterator} and
+ \c{std::sentinel_for}, but while Qt still supports C++17, only raw pointers
+ are considered contiguous iterators.
+
+ \section2 Compatible Ranges
+ \target span-compatible-ranges
+
+ QSpan can also be constructed from a \e{compatible} range. A range is
+ compatible if it has \l{span-compatible-iterators}{compatible iterators}.
+
+ \sa QList, QStringView, QLatin1StringView, QUtf8StringView
+*/
+
+//
+// Nested types and constants
+//
+
+/*!
+ \typedef QSpan::element_type
+
+ An alias for \c{T}. Includes the \c{const}, if any.
+
+ This alias is provided for compatbility with the STL.
+
+ \sa value_type, pointer
+*/
+
+/*!
+ \typedef QSpan::value_type
+
+ An alias for \c{T}. Excludes the \c{const}, if any.
+
+ This alias is provided for compatbility with the STL.
+
+ \sa element_type
+*/
+
+/*!
+ \typedef QSpan::size_type
+
+ An alias for qsizetype. This \l{span-STL}{differs from \c{std::span}}.
+
+ This alias is provided for compatbility with the STL.
+*/
+
+/*!
+ \typedef QSpan::difference_type
+
+ An alias for qptrdiff. This \l{span-STL}{differs from \c{std::span}}.
+
+ This alias is provided for compatbility with the STL.
+*/
+
+/*!
+ \typedef QSpan::pointer
+
+ An alias for \c{T*} and \c{element_type*}, respectively. Includes the \c{const}, if any.
+
+ This alias is provided for compatbility with the STL.
+
+ \sa element_type, const_pointer, reference, iterator
+*/
+
+/*!
+ \typedef QSpan::const_pointer
+
+ An alias for \c{const T*} and \c{const element_type*}, respectively.
+
+ This alias is provided for compatbility with the STL.
+
+ \sa element_type, pointer, const_reference, const_iterator
+*/
+
+/*!
+ \typedef QSpan::reference
+
+ An alias for \c{T&} and \c{element_type&}, respectively. Includes the \c{const}, if any.
+
+ This alias is provided for compatbility with the STL.
+
+ \sa element_type, const_reference, pointer
+*/
+
+/*!
+ \typedef QSpan::const_reference
+
+ An alias for \c{const T&} and \c{const element_type&}, respectively.
+
+ This alias is provided for compatbility with the STL.
+
+ \sa element_type, reference, const_pointer
+*/
+
+/*!
+ \typedef QSpan::iterator
+
+ An alias for \c{T*} and \c{pointer}, respectively. Includes the \c{const}, if any.
+
+ \sa pointer, const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QSpan::const_iterator
+
+ An alias for \c{const T*} and \c{const_pointer}, respectively.
+
+ \sa const_pointer, iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QSpan::reverse_iterator
+
+ An alias for \c{std::reverse_iterator<iterator>}. Includes the \c{const}, if any.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QSpan::const_reverse_iterator
+
+ An alias for \c{std::reverse_iterator<const_iterator>}.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \variable QSpan::extent
+
+ The second template argument of \c{QSpan<T, E>}, that is, \c{E}. This is
+ \c{std::dynamic_extent} for variable-sized spans.
+
+ \note While all other sizes and indexes in QSpan use qsizetype, this
+ variable, like \c{E}, is actually of type \c{size_t}, for compatibility with
+ \c{std::span} and \c{std::dynamic_extent}.
+
+ \sa size()
+*/
+
+//
+// Constructors and SMFs
+//
+
+/*!
+ \fn template <typename T, size_t E> QSpan<T,E>::QSpan()
+
+ Default constructor.
+
+ This constructor is only present if \c{E} is either zero (0) or
+ \c{std::dynamic_extent}. In other words: only fixed-zero-sized or variable-sized spans
+ are default-constructible.
+
+ \sa extent
+*/
+
+/*!
+ \fn template <typename T, size_t E> QSpan<T,E>::QSpan(const QSpan &other)
+ \fn template <typename T, size_t E> QSpan<T,E>::QSpan(QSpan &&other)
+ \fn template <typename T, size_t E> QSpan<T,E> &QSpan<T,E>::operator=(const QSpan &other)
+ \fn template <typename T, size_t E> QSpan<T,E> &QSpan<T,E>::operator=(QSpan &&other)
+ \fn template <typename T, size_t E> QSpan<T,E>::~QSpan()
+
+ These Special Member Functions are implicitly-defined.
+
+ \note Moves are equivalent to copies. Only data() and size() are copied
+ from span to span, not the referenced data.
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <typename It, QSpan<T, E>::if_compatible_iterator<It>> QSpan<T,E>::QSpan(It first, qsizetype count)
+
+ Constructs a QSpan referencing the data starting at \a first and having length
+ \a count.
+
+ \c{[first, count)} must be a valid range.
+
+ \note This constructor participates in overload resolution only if \c{It}
+ is \l{span-compatible-iterators}{a compatible iterator}.
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <typename It, QSpan<T, E>::if_compatible_iterator<It>> QSpan<T,E>::QSpan(It first, It last)
+
+ Constructs a QSpan referencing the data starting at \a first and having length
+ (\a last - \a first).
+
+ \c{[first, last)} must be a valid range.
+
+ \note This constructor participates in overload resolution only if \c{It}
+ is \l{span-compatible-iterators}{a compatible iterator}.
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <size_t N> QSpan<T,E>::QSpan(q20::type_identity_t<T> (&arr)[N]);
+ \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(std::array<S, N> &arr);
+ \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(const std::array<S, N> &arr);
+
+ Constructs a QSpan referencing the data in the supplied array \a arr.
+
+ \note This constructor participates in overload resolution only if
+ \list
+ \li either \c{N} or \l{extent} are \c{std::dynamic_extent} or otherwise \l{extent} \c{==} \c{N}
+ \li and either \c{S} or \c{const S} are the same as \c{T}.
+ \endlist
+
+ \note \c{q20::type_identity_t} is a C++17 backport of C++20's
+ \l{https://en.cppreference.com/w/cpp/types/type_identity}{\c{std::type_identity_t}}.
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <typename Range, QSpan<T, E>::if_compatible_range<Range> = true> QSpan<T,E>::QSpan(Range &&r)
+
+ Constructs a QSpan referencing the data in the supplied range \a r.
+
+ \note This constructor participates in overload resolution only if \c{Range}
+ is \l{span-compatible-ranges}{a compatible range}.
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(QSpan<S, N> other);
+ \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(std::span<S, N> other);
+
+ Constructs a QSpan referencing the data in the supplied span \a other.
+
+ \note This constructor participates in overload resolution only if
+ \list
+ \li either \c{N} or \l{extent} are \c{std::dynamic_extent} or \l{extent} \c{==} \c{N}
+ \li and either \c{S} or \c{const S} are the same as \c{T}.
+ \endlist
+*/
+
+/*!
+ \fn template <typename T, size_t E> QSpan<T, E>::QSpan(std::initializer_list<value_type> il);
+
+ Constructs a QSpan referencing the data in the supplied initializer list \a il.
+
+ \note This constructor participates in overload resolution only if \c{T} is \c{const}-qualified.
+
+ \note This constructor is \c{noexcept} only if \c{E} is \c{std::dynamic_extent}.
+
+ \note If \c{E} is not \c{std::dynamic_extent} and the size of \a il is not \c{E}, the behavior is undefined.
+*/
+
+//
+// Member functions: sizes
+//
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::size() const
+
+ Returns the size of the span, that is, the number of elements it references.
+
+ \sa size_bytes(), empty(), isEmpty()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::size_bytes() const
+
+ Returns the size of the span in bytes, that is, the number of elements
+ multiplied by \c{sizeof(T)}.
+
+ \sa size(), empty(), isEmpty()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::empty() const
+ \fn template <typename T, size_t E> auto QSpan<T, E>::isEmpty() const
+
+ Returns whether the span is empty, that is, whether \c{size() == 0}.
+
+ These functions do the same thing: empty() is provided for STL
+ compatibility and isEmpty() is provided for Qt compatibility.
+
+ \sa size(), size_bytes()
+*/
+
+//
+// element access
+//
+
+/*!
+ \fn template <typename T, size_t E> QSpan<T, E>::operator[](size_type idx) const
+
+ Returns a reference to the element at index \a idx in the span.
+
+ The index must be in range, that is, \a idx >= 0 and \a idx < size(),
+ otherwise the behavior is undefined.
+
+ \sa front(), back(), size(), empty()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::front() const
+
+ Returns a reference to the first element in the span.
+
+ The span must not be empty, otherwise the behavior is undefined.
+
+ \sa operator[](), back(), size(), empty()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::back() const
+
+ Returns a reference to the last element in the span.
+
+ The span must not be empty, otherwise the behavior is undefined.
+
+ \sa operator[](), front(), size(), empty()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::data() const
+
+ Returns a pointer to the beginning of the span.
+
+ The same as calling begin().
+
+ \sa begin(), front()
+*/
+
+//
+// iterators
+//
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::begin() const
+
+ Returns an interator pointing at the beginning of the span.
+
+ Because QSpan iterators are just pointers, this is the same as calling
+ data().
+
+ \sa end(), cbegin(), rbegin(), crbegin(), data()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::end() const
+
+ Returns an iterator pointing to one past the end of the span.
+
+ Because QSpan iterators are just pointers, this it the same as calling
+ \c{data() + size()}.
+
+ \sa begin(), cend(), rend(), crend(), data(), size()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::cbegin() const
+
+ Returns a const_iterator pointing to the beginning of the span.
+
+ This will return a read-only iterator even if \c{T} is not \c{const}:
+ \code
+ QSpan<int> span = ~~~;
+ *span.begin() = 42; // OK
+ *span.cbegin() = 42; // ERROR: cannot assign through a const_iterator
+ \endcode
+
+ \sa cend(), begin(), crbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::cend() const
+
+ Returns a const_iterator pointing to one past the end of the span.
+
+ \sa cbegin(), end(), crend(), rend(), data(), size()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::rbegin() const
+
+ Returns a reverse_iterator pointing to the beginning of the reversed span.
+
+ \sa rend(), crbegin(), begin(), cbegin()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::rend() const
+
+ Returns a reverse_iterator pointing to one past the end of the reversed span.
+
+ \sa rbegin(), crend(), end(), cend()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::crbegin() const
+
+ Returns a const_reverse_iterator pointing to the beginning of the reversed span.
+
+ \sa crend(), rbegin(), cbegin(), begin()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::crend() const
+
+ Returns a const_reverse_iterator pointing to one past the end of the reversed span.
+
+ \sa crbegin(), rend(), cend(), end()
+*/
+
+//
+// compile-time subspans:
+//
+
+/*!
+ \fn template <typename T, size_t E> template <std::size_t Count> auto QSpan<T, E>::first() const
+ \keyword first-t
+
+ Returns a fixed-sized span of size \c{Count} referencing the first \c{Count} elements of \c{*this}.
+
+ The span must hold at least \c{Count} elements (\c{E} >= \c{Count} \e{and}
+ size() >= \c{Count}), otherwise the behavior is undefined.
+
+ \sa first(QSpan<T,E>::size_type), last(), subspan()
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <std::size_t Count> auto QSpan<T, E>::last() const
+ \keyword last-t
+
+ Returns a fixed-sized span of size \c{Count} referencing the last \c{Count} elements of \c{*this}.
+
+ The span must hold at least \c{Count} elements (\c{E} >= \c{Count} \e{and}
+ size() >= \c{Count}), otherwise the behavior is undefined.
+
+ \sa last(QSpan<T,E>::size_type), first(), subspan()
+*/
+
+/*!
+ \fn template <typename T, size_t E> template <std::size_t Offset> auto QSpan<T, E>::subspan() const
+ \keyword subspan-t1
+
+ Returns a span of size \c{E - Offset} referencing the remainder of this span
+ after dropping the first \c{Offset} elements.
+
+ If \c{*this} is a variable-sized span, the return type is a variable-sized
+ span, otherwise it is a fixed-sized span.
+
+ This span must hold at least \c{Offset} elements (\c{E} >= \c{Offset} \e{and}
+ size() >= \c{Offset}), otherwise the behavior is undefined.
+
+ \sa subspan(QSpan<T,E>::size_type), subspan(), first(), last()
+*/
+
+#if 0 // needs fix for QTBUG-118080 integrated into qt5.git
+/*!
+ \fn template <typename T, size_t E> template <std::size_t Offset, std::size_t Count> auto QSpan<T, E>::subspan() const
+ \keyword subspan-t2
+
+ Returns a span of size \c{Count} referencing the \c{Count} elements of this
+ span starting at \c{Offset}.
+
+ If \c{*this} is a variable-sized span, the return type is a variable-sized
+ span, otherwise it is a fixed-sized span.
+
+ This span must hold at least \c{Offset + Count} elements (\c{E} >=
+ \c{Offset + Count} \e{and} size() >= \c{Offset + Count}), otherwise the
+ behavior is undefined.
+
+ \sa subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), subspan(), first(), last()
+*/
+#endif
+
+//
+// runtime subspans:
+//
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::first(qsizetype n) const
+ \keyword first-n
+
+ Returns a variable-sized span of size \a n referencing the first \a n elements of \c{*this}.
+
+ \a n must be non-negative.
+
+ The span must hold at least \a n elements (\c{E} >= \a n \e{and} size() >=
+ \a n), otherwise the behavior is undefined.
+
+ \sa {first-t}{first<N>()}, last(QSpan<T,E>::size_type), subspan(QSpan<T,E>::size_type),
+ subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type)
+ \sa sliced()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::last(qsizetype n) const
+ \keyword last-n
+
+ Returns a variable-sized span of size \a n referencing the last \a n elements of \c{*this}.
+
+ \a n must be non-negative.
+
+ The span must hold at least \a n elements (\c{E} >= \a n \e{and}
+ size() >= \a n), otherwise the behavior is undefined.
+
+ \sa last(), first(QSpan<T,E>::size_type), subspan(QSpan<T,E>::size_type),
+ subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), sliced()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::subspan(qsizetype pos) const
+ \fn template <typename T, size_t E> auto QSpan<T, E>::sliced(qsizetype pos) const
+ \keyword subspan-n1
+
+ Returns a variable-sized span of size \c{size() - pos} referencing the
+ remainder of this span after dropping the first \a pos elements.
+
+ \a pos must be non-negative.
+
+ This span must hold at least \a pos elements (\c{E} >= \a pos \e{and}
+ size() >= \a pos), otherwise the behavior is undefined.
+
+ These functions do the same thing: subspan() is provided for STL
+ compatibility and sliced() is provided for Qt compatibility.
+
+ \sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type)
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::subspan(qsizetype pos, qsizetype n) const
+ \fn template <typename T, size_t E> auto QSpan<T, E>::sliced(qsizetype pos, qsizetype n) const
+ \keyword subspan-n2
+
+ Returns a variable-sized span of size \a n referencing the \a n elements of
+ this span starting at \a pos.
+
+ Both \a pos and \a n must be non-negative.
+
+ This span must hold at least \c{pos + n} elements (\c{E} >=
+ \c{pos + n} \e{and} size() >= \c{pos + n}), otherwise the
+ behavior is undefined.
+
+ These functions do the same thing: subspan() is provided for STL
+ compatibility and sliced() is provided for Qt compatibility.
+
+ \sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type)
+*/
+
diff --git a/src/corelib/tools/qspan_p.h b/src/corelib/tools/qspan_p.h
new file mode 100644
index 0000000000..0072e3ef64
--- /dev/null
+++ b/src/corelib/tools/qspan_p.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSPAN_P_H
+#define QSPAN_P_H
+
+#include <QtCore/qspan.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+QT_END_NAMESPACE
+
+#endif // QSPAN_P_H
diff --git a/src/corelib/tools/qstack.cpp b/src/corelib/tools/qstack.cpp
index 849a474d2c..5255e0e100 100644
--- a/src/corelib/tools/qstack.cpp
+++ b/src/corelib/tools/qstack.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QStack
diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h
index a0e39f8ece..11ffb13328 100644
--- a/src/corelib/tools/qstack.h
+++ b/src/corelib/tools/qstack.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTACK_H
#define QSTACK_H
@@ -49,26 +13,13 @@ class QStack : public QList<T>
{
public:
// compiler-generated special member functions are fine!
- inline void swap(QStack<T> &other) noexcept { QList<T>::swap(other); } // prevent QList<->QStack swaps
- inline void push(const T &t) { QList<T>::append(t); }
- T pop();
- T &top();
- const T &top() const;
+ void swap(QStack<T> &other) noexcept { QList<T>::swap(other); } // prevent QList<->QStack swaps
+ void push(const T &t) { QList<T>::append(t); }
+ T pop() { return QList<T>::takeLast(); }
+ T &top() { return QList<T>::last(); }
+ const T &top() const { return QList<T>::last(); }
};
-template<class T>
-inline T QStack<T>::pop()
-{ Q_ASSERT(!this->isEmpty()); T t = this->data()[this->size() -1];
- this->resize(this->size()-1); return t; }
-
-template<class T>
-inline T &QStack<T>::top()
-{ Q_ASSERT(!this->isEmpty()); this->detach(); return this->data()[this->size()-1]; }
-
-template<class T>
-inline const T &QStack<T>::top() const
-{ Q_ASSERT(!this->isEmpty()); return this->data()[this->size()-1]; }
-
QT_END_NAMESPACE
#endif // QSTACK_H
diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h
index 819ebb2387..6c467d59f8 100644
--- a/src/corelib/tools/qtaggedpointer.h
+++ b/src/corelib/tools/qtaggedpointer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTAGGEDPOINTER_H
#define QTAGGEDPOINTER_H
@@ -48,7 +12,7 @@
QT_BEGIN_NAMESPACE
namespace QtPrivate {
- constexpr quint8 nextByteSize(quint8 bits) { return (bits + 7) / 8; }
+ constexpr quint8 nextByteSize(quint8 bits) { return quint8((bits + 7) / 8); }
template <typename T>
struct TagInfo
@@ -57,7 +21,7 @@ namespace QtPrivate {
static_assert((alignment & (alignment - 1)) == 0,
"Alignment of template parameter must be power of two");
- static constexpr quint8 tagBits = QtPrivate::qConstexprCountTrailingZeroBits(alignment);
+ static constexpr quint8 tagBits = quint8{QtPrivate::qConstexprCountTrailingZeroBits(alignment)};
static_assert(tagBits > 0,
"Alignment of template parameter does not allow any tags");
@@ -79,18 +43,17 @@ public:
static constexpr quintptr tagMask() { return QtPrivate::TagInfo<T>::alignment - 1; }
static constexpr quintptr pointerMask() { return ~tagMask(); }
- constexpr QTaggedPointer() noexcept : d(0) {}
- constexpr QTaggedPointer(std::nullptr_t) noexcept : QTaggedPointer() {}
+ Q_NODISCARD_CTOR constexpr QTaggedPointer() noexcept : d(0) {}
+ Q_NODISCARD_CTOR constexpr QTaggedPointer(std::nullptr_t) noexcept : QTaggedPointer() {}
- explicit QTaggedPointer(T *pointer, Tag tag = Tag()) noexcept
- : d(quintptr(pointer))
+ Q_NODISCARD_CTOR explicit QTaggedPointer(T *pointer, Tag tag = Tag()) noexcept
+ : d(quintptr(pointer) | quintptr(tag))
{
static_assert(sizeof(Type*) == sizeof(QTaggedPointer));
- Q_ASSERT_X((quintptr(pointer) & tagMask()) == 0,
- "QTaggedPointer<T, Tag>", "Pointer is not aligned");
-
- setTag(tag);
+ Q_ASSERT_X((quintptr(pointer) & tagMask()) == 0, "QTaggedPointer<T, Tag>", "Pointer is not aligned");
+ Q_ASSERT_X((static_cast<typename QtPrivate::TagInfo<T>::TagType>(tag) & pointerMask()) == 0,
+ "QTaggedPointer<T, Tag>::setTag", "Tag is larger than allowed by number of available tag bits");
}
Type &operator*() const noexcept
@@ -109,12 +72,31 @@ public:
return !isNull();
}
- QTaggedPointer &operator=(T *other) noexcept
+#ifdef Q_QDOC
+ QTaggedPointer &operator=(T *other) noexcept;
+#else
+ // Disables the usage of `ptr = {}`, which would go through this operator
+ // (rather than using the implicitly-generated assignment operator).
+ // The operators have different semantics: the ones here leave the tag intact,
+ // the implicitly-generated one overwrites it.
+ template <typename U,
+ std::enable_if_t<std::is_convertible_v<U *, T *>, bool> = false>
+ QTaggedPointer &operator=(U *other) noexcept
{
- d = reinterpret_cast<quintptr>(other) | (d & tagMask());
+ T *otherT = other;
+ d = reinterpret_cast<quintptr>(otherT) | (d & tagMask());
return *this;
}
+ template <typename U,
+ std::enable_if_t<std::is_null_pointer_v<U>, bool> = false>
+ QTaggedPointer &operator=(U) noexcept
+ {
+ d = reinterpret_cast<quintptr>(static_cast<T *>(nullptr)) | (d & tagMask());
+ return *this;
+ }
+#endif
+
static constexpr Tag maximumTag() noexcept
{
return TagType(typename QtPrivate::TagInfo<T>::TagType(tagMask()));
@@ -122,10 +104,12 @@ public:
void setTag(Tag tag)
{
- Q_ASSERT_X((static_cast<typename QtPrivate::TagInfo<T>::TagType>(tag) & pointerMask()) == 0,
- "QTaggedPointer<T, Tag>::setTag", "Tag is larger than allowed by number of available tag bits");
+ Q_ASSERT_X(
+ (static_cast<quintptr>(tag) & pointerMask()) == 0,
+ "QTaggedPointer<T, Tag>::setTag",
+ "Tag is larger than allowed by number of available tag bits");
- d = (d & pointerMask()) | (static_cast<typename QtPrivate::TagInfo<T>::TagType>(tag) & tagMask());
+ d = (d & pointerMask()) | static_cast<quintptr>(tag);
}
Tag tag() const noexcept
@@ -145,7 +129,7 @@ public:
void swap(QTaggedPointer &other) noexcept
{
- qSwap(d, other.d);
+ std::swap(d, other.d);
}
friend inline bool operator==(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
diff --git a/src/corelib/tools/qtaggedpointer.qdoc b/src/corelib/tools/qtaggedpointer.qdoc
index 303b89232c..f910e35b69 100644
--- a/src/corelib/tools/qtaggedpointer.qdoc
+++ b/src/corelib/tools/qtaggedpointer.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QTaggedPointer
@@ -123,9 +99,9 @@
*/
/*!
- \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!() const noexcept
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!(QTaggedPointer<T, Tag> pointer) noexcept
- Returns \c true if the pointer is \nullptr.
+ Returns \c true if \a pointer is \nullptr.
*/
/*!
@@ -153,7 +129,7 @@
*/
/*!
- \fn template <typename T, typename Tag> Tag QTaggedPointer<T, Tag>::pointer() const noexcept
+ \fn template <typename T, typename Tag> T *QTaggedPointer<T, Tag>::data() const noexcept
Returns the pointer stored in the tagged pointer.
*/
@@ -171,8 +147,7 @@
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator==(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator==(QTaggedPointer<T, Tag> lhs, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
@@ -180,8 +155,7 @@
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator!=(QTaggedPointer lhs, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!=(QTaggedPointer<T, Tag> lhs, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a lhs is not equal to \a rhs; otherwise returns \c false.
@@ -189,35 +163,31 @@
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator==(QTaggedPointer lhs, std::nullptr_t) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator==(QTaggedPointer<T, Tag> lhs, std::nullptr_t) noexcept
Returns \c true if \a lhs refers to \c nullptr.
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator==(std::nullptr_t, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator==(std::nullptr_t, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a rhs refers to \c nullptr.
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator!=(QTaggedPointerlhs, std::nullptr_t) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!=(QTaggedPointer<T, Tag> lhs, std::nullptr_t) noexcept
Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
*/
/*!
- \fn template <typename T, typename Tag> inline bool operator!=(std::nullptr_t, QTaggedPointer rhs) noexcept
- \relates QTaggedPointer
+ \fn template <typename T, typename Tag> bool QTaggedPointer<T, Tag>::operator!=(std::nullptr_t, QTaggedPointer<T, Tag> rhs) noexcept
Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
*/
/*!
- \fn template <typename T, typename Tag> qHash(QTaggedPointer<T, Tag> key, std::size_t seed)
+ \fn template <typename T, typename Tag> qHash(QTaggedPointer<T, Tag> key, std::size_t seed = 0)
\relates QTaggedPointer
Returns the hash value for the \a key, using \a seed to seed the calculation.
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 0b11e7c77b..5512da867f 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtimeline.h"
+#include <private/qproperty_p.h>
#include <private/qobject_p.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmath.h>
@@ -50,31 +15,29 @@ class QTimeLinePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTimeLine)
public:
- inline QTimeLinePrivate()
- : easingCurve(QEasingCurve::InOutSine),
- startTime(0), duration(1000), startFrame(0), endFrame(0),
- updateInterval(1000 / 25),
- totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
- direction(QTimeLine::Forward),
- state(QTimeLine::NotRunning)
- { }
-
QElapsedTimer timer;
- QEasingCurve easingCurve;
-
- int startTime;
- int duration;
- int startFrame;
- int endFrame;
- int updateInterval;
- int totalLoopCount;
- int currentLoopCount;
-
- int currentTime;
- int timerId;
-
- QTimeLine::Direction direction;
- QTimeLine::State state;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, QEasingCurve, easingCurve,
+ QEasingCurve::InOutSine)
+
+ int startTime = 0;
+ void setDuration(int duration) { q_func()->setDuration(duration); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, duration,
+ &QTimeLinePrivate::setDuration, 1000)
+ int startFrame = 0;
+ int endFrame = 0;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, updateInterval, 1000 / 25)
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, loopCount, 1)
+ int currentLoopCount = 0;
+
+ void setCurrentTimeForwardToQ(int time) { q_func()->setCurrentTime(time); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, currentTime,
+ &QTimeLinePrivate::setCurrentTimeForwardToQ, 0)
+ int timerId = 0;
+
+ void setDirection(QTimeLine::Direction direction) { q_func()->setDirection(direction); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, QTimeLine::Direction, direction,
+ &QTimeLinePrivate::setDirection, QTimeLine::Forward)
+ QTimeLine::State state = QTimeLine::NotRunning;
inline void setState(QTimeLine::State newState)
{
Q_Q(QTimeLine);
@@ -91,42 +54,45 @@ public:
void QTimeLinePrivate::setCurrentTime(int msecs)
{
Q_Q(QTimeLine);
+ currentTime.removeBindingUnlessInWrapper();
+ const auto previousCurrentTime = currentTime.valueBypassingBindings();
- qreal lastValue = q->currentValue();
- int lastFrame = q->currentFrame();
+ const qreal lastValue = q->valueForTime(previousCurrentTime);
+ const int lastFrame = q->frameForTime(previousCurrentTime);
// Determine if we are looping.
- int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
- int loopCount = elapsed / duration;
+ const int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
+ const int loopCountNow = elapsed / duration;
- bool looping = (loopCount != currentLoopCount);
+ const bool looping = (loopCountNow != currentLoopCount);
#ifdef QTIMELINE_DEBUG
- qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount
- << "currentLoopCount" << currentLoopCount
- << "looping" << looping;
+ qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCountNow"
+ << loopCountNow << "currentLoopCount" << currentLoopCount << "looping" << looping;
#endif
if (looping)
- currentLoopCount = loopCount;
+ currentLoopCount = loopCountNow;
// Normalize msecs to be between 0 and duration, inclusive.
- currentTime = elapsed % duration;
- if (direction == QTimeLine::Backward)
- currentTime = duration - currentTime;
+ currentTime.setValueBypassingBindings(elapsed % duration);
+ if (direction.value() == QTimeLine::Backward)
+ currentTime.setValueBypassingBindings(duration - currentTime.valueBypassingBindings());
// Check if we have reached the end of loopcount.
bool finished = false;
- if (totalLoopCount && currentLoopCount >= totalLoopCount) {
+ if (loopCount && currentLoopCount >= loopCount) {
finished = true;
- currentTime = (direction == QTimeLine::Backward) ? 0 : duration;
- currentLoopCount = totalLoopCount - 1;
+ currentTime.setValueBypassingBindings((direction == QTimeLine::Backward) ? 0 : duration);
+ currentLoopCount = loopCount - 1;
}
- int currentFrame = q->frameForTime(currentTime);
+ const int currentFrame = q->frameForTime(currentTime.valueBypassingBindings());
#ifdef QTIMELINE_DEBUG
- qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame;
+ qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime"
+ << currentTime.valueBypassingBindings() << currentFrame;
#endif
- if (!qFuzzyCompare(lastValue, q->currentValue()))
- emit q->valueChanged(q->currentValue(), QTimeLine::QPrivateSignal());
+ const qreal currentValue = q->valueForTime(currentTime.valueBypassingBindings());
+ if (!qFuzzyCompare(lastValue, currentValue))
+ emit q->valueChanged(currentValue, QTimeLine::QPrivateSignal());
if (lastFrame != currentFrame) {
const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
if (looping && !finished && transitionframe != currentFrame) {
@@ -159,6 +125,13 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
q->stop();
emit q->finished(QTimeLine::QPrivateSignal());
}
+ if (currentTime.valueBypassingBindings() != previousCurrentTime)
+ currentTime.notify();
+}
+QBindable<int> QTimeLine::bindableCurrentTime()
+{
+ Q_D(QTimeLine);
+ return &d->currentTime;
}
/*!
@@ -185,7 +158,7 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
\snippet code/src_corelib_tools_qtimeline.cpp 0
- By default the timeline runs once, from the beginning and towards the end,
+ By default the timeline runs once, from its beginning to its end,
upon which you must call start() again to restart from the beginning. To
make the timeline loop, you can call setLoopCount(), passing the number of
times the timeline should run before finishing. The direction can also be
@@ -193,8 +166,8 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
setDirection(). You can also pause and unpause the timeline while it's
running by calling setPaused(). For interactive control, the
setCurrentTime() function is provided, which sets the time position of the
- time line directly. Although most useful in NotRunning state, (e.g.,
- connected to a valueChanged() signal in a QSlider,) this function can be
+ time line directly. Although most useful in NotRunning state (e.g.,
+ connected to a valueChanged() signal in a QSlider), this function can be
called at any time.
The frame interface is useful for standard widgets, but QTimeLine can be
@@ -205,13 +178,12 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
step. When running, QTimeLine generates values between 0 and 1 by calling
valueForTime() and emitting valueChanged(). By default, valueForTime()
applies an interpolation algorithm to generate these value. You can choose
- from a set of predefined timeline algorithms by calling
- setCurveShape().
+ from a set of predefined timeline algorithms by calling setEasingCurve().
- Note that by default, QTimeLine uses the EaseInOut curve shape,
- which provides a value that grows slowly, then grows steadily, and
- finally grows slowly. For a custom timeline, you can reimplement
- valueForTime(), in which case QTimeLine's curveShape property is ignored.
+ Note that, by default, QTimeLine uses QEasingCurve::InOutSine, which
+ provides a value that grows slowly, then grows steadily, and finally grows
+ slowly. For a custom timeline, you can reimplement valueForTime(), in which
+ case QTimeLine's easingCurve property is ignored.
\sa QProgressBar, QProgressDialog
*/
@@ -251,24 +223,6 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
*/
/*!
- \enum QTimeLine::CurveShape
-
- This enum describes the default shape of QTimeLine's value curve. The
- default, shape is EaseInOutCurve. The curve defines the relation
- between the value and the timeline.
-
- \value EaseInCurve The value starts growing slowly, then increases in speed.
- \value EaseOutCurve The value starts growing steadily, then ends slowly.
- \value EaseInOutCurve The value starts growing slowly, then runs steadily, then grows slowly again.
- \value LinearCurve The value grows linearly (e.g., if the duration is 1000 ms,
- the value at time 500 ms is 0.5).
- \value SineCurve The value grows sinusoidally.
- \value CosineCurve The value grows cosinusoidally.
-
- \sa setCurveShape()
-*/
-
-/*!
\fn void QTimeLine::valueChanged(qreal value)
QTimeLine emits this signal at regular intervals when in \l Running state,
@@ -338,19 +292,26 @@ QTimeLine::State QTimeLine::state() const
\property QTimeLine::loopCount
\brief the number of times the timeline should loop before it's finished.
- A loop count of of 0 means that the timeline will loop forever.
+ A loop count of 0 means that the timeline will loop forever.
By default, this property contains a value of 1.
*/
int QTimeLine::loopCount() const
{
Q_D(const QTimeLine);
- return d->totalLoopCount;
+ return d->loopCount;
}
+
void QTimeLine::setLoopCount(int count)
{
Q_D(QTimeLine);
- d->totalLoopCount = count;
+ d->loopCount = count;
+}
+
+QBindable<int> QTimeLine::bindableLoopCount()
+{
+ Q_D(QTimeLine);
+ return &d->loopCount;
}
/*!
@@ -362,6 +323,9 @@ void QTimeLine::setLoopCount(int count)
timeline duration, or from the value of the duration and towards 0 after
start() has been called.
+ Any binding of direction will be removed not only by setDirection(),
+ but also by toggleDirection().
+
By default, this property is set to \l Forward.
*/
QTimeLine::Direction QTimeLine::direction() const
@@ -372,9 +336,19 @@ QTimeLine::Direction QTimeLine::direction() const
void QTimeLine::setDirection(Direction direction)
{
Q_D(QTimeLine);
- d->direction = direction;
+ d->direction.removeBindingUnlessInWrapper();
+ const auto previousDirection = d->direction.valueBypassingBindings();
+ d->direction.setValueBypassingBindings(direction);
d->startTime = d->currentTime;
d->timer.start();
+ if (previousDirection != d->direction.valueBypassingBindings())
+ d->direction.notify();
+}
+
+QBindable<QTimeLine::Direction> QTimeLine::bindableDirection()
+{
+ Q_D(QTimeLine);
+ return &d->direction;
}
/*!
@@ -401,7 +375,17 @@ void QTimeLine::setDuration(int duration)
qWarning("QTimeLine::setDuration: cannot set duration <= 0");
return;
}
- d->duration = duration;
+ d->duration.removeBindingUnlessInWrapper();
+ if (duration != d->duration.valueBypassingBindings()) {
+ d->duration.setValueBypassingBindings(duration);
+ d->duration.notify();
+ }
+}
+
+QBindable<int> QTimeLine::bindableDuration()
+{
+ Q_D(QTimeLine);
+ return &d->duration;
}
/*!
@@ -491,59 +475,10 @@ void QTimeLine::setUpdateInterval(int interval)
Q_D(QTimeLine);
d->updateInterval = interval;
}
-
-/*!
- \property QTimeLine::curveShape
- \brief the shape of the timeline curve.
-
- The curve shape describes the relation between the time and value for the
- base implementation of valueForTime().
-
- If you have reimplemented valueForTime(), this value is ignored.
-
- By default, this property is set to \l EaseInOutCurve.
-
- \sa valueForTime()
-*/
-QTimeLine::CurveShape QTimeLine::curveShape() const
-{
- Q_D(const QTimeLine);
- switch (d->easingCurve.type()) {
- default:
- case QEasingCurve::InOutSine:
- return EaseInOutCurve;
- case QEasingCurve::InCurve:
- return EaseInCurve;
- case QEasingCurve::OutCurve:
- return EaseOutCurve;
- case QEasingCurve::Linear:
- return LinearCurve;
- case QEasingCurve::SineCurve:
- return SineCurve;
- case QEasingCurve::CosineCurve:
- return CosineCurve;
- }
- return EaseInOutCurve;
-}
-
-static QEasingCurve::Type convert(QTimeLine::CurveShape shape)
+QBindable<int> QTimeLine::bindableUpdateInterval()
{
- switch (shape) {
-#define CASE(x, y) case QTimeLine::x: return QEasingCurve::y
- CASE(EaseInOutCurve, InOutSine);
- CASE(EaseInCurve, InCurve);
- CASE(EaseOutCurve, OutCurve);
- CASE(LinearCurve, Linear);
- CASE(SineCurve, SineCurve);
- CASE(CosineCurve, CosineCurve);
-#undef CASE
- }
- Q_UNREACHABLE();
-}
-
-void QTimeLine::setCurveShape(CurveShape shape)
-{
- setEasingCurve(convert(shape));
+ Q_D(QTimeLine);
+ return &d->updateInterval;
}
/*!
@@ -552,9 +487,9 @@ void QTimeLine::setCurveShape(CurveShape shape)
\since 4.6
Specifies the easing curve that the timeline will use.
- If both easing curve and curveShape are set, the last set property will
- override the previous one. (If valueForTime() is reimplemented it will
- override both)
+ If valueForTime() is reimplemented, this value is ignored.
+
+ \sa valueForTime()
*/
QEasingCurve QTimeLine::easingCurve() const
@@ -563,12 +498,18 @@ QEasingCurve QTimeLine::easingCurve() const
return d->easingCurve;
}
-void QTimeLine::setEasingCurve(const QEasingCurve& curve)
+void QTimeLine::setEasingCurve(const QEasingCurve &curve)
{
Q_D(QTimeLine);
d->easingCurve = curve;
}
+QBindable<QEasingCurve> QTimeLine::bindableEasingCurve()
+{
+ Q_D(QTimeLine);
+ return &d->easingCurve;
+}
+
/*!
\property QTimeLine::currentTime
\brief the current time of the time line.
@@ -578,6 +519,10 @@ void QTimeLine::setEasingCurve(const QEasingCurve& curve)
value that was current when stop() was called last, or the value set by
setCurrentTime().
+ \note You can bind other properties to currentTime, but it is not
+ recommended setting bindings to it. As animation progresses, the currentTime
+ is updated automatically, which cancels its bindings.
+
By default, this property contains a value of 0.
*/
int QTimeLine::currentTime() const
@@ -639,15 +584,15 @@ int QTimeLine::frameForTime(int msec) const
Reimplement this function to provide a custom curve shape for your
timeline.
- \sa CurveShape, frameForTime()
+ \sa easingCurve, frameForTime()
*/
qreal QTimeLine::valueForTime(int msec) const
{
Q_D(const QTimeLine);
- msec = qMin(qMax(msec, 0), d->duration);
+ msec = qBound(0, msec, d->duration.value());
- qreal value = msec / qreal(d->duration);
- return d->easingCurve.valueForProgress(value);
+ qreal value = msec / qreal(d->duration.value());
+ return d->easingCurve.value().valueForProgress(value);
}
/*!
@@ -751,6 +696,8 @@ void QTimeLine::setPaused(bool paused)
Toggles the direction of the timeline. If the direction was Forward, it
becomes Backward, and vice verca.
+ Existing bindings of \l direction are removed.
+
\sa setDirection()
*/
void QTimeLine::toggleDirection()
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
index 9a60cd679f..4bdcceaebd 100644
--- a/src/corelib/tools/qtimeline.h
+++ b/src/corelib/tools/qtimeline.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTIMELINE_H
#define QTIMELINE_H
@@ -54,13 +18,14 @@ class QTimeLinePrivate;
class Q_CORE_EXPORT QTimeLine : public QObject
{
Q_OBJECT
- Q_PROPERTY(int duration READ duration WRITE setDuration)
- Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval)
- Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime)
- Q_PROPERTY(Direction direction READ direction WRITE setDirection)
- Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
- Q_PROPERTY(CurveShape curveShape READ curveShape WRITE setCurveShape)
- Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
+ Q_PROPERTY(int duration READ duration WRITE setDuration BINDABLE bindableDuration)
+ Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval
+ BINDABLE bindableUpdateInterval)
+ Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime BINDABLE bindableCurrentTime)
+ Q_PROPERTY(Direction direction READ direction WRITE setDirection BINDABLE bindableDirection)
+ Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount BINDABLE bindableLoopCount)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve
+ BINDABLE bindableEasingCurve)
public:
enum State {
NotRunning,
@@ -71,14 +36,6 @@ public:
Forward,
Backward
};
- enum CurveShape {
- EaseInCurve,
- EaseOutCurve,
- EaseInOutCurve,
- LinearCurve,
- SineCurve,
- CosineCurve
- };
explicit QTimeLine(int duration = 1000, QObject *parent = nullptr);
virtual ~QTimeLine();
@@ -87,12 +44,15 @@ public:
int loopCount() const;
void setLoopCount(int count);
+ QBindable<int> bindableLoopCount();
Direction direction() const;
void setDirection(Direction direction);
+ QBindable<Direction> bindableDirection();
int duration() const;
void setDuration(int duration);
+ QBindable<int> bindableDuration();
int startFrame() const;
void setStartFrame(int frame);
@@ -102,14 +62,14 @@ public:
int updateInterval() const;
void setUpdateInterval(int interval);
-
- CurveShape curveShape() const;
- void setCurveShape(CurveShape shape);
+ QBindable<int> bindableUpdateInterval();
QEasingCurve easingCurve() const;
void setEasingCurve(const QEasingCurve &curve);
+ QBindable<QEasingCurve> bindableEasingCurve();
int currentTime() const;
+ QBindable<int> bindableCurrentTime();
int currentFrame() const;
qreal currentValue() const;
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index 7a1e2b064f..105aa40c02 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTOOLS_P_H
#define QTOOLS_P_H
@@ -52,22 +16,32 @@
//
#include "QtCore/private/qglobal_p.h"
+
+#include <chrono>
#include <limits.h>
+#include <time.h>
QT_BEGIN_NAMESPACE
namespace QtMiscUtils {
-Q_DECL_CONSTEXPR inline char toHexUpper(uint value) noexcept
+constexpr inline char toHexUpper(char32_t value) noexcept
{
return "0123456789ABCDEF"[value & 0xF];
}
-Q_DECL_CONSTEXPR inline char toHexLower(uint value) noexcept
+constexpr inline char toHexLower(char32_t value) noexcept
{
return "0123456789abcdef"[value & 0xF];
}
-Q_DECL_CONSTEXPR inline int fromHex(uint c) noexcept
+[[nodiscard]] constexpr inline bool isHexDigit(char32_t c) noexcept
+{
+ return (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'F')
+ || (c >= 'a' && c <= 'f');
+}
+
+constexpr inline int fromHex(char32_t c) noexcept
{
return ((c >= '0') && (c <= '9')) ? int(c - '0') :
((c >= 'A') && (c <= 'F')) ? int(c - 'A' + 10) :
@@ -75,32 +49,83 @@ Q_DECL_CONSTEXPR inline int fromHex(uint c) noexcept
/* otherwise */ -1;
}
-Q_DECL_CONSTEXPR inline char toOct(uint value) noexcept
+constexpr inline char toOct(char32_t value) noexcept
{
return char('0' + (value & 0x7));
}
-Q_DECL_CONSTEXPR inline int fromOct(uint c) noexcept
+[[nodiscard]] constexpr inline bool isOctalDigit(char32_t c) noexcept
{
- return ((c >= '0') && (c <= '7')) ? int(c - '0') : -1;
+ return c >= '0' && c <= '7';
}
+
+constexpr inline int fromOct(char32_t c) noexcept
+{
+ return isOctalDigit(c) ? int(c - '0') : -1;
}
-// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size.
-enum {
- MaxAllocSize = INT_MAX
-};
+[[nodiscard]] constexpr inline bool isAsciiDigit(char32_t c) noexcept
+{
+ return c >= '0' && c <= '9';
+}
+
+constexpr inline bool isAsciiUpper(char32_t c) noexcept
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+constexpr inline bool isAsciiLower(char32_t c) noexcept
+{
+ return c >= 'a' && c <= 'z';
+}
+
+constexpr inline bool isAsciiLetterOrNumber(char32_t c) noexcept
+{
+ return isAsciiDigit(c) || isAsciiLower(c) || isAsciiUpper(c);
+}
-struct CalculateGrowingBlockSizeResult {
- size_t size;
- size_t elementCount;
+constexpr inline char toAsciiLower(char ch) noexcept
+{
+ return isAsciiUpper(ch) ? ch - 'A' + 'a' : ch;
+}
+
+constexpr inline char toAsciiUpper(char ch) noexcept
+{
+ return isAsciiLower(ch) ? ch - 'a' + 'A' : ch;
+}
+
+constexpr inline int caseCompareAscii(char lhs, char rhs) noexcept
+{
+ const char lhsLower = QtMiscUtils::toAsciiLower(lhs);
+ const char rhsLower = QtMiscUtils::toAsciiLower(rhs);
+ return int(uchar(lhsLower)) - int(uchar(rhsLower));
+}
+
+constexpr inline int isAsciiPrintable(char32_t ch) noexcept
+{
+ return ch >= ' ' && ch < 0x7f;
+}
+
+constexpr inline int qt_lencmp(qsizetype lhs, qsizetype rhs) noexcept
+{
+ return lhs == rhs ? 0 :
+ lhs > rhs ? 1 :
+ /* else */ -1 ;
+}
+
+} // namespace QtMiscUtils
+
+struct CalculateGrowingBlockSizeResult
+{
+ qsizetype size;
+ qsizetype elementCount;
};
// Implemented in qarraydata.cpp:
-size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
-qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) noexcept;
+qsizetype Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
+qCalculateBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize = 0) noexcept;
CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
-qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) noexcept ;
+qCalculateGrowingBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize = 0) noexcept ;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qtyperevision.cpp b/src/corelib/tools/qtyperevision.cpp
new file mode 100644
index 0000000000..6426236288
--- /dev/null
+++ b/src/corelib/tools/qtyperevision.cpp
@@ -0,0 +1,217 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qtyperevision.h>
+#include <QtCore/qhashfunctions.h>
+
+#ifndef QT_NO_DATASTREAM
+# include <QtCore/qdatastream.h>
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+# include <QtCore/qdebug.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+
+QT_IMPL_METATYPE_EXTERN(QTypeRevision)
+
+/*!
+ \class QTypeRevision
+ \inmodule QtCore
+ \since 6.0
+ \brief The QTypeRevision class contains a lightweight representation of
+ a version number with two 8-bit segments, major and minor, either
+ of which can be unknown.
+ \compares strong
+
+ Use this class to describe revisions of a type. Compatible revisions can be
+ expressed as increments of the minor version. Breaking changes can be
+ expressed as increments of the major version. The return values of
+ \l QMetaMethod::revision() and \l QMetaProperty::revision() can be passed to
+ \l QTypeRevision::fromEncodedVersion(). The resulting major and minor versions
+ specify in which Qt versions the properties and methods were added.
+
+ \sa QMetaMethod::revision(), QMetaProperty::revision()
+*/
+
+/*!
+ \fn template<typename Integer, QTypeRevision::if_valid_segment_type<Integer> = true> static bool QTypeRevision::isValidSegment(Integer segment)
+
+ Returns true if the given number can be used as either major or minor
+ version in a QTypeRevision. The valid range for \a segment is \c {>= 0} and \c {< 255}.
+*/
+
+/*!
+ \fn QTypeRevision::QTypeRevision()
+
+ Produces an invalid revision.
+
+ \sa isValid()
+*/
+
+/*!
+ \fn template<typename Major, typename Minor, QTypeRevision::if_valid_segment_type<Major> = true, QTypeRevision::if_valid_segment_type<Minor> = true> static QTypeRevision QTypeRevision::fromVersion(Major majorVersion, Minor minorVersion)
+
+ Produces a QTypeRevision from the given \a majorVersion and \a minorVersion,
+ both of which need to be a valid segments.
+
+ \sa isValidSegment()
+*/
+
+/*!
+ \fn template<typename Major, QTypeRevision::if_valid_segment_type<Major> = true> static QTypeRevision QTypeRevision::fromMajorVersion(Major majorVersion)
+
+ Produces a QTypeRevision from the given \a majorVersion with an invalid minor
+ version. \a majorVersion needs to be a valid segment.
+
+ \sa isValidSegment()
+*/
+
+/*!
+ \fn template<typename Minor, QTypeRevision::if_valid_segment_type<Minor> = true> static QTypeRevision QTypeRevision::fromMinorVersion(Minor minorVersion)
+
+ Produces a QTypeRevision from the given \a minorVersion with an invalid major
+ version. \a minorVersion needs to be a valid segment.
+
+ \sa isValidSegment()
+*/
+
+/*!
+ \fn template<typename Integer, QTypeRevision::if_valid_value_type<Integer> = true> static QTypeRevision QTypeRevision::fromEncodedVersion(Integer value)
+
+ Produces a QTypeRevision from the given \a value. \a value encodes both the
+ minor and major versions in the least significant and second least
+ significant byte, respectively.
+
+ \a value must not have any bits outside the least significant two bytes set.
+ \c Integer needs to be at least 16 bits wide, and must not have a sign bit
+ in the least significant 16 bits.
+
+ \sa toEncodedVersion()
+*/
+
+/*!
+ \fn static QTypeRevision QTypeRevision::zero()
+
+ Produces a QTypeRevision with major and minor version \c{0}.
+*/
+
+/*!
+ \fn bool QTypeRevision::hasMajorVersion() const
+
+ Returns true if the major version is known, otherwise false.
+
+ \sa majorVersion(), hasMinorVersion()
+*/
+
+/*!
+ \fn quint8 QTypeRevision::majorVersion() const
+
+ Returns the major version encoded in the revision.
+
+ \sa hasMajorVersion(), minorVersion()
+*/
+
+/*!
+ \fn bool QTypeRevision::hasMinorVersion() const
+
+ Returns true if the minor version is known, otherwise false.
+
+ \sa minorVersion(), hasMajorVersion()
+*/
+
+/*!
+ \fn quint8 QTypeRevision::minorVersion() const
+
+ Returns the minor version encoded in the revision.
+
+ \sa hasMinorVersion(), majorVersion()
+*/
+
+/*!
+ \fn bool QTypeRevision::isValid() const
+
+ Returns true if the major version or the minor version is known,
+ otherwise false.
+
+ \sa hasMajorVersion(), hasMinorVersion()
+*/
+
+/*!
+ \fn template<typename Integer, QTypeRevision::if_valid_value_type<Integer> = true> Integer QTypeRevision::toEncodedVersion() const
+
+ Transforms the revision into an integer value, encoding the minor
+ version into the least significant byte, and the major version into
+ the second least significant byte.
+
+ \c Integer needs to be at least 16 bits wide, and must not have a sign bit
+ in the least significant 16 bits.
+
+ \sa fromEncodedVersion()
+*/
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision)
+ \relates QTypeRevision
+ \since 6.0
+
+ Writes the revision \a revision to stream \a out.
+ */
+QDataStream &operator<<(QDataStream &out, const QTypeRevision &revision)
+{
+ return out << revision.toEncodedVersion<quint16>();
+}
+
+/*!
+ \fn QDataStream& operator>>(QDataStream &in, QTypeRevision &revision)
+ \relates QTypeRevision
+ \since 6.0
+
+ Reads a revision from stream \a in and stores it in \a revision.
+ */
+QDataStream &operator>>(QDataStream &in, QTypeRevision &revision)
+{
+ quint16 value;
+ in >> value;
+ revision = QTypeRevision::fromEncodedVersion(value);
+ return in;
+}
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QTypeRevision &revision)
+{
+ QDebugStateSaver saver(debug);
+ if (revision.hasMajorVersion()) {
+ if (revision.hasMinorVersion())
+ debug.nospace() << revision.majorVersion() << '.' << revision.minorVersion();
+ else
+ debug.nospace().noquote() << revision.majorVersion() << ".x";
+ } else {
+ if (revision.hasMinorVersion())
+ debug << revision.minorVersion();
+ else
+ debug.noquote() << "invalid";
+ }
+ return debug;
+}
+#endif
+
+/*!
+ \relates QHash
+ \since 6.0
+
+ Returns the hash value for the \a key, using \a seed to seed the
+ calculation.
+*/
+size_t qHash(const QTypeRevision &key, size_t seed)
+{
+ return qHash(key.toEncodedVersion<quint16>(), seed);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qtyperevision.h b/src/corelib/tools/qtyperevision.h
new file mode 100644
index 0000000000..8f255a77e8
--- /dev/null
+++ b/src/corelib/tools/qtyperevision.h
@@ -0,0 +1,167 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// Copyright (C) 2015 Keith Gardner <kreios4004@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTYPEREVISION_H
+#define QTYPEREVISION_H
+
+#include <QtCore/qassert.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qtypeinfo.h>
+
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+
+class QDataStream;
+class QDebug;
+
+class QTypeRevision;
+Q_CORE_EXPORT size_t qHash(const QTypeRevision &key, size_t seed = 0);
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision);
+Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QTypeRevision &revision);
+#endif
+
+class QTypeRevision
+{
+public:
+ template<typename Integer>
+ using if_valid_segment_type = typename std::enable_if<
+ std::is_integral<Integer>::value, bool>::type;
+
+ template<typename Integer>
+ using if_valid_value_type = typename std::enable_if<
+ std::is_integral<Integer>::value
+ && (sizeof(Integer) > sizeof(quint16)
+ || (sizeof(Integer) == sizeof(quint16)
+ && !std::is_signed<Integer>::value)), bool>::type;
+
+ template<typename Integer, if_valid_segment_type<Integer> = true>
+ static constexpr bool isValidSegment(Integer segment)
+ {
+ // using extra parentheses around max to avoid expanding it if it is a macro
+ return segment >= Integer(0)
+ && ((std::numeric_limits<Integer>::max)() < Integer(SegmentUnknown)
+ || segment < Integer(SegmentUnknown));
+ }
+
+ template<typename Major, typename Minor,
+ if_valid_segment_type<Major> = true,
+ if_valid_segment_type<Minor> = true>
+ static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
+ {
+ return Q_ASSERT(isValidSegment(majorVersion)),
+ Q_ASSERT(isValidSegment(minorVersion)),
+ QTypeRevision(quint8(majorVersion), quint8(minorVersion));
+ }
+
+ template<typename Major, if_valid_segment_type<Major> = true>
+ static constexpr QTypeRevision fromMajorVersion(Major majorVersion)
+ {
+ return Q_ASSERT(isValidSegment(majorVersion)),
+ QTypeRevision(quint8(majorVersion), SegmentUnknown);
+ }
+
+ template<typename Minor, if_valid_segment_type<Minor> = true>
+ static constexpr QTypeRevision fromMinorVersion(Minor minorVersion)
+ {
+ return Q_ASSERT(isValidSegment(minorVersion)),
+ QTypeRevision(SegmentUnknown, quint8(minorVersion));
+ }
+
+ template<typename Integer, if_valid_value_type<Integer> = true>
+ static constexpr QTypeRevision fromEncodedVersion(Integer value)
+ {
+ return Q_ASSERT((value & ~Integer(0xffff)) == Integer(0)),
+ QTypeRevision((value & Integer(0xff00)) >> 8, value & Integer(0xff));
+ }
+
+ static constexpr QTypeRevision zero() { return QTypeRevision(0, 0); }
+
+ constexpr QTypeRevision() = default;
+
+ constexpr bool hasMajorVersion() const { return m_majorVersion != SegmentUnknown; }
+ constexpr quint8 majorVersion() const { return m_majorVersion; }
+
+ constexpr bool hasMinorVersion() const { return m_minorVersion != SegmentUnknown; }
+ constexpr quint8 minorVersion() const { return m_minorVersion; }
+
+ constexpr bool isValid() const { return hasMajorVersion() || hasMinorVersion(); }
+
+ template<typename Integer, if_valid_value_type<Integer> = true>
+ constexpr Integer toEncodedVersion() const
+ {
+ return Integer(m_majorVersion << 8) | Integer(m_minorVersion);
+ }
+
+private:
+ friend constexpr bool
+ comparesEqual(const QTypeRevision &lhs, const QTypeRevision &rhs) noexcept
+ { return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>(); }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QTypeRevision &lhs, const QTypeRevision &rhs) noexcept
+ {
+ // For both major and minor the following rule applies:
+ // non-0 ver > unspecified ver > 0 ver
+ auto cmpUnspecified = [](quint8 leftVer, quint8 rightVer) {
+ Q_ASSERT(leftVer != rightVer
+ && (leftVer == QTypeRevision::SegmentUnknown
+ || rightVer == QTypeRevision::SegmentUnknown));
+ if (leftVer != QTypeRevision::SegmentUnknown)
+ return leftVer > 0 ? Qt::strong_ordering::greater : Qt::strong_ordering::less;
+ return rightVer > 0 ? Qt::strong_ordering::less : Qt::strong_ordering::greater;
+ };
+
+ if (lhs.hasMajorVersion() != rhs.hasMajorVersion()) {
+ return cmpUnspecified(lhs.majorVersion(), rhs.majorVersion());
+ } else {
+ const auto majorRes = Qt::compareThreeWay(lhs.majorVersion(), rhs.majorVersion());
+ if (is_eq(majorRes)) {
+ if (lhs.hasMinorVersion() != rhs.hasMinorVersion())
+ return cmpUnspecified(lhs.minorVersion(), rhs.minorVersion());
+ return Qt::compareThreeWay(lhs.minorVersion(), rhs.minorVersion());
+ }
+ return majorRes;
+ }
+ }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QTypeRevision)
+
+ enum { SegmentUnknown = 0xff };
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ constexpr QTypeRevision(quint8 major, quint8 minor)
+ : m_minorVersion(minor), m_majorVersion(major) {}
+
+ quint8 m_minorVersion = SegmentUnknown;
+ quint8 m_majorVersion = SegmentUnknown;
+#else
+ constexpr QTypeRevision(quint8 major, quint8 minor)
+ : m_majorVersion(major), m_minorVersion(minor) {}
+
+ quint8 m_majorVersion = SegmentUnknown;
+ quint8 m_minorVersion = SegmentUnknown;
+#endif
+};
+
+static_assert(sizeof(QTypeRevision) == 2);
+Q_DECLARE_TYPEINFO(QTypeRevision, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QTypeRevision &revision);
+#endif
+
+QT_END_NAMESPACE
+
+QT_DECL_METATYPE_EXTERN(QTypeRevision, Q_CORE_EXPORT)
+
+#endif // QTYPEREVISION_H
+
+#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
+// make QVersionNumber available from <QTypeRevision>
+#include <QtCore/qversionnumber.h>
+#endif
diff --git a/src/corelib/tools/quniquehandle_p.h b/src/corelib/tools/quniquehandle_p.h
new file mode 100644
index 0000000000..7af1536c2e
--- /dev/null
+++ b/src/corelib/tools/quniquehandle_p.h
@@ -0,0 +1,225 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QUNIQUEHANDLE_P_H
+#define QUNIQUEHANDLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qassert.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+/*! \internal QUniqueHandle is a general purpose RAII wrapper intended
+ for interfacing with resource-allocating C-style APIs, for example
+ operating system APIs, database engine APIs, or any other scenario
+ where resources are allocated and released, and where pointer
+ semantics does not seem a perfect fit.
+
+ QUniqueHandle does not support copying, because it is intended to
+ maintain ownership of resources that can not be copied. This makes
+ it safer to use than naked handle types, since ownership is
+ maintained by design.
+
+ The underlying handle object is described using a client supplied
+ HandleTraits object that is implemented per resource type. The
+ traits struct must describe two properties of a handle:
+
+ 1) What value is considered invalid
+ 2) How to close a resource.
+
+ Example 1:
+
+ struct InvalidHandleTraits {
+ using Type = HANDLE;
+
+ static Type invalidValue() {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ static bool close(Type handle) {
+ return CloseHandle(handle) != 0;
+ }
+ }
+
+ using FileHandle = QUniqueHandle<InvalidHandleTraits>;
+
+ Usage:
+
+ // Takes ownership of returned handle.
+ FileHandle handle{ CreateFile(...) };
+
+ if (!handle.isValid()) {
+ qDebug() << GetLastError()
+ return;
+ }
+
+ ...
+
+ Example 2:
+
+ struct SqLiteTraits {
+ using Type = sqlite3*;
+
+ static Type invalidValue() {
+ return nullptr;
+ }
+
+ static bool close(Type handle) {
+ sqlite3_close(handle);
+ return true;
+ }
+ }
+
+ using DbHandle = QUniqueHandle<SqLiteTraits>;
+
+ Usage:
+
+ DbHandle h;
+
+ // Take ownership of returned handle.
+ int result = sqlite3_open(":memory:", &h);
+
+ ...
+
+ NOTE: The QUniqueHandle assumes that closing a resource is
+ guaranteed to succeed, and provides no support for handling failure
+ to close a resource. It is therefore only recommended for use cases
+ where failure to close a resource is either not an error, or an
+ unrecoverable error.
+*/
+
+// clang-format off
+
+template <typename HandleTraits>
+class QUniqueHandle
+{
+public:
+ using Type = typename HandleTraits::Type;
+
+ QUniqueHandle() = default;
+
+ explicit QUniqueHandle(const Type &handle) noexcept
+ : m_handle{ handle }
+ {}
+
+ QUniqueHandle(QUniqueHandle &&other) noexcept
+ : m_handle{ other.release() }
+ {}
+
+ ~QUniqueHandle() noexcept
+ {
+ close();
+ }
+
+ QUniqueHandle& operator=(QUniqueHandle &&rhs) noexcept
+ {
+ if (this != std::addressof(rhs))
+ reset(rhs.release());
+
+ return *this;
+ }
+
+ QUniqueHandle(const QUniqueHandle &) = delete;
+ QUniqueHandle &operator=(const QUniqueHandle &) = delete;
+
+
+ [[nodiscard]] bool isValid() const noexcept
+ {
+ return m_handle != HandleTraits::invalidValue();
+ }
+
+ [[nodiscard]] explicit operator bool() const noexcept
+ {
+ return isValid();
+ }
+
+ [[nodiscard]] Type get() const noexcept
+ {
+ return m_handle;
+ }
+
+ void reset(const Type& handle) noexcept
+ {
+ if (handle == m_handle)
+ return;
+
+ close();
+ m_handle = handle;
+ }
+
+ [[nodiscard]] Type release() noexcept
+ {
+ Type handle = m_handle;
+ m_handle = HandleTraits::invalidValue();
+ return handle;
+ }
+
+ [[nodiscard]] Type *operator&() noexcept // NOLINT(google-runtime-operator)
+ {
+ Q_ASSERT(!isValid());
+ return &m_handle;
+ }
+
+ void close() noexcept
+ {
+ if (!isValid())
+ return;
+
+ const bool success = HandleTraits::close(m_handle);
+ Q_ASSERT(success);
+
+ m_handle = HandleTraits::invalidValue();
+ }
+
+ [[nodiscard]] friend bool operator==(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
+ {
+ return lhs.get() == rhs.get();
+ }
+
+ [[nodiscard]] friend bool operator!=(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
+ {
+ return lhs.get() != rhs.get();
+ }
+
+ [[nodiscard]] friend bool operator<(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
+ {
+ return lhs.get() < rhs.get();
+ }
+
+ [[nodiscard]] friend bool operator<=(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
+ {
+ return lhs.get() <= rhs.get();
+ }
+
+ [[nodiscard]] friend bool operator>(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
+ {
+ return lhs.get() > rhs.get();
+ }
+
+ [[nodiscard]] friend bool operator>=(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept
+ {
+ return lhs.get() >= rhs.get();
+ }
+
+private:
+ Type m_handle{ HandleTraits::invalidValue() };
+};
+
+// clang-format on
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index cea0e14d41..0a579bf487 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -1,45 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVARLENGTHARRAY_H
#define QVARLENGTHARRAY_H
+#if 0
+#pragma qt_class(QVarLengthArray)
+#pragma qt_sync_stop_processing
+#endif
+
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qglobal.h>
#include <QtCore/qalgorithms.h>
@@ -49,39 +18,320 @@
#include <algorithm>
#include <initializer_list>
#include <iterator>
+#include <QtCore/q20memory.h>
#include <new>
+
#include <string.h>
#include <stdlib.h>
QT_BEGIN_NAMESPACE
+template <size_t Size, size_t Align, qsizetype Prealloc>
+class QVLAStorage
+{
+ template <size_t> class print;
+protected:
+ ~QVLAStorage() = default;
+
+ alignas(Align) char array[Prealloc * (Align > Size ? Align : Size)];
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
+ // ensure we maintain BC: std::aligned_storage_t was only specified by a
+ // minimum size, but for BC we need the substitution to be exact in size:
+ static_assert(std::is_same_v<print<sizeof(std::aligned_storage_t<Size, Align>[Prealloc])>,
+ print<sizeof(array)>>);
+ QT_WARNING_POP
+};
+
+class QVLABaseBase
+{
+protected:
+ ~QVLABaseBase() = default;
+
+ qsizetype a; // capacity
+ qsizetype s; // size
+ void *ptr; // data
+
+ Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
+ [[maybe_unused]] qsizetype n = 1) const
+ {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= size());
+ Q_ASSERT(n >= 0);
+ Q_ASSERT(n <= size() - pos);
+ }
+
+ struct free_deleter {
+ void operator()(void *p) const noexcept { free(p); }
+ };
+ using malloced_ptr = std::unique_ptr<void, free_deleter>;
+
+public:
+ using size_type = qsizetype;
+
+ constexpr size_type capacity() const noexcept { return a; }
+ constexpr size_type size() const noexcept { return s; }
+ constexpr bool empty() const noexcept { return size() == 0; }
+};
+
+template<class T>
+class QVLABase : public QVLABaseBase
+{
+protected:
+ ~QVLABase() = default;
+
+public:
+ T *data() noexcept { return static_cast<T *>(ptr); }
+ const T *data() const noexcept { return static_cast<T *>(ptr); }
+
+ using iterator = T*;
+ using const_iterator = const T*;
+
+ iterator begin() noexcept { return data(); }
+ const_iterator begin() const noexcept { return data(); }
+ const_iterator cbegin() const noexcept { return begin(); }
+ iterator end() noexcept { return data() + size(); }
+ const_iterator end() const noexcept { return data() + size(); }
+ const_iterator cend() const noexcept { return end(); }
+
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ using value_type = T;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using pointer = value_type*;
+ using const_pointer = const value_type*;
+ using difference_type = qptrdiff;
+
+ reference front()
+ {
+ verify();
+ return *begin();
+ }
+
+ const_reference front() const
+ {
+ verify();
+ return *begin();
+ }
+
+ reference back()
+ {
+ verify();
+ return *rbegin();
+ }
+
+ const_reference back() const
+ {
+ verify();
+ return *rbegin();
+ }
+
+ void pop_back()
+ {
+ verify();
+ if constexpr (QTypeInfo<T>::isComplex)
+ data()[size() - 1].~T();
+ --s;
+ }
+
+ template <typename AT = T>
+ qsizetype indexOf(const AT &t, qsizetype from = 0) const;
+ template <typename AT = T>
+ qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
+ template <typename AT = T>
+ bool contains(const AT &t) const;
+
+ reference operator[](qsizetype idx)
+ {
+ verify(idx);
+ return data()[idx];
+ }
+ const_reference operator[](qsizetype idx) const
+ {
+ verify(idx);
+ return data()[idx];
+ }
+
+ value_type value(qsizetype i) const;
+ value_type value(qsizetype i, const T& defaultValue) const;
+
+ void replace(qsizetype i, const T &t);
+ void remove(qsizetype i, qsizetype n = 1);
+ template <typename AT = T>
+ qsizetype removeAll(const AT &t);
+ template <typename AT = T>
+ bool removeOne(const AT &t);
+ template <typename Predicate>
+ qsizetype removeIf(Predicate pred);
+
+ void clear()
+ {
+ if constexpr (QTypeInfo<T>::isComplex)
+ std::destroy_n(data(), size());
+ s = 0;
+ }
+
+ iterator erase(const_iterator begin, const_iterator end);
+ iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
+
+ static constexpr qsizetype max_size() noexcept
+ {
+ // -1 to deal with the pointer one-past-the-end
+ return (QtPrivate::MaxAllocSize / sizeof(T)) - 1;
+ }
+
+ size_t hash(size_t seed) const noexcept(QtPrivate::QNothrowHashable_v<T>)
+ {
+ return qHashRange(begin(), end(), seed);
+ }
+protected:
+ void growBy(qsizetype prealloc, void *array, qsizetype increment)
+ { reallocate_impl(prealloc, array, size(), (std::max)(size() * 2, size() + increment)); }
+ template <typename...Args>
+ reference emplace_back_impl(qsizetype prealloc, void *array, Args&&...args)
+ {
+ if (size() == capacity()) // ie. size() != 0
+ growBy(prealloc, array, 1);
+ reference r = *q20::construct_at(end(), std::forward<Args>(args)...);
+ ++s;
+ return r;
+ }
+ template <typename...Args>
+ iterator emplace_impl(qsizetype prealloc, void *array, const_iterator pos, Args&&...arg);
+
+ iterator insert_impl(qsizetype prealloc, void *array, const_iterator pos, qsizetype n, const T &t);
+
+ template <typename S>
+ bool equal(const QVLABase<S> &other) const
+ {
+ return std::equal(begin(), end(), other.begin(), other.end());
+ }
+ template <typename S>
+ bool less_than(const QVLABase<S> &other) const
+ {
+ return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
+ }
+
+ void append_impl(qsizetype prealloc, void *array, const T *buf, qsizetype n);
+ void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc);
+ void resize_impl(qsizetype prealloc, void *array, qsizetype sz, const T &v)
+ {
+ if (QtPrivate::q_points_into_range(&v, begin(), end())) {
+ resize_impl(prealloc, array, sz, T(v));
+ return;
+ }
+ reallocate_impl(prealloc, array, sz, qMax(sz, capacity()));
+ while (size() < sz) {
+ q20::construct_at(data() + size(), v);
+ ++s;
+ }
+ }
+ void resize_impl(qsizetype prealloc, void *array, qsizetype sz)
+ {
+ reallocate_impl(prealloc, array, sz, qMax(sz, capacity()));
+ if constexpr (QTypeInfo<T>::isComplex) {
+ // call default constructor for new objects (which can throw)
+ while (size() < sz) {
+ q20::construct_at(data() + size());
+ ++s;
+ }
+ } else {
+ s = sz;
+ }
+ }
+
+ void assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t);
+ template <typename Iterator>
+ void assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last);
+
+ bool isValidIterator(const const_iterator &i) const
+ {
+ const std::less<const T *> less = {};
+ return !less(cend(), i) && !less(i, cbegin());
+ }
+};
// Prealloc = 256 by default, specified in qcontainerfwd.h
template<class T, qsizetype Prealloc>
class QVarLengthArray
+#if QT_VERSION >= QT_VERSION_CHECK(7,0,0) || defined(QT_BOOTSTRAPPED)
+ : public QVLAStorage<sizeof(T), alignof(T), Prealloc>,
+ public QVLABase<T>
+#else
+ : public QVLABase<T>,
+ public QVLAStorage<sizeof(T), alignof(T), Prealloc>
+#endif
{
+ template <class S, qsizetype Prealloc2>
+ friend class QVarLengthArray;
+ using Base = QVLABase<T>;
+ using Storage = QVLAStorage<sizeof(T), alignof(T), Prealloc>;
+ static_assert(Prealloc > 0, "QVarLengthArray Prealloc must be greater than 0.");
+ static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
+ using Base::verify;
+
+ template <typename U>
+ using if_copyable = std::enable_if_t<std::is_copy_constructible_v<U>, bool>;
+ template <typename InputIterator>
+ using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>;
public:
- QVarLengthArray() : QVarLengthArray(0) {}
+ static constexpr qsizetype PreallocatedSize = Prealloc;
+
+ using size_type = typename Base::size_type;
+ using value_type = typename Base::value_type;
+ using pointer = typename Base::pointer;
+ using const_pointer = typename Base::const_pointer;
+ using reference = typename Base::reference;
+ using const_reference = typename Base::const_reference;
+ using difference_type = typename Base::difference_type;
+
+ using iterator = typename Base::iterator;
+ using const_iterator = typename Base::const_iterator;
+ using reverse_iterator = typename Base::reverse_iterator;
+ using const_reverse_iterator = typename Base::const_reverse_iterator;
+
+ QVarLengthArray() noexcept
+ {
+ this->a = Prealloc;
+ this->s = 0;
+ this->ptr = this->array;
+ }
inline explicit QVarLengthArray(qsizetype size);
- inline QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
- : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
+#ifndef Q_QDOC
+ template <typename U = T, if_copyable<U> = true>
+#endif
+ explicit QVarLengthArray(qsizetype sz, const T &v)
+ : QVarLengthArray{}
+ {
+ resize(sz, v);
+ }
+
+ QVarLengthArray(const QVarLengthArray &other)
+ : QVarLengthArray{}
{
append(other.constData(), other.size());
}
QVarLengthArray(QVarLengthArray &&other)
noexcept(std::is_nothrow_move_constructible_v<T>)
- : a{other.a},
- s{other.s},
- ptr{other.ptr}
+ : Base(other)
{
const auto otherInlineStorage = reinterpret_cast<T*>(other.array);
- if (ptr == otherInlineStorage) {
+ if (data() == otherInlineStorage) {
// inline buffer - move into our inline buffer:
- ptr = reinterpret_cast<T*>(array);
- QtPrivate::q_uninitialized_relocate_n(otherInlineStorage, s, ptr);
+ this->ptr = this->array;
+ QtPrivate::q_uninitialized_relocate_n(otherInlineStorage, size(), data());
} else {
// heap buffer - we just stole the memory
}
@@ -96,7 +346,7 @@ public:
{
}
- template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ template <typename InputIterator, if_input_iterator<InputIterator> = true>
inline QVarLengthArray(InputIterator first, InputIterator last)
: QVarLengthArray()
{
@@ -104,14 +354,12 @@ public:
std::copy(first, last, std::back_inserter(*this));
}
- inline ~QVarLengthArray() {
- if (QTypeInfo<T>::isComplex) {
- T *i = ptr + s;
- while (i-- != ptr)
- i->~T();
- }
- if (ptr != reinterpret_cast<T *>(array))
- free(ptr);
+ inline ~QVarLengthArray()
+ {
+ if constexpr (QTypeInfo<T>::isComplex)
+ std::destroy_n(data(), size());
+ if (data() != reinterpret_cast<T *>(this->array))
+ free(data());
}
inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other)
{
@@ -130,96 +378,119 @@ public:
// the moved-from state is the empty state, so we're good with the clear() here:
clear();
Q_ASSERT(capacity() >= Prealloc);
- const auto otherInlineStorage = reinterpret_cast<T*>(other.array);
+ const auto otherInlineStorage = other.array;
if (other.ptr != otherInlineStorage) {
// heap storage: steal the external buffer, reset other to otherInlineStorage
- a = std::exchange(other.a, Prealloc);
- ptr = std::exchange(other.ptr, otherInlineStorage);
+ this->a = std::exchange(other.a, Prealloc);
+ this->ptr = std::exchange(other.ptr, otherInlineStorage);
} else {
// inline storage: move into our storage (doesn't matter whether inline or external)
- QtPrivate::q_uninitialized_relocate_n(other.ptr, other.s, ptr);
+ QtPrivate::q_uninitialized_relocate_n(other.data(), other.size(), data());
}
- s = std::exchange(other.s, 0);
+ this->s = std::exchange(other.s, 0);
return *this;
}
QVarLengthArray<T, Prealloc> &operator=(std::initializer_list<T> list)
{
- resize(qsizetype(list.size()));
- std::copy(list.begin(), list.end(),
- QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size()));
+ assign(list);
return *this;
}
- inline void removeLast() {
- Q_ASSERT(s > 0);
- if (QTypeInfo<T>::isComplex)
- ptr[s - 1].~T();
- --s;
+ inline void removeLast()
+ {
+ Base::pop_back();
}
- inline qsizetype size() const { return s; }
- inline qsizetype count() const { return s; }
- inline qsizetype length() const { return s; }
- inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
- inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); }
- T& last() { Q_ASSERT(!isEmpty()); return *(end() - 1); }
- const T& last() const { Q_ASSERT(!isEmpty()); return *(end() - 1); }
- inline bool isEmpty() const { return (s == 0); }
- inline void resize(qsizetype size);
+#ifdef Q_QDOC
+ inline qsizetype size() const { return this->s; }
+ static constexpr qsizetype max_size() noexcept { return QVLABase<T>::max_size(); }
+#endif
+ using Base::size;
+ inline qsizetype count() const { return size(); }
+ inline qsizetype length() const { return size(); }
+ inline T &first()
+ {
+ return front();
+ }
+ inline const T &first() const
+ {
+ return front();
+ }
+ T &last()
+ {
+ return back();
+ }
+ const T &last() const
+ {
+ return back();
+ }
+ bool isEmpty() const { return empty(); }
+ void resize(qsizetype sz) { Base::resize_impl(Prealloc, this->array, sz); }
+#ifndef Q_QDOC
+ template <typename U = T, if_copyable<U> = true>
+#endif
+ void resize(qsizetype sz, const T &v)
+ { Base::resize_impl(Prealloc, this->array, sz, v); }
+ using Base::clear;
+#ifdef Q_QDOC
inline void clear() { resize(0); }
- inline void squeeze();
-
- inline qsizetype capacity() const { return a; }
- inline void reserve(qsizetype size);
+#endif
+ void squeeze() { reallocate(size(), size()); }
- inline qsizetype indexOf(const T &t, qsizetype from = 0) const;
- inline qsizetype lastIndexOf(const T &t, qsizetype from = -1) const;
- inline bool contains(const T &t) const;
+ using Base::capacity;
+#ifdef Q_QDOC
+ qsizetype capacity() const { return this->a; }
+#endif
+ void reserve(qsizetype sz) { if (sz > capacity()) reallocate(size(), sz); }
+
+#ifdef Q_QDOC
+ template <typename AT = T>
+ inline qsizetype indexOf(const AT &t, qsizetype from = 0) const;
+ template <typename AT = T>
+ inline qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
+ template <typename AT = T>
+ inline bool contains(const AT &t) const;
+#endif
+ using Base::indexOf;
+ using Base::lastIndexOf;
+ using Base::contains;
- inline T &operator[](qsizetype idx) {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
+#ifdef Q_QDOC
+ inline T &operator[](qsizetype idx)
+ {
+ verify(idx);
+ return data()[idx];
}
- inline const T &operator[](qsizetype idx) const {
- Q_ASSERT(idx >= 0 && idx < s);
- return ptr[idx];
+ inline const T &operator[](qsizetype idx) const
+ {
+ verify(idx);
+ return data()[idx];
}
+#endif
+ using Base::operator[];
inline const T &at(qsizetype idx) const { return operator[](idx); }
+#ifdef Q_QDOC
T value(qsizetype i) const;
T value(qsizetype i, const T &defaultValue) const;
+#endif
+ using Base::value;
- inline void append(const T &t) {
- if (s == a) { // i.e. s != 0
- T copy(t);
- realloc(s, s<<1);
- const qsizetype idx = s++;
- if (QTypeInfo<T>::isComplex) {
- new (ptr + idx) T(std::move(copy));
- } else {
- ptr[idx] = std::move(copy);
- }
- } else {
- const qsizetype idx = s++;
- if (QTypeInfo<T>::isComplex) {
- new (ptr + idx) T(t);
- } else {
- ptr[idx] = t;
- }
- }
+ inline void append(const T &t)
+ {
+ if (size() == capacity())
+ emplace_back(T(t));
+ else
+ emplace_back(t);
}
- void append(T &&t) {
- if (s == a)
- realloc(s, s << 1);
- const qsizetype idx = s++;
- if (QTypeInfo<T>::isComplex)
- new (ptr + idx) T(std::move(t));
- else
- ptr[idx] = std::move(t);
+ void append(T &&t)
+ {
+ emplace_back(std::move(t));
}
- void append(const T *buf, qsizetype size);
+ void append(const T *buf, qsizetype sz)
+ { Base::append_impl(Prealloc, this->array, buf, sz); }
inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
{ append(t); return *this; }
inline QVarLengthArray<T, Prealloc> &operator<<(T &&t)
@@ -229,143 +500,233 @@ public:
inline QVarLengthArray<T, Prealloc> &operator+=(T &&t)
{ append(std::move(t)); return *this; }
+#if QT_DEPRECATED_SINCE(6, 3)
+ QT_DEPRECATED_VERSION_X_6_3("This is slow. If you must, use insert(cbegin(), ~~~) instead.")
void prepend(T &&t);
+ QT_DEPRECATED_VERSION_X_6_3("This is slow. If you must, use insert(cbegin(), ~~~) instead.")
void prepend(const T &t);
+#endif
void insert(qsizetype i, T &&t);
void insert(qsizetype i, const T &t);
void insert(qsizetype i, qsizetype n, const T &t);
+
+ QVarLengthArray &assign(qsizetype n, const T &t)
+ { Base::assign_impl(Prealloc, this->array, n, t); return *this; }
+ template <typename InputIterator, if_input_iterator<InputIterator> = true>
+ QVarLengthArray &assign(InputIterator first, InputIterator last)
+ { Base::assign_impl(Prealloc, this->array, first, last); return *this; }
+ QVarLengthArray &assign(std::initializer_list<T> list)
+ { assign(list.begin(), list.end()); return *this; }
+
+#ifdef Q_QDOC
void replace(qsizetype i, const T &t);
- void remove(qsizetype i);
- void remove(qsizetype i, qsizetype n);
-
-
- inline T *data() { return ptr; }
- inline const T *data() const { return ptr; }
- inline const T * constData() const { return ptr; }
- typedef qsizetype size_type;
- typedef T value_type;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- typedef qptrdiff difference_type;
-
-
- typedef T* iterator;
- typedef const T* const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
- inline iterator begin() { return ptr; }
- inline const_iterator begin() const { return ptr; }
- inline const_iterator cbegin() const { return ptr; }
- inline const_iterator constBegin() const { return ptr; }
- inline iterator end() { return ptr + s; }
- inline const_iterator end() const { return ptr + s; }
- inline const_iterator cend() const { return ptr + s; }
- inline const_iterator constEnd() const { return ptr + s; }
+ void remove(qsizetype i, qsizetype n = 1);
+ template <typename AT = T>
+ qsizetype removeAll(const AT &t);
+ template <typename AT = T>
+ bool removeOne(const AT &t);
+ template <typename Predicate>
+ qsizetype removeIf(Predicate pred);
+#endif
+ using Base::replace;
+ using Base::remove;
+ using Base::removeAll;
+ using Base::removeOne;
+ using Base::removeIf;
+
+#ifdef Q_QDOC
+ inline T *data() { return this->ptr; }
+ inline const T *data() const { return this->ptr; }
+#endif
+ using Base::data;
+ inline const T *constData() const { return data(); }
+#ifdef Q_QDOC
+ inline iterator begin() { return data(); }
+ inline const_iterator begin() const { return data(); }
+ inline const_iterator cbegin() const { return begin(); }
+ inline const_iterator constBegin() const { return begin(); }
+ inline iterator end() { return data() + size(); }
+ inline const_iterator end() const { return data() + size(); }
+ inline const_iterator cend() const { return end(); }
+#endif
+
+ using Base::begin;
+ using Base::cbegin;
+ auto constBegin() const -> const_iterator { return begin(); }
+ using Base::end;
+ using Base::cend;
+ inline const_iterator constEnd() const { return end(); }
+#ifdef Q_QDOC
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
- iterator insert(const_iterator before, qsizetype n, const T &x);
- iterator insert(const_iterator before, T &&x);
+#endif
+ using Base::rbegin;
+ using Base::crbegin;
+ using Base::rend;
+ using Base::crend;
+
+ iterator insert(const_iterator before, qsizetype n, const T &x)
+ { return Base::insert_impl(Prealloc, this->array, before, n, x); }
+ iterator insert(const_iterator before, T &&x) { return emplace(before, std::move(x)); }
inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
+#ifdef Q_QDOC
iterator erase(const_iterator begin, const_iterator end);
- inline iterator erase(const_iterator pos) { return erase(pos, pos+1); }
+ inline iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
+#endif
+ using Base::erase;
// STL compatibility:
+#ifdef Q_QDOC
inline bool empty() const { return isEmpty(); }
+#endif
+ using Base::empty;
inline void push_back(const T &t) { append(t); }
void push_back(T &&t) { append(std::move(t)); }
+#ifdef Q_QDOC
inline void pop_back() { removeLast(); }
inline T &front() { return first(); }
inline const T &front() const { return first(); }
inline T &back() { return last(); }
inline const T &back() const { return last(); }
+#endif
+ using Base::pop_back;
+ using Base::front;
+ using Base::back;
void shrink_to_fit() { squeeze(); }
+ template <typename...Args>
+ iterator emplace(const_iterator pos, Args &&...args)
+ { return Base::emplace_impl(Prealloc, this->array, pos, std::forward<Args>(args)...); }
+ template <typename...Args>
+ T &emplace_back(Args &&...args)
+ { return Base::emplace_back_impl(Prealloc, this->array, std::forward<Args>(args)...); }
+
+
+#ifdef Q_QDOC
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+ template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+ friend inline bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
+#else
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_eq_result<U> operator==(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
+ {
+ return l.equal(r);
+ }
-private:
- void realloc(qsizetype size, qsizetype alloc);
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_eq_result<U> operator!=(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
+ {
+ return !(l == r);
+ }
- qsizetype a; // capacity
- qsizetype s; // size
- T *ptr; // data
- union {
- char array[Prealloc * sizeof(T)];
- qint64 q_for_alignment_1;
- double q_for_alignment_2;
- };
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator<(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end())))
+ {
+ return lhs.less_than(rhs);
+ }
- bool isValidIterator(const const_iterator &i) const
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator>(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(lhs < rhs))
{
- const std::less<const T*> less = {};
- return !less(cend(), i) && !less(i, cbegin());
+ return rhs < lhs;
}
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator<=(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ {
+ return !(lhs > rhs);
+ }
+
+ template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
+ QTypeTraits::compare_lt_result<U> operator>=(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ {
+ return !(lhs < rhs);
+ }
+#endif
+
+private:
+ template <typename U, qsizetype Prealloc2>
+ bool equal(const QVarLengthArray<U, Prealloc2> &other) const
+ { return Base::equal(other); }
+ template <typename U, qsizetype Prealloc2>
+ bool less_than(const QVarLengthArray<U, Prealloc2> &other) const
+ { return Base::less_than(other); }
+
+ void reallocate(qsizetype sz, qsizetype alloc)
+ { Base::reallocate_impl(Prealloc, this->array, sz, alloc); }
+
+ using Base::isValidIterator;
};
-#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
template <typename InputIterator,
typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
QtPrivate::IfIsInputIterator<InputIterator> = true>
QVarLengthArray(InputIterator, InputIterator) -> QVarLengthArray<ValueType>;
-#endif
template <class T, qsizetype Prealloc>
Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(qsizetype asize)
- : s(asize) {
- static_assert(Prealloc > 0, "QVarLengthArray Prealloc must be greater than 0.");
- Q_ASSERT_X(s >= 0, "QVarLengthArray::QVarLengthArray()", "Size must be greater than or equal to 0.");
- if (s > Prealloc) {
- ptr = reinterpret_cast<T *>(malloc(s * sizeof(T)));
- Q_CHECK_PTR(ptr);
- a = s;
- } else {
- ptr = reinterpret_cast<T *>(array);
- a = Prealloc;
- }
- if (QTypeInfo<T>::isComplex) {
- T *i = ptr + s;
- while (i != ptr)
- new (--i) T;
- }
-}
+ : QVarLengthArray()
+{
+ Q_ASSERT_X(asize >= 0, "QVarLengthArray::QVarLengthArray(qsizetype)",
+ "Size must be greater than or equal to 0.");
-template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::resize(qsizetype asize)
-{ realloc(asize, qMax(asize, a)); }
+ // historically, this ctor worked for non-copyable/non-movable T, so keep it working, why not?
+ // resize(asize) // this requires a movable or copyable T, can't use, need to do it by hand
-template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(qsizetype asize)
-{ if (asize > a) realloc(s, asize); }
+ if (asize > Prealloc) {
+ this->ptr = malloc(asize * sizeof(T));
+ Q_CHECK_PTR(this->ptr);
+ this->a = asize;
+ }
+ if constexpr (QTypeInfo<T>::isComplex)
+ std::uninitialized_default_construct_n(data(), asize);
+ this->s = asize;
+}
-template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::indexOf(const T &t, qsizetype from) const
+template <class T>
+template <typename AT>
+Q_INLINE_TEMPLATE qsizetype QVLABase<T>::indexOf(const AT &t, qsizetype from) const
{
if (from < 0)
- from = qMax(from + s, qsizetype(0));
- if (from < s) {
- T *n = ptr + from - 1;
- T *e = ptr + s;
+ from = qMax(from + size(), qsizetype(0));
+ if (from < size()) {
+ const T *n = data() + from - 1;
+ const T *e = end();
while (++n != e)
if (*n == t)
- return n - ptr;
+ return n - data();
}
return -1;
}
-template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const T &t, qsizetype from) const
+template <class T>
+template <typename AT>
+Q_INLINE_TEMPLATE qsizetype QVLABase<T>::lastIndexOf(const AT &t, qsizetype from) const
{
if (from < 0)
- from += s;
- else if (from >= s)
- from = s - 1;
+ from += size();
+ else if (from >= size())
+ from = size() - 1;
if (from >= 0) {
- T *b = ptr;
- T *n = ptr + from + 1;
+ const T *b = begin();
+ const T *n = b + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
@@ -374,11 +735,12 @@ Q_INLINE_TEMPLATE qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const T &t
return -1;
}
-template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE bool QVarLengthArray<T, Prealloc>::contains(const T &t) const
+template <class T>
+template <typename AT>
+Q_INLINE_TEMPLATE bool QVLABase<T>::contains(const AT &t) const
{
- T *b = ptr;
- T *i = ptr + s;
+ const T *b = begin();
+ const T *i = end();
while (i != b) {
if (*--i == t)
return true;
@@ -386,276 +748,276 @@ Q_INLINE_TEMPLATE bool QVarLengthArray<T, Prealloc>::contains(const T &t) const
return false;
}
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, qsizetype increment)
+template <class T>
+Q_OUTOFLINE_TEMPLATE void QVLABase<T>::append_impl(qsizetype prealloc, void *array, const T *abuf, qsizetype increment)
{
- Q_ASSERT(abuf);
+ Q_ASSERT(abuf || increment == 0);
if (increment <= 0)
return;
- const qsizetype asize = s + increment;
+ const qsizetype asize = size() + increment;
+
+ if (asize >= capacity())
+ growBy(prealloc, array, increment);
- if (asize >= a)
- realloc(s, qMax(s*2, asize));
+ if constexpr (QTypeInfo<T>::isComplex)
+ std::uninitialized_copy_n(abuf, increment, end());
+ else
+ memcpy(static_cast<void *>(end()), static_cast<const void *>(abuf), increment * sizeof(T));
- if (QTypeInfo<T>::isComplex) {
- // call constructor for new objects (which can throw)
- while (s < asize)
- new (ptr+(s++)) T(*abuf++);
+ this->s = asize;
+}
+
+template <class T>
+Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t)
+{
+ Q_ASSERT(n >= 0);
+ if (n > capacity()) {
+ reallocate_impl(prealloc, array, 0, capacity()); // clear
+ resize_impl(prealloc, array, n, t);
} else {
- memcpy(static_cast<void *>(&ptr[s]), static_cast<const void *>(abuf), increment * sizeof(T));
- s = asize;
+ auto mid = (std::min)(n, size());
+ std::fill(data(), data() + mid, t);
+ std::uninitialized_fill(data() + mid, data() + n, t);
+ s = n;
+ erase(data() + n, data() + size());
}
}
-template <class T, qsizetype Prealloc>
-Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::squeeze()
-{ realloc(s, s); }
+template <class T>
+template <typename Iterator>
+Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last)
+{
+ // This function only provides the basic exception guarantee.
+ constexpr bool IsFwdIt =
+ std::is_convertible_v<typename std::iterator_traits<Iterator>::iterator_category,
+ std::forward_iterator_tag>;
+ if constexpr (IsFwdIt) {
+ const qsizetype n = std::distance(first, last);
+ if (n > capacity())
+ reallocate_impl(prealloc, array, 0, n); // clear & reserve n
+ }
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(qsizetype asize, qsizetype aalloc)
+ auto dst = begin();
+ const auto dend = end();
+ while (true) {
+ if (first == last) { // ran out of elements to assign
+ std::destroy(dst, dend);
+ break;
+ }
+ if (dst == dend) { // ran out of existing elements to overwrite
+ if constexpr (IsFwdIt) {
+ dst = std::uninitialized_copy(first, last, dst);
+ break;
+ } else {
+ do {
+ emplace_back_impl(prealloc, array, *first);
+ } while (++first != last);
+ return; // size() is already correct (and dst invalidated)!
+ }
+ }
+ *dst = *first; // overwrite existing element
+ ++dst;
+ ++first;
+ }
+ this->s = dst - begin();
+}
+
+template <class T>
+Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc)
{
Q_ASSERT(aalloc >= asize);
- T *oldPtr = ptr;
- qsizetype osize = s;
+ Q_ASSERT(data());
+ T *oldPtr = data();
+ qsizetype osize = size();
const qsizetype copySize = qMin(asize, osize);
- Q_ASSUME(copySize >= 0);
- if (aalloc != a) {
- if (aalloc > Prealloc) {
- T* newPtr = reinterpret_cast<T *>(malloc(aalloc * sizeof(T)));
+ Q_ASSERT(copySize >= 0);
+
+ if (aalloc != capacity()) {
+ QVLABaseBase::malloced_ptr guard;
+ void *newPtr;
+ qsizetype newA;
+ if (aalloc > prealloc) {
+ newPtr = malloc(aalloc * sizeof(T));
+ guard.reset(newPtr);
Q_CHECK_PTR(newPtr); // could throw
// by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here
- ptr = newPtr;
- a = aalloc;
- } else {
- ptr = reinterpret_cast<T *>(array);
- a = Prealloc;
- }
- s = 0;
- if (!QTypeInfoQuery<T>::isRelocatable) {
- QT_TRY {
- // move all the old elements
- while (s < copySize) {
- new (ptr+s) T(std::move(*(oldPtr+s)));
- (oldPtr+s)->~T();
- s++;
- }
- } QT_CATCH(...) {
- // clean up all the old objects and then free the old ptr
- qsizetype sClean = s;
- while (sClean < osize)
- (oldPtr+(sClean++))->~T();
- if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
- free(oldPtr);
- QT_RETHROW;
- }
+ newA = aalloc;
} else {
- memcpy(static_cast<void *>(ptr), static_cast<const void *>(oldPtr), copySize * sizeof(T));
+ newPtr = array;
+ newA = prealloc;
}
+ QtPrivate::q_uninitialized_relocate_n(oldPtr, copySize,
+ reinterpret_cast<T *>(newPtr));
+ // commit:
+ ptr = newPtr;
+ guard.release();
+ a = newA;
}
s = copySize;
- if (QTypeInfo<T>::isComplex) {
- // destroy remaining old objects
- while (osize > asize)
- (oldPtr+(--osize))->~T();
+ // destroy remaining old objects
+ if constexpr (QTypeInfo<T>::isComplex) {
+ if (osize > asize)
+ std::destroy(oldPtr + asize, oldPtr + osize);
}
- if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
+ if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != data())
free(oldPtr);
-
- if (QTypeInfo<T>::isComplex) {
- // call default constructor for new objects (which can throw)
- while (s < asize)
- new (ptr+(s++)) T;
- } else {
- s = asize;
- }
}
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(qsizetype i) const
+template <class T>
+Q_OUTOFLINE_TEMPLATE T QVLABase<T>::value(qsizetype i) const
{
if (size_t(i) >= size_t(size()))
return T();
- return at(i);
+ return operator[](i);
}
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(qsizetype i, const T &defaultValue) const
+template <class T>
+Q_OUTOFLINE_TEMPLATE T QVLABase<T>::value(qsizetype i, const T &defaultValue) const
{
- return (size_t(i) >= size_t(size())) ? defaultValue : at(i);
+ return (size_t(i) >= size_t(size())) ? defaultValue : operator[](i);
}
template <class T, qsizetype Prealloc>
inline void QVarLengthArray<T, Prealloc>::insert(qsizetype i, T &&t)
-{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
+{ verify(i, 0);
insert(cbegin() + i, std::move(t)); }
template <class T, qsizetype Prealloc>
inline void QVarLengthArray<T, Prealloc>::insert(qsizetype i, const T &t)
-{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
+{ verify(i, 0);
insert(begin() + i, 1, t); }
template <class T, qsizetype Prealloc>
inline void QVarLengthArray<T, Prealloc>::insert(qsizetype i, qsizetype n, const T &t)
-{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
+{ verify(i, 0);
insert(begin() + i, n, t); }
-template <class T, qsizetype Prealloc>
-inline void QVarLengthArray<T, Prealloc>::remove(qsizetype i, qsizetype n)
-{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= s, "QVarLengthArray::remove", "index out of range");
+template <class T>
+inline void QVLABase<T>::remove(qsizetype i, qsizetype n)
+{ verify(i, n);
erase(begin() + i, begin() + i + n); }
-template <class T, qsizetype Prealloc>
-inline void QVarLengthArray<T, Prealloc>::remove(qsizetype i)
-{ Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::remove", "index out of range");
- erase(begin() + i, begin() + i + 1); }
+template <class T>
+template <typename AT>
+inline qsizetype QVLABase<T>::removeAll(const AT &t)
+{ return QtPrivate::sequential_erase_with_copy(*this, t); }
+template <class T>
+template <typename AT>
+inline bool QVLABase<T>::removeOne(const AT &t)
+{ return QtPrivate::sequential_erase_one(*this, t); }
+template <class T>
+template <typename Predicate>
+inline qsizetype QVLABase<T>::removeIf(Predicate pred)
+{ return QtPrivate::sequential_erase_if(*this, pred); }
+#if QT_DEPRECATED_SINCE(6, 3)
template <class T, qsizetype Prealloc>
inline void QVarLengthArray<T, Prealloc>::prepend(T &&t)
{ insert(cbegin(), std::move(t)); }
template <class T, qsizetype Prealloc>
inline void QVarLengthArray<T, Prealloc>::prepend(const T &t)
{ insert(begin(), 1, t); }
+#endif
-template <class T, qsizetype Prealloc>
-inline void QVarLengthArray<T, Prealloc>::replace(qsizetype i, const T &t)
+template <class T>
+inline void QVLABase<T>::replace(qsizetype i, const T &t)
{
- Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::replace", "index out of range");
- const T copy(t);
- data()[i] = copy;
+ verify(i);
+ data()[i] = t;
}
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, T &&t)
+template <class T>
+template <typename...Args>
+Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::emplace_impl(qsizetype prealloc, void *array, const_iterator before, Args &&...args) -> iterator
{
Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
-
- qsizetype offset = qsizetype(before - ptr);
- reserve(s + 1);
- if (!QTypeInfo<T>::isRelocatable) {
- T *b = ptr + offset;
- T *i = ptr + s;
- T *j = i + 1;
- // The new end-element needs to be constructed, the rest must be move assigned
- if (i != b) {
- new (--j) T(std::move(*--i));
- while (i != b)
- *--j = std::move(*--i);
- *b = std::move(t);
- } else {
- new (b) T(std::move(t));
- }
- } else {
- T *b = ptr + offset;
- memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (s - offset) * sizeof(T));
- new (b) T(std::move(t));
- }
- s += 1;
- return ptr + offset;
+ Q_ASSERT(size() <= capacity());
+ Q_ASSERT(capacity() > 0);
+
+ const qsizetype offset = qsizetype(before - cbegin());
+ emplace_back_impl(prealloc, array, std::forward<Args>(args)...);
+ const auto b = begin() + offset;
+ const auto e = end();
+ QtPrivate::q_rotate(b, e - 1, e);
+ return b;
}
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, size_type n, const T &t)
+template <class T>
+Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::insert_impl(qsizetype prealloc, void *array, const_iterator before, qsizetype n, const T &t) -> iterator
{
Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
- qsizetype offset = qsizetype(before - ptr);
- if (n != 0) {
- resize(s + n);
- const T copy(t);
- if (!QTypeInfoQuery<T>::isRelocatable) {
- T *b = ptr + offset;
- T *j = ptr + s;
- T *i = j - n;
- while (i != b)
- *--j = *--i;
- i = b + n;
- while (i != b)
- *--i = copy;
- } else {
- T *b = ptr + offset;
- T *i = b + n;
- memmove(static_cast<void *>(i), static_cast<const void *>(b), (s - offset - n) * sizeof(T));
- while (i != b)
- new (--i) T(copy);
- }
- }
- return ptr + offset;
+ const qsizetype offset = qsizetype(before - cbegin());
+ resize_impl(prealloc, array, size() + n, t);
+ const auto b = begin() + offset;
+ const auto e = end();
+ QtPrivate::q_rotate(b, e - n, e);
+ return b;
}
-template <class T, qsizetype Prealloc>
-Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::erase(const_iterator abegin, const_iterator aend)
+template <class T>
+Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::erase(const_iterator abegin, const_iterator aend) -> iterator
{
- Q_ASSERT_X(isValidIterator(abegin), "QVarLengthArray::insert", "The specified const_iterator argument 'abegin' is invalid");
- Q_ASSERT_X(isValidIterator(aend), "QVarLengthArray::insert", "The specified const_iterator argument 'aend' is invalid");
+ Q_ASSERT_X(isValidIterator(abegin), "QVarLengthArray::erase", "The specified const_iterator argument 'abegin' is invalid");
+ Q_ASSERT_X(isValidIterator(aend), "QVarLengthArray::erase", "The specified const_iterator argument 'aend' is invalid");
- qsizetype f = qsizetype(abegin - ptr);
- qsizetype l = qsizetype(aend - ptr);
+ qsizetype f = qsizetype(abegin - cbegin());
+ qsizetype l = qsizetype(aend - cbegin());
qsizetype n = l - f;
- if (QTypeInfo<T>::isComplex) {
- std::copy(ptr + l, ptr + s, QT_MAKE_CHECKED_ARRAY_ITERATOR(ptr + f, s - f));
- T *i = ptr + s;
- T *b = ptr + s - n;
- while (i != b) {
- --i;
- i->~T();
- }
+
+ if (n == 0) // avoid UB in std::move() below
+ return data() + f;
+
+ Q_ASSERT(n > 0); // aend must be reachable from abegin
+
+ if constexpr (!QTypeInfo<T>::isRelocatable) {
+ std::move(begin() + l, end(), QT_MAKE_CHECKED_ARRAY_ITERATOR(begin() + f, size() - f));
+ std::destroy(end() - n, end());
} else {
- memmove(static_cast<void *>(ptr + f), static_cast<const void *>(ptr + l), (s - l) * sizeof(T));
+ std::destroy(abegin, aend);
+ memmove(static_cast<void *>(data() + f), static_cast<const void *>(data() + l), (size() - l) * sizeof(T));
}
- s -= n;
- return ptr + f;
+ this->s -= n;
+ return data() + f;
}
+#ifdef Q_QDOC
+// Fake definitions for qdoc, only the redeclaration is used.
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
-{
- if (l.size() != r.size())
- return false;
- const T *rb = r.begin();
- const T *b = l.begin();
- const T *e = l.end();
- return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(rb, r.size()));
-}
-
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
-{
- return !(l == r);
-}
-
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-bool operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end())))
-{
- return std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end());
-}
-
+bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-inline bool operator>(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(lhs < rhs))
-{
- return rhs < lhs;
-}
-
+bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
+template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
+bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-inline bool operator<=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(lhs < rhs))
+bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+{ return bool{}; }
+#endif
+
+template <typename T, qsizetype Prealloc>
+size_t qHash(const QVarLengthArray<T, Prealloc> &key, size_t seed = 0)
+ noexcept(QtPrivate::QNothrowHashable_v<T>)
{
- return !(lhs > rhs);
+ return key.hash(seed);
}
-template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-inline bool operator>=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- noexcept(noexcept(lhs < rhs))
+template <typename T, qsizetype Prealloc, typename AT>
+qsizetype erase(QVarLengthArray<T, Prealloc> &array, const AT &t)
{
- return !(lhs < rhs);
+ return array.removeAll(t);
}
-template <typename T, qsizetype Prealloc>
-size_t qHash(const QVarLengthArray<T, Prealloc> &key, size_t seed = 0)
- noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
+template <typename T, qsizetype Prealloc, typename Predicate>
+qsizetype erase_if(QVarLengthArray<T, Prealloc> &array, Predicate pred)
{
- return qHashRange(key.cbegin(), key.cend(), seed);
+ return array.removeIf(pred);
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
index 5970081d85..4467e0c65a 100644
--- a/src/corelib/tools/qvarlengtharray.qdoc
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QVarLengthArray
@@ -90,6 +66,11 @@
\sa QList
*/
+/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::QVarLengthArray()
+
+ Constructs an array with an initial size of zero.
+*/
+
/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::QVarLengthArray(qsizetype size)
Constructs an array with an initial size of \a size elements.
@@ -100,21 +81,34 @@
\l{default-constructed value}.
*/
+/*!
+ \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::QVarLengthArray(qsizetype size, const T &v)
+ \since 6.4
+
+ Constructs an array with an initial size of \a size elements filled with
+ copies of \a v.
+
+ \note This constructor is only available when \c T is copy-constructible.
+
+ \sa size(), squeeze()
+*/
+
/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::QVarLengthArray(std::initializer_list<T> args)
\since 5.5
Constructs an array from the std::initializer_list given by \a args.
-
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
*/
-/*! \fn template<class T, qsizetype Prealloc> template<typename InputIterator> QVarLengthArray<T, Prealloc>::QVarLengthArray(InputIterator first, InputIterator last)
+/*! \fn template<class T, qsizetype Prealloc> template<typename InputIterator, QVarLengthArray<T, Prealloc>::if_input_iterator<InputIterator>> QVarLengthArray<T, Prealloc>::QVarLengthArray(InputIterator first, InputIterator last)
\since 5.14
Constructs an array with the contents in the iterator range [\a first, \a last).
+ This constructor only participates in overload resolution if
+ \c InputIterator meets the requirements of an
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}.
+
The value type of \c InputIterator must be convertible to \c T.
*/
@@ -146,6 +140,15 @@
\sa isEmpty(), resize()
*/
+/*! \fn template<class T, qsizetype Prealloc> qsizetype QVarLengthArray<T, Prealloc>::max_size()
+ \since 6.8
+
+ This function is provided for STL compatibility.
+ It returns the maximum number of elements that the array can
+ theoretically hold. In practice, the number can be much smaller,
+ limited by the amount of memory available to the system.
+*/
+
/*! \fn template<class T, qsizetype Prealloc> T& QVarLengthArray<T, Prealloc>::first()
Returns a reference to the first item in the array. The array must
@@ -240,6 +243,19 @@
\sa size(), squeeze()
*/
+/*!
+ \fn template<class T, qsizetype Prealloc> void QVarLengthArray<T, Prealloc>::resize(qsizetype size, const T &v)
+ \since 6.4
+
+ Sets the size of the array to \a size. If \a size is greater than
+ the current size, copies of \a v are added to the end. If \a size is
+ less than the current size, elements are removed from the end.
+
+ \note This function is only available when \c T is copy-constructible.
+
+ \sa size(), squeeze()
+*/
+
/*! \fn template<class T, qsizetype Prealloc> qsizetype QVarLengthArray<T, Prealloc>::capacity() const
Returns the maximum number of elements that can be stored in the
@@ -414,9 +430,6 @@
\since 5.5
Assigns the values of \a list to this array, and returns a reference to this array.
-
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
*/
/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
@@ -458,6 +471,15 @@
\a defaultValue.
*/
+/*
+ \var QVarLengthArray::PreallocatedSize
+ \since 6.8
+
+ The same value as the \c{Prealloc} template argument. Provided for easier
+ access compared to manually extracting the value from the template
+ argument.
+*/
+
/*!
\typedef QVarLengthArray::size_type
\since 4.7
@@ -540,6 +562,8 @@
\fn template<class T, qsizetype Prealloc> void QVarLengthArray<T, Prealloc>::prepend(T &&value)
\since 4.8
+ \deprecated [6.3] This is slow. If you must, use \c{insert(cbegin(), ~~~)} instead.
+
Inserts \a value at the beginning of the array.
@@ -564,16 +588,6 @@
\sa operator[](), remove()
*/
-/*! \fn template<class T, qsizetype Prealloc> void QVarLengthArray<T, Prealloc>::remove(qsizetype i)
-
- \overload
- \since 4.8
-
- Removes the element at index position \a i.
-
- \sa insert(), replace()
-*/
-
/*! \fn template<class T, qsizetype Prealloc> void QVarLengthArray<T, Prealloc>::remove(qsizetype i, qsizetype count)
\overload
@@ -753,6 +767,27 @@
\a before. Returns an iterator pointing at the inserted item.
*/
+/*!
+ \fn template <class T, qsizetype Prealloc> template <typename...Args> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::emplace(const_iterator pos, Args &&...args)
+
+ \since 6.3
+
+ Inserts an item in front of the item pointed to by the iterator
+ \a pos, passing \a args to its constructor.
+
+ Returns an iterator pointing at the emplaced item.
+*/
+
+/*!
+ \fn template <class T, qsizetype Prealloc> template <typename...Args> T &QVarLengthArray<T, Prealloc>::emplace_back(Args &&...args)
+ \since 6.3
+
+ Inserts an item at the back of this QVarLengthArray, passing
+ \a args to its constructor.
+
+ Returns a reference to the emplaced item.
+*/
+
/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, qsizetype count, const T &value)
\since 4.8
@@ -775,7 +810,7 @@
This function requires the value type to have an implementation
of \c operator==().
- \sa operator!=()
+ \sa {operator!=(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right)}{operator!=()}
*/
/*! \fn template<typename T, qsizetype Prealloc1, qsizetype Prealloc2> bool operator!=(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right)
@@ -790,7 +825,7 @@
This function requires the value type to have an implementation
of \c operator==().
- \sa operator==()
+ \sa {operator==(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right)}{operator==()}
*/
/*! \fn template<typename T, qsizetype Prealloc1, qsizetype Prealloc2> bool operator<(const QVarLengthArray<T,Prealloc1> &lhs, const QVarLengthArray<T,Prealloc2> &rhs)
@@ -874,7 +909,7 @@
\sa append(), operator<<()
*/
-/*! \fn template<class T, qsizetype Prealloc> qsizetype QVarLengthArray<T, Prealloc>::indexOf(const T &value, qsizetype from = 0) const
+/*! \fn template<class T, qsizetype Prealloc> template <typename AT = T> qsizetype QVarLengthArray<T, Prealloc>::indexOf(const AT &value, qsizetype from = 0) const
\since 5.3
Returns the index position of the first occurrence of \a value in
@@ -887,7 +922,7 @@
\sa lastIndexOf(), contains()
*/
-/*! \fn template<class T, qsizetype Prealloc> qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const T &value, qsizetype from = -1) const
+/*! \fn template<class T, qsizetype Prealloc> template <typename AT = T> qsizetype QVarLengthArray<T, Prealloc>::lastIndexOf(const AT &value, qsizetype from = -1) const
\since 5.3
Returns the index position of the last occurrence of the value \a
@@ -901,7 +936,7 @@
\sa indexOf(), contains()
*/
-/*! \fn template<class T, qsizetype Prealloc> bool QVarLengthArray<T, Prealloc>::contains(const T &value) const
+/*! \fn template<class T, qsizetype Prealloc> template <typename AT = T> bool QVarLengthArray<T, Prealloc>::contains(const AT &value) const
\since 5.3
Returns \c true if the array contains an occurrence of \a value;
@@ -921,3 +956,92 @@
Returns the hash value for \a key, using \a seed to seed the
calculation.
*/
+
+/*! \fn template <typename T, qsizetype Prealloc> template <typename AT = T> qsizetype QVarLengthArray<T, Prealloc>::removeAll(const AT &t)
+ \since 6.1
+
+ Removes all elements that compare equal to \a t from the
+ array. Returns the number of elements removed, if any.
+
+ \sa removeOne()
+*/
+
+/*! \fn template <typename T, qsizetype Prealloc> template <typename AT = T> bool QVarLengthArray<T, Prealloc>::removeOne(const AT &t)
+ \since 6.1
+
+ Removes the first element that compares equal to \a t from the
+ array. Returns whether an element was, in fact, removed.
+
+ \sa removeAll()
+*/
+
+/*! \fn template <typename T, qsizetype Prealloc> template <typename Predicate> qsizetype QVarLengthArray<T, Prealloc>::removeIf(Predicate pred)
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the array. Returns the number of elements removed, if any.
+
+ \sa removeAll()
+*/
+
+/*! \fn template <typename T, qsizetype Prealloc, typename AT> qsizetype erase(QVarLengthArray<T, Prealloc> &array, const AT &t)
+ \relates QVarLengthArray
+ \since 6.1
+
+ Removes all elements that compare equal to \a t from the
+ array \a array. Returns the number of elements removed, if any.
+
+ \note \a t is not allowed to be a reference to an element inside \a
+ array. If you cannot be sure that this is not the case, take a copy
+ of \a t and call this function with the copy.
+
+ \sa erase_if()
+*/
+
+/*! \fn template <typename T, qsizetype Prealloc, typename Predicate> qsizetype erase_if(QVarLengthArray<T, Prealloc> &array, Predicate pred)
+ \relates QVarLengthArray
+ \since 6.1
+
+ Removes all elements for which the predicate \a pred returns true
+ from the list \a array. Returns the number of elements removed, if
+ any.
+
+ \sa erase()
+*/
+
+/*! \fn template <class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>& QVarLengthArray<T, Prealloc>::assign(qsizetype n, const T &t)
+ \since 6.6
+
+ Replaces the contents of this container with \a n copies of \a t.
+
+ The size of this container will be equal to \a n. This function will only
+ allocate memory if \a n exceeds the capacity of the container.
+*/
+
+/*! \fn template <class T, qsizetype Prealloc> template <typename InputIterator, QVarLengthArray<T, Prealloc>::if_input_iterator<InputIterator>> QVarLengthArray<T, Prealloc>& QVarLengthArray<T, Prealloc>::assign(InputIterator first, InputIterator last)
+ \since 6.6
+
+ Replaces the contents of this container with a copy of the elements in the
+ iterator range [\a first, \a last).
+
+ The size of this container will be equal to the number of elements in the
+ range [\a first, \a last). This function will only allocate memory if the
+ number of elements in the range exceeds the capacity of the container.
+
+ This function overload only participates in overload resolution if
+ \c InputIterator meets the requirements of an
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}.
+
+ The behavior is undefined if either argument is an iterator into *this.
+*/
+
+/*! \fn template <class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>& QVarLengthArray<T, Prealloc>::assign(std::initializer_list<T> list)
+ \since 6.6
+
+ Replaces the contents of this container with a copy of the elements of \a list.
+
+ The size of this container will be equal to the number of elements in \a list.
+
+ This function only allocates memory if the number of elements in \a list
+ exceeds the capacity of the container.
+*/
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 8d880407dd..4fad2bce8f 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVECTOR_H
#define QVECTOR_H
@@ -43,6 +7,12 @@
#include <QtCore/qlist.h>
#include <QtCore/qcontainerfwd.h>
+#if 0
+#pragma qt_class(QVector)
+#pragma qt_class(QMutableVectorIterator)
+#pragma qt_class(QVectorIterator)
+#endif
+
QT_BEGIN_NAMESPACE
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
diff --git a/src/corelib/tools/qvector_msvc.cpp b/src/corelib/tools/qvector_msvc.cpp
deleted file mode 100644
index e3815852dc..0000000000
--- a/src/corelib/tools/qvector_msvc.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// ### Qt6: verify if we can remove this, somehow.
-// First, try to see if the extern template from qlist.h is necessary.
-// If it still is, check if removing the copy constructors in qarraydata.h
-// make the calling convention of both sets of begin() and end() functions
-// match, as it does for the IA-64 C++ ABI.
-
-#ifdef QVECTOR_H
-# error "This file must be compiled with no precompiled headers"
-#endif
-
-// the Q_TEMPLATE_EXTERN at the bottom of qlist.h will do the trick
-#include <QtCore/qlist.h>
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
index 517f026547..af95875b44 100644
--- a/src/corelib/tools/qversionnumber.cpp
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qversionnumber.h>
#include <QtCore/qhash.h>
@@ -57,6 +21,8 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QVersionNumber)
+
/*!
\class QVersionNumber
\inmodule QtCore
@@ -64,6 +30,7 @@ QT_BEGIN_NAMESPACE
\brief The QVersionNumber class contains a version number with an arbitrary
number of segments.
+ \compares strong
\snippet qversionnumber/main.cpp 0
*/
@@ -105,18 +72,23 @@ QT_BEGIN_NAMESPACE
\fn QVersionNumber::QVersionNumber(QList<int> &&seg)
Move-constructs a version number from the list of numbers contained in \a seg.
-
- This constructor is only enabled if the compiler supports C++11 move semantics.
*/
/*!
\fn QVersionNumber::QVersionNumber(std::initializer_list<int> args)
- Construct a version number from the std::initializer_list specified by
+ Constructs a version number from the std::initializer_list specified by
\a args.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(QSpan<const int> args)
+ \since 6.8
+
+ Constructs a version number from the span specified by \a args.
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
+ \note In Qt versions prior to 6.8, QVersionNumber could only be constructed
+ from QList, QVarLenthArray or std::initializer_list.
*/
/*!
@@ -168,7 +140,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QList<int>& QVersionNumber::segments() const
+ \fn QList<int> QVersionNumber::segments() const
Returns all of the numerical segments.
@@ -181,22 +153,22 @@ QList<int> QVersionNumber::segments() const
QList<int> result;
result.resize(segmentCount());
- for (int i = 0; i < segmentCount(); ++i)
+ for (qsizetype i = 0; i < segmentCount(); ++i)
result[i] = segmentAt(i);
return result;
}
/*!
- \fn int QVersionNumber::segmentAt(int index) const
+ \fn int QVersionNumber::segmentAt(qsizetype index) const
- Returns the segement value at \a index. If the index does not exist,
+ Returns the segment value at \a index. If the index does not exist,
returns 0.
\sa segments(), segmentCount()
*/
/*!
- \fn int QVersionNumber::segmentCount() const
+ \fn qsizetype QVersionNumber::segmentCount() const
Returns the number of integers stored in segments().
@@ -204,6 +176,55 @@ QList<int> QVersionNumber::segments() const
*/
/*!
+ \typedef QVersionNumber::const_iterator
+ \typedef QVersionNumber::const_reverse_iterator
+ \since 6.8
+
+ Typedefs for an opaque class that implements a (reverse) random-access
+ iterator over QVersionNumber segments.
+
+ \note QVersionNumber does not support modifying segments in-place, so
+ there is no mutable iterator.
+*/
+
+/*!
+ \typedef QVersionNumber::value_type
+ \typedef QVersionNumber::difference_type
+ \typedef QVersionNumber::size_type
+ \typedef QVersionNumber::reference
+ \typedef QVersionNumber::const_reference
+ \typedef QVersionNumber::pointer
+ \typedef QVersionNumber::const_pointer
+ \since 6.8
+
+ Provided for STL-compatibility.
+
+ \note QVersionNumber does not support modifying segments in-place, so
+ reference and const_reference, as well as pointer and const_pointer are
+ pairwise the same types.
+*/
+
+/*!
+ \fn QVersionNumber::begin() const
+ \fn QVersionNumber::end() const;
+ \fn QVersionNumber::rbegin() const
+ \fn QVersionNumber::rend() const;
+ \fn QVersionNumber::cbegin() const
+ \fn QVersionNumber::cend() const;
+ \fn QVersionNumber::crbegin() const
+ \fn QVersionNumber::crend() const;
+ \fn QVersionNumber::constBegin() const;
+ \fn QVersionNumber::constEnd() const;
+ \since 6.8
+
+ Returns a const_iterator or const_reverse_iterator, respectively, pointing
+ to the first or one past the last segment of this version number.
+
+ \note QVersionNumber does not support modifying segments in-place, so
+ there is no mutable iterator.
+*/
+
+/*!
\fn QVersionNumber QVersionNumber::normalized() const
Returns an equivalent version number but with all trailing zeros removed.
@@ -215,7 +236,7 @@ QList<int> QVersionNumber::segments() const
*/
QVersionNumber QVersionNumber::normalized() const
{
- int i;
+ qsizetype i;
for (i = m_segments.size(); i; --i)
if (m_segments.at(i - 1) != 0)
break;
@@ -239,7 +260,7 @@ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const noexcept
{
if (segmentCount() > other.segmentCount())
return false;
- for (int i = 0; i < segmentCount(); ++i) {
+ for (qsizetype i = 0; i < segmentCount(); ++i) {
if (segmentAt(i) != other.segmentAt(i))
return false;
}
@@ -261,7 +282,7 @@ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const noexcept
*/
int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept
{
- int commonlen;
+ qsizetype commonlen;
if (Q_LIKELY(!v1.m_segments.isUsingPointer() && !v2.m_segments.isUsingPointer())) {
// we can't use memcmp because it interprets the data as unsigned bytes
@@ -269,12 +290,12 @@ int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2)
const qint8 *ptr2 = v2.m_segments.inline_segments + InlineSegmentStartIdx;
commonlen = qMin(v1.m_segments.size(),
v2.m_segments.size());
- for (int i = 0; i < commonlen; ++i)
+ for (qsizetype i = 0; i < commonlen; ++i)
if (int x = ptr1[i] - ptr2[i])
return x;
} else {
commonlen = qMin(v1.segmentCount(), v2.segmentCount());
- for (int i = 0; i < commonlen; ++i) {
+ for (qsizetype i = 0; i < commonlen; ++i) {
if (v1.segmentAt(i) != v2.segmentAt(i))
return v1.segmentAt(i) - v2.segmentAt(i);
}
@@ -311,8 +332,8 @@ int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2)
QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
const QVersionNumber &v2)
{
- int commonlen = qMin(v1.segmentCount(), v2.segmentCount());
- int i;
+ qsizetype commonlen = qMin(v1.segmentCount(), v2.segmentCount());
+ qsizetype i;
for (i = 0; i < commonlen; ++i) {
if (v1.segmentAt(i) != v2.segmentAt(i))
break;
@@ -328,8 +349,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
}
/*!
- \fn bool operator<(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator<(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is less than \a rhs; otherwise returns \c false.
@@ -337,8 +357,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is less than or equal to \a rhs; otherwise
returns \c false.
@@ -347,8 +366,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator>(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator>(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is greater than \a rhs; otherwise returns \c
false.
@@ -357,8 +375,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is greater than or equal to \a rhs; otherwise
returns \c false.
@@ -367,8 +384,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator==(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
@@ -376,8 +392,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
*/
/*!
- \fn bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs)
- \relates QVersionNumber
+ \fn bool QVersionNumber::operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs)
Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
\c false.
@@ -397,17 +412,19 @@ QString QVersionNumber::toString() const
QString version;
version.reserve(qMax(segmentCount() * 2 - 1, 0));
bool first = true;
- for (int i = 0; i < segmentCount(); ++i) {
+ for (qsizetype i = 0; i < segmentCount(); ++i) {
if (!first)
- version += QLatin1Char('.');
+ version += u'.';
version += QString::number(segmentAt(i));
first = false;
}
return version;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
+ \fn QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suffixIndex)
+ \since 6.4
+
Constructs a QVersionNumber from a specially formatted \a string of
non-negative decimal numbers delimited by a period (\c{.}).
@@ -415,74 +432,86 @@ QString QVersionNumber::toString() const
is considered to be the suffix string. The start index of that string will be
stored in \a suffixIndex if it is not null.
- \snippet qversionnumber/main.cpp 3
+ \snippet qversionnumber/main.cpp 3-latin1-1
+
+ \note In versions prior to Qt 6.4, this function was overloaded for QString,
+ QLatin1StringView and QStringView instead, and \a suffixIndex was an \c{int*}.
\sa isNull()
*/
-QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixIndex)
+
+static QVersionNumber from_string(QLatin1StringView string, qsizetype *suffixIndex)
{
- return fromString(QLatin1String(string.toLatin1()), suffixIndex);
-}
-#endif
+ // 32 should be more than enough, and, crucially, it means we're allocating
+ // not more (and often less) often when compared with direct QList usage
+ // for all possible segment counts (under the constraint that we don't want
+ // to keep more capacity around for the lifetime of the resulting
+ // QVersionNumber than required), esp. in the common case where the inline
+ // storage can be used.
+ QVarLengthArray<int, 32> seg;
-/*!
- \since 5.10
- \overload
+ const char *start = string.begin();
+ const char *lastGoodEnd = start;
+ const char *endOfString = string.end();
- Constructs a QVersionNumber from a specially formatted \a string of
- non-negative decimal numbers delimited by '.'.
+ do {
+ // parsing as unsigned so a minus sign is rejected
+ auto [value, used] = qstrntoull(start, endOfString - start, 10);
+ if (used <= 0 || value > qulonglong(std::numeric_limits<int>::max()))
+ break;
+ seg.append(int(value));
+ start += used + 1;
+ lastGoodEnd = start - 1;
+ } while (start < endOfString && *lastGoodEnd == '.');
- Once the numerical segments have been parsed, the remainder of the string
- is considered to be the suffix string. The start index of that string will be
- stored in \a suffixIndex if it is not null.
+ if (suffixIndex)
+ *suffixIndex = lastGoodEnd - string.begin();
- \snippet qversionnumber/main.cpp 3
+ return QVersionNumber(seg);
+}
- \sa isNull()
-*/
-QVersionNumber QVersionNumber::fromString(QStringView string, int *suffixIndex)
+static QVersionNumber from_string(q_no_char8_t::QUtf8StringView string, qsizetype *suffixIndex)
{
- return fromString(QLatin1String(string.toLatin1()), suffixIndex);
+ return from_string(QLatin1StringView(string.data(), string.size()), suffixIndex);
}
-/*!
- \since 5.10
- \overload
-
- Constructs a QVersionNumber from a specially formatted \a string of
- non-negative decimal numbers delimited by '.'.
-
- Once the numerical segments have been parsed, the remainder of the string
- is considered to be the suffix string. The start index of that string will be
- stored in \a suffixIndex if it is not null.
+// in qstring.cpp
+extern void qt_to_latin1(uchar *dst, const char16_t *uc, qsizetype len);
- \snippet qversionnumber/main.cpp 3-latin1-1
+static QVersionNumber from_string(QStringView string, qsizetype *suffixIndex)
+{
+ QVarLengthArray<char> copy;
+ copy.resize(string.size());
+ qt_to_latin1(reinterpret_cast<uchar*>(copy.data()), string.utf16(), string.size());
+ return from_string(QLatin1StringView(copy.data(), copy.size()), suffixIndex);
+}
- \sa isNull()
-*/
-QVersionNumber QVersionNumber::fromString(QLatin1String string, int *suffixIndex)
+QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suffixIndex)
{
- QList<int> seg;
+ return string.visit([=] (auto string) { return from_string(string, suffixIndex); });
+}
- const char *start = string.begin();
- const char *end = start;
- const char *lastGoodEnd = start;
- const char *endOfString = string.end();
+void QVersionNumber::SegmentStorage::setListData(const QList<int> &seg)
+{
+ pointer_segments = new QList<int>(seg);
+}
- do {
- bool ok = false;
- const qulonglong value = qstrtoull(start, &end, 10, &ok);
- if (!ok || value > qulonglong(std::numeric_limits<int>::max()))
- break;
- seg.append(int(value));
- start = end + 1;
- lastGoodEnd = end;
- } while (start < endOfString && (end < endOfString && *end == '.'));
+void QVersionNumber::SegmentStorage::setListData(QList<int> &&seg)
+{
+ pointer_segments = new QList<int>(std::move(seg));
+}
- if (suffixIndex)
- *suffixIndex = int(lastGoodEnd - string.begin());
+void QVersionNumber::SegmentStorage::setListData(const int *first, const int *last)
+{
+ pointer_segments = new QList<int>(first, last);
+}
- return QVersionNumber(std::move(seg));
+void QVersionNumber::SegmentStorage::resize(qsizetype len)
+{
+ if (isUsingPointer())
+ pointer_segments->resize(len);
+ else
+ setInlineSize(len);
}
void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic)
@@ -535,13 +564,13 @@ QDataStream& operator>>(QDataStream &in, QVersionNumber &version)
QDebug operator<<(QDebug debug, const QVersionNumber &version)
{
QDebugStateSaver saver(debug);
- debug.noquote() << version.toString();
+ debug.nospace().noquote();
+ debug << "QVersionNumber(" << version.toString() << ")";
return debug;
}
#endif
/*!
- \fn size_t qHash(const QVersionNumber &key, size_t seed)
\relates QHash
\since 5.6
@@ -556,199 +585,4 @@ size_t qHash(const QVersionNumber &key, size_t seed)
return seed;
}
-/*!
- \class QTypeRevision
- \inmodule QtCore
- \since 6.0
- \brief The QTypeRevision class contains a lightweight representation of
- a version number with two 8-bit segments, major and minor, either
- of which can be unknown.
-
- Use this class to describe revisions of a type. Compatible revisions can be
- expressed as increments of the minor version. Breaking changes can be
- expressed as increments of the major version. The return values of
- \l QMetaMethod::revision() and \l QMetaProperty::revision() can be passed to
- \l QTypeRevision::fromEncodedVersion(). The resulting major and minor versions
- specify in which Qt versions the properties and methods were added.
-
- \sa QMetaMethod::revision(), QMetaProperty::revision()
-*/
-
-/*!
- \fn template<typename Integer> static bool QTypeRevision::isValidSegment(Integer segment)
-
- Returns true if the given number can be used as either major or minor
- version in a QTypeRevision. Valid segments need to be \c {>= 0} and \c {< 255}.
-*/
-
-/*!
- \fn QTypeRevision::QTypeRevision()
-
- Produces an invalid revision.
-
- \sa isValid()
-*/
-
-/*!
- \fn template <typename Major, typename Minor> static QTypeRevision QTypeRevision::fromVersion(Major majorVersion, Minor minorVersion)
-
- Produces a QTypeRevision from the given \a majorVersion and \a minorVersion,
- both of which need to be a valid segments.
-
- \sa isValidSegment()
-*/
-
-/*!
- \fn template <typename Major> static QTypeRevision QTypeRevision::fromMajorVersion(Major majorVersion)
-
- Produces a QTypeRevision from the given \a majorVersion with an invalid minor
- version. \a majorVersion needs to be a valid segment.
-
- \sa isValidSegment()
-*/
-
-/*!
- \fn template <typename Minor> static QTypeRevision QTypeRevision::fromMinorVersion(Minor minorVersion)
-
- Produces a QTypeRevision from the given \a minorVersion with an invalid major
- version. \a minorVersion needs to be a valid segment.
-
- \sa isValidSegment()
-*/
-
-/*!
- \fn template <typename Integer> static QTypeRevision QTypeRevision::fromEncodedVersion(Integer value)
-
- Produces a QTypeRevision from the given \a value. \a value encodes both the
- minor and major versions in the least significant and second least
- significant byte, respectively.
-
- \a value must not have any bits outside the least significant two bytes set.
- \c Integer needs to be at least 16 bits wide, and must not have a sign bit
- in the least significant 16 bits.
-
- \sa toEncodedVersion()
-*/
-
-/*!
- \fn static QTypeRevision QTypeRevision::zero()
-
- Produces a QTypeRevision with major and minor version \c{0}.
-*/
-
-/*!
- \fn bool QTypeRevision::hasMajorVersion() const
-
- Returns true if the major version is known, otherwise false.
-
- \sa majorVersion(), hasMinorVersion()
-*/
-
-/*!
- \fn quint8 QTypeRevision::majorVersion() const
-
- Returns the major version encoded in the revision.
-
- \sa hasMajorVersion(), minorVersion()
-*/
-
-/*!
- \fn bool QTypeRevision::hasMinorVersion() const
-
- Returns true if the minor version is known, otherwise false.
-
- \sa minorVersion(), hasMajorVersion()
-*/
-
-/*!
- \fn quint8 QTypeRevision::minorVersion() const
-
- Returns the minor version encoded in the revision.
-
- \sa hasMinorVersion(), majorVersion()
-*/
-
-/*!
- \fn bool QTypeRevision::isValid() const
-
- Returns true if the major version or the minor version is known,
- otherwise false.
-
- \sa hasMajorVersion(), hasMinorVersion()
-*/
-
-/*!
- \fn template<typename Integer> Integer QTypeRevision::toEncodedVersion() const
-
- Transforms the revision into an integer value, encoding the minor
- version into the least significant byte, and the major version into
- the second least significant byte.
-
- \c Integer needs to be at least 16 bits wide, and must not have a sign bit
- in the least significant 16 bits.
-
- \sa fromEncodedVersion()
-*/
-
-#ifndef QT_NO_DATASTREAM
-/*!
- \fn QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision)
- \relates QTypeRevision
- \since 6.0
-
- Writes the revision \a revision to stream \a out.
- */
-QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision)
-{
- return out << revision.toEncodedVersion<quint16>();
-}
-
-/*!
- \fn QDataStream& operator>>(QDataStream &in, QTypeRevision &revision)
- \relates QTypeRevision
- \since 6.0
-
- Reads a revision from stream \a in and stores it in \a revision.
- */
-QDataStream& operator>>(QDataStream &in, QTypeRevision &revision)
-{
- quint16 value;
- in >> value;
- revision = QTypeRevision::fromEncodedVersion(value);
- return in;
-}
-#endif
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, const QTypeRevision &revision)
-{
- QDebugStateSaver saver(debug);
- if (revision.hasMajorVersion()) {
- if (revision.hasMinorVersion())
- debug.nospace() << revision.majorVersion() << '.' << revision.minorVersion();
- else
- debug.nospace().noquote() << revision.majorVersion() << ".x";
- } else {
- if (revision.hasMinorVersion())
- debug << revision.minorVersion();
- else
- debug.noquote() << "invalid";
- }
- return debug;
-}
-#endif
-
-/*!
- \fn size_t qHash(const QTypeRevision &key, size_t seed)
- \relates QHash
- \since 6.0
-
- Returns the hash value for the \a key, using \a seed to seed the
- calculation.
-*/
-size_t qHash(const QTypeRevision &key, size_t seed)
-{
- return qHash(key.toEncodedVersion<quint16>(), seed);
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h
index f8a2d8eae8..e7ae107226 100644
--- a/src/corelib/tools/qversionnumber.h
+++ b/src/corelib/tools/qversionnumber.h
@@ -1,53 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// Copyright (C) 2015 Keith Gardner <kreios4004@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVERSIONNUMBER_H
#define QVERSIONNUMBER_H
+#include <QtCore/qcompare.h>
+#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qlist.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qspan.h>
#include <QtCore/qstring.h>
#include <QtCore/qtypeinfo.h>
-#include <limits>
+#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
+#include <QtCore/qtyperevision.h>
+#endif // lean headers level 2
QT_BEGIN_NAMESPACE
@@ -55,8 +24,8 @@ class QVersionNumber;
Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed = 0);
#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QVersionNumber &version);
-Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QVersionNumber &version);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QVersionNumber &version);
#endif
class QVersionNumber
@@ -71,19 +40,20 @@ class QVersionNumber
enum {
// in little-endian, inline_segments[0] is shared with the pointer's LSB, while
// in big-endian, it's inline_segments[7]
- InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void*) - 1,
+ InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void *) - 1,
InlineSegmentStartIdx = !InlineSegmentMarker, // 0 for BE, 1 for LE
- InlineSegmentCount = sizeof(void*) - 1
+ InlineSegmentCount = sizeof(void *) - 1
};
static_assert(InlineSegmentCount >= 3); // at least major, minor, micro
- struct SegmentStorage {
+ struct SegmentStorage
+ {
// Note: we alias the use of dummy and inline_segments in the use of the
// union below. This is undefined behavior in C++98, but most compilers implement
// the C++11 behavior. The one known exception is older versions of Sun Studio.
union {
quintptr dummy;
- qint8 inline_segments[sizeof(void*)];
+ qint8 inline_segments[sizeof(void *)];
QList<int> *pointer_segments;
};
@@ -92,16 +62,18 @@ class QVersionNumber
SegmentStorage(const QList<int> &seg)
{
- if (dataFitsInline(seg.begin(), seg.size()))
- setInlineData(seg.begin(), seg.size());
+ if (dataFitsInline(seg.data(), seg.size()))
+ setInlineData(seg.data(), seg.size());
else
- pointer_segments = new QList<int>(seg);
+ setListData(seg);
}
+ Q_CORE_EXPORT void setListData(const QList<int> &seg);
+
SegmentStorage(const SegmentStorage &other)
{
if (other.isUsingPointer())
- pointer_segments = new QList<int>(*other.pointer_segments);
+ setListData(*other.pointer_segments);
else
dummy = other.dummy;
}
@@ -111,7 +83,7 @@ class QVersionNumber
if (isUsingPointer() && other.isUsingPointer()) {
*pointer_segments = *other.pointer_segments;
} else if (other.isUsingPointer()) {
- pointer_segments = new QList<int>(*other.pointer_segments);
+ setListData(*other.pointer_segments);
} else {
if (isUsingPointer())
delete pointer_segments;
@@ -126,48 +98,54 @@ class QVersionNumber
other.dummy = 1;
}
- SegmentStorage &operator=(SegmentStorage &&other) noexcept
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(SegmentStorage)
+
+ void swap(SegmentStorage &other) noexcept
{
- qSwap(dummy, other.dummy);
- return *this;
+ std::swap(dummy, other.dummy);
}
explicit SegmentStorage(QList<int> &&seg)
{
- if (dataFitsInline(seg.begin(), seg.size()))
- setInlineData(seg.begin(), seg.size());
+ if (dataFitsInline(std::as_const(seg).data(), seg.size()))
+ setInlineData(std::as_const(seg).data(), seg.size());
else
- pointer_segments = new QList<int>(std::move(seg));
+ setListData(std::move(seg));
}
- SegmentStorage(std::initializer_list<int> args)
+
+ Q_CORE_EXPORT void setListData(QList<int> &&seg);
+
+ explicit SegmentStorage(QSpan<const int> args)
+ : SegmentStorage(args.begin(), args.end()) {}
+
+ explicit SegmentStorage(const int *first, const int *last)
{
- if (dataFitsInline(args.begin(), int(args.size()))) {
- setInlineData(args.begin(), int(args.size()));
+ if (dataFitsInline(first, last - first)) {
+ setInlineData(first, last - first);
} else {
- pointer_segments = new QList<int>(args);
+ setListData(first, last);
}
}
+ Q_CORE_EXPORT void setListData(const int *first, const int *last);
+
~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; }
bool isUsingPointer() const noexcept
{ return (inline_segments[InlineSegmentMarker] & 1) == 0; }
- int size() const noexcept
+ qsizetype size() const noexcept
{ return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); }
- void setInlineSize(int len)
- { inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len); }
-
- void resize(int len)
+ void setInlineSize(qsizetype len)
{
- if (isUsingPointer())
- pointer_segments->resize(len);
- else
- setInlineSize(len);
+ Q_ASSERT(len <= InlineSegmentCount);
+ inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len);
}
- int at(int index) const
+ Q_CORE_EXPORT void resize(qsizetype len);
+
+ int at(qsizetype index) const
{
return isUsingPointer() ?
pointer_segments->at(index) :
@@ -185,28 +163,29 @@ class QVersionNumber
}
private:
- static bool dataFitsInline(const int *data, int len)
+ static bool dataFitsInline(const int *data, qsizetype len)
{
if (len > InlineSegmentCount)
return false;
- for (int i = 0; i < len; ++i)
+ for (qsizetype i = 0; i < len; ++i)
if (data[i] != qint8(data[i]))
return false;
return true;
}
- void setInlineData(const int *data, int len)
+ void setInlineData(const int *data, qsizetype len)
{
+ Q_ASSERT(len <= InlineSegmentCount);
dummy = 1 + len * 2;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- for (int i = 0; i < len; ++i)
+ for (qsizetype i = 0; i < len; ++i)
dummy |= quintptr(data[i] & 0xFF) << (8 * (i + 1));
#elif Q_BYTE_ORDER == Q_BIG_ENDIAN
- for (int i = 0; i < len; ++i)
+ for (qsizetype i = 0; i < len; ++i)
dummy |= quintptr(data[i] & 0xFF) << (8 * (sizeof(void *) - i - 1));
#else
// the code above is equivalent to:
setInlineSize(len);
- for (int i = 0; i < len; ++i)
+ for (qsizetype i = 0; i < len; ++i)
inline_segments[InlineSegmentStartIdx + i] = data[i] & 0xFF;
#endif
}
@@ -214,17 +193,84 @@ class QVersionNumber
Q_CORE_EXPORT void setVector(int len, int maj, int min, int mic);
} m_segments;
+ class It
+ {
+ const QVersionNumber *v;
+ qsizetype i;
+
+ friend class QVersionNumber;
+ explicit constexpr It(const QVersionNumber *vn, qsizetype idx) noexcept : v(vn), i(idx) {}
+
+ friend constexpr bool comparesEqual(const It &lhs, const It &rhs)
+ { Q_ASSERT(lhs.v == rhs.v); return lhs.i == rhs.i; }
+ friend constexpr Qt::strong_ordering compareThreeWay(const It &lhs, const It &rhs)
+ { Q_ASSERT(lhs.v == rhs.v); return Qt::compareThreeWay(lhs.i, rhs.i); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(It)
+
+ public:
+ // Rule Of Zero applies
+ It() = default;
+
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = int;
+#ifdef QT_COMPILER_HAS_LWG3346
+ using element_type = const int;
+#endif
+ using difference_type = qptrdiff; // difference to container requirements
+ using size_type = qsizetype; // difference to container requirements
+ using reference = value_type; // difference to container requirements
+ using pointer = QtPrivate::ArrowProxy<reference>;
+
+ reference operator*() const { return v->segmentAt(i); }
+ pointer operator->() const { return {**this}; }
+
+ It &operator++() { ++i; return *this; }
+ It operator++(int) { auto copy = *this; ++*this; return copy; }
+
+ It &operator--() { --i; return *this; }
+ It operator--(int) { auto copy = *this; --*this; return copy; }
+
+ It &operator+=(difference_type n) { i += n; return *this; }
+ friend It operator+(It it, difference_type n) { it += n; return it; }
+ friend It operator+(difference_type n, It it) { return it + n; }
+
+ It &operator-=(difference_type n) { i -= n; return *this; }
+ friend It operator-(It it, difference_type n) { it -= n; return it; }
+
+ friend difference_type operator-(It lhs, It rhs)
+ { Q_ASSERT(lhs.v == rhs.v); return lhs.i - rhs.i; }
+
+ reference operator[](difference_type n) const { return *(*this + n); }
+ };
+
public:
+ using const_iterator = It;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ using value_type = It::value_type;
+ using difference_type = It::difference_type;
+ using size_type = It::size_type;
+ using reference = It::reference;
+ using const_reference = reference;
+ using pointer = It::pointer;
+ using const_pointer = pointer;
+
inline QVersionNumber() noexcept
: m_segments()
{}
+ Q_WEAK_OVERLOAD
inline explicit QVersionNumber(const QList<int> &seg) : m_segments(seg) { }
// compiler-generated copy/move ctor/assignment operators and the destructor are ok
+ Q_WEAK_OVERLOAD
explicit QVersionNumber(QList<int> &&seg) : m_segments(std::move(seg)) { }
inline QVersionNumber(std::initializer_list<int> args)
+ : m_segments(QSpan{args})
+ {}
+
+ explicit QVersionNumber(QSpan<const int> args)
: m_segments(args)
{}
@@ -237,229 +283,107 @@ public:
inline explicit QVersionNumber(int maj, int min, int mic)
{ m_segments.setSegments(3, maj, min, mic); }
- Q_REQUIRED_RESULT inline bool isNull() const noexcept
+ [[nodiscard]] inline bool isNull() const noexcept
{ return segmentCount() == 0; }
- Q_REQUIRED_RESULT inline bool isNormalized() const noexcept
+ [[nodiscard]] inline bool isNormalized() const noexcept
{ return isNull() || segmentAt(segmentCount() - 1) != 0; }
- Q_REQUIRED_RESULT inline int majorVersion() const noexcept
+ [[nodiscard]] inline int majorVersion() const noexcept
{ return segmentAt(0); }
- Q_REQUIRED_RESULT inline int minorVersion() const noexcept
+ [[nodiscard]] inline int minorVersion() const noexcept
{ return segmentAt(1); }
- Q_REQUIRED_RESULT inline int microVersion() const noexcept
+ [[nodiscard]] inline int microVersion() const noexcept
{ return segmentAt(2); }
- Q_REQUIRED_RESULT Q_CORE_EXPORT QVersionNumber normalized() const;
+ [[nodiscard]] Q_CORE_EXPORT QVersionNumber normalized() const;
- Q_REQUIRED_RESULT Q_CORE_EXPORT QList<int> segments() const;
+ [[nodiscard]] Q_CORE_EXPORT QList<int> segments() const;
- Q_REQUIRED_RESULT inline int segmentAt(int index) const noexcept
+ [[nodiscard]] inline int segmentAt(qsizetype index) const noexcept
{ return (m_segments.size() > index) ? m_segments.at(index) : 0; }
- Q_REQUIRED_RESULT inline int segmentCount() const noexcept
+ [[nodiscard]] inline qsizetype segmentCount() const noexcept
{ return m_segments.size(); }
- Q_REQUIRED_RESULT Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
-
- Q_REQUIRED_RESULT Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
-
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
-
- Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const;
-#if QT_STRINGVIEW_LEVEL < 2
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr);
-#endif
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr);
- Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr);
-
-private:
-#ifndef QT_NO_DATASTREAM
- friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
-#endif
- friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed);
-};
-
-Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
-#endif
-
-Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) > 0; }
+ [[nodiscard]] const_iterator begin() const noexcept { return const_iterator{this, 0}; }
+ [[nodiscard]] const_iterator end() const noexcept { return begin() + segmentCount(); }
+ [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] const_iterator cend() const noexcept { return end(); }
-Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) >= 0; }
+ [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
+ [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
+ [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
-Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) < 0; }
+ [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); }
+ [[nodiscard]] const_iterator constEnd() const noexcept { return end(); }
-Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) <= 0; }
+ [[nodiscard]] Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
-Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) == 0; }
+ [[nodiscard]] Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
-Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
-{ return QVersionNumber::compare(lhs, rhs) != 0; }
+ [[nodiscard]] Q_CORE_EXPORT static QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
-class QTypeRevision;
-Q_CORE_EXPORT size_t qHash(const QTypeRevision &key, size_t seed = 0);
+ [[nodiscard]] Q_CORE_EXPORT QString toString() const;
+ [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex = nullptr);
-#ifndef QT_NO_DATASTREAM
-Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision);
-Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QTypeRevision &revision);
-#endif
-
-class QTypeRevision
-{
-public:
- template<typename Integer>
- using if_valid_segment_type = typename std::enable_if<
- std::is_integral<Integer>::value, bool>::type;
-
- template<typename Integer>
- using if_valid_value_type = typename std::enable_if<
- std::is_integral<Integer>::value
- && (sizeof(Integer) > sizeof(quint16)
- || (sizeof(Integer) == sizeof(quint16)
- && !std::is_signed<Integer>::value)), bool>::type;
-
- template<typename Integer, if_valid_segment_type<Integer> = true>
- static constexpr bool isValidSegment(Integer segment)
+#if QT_DEPRECATED_SINCE(6, 4) && QT_POINTER_SIZE != 4
+ Q_WEAK_OVERLOAD
+ QT_DEPRECATED_VERSION_X_6_4("Use the 'qsizetype *suffixIndex' overload.")
+ [[nodiscard]] static QVersionNumber fromString(QAnyStringView string, int *suffixIndex)
{
- // using extra parentheses around max to avoid expanding it if it is a macro
- return segment >= Integer(0)
- && ((std::numeric_limits<Integer>::max)() < Integer(SegmentUnknown)
- || segment < Integer(SegmentUnknown));
- }
-
- template<typename Major, typename Minor,
- if_valid_segment_type<Major> = true,
- if_valid_segment_type<Minor> = true>
- static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
- {
- return Q_ASSERT(isValidSegment(majorVersion)),
- Q_ASSERT(isValidSegment(minorVersion)),
- QTypeRevision(quint8(majorVersion), quint8(minorVersion));
+ QT_WARNING_PUSH
+ // fromString() writes to *n unconditionally, but GCC can't know that
+ QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
+ qsizetype n;
+ auto r = fromString(string, &n);
+ if (suffixIndex) {
+ Q_ASSERT(int(n) == n);
+ *suffixIndex = int(n);
+ }
+ return r;
+ QT_WARNING_POP
}
+#endif
- template<typename Major, if_valid_segment_type<Major> = true>
- static constexpr QTypeRevision fromMajorVersion(Major majorVersion)
- {
- return Q_ASSERT(isValidSegment(majorVersion)),
- QTypeRevision(quint8(majorVersion), SegmentUnknown);
- }
- template<typename Minor, if_valid_segment_type<Minor> = true>
- static constexpr QTypeRevision fromMinorVersion(Minor minorVersion)
- {
- return Q_ASSERT(isValidSegment(minorVersion)),
- QTypeRevision(SegmentUnknown, quint8(minorVersion));
- }
+#if QT_CORE_REMOVED_SINCE(6, 4)
+ [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(const QString &string, int *suffixIndex);
+ [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QLatin1StringView string, int *suffixIndex);
+ [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex);
+#endif
- template<typename Integer, if_valid_value_type<Integer> = true>
- static constexpr QTypeRevision fromEncodedVersion(Integer value)
+private:
+ [[nodiscard]] friend bool comparesEqual(const QVersionNumber &lhs,
+ const QVersionNumber &rhs) noexcept
{
- return Q_ASSERT((value & ~Integer(0xffff)) == Integer(0)),
- QTypeRevision((value & Integer(0xff00)) >> 8, value & Integer(0xff));
+ return compare(lhs, rhs) == 0;
}
-
- static constexpr QTypeRevision zero() { return QTypeRevision(0, 0); }
-
- constexpr QTypeRevision() = default;
-
- constexpr bool hasMajorVersion() const { return m_majorVersion != SegmentUnknown; }
- constexpr quint8 majorVersion() const { return m_majorVersion; }
-
- constexpr bool hasMinorVersion() const { return m_minorVersion != SegmentUnknown; }
- constexpr quint8 minorVersion() const { return m_minorVersion; }
-
- constexpr bool isValid() const { return hasMajorVersion() || hasMinorVersion(); }
-
- template<typename Integer, if_valid_value_type<Integer> = true>
- constexpr Integer toEncodedVersion() const
+ [[nodiscard]] friend Qt::strong_ordering compareThreeWay(const QVersionNumber &lhs,
+ const QVersionNumber &rhs) noexcept
{
- return Integer(m_majorVersion << 8) | Integer(m_minorVersion);
+ int c = compare(lhs, rhs);
+ return Qt::compareThreeWay(c, 0);
}
+ Q_DECLARE_STRONGLY_ORDERED(QVersionNumber)
-private:
- enum { SegmentUnknown = quint8(~0U) };
-
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- constexpr QTypeRevision(quint8 major, quint8 minor)
- : m_minorVersion(minor), m_majorVersion(major) {}
-
- quint8 m_minorVersion = SegmentUnknown;
- quint8 m_majorVersion = SegmentUnknown;
-#else
- constexpr QTypeRevision(quint8 major, quint8 minor)
- : m_majorVersion(major), m_minorVersion(minor) {}
-
- quint8 m_majorVersion = SegmentUnknown;
- quint8 m_minorVersion = SegmentUnknown;
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
#endif
+ friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed);
};
-inline constexpr bool operator==(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>();
-}
-
-inline constexpr bool operator!=(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs.toEncodedVersion<quint16>() != rhs.toEncodedVersion<quint16>();
-}
-
-inline constexpr bool operator<(QTypeRevision lhs, QTypeRevision rhs)
-{
- return (!lhs.hasMajorVersion() && rhs.hasMajorVersion())
- // non-0 major > unspecified major > major 0
- ? rhs.majorVersion() != 0
- : ((lhs.hasMajorVersion() && !rhs.hasMajorVersion())
- // major 0 < unspecified major < non-0 major
- ? lhs.majorVersion() == 0
- : (lhs.majorVersion() != rhs.majorVersion()
- // both majors specified and non-0
- ? lhs.majorVersion() < rhs.majorVersion()
- : ((!lhs.hasMinorVersion() && rhs.hasMinorVersion())
- // non-0 minor > unspecified minor > minor 0
- ? rhs.minorVersion() != 0
- : ((lhs.hasMinorVersion() && !rhs.hasMinorVersion())
- // minor 0 < unspecified minor < non-0 minor
- ? lhs.minorVersion() == 0
- // both minors specified and non-0
- : lhs.minorVersion() < rhs.minorVersion()))));
-}
-
-inline constexpr bool operator>(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs != rhs && !(lhs < rhs);
-}
-
-inline constexpr bool operator<=(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs == rhs || lhs < rhs;
-}
-
-inline constexpr bool operator>=(QTypeRevision lhs, QTypeRevision rhs)
-{
- return lhs == rhs || !(lhs < rhs);
-}
-
-static_assert(sizeof(QTypeRevision) == 2);
-Q_DECLARE_TYPEINFO(QTypeRevision, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QVersionNumber, Q_RELOCATABLE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
-Q_CORE_EXPORT QDebug operator<<(QDebug, const QTypeRevision &revision);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
#endif
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QVersionNumber)
-Q_DECLARE_METATYPE(QTypeRevision)
+QT_DECL_METATYPE_EXTERN(QVersionNumber, Q_CORE_EXPORT)
-#endif //QVERSIONNUMBER_H
+#endif // QVERSIONNUMBER_H
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
deleted file mode 100644
index 607a6eaf06..0000000000
--- a/src/corelib/tools/tools.pri
+++ /dev/null
@@ -1,117 +0,0 @@
-# Qt tools module
-
-intel_icc: QMAKE_CXXFLAGS += -fp-model strict
-
-HEADERS += \
- tools/qalgorithms.h \
- tools/qarraydata.h \
- tools/qarraydataops.h \
- tools/qarraydatapointer.h \
- tools/qbitarray.h \
- tools/qcache.h \
- tools/qcontainerfwd.h \
- tools/qcontainertools_impl.h \
- tools/qcryptographichash.h \
- tools/qduplicatetracker_p.h \
- tools/qflatmap_p.h \
- tools/qfreelist_p.h \
- tools/qhash.h \
- tools/qhashfunctions.h \
- tools/qiterator.h \
- tools/qline.h \
- tools/qlist.h \
- tools/qmakearray_p.h \
- tools/qmap.h \
- tools/qmargins.h \
- tools/qmessageauthenticationcode.h \
- tools/qcontiguouscache.h \
- tools/qoffsetstringarray_p.h \
- tools/qpair.h \
- tools/qpoint.h \
- tools/qqueue.h \
- tools/qrect.h \
- tools/qringbuffer_p.h \
- tools/qrefcount.h \
- tools/qscopeguard.h \
- tools/qscopedpointer.h \
- tools/qscopedpointer_p.h \
- tools/qscopedvaluerollback.h \
- tools/qshareddata.h \
- tools/qsharedpointer.h \
- tools/qsharedpointer_impl.h \
- tools/qset.h \
- tools/qsize.h \
- tools/qstack.h \
- tools/qtools_p.h \
- tools/qtaggedpointer.h \
- tools/qvarlengtharray.h \
- tools/qvector.h \
- tools/qversionnumber.h
-
-SOURCES += \
- tools/qarraydata.cpp \
- tools/qbitarray.cpp \
- tools/qcryptographichash.cpp \
- tools/qfreelist.cpp \
- tools/qhash.cpp \
- tools/qline.cpp \
- tools/qlist.cpp \
- tools/qpoint.cpp \
- tools/qmap.cpp \
- tools/qmargins.cpp \
- tools/qmessageauthenticationcode.cpp \
- tools/qcontiguouscache.cpp \
- tools/qrect.cpp \
- tools/qrefcount.cpp \
- tools/qringbuffer.cpp \
- tools/qshareddata.cpp \
- tools/qsharedpointer.cpp \
- tools/qsize.cpp \
- tools/qversionnumber.cpp
-
-msvc: NO_PCH_SOURCES += tools/qvector_msvc.cpp
-false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator
-
-qtConfig(system-zlib) {
- include($$PWD/../../3rdparty/zlib_dependency.pri)
-} else {
- CONFIG += no_core_dep
- include($$PWD/../../3rdparty/zlib.pri)
-}
-
-qtConfig(commandlineparser) {
- HEADERS += \
- tools/qcommandlineoption.h \
- tools/qcommandlineparser.h
- SOURCES += \
- tools/qcommandlineoption.cpp \
- tools/qcommandlineparser.cpp
-}
-
-INCLUDEPATH += ../3rdparty/md5 \
- ../3rdparty/md4 \
- ../3rdparty/sha3
-
-qtConfig(system-doubleconversion) {
- QMAKE_USE_PRIVATE += doubleconversion
-} else: qtConfig(doubleconversion) {
- include($$PWD/../../3rdparty/double-conversion/double-conversion.pri)
-}
-
-qtConfig(easingcurve) {
- HEADERS += \
- tools/qeasingcurve.h \
- tools/qtimeline.h
-
- SOURCES += \
- tools/qeasingcurve.cpp \
- tools/qtimeline.cpp
-}
-
-# Note: libm should be present by default becaue this is C++
-unix:!macx-icc:!vxworks:!haiku:!integrity:!wasm: LIBS_PRIVATE += -lm
-
-TR_EXCLUDE += ../3rdparty/*
-
-# MIPS DSP
-MIPS_DSP_HEADERS += ../gui/painting/qt_mips_asm_dsp_p.h
diff --git a/src/corelib/tracing/qctf.cpp b/src/corelib/tracing/qctf.cpp
new file mode 100644
index 0000000000..ff81d0a678
--- /dev/null
+++ b/src/corelib/tracing/qctf.cpp
@@ -0,0 +1,144 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#define BUILD_LIBRARY
+
+#include <qthread.h>
+#include <qpluginloader.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qjsonarray.h>
+
+#include "qctf_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static bool s_initialized = false;
+static bool s_triedLoading = false;
+static bool s_prevent_recursion = false;
+static bool s_shutdown = false;
+static QCtfLib* s_plugin = nullptr;
+
+#if QT_CONFIG(library) && defined(QT_SHARED)
+
+#if defined(Q_OS_ANDROID)
+static QString findPlugin(const QString &plugin)
+{
+ QString pluginPath = QString::fromUtf8(qgetenv("QT_PLUGIN_PATH"));
+ QDir dir(pluginPath);
+ const QStringList files = dir.entryList(QDir::Files);
+ for (const QString &file : files) {
+ if (file.contains(plugin))
+ return QFileInfo(pluginPath + QLatin1Char('/') + file).absoluteFilePath();
+ }
+ return {};
+}
+#endif
+
+static bool loadPlugin(bool &retry)
+{
+ retry = false;
+#ifdef Q_OS_WIN
+#ifdef QT_DEBUG
+ QPluginLoader loader(QStringLiteral("tracing/QCtfTracePlugind.dll"));
+#else
+ QPluginLoader loader(QStringLiteral("tracing/QCtfTracePlugin.dll"));
+#endif
+#elif defined(Q_OS_ANDROID)
+
+ QString plugin = findPlugin(QStringLiteral("QCtfTracePlugin"));
+ if (plugin.isEmpty()) {
+ retry = true;
+ return false;
+ }
+ QPluginLoader loader(plugin);
+#else
+ QPluginLoader loader(QStringLiteral("tracing/libQCtfTracePlugin.so"));
+#endif
+
+ if (!loader.isLoaded()) {
+ if (!loader.load())
+ return false;
+ }
+ s_plugin = qobject_cast<QCtfLib *>(loader.instance());
+ if (!s_plugin)
+ return false;
+ s_plugin->shutdown(&s_shutdown);
+ return true;
+}
+
+#else
+
+#define QCtfPluginIID QStringLiteral("org.qt-project.Qt.QCtfLib")
+
+static bool loadPlugin(bool &retry)
+{
+ retry = false;
+ const auto &plugins = QPluginLoader::staticPlugins();
+ for (const auto &plugin : plugins) {
+ const auto json = plugin.metaData();
+ const auto IID = json[QStringLiteral("IID")];
+ if (IID.toString() == QCtfPluginIID) {
+ s_plugin = qobject_cast<QCtfLib *>(plugin.instance());
+ if (!s_plugin)
+ return false;
+ s_plugin->shutdown(&s_shutdown);
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif
+
+static bool initialize()
+{
+ if (s_shutdown || s_prevent_recursion)
+ return false;
+ if (s_initialized || s_triedLoading)
+ return s_initialized;
+ s_prevent_recursion = true;
+ bool retry = false;
+ if (!loadPlugin(retry)) {
+ if (!retry) {
+ s_triedLoading = true;
+ s_initialized = false;
+ }
+ } else {
+ bool enabled = s_plugin->sessionEnabled();
+ if (!enabled) {
+ s_triedLoading = true;
+ s_initialized = false;
+ } else {
+ s_initialized = true;
+ }
+ }
+ s_prevent_recursion = false;
+ return s_initialized;
+}
+
+bool _tracepoint_enabled(const QCtfTracePointEvent &point)
+{
+ if (!initialize())
+ return false;
+ return s_plugin ? s_plugin->tracepointEnabled(point) : false;
+}
+
+void _do_tracepoint(const QCtfTracePointEvent &point, const QByteArray &arr)
+{
+ if (!initialize())
+ return;
+ if (s_plugin)
+ s_plugin->doTracepoint(point, arr);
+}
+
+QCtfTracePointPrivate *_initialize_tracepoint(const QCtfTracePointEvent &point)
+{
+ if (!initialize())
+ return nullptr;
+ return s_plugin ? s_plugin->initializeTracepoint(point) : nullptr;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qctf_p.cpp"
diff --git a/src/corelib/tracing/qctf_p.h b/src/corelib/tracing/qctf_p.h
new file mode 100644
index 0000000000..70d00d018c
--- /dev/null
+++ b/src/corelib/tracing/qctf_p.h
@@ -0,0 +1,238 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef Q_CTF_H
+#define Q_CTF_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include <qtcoreexports.h>
+#include <qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QCtfTraceMetadata;
+struct Q_CORE_EXPORT QCtfTracePointProvider
+{
+ const QString provider;
+ QCtfTraceMetadata *metadata;
+ QCtfTracePointProvider(const QString &provider)
+ : provider(provider), metadata(nullptr)
+ {
+
+ }
+};
+
+struct Q_CORE_EXPORT QCtfTraceMetadata
+{
+ const QString name;
+ const QString metadata;
+ QCtfTraceMetadata(QCtfTracePointProvider &provider, const QString &name, const QString &metadata)
+ : name(name), metadata(metadata)
+ {
+ next = provider.metadata;
+ provider.metadata = this;
+ }
+ QCtfTraceMetadata *next = nullptr;
+};
+
+struct QCtfTracePointPrivate;
+struct Q_CORE_EXPORT QCtfTracePointEvent
+{
+ const QCtfTracePointProvider &provider;
+ const QString eventName;
+ const QString metadata;
+ const int size;
+ const bool variableSize;
+
+ QCtfTracePointEvent(const QCtfTracePointProvider &provider, const QString &name, const QString &metadata, int size, bool variableSize)
+ : provider(provider), eventName(name), metadata(metadata), size(size), variableSize(variableSize)
+ {
+ }
+ QCtfTracePointPrivate *d = nullptr;
+};
+
+
+
+Q_CORE_EXPORT bool _tracepoint_enabled(const QCtfTracePointEvent &point);
+Q_CORE_EXPORT void _do_tracepoint(const QCtfTracePointEvent &point, const QByteArray &arr);
+Q_CORE_EXPORT QCtfTracePointPrivate *_initialize_tracepoint(const QCtfTracePointEvent &point);
+
+#ifndef BUILD_LIBRARY
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qurl.h>
+namespace trace {
+inline void toByteArray(QByteArray &)
+{
+}
+
+inline void toByteArray(QByteArray &arr, const QString &value)
+{
+ arr.append(value.toUtf8());
+ arr.append((char)0);
+}
+
+inline void toByteArray(QByteArray &arr, const QUrl &value)
+{
+ arr.append(value.toString().toUtf8());
+ arr.append((char)0);
+}
+
+inline void toByteArray(QByteArray &arr, const QByteArray &data)
+{
+ arr.append(data);
+}
+
+template <typename T>
+inline void toByteArray(QByteArray &arr, T value)
+{
+ arr.append((char *)&value, sizeof(value));
+}
+
+template <typename T, typename... Ts>
+inline void toByteArray(QByteArray &arr, T value, Ts... args)
+{
+ toByteArray(arr, value);
+ toByteArray(arr, args...);
+}
+
+inline QByteArray toByteArray()
+{
+ return {};
+}
+
+template <typename... Ts>
+inline QByteArray toByteArray(Ts... args)
+{
+ QByteArray data;
+ toByteArray(data, args...);
+ return data;
+}
+
+template <typename T>
+inline QByteArray toByteArrayFromArray(const T *values, int arraySize)
+{
+ QByteArray data;
+ data.append((char *)values, arraySize * sizeof(T));
+ return data;
+}
+
+template <typename IntegerType, typename T>
+inline QByteArray toByteArrayFromEnum(T value)
+{
+ IntegerType e = static_cast<IntegerType>(value);
+ QByteArray data;
+ data.append((char *)&e, sizeof(e));
+ return data;
+}
+
+inline QByteArray toByteArrayFromCString(const char *str)
+{
+ QByteArray data;
+ if (str && *str != 0)
+ data.append(str);
+ data.append((char)0);
+ return data;
+}
+
+static inline void appendFlags(QByteArray &data, quint8 &count, quint32 value)
+{
+ count = 0;
+ quint8 d = 1;
+ while (value) {
+ if (value&1) {
+ data.append(d);
+ count++;
+ }
+ d++;
+ value >>= 1;
+ }
+}
+
+template <typename T>
+inline QByteArray toByteArrayFromFlags(QFlags<T> value)
+{
+ quint32 intValue = static_cast<quint32>(value.toInt());
+ quint8 count;
+ QByteArray data;
+ data.append((char)0);
+ if (intValue == 0) {
+ data.append((char)0);
+ data.data()[0] = 1;
+ } else {
+ appendFlags(data, count, intValue);
+ data.data()[0] = count;
+ }
+ return data;
+}
+
+} // trace
+
+#define _DEFINE_EVENT(provider, event, metadata, size, varSize) \
+ static QCtfTracePointEvent _ctf_ ## event = QCtfTracePointEvent(_ctf_provider_ ## provider, QStringLiteral(QT_STRINGIFY(event)), metadata, size, varSize);
+#define _DEFINE_METADATA(provider, name, metadata) \
+ static QCtfTraceMetadata _ctf_metadata_ ## name = QCtfTraceMetadata(_ctf_provider_ ## provider, QStringLiteral(QT_STRINGIFY(name)), metadata);
+#define _DEFINE_TRACEPOINT_PROVIDER(provider) \
+ static QCtfTracePointProvider _ctf_provider_ ## provider = QCtfTracePointProvider(QStringLiteral(QT_STRINGIFY(provider)));
+
+#define TRACEPOINT_EVENT(provider, event, metadata, size, varSize) \
+ _DEFINE_EVENT(provider, event, metadata, size, varSize)
+
+#define TRACEPOINT_PROVIDER(provider) \
+ _DEFINE_TRACEPOINT_PROVIDER(provider)
+
+#define TRACEPOINT_METADATA(provider, name, metadata) \
+ _DEFINE_METADATA(provider, name, metadata)
+
+#define tracepoint_enabled(provider, event) \
+ _tracepoint_enabled(_ctf_ ## event)
+
+#define do_tracepoint(provider, event, ...) \
+{ \
+ auto &tp = _ctf_ ## event; \
+ if (!tp.d) \
+ tp.d = _initialize_tracepoint(tp); \
+ if (tp.d) { \
+ QByteArray data(tp.size, 0); \
+ if (!tp.metadata.isEmpty()) \
+ data = trace::toByteArray(__VA_ARGS__); \
+ _do_tracepoint(tp, data); \
+ } \
+}
+
+#define tracepoint(provider, name, ...) \
+ do { \
+ if (tracepoint_enabled(provider, name)) \
+ do_tracepoint(provider, name, __VA_ARGS__); \
+ } while (0)
+
+#endif
+
+class Q_CORE_EXPORT QCtfLib : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QCtfLib)
+public:
+ explicit QCtfLib(QObject *parent = nullptr) : QObject(parent) {}
+ virtual ~QCtfLib() = default;
+ virtual bool tracepointEnabled(const QCtfTracePointEvent &point) = 0;
+ virtual void doTracepoint(const QCtfTracePointEvent &point, const QByteArray &arr) = 0;
+ virtual bool sessionEnabled() = 0;
+ virtual QCtfTracePointPrivate *initializeTracepoint(const QCtfTracePointEvent &point) = 0;
+ virtual void shutdown(bool *shutdown) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif